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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt182
-rw-r--r--SConstruct232
-rwxr-xr-xbuild_files/build_environment/install_deps.sh995
-rw-r--r--build_files/buildbot/config/user-config-cuda-glibc211-i686.py5
-rw-r--r--build_files/buildbot/config/user-config-cuda-glibc211-x86_64.py5
-rw-r--r--build_files/buildbot/config/user-config-glibc211-i686.py8
-rw-r--r--build_files/buildbot/config/user-config-glibc211-x86_64.py8
-rw-r--r--build_files/buildbot/config/user-config-glibc27-i686.py149
-rw-r--r--build_files/buildbot/config/user-config-glibc27-x86_64.py149
-rw-r--r--build_files/buildbot/config/user-config-mac-i386.py420
-rw-r--r--build_files/buildbot/config/user-config-mac-x86_64.py420
-rw-r--r--build_files/buildbot/config/user-config-player-glibc211-i686.py4
-rw-r--r--build_files/buildbot/config/user-config-player-glibc211-x86_64.py4
-rw-r--r--build_files/buildbot/config/user-config-player-glibc27-i686.py114
-rw-r--r--build_files/buildbot/config/user-config-player-glibc27-x86_64.py114
-rw-r--r--build_files/buildbot/master.cfg16
-rw-r--r--build_files/buildbot/slave_compile.py85
-rw-r--r--build_files/buildbot/slave_pack.py32
-rw-r--r--build_files/buildbot/slave_rsync.py2
-rw-r--r--build_files/cmake/Modules/FindOpenCOLLADA.cmake1
-rw-r--r--build_files/cmake/clang_array_check.py2
-rwxr-xr-xbuild_files/cmake/cmake_consistency_check.py4
-rw-r--r--build_files/cmake/cmake_consistency_check_config.py21
-rwxr-xr-xbuild_files/cmake/cmake_netbeans_project.py4
-rwxr-xr-xbuild_files/cmake/cmake_qtcreator_project.py3
-rw-r--r--build_files/cmake/cmake_static_check_clang_array.py2
-rw-r--r--build_files/cmake/cmake_static_check_cppcheck.py2
-rw-r--r--build_files/cmake/cmake_static_check_smatch.py3
-rw-r--r--build_files/cmake/cmake_static_check_sparse.py2
-rw-r--r--build_files/cmake/cmake_static_check_splint.py2
-rw-r--r--build_files/cmake/config/blender_headless.cmake22
-rw-r--r--build_files/cmake/config/blender_lite.cmake86
-rw-r--r--build_files/cmake/config/bpy_module.cmake32
-rw-r--r--build_files/cmake/macros.cmake23
-rwxr-xr-xbuild_files/cmake/project_info.py13
-rw-r--r--build_files/cmake/project_source_info.py8
-rw-r--r--build_files/package_spec/rpm/blender.spec.in1
-rw-r--r--build_files/scons/config/Modules/FindPython.py10
-rw-r--r--build_files/scons/config/darwin-config.py9
-rw-r--r--build_files/scons/config/freebsd7-config.py3
-rw-r--r--build_files/scons/config/freebsd8-config.py3
-rw-r--r--build_files/scons/config/freebsd9-config.py3
-rw-r--r--build_files/scons/config/linux-config.py74
-rw-r--r--build_files/scons/config/linuxcross-config.py3
-rw-r--r--build_files/scons/config/win32-mingw-config.py5
-rw-r--r--build_files/scons/config/win32-vc-config.py7
-rw-r--r--build_files/scons/config/win64-mingw-config.py5
-rw-r--r--build_files/scons/config/win64-vc-config.py7
-rw-r--r--build_files/scons/tools/Blender.py23
-rw-r--r--build_files/scons/tools/btools.py25
-rw-r--r--doc/build_systems/cmake.txt82
-rw-r--r--doc/license/bf-members.txt100
-rw-r--r--doc/manpage/blender.124
-rw-r--r--doc/python_api/examples/bpy.props.5.py89
-rw-r--r--doc/python_api/examples/bpy.types.AddonPreferences.1.py72
-rw-r--r--doc/python_api/examples/bpy.types.NodeTree.py23
-rw-r--r--doc/python_api/examples/bpy.types.UIList.py90
-rw-r--r--doc/python_api/rst/bge.events.rst4
-rw-r--r--doc/python_api/rst/bge.logic.rst18
-rw-r--r--doc/python_api/rst/bge.types.rst5261
-rw-r--r--doc/python_api/rst/bge_types/bge.types.BL_ActionActuator.rst78
-rw-r--r--doc/python_api/rst/bge_types/bge.types.BL_ArmatureActuator.rst61
-rw-r--r--doc/python_api/rst/bge_types/bge.types.BL_ArmatureBone.rst105
-rw-r--r--doc/python_api/rst/bge_types/bge.types.BL_ArmatureChannel.rst278
-rw-r--r--doc/python_api/rst/bge_types/bge.types.BL_ArmatureConstraint.rst129
-rw-r--r--doc/python_api/rst/bge_types/bge.types.BL_ArmatureObject.rst34
-rw-r--r--doc/python_api/rst/bge_types/bge.types.BL_Shader.rst220
-rw-r--r--doc/python_api/rst/bge_types/bge.types.BL_ShapeActionActuator.rst72
-rw-r--r--doc/python_api/rst/bge_types/bge.types.CListValue.rst72
-rw-r--r--doc/python_api/rst/bge_types/bge.types.CPropValue.rst11
-rw-r--r--doc/python_api/rst/bge_types/bge.types.CValue.rst17
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_ArmatureSensor.rst36
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_BlenderMaterial.rst77
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_Camera.rst284
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_CameraActuator.rst47
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_CharacterWrapper.rst45
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_ConstraintActuator.rst78
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst18
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_FontObject.rst12
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_GameActuator.rst23
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst839
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_IpoActuator.rst65
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_LibLoadStatus.rst45
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_LightObject.rst90
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_MeshProxy.rst134
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_MouseFocusSensor.rst66
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_NavMeshObject.rst47
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_NearSensor.rst23
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_NetworkMessageActuator.rst35
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_NetworkMessageSensor.rst38
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_ObjectActuator.rst129
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_ParentActuator.rst38
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_PolyProxy.rst139
-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_RadarSensor.rst44
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_RaySensor.rst72
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_SCA_AddObjectActuator.rst55
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_SCA_DynamicActuator.rst29
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_SCA_EndObjectActuator.rst13
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_SCA_ReplaceMeshActuator.rst89
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_Scene.rst172
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_SceneActuator.rst49
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_SoundActuator.rst115
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_StateActuator.rst29
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_SteeringActuator.rst71
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_TouchSensor.rst41
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_TrackToActuator.rst39
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_VehicleWrapper.rst161
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_VertexProxy.rst209
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_VisibilityActuator.rst29
-rw-r--r--doc/python_api/rst/bge_types/bge.types.PyObjectPlus.rst21
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_2DFilterActuator.rst49
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_ANDController.rst13
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_ActuatorSensor.rst19
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_AlwaysSensor.rst11
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_DelaySensor.rst39
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_IActuator.rst11
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_IController.rst55
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_ILogicBrick.rst29
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_IObject.rst11
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_ISensor.rst95
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_JoystickSensor.rst133
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_KeyboardSensor.rst64
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_MouseSensor.rst39
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_NANDController.rst13
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_NORController.rst13
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_ORController.rst13
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_PropertyActuator.rst29
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_PropertySensor.rst41
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_PythonController.rst48
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_PythonJoystick.rst75
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_PythonKeyboard.rst37
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_PythonMouse.rst35
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_RandomActuator.rst127
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_RandomSensor.rst23
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_XNORController.rst13
-rw-r--r--doc/python_api/rst/bge_types/bge.types.SCA_XORController.rst13
-rw-r--r--doc/python_api/rst/info_tutorial_addon.rst18
-rw-r--r--doc/python_api/rst_from_bmesh_opdefines.py50
-rw-r--r--doc/python_api/sphinx_doc_gen.py43
-rwxr-xr-xdoc/python_api/sphinx_doc_gen.sh8
-rw-r--r--doc/python_api/sphinx_doc_gen_monkeypatch.py47
-rw-r--r--extern/CMakeLists.txt6
-rw-r--r--extern/SConscript2
-rw-r--r--extern/bullet2/CMakeLists.txt11
-rw-r--r--extern/bullet2/patches/make_id.patch42
-rw-r--r--extern/bullet2/patches/pvs_warning_fixes.patch31
-rw-r--r--extern/bullet2/readme.txt7
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h2
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h3
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h19
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h10
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp18
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp1
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp2
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h2
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp46
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h8
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp23
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h8
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp2
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h6
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h8
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp26
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h9
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp10
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h62
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h43
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp461
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h37
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp145
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h14
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp22
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h8
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp79
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h25
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp119
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h9
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp51
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h12
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h2
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp2
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h10
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp40
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h3
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp59
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h50
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp264
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h14
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp17
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h8
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp22
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h8
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btBox2dShape.h4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h8
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h17
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h11
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h21
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConvex2dShape.h4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp89
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp62
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp28
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h7
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp37
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.h15
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.h4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp9
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h10
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp61
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp153
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h8
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h2
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h2
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp2
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h16
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp22
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp6
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h3
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h6
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h4
-rw-r--r--extern/bullet2/src/BulletCollision/Gimpact/btBoxCollision.h18
-rw-r--r--extern/bullet2/src/BulletCollision/Gimpact/btCompoundFromGimpact.h93
-rw-r--r--extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp342
-rw-r--r--extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h114
-rw-r--r--extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp8
-rw-r--r--extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h4
-rw-r--r--extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.cpp35
-rw-r--r--extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.h27
-rw-r--r--extern/bullet2/src/BulletCollision/Gimpact/gim_array.h6
-rw-r--r--extern/bullet2/src/BulletCollision/Gimpact/gim_box_collision.h12
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp1
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h4
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h30
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp11
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h54
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp178
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h2
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp23
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h6
-rw-r--r--extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp22
-rw-r--r--extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.h5
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp43
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h7
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp4
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h86
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp54
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btGearConstraint.h56
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp47
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h6
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp2
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h13
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h4
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp18
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h2
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h3
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp9
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h2
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp1016
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h65
-rwxr-xr-x[-rw-r--r--]extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp7
-rwxr-xr-x[-rw-r--r--]extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h4
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h134
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h51
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp6
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h36
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h5
-rw-r--r--extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp263
-rw-r--r--extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h22
-rw-r--r--extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h15
-rw-r--r--extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp45
-rw-r--r--extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h115
-rw-r--r--extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp4
-rw-r--r--extern/bullet2/src/BulletSoftBody/btDefaultSoftBodySolver.cpp4
-rw-r--r--extern/bullet2/src/BulletSoftBody/btDefaultSoftBodySolver.h4
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftBody.cpp220
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftBody.h25
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp69
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h18
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftBodyData.h2
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h72
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftBodySolvers.h2
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp16
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h10
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp2
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp9
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h8
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSparseSDF.h12
-rw-r--r--extern/bullet2/src/LinearMath/btAabbUtil2.h8
-rw-r--r--extern/bullet2/src/LinearMath/btAlignedAllocator.cpp2
-rw-r--r--extern/bullet2/src/LinearMath/btAlignedObjectArray.h19
-rw-r--r--extern/bullet2/src/LinearMath/btConvexHull.cpp11
-rw-r--r--extern/bullet2/src/LinearMath/btConvexHullComputer.cpp14
-rw-r--r--extern/bullet2/src/LinearMath/btDefaultMotionState.h4
-rw-r--r--extern/bullet2/src/LinearMath/btGrahamScan2dConvexHull.h33
-rw-r--r--extern/bullet2/src/LinearMath/btIDebugDraw.h1
-rw-r--r--extern/bullet2/src/LinearMath/btMatrix3x3.h659
-rw-r--r--extern/bullet2/src/LinearMath/btPolarDecomposition.cpp99
-rw-r--r--extern/bullet2/src/LinearMath/btPolarDecomposition.h73
-rw-r--r--extern/bullet2/src/LinearMath/btQuadWord.h108
-rw-r--r--extern/bullet2/src/LinearMath/btQuaternion.h497
-rw-r--r--extern/bullet2/src/LinearMath/btScalar.h136
-rw-r--r--extern/bullet2/src/LinearMath/btSerializer.cpp1743
-rw-r--r--extern/bullet2/src/LinearMath/btSerializer.h9
-rw-r--r--extern/bullet2/src/LinearMath/btTransform.h6
-rw-r--r--extern/bullet2/src/LinearMath/btVector3.cpp1639
-rw-r--r--extern/bullet2/src/LinearMath/btVector3.h808
-rw-r--r--extern/bullet2/src/SConscript5
-rw-r--r--extern/bullet2/src/btBulletCollisionCommon.h1
-rw-r--r--extern/bullet2/src/btBulletDynamicsCommon.h1
-rwxr-xr-xextern/carve/bundle.sh2
-rw-r--r--extern/carve/files.txt174
-rw-r--r--extern/carve/include/carve/csg_triangulator.hpp2
-rw-r--r--extern/carve/include/carve/geom3d.hpp19
-rw-r--r--extern/carve/include/carve/geom_impl.hpp2
-rw-r--r--extern/carve/include/carve/input.hpp81
-rw-r--r--extern/carve/include/carve/mesh.hpp38
-rw-r--r--extern/carve/include/carve/mesh_impl.hpp59
-rw-r--r--extern/carve/lib/intersect.cpp4
-rw-r--r--extern/carve/lib/intersect_face_division.cpp6
-rw-r--r--extern/carve/lib/mesh.cpp36
-rw-r--r--extern/carve/lib/polyhedron.cpp2
-rw-r--r--extern/carve/patches/series1
-rw-r--r--extern/carve/patches/strict_flags.patch22
-rw-r--r--extern/libmv/CMakeLists.txt30
-rw-r--r--extern/libmv/ChangeLog1062
-rw-r--r--extern/libmv/SConscript29
-rwxr-xr-xextern/libmv/bundle.sh51
-rw-r--r--extern/libmv/files.txt27
-rw-r--r--extern/libmv/libmv-capi.cpp480
-rw-r--r--extern/libmv/libmv-capi.h91
-rw-r--r--extern/libmv/libmv/multiview/euclidean_resection.cc4
-rw-r--r--extern/libmv/libmv/multiview/homography.cc15
-rw-r--r--extern/libmv/libmv/multiview/homography.h8
-rw-r--r--extern/libmv/libmv/multiview/panography.h181
-rw-r--r--extern/libmv/libmv/simple_pipeline/bundle.cc453
-rw-r--r--extern/libmv/libmv/simple_pipeline/bundle.h12
-rw-r--r--extern/libmv/libmv/simple_pipeline/camera_intrinsics.cc71
-rw-r--r--extern/libmv/libmv/simple_pipeline/camera_intrinsics.h36
-rw-r--r--extern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc16
-rw-r--r--extern/libmv/libmv/simple_pipeline/intersect.cc80
-rw-r--r--extern/libmv/libmv/simple_pipeline/modal_solver.cc180
-rw-r--r--extern/libmv/libmv/simple_pipeline/pipeline.cc2
-rw-r--r--extern/libmv/libmv/simple_pipeline/rigid_registration.cc182
-rw-r--r--extern/libmv/libmv/simple_pipeline/rigid_registration.h68
-rw-r--r--extern/libmv/libmv/simple_pipeline/tracks.cc26
-rw-r--r--extern/libmv/libmv/simple_pipeline/tracks.h8
-rw-r--r--extern/libmv/libmv/tracking/track_region.cc2
-rw-r--r--extern/libmv/patches/series1
-rw-r--r--extern/libmv/patches/v3d_verbosity.patch12
-rw-r--r--extern/libmv/third_party/ceres/CMakeLists.txt41
-rw-r--r--extern/libmv/third_party/ceres/ChangeLog771
-rw-r--r--extern/libmv/third_party/ceres/SConscript4
-rwxr-xr-xextern/libmv/third_party/ceres/bundle.sh15
-rw-r--r--extern/libmv/third_party/ceres/files.txt33
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h71
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/ceres.h8
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/cost_function_to_functor.h752
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/crs_matrix.h32
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/dynamic_autodiff_cost_function.h215
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/fpclassify.h2
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/gradient_checker.h222
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h162
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/internal/eigen.h33
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h6
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/internal/macros.h12
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h29
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/internal/numeric_diff.h199
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/internal/scoped_ptr.h15
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/internal/variadic_evaluate.h182
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/iteration_callback.h43
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h374
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/numeric_diff_functor.h346
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/ordered_groups.h176
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/problem.h166
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/rotation.h204
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/sized_cost_function.h30
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/solver.h315
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/types.h110
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/array_utils.h2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc20
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.h29
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc17
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h9
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.cc34
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h15
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/collections_port.h2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc3
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h9
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.cc236
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.h88
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/corrector.cc17
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/cxsparse.cc11
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/cxsparse.h5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dense_jacobian_writer.h11
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.cc15
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc29
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc50
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h9
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.cc18
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.h4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/evaluator.cc71
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/evaluator.h49
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/execution_summary.h90
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/file.cc3
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generate_eliminator_specialization.py148
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_2.cc5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_3.cc5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_4.cc5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_d.cc7
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_3.cc5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_4.cc5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_9.cc5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_d.cc7
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_3.cc5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_4.cc5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_d.cc7
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_2.cc5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_3.cc5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_4.cc5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_d.cc7
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_d_d_d.cc6
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/graph.h25
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/graph_algorithms.h4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc64
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.h12
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.h5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/line_search.cc214
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/line_search.h215
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/line_search_direction.cc149
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/line_search_direction.h (renamed from extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.h)58
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.cc287
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.h80
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc72
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.h2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/linear_solver.h62
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/low_rank_inverse_hessian.cc109
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/low_rank_inverse_hessian.h99
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/map_util.h1
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/minimizer.cc67
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/minimizer.h24
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/mutex.h9
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/parameter_block.h61
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/parameter_block_ordering.cc (renamed from extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc)29
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/parameter_block_ordering.h (renamed from extern/libmv/third_party/ceres/internal/ceres/schur_ordering.h)16
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/polynomial.cc (renamed from extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.cc)141
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/polynomial.h134
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/preconditioner.cc63
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/preconditioner.h148
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/problem.cc64
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc605
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/problem_impl.h62
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h32
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/residual_block.cc11
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/residual_block.h28
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc53
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h9
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.cc32
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.h6
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.cc145
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.h110
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/solver.cc339
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc1057
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/solver_impl.h96
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc42
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/split.cc3
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/split.h2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/stl_util.h16
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc3
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/stringprintf.h6
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc7
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/suitesparse.h4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc3
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc238
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.h12
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.cc32
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.h2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/types.cc208
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/visibility.cc10
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/visibility.h5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc82
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h82
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/wall_time.cc96
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/wall_time.h88
-rw-r--r--[-rwxr-xr-x]extern/libmv/third_party/ceres/mkfiles.sh0
-rw-r--r--extern/libmv/third_party/ceres/patches/collections_port.h.mingw.patch13
-rw-r--r--extern/libmv/third_party/ceres/patches/msvc_glog_fix.patch50
-rw-r--r--extern/libmv/third_party/ceres/patches/no_previous_declaration_fix.patch199
-rw-r--r--extern/libmv/third_party/ceres/patches/series3
-rw-r--r--extern/libmv/third_party/gflags/README.libmv2
-rw-r--r--extern/libmv/third_party/glog/README.libmv1
-rw-r--r--extern/libmv/third_party/ldl/CMakeLists.txt5
-rw-r--r--extern/libmv/third_party/ldl/Doc/ChangeLog39
-rw-r--r--extern/libmv/third_party/ldl/Doc/lesser.txt504
-rw-r--r--extern/libmv/third_party/ldl/Include/ldl.h104
-rw-r--r--extern/libmv/third_party/ldl/README.libmv10
-rw-r--r--extern/libmv/third_party/ldl/README.txt136
-rw-r--r--extern/libmv/third_party/ldl/Source/ldl.c507
-rw-r--r--extern/libmv/third_party/ssba/COPYING.TXT165
-rw-r--r--extern/libmv/third_party/ssba/Geometry/v3d_cameramatrix.h204
-rw-r--r--extern/libmv/third_party/ssba/Geometry/v3d_distortion.h97
-rw-r--r--extern/libmv/third_party/ssba/Geometry/v3d_metricbundle.cpp405
-rw-r--r--extern/libmv/third_party/ssba/Geometry/v3d_metricbundle.h352
-rw-r--r--extern/libmv/third_party/ssba/Math/v3d_linear.h923
-rw-r--r--extern/libmv/third_party/ssba/Math/v3d_linear_utils.h391
-rw-r--r--extern/libmv/third_party/ssba/Math/v3d_mathutilities.h59
-rw-r--r--extern/libmv/third_party/ssba/Math/v3d_optimization.cpp955
-rw-r--r--extern/libmv/third_party/ssba/Math/v3d_optimization.h273
-rw-r--r--extern/libmv/third_party/ssba/README.TXT92
-rw-r--r--extern/libmv/third_party/ssba/README.libmv23
-rw-r--r--extern/lzo/minilzo/COPYING29
-rw-r--r--extern/lzo/minilzo/README.LZO27
-rw-r--r--extern/lzo/minilzo/lzoconf.h79
-rw-r--r--extern/lzo/minilzo/lzodefs.h179
-rw-r--r--extern/lzo/minilzo/minilzo.c1195
-rw-r--r--extern/lzo/minilzo/minilzo.h8
-rw-r--r--extern/rangetree/CMakeLists.txt31
-rw-r--r--extern/rangetree/README.org13
-rw-r--r--extern/rangetree/SConscript9
-rw-r--r--extern/rangetree/range_tree.hh228
-rw-r--r--extern/rangetree/range_tree_c_api.cc86
-rw-r--r--extern/rangetree/range_tree_c_api.h60
-rw-r--r--extern/wcwidth/CMakeLists.txt40
-rw-r--r--extern/wcwidth/SConscript9
-rw-r--r--extern/wcwidth/wcwidth.c309
-rw-r--r--extern/wcwidth/wcwidth.h (renamed from source/gameengine/Physics/common/PHY_IPhysicsController.cpp)20
-rw-r--r--intern/CMakeLists.txt8
-rw-r--r--intern/SConscript34
-rw-r--r--intern/audaspace/FX/AUD_CallbackIIRFilterReader.h2
-rw-r--r--intern/audaspace/FX/AUD_IDynamicIIRFilterCalculator.h2
-rw-r--r--intern/audaspace/SConscript23
-rw-r--r--intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp18
-rw-r--r--intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp15
-rw-r--r--intern/audaspace/intern/AUD_C-API.cpp5
-rw-r--r--intern/audaspace/intern/AUD_Sequencer.h2
-rw-r--r--intern/bsp/SConscript28
-rw-r--r--intern/bsp/intern/CSG_BooleanOps.cpp20
-rw-r--r--intern/container/SConscript28
-rw-r--r--intern/cycles/CMakeLists.txt13
-rw-r--r--intern/cycles/SConscript59
-rw-r--r--intern/cycles/app/cycles_server.cpp23
-rw-r--r--intern/cycles/app/cycles_xml.cpp16
-rw-r--r--intern/cycles/blender/CMakeLists.txt2
-rw-r--r--intern/cycles/blender/addon/__init__.py40
-rw-r--r--intern/cycles/blender/addon/engine.py9
-rw-r--r--intern/cycles/blender/addon/enums.py63
-rw-r--r--intern/cycles/blender/addon/osl.py17
-rw-r--r--intern/cycles/blender/addon/properties.py291
-rw-r--r--intern/cycles/blender/addon/ui.py432
-rw-r--r--intern/cycles/blender/blender_camera.cpp71
-rw-r--r--intern/cycles/blender/blender_curves.cpp1175
-rw-r--r--intern/cycles/blender/blender_mesh.cpp67
-rw-r--r--intern/cycles/blender/blender_object.cpp95
-rw-r--r--intern/cycles/blender/blender_python.cpp108
-rw-r--r--intern/cycles/blender/blender_session.cpp196
-rw-r--r--intern/cycles/blender/blender_session.h6
-rw-r--r--intern/cycles/blender/blender_shader.cpp1110
-rw-r--r--intern/cycles/blender/blender_sync.cpp34
-rw-r--r--intern/cycles/blender/blender_sync.h13
-rw-r--r--intern/cycles/blender/blender_util.h96
-rw-r--r--intern/cycles/bvh/bvh.cpp153
-rw-r--r--intern/cycles/bvh/bvh.h9
-rw-r--r--intern/cycles/bvh/bvh_build.cpp65
-rw-r--r--intern/cycles/bvh/bvh_build.h2
-rw-r--r--intern/cycles/bvh/bvh_params.h5
-rw-r--r--intern/cycles/bvh/bvh_sort.cpp2
-rw-r--r--intern/cycles/bvh/bvh_split.cpp55
-rw-r--r--intern/cycles/device/CMakeLists.txt7
-rw-r--r--intern/cycles/device/device.h1
-rw-r--r--intern/cycles/device/device_cpu.cpp53
-rw-r--r--intern/cycles/device/device_cuda.cpp91
-rw-r--r--intern/cycles/device/device_network.cpp543
-rw-r--r--intern/cycles/device/device_network.h111
-rw-r--r--intern/cycles/device/device_opencl.cpp2
-rw-r--r--intern/cycles/kernel/CMakeLists.txt12
-rw-r--r--intern/cycles/kernel/SConscript28
-rw-r--r--intern/cycles/kernel/closure/bsdf.h379
-rw-r--r--intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h2
-rw-r--r--intern/cycles/kernel/closure/bsdf_diffuse.h8
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet.h28
-rw-r--r--intern/cycles/kernel/closure/bsdf_oren_nayar.h2
-rw-r--r--intern/cycles/kernel/closure/bsdf_phong_ramp.h9
-rw-r--r--intern/cycles/kernel/closure/bsdf_toon.h206
-rw-r--r--intern/cycles/kernel/closure/bsdf_util.h137
-rw-r--r--intern/cycles/kernel/closure/bsdf_ward.h6
-rw-r--r--intern/cycles/kernel/closure/bsdf_westin.h10
-rw-r--r--intern/cycles/kernel/closure/emissive.h7
-rw-r--r--intern/cycles/kernel/closure/volume.h7
-rw-r--r--intern/cycles/kernel/kernel.h13
-rw-r--r--intern/cycles/kernel/kernel_accumulate.h63
-rw-r--r--intern/cycles/kernel/kernel_attribute.h50
-rw-r--r--intern/cycles/kernel/kernel_bvh.h673
-rw-r--r--intern/cycles/kernel/kernel_camera.h23
-rw-r--r--intern/cycles/kernel/kernel_compat_cpu.h4
-rw-r--r--intern/cycles/kernel/kernel_compat_cuda.h1
-rw-r--r--intern/cycles/kernel/kernel_compat_opencl.h1
-rw-r--r--intern/cycles/kernel/kernel_curve.h141
-rw-r--r--intern/cycles/kernel/kernel_displace.h4
-rw-r--r--intern/cycles/kernel/kernel_emission.h80
-rw-r--r--intern/cycles/kernel/kernel_light.h477
-rw-r--r--intern/cycles/kernel/kernel_montecarlo.h16
-rw-r--r--intern/cycles/kernel/kernel_object.h28
-rw-r--r--intern/cycles/kernel/kernel_passes.h13
-rw-r--r--intern/cycles/kernel/kernel_path.h106
-rw-r--r--intern/cycles/kernel/kernel_primitive.h185
-rw-r--r--intern/cycles/kernel/kernel_shader.h280
-rw-r--r--intern/cycles/kernel/kernel_sse2.cpp60
-rw-r--r--intern/cycles/kernel/kernel_sse3.cpp (renamed from intern/cycles/kernel/kernel_optimized.cpp)6
-rw-r--r--intern/cycles/kernel/kernel_textures.h6
-rw-r--r--intern/cycles/kernel/kernel_triangle.h77
-rw-r--r--intern/cycles/kernel/kernel_types.h105
-rw-r--r--intern/cycles/kernel/osl/CMakeLists.txt1
-rw-r--r--intern/cycles/kernel/osl/SConscript28
-rw-r--r--intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp4
-rw-r--r--intern/cycles/kernel/osl/bsdf_phong_ramp.cpp4
-rw-r--r--intern/cycles/kernel/osl/bsdf_toon.cpp179
-rw-r--r--intern/cycles/kernel/osl/emissive.cpp2
-rw-r--r--intern/cycles/kernel/osl/osl_closures.cpp39
-rw-r--r--intern/cycles/kernel/osl/osl_closures.h20
-rw-r--r--intern/cycles/kernel/osl/osl_globals.h11
-rw-r--r--intern/cycles/kernel/osl/osl_services.cpp120
-rw-r--r--intern/cycles/kernel/osl/osl_services.h10
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp162
-rw-r--r--intern/cycles/kernel/osl/osl_shader.h14
-rw-r--r--intern/cycles/kernel/shaders/CMakeLists.txt1
-rw-r--r--intern/cycles/kernel/shaders/SConscript28
-rw-r--r--intern/cycles/kernel/shaders/node_geometry.osl3
-rw-r--r--intern/cycles/kernel/shaders/node_hair_info.osl32
-rw-r--r--intern/cycles/kernel/shaders/node_mapping.osl3
-rw-r--r--intern/cycles/kernel/shaders/node_math.osl32
-rw-r--r--intern/cycles/kernel/shaders/node_musgrave_texture.osl24
-rw-r--r--intern/cycles/kernel/shaders/node_normal_map.osl20
-rw-r--r--intern/cycles/kernel/shaders/node_texture.h69
-rw-r--r--intern/cycles/kernel/shaders/node_vector_math.osl10
-rw-r--r--intern/cycles/kernel/shaders/node_wave_texture.osl7
-rw-r--r--intern/cycles/kernel/shaders/stdosl.h20
-rw-r--r--intern/cycles/kernel/svm/svm.h6
-rw-r--r--intern/cycles/kernel/svm/svm_attribute.h35
-rw-r--r--intern/cycles/kernel/svm/svm_bsdf.h279
-rw-r--r--intern/cycles/kernel/svm/svm_geometry.h49
-rw-r--r--intern/cycles/kernel/svm/svm_math.h67
-rw-r--r--intern/cycles/kernel/svm/svm_noise.h15
-rw-r--r--intern/cycles/kernel/svm/svm_tex_coord.h34
-rw-r--r--intern/cycles/kernel/svm/svm_types.h12
-rw-r--r--intern/cycles/render/CMakeLists.txt2
-rw-r--r--intern/cycles/render/attribute.cpp205
-rw-r--r--intern/cycles/render/attribute.h46
-rw-r--r--intern/cycles/render/buffers.cpp1
-rw-r--r--intern/cycles/render/camera.cpp4
-rw-r--r--intern/cycles/render/camera.h2
-rw-r--r--intern/cycles/render/curves.cpp210
-rw-r--r--intern/cycles/render/curves.h139
-rw-r--r--intern/cycles/render/graph.cpp3
-rw-r--r--intern/cycles/render/graph.h5
-rw-r--r--intern/cycles/render/image.cpp175
-rw-r--r--intern/cycles/render/image.h10
-rw-r--r--intern/cycles/render/light.cpp122
-rw-r--r--intern/cycles/render/light.h1
-rw-r--r--intern/cycles/render/mesh.cpp439
-rw-r--r--intern/cycles/render/mesh.h28
-rw-r--r--intern/cycles/render/mesh_displace.cpp28
-rw-r--r--intern/cycles/render/nodes.cpp96
-rw-r--r--intern/cycles/render/nodes.h21
-rw-r--r--intern/cycles/render/object.cpp102
-rw-r--r--intern/cycles/render/object.h1
-rw-r--r--intern/cycles/render/osl.cpp55
-rw-r--r--intern/cycles/render/osl.h19
-rw-r--r--intern/cycles/render/scene.cpp28
-rw-r--r--intern/cycles/render/scene.h12
-rw-r--r--intern/cycles/render/session.cpp35
-rw-r--r--intern/cycles/render/session.h1
-rw-r--r--intern/cycles/render/shader.h2
-rw-r--r--intern/cycles/render/svm.cpp12
-rw-r--r--intern/cycles/render/svm.h2
-rw-r--r--intern/cycles/render/tile.cpp60
-rw-r--r--intern/cycles/render/tile.h20
-rw-r--r--intern/cycles/subd/subd_dice.cpp2
-rw-r--r--intern/cycles/util/CMakeLists.txt2
-rw-r--r--intern/cycles/util/util_attribute.cpp51
-rw-r--r--intern/cycles/util/util_boundbox.h13
-rw-r--r--intern/cycles/util/util_cache.h8
-rw-r--r--intern/cycles/util/util_cuda.cpp40
-rw-r--r--intern/cycles/util/util_cuda.h6
-rw-r--r--intern/cycles/util/util_dynlib.cpp2
-rw-r--r--intern/cycles/util/util_math.h193
-rw-r--r--intern/cycles/util/util_system.cpp15
-rw-r--r--intern/cycles/util/util_system.h3
-rw-r--r--intern/cycles/util/util_task.cpp7
-rw-r--r--intern/cycles/util/util_task.h1
-rw-r--r--intern/cycles/util/util_transform.h2
-rw-r--r--intern/cycles/util/util_types.h20
-rw-r--r--intern/dualcon/SConscript28
-rw-r--r--intern/dualcon/intern/MemoryAllocator.h2
-rw-r--r--intern/elbeem/SConscript28
-rw-r--r--intern/elbeem/intern/ntl_geometrymodel.cpp8
-rw-r--r--intern/elbeem/intern/ntl_geometryobject.cpp7
-rw-r--r--intern/elbeem/intern/ntl_geometryobject.h2
-rw-r--r--intern/elbeem/intern/ntl_ray.cpp1
-rw-r--r--intern/elbeem/intern/ntl_ray.h3
-rw-r--r--intern/elbeem/intern/solver_main.cpp1
-rw-r--r--intern/elbeem/intern/solver_util.cpp14
-rw-r--r--intern/ffmpeg/ffmpeg_compat.h60
-rw-r--r--intern/ghost/CMakeLists.txt3
-rw-r--r--intern/ghost/GHOST_C-api.h24
-rw-r--r--intern/ghost/GHOST_ISystem.h34
-rw-r--r--intern/ghost/GHOST_IWindow.h7
-rw-r--r--intern/ghost/GHOST_Types.h1
-rw-r--r--intern/ghost/SConscript30
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp25
-rw-r--r--intern/ghost/intern/GHOST_Debug.h17
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp11
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerSDL.cpp2
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerWin32.cpp32
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerX11.cpp168
-rw-r--r--intern/ghost/intern/GHOST_DropTargetWin32.cpp2
-rw-r--r--intern/ghost/intern/GHOST_Event.h2
-rw-r--r--intern/ghost/intern/GHOST_EventManager.cpp2
-rw-r--r--intern/ghost/intern/GHOST_EventManager.h2
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerCocoa.mm2
-rw-r--r--intern/ghost/intern/GHOST_Path-api.cpp7
-rw-r--r--intern/ghost/intern/GHOST_System.cpp58
-rw-r--r--intern/ghost/intern/GHOST_System.h12
-rw-r--r--intern/ghost/intern/GHOST_SystemCarbon.cpp6
-rw-r--r--intern/ghost/intern/GHOST_SystemCarbon.h7
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h8
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm166
-rw-r--r--intern/ghost/intern/GHOST_SystemNULL.h22
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.cpp24
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.h11
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp29
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h9
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp519
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h112
-rw-r--r--intern/ghost/intern/GHOST_TimerManager.cpp2
-rw-r--r--intern/ghost/intern/GHOST_TimerTask.h2
-rw-r--r--intern/ghost/intern/GHOST_Window.cpp4
-rw-r--r--intern/ghost/intern/GHOST_Window.h13
-rw-r--r--intern/ghost/intern/GHOST_WindowCarbon.cpp3
-rw-r--r--intern/ghost/intern/GHOST_WindowCarbon.h5
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.h9
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm114
-rw-r--r--intern/ghost/intern/GHOST_WindowManager.cpp3
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.cpp3
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.h13
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp71
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h6
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp550
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.h35
-rw-r--r--intern/guardedalloc/MEM_guardedalloc.h2
-rw-r--r--intern/guardedalloc/SConscript27
-rw-r--r--intern/guardedalloc/intern/mallocn.c62
-rw-r--r--intern/iksolver/SConscript28
-rw-r--r--intern/iksolver/intern/IK_Solver.cpp2
-rw-r--r--intern/itasc/Armature.cpp8
-rw-r--r--intern/itasc/Armature.hpp2
-rw-r--r--intern/itasc/SConscript28
-rw-r--r--intern/itasc/kdl/chain.hpp2
-rw-r--r--intern/itasc/kdl/segment.cpp4
-rw-r--r--intern/itasc/kdl/tree.hpp4
-rw-r--r--intern/locale/SConscript27
-rw-r--r--intern/locale/boost_locale_wrapper.cpp73
-rw-r--r--intern/locale/boost_locale_wrapper.h5
-rw-r--r--intern/memutil/MEM_Allocator.h2
-rw-r--r--intern/memutil/MEM_CacheLimiter.h16
-rw-r--r--intern/memutil/MEM_CacheLimiterC-Api.h4
-rw-r--r--intern/memutil/SConscript28
-rw-r--r--intern/memutil/intern/MEM_CacheLimiterC-Api.cpp7
-rw-r--r--intern/mikktspace/SConscript28
-rw-r--r--intern/moto/SConscript28
-rw-r--r--intern/opencl/CMakeLists.txt (renamed from source/blender/opencl/CMakeLists.txt)2
-rw-r--r--intern/opencl/OCL_opencl.h (renamed from source/blender/opencl/OCL_opencl.h)0
-rw-r--r--intern/opencl/SConscript34
-rw-r--r--intern/opencl/intern/OCL_opencl.c (renamed from source/blender/opencl/intern/OCL_opencl.c)0
-rw-r--r--intern/opencl/intern/clew.c (renamed from source/blender/opencl/intern/clew.c)0
-rw-r--r--intern/opencl/intern/clew.h (renamed from source/blender/opencl/intern/clew.h)0
-rw-r--r--intern/opencolorio/SConscript27
-rw-r--r--intern/opencolorio/fallback_impl.cc2
-rw-r--r--intern/opencolorio/ocio_capi.cc4
-rw-r--r--intern/opencolorio/ocio_capi.h4
-rw-r--r--intern/opencolorio/ocio_impl.cc2
-rw-r--r--intern/opencolorio/ocio_impl.h4
-rw-r--r--intern/opennl/SConscript28
-rw-r--r--intern/raskter/SConscript27
-rw-r--r--intern/raskter/raskter.c2
-rw-r--r--intern/rigidbody/CMakeLists.txt (renamed from source/gameengine/Physics/common/CMakeLists.txt)25
-rw-r--r--intern/rigidbody/RBI_api.h315
-rw-r--r--intern/rigidbody/SConscript42
-rw-r--r--intern/rigidbody/rb_bullet_api.cpp995
-rw-r--r--intern/smoke/CMakeLists.txt2
-rw-r--r--intern/smoke/SConscript28
-rw-r--r--intern/smoke/intern/FFT_NOISE.h6
-rw-r--r--intern/smoke/intern/FLUID_3D.cpp6
-rw-r--r--intern/smoke/intern/FLUID_3D.h4
-rw-r--r--intern/smoke/intern/FLUID_3D_STATIC.cpp52
-rw-r--r--intern/smoke/intern/WAVELET_NOISE.h2
-rw-r--r--intern/smoke/intern/WTURBULENCE.h2
-rw-r--r--intern/smoke/intern/smoke_API.cpp42
-rw-r--r--intern/string/SConscript28
-rw-r--r--intern/string/STR_String.h10
-rw-r--r--intern/string/intern/STR_String.cpp2
-rw-r--r--intern/utfconv/SConscript28
-rw-r--r--intern/utfconv/utf_winfunc.c18
-rw-r--r--intern/utfconv/utf_winfunc.h1
-rw-r--r--[-rwxr-xr-x]release/bin/blender-softwaregl50
-rw-r--r--release/darwin/blender.app/Contents/Info.plist2
-rw-r--r--release/darwin/blender.app/Contents/MacOS/blender2
-rw-r--r--release/darwin/blenderplayer.app/Contents/Info.plist2
-rw-r--r--release/darwin/blenderplayer.app/Contents/MacOS/blenderplayer2
-rw-r--r--release/datafiles/LICENSE-bmonofont-i18n.ttf.txt90
-rw-r--r--release/datafiles/LICENSE-droidsans.ttf.txt83
-rw-r--r--release/datafiles/blender_icons.pngbin189744 -> 0 bytes
-rwxr-xr-xrelease/datafiles/blender_icons.sh5
-rw-r--r--release/datafiles/blender_icons.svg85288
-rw-r--r--release/datafiles/blender_icons16.pngbin0 -> 239745 bytes
-rw-r--r--release/datafiles/blender_icons32.pngbin0 -> 602125 bytes
-rw-r--r--release/datafiles/fonts/bmonofont-i18n.ttf.gzbin0 -> 2623844 bytes
-rw-r--r--release/datafiles/fonts/droidsans.ttf.gzbin2347305 -> 2617436 bytes
-rw-r--r--release/datafiles/matcaps/license.txt3
-rw-r--r--release/datafiles/matcaps/mc01.jpgbin0 -> 20830 bytes
-rw-r--r--release/datafiles/matcaps/mc02.jpgbin0 -> 23428 bytes
-rw-r--r--release/datafiles/matcaps/mc03.jpgbin0 -> 17550 bytes
-rw-r--r--release/datafiles/matcaps/mc04.jpgbin0 -> 29197 bytes
-rw-r--r--release/datafiles/matcaps/mc05.jpgbin0 -> 25454 bytes
-rw-r--r--release/datafiles/matcaps/mc06.jpgbin0 -> 19864 bytes
-rw-r--r--release/datafiles/matcaps/mc07.jpgbin0 -> 59262 bytes
-rw-r--r--release/datafiles/matcaps/mc08.jpgbin0 -> 24133 bytes
-rw-r--r--release/datafiles/matcaps/mc09.jpgbin0 -> 31101 bytes
-rw-r--r--release/datafiles/matcaps/mc10.jpgbin0 -> 28973 bytes
-rw-r--r--release/datafiles/matcaps/mc11.jpgbin0 -> 21395 bytes
-rw-r--r--release/datafiles/matcaps/mc12.jpgbin0 -> 23797 bytes
-rw-r--r--release/datafiles/matcaps/mc13.jpgbin0 -> 45661 bytes
-rw-r--r--release/datafiles/matcaps/mc14.jpgbin0 -> 44762 bytes
-rw-r--r--release/datafiles/matcaps/mc15.jpgbin0 -> 27456 bytes
-rw-r--r--release/datafiles/matcaps/mc16.jpgbin0 -> 33401 bytes
-rw-r--r--release/datafiles/matcaps/mc17.jpgbin0 -> 49292 bytes
-rw-r--r--release/datafiles/matcaps/mc18.jpgbin0 -> 40254 bytes
-rw-r--r--release/datafiles/matcaps/mc19.jpgbin0 -> 46330 bytes
-rw-r--r--release/datafiles/matcaps/mc20.jpgbin0 -> 52893 bytes
-rw-r--r--release/datafiles/matcaps/mc21.jpgbin0 -> 28717 bytes
-rw-r--r--release/datafiles/matcaps/mc22.jpgbin0 -> 33801 bytes
-rw-r--r--release/datafiles/matcaps/mc23.jpgbin0 -> 26688 bytes
-rw-r--r--release/datafiles/matcaps/mc24.jpgbin0 -> 14149 bytes
-rw-r--r--release/datafiles/preview_cycles.blendbin0 -> 1326220 bytes
-rwxr-xr-xrelease/datafiles/prvicons.sh4
-rw-r--r--release/datafiles/prvicons.svg19741
-rw-r--r--release/datafiles/splash.pngbin330539 -> 128911 bytes
-rw-r--r--release/datafiles/startup.blendbin415348 -> 418164 bytes
-rw-r--r--release/scripts/freestyle/data/env_map/brown00.pngbin0 -> 22195 bytes
-rw-r--r--release/scripts/freestyle/data/env_map/gray00.pngbin0 -> 18513 bytes
-rw-r--r--release/scripts/freestyle/data/env_map/gray01.pngbin0 -> 9915 bytes
-rw-r--r--release/scripts/freestyle/data/env_map/gray02.pngbin0 -> 7197 bytes
-rw-r--r--release/scripts/freestyle/data/env_map/gray03.pngbin0 -> 16109 bytes
-rw-r--r--release/scripts/freestyle/style_modules/ChainingIterators.py703
-rw-r--r--release/scripts/freestyle/style_modules/Functions0D.py105
-rw-r--r--release/scripts/freestyle/style_modules/Functions1D.py58
-rw-r--r--release/scripts/freestyle/style_modules/PredicatesB1D.py73
-rw-r--r--release/scripts/freestyle/style_modules/PredicatesU0D.py96
-rw-r--r--release/scripts/freestyle/style_modules/PredicatesU1D.py342
-rw-r--r--release/scripts/freestyle/style_modules/anisotropic_diffusion.py44
-rw-r--r--release/scripts/freestyle/style_modules/apriori_and_causal_density.py39
-rw-r--r--release/scripts/freestyle/style_modules/apriori_density.py37
-rw-r--r--release/scripts/freestyle/style_modules/backbone_stretcher.py35
-rw-r--r--release/scripts/freestyle/style_modules/blueprint_circles.py42
-rw-r--r--release/scripts/freestyle/style_modules/blueprint_ellipses.py42
-rw-r--r--release/scripts/freestyle/style_modules/blueprint_squares.py43
-rw-r--r--release/scripts/freestyle/style_modules/cartoon.py38
-rw-r--r--release/scripts/freestyle/style_modules/contour.py36
-rw-r--r--release/scripts/freestyle/style_modules/curvature2d.py37
-rw-r--r--release/scripts/freestyle/style_modules/external_contour.py36
-rw-r--r--release/scripts/freestyle/style_modules/external_contour_sketchy.py43
-rw-r--r--release/scripts/freestyle/style_modules/external_contour_smooth.py39
-rw-r--r--release/scripts/freestyle/style_modules/haloing.py46
-rw-r--r--release/scripts/freestyle/style_modules/ignore_small_occlusions.py36
-rw-r--r--release/scripts/freestyle/style_modules/invisible_lines.py37
-rw-r--r--release/scripts/freestyle/style_modules/japanese_bigbrush.py56
-rw-r--r--release/scripts/freestyle/style_modules/logical_operators.py47
-rw-r--r--release/scripts/freestyle/style_modules/long_anisotropically_dense.py68
-rw-r--r--release/scripts/freestyle/style_modules/multiple_parameterization.py47
-rw-r--r--release/scripts/freestyle/style_modules/nature.py39
-rw-r--r--release/scripts/freestyle/style_modules/near_lines.py38
-rw-r--r--release/scripts/freestyle/style_modules/occluded_by_specific_object.py40
-rw-r--r--release/scripts/freestyle/style_modules/parameter_editor.py1259
-rw-r--r--release/scripts/freestyle/style_modules/polygonalize.py36
-rw-r--r--release/scripts/freestyle/style_modules/qi0.py36
-rw-r--r--release/scripts/freestyle/style_modules/qi0_not_external_contour.py41
-rw-r--r--release/scripts/freestyle/style_modules/qi1.py37
-rw-r--r--release/scripts/freestyle/style_modules/qi2.py37
-rw-r--r--release/scripts/freestyle/style_modules/sequentialsplit_sketchy.py44
-rw-r--r--release/scripts/freestyle/style_modules/shaders.py1238
-rw-r--r--release/scripts/freestyle/style_modules/sketchy_multiple_parameterization.py43
-rw-r--r--release/scripts/freestyle/style_modules/sketchy_topology_broken.py47
-rw-r--r--release/scripts/freestyle/style_modules/sketchy_topology_preserved.py42
-rw-r--r--release/scripts/freestyle/style_modules/split_at_highest_2d_curvatures.py41
-rw-r--r--release/scripts/freestyle/style_modules/split_at_tvertices.py40
-rw-r--r--release/scripts/freestyle/style_modules/stroke_texture.py38
-rw-r--r--release/scripts/freestyle/style_modules/suggestive.py38
-rw-r--r--release/scripts/freestyle/style_modules/thickness_fof_depth_discontinuity.py37
-rw-r--r--release/scripts/freestyle/style_modules/tipremover.py36
-rw-r--r--release/scripts/freestyle/style_modules/tvertex_remover.py37
-rw-r--r--release/scripts/freestyle/style_modules/uniformpruning_zsort.py39
-rw-r--r--release/scripts/modules/addon_utils.py63
-rw-r--r--release/scripts/modules/bl_i18n_utils/bl_extract_messages.py917
-rw-r--r--release/scripts/modules/bl_i18n_utils/bl_process_msg.py524
-rwxr-xr-xrelease/scripts/modules/bl_i18n_utils/check_po.py177
-rwxr-xr-xrelease/scripts/modules/bl_i18n_utils/clean_po.py99
-rwxr-xr-xrelease/scripts/modules/bl_i18n_utils/import_po_from_branches.py123
-rwxr-xr-xrelease/scripts/modules/bl_i18n_utils/merge_po.py105
-rw-r--r--release/scripts/modules/bl_i18n_utils/settings.py413
-rw-r--r--release/scripts/modules/bl_i18n_utils/settings_user.py (renamed from release/scripts/modules/bl_i18n_utils/user_settings.py)0
-rw-r--r--release/scripts/modules/bl_i18n_utils/spell_check_utils.py528
-rwxr-xr-xrelease/scripts/modules/bl_i18n_utils/update_branches.py107
-rwxr-xr-xrelease/scripts/modules/bl_i18n_utils/update_languages_menu.py148
-rwxr-xr-xrelease/scripts/modules/bl_i18n_utils/update_mo.py106
-rwxr-xr-xrelease/scripts/modules/bl_i18n_utils/update_msg.py72
-rwxr-xr-xrelease/scripts/modules/bl_i18n_utils/update_po.py172
-rwxr-xr-xrelease/scripts/modules/bl_i18n_utils/update_pot.py339
-rwxr-xr-xrelease/scripts/modules/bl_i18n_utils/update_trunk.py162
-rw-r--r--release/scripts/modules/bl_i18n_utils/utils.py1621
-rwxr-xr-xrelease/scripts/modules/bl_i18n_utils/utils_languages_menu.py96
-rwxr-xr-xrelease/scripts/modules/bl_i18n_utils/utils_rtl.py (renamed from release/scripts/modules/bl_i18n_utils/rtl_preprocess.py)72
-rw-r--r--release/scripts/modules/bl_i18n_utils/utils_spell_check.py598
-rw-r--r--release/scripts/modules/bpy/__init__.py1
-rw-r--r--release/scripts/modules/bpy/path.py8
-rw-r--r--release/scripts/modules/bpy/utils.py60
-rw-r--r--release/scripts/modules/bpy_extras/anim_utils.py190
-rw-r--r--release/scripts/modules/bpy_extras/io_utils.py32
-rw-r--r--release/scripts/modules/bpy_extras/keyconfig_utils.py37
-rw-r--r--release/scripts/modules/bpy_extras/mesh_utils.py15
-rw-r--r--release/scripts/modules/bpy_extras/object_utils.py10
-rw-r--r--release/scripts/modules/bpy_extras/view3d_utils.py4
-rw-r--r--release/scripts/modules/bpy_restrict_state.py66
-rw-r--r--release/scripts/modules/bpy_types.py175
-rw-r--r--release/scripts/modules/console/complete_import.py8
-rw-r--r--release/scripts/modules/console/intellisense.py2
-rw-r--r--release/scripts/modules/console_python.py4
-rw-r--r--release/scripts/modules/rna_prop_ui.py9
-rw-r--r--release/scripts/modules/rna_xml.py10
-rw-r--r--release/scripts/presets/interaction/3dsmax.py12
-rw-r--r--release/scripts/presets/interface_theme/back_to_black.xml204
-rw-r--r--release/scripts/presets/interface_theme/blender_24x.xml204
-rw-r--r--release/scripts/presets/interface_theme/elsyiun.xml204
-rw-r--r--release/scripts/presets/interface_theme/hexagon.xml204
-rw-r--r--release/scripts/presets/interface_theme/ubuntu_ambiance.xml204
-rw-r--r--release/scripts/presets/keyconfig/3dsmax.py1359
-rw-r--r--release/scripts/presets/keyconfig/maya.py14
-rw-r--r--release/scripts/presets/operator/wm.collada_export/second_life_rigged.py2
-rw-r--r--release/scripts/presets/operator/wm.collada_export/second_life_static.py2
-rw-r--r--release/scripts/startup/bl_operators/__init__.py15
-rw-r--r--release/scripts/startup/bl_operators/add_mesh_torus.py5
-rw-r--r--release/scripts/startup/bl_operators/anim.py19
-rw-r--r--release/scripts/startup/bl_operators/freestyle.py135
-rw-r--r--release/scripts/startup/bl_operators/node.py267
-rw-r--r--release/scripts/startup/bl_operators/object.py35
-rw-r--r--release/scripts/startup/bl_operators/object_align.py22
-rw-r--r--release/scripts/startup/bl_operators/object_quick_effects.py8
-rw-r--r--release/scripts/startup/bl_operators/object_randomize_transform.py8
-rw-r--r--release/scripts/startup/bl_operators/presets.py12
-rw-r--r--release/scripts/startup/bl_operators/rigidbody.py292
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_follow_active.py93
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_lightmap.py18
-rw-r--r--release/scripts/startup/bl_operators/vertexpaint_dirt.py24
-rw-r--r--release/scripts/startup/bl_operators/wm.py72
-rw-r--r--release/scripts/startup/bl_ui/__init__.py27
-rw-r--r--release/scripts/startup/bl_ui/properties_constraint.py (renamed from release/scripts/startup/bl_ui/properties_object_constraint.py)13
-rw-r--r--release/scripts/startup/bl_ui/properties_data_armature.py5
-rw-r--r--release/scripts/startup/bl_ui/properties_data_bone.py8
-rw-r--r--release/scripts/startup/bl_ui/properties_data_camera.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py81
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py136
-rw-r--r--release/scripts/startup/bl_ui/properties_freestyle.py668
-rw-r--r--release/scripts/startup/bl_ui/properties_game.py26
-rw-r--r--release/scripts/startup/bl_ui/properties_mask_common.py22
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py32
-rw-r--r--release/scripts/startup/bl_ui/properties_object.py9
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py35
-rw-r--r--release/scripts/startup/bl_ui/properties_particle.py104
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_cloth.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_common.py44
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py26
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py17
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_rigidbody.py132
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py233
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_smoke.py24
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py150
-rw-r--r--release/scripts/startup/bl_ui/properties_render_layer.py178
-rw-r--r--release/scripts/startup/bl_ui/properties_scene.py228
-rw-r--r--release/scripts/startup/bl_ui/properties_texture.py63
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py37
-rw-r--r--release/scripts/startup/bl_ui/space_console.py4
-rw-r--r--release/scripts/startup/bl_ui/space_dopesheet.py12
-rw-r--r--release/scripts/startup/bl_ui/space_graph.py4
-rw-r--r--release/scripts/startup/bl_ui/space_image.py44
-rw-r--r--release/scripts/startup/bl_ui/space_info.py19
-rw-r--r--release/scripts/startup/bl_ui/space_nla.py3
-rw-r--r--release/scripts/startup/bl_ui/space_node.py45
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py28
-rw-r--r--release/scripts/startup/bl_ui/space_text.py38
-rw-r--r--release/scripts/startup/bl_ui/space_time.py1
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py150
-rw-r--r--release/scripts/startup/bl_ui/space_userpref_keymap.py142
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py178
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py187
-rw-r--r--release/scripts/startup/keyingsets_builtins.py127
-rw-r--r--release/scripts/templates_osl/empty_shader.osl6
-rw-r--r--release/scripts/templates_osl/noise.osl18
-rw-r--r--release/scripts/templates_osl/wireframe.osl11
-rw-r--r--release/scripts/templates_py/addon_add_object.py (renamed from release/scripts/templates/addon_add_object.py)2
-rw-r--r--release/scripts/templates_py/background_job.py (renamed from release/scripts/templates/background_job.py)0
-rw-r--r--release/scripts/templates_py/batch_export.py (renamed from release/scripts/templates/batch_export.py)0
-rw-r--r--release/scripts/templates_py/bmesh_simple.py (renamed from release/scripts/templates/bmesh_simple.py)0
-rw-r--r--release/scripts/templates_py/bmesh_simple_editmode.py (renamed from release/scripts/templates/bmesh_simple_editmode.py)0
-rw-r--r--release/scripts/templates_py/builtin_keyingset.py (renamed from release/scripts/templates/builtin_keyingset.py)0
-rw-r--r--release/scripts/templates_py/custom_nodes.py160
-rw-r--r--release/scripts/templates_py/driver_functions.py (renamed from release/scripts/templates/driver_functions.py)0
-rw-r--r--release/scripts/templates_py/gamelogic.py (renamed from release/scripts/templates/gamelogic.py)0
-rw-r--r--release/scripts/templates_py/gamelogic_module.py (renamed from release/scripts/templates/gamelogic_module.py)0
-rw-r--r--release/scripts/templates_py/gamelogic_simple.py (renamed from release/scripts/templates/gamelogic_simple.py)0
-rw-r--r--release/scripts/templates_py/operator_file_export.py (renamed from release/scripts/templates/operator_file_export.py)0
-rw-r--r--release/scripts/templates_py/operator_file_import.py (renamed from release/scripts/templates/operator_file_import.py)0
-rw-r--r--release/scripts/templates_py/operator_mesh_add.py (renamed from release/scripts/templates/operator_mesh_add.py)0
-rw-r--r--release/scripts/templates_py/operator_modal.py (renamed from release/scripts/templates/operator_modal.py)0
-rw-r--r--release/scripts/templates_py/operator_modal_draw.py (renamed from release/scripts/templates/operator_modal_draw.py)8
-rw-r--r--release/scripts/templates_py/operator_modal_timer.py (renamed from release/scripts/templates/operator_modal_timer.py)2
-rw-r--r--release/scripts/templates_py/operator_modal_view3d.py (renamed from release/scripts/templates/operator_modal_view3d.py)0
-rw-r--r--release/scripts/templates_py/operator_modal_view3d_raycast.py (renamed from release/scripts/templates/operator_modal_view3d_raycast.py)7
-rw-r--r--release/scripts/templates_py/operator_node.py (renamed from release/scripts/templates/operator_node.py)0
-rw-r--r--release/scripts/templates_py/operator_simple.py (renamed from release/scripts/templates/operator_simple.py)0
-rw-r--r--release/scripts/templates_py/operator_uv.py (renamed from release/scripts/templates/operator_uv.py)0
-rw-r--r--release/scripts/templates_py/script_stub.py (renamed from release/scripts/templates/script_stub.py)0
-rw-r--r--release/scripts/templates_py/ui_list.py79
-rw-r--r--release/scripts/templates_py/ui_menu.py (renamed from release/scripts/templates/ui_menu.py)0
-rw-r--r--release/scripts/templates_py/ui_menu_simple.py (renamed from release/scripts/templates/ui_menu_simple.py)0
-rw-r--r--release/scripts/templates_py/ui_panel.py (renamed from release/scripts/templates/ui_panel.py)0
-rw-r--r--release/scripts/templates_py/ui_panel_simple.py (renamed from release/scripts/templates/ui_panel_simple.py)0
-rw-r--r--release/text/readme.html10
-rw-r--r--release/windows/contrib/vfapi/vfapi-plugin.c6
-rw-r--r--source/SConscript28
-rw-r--r--source/blender/CMakeLists.txt9
-rw-r--r--source/blender/SConscript34
-rw-r--r--source/blender/avi/SConscript28
-rw-r--r--source/blender/avi/intern/avi.c38
-rw-r--r--source/blender/avi/intern/avi_endian.c2
-rw-r--r--source/blender/avi/intern/avi_intern.h24
-rw-r--r--source/blender/avi/intern/avi_mjpeg.c23
-rw-r--r--source/blender/blenfont/BLF_api.h3
-rw-r--r--source/blender/blenfont/BLF_translation.h112
-rw-r--r--source/blender/blenfont/CMakeLists.txt1
-rw-r--r--source/blender/blenfont/SConscript32
-rw-r--r--source/blender/blenfont/intern/blf.c27
-rw-r--r--source/blender/blenfont/intern/blf_dir.c1
-rw-r--r--source/blender/blenfont/intern/blf_font.c34
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c32
-rw-r--r--source/blender/blenfont/intern/blf_internal.h1
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h2
-rw-r--r--source/blender/blenfont/intern/blf_lang.c146
-rw-r--r--source/blender/blenfont/intern/blf_translation.c118
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h16
-rw-r--r--source/blender/blenkernel/BKE_action.h5
-rw-r--r--source/blender/blenkernel/BKE_addon.h42
-rw-r--r--source/blender/blenkernel/BKE_anim.h4
-rw-r--r--source/blender/blenkernel/BKE_animsys.h4
-rw-r--r--source/blender/blenkernel/BKE_armature.h2
-rw-r--r--source/blender/blenkernel/BKE_blender.h24
-rw-r--r--source/blender/blenkernel/BKE_bmesh.h3
-rw-r--r--source/blender/blenkernel/BKE_bpath.h (renamed from source/blender/blenlib/BLI_bpath.h)40
-rw-r--r--source/blender/blenkernel/BKE_brush.h28
-rw-r--r--source/blender/blenkernel/BKE_camera.h5
-rw-r--r--source/blender/blenkernel/BKE_ccg.h2
-rw-r--r--source/blender/blenkernel/BKE_cdderivedmesh.h4
-rw-r--r--source/blender/blenkernel/BKE_colortools.h8
-rw-r--r--source/blender/blenkernel/BKE_constraint.h48
-rw-r--r--source/blender/blenkernel/BKE_context.h1
-rw-r--r--source/blender/blenkernel/BKE_curve.h21
-rw-r--r--source/blender/blenkernel/BKE_customdata.h8
-rw-r--r--source/blender/blenkernel/BKE_deform.h18
-rw-r--r--source/blender/blenkernel/BKE_depsgraph.h175
-rw-r--r--source/blender/blenkernel/BKE_displist.h6
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h9
-rw-r--r--source/blender/blenkernel/BKE_font.h2
-rw-r--r--source/blender/blenkernel/BKE_freestyle.h64
-rw-r--r--source/blender/blenkernel/BKE_global.h10
-rw-r--r--source/blender/blenkernel/BKE_group.h3
-rw-r--r--source/blender/blenkernel/BKE_idcode.h42
-rw-r--r--source/blender/blenkernel/BKE_idprop.h86
-rw-r--r--source/blender/blenkernel/BKE_image.h27
-rw-r--r--source/blender/blenkernel/BKE_key.h2
-rw-r--r--source/blender/blenkernel/BKE_lamp.h3
-rw-r--r--source/blender/blenkernel/BKE_lattice.h8
-rw-r--r--source/blender/blenkernel/BKE_library.h26
-rw-r--r--source/blender/blenkernel/BKE_linestyle.h76
-rw-r--r--source/blender/blenkernel/BKE_main.h15
-rw-r--r--source/blender/blenkernel/BKE_mask.h2
-rw-r--r--source/blender/blenkernel/BKE_material.h2
-rw-r--r--source/blender/blenkernel/BKE_mball.h7
-rw-r--r--source/blender/blenkernel/BKE_mesh.h74
-rw-r--r--source/blender/blenkernel/BKE_modifier.h2
-rw-r--r--source/blender/blenkernel/BKE_movieclip.h11
-rw-r--r--source/blender/blenkernel/BKE_multires.h2
-rw-r--r--source/blender/blenkernel/BKE_nla.h4
-rw-r--r--source/blender/blenkernel/BKE_node.h505
-rw-r--r--source/blender/blenkernel/BKE_object.h39
-rw-r--r--source/blender/blenkernel/BKE_packedFile.h8
-rw-r--r--source/blender/blenkernel/BKE_paint.h26
-rw-r--r--source/blender/blenkernel/BKE_particle.h32
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h (renamed from source/blender/blenlib/BLI_pbvh.h)174
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h7
-rw-r--r--source/blender/blenkernel/BKE_property.h3
-rw-r--r--source/blender/blenkernel/BKE_report.h8
-rw-r--r--source/blender/blenkernel/BKE_rigidbody.h97
-rw-r--r--source/blender/blenkernel/BKE_scene.h6
-rw-r--r--source/blender/blenkernel/BKE_screen.h33
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h27
-rw-r--r--source/blender/blenkernel/BKE_shrinkwrap.h14
-rw-r--r--source/blender/blenkernel/BKE_speaker.h4
-rw-r--r--source/blender/blenkernel/BKE_suggestions.h2
-rw-r--r--source/blender/blenkernel/BKE_tessmesh.h7
-rw-r--r--source/blender/blenkernel/BKE_text.h24
-rw-r--r--source/blender/blenkernel/BKE_texture.h7
-rw-r--r--source/blender/blenkernel/BKE_tracking.h6
-rw-r--r--source/blender/blenkernel/BKE_unit.h3
-rw-r--r--source/blender/blenkernel/BKE_world.h3
-rw-r--r--source/blender/blenkernel/CMakeLists.txt28
-rw-r--r--source/blender/blenkernel/SConscript34
-rw-r--r--source/blender/blenkernel/depsgraph_private.h34
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c49
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c215
-rw-r--r--source/blender/blenkernel/intern/action.c20
-rw-r--r--source/blender/blenkernel/intern/addon.c85
-rw-r--r--source/blender/blenkernel/intern/anim.c78
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c26
-rw-r--r--source/blender/blenkernel/intern/armature.c29
-rw-r--r--source/blender/blenkernel/intern/blender.c288
-rw-r--r--source/blender/blenkernel/intern/bmfont.c12
-rw-r--r--source/blender/blenkernel/intern/booleanops_mesh.c24
-rw-r--r--source/blender/blenkernel/intern/bpath.c (renamed from source/blender/blenlib/intern/bpath.c)83
-rw-r--r--source/blender/blenkernel/intern/brush.c693
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c2
-rw-r--r--source/blender/blenkernel/intern/camera.c9
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c203
-rw-r--r--source/blender/blenkernel/intern/cloth.c8
-rw-r--r--source/blender/blenkernel/intern/collision.c18
-rw-r--r--source/blender/blenkernel/intern/colortools.c10
-rw-r--r--source/blender/blenkernel/intern/constraint.c124
-rw-r--r--source/blender/blenkernel/intern/context.c80
-rw-r--r--source/blender/blenkernel/intern/curve.c357
-rw-r--r--source/blender/blenkernel/intern/customdata.c166
-rw-r--r--source/blender/blenkernel/intern/customdata_file.c4
-rw-r--r--source/blender/blenkernel/intern/deform.c121
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c762
-rw-r--r--source/blender/blenkernel/intern/displist.c136
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c158
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c444
-rw-r--r--source/blender/blenkernel/intern/effect.c10
-rw-r--r--source/blender/blenkernel/intern/fcurve.c171
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c141
-rw-r--r--source/blender/blenkernel/intern/font.c27
-rw-r--r--source/blender/blenkernel/intern/freestyle.c234
-rw-r--r--source/blender/blenkernel/intern/gpencil.c4
-rw-r--r--source/blender/blenkernel/intern/group.c9
-rw-r--r--source/blender/blenkernel/intern/icons.c6
-rw-r--r--source/blender/blenkernel/intern/idcode.c56
-rw-r--r--source/blender/blenkernel/intern/idprop.c125
-rw-r--r--source/blender/blenkernel/intern/image.c441
-rw-r--r--source/blender/blenkernel/intern/image_gen.c5
-rw-r--r--source/blender/blenkernel/intern/implicit.c2
-rw-r--r--source/blender/blenkernel/intern/ipo.c4
-rw-r--r--source/blender/blenkernel/intern/key.c90
-rw-r--r--source/blender/blenkernel/intern/lamp.c4
-rw-r--r--source/blender/blenkernel/intern/lattice.c100
-rw-r--r--source/blender/blenkernel/intern/library.c408
-rw-r--r--source/blender/blenkernel/intern/linestyle.c1070
-rw-r--r--source/blender/blenkernel/intern/mask.c19
-rw-r--r--source/blender/blenkernel/intern/mask_rasterize.c6
-rw-r--r--source/blender/blenkernel/intern/material.c45
-rw-r--r--source/blender/blenkernel/intern/mball.c112
-rw-r--r--source/blender/blenkernel/intern/mesh.c594
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c50
-rw-r--r--source/blender/blenkernel/intern/modifier.c16
-rw-r--r--source/blender/blenkernel/intern/modifiers_bmesh.c78
-rw-r--r--source/blender/blenkernel/intern/movieclip.c175
-rw-r--r--source/blender/blenkernel/intern/multires.c10
-rw-r--r--source/blender/blenkernel/intern/navmesh_conversion.c2
-rw-r--r--source/blender/blenkernel/intern/nla.c10
-rw-r--r--source/blender/blenkernel/intern/node.c2996
-rw-r--r--source/blender/blenkernel/intern/object.c415
-rw-r--r--source/blender/blenkernel/intern/ocean.c359
-rw-r--r--source/blender/blenkernel/intern/packedFile.c136
-rw-r--r--source/blender/blenkernel/intern/paint.c96
-rw-r--r--source/blender/blenkernel/intern/particle.c31
-rw-r--r--source/blender/blenkernel/intern/particle_system.c489
-rw-r--r--source/blender/blenkernel/intern/pbvh.c (renamed from source/blender/blenlib/intern/pbvh.c)389
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c1440
-rw-r--r--source/blender/blenkernel/intern/pbvh_intern.h186
-rw-r--r--source/blender/blenkernel/intern/pointcache.c345
-rw-r--r--source/blender/blenkernel/intern/property.c8
-rw-r--r--source/blender/blenkernel/intern/report.c43
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c1348
-rw-r--r--source/blender/blenkernel/intern/sca.c6
-rw-r--r--source/blender/blenkernel/intern/scene.c166
-rw-r--r--source/blender/blenkernel/intern/screen.c16
-rw-r--r--source/blender/blenkernel/intern/seqcache.c4
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c591
-rw-r--r--source/blender/blenkernel/intern/seqmodifier.c24
-rw-r--r--source/blender/blenkernel/intern/sequencer.c312
-rw-r--r--source/blender/blenkernel/intern/smoke.c85
-rw-r--r--source/blender/blenkernel/intern/softbody.c68
-rw-r--r--source/blender/blenkernel/intern/speaker.c5
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c176
-rw-r--r--source/blender/blenkernel/intern/suggestions.c8
-rw-r--r--source/blender/blenkernel/intern/text.c110
-rw-r--r--source/blender/blenkernel/intern/texture.c30
-rw-r--r--source/blender/blenkernel/intern/tracking.c329
-rw-r--r--source/blender/blenkernel/intern/unit.c66
-rw-r--r--source/blender/blenkernel/intern/world.c4
-rw-r--r--source/blender/blenkernel/intern/writeavi.c2
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c121
-rw-r--r--source/blender/blenkernel/nla_private.h4
-rw-r--r--source/blender/blenlib/BLI_array.h131
-rw-r--r--source/blender/blenlib/BLI_buffer.h106
-rw-r--r--source/blender/blenlib/BLI_callbacks.h2
-rw-r--r--source/blender/blenlib/BLI_fileops.h21
-rw-r--r--source/blender/blenlib/BLI_fileops_types.h1
-rw-r--r--source/blender/blenlib/BLI_ghash.h9
-rw-r--r--source/blender/blenlib/BLI_gsqueue.h52
-rw-r--r--source/blender/blenlib/BLI_heap.h2
-rw-r--r--source/blender/blenlib/BLI_lasso.h4
-rw-r--r--source/blender/blenlib/BLI_linklist.h1
-rw-r--r--source/blender/blenlib/BLI_listbase.h8
-rw-r--r--source/blender/blenlib/BLI_math_base.h37
-rw-r--r--source/blender/blenlib/BLI_math_color.h9
-rw-r--r--source/blender/blenlib/BLI_math_geom.h40
-rw-r--r--source/blender/blenlib/BLI_math_inline.h5
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h13
-rw-r--r--source/blender/blenlib/BLI_math_rotation.h5
-rw-r--r--source/blender/blenlib/BLI_math_vector.h15
-rw-r--r--source/blender/blenlib/BLI_mempool.h12
-rw-r--r--source/blender/blenlib/BLI_path_util.h79
-rw-r--r--source/blender/blenlib/BLI_rect.h32
-rw-r--r--source/blender/blenlib/BLI_scanfill.h7
-rw-r--r--source/blender/blenlib/BLI_string.h85
-rw-r--r--source/blender/blenlib/BLI_string_cursor_utf8.h2
-rw-r--r--source/blender/blenlib/BLI_string_utf8.h10
-rw-r--r--source/blender/blenlib/BLI_utildefines.h68
-rw-r--r--source/blender/blenlib/BLI_vfontdata.h8
-rw-r--r--source/blender/blenlib/BLI_winstuff.h9
-rw-r--r--source/blender/blenlib/CMakeLists.txt15
-rw-r--r--source/blender/blenlib/SConscript32
-rw-r--r--source/blender/blenlib/intern/BLI_array.c97
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c64
-rw-r--r--source/blender/blenlib/intern/BLI_heap.c7
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c4
-rw-r--r--source/blender/blenlib/intern/BLI_linklist.c12
-rw-r--r--source/blender/blenlib/intern/BLI_memarena.c2
-rw-r--r--source/blender/blenlib/intern/BLI_mempool.c75
-rw-r--r--source/blender/blenlib/intern/buffer.c82
-rw-r--r--source/blender/blenlib/intern/endian_switch.c2
-rw-r--r--source/blender/blenlib/intern/fileops.c301
-rw-r--r--source/blender/blenlib/intern/freetypefont.c15
-rw-r--r--source/blender/blenlib/intern/gsqueue.c50
-rw-r--r--source/blender/blenlib/intern/jitter.c2
-rw-r--r--source/blender/blenlib/intern/lasso.c65
-rw-r--r--source/blender/blenlib/intern/listbase.c142
-rw-r--r--source/blender/blenlib/intern/math_base.c7
-rw-r--r--source/blender/blenlib/intern/math_base_inline.c36
-rw-r--r--source/blender/blenlib/intern/math_color.c4
-rw-r--r--source/blender/blenlib/intern/math_color_inline.c96
-rw-r--r--source/blender/blenlib/intern/math_geom.c533
-rw-r--r--source/blender/blenlib/intern/math_geom_inline.c27
-rw-r--r--source/blender/blenlib/intern/math_matrix.c101
-rw-r--r--source/blender/blenlib/intern/math_rotation.c167
-rw-r--r--source/blender/blenlib/intern/math_vector.c58
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c16
-rw-r--r--source/blender/blenlib/intern/noise.c28
-rw-r--r--source/blender/blenlib/intern/path_util.c792
-rw-r--r--source/blender/blenlib/intern/rct.c173
-rw-r--r--source/blender/blenlib/intern/scanfill.c271
-rw-r--r--source/blender/blenlib/intern/storage.c272
-rw-r--r--source/blender/blenlib/intern/string.c172
-rw-r--r--source/blender/blenlib/intern/string_cursor_utf8.c16
-rw-r--r--source/blender/blenlib/intern/string_utf8.c69
-rw-r--r--source/blender/blenlib/intern/threads.c14
-rw-r--r--source/blender/blenlib/intern/voronoi.c2
-rw-r--r--source/blender/blenlib/intern/winstuff.c7
-rw-r--r--source/blender/blenloader/BLO_readfile.h27
-rw-r--r--source/blender/blenloader/CMakeLists.txt1
-rw-r--r--source/blender/blenloader/SConscript28
-rw-r--r--source/blender/blenloader/intern/readblenentry.c12
-rw-r--r--source/blender/blenloader/intern/readfile.c2213
-rw-r--r--source/blender/blenloader/intern/readfile.h11
-rw-r--r--source/blender/blenloader/intern/runtime.c5
-rw-r--r--source/blender/blenloader/intern/versioning_250.c182
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c26
-rw-r--r--source/blender/blenloader/intern/writefile.c564
-rw-r--r--source/blender/bmesh/CMakeLists.txt17
-rw-r--r--source/blender/bmesh/SConscript49
-rw-r--r--source/blender/bmesh/bmesh.h5
-rw-r--r--source/blender/bmesh/bmesh_class.h26
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c114
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c541
-rw-r--r--source/blender/bmesh/intern/bmesh_core.h25
-rw-r--r--source/blender/bmesh/intern/bmesh_error.h6
-rw-r--r--source/blender/bmesh/intern/bmesh_inline.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.c60
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.c8
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators_inline.h78
-rw-r--r--source/blender/bmesh/intern/bmesh_log.c984
-rw-r--r--source/blender/bmesh/intern/bmesh_log.h102
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c311
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.h36
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c190
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.c221
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.h8
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_validate.c10
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_validate.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c292
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.h28
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c42
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api.h20
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api_inline.h14
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c313
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.h10
-rw-r--r--source/blender/bmesh/intern/bmesh_operators_private.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c411
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.h16
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c474
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.h59
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.c78
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.h16
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers.h7
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers_impl.c81
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers_private.h6
-rw-r--r--source/blender/bmesh/operators/bmo_bevel.c5
-rw-r--r--source/blender/bmesh/operators/bmo_connect.c69
-rw-r--r--source/blender/bmesh/operators/bmo_create.c54
-rw-r--r--source/blender/bmesh/operators/bmo_dissolve.c126
-rw-r--r--source/blender/bmesh/operators/bmo_dupe.c10
-rw-r--r--source/blender/bmesh/operators/bmo_edgesplit.c136
-rw-r--r--source/blender/bmesh/operators/bmo_extrude.c91
-rw-r--r--source/blender/bmesh/operators/bmo_hull.c39
-rw-r--r--source/blender/bmesh/operators/bmo_inset.c32
-rw-r--r--source/blender/bmesh/operators/bmo_join_triangles.c29
-rw-r--r--source/blender/bmesh/operators/bmo_mesh_conv.c16
-rw-r--r--source/blender/bmesh/operators/bmo_mirror.c10
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c44
-rw-r--r--source/blender/bmesh/operators/bmo_removedoubles.c25
-rw-r--r--source/blender/bmesh/operators/bmo_similar.c82
-rw-r--r--source/blender/bmesh/operators/bmo_slide.c113
-rw-r--r--source/blender/bmesh/operators/bmo_smooth_laplacian.c61
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide.c251
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide.h72
-rw-r--r--source/blender/bmesh/operators/bmo_symmetrize.c37
-rw-r--r--source/blender/bmesh/operators/bmo_triangulate.c66
-rw-r--r--source/blender/bmesh/operators/bmo_unsubdivide.c2
-rw-r--r--source/blender/bmesh/operators/bmo_utils.c44
-rw-r--r--source/blender/bmesh/operators/bmo_wireframe.c38
-rw-r--r--source/blender/bmesh/tools/BME_bevel.c42
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c827
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.h6
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate.h8
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_collapse.c110
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_dissolve.c26
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c48
-rw-r--r--source/blender/bmesh/tools/bmesh_edgesplit.c170
-rw-r--r--source/blender/bmesh/tools/bmesh_edgesplit.h32
-rw-r--r--source/blender/bmesh/tools/bmesh_triangulate.c87
-rw-r--r--source/blender/bmesh/tools/bmesh_triangulate.h36
-rw-r--r--source/blender/collada/AnimationExporter.cpp306
-rw-r--r--source/blender/collada/AnimationExporter.h35
-rw-r--r--source/blender/collada/AnimationImporter.cpp15
-rw-r--r--source/blender/collada/ArmatureExporter.cpp443
-rw-r--r--source/blender/collada/ArmatureExporter.h31
-rw-r--r--source/blender/collada/ArmatureImporter.cpp279
-rw-r--r--source/blender/collada/ArmatureImporter.h17
-rw-r--r--source/blender/collada/CMakeLists.txt7
-rw-r--r--source/blender/collada/CameraExporter.cpp3
-rw-r--r--source/blender/collada/ControllerExporter.cpp609
-rw-r--r--source/blender/collada/ControllerExporter.h127
-rw-r--r--source/blender/collada/DocumentExporter.cpp23
-rw-r--r--source/blender/collada/DocumentImporter.cpp252
-rw-r--r--source/blender/collada/DocumentImporter.h15
-rw-r--r--source/blender/collada/EffectExporter.cpp6
-rw-r--r--source/blender/collada/ExportSettings.h4
-rw-r--r--source/blender/collada/ExtraHandler.cpp3
-rw-r--r--source/blender/collada/ExtraHandler.h1
-rw-r--r--source/blender/collada/GeometryExporter.cpp328
-rw-r--r--source/blender/collada/GeometryExporter.h17
-rw-r--r--source/blender/collada/ImageExporter.cpp2
-rw-r--r--source/blender/collada/ImportSettings.cpp (renamed from intern/cycles/util/util_attribute.h)22
-rw-r--r--source/blender/collada/ImportSettings.h39
-rw-r--r--source/blender/collada/MaterialExporter.h2
-rw-r--r--source/blender/collada/MeshImporter.cpp606
-rw-r--r--source/blender/collada/MeshImporter.h57
-rw-r--r--source/blender/collada/SConscript7
-rw-r--r--source/blender/collada/SceneExporter.cpp57
-rw-r--r--source/blender/collada/SceneExporter.h4
-rw-r--r--source/blender/collada/SkinInfo.cpp5
-rw-r--r--source/blender/collada/TransformReader.cpp9
-rw-r--r--source/blender/collada/TransformWriter.cpp40
-rw-r--r--source/blender/collada/TransformWriter.h3
-rw-r--r--source/blender/collada/collada.cpp28
-rw-r--r--source/blender/collada/collada.h23
-rw-r--r--source/blender/collada/collada_internal.cpp40
-rw-r--r--source/blender/collada/collada_internal.h16
-rw-r--r--source/blender/collada/collada_utils.cpp145
-rw-r--r--source/blender/collada/collada_utils.h29
-rw-r--r--source/blender/compositor/CMakeLists.txt14
-rw-r--r--source/blender/compositor/COM_compositor.h4
-rw-r--r--source/blender/compositor/SConscript30
-rw-r--r--source/blender/compositor/intern/COM_CompositorContext.cpp1
-rw-r--r--source/blender/compositor/intern/COM_CompositorContext.h22
-rw-r--r--source/blender/compositor/intern/COM_Converter.cpp6
-rw-r--r--source/blender/compositor/intern/COM_ExecutionGroup.cpp103
-rw-r--r--source/blender/compositor/intern/COM_ExecutionGroup.h26
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.cpp28
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.h28
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp66
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystemHelper.h2
-rw-r--r--source/blender/compositor/intern/COM_InputSocket.cpp21
-rw-r--r--source/blender/compositor/intern/COM_InputSocket.h1
-rw-r--r--source/blender/compositor/intern/COM_Node.cpp33
-rw-r--r--source/blender/compositor/intern/COM_Node.h12
-rw-r--r--source/blender/compositor/intern/COM_NodeBase.h20
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.cpp1
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.h11
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.cpp8
-rw-r--r--source/blender/compositor/intern/COM_Socket.cpp25
-rw-r--r--source/blender/compositor/intern/COM_Socket.h5
-rw-r--r--source/blender/compositor/intern/COM_compositor.cpp12
-rw-r--r--source/blender/compositor/nodes/COM_BlurNode.cpp3
-rw-r--r--source/blender/compositor/nodes/COM_BokehBlurNode.cpp6
-rw-r--r--source/blender/compositor/nodes/COM_ColorCurveNode.cpp9
-rw-r--r--source/blender/compositor/nodes/COM_ColorNode.cpp9
-rw-r--r--source/blender/compositor/nodes/COM_CompositorNode.cpp5
-rw-r--r--source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp8
-rw-r--r--source/blender/compositor/nodes/COM_GroupNode.cpp88
-rw-r--r--source/blender/compositor/nodes/COM_ImageNode.cpp56
-rw-r--r--source/blender/compositor/nodes/COM_LensDistortionNode.cpp4
-rw-r--r--source/blender/compositor/nodes/COM_MixNode.cpp10
-rw-r--r--source/blender/compositor/nodes/COM_MovieClipNode.cpp21
-rw-r--r--source/blender/compositor/nodes/COM_NormalNode.cpp6
-rw-r--r--source/blender/compositor/nodes/COM_PixelateNode.cpp4
-rw-r--r--source/blender/compositor/nodes/COM_RenderLayersNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ScaleNode.cpp22
-rw-r--r--source/blender/compositor/nodes/COM_SetAlphaNode.cpp6
-rw-r--r--source/blender/compositor/nodes/COM_SocketProxyNode.cpp90
-rw-r--r--source/blender/compositor/nodes/COM_SocketProxyNode.h4
-rw-r--r--source/blender/compositor/nodes/COM_SplitViewerNode.cpp12
-rw-r--r--source/blender/compositor/nodes/COM_TranslateNode.cpp27
-rw-r--r--source/blender/compositor/nodes/COM_ValueNode.cpp7
-rw-r--r--source/blender/compositor/nodes/COM_ViewerNode.cpp10
-rw-r--r--source/blender/compositor/operations/COM_ChannelMatteOperation.cpp15
-rw-r--r--source/blender/compositor/operations/COM_CompositorOperation.cpp71
-rw-r--r--source/blender/compositor/operations/COM_CompositorOperation.h16
-rw-r--r--source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.cpp (renamed from source/blender/compositor/operations/COM_ConvertPremulToKeyOperation.cpp)10
-rw-r--r--source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.h (renamed from source/blender/compositor/operations/COM_ConvertPremulToKeyOperation.h)8
-rw-r--r--source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.cpp (renamed from source/blender/compositor/operations/COM_ConvertKeyToPremulOperation.cpp)10
-rw-r--r--source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.h (renamed from source/blender/compositor/operations/COM_ConvertKeyToPremulOperation.h)8
-rw-r--r--source/blender/compositor/operations/COM_CropOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_DilateErodeOperation.cpp292
-rw-r--r--source/blender/compositor/operations/COM_DilateErodeOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp26
-rw-r--r--source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_InpaintOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_MixBaseOperation.cpp26
-rw-r--r--source/blender/compositor/operations/COM_MixBaseOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_MovieClipOperation.cpp30
-rw-r--r--source/blender/compositor/operations/COM_MovieClipOperation.h19
-rw-r--r--source/blender/compositor/operations/COM_MovieDistortionOperation.cpp32
-rw-r--r--source/blender/compositor/operations/COM_MovieDistortionOperation.h3
-rw-r--r--source/blender/compositor/operations/COM_OpenCLKernels.cl5
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_PreviewOperation.cpp35
-rw-r--r--source/blender/compositor/operations/COM_PreviewOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp24
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersBaseProg.h8
-rw-r--r--source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp10
-rw-r--r--source/blender/compositor/operations/COM_TextureOperation.cpp37
-rw-r--r--source/blender/compositor/operations/COM_TextureOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_TrackPositionOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_TranslateOperation.cpp32
-rw-r--r--source/blender/compositor/operations/COM_TranslateOperation.h8
-rw-r--r--source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_ViewerBaseOperation.cpp1
-rw-r--r--source/blender/compositor/operations/COM_ViewerBaseOperation.h5
-rw-r--r--source/blender/compositor/operations/COM_ViewerOperation.cpp11
-rw-r--r--source/blender/compositor/operations/COM_WrapOperation.cpp117
-rw-r--r--source/blender/compositor/operations/COM_WrapOperation.h47
-rw-r--r--source/blender/datatoc/datatoc.c4
-rw-r--r--source/blender/editors/SConscript28
-rw-r--r--source/blender/editors/animation/SConscript28
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c176
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c278
-rw-r--r--source/blender/editors/animation/anim_draw.c26
-rw-r--r--source/blender/editors/animation/anim_filter.c126
-rw-r--r--source/blender/editors/animation/anim_ipo_utils.c14
-rw-r--r--source/blender/editors/animation/anim_markers.c128
-rw-r--r--source/blender/editors/animation/anim_ops.c36
-rw-r--r--source/blender/editors/animation/drivers.c4
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c97
-rw-r--r--source/blender/editors/animation/keyframes_draw.c6
-rw-r--r--source/blender/editors/animation/keyframes_edit.c9
-rw-r--r--source/blender/editors/animation/keyframing.c244
-rw-r--r--source/blender/editors/animation/keyingsets.c11
-rw-r--r--source/blender/editors/armature/CMakeLists.txt19
-rw-r--r--source/blender/editors/armature/SConscript28
-rw-r--r--source/blender/editors/armature/armature_add.c849
-rw-r--r--source/blender/editors/armature/armature_edit.c1245
-rw-r--r--source/blender/editors/armature/armature_intern.h38
-rw-r--r--source/blender/editors/armature/armature_naming.c372
-rw-r--r--source/blender/editors/armature/armature_ops.c8
-rw-r--r--source/blender/editors/armature/armature_relations.c774
-rw-r--r--source/blender/editors/armature/armature_select.c946
-rw-r--r--source/blender/editors/armature/armature_skinning.c441
-rw-r--r--source/blender/editors/armature/armature_utils.c680
-rw-r--r--source/blender/editors/armature/editarmature.c6163
-rw-r--r--source/blender/editors/armature/editarmature_generate.c17
-rw-r--r--source/blender/editors/armature/editarmature_retarget.c31
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c52
-rw-r--r--source/blender/editors/armature/meshlaplacian.c18
-rw-r--r--source/blender/editors/armature/pose_edit.c1180
-rw-r--r--source/blender/editors/armature/pose_group.c523
-rw-r--r--source/blender/editors/armature/pose_lib.c (renamed from source/blender/editors/armature/poselib.c)32
-rw-r--r--source/blender/editors/armature/pose_select.c853
-rw-r--r--source/blender/editors/armature/pose_slide.c (renamed from source/blender/editors/armature/poseSlide.c)26
-rw-r--r--source/blender/editors/armature/pose_transform.c879
-rw-r--r--source/blender/editors/armature/pose_utils.c (renamed from source/blender/editors/armature/poseUtils.c)13
-rw-r--r--source/blender/editors/armature/poseobject.c2364
-rw-r--r--source/blender/editors/armature/reeb.c21
-rw-r--r--source/blender/editors/curve/CMakeLists.txt5
-rw-r--r--source/blender/editors/curve/SConscript37
-rw-r--r--source/blender/editors/curve/editcurve.c510
-rw-r--r--source/blender/editors/curve/editfont.c41
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt31
-rw-r--r--source/blender/editors/datafiles/SConscript140
-rw-r--r--source/blender/editors/gpencil/SConscript28
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c5
-rw-r--r--source/blender/editors/gpencil/gpencil_buttons.c46
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c84
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c45
-rw-r--r--source/blender/editors/include/BIF_gl.h8
-rw-r--r--source/blender/editors/include/BIF_glutil.h22
-rw-r--r--source/blender/editors/include/ED_anim_api.h38
-rw-r--r--source/blender/editors/include/ED_armature.h9
-rw-r--r--source/blender/editors/include/ED_curve.h5
-rw-r--r--source/blender/editors/include/ED_datafiles.h88
-rw-r--r--source/blender/editors/include/ED_fileselect.h7
-rw-r--r--source/blender/editors/include/ED_gpencil.h3
-rw-r--r--source/blender/editors/include/ED_image.h2
-rw-r--r--source/blender/editors/include/ED_mball.h6
-rw-r--r--source/blender/editors/include/ED_mesh.h77
-rw-r--r--source/blender/editors/include/ED_node.h35
-rw-r--r--source/blender/editors/include/ED_numinput.h2
-rw-r--r--source/blender/editors/include/ED_object.h16
-rw-r--r--source/blender/editors/include/ED_particle.h6
-rw-r--r--source/blender/editors/include/ED_physics.h13
-rw-r--r--source/blender/editors/include/ED_screen.h5
-rw-r--r--source/blender/editors/include/ED_sequencer.h4
-rw-r--r--source/blender/editors/include/ED_space_api.h2
-rw-r--r--source/blender/editors/include/ED_transform.h21
-rw-r--r--source/blender/editors/include/ED_view3d.h123
-rw-r--r--source/blender/editors/include/UI_icons.h40
-rw-r--r--source/blender/editors/include/UI_interface.h56
-rw-r--r--source/blender/editors/include/UI_interface_icons.h6
-rw-r--r--source/blender/editors/include/UI_resources.h31
-rw-r--r--source/blender/editors/include/UI_view2d.h30
-rw-r--r--source/blender/editors/interface/SConscript28
-rw-r--r--source/blender/editors/interface/interface.c342
-rw-r--r--source/blender/editors/interface/interface_anim.c27
-rw-r--r--source/blender/editors/interface/interface_draw.c120
-rw-r--r--source/blender/editors/interface/interface_handlers.c1072
-rw-r--r--source/blender/editors/interface/interface_icons.c321
-rw-r--r--source/blender/editors/interface/interface_intern.h49
-rw-r--r--source/blender/editors/interface/interface_layout.c112
-rw-r--r--source/blender/editors/interface/interface_ops.c12
-rw-r--r--source/blender/editors/interface/interface_panel.c190
-rw-r--r--source/blender/editors/interface/interface_regions.c247
-rw-r--r--source/blender/editors/interface/interface_style.c68
-rw-r--r--source/blender/editors/interface/interface_templates.c875
-rw-r--r--source/blender/editors/interface/interface_utils.c4
-rw-r--r--source/blender/editors/interface/interface_widgets.c435
-rw-r--r--source/blender/editors/interface/resources.c231
-rw-r--r--source/blender/editors/interface/view2d.c540
-rw-r--r--source/blender/editors/interface/view2d_ops.c76
-rw-r--r--source/blender/editors/io/CMakeLists.txt4
-rw-r--r--source/blender/editors/io/SConscript30
-rw-r--r--source/blender/editors/io/io_collada.c98
-rw-r--r--source/blender/editors/io/io_ops.c2
-rw-r--r--source/blender/editors/mask/SConscript28
-rw-r--r--source/blender/editors/mask/mask_add.c6
-rw-r--r--source/blender/editors/mask/mask_draw.c2
-rw-r--r--source/blender/editors/mask/mask_edit.c20
-rw-r--r--source/blender/editors/mask/mask_ops.c10
-rw-r--r--source/blender/editors/mask/mask_relationships.c5
-rw-r--r--source/blender/editors/mask/mask_select.c12
-rw-r--r--source/blender/editors/mesh/CMakeLists.txt7
-rw-r--r--source/blender/editors/mesh/SConscript31
-rw-r--r--source/blender/editors/mesh/editface.c136
-rw-r--r--source/blender/editors/mesh/editmesh_add.c55
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c726
-rw-r--r--source/blender/editors/mesh/editmesh_knife_project.c174
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c163
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c92
-rw-r--r--source/blender/editors/mesh/editmesh_select.c594
-rw-r--r--source/blender/editors/mesh/editmesh_slide.c793
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c1348
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c315
-rw-r--r--source/blender/editors/mesh/mesh_data.c204
-rw-r--r--source/blender/editors/mesh/mesh_intern.h30
-rw-r--r--source/blender/editors/mesh/mesh_navmesh.c91
-rw-r--r--source/blender/editors/mesh/mesh_ops.c100
-rw-r--r--source/blender/editors/mesh/meshtools.c196
-rw-r--r--source/blender/editors/metaball/SConscript28
-rw-r--r--source/blender/editors/metaball/mball_edit.c32
-rw-r--r--source/blender/editors/metaball/mball_ops.c7
-rw-r--r--source/blender/editors/object/CMakeLists.txt5
-rw-r--r--source/blender/editors/object/SConscript33
-rw-r--r--source/blender/editors/object/object_add.c228
-rw-r--r--source/blender/editors/object/object_bake.c939
-rw-r--r--source/blender/editors/object/object_constraint.c235
-rw-r--r--source/blender/editors/object/object_edit.c119
-rw-r--r--source/blender/editors/object/object_group.c17
-rw-r--r--source/blender/editors/object/object_hook.c77
-rw-r--r--source/blender/editors/object/object_intern.h10
-rw-r--r--source/blender/editors/object/object_lattice.c69
-rw-r--r--source/blender/editors/object/object_modifier.c69
-rw-r--r--source/blender/editors/object/object_ops.c23
-rw-r--r--source/blender/editors/object/object_relations.c161
-rw-r--r--source/blender/editors/object/object_select.c70
-rw-r--r--source/blender/editors/object/object_transform.c59
-rw-r--r--source/blender/editors/object/object_vgroup.c231
-rw-r--r--source/blender/editors/physics/CMakeLists.txt10
-rw-r--r--source/blender/editors/physics/SConscript29
-rw-r--r--source/blender/editors/physics/dynamicpaint_ops.c16
-rw-r--r--source/blender/editors/physics/particle_boids.c14
-rw-r--r--source/blender/editors/physics/particle_edit.c128
-rw-r--r--source/blender/editors/physics/particle_object.c36
-rw-r--r--source/blender/editors/physics/physics_fluid.c27
-rw-r--r--source/blender/editors/physics/physics_intern.h20
-rw-r--r--source/blender/editors/physics/physics_ops.c20
-rw-r--r--source/blender/editors/physics/physics_pointcache.c26
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c199
-rw-r--r--source/blender/editors/physics/rigidbody_object.c625
-rw-r--r--source/blender/editors/physics/rigidbody_world.c210
-rw-r--r--source/blender/editors/render/CMakeLists.txt7
-rw-r--r--source/blender/editors/render/SConscript33
-rw-r--r--source/blender/editors/render/render_intern.h19
-rw-r--r--source/blender/editors/render/render_internal.c49
-rw-r--r--source/blender/editors/render/render_opengl.c28
-rw-r--r--source/blender/editors/render/render_ops.c25
-rw-r--r--source/blender/editors/render/render_preview.c317
-rw-r--r--source/blender/editors/render/render_shading.c642
-rw-r--r--source/blender/editors/render/render_update.c82
-rw-r--r--source/blender/editors/render/render_view.c15
-rw-r--r--source/blender/editors/screen/SConscript28
-rw-r--r--source/blender/editors/screen/area.c548
-rw-r--r--source/blender/editors/screen/glutil.c63
-rw-r--r--source/blender/editors/screen/screen_edit.c89
-rw-r--r--source/blender/editors/screen/screen_intern.h13
-rw-r--r--source/blender/editors/screen/screen_ops.c277
-rw-r--r--source/blender/editors/screen/screendump.c40
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt7
-rw-r--r--source/blender/editors/sculpt_paint/SConscript33
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c117
-rw-r--r--source/blender/editors/sculpt_paint/paint_hide.c104
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c5387
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c824
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c4465
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h57
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c20
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c61
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c296
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c62
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c759
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c1332
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h31
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c291
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c73
-rw-r--r--source/blender/editors/sound/SConscript28
-rw-r--r--source/blender/editors/sound/sound_ops.c14
-rw-r--r--source/blender/editors/space_action/SConscript28
-rw-r--r--source/blender/editors/space_action/action_draw.c16
-rw-r--r--source/blender/editors/space_action/action_edit.c7
-rw-r--r--source/blender/editors/space_action/action_intern.h16
-rw-r--r--source/blender/editors/space_action/action_select.c45
-rw-r--r--source/blender/editors/space_action/space_action.c9
-rw-r--r--source/blender/editors/space_api/SConscript28
-rw-r--r--source/blender/editors/space_buttons/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_buttons/SConscript31
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c10
-rw-r--r--source/blender/editors/space_buttons/buttons_header.c6
-rw-r--r--source/blender/editors/space_buttons/buttons_ops.c31
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c22
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c9
-rw-r--r--source/blender/editors/space_clip/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_clip/SConscript34
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c84
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_draw.c31
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_ops.c61
-rw-r--r--source/blender/editors/space_clip/clip_draw.c43
-rw-r--r--source/blender/editors/space_clip/clip_editor.c415
-rw-r--r--source/blender/editors/space_clip/clip_graph_ops.c2
-rw-r--r--source/blender/editors/space_clip/clip_intern.h16
-rw-r--r--source/blender/editors/space_clip/clip_ops.c288
-rw-r--r--source/blender/editors/space_clip/clip_toolbar.c41
-rw-r--r--source/blender/editors/space_clip/space_clip.c62
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c40
-rw-r--r--source/blender/editors/space_clip/tracking_select.c30
-rw-r--r--source/blender/editors/space_console/SConscript28
-rw-r--r--source/blender/editors/space_console/console_draw.c67
-rw-r--r--source/blender/editors/space_console/console_intern.h6
-rw-r--r--source/blender/editors/space_console/console_ops.c64
-rw-r--r--source/blender/editors/space_console/space_console.c6
-rw-r--r--source/blender/editors/space_file/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_file/SConscript31
-rw-r--r--source/blender/editors/space_file/file_draw.c49
-rw-r--r--source/blender/editors/space_file/file_ops.c46
-rw-r--r--source/blender/editors/space_file/file_panels.c8
-rw-r--r--source/blender/editors/space_file/filelist.c45
-rw-r--r--source/blender/editors/space_file/filelist.h15
-rw-r--r--source/blender/editors/space_file/filesel.c67
-rw-r--r--source/blender/editors/space_file/fsmenu.c30
-rw-r--r--source/blender/editors/space_file/fsmenu.h2
-rw-r--r--source/blender/editors/space_file/space_file.c36
-rw-r--r--source/blender/editors/space_graph/SConscript28
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c44
-rw-r--r--source/blender/editors/space_graph/graph_draw.c114
-rw-r--r--source/blender/editors/space_graph/graph_edit.c24
-rw-r--r--source/blender/editors/space_graph/graph_intern.h16
-rw-r--r--source/blender/editors/space_graph/graph_ops.c6
-rw-r--r--source/blender/editors/space_graph/graph_select.c9
-rw-r--r--source/blender/editors/space_graph/space_graph.c6
-rw-r--r--source/blender/editors/space_image/SConscript30
-rw-r--r--source/blender/editors/space_image/image_buttons.c102
-rw-r--r--source/blender/editors/space_image/image_draw.c198
-rw-r--r--source/blender/editors/space_image/image_edit.c11
-rw-r--r--source/blender/editors/space_image/image_intern.h2
-rw-r--r--source/blender/editors/space_image/image_ops.c112
-rw-r--r--source/blender/editors/space_image/space_image.c43
-rw-r--r--source/blender/editors/space_info/SConscript28
-rw-r--r--source/blender/editors/space_info/info_draw.c12
-rw-r--r--source/blender/editors/space_info/info_intern.h5
-rw-r--r--source/blender/editors/space_info/info_ops.c168
-rw-r--r--source/blender/editors/space_info/info_report.c11
-rw-r--r--source/blender/editors/space_info/info_stats.c119
-rw-r--r--source/blender/editors/space_info/space_info.c6
-rw-r--r--source/blender/editors/space_info/textview.c160
-rw-r--r--source/blender/editors/space_info/textview.h3
-rw-r--r--source/blender/editors/space_logic/SConscript28
-rw-r--r--source/blender/editors/space_logic/logic_buttons.c2
-rw-r--r--source/blender/editors/space_logic/logic_ops.c93
-rw-r--r--source/blender/editors/space_logic/logic_window.c44
-rw-r--r--source/blender/editors/space_logic/space_logic.c4
-rw-r--r--source/blender/editors/space_nla/SConscript28
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c66
-rw-r--r--source/blender/editors/space_nla/nla_channels.c186
-rw-r--r--source/blender/editors/space_nla/nla_draw.c46
-rw-r--r--source/blender/editors/space_nla/nla_edit.c23
-rw-r--r--source/blender/editors/space_nla/nla_intern.h12
-rw-r--r--source/blender/editors/space_nla/nla_ops.c8
-rw-r--r--source/blender/editors/space_nla/nla_select.c6
-rw-r--r--source/blender/editors/space_node/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_node/SConscript28
-rw-r--r--source/blender/editors/space_node/drawnode.c1175
-rw-r--r--source/blender/editors/space_node/node_add.c203
-rw-r--r--source/blender/editors/space_node/node_buttons.c90
-rw-r--r--source/blender/editors/space_node/node_draw.c683
-rw-r--r--source/blender/editors/space_node/node_edit.c865
-rw-r--r--source/blender/editors/space_node/node_group.c1307
-rw-r--r--source/blender/editors/space_node/node_header.c179
-rw-r--r--source/blender/editors/space_node/node_intern.h93
-rw-r--r--source/blender/editors/space_node/node_ops.c58
-rw-r--r--source/blender/editors/space_node/node_relationships.c227
-rw-r--r--source/blender/editors/space_node/node_select.c89
-rw-r--r--source/blender/editors/space_node/node_templates.c228
-rw-r--r--source/blender/editors/space_node/node_toolbar.c92
-rw-r--r--source/blender/editors/space_node/node_view.c47
-rw-r--r--source/blender/editors/space_node/space_node.c311
-rw-r--r--source/blender/editors/space_outliner/SConscript28
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c434
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c74
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h14
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c18
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c194
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c111
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c200
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c29
-rw-r--r--source/blender/editors/space_script/SConscript28
-rw-r--r--source/blender/editors/space_script/script_edit.c2
-rw-r--r--source/blender/editors/space_sequencer/SConscript28
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c88
-rw-r--r--source/blender/editors/space_sequencer/sequencer_buttons.c11
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c40
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c88
-rw-r--r--source/blender/editors/space_sequencer/sequencer_modifier.c4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c22
-rw-r--r--source/blender/editors/space_sequencer/sequencer_view.c16
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c8
-rw-r--r--source/blender/editors/space_text/CMakeLists.txt7
-rw-r--r--source/blender/editors/space_text/SConscript28
-rw-r--r--source/blender/editors/space_text/space_text.c39
-rw-r--r--source/blender/editors/space_text/text_autocomplete.c557
-rw-r--r--source/blender/editors/space_text/text_draw.c717
-rw-r--r--source/blender/editors/space_text/text_format.c227
-rw-r--r--source/blender/editors/space_text/text_format.h109
-rw-r--r--source/blender/editors/space_text/text_format_lua.c318
-rw-r--r--source/blender/editors/space_text/text_format_osl.c336
-rw-r--r--source/blender/editors/space_text/text_format_py.c325
-rw-r--r--source/blender/editors/space_text/text_header.c35
-rw-r--r--source/blender/editors/space_text/text_intern.h28
-rw-r--r--source/blender/editors/space_text/text_ops.c237
-rw-r--r--source/blender/editors/space_text/text_python.c361
-rw-r--r--source/blender/editors/space_time/SConscript28
-rw-r--r--source/blender/editors/space_time/space_time.c14
-rw-r--r--source/blender/editors/space_userpref/SConscript28
-rw-r--r--source/blender/editors/space_userpref/space_userpref.c8
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt5
-rw-r--r--source/blender/editors/space_view3d/SConscript31
-rw-r--r--source/blender/editors/space_view3d/drawanimviz.c33
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c47
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c112
-rw-r--r--source/blender/editors/space_view3d/drawobject.c683
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c73
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c166
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c203
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c699
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c688
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c193
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c58
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h28
-rw-r--r--source/blender/editors/space_view3d/view3d_iterators.c56
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c104
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c168
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c939
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c532
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c23
-rw-r--r--source/blender/editors/space_view3d/view3d_toolbar.c41
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c289
-rw-r--r--source/blender/editors/transform/SConscript28
-rw-r--r--source/blender/editors/transform/transform.c1487
-rw-r--r--source/blender/editors/transform/transform.h112
-rw-r--r--source/blender/editors/transform/transform_constraints.c55
-rw-r--r--source/blender/editors/transform/transform_conversions.c223
-rw-r--r--source/blender/editors/transform/transform_generics.c78
-rw-r--r--source/blender/editors/transform/transform_input.c44
-rw-r--r--source/blender/editors/transform/transform_manipulator.c442
-rw-r--r--source/blender/editors/transform/transform_ops.c100
-rw-r--r--source/blender/editors/transform/transform_orientations.c117
-rw-r--r--source/blender/editors/transform/transform_snap.c134
-rw-r--r--source/blender/editors/util/SConscript28
-rw-r--r--source/blender/editors/util/ed_util.c25
-rw-r--r--source/blender/editors/util/editmode_undo.c8
-rw-r--r--source/blender/editors/util/numinput.c2
-rw-r--r--source/blender/editors/util/undo.c51
-rw-r--r--source/blender/editors/uvedit/CMakeLists.txt5
-rw-r--r--source/blender/editors/uvedit/SConscript37
-rw-r--r--source/blender/editors/uvedit/uvedit_buttons.c10
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c220
-rw-r--r--source/blender/editors/uvedit/uvedit_intern.h8
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c408
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c56
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c1404
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c256
-rw-r--r--source/blender/freestyle/CMakeLists.txt45
-rw-r--r--source/blender/freestyle/FRS_freestyle.h74
-rw-r--r--source/blender/freestyle/SConscript75
-rw-r--r--source/blender/freestyle/intern/application/AppCanvas.cpp218
-rw-r--r--source/blender/freestyle/intern/application/AppCanvas.h101
-rw-r--r--source/blender/freestyle/intern/application/AppConfig.cpp104
-rw-r--r--source/blender/freestyle/intern/application/AppConfig.h108
-rw-r--r--source/blender/freestyle/intern/application/AppView.cpp198
-rw-r--r--source/blender/freestyle/intern/application/AppView.h238
-rw-r--r--source/blender/freestyle/intern/application/Controller.cpp1052
-rw-r--r--source/blender/freestyle/intern/application/Controller.h257
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp765
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h138
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp519
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h78
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h74
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderTextureManager.cpp104
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderTextureManager.h53
-rw-r--r--source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp732
-rw-r--r--source/blender/freestyle/intern/geometry/BBox.h154
-rw-r--r--source/blender/freestyle/intern/geometry/Bezier.cpp127
-rw-r--r--source/blender/freestyle/intern/geometry/Bezier.h96
-rw-r--r--source/blender/freestyle/intern/geometry/FastGrid.cpp87
-rw-r--r--source/blender/freestyle/intern/geometry/FastGrid.h86
-rw-r--r--source/blender/freestyle/intern/geometry/FitCurve.cpp600
-rw-r--r--source/blender/freestyle/intern/geometry/FitCurve.h125
-rw-r--r--source/blender/freestyle/intern/geometry/Geom.h84
-rw-r--r--source/blender/freestyle/intern/geometry/GeomCleaner.cpp240
-rw-r--r--source/blender/freestyle/intern/geometry/GeomCleaner.h227
-rw-r--r--source/blender/freestyle/intern/geometry/GeomUtils.cpp783
-rw-r--r--source/blender/freestyle/intern/geometry/GeomUtils.h277
-rw-r--r--source/blender/freestyle/intern/geometry/Grid.cpp391
-rw-r--r--source/blender/freestyle/intern/geometry/Grid.h384
-rw-r--r--source/blender/freestyle/intern/geometry/GridHelpers.cpp59
-rw-r--r--source/blender/freestyle/intern/geometry/GridHelpers.h215
-rw-r--r--source/blender/freestyle/intern/geometry/HashGrid.cpp53
-rw-r--r--source/blender/freestyle/intern/geometry/HashGrid.h116
-rw-r--r--source/blender/freestyle/intern/geometry/Noise.cpp285
-rw-r--r--source/blender/freestyle/intern/geometry/Noise.h83
-rw-r--r--source/blender/freestyle/intern/geometry/Polygon.h221
-rw-r--r--source/blender/freestyle/intern/geometry/SweepLine.h332
-rw-r--r--source/blender/freestyle/intern/geometry/VecMat.h977
-rw-r--r--source/blender/freestyle/intern/geometry/matrix_util.cpp266
-rw-r--r--source/blender/freestyle/intern/geometry/matrix_util.h72
-rw-r--r--source/blender/freestyle/intern/geometry/normal_cycle.cpp100
-rw-r--r--source/blender/freestyle/intern/geometry/normal_cycle.h144
-rw-r--r--source/blender/freestyle/intern/image/GaussianFilter.cpp112
-rw-r--r--source/blender/freestyle/intern/image/GaussianFilter.h162
-rw-r--r--source/blender/freestyle/intern/image/Image.h415
-rw-r--r--source/blender/freestyle/intern/image/ImagePyramid.cpp192
-rw-r--r--source/blender/freestyle/intern/image/ImagePyramid.h116
-rw-r--r--source/blender/freestyle/intern/python/BPy_BBox.cpp131
-rw-r--r--source/blender/freestyle/intern/python/BPy_BBox.h69
-rw-r--r--source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp193
-rw-r--r--source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h67
-rw-r--r--source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp223
-rw-r--r--source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h66
-rw-r--r--source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp287
-rw-r--r--source/blender/freestyle/intern/python/BPy_ContextFunctions.h (renamed from source/gameengine/Physics/common/PHY_IPhysicsEnvironment.cpp)26
-rw-r--r--source/blender/freestyle/intern/python/BPy_Convert.cpp723
-rw-r--r--source/blender/freestyle/intern/python/BPy_Convert.h183
-rw-r--r--source/blender/freestyle/intern/python/BPy_Freestyle.cpp544
-rw-r--r--source/blender/freestyle/intern/python/BPy_Freestyle.h53
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp462
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsMaterial.h67
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsNoise.cpp321
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsNoise.h67
-rw-r--r--source/blender/freestyle/intern/python/BPy_Id.cpp232
-rw-r--r--source/blender/freestyle/intern/python/BPy_Id.h67
-rw-r--r--source/blender/freestyle/intern/python/BPy_IntegrationType.cpp262
-rw-r--r--source/blender/freestyle/intern/python/BPy_IntegrationType.h59
-rw-r--r--source/blender/freestyle/intern/python/BPy_Interface0D.cpp325
-rw-r--r--source/blender/freestyle/intern/python/BPy_Interface0D.h66
-rw-r--r--source/blender/freestyle/intern/python/BPy_Interface1D.cpp357
-rw-r--r--source/blender/freestyle/intern/python/BPy_Interface1D.h67
-rw-r--r--source/blender/freestyle/intern/python/BPy_Iterator.cpp269
-rw-r--r--source/blender/freestyle/intern/python/BPy_Iterator.h66
-rw-r--r--source/blender/freestyle/intern/python/BPy_MediumType.cpp129
-rw-r--r--source/blender/freestyle/intern/python/BPy_MediumType.h73
-rw-r--r--source/blender/freestyle/intern/python/BPy_Nature.cpp337
-rw-r--r--source/blender/freestyle/intern/python/BPy_Nature.h64
-rw-r--r--source/blender/freestyle/intern/python/BPy_Operators.cpp743
-rw-r--r--source/blender/freestyle/intern/python/BPy_Operators.h65
-rw-r--r--source/blender/freestyle/intern/python/BPy_SShape.cpp324
-rw-r--r--source/blender/freestyle/intern/python/BPy_SShape.h66
-rw-r--r--source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp648
-rw-r--r--source/blender/freestyle/intern/python/BPy_StrokeAttribute.h67
-rw-r--r--source/blender/freestyle/intern/python/BPy_StrokeShader.cpp334
-rw-r--r--source/blender/freestyle/intern/python/BPy_StrokeShader.h71
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp172
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h65
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp166
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h65
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp209
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h65
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp257
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h65
-rw-r--r--source/blender/freestyle/intern/python/BPy_ViewMap.cpp225
-rw-r--r--source/blender/freestyle/intern/python/BPy_ViewMap.h65
-rw-r--r--source/blender/freestyle/intern/python/BPy_ViewShape.cpp371
-rw-r--r--source/blender/freestyle/intern/python/BPy_ViewShape.h69
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp112
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.h60
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp114
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.h60
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp113
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.h60
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp113
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.h60
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp139
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h61
-rw-r--r--source/blender/freestyle/intern/python/Director.cpp330
-rw-r--r--source/blender/freestyle/intern/python/Director.h80
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp278
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h62
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp482
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h67
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp211
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h62
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp388
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h66
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp158
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h62
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp254
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h62
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp385
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h62
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp240
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h62
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp478
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h62
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp389
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h63
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp207
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h62
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp440
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h66
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp288
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h66
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp196
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h63
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp227
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h67
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp165
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h65
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp272
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h64
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp185
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h63
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp211
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h64
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp205
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h64
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp202
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h64
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp265
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h64
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp169
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h66
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp122
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.h63
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp124
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.h62
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp146
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.h62
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp123
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.h62
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp129
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.h63
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp127
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.h62
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp121
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.h63
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp128
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h63
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp129
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.h62
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp138
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.h62
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp127
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.h63
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp128
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.h63
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp121
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.h62
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp147
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.h62
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp136
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.h62
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp150
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.h62
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp137
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.h62
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp123
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.h62
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp135
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h63
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp122
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.h62
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp121
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.h62
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp117
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.h62
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp225
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h65
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp170
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h68
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp199
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h65
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp169
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h67
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp169
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h68
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp169
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h66
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp175
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h68
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp169
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h68
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp186
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h69
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp175
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h68
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp125
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp129
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp120
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp122
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp122
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h62
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp122
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h62
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp119
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp119
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp122
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp128
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp119
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp119
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp119
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp119
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp119
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp119
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp124
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp124
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp120
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h62
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp119
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp125
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h62
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp123
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h62
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp126
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp127
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h62
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp125
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h62
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp120
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp292
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h65
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp215
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h68
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp207
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h65
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp214
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h66
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp220
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h68
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp214
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h68
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp244
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h69
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp227
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h65
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp130
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp125
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp125
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp125
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp125
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp139
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp140
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h62
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp146
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h62
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp125
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp125
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp125
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp138
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp137
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h63
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp125
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp124
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp125
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp133
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp129
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp129
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h62
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp119
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp119
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp119
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp117
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp118
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h62
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp117
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp111
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.h60
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp111
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.h60
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp112
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.h60
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp126
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.h60
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp120
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp120
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h60
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp114
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.h60
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp111
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.h60
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp123
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h61
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp123
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.h60
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp111
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.h60
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.cpp120
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.h61
-rw-r--r--source/blender/freestyle/intern/scene_graph/DrawingStyle.h128
-rw-r--r--source/blender/freestyle/intern/scene_graph/FrsMaterial.h379
-rw-r--r--source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp330
-rw-r--r--source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h322
-rw-r--r--source/blender/freestyle/intern/scene_graph/LineRep.cpp71
-rw-r--r--source/blender/freestyle/intern/scene_graph/LineRep.h158
-rw-r--r--source/blender/freestyle/intern/scene_graph/Node.h115
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeCamera.cpp143
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeCamera.h216
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.cpp46
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.h111
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeGroup.cpp126
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeGroup.h89
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeLight.cpp86
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeLight.h113
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeShape.cpp63
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeShape.h103
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeTransform.cpp178
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeTransform.h110
-rw-r--r--source/blender/freestyle/intern/scene_graph/OrientedLineRep.cpp46
-rw-r--r--source/blender/freestyle/intern/scene_graph/OrientedLineRep.h66
-rw-r--r--source/blender/freestyle/intern/scene_graph/Rep.cpp (renamed from source/gameengine/Physics/common/PHY_IMotionState.cpp)16
-rw-r--r--source/blender/freestyle/intern/scene_graph/Rep.h173
-rw-r--r--source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp110
-rw-r--r--source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.h109
-rw-r--r--source/blender/freestyle/intern/scene_graph/SceneVisitor.cpp (renamed from source/blender/blenloader/BLO_soundfile.h)20
-rw-r--r--source/blender/freestyle/intern/scene_graph/SceneVisitor.h102
-rw-r--r--source/blender/freestyle/intern/scene_graph/TriangleRep.cpp69
-rw-r--r--source/blender/freestyle/intern/scene_graph/TriangleRep.h150
-rw-r--r--source/blender/freestyle/intern/scene_graph/VertexRep.cpp41
-rw-r--r--source/blender/freestyle/intern/scene_graph/VertexRep.h141
-rw-r--r--source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp119
-rw-r--r--source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h229
-rw-r--r--source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp138
-rw-r--r--source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h298
-rw-r--r--source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h95
-rw-r--r--source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp404
-rw-r--r--source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h226
-rw-r--r--source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp1137
-rw-r--r--source/blender/freestyle/intern/stroke/BasicStrokeShaders.h902
-rw-r--r--source/blender/freestyle/intern/stroke/Canvas.cpp477
-rw-r--r--source/blender/freestyle/intern/stroke/Canvas.h249
-rw-r--r--source/blender/freestyle/intern/stroke/Chain.cpp156
-rw-r--r--source/blender/freestyle/intern/stroke/Chain.h116
-rw-r--r--source/blender/freestyle/intern/stroke/ChainingIterators.cpp202
-rw-r--r--source/blender/freestyle/intern/stroke/ChainingIterators.h407
-rw-r--r--source/blender/freestyle/intern/stroke/ContextFunctions.cpp87
-rw-r--r--source/blender/freestyle/intern/stroke/ContextFunctions.h120
-rw-r--r--source/blender/freestyle/intern/stroke/Curve.cpp932
-rw-r--r--source/blender/freestyle/intern/stroke/Curve.h589
-rw-r--r--source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h383
-rw-r--r--source/blender/freestyle/intern/stroke/CurveIterators.h302
-rw-r--r--source/blender/freestyle/intern/stroke/Modifiers.h74
-rw-r--r--source/blender/freestyle/intern/stroke/Module.h82
-rw-r--r--source/blender/freestyle/intern/stroke/Operators.cpp1281
-rw-r--r--source/blender/freestyle/intern/stroke/Operators.h274
-rw-r--r--source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp106
-rw-r--r--source/blender/freestyle/intern/stroke/PSStrokeRenderer.h69
-rw-r--r--source/blender/freestyle/intern/stroke/Predicates0D.h186
-rw-r--r--source/blender/freestyle/intern/stroke/Predicates1D.h588
-rw-r--r--source/blender/freestyle/intern/stroke/QInformationMap.h73
-rw-r--r--source/blender/freestyle/intern/stroke/Stroke.cpp954
-rw-r--r--source/blender/freestyle/intern/stroke/Stroke.h822
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h191
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeIO.cpp77
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeIO.h53
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeIterators.h229
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeLayer.cpp70
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeLayer.h106
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeRenderer.cpp138
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeRenderer.h145
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeRep.cpp789
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeRep.h217
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeShader.h107
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeTesselator.cpp94
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeTesselator.h78
-rw-r--r--source/blender/freestyle/intern/stroke/StyleModule.h186
-rw-r--r--source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp79
-rw-r--r--source/blender/freestyle/intern/stroke/TextStrokeRenderer.h68
-rw-r--r--source/blender/freestyle/intern/system/BaseIterator.h97
-rw-r--r--source/blender/freestyle/intern/system/BaseObject.cpp36
-rw-r--r--source/blender/freestyle/intern/system/BaseObject.h77
-rw-r--r--source/blender/freestyle/intern/system/Cast.h49
-rw-r--r--source/blender/freestyle/intern/system/Exception.cpp37
-rw-r--r--source/blender/freestyle/intern/system/Exception.h70
-rw-r--r--source/blender/freestyle/intern/system/FreestyleConfig.h96
-rw-r--r--source/blender/freestyle/intern/system/Id.h142
-rw-r--r--source/blender/freestyle/intern/system/Interpreter.h65
-rw-r--r--source/blender/freestyle/intern/system/Iterator.cpp (renamed from source/gameengine/Physics/common/PHY_IController.cpp)14
-rw-r--r--source/blender/freestyle/intern/system/Iterator.h75
-rw-r--r--source/blender/freestyle/intern/system/PointerSequence.h96
-rw-r--r--source/blender/freestyle/intern/system/Precision.h44
-rw-r--r--source/blender/freestyle/intern/system/ProgressBar.h96
-rw-r--r--source/blender/freestyle/intern/system/PseudoNoise.cpp116
-rw-r--r--source/blender/freestyle/intern/system/PseudoNoise.h60
-rw-r--r--source/blender/freestyle/intern/system/PythonInterpreter.cpp38
-rw-r--r--source/blender/freestyle/intern/system/PythonInterpreter.h198
-rw-r--r--source/blender/freestyle/intern/system/RandGen.cpp132
-rw-r--r--source/blender/freestyle/intern/system/RandGen.h54
-rw-r--r--source/blender/freestyle/intern/system/RenderMonitor.h63
-rw-r--r--source/blender/freestyle/intern/system/StringUtils.cpp89
-rw-r--r--source/blender/freestyle/intern/system/StringUtils.h75
-rw-r--r--source/blender/freestyle/intern/system/TimeStamp.cpp (renamed from source/gameengine/Physics/common/PHY_IGraphicController.cpp)18
-rw-r--r--source/blender/freestyle/intern/system/TimeStamp.h78
-rw-r--r--source/blender/freestyle/intern/system/TimeUtils.h64
-rw-r--r--source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp124
-rw-r--r--source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h75
-rw-r--r--source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp138
-rw-r--r--source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h72
-rw-r--r--source/blender/freestyle/intern/view_map/BoxGrid.cpp241
-rw-r--r--source/blender/freestyle/intern/view_map/BoxGrid.h417
-rw-r--r--source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp287
-rw-r--r--source/blender/freestyle/intern/view_map/CulledOccluderSource.h69
-rw-r--r--source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp762
-rw-r--r--source/blender/freestyle/intern/view_map/FEdgeXDetector.h241
-rw-r--r--source/blender/freestyle/intern/view_map/Functions0D.cpp376
-rw-r--r--source/blender/freestyle/intern/view_map/Functions0D.h532
-rw-r--r--source/blender/freestyle/intern/view_map/Functions1D.cpp271
-rw-r--r--source/blender/freestyle/intern/view_map/Functions1D.h627
-rw-r--r--source/blender/freestyle/intern/view_map/GridDensityProvider.h152
-rw-r--r--source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp84
-rw-r--r--source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h60
-rw-r--r--source/blender/freestyle/intern/view_map/Interface0D.h390
-rw-r--r--source/blender/freestyle/intern/view_map/Interface1D.h230
-rw-r--r--source/blender/freestyle/intern/view_map/OccluderSource.cpp151
-rw-r--r--source/blender/freestyle/intern/view_map/OccluderSource.h76
-rw-r--r--source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp123
-rw-r--r--source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h75
-rw-r--r--source/blender/freestyle/intern/view_map/Silhouette.cpp420
-rw-r--r--source/blender/freestyle/intern/view_map/Silhouette.h1876
-rw-r--r--source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp322
-rw-r--r--source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h136
-rw-r--r--source/blender/freestyle/intern/view_map/SphericalGrid.cpp249
-rw-r--r--source/blender/freestyle/intern/view_map/SphericalGrid.h423
-rw-r--r--source/blender/freestyle/intern/view_map/SteerableViewMap.cpp302
-rw-r--r--source/blender/freestyle/intern/view_map/SteerableViewMap.h154
-rw-r--r--source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp753
-rw-r--r--source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h288
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMap.cpp754
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMap.h1779
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h789
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp2391
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMapBuilder.h257
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMapIO.cpp1258
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMapIO.h129
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMapIterators.h574
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp49
-rw-r--r--source/blender/freestyle/intern/view_map/ViewMapTesselator.h211
-rw-r--r--source/blender/freestyle/intern/winged_edge/Curvature.cpp642
-rw-r--r--source/blender/freestyle/intern/winged_edge/Curvature.h143
-rw-r--r--source/blender/freestyle/intern/winged_edge/Nature.h79
-rw-r--r--source/blender/freestyle/intern/winged_edge/WEdge.cpp714
-rw-r--r--source/blender/freestyle/intern/winged_edge/WEdge.h1344
-rw-r--r--source/blender/freestyle/intern/winged_edge/WFillGrid.cpp68
-rw-r--r--source/blender/freestyle/intern/winged_edge/WFillGrid.h88
-rw-r--r--source/blender/freestyle/intern/winged_edge/WSFillGrid.cpp67
-rw-r--r--source/blender/freestyle/intern/winged_edge/WSFillGrid.h87
-rw-r--r--source/blender/freestyle/intern/winged_edge/WXEdge.cpp301
-rw-r--r--source/blender/freestyle/intern/winged_edge/WXEdge.h809
-rw-r--r--source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp58
-rw-r--r--source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h54
-rw-r--r--source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp373
-rw-r--r--source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h157
-rw-r--r--source/blender/gpu/CMakeLists.txt7
-rw-r--r--source/blender/gpu/GPU_buffers.h14
-rw-r--r--source/blender/gpu/GPU_draw.h4
-rw-r--r--source/blender/gpu/GPU_extensions.h15
-rw-r--r--source/blender/gpu/GPU_material.h4
-rw-r--r--source/blender/gpu/GPU_simple_shader.h89
-rw-r--r--source/blender/gpu/SConscript48
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c270
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c60
-rw-r--r--source/blender/gpu/intern/gpu_codegen.h2
-rw-r--r--source/blender/gpu/intern/gpu_draw.c210
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c141
-rw-r--r--source/blender/gpu/intern/gpu_material.c61
-rw-r--r--source/blender/gpu/intern/gpu_simple_shader.c283
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl41
-rw-r--r--source/blender/gpu/shaders/gpu_shader_simple_frag.glsl169
-rw-r--r--source/blender/gpu/shaders/gpu_shader_simple_vert.glsl46
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vertex.glsl12
-rw-r--r--source/blender/ikplugin/SConscript28
-rw-r--r--source/blender/ikplugin/intern/iksolver_plugin.c8
-rw-r--r--source/blender/ikplugin/intern/itasc_plugin.cpp67
-rw-r--r--source/blender/imbuf/IMB_colormanagement.h5
-rw-r--r--source/blender/imbuf/IMB_imbuf.h15
-rw-r--r--source/blender/imbuf/IMB_imbuf_types.h16
-rw-r--r--source/blender/imbuf/IMB_moviecache.h2
-rw-r--r--source/blender/imbuf/IMB_thumbs.h2
-rw-r--r--source/blender/imbuf/SConscript34
-rw-r--r--source/blender/imbuf/intern/IMB_colormanagement_intern.h13
-rw-r--r--source/blender/imbuf/intern/IMB_filter.h3
-rw-r--r--source/blender/imbuf/intern/IMB_indexer.h3
-rw-r--r--source/blender/imbuf/intern/IMB_metadata.h2
-rw-r--r--source/blender/imbuf/intern/allocimbuf.c2
-rw-r--r--source/blender/imbuf/intern/anim_movie.c14
-rw-r--r--source/blender/imbuf/intern/bmp.c12
-rw-r--r--source/blender/imbuf/intern/cineon/SConscript28
-rw-r--r--source/blender/imbuf/intern/cineon/cineon_dpx.c44
-rw-r--r--source/blender/imbuf/intern/cineon/cineonlib.c55
-rw-r--r--source/blender/imbuf/intern/cineon/dpxlib.c74
-rw-r--r--source/blender/imbuf/intern/cineon/logImageCore.c42
-rw-r--r--source/blender/imbuf/intern/colormanagement.c298
-rw-r--r--source/blender/imbuf/intern/dds/BlockDXT.cpp4
-rw-r--r--source/blender/imbuf/intern/dds/ColorBlock.h2
-rw-r--r--source/blender/imbuf/intern/dds/DirectDrawSurface.cpp8
-rw-r--r--source/blender/imbuf/intern/dds/DirectDrawSurface.h2
-rw-r--r--source/blender/imbuf/intern/dds/FlipDXT.cpp8
-rw-r--r--source/blender/imbuf/intern/dds/SConscript28
-rw-r--r--source/blender/imbuf/intern/dds/Stream.cpp10
-rw-r--r--source/blender/imbuf/intern/dds/dds_api.cpp10
-rw-r--r--source/blender/imbuf/intern/divers.c122
-rw-r--r--source/blender/imbuf/intern/filetype.c5
-rw-r--r--source/blender/imbuf/intern/filter.c68
-rw-r--r--source/blender/imbuf/intern/imageprocess.c54
-rw-r--r--source/blender/imbuf/intern/indexer.c35
-rw-r--r--source/blender/imbuf/intern/iris.c3
-rw-r--r--source/blender/imbuf/intern/jp2.c227
-rw-r--r--source/blender/imbuf/intern/jpeg.c7
-rw-r--r--source/blender/imbuf/intern/moviecache.c52
-rw-r--r--source/blender/imbuf/intern/openexr/SConscript28
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp39
-rw-r--r--source/blender/imbuf/intern/png.c229
-rw-r--r--source/blender/imbuf/intern/radiance_hdr.c8
-rw-r--r--source/blender/imbuf/intern/readimage.c38
-rw-r--r--source/blender/imbuf/intern/rectop.c104
-rw-r--r--source/blender/imbuf/intern/scaling.c177
-rw-r--r--source/blender/imbuf/intern/targa.c95
-rw-r--r--source/blender/imbuf/intern/thumbs.c7
-rw-r--r--source/blender/imbuf/intern/tiff.c52
-rw-r--r--source/blender/imbuf/intern/util.c8
-rw-r--r--source/blender/makesdna/CMakeLists.txt4
-rw-r--r--source/blender/makesdna/DNA_ID.h13
-rw-r--r--source/blender/makesdna/DNA_action_types.h7
-rw-r--r--source/blender/makesdna/DNA_actuator_types.h13
-rw-r--r--source/blender/makesdna/DNA_anim_types.h11
-rw-r--r--source/blender/makesdna/DNA_armature_types.h4
-rw-r--r--source/blender/makesdna/DNA_brush_types.h22
-rw-r--r--source/blender/makesdna/DNA_controller_types.h5
-rw-r--r--source/blender/makesdna/DNA_customdata_types.h14
-rw-r--r--source/blender/makesdna/DNA_defs.h2
-rw-r--r--source/blender/makesdna/DNA_freestyle_types.h128
-rw-r--r--source/blender/makesdna/DNA_genfile.h12
-rw-r--r--source/blender/makesdna/DNA_group_types.h4
-rw-r--r--source/blender/makesdna/DNA_image_types.h20
-rw-r--r--source/blender/makesdna/DNA_key_types.h4
-rw-r--r--source/blender/makesdna/DNA_linestyle_types.h410
-rw-r--r--source/blender/makesdna/DNA_listBase.h7
-rw-r--r--source/blender/makesdna/DNA_mask_types.h3
-rw-r--r--source/blender/makesdna/DNA_material_types.h7
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h26
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h31
-rw-r--r--source/blender/makesdna/DNA_meta_types.h2
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h85
-rw-r--r--source/blender/makesdna/DNA_movieclip_types.h5
-rw-r--r--source/blender/makesdna/DNA_node_types.h234
-rw-r--r--source/blender/makesdna/DNA_object_types.h42
-rw-r--r--source/blender/makesdna/DNA_particle_types.h17
-rw-r--r--source/blender/makesdna/DNA_property_types.h5
-rw-r--r--source/blender/makesdna/DNA_rigidbody_types.h292
-rw-r--r--source/blender/makesdna/DNA_scene_types.h127
-rw-r--r--source/blender/makesdna/DNA_screen_types.h48
-rw-r--r--source/blender/makesdna/DNA_sensor_types.h4
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h23
-rw-r--r--source/blender/makesdna/DNA_space_types.h60
-rw-r--r--source/blender/makesdna/DNA_text_types.h13
-rw-r--r--source/blender/makesdna/DNA_tracking_types.h28
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h95
-rw-r--r--source/blender/makesdna/DNA_vfont_types.h5
-rw-r--r--source/blender/makesdna/DNA_view2d_types.h6
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h27
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h18
-rw-r--r--source/blender/makesdna/DNA_world_types.h3
-rw-r--r--source/blender/makesdna/SConscript36
-rw-r--r--source/blender/makesdna/intern/CMakeLists.txt1
-rw-r--r--source/blender/makesdna/intern/SConscript28
-rw-r--r--source/blender/makesdna/intern/dna_genfile.c410
-rw-r--r--source/blender/makesdna/intern/makesdna.c45
-rw-r--r--source/blender/makesrna/RNA_access.h192
-rw-r--r--source/blender/makesrna/RNA_define.h17
-rw-r--r--source/blender/makesrna/RNA_enum_types.h40
-rw-r--r--source/blender/makesrna/RNA_types.h48
-rw-r--r--source/blender/makesrna/SConscript36
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt20
-rw-r--r--source/blender/makesrna/intern/SConscript40
-rw-r--r--source/blender/makesrna/intern/makesrna.c170
-rw-r--r--source/blender/makesrna/intern/rna_ID.c22
-rw-r--r--source/blender/makesrna/intern/rna_access.c768
-rw-r--r--source/blender/makesrna/intern/rna_action.c23
-rw-r--r--source/blender/makesrna/intern/rna_actuator.c32
-rw-r--r--source/blender/makesrna/intern/rna_animation.c50
-rw-r--r--source/blender/makesrna/intern/rna_animviz.c7
-rw-r--r--source/blender/makesrna/intern/rna_armature.c9
-rw-r--r--source/blender/makesrna/intern/rna_boid.c15
-rw-r--r--source/blender/makesrna/intern/rna_brush.c175
-rw-r--r--source/blender/makesrna/intern/rna_camera.c34
-rw-r--r--source/blender/makesrna/intern/rna_cloth.c13
-rw-r--r--source/blender/makesrna/intern/rna_color.c71
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c104
-rw-r--r--source/blender/makesrna/intern/rna_context.c6
-rw-r--r--source/blender/makesrna/intern/rna_controller.c11
-rw-r--r--source/blender/makesrna/intern/rna_curve.c16
-rw-r--r--source/blender/makesrna/intern/rna_define.c355
-rw-r--r--source/blender/makesrna/intern/rna_dynamicpaint.c31
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c121
-rw-r--r--source/blender/makesrna/intern/rna_fluidsim.c1
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c19
-rw-r--r--source/blender/makesrna/intern/rna_group.c7
-rw-r--r--source/blender/makesrna/intern/rna_image.c129
-rw-r--r--source/blender/makesrna/intern/rna_image_api.c12
-rw-r--r--source/blender/makesrna/intern/rna_internal.h21
-rw-r--r--source/blender/makesrna/intern/rna_internal_types.h56
-rw-r--r--source/blender/makesrna/intern/rna_key.c13
-rw-r--r--source/blender/makesrna/intern/rna_lamp.c21
-rw-r--r--source/blender/makesrna/intern/rna_lattice.c12
-rw-r--r--source/blender/makesrna/intern/rna_linestyle.c1146
-rw-r--r--source/blender/makesrna/intern/rna_main.c8
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c396
-rw-r--r--source/blender/makesrna/intern/rna_mask.c8
-rw-r--r--source/blender/makesrna/intern/rna_material.c23
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c163
-rw-r--r--source/blender/makesrna/intern/rna_mesh_utils.h4
-rw-r--r--source/blender/makesrna/intern/rna_meta.c11
-rw-r--r--source/blender/makesrna/intern/rna_meta_api.c60
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c373
-rw-r--r--source/blender/makesrna/intern/rna_movieclip.c9
-rw-r--r--source/blender/makesrna/intern/rna_nla.c15
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c4226
-rw-r--r--source/blender/makesrna/intern/rna_object.c112
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c326
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c26
-rw-r--r--source/blender/makesrna/intern/rna_packedfile.c7
-rw-r--r--source/blender/makesrna/intern/rna_particle.c513
-rw-r--r--source/blender/makesrna/intern/rna_pose.c24
-rw-r--r--source/blender/makesrna/intern/rna_render.c36
-rw-r--r--source/blender/makesrna/intern/rna_rigidbody.c1150
-rw-r--r--source/blender/makesrna/intern/rna_rna.c59
-rw-r--r--source/blender/makesrna/intern/rna_scene.c747
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c22
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c101
-rw-r--r--source/blender/makesrna/intern/rna_sensor.c11
-rw-r--r--source/blender/makesrna/intern/rna_sensor_api.c6
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c55
-rw-r--r--source/blender/makesrna/intern/rna_sequencer_api.c90
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c2
-rw-r--r--source/blender/makesrna/intern/rna_space.c356
-rw-r--r--source/blender/makesrna/intern/rna_speaker.c1
-rw-r--r--source/blender/makesrna/intern/rna_text.c3
-rw-r--r--source/blender/makesrna/intern/rna_text_api.c3
-rw-r--r--source/blender/makesrna/intern/rna_texture.c43
-rw-r--r--source/blender/makesrna/intern/rna_texture_api.c3
-rw-r--r--source/blender/makesrna/intern/rna_timeline.c5
-rw-r--r--source/blender/makesrna/intern/rna_tracking.c65
-rw-r--r--source/blender/makesrna/intern/rna_ui.c224
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c445
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c521
-rw-r--r--source/blender/makesrna/intern/rna_wm.c93
-rw-r--r--source/blender/makesrna/intern/rna_wm_api.c14
-rw-r--r--source/blender/makesrna/intern/rna_world.c28
-rw-r--r--source/blender/modifiers/CMakeLists.txt11
-rw-r--r--source/blender/modifiers/MOD_modifiertypes.h2
-rw-r--r--source/blender/modifiers/SConscript67
-rw-r--r--source/blender/modifiers/intern/MOD_array.c2
-rw-r--r--source/blender/modifiers/intern/MOD_bevel.c59
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c8
-rw-r--r--source/blender/modifiers/intern/MOD_boolean_util.c13
-rw-r--r--source/blender/modifiers/intern/MOD_build.c22
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c227
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c2
-rw-r--r--source/blender/modifiers/intern/MOD_collision.c2
-rw-r--r--source/blender/modifiers/intern/MOD_decimate.c6
-rw-r--r--source/blender/modifiers/intern/MOD_edgesplit.c29
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c2
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciansmooth.c159
-rw-r--r--source/blender/modifiers/intern/MOD_mask.c6
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache.c344
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_mdd.c301
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_pc2.c277
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_util.c71
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_util.h67
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c8
-rw-r--r--source/blender/modifiers/intern/MOD_ocean.c39
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c4
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c8
-rw-r--r--source/blender/modifiers/intern/MOD_shapekey.c11
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c11
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c20
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c67
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c5
-rw-r--r--source/blender/modifiers/intern/MOD_triangulate.c10
-rw-r--r--source/blender/modifiers/intern/MOD_util.c4
-rw-r--r--source/blender/modifiers/intern/MOD_uvwarp.c268
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c2
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c6
-rw-r--r--source/blender/nodes/CMakeLists.txt16
-rw-r--r--source/blender/nodes/NOD_common.h54
-rw-r--r--source/blender/nodes/NOD_composite.h190
-rw-r--r--source/blender/nodes/NOD_shader.h155
-rw-r--r--source/blender/nodes/NOD_socket.h36
-rw-r--r--source/blender/nodes/NOD_static_types.h (renamed from source/blender/makesrna/intern/rna_nodetree_types.h)100
-rw-r--r--source/blender/nodes/NOD_texture.h74
-rw-r--r--source/blender/nodes/SConscript31
-rw-r--r--source/blender/nodes/composite/node_composite_tree.c551
-rw-r--r--source/blender/nodes/composite/node_composite_util.c1381
-rw-r--r--source/blender/nodes/composite/node_composite_util.h150
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_alphaOver.c109
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_bilateralblur.c227
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_blur.c692
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_bokehblur.c9
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_bokehimage.c12
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_boxmask.c9
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_brightness.c58
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_channelMatte.c163
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_chromaMatte.c142
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_colorMatte.c83
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_colorSpill.c287
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_colorbalance.c143
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_colorcorrection.c10
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_common.c200
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_composite.c69
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_crop.c74
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_curves.c126
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_defocus.c836
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_despeckle.c21
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_diffMatte.c97
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_dilate.c119
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_directionalblur.c96
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_displace.c149
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_distanceMatte.c153
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c1244
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_ellipsemask.c10
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_filter.c190
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_flip.c59
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_gamma.c46
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_glare.c448
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_hueSatVal.c65
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_huecorrect.c113
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_idMask.c76
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_image.c434
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_inpaint.c19
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_invert.c88
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_keying.c19
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_keyingscreen.c146
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_lensdist.c155
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_levels.c280
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_lummaMatte.c67
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_mapRange.c7
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_mapUV.c132
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_mapValue.c50
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_mask.c56
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_math.c165
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_mixrgb.c52
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_movieclip.c113
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_moviedistortion.c79
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_normal.c62
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_normalize.c73
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_outputFile.c251
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_pixelate.c7
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_premulkey.c31
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_rgb.c38
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_rotate.c93
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_scale.c151
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c124
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c101
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c245
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c126
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_setalpha.c45
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_splitViewer.c116
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_stabilize2d.c36
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_switch.c8
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_texture.c112
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_tonemap.c120
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_trackpos.c25
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_transform.c93
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_translate.c29
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_valToRgb.c96
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_value.c37
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_vecBlur.c54
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_viewer.c96
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_zcombine.c187
-rw-r--r--source/blender/nodes/intern/node_common.c518
-rw-r--r--source/blender/nodes/intern/node_common.h9
-rw-r--r--source/blender/nodes/intern/node_exec.c146
-rw-r--r--source/blender/nodes/intern/node_exec.h22
-rw-r--r--source/blender/nodes/intern/node_socket.c714
-rw-r--r--source/blender/nodes/intern/node_util.c57
-rw-r--r--source/blender/nodes/intern/node_util.h35
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c225
-rw-r--r--source/blender/nodes/shader/node_shader_util.c125
-rw-r--r--source/blender/nodes/shader/node_shader_util.h51
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_add_shader.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_attribute.c10
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_background.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_brightness.c14
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bump.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_camera.c12
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_common.c128
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_curves.c30
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_emission.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_fresnel.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_gamma.c10
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_geom.c14
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_geometry.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_hair_info.c51
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_holdout.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_hueSatVal.c12
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_invert.c12
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_layer_weight.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_light_falloff.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_light_path.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mapping.c16
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_material.c31
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.c13
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mixRgb.c12
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mix_shader.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal.c34
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal_map.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_object_info.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output.c14
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_lamp.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_material.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_world.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_particle_info.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_rgb.c36
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_script.c28
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c24
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_squeeze.c12
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tangent.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_brick.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_checker.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_coord.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_environment.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_gradient.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_magic.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_noise.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_sky.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_wave.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_texture.c25
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_valToRgb.c28
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_value.c36
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vectMath.c12
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c9
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_transparent.c9
-rw-r--r--source/blender/nodes/texture/node_texture_tree.c213
-rw-r--r--source/blender/nodes/texture/node_texture_util.c28
-rw-r--r--source/blender/nodes/texture/node_texture_util.h23
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_at.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_bricks.c14
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_checker.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_common.c71
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_compose.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_coord.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_curves.c30
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_decompose.c18
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_distance.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_hueSatVal.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_image.c14
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_invert.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_math.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_mixRgb.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_output.c22
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_proc.c18
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_rotate.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_scale.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_texture.c14
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_translate.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_valToNor.c12
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_valToRgb.c28
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_viewer.c12
-rw-r--r--source/blender/opencl/SConscript8
-rw-r--r--source/blender/python/BPY_extern.h7
-rw-r--r--source/blender/python/SConscript128
-rw-r--r--source/blender/python/bmesh/CMakeLists.txt4
-rw-r--r--source/blender/python/bmesh/bmesh_py_api.c25
-rw-r--r--source/blender/python/bmesh/bmesh_py_ops.c2
-rw-r--r--source/blender/python/bmesh/bmesh_py_ops_call.c13
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.c265
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.h4
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_customdata.c27
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_meshdata.c6
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_meshdata.h3
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_select.c14
-rw-r--r--source/blender/python/bmesh/bmesh_py_utils.c22
-rw-r--r--source/blender/python/generic/bpy_internal_import.c4
-rw-r--r--source/blender/python/generic/bpy_internal_import.h6
-rw-r--r--source/blender/python/generic/idprop_py_api.c15
-rw-r--r--source/blender/python/generic/py_capi_utils.c73
-rw-r--r--source/blender/python/generic/py_capi_utils.h7
-rw-r--r--source/blender/python/intern/CMakeLists.txt139
-rw-r--r--source/blender/python/intern/bpy.c77
-rw-r--r--source/blender/python/intern/bpy_app.c30
-rw-r--r--source/blender/python/intern/bpy_app_build_options.c310
-rw-r--r--source/blender/python/intern/bpy_app_build_options.h32
-rw-r--r--source/blender/python/intern/bpy_app_ffmpeg.c12
-rw-r--r--source/blender/python/intern/bpy_app_translations.c829
-rw-r--r--source/blender/python/intern/bpy_app_translations.h32
-rw-r--r--source/blender/python/intern/bpy_driver.c10
-rw-r--r--source/blender/python/intern/bpy_interface.c90
-rw-r--r--source/blender/python/intern/bpy_interface_atexit.c6
-rw-r--r--source/blender/python/intern/bpy_intern_string.c3
-rw-r--r--source/blender/python/intern/bpy_intern_string.h1
-rw-r--r--source/blender/python/intern/bpy_library.c4
-rw-r--r--source/blender/python/intern/bpy_operator.c28
-rw-r--r--source/blender/python/intern/bpy_operator_wrap.c95
-rw-r--r--source/blender/python/intern/bpy_path.c67
-rw-r--r--source/blender/python/intern/bpy_path.h33
-rw-r--r--source/blender/python/intern/bpy_props.c1945
-rw-r--r--source/blender/python/intern/bpy_rna.c360
-rw-r--r--source/blender/python/intern/bpy_rna.h13
-rw-r--r--source/blender/python/intern/bpy_rna_anim.c51
-rw-r--r--source/blender/python/intern/bpy_rna_callback.c185
-rw-r--r--source/blender/python/intern/bpy_rna_callback.h5
-rw-r--r--source/blender/python/intern/bpy_traceback.c1
-rw-r--r--source/blender/python/intern/bpy_util.c10
-rw-r--r--source/blender/python/intern/bpy_util.h2
-rw-r--r--source/blender/python/intern/gpu.c2
-rw-r--r--source/blender/python/mathutils/mathutils.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c93
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c83
-rw-r--r--source/blender/python/mathutils/mathutils_noise.c34
-rw-r--r--source/blender/quicktime/SConscript28
-rw-r--r--source/blender/quicktime/apple/qtkit_export.m12
-rw-r--r--source/blender/quicktime/apple/qtkit_import.m1
-rw-r--r--source/blender/quicktime/apple/quicktime_export.c6
-rw-r--r--source/blender/quicktime/apple/quicktime_import.c10
-rw-r--r--source/blender/quicktime/quicktime_export.h6
-rw-r--r--source/blender/render/CMakeLists.txt17
-rw-r--r--source/blender/render/SConscript35
-rw-r--r--source/blender/render/extern/include/RE_engine.h8
-rw-r--r--source/blender/render/extern/include/RE_multires_bake.h62
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h3
-rw-r--r--source/blender/render/extern/include/RE_render_ext.h3
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h12
-rw-r--r--source/blender/render/intern/include/envmap.h3
-rw-r--r--source/blender/render/intern/include/pixelshading.h2
-rw-r--r--source/blender/render/intern/include/rayobject.h2
-rw-r--r--source/blender/render/intern/include/render_result.h2
-rw-r--r--source/blender/render/intern/include/render_types.h31
-rw-r--r--source/blender/render/intern/include/rendercore.h2
-rw-r--r--source/blender/render/intern/include/renderdatabase.h6
-rw-r--r--source/blender/render/intern/include/texture.h7
-rw-r--r--source/blender/render/intern/raytrace/rayobject.cpp7
-rw-r--r--source/blender/render/intern/raytrace/rayobject_instance.cpp4
-rw-r--r--source/blender/render/intern/raytrace/rayobject_internal.h8
-rw-r--r--source/blender/render/intern/raytrace/rayobject_octree.cpp18
-rw-r--r--source/blender/render/intern/raytrace/rayobject_rtbuild.cpp10
-rw-r--r--source/blender/render/intern/raytrace/rayobject_vbvh.cpp4
-rw-r--r--source/blender/render/intern/raytrace/reorganize.h3
-rw-r--r--source/blender/render/intern/source/bake.c1117
-rw-r--r--source/blender/render/intern/source/convertblender.c223
-rw-r--r--source/blender/render/intern/source/envmap.c18
-rw-r--r--source/blender/render/intern/source/external_engine.c104
-rw-r--r--source/blender/render/intern/source/imagetexture.c142
-rw-r--r--source/blender/render/intern/source/multires_bake.c1298
-rw-r--r--source/blender/render/intern/source/occlusion.c436
-rw-r--r--source/blender/render/intern/source/pipeline.c450
-rw-r--r--source/blender/render/intern/source/pixelblending.c2
-rw-r--r--source/blender/render/intern/source/pixelshading.c2
-rw-r--r--source/blender/render/intern/source/pointdensity.c8
-rw-r--r--source/blender/render/intern/source/rayshade.c50
-rw-r--r--source/blender/render/intern/source/render_result.c37
-rw-r--r--source/blender/render/intern/source/render_texture.c149
-rw-r--r--source/blender/render/intern/source/rendercore.c822
-rw-r--r--source/blender/render/intern/source/renderdatabase.c66
-rw-r--r--source/blender/render/intern/source/shadbuf.c9
-rw-r--r--source/blender/render/intern/source/shadeinput.c10
-rw-r--r--source/blender/render/intern/source/shadeoutput.c10
-rw-r--r--source/blender/render/intern/source/sss.c6
-rw-r--r--source/blender/render/intern/source/strand.c6
-rw-r--r--source/blender/render/intern/source/volume_precache.c28
-rw-r--r--source/blender/render/intern/source/voxeldata.c10
-rw-r--r--source/blender/render/intern/source/zbuf.c13
-rw-r--r--source/blender/windowmanager/SConscript28
-rw-r--r--source/blender/windowmanager/WM_api.h100
-rw-r--r--source/blender/windowmanager/WM_keymap.h3
-rw-r--r--source/blender/windowmanager/WM_types.h18
-rw-r--r--source/blender/windowmanager/intern/wm.c85
-rw-r--r--source/blender/windowmanager/intern/wm_apple.c2
-rw-r--r--source/blender/windowmanager/intern/wm_cursors.c26
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c4
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c102
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c236
-rw-r--r--source/blender/windowmanager/intern/wm_files.c123
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c19
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c44
-rw-r--r--source/blender/windowmanager/intern/wm_jobs.c17
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c33
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c478
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c190
-rw-r--r--source/blender/windowmanager/intern/wm_subwindow.c19
-rw-r--r--source/blender/windowmanager/intern/wm_window.c324
-rw-r--r--source/blender/windowmanager/wm_event_system.h20
-rw-r--r--source/blender/windowmanager/wm_event_types.h43
-rw-r--r--source/blender/windowmanager/wm_files.h8
-rw-r--r--source/blender/windowmanager/wm_window.h10
-rw-r--r--source/blenderplayer/CMakeLists.txt4
-rw-r--r--source/blenderplayer/bad_level_call_stubs/CMakeLists.txt5
-rw-r--r--source/blenderplayer/bad_level_call_stubs/SConscript52
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c91
-rw-r--r--source/creator/CMakeLists.txt40
-rw-r--r--source/creator/creator.c277
-rw-r--r--source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp23
-rw-r--r--source/gameengine/BlenderRoutines/CMakeLists.txt9
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp22
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderCanvas.h12
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderGL.cpp60
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderGL.h1
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h2
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp24
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.cpp26
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp10
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h7
-rw-r--r--source/gameengine/BlenderRoutines/SConscript28
-rw-r--r--source/gameengine/CMakeLists.txt1
-rw-r--r--source/gameengine/Converter/BL_ArmatureConstraint.cpp4
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.cpp21
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp883
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.h5
-rw-r--r--source/gameengine/Converter/BL_DeformableGameObject.cpp2
-rw-r--r--source/gameengine/Converter/BL_ModifierDeformer.cpp4
-rw-r--r--source/gameengine/Converter/BL_ShapeActionActuator.cpp6
-rw-r--r--source/gameengine/Converter/CMakeLists.txt8
-rw-r--r--source/gameengine/Converter/KX_BlenderSceneConverter.cpp218
-rw-r--r--source/gameengine/Converter/KX_BlenderSceneConverter.h36
-rw-r--r--source/gameengine/Converter/KX_ConvertActuators.cpp6
-rw-r--r--source/gameengine/Converter/KX_ConvertControllers.cpp6
-rw-r--r--source/gameengine/Converter/KX_ConvertSensors.cpp7
-rw-r--r--source/gameengine/Converter/KX_LibLoadStatus.cpp252
-rw-r--r--source/gameengine/Converter/KX_LibLoadStatus.h85
-rw-r--r--source/gameengine/Converter/KX_SoftBodyDeformer.cpp2
-rw-r--r--source/gameengine/Converter/SConscript30
-rw-r--r--source/gameengine/Expressions/EmptyValue.cpp28
-rw-r--r--source/gameengine/Expressions/InputParser.cpp16
-rw-r--r--source/gameengine/Expressions/InputParser.h2
-rw-r--r--source/gameengine/Expressions/Operator2Expr.cpp83
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.cpp36
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.h224
-rw-r--r--source/gameengine/Expressions/SConscript28
-rw-r--r--source/gameengine/Expressions/Value.cpp6
-rw-r--r--source/gameengine/Expressions/Value.h8
-rw-r--r--source/gameengine/GameLogic/CMakeLists.txt2
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp26
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_Joystick.h5
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h4
-rw-r--r--source/gameengine/GameLogic/SCA_2DFilterActuator.cpp5
-rw-r--r--source/gameengine/GameLogic/SCA_2DFilterActuator.h2
-rw-r--r--source/gameengine/GameLogic/SCA_IActuator.h2
-rw-r--r--source/gameengine/GameLogic/SCA_IInputDevice.h25
-rw-r--r--source/gameengine/GameLogic/SCA_IObject.h2
-rw-r--r--source/gameengine/GameLogic/SCA_JoystickManager.cpp8
-rw-r--r--source/gameengine/GameLogic/SCA_LogicManager.h8
-rw-r--r--source/gameengine/GameLogic/SCA_PythonController.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_PythonJoystick.cpp188
-rw-r--r--source/gameengine/GameLogic/SCA_PythonJoystick.h56
-rw-r--r--source/gameengine/GameLogic/SCA_RandomActuator.cpp20
-rw-r--r--source/gameengine/GameLogic/SConscript28
-rw-r--r--source/gameengine/GamePlayer/SConscript28
-rw-r--r--source/gameengine/GamePlayer/common/GPC_Canvas.cpp10
-rw-r--r--source/gameengine/GamePlayer/common/GPC_Canvas.h5
-rw-r--r--source/gameengine/GamePlayer/common/GPC_Engine.cpp6
-rw-r--r--source/gameengine/GamePlayer/common/GPC_Engine.h2
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RawImage.cpp1
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RenderTools.cpp72
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RenderTools.h6
-rw-r--r--source/gameengine/GamePlayer/common/SConscript28
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.cpp65
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.h36
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_ghost.cpp144
-rw-r--r--source/gameengine/GamePlayer/ghost/SConscript28
-rw-r--r--source/gameengine/Ketsji/BL_Action.cpp92
-rw-r--r--source/gameengine/Ketsji/BL_BlenderShader.cpp14
-rw-r--r--source/gameengine/Ketsji/BL_Material.cpp39
-rw-r--r--source/gameengine/Ketsji/BL_Material.h10
-rw-r--r--source/gameengine/Ketsji/BL_Texture.cpp16
-rw-r--r--source/gameengine/Ketsji/CMakeLists.txt18
-rw-r--r--source/gameengine/Ketsji/KXNetwork/SConscript28
-rw-r--r--source/gameengine/Ketsji/KX_ArmatureSensor.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.cpp64
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.h19
-rw-r--r--source/gameengine/Ketsji/KX_BulletPhysicsController.cpp21
-rw-r--r--source/gameengine/Ketsji/KX_BulletPhysicsController.h7
-rw-r--r--source/gameengine/Ketsji/KX_CameraActuator.cpp3
-rw-r--r--source/gameengine/Ketsji/KX_CharacterWrapper.cpp53
-rw-r--r--source/gameengine/Ketsji/KX_CharacterWrapper.h5
-rw-r--r--source/gameengine/Ketsji/KX_ConvertPhysicsObject.h2
-rw-r--r--source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp8
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp25
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h6
-rw-r--r--source/gameengine/Ketsji/KX_IPhysicsController.h3
-rw-r--r--source/gameengine/Ketsji/KX_ISceneConverter.h10
-rw-r--r--source/gameengine/Ketsji/KX_IpoConvert.cpp (renamed from source/gameengine/Converter/KX_IpoConvert.cpp)237
-rw-r--r--source/gameengine/Ketsji/KX_IpoConvert.h (renamed from source/gameengine/Converter/KX_IpoConvert.h)47
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.cpp169
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.h4
-rw-r--r--source/gameengine/Ketsji/KX_Light.cpp11
-rw-r--r--source/gameengine/Ketsji/KX_Light.h2
-rw-r--r--source/gameengine/Ketsji/KX_MeshProxy.cpp12
-rw-r--r--source/gameengine/Ketsji/KX_NavMeshObject.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_ObColorIpoSGController.cpp11
-rw-r--r--source/gameengine/Ketsji/KX_ObjectActuator.cpp47
-rw-r--r--source/gameengine/Ketsji/KX_ObjectActuator.h8
-rw-r--r--source/gameengine/Ketsji/KX_PolygonMaterial.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_PolygonMaterial.h2
-rw-r--r--source/gameengine/Ketsji/KX_PyConstraintBinding.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp76
-rw-r--r--source/gameengine/Ketsji/KX_PythonInitTypes.cpp10
-rw-r--r--source/gameengine/Ketsji/KX_RayCast.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp66
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.cpp11
-rw-r--r--source/gameengine/Ketsji/KX_TrackToActuator.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_VehicleWrapper.cpp15
-rw-r--r--source/gameengine/Ketsji/KX_VehicleWrapper.h1
-rw-r--r--source/gameengine/Ketsji/KX_VertexProxy.cpp86
-rw-r--r--source/gameengine/Ketsji/KX_VertexProxy.h2
-rw-r--r--source/gameengine/Ketsji/SConscript30
-rw-r--r--source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.h4
-rw-r--r--source/gameengine/Network/LoopBackNetwork/SConscript28
-rw-r--r--source/gameengine/Network/NG_NetworkDeviceInterface.h18
-rw-r--r--source/gameengine/Network/NG_NetworkMessage.h4
-rw-r--r--source/gameengine/Network/NG_NetworkScene.h2
-rw-r--r--source/gameengine/Network/SConscript28
-rw-r--r--source/gameengine/Physics/Bullet/CMakeLists.txt6
-rw-r--r--source/gameengine/Physics/Bullet/CcdGraphicController.cpp2
-rw-r--r--source/gameengine/Physics/Bullet/CcdGraphicController.h2
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp145
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.h42
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp61
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h6
-rw-r--r--source/gameengine/Physics/Bullet/SConscript30
-rw-r--r--source/gameengine/Physics/Dummy/CMakeLists.txt1
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp2
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h6
-rw-r--r--source/gameengine/Physics/Dummy/SConscript30
-rw-r--r--source/gameengine/Physics/common/PHY_DynamicTypes.h71
-rw-r--r--source/gameengine/Physics/common/PHY_ICharacter.h9
-rw-r--r--source/gameengine/Physics/common/PHY_IController.h10
-rw-r--r--source/gameengine/Physics/common/PHY_IGraphicController.h13
-rw-r--r--source/gameengine/Physics/common/PHY_IMotionState.h8
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsController.h20
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h25
-rw-r--r--source/gameengine/Physics/common/PHY_IVehicle.cpp10
-rw-r--r--source/gameengine/Physics/common/PHY_IVehicle.h8
-rw-r--r--source/gameengine/Physics/common/SConscript14
-rw-r--r--source/gameengine/Rasterizer/CMakeLists.txt1
-rw-r--r--source/gameengine/Rasterizer/RAS_2DFilterManager.cpp9
-rw-r--r--source/gameengine/Rasterizer/RAS_BucketManager.cpp21
-rw-r--r--source/gameengine/Rasterizer/RAS_ICanvas.h14
-rw-r--r--source/gameengine/Rasterizer/RAS_IPolygonMaterial.h6
-rw-r--r--source/gameengine/Rasterizer/RAS_IRasterizer.h8
-rw-r--r--source/gameengine/Rasterizer/RAS_IRenderTools.h16
-rw-r--r--source/gameengine/Rasterizer/RAS_MaterialBucket.cpp7
-rw-r--r--source/gameengine/Rasterizer/RAS_MeshObject.cpp9
-rw-r--r--source/gameengine/Rasterizer/RAS_MeshObject.h3
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt9
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_IStorage.h62
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp38
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h7
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp317
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h20
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp310
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.h69
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp320
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.h (renamed from source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h)54
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp258
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h101
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp382
-rw-r--r--source/gameengine/Rasterizer/RAS_TexVert.cpp87
-rw-r--r--source/gameengine/Rasterizer/RAS_TexVert.h32
-rw-r--r--source/gameengine/Rasterizer/RAS_texmatrix.cpp6
-rw-r--r--source/gameengine/Rasterizer/SConscript56
-rw-r--r--source/gameengine/SConscript29
-rw-r--r--source/gameengine/SceneGraph/SConscript27
-rw-r--r--source/gameengine/SceneGraph/SG_ParentRelation.h4
-rw-r--r--source/gameengine/VideoTexture/PyTypeList.cpp2
-rw-r--r--source/gameengine/VideoTexture/SConscript28
-rw-r--r--source/gameengine/VideoTexture/VideoFFmpeg.cpp6
-rw-r--r--source/gameengine/VideoTexture/blendVideoTex.cpp12
-rw-r--r--source/icons/SConscript28
-rw-r--r--source/tests/CMakeLists.txt4
-rw-r--r--source/tests/batch_import.py5
-rw-r--r--source/tests/bl_keymap_completeness.py84
-rw-r--r--source/tests/bl_load_addons.py45
-rw-r--r--source/tests/bl_load_py_modules.py24
-rw-r--r--source/tests/bl_mesh_modifiers.py6
-rw-r--r--source/tests/bl_mesh_validate.py4
-rw-r--r--source/tests/bl_pyapi_mathutils.py2
-rw-r--r--source/tests/bl_rst_completeness.py6
-rw-r--r--source/tests/bl_run_operators.py175
-rw-r--r--source/tests/check_deprecated.py4
-rw-r--r--source/tests/pep8.py8
-rw-r--r--source/tests/rna_info_dump.py2
-rw-r--r--source/tests/rst_to_doctree_mini.py2
3159 files changed, 369538 insertions, 95497 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3e1c8fec02a..58f0fb08318 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -124,16 +124,21 @@ mark_as_advanced(WITH_PYTHON_SECURITY) # some distributions see this as a secur
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)
+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_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_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_PLAYER "Build Player" OFF)
option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ON)
option(WITH_COMPOSITOR "Enable the tile based nodal compositor" ON)
-option(WITH_COMPOSITOR_LEGACY "Enable legacy compositor" OFF)
# GHOST Windowing Library Options
option(WITH_GHOST_DEBUG "Enable debugging output for the GHOST library" OFF)
@@ -149,6 +154,9 @@ mark_as_advanced(WITH_HEADLESS)
option(WITH_AUDASPACE "Build with blenders audio library (only disable if you know what you're doing!)" ON)
mark_as_advanced(WITH_AUDASPACE)
+option(WITH_BOOL_COMPAT "Continue defining \"TRUE\" and \"FALSE\" until these can be replaced with \"true\" and \"false\" from stdbool.h" ON)
+mark_as_advanced(WITH_BOOL_COMPAT)
+
# (unix defaults to OpenMP On)
if((UNIX AND NOT APPLE) OR (MINGW))
@@ -229,12 +237,19 @@ option(WITH_LZMA "Enable best LZMA compression, (used for pointcache)"
# Camera/motion tracking
option(WITH_LIBMV "Enable libmv structure from motion library" ON)
+# Freestyle
+option(WITH_FREESTYLE "Enable Freestyle (advanced edges rendering)" ON)
+
# Misc
option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ON)
option(WITH_RAYOPTIMIZATION "Enable use of SIMD (SSE) optimizations for the raytracer" ON)
if(UNIX AND NOT APPLE)
option(WITH_INSTALL_PORTABLE "Install redistributeable runtime, otherwise install into CMAKE_INSTALL_PREFIX" ON)
option(WITH_STATIC_LIBS "Try to link with static libraries, as much as possible, to make blender more portable across distributions" OFF)
+ if(WITH_STATIC_LIBS)
+ option(WITH_BOOST_ICU "Boost uses ICU library (required for linking with static Boost built with libicu)." OFF)
+ mark_as_advanced(WITH_BOOST_ICU)
+ endif()
endif()
option(WITH_PYTHON_INSTALL "Copy system python into the blender install folder" ON)
option(WITH_PYTHON_INSTALL_NUMPY "Copy system numpy into the blender install folder" ON)
@@ -246,7 +261,7 @@ option(WITH_CYCLES "Enable cycles Render Engine" ON)
option(WITH_CYCLES_TEST "Build cycles test application" 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_13 sm_20 sm_21 sm_30 CACHE STRING "CUDA architectures to build binaries for")
+set(CYCLES_CUDA_BINARIES_ARCH sm_20 sm_21 sm_30 CACHE STRING "CUDA architectures to build binaries for")
mark_as_advanced(CYCLES_CUDA_BINARIES_ARCH)
unset(PLATFORM_DEFAULT)
@@ -264,6 +279,12 @@ mark_as_advanced(WITH_CXX_GUARDEDALLOC)
option(WITH_ASSERT_ABORT "Call abort() when raising an assertion through BLI_assert()" OFF)
mark_as_advanced(WITH_ASSERT_ABORT)
+option(WITH_BOOST "Enable features depending no boost" ON)
+
+if(CMAKE_COMPILER_IS_GNUCC)
+ option(WITH_GCC_MUDFLAP "Enable mudflap" OFF)
+ mark_as_advanced(WITH_GCC_MUDFLAP)
+endif()
if(APPLE)
cmake_minimum_required(VERSION 2.8.8)
@@ -276,9 +297,9 @@ if(APPLE)
endif()
execute_process(COMMAND uname -r OUTPUT_VARIABLE MAC_SYS) # check for actual system-version
- if (${MAC_SYS} MATCHES 12)
+ if(${MAC_SYS} MATCHES 12)
set(OSX_SYSTEM 10.8)
- elseif (${MAC_SYS} MATCHES 11)
+ elseif(${MAC_SYS} MATCHES 11)
set(OSX_SYSTEM 10.7)
elseif(${MAC_SYS} MATCHES 10)
set(OSX_SYSTEM 10.6)
@@ -392,9 +413,22 @@ if(WITH_CYCLES)
set(WITH_OPENIMAGEIO ON)
endif()
-# auto enable boost for cycles, booleans, audaspace or i18n
-if(WITH_CYCLES OR WITH_MOD_BOOLEAN OR WITH_AUDASPACE OR WITH_INTERNATIONAL)
- set(WITH_BOOST ON)
+# enable boost for cycles, booleans, audaspace or i18n
+# otherwise if the user disabled
+if(NOT WITH_BOOST)
+ # Explicitly disabled. so disable all deps.
+ set(WITH_CYCLES OFF)
+ set(WITH_MOD_BOOLEAN OFF)
+ set(WITH_AUDASPACE OFF)
+ set(WITH_INTERNATIONAL OFF)
+
+ set(WITH_OPENAL OFF) # depends on AUDASPACE
+ set(WITH_GAMEENGINE OFF) # depends on AUDASPACE
+elseif(WITH_CYCLES OR WITH_MOD_BOOLEAN OR WITH_AUDASPACE OR WITH_INTERNATIONAL)
+ # Keep enabled
+else()
+ # Enabled but we don't need it
+ set(WITH_BOOST OFF)
endif()
# auto enable llvm for cycles_osl
@@ -423,6 +457,13 @@ endif()
TEST_SSE_SUPPORT(COMPILER_SSE_FLAG COMPILER_SSE2_FLAG)
+TEST_STDBOOL_SUPPORT()
+if(HAVE_STDBOOL_H)
+ add_definitions(-DHAVE_STDBOOL_H)
+endif()
+if(WITH_BOOL_COMPAT)
+ add_definitions(-DWITH_BOOL_COMPAT)
+endif()
#-----------------------------------------------------------------------------
# Check for valid directories
@@ -498,7 +539,7 @@ set(PLATFORM_LINKFLAGS_DEBUG "")
if(UNIX AND NOT APPLE)
macro(find_package_wrapper)
- STRING(TOUPPER ${ARGV0} _NAME_UPPER)
+ 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})
@@ -628,7 +669,7 @@ if(UNIX AND NOT APPLE)
endif()
endif()
- if (WITH_INPUT_NDOF)
+ if(WITH_INPUT_NDOF)
find_package_wrapper(Spacenav)
if(NOT SPACENAV_FOUND)
set(WITH_INPUT_NDOF OFF)
@@ -644,21 +685,17 @@ if(UNIX AND NOT APPLE)
if(WITH_BOOST)
# uses in build instructions to override include and library variables
if(NOT BOOST_CUSTOM)
- # XXX No more lib dir, is this multithread stuff still needed?
if(${WITH_STATIC_LIBS})
set(Boost_USE_STATIC_LIBS ON)
endif()
- if(NOT BOOST_ROOT)
- set(Boost_USE_MULTITHREADED OFF)
- else()
- set(Boost_USE_MULTITHREADED ON)
- endif()
+ set(Boost_USE_MULTITHREADED ON)
set(__boost_packages filesystem regex system thread date_time)
- if (WITH_INTERNATIONAL)
+ if(WITH_INTERNATIONAL)
list(APPEND __boost_packages locale)
endif()
- find_package(Boost 1.34 COMPONENTS ${__boost_packages})
- if(Boost_USE_STATIC_LIBS AND Boost_USE_ICU)
+ find_package(Boost 1.48 COMPONENTS ${__boost_packages})
+ unset(__boost_packages)
+ if(Boost_USE_STATIC_LIBS AND WITH_BOOST_ICU)
find_package(IcuLinux)
endif()
mark_as_advanced(Boost_DIR) # why doesnt boost do this?
@@ -675,7 +712,7 @@ if(UNIX AND NOT APPLE)
set(OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO_LIBRARIES} ${PNG_LIBRARIES} ${JPEG_LIBRARIES} ${ZLIB_LIBRARIES} ${BOOST_LIBRARIES})
set(OPENIMAGEIO_LIBPATH) # TODO, remove and reference the absolute path everywhere
- set(OPENIMAGEIO_DEFINITIONS)
+ set(OPENIMAGEIO_DEFINITIONS "")
if(WITH_IMAGE_TIFF)
list(APPEND OPENIMAGEIO_LIBRARIES "${TIFF_LIBRARY}")
@@ -792,7 +829,11 @@ if(UNIX AND NOT APPLE)
set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS} ${X11_X11_LIB}")
if(WITH_X11_XINPUT)
- set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS} ${X11_Xinput_LIB}")
+ if(X11_Xinput_LIB)
+ set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS} ${X11_Xinput_LIB}")
+ else()
+ set(WITH_X11_XINPUT OFF)
+ endif()
endif()
if(WITH_X11_XF86VMODE)
@@ -862,7 +903,7 @@ elseif(WIN32)
if(CMAKE_COMPILER_IS_GNUCC)
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw32)
- INCLUDE (CheckCSourceCompiles)
+ include(CheckCSourceCompiles)
# Setup 64bit and 64bit windows systems
CHECK_C_SOURCE_COMPILES("
#ifndef __MINGW64__
@@ -1092,14 +1133,16 @@ elseif(WIN32)
if(WITH_PYTHON)
# normally cached but not since we include them with blender
if(MSVC10)
- set(PYTHON_VERSION 3.2) # CACHE STRING)
+ set(PYTHON_VERSION 3.3) # CACHE STRING)
else()
set(PYTHON_VERSION 3.3) # CACHE STRING)
endif()
set_lib_path(PYTHON "python")
- STRING(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
- set(PYTHON_LIBRARY ${PYTHON}/lib/python${_PYTHON_VERSION_NO_DOTS}.lib) #CACHE FILEPATH
+ string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
+ # Use shared libs for vc2008 and vc2010 until we actually have vc2010 libs
+ set(PYTHON_LIBRARY ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}.lib)
+ # set(PYTHON_LIBRARY ${PYTHON}/lib/python${_PYTHON_VERSION_NO_DOTS}.lib) #CACHE FILEPATH
unset(_PYTHON_VERSION_NO_DOTS)
#Shared includes for both vc2008 and vc2010
@@ -1129,11 +1172,16 @@ elseif(WIN32)
debug libboost_date_time-${BOOST_DEBUG_POSTFIX} debug libboost_filesystem-${BOOST_DEBUG_POSTFIX}
debug libboost_regex-${BOOST_DEBUG_POSTFIX}
debug libboost_system-${BOOST_DEBUG_POSTFIX} debug libboost_thread-${BOOST_DEBUG_POSTFIX})
+ if(WITH_CYCLES_OSL)
+ set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
+ optimized libboost_wave-${BOOST_POSTFIX}
+ debug libboost_wave-${BOOST_DEBUG_POSTFIX})
+ endif()
if(WITH_INTERNATIONAL)
set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
optimized libboost_locale-${BOOST_POSTFIX}
debug libboost_locale-${BOOST_DEBUG_POSTFIX})
- endif(WITH_INTERNATIONAL)
+ endif()
set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB")
endif()
@@ -1319,6 +1367,11 @@ elseif(WIN32)
optimized boost_locale-${BOOST_POSTFIX}
debug boost_locale-${BOOST_DEBUG_POSTFIX})
endif()
+ if(WITH_CYCLES_OSL)
+ set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
+ optimized boost_wave-${BOOST_POSTFIX}
+ debug boost_wave-${BOOST_DEBUG_POSTFIX})
+ endif()
set(BOOST_LIBPATH ${BOOST}/lib)
set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB -DBOOST_THREAD_USE_LIB ")
endif()
@@ -1328,7 +1381,7 @@ elseif(WIN32)
set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include)
set(OPENIMAGEIO_LIBRARIES OpenImageIO)
set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib)
- set(OPENIMAGEIO_DEFINITIONS)
+ set(OPENIMAGEIO_DEFINITIONS "")
endif()
if(WITH_LLVM)
@@ -1420,11 +1473,10 @@ elseif(APPLE)
endif()
if(WITH_PYTHON)
- if(NOT WITH_PYTHON_MODULE)
- # we use precompiled libraries for py 3.3 and up by default
-
+ # we use precompiled libraries for py 3.3 and up by default
+ set(PYTHON_VERSION 3.3)
+ if(NOT WITH_PYTHON_MODULE AND NOT WITH_PYTHON_FRAMEWORK)
# normally cached but not since we include them with blender
- set(PYTHON_VERSION 3.3)
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_LIBRARY python${PYTHON_VERSION}m)
@@ -1432,13 +1484,10 @@ elseif(APPLE)
# set(PYTHON_LINKFLAGS "-u _PyMac_Error") # won't build with this enabled
else()
# module must be compiled against Python framework
-
- # normally cached but not since we include them with blender
- set(PYTHON_VERSION 3.2)
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_LIBRARY python${PYTHON_VERSION})
- set(PYTHON_LIBPATH "/Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/lib/python${PYTHON_VERSION}/config-3.2m")
+ 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
endif()
@@ -1521,7 +1570,8 @@ elseif(APPLE)
endif()
if(WITH_INPUT_NDOF)
- set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -weak_framework 3DconnexionClient")
+ set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -F/Library/Frameworks -weak_framework 3DconnexionClient")
+ set(NDOF_INCLUDE_DIRS /Library/Frameworks/3DconnexionClient.framework/Headers )
endif()
endif()
@@ -1535,8 +1585,8 @@ elseif(APPLE)
set(WITH_INPUT_NDOF OFF) # unsupported
endif()
- if(WITH_PYTHON_MODULE)
- set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/python")# force cmake to link right framework
+ if(WITH_PYTHON_MODULE OR WITH_PYTHON_FRAMEWORK)
+ set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/Python")# force cmake to link right framework
endif()
if(WITH_OPENCOLLADA)
@@ -1584,7 +1634,7 @@ elseif(APPLE)
set(TIFF_LIBPATH ${TIFF}/lib)
endif()
- if (WITH_INPUT_NDOF)
+ if(WITH_INPUT_NDOF)
# linker needs "-weak_framework 3DconnexionClient"
endif()
@@ -1592,7 +1642,7 @@ elseif(APPLE)
set(BOOST ${LIBDIR}/boost)
set(BOOST_INCLUDE_DIR ${BOOST}/include)
set(BOOST_LIBRARIES boost_date_time-mt boost_filesystem-mt boost_regex-mt boost_system-mt boost_thread-mt boost_wave-mt)
- if (WITH_INTERNATIONAL)
+ if(WITH_INTERNATIONAL)
list(APPEND BOOST_LIBRARIES boost_locale-mt)
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -liconv") # boost_locale needs it !
endif()
@@ -1837,6 +1887,20 @@ else()
set(GLEW_INCLUDE_PATH "${CMAKE_SOURCE_DIR}/extern/glew/include")
endif()
+
+#-----------------------------------------------------------------------------
+# Configure Bullet
+
+if(WITH_BULLET AND WITH_SYSTEM_BULLET)
+ find_package(Bullet)
+ if(NOT BULLET_FOUND)
+ set(WITH_BULLET OFF)
+ endif()
+else()
+ set(BULLET_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/extern/bullet2/src")
+ # set(BULLET_LIBRARIES "")
+endif()
+
#-----------------------------------------------------------------------------
# Configure Python.
@@ -1870,10 +1934,16 @@ if(CMAKE_COMPILER_IS_GNUCC)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero)
# gcc 4.2 gives annoying warnings on every file with this
- if (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.3")
+ if(NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.3")
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNINITIALIZED -Wuninitialized)
endif()
+ # versions before gcc4.6 give many BLI_math warnings
+ if(NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.6")
+ ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_REDUNDANT_DECLS -Wredundant-decls)
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_REDUNDANT_DECLS -Wredundant-decls)
+ endif()
+
# disable because it gives warnings for printf() & friends.
# ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_DOUBLE_PROMOTION -Wdouble-promotion -Wno-error=double-promotion)
@@ -1890,7 +1960,7 @@ if(CMAKE_COMPILER_IS_GNUCC)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero)
# gcc 4.2 gives annoying warnings on every file with this
- if (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.3")
+ if(NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.3")
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNINITIALIZED -Wuninitialized)
endif()
@@ -1912,20 +1982,31 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# strange, clang complains these are not supported, but then yses them.
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ALL -Wall)
+ ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ERROR_DECLARATION_AFTER_STATEMENT -Werror=declaration-after-statement)
+ ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ERROR_IMPLICIT_FUNCTION_DECLARATION -Werror=implicit-function-declaration)
+ ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ERROR_RETURN_TYPE -Werror=return-type)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_AUTOLOGICAL_COMPARE -Wno-tautological-compare)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_STRICT_PROTOTYPES -Wstrict-prototypes)
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_MISSING_PROTOTYPES -Wmissing-prototypes)
- ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNUSED_MACROS -Wunused-macros)
+ ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNUSED_PARAMETER -Wunused-parameter)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ALL -Wall)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_AUTOLOGICAL_COMPARE -Wno-tautological-compare)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas)
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_OVERLOADED_VIRTUAL -Wno-overloaded-virtual) # we get a lot of these, if its a problem a dev needs to look into it.
+ ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_SIGN_COMPARE -Wno-sign-compare)
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_INVALID_OFFSETOF -Wno-invalid-offsetof)
- ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNUSED_MACROS -Wunused-macros)
+
+ # gives too many unfixable warnings
+ # ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNUSED_MACROS -Wunused-macros)
+ # ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNUSED_MACROS -Wunused-macros)
+
+ # flags to undo strict flags
+ ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_PARAMETER -Wno-unused-parameter)
+ ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_MACROS -Wno-unused-macros)
elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
@@ -1963,7 +2044,7 @@ if(WITH_PYTHON)
if(WITH_PYTHON_INSTALL AND WITH_PYTHON_INSTALL_NUMPY)
# set but invalid
- # -- disabled until we make numpy bundled with blender - campbell
+ # -- disabled until we make numpy bundled with blender - campbell
if((NOT ${PYTHON_NUMPY_PATH} STREQUAL "") AND (NOT ${PYTHON_NUMPY_PATH} MATCHES NOTFOUND))
# if(NOT EXISTS "${PYTHON_NUMPY_PATH}/numpy")
# message(WARNING "PYTHON_NUMPY_PATH is invalid, numpy not found in '${PYTHON_NUMPY_PATH}' "
@@ -2007,6 +2088,13 @@ 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)
+endif()
+
# Include warnings first, so its possible to disable them with user defined flags
# eg: -Wno-uninitialized
set(CMAKE_C_FLAGS "${C_WARNINGS} ${CMAKE_C_FLAGS} ${PLATFORM_CFLAGS}")
@@ -2130,6 +2218,9 @@ if(FIRST_RUN)
info_cfg_option(WITH_PYTHON_INSTALL_NUMPY)
info_cfg_option(WITH_PYTHON_MODULE)
info_cfg_option(WITH_PYTHON_SAFETY)
+ if(APPLE)
+ info_cfg_option(WITH_PYTHON_FRAMEWORK)
+ endif()
info_cfg_text("Modifiers:")
info_cfg_option(WITH_MOD_BOOLEAN)
@@ -2137,6 +2228,9 @@ if(FIRST_RUN)
info_cfg_option(WITH_MOD_FLUID)
info_cfg_option(WITH_MOD_OCEANSIM)
+ # debug
+ message(STATUS "HAVE_STDBOOL_H = ${HAVE_STDBOOL_H}")
+
info_cfg_text("")
message("${_config_msg}")
diff --git a/SConstruct b/SConstruct
index c2bae0459ca..03cfe3ed4ca 100644
--- a/SConstruct
+++ b/SConstruct
@@ -14,7 +14,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# The Original Code is Copyright (C) 2006, Blender Foundation
# All rights reserved.
@@ -269,12 +269,18 @@ if 'blenderlite' in B.targets:
target_env_defs['WITH_BF_PYTHON'] = False
target_env_defs['WITH_BF_3DMOUSE'] = False
target_env_defs['WITH_BF_LIBMV'] = False
+ target_env_defs['WITH_BF_FREESTYLE'] = False
# Merge blenderlite, let command line to override
for k,v in target_env_defs.iteritems():
if k not in B.arguments:
env[k] = v
+if 'cudakernels' in B.targets:
+ env['WITH_BF_CYCLES'] = True
+ env['WITH_BF_CYCLES_CUDA_BINARIES'] = True
+ env['WITH_BF_PYTHON'] = False
+
# Extended OSX_SDK and 3D_CONNEXION_CLIENT_LIBRARY and JAckOSX detection for OSX
if env['OURPLATFORM']=='darwin':
print B.bc.OKGREEN + "Detected Xcode version: -- " + B.bc.ENDC + env['XCODE_CUR_VER'] + " --"
@@ -294,7 +300,8 @@ if env['OURPLATFORM']=='darwin':
print "3D_CONNEXION_CLIENT_LIBRARY not found, disabling WITH_BF_3DMOUSE" # avoid build errors !
env['WITH_BF_3DMOUSE'] = 0
else:
- env.Append(LINKFLAGS=['-Xlinker','-weak_framework','-Xlinker','3DconnexionClient'])
+ env.Append(LINKFLAGS=['-F/Library/Frameworks','-Xlinker','-weak_framework','-Xlinker','3DconnexionClient'])
+ env['BF_3DMOUSE_INC'] = '/Library/Frameworks/3DconnexionClient.framework/Headers'
# for now, Mac builders must download and install the JackOSX framework
# necessary header file lives here when installed:
@@ -304,7 +311,7 @@ if env['OURPLATFORM']=='darwin':
print "JackOSX install not found, disabling WITH_BF_JACK" # avoid build errors !
env['WITH_BF_JACK'] = 0
else:
- env.Append(LINKFLAGS=['-Xlinker','-weak_framework','-Xlinker','Jackmp'])
+ env.Append(LINKFLAGS=['-L/Library/Frameworks','-Xlinker','-weak_framework','-Xlinker','Jackmp'])
if env['WITH_BF_CYCLES_OSL'] == 1:
OSX_OSL_LIBPATH = Dir(env.subst(env['BF_OSL_LIBPATH'])).abspath
@@ -372,9 +379,13 @@ if btools.ENDIAN == "big":
else:
env['CPPFLAGS'].append('-D__LITTLE_ENDIAN__')
-# TODO, make optional
+# TODO, make optional (as with CMake)
env['CPPFLAGS'].append('-DWITH_AUDASPACE')
env['CPPFLAGS'].append('-DWITH_AVI')
+env['CPPFLAGS'].append('-DWITH_BOOL_COMPAT')
+
+if env['OURPLATFORM'] not in ('win32-vc', 'win64-vc'):
+ env['CPPFLAGS'].append('-DHAVE_STDBOOL_H')
# 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']
@@ -441,11 +452,12 @@ if env['WITH_BF_PYTHON']:
found_pyconfig_h = True
if not (found_python_h and found_pyconfig_h):
- print("\nMissing: Python.h and/or pyconfig.h in\"" + env.subst('${BF_PYTHON_INC}') + "\",\n"
- " Set 'BF_PYTHON_INC' to point "
- "to valid python include path(s).\n Containing "
- "Python.h and pyconfig.h for python version \"" + env.subst('${BF_PYTHON_VERSION}') + "\"")
+ print("""\nMissing: Python.h and/or pyconfig.h in "%s"
+ Set 'BF_PYTHON_INC' to point to valid include path(s),
+ containing Python.h and pyconfig.h for Python version "%s".
+ Example: python scons/scons.py BF_PYTHON_INC=../Python/include
+ """ % (env.subst('${BF_PYTHON_INC}'), env.subst('${BF_PYTHON_VERSION}')))
Exit()
@@ -509,61 +521,91 @@ def data_to_c_simple(FILE_FROM):
data_to_c(FILE_FROM, FILE_TO, VAR_NAME)
-data_to_c("source/blender/compositor/operations/COM_OpenCLKernels.cl",
- B.root_build_dir + "data_headers/COM_OpenCLKernels.cl.h",
- "datatoc_COM_OpenCLKernels_cl")
-
-data_to_c_simple("release/datafiles/startup.blend")
-data_to_c_simple("release/datafiles/preview.blend")
-
-# --- glsl ---
-data_to_c_simple("source/blender/gpu/shaders/gpu_shader_material.glsl")
-data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vertex.glsl")
-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_material.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")
-
-# --- blender ---
-data_to_c_simple("release/datafiles/bfont.pfb")
-data_to_c_simple("release/datafiles/bfont.ttf")
-data_to_c_simple("release/datafiles/bmonofont.ttf")
-
-data_to_c_simple("release/datafiles/splash.png")
-data_to_c_simple("release/datafiles/blender_icons.png")
-data_to_c_simple("release/datafiles/prvicons.png")
-
-data_to_c_simple("release/datafiles/brushicons/add.png")
-data_to_c_simple("release/datafiles/brushicons/blob.png")
-data_to_c_simple("release/datafiles/brushicons/blur.png")
-data_to_c_simple("release/datafiles/brushicons/clay.png")
-data_to_c_simple("release/datafiles/brushicons/claystrips.png")
-data_to_c_simple("release/datafiles/brushicons/clone.png")
-data_to_c_simple("release/datafiles/brushicons/crease.png")
-data_to_c_simple("release/datafiles/brushicons/darken.png")
-data_to_c_simple("release/datafiles/brushicons/draw.png")
-data_to_c_simple("release/datafiles/brushicons/fill.png")
-data_to_c_simple("release/datafiles/brushicons/flatten.png")
-data_to_c_simple("release/datafiles/brushicons/grab.png")
-data_to_c_simple("release/datafiles/brushicons/inflate.png")
-data_to_c_simple("release/datafiles/brushicons/layer.png")
-data_to_c_simple("release/datafiles/brushicons/lighten.png")
-data_to_c_simple("release/datafiles/brushicons/mask.png")
-data_to_c_simple("release/datafiles/brushicons/mix.png")
-data_to_c_simple("release/datafiles/brushicons/multiply.png")
-data_to_c_simple("release/datafiles/brushicons/nudge.png")
-data_to_c_simple("release/datafiles/brushicons/pinch.png")
-data_to_c_simple("release/datafiles/brushicons/scrape.png")
-data_to_c_simple("release/datafiles/brushicons/smear.png")
-data_to_c_simple("release/datafiles/brushicons/smooth.png")
-data_to_c_simple("release/datafiles/brushicons/snake_hook.png")
-data_to_c_simple("release/datafiles/brushicons/soften.png")
-data_to_c_simple("release/datafiles/brushicons/subtract.png")
-data_to_c_simple("release/datafiles/brushicons/texdraw.png")
-data_to_c_simple("release/datafiles/brushicons/thumb.png")
-data_to_c_simple("release/datafiles/brushicons/twist.png")
-data_to_c_simple("release/datafiles/brushicons/vertexdraw.png")
+if B.targets != ['cudakernels']:
+ data_to_c("source/blender/compositor/operations/COM_OpenCLKernels.cl",
+ B.root_build_dir + "data_headers/COM_OpenCLKernels.cl.h",
+ "datatoc_COM_OpenCLKernels_cl")
+
+ data_to_c_simple("release/datafiles/startup.blend")
+ data_to_c_simple("release/datafiles/preview.blend")
+ data_to_c_simple("release/datafiles/preview_cycles.blend")
+
+ # --- 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")
+ data_to_c_simple("source/blender/gpu/shaders/gpu_shader_material.glsl")
+ 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_vsm_store_frag.glsl")
+ data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl")
+
+ # --- blender ---
+ data_to_c_simple("release/datafiles/bfont.pfb")
+ data_to_c_simple("release/datafiles/bfont.ttf")
+ data_to_c_simple("release/datafiles/bmonofont.ttf")
+
+ data_to_c_simple("release/datafiles/splash.png")
+ data_to_c_simple("release/datafiles/blender_icons16.png")
+ data_to_c_simple("release/datafiles/blender_icons32.png")
+ data_to_c_simple("release/datafiles/prvicons.png")
+
+ data_to_c_simple("release/datafiles/brushicons/add.png")
+ data_to_c_simple("release/datafiles/brushicons/blob.png")
+ data_to_c_simple("release/datafiles/brushicons/blur.png")
+ data_to_c_simple("release/datafiles/brushicons/clay.png")
+ data_to_c_simple("release/datafiles/brushicons/claystrips.png")
+ data_to_c_simple("release/datafiles/brushicons/clone.png")
+ data_to_c_simple("release/datafiles/brushicons/crease.png")
+ data_to_c_simple("release/datafiles/brushicons/darken.png")
+ data_to_c_simple("release/datafiles/brushicons/draw.png")
+ data_to_c_simple("release/datafiles/brushicons/fill.png")
+ data_to_c_simple("release/datafiles/brushicons/flatten.png")
+ data_to_c_simple("release/datafiles/brushicons/grab.png")
+ data_to_c_simple("release/datafiles/brushicons/inflate.png")
+ data_to_c_simple("release/datafiles/brushicons/layer.png")
+ data_to_c_simple("release/datafiles/brushicons/lighten.png")
+ data_to_c_simple("release/datafiles/brushicons/mask.png")
+ data_to_c_simple("release/datafiles/brushicons/mix.png")
+ data_to_c_simple("release/datafiles/brushicons/multiply.png")
+ data_to_c_simple("release/datafiles/brushicons/nudge.png")
+ data_to_c_simple("release/datafiles/brushicons/pinch.png")
+ data_to_c_simple("release/datafiles/brushicons/scrape.png")
+ data_to_c_simple("release/datafiles/brushicons/smear.png")
+ data_to_c_simple("release/datafiles/brushicons/smooth.png")
+ data_to_c_simple("release/datafiles/brushicons/snake_hook.png")
+ data_to_c_simple("release/datafiles/brushicons/soften.png")
+ data_to_c_simple("release/datafiles/brushicons/subtract.png")
+ data_to_c_simple("release/datafiles/brushicons/texdraw.png")
+ data_to_c_simple("release/datafiles/brushicons/thumb.png")
+ data_to_c_simple("release/datafiles/brushicons/twist.png")
+ data_to_c_simple("release/datafiles/brushicons/vertexdraw.png")
+
+ data_to_c_simple("release/datafiles/matcaps/mc01.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc02.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc03.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc04.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc05.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc06.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc07.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc08.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc09.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc10.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc11.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc12.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc13.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc14.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc15.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc16.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc17.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc18.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc19.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc20.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc21.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc22.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc23.jpg")
+ data_to_c_simple("release/datafiles/matcaps/mc24.jpg")
##### END DATAFILES ##########
@@ -647,6 +689,7 @@ datafileslist = []
datafilestargetlist = []
dottargetlist = []
scriptinstall = []
+cubininstall = []
if env['OURPLATFORM']!='darwin':
dotblenderinstall = []
@@ -673,6 +716,10 @@ if env['OURPLATFORM']!='darwin':
if VERSION_RELEASE_CYCLE == "release" and "addons_contrib" in dn:
dn.remove('addons_contrib')
+ # do not install freestyle if disabled
+ if not env['WITH_BF_FREESTYLE'] and "freestyle" in dn:
+ dn.remove("freestyle")
+
dir = os.path.join(env['BF_INSTALLDIR'], VERSION)
dir += os.sep + os.path.basename(scriptpath) + dp[len(scriptpath):]
@@ -736,29 +783,30 @@ if env['OURPLATFORM']!='darwin':
source=['intern/cycles/doc/license/'+s for s in source]
scriptinstall.append(env.Install(dir=dir,source=source))
- # cuda binaries
- if env['WITH_BF_CYCLES_CUDA_BINARIES']:
- dir=os.path.join(env['BF_INSTALLDIR'], VERSION, 'scripts', 'addons','cycles', 'lib')
- for arch in env['BF_CYCLES_CUDA_BINARIES_ARCH']:
- kernel_build_dir = os.path.join(B.root_build_dir, 'intern/cycles/kernel')
- cubin_file = os.path.join(kernel_build_dir, "kernel_%s.cubin" % arch)
- scriptinstall.append(env.Install(dir=dir,source=cubin_file))
+ if env['WITH_BF_CYCLES']:
+ # cuda binaries
+ if env['WITH_BF_CYCLES_CUDA_BINARIES']:
+ dir=os.path.join(env['BF_INSTALLDIR'], VERSION, 'scripts', 'addons','cycles', 'lib')
+ for arch in env['BF_CYCLES_CUDA_BINARIES_ARCH']:
+ kernel_build_dir = os.path.join(B.root_build_dir, 'intern/cycles/kernel')
+ cubin_file = os.path.join(kernel_build_dir, "kernel_%s.cubin" % arch)
+ cubininstall.append(env.Install(dir=dir,source=cubin_file))
- # osl shaders
- if env['WITH_BF_CYCLES_OSL']:
- dir=os.path.join(env['BF_INSTALLDIR'], VERSION, 'scripts', 'addons','cycles', 'shader')
+ # osl shaders
+ if env['WITH_BF_CYCLES_OSL']:
+ dir=os.path.join(env['BF_INSTALLDIR'], VERSION, 'scripts', 'addons','cycles', 'shader')
- osl_source_dir = Dir('./intern/cycles/kernel/shaders').srcnode().path
- oso_build_dir = os.path.join(B.root_build_dir, 'intern/cycles/kernel/shaders')
+ osl_source_dir = Dir('./intern/cycles/kernel/shaders').srcnode().path
+ oso_build_dir = os.path.join(B.root_build_dir, 'intern/cycles/kernel/shaders')
- headers='node_color.h node_fresnel.h node_texture.h oslutil.h stdosl.h'.split()
- source=['intern/cycles/kernel/shaders/'+s for s in headers]
- scriptinstall.append(env.Install(dir=dir,source=source))
+ headers='node_color.h node_fresnel.h node_texture.h oslutil.h stdosl.h'.split()
+ source=['intern/cycles/kernel/shaders/'+s for s in headers]
+ scriptinstall.append(env.Install(dir=dir,source=source))
- for f in os.listdir(osl_source_dir):
- if f.endswith('.osl'):
- oso_file = os.path.join(oso_build_dir, f.replace('.osl', '.oso'))
- scriptinstall.append(env.Install(dir=dir,source=oso_file))
+ for f in os.listdir(osl_source_dir):
+ if f.endswith('.osl'):
+ oso_file = os.path.join(oso_build_dir, f.replace('.osl', '.oso'))
+ scriptinstall.append(env.Install(dir=dir,source=oso_file))
if env['WITH_BF_OCIO']:
colormanagement = os.path.join('release', 'datafiles', 'colormanagement')
@@ -827,6 +875,8 @@ if env['OURPLATFORM']=='linux':
td, tf = os.path.split(targetdir)
iconinstall.append(env.Install(dir=td, source=srcfile))
+ scriptinstall.append(env.Install(dir=env['BF_INSTALLDIR'], source='release/bin/blender-thumbnailer.py'))
+
# dlls for linuxcross
# TODO - add more libs, for now this lets blenderlite run
if env['OURPLATFORM']=='linuxcross':
@@ -853,9 +903,9 @@ textinstall = env.Install(dir=env['BF_INSTALLDIR'], source=textlist)
if env['OURPLATFORM']=='darwin':
allinstall = [blenderinstall, textinstall]
elif env['OURPLATFORM']=='linux':
- allinstall = [blenderinstall, dotblenderinstall, scriptinstall, textinstall, iconinstall]
+ allinstall = [blenderinstall, dotblenderinstall, scriptinstall, textinstall, iconinstall, cubininstall]
else:
- allinstall = [blenderinstall, dotblenderinstall, scriptinstall, textinstall]
+ allinstall = [blenderinstall, dotblenderinstall, scriptinstall, textinstall, cubininstall]
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'):
dllsources = []
@@ -985,6 +1035,20 @@ buildslave_alias = env.Alias('buildslave', buildslave_cmd)
Depends(buildslave_cmd, allinstall)
+cudakernels_action = env.Action(btools.cudakernels, btools.cudakernels_print)
+cudakernels_cmd = env.Command('cudakernels_exec', None, cudakernels_action)
+cudakernels_alias = env.Alias('cudakernels', cudakernels_cmd)
+
+cudakernel_dir = os.path.join(os.path.abspath(os.path.normpath(B.root_build_dir)), 'intern/cycles/kernel')
+cuda_kernels = []
+
+for x in env['BF_CYCLES_CUDA_BINARIES_ARCH']:
+ cubin = os.path.join(cudakernel_dir, 'kernel_' + x + '.cubin')
+ cuda_kernels.append(cubin)
+
+Depends(cudakernels_cmd, cuda_kernels)
+Depends(cudakernels_cmd, cubininstall)
+
Default(B.program_list)
if not env['WITHOUT_BF_INSTALL']:
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index 75b07ff73b3..81a12dbf910 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -1,16 +1,37 @@
-#!/bin/bash
+#!/usr/bin/env bash
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public 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 #####
+
+# A shell script installing/building all needed dependencies to build Blender, for some Linux distributions.
# Parse command line!
ARGS=$( \
getopt \
-o s:i:t:h \
---long source:,install:,threads:,help,with-all,with-osl,all-static,force-all,force-python,\
-force-boost,force-ocio,force-oiio,force-llvm,force-osl,force-ffmpeg,\
-skip-python,skip-boost,skip-ocio,skip-oiio,skip-llvm,skip-osl,skip-ffmpeg \
+--long source:,install:,threads:,help,with-all,with-osl,with-opencollada,all-static,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 \
-- "$@" \
)
DISTRO=""
+RPM=""
SRC="$HOME/src/blender-deps"
INST="/opt/lib"
CWD=$PWD
@@ -21,6 +42,9 @@ WITH_ALL=false
# Do not yet enable osl, use --with-osl (or --with-all) option to try it.
WITH_OSL=false
+# Do not yet enable opencollada, use --with-opencollada (or --with-all) option to try it.
+WITH_OPENCOLLADA=false
+
# Try to link everything statically. Use this to produce portable versions of blender.
ALL_STATIC=false
@@ -37,8 +61,12 @@ or use --source/--install options, if you want to use other paths!
Number of threads for building: \$THREADS (automatically detected, use --threads=<nbr> to override it).
Full install: \$WITH_ALL (use --with-all option to enable it).
Building OSL: \$WITH_OSL (use --with-osl option to enable it).
+Building OpenCOLLADA: \$WITH_OPENCOLLADA (use --with-opencollada option to enable it).
All static linking: \$ALL_STATIC (use --all-static option to enable it).
+Example:
+Full install without OpenCOLLADA: --with-all --skip-opencollada
+
Use --help to show all available options!\""
ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
@@ -64,6 +92,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
Try to install or build the OpenShadingLanguage libraries (and their dependencies).
Still experimental!
+ --with-opencollada
+ Build and install the OpenCOLLADA libraries.
+
--all-static
Build libraries as statically as possible, to create static builds of Blender.
@@ -73,6 +104,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--force-python
Force the rebuild of Python.
+ --force-numpy
+ Force the rebuild of NumPy.
+
--force-boost
Force the rebuild of Boost.
@@ -88,6 +122,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--force-osl
Force the rebuild of OpenShadingLanguage.
+ --force-opencollada
+ Force the rebuild of OpenCOLLADA.
+
--force-ffmpeg
Force the rebuild of FFMpeg.
@@ -101,6 +138,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--skip-python
Unconditionally skip Python installation/building.
+ --skip-numpy
+ Unconditionally skip NumPy installation/building.
+
--skip-boost
Unconditionally skip Boost installation/building.
@@ -116,6 +156,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--skip-osl
Unconditionally skip OpenShadingLanguage installation/building.
+ --skip-opencollada
+ Unconditionally skip OpenCOLLADA installation/building.
+
--skip-ffmpeg
Unconditionally skip FFMpeg installation/building.\""
@@ -125,6 +168,12 @@ PYTHON_SOURCE="http://python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSI
PYTHON_FORCE_REBUILD=false
PYTHON_SKIP=false
+NUMPY_VERSION="1.7.0"
+NUMPY_VERSION_MIN="1.7"
+NUMPY_SOURCE="http://sourceforge.net/projects/numpy/files/NumPy/$NUMPY_VERSION/numpy-$NUMPY_VERSION.tar.gz"
+NUMPY_FORCE_REBUILD=false
+NUMPY_SKIP=false
+
BOOST_VERSION="1.51.0"
_boost_version_nodots=`echo "$BOOST_VERSION" | sed -r 's/\./_/g'`
BOOST_SOURCE="http://sourceforge.net/projects/boost/files/boost/$BOOST_VERSION/boost_$_boost_version_nodots.tar.bz2/download"
@@ -138,7 +187,7 @@ OCIO_VERSION_MIN="1.0"
OCIO_FORCE_REBUILD=false
OCIO_SKIP=false
-OIIO_VERSION="1.1.1"
+OIIO_VERSION="1.1.7"
OIIO_SOURCE="https://github.com/OpenImageIO/oiio/tarball/Release-$OIIO_VERSION"
OIIO_VERSION_MIN="1.1"
OIIO_FORCE_REBUILD=false
@@ -153,11 +202,17 @@ LLVM_FORCE_REBUILD=false
LLVM_SKIP=false
# OSL needs to be compiled for now!
-OSL_VERSION="1.2.0"
-OSL_SOURCE="https://github.com/mont29/OpenShadingLanguage/archive/blender-fixes.tar.gz"
+OSL_VERSION="1.3.0"
+OSL_SOURCE="https://github.com/imageworks/OpenShadingLanguage/archive/Release-1.3.0.tar.gz"
OSL_FORCE_REBUILD=false
OSL_SKIP=false
+# Version??
+OPENCOLLADA_VERSION="1.3"
+OPENCOLLADA_SOURCE="https://github.com/KhronosGroup/OpenCOLLADA.git"
+OPENCOLLADA_FORCE_REBUILD=false
+OPENCOLLADA_SKIP=false
+
FFMPEG_VERSION="1.0"
FFMPEG_SOURCE="http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2"
FFMPEG_VERSION_MIN="0.7.6"
@@ -168,8 +223,6 @@ _ffmpeg_list_sep=";"
# FFMPEG optional libs.
VORBIS_USE=false
VORBIS_DEV=""
-SCHRO_USE=false
-SCRHO_DEV=""
THEORA_USE=false
THEORA_DEV=""
XVID_USE=false
@@ -236,22 +289,30 @@ while true; do
--with-osl)
WITH_OSL=true; shift; continue
;;
+ --with-opencollada)
+ WITH_OPENCOLLADA=true; shift; continue
+ ;;
--all-static)
ALL_STATIC=true; shift; continue
;;
--force-all)
PYTHON_FORCE_REBUILD=true
+ NUMPY_FORCE_REBUILD=true
BOOST_FORCE_REBUILD=true
OCIO_FORCE_REBUILD=true
OIIO_FORCE_REBUILD=true
LLVM_FORCE_REBUILD=true
OSL_FORCE_REBUILD=true
+ OPENCOLLADA_FORCE_REBUILD=true
FFMPEG_FORCE_REBUILD=true
shift; continue
;;
--force-python)
PYTHON_FORCE_REBUILD=true; shift; continue
;;
+ --force-numpy)
+ NUMPY_FORCE_REBUILD=true; shift; continue
+ ;;
--force-boost)
BOOST_FORCE_REBUILD=true; shift; continue
;;
@@ -267,12 +328,18 @@ while true; do
--force-osl)
OSL_FORCE_REBUILD=true; shift; continue
;;
+ --force-opencollada)
+ OPENCOLLADA_FORCE_REBUILD=true; shift; continue
+ ;;
--force-ffmpeg)
FFMPEG_FORCE_REBUILD=true; shift; continue
;;
--skip-python)
PYTHON_SKIP=true; shift; continue
;;
+ --skip-numpy)
+ NUMPY_SKIP=true; shift; continue
+ ;;
--skip-boost)
BOOST_SKIP=true; shift; continue
;;
@@ -288,6 +355,9 @@ while true; do
--skip-osl)
OSL_SKIP=true; shift; continue
;;
+ --skip-opencollada)
+ OPENCOLLADA_SKIP=true; shift; continue
+ ;;
--skip-ffmpeg)
FFMPEG_SKIP=true; shift; continue
;;
@@ -308,6 +378,7 @@ done
if $WITH_ALL; then
WITH_OSL=true
+ WITH_OPENCOLLADA=true
fi
# Return 0 if $1 = $2 (i.e. 1.01.0 = 1.1, but 1.1.1 != 1.1), else 1.
@@ -397,10 +468,22 @@ version_match() {
detect_distro() {
if [ -f /etc/debian_version ]; then
DISTRO="DEB"
- elif [ -f /etc/redhat-release ]; then
+ elif [ -f /etc/arch-release ]; then
+ DISTRO="ARCH"
+ elif [ -f /etc/redhat-release -o /etc/SuSE-release ]; then
DISTRO="RPM"
+ fi
+}
+
+rpm_flavour() {
+ if [ -f /etc/redhat-release ]; then
+ if [ "`grep '6\.' /etc/redhat-release`" ]; then
+ RPM="RHEL"
+ else
+ RPM="FEDORA"
+ fi
elif [ -f /etc/SuSE-release ]; then
- DISTRO="SUSE"
+ RPM="SUSE"
fi
}
@@ -483,6 +566,56 @@ compile_Python() {
fi
}
+compile_Numpy() {
+ # To be changed each time we make edits that would modify the compiled result!
+ py_magic=0
+
+ _src=$SRC/numpy-$NUMPY_VERSION
+ _inst=$INST/numpy-$NUMPY_VERSION
+ _python=$INST/python-$PYTHON_VERSION
+ _site=lib/python3.3/site-packages
+
+ # Clean install if needed!
+ magic_compile_check numpy-$NUMPY_VERSION $py_magic
+ if [ $? -eq 1 -o $NUMPY_FORCE_REBUILD == true ]; then
+ rm -rf $_inst
+ fi
+
+ if [ ! -d $_inst ]; then
+ INFO "Building Numpy-$NUMPY_VERSION"
+
+ prepare_opt
+
+ if [ ! -d $_src ]; then
+ mkdir -p $SRC
+ wget -c $NUMPY_SOURCE -O $_src.tar.gz
+
+ INFO "Unpacking Numpy-$NUMPY_VERSION"
+ tar -C $SRC -xf $_src.tar.gz
+ fi
+
+ cd $_src
+
+ $_python/bin/python3 setup.py install --prefix=$_inst
+
+ if [ -d $_inst ]; then
+ rm -f $_python/$_site/numpy
+ ln -s $_inst/$_site/numpy $_python/$_site/numpy
+ else
+ ERROR "Numpy-$NUMPY_VERSION failed to compile, exiting"
+ exit 1
+ fi
+
+ magic_compile_set numpy-$NUMPY_VERSION $py_magic
+
+ cd $CWD
+ INFO "Done compiling Numpy-$NUMPY_VERSION!"
+ else
+ INFO "Own Numpy-$NUMPY_VERSION is up to date, nothing to do!"
+ INFO "If you want to force rebuild of this lib, use the --force-numpy option."
+ fi
+}
+
compile_Boost() {
# To be changed each time we make edits that would modify the compiled result!
boost_magic=7
@@ -620,7 +753,7 @@ compile_OCIO() {
compile_OIIO() {
# To be changed each time we make edits that would modify the compiled result!
- oiio_magic=6
+ oiio_magic=7
_src=$SRC/OpenImageIO-$OIIO_VERSION
_inst=$INST/oiio-$OIIO_VERSION
@@ -644,27 +777,6 @@ compile_OIIO() {
tar -C $SRC --transform "s,(.*/?)OpenImageIO-oiio[^/]*(.*),\1OpenImageIO-$OIIO_VERSION\2,x" \
-xf $_src.tar.gz
- cd $_src
-
- # XXX Ugly patching hack!
- cat << EOF | patch -p1
-diff --git a/src/libutil/SHA1.cpp b/src/libutil/SHA1.cpp
-index b9e6c8b..c761185 100644
---- a/src/libutil/SHA1.cpp
-+++ b/src/libutil/SHA1.cpp
-@@ -8,9 +8,9 @@
-
- // If compiling with MFC, you might want to add #include "StdAfx.h"
-
-+#include "SHA1.h"
- #include "hash.h"
- #include "dassert.h"
--#include "SHA1.h"
-
- #ifdef SHA1_UTILITY_FUNCTIONS
- #define SHA1_MAX_FILE_BUFFER 8000
-EOF
-
cd $CWD
fi
@@ -681,6 +793,11 @@ EOF
cmake_d="$cmake_d -D CMAKE_PREFIX_PATH=$_inst"
cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
cmake_d="$cmake_d -D BUILDSTATIC=ON"
+
+ # Optional tests and cmd tools
+ cmake_d="$cmake_d -D USE_QT=OFF"
+ cmake_d="$cmake_d -D OIIO_BUILD_TOOLS=OFF"
+ cmake_d="$cmake_d -D OIIO_BUILD_TESTS=OFF"
# linking statically could give issues on Debian/Ubuntu (and probably other distros
# which doesn't like static linking) when linking shared oiio library due to missing
@@ -797,6 +914,7 @@ EOF
cmake_d="-D CMAKE_BUILD_TYPE=Release"
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"
if [ -d $_FFI_INCLUDE_DIR ]; then
cmake_d="$cmake_d -D FFI_INCLUDE_DIR=$_FFI_INCLUDE_DIR"
@@ -920,6 +1038,74 @@ compile_OSL() {
fi
}
+compile_OpenCOLLADA() {
+ # To be changed each time we make edits that would modify the compiled results!
+ opencollada_magic=5
+
+ _src=$SRC/OpenCOLLADA-$OPENCOLLADA_VERSION
+ _inst=$INST/opencollada-$OPENCOLLADA_VERSION
+
+ # Clean install if needed!
+ magic_compile_check opencollada-$OPENCOLLADA_VERSION $opencollada_magic
+ if [ $? -eq 1 -o $OPENCOLLADA_FORCE_REBUILD == true ]; then
+ rm -rf $_inst
+ fi
+
+ if [ ! -d $_inst ]; then
+ INFO "Building OpenCOLLADA-$OPENCOLLADA_VERSION"
+
+ prepare_opt
+
+ if [ ! -d $_src ]; then
+ mkdir -p $SRC
+ git clone $OPENCOLLADA_SOURCE $_src
+ fi
+
+ cd $_src
+
+ # XXX For now, always update from latest repo...
+ git pull origin master
+
+ # XXX We have to stick to this revision, the next one introduced a change to ExtraHandler' parseElement signature :/
+ git checkout c89cf095c40aa2a518b1104c448825eacc92d174
+ git reset --hard
+
+ # 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"
+ cmake_d="$cmake_d -D USE_EXPAT=OFF"
+ cmake_d="$cmake_d -D USE_LIBXML=ON"
+ cmake_d="$cmake_d -D USE_STATIC=ON"
+
+ cmake $cmake_d ../
+
+ make -j$THREADS && make install
+ make clean
+
+ if [ -d $_inst ]; then
+ rm -f $INST/opencollada
+ ln -s opencollada-$OPENCOLLADA_VERSION $INST/opencollada
+ else
+ ERROR "OpenCOLLADA-$OPENCOLLADA_VERSION failed to compile, exiting"
+ exit 1
+ fi
+
+ magic_compile_set opencollada-$OPENCOLLADA_VERSION $opencollada_magic
+
+ cd $CWD
+ INFO "Done compiling OpenCOLLADA-$OPENCOLLADA_VERSION!"
+ else
+ INFO "Own OpenCOLLADA-$OPENCOLLADA_VERSION is up to date, nothing to do!"
+ INFO "If you want to force rebuild of this lib, use the --force-opencollada option."
+ fi
+}
+
compile_FFmpeg() {
# To be changed each time we make edits that would modify the compiled result!
ffmpeg_magic=3
@@ -959,11 +1145,6 @@ compile_FFmpeg() {
extra="$extra --enable-libtheora"
fi
- # XXX At least under Debian, static schro gives problem at blender linking time... :/
- if $SCHRO_USE && ! $ALL_STATIC; then
- extra="$extra --enable-libschroedinger"
- fi
-
if $XVID_USE; then
extra="$extra --enable-libxvid"
fi
@@ -992,9 +1173,9 @@ compile_FFmpeg() {
--enable-avfilter --disable-vdpau \
--disable-bzlib --disable-libgsm --disable-libspeex \
--enable-pthreads --enable-zlib --enable-stripping --enable-runtime-cpudetect \
- --disable-vaapi --disable-libfaac --disable-nonfree --enable-gpl \
- --disable-postproc --disable-x11grab --disable-librtmp --disable-libopencore-amrnb \
- --disable-libopencore-amrwb --disable-libdc1394 --disable-version3 --disable-outdev=sdl \
+ --disable-vaapi --disable-libfaac --disable-nonfree --enable-gpl \
+ --disable-postproc --disable-x11grab --disable-librtmp --disable-libopencore-amrnb \
+ --disable-libopencore-amrwb --disable-libdc1394 --disable-version3 --disable-outdev=sdl \
--disable-outdev=alsa --disable-indev=sdl --disable-indev=alsa --disable-indev=jack \
--disable-indev=lavfi $extra
@@ -1019,6 +1200,8 @@ compile_FFmpeg() {
fi
}
+
+
get_package_version_DEB() {
dpkg-query -W -f '${Version}' $1 | sed -r 's/.*:\s*([0-9]+:)(([0-9]+\.?)+).*/\2/'
}
@@ -1056,7 +1239,7 @@ check_package_version_ge_DEB() {
}
install_packages_DEB() {
- sudo apt-get install -y $@
+ sudo apt-get install -y --force-yes $@
if [ $? -ge 1 ]; then
ERROR "apt-get failed to install requested packages, exiting."
exit 1
@@ -1070,6 +1253,9 @@ install_DEB() {
INFO "`eval _echo "$COMMON_INFO"`"
INFO ""
+ read -p "Do you want to continue (Y/n)?"
+ [ "$(echo ${REPLY:=Y} | tr [:upper:] [:lower:])" != "y" ] && exit
+
if [ ! -z "`cat /etc/debian_version | grep ^6`" ]; then
if [ -z "`cat /etc/apt/sources.list | grep backports.debian.org`" ]; then
INFO "Looks like you're using Debian Squeeze which does have broken CMake"
@@ -1095,27 +1281,37 @@ install_DEB() {
fi
sudo apt-get update
-# XXX Why in hell? Let's let this stuff to the user's responsability!!!
-# sudo apt-get -y upgrade
# These libs should always be available in debian/ubuntu official repository...
OPENJPEG_DEV="libopenjpeg-dev"
- SCHRO_DEV="libschroedinger-dev"
VORBIS_DEV="libvorbis-dev"
THEORA_DEV="libtheora-dev"
- _packages="gawk cmake scons build-essential libjpeg-dev libpng-dev libtiff-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 \
- libopenexr-dev libopenal-dev libglew-dev yasm $THEORA_DEV \
- $VORBIS_DEV libsdl1.2-dev libfftw3-dev python-dev patch bzip2"
+ libopenexr-dev libopenal-dev libglew-dev yasm $THEORA_DEV $VORBIS_DEV \
+ libsdl1.2-dev libfftw3-dev patch bzip2"
+
OPENJPEG_USE=true
VORBIS_USE=true
THEORA_USE=true
+ # Install newest libtiff-dev in debian/ubuntu.
+ TIFF="libtiff5"
+ check_package_DEB $TIFF
+ if [ $? -eq 0 ]; then
+ _packages="$_packages $TIFF-dev"
+ else
+ TIFF="libtiff"
+ check_package_DEB $TIFF
+ if [ $? -eq 0 ]; then
+ _packages="$_packages $TIFF-dev"
+ fi
+ fi
+
if $WITH_ALL; then
- _packages="$_packages $SCHRO_DEV libjack0 libjack-dev"
- SCHRO_USE=true
+ _packages="$_packages libspnav-dev libjack-dev"
fi
INFO ""
@@ -1132,6 +1328,7 @@ install_DEB() {
if $WITH_ALL; then
INFO ""
# Grmpf, debian is libxvidcore-dev and ubuntu libxvidcore4-dev!
+ # Note: not since ubuntu 10.04
XVID_DEV="libxvidcore-dev"
check_package_DEB $XVID_DEV
if [ $? -eq 0 ]; then
@@ -1161,23 +1358,34 @@ install_DEB() {
install_packages_DEB $VPX_DEV
VPX_USE=true
fi
-
- INFO ""
- check_package_DEB libspnav-dev
- if [ $? -eq 0 ]; then
- install_packages_DEB libspnav-dev
- fi
fi
INFO ""
if $PYTHON_SKIP; then
INFO "WARNING! Skipping Python installation, as requested..."
else
- check_package_DEB python3.3-dev
+ check_package_DEB python$PYTHON_VERSION_MIN-dev
if [ $? -eq 0 ]; then
- install_packages_DEB python3.3-dev
+ install_packages_DEB python$PYTHON_VERSION_MIN-dev
+ INFO ""
+ if $NUMPY_SKIP; then
+ INFO "WARNING! Skipping NumPy installation, as requested..."
+ else
+ check_package_DEB python$PYTHON_VERSION_MIN-numpy
+ if [ $? -eq 0 ]; then
+ install_packages_DEB python$PYTHON_VERSION_MIN-numpy
+ else
+ INFO "WARNING! Sorry, using python package but no numpy package available!"
+ fi
+ fi
else
compile_Python
+ INFO ""
+ if $NUMPY_SKIP; then
+ INFO "WARNING! Skipping NumPy installation, as requested..."
+ else
+ compile_Numpy
+ fi
fi
fi
@@ -1237,17 +1445,19 @@ install_DEB() {
INFO ""
check_package_DEB llvm-$LLVM_VERSION-dev
if [ $? -eq 0 ]; then
- install_packages_DEB llvm-$LLVM_VERSION-dev
+ install_packages_DEB llvm-$LLVM_VERSION-dev clang
have_llvm=true
LLVM_VERSION_FOUND=$LLVM_VERSION
else
check_package_DEB llvm-$LLVM_VERSION_MIN-dev
if [ $? -eq 0 ]; then
- install_packages_DEB llvm-$LLVM_VERSION_MIN-dev
+ install_packages_DEB llvm-$LLVM_VERSION_MIN-dev clang
have_llvm=true
LLVM_VERSION_FOUND=$LLVM_VERSION_MIN
else
install_packages_DEB libffi-dev
+ # LLVM can't find the debian ffi header dir
+ _FFI_INCLUDE_DIR=`dpkg -L libffi-dev | grep -e ".*/ffi.h" | sed -r 's/(.*)\/ffi.h/\1/'`
INFO ""
compile_LLVM
have_llvm=true
@@ -1257,12 +1467,11 @@ install_DEB() {
fi
if $OSL_SKIP; then
- INFO ""
INFO "WARNING! Skipping OpenShadingLanguage installation, as requested..."
else
if $have_llvm; then
INFO ""
- install_packages_DEB clang flex bison libtbb-dev git
+ install_packages_DEB flex bison libtbb-dev git
# No package currently!
INFO ""
compile_OSL
@@ -1270,6 +1479,19 @@ install_DEB() {
fi
fi
+ if $WITH_OPENCOLLADA; then
+ if $OPENCOLLADA_SKIP; then
+ INFO "WARNING! Skipping OpenCOLLADA installation, as requested..."
+ else
+ INFO ""
+ install_packages_DEB git libpcre3-dev libxml2-dev
+ # Find path to libxml shared lib...
+ _XML2_LIB=`dpkg -L libxml2-dev | grep -e ".*/libxml2.so"`
+ # No package
+ INFO ""
+ compile_OpenCOLLADA
+ fi
+ fi
INFO ""
if $FFMPEG_SKIP; then
@@ -1294,12 +1516,24 @@ install_DEB() {
fi
}
+
+
get_package_version_RPM() {
- yum info $1 | grep Version | tail -n 1 | sed -r 's/.*:\s+(([0-9]+\.?)+).*/\1/'
+ rpm_flavour
+ if [ $RPM = "FEDORA" -o $RPM = "RHEL" ]; then
+ yum info $1 | grep Version | tail -n 1 | sed -r 's/.*:\s+(([0-9]+\.?)+).*/\1/'
+ elif [ $RPM = "SUSE" ]; then
+ zypper info $1 | grep Version | tail -n 1 | sed -r 's/.*:\s+(([0-9]+\.?)+).*/\1/'
+ fi
}
check_package_RPM() {
- r=`yum info $1 | grep -c 'Summary'`
+ rpm_flavour
+ if [ $RPM = "FEDORA" -o $RPM = "RHEL" ]; then
+ r=`yum info $1 | grep -c 'Summary'`
+ elif [ $RPM = "SUSE" ]; then
+ r=`zypper info $1 | grep -c 'Summary'`
+ fi
if [ $r -ge 1 ]; then
return 0
@@ -1331,10 +1565,20 @@ check_package_version_ge_RPM() {
}
install_packages_RPM() {
- sudo yum install -y $@
- if [ $? -ge 1 ]; then
- ERROR "yum failed to install requested packages, exiting."
- exit 1
+ rpm_flavour
+ if [ $RPM = "FEDORA" -o $RPM = "RHEL" ]; then
+ sudo yum install -y $@
+ if [ $? -ge 1 ]; then
+ ERROR "yum failed to install requested packages, exiting."
+ exit 1
+ fi
+
+ elif [ $RPM = "SUSE" ]; then
+ sudo zypper --non-interactive install --auto-agree-with-licenses $@
+ if [ $? -ge 1 ]; then
+ ERROR "zypper failed to install requested packages, exiting."
+ exit 1
+ fi
fi
}
@@ -1345,48 +1589,139 @@ install_RPM() {
INFO "`eval _echo "$COMMON_INFO"`"
INFO ""
- sudo yum -y update
+ read -p "Do you want to continue (Y/n)?"
+ [ "$(echo ${REPLY:=Y} | tr [:upper:] [:lower:])" != "y" ] && exit
- # These libs should always be available in debian/ubuntu official repository...
+ # Enable non-free repositories for all flavours
+ rpm_flavour
+ if [ $RPM = "FEDORA" ]; then
+ _fedora_rel="`egrep "[0-9]{1,}" /etc/fedora-release -o`"
+ sudo yum -y localinstall --nogpgcheck \
+ http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$_fedora_rel.noarch.rpm \
+ http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$_fedora_rel.noarch.rpm
+
+ sudo yum -y update
+
+ # Install cmake now because of difference with RHEL
+ sudo yum -y install cmake
+
+ elif [ $RPM = "RHEL" ]; then
+ sudo yum -y localinstall --nogpgcheck \
+ http://download.fedoraproject.org/pub/epel/6/$(uname -i)/epel-release-6-8.noarch.rpm \
+ http://download1.rpmfusion.org/free/el/updates/6/$(uname -i)/rpmfusion-free-release-6-1.noarch.rpm \
+ http://download1.rpmfusion.org/nonfree/el/updates/6/$(uname -i)/rpmfusion-nonfree-release-6-1.noarch.rpm
+
+ sudo yum -y update
+
+ # Install cmake 2.8 from other repo
+ mkdir -p $SRC
+ if [ -f $SRC/cmake-2.8.8-4.el6.$(uname -m).rpm ]; then
+ INFO ""
+ INFO "Special cmake already installed"
+ else
+ curl -O ftp://ftp.pbone.net/mirror/atrpms.net/el6-$(uname -i)/atrpms/testing/cmake-2.8.8-4.el6.$(uname -m).rpm
+ mv cmake-2.8.8-4.el6.$(uname -m).rpm $SRC/
+ sudo rpm -ihv $SRC/cmake-2.8.8-4.el6.$(uname -m).rpm
+ fi
+
+ elif [ $RPM = "SUSE" ]; then
+ # Install this now to avoid using the version from packman repository...
+ if $WITH_ALL; then
+ install_packages_RPM libjack-devel
+ fi
+
+ _suse_rel="`grep VERSION /etc/SuSE-release | gawk '{print $3}'`"
+ sudo zypper ar -f http://packman.inode.at/suse/openSUSE_$_suse_rel/ packman
+
+ sudo zypper --non-interactive --gpg-auto-import-keys update --auto-agree-with-licenses
+ fi
+
+ # These libs should always be available in fedora/suse official repository...
OPENJPEG_DEV="openjpeg-devel"
- SCHRO_DEV="schroedinger-devel"
VORBIS_DEV="libvorbis-devel"
THEORA_DEV="libtheora-devel"
- _packages="gawk gcc gcc-c++ cmake scons libpng-devel libtiff-devel freetype-devel \
- libX11-devel libXi-devel wget libsqlite3x-devel ncurses-devel \
- readline-devel $OPENJPEG_DEV openexr-devel openal-soft-devel \
- glew-devel yasm $THEORA_DEV $VORBIS_DEV SDL-devel fftw-devel \
- lame-libs libjpeg-devel patch python-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 \
+ glew-devel yasm $THEORA_DEV $VORBIS_DEV patch"
+
OPENJPEG_USE=true
VORBIS_USE=true
THEORA_USE=true
- if $WITH_ALL; then
- _packages="$_packages $SCHRO_DEV jack-audio-connection-kit-devel libspnav-devel"
- SCHRO_USE=true
- fi
+ if [ $RPM = "FEDORA" -o $RPM = "RHEL" ]; then
- INFO ""
- install_packages_RPM $_packages
+ _packages="$_packages libsqlite3x-devel openexr-devel fftw-devel SDL-devel"
- INFO ""
- X264_DEV="x264-devel"
- check_package_version_ge_RPM $X264_DEV $X264_VERSION_MIN
- if [ $? -eq 0 ]; then
- install_packages_RPM $X264_DEV
- X264_USE=true
- fi
+ if $WITH_ALL; then
+ _packages="$_packages jack-audio-connection-kit-devel"
+ fi
- if $WITH_ALL; then
INFO ""
- XVID_DEV="xvidcore-devel"
- check_package_RPM $XVID_DEV
+ install_packages_RPM $_packages
+
+ INFO ""
+ X264_DEV="x264-devel"
+ check_package_version_ge_RPM $X264_DEV $X264_VERSION_MIN
if [ $? -eq 0 ]; then
- install_packages_RPM $XVID_DEV
- XVID_USE=true
+ install_packages_RPM $X264_DEV
+ X264_USE=true
+ fi
+
+ if $WITH_ALL; then
+ INFO ""
+ XVID_DEV="xvidcore-devel"
+ check_package_RPM $XVID_DEV
+ if [ $? -eq 0 ]; then
+ install_packages_RPM $XVID_DEV
+ XVID_USE=true
+ fi
+
+ INFO ""
+ MP3LAME_DEV="lame-devel"
+ check_package_RPM $MP3LAME_DEV
+ if [ $? -eq 0 ]; then
+ install_packages_RPM $MP3LAME_DEV
+ MP3LAME_USE=true
+ fi
+ fi
+
+ elif [ $RPM = "SUSE" ]; then
+
+ _packages="$_packages cmake sqlite3-devel libopenexr-devel fftw3-devel libSDL-devel"
+
+ INFO ""
+ install_packages_RPM $_packages
+
+ INFO ""
+ X264_DEV="libx264-devel"
+ check_package_version_ge_RPM $X264_DEV $X264_VERSION_MIN
+ if [ $? -eq 0 ]; then
+ install_packages_RPM $X264_DEV
+ X264_USE=true
fi
+ if $WITH_ALL; then
+ INFO ""
+ XVID_DEV="libxvidcore-devel"
+ check_package_RPM $XVID_DEV
+ if [ $? -eq 0 ]; then
+ install_packages_RPM $XVID_DEV
+ XVID_USE=true
+ fi
+
+ INFO ""
+ MP3LAME_DEV="libmp3lame-devel"
+ check_package_RPM $MP3LAME_DEV
+ if [ $? -eq 0 ]; then
+ install_packages_RPM $MP3LAME_DEV
+ MP3LAME_USE=true
+ fi
+ fi
+ fi
+
+ if $WITH_ALL; then
INFO ""
VPX_DEV="libvpx-devel"
check_package_version_ge_RPM $VPX_DEV $VPX_VERSION_MIN
@@ -1394,14 +1729,8 @@ install_RPM() {
install_packages_RPM $VPX_DEV
VPX_USE=true
fi
-
INFO ""
- MP3LAME_DEV="lame-devel"
- check_package_RPM $MP3LAME_DEV
- if [ $? -eq 0 ]; then
- install_packages_RPM $MP3LAME_DEV
- MP3LAME_USE=true
- fi
+ install_packages_RPM libspnav-devel
fi
INFO ""
@@ -1411,8 +1740,25 @@ install_RPM() {
check_package_version_match_RPM python3-devel $PYTHON_VERSION_MIN
if [ $? -eq 0 ]; then
install_packages_RPM python3-devel
+ INFO ""
+ if $NUMPY_SKIP; then
+ INFO "WARNING! Skipping NumPy installation, as requested..."
+ else
+ check_package_version_match_RPM python3-numpy $NUMPY_VERSION_MIN
+ if [ $? -eq 0 ]; then
+ install_packages_RPM python3-numpy
+ else
+ INFO "WARNING! Sorry, using python package but no numpy package available!"
+ fi
+ fi
else
compile_Python
+ INFO ""
+ if $NUMPY_SKIP; then
+ INFO "WARNING! Skipping NumPy installation, as requested..."
+ else
+ compile_Numpy
+ fi
fi
fi
@@ -1420,7 +1766,7 @@ install_RPM() {
if $BOOST_SKIP; then
INFO "WARNING! Skipping Boost installation, as requested..."
else
- check_package_version_ge_RPM boost-devel $BOOST_VERSION_MIN
+ check_package_version_ge_RPM boost-devel $BOOST_VERSION
if [ $? -eq 0 ]; then
install_packages_RPM boost-devel
else
@@ -1459,32 +1805,27 @@ install_RPM() {
if $LLVM_SKIP; then
INFO "WARNING! Skipping LLVM installation, as requested (this also implies skipping OSL!)..."
else
- check_package_RPM llvm-$LLVM_VERSION-devel
+ # Problem compiling with LLVM 3.2 so match version 3.1 ...
+ check_package_version_match_RPM llvm $LLVM_VERSION
if [ $? -eq 0 ]; then
- install_packages_RPM llvm-$LLVM_VERSION-devel
+ if [ $RPM = "SUSE" ]; then
+ install_packages_RPM llvm-devel llvm-clang-devel
+ else
+ install_packages_RPM llvm-devel clang-devel
+ fi
have_llvm=true
LLVM_VERSION_FOUND=$LLVM_VERSION
else
-# check_package_RPM llvm-$LLVM_VERSION_MIN-devel
-# if [ $? -eq 0 ]; then
-# install_packages_RPM llvm-$LLVM_VERSION_MIN-devel
-# have_llvm=true
-# LLVM_VERSION_FOUND=$LLVM_VERSION_MIN
-# else
-# check_package_version_ge_RPM llvm-devel $LLVM_VERSION_MIN
-# if [ $? -eq 0 ]; then
-# install_packages_RPM llvm-devel
-# have_llvm=true
-# LLVM_VERSION_FOUND=`get_package_version_RPM llvm-devel`
-# fi
-# fi
- install_packages_RPM libffi-devel
- # XXX Stupid fedora puts ffi header into a darn stupid dir!
- _FFI_INCLUDE_DIR=`rpm -ql libffi-devel | grep -e ".*/ffi.h" | sed -r 's/(.*)\/ffi.h/\1/'`
- INFO ""
- compile_LLVM
- have_llvm=true
- LLVM_VERSION_FOUND=$LLVM_VERSION
+ #
+ # Better to compile it than use minimum version from repo...
+ #
+ install_packages_RPM libffi-devel
+ # LLVM can't find the fedora ffi header dir...
+ _FFI_INCLUDE_DIR=`rpm -ql libffi-devel | grep -e ".*/ffi.h" | sed -r 's/(.*)\/ffi.h/\1/'`
+ INFO ""
+ compile_LLVM
+ have_llvm=true
+ LLVM_VERSION_FOUND=$LLVM_VERSION
fi
fi
@@ -1493,30 +1834,52 @@ install_RPM() {
INFO "WARNING! Skipping OpenShadingLanguage installation, as requested..."
else
if $have_llvm; then
- INFO ""
- install_packages_RPM flex bison clang tbb-devel git
# No package currently!
INFO ""
+ install_packages_RPM flex bison git
+ if [ $RPM = "FEDORA" -o $RPM = "RHEL" ]; then
+ install_packages_RPM tbb-devel
+ fi
+ INFO ""
compile_OSL
fi
fi
fi
- INFO ""
+ if $WITH_OPENCOLLADA; then
+ if $OPENCOLLADA_SKIP; then
+ INFO "WARNING! Skipping OpenCOLLADA installation, as requested..."
+ else
+ INFO ""
+ install_packages_RPM pcre-devel libxml2-devel git
+ # Find path to libxml shared lib...
+ _XML2_LIB=`rpm -ql libxml2-devel | grep -e ".*/libxml2.so"`
+ # No package...
+ INFO ""
+ compile_OpenCOLLADA
+ fi
+ fi
+
if $FFMPEG_SKIP; then
INFO "WARNING! Skipping FFMpeg installation, as requested..."
else
- # Always for now, not sure which packages should be installed
- compile_FFmpeg
+ check_package_version_ge_RPM ffmpeg $FFMPEG_VERSION_MIN
+ if [ $? -eq 0 ]; then
+ install_packages_RPM ffmpeg ffmpeg-devel
+ else
+ INFO ""
+ compile_FFmpeg
+ fi
fi
}
-get_package_version_SUSE() {
- zypper info $1 | grep Version | tail -n 1 | sed -r 's/.*:\s+(([0-9]+\.?)+).*/\1/'
+
+get_package_version_ARCH() {
+ pacman -Si $1 | grep Version | tail -n 1 | sed -r 's/.*:\s+(([0-9]+\.?)+).*/\1/'
}
-check_package_SUSE() {
- r=`zypper info $1 | grep -c 'Summary'`
+check_package_ARCH() {
+ r=`pacman -Si $1 | grep -c 'Description'`
if [ $r -ge 1 ]; then
return 0
@@ -1525,8 +1888,8 @@ check_package_SUSE() {
fi
}
-check_package_version_match_SUSE() {
- v=`get_package_version_SUSE $1`
+check_package_version_match_ARCH() {
+ v=`get_package_version_ARCH $1`
if [ -z "$v" ]; then
return 1
@@ -1536,8 +1899,8 @@ check_package_version_match_SUSE() {
return $?
}
-check_package_version_ge_SUSE() {
- v=`get_package_version_SUSE $1`
+check_package_version_ge_ARCH() {
+ v=`get_package_version_ARCH $1`
if [ -z "$v" ]; then
return 1
@@ -1547,79 +1910,88 @@ check_package_version_ge_SUSE() {
return $?
}
-install_packages_SUSE() {
- sudo zypper --non-interactive install --auto-agree-with-licenses $@
+install_packages_ARCH() {
+ sudo pacman -S --needed --noconfirm $@
if [ $? -ge 1 ]; then
- ERROR "zypper failed to install requested packages, exiting."
+ ERROR "pacman failed to install requested packages, exiting."
exit 1
fi
}
-
-install_SUSE() {
+install_ARCH() {
INFO ""
- INFO "Installing dependencies for SuSE-based distribution"
+ INFO "Installing dependencies for ARCH-based distribution"
INFO ""
INFO "`eval _echo "$COMMON_INFO"`"
INFO ""
- sudo zypper --non-interactive update --auto-agree-with-licenses
+ read -p "Do you want to continue (Y/n)?"
+ [ "$(echo ${REPLY:=Y} | tr [:upper:] [:lower:])" != "y" ] && exit
- # These libs should always be available in debian/ubuntu official repository...
- OPENJPEG_DEV="openjpeg-devel"
- SCHRO_DEV="schroedinger-devel"
- VORBIS_DEV="libvorbis-devel"
- THEORA_DEV="libtheora-devel"
+ # Check for sudo...
+ if [ ! -x "/usr/bin/sudo" ]; then
+ INFO ""
+ INFO "This script requires sudo but it is not installed."
+ INFO "Please setup sudo according to:"
+ INFO "https://wiki.archlinux.org/index.php/Sudo"
+ INFO "and try again."
+ INFO ""
+ exit
+ fi
+
+ sudo pacman -Sy
+
+ # These libs should always be available in arch official repository...
+ OPENJPEG_DEV="openjpeg"
+ VORBIS_DEV="libvorbis"
+ THEORA_DEV="libtheora"
+
+ _packages="base-devel scons cmake libxi glew libpng libtiff wget openal \
+ $OPENJPEG_DEV $VORBIS_DEV $THEORA_DEV openexr yasm sdl fftw"
- _packages="gawk gcc gcc-c++ cmake scons libpng12-devel libtiff-devel freetype-devel \
- libX11-devel libXi-devel wget sqlite3-devel ncurses-devel \
- readline-devel $OPENJPEG_DEV libopenexr-devel openal-soft-devel \
- glew-devel yasm $THEORA_DEV $VORBIS_DEV libSDL-devel fftw3-devel \
- libjpeg62-devel patch python-devel"
OPENJPEG_USE=true
VORBIS_USE=true
THEORA_USE=true
if $WITH_ALL; then
- _packages="$_packages $SCHRO_DEV libjack-devel libspnav-devel"
- SCHRO_USE=true
+ # No libspacenav in official arch repos...
+ _packages="$_packages jack"
fi
INFO ""
- install_packages_SUSE $_packages
+ install_packages_ARCH $_packages
INFO ""
- X264_DEV="x264-devel"
- check_package_version_ge_SUSE $X264_DEV $X264_VERSION_MIN
+ X264_DEV="x264"
+ check_package_version_ge_ARCH $X264_DEV $X264_VERSION_MIN
if [ $? -eq 0 ]; then
- install_packages_SUSE $X264_DEV
+ install_packages_ARCH $X264_DEV
X264_USE=true
fi
if $WITH_ALL; then
INFO ""
- XVID_DEV="xvidcore-devel"
- check_package_SUSE $XVID_DEV
+ XVID_DEV="xvidcore"
+ check_package_ARCH $XVID_DEV
if [ $? -eq 0 ]; then
- install_packages_SUSE $XVID_DEV
+ install_packages_ARCH $XVID_DEV
XVID_USE=true
fi
INFO ""
- VPX_DEV="libvpx-devel"
- check_package_version_ge_SUSE $VPX_DEV $VPX_VERSION_MIN
+ MP3LAME_DEV="lame"
+ check_package_ARCH $MP3LAME_DEV
if [ $? -eq 0 ]; then
- install_packages_SUSE $VPX_DEV
- VPX_USE=true
+ install_packages_ARCH $MP3LAME_DEV
+ MP3LAME_USE=true
fi
INFO ""
- # No mp3 in suse, it seems.
- MP3LAME_DEV="lame-devel"
- check_package_SUSE $MP3LAME_DEV
+ VPX_DEV="libvpx"
+ check_package_version_ge_ARCH $VPX_DEV $VPX_VERSION_MIN
if [ $? -eq 0 ]; then
- install_packages_SUSE $MP3LAME_DEV
- MP3LAME_USE=true
+ install_packages_ARCH $VPX_DEV
+ VPX_USE=true
fi
fi
@@ -1627,11 +1999,32 @@ install_SUSE() {
if $PYTHON_SKIP; then
INFO "WARNING! Skipping Python installation, as requested..."
else
- check_package_version_match_SUSE python3-devel 3.3.
+ check_package_version_ge_ARCH python $PYTHON_VERSION_MIN
if [ $? -eq 0 ]; then
- install_packages_SUSE python3-devel
+ install_packages_ARCH python
+ INFO ""
+ if $WITH_NUMPY; then
+ if $NUMPY_SKIP; then
+ INFO "WARNING! Skipping NumPy installation, as requested..."
+ else
+ check_package_version_ge_ARCH python-numpy $NUMPY_VERSION_MIN
+ if [ $? -eq 0 ]; then
+ install_packages_ARCH python-numpy
+ else
+ INFO "WARNING! Sorry, using python package but no numpy package available!"
+ fi
+ fi
+ fi
else
compile_Python
+ INFO ""
+ if $WITH_NUMPY; then
+ if $NUMPY_SKIP; then
+ INFO "WARNING! Skipping NumPy installation, as requested..."
+ else
+ compile_Numpy
+ fi
+ fi
fi
fi
@@ -1639,24 +2032,37 @@ install_SUSE() {
if $BOOST_SKIP; then
INFO "WARNING! Skipping Boost installation, as requested..."
else
- # No boost_locale currently available, so let's build own boost.
- compile_Boost
+ check_package_version_ge_ARCH boost $BOOST_VERSION_MIN
+ if [ $? -eq 0 ]; then
+ install_packages_ARCH boost
+ else
+ compile_Boost
+ fi
fi
INFO ""
if $OCIO_SKIP; then
INFO "WARNING! Skipping OpenColorIO installation, as requested..."
else
- # No ocio currently available, so let's build own boost.
- compile_OCIO
+ check_package_version_ge_ARCH opencolorio $OCIO_VERSION_MIN
+ if [ $? -eq 0 ]; then
+ install_packages_ARCH opencolorio yaml-cpp tinyxml
+ else
+ install_packages_ARCH yaml-cpp tinyxml
+ compile_OCIO
+ fi
fi
INFO ""
if $OIIO_SKIP; then
INFO "WARNING! Skipping OpenImageIO installation, as requested..."
else
- # No oiio currently available, so let's build own boost.
- compile_OIIO
+ check_package_version_ge_ARCH openimageio $OIIO_VERSION_MIN
+ if [ $? -eq 0 ]; then
+ install_packages_ARCH openimageio
+ else
+ compile_OIIO
+ fi
fi
if $WITH_OSL; then
@@ -1666,33 +2072,60 @@ install_SUSE() {
if $LLVM_SKIP; then
INFO "WARNING! Skipping LLVM installation, as requested (this also implies skipping OSL!)..."
else
- # Suse llvm package *_$SUCKS$_* (tm) !!!
-# check_package_version_ge_SUSE llvm-devel $LLVM_VERSION_MIN
-# if [ $? -eq 0 ]; then
-# install_packages_SUSE llvm-devel
-# have_llvm=true
-# LLVM_VERSION_FOUND=`get_package_version_SUSE llvm-devel`
-# fi
-
- install_packages_SUSE libffi47-devel
- INFO ""
- compile_LLVM
- have_llvm=true
- LLVM_VERSION_FOUND=$LLVM_VERSION
+ check_package_version_ge_ARCH llvm $LLVM_VERSION_MIN
+ if [ $? -eq 0 ]; then
+ install_packages_ARCH llvm clang
+ have_llvm=true
+ LLVM_VERSION=`check_package_version_ge_ARCH llvm`
+ LLVM_VERSION_FOUND=$LLVM_VERSION
+ else
+ install_packages_ARCH libffi
+ # LLVM can't find the arch ffi header dir...
+ _FFI_INCLUDE_DIR=`pacman -Ql libffi | grep -e ".*/ffi.h" | awk '{print $2}' | sed -r 's/(.*)\/ffi.h/\1/'`
+ # LLVM 3.1 needs python2 to build and arch defaults to python3
+ _PYTHON2_BIN="/usr/bin/python2"
+ INFO ""
+ compile_LLVM
+ have_llvm=true
+ LLVM_VERSION_FOUND=$LLVM_VERSION
+ fi
fi
if $OSL_SKIP; then
INFO ""
- INFO "WARNING! Skipping OpenShaderLanguage installation, as requested..."
+ INFO "WARNING! Skipping OpenShadingLanguage installation, as requested..."
else
if $have_llvm; then
+ check_package_version_ge_ARCH openshadinglanguage $OSL_VERSION_MIN
+ if [ $? -eq 0 ]; then
+ install_packages_ARCH openshadinglanguage
+ else
+ #XXX Note: will fail to build with LLVM 3.2!
+ INFO ""
+ install_packages_ARCH git intel-tbb
+ INFO ""
+ compile_OSL
+ fi
+ fi
+ fi
+ fi
+
+ INFO ""
+ if $WITH_OPENCOLLADA; then
+ if $OPENCOLLADA_SKIP; then
+ INFO "WARNING! Skipping OpenCOLLADA installation, as requested..."
+ else
+ INFO ""
+ check_package_ARCH opencollada
+ if [ $? -eq 0 ]; then
+ install_packages_ARCH opencollada
+ else
+ install_packages_ARCH pcre git
INFO ""
- # XXX No tbb lib!
- install_packages_SUSE flex bison git
- # No package currently!
- INFO ""
- compile_OSL
+ compile_OpenCOLLADA
fi
+ # Find path to libxml shared lib...
+ _XML2_LIB=`pacman -Ql libxml2 | grep -e ".*/libxml2.so$" | gawk '{print $2}'`
fi
fi
@@ -1700,11 +2133,16 @@ install_SUSE() {
if $FFMPEG_SKIP; then
INFO "WARNING! Skipping FFMpeg installation, as requested..."
else
- # No ffmpeg currently available, so let's build own boost.
- compile_FFmpeg
+ check_package_version_ge_ARCH ffmpeg $FFMPEG_VERSION_MIN
+ if [ $? -eq 0 ]; then
+ install_packages_ARCH ffmpeg
+ else
+ compile_FFmpeg
+ fi
fi
}
+
print_info_ffmpeglink_DEB() {
if $ALL_STATIC; then
dpkg -L $_packages | grep -e ".*\/lib[^\/]\+\.a" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", $0); nlines++ }'
@@ -1714,19 +2152,17 @@ print_info_ffmpeglink_DEB() {
}
print_info_ffmpeglink_RPM() {
- if $ALL_STATIC; then
- rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.a" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", $0); nlines++ }'
- else
- rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.so" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", "g", $0)); nlines++ }'
- fi
+# # XXX No static libs...
+# if $ALL_STATIC; then
+# rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.a" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", $0); nlines++ }'
+# else
+ rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.so" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", "g", $0)); nlines++ }'
+# fi
}
-print_info_ffmpeglink_SUSE() {
- if $ALL_STATIC; then
- rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.a" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", $0); nlines++ }'
- else
- rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.so" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", "g", $0)); nlines++ }'
- fi
+print_info_ffmpeglink_ARCH() {
+# No static libs...
+ pacman -Ql $_packages | grep -e ".*\/lib[^\/]\+\.so$" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", $0)); nlines++ }'
}
print_info_ffmpeglink() {
@@ -1767,17 +2203,12 @@ print_info_ffmpeglink() {
_packages="$_packages $OPENJPEG_DEV"
fi
- # XXX At least under Debian, static schro gives problem at blender linking time... :/
- if $SCHRO_USE && ! $ALL_STATIC; then
- _packages="$_packages $SCHRO_DEV"
- fi
-
if [ "$DISTRO" = "DEB" ]; then
print_info_ffmpeglink_DEB
elif [ "$DISTRO" = "RPM" ]; then
print_info_ffmpeglink_RPM
- elif [ "$DISTRO" = "SUSE" ]; then
- print_info_ffmpeglink_SUSE
+ elif [ "$DISTRO" = "ARCH" ]; then
+ print_info_ffmpeglink_ARCH
# XXX TODO!
else INFO "<Could not determine additional link libraries needed for ffmpeg, replace this by valid list of libs...>"
fi
@@ -1787,57 +2218,140 @@ print_info() {
INFO ""
INFO "If you're using CMake add this to your configuration flags:"
+ _buildargs=""
+
if $ALL_STATIC; then
- INFO " -D WITH_STATIC_LIBS=ON"
+ _1="-D WITH_STATIC_LIBS=ON"
+ # XXX Force linking with shared SDL lib!
+ _2="-D SDL_LIBRARY='libSDL.so;-lpthread'"
+ INFO " $_1"
+ INFO " $_2"
+ _buildargs="$_buildargs $_1 $_2"
+ # XXX Arch linux needs to link freetype dynamically...
+ if [ "$DISTRO" = "ARCH" ]; then
+ _1="-D FREETYPE_LIBRARY=/usr/lib/libfreetype.so"
+ INFO " $_1"
+ _buildargs="$_buildargs $_1"
+ fi
fi
if [ -d $INST/boost ]; then
- INFO " -D BOOST_ROOT=$INST/boost"
- INFO " -D Boost_NO_SYSTEM_PATHS=ON"
+ _1="-D BOOST_ROOT=$INST/boost"
+ _2="-D Boost_NO_SYSTEM_PATHS=ON"
+ INFO " $_1"
+ INFO " $_2"
+ _buildargs="$_buildargs $_1 $_2"
elif $ALL_STATIC; then
- INFO " -D Boost_USE_ICU=ON"
+ _1="-D WITH_BOOST_ICU=ON"
+ INFO " $_1"
+ _buildargs="$_buildargs $_1"
+ # XXX Arch linux fails static linking without these...
+ if [ "$DISTRO" = "ARCH" ]; then
+ _1="-D ICU_LIBRARY_DATA=/usr/lib/libicudata.so"
+ _2="-D ICU_LIBRARY_I18N=/usr/lib/libicui18n.so"
+ _3="-D ICU_LIBRARY_IO=/usr/lib/libicuio.so"
+ _4="-D ICU_LIBRARY_LE=/usr/lib/libicule.so"
+ _5="-D ICU_LIBRARY_LX=/usr/lib/libiculx.so"
+ _6="-D ICU_LIBRARY_TU=/usr/lib/libicutu.so"
+ _7="-D ICU_LIBRARY_UC=/usr/lib/libicuuc.so"
+ INFO " $_1"
+ INFO " $_2"
+ INFO " $_3"
+ INFO " $_4"
+ INFO " $_5"
+ INFO " $_6"
+ INFO " $_7"
+ _buildargs="$_buildargs $_1 $_2 $_3 $_4 $_5 $_6 $_7"
+ fi
fi
- if [ -d $INST/osl -a $WITH_OSL == true ]; then
- INFO " -D CYCLES_OSL=$INST/osl"
- INFO " -D WITH_CYCLES_OSL=ON"
- INFO " -D LLVM_VERSION=$LLVM_VERSION_FOUND"
+ if $WITH_OSL; then
+ _1="-D WITH_CYCLES_OSL=ON"
+ _2="-D WITH_LLVM=ON"
+ _3="-D LLVM_VERSION=$LLVM_VERSION_FOUND"
+ INFO " $_1"
+ INFO " $_2"
+ INFO " $_3"
+ _buildargs="$_buildargs $_1 $_2 $_3"
+ if [ -d $INST/osl ]; then
+ _1="-D CYCLES_OSL=$INST/osl"
+ INFO " $_1"
+ _buildargs="$_buildargs $_1"
+ fi
if [ -d $INST/llvm ]; then
- INFO " -D LLVM_DIRECTORY=$INST/llvm"
- INFO " -D LLVM_STATIC=ON"
+ _1="-D LLVM_DIRECTORY=$INST/llvm"
+ _2="-D LLVM_STATIC=ON"
+ INFO " $_1"
+ INFO " $_2"
+ _buildargs="$_buildargs $_1 $_2"
fi
fi
+ if $WITH_OPENCOLLADA; then
+ _1="-D WITH_OPENCOLLADA=ON"
+ INFO " $_1"
+ _buildargs="$_buildargs $_1"
+ if $ALL_STATIC; then
+ _1="-D XML2_LIBRARY=$_XML2_LIB"
+ INFO " $_1"
+ _buildargs="$_buildargs $_1"
+ fi
+ fi
+
+ _1="-D WITH_CODEC_FFMPEG=ON"
+ _2="-D FFMPEG_LIBRARIES='avformat;avcodec;avutil;avdevice;swscale;rt;`print_info_ffmpeglink`'"
+ INFO " $_1"
+ INFO " $_2"
+ _buildargs="$_buildargs $_1 $_2"
if [ -d $INST/ffmpeg ]; then
- INFO " -D WITH_CODEC_FFMPEG=ON"
- INFO " -D FFMPEG=$INST/ffmpeg"
- INFO " -D FFMPEG_LIBRARIES='avformat;avcodec;avutil;avdevice;swscale;rt;`print_info_ffmpeglink`'"
+ _1="-D FFMPEG=$INST/ffmpeg"
+ INFO " $_1"
+ _buildargs="$_buildargs $_1"
fi
INFO ""
+ INFO "Or even simpler, just run (in your blender-source dir):"
+ INFO " make -j$THREADS BUILD_CMAKE_ARGS=\"$_buildargs\""
+
+ INFO ""
INFO "If you're using SCons add this to your user-config:"
- if [ -d $INST/python-3.3 ]; then
- INFO "BF_PYTHON = '$INST/python-3.3'"
+ if [ -d $INST/python-$PYTHON_VERSION_MIN ]; then
+ INFO "BF_PYTHON = '$INST/python-$PYTHON_VERSION_MIN'"
INFO "BF_PYTHON_ABI_FLAGS = 'm'"
fi
+ INFO "WITH_BF_OCIO = True"
if [ -d $INST/ocio ]; then
INFO "BF_OCIO = '$INST/ocio'"
fi
+ INFO "WITH_BF_OIIO = True"
if [ -d $INST/oiio ]; then
INFO "BF_OIIO = '$INST/oiio'"
fi
+ INFO "WITH_BF_CYCLES = True"
+
+ if [ -d $INST/osl ]; then
+ INFO "BF_OSL = '$INST/osl'"
+ fi
+ INFO "WITH_BF_BOOST = True"
if [ -d $INST/boost ]; then
INFO "BF_BOOST = '$INST/boost'"
fi
+ _ffmpeg_list_sep=" "
+ INFO "BF_FFMPEG_LIB = 'avformat avcodec swscale avutil avdevice `print_info_ffmpeglink`'"
if [ -d $INST/ffmpeg ]; then
INFO "BF_FFMPEG = '$INST/ffmpeg'"
- _ffmpeg_list_sep=" "
- INFO "BF_FFMPEG_LIB = 'avformat avcodec swscale avutil avdevice `print_info_ffmpeglink`'"
+ fi
+
+ if ! $WITH_ALL; then
+ INFO "WITH_BF_3DMOUSE = False"
+ # No libspacenav in official arch repos...
+ elif [ "$DISTRO" = "ARCH" ]; then
+ INFO "WITH_BF_3DMOUSE = False"
fi
INFO ""
@@ -1860,11 +2374,14 @@ elif [ "$DISTRO" = "DEB" ]; then
install_DEB
elif [ "$DISTRO" = "RPM" ]; then
install_RPM
-elif [ "$DISTRO" = "SUSE" ]; then
- install_SUSE
+elif [ "$DISTRO" = "ARCH" ]; then
+ install_ARCH
fi
-print_info
+print_info | tee BUILD_NOTES.txt
+INFO ""
+INFO "This information has been written to BUILD_NOTES.txt"
+INFO ""
# Switch back to user language.
LANG=LANG_BACK
diff --git a/build_files/buildbot/config/user-config-cuda-glibc211-i686.py b/build_files/buildbot/config/user-config-cuda-glibc211-i686.py
new file mode 100644
index 00000000000..0e56c4326f9
--- /dev/null
+++ b/build_files/buildbot/config/user-config-cuda-glibc211-i686.py
@@ -0,0 +1,5 @@
+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']
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
new file mode 100644
index 00000000000..59725522e18
--- /dev/null
+++ b/build_files/buildbot/config/user-config-cuda-glibc211-x86_64.py
@@ -0,0 +1,5 @@
+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']
diff --git a/build_files/buildbot/config/user-config-glibc211-i686.py b/build_files/buildbot/config/user-config-glibc211-i686.py
index e665657d91e..540416ee1fb 100644
--- a/build_files/buildbot/config/user-config-glibc211-i686.py
+++ b/build_files/buildbot/config/user-config-glibc211-i686.py
@@ -1,6 +1,7 @@
BF_BUILDDIR = '../blender-build/linux-glibc211-i686'
BF_INSTALLDIR = '../blender-install/linux-glibc211-i686'
-BF_NUMJOBS = 2
+BF_NUMJOBS = 4
+WITHOUT_BF_OVERWRITE_INSTALL = True
# Python configuration
BF_PYTHON_VERSION = '3.3'
@@ -103,14 +104,13 @@ WITH_BF_FFTW3 = True
WITH_BF_STATICFFTW3 = True
# JACK
-WITH_BF_JACK = True
+WITH_BF_JACK = False
WITH_BF_STATICJACK = True
BF_JACK_LIB_STATIC = '${BF_ZLIB}/lib/libjack.a'
# Cycles
WITH_BF_CYCLES = True
-WITH_BF_CYCLES_CUDA_BINARIES = True
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30']
+WITH_BF_CYCLES_CUDA_BINARIES = False
WITH_BF_OIIO = True
WITH_BF_STATICOIIO = True
diff --git a/build_files/buildbot/config/user-config-glibc211-x86_64.py b/build_files/buildbot/config/user-config-glibc211-x86_64.py
index 420d9ed4db9..c0ba8060712 100644
--- a/build_files/buildbot/config/user-config-glibc211-x86_64.py
+++ b/build_files/buildbot/config/user-config-glibc211-x86_64.py
@@ -1,6 +1,7 @@
BF_BUILDDIR = '../blender-build/linux-glibc211-x86_64'
BF_INSTALLDIR = '../blender-install/linux-glibc211-x86_64'
-BF_NUMJOBS = 2
+BF_NUMJOBS = 4
+WITHOUT_BF_OVERWRITE_INSTALL = True
# Python configuration
BF_PYTHON_VERSION = '3.3'
@@ -103,14 +104,13 @@ WITH_BF_FFTW3 = True
WITH_BF_STATICFFTW3 = True
# JACK
-WITH_BF_JACK = True
+WITH_BF_JACK = False
WITH_BF_STATICJACK = True
BF_JACK_LIB_STATIC = '${BF_ZLIB}/lib/libjack.a'
# Cycles
WITH_BF_CYCLES = True
-WITH_BF_CYCLES_CUDA_BINARIES = True
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30']
+WITH_BF_CYCLES_CUDA_BINARIES = False
WITH_BF_OIIO = True
WITH_BF_STATICOIIO = True
diff --git a/build_files/buildbot/config/user-config-glibc27-i686.py b/build_files/buildbot/config/user-config-glibc27-i686.py
deleted file mode 100644
index b36196fd835..00000000000
--- a/build_files/buildbot/config/user-config-glibc27-i686.py
+++ /dev/null
@@ -1,149 +0,0 @@
-BF_BUILDDIR = '../blender-build/linux-glibc27-i686'
-BF_INSTALLDIR = '../blender-install/linux-glibc27-i686'
-BF_NUMJOBS = 2
-
-# Python configuration
-BF_PYTHON_VERSION = '3.3'
-BF_PYTHON_ABI_FLAGS = 'm'
-BF_PYTHON = '/opt/python3'
-
-WITH_BF_STATICPYTHON = True
-
-# OpenCollada configuration
-WITH_BF_COLLADA = True
-BF_OPENCOLLADA = '/opt/opencollada'
-BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include'
-BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser UTF MathMLSolver buffer ftoa libxml2-static libexpat-static libpcre-static'
-BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib /home/sources/staticlibs/lib32'
-BF_PCRE_LIB = ''
-BF_EXPAT_LIB = ''
-
-# FFMPEG configuration
-WITH_BF_FFMPEG = True
-WITH_BF_STATICFFMPEG = True
-
-BF_FFMPEG = '/home/sources/staticlibs/ffmpeg'
-BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib32'
-BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libswscale.a ' + \
- '${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \
- '${BF_FFMPEG_LIBPATH}/libxvidcore.a ${BF_FFMPEG_LIBPATH}/libx264.a ${BF_FFMPEG_LIBPATH}/libmp3lame.a ' + \
- '${BF_FFMPEG_LIBPATH}/libvpx.a ${BF_FFMPEG_LIBPATH}/libvorbis.a ${BF_FFMPEG_LIBPATH}/libogg.a ' + \
- '${BF_FFMPEG_LIBPATH}/libvorbisenc.a ${BF_FFMPEG_LIBPATH}/libtheora.a ' + \
- '${BF_FFMPEG_LIBPATH}/libschroedinger-1.0.a ${BF_FFMPEG_LIBPATH}/liborc-0.4.a ${BF_FFMPEG_LIBPATH}/libdirac_encoder.a ' + \
- '${BF_FFMPEG_LIBPATH}/libfaad.a'
-
-# Don't depend on system's libstdc++
-WITH_BF_STATICCXX = True
-BF_CXX_LIB_STATIC = '/usr/lib/gcc/i486-linux-gnu/4.3.4/libstdc++.a'
-
-WITH_BF_OPENAL = True
-WITH_BF_STATICOPENAL = True
-BF_OPENAL_LIB_STATIC = '/opt/openal/lib/libopenal.a'
-
-WITH_BF_GETTEXT_STATIC = True
-BF_FREETYPE_LIB_STATIC = True
-
-WITH_BF_OPENEXR = True
-WITH_BF_STATICOPENEXR = True
-
-WITH_BF_TIFF = True
-WITH_BF_STATICTIFF = True
-BF_TIFF_LIB_STATIC = '${BF_TIFF}/lib/libtiff.a'
-
-WITH_BF_JPEG = True
-BF_JPEG_LIB = 'libjpeg'
-BF_JPEG_LIBPATH = '/home/sources/staticlibs/lib32'
-
-WITH_BF_PNG = True
-BF_PNG_LIB = 'libpng'
-BF_PNG_LIBPATH = '/home/sources/staticlibs/lib32'
-
-WITH_BF_STATICLIBSAMPLERATE = True
-
-WITH_BF_ZLIB = True
-WITH_BF_STATICZLIB = True
-BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
-
-WITH_BF_SDL = True
-WITH_BF_OGG = True
-
-WITH_BF_OPENMP = True
-
-WITH_BF_GAMEENGINE = True
-WITH_BF_BULLET = True
-
-# Blender player (would be enabled in it's own config)
-WITH_BF_PLAYER = False
-
-# Use jemalloc memory manager
-WITH_BF_JEMALLOC = True
-WITH_BF_STATICJEMALLOC = True
-BF_JEMALLOC = '/home/sources/staticlibs/jemalloc'
-BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib32'
-
-# Use 3d mouse library
-WITH_BF_3DMOUSE = True
-WITH_BF_STATIC3DMOUSE = True
-BF_3DMOUSE = '/home/sources/staticlibs/spnav'
-BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib32'
-
-# FFT
-WITH_BF_FFTW3 = True
-WITH_BF_STATICFFTW3 = True
-
-# JACK
-WITH_BF_JACK = True
-
-# Cycles
-WITH_BF_CYCLES = True
-WITH_BF_CYCLES_CUDA_BINARIES = True
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30']
-
-WITH_BF_OIIO = True
-WITH_BF_STATICOIIO = True
-BF_OIIO = '/opt/oiio'
-BF_OIIO_INC = '${BF_OIIO}/include'
-BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a'
-BF_OIIO_LIBPATH = '${BF_OIIO}/lib'
-
-WITH_BF_CYCLES_OSL = True
-WITH_BF_STATICOSL = False
-BF_OSL = '/opt/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_LIBPATH = '${BF_OSL}/lib'
-BF_OSL_COMPILER = '${BF_OSL}/bin/oslc'
-
-WITH_BF_LLVM = True
-WITH_BF_STATICLLVM = False
-BF_LLVM = '/opt/llvm-3.1'
-BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \
- 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \
- 'LLVMTarget LLVMMC LLVMCore LLVMSupport'
-BF_LLVM_LIBPATH = '${BF_LLVM}/lib'
-
-# Color management
-WITH_BF_OCIO = True
-WITH_BF_STATICOCIO = True
-BF_OCIO = '/opt/ocio'
-BF_OCIO_INC = '${BF_OCIO}/include'
-BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a'
-BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
-
-WITH_BF_BOOST = True
-WITH_BF_STATICBOOST = True
-BF_BOOST = '/opt/boost'
-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'
-BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
-
-# Ocean Simulation
-WITH_BF_OCEANSIM = True
-
-# Compilation and optimization
-BF_DEBUG = False
-REL_CCFLAGS = ['-DNDEBUG', '-DNDEBUG', '-O2'] # C & C++
-PLATFORM_LINKFLAGS = ['-L/home/sources/staticlibs/lib32']
-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-glibc27-x86_64.py b/build_files/buildbot/config/user-config-glibc27-x86_64.py
deleted file mode 100644
index 7359e155586..00000000000
--- a/build_files/buildbot/config/user-config-glibc27-x86_64.py
+++ /dev/null
@@ -1,149 +0,0 @@
-BF_BUILDDIR = '../blender-build/linux-glibc27-x86_64'
-BF_INSTALLDIR = '../blender-install/linux-glibc27-x86_64'
-BF_NUMJOBS = 2
-
-# Python configuration
-BF_PYTHON_VERSION = '3.3'
-BF_PYTHON_ABI_FLAGS = 'm'
-BF_PYTHON = '/opt/python3'
-
-WITH_BF_STATICPYTHON = True
-
-# OpenCollada configuration
-WITH_BF_COLLADA = True
-BF_OPENCOLLADA = '/opt/opencollada'
-BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include'
-BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser UTF MathMLSolver buffer ftoa libxml2-static libexpat-static libpcre-static'
-BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib /home/sources/staticlibs/lib64'
-BF_PCRE_LIB = ''
-BF_EXPAT_LIB = ''
-
-# FFMPEG configuration
-WITH_BF_FFMPEG = True
-WITH_BF_STATICFFMPEG = True
-
-BF_FFMPEG = '/home/sources/staticlibs/ffmpeg'
-BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib64'
-BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libswscale.a ' + \
- '${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \
- '${BF_FFMPEG_LIBPATH}/libxvidcore.a ${BF_FFMPEG_LIBPATH}/libx264.a ${BF_FFMPEG_LIBPATH}/libmp3lame.a ' + \
- '${BF_FFMPEG_LIBPATH}/libvpx.a ${BF_FFMPEG_LIBPATH}/libvorbis.a ${BF_FFMPEG_LIBPATH}/libogg.a ' + \
- '${BF_FFMPEG_LIBPATH}/libvorbisenc.a ${BF_FFMPEG_LIBPATH}/libtheora.a ' + \
- '${BF_FFMPEG_LIBPATH}/libschroedinger-1.0.a ${BF_FFMPEG_LIBPATH}/liborc-0.4.a ${BF_FFMPEG_LIBPATH}/libdirac_encoder.a ' + \
- '${BF_FFMPEG_LIBPATH}/libfaad.a'
-
-# Don't depend on system's libstdc++
-WITH_BF_STATICCXX = True
-BF_CXX_LIB_STATIC = '/usr/lib/gcc/x86_64-linux-gnu/4.3.4/libstdc++.a'
-
-WITH_BF_OPENAL = True
-WITH_BF_STATICOPENAL = True
-BF_OPENAL_LIB_STATIC = '/opt/openal/lib/libopenal.a'
-
-WITH_BF_GETTEXT_STATIC = True
-BF_FREETYPE_LIB_STATIC = True
-
-WITH_BF_OPENEXR = True
-WITH_BF_STATICOPENEXR = True
-
-WITH_BF_TIFF = True
-WITH_BF_STATICTIFF = True
-BF_TIFF_LIB_STATIC = '${BF_TIFF}/lib/libtiff.a'
-
-WITH_BF_JPEG = True
-BF_JPEG_LIB = 'libjpeg'
-BF_JPEG_LIBPATH = '/home/sources/staticlibs/lib64'
-
-WITH_BF_PNG = True
-BF_PNG_LIB = 'libpng'
-BF_PNG_LIBPATH = '/home/sources/staticlibs/lib64'
-
-WITH_BF_STATICLIBSAMPLERATE = True
-
-WITH_BF_ZLIB = True
-WITH_BF_STATICZLIB = True
-BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
-
-WITH_BF_SDL = True
-WITH_BF_OGG = True
-
-WITH_BF_OPENMP = True
-
-WITH_BF_GAMEENGINE = True
-WITH_BF_BULLET = True
-
-# Blender player (would be enabled in it's own config)
-WITH_BF_PLAYER = False
-
-# Use jemalloc memory manager
-WITH_BF_JEMALLOC = True
-WITH_BF_STATICJEMALLOC = True
-BF_JEMALLOC = '/home/sources/staticlibs/jemalloc'
-BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib64'
-
-# Use 3d mouse library
-WITH_BF_3DMOUSE = True
-WITH_BF_STATIC3DMOUSE = True
-BF_3DMOUSE = '/home/sources/staticlibs/spnav'
-BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib64'
-
-# FFT
-WITH_BF_FFTW3 = True
-WITH_BF_STATICFFTW3 = True
-
-# JACK
-WITH_BF_JACK = True
-
-# Cycles
-WITH_BF_CYCLES = True
-WITH_BF_CYCLES_CUDA_BINARIES = True
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30']
-
-WITH_BF_OIIO = True
-WITH_BF_STATICOIIO = True
-BF_OIIO = '/opt/oiio'
-BF_OIIO_INC = '${BF_OIIO}/include'
-BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a'
-BF_OIIO_LIBPATH = '${BF_OIIO}/lib'
-
-WITH_BF_CYCLES_OSL = True
-WITH_BF_STATICOSL = False
-BF_OSL = '/opt/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_LIBPATH = '${BF_OSL}/lib'
-BF_OSL_COMPILER = '${BF_OSL}/bin/oslc'
-
-WITH_BF_LLVM = True
-WITH_BF_STATICLLVM = False
-BF_LLVM = '/opt/llvm-3.1'
-BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \
- 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \
- 'LLVMTarget LLVMMC LLVMCore LLVMSupport'
-BF_LLVM_LIBPATH = '${BF_LLVM}/lib'
-
-# Color management
-WITH_BF_OCIO = True
-WITH_BF_STATICOCIO = True
-BF_OCIO = '/opt/ocio'
-BF_OCIO_INC = '${BF_OCIO}/include'
-BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a'
-BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
-
-WITH_BF_BOOST = True
-WITH_BF_STATICBOOST = True
-BF_BOOST = '/opt/boost'
-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'
-BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
-
-# Ocean Simulation
-WITH_BF_OCEANSIM = True
-
-# Compilation and optimization
-BF_DEBUG = False
-REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++
-PLATFORM_LINKFLAGS = ['-L/home/sources/staticlibs/lib64']
-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
new file mode 100644
index 00000000000..e39b13039c5
--- /dev/null
+++ b/build_files/buildbot/config/user-config-mac-i386.py
@@ -0,0 +1,420 @@
+#
+# Note : if you want to alter this file
+# copy it as a whole in the upper folder
+# as user-config.py
+# dont create a new file with only some
+# vars changed.
+
+import commands
+
+# IMPORTANT NOTE : OFFICIAL BUILDS SHOULD BE DONE WITH SDKs
+USE_SDK=True
+
+#############################################################################
+################### Cocoa & architecture settings ##################
+#############################################################################
+WITH_GHOST_COCOA=True
+MACOSX_ARCHITECTURE = 'i386' # valid archs: ppc, i386, ppc64, x86_64
+
+
+cmd = 'uname -p'
+MAC_PROC=commands.getoutput(cmd)
+cmd = 'uname -r'
+cmd_res=commands.getoutput(cmd)
+
+if cmd_res[:1]=='7':
+ MAC_CUR_VER='10.3'
+elif cmd_res[:1]=='8':
+ MAC_CUR_VER='10.4'
+elif cmd_res[:1]=='9':
+ MAC_CUR_VER='10.5'
+elif cmd_res[:2]=='10':
+ MAC_CUR_VER='10.6'
+elif cmd_res[:2]=='11':
+ MAC_CUR_VER='10.7'
+elif cmd_res[:2]=='12':
+ MAC_CUR_VER='10.8'
+cmd = 'xcodebuild -version'
+cmd_xcode=commands.getoutput(cmd)
+XCODE_CUR_VER=cmd_xcode[6:][:3] # truncate output to major.minor version
+cmd = 'xcodebuild -showsdks'
+cmd_sdk=commands.getoutput(cmd)
+MACOSX_SDK_CHECK=cmd_sdk
+
+if MACOSX_ARCHITECTURE == 'x86_64' or MACOSX_ARCHITECTURE == 'ppc64':
+ USE_QTKIT=True # Carbon quicktime is not available for 64bit
+
+
+# Default target OSX settings per architecture
+# Can be customized
+
+if MACOSX_ARCHITECTURE == 'ppc' and MAC_CUR_VER == '10.4':
+# all releases are now made for 10.5 !
+# MAC_MIN_VERS = '10.3'
+# MACOSX_SDK='/Developer/SDKs/MacOSX10.3.9.sdk'
+# LCGDIR = '#../lib/darwin-6.1-powerpc'
+# CC = 'gcc-3.3'
+# CXX = 'g++-3.3'
+ MAC_MIN_VERS = '10.4'
+ MACOSX_DEPLOYMENT_TARGET = '10.4'
+ MACOSX_SDK='/Developer/SDKs/MacOSX10.4u.sdk'
+ LCGDIR = '#../lib/darwin-8.0.0-powerpc'
+ CC = 'gcc-4.0'
+ CXX = 'g++-4.0'
+elif MACOSX_ARCHITECTURE == 'i386' and MAC_CUR_VER == '10.4':
+ MAC_MIN_VERS = '10.4'
+ MACOSX_DEPLOYMENT_TARGET = '10.4'
+ MACOSX_SDK='/Developer/SDKs/MacOSX10.4u.sdk'
+ LCGDIR = '#../lib/darwin-8.x.i386'
+ CC = 'gcc-4.0'
+ CXX = 'g++-4.0'
+else :
+ if 'Mac OS X 10.5' in MACOSX_SDK_CHECK:
+ # OSX 10.5/6 with Xcode 3.x
+ MAC_MIN_VERS = '10.5'
+ MACOSX_DEPLOYMENT_TARGET = '10.5'
+ MACOSX_SDK='/Developer/SDKs/MacOSX10.5.sdk'
+ LCGDIR = '#../lib/darwin-9.x.universal'
+ CC = 'gcc-4.2'
+ CXX = 'g++-4.2'
+ elif 'Mac OS X 10.6' in MACOSX_SDK_CHECK:
+ # OSX 10.6/7 with Xcode 4.x
+ MAC_MIN_VERS = '10.6'
+ MACOSX_DEPLOYMENT_TARGET = '10.6'
+ MACOSX_SDK='/Developer/SDKs/MacOSX10.6.sdk'
+ LCGDIR = '#../lib/darwin-9.x.universal'
+ CC = 'gcc-4.2'
+ CXX = 'g++-4.2'
+ else:
+ # OSX 10.8 with Xcode 4.4 and higher (no 10.6sdk! )
+ MAC_MIN_VERS = '10.6'
+ MACOSX_DEPLOYMENT_TARGET = '10.6'
+ MACOSX_SDK='/Developer/SDKs/MacOSX10.7.sdk'
+ LCGDIR = '#../lib/darwin-9.x.universal'
+ CC = 'gcc'
+ CXX = 'g++'
+
+LIBDIR = '${LCGDIR}'
+
+if XCODE_CUR_VER >= '4.3': ## since version 4.3, XCode and developer dir are bundled ##
+ MACOSX_SDK = '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform' + MACOSX_SDK
+
+#############################################################################
+################### Dependency settings ##################
+#############################################################################
+
+#Defaults openMP to true if compiler handles it ( only gcc 4.6.1 and newer )
+# if your compiler does not have accurate suffix you may have to enable it by hand !
+if CC[:-2].endswith('4.6'):
+ WITH_BF_OPENMP = True # multithreading for fluids, cloth, sculpt and smoke
+else:
+ WITH_BF_OPENMP = False
+
+# enable ffmpeg support
+WITH_BF_FFMPEG = True
+BF_FFMPEG = LIBDIR + '/ffmpeg'
+BF_FFMPEG_INC = "${BF_FFMPEG}/include"
+BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib'
+BF_FFMPEG_LIB = 'avcodec avdevice avformat avutil mp3lame swscale x264 xvidcore theora theoradec theoraenc vorbis vorbisenc vorbisfile ogg bz2'
+#bz2 is a standard osx dynlib
+
+BF_PYTHON_VERSION = '3.3'
+WITH_OSX_STATICPYTHON = True
+
+if WITH_OSX_STATICPYTHON:
+ # python 3.3 uses precompiled libraries in bf svn /lib by default
+
+ BF_PYTHON = LIBDIR + '/python'
+ BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}m'
+ # BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}'
+ BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}m'
+ BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/python${BF_PYTHON_VERSION}'
+ # BF_PYTHON_LINKFLAGS = ['-u', '_PyMac_Error', '-framework', 'System']
+else:
+ # python 3.2 uses Python-framework additionally installed in /Library/Frameworks
+
+ BF_PYTHON = '/Library/Frameworks/Python.framework/Versions/'
+ BF_PYTHON_INC = '${BF_PYTHON}${BF_PYTHON_VERSION}/include/python${BF_PYTHON_VERSION}m'
+ BF_PYTHON_BINARY = '${BF_PYTHON}${BF_PYTHON_VERSION}/bin/python${BF_PYTHON_VERSION}'
+ #BF_PYTHON_LIB = ''
+ BF_PYTHON_LIBPATH = '${BF_PYTHON}${BF_PYTHON_VERSION}/lib/python${BF_PYTHON_VERSION}/config-${BF_PYTHON_VERSION}m'
+
+WITH_BF_OPENAL = True
+#different lib must be used following version of gcc
+# for gcc 3.3
+#BF_OPENAL = LIBDIR + '/openal'
+# for gcc 3.4 and ulterior
+if MAC_PROC == 'powerpc':
+ BF_OPENAL = '#../lib/darwin-8.0.0-powerpc/openal'
+else :
+ BF_OPENAL = LIBDIR + '/openal'
+
+WITH_BF_STATICOPENAL = False
+BF_OPENAL_INC = '${BF_OPENAL}/include' # only headers from libdir needed for proper use of framework !!!!
+#BF_OPENAL_LIB = 'openal'
+#BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+#BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
+
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+BF_CXX = '/usr'
+WITH_BF_STATICCXX = False
+BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
+
+# we use simply jack framework
+WITH_BF_JACK = True
+BF_JACK = '/Library/Frameworks/Jackmp.framework'
+BF_JACK_INC = '${BF_JACK}/headers'
+#BF_JACK_LIB = 'jack' # not used due framework
+BF_JACK_LIBPATH = '${BF_JACK}'
+
+WITH_BF_SNDFILE = True
+BF_SNDFILE = LIBDIR + '/sndfile'
+BF_SNDFILE_INC = '${BF_SNDFILE}/include'
+BF_SNDFILE_LIB = 'sndfile FLAC ogg vorbis vorbisenc'
+BF_SNDFILE_LIBPATH = '${BF_SNDFILE}/lib ${BF_FFMPEG}/lib' #ogg libs are stored in ffmpeg dir
+
+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_LIBPATH = '${BF_SDL}/lib'
+
+WITH_BF_OPENEXR = True
+WITH_BF_STATICOPENEXR = False
+BF_OPENEXR = '${LCGDIR}/openexr'
+BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR'
+BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread'
+BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+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'
+
+WITH_BF_DDS = True
+
+#Color Management System
+WITH_BF_LCMS = False
+BF_LCMS = LIBDIR + '/lcms'
+BF_LCMS_INC = '${BF_LCMS}/include'
+BF_LCMS_LIB = 'lcms'
+BF_LCMS_LIBPATH = '${BF_LCMS}/lib'
+
+WITH_BF_JPEG = True
+BF_JPEG = LIBDIR + '/jpeg'
+BF_JPEG_INC = '${BF_JPEG}/include'
+BF_JPEG_LIB = 'jpeg'
+BF_JPEG_LIBPATH = '${BF_JPEG}/lib'
+
+WITH_BF_PNG = True
+BF_PNG = LIBDIR + '/png'
+BF_PNG_INC = '${BF_PNG}/include'
+BF_PNG_LIB = 'png'
+BF_PNG_LIBPATH = '${BF_PNG}/lib'
+
+WITH_BF_TIFF = True
+BF_TIFF = LIBDIR + '/tiff'
+BF_TIFF_INC = '${BF_TIFF}/include'
+BF_TIFF_LIB = 'tiff'
+BF_TIFF_LIBPATH = '${BF_TIFF}/lib'
+
+WITH_BF_ZLIB = True
+BF_ZLIB = '/usr'
+BF_ZLIB_INC = '${BF_ZLIB}/include'
+BF_ZLIB_LIB = 'z'
+
+WITH_BF_INTERNATIONAL = True
+
+WITH_BF_GAMEENGINE = True
+WITH_BF_PLAYER = True
+WITH_BF_OCEANSIM = True
+
+WITH_BF_BULLET = True
+BF_BULLET = '#extern/bullet2/src'
+BF_BULLET_INC = '${BF_BULLET}'
+BF_BULLET_LIB = 'extern_bullet'
+
+WITH_BF_FFTW3 = True
+BF_FFTW3 = LIBDIR + '/fftw3'
+BF_FFTW3_INC = '${BF_FFTW3}/include'
+BF_FFTW3_LIB = 'libfftw3'
+BF_FFTW3_LIBPATH = '${BF_FFTW3}/lib'
+
+BF_FREETYPE = LIBDIR + '/freetype'
+BF_FREETYPE_INC = '${BF_FREETYPE}/include ${BF_FREETYPE}/include/freetype2'
+BF_FREETYPE_LIB = 'freetype'
+BF_FREETYPE_LIBPATH = '${BF_FREETYPE}/lib'
+
+WITH_BF_QUICKTIME = True
+
+WITH_BF_ICONV = True
+BF_ICONV = '/usr'
+BF_ICONV_INC = '${BF_ICONV}/include'
+BF_ICONV_LIB = 'iconv'
+#BF_ICONV_LIBPATH = '${BF_ICONV}/lib'
+
+# Mesa Libs should go here if your using them as well....
+WITH_BF_STATICOPENGL = True
+BF_OPENGL_LIB = 'GL GLU'
+BF_OPENGL_LIBPATH = '/System/Library/Frameworks/OpenGL.framework/Libraries'
+BF_OPENGL_LINKFLAGS = ['-framework', 'OpenGL']
+
+#OpenCollada flags
+WITH_BF_COLLADA = True
+BF_COLLADA = '#source/blender/collada'
+BF_COLLADA_INC = '${BF_COLLADA}'
+BF_COLLADA_LIB = 'bf_collada'
+BF_OPENCOLLADA = LIBDIR + '/opencollada'
+BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include'
+BF_OPENCOLLADA_LIB = 'OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils OpenCOLLADAStreamWriter MathMLSolver GeneratedSaxParser UTF xml2 buffer ftoa'
+BF_OPENCOLLADA_LIBPATH = LIBDIR + '/opencollada'
+BF_PCRE = LIBDIR + '/opencollada'
+BF_PCRE_LIB = 'pcre'
+BF_PCRE_LIBPATH = '${BF_PCRE}/lib'
+#BF_EXPAT = '/usr'
+#BF_EXPAT_LIB = 'expat'
+#BF_EXPAT_LIBPATH = '/usr/lib'
+
+# Cycles
+WITH_BF_CYCLES = True
+
+#OSL
+
+WITH_BF_CYCLES_OSL = True
+BF_OSL = LIBDIR + '/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 oslquery'
+BF_OSL_LIBPATH = '${BF_OSL}/lib'
+BF_OSL_COMPILER = '${BF_OSL}/bin/oslc'
+
+WITH_BF_LLVM = True
+BF_LLVM = LIBDIR + '/llvm'
+BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \
+ 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \
+ 'LLVMTarget LLVMMC LLVMCore LLVMSupport'
+BF_LLVM_LIBPATH = '${BF_LLVM}/lib'
+
+WITH_BF_OIIO = True
+BF_OIIO = LIBDIR + '/openimageio'
+BF_OIIO_INC = '${BF_OIIO}/include'
+BF_OIIO_LIB = 'OpenImageIO'
+BF_OIIO_LIBPATH = '${BF_OIIO}/lib'
+
+WITH_BF_OCIO = True
+BF_OCIO = LIBDIR + '/opencolorio'
+BF_OCIO_INC = '${BF_OCIO}/include'
+BF_OCIO_LIB = 'OpenColorIO tinyxml yaml-cpp'
+BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
+
+WITH_BF_BOOST = True
+BF_BOOST = LIBDIR + '/boost'
+BF_BOOST_INC = '${BF_BOOST}/include'
+BF_BOOST_LIB = 'boost_date_time-mt boost_filesystem-mt boost_regex-mt boost_system-mt boost_thread-mt boost_wave-mt'
+BF_BOOST_LIB_INTERNATIONAL = 'boost_locale-mt'
+BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
+
+WITH_BF_CYCLES_CUDA_BINARIES = True
+BF_CYCLES_CUDA_NVCC = '/usr/local/cuda/bin/nvcc'
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30']
+
+#Ray trace optimization
+if MACOSX_ARCHITECTURE == 'x86_64' or MACOSX_ARCHITECTURE == 'i386':
+ WITH_BF_RAYOPTIMIZATION = True
+else:
+ WITH_BF_RAYOPTIMIZATION = False
+if MACOSX_ARCHITECTURE == 'i386':
+ BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse']
+elif MACOSX_ARCHITECTURE == 'x86_64':
+ BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-msse2']
+
+# SpaceNavigator and related 3D mice, driver must be 3DxWare 10 Beta 4 (Mac OS X) or later !
+WITH_BF_3DMOUSE = True
+
+#############################################################################
+################### various compile settings and flags ##################
+#############################################################################
+
+BF_QUIET = '1' # suppress verbose output
+
+if MACOSX_ARCHITECTURE == 'x86_64' or MACOSX_ARCHITECTURE == 'ppc64':
+ ARCH_FLAGS = ['-m64']
+else:
+ ARCH_FLAGS = ['-m32']
+
+CFLAGS = []
+CXXFLAGS = []
+CCFLAGS = ['-pipe','-funsigned-char']
+
+CPPFLAGS = list(ARCH_FLAGS)
+
+if WITH_GHOST_COCOA:
+ PLATFORM_LINKFLAGS = ['-fexceptions','-framework','CoreServices','-framework','Foundation','-framework','IOKit','-framework','AppKit','-framework','Cocoa','-framework','Carbon','-framework','AudioUnit','-framework','AudioToolbox','-framework','CoreAudio','-framework','OpenAL']+ARCH_FLAGS
+else:
+ PLATFORM_LINKFLAGS = ['-fexceptions','-framework','CoreServices','-framework','Foundation','-framework','IOKit','-framework','AppKit','-framework','Carbon','-framework','AGL','-framework','AudioUnit','-framework','AudioToolbox','-framework','CoreAudio','-framework','OpenAL']+ARCH_FLAGS
+
+if WITH_BF_QUICKTIME:
+ if USE_QTKIT:
+ PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QTKit']
+ else:
+ PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QuickTime']
+
+if not WITH_OSX_STATICPYTHON:
+ PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','Python']
+
+
+#note to build succesfully on 10.3.9 SDK you need to patch 10.3.9 by adding the SystemStubs.a lib from 10.4
+#for > 10.7.sdk, SystemStubs needs to be excluded (lib doesn't exist anymore)
+if MACOSX_SDK.endswith("10.7.sdk") or MACOSX_SDK.endswith("10.8.sdk"):
+ LLIBS = ['stdc++']
+else:
+ LLIBS = ['stdc++', 'SystemStubs']
+
+# some flags shuffling for different OS versions
+if MAC_MIN_VERS == '10.3':
+ CCFLAGS = ['-fuse-cxa-atexit'] + CCFLAGS
+ PLATFORM_LINKFLAGS = ['-fuse-cxa-atexit'] + PLATFORM_LINKFLAGS
+ LLIBS.append('crt3.o')
+
+if USE_SDK:
+ SDK_FLAGS=['-isysroot', MACOSX_SDK,'-mmacosx-version-min='+MAC_MIN_VERS,'-arch',MACOSX_ARCHITECTURE]
+ PLATFORM_LINKFLAGS = ['-mmacosx-version-min='+MAC_MIN_VERS,'-Wl','-isysroot',MACOSX_SDK,'-arch',MACOSX_ARCHITECTURE]+PLATFORM_LINKFLAGS
+ CCFLAGS=SDK_FLAGS+CCFLAGS
+ CXXFLAGS=SDK_FLAGS+CXXFLAGS
+
+#Intel Macs are CoreDuo and Up
+if MACOSX_ARCHITECTURE == 'i386' or MACOSX_ARCHITECTURE == 'x86_64':
+ REL_CFLAGS = []
+ REL_CXXFLAGS = []
+ REL_CCFLAGS = ['-DNDEBUG', '-O2','-ftree-vectorize','-msse','-msse2','-msse3','-mfpmath=sse']
+else:
+ CCFLAGS += ['-fno-strict-aliasing']
+ REL_CFLAGS = []
+ REL_CXXFLAGS = []
+ REL_CCFLAGS = ['-DNDEBUG', '-O2']
+
+# Intel 64bit Macs are Core2Duo and up
+if MACOSX_ARCHITECTURE == 'x86_64':
+ REL_CCFLAGS += ['-march=core2','-mssse3','-with-tune=core2','-enable-threads']
+
+CC_WARN = ['-Wall']
+C_WARN = ['-Wno-char-subscripts', '-Wpointer-arith', '-Wcast-align', '-Wdeclaration-after-statement', '-Wno-unknown-pragmas', '-Wstrict-prototypes']
+CXX_WARN = ['-Wno-invalid-offsetof', '-Wno-sign-compare']
+
+##FIX_STUBS_WARNINGS = -Wno-unused
+
+##LOPTS = --dynamic
+##DYNLDFLAGS = -shared $(LDFLAGS)
+
+BF_PROFILE_CCFLAGS = ['-pg', '-g ']
+BF_PROFILE_LINKFLAGS = ['-pg']
+BF_PROFILE = False
+
+BF_DEBUG = False
+BF_DEBUG_CCFLAGS = ['-g', '-D_DEBUG']
+
+#############################################################################
+################### Output directories ##################
+#############################################################################
+
+BF_BUILDDIR='../build/darwin'
+BF_INSTALLDIR='../install/darwin'
diff --git a/build_files/buildbot/config/user-config-mac-x86_64.py b/build_files/buildbot/config/user-config-mac-x86_64.py
new file mode 100644
index 00000000000..0331bdf3ab2
--- /dev/null
+++ b/build_files/buildbot/config/user-config-mac-x86_64.py
@@ -0,0 +1,420 @@
+#
+# Note : if you want to alter this file
+# copy it as a whole in the upper folder
+# as user-config.py
+# dont create a new file with only some
+# vars changed.
+
+import commands
+
+# IMPORTANT NOTE : OFFICIAL BUILDS SHOULD BE DONE WITH SDKs
+USE_SDK=True
+
+#############################################################################
+################### Cocoa & architecture settings ##################
+#############################################################################
+WITH_GHOST_COCOA=True
+MACOSX_ARCHITECTURE = 'x86_64' # valid archs: ppc, i386, ppc64, x86_64
+
+
+cmd = 'uname -p'
+MAC_PROC=commands.getoutput(cmd)
+cmd = 'uname -r'
+cmd_res=commands.getoutput(cmd)
+
+if cmd_res[:1]=='7':
+ MAC_CUR_VER='10.3'
+elif cmd_res[:1]=='8':
+ MAC_CUR_VER='10.4'
+elif cmd_res[:1]=='9':
+ MAC_CUR_VER='10.5'
+elif cmd_res[:2]=='10':
+ MAC_CUR_VER='10.6'
+elif cmd_res[:2]=='11':
+ MAC_CUR_VER='10.7'
+elif cmd_res[:2]=='12':
+ MAC_CUR_VER='10.8'
+cmd = 'xcodebuild -version'
+cmd_xcode=commands.getoutput(cmd)
+XCODE_CUR_VER=cmd_xcode[6:][:3] # truncate output to major.minor version
+cmd = 'xcodebuild -showsdks'
+cmd_sdk=commands.getoutput(cmd)
+MACOSX_SDK_CHECK=cmd_sdk
+
+if MACOSX_ARCHITECTURE == 'x86_64' or MACOSX_ARCHITECTURE == 'ppc64':
+ USE_QTKIT=True # Carbon quicktime is not available for 64bit
+
+
+# Default target OSX settings per architecture
+# Can be customized
+
+if MACOSX_ARCHITECTURE == 'ppc' and MAC_CUR_VER == '10.4':
+# all releases are now made for 10.5 !
+# MAC_MIN_VERS = '10.3'
+# MACOSX_SDK='/Developer/SDKs/MacOSX10.3.9.sdk'
+# LCGDIR = '#../lib/darwin-6.1-powerpc'
+# CC = 'gcc-3.3'
+# CXX = 'g++-3.3'
+ MAC_MIN_VERS = '10.4'
+ MACOSX_DEPLOYMENT_TARGET = '10.4'
+ MACOSX_SDK='/Developer/SDKs/MacOSX10.4u.sdk'
+ LCGDIR = '#../lib/darwin-8.0.0-powerpc'
+ CC = 'gcc-4.0'
+ CXX = 'g++-4.0'
+elif MACOSX_ARCHITECTURE == 'i386' and MAC_CUR_VER == '10.4':
+ MAC_MIN_VERS = '10.4'
+ MACOSX_DEPLOYMENT_TARGET = '10.4'
+ MACOSX_SDK='/Developer/SDKs/MacOSX10.4u.sdk'
+ LCGDIR = '#../lib/darwin-8.x.i386'
+ CC = 'gcc-4.0'
+ CXX = 'g++-4.0'
+else :
+ if 'Mac OS X 10.5' in MACOSX_SDK_CHECK:
+ # OSX 10.5/6 with Xcode 3.x
+ MAC_MIN_VERS = '10.5'
+ MACOSX_DEPLOYMENT_TARGET = '10.5'
+ MACOSX_SDK='/Developer/SDKs/MacOSX10.5.sdk'
+ LCGDIR = '#../lib/darwin-9.x.universal'
+ CC = 'gcc-4.2'
+ CXX = 'g++-4.2'
+ elif 'Mac OS X 10.6' in MACOSX_SDK_CHECK:
+ # OSX 10.6/7 with Xcode 4.x
+ MAC_MIN_VERS = '10.6'
+ MACOSX_DEPLOYMENT_TARGET = '10.6'
+ MACOSX_SDK='/Developer/SDKs/MacOSX10.6.sdk'
+ LCGDIR = '#../lib/darwin-9.x.universal'
+ CC = 'gcc-4.2'
+ CXX = 'g++-4.2'
+ else:
+ # OSX 10.8 with Xcode 4.4 and higher (no 10.6sdk! )
+ MAC_MIN_VERS = '10.6'
+ MACOSX_DEPLOYMENT_TARGET = '10.6'
+ MACOSX_SDK='/Developer/SDKs/MacOSX10.7.sdk'
+ LCGDIR = '#../lib/darwin-9.x.universal'
+ CC = 'gcc'
+ CXX = 'g++'
+
+LIBDIR = '${LCGDIR}'
+
+if XCODE_CUR_VER >= '4.3': ## since version 4.3, XCode and developer dir are bundled ##
+ MACOSX_SDK = '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform' + MACOSX_SDK
+
+#############################################################################
+################### Dependency settings ##################
+#############################################################################
+
+#Defaults openMP to true if compiler handles it ( only gcc 4.6.1 and newer )
+# if your compiler does not have accurate suffix you may have to enable it by hand !
+if CC[:-2].endswith('4.6'):
+ WITH_BF_OPENMP = True # multithreading for fluids, cloth, sculpt and smoke
+else:
+ WITH_BF_OPENMP = False
+
+# enable ffmpeg support
+WITH_BF_FFMPEG = True
+BF_FFMPEG = LIBDIR + '/ffmpeg'
+BF_FFMPEG_INC = "${BF_FFMPEG}/include"
+BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib'
+BF_FFMPEG_LIB = 'avcodec avdevice avformat avutil mp3lame swscale x264 xvidcore theora theoradec theoraenc vorbis vorbisenc vorbisfile ogg bz2'
+#bz2 is a standard osx dynlib
+
+BF_PYTHON_VERSION = '3.3'
+WITH_OSX_STATICPYTHON = True
+
+if WITH_OSX_STATICPYTHON:
+ # python 3.3 uses precompiled libraries in bf svn /lib by default
+
+ BF_PYTHON = LIBDIR + '/python'
+ BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}m'
+ # BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}'
+ BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}m'
+ BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/python${BF_PYTHON_VERSION}'
+ # BF_PYTHON_LINKFLAGS = ['-u', '_PyMac_Error', '-framework', 'System']
+else:
+ # python 3.2 uses Python-framework additionally installed in /Library/Frameworks
+
+ BF_PYTHON = '/Library/Frameworks/Python.framework/Versions/'
+ BF_PYTHON_INC = '${BF_PYTHON}${BF_PYTHON_VERSION}/include/python${BF_PYTHON_VERSION}m'
+ BF_PYTHON_BINARY = '${BF_PYTHON}${BF_PYTHON_VERSION}/bin/python${BF_PYTHON_VERSION}'
+ #BF_PYTHON_LIB = ''
+ BF_PYTHON_LIBPATH = '${BF_PYTHON}${BF_PYTHON_VERSION}/lib/python${BF_PYTHON_VERSION}/config-${BF_PYTHON_VERSION}m'
+
+WITH_BF_OPENAL = True
+#different lib must be used following version of gcc
+# for gcc 3.3
+#BF_OPENAL = LIBDIR + '/openal'
+# for gcc 3.4 and ulterior
+if MAC_PROC == 'powerpc':
+ BF_OPENAL = '#../lib/darwin-8.0.0-powerpc/openal'
+else :
+ BF_OPENAL = LIBDIR + '/openal'
+
+WITH_BF_STATICOPENAL = False
+BF_OPENAL_INC = '${BF_OPENAL}/include' # only headers from libdir needed for proper use of framework !!!!
+#BF_OPENAL_LIB = 'openal'
+#BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib'
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+#BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a'
+
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+BF_CXX = '/usr'
+WITH_BF_STATICCXX = False
+BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
+
+# we use simply jack framework
+WITH_BF_JACK = True
+BF_JACK = '/Library/Frameworks/Jackmp.framework'
+BF_JACK_INC = '${BF_JACK}/headers'
+#BF_JACK_LIB = 'jack' # not used due framework
+BF_JACK_LIBPATH = '${BF_JACK}'
+
+WITH_BF_SNDFILE = True
+BF_SNDFILE = LIBDIR + '/sndfile'
+BF_SNDFILE_INC = '${BF_SNDFILE}/include'
+BF_SNDFILE_LIB = 'sndfile FLAC ogg vorbis vorbisenc'
+BF_SNDFILE_LIBPATH = '${BF_SNDFILE}/lib ${BF_FFMPEG}/lib' #ogg libs are stored in ffmpeg dir
+
+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_LIBPATH = '${BF_SDL}/lib'
+
+WITH_BF_OPENEXR = True
+WITH_BF_STATICOPENEXR = False
+BF_OPENEXR = '${LCGDIR}/openexr'
+BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR'
+BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread'
+BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib'
+# Warning, this static lib configuration is untested! users of this OS please confirm.
+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'
+
+WITH_BF_DDS = True
+
+#Color Management System
+WITH_BF_LCMS = False
+BF_LCMS = LIBDIR + '/lcms'
+BF_LCMS_INC = '${BF_LCMS}/include'
+BF_LCMS_LIB = 'lcms'
+BF_LCMS_LIBPATH = '${BF_LCMS}/lib'
+
+WITH_BF_JPEG = True
+BF_JPEG = LIBDIR + '/jpeg'
+BF_JPEG_INC = '${BF_JPEG}/include'
+BF_JPEG_LIB = 'jpeg'
+BF_JPEG_LIBPATH = '${BF_JPEG}/lib'
+
+WITH_BF_PNG = True
+BF_PNG = LIBDIR + '/png'
+BF_PNG_INC = '${BF_PNG}/include'
+BF_PNG_LIB = 'png'
+BF_PNG_LIBPATH = '${BF_PNG}/lib'
+
+WITH_BF_TIFF = True
+BF_TIFF = LIBDIR + '/tiff'
+BF_TIFF_INC = '${BF_TIFF}/include'
+BF_TIFF_LIB = 'tiff'
+BF_TIFF_LIBPATH = '${BF_TIFF}/lib'
+
+WITH_BF_ZLIB = True
+BF_ZLIB = '/usr'
+BF_ZLIB_INC = '${BF_ZLIB}/include'
+BF_ZLIB_LIB = 'z'
+
+WITH_BF_INTERNATIONAL = True
+
+WITH_BF_GAMEENGINE = True
+WITH_BF_PLAYER = True
+WITH_BF_OCEANSIM = True
+
+WITH_BF_BULLET = True
+BF_BULLET = '#extern/bullet2/src'
+BF_BULLET_INC = '${BF_BULLET}'
+BF_BULLET_LIB = 'extern_bullet'
+
+WITH_BF_FFTW3 = True
+BF_FFTW3 = LIBDIR + '/fftw3'
+BF_FFTW3_INC = '${BF_FFTW3}/include'
+BF_FFTW3_LIB = 'libfftw3'
+BF_FFTW3_LIBPATH = '${BF_FFTW3}/lib'
+
+BF_FREETYPE = LIBDIR + '/freetype'
+BF_FREETYPE_INC = '${BF_FREETYPE}/include ${BF_FREETYPE}/include/freetype2'
+BF_FREETYPE_LIB = 'freetype'
+BF_FREETYPE_LIBPATH = '${BF_FREETYPE}/lib'
+
+WITH_BF_QUICKTIME = True
+
+WITH_BF_ICONV = True
+BF_ICONV = '/usr'
+BF_ICONV_INC = '${BF_ICONV}/include'
+BF_ICONV_LIB = 'iconv'
+#BF_ICONV_LIBPATH = '${BF_ICONV}/lib'
+
+# Mesa Libs should go here if your using them as well....
+WITH_BF_STATICOPENGL = True
+BF_OPENGL_LIB = 'GL GLU'
+BF_OPENGL_LIBPATH = '/System/Library/Frameworks/OpenGL.framework/Libraries'
+BF_OPENGL_LINKFLAGS = ['-framework', 'OpenGL']
+
+#OpenCollada flags
+WITH_BF_COLLADA = True
+BF_COLLADA = '#source/blender/collada'
+BF_COLLADA_INC = '${BF_COLLADA}'
+BF_COLLADA_LIB = 'bf_collada'
+BF_OPENCOLLADA = LIBDIR + '/opencollada'
+BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include'
+BF_OPENCOLLADA_LIB = 'OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils OpenCOLLADAStreamWriter MathMLSolver GeneratedSaxParser UTF xml2 buffer ftoa'
+BF_OPENCOLLADA_LIBPATH = LIBDIR + '/opencollada'
+BF_PCRE = LIBDIR + '/opencollada'
+BF_PCRE_LIB = 'pcre'
+BF_PCRE_LIBPATH = '${BF_PCRE}/lib'
+#BF_EXPAT = '/usr'
+#BF_EXPAT_LIB = 'expat'
+#BF_EXPAT_LIBPATH = '/usr/lib'
+
+# Cycles
+WITH_BF_CYCLES = True
+
+#OSL
+
+WITH_BF_CYCLES_OSL = True
+BF_OSL = LIBDIR + '/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 oslquery'
+BF_OSL_LIBPATH = '${BF_OSL}/lib'
+BF_OSL_COMPILER = '${BF_OSL}/bin/oslc'
+
+WITH_BF_LLVM = True
+BF_LLVM = LIBDIR + '/llvm'
+BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \
+ 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \
+ 'LLVMTarget LLVMMC LLVMCore LLVMSupport'
+BF_LLVM_LIBPATH = '${BF_LLVM}/lib'
+
+WITH_BF_OIIO = True
+BF_OIIO = LIBDIR + '/openimageio'
+BF_OIIO_INC = '${BF_OIIO}/include'
+BF_OIIO_LIB = 'OpenImageIO'
+BF_OIIO_LIBPATH = '${BF_OIIO}/lib'
+
+WITH_BF_OCIO = True
+BF_OCIO = LIBDIR + '/opencolorio'
+BF_OCIO_INC = '${BF_OCIO}/include'
+BF_OCIO_LIB = 'OpenColorIO tinyxml yaml-cpp'
+BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
+
+WITH_BF_BOOST = True
+BF_BOOST = LIBDIR + '/boost'
+BF_BOOST_INC = '${BF_BOOST}/include'
+BF_BOOST_LIB = 'boost_date_time-mt boost_filesystem-mt boost_regex-mt boost_system-mt boost_thread-mt boost_wave-mt'
+BF_BOOST_LIB_INTERNATIONAL = 'boost_locale-mt'
+BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
+
+WITH_BF_CYCLES_CUDA_BINARIES = True
+BF_CYCLES_CUDA_NVCC = '/usr/local/cuda/bin/nvcc'
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30']
+
+#Ray trace optimization
+if MACOSX_ARCHITECTURE == 'x86_64' or MACOSX_ARCHITECTURE == 'i386':
+ WITH_BF_RAYOPTIMIZATION = True
+else:
+ WITH_BF_RAYOPTIMIZATION = False
+if MACOSX_ARCHITECTURE == 'i386':
+ BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse']
+elif MACOSX_ARCHITECTURE == 'x86_64':
+ BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-msse2']
+
+# SpaceNavigator and related 3D mice, driver must be 3DxWare 10 Beta 4 (Mac OS X) or later !
+WITH_BF_3DMOUSE = True
+
+#############################################################################
+################### various compile settings and flags ##################
+#############################################################################
+
+BF_QUIET = '1' # suppress verbose output
+
+if MACOSX_ARCHITECTURE == 'x86_64' or MACOSX_ARCHITECTURE == 'ppc64':
+ ARCH_FLAGS = ['-m64']
+else:
+ ARCH_FLAGS = ['-m32']
+
+CFLAGS = []
+CXXFLAGS = []
+CCFLAGS = ['-pipe','-funsigned-char']
+
+CPPFLAGS = list(ARCH_FLAGS)
+
+if WITH_GHOST_COCOA:
+ PLATFORM_LINKFLAGS = ['-fexceptions','-framework','CoreServices','-framework','Foundation','-framework','IOKit','-framework','AppKit','-framework','Cocoa','-framework','Carbon','-framework','AudioUnit','-framework','AudioToolbox','-framework','CoreAudio','-framework','OpenAL']+ARCH_FLAGS
+else:
+ PLATFORM_LINKFLAGS = ['-fexceptions','-framework','CoreServices','-framework','Foundation','-framework','IOKit','-framework','AppKit','-framework','Carbon','-framework','AGL','-framework','AudioUnit','-framework','AudioToolbox','-framework','CoreAudio','-framework','OpenAL']+ARCH_FLAGS
+
+if WITH_BF_QUICKTIME:
+ if USE_QTKIT:
+ PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QTKit']
+ else:
+ PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QuickTime']
+
+if not WITH_OSX_STATICPYTHON:
+ PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','Python']
+
+
+#note to build succesfully on 10.3.9 SDK you need to patch 10.3.9 by adding the SystemStubs.a lib from 10.4
+#for > 10.7.sdk, SystemStubs needs to be excluded (lib doesn't exist anymore)
+if MACOSX_SDK.endswith("10.7.sdk") or MACOSX_SDK.endswith("10.8.sdk"):
+ LLIBS = ['stdc++']
+else:
+ LLIBS = ['stdc++', 'SystemStubs']
+
+# some flags shuffling for different OS versions
+if MAC_MIN_VERS == '10.3':
+ CCFLAGS = ['-fuse-cxa-atexit'] + CCFLAGS
+ PLATFORM_LINKFLAGS = ['-fuse-cxa-atexit'] + PLATFORM_LINKFLAGS
+ LLIBS.append('crt3.o')
+
+if USE_SDK:
+ SDK_FLAGS=['-isysroot', MACOSX_SDK,'-mmacosx-version-min='+MAC_MIN_VERS,'-arch',MACOSX_ARCHITECTURE]
+ PLATFORM_LINKFLAGS = ['-mmacosx-version-min='+MAC_MIN_VERS,'-Wl','-isysroot',MACOSX_SDK,'-arch',MACOSX_ARCHITECTURE]+PLATFORM_LINKFLAGS
+ CCFLAGS=SDK_FLAGS+CCFLAGS
+ CXXFLAGS=SDK_FLAGS+CXXFLAGS
+
+#Intel Macs are CoreDuo and Up
+if MACOSX_ARCHITECTURE == 'i386' or MACOSX_ARCHITECTURE == 'x86_64':
+ REL_CFLAGS = []
+ REL_CXXFLAGS = []
+ REL_CCFLAGS = ['-DNDEBUG', '-O2','-ftree-vectorize','-msse','-msse2','-msse3','-mfpmath=sse']
+else:
+ CCFLAGS += ['-fno-strict-aliasing']
+ REL_CFLAGS = []
+ REL_CXXFLAGS = []
+ REL_CCFLAGS = ['-DNDEBUG', '-O2']
+
+# Intel 64bit Macs are Core2Duo and up
+if MACOSX_ARCHITECTURE == 'x86_64':
+ REL_CCFLAGS += ['-march=core2','-mssse3','-with-tune=core2','-enable-threads']
+
+CC_WARN = ['-Wall']
+C_WARN = ['-Wno-char-subscripts', '-Wpointer-arith', '-Wcast-align', '-Wdeclaration-after-statement', '-Wno-unknown-pragmas', '-Wstrict-prototypes']
+CXX_WARN = ['-Wno-invalid-offsetof', '-Wno-sign-compare']
+
+##FIX_STUBS_WARNINGS = -Wno-unused
+
+##LOPTS = --dynamic
+##DYNLDFLAGS = -shared $(LDFLAGS)
+
+BF_PROFILE_CCFLAGS = ['-pg', '-g ']
+BF_PROFILE_LINKFLAGS = ['-pg']
+BF_PROFILE = False
+
+BF_DEBUG = False
+BF_DEBUG_CCFLAGS = ['-g', '-D_DEBUG']
+
+#############################################################################
+################### Output directories ##################
+#############################################################################
+
+BF_BUILDDIR='../build/darwin'
+BF_INSTALLDIR='../install/darwin'
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 96f201235c4..a99337f03e6 100644
--- a/build_files/buildbot/config/user-config-player-glibc211-i686.py
+++ b/build_files/buildbot/config/user-config-player-glibc211-i686.py
@@ -1,6 +1,6 @@
BF_BUILDDIR = '../blender-build/linux-glibc211-i686'
BF_INSTALLDIR = '../blender-install/linux-glibc211-i686'
-BF_NUMJOBS = 2
+BF_NUMJOBS = 4
# Python configuration
BF_PYTHON_VERSION = '3.3'
@@ -103,7 +103,7 @@ BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBP
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
# JACK
-WITH_BF_JACK = True
+WITH_BF_JACK = False
WITH_BF_STATICJACK = True
BF_JACK_LIB_STATIC = '${BF_ZLIB}/lib/libjack.a'
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 75979d0bcfe..c17cff2893d 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
@@ -1,6 +1,6 @@
BF_BUILDDIR = '../blender-build/linux-glibc211-x86_64'
BF_INSTALLDIR = '../blender-install/linux-glibc211-x86_64'
-BF_NUMJOBS = 2
+BF_NUMJOBS = 4
# Python configuration
BF_PYTHON_VERSION = '3.3'
@@ -103,7 +103,7 @@ BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBP
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
# JACK
-WITH_BF_JACK = True
+WITH_BF_JACK = False
WITH_BF_STATICJACK = True
BF_JACK_LIB_STATIC = '${BF_ZLIB}/lib/libjack.a'
diff --git a/build_files/buildbot/config/user-config-player-glibc27-i686.py b/build_files/buildbot/config/user-config-player-glibc27-i686.py
deleted file mode 100644
index 82b105c4527..00000000000
--- a/build_files/buildbot/config/user-config-player-glibc27-i686.py
+++ /dev/null
@@ -1,114 +0,0 @@
-BF_BUILDDIR = '../blender-build/linux-glibc27-i686'
-BF_INSTALLDIR = '../blender-install/linux-glibc27-i686'
-BF_NUMJOBS = 2
-
-# Python configuration
-BF_PYTHON_VERSION = '3.3'
-BF_PYTHON_ABI_FLAGS = 'm'
-BF_PYTHON = '/opt/python3'
-
-WITH_BF_STATICPYTHON = True
-
-# OpenCollada configuration
-WITH_BF_COLLADA = False
-
-# FFMPEG configuration
-WITH_BF_FFMPEG = True
-WITH_BF_STATICFFMPEG = True
-
-BF_FFMPEG = '/home/sources/staticlibs/ffmpeg'
-BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib32'
-BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libswscale.a ' + \
- '${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \
- '${BF_FFMPEG_LIBPATH}/libxvidcore.a ${BF_FFMPEG_LIBPATH}/libx264.a ${BF_FFMPEG_LIBPATH}/libmp3lame.a ' + \
- '${BF_FFMPEG_LIBPATH}/libvpx.a ${BF_FFMPEG_LIBPATH}/libvorbis.a ${BF_FFMPEG_LIBPATH}/libogg.a ' + \
- '${BF_FFMPEG_LIBPATH}/libvorbisenc.a ${BF_FFMPEG_LIBPATH}/libtheora.a ' + \
- '${BF_FFMPEG_LIBPATH}/libschroedinger-1.0.a ${BF_FFMPEG_LIBPATH}/liborc-0.4.a ${BF_FFMPEG_LIBPATH}/libdirac_encoder.a ' + \
- '${BF_FFMPEG_LIBPATH}/libfaad.a'
-
-# Don't depend on system's libstdc++
-WITH_BF_STATICCXX = True
-BF_CXX_LIB_STATIC = '/usr/lib/gcc/i486-linux-gnu/4.3.4/libstdc++.a'
-
-WITH_BF_OPENAL = True
-WITH_BF_STATICOPENAL = True
-BF_OPENAL_LIB_STATIC = '/opt/openal/lib/libopenal.a'
-
-WITH_BF_GETTEXT_STATIC = True
-BF_FREETYPE_LIB_STATIC = True
-
-WITH_BF_OPENEXR = False
-WITH_BF_STATICOPENEXR = True
-
-WITH_BF_TIFF = False
-WITH_BF_STATICTIFF = True
-BF_TIFF_LIB_STATIC = '${BF_TIFF}/lib/libtiff.a'
-
-WITH_BF_JPEG = True
-BF_JPEG_LIB = 'libjpeg'
-BF_JPEG_LIBPATH = '/home/sources/staticlibs/lib32'
-
-WITH_BF_PNG = True
-BF_PNG_LIB = 'libpng'
-BF_PNG_LIBPATH = '/home/sources/staticlibs/lib32'
-
-WITH_BF_STATICLIBSAMPLERATE = True
-
-WITH_BF_ZLIB = True
-WITH_BF_STATICZLIB = True
-BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
-
-WITH_BF_SDL = True
-WITH_BF_OGG = False
-
-WITH_BF_OPENMP = True
-
-WITH_BF_GAMEENGINE = True
-WITH_BF_BULLET = True
-
-# Do not build blender when building blenderplayer
-WITH_BF_NOBLENDER = True
-WITH_BF_PLAYER = True
-
-# Use jemalloc memory manager
-WITH_BF_JEMALLOC = True
-WITH_BF_STATICJEMALLOC = True
-BF_JEMALLOC = '/home/sources/staticlibs/jemalloc'
-BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib32'
-
-# Use 3d mouse library
-WITH_BF_3DMOUSE = True
-WITH_BF_STATIC3DMOUSE = True
-BF_3DMOUSE = '/home/sources/staticlibs/spnav'
-BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib32'
-
-# Color management
-WITH_BF_OCIO = True
-WITH_BF_STATICOCIO = True
-BF_OCIO = '/opt/ocio'
-BF_OCIO_INC = '${BF_OCIO}/include'
-BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a'
-BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
-
-WITH_BF_BOOST = True
-WITH_BF_STATICBOOST = True
-BF_BOOST = '/opt/boost'
-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'
-BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
-
-# JACK
-WITH_BF_JACK = True
-
-# Motion Tracking
-WITH_BF_LIBMV = False
-
-# Ocean Simulation
-WITH_BF_FFTW3 = True
-WITH_BF_STATICFFTW3 = True
-WITH_BF_OCEANSIM = True
-
-# Compilation and optimization
-BF_DEBUG = False
-REL_CCFLAGS = ['-DNDEBUG', '-O2'] # C & C++
-PLATFORM_LINKFLAGS = ['-L/home/sources/staticlibs/lib32']
diff --git a/build_files/buildbot/config/user-config-player-glibc27-x86_64.py b/build_files/buildbot/config/user-config-player-glibc27-x86_64.py
deleted file mode 100644
index 1e6aa4af802..00000000000
--- a/build_files/buildbot/config/user-config-player-glibc27-x86_64.py
+++ /dev/null
@@ -1,114 +0,0 @@
-BF_BUILDDIR = '../blender-build/linux-glibc27-x86_64'
-BF_INSTALLDIR = '../blender-install/linux-glibc27-x86_64'
-BF_NUMJOBS = 2
-
-# Python configuration
-BF_PYTHON_VERSION = '3.3'
-BF_PYTHON_ABI_FLAGS = 'm'
-BF_PYTHON = '/opt/python3'
-
-WITH_BF_STATICPYTHON = True
-
-# OpenCollada configuration
-WITH_BF_COLLADA = False
-
-# FFMPEG configuration
-WITH_BF_FFMPEG = True
-WITH_BF_STATICFFMPEG = True
-
-BF_FFMPEG = '/home/sources/staticlibs/ffmpeg'
-BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib64'
-BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libswscale.a ' + \
- '${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \
- '${BF_FFMPEG_LIBPATH}/libxvidcore.a ${BF_FFMPEG_LIBPATH}/libx264.a ${BF_FFMPEG_LIBPATH}/libmp3lame.a ' + \
- '${BF_FFMPEG_LIBPATH}/libvpx.a ${BF_FFMPEG_LIBPATH}/libvorbis.a ${BF_FFMPEG_LIBPATH}/libogg.a ' + \
- '${BF_FFMPEG_LIBPATH}/libvorbisenc.a ${BF_FFMPEG_LIBPATH}/libtheora.a ' + \
- '${BF_FFMPEG_LIBPATH}/libschroedinger-1.0.a ${BF_FFMPEG_LIBPATH}/liborc-0.4.a ${BF_FFMPEG_LIBPATH}/libdirac_encoder.a ' + \
- '${BF_FFMPEG_LIBPATH}/libfaad.a'
-
-# Don't depend on system's libstdc++
-WITH_BF_STATICCXX = True
-BF_CXX_LIB_STATIC = '/usr/lib/gcc/x86_64-linux-gnu/4.3.4/libstdc++.a'
-
-WITH_BF_OPENAL = True
-WITH_BF_STATICOPENAL = True
-BF_OPENAL_LIB_STATIC = '/opt/openal/lib/libopenal.a'
-
-WITH_BF_GETTEXT_STATIC = True
-BF_FREETYPE_LIB_STATIC = True
-
-WITH_BF_OPENEXR = False
-WITH_BF_STATICOPENEXR = True
-
-WITH_BF_TIFF = False
-WITH_BF_STATICTIFF = True
-BF_TIFF_LIB_STATIC = '${BF_TIFF}/lib/libtiff.a'
-
-WITH_BF_JPEG = True
-BF_JPEG_LIB = 'libjpeg'
-BF_JPEG_LIBPATH = '/home/sources/staticlibs/lib64'
-
-WITH_BF_STATICLIBSAMPLERATE = True
-
-WITH_BF_PNG = True
-BF_PNG_LIB = 'libpng'
-BF_PNG_LIBPATH = '/home/sources/staticlibs/lib64'
-
-WITH_BF_ZLIB = True
-WITH_BF_STATICZLIB = True
-BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a'
-
-WITH_BF_SDL = True
-WITH_BF_OGG = False
-
-WITH_BF_OPENMP = True
-
-WITH_BF_GAMEENGINE = True
-WITH_BF_BULLET = True
-
-# Do not build blender when building blenderplayer
-WITH_BF_NOBLENDER = True
-WITH_BF_PLAYER = True
-
-# Use jemalloc memory manager
-WITH_BF_JEMALLOC = True
-WITH_BF_STATICJEMALLOC = True
-BF_JEMALLOC = '/home/sources/staticlibs/jemalloc'
-BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib64'
-
-# Use 3d mouse library
-WITH_BF_3DMOUSE = True
-WITH_BF_STATIC3DMOUSE = True
-BF_3DMOUSE = '/home/sources/staticlibs/spnav'
-BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib64'
-
-# Color management
-WITH_BF_OCIO = True
-WITH_BF_STATICOCIO = True
-BF_OCIO = '/opt/ocio'
-BF_OCIO_INC = '${BF_OCIO}/include'
-BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a'
-BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
-
-WITH_BF_BOOST = True
-WITH_BF_STATICBOOST = True
-BF_BOOST = '/opt/boost'
-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'
-BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
-
-# JACK
-WITH_BF_JACK = True
-
-# Motion Tracking
-WITH_BF_LIBMV = False
-
-# Ocean Simulation
-WITH_BF_FFTW3 = True
-WITH_BF_STATICFFTW3 = True
-WITH_BF_OCEANSIM = True
-
-# Compilation and optimization
-BF_DEBUG = False
-REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++
-PLATFORM_LINKFLAGS = ['-L/home/sources/staticlibs/lib64']
diff --git a/build_files/buildbot/master.cfg b/build_files/buildbot/master.cfg
index 90f0c805f58..3cfea2a3abd 100644
--- a/build_files/buildbot/master.cfg
+++ b/build_files/buildbot/master.cfg
@@ -28,8 +28,8 @@ c['slavePortnum'] = 9989
from buildbot.changes.svnpoller import SVNPoller
c['change_source'] = SVNPoller(
- 'https://svn.blender.org/svnroot/bf-blender/trunk/',
- pollinterval=1200)
+ 'https://svn.blender.org/svnroot/bf-blender/trunk/',
+ pollinterval=1200)
# BUILDERS
#
@@ -74,9 +74,11 @@ def svn_step(branch=''):
else:
return SVN(baseURL='https://svn.blender.org/svnroot/bf-blender/%%BRANCH%%/blender', mode='update', defaultBranch='trunk', workdir='blender')
+
def lib_svn_step(dir):
return SVN(name='lib svn', baseURL='https://svn.blender.org/svnroot/bf-blender/%%BRANCH%%/lib/' + dir, mode='update', defaultBranch='trunk', workdir='lib/' + dir)
+
def rsync_step(id, branch, rsync_script):
return ShellCommand(name='rsync', command=['python', rsync_script, id, branch], description='uploading', descriptionDone='uploaded', workdir='install')
@@ -116,10 +118,10 @@ add_builder(c, 'mac_x86_64_10_5_scons', '', generic_builder, '', True)
add_builder(c, 'mac_i386_scons', 'darwin-9.x.universal', generic_builder)
add_builder(c, 'mac_ppc_scons', 'darwin-9.x.universal', generic_builder)
#add_builder(c, 'linux_x86_64_cmake', '', generic_builder)
-add_builder(c, 'linux_glibc27_i386_scons', '', generic_builder)
+#add_builder(c, 'linux_glibc27_i386_scons', '', generic_builder)
add_builder(c, 'linux_glibc211_i386_scons', '', generic_builder)
#add_builder(c, 'salad_linux_i386_scons', '', generic_builder, 'soc-2011-salad')
-add_builder(c, 'linux_glibc27_x86_64_scons', '', generic_builder)
+#add_builder(c, 'linux_glibc27_x86_64_scons', '', generic_builder)
add_builder(c, 'linux_glibc211_x86_64_scons', '', generic_builder)
#add_builder(c, 'salad_linux_x86_64_scons', '', generic_builder, 'soc-2011-salad')
add_builder(c, 'win32_scons', 'windows', generic_builder)
@@ -155,9 +157,9 @@ for i in range(0, schedule_cycle):
print(names)
c['schedulers'].append(timed.Nightly(name='nightly' + str(i),
- builderNames=names,
- hour=3+i,
- minute=0))
+ builderNames=names,
+ hour=3 + i,
+ minute=0))
# STATUS TARGETS
#
diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py
index bedada93a5a..caa4acc4ecd 100644
--- a/build_files/buildbot/slave_compile.py
+++ b/build_files/buildbot/slave_compile.py
@@ -21,6 +21,7 @@
import os
import subprocess
import sys
+import shutil
# get builder name
if len(sys.argv) < 2:
@@ -57,36 +58,41 @@ else:
scons_cmd = ['python', 'scons/scons.py']
scons_options = ['BF_FANCY=False']
- if builder.find('linux') != -1:
- import shutil
-
- # We're using the same rules as release builder, so tweak
- # build and install dirs
- build_dir = os.path.join('..', 'build', builder)
- install_dir = os.path.join('..', 'install', builder)
+ # We're using the same rules as release builder, so tweak
+ # build and install dirs
+ build_dir = os.path.join('..', 'build', builder)
+ install_dir = os.path.join('..', 'install', builder)
- common_options = ['BF_INSTALLDIR=' + install_dir] + scons_options
+ # Clean install directory so we'll be sure there's no
+ if os.path.isdir(install_dir):
+ shutil.rmtree(install_dir)
- # Clean install directory so we'll be sure there's no
- if os.path.isdir(install_dir):
- shutil.rmtree(install_dir)
-
- buildbot_dir = os.path.dirname(os.path.realpath(__file__))
- config_dir = os.path.join(buildbot_dir, 'config')
+ buildbot_dir = os.path.dirname(os.path.realpath(__file__))
+ config_dir = os.path.join(buildbot_dir, 'config')
+ if builder.find('linux') != -1:
configs = []
- if builder.endswith('linux_glibc27_x86_64_scons'):
- configs = ['user-config-player-glibc27-x86_64.py',
- 'user-config-glibc27-x86_64.py']
- elif builder.endswith('linux_glibc27_i386_scons'):
- configs = ['user-config-player-glibc27-i686.py',
- 'user-config-glibc27-i686.py']
if builder.endswith('linux_glibc211_x86_64_scons'):
configs = ['user-config-player-glibc211-x86_64.py',
- 'user-config-glibc211-x86_64.py']
+ 'user-config-cuda-glibc211-x86_64.py',
+ 'user-config-glibc211-x86_64.py'
+ ]
+ chroot_name = 'buildbot_squeeze_x86_64'
+ cuda_chroot = 'buildbot_squeeze_x86_64'
elif builder.endswith('linux_glibc211_i386_scons'):
configs = ['user-config-player-glibc211-i686.py',
+ 'user-config-cuda-glibc211-i686.py',
'user-config-glibc211-i686.py']
+ chroot_name = 'buildbot_squeeze_i686'
+
+ # use 64bit cuda toolkit, so there'll be no memory limit issues
+ cuda_chroot = 'buildbot_squeeze_x86_64'
+
+ # Compilation will happen inside of chroot environment
+ prog_scons_cmd = ['schroot', '-c', chroot_name, '--'] + scons_cmd
+ cuda_scons_cmd = ['schroot', '-c', cuda_chroot, '--'] + scons_cmd
+
+ common_options = ['BF_INSTALLDIR=' + install_dir] + scons_options
for config in configs:
config_fpath = os.path.join(config_dir, config)
@@ -100,14 +106,24 @@ else:
scons_options += common_options
- if config.find('player') == -1:
- scons_options.append('blender')
- else:
+ if config.find('player') != -1:
scons_options.append('blenderplayer')
+ cur_scons_cmd = prog_scons_cmd
+ elif config.find('cuda') != -1:
+ scons_options.append('cudakernels')
+ cur_scons_cmd = cuda_scons_cmd
+
+ if config.find('i686') != -1:
+ scons_options.append('BF_BITNESS=32')
+ elif config.find('x86_64') != -1:
+ scons_options.append('BF_BITNESS=64')
+ else:
+ scons_options.append('blender')
+ cur_scons_cmd = prog_scons_cmd
scons_options.append('BF_CONFIG=' + config_fpath)
- retcode = subprocess.call(scons_cmd + scons_options)
+ retcode = subprocess.call(cur_scons_cmd + scons_options)
if retcode != 0:
print('Error building rules wuth config ' + config)
sys.exit(retcode)
@@ -120,11 +136,30 @@ else:
if builder.find('win64') != -1:
bitness = '64'
+ scons_options.append('BF_INSTALLDIR=' + install_dir)
+ scons_options.append('BF_BUILDDIR=' + build_dir)
scons_options.append('BF_BITNESS=' + bitness)
scons_options.append('WITH_BF_CYCLES_CUDA_BINARIES=True')
scons_options.append('BF_CYCLES_CUDA_NVCC=nvcc.exe')
if builder.find('mingw') != -1:
scons_options.append('BF_TOOLSET=mingw')
+ elif builder.find('mac') != -1:
+ if builder.find('x86_64') != -1:
+ config = 'user-config-mac-x86_64.py'
+ else:
+ config = 'user-config-mac-i386.py'
+
+ scons_options.append('BF_CONFIG=' + os.path.join(config_dir, config))
retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options)
+
+ if builder.find('win') != -1:
+ dlls = ('msvcm90.dll', 'msvcp90.dll', 'msvcr90.dll', 'vcomp90.dll', 'Microsoft.VC90.CRT.manifest', 'Microsoft.VC90.OpenMP.manifest')
+ if builder.find('win64') == -1:
+ dlls_path = 'C:\\b\\redist\\x86'
+ else:
+ dlls_path = 'C:\\b\\redist\\amd64'
+ for dll in dlls:
+ shutil.copyfile(os.path.join(dlls_path, dll), os.path.join(install_dir, dll))
+
sys.exit(retcode)
diff --git a/build_files/buildbot/slave_pack.py b/build_files/buildbot/slave_pack.py
index b7775ef872f..3c2569e4a69 100644
--- a/build_files/buildbot/slave_pack.py
+++ b/build_files/buildbot/slave_pack.py
@@ -43,12 +43,12 @@ if builder.find('scons') != -1:
os.chdir('../blender')
scons_options = ['BF_QUICK=slnt', 'BUILDBOT_BRANCH=' + branch, 'buildslave', 'BF_FANCY=False']
- if builder.find('linux') != -1:
- buildbot_dir = os.path.dirname(os.path.realpath(__file__))
- config_dir = os.path.join(buildbot_dir, 'config')
- build_dir = os.path.join('..', 'build', builder)
- install_dir = os.path.join('..', 'install', builder)
+ buildbot_dir = os.path.dirname(os.path.realpath(__file__))
+ config_dir = os.path.join(buildbot_dir, 'config')
+ build_dir = os.path.join('..', 'build', builder)
+ install_dir = os.path.join('..', 'install', builder)
+ if builder.find('linux') != -1:
scons_options += ['WITH_BF_NOBLENDER=True', 'WITH_BF_PLAYER=False',
'BF_BUILDDIR=' + build_dir,
'BF_INSTALLDIR=' + install_dir,
@@ -57,17 +57,13 @@ if builder.find('scons') != -1:
config = None
bits = None
- if builder.endswith('linux_glibc27_x86_64_scons'):
- config = 'user-config-glibc27-x86_64.py'
- bits = 64
- elif builder.endswith('linux_glibc27_i386_scons'):
- config = 'user-config-glibc27-i686.py'
- bits = 32
if builder.endswith('linux_glibc211_x86_64_scons'):
config = 'user-config-glibc211-x86_64.py'
+ chroot_name = 'buildbot_squeeze_x86_64'
bits = 64
elif builder.endswith('linux_glibc211_i386_scons'):
config = 'user-config-glibc211-i686.py'
+ chroot_name = 'buildbot_squeeze_i686'
bits = 32
if config is not None:
@@ -76,7 +72,7 @@ if builder.find('scons') != -1:
blender = os.path.join(install_dir, 'blender')
blenderplayer = os.path.join(install_dir, 'blenderplayer')
- subprocess.call(['strip', '--strip-all', blender, blenderplayer])
+ subprocess.call(['schroot', '-c', chroot_name, '--', 'strip', '--strip-all', blender, blenderplayer])
extra = '/' + os.path.join('home', 'sources', 'release-builder', 'extra')
mesalibs = os.path.join(extra, 'mesalibs' + str(bits) + '.tar.bz2')
@@ -86,7 +82,7 @@ if builder.find('scons') != -1:
os.system('cp %s %s' % (software_gl, install_dir))
os.system('chmod 755 %s' % (os.path.join(install_dir, 'blender-softwaregl')))
- retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options)
+ retcode = subprocess.call(['schroot', '-c', chroot_name, '--', 'python', 'scons/scons.py'] + scons_options)
sys.exit(retcode)
else:
@@ -96,12 +92,22 @@ if builder.find('scons') != -1:
if builder.find('win64') != -1:
bitness = '64'
+ scons_options.append('BF_INSTALLDIR=' + install_dir)
+ scons_options.append('BF_BUILDDIR=' + build_dir)
scons_options.append('BF_BITNESS=' + bitness)
scons_options.append('WITH_BF_CYCLES_CUDA_BINARIES=True')
scons_options.append('BF_CYCLES_CUDA_NVCC=nvcc.exe')
if builder.find('mingw') != -1:
scons_options.append('BF_TOOLSET=mingw')
+ elif builder.find('mac') != -1:
+ if builder.find('x86_64') != -1:
+ config = 'user-config-mac-x86_64.py'
+ else:
+ config = 'user-config-mac-i386.py'
+
+ scons_options.append('BF_CONFIG=' + os.path.join(config_dir, config))
+
retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options)
sys.exit(retcode)
diff --git a/build_files/buildbot/slave_rsync.py b/build_files/buildbot/slave_rsync.py
index aea1b65e333..6936232a495 100644
--- a/build_files/buildbot/slave_rsync.py
+++ b/build_files/buildbot/slave_rsync.py
@@ -41,5 +41,3 @@ print(command)
ret = os.system(command)
sys.exit(ret)
-
-
diff --git a/build_files/cmake/Modules/FindOpenCOLLADA.cmake b/build_files/cmake/Modules/FindOpenCOLLADA.cmake
index 169d3a82fc7..84aead58b60 100644
--- a/build_files/cmake/Modules/FindOpenCOLLADA.cmake
+++ b/build_files/cmake/Modules/FindOpenCOLLADA.cmake
@@ -66,6 +66,7 @@ SET(_opencollada_SEARCH_DIRS
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
+ /opt/lib/opencollada
)
SET(_opencollada_INCLUDES)
diff --git a/build_files/cmake/clang_array_check.py b/build_files/cmake/clang_array_check.py
index 3070c27f769..fc85b5c454d 100644
--- a/build_files/cmake/clang_array_check.py
+++ b/build_files/cmake/clang_array_check.py
@@ -115,7 +115,7 @@ args = sys.argv[2:]
# print(args)
tu = index.parse(sys.argv[1], args)
-print('Translation unit: %s' % tu.spelling)
+# print('Translation unit: %s' % tu.spelling)
# -----------------------------------------------------------------------------
diff --git a/build_files/cmake/cmake_consistency_check.py b/build_files/cmake/cmake_consistency_check.py
index b13b0ddb424..665bc600efa 100755
--- a/build_files/cmake/cmake_consistency_check.py
+++ b/build_files/cmake/cmake_consistency_check.py
@@ -75,12 +75,12 @@ def is_cmake(filename):
def is_c_header(filename):
ext = splitext(filename)[1]
- return (ext in (".h", ".hpp", ".hxx"))
+ return (ext in {".h", ".hpp", ".hxx", ".hh"})
def is_c(filename):
ext = splitext(filename)[1]
- return (ext in (".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl"))
+ return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl"})
def is_c_any(filename):
diff --git a/build_files/cmake/cmake_consistency_check_config.py b/build_files/cmake/cmake_consistency_check_config.py
index 6b82e224a32..55bad251a53 100644
--- a/build_files/cmake/cmake_consistency_check_config.py
+++ b/build_files/cmake/cmake_consistency_check_config.py
@@ -29,6 +29,22 @@ IGNORE = (
"extern/recastnavigation/Recast/Source/RecastTimer.cpp",
"intern/audaspace/SRC/AUD_SRCResampleFactory.cpp",
"intern/audaspace/SRC/AUD_SRCResampleReader.cpp",
+ "intern/cycles/render/film_response.cpp",
+ "extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_2.cc",
+ "extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_3.cc",
+ "extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_4.cc",
+ "extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_d.cc",
+ "extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_3.cc",
+ "extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_4.cc",
+ "extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_9.cc",
+ "extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_d.cc",
+ "extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_3.cc",
+ "extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_4.cc",
+ "extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_d.cc",
+ "extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_2.cc",
+ "extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_3.cc",
+ "extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_4.cc",
+ "extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_d.cc",
"extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h",
"extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h",
@@ -47,6 +63,11 @@ IGNORE = (
"extern/recastnavigation/Recast/Include/RecastTimer.h",
"intern/audaspace/SRC/AUD_SRCResampleFactory.h",
"intern/audaspace/SRC/AUD_SRCResampleReader.h",
+ "intern/cycles/render/film_response.h",
+ "extern/carve/include/carve/config.h",
+ "extern/carve/include/carve/external/boost/random.hpp",
+ "extern/carve/patches/files/config.h",
+ "extern/carve/patches/files/random.hpp",
)
UTF8_CHECK = True
diff --git a/build_files/cmake/cmake_netbeans_project.py b/build_files/cmake/cmake_netbeans_project.py
index 2f36cad4d24..17490e36bb3 100755
--- a/build_files/cmake/cmake_netbeans_project.py
+++ b/build_files/cmake/cmake_netbeans_project.py
@@ -56,6 +56,10 @@ def create_nb_project_main():
pass
else:
includes, defines = cmake_advanced_info()
+
+ if (includes, defines) == (None, None):
+ return
+
# for some reason it doesnt give all internal includes
includes = list(set(includes) | set(dirname(f) for f in files if is_c_header(f)))
includes.sort()
diff --git a/build_files/cmake/cmake_qtcreator_project.py b/build_files/cmake/cmake_qtcreator_project.py
index 86201da23de..4cf854aad77 100755
--- a/build_files/cmake/cmake_qtcreator_project.py
+++ b/build_files/cmake/cmake_qtcreator_project.py
@@ -81,6 +81,9 @@ def create_qtc_project_main():
else:
includes, defines = cmake_advanced_info()
+ if (includes, defines) == (None, None):
+ return
+
# for some reason it doesnt give all internal includes
includes = list(set(includes) | set(os.path.dirname(f)
for f in files_rel if is_c_header(f)))
diff --git a/build_files/cmake/cmake_static_check_clang_array.py b/build_files/cmake/cmake_static_check_clang_array.py
index 7f45cc6aadc..448454c2177 100644
--- a/build_files/cmake/cmake_static_check_clang_array.py
+++ b/build_files/cmake/cmake_static_check_clang_array.py
@@ -50,7 +50,7 @@ def main():
check_commands = []
for c, inc_dirs, defs in source_info:
cmd = ([CHECKER_BIN] +
- CHECKER_ARGS +
+ CHECKER_ARGS +
[c] +
[("-I%s" % i) for i in inc_dirs] +
[("-D%s" % d) for d in defs]
diff --git a/build_files/cmake/cmake_static_check_cppcheck.py b/build_files/cmake/cmake_static_check_cppcheck.py
index d79145f8586..2f7ffa5c240 100644
--- a/build_files/cmake/cmake_static_check_cppcheck.py
+++ b/build_files/cmake/cmake_static_check_cppcheck.py
@@ -56,7 +56,7 @@ def main():
check_commands = []
for c, inc_dirs, defs in source_info:
cmd = ([CHECKER_BIN] +
- CHECKER_ARGS +
+ CHECKER_ARGS +
[c] +
[("-I%s" % i) for i in inc_dirs] +
[("-D%s" % d) for d in defs]
diff --git a/build_files/cmake/cmake_static_check_smatch.py b/build_files/cmake/cmake_static_check_smatch.py
index 7535f1cc55a..2cf07b093fb 100644
--- a/build_files/cmake/cmake_static_check_smatch.py
+++ b/build_files/cmake/cmake_static_check_smatch.py
@@ -41,6 +41,7 @@ import os
USE_QUIET = (os.environ.get("QUIET", None) is not None)
+
def main():
source_info = project_source_info.build_info(use_cxx=False, ignore_prefix_list=CHECKER_IGNORE_PREFIX)
@@ -48,7 +49,7 @@ def main():
for c, inc_dirs, defs in source_info:
cmd = ([CHECKER_BIN] +
- CHECKER_ARGS +
+ CHECKER_ARGS +
[c] +
[("-I%s" % i) for i in inc_dirs] +
[("-D%s" % d) for d in defs]
diff --git a/build_files/cmake/cmake_static_check_sparse.py b/build_files/cmake/cmake_static_check_sparse.py
index 06bef1a1327..8a3fb477239 100644
--- a/build_files/cmake/cmake_static_check_sparse.py
+++ b/build_files/cmake/cmake_static_check_sparse.py
@@ -47,7 +47,7 @@ def main():
for c, inc_dirs, defs in source_info:
cmd = ([CHECKER_BIN] +
- CHECKER_ARGS +
+ CHECKER_ARGS +
[c] +
[("-I%s" % i) for i in inc_dirs] +
[("-D%s" % d) for d in defs]
diff --git a/build_files/cmake/cmake_static_check_splint.py b/build_files/cmake/cmake_static_check_splint.py
index 5b1207543f5..6ad03f2bdca 100644
--- a/build_files/cmake/cmake_static_check_splint.py
+++ b/build_files/cmake/cmake_static_check_splint.py
@@ -79,7 +79,7 @@ def main():
check_commands = []
for c, inc_dirs, defs in source_info:
cmd = ([CHECKER_BIN] +
- CHECKER_ARGS +
+ CHECKER_ARGS +
[c] +
[("-I%s" % i) for i in inc_dirs] +
[("-D%s" % d) for d in defs]
diff --git a/build_files/cmake/config/blender_headless.cmake b/build_files/cmake/config/blender_headless.cmake
index c4d64125744..cfde86aac6d 100644
--- a/build_files/cmake/config/blender_headless.cmake
+++ b/build_files/cmake/config/blender_headless.cmake
@@ -5,19 +5,19 @@
# cmake -C../blender/build_files/cmake/config/blender_headless.cmake ../blender
#
-set(WITH_HEADLESS ON CACHE FORCE BOOL)
-set(WITH_GAMEENGINE OFF CACHE FORCE BOOL)
+set(WITH_HEADLESS ON CACHE BOOL "" FORCE)
+set(WITH_GAMEENGINE OFF CACHE BOOL "" FORCE)
# disable audio, its possible some devs may want this but for now disable
# so the python module doesnt hold the audio device and loads quickly.
-set(WITH_AUDASPACE OFF CACHE FORCE BOOL)
-set(WITH_FFTW3 OFF CACHE FORCE BOOL)
-set(WITH_JACK OFF CACHE FORCE BOOL)
-set(WITH_SDL OFF CACHE FORCE BOOL)
-set(WITH_OPENAL OFF CACHE FORCE BOOL)
-set(WITH_CODEC_FFMPEG OFF CACHE FORCE BOOL)
-set(WITH_CODEC_SNDFILE OFF CACHE FORCE BOOL)
+set(WITH_AUDASPACE OFF CACHE BOOL "" FORCE)
+set(WITH_FFTW3 OFF CACHE BOOL "" FORCE)
+set(WITH_JACK OFF CACHE BOOL "" FORCE)
+set(WITH_SDL OFF CACHE BOOL "" FORCE)
+set(WITH_OPENAL OFF CACHE BOOL "" FORCE)
+set(WITH_CODEC_FFMPEG OFF CACHE BOOL "" FORCE)
+set(WITH_CODEC_SNDFILE OFF CACHE BOOL "" FORCE)
# other features which are not especially useful as a python module
-set(WITH_X11_XINPUT OFF CACHE FORCE BOOL)
-set(WITH_INPUT_NDOF OFF CACHE FORCE BOOL)
+set(WITH_X11_XINPUT OFF CACHE BOOL "" FORCE)
+set(WITH_INPUT_NDOF OFF CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake
index e74d1adcb1b..f7778ac214d 100644
--- a/build_files/cmake/config/blender_lite.cmake
+++ b/build_files/cmake/config/blender_lite.cmake
@@ -5,47 +5,47 @@
# cmake -C../blender/build_files/cmake/config/blender_lite.cmake ../blender
#
-set(WITH_INSTALL_PORTABLE ON CACHE FORCE BOOL)
-set(WITH_SYSTEM_GLEW ON CACHE FORCE BOOL)
+set(WITH_INSTALL_PORTABLE ON CACHE BOOL "" FORCE)
+set(WITH_SYSTEM_GLEW ON CACHE BOOL "" FORCE)
-set(WITH_BUILDINFO OFF CACHE FORCE BOOL)
-set(WITH_BULLET OFF CACHE FORCE BOOL)
-set(WITH_CODEC_AVI OFF CACHE FORCE BOOL)
-set(WITH_CODEC_FFMPEG OFF CACHE FORCE BOOL)
-set(WITH_CODEC_SNDFILE OFF CACHE FORCE BOOL)
-set(WITH_CYCLES OFF CACHE FORCE BOOL)
-set(WITH_FFTW3 OFF CACHE FORCE BOOL)
-set(WITH_LIBMV OFF CACHE FORCE BOOL)
-set(WITH_GAMEENGINE OFF CACHE FORCE BOOL)
-set(WITH_COMPOSITOR OFF CACHE FORCE BOOL)
-set(WITH_GHOST_XDND OFF CACHE FORCE BOOL)
-set(WITH_IK_SOLVER OFF CACHE FORCE BOOL)
-set(WITH_IK_ITASC OFF CACHE FORCE BOOL)
-set(WITH_IMAGE_CINEON OFF CACHE FORCE BOOL)
-set(WITH_IMAGE_DDS OFF CACHE FORCE BOOL)
-set(WITH_IMAGE_FRAMESERVER OFF CACHE FORCE BOOL)
-set(WITH_IMAGE_HDR OFF CACHE FORCE BOOL)
-set(WITH_IMAGE_OPENEXR OFF CACHE FORCE BOOL)
-set(WITH_IMAGE_OPENJPEG OFF CACHE FORCE BOOL)
-set(WITH_IMAGE_REDCODE OFF CACHE FORCE BOOL)
-set(WITH_IMAGE_TIFF OFF CACHE FORCE BOOL)
-set(WITH_INPUT_NDOF OFF CACHE FORCE BOOL)
-set(WITH_INTERNATIONAL OFF CACHE FORCE BOOL)
-set(WITH_JACK OFF CACHE FORCE BOOL)
-set(WITH_LZMA OFF CACHE FORCE BOOL)
-set(WITH_LZO OFF CACHE FORCE BOOL)
-set(WITH_MOD_BOOLEAN OFF CACHE FORCE BOOL)
-set(WITH_MOD_FLUID OFF CACHE FORCE BOOL)
-set(WITH_MOD_REMESH OFF CACHE FORCE BOOL)
-set(WITH_MOD_SMOKE OFF CACHE FORCE BOOL)
-set(WITH_MOD_OCEANSIM OFF CACHE FORCE BOOL)
-set(WITH_AUDASPACE OFF CACHE FORCE BOOL)
-set(WITH_OPENAL OFF CACHE FORCE BOOL)
-set(WITH_OPENCOLLADA OFF CACHE FORCE BOOL)
-set(WITH_OPENCOLORIO OFF CACHE FORCE BOOL)
-set(WITH_OPENMP OFF CACHE FORCE BOOL)
-set(WITH_PYTHON_INSTALL OFF CACHE FORCE BOOL)
-set(WITH_RAYOPTIMIZATION OFF CACHE FORCE BOOL)
-set(WITH_SDL OFF CACHE FORCE BOOL)
-set(WITH_X11_XINPUT OFF CACHE FORCE BOOL)
-set(WITH_X11_XF86VMODE OFF CACHE FORCE BOOL)
+set(WITH_BUILDINFO OFF CACHE BOOL "" FORCE)
+set(WITH_BULLET OFF CACHE BOOL "" FORCE)
+set(WITH_CODEC_AVI OFF CACHE BOOL "" FORCE)
+set(WITH_CODEC_FFMPEG OFF CACHE BOOL "" FORCE)
+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_GAMEENGINE OFF CACHE BOOL "" FORCE)
+set(WITH_COMPOSITOR OFF CACHE BOOL "" FORCE)
+set(WITH_GHOST_XDND OFF CACHE BOOL "" FORCE)
+set(WITH_IK_SOLVER OFF CACHE BOOL "" FORCE)
+set(WITH_IK_ITASC OFF CACHE BOOL "" FORCE)
+set(WITH_IMAGE_CINEON OFF CACHE BOOL "" FORCE)
+set(WITH_IMAGE_DDS OFF CACHE BOOL "" FORCE)
+set(WITH_IMAGE_FRAMESERVER OFF CACHE BOOL "" FORCE)
+set(WITH_IMAGE_HDR OFF CACHE BOOL "" FORCE)
+set(WITH_IMAGE_OPENEXR OFF CACHE BOOL "" FORCE)
+set(WITH_IMAGE_OPENJPEG OFF CACHE BOOL "" FORCE)
+set(WITH_IMAGE_REDCODE OFF CACHE BOOL "" FORCE)
+set(WITH_IMAGE_TIFF OFF CACHE BOOL "" FORCE)
+set(WITH_INPUT_NDOF OFF CACHE BOOL "" FORCE)
+set(WITH_INTERNATIONAL OFF CACHE BOOL "" FORCE)
+set(WITH_JACK OFF CACHE BOOL "" FORCE)
+set(WITH_LZMA OFF CACHE BOOL "" FORCE)
+set(WITH_LZO OFF CACHE BOOL "" FORCE)
+set(WITH_MOD_BOOLEAN OFF CACHE BOOL "" FORCE)
+set(WITH_MOD_FLUID OFF CACHE BOOL "" FORCE)
+set(WITH_MOD_REMESH OFF CACHE BOOL "" FORCE)
+set(WITH_MOD_SMOKE OFF CACHE BOOL "" FORCE)
+set(WITH_MOD_OCEANSIM OFF CACHE BOOL "" FORCE)
+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_OPENMP OFF CACHE BOOL "" FORCE)
+set(WITH_PYTHON_INSTALL OFF CACHE BOOL "" FORCE)
+set(WITH_RAYOPTIMIZATION OFF CACHE BOOL "" FORCE)
+set(WITH_SDL OFF CACHE BOOL "" FORCE)
+set(WITH_X11_XINPUT OFF CACHE BOOL "" FORCE)
+set(WITH_X11_XF86VMODE OFF CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/config/bpy_module.cmake b/build_files/cmake/config/bpy_module.cmake
index 6279f06214f..b5b13b40987 100644
--- a/build_files/cmake/config/bpy_module.cmake
+++ b/build_files/cmake/config/bpy_module.cmake
@@ -4,30 +4,30 @@
# cmake -C../blender/build_files/cmake/config/bpy_module.cmake ../blender
#
-set(WITH_PYTHON_MODULE ON CACHE FORCE BOOL)
+set(WITH_PYTHON_MODULE ON CACHE BOOL "" FORCE)
# install into the systems python dir
-set(WITH_INSTALL_PORTABLE OFF CACHE FORCE BOOL)
+set(WITH_INSTALL_PORTABLE OFF CACHE BOOL "" FORCE)
# no point int copying python into python
-set(WITH_PYTHON_INSTALL OFF CACHE FORCE BOOL)
+set(WITH_PYTHON_INSTALL OFF CACHE BOOL "" FORCE)
# dont build the game engine
-set(WITH_GAMEENGINE OFF CACHE FORCE BOOL)
+set(WITH_GAMEENGINE OFF CACHE BOOL "" FORCE)
# disable audio, its possible some devs may want this but for now disable
# so the python module doesnt hold the audio device and loads quickly.
-set(WITH_AUDASPACE OFF CACHE FORCE BOOL)
-set(WITH_FFTW3 OFF CACHE FORCE BOOL)
-set(WITH_JACK OFF CACHE FORCE BOOL)
-set(WITH_SDL OFF CACHE FORCE BOOL)
-set(WITH_OPENAL OFF CACHE FORCE BOOL)
-set(WITH_CODEC_FFMPEG OFF CACHE FORCE BOOL)
-set(WITH_CODEC_SNDFILE OFF CACHE FORCE BOOL)
+set(WITH_AUDASPACE OFF CACHE BOOL "" FORCE)
+set(WITH_FFTW3 OFF CACHE BOOL "" FORCE)
+set(WITH_JACK OFF CACHE BOOL "" FORCE)
+set(WITH_SDL OFF CACHE BOOL "" FORCE)
+set(WITH_OPENAL OFF CACHE BOOL "" FORCE)
+set(WITH_CODEC_FFMPEG OFF CACHE BOOL "" FORCE)
+set(WITH_CODEC_SNDFILE OFF CACHE BOOL "" FORCE)
# other features which are not especially useful as a python module
-set(WITH_X11_XINPUT OFF CACHE FORCE BOOL)
-set(WITH_INPUT_NDOF OFF CACHE FORCE BOOL)
-set(WITH_OPENCOLLADA OFF CACHE FORCE BOOL)
-set(WITH_INTERNATIONAL OFF CACHE FORCE BOOL)
-set(WITH_BULLET OFF CACHE FORCE BOOL)
+set(WITH_X11_XINPUT OFF CACHE BOOL "" FORCE)
+set(WITH_INPUT_NDOF OFF CACHE BOOL "" FORCE)
+set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
+set(WITH_INTERNATIONAL OFF CACHE BOOL "" FORCE)
+set(WITH_BULLET OFF CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index efa258aa9dc..9fe76df20b9 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -143,7 +143,9 @@ macro(blender_source_group
foreach(_SRC ${sources})
get_filename_component(_SRC_EXT ${_SRC} EXT)
- if((${_SRC_EXT} MATCHES ".h") OR (${_SRC_EXT} MATCHES ".hpp"))
+ if((${_SRC_EXT} MATCHES ".h") OR
+ (${_SRC_EXT} MATCHES ".hpp") OR
+ (${_SRC_EXT} MATCHES ".hh"))
source_group("Header Files" FILES ${_SRC})
else()
source_group("Source Files" FILES ${_SRC})
@@ -282,7 +284,9 @@ macro(setup_liblinks
if(WITH_SYSTEM_GLEW)
target_link_libraries(${target} ${GLEW_LIBRARY})
endif()
-
+ if(WITH_BULLET AND WITH_SYSTEM_BULLET)
+ target_link_libraries(${target} ${BULLET_LIBRARIES})
+ endif()
if(WITH_OPENAL)
target_link_libraries(${target} ${OPENAL_LIBRARY})
endif()
@@ -441,6 +445,15 @@ macro(TEST_SSE_SUPPORT
unset(CMAKE_REQUIRED_FLAGS)
endmacro()
+macro(TEST_STDBOOL_SUPPORT)
+ # This program will compile correctly if and only if
+ # this C compiler supports C99 stdbool.
+ check_c_source_runs("
+ #include <stdbool.h>
+ int main(void) { return (int)false; }"
+ HAVE_STDBOOL_H)
+endmacro()
+
# when we have warnings as errors applied globally this
# needs to be removed for some external libs which we dont maintain.
@@ -476,8 +489,10 @@ macro(remove_strict_flags)
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("-Wold-style-definition")
remove_cc_flag("-Werror=[^ ]+")
remove_cc_flag("-Werror")
@@ -488,7 +503,11 @@ macro(remove_strict_flags)
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
remove_cc_flag("-Wunused-parameter")
remove_cc_flag("-Wunused-variable")
+ remove_cc_flag("-Werror=[^ ]+")
remove_cc_flag("-Werror")
+
+ # negate flags implied by '-Wall'
+ add_cc_flag("${CC_REMOVE_STRICT_FLAGS}")
endif()
if(MSVC)
diff --git a/build_files/cmake/project_info.py b/build_files/cmake/project_info.py
index 34f378a58dd..73648be3f15 100755
--- a/build_files/cmake/project_info.py
+++ b/build_files/cmake/project_info.py
@@ -97,7 +97,7 @@ def is_cmake(filename):
def is_c_header(filename):
ext = splitext(filename)[1]
- return (ext in (".h", ".hpp", ".hxx"))
+ return (ext in {".h", ".hpp", ".hxx", ".hh"})
def is_py(filename):
@@ -141,7 +141,7 @@ def cmake_advanced_info():
if sys.platform == "win32":
cmd = 'cmake "%s" -G"Eclipse CDT4 - MinGW Makefiles"' % CMAKE_DIR
else:
- if make_exe_basename.startswith("make"):
+ if make_exe_basename.startswith(("make", "gmake")):
cmd = 'cmake "%s" -G"Eclipse CDT4 - Unix Makefiles"' % CMAKE_DIR
elif make_exe_basename.startswith("ninja"):
cmd = 'cmake "%s" -G"Eclipse CDT4 - Ninja"' % CMAKE_DIR
@@ -149,14 +149,19 @@ def cmake_advanced_info():
raise Exception("Unknown make program %r" % make_exe)
os.system(cmd)
+ return join(CMAKE_DIR, ".cproject")
includes = []
defines = []
- create_eclipse_project()
+ project_path = create_eclipse_project()
+
+ if not exists(project_path):
+ print("Generating Eclipse Prokect File Failed: %r not found" % project_path)
+ return None, None
from xml.dom.minidom import parse
- tree = parse(join(CMAKE_DIR, ".cproject"))
+ tree = parse(project_path)
# to check on nicer xml
# f = open(".cproject_pretty", 'w')
diff --git a/build_files/cmake/project_source_info.py b/build_files/cmake/project_source_info.py
index 10bc36ba1a8..90e240c35ef 100644
--- a/build_files/cmake/project_source_info.py
+++ b/build_files/cmake/project_source_info.py
@@ -43,7 +43,7 @@ SOURCE_DIR = abspath(SOURCE_DIR)
def is_c_header(filename):
ext = os.path.splitext(filename)[1]
- return (ext in (".h", ".hpp", ".hxx"))
+ return (ext in {".h", ".hpp", ".hxx", ".hh"})
def is_c(filename):
@@ -86,15 +86,15 @@ def makefile_log():
make_exe = cmake_cache_var("CMAKE_MAKE_PROGRAM")
make_exe_basename = os.path.basename(make_exe)
- if make_exe_basename.startswith("make"):
+ if make_exe_basename.startswith(("make", "gmake")):
print("running 'make' with --dry-run ...")
process = subprocess.Popen([make_exe, "--always-make", "--dry-run", "--keep-going", "VERBOSE=1"],
- stdout=subprocess.PIPE,
+ stdout=subprocess.PIPE,
)
elif make_exe_basename.startswith("ninja"):
print("running 'ninja' with -t commands ...")
process = subprocess.Popen([make_exe, "-t", "commands"],
- stdout=subprocess.PIPE,
+ stdout=subprocess.PIPE,
)
while process.poll():
diff --git a/build_files/package_spec/rpm/blender.spec.in b/build_files/package_spec/rpm/blender.spec.in
index a95fce80103..e75cc8ec7a6 100644
--- a/build_files/package_spec/rpm/blender.spec.in
+++ b/build_files/package_spec/rpm/blender.spec.in
@@ -77,6 +77,7 @@ fi || :
%{_bindir}/%{name}
%{_datadir}/%{name}/%{blender_api}/datafiles/fonts
%{_datadir}/%{name}/%{blender_api}/datafiles/colormanagement
+%{_datadir}/%{name}/%{blender_api}/datafiles/locale/languages
%{_datadir}/%{name}/%{blender_api}/scripts
%{_datadir}/icons/hicolor/*/apps/%{name}.*
%{_datadir}/applications/%{name}.desktop
diff --git a/build_files/scons/config/Modules/FindPython.py b/build_files/scons/config/Modules/FindPython.py
index c93a10351d5..01215753cf7 100644
--- a/build_files/scons/config/Modules/FindPython.py
+++ b/build_files/scons/config/Modules/FindPython.py
@@ -15,6 +15,13 @@ def FindPython():
abi_flags = cur_flags
break
+ # Find config.h. In some distros, such as ubuntu 12.10 they are not in standard include dir.
+ incconf64 = os.path.join(include, "x86_64-linux-gnu", "python" + version + cur_flags, "pyconfig.h")
+ if os.path.exists(incconf64):
+ incconf = os.path.join(include, "x86_64-linux-gnu", "python" + version + cur_flags)
+ else:
+ incconf = ''
+
# Determine whether python is in /usr/lib or /usr/lib64
lib32 = os.path.join(python, "lib", "python" + version, "sysconfig.py")
lib64 = os.path.join(python, "lib64", "python" + version, "sysconfig.py")
@@ -29,4 +36,5 @@ def FindPython():
return {'PYTHON': python,
"VERSION": version,
'LIBPATH': libpath,
- 'ABI_FLAGS': abi_flags}
+ 'ABI_FLAGS': abi_flags,
+ 'CONFIG': incconf}
diff --git a/build_files/scons/config/darwin-config.py b/build_files/scons/config/darwin-config.py
index 252a1b1b37e..0e413711210 100644
--- a/build_files/scons/config/darwin-config.py
+++ b/build_files/scons/config/darwin-config.py
@@ -137,7 +137,7 @@ else:
BF_PYTHON_INC = '${BF_PYTHON}${BF_PYTHON_VERSION}/include/python${BF_PYTHON_VERSION}m'
BF_PYTHON_BINARY = '${BF_PYTHON}${BF_PYTHON_VERSION}/bin/python${BF_PYTHON_VERSION}'
#BF_PYTHON_LIB = ''
- BF_PYTHON_LIBPATH = '${BF_PYTHON}${BF_PYTHON_VERSION}/lib/python${BF_PYTHON_VERSION}/config-3.2m'
+ BF_PYTHON_LIBPATH = '${BF_PYTHON}${BF_PYTHON_VERSION}/lib/python${BF_PYTHON_VERSION}/config-${BF_PYTHON_VERSION}m'
WITH_BF_OPENAL = True
#different lib must be used following version of gcc
@@ -165,7 +165,7 @@ BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a'
WITH_BF_JACK = True
BF_JACK = '/Library/Frameworks/Jackmp.framework'
BF_JACK_INC = '${BF_JACK}/headers'
-BF_JACK_LIB = 'jack'
+#BF_JACK_LIB = 'jack' # not used due framework
BF_JACK_LIBPATH = '${BF_JACK}'
WITH_BF_SNDFILE = True
@@ -315,7 +315,10 @@ 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_13', 'sm_20', 'sm_21']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30']
+
+#Freestyle
+WITH_BF_FREESTYLE = True
#Ray trace optimization
if MACOSX_ARCHITECTURE == 'x86_64' or MACOSX_ARCHITECTURE == 'i386':
diff --git a/build_files/scons/config/freebsd7-config.py b/build_files/scons/config/freebsd7-config.py
index 02c9093567a..6c39039c4fb 100644
--- a/build_files/scons/config/freebsd7-config.py
+++ b/build_files/scons/config/freebsd7-config.py
@@ -162,6 +162,9 @@ WITH_GHOST_XDND = False
WITH_BF_OPENMP = True
+#Freestyle
+WITH_BF_FREESTYLE = True
+
#Ray trace optimization
WITH_BF_RAYOPTIMIZATION = True
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-pthread']
diff --git a/build_files/scons/config/freebsd8-config.py b/build_files/scons/config/freebsd8-config.py
index 5d3308c50d4..3318e21bf1d 100644
--- a/build_files/scons/config/freebsd8-config.py
+++ b/build_files/scons/config/freebsd8-config.py
@@ -162,6 +162,9 @@ WITH_BF_OPENMP = True
WITH_GHOST_XDND = False
+#Freestyle
+WITH_BF_FREESTYLE = True
+
#Ray trace optimization
WITH_BF_RAYOPTIMIZATION = True
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-pthread']
diff --git a/build_files/scons/config/freebsd9-config.py b/build_files/scons/config/freebsd9-config.py
index 98c2c8fa500..b6c5c0d45eb 100644
--- a/build_files/scons/config/freebsd9-config.py
+++ b/build_files/scons/config/freebsd9-config.py
@@ -162,6 +162,9 @@ WITH_BF_OPENMP = True
WITH_GHOST_XDND = False
+#Freestyle
+WITH_BF_FREESTYLE = True
+
#Ray trace optimization
WITH_BF_RAYOPTIMIZATION = True
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-pthread']
diff --git a/build_files/scons/config/linux-config.py b/build_files/scons/config/linux-config.py
index 038a9bc421d..2aec75edb08 100644
--- a/build_files/scons/config/linux-config.py
+++ b/build_files/scons/config/linux-config.py
@@ -1,23 +1,14 @@
-# find library directory
-import platform
-import os
from Modules.FindPython import FindPython
-bitness = platform.architecture()[0]
-if bitness == '64bit':
- LCGDIR = '../lib/linux64'
-else:
- LCGDIR = '../lib/linux'
-LIBDIR = "#${LCGDIR}"
-
py = FindPython()
BF_PYTHON_ABI_FLAGS = py['ABI_FLAGS']
BF_PYTHON = py['PYTHON']
BF_PYTHON_LIBPATH = py['LIBPATH']
+BF_PYTHON_CONFIG = py['CONFIG']
BF_PYTHON_VERSION = py['VERSION']
WITH_BF_STATICPYTHON = False
-BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}${BF_PYTHON_ABI_FLAGS}'
+BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}${BF_PYTHON_ABI_FLAGS} ' + BF_PYTHON_CONFIG
BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}'
BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}${BF_PYTHON_ABI_FLAGS}' # BF_PYTHON+'/lib/python'+BF_PYTHON_VERSION+'/config/libpython'+BF_PYTHON_VERSION+'.a'
BF_PYTHON_LINKFLAGS = ['-Xlinker', '-export-dynamic']
@@ -113,7 +104,7 @@ BF_QUICKTIME = '/usr/local'
BF_QUICKTIME_INC = '${BF_QUICKTIME}/include'
WITH_BF_ICONV = False
-BF_ICONV = LIBDIR + "/iconv"
+BF_ICONV = "/usr"
BF_ICONV_INC = '${BF_ICONV}/include'
BF_ICONV_LIB = 'iconv'
BF_ICONV_LIBPATH = '${BF_ICONV}/lib'
@@ -122,18 +113,7 @@ WITH_BF_BINRELOC = True
# enable ffmpeg support
WITH_BF_FFMPEG = True
-BF_FFMPEG = LIBDIR + '/ffmpeg'
-if os.path.exists(LCGDIR + '/ffmpeg'):
- WITH_BF_STATICFFMPEG = True
- BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libswscale.a ' + \
- '${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \
- '${BF_FFMPEG_LIBPATH}/libxvidcore.a ${BF_FFMPEG_LIBPATH}/libx264.a ${BF_FFMPEG_LIBPATH}/libmp3lame.a ' + \
- '${BF_FFMPEG_LIBPATH}/libvpx.a ${BF_FFMPEG_LIBPATH}/libvorbis.a ${BF_FFMPEG_LIBPATH}/libogg.a ' + \
- '${BF_FFMPEG_LIBPATH}/libvorbisenc.a ${BF_FFMPEG_LIBPATH}/libtheora.a ' + \
- '${BF_FFMPEG_LIBPATH}/libschroedinger-1.0.a ${BF_FFMPEG_LIBPATH}/liborc-0.4.a ${BF_FFMPEG_LIBPATH}/libdirac_encoder.a ' + \
- '${BF_FFMPEG_LIBPATH}/libfaad.a'
-else:
- BF_FFMPEG = '/usr'
+BF_FFMPEG = '/usr'
BF_FFMPEG_LIB = 'avformat avcodec swscale avutil avdevice'
BF_FFMPEG_INC = '${BF_FFMPEG}/include'
BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib'
@@ -198,34 +178,30 @@ BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib'
BF_JEMALLOC_LIB = 'jemalloc'
BF_JEMALLOC_LIB_STATIC = '${BF_JEMALLOC_LIBPATH}/libjemalloc.a'
-WITH_BF_OIIO = True
+WITH_BF_OIIO = False
WITH_BF_STATICOIIO = False
-BF_OIIO = LIBDIR + '/oiio'
-if not os.path.exists(LCGDIR + '/oiio'):
- WITH_BF_OIIO = False
- BF_OIIO = '/usr'
+BF_OIIO = '/usr'
BF_OIIO_INC = '${BF_OIIO}/include'
BF_OIIO_LIB = 'OpenImageIO'
+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'
-WITH_BF_OCIO = True
+WITH_BF_OCIO = False
WITH_BF_STATICOCIO = False
-BF_OCIO = LIBDIR + '/ocio'
-if not os.path.exists(LCGDIR + '/ocio'):
- WITH_BF_OCIO = False
- BF_OCIO = '/usr'
+BF_OCIO = '/usr'
BF_OCIO_INC = '${BF_OCIO}/include'
BF_OCIO_LIB = 'OpenColorIO yaml-cpp tinyxml'
+BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a'
BF_OCIO_LIBPATH = '${BF_OCIO}/lib'
WITH_BF_BOOST = True
WITH_BF_STATICBOOST = False
-BF_BOOST = LIBDIR + '/boost'
-if not os.path.exists(LCGDIR + '/boost'):
- WITH_BF_BOOST = False
- BF_BOOST = '/usr'
+BF_BOOST = '/usr'
BF_BOOST_INC = '${BF_BOOST}/include'
-BF_BOOST_LIB = 'boost_date_time boost_filesystem boost_regex boost_system boost_thread'
+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_thread.a'
BF_BOOST_LIB_INTERNATIONAL = 'boost_locale'
BF_BOOST_LIBPATH = '${BF_BOOST}/lib'
@@ -233,7 +209,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_13', 'sm_20', 'sm_21', 'sm_30']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30']
WITH_BF_OPENMP = True
@@ -250,11 +226,12 @@ BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib'
BF_3DMOUSE_LIB = 'spnav'
BF_3DMOUSE_LIB_STATIC = '${BF_3DMOUSE_LIBPATH}/libspnav.a'
+#Freestyle
+WITH_BF_FREESTYLE = True
+
##
CC = 'gcc'
CXX = 'g++'
-##ifeq ($CPU),alpha)
-## CFLAGS += -pipe -fPIC -funsigned-char -fno-strict-aliasing -mieee
CCFLAGS = ['-pipe','-fPIC','-funsigned-char','-fno-strict-aliasing','-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64','-D_LARGEFILE64_SOURCE']
CXXFLAGS = []
@@ -268,22 +245,12 @@ if WITH_BF_FFMPEG:
REL_CFLAGS = []
REL_CXXFLAGS = []
REL_CCFLAGS = ['-DNDEBUG', '-O2']
-##BF_DEPEND = True
-##
-##AR = ar
-##ARFLAGS = ruv
-##ARFLAGSQUIET = ru
-##
+
C_WARN = ['-Wno-char-subscripts', '-Wdeclaration-after-statement', '-Wunused-parameter', '-Wstrict-prototypes', '-Werror=declaration-after-statement', '-Werror=implicit-function-declaration', '-Werror=return-type']
CC_WARN = ['-Wall']
CXX_WARN = ['-Wno-invalid-offsetof', '-Wno-sign-compare']
-
-##FIX_STUBS_WARNINGS = -Wno-unused
-
LLIBS = ['util', 'c', 'm', 'dl', 'pthread', 'stdc++']
-##LOPTS = --dynamic
-##DYNLDFLAGS = -shared $(LDFLAGS)
BF_PROFILE = False
BF_PROFILE_CCFLAGS = ['-pg','-g']
@@ -301,4 +268,3 @@ PLATFORM_LINKFLAGS = ['-pthread']
#Fix for LLVM conflict with Mesa llvmpipe
if WITH_BF_LLVM:
PLATFORM_LINKFLAGS += ['-Wl,--version-script=source/creator/blender.map']
-
diff --git a/build_files/scons/config/linuxcross-config.py b/build_files/scons/config/linuxcross-config.py
index 54faf59b2a4..925ca5bb889 100644
--- a/build_files/scons/config/linuxcross-config.py
+++ b/build_files/scons/config/linuxcross-config.py
@@ -160,6 +160,9 @@ BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include'
BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser UTF MathMLSolver expat pcre buffer ftoa'
BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib ${BF_ICONV_LIBPATH}'
+#Freestyle
+WITH_BF_FREESTYLE = True
+
#Ray trace optimization
WITH_BF_RAYOPTIMIZATION = True
BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse']
diff --git a/build_files/scons/config/win32-mingw-config.py b/build_files/scons/config/win32-mingw-config.py
index 391421609d2..691a4842625 100644
--- a/build_files/scons/config/win32-mingw-config.py
+++ b/build_files/scons/config/win32-mingw-config.py
@@ -174,7 +174,10 @@ BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse']
#CUDA
WITH_BF_CYCLES_CUDA_BINARIES = False
#BF_CYCLES_CUDA_NVCC = "" # Path to the nvidia compiler
-BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30']
+
+#Freestyle
+WITH_BF_FREESTYLE = True
##
CC = 'gcc'
diff --git a/build_files/scons/config/win32-vc-config.py b/build_files/scons/config/win32-vc-config.py
index 21488e75f7e..5aa1e7650cc 100644
--- a/build_files/scons/config/win32-vc-config.py
+++ b/build_files/scons/config/win32-vc-config.py
@@ -182,19 +182,22 @@ WITH_BF_STATICOCIO = True
WITH_BF_BOOST = True
BF_BOOST = '${LIBDIR}/boost'
BF_BOOST_INC = '${BF_BOOST}/include'
-BF_BOOST_LIB = 'libboost_date_time-vc90-mt-s-1_49 libboost_filesystem-vc90-mt-s-1_49 libboost_regex-vc90-mt-s-1_49 libboost_system-vc90-mt-s-1_49 libboost_thread-vc90-mt-s-1_49'
+BF_BOOST_LIB = 'libboost_date_time-vc90-mt-s-1_49 libboost_filesystem-vc90-mt-s-1_49 libboost_regex-vc90-mt-s-1_49 libboost_system-vc90-mt-s-1_49 libboost_thread-vc90-mt-s-1_49 libboost_wave-vc90-mt-s-1_49'
BF_BOOST_LIB_INTERNATIONAL = 'libboost_locale-vc90-mt-s-1_49'
BF_BOOST_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_13', 'sm_20', 'sm_21', 'sm_30']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30']
#Ray trace optimization
WITH_BF_RAYOPTIMIZATION = True
BF_RAYOPTIMIZATION_SSE_FLAGS = ['/arch:SSE']
+#Freestyle
+WITH_BF_FREESTYLE = True
+
WITH_BF_STATICOPENGL = False
BF_OPENGL_INC = '${BF_OPENGL}/include'
BF_OPENGL_LIBINC = '${BF_OPENGL}/lib'
diff --git a/build_files/scons/config/win64-mingw-config.py b/build_files/scons/config/win64-mingw-config.py
index d00e7a3ffa7..203d63bb1a1 100644
--- a/build_files/scons/config/win64-mingw-config.py
+++ b/build_files/scons/config/win64-mingw-config.py
@@ -146,7 +146,7 @@ BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib'
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_13', 'sm_20', 'sm_21', 'sm_30']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30']
WITH_BF_OIIO = True
BF_OIIO = LIBDIR + '/openimageio'
@@ -174,6 +174,9 @@ BF_RAYOPTIMIZATION_SSE_FLAGS = ['-mmmx', '-msse', '-msse2']
#May produce errors with unsupported MinGW-w64 builds
WITH_BF_OPENMP = False
+#Freestyle
+WITH_BF_FREESTYLE = True
+
##
CC = 'gcc'
CXX = 'g++'
diff --git a/build_files/scons/config/win64-vc-config.py b/build_files/scons/config/win64-vc-config.py
index c0ea7972aeb..c2f57dab0a7 100644
--- a/build_files/scons/config/win64-vc-config.py
+++ b/build_files/scons/config/win64-vc-config.py
@@ -178,20 +178,23 @@ WITH_BF_STATICOCIO = True
WITH_BF_BOOST = True
BF_BOOST = '${LIBDIR}/boost'
BF_BOOST_INC = '${BF_BOOST}/include'
-BF_BOOST_LIB = 'libboost_date_time-vc90-mt-s-1_49 libboost_filesystem-vc90-mt-s-1_49 libboost_regex-vc90-mt-s-1_49 libboost_system-vc90-mt-s-1_49 libboost_thread-vc90-mt-s-1_49'
+BF_BOOST_LIB = 'libboost_date_time-vc90-mt-s-1_49 libboost_filesystem-vc90-mt-s-1_49 libboost_regex-vc90-mt-s-1_49 libboost_system-vc90-mt-s-1_49 libboost_thread-vc90-mt-s-1_49 libboost_wave-vc90-mt-s-1_49'
BF_BOOST_LIB_INTERNATIONAL = ' libboost_locale-vc90-mt-s-1_49'
BF_BOOST_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_13', 'sm_20', 'sm_21', 'sm_30']
+BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30']
#Ray trace optimization
WITH_BF_RAYOPTIMIZATION = True
# No need to manually specify SSE/SSE2 on x64 systems.
BF_RAYOPTIMIZATION_SSE_FLAGS = ['']
+#Freestyle
+WITH_BF_FREESTYLE = True
+
WITH_BF_STATICOPENGL = False
BF_OPENGL_INC = '${BF_OPENGL}/include'
BF_OPENGL_LIBINC = '${BF_OPENGL}/lib'
diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py
index 94a9f1d9c24..4572ee7f742 100644
--- a/build_files/scons/tools/Blender.py
+++ b/build_files/scons/tools/Blender.py
@@ -29,6 +29,7 @@ from SCons.Script.SConscript import SConsEnvironment
import SCons.Action
import SCons.Util
import SCons.Builder
+import SCons.Subst
import SCons.Tool
import bcolors
bc = bcolors.bcolors()
@@ -234,10 +235,6 @@ def setup_staticlibs(lenv):
if lenv['WITH_BF_STATICLLVM']:
statlibs += Split(lenv['BF_LLVM_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'):
- libincs.append('/usr/lib')
-
if lenv['WITH_BF_JEMALLOC']:
libincs += Split(lenv['BF_JEMALLOC_LIBPATH'])
if lenv['WITH_BF_STATICJEMALLOC']:
@@ -249,6 +246,12 @@ def setup_staticlibs(lenv):
if lenv['WITH_BF_STATIC3DMOUSE']:
statlibs += Split(lenv['BF_3DMOUSE_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!
+ libincs = [e for e in libincs if SCons.Subst.scons_subst(e, lenv, gvars=lenv.Dictionary()) != "/usr/lib"]
+ libincs.append('/usr/lib')
+
return statlibs, libincs
def setup_syslibs(lenv):
@@ -388,6 +391,10 @@ def creator(env):
if env['BF_DEBUG']:
defs.append('_DEBUG')
+ if env['WITH_BF_FREESTYLE']:
+ incs.append('#/source/blender/freestyle')
+ defs.append('WITH_FREESTYLE')
+
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs.append(env['BF_PTHREADS_INC'])
incs.append('#/intern/utfconv')
@@ -452,22 +459,22 @@ def my_print_cmd_line(self, s, target, source, env):
def my_compile_print(target, source, env):
a = '%s' % (source[0])
d, f = os.path.split(a)
- return bc.OKBLUE+"Compiling"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
+ return bc.OKBLUE + "Compiling" + bc.ENDC + " ==> '" + bc.OKGREEN + ("%s" % f) + bc.ENDC + "'"
def my_moc_print(target, source, env):
a = '%s' % (source[0])
d, f = os.path.split(a)
- return bc.OKBLUE+"Creating MOC"+bc.ENDC+ " ==> '"+bc.OKGREEN+"%s" %(f) + "'"+bc.ENDC
+ return bc.OKBLUE + "Creating MOC" + bc.ENDC + " ==> '" + bc.OKGREEN + ("%s" % f) + bc.ENDC + "'"
def my_linking_print(target, source, env):
t = '%s' % (target[0])
d, f = os.path.split(t)
- return bc.OKBLUE+"Linking library"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
+ return bc.OKBLUE + "Linking library" + bc.ENDC + " ==> '" + bc.OKGREEN + ("%s" % f) + bc.ENDC + "'"
def my_program_print(target, source, env):
t = '%s' % (target[0])
d, f = os.path.split(t)
- return bc.OKBLUE+"Linking program"+bc.ENDC +" ==> '"+bc.OKGREEN+"%s" % (f) + "'"+bc.ENDC
+ return bc.OKBLUE + "Linking program" + bc.ENDC + " ==> '" + bc.OKGREEN + ("%s" % f) + bc.ENDC + "'"
def msvc_hack(env):
static_lib = SCons.Tool.createStaticLibBuilder(env)
diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py
index 19f4ac9a1de..9a31ba650f5 100644
--- a/build_files/scons/tools/btools.py
+++ b/build_files/scons/tools/btools.py
@@ -47,10 +47,10 @@ def get_version():
if (ver_base is not None) and (ver_char is not None) and (ver_cycle is not None):
# eg '2.56a-beta'
- if ver_cycle:
+ if ver_cycle != "release":
ver_display = "%s%s-%s" % (ver_base, ver_char, ver_cycle)
else:
- ver_display = "%s%s" % (ver_base, ver_char) # assume release
+ ver_display = "%s%s" % (ver_base, ver_char)
return ver_base, ver_display, ver_cycle
@@ -108,7 +108,7 @@ def validate_arguments(args, bc):
'WITH_BF_STATICFFMPEG', 'BF_FFMPEG_LIB_STATIC',
'WITH_BF_OGG', 'BF_OGG', 'BF_OGG_LIB',
'WITH_BF_FRAMESERVER',
- 'WITH_BF_COMPOSITOR', 'WITH_BF_COMPOSITOR_LEGACY',
+ 'WITH_BF_COMPOSITOR',
'WITH_BF_JPEG', 'BF_JPEG', 'BF_JPEG_INC', 'BF_JPEG_LIB', 'BF_JPEG_LIBPATH', 'WITH_BF_STATICJPEG', 'BF_JPEG_LIB_STATIC',
'WITH_BF_OPENJPEG', 'BF_OPENJPEG', 'BF_OPENJPEG_INC', 'BF_OPENJPEG_LIB', 'BF_OPENJPEG_LIBPATH',
'WITH_BF_REDCODE', 'BF_REDCODE', 'BF_REDCODE_INC', 'BF_REDCODE_LIB', 'BF_REDCODE_LIBPATH',
@@ -116,6 +116,7 @@ def validate_arguments(args, bc):
'WITH_BF_TIFF', 'BF_TIFF', 'BF_TIFF_INC', 'BF_TIFF_LIB', 'BF_TIFF_LIBPATH', 'WITH_BF_STATICTIFF', 'BF_TIFF_LIB_STATIC',
'WITH_BF_ZLIB', 'BF_ZLIB', 'BF_ZLIB_INC', 'BF_ZLIB_LIB', 'BF_ZLIB_LIBPATH', 'WITH_BF_STATICZLIB', 'BF_ZLIB_LIB_STATIC',
'WITH_BF_INTERNATIONAL',
+ 'WITH_BF_FREESTYLE',
'WITH_BF_ICONV', 'BF_ICONV', 'BF_ICONV_INC', 'BF_ICONV_LIB', 'BF_ICONV_LIBPATH',
'WITH_BF_GAMEENGINE',
'WITH_BF_BULLET', 'BF_BULLET', 'BF_BULLET_INC', 'BF_BULLET_LIB',
@@ -215,7 +216,8 @@ def print_targets(targs, bc):
def validate_targets(targs, bc):
valid_list = ['.', 'blender', 'blenderstatic', 'blenderplayer', 'webplugin',
'blendernogame', 'blenderstaticnogame', 'blenderlite', 'release',
- 'everything', 'clean', 'install-bin', 'install', 'nsis','buildslave']
+ 'everything', 'clean', 'install-bin', 'install', 'nsis','buildslave',
+ 'cudakernels']
oklist = []
for t in targs:
if t in valid_list:
@@ -385,6 +387,8 @@ def read_opts(env, cfg, args):
(BoolVariable('WITH_BF_INTERNATIONAL', 'Use Boost::locale if true', True)),
+ (BoolVariable('WITH_BF_FREESTYLE', 'Build advanced edge renderer', True)),
+
(BoolVariable('WITH_BF_ICONV', 'Use iconv if true', True)),
('BF_ICONV', 'iconv base path', ''),
('BF_ICONV_INC', 'iconv include path', ''),
@@ -598,7 +602,6 @@ def read_opts(env, cfg, args):
('BF_BOOST_LIB_STATIC', 'Boost static library', ''),
(BoolVariable('WITH_GHOST_XDND', 'Build with drag-n-drop support on Linux platforms using XDND protocol', True)),
- (BoolVariable('WITH_BF_COMPOSITOR_LEGACY', 'Enable the legacy compositor', False)),
(BoolVariable('WITH_BF_CYCLES_OSL', 'Build with OSL sypport in Cycles', False)),
(BoolVariable('WITH_BF_STATICOSL', 'Staticly link to OSL', False)),
@@ -826,6 +829,18 @@ def NSIS_Installer(target=None, source=None, env=None):
print data.strip().split("\n")[-1]
return rv
+def cudakernels_print(target, source, env):
+ return "Running cudakernels target"
+
+def cudakernels(target=None, source=None, env=None):
+ """
+ Builder for cuda kernels compilation. Used by release build environment only
+ """
+
+ # Currently nothing to do, everything is handled by a dependency resolver
+
+ pass
+
def check_environ():
problematic_envvars = ""
for i in os.environ:
diff --git a/doc/build_systems/cmake.txt b/doc/build_systems/cmake.txt
index b7a6bd9871e..c46978df2fa 100644
--- a/doc/build_systems/cmake.txt
+++ b/doc/build_systems/cmake.txt
@@ -7,12 +7,9 @@
1. Introduction
2. Obtaining CMake
- 3. Obtaining Dependencies
- 4. Deciding on a Build Environment
- 5. Configuring the build for the first time
- 6. Configuring the build after SVN updates
- 7. Specify alternate Python library versions and locations
-
+ 3. Building Blender
+ 4. Generic Setup
+ 5. Configuring the build after SVN updates
1. Introduction
---------------
@@ -28,36 +25,17 @@
The website also contains some documentation on CMake usage but I found
the man page alone pretty helpful.
- 3. Obtaining Dependencies
- -------------------------
-
- Check from the page
- http://www.blender.org/cms/Getting_Dependencies.135.0.html that you
- have all dependencies needed for building Blender. Note that for
- windows many of these dependencies already come in the lib/windows
- module from SVN.
-
- 4. Deciding on a Build Environment
- ----------------------------------
-
- To build Blender with the CMake scripts you first need to decide which
- build environment you feel comfortable with. This decision will also be
- influenced by the platform you are developing on. The current implementation
- have been successfully used to generate build files for the following
- environments:
+ 3. Building Blender
+ -------------------
- 1. Microsoft Visual Studio 2008. There is a free version available
- at http://http://www.microsoft.com/visualstudio/en-us/products/2008-editions/express
+ 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:
- 2. Xcode on Mac OSX
+ http://wiki.blender.org/index.php/Dev:Doc/Building_Blender
- 3. Unix Makefiles (On Linux and Mac OSX): CMake actually creates make
- files which generates nicely color coded output and a percentage
- progress indicator.
-
-
- 5. Configuring the build for the first time
- -------------------------------------------
+ 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
@@ -113,42 +91,14 @@
It is also possible to use the commandline of 'cmake' to override certain
of these settings.
- 6. Configuring the build after SVN updates
+ 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
- every SVN update it may be a good idea to rerun the generation before building
- Blender again. Just rerun the original 'cmake' run to do this, the settings
- will be remembered. For the example above the following will do after every
- 'svn up':
-
- % cmake -G Xcode $BLENDERSOURCE
-
- 7. Specify alternate Python library versions and locations
- ----------------------------------------------------------
-
- The commandline can be used to override detected/default settings, e.g:
-
- On Unix:
- cmake -D PYTHON_LIBRARY=/usr/local/lib/python3.2/config/libpython3.2.so -D PYTHON_INCLUDE_DIR=/usr/local/include/python3.2 ../blender
- On Macs:
- cmake -D PYTHON_INCLUDE_DIRS=/System/Library/Frameworks/Python.framework/Versions/3.2/include/python3.2 -G Xcode ../blender
-
- Mote that this should only be needed once per build directory generation because it will keep the overrides in CMakeCache.txt for subsequent runs.
-
-
-
- To be continued...
-
- TODO's
- ------
-
- 1. Get CMake to create proper distribution directories for the various platforms
- like scons does.
- 2. Investigate the viability of using CPack to package installs automatically.
- 3. Refine this document and write detailed developer's document.
- 4. Make sure all options (ffmpeg, openexr, quicktime) has proper CMake support
- on the various platforms.
+ 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/license/bf-members.txt b/doc/license/bf-members.txt
index 41aad8b7264..d2f71a56ad5 100644
--- a/doc/license/bf-members.txt
+++ b/doc/license/bf-members.txt
@@ -35,7 +35,7 @@ Eric Van Hensbergen
Christian Reichlin
brian moore
Anthony Walker
-Carsten Hšfer
+Carsten Höfer
Raymond Fordham
David Megginson
Jason Schmidt
@@ -78,7 +78,7 @@ Ken Payne
DEBEUX Sylvain
Douglas Philips
Lai Che Hung
-Johan Bolmsjš
+Johan Bolmsjö
Aaron Mitchell
Teinye Horsfall
Martin Marbach
@@ -98,7 +98,7 @@ lukas schroeder
Dan Lyke
Mark Thorpe
A.D. Arul Nirai Selvan
-Herbert Pštzl
+Herbert Pötzl
Andy Payne
LAFFITTE Benoit (KenjForce)
James Ertle
@@ -148,7 +148,7 @@ Kendall Dugger
Brice Due
Simon Vogl
Bernd Koestler
-clŽment CORDIER
+clément CORDIER
CreationAnimation.com
Pete Carss
HERSEN Antoine
@@ -197,9 +197,9 @@ cadic jean-yves
Ralf Pietersz
KAZY
serge Jadot
-HervŽ LOUINET
+Hervé LOUINET
Tom Houtman
-Magnus Kššhler
+Magnus Kööhler
Martin Sinnaeve
Kevin Yank
Tomoichi Iriyama
@@ -221,12 +221,12 @@ Gianluigi Belli
Naoki Abe
NOTTE Jean-Pierre
Jack Way
-Bjšrn Westlin
+Björn Westlin
Mitch Magee
wizoptic
Jake Edge
David Hoover
-Xabier Go–i
+Xabier Goñi
Daniel Fort
Erik Noteboom
Pavel Vostatek
@@ -234,7 +234,7 @@ Javier Belanche Alonso
Jeffrey Blank
Nathan Ryan
Peter Wrangell
-Josef Sie§
+Josef Sieß
Timm Krumnack
Steve Martin
Shigeru Matsumoto
@@ -261,7 +261,7 @@ Colin Foster
Sascha Adler
Stuart Duncan
Brendon Smith
-SŽbastien COLLETTE
+Sébastien COLLETTE
Clemens Auer
Kay Fricke
Fabian Fagerholm
@@ -282,7 +282,7 @@ STEMax
Jeff Cox
Trevor Ratliff
Matt Henley
-Franois VALETTE
+François VALETTE
Rob Saunders
Mike Luethi
Rami Aubourg-Kaires
@@ -290,9 +290,9 @@ Matthew Thomas
Allan Jacobsen
Adam Lowe
David Hostetler
-Lo•c Vigneras
+Loïc Vigneras
Dan Reiland
-Pedro D’az del Arco
+Pedro Díaz del Arco
Pierre Beyssac
Chris Davey
YOSHIAKI Nishino
@@ -385,7 +385,7 @@ Kiernan Holland
Holger Malessa
Masanori Okuda
Andrea Maracci
-Kai-Peter BŠckman
+Kai-Peter Bäckman
Gregg Patton
Luis M Ibarra
Julian Green
@@ -394,7 +394,7 @@ Mark Winkelman
Ebbe L. Nielsen
Carlos Orozco
magnetHead
-KrŸckel Oliver
+Krückel Oliver
Thomas Ingham
Wes Devauld
Uwe Steinmann
@@ -417,7 +417,7 @@ Steve Mackay
NDNWarrior
Christopher Gray
Darius Clarke (Socinian)
-Jean-SŽbastien SEVESTRE
+Jean-Sébastien SEVESTRE
Douglas Fellows
Craig Symons
Quincin Gonjon
@@ -447,7 +447,7 @@ Markus Q. Roberts
Christoher Bartak
Peter Truog
Eric Dynowski
-Philipp GŸhring
+Philipp Gühring
Pierre-Yves RANNO
Jason Nollan (Cluh)
Launay Jean-Claude
@@ -465,7 +465,7 @@ TROJANI Cedric
David Polston
Patrick Mullen
Tetsuya Okuno
-Bodo JŠger
+Bodo Jäger
Leon Brooks
Cedric Adjih
Michael L. Fisher
@@ -521,7 +521,7 @@ Vincent Stoessel
Adrian Virnig
Chris Dixon
Travis Cole
-MŒrten MŒrtensson
+MÃ¥rten MÃ¥rtensson
Evan Scott
Mark Coletti
Ken Burke
@@ -541,7 +541,7 @@ Iain Russell
Thomas Bleicher
Anthony Zishka
Jefferson Dubrule
-Esa PiirilŠ
+Esa Piirilä
Bill Thiede
William Anderson
Alexander Kittel
@@ -561,7 +561,7 @@ John DiLauro
John Miller
Frederic Crozat
Matt Welland
-Paul CalcŽ
+Paul Calcé
Joe Prochilo
Justin Shafer
Joe Croft
@@ -571,7 +571,7 @@ Alain Gallo
Phuoc Ngo
Krabat
Derek Harmison
-SŽbastien Devine
+Sébastien Devine
Kenneth P. Stox
Wade Felde
Kai Groshert
@@ -603,7 +603,7 @@ Martin Forisch
Guillermina Manon
Randal D. Adams
Kevin Reagh (kevin3D)
-Wolfgang KŸhn
+Wolfgang Kühn
BEAUSOLEIL Arnaud
Stan Jakubek
Klaus Brand
@@ -628,7 +628,7 @@ Samuel Seay
Mike Schaudies
Robert Sherwood
Fernando Villalon Panzano
-Jšrg Roschke
+Jörg Roschke
Carl Symons
Peter Pichler
Alan Heckart
@@ -714,7 +714,7 @@ Rau, Bernhard
Stephen Uithoven
Ken Beyer
Matjaz Jakopec
-Eckhard M. JŠger
+Eckhard M. Jäger
Mike Siebach
John Harger
Justin W. Carper
@@ -747,7 +747,7 @@ Karl Bartel
Ralph Howes
Matthew J. Stott
Omar Priego
-ke Westerstršm
+Åke Westerström
Imago Viva
James E Hill
Rune Myrland
@@ -785,7 +785,7 @@ Claude Bilat
Mario Palomo
Neipi
Grethus Bode
-Jan MŸller
+Jan Müller
Mark Pearson
Stanislav Osicka
DataCare Solutions AG
@@ -804,9 +804,9 @@ Aaron Bredon
Hideki Suzuki
josef radinger
Robert Friemer
-Jšrg Zastrau
+Jörg Zastrau
Burton Bicksler
-Kimmo Mšsš
+Kimmo Mösö
Robert F Johnson
Mark Johnson
Avi Bercovich
@@ -821,21 +821,21 @@ Duffaud
Marco Ardito
Simon Suter
Tobias Huelsdau
-Winfried EnglŠnder
+Winfried Engländer
Stephen Groundwater
Joel Ray Holveck
Mag. Tibor Rudas
Hartmut Wolf
Douglas Jones
brett hartshorn
-Beat MŠgert
+Beat Mägert
Javon Prince
bri
James Klicman
Harvey Fong
jeroen v.d. Meulen
Wim Vandersmissen
-Carlos Moreno Rodr’guez
+Carlos Moreno Rodríguez
Trausti Kristjansson
Larry Snyder
olivier
@@ -887,7 +887,7 @@ Fred Roberts
Njin-Zu Chen
GUILLON Marc
Felix Klock
-Ernesto Salas Rodr’guez
+Ernesto Salas Rodríguez
Pavel Roskin
Jaap
Stefan Maass
@@ -911,7 +911,7 @@ delerue
Dirk Behrens
Doc Holiday
Wouter Kerkhoven
-Andreas BŸttner
+Andreas Büttner
James Black
Nicholas Ward
David Oberbeck
@@ -940,7 +940,7 @@ Ian Whitworth
Ruud H.G. van Tol
Pierre Lo Cicero
Srinivas Digumarty
-digitalvelocity¨
+digitalvelocity®
Alan J Booth
Tony OBrien
Douglas Toltzman
@@ -957,12 +957,12 @@ Craig Spitzer
Jeffrey Van Ness
Lucas Vergnettes
Wolfgang Michaelis
-Luis JimŽnez Linares
+Luis Jiménez Linares
Julian Eden
Ms Lilo von Hanffstengel
Kurt B. Kaiser
Mark Ping
-CombŽe
+Combée
Diego Matho
MELIN Philippe
Damian Sobieralski
@@ -1028,7 +1028,7 @@ evolutie
Stephane Portha
Robert Gentner
David B. Camhy
-RenŽ Foucart
+René Foucart
Coyok Drio
Mark Ng
klein michael
@@ -1094,14 +1094,14 @@ Stuart MacKinnon
Dietrich Dietz - the IMaGiNation project (IMGN)
Tina Hirsch
John R Thorp
-FrŽdŽric Bouvier
+Frédéric Bouvier
LINETTE
Felix Rabe
Chay Adamou
nick harron
stephen john ford
Kino
-Daniel Sjšlie
+Daniel Sjölie
Matthias Derer
Alain VALLETON
Kervin Pierre
@@ -1142,13 +1142,13 @@ Satoshi Yamasaki
Rolf-Dieter Klein
J. Deetman
Helge Walter
-Roland StrŒlberg
+Roland Strålberg
Nicolas Morenas (Caronte)
Simon Clarke
Maigrot Michel
Rod Robinson
Kevin Cozens
-Germ‡n Alonso (taz)
+Germán Alonso (taz)
Martin Stegeman
Henrik Jordfald Olsen
Mitchell Skinner
@@ -1157,7 +1157,7 @@ Spiridon G. Kontarakis
Bas Denissen
Loic Dachary
Michael Rutter
-Thorsten SchlŸter
+Thorsten Schlüter
hijothema
Andreas Hauser
Holger Haase
@@ -1232,9 +1232,9 @@ Starr Kline
John Lullie
Chiffi Cosimo
Morgan McMillian
-Stefan HŸbner
+Stefan Hübner
Loic de MONTAIGNAC
-AndrŽs Castillo
+Andrés Castillo
Francesco Anselmo
Ingo Guenther
James C. Davis, Jr.
@@ -1314,7 +1314,7 @@ Luke Titley
marinus meijers
Henry Kaminski
Alistair Riddoch
-Daniel NŸmm
+Daniel Nümm
Matthew Meadows
Bjoern Paschen
Paul Fredrickson
@@ -1325,7 +1325,7 @@ Thomas Muldowney
Cheyenne Cloud, LLC
Helmut A. Goettl
Martin A. Boegelund
-Beno”t Cousson
+Benoît Cousson
Scott Brooks
Ferlet Patrice
Aaron Porterfield
@@ -1335,13 +1335,13 @@ Rui Paulo Sanguinheira Diogo
Jason Saville
Active-Websight GbR
Bryon Roche
-Gustavo Mu–oz
+Gustavo Muñoz
Christopher Gillanders
Phil Frost Tate
Gilles Gonon
Kay
James C. Franklin
-Luis Enrique Caama–o Navas
+Luis Enrique Caamaño Navas
Alexander "estartu" Felder
Marc Ledermann
vrijschrift.org
@@ -1371,7 +1371,7 @@ Maurizio Sibaud
Ron Bolger
Nathan Parton
Andrew Fry
-VINCENT StŽphane
+VINCENT Stéphane
Yan Yan
Justin L Graham
Wade Beasley
diff --git a/doc/manpage/blender.1 b/doc/manpage/blender.1
index 2addb60c5f7..9cefe7a2b24 100644
--- a/doc/manpage/blender.1
+++ b/doc/manpage/blender.1
@@ -1,4 +1,4 @@
-.TH "BLENDER" "1" "December 04, 2012" "Blender Blender 2\&.65"
+.TH "BLENDER" "1" "February 14, 2013" "Blender Blender 2\&.66"
.SH NAME
blender \- a 3D modelling and rendering package
@@ -15,7 +15,7 @@ Use Blender to create TV commercials, to make technical visualizations, business
http://www.blender.org
.SH OPTIONS
-Blender 2.65
+Blender 2.66
Usage: blender [args ...] [file] [args ...]
.br
.SS "Render Options:"
@@ -218,6 +218,12 @@ Turn debugging on
Enable floating point exceptions
.br
+.TP
+.B \-\-disable\-crash\-handler
+.br
+Disable the crash handler
+.br
+
.IP
.TP
@@ -301,7 +307,13 @@ Disable automatic python script execution (pydrivers & startup scripts)
.TP
.B \-P or \-\-python <filename>
.br
-Run the given Python script (filename or Blender Text)
+Run the given Python script file
+.br
+
+.TP
+.B \-\-python\-text <name>
+.br
+Run the given Python script text block
.br
.TP
@@ -398,6 +410,12 @@ Register .blend extension, then exit (Windows only)
Silently register .blend extension, then exit (Windows only)
.br
+.TP
+.B \-\-no\-native\-pixels
+.br
+Do not use native pixel size, for high resolution displays (MacBook 'Retina')
+.br
+
.SS "Argument Parsing:"
arguments must be separated by white space. eg
diff --git a/doc/python_api/examples/bpy.props.5.py b/doc/python_api/examples/bpy.props.5.py
new file mode 100644
index 00000000000..1f61e33c30f
--- /dev/null
+++ b/doc/python_api/examples/bpy.props.5.py
@@ -0,0 +1,89 @@
+"""
+Get/Set Example
+++++++++++++++
+
+Get/Set functions can be used for boolean, int, float, string and enum properties.
+If these callbacks are defined the property will not be stored in the ID properties
+automatically, instead the get/set functions will be called when the property is
+read or written from the API.
+"""
+
+import bpy
+
+
+# Simple property reading/writing from ID properties.
+# This is what the RNA would do internally.
+def get_float(self):
+ return self["testprop"]
+
+
+def set_float(self, value):
+ self["testprop"] = value
+
+bpy.types.Scene.test_float = bpy.props.FloatProperty(get=get_float, set=set_float)
+
+
+# Read-only string property, returns the current date
+def get_date(self):
+ import datetime
+ return str(datetime.datetime.now())
+
+bpy.types.Scene.test_date = bpy.props.StringProperty(get=get_date)
+
+
+# Boolean array. Set function stores a single boolean value, returned as the second component.
+# Array getters must return a list or tuple
+# Array size must match the property vector size exactly
+def get_array(self):
+ return (True, self["somebool"])
+
+
+def set_array(self, values):
+ self["somebool"] = values[0] and values[1]
+
+bpy.types.Scene.test_array = bpy.props.BoolVectorProperty(size=2, get=get_array, set=set_array)
+
+
+# Enum property.
+# Note: the getter/setter callback must use integer identifiers!
+test_items = [
+ ("RED", "Red", "", 1),
+ ("GREEN", "Red", "", 2),
+ ("BLUE", "Red", "", 3),
+ ("YELLOW", "Red", "", 4),
+ ]
+
+
+def get_enum(self):
+ import random
+ return random.randint(1, 4)
+
+
+def set_enum(self, value):
+ print("setting value", value)
+
+bpy.types.Scene.test_enum = bpy.props.EnumProperty(items=test_items, get=get_enum, set=set_enum)
+
+
+# Testing
+
+scene = bpy.context.scene
+
+scene.test_float = 12.34
+print(scene.test_float)
+
+scene.test_array = (True, False)
+print([x for x in scene.test_array])
+
+#scene.test_date = "blah" # this would fail, property is read-only
+print(scene.test_date)
+
+scene.test_enum = 'BLUE'
+print(scene.test_enum)
+
+
+# >>> 12.34000015258789
+# >>> [True, False]
+# >>> 2013-01-05 16:33:52.135340
+# >>> setting value 3
+# >>> GREEN
diff --git a/doc/python_api/examples/bpy.types.AddonPreferences.1.py b/doc/python_api/examples/bpy.types.AddonPreferences.1.py
new file mode 100644
index 00000000000..73f90acb3fa
--- /dev/null
+++ b/doc/python_api/examples/bpy.types.AddonPreferences.1.py
@@ -0,0 +1,72 @@
+bl_info = {
+ "name": "Example Addon Preferences",
+ "author": "Your Name Here",
+ "version": (1, 0),
+ "blender": (2, 65, 0),
+ "location": "SpaceBar Search -> Addon Preferences Example",
+ "description": "Example Addon",
+ "warning": "",
+ "wiki_url": "",
+ "tracker_url": "",
+ "category": "Object"}
+
+
+import bpy
+from bpy.types import Operator, AddonPreferences
+from bpy.props import StringProperty, IntProperty, BoolProperty
+
+
+class ExampleAddonPreferences(AddonPreferences):
+ # this must match the addon name, use '__package__'
+ # when defining this in a submodule of a python package.
+ bl_idname = __name__
+
+ filepath = StringProperty(
+ name="Example File Path",
+ subtype='FILE_PATH',
+ )
+ number = IntProperty(
+ name="Example Number",
+ default=4,
+ )
+ boolean = BoolProperty(
+ name="Example Boolean",
+ default=False,
+ )
+
+ def draw(self, context):
+ layout = self.layout
+ layout.label(text="This is a preferences view for our addon")
+ layout.prop(self, "filepath")
+ layout.prop(self, "number")
+ layout.prop(self, "boolean")
+
+
+class OBJECT_OT_addon_prefs_example(Operator):
+ """Display example preferences"""
+ bl_idname = "object.addon_prefs_example"
+ bl_label = "Addon Preferences Example"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ def execute(self, context):
+ user_preferences = context.user_preferences
+ addon_prefs = user_preferences.addons[__name__].preferences
+
+ info = ("Path: %s, Number: %d, Boolean %r" %
+ (addon_prefs.filepath, addon_prefs.number, addon_prefs.boolean))
+
+ self.report({'INFO'}, info)
+ print(info)
+
+ return {'FINISHED'}
+
+
+# Registration
+def register():
+ bpy.utils.register_class(OBJECT_OT_addon_prefs_example)
+ bpy.utils.register_class(ExampleAddonPreferences)
+
+
+def unregister():
+ bpy.utils.unregister_class(OBJECT_OT_addon_prefs_example)
+ bpy.utils.unregister_class(ExampleAddonPreferences)
diff --git a/doc/python_api/examples/bpy.types.NodeTree.py b/doc/python_api/examples/bpy.types.NodeTree.py
new file mode 100644
index 00000000000..401b3a01ae0
--- /dev/null
+++ b/doc/python_api/examples/bpy.types.NodeTree.py
@@ -0,0 +1,23 @@
+"""
+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,
+the node tree type will not be selectable in the node editor.
+
+A typical condition for shader nodes would be to check the active render engine
+of the scene and only show nodes of the renderer they are designed for.
+"""
+import bpy
+
+
+class CyclesNodeTree(bpy.types.NodeTree):
+ """ This operator is only visible when Cycles is the selected render engine"""
+ bl_label = "Cycles Node Tree"
+
+ @classmethod
+ def poll(cls, context):
+ return context.scene.render.engine == 'CYCLES'
+
+bpy.utils.register_class(CyclesNodeTree)
diff --git a/doc/python_api/examples/bpy.types.UIList.py b/doc/python_api/examples/bpy.types.UIList.py
new file mode 100644
index 00000000000..0f4ae0703cc
--- /dev/null
+++ b/doc/python_api/examples/bpy.types.UIList.py
@@ -0,0 +1,90 @@
+"""
+Basic UIList Example
++++++++++++++++++++
+This script is the UIList subclass used to show material slots, with a bunch of additional commentaries.
+
+Notice the name of the class, this naming convention is similar as the one for panels or menus.
+
+.. note::
+
+ UIList subclasses must be registered for blender to use them.
+"""
+import bpy
+
+
+class MATERIAL_UL_matslots_example(bpy.types.UIList):
+ # The draw_item function is called for each item of the collection that is visible in the list.
+ # data is the RNA object containing the collection,
+ # item is the current drawn item of the collection,
+ # icon is the "computed" icon for the item (as an integer, because some objects like materials or textures
+ # have custom icons ID, which are not available as enum items).
+ # active_data is the RNA object containing the active property for the collection (i.e. integer pointing to the
+ # active item of the collection).
+ # active_propname is the name of the active property (use 'getattr(active_data, active_propname)').
+ # index is index of the current item in the collection.
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ ob = data
+ slot = item
+ ma = slot.material
+ # draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code.
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ # You should always start your row layout by a label (icon + text), this will also make the row easily
+ # selectable in the list!
+ # We use icon_value of label, as our given icon is an integer value, not an enum ID.
+ # Note "data" names should never be translated!
+ layout.label(text=ma.name if ma else "", translate=False, icon_value=icon)
+ # And now we can add other UI stuff...
+ # Here, we add nodes info if this material uses (old!) shading nodes.
+ if ma and not context.scene.render.use_shading_nodes:
+ manode = ma.active_node_material
+ if manode:
+ # The static method UILayout.icon returns the integer value of the icon ID "computed" for the given
+ # RNA object.
+ layout.label(text="Node %s" % manode.name, translate=False, icon_value=layout.icon(manode))
+ elif ma.use_nodes:
+ layout.label(text="Node <none>", translate=False)
+ else:
+ layout.label(text="")
+ # 'GRID' layout type should be as compact as possible (typically a single icon!).
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
+# And now we can use this list everywhere in Blender. Here is a small example panel.
+class UIListPanelExample(bpy.types.Panel):
+ """Creates a Panel in the Object properties window"""
+ bl_label = "UIList Panel"
+ bl_idname = "OBJECT_PT_ui_list_example"
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "object"
+
+ def draw(self, context):
+ layout = self.layout
+
+ obj = context.object
+
+ # template_list now takes two new args.
+ # The first one is the identifier of the registered UIList to use (if you want only the default list,
+ # with no custom draw code, use "UI_UL_list").
+ layout.template_list("MATERIAL_UL_matslots_example", "", obj, "material_slots", obj, "active_material_index")
+
+ # The second one can usually be left as an empty string. It's an additional ID used to distinguish lists in case you
+ # use the same list several times in a given area.
+ layout.template_list("MATERIAL_UL_matslots_example", "compact", obj, "material_slots",
+ obj, "active_material_index", type='COMPACT')
+
+
+def register():
+ bpy.utils.register_class(MATERIAL_UL_matslots_example)
+ bpy.utils.register_class(UIListPanelExample)
+
+
+def unregister():
+ bpy.utils.unregister_class(MATERIAL_UL_matslots_example)
+ bpy.utils.unregister_class(UIListPanelExample)
+
+
+if __name__ == "__main__":
+ register()
diff --git a/doc/python_api/rst/bge.events.rst b/doc/python_api/rst/bge.events.rst
index 074e928f0d8..2238faea242 100644
--- a/doc/python_api/rst/bge.events.rst
+++ b/doc/python_api/rst/bge.events.rst
@@ -69,7 +69,7 @@ Functions
Return the string name of a key event. Will raise a ValueError error if its invalid.
- :arg event: key event from bge.keys or the keyboard sensor.
+ :arg event: key event constant from :mod:`bge.events` or the keyboard sensor.
:type event: int
:rtype: string
@@ -78,7 +78,7 @@ Functions
Return the string name of a key event. Returns an empty string if the event cant be represented as a character.
:type event: int
- :arg event: key event from :mod:`bge.keys` or the keyboard sensor.
+ :arg event: key event constant from :mod:`bge.events` or the keyboard sensor.
:type shift: bool
:arg shift: set to true if shift is held.
:rtype: string
diff --git a/doc/python_api/rst/bge.logic.rst b/doc/python_api/rst/bge.logic.rst
index 7d20aa31a36..4dd0614700e 100644
--- a/doc/python_api/rst/bge.logic.rst
+++ b/doc/python_api/rst/bge.logic.rst
@@ -125,6 +125,10 @@ Variables
The current mouse wrapped in an :class:`~bge.types.SCA_PythonMouse` object.
+.. data:: joysticks
+
+ A list of attached :class:`~bge.types.SCA_PythonJoystick`s. The list size is the maximum number of supported joysticks. If no joystick is available for a given slot, the slot is set to None.
+
*****************
General functions
*****************
@@ -172,7 +176,7 @@ General functions
Restarts the current game by reloading the .blend file (the last saved version, not what is currently running).
-.. function:: LibLoad(blend, type, data, load_actions=False, verbose=False, load_scripts=True)
+.. function:: LibLoad(blend, type, data, load_actions=False, verbose=False, load_scripts=True, async=False)
Converts the all of the datablocks of the given type from the given blend.
@@ -187,7 +191,13 @@ General functions
:arg verbose: Whether or not to print debugging information (e.g., "SceneName: Scene")
:type verbose: bool
:arg load_scripts: Whether or not to load text datablocks as well (can be disabled for some extra security)
- :type load_scripts: bool
+ :type load_scripts: bool
+ :arg async: Whether or not to do the loading asynchronously (in another thread). Only the "Scene" type is currently supported for this feature.
+ :type async: bool
+
+ :rtype: :class:`bge.types.KX_LibLoadStatus`
+
+ .. note:: Asynchronously loaded libraries will not be available immediately after LibLoad() returns. Use the returned KX_LibLoadStatus to figure out when the libraries are ready.
.. function:: LibNew(name, type, data)
@@ -388,6 +398,10 @@ Utility functions
.. function:: PrintMemInfo()
Prints engine statistics into the console
+
+.. function:: getProfileInfo()
+
+ Returns a Python dictionary that contains the same information as the on screen profiler. The keys are the profiler categories and the values are tuples with the first element being time taken (in ms) and the second element being the percentage of total time.
*********
Constants
diff --git a/doc/python_api/rst/bge.types.rst b/doc/python_api/rst/bge.types.rst
index 8cf9ccb794c..f24cc3f998c 100644
--- a/doc/python_api/rst/bge.types.rst
+++ b/doc/python_api/rst/bge.types.rst
@@ -31,5263 +31,8 @@ a :class:`SCA_PythonController` logic brick.
Types
*****
-.. class:: PyObjectPlus
+.. toctree::
+ :glob:
- PyObjectPlus base class of most other types in the Game Engine.
+ bge.types.*
- .. attribute:: invalid
-
- Test if the object has been freed by the game engine and is no longer valid.
-
- Normally this is not a problem but when storing game engine data in the GameLogic module,
- KX_Scenes or other KX_GameObjects its possible to hold a reference to invalid data.
- Calling an attribute or method on an invalid object will raise a SystemError.
-
- The invalid attribute allows testing for this case without exception handling.
-
- :type: boolean
-
-.. class:: CValue(PyObjectPlus)
-
- This class is a basis for other classes.
-
- .. attribute:: name
-
- The name of this CValue derived object (read-only).
-
- :type: string
-
-.. class:: CPropValue(CValue)
-
- This class has no python functions
-
-.. class:: SCA_ILogicBrick(CValue)
-
- Base class for all logic bricks.
-
- .. attribute:: executePriority
-
- This determines the order controllers are evaluated, and actuators are activated (lower priority is executed first).
-
- :type: executePriority: int
-
- .. attribute:: owner
-
- The game object this logic brick is attached to (read-only).
-
- :type: :class:`KX_GameObject` or None in exceptional cases.
-
- .. attribute:: name
-
- The name of this logic brick (read-only).
-
- :type: string
-
-.. class:: SCA_PythonKeyboard(PyObjectPlus)
-
- The current keyboard.
-
- .. attribute:: events
-
- A dictionary containing the status of each keyboard event or key. (read-only).
-
- :type: dictionary {:ref:`keycode<keyboard-keys>`::ref:`status<input-status>`, ...}
-
- .. attribute:: active_events
-
- A dictionary containing the status of only the active keyboard events or keys. (read-only).
-
- :type: dictionary {:ref:`keycode<keyboard-keys>`::ref:`status<input-status>`, ...}
-
-
- .. function:: getClipboard()
-
- Gets the clipboard text.
-
- :rtype: string
-
- .. function:: setClipboard(text)
-
- Sets the clipboard text.
-
- :arg text: New clipboard text
- :type text: string
-
-.. class:: SCA_PythonMouse(PyObjectPlus)
-
- The current mouse.
-
- .. attribute:: events
-
- a dictionary containing the status of each mouse event. (read-only).
-
- :type: dictionary {:ref:`keycode<mouse-keys>`::ref:`status<input-status>`, ...}
-
- .. attribute:: active_events
-
- a dictionary containing the status of only the active mouse events. (read-only).
-
- :type: dictionary {:ref:`keycode<mouse-keys>`::ref:`status<input-status>`, ...}
-
- .. attribute:: position
-
- The normalized x and y position of the mouse cursor.
-
- :type: list [x, y]
-
- .. attribute:: visible
-
- The visibility of the mouse cursor.
-
- :type: boolean
-
-.. class:: SCA_IObject(CValue)
-
- This class has no python functions
-
-.. class:: SCA_ISensor(SCA_ILogicBrick)
-
- Base class for all sensor logic bricks.
-
- .. attribute:: usePosPulseMode
-
- Flag to turn positive pulse mode on and off.
-
- :type: boolean
-
- .. attribute:: useNegPulseMode
-
- Flag to turn negative pulse mode on and off.
-
- :type: boolean
-
- .. attribute:: frequency
-
- The frequency for pulse mode sensors.
-
- :type: integer
-
- .. attribute:: level
-
- level Option whether to detect level or edge transition when entering a state.
- It makes a difference only in case of logic state transition (state actuator).
- A level detector will immediately generate a pulse, negative or positive
- depending on the sensor condition, as soon as the state is activated.
- A edge detector will wait for a state change before generating a pulse.
- note: mutually exclusive with :data:`tap`, enabling will disable :data:`tap`.
-
- :type: boolean
-
- .. attribute:: tap
-
- When enabled only sensors that are just activated will send a positive event,
- after this they will be detected as negative by the controllers.
- This will make a key thats held act as if its only tapped for an instant.
- note: mutually exclusive with :data:`level`, enabling will disable :data:`level`.
-
- :type: boolean
-
- .. attribute:: invert
-
- Flag to set if this sensor activates on positive or negative events.
-
- :type: boolean
-
- .. attribute:: triggered
-
- True if this sensor brick is in a positive state. (read-only).
-
- :type: boolean
-
- .. attribute:: positive
-
- True if this sensor brick is in a positive state. (read-only).
-
- :type: boolean
-
- .. attribute:: pos_ticks
-
- The number of ticks since the last positive pulse (read-only).
-
- :type: int
-
- .. attribute:: neg_ticks
-
- The number of ticks since the last negative pulse (read-only).
-
- :type: int
-
- .. attribute:: status
-
- The status of the sensor (read-only): can be one of :ref:`these constants<sensor-status>`.
-
- :type: int
-
- .. note::
-
- This convenient attribute combines the values of triggered and positive attributes.
-
- .. method:: reset()
-
- Reset sensor internal state, effect depends on the type of sensor and settings.
-
- The sensor is put in its initial state as if it was just activated.
-
-.. class:: SCA_IController(SCA_ILogicBrick)
-
- Base class for all controller logic bricks.
-
- .. attribute:: state
-
- The controllers state bitmask. This can be used with the GameObject's state to test if the controller is active.
-
- :type: int bitmask
-
- .. attribute:: sensors
-
- A list of sensors linked to this controller.
-
- :type: sequence supporting index/string lookups and iteration.
-
- .. note::
-
- The sensors are not necessarily owned by the same object.
-
- .. note::
-
- When objects are instanced in dupligroups links may be lost from objects outside the dupligroup.
-
- .. attribute:: actuators
-
- A list of actuators linked to this controller.
-
- :type: sequence supporting index/string lookups and iteration.
-
- .. note::
-
- The sensors are not necessarily owned by the same object.
-
- .. note::
-
- When objects are instanced in dupligroups links may be lost from objects outside the dupligroup.
-
- .. attribute:: useHighPriority
-
- When set the controller executes always before all other controllers that dont have this set.
-
- :type: boolen
-
- .. note::
-
- Order of execution between high priority controllers is not guaranteed.
-
-.. class:: SCA_IActuator(SCA_ILogicBrick)
-
- Base class for all actuator logic bricks.
-
-.. class:: BL_ActionActuator(SCA_IActuator)
-
- Action Actuators apply an action to an actor.
-
- .. attribute:: action
-
- The name of the action to set as the current action.
-
- :type: string
-
- .. attribute:: frameStart
-
- Specifies the starting frame of the animation.
-
- :type: float
-
- .. attribute:: frameEnd
-
- Specifies the ending frame of the animation.
-
- :type: float
-
- .. attribute:: blendIn
-
- Specifies the number of frames of animation to generate when making transitions between actions.
-
- :type: float
-
- .. attribute:: priority
-
- Sets the priority of this actuator. Actuators will lower priority numbers will override actuators with higher numbers.
-
- :type: integer
-
- .. attribute:: frame
-
- Sets the current frame for the animation.
-
- :type: float
-
- .. attribute:: propName
-
- Sets the property to be used in FromProp playback mode.
-
- :type: string
-
- .. attribute:: blendTime
-
- Sets the internal frame timer. This property must be in the range from 0.0 to blendIn.
-
- :type: float
-
- .. attribute:: mode
-
- The operation mode of the actuator. Can be one of :ref:`these constants<action-actuator>`.
-
- :type: integer
-
- .. attribute:: useContinue
-
- The actions continue option, True or False. When True, the action will always play from where last left off,
- otherwise negative events to this actuator will reset it to its start frame.
-
- :type: boolean
-
- .. attribute:: framePropName
-
- The name of the property that is set to the current frame number.
-
- :type: string
-
-.. class:: BL_Shader(PyObjectPlus)
-
- BL_Shader GLSL shaders.
-
- TODO - Description
-
- .. method:: setUniformfv(name, fList)
-
- Set a uniform with a list of float values
-
- :arg name: the uniform name
- :type name: string
- :arg fList: a list (2, 3 or 4 elements) of float values
- :type fList: list[float]
-
- .. method:: delSource()
-
- Clear the shader. Use this method before the source is changed with :data:`setSource`.
-
- .. method:: getFragmentProg()
-
- Returns the fragment program.
-
- :return: The fragment program.
- :rtype: string
-
- .. method:: getVertexProg()
-
- Get the vertex program.
-
- :return: The vertex program.
- :rtype: string
-
- .. method:: isValid()
-
- Check if the shader is valid.
-
- :return: True if the shader is valid
- :rtype: boolean
-
- .. method:: setAttrib(enum)
-
- Set attribute location. (The parameter is ignored a.t.m. and the value of "tangent" is always used.)
-
- :arg enum: attribute location value
- :type enum: integer
-
- .. method:: setNumberOfPasses( max_pass )
-
- Set the maximum number of passes. Not used a.t.m.
-
- :arg max_pass: the maximum number of passes
- :type max_pass: integer
-
- .. method:: setSampler(name, index)
-
- Set uniform texture sample index.
-
- :arg name: Uniform name
- :type name: string
- :arg index: Texture sample index.
- :type index: integer
-
- .. method:: setSource(vertexProgram, fragmentProgram)
-
- Set the vertex and fragment programs
-
- :arg vertexProgram: Vertex program
- :type vertexProgram: string
- :arg fragmentProgram: Fragment program
- :type fragmentProgram: string
-
- .. method:: setUniform1f(name, fx)
-
- Set a uniform with 1 float value.
-
- :arg name: the uniform name
- :type name: string
- :arg fx: Uniform value
- :type fx: float
-
- .. method:: setUniform1i(name, ix)
-
- Set a uniform with an integer value.
-
- :arg name: the uniform name
- :type name: string
- :arg ix: the uniform value
- :type ix: integer
-
- .. method:: setUniform2f(name, fx, fy)
-
- Set a uniform with 2 float values
-
- :arg name: the uniform name
- :type name: string
- :arg fx: first float value
- :type fx: float
-
- :arg fy: second float value
- :type fy: float
-
- .. method:: setUniform2i(name, ix, iy)
-
- Set a uniform with 2 integer values
-
- :arg name: the uniform name
- :type name: string
- :arg ix: first integer value
- :type ix: integer
- :arg iy: second integer value
- :type iy: integer
-
- .. method:: setUniform3f(name, fx, fy, fz)
-
- Set a uniform with 3 float values.
-
- :arg name: the uniform name
- :type name: string
- :arg fx: first float value
- :type fx: float
- :arg fy: second float value
- :type fy: float
- :arg fz: third float value
- :type fz: float
-
- .. method:: setUniform3i(name, ix, iy, iz)
-
- Set a uniform with 3 integer values
-
- :arg name: the uniform name
- :type name: string
- :arg ix: first integer value
- :type ix: integer
- :arg iy: second integer value
- :type iy: integer
- :arg iz: third integer value
- :type iz: integer
-
- .. method:: setUniform4f(name, fx, fy, fz, fw)
-
- Set a uniform with 4 float values.
-
- :arg name: the uniform name
- :type name: string
- :arg fx: first float value
- :type fx: float
- :arg fy: second float value
- :type fy: float
- :arg fz: third float value
- :type fz: float
- :arg fw: fourth float value
- :type fw: float
-
- .. method:: setUniform4i(name, ix, iy, iz, iw)
-
- Set a uniform with 4 integer values
-
- :arg name: the uniform name
- :type name: string
- :arg ix: first integer value
- :type ix: integer
- :arg iy: second integer value
- :type iy: integer
- :arg iz: third integer value
- :type iz: integer
- :arg iw: fourth integer value
- :type iw: integer
-
- .. method:: setUniformDef(name, type)
-
- Define a new uniform
-
- :arg name: the uniform name
- :type name: string
- :arg type: uniform type
- :type type: UNI_NONE, UNI_INT, UNI_FLOAT, UNI_INT2, UNI_FLOAT2, UNI_INT3, UNI_FLOAT3, UNI_INT4, UNI_FLOAT4, UNI_MAT3, UNI_MAT4, UNI_MAX
-
- .. method:: setUniformMatrix3(name, mat, transpose)
-
- Set a uniform with a 3x3 matrix value
-
- :arg name: the uniform name
- :type name: string
- :arg mat: A 3x3 matrix [[f, f, f], [f, f, f], [f, f, f]]
- :type mat: 3x3 matrix
- :arg transpose: set to True to transpose the matrix
- :type transpose: boolean
-
- .. method:: setUniformMatrix4(name, mat, transpose)
-
- Set a uniform with a 4x4 matrix value
-
- :arg name: the uniform name
- :type name: string
- :arg mat: A 4x4 matrix [[f, f, f, f], [f, f, f, f], [f, f, f, f], [f, f, f, f]]
- :type mat: 4x4 matrix
- :arg transpose: set to True to transpose the matrix
- :type transpose: boolean
-
- .. method:: setUniformiv(name, iList)
-
- Set a uniform with a list of integer values
-
- :arg name: the uniform name
- :type name: string
- :arg iList: a list (2, 3 or 4 elements) of integer values
- :type iList: list[integer]
-
- .. method:: validate()
-
- Validate the shader object.
-
-.. class:: BL_ShapeActionActuator(SCA_IActuator)
-
- ShapeAction Actuators apply an shape action to an mesh object.
-
- .. attribute:: action
-
- The name of the action to set as the current shape action.
-
- :type: string
-
- .. attribute:: frameStart
-
- Specifies the starting frame of the shape animation.
-
- :type: float
-
- .. attribute:: frameEnd
-
- Specifies the ending frame of the shape animation.
-
- :type: float
-
- .. attribute:: blendIn
-
- Specifies the number of frames of animation to generate when making transitions between actions.
-
- :type: float
-
- .. attribute:: priority
-
- Sets the priority of this actuator. Actuators will lower priority numbers will override actuators with higher numbers.
-
- :type: integer
-
- .. attribute:: frame
-
- Sets the current frame for the animation.
-
- :type: float
-
- .. attribute:: propName
-
- Sets the property to be used in FromProp playback mode.
-
- :type: string
-
- .. attribute:: blendTime
-
- Sets the internal frame timer. This property must be in the range from 0.0 to blendin.
-
- :type: float
-
- .. attribute:: mode
-
- The operation mode of the actuator. Can be one of :ref:`these constants<shape-action-actuator>`.
-
- :type: integer
-
- .. attribute:: framePropName
-
- The name of the property that is set to the current frame number.
-
- :type: string
-
-
-.. class:: KX_SteeringActuator(SCA_IActuator)
-
- Steering Actuator for navigation.
-
- .. attribute:: behavior
-
- The steering behavior to use.
-
- :type: one of :ref:`these constants <logic-steering-actuator>`
-
- .. attribute:: velocity
-
- Velocity magnitude
-
- :type: float
-
- .. attribute:: acceleration
-
- Max acceleration
-
- :type: float
-
- .. attribute:: turnspeed
-
- Max turn speed
-
- :type: float
-
- .. attribute:: distance
-
- Relax distance
-
- :type: float
-
- .. attribute:: target
-
- Target object
-
- :type: :class:`KX_GameObject`
-
- .. attribute:: navmesh
-
- Navigation mesh
-
- :type: :class:`KX_GameObject`
-
- .. attribute:: selfterminated
-
- Terminate when target is reached
-
- :type: boolean
-
- .. attribute:: enableVisualization
-
- Enable debug visualization
-
- :type: boolean
-
- .. attribute:: pathUpdatePeriod
-
- Path update period
-
- :type: int
-
-.. class:: CListValue(CPropValue)
-
- This is a list like object used in the game engine internally that behaves similar to a python list in most ways.
-
- As well as the normal index lookup (``val= clist[i]``), CListValue supports string lookups (``val= scene.objects["Cube"]``)
-
- Other operations such as ``len(clist)``, ``list(clist)``, ``clist[0:10]`` are also supported.
-
- .. method:: append(val)
-
- Add an item to the list (like pythons append)
-
- .. warning::
-
- Appending values to the list can cause crashes when the list is used internally by the game engine.
-
- .. method:: count(val)
-
- Count the number of instances of a value in the list.
-
- :return: number of instances
- :rtype: integer
-
- .. method:: index(val)
-
- Return the index of a value in the list.
-
- :return: The index of the value in the list.
- :rtype: integer
-
- .. method:: reverse()
-
- Reverse the order of the list.
-
- .. method:: get(key, default=None)
-
- Return the value matching key, or the default value if its not found.
-
- :return: The key value or a default.
-
- .. method:: from_id(id)
-
- This is a funtion especially for the game engine to return a value with a spesific id.
-
- Since object names are not always unique, the id of an object can be used to get an object from the CValueList.
-
- Example:
-
- .. code-block:: python
-
- myObID=id(gameObject)
- ob= scene.objects.from_id(myObID)
-
- Where ``myObID`` is an int or long from the id function.
-
- This has the advantage that you can store the id in places you could not store a gameObject.
-
- .. warning::
-
- The id is derived from a memory location and will be different each time the game engine starts.
-
- .. warning::
-
- The id can't be stored as an integer in game object properties, as those only have a limited range that the id may not be contained in. Instead an id can be stored as a string game property and converted back to an integer for use in from_id lookups.
-
-.. class:: KX_BlenderMaterial(PyObjectPlus)
-
- KX_BlenderMaterial
-
- .. attribute:: shader
-
- The materials shader.
-
- :type: :class:`BL_Shader`
-
- .. attribute:: blending
-
- Ints used for pixel blending, (src, dst), matching the setBlending method.
-
- :type: (integer, integer)
-
- .. attribute:: material_index
-
- The material's index.
-
- :type: integer
-
- .. method:: getShader()
-
- Returns the material's shader.
-
- :return: the material's shader
- :rtype: :class:`BL_Shader`
-
- .. 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
-
- .. method:: getMaterialIndex()
-
- Returns the material's index.
-
- :return: the material's index
- :rtype: integer
-
-.. class:: KX_CameraActuator(SCA_IActuator)
-
- Applies changes to a camera.
-
- .. attribute:: damping
-
- strength of of the camera following movement.
-
- :type: float
-
- .. attribute:: axis
-
- The camera axis (0, 1, 2) for positive ``XYZ``, (3, 4, 5) for negative ``XYZ``.
-
- :type: int
-
- .. attribute:: min
-
- minimum distance to the target object maintained by the actuator.
-
- :type: float
-
- .. attribute:: max
-
- maximum distance to stay from the target object.
-
- :type: float
-
- .. attribute:: height
-
- height to stay above the target object.
-
- :type: float
-
- .. attribute:: object
-
- the object this actuator tracks.
-
- :type: :class:`KX_GameObject` or None
-
-.. class:: KX_ConstraintActuator(SCA_IActuator)
-
- A constraint actuator limits the position, rotation, distance or orientation of an object.
-
- .. attribute:: damp
-
- Time constant of the constraint expressed in frame (not use by Force field constraint).
-
- :type: integer
-
- .. attribute:: rotDamp
-
- Time constant for the rotation expressed in frame (only for the distance constraint), 0 = use damp for rotation as well.
-
- :type: integer
-
- .. attribute:: direction
-
- The reference direction in world coordinate for the orientation constraint.
-
- :type: 3-tuple of float: (x, y, z)
-
- .. attribute:: option
-
- Binary combination of :ref:`these constants <constraint-actuator-option>`
-
- :type: integer
-
- .. attribute:: time
-
- activation time of the actuator. The actuator disables itself after this many frame. If set to 0, the actuator is not limited in time.
-
- :type: integer
-
- .. attribute:: propName
-
- the name of the property or material for the ray detection of the distance constraint.
-
- :type: string
-
- .. attribute:: min
-
- The lower bound of the constraint. For the rotation and orientation constraint, it represents radiant.
-
- :type: float
-
- .. attribute:: distance
-
- the target distance of the distance constraint.
-
- :type: float
-
- .. attribute:: max
-
- the upper bound of the constraint. For rotation and orientation constraints, it represents radiant.
-
- :type: float
-
- .. attribute:: rayLength
-
- the length of the ray of the distance constraint.
-
- :type: float
-
- .. attribute:: limit
-
- type of constraint. Use one of the :ref:`these constants <constraint-actuator-limit>`
-
- :type: integer.
-
-
-.. class:: KX_ConstraintWrapper(PyObjectPlus)
-
- KX_ConstraintWrapper
-
- .. method:: getConstraintId(val)
-
- Returns the contraint's ID
-
- :return: the constraint's ID
- :rtype: integer
-
-.. class:: KX_GameActuator(SCA_IActuator)
-
- The game actuator loads a new .blend file, restarts the current .blend file or quits the game.
-
- .. attribute:: fileName
-
- the new .blend file to load.
-
- :type: string
-
- .. attribute:: mode
-
- The mode of this actuator. Can be on of :ref:`these constants <game-actuator>`
-
- :type: Int
-
-.. class:: KX_GameObject(SCA_IObject)
-
- All game objects are derived from this class.
-
- Properties assigned to game objects are accessible as attributes of this class.
-
- .. note::
-
- Calling ANY method or attribute on an object that has been removed from a scene will raise a SystemError,
- if an object may have been removed since last accessing it use the :data:`invalid` attribute to check.
-
- KX_GameObject can be subclassed to extend functionality. For example:
-
- .. code-block:: python
-
- import bge
-
- class CustomGameObject(bge.types.KX_GameObject):
- RATE = 0.05
-
- def __init__(self, old_owner):
- # "old_owner" can just be ignored. At this point, "self" is
- # already the object in the scene, and "old_owner" has been
- # destroyed.
-
- # New attributes can be defined - but we could also use a game
- # property, like "self['rate']".
- self.rate = CustomGameObject.RATE
-
- def update(self):
- self.worldPosition.z += self.rate
-
- # switch direction
- if self.worldPosition.z > 1.0:
- self.rate = -CustomGameObject.RATE
- elif self.worldPosition.z < 0.0:
- self.rate = CustomGameObject.RATE
-
- # Called first
- def mutate(cont):
- old_object = cont.owner
- mutated_object = CustomGameObject(cont.owner)
-
- # After calling the constructor above, references to the old object
- # should not be used.
- assert(old_object is not mutated_object)
- assert(old_object.invalid)
- assert(mutated_object is cont.owner)
-
- # Called later - note we are now working with the mutated object.
- def update(cont):
- cont.owner.update()
-
- When subclassing objects other than empties and meshes, the specific type
- should be used - e.g. inherit from :class:`BL_ArmatureObject` when the object
- to mutate is an armature.
-
- .. attribute:: name
-
- The object's name. (read-only).
-
- :type: string
-
- .. attribute:: mass
-
- The object's mass
-
- :type: float
-
- .. note::
-
- The object must have a physics controller for the mass to be applied, otherwise the mass value will be returned as 0.0.
-
- .. attribute:: linVelocityMin
-
- Enforces the object keeps moving at a minimum velocity.
-
- :type: float
-
- .. note::
-
- Applies to dynamic and rigid body objects only.
-
- .. note::
-
- A value of 0.0 disables this option.
-
- .. note::
-
- While objects are stationary the minimum velocity will not be applied.
-
- .. attribute:: linVelocityMax
-
- Clamp the maximum linear velocity to prevent objects moving beyond a set speed.
-
- :type: float
-
- .. note::
-
- Applies to dynamic and rigid body objects only.
-
- .. note::
-
- A value of 0.0 disables this option (rather then setting it stationary).
-
- .. attribute:: localInertia
-
- the object's inertia vector in local coordinates. Read only.
-
- :type: list [ix, iy, iz]
-
- .. attribute:: parent
-
- The object's parent object. (read-only).
-
- :type: :class:`KX_GameObject` or None
-
- .. attribute:: groupMembers
-
- Returns the list of group members if the object is a group object, 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.
-
- :type: :class:`KX_GameObject` or None
-
- .. attribute:: scene
-
- The object's scene. (read-only).
-
- :type: :class:`KX_Scene` or None
-
- .. attribute:: visible
-
- visibility flag.
-
- :type: boolean
-
- .. note::
-
- Game logic will still run for invisible objects.
-
- .. attribute:: color
-
- The object color of the object. [r, g, b, a]
-
- :type: :class:`mathutils.Vector`
-
- .. attribute:: occlusion
-
- occlusion capability flag.
-
- :type: boolean
-
- .. attribute:: position
-
- The object's position. [x, y, z] On write: local position, on read: world position
-
- .. deprecated:: use :data:`localPosition` and :data:`worldPosition`.
-
- :type: :class:`mathutils.Vector`
-
- .. attribute:: orientation
-
- The object's orientation. 3x3 Matrix. You can also write a Quaternion or Euler vector. On write: local orientation, on read: world orientation
-
- .. deprecated:: use :data:`localOrientation` and :data:`worldOrientation`.
-
- :type: :class:`mathutils.Matrix`
-
- .. attribute:: scaling
-
- The object's scaling factor. [sx, sy, sz] On write: local scaling, on read: world scaling
-
- .. deprecated:: use :data:`localScale` and :data:`worldScale`.
-
- :type: :class:`mathutils.Vector`
-
- .. attribute:: localOrientation
-
- The object's local orientation. 3x3 Matrix. You can also write a Quaternion or Euler vector.
-
- :type: :class:`mathutils.Matrix`
-
- .. attribute:: worldOrientation
-
- The object's world orientation. 3x3 Matrix.
-
- :type: :class:`mathutils.Matrix`
-
- .. attribute:: localScale
-
- The object's local scaling factor. [sx, sy, sz]
-
- :type: :class:`mathutils.Vector`
-
- .. attribute:: worldScale
-
- The object's world scaling factor. [sx, sy, sz]
-
- :type: :class:`mathutils.Vector`
-
- .. attribute:: localPosition
-
- The object's local position. [x, y, z]
-
- :type: :class:`mathutils.Vector`
-
- .. attribute:: worldPosition
-
- The object's world position. [x, y, z]
-
- :type: :class:`mathutils.Vector`
-
- .. attribute:: localTransform
-
- The object's local space transform matrix. 4x4 Matrix.
-
- :type: :class:`mathutils.Matrix`
-
- .. attribute:: worldTransform
-
- The object's world space transform matrix. 4x4 Matrix.
-
- :type: :class:`mathutils.Matrix`
-
- .. attribute:: localLinearVelocity
-
- The object's local linear velocity. [x, y, z]
-
- :type: :class:`mathutils.Vector`
-
- .. attribute:: worldLinearVelocity
-
- The object's world linear velocity. [x, y, z]
-
- :type: :class:`mathutils.Vector`
-
- .. attribute:: localAngularVelocity
-
- The object's local angular velocity. [x, y, z]
-
- :type: :class:`mathutils.Vector`
-
- .. attribute:: worldAngularVelocity
-
- The object's world angular velocity. [x, y, z]
-
- :type: :class:`mathutils.Vector`
-
- .. attribute:: timeOffset
-
- adjust the slowparent delay at runtime.
-
- :type: float
-
- .. attribute:: state
-
- the game object's state bitmask, using the first 30 bits, one bit must always be set.
-
- :type: int
-
- .. attribute:: meshes
-
- a list meshes for this object.
-
- :type: list of :class:`KX_MeshProxy`
-
- .. note::
-
- Most objects use only 1 mesh.
-
- .. note::
-
- Changes to this list will not update the KX_GameObject.
-
- .. attribute:: sensors
-
- a sequence of :class:`SCA_ISensor` objects with string/index lookups and iterator support.
-
- :type: list
-
- .. note::
-
- This attribute is experemental and may be removed (but probably wont be).
-
- .. note::
-
- Changes to this list will not update the KX_GameObject.
-
- .. attribute:: controllers
-
- a sequence of :class:`SCA_IController` objects with string/index lookups and iterator support.
-
- :type: list of :class:`SCA_ISensor`
-
- .. note::
-
- This attribute is experemental and may be removed (but probably wont be).
-
- .. note::
-
- Changes to this list will not update the KX_GameObject.
-
- .. attribute:: actuators
-
- a list of :class:`SCA_IActuator` with string/index lookups and iterator support.
-
- :type: list
-
- .. note::
-
- This attribute is experemental and may be removed (but probably wont be).
-
- .. note::
-
- Changes to this list will not update the KX_GameObject.
-
- .. attribute:: attrDict
-
- get the objects internal python attribute dictionary for direct (faster) access.
-
- :type: dict
-
- .. attribute:: children
-
- direct children of this object, (read-only).
-
- :type: :class:`CListValue` of :class:`KX_GameObject`'s
-
- .. attribute:: childrenRecursive
-
- all children of this object including childrens children, (read-only).
-
- :type: :class:`CListValue` of :class:`KX_GameObject`'s
-
- .. attribute:: life
-
- The number of seconds until the object ends, assumes 50fps.
- (when added with an add object actuator), (read-only).
-
- :type: float
-
- .. method:: endObject()
-
- Delete this object, can be used in place of the EndObject Actuator.
-
- The actual removal of the object from the scene is delayed.
-
- .. method:: replaceMesh(mesh, useDisplayMesh=True, usePhysicsMesh=False)
-
- Replace the mesh of this object with a new mesh. This works the same was as the actuator.
-
- :arg mesh: mesh to replace or the meshes name.
- :type mesh: :class:`MeshProxy` or string
- :arg useDisplayMesh: when enabled the display mesh will be replaced (optional argument).
- :type useDisplayMesh: boolean
- :arg usePhysicsMesh: when enabled the physics mesh will be replaced (optional argument).
- :type usePhysicsMesh: boolean
-
- .. method:: setVisible(visible, recursive)
-
- Sets the game object's visible flag.
-
- :arg visible: the visible state to set.
- :type visible: boolean
- :arg recursive: optional argument to set all childrens visibility flag too.
- :type recursive: boolean
-
- .. method:: setOcclusion(occlusion, recursive)
-
- Sets the game object's occlusion capability.
-
- :arg occlusion: the state to set the occlusion to.
- :type occlusion: boolean
- :arg recursive: optional argument to set all childrens occlusion flag too.
- :type recursive: boolean
-
- .. method:: alignAxisToVect(vect, axis=2, factor=1.0)
-
- Aligns any of the game object's axis along the given vector.
-
-
- :arg vect: a vector to align the axis.
- :type vect: 3D vector
- :arg axis: The axis you want to align
-
- * 0: X axis
- * 1: Y axis
- * 2: Z axis
-
- :type axis: integer
- :arg factor: Only rotate a feaction of the distance to the target vector (0.0 - 1.0)
- :type factor: float
-
- .. method:: getAxisVect(vect)
-
- Returns the axis vector rotates by the objects worldspace orientation.
- This is the equivalent of multiplying the vector by the orientation matrix.
-
- :arg vect: a vector to align the axis.
- :type vect: 3D Vector
- :return: The vector in relation to the objects rotation.
- :rtype: 3d vector.
-
- .. method:: applyMovement(movement, local=False)
-
- Sets the game object's movement.
-
- :arg movement: movement vector.
- :type movement: 3D Vector
- :arg local:
- * False: you get the "global" movement ie: relative to world orientation.
- * True: you get the "local" movement ie: relative to object orientation.
- :arg local: boolean
-
- .. method:: applyRotation(rotation, local=False)
-
- Sets the game object's rotation.
-
- :arg rotation: rotation vector.
- :type rotation: 3D Vector
- :arg local:
- * False: you get the "global" rotation ie: relative to world orientation.
- * True: you get the "local" rotation ie: relative to object orientation.
- :arg local: boolean
-
- .. method:: applyForce(force, local=False)
-
- Sets the game object's force.
-
- This requires a dynamic object.
-
- :arg force: force vector.
- :type force: 3D Vector
- :arg local:
- * False: you get the "global" force ie: relative to world orientation.
- * True: you get the "local" force ie: relative to object orientation.
- :type local: boolean
-
- .. method:: applyTorque(torque, local=False)
-
- Sets the game object's torque.
-
- This requires a dynamic object.
-
- :arg torque: torque vector.
- :type torque: 3D Vector
- :arg local:
- * False: you get the "global" torque ie: relative to world orientation.
- * True: you get the "local" torque ie: relative to object orientation.
- :type local: boolean
-
- .. method:: getLinearVelocity(local=False)
-
- Gets the game object's linear velocity.
-
- This method returns the game object's velocity through it's centre of mass, ie no angular velocity component.
-
- :arg local:
- * False: you get the "global" velocity ie: relative to world orientation.
- * 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]
-
- .. method:: setLinearVelocity(velocity, local=False)
-
- Sets the game object's linear velocity.
-
- This method sets game object's velocity through it's centre of mass,
- ie no angular velocity component.
-
- This requires a dynamic object.
-
- :arg velocity: linear velocity vector.
- :type velocity: 3D Vector
- :arg local:
- * False: you get the "global" velocity ie: relative to world orientation.
- * True: you get the "local" velocity ie: relative to object orientation.
- :type local: boolean
-
- .. method:: getAngularVelocity(local=False)
-
- Gets the game object's angular velocity.
-
- :arg local:
- * False: you get the "global" velocity ie: relative to world orientation.
- * 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]
-
- .. method:: setAngularVelocity(velocity, local=False)
-
- Sets the game object's angular velocity.
-
- This requires a dynamic object.
-
- :arg velocity: angular velocity vector.
- :type velocity: boolean
- :arg local:
- * False: you get the "global" velocity ie: relative to world orientation.
- * True: you get the "local" velocity ie: relative to object orientation.
-
- .. method:: getVelocity(point=(0, 0, 0))
-
- Gets the game object's velocity at the specified point.
-
- Gets the game object's velocity at the specified point, including angular
- components.
-
- :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]
-
- .. method:: getReactionForce()
-
- Gets the game object's reaction force.
-
- The reaction force is the force applied to this object over the last simulation timestep.
- This also includes impulses, eg from collisions.
-
- :return: the reaction force of this object.
- :rtype: list [fx, fy, fz]
-
- .. note::
-
- This is not implimented at the moment.
-
- .. method:: applyImpulse(point, impulse)
-
- Applies an impulse to the game object.
-
- This will apply the specified impulse to the game object at the specified point.
- If point != position, applyImpulse will also change the object's angular momentum.
- Otherwise, only linear momentum will change.
-
- :arg point: the point to apply the impulse to (in world coordinates)
- :type point: the point to apply the impulse to (in world coordinates)
-
- .. method:: suspendDynamics()
-
- Suspends physics for this object.
-
- .. method:: restoreDynamics()
-
- Resumes physics for this object.
-
- .. note::
-
- The objects linear velocity will be applied from when the dynamics were suspended.
-
- .. method:: enableRigidBody()
-
- Enables rigid body physics for this object.
-
- Rigid body physics allows the object to roll on collisions.
-
- .. method:: disableRigidBody()
-
- Disables rigid body physics for this object.
-
- .. method:: setParent(parent, compound=True, ghost=True)
-
- Sets this object's parent.
- Control the shape status with the optional compound and ghost parameters:
-
- In that case you can control if it should be ghost or not:
-
- :arg parent: new parent object.
- :type parent: :class:`KX_GameObject`
- :arg compound: whether the shape should be added to the parent compound shape.
-
- * True: the object shape should be added to the parent compound shape.
- * False: the object should keep its individual shape.
-
- :type compound: boolean
- :arg ghost: whether the object should be ghost while parented.
-
- * True: if the object should be made ghost while parented.
- * False: if the object should be solid while parented.
-
- :type ghost: boolean
-
- .. note::
-
- If the object type is sensor, it stays ghost regardless of ghost parameter
-
- .. method:: removeParent()
-
- Removes this objects parent.
-
- .. method:: getPhysicsId()
-
- Returns the user data object associated with this game object's physics controller.
-
- .. method:: getPropertyNames()
-
- Gets a list of all property names.
-
- :return: All property names for this object.
- :rtype: list
-
- .. method:: getDistanceTo(other)
-
- :arg other: a point or another :class:`KX_GameObject` to measure the distance to.
- :type other: :class:`KX_GameObject` or list [x, y, z]
- :return: distance to another object or point.
- :rtype: float
-
- .. method:: getVectTo(other)
-
- Returns the vector and the distance to another object or point.
- The vector is normalized unless the distance is 0, in which a zero length vector is returned.
-
- :arg other: a point or another :class:`KX_GameObject` to get the vector and distance to.
- :type other: :class:`KX_GameObject` or list [x, y, z]
- :return: (distance, globalVector(3), localVector(3))
- :rtype: 3-tuple (float, 3-tuple (x, y, z), 3-tuple (x, y, z))
-
- .. method:: rayCastTo(other, dist, prop)
-
- Look towards another point/object and find first object hit within dist that matches prop.
-
- The ray is always casted from the center of the object, ignoring the object itself.
- The ray is casted towards the center of another object or an explicit [x, y, z] point.
- Use rayCast() if you need to retrieve the hit point
-
- :arg other: [x, y, z] or object towards which the ray is casted
- :type other: :class:`KX_GameObject` or 3-tuple
- :arg dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to other
- :type dist: float
- :arg prop: property name that object must have; can be omitted => detect any object
- :type prop: string
- :return: the first object hit or None if no object or object does not match prop
- :rtype: :class:`KX_GameObject`
-
- .. method:: rayCast(objto, objfrom, dist, prop, face, xray, poly)
-
- Look from a point/object to another point/object and find first object hit within dist that matches prop.
- if poly is 0, returns a 3-tuple with object reference, hit point and hit normal or (None, None, None) if no hit.
- if poly is 1, returns a 4-tuple with in addition a :class:`KX_PolyProxy` as 4th element.
- if poly is 2, returns a 5-tuple with in addition a 2D vector with the UV mapping of the hit point as 5th element.
-
- .. code-block:: python
-
- # shoot along the axis gun-gunAim (gunAim should be collision-free)
- obj, point, normal = gun.rayCast(gunAim, None, 50)
- if obj:
- # do something
- pass
-
- The face paremeter determines the orientation of the normal.
-
- * 0 => hit normal is always oriented towards the ray origin (as if you casted the ray from outside)
- * 1 => hit normal is the real face normal (only for mesh object, otherwise face has no effect)
-
- The ray has X-Ray capability if xray parameter is 1, otherwise the first object hit (other than self object) stops the ray.
- The prop and xray parameters interact as follow.
-
- * prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray.
- * prop off, xray on : idem.
- * prop on, xray off: return closest hit if it matches prop, no hit otherwise.
- * prop on, xray on : return closest hit matching prop or no hit if there is no object matching prop on the full extend of the ray.
-
- The :class:`KX_PolyProxy` 4th element of the return tuple when poly=1 allows to retrieve information on the polygon hit by the ray.
- If there is no hit or the hit object is not a static mesh, None is returned as 4th element.
-
- The ray ignores collision-free objects and faces that dont have the collision flag enabled, you can however use ghost objects.
-
- :arg objto: [x, y, z] or object to which the ray is casted
- :type objto: :class:`KX_GameObject` or 3-tuple
- :arg objfrom: [x, y, z] or object from which the ray is casted; None or omitted => use self object center
- :type objfrom: :class:`KX_GameObject` or 3-tuple or None
- :arg dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to to
- :type dist: float
- :arg prop: property name that object must have; can be omitted or "" => detect any object
- :type prop: string
- :arg face: normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin
- :type face: integer
- :arg xray: X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object
- :type xray: integer
- :arg poly: polygon option: 0, 1 or 2 to return a 3-, 4- or 5-tuple with information on the face hit.
-
- * 0 or omitted: return value is a 3-tuple (object, hitpoint, hitnormal) or (None, None, None) if no hit
- * 1: return value is a 4-tuple and the 4th element is a :class:`KX_PolyProxy` or None if no hit or the object doesn't use a mesh collision shape.
- * 2: return value is a 5-tuple and the 5th element is a 2-tuple (u, v) with the UV mapping of the hit point or None if no hit, or the object doesn't use a mesh collision shape, or doesn't have a UV mapping.
-
- :type poly: integer
- :return: (object, hitpoint, hitnormal) or (object, hitpoint, hitnormal, polygon) or (object, hitpoint, hitnormal, polygon, hituv).
-
- * object, hitpoint and hitnormal are None if no hit.
- * polygon is valid only if the object is valid and is a static object, a dynamic object using mesh collision shape or a soft body object, otherwise it is None
- * hituv is valid only if polygon is valid and the object has a UV mapping, otherwise it is None
-
- :rtype:
-
- * 3-tuple (:class:`KX_GameObject`, 3-tuple (x, y, z), 3-tuple (nx, ny, nz))
- * or 4-tuple (:class:`KX_GameObject`, 3-tuple (x, y, z), 3-tuple (nx, ny, nz), :class:`PolyProxy`)
- * or 5-tuple (:class:`KX_GameObject`, 3-tuple (x, y, z), 3-tuple (nx, ny, nz), :class:`PolyProxy`, 2-tuple (u, v))
-
- .. note::
-
- The ray ignores the object on which the method is called. It is casted from/to object center or explicit [x, y, z] points.
-
- .. method:: setCollisionMargin(margin)
-
- Set the objects collision margin.
-
- :arg margin: the collision margin distance in blender units.
- :type margin: float
-
- .. note::
-
- If this object has no physics controller (a physics ID of zero), this function will raise RuntimeError.
-
- .. method:: sendMessage(subject, body="", to="")
-
- Sends a message.
-
- :arg subject: The subject of the message
- :type subject: string
- :arg body: The body of the message (optional)
- :type body: string
- :arg to: The name of the object to send the message to (optional)
- :type to: string
-
- .. method:: reinstancePhysicsMesh(gameObject, meshObject)
-
- Updates the physics system with the changed mesh.
-
- If no arguments are given the physics mesh will be re-created from the first mesh assigned to the game object.
-
- :arg gameObject: optional argument, set the physics shape from this gameObjets mesh.
- :type gameObject: string, :class:`KX_GameObject` or None
- :arg meshObject: optional argument, set the physics shape from this mesh.
- :type meshObject: string, :class:`MeshProxy` or None
-
- :return: True if reinstance succeeded, False if it failed.
- :rtype: boolean
-
- .. note::
-
- If this object has instances the other instances will be updated too.
-
- .. note::
-
- The gameObject argument has an advantage that it can convert from a mesh with modifiers applied (such as subsurf).
-
- .. warning::
-
- Only triangle mesh type objects are supported currently (not convex hull)
-
- .. warning::
-
- If the object is a part of a combound object it will fail (parent or child)
-
- .. warning::
-
- Rebuilding the physics mesh can be slow, running many times per second will give a performance hit.
-
- .. method:: get(key, default=None)
-
- Return the value matching key, or the default value if its not found.
- :return: The key value or a default.
-
- .. method:: playAction(name, start_frame, end_frame, layer=0, priority=0, blendin=0, play_mode=ACT_MODE_PLAY, layer_weight=0.0, ipo_flags=0, speed=1.0)
-
- Plays an action.
-
- :arg name: the name of the action
- :type name: string
- :arg start: the start frame of the action
- :type start: float
- :arg end: the end frame of the action
- :type end: float
- :arg layer: the layer the action will play in (actions in different layers are added/blended together)
- :type layer: integer
- :arg priority: only play this action if there isn't an action currently playing in this layer with a higher (lower number) priority
- :type priority: integer
- :arg blendin: the amount of blending between this animation and the previous one on this layer
- :type blendin: float
- :arg play_mode: the play mode
- :type play_mode: one of :ref:`these constants <gameobject-playaction-mode>`
- :arg layer_weight: how much of the previous layer to use for blending (0 = add)
- :type layer_weight: float
- :arg ipo_flags: flags for the old IPO behaviors (force, etc)
- :type ipo_flags: int bitfield
- :arg speed: the playback speed of the action as a factor (1.0 = normal speed, 2.0 = 2x speed, etc)
- :type speed: float
-
- .. method:: stopAction(layer=0)
-
- Stop playing the action on the given layer.
-
- :arg layer: The layer to stop playing.
- :type layer: integer
-
- .. method:: getActionFrame(layer=0)
-
- Gets the current frame of the action playing in the supplied layer.
-
- :arg layer: The layer that you want to get the frame from.
- :type layer: integer
-
- :return: The current frame of the action
- :rtype: float
-
- .. method:: setActionFrame(frame, layer=0)
-
- Set the current frame of the action playing in the supplied layer.
-
- :arg layer: The layer where you want to set the frame
- :type layer: integer
- :arg frame: The frame to set the action to
- :type frame: float
-
- .. method:: isPlayingAction(layer=0)
-
- Checks to see if there is an action playing in the given layer.
-
- :arg layer: The layer to check for a playing action.
- :type layer: integer
-
- :return: Whether or not the action is playing
- :rtype: boolean
-
-.. class:: KX_IpoActuator(SCA_IActuator)
-
- IPO actuator activates an animation.
-
- .. attribute:: frameStart
-
- Start frame.
-
- :type: float
-
- .. attribute:: frameEnd
-
- End frame.
-
- :type: float
-
- .. attribute:: propName
-
- Use this property to define the Ipo position.
-
- :type: string
-
- .. attribute:: framePropName
-
- Assign this property this action current frame number.
-
- :type: string
-
- .. attribute:: mode
-
- Play mode for the ipo. Can be on of :ref:`these constants <ipo-actuator>`
-
- :type: integer
-
- .. attribute:: useIpoAsForce
-
- Apply Ipo as a global or local force depending on the local option (dynamic objects only).
-
- :type: boolean
-
- .. attribute:: useIpoAdd
-
- Ipo is added to the current loc/rot/scale in global or local coordinate according to Local flag.
-
- :type: boolean
-
- .. attribute:: useIpoLocal
-
- Let the ipo acts in local coordinates, used in Force and Add mode.
-
- :type: boolean
-
- .. attribute:: useChildren
-
- Update IPO on all children Objects as well.
-
- :type: boolean
-
-.. class:: KX_LightObject(KX_GameObject)
-
- A Light object.
-
- .. code-block:: python
-
- # Turn on a red alert light.
- import bge
-
- co = bge.logic.getCurrentController()
- light = co.owner
-
- light.energy = 1.0
- light.color = [1.0, 0.0, 0.0]
-
- .. data:: SPOT
-
- A spot light source. See attribute :data:`type`
-
- .. data:: SUN
-
- A point light source with no attenuation. See attribute :data:`type`
-
- .. data:: NORMAL
-
- A point light source. See attribute :data:`type`
-
- .. attribute:: type
-
- The type of light - must be SPOT, SUN or NORMAL
-
- .. attribute:: layer
-
- The layer mask that this light affects object on.
-
- :type: bitfield
-
- .. attribute:: energy
-
- The brightness of this light.
-
- :type: float
-
- .. attribute:: distance
-
- The maximum distance this light can illuminate. (SPOT and NORMAL lights only).
-
- :type: float
-
- .. attribute:: color
-
- The color of this light. Black = [0.0, 0.0, 0.0], White = [1.0, 1.0, 1.0].
-
- :type: list [r, g, b]
-
- .. attribute:: lin_attenuation
-
- The linear component of this light's attenuation. (SPOT and NORMAL lights only).
-
- :type: float
-
- .. attribute:: quad_attenuation
-
- The quadratic component of this light's attenuation (SPOT and NORMAL lights only).
-
- :type: float
-
- .. attribute:: spotsize
-
- The cone angle of the spot light, in degrees (SPOT lights only).
-
- :type: float in [0 - 180].
-
- .. attribute:: spotblend
-
- Specifies the intensity distribution of the spot light (SPOT lights only).
-
- :type: float in [0 - 1]
-
- .. note::
-
- Higher values result in a more focused light source.
-
-.. class:: KX_MeshProxy(SCA_IObject)
-
- A mesh object.
-
- You can only change the vertex properties of a mesh object, not the mesh topology.
-
- To use mesh objects effectively, you should know a bit about how the game engine handles them.
-
- #. Mesh Objects are converted from Blender at scene load.
- #. The Converter groups polygons by Material. This means they can be sent to the renderer efficiently. A material holds:
-
- #. The texture.
- #. The Blender material.
- #. The Tile properties
- #. The face properties - (From the "Texture Face" panel)
- #. Transparency & z sorting
- #. Light layer
- #. Polygon shape (triangle/quad)
- #. Game Object
-
- #. Vertices will be split by face if necessary. Vertices can only be shared between faces if:
-
- #. They are at the same position
- #. UV coordinates are the same
- #. Their normals are the same (both polygons are "Set Smooth")
- #. They are the same color, for example: a cube has 24 vertices: 6 faces with 4 vertices per face.
-
- The correct method of iterating over every :class:`KX_VertexProxy` in a game object
-
- .. code-block:: python
-
- from bge import logic
-
- cont = logic.getCurrentController()
- object = cont.owner
-
- for mesh in object.meshes:
- for m_index in range(len(mesh.materials)):
- for v_index in range(mesh.getVertexArrayLength(m_index)):
- vertex = mesh.getVertex(m_index, v_index)
- # Do something with vertex here...
- # ... eg: color the vertex red.
- vertex.color = [1.0, 0.0, 0.0, 1.0]
-
- .. attribute:: materials
-
- :type: list of :class:`KX_BlenderMaterial` or :class:`KX_PolygonMaterial` types
-
- .. attribute:: numPolygons
-
- :type: integer
-
- .. attribute:: numMaterials
-
- :type: integer
-
- .. method:: getMaterialName(matid)
-
- Gets the name of the specified material.
-
- :arg matid: the specified material.
- :type matid: integer
- :return: the attached material name.
- :rtype: string
-
- .. method:: getTextureName(matid)
-
- Gets the name of the specified material's texture.
-
- :arg matid: the specified material
- :type matid: integer
- :return: the attached material's texture name.
- :rtype: string
-
- .. method:: getVertexArrayLength(matid)
-
- Gets the length of the vertex array associated with the specified material.
-
- There is one vertex array for each material.
-
- :arg matid: the specified material
- :type matid: integer
- :return: the number of verticies in the vertex array.
- :rtype: integer
-
- .. method:: getVertex(matid, index)
-
- Gets the specified vertex from the mesh object.
-
- :arg matid: the specified material
- :type matid: integer
- :arg index: the index into the vertex array.
- :type index: integer
- :return: a vertex object.
- :rtype: :class:`KX_VertexProxy`
-
- .. method:: getPolygon(index)
-
- Gets the specified polygon from the mesh.
-
- :arg index: polygon number
- :type index: integer
- :return: a polygon object.
- :rtype: :class:`PolyProxy`
-
- .. method:: transform(matid, matrix)
-
- Transforms the vertices of a mesh.
-
- :arg matid: material index, -1 transforms all.
- :type matid: integer
- :arg matrix: transformation matrix.
- :type matrix: 4x4 matrix [[float]]
-
- .. method:: transformUV(matid, matrix, uv_index=-1, uv_index_from=-1)
-
- Transforms the vertices UV's of a mesh.
-
- :arg matid: material index, -1 transforms all.
- :type matid: integer
- :arg matrix: transformation matrix.
- :type matrix: 4x4 matrix [[float]]
- :arg uv_index: optional uv index, -1 for all, otherwise 0 or 1.
- :type uv_index: integer
- :arg uv_index_from: optional uv index to copy from, -1 to transform the current uv.
- :type uv_index_from: integer
-
-.. class:: SCA_MouseSensor(SCA_ISensor)
-
- Mouse Sensor logic brick.
-
- .. attribute:: position
-
- current [x, y] coordinates of the mouse, in frame coordinates (pixels).
-
- :type: [integer, interger]
-
- .. attribute:: mode
-
- sensor mode.
-
- :type: integer
-
- * KX_MOUSESENSORMODE_LEFTBUTTON(1)
- * KX_MOUSESENSORMODE_MIDDLEBUTTON(2)
- * KX_MOUSESENSORMODE_RIGHTBUTTON(3)
- * KX_MOUSESENSORMODE_WHEELUP(4)
- * KX_MOUSESENSORMODE_WHEELDOWN(5)
- * KX_MOUSESENSORMODE_MOVEMENT(6)
-
- .. method:: getButtonStatus(button)
-
- Get the mouse button status.
-
- :arg button: The code that represents the key you want to get the state of, use one of :ref:`these constants<mouse-keys>`
- :type button: int
- :return: The state of the given key, can be one of :ref:`these constants<input-status>`
- :rtype: int
-
-.. class:: KX_MouseFocusSensor(SCA_MouseSensor)
-
- The mouse focus sensor detects when the mouse is over the current game object.
-
- The mouse focus sensor works by transforming the mouse coordinates from 2d device
- space to 3d space then raycasting away from the camera.
-
- .. attribute:: raySource
-
- The worldspace source of the ray (the view position).
-
- :type: list (vector of 3 floats)
-
- .. attribute:: rayTarget
-
- The worldspace target of the ray.
-
- :type: list (vector of 3 floats)
-
- .. attribute:: rayDirection
-
- The :data:`rayTarget` - :class:`raySource` normalized.
-
- :type: list (normalized vector of 3 floats)
-
- .. attribute:: hitObject
-
- the last object the mouse was over.
-
- :type: :class:`KX_GameObject` or None
-
- .. attribute:: hitPosition
-
- The worldspace position of the ray intersecton.
-
- :type: list (vector of 3 floats)
-
- .. attribute:: hitNormal
-
- the worldspace normal from the face at point of intersection.
-
- :type: list (normalized vector of 3 floats)
-
- .. attribute:: hitUV
-
- the UV coordinates at the point of intersection.
-
- :type: list (vector of 2 floats)
-
- If the object has no UV mapping, it returns [0, 0].
-
- The UV coordinates are not normalized, they can be < 0 or > 1 depending on the UV mapping.
-
- .. attribute:: usePulseFocus
-
- When enabled, moving the mouse over a different object generates a pulse. (only used when the 'Mouse Over Any' sensor option is set).
-
- :type: boolean
-
-.. class:: KX_TouchSensor(SCA_ISensor)
-
- Touch sensor detects collisions between objects.
-
- .. attribute:: propName
-
- The property or material to collide with.
-
- :type: string
-
- .. attribute:: useMaterial
-
- Determines if the sensor is looking for a property or material. KX_True = Find material; KX_False = Find property.
-
- :type: boolean
-
- .. attribute:: usePulseCollision
-
- When enabled, changes to the set of colliding objects generate a pulse.
-
- :type: boolean
-
- .. attribute:: hitObject
-
- The last collided object. (read-only).
-
- :type: :class:`KX_GameObject` or None
-
- .. attribute:: hitObjectList
-
- A list of colliding objects. (read-only).
-
- :type: :class:`CListValue` of :class:`KX_GameObject`
-
-.. class:: KX_NearSensor(KX_TouchSensor)
-
- A near sensor is a specialised form of touch sensor.
-
- .. attribute:: distance
-
- The near sensor activates when an object is within this distance.
-
- :type: float
-
- .. attribute:: resetDistance
-
- The near sensor deactivates when the object exceeds this distance.
-
- :type: float
-
-.. class:: KX_NetworkMessageActuator(SCA_IActuator)
-
- Message Actuator
-
- .. attribute:: propName
-
- Messages will only be sent to objects with the given property name.
-
- :type: string
-
- .. attribute:: subject
-
- The subject field of the message.
-
- :type: string
-
- .. attribute:: body
-
- The body of the message.
-
- :type: string
-
- .. attribute:: usePropBody
-
- Send a property instead of a regular body message.
-
- :type: boolean
-
-.. class:: KX_NetworkMessageSensor(SCA_ISensor)
-
- The Message Sensor logic brick.
-
- Currently only loopback (local) networks are supported.
-
- .. attribute:: subject
-
- The subject the sensor is looking for.
-
- :type: string
-
- .. attribute:: frameMessageCount
-
- The number of messages received since the last frame. (read-only).
-
- :type: integer
-
- .. attribute:: subjects
-
- The list of message subjects received. (read-only).
-
- :type: list of strings
-
- .. attribute:: bodies
-
- The list of message bodies received. (read-only).
-
- :type: list of strings
-
-
-.. class:: KX_FontObject(KX_GameObject)
-
- TODO.
-
-
-.. class:: KX_NavMeshObject(KX_GameObject)
-
- Python interface for using and controlling navigation meshes.
-
- .. method:: findPath(start, goal)
-
- Finds the path from start to goal points.
-
- :arg start: the start point
- :arg start: 3D Vector
- :arg goal: the goal point
- :arg start: 3D Vector
- :return: a path as a list of points
- :rtype: list of points
-
- .. method:: raycast(start, goal)
-
- Raycast from start to goal points.
-
- :arg start: the start point
- :arg start: 3D Vector
- :arg goal: the goal point
- :arg start: 3D Vector
- :return: the hit factor
- :rtype: float
-
- .. method:: draw(mode)
-
- Draws a debug mesh for the navigation mesh.
-
- :arg mode: the drawing mode (one of :ref:`these constants <navmesh-draw-mode>`)
- :arg mode: integer
- :return: None
-
- .. method:: rebuild()
-
- Rebuild the navigation mesh.
-
- :return: None
-
-.. class:: KX_ObjectActuator(SCA_IActuator)
-
- The object actuator ("Motion Actuator") applies force, torque, displacement, angular displacement,
- velocity, or angular velocity to an object.
- Servo control allows to regulate force to achieve a certain speed target.
-
- .. attribute:: force
-
- The force applied by the actuator.
-
- :type: list [x, y, z]
-
- .. attribute:: useLocalForce
-
- A flag specifying if the force is local.
-
- :type: boolean
-
- .. attribute:: torque
-
- The torque applied by the actuator.
-
- :type: list [x, y, z]
-
- .. attribute:: useLocalTorque
-
- A flag specifying if the torque is local.
-
- :type: boolean
-
- .. attribute:: dLoc
-
- The displacement vector applied by the actuator.
-
- :type: list [x, y, z]
-
- .. attribute:: useLocalDLoc
-
- A flag specifying if the dLoc is local.
-
- :type: boolean
-
- .. attribute:: dRot
-
- The angular displacement vector applied by the actuator
-
- :type: list [x, y, z]
-
- .. note::
-
- Since the displacement is applied every frame, you must adjust the displacement based on the frame rate, or you game experience will depend on the player's computer speed.
-
- .. attribute:: useLocalDRot
-
- A flag specifying if the dRot is local.
-
- :type: boolean
-
- .. attribute:: linV
-
- The linear velocity applied by the actuator.
-
- :type: list [x, y, z]
-
- .. attribute:: useLocalLinV
-
- A flag specifying if the linear velocity is local.
-
- :type: boolean
-
- .. note::
-
- This is the target speed for servo controllers.
-
- .. attribute:: angV
-
- The angular velocity applied by the actuator.
-
- :type: list [x, y, z]
-
- .. attribute:: useLocalAngV
-
- A flag specifying if the angular velocity is local.
-
- :type: boolean
-
- .. attribute:: damping
-
- The damping parameter of the servo controller.
-
- :type: short
-
- .. attribute:: forceLimitX
-
- The min/max force limit along the X axis and activates or deactivates the limits in the servo controller.
-
- :type: list [min(float), max(float), bool]
-
- .. attribute:: forceLimitY
-
- The min/max force limit along the Y axis and activates or deactivates the limits in the servo controller.
-
- :type: list [min(float), max(float), bool]
-
- .. attribute:: forceLimitZ
-
- The min/max force limit along the Z axis and activates or deactivates the limits in the servo controller.
-
- :type: list [min(float), max(float), bool]
-
- .. attribute:: pid
-
- The PID coefficients of the servo controller.
-
- :type: list of floats [proportional, integral, derivate]
-
- .. attribute:: reference
-
- The object that is used as reference to compute the velocity for the servo controller.
-
- :type: :class:`KX_GameObject` or None
-
-.. class:: KX_ParentActuator(SCA_IActuator)
-
- The parent actuator can set or remove an objects parent object.
-
- .. attribute:: object
-
- the object this actuator sets the parent too.
-
- :type: :class:`KX_GameObject` or None
-
- .. attribute:: mode
-
- The mode of this actuator.
-
- :type: integer from 0 to 1.
-
- .. attribute:: compound
-
- Whether the object shape should be added to the parent compound shape when parenting.
-
- Effective only if the parent is already a compound shape.
-
- :type: boolean
-
- .. attribute:: ghost
-
- Whether the object should be made ghost when parenting
- Effective only if the shape is not added to the parent compound shape.
-
- :type: boolean
-
-.. class:: KX_PolyProxy(SCA_IObject)
-
- A polygon holds the index of the vertex forming the poylgon.
-
- Note:
- The polygon attributes are read-only, you need to retrieve the vertex proxy if you want
- to change the vertex settings.
-
- .. attribute:: material_name
-
- The name of polygon material, empty if no material.
-
- :type: string
-
- .. attribute:: material
-
- The material of the polygon.
-
- :type: :class:`KX_PolygonMaterial` or :class:`KX_BlenderMaterial`
-
- .. attribute:: texture_name
-
- The texture name of the polygon.
-
- :type: string
-
- .. attribute:: material_id
-
- The material index of the polygon, use this to retrieve vertex proxy from mesh proxy.
-
- :type: integer
-
- .. attribute:: v1
-
- vertex index of the first vertex of the polygon, use this to retrieve vertex proxy from mesh proxy.
-
- :type: integer
-
- .. attribute:: v2
-
- vertex index of the second vertex of the polygon, use this to retrieve vertex proxy from mesh proxy.
-
- :type: integer
-
- .. attribute:: v3
-
- vertex index of the third vertex of the polygon, use this to retrieve vertex proxy from mesh proxy.
-
- :type: integer
-
- .. attribute:: v4
-
- Vertex index of the fourth vertex of the polygon, 0 if polygon has only 3 vertex
- Use this to retrieve vertex proxy from mesh proxy.
-
- :type: integer
-
- .. attribute:: visible
-
- visible state of the polygon: 1=visible, 0=invisible.
-
- :type: integer
-
- .. attribute:: collide
-
- collide state of the polygon: 1=receives collision, 0=collision free.
-
- :type: integer
-
- .. method:: getMaterialName()
-
- Returns the polygon material name with MA prefix
-
- :return: material name
- :rtype: string
-
- .. method:: getMaterial()
-
- :return: The polygon material
- :rtype: :class:`KX_PolygonMaterial` or :class:`KX_BlenderMaterial`
-
- .. method:: getTextureName()
-
- :return: The texture name
- :rtype: string
-
- .. method:: getMaterialIndex()
-
- Returns the material bucket index of the polygon.
- This index and the ones returned by getVertexIndex() are needed to retrieve the vertex proxy from :class:`MeshProxy`.
-
- :return: the material index in the mesh
- :rtype: integer
-
- .. method:: getNumVertex()
-
- Returns the number of vertex of the polygon.
-
- :return: number of vertex, 3 or 4.
- :rtype: integer
-
- .. method:: isVisible()
-
- Returns whether the polygon is visible or not
-
- :return: 0=invisible, 1=visible
- :rtype: boolean
-
- .. method:: isCollider()
-
- Returns whether the polygon is receives collision or not
-
- :return: 0=collision free, 1=receives collision
- :rtype: integer
-
- .. method:: getVertexIndex(vertex)
-
- Returns the mesh vertex index of a polygon vertex
- This index and the one returned by getMaterialIndex() are needed to retrieve the vertex proxy from :class:`MeshProxy`.
-
- :arg vertex: index of the vertex in the polygon: 0->3
- :arg vertex: integer
- :return: mesh vertex index
- :rtype: integer
-
- .. method:: getMesh()
-
- Returns a mesh proxy
-
- :return: mesh proxy
- :rtype: :class:`MeshProxy`
-
-.. 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())
-
-.. class:: KX_RadarSensor(KX_NearSensor)
-
- Radar sensor is a near sensor with a conical sensor object.
-
- .. attribute:: coneOrigin
-
- The origin of the cone with which to test. The origin is in the middle of the cone. (read-only).
-
- :type: list of floats [x, y, z]
-
- .. attribute:: coneTarget
-
- The center of the bottom face of the cone with which to test. (read-only).
-
- :type: list of floats [x, y, z]
-
- .. attribute:: distance
-
- The height of the cone with which to test.
-
- :type: float
-
- .. attribute:: angle
-
- The angle of the cone (in degrees) with which to test.
-
- :type: float
-
- .. attribute:: axis
-
- The axis on which the radar cone is cast.
-
- :type: integer from 0 to 5
-
- KX_RADAR_AXIS_POS_X, KX_RADAR_AXIS_POS_Y, KX_RADAR_AXIS_POS_Z,
- KX_RADAR_AXIS_NEG_X, KX_RADAR_AXIS_NEG_Y, KX_RADAR_AXIS_NEG_Z
-
-.. class:: KX_RaySensor(SCA_ISensor)
-
- A ray sensor detects the first object in a given direction.
-
- .. attribute:: propName
-
- The property the ray is looking for.
-
- :type: string
-
- .. attribute:: range
-
- The distance of the ray.
-
- :type: float
-
- .. attribute:: useMaterial
-
- Whether or not to look for a material (false = property).
-
- :type: boolean
-
- .. attribute:: useXRay
-
- Whether or not to use XRay.
-
- :type: boolean
-
- .. attribute:: hitObject
-
- The game object that was hit by the ray. (read-only).
-
- :type: :class:`KX_GameObject`
-
- .. attribute:: hitPosition
-
- The position (in worldcoordinates) where the object was hit by the ray. (read-only).
-
- :type: list [x, y, z]
-
- .. attribute:: hitNormal
-
- The normal (in worldcoordinates) of the object at the location where the object was hit by the ray. (read-only).
-
- :type: list [x, y, z]
-
- .. attribute:: rayDirection
-
- The direction from the ray (in worldcoordinates). (read-only).
-
- :type: list [x, y, z]
-
- .. attribute:: axis
-
- The axis the ray is pointing on.
-
- :type: integer from 0 to 5
-
- * KX_RAY_AXIS_POS_X
- * KX_RAY_AXIS_POS_Y
- * KX_RAY_AXIS_POS_Z
- * KX_RAY_AXIS_NEG_X
- * KX_RAY_AXIS_NEG_Y
- * KX_RAY_AXIS_NEG_Z
-
-.. class:: KX_SCA_AddObjectActuator(SCA_IActuator)
-
- Edit Object Actuator (in Add Object Mode)
-
- .. warning::
-
- An Add Object actuator will be ignored if at game start, the linked object doesn't exist (or is empty) or the linked object is in an active layer.
-
- .. code-block:: none
-
- Error: GameObject 'Name' has a AddObjectActuator 'ActuatorName' without object (in 'nonactive' layer)
-
- .. attribute:: object
-
- the object this actuator adds.
-
- :type: :class:`KX_GameObject` or None
-
- .. attribute:: objectLastCreated
-
- the last added object from this actuator (read-only).
-
- :type: :class:`KX_GameObject` or None
-
- .. attribute:: time
-
- the lifetime of added objects, in frames. Set to 0 to disable automatic deletion.
-
- :type: integer
-
- .. attribute:: linearVelocity
-
- the initial linear velocity of added objects.
-
- :type: list [vx, vy, vz]
-
- .. attribute:: angularVelocity
-
- the initial angular velocity of added objects.
-
- :type: list [vx, vy, vz]
-
- .. method:: instantAddObject()
-
- adds the object without needing to calling SCA_PythonController.activate()
-
- .. note:: Use objectLastCreated to get the newly created object.
-
-.. class:: KX_SCA_DynamicActuator(SCA_IActuator)
-
- Dynamic Actuator.
-
- .. attribute:: mode
-
- :type: integer
-
- the type of operation of the actuator, 0-4
-
- * KX_DYN_RESTORE_DYNAMICS(0)
- * KX_DYN_DISABLE_DYNAMICS(1)
- * KX_DYN_ENABLE_RIGID_BODY(2)
- * KX_DYN_DISABLE_RIGID_BODY(3)
- * KX_DYN_SET_MASS(4)
-
- .. attribute:: mass
-
- the mass value for the KX_DYN_SET_MASS operation.
-
- :type: float
-
-.. class:: KX_SCA_EndObjectActuator(SCA_IActuator)
-
- Edit Object Actuator (in End Object mode)
-
- This actuator has no python methods.
-
-.. class:: KX_SCA_ReplaceMeshActuator(SCA_IActuator)
-
- Edit Object actuator, in Replace Mesh mode.
-
- .. warning::
-
- Replace mesh actuators will be ignored if at game start, the named mesh doesn't exist.
-
- This will generate a warning in the console
-
- .. code-block:: none
-
- Error: GameObject 'Name' ReplaceMeshActuator 'ActuatorName' without object
-
- .. code-block:: python
-
- # Level-of-detail
- # Switch a game object's mesh based on its depth in the camera view.
- # +----------+ +-----------+ +-------------------------------------+
- # | Always +-----+ Python +-----+ Edit Object (Replace Mesh) LOD.Mesh |
- # +----------+ +-----------+ +-------------------------------------+
- from bge import logic
-
- # List detail meshes here
- # Mesh (name, near, far)
- # Meshes overlap so that they don't 'pop' when on the edge of the distance.
- meshes = ((".Hi", 0.0, -20.0),
- (".Med", -15.0, -50.0),
- (".Lo", -40.0, -100.0)
- )
-
- cont = logic.getCurrentController()
- object = cont.owner
- actuator = cont.actuators["LOD." + obj.name]
- camera = logic.getCurrentScene().active_camera
-
- def Depth(pos, plane):
- return pos[0]*plane[0] + pos[1]*plane[1] + pos[2]*plane[2] + plane[3]
-
- # Depth is negative and decreasing further from the camera
- depth = Depth(object.position, camera.world_to_camera[2])
-
- newmesh = None
- curmesh = None
- # Find the lowest detail mesh for depth
- for mesh in meshes:
- if depth < mesh[1] and depth > mesh[2]:
- newmesh = mesh
- if "ME" + object.name + mesh[0] == actuator.getMesh():
- curmesh = mesh
-
- if newmesh != None and "ME" + object.name + newmesh[0] != actuator.mesh:
- # The mesh is a different mesh - switch it.
- # Check the current mesh is not a better fit.
- if curmesh == None or curmesh[1] < depth or curmesh[2] > depth:
- actuator.mesh = object.name + newmesh[0]
- cont.activate(actuator)
-
- .. attribute:: mesh
-
- :class:`MeshProxy` or the name of the mesh that will replace the current one.
-
- Set to None to disable actuator.
-
- :type: :class:`MeshProxy` or None if no mesh is set
-
- .. attribute:: useDisplayMesh
-
- when true the displayed mesh is replaced.
-
- :type: boolean
-
- .. attribute:: usePhysicsMesh
-
- when true the physics mesh is replaced.
-
- :type: boolean
-
- .. method:: instantReplaceMesh()
-
- Immediately replace mesh without delay.
-
-.. class:: KX_Scene(PyObjectPlus)
-
- An active scene that gives access to objects, cameras, lights and scene attributes.
-
- The activity culling stuff is supposed to disable logic bricks when their owner gets too far
- from the active camera. It was taken from some code lurking at the back of KX_Scene - who knows
- what it does!
-
- .. code-block:: python
-
- from bge import logic
-
- # get the scene
- scene = logic.getCurrentScene()
-
- # print all the objects in the scene
- for object in scene.objects:
- print(object.name)
-
- # get an object named 'Cube'
- object = scene.objects["Cube"]
-
- # get the first object in the scene.
- object = scene.objects[0]
-
- .. code-block:: python
-
- # Get the depth of an object in the camera view.
- from bge import logic
-
- object = logic.getCurrentController().owner
- cam = logic.getCurrentScene().active_camera
-
- # Depth is negative and decreasing further from the camera
- depth = object.position[0]*cam.world_to_camera[2][0] + object.position[1]*cam.world_to_camera[2][1] + object.position[2]*cam.world_to_camera[2][2] + cam.world_to_camera[2][3]
-
- @bug: All attributes are read only at the moment.
-
- .. attribute:: name
-
- The scene's name, (read-only).
-
- :type: string
-
- .. attribute:: objects
-
- A list of objects in the scene, (read-only).
-
- :type: :class:`CListValue` of :class:`KX_GameObject`
-
- .. attribute:: objectsInactive
-
- A list of objects on background layers (used for the addObject actuator), (read-only).
-
- :type: :class:`CListValue` of :class:`KX_GameObject`
-
- .. attribute:: lights
-
- A list of lights in the scene, (read-only).
-
- :type: :class:`CListValue` of :class:`KX_LightObject`
-
- .. attribute:: cameras
-
- A list of cameras in the scene, (read-only).
-
- :type: :class:`CListValue` of :class:`KX_Camera`
-
- .. attribute:: active_camera
-
- The current active camera.
-
- :type: :class:`KX_Camera`
-
- .. note::
-
- This can be set directly from python to avoid using the :class:`KX_SceneActuator`.
-
- .. attribute:: suspended
-
- True if the scene is suspended, (read-only).
-
- :type: boolean
-
- .. attribute:: activity_culling
-
- True if the scene is activity culling.
-
- :type: boolean
-
- .. attribute:: activity_culling_radius
-
- The distance outside which to do activity culling. Measured in manhattan distance.
-
- :type: float
-
- .. attribute:: dbvt_culling
-
- True when Dynamic Bounding box Volume Tree is set (read-only).
-
- :type: boolean
-
- .. attribute:: pre_draw
-
- A list of callables to be run before the render step.
-
- :type: list
-
- .. attribute:: post_draw
-
- A list of callables to be run after the render step.
-
- :type: list
-
- .. attribute:: gravity
-
- The scene gravity using the world x, y and z axis.
-
- :type: list [fx, fy, fz]
-
- .. method:: addObject(object, other, time=0)
-
- Adds an object to the scene like the Add Object Actuator would.
-
- :arg object: 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.
- :type time: integer
- :return: The newly added object.
- :rtype: :class:`KX_GameObject`
-
- .. method:: end()
-
- Removes the scene from the game.
-
- .. method:: restart()
-
- Restarts the scene.
-
- .. method:: replace(scene)
-
- Replaces this scene with another one.
-
- :arg scene: The name of the scene to replace this scene with.
- :type scene: string
-
- .. method:: suspend()
-
- Suspends this scene.
-
- .. method:: resume()
-
- Resume this scene.
-
- .. method:: get(key, default=None)
-
- Return the value matching key, or the default value if its not found.
- :return: The key value or a default.
-
- .. method:: drawObstacleSimulation()
-
- Draw debug visualization of obstacle simulation.
-
-.. class:: KX_SceneActuator(SCA_IActuator)
-
- Scene Actuator logic brick.
-
- .. warning::
-
- Scene actuators that use a scene name will be ignored if at game start, the named scene doesn't exist or is empty
-
- This will generate a warning in the console:
-
- .. code-block:: none
-
- Error: GameObject 'Name' has a SceneActuator 'ActuatorName' (SetScene) without scene
-
- .. attribute:: scene
-
- the name of the scene to change to/overlay/underlay/remove/suspend/resume.
-
- :type: string
-
- .. attribute:: camera
-
- the camera to change to.
-
- :type: :class:`KX_Camera` on read, string or :class:`KX_Camera` on write
-
- .. note::
-
- When setting the attribute, you can use either a :class:`KX_Camera` or the name of the camera.
-
- .. attribute:: useRestart
-
- Set flag to True to restart the sene.
-
- :type: boolean
-
- .. attribute:: mode
-
- The mode of the actuator.
-
- :type: integer from 0 to 5.
-
-.. class:: KX_SoundActuator(SCA_IActuator)
-
- Sound Actuator.
-
- The :data:`startSound`, :data:`pauseSound` and :data:`stopSound` do not require the actuator to be activated - they act instantly provided that the actuator has been activated once at least.
-
- .. attribute:: volume
-
- The volume (gain) of the sound.
-
- :type: float
-
- .. attribute:: time
-
- The current position in the audio stream (in seconds).
-
- :type: float
-
- .. attribute:: pitch
-
- The pitch of the sound.
-
- :type: float
-
- .. attribute:: mode
-
- The operation mode of the actuator. Can be one of :ref:`these constants<logic-sound-actuator>`
-
- :type: integer
-
- .. attribute:: sound
-
- The sound the actuator should play.
-
- :type: Audaspace factory
-
- .. attribute:: is3D
-
- Whether or not the actuator should be using 3D sound. (read-only)
-
- :type: boolean
-
- .. attribute:: volume_maximum
-
- The maximum gain of the sound, no matter how near it is.
-
- :type: float
-
- .. attribute:: volume_minimum
-
- The minimum gain of the sound, no matter how far it is away.
-
- :type: float
-
- .. attribute:: distance_reference
-
- The distance where the sound has a gain of 1.0.
-
- :type: float
-
- .. attribute:: distance_maximum
-
- The maximum distance at which you can hear the sound.
-
- :type: float
-
- .. attribute:: attenuation
-
- The influence factor on volume depending on distance.
-
- :type: float
-
- .. attribute:: cone_angle_inner
-
- The angle of the inner cone.
-
- :type: float
-
- .. attribute:: cone_angle_outer
-
- The angle of the outer cone.
-
- :type: float
-
- .. attribute:: cone_volume_outer
-
- The gain outside the outer cone (the gain in the outer cone will be interpolated between this value and the normal gain in the inner cone).
-
- :type: float
-
- .. method:: startSound()
-
- Starts the sound.
-
- :return: None
-
- .. method:: pauseSound()
-
- Pauses the sound.
-
- :return: None
-
- .. method:: stopSound()
-
- Stops the sound.
-
- :return: None
-
-.. class:: KX_StateActuator(SCA_IActuator)
-
- State actuator changes the state mask of parent object.
-
- .. attribute:: operation
-
- Type of bit operation to be applied on object state mask.
-
- You can use one of :ref:`these constants <state-actuator-operation>`
-
- :type: integer
-
- .. attribute:: mask
-
- Value that defines the bits that will be modified by the operation.
-
- The bits that are 1 in the mask will be updated in the object state.
-
- The bits that are 0 are will be left unmodified expect for the Copy operation which copies the mask to the object state.
-
- :type: integer
-
-.. class:: KX_TrackToActuator(SCA_IActuator)
-
- Edit Object actuator in Track To mode.
-
- .. warning::
-
- Track To Actuators will be ignored if at game start, the object to track to is invalid.
-
- This will generate a warning in the console:
-
- .. code-block:: none
-
- GameObject 'Name' no object in EditObjectActuator 'ActuatorName'
-
- .. attribute:: object
-
- the object this actuator tracks.
-
- :type: :class:`KX_GameObject` or None
-
- .. attribute:: time
-
- the time in frames with which to delay the tracking motion.
-
- :type: integer
-
- .. attribute:: use3D
-
- the tracking motion to use 3D.
-
- :type: boolean
-
-.. class:: KX_VehicleWrapper(PyObjectPlus)
-
- KX_VehicleWrapper
-
- TODO - description
-
- .. method:: addWheel(wheel, attachPos, attachDir, 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 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.
- :type axleDir: vector of 3 floats
- :arg suspensionRestLength: TODO - Description
- :type suspensionRestLength: float
- :arg wheelRadius: The size of the wheel.
- :type wheelRadius: float
-
- .. method:: applyBraking(force, wheelIndex)
-
- Apply a braking force to the specified wheel
-
- :arg force: the brake force
- :type force: float
-
- :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
-
- :arg force: the engine force
- :type force: float
-
- :arg wheelIndex: index of the wheel where the force needs to be applied
- :type wheelIndex: integer
-
- .. method:: getConstraintId()
-
- Get the constraint ID
-
- :return: the constraint id
- :rtype: integer
-
- .. method:: getConstraintType()
-
- Returns the constraint type.
-
- :return: constraint type
- :rtype: integer
-
- .. method:: getNumWheels()
-
- Returns the number of wheels.
-
- :return: the number of wheels for this vehicle
- :rtype: integer
-
- .. method:: getWheelOrientationQuaternion(wheelIndex)
-
- Returns the wheel orientation as a quaternion.
-
- :arg wheelIndex: the wheel index
- :type wheelIndex: integer
-
- :return: TODO Description
- :rtype: TODO - type should be quat as per method name but from the code it looks like a matrix
-
- .. method:: getWheelPosition(wheelIndex)
-
- Returns the position of the specified wheel
-
- :arg wheelIndex: the wheel index
- :type wheelIndex: integer
- :return: position vector
- :rtype: list[x, y, z]
-
- .. method:: getWheelRotation(wheelIndex)
-
- Returns the rotation of the specified wheel
-
- :arg wheelIndex: the wheel index
- :type wheelIndex: integer
-
- :return: the wheel rotation
- :rtype: float
-
- .. method:: setRollInfluence(rollInfluece, wheelIndex)
-
- Set the specified wheel's roll influence.
- The higher the roll influence the more the vehicle will tend to roll over in corners.
-
- :arg rollInfluece: the wheel roll influence
- :type rollInfluece: float
-
- :arg wheelIndex: the wheel index
- :type wheelIndex: integer
-
- .. method:: setSteeringValue(steering, wheelIndex)
-
- Set the specified wheel's steering
-
- :arg steering: the wheel steering
- :type steering: float
-
- :arg wheelIndex: the wheel index
- :type wheelIndex: integer
-
- .. method:: setSuspensionCompression(compression, wheelIndex)
-
- Set the specified wheel's compression
-
- :arg compression: the wheel compression
- :type compression: float
-
- :arg wheelIndex: the wheel index
- :type wheelIndex: integer
-
- .. method:: setSuspensionDamping(damping, wheelIndex)
-
- Set the specified wheel's damping
-
- :arg damping: the wheel damping
- :type damping: float
-
- :arg wheelIndex: the wheel index
- :type wheelIndex: integer
-
- .. method:: setSuspensionStiffness(stiffness, wheelIndex)
-
- Set the specified wheel's stiffness
-
- :arg stiffness: the wheel stiffness
- :type stiffness: float
-
- :arg wheelIndex: the wheel index
- :type wheelIndex: integer
-
- .. method:: setTyreFriction(friction, wheelIndex)
-
- Set the specified wheel's tyre friction
-
- :arg friction: the tyre friction
- :type friction: float
-
- :arg wheelIndex: the wheel index
- :type wheelIndex: integer
-
-.. class:: KX_CharacterWrapper(PyObjectPlus)
-
- A wrapper to expose character physics options.
-
- .. attribute:: onGround
-
- Whether or not the character is on the ground. (read-only)
-
- :type: boolean
-
- .. attribute:: gravity
-
- The gravity value used for the character.
-
- :type: float
-
- .. method:: jump()
-
- The character jumps based on it's jump speed.
-
-.. class:: KX_VertexProxy(SCA_IObject)
-
- A vertex holds position, UV, color and normal information.
-
- Note:
- The physics simulation is NOT currently updated - physics will not respond
- to changes in the vertex position.
-
- .. attribute:: XYZ
-
- The position of the vertex.
-
- :type: list [x, y, z]
-
- .. attribute:: UV
-
- The texture coordinates of the vertex.
-
- :type: list [u, v]
-
- .. attribute:: normal
-
- The normal of the vertex.
-
- :type: list [nx, ny, nz]
-
- .. attribute:: color
-
- The color of the vertex.
-
- :type: list [r, g, b, a]
-
- Black = [0.0, 0.0, 0.0, 1.0], White = [1.0, 1.0, 1.0, 1.0]
-
- .. attribute:: x
-
- The x coordinate of the vertex.
-
- :type: float
-
- .. attribute:: y
-
- The y coordinate of the vertex.
-
- :type: float
-
- .. attribute:: z
-
- The z coordinate of the vertex.
-
- :type: float
-
- .. attribute:: u
-
- The u texture coordinate of the vertex.
-
- :type: float
-
- .. attribute:: v
-
- The v texture coordinate of the vertex.
-
- :type: float
-
- .. attribute:: u2
-
- The second u texture coordinate of the vertex.
-
- :type: float
-
- .. attribute:: v2
-
- The second v texture coordinate of the vertex.
-
- :type: float
-
- .. attribute:: r
-
- The red component of the vertex color. 0.0 <= r <= 1.0.
-
- :type: float
-
- .. attribute:: g
-
- The green component of the vertex color. 0.0 <= g <= 1.0.
-
- :type: float
-
- .. attribute:: b
-
- The blue component of the vertex color. 0.0 <= b <= 1.0.
-
- :type: float
-
- .. attribute:: a
-
- The alpha component of the vertex color. 0.0 <= a <= 1.0.
-
- :type: float
-
- .. method:: getXYZ()
-
- Gets the position of this vertex.
-
- :return: this vertexes position in local coordinates.
- :rtype: list [x, y, z]
-
- .. method:: setXYZ(pos)
-
- Sets the position of this vertex.
-
- :type: list [x, y, z]
-
- :arg pos: the new position for this vertex in local coordinates.
-
- .. method:: getUV()
-
- Gets the UV (texture) coordinates of this vertex.
-
- :return: this vertexes UV (texture) coordinates.
- :rtype: list [u, v]
-
- .. method:: setUV(uv)
-
- Sets the UV (texture) coordinates of this vertex.
-
- :type: list [u, v]
-
- .. method:: getUV2()
-
- Gets the 2nd UV (texture) coordinates of this vertex.
-
- :return: this vertexes UV (texture) coordinates.
- :rtype: list [u, v]
-
- .. method:: setUV2(uv, unit)
-
- Sets the 2nd UV (texture) coordinates of this vertex.
-
- :type: list [u, v]
-
- :arg unit: optional argument, FLAT==1, SECOND_UV==2, defaults to SECOND_UV
- :arg unit: integer
-
- .. method:: getRGBA()
-
- Gets the color of this vertex.
-
- The color is represented as four bytes packed into an integer value. The color is
- packed as RGBA.
-
- Since Python offers no way to get each byte without shifting, you must use the struct module to
- access color in an machine independent way.
-
- Because of this, it is suggested you use the r, g, b and a attributes or the color attribute instead.
-
- .. code-block:: python
-
- import struct;
- col = struct.unpack('4B', struct.pack('I', v.getRGBA()))
- # col = (r, g, b, a)
- # black = ( 0, 0, 0, 255)
- # white = (255, 255, 255, 255)
-
- :return: packed color. 4 byte integer with one byte per color channel in RGBA format.
- :rtype: integer
-
- .. method:: setRGBA(col)
-
- Sets the color of this vertex.
-
- See getRGBA() for the format of col, and its relevant problems. Use the r, g, b and a attributes
- or the color attribute instead.
-
- setRGBA() also accepts a four component list as argument col. The list represents the color as [r, g, b, a]
- with black = [0.0, 0.0, 0.0, 1.0] and white = [1.0, 1.0, 1.0, 1.0]
-
- .. code-block:: python
-
- v.setRGBA(0xff0000ff) # Red
- v.setRGBA(0xff00ff00) # Green on little endian, transparent purple on big endian
- v.setRGBA([1.0, 0.0, 0.0, 1.0]) # Red
- v.setRGBA([0.0, 1.0, 0.0, 1.0]) # Green on all platforms.
-
- :arg col: the new color of this vertex in packed RGBA format.
- :type col: integer or list [r, g, b, a]
-
- .. method:: getNormal()
-
- Gets the normal vector of this vertex.
-
- :return: normalized normal vector.
- :rtype: list [nx, ny, nz]
-
- .. method:: setNormal(normal)
-
- Sets the normal vector of this vertex.
-
- :type: sequence of floats [r, g, b]
-
- :arg normal: the new normal of this vertex.
-
-.. class:: KX_VisibilityActuator(SCA_IActuator)
-
- Visibility Actuator.
-
- .. attribute:: visibility
-
- whether the actuator makes its parent object visible or invisible.
-
- :type: boolean
-
- .. attribute:: useOcclusion
-
- whether the actuator makes its parent object an occluder or not.
-
- :type: boolean
-
- .. attribute:: useRecursion
-
- whether the visibility/occlusion should be propagated to all children of the object.
-
- :type: boolean
-
-.. class:: SCA_2DFilterActuator(SCA_IActuator)
-
- Create, enable and disable 2D filters
-
- The following properties don't have an immediate effect.
- You must active the actuator to get the result.
- The actuator is not persistent: it automatically stops itself after setting up the filter
- but the filter remains active. To stop a filter you must activate the actuator with 'type'
- set to :data:`~bge.logic.RAS_2DFILTER_DISABLED` or :data:`~bge.logic.RAS_2DFILTER_NOFILTER`.
-
- .. attribute:: shaderText
-
- shader source code for custom shader.
-
- :type: string
-
- .. attribute:: disableMotionBlur
-
- action on motion blur: 0=enable, 1=disable.
-
- :type: integer
-
- .. attribute:: mode
-
- Type of 2D filter, use one of :ref:`these constants <Two-D-FilterActuator-mode>`
-
- :type: integer
-
- .. attribute:: passNumber
-
- order number of filter in the stack of 2D filters. Filters are executed in increasing order of passNb.
-
- Only be one filter can be defined per passNb.
-
- :type: integer (0-100)
-
- .. attribute:: value
-
- argument for motion blur filter.
-
- :type: float (0.0-100.0)
-
-.. class:: SCA_ANDController(SCA_IController)
-
- An AND controller activates only when all linked sensors are activated.
-
- There are no special python methods for this controller.
-
-.. class:: SCA_ActuatorSensor(SCA_ISensor)
-
- Actuator sensor detect change in actuator state of the parent object.
- It generates a positive pulse if the corresponding actuator is activated
- and a negative pulse if the actuator is deactivated.
-
- .. attribute:: actuator
-
- the name of the actuator that the sensor is monitoring.
-
- :type: string
-
-.. class:: SCA_AlwaysSensor(SCA_ISensor)
-
- This sensor is always activated.
-
-.. class:: SCA_DelaySensor(SCA_ISensor)
-
- The Delay sensor generates positive and negative triggers at precise time,
- expressed in number of frames. The delay parameter defines the length of the initial OFF period. A positive trigger is generated at the end of this period.
-
- The duration parameter defines the length of the ON period following the OFF period.
- There is a negative trigger at the end of the ON period. If duration is 0, the sensor stays ON and there is no negative trigger.
-
- The sensor runs the OFF-ON cycle once unless the repeat option is set: the OFF-ON cycle repeats indefinately (or the OFF cycle if duration is 0).
-
- Use :class:`SCA_ISensor.reset` at any time to restart sensor.
-
- .. attribute:: delay
-
- length of the initial OFF period as number of frame, 0 for immediate trigger.
-
- :type: integer.
-
- .. attribute:: duration
-
- length of the ON period in number of frame after the initial OFF period.
-
- If duration is greater than 0, a negative trigger is sent at the end of the ON pulse.
-
- :type: integer
-
- .. attribute:: repeat
-
- 1 if the OFF-ON cycle should be repeated indefinately, 0 if it should run once.
-
- :type: integer
-
-.. class:: SCA_JoystickSensor(SCA_ISensor)
-
- This sensor detects player joystick events.
-
- .. attribute:: axisValues
-
- The state of the joysticks axis as a list of values :data:`numAxis` long. (read-only).
-
- :type: list of ints.
-
- Each spesifying the value of an axis between -32767 and 32767 depending on how far the axis is pushed, 0 for nothing.
- The first 2 values are used by most joysticks and gamepads for directional control. 3rd and 4th values are only on some joysticks and can be used for arbitary controls.
-
- * left:[-32767, 0, ...]
- * right:[32767, 0, ...]
- * up:[0, -32767, ...]
- * down:[0, 32767, ...]
-
- .. attribute:: axisSingle
-
- like :data:`axisValues` but returns a single axis value that is set by the sensor. (read-only).
-
- :type: integer
-
- .. note::
-
- Only use this for "Single Axis" type sensors otherwise it will raise an error.
-
- .. attribute:: hatValues
-
- The state of the joysticks hats as a list of values :data:`numHats` long. (read-only).
-
- :type: list of ints
-
- Each spesifying the direction of the hat from 1 to 12, 0 when inactive.
-
- Hat directions are as follows...
-
- * 0:None
- * 1:Up
- * 2:Right
- * 4:Down
- * 8:Left
- * 3:Up - Right
- * 6:Down - Right
- * 12:Down - Left
- * 9:Up - Left
-
- .. attribute:: hatSingle
-
- Like :data:`hatValues` but returns a single hat direction value that is set by the sensor. (read-only).
-
- :type: integer
-
- .. attribute:: numAxis
-
- The number of axes for the joystick at this index. (read-only).
-
- :type: integer
-
- .. attribute:: numButtons
-
- The number of buttons for the joystick at this index. (read-only).
-
- :type: integer
-
- .. attribute:: numHats
-
- The number of hats for the joystick at this index. (read-only).
-
- :type: integer
-
- .. attribute:: connected
-
- True if a joystick is connected at this joysticks index. (read-only).
-
- :type: boolean
-
- .. attribute:: index
-
- The joystick index to use (from 0 to 7). The first joystick is always 0.
-
- :type: integer
-
- .. attribute:: threshold
-
- Axis threshold. Joystick axis motion below this threshold wont trigger an event. Use values between (0 and 32767), lower values are more sensitive.
-
- :type: integer
-
- .. attribute:: button
-
- The button index the sensor reacts to (first button = 0). When the "All Events" toggle is set, this option has no effect.
-
- :type: integer
-
- .. attribute:: axis
-
- The axis this sensor reacts to, as a list of two values [axisIndex, axisDirection]
-
- * axisIndex: the axis index to use when detecting axis movement, 1=primary directional control, 2=secondary directional control.
- * axisDirection: 0=right, 1=up, 2=left, 3=down.
-
- :type: [integer, integer]
-
- .. attribute:: hat
-
- The hat the sensor reacts to, as a list of two values: [hatIndex, hatDirection]
-
- * hatIndex: the hat index to use when detecting hat movement, 1=primary hat, 2=secondary hat (4 max).
- * hatDirection: 1-12.
-
- :type: [integer, integer]
-
- .. method:: getButtonActiveList()
-
- :return: A list containing the indicies of the currently pressed buttons.
- :rtype: list
-
- .. method:: getButtonStatus(buttonIndex)
-
- :arg buttonIndex: the button index, 0=first button
- :type buttonIndex: integer
- :return: The current pressed state of the specified button.
- :rtype: boolean
-
-.. class:: SCA_KeyboardSensor(SCA_ISensor)
-
- A keyboard sensor detects player key presses.
-
- See module :mod:`bge.keys` for keycode values.
-
- .. attribute:: key
-
- The key code this sensor is looking for.
-
- :type: keycode from :mod:`bge.keys` module
-
- .. attribute:: hold1
-
- The key code for the first modifier this sensor is looking for.
-
- :type: keycode from :mod:`bge.keys` module
-
- .. attribute:: hold2
-
- The key code for the second modifier this sensor is looking for.
-
- :type: keycode from :mod:`bge.keys` module
-
- .. attribute:: toggleProperty
-
- The name of the property that indicates whether or not to log keystrokes as a string.
-
- :type: string
-
- .. attribute:: targetProperty
-
- The name of the property that receives keystrokes in case in case a string is logged.
-
- :type: string
-
- .. attribute:: useAllKeys
-
- Flag to determine whether or not to accept all keys.
-
- :type: boolean
-
- .. attribute:: events
-
- a list of pressed keys that have either been pressed, or just released, or are active this frame. (read-only).
-
- :type: list [[:ref:`keycode<keyboard-keys>`, :ref:`status<input-status>`], ...]
-
- .. method:: getKeyStatus(keycode)
-
- Get the status of a key.
-
- :arg keycode: The code that represents the key you want to get the state of, use one of :ref:`these constants<keyboard-keys>`
- :type keycode: integer
- :return: The state of the given key, can be one of :ref:`these constants<input-status>`
- :rtype: int
-
-.. class:: SCA_NANDController(SCA_IController)
-
- An NAND controller activates when all linked sensors are not active.
-
- There are no special python methods for this controller.
-
-.. class:: SCA_NORController(SCA_IController)
-
- An NOR controller activates only when all linked sensors are de-activated.
-
- There are no special python methods for this controller.
-
-.. class:: SCA_ORController(SCA_IController)
-
- An OR controller activates when any connected sensor activates.
-
- There are no special python methods for this controller.
-
-.. class:: SCA_PropertyActuator(SCA_IActuator)
-
- Property Actuator
-
- .. attribute:: propName
-
- the property on which to operate.
-
- :type: string
-
- .. attribute:: value
-
- the value with which the actuator operates.
-
- :type: string
-
- .. attribute:: mode
-
- TODO - add constants to game logic dict!.
-
- :type: integer
-
-.. class:: SCA_PropertySensor(SCA_ISensor)
-
- Activates when the game object property matches.
-
- .. attribute:: mode
-
- Type of check on the property. Can be one of :ref:`these constants <logic-property-sensor>`
-
- :type: integer.
-
- .. attribute:: propName
-
- the property the sensor operates.
-
- :type: string
-
- .. attribute:: value
-
- the value with which the sensor compares to the value of the property.
-
- :type: string
-
- .. attribute:: min
-
- the minimum value of the range used to evaluate the property when in interval mode.
-
- :type: string
-
- .. attribute:: max
-
- the maximum value of the range used to evaluate the property when in interval mode.
-
- :type: string
-
-.. class:: SCA_PythonController(SCA_IController)
-
- A Python controller uses a Python script to activate it's actuators,
- based on it's sensors.
-
- .. attribute:: script
-
- The value of this variable depends on the execution methid.
-
- * When 'Script' execution mode is set this value contains the entire python script as a single string (not the script name as you might expect) which can be modified to run different scripts.
- * When 'Module' execution mode is set this value will contain a single line string - module name and function "module.func" or "package.modile.func" where the module names are python textblocks or external scripts.
-
- :type: string
-
- .. note::
-
- Once this is set the script name given for warnings will remain unchanged.
-
- .. attribute:: mode
-
- the execution mode for this controller (read-only).
-
- * Script: 0, Execite the :data:`script` as a python code.
- * Module: 1, Execite the :data:`script` as a module and function.
-
- :type: integer
-
- .. method:: activate(actuator)
-
- Activates an actuator attached to this controller.
-
- :arg actuator: The actuator to operate on.
- :type actuator: actuator or the actuator name as a string
-
- .. method:: deactivate(actuator)
-
- Deactivates an actuator attached to this controller.
-
- :arg actuator: The actuator to operate on.
- :type actuator: actuator or the actuator name as a string
-
-.. class:: SCA_RandomActuator(SCA_IActuator)
-
- Random Actuator
-
- .. attribute:: seed
-
- Seed of the random number generator.
-
- :type: integer.
-
- Equal seeds produce equal series. If the seed is 0, the generator will produce the same value on every call.
-
- .. attribute:: para1
-
- the first parameter of the active distribution.
-
- :type: float, read-only.
-
- Refer to the documentation of the generator types for the meaning of this value.
-
- .. attribute:: para2
-
- the second parameter of the active distribution.
-
- :type: float, read-only
-
- Refer to the documentation of the generator types for the meaning of this value.
-
- .. attribute:: distribution
-
- Distribution type. (read-only). Can be one of :ref:`these constants <logic-random-distributions>`
-
- :type: integer
-
- .. attribute:: propName
-
- the name of the property to set with the random value.
-
- :type: string
-
- If the generator and property types do not match, the assignment is ignored.
-
- .. method:: setBoolConst(value)
-
- Sets this generator to produce a constant boolean value.
-
- :arg value: The value to return.
- :type value: boolean
-
- .. method:: setBoolUniform()
-
- Sets this generator to produce a uniform boolean distribution.
-
- The generator will generate True or False with 50% chance.
-
- .. method:: setBoolBernouilli(value)
-
- Sets this generator to produce a Bernouilli distribution.
-
- :arg value: Specifies the proportion of False values to produce.
-
- * 0.0: Always generate True
- * 1.0: Always generate False
- :type value: float
-
- .. method:: setIntConst(value)
-
- Sets this generator to always produce the given value.
-
- :arg value: the value this generator produces.
- :type value: integer
-
- .. method:: setIntUniform(lower_bound, upper_bound)
-
- Sets this generator to produce a random value between the given lower and
- upper bounds (inclusive).
-
- :type lower_bound: integer
- :type upper_bound: integer
-
- .. method:: setIntPoisson(value)
-
- Generate a Poisson-distributed number.
-
- This performs a series of Bernouilli tests with parameter value.
- It returns the number of tries needed to achieve succes.
-
- :type value: float
-
- .. method:: setFloatConst(value)
-
- Always generate the given value.
-
- :type value: float
-
- .. method:: setFloatUniform(lower_bound, upper_bound)
-
- Generates a random float between lower_bound and upper_bound with a
- uniform distribution.
-
- :type lower_bound: float
- :type upper_bound: float
-
- .. method:: setFloatNormal(mean, standard_deviation)
-
- Generates a random float from the given normal distribution.
-
- :arg mean: The mean (average) value of the generated numbers
- :type mean: float
- :arg standard_deviation: The standard deviation of the generated numbers.
- :type standard_deviation: float
-
- .. method:: setFloatNegativeExponential(half_life)
-
- Generate negative-exponentially distributed numbers.
-
- The half-life 'time' is characterized by half_life.
-
- :type half_life: float
-
-.. class:: SCA_RandomSensor(SCA_ISensor)
-
- This sensor activates randomly.
-
- .. attribute:: lastDraw
-
- The seed of the random number generator.
-
- :type: integer
-
- .. attribute:: seed
-
- The seed of the random number generator.
-
- :type: integer
-
-.. class:: SCA_XNORController(SCA_IController)
-
- An XNOR controller activates when all linked sensors are the same (activated or inative).
-
- There are no special python methods for this controller.
-
-.. class:: SCA_XORController(SCA_IController)
-
- An XOR controller activates when there is the input is mixed, but not when all are on or off.
-
- There are no special python methods for this controller.
-
-.. class:: KX_Camera(KX_GameObject)
-
- A Camera object.
-
- .. data:: INSIDE
-
- See :data:`sphereInsideFrustum` and :data:`boxInsideFrustum`
-
- .. data:: INTERSECT
-
- See :data:`sphereInsideFrustum` and :data:`boxInsideFrustum`
-
- .. data:: OUTSIDE
-
- See :data:`sphereInsideFrustum` and :data:`boxInsideFrustum`
-
- .. attribute:: lens
-
- The camera's lens value.
-
- :type: float
-
- .. attribute:: ortho_scale
-
- The camera's view scale when in orthographic mode.
-
- :type: float
-
- .. attribute:: near
-
- The camera's near clip distance.
-
- :type: float
-
- .. attribute:: far
-
- The camera's far clip distance.
-
- :type: float
-
- .. attribute:: perspective
-
- True if this camera has a perspective transform, False for an orthographic projection.
-
- :type: boolean
-
- .. attribute:: frustum_culling
-
- True if this camera is frustum culling.
-
- :type: boolean
-
- .. attribute:: projection_matrix
-
- This camera's 4x4 projection matrix.
-
- .. note::
-
- This is the identity matrix prior to rendering the first frame (any Python done on frame 1).
-
- :type: 4x4 Matrix [[float]]
-
- .. attribute:: modelview_matrix
-
- This camera's 4x4 model view matrix. (read-only).
-
- :type: 4x4 Matrix [[float]]
-
- .. note::
-
- This matrix is regenerated every frame from the camera's position and orientation. Also, this is the identity matrix prior to rendering the first frame (any Python done on frame 1).
-
- .. attribute:: camera_to_world
-
- This camera's camera to world transform. (read-only).
-
- :type: 4x4 Matrix [[float]]
-
- .. note::
-
- This matrix is regenerated every frame from the camera's position and orientation.
-
- .. attribute:: world_to_camera
-
- This camera's world to camera transform. (read-only).
-
- :type: 4x4 Matrix [[float]]
-
- .. note::
-
- Regenerated every frame from the camera's position and orientation.
-
- .. note::
-
- This is camera_to_world inverted.
-
- .. attribute:: useViewport
-
- True when the camera is used as a viewport, set True to enable a viewport for this camera.
-
- :type: boolean
-
- .. method:: sphereInsideFrustum(centre, radius)
-
- Tests the given sphere against the view frustum.
-
- :arg centre: The centre of the sphere (in world coordinates.)
- :type centre: list [x, y, z]
- :arg radius: the radius of the sphere
- :type radius: float
- :return: :data:`~bge.types.KX_Camera.INSIDE`, :data:`~bge.types.KX_Camera.OUTSIDE` or :data:`~bge.types.KX_Camera.INTERSECT`
- :rtype: integer
-
- .. note::
-
- When the camera is first initialized the result will be invalid because the projection matrix has not been set.
-
- .. code-block:: python
-
- from bge import logic
- cont = logic.getCurrentController()
- cam = cont.owner
-
- # A sphere of radius 4.0 located at [x, y, z] = [1.0, 1.0, 1.0]
- if (cam.sphereInsideFrustum([1.0, 1.0, 1.0], 4) != cam.OUTSIDE):
- # Sphere is inside frustum !
- # Do something useful !
- else:
- # Sphere is outside frustum
-
- .. method:: boxInsideFrustum(box)
-
- Tests the given box against the view frustum.
-
- :arg box: Eight (8) corner points of the box (in world coordinates.)
- :type box: list of lists
- :return: :data:`~bge.types.KX_Camera.INSIDE`, :data:`~bge.types.KX_Camera.OUTSIDE` or :data:`~bge.types.KX_Camera.INTERSECT`
-
- .. note::
-
- When the camera is first initialized the result will be invalid because the projection matrix has not been set.
-
- .. code-block:: python
-
- from bge import logic
- cont = logic.getCurrentController()
- cam = cont.owner
-
- # Box to test...
- box = []
- box.append([-1.0, -1.0, -1.0])
- box.append([-1.0, -1.0, 1.0])
- box.append([-1.0, 1.0, -1.0])
- box.append([-1.0, 1.0, 1.0])
- box.append([ 1.0, -1.0, -1.0])
- box.append([ 1.0, -1.0, 1.0])
- box.append([ 1.0, 1.0, -1.0])
- box.append([ 1.0, 1.0, 1.0])
-
- if (cam.boxInsideFrustum(box) != cam.OUTSIDE):
- # Box is inside/intersects frustum !
- # Do something useful !
- else:
- # Box is outside the frustum !
-
- .. method:: pointInsideFrustum(point)
-
- Tests the given point against the view frustum.
-
- :arg point: The point to test (in world coordinates.)
- :type point: 3D Vector
- :return: True if the given point is inside this camera's viewing frustum.
- :rtype: boolean
-
- .. note::
-
- When the camera is first initialized the result will be invalid because the projection matrix has not been set.
-
- .. code-block:: python
-
- from bge import logic
- cont = logic.getCurrentController()
- cam = cont.owner
-
- # Test point [0.0, 0.0, 0.0]
- if (cam.pointInsideFrustum([0.0, 0.0, 0.0])):
- # Point is inside frustum !
- # Do something useful !
- else:
- # Box is outside the frustum !
-
- .. method:: getCameraToWorld()
-
- Returns the camera-to-world transform.
-
- :return: the camera-to-world transform matrix.
- :rtype: matrix (4x4 list)
-
- .. method:: getWorldToCamera()
-
- Returns the world-to-camera transform.
-
- This returns the inverse matrix of getCameraToWorld().
-
- :return: the world-to-camera transform matrix.
- :rtype: matrix (4x4 list)
-
- .. method:: setOnTop()
-
- Set this cameras viewport ontop of all other viewport.
-
- .. method:: setViewport(left, bottom, right, top)
-
- Sets the region of this viewport on the screen in pixels.
-
- Use :data:`bge.render.getWindowHeight` and :data:`bge.render.getWindowWidth` to calculate values relative to the entire display.
-
- :arg left: left pixel coordinate of this viewport
- :type left: integer
- :arg bottom: bottom pixel coordinate of this viewport
- :type bottom: integer
- :arg right: right pixel coordinate of this viewport
- :type right: integer
- :arg top: top pixel coordinate of this viewport
- :type top: integer
-
- .. method:: getScreenPosition(object)
-
- Gets the position of an object projected on screen space.
-
- .. code-block:: python
-
- # For an object in the middle of the screen, coord = [0.5, 0.5]
- coord = camera.getScreenPosition(object)
-
- :arg object: object name or list [x, y, z]
- :type object: :class:`KX_GameObject` or 3D Vector
- :return: the object's position in screen coordinates.
- :rtype: list [x, y]
-
- .. method:: getScreenVect(x, y)
-
- Gets the vector from the camera position in the screen coordinate direction.
-
- :arg x: X Axis
- :type x: float
- :arg y: Y Axis
- :type y: float
- :rtype: 3D Vector
- :return: The vector from screen coordinate.
-
- .. code-block:: python
-
- # Gets the vector of the camera front direction:
- m_vect = camera.getScreenVect(0.5, 0.5)
-
- .. method:: getScreenRay(x, y, dist=inf, property=None)
-
- Look towards a screen coordinate (x, y) and find first object hit within dist that matches prop.
- The ray is similar to KX_GameObject->rayCastTo.
-
- :arg x: X Axis
- :type x: float
- :arg y: Y Axis
- :type y: float
- :arg dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to other
- :type dist: float
- :arg property: property name that object must have; can be omitted => detect any object
- :type property: string
- :rtype: :class:`KX_GameObject`
- :return: the first object hit or None if no object or object does not match prop
-
- .. code-block:: python
-
- # Gets an object with a property "wall" in front of the camera within a distance of 100:
- target = camera.getScreenRay(0.5, 0.5, 100, "wall")
-
-.. class:: BL_ArmatureObject(KX_GameObject)
-
- An armature object.
-
- .. attribute:: constraints
-
- The list of armature constraint defined on this armature.
- Elements of the list can be accessed by index or string.
- The key format for string access is '<bone_name>:<constraint_name>'.
-
- :type: list of :class:`BL_ArmatureConstraint`
-
- .. attribute:: channels
-
- The list of armature channels.
- Elements of the list can be accessed by index or name the bone.
-
- :type: list of :class:`BL_ArmatureChannel`
-
- .. method:: update()
-
- Ensures that the armature will be updated on next graphic frame.
-
- This action is unecessary if a KX_ArmatureActuator with mode run is active
- or if an action is playing. Use this function in other cases. It must be called
- on each frame to ensure that the armature is updated continously.
-
-.. class:: BL_ArmatureActuator(SCA_IActuator)
-
- Armature Actuators change constraint condition on armatures.
-
- .. attribute:: type
-
- The type of action that the actuator executes when it is active.
-
- Can be one of :ref:`these constants <armatureactuator-constants-type>`
-
- :type: integer
-
- .. attribute:: constraint
-
- The constraint object this actuator is controlling.
-
- :type: :class:`BL_ArmatureConstraint`
-
- .. attribute:: target
-
- The object that this actuator will set as primary target to the constraint it controls.
-
- :type: :class:`KX_GameObject`
-
- .. attribute:: subtarget
-
- The object that this actuator will set as secondary target to the constraint it controls.
-
- :type: :class:`KX_GameObject`.
-
- .. note::
-
- Currently, the only secondary target is the pole target for IK constraint.
-
- .. attribute:: weight
-
- The weight this actuator will set on the constraint it controls.
-
- :type: float.
-
- .. note::
-
- Currently only the IK constraint has a weight. It must be a value between 0 and 1.
-
- .. note::
-
- A weight of 0 disables a constraint while still updating constraint runtime values (see :class:`BL_ArmatureConstraint`)
-
- .. attribute:: influence
-
- The influence this actuator will set on the constraint it controls.
-
- :type: float.
-
-.. class:: KX_ArmatureSensor(SCA_ISensor)
-
- Armature sensor detect conditions on armatures.
-
- .. attribute:: type
-
- The type of measurement that the sensor make when it is active.
-
- Can be one of :ref:`these constants <armaturesensor-type>`
-
- :type: integer.
-
- .. attribute:: constraint
-
- The constraint object this sensor is watching.
-
- :type: :class:`BL_ArmatureConstraint`
-
- .. attribute:: value
-
- The threshold used in the comparison with the constraint error
- The linear error is only updated on CopyPose/Distance IK constraint with iTaSC solver
- The rotation error is only updated on CopyPose+rotation IK constraint with iTaSC solver
- The linear error on CopyPose is always >= 0: it is the norm of the distance between the target and the bone
- The rotation error on CopyPose is always >= 0: it is the norm of the equivalent rotation vector between the bone and the target orientations
- The linear error on Distance can be positive if the distance between the bone and the target is greater than the desired distance, and negative if the distance is smaller.
-
- :type: float
-
-.. class:: BL_ArmatureConstraint(PyObjectPlus)
-
- Proxy to Armature Constraint. Allows to change constraint on the fly.
- Obtained through :class:`BL_ArmatureObject`.constraints.
-
- .. note::
-
- Not all armature constraints are supported in the GE.
-
-
- .. attribute:: type
-
- Type of constraint, (read-only).
-
- Use one of :ref:`these constants<armatureconstraint-constants-type>`.
-
- :type: integer, one of CONSTRAINT_TYPE_* constants
-
- .. attribute:: name
-
- Name of constraint constructed as <bone_name>:<constraint_name>. constraints list.
-
- :type: string
-
- This name is also the key subscript on :class:`BL_ArmatureObject`.
-
- .. attribute:: enforce
-
- fraction of constraint effect that is enforced. Between 0 and 1.
-
- :type: float
-
- .. attribute:: headtail
-
- Position of target between head and tail of the target bone: 0=head, 1=tail.
-
- :type: float.
-
- .. note::
-
- Only used if the target is a bone (i.e target object is an armature.
-
- .. attribute:: lin_error
-
- runtime linear error (in Blender units) on constraint at the current frame.
-
- This is a runtime value updated on each frame by the IK solver. Only available on IK constraint and iTaSC solver.
-
- :type: float
-
- .. attribute:: rot_error
-
- Runtime rotation error (in radiant) on constraint at the current frame.
-
- :type: float.
-
- This is a runtime value updated on each frame by the IK solver. Only available on IK constraint and iTaSC solver.
-
- It is only set if the constraint has a rotation part, for example, a CopyPose+Rotation IK constraint.
-
- .. attribute:: target
-
- Primary target object for the constraint. The position of this object in the GE will be used as target for the constraint.
-
- :type: :class:`KX_GameObject`.
-
- .. attribute:: subtarget
-
- Secondary target object for the constraint. The position of this object in the GE will be used as secondary target for the constraint.
-
- :type: :class:`KX_GameObject`.
-
- Currently this is only used for pole target on IK constraint.
-
- .. attribute:: active
-
- True if the constraint is active.
-
- :type: boolean
-
- .. note::
-
- An inactive constraint does not update lin_error and rot_error.
-
- .. attribute:: ik_weight
-
- Weight of the IK constraint between 0 and 1.
-
- Only defined for IK constraint.
-
- :type: float
-
- .. attribute:: ik_type
-
- Type of IK constraint, (read-only).
-
- Use one of :ref:`these constants<armatureconstraint-constants-ik-type>`.
-
- :type: integer.
-
- .. attribute:: ik_flag
-
- Combination of IK constraint option flags, read-only.
-
- Use one of :ref:`these constants<armatureconstraint-constants-ik-flag>`.
-
- :type: integer
-
- .. attribute:: ik_dist
-
- Distance the constraint is trying to maintain with target, only used when ik_type=CONSTRAINT_IK_DISTANCE.
-
- :type: float
-
- .. attribute:: ik_mode
-
- Use one of :ref:`these constants<armatureconstraint-constants-ik-mode>`.
-
- Additional mode for IK constraint. Currently only used for Distance constraint:
-
- :type: integer
-
-.. class:: BL_ArmatureChannel(PyObjectPlus)
-
- Proxy to armature pose channel. Allows to read and set armature pose.
- The attributes are identical to RNA attributes, but mostly in read-only mode.
-
- .. attribute:: name
-
- channel name (=bone name), read-only.
-
- :type: string
-
- .. attribute:: bone
-
- return the bone object corresponding to this pose channel, read-only.
-
- :type: :class:`BL_ArmatureBone`
-
- .. attribute:: parent
-
- return the parent channel object, None if root channel, read-only.
-
- :type: :class:`BL_ArmatureChannel`
-
- .. attribute:: has_ik
-
- true if the bone is part of an active IK chain, read-only.
- This flag is not set when an IK constraint is defined but not enabled (miss target information for example).
-
- :type: boolean
-
- .. attribute:: ik_dof_x
-
- true if the bone is free to rotation in the X axis, read-only.
-
- :type: boolean
-
- .. attribute:: ik_dof_y
-
- true if the bone is free to rotation in the Y axis, read-only.
-
- :type: boolean
-
- .. attribute:: ik_dof_z
-
- true if the bone is free to rotation in the Z axis, read-only.
-
- :type: boolean
-
- .. attribute:: ik_limit_x
-
- true if a limit is imposed on X rotation, read-only.
-
- :type: boolean
-
- .. attribute:: ik_limit_y
-
- true if a limit is imposed on Y rotation, read-only.
-
- :type: boolean
-
- .. attribute:: ik_limit_z
-
- true if a limit is imposed on Z rotation, read-only.
-
- :type: boolean
-
- .. attribute:: ik_rot_control
-
- true if channel rotation should applied as IK constraint, read-only.
-
- :type: boolean
-
- .. attribute:: ik_lin_control
-
- true if channel size should applied as IK constraint, read-only.
-
- :type: boolean
-
- .. attribute:: location
-
- displacement of the bone head in armature local space, read-write.
-
- :type: vector [X, Y, Z].
-
- .. note::
-
- You can only move a bone if it is unconnected to its parent. An action playing on the armature may change the value. An IK chain does not update this value, see joint_rotation.
-
- .. note::
-
- Changing this field has no immediate effect, the pose is updated when the armature is updated during the graphic render (see :data:`BL_ArmatureObject.update`).
-
- .. attribute:: scale
-
- scale of the bone relative to its parent, read-write.
-
- :type: vector [sizeX, sizeY, sizeZ].
-
- .. note::
-
- An action playing on the armature may change the value. An IK chain does not update this value, see joint_rotation.
-
- .. note::
-
- Changing this field has no immediate effect, the pose is updated when the armature is updated during the graphic render (see :data:`BL_ArmatureObject.update`)
-
- .. attribute:: rotation_quaternion
-
- rotation of the bone relative to its parent expressed as a quaternion, read-write.
-
- :type: vector [qr, qi, qj, qk].
-
- .. note::
-
- This field is only used if rotation_mode is 0. An action playing on the armature may change the value. An IK chain does not update this value, see joint_rotation.
-
- .. note::
-
- Changing this field has no immediate effect, the pose is updated when the armature is updated during the graphic render (see :data:`BL_ArmatureObject.update`)
-
- .. attribute:: rotation_euler
-
- rotation of the bone relative to its parent expressed as a set of euler angles, read-write.
-
- :type: vector [X, Y, Z].
-
- .. note::
-
- This field is only used if rotation_mode is > 0. You must always pass the angles in [X, Y, Z] order; the order of applying the angles to the bone depends on rotation_mode. An action playing on the armature may change this field. An IK chain does not update this value, see joint_rotation.
-
- .. note::
-
- Changing this field has no immediate effect, the pose is updated when the armature is updated during the graphic render (see :data:`BL_ArmatureObject.update`)
-
- .. attribute:: rotation_mode
-
- Method of updating the bone rotation, read-write.
-
- :type: integer (one of :ref:`these constants <armaturechannel-constants-rotation-mode>`)
-
- .. attribute:: channel_matrix
-
- pose matrix in bone space (deformation of the bone due to action, constraint, etc), Read-only.
- This field is updated after the graphic render, it represents the current pose.
-
- :type: matrix [4][4]
-
- .. attribute:: pose_matrix
-
- pose matrix in armature space, read-only,
- This field is updated after the graphic render, it represents the current pose.
-
- :type: matrix [4][4]
-
- .. attribute:: pose_head
-
- position of bone head in armature space, read-only.
-
- :type: vector [x, y, z]
-
- .. attribute:: pose_tail
-
- position of bone tail in armature space, read-only.
-
- :type: vector [x, y, z]
-
- .. attribute:: ik_min_x
-
- minimum value of X rotation in degree (<= 0) when X rotation is limited (see ik_limit_x), read-only.
-
- :type: float
-
- .. attribute:: ik_max_x
-
- maximum value of X rotation in degree (>= 0) when X rotation is limited (see ik_limit_x), read-only.
-
- :type: float
-
- .. attribute:: ik_min_y
-
- minimum value of Y rotation in degree (<= 0) when Y rotation is limited (see ik_limit_y), read-only.
-
- :type: float
-
- .. attribute:: ik_max_y
-
- maximum value of Y rotation in degree (>= 0) when Y rotation is limited (see ik_limit_y), read-only.
-
- :type: float
-
- .. attribute:: ik_min_z
-
- minimum value of Z rotation in degree (<= 0) when Z rotation is limited (see ik_limit_z), read-only.
-
- :type: float
-
- .. attribute:: ik_max_z
-
- maximum value of Z rotation in degree (>= 0) when Z rotation is limited (see ik_limit_z), read-only.
-
- :type: float
-
- .. attribute:: ik_stiffness_x
-
- bone rotation stiffness in X axis, read-only.
-
- :type: float between 0 and 1
-
- .. attribute:: ik_stiffness_y
-
- bone rotation stiffness in Y axis, read-only.
-
- :type: float between 0 and 1
-
- .. attribute:: ik_stiffness_z
-
- bone rotation stiffness in Z axis, read-only.
-
- :type: float between 0 and 1
-
- .. attribute:: ik_stretch
-
- ratio of scale change that is allowed, 0=bone can't change size, read-only.
-
- :type: float
-
- .. attribute:: ik_rot_weight
-
- weight of rotation constraint when ik_rot_control is set, read-write.
-
- :type: float between 0 and 1
-
- .. attribute:: ik_lin_weight
-
- weight of size constraint when ik_lin_control is set, read-write.
-
- :type: float between 0 and 1
-
- .. attribute:: joint_rotation
-
- Control bone rotation in term of joint angle (for robotic applications), read-write.
-
- When writing to this attribute, you pass a [x, y, z] vector and an appropriate set of euler angles or quaternion is calculated according to the rotation_mode.
-
- When you read this attribute, the current pose matrix is converted into a [x, y, z] vector representing the joint angles.
-
- The value and the meaning of the x, y, z depends on the ik_dof_x/ik_dof_y/ik_dof_z attributes:
-
- * 1DoF joint X, Y or Z: the corresponding x, y, or z value is used an a joint angle in radiant
- * 2DoF joint X+Y or Z+Y: treated as 2 successive 1DoF joints: first X or Z, then Y. The x or z value is used as a joint angle in radiant along the X or Z axis, followed by a rotation along the new Y axis of y radiants.
- * 2DoF joint X+Z: treated as a 2DoF joint with rotation axis on the X/Z plane. The x and z values are used as the coordinates of the rotation vector in the X/Z plane.
- * 3DoF joint X+Y+Z: treated as a revolute joint. The [x, y, z] vector represents the equivalent rotation vector to bring the joint from the rest pose to the new pose.
-
- :type: vector [x, y, z]
-
- .. note::
-
- The bone must be part of an IK chain if you want to set the ik_dof_x/ik_dof_y/ik_dof_z attributes via the UI, but this will interfere with this attribute since the IK solver will overwrite the pose. You can stay in control of the armature if you create an IK constraint but do not finalize it (e.g. don't set a target) the IK solver will not run but the IK panel will show up on the UI for each bone in the chain.
-
- .. note::
-
- [0, 0, 0] always corresponds to the rest pose.
-
- .. note::
-
- You must request the armature pose to update and wait for the next graphic frame to see the effect of setting this attribute (see :data:`BL_ArmatureObject.update`).
-
- .. note::
-
- You can read the result of the calculation in rotation or euler_rotation attributes after setting this attribute.
-
-.. class:: BL_ArmatureBone(PyObjectPlus)
-
- Proxy to Blender bone structure. All fields are read-only and comply to RNA names.
- All space attribute correspond to the rest pose.
-
- .. attribute:: name
-
- bone name.
-
- :type: string
-
- .. attribute:: connected
-
- true when the bone head is struck to the parent's tail.
-
- :type: boolean
-
- .. attribute:: hinge
-
- true when bone doesn't inherit rotation or scale from parent bone.
-
- :type: boolean
-
- .. attribute:: inherit_scale
-
- true when bone inherits scaling from parent bone.
-
- :type: boolean
-
- .. attribute:: bbone_segments
-
- number of B-bone segments.
-
- :type: integer
-
- .. attribute:: roll
-
- bone rotation around head-tail axis.
-
- :type: float
-
- .. attribute:: head
-
- location of head end of the bone in parent bone space.
-
- :type: vector [x, y, z]
-
- .. attribute:: tail
-
- location of head end of the bone in parent bone space.
-
- :type: vector [x, y, z]
-
- .. attribute:: length
-
- bone length.
-
- :type: float
-
- .. attribute:: arm_head
-
- location of head end of the bone in armature space.
-
- :type: vector [x, y, z]
-
- .. attribute:: arm_tail
-
- location of tail end of the bone in armature space.
-
- :type: vector [x, y, z]
-
- .. attribute:: arm_mat
-
- matrix of the bone head in armature space.
-
- :type: matrix [4][4]
-
- .. note::
-
- This matrix has no scale part.
-
- .. attribute:: bone_mat
-
- rotation matrix of the bone in parent bone space.
-
- :type: matrix [3][3]
-
- .. attribute:: parent
-
- parent bone, or None for root bone.
-
- :type: :class:`BL_ArmatureBone`
-
- .. attribute:: children
-
- list of bone's children.
-
- :type: list of :class:`BL_ArmatureBone`
diff --git a/doc/python_api/rst/bge_types/bge.types.BL_ActionActuator.rst b/doc/python_api/rst/bge_types/bge.types.BL_ActionActuator.rst
new file mode 100644
index 00000000000..9b95a5ba611
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.BL_ActionActuator.rst
@@ -0,0 +1,78 @@
+BL_ActionActuator(SCA_IActuator)
+================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: BL_ActionActuator(SCA_IActuator)
+
+ Action Actuators apply an action to an actor.
+
+ .. attribute:: action
+
+ The name of the action to set as the current action.
+
+ :type: string
+
+ .. attribute:: frameStart
+
+ Specifies the starting frame of the animation.
+
+ :type: float
+
+ .. attribute:: frameEnd
+
+ Specifies the ending frame of the animation.
+
+ :type: float
+
+ .. attribute:: blendIn
+
+ Specifies the number of frames of animation to generate when making transitions between actions.
+
+ :type: float
+
+ .. attribute:: priority
+
+ Sets the priority of this actuator. Actuators will lower priority numbers will override actuators with higher numbers.
+
+ :type: integer
+
+ .. attribute:: frame
+
+ Sets the current frame for the animation.
+
+ :type: float
+
+ .. attribute:: propName
+
+ Sets the property to be used in FromProp playback mode.
+
+ :type: string
+
+ .. attribute:: blendTime
+
+ Sets the internal frame timer. This property must be in the range from 0.0 to blendIn.
+
+ :type: float
+
+ .. attribute:: mode
+
+ The operation mode of the actuator. Can be one of :ref:`these constants<action-actuator>`.
+
+ :type: integer
+
+ .. attribute:: useContinue
+
+ The actions continue option, True or False. When True, the action will always play from where last left off,
+ otherwise negative events to this actuator will reset it to its start frame.
+
+ :type: boolean
+
+ .. attribute:: framePropName
+
+ The name of the property that is set to the current frame number.
+
+ :type: string
+
diff --git a/doc/python_api/rst/bge_types/bge.types.BL_ArmatureActuator.rst b/doc/python_api/rst/bge_types/bge.types.BL_ArmatureActuator.rst
new file mode 100644
index 00000000000..579186ac1d6
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.BL_ArmatureActuator.rst
@@ -0,0 +1,61 @@
+BL_ArmatureActuator(SCA_IActuator)
+==================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: BL_ArmatureActuator(SCA_IActuator)
+
+ Armature Actuators change constraint condition on armatures.
+
+ .. attribute:: type
+
+ The type of action that the actuator executes when it is active.
+
+ Can be one of :ref:`these constants <armatureactuator-constants-type>`
+
+ :type: integer
+
+ .. attribute:: constraint
+
+ The constraint object this actuator is controlling.
+
+ :type: :class:`BL_ArmatureConstraint`
+
+ .. attribute:: target
+
+ The object that this actuator will set as primary target to the constraint it controls.
+
+ :type: :class:`KX_GameObject`
+
+ .. attribute:: subtarget
+
+ The object that this actuator will set as secondary target to the constraint it controls.
+
+ :type: :class:`KX_GameObject`.
+
+ .. note::
+
+ Currently, the only secondary target is the pole target for IK constraint.
+
+ .. attribute:: weight
+
+ The weight this actuator will set on the constraint it controls.
+
+ :type: float.
+
+ .. note::
+
+ Currently only the IK constraint has a weight. It must be a value between 0 and 1.
+
+ .. note::
+
+ A weight of 0 disables a constraint while still updating constraint runtime values (see :class:`BL_ArmatureConstraint`)
+
+ .. attribute:: influence
+
+ The influence this actuator will set on the constraint it controls.
+
+ :type: float.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.BL_ArmatureBone.rst b/doc/python_api/rst/bge_types/bge.types.BL_ArmatureBone.rst
new file mode 100644
index 00000000000..14a9ebe9ef3
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.BL_ArmatureBone.rst
@@ -0,0 +1,105 @@
+BL_ArmatureBone(PyObjectPlus)
+=============================
+
+.. module:: bge.types
+
+base class --- :class:`PyObjectPlus`
+
+.. class:: BL_ArmatureBone(PyObjectPlus)
+
+ Proxy to Blender bone structure. All fields are read-only and comply to RNA names.
+ All space attribute correspond to the rest pose.
+
+ .. attribute:: name
+
+ bone name.
+
+ :type: string
+
+ .. attribute:: connected
+
+ true when the bone head is struck to the parent's tail.
+
+ :type: boolean
+
+ .. attribute:: hinge
+
+ true when bone doesn't inherit rotation or scale from parent bone.
+
+ :type: boolean
+
+ .. attribute:: inherit_scale
+
+ true when bone inherits scaling from parent bone.
+
+ :type: boolean
+
+ .. attribute:: bbone_segments
+
+ number of B-bone segments.
+
+ :type: integer
+
+ .. attribute:: roll
+
+ bone rotation around head-tail axis.
+
+ :type: float
+
+ .. attribute:: head
+
+ location of head end of the bone in parent bone space.
+
+ :type: vector [x, y, z]
+
+ .. attribute:: tail
+
+ location of head end of the bone in parent bone space.
+
+ :type: vector [x, y, z]
+
+ .. attribute:: length
+
+ bone length.
+
+ :type: float
+
+ .. attribute:: arm_head
+
+ location of head end of the bone in armature space.
+
+ :type: vector [x, y, z]
+
+ .. attribute:: arm_tail
+
+ location of tail end of the bone in armature space.
+
+ :type: vector [x, y, z]
+
+ .. attribute:: arm_mat
+
+ matrix of the bone head in armature space.
+
+ :type: matrix [4][4]
+
+ .. note::
+
+ This matrix has no scale part.
+
+ .. attribute:: bone_mat
+
+ rotation matrix of the bone in parent bone space.
+
+ :type: matrix [3][3]
+
+ .. attribute:: parent
+
+ parent bone, or None for root bone.
+
+ :type: :class:`BL_ArmatureBone`
+
+ .. attribute:: children
+
+ list of bone's children.
+
+ :type: list of :class:`BL_ArmatureBone`
diff --git a/doc/python_api/rst/bge_types/bge.types.BL_ArmatureChannel.rst b/doc/python_api/rst/bge_types/bge.types.BL_ArmatureChannel.rst
new file mode 100644
index 00000000000..07220534b28
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.BL_ArmatureChannel.rst
@@ -0,0 +1,278 @@
+BL_ArmatureChannel(PyObjectPlus)
+================================
+
+.. module:: bge.types
+
+base class --- :class:`PyObjectPlus`
+
+.. class:: BL_ArmatureChannel(PyObjectPlus)
+
+ Proxy to armature pose channel. Allows to read and set armature pose.
+ The attributes are identical to RNA attributes, but mostly in read-only mode.
+
+ .. attribute:: name
+
+ channel name (=bone name), read-only.
+
+ :type: string
+
+ .. attribute:: bone
+
+ return the bone object corresponding to this pose channel, read-only.
+
+ :type: :class:`BL_ArmatureBone`
+
+ .. attribute:: parent
+
+ return the parent channel object, None if root channel, read-only.
+
+ :type: :class:`BL_ArmatureChannel`
+
+ .. attribute:: has_ik
+
+ true if the bone is part of an active IK chain, read-only.
+ This flag is not set when an IK constraint is defined but not enabled (miss target information for example).
+
+ :type: boolean
+
+ .. attribute:: ik_dof_x
+
+ true if the bone is free to rotation in the X axis, read-only.
+
+ :type: boolean
+
+ .. attribute:: ik_dof_y
+
+ true if the bone is free to rotation in the Y axis, read-only.
+
+ :type: boolean
+
+ .. attribute:: ik_dof_z
+
+ true if the bone is free to rotation in the Z axis, read-only.
+
+ :type: boolean
+
+ .. attribute:: ik_limit_x
+
+ true if a limit is imposed on X rotation, read-only.
+
+ :type: boolean
+
+ .. attribute:: ik_limit_y
+
+ true if a limit is imposed on Y rotation, read-only.
+
+ :type: boolean
+
+ .. attribute:: ik_limit_z
+
+ true if a limit is imposed on Z rotation, read-only.
+
+ :type: boolean
+
+ .. attribute:: ik_rot_control
+
+ true if channel rotation should applied as IK constraint, read-only.
+
+ :type: boolean
+
+ .. attribute:: ik_lin_control
+
+ true if channel size should applied as IK constraint, read-only.
+
+ :type: boolean
+
+ .. attribute:: location
+
+ displacement of the bone head in armature local space, read-write.
+
+ :type: vector [X, Y, Z].
+
+ .. note::
+
+ You can only move a bone if it is unconnected to its parent. An action playing on the armature may change the value. An IK chain does not update this value, see joint_rotation.
+
+ .. note::
+
+ Changing this field has no immediate effect, the pose is updated when the armature is updated during the graphic render (see :data:`BL_ArmatureObject.update`).
+
+ .. attribute:: scale
+
+ scale of the bone relative to its parent, read-write.
+
+ :type: vector [sizeX, sizeY, sizeZ].
+
+ .. note::
+
+ An action playing on the armature may change the value. An IK chain does not update this value, see joint_rotation.
+
+ .. note::
+
+ Changing this field has no immediate effect, the pose is updated when the armature is updated during the graphic render (see :data:`BL_ArmatureObject.update`)
+
+ .. attribute:: rotation_quaternion
+
+ rotation of the bone relative to its parent expressed as a quaternion, read-write.
+
+ :type: vector [qr, qi, qj, qk].
+
+ .. note::
+
+ This field is only used if rotation_mode is 0. An action playing on the armature may change the value. An IK chain does not update this value, see joint_rotation.
+
+ .. note::
+
+ Changing this field has no immediate effect, the pose is updated when the armature is updated during the graphic render (see :data:`BL_ArmatureObject.update`)
+
+ .. attribute:: rotation_euler
+
+ rotation of the bone relative to its parent expressed as a set of euler angles, read-write.
+
+ :type: vector [X, Y, Z].
+
+ .. note::
+
+ This field is only used if rotation_mode is > 0. You must always pass the angles in [X, Y, Z] order; the order of applying the angles to the bone depends on rotation_mode. An action playing on the armature may change this field. An IK chain does not update this value, see joint_rotation.
+
+ .. note::
+
+ Changing this field has no immediate effect, the pose is updated when the armature is updated during the graphic render (see :data:`BL_ArmatureObject.update`)
+
+ .. attribute:: rotation_mode
+
+ Method of updating the bone rotation, read-write.
+
+ :type: integer (one of :ref:`these constants <armaturechannel-constants-rotation-mode>`)
+
+ .. attribute:: channel_matrix
+
+ pose matrix in bone space (deformation of the bone due to action, constraint, etc), Read-only.
+ This field is updated after the graphic render, it represents the current pose.
+
+ :type: matrix [4][4]
+
+ .. attribute:: pose_matrix
+
+ pose matrix in armature space, read-only,
+ This field is updated after the graphic render, it represents the current pose.
+
+ :type: matrix [4][4]
+
+ .. attribute:: pose_head
+
+ position of bone head in armature space, read-only.
+
+ :type: vector [x, y, z]
+
+ .. attribute:: pose_tail
+
+ position of bone tail in armature space, read-only.
+
+ :type: vector [x, y, z]
+
+ .. attribute:: ik_min_x
+
+ minimum value of X rotation in degree (<= 0) when X rotation is limited (see ik_limit_x), read-only.
+
+ :type: float
+
+ .. attribute:: ik_max_x
+
+ maximum value of X rotation in degree (>= 0) when X rotation is limited (see ik_limit_x), read-only.
+
+ :type: float
+
+ .. attribute:: ik_min_y
+
+ minimum value of Y rotation in degree (<= 0) when Y rotation is limited (see ik_limit_y), read-only.
+
+ :type: float
+
+ .. attribute:: ik_max_y
+
+ maximum value of Y rotation in degree (>= 0) when Y rotation is limited (see ik_limit_y), read-only.
+
+ :type: float
+
+ .. attribute:: ik_min_z
+
+ minimum value of Z rotation in degree (<= 0) when Z rotation is limited (see ik_limit_z), read-only.
+
+ :type: float
+
+ .. attribute:: ik_max_z
+
+ maximum value of Z rotation in degree (>= 0) when Z rotation is limited (see ik_limit_z), read-only.
+
+ :type: float
+
+ .. attribute:: ik_stiffness_x
+
+ bone rotation stiffness in X axis, read-only.
+
+ :type: float between 0 and 1
+
+ .. attribute:: ik_stiffness_y
+
+ bone rotation stiffness in Y axis, read-only.
+
+ :type: float between 0 and 1
+
+ .. attribute:: ik_stiffness_z
+
+ bone rotation stiffness in Z axis, read-only.
+
+ :type: float between 0 and 1
+
+ .. attribute:: ik_stretch
+
+ ratio of scale change that is allowed, 0=bone can't change size, read-only.
+
+ :type: float
+
+ .. attribute:: ik_rot_weight
+
+ weight of rotation constraint when ik_rot_control is set, read-write.
+
+ :type: float between 0 and 1
+
+ .. attribute:: ik_lin_weight
+
+ weight of size constraint when ik_lin_control is set, read-write.
+
+ :type: float between 0 and 1
+
+ .. attribute:: joint_rotation
+
+ Control bone rotation in term of joint angle (for robotic applications), read-write.
+
+ When writing to this attribute, you pass a [x, y, z] vector and an appropriate set of euler angles or quaternion is calculated according to the rotation_mode.
+
+ When you read this attribute, the current pose matrix is converted into a [x, y, z] vector representing the joint angles.
+
+ The value and the meaning of the x, y, z depends on the ik_dof_x/ik_dof_y/ik_dof_z attributes:
+
+ * 1DoF joint X, Y or Z: the corresponding x, y, or z value is used an a joint angle in radiant
+ * 2DoF joint X+Y or Z+Y: treated as 2 successive 1DoF joints: first X or Z, then Y. The x or z value is used as a joint angle in radiant along the X or Z axis, followed by a rotation along the new Y axis of y radiants.
+ * 2DoF joint X+Z: treated as a 2DoF joint with rotation axis on the X/Z plane. The x and z values are used as the coordinates of the rotation vector in the X/Z plane.
+ * 3DoF joint X+Y+Z: treated as a revolute joint. The [x, y, z] vector represents the equivalent rotation vector to bring the joint from the rest pose to the new pose.
+
+ :type: vector [x, y, z]
+
+ .. note::
+
+ The bone must be part of an IK chain if you want to set the ik_dof_x/ik_dof_y/ik_dof_z attributes via the UI, but this will interfere with this attribute since the IK solver will overwrite the pose. You can stay in control of the armature if you create an IK constraint but do not finalize it (e.g. don't set a target) the IK solver will not run but the IK panel will show up on the UI for each bone in the chain.
+
+ .. note::
+
+ [0, 0, 0] always corresponds to the rest pose.
+
+ .. note::
+
+ You must request the armature pose to update and wait for the next graphic frame to see the effect of setting this attribute (see :data:`BL_ArmatureObject.update`).
+
+ .. note::
+
+ You can read the result of the calculation in rotation or euler_rotation attributes after setting this attribute.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.BL_ArmatureConstraint.rst b/doc/python_api/rst/bge_types/bge.types.BL_ArmatureConstraint.rst
new file mode 100644
index 00000000000..1a4370945c1
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.BL_ArmatureConstraint.rst
@@ -0,0 +1,129 @@
+BL_ArmatureConstraint(PyObjectPlus)
+===================================
+
+.. module:: bge.types
+
+base class --- :class:`PyObjectPlus`
+
+.. class:: BL_ArmatureConstraint(PyObjectPlus)
+
+ Proxy to Armature Constraint. Allows to change constraint on the fly.
+ Obtained through :class:`BL_ArmatureObject`.constraints.
+
+ .. note::
+
+ Not all armature constraints are supported in the GE.
+
+
+ .. attribute:: type
+
+ Type of constraint, (read-only).
+
+ Use one of :ref:`these constants<armatureconstraint-constants-type>`.
+
+ :type: integer, one of CONSTRAINT_TYPE_* constants
+
+ .. attribute:: name
+
+ Name of constraint constructed as <bone_name>:<constraint_name>. constraints list.
+
+ :type: string
+
+ This name is also the key subscript on :class:`BL_ArmatureObject`.
+
+ .. attribute:: enforce
+
+ fraction of constraint effect that is enforced. Between 0 and 1.
+
+ :type: float
+
+ .. attribute:: headtail
+
+ Position of target between head and tail of the target bone: 0=head, 1=tail.
+
+ :type: float.
+
+ .. note::
+
+ Only used if the target is a bone (i.e target object is an armature.
+
+ .. attribute:: lin_error
+
+ runtime linear error (in Blender units) on constraint at the current frame.
+
+ This is a runtime value updated on each frame by the IK solver. Only available on IK constraint and iTaSC solver.
+
+ :type: float
+
+ .. attribute:: rot_error
+
+ Runtime rotation error (in radiant) on constraint at the current frame.
+
+ :type: float.
+
+ This is a runtime value updated on each frame by the IK solver. Only available on IK constraint and iTaSC solver.
+
+ It is only set if the constraint has a rotation part, for example, a CopyPose+Rotation IK constraint.
+
+ .. attribute:: target
+
+ Primary target object for the constraint. The position of this object in the GE will be used as target for the constraint.
+
+ :type: :class:`KX_GameObject`.
+
+ .. attribute:: subtarget
+
+ Secondary target object for the constraint. The position of this object in the GE will be used as secondary target for the constraint.
+
+ :type: :class:`KX_GameObject`.
+
+ Currently this is only used for pole target on IK constraint.
+
+ .. attribute:: active
+
+ True if the constraint is active.
+
+ :type: boolean
+
+ .. note::
+
+ An inactive constraint does not update lin_error and rot_error.
+
+ .. attribute:: ik_weight
+
+ Weight of the IK constraint between 0 and 1.
+
+ Only defined for IK constraint.
+
+ :type: float
+
+ .. attribute:: ik_type
+
+ Type of IK constraint, (read-only).
+
+ Use one of :ref:`these constants<armatureconstraint-constants-ik-type>`.
+
+ :type: integer.
+
+ .. attribute:: ik_flag
+
+ Combination of IK constraint option flags, read-only.
+
+ Use one of :ref:`these constants<armatureconstraint-constants-ik-flag>`.
+
+ :type: integer
+
+ .. attribute:: ik_dist
+
+ Distance the constraint is trying to maintain with target, only used when ik_type=CONSTRAINT_IK_DISTANCE.
+
+ :type: float
+
+ .. attribute:: ik_mode
+
+ Use one of :ref:`these constants<armatureconstraint-constants-ik-mode>`.
+
+ Additional mode for IK constraint. Currently only used for Distance constraint:
+
+ :type: integer
+
diff --git a/doc/python_api/rst/bge_types/bge.types.BL_ArmatureObject.rst b/doc/python_api/rst/bge_types/bge.types.BL_ArmatureObject.rst
new file mode 100644
index 00000000000..8389affe8a9
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.BL_ArmatureObject.rst
@@ -0,0 +1,34 @@
+BL_ArmatureObject(KX_GameObject)
+================================
+
+.. module:: bge.types
+
+base class --- :class:`KX_GameObject`
+
+.. class:: BL_ArmatureObject(KX_GameObject)
+
+ An armature object.
+
+ .. attribute:: constraints
+
+ The list of armature constraint defined on this armature.
+ Elements of the list can be accessed by index or string.
+ The key format for string access is '<bone_name>:<constraint_name>'.
+
+ :type: list of :class:`BL_ArmatureConstraint`
+
+ .. attribute:: channels
+
+ The list of armature channels.
+ Elements of the list can be accessed by index or name the bone.
+
+ :type: list of :class:`BL_ArmatureChannel`
+
+ .. method:: update()
+
+ Ensures that the armature will be updated on next graphic frame.
+
+ This action is unecessary if a KX_ArmatureActuator with mode run is active
+ or if an action is playing. Use this function in other cases. It must be called
+ on each frame to ensure that the armature is updated continously.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.BL_Shader.rst b/doc/python_api/rst/bge_types/bge.types.BL_Shader.rst
new file mode 100644
index 00000000000..f4f5c0d62ba
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.BL_Shader.rst
@@ -0,0 +1,220 @@
+BL_Shader(PyObjectPlus)
+=======================
+
+.. module:: bge.types
+
+base class --- :class:`PyObjectPlus`
+
+.. class:: BL_Shader(PyObjectPlus)
+
+ BL_Shader GLSL shaders.
+
+ TODO - Description
+
+ .. method:: setUniformfv(name, fList)
+
+ Set a uniform with a list of float values
+
+ :arg name: the uniform name
+ :type name: string
+ :arg fList: a list (2, 3 or 4 elements) of float values
+ :type fList: list[float]
+
+ .. method:: delSource()
+
+ Clear the shader. Use this method before the source is changed with :data:`setSource`.
+
+ .. method:: getFragmentProg()
+
+ Returns the fragment program.
+
+ :return: The fragment program.
+ :rtype: string
+
+ .. method:: getVertexProg()
+
+ Get the vertex program.
+
+ :return: The vertex program.
+ :rtype: string
+
+ .. method:: isValid()
+
+ Check if the shader is valid.
+
+ :return: True if the shader is valid
+ :rtype: boolean
+
+ .. method:: setAttrib(enum)
+
+ Set attribute location. (The parameter is ignored a.t.m. and the value of "tangent" is always used.)
+
+ :arg enum: attribute location value
+ :type enum: integer
+
+ .. method:: setNumberOfPasses( max_pass )
+
+ Set the maximum number of passes. Not used a.t.m.
+
+ :arg max_pass: the maximum number of passes
+ :type max_pass: integer
+
+ .. method:: setSampler(name, index)
+
+ Set uniform texture sample index.
+
+ :arg name: Uniform name
+ :type name: string
+ :arg index: Texture sample index.
+ :type index: integer
+
+ .. method:: setSource(vertexProgram, fragmentProgram)
+
+ Set the vertex and fragment programs
+
+ :arg vertexProgram: Vertex program
+ :type vertexProgram: string
+ :arg fragmentProgram: Fragment program
+ :type fragmentProgram: string
+
+ .. method:: setUniform1f(name, fx)
+
+ Set a uniform with 1 float value.
+
+ :arg name: the uniform name
+ :type name: string
+ :arg fx: Uniform value
+ :type fx: float
+
+ .. method:: setUniform1i(name, ix)
+
+ Set a uniform with an integer value.
+
+ :arg name: the uniform name
+ :type name: string
+ :arg ix: the uniform value
+ :type ix: integer
+
+ .. method:: setUniform2f(name, fx, fy)
+
+ Set a uniform with 2 float values
+
+ :arg name: the uniform name
+ :type name: string
+ :arg fx: first float value
+ :type fx: float
+
+ :arg fy: second float value
+ :type fy: float
+
+ .. method:: setUniform2i(name, ix, iy)
+
+ Set a uniform with 2 integer values
+
+ :arg name: the uniform name
+ :type name: string
+ :arg ix: first integer value
+ :type ix: integer
+ :arg iy: second integer value
+ :type iy: integer
+
+ .. method:: setUniform3f(name, fx, fy, fz)
+
+ Set a uniform with 3 float values.
+
+ :arg name: the uniform name
+ :type name: string
+ :arg fx: first float value
+ :type fx: float
+ :arg fy: second float value
+ :type fy: float
+ :arg fz: third float value
+ :type fz: float
+
+ .. method:: setUniform3i(name, ix, iy, iz)
+
+ Set a uniform with 3 integer values
+
+ :arg name: the uniform name
+ :type name: string
+ :arg ix: first integer value
+ :type ix: integer
+ :arg iy: second integer value
+ :type iy: integer
+ :arg iz: third integer value
+ :type iz: integer
+
+ .. method:: setUniform4f(name, fx, fy, fz, fw)
+
+ Set a uniform with 4 float values.
+
+ :arg name: the uniform name
+ :type name: string
+ :arg fx: first float value
+ :type fx: float
+ :arg fy: second float value
+ :type fy: float
+ :arg fz: third float value
+ :type fz: float
+ :arg fw: fourth float value
+ :type fw: float
+
+ .. method:: setUniform4i(name, ix, iy, iz, iw)
+
+ Set a uniform with 4 integer values
+
+ :arg name: the uniform name
+ :type name: string
+ :arg ix: first integer value
+ :type ix: integer
+ :arg iy: second integer value
+ :type iy: integer
+ :arg iz: third integer value
+ :type iz: integer
+ :arg iw: fourth integer value
+ :type iw: integer
+
+ .. method:: setUniformDef(name, type)
+
+ Define a new uniform
+
+ :arg name: the uniform name
+ :type name: string
+ :arg type: uniform type
+ :type type: UNI_NONE, UNI_INT, UNI_FLOAT, UNI_INT2, UNI_FLOAT2, UNI_INT3, UNI_FLOAT3, UNI_INT4, UNI_FLOAT4, UNI_MAT3, UNI_MAT4, UNI_MAX
+
+ .. method:: setUniformMatrix3(name, mat, transpose)
+
+ Set a uniform with a 3x3 matrix value
+
+ :arg name: the uniform name
+ :type name: string
+ :arg mat: A 3x3 matrix [[f, f, f], [f, f, f], [f, f, f]]
+ :type mat: 3x3 matrix
+ :arg transpose: set to True to transpose the matrix
+ :type transpose: boolean
+
+ .. method:: setUniformMatrix4(name, mat, transpose)
+
+ Set a uniform with a 4x4 matrix value
+
+ :arg name: the uniform name
+ :type name: string
+ :arg mat: A 4x4 matrix [[f, f, f, f], [f, f, f, f], [f, f, f, f], [f, f, f, f]]
+ :type mat: 4x4 matrix
+ :arg transpose: set to True to transpose the matrix
+ :type transpose: boolean
+
+ .. method:: setUniformiv(name, iList)
+
+ Set a uniform with a list of integer values
+
+ :arg name: the uniform name
+ :type name: string
+ :arg iList: a list (2, 3 or 4 elements) of integer values
+ :type iList: list[integer]
+
+ .. method:: validate()
+
+ Validate the shader object.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.BL_ShapeActionActuator.rst b/doc/python_api/rst/bge_types/bge.types.BL_ShapeActionActuator.rst
new file mode 100644
index 00000000000..d08a761ed95
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.BL_ShapeActionActuator.rst
@@ -0,0 +1,72 @@
+BL_ShapeActionActuator(SCA_IActuator)
+=====================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: BL_ShapeActionActuator(SCA_IActuator)
+
+ ShapeAction Actuators apply an shape action to an mesh object.
+
+ .. attribute:: action
+
+ The name of the action to set as the current shape action.
+
+ :type: string
+
+ .. attribute:: frameStart
+
+ Specifies the starting frame of the shape animation.
+
+ :type: float
+
+ .. attribute:: frameEnd
+
+ Specifies the ending frame of the shape animation.
+
+ :type: float
+
+ .. attribute:: blendIn
+
+ Specifies the number of frames of animation to generate when making transitions between actions.
+
+ :type: float
+
+ .. attribute:: priority
+
+ Sets the priority of this actuator. Actuators will lower priority numbers will override actuators with higher numbers.
+
+ :type: integer
+
+ .. attribute:: frame
+
+ Sets the current frame for the animation.
+
+ :type: float
+
+ .. attribute:: propName
+
+ Sets the property to be used in FromProp playback mode.
+
+ :type: string
+
+ .. attribute:: blendTime
+
+ Sets the internal frame timer. This property must be in the range from 0.0 to blendin.
+
+ :type: float
+
+ .. attribute:: mode
+
+ The operation mode of the actuator. Can be one of :ref:`these constants<shape-action-actuator>`.
+
+ :type: integer
+
+ .. attribute:: framePropName
+
+ The name of the property that is set to the current frame number.
+
+ :type: string
+
+
diff --git a/doc/python_api/rst/bge_types/bge.types.CListValue.rst b/doc/python_api/rst/bge_types/bge.types.CListValue.rst
new file mode 100644
index 00000000000..ca4cdc44bf5
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.CListValue.rst
@@ -0,0 +1,72 @@
+CListValue(CPropValue)
+======================
+
+.. module:: bge.types
+
+base class --- :class:`CPropValue`
+
+.. class:: CListValue(CPropValue)
+
+ This is a list like object used in the game engine internally that behaves similar to a python list in most ways.
+
+ As well as the normal index lookup (``val= clist[i]``), CListValue supports string lookups (``val= scene.objects["Cube"]``)
+
+ Other operations such as ``len(clist)``, ``list(clist)``, ``clist[0:10]`` are also supported.
+
+ .. method:: append(val)
+
+ Add an item to the list (like pythons append)
+
+ .. warning::
+
+ Appending values to the list can cause crashes when the list is used internally by the game engine.
+
+ .. method:: count(val)
+
+ Count the number of instances of a value in the list.
+
+ :return: number of instances
+ :rtype: integer
+
+ .. method:: index(val)
+
+ Return the index of a value in the list.
+
+ :return: The index of the value in the list.
+ :rtype: integer
+
+ .. method:: reverse()
+
+ Reverse the order of the list.
+
+ .. method:: get(key, default=None)
+
+ Return the value matching key, or the default value if its not found.
+
+ :return: The key value or a default.
+
+ .. method:: from_id(id)
+
+ This is a funtion especially for the game engine to return a value with a spesific id.
+
+ Since object names are not always unique, the id of an object can be used to get an object from the CValueList.
+
+ Example:
+
+ .. code-block:: python
+
+ myObID=id(gameObject)
+ ob= scene.objects.from_id(myObID)
+
+ Where ``myObID`` is an int or long from the id function.
+
+ This has the advantage that you can store the id in places you could not store a gameObject.
+
+ .. warning::
+
+ The id is derived from a memory location and will be different each time the game engine starts.
+
+ .. warning::
+
+ The id can't be stored as an integer in game object properties, as those only have a limited range that the id may not be contained in. Instead an id can be stored as a string game property and converted back to an integer for use in from_id lookups.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.CPropValue.rst b/doc/python_api/rst/bge_types/bge.types.CPropValue.rst
new file mode 100644
index 00000000000..7be28c1e006
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.CPropValue.rst
@@ -0,0 +1,11 @@
+CPropValue(CValue)
+==================
+
+.. module:: bge.types
+
+base class --- :class:`CValue`
+
+.. class:: CPropValue(CValue)
+
+ This class has no python functions
+
diff --git a/doc/python_api/rst/bge_types/bge.types.CValue.rst b/doc/python_api/rst/bge_types/bge.types.CValue.rst
new file mode 100644
index 00000000000..52906de5576
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.CValue.rst
@@ -0,0 +1,17 @@
+CValue(PyObjectPlus)
+====================
+
+.. module:: bge.types
+
+base class --- :class:`PyObjectPlus`
+
+.. class:: CValue(PyObjectPlus)
+
+ This class is a basis for other classes.
+
+ .. attribute:: name
+
+ The name of this CValue derived object (read-only).
+
+ :type: string
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_ArmatureSensor.rst b/doc/python_api/rst/bge_types/bge.types.KX_ArmatureSensor.rst
new file mode 100644
index 00000000000..a7123eb5c9d
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_ArmatureSensor.rst
@@ -0,0 +1,36 @@
+KX_ArmatureSensor(SCA_ISensor)
+==============================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_ISensor`
+
+.. class:: KX_ArmatureSensor(SCA_ISensor)
+
+ Armature sensor detect conditions on armatures.
+
+ .. attribute:: type
+
+ The type of measurement that the sensor make when it is active.
+
+ Can be one of :ref:`these constants <armaturesensor-type>`
+
+ :type: integer.
+
+ .. attribute:: constraint
+
+ The constraint object this sensor is watching.
+
+ :type: :class:`BL_ArmatureConstraint`
+
+ .. attribute:: value
+
+ The threshold used in the comparison with the constraint error
+ The linear error is only updated on CopyPose/Distance IK constraint with iTaSC solver
+ The rotation error is only updated on CopyPose+rotation IK constraint with iTaSC solver
+ The linear error on CopyPose is always >= 0: it is the norm of the distance between the target and the bone
+ The rotation error on CopyPose is always >= 0: it is the norm of the equivalent rotation vector between the bone and the target orientations
+ The linear error on Distance can be positive if the distance between the bone and the target is greater than the desired distance, and negative if the distance is smaller.
+
+ :type: float
+
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
new file mode 100644
index 00000000000..0dfc7a10d13
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_BlenderMaterial.rst
@@ -0,0 +1,77 @@
+KX_BlenderMaterial(PyObjectPlus)
+================================
+
+.. module:: bge.types
+
+base class --- :class:`PyObjectPlus`
+
+.. class:: KX_BlenderMaterial(PyObjectPlus)
+
+ KX_BlenderMaterial
+
+ .. attribute:: shader
+
+ The materials shader.
+
+ :type: :class:`BL_Shader`
+
+ .. attribute:: blending
+
+ Ints used for pixel blending, (src, dst), matching the setBlending method.
+
+ :type: (integer, integer)
+
+ .. attribute:: material_index
+
+ The material's index.
+
+ :type: integer
+
+ .. method:: getShader()
+
+ Returns the material's shader.
+
+ :return: the material's shader
+ :rtype: :class:`BL_Shader`
+
+ .. 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
+
+ .. method:: getMaterialIndex()
+
+ Returns the material's index.
+
+ :return: the material's index
+ :rtype: integer
+
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
new file mode 100644
index 00000000000..baf60ec0c97
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_Camera.rst
@@ -0,0 +1,284 @@
+KX_Camera(KX_GameObject)
+========================
+
+.. module:: bge.types
+
+base class --- :class:`KX_GameObject`
+
+.. class:: KX_Camera(KX_GameObject)
+
+ A Camera object.
+
+ .. data:: INSIDE
+
+ See :data:`sphereInsideFrustum` and :data:`boxInsideFrustum`
+
+ .. data:: INTERSECT
+
+ See :data:`sphereInsideFrustum` and :data:`boxInsideFrustum`
+
+ .. data:: OUTSIDE
+
+ See :data:`sphereInsideFrustum` and :data:`boxInsideFrustum`
+
+ .. attribute:: lens
+
+ The camera's lens value.
+
+ :type: float
+
+ .. attribute:: ortho_scale
+
+ The camera's view scale when in orthographic mode.
+
+ :type: float
+
+ .. attribute:: near
+
+ The camera's near clip distance.
+
+ :type: float
+
+ .. attribute:: far
+
+ The camera's far clip distance.
+
+ :type: float
+
+ .. attribute:: perspective
+
+ True if this camera has a perspective transform, False for an orthographic projection.
+
+ :type: boolean
+
+ .. attribute:: frustum_culling
+
+ True if this camera is frustum culling.
+
+ :type: boolean
+
+ .. attribute:: projection_matrix
+
+ This camera's 4x4 projection matrix.
+
+ .. note::
+
+ This is the identity matrix prior to rendering the first frame (any Python done on frame 1).
+
+ :type: 4x4 Matrix [[float]]
+
+ .. attribute:: modelview_matrix
+
+ This camera's 4x4 model view matrix. (read-only).
+
+ :type: 4x4 Matrix [[float]]
+
+ .. note::
+
+ This matrix is regenerated every frame from the camera's position and orientation. Also, this is the identity matrix prior to rendering the first frame (any Python done on frame 1).
+
+ .. attribute:: camera_to_world
+
+ This camera's camera to world transform. (read-only).
+
+ :type: 4x4 Matrix [[float]]
+
+ .. note::
+
+ This matrix is regenerated every frame from the camera's position and orientation.
+
+ .. attribute:: world_to_camera
+
+ This camera's world to camera transform. (read-only).
+
+ :type: 4x4 Matrix [[float]]
+
+ .. note::
+
+ Regenerated every frame from the camera's position and orientation.
+
+ .. note::
+
+ This is camera_to_world inverted.
+
+ .. attribute:: useViewport
+
+ True when the camera is used as a viewport, set True to enable a viewport for this camera.
+
+ :type: boolean
+
+ .. method:: sphereInsideFrustum(centre, radius)
+
+ Tests the given sphere against the view frustum.
+
+ :arg centre: The centre of the sphere (in world coordinates.)
+ :type centre: list [x, y, z]
+ :arg radius: the radius of the sphere
+ :type radius: float
+ :return: :data:`~bge.types.KX_Camera.INSIDE`, :data:`~bge.types.KX_Camera.OUTSIDE` or :data:`~bge.types.KX_Camera.INTERSECT`
+ :rtype: integer
+
+ .. note::
+
+ When the camera is first initialized the result will be invalid because the projection matrix has not been set.
+
+ .. code-block:: python
+
+ from bge import logic
+ cont = logic.getCurrentController()
+ cam = cont.owner
+
+ # A sphere of radius 4.0 located at [x, y, z] = [1.0, 1.0, 1.0]
+ if (cam.sphereInsideFrustum([1.0, 1.0, 1.0], 4) != cam.OUTSIDE):
+ # Sphere is inside frustum !
+ # Do something useful !
+ else:
+ # Sphere is outside frustum
+
+ .. method:: boxInsideFrustum(box)
+
+ Tests the given box against the view frustum.
+
+ :arg box: Eight (8) corner points of the box (in world coordinates.)
+ :type box: list of lists
+ :return: :data:`~bge.types.KX_Camera.INSIDE`, :data:`~bge.types.KX_Camera.OUTSIDE` or :data:`~bge.types.KX_Camera.INTERSECT`
+
+ .. note::
+
+ When the camera is first initialized the result will be invalid because the projection matrix has not been set.
+
+ .. code-block:: python
+
+ from bge import logic
+ cont = logic.getCurrentController()
+ cam = cont.owner
+
+ # Box to test...
+ box = []
+ box.append([-1.0, -1.0, -1.0])
+ box.append([-1.0, -1.0, 1.0])
+ box.append([-1.0, 1.0, -1.0])
+ box.append([-1.0, 1.0, 1.0])
+ box.append([ 1.0, -1.0, -1.0])
+ box.append([ 1.0, -1.0, 1.0])
+ box.append([ 1.0, 1.0, -1.0])
+ box.append([ 1.0, 1.0, 1.0])
+
+ if (cam.boxInsideFrustum(box) != cam.OUTSIDE):
+ # Box is inside/intersects frustum !
+ # Do something useful !
+ else:
+ # Box is outside the frustum !
+
+ .. method:: pointInsideFrustum(point)
+
+ Tests the given point against the view frustum.
+
+ :arg point: The point to test (in world coordinates.)
+ :type point: 3D Vector
+ :return: True if the given point is inside this camera's viewing frustum.
+ :rtype: boolean
+
+ .. note::
+
+ When the camera is first initialized the result will be invalid because the projection matrix has not been set.
+
+ .. code-block:: python
+
+ from bge import logic
+ cont = logic.getCurrentController()
+ cam = cont.owner
+
+ # Test point [0.0, 0.0, 0.0]
+ if (cam.pointInsideFrustum([0.0, 0.0, 0.0])):
+ # Point is inside frustum !
+ # Do something useful !
+ else:
+ # Box is outside the frustum !
+
+ .. method:: getCameraToWorld()
+
+ Returns the camera-to-world transform.
+
+ :return: the camera-to-world transform matrix.
+ :rtype: matrix (4x4 list)
+
+ .. method:: getWorldToCamera()
+
+ Returns the world-to-camera transform.
+
+ This returns the inverse matrix of getCameraToWorld().
+
+ :return: the world-to-camera transform matrix.
+ :rtype: matrix (4x4 list)
+
+ .. method:: setOnTop()
+
+ Set this cameras viewport ontop of all other viewport.
+
+ .. method:: setViewport(left, bottom, right, top)
+
+ Sets the region of this viewport on the screen in pixels.
+
+ Use :data:`bge.render.getWindowHeight` and :data:`bge.render.getWindowWidth` to calculate values relative to the entire display.
+
+ :arg left: left pixel coordinate of this viewport
+ :type left: integer
+ :arg bottom: bottom pixel coordinate of this viewport
+ :type bottom: integer
+ :arg right: right pixel coordinate of this viewport
+ :type right: integer
+ :arg top: top pixel coordinate of this viewport
+ :type top: integer
+
+ .. method:: getScreenPosition(object)
+
+ Gets the position of an object projected on screen space.
+
+ .. code-block:: python
+
+ # For an object in the middle of the screen, coord = [0.5, 0.5]
+ coord = camera.getScreenPosition(object)
+
+ :arg object: object name or list [x, y, z]
+ :type object: :class:`KX_GameObject` or 3D Vector
+ :return: the object's position in screen coordinates.
+ :rtype: list [x, y]
+
+ .. method:: getScreenVect(x, y)
+
+ Gets the vector from the camera position in the screen coordinate direction.
+
+ :arg x: X Axis
+ :type x: float
+ :arg y: Y Axis
+ :type y: float
+ :rtype: 3D Vector
+ :return: The vector from screen coordinate.
+
+ .. code-block:: python
+
+ # Gets the vector of the camera front direction:
+ m_vect = camera.getScreenVect(0.5, 0.5)
+
+ .. method:: getScreenRay(x, y, dist=inf, property=None)
+
+ Look towards a screen coordinate (x, y) and find first object hit within dist that matches prop.
+ The ray is similar to KX_GameObject->rayCastTo.
+
+ :arg x: X Axis
+ :type x: float
+ :arg y: Y Axis
+ :type y: float
+ :arg dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to other
+ :type dist: float
+ :arg property: property name that object must have; can be omitted => detect any object
+ :type property: string
+ :rtype: :class:`KX_GameObject`
+ :return: the first object hit or None if no object or object does not match prop
+
+ .. code-block:: python
+
+ # Gets an object with a property "wall" in front of the camera within a distance of 100:
+ target = camera.getScreenRay(0.5, 0.5, 100, "wall")
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_CameraActuator.rst b/doc/python_api/rst/bge_types/bge.types.KX_CameraActuator.rst
new file mode 100644
index 00000000000..bc5efed4b08
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_CameraActuator.rst
@@ -0,0 +1,47 @@
+KX_CameraActuator(SCA_IActuator)
+================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: KX_CameraActuator(SCA_IActuator)
+
+ Applies changes to a camera.
+
+ .. attribute:: damping
+
+ strength of of the camera following movement.
+
+ :type: float
+
+ .. attribute:: axis
+
+ The camera axis (0, 1, 2) for positive ``XYZ``, (3, 4, 5) for negative ``XYZ``.
+
+ :type: int
+
+ .. attribute:: min
+
+ minimum distance to the target object maintained by the actuator.
+
+ :type: float
+
+ .. attribute:: max
+
+ maximum distance to stay from the target object.
+
+ :type: float
+
+ .. attribute:: height
+
+ height to stay above the target object.
+
+ :type: float
+
+ .. attribute:: object
+
+ the object this actuator tracks.
+
+ :type: :class:`KX_GameObject` or None
+
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
new file mode 100644
index 00000000000..32e5c3eaad8
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_CharacterWrapper.rst
@@ -0,0 +1,45 @@
+KX_CharacterWrapper(PyObjectPlus)
+=================================
+
+.. module:: bge.types
+
+base class --- :class:`PyObjectPlus`
+
+.. class:: KX_CharacterWrapper(PyObjectPlus)
+
+ A wrapper to expose character physics options.
+
+ .. attribute:: onGround
+
+ Whether or not the character is on the ground. (read-only)
+
+ :type: boolean
+
+ .. attribute:: gravity
+
+ The gravity value used for the character.
+
+ :type: float
+
+ .. attribute:: maxJumps
+
+ The maximum number of jumps a character can perform before having to touch the ground. By default this is set to 1. 2 allows for a double jump, etc.
+
+ :type: int
+
+ .. attribute:: jumpCount
+
+ The current jump count. This can be used to have different logic for a single jump versus a double jump. For example, a different animation for the second jump.
+
+ :type: int
+
+ .. attribute:: walkDirection
+
+ 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]
+
+ .. method:: jump()
+
+ The character jumps based on it's jump speed.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_ConstraintActuator.rst b/doc/python_api/rst/bge_types/bge.types.KX_ConstraintActuator.rst
new file mode 100644
index 00000000000..498990449fe
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_ConstraintActuator.rst
@@ -0,0 +1,78 @@
+KX_ConstraintActuator(SCA_IActuator)
+====================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: KX_ConstraintActuator(SCA_IActuator)
+
+ A constraint actuator limits the position, rotation, distance or orientation of an object.
+
+ .. attribute:: damp
+
+ Time constant of the constraint expressed in frame (not use by Force field constraint).
+
+ :type: integer
+
+ .. attribute:: rotDamp
+
+ Time constant for the rotation expressed in frame (only for the distance constraint), 0 = use damp for rotation as well.
+
+ :type: integer
+
+ .. attribute:: direction
+
+ The reference direction in world coordinate for the orientation constraint.
+
+ :type: 3-tuple of float: (x, y, z)
+
+ .. attribute:: option
+
+ Binary combination of :ref:`these constants <constraint-actuator-option>`
+
+ :type: integer
+
+ .. attribute:: time
+
+ activation time of the actuator. The actuator disables itself after this many frame. If set to 0, the actuator is not limited in time.
+
+ :type: integer
+
+ .. attribute:: propName
+
+ the name of the property or material for the ray detection of the distance constraint.
+
+ :type: string
+
+ .. attribute:: min
+
+ The lower bound of the constraint. For the rotation and orientation constraint, it represents radiant.
+
+ :type: float
+
+ .. attribute:: distance
+
+ the target distance of the distance constraint.
+
+ :type: float
+
+ .. attribute:: max
+
+ the upper bound of the constraint. For rotation and orientation constraints, it represents radiant.
+
+ :type: float
+
+ .. attribute:: rayLength
+
+ the length of the ray of the distance constraint.
+
+ :type: float
+
+ .. attribute:: limit
+
+ type of constraint. Use one of the :ref:`these constants <constraint-actuator-limit>`
+
+ :type: integer.
+
+
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
new file mode 100644
index 00000000000..c26675147ac
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_ConstraintWrapper.rst
@@ -0,0 +1,18 @@
+KX_ConstraintWrapper(PyObjectPlus)
+==================================
+
+.. module:: bge.types
+
+base class --- :class:`PyObjectPlus`
+
+.. class:: KX_ConstraintWrapper(PyObjectPlus)
+
+ KX_ConstraintWrapper
+
+ .. method:: getConstraintId(val)
+
+ Returns the contraint's ID
+
+ :return: the constraint's ID
+ :rtype: integer
+
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
new file mode 100644
index 00000000000..1961f5e3e92
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_FontObject.rst
@@ -0,0 +1,12 @@
+KX_FontObject(KX_GameObject)
+============================
+
+.. module:: bge.types
+
+base class --- :class:`KX_GameObject`
+
+.. class:: KX_FontObject(KX_GameObject)
+
+ TODO.
+
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_GameActuator.rst b/doc/python_api/rst/bge_types/bge.types.KX_GameActuator.rst
new file mode 100644
index 00000000000..54702c5318d
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_GameActuator.rst
@@ -0,0 +1,23 @@
+KX_GameActuator(SCA_IActuator)
+==============================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: KX_GameActuator(SCA_IActuator)
+
+ The game actuator loads a new .blend file, restarts the current .blend file or quits the game.
+
+ .. attribute:: fileName
+
+ the new .blend file to load.
+
+ :type: string
+
+ .. attribute:: mode
+
+ The mode of this actuator. Can be on of :ref:`these constants <game-actuator>`
+
+ :type: Int
+
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
new file mode 100644
index 00000000000..a9c91735f91
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
@@ -0,0 +1,839 @@
+KX_GameObject(SCA_IObject)
+==========================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IObject`
+
+.. class:: KX_GameObject(SCA_IObject)
+
+ All game objects are derived from this class.
+
+ Properties assigned to game objects are accessible as attributes of this class.
+
+ .. note::
+
+ Calling ANY method or attribute on an object that has been removed from a scene will raise a SystemError,
+ if an object may have been removed since last accessing it use the :data:`invalid` attribute to check.
+
+ KX_GameObject can be subclassed to extend functionality. For example:
+
+ .. code-block:: python
+
+ import bge
+
+ class CustomGameObject(bge.types.KX_GameObject):
+ RATE = 0.05
+
+ def __init__(self, old_owner):
+ # "old_owner" can just be ignored. At this point, "self" is
+ # already the object in the scene, and "old_owner" has been
+ # destroyed.
+
+ # New attributes can be defined - but we could also use a game
+ # property, like "self['rate']".
+ self.rate = CustomGameObject.RATE
+
+ def update(self):
+ self.worldPosition.z += self.rate
+
+ # switch direction
+ if self.worldPosition.z > 1.0:
+ self.rate = -CustomGameObject.RATE
+ elif self.worldPosition.z < 0.0:
+ self.rate = CustomGameObject.RATE
+
+ # Called first
+ def mutate(cont):
+ old_object = cont.owner
+ mutated_object = CustomGameObject(cont.owner)
+
+ # After calling the constructor above, references to the old object
+ # should not be used.
+ assert(old_object is not mutated_object)
+ assert(old_object.invalid)
+ assert(mutated_object is cont.owner)
+
+ # Called later - note we are now working with the mutated object.
+ def update(cont):
+ cont.owner.update()
+
+ When subclassing objects other than empties and meshes, the specific type
+ should be used - e.g. inherit from :class:`BL_ArmatureObject` when the object
+ to mutate is an armature.
+
+ .. attribute:: name
+
+ The object's name. (read-only).
+
+ :type: string
+
+ .. attribute:: mass
+
+ The object's mass
+
+ :type: float
+
+ .. note::
+
+ The object must have a physics controller for the mass to be applied, otherwise the mass value will be returned as 0.0.
+
+ .. attribute:: linVelocityMin
+
+ Enforces the object keeps moving at a minimum velocity.
+
+ :type: float
+
+ .. note::
+
+ Applies to dynamic and rigid body objects only.
+
+ .. note::
+
+ A value of 0.0 disables this option.
+
+ .. note::
+
+ While objects are stationary the minimum velocity will not be applied.
+
+ .. attribute:: linVelocityMax
+
+ Clamp the maximum linear velocity to prevent objects moving beyond a set speed.
+
+ :type: float
+
+ .. note::
+
+ Applies to dynamic and rigid body objects only.
+
+ .. note::
+
+ A value of 0.0 disables this option (rather then setting it stationary).
+
+ .. attribute:: localInertia
+
+ the object's inertia vector in local coordinates. Read only.
+
+ :type: list [ix, iy, iz]
+
+ .. attribute:: parent
+
+ The object's parent object. (read-only).
+
+ :type: :class:`KX_GameObject` or None
+
+ .. attribute:: groupMembers
+
+ Returns the list of group members if the object is a group object, 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.
+
+ :type: :class:`KX_GameObject` or None
+
+ .. attribute:: scene
+
+ The object's scene. (read-only).
+
+ :type: :class:`KX_Scene` or None
+
+ .. attribute:: visible
+
+ visibility flag.
+
+ :type: boolean
+
+ .. note::
+
+ Game logic will still run for invisible objects.
+
+ .. attribute:: color
+
+ The object color of the object. [r, g, b, a]
+
+ :type: :class:`mathutils.Vector`
+
+ .. attribute:: occlusion
+
+ occlusion capability flag.
+
+ :type: boolean
+
+ .. attribute:: position
+
+ The object's position. [x, y, z] On write: local position, on read: world position
+
+ .. deprecated:: use :data:`localPosition` and :data:`worldPosition`.
+
+ :type: :class:`mathutils.Vector`
+
+ .. attribute:: orientation
+
+ The object's orientation. 3x3 Matrix. You can also write a Quaternion or Euler vector. On write: local orientation, on read: world orientation
+
+ .. deprecated:: use :data:`localOrientation` and :data:`worldOrientation`.
+
+ :type: :class:`mathutils.Matrix`
+
+ .. attribute:: scaling
+
+ The object's scaling factor. [sx, sy, sz] On write: local scaling, on read: world scaling
+
+ .. deprecated:: use :data:`localScale` and :data:`worldScale`.
+
+ :type: :class:`mathutils.Vector`
+
+ .. attribute:: localOrientation
+
+ The object's local orientation. 3x3 Matrix. You can also write a Quaternion or Euler vector.
+
+ :type: :class:`mathutils.Matrix`
+
+ .. attribute:: worldOrientation
+
+ The object's world orientation. 3x3 Matrix.
+
+ :type: :class:`mathutils.Matrix`
+
+ .. attribute:: localScale
+
+ The object's local scaling factor. [sx, sy, sz]
+
+ :type: :class:`mathutils.Vector`
+
+ .. attribute:: worldScale
+
+ The object's world scaling factor. [sx, sy, sz]
+
+ :type: :class:`mathutils.Vector`
+
+ .. attribute:: localPosition
+
+ The object's local position. [x, y, z]
+
+ :type: :class:`mathutils.Vector`
+
+ .. attribute:: worldPosition
+
+ The object's world position. [x, y, z]
+
+ :type: :class:`mathutils.Vector`
+
+ .. attribute:: localTransform
+
+ The object's local space transform matrix. 4x4 Matrix.
+
+ :type: :class:`mathutils.Matrix`
+
+ .. attribute:: worldTransform
+
+ The object's world space transform matrix. 4x4 Matrix.
+
+ :type: :class:`mathutils.Matrix`
+
+ .. attribute:: localLinearVelocity
+
+ The object's local linear velocity. [x, y, z]
+
+ :type: :class:`mathutils.Vector`
+
+ .. attribute:: worldLinearVelocity
+
+ The object's world linear velocity. [x, y, z]
+
+ :type: :class:`mathutils.Vector`
+
+ .. attribute:: localAngularVelocity
+
+ The object's local angular velocity. [x, y, z]
+
+ :type: :class:`mathutils.Vector`
+
+ .. attribute:: worldAngularVelocity
+
+ The object's world angular velocity. [x, y, z]
+
+ :type: :class:`mathutils.Vector`
+
+ .. attribute:: timeOffset
+
+ adjust the slowparent delay at runtime.
+
+ :type: float
+
+ .. attribute:: state
+
+ the game object's state bitmask, using the first 30 bits, one bit must always be set.
+
+ :type: int
+
+ .. attribute:: meshes
+
+ a list meshes for this object.
+
+ :type: list of :class:`KX_MeshProxy`
+
+ .. note::
+
+ Most objects use only 1 mesh.
+
+ .. note::
+
+ Changes to this list will not update the KX_GameObject.
+
+ .. attribute:: sensors
+
+ a sequence of :class:`SCA_ISensor` objects with string/index lookups and iterator support.
+
+ :type: list
+
+ .. note::
+
+ This attribute is experemental and may be removed (but probably wont be).
+
+ .. note::
+
+ Changes to this list will not update the KX_GameObject.
+
+ .. attribute:: controllers
+
+ a sequence of :class:`SCA_IController` objects with string/index lookups and iterator support.
+
+ :type: list of :class:`SCA_ISensor`
+
+ .. note::
+
+ This attribute is experemental and may be removed (but probably wont be).
+
+ .. note::
+
+ Changes to this list will not update the KX_GameObject.
+
+ .. attribute:: actuators
+
+ a list of :class:`SCA_IActuator` with string/index lookups and iterator support.
+
+ :type: list
+
+ .. note::
+
+ This attribute is experemental and may be removed (but probably wont be).
+
+ .. note::
+
+ Changes to this list will not update the KX_GameObject.
+
+ .. attribute:: attrDict
+
+ get the objects internal python attribute dictionary for direct (faster) access.
+
+ :type: dict
+
+ .. attribute:: children
+
+ direct children of this object, (read-only).
+
+ :type: :class:`CListValue` of :class:`KX_GameObject`'s
+
+ .. attribute:: childrenRecursive
+
+ all children of this object including childrens children, (read-only).
+
+ :type: :class:`CListValue` of :class:`KX_GameObject`'s
+
+ .. attribute:: life
+
+ The number of seconds until the object ends, assumes 50fps.
+ (when added with an add object actuator), (read-only).
+
+ :type: float
+
+ .. method:: endObject()
+
+ Delete this object, can be used in place of the EndObject Actuator.
+
+ The actual removal of the object from the scene is delayed.
+
+ .. method:: replaceMesh(mesh, useDisplayMesh=True, usePhysicsMesh=False)
+
+ Replace the mesh of this object with a new mesh. This works the same was as the actuator.
+
+ :arg mesh: mesh to replace or the meshes name.
+ :type mesh: :class:`MeshProxy` or string
+ :arg useDisplayMesh: when enabled the display mesh will be replaced (optional argument).
+ :type useDisplayMesh: boolean
+ :arg usePhysicsMesh: when enabled the physics mesh will be replaced (optional argument).
+ :type usePhysicsMesh: boolean
+
+ .. method:: setVisible(visible, recursive)
+
+ Sets the game object's visible flag.
+
+ :arg visible: the visible state to set.
+ :type visible: boolean
+ :arg recursive: optional argument to set all childrens visibility flag too.
+ :type recursive: boolean
+
+ .. method:: setOcclusion(occlusion, recursive)
+
+ Sets the game object's occlusion capability.
+
+ :arg occlusion: the state to set the occlusion to.
+ :type occlusion: boolean
+ :arg recursive: optional argument to set all childrens occlusion flag too.
+ :type recursive: boolean
+
+ .. method:: alignAxisToVect(vect, axis=2, factor=1.0)
+
+ Aligns any of the game object's axis along the given vector.
+
+
+ :arg vect: a vector to align the axis.
+ :type vect: 3D vector
+ :arg axis: The axis you want to align
+
+ * 0: X axis
+ * 1: Y axis
+ * 2: Z axis
+
+ :type axis: integer
+ :arg factor: Only rotate a feaction of the distance to the target vector (0.0 - 1.0)
+ :type factor: float
+
+ .. method:: getAxisVect(vect)
+
+ Returns the axis vector rotates by the objects worldspace orientation.
+ This is the equivalent of multiplying the vector by the orientation matrix.
+
+ :arg vect: a vector to align the axis.
+ :type vect: 3D Vector
+ :return: The vector in relation to the objects rotation.
+ :rtype: 3d vector.
+
+ .. method:: applyMovement(movement, local=False)
+
+ Sets the game object's movement.
+
+ :arg movement: movement vector.
+ :type movement: 3D Vector
+ :arg local:
+ * False: you get the "global" movement ie: relative to world orientation.
+ * True: you get the "local" movement ie: relative to object orientation.
+ :arg local: boolean
+
+ .. method:: applyRotation(rotation, local=False)
+
+ Sets the game object's rotation.
+
+ :arg rotation: rotation vector.
+ :type rotation: 3D Vector
+ :arg local:
+ * False: you get the "global" rotation ie: relative to world orientation.
+ * True: you get the "local" rotation ie: relative to object orientation.
+ :arg local: boolean
+
+ .. method:: applyForce(force, local=False)
+
+ Sets the game object's force.
+
+ This requires a dynamic object.
+
+ :arg force: force vector.
+ :type force: 3D Vector
+ :arg local:
+ * False: you get the "global" force ie: relative to world orientation.
+ * True: you get the "local" force ie: relative to object orientation.
+ :type local: boolean
+
+ .. method:: applyTorque(torque, local=False)
+
+ Sets the game object's torque.
+
+ This requires a dynamic object.
+
+ :arg torque: torque vector.
+ :type torque: 3D Vector
+ :arg local:
+ * False: you get the "global" torque ie: relative to world orientation.
+ * True: you get the "local" torque ie: relative to object orientation.
+ :type local: boolean
+
+ .. method:: getLinearVelocity(local=False)
+
+ Gets the game object's linear velocity.
+
+ This method returns the game object's velocity through it's centre of mass, ie no angular velocity component.
+
+ :arg local:
+ * False: you get the "global" velocity ie: relative to world orientation.
+ * 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]
+
+ .. method:: setLinearVelocity(velocity, local=False)
+
+ Sets the game object's linear velocity.
+
+ This method sets game object's velocity through it's centre of mass,
+ ie no angular velocity component.
+
+ This requires a dynamic object.
+
+ :arg velocity: linear velocity vector.
+ :type velocity: 3D Vector
+ :arg local:
+ * False: you get the "global" velocity ie: relative to world orientation.
+ * True: you get the "local" velocity ie: relative to object orientation.
+ :type local: boolean
+
+ .. method:: getAngularVelocity(local=False)
+
+ Gets the game object's angular velocity.
+
+ :arg local:
+ * False: you get the "global" velocity ie: relative to world orientation.
+ * 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]
+
+ .. method:: setAngularVelocity(velocity, local=False)
+
+ Sets the game object's angular velocity.
+
+ This requires a dynamic object.
+
+ :arg velocity: angular velocity vector.
+ :type velocity: boolean
+ :arg local:
+ * False: you get the "global" velocity ie: relative to world orientation.
+ * True: you get the "local" velocity ie: relative to object orientation.
+
+ .. method:: getVelocity(point=(0, 0, 0))
+
+ Gets the game object's velocity at the specified point.
+
+ Gets the game object's velocity at the specified point, including angular
+ components.
+
+ :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]
+
+ .. method:: getReactionForce()
+
+ Gets the game object's reaction force.
+
+ The reaction force is the force applied to this object over the last simulation timestep.
+ This also includes impulses, eg from collisions.
+
+ :return: the reaction force of this object.
+ :rtype: list [fx, fy, fz]
+
+ .. note::
+
+ This is not implimented at the moment.
+
+ .. method:: applyImpulse(point, impulse)
+
+ Applies an impulse to the game object.
+
+ This will apply the specified impulse to the game object at the specified point.
+ If point != position, applyImpulse will also change the object's angular momentum.
+ Otherwise, only linear momentum will change.
+
+ :arg point: the point to apply the impulse to (in world coordinates)
+ :type point: the point to apply the impulse to (in world coordinates)
+
+ .. method:: suspendDynamics()
+
+ Suspends physics for this object.
+
+ .. method:: restoreDynamics()
+
+ Resumes physics for this object.
+
+ .. note::
+
+ The objects linear velocity will be applied from when the dynamics were suspended.
+
+ .. method:: enableRigidBody()
+
+ Enables rigid body physics for this object.
+
+ Rigid body physics allows the object to roll on collisions.
+
+ .. method:: disableRigidBody()
+
+ Disables rigid body physics for this object.
+
+ .. method:: setParent(parent, compound=True, ghost=True)
+
+ Sets this object's parent.
+ Control the shape status with the optional compound and ghost parameters:
+
+ In that case you can control if it should be ghost or not:
+
+ :arg parent: new parent object.
+ :type parent: :class:`KX_GameObject`
+ :arg compound: whether the shape should be added to the parent compound shape.
+
+ * True: the object shape should be added to the parent compound shape.
+ * False: the object should keep its individual shape.
+
+ :type compound: boolean
+ :arg ghost: whether the object should be ghost while parented.
+
+ * True: if the object should be made ghost while parented.
+ * False: if the object should be solid while parented.
+
+ :type ghost: boolean
+
+ .. note::
+
+ If the object type is sensor, it stays ghost regardless of ghost parameter
+
+ .. method:: removeParent()
+
+ Removes this objects parent.
+
+ .. method:: getPhysicsId()
+
+ Returns the user data object associated with this game object's physics controller.
+
+ .. method:: getPropertyNames()
+
+ Gets a list of all property names.
+
+ :return: All property names for this object.
+ :rtype: list
+
+ .. method:: getDistanceTo(other)
+
+ :arg other: a point or another :class:`KX_GameObject` to measure the distance to.
+ :type other: :class:`KX_GameObject` or list [x, y, z]
+ :return: distance to another object or point.
+ :rtype: float
+
+ .. method:: getVectTo(other)
+
+ Returns the vector and the distance to another object or point.
+ The vector is normalized unless the distance is 0, in which a zero length vector is returned.
+
+ :arg other: a point or another :class:`KX_GameObject` to get the vector and distance to.
+ :type other: :class:`KX_GameObject` or list [x, y, z]
+ :return: (distance, globalVector(3), localVector(3))
+ :rtype: 3-tuple (float, 3-tuple (x, y, z), 3-tuple (x, y, z))
+
+ .. method:: rayCastTo(other, dist, prop)
+
+ Look towards another point/object and find first object hit within dist that matches prop.
+
+ The ray is always casted from the center of the object, ignoring the object itself.
+ The ray is casted towards the center of another object or an explicit [x, y, z] point.
+ Use rayCast() if you need to retrieve the hit point
+
+ :arg other: [x, y, z] or object towards which the ray is casted
+ :type other: :class:`KX_GameObject` or 3-tuple
+ :arg dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to other
+ :type dist: float
+ :arg prop: property name that object must have; can be omitted => detect any object
+ :type prop: string
+ :return: the first object hit or None if no object or object does not match prop
+ :rtype: :class:`KX_GameObject`
+
+ .. method:: rayCast(objto, objfrom, dist, prop, face, xray, poly)
+
+ Look from a point/object to another point/object and find first object hit within dist that matches prop.
+ if poly is 0, returns a 3-tuple with object reference, hit point and hit normal or (None, None, None) if no hit.
+ if poly is 1, returns a 4-tuple with in addition a :class:`KX_PolyProxy` as 4th element.
+ if poly is 2, returns a 5-tuple with in addition a 2D vector with the UV mapping of the hit point as 5th element.
+
+ .. code-block:: python
+
+ # shoot along the axis gun-gunAim (gunAim should be collision-free)
+ obj, point, normal = gun.rayCast(gunAim, None, 50)
+ if obj:
+ # do something
+ pass
+
+ The face paremeter determines the orientation of the normal.
+
+ * 0 => hit normal is always oriented towards the ray origin (as if you casted the ray from outside)
+ * 1 => hit normal is the real face normal (only for mesh object, otherwise face has no effect)
+
+ The ray has X-Ray capability if xray parameter is 1, otherwise the first object hit (other than self object) stops the ray.
+ The prop and xray parameters interact as follow.
+
+ * prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray.
+ * prop off, xray on : idem.
+ * prop on, xray off: return closest hit if it matches prop, no hit otherwise.
+ * prop on, xray on : return closest hit matching prop or no hit if there is no object matching prop on the full extend of the ray.
+
+ The :class:`KX_PolyProxy` 4th element of the return tuple when poly=1 allows to retrieve information on the polygon hit by the ray.
+ If there is no hit or the hit object is not a static mesh, None is returned as 4th element.
+
+ The ray ignores collision-free objects and faces that dont have the collision flag enabled, you can however use ghost objects.
+
+ :arg objto: [x, y, z] or object to which the ray is casted
+ :type objto: :class:`KX_GameObject` or 3-tuple
+ :arg objfrom: [x, y, z] or object from which the ray is casted; None or omitted => use self object center
+ :type objfrom: :class:`KX_GameObject` or 3-tuple or None
+ :arg dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to to
+ :type dist: float
+ :arg prop: property name that object must have; can be omitted or "" => detect any object
+ :type prop: string
+ :arg face: normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin
+ :type face: integer
+ :arg xray: X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object
+ :type xray: integer
+ :arg poly: polygon option: 0, 1 or 2 to return a 3-, 4- or 5-tuple with information on the face hit.
+
+ * 0 or omitted: return value is a 3-tuple (object, hitpoint, hitnormal) or (None, None, None) if no hit
+ * 1: return value is a 4-tuple and the 4th element is a :class:`KX_PolyProxy` or None if no hit or the object doesn't use a mesh collision shape.
+ * 2: return value is a 5-tuple and the 5th element is a 2-tuple (u, v) with the UV mapping of the hit point or None if no hit, or the object doesn't use a mesh collision shape, or doesn't have a UV mapping.
+
+ :type poly: integer
+ :return: (object, hitpoint, hitnormal) or (object, hitpoint, hitnormal, polygon) or (object, hitpoint, hitnormal, polygon, hituv).
+
+ * object, hitpoint and hitnormal are None if no hit.
+ * polygon is valid only if the object is valid and is a static object, a dynamic object using mesh collision shape or a soft body object, otherwise it is None
+ * hituv is valid only if polygon is valid and the object has a UV mapping, otherwise it is None
+
+ :rtype:
+
+ * 3-tuple (:class:`KX_GameObject`, 3-tuple (x, y, z), 3-tuple (nx, ny, nz))
+ * or 4-tuple (:class:`KX_GameObject`, 3-tuple (x, y, z), 3-tuple (nx, ny, nz), :class:`PolyProxy`)
+ * or 5-tuple (:class:`KX_GameObject`, 3-tuple (x, y, z), 3-tuple (nx, ny, nz), :class:`PolyProxy`, 2-tuple (u, v))
+
+ .. note::
+
+ The ray ignores the object on which the method is called. It is casted from/to object center or explicit [x, y, z] points.
+
+ .. method:: setCollisionMargin(margin)
+
+ Set the objects collision margin.
+
+ :arg margin: the collision margin distance in blender units.
+ :type margin: float
+
+ .. note::
+
+ If this object has no physics controller (a physics ID of zero), this function will raise RuntimeError.
+
+ .. method:: sendMessage(subject, body="", to="")
+
+ Sends a message.
+
+ :arg subject: The subject of the message
+ :type subject: string
+ :arg body: The body of the message (optional)
+ :type body: string
+ :arg to: The name of the object to send the message to (optional)
+ :type to: string
+
+ .. method:: reinstancePhysicsMesh(gameObject, meshObject)
+
+ Updates the physics system with the changed mesh.
+
+ If no arguments are given the physics mesh will be re-created from the first mesh assigned to the game object.
+
+ :arg gameObject: optional argument, set the physics shape from this gameObjets mesh.
+ :type gameObject: string, :class:`KX_GameObject` or None
+ :arg meshObject: optional argument, set the physics shape from this mesh.
+ :type meshObject: string, :class:`MeshProxy` or None
+
+ :return: True if reinstance succeeded, False if it failed.
+ :rtype: boolean
+
+ .. note::
+
+ If this object has instances the other instances will be updated too.
+
+ .. note::
+
+ The gameObject argument has an advantage that it can convert from a mesh with modifiers applied (such as subsurf).
+
+ .. warning::
+
+ Only triangle mesh type objects are supported currently (not convex hull)
+
+ .. warning::
+
+ If the object is a part of a combound object it will fail (parent or child)
+
+ .. warning::
+
+ Rebuilding the physics mesh can be slow, running many times per second will give a performance hit.
+
+ .. method:: get(key, default=None)
+
+ Return the value matching key, or the default value if its not found.
+ :return: The key value or a default.
+
+ .. method:: playAction(name, start_frame, end_frame, layer=0, priority=0, blendin=0, play_mode=ACT_MODE_PLAY, layer_weight=0.0, ipo_flags=0, speed=1.0)
+
+ Plays an action.
+
+ :arg name: the name of the action
+ :type name: string
+ :arg start: the start frame of the action
+ :type start: float
+ :arg end: the end frame of the action
+ :type end: float
+ :arg layer: the layer the action will play in (actions in different layers are added/blended together)
+ :type layer: integer
+ :arg priority: only play this action if there isn't an action currently playing in this layer with a higher (lower number) priority
+ :type priority: integer
+ :arg blendin: the amount of blending between this animation and the previous one on this layer
+ :type blendin: float
+ :arg play_mode: the play mode
+ :type play_mode: one of :ref:`these constants <gameobject-playaction-mode>`
+ :arg layer_weight: how much of the previous layer to use for blending (0 = add)
+ :type layer_weight: float
+ :arg ipo_flags: flags for the old IPO behaviors (force, etc)
+ :type ipo_flags: int bitfield
+ :arg speed: the playback speed of the action as a factor (1.0 = normal speed, 2.0 = 2x speed, etc)
+ :type speed: float
+
+ .. method:: stopAction(layer=0)
+
+ Stop playing the action on the given layer.
+
+ :arg layer: The layer to stop playing.
+ :type layer: integer
+
+ .. method:: getActionFrame(layer=0)
+
+ Gets the current frame of the action playing in the supplied layer.
+
+ :arg layer: The layer that you want to get the frame from.
+ :type layer: integer
+
+ :return: The current frame of the action
+ :rtype: float
+
+ .. method:: setActionFrame(frame, layer=0)
+
+ Set the current frame of the action playing in the supplied layer.
+
+ :arg layer: The layer where you want to set the frame
+ :type layer: integer
+ :arg frame: The frame to set the action to
+ :type frame: float
+
+ .. method:: isPlayingAction(layer=0)
+
+ Checks to see if there is an action playing in the given layer.
+
+ :arg layer: The layer to check for a playing action.
+ :type layer: integer
+
+ :return: Whether or not the action is playing
+ :rtype: boolean
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_IpoActuator.rst b/doc/python_api/rst/bge_types/bge.types.KX_IpoActuator.rst
new file mode 100644
index 00000000000..2cae4fb3b1a
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_IpoActuator.rst
@@ -0,0 +1,65 @@
+KX_IpoActuator(SCA_IActuator)
+=============================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: KX_IpoActuator(SCA_IActuator)
+
+ IPO actuator activates an animation.
+
+ .. attribute:: frameStart
+
+ Start frame.
+
+ :type: float
+
+ .. attribute:: frameEnd
+
+ End frame.
+
+ :type: float
+
+ .. attribute:: propName
+
+ Use this property to define the Ipo position.
+
+ :type: string
+
+ .. attribute:: framePropName
+
+ Assign this property this action current frame number.
+
+ :type: string
+
+ .. attribute:: mode
+
+ Play mode for the ipo. Can be on of :ref:`these constants <ipo-actuator>`
+
+ :type: integer
+
+ .. attribute:: useIpoAsForce
+
+ Apply Ipo as a global or local force depending on the local option (dynamic objects only).
+
+ :type: boolean
+
+ .. attribute:: useIpoAdd
+
+ Ipo is added to the current loc/rot/scale in global or local coordinate according to Local flag.
+
+ :type: boolean
+
+ .. attribute:: useIpoLocal
+
+ Let the ipo acts in local coordinates, used in Force and Add mode.
+
+ :type: boolean
+
+ .. attribute:: useChildren
+
+ Update IPO on all children Objects as well.
+
+ :type: boolean
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_LibLoadStatus.rst b/doc/python_api/rst/bge_types/bge.types.KX_LibLoadStatus.rst
new file mode 100644
index 00000000000..a5b7aaf5dee
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_LibLoadStatus.rst
@@ -0,0 +1,45 @@
+KX_LibLoadStatus(PyObjectPlus)
+==============================
+
+.. module:: bge.types
+
+base class --- :class:`PyObjectPlus`
+
+.. class:: KX_LibLoadStatus(PyObjectPlus)
+
+ An object providing information about a LibLoad() operation.
+
+ .. code-block:: python
+
+ # Print a message when an async LibLoad is done
+ import bge
+
+ def finished_cb(status):
+ print("Library (%s) loaded in %.2fms." % (status.libraryName, status.timeTaken))
+
+ bge.logic.LibLoad('myblend.blend', 'Scene', async=True).onFinish = finished_cb
+
+ .. attribute:: onFinish
+
+ A callback that gets called when the lib load is done.
+
+ :type: callable
+
+ .. attribute:: progress
+
+ The current progress of the lib load as a normalized value from 0.0 to 1.0.
+
+ :type: float
+
+ .. attribute:: libraryName
+
+ The name of the library being loaded (the first argument to LibLoad).
+
+ :type: string
+
+ .. attribute:: timeTaken
+
+ The amount of time, in seconds, the lib load took (0 until the operation is complete).
+
+ :type: float
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_LightObject.rst b/doc/python_api/rst/bge_types/bge.types.KX_LightObject.rst
new file mode 100644
index 00000000000..2b2bdf76b4f
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_LightObject.rst
@@ -0,0 +1,90 @@
+KX_LightObject(KX_GameObject)
+=============================
+
+.. module:: bge.types
+
+base class --- :class:`KX_GameObject`
+
+.. class:: KX_LightObject(KX_GameObject)
+
+ A Light object.
+
+ .. code-block:: python
+
+ # Turn on a red alert light.
+ import bge
+
+ co = bge.logic.getCurrentController()
+ light = co.owner
+
+ light.energy = 1.0
+ light.color = [1.0, 0.0, 0.0]
+
+ .. data:: SPOT
+
+ A spot light source. See attribute :data:`type`
+
+ .. data:: SUN
+
+ A point light source with no attenuation. See attribute :data:`type`
+
+ .. data:: NORMAL
+
+ A point light source. See attribute :data:`type`
+
+ .. attribute:: type
+
+ The type of light - must be SPOT, SUN or NORMAL
+
+ .. attribute:: layer
+
+ The layer mask that this light affects object on.
+
+ :type: bitfield
+
+ .. attribute:: energy
+
+ The brightness of this light.
+
+ :type: float
+
+ .. attribute:: distance
+
+ The maximum distance this light can illuminate. (SPOT and NORMAL lights only).
+
+ :type: float
+
+ .. attribute:: color
+
+ The color of this light. Black = [0.0, 0.0, 0.0], White = [1.0, 1.0, 1.0].
+
+ :type: list [r, g, b]
+
+ .. attribute:: lin_attenuation
+
+ The linear component of this light's attenuation. (SPOT and NORMAL lights only).
+
+ :type: float
+
+ .. attribute:: quad_attenuation
+
+ The quadratic component of this light's attenuation (SPOT and NORMAL lights only).
+
+ :type: float
+
+ .. attribute:: spotsize
+
+ The cone angle of the spot light, in degrees (SPOT lights only).
+
+ :type: float in [0 - 180].
+
+ .. attribute:: spotblend
+
+ Specifies the intensity distribution of the spot light (SPOT lights only).
+
+ :type: float in [0 - 1]
+
+ .. note::
+
+ Higher values result in a more focused light source.
+
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
new file mode 100644
index 00000000000..2ec8b8ece5c
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_MeshProxy.rst
@@ -0,0 +1,134 @@
+KX_MeshProxy(SCA_IObject)
+=========================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IObject`
+
+.. class:: KX_MeshProxy(SCA_IObject)
+
+ A mesh object.
+
+ You can only change the vertex properties of a mesh object, not the mesh topology.
+
+ To use mesh objects effectively, you should know a bit about how the game engine handles them.
+
+ #. Mesh Objects are converted from Blender at scene load.
+ #. The Converter groups polygons by Material. This means they can be sent to the renderer efficiently. A material holds:
+
+ #. The texture.
+ #. The Blender material.
+ #. The Tile properties
+ #. The face properties - (From the "Texture Face" panel)
+ #. Transparency & z sorting
+ #. Light layer
+ #. Polygon shape (triangle/quad)
+ #. Game Object
+
+ #. Vertices will be split by face if necessary. Vertices can only be shared between faces if:
+
+ #. They are at the same position
+ #. UV coordinates are the same
+ #. Their normals are the same (both polygons are "Set Smooth")
+ #. They are the same color, for example: a cube has 24 vertices: 6 faces with 4 vertices per face.
+
+ The correct method of iterating over every :class:`KX_VertexProxy` in a game object
+
+ .. code-block:: python
+
+ from bge import logic
+
+ cont = logic.getCurrentController()
+ object = cont.owner
+
+ for mesh in object.meshes:
+ for m_index in range(len(mesh.materials)):
+ for v_index in range(mesh.getVertexArrayLength(m_index)):
+ vertex = mesh.getVertex(m_index, v_index)
+ # Do something with vertex here...
+ # ... eg: color the vertex red.
+ vertex.color = [1.0, 0.0, 0.0, 1.0]
+
+ .. attribute:: materials
+
+ :type: list of :class:`KX_BlenderMaterial` or :class:`KX_PolygonMaterial` types
+
+ .. attribute:: numPolygons
+
+ :type: integer
+
+ .. attribute:: numMaterials
+
+ :type: integer
+
+ .. method:: getMaterialName(matid)
+
+ Gets the name of the specified material.
+
+ :arg matid: the specified material.
+ :type matid: integer
+ :return: the attached material name.
+ :rtype: string
+
+ .. method:: getTextureName(matid)
+
+ Gets the name of the specified material's texture.
+
+ :arg matid: the specified material
+ :type matid: integer
+ :return: the attached material's texture name.
+ :rtype: string
+
+ .. method:: getVertexArrayLength(matid)
+
+ Gets the length of the vertex array associated with the specified material.
+
+ There is one vertex array for each material.
+
+ :arg matid: the specified material
+ :type matid: integer
+ :return: the number of verticies in the vertex array.
+ :rtype: integer
+
+ .. method:: getVertex(matid, index)
+
+ Gets the specified vertex from the mesh object.
+
+ :arg matid: the specified material
+ :type matid: integer
+ :arg index: the index into the vertex array.
+ :type index: integer
+ :return: a vertex object.
+ :rtype: :class:`KX_VertexProxy`
+
+ .. method:: getPolygon(index)
+
+ Gets the specified polygon from the mesh.
+
+ :arg index: polygon number
+ :type index: integer
+ :return: a polygon object.
+ :rtype: :class:`PolyProxy`
+
+ .. method:: transform(matid, matrix)
+
+ Transforms the vertices of a mesh.
+
+ :arg matid: material index, -1 transforms all.
+ :type matid: integer
+ :arg matrix: transformation matrix.
+ :type matrix: 4x4 matrix [[float]]
+
+ .. method:: transformUV(matid, matrix, uv_index=-1, uv_index_from=-1)
+
+ Transforms the vertices UV's of a mesh.
+
+ :arg matid: material index, -1 transforms all.
+ :type matid: integer
+ :arg matrix: transformation matrix.
+ :type matrix: 4x4 matrix [[float]]
+ :arg uv_index: optional uv index, -1 for all, otherwise 0 or 1.
+ :type uv_index: integer
+ :arg uv_index_from: optional uv index to copy from, -1 to transform the current uv.
+ :type uv_index_from: integer
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_MouseFocusSensor.rst b/doc/python_api/rst/bge_types/bge.types.KX_MouseFocusSensor.rst
new file mode 100644
index 00000000000..dda73eadb52
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_MouseFocusSensor.rst
@@ -0,0 +1,66 @@
+KX_MouseFocusSensor(SCA_MouseSensor)
+====================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_MouseSensor`
+
+.. class:: KX_MouseFocusSensor(SCA_MouseSensor)
+
+ The mouse focus sensor detects when the mouse is over the current game object.
+
+ The mouse focus sensor works by transforming the mouse coordinates from 2d device
+ space to 3d space then raycasting away from the camera.
+
+ .. attribute:: raySource
+
+ The worldspace source of the ray (the view position).
+
+ :type: list (vector of 3 floats)
+
+ .. attribute:: rayTarget
+
+ The worldspace target of the ray.
+
+ :type: list (vector of 3 floats)
+
+ .. attribute:: rayDirection
+
+ The :data:`rayTarget` - :class:`raySource` normalized.
+
+ :type: list (normalized vector of 3 floats)
+
+ .. attribute:: hitObject
+
+ the last object the mouse was over.
+
+ :type: :class:`KX_GameObject` or None
+
+ .. attribute:: hitPosition
+
+ The worldspace position of the ray intersecton.
+
+ :type: list (vector of 3 floats)
+
+ .. attribute:: hitNormal
+
+ the worldspace normal from the face at point of intersection.
+
+ :type: list (normalized vector of 3 floats)
+
+ .. attribute:: hitUV
+
+ the UV coordinates at the point of intersection.
+
+ :type: list (vector of 2 floats)
+
+ If the object has no UV mapping, it returns [0, 0].
+
+ The UV coordinates are not normalized, they can be < 0 or > 1 depending on the UV mapping.
+
+ .. attribute:: usePulseFocus
+
+ When enabled, moving the mouse over a different object generates a pulse. (only used when the 'Mouse Over Any' sensor option is set).
+
+ :type: boolean
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_NavMeshObject.rst b/doc/python_api/rst/bge_types/bge.types.KX_NavMeshObject.rst
new file mode 100644
index 00000000000..5c73d0aa1d3
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_NavMeshObject.rst
@@ -0,0 +1,47 @@
+KX_NavMeshObject(KX_GameObject)
+===============================
+
+.. module:: bge.types
+
+base class --- :class:`KX_GameObject`
+
+.. class:: KX_NavMeshObject(KX_GameObject)
+
+ Python interface for using and controlling navigation meshes.
+
+ .. method:: findPath(start, goal)
+
+ Finds the path from start to goal points.
+
+ :arg start: the start point
+ :arg start: 3D Vector
+ :arg goal: the goal point
+ :arg start: 3D Vector
+ :return: a path as a list of points
+ :rtype: list of points
+
+ .. method:: raycast(start, goal)
+
+ Raycast from start to goal points.
+
+ :arg start: the start point
+ :arg start: 3D Vector
+ :arg goal: the goal point
+ :arg start: 3D Vector
+ :return: the hit factor
+ :rtype: float
+
+ .. method:: draw(mode)
+
+ Draws a debug mesh for the navigation mesh.
+
+ :arg mode: the drawing mode (one of :ref:`these constants <navmesh-draw-mode>`)
+ :arg mode: integer
+ :return: None
+
+ .. method:: rebuild()
+
+ Rebuild the navigation mesh.
+
+ :return: None
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_NearSensor.rst b/doc/python_api/rst/bge_types/bge.types.KX_NearSensor.rst
new file mode 100644
index 00000000000..995e645b979
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_NearSensor.rst
@@ -0,0 +1,23 @@
+KX_NearSensor(KX_TouchSensor)
+=============================
+
+.. module:: bge.types
+
+base class --- :class:`KX_TouchSensor`
+
+.. class:: KX_NearSensor(KX_TouchSensor)
+
+ A near sensor is a specialised form of touch sensor.
+
+ .. attribute:: distance
+
+ The near sensor activates when an object is within this distance.
+
+ :type: float
+
+ .. attribute:: resetDistance
+
+ The near sensor deactivates when the object exceeds this distance.
+
+ :type: float
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_NetworkMessageActuator.rst b/doc/python_api/rst/bge_types/bge.types.KX_NetworkMessageActuator.rst
new file mode 100644
index 00000000000..b8dcd01fe43
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_NetworkMessageActuator.rst
@@ -0,0 +1,35 @@
+KX_NetworkMessageActuator(SCA_IActuator)
+========================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: KX_NetworkMessageActuator(SCA_IActuator)
+
+ Message Actuator
+
+ .. attribute:: propName
+
+ Messages will only be sent to objects with the given property name.
+
+ :type: string
+
+ .. attribute:: subject
+
+ The subject field of the message.
+
+ :type: string
+
+ .. attribute:: body
+
+ The body of the message.
+
+ :type: string
+
+ .. attribute:: usePropBody
+
+ Send a property instead of a regular body message.
+
+ :type: boolean
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_NetworkMessageSensor.rst b/doc/python_api/rst/bge_types/bge.types.KX_NetworkMessageSensor.rst
new file mode 100644
index 00000000000..a6b1082a4fe
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_NetworkMessageSensor.rst
@@ -0,0 +1,38 @@
+KX_NetworkMessageSensor(SCA_ISensor)
+====================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_ISensor`
+
+.. class:: KX_NetworkMessageSensor(SCA_ISensor)
+
+ The Message Sensor logic brick.
+
+ Currently only loopback (local) networks are supported.
+
+ .. attribute:: subject
+
+ The subject the sensor is looking for.
+
+ :type: string
+
+ .. attribute:: frameMessageCount
+
+ The number of messages received since the last frame. (read-only).
+
+ :type: integer
+
+ .. attribute:: subjects
+
+ The list of message subjects received. (read-only).
+
+ :type: list of strings
+
+ .. attribute:: bodies
+
+ The list of message bodies received. (read-only).
+
+ :type: list of strings
+
+
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
new file mode 100644
index 00000000000..f10f101a4cc
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_ObjectActuator.rst
@@ -0,0 +1,129 @@
+KX_ObjectActuator(SCA_IActuator)
+================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: KX_ObjectActuator(SCA_IActuator)
+
+ The object actuator ("Motion Actuator") applies force, torque, displacement, angular displacement,
+ velocity, or angular velocity to an object.
+ Servo control allows to regulate force to achieve a certain speed target.
+
+ .. attribute:: force
+
+ The force applied by the actuator.
+
+ :type: list [x, y, z]
+
+ .. attribute:: useLocalForce
+
+ A flag specifying if the force is local.
+
+ :type: boolean
+
+ .. attribute:: torque
+
+ The torque applied by the actuator.
+
+ :type: list [x, y, z]
+
+ .. attribute:: useLocalTorque
+
+ A flag specifying if the torque is local.
+
+ :type: boolean
+
+ .. attribute:: dLoc
+
+ The displacement vector applied by the actuator.
+
+ :type: list [x, y, z]
+
+ .. attribute:: useLocalDLoc
+
+ A flag specifying if the dLoc is local.
+
+ :type: boolean
+
+ .. attribute:: dRot
+
+ The angular displacement vector applied by the actuator
+
+ :type: list [x, y, z]
+
+ .. note::
+
+ Since the displacement is applied every frame, you must adjust the displacement based on the frame rate, or you game experience will depend on the player's computer speed.
+
+ .. attribute:: useLocalDRot
+
+ A flag specifying if the dRot is local.
+
+ :type: boolean
+
+ .. attribute:: linV
+
+ The linear velocity applied by the actuator.
+
+ :type: list [x, y, z]
+
+ .. attribute:: useLocalLinV
+
+ A flag specifying if the linear velocity is local.
+
+ :type: boolean
+
+ .. note::
+
+ This is the target speed for servo controllers.
+
+ .. attribute:: angV
+
+ The angular velocity applied by the actuator.
+
+ :type: list [x, y, z]
+
+ .. attribute:: useLocalAngV
+
+ A flag specifying if the angular velocity is local.
+
+ :type: boolean
+
+ .. attribute:: damping
+
+ The damping parameter of the servo controller.
+
+ :type: short
+
+ .. attribute:: forceLimitX
+
+ The min/max force limit along the X axis and activates or deactivates the limits in the servo controller.
+
+ :type: list [min(float), max(float), bool]
+
+ .. attribute:: forceLimitY
+
+ The min/max force limit along the Y axis and activates or deactivates the limits in the servo controller.
+
+ :type: list [min(float), max(float), bool]
+
+ .. attribute:: forceLimitZ
+
+ The min/max force limit along the Z axis and activates or deactivates the limits in the servo controller.
+
+ :type: list [min(float), max(float), bool]
+
+ .. attribute:: pid
+
+ The PID coefficients of the servo controller.
+
+ :type: list of floats [proportional, integral, derivate]
+
+ .. attribute:: reference
+
+ The object that is used as reference to compute the velocity for the servo controller.
+
+ :type: :class:`KX_GameObject` or None
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_ParentActuator.rst b/doc/python_api/rst/bge_types/bge.types.KX_ParentActuator.rst
new file mode 100644
index 00000000000..77dcb907d6a
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_ParentActuator.rst
@@ -0,0 +1,38 @@
+KX_ParentActuator(SCA_IActuator)
+================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: KX_ParentActuator(SCA_IActuator)
+
+ The parent actuator can set or remove an objects parent object.
+
+ .. attribute:: object
+
+ the object this actuator sets the parent too.
+
+ :type: :class:`KX_GameObject` or None
+
+ .. attribute:: mode
+
+ The mode of this actuator.
+
+ :type: integer from 0 to 1.
+
+ .. attribute:: compound
+
+ Whether the object shape should be added to the parent compound shape when parenting.
+
+ Effective only if the parent is already a compound shape.
+
+ :type: boolean
+
+ .. attribute:: ghost
+
+ Whether the object should be made ghost when parenting
+ Effective only if the shape is not added to the parent compound shape.
+
+ :type: boolean
+
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
new file mode 100644
index 00000000000..534f6deedc0
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_PolyProxy.rst
@@ -0,0 +1,139 @@
+KX_PolyProxy(SCA_IObject)
+=========================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IObject`
+
+.. class:: KX_PolyProxy(SCA_IObject)
+
+ A polygon holds the index of the vertex forming the poylgon.
+
+ Note:
+ The polygon attributes are read-only, you need to retrieve the vertex proxy if you want
+ to change the vertex settings.
+
+ .. attribute:: material_name
+
+ The name of polygon material, empty if no material.
+
+ :type: string
+
+ .. attribute:: material
+
+ The material of the polygon.
+
+ :type: :class:`KX_PolygonMaterial` or :class:`KX_BlenderMaterial`
+
+ .. attribute:: texture_name
+
+ The texture name of the polygon.
+
+ :type: string
+
+ .. attribute:: material_id
+
+ The material index of the polygon, use this to retrieve vertex proxy from mesh proxy.
+
+ :type: integer
+
+ .. attribute:: v1
+
+ vertex index of the first vertex of the polygon, use this to retrieve vertex proxy from mesh proxy.
+
+ :type: integer
+
+ .. attribute:: v2
+
+ vertex index of the second vertex of the polygon, use this to retrieve vertex proxy from mesh proxy.
+
+ :type: integer
+
+ .. attribute:: v3
+
+ vertex index of the third vertex of the polygon, use this to retrieve vertex proxy from mesh proxy.
+
+ :type: integer
+
+ .. attribute:: v4
+
+ Vertex index of the fourth vertex of the polygon, 0 if polygon has only 3 vertex
+ Use this to retrieve vertex proxy from mesh proxy.
+
+ :type: integer
+
+ .. attribute:: visible
+
+ visible state of the polygon: 1=visible, 0=invisible.
+
+ :type: integer
+
+ .. attribute:: collide
+
+ collide state of the polygon: 1=receives collision, 0=collision free.
+
+ :type: integer
+
+ .. method:: getMaterialName()
+
+ Returns the polygon material name with MA prefix
+
+ :return: material name
+ :rtype: string
+
+ .. method:: getMaterial()
+
+ :return: The polygon material
+ :rtype: :class:`KX_PolygonMaterial` or :class:`KX_BlenderMaterial`
+
+ .. method:: getTextureName()
+
+ :return: The texture name
+ :rtype: string
+
+ .. method:: getMaterialIndex()
+
+ Returns the material bucket index of the polygon.
+ This index and the ones returned by getVertexIndex() are needed to retrieve the vertex proxy from :class:`MeshProxy`.
+
+ :return: the material index in the mesh
+ :rtype: integer
+
+ .. method:: getNumVertex()
+
+ Returns the number of vertex of the polygon.
+
+ :return: number of vertex, 3 or 4.
+ :rtype: integer
+
+ .. method:: isVisible()
+
+ Returns whether the polygon is visible or not
+
+ :return: 0=invisible, 1=visible
+ :rtype: boolean
+
+ .. method:: isCollider()
+
+ Returns whether the polygon is receives collision or not
+
+ :return: 0=collision free, 1=receives collision
+ :rtype: integer
+
+ .. method:: getVertexIndex(vertex)
+
+ Returns the mesh vertex index of a polygon vertex
+ This index and the one returned by getMaterialIndex() are needed to retrieve the vertex proxy from :class:`MeshProxy`.
+
+ :arg vertex: index of the vertex in the polygon: 0->3
+ :arg vertex: integer
+ :return: mesh vertex index
+ :rtype: integer
+
+ .. method:: getMesh()
+
+ Returns a mesh proxy
+
+ :return: mesh proxy
+ :rtype: :class:`MeshProxy`
+
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
new file mode 100644
index 00000000000..3421e194d77
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_PolygonMaterial.rst
@@ -0,0 +1,250 @@
+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_RadarSensor.rst b/doc/python_api/rst/bge_types/bge.types.KX_RadarSensor.rst
new file mode 100644
index 00000000000..4274c1142f4
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_RadarSensor.rst
@@ -0,0 +1,44 @@
+KX_RadarSensor(KX_NearSensor)
+=============================
+
+.. module:: bge.types
+
+base class --- :class:`KX_NearSensor`
+
+.. class:: KX_RadarSensor(KX_NearSensor)
+
+ Radar sensor is a near sensor with a conical sensor object.
+
+ .. attribute:: coneOrigin
+
+ The origin of the cone with which to test. The origin is in the middle of the cone. (read-only).
+
+ :type: list of floats [x, y, z]
+
+ .. attribute:: coneTarget
+
+ The center of the bottom face of the cone with which to test. (read-only).
+
+ :type: list of floats [x, y, z]
+
+ .. attribute:: distance
+
+ The height of the cone with which to test.
+
+ :type: float
+
+ .. attribute:: angle
+
+ The angle of the cone (in degrees) with which to test.
+
+ :type: float
+
+ .. attribute:: axis
+
+ The axis on which the radar cone is cast.
+
+ :type: integer from 0 to 5
+
+ KX_RADAR_AXIS_POS_X, KX_RADAR_AXIS_POS_Y, KX_RADAR_AXIS_POS_Z,
+ KX_RADAR_AXIS_NEG_X, KX_RADAR_AXIS_NEG_Y, KX_RADAR_AXIS_NEG_Z
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_RaySensor.rst b/doc/python_api/rst/bge_types/bge.types.KX_RaySensor.rst
new file mode 100644
index 00000000000..2ff989729f5
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_RaySensor.rst
@@ -0,0 +1,72 @@
+KX_RaySensor(SCA_ISensor)
+=========================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_ISensor`
+
+.. class:: KX_RaySensor(SCA_ISensor)
+
+ A ray sensor detects the first object in a given direction.
+
+ .. attribute:: propName
+
+ The property the ray is looking for.
+
+ :type: string
+
+ .. attribute:: range
+
+ The distance of the ray.
+
+ :type: float
+
+ .. attribute:: useMaterial
+
+ Whether or not to look for a material (false = property).
+
+ :type: boolean
+
+ .. attribute:: useXRay
+
+ Whether or not to use XRay.
+
+ :type: boolean
+
+ .. attribute:: hitObject
+
+ The game object that was hit by the ray. (read-only).
+
+ :type: :class:`KX_GameObject`
+
+ .. attribute:: hitPosition
+
+ The position (in worldcoordinates) where the object was hit by the ray. (read-only).
+
+ :type: list [x, y, z]
+
+ .. attribute:: hitNormal
+
+ The normal (in worldcoordinates) of the object at the location where the object was hit by the ray. (read-only).
+
+ :type: list [x, y, z]
+
+ .. attribute:: rayDirection
+
+ The direction from the ray (in worldcoordinates). (read-only).
+
+ :type: list [x, y, z]
+
+ .. attribute:: axis
+
+ The axis the ray is pointing on.
+
+ :type: integer from 0 to 5
+
+ * KX_RAY_AXIS_POS_X
+ * KX_RAY_AXIS_POS_Y
+ * KX_RAY_AXIS_POS_Z
+ * KX_RAY_AXIS_NEG_X
+ * KX_RAY_AXIS_NEG_Y
+ * KX_RAY_AXIS_NEG_Z
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_SCA_AddObjectActuator.rst b/doc/python_api/rst/bge_types/bge.types.KX_SCA_AddObjectActuator.rst
new file mode 100644
index 00000000000..fecc863909d
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_SCA_AddObjectActuator.rst
@@ -0,0 +1,55 @@
+KX_SCA_AddObjectActuator(SCA_IActuator)
+=======================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: KX_SCA_AddObjectActuator(SCA_IActuator)
+
+ Edit Object Actuator (in Add Object Mode)
+
+ .. warning::
+
+ An Add Object actuator will be ignored if at game start, the linked object doesn't exist (or is empty) or the linked object is in an active layer.
+
+ .. code-block:: none
+
+ Error: GameObject 'Name' has a AddObjectActuator 'ActuatorName' without object (in 'nonactive' layer)
+
+ .. attribute:: object
+
+ the object this actuator adds.
+
+ :type: :class:`KX_GameObject` or None
+
+ .. attribute:: objectLastCreated
+
+ the last added object from this actuator (read-only).
+
+ :type: :class:`KX_GameObject` or None
+
+ .. attribute:: time
+
+ the lifetime of added objects, in frames. Set to 0 to disable automatic deletion.
+
+ :type: integer
+
+ .. attribute:: linearVelocity
+
+ the initial linear velocity of added objects.
+
+ :type: list [vx, vy, vz]
+
+ .. attribute:: angularVelocity
+
+ the initial angular velocity of added objects.
+
+ :type: list [vx, vy, vz]
+
+ .. method:: instantAddObject()
+
+ adds the object without needing to calling SCA_PythonController.activate()
+
+ .. note:: Use objectLastCreated to get the newly created object.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_SCA_DynamicActuator.rst b/doc/python_api/rst/bge_types/bge.types.KX_SCA_DynamicActuator.rst
new file mode 100644
index 00000000000..055c4098253
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_SCA_DynamicActuator.rst
@@ -0,0 +1,29 @@
+KX_SCA_DynamicActuator(SCA_IActuator)
+=====================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: KX_SCA_DynamicActuator(SCA_IActuator)
+
+ Dynamic Actuator.
+
+ .. attribute:: mode
+
+ :type: integer
+
+ the type of operation of the actuator, 0-4
+
+ * KX_DYN_RESTORE_DYNAMICS(0)
+ * KX_DYN_DISABLE_DYNAMICS(1)
+ * KX_DYN_ENABLE_RIGID_BODY(2)
+ * KX_DYN_DISABLE_RIGID_BODY(3)
+ * KX_DYN_SET_MASS(4)
+
+ .. attribute:: mass
+
+ the mass value for the KX_DYN_SET_MASS operation.
+
+ :type: float
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_SCA_EndObjectActuator.rst b/doc/python_api/rst/bge_types/bge.types.KX_SCA_EndObjectActuator.rst
new file mode 100644
index 00000000000..8d9221febb0
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_SCA_EndObjectActuator.rst
@@ -0,0 +1,13 @@
+KX_SCA_EndObjectActuator(SCA_IActuator)
+=======================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: KX_SCA_EndObjectActuator(SCA_IActuator)
+
+ Edit Object Actuator (in End Object mode)
+
+ This actuator has no python methods.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_SCA_ReplaceMeshActuator.rst b/doc/python_api/rst/bge_types/bge.types.KX_SCA_ReplaceMeshActuator.rst
new file mode 100644
index 00000000000..137c63ea829
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_SCA_ReplaceMeshActuator.rst
@@ -0,0 +1,89 @@
+KX_SCA_ReplaceMeshActuator(SCA_IActuator)
+=========================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: KX_SCA_ReplaceMeshActuator(SCA_IActuator)
+
+ Edit Object actuator, in Replace Mesh mode.
+
+ .. warning::
+
+ Replace mesh actuators will be ignored if at game start, the named mesh doesn't exist.
+
+ This will generate a warning in the console
+
+ .. code-block:: none
+
+ Error: GameObject 'Name' ReplaceMeshActuator 'ActuatorName' without object
+
+ .. code-block:: python
+
+ # Level-of-detail
+ # Switch a game object's mesh based on its depth in the camera view.
+ # +----------+ +-----------+ +-------------------------------------+
+ # | Always +-----+ Python +-----+ Edit Object (Replace Mesh) LOD.Mesh |
+ # +----------+ +-----------+ +-------------------------------------+
+ from bge import logic
+
+ # List detail meshes here
+ # Mesh (name, near, far)
+ # Meshes overlap so that they don't 'pop' when on the edge of the distance.
+ meshes = ((".Hi", 0.0, -20.0),
+ (".Med", -15.0, -50.0),
+ (".Lo", -40.0, -100.0)
+ )
+
+ cont = logic.getCurrentController()
+ object = cont.owner
+ actuator = cont.actuators["LOD." + obj.name]
+ camera = logic.getCurrentScene().active_camera
+
+ def Depth(pos, plane):
+ return pos[0]*plane[0] + pos[1]*plane[1] + pos[2]*plane[2] + plane[3]
+
+ # Depth is negative and decreasing further from the camera
+ depth = Depth(object.position, camera.world_to_camera[2])
+
+ newmesh = None
+ curmesh = None
+ # Find the lowest detail mesh for depth
+ for mesh in meshes:
+ if depth < mesh[1] and depth > mesh[2]:
+ newmesh = mesh
+ if "ME" + object.name + mesh[0] == actuator.getMesh():
+ curmesh = mesh
+
+ if newmesh != None and "ME" + object.name + newmesh[0] != actuator.mesh:
+ # The mesh is a different mesh - switch it.
+ # Check the current mesh is not a better fit.
+ if curmesh == None or curmesh[1] < depth or curmesh[2] > depth:
+ actuator.mesh = object.name + newmesh[0]
+ cont.activate(actuator)
+
+ .. attribute:: mesh
+
+ :class:`MeshProxy` or the name of the mesh that will replace the current one.
+
+ Set to None to disable actuator.
+
+ :type: :class:`MeshProxy` or None if no mesh is set
+
+ .. attribute:: useDisplayMesh
+
+ when true the displayed mesh is replaced.
+
+ :type: boolean
+
+ .. attribute:: usePhysicsMesh
+
+ when true the physics mesh is replaced.
+
+ :type: boolean
+
+ .. method:: instantReplaceMesh()
+
+ Immediately replace mesh without delay.
+
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
new file mode 100644
index 00000000000..75630ae4d26
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_Scene.rst
@@ -0,0 +1,172 @@
+KX_Scene(PyObjectPlus)
+======================
+
+.. module:: bge.types
+
+base class --- :class:`PyObjectPlus`
+
+.. class:: KX_Scene(PyObjectPlus)
+
+ An active scene that gives access to objects, cameras, lights and scene attributes.
+
+ The activity culling stuff is supposed to disable logic bricks when their owner gets too far
+ from the active camera. It was taken from some code lurking at the back of KX_Scene - who knows
+ what it does!
+
+ .. code-block:: python
+
+ from bge import logic
+
+ # get the scene
+ scene = logic.getCurrentScene()
+
+ # print all the objects in the scene
+ for object in scene.objects:
+ print(object.name)
+
+ # get an object named 'Cube'
+ object = scene.objects["Cube"]
+
+ # get the first object in the scene.
+ object = scene.objects[0]
+
+ .. code-block:: python
+
+ # Get the depth of an object in the camera view.
+ from bge import logic
+
+ object = logic.getCurrentController().owner
+ cam = logic.getCurrentScene().active_camera
+
+ # Depth is negative and decreasing further from the camera
+ depth = object.position[0]*cam.world_to_camera[2][0] + object.position[1]*cam.world_to_camera[2][1] + object.position[2]*cam.world_to_camera[2][2] + cam.world_to_camera[2][3]
+
+ @bug: All attributes are read only at the moment.
+
+ .. attribute:: name
+
+ The scene's name, (read-only).
+
+ :type: string
+
+ .. attribute:: objects
+
+ A list of objects in the scene, (read-only).
+
+ :type: :class:`CListValue` of :class:`KX_GameObject`
+
+ .. attribute:: objectsInactive
+
+ A list of objects on background layers (used for the addObject actuator), (read-only).
+
+ :type: :class:`CListValue` of :class:`KX_GameObject`
+
+ .. attribute:: lights
+
+ A list of lights in the scene, (read-only).
+
+ :type: :class:`CListValue` of :class:`KX_LightObject`
+
+ .. attribute:: cameras
+
+ A list of cameras in the scene, (read-only).
+
+ :type: :class:`CListValue` of :class:`KX_Camera`
+
+ .. attribute:: active_camera
+
+ The current active camera.
+
+ :type: :class:`KX_Camera`
+
+ .. note::
+
+ This can be set directly from python to avoid using the :class:`KX_SceneActuator`.
+
+ .. attribute:: suspended
+
+ True if the scene is suspended, (read-only).
+
+ :type: boolean
+
+ .. attribute:: activity_culling
+
+ True if the scene is activity culling.
+
+ :type: boolean
+
+ .. attribute:: activity_culling_radius
+
+ The distance outside which to do activity culling. Measured in manhattan distance.
+
+ :type: float
+
+ .. attribute:: dbvt_culling
+
+ True when Dynamic Bounding box Volume Tree is set (read-only).
+
+ :type: boolean
+
+ .. attribute:: pre_draw
+
+ A list of callables to be run before the render step.
+
+ :type: list
+
+ .. attribute:: post_draw
+
+ A list of callables to be run after the render step.
+
+ :type: list
+
+ .. attribute:: gravity
+
+ The scene gravity using the world x, y and z axis.
+
+ :type: list [fx, fy, fz]
+
+ .. method:: addObject(object, other, time=0)
+
+ Adds an object to the scene like the Add Object Actuator would.
+
+ :arg object: 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.
+ :type time: integer
+ :return: The newly added object.
+ :rtype: :class:`KX_GameObject`
+
+ .. method:: end()
+
+ Removes the scene from the game.
+
+ .. method:: restart()
+
+ Restarts the scene.
+
+ .. method:: replace(scene)
+
+ Replaces this scene with another one.
+
+ :arg scene: The name of the scene to replace this scene with.
+ :type scene: string
+
+ .. method:: suspend()
+
+ Suspends this scene.
+
+ .. method:: resume()
+
+ Resume this scene.
+
+ .. method:: get(key, default=None)
+
+ Return the value matching key, or the default value if its not found.
+ :return: The key value or a default.
+
+ .. method:: drawObstacleSimulation()
+
+ Draw debug visualization of obstacle simulation.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_SceneActuator.rst b/doc/python_api/rst/bge_types/bge.types.KX_SceneActuator.rst
new file mode 100644
index 00000000000..9d073ff5b19
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_SceneActuator.rst
@@ -0,0 +1,49 @@
+KX_SceneActuator(SCA_IActuator)
+===============================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: KX_SceneActuator(SCA_IActuator)
+
+ Scene Actuator logic brick.
+
+ .. warning::
+
+ Scene actuators that use a scene name will be ignored if at game start, the named scene doesn't exist or is empty
+
+ This will generate a warning in the console:
+
+ .. code-block:: none
+
+ Error: GameObject 'Name' has a SceneActuator 'ActuatorName' (SetScene) without scene
+
+ .. attribute:: scene
+
+ the name of the scene to change to/overlay/underlay/remove/suspend/resume.
+
+ :type: string
+
+ .. attribute:: camera
+
+ the camera to change to.
+
+ :type: :class:`KX_Camera` on read, string or :class:`KX_Camera` on write
+
+ .. note::
+
+ When setting the attribute, you can use either a :class:`KX_Camera` or the name of the camera.
+
+ .. attribute:: useRestart
+
+ Set flag to True to restart the sene.
+
+ :type: boolean
+
+ .. attribute:: mode
+
+ The mode of the actuator.
+
+ :type: integer from 0 to 5.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_SoundActuator.rst b/doc/python_api/rst/bge_types/bge.types.KX_SoundActuator.rst
new file mode 100644
index 00000000000..aa85bd663b8
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_SoundActuator.rst
@@ -0,0 +1,115 @@
+KX_SoundActuator(SCA_IActuator)
+===============================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: KX_SoundActuator(SCA_IActuator)
+
+ Sound Actuator.
+
+ The :data:`startSound`, :data:`pauseSound` and :data:`stopSound` do not require the actuator to be activated - they act instantly provided that the actuator has been activated once at least.
+
+ .. attribute:: volume
+
+ The volume (gain) of the sound.
+
+ :type: float
+
+ .. attribute:: time
+
+ The current position in the audio stream (in seconds).
+
+ :type: float
+
+ .. attribute:: pitch
+
+ The pitch of the sound.
+
+ :type: float
+
+ .. attribute:: mode
+
+ The operation mode of the actuator. Can be one of :ref:`these constants<logic-sound-actuator>`
+
+ :type: integer
+
+ .. attribute:: sound
+
+ The sound the actuator should play.
+
+ :type: Audaspace factory
+
+ .. attribute:: is3D
+
+ Whether or not the actuator should be using 3D sound. (read-only)
+
+ :type: boolean
+
+ .. attribute:: volume_maximum
+
+ The maximum gain of the sound, no matter how near it is.
+
+ :type: float
+
+ .. attribute:: volume_minimum
+
+ The minimum gain of the sound, no matter how far it is away.
+
+ :type: float
+
+ .. attribute:: distance_reference
+
+ The distance where the sound has a gain of 1.0.
+
+ :type: float
+
+ .. attribute:: distance_maximum
+
+ The maximum distance at which you can hear the sound.
+
+ :type: float
+
+ .. attribute:: attenuation
+
+ The influence factor on volume depending on distance.
+
+ :type: float
+
+ .. attribute:: cone_angle_inner
+
+ The angle of the inner cone.
+
+ :type: float
+
+ .. attribute:: cone_angle_outer
+
+ The angle of the outer cone.
+
+ :type: float
+
+ .. attribute:: cone_volume_outer
+
+ The gain outside the outer cone (the gain in the outer cone will be interpolated between this value and the normal gain in the inner cone).
+
+ :type: float
+
+ .. method:: startSound()
+
+ Starts the sound.
+
+ :return: None
+
+ .. method:: pauseSound()
+
+ Pauses the sound.
+
+ :return: None
+
+ .. method:: stopSound()
+
+ Stops the sound.
+
+ :return: None
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_StateActuator.rst b/doc/python_api/rst/bge_types/bge.types.KX_StateActuator.rst
new file mode 100644
index 00000000000..c9d08457cc6
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_StateActuator.rst
@@ -0,0 +1,29 @@
+KX_StateActuator(SCA_IActuator)
+===============================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: KX_StateActuator(SCA_IActuator)
+
+ State actuator changes the state mask of parent object.
+
+ .. attribute:: operation
+
+ Type of bit operation to be applied on object state mask.
+
+ You can use one of :ref:`these constants <state-actuator-operation>`
+
+ :type: integer
+
+ .. attribute:: mask
+
+ Value that defines the bits that will be modified by the operation.
+
+ The bits that are 1 in the mask will be updated in the object state.
+
+ The bits that are 0 are will be left unmodified expect for the Copy operation which copies the mask to the object state.
+
+ :type: integer
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_SteeringActuator.rst b/doc/python_api/rst/bge_types/bge.types.KX_SteeringActuator.rst
new file mode 100644
index 00000000000..f0ce248f069
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_SteeringActuator.rst
@@ -0,0 +1,71 @@
+KX_SteeringActuator(SCA_IActuator)
+==================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: KX_SteeringActuator(SCA_IActuator)
+
+ Steering Actuator for navigation.
+
+ .. attribute:: behavior
+
+ The steering behavior to use.
+
+ :type: one of :ref:`these constants <logic-steering-actuator>`
+
+ .. attribute:: velocity
+
+ Velocity magnitude
+
+ :type: float
+
+ .. attribute:: acceleration
+
+ Max acceleration
+
+ :type: float
+
+ .. attribute:: turnspeed
+
+ Max turn speed
+
+ :type: float
+
+ .. attribute:: distance
+
+ Relax distance
+
+ :type: float
+
+ .. attribute:: target
+
+ Target object
+
+ :type: :class:`KX_GameObject`
+
+ .. attribute:: navmesh
+
+ Navigation mesh
+
+ :type: :class:`KX_GameObject`
+
+ .. attribute:: selfterminated
+
+ Terminate when target is reached
+
+ :type: boolean
+
+ .. attribute:: enableVisualization
+
+ Enable debug visualization
+
+ :type: boolean
+
+ .. attribute:: pathUpdatePeriod
+
+ Path update period
+
+ :type: int
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_TouchSensor.rst b/doc/python_api/rst/bge_types/bge.types.KX_TouchSensor.rst
new file mode 100644
index 00000000000..fd8f319f6f3
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_TouchSensor.rst
@@ -0,0 +1,41 @@
+KX_TouchSensor(SCA_ISensor)
+===========================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_ISensor`
+
+.. class:: KX_TouchSensor(SCA_ISensor)
+
+ Touch sensor detects collisions between objects.
+
+ .. attribute:: propName
+
+ The property or material to collide with.
+
+ :type: string
+
+ .. attribute:: useMaterial
+
+ Determines if the sensor is looking for a property or material. KX_True = Find material; KX_False = Find property.
+
+ :type: boolean
+
+ .. attribute:: usePulseCollision
+
+ When enabled, changes to the set of colliding objects generate a pulse.
+
+ :type: boolean
+
+ .. attribute:: hitObject
+
+ The last collided object. (read-only).
+
+ :type: :class:`KX_GameObject` or None
+
+ .. attribute:: hitObjectList
+
+ A list of colliding objects. (read-only).
+
+ :type: :class:`CListValue` of :class:`KX_GameObject`
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_TrackToActuator.rst b/doc/python_api/rst/bge_types/bge.types.KX_TrackToActuator.rst
new file mode 100644
index 00000000000..070243c6a05
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_TrackToActuator.rst
@@ -0,0 +1,39 @@
+KX_TrackToActuator(SCA_IActuator)
+=================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: KX_TrackToActuator(SCA_IActuator)
+
+ Edit Object actuator in Track To mode.
+
+ .. warning::
+
+ Track To Actuators will be ignored if at game start, the object to track to is invalid.
+
+ This will generate a warning in the console:
+
+ .. code-block:: none
+
+ GameObject 'Name' no object in EditObjectActuator 'ActuatorName'
+
+ .. attribute:: object
+
+ the object this actuator tracks.
+
+ :type: :class:`KX_GameObject` or None
+
+ .. attribute:: time
+
+ the time in frames with which to delay the tracking motion.
+
+ :type: integer
+
+ .. attribute:: use3D
+
+ the tracking motion to use 3D.
+
+ :type: boolean
+
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
new file mode 100644
index 00000000000..9340d33f8a9
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_VehicleWrapper.rst
@@ -0,0 +1,161 @@
+KX_VehicleWrapper(PyObjectPlus)
+===============================
+
+.. module:: bge.types
+
+base class --- :class:`PyObjectPlus`
+
+.. class:: KX_VehicleWrapper(PyObjectPlus)
+
+ KX_VehicleWrapper
+
+ TODO - description
+
+ .. method:: addWheel(wheel, attachPos, attachDir, 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 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.
+ :type axleDir: vector of 3 floats
+ :arg suspensionRestLength: TODO - Description
+ :type suspensionRestLength: float
+ :arg wheelRadius: The size of the wheel.
+ :type wheelRadius: float
+
+ .. method:: applyBraking(force, wheelIndex)
+
+ Apply a braking force to the specified wheel
+
+ :arg force: the brake force
+ :type force: float
+
+ :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
+
+ :arg force: the engine force
+ :type force: float
+
+ :arg wheelIndex: index of the wheel where the force needs to be applied
+ :type wheelIndex: integer
+
+ .. method:: getConstraintId()
+
+ Get the constraint ID
+
+ :return: the constraint id
+ :rtype: integer
+
+ .. method:: getConstraintType()
+
+ Returns the constraint type.
+
+ :return: constraint type
+ :rtype: integer
+
+ .. method:: getNumWheels()
+
+ Returns the number of wheels.
+
+ :return: the number of wheels for this vehicle
+ :rtype: integer
+
+ .. method:: getWheelOrientationQuaternion(wheelIndex)
+
+ Returns the wheel orientation as a quaternion.
+
+ :arg wheelIndex: the wheel index
+ :type wheelIndex: integer
+
+ :return: TODO Description
+ :rtype: TODO - type should be quat as per method name but from the code it looks like a matrix
+
+ .. method:: getWheelPosition(wheelIndex)
+
+ Returns the position of the specified wheel
+
+ :arg wheelIndex: the wheel index
+ :type wheelIndex: integer
+ :return: position vector
+ :rtype: list[x, y, z]
+
+ .. method:: getWheelRotation(wheelIndex)
+
+ Returns the rotation of the specified wheel
+
+ :arg wheelIndex: the wheel index
+ :type wheelIndex: integer
+
+ :return: the wheel rotation
+ :rtype: float
+
+ .. method:: setRollInfluence(rollInfluece, wheelIndex)
+
+ Set the specified wheel's roll influence.
+ The higher the roll influence the more the vehicle will tend to roll over in corners.
+
+ :arg rollInfluece: the wheel roll influence
+ :type rollInfluece: float
+
+ :arg wheelIndex: the wheel index
+ :type wheelIndex: integer
+
+ .. method:: setSteeringValue(steering, wheelIndex)
+
+ Set the specified wheel's steering
+
+ :arg steering: the wheel steering
+ :type steering: float
+
+ :arg wheelIndex: the wheel index
+ :type wheelIndex: integer
+
+ .. method:: setSuspensionCompression(compression, wheelIndex)
+
+ Set the specified wheel's compression
+
+ :arg compression: the wheel compression
+ :type compression: float
+
+ :arg wheelIndex: the wheel index
+ :type wheelIndex: integer
+
+ .. method:: setSuspensionDamping(damping, wheelIndex)
+
+ Set the specified wheel's damping
+
+ :arg damping: the wheel damping
+ :type damping: float
+
+ :arg wheelIndex: the wheel index
+ :type wheelIndex: integer
+
+ .. method:: setSuspensionStiffness(stiffness, wheelIndex)
+
+ Set the specified wheel's stiffness
+
+ :arg stiffness: the wheel stiffness
+ :type stiffness: float
+
+ :arg wheelIndex: the wheel index
+ :type wheelIndex: integer
+
+ .. method:: setTyreFriction(friction, wheelIndex)
+
+ Set the specified wheel's tyre friction
+
+ :arg friction: the tyre friction
+ :type friction: float
+
+ :arg wheelIndex: the wheel index
+ :type wheelIndex: integer
+
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
new file mode 100644
index 00000000000..9c0d1169d49
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_VertexProxy.rst
@@ -0,0 +1,209 @@
+KX_VertexProxy(SCA_IObject)
+===========================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IObject`
+
+.. class:: KX_VertexProxy(SCA_IObject)
+
+ A vertex holds position, UV, color and normal information.
+
+ Note:
+ The physics simulation is NOT currently updated - physics will not respond
+ to changes in the vertex position.
+
+ .. attribute:: XYZ
+
+ The position of the vertex.
+
+ :type: list [x, y, z]
+
+ .. attribute:: UV
+
+ The texture coordinates of the vertex.
+
+ :type: list [u, v]
+
+ .. attribute:: normal
+
+ The normal of the vertex.
+
+ :type: list [nx, ny, nz]
+
+ .. attribute:: color
+
+ The color of the vertex.
+
+ :type: list [r, g, b, a]
+
+ Black = [0.0, 0.0, 0.0, 1.0], White = [1.0, 1.0, 1.0, 1.0]
+
+ .. attribute:: x
+
+ The x coordinate of the vertex.
+
+ :type: float
+
+ .. attribute:: y
+
+ The y coordinate of the vertex.
+
+ :type: float
+
+ .. attribute:: z
+
+ The z coordinate of the vertex.
+
+ :type: float
+
+ .. attribute:: u
+
+ The u texture coordinate of the vertex.
+
+ :type: float
+
+ .. attribute:: v
+
+ The v texture coordinate of the vertex.
+
+ :type: float
+
+ .. attribute:: u2
+
+ The second u texture coordinate of the vertex.
+
+ :type: float
+
+ .. attribute:: v2
+
+ The second v texture coordinate of the vertex.
+
+ :type: float
+
+ .. attribute:: r
+
+ The red component of the vertex color. 0.0 <= r <= 1.0.
+
+ :type: float
+
+ .. attribute:: g
+
+ The green component of the vertex color. 0.0 <= g <= 1.0.
+
+ :type: float
+
+ .. attribute:: b
+
+ The blue component of the vertex color. 0.0 <= b <= 1.0.
+
+ :type: float
+
+ .. attribute:: a
+
+ The alpha component of the vertex color. 0.0 <= a <= 1.0.
+
+ :type: float
+
+ .. method:: getXYZ()
+
+ Gets the position of this vertex.
+
+ :return: this vertexes position in local coordinates.
+ :rtype: list [x, y, z]
+
+ .. method:: setXYZ(pos)
+
+ Sets the position of this vertex.
+
+ :type: list [x, y, z]
+
+ :arg pos: the new position for this vertex in local coordinates.
+
+ .. method:: getUV()
+
+ Gets the UV (texture) coordinates of this vertex.
+
+ :return: this vertexes UV (texture) coordinates.
+ :rtype: list [u, v]
+
+ .. method:: setUV(uv)
+
+ Sets the UV (texture) coordinates of this vertex.
+
+ :type: list [u, v]
+
+ .. method:: getUV2()
+
+ Gets the 2nd UV (texture) coordinates of this vertex.
+
+ :return: this vertexes UV (texture) coordinates.
+ :rtype: list [u, v]
+
+ .. method:: setUV2(uv, unit)
+
+ Sets the 2nd UV (texture) coordinates of this vertex.
+
+ :type: list [u, v]
+
+ :arg unit: optional argument, FLAT==1, SECOND_UV==2, defaults to SECOND_UV
+ :arg unit: integer
+
+ .. method:: getRGBA()
+
+ Gets the color of this vertex.
+
+ The color is represented as four bytes packed into an integer value. The color is
+ packed as RGBA.
+
+ Since Python offers no way to get each byte without shifting, you must use the struct module to
+ access color in an machine independent way.
+
+ Because of this, it is suggested you use the r, g, b and a attributes or the color attribute instead.
+
+ .. code-block:: python
+
+ import struct;
+ col = struct.unpack('4B', struct.pack('I', v.getRGBA()))
+ # col = (r, g, b, a)
+ # black = ( 0, 0, 0, 255)
+ # white = (255, 255, 255, 255)
+
+ :return: packed color. 4 byte integer with one byte per color channel in RGBA format.
+ :rtype: integer
+
+ .. method:: setRGBA(col)
+
+ Sets the color of this vertex.
+
+ See getRGBA() for the format of col, and its relevant problems. Use the r, g, b and a attributes
+ or the color attribute instead.
+
+ setRGBA() also accepts a four component list as argument col. The list represents the color as [r, g, b, a]
+ with black = [0.0, 0.0, 0.0, 1.0] and white = [1.0, 1.0, 1.0, 1.0]
+
+ .. code-block:: python
+
+ v.setRGBA(0xff0000ff) # Red
+ v.setRGBA(0xff00ff00) # Green on little endian, transparent purple on big endian
+ v.setRGBA([1.0, 0.0, 0.0, 1.0]) # Red
+ v.setRGBA([0.0, 1.0, 0.0, 1.0]) # Green on all platforms.
+
+ :arg col: the new color of this vertex in packed RGBA format.
+ :type col: integer or list [r, g, b, a]
+
+ .. method:: getNormal()
+
+ Gets the normal vector of this vertex.
+
+ :return: normalized normal vector.
+ :rtype: list [nx, ny, nz]
+
+ .. method:: setNormal(normal)
+
+ Sets the normal vector of this vertex.
+
+ :type: sequence of floats [r, g, b]
+
+ :arg normal: the new normal of this vertex.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_VisibilityActuator.rst b/doc/python_api/rst/bge_types/bge.types.KX_VisibilityActuator.rst
new file mode 100644
index 00000000000..4beb6539e0e
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.KX_VisibilityActuator.rst
@@ -0,0 +1,29 @@
+KX_VisibilityActuator(SCA_IActuator)
+====================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: KX_VisibilityActuator(SCA_IActuator)
+
+ Visibility Actuator.
+
+ .. attribute:: visibility
+
+ whether the actuator makes its parent object visible or invisible.
+
+ :type: boolean
+
+ .. attribute:: useOcclusion
+
+ whether the actuator makes its parent object an occluder or not.
+
+ :type: boolean
+
+ .. attribute:: useRecursion
+
+ whether the visibility/occlusion should be propagated to all children of the object.
+
+ :type: boolean
+
diff --git a/doc/python_api/rst/bge_types/bge.types.PyObjectPlus.rst b/doc/python_api/rst/bge_types/bge.types.PyObjectPlus.rst
new file mode 100644
index 00000000000..e035f457a96
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.PyObjectPlus.rst
@@ -0,0 +1,21 @@
+PyObjectPlus
+============
+
+.. module:: bge.types
+
+.. class:: PyObjectPlus
+
+ PyObjectPlus base class of most other types in the Game Engine.
+
+ .. attribute:: invalid
+
+ Test if the object has been freed by the game engine and is no longer valid.
+
+ Normally this is not a problem but when storing game engine data in the GameLogic module,
+ KX_Scenes or other KX_GameObjects its possible to hold a reference to invalid data.
+ Calling an attribute or method on an invalid object will raise a SystemError.
+
+ The invalid attribute allows testing for this case without exception handling.
+
+ :type: boolean
+
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
new file mode 100644
index 00000000000..291ee8426cf
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_2DFilterActuator.rst
@@ -0,0 +1,49 @@
+SCA_2DFilterActuator(SCA_IActuator)
+===================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: SCA_2DFilterActuator(SCA_IActuator)
+
+ Create, enable and disable 2D filters
+
+ The following properties don't have an immediate effect.
+ You must active the actuator to get the result.
+ The actuator is not persistent: it automatically stops itself after setting up the filter
+ but the filter remains active. To stop a filter you must activate the actuator with 'type'
+ set to :data:`~bge.logic.RAS_2DFILTER_DISABLED` or :data:`~bge.logic.RAS_2DFILTER_NOFILTER`.
+
+ .. attribute:: shaderText
+
+ shader source code for custom shader.
+
+ :type: string
+
+ .. attribute:: disableMotionBlur
+
+ action on motion blur: 0=enable, 1=disable.
+
+ :type: integer
+
+ .. attribute:: mode
+
+ Type of 2D filter, use one of :ref:`these constants <Two-D-FilterActuator-mode>`
+
+ :type: integer
+
+ .. attribute:: passNumber
+
+ order number of filter in the stack of 2D filters. Filters are executed in increasing order of passNb.
+
+ Only be one filter can be defined per passNb.
+
+ :type: integer (0-100)
+
+ .. attribute:: value
+
+ argument for motion blur filter.
+
+ :type: float (0.0-100.0)
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_ANDController.rst b/doc/python_api/rst/bge_types/bge.types.SCA_ANDController.rst
new file mode 100644
index 00000000000..0942f715231
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_ANDController.rst
@@ -0,0 +1,13 @@
+SCA_ANDController(SCA_IController)
+==================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IController`
+
+.. class:: SCA_ANDController(SCA_IController)
+
+ An AND controller activates only when all linked sensors are activated.
+
+ There are no special python methods for this controller.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_ActuatorSensor.rst b/doc/python_api/rst/bge_types/bge.types.SCA_ActuatorSensor.rst
new file mode 100644
index 00000000000..54916389298
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_ActuatorSensor.rst
@@ -0,0 +1,19 @@
+SCA_ActuatorSensor(SCA_ISensor)
+===============================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_ISensor`
+
+.. class:: SCA_ActuatorSensor(SCA_ISensor)
+
+ Actuator sensor detect change in actuator state of the parent object.
+ It generates a positive pulse if the corresponding actuator is activated
+ and a negative pulse if the actuator is deactivated.
+
+ .. attribute:: actuator
+
+ the name of the actuator that the sensor is monitoring.
+
+ :type: string
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_AlwaysSensor.rst b/doc/python_api/rst/bge_types/bge.types.SCA_AlwaysSensor.rst
new file mode 100644
index 00000000000..a217b114d62
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_AlwaysSensor.rst
@@ -0,0 +1,11 @@
+SCA_AlwaysSensor(SCA_ISensor)
+=============================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_ISensor`
+
+.. class:: SCA_AlwaysSensor(SCA_ISensor)
+
+ This sensor is always activated.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_DelaySensor.rst b/doc/python_api/rst/bge_types/bge.types.SCA_DelaySensor.rst
new file mode 100644
index 00000000000..ce2b8e52eec
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_DelaySensor.rst
@@ -0,0 +1,39 @@
+SCA_DelaySensor(SCA_ISensor)
+============================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_ISensor`
+
+.. class:: SCA_DelaySensor(SCA_ISensor)
+
+ The Delay sensor generates positive and negative triggers at precise time,
+ expressed in number of frames. The delay parameter defines the length of the initial OFF period. A positive trigger is generated at the end of this period.
+
+ The duration parameter defines the length of the ON period following the OFF period.
+ There is a negative trigger at the end of the ON period. If duration is 0, the sensor stays ON and there is no negative trigger.
+
+ The sensor runs the OFF-ON cycle once unless the repeat option is set: the OFF-ON cycle repeats indefinately (or the OFF cycle if duration is 0).
+
+ Use :class:`SCA_ISensor.reset` at any time to restart sensor.
+
+ .. attribute:: delay
+
+ length of the initial OFF period as number of frame, 0 for immediate trigger.
+
+ :type: integer.
+
+ .. attribute:: duration
+
+ length of the ON period in number of frame after the initial OFF period.
+
+ If duration is greater than 0, a negative trigger is sent at the end of the ON pulse.
+
+ :type: integer
+
+ .. attribute:: repeat
+
+ 1 if the OFF-ON cycle should be repeated indefinately, 0 if it should run once.
+
+ :type: integer
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_IActuator.rst b/doc/python_api/rst/bge_types/bge.types.SCA_IActuator.rst
new file mode 100644
index 00000000000..1432d5166ef
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_IActuator.rst
@@ -0,0 +1,11 @@
+SCA_IActuator(SCA_ILogicBrick)
+==============================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_ILogicBrick`
+
+.. class:: SCA_IActuator(SCA_ILogicBrick)
+
+ Base class for all actuator logic bricks.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_IController.rst b/doc/python_api/rst/bge_types/bge.types.SCA_IController.rst
new file mode 100644
index 00000000000..5eb225ed329
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_IController.rst
@@ -0,0 +1,55 @@
+SCA_IController(SCA_ILogicBrick)
+================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_ILogicBrick`
+
+.. class:: SCA_IController(SCA_ILogicBrick)
+
+ Base class for all controller logic bricks.
+
+ .. attribute:: state
+
+ The controllers state bitmask. This can be used with the GameObject's state to test if the controller is active.
+
+ :type: int bitmask
+
+ .. attribute:: sensors
+
+ A list of sensors linked to this controller.
+
+ :type: sequence supporting index/string lookups and iteration.
+
+ .. note::
+
+ The sensors are not necessarily owned by the same object.
+
+ .. note::
+
+ When objects are instanced in dupligroups links may be lost from objects outside the dupligroup.
+
+ .. attribute:: actuators
+
+ A list of actuators linked to this controller.
+
+ :type: sequence supporting index/string lookups and iteration.
+
+ .. note::
+
+ The sensors are not necessarily owned by the same object.
+
+ .. note::
+
+ When objects are instanced in dupligroups links may be lost from objects outside the dupligroup.
+
+ .. attribute:: useHighPriority
+
+ When set the controller executes always before all other controllers that dont have this set.
+
+ :type: boolen
+
+ .. note::
+
+ Order of execution between high priority controllers is not guaranteed.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_ILogicBrick.rst b/doc/python_api/rst/bge_types/bge.types.SCA_ILogicBrick.rst
new file mode 100644
index 00000000000..5ed44c4bb38
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_ILogicBrick.rst
@@ -0,0 +1,29 @@
+SCA_ILogicBrick(CValue)
+=======================
+
+.. module:: bge.types
+
+base class --- :class:`CValue`
+
+.. class:: SCA_ILogicBrick(CValue)
+
+ Base class for all logic bricks.
+
+ .. attribute:: executePriority
+
+ This determines the order controllers are evaluated, and actuators are activated (lower priority is executed first).
+
+ :type: executePriority: int
+
+ .. attribute:: owner
+
+ The game object this logic brick is attached to (read-only).
+
+ :type: :class:`KX_GameObject` or None in exceptional cases.
+
+ .. attribute:: name
+
+ The name of this logic brick (read-only).
+
+ :type: string
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_IObject.rst b/doc/python_api/rst/bge_types/bge.types.SCA_IObject.rst
new file mode 100644
index 00000000000..22065944542
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_IObject.rst
@@ -0,0 +1,11 @@
+SCA_IObject(CValue)
+===================
+
+.. module:: bge.types
+
+base class --- :class:`CValue`
+
+.. class:: SCA_IObject(CValue)
+
+ This class has no python functions
+
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
new file mode 100644
index 00000000000..9efd2e2d63a
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_ISensor.rst
@@ -0,0 +1,95 @@
+SCA_ISensor(SCA_ILogicBrick)
+============================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_ILogicBrick`
+
+.. class:: SCA_ISensor(SCA_ILogicBrick)
+
+ Base class for all sensor logic bricks.
+
+ .. attribute:: usePosPulseMode
+
+ Flag to turn positive pulse mode on and off.
+
+ :type: boolean
+
+ .. attribute:: useNegPulseMode
+
+ Flag to turn negative pulse mode on and off.
+
+ :type: boolean
+
+ .. attribute:: frequency
+
+ The frequency for pulse mode sensors.
+
+ :type: integer
+
+ .. attribute:: level
+
+ level Option whether to detect level or edge transition when entering a state.
+ It makes a difference only in case of logic state transition (state actuator).
+ A level detector will immediately generate a pulse, negative or positive
+ depending on the sensor condition, as soon as the state is activated.
+ A edge detector will wait for a state change before generating a pulse.
+ note: mutually exclusive with :data:`tap`, enabling will disable :data:`tap`.
+
+ :type: boolean
+
+ .. attribute:: tap
+
+ When enabled only sensors that are just activated will send a positive event,
+ after this they will be detected as negative by the controllers.
+ This will make a key thats held act as if its only tapped for an instant.
+ note: mutually exclusive with :data:`level`, enabling will disable :data:`level`.
+
+ :type: boolean
+
+ .. attribute:: invert
+
+ Flag to set if this sensor activates on positive or negative events.
+
+ :type: boolean
+
+ .. attribute:: triggered
+
+ True if this sensor brick is in a positive state. (read-only).
+
+ :type: boolean
+
+ .. attribute:: positive
+
+ True if this sensor brick is in a positive state. (read-only).
+
+ :type: boolean
+
+ .. attribute:: pos_ticks
+
+ The number of ticks since the last positive pulse (read-only).
+
+ :type: int
+
+ .. attribute:: neg_ticks
+
+ The number of ticks since the last negative pulse (read-only).
+
+ :type: int
+
+ .. attribute:: status
+
+ The status of the sensor (read-only): can be one of :ref:`these constants<sensor-status>`.
+
+ :type: int
+
+ .. note::
+
+ This convenient attribute combines the values of triggered and positive attributes.
+
+ .. method:: reset()
+
+ Reset sensor internal state, effect depends on the type of sensor and settings.
+
+ The sensor is put in its initial state as if it was just activated.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_JoystickSensor.rst b/doc/python_api/rst/bge_types/bge.types.SCA_JoystickSensor.rst
new file mode 100644
index 00000000000..5b6628f60be
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_JoystickSensor.rst
@@ -0,0 +1,133 @@
+SCA_JoystickSensor(SCA_ISensor)
+===============================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_ISensor`
+
+.. class:: SCA_JoystickSensor(SCA_ISensor)
+
+ This sensor detects player joystick events.
+
+ .. attribute:: axisValues
+
+ The state of the joysticks axis as a list of values :data:`numAxis` long. (read-only).
+
+ :type: list of ints.
+
+ Each specifying the value of an axis between -32767 and 32767 depending on how far the axis is pushed, 0 for nothing.
+ The first 2 values are used by most joysticks and gamepads for directional control. 3rd and 4th values are only on some joysticks and can be used for arbitary controls.
+
+ * left:[-32767, 0, ...]
+ * right:[32767, 0, ...]
+ * up:[0, -32767, ...]
+ * down:[0, 32767, ...]
+
+ .. attribute:: axisSingle
+
+ like :data:`axisValues` but returns a single axis value that is set by the sensor. (read-only).
+
+ :type: integer
+
+ .. note::
+
+ Only use this for "Single Axis" type sensors otherwise it will raise an error.
+
+ .. attribute:: hatValues
+
+ The state of the joysticks hats as a list of values :data:`numHats` long. (read-only).
+
+ :type: list of ints
+
+ Each specifying the direction of the hat from 1 to 12, 0 when inactive.
+
+ Hat directions are as follows...
+
+ * 0:None
+ * 1:Up
+ * 2:Right
+ * 4:Down
+ * 8:Left
+ * 3:Up - Right
+ * 6:Down - Right
+ * 12:Down - Left
+ * 9:Up - Left
+
+ .. attribute:: hatSingle
+
+ Like :data:`hatValues` but returns a single hat direction value that is set by the sensor. (read-only).
+
+ :type: integer
+
+ .. attribute:: numAxis
+
+ The number of axes for the joystick at this index. (read-only).
+
+ :type: integer
+
+ .. attribute:: numButtons
+
+ The number of buttons for the joystick at this index. (read-only).
+
+ :type: integer
+
+ .. attribute:: numHats
+
+ The number of hats for the joystick at this index. (read-only).
+
+ :type: integer
+
+ .. attribute:: connected
+
+ True if a joystick is connected at this joysticks index. (read-only).
+
+ :type: boolean
+
+ .. attribute:: index
+
+ The joystick index to use (from 0 to 7). The first joystick is always 0.
+
+ :type: integer
+
+ .. attribute:: threshold
+
+ Axis threshold. Joystick axis motion below this threshold wont trigger an event. Use values between (0 and 32767), lower values are more sensitive.
+
+ :type: integer
+
+ .. attribute:: button
+
+ The button index the sensor reacts to (first button = 0). When the "All Events" toggle is set, this option has no effect.
+
+ :type: integer
+
+ .. attribute:: axis
+
+ The axis this sensor reacts to, as a list of two values [axisIndex, axisDirection]
+
+ * axisIndex: the axis index to use when detecting axis movement, 1=primary directional control, 2=secondary directional control.
+ * axisDirection: 0=right, 1=up, 2=left, 3=down.
+
+ :type: [integer, integer]
+
+ .. attribute:: hat
+
+ The hat the sensor reacts to, as a list of two values: [hatIndex, hatDirection]
+
+ * hatIndex: the hat index to use when detecting hat movement, 1=primary hat, 2=secondary hat (4 max).
+ * hatDirection: 1-12.
+
+ :type: [integer, integer]
+
+ .. method:: getButtonActiveList()
+
+ :return: A list containing the indicies of the currently pressed buttons.
+ :rtype: list
+
+ .. method:: getButtonStatus(buttonIndex)
+
+ :arg buttonIndex: the button index, 0=first button
+ :type buttonIndex: integer
+ :return: The current pressed state of the specified button.
+ :rtype: boolean
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_KeyboardSensor.rst b/doc/python_api/rst/bge_types/bge.types.SCA_KeyboardSensor.rst
new file mode 100644
index 00000000000..91613068ad0
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_KeyboardSensor.rst
@@ -0,0 +1,64 @@
+SCA_KeyboardSensor(SCA_ISensor)
+===============================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_ISensor`
+
+.. class:: SCA_KeyboardSensor(SCA_ISensor)
+
+ A keyboard sensor detects player key presses.
+
+ See module :mod:`bge.events` for keycode values.
+
+ .. attribute:: key
+
+ The key code this sensor is looking for.
+
+ :type: keycode from :mod:`bge.events` module
+
+ .. attribute:: hold1
+
+ The key code for the first modifier this sensor is looking for.
+
+ :type: keycode from :mod:`bge.events` module
+
+ .. attribute:: hold2
+
+ The key code for the second modifier this sensor is looking for.
+
+ :type: keycode from :mod:`bge.events` module
+
+ .. attribute:: toggleProperty
+
+ The name of the property that indicates whether or not to log keystrokes as a string.
+
+ :type: string
+
+ .. attribute:: targetProperty
+
+ The name of the property that receives keystrokes in case in case a string is logged.
+
+ :type: string
+
+ .. attribute:: useAllKeys
+
+ Flag to determine whether or not to accept all keys.
+
+ :type: boolean
+
+ .. attribute:: events
+
+ a list of pressed keys that have either been pressed, or just released, or are active this frame. (read-only).
+
+ :type: list [[:ref:`keycode<keyboard-keys>`, :ref:`status<input-status>`], ...]
+
+ .. method:: getKeyStatus(keycode)
+
+ Get the status of a key.
+
+ :arg keycode: The code that represents the key you want to get the state of, use one of :ref:`these constants<keyboard-keys>`
+ :type keycode: integer
+ :return: The state of the given key, can be one of :ref:`these constants<input-status>`
+ :rtype: int
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_MouseSensor.rst b/doc/python_api/rst/bge_types/bge.types.SCA_MouseSensor.rst
new file mode 100644
index 00000000000..bbc695e4cbf
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_MouseSensor.rst
@@ -0,0 +1,39 @@
+SCA_MouseSensor(SCA_ISensor)
+============================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_ISensor`
+
+.. class:: SCA_MouseSensor(SCA_ISensor)
+
+ Mouse Sensor logic brick.
+
+ .. attribute:: position
+
+ current [x, y] coordinates of the mouse, in frame coordinates (pixels).
+
+ :type: [integer, interger]
+
+ .. attribute:: mode
+
+ sensor mode.
+
+ :type: integer
+
+ * KX_MOUSESENSORMODE_LEFTBUTTON(1)
+ * KX_MOUSESENSORMODE_MIDDLEBUTTON(2)
+ * KX_MOUSESENSORMODE_RIGHTBUTTON(3)
+ * KX_MOUSESENSORMODE_WHEELUP(4)
+ * KX_MOUSESENSORMODE_WHEELDOWN(5)
+ * KX_MOUSESENSORMODE_MOVEMENT(6)
+
+ .. method:: getButtonStatus(button)
+
+ Get the mouse button status.
+
+ :arg button: The code that represents the key you want to get the state of, use one of :ref:`these constants<mouse-keys>`
+ :type button: int
+ :return: The state of the given key, can be one of :ref:`these constants<input-status>`
+ :rtype: int
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_NANDController.rst b/doc/python_api/rst/bge_types/bge.types.SCA_NANDController.rst
new file mode 100644
index 00000000000..4bd67fb22ee
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_NANDController.rst
@@ -0,0 +1,13 @@
+SCA_NANDController(SCA_IController)
+===================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IController`
+
+.. class:: SCA_NANDController(SCA_IController)
+
+ An NAND controller activates when all linked sensors are not active.
+
+ There are no special python methods for this controller.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_NORController.rst b/doc/python_api/rst/bge_types/bge.types.SCA_NORController.rst
new file mode 100644
index 00000000000..5a567c84ece
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_NORController.rst
@@ -0,0 +1,13 @@
+SCA_NORController(SCA_IController)
+==================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IController`
+
+.. class:: SCA_NORController(SCA_IController)
+
+ An NOR controller activates only when all linked sensors are de-activated.
+
+ There are no special python methods for this controller.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_ORController.rst b/doc/python_api/rst/bge_types/bge.types.SCA_ORController.rst
new file mode 100644
index 00000000000..ed57b0dbaf2
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_ORController.rst
@@ -0,0 +1,13 @@
+SCA_ORController(SCA_IController)
+=================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IController`
+
+.. class:: SCA_ORController(SCA_IController)
+
+ An OR controller activates when any connected sensor activates.
+
+ There are no special python methods for this controller.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_PropertyActuator.rst b/doc/python_api/rst/bge_types/bge.types.SCA_PropertyActuator.rst
new file mode 100644
index 00000000000..36a4ea7fefe
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_PropertyActuator.rst
@@ -0,0 +1,29 @@
+SCA_PropertyActuator(SCA_IActuator)
+===================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: SCA_PropertyActuator(SCA_IActuator)
+
+ Property Actuator
+
+ .. attribute:: propName
+
+ the property on which to operate.
+
+ :type: string
+
+ .. attribute:: value
+
+ the value with which the actuator operates.
+
+ :type: string
+
+ .. attribute:: mode
+
+ TODO - add constants to game logic dict!.
+
+ :type: integer
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_PropertySensor.rst b/doc/python_api/rst/bge_types/bge.types.SCA_PropertySensor.rst
new file mode 100644
index 00000000000..3c41e4679db
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_PropertySensor.rst
@@ -0,0 +1,41 @@
+SCA_PropertySensor(SCA_ISensor)
+===============================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_ISensor`
+
+.. class:: SCA_PropertySensor(SCA_ISensor)
+
+ Activates when the game object property matches.
+
+ .. attribute:: mode
+
+ Type of check on the property. Can be one of :ref:`these constants <logic-property-sensor>`
+
+ :type: integer.
+
+ .. attribute:: propName
+
+ the property the sensor operates.
+
+ :type: string
+
+ .. attribute:: value
+
+ the value with which the sensor compares to the value of the property.
+
+ :type: string
+
+ .. attribute:: min
+
+ the minimum value of the range used to evaluate the property when in interval mode.
+
+ :type: string
+
+ .. attribute:: max
+
+ the maximum value of the range used to evaluate the property when in interval mode.
+
+ :type: string
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_PythonController.rst b/doc/python_api/rst/bge_types/bge.types.SCA_PythonController.rst
new file mode 100644
index 00000000000..a00e9c29ad4
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_PythonController.rst
@@ -0,0 +1,48 @@
+SCA_PythonController(SCA_IController)
+=====================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IController`
+
+.. class:: SCA_PythonController(SCA_IController)
+
+ A Python controller uses a Python script to activate it's actuators,
+ based on it's sensors.
+
+ .. attribute:: script
+
+ The value of this variable depends on the execution methid.
+
+ * When 'Script' execution mode is set this value contains the entire python script as a single string (not the script name as you might expect) which can be modified to run different scripts.
+ * When 'Module' execution mode is set this value will contain a single line string - module name and function "module.func" or "package.modile.func" where the module names are python textblocks or external scripts.
+
+ :type: string
+
+ .. note::
+
+ Once this is set the script name given for warnings will remain unchanged.
+
+ .. attribute:: mode
+
+ the execution mode for this controller (read-only).
+
+ * Script: 0, Execite the :data:`script` as a python code.
+ * Module: 1, Execite the :data:`script` as a module and function.
+
+ :type: integer
+
+ .. method:: activate(actuator)
+
+ Activates an actuator attached to this controller.
+
+ :arg actuator: The actuator to operate on.
+ :type actuator: actuator or the actuator name as a string
+
+ .. method:: deactivate(actuator)
+
+ Deactivates an actuator attached to this controller.
+
+ :arg actuator: The actuator to operate on.
+ :type actuator: actuator or the actuator name as a string
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_PythonJoystick.rst b/doc/python_api/rst/bge_types/bge.types.SCA_PythonJoystick.rst
new file mode 100644
index 00000000000..2b97b5939e2
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_PythonJoystick.rst
@@ -0,0 +1,75 @@
+SCA_PythonJoystick(PyObjectPlus)
+================================
+
+.. module:: bge.types
+
+base class --- :class:`PyObjectPlus`
+
+.. class:: SCA_PythonJoystick(PyObjectPlus)
+
+ A Python interface to a joystick.
+
+ .. attribute:: name
+
+ The name assigned to the joystick by the operating system. (read-only)
+
+ :type: string
+
+ .. attribute:: activeButtons
+
+ A list of active button values. (read-only)
+
+ :type: list
+
+ .. attribute:: axisValues
+
+ The state of the joysticks axis as a list of values :data:`numAxis` long. (read-only).
+
+ :type: list of ints.
+
+ Each specifying the value of an axis between -1.0 and 1.0 depending on how far the axis is pushed, 0 for nothing.
+ The first 2 values are used by most joysticks and gamepads for directional control. 3rd and 4th values are only on some joysticks and can be used for arbitary controls.
+
+ * left:[-1.0, 0.0, ...]
+ * right:[1.0, 0.0, ...]
+ * up:[0.0, -1.0, ...]
+ * down:[0.0, 1.0, ...]
+
+ .. attribute:: hatValues
+
+ The state of the joysticks hats as a list of values :data:`numHats` long. (read-only).
+
+ :type: list of ints
+
+ Each specifying the direction of the hat from 1 to 12, 0 when inactive.
+
+ Hat directions are as follows...
+
+ * 0:None
+ * 1:Up
+ * 2:Right
+ * 4:Down
+ * 8:Left
+ * 3:Up - Right
+ * 6:Down - Right
+ * 12:Down - Left
+ * 9:Up - Left
+
+ .. attribute:: numAxis
+
+ The number of axes for the joystick at this index. (read-only).
+
+ :type: integer
+
+ .. attribute:: numButtons
+
+ The number of buttons for the joystick at this index. (read-only).
+
+ :type: integer
+
+ .. attribute:: numHats
+
+ The number of hats for the joystick at this index. (read-only).
+
+ :type: integer
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_PythonKeyboard.rst b/doc/python_api/rst/bge_types/bge.types.SCA_PythonKeyboard.rst
new file mode 100644
index 00000000000..6cfef2f80f1
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_PythonKeyboard.rst
@@ -0,0 +1,37 @@
+SCA_PythonKeyboard(PyObjectPlus)
+================================
+
+.. module:: bge.types
+
+base class --- :class:`PyObjectPlus`
+
+.. class:: SCA_PythonKeyboard(PyObjectPlus)
+
+ The current keyboard.
+
+ .. attribute:: events
+
+ A dictionary containing the status of each keyboard event or key. (read-only).
+
+ :type: dictionary {:ref:`keycode<keyboard-keys>`::ref:`status<input-status>`, ...}
+
+ .. attribute:: active_events
+
+ A dictionary containing the status of only the active keyboard events or keys. (read-only).
+
+ :type: dictionary {:ref:`keycode<keyboard-keys>`::ref:`status<input-status>`, ...}
+
+
+ .. function:: getClipboard()
+
+ Gets the clipboard text.
+
+ :rtype: string
+
+ .. function:: setClipboard(text)
+
+ Sets the clipboard text.
+
+ :arg text: New clipboard text
+ :type text: string
+
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
new file mode 100644
index 00000000000..b1c6e5d1487
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_PythonMouse.rst
@@ -0,0 +1,35 @@
+SCA_PythonMouse(PyObjectPlus)
+=============================
+
+.. module:: bge.types
+
+base class --- :class:`PyObjectPlus`
+
+.. class:: SCA_PythonMouse(PyObjectPlus)
+
+ The current mouse.
+
+ .. attribute:: events
+
+ a dictionary containing the status of each mouse event. (read-only).
+
+ :type: dictionary {:ref:`keycode<mouse-keys>`::ref:`status<input-status>`, ...}
+
+ .. attribute:: active_events
+
+ a dictionary containing the status of only the active mouse events. (read-only).
+
+ :type: dictionary {:ref:`keycode<mouse-keys>`::ref:`status<input-status>`, ...}
+
+ .. attribute:: position
+
+ The normalized x and y position of the mouse cursor.
+
+ :type: list [x, y]
+
+ .. attribute:: visible
+
+ The visibility of the mouse cursor.
+
+ :type: boolean
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_RandomActuator.rst b/doc/python_api/rst/bge_types/bge.types.SCA_RandomActuator.rst
new file mode 100644
index 00000000000..68357229262
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_RandomActuator.rst
@@ -0,0 +1,127 @@
+SCA_RandomActuator(SCA_IActuator)
+=================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IActuator`
+
+.. class:: SCA_RandomActuator(SCA_IActuator)
+
+ Random Actuator
+
+ .. attribute:: seed
+
+ Seed of the random number generator.
+
+ :type: integer.
+
+ Equal seeds produce equal series. If the seed is 0, the generator will produce the same value on every call.
+
+ .. attribute:: para1
+
+ the first parameter of the active distribution.
+
+ :type: float, read-only.
+
+ Refer to the documentation of the generator types for the meaning of this value.
+
+ .. attribute:: para2
+
+ the second parameter of the active distribution.
+
+ :type: float, read-only
+
+ Refer to the documentation of the generator types for the meaning of this value.
+
+ .. attribute:: distribution
+
+ Distribution type. (read-only). Can be one of :ref:`these constants <logic-random-distributions>`
+
+ :type: integer
+
+ .. attribute:: propName
+
+ the name of the property to set with the random value.
+
+ :type: string
+
+ If the generator and property types do not match, the assignment is ignored.
+
+ .. method:: setBoolConst(value)
+
+ Sets this generator to produce a constant boolean value.
+
+ :arg value: The value to return.
+ :type value: boolean
+
+ .. method:: setBoolUniform()
+
+ Sets this generator to produce a uniform boolean distribution.
+
+ The generator will generate True or False with 50% chance.
+
+ .. method:: setBoolBernouilli(value)
+
+ Sets this generator to produce a Bernouilli distribution.
+
+ :arg value: Specifies the proportion of False values to produce.
+
+ * 0.0: Always generate True
+ * 1.0: Always generate False
+ :type value: float
+
+ .. method:: setIntConst(value)
+
+ Sets this generator to always produce the given value.
+
+ :arg value: the value this generator produces.
+ :type value: integer
+
+ .. method:: setIntUniform(lower_bound, upper_bound)
+
+ Sets this generator to produce a random value between the given lower and
+ upper bounds (inclusive).
+
+ :type lower_bound: integer
+ :type upper_bound: integer
+
+ .. method:: setIntPoisson(value)
+
+ Generate a Poisson-distributed number.
+
+ This performs a series of Bernouilli tests with parameter value.
+ It returns the number of tries needed to achieve succes.
+
+ :type value: float
+
+ .. method:: setFloatConst(value)
+
+ Always generate the given value.
+
+ :type value: float
+
+ .. method:: setFloatUniform(lower_bound, upper_bound)
+
+ Generates a random float between lower_bound and upper_bound with a
+ uniform distribution.
+
+ :type lower_bound: float
+ :type upper_bound: float
+
+ .. method:: setFloatNormal(mean, standard_deviation)
+
+ Generates a random float from the given normal distribution.
+
+ :arg mean: The mean (average) value of the generated numbers
+ :type mean: float
+ :arg standard_deviation: The standard deviation of the generated numbers.
+ :type standard_deviation: float
+
+ .. method:: setFloatNegativeExponential(half_life)
+
+ Generate negative-exponentially distributed numbers.
+
+ The half-life 'time' is characterized by half_life.
+
+ :type half_life: float
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_RandomSensor.rst b/doc/python_api/rst/bge_types/bge.types.SCA_RandomSensor.rst
new file mode 100644
index 00000000000..05e61ccf118
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_RandomSensor.rst
@@ -0,0 +1,23 @@
+SCA_RandomSensor(SCA_ISensor)
+=============================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_ISensor`
+
+.. class:: SCA_RandomSensor(SCA_ISensor)
+
+ This sensor activates randomly.
+
+ .. attribute:: lastDraw
+
+ The seed of the random number generator.
+
+ :type: integer
+
+ .. attribute:: seed
+
+ The seed of the random number generator.
+
+ :type: integer
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_XNORController.rst b/doc/python_api/rst/bge_types/bge.types.SCA_XNORController.rst
new file mode 100644
index 00000000000..d0235f29a20
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_XNORController.rst
@@ -0,0 +1,13 @@
+SCA_XNORController(SCA_IController)
+===================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IController`
+
+.. class:: SCA_XNORController(SCA_IController)
+
+ An XNOR controller activates when all linked sensors are the same (activated or inative).
+
+ There are no special python methods for this controller.
+
diff --git a/doc/python_api/rst/bge_types/bge.types.SCA_XORController.rst b/doc/python_api/rst/bge_types/bge.types.SCA_XORController.rst
new file mode 100644
index 00000000000..98ccf142f63
--- /dev/null
+++ b/doc/python_api/rst/bge_types/bge.types.SCA_XORController.rst
@@ -0,0 +1,13 @@
+SCA_XORController(SCA_IController)
+==================================
+
+.. module:: bge.types
+
+base class --- :class:`SCA_IController`
+
+.. class:: SCA_XORController(SCA_IController)
+
+ An XOR controller activates when there is the input is mixed, but not when all are on or off.
+
+ There are no special python methods for this controller.
+
diff --git a/doc/python_api/rst/info_tutorial_addon.rst b/doc/python_api/rst/info_tutorial_addon.rst
index 2a101041227..5637cf2f638 100644
--- a/doc/python_api/rst/info_tutorial_addon.rst
+++ b/doc/python_api/rst/info_tutorial_addon.rst
@@ -486,16 +486,14 @@ using :kbd:`Ctrl-Shift-Space` as the key shortcut to activate it.
kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True)
kmi.properties.total = 4
- addon_keymaps.append(km)
+ addon_keymaps.append((km, kmi))
def unregister():
# handle the keymap
- wm = bpy.context.window_manager
- for km in addon_keymaps:
- wm.keyconfigs.addon.keymaps.remove(km)
- # clear the list
+ for km, kmi in addon_keymaps:
+ km.keymap_items.remove(kmi)
addon_keymaps.clear()
@@ -568,18 +566,16 @@ Bringing it all together
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)
+ addon_keymaps.append((km, kmi))
def unregister():
bpy.utils.unregister_class(ObjectCursorArray)
bpy.types.VIEW3D_MT_object.remove(menu_func)
# handle the keymap
- wm = bpy.context.window_manager
- for km in addon_keymaps:
- wm.keyconfigs.addon.keymaps.remove(km)
- # clear the list
- del addon_keymaps[:]
+ for km, kmi in addon_keymaps:
+ km.keymap_items.remove(kmi)
+ addon_keymaps.clear()
if __name__ == "__main__":
diff --git a/doc/python_api/rst_from_bmesh_opdefines.py b/doc/python_api/rst_from_bmesh_opdefines.py
index c1b6643389d..3776ef7ce56 100644
--- a/doc/python_api/rst_from_bmesh_opdefines.py
+++ b/doc/python_api/rst_from_bmesh_opdefines.py
@@ -65,10 +65,10 @@ def main():
fsrc = open(FILE_OP_DEFINES_C, 'r', encoding="utf-8")
blocks = []
-
+
is_block = False
is_comment = False # /* global comments only */
-
+
comment_ctx = None
block_ctx = None
@@ -82,7 +82,7 @@ def main():
elif l.strip().startswith("/*"):
is_comment = True
comment_ctx = []
-
+
if is_block:
if l.strip().startswith("//"):
pass
@@ -93,11 +93,11 @@ def main():
l = l[:cpp_comment]
block_ctx.append(l)
-
+
if l.strip() == "};":
is_block = False
comment_ctx = None
-
+
if is_comment:
c_comment_start = l.find("/*")
if c_comment_start != -1:
@@ -113,7 +113,6 @@ def main():
fsrc.close()
del fsrc
-
# namespace hack
vars = (
"BMO_OP_SLOT_ELEMENT_BUF",
@@ -124,7 +123,7 @@ def main():
"BMO_OP_SLOT_VEC",
"BMO_OP_SLOT_PTR",
"BMO_OP_SLOT_MAPPING",
-
+
"BMO_OP_SLOT_SUBTYPE_MAP_ELEM",
"BMO_OP_SLOT_SUBTYPE_MAP_BOOL",
"BMO_OP_SLOT_SUBTYPE_MAP_INT",
@@ -157,23 +156,23 @@ def main():
for comment, b in blocks:
# magic, translate into python
b[0] = b[0].replace("static BMOpDefine ", "")
-
+
for i, l in enumerate(b):
l = l.strip()
l = l.replace("{", "(")
l = l.replace("}", ")")
-
+
if l.startswith("/*"):
l = l.replace("/*", "'''own <")
else:
l = l.replace("/*", "'''inline <")
l = l.replace("*/", ">''',")
-
+
# exec func. eg: bmo_rotate_edges_exec,
if l.startswith("bmo_") and l.endswith("_exec,"):
l = "None,"
b[i] = l
-
+
#for l in b:
# print(l)
@@ -182,7 +181,7 @@ def main():
"__file__": "generated",
"__name__": "__main__",
}
-
+
global_namespace.update(vars_dict)
text_a, text_b = text.split("=", 1)
@@ -191,7 +190,6 @@ def main():
# print(global_namespace["result"])
blocks_py.append((comment, global_namespace["result"]))
-
# ---------------------
# Now convert into rst.
fout = open(OUT_RST, 'w', encoding="utf-8")
@@ -217,7 +215,7 @@ def main():
args_out_index[:] = [i for (i, a) in enumerate(args_out) if type(a) == tuple]
fw(".. function:: %s(bm, %s)\n\n" % (b[0], ", ".join([args_in[i][0] for i in args_in_index])))
-
+
# -- wash the comment
comment_washed = []
for i, l in enumerate(comment):
@@ -236,7 +234,6 @@ def main():
fw("\n")
# -- done
-
# get the args
def get_args_wash(args, args_index, is_ret):
args_wash = []
@@ -268,7 +265,7 @@ def main():
comment_next = comment_next[8:-1] # strip inline <...>
else:
comment_next = ""
-
+
comment = ""
if comment_prev:
comment += comment_prev.strip()
@@ -304,18 +301,21 @@ def main():
elif tp == BMO_OP_SLOT_ELEMENT_BUF:
assert(tp_sub is not None)
-
+
ls = []
- if tp_sub & BM_VERT: ls.append(":class:`bmesh.types.BMVert`")
- if tp_sub & BM_EDGE: ls.append(":class:`bmesh.types.BMEdge`")
- if tp_sub & BM_FACE: ls.append(":class:`bmesh.types.BMFace`")
+ if tp_sub & BM_VERT:
+ ls.append(":class:`bmesh.types.BMVert`")
+ if tp_sub & BM_EDGE:
+ ls.append(":class:`bmesh.types.BMEdge`")
+ if tp_sub & BM_FACE:
+ ls.append(":class:`bmesh.types.BMFace`")
assert(ls) # must be at least one
if tp_sub & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE:
tp_str = "/".join(ls)
else:
tp_str = ("list of (%s)" % ", ".join(ls))
-
+
del ls
elif tp == BMO_OP_SLOT_MAPPING:
if tp_sub & BMO_OP_SLOT_SUBTYPE_MAP_EMPTY:
@@ -356,21 +356,21 @@ def main():
fw(" :arg %s: %s\n" % (name, comment))
fw(" :type %s: %s\n" % (name, tp))
-
+
if args_out_wash:
fw(" :return:\n\n")
-
+
for (name, tp, comment) in args_out_wash:
assert(name.endswith(".out"))
name = name[:-4]
fw(" - ``%s``: %s\n\n" % (name, comment))
fw(" **type** %s\n" % tp)
-
+
fw("\n")
fw(" :rtype: dict with string keys\n")
fw("\n\n")
-
+
fout.close()
del fout
print(OUT_RST)
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index 441a6c04efe..72e92e5855f 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -262,6 +262,7 @@ else:
"mathutils",
"mathutils.geometry",
"mathutils.noise",
+ "Freestyle",
]
# ------
@@ -449,6 +450,7 @@ if ARGS.sphinx_build_pdf:
ClassMethodDescriptorType = type(dict.__dict__['fromkeys'])
MethodDescriptorType = type(dict.get)
GetSetDescriptorType = type(int.real)
+StaticMethodType = type(staticmethod(lambda: None))
from types import MemberDescriptorType
_BPY_STRUCT_FAKE = "bpy_struct"
@@ -612,6 +614,10 @@ def pyfunc2sphinx(ident, fw, identifier, py_func, is_class=True):
'''
function or class method to sphinx
'''
+
+ if type(py_func) == type(bpy.types.Space.draw_handler_add):
+ return
+
arg_str = inspect.formatargspec(*inspect.getargspec(py_func))
if not is_class:
@@ -692,6 +698,8 @@ def pyprop2sphinx(ident, fw, identifier, py_prop):
write_indented_lines(ident + " ", fw, py_prop.__doc__)
if py_prop.fset is None:
fw(ident + " (readonly)\n\n")
+ else:
+ fw("\n")
def pymodule2sphinx(basepath, module_name, module, title):
@@ -909,6 +917,12 @@ def pymodule2sphinx(basepath, module_name, module, title):
if type(descr) == GetSetDescriptorType:
py_descr2sphinx(" ", fw, descr, module_name, type_name, key)
+ for key, descr in descr_items:
+ if type(descr) == StaticMethodType:
+ descr = getattr(value, key)
+ write_indented_lines(" ", fw, descr.__doc__ or "Undocumented", False)
+ fw("\n")
+
fw("\n\n")
file.close()
@@ -980,6 +994,7 @@ context_type_map = {
"world": ("World", False),
}
+
def pycontext2sphinx(basepath):
# Only use once. very irregular
@@ -1007,7 +1022,6 @@ def pycontext2sphinx(basepath):
"sequencer_context_dir",
)
-
unique = set()
blend_cdll = ctypes.CDLL("")
for ctx_str in context_strings:
@@ -1477,7 +1491,9 @@ def write_sphinx_conf_py(basepath):
def execfile(filepath):
global_namespace = {"__file__": filepath, "__name__": "__main__"}
- exec(compile(open(filepath).read(), filepath, 'exec'), global_namespace)
+ file_handle = open(filepath)
+ exec(compile(file_handle.read(), filepath, 'exec'), global_namespace)
+ file_handle.close()
def write_rst_contents(basepath):
@@ -1539,7 +1555,7 @@ def write_rst_contents(basepath):
# mathutils
"mathutils", "mathutils.geometry", "mathutils.noise",
# misc
- "bgl", "blf", "gpu", "aud", "bpy_extras",
+ "Freestyle", "bgl", "blf", "gpu", "aud", "bpy_extras",
# bmesh, submodules are in own page
"bmesh",
)
@@ -1687,6 +1703,7 @@ def write_rst_importable_modules(basepath):
"mathutils" : "Math Types & Utilities",
"mathutils.geometry": "Geometry Utilities",
"mathutils.noise" : "Noise Utilities",
+ "Freestyle" : "Freestyle Data Types & Operators",
}
for mod_name, mod_descr in importable_modules.items():
if mod_name not in EXCLUDE_MODULES:
@@ -1704,7 +1721,6 @@ def copy_handwritten_rsts(basepath):
# TODO put this docs in blender's code and use import as per modules above
handwritten_modules = [
- "bge.types",
"bge.logic",
"bge.render",
"bge.texture",
@@ -1723,6 +1739,14 @@ def copy_handwritten_rsts(basepath):
# copy2 keeps time/date stamps
shutil.copy2(os.path.join(RST_DIR, "%s.rst" % mod_name), basepath)
+ if "bge.types" not in EXCLUDE_MODULES:
+ shutil.copy2(os.path.join(RST_DIR, "bge.types.rst"), basepath)
+
+ bge_types_dir = os.path.join(RST_DIR, "bge_types")
+
+ for i in os.listdir(bge_types_dir):
+ shutil.copy2(os.path.join(bge_types_dir, i), basepath)
+
# changelog
shutil.copy2(os.path.join(RST_DIR, "change_log.rst"), basepath)
@@ -1810,8 +1834,19 @@ def refactor_sphinx_log(sphinx_logfile):
refactored_logfile.write("%-12s %s\n %s\n" % log)
+def monkey_patch():
+ filepath = os.path.join(SCRIPT_DIR, "sphinx_doc_gen_monkeypatch.py")
+ global_namespace = {"__file__": filepath, "__name__": "__main__"}
+ file = open(filepath, 'rb')
+ exec(compile(file.read(), filepath, 'exec'), global_namespace)
+ file.close()
+
+
def main():
+ # first monkey patch to load in fake members
+ monkey_patch()
+
# eventually, create the dirs
for dir_path in [ARGS.output_dir, SPHINX_IN]:
if not os.path.exists(dir_path):
diff --git a/doc/python_api/sphinx_doc_gen.sh b/doc/python_api/sphinx_doc_gen.sh
index 92461961920..14919f678be 100755
--- a/doc/python_api/sphinx_doc_gen.sh
+++ b/doc/python_api/sphinx_doc_gen.sh
@@ -32,8 +32,7 @@ blender_version_char=$(grep BLENDER_VERSION_CHAR $blender_srcdir/source/blender/
blender_version_cycle=$(grep BLENDER_VERSION_CYCLE $blender_srcdir/source/blender/blenkernel/BKE_blender.h | awk '{print $3}')
blender_subversion=$(grep BLENDER_SUBVERSION $blender_srcdir/source/blender/blenkernel/BKE_blender.h | awk '{print $3}')
-if [ "$blender_version_cycle" == "release" ]
-then
+if [ "$blender_version_cycle" == "release" ] ; then
BLENDER_VERSION=$(expr $blender_version / 100)_$(expr $blender_version % 100)$blender_version_char"_release"
else
BLENDER_VERSION=$(expr $blender_version / 100)_$(expr $blender_version % 100)_$blender_subversion
@@ -109,6 +108,11 @@ if $DO_UPLOAD ; then
# better redirect
ssh $SSH_USER@emo.blender.org 'echo "<html><head><title>Redirecting...</title><meta http-equiv=\"REFRESH\" content=\"0;url=../blender_python_api_'$BLENDER_VERSION'/\"></head><body>Redirecting...</body></html>" > '$SSH_UPLOAD'/250PythonDoc/index.html'
+ # redirect for release only so wiki can point here
+ if [ "$blender_version_cycle" == "release" ] ; then
+ ssh $SSH_USER@emo.blender.org 'echo "<html><head><title>Redirecting...</title><meta http-equiv=\"REFRESH\" content=\"0;url=../blender_python_api_'$BLENDER_VERSION'/\"></head><body>Redirecting...</body></html>" > '$SSH_UPLOAD'/blender_python_api/index.html'
+ fi
+
if $DO_OUT_PDF ; then
# rename so local PDF has matching name.
rsync --progress -avze "ssh -p 22" $SPHINXBASE/sphinx-out/blender_python_reference_$BLENDER_VERSION.pdf $SSH_HOST:$SSH_UPLOAD_FULL/blender_python_reference_$BLENDER_VERSION.pdf
diff --git a/doc/python_api/sphinx_doc_gen_monkeypatch.py b/doc/python_api/sphinx_doc_gen_monkeypatch.py
new file mode 100644
index 00000000000..1167ece05b7
--- /dev/null
+++ b/doc/python_api/sphinx_doc_gen_monkeypatch.py
@@ -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): Campbell Barton
+ #
+ # #**** END GPL LICENSE BLOCK #****
+
+# <pep8 compliant>
+
+bpy_types_Operator_bl_property__doc__ = (
+"""
+The name of a property to use as this operators primary property.
+Currently this is only used to select the default property when
+expanding an operator into a menu.
+:type: string
+""")
+
+
+def main():
+ import bpy
+ from bpy.types import Operator
+
+ def dummy_func(test):
+ pass
+
+ kw_dummy = dict(fget=dummy_func, fset=dummy_func, fdel=dummy_func)
+
+ # bpy registration handles this,
+ # but its only checked for and not existing in the base class.
+ Operator.bl_property = property(doc=bpy_types_Operator_bl_property__doc__, **kw_dummy)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt
index 2640c528c94..941f69e9047 100644
--- a/extern/CMakeLists.txt
+++ b/extern/CMakeLists.txt
@@ -27,9 +27,13 @@
remove_strict_flags()
add_subdirectory(colamd)
+add_subdirectory(rangetree)
+add_subdirectory(wcwidth)
if(WITH_BULLET)
- add_subdirectory(bullet2)
+ if(NOT WITH_SYSTEM_BULLET)
+ add_subdirectory(bullet2)
+ endif()
endif()
# now only available in a branch
diff --git a/extern/SConscript b/extern/SConscript
index 71998ee072c..e2bb1dc1f31 100644
--- a/extern/SConscript
+++ b/extern/SConscript
@@ -4,6 +4,8 @@ Import('env')
SConscript(['glew/SConscript'])
SConscript(['colamd/SConscript'])
+SConscript(['rangetree/SConscript'])
+SConscript(['wcwidth/SConscript'])
if env['WITH_BF_GAMEENGINE']:
SConscript(['recastnavigation/SConscript'])
diff --git a/extern/bullet2/CMakeLists.txt b/extern/bullet2/CMakeLists.txt
index c57474f99f2..02ca2cd3755 100644
--- a/extern/bullet2/CMakeLists.txt
+++ b/extern/bullet2/CMakeLists.txt
@@ -139,6 +139,7 @@ set(SRC
src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp
src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp
src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp
+ src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp
src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
src/BulletDynamics/Dynamics/btRigidBody.cpp
src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp
@@ -162,6 +163,8 @@ set(SRC
src/LinearMath/btGeometryUtil.cpp
src/LinearMath/btQuickprof.cpp
src/LinearMath/btSerializer.cpp
+ src/LinearMath/btVector3.cpp
+ src/LinearMath/btPolarDecomposition.cpp
src/BulletCollision/BroadphaseCollision/btAxisSweep3.h
@@ -183,6 +186,7 @@ set(SRC
src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h
src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h
src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
+ src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h
src/BulletCollision/CollisionDispatch/btCollisionObject.h
src/BulletCollision/CollisionDispatch/btCollisionWorld.h
src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h
@@ -242,14 +246,15 @@ set(SRC
src/BulletCollision/CollisionShapes/btUniformScalingShape.h
src/BulletCollision/Gimpact/btBoxCollision.h
src/BulletCollision/Gimpact/btClipPolygon.h
+ src/BulletCollision/Gimpact/btCompoundFromGimpact.h
src/BulletCollision/Gimpact/btContactProcessing.h
- src/BulletCollision/Gimpact/btGenericPoolAllocator.h
- src/BulletCollision/Gimpact/btGeometryOperations.h
src/BulletCollision/Gimpact/btGImpactBvh.h
src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h
src/BulletCollision/Gimpact/btGImpactMassUtil.h
src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h
src/BulletCollision/Gimpact/btGImpactShape.h
+ src/BulletCollision/Gimpact/btGenericPoolAllocator.h
+ src/BulletCollision/Gimpact/btGeometryOperations.h
src/BulletCollision/Gimpact/btQuantization.h
src/BulletCollision/Gimpact/btTriangleShapeEx.h
src/BulletCollision/Gimpact/gim_array.h
@@ -302,6 +307,7 @@ set(SRC
src/BulletDynamics/ConstraintSolver/btSolverConstraint.h
src/BulletDynamics/ConstraintSolver/btTypedConstraint.h
src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h
+ src/BulletDynamics/ConstraintSolver/btGearConstraint.h
src/BulletDynamics/Dynamics/btActionInterface.h
src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
src/BulletDynamics/Dynamics/btDynamicsWorld.h
@@ -352,6 +358,7 @@ set(SRC
src/LinearMath/btTransform.h
src/LinearMath/btTransformUtil.h
src/LinearMath/btVector3.h
+ src/LinearMath/btPolarDecomposition.h
src/btBulletCollisionCommon.h
diff --git a/extern/bullet2/patches/make_id.patch b/extern/bullet2/patches/make_id.patch
deleted file mode 100644
index 959e578ad0e..00000000000
--- a/extern/bullet2/patches/make_id.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-Index: src/LinearMath/btSerializer.h
-===================================================================
---- src/LinearMath/btSerializer.h (revision 46625)
-+++ src/LinearMath/btSerializer.h (working copy)
-@@ -106,23 +106,23 @@
-
- #define BT_HEADER_LENGTH 12
- #if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
--# define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
-+# define BT_MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
- #else
--# define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
-+# define BT_MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
- #endif
-
--#define BT_SOFTBODY_CODE MAKE_ID('S','B','D','Y')
--#define BT_COLLISIONOBJECT_CODE MAKE_ID('C','O','B','J')
--#define BT_RIGIDBODY_CODE MAKE_ID('R','B','D','Y')
--#define BT_CONSTRAINT_CODE MAKE_ID('C','O','N','S')
--#define BT_BOXSHAPE_CODE MAKE_ID('B','O','X','S')
--#define BT_QUANTIZED_BVH_CODE MAKE_ID('Q','B','V','H')
--#define BT_TRIANLGE_INFO_MAP MAKE_ID('T','M','A','P')
--#define BT_SHAPE_CODE MAKE_ID('S','H','A','P')
--#define BT_ARRAY_CODE MAKE_ID('A','R','A','Y')
--#define BT_SBMATERIAL_CODE MAKE_ID('S','B','M','T')
--#define BT_SBNODE_CODE MAKE_ID('S','B','N','D')
--#define BT_DNA_CODE MAKE_ID('D','N','A','1')
-+#define BT_SOFTBODY_CODE BT_MAKE_ID('S','B','D','Y')
-+#define BT_COLLISIONOBJECT_CODE BT_MAKE_ID('C','O','B','J')
-+#define BT_RIGIDBODY_CODE BT_MAKE_ID('R','B','D','Y')
-+#define BT_CONSTRAINT_CODE BT_MAKE_ID('C','O','N','S')
-+#define BT_BOXSHAPE_CODE BT_MAKE_ID('B','O','X','S')
-+#define BT_QUANTIZED_BVH_CODE BT_MAKE_ID('Q','B','V','H')
-+#define BT_TRIANLGE_INFO_MAP BT_MAKE_ID('T','M','A','P')
-+#define BT_SHAPE_CODE BT_MAKE_ID('S','H','A','P')
-+#define BT_ARRAY_CODE BT_MAKE_ID('A','R','A','Y')
-+#define BT_SBMATERIAL_CODE BT_MAKE_ID('S','B','M','T')
-+#define BT_SBNODE_CODE BT_MAKE_ID('S','B','N','D')
-+#define BT_DNA_CODE BT_MAKE_ID('D','N','A','1')
-
-
- struct btPointerUid
diff --git a/extern/bullet2/patches/pvs_warning_fixes.patch b/extern/bullet2/patches/pvs_warning_fixes.patch
deleted file mode 100644
index 5a3fe140454..00000000000
--- a/extern/bullet2/patches/pvs_warning_fixes.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-Index: extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h
-===================================================================
---- extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h (Revision 45907)
-+++ extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h (Revision 45908)
-@@ -45,7 +45,9 @@
- int getTriangleIndex() const
- {
- // Get only the lower bits where the triangle index is stored
-- return (m_PartIdTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS)));
-+ unsigned int x = 0;
-+ unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
-+ return (m_PartIdTriangleIndex&~(y));
- }
- int getPartId() const
- {
-Index: extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
-===================================================================
---- extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h (Revision 45907)
-+++ extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h (Revision 45908)
-@@ -78,8 +78,10 @@
- int getTriangleIndex() const
- {
- btAssert(isLeafNode());
-+ unsigned int x=0;
-+ unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
- // Get only the lower bits where the triangle index is stored
-- return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS)));
-+ return (m_escapeIndexOrTriangleIndex&~(y));
- }
- int getPartId() const
- {
diff --git a/extern/bullet2/readme.txt b/extern/bullet2/readme.txt
index 7f5a7f1e163..dd806d40fac 100644
--- a/extern/bullet2/readme.txt
+++ b/extern/bullet2/readme.txt
@@ -7,13 +7,6 @@ Erwin
Apply patches/ghost_softbody.patch to prevent softbodies being hit by ghost objects.
Originally committed in blender svn revision: 43905.
-Apply patches/pvs_warning_fixes.patch to fix warnings reported by PVS-Studio.
-Originally committed in blender svn revision: 45908.
-
-Apply patches/make_id.patch to prevent duplicated define of MAKE_ID macro in blender
-side and bullet side.
-Sergey
-
Apply patches/ghost_character.patch to prevent characters from colliding with ghost objects.
Mitchell
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h
index 4f4d94b3cc7..cd6e1a8929e 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h
@@ -615,7 +615,7 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::removeHandle(BP_FP_INT_TYPE handle,bt
}
template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::resetPool(btDispatcher* dispatcher)
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::resetPool(btDispatcher* /*dispatcher*/)
{
if (m_numHandles == 0)
{
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
index 36eec97174f..405656236bd 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
@@ -23,6 +23,7 @@ struct btBroadphaseProxy;
class btDispatcher;
class btManifoldResult;
class btCollisionObject;
+struct btCollisionObjectWrapper;
struct btDispatcherInfo;
class btPersistentManifold;
@@ -69,7 +70,7 @@ public:
virtual ~btCollisionAlgorithm() {};
- virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h
index 409da80ae1b..b64936844d5 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h
@@ -57,7 +57,7 @@ subject to the following restrictions:
// Specific methods implementation
//SSE gives errors on a MSVC 7.1
-#if defined (BT_USE_SSE) && defined (_WIN32)
+#if defined (BT_USE_SSE) //&& defined (_WIN32)
#define DBVT_SELECT_IMPL DBVT_IMPL_SSE
#define DBVT_MERGE_IMPL DBVT_IMPL_SSE
#define DBVT_INT0_IMPL DBVT_IMPL_SSE
@@ -160,6 +160,10 @@ struct btDbvtAabbMm
btDbvtAabbMm& r);
DBVT_INLINE friend bool NotEqual( const btDbvtAabbMm& a,
const btDbvtAabbMm& b);
+
+ DBVT_INLINE btVector3& tMins() { return(mi); }
+ DBVT_INLINE btVector3& tMaxs() { return(mx); }
+
private:
DBVT_INLINE void AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const;
private:
@@ -320,7 +324,7 @@ struct btDbvt
DBVT_PREFIX
void collideTV( const btDbvtNode* root,
const btDbvtVolume& volume,
- DBVT_IPOLICY);
+ DBVT_IPOLICY) const;
///rayTest is a re-entrant ray test, and can be called in parallel as long as the btAlignedAlloc is thread-safe (uses locking etc)
///rayTest is slower than rayTestInternal, because it builds a local stack, using memory allocations, and it recomputes signs/rayDirectionInverses each time
DBVT_PREFIX
@@ -519,7 +523,11 @@ DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,
#if DBVT_INT0_IMPL == DBVT_IMPL_SSE
const __m128 rt(_mm_or_ps( _mm_cmplt_ps(_mm_load_ps(b.mx),_mm_load_ps(a.mi)),
_mm_cmplt_ps(_mm_load_ps(a.mx),_mm_load_ps(b.mi))));
+#if defined (_WIN32)
const __int32* pu((const __int32*)&rt);
+#else
+ const int* pu((const int*)&rt);
+#endif
return((pu[0]|pu[1]|pu[2])==0);
#else
return( (a.mi.x()<=b.mx.x())&&
@@ -568,7 +576,12 @@ DBVT_INLINE int Select( const btDbvtAabbMm& o,
const btDbvtAabbMm& b)
{
#if DBVT_SELECT_IMPL == DBVT_IMPL_SSE
+
+#if defined (_WIN32)
static ATTRIBUTE_ALIGNED16(const unsigned __int32) mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff};
+#else
+ static ATTRIBUTE_ALIGNED16(const unsigned int) mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x00000000 /*0x7fffffff*/};
+#endif
///@todo: the intrinsic version is 11% slower
#if DBVT_USE_INTRINSIC_SSE
@@ -908,7 +921,7 @@ inline void btDbvt::collideTT( const btDbvtNode* root0,
DBVT_PREFIX
inline void btDbvt::collideTV( const btDbvtNode* root,
const btDbvtVolume& vol,
- DBVT_IPOLICY)
+ DBVT_IPOLICY) const
{
DBVT_CHECKTYPE
if(root)
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h
index a79cf9402b1..1ebb37797d9 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h
@@ -22,7 +22,7 @@ struct btBroadphaseProxy;
class btRigidBody;
class btCollisionObject;
class btOverlappingPairCache;
-
+struct btCollisionObjectWrapper;
class btPersistentManifold;
class btStackAlloc;
@@ -76,17 +76,17 @@ class btDispatcher
public:
virtual ~btDispatcher() ;
- virtual btCollisionAlgorithm* findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold=0) = 0;
+ virtual btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold=0) = 0;
- virtual btPersistentManifold* getNewManifold(void* body0,void* body1)=0;
+ virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0,const btCollisionObject* b1)=0;
virtual void releaseManifold(btPersistentManifold* manifold)=0;
virtual void clearManifold(btPersistentManifold* manifold)=0;
- virtual bool needsCollision(btCollisionObject* body0,btCollisionObject* body1) = 0;
+ virtual bool needsCollision(const btCollisionObject* body0,const btCollisionObject* body1) = 0;
- virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0;
+ virtual bool needsResponse(const btCollisionObject* body0,const btCollisionObject* body1)=0;
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) =0;
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
index c911435a946..889216df509 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
@@ -96,7 +96,25 @@ void btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btV
m_bvhAabbMax = bvhAabbMax + clampValue;
btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin;
m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize;
+
m_useQuantization = true;
+
+ {
+ unsigned short vecIn[3];
+ btVector3 v;
+ {
+ quantize(vecIn,m_bvhAabbMin,false);
+ v = unQuantize(vecIn);
+ m_bvhAabbMin.setMin(v-clampValue);
+ }
+ {
+ quantize(vecIn,m_bvhAabbMax,true);
+ v = unQuantize(vecIn);
+ m_bvhAabbMax.setMax(v+clampValue);
+ }
+ aabbSize = m_bvhAabbMax - m_bvhAabbMin;
+ m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize;
+ }
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
index 23a5c7526b4..63401780970 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
@@ -158,7 +158,6 @@ bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &po
depth = -(radius-distance);
} else
{
- btScalar distance = 0.f;
resultNormal = normal;
point = contactPoint;
depth = -radius;
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp
index 7e5da6c5872..57f14649353 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp
@@ -24,7 +24,7 @@ btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisio
//m_colObj1(0)
{
}
-btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* colObj0,btCollisionObject* colObj1)
+btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* ,const btCollisionObjectWrapper* )
:btCollisionAlgorithm(ci)
//,
//m_colObj0(0),
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h
index 25fe088942d..489812b9663 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h
@@ -28,7 +28,7 @@ public:
btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci);
- btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* colObj0,btCollisionObject* colObj1);
+ btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
virtual ~btActivatingCollisionAlgorithm();
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
index 2182d0d7e49..2c362778210 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
@@ -22,17 +22,18 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionDispatch/btBoxBoxDetector.h"
#include "BulletCollision/CollisionShapes/btBox2dShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
#define USE_PERSISTENT_CONTACTS 1
-btBox2dBox2dCollisionAlgorithm::btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1)
-: btActivatingCollisionAlgorithm(ci,obj0,obj1),
+btBox2dBox2dCollisionAlgorithm::btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* obj0Wrap,const btCollisionObjectWrapper* obj1Wrap)
+: btActivatingCollisionAlgorithm(ci,obj0Wrap,obj1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf)
{
- if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1))
+ if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0Wrap->getCollisionObject(),obj1Wrap->getCollisionObject()))
{
- m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1);
+ m_manifoldPtr = m_dispatcher->getNewManifold(obj0Wrap->getCollisionObject(),obj1Wrap->getCollisionObject());
m_ownManifold = true;
}
}
@@ -52,19 +53,18 @@ btBox2dBox2dCollisionAlgorithm::~btBox2dBox2dCollisionAlgorithm()
void b2CollidePolygons(btManifoldResult* manifold, const btBox2dShape* polyA, const btTransform& xfA, const btBox2dShape* polyB, const btTransform& xfB);
//#include <stdio.h>
-void btBox2dBox2dCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btBox2dBox2dCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
return;
- btCollisionObject* col0 = body0;
- btCollisionObject* col1 = body1;
- btBox2dShape* box0 = (btBox2dShape*)col0->getCollisionShape();
- btBox2dShape* box1 = (btBox2dShape*)col1->getCollisionShape();
+
+ const btBox2dShape* box0 = (const btBox2dShape*)body0Wrap->getCollisionShape();
+ const btBox2dShape* box1 = (const btBox2dShape*)body1Wrap->getCollisionShape();
resultOut->setPersistentManifold(m_manifoldPtr);
- b2CollidePolygons(resultOut,box0,col0->getWorldTransform(),box1,col1->getWorldTransform());
+ b2CollidePolygons(resultOut,box0,body0Wrap->getWorldTransform(),box1,body1Wrap->getWorldTransform());
// refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
if (m_ownManifold)
@@ -151,15 +151,8 @@ static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1
int index = 0;
btScalar minDot = BT_LARGE_FLOAT;
- for (int i = 0; i < count2; ++i)
- {
- btScalar dot = b2Dot(vertices2[i], normal1);
- if (dot < minDot)
- {
- minDot = dot;
- index = i;
- }
- }
+ if( count2 > 0 )
+ index = (int) normal1.minDot( vertices2, count2, minDot);
btVector3 v1 = b2Mul(xf1, vertices1[edge1]);
btVector3 v2 = b2Mul(xf2, vertices2[index]);
@@ -181,16 +174,9 @@ static btScalar FindMaxSeparation(int* edgeIndex,
// Find edge normal on poly1 that has the largest projection onto d.
int edge = 0;
- btScalar maxDot = -BT_LARGE_FLOAT;
- for (int i = 0; i < count1; ++i)
- {
- btScalar dot = b2Dot(normals1[i], dLocal1);
- if (dot > maxDot)
- {
- maxDot = dot;
- edge = i;
- }
- }
+ btScalar maxDot;
+ if( count1 > 0 )
+ edge = (int) dLocal1.maxDot( normals1, count1, maxDot);
// Get the separation for the edge normal.
btScalar s = EdgeSeparation(poly1, xf1, edge, poly2, xf2);
@@ -368,7 +354,7 @@ void b2CollidePolygons(btManifoldResult* manifold,
btVector3 v11 = vertices1[edge1];
btVector3 v12 = edge1 + 1 < count1 ? vertices1[edge1+1] : vertices1[0];
- btVector3 dv = v12 - v11;
+ //btVector3 dv = v12 - v11;
btVector3 sideNormal = b2Mul(xf1.getBasis(), v12 - v11);
sideNormal.normalize();
btVector3 frontNormal = btCrossS(sideNormal, 1.0f);
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h
index 97c5be77003..6ea6e89bda6 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h
@@ -33,11 +33,11 @@ public:
btBox2dBox2dCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
- virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
- btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
+ btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
virtual ~btBox2dBox2dCollisionAlgorithm();
@@ -52,11 +52,11 @@ public:
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
int bbsize = sizeof(btBox2dBox2dCollisionAlgorithm);
void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
- return new(ptr) btBox2dBox2dCollisionAlgorithm(0,ci,body0,body1);
+ return new(ptr) btBox2dBox2dCollisionAlgorithm(0,ci,body0Wrap,body1Wrap);
}
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
index 49628853493..ac68968f590 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
@@ -18,17 +18,17 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "btBoxBoxDetector.h"
-
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
#define USE_PERSISTENT_CONTACTS 1
-btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1)
-: btActivatingCollisionAlgorithm(ci,obj0,obj1),
+btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf)
{
- if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1))
+ if (!m_manifoldPtr && m_dispatcher->needsCollision(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject()))
{
- m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1);
+ m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
m_ownManifold = true;
}
}
@@ -42,15 +42,14 @@ btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm()
}
}
-void btBoxBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btBoxBoxCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
return;
- btCollisionObject* col0 = body0;
- btCollisionObject* col1 = body1;
- btBoxShape* box0 = (btBoxShape*)col0->getCollisionShape();
- btBoxShape* box1 = (btBoxShape*)col1->getCollisionShape();
+
+ const btBoxShape* box0 = (btBoxShape*)body0Wrap->getCollisionShape();
+ const btBoxShape* box1 = (btBoxShape*)body1Wrap->getCollisionShape();
@@ -62,8 +61,8 @@ void btBoxBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCo
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
- input.m_transformA = body0->getWorldTransform();
- input.m_transformB = body1->getWorldTransform();
+ input.m_transformA = body0Wrap->getWorldTransform();
+ input.m_transformB = body1Wrap->getWorldTransform();
btBoxBoxDetector detector(box0,box1);
detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
index f0bbae61e3b..59808df5a9d 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
@@ -33,11 +33,11 @@ public:
btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
- virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
- btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
+ btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
virtual ~btBoxBoxCollisionAlgorithm();
@@ -52,11 +52,11 @@ public:
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
int bbsize = sizeof(btBoxBoxCollisionAlgorithm);
void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
- return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0,body1);
+ return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0Wrap,body1Wrap);
}
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
index a7c8cf140ce..7043bde34f5 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
@@ -24,7 +24,7 @@ subject to the following restrictions:
#include <float.h>
#include <string.h>
-btBoxBoxDetector::btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2)
+btBoxBoxDetector::btBoxBoxDetector(const btBoxShape* box1,const btBoxShape* box2)
: m_box1(box1),
m_box2(box2)
{
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
index 3c941f7deb2..39243777051 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
@@ -28,12 +28,12 @@ class btBoxShape;
/// re-distributed under the Zlib license with permission from Russell L. Smith
struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface
{
- btBoxShape* m_box1;
- btBoxShape* m_box2;
+ const btBoxShape* m_box1;
+ const btBoxShape* m_box2;
public:
- btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2);
+ btBoxBoxDetector(const btBoxShape* box1,const btBoxShape* box2);
virtual ~btBoxBoxDetector() {};
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h
index 1d7e74401dd..62ee66c4e9a 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h
@@ -19,7 +19,7 @@ subject to the following restrictions:
#include "LinearMath/btAlignedObjectArray.h"
class btCollisionAlgorithm;
class btCollisionObject;
-
+struct btCollisionObjectWrapper;
struct btCollisionAlgorithmConstructionInfo;
///Used by the btCollisionDispatcher to register and create instances for btCollisionAlgorithm
@@ -33,11 +33,11 @@ struct btCollisionAlgorithmCreateFunc
}
virtual ~btCollisionAlgorithmCreateFunc(){};
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& , btCollisionObject* body0,btCollisionObject* body1)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& , const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
- (void)body0;
- (void)body1;
+ (void)body0Wrap;
+ (void)body1Wrap;
return 0;
}
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
index 29674f3be46..669d0b6b55e 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
@@ -25,6 +25,7 @@ subject to the following restrictions:
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
#include "LinearMath/btPoolAllocator.h"
#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
int gNumManifold = 0;
@@ -67,15 +68,13 @@ btCollisionDispatcher::~btCollisionDispatcher()
{
}
-btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1)
+btPersistentManifold* btCollisionDispatcher::getNewManifold(const btCollisionObject* body0,const btCollisionObject* body1)
{
gNumManifold++;
//btAssert(gNumManifold < 65535);
- btCollisionObject* body0 = (btCollisionObject*)b0;
- btCollisionObject* body1 = (btCollisionObject*)b1;
//optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
@@ -85,7 +84,7 @@ btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1)
btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(),body1->getContactProcessingThreshold());
- void* mem = 0;
+ void* mem = 0;
if (m_persistentManifoldPoolAllocator->getFreeCount())
{
@@ -143,14 +142,14 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
-btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold)
+btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold)
{
btCollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher1 = this;
ci.m_manifold = sharedManifold;
- btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1);
+ btCollisionAlgorithm* algo = m_doubleDispatch[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0Wrap,body1Wrap);
return algo;
}
@@ -158,7 +157,7 @@ btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* bo
-bool btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1)
+bool btCollisionDispatcher::needsResponse(const btCollisionObject* body0,const btCollisionObject* body1)
{
//here you can do filtering
bool hasResponse =
@@ -169,7 +168,7 @@ bool btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionOb
return hasResponse;
}
-bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionObject* body1)
+bool btCollisionDispatcher::needsCollision(const btCollisionObject* body0,const btCollisionObject* body1)
{
btAssert(body0);
btAssert(body1);
@@ -259,20 +258,25 @@ void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair,
if (dispatcher.needsCollision(colObj0,colObj1))
{
+ btCollisionObjectWrapper obj0Wrap(0,colObj0->getCollisionShape(),colObj0,colObj0->getWorldTransform(),-1,-1);
+ btCollisionObjectWrapper obj1Wrap(0,colObj1->getCollisionShape(),colObj1,colObj1->getWorldTransform(),-1,-1);
+
+
//dispatcher will keep algorithms persistent in the collision pair
if (!collisionPair.m_algorithm)
{
- collisionPair.m_algorithm = dispatcher.findAlgorithm(colObj0,colObj1);
+ collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap,&obj1Wrap);
}
if (collisionPair.m_algorithm)
{
- btManifoldResult contactPointResult(colObj0,colObj1);
+ btManifoldResult contactPointResult(&obj0Wrap,&obj1Wrap);
if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
{
//discrete collision detection query
- collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult);
+
+ collisionPair.m_algorithm->processCollision(&obj0Wrap,&obj1Wrap,dispatchInfo,&contactPointResult);
} else
{
//continuous collision detection query, time of impact (toi)
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
index 5accad9a993..92696ee5429 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
@@ -108,19 +108,18 @@ public:
virtual ~btCollisionDispatcher();
- virtual btPersistentManifold* getNewManifold(void* b0,void* b1);
+ virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0,const btCollisionObject* b1);
virtual void releaseManifold(btPersistentManifold* manifold);
virtual void clearManifold(btPersistentManifold* manifold);
-
- btCollisionAlgorithm* findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold = 0);
+ btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold = 0);
- virtual bool needsCollision(btCollisionObject* body0,btCollisionObject* body1);
+ virtual bool needsCollision(const btCollisionObject* body0,const btCollisionObject* body1);
- virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1);
+ virtual bool needsResponse(const btCollisionObject* body0,const btCollisionObject* body1);
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ;
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp
index 580ea345860..cf8ed59a541 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp
@@ -31,6 +31,7 @@ btCollisionObject::btCollisionObject()
m_activationState1(1),
m_deactivationTime(btScalar(0.)),
m_friction(btScalar(0.5)),
+ m_rollingFriction(0.0f),
m_restitution(btScalar(0.)),
m_internalType(CO_COLLISION_OBJECT),
m_userObjectPointer(0),
@@ -46,18 +47,18 @@ btCollisionObject::~btCollisionObject()
{
}
-void btCollisionObject::setActivationState(int newState)
+void btCollisionObject::setActivationState(int newState) const
{
if ( (m_activationState1 != DISABLE_DEACTIVATION) && (m_activationState1 != DISABLE_SIMULATION))
m_activationState1 = newState;
}
-void btCollisionObject::forceActivationState(int newState)
+void btCollisionObject::forceActivationState(int newState) const
{
m_activationState1 = newState;
}
-void btCollisionObject::activate(bool forceActivation)
+void btCollisionObject::activate(bool forceActivation) const
{
if (forceActivation || !(m_collisionFlags & (CF_STATIC_OBJECT|CF_KINEMATIC_OBJECT)))
{
@@ -85,9 +86,9 @@ const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* seriali
dataOut->m_islandTag1 = m_islandTag1;
dataOut->m_companionId = m_companionId;
dataOut->m_activationState1 = m_activationState1;
- dataOut->m_activationState1 = m_activationState1;
dataOut->m_deactivationTime = m_deactivationTime;
dataOut->m_friction = m_friction;
+ dataOut->m_rollingFriction = m_rollingFriction;
dataOut->m_restitution = m_restitution;
dataOut->m_internalType = m_internalType;
@@ -100,7 +101,6 @@ const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* seriali
dataOut->m_hitFraction = m_hitFraction;
dataOut->m_ccdSweptSphereRadius = m_ccdSweptSphereRadius;
dataOut->m_ccdMotionThreshold = m_ccdMotionThreshold;
- dataOut->m_ccdMotionThreshold = m_ccdMotionThreshold;
dataOut->m_checkCollideWith = m_checkCollideWith;
return btCollisionObjectDataName;
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h
index 3a11c967ac9..2f17967fe0f 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h
@@ -80,11 +80,12 @@ protected:
int m_islandTag1;
int m_companionId;
- int m_activationState1;
- btScalar m_deactivationTime;
+ mutable int m_activationState1;
+ mutable btScalar m_deactivationTime;
btScalar m_friction;
btScalar m_restitution;
+ btScalar m_rollingFriction;
///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody, btGhostObject etc.
///do not assign your own m_internalType unless you write a new dynamics object class.
@@ -105,7 +106,7 @@ protected:
/// If some object should have elaborate collision filtering by sub-classes
int m_checkCollideWith;
- virtual bool checkCollideWithOverride(btCollisionObject* /* co */)
+ virtual bool checkCollideWithOverride(const btCollisionObject* /* co */) const
{
return true;
}
@@ -137,6 +138,13 @@ public:
CO_USER_TYPE=32
};
+ enum AnisotropicFrictionFlags
+ {
+ CF_ANISOTROPIC_FRICTION_DISABLED=0,
+ CF_ANISOTROPIC_FRICTION = 1,
+ CF_ANISOTROPIC_ROLLING_FRICTION = 2
+ };
+
SIMD_FORCE_INLINE bool mergesSimulationIslands() const
{
///static objects, kinematic and object without contact response don't merge islands
@@ -147,14 +155,15 @@ public:
{
return m_anisotropicFriction;
}
- void setAnisotropicFriction(const btVector3& anisotropicFriction)
+ void setAnisotropicFriction(const btVector3& anisotropicFriction, int frictionMode = CF_ANISOTROPIC_FRICTION)
{
m_anisotropicFriction = anisotropicFriction;
- m_hasAnisotropicFriction = (anisotropicFriction[0]!=1.f) || (anisotropicFriction[1]!=1.f) || (anisotropicFriction[2]!=1.f);
+ bool isUnity = (anisotropicFriction[0]!=1.f) || (anisotropicFriction[1]!=1.f) || (anisotropicFriction[2]!=1.f);
+ m_hasAnisotropicFriction = isUnity?frictionMode : 0;
}
- bool hasAnisotropicFriction() const
+ bool hasAnisotropicFriction(int frictionMode = CF_ANISOTROPIC_FRICTION) const
{
- return m_hasAnisotropicFriction!=0;
+ return (m_hasAnisotropicFriction&frictionMode)!=0;
}
///the constraint solver can discard solving contacts, if the distance is above this threshold. 0 by default.
@@ -207,22 +216,9 @@ public:
return m_collisionShape;
}
- SIMD_FORCE_INLINE const btCollisionShape* getRootCollisionShape() const
- {
- return m_rootCollisionShape;
- }
-
- SIMD_FORCE_INLINE btCollisionShape* getRootCollisionShape()
- {
- return m_rootCollisionShape;
- }
+
- ///Avoid using this internal API call
- ///internalSetTemporaryCollisionShape is used to temporary replace the actual collision shape by a child collision shape.
- void internalSetTemporaryCollisionShape(btCollisionShape* collisionShape)
- {
- m_collisionShape = collisionShape;
- }
+
///Avoid using this internal API call, the extension pointer is used by some Bullet extensions.
///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
@@ -239,7 +235,7 @@ public:
SIMD_FORCE_INLINE int getActivationState() const { return m_activationState1;}
- void setActivationState(int newState);
+ void setActivationState(int newState) const;
void setDeactivationTime(btScalar time)
{
@@ -250,9 +246,9 @@ public:
return m_deactivationTime;
}
- void forceActivationState(int newState);
+ void forceActivationState(int newState) const;
- void activate(bool forceActivation = false);
+ void activate(bool forceActivation = false) const;
SIMD_FORCE_INLINE bool isActive() const
{
@@ -276,6 +272,16 @@ public:
return m_friction;
}
+ void setRollingFriction(btScalar frict)
+ {
+ m_rollingFriction = frict;
+ }
+ btScalar getRollingFriction() const
+ {
+ return m_rollingFriction;
+ }
+
+
///reserved for Bullet internal usage
int getInternalType() const
{
@@ -433,7 +439,7 @@ public:
}
- inline bool checkCollideWith(btCollisionObject* co)
+ inline bool checkCollideWith(const btCollisionObject* co) const
{
if (m_checkCollideWith)
return checkCollideWithOverride(co);
@@ -466,6 +472,7 @@ struct btCollisionObjectDoubleData
double m_contactProcessingThreshold;
double m_deactivationTime;
double m_friction;
+ double m_rollingFriction;
double m_restitution;
double m_hitFraction;
double m_ccdSweptSphereRadius;
@@ -498,6 +505,8 @@ struct btCollisionObjectFloatData
float m_contactProcessingThreshold;
float m_deactivationTime;
float m_friction;
+ float m_rollingFriction;
+
float m_restitution;
float m_hitFraction;
float m_ccdSweptSphereRadius;
@@ -510,6 +519,7 @@ struct btCollisionObjectFloatData
int m_activationState1;
int m_internalType;
int m_checkCollideWith;
+ char m_padding[4];
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h
new file mode 100644
index 00000000000..952440b7dee
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h
@@ -0,0 +1,43 @@
+#ifndef BT_COLLISION_OBJECT_WRAPPER_H
+#define BT_COLLISION_OBJECT_WRAPPER_H
+
+///btCollisionObjectWrapperis an internal data structure.
+///Most users can ignore this and use btCollisionObject and btCollisionShape instead
+class btCollisionShape;
+class btCollisionObject;
+class btTransform;
+#include "LinearMath/btScalar.h" // for SIMD_FORCE_INLINE definition
+
+#define BT_DECLARE_STACK_ONLY_OBJECT \
+ private: \
+ void* operator new(size_t size); \
+ void operator delete(void*);
+
+struct btCollisionObjectWrapper;
+struct btCollisionObjectWrapper
+{
+BT_DECLARE_STACK_ONLY_OBJECT
+
+private:
+ btCollisionObjectWrapper(const btCollisionObjectWrapper&); // not implemented. Not allowed.
+ btCollisionObjectWrapper* operator=(const btCollisionObjectWrapper&);
+
+public:
+ const btCollisionObjectWrapper* m_parent;
+ const btCollisionShape* m_shape;
+ const btCollisionObject* m_collisionObject;
+ const btTransform& m_worldTransform;
+ int m_partId;
+ int m_index;
+
+ btCollisionObjectWrapper(const btCollisionObjectWrapper* parent, const btCollisionShape* shape, const btCollisionObject* collisionObject, const btTransform& worldTransform, int partId, int index)
+ : m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform),
+ m_partId(partId), m_index(index)
+ {}
+
+ SIMD_FORCE_INLINE const btTransform& getWorldTransform() const { return m_worldTransform; }
+ SIMD_FORCE_INLINE const btCollisionObject* getCollisionObject() const { return m_collisionObject; }
+ SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { return m_shape; }
+};
+
+#endif //BT_COLLISION_OBJECT_WRAPPER_H
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
index 66b93b88efa..4c09291692d 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
@@ -34,6 +34,7 @@ subject to the following restrictions:
#include "LinearMath/btStackAlloc.h"
#include "LinearMath/btSerializer.h"
#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
//#define DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
@@ -207,6 +208,11 @@ void btCollisionWorld::updateAabbs()
}
+void btCollisionWorld::computeOverlappingPairs()
+{
+ BT_PROFILE("calculateOverlappingPairs");
+ m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
+}
void btCollisionWorld::performDiscreteCollisionDetection()
{
@@ -216,11 +222,7 @@ void btCollisionWorld::performDiscreteCollisionDetection()
updateAabbs();
- {
- BT_PROFILE("calculateOverlappingPairs");
- m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
- }
-
+ computeOverlappingPairs();
btDispatcher* dispatcher = getDispatcher();
{
@@ -260,16 +262,25 @@ void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
}
-
void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
RayResultCallback& resultCallback)
{
+ btCollisionObjectWrapper colObWrap(0,collisionShape,collisionObject,colObjWorldTransform,-1,-1);
+ btCollisionWorld::rayTestSingleInternal(rayFromTrans,rayToTrans,&colObWrap,resultCallback);
+}
+
+void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans,const btTransform& rayToTrans,
+ const btCollisionObjectWrapper* collisionObjectWrap,
+ RayResultCallback& resultCallback)
+{
btSphereShape pointShape(btScalar(0.0));
pointShape.setMargin(0.f);
const btConvexShape* castShape = &pointShape;
+ const btCollisionShape* collisionShape = collisionObjectWrap->getCollisionShape();
+ const btTransform& colObjWorldTransform = collisionObjectWrap->getWorldTransform();
if (collisionShape->isConvex())
{
@@ -302,7 +313,7 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
castResult.m_normal.normalize();
btCollisionWorld::LocalRayResult localRayResult
(
- collisionObject,
+ collisionObjectWrap->getCollisionObject(),
0,
castResult.m_normal,
castResult.m_fraction
@@ -330,13 +341,13 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
{
btCollisionWorld::RayResultCallback* m_resultCallback;
- btCollisionObject* m_collisionObject;
+ const btCollisionObject* m_collisionObject;
btTriangleMeshShape* m_triangleMesh;
btTransform m_colObjWorldTransform;
BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
- btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh,const btTransform& colObjWorldTransform):
+ btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh,const btTransform& colObjWorldTransform):
//@BP Mod
btTriangleRaycastCallback(from,to, resultCallback->m_flags),
m_resultCallback(resultCallback),
@@ -367,7 +378,7 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
};
- BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh,colObjWorldTransform);
+ BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObjectWrap->getCollisionObject(),triangleMesh,colObjWorldTransform);
rcb.m_hitFraction = resultCallback.m_closestHitFraction;
triangleMesh->performRaycast(&rcb,rayFromLocal,rayToLocal);
} else
@@ -385,13 +396,13 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
{
btCollisionWorld::RayResultCallback* m_resultCallback;
- btCollisionObject* m_collisionObject;
+ const btCollisionObject* m_collisionObject;
btConcaveShape* m_triangleMesh;
btTransform m_colObjWorldTransform;
BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
- btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& colObjWorldTransform):
+ btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& colObjWorldTransform):
//@BP Mod
btTriangleRaycastCallback(from,to, resultCallback->m_flags),
m_resultCallback(resultCallback),
@@ -423,7 +434,7 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
};
- BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,concaveShape, colObjWorldTransform);
+ BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObjectWrap->getCollisionObject(),concaveShape, colObjWorldTransform);
rcb.m_hitFraction = resultCallback.m_closestHitFraction;
btVector3 rayAabbMinLocal = rayFromLocal;
@@ -446,6 +457,7 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
: m_userCallback(user), m_i(i)
{
m_closestHitFraction = m_userCallback->m_closestHitFraction;
+ m_flags = m_userCallback->m_flags;
}
virtual bool needsCollision(btBroadphaseProxy* p) const
{
@@ -468,14 +480,14 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
struct RayTester : btDbvt::ICollide
{
- btCollisionObject* m_collisionObject;
+ const btCollisionObject* m_collisionObject;
const btCompoundShape* m_compoundShape;
const btTransform& m_colObjWorldTransform;
const btTransform& m_rayFromTrans;
const btTransform& m_rayToTrans;
RayResultCallback& m_resultCallback;
- RayTester(btCollisionObject* collisionObject,
+ RayTester(const btCollisionObject* collisionObject,
const btCompoundShape* compoundShape,
const btTransform& colObjWorldTransform,
const btTransform& rayFromTrans,
@@ -491,33 +503,30 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
}
- void Process(int i)
+ void ProcessLeaf(int i)
{
const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(i);
const btTransform& childTrans = m_compoundShape->getChildTransform(i);
btTransform childWorldTrans = m_colObjWorldTransform * childTrans;
+ btCollisionObjectWrapper tmpOb(0,childCollisionShape,m_collisionObject,childWorldTrans,-1,i);
// replace collision shape so that callback can determine the triangle
- btCollisionShape* saveCollisionShape = m_collisionObject->getCollisionShape();
- m_collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape);
+
+
LocalInfoAdder2 my_cb(i, &m_resultCallback);
- rayTestSingle(
+ rayTestSingleInternal(
m_rayFromTrans,
m_rayToTrans,
- m_collisionObject,
- childCollisionShape,
- childWorldTrans,
+ &tmpOb,
my_cb);
- // restore
- m_collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape);
}
-
+
void Process(const btDbvtNode* leaf)
{
- Process(leaf->dataAsInt);
+ ProcessLeaf(leaf->dataAsInt);
}
};
@@ -526,7 +535,7 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
RayTester rayCB(
- collisionObject,
+ collisionObjectWrap->getCollisionObject(),
compoundShape,
colObjWorldTransform,
rayFromTrans,
@@ -544,7 +553,7 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
{
for (int i = 0, n = compoundShape->getNumChildShapes(); i < n; ++i)
{
- rayCB.Process(i);
+ rayCB.ProcessLeaf(i);
}
}
}
@@ -558,6 +567,17 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
const btTransform& colObjWorldTransform,
ConvexResultCallback& resultCallback, btScalar allowedPenetration)
{
+ btCollisionObjectWrapper tmpOb(0,collisionShape,collisionObject,colObjWorldTransform,-1,-1);
+ btCollisionWorld::objectQuerySingleInternal(castShape,convexFromTrans,convexToTrans,&tmpOb,resultCallback,allowedPenetration);
+}
+
+void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
+ const btCollisionObjectWrapper* colObjWrap,
+ ConvexResultCallback& resultCallback, btScalar allowedPenetration)
+{
+ const btCollisionShape* collisionShape = colObjWrap->getCollisionShape();
+ const btTransform& colObjWorldTransform = colObjWrap->getWorldTransform();
+
if (collisionShape->isConvex())
{
//BT_PROFILE("convexSweepConvex");
@@ -587,7 +607,7 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
castResult.m_normal.normalize();
btCollisionWorld::LocalConvexResult localConvexResult
(
- collisionObject,
+ colObjWrap->getCollisionObject(),
0,
castResult.m_normal,
castResult.m_hitPoint,
@@ -617,11 +637,11 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
{
btCollisionWorld::ConvexResultCallback* m_resultCallback;
- btCollisionObject* m_collisionObject;
+ const btCollisionObject* m_collisionObject;
btTriangleMeshShape* m_triangleMesh;
BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
- btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld):
+ btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld):
btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
m_resultCallback(resultCallback),
m_collisionObject(collisionObject),
@@ -655,7 +675,7 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
};
- BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform);
+ BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,colObjWrap->getCollisionObject(),triangleMesh, colObjWorldTransform);
tccb.m_hitFraction = resultCallback.m_closestHitFraction;
tccb.m_allowedPenetration = allowedPenetration;
btVector3 boxMinLocal, boxMaxLocal;
@@ -682,7 +702,7 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
castResult.m_normal.normalize();
btCollisionWorld::LocalConvexResult localConvexResult
(
- collisionObject,
+ colObjWrap->getCollisionObject(),
0,
castResult.m_normal,
castResult.m_hitPoint,
@@ -709,11 +729,11 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
{
btCollisionWorld::ConvexResultCallback* m_resultCallback;
- btCollisionObject* m_collisionObject;
+ const btCollisionObject* m_collisionObject;
btConcaveShape* m_triangleMesh;
BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
- btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& triangleToWorld):
+ btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& triangleToWorld):
btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
m_resultCallback(resultCallback),
m_collisionObject(collisionObject),
@@ -746,7 +766,7 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
};
- BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,concaveShape, colObjWorldTransform);
+ BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,colObjWrap->getCollisionObject(),concaveShape, colObjWorldTransform);
tccb.m_hitFraction = resultCallback.m_closestHitFraction;
tccb.m_allowedPenetration = allowedPenetration;
btVector3 boxMinLocal, boxMaxLocal;
@@ -773,9 +793,7 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
btTransform childTrans = compoundShape->getChildTransform(i);
const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
btTransform childWorldTrans = colObjWorldTransform * childTrans;
- // replace collision shape so that callback can determine the triangle
- btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape();
- collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape);
+
struct LocalInfoAdder : public ConvexResultCallback {
ConvexResultCallback* m_userCallback;
int m_i;
@@ -805,14 +823,11 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
LocalInfoAdder my_cb(i, &resultCallback);
+ btCollisionObjectWrapper tmpObj(colObjWrap,childCollisionShape,colObjWrap->getCollisionObject(),childWorldTrans,-1,i);
- objectQuerySingle(castShape, convexFromTrans,convexToTrans,
- collisionObject,
- childCollisionShape,
- childWorldTrans,
- my_cb, allowedPenetration);
- // restore
- collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape);
+ objectQuerySingleInternal(castShape, convexFromTrans,convexToTrans,
+ &tmpObj,my_cb, allowedPenetration);
+
}
}
}
@@ -993,13 +1008,13 @@ void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btT
/* Compute AABB that encompasses angular movement */
{
btVector3 linVel, angVel;
- btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel);
+ btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0f, linVel, angVel);
btVector3 zeroLinVel;
zeroLinVel.setValue(0,0,0);
btTransform R;
R.setIdentity ();
R.setRotation (convexFromTrans.getRotation());
- castShape->calculateTemporalAabb (R, zeroLinVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax);
+ castShape->calculateTemporalAabb (R, zeroLinVel, angVel, 1.0f, castShapeAabbMin, castShapeAabbMax);
}
#ifndef USE_BRUTEFORCE_RAYBROADPHASE
@@ -1044,26 +1059,26 @@ struct btBridgedManifoldResult : public btManifoldResult
btCollisionWorld::ContactResultCallback& m_resultCallback;
- btBridgedManifoldResult( btCollisionObject* obj0,btCollisionObject* obj1,btCollisionWorld::ContactResultCallback& resultCallback )
- :btManifoldResult(obj0,obj1),
+ btBridgedManifoldResult( const btCollisionObjectWrapper* obj0Wrap,const btCollisionObjectWrapper* obj1Wrap,btCollisionWorld::ContactResultCallback& resultCallback )
+ :btManifoldResult(obj0Wrap,obj1Wrap),
m_resultCallback(resultCallback)
{
}
virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
{
- bool isSwapped = m_manifoldPtr->getBody0() != m_body0;
+ bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
btVector3 localA;
btVector3 localB;
if (isSwapped)
{
- localA = m_rootTransB.invXform(pointA );
- localB = m_rootTransA.invXform(pointInWorld);
+ localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
+ localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
} else
{
- localA = m_rootTransA.invXform(pointA );
- localB = m_rootTransB.invXform(pointInWorld);
+ localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
+ localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
}
btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
@@ -1086,9 +1101,9 @@ struct btBridgedManifoldResult : public btManifoldResult
}
//experimental feature info, for per-triangle material etc.
- btCollisionObject* obj0 = isSwapped? m_body1 : m_body0;
- btCollisionObject* obj1 = isSwapped? m_body0 : m_body1;
- m_resultCallback.addSingleResult(newPt,obj0,newPt.m_partId0,newPt.m_index0,obj1,newPt.m_partId1,newPt.m_index1);
+ const btCollisionObjectWrapper* obj0Wrap = isSwapped? m_body1Wrap : m_body0Wrap;
+ const btCollisionObjectWrapper* obj1Wrap = isSwapped? m_body0Wrap : m_body1Wrap;
+ m_resultCallback.addSingleResult(newPt,obj0Wrap,newPt.m_partId0,newPt.m_index0,obj1Wrap,newPt.m_partId1,newPt.m_index1);
}
@@ -1120,12 +1135,16 @@ struct btSingleContactCallback : public btBroadphaseAabbCallback
//only perform raycast if filterMask matches
if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
{
- btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(m_collisionObject,collisionObject);
+ btCollisionObjectWrapper ob0(0,m_collisionObject->getCollisionShape(),m_collisionObject,m_collisionObject->getWorldTransform(),-1,-1);
+ btCollisionObjectWrapper ob1(0,collisionObject->getCollisionShape(),collisionObject,collisionObject->getWorldTransform(),-1,-1);
+
+ btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(&ob0,&ob1);
if (algorithm)
{
- btBridgedManifoldResult contactPointResult(m_collisionObject,collisionObject, m_resultCallback);
+ btBridgedManifoldResult contactPointResult(&ob0,&ob1, m_resultCallback);
//discrete collision detection query
- algorithm->processCollision(m_collisionObject,collisionObject, m_world->getDispatchInfo(),&contactPointResult);
+
+ algorithm->processCollision(&ob0,&ob1, m_world->getDispatchInfo(),&contactPointResult);
algorithm->~btCollisionAlgorithm();
m_world->getDispatcher()->freeCollisionAlgorithm(algorithm);
@@ -1152,12 +1171,15 @@ void btCollisionWorld::contactTest( btCollisionObject* colObj, ContactResultCall
///it reports one or more contact points (including the one with deepest penetration)
void btCollisionWorld::contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback)
{
- btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(colObjA,colObjB);
+ btCollisionObjectWrapper obA(0,colObjA->getCollisionShape(),colObjA,colObjA->getWorldTransform(),-1,-1);
+ btCollisionObjectWrapper obB(0,colObjB->getCollisionShape(),colObjB,colObjB->getWorldTransform(),-1,-1);
+
+ btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(&obA,&obB);
if (algorithm)
{
- btBridgedManifoldResult contactPointResult(colObjA,colObjB, resultCallback);
+ btBridgedManifoldResult contactPointResult(&obA,&obB, resultCallback);
//discrete collision detection query
- algorithm->processCollision(colObjA,colObjB, getDispatchInfo(),&contactPointResult);
+ algorithm->processCollision(&obA,&obB, getDispatchInfo(),&contactPointResult);
algorithm->~btCollisionAlgorithm();
getDispatcher()->freeCollisionAlgorithm(algorithm);
@@ -1231,163 +1253,162 @@ void btCollisionWorld::debugDrawObject(const btTransform& worldTransform, const
} else
{
- /// for polyhedral shapes
- if (shape->isPolyhedral())
- {
- btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shape;
-
- int i;
- if (polyshape->getConvexPolyhedron())
- {
- const btConvexPolyhedron* poly = polyshape->getConvexPolyhedron();
- for (i=0;i<poly->m_faces.size();i++)
- {
- btVector3 centroid(0,0,0);
- int numVerts = poly->m_faces[i].m_indices.size();
- if (numVerts)
- {
- int lastV = poly->m_faces[i].m_indices[numVerts-1];
- for (int v=0;v<poly->m_faces[i].m_indices.size();v++)
- {
- int curVert = poly->m_faces[i].m_indices[v];
- centroid+=poly->m_vertices[curVert];
- getDebugDrawer()->drawLine(worldTransform*poly->m_vertices[lastV],worldTransform*poly->m_vertices[curVert],color);
- lastV = curVert;
- }
- }
- centroid*= btScalar(1.f)/btScalar(numVerts);
- if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawNormals)
+ switch (shape->getShapeType())
+ {
+
+ case BOX_SHAPE_PROXYTYPE:
+ {
+ const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
+ btVector3 halfExtents = boxShape->getHalfExtentsWithMargin();
+ getDebugDrawer()->drawBox(-halfExtents,halfExtents,worldTransform,color);
+ break;
+ }
+
+ case SPHERE_SHAPE_PROXYTYPE:
+ {
+ const btSphereShape* sphereShape = static_cast<const btSphereShape*>(shape);
+ btScalar radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin
+
+ getDebugDrawer()->drawSphere(radius, worldTransform, color);
+ break;
+ }
+ case MULTI_SPHERE_SHAPE_PROXYTYPE:
+ {
+ const btMultiSphereShape* multiSphereShape = static_cast<const btMultiSphereShape*>(shape);
+
+ btTransform childTransform;
+ childTransform.setIdentity();
+
+ for (int i = multiSphereShape->getSphereCount()-1; i>=0;i--)
+ {
+ childTransform.setOrigin(multiSphereShape->getSpherePosition(i));
+ getDebugDrawer()->drawSphere(multiSphereShape->getSphereRadius(i), worldTransform*childTransform, color);
+ }
+
+ break;
+ }
+ case CAPSULE_SHAPE_PROXYTYPE:
+ {
+ const btCapsuleShape* capsuleShape = static_cast<const btCapsuleShape*>(shape);
+
+ btScalar radius = capsuleShape->getRadius();
+ btScalar halfHeight = capsuleShape->getHalfHeight();
+
+ int upAxis = capsuleShape->getUpAxis();
+ getDebugDrawer()->drawCapsule(radius, halfHeight, upAxis, worldTransform, color);
+ break;
+ }
+ case CONE_SHAPE_PROXYTYPE:
+ {
+ const btConeShape* coneShape = static_cast<const btConeShape*>(shape);
+ btScalar radius = coneShape->getRadius();//+coneShape->getMargin();
+ btScalar height = coneShape->getHeight();//+coneShape->getMargin();
+
+ int upAxis= coneShape->getConeUpIndex();
+ getDebugDrawer()->drawCone(radius, height, upAxis, worldTransform, color);
+ break;
+
+ }
+ case CYLINDER_SHAPE_PROXYTYPE:
+ {
+ const btCylinderShape* cylinder = static_cast<const btCylinderShape*>(shape);
+ int upAxis = cylinder->getUpAxis();
+ btScalar radius = cylinder->getRadius();
+ btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis];
+ getDebugDrawer()->drawCylinder(radius, halfHeight, upAxis, worldTransform, color);
+ break;
+ }
+
+ case STATIC_PLANE_PROXYTYPE:
+ {
+ const btStaticPlaneShape* staticPlaneShape = static_cast<const btStaticPlaneShape*>(shape);
+ btScalar planeConst = staticPlaneShape->getPlaneConstant();
+ const btVector3& planeNormal = staticPlaneShape->getPlaneNormal();
+ getDebugDrawer()->drawPlane(planeNormal, planeConst,worldTransform, color);
+ break;
+
+ }
+ default:
+ {
+
+ /// for polyhedral shapes
+ if (shape->isPolyhedral())
+ {
+ btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shape;
+
+ int i;
+ if (polyshape->getConvexPolyhedron())
+ {
+ const btConvexPolyhedron* poly = polyshape->getConvexPolyhedron();
+ for (i=0;i<poly->m_faces.size();i++)
+ {
+ btVector3 centroid(0,0,0);
+ int numVerts = poly->m_faces[i].m_indices.size();
+ if (numVerts)
+ {
+ int lastV = poly->m_faces[i].m_indices[numVerts-1];
+ for (int v=0;v<poly->m_faces[i].m_indices.size();v++)
+ {
+ int curVert = poly->m_faces[i].m_indices[v];
+ centroid+=poly->m_vertices[curVert];
+ getDebugDrawer()->drawLine(worldTransform*poly->m_vertices[lastV],worldTransform*poly->m_vertices[curVert],color);
+ lastV = curVert;
+ }
+ }
+ centroid*= btScalar(1.f)/btScalar(numVerts);
+ if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawNormals)
+ {
+ btVector3 normalColor(1,1,0);
+ btVector3 faceNormal(poly->m_faces[i].m_plane[0],poly->m_faces[i].m_plane[1],poly->m_faces[i].m_plane[2]);
+ getDebugDrawer()->drawLine(worldTransform*centroid,worldTransform*(centroid+faceNormal),normalColor);
+ }
+
+ }
+
+
+ } else
{
- btVector3 normalColor(1,1,0);
- btVector3 faceNormal(poly->m_faces[i].m_plane[0],poly->m_faces[i].m_plane[1],poly->m_faces[i].m_plane[2]);
- getDebugDrawer()->drawLine(worldTransform*centroid,worldTransform*(centroid+faceNormal),normalColor);
+ for (i=0;i<polyshape->getNumEdges();i++)
+ {
+ btVector3 a,b;
+ polyshape->getEdge(i,a,b);
+ btVector3 wa = worldTransform * a;
+ btVector3 wb = worldTransform * b;
+ getDebugDrawer()->drawLine(wa,wb,color);
+ }
}
-
- }
-
-
- } else
- {
- for (i=0;i<polyshape->getNumEdges();i++)
- {
- btVector3 a,b;
- polyshape->getEdge(i,a,b);
- btVector3 wa = worldTransform * a;
- btVector3 wb = worldTransform * b;
- getDebugDrawer()->drawLine(wa,wb,color);
- }
- }
-
-
- }
- else
- {
- switch (shape->getShapeType())
- {
-
- case BOX_SHAPE_PROXYTYPE:
- {
- const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
- btVector3 halfExtents = boxShape->getHalfExtentsWithMargin();
- getDebugDrawer()->drawBox(-halfExtents,halfExtents,worldTransform,color);
- break;
- }
-
- case SPHERE_SHAPE_PROXYTYPE:
- {
- const btSphereShape* sphereShape = static_cast<const btSphereShape*>(shape);
- btScalar radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin
-
- getDebugDrawer()->drawSphere(radius, worldTransform, color);
- break;
- }
- case MULTI_SPHERE_SHAPE_PROXYTYPE:
- {
- const btMultiSphereShape* multiSphereShape = static_cast<const btMultiSphereShape*>(shape);
-
- btTransform childTransform;
- childTransform.setIdentity();
-
- for (int i = multiSphereShape->getSphereCount()-1; i>=0;i--)
- {
- childTransform.setOrigin(multiSphereShape->getSpherePosition(i));
- getDebugDrawer()->drawSphere(multiSphereShape->getSphereRadius(i), worldTransform*childTransform, color);
- }
-
- break;
- }
- case CAPSULE_SHAPE_PROXYTYPE:
- {
- const btCapsuleShape* capsuleShape = static_cast<const btCapsuleShape*>(shape);
-
- btScalar radius = capsuleShape->getRadius();
- btScalar halfHeight = capsuleShape->getHalfHeight();
-
- int upAxis = capsuleShape->getUpAxis();
- getDebugDrawer()->drawCapsule(radius, halfHeight, upAxis, worldTransform, color);
- break;
- }
- case CONE_SHAPE_PROXYTYPE:
- {
- const btConeShape* coneShape = static_cast<const btConeShape*>(shape);
- btScalar radius = coneShape->getRadius();//+coneShape->getMargin();
- btScalar height = coneShape->getHeight();//+coneShape->getMargin();
-
- int upAxis= coneShape->getConeUpIndex();
- getDebugDrawer()->drawCone(radius, height, upAxis, worldTransform, color);
- break;
-
- }
- case CYLINDER_SHAPE_PROXYTYPE:
- {
- const btCylinderShape* cylinder = static_cast<const btCylinderShape*>(shape);
- int upAxis = cylinder->getUpAxis();
- btScalar radius = cylinder->getRadius();
- btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis];
- getDebugDrawer()->drawCylinder(radius, halfHeight, upAxis, worldTransform, color);
- break;
- }
-
- case STATIC_PLANE_PROXYTYPE:
- {
- const btStaticPlaneShape* staticPlaneShape = static_cast<const btStaticPlaneShape*>(shape);
- btScalar planeConst = staticPlaneShape->getPlaneConstant();
- const btVector3& planeNormal = staticPlaneShape->getPlaneNormal();
- getDebugDrawer()->drawPlane(planeNormal, planeConst,worldTransform, color);
- break;
-
- }
- default:
- {
-
- if (shape->isConcave())
- {
- btConcaveShape* concaveMesh = (btConcaveShape*) shape;
-
- ///@todo pass camera, for some culling? no -> we are not a graphics lib
- btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
- btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
-
- DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color);
- concaveMesh->processAllTriangles(&drawCallback,aabbMin,aabbMax);
-
- }
-
- if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE)
- {
- btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*) shape;
- //todo: pass camera for some culling
- btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
- btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
- //DebugDrawcallback drawCallback;
- DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color);
- convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax);
- }
-
-
-
- }
- }
+
+
+ }
+
+ if (shape->isConcave())
+ {
+ btConcaveShape* concaveMesh = (btConcaveShape*) shape;
+
+ ///@todo pass camera, for some culling? no -> we are not a graphics lib
+ btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+ btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+
+ DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color);
+ concaveMesh->processAllTriangles(&drawCallback,aabbMin,aabbMax);
+
+ }
+
+ if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE)
+ {
+ btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*) shape;
+ //todo: pass camera for some culling
+ btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+ btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+ //DebugDrawcallback drawCallback;
+ DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color);
+ convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax);
+ }
+
+
+
+ }
+
}
}
}
@@ -1398,7 +1419,7 @@ void btCollisionWorld::debugDrawWorld()
if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)
{
int numManifolds = getDispatcher()->getNumManifolds();
- btVector3 color(1,0.65,0);
+ btVector3 color(1,1,0);
for (int i=0;i<numManifolds;i++)
{
btPersistentManifold* contactManifold = getDispatcher()->getManifoldByIndexInternal(i);
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
index 0a92d2d6e15..9412242e8a3 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
@@ -144,6 +144,11 @@ public:
void updateSingleAabb(btCollisionObject* colObj);
virtual void updateAabbs();
+
+ ///the computeOverlappingPairs is usually already called by performDiscreteCollisionDetection (or stepSimulation)
+ ///it can be useful to use if you perform ray tests without collision detection/simulation
+ virtual void computeOverlappingPairs();
+
virtual void setDebugDrawer(btIDebugDraw* debugDrawer)
{
@@ -173,7 +178,7 @@ public:
struct LocalRayResult
{
- LocalRayResult(btCollisionObject* collisionObject,
+ LocalRayResult(const btCollisionObject* collisionObject,
LocalShapeInfo* localShapeInfo,
const btVector3& hitNormalLocal,
btScalar hitFraction)
@@ -184,7 +189,7 @@ public:
{
}
- btCollisionObject* m_collisionObject;
+ const btCollisionObject* m_collisionObject;
LocalShapeInfo* m_localShapeInfo;
btVector3 m_hitNormalLocal;
btScalar m_hitFraction;
@@ -195,11 +200,11 @@ public:
struct RayResultCallback
{
btScalar m_closestHitFraction;
- btCollisionObject* m_collisionObject;
+ const btCollisionObject* m_collisionObject;
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
- //@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback
- unsigned int m_flags;
+ //@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback.h. Apply any of the EFlags defined there on m_flags here to invoke.
+ unsigned int m_flags;
virtual ~RayResultCallback()
{
@@ -214,8 +219,8 @@ public:
m_collisionObject(0),
m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
m_collisionFilterMask(btBroadphaseProxy::AllFilter),
- //@BP Mod
- m_flags(0)
+ //@BP Mod
+ m_flags(0)
{
}
@@ -272,7 +277,7 @@ public:
{
}
- btAlignedObjectArray<btCollisionObject*> m_collisionObjects;
+ btAlignedObjectArray<const btCollisionObject*> m_collisionObjects;
btVector3 m_rayFromWorld;//used to calculate hitPointWorld from hitFraction
btVector3 m_rayToWorld;
@@ -306,7 +311,7 @@ public:
struct LocalConvexResult
{
- LocalConvexResult(btCollisionObject* hitCollisionObject,
+ LocalConvexResult(const btCollisionObject* hitCollisionObject,
LocalShapeInfo* localShapeInfo,
const btVector3& hitNormalLocal,
const btVector3& hitPointLocal,
@@ -320,7 +325,7 @@ public:
{
}
- btCollisionObject* m_hitCollisionObject;
+ const btCollisionObject* m_hitCollisionObject;
LocalShapeInfo* m_localShapeInfo;
btVector3 m_hitNormalLocal;
btVector3 m_hitPointLocal;
@@ -376,7 +381,7 @@ public:
btVector3 m_hitNormalWorld;
btVector3 m_hitPointWorld;
- btCollisionObject* m_hitCollisionObject;
+ const btCollisionObject* m_hitCollisionObject;
virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace)
{
@@ -421,7 +426,7 @@ public:
return collides;
}
- virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1) = 0;
+ virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) = 0;
};
@@ -457,6 +462,10 @@ public:
const btTransform& colObjWorldTransform,
RayResultCallback& resultCallback);
+ static void rayTestSingleInternal(const btTransform& rayFromTrans,const btTransform& rayToTrans,
+ const btCollisionObjectWrapper* collisionObjectWrap,
+ RayResultCallback& resultCallback);
+
/// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest.
static void objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans,
btCollisionObject* collisionObject,
@@ -464,6 +473,10 @@ public:
const btTransform& colObjWorldTransform,
ConvexResultCallback& resultCallback, btScalar allowedPenetration);
+ static void objectQuerySingleInternal(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
+ const btCollisionObjectWrapper* colObjWrap,
+ ConvexResultCallback& resultCallback, btScalar allowedPenetration);
+
virtual void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter);
btCollisionObjectArray& getCollisionObjectArray()
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
index 54889a6375d..39b86a28918 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
@@ -20,30 +20,32 @@ subject to the following restrictions:
#include "LinearMath/btIDebugDraw.h"
#include "LinearMath/btAabbUtil2.h"
#include "btManifoldResult.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
-:btActivatingCollisionAlgorithm(ci,body0,body1),
+btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
+:btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
m_isSwapped(isSwapped),
m_sharedManifold(ci.m_manifold)
{
m_ownsManifold = false;
- btCollisionObject* colObj = m_isSwapped? body1 : body0;
- btAssert (colObj->getCollisionShape()->isCompound());
+ const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
+ btAssert (colObjWrap->getCollisionShape()->isCompound());
- btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
+ const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
m_compoundShapeRevision = compoundShape->getUpdateRevision();
- preallocateChildAlgorithms(body0,body1);
+
+ preallocateChildAlgorithms(body0Wrap,body1Wrap);
}
-void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1)
+void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
- btCollisionObject* colObj = m_isSwapped? body1 : body0;
- btCollisionObject* otherObj = m_isSwapped? body0 : body1;
- btAssert (colObj->getCollisionShape()->isCompound());
+ const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
+ const btCollisionObjectWrapper* otherObjWrap = m_isSwapped? body0Wrap : body1Wrap;
+ btAssert (colObjWrap->getCollisionShape()->isCompound());
- btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
+ const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
int numChildren = compoundShape->getNumChildShapes();
int i;
@@ -56,11 +58,11 @@ void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(btCollisionObject*
m_childCollisionAlgorithms[i] = 0;
} else
{
- btCollisionShape* tmpShape = colObj->getCollisionShape();
- btCollisionShape* childShape = compoundShape->getChildShape(i);
- colObj->internalSetTemporaryCollisionShape( childShape );
- m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(colObj,otherObj,m_sharedManifold);
- colObj->internalSetTemporaryCollisionShape( tmpShape );
+
+ const btCollisionShape* childShape = compoundShape->getChildShape(i);
+
+ btCollisionObjectWrapper childWrap(colObjWrap,childShape,colObjWrap->getCollisionObject(),colObjWrap->getWorldTransform(),-1,i);//wrong child trans, but unused (hopefully)
+ m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(&childWrap,otherObjWrap,m_sharedManifold);
}
}
}
@@ -92,19 +94,16 @@ struct btCompoundLeafCallback : btDbvt::ICollide
public:
- btCollisionObject* m_compoundColObj;
- btCollisionObject* m_otherObj;
+ const btCollisionObjectWrapper* m_compoundColObjWrap;
+ const btCollisionObjectWrapper* m_otherObjWrap;
btDispatcher* m_dispatcher;
const btDispatcherInfo& m_dispatchInfo;
btManifoldResult* m_resultOut;
btCollisionAlgorithm** m_childCollisionAlgorithms;
btPersistentManifold* m_sharedManifold;
-
-
-
-
- btCompoundLeafCallback (btCollisionObject* compoundObj,btCollisionObject* otherObj,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut,btCollisionAlgorithm** childCollisionAlgorithms,btPersistentManifold* sharedManifold)
- :m_compoundColObj(compoundObj),m_otherObj(otherObj),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
+
+ btCompoundLeafCallback (const btCollisionObjectWrapper* compoundObjWrap,const btCollisionObjectWrapper* otherObjWrap,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut,btCollisionAlgorithm** childCollisionAlgorithms,btPersistentManifold* sharedManifold)
+ :m_compoundColObjWrap(compoundObjWrap),m_otherObjWrap(otherObjWrap),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
m_childCollisionAlgorithms(childCollisionAlgorithms),
m_sharedManifold(sharedManifold)
{
@@ -112,73 +111,89 @@ public:
}
- void ProcessChildShape(btCollisionShape* childShape,int index)
+ void ProcessChildShape(const btCollisionShape* childShape,int index)
{
btAssert(index>=0);
- btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape());
+ const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(m_compoundColObjWrap->getCollisionShape());
btAssert(index<compoundShape->getNumChildShapes());
//backup
- btTransform orgTrans = m_compoundColObj->getWorldTransform();
- btTransform orgInterpolationTrans = m_compoundColObj->getInterpolationWorldTransform();
+ btTransform orgTrans = m_compoundColObjWrap->getWorldTransform();
+ btTransform orgInterpolationTrans = m_compoundColObjWrap->getWorldTransform();
const btTransform& childTrans = compoundShape->getChildTransform(index);
btTransform newChildWorldTrans = orgTrans*childTrans ;
//perform an AABB check first
btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
- m_otherObj->getCollisionShape()->getAabb(m_otherObj->getWorldTransform(),aabbMin1,aabbMax1);
+ m_otherObjWrap->getCollisionShape()->getAabb(m_otherObjWrap->getWorldTransform(),aabbMin1,aabbMax1);
if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
{
- m_compoundColObj->setWorldTransform( newChildWorldTrans);
- m_compoundColObj->setInterpolationWorldTransform(newChildWorldTrans);
+ btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap,childShape,m_compoundColObjWrap->getCollisionObject(),newChildWorldTrans,-1,index);
- //the contactpoint is still projected back using the original inverted worldtrans
- btCollisionShape* tmpShape = m_compoundColObj->getCollisionShape();
- m_compoundColObj->internalSetTemporaryCollisionShape( childShape );
+ //the contactpoint is still projected back using the original inverted worldtrans
if (!m_childCollisionAlgorithms[index])
- m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(m_compoundColObj,m_otherObj,m_sharedManifold);
+ m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(&compoundWrap,m_otherObjWrap,m_sharedManifold);
+
+
+ const btCollisionObjectWrapper* tmpWrap = 0;
///detect swapping case
- if (m_resultOut->getBody0Internal() == m_compoundColObj)
+ if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject())
{
+ tmpWrap = m_resultOut->getBody0Wrap();
+ m_resultOut->setBody0Wrap(&compoundWrap);
m_resultOut->setShapeIdentifiersA(-1,index);
} else
{
+ tmpWrap = m_resultOut->getBody1Wrap();
+ m_resultOut->setBody1Wrap(&compoundWrap);
m_resultOut->setShapeIdentifiersB(-1,index);
}
- m_childCollisionAlgorithms[index]->processCollision(m_compoundColObj,m_otherObj,m_dispatchInfo,m_resultOut);
+
+ m_childCollisionAlgorithms[index]->processCollision(&compoundWrap,m_otherObjWrap,m_dispatchInfo,m_resultOut);
+
+#if 0
if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
{
btVector3 worldAabbMin,worldAabbMax;
m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1));
m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1));
}
+#endif
+
+ if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject())
+ {
+ m_resultOut->setBody0Wrap(tmpWrap);
+ } else
+ {
+ m_resultOut->setBody1Wrap(tmpWrap);
+ }
- //revert back transform
- m_compoundColObj->internalSetTemporaryCollisionShape( tmpShape);
- m_compoundColObj->setWorldTransform( orgTrans );
- m_compoundColObj->setInterpolationWorldTransform(orgInterpolationTrans);
}
}
void Process(const btDbvtNode* leaf)
{
int index = leaf->dataAsInt;
- btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape());
- btCollisionShape* childShape = compoundShape->getChildShape(index);
+ const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(m_compoundColObjWrap->getCollisionShape());
+ const btCollisionShape* childShape = compoundShape->getChildShape(index);
+
+#if 0
if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
{
btVector3 worldAabbMin,worldAabbMax;
- btTransform orgTrans = m_compoundColObj->getWorldTransform();
+ btTransform orgTrans = m_compoundColObjWrap->getWorldTransform();
btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax);
m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0));
}
+#endif
+
ProcessChildShape(childShape,index);
}
@@ -189,15 +204,13 @@ public:
-void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
- btCollisionObject* colObj = m_isSwapped? body1 : body0;
- btCollisionObject* otherObj = m_isSwapped? body0 : body1;
-
-
+ const btCollisionObjectWrapper* colObjWrap = m_isSwapped? body1Wrap : body0Wrap;
+ const btCollisionObjectWrapper* otherObjWrap = m_isSwapped? body0Wrap : body1Wrap;
- btAssert (colObj->getCollisionShape()->isCompound());
- btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
+ btAssert (colObjWrap->getCollisionShape()->isCompound());
+ const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
///btCompoundShape might have changed:
////make sure the internal child collision algorithm caches are still valid
@@ -206,13 +219,13 @@ void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,bt
///clear and update all
removeChildAlgorithms();
- preallocateChildAlgorithms(body0,body1);
+ preallocateChildAlgorithms(body0Wrap,body1Wrap);
}
- btDbvt* tree = compoundShape->getDynamicAabbTree();
+ const btDbvt* tree = compoundShape->getDynamicAabbTree();
//use a dynamic aabb tree to cull potential child-overlaps
- btCompoundLeafCallback callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
+ btCompoundLeafCallback callback(colObjWrap,otherObjWrap,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
///we need to refresh all contact manifolds
///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep
@@ -244,8 +257,8 @@ void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,bt
btVector3 localAabbMin,localAabbMax;
btTransform otherInCompoundSpace;
- otherInCompoundSpace = colObj->getWorldTransform().inverse() * otherObj->getWorldTransform();
- otherObj->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax);
+ otherInCompoundSpace = colObjWrap->getWorldTransform().inverse() * otherObjWrap->getWorldTransform();
+ otherObjWrap->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax);
const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
//process all children, that overlap with the given AABB bounds
@@ -267,7 +280,7 @@ void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,bt
int numChildren = m_childCollisionAlgorithms.size();
int i;
btManifoldArray manifoldArray;
- btCollisionShape* childShape = 0;
+ const btCollisionShape* childShape = 0;
btTransform orgTrans;
btTransform orgInterpolationTrans;
btTransform newChildWorldTrans;
@@ -279,14 +292,14 @@ void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,bt
{
childShape = compoundShape->getChildShape(i);
//if not longer overlapping, remove the algorithm
- orgTrans = colObj->getWorldTransform();
- orgInterpolationTrans = colObj->getInterpolationWorldTransform();
+ orgTrans = colObjWrap->getWorldTransform();
+ orgInterpolationTrans = colObjWrap->getWorldTransform();
const btTransform& childTrans = compoundShape->getChildTransform(i);
newChildWorldTrans = orgTrans*childTrans ;
//perform an AABB check first
childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
- otherObj->getCollisionShape()->getAabb(otherObj->getWorldTransform(),aabbMin1,aabbMax1);
+ otherObjWrap->getCollisionShape()->getAabb(otherObjWrap->getWorldTransform(),aabbMin1,aabbMax1);
if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
{
@@ -301,7 +314,8 @@ void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,bt
btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
-
+ btAssert(0);
+ //needs to be fixed, using btCollisionObjectWrapper and NOT modifying internal data structures
btCollisionObject* colObj = m_isSwapped? body1 : body0;
btCollisionObject* otherObj = m_isSwapped? body0 : body1;
@@ -324,8 +338,7 @@ btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject*
btScalar frac;
for (i=0;i<numChildren;i++)
{
- //temporarily exchange parent btCollisionShape with childShape, and recurse
- btCollisionShape* childShape = compoundShape->getChildShape(i);
+ //btCollisionShape* childShape = compoundShape->getChildShape(i);
//backup
orgTrans = colObj->getWorldTransform();
@@ -334,15 +347,15 @@ btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject*
//btTransform newChildWorldTrans = orgTrans*childTrans ;
colObj->setWorldTransform( orgTrans*childTrans );
- btCollisionShape* tmpShape = colObj->getCollisionShape();
- colObj->internalSetTemporaryCollisionShape( childShape );
+ //btCollisionShape* tmpShape = colObj->getCollisionShape();
+ //colObj->internalSetTemporaryCollisionShape( childShape );
frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut);
if (frac<hitFraction)
{
hitFraction = frac;
}
//revert back
- colObj->internalSetTemporaryCollisionShape( tmpShape);
+ //colObj->internalSetTemporaryCollisionShape( tmpShape);
colObj->setWorldTransform( orgTrans);
}
return hitFraction;
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h
index 404574989ab..b16fc524672 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h
@@ -41,15 +41,15 @@ class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm
void removeChildAlgorithms();
- void preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1);
+ void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
public:
- btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
+ btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
virtual ~btCompoundCollisionAlgorithm();
- virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
@@ -65,19 +65,19 @@ public:
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
- return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,false);
+ return new(mem) btCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,false);
}
};
struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
- return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,true);
+ return new(mem) btCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,true);
}
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp
index db7f884ac82..3e1afede1bf 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp
@@ -43,7 +43,7 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
-
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
btConvex2dConvex2dAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
{
@@ -57,8 +57,8 @@ btConvex2dConvex2dAlgorithm::CreateFunc::~CreateFunc()
{
}
-btConvex2dConvex2dAlgorithm::btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold)
-: btActivatingCollisionAlgorithm(ci,body0,body1),
+btConvex2dConvex2dAlgorithm::btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold)
+: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
m_simplexSolver(simplexSolver),
m_pdSolver(pdSolver),
m_ownManifold (false),
@@ -67,8 +67,8 @@ m_lowLevelOfDetail(false),
m_numPerturbationIterations(numPerturbationIterations),
m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
{
- (void)body0;
- (void)body1;
+ (void)body0Wrap;
+ (void)body1Wrap;
}
@@ -96,13 +96,13 @@ extern btScalar gContactBreakingThreshold;
//
// Convex-Convex collision algorithm
//
-void btConvex2dConvex2dAlgorithm ::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btConvex2dConvex2dAlgorithm ::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
{
//swapped?
- m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
+ m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
m_ownManifold = true;
}
resultOut->setPersistentManifold(m_manifoldPtr);
@@ -111,8 +111,8 @@ void btConvex2dConvex2dAlgorithm ::processCollision (btCollisionObject* body0,bt
//resultOut->getPersistentManifold()->clearManifold();
- btConvexShape* min0 = static_cast<btConvexShape*>(body0->getCollisionShape());
- btConvexShape* min1 = static_cast<btConvexShape*>(body1->getCollisionShape());
+ const btConvexShape* min0 = static_cast<const btConvexShape*>(body0Wrap->getCollisionShape());
+ const btConvexShape* min1 = static_cast<const btConvexShape*>(body1Wrap->getCollisionShape());
btVector3 normalOnB;
btVector3 pointOnBWorld;
@@ -133,8 +133,8 @@ void btConvex2dConvex2dAlgorithm ::processCollision (btCollisionObject* body0,bt
}
input.m_stackAlloc = dispatchInfo.m_stackAllocator;
- input.m_transformA = body0->getWorldTransform();
- input.m_transformB = body1->getWorldTransform();
+ input.m_transformA = body0Wrap->getWorldTransform();
+ input.m_transformB = body1Wrap->getWorldTransform();
gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h
index 53d13b87151..18d9385a180 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h
@@ -45,12 +45,12 @@ class btConvex2dConvex2dAlgorithm : public btActivatingCollisionAlgorithm
public:
- btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
+ btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
virtual ~btConvex2dConvex2dAlgorithm();
- virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
@@ -82,10 +82,10 @@ public:
virtual ~CreateFunc();
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvex2dConvex2dAlgorithm));
- return new(mem) btConvex2dConvex2dAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+ return new(mem) btConvex2dConvex2dAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
}
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
index d2b2c221426..18fde771b14 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
@@ -25,11 +25,12 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "LinearMath/btIDebugDraw.h"
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
-: btActivatingCollisionAlgorithm(ci,body0,body1),
+btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
+: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
m_isSwapped(isSwapped),
-m_btConvexTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped)
+m_btConvexTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped)
{
}
@@ -46,17 +47,17 @@ void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray&
}
-btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped):
+btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped):
m_dispatcher(dispatcher),
m_dispatchInfoPtr(0)
{
- m_convexBody = isSwapped? body1:body0;
- m_triBody = isSwapped? body0:body1;
+ m_convexBodyWrap = isSwapped? body1Wrap:body0Wrap;
+ m_triBodyWrap = isSwapped? body0Wrap:body1Wrap;
//
// create the manifold from the dispatcher 'manifold pool'
//
- m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody);
+ m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBodyWrap->getCollisionObject(),m_triBodyWrap->getCollisionObject());
clearCache();
}
@@ -88,7 +89,7 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i
btCollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher1 = m_dispatcher;
- btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBody);
+ //const btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBodyWrap->getCollisionObject());
#if 0
@@ -103,46 +104,63 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i
}
#endif
- if (m_convexBody->getCollisionShape()->isConvex())
+ if (m_convexBodyWrap->getCollisionShape()->isConvex())
{
btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
tm.setMargin(m_collisionMarginTriangle);
- btCollisionShape* tmpShape = ob->getCollisionShape();
- ob->internalSetTemporaryCollisionShape( &tm );
+
+ btCollisionObjectWrapper triObWrap(m_triBodyWrap,&tm,m_triBodyWrap->getCollisionObject(),m_triBodyWrap->getWorldTransform(),partId,triangleIndex);//correct transform?
+ btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap,&triObWrap,m_manifoldPtr);
- btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr);
+ const btCollisionObjectWrapper* tmpWrap = 0;
- if (m_resultOut->getBody0Internal() == m_triBody)
+ if (m_resultOut->getBody0Internal() == m_triBodyWrap->getCollisionObject())
{
+ tmpWrap = m_resultOut->getBody0Wrap();
+ m_resultOut->setBody0Wrap(&triObWrap);
m_resultOut->setShapeIdentifiersA(partId,triangleIndex);
}
else
{
+ tmpWrap = m_resultOut->getBody1Wrap();
+ m_resultOut->setBody1Wrap(&triObWrap);
m_resultOut->setShapeIdentifiersB(partId,triangleIndex);
}
- colAlgo->processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
+ colAlgo->processCollision(m_convexBodyWrap,&triObWrap,*m_dispatchInfoPtr,m_resultOut);
+
+ if (m_resultOut->getBody0Internal() == m_triBodyWrap->getCollisionObject())
+ {
+ m_resultOut->setBody0Wrap(tmpWrap);
+ } else
+ {
+ m_resultOut->setBody1Wrap(tmpWrap);
+ }
+
+
+
colAlgo->~btCollisionAlgorithm();
ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
- ob->internalSetTemporaryCollisionShape( tmpShape);
}
-
}
-void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut)
{
+ m_convexBodyWrap = convexBodyWrap;
+ m_triBodyWrap = triBodyWrap;
+
m_dispatchInfoPtr = &dispatchInfo;
m_collisionMarginTriangle = collisionMarginTriangle;
m_resultOut = resultOut;
//recalc aabbs
btTransform convexInTriangleSpace;
- convexInTriangleSpace = m_triBody->getWorldTransform().inverse() * m_convexBody->getWorldTransform();
- btCollisionShape* convexShape = static_cast<btCollisionShape*>(m_convexBody->getCollisionShape());
+ convexInTriangleSpace = m_triBodyWrap->getWorldTransform().inverse() * m_convexBodyWrap->getWorldTransform();
+ const btCollisionShape* convexShape = static_cast<const btCollisionShape*>(m_convexBodyWrap->getCollisionShape());
//CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape);
convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax);
btScalar extraMargin = collisionMarginTriangle;
@@ -159,35 +177,34 @@ void btConvexConcaveCollisionAlgorithm::clearCache()
}
-void btConvexConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btConvexConcaveCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
- btCollisionObject* convexBody = m_isSwapped ? body1 : body0;
- btCollisionObject* triBody = m_isSwapped ? body0 : body1;
+ const btCollisionObjectWrapper* convexBodyWrap = m_isSwapped ? body1Wrap : body0Wrap;
+ const btCollisionObjectWrapper* triBodyWrap = m_isSwapped ? body0Wrap : body1Wrap;
- if (triBody->getCollisionShape()->isConcave())
+ if (triBodyWrap->getCollisionShape()->isConcave())
{
- btCollisionObject* triOb = triBody;
- btConcaveShape* concaveShape = static_cast<btConcaveShape*>( triOb->getCollisionShape());
- if (convexBody->getCollisionShape()->isConvex())
+ const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>( triBodyWrap->getCollisionShape());
+
+ if (convexBodyWrap->getCollisionShape()->isConvex())
{
btScalar collisionMarginTriangle = concaveShape->getMargin();
resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
- m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut);
-
- //Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here.
- //m_dispatcher->clearManifold(m_btConvexTriangleCallback.m_manifoldPtr);
+ m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,convexBodyWrap,triBodyWrap,resultOut);
- m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody);
+ m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBodyWrap->getCollisionObject(),triBodyWrap->getCollisionObject());
concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax());
resultOut->refreshContactPoints();
+
+ m_btConvexTriangleCallback.clearWrapperData();
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
index f718d1dec25..e90d06eb191 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
@@ -28,8 +28,8 @@ class btDispatcher;
///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called.
class btConvexTriangleCallback : public btTriangleCallback
{
- btCollisionObject* m_convexBody;
- btCollisionObject* m_triBody;
+ const btCollisionObjectWrapper* m_convexBodyWrap;
+ const btCollisionObjectWrapper* m_triBodyWrap;
btVector3 m_aabbMin;
btVector3 m_aabbMax ;
@@ -45,10 +45,15 @@ int m_triangleCount;
btPersistentManifold* m_manifoldPtr;
- btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
+ btConvexTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
- void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut);
+ void clearWrapperData()
+ {
+ m_convexBodyWrap = 0;
+ m_triBodyWrap = 0;
+ }
virtual ~btConvexTriangleCallback();
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
@@ -81,11 +86,11 @@ class btConvexConcaveCollisionAlgorithm : public btActivatingCollisionAlgorithm
public:
- btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
+ btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
virtual ~btConvexConcaveCollisionAlgorithm();
- virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
@@ -95,19 +100,19 @@ public:
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
- return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,false);
+ return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,false);
}
};
struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
- return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,true);
+ return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,true);
}
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
index dd1f3e2490f..62f98a846f4 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
@@ -52,7 +52,7 @@ subject to the following restrictions:
#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h"
-
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
///////////
@@ -191,8 +191,8 @@ btConvexConvexAlgorithm::CreateFunc::~CreateFunc()
{
}
-btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold)
-: btActivatingCollisionAlgorithm(ci,body0,body1),
+btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold)
+: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
m_simplexSolver(simplexSolver),
m_pdSolver(pdSolver),
m_ownManifold (false),
@@ -205,8 +205,8 @@ m_sepDistance((static_cast<btConvexShape*>(body0->getCollisionShape()))->getAngu
m_numPerturbationIterations(numPerturbationIterations),
m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
{
- (void)body0;
- (void)body1;
+ (void)body0Wrap;
+ (void)body1Wrap;
}
@@ -289,13 +289,13 @@ extern btScalar gContactBreakingThreshold;
//
// Convex-Convex collision algorithm
//
-void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btConvexConvexAlgorithm ::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
{
//swapped?
- m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
+ m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
m_ownManifold = true;
}
resultOut->setPersistentManifold(m_manifoldPtr);
@@ -304,8 +304,8 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
//resultOut->getPersistentManifold()->clearManifold();
- btConvexShape* min0 = static_cast<btConvexShape*>(body0->getCollisionShape());
- btConvexShape* min1 = static_cast<btConvexShape*>(body1->getCollisionShape());
+ const btConvexShape* min0 = static_cast<const btConvexShape*>(body0Wrap->getCollisionShape());
+ const btConvexShape* min1 = static_cast<const btConvexShape*>(body1Wrap->getCollisionShape());
btVector3 normalOnB;
btVector3 pointOnBWorld;
@@ -314,14 +314,14 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
{
btCapsuleShape* capsuleA = (btCapsuleShape*) min0;
btCapsuleShape* capsuleB = (btCapsuleShape*) min1;
- btVector3 localScalingA = capsuleA->getLocalScaling();
- btVector3 localScalingB = capsuleB->getLocalScaling();
+ // btVector3 localScalingA = capsuleA->getLocalScaling();
+ // btVector3 localScalingB = capsuleB->getLocalScaling();
btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld,capsuleA->getHalfHeight(),capsuleA->getRadius(),
capsuleB->getHalfHeight(),capsuleB->getRadius(),capsuleA->getUpAxis(),capsuleB->getUpAxis(),
- body0->getWorldTransform(),body1->getWorldTransform(),threshold);
+ body0Wrap->getWorldTransform(),body1Wrap->getWorldTransform(),threshold);
if (dist<threshold)
{
@@ -374,8 +374,8 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
}
input.m_stackAlloc = dispatchInfo.m_stackAllocator;
- input.m_transformA = body0->getWorldTransform();
- input.m_transformB = body1->getWorldTransform();
+ input.m_transformA = body0Wrap->getWorldTransform();
+ input.m_transformB = body1Wrap->getWorldTransform();
@@ -407,9 +407,51 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
{
}
};
+
+
+ struct btWithoutMarginResult : public btDiscreteCollisionDetectorInterface::Result
+ {
+ btDiscreteCollisionDetectorInterface::Result* m_originalResult;
+ btVector3 m_reportedNormalOnWorld;
+ btScalar m_marginOnA;
+ btScalar m_marginOnB;
+ btScalar m_reportedDistance;
+
+ bool m_foundResult;
+ btWithoutMarginResult(btDiscreteCollisionDetectorInterface::Result* result, btScalar marginOnA, btScalar marginOnB)
+ :m_originalResult(result),
+ m_marginOnA(marginOnA),
+ m_marginOnB(marginOnB),
+ m_foundResult(false)
+ {
+ }
+
+ virtual void setShapeIdentifiersA(int partId0,int index0){}
+ virtual void setShapeIdentifiersB(int partId1,int index1){}
+ virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorldOrg,btScalar depthOrg)
+ {
+ m_reportedDistance = depthOrg;
+ m_reportedNormalOnWorld = normalOnBInWorld;
+
+ btVector3 adjustedPointB = pointInWorldOrg - normalOnBInWorld*m_marginOnB;
+ m_reportedDistance = depthOrg+(m_marginOnA+m_marginOnB);
+ if (m_reportedDistance<0.f)
+ {
+ m_foundResult = true;
+ }
+ m_originalResult->addContactPoint(normalOnBInWorld,adjustedPointB,m_reportedDistance);
+ }
+ };
+
btDummyResult dummy;
+///btBoxShape is an exception: its vertices are created WITH margin so don't subtract it
+
+ btScalar min0Margin = min0->getShapeType()==BOX_SHAPE_PROXYTYPE? 0.f : min0->getMargin();
+ btScalar min1Margin = min1->getShapeType()==BOX_SHAPE_PROXYTYPE? 0.f : min1->getMargin();
+
+ btWithoutMarginResult withoutMargin(resultOut, min0Margin,min1Margin);
btPolyhedralConvexShape* polyhedronA = (btPolyhedralConvexShape*) min0;
btPolyhedralConvexShape* polyhedronB = (btPolyhedralConvexShape*) min1;
@@ -429,39 +471,42 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
{
foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis(
*polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
- body0->getWorldTransform(),
- body1->getWorldTransform(),
- sepNormalWorldSpace);
+ body0Wrap->getWorldTransform(),
+ body1Wrap->getWorldTransform(),
+ sepNormalWorldSpace,*resultOut);
} else
{
#ifdef ZERO_MARGIN
gjkPairDetector.setIgnoreMargin(true);
gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
#else
- //gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
- gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw);
+
+
+ gjkPairDetector.getClosestPoints(input,withoutMargin,dispatchInfo.m_debugDraw);
+ //gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw);
#endif //ZERO_MARGIN
- btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
- if (l2>SIMD_EPSILON)
+ //btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
+ //if (l2>SIMD_EPSILON)
{
- sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2);
+ sepNormalWorldSpace = withoutMargin.m_reportedNormalOnWorld;//gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2);
//minDist = -1e30f;//gjkPairDetector.getCachedSeparatingDistance();
- minDist = gjkPairDetector.getCachedSeparatingDistance()-min0->getMargin()-min1->getMargin();
+ minDist = withoutMargin.m_reportedDistance;//gjkPairDetector.getCachedSeparatingDistance()+min0->getMargin()+min1->getMargin();
#ifdef ZERO_MARGIN
foundSepAxis = true;//gjkPairDetector.getCachedSeparatingDistance()<0.f;
#else
- foundSepAxis = gjkPairDetector.getCachedSeparatingDistance()<(min0->getMargin()+min1->getMargin());
+ foundSepAxis = withoutMargin.m_foundResult && minDist<0;//-(min0->getMargin()+min1->getMargin());
#endif
}
}
if (foundSepAxis)
{
+
// printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ());
btPolyhedralContactClipping::clipHullAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
- body0->getWorldTransform(),
- body1->getWorldTransform(), minDist-threshold, threshold, *resultOut);
+ body0Wrap->getWorldTransform(),
+ body1Wrap->getWorldTransform(), minDist-threshold, threshold, *resultOut);
}
if (m_ownManifold)
@@ -478,9 +523,9 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
btVertexArray vertices;
btTriangleShape* tri = (btTriangleShape*)polyhedronB;
- vertices.push_back( body1->getWorldTransform()*tri->m_vertices1[0]);
- vertices.push_back( body1->getWorldTransform()*tri->m_vertices1[1]);
- vertices.push_back( body1->getWorldTransform()*tri->m_vertices1[2]);
+ vertices.push_back( body1Wrap->getWorldTransform()*tri->m_vertices1[0]);
+ vertices.push_back( body1Wrap->getWorldTransform()*tri->m_vertices1[1]);
+ vertices.push_back( body1Wrap->getWorldTransform()*tri->m_vertices1[2]);
//tri->initializePolyhedralFeatures();
@@ -496,9 +541,9 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
polyhedronB->initializePolyhedralFeatures();
foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis(
*polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
- body0->getWorldTransform(),
- body1->getWorldTransform(),
- sepNormalWorldSpace);
+ body0Wrap->getWorldTransform(),
+ body1Wrap->getWorldTransform(),
+ sepNormalWorldSpace,*resultOut);
// printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ());
} else
@@ -525,7 +570,7 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
if (foundSepAxis)
{
btPolyhedralContactClipping::clipFaceAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(),
- body0->getWorldTransform(), vertices, minDist-threshold, maxDist, *resultOut);
+ body0Wrap->getWorldTransform(), vertices, minDist-threshold, maxDist, *resultOut);
}
@@ -599,15 +644,15 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl
if (perturbeA)
{
- input.m_transformA.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body0->getWorldTransform().getBasis());
- input.m_transformB = body1->getWorldTransform();
+ input.m_transformA.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body0Wrap->getWorldTransform().getBasis());
+ input.m_transformB = body1Wrap->getWorldTransform();
#ifdef DEBUG_CONTACTS
dispatchInfo.m_debugDraw->drawTransform(input.m_transformA,10.0);
#endif //DEBUG_CONTACTS
} else
{
- input.m_transformA = body0->getWorldTransform();
- input.m_transformB.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body1->getWorldTransform().getBasis());
+ input.m_transformA = body0Wrap->getWorldTransform();
+ input.m_transformB.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body1Wrap->getWorldTransform().getBasis());
#ifdef DEBUG_CONTACTS
dispatchInfo.m_debugDraw->drawTransform(input.m_transformB,10.0);
#endif
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h
index 4380b80eb4d..51db0c6548d 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h
@@ -59,12 +59,11 @@ class btConvexConvexAlgorithm : public btActivatingCollisionAlgorithm
public:
- btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
-
+ btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
virtual ~btConvexConvexAlgorithm();
- virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
@@ -96,10 +95,10 @@ public:
virtual ~CreateFunc();
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm));
- return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+ return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
}
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
index b2e9bfaf593..cce2d95bcf9 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
@@ -19,10 +19,11 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
//#include <stdio.h>
-btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold)
+btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold)
: btCollisionAlgorithm(ci),
m_ownManifold(false),
m_manifoldPtr(mf),
@@ -30,12 +31,12 @@ m_isSwapped(isSwapped),
m_numPerturbationIterations(numPerturbationIterations),
m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
{
- btCollisionObject* convexObj = m_isSwapped? col1 : col0;
- btCollisionObject* planeObj = m_isSwapped? col0 : col1;
+ const btCollisionObjectWrapper* convexObjWrap = m_isSwapped? col1Wrap : col0Wrap;
+ const btCollisionObjectWrapper* planeObjWrap = m_isSwapped? col0Wrap : col1Wrap;
- if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObj,planeObj))
+ if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObjWrap->getCollisionObject(),planeObjWrap->getCollisionObject()))
{
- m_manifoldPtr = m_dispatcher->getNewManifold(convexObj,planeObj);
+ m_manifoldPtr = m_dispatcher->getNewManifold(convexObjWrap->getCollisionObject(),planeObjWrap->getCollisionObject());
m_ownManifold = true;
}
}
@@ -50,25 +51,25 @@ btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
}
}
-void btConvexPlaneCollisionAlgorithm::collideSingleContact (const btQuaternion& perturbeRot, btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btConvexPlaneCollisionAlgorithm::collideSingleContact (const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
- btCollisionObject* convexObj = m_isSwapped? body1 : body0;
- btCollisionObject* planeObj = m_isSwapped? body0: body1;
+ const btCollisionObjectWrapper* convexObjWrap = m_isSwapped? body1Wrap : body0Wrap;
+ const btCollisionObjectWrapper* planeObjWrap = m_isSwapped? body0Wrap: body1Wrap;
- btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape();
- btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape();
+ btConvexShape* convexShape = (btConvexShape*) convexObjWrap->getCollisionShape();
+ btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObjWrap->getCollisionShape();
bool hasCollision = false;
const btVector3& planeNormal = planeShape->getPlaneNormal();
const btScalar& planeConstant = planeShape->getPlaneConstant();
- btTransform convexWorldTransform = convexObj->getWorldTransform();
+ btTransform convexWorldTransform = convexObjWrap->getWorldTransform();
btTransform convexInPlaneTrans;
- convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexWorldTransform;
+ convexInPlaneTrans= planeObjWrap->getWorldTransform().inverse() * convexWorldTransform;
//now perturbe the convex-world transform
convexWorldTransform.getBasis()*=btMatrix3x3(perturbeRot);
btTransform planeInConvex;
- planeInConvex= convexWorldTransform.inverse() * planeObj->getWorldTransform();
+ planeInConvex= convexWorldTransform.inverse() * planeObjWrap->getWorldTransform();
btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
@@ -76,53 +77,53 @@ void btConvexPlaneCollisionAlgorithm::collideSingleContact (const btQuaternion&
btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
- btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected;
+ btVector3 vtxInPlaneWorld = planeObjWrap->getWorldTransform() * vtxInPlaneProjected;
hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
resultOut->setPersistentManifold(m_manifoldPtr);
if (hasCollision)
{
/// report a contact. internally this will be kept persistent, and contact reduction is done
- btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal;
+ btVector3 normalOnSurfaceB = planeObjWrap->getWorldTransform().getBasis() * planeNormal;
btVector3 pOnB = vtxInPlaneWorld;
resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
}
}
-void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btConvexPlaneCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)dispatchInfo;
if (!m_manifoldPtr)
return;
- btCollisionObject* convexObj = m_isSwapped? body1 : body0;
- btCollisionObject* planeObj = m_isSwapped? body0: body1;
+ const btCollisionObjectWrapper* convexObjWrap = m_isSwapped? body1Wrap : body0Wrap;
+ const btCollisionObjectWrapper* planeObjWrap = m_isSwapped? body0Wrap: body1Wrap;
- btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape();
- btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape();
+ btConvexShape* convexShape = (btConvexShape*) convexObjWrap->getCollisionShape();
+ btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObjWrap->getCollisionShape();
bool hasCollision = false;
const btVector3& planeNormal = planeShape->getPlaneNormal();
const btScalar& planeConstant = planeShape->getPlaneConstant();
btTransform planeInConvex;
- planeInConvex= convexObj->getWorldTransform().inverse() * planeObj->getWorldTransform();
+ planeInConvex= convexObjWrap->getWorldTransform().inverse() * planeObjWrap->getWorldTransform();
btTransform convexInPlaneTrans;
- convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexObj->getWorldTransform();
+ convexInPlaneTrans= planeObjWrap->getWorldTransform().inverse() * convexObjWrap->getWorldTransform();
btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
btVector3 vtxInPlane = convexInPlaneTrans(vtx);
btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
- btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected;
+ btVector3 vtxInPlaneWorld = planeObjWrap->getWorldTransform() * vtxInPlaneProjected;
hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
resultOut->setPersistentManifold(m_manifoldPtr);
if (hasCollision)
{
/// report a contact. internally this will be kept persistent, and contact reduction is done
- btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal;
+ btVector3 normalOnSurfaceB = planeObjWrap->getWorldTransform().getBasis() * planeNormal;
btVector3 pOnB = vtxInPlaneWorld;
resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
}
@@ -148,7 +149,7 @@ void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0
{
btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations));
btQuaternion rotq(planeNormal,iterationAngle);
- collideSingleContact(rotq.inverse()*perturbeRot*rotq,body0,body1,dispatchInfo,resultOut);
+ collideSingleContact(rotq.inverse()*perturbeRot*rotq,body0Wrap,body1Wrap,dispatchInfo,resultOut);
}
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
index b9494f5ad3b..d28c430c4c1 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
@@ -36,13 +36,13 @@ class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm
public:
- btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold);
+ btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold);
virtual ~btConvexPlaneCollisionAlgorithm();
- virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
- void collideSingleContact (const btQuaternion& perturbeRot, btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ void collideSingleContact (const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
@@ -65,15 +65,15 @@ public:
{
}
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm));
if (!m_swapped)
{
- return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,false,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+ return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,false,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
} else
{
- return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+ return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,true,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
}
}
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
index 81ed424a3db..474785bfc7d 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
@@ -78,10 +78,8 @@ protected:
btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc;
btCollisionAlgorithmCreateFunc* m_emptyCreateFunc;
btCollisionAlgorithmCreateFunc* m_sphereSphereCF;
-#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
btCollisionAlgorithmCreateFunc* m_sphereBoxCF;
btCollisionAlgorithmCreateFunc* m_boxSphereCF;
-#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
btCollisionAlgorithmCreateFunc* m_boxBoxCF;
btCollisionAlgorithmCreateFunc* m_sphereTriangleCF;
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp
index 936054387c4..5fa1c8be5e4 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp
@@ -22,7 +22,7 @@ btEmptyAlgorithm::btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& c
{
}
-void btEmptyAlgorithm::processCollision (btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* )
+void btEmptyAlgorithm::processCollision (const btCollisionObjectWrapper* ,const btCollisionObjectWrapper* ,const btDispatcherInfo& ,btManifoldResult* )
{
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h
index f03c9dc3833..cb0f152183c 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h
@@ -30,7 +30,7 @@ public:
btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
- virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
@@ -40,10 +40,10 @@ public:
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
- {
- (void)body0;
- (void)body1;
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+ {
+ (void)body0Wrap;
+ (void)body1Wrap;
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm));
return new(mem) btEmptyAlgorithm(ci);
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
index 4353cdac0b1..73fa4e87ea4 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
@@ -6,7 +6,7 @@
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
#include "LinearMath/btIDebugDraw.h"
-
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
//#define DEBUG_INTERNAL_EDGE
@@ -450,18 +450,18 @@ bool btClampNormal(const btVector3& edge,const btVector3& tri_normal_org,const b
/// Changes a btManifoldPoint collision normal to the normal from the mesh.
-void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* colObj0,const btCollisionObject* colObj1, int partId0, int index0, int normalAdjustFlags)
+void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,const btCollisionObjectWrapper* colObj1Wrap, int partId0, int index0, int normalAdjustFlags)
{
//btAssert(colObj0->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE);
- if (colObj0->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE)
+ if (colObj0Wrap->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE)
return;
btBvhTriangleMeshShape* trimesh = 0;
- if( colObj0->getRootCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE )
- trimesh = ((btScaledBvhTriangleMeshShape*)colObj0->getRootCollisionShape())->getChildShape();
+ if( colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE )
+ trimesh = ((btScaledBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape())->getChildShape();
else
- trimesh = (btBvhTriangleMeshShape*)colObj0->getRootCollisionShape();
+ trimesh = (btBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
btTriangleInfoMap* triangleInfoMapPtr = (btTriangleInfoMap*) trimesh->getTriangleInfoMap();
if (!triangleInfoMapPtr)
@@ -476,13 +476,13 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject*
btScalar frontFacing = (normalAdjustFlags & BT_TRIANGLE_CONVEX_BACKFACE_MODE)==0? 1.f : -1.f;
- const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0->getCollisionShape());
+ const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0Wrap->getCollisionShape());
btVector3 v0,v1,v2;
tri_shape->getVertex(0,v0);
tri_shape->getVertex(1,v1);
tri_shape->getVertex(2,v2);
- btVector3 center = (v0+v1+v2)*btScalar(1./3.);
+ //btVector3 center = (v0+v1+v2)*btScalar(1./3.);
btVector3 red(1,0,0), green(0,1,0),blue(0,0,1),white(1,1,1),black(0,0,0);
btVector3 tri_normal;
@@ -505,7 +505,7 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject*
int numConcaveEdgeHits = 0;
int numConvexEdgeHits = 0;
- btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
+ btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
localContactNormalOnB.normalize();//is this necessary?
// Get closest edge
@@ -613,12 +613,12 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject*
{
if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0))
{
- btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal;
+ btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
// cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
cp.m_normalWorldOnB = newNormal;
// Reproject collision point along normal. (what about cp.m_distance1?)
cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
- cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB);
+ cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
}
}
@@ -694,19 +694,19 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject*
else
{
numConvexEdgeHits++;
- btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
+ btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
btVector3 clampedLocalNormal;
bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV1V2Angle,clampedLocalNormal);
if (isClamped)
{
if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0))
{
- btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal;
+ btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
// cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
cp.m_normalWorldOnB = newNormal;
// Reproject collision point along normal.
cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
- cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB);
+ cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
}
}
}
@@ -779,19 +779,19 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject*
// printf("hitting convex edge\n");
- btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
+ btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
btVector3 clampedLocalNormal;
bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB,info->m_edgeV2V0Angle,clampedLocalNormal);
if (isClamped)
{
if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0))
{
- btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal;
+ btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
// cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
cp.m_normalWorldOnB = newNormal;
// Reproject collision point along normal.
cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
- cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB);
+ cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
}
}
}
@@ -820,7 +820,7 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject*
{
tri_normal *= -1;
}
- cp.m_normalWorldOnB = colObj0->getWorldTransform().getBasis()*tri_normal;
+ cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis()*tri_normal;
} else
{
btVector3 newNormal = tri_normal *frontFacing;
@@ -831,12 +831,12 @@ void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject*
return;
}
//modify the normal to be the triangle normal (or backfacing normal)
- cp.m_normalWorldOnB = colObj0->getWorldTransform().getBasis() *newNormal;
+ cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis() *newNormal;
}
// Reproject collision point along normal.
cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
- cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB);
+ cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
}
}
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
index 9efb0122bb8..7d9aafeee69 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
@@ -12,6 +12,7 @@
class btBvhTriangleMeshShape;
class btCollisionObject;
+struct btCollisionObjectWrapper;
class btManifoldPoint;
class btIDebugDraw;
@@ -31,7 +32,7 @@ void btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangle
///Call the btFixMeshNormal to adjust the collision normal, using the triangle info map (generated using btGenerateInternalEdgeInfo)
///If this info map is missing, or the triangle is not store in this map, nothing will be done
-void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* trimeshColObj0,const btCollisionObject* otherColObj1, int partId0, int index0, int normalAdjustFlags = 0);
+void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* trimeshColObj0Wrap,const btCollisionObjectWrapper* otherColObj1Wrap, int partId0, int index0, int normalAdjustFlags = 0);
///Enable the BT_INTERNAL_EDGE_DEBUG_DRAW define and call btSetDebugDrawer, to get visual info to see if the internal edge utility works properly.
///If the utility doesn't work properly, you might have to adjust the threshold values in btTriangleInfoMap
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp
index bf24246ea2f..4b2986a0087 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp
@@ -17,13 +17,30 @@ subject to the following restrictions:
#include "btManifoldResult.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
///This is to allow MaterialCombiner/Custom Friction/Restitution values
ContactAddedCallback gContactAddedCallback=0;
+
+
+///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
+inline btScalar calculateCombinedRollingFriction(const btCollisionObject* body0,const btCollisionObject* body1)
+{
+ btScalar friction = body0->getRollingFriction() * body1->getRollingFriction();
+
+ const btScalar MAX_FRICTION = btScalar(10.);
+ if (friction < -MAX_FRICTION)
+ friction = -MAX_FRICTION;
+ if (friction > MAX_FRICTION)
+ friction = MAX_FRICTION;
+ return friction;
+
+}
+
+
///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
-inline btScalar calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1)
+btScalar btManifoldResult::calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1)
{
btScalar friction = body0->getFriction() * body1->getFriction();
@@ -36,17 +53,17 @@ inline btScalar calculateCombinedFriction(const btCollisionObject* body0,const b
}
-inline btScalar calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1)
+btScalar btManifoldResult::calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1)
{
return body0->getRestitution() * body1->getRestitution();
}
-btManifoldResult::btManifoldResult(btCollisionObject* body0,btCollisionObject* body1)
+btManifoldResult::btManifoldResult(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
:m_manifoldPtr(0),
- m_body0(body0),
- m_body1(body1)
+ m_body0Wrap(body0Wrap),
+ m_body1Wrap(body1Wrap)
#ifdef DEBUG_PART_INDEX
,m_partId0(-1),
m_partId1(-1),
@@ -54,8 +71,6 @@ btManifoldResult::btManifoldResult(btCollisionObject* body0,btCollisionObject* b
m_index1(-1)
#endif //DEBUG_PART_INDEX
{
- m_rootTransA = body0->getWorldTransform();
- m_rootTransB = body1->getWorldTransform();
}
@@ -68,7 +83,7 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b
// if (depth > m_manifoldPtr->getContactProcessingThreshold())
return;
- bool isSwapped = m_manifoldPtr->getBody0() != m_body0;
+ bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
@@ -77,12 +92,12 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b
if (isSwapped)
{
- localA = m_rootTransB.invXform(pointA );
- localB = m_rootTransA.invXform(pointInWorld);
+ localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
+ localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
} else
{
- localA = m_rootTransA.invXform(pointA );
- localB = m_rootTransB.invXform(pointInWorld);
+ localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
+ localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
}
btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
@@ -91,9 +106,13 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b
int insertIndex = m_manifoldPtr->getCacheEntry(newPt);
- newPt.m_combinedFriction = calculateCombinedFriction(m_body0,m_body1);
- newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0,m_body1);
+ newPt.m_combinedFriction = calculateCombinedFriction(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
+ newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
+ newPt.m_combinedRollingFriction = calculateCombinedRollingFriction(m_body0Wrap->getCollisionObject(),m_body1Wrap->getCollisionObject());
+ btPlaneSpace1(newPt.m_normalWorldOnB,newPt.m_lateralFrictionDir1,newPt.m_lateralFrictionDir2);
+
+
//BP mod, store contact triangles.
if (isSwapped)
{
@@ -122,13 +141,13 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b
//User can override friction and/or restitution
if (gContactAddedCallback &&
//and if either of the two bodies requires custom material
- ((m_body0->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) ||
- (m_body1->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)))
+ ((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) ||
+ (m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)))
{
//experimental feature info, for per-triangle material etc.
- btCollisionObject* obj0 = isSwapped? m_body1 : m_body0;
- btCollisionObject* obj1 = isSwapped? m_body0 : m_body1;
- (*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex),obj0,newPt.m_partId0,newPt.m_index0,obj1,newPt.m_partId1,newPt.m_index1);
+ const btCollisionObjectWrapper* obj0Wrap = isSwapped? m_body1Wrap : m_body0Wrap;
+ const btCollisionObjectWrapper* obj1Wrap = isSwapped? m_body0Wrap : m_body1Wrap;
+ (*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex),obj0Wrap,newPt.m_partId0,newPt.m_index0,obj1Wrap,newPt.m_partId1,newPt.m_index1);
}
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h
index 18199b49752..977b9a02fc5 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h
@@ -18,14 +18,18 @@ subject to the following restrictions:
#define BT_MANIFOLD_RESULT_H
class btCollisionObject;
+struct btCollisionObjectWrapper;
+
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
class btManifoldPoint;
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
#include "LinearMath/btTransform.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1);
+typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1);
extern ContactAddedCallback gContactAddedCallback;
//#define DEBUG_PART_INDEX 1
@@ -38,12 +42,8 @@ protected:
btPersistentManifold* m_manifoldPtr;
- //we need this for compounds
- btTransform m_rootTransA;
- btTransform m_rootTransB;
-
- btCollisionObject* m_body0;
- btCollisionObject* m_body1;
+ const btCollisionObjectWrapper* m_body0Wrap;
+ const btCollisionObjectWrapper* m_body1Wrap;
int m_partId0;
int m_partId1;
int m_index0;
@@ -63,7 +63,7 @@ public:
{
}
- btManifoldResult(btCollisionObject* body0,btCollisionObject* body1);
+ btManifoldResult(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
virtual ~btManifoldResult() {};
@@ -102,27 +102,49 @@ public:
if (!m_manifoldPtr->getNumContacts())
return;
- bool isSwapped = m_manifoldPtr->getBody0() != m_body0;
+ bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
if (isSwapped)
{
- m_manifoldPtr->refreshContactPoints(m_rootTransB,m_rootTransA);
+ m_manifoldPtr->refreshContactPoints(m_body1Wrap->getCollisionObject()->getWorldTransform(),m_body0Wrap->getCollisionObject()->getWorldTransform());
} else
{
- m_manifoldPtr->refreshContactPoints(m_rootTransA,m_rootTransB);
+ m_manifoldPtr->refreshContactPoints(m_body0Wrap->getCollisionObject()->getWorldTransform(),m_body1Wrap->getCollisionObject()->getWorldTransform());
}
}
+ const btCollisionObjectWrapper* getBody0Wrap() const
+ {
+ return m_body0Wrap;
+ }
+ const btCollisionObjectWrapper* getBody1Wrap() const
+ {
+ return m_body1Wrap;
+ }
+
+ void setBody0Wrap(const btCollisionObjectWrapper* obj0Wrap)
+ {
+ m_body0Wrap = obj0Wrap;
+ }
+
+ void setBody1Wrap(const btCollisionObjectWrapper* obj1Wrap)
+ {
+ m_body1Wrap = obj1Wrap;
+ }
+
const btCollisionObject* getBody0Internal() const
{
- return m_body0;
+ return m_body0Wrap->getCollisionObject();
}
const btCollisionObject* getBody1Internal() const
{
- return m_body1;
+ return m_body1Wrap->getCollisionObject();
}
-
+
+ /// in the future we can let the user override the methods to combine restitution and friction
+ static btScalar calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1);
+ static btScalar calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1);
};
#endif //BT_MANIFOLD_RESULT_H
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
index 871c64415a2..13447822571 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
@@ -319,8 +319,8 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio
{
btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
- btCollisionObject* colObj0 = static_cast<btCollisionObject*>(manifold->getBody0());
- btCollisionObject* colObj1 = static_cast<btCollisionObject*>(manifold->getBody1());
+ const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
+ const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
///@todo: check sleeping conditions!
if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
index 8df876928c1..e8b567e0efc 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
@@ -18,20 +18,21 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
//#include <stdio.h>
-btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped)
-: btActivatingCollisionAlgorithm(ci,col0,col1),
+btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap, bool isSwapped)
+: btActivatingCollisionAlgorithm(ci,col0Wrap,col1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf),
m_isSwapped(isSwapped)
{
- btCollisionObject* sphereObj = m_isSwapped? col1 : col0;
- btCollisionObject* boxObj = m_isSwapped? col0 : col1;
+ const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped? col1Wrap : col0Wrap;
+ const btCollisionObjectWrapper* boxObjWrap = m_isSwapped? col0Wrap : col1Wrap;
- if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObj,boxObj))
+ if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObjWrap->getCollisionObject(),boxObjWrap->getCollisionObject()))
{
- m_manifoldPtr = m_dispatcher->getNewManifold(sphereObj,boxObj);
+ m_manifoldPtr = m_dispatcher->getNewManifold(sphereObjWrap->getCollisionObject(),boxObjWrap->getCollisionObject());
m_ownManifold = true;
}
}
@@ -48,36 +49,31 @@ btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm()
-void btSphereBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btSphereBoxCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
{
(void)dispatchInfo;
(void)resultOut;
if (!m_manifoldPtr)
return;
- btCollisionObject* sphereObj = m_isSwapped? body1 : body0;
- btCollisionObject* boxObj = m_isSwapped? body0 : body1;
+ const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped? body1Wrap : body0Wrap;
+ const btCollisionObjectWrapper* boxObjWrap = m_isSwapped? body0Wrap : body1Wrap;
-
- btSphereShape* sphere0 = (btSphereShape*)sphereObj->getCollisionShape();
+ btVector3 pOnBox;
btVector3 normalOnSurfaceB;
- btVector3 pOnBox,pOnSphere;
- btVector3 sphereCenter = sphereObj->getWorldTransform().getOrigin();
+ btScalar penetrationDepth;
+ btVector3 sphereCenter = sphereObjWrap->getWorldTransform().getOrigin();
+ const btSphereShape* sphere0 = (const btSphereShape*)sphereObjWrap->getCollisionShape();
btScalar radius = sphere0->getRadius();
-
- btScalar dist = getSphereDistance(boxObj,pOnBox,pOnSphere,sphereCenter,radius);
+ btScalar maxContactDistance = m_manifoldPtr->getContactBreakingThreshold();
resultOut->setPersistentManifold(m_manifoldPtr);
- if (dist < SIMD_EPSILON)
+ if (getSphereDistance(boxObjWrap, pOnBox, normalOnSurfaceB, penetrationDepth, sphereCenter, radius, maxContactDistance))
{
- btVector3 normalOnSurfaceB = (pOnBox- pOnSphere).normalize();
-
/// report a contact. internally this will be kept persistent, and contact reduction is done
-
- resultOut->addContactPoint(normalOnSurfaceB,pOnBox,dist);
-
+ resultOut->addContactPoint(normalOnSurfaceB, pOnBox, penetrationDepth);
}
if (m_ownManifold)
@@ -102,159 +98,117 @@ btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject*
}
-btScalar btSphereBoxCollisionAlgorithm::getSphereDistance(btCollisionObject* boxObj, btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius )
+bool btSphereBoxCollisionAlgorithm::getSphereDistance(const btCollisionObjectWrapper* boxObjWrap, btVector3& pointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& sphereCenter, btScalar fRadius, btScalar maxContactDistance )
{
-
- btScalar margins;
- btVector3 bounds[2];
- btBoxShape* boxShape= (btBoxShape*)boxObj->getCollisionShape();
+ const btBoxShape* boxShape= (const btBoxShape*)boxObjWrap->getCollisionShape();
+ btVector3 const &boxHalfExtent = boxShape->getHalfExtentsWithoutMargin();
+ btScalar boxMargin = boxShape->getMargin();
+ penetrationDepth = 1.0f;
+
+ // convert the sphere position to the box's local space
+ btTransform const &m44T = boxObjWrap->getWorldTransform();
+ btVector3 sphereRelPos = m44T.invXform(sphereCenter);
+
+ // Determine the closest point to the sphere center in the box
+ btVector3 closestPoint = sphereRelPos;
+ closestPoint.setX( btMin(boxHalfExtent.getX(), closestPoint.getX()) );
+ closestPoint.setX( btMax(-boxHalfExtent.getX(), closestPoint.getX()) );
+ closestPoint.setY( btMin(boxHalfExtent.getY(), closestPoint.getY()) );
+ closestPoint.setY( btMax(-boxHalfExtent.getY(), closestPoint.getY()) );
+ closestPoint.setZ( btMin(boxHalfExtent.getZ(), closestPoint.getZ()) );
+ closestPoint.setZ( btMax(-boxHalfExtent.getZ(), closestPoint.getZ()) );
- bounds[0] = -boxShape->getHalfExtentsWithoutMargin();
- bounds[1] = boxShape->getHalfExtentsWithoutMargin();
-
- margins = boxShape->getMargin();//also add sphereShape margin?
-
- const btTransform& m44T = boxObj->getWorldTransform();
-
- btVector3 boundsVec[2];
- btScalar fPenetration;
-
- boundsVec[0] = bounds[0];
- boundsVec[1] = bounds[1];
-
- btVector3 marginsVec( margins, margins, margins );
-
- // add margins
- bounds[0] += marginsVec;
- bounds[1] -= marginsVec;
-
- /////////////////////////////////////////////////
-
- btVector3 tmp, prel, n[6], normal, v3P;
- btScalar fSep = btScalar(10000000.0), fSepThis;
+ btScalar intersectionDist = fRadius + boxMargin;
+ btScalar contactDist = intersectionDist + maxContactDistance;
+ normal = sphereRelPos - closestPoint;
- n[0].setValue( btScalar(-1.0), btScalar(0.0), btScalar(0.0) );
- n[1].setValue( btScalar(0.0), btScalar(-1.0), btScalar(0.0) );
- n[2].setValue( btScalar(0.0), btScalar(0.0), btScalar(-1.0) );
- n[3].setValue( btScalar(1.0), btScalar(0.0), btScalar(0.0) );
- n[4].setValue( btScalar(0.0), btScalar(1.0), btScalar(0.0) );
- n[5].setValue( btScalar(0.0), btScalar(0.0), btScalar(1.0) );
-
- // convert point in local space
- prel = m44T.invXform( sphereCenter);
-
- bool bFound = false;
+ //if there is no penetration, we are done
+ btScalar dist2 = normal.length2();
+ if (dist2 > contactDist * contactDist)
+ {
+ return false;
+ }
- v3P = prel;
+ btScalar distance;
- for (int i=0;i<6;i++)
+ //special case if the sphere center is inside the box
+ if (dist2 <= SIMD_EPSILON)
{
- int j = i<3? 0:1;
- if ( (fSepThis = ((v3P-bounds[j]) .dot(n[i]))) > btScalar(0.0) )
- {
- v3P = v3P - n[i]*fSepThis;
- bFound = true;
- }
+ distance = -getSpherePenetration(boxHalfExtent, sphereRelPos, closestPoint, normal);
}
-
- //
-
- if ( bFound )
+ else //compute the penetration details
{
- bounds[0] = boundsVec[0];
- bounds[1] = boundsVec[1];
-
- normal = (prel - v3P).normalize();
- pointOnBox = v3P + normal*margins;
- v3PointOnSphere = prel - normal*fRadius;
-
- if ( ((v3PointOnSphere - pointOnBox) .dot (normal)) > btScalar(0.0) )
- {
- return btScalar(1.0);
- }
-
- // transform back in world space
- tmp = m44T( pointOnBox);
- pointOnBox = tmp;
- tmp = m44T( v3PointOnSphere);
- v3PointOnSphere = tmp;
- btScalar fSeps2 = (pointOnBox-v3PointOnSphere).length2();
-
- //if this fails, fallback into deeper penetration case, below
- if (fSeps2 > SIMD_EPSILON)
- {
- fSep = - btSqrt(fSeps2);
- normal = (pointOnBox-v3PointOnSphere);
- normal *= btScalar(1.)/fSep;
- }
-
- return fSep;
+ distance = normal.length();
+ normal /= distance;
}
- //////////////////////////////////////////////////
- // Deep penetration case
-
- fPenetration = getSpherePenetration( boxObj,pointOnBox, v3PointOnSphere, sphereCenter, fRadius,bounds[0],bounds[1] );
+ pointOnBox = closestPoint + normal * boxMargin;
+// v3PointOnSphere = sphereRelPos - (normal * fRadius);
+ penetrationDepth = distance - intersectionDist;
- bounds[0] = boundsVec[0];
- bounds[1] = boundsVec[1];
-
- if ( fPenetration <= btScalar(0.0) )
- return (fPenetration-margins);
- else
- return btScalar(1.0);
+ // transform back in world space
+ btVector3 tmp = m44T(pointOnBox);
+ pointOnBox = tmp;
+// tmp = m44T(v3PointOnSphere);
+// v3PointOnSphere = tmp;
+ tmp = m44T.getBasis() * normal;
+ normal = tmp;
+
+ return true;
}
-btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btCollisionObject* boxObj,btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax)
+btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btVector3 const &boxHalfExtent, btVector3 const &sphereRelPos, btVector3 &closestPoint, btVector3& normal )
{
+ //project the center of the sphere on the closest face of the box
+ btScalar faceDist = boxHalfExtent.getX() - sphereRelPos.getX();
+ btScalar minDist = faceDist;
+ closestPoint.setX( boxHalfExtent.getX() );
+ normal.setValue(btScalar(1.0f), btScalar(0.0f), btScalar(0.0f));
+
+ faceDist = boxHalfExtent.getX() + sphereRelPos.getX();
+ if (faceDist < minDist)
+ {
+ minDist = faceDist;
+ closestPoint = sphereRelPos;
+ closestPoint.setX( -boxHalfExtent.getX() );
+ normal.setValue(btScalar(-1.0f), btScalar(0.0f), btScalar(0.0f));
+ }
- btVector3 bounds[2];
-
- bounds[0] = aabbMin;
- bounds[1] = aabbMax;
-
- btVector3 p0, tmp, prel, n[6], normal;
- btScalar fSep = btScalar(-10000000.0), fSepThis;
-
- // set p0 and normal to a default value to shup up GCC
- p0.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
- normal.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
-
- n[0].setValue( btScalar(-1.0), btScalar(0.0), btScalar(0.0) );
- n[1].setValue( btScalar(0.0), btScalar(-1.0), btScalar(0.0) );
- n[2].setValue( btScalar(0.0), btScalar(0.0), btScalar(-1.0) );
- n[3].setValue( btScalar(1.0), btScalar(0.0), btScalar(0.0) );
- n[4].setValue( btScalar(0.0), btScalar(1.0), btScalar(0.0) );
- n[5].setValue( btScalar(0.0), btScalar(0.0), btScalar(1.0) );
-
- const btTransform& m44T = boxObj->getWorldTransform();
-
- // convert point in local space
- prel = m44T.invXform( sphereCenter);
-
- ///////////
-
- for (int i=0;i<6;i++)
+ faceDist = boxHalfExtent.getY() - sphereRelPos.getY();
+ if (faceDist < minDist)
{
- int j = i<3 ? 0:1;
- if ( (fSepThis = ((prel-bounds[j]) .dot( n[i]))-fRadius) > btScalar(0.0) ) return btScalar(1.0);
- if ( fSepThis > fSep )
- {
- p0 = bounds[j]; normal = (btVector3&)n[i];
- fSep = fSepThis;
- }
+ minDist = faceDist;
+ closestPoint = sphereRelPos;
+ closestPoint.setY( boxHalfExtent.getY() );
+ normal.setValue(btScalar(0.0f), btScalar(1.0f), btScalar(0.0f));
}
- pointOnBox = prel - normal*(normal.dot((prel-p0)));
- v3PointOnSphere = pointOnBox + normal*fSep;
+ faceDist = boxHalfExtent.getY() + sphereRelPos.getY();
+ if (faceDist < minDist)
+ {
+ minDist = faceDist;
+ closestPoint = sphereRelPos;
+ closestPoint.setY( -boxHalfExtent.getY() );
+ normal.setValue(btScalar(0.0f), btScalar(-1.0f), btScalar(0.0f));
+ }
- // transform back in world space
- tmp = m44T( pointOnBox);
- pointOnBox = tmp;
- tmp = m44T( v3PointOnSphere); v3PointOnSphere = tmp;
- normal = (pointOnBox-v3PointOnSphere).normalize();
+ faceDist = boxHalfExtent.getZ() - sphereRelPos.getZ();
+ if (faceDist < minDist)
+ {
+ minDist = faceDist;
+ closestPoint = sphereRelPos;
+ closestPoint.setZ( boxHalfExtent.getZ() );
+ normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(1.0f));
+ }
- return fSep;
+ faceDist = boxHalfExtent.getZ() + sphereRelPos.getZ();
+ if (faceDist < minDist)
+ {
+ minDist = faceDist;
+ closestPoint = sphereRelPos;
+ closestPoint.setZ( -boxHalfExtent.getZ() );
+ normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(-1.0f));
+ }
+ return minDist;
}
-
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h
index 60286ae0aa4..eefaedc9e7e 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h
@@ -34,11 +34,11 @@ class btSphereBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
public:
- btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped);
+ btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
virtual ~btSphereBoxCollisionAlgorithm();
- virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
@@ -50,21 +50,21 @@ public:
}
}
- btScalar getSphereDistance( btCollisionObject* boxObj,btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius );
+ bool getSphereDistance( const btCollisionObjectWrapper* boxObjWrap, btVector3& v3PointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& v3SphereCenter, btScalar fRadius, btScalar maxContactDistance );
- btScalar getSpherePenetration( btCollisionObject* boxObj, btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax);
+ btScalar getSpherePenetration( btVector3 const &boxHalfExtent, btVector3 const &sphereRelPos, btVector3 &closestPoint, btVector3& normal );
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm));
if (!m_swapped)
{
- return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false);
+ return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,false);
} else
{
- return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true);
+ return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,true);
}
}
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
index 5c4e78fe518..36ba21f5bb0 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
@@ -17,15 +17,16 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1)
-: btActivatingCollisionAlgorithm(ci,col0,col1),
+btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap)
+: btActivatingCollisionAlgorithm(ci,col0Wrap,col1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf)
{
if (!m_manifoldPtr)
{
- m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1);
+ m_manifoldPtr = m_dispatcher->getNewManifold(col0Wrap->getCollisionObject(),col1Wrap->getCollisionObject());
m_ownManifold = true;
}
}
@@ -39,7 +40,7 @@ btSphereSphereCollisionAlgorithm::~btSphereSphereCollisionAlgorithm()
}
}
-void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btSphereSphereCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)dispatchInfo;
@@ -48,10 +49,10 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0
resultOut->setPersistentManifold(m_manifoldPtr);
- btSphereShape* sphere0 = (btSphereShape*)col0->getCollisionShape();
- btSphereShape* sphere1 = (btSphereShape*)col1->getCollisionShape();
+ btSphereShape* sphere0 = (btSphereShape*)col0Wrap->getCollisionShape();
+ btSphereShape* sphere1 = (btSphereShape*)col1Wrap->getCollisionShape();
- btVector3 diff = col0->getWorldTransform().getOrigin()- col1->getWorldTransform().getOrigin();
+ btVector3 diff = col0Wrap->getWorldTransform().getOrigin()- col1Wrap->getWorldTransform().getOrigin();
btScalar len = diff.length();
btScalar radius0 = sphere0->getRadius();
btScalar radius1 = sphere1->getRadius();
@@ -80,7 +81,7 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0
///point on A (worldspace)
///btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB;
///point on B (worldspace)
- btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB;
+ btVector3 pos1 = col1Wrap->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB;
/// report a contact. internally this will be kept persistent, and contact reduction is done
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h
index e55acf277e6..3517a568a99 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h
@@ -32,12 +32,12 @@ class btSphereSphereCollisionAlgorithm : public btActivatingCollisionAlgorithm
btPersistentManifold* m_manifoldPtr;
public:
- btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
+ btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap);
btSphereSphereCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
- virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
@@ -53,10 +53,10 @@ public:
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm));
- return new(mem) btSphereSphereCollisionAlgorithm(0,ci,body0,body1);
+ return new(mem) btSphereSphereCollisionAlgorithm(0,ci,col0Wrap,col1Wrap);
}
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
index c327c3ff72a..280a4d355fd 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
@@ -19,17 +19,17 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "SphereTriangleDetector.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1,bool swapped)
-: btActivatingCollisionAlgorithm(ci,col0,col1),
+btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool swapped)
+: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
m_ownManifold(false),
m_manifoldPtr(mf),
m_swapped(swapped)
{
if (!m_manifoldPtr)
{
- m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1);
+ m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
m_ownManifold = true;
}
}
@@ -43,16 +43,16 @@ btSphereTriangleCollisionAlgorithm::~btSphereTriangleCollisionAlgorithm()
}
}
-void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btSphereTriangleCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* col0Wrap,const btCollisionObjectWrapper* col1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
if (!m_manifoldPtr)
return;
- btCollisionObject* sphereObj = m_swapped? col1 : col0;
- btCollisionObject* triObj = m_swapped? col0 : col1;
+ const btCollisionObjectWrapper* sphereObjWrap = m_swapped? col1Wrap : col0Wrap;
+ const btCollisionObjectWrapper* triObjWrap = m_swapped? col0Wrap : col1Wrap;
- btSphereShape* sphere = (btSphereShape*)sphereObj->getCollisionShape();
- btTriangleShape* triangle = (btTriangleShape*)triObj->getCollisionShape();
+ btSphereShape* sphere = (btSphereShape*)sphereObjWrap->getCollisionShape();
+ btTriangleShape* triangle = (btTriangleShape*)triObjWrap->getCollisionShape();
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->setPersistentManifold(m_manifoldPtr);
@@ -60,8 +60,8 @@ void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* co
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);///@todo: tighter bounds
- input.m_transformA = sphereObj->getWorldTransform();
- input.m_transformB = triObj->getWorldTransform();
+ input.m_transformA = sphereObjWrap->getWorldTransform();
+ input.m_transformB = triObjWrap->getWorldTransform();
bool swapResults = m_swapped;
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
index 7c6c4d8f8d5..6b6e39a72b6 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
@@ -32,12 +32,12 @@ class btSphereTriangleCollisionAlgorithm : public btActivatingCollisionAlgorithm
bool m_swapped;
public:
- btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool swapped);
+ btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool swapped);
btSphereTriangleCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btActivatingCollisionAlgorithm(ci) {}
- virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
@@ -54,12 +54,12 @@ public:
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm));
- return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped);
+ return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0Wrap,body1Wrap,m_swapped);
}
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBox2dShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBox2dShape.h
index f4a9ca03e5c..ce333783e44 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBox2dShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBox2dShape.h
@@ -23,7 +23,7 @@ subject to the following restrictions:
#include "LinearMath/btMinMax.h"
///The btBox2dShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space.
-class btBox2dShape: public btPolyhedralConvexShape
+ATTRIBUTE_ALIGNED16(class) btBox2dShape: public btPolyhedralConvexShape
{
//btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead
@@ -34,6 +34,8 @@ class btBox2dShape: public btPolyhedralConvexShape
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btVector3 getHalfExtentsWithMargin() const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h
index 0c5857dae62..715e3f2ab98 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h
@@ -23,7 +23,7 @@ subject to the following restrictions:
#include "LinearMath/btMinMax.h"
///The btBoxShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space.
-class btBoxShape: public btPolyhedralConvexShape
+ATTRIBUTE_ALIGNED16(class) btBoxShape: public btPolyhedralConvexShape
{
//btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead
@@ -31,6 +31,8 @@ class btBoxShape: public btPolyhedralConvexShape
public:
+BT_DECLARE_ALIGNED_ALLOCATOR();
+
btVector3 getHalfExtentsWithMargin() const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h
index d1c21629873..493d635539e 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h
@@ -21,7 +21,13 @@ subject to the following restrictions:
#include "LinearMath/btAlignedAllocator.h"
#include "btTriangleInfoMap.h"
-///The btBvhTriangleMeshShape is a static-triangle mesh shape with several optimizations, such as bounding volume hierarchy and cache friendly traversal for PlayStation 3 Cell SPU. It is recommended to enable useQuantizedAabbCompression for better memory usage.
+///The btBvhTriangleMeshShape is a static-triangle mesh shape, it can only be used for fixed/non-moving objects.
+///If you required moving concave triangle meshes, it is recommended to perform convex decomposition
+///using HACD, see Bullet/Demos/ConvexDecompositionDemo.
+///Alternatively, you can use btGimpactMeshShape for moving concave triangle meshes.
+///btBvhTriangleMeshShape has several optimizations, such as bounding volume hierarchy and
+///cache friendly traversal for PlayStation 3 Cell SPU.
+///It is recommended to enable useQuantizedAabbCompression for better memory usage.
///It takes a triangle mesh as input, for example a btTriangleMesh or btTriangleIndexVertexArray. The btBvhTriangleMeshShape class allows for triangle mesh deformations by a refit or partialRefit method.
///Instead of building the bounding volume hierarchy acceleration structure, it is also possible to serialize (save) and deserialize (load) the structure from disk.
///See Demos\ConcaveDemo\ConcavePhysicsDemo.cpp for an example.
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h
index ab763abf808..7578bb258df 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h
@@ -23,7 +23,7 @@ subject to the following restrictions:
///The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned around the X axis and btCapsuleShapeZ around the Z axis.
///The total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
///The btCapsuleShape is a convex hull of two spheres. The btMultiSphereShape is a more general collision shape that takes the convex hull of multiple sphere, so it can also represent a capsule when just using two spheres.
-class btCapsuleShape : public btConvexInternalShape
+ATTRIBUTE_ALIGNED16(class) btCapsuleShape : public btConvexInternalShape
{
protected:
int m_upAxis;
@@ -33,6 +33,9 @@ protected:
btCapsuleShape() : btConvexInternalShape() {m_shapeType = CAPSULE_SHAPE_PROXYTYPE;};
public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btCapsuleShape(btScalar radius,btScalar height);
///CollisionShape Interface
@@ -62,8 +65,8 @@ public:
halfExtents += btVector3(getMargin(),getMargin(),getMargin());
btMatrix3x3 abs_b = t.getBasis().absolute();
btVector3 center = t.getOrigin();
- btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));
-
+ btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+
aabbMin = center - extent;
aabbMax = center + extent;
}
@@ -101,6 +104,14 @@ public:
}
+ virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ {
+ btVector3 aniDir(0,0,0);
+ aniDir[getUpAxis()]=1;
+ return aniDir;
+ }
+
+
virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h
index 865c1067744..ff017a20671 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h
@@ -24,7 +24,7 @@ class btSerializer;
///The btCollisionShape class provides an interface for collision shapes that can be shared among btCollisionObjects.
-class btCollisionShape
+ATTRIBUTE_ALIGNED16(class) btCollisionShape
{
protected:
int m_shapeType;
@@ -32,6 +32,8 @@ protected:
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btCollisionShape() : m_shapeType (INVALID_SHAPE_PROXYTYPE), m_userPointer(0)
{
}
@@ -107,6 +109,13 @@ public:
int getShapeType() const { return m_shapeType; }
+
+ ///the getAnisotropicRollingFrictionDirection can be used in combination with setAnisotropicFriction
+ ///See Bullet/Demos/RollingFrictionDemo for an example
+ virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ {
+ return btVector3(1,1,1);
+ }
virtual void setMargin(btScalar margin) = 0;
virtual btScalar getMargin() const = 0;
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp
index 4eb860c57f1..12f422f193f 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp
@@ -182,9 +182,7 @@ void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVect
btVector3 center = trans(localCenter);
- btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
- abs_b[1].dot(localHalfExtents),
- abs_b[2].dot(localHalfExtents));
+ btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
aabbMin = center-extent;
aabbMax = center+extent;
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h
index 2a03241c9d7..2917cc5b60f 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h
@@ -33,12 +33,14 @@ typedef enum PHY_ScalarType {
///The btConcaveShape class provides an interface for non-moving (static) concave shapes.
///It has been implemented by the btStaticPlaneShape, btBvhTriangleMeshShape and btHeightfieldTerrainShape.
-class btConcaveShape : public btCollisionShape
+ATTRIBUTE_ALIGNED16(class) btConcaveShape : public btCollisionShape
{
protected:
btScalar m_collisionMargin;
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btConcaveShape();
virtual ~btConcaveShape();
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h
index b69b5c5b0c8..5966ae48f11 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h
@@ -20,7 +20,7 @@ subject to the following restrictions:
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
///The btConeShape implements a cone shape primitive, centered around the origin and aligned with the Y axis. The btConeShapeX is aligned around the X axis and btConeShapeZ around the Z axis.
-class btConeShape : public btConvexInternalShape
+ATTRIBUTE_ALIGNED16(class) btConeShape : public btConvexInternalShape
{
@@ -32,6 +32,8 @@ class btConeShape : public btConvexInternalShape
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btConeShape (btScalar radius,btScalar height);
virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
@@ -82,6 +84,11 @@ public:
return m_coneIndices[1];
}
+ virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ {
+ return btVector3 (0,1,0);
+ }
+
virtual void setLocalScaling(const btVector3& scaling);
};
@@ -91,6 +98,12 @@ class btConeShapeX : public btConeShape
{
public:
btConeShapeX(btScalar radius,btScalar height);
+
+ virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ {
+ return btVector3 (1,0,0);
+ }
+
};
///btConeShapeZ implements a Cone shape, around the Z axis
@@ -98,6 +111,12 @@ class btConeShapeZ : public btConeShape
{
public:
btConeShapeZ(btScalar radius,btScalar height);
+
+ virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ {
+ return btVector3 (0,0,1);
+ }
+
};
#endif //BT_CONE_MINKOWSKI_H
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvex2dShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvex2dShape.h
index caf54329da9..bbd1caf42fb 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvex2dShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvex2dShape.h
@@ -21,12 +21,14 @@ subject to the following restrictions:
///The btConvex2dShape allows to use arbitrary convex shapes as 2d convex shapes, with the Z component assumed to be 0.
///For 2d boxes, the btBox2dShape is recommended.
-class btConvex2dShape : public btConvexShape
+ATTRIBUTE_ALIGNED16(class) btConvex2dShape : public btConvexShape
{
btConvexShape* m_childConvexShape;
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btConvex2dShape( btConvexShape* convexChildShape);
virtual ~btConvex2dShape();
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp
index 226245979ab..0623e351a97 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp
@@ -13,6 +13,10 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
+#if defined (_WIN32) || defined (__i386__)
+#define BT_USE_SSE_IN_API
+#endif
+
#include "btConvexHullShape.h"
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
@@ -45,30 +49,28 @@ void btConvexHullShape::setLocalScaling(const btVector3& scaling)
recalcLocalAabb();
}
-void btConvexHullShape::addPoint(const btVector3& point)
+void btConvexHullShape::addPoint(const btVector3& point, bool recalculateLocalAabb)
{
m_unscaledPoints.push_back(point);
- recalcLocalAabb();
+ if (recalculateLocalAabb)
+ recalcLocalAabb();
}
btVector3 btConvexHullShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
{
btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
- btScalar newDot,maxDot = btScalar(-BT_LARGE_FLOAT);
+ btScalar maxDot = btScalar(-BT_LARGE_FLOAT);
- for (int i=0;i<m_unscaledPoints.size();i++)
- {
- btVector3 vtx = m_unscaledPoints[i] * m_localScaling;
+ // Here we take advantage of dot(a, b*c) = dot(a*b, c). Note: This is true mathematically, but not numerically.
+ if( 0 < m_unscaledPoints.size() )
+ {
+ btVector3 scaled = vec * m_localScaling;
+ int index = (int) scaled.maxDot( &m_unscaledPoints[0], m_unscaledPoints.size(), maxDot); // FIXME: may violate encapsulation of m_unscaledPoints
+ return m_unscaledPoints[index] * m_localScaling;
+ }
- newDot = vec.dot(vtx);
- if (newDot > maxDot)
- {
- maxDot = newDot;
- supVec = vtx;
- }
- }
- return supVec;
+ return supVec;
}
void btConvexHullShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
@@ -81,23 +83,19 @@ void btConvexHullShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const
supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
}
}
- for (int i=0;i<m_unscaledPoints.size();i++)
- {
- btVector3 vtx = getScaledPoint(i);
- for (int j=0;j<numVectors;j++)
- {
- const btVector3& vec = vectors[j];
-
- newDot = vec.dot(vtx);
- if (newDot > supportVerticesOut[j][3])
- {
- //WARNING: don't swap next lines, the w component would get overwritten!
- supportVerticesOut[j] = vtx;
- supportVerticesOut[j][3] = newDot;
- }
- }
- }
+ for (int j=0;j<numVectors;j++)
+ {
+ btVector3 vec = vectors[j] * m_localScaling; // dot(a*b,c) = dot(a,b*c)
+ if( 0 < m_unscaledPoints.size() )
+ {
+ int i = (int) vec.maxDot( &m_unscaledPoints[0], m_unscaledPoints.size(), newDot);
+ supportVerticesOut[j] = getScaledPoint(i);
+ supportVerticesOut[j][3] = newDot;
+ }
+ else
+ supportVerticesOut[j][3] = -BT_LARGE_FLOAT;
+ }
@@ -208,13 +206,11 @@ const char* btConvexHullShape::serialize(void* dataBuffer, btSerializer* seriali
return "btConvexHullShapeData";
}
-void btConvexHullShape::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const
+void btConvexHullShape::project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const
{
#if 1
- min = FLT_MAX;
- max = -FLT_MAX;
- btVector3 witnesPtMin;
- btVector3 witnesPtMax;
+ minProj = FLT_MAX;
+ maxProj = -FLT_MAX;
int numVerts = m_unscaledPoints.size();
for(int i=0;i<numVerts;i++)
@@ -222,31 +218,30 @@ void btConvexHullShape::project(const btTransform& trans, const btVector3& dir,
btVector3 vtx = m_unscaledPoints[i] * m_localScaling;
btVector3 pt = trans * vtx;
btScalar dp = pt.dot(dir);
- if(dp < min)
+ if(dp < minProj)
{
- min = dp;
+ minProj = dp;
witnesPtMin = pt;
}
- if(dp > max)
+ if(dp > maxProj)
{
- max = dp;
+ maxProj = dp;
witnesPtMax=pt;
}
}
#else
btVector3 localAxis = dir*trans.getBasis();
- btVector3 vtx1 = trans(localGetSupportingVertex(localAxis));
- btVector3 vtx2 = trans(localGetSupportingVertex(-localAxis));
+ witnesPtMin = trans(localGetSupportingVertex(localAxis));
+ witnesPtMax = trans(localGetSupportingVertex(-localAxis));
- min = vtx1.dot(dir);
- max = vtx2.dot(dir);
+ minProj = witnesPtMin.dot(dir);
+ maxProj = witnesPtMax.dot(dir);
#endif
- if(min>max)
+ if(minProj>maxProj)
{
- btScalar tmp = min;
- min = max;
- max = tmp;
+ btSwap(minProj,maxProj);
+ btSwap(witnesPtMin,witnesPtMax);
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h
index 95a2af6a3a0..3bd598ec4e9 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h
@@ -36,7 +36,7 @@ public:
///btConvexHullShape make an internal copy of the points.
btConvexHullShape(const btScalar* points=0,int numPoints=0, int stride=sizeof(btVector3));
- void addPoint(const btVector3& point);
+ void addPoint(const btVector3& point, bool recalculateLocalAabb = true);
btVector3* getUnscaledPoints()
@@ -73,7 +73,7 @@ public:
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
- virtual void project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const;
+ virtual void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const;
//debugging
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h
index 85cd9ef90c7..37e04f5fc81 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h
@@ -26,7 +26,7 @@ subject to the following restrictions:
///Note that when creating small shapes (derived from btConvexInternalShape),
///you need to make sure to set a smaller collision margin, using the 'setMargin' API
///There is a automatic mechanism 'setSafeMargin' used by btBoxShape and btCylinderShape
-class btConvexInternalShape : public btConvexShape
+ATTRIBUTE_ALIGNED16(class) btConvexInternalShape : public btConvexShape
{
protected:
@@ -44,7 +44,7 @@ class btConvexInternalShape : public btConvexShape
public:
-
+ BT_DECLARE_ALIGNED_ALLOCATOR();
virtual ~btConvexInternalShape()
{
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp
index c1b155aef45..ad1d1bf78f8 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp
@@ -28,7 +28,7 @@ void btConvexPointCloudShape::setLocalScaling(const btVector3& scaling)
btVector3 btConvexPointCloudShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
{
btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
- btScalar newDot,maxDot = btScalar(-BT_LARGE_FLOAT);
+ btScalar maxDot = btScalar(-BT_LARGE_FLOAT);
btVector3 vec = vec0;
btScalar lenSqr = vec.length2();
@@ -40,51 +40,33 @@ btVector3 btConvexPointCloudShape::localGetSupportingVertexWithoutMargin(const b
btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
vec *= rlen;
}
+
+ if( m_numPoints > 0 )
+ {
+ // Here we take advantage of dot(a*b, c) = dot( a, b*c) to do less work. Note this transformation is true mathematically, not numerically.
+ // btVector3 scaled = vec * m_localScaling;
+ int index = (int) vec.maxDot( &m_unscaledPoints[0], m_numPoints, maxDot); //FIXME: may violate encapsulation of m_unscaledPoints
+ return getScaledPoint(index);
+ }
-
- for (int i=0;i<m_numPoints;i++)
- {
- btVector3 vtx = getScaledPoint(i);
-
- newDot = vec.dot(vtx);
- if (newDot > maxDot)
- {
- maxDot = newDot;
- supVec = vtx;
- }
- }
return supVec;
}
void btConvexPointCloudShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
{
- btScalar newDot;
- //use 'w' component of supportVerticesOut?
- {
- for (int i=0;i<numVectors;i++)
- {
- supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
- }
- }
- for (int i=0;i<m_numPoints;i++)
- {
- btVector3 vtx = getScaledPoint(i);
-
- for (int j=0;j<numVectors;j++)
- {
- const btVector3& vec = vectors[j];
-
- newDot = vec.dot(vtx);
- if (newDot > supportVerticesOut[j][3])
- {
- //WARNING: don't swap next lines, the w component would get overwritten!
- supportVerticesOut[j] = vtx;
- supportVerticesOut[j][3] = newDot;
- }
- }
- }
-
-
+ for( int j = 0; j < numVectors; j++ )
+ {
+ const btVector3& vec = vectors[j] * m_localScaling; // dot( a*c, b) = dot(a, b*c)
+ btScalar maxDot;
+ int index = (int) vec.maxDot( &m_unscaledPoints[0], m_numPoints, maxDot);
+ supportVerticesOut[j][3] = btScalar(-BT_LARGE_FLOAT);
+ if( 0 <= index )
+ {
+ //WARNING: don't swap next lines, the w component would get overwritten!
+ supportVerticesOut[j] = getScaledPoint(index);
+ supportVerticesOut[j][3] = maxDot;
+ }
+ }
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp
index 1e26be531c2..f4324c1f401 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp
@@ -274,23 +274,29 @@ void btConvexPolyhedron::initialize()
#endif
}
-
-void btConvexPolyhedron::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const
+void btConvexPolyhedron::project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const
{
- min = FLT_MAX;
- max = -FLT_MAX;
+ minProj = FLT_MAX;
+ maxProj = -FLT_MAX;
int numVerts = m_vertices.size();
for(int i=0;i<numVerts;i++)
{
btVector3 pt = trans * m_vertices[i];
btScalar dp = pt.dot(dir);
- if(dp < min) min = dp;
- if(dp > max) max = dp;
+ if(dp < minProj)
+ {
+ minProj = dp;
+ witnesPtMin = pt;
+ }
+ if(dp > maxProj)
+ {
+ maxProj = dp;
+ witnesPtMax = pt;
+ }
}
- if(min>max)
+ if(minProj>maxProj)
{
- btScalar tmp = min;
- min = max;
- max = tmp;
+ btSwap(minProj,maxProj);
+ btSwap(witnesPtMin,witnesPtMax);
}
-} \ No newline at end of file
+}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h
index 08db39a33c8..d3cd066ac8d 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexPolyhedron.h
@@ -34,9 +34,12 @@ struct btFace
};
-class btConvexPolyhedron
+ATTRIBUTE_ALIGNED16(class) btConvexPolyhedron
{
public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btConvexPolyhedron();
virtual ~btConvexPolyhedron();
@@ -53,7 +56,7 @@ class btConvexPolyhedron
void initialize();
bool testContainment() const;
- void project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const;
+ void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const;
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp
index 8c67d8ebef1..4b16130211f 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp
@@ -13,6 +13,10 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
+#if defined (_WIN32) || defined (__i386__)
+#define BT_USE_SSE_IN_API
+#endif
+
#include "btConvexShape.h"
#include "btTriangleShape.h"
#include "btSphereShape.h"
@@ -109,19 +113,8 @@ static btVector3 convexHullSupport (const btVector3& localDirOrg, const btVector
return supVec;
#else
- btScalar newDot,maxDot = btScalar(-BT_LARGE_FLOAT);
- int ptIndex = -1;
-
- for (int i=0;i<numPoints;i++)
- {
-
- newDot = vec.dot(points[i]);
- if (newDot > maxDot)
- {
- maxDot = newDot;
- ptIndex = i;
- }
- }
+ btScalar maxDot;
+ long ptIndex = vec.maxDot( points, numPoints, maxDot);
btAssert(ptIndex >= 0);
btVector3 supVec = points[ptIndex] * localScaling;
return supVec;
@@ -141,16 +134,26 @@ btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual (const btV
btBoxShape* convexShape = (btBoxShape*)this;
const btVector3& halfExtents = convexShape->getImplicitShapeDimensions();
+#if defined( __APPLE__ ) && (defined( BT_USE_SSE )||defined( BT_USE_NEON ))
+ #if defined( BT_USE_SSE )
+ return btVector3( _mm_xor_ps( _mm_and_ps( localDir.mVec128, (__m128){-0.0f, -0.0f, -0.0f, -0.0f }), halfExtents.mVec128 ));
+ #elif defined( BT_USE_NEON )
+ return btVector3( (float32x4_t) (((uint32x4_t) localDir.mVec128 & (uint32x4_t){ 0x80000000, 0x80000000, 0x80000000, 0x80000000}) ^ (uint32x4_t) halfExtents.mVec128 ));
+ #else
+ #error unknown vector arch
+ #endif
+#else
return btVector3(btFsels(localDir.x(), halfExtents.x(), -halfExtents.x()),
btFsels(localDir.y(), halfExtents.y(), -halfExtents.y()),
btFsels(localDir.z(), halfExtents.z(), -halfExtents.z()));
+#endif
}
case TRIANGLE_SHAPE_PROXYTYPE:
{
btTriangleShape* triangleShape = (btTriangleShape*)this;
btVector3 dir(localDir.getX(),localDir.getY(),localDir.getZ());
btVector3* vertices = &triangleShape->m_vertices1[0];
- btVector3 dots(dir.dot(vertices[0]), dir.dot(vertices[1]), dir.dot(vertices[2]));
+ btVector3 dots = dir.dot3(vertices[0], vertices[1], vertices[2]);
btVector3 sup = vertices[dots.maxAxis()];
return btVector3(sup.getX(),sup.getY(),sup.getZ());
}
@@ -383,8 +386,8 @@ void btConvexShape::getAabbNonVirtual (const btTransform& t, btVector3& aabbMin,
halfExtents += btVector3(margin,margin,margin);
btMatrix3x3 abs_b = t.getBasis().absolute();
btVector3 center = t.getOrigin();
- btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));
-
+ btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
+
aabbMin = center - extent;
aabbMax = center + extent;
break;
@@ -417,7 +420,7 @@ void btConvexShape::getAabbNonVirtual (const btTransform& t, btVector3& aabbMin,
halfExtents += btVector3(capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual());
btMatrix3x3 abs_b = t.getBasis().absolute();
btVector3 center = t.getOrigin();
- btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));
+ btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
aabbMin = center - extent;
aabbMax = center + extent;
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h
index af5d00388e8..f338865ca13 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h
@@ -22,12 +22,14 @@ subject to the following restrictions:
/// The btConvexTriangleMeshShape is a convex hull of a triangle mesh, but the performance is not as good as btConvexHullShape.
/// A small benefit of this class is that it uses the btStridingMeshInterface, so you can avoid the duplication of the triangle mesh data. Nevertheless, most users should use the much better performing btConvexHullShape instead.
-class btConvexTriangleMeshShape : public btPolyhedralConvexAabbCachingShape
+ATTRIBUTE_ALIGNED16(class) btConvexTriangleMeshShape : public btPolyhedralConvexAabbCachingShape
{
class btStridingMeshInterface* m_stridingMesh;
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface, bool calcAabb = true);
class btStridingMeshInterface* getMeshInterface()
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.h
index 125bfc78a77..6f796950e1d 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.h
@@ -21,7 +21,7 @@ subject to the following restrictions:
#include "LinearMath/btVector3.h"
/// The btCylinderShape class implements a cylinder shape primitive, centered around the origin. Its central axis aligned with the Y axis. btCylinderShapeX is aligned with the X axis and btCylinderShapeZ around the Z axis.
-class btCylinderShape : public btConvexInternalShape
+ATTRIBUTE_ALIGNED16(class) btCylinderShape : public btConvexInternalShape
{
@@ -31,6 +31,8 @@ protected:
public:
+BT_DECLARE_ALIGNED_ALLOCATOR();
+
btVector3 getHalfExtentsWithMargin() const
{
btVector3 halfExtents = getHalfExtentsWithoutMargin();
@@ -95,6 +97,13 @@ public:
return m_upAxis;
}
+ virtual btVector3 getAnisotropicRollingFrictionDirection() const
+ {
+ btVector3 aniDir(0,0,0);
+ aniDir[getUpAxis()]=1;
+ return aniDir;
+ }
+
virtual btScalar getRadius() const
{
return getHalfExtentsWithMargin().getX();
@@ -128,6 +137,8 @@ public:
class btCylinderShapeX : public btCylinderShape
{
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btCylinderShapeX (const btVector3& halfExtents);
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
@@ -149,6 +160,8 @@ public:
class btCylinderShapeZ : public btCylinderShape
{
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btCylinderShapeZ (const btVector3& halfExtents);
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.h
index 87b7b66d1e1..069a79402bf 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.h
@@ -28,9 +28,11 @@ subject to the following restrictions:
/// The btEmptyShape is a collision shape without actual collision detection shape, so most users should ignore this class.
/// It can be replaced by another shape during runtime, but the inertia tensor should be recomputed.
-class btEmptyShape : public btConcaveShape
+ATTRIBUTE_ALIGNED16(class) btEmptyShape : public btConcaveShape
{
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btEmptyShape();
virtual ~btEmptyShape();
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
index 95631c30190..8d4080a63a6 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
@@ -38,7 +38,7 @@ btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int h
// legacy constructor: support only float or unsigned char,
// and min height is zero
PHY_ScalarType hdt = (useFloatData) ? PHY_FLOAT : PHY_UCHAR;
- btScalar minHeight = 0.0;
+ btScalar minHeight = 0.0f;
// previously, height = uchar * maxHeight / 65535.
// So to preserve legacy behavior, heightScale = maxHeight / 65535
@@ -82,6 +82,7 @@ PHY_ScalarType hdt, bool flipQuadEdges
m_heightDataType = hdt;
m_flipQuadEdges = flipQuadEdges;
m_useDiamondSubdivision = false;
+ m_useZigzagSubdivision = false;
m_upAxis = upAxis;
m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.));
@@ -135,9 +136,7 @@ void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,
btMatrix3x3 abs_b = t.getBasis().absolute();
btVector3 center = t.getOrigin();
- btVector3 extent = btVector3(abs_b[0].dot(halfExtents),
- abs_b[1].dot(halfExtents),
- abs_b[2].dot(halfExtents));
+ btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
extent += btVector3(getMargin(),getMargin(),getMargin());
aabbMin = center - extent;
@@ -362,7 +361,7 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
for(int x=startX; x<endX; x++)
{
btVector3 vertices[3];
- if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1)))
+ if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1))|| (m_useZigzagSubdivision && !(j & 1)))
{
//first triangle
getVertex(x,j,vertices[0]);
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
index 78e231e08e6..4a7a4a4bda4 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
@@ -68,7 +68,7 @@ subject to the following restrictions:
For usage and testing see the TerrainDemo.
*/
-class btHeightfieldTerrainShape : public btConcaveShape
+ATTRIBUTE_ALIGNED16(class) btHeightfieldTerrainShape : public btConcaveShape
{
protected:
btVector3 m_localAabbMin;
@@ -93,7 +93,8 @@ protected:
PHY_ScalarType m_heightDataType;
bool m_flipQuadEdges;
- bool m_useDiamondSubdivision;
+ bool m_useDiamondSubdivision;
+ bool m_useZigzagSubdivision;
int m_upAxis;
@@ -116,6 +117,9 @@ protected:
PHY_ScalarType heightDataType, bool flipQuadEdges);
public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
/// preferred constructor
/**
This constructor supports a range of heightfield
@@ -142,6 +146,8 @@ public:
void setUseDiamondSubdivision(bool useDiamondSubdivision=true) { m_useDiamondSubdivision = useDiamondSubdivision;}
+ ///could help compatibility with Ogre heightfields. See https://code.google.com/p/bullet/issues/detail?id=625
+ void setUseZigzagSubdivision(bool useZigzagSubdivision=true) { m_useZigzagSubdivision = useZigzagSubdivision;}
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
index 6c844e8c0af..a3f9a472394 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
@@ -20,7 +20,7 @@ subject to the following restrictions:
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
/// The btMinkowskiSumShape is only for advanced users. This shape represents implicit based minkowski sum of two convex implicit shapes.
-class btMinkowskiSumShape : public btConvexInternalShape
+ATTRIBUTE_ALIGNED16(class) btMinkowskiSumShape : public btConvexInternalShape
{
btTransform m_transA;
@@ -30,6 +30,8 @@ class btMinkowskiSumShape : public btConvexInternalShape
public:
+BT_DECLARE_ALIGNED_ALLOCATOR();
+
btMinkowskiSumShape(const btConvexShape* shapeA,const btConvexShape* shapeB);
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
index c996bfcdaba..a7362ea01f4 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
@@ -13,7 +13,9 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
+#if defined (_WIN32) || defined (__i386__)
+#define BT_USE_SSE_IN_API
+#endif
#include "btMultiSphereShape.h"
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
@@ -39,10 +41,11 @@ btMultiSphereShape::btMultiSphereShape (const btVector3* positions,const btScala
}
-
+#ifndef MIN
+ #define MIN( _a, _b) ((_a) < (_b) ? (_a) : (_b))
+#endif
btVector3 btMultiSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
{
- int i;
btVector3 supVec(0,0,0);
btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
@@ -66,18 +69,23 @@ btMultiSphereShape::btMultiSphereShape (const btVector3* positions,const btScala
const btScalar* rad = &m_radiArray[0];
int numSpheres = m_localPositionArray.size();
- for (i=0;i<numSpheres;i++)
+ for( int k = 0; k < numSpheres; k+= 128 )
{
- vtx = (*pos) +vec*m_localScaling*(*rad) - vec * getMargin();
- pos++;
- rad++;
- newDot = vec.dot(vtx);
- if (newDot > maxDot)
+ btVector3 temp[128];
+ int inner_count = MIN( numSpheres - k, 128 );
+ for( long i = 0; i < inner_count; i++ )
+ {
+ temp[i] = (*pos) +vec*m_localScaling*(*rad) - vec * getMargin();
+ pos++;
+ rad++;
+ }
+ long i = vec.maxDot( temp, inner_count, newDot);
+ if( newDot > maxDot )
{
maxDot = newDot;
- supVec = vtx;
+ supVec = temp[i];
}
- }
+ }
return supVec;
@@ -98,18 +106,25 @@ btMultiSphereShape::btMultiSphereShape (const btVector3* positions,const btScala
const btVector3* pos = &m_localPositionArray[0];
const btScalar* rad = &m_radiArray[0];
int numSpheres = m_localPositionArray.size();
- for (int i=0;i<numSpheres;i++)
- {
- vtx = (*pos) +vec*m_localScaling*(*rad) - vec * getMargin();
- pos++;
- rad++;
- newDot = vec.dot(vtx);
- if (newDot > maxDot)
- {
- maxDot = newDot;
- supportVerticesOut[j] = vtx;
- }
- }
+
+ for( int k = 0; k < numSpheres; k+= 128 )
+ {
+ btVector3 temp[128];
+ int inner_count = MIN( numSpheres - k, 128 );
+ for( long i = 0; i < inner_count; i++ )
+ {
+ temp[i] = (*pos) +vec*m_localScaling*(*rad) - vec * getMargin();
+ pos++;
+ rad++;
+ }
+ long i = vec.maxDot( temp, inner_count, newDot);
+ if( newDot > maxDot )
+ {
+ maxDot = newDot;
+ supportVerticesOut[j] = temp[i];
+ }
+ }
+
}
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h
index 06c5d16d941..5d3b4026848 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h
@@ -25,13 +25,15 @@ subject to the following restrictions:
///The btMultiSphereShape represents the convex hull of a collection of spheres. You can create special capsules or other smooth volumes.
///It is possible to animate the spheres for deformation, but call 'recalcLocalAabb' after changing any sphere position/radius
-class btMultiSphereShape : public btConvexInternalAabbCachingShape
+ATTRIBUTE_ALIGNED16(class) btMultiSphereShape : public btConvexInternalAabbCachingShape
{
btAlignedObjectArray<btVector3> m_localPositionArray;
btAlignedObjectArray<btScalar> m_radiArray;
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btMultiSphereShape (const btVector3* positions,const btScalar* radi,int numSpheres);
///CollisionShape Interface
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
index 82def79cf55..4854f370f73 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
@@ -12,6 +12,9 @@ subject to the following restrictions:
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
+#if defined (_WIN32) || defined (__i386__)
+#define BT_USE_SSE_IN_API
+#endif
#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
#include "btConvexPolyhedron.h"
@@ -31,51 +34,58 @@ btPolyhedralConvexShape::~btPolyhedralConvexShape()
{
if (m_polyhedron)
{
+ m_polyhedron->~btConvexPolyhedron();
btAlignedFree(m_polyhedron);
}
}
-bool btPolyhedralConvexShape::initializePolyhedralFeatures()
+bool btPolyhedralConvexShape::initializePolyhedralFeatures(int shiftVerticesByMargin)
{
if (m_polyhedron)
+ {
+ m_polyhedron->~btConvexPolyhedron();
btAlignedFree(m_polyhedron);
+ }
void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron),16);
m_polyhedron = new (mem) btConvexPolyhedron;
- btAlignedObjectArray<btVector3> orgVertices;
+ btAlignedObjectArray<btVector3> orgVertices;
for (int i=0;i<getNumVertices();i++)
{
btVector3& newVertex = orgVertices.expand();
getVertex(i,newVertex);
}
-
-#if 0
- btAlignedObjectArray<btVector3> planeEquations;
- btGeometryUtil::getPlaneEquationsFromVertices(orgVertices,planeEquations);
-
- btAlignedObjectArray<btVector3> shiftedPlaneEquations;
- for (int p=0;p<planeEquations.size();p++)
+
+ btConvexHullComputer conv;
+
+ if (shiftVerticesByMargin)
{
- btVector3 plane = planeEquations[p];
- plane[3] -= getMargin();
- shiftedPlaneEquations.push_back(plane);
- }
+ btAlignedObjectArray<btVector3> planeEquations;
+ btGeometryUtil::getPlaneEquationsFromVertices(orgVertices,planeEquations);
- btAlignedObjectArray<btVector3> tmpVertices;
+ btAlignedObjectArray<btVector3> shiftedPlaneEquations;
+ for (int p=0;p<planeEquations.size();p++)
+ {
+ btVector3 plane = planeEquations[p];
+ // btScalar margin = getMargin();
+ plane[3] -= getMargin();
+ shiftedPlaneEquations.push_back(plane);
+ }
- btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,tmpVertices);
- btConvexHullComputer conv;
- conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f);
+ btAlignedObjectArray<btVector3> tmpVertices;
-#else
- btConvexHullComputer conv;
- conv.compute(&orgVertices[0].getX(), sizeof(btVector3),orgVertices.size(),0.f,0.f);
-
-#endif
+ btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,tmpVertices);
+
+ conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f);
+ } else
+ {
+
+ conv.compute(&orgVertices[0].getX(), sizeof(btVector3),orgVertices.size(),0.f,0.f);
+ }
@@ -107,9 +117,6 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures()
int numEdges = 0;
//compute face normals
- btScalar maxCross2 = 0.f;
- int chosenEdge = -1;
-
do
{
@@ -192,7 +199,8 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures()
{
//do the merge: use Graham Scan 2d convex hull
- btAlignedObjectArray<GrahamVector2> orgpoints;
+ btAlignedObjectArray<GrahamVector3> orgpoints;
+ btVector3 averageFaceNormal(0,0,0);
for (int i=0;i<coplanarFaceGroup.size();i++)
{
@@ -200,16 +208,12 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures()
btFace& face = tmpFaces[coplanarFaceGroup[i]];
btVector3 faceNormal(face.m_plane[0],face.m_plane[1],face.m_plane[2]);
- btVector3 xyPlaneNormal(0,0,1);
-
- btQuaternion rotationArc = shortestArcQuat(faceNormal,xyPlaneNormal);
-
+ averageFaceNormal+=faceNormal;
for (int f=0;f<face.m_indices.size();f++)
{
int orgIndex = face.m_indices[f];
btVector3 pt = m_polyhedron->m_vertices[orgIndex];
- btVector3 rotatedPt = quatRotate(rotationArc,pt);
- rotatedPt.setZ(0);
+
bool found = false;
for (int i=0;i<orgpoints.size();i++)
@@ -222,34 +226,45 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures()
}
}
if (!found)
- orgpoints.push_back(GrahamVector2(rotatedPt,orgIndex));
+ orgpoints.push_back(GrahamVector3(pt,orgIndex));
}
}
+
+
btFace combinedFace;
for (int i=0;i<4;i++)
combinedFace.m_plane[i] = tmpFaces[coplanarFaceGroup[0]].m_plane[i];
- btAlignedObjectArray<GrahamVector2> hull;
- GrahamScanConvexHull2D(orgpoints,hull);
+ btAlignedObjectArray<GrahamVector3> hull;
+
+ averageFaceNormal.normalize();
+ GrahamScanConvexHull2D(orgpoints,hull,averageFaceNormal);
for (int i=0;i<hull.size();i++)
{
combinedFace.m_indices.push_back(hull[i].m_orgIndex);
- for(int k = 0; k < orgpoints.size(); k++) {
- if(orgpoints[k].m_orgIndex == hull[i].m_orgIndex) {
+ for(int k = 0; k < orgpoints.size(); k++)
+ {
+ if(orgpoints[k].m_orgIndex == hull[i].m_orgIndex)
+ {
orgpoints[k].m_orgIndex = -1; // invalidate...
break;
- }
+ }
}
}
+
// are there rejected vertices?
bool reject_merge = false;
+
+
+
for(int i = 0; i < orgpoints.size(); i++) {
if(orgpoints[i].m_orgIndex == -1)
continue; // this is in the hull...
// this vertex is rejected -- is anybody else using this vertex?
for(int j = 0; j < tmpFaces.size(); j++) {
+
btFace& face = tmpFaces[j];
// is this a face of the current coplanar group?
bool is_in_current_group = false;
@@ -275,20 +290,23 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures()
if(reject_merge)
break;
}
- if(!reject_merge) {
+
+ if (!reject_merge)
+ {
// do this merge!
did_merge = true;
- m_polyhedron->m_faces.push_back(combinedFace);
+ m_polyhedron->m_faces.push_back(combinedFace);
}
}
if(!did_merge)
{
for (int i=0;i<coplanarFaceGroup.size();i++)
{
- m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);
+ btFace face = tmpFaces[coplanarFaceGroup[i]];
+ m_polyhedron->m_faces.push_back(face);
}
- }
+ }
@@ -299,6 +317,9 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures()
return true;
}
+#ifndef MIN
+ #define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
+#endif
btVector3 btPolyhedralConvexShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
{
@@ -323,17 +344,19 @@ btVector3 btPolyhedralConvexShape::localGetSupportingVertexWithoutMargin(const b
btVector3 vtx;
btScalar newDot;
- for (i=0;i<getNumVertices();i++)
- {
- getVertex(i,vtx);
- newDot = vec.dot(vtx);
+ for( int k = 0; k < getNumVertices(); k += 128 )
+ {
+ btVector3 temp[128];
+ int inner_count = MIN(getNumVertices() - k, 128);
+ for( i = 0; i < inner_count; i++ )
+ getVertex(i,temp[i]);
+ i = (int) vec.maxDot( temp, inner_count, newDot);
if (newDot > maxDot)
{
maxDot = newDot;
- supVec = vtx;
- }
- }
-
+ supVec = temp[i];
+ }
+ }
#endif //__SPU__
return supVec;
@@ -356,21 +379,23 @@ void btPolyhedralConvexShape::batchedUnitVectorGetSupportingVertexWithoutMargin(
for (int j=0;j<numVectors;j++)
{
-
- const btVector3& vec = vectors[j];
-
- for (i=0;i<getNumVertices();i++)
- {
- getVertex(i,vtx);
- newDot = vec.dot(vtx);
- if (newDot > supportVerticesOut[j][3])
- {
- //WARNING: don't swap next lines, the w component would get overwritten!
- supportVerticesOut[j] = vtx;
+ const btVector3& vec = vectors[j];
+
+ for( int k = 0; k < getNumVertices(); k += 128 )
+ {
+ btVector3 temp[128];
+ int inner_count = MIN(getNumVertices() - k, 128);
+ for( i = 0; i < inner_count; i++ )
+ getVertex(i,temp[i]);
+ i = (int) vec.maxDot( temp, inner_count, newDot);
+ if (newDot > supportVerticesOut[j][3])
+ {
+ supportVerticesOut[j] = temp[i];
supportVerticesOut[j][3] = newDot;
- }
- }
- }
+ }
+ }
+ }
+
#endif //__SPU__
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h
index ee2e1e28277..961d001a9dd 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h
@@ -22,7 +22,7 @@ class btConvexPolyhedron;
///The btPolyhedralConvexShape is an internal interface class for polyhedral convex shapes.
-class btPolyhedralConvexShape : public btConvexInternalShape
+ATTRIBUTE_ALIGNED16(class) btPolyhedralConvexShape : public btConvexInternalShape
{
@@ -31,13 +31,17 @@ protected:
btConvexPolyhedron* m_polyhedron;
public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btPolyhedralConvexShape();
virtual ~btPolyhedralConvexShape();
///optional method mainly used to generate multiple contact points by clipping polyhedral features (faces/edges)
- virtual bool initializePolyhedralFeatures();
+ ///experimental/work-in-progress
+ virtual bool initializePolyhedralFeatures(int shiftVerticesByMargin=0);
const btConvexPolyhedron* getConvexPolyhedron() const
{
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp
index 25d58d61bb1..6a337c786c4 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp
@@ -98,9 +98,7 @@ void btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans,btVector3& a
btVector3 center = trans(localCenter);
- btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
- abs_b[1].dot(localHalfExtents),
- abs_b[2].dot(localHalfExtents));
+ btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
aabbMin = center - extent;
aabbMax = center + extent;
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h
index ff86ef319e9..39049eaf083 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h
@@ -31,6 +31,8 @@ ATTRIBUTE_ALIGNED16(class) btScaledBvhTriangleMeshShape : public btConcaveShape
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,const btVector3& localScaling);
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h
index 642a2887435..e959f198b69 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h
@@ -25,7 +25,7 @@ subject to the following restrictions:
///The btShapeHull class takes a btConvexShape, builds a simplified convex hull using btConvexHull and provides triangle indices and vertices.
///It can be useful for to simplify a complex convex object and for visualization of a non-polyhedral convex object.
///It approximates the convex hull using the supporting vertex of 42 directions.
-class btShapeHull
+ATTRIBUTE_ALIGNED16(class) btShapeHull
{
protected:
@@ -37,6 +37,8 @@ protected:
static btVector3* getUnitSpherePoints();
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btShapeHull (const btConvexShape* shape);
~btShapeHull ();
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h
index b13825e610d..e6e32883959 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h
@@ -31,6 +31,8 @@ protected:
btVector3 m_localScaling;
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant);
virtual ~btStaticPlaneShape();
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp
index dd22fc5635a..b3d449676b9 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp
@@ -242,7 +242,7 @@ const char* btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* s
int gfxindex;
// btVector3 triangle[3];
- btVector3 meshScaling = getScaling();
+ // btVector3 meshScaling = getScaling();
///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
for (part=0;part<graphicssubparts ;part++,memPtr++)
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h
index f2b27ade8e8..9fbe139768d 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h
@@ -27,13 +27,15 @@ subject to the following restrictions:
/// The btStridingMeshInterface is the interface class for high performance generic access to triangle meshes, used in combination with btBvhTriangleMeshShape and some other collision shapes.
/// Using index striding of 3*sizeof(integer) it can use triangle arrays, using index striding of 1*sizeof(integer) it can handle triangle strips.
/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory.
-class btStridingMeshInterface
+ATTRIBUTE_ALIGNED16(class ) btStridingMeshInterface
{
protected:
btVector3 m_scaling;
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btStridingMeshInterface() :m_scaling(btScalar(1.),btScalar(1.),btScalar(1.))
{
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h
index 6b7128efc8e..b69209835ef 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h
@@ -22,7 +22,7 @@ subject to the following restrictions:
///The btBU_Simplex1to4 implements tetrahedron, triangle, line, vertex collision shapes. In most cases it is better to use btConvexHullShape instead.
-class btBU_Simplex1to4 : public btPolyhedralConvexAabbCachingShape
+ATTRIBUTE_ALIGNED16(class) btBU_Simplex1to4 : public btPolyhedralConvexAabbCachingShape
{
protected:
@@ -30,6 +30,8 @@ protected:
btVector3 m_vertices[4];
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btBU_Simplex1to4();
btBU_Simplex1to4(const btVector3& pt0);
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h
index 1cea7045f20..17deef89d37 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleInfoMap.h
@@ -123,11 +123,11 @@ SIMD_FORCE_INLINE int btTriangleInfoMap::calculateSerializeBufferSize() const
SIMD_FORCE_INLINE const char* btTriangleInfoMap::serialize(void* dataBuffer, btSerializer* serializer) const
{
btTriangleInfoMapData* tmapData = (btTriangleInfoMapData*) dataBuffer;
- tmapData->m_convexEpsilon = m_convexEpsilon;
- tmapData->m_planarEpsilon = m_planarEpsilon;
- tmapData->m_equalVertexThreshold = m_equalVertexThreshold;
- tmapData->m_edgeDistanceThreshold = m_edgeDistanceThreshold;
- tmapData->m_zeroAreaThreshold = m_zeroAreaThreshold;
+ tmapData->m_convexEpsilon = (float)m_convexEpsilon;
+ tmapData->m_planarEpsilon = (float)m_planarEpsilon;
+ tmapData->m_equalVertexThreshold =(float) m_equalVertexThreshold;
+ tmapData->m_edgeDistanceThreshold = (float)m_edgeDistanceThreshold;
+ tmapData->m_zeroAreaThreshold = (float)m_zeroAreaThreshold;
tmapData->m_hashTableSize = m_hashTable.size();
@@ -172,9 +172,9 @@ SIMD_FORCE_INLINE const char* btTriangleInfoMap::serialize(void* dataBuffer, btS
btTriangleInfoData* memPtr = (btTriangleInfoData*)chunk->m_oldPtr;
for (int i=0;i<numElem;i++,memPtr++)
{
- memPtr->m_edgeV0V1Angle = m_valueArray[i].m_edgeV0V1Angle;
- memPtr->m_edgeV1V2Angle = m_valueArray[i].m_edgeV1V2Angle;
- memPtr->m_edgeV2V0Angle = m_valueArray[i].m_edgeV2V0Angle;
+ memPtr->m_edgeV0V1Angle = (float)m_valueArray[i].m_edgeV0V1Angle;
+ memPtr->m_edgeV1V2Angle = (float)m_valueArray[i].m_edgeV1V2Angle;
+ memPtr->m_edgeV2V0Angle = (float)m_valueArray[i].m_edgeV2V0Angle;
memPtr->m_flags = m_valueArray[i].m_flags;
}
serializer->finalizeChunk(chunk,"btTriangleInfoData",BT_ARRAY_CODE,(void*) &m_valueArray[0]);
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp
index b29e0f71e62..51a2f8a0739 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp
@@ -138,3 +138,25 @@ int btTriangleMesh::getNumTriangles() const
}
return m_16bitIndices.size() / 3;
}
+
+void btTriangleMesh::preallocateVertices(int numverts)
+{
+ if (m_use4componentVertices)
+ {
+ m_4componentVertices.reserve(numverts);
+ } else
+ {
+ m_3componentVertices.reserve(numverts);
+ }
+}
+
+void btTriangleMesh::preallocateIndices(int numindices)
+{
+ if (m_use32bitIndices)
+ {
+ m_32bitIndices.reserve(numindices);
+ } else
+ {
+ m_16bitIndices.reserve(numindices);
+ }
+}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h
index f623157fac1..29d1b5cdaa4 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h
@@ -55,8 +55,8 @@ class btTriangleMesh : public btTriangleIndexVertexArray
int getNumTriangles() const;
- virtual void preallocateVertices(int numverts){(void) numverts;}
- virtual void preallocateIndices(int numindices){(void) numindices;}
+ virtual void preallocateVertices(int numverts);
+ virtual void preallocateIndices(int numindices);
///findOrAddVertex is an internal method, use addTriangle instead
int findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices);
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp
index 683684da770..0e17951405c 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp
@@ -55,13 +55,9 @@ void btTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,bt
btVector3 center = trans(localCenter);
- btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
- abs_b[1].dot(localHalfExtents),
- abs_b[2].dot(localHalfExtents));
+ btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
aabbMin = center - extent;
aabbMax = center + extent;
-
-
}
void btTriangleMeshShape::recalcLocalAabb()
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h
index c8caf8fe696..453e58005a4 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h
@@ -21,7 +21,7 @@ subject to the following restrictions:
///The btTriangleMeshShape is an internal concave triangle mesh interface. Don't use this class directly, use btBvhTriangleMeshShape instead.
-class btTriangleMeshShape : public btConcaveShape
+ATTRIBUTE_ALIGNED16(class) btTriangleMeshShape : public btConcaveShape
{
protected:
btVector3 m_localAabbMin;
@@ -33,6 +33,7 @@ protected:
btTriangleMeshShape(btStridingMeshInterface* meshInterface);
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
virtual ~btTriangleMeshShape();
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h
index 71b0557384e..a8a80f82fe2 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h
@@ -25,6 +25,8 @@ ATTRIBUTE_ALIGNED16(class) btTriangleShape : public btPolyhedralConvexShape
public:
+BT_DECLARE_ALIGNED_ALLOCATOR();
+
btVector3 m_vertices1[3];
virtual int getNumVertices() const
@@ -66,7 +68,7 @@ public:
btVector3 localGetSupportingVertexWithoutMargin(const btVector3& dir)const
{
- btVector3 dots(dir.dot(m_vertices1[0]), dir.dot(m_vertices1[1]), dir.dot(m_vertices1[2]));
+ btVector3 dots = dir.dot3(m_vertices1[0], m_vertices1[1], m_vertices1[2]);
return m_vertices1[dots.maxAxis()];
}
@@ -76,7 +78,7 @@ public:
for (int i=0;i<numVectors;i++)
{
const btVector3& dir = vectors[i];
- btVector3 dots(dir.dot(m_vertices1[0]), dir.dot(m_vertices1[1]), dir.dot(m_vertices1[2]));
+ btVector3 dots = dir.dot3(m_vertices1[0], m_vertices1[1], m_vertices1[2]);
supportVerticesOut[i] = m_vertices1[dots.maxAxis()];
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h
index cbf7e6fd3ed..a10f58d2429 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h
@@ -21,7 +21,7 @@ subject to the following restrictions:
///The btUniformScalingShape allows to re-use uniform scaled instances of btConvexShape in a memory efficient way.
///Istead of using btUniformScalingShape, it is better to use the non-uniform setLocalScaling method on convex shapes that implement it.
-class btUniformScalingShape : public btConvexShape
+ATTRIBUTE_ALIGNED16(class) btUniformScalingShape : public btConvexShape
{
btConvexShape* m_childConvexShape;
@@ -29,6 +29,8 @@ class btUniformScalingShape : public btConvexShape
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btUniformScalingShape( btConvexShape* convexChildShape, btScalar uniformScalingFactor);
virtual ~btUniformScalingShape();
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btBoxCollision.h b/extern/bullet2/src/BulletCollision/Gimpact/btBoxCollision.h
index d5676aaa80e..0a0357e5a81 100644
--- a/extern/bullet2/src/BulletCollision/Gimpact/btBoxCollision.h
+++ b/extern/bullet2/src/BulletCollision/Gimpact/btBoxCollision.h
@@ -218,9 +218,7 @@ public:
SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point) const
{
- return btVector3(m_R1to0[0].dot(point) + m_T1to0.x(),
- m_R1to0[1].dot(point) + m_T1to0.y(),
- m_R1to0[2].dot(point) + m_T1to0.z());
+ return point.dot3( m_R1to0[0], m_R1to0[1], m_R1to0[2] ) + m_T1to0;
}
};
@@ -364,9 +362,9 @@ public:
// Compute new center
center = trans(center);
- btVector3 textends(extends.dot(trans.getBasis().getRow(0).absolute()),
- extends.dot(trans.getBasis().getRow(1).absolute()),
- extends.dot(trans.getBasis().getRow(2).absolute()));
+ btVector3 textends = extends.dot3(trans.getBasis().getRow(0).absolute(),
+ trans.getBasis().getRow(1).absolute(),
+ trans.getBasis().getRow(2).absolute());
m_min = center - textends;
m_max = center + textends;
@@ -381,10 +379,10 @@ public:
// Compute new center
center = trans.transform(center);
- btVector3 textends(extends.dot(trans.m_R1to0.getRow(0).absolute()),
- extends.dot(trans.m_R1to0.getRow(1).absolute()),
- extends.dot(trans.m_R1to0.getRow(2).absolute()));
-
+ btVector3 textends = extends.dot3(trans.m_R1to0.getRow(0).absolute(),
+ trans.m_R1to0.getRow(1).absolute(),
+ trans.m_R1to0.getRow(2).absolute());
+
m_min = center - textends;
m_max = center + textends;
}
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btCompoundFromGimpact.h b/extern/bullet2/src/BulletCollision/Gimpact/btCompoundFromGimpact.h
new file mode 100644
index 00000000000..02f8b678a45
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/Gimpact/btCompoundFromGimpact.h
@@ -0,0 +1,93 @@
+#ifndef BT_COMPOUND_FROM_GIMPACT
+#define BT_COMPOUND_FROM_GIMPACT
+
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "btGImpactShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
+
+struct MyCallback : public btTriangleRaycastCallback
+ {
+ int m_ignorePart;
+ int m_ignoreTriangleIndex;
+
+
+ MyCallback(const btVector3& from, const btVector3& to, int ignorePart, int ignoreTriangleIndex)
+ :btTriangleRaycastCallback(from,to),
+ m_ignorePart(ignorePart),
+ m_ignoreTriangleIndex(ignoreTriangleIndex)
+ {
+
+ }
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex)
+ {
+ if (partId!=m_ignorePart || triangleIndex!=m_ignoreTriangleIndex)
+ {
+ if (hitFraction < m_hitFraction)
+ return hitFraction;
+ }
+
+ return m_hitFraction;
+ }
+ };
+ struct MyInternalTriangleIndexCallback :public btInternalTriangleIndexCallback
+ {
+ const btGImpactMeshShape* m_gimpactShape;
+ btCompoundShape* m_colShape;
+ btScalar m_depth;
+
+ MyInternalTriangleIndexCallback (btCompoundShape* colShape, const btGImpactMeshShape* meshShape, btScalar depth)
+ :m_colShape(colShape),
+ m_gimpactShape(meshShape),
+ m_depth(depth)
+ {
+ }
+
+ virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
+ {
+ btVector3 scale = m_gimpactShape->getLocalScaling();
+ btVector3 v0=triangle[0]*scale;
+ btVector3 v1=triangle[1]*scale;
+ btVector3 v2=triangle[2]*scale;
+
+ btVector3 centroid = (v0+v1+v2)/3;
+ btVector3 normal = (v1-v0).cross(v2-v0);
+ normal.normalize();
+ btVector3 rayFrom = centroid;
+ btVector3 rayTo = centroid-normal*m_depth;
+
+ MyCallback cb(rayFrom,rayTo,partId,triangleIndex);
+
+ m_gimpactShape->processAllTrianglesRay(&cb,rayFrom, rayTo);
+ if (cb.m_hitFraction<1)
+ {
+ rayTo.setInterpolate3(cb.m_from,cb.m_to,cb.m_hitFraction);
+ //rayTo = cb.m_from;
+ //rayTo = rayTo.lerp(cb.m_to,cb.m_hitFraction);
+ //gDebugDraw.drawLine(tr(centroid),tr(centroid+normal),btVector3(1,0,0));
+ }
+
+
+
+ btBU_Simplex1to4* tet = new btBU_Simplex1to4(v0,v1,v2,rayTo);
+ btTransform ident;
+ ident.setIdentity();
+ m_colShape->addChildShape(ident,tet);
+ }
+ };
+
+btCompoundShape* btCreateCompoundFromGimpactShape(const btGImpactMeshShape* gimpactMesh, btScalar depth)
+{
+ btCompoundShape* colShape = new btCompoundShape();
+
+ btTransform tr;
+ tr.setIdentity();
+
+ MyInternalTriangleIndexCallback cb(colShape,gimpactMesh, depth);
+ btVector3 aabbMin,aabbMax;
+ gimpactMesh->getAabb(tr,aabbMin,aabbMax);
+ gimpactMesh->getMeshInterface()->InternalProcessAllTriangles(&cb,aabbMin,aabbMax);
+
+ return colShape;
+}
+
+#endif //BT_COMPOUND_FROM_GIMPACT \ No newline at end of file
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp
index 2f2c09ffc03..2e87475e393 100644
--- a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp
+++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp
@@ -51,7 +51,7 @@ public:
}
- void get_plane_equation_transformed(const btTransform & trans,btVector4 &equation)
+ void get_plane_equation_transformed(const btTransform & trans,btVector4 &equation) const
{
equation[0] = trans.getBasis().getRow(0).dot(m_planeNormal);
equation[1] = trans.getBasis().getRow(1).dot(m_planeNormal);
@@ -89,7 +89,7 @@ Declared here due of insuficent space on Pool allocators
class GIM_ShapeRetriever
{
public:
- btGImpactShapeInterface * m_gim_shape;
+ const btGImpactShapeInterface * m_gim_shape;
btTriangleShapeEx m_trishape;
btTetrahedronShapeEx m_tetrashape;
@@ -98,7 +98,7 @@ public:
{
public:
GIM_ShapeRetriever * m_parent;
- virtual btCollisionShape * getChildShape(int index)
+ virtual const btCollisionShape * getChildShape(int index)
{
return m_parent->m_gim_shape->getChildShape(index);
}
@@ -133,7 +133,7 @@ public:
TetraShapeRetriever m_tetra_retriever;
ChildShapeRetriever * m_current_retriever;
- GIM_ShapeRetriever(btGImpactShapeInterface * gim_shape)
+ GIM_ShapeRetriever(const btGImpactShapeInterface * gim_shape)
{
m_gim_shape = gim_shape;
//select retriever
@@ -153,7 +153,7 @@ public:
m_current_retriever->m_parent = this;
}
- btCollisionShape * getChildShape(int index)
+ const btCollisionShape * getChildShape(int index)
{
return m_current_retriever->getChildShape(index);
}
@@ -193,8 +193,8 @@ float btGImpactCollisionAlgorithm::getAverageTriangleCollisionTime()
-btGImpactCollisionAlgorithm::btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
-: btActivatingCollisionAlgorithm(ci,body0,body1)
+btGImpactCollisionAlgorithm::btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
+: btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap)
{
m_manifoldPtr = NULL;
m_convex_algorithm = NULL;
@@ -209,71 +209,58 @@ btGImpactCollisionAlgorithm::~btGImpactCollisionAlgorithm()
-void btGImpactCollisionAlgorithm::addContactPoint(btCollisionObject * body0,
- btCollisionObject * body1,
+void btGImpactCollisionAlgorithm::addContactPoint(const btCollisionObjectWrapper * body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
const btVector3 & point,
const btVector3 & normal,
btScalar distance)
{
m_resultOut->setShapeIdentifiersA(m_part0,m_triface0);
m_resultOut->setShapeIdentifiersB(m_part1,m_triface1);
- checkManifold(body0,body1);
+ checkManifold(body0Wrap,body1Wrap);
m_resultOut->addContactPoint(normal,point,distance);
}
void btGImpactCollisionAlgorithm::shape_vs_shape_collision(
- btCollisionObject * body0,
- btCollisionObject * body1,
- btCollisionShape * shape0,
- btCollisionShape * shape1)
+ const btCollisionObjectWrapper * body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btCollisionShape * shape0,
+ const btCollisionShape * shape1)
{
- btCollisionShape* tmpShape0 = body0->getCollisionShape();
- btCollisionShape* tmpShape1 = body1->getCollisionShape();
-
- body0->internalSetTemporaryCollisionShape(shape0);
- body1->internalSetTemporaryCollisionShape(shape1);
{
- btCollisionAlgorithm* algor = newAlgorithm(body0,body1);
+
+ btCollisionAlgorithm* algor = newAlgorithm(body0Wrap,body1Wrap);
// post : checkManifold is called
m_resultOut->setShapeIdentifiersA(m_part0,m_triface0);
m_resultOut->setShapeIdentifiersB(m_part1,m_triface1);
-
- algor->processCollision(body0,body1,*m_dispatchInfo,m_resultOut);
-
+
+ algor->processCollision(body0Wrap,body1Wrap,*m_dispatchInfo,m_resultOut);
+
algor->~btCollisionAlgorithm();
m_dispatcher->freeCollisionAlgorithm(algor);
}
- body0->internalSetTemporaryCollisionShape(tmpShape0);
- body1->internalSetTemporaryCollisionShape(tmpShape1);
}
void btGImpactCollisionAlgorithm::convex_vs_convex_collision(
- btCollisionObject * body0,
- btCollisionObject * body1,
- btCollisionShape * shape0,
- btCollisionShape * shape1)
+ const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btCollisionShape* shape0,
+ const btCollisionShape* shape1)
{
- btCollisionShape* tmpShape0 = body0->getCollisionShape();
- btCollisionShape* tmpShape1 = body1->getCollisionShape();
-
- body0->internalSetTemporaryCollisionShape(shape0);
- body1->internalSetTemporaryCollisionShape(shape1);
-
-
m_resultOut->setShapeIdentifiersA(m_part0,m_triface0);
m_resultOut->setShapeIdentifiersB(m_part1,m_triface1);
- checkConvexAlgorithm(body0,body1);
- m_convex_algorithm->processCollision(body0,body1,*m_dispatchInfo,m_resultOut);
+ btCollisionObjectWrapper ob0(body0Wrap,shape0,body0Wrap->getCollisionObject(),body0Wrap->getWorldTransform(),m_part0,m_triface0);
+ btCollisionObjectWrapper ob1(body1Wrap,shape1,body1Wrap->getCollisionObject(),body1Wrap->getWorldTransform(),m_part1,m_triface1);
+ checkConvexAlgorithm(&ob0,&ob1);
+ m_convex_algorithm->processCollision(&ob0,&ob1,*m_dispatchInfo,m_resultOut);
- body0->internalSetTemporaryCollisionShape(tmpShape0);
- body1->internalSetTemporaryCollisionShape(tmpShape1);
}
@@ -283,8 +270,8 @@ void btGImpactCollisionAlgorithm::convex_vs_convex_collision(
void btGImpactCollisionAlgorithm::gimpact_vs_gimpact_find_pairs(
const btTransform & trans0,
const btTransform & trans1,
- btGImpactShapeInterface * shape0,
- btGImpactShapeInterface * shape1,btPairSet & pairset)
+ const btGImpactShapeInterface * shape0,
+ const btGImpactShapeInterface * shape1,btPairSet & pairset)
{
if(shape0->hasBoxSet() && shape1->hasBoxSet())
{
@@ -320,8 +307,8 @@ void btGImpactCollisionAlgorithm::gimpact_vs_gimpact_find_pairs(
void btGImpactCollisionAlgorithm::gimpact_vs_shape_find_pairs(
const btTransform & trans0,
const btTransform & trans1,
- btGImpactShapeInterface * shape0,
- btCollisionShape * shape1,
+ const btGImpactShapeInterface * shape0,
+ const btCollisionShape * shape1,
btAlignedObjectArray<int> & collided_primitives)
{
@@ -359,10 +346,10 @@ void btGImpactCollisionAlgorithm::gimpact_vs_shape_find_pairs(
}
-void btGImpactCollisionAlgorithm::collide_gjk_triangles(btCollisionObject * body0,
- btCollisionObject * body1,
- btGImpactMeshShapePart * shape0,
- btGImpactMeshShapePart * shape1,
+void btGImpactCollisionAlgorithm::collide_gjk_triangles(const btCollisionObjectWrapper * body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btGImpactMeshShapePart * shape0,
+ const btGImpactMeshShapePart * shape1,
const int * pairs, int pair_count)
{
btTriangleShapeEx tri0;
@@ -389,7 +376,7 @@ void btGImpactCollisionAlgorithm::collide_gjk_triangles(btCollisionObject * body
//collide two convex shapes
if(tri0.overlap_test_conservative(tri1))
{
- convex_vs_convex_collision(body0,body1,&tri0,&tri1);
+ convex_vs_convex_collision(body0Wrap,body1Wrap,&tri0,&tri1);
}
}
@@ -398,14 +385,14 @@ void btGImpactCollisionAlgorithm::collide_gjk_triangles(btCollisionObject * body
shape1->unlockChildShapes();
}
-void btGImpactCollisionAlgorithm::collide_sat_triangles(btCollisionObject * body0,
- btCollisionObject * body1,
- btGImpactMeshShapePart * shape0,
- btGImpactMeshShapePart * shape1,
+void btGImpactCollisionAlgorithm::collide_sat_triangles(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactMeshShapePart * shape0,
+ const btGImpactMeshShapePart * shape1,
const int * pairs, int pair_count)
{
- btTransform orgtrans0 = body0->getWorldTransform();
- btTransform orgtrans1 = body1->getWorldTransform();
+ btTransform orgtrans0 = body0Wrap->getWorldTransform();
+ btTransform orgtrans1 = body1Wrap->getWorldTransform();
btPrimitiveTriangle ptri0;
btPrimitiveTriangle ptri1;
@@ -451,7 +438,7 @@ void btGImpactCollisionAlgorithm::collide_sat_triangles(btCollisionObject * body
while(j--)
{
- addContactPoint(body0, body1,
+ addContactPoint(body0Wrap, body1Wrap,
contact_data.m_points[j],
contact_data.m_separating_normal,
-contact_data.m_penetration_depth);
@@ -472,20 +459,20 @@ void btGImpactCollisionAlgorithm::collide_sat_triangles(btCollisionObject * body
void btGImpactCollisionAlgorithm::gimpact_vs_gimpact(
- btCollisionObject * body0,
- btCollisionObject * body1,
- btGImpactShapeInterface * shape0,
- btGImpactShapeInterface * shape1)
+ const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btGImpactShapeInterface * shape0,
+ const btGImpactShapeInterface * shape1)
{
if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
{
- btGImpactMeshShape * meshshape0 = static_cast<btGImpactMeshShape *>(shape0);
+ const btGImpactMeshShape * meshshape0 = static_cast<const btGImpactMeshShape *>(shape0);
m_part0 = meshshape0->getMeshPartCount();
while(m_part0--)
{
- gimpact_vs_gimpact(body0,body1,meshshape0->getMeshPart(m_part0),shape1);
+ gimpact_vs_gimpact(body0Wrap,body1Wrap,meshshape0->getMeshPart(m_part0),shape1);
}
return;
@@ -493,13 +480,13 @@ void btGImpactCollisionAlgorithm::gimpact_vs_gimpact(
if(shape1->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
{
- btGImpactMeshShape * meshshape1 = static_cast<btGImpactMeshShape *>(shape1);
+ const btGImpactMeshShape * meshshape1 = static_cast<const btGImpactMeshShape *>(shape1);
m_part1 = meshshape1->getMeshPartCount();
while(m_part1--)
{
- gimpact_vs_gimpact(body0,body1,shape0,meshshape1->getMeshPart(m_part1));
+ gimpact_vs_gimpact(body0Wrap,body1Wrap,shape0,meshshape1->getMeshPart(m_part1));
}
@@ -507,8 +494,8 @@ void btGImpactCollisionAlgorithm::gimpact_vs_gimpact(
}
- btTransform orgtrans0 = body0->getWorldTransform();
- btTransform orgtrans1 = body1->getWorldTransform();
+ btTransform orgtrans0 = body0Wrap->getWorldTransform();
+ btTransform orgtrans1 = body1Wrap->getWorldTransform();
btPairSet pairset;
@@ -519,13 +506,13 @@ void btGImpactCollisionAlgorithm::gimpact_vs_gimpact(
if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART)
{
- btGImpactMeshShapePart * shapepart0 = static_cast<btGImpactMeshShapePart * >(shape0);
- btGImpactMeshShapePart * shapepart1 = static_cast<btGImpactMeshShapePart * >(shape1);
+ const btGImpactMeshShapePart * shapepart0 = static_cast<const btGImpactMeshShapePart * >(shape0);
+ const btGImpactMeshShapePart * shapepart1 = static_cast<const btGImpactMeshShapePart * >(shape1);
//specialized function
#ifdef BULLET_TRIANGLE_COLLISION
- collide_gjk_triangles(body0,body1,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
+ collide_gjk_triangles(body0Wrap,body1Wrap,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
#else
- collide_sat_triangles(body0,body1,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
+ collide_sat_triangles(body0Wrap,body1Wrap,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
#endif
return;
@@ -548,55 +535,49 @@ void btGImpactCollisionAlgorithm::gimpact_vs_gimpact(
GIM_PAIR * pair = &pairset[i];
m_triface0 = pair->m_index1;
m_triface1 = pair->m_index2;
- btCollisionShape * colshape0 = retriever0.getChildShape(m_triface0);
- btCollisionShape * colshape1 = retriever1.getChildShape(m_triface1);
-
- if(child_has_transform0)
- {
- body0->setWorldTransform(orgtrans0*shape0->getChildTransform(m_triface0));
- }
-
- if(child_has_transform1)
- {
- body1->setWorldTransform(orgtrans1*shape1->getChildTransform(m_triface1));
- }
-
- //collide two convex shapes
- convex_vs_convex_collision(body0,body1,colshape0,colshape1);
+ const btCollisionShape * colshape0 = retriever0.getChildShape(m_triface0);
+ const btCollisionShape * colshape1 = retriever1.getChildShape(m_triface1);
+ btTransform tr0 = body0Wrap->getWorldTransform();
+ btTransform tr1 = body1Wrap->getWorldTransform();
if(child_has_transform0)
{
- body0->setWorldTransform(orgtrans0);
+ tr0 = orgtrans0*shape0->getChildTransform(m_triface0);
}
if(child_has_transform1)
{
- body1->setWorldTransform(orgtrans1);
+ tr1 = orgtrans1*shape1->getChildTransform(m_triface1);
}
+ btCollisionObjectWrapper ob0(body0Wrap,colshape0,body0Wrap->getCollisionObject(),tr0,m_part0,m_triface0);
+ btCollisionObjectWrapper ob1(body1Wrap,colshape1,body1Wrap->getCollisionObject(),tr1,m_part1,m_triface1);
+
+ //collide two convex shapes
+ convex_vs_convex_collision(&ob0,&ob1,colshape0,colshape1);
}
shape0->unlockChildShapes();
shape1->unlockChildShapes();
}
-void btGImpactCollisionAlgorithm::gimpact_vs_shape(btCollisionObject * body0,
- btCollisionObject * body1,
- btGImpactShapeInterface * shape0,
- btCollisionShape * shape1,bool swapped)
+void btGImpactCollisionAlgorithm::gimpact_vs_shape(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btGImpactShapeInterface * shape0,
+ const btCollisionShape * shape1,bool swapped)
{
if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
{
- btGImpactMeshShape * meshshape0 = static_cast<btGImpactMeshShape *>(shape0);
+ const btGImpactMeshShape * meshshape0 = static_cast<const btGImpactMeshShape *>(shape0);
int& part = swapped ? m_part1 : m_part0;
part = meshshape0->getMeshPartCount();
while(part--)
{
- gimpact_vs_shape(body0,
- body1,
+ gimpact_vs_shape(body0Wrap,
+ body1Wrap,
meshshape0->getMeshPart(part),
shape1,swapped);
@@ -609,9 +590,9 @@ void btGImpactCollisionAlgorithm::gimpact_vs_shape(btCollisionObject * body0,
if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
shape1->getShapeType() == STATIC_PLANE_PROXYTYPE)
{
- btGImpactMeshShapePart * shapepart = static_cast<btGImpactMeshShapePart *>(shape0);
- btStaticPlaneShape * planeshape = static_cast<btStaticPlaneShape * >(shape1);
- gimpacttrimeshpart_vs_plane_collision(body0,body1,shapepart,planeshape,swapped);
+ const btGImpactMeshShapePart * shapepart = static_cast<const btGImpactMeshShapePart *>(shape0);
+ const btStaticPlaneShape * planeshape = static_cast<const btStaticPlaneShape * >(shape1);
+ gimpacttrimeshpart_vs_plane_collision(body0Wrap,body1Wrap,shapepart,planeshape,swapped);
return;
}
@@ -621,21 +602,21 @@ void btGImpactCollisionAlgorithm::gimpact_vs_shape(btCollisionObject * body0,
if(shape1->isCompound())
{
- btCompoundShape * compoundshape = static_cast<btCompoundShape *>(shape1);
- gimpact_vs_compoundshape(body0,body1,shape0,compoundshape,swapped);
+ const btCompoundShape * compoundshape = static_cast<const btCompoundShape *>(shape1);
+ gimpact_vs_compoundshape(body0Wrap,body1Wrap,shape0,compoundshape,swapped);
return;
}
else if(shape1->isConcave())
{
- btConcaveShape * concaveshape = static_cast<btConcaveShape *>(shape1);
- gimpact_vs_concave(body0,body1,shape0,concaveshape,swapped);
+ const btConcaveShape * concaveshape = static_cast<const btConcaveShape *>(shape1);
+ gimpact_vs_concave(body0Wrap,body1Wrap,shape0,concaveshape,swapped);
return;
}
- btTransform orgtrans0 = body0->getWorldTransform();
+ btTransform orgtrans0 = body0Wrap->getWorldTransform();
- btTransform orgtrans1 = body1->getWorldTransform();
+ btTransform orgtrans1 = body1Wrap->getWorldTransform();
btAlignedObjectArray<int> collided_results;
@@ -662,28 +643,38 @@ void btGImpactCollisionAlgorithm::gimpact_vs_shape(btCollisionObject * body0,
else
m_triface0 = child_index;
- btCollisionShape * colshape0 = retriever0.getChildShape(child_index);
+ const btCollisionShape * colshape0 = retriever0.getChildShape(child_index);
+
+ btTransform tr0 = body0Wrap->getWorldTransform();
if(child_has_transform0)
{
- body0->setWorldTransform(orgtrans0*shape0->getChildTransform(child_index));
+ tr0 = orgtrans0*shape0->getChildTransform(child_index);
+ }
+
+ btCollisionObjectWrapper ob0(body0Wrap,colshape0,body0Wrap->getCollisionObject(),body0Wrap->getWorldTransform(),m_part0,m_triface0);
+ const btCollisionObjectWrapper* prevObj0 = m_resultOut->getBody0Wrap();
+
+ if (m_resultOut->getBody0Wrap()->getCollisionObject()==ob0.getCollisionObject())
+ {
+ m_resultOut->setBody0Wrap(&ob0);
+ } else
+ {
+ m_resultOut->setBody1Wrap(&ob0);
}
//collide two shapes
if(swapped)
{
- shape_vs_shape_collision(body1,body0,shape1,colshape0);
+
+ shape_vs_shape_collision(body1Wrap,&ob0,shape1,colshape0);
}
else
{
- shape_vs_shape_collision(body0,body1,colshape0,shape1);
- }
-
- //restore transforms
- if(child_has_transform0)
- {
- body0->setWorldTransform(orgtrans0);
+
+ shape_vs_shape_collision(&ob0,body1Wrap,colshape0,shape1);
}
+ m_resultOut->setBody0Wrap(prevObj0);
}
@@ -691,44 +682,58 @@ void btGImpactCollisionAlgorithm::gimpact_vs_shape(btCollisionObject * body0,
}
-void btGImpactCollisionAlgorithm::gimpact_vs_compoundshape(btCollisionObject * body0,
- btCollisionObject * body1,
- btGImpactShapeInterface * shape0,
- btCompoundShape * shape1,bool swapped)
+void btGImpactCollisionAlgorithm::gimpact_vs_compoundshape(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactShapeInterface * shape0,
+ const btCompoundShape * shape1,bool swapped)
{
- btTransform orgtrans1 = body1->getWorldTransform();
+ btTransform orgtrans1 = body1Wrap->getWorldTransform();
int i = shape1->getNumChildShapes();
while(i--)
{
- btCollisionShape * colshape1 = shape1->getChildShape(i);
+ const btCollisionShape * colshape1 = shape1->getChildShape(i);
btTransform childtrans1 = orgtrans1*shape1->getChildTransform(i);
- body1->setWorldTransform(childtrans1);
-
+ btCollisionObjectWrapper ob1(body1Wrap,colshape1,body1Wrap->getCollisionObject(),childtrans1,-1,i);
+
+ const btCollisionObjectWrapper* tmp = 0;
+ if (m_resultOut->getBody0Wrap()->getCollisionObject()==ob1.getCollisionObject())
+ {
+ tmp = m_resultOut->getBody0Wrap();
+ m_resultOut->setBody0Wrap(&ob1);
+ } else
+ {
+ tmp = m_resultOut->getBody1Wrap();
+ m_resultOut->setBody1Wrap(&ob1);
+ }
//collide child shape
- gimpact_vs_shape(body0, body1,
+ gimpact_vs_shape(body0Wrap, &ob1,
shape0,colshape1,swapped);
-
- //restore transforms
- body1->setWorldTransform(orgtrans1);
+ if (m_resultOut->getBody0Wrap()->getCollisionObject()==ob1.getCollisionObject())
+ {
+ m_resultOut->setBody0Wrap(tmp);
+ } else
+ {
+ m_resultOut->setBody1Wrap(tmp);
+ }
}
}
void btGImpactCollisionAlgorithm::gimpacttrimeshpart_vs_plane_collision(
- btCollisionObject * body0,
- btCollisionObject * body1,
- btGImpactMeshShapePart * shape0,
- btStaticPlaneShape * shape1,bool swapped)
+ const btCollisionObjectWrapper * body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btGImpactMeshShapePart * shape0,
+ const btStaticPlaneShape * shape1,bool swapped)
{
- btTransform orgtrans0 = body0->getWorldTransform();
- btTransform orgtrans1 = body1->getWorldTransform();
+ btTransform orgtrans0 = body0Wrap->getWorldTransform();
+ btTransform orgtrans1 = body1Wrap->getWorldTransform();
- btPlaneShape * planeshape = static_cast<btPlaneShape *>(shape1);
+ const btPlaneShape * planeshape = static_cast<const btPlaneShape *>(shape1);
btVector4 plane;
planeshape->get_plane_equation_transformed(orgtrans1,plane);
@@ -757,14 +762,14 @@ void btGImpactCollisionAlgorithm::gimpacttrimeshpart_vs_plane_collision(
{
if(swapped)
{
- addContactPoint(body1, body0,
+ addContactPoint(body1Wrap, body0Wrap,
vertex,
-plane,
distance);
}
else
{
- addContactPoint(body0, body1,
+ addContactPoint(body0Wrap, body1Wrap,
vertex,
plane,
distance);
@@ -782,9 +787,9 @@ class btGImpactTriangleCallback: public btTriangleCallback
{
public:
btGImpactCollisionAlgorithm * algorithm;
- btCollisionObject * body0;
- btCollisionObject * body1;
- btGImpactShapeInterface * gimpactshape0;
+ const btCollisionObjectWrapper * body0Wrap;
+ const btCollisionObjectWrapper * body1Wrap;
+ const btGImpactShapeInterface * gimpactshape0;
bool swapped;
btScalar margin;
@@ -802,8 +807,31 @@ public:
algorithm->setPart1(partId);
algorithm->setFace1(triangleIndex);
}
+
+ btCollisionObjectWrapper ob1Wrap(body1Wrap,&tri1,body1Wrap->getCollisionObject(),body1Wrap->getWorldTransform(),partId,triangleIndex);
+ const btCollisionObjectWrapper * tmp = 0;
+
+ if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject()==ob1Wrap.getCollisionObject())
+ {
+ tmp = algorithm->internalGetResultOut()->getBody0Wrap();
+ algorithm->internalGetResultOut()->setBody0Wrap(&ob1Wrap);
+ } else
+ {
+ tmp = algorithm->internalGetResultOut()->getBody1Wrap();
+ algorithm->internalGetResultOut()->setBody1Wrap(&ob1Wrap);
+ }
+
algorithm->gimpact_vs_shape(
- body0,body1,gimpactshape0,&tri1,swapped);
+ body0Wrap,&ob1Wrap,gimpactshape0,&tri1,swapped);
+
+ if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject()==ob1Wrap.getCollisionObject())
+ {
+ algorithm->internalGetResultOut()->setBody0Wrap(tmp);
+ } else
+ {
+ algorithm->internalGetResultOut()->setBody1Wrap(tmp);
+ }
+
}
};
@@ -811,16 +839,16 @@ public:
void btGImpactCollisionAlgorithm::gimpact_vs_concave(
- btCollisionObject * body0,
- btCollisionObject * body1,
- btGImpactShapeInterface * shape0,
- btConcaveShape * shape1,bool swapped)
+ const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btGImpactShapeInterface * shape0,
+ const btConcaveShape * shape1,bool swapped)
{
//create the callback
btGImpactTriangleCallback tricallback;
tricallback.algorithm = this;
- tricallback.body0 = body0;
- tricallback.body1 = body1;
+ tricallback.body0Wrap = body0Wrap;
+ tricallback.body1Wrap = body1Wrap;
tricallback.gimpactshape0 = shape0;
tricallback.swapped = swapped;
tricallback.margin = shape1->getMargin();
@@ -828,7 +856,7 @@ void btGImpactCollisionAlgorithm::gimpact_vs_concave(
//getting the trimesh AABB
btTransform gimpactInConcaveSpace;
- gimpactInConcaveSpace = body1->getWorldTransform().inverse() * body0->getWorldTransform();
+ gimpactInConcaveSpace = body1Wrap->getWorldTransform().inverse() * body0Wrap->getWorldTransform();
btVector3 minAABB,maxAABB;
shape0->getAabb(gimpactInConcaveSpace,minAABB,maxAABB);
@@ -839,36 +867,36 @@ void btGImpactCollisionAlgorithm::gimpact_vs_concave(
-void btGImpactCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btGImpactCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
clearCache();
m_resultOut = resultOut;
m_dispatchInfo = &dispatchInfo;
- btGImpactShapeInterface * gimpactshape0;
- btGImpactShapeInterface * gimpactshape1;
+ const btGImpactShapeInterface * gimpactshape0;
+ const btGImpactShapeInterface * gimpactshape1;
- if (body0->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE)
+ if (body0Wrap->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE)
{
- gimpactshape0 = static_cast<btGImpactShapeInterface *>(body0->getCollisionShape());
+ gimpactshape0 = static_cast<const btGImpactShapeInterface *>(body0Wrap->getCollisionShape());
- if( body1->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
+ if( body1Wrap->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
{
- gimpactshape1 = static_cast<btGImpactShapeInterface *>(body1->getCollisionShape());
+ gimpactshape1 = static_cast<const btGImpactShapeInterface *>(body1Wrap->getCollisionShape());
- gimpact_vs_gimpact(body0,body1,gimpactshape0,gimpactshape1);
+ gimpact_vs_gimpact(body0Wrap,body1Wrap,gimpactshape0,gimpactshape1);
}
else
{
- gimpact_vs_shape(body0,body1,gimpactshape0,body1->getCollisionShape(),false);
+ gimpact_vs_shape(body0Wrap,body1Wrap,gimpactshape0,body1Wrap->getCollisionShape(),false);
}
}
- else if (body1->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
+ else if (body1Wrap->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
{
- gimpactshape1 = static_cast<btGImpactShapeInterface *>(body1->getCollisionShape());
+ gimpactshape1 = static_cast<const btGImpactShapeInterface *>(body1Wrap->getCollisionShape());
- gimpact_vs_shape(body1,body0,gimpactshape1,body0->getCollisionShape(),true);
+ gimpact_vs_shape(body1Wrap,body0Wrap,gimpactshape1,body0Wrap->getCollisionShape(),true);
}
}
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h
index 6b6e07c983d..f85a94cb4c7 100644
--- a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h
+++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h
@@ -40,7 +40,7 @@ class btDispatcher;
#include "BulletCollision/CollisionShapes/btCompoundShape.h"
#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
#include "LinearMath/btIDebugDraw.h"
-
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
//! Collision Algorithm for GImpact Shapes
@@ -65,7 +65,7 @@ protected:
//! Creates a new contact point
- SIMD_FORCE_INLINE btPersistentManifold* newContactManifold(btCollisionObject* body0,btCollisionObject* body1)
+ SIMD_FORCE_INLINE btPersistentManifold* newContactManifold(const btCollisionObject* body0,const btCollisionObject* body1)
{
m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
return m_manifoldPtr;
@@ -106,38 +106,38 @@ protected:
// Call before process collision
- SIMD_FORCE_INLINE void checkManifold(btCollisionObject* body0,btCollisionObject* body1)
+ SIMD_FORCE_INLINE void checkManifold(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
if(getLastManifold() == 0)
{
- newContactManifold(body0,body1);
+ newContactManifold(body0Wrap->getCollisionObject(),body1Wrap->getCollisionObject());
}
m_resultOut->setPersistentManifold(getLastManifold());
}
// Call before process collision
- SIMD_FORCE_INLINE btCollisionAlgorithm * newAlgorithm(btCollisionObject* body0,btCollisionObject* body1)
+ SIMD_FORCE_INLINE btCollisionAlgorithm * newAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
- checkManifold(body0,body1);
+ checkManifold(body0Wrap,body1Wrap);
btCollisionAlgorithm * convex_algorithm = m_dispatcher->findAlgorithm(
- body0,body1,getLastManifold());
+ body0Wrap,body1Wrap,getLastManifold());
return convex_algorithm ;
}
// Call before process collision
- SIMD_FORCE_INLINE void checkConvexAlgorithm(btCollisionObject* body0,btCollisionObject* body1)
+ SIMD_FORCE_INLINE void checkConvexAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
if(m_convex_algorithm) return;
- m_convex_algorithm = newAlgorithm(body0,body1);
+ m_convex_algorithm = newAlgorithm(body0Wrap,body1Wrap);
}
- void addContactPoint(btCollisionObject * body0,
- btCollisionObject * body1,
+ void addContactPoint(const btCollisionObjectWrapper * body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
const btVector3 & point,
const btVector3 & normal,
btScalar distance);
@@ -145,62 +145,62 @@ protected:
//! Collision routines
//!@{
- void collide_gjk_triangles(btCollisionObject * body0,
- btCollisionObject * body1,
- btGImpactMeshShapePart * shape0,
- btGImpactMeshShapePart * shape1,
+ void collide_gjk_triangles(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactMeshShapePart * shape0,
+ const btGImpactMeshShapePart * shape1,
const int * pairs, int pair_count);
- void collide_sat_triangles(btCollisionObject * body0,
- btCollisionObject * body1,
- btGImpactMeshShapePart * shape0,
- btGImpactMeshShapePart * shape1,
+ void collide_sat_triangles(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactMeshShapePart * shape0,
+ const btGImpactMeshShapePart * shape1,
const int * pairs, int pair_count);
void shape_vs_shape_collision(
- btCollisionObject * body0,
- btCollisionObject * body1,
- btCollisionShape * shape0,
- btCollisionShape * shape1);
+ const btCollisionObjectWrapper* body0,
+ const btCollisionObjectWrapper* body1,
+ const btCollisionShape * shape0,
+ const btCollisionShape * shape1);
- void convex_vs_convex_collision(btCollisionObject * body0,
- btCollisionObject * body1,
- btCollisionShape * shape0,
- btCollisionShape * shape1);
+ void convex_vs_convex_collision(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btCollisionShape* shape0,
+ const btCollisionShape* shape1);
void gimpact_vs_gimpact_find_pairs(
const btTransform & trans0,
const btTransform & trans1,
- btGImpactShapeInterface * shape0,
- btGImpactShapeInterface * shape1,btPairSet & pairset);
+ const btGImpactShapeInterface * shape0,
+ const btGImpactShapeInterface * shape1,btPairSet & pairset);
void gimpact_vs_shape_find_pairs(
const btTransform & trans0,
const btTransform & trans1,
- btGImpactShapeInterface * shape0,
- btCollisionShape * shape1,
+ const btGImpactShapeInterface * shape0,
+ const btCollisionShape * shape1,
btAlignedObjectArray<int> & collided_primitives);
void gimpacttrimeshpart_vs_plane_collision(
- btCollisionObject * body0,
- btCollisionObject * body1,
- btGImpactMeshShapePart * shape0,
- btStaticPlaneShape * shape1,bool swapped);
+ const btCollisionObjectWrapper * body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btGImpactMeshShapePart * shape0,
+ const btStaticPlaneShape * shape1,bool swapped);
public:
- btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
+ btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
virtual ~btGImpactCollisionAlgorithm();
- virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
@@ -210,13 +210,17 @@ public:
manifoldArray.push_back(m_manifoldPtr);
}
+ btManifoldResult* internalGetResultOut()
+ {
+ return m_resultOut;
+ }
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btGImpactCollisionAlgorithm));
- return new(mem) btGImpactCollisionAlgorithm(ci,body0,body1);
+ return new(mem) btGImpactCollisionAlgorithm(ci,body0Wrap,body1Wrap);
}
};
@@ -236,26 +240,26 @@ public:
*/
- void gimpact_vs_gimpact(btCollisionObject * body0,
- btCollisionObject * body1,
- btGImpactShapeInterface * shape0,
- btGImpactShapeInterface * shape1);
+ void gimpact_vs_gimpact(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btGImpactShapeInterface * shape0,
+ const btGImpactShapeInterface * shape1);
- void gimpact_vs_shape(btCollisionObject * body0,
- btCollisionObject * body1,
- btGImpactShapeInterface * shape0,
- btCollisionShape * shape1,bool swapped);
+ void gimpact_vs_shape(const btCollisionObjectWrapper* body0Wrap,
+ const btCollisionObjectWrapper* body1Wrap,
+ const btGImpactShapeInterface * shape0,
+ const btCollisionShape * shape1,bool swapped);
- void gimpact_vs_compoundshape(btCollisionObject * body0,
- btCollisionObject * body1,
- btGImpactShapeInterface * shape0,
- btCompoundShape * shape1,bool swapped);
+ void gimpact_vs_compoundshape(const btCollisionObjectWrapper * body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btGImpactShapeInterface * shape0,
+ const btCompoundShape * shape1,bool swapped);
void gimpact_vs_concave(
- btCollisionObject * body0,
- btCollisionObject * body1,
- btGImpactShapeInterface * shape0,
- btConcaveShape * shape1,bool swapped);
+ const btCollisionObjectWrapper * body0Wrap,
+ const btCollisionObjectWrapper * body1Wrap,
+ const btGImpactShapeInterface * shape0,
+ const btConcaveShape * shape1,bool swapped);
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp
index cd4dfdb60e9..4528758c370 100644
--- a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp
+++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp
@@ -384,7 +384,7 @@ bool btGImpactQuantizedBvh::rayQuery(
SIMD_FORCE_INLINE bool _quantized_node_collision(
- btGImpactQuantizedBvh * boxset0, btGImpactQuantizedBvh * boxset1,
+ const btGImpactQuantizedBvh * boxset0, const btGImpactQuantizedBvh * boxset1,
const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
int node0 ,int node1, bool complete_primitive_tests)
{
@@ -402,7 +402,7 @@ SIMD_FORCE_INLINE bool _quantized_node_collision(
//stackless recursive collision routine
static void _find_quantized_collision_pairs_recursive(
- btGImpactQuantizedBvh * boxset0, btGImpactQuantizedBvh * boxset1,
+ const btGImpactQuantizedBvh * boxset0, const btGImpactQuantizedBvh * boxset1,
btPairSet * collision_pairs,
const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
int node0, int node1, bool complete_primitive_tests)
@@ -501,8 +501,8 @@ static void _find_quantized_collision_pairs_recursive(
}
-void btGImpactQuantizedBvh::find_collision(btGImpactQuantizedBvh * boxset0, const btTransform & trans0,
- btGImpactQuantizedBvh * boxset1, const btTransform & trans1,
+void btGImpactQuantizedBvh::find_collision(const btGImpactQuantizedBvh * boxset0, const btTransform & trans0,
+ const btGImpactQuantizedBvh * boxset1, const btTransform & trans1,
btPairSet & collision_pairs)
{
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h
index 9c990774739..e6e52fff4c0 100644
--- a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h
+++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h
@@ -363,8 +363,8 @@ public:
static float getAverageTreeCollisionTime();
#endif //TRI_COLLISION_PROFILING
- static void find_collision(btGImpactQuantizedBvh * boxset1, const btTransform & trans1,
- btGImpactQuantizedBvh * boxset2, const btTransform & trans2,
+ static void find_collision(const btGImpactQuantizedBvh * boxset1, const btTransform & trans1,
+ const btGImpactQuantizedBvh * boxset2, const btTransform & trans2,
btPairSet & collision_pairs);
};
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.cpp
index cceace55e4b..ac8efdf3833 100644
--- a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.cpp
+++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.cpp
@@ -25,6 +25,7 @@ subject to the following restrictions:
#define CALC_EXACT_INERTIA 1
+
void btGImpactCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
lockChildShapes();
@@ -144,6 +145,31 @@ void btGImpactMeshShape::rayTest(const btVector3& rayFrom, const btVector3& rayT
{
}
+void btGImpactMeshShapePart::processAllTrianglesRay(btTriangleCallback* callback,const btVector3& rayFrom, const btVector3& rayTo) const
+{
+ lockChildShapes();
+
+ btAlignedObjectArray<int> collided;
+ btVector3 rayDir(rayTo - rayFrom);
+ rayDir.normalize();
+ m_box_set.rayQuery(rayDir, rayFrom, collided);
+
+ if(collided.size()==0)
+ {
+ unlockChildShapes();
+ return;
+ }
+
+ int part = (int)getPart();
+ btPrimitiveTriangle triangle;
+ int i = collided.size();
+ while(i--)
+ {
+ getPrimitiveTriangle(collided[i],triangle);
+ callback->processTriangle(triangle.m_vertices,part,collided[i]);
+ }
+ unlockChildShapes();
+}
void btGImpactMeshShapePart::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
{
@@ -182,6 +208,15 @@ void btGImpactMeshShape::processAllTriangles(btTriangleCallback* callback,const
}
}
+void btGImpactMeshShape::processAllTrianglesRay(btTriangleCallback* callback,const btVector3& rayFrom, const btVector3& rayTo) const
+{
+ int i = m_mesh_parts.size();
+ while(i--)
+ {
+ m_mesh_parts[i]->processAllTrianglesRay(callback, rayFrom, rayTo);
+ }
+}
+
///fills the dataBuffer and returns the struct name (and 0 on failure)
const char* btGImpactMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.h b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.h
index 90015bb9ac0..3d1f48d4776 100644
--- a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.h
+++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.h
@@ -51,6 +51,7 @@ enum eGIMPACT_SHAPE_TYPE
};
+
//! Helper class for tetrahedrons
class btTetrahedronShapeEx:public btBU_Simplex1to4
{
@@ -192,7 +193,7 @@ public:
virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const = 0 ;
//! gets boxset
- SIMD_FORCE_INLINE btGImpactBoxSet * getBoxSet()
+ SIMD_FORCE_INLINE const btGImpactBoxSet * getBoxSet() const
{
return &m_box_set;
}
@@ -288,6 +289,15 @@ public:
(void) callback; (void) aabbMin; (void) aabbMax;
}
+ //! Function for retrieve triangles.
+ /*!
+ It gives the triangles in local space
+ */
+ virtual void processAllTrianglesRay(btTriangleCallback* /*callback*/,const btVector3& /*rayFrom*/, const btVector3& /*rayTo*/) const
+ {
+
+ }
+
//!@}
};
@@ -635,25 +645,25 @@ public:
return (int )numverts;
}
- SIMD_FORCE_INLINE void get_indices(int face_index,int &i0,int &i1,int &i2) const
+ SIMD_FORCE_INLINE void get_indices(int face_index,unsigned int &i0,unsigned int &i1,unsigned int &i2) const
{
if(indicestype == PHY_SHORT)
{
- short * s_indices = (short *)(indexbase + face_index*indexstride);
+ unsigned short* s_indices = (unsigned short *)(indexbase + face_index * indexstride);
i0 = s_indices[0];
i1 = s_indices[1];
i2 = s_indices[2];
}
else
{
- int * i_indices = (int *)(indexbase + face_index*indexstride);
+ unsigned int * i_indices = (unsigned int *)(indexbase + face_index*indexstride);
i0 = i_indices[0];
i1 = i_indices[1];
i2 = i_indices[2];
}
}
- SIMD_FORCE_INLINE void get_vertex(int vertex_index, btVector3 & vertex) const
+ SIMD_FORCE_INLINE void get_vertex(unsigned int vertex_index, btVector3 & vertex) const
{
if(type == PHY_DOUBLE)
{
@@ -682,7 +692,7 @@ public:
virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const
{
- int indices[3];
+ unsigned int indices[3];
get_indices(prim_index,indices[0],indices[1],indices[2]);
get_vertex(indices[0],triangle.m_vertices[0]);
get_vertex(indices[1],triangle.m_vertices[1]);
@@ -692,7 +702,7 @@ public:
SIMD_FORCE_INLINE void get_bullet_triangle(int prim_index,btTriangleShapeEx & triangle) const
{
- int indices[3];
+ unsigned int indices[3];
get_indices(prim_index,indices[0],indices[1],indices[2]);
get_vertex(indices[0],triangle.m_vertices1[0]);
get_vertex(indices[1],triangle.m_vertices1[1]);
@@ -885,6 +895,7 @@ public:
}
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+ virtual void processAllTrianglesRay(btTriangleCallback* callback,const btVector3& rayFrom,const btVector3& rayTo) const;
};
@@ -1141,6 +1152,8 @@ public:
*/
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+ virtual void processAllTrianglesRay (btTriangleCallback* callback,const btVector3& rayFrom,const btVector3& rayTo) const;
+
virtual int calculateSerializeBufferSize() const;
///fills the dataBuffer and returns the struct name (and 0 on failure)
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_array.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_array.h
index cfd5da8f49a..27e6f32fc8b 100644
--- a/extern/bullet2/src/BulletCollision/Gimpact/gim_array.h
+++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_array.h
@@ -285,18 +285,16 @@ public:
m_data[index] = obj;
}
- inline void resize(GUINT size, bool call_constructor = true)
+ inline void resize(GUINT size, bool call_constructor = true, const T& fillData=T())
{
-
if(size>m_size)
{
reserve(size);
if(call_constructor)
{
- T obj;
while(m_size<size)
{
- m_data[m_size] = obj;
+ m_data[m_size] = fillData;
m_size++;
}
}
diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_box_collision.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_box_collision.h
index b360dd47038..9c572638acd 100644
--- a/extern/bullet2/src/BulletCollision/Gimpact/gim_box_collision.h
+++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_box_collision.h
@@ -186,9 +186,7 @@ public:
SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point)
{
- return btVector3(m_R1to0[0].dot(point) + m_T1to0.x(),
- m_R1to0[1].dot(point) + m_T1to0.y(),
- m_R1to0[2].dot(point) + m_T1to0.z());
+ return point.dot3(m_R1to0[0], m_R1to0[1], m_R1to0[2]) + m_T1to0;
}
};
@@ -332,10 +330,10 @@ public:
// Compute new center
center = trans(center);
- btVector3 textends(extends.dot(trans.getBasis().getRow(0).absolute()),
- extends.dot(trans.getBasis().getRow(1).absolute()),
- extends.dot(trans.getBasis().getRow(2).absolute()));
-
+ btVector3 textends = extends.dot3(trans.getBasis().getRow(0).absolute(),
+ trans.getBasis().getRow(1).absolute(),
+ trans.getBasis().getRow(2).absolute());
+
m_min = center - textends;
m_max = center + textends;
}
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp
index 91fcea57a3c..940282f5762 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp
@@ -62,7 +62,6 @@ void btContinuousConvexCollision::computeClosestPoints( const btTransform& trans
const btConvexShape* convexShape = m_convexA;
const btStaticPlaneShape* planeShape = m_planeShape;
- bool hasCollision = false;
const btVector3& planeNormal = planeShape->getPlaneNormal();
const btScalar& planeConstant = planeShape->getPlaneConstant();
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
index 2277a19d981..f0043b8b9f2 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
@@ -63,12 +63,12 @@ public:
void getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw);
- void setMinkowskiA(btConvexShape* minkA)
+ void setMinkowskiA(const btConvexShape* minkA)
{
m_minkowskiA = minkA;
}
- void setMinkowskiB(btConvexShape* minkB)
+ void setMinkowskiB(const btConvexShape* minkB)
{
m_minkowskiB = minkB;
}
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
index 0ce9dd25926..e40fb1d3db6 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
@@ -44,9 +44,9 @@ class btManifoldPoint
public:
btManifoldPoint()
:m_userPersistentData(0),
- m_appliedImpulse(0.f),
m_lateralFrictionInitialized(false),
- m_appliedImpulseLateral1(0.f),
+ m_appliedImpulse(0.f),
+ m_appliedImpulseLateral1(0.f),
m_appliedImpulseLateral2(0.f),
m_contactMotion1(0.f),
m_contactMotion2(0.f),
@@ -64,11 +64,12 @@ class btManifoldPoint
m_normalWorldOnB( normal ),
m_distance1( distance ),
m_combinedFriction(btScalar(0.)),
+ m_combinedRollingFriction(btScalar(0.)),
m_combinedRestitution(btScalar(0.)),
m_userPersistentData(0),
- m_appliedImpulse(0.f),
m_lateralFrictionInitialized(false),
- m_appliedImpulseLateral1(0.f),
+ m_appliedImpulse(0.f),
+ m_appliedImpulseLateral1(0.f),
m_appliedImpulseLateral2(0.f),
m_contactMotion1(0.f),
m_contactMotion2(0.f),
@@ -76,9 +77,7 @@ class btManifoldPoint
m_contactCFM2(0.f),
m_lifeTime(0)
{
- mConstraintRow[0].m_accumImpulse = 0.f;
- mConstraintRow[1].m_accumImpulse = 0.f;
- mConstraintRow[2].m_accumImpulse = 0.f;
+
}
@@ -92,18 +91,19 @@ class btManifoldPoint
btScalar m_distance1;
btScalar m_combinedFriction;
+ btScalar m_combinedRollingFriction;
btScalar m_combinedRestitution;
- //BP mod, store contact triangles.
- int m_partId0;
- int m_partId1;
- int m_index0;
- int m_index1;
+ //BP mod, store contact triangles.
+ int m_partId0;
+ int m_partId1;
+ int m_index0;
+ int m_index1;
mutable void* m_userPersistentData;
- btScalar m_appliedImpulse;
-
bool m_lateralFrictionInitialized;
+
+ btScalar m_appliedImpulse;
btScalar m_appliedImpulseLateral1;
btScalar m_appliedImpulseLateral2;
btScalar m_contactMotion1;
@@ -118,8 +118,6 @@ class btManifoldPoint
- btConstraintRow mConstraintRow[3];
-
btScalar getDistance() const
{
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
index 954b8395299..4d92e853d3f 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
@@ -205,10 +205,13 @@ int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const
return nearestPoint;
}
-int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint)
+int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint, bool isPredictive)
{
- btAssert(validContactDistance(newPoint));
-
+ if (!isPredictive)
+ {
+ btAssert(validContactDistance(newPoint));
+ }
+
int insertIndex = getNumContacts();
if (insertIndex == MANIFOLD_CACHE_SIZE)
{
@@ -287,7 +290,7 @@ void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btT
{
//contact point processed callback
if (gContactProcessedCallback)
- (*gContactProcessedCallback)(manifoldPoint,m_body0,m_body1);
+ (*gContactProcessedCallback)(manifoldPoint,(void*)m_body0,(void*)m_body1);
}
}
}
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
index d877f09944f..2ceaab750fa 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
@@ -20,6 +20,7 @@ subject to the following restrictions:
#include "LinearMath/btVector3.h"
#include "LinearMath/btTransform.h"
#include "btManifoldPoint.h"
+class btCollisionObject;
#include "LinearMath/btAlignedAllocator.h"
struct btCollisionResult;
@@ -57,9 +58,8 @@ ATTRIBUTE_ALIGNED128( class) btPersistentManifold : public btTypedObject
btManifoldPoint m_pointCache[MANIFOLD_CACHE_SIZE];
/// this two body pointers can point to the physics rigidbody class.
- /// void* will allow any rigidbody class
- void* m_body0;
- void* m_body1;
+ const btCollisionObject* m_body0;
+ const btCollisionObject* m_body1;
int m_cachedPoints;
@@ -83,7 +83,7 @@ public:
btPersistentManifold();
- btPersistentManifold(void* body0,void* body1,int , btScalar contactBreakingThreshold,btScalar contactProcessingThreshold)
+ btPersistentManifold(const btCollisionObject* body0,const btCollisionObject* body1,int , btScalar contactBreakingThreshold,btScalar contactProcessingThreshold)
: btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
m_body0(body0),m_body1(body1),m_cachedPoints(0),
m_contactBreakingThreshold(contactBreakingThreshold),
@@ -91,13 +91,10 @@ public:
{
}
- SIMD_FORCE_INLINE void* getBody0() { return m_body0;}
- SIMD_FORCE_INLINE void* getBody1() { return m_body1;}
+ SIMD_FORCE_INLINE const btCollisionObject* getBody0() const { return m_body0;}
+ SIMD_FORCE_INLINE const btCollisionObject* getBody1() const { return m_body1;}
- SIMD_FORCE_INLINE const void* getBody0() const { return m_body0;}
- SIMD_FORCE_INLINE const void* getBody1() const { return m_body1;}
-
- void setBodies(void* body0,void* body1)
+ void setBodies(const btCollisionObject* body0,const btCollisionObject* body1)
{
m_body0 = body0;
m_body1 = body1;
@@ -110,6 +107,12 @@ public:
#endif //
SIMD_FORCE_INLINE int getNumContacts() const { return m_cachedPoints;}
+ /// the setNumContacts API is usually not used, except when you gather/fill all contacts manually
+ void setNumContacts(int cachedPoints)
+ {
+ m_cachedPoints = cachedPoints;
+ }
+
SIMD_FORCE_INLINE const btManifoldPoint& getContactPoint(int index) const
{
@@ -131,9 +134,22 @@ public:
return m_contactProcessingThreshold;
}
+ void setContactBreakingThreshold(btScalar contactBreakingThreshold)
+ {
+ m_contactBreakingThreshold = contactBreakingThreshold;
+ }
+
+ void setContactProcessingThreshold(btScalar contactProcessingThreshold)
+ {
+ m_contactProcessingThreshold = contactProcessingThreshold;
+ }
+
+
+
+
int getCacheEntry(const btManifoldPoint& newPoint) const;
- int addManifoldPoint( const btManifoldPoint& newPoint);
+ int addManifoldPoint( const btManifoldPoint& newPoint, bool isPredictive=false);
void removeContactPoint (int index)
{
@@ -146,10 +162,6 @@ public:
m_pointCache[index] = m_pointCache[lastUsedIndex];
//get rid of duplicated userPersistentData pointer
m_pointCache[lastUsedIndex].m_userPersistentData = 0;
- m_pointCache[lastUsedIndex].mConstraintRow[0].m_accumImpulse = 0.f;
- m_pointCache[lastUsedIndex].mConstraintRow[1].m_accumImpulse = 0.f;
- m_pointCache[lastUsedIndex].mConstraintRow[2].m_accumImpulse = 0.f;
-
m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f;
m_pointCache[lastUsedIndex].m_lateralFrictionInitialized = false;
m_pointCache[lastUsedIndex].m_appliedImpulseLateral1 = 0.f;
@@ -167,9 +179,9 @@ public:
#define MAINTAIN_PERSISTENCY 1
#ifdef MAINTAIN_PERSISTENCY
int lifeTime = m_pointCache[insertIndex].getLifeTime();
- btScalar appliedImpulse = m_pointCache[insertIndex].mConstraintRow[0].m_accumImpulse;
- btScalar appliedLateralImpulse1 = m_pointCache[insertIndex].mConstraintRow[1].m_accumImpulse;
- btScalar appliedLateralImpulse2 = m_pointCache[insertIndex].mConstraintRow[2].m_accumImpulse;
+ btScalar appliedImpulse = m_pointCache[insertIndex].m_appliedImpulse;
+ btScalar appliedLateralImpulse1 = m_pointCache[insertIndex].m_appliedImpulseLateral1;
+ btScalar appliedLateralImpulse2 = m_pointCache[insertIndex].m_appliedImpulseLateral2;
// bool isLateralFrictionInitialized = m_pointCache[insertIndex].m_lateralFrictionInitialized;
@@ -184,9 +196,9 @@ public:
m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1;
m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2;
- m_pointCache[insertIndex].mConstraintRow[0].m_accumImpulse = appliedImpulse;
- m_pointCache[insertIndex].mConstraintRow[1].m_accumImpulse = appliedLateralImpulse1;
- m_pointCache[insertIndex].mConstraintRow[2].m_accumImpulse = appliedLateralImpulse2;
+ m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse;
+ m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1;
+ m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2;
m_pointCache[insertIndex].m_lifeTime = lifeTime;
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp
index db1909113b3..b08205e84aa 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp
@@ -77,21 +77,36 @@ void btPolyhedralContactClipping::clipFace(const btVertexArray& pVtxIn, btVertex
}
-static bool TestSepAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btVector3& sep_axis, btScalar& depth)
+static bool TestSepAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btVector3& sep_axis, btScalar& depth, btVector3& witnessPointA, btVector3& witnessPointB)
{
btScalar Min0,Max0;
btScalar Min1,Max1;
- hullA.project(transA,sep_axis, Min0, Max0);
- hullB.project(transB, sep_axis, Min1, Max1);
+ btVector3 witnesPtMinA,witnesPtMaxA;
+ btVector3 witnesPtMinB,witnesPtMaxB;
+
+ hullA.project(transA,sep_axis, Min0, Max0,witnesPtMinA,witnesPtMaxA);
+ hullB.project(transB, sep_axis, Min1, Max1,witnesPtMinB,witnesPtMaxB);
if(Max0<Min1 || Max1<Min0)
return false;
btScalar d0 = Max0 - Min1;
- assert(d0>=0.0f);
+ btAssert(d0>=0.0f);
btScalar d1 = Max1 - Min0;
- assert(d1>=0.0f);
- depth = d0<d1 ? d0:d1;
+ btAssert(d1>=0.0f);
+ if (d0<d1)
+ {
+ depth = d0;
+ witnessPointA = witnesPtMaxA;
+ witnessPointB = witnesPtMinB;
+
+ } else
+ {
+ depth = d1;
+ witnessPointA = witnesPtMinA;
+ witnessPointB = witnesPtMaxB;
+ }
+
return true;
}
@@ -163,8 +178,66 @@ void InverseTransformPoint3x3(btVector3& out, const btVector3& in, const btTrans
}
#endif //TEST_INTERNAL_OBJECTS
+
+
+ SIMD_FORCE_INLINE void btSegmentsClosestPoints(
+ btVector3& ptsVector,
+ btVector3& offsetA,
+ btVector3& offsetB,
+ btScalar& tA, btScalar& tB,
+ const btVector3& translation,
+ const btVector3& dirA, btScalar hlenA,
+ const btVector3& dirB, btScalar hlenB )
+{
+ // compute the parameters of the closest points on each line segment
+
+ btScalar dirA_dot_dirB = btDot(dirA,dirB);
+ btScalar dirA_dot_trans = btDot(dirA,translation);
+ btScalar dirB_dot_trans = btDot(dirB,translation);
+
+ btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB;
+
+ if ( denom == 0.0f ) {
+ tA = 0.0f;
+ } else {
+ tA = ( dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB ) / denom;
+ if ( tA < -hlenA )
+ tA = -hlenA;
+ else if ( tA > hlenA )
+ tA = hlenA;
+ }
+
+ tB = tA * dirA_dot_dirB - dirB_dot_trans;
-bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep)
+ if ( tB < -hlenB ) {
+ tB = -hlenB;
+ tA = tB * dirA_dot_dirB + dirA_dot_trans;
+
+ if ( tA < -hlenA )
+ tA = -hlenA;
+ else if ( tA > hlenA )
+ tA = hlenA;
+ } else if ( tB > hlenB ) {
+ tB = hlenB;
+ tA = tB * dirA_dot_dirB + dirA_dot_trans;
+
+ if ( tA < -hlenA )
+ tA = -hlenA;
+ else if ( tA > hlenA )
+ tA = hlenA;
+ }
+
+ // compute the closest points relative to segment centers.
+
+ offsetA = dirA * tA;
+ offsetB = dirB * tB;
+
+ ptsVector = translation - offsetA + offsetB;
+}
+
+
+
+bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut)
{
gActualSATPairTests++;
@@ -182,9 +255,9 @@ bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron&
for(int i=0;i<numFacesA;i++)
{
const btVector3 Normal(hullA.m_faces[i].m_plane[0], hullA.m_faces[i].m_plane[1], hullA.m_faces[i].m_plane[2]);
- const btVector3 faceANormalWS = transA.getBasis() * Normal;
+ btVector3 faceANormalWS = transA.getBasis() * Normal;
if (DeltaC2.dot(faceANormalWS)<0)
- continue;
+ faceANormalWS*=-1.f;
curPlaneTests++;
#ifdef TEST_INTERNAL_OBJECTS
@@ -195,7 +268,8 @@ bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron&
#endif
btScalar d;
- if(!TestSepAxis( hullA, hullB, transA,transB, faceANormalWS, d))
+ btVector3 wA,wB;
+ if(!TestSepAxis( hullA, hullB, transA,transB, faceANormalWS, d,wA,wB))
return false;
if(d<dmin)
@@ -210,9 +284,9 @@ bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron&
for(int i=0;i<numFacesB;i++)
{
const btVector3 Normal(hullB.m_faces[i].m_plane[0], hullB.m_faces[i].m_plane[1], hullB.m_faces[i].m_plane[2]);
- const btVector3 WorldNormal = transB.getBasis() * Normal;
+ btVector3 WorldNormal = transB.getBasis() * Normal;
if (DeltaC2.dot(WorldNormal)<0)
- continue;
+ WorldNormal *=-1.f;
curPlaneTests++;
#ifdef TEST_INTERNAL_OBJECTS
@@ -223,7 +297,8 @@ bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron&
#endif
btScalar d;
- if(!TestSepAxis(hullA, hullB,transA,transB, WorldNormal,d))
+ btVector3 wA,wB;
+ if(!TestSepAxis(hullA, hullB,transA,transB, WorldNormal,d,wA,wB))
return false;
if(d<dmin)
@@ -234,6 +309,12 @@ bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron&
}
btVector3 edgeAstart,edgeAend,edgeBstart,edgeBend;
+ int edgeA=-1;
+ int edgeB=-1;
+ btVector3 worldEdgeA;
+ btVector3 worldEdgeB;
+ btVector3 witnessPointA,witnessPointB;
+
int curEdgeEdge = 0;
// Test edges
@@ -252,7 +333,7 @@ bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron&
{
Cross = Cross.normalize();
if (DeltaC2.dot(Cross)<0)
- continue;
+ Cross *= -1.f;
#ifdef TEST_INTERNAL_OBJECTS
@@ -263,21 +344,68 @@ bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron&
#endif
btScalar dist;
- if(!TestSepAxis( hullA, hullB, transA,transB, Cross, dist))
+ btVector3 wA,wB;
+ if(!TestSepAxis( hullA, hullB, transA,transB, Cross, dist,wA,wB))
return false;
if(dist<dmin)
{
dmin = dist;
sep = Cross;
+ edgeA=e0;
+ edgeB=e1;
+ worldEdgeA = WorldEdge0;
+ worldEdgeB = WorldEdge1;
+ witnessPointA=wA;
+ witnessPointB=wB;
}
}
}
}
- const btVector3 deltaC = transB.getOrigin() - transA.getOrigin();
- if((deltaC.dot(sep))>0.0f)
+ if (edgeA>=0&&edgeB>=0)
+ {
+// printf("edge-edge\n");
+ //add an edge-edge contact
+
+ btVector3 ptsVector;
+ btVector3 offsetA;
+ btVector3 offsetB;
+ btScalar tA;
+ btScalar tB;
+
+ btVector3 translation = witnessPointB-witnessPointA;
+
+ btVector3 dirA = worldEdgeA;
+ btVector3 dirB = worldEdgeB;
+
+ btScalar hlenB = 1e30f;
+ btScalar hlenA = 1e30f;
+
+ btSegmentsClosestPoints(ptsVector,offsetA,offsetB,tA,tB,
+ translation,
+ dirA, hlenA,
+ dirB,hlenB);
+
+ btScalar nlSqrt = ptsVector.length2();
+ if (nlSqrt>SIMD_EPSILON)
+ {
+ btScalar nl = btSqrt(nlSqrt);
+ ptsVector *= 1.f/nl;
+ if (ptsVector.dot(DeltaC2)<0.f)
+ {
+ ptsVector*=-1.f;
+ }
+ btVector3 ptOnB = witnessPointB + offsetB;
+ btScalar distance = nl;
+ resultOut.addContactPoint(ptsVector, ptOnB,-distance);
+ }
+
+ }
+
+
+ if((DeltaC2.dot(sep))<0.0f)
sep = -sep;
return true;
@@ -312,7 +440,6 @@ void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatin
const btFace& polyA = hullA.m_faces[closestFaceA];
// clip polygon to back of planes of all faces of hull A that are adjacent to witness face
- int numContacts = pVtxIn->size();
int numVerticesA = polyA.m_indices.size();
for(int e0=0;e0<numVerticesA;e0++)
{
@@ -361,8 +488,8 @@ void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatin
btScalar planeEqWS=localPlaneEq-planeNormalWS.dot(transA.getOrigin());
for (int i=0;i<pVtxIn->size();i++)
{
-
- btScalar depth = planeNormalWS.dot(pVtxIn->at(i))+planeEqWS;
+ btVector3 vtx = pVtxIn->at(i);
+ btScalar depth = planeNormalWS.dot(vtx)+planeEqWS;
if (depth <=minDist)
{
// printf("clamped: depth=%f to minDist=%f\n",depth,minDist);
@@ -397,16 +524,19 @@ void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatin
}
+
+
+
void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut)
{
btVector3 separatingNormal = separatingNormal1.normalized();
- const btVector3 c0 = transA * hullA.m_localCenter;
- const btVector3 c1 = transB * hullB.m_localCenter;
- const btVector3 DeltaC2 = c0 - c1;
+// const btVector3 c0 = transA * hullA.m_localCenter;
+// const btVector3 c1 = transB * hullB.m_localCenter;
+ //const btVector3 DeltaC2 = c0 - c1;
+
- btScalar curMaxDist=maxDist;
int closestFaceB=-1;
btScalar dmax = -FLT_MAX;
{
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h
index 99103df2027..b87bd4f3245 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h
@@ -35,7 +35,7 @@ struct btPolyhedralContactClipping
static void clipHullAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist, btDiscreteCollisionDetectorInterface::Result& resultOut);
static void clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut);
- static bool findSeparatingAxis( const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep);
+ static bool findSeparatingAxis( const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut);
///the clipFace method is used internally
static void clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS,btScalar planeEqWS);
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
index fbe579ce1e5..786efd18200 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
@@ -57,12 +57,13 @@ void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId,
{
return ; // same sign
}
- //@BP Mod - Backface filtering
- if (((m_flags & kF_FilterBackfaces) != 0) && (dist_a > btScalar(0.0)))
- {
- // Backface, skip check
- return;
- }
+
+ if (((m_flags & kF_FilterBackfaces) != 0) && (dist_a <= btScalar(0.0)))
+ {
+ // Backface, skip check
+ return;
+ }
+
const btScalar proj_length=dist_a-dist_b;
const btScalar distance = (dist_a)/(proj_length);
@@ -97,18 +98,18 @@ void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId,
if ( (btScalar)(cp2.dot(triangleNormal)) >=edge_tolerance)
{
- //@BP Mod
- // Triangle normal isn't normalized
+ //@BP Mod
+ // Triangle normal isn't normalized
triangleNormal.normalize();
- //@BP Mod - Allow for unflipped normal when raycasting against backfaces
- if (((m_flags & kF_KeepUnflippedNormal) != 0) || (dist_a <= btScalar(0.0)))
+ //@BP Mod - Allow for unflipped normal when raycasting against backfaces
+ if (((m_flags & kF_KeepUnflippedNormal) == 0) && (dist_a <= btScalar(0.0)))
{
m_hitFraction = reportHit(-triangleNormal,distance,partId,triangleIndex);
}
else
{
- m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex);
+ m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex);
}
}
}
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h
index f1c7613efa1..2f389e27e3f 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h
@@ -92,13 +92,15 @@ struct btSubSimplexClosestResult
/// btVoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points simplex to the origin.
/// Can be used with GJK, as an alternative to Johnson distance algorithm.
#ifdef NO_VIRTUAL_INTERFACE
-class btVoronoiSimplexSolver
+ATTRIBUTE_ALIGNED16(class) btVoronoiSimplexSolver
#else
-class btVoronoiSimplexSolver : public btSimplexSolverInterface
+ATTRIBUTE_ALIGNED16(class) btVoronoiSimplexSolver : public btSimplexSolverInterface
#endif
{
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
int m_numVertices;
btVector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS];
diff --git a/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp b/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp
index 5fd4ee28511..9db909a5469 100644
--- a/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp
+++ b/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp
@@ -79,7 +79,7 @@ public:
if (!convexResult.m_hitCollisionObject->hasContactResponse())
return btScalar(1.0);
-
+
btVector3 hitNormalWorld;
if (normalInWorldSpace)
{
@@ -163,7 +163,21 @@ btPairCachingGhostObject* btKinematicCharacterController::getGhostObject()
bool btKinematicCharacterController::recoverFromPenetration ( btCollisionWorld* collisionWorld)
{
-
+ // Here we must refresh the overlapping paircache as the penetrating movement itself or the
+ // previous recovery iteration might have used setWorldTransform and pushed us into an object
+ // that is not in the previous cache contents from the last timestep, as will happen if we
+ // are pushed into a new AABB overlap. Unhandled this means the next convex sweep gets stuck.
+ //
+ // Do this by calling the broadphase's setAabb with the moved AABB, this will update the broadphase
+ // paircache and the ghostobject's internal paircache at the same time. /BW
+
+ btVector3 minAabb, maxAabb;
+ m_convexShape->getAabb(m_ghostObject->getWorldTransform(), minAabb,maxAabb);
+ collisionWorld->getBroadphase()->setAabb(m_ghostObject->getBroadphaseHandle(),
+ minAabb,
+ maxAabb,
+ collisionWorld->getDispatcher());
+
bool penetration = false;
collisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher());
@@ -178,10 +192,10 @@ bool btKinematicCharacterController::recoverFromPenetration ( btCollisionWorld*
btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
btCollisionObject* obj0 = static_cast<btCollisionObject*>(collisionPair->m_pProxy0->m_clientObject);
btCollisionObject* obj1 = static_cast<btCollisionObject*>(collisionPair->m_pProxy1->m_clientObject);
-
+
if ((obj0 && !obj0->hasContactResponse()) || (obj1 && !obj1->hasContactResponse()))
continue;
-
+
if (collisionPair->m_algorithm)
collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray);
diff --git a/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.h b/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.h
index ef01f8a3e60..8ec63735cd8 100644
--- a/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.h
+++ b/extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.h
@@ -34,7 +34,7 @@ class btPairCachingGhostObject;
///btKinematicCharacterController is an object that supports a sliding motion in a world.
///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations.
///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
-class btKinematicCharacterController : public btCharacterControllerInterface
+ATTRIBUTE_ALIGNED16(class) btKinematicCharacterController : public btCharacterControllerInterface
{
protected:
@@ -92,6 +92,9 @@ protected:
void stepForwardAndStrafe (btCollisionWorld* collisionWorld, const btVector3& walkMove);
void stepDown (btCollisionWorld* collisionWorld, btScalar dt);
public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, int upAxis = 1);
~btKinematicCharacterController ();
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
index 755544f0dee..15a4c92de20 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
@@ -53,6 +53,7 @@ btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,const btTransform&
m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER)
{
m_rbBFrame = m_rbAFrame;
+ m_rbBFrame.setOrigin(btVector3(0., 0., 0.));
init();
}
@@ -136,6 +137,9 @@ void btConeTwistConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const bt
btVector3 a1neg = -a1;
a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
}
+ info->m_J2linearAxis[0] = -1;
+ info->m_J2linearAxis[info->rowskip+1] = -1;
+ info->m_J2linearAxis[2*info->rowskip+2] = -1;
btVector3 a2 = transB.getBasis() * m_rbBFrame.getOrigin();
{
btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
@@ -304,7 +308,7 @@ void btConeTwistConstraint::buildJacobian()
-void btConeTwistConstraint::solveConstraintObsolete(btRigidBody& bodyA,btRigidBody& bodyB,btScalar timeStep)
+void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep)
{
#ifndef __SPU__
if (m_useSolveConstraintObsolete)
@@ -506,7 +510,7 @@ void btConeTwistConstraint::solveConstraintObsolete(btRigidBody& bodyA,btRigidBo
m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0) );
impulseMag = m_accTwistLimitImpulse - temp;
- btVector3 impulse = m_twistAxis * impulseMag;
+ // btVector3 impulse = m_twistAxis * impulseMag;
bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*m_twistAxis,impulseMag);
bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*m_twistAxis,-impulseMag);
@@ -725,7 +729,8 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr
{
if(m_swingSpan1 < m_fixThresh)
{ // hinge around Y axis
- if(!(btFuzzyZero(y)))
+// if(!(btFuzzyZero(y)))
+ if((!(btFuzzyZero(x))) || (!(btFuzzyZero(z))))
{
m_solveSwingLimit = true;
if(m_swingSpan2 >= m_fixThresh)
@@ -747,7 +752,8 @@ void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTr
}
else
{ // hinge around Z axis
- if(!btFuzzyZero(z))
+// if(!btFuzzyZero(z))
+ if((!(btFuzzyZero(x))) || (!(btFuzzyZero(y))))
{
m_solveSwingLimit = true;
if(m_swingSpan1 >= m_fixThresh)
@@ -828,12 +834,11 @@ void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone,
{
vSwingAxis = btVector3(qCone.x(), qCone.y(), qCone.z());
vSwingAxis.normalize();
- if (fabs(vSwingAxis.x()) > SIMD_EPSILON)
- {
- // non-zero twist?! this should never happen.
- int wtf = 0; wtf = wtf;
- }
-
+#if 0
+ // non-zero twist?! this should never happen.
+ btAssert(fabs(vSwingAxis.x()) <= SIMD_EPSILON));
+#endif
+
// Compute limit for given swing. tricky:
// Given a swing axis, we're looking for the intersection with the bounding cone ellipse.
// (Since we're dealing with angles, this ellipse is embedded on the surface of a sphere.)
@@ -877,8 +882,10 @@ void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone,
else if (swingAngle < 0)
{
// this should never happen!
- int wtf = 0; wtf = wtf;
- }
+#if 0
+ btAssert(0);
+#endif
+ }
}
btVector3 btConeTwistConstraint::GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const
@@ -929,7 +936,9 @@ void btConeTwistConstraint::computeTwistLimitInfo(const btQuaternion& qTwist,
if (twistAngle < 0)
{
// this should never happen
- int wtf = 0; wtf = wtf;
+#if 0
+ btAssert(0);
+#endif
}
vTwistAxis = btVector3(qMinTwist.x(), qMinTwist.y(), qMinTwist.z());
@@ -976,10 +985,10 @@ void btConeTwistConstraint::setMotorTarget(const btQuaternion &q)
{
btTransform trACur = m_rbA.getCenterOfMassTransform();
btTransform trBCur = m_rbB.getCenterOfMassTransform();
- btTransform trABCur = trBCur.inverse() * trACur;
- btQuaternion qABCur = trABCur.getRotation();
- btTransform trConstraintCur = (trBCur * m_rbBFrame).inverse() * (trACur * m_rbAFrame);
- btQuaternion qConstraintCur = trConstraintCur.getRotation();
+// btTransform trABCur = trBCur.inverse() * trACur;
+// btQuaternion qABCur = trABCur.getRotation();
+// btTransform trConstraintCur = (trBCur * m_rbBFrame).inverse() * (trACur * m_rbAFrame);
+ //btQuaternion qConstraintCur = trConstraintCur.getRotation();
btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * q * m_rbAFrame.getRotation();
setMotorTargetInConstraintSpace(qConstraint);
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h
index 868e62f063e..09c048beda8 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h
@@ -50,7 +50,7 @@ enum btConeTwistFlags
};
///btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc)
-class btConeTwistConstraint : public btTypedConstraint
+ATTRIBUTE_ALIGNED16(class) btConeTwistConstraint : public btTypedConstraint
{
#ifdef IN_PARALLELL_SOLVER
public:
@@ -126,6 +126,8 @@ protected:
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,const btTransform& rbAFrame, const btTransform& rbBFrame);
btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame);
@@ -140,8 +142,9 @@ public:
void getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB);
- virtual void solveConstraintObsolete(btRigidBody& bodyA,btRigidBody& bodyB,btScalar timeStep);
+ virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep);
+
void updateRHS(btScalar timeStep);
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp
index 88859182925..9d60d9957a5 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp
@@ -70,7 +70,7 @@ void btContactConstraint::buildJacobian()
-//response between two dynamic objects without friction, assuming 0 penetration depth
+//response between two dynamic objects without friction and no restitution, assuming 0 penetration depth
btScalar resolveSingleCollision(
btRigidBody* body1,
btCollisionObject* colObj2,
@@ -93,7 +93,7 @@ btScalar resolveSingleCollision(
btScalar rel_vel;
rel_vel = normal.dot(vel);
- btScalar combinedRestitution = body1->getRestitution() * colObj2->getRestitution();
+ btScalar combinedRestitution = 0.f;
btScalar restitution = combinedRestitution* -rel_vel;
btScalar positionalError = solverInfo.m_erp *-distance /solverInfo.m_timeStep ;
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
index 6204cb3d16c..c07e9bbd806 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
@@ -16,18 +16,20 @@ subject to the following restrictions:
#ifndef BT_CONTACT_SOLVER_INFO
#define BT_CONTACT_SOLVER_INFO
+#include "LinearMath/btScalar.h"
+
enum btSolverMode
{
SOLVER_RANDMIZE_ORDER = 1,
SOLVER_FRICTION_SEPARATE = 2,
SOLVER_USE_WARMSTARTING = 4,
- SOLVER_USE_FRICTION_WARMSTARTING = 8,
SOLVER_USE_2_FRICTION_DIRECTIONS = 16,
SOLVER_ENABLE_FRICTION_DIRECTION_CACHING = 32,
SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION = 64,
SOLVER_CACHE_FRIENDLY = 128,
- SOLVER_SIMD = 256, //enabled for Windows, the solver innerloop is branchless SIMD, 40% faster than FPU/scalar version
- SOLVER_CUDA = 512 //will be open sourced during Game Developers Conference 2009. Much faster.
+ SOLVER_SIMD = 256,
+ SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS = 512,
+ SOLVER_ALLOW_ZERO_LENGTH_FRICTION_DIRECTIONS = 1024
};
struct btContactSolverInfoData
@@ -47,12 +49,15 @@ struct btContactSolverInfoData
btScalar m_globalCfm;//constraint force mixing
int m_splitImpulse;
btScalar m_splitImpulsePenetrationThreshold;
+ btScalar m_splitImpulseTurnErp;
btScalar m_linearSlop;
btScalar m_warmstartingFactor;
int m_solverMode;
int m_restingContactRestitutionThreshold;
int m_minimumSolverBatchSize;
+ btScalar m_maxGyroscopicForce;
+ btScalar m_singleAxisRollingFrictionThreshold;
};
@@ -67,21 +72,88 @@ struct btContactSolverInfo : public btContactSolverInfoData
m_tau = btScalar(0.6);
m_damping = btScalar(1.0);
m_friction = btScalar(0.3);
+ m_timeStep = btScalar(1.f/60.f);
m_restitution = btScalar(0.);
m_maxErrorReduction = btScalar(20.);
m_numIterations = 10;
m_erp = btScalar(0.2);
- m_erp2 = btScalar(0.1);
+ m_erp2 = btScalar(0.8);
m_globalCfm = btScalar(0.);
m_sor = btScalar(1.);
- m_splitImpulse = false;
- m_splitImpulsePenetrationThreshold = -0.02f;
+ m_splitImpulse = true;
+ m_splitImpulsePenetrationThreshold = -.04f;
+ m_splitImpulseTurnErp = 0.1f;
m_linearSlop = btScalar(0.0);
m_warmstartingFactor=btScalar(0.85);
+ //m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD | SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION|SOLVER_USE_2_FRICTION_DIRECTIONS|SOLVER_ENABLE_FRICTION_DIRECTION_CACHING;// | SOLVER_RANDMIZE_ORDER;
m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD;// | SOLVER_RANDMIZE_ORDER;
- m_restingContactRestitutionThreshold = 2;//resting contact lifetime threshold to disable restitution
+ m_restingContactRestitutionThreshold = 2;//unused as of 2.81
m_minimumSolverBatchSize = 128; //try to combine islands until the amount of constraints reaches this limit
+ m_maxGyroscopicForce = 100.f; ///only used to clamp forces for bodies that have their BT_ENABLE_GYROPSCOPIC_FORCE flag set (using btRigidBody::setFlag)
+ m_singleAxisRollingFrictionThreshold = 1e30f;///if the velocity is above this threshold, it will use a single constraint row (axis), otherwise 3 rows.
}
};
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btContactSolverInfoDoubleData
+{
+ double m_tau;
+ double m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+ double m_friction;
+ double m_timeStep;
+ double m_restitution;
+ double m_maxErrorReduction;
+ double m_sor;
+ double m_erp;//used as Baumgarte factor
+ double m_erp2;//used in Split Impulse
+ double m_globalCfm;//constraint force mixing
+ double m_splitImpulsePenetrationThreshold;
+ double m_splitImpulseTurnErp;
+ double m_linearSlop;
+ double m_warmstartingFactor;
+ double m_maxGyroscopicForce;
+ double m_singleAxisRollingFrictionThreshold;
+
+ int m_numIterations;
+ int m_solverMode;
+ int m_restingContactRestitutionThreshold;
+ int m_minimumSolverBatchSize;
+ int m_splitImpulse;
+ char m_padding[4];
+
+};
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btContactSolverInfoFloatData
+{
+ float m_tau;
+ float m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+ float m_friction;
+ float m_timeStep;
+
+ float m_restitution;
+ float m_maxErrorReduction;
+ float m_sor;
+ float m_erp;//used as Baumgarte factor
+
+ float m_erp2;//used in Split Impulse
+ float m_globalCfm;//constraint force mixing
+ float m_splitImpulsePenetrationThreshold;
+ float m_splitImpulseTurnErp;
+
+ float m_linearSlop;
+ float m_warmstartingFactor;
+ float m_maxGyroscopicForce;
+ float m_singleAxisRollingFrictionThreshold;
+
+ int m_numIterations;
+ int m_solverMode;
+ int m_restingContactRestitutionThreshold;
+ int m_minimumSolverBatchSize;
+
+ int m_splitImpulse;
+ char m_padding[4];
+};
+
+
+
#endif //BT_CONTACT_SOLVER_INFO
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp
new file mode 100644
index 00000000000..bcd457b6731
--- /dev/null
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGearConstraint.cpp
@@ -0,0 +1,54 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2012 Advanced Micro Devices, Inc. http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/// Implemented by Erwin Coumans. The idea for the constraint comes from Dimitris Papavasiliou.
+
+#include "btGearConstraint.h"
+
+btGearConstraint::btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA,const btVector3& axisInB, btScalar ratio)
+:btTypedConstraint(GEAR_CONSTRAINT_TYPE,rbA,rbB),
+m_axisInA(axisInA),
+m_axisInB(axisInB),
+m_ratio(ratio)
+{
+}
+
+btGearConstraint::~btGearConstraint ()
+{
+}
+
+void btGearConstraint::getInfo1 (btConstraintInfo1* info)
+{
+ info->m_numConstraintRows = 1;
+ info->nub = 1;
+}
+
+void btGearConstraint::getInfo2 (btConstraintInfo2* info)
+{
+ btVector3 globalAxisA, globalAxisB;
+
+ globalAxisA = m_rbA.getWorldTransform().getBasis()*this->m_axisInA;
+ globalAxisB = m_rbB.getWorldTransform().getBasis()*this->m_axisInB;
+
+ info->m_J1angularAxis[0] = globalAxisA[0];
+ info->m_J1angularAxis[1] = globalAxisA[1];
+ info->m_J1angularAxis[2] = globalAxisA[2];
+
+ info->m_J2angularAxis[0] = m_ratio*globalAxisB[0];
+ info->m_J2angularAxis[1] = m_ratio*globalAxisB[1];
+ info->m_J2angularAxis[2] = m_ratio*globalAxisB[2];
+
+}
+
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGearConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGearConstraint.h
new file mode 100644
index 00000000000..60f60094843
--- /dev/null
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGearConstraint.h
@@ -0,0 +1,56 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2012 Advanced Micro Devices, Inc. http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_GEAR_CONSTRAINT_H
+#define BT_GEAR_CONSTRAINT_H
+
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+///The btGeatConstraint will couple the angular velocity for two bodies around given local axis and ratio.
+///See Bullet/Demos/ConstraintDemo for an example use.
+class btGearConstraint : public btTypedConstraint
+{
+protected:
+ btVector3 m_axisInA;
+ btVector3 m_axisInB;
+ bool m_useFrameA;
+ btScalar m_ratio;
+
+public:
+ btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA,const btVector3& axisInB, btScalar ratio=1.f);
+ virtual ~btGearConstraint ();
+
+ ///internal method used by the constraint solver, don't use them directly
+ virtual void getInfo1 (btConstraintInfo1* info);
+
+ ///internal method used by the constraint solver, don't use them directly
+ virtual void getInfo2 (btConstraintInfo2* info);
+
+ virtual void setParam(int num, btScalar value, int axis = -1)
+ {
+ btAssert(0);
+ };
+
+ ///return the local value of parameter
+ virtual btScalar getParam(int num, int axis = -1) const
+ {
+ btAssert(0);
+ return 0.f;
+ }
+
+};
+
+#endif //BT_GEAR_CONSTRAINT_H
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp
index 8ff9940bba3..bc2b5a85df9 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp
@@ -174,10 +174,8 @@ btScalar btRotationalLimitMotor::solveAngularLimits(
// current velocity difference
- btVector3 angVelA;
- body0->internalGetAngularVelocity(angVelA);
- btVector3 angVelB;
- body1->internalGetAngularVelocity(angVelB);
+ btVector3 angVelA = body0->getAngularVelocity();
+ btVector3 angVelB = body1->getAngularVelocity();
btVector3 vel_diff;
vel_diff = angVelA-angVelB;
@@ -225,12 +223,8 @@ btScalar btRotationalLimitMotor::solveAngularLimits(
btVector3 motorImp = clippedMotorImpulse * axis;
- //body0->applyTorqueImpulse(motorImp);
- //body1->applyTorqueImpulse(-motorImp);
-
- body0->internalApplyImpulse(btVector3(0,0,0), body0->getInvInertiaTensorWorld()*axis,clippedMotorImpulse);
- body1->internalApplyImpulse(btVector3(0,0,0), body1->getInvInertiaTensorWorld()*axis,-clippedMotorImpulse);
-
+ body0->applyTorqueImpulse(motorImp);
+ body1->applyTorqueImpulse(-motorImp);
return clippedMotorImpulse;
@@ -292,10 +286,8 @@ btScalar btTranslationalLimitMotor::solveLinearAxis(
btVector3 rel_pos1 = anchorPos - body1.getCenterOfMassPosition();
btVector3 rel_pos2 = anchorPos - body2.getCenterOfMassPosition();
- btVector3 vel1;
- body1.internalGetVelocityInLocalPointObsolete(rel_pos1,vel1);
- btVector3 vel2;
- body2.internalGetVelocityInLocalPointObsolete(rel_pos2,vel2);
+ btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
+ btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
btVector3 vel = vel1 - vel2;
btScalar rel_vel = axis_normal_on_a.dot(vel);
@@ -348,16 +340,10 @@ btScalar btTranslationalLimitMotor::solveLinearAxis(
normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse;
btVector3 impulse_vector = axis_normal_on_a * normalImpulse;
- //body1.applyImpulse( impulse_vector, rel_pos1);
- //body2.applyImpulse(-impulse_vector, rel_pos2);
-
- btVector3 ftorqueAxis1 = rel_pos1.cross(axis_normal_on_a);
- btVector3 ftorqueAxis2 = rel_pos2.cross(axis_normal_on_a);
- body1.internalApplyImpulse(axis_normal_on_a*body1.getInvMass(), body1.getInvInertiaTensorWorld()*ftorqueAxis1,normalImpulse);
- body2.internalApplyImpulse(axis_normal_on_a*body2.getInvMass(), body2.getInvInertiaTensorWorld()*ftorqueAxis2,-normalImpulse);
-
-
+ body1.applyImpulse( impulse_vector, rel_pos1);
+ body2.applyImpulse(-impulse_vector, rel_pos2);
+
return normalImpulse;
}
@@ -795,17 +781,16 @@ int btGeneric6DofConstraint::get_limit_motor_info2(
if (powered || limit)
{ // if the joint is powered, or has joint limits, add in the extra row
btScalar *J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis;
- btScalar *J2 = rotational ? info->m_J2angularAxis : 0;
+ btScalar *J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis;
J1[srow+0] = ax1[0];
J1[srow+1] = ax1[1];
J1[srow+2] = ax1[2];
- if(rotational)
- {
- J2[srow+0] = -ax1[0];
- J2[srow+1] = -ax1[1];
- J2[srow+2] = -ax1[2];
- }
- if((!rotational))
+
+ J2[srow+0] = -ax1[0];
+ J2[srow+1] = -ax1[1];
+ J2[srow+2] = -ax1[2];
+
+ if((!rotational))
{
if (m_useOffsetForConstraintFrame)
{
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h
index a8e7bc22902..0409f95379b 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h
@@ -268,7 +268,7 @@ This brings support for limit parameters and motors. </li>
</ul>
*/
-class btGeneric6DofConstraint : public btTypedConstraint
+ATTRIBUTE_ALIGNED16(class) btGeneric6DofConstraint : public btTypedConstraint
{
protected:
@@ -346,6 +346,8 @@ protected:
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
///for backwards compatibility during the transition to 'getInfo/getInfo2'
bool m_useSolveConstraintObsolete;
@@ -354,7 +356,7 @@ public:
//! Calcs global transform of the offsets
/*!
- Calcs the global transform for the joint offset for body A an B, and also calcs the angle differences between the bodies.
+ Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies.
\sa btGeneric6DofConstraint.getCalculatedTransformA , btGeneric6DofConstraint.getCalculatedTransformB, btGeneric6DofConstraint.calculateAngleInfo
*/
void calculateTransforms(const btTransform& transA,const btTransform& transB);
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp
index 2b38714987b..6f765884ec0 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp
@@ -118,7 +118,7 @@ void btGeneric6DofSpringConstraint::internalUpdateSprings(btConstraintInfo2* inf
{
// it is assumed that calculateTransforms() have been called before this call
int i;
- btVector3 relVel = m_rbB.getLinearVelocity() - m_rbA.getLinearVelocity();
+ //btVector3 relVel = m_rbB.getLinearVelocity() - m_rbA.getLinearVelocity();
for(i = 0; i < 3; i++)
{
if(m_springEnabled[i])
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h
index 31e0cd531ae..6fabb30369b 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h
@@ -32,7 +32,7 @@ subject to the following restrictions:
/// 4 : rotation Y (2nd Euler rotational around new position of Y axis, range [-PI/2+epsilon, PI/2-epsilon] )
/// 5 : rotation Z (1st Euler rotational around Z axis, range [-PI+epsilon, PI-epsilon] )
-class btGeneric6DofSpringConstraint : public btGeneric6DofConstraint
+ATTRIBUTE_ALIGNED16(class) btGeneric6DofSpringConstraint : public btGeneric6DofConstraint
{
protected:
bool m_springEnabled[6];
@@ -42,6 +42,9 @@ protected:
void init();
void internalUpdateSprings(btConstraintInfo2* info);
public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
btGeneric6DofSpringConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB);
void enableSpring(int index, bool onOff);
@@ -87,12 +90,12 @@ SIMD_FORCE_INLINE const char* btGeneric6DofSpringConstraint::serialize(void* dat
int i;
for (i=0;i<6;i++)
{
- dof->m_equilibriumPoint[i] = m_equilibriumPoint[i];
- dof->m_springDamping[i] = m_springDamping[i];
+ dof->m_equilibriumPoint[i] = (float)m_equilibriumPoint[i];
+ dof->m_springDamping[i] = (float)m_springDamping[i];
dof->m_springEnabled[i] = m_springEnabled[i]? 1 : 0;
- dof->m_springStiffness[i] = m_springStiffness[i];
+ dof->m_springStiffness[i] = (float)m_springStiffness[i];
}
- return "btGeneric6DofConstraintData";
+ return "btGeneric6DofSpringConstraintData";
}
#endif // BT_GENERIC_6DOF_SPRING_CONSTRAINT_H
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h
index a76452ddb64..9a004986911 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h
@@ -29,13 +29,15 @@ subject to the following restrictions:
// 2 rotational degrees of freedom, similar to Euler rotations around Z (axis 1) and X (axis 2)
// 1 translational (along axis Z) with suspension spring
-class btHinge2Constraint : public btGeneric6DofSpringConstraint
+ATTRIBUTE_ALIGNED16(class) btHinge2Constraint : public btGeneric6DofSpringConstraint
{
protected:
btVector3 m_anchor;
btVector3 m_axis1;
btVector3 m_axis2;
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
// constructor
// anchor, axis1 and axis2 are in world coordinate system
// axis1 must be orthogonal to axis2
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp
index 9e3a2baeed9..c1897413078 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp
@@ -369,6 +369,10 @@ void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransf
info->m_J1angularAxis[i*skip+1]=0;
info->m_J1angularAxis[i*skip+2]=0;
+ info->m_J2linearAxis[i*skip]=0;
+ info->m_J2linearAxis[i*skip+1]=0;
+ info->m_J2linearAxis[i*skip+2]=0;
+
info->m_J2angularAxis[i*skip]=0;
info->m_J2angularAxis[i*skip+1]=0;
info->m_J2angularAxis[i*skip+2]=0;
@@ -384,6 +388,10 @@ void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransf
info->m_J1linearAxis[0] = 1;
info->m_J1linearAxis[skip + 1] = 1;
info->m_J1linearAxis[2 * skip + 2] = 1;
+
+ info->m_J2linearAxis[0] = -1;
+ info->m_J2linearAxis[skip + 1] = -1;
+ info->m_J2linearAxis[2 * skip + 2] = -1;
}
@@ -702,8 +710,8 @@ void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info
btTransform trA = transA*m_rbAFrame;
btTransform trB = transB*m_rbBFrame;
// pivot point
- btVector3 pivotAInW = trA.getOrigin();
- btVector3 pivotBInW = trB.getOrigin();
+// btVector3 pivotAInW = trA.getOrigin();
+// btVector3 pivotBInW = trB.getOrigin();
#if 1
// difference between frames in WCS
btVector3 ofs = trB.getOrigin() - trA.getOrigin();
@@ -797,7 +805,11 @@ void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info
for (i=0; i<3; i++) info->m_J1linearAxis[s0+i] = p[i];
for (i=0; i<3; i++) info->m_J1linearAxis[s1+i] = q[i];
for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = ax1[i];
-
+
+ for (i=0; i<3; i++) info->m_J2linearAxis[s0+i] = -p[i];
+ for (i=0; i<3; i++) info->m_J2linearAxis[s1+i] = -q[i];
+ for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -ax1[i];
+
// compute three elements of right hand side
btScalar rhs = k * p.dot(ofs);
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h
index cb2973e1d1d..a7f2cca5500 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h
@@ -100,6 +100,8 @@ public:
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA = false);
btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA = false);
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h
index f1994a2dfd8..125580d1998 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h
@@ -16,8 +16,7 @@ subject to the following restrictions:
#ifndef BT_JACOBIAN_ENTRY_H
#define BT_JACOBIAN_ENTRY_H
-#include "LinearMath/btVector3.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btMatrix3x3.h"
//notes:
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp
index 7e0d93b9765..3c0430b903f 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp
@@ -116,15 +116,14 @@ void btPoint2PointConstraint::getInfo2NonVirtual (btConstraintInfo2* info, const
a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
}
- /*info->m_J2linearAxis[0] = -1;
- info->m_J2linearAxis[s+1] = -1;
- info->m_J2linearAxis[2*s+2] = -1;
- */
+ info->m_J2linearAxis[0] = -1;
+ info->m_J2linearAxis[info->rowskip+1] = -1;
+ info->m_J2linearAxis[2*info->rowskip+2] = -1;
btVector3 a2 = body1_trans.getBasis()*getPivotInB();
{
- btVector3 a2n = -a2;
+ // btVector3 a2n = -a2;
btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip);
btVector3* angular2 = (btVector3*)(info->m_J2angularAxis+2*info->rowskip);
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h
index b3bda03eec1..1e13416dfeb 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h
@@ -67,6 +67,8 @@ public:
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
///for backwards compatibility during the transition to 'getInfo/getInfo2'
bool m_useSolveConstraintObsolete;
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
index ab074224028..0ccadea7ab8 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
@@ -14,28 +14,29 @@ subject to the following restrictions:
*/
//#define COMPUTE_IMPULSE_DENOM 1
+//#define BT_ADDITIONAL_DEBUG
+
//It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms.
#include "btSequentialImpulseConstraintSolver.h"
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "btContactConstraint.h"
-#include "btSolve2LinearConstraint.h"
-#include "btContactSolverInfo.h"
+
#include "LinearMath/btIDebugDraw.h"
-#include "btJacobianEntry.h"
+//#include "btJacobianEntry.h"
#include "LinearMath/btMinMax.h"
#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
#include <new>
#include "LinearMath/btStackAlloc.h"
#include "LinearMath/btQuickprof.h"
-#include "btSolverBody.h"
-#include "btSolverConstraint.h"
+//#include "btSolverBody.h"
+//#include "btSolverConstraint.h"
#include "LinearMath/btAlignedObjectArray.h"
#include <string.h> //for memset
int gNumSplitImpulseRecoveries = 0;
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+
btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver()
:m_btSeed2(0)
{
@@ -57,15 +58,15 @@ static inline __m128 btSimdDot3( __m128 vec0, __m128 vec1 )
#endif//USE_SIMD
// Project Gauss Seidel or the equivalent Sequential Impulse
-void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c)
+void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
{
#ifdef USE_SIMD
__m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
__m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
__m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
__m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse),_mm_set1_ps(c.m_cfm)));
- __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal.mVec128,body1.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetDeltaAngularVelocity().mVec128));
- __m128 deltaVel2Dotn = _mm_sub_ps(btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetDeltaAngularVelocity().mVec128),btSimdDot3((c.m_contactNormal).mVec128,body2.internalGetDeltaLinearVelocity().mVec128));
+ __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128,body1.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetDeltaAngularVelocity().mVec128));
+ __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128,body2.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetDeltaAngularVelocity().mVec128));
deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse);
@@ -78,12 +79,12 @@ void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(
__m128 upperMinApplied = _mm_sub_ps(upperLimit1,cpAppliedImp);
deltaImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied) );
c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1) );
- __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128);
- __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128);
+ __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128,body1.internalGetInvMass().mVec128);
+ __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal2).mVec128,body2.internalGetInvMass().mVec128);
__m128 impulseMagnitude = deltaImpulse;
body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude));
body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude));
- body2.internalGetDeltaLinearVelocity().mVec128 = _mm_sub_ps(body2.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
+ body2.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
#else
resolveSingleConstraintRowGeneric(body1,body2,c);
@@ -91,11 +92,11 @@ void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(
}
// Project Gauss Seidel or the equivalent Sequential Impulse
- void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c)
+ void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
{
btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm;
- const btScalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
- const btScalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
+ const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
+ const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
// const btScalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn;
deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
@@ -116,19 +117,20 @@ void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(
{
c.m_appliedImpulse = sum;
}
- body1.internalApplyImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
- body2.internalApplyImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
+
+ body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
+ body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
}
- void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c)
+ void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
{
#ifdef USE_SIMD
__m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
__m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
__m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
__m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse),_mm_set1_ps(c.m_cfm)));
- __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal.mVec128,body1.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetDeltaAngularVelocity().mVec128));
- __m128 deltaVel2Dotn = _mm_sub_ps(btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetDeltaAngularVelocity().mVec128),btSimdDot3((c.m_contactNormal).mVec128,body2.internalGetDeltaLinearVelocity().mVec128));
+ __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128,body1.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetDeltaAngularVelocity().mVec128));
+ __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128,body2.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetDeltaAngularVelocity().mVec128));
deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse);
@@ -138,12 +140,12 @@ void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(
__m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp);
deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) );
c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) );
- __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128);
- __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128);
+ __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128,body1.internalGetInvMass().mVec128);
+ __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128,body2.internalGetInvMass().mVec128);
__m128 impulseMagnitude = deltaImpulse;
body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude));
body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude));
- body2.internalGetDeltaLinearVelocity().mVec128 = _mm_sub_ps(body2.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
+ body2.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
#else
resolveSingleConstraintRowLowerLimit(body1,body2,c);
@@ -151,11 +153,11 @@ void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(
}
// Project Gauss Seidel or the equivalent Sequential Impulse
- void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c)
+ void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
{
btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm;
- const btScalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
- const btScalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
+ const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
+ const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
@@ -169,22 +171,22 @@ void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(
{
c.m_appliedImpulse = sum;
}
- body1.internalApplyImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
- body2.internalApplyImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
+ body1.internalApplyImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
+ body2.internalApplyImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
}
void btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFriendly(
- btRigidBody& body1,
- btRigidBody& body2,
+ btSolverBody& body1,
+ btSolverBody& body2,
const btSolverConstraint& c)
{
if (c.m_rhsPenetration)
{
gNumSplitImpulseRecoveries++;
btScalar deltaImpulse = c.m_rhsPenetration-btScalar(c.m_appliedPushImpulse)*c.m_cfm;
- const btScalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetTurnVelocity());
- const btScalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetTurnVelocity());
+ const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(body1.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetTurnVelocity());
+ const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(body2.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetTurnVelocity());
deltaImpulse -= deltaVel1Dotn*c.m_jacDiagABInv;
deltaImpulse -= deltaVel2Dotn*c.m_jacDiagABInv;
@@ -198,12 +200,12 @@ void btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFri
{
c.m_appliedPushImpulse = sum;
}
- body1.internalApplyPushImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
- body2.internalApplyPushImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
+ body1.internalApplyPushImpulse(c.m_contactNormal1*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
+ body2.internalApplyPushImpulse(c.m_contactNormal2*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
}
}
- void btSequentialImpulseConstraintSolver::resolveSplitPenetrationSIMD(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c)
+ void btSequentialImpulseConstraintSolver::resolveSplitPenetrationSIMD(btSolverBody& body1,btSolverBody& body2,const btSolverConstraint& c)
{
#ifdef USE_SIMD
if (!c.m_rhsPenetration)
@@ -215,8 +217,8 @@ void btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFri
__m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
__m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
__m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhsPenetration), _mm_mul_ps(_mm_set1_ps(c.m_appliedPushImpulse),_mm_set1_ps(c.m_cfm)));
- __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal.mVec128,body1.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetTurnVelocity().mVec128));
- __m128 deltaVel2Dotn = _mm_sub_ps(btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetTurnVelocity().mVec128),btSimdDot3((c.m_contactNormal).mVec128,body2.internalGetPushVelocity().mVec128));
+ __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128,body1.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetTurnVelocity().mVec128));
+ __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128,body2.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetTurnVelocity().mVec128));
deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
deltaImpulse = _mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse);
@@ -226,12 +228,12 @@ void btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFri
__m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp);
deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) );
c.m_appliedPushImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) );
- __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128);
- __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128);
+ __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128,body1.internalGetInvMass().mVec128);
+ __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128,body2.internalGetInvMass().mVec128);
__m128 impulseMagnitude = deltaImpulse;
body1.internalGetPushVelocity().mVec128 = _mm_add_ps(body1.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude));
body1.internalGetTurnVelocity().mVec128 = _mm_add_ps(body1.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude));
- body2.internalGetPushVelocity().mVec128 = _mm_sub_ps(body2.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
+ body2.internalGetPushVelocity().mVec128 = _mm_add_ps(body2.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
body2.internalGetTurnVelocity().mVec128 = _mm_add_ps(body2.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
#else
resolveSplitPenetrationImpulseCacheFriendly(body1,body2,c);
@@ -277,9 +279,10 @@ int btSequentialImpulseConstraintSolver::btRandInt2 (int n)
}
-#if 0
+
void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject)
{
+
btRigidBody* rb = collisionObject? btRigidBody::upcast(collisionObject) : 0;
solverBody->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
@@ -289,17 +292,27 @@ void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBod
if (rb)
{
- solverBody->internalGetInvMass() = btVector3(rb->getInvMass(),rb->getInvMass(),rb->getInvMass())*rb->getLinearFactor();
+ solverBody->m_worldTransform = rb->getWorldTransform();
+ solverBody->internalSetInvMass(btVector3(rb->getInvMass(),rb->getInvMass(),rb->getInvMass())*rb->getLinearFactor());
solverBody->m_originalBody = rb;
solverBody->m_angularFactor = rb->getAngularFactor();
+ solverBody->m_linearFactor = rb->getLinearFactor();
+ solverBody->m_linearVelocity = rb->getLinearVelocity();
+ solverBody->m_angularVelocity = rb->getAngularVelocity();
} else
{
- solverBody->internalGetInvMass().setValue(0,0,0);
+ solverBody->m_worldTransform.setIdentity();
+ solverBody->internalSetInvMass(btVector3(0,0,0));
solverBody->m_originalBody = 0;
solverBody->m_angularFactor.setValue(1,1,1);
+ solverBody->m_linearFactor.setValue(1,1,1);
+ solverBody->m_linearVelocity.setValue(0,0,0);
+ solverBody->m_angularVelocity.setValue(0,0,0);
}
+
+
}
-#endif
+
@@ -313,10 +326,12 @@ btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel,
-void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection);
-void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection)
+static void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection, int frictionMode);
+static void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection, int frictionMode)
{
- if (colObj && colObj->hasAnisotropicFriction())
+
+
+ if (colObj && colObj->hasAnisotropicFriction(frictionMode))
{
// transform to local coordinates
btVector3 loc_lateral = frictionDirection * colObj->getWorldTransform().getBasis();
@@ -326,20 +341,26 @@ void applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirec
// ... and transform it back to global coordinates
frictionDirection = colObj->getWorldTransform().getBasis() * loc_lateral;
}
+
}
-void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis,btRigidBody* solverBodyA,btRigidBody* solverBodyB,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
-{
- btRigidBody* body0=btRigidBody::upcast(colObj0);
- btRigidBody* body1=btRigidBody::upcast(colObj1);
+void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
+{
+
+
+ solverConstraint.m_contactNormal1 = normalAxis;
+ solverConstraint.m_contactNormal2 = -normalAxis;
+ btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
- solverConstraint.m_contactNormal = normalAxis;
+ btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody;
+ btRigidBody* body1 = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody;
- solverConstraint.m_solverBodyA = body0 ? body0 : &getFixedBody();
- solverConstraint.m_solverBodyB = body1 ? body1 : &getFixedBody();
+ solverConstraint.m_solverBodyIdA = solverBodyIdA;
+ solverConstraint.m_solverBodyIdB = solverBodyIdB;
solverConstraint.m_friction = cp.m_combinedFriction;
solverConstraint.m_originalContactPoint = 0;
@@ -348,55 +369,122 @@ void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstr
solverConstraint.m_appliedPushImpulse = 0.f;
{
- btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal);
+ btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal1);
solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld()*ftorqueAxis1*body0->getAngularFactor() : btVector3(0,0,0);
}
{
- btVector3 ftorqueAxis1 = rel_pos2.cross(-solverConstraint.m_contactNormal);
+ btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal2);
solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
solverConstraint.m_angularComponentB = body1 ? body1->getInvInertiaTensorWorld()*ftorqueAxis1*body1->getAngularFactor() : btVector3(0,0,0);
}
-#ifdef COMPUTE_IMPULSE_DENOM
- btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal);
- btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal);
-#else
- btVector3 vec;
- btScalar denom0 = 0.f;
- btScalar denom1 = 0.f;
- if (body0)
{
- vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
- denom0 = body0->getInvMass() + normalAxis.dot(vec);
+ btVector3 vec;
+ btScalar denom0 = 0.f;
+ btScalar denom1 = 0.f;
+ if (body0)
+ {
+ vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
+ denom0 = body0->getInvMass() + normalAxis.dot(vec);
+ }
+ if (body1)
+ {
+ vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
+ denom1 = body1->getInvMass() + normalAxis.dot(vec);
+ }
+ btScalar denom = relaxation/(denom0+denom1);
+ solverConstraint.m_jacDiagABInv = denom;
}
- if (body1)
+
{
- vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
- denom1 = body1->getInvMass() + normalAxis.dot(vec);
+
+
+ btScalar rel_vel;
+ btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0?solverBodyA.m_linearVelocity:btVector3(0,0,0))
+ + solverConstraint.m_relpos1CrossNormal.dot(body0?solverBodyA.m_angularVelocity:btVector3(0,0,0));
+ btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(body1?solverBodyB.m_linearVelocity:btVector3(0,0,0))
+ + solverConstraint.m_relpos2CrossNormal.dot(body1?solverBodyB.m_angularVelocity:btVector3(0,0,0));
+
+ rel_vel = vel1Dotn+vel2Dotn;
+
+// btScalar positionalError = 0.f;
+
+ btSimdScalar velocityError = desiredVelocity - rel_vel;
+ btSimdScalar velocityImpulse = velocityError * btSimdScalar(solverConstraint.m_jacDiagABInv);
+ solverConstraint.m_rhs = velocityImpulse;
+ solverConstraint.m_cfm = cfmSlip;
+ solverConstraint.m_lowerLimit = 0;
+ solverConstraint.m_upperLimit = 1e10f;
+
}
+}
+btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
+{
+ btSolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing();
+ solverConstraint.m_frictionIndex = frictionIndex;
+ setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
+ colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
+ return solverConstraint;
+}
-#endif //COMPUTE_IMPULSE_DENOM
- btScalar denom = relaxation/(denom0+denom1);
- solverConstraint.m_jacDiagABInv = denom;
-#ifdef _USE_JACOBIAN
- solverConstraint.m_jac = btJacobianEntry (
- rel_pos1,rel_pos2,solverConstraint.m_contactNormal,
- body0->getInvInertiaDiagLocal(),
- body0->getInvMass(),
- body1->getInvInertiaDiagLocal(),
- body1->getInvMass());
-#endif //_USE_JACOBIAN
+void btSequentialImpulseConstraintSolver::setupRollingFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis1,int solverBodyIdA,int solverBodyIdB,
+ btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,
+ btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation,
+ btScalar desiredVelocity, btScalar cfmSlip)
+{
+ btVector3 normalAxis(0,0,0);
+
+
+ solverConstraint.m_contactNormal1 = normalAxis;
+ solverConstraint.m_contactNormal2 = -normalAxis;
+ btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
+
+ btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody;
+ btRigidBody* body1 = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody;
+
+ solverConstraint.m_solverBodyIdA = solverBodyIdA;
+ solverConstraint.m_solverBodyIdB = solverBodyIdB;
+
+ solverConstraint.m_friction = cp.m_combinedRollingFriction;
+ solverConstraint.m_originalContactPoint = 0;
+
+ solverConstraint.m_appliedImpulse = 0.f;
+ solverConstraint.m_appliedPushImpulse = 0.f;
+
+ {
+ btVector3 ftorqueAxis1 = -normalAxis1;
+ solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
+ solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld()*ftorqueAxis1*body0->getAngularFactor() : btVector3(0,0,0);
+ }
+ {
+ btVector3 ftorqueAxis1 = normalAxis1;
+ solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
+ solverConstraint.m_angularComponentB = body1 ? body1->getInvInertiaTensorWorld()*ftorqueAxis1*body1->getAngularFactor() : btVector3(0,0,0);
+ }
+
+
+ {
+ btVector3 iMJaA = body0?body0->getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal:btVector3(0,0,0);
+ btVector3 iMJaB = body1?body1->getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal:btVector3(0,0,0);
+ btScalar sum = 0;
+ sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
+ sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
+ solverConstraint.m_jacDiagABInv = btScalar(1.)/sum;
+ }
{
+
+
btScalar rel_vel;
- btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(body0?body0->getLinearVelocity():btVector3(0,0,0))
- + solverConstraint.m_relpos1CrossNormal.dot(body0?body0->getAngularVelocity():btVector3(0,0,0));
- btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(body1?body1->getLinearVelocity():btVector3(0,0,0))
- + solverConstraint.m_relpos2CrossNormal.dot(body1?body1->getAngularVelocity():btVector3(0,0,0));
+ btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0?solverBodyA.m_linearVelocity:btVector3(0,0,0))
+ + solverConstraint.m_relpos1CrossNormal.dot(body0?solverBodyA.m_angularVelocity:btVector3(0,0,0));
+ btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(body1?solverBodyB.m_linearVelocity:btVector3(0,0,0))
+ + solverConstraint.m_relpos2CrossNormal.dot(body1?solverBodyB.m_angularVelocity:btVector3(0,0,0));
rel_vel = vel1Dotn+vel2Dotn;
@@ -408,33 +496,42 @@ void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstr
solverConstraint.m_cfm = cfmSlip;
solverConstraint.m_lowerLimit = 0;
solverConstraint.m_upperLimit = 1e10f;
+
}
}
-btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis,btRigidBody* solverBodyA,btRigidBody* solverBodyB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
+
+
+
+
+
+btSolverConstraint& btSequentialImpulseConstraintSolver::addRollingFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
{
- btSolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing();
+ btSolverConstraint& solverConstraint = m_tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing();
solverConstraint.m_frictionIndex = frictionIndex;
- setupFrictionConstraint(solverConstraint, normalAxis, solverBodyA, solverBodyB, cp, rel_pos1, rel_pos2,
+ setupRollingFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
return solverConstraint;
}
+
int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body)
{
-#if 0
+
int solverBodyIdA = -1;
if (body.getCompanionId() >= 0)
{
//body has already been converted
solverBodyIdA = body.getCompanionId();
+ btAssert(solverBodyIdA < m_tmpSolverBodyPool.size());
} else
{
btRigidBody* rb = btRigidBody::upcast(&body);
- if (rb && rb->getInvMass())
+ //convert both active and kinematic objects (for their velocity)
+ if (rb && (rb->getInvMass() || rb->isKinematicObject()))
{
solverBodyIdA = m_tmpSolverBodyPool.size();
btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
@@ -445,29 +542,33 @@ int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject&
return 0;//assume first one is a fixed solver body
}
}
+
return solverBodyIdA;
-#endif
- return 0;
+
}
#include <stdio.h>
void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstraint& solverConstraint,
- btCollisionObject* colObj0, btCollisionObject* colObj1,
+ int solverBodyIdA, int solverBodyIdB,
btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
btVector3& vel, btScalar& rel_vel, btScalar& relaxation,
btVector3& rel_pos1, btVector3& rel_pos2)
{
- btRigidBody* rb0 = btRigidBody::upcast(colObj0);
- btRigidBody* rb1 = btRigidBody::upcast(colObj1);
-
+
const btVector3& pos1 = cp.getPositionWorldOnA();
const btVector3& pos2 = cp.getPositionWorldOnB();
+ btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+
+ btRigidBody* rb0 = bodyA->m_originalBody;
+ btRigidBody* rb1 = bodyB->m_originalBody;
+
// btVector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
// btVector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
- rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
- rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
+ rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
+ rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
relaxation = 1.f;
@@ -500,30 +601,29 @@ void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstra
solverConstraint.m_jacDiagABInv = denom;
}
- solverConstraint.m_contactNormal = cp.m_normalWorldOnB;
- solverConstraint.m_relpos1CrossNormal = rel_pos1.cross(cp.m_normalWorldOnB);
- solverConstraint.m_relpos2CrossNormal = rel_pos2.cross(-cp.m_normalWorldOnB);
-
+ solverConstraint.m_contactNormal1 = cp.m_normalWorldOnB;
+ solverConstraint.m_contactNormal2 = -cp.m_normalWorldOnB;
+ solverConstraint.m_relpos1CrossNormal = torqueAxis0;
+ solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
+ btScalar restitution = 0.f;
+ btScalar penetration = cp.getDistance()+infoGlobal.m_linearSlop;
+ {
+ btVector3 vel1,vel2;
- btVector3 vel1 = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0);
- btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
- vel = vel1 - vel2;
- rel_vel = cp.m_normalWorldOnB.dot(vel);
+ vel1 = rb0? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0);
+ vel2 = rb1? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
- btScalar penetration = cp.getDistance()+infoGlobal.m_linearSlop;
+ // btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
+ vel = vel1 - vel2;
+ rel_vel = cp.m_normalWorldOnB.dot(vel);
+
- solverConstraint.m_friction = cp.m_combinedFriction;
+ solverConstraint.m_friction = cp.m_combinedFriction;
- btScalar restitution = 0.f;
- if (cp.m_lifeTime>infoGlobal.m_restingContactRestitutionThreshold)
- {
- restitution = 0.f;
- } else
- {
restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution);
if (restitution <= btScalar(0.))
{
@@ -537,9 +637,9 @@ void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstra
{
solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
if (rb0)
- rb0->internalApplyImpulse(solverConstraint.m_contactNormal*rb0->getInvMass()*rb0->getLinearFactor(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse);
+ bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1*bodyA->internalGetInvMass()*rb0->getLinearFactor(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse);
if (rb1)
- rb1->internalApplyImpulse(solverConstraint.m_contactNormal*rb1->getInvMass()*rb1->getLinearFactor(),-solverConstraint.m_angularComponentB,-(btScalar)solverConstraint.m_appliedImpulse);
+ bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2*bodyB->internalGetInvMass()*rb1->getLinearFactor(),-solverConstraint.m_angularComponentB,-(btScalar)solverConstraint.m_appliedImpulse);
} else
{
solverConstraint.m_appliedImpulse = 0.f;
@@ -548,33 +648,41 @@ void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstra
solverConstraint.m_appliedPushImpulse = 0.f;
{
- btScalar rel_vel;
- btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(rb0?rb0->getLinearVelocity():btVector3(0,0,0))
- + solverConstraint.m_relpos1CrossNormal.dot(rb0?rb0->getAngularVelocity():btVector3(0,0,0));
- btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rb1?rb1->getLinearVelocity():btVector3(0,0,0))
- + solverConstraint.m_relpos2CrossNormal.dot(rb1?rb1->getAngularVelocity():btVector3(0,0,0));
-
- rel_vel = vel1Dotn+vel2Dotn;
+ btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(rb0?bodyA->m_linearVelocity:btVector3(0,0,0))
+ + solverConstraint.m_relpos1CrossNormal.dot(rb0?bodyA->m_angularVelocity:btVector3(0,0,0));
+ btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(rb1?bodyB->m_linearVelocity:btVector3(0,0,0))
+ + solverConstraint.m_relpos2CrossNormal.dot(rb1?bodyB->m_angularVelocity:btVector3(0,0,0));
+ btScalar rel_vel = vel1Dotn+vel2Dotn;
btScalar positionalError = 0.f;
btScalar velocityError = restitution - rel_vel;// * damping;
+
+
+ btScalar erp = infoGlobal.m_erp2;
+ if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+ {
+ erp = infoGlobal.m_erp;
+ }
if (penetration>0)
{
positionalError = 0;
+
velocityError -= penetration / infoGlobal.m_timeStep;
} else
{
- positionalError = -penetration * infoGlobal.m_erp/infoGlobal.m_timeStep;
+ positionalError = -penetration * erp/infoGlobal.m_timeStep;
}
btScalar penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
+
if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
{
//combine position and velocity into rhs
solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
solverConstraint.m_rhsPenetration = 0.f;
+
} else
{
//split position and velocity into rhs and m_rhsPenetration
@@ -594,51 +702,46 @@ void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstra
void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse( btSolverConstraint& solverConstraint,
- btRigidBody* rb0, btRigidBody* rb1,
+ int solverBodyIdA, int solverBodyIdB,
btManifoldPoint& cp, const btContactSolverInfo& infoGlobal)
{
- if (infoGlobal.m_solverMode & SOLVER_USE_FRICTION_WARMSTARTING)
- {
- {
- btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor;
- if (rb0)
- rb0->internalApplyImpulse(frictionConstraint1.m_contactNormal*rb0->getInvMass()*rb0->getLinearFactor(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse);
- if (rb1)
- rb1->internalApplyImpulse(frictionConstraint1.m_contactNormal*rb1->getInvMass()*rb1->getLinearFactor(),-frictionConstraint1.m_angularComponentB,-(btScalar)frictionConstraint1.m_appliedImpulse);
- } else
- {
- frictionConstraint1.m_appliedImpulse = 0.f;
- }
- }
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex+1];
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor;
- if (rb0)
- rb0->internalApplyImpulse(frictionConstraint2.m_contactNormal*rb0->getInvMass(),frictionConstraint2.m_angularComponentA,frictionConstraint2.m_appliedImpulse);
- if (rb1)
- rb1->internalApplyImpulse(frictionConstraint2.m_contactNormal*rb1->getInvMass(),-frictionConstraint2.m_angularComponentB,-(btScalar)frictionConstraint2.m_appliedImpulse);
- } else
- {
- frictionConstraint2.m_appliedImpulse = 0.f;
- }
- }
- } else
- {
- btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
- frictionConstraint1.m_appliedImpulse = 0.f;
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex+1];
- frictionConstraint2.m_appliedImpulse = 0.f;
- }
- }
+ btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+
+ btRigidBody* rb0 = bodyA->m_originalBody;
+ btRigidBody* rb1 = bodyB->m_originalBody;
+
+ {
+ btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
+ if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+ {
+ frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor;
+ if (rb0)
+ bodyA->internalApplyImpulse(frictionConstraint1.m_contactNormal1*rb0->getInvMass()*rb0->getLinearFactor(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse);
+ if (rb1)
+ bodyB->internalApplyImpulse(-frictionConstraint1.m_contactNormal2*rb1->getInvMass()*rb1->getLinearFactor(),-frictionConstraint1.m_angularComponentB,-(btScalar)frictionConstraint1.m_appliedImpulse);
+ } else
+ {
+ frictionConstraint1.m_appliedImpulse = 0.f;
+ }
+ }
+
+ if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+ {
+ btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex+1];
+ if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+ {
+ frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor;
+ if (rb0)
+ bodyA->internalApplyImpulse(frictionConstraint2.m_contactNormal1*rb0->getInvMass(),frictionConstraint2.m_angularComponentA,frictionConstraint2.m_appliedImpulse);
+ if (rb1)
+ bodyB->internalApplyImpulse(-frictionConstraint2.m_contactNormal2*rb1->getInvMass(),-frictionConstraint2.m_angularComponentB,-(btScalar)frictionConstraint2.m_appliedImpulse);
+ } else
+ {
+ frictionConstraint2.m_appliedImpulse = 0.f;
+ }
+ }
}
@@ -651,14 +754,22 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
colObj0 = (btCollisionObject*)manifold->getBody0();
colObj1 = (btCollisionObject*)manifold->getBody1();
+ int solverBodyIdA = getOrInitSolverBody(*colObj0);
+ int solverBodyIdB = getOrInitSolverBody(*colObj1);
+
+// btRigidBody* bodyA = btRigidBody::upcast(colObj0);
+// btRigidBody* bodyB = btRigidBody::upcast(colObj1);
+
+ btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
+
- btRigidBody* solverBodyA = btRigidBody::upcast(colObj0);
- btRigidBody* solverBodyB = btRigidBody::upcast(colObj1);
///avoid collision response between two static objects
- if ((!solverBodyA || !solverBodyA->getInvMass()) && (!solverBodyB || !solverBodyB->getInvMass()))
+ if (!solverBodyA || (!solverBodyA->m_originalBody && (!solverBodyB || !solverBodyB->m_originalBody)))
return;
+ int rollingFriction=1;
for (int j=0;j<manifold->getNumContacts();j++)
{
@@ -674,13 +785,14 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
int frictionIndex = m_tmpSolverContactConstraintPool.size();
btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing();
- btRigidBody* rb0 = btRigidBody::upcast(colObj0);
- btRigidBody* rb1 = btRigidBody::upcast(colObj1);
- solverConstraint.m_solverBodyA = rb0? rb0 : &getFixedBody();
- solverConstraint.m_solverBodyB = rb1? rb1 : &getFixedBody();
+// btRigidBody* rb0 = btRigidBody::upcast(colObj0);
+// btRigidBody* rb1 = btRigidBody::upcast(colObj1);
+ solverConstraint.m_solverBodyIdA = solverBodyIdA;
+ solverConstraint.m_solverBodyIdB = solverBodyIdB;
+
solverConstraint.m_originalContactPoint = &cp;
- setupContactConstraint(solverConstraint, colObj0, colObj1, cp, infoGlobal, vel, rel_vel, relaxation, rel_pos1, rel_pos2);
+ setupContactConstraint(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, vel, rel_vel, relaxation, rel_pos1, rel_pos2);
// const btVector3& pos1 = cp.getPositionWorldOnA();
// const btVector3& pos2 = cp.getPositionWorldOnB();
@@ -689,52 +801,109 @@ void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* m
solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size();
+ btVector3 angVelA,angVelB;
+ solverBodyA->getAngularVelocity(angVelA);
+ solverBodyB->getAngularVelocity(angVelB);
+ btVector3 relAngVel = angVelB-angVelA;
+
+ if ((cp.m_combinedRollingFriction>0.f) && (rollingFriction>0))
+ {
+ //only a single rollingFriction per manifold
+ rollingFriction--;
+ if (relAngVel.length()>infoGlobal.m_singleAxisRollingFrictionThreshold)
+ {
+ relAngVel.normalize();
+ applyAnisotropicFriction(colObj0,relAngVel,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj1,relAngVel,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ if (relAngVel.length()>0.001)
+ addRollingFrictionConstraint(relAngVel,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+
+ } else
+ {
+ addRollingFrictionConstraint(cp.m_normalWorldOnB,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+ btVector3 axis0,axis1;
+ btPlaneSpace1(cp.m_normalWorldOnB,axis0,axis1);
+ applyAnisotropicFriction(colObj0,axis0,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj1,axis0,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj0,axis1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ applyAnisotropicFriction(colObj1,axis1,btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
+ if (axis0.length()>0.001)
+ addRollingFrictionConstraint(axis0,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+ if (axis1.length()>0.001)
+ addRollingFrictionConstraint(axis1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+
+ }
+ }
+
+ ///Bullet has several options to set the friction directions
+ ///By default, each contact has only a single friction direction that is recomputed automatically very frame
+ ///based on the relative linear velocity.
+ ///If the relative velocity it zero, it will automatically compute a friction direction.
+
+ ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS.
+ ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
+ ///
+ ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
+ ///
+ ///The user can manually override the friction directions for certain contacts using a contact callback,
+ ///and set the cp.m_lateralFrictionInitialized to true
+ ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
+ ///this will give a conveyor belt effect
+ ///
if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !cp.m_lateralFrictionInitialized)
{
cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
{
- cp.m_lateralFrictionDir1 /= btSqrt(lat_rel_vel);
+ cp.m_lateralFrictionDir1 *= 1.f/btSqrt(lat_rel_vel);
if((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
cp.m_lateralFrictionDir2.normalize();//??
- applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2);
- applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2);
- addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+ applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+
}
- applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1);
- applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1);
- addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
- cp.m_lateralFrictionInitialized = true;
+ applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+
} else
{
- //re-calculate friction direction every frame, todo: check if this is really needed
btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2);
+
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
{
- applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2);
- applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2);
- addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+ applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
}
- applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1);
- applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1);
- addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+ applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
+ addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
- cp.m_lateralFrictionInitialized = true;
+ if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
+ {
+ cp.m_lateralFrictionInitialized = true;
+ }
}
} else
{
- addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation,cp.m_contactMotion1, cp.m_contactCFM1);
+ addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation,cp.m_contactMotion1, cp.m_contactCFM1);
+
if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, cp.m_contactMotion2, cp.m_contactCFM2);
+ addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, cp.m_contactMotion2, cp.m_contactCFM2);
+
+ setFrictionConstraintImpulse( solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
}
+
+
- setFrictionConstraintImpulse( solverConstraint, rb0, rb1, cp, infoGlobal);
}
}
@@ -748,39 +917,107 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
m_maxOverrideNumSolverIterations = 0;
- if (!(numConstraints + numManifolds))
- {
- // printf("empty\n");
- return 0.f;
- }
-
- if (infoGlobal.m_splitImpulse)
+#ifdef BT_ADDITIONAL_DEBUG
+ //make sure that dynamic bodies exist for all (enabled) constraints
+ for (int i=0;i<numConstraints;i++)
{
- for (int i = 0; i < numBodies; i++)
+ btTypedConstraint* constraint = constraints[i];
+ if (constraint->isEnabled())
{
- btRigidBody* body = btRigidBody::upcast(bodies[i]);
- if (body)
- {
- body->internalGetDeltaLinearVelocity().setZero();
- body->internalGetDeltaAngularVelocity().setZero();
- body->internalGetPushVelocity().setZero();
- body->internalGetTurnVelocity().setZero();
+ if (!constraint->getRigidBodyA().isStaticOrKinematicObject())
+ {
+ bool found=false;
+ for (int b=0;b<numBodies;b++)
+ {
+
+ if (&constraint->getRigidBodyA()==bodies[b])
+ {
+ found = true;
+ break;
+ }
+ }
+ btAssert(found);
+ }
+ if (!constraint->getRigidBodyB().isStaticOrKinematicObject())
+ {
+ bool found=false;
+ for (int b=0;b<numBodies;b++)
+ {
+ if (&constraint->getRigidBodyB()==bodies[b])
+ {
+ found = true;
+ break;
+ }
+ }
+ btAssert(found);
}
}
}
- else
+ //make sure that dynamic bodies exist for all contact manifolds
+ for (int i=0;i<numManifolds;i++)
+ {
+ if (!manifoldPtr[i]->getBody0()->isStaticOrKinematicObject())
+ {
+ bool found=false;
+ for (int b=0;b<numBodies;b++)
+ {
+
+ if (manifoldPtr[i]->getBody0()==bodies[b])
+ {
+ found = true;
+ break;
+ }
+ }
+ btAssert(found);
+ }
+ if (!manifoldPtr[i]->getBody1()->isStaticOrKinematicObject())
+ {
+ bool found=false;
+ for (int b=0;b<numBodies;b++)
+ {
+ if (manifoldPtr[i]->getBody1()==bodies[b])
+ {
+ found = true;
+ break;
+ }
+ }
+ btAssert(found);
+ }
+ }
+#endif //BT_ADDITIONAL_DEBUG
+
+
+ for (int i = 0; i < numBodies; i++)
{
- for (int i = 0; i < numBodies; i++)
+ bodies[i]->setCompanionId(-1);
+ }
+
+
+ m_tmpSolverBodyPool.reserve(numBodies+1);
+ m_tmpSolverBodyPool.resize(0);
+
+ btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(&fixedBody,0);
+
+ //convert all bodies
+
+ for (int i=0;i<numBodies;i++)
+ {
+ int bodyId = getOrInitSolverBody(*bodies[i]);
+ btRigidBody* body = btRigidBody::upcast(bodies[i]);
+ if (body && body->getInvMass())
{
- btRigidBody* body = btRigidBody::upcast(bodies[i]);
- if (body)
- {
- body->internalGetDeltaLinearVelocity().setZero();
- body->internalGetDeltaAngularVelocity().setZero();
+ btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
+ btVector3 gyroForce (0,0,0);
+ if (body->getFlags()&BT_ENABLE_GYROPSCOPIC_FORCE)
+ {
+ gyroForce = body->computeGyroscopicForce(infoGlobal.m_maxGyroscopicForce);
}
+ solverBody.m_linearVelocity += body->getTotalForce()*body->getInvMass()*infoGlobal.m_timeStep;
+ solverBody.m_angularVelocity += (body->getTotalTorque()-gyroForce)*body->getInvInertiaTensorWorld()*infoGlobal.m_timeStep;
}
}
-
+
if (1)
{
int j;
@@ -791,6 +1028,7 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
constraint->internalSetAppliedImpulse(0.0f);
}
}
+
//btRigidBody* rb0=0,*rb1=0;
//if (1)
@@ -800,11 +1038,23 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
int totalNumRows = 0;
int i;
- m_tmpConstraintSizesPool.resize(numConstraints);
+ m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
//calculate the total number of contraint rows
for (i=0;i<numConstraints;i++)
{
btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
+ btJointFeedback* fb = constraints[i]->getJointFeedback();
+ if (fb)
+ {
+ fb->m_appliedForceBodyA.setZero();
+ fb->m_appliedTorqueBodyA.setZero();
+ fb->m_appliedForceBodyB.setZero();
+ fb->m_appliedTorqueBodyB.setZero();
+ }
+
+ if (constraints[i]->isEnabled())
+ {
+ }
if (constraints[i]->isEnabled())
{
constraints[i]->getInfo1(&info1);
@@ -815,7 +1065,7 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
}
totalNumRows += info1.m_numConstraintRows;
}
- m_tmpSolverNonContactConstraintPool.resize(totalNumRows);
+ m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
///setup the btSolverConstraints
@@ -834,6 +1084,14 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
btRigidBody& rbA = constraint->getRigidBodyA();
btRigidBody& rbB = constraint->getRigidBodyB();
+ int solverBodyIdA = getOrInitSolverBody(rbA);
+ int solverBodyIdB = getOrInitSolverBody(rbB);
+
+ btSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
+ btSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
+
+
+
int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)
@@ -848,28 +1106,31 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
currentConstraintRow[j].m_upperLimit = SIMD_INFINITY;
currentConstraintRow[j].m_appliedImpulse = 0.f;
currentConstraintRow[j].m_appliedPushImpulse = 0.f;
- currentConstraintRow[j].m_solverBodyA = &rbA;
- currentConstraintRow[j].m_solverBodyB = &rbB;
+ currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;
+ currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;
currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
}
- rbA.internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
- rbA.internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
- rbB.internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
- rbB.internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
-
+ bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
+ bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
+ bodyAPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
+ bodyAPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
+ bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
+ bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
+ bodyBPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
+ bodyBPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
btTypedConstraint::btConstraintInfo2 info2;
info2.fps = 1.f/infoGlobal.m_timeStep;
info2.erp = infoGlobal.m_erp;
- info2.m_J1linearAxis = currentConstraintRow->m_contactNormal;
+ info2.m_J1linearAxis = currentConstraintRow->m_contactNormal1;
info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
- info2.m_J2linearAxis = 0;
+ info2.m_J2linearAxis = currentConstraintRow->m_contactNormal2;
info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this
///the size of btSolverConstraint needs be a multiple of btScalar
- btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint));
+ btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint));
info2.m_constraintError = &currentConstraintRow->m_rhs;
currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
info2.m_damping = infoGlobal.m_damping;
@@ -906,17 +1167,18 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
}
{
- btVector3 iMJlA = solverConstraint.m_contactNormal*rbA.getInvMass();
+ btVector3 iMJlA = solverConstraint.m_contactNormal1*rbA.getInvMass();
btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal;
- btVector3 iMJlB = solverConstraint.m_contactNormal*rbB.getInvMass();//sign of normal?
+ btVector3 iMJlB = solverConstraint.m_contactNormal2*rbB.getInvMass();//sign of normal?
btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal;
- btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal);
+ btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal1);
sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
- sum += iMJlB.dot(solverConstraint.m_contactNormal);
+ sum += iMJlB.dot(solverConstraint.m_contactNormal2);
sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
-
- solverConstraint.m_jacDiagABInv = btScalar(1.)/sum;
+ btScalar fsum = btFabs(sum);
+ btAssert(fsum > SIMD_EPSILON);
+ solverConstraint.m_jacDiagABInv = fsum>SIMD_EPSILON?btScalar(1.)/sum : 0.f;
}
@@ -924,8 +1186,8 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
///todo: add force/torque accelerators
{
btScalar rel_vel;
- btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.getLinearVelocity()) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity());
- btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.getLinearVelocity()) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity());
+ btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(rbA.getLinearVelocity()) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity());
+ btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(rbB.getLinearVelocity()) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity());
rel_vel = vel1Dotn+vel2Dotn;
@@ -958,7 +1220,7 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
}
}
- btContactSolverInfo info = infoGlobal;
+// btContactSolverInfo info = infoGlobal;
int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
@@ -966,9 +1228,13 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
///@todo: use stack allocator for such temporarily memory, same for solver bodies/constraints
- m_orderNonContactConstraintPool.resize(numNonContactPool);
- m_orderTmpConstraintPool.resize(numConstraintPool);
- m_orderFrictionConstraintPool.resize(numFrictionPool);
+ m_orderNonContactConstraintPool.resizeNoInitialize(numNonContactPool);
+ if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+ m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool*2);
+ else
+ m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool);
+
+ m_orderFrictionConstraintPool.resizeNoInitialize(numFrictionPool);
{
int i;
for (i=0;i<numNonContactPool;i++)
@@ -989,19 +1255,20 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
}
+
btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */,int /*numBodies*/,btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* /*debugDrawer*/,btStackAlloc* /*stackAlloc*/)
{
int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
int numConstraintPool = m_tmpSolverContactConstraintPool.size();
int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
-
- int j;
-
+
if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
{
- if ((iteration & 7) == 0) {
- for (j=0; j<numNonContactPool; ++j) {
+ if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
+ {
+
+ for (int j=0; j<numNonContactPool; ++j) {
int tmp = m_orderNonContactConstraintPool[j];
int swapi = btRandInt2(j+1);
m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi];
@@ -1011,14 +1278,14 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
//contact/friction constraints are not solved more than
if (iteration< infoGlobal.m_numIterations)
{
- for (j=0; j<numConstraintPool; ++j) {
+ for (int j=0; j<numConstraintPool; ++j) {
int tmp = m_orderTmpConstraintPool[j];
int swapi = btRandInt2(j+1);
m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
m_orderTmpConstraintPool[swapi] = tmp;
}
- for (j=0; j<numFrictionPool; ++j) {
+ for (int j=0; j<numFrictionPool; ++j) {
int tmp = m_orderFrictionConstraintPool[j];
int swapi = btRandInt2(j+1);
m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
@@ -1031,72 +1298,164 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
if (infoGlobal.m_solverMode & SOLVER_SIMD)
{
///solve all joint constraints, using SIMD, if available
- for (j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
+ for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
{
btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
if (iteration < constraint.m_overrideNumSolverIterations)
- resolveSingleConstraintRowGenericSIMD(*constraint.m_solverBodyA,*constraint.m_solverBodyB,constraint);
+ resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
}
if (iteration< infoGlobal.m_numIterations)
{
- for (j=0;j<numConstraints;j++)
+ for (int j=0;j<numConstraints;j++)
{
- constraints[j]->solveConstraintObsolete(constraints[j]->getRigidBodyA(),constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep);
+ if (constraints[j]->isEnabled())
+ {
+ int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA());
+ int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB());
+ btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
+ btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
+ constraints[j]->solveConstraintObsolete(bodyA,bodyB,infoGlobal.m_timeStep);
+ }
}
///solve all contact constraints using SIMD, if available
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- for (j=0;j<numPoolConstraints;j++)
+ if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
{
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- resolveSingleConstraintRowLowerLimitSIMD(*solveManifold.m_solverBodyA,*solveManifold.m_solverBodyB,solveManifold);
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)? 2 : 1;
+
+ for (int c=0;c<numPoolConstraints;c++)
+ {
+ btScalar totalImpulse =0;
+
+ {
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
+ resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ totalImpulse = solveManifold.m_appliedImpulse;
+ }
+ bool applyFriction = true;
+ if (applyFriction)
+ {
+ {
+
+ btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier]];
+
+ if (totalImpulse>btScalar(0))
+ {
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
+
+ resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ }
+ }
+
+ if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
+ {
+
+ btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c*multiplier+1]];
+
+ if (totalImpulse>btScalar(0))
+ {
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
+
+ resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ }
+ }
+ }
+ }
}
-
- ///solve all friction constraints, using SIMD, if available
- int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
- for (j=0;j<numFrictionPoolConstraints;j++)
+ else//SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
{
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+ //solve the friction constraints after all contact constraints, don't interleave them
+ int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+ int j;
- if (totalImpulse>btScalar(0))
+ for (j=0;j<numPoolConstraints;j++)
{
- solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+ resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
- resolveSingleConstraintRowGenericSIMD(*solveManifold.m_solverBodyA, *solveManifold.m_solverBodyB,solveManifold);
}
- }
+
+
+
+ ///solve all friction constraints, using SIMD, if available
+
+ int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
+ for (j=0;j<numFrictionPoolConstraints;j++)
+ {
+ btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
+ btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+
+ if (totalImpulse>btScalar(0))
+ {
+ solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
+ solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
+
+ resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ }
+ }
+
+
+ int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
+ for (j=0;j<numRollingFrictionPoolConstraints;j++)
+ {
+
+ btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
+ btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
+ if (totalImpulse>btScalar(0))
+ {
+ btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
+ if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction)
+ rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
+
+ rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
+ rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
+
+ resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
+ }
+ }
+
+
+ }
}
} else
{
-
+ //non-SIMD version
///solve all joint constraints
- for (j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
+ for (int j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
{
btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
if (iteration < constraint.m_overrideNumSolverIterations)
- resolveSingleConstraintRowGeneric(*constraint.m_solverBodyA,*constraint.m_solverBodyB,constraint);
+ resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
}
if (iteration< infoGlobal.m_numIterations)
{
- for (j=0;j<numConstraints;j++)
+ for (int j=0;j<numConstraints;j++)
{
- constraints[j]->solveConstraintObsolete(constraints[j]->getRigidBodyA(),constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep);
+ if (constraints[j]->isEnabled())
+ {
+ int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA());
+ int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB());
+ btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
+ btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
+ constraints[j]->solveConstraintObsolete(bodyA,bodyB,infoGlobal.m_timeStep);
+ }
}
///solve all contact constraints
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- for (j=0;j<numPoolConstraints;j++)
+ for (int j=0;j<numPoolConstraints;j++)
{
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- resolveSingleConstraintRowLowerLimit(*solveManifold.m_solverBodyA,*solveManifold.m_solverBodyB,solveManifold);
+ resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
}
///solve all friction constraints
int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
- for (j=0;j<numFrictionPoolConstraints;j++)
+ for (int j=0;j<numFrictionPoolConstraints;j++)
{
btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
@@ -1106,7 +1465,25 @@ btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration
solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
- resolveSingleConstraintRowGeneric(*solveManifold.m_solverBodyA,*solveManifold.m_solverBodyB,solveManifold);
+ resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
+ }
+ }
+
+ int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
+ for (int j=0;j<numRollingFrictionPoolConstraints;j++)
+ {
+ btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
+ btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
+ if (totalImpulse>btScalar(0))
+ {
+ btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction*totalImpulse;
+ if (rollingFrictionMagnitude>rollingFrictionConstraint.m_friction)
+ rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
+
+ rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
+ rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
+
+ resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA],m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB],rollingFrictionConstraint);
}
}
}
@@ -1131,7 +1508,7 @@ void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIte
{
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- resolveSplitPenetrationSIMD(*solveManifold.m_solverBodyA,*solveManifold.m_solverBodyB,solveManifold);
+ resolveSplitPenetrationSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
}
}
}
@@ -1147,7 +1524,7 @@ void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIte
{
const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- resolveSplitPenetrationImpulseCacheFriendly(*solveManifold.m_solverBodyA,*solveManifold.m_solverBodyB,solveManifold);
+ resolveSplitPenetrationImpulseCacheFriendly(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold);
}
}
}
@@ -1175,25 +1552,29 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(
return 0.f;
}
-btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies ,int numBodies,btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/,btTypedConstraint** /*constraints*/,int /* numConstraints*/,const btContactSolverInfo& infoGlobal,btIDebugDraw* /*debugDrawer*/,btStackAlloc* /*stackAlloc*/)
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal)
{
int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
int i,j;
- for (j=0;j<numPoolConstraints;j++)
+ if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
{
-
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j];
- btManifoldPoint* pt = (btManifoldPoint*) solveManifold.m_originalContactPoint;
- btAssert(pt);
- pt->m_appliedImpulse = solveManifold.m_appliedImpulse;
- if (infoGlobal.m_solverMode & SOLVER_USE_FRICTION_WARMSTARTING)
+ for (j=0;j<numPoolConstraints;j++)
{
+ const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j];
+ btManifoldPoint* pt = (btManifoldPoint*) solveManifold.m_originalContactPoint;
+ btAssert(pt);
+ pt->m_appliedImpulse = solveManifold.m_appliedImpulse;
+ // float f = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+ // printf("pt->m_appliedImpulseLateral1 = %f\n", f);
pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
- pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse;
+ //printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
+ if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+ {
+ pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse;
+ }
+ //do a callback here?
}
-
- //do a callback here?
}
numPoolConstraints = m_tmpSolverNonContactConstraintPool.size();
@@ -1201,6 +1582,16 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCo
{
const btSolverConstraint& solverConstr = m_tmpSolverNonContactConstraintPool[j];
btTypedConstraint* constr = (btTypedConstraint*)solverConstr.m_originalContactPoint;
+ btJointFeedback* fb = constr->getJointFeedback();
+ if (fb)
+ {
+ fb->m_appliedForceBodyA += solverConstr.m_contactNormal1*solverConstr.m_appliedImpulse*constr->getRigidBodyA().getLinearFactor()/infoGlobal.m_timeStep;
+ fb->m_appliedForceBodyB += solverConstr.m_contactNormal2*solverConstr.m_appliedImpulse*constr->getRigidBodyB().getLinearFactor()/infoGlobal.m_timeStep;
+ fb->m_appliedTorqueBodyA += solverConstr.m_relpos1CrossNormal* constr->getRigidBodyA().getAngularFactor()*solverConstr.m_appliedImpulse/infoGlobal.m_timeStep;
+ fb->m_appliedTorqueBodyB += solverConstr.m_relpos2CrossNormal* constr->getRigidBodyB().getAngularFactor()*solverConstr.m_appliedImpulse/infoGlobal.m_timeStep; /*RGM ???? */
+
+ }
+
constr->internalSetAppliedImpulse(solverConstr.m_appliedImpulse);
if (btFabs(solverConstr.m_appliedImpulse)>=constr->getBreakingImpulseThreshold())
{
@@ -1209,29 +1600,32 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCo
}
- if (infoGlobal.m_splitImpulse)
- {
- for ( i=0;i<numBodies;i++)
- {
- btRigidBody* body = btRigidBody::upcast(bodies[i]);
- if (body)
- body->internalWritebackVelocity(infoGlobal.m_timeStep);
- }
- } else
+
+ for ( i=0;i<m_tmpSolverBodyPool.size();i++)
{
- for ( i=0;i<numBodies;i++)
+ btRigidBody* body = m_tmpSolverBodyPool[i].m_originalBody;
+ if (body)
{
- btRigidBody* body = btRigidBody::upcast(bodies[i]);
- if (body)
- body->internalWritebackVelocity();
+ if (infoGlobal.m_splitImpulse)
+ m_tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
+ else
+ m_tmpSolverBodyPool[i].writebackVelocity();
+
+ m_tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(m_tmpSolverBodyPool[i].m_linearVelocity);
+ m_tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(m_tmpSolverBodyPool[i].m_angularVelocity);
+ if (infoGlobal.m_splitImpulse)
+ m_tmpSolverBodyPool[i].m_originalBody->setWorldTransform(m_tmpSolverBodyPool[i].m_worldTransform);
+
+ m_tmpSolverBodyPool[i].m_originalBody->setCompanionId(-1);
}
}
+ m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
+ m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
- m_tmpSolverContactConstraintPool.resize(0);
- m_tmpSolverNonContactConstraintPool.resize(0);
- m_tmpSolverContactFrictionConstraintPool.resize(0);
-
+ m_tmpSolverBodyPool.resizeNoInitialize(0);
return 0.f;
}
@@ -1243,14 +1637,12 @@ btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bod
BT_PROFILE("solveGroup");
//you need to provide at least some bodies
- btAssert(bodies);
- btAssert(numBodies);
-
+
solveGroupCacheFriendlySetup( bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc);
solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc);
- solveGroupCacheFriendlyFinish(bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc);
+ solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal);
return 0.f;
}
@@ -1260,10 +1652,4 @@ void btSequentialImpulseConstraintSolver::reset()
m_btSeed2 = 0;
}
-btRigidBody& btSequentialImpulseConstraintSolver::getFixedBody()
-{
- static btRigidBody s_fixed(0, 0,0);
- s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.)));
- return s_fixed;
-}
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
index bb377db8db9..2eea6be0db2 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
@@ -16,77 +16,89 @@ subject to the following restrictions:
#ifndef BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
#define BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
-#include "btConstraintSolver.h"
class btIDebugDraw;
-#include "btContactConstraint.h"
-#include "btSolverBody.h"
-#include "btSolverConstraint.h"
-#include "btTypedConstraint.h"
+class btPersistentManifold;
+class btStackAlloc;
+class btDispatcher;
+class btCollisionObject;
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+#include "BulletDynamics/ConstraintSolver/btSolverBody.h"
+#include "BulletDynamics/ConstraintSolver/btSolverConstraint.h"
#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
+#include "BulletDynamics/ConstraintSolver/btConstraintSolver.h"
///The btSequentialImpulseConstraintSolver is a fast SIMD implementation of the Projected Gauss Seidel (iterative LCP) method.
-class btSequentialImpulseConstraintSolver : public btConstraintSolver
+ATTRIBUTE_ALIGNED16(class) btSequentialImpulseConstraintSolver : public btConstraintSolver
{
protected:
-
+ btAlignedObjectArray<btSolverBody> m_tmpSolverBodyPool;
btConstraintArray m_tmpSolverContactConstraintPool;
btConstraintArray m_tmpSolverNonContactConstraintPool;
btConstraintArray m_tmpSolverContactFrictionConstraintPool;
+ btConstraintArray m_tmpSolverContactRollingFrictionConstraintPool;
+
btAlignedObjectArray<int> m_orderTmpConstraintPool;
btAlignedObjectArray<int> m_orderNonContactConstraintPool;
btAlignedObjectArray<int> m_orderFrictionConstraintPool;
btAlignedObjectArray<btTypedConstraint::btConstraintInfo1> m_tmpConstraintSizesPool;
int m_maxOverrideNumSolverIterations;
- void setupFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis,btRigidBody* solverBodyA,btRigidBody* solverBodyIdB,
+ void setupFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,
btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,
btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation,
btScalar desiredVelocity=0., btScalar cfmSlip=0.);
- btSolverConstraint& addFrictionConstraint(const btVector3& normalAxis,btRigidBody* solverBodyA,btRigidBody* solverBodyB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity=0., btScalar cfmSlip=0.);
-
- void setupContactConstraint(btSolverConstraint& solverConstraint, btCollisionObject* colObj0, btCollisionObject* colObj1, btManifoldPoint& cp,
+ void setupRollingFrictionConstraint( btSolverConstraint& solverConstraint, const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,
+ btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,
+ btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation,
+ btScalar desiredVelocity=0., btScalar cfmSlip=0.);
+
+ btSolverConstraint& addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity=0., btScalar cfmSlip=0.);
+ btSolverConstraint& addRollingFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity=0, btScalar cfmSlip=0.f);
+
+
+ void setupContactConstraint(btSolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp,
const btContactSolverInfo& infoGlobal, btVector3& vel, btScalar& rel_vel, btScalar& relaxation,
btVector3& rel_pos1, btVector3& rel_pos2);
- void setFrictionConstraintImpulse( btSolverConstraint& solverConstraint, btRigidBody* rb0, btRigidBody* rb1,
+ void setFrictionConstraintImpulse( btSolverConstraint& solverConstraint, int solverBodyIdA,int solverBodyIdB,
btManifoldPoint& cp, const btContactSolverInfo& infoGlobal);
///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction
unsigned long m_btSeed2;
-// void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject);
+
btScalar restitutionCurve(btScalar rel_vel, btScalar restitution);
void convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal);
void resolveSplitPenetrationSIMD(
- btRigidBody& body1,
- btRigidBody& body2,
+ btSolverBody& bodyA,btSolverBody& bodyB,
const btSolverConstraint& contactConstraint);
void resolveSplitPenetrationImpulseCacheFriendly(
- btRigidBody& body1,
- btRigidBody& body2,
+ btSolverBody& bodyA,btSolverBody& bodyB,
const btSolverConstraint& contactConstraint);
//internal method
- int getOrInitSolverBody(btCollisionObject& body);
+ int getOrInitSolverBody(btCollisionObject& body);
+ void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject);
- void resolveSingleConstraintRowGeneric(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& contactConstraint);
+ void resolveSingleConstraintRowGeneric(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint);
- void resolveSingleConstraintRowGenericSIMD(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& contactConstraint);
+ void resolveSingleConstraintRowGenericSIMD(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint);
- void resolveSingleConstraintRowLowerLimit(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& contactConstraint);
+ void resolveSingleConstraintRowLowerLimit(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint);
- void resolveSingleConstraintRowLowerLimitSIMD(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& contactConstraint);
+ void resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& bodyA,btSolverBody& bodyB,const btSolverConstraint& contactConstraint);
protected:
- static btRigidBody& getFixedBody();
+
virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc);
- virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc);
+ virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject** bodies,int numBodies,const btContactSolverInfo& infoGlobal);
btScalar solveSingleIteration(int iteration, btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc);
virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc);
@@ -95,6 +107,7 @@ protected:
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
btSequentialImpulseConstraintSolver();
virtual ~btSequentialImpulseConstraintSolver();
@@ -121,9 +134,7 @@ public:
};
-#ifndef BT_PREFER_SIMD
-typedef btSequentialImpulseConstraintSolver btSequentialImpulseConstraintSolverPrefered;
-#endif
+
#endif //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
index b69f46da1b4..aff9f27f594 100644..100755
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
@@ -426,6 +426,8 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = -tmpB[i];
for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i];
for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i];
+ for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -p[i];
+ for (i=0; i<3; i++) info->m_J2linearAxis[s3+i] = -q[i];
}
else
{ // old way - maybe incorrect if bodies are not on the slider axis
@@ -440,6 +442,8 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i];
for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i];
+ for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -p[i];
+ for (i=0; i<3; i++) info->m_J2linearAxis[s3+i] = -q[i];
}
// compute two elements of right hand side
@@ -479,6 +483,9 @@ void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTra
info->m_J1linearAxis[srow+0] = ax1[0];
info->m_J1linearAxis[srow+1] = ax1[1];
info->m_J1linearAxis[srow+2] = ax1[2];
+ info->m_J2linearAxis[srow+0] = -ax1[0];
+ info->m_J2linearAxis[srow+1] = -ax1[1];
+ info->m_J2linearAxis[srow+2] = -ax1[2];
// linear torque decoupling step:
//
// we have to be careful that the linear constraint forces (+/- ax1) applied to the two bodies
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h
index 2edc8d2b2e1..ca8e715bc47 100644..100755
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h
@@ -60,7 +60,7 @@ enum btSliderFlags
};
-class btSliderConstraint : public btTypedConstraint
+ATTRIBUTE_ALIGNED16(class) btSliderConstraint : public btTypedConstraint
{
protected:
///for backwards compatibility during the transition to 'getInfo/getInfo2'
@@ -155,6 +155,8 @@ protected:
//------------------------
void initParams();
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
// constructors
btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA);
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h
index 8de515812ee..ccc45996c8b 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h
@@ -19,7 +19,7 @@ subject to the following restrictions:
class btRigidBody;
#include "LinearMath/btVector3.h"
#include "LinearMath/btMatrix3x3.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
+
#include "LinearMath/btAlignedAllocator.h"
#include "LinearMath/btTransformUtil.h"
@@ -105,22 +105,35 @@ operator+(const btSimdScalar& v1, const btSimdScalar& v2)
#endif
///The btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance.
-ATTRIBUTE_ALIGNED64 (struct) btSolverBodyObsolete
+ATTRIBUTE_ALIGNED16 (struct) btSolverBody
{
BT_DECLARE_ALIGNED_ALLOCATOR();
+ btTransform m_worldTransform;
btVector3 m_deltaLinearVelocity;
btVector3 m_deltaAngularVelocity;
btVector3 m_angularFactor;
+ btVector3 m_linearFactor;
btVector3 m_invMass;
- btRigidBody* m_originalBody;
btVector3 m_pushVelocity;
btVector3 m_turnVelocity;
+ btVector3 m_linearVelocity;
+ btVector3 m_angularVelocity;
+
+ btRigidBody* m_originalBody;
+ void setWorldTransform(const btTransform& worldTransform)
+ {
+ m_worldTransform = worldTransform;
+ }
+ const btTransform& getWorldTransform() const
+ {
+ return m_worldTransform;
+ }
SIMD_FORCE_INLINE void getVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const
{
if (m_originalBody)
- velocity = m_originalBody->getLinearVelocity()+m_deltaLinearVelocity + (m_originalBody->getAngularVelocity()+m_deltaAngularVelocity).cross(rel_pos);
+ velocity = m_linearVelocity+m_deltaLinearVelocity + (m_angularVelocity+m_deltaAngularVelocity).cross(rel_pos);
else
velocity.setValue(0,0,0);
}
@@ -128,7 +141,7 @@ ATTRIBUTE_ALIGNED64 (struct) btSolverBodyObsolete
SIMD_FORCE_INLINE void getAngularVelocity(btVector3& angVel) const
{
if (m_originalBody)
- angVel = m_originalBody->getAngularVelocity()+m_deltaAngularVelocity;
+ angVel =m_angularVelocity+m_deltaAngularVelocity;
else
angVel.setValue(0,0,0);
}
@@ -137,9 +150,9 @@ ATTRIBUTE_ALIGNED64 (struct) btSolverBodyObsolete
//Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
SIMD_FORCE_INLINE void applyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude)
{
- //if (m_invMass)
+ if (m_originalBody)
{
- m_deltaLinearVelocity += linearComponent*impulseMagnitude;
+ m_deltaLinearVelocity += linearComponent*impulseMagnitude*m_linearFactor;
m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
}
}
@@ -148,36 +161,125 @@ ATTRIBUTE_ALIGNED64 (struct) btSolverBodyObsolete
{
if (m_originalBody)
{
- m_pushVelocity += linearComponent*impulseMagnitude;
+ m_pushVelocity += linearComponent*impulseMagnitude*m_linearFactor;
m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
}
}
+
+
+
+ const btVector3& getDeltaLinearVelocity() const
+ {
+ return m_deltaLinearVelocity;
+ }
+
+ const btVector3& getDeltaAngularVelocity() const
+ {
+ return m_deltaAngularVelocity;
+ }
+
+ const btVector3& getPushVelocity() const
+ {
+ return m_pushVelocity;
+ }
+
+ const btVector3& getTurnVelocity() const
+ {
+ return m_turnVelocity;
+ }
+
+
+ ////////////////////////////////////////////////
+ ///some internal methods, don't use them
+
+ btVector3& internalGetDeltaLinearVelocity()
+ {
+ return m_deltaLinearVelocity;
+ }
+
+ btVector3& internalGetDeltaAngularVelocity()
+ {
+ return m_deltaAngularVelocity;
+ }
+
+ const btVector3& internalGetAngularFactor() const
+ {
+ return m_angularFactor;
+ }
+
+ const btVector3& internalGetInvMass() const
+ {
+ return m_invMass;
+ }
+
+ void internalSetInvMass(const btVector3& invMass)
+ {
+ m_invMass = invMass;
+ }
+ btVector3& internalGetPushVelocity()
+ {
+ return m_pushVelocity;
+ }
+
+ btVector3& internalGetTurnVelocity()
+ {
+ return m_turnVelocity;
+ }
+
+ SIMD_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const
+ {
+ velocity = m_linearVelocity+m_deltaLinearVelocity + (m_angularVelocity+m_deltaAngularVelocity).cross(rel_pos);
+ }
+
+ SIMD_FORCE_INLINE void internalGetAngularVelocity(btVector3& angVel) const
+ {
+ angVel = m_angularVelocity+m_deltaAngularVelocity;
+ }
+
+
+ //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
+ SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude)
+ {
+ if (m_originalBody)
+ {
+ m_deltaLinearVelocity += linearComponent*impulseMagnitude*m_linearFactor;
+ m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ }
+ }
+
+
+
+
void writebackVelocity()
{
if (m_originalBody)
{
- m_originalBody->setLinearVelocity(m_originalBody->getLinearVelocity()+ m_deltaLinearVelocity);
- m_originalBody->setAngularVelocity(m_originalBody->getAngularVelocity()+m_deltaAngularVelocity);
+ m_linearVelocity +=m_deltaLinearVelocity;
+ m_angularVelocity += m_deltaAngularVelocity;
//m_originalBody->setCompanionId(-1);
}
}
- void writebackVelocity(btScalar timeStep)
+ void writebackVelocityAndTransform(btScalar timeStep, btScalar splitImpulseTurnErp)
{
(void) timeStep;
if (m_originalBody)
{
- m_originalBody->setLinearVelocity(m_originalBody->getLinearVelocity()+ m_deltaLinearVelocity);
- m_originalBody->setAngularVelocity(m_originalBody->getAngularVelocity()+m_deltaAngularVelocity);
+ m_linearVelocity += m_deltaLinearVelocity;
+ m_angularVelocity += m_deltaAngularVelocity;
//correct the position/orientation based on push/turn recovery
btTransform newTransform;
- btTransformUtil::integrateTransform(m_originalBody->getWorldTransform(),m_pushVelocity,m_turnVelocity,timeStep,newTransform);
- m_originalBody->setWorldTransform(newTransform);
-
+ if (m_pushVelocity[0]!=0.f || m_pushVelocity[1]!=0 || m_pushVelocity[2]!=0 || m_turnVelocity[0]!=0.f || m_turnVelocity[1]!=0 || m_turnVelocity[2]!=0)
+ {
+ // btQuaternion orn = m_worldTransform.getRotation();
+ btTransformUtil::integrateTransform(m_worldTransform,m_pushVelocity,m_turnVelocity*splitImpulseTurnErp,timeStep,newTransform);
+ m_worldTransform = newTransform;
+ }
+ //m_worldTransform.setRotation(orn);
//m_originalBody->setCompanionId(-1);
}
}
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h
index 179e79d7911..2ade61b2f69 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h
@@ -20,68 +20,49 @@ class btRigidBody;
#include "LinearMath/btVector3.h"
#include "LinearMath/btMatrix3x3.h"
#include "btJacobianEntry.h"
+#include "LinearMath/btAlignedObjectArray.h"
//#define NO_FRICTION_TANGENTIALS 1
#include "btSolverBody.h"
///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints.
-ATTRIBUTE_ALIGNED64 (struct) btSolverConstraint
+ATTRIBUTE_ALIGNED16 (struct) btSolverConstraint
{
BT_DECLARE_ALIGNED_ALLOCATOR();
btVector3 m_relpos1CrossNormal;
- btVector3 m_contactNormal;
+ btVector3 m_contactNormal1;
btVector3 m_relpos2CrossNormal;
- //btVector3 m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal
+ btVector3 m_contactNormal2; //usually m_contactNormal2 == -m_contactNormal1, but not always
btVector3 m_angularComponentA;
btVector3 m_angularComponentB;
mutable btSimdScalar m_appliedPushImpulse;
mutable btSimdScalar m_appliedImpulse;
-
-
+
btScalar m_friction;
btScalar m_jacDiagABInv;
- union
- {
- int m_numConsecutiveRowsPerKernel;
- btScalar m_unusedPadding0;
- };
-
- int m_overrideNumSolverIterations;
-
- union
- {
- int m_frictionIndex;
- btScalar m_unusedPadding1;
- };
- union
- {
- btRigidBody* m_solverBodyA;
- int m_companionIdA;
- };
- union
- {
- btRigidBody* m_solverBodyB;
- int m_companionIdB;
- };
+ btScalar m_rhs;
+ btScalar m_cfm;
- union
+ btScalar m_lowerLimit;
+ btScalar m_upperLimit;
+ btScalar m_rhsPenetration;
+ union
{
void* m_originalContactPoint;
btScalar m_unusedPadding4;
};
- btScalar m_rhs;
- btScalar m_cfm;
- btScalar m_lowerLimit;
- btScalar m_upperLimit;
-
- btScalar m_rhsPenetration;
+ int m_overrideNumSolverIterations;
+ int m_frictionIndex;
+ int m_solverBodyIdA;
+ int m_solverBodyIdB;
+
enum btSolverConstraintType
{
BT_SOLVER_CONTACT_1D = 0,
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp
index 06bde5e7eec..465c0746c58 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp
@@ -32,7 +32,8 @@ m_overrideNumSolverIterations(-1),
m_rbA(rbA),
m_rbB(getFixedBody()),
m_appliedImpulse(btScalar(0.)),
-m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE)
+m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE),
+m_jointFeedback(0)
{
}
@@ -48,7 +49,8 @@ m_overrideNumSolverIterations(-1),
m_rbA(rbA),
m_rbB(rbB),
m_appliedImpulse(btScalar(0.)),
-m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE)
+m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE),
+m_jointFeedback(0)
{
}
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h
index a16e869a973..441fa375050 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h
@@ -16,9 +16,10 @@ subject to the following restrictions:
#ifndef BT_TYPED_CONSTRAINT_H
#define BT_TYPED_CONSTRAINT_H
-class btRigidBody;
+
#include "LinearMath/btScalar.h"
#include "btSolverConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
class btSerializer;
@@ -32,6 +33,7 @@ enum btTypedConstraintType
SLIDER_CONSTRAINT_TYPE,
CONTACT_CONSTRAINT_TYPE,
D6_SPRING_CONSTRAINT_TYPE,
+ GEAR_CONSTRAINT_TYPE,
MAX_CONSTRAINT_TYPE
};
@@ -51,8 +53,17 @@ enum btConstraintParams
#endif
+ATTRIBUTE_ALIGNED16(struct) btJointFeedback
+{
+ btVector3 m_appliedForceBodyA;
+ btVector3 m_appliedTorqueBodyA;
+ btVector3 m_appliedForceBodyB;
+ btVector3 m_appliedTorqueBodyB;
+};
+
+
///TypedConstraint is the baseclass for Bullet constraints and vehicles
-class btTypedConstraint : public btTypedObject
+ATTRIBUTE_ALIGNED16(class) btTypedConstraint : public btTypedObject
{
int m_userConstraintType;
@@ -80,6 +91,7 @@ protected:
btRigidBody& m_rbB;
btScalar m_appliedImpulse;
btScalar m_dbgDrawSize;
+ btJointFeedback* m_jointFeedback;
///internal method used by the constraint solver, don't use them directly
btScalar getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact);
@@ -87,6 +99,8 @@ protected:
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
virtual ~btTypedConstraint() {};
btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA);
btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB);
@@ -195,7 +209,7 @@ public:
///internal method used by the constraint solver, don't use them directly
- virtual void solveConstraintObsolete(btRigidBody& /*bodyA*/,btRigidBody& /*bodyB*/,btScalar /*timeStep*/) {};
+ virtual void solveConstraintObsolete(btSolverBody& /*bodyA*/,btSolverBody& /*bodyB*/,btScalar /*timeStep*/) {};
const btRigidBody& getRigidBodyA() const
@@ -246,6 +260,22 @@ public:
return m_userConstraintPtr;
}
+ void setJointFeedback(btJointFeedback* jointFeedback)
+ {
+ m_jointFeedback = jointFeedback;
+ }
+
+ const btJointFeedback* getJointFeedback() const
+ {
+ return m_jointFeedback;
+ }
+
+ btJointFeedback* getJointFeedback()
+ {
+ return m_jointFeedback;
+ }
+
+
int getUid() const
{
return m_userConstraintId;
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h
index a86939164ec..9e708410430 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h
@@ -31,13 +31,16 @@ subject to the following restrictions:
/// "Given axis 1 on body 1, and axis 2 on body 2 that is perpendicular to axis 1, it keeps them perpendicular.
/// In other words, rotation of the two bodies about the direction perpendicular to the two axes will be equal."
-class btUniversalConstraint : public btGeneric6DofConstraint
+ATTRIBUTE_ALIGNED16(class) btUniversalConstraint : public btGeneric6DofConstraint
{
protected:
btVector3 m_anchor;
btVector3 m_axis1;
btVector3 m_axis2;
public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
// constructor
// anchor, axis1 and axis2 are in world coordinate system
// axis1 must be orthogonal to axis2
diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
index 954ef241adc..9ff2d9f1173 100644
--- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
@@ -134,11 +134,8 @@ struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCal
{
if (islandId<0)
{
- if (numManifolds + m_numConstraints)
- {
- ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id
- m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,*m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher);
- }
+ ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id
+ m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,*m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher);
} else
{
//also add all non-contact constraints/joints for this island
@@ -166,11 +163,7 @@ struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCal
if (m_solverInfo->m_minimumSolverBatchSize<=1)
{
- ///only call solveGroup if there is some work: avoid virtual function call, its overhead can be excessive
- if (numManifolds + numCurConstraints)
- {
- m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher);
- }
+ m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher);
} else
{
@@ -192,15 +185,12 @@ struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCal
}
void processConstraints()
{
- if (m_manifolds.size() + m_constraints.size()>0)
- {
- btCollisionObject** bodies = m_bodies.size()? &m_bodies[0]:0;
- btPersistentManifold** manifold = m_manifolds.size()?&m_manifolds[0]:0;
- btTypedConstraint** constraints = m_constraints.size()?&m_constraints[0]:0;
+ btCollisionObject** bodies = m_bodies.size()? &m_bodies[0]:0;
+ btPersistentManifold** manifold = m_manifolds.size()?&m_manifolds[0]:0;
+ btTypedConstraint** constraints = m_constraints.size()?&m_constraints[0]:0;
- m_solver->solveGroup( bodies,m_bodies.size(),manifold, m_manifolds.size(),constraints, m_constraints.size() ,*m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher);
- }
+ m_solver->solveGroup( bodies,m_bodies.size(),manifold, m_manifolds.size(),constraints, m_constraints.size() ,*m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher);
m_bodies.resize(0);
m_manifolds.resize(0);
m_constraints.resize(0);
@@ -213,13 +203,15 @@ struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCal
btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration),
+m_sortedConstraints (),
+m_solverIslandCallback ( NULL ),
m_constraintSolver(constraintSolver),
m_gravity(0,-10,0),
m_localTime(0),
m_synchronizeAllMotionStates(false),
-m_profileTimings(0),
-m_sortedConstraints (),
-m_solverIslandCallback ( NULL )
+m_applySpeculativeContactRestitution(false),
+m_profileTimings(0)
+
{
if (!m_constraintSolver)
{
@@ -240,7 +232,7 @@ m_solverIslandCallback ( NULL )
{
void* mem = btAlignedAlloc(sizeof(InplaceSolverIslandCallback),16);
- m_solverIslandCallback = new (mem) InplaceSolverIslandCallback (constraintSolver, m_stackAlloc, dispatcher);
+ m_solverIslandCallback = new (mem) InplaceSolverIslandCallback (m_constraintSolver, m_stackAlloc, dispatcher);
}
}
@@ -490,10 +482,11 @@ void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
dispatchInfo.m_debugDraw = getDebugDrawer();
+ createPredictiveContacts(timeStep);
+
///perform collision detection
performDiscreteCollisionDetection();
-
calculateSimulationIslands();
@@ -507,6 +500,7 @@ void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
///CallbackTriggers();
///integrate transforms
+
integrateTransforms(timeStep);
///update vehicle simulation
@@ -740,6 +734,28 @@ void btDiscreteDynamicsWorld::calculateSimulationIslands()
getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher());
+ {
+ //merge islands based on speculative contact manifolds too
+ for (int i=0;i<this->m_predictiveManifolds.size();i++)
+ {
+ btPersistentManifold* manifold = m_predictiveManifolds[i];
+
+ const btCollisionObject* colObj0 = manifold->getBody0();
+ const btCollisionObject* colObj1 = manifold->getBody1();
+
+ if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
+ ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
+ {
+ if (colObj0->isActive() || colObj1->isActive())
+ {
+
+ getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),
+ (colObj1)->getIslandTag());
+ }
+ }
+ }
+ }
+
{
int i;
int numConstraints = int(m_constraints.size());
@@ -860,6 +876,103 @@ public:
///internal debugging variable. this value shouldn't be too high
int gNumClampedCcdMotions=0;
+
+void btDiscreteDynamicsWorld::createPredictiveContacts(btScalar timeStep)
+{
+ BT_PROFILE("createPredictiveContacts");
+
+ {
+ BT_PROFILE("release predictive contact manifolds");
+
+ for (int i=0;i<m_predictiveManifolds.size();i++)
+ {
+ btPersistentManifold* manifold = m_predictiveManifolds[i];
+ this->m_dispatcher1->releaseManifold(manifold);
+ }
+ m_predictiveManifolds.clear();
+ }
+
+ btTransform predictedTrans;
+ for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ {
+ btRigidBody* body = m_nonStaticRigidBodies[i];
+ body->setHitFraction(1.f);
+
+ if (body->isActive() && (!body->isStaticOrKinematicObject()))
+ {
+
+ body->predictIntegratedTransform(timeStep, predictedTrans);
+
+ btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
+
+ if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
+ {
+ BT_PROFILE("predictive convexSweepTest");
+ if (body->getCollisionShape()->isConvex())
+ {
+ gNumClampedCcdMotions++;
+#ifdef PREDICTIVE_CONTACT_USE_STATIC_ONLY
+ class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
+ {
+ public:
+
+ StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :
+ btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher)
+ {
+ }
+
+ virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+ {
+ btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
+ if (!otherObj->isStaticOrKinematicObject())
+ return false;
+ return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
+ }
+ };
+
+ StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
+#else
+ btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
+#endif
+ //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
+ btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
+ sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration;
+
+ sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
+ sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
+ btTransform modifiedPredictedTrans = predictedTrans;
+ modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
+
+ convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults);
+ if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
+ {
+
+ btVector3 distVec = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin())*sweepResults.m_closestHitFraction;
+ btScalar distance = distVec.dot(-sweepResults.m_hitNormalWorld);
+
+
+ btPersistentManifold* manifold = m_dispatcher1->getNewManifold(body,sweepResults.m_hitCollisionObject);
+ m_predictiveManifolds.push_back(manifold);
+
+ btVector3 worldPointB = body->getWorldTransform().getOrigin()+distVec;
+ btVector3 localPointB = sweepResults.m_hitCollisionObject->getWorldTransform().inverse()*worldPointB;
+
+ btManifoldPoint newPoint(btVector3(0,0,0), localPointB,sweepResults.m_hitNormalWorld,distance);
+
+ bool isPredictive = true;
+ int index = manifold->addManifoldPoint(newPoint, isPredictive);
+ btManifoldPoint& pt = manifold->getContactPoint(index);
+ pt.m_combinedRestitution = 0;
+ pt.m_combinedFriction = btManifoldResult::calculateCombinedFriction(body,sweepResults.m_hitCollisionObject);
+ pt.m_positionWorldOnA = body->getWorldTransform().getOrigin();
+ pt.m_positionWorldOnB = worldPointB;
+
+ }
+ }
+ }
+ }
+ }
+}
void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
{
BT_PROFILE("integrateTransforms");
@@ -944,10 +1057,12 @@ void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
printf("sm2=%f\n",sm2);
}
#else
- //response between two dynamic objects without friction, assuming 0 penetration depth
- btScalar appliedImpulse = 0.f;
- btScalar depth = 0.f;
- appliedImpulse = resolveSingleCollision(body,sweepResults.m_hitCollisionObject,sweepResults.m_hitPointWorld,sweepResults.m_hitNormalWorld,getSolverInfo(), depth);
+
+ //don't apply the collision response right now, it will happen next frame
+ //if you really need to, you can uncomment next 3 lines. Note that is uses zero restitution.
+ //btScalar appliedImpulse = 0.f;
+ //btScalar depth = 0.f;
+ //appliedImpulse = resolveSingleCollision(body,(btCollisionObject*)sweepResults.m_hitCollisionObject,sweepResults.m_hitPointWorld,sweepResults.m_hitNormalWorld,getSolverInfo(), depth);
#endif
@@ -959,8 +1074,46 @@ void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
body->proceedToTransform( predictedTrans);
+
+ }
+
+ }
+
+ ///this should probably be switched on by default, but it is not well tested yet
+ if (m_applySpeculativeContactRestitution)
+ {
+ BT_PROFILE("apply speculative contact restitution");
+ for (int i=0;i<m_predictiveManifolds.size();i++)
+ {
+ btPersistentManifold* manifold = m_predictiveManifolds[i];
+ btRigidBody* body0 = btRigidBody::upcast((btCollisionObject*)manifold->getBody0());
+ btRigidBody* body1 = btRigidBody::upcast((btCollisionObject*)manifold->getBody1());
+
+ for (int p=0;p<manifold->getNumContacts();p++)
+ {
+ const btManifoldPoint& pt = manifold->getContactPoint(p);
+ btScalar combinedRestitution = btManifoldResult::calculateCombinedRestitution(body0, body1);
+
+ if (combinedRestitution>0 && pt.m_appliedImpulse != 0.f)
+ //if (pt.getDistance()>0 && combinedRestitution>0 && pt.m_appliedImpulse != 0.f)
+ {
+ btVector3 imp = -pt.m_normalWorldOnB * pt.m_appliedImpulse* combinedRestitution;
+
+ const btVector3& pos1 = pt.getPositionWorldOnA();
+ const btVector3& pos2 = pt.getPositionWorldOnB();
+
+ btVector3 rel_pos0 = pos1 - body0->getWorldTransform().getOrigin();
+ btVector3 rel_pos1 = pos2 - body1->getWorldTransform().getOrigin();
+
+ if (body0)
+ body0->applyImpulse(imp,rel_pos0);
+ if (body1)
+ body1->applyImpulse(-imp,rel_pos1);
+ }
+ }
}
}
+
}
@@ -976,7 +1129,8 @@ void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
btRigidBody* body = m_nonStaticRigidBodies[i];
if (!body->isStaticOrKinematicObject())
{
- body->integrateVelocities( timeStep);
+ //don't integrate/update velocities here, it happens in the constraint solver
+
//damping
body->applyDamping(timeStep);
@@ -1193,6 +1347,7 @@ void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
}
m_ownsConstraintSolver = false;
m_constraintSolver = solver;
+ m_solverIslandCallback->m_solver = solver;
}
btConstraintSolver* btDiscreteDynamicsWorld::getConstraintSolver()
@@ -1243,11 +1398,65 @@ void btDiscreteDynamicsWorld::serializeRigidBodies(btSerializer* serializer)
}
+
+
+void btDiscreteDynamicsWorld::serializeDynamicsWorldInfo(btSerializer* serializer)
+{
+#ifdef BT_USE_DOUBLE_PRECISION
+ int len = sizeof(btDynamicsWorldDoubleData);
+ btChunk* chunk = serializer->allocate(len,1);
+ btDynamicsWorldDoubleData* worldInfo = (btDynamicsWorldDoubleData*)chunk->m_oldPtr;
+#else//BT_USE_DOUBLE_PRECISION
+ int len = sizeof(btDynamicsWorldFloatData);
+ btChunk* chunk = serializer->allocate(len,1);
+ btDynamicsWorldFloatData* worldInfo = (btDynamicsWorldFloatData*)chunk->m_oldPtr;
+#endif//BT_USE_DOUBLE_PRECISION
+
+ memset(worldInfo ,0x00,len);
+
+ m_gravity.serialize(worldInfo->m_gravity);
+ worldInfo->m_solverInfo.m_tau = getSolverInfo().m_tau;
+ worldInfo->m_solverInfo.m_damping = getSolverInfo().m_damping;
+ worldInfo->m_solverInfo.m_friction = getSolverInfo().m_friction;
+ worldInfo->m_solverInfo.m_timeStep = getSolverInfo().m_timeStep;
+
+ worldInfo->m_solverInfo.m_restitution = getSolverInfo().m_restitution;
+ worldInfo->m_solverInfo.m_maxErrorReduction = getSolverInfo().m_maxErrorReduction;
+ worldInfo->m_solverInfo.m_sor = getSolverInfo().m_sor;
+ worldInfo->m_solverInfo.m_erp = getSolverInfo().m_erp;
+
+ worldInfo->m_solverInfo.m_erp2 = getSolverInfo().m_erp2;
+ worldInfo->m_solverInfo.m_globalCfm = getSolverInfo().m_globalCfm;
+ worldInfo->m_solverInfo.m_splitImpulsePenetrationThreshold = getSolverInfo().m_splitImpulsePenetrationThreshold;
+ worldInfo->m_solverInfo.m_splitImpulseTurnErp = getSolverInfo().m_splitImpulseTurnErp;
+
+ worldInfo->m_solverInfo.m_linearSlop = getSolverInfo().m_linearSlop;
+ worldInfo->m_solverInfo.m_warmstartingFactor = getSolverInfo().m_warmstartingFactor;
+ worldInfo->m_solverInfo.m_maxGyroscopicForce = getSolverInfo().m_maxGyroscopicForce;
+ worldInfo->m_solverInfo.m_singleAxisRollingFrictionThreshold = getSolverInfo().m_singleAxisRollingFrictionThreshold;
+
+ worldInfo->m_solverInfo.m_numIterations = getSolverInfo().m_numIterations;
+ worldInfo->m_solverInfo.m_solverMode = getSolverInfo().m_solverMode;
+ worldInfo->m_solverInfo.m_restingContactRestitutionThreshold = getSolverInfo().m_restingContactRestitutionThreshold;
+ worldInfo->m_solverInfo.m_minimumSolverBatchSize = getSolverInfo().m_minimumSolverBatchSize;
+
+ worldInfo->m_solverInfo.m_splitImpulse = getSolverInfo().m_splitImpulse;
+
+#ifdef BT_USE_DOUBLE_PRECISION
+ const char* structType = "btDynamicsWorldDoubleData";
+#else//BT_USE_DOUBLE_PRECISION
+ const char* structType = "btDynamicsWorldFloatData";
+#endif//BT_USE_DOUBLE_PRECISION
+ serializer->finalizeChunk(chunk,structType,BT_DYNAMICSWORLD_CODE,worldInfo);
+}
+
void btDiscreteDynamicsWorld::serialize(btSerializer* serializer)
{
serializer->startSerialization();
+ serializeDynamicsWorldInfo(serializer);
+
serializeRigidBodies(serializer);
serializeCollisionObjects(serializer);
diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
index 23a38dd2a12..fa934c49d2b 100644
--- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
@@ -25,7 +25,7 @@ class btConstraintSolver;
class btSimulationIslandManager;
class btTypedConstraint;
class btActionInterface;
-
+class btPersistentManifold;
class btIDebugDraw;
struct InplaceSolverIslandCallback;
@@ -34,7 +34,7 @@ struct InplaceSolverIslandCallback;
///btDiscreteDynamicsWorld provides discrete rigid body simulation
///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController
-class btDiscreteDynamicsWorld : public btDynamicsWorld
+ATTRIBUTE_ALIGNED16(class) btDiscreteDynamicsWorld : public btDynamicsWorld
{
protected:
@@ -58,11 +58,14 @@ protected:
bool m_ownsIslandManager;
bool m_ownsConstraintSolver;
bool m_synchronizeAllMotionStates;
+ bool m_applySpeculativeContactRestitution;
btAlignedObjectArray<btActionInterface*> m_actions;
int m_profileTimings;
+ btAlignedObjectArray<btPersistentManifold*> m_predictiveManifolds;
+
virtual void predictUnconstraintMotion(btScalar timeStep);
virtual void integrateTransforms(btScalar timeStep);
@@ -79,14 +82,19 @@ protected:
virtual void internalSingleStepSimulation( btScalar timeStep);
+ void createPredictiveContacts(btScalar timeStep);
virtual void saveKinematicState(btScalar timeStep);
void serializeRigidBodies(btSerializer* serializer);
+ void serializeDynamicsWorldInfo(btSerializer* serializer);
+
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those
btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
@@ -195,6 +203,16 @@ public:
return m_synchronizeAllMotionStates;
}
+ void setApplySpeculativeContactRestitution(bool enable)
+ {
+ m_applySpeculativeContactRestitution = enable;
+ }
+
+ bool getApplySpeculativeContactRestitution() const
+ {
+ return m_applySpeculativeContactRestitution;
+ }
+
///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (see Bullet/Demos/SerializeDemo)
virtual void serialize(btSerializer* serializer);
diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h
index 6b0093371b8..7d5c621f850 100644
--- a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h
@@ -146,6 +146,21 @@ public:
};
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btDynamicsWorldDoubleData
+{
+ btContactSolverInfoDoubleData m_solverInfo;
+ btVector3DoubleData m_gravity;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btDynamicsWorldFloatData
+{
+ btContactSolverInfoFloatData m_solverInfo;
+ btVector3FloatData m_gravity;
+};
+
+
#endif //BT_DYNAMICS_WORLD_H
diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp
index 911b5072394..222f9006687 100644
--- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp
@@ -78,6 +78,7 @@ void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo&
//moved to btCollisionObject
m_friction = constructionInfo.m_friction;
+ m_rollingFriction = constructionInfo.m_rollingFriction;
m_restitution = constructionInfo.m_restitution;
setCollisionShape( constructionInfo.m_collisionShape );
@@ -250,13 +251,29 @@ void btRigidBody::setMassProps(btScalar mass, const btVector3& inertia)
}
-
void btRigidBody::updateInertiaTensor()
{
m_invInertiaTensorWorld = m_worldTransform.getBasis().scaled(m_invInertiaLocal) * m_worldTransform.getBasis().transpose();
}
+btVector3 btRigidBody::computeGyroscopicForce(btScalar maxGyroscopicForce) const
+{
+ btVector3 inertiaLocal;
+ inertiaLocal[0] = 1.f/getInvInertiaDiagLocal()[0];
+ inertiaLocal[1] = 1.f/getInvInertiaDiagLocal()[1];
+ inertiaLocal[2] = 1.f/getInvInertiaDiagLocal()[2];
+ btMatrix3x3 inertiaTensorWorld = getWorldTransform().getBasis().scaled(inertiaLocal) * getWorldTransform().getBasis().transpose();
+ btVector3 tmp = inertiaTensorWorld*getAngularVelocity();
+ btVector3 gf = getAngularVelocity().cross(tmp);
+ btScalar l2 = gf.length2();
+ if (l2>maxGyroscopicForce*maxGyroscopicForce)
+ {
+ gf *= btScalar(1.)/btSqrt(l2)*maxGyroscopicForce;
+ }
+ return gf;
+}
+
void btRigidBody::integrateVelocities(btScalar step)
{
if (isStaticOrKinematicObject())
@@ -300,15 +317,15 @@ void btRigidBody::setCenterOfMassTransform(const btTransform& xform)
}
-bool btRigidBody::checkCollideWithOverride(btCollisionObject* co)
+bool btRigidBody::checkCollideWithOverride(const btCollisionObject* co) const
{
- btRigidBody* otherRb = btRigidBody::upcast(co);
+ const btRigidBody* otherRb = btRigidBody::upcast(co);
if (!otherRb)
return true;
for (int i = 0; i < m_constraintRefs.size(); ++i)
{
- btTypedConstraint* c = m_constraintRefs[i];
+ const btTypedConstraint* c = m_constraintRefs[i];
if (c->isEnabled())
if (&c->getRigidBodyA() == otherRb || &c->getRigidBodyB() == otherRb)
return false;
@@ -317,26 +334,6 @@ bool btRigidBody::checkCollideWithOverride(btCollisionObject* co)
return true;
}
-void btRigidBody::internalWritebackVelocity(btScalar timeStep)
-{
- (void) timeStep;
- if (m_inverseMass)
- {
- setLinearVelocity(getLinearVelocity()+ m_deltaLinearVelocity);
- setAngularVelocity(getAngularVelocity()+m_deltaAngularVelocity);
-
- //correct the position/orientation based on push/turn recovery
- btTransform newTransform;
- btTransformUtil::integrateTransform(getWorldTransform(),m_pushVelocity,m_turnVelocity,timeStep,newTransform);
- setWorldTransform(newTransform);
- //m_originalBody->setCompanionId(-1);
- }
-// m_deltaLinearVelocity.setZero();
-// m_deltaAngularVelocity .setZero();
-// m_pushVelocity.setZero();
-// m_turnVelocity.setZero();
-}
-
void btRigidBody::addConstraintRef(btTypedConstraint* c)
diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h
index 7c121e6df13..f0e07f942af 100644
--- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h
@@ -40,7 +40,11 @@ extern bool gDisableDeactivation;
enum btRigidBodyFlags
{
- BT_DISABLE_WORLD_GRAVITY = 1
+ BT_DISABLE_WORLD_GRAVITY = 1,
+ ///The BT_ENABLE_GYROPSCOPIC_FORCE can easily introduce instability
+ ///So generally it is best to not enable it.
+ ///If really needed, run at a high frequency like 1000 Hertz: ///See Demos/GyroscopicDemo for an example use
+ BT_ENABLE_GYROPSCOPIC_FORCE = 2
};
@@ -93,7 +97,7 @@ class btRigidBody : public btCollisionObject
protected:
- ATTRIBUTE_ALIGNED64(btVector3 m_deltaLinearVelocity);
+ ATTRIBUTE_ALIGNED16(btVector3 m_deltaLinearVelocity);
btVector3 m_deltaAngularVelocity;
btVector3 m_angularFactor;
btVector3 m_invMass;
@@ -125,6 +129,9 @@ public:
///best simulation results when friction is non-zero
btScalar m_friction;
+ ///the m_rollingFriction prevents rounded shapes, such as spheres, cylinders and capsules from rolling forever.
+ ///See Bullet/Demos/RollingFrictionDemo for usage
+ btScalar m_rollingFriction;
///best simulation results using zero restitution.
btScalar m_restitution;
@@ -147,6 +154,7 @@ public:
m_linearDamping(btScalar(0.)),
m_angularDamping(btScalar(0.)),
m_friction(btScalar(0.5)),
+ m_rollingFriction(btScalar(0)),
m_restitution(btScalar(0.)),
m_linearSleepingThreshold(btScalar(0.8)),
m_angularSleepingThreshold(btScalar(1.f)),
@@ -494,7 +502,7 @@ public:
return (getBroadphaseProxy() != 0);
}
- virtual bool checkCollideWithOverride(btCollisionObject* co);
+ virtual bool checkCollideWithOverride(const btCollisionObject* co) const;
void addConstraintRef(btTypedConstraint* c);
void removeConstraintRef(btTypedConstraint* c);
@@ -519,106 +527,7 @@ public:
return m_rigidbodyFlags;
}
- const btVector3& getDeltaLinearVelocity() const
- {
- return m_deltaLinearVelocity;
- }
-
- const btVector3& getDeltaAngularVelocity() const
- {
- return m_deltaAngularVelocity;
- }
-
- const btVector3& getPushVelocity() const
- {
- return m_pushVelocity;
- }
-
- const btVector3& getTurnVelocity() const
- {
- return m_turnVelocity;
- }
-
-
- ////////////////////////////////////////////////
- ///some internal methods, don't use them
-
- btVector3& internalGetDeltaLinearVelocity()
- {
- return m_deltaLinearVelocity;
- }
-
- btVector3& internalGetDeltaAngularVelocity()
- {
- return m_deltaAngularVelocity;
- }
-
- const btVector3& internalGetAngularFactor() const
- {
- return m_angularFactor;
- }
-
- const btVector3& internalGetInvMass() const
- {
- return m_invMass;
- }
-
- btVector3& internalGetPushVelocity()
- {
- return m_pushVelocity;
- }
-
- btVector3& internalGetTurnVelocity()
- {
- return m_turnVelocity;
- }
-
- SIMD_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const
- {
- velocity = getLinearVelocity()+m_deltaLinearVelocity + (getAngularVelocity()+m_deltaAngularVelocity).cross(rel_pos);
- }
-
- SIMD_FORCE_INLINE void internalGetAngularVelocity(btVector3& angVel) const
- {
- angVel = getAngularVelocity()+m_deltaAngularVelocity;
- }
-
-
- //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
- SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude)
- {
- if (m_inverseMass)
- {
- m_deltaLinearVelocity += linearComponent*impulseMagnitude;
- m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
- }
- }
-
- SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude)
- {
- if (m_inverseMass)
- {
- m_pushVelocity += linearComponent*impulseMagnitude;
- m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
- }
- }
-
- void internalWritebackVelocity()
- {
- if (m_inverseMass)
- {
- setLinearVelocity(getLinearVelocity()+ m_deltaLinearVelocity);
- setAngularVelocity(getAngularVelocity()+m_deltaAngularVelocity);
- //m_deltaLinearVelocity.setZero();
- //m_deltaAngularVelocity .setZero();
- //m_originalBody->setCompanionId(-1);
- }
- }
-
-
- void internalWritebackVelocity(btScalar timeStep);
-
-
+ btVector3 computeGyroscopicForce(btScalar maxGyroscopicForce) const;
///////////////////////////////////////////////
diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp
index 5b467883d84..77b475b9682 100644
--- a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp
+++ b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp
@@ -756,14 +756,14 @@ void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3&
if (rayCallback.hasHit())
{
- btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject);
+ const btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject);
if (body && body->hasContactResponse())
{
result.m_hitPointInWorld = rayCallback.m_hitPointWorld;
result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld;
result.m_hitNormalInWorld.normalize();
result.m_distFraction = rayCallback.m_closestHitFraction;
- return body;
+ return (void*)body;
}
}
return 0;
diff --git a/extern/bullet2/src/BulletSoftBody/btDefaultSoftBodySolver.cpp b/extern/bullet2/src/BulletSoftBody/btDefaultSoftBodySolver.cpp
index d1435b65cda..e90d24e6edf 100644
--- a/extern/bullet2/src/BulletSoftBody/btDefaultSoftBodySolver.cpp
+++ b/extern/bullet2/src/BulletSoftBody/btDefaultSoftBodySolver.cpp
@@ -130,9 +130,9 @@ void btDefaultSoftBodySolver::processCollision( btSoftBody* softBody, btSoftBody
}
// For the default solver just leave the soft body to do its collision processing
-void btDefaultSoftBodySolver::processCollision( btSoftBody *softBody, btCollisionObject* collisionObject )
+void btDefaultSoftBodySolver::processCollision( btSoftBody *softBody, const btCollisionObjectWrapper* collisionObjectWrap )
{
- softBody->defaultCollisionHandler( collisionObject );
+ softBody->defaultCollisionHandler( collisionObjectWrap );
} // btDefaultSoftBodySolver::processCollision
diff --git a/extern/bullet2/src/BulletSoftBody/btDefaultSoftBodySolver.h b/extern/bullet2/src/BulletSoftBody/btDefaultSoftBodySolver.h
index 7d9092ce5b9..1c17ffcbb2b 100644
--- a/extern/bullet2/src/BulletSoftBody/btDefaultSoftBodySolver.h
+++ b/extern/bullet2/src/BulletSoftBody/btDefaultSoftBodySolver.h
@@ -19,7 +19,7 @@ subject to the following restrictions:
#include "BulletSoftBody/btSoftBodySolvers.h"
#include "btSoftBodySolverVertexBuffer.h"
-
+struct btCollisionObjectWrapper;
class btDefaultSoftBodySolver : public btSoftBodySolver
{
@@ -54,7 +54,7 @@ public:
virtual void copySoftBodyToVertexBuffer( const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer );
- virtual void processCollision( btSoftBody *, btCollisionObject* );
+ virtual void processCollision( btSoftBody *, const btCollisionObjectWrapper* );
virtual void processCollision( btSoftBody*, btSoftBody* );
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp
index 9c06841801c..e8c8fdb6402 100644
--- a/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp
+++ b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp
@@ -105,12 +105,12 @@ void btSoftBody::initDefaults()
/* Collision shape */
///for now, create a collision shape internally
m_collisionShape = new btSoftBodyCollisionShape(this);
- m_collisionShape->setMargin(0.25);
+ m_collisionShape->setMargin(0.25f);
m_initialWorldTransform.setIdentity();
m_windVelocity = btVector3(0,0,0);
-
+ m_restLengthScale = btScalar(1.0);
}
//
@@ -460,8 +460,8 @@ void btSoftBody::addAeroForceToNode(const btVector3& windVelocity,int nodeInde
const btScalar dt = m_sst.sdt;
const btScalar kLF = m_cfg.kLF;
const btScalar kDG = m_cfg.kDG;
- const btScalar kPR = m_cfg.kPR;
- const btScalar kVC = m_cfg.kVC;
+ //const btScalar kPR = m_cfg.kPR;
+ //const btScalar kVC = m_cfg.kVC;
const bool as_lift = kLF>0;
const bool as_drag = kDG>0;
const bool as_aero = as_lift || as_drag;
@@ -501,10 +501,22 @@ void btSoftBody::addAeroForceToNode(const btVector3& windVelocity,int nodeInde
fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
// Check angle of attack
- // cos(10º) = 0.98480
+ // cos(10º) = 0.98480
if ( 0 < n_dot_v && n_dot_v < 0.98480f)
fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f-n_dot_v*n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
+ // Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
+ btVector3 del_v_by_fDrag = fDrag*n.m_im*m_sst.sdt;
+ btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2();
+ btScalar v_len2 = n.m_v.length2();
+
+ if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0)
+ {
+ btScalar del_v_by_fDrag_len = del_v_by_fDrag.length();
+ btScalar v_len = n.m_v.length();
+ fDrag *= btScalar(0.8)*(v_len / del_v_by_fDrag_len);
+ }
+
n.m_f += fDrag;
n.m_f += fLift;
}
@@ -535,8 +547,8 @@ void btSoftBody::addAeroForceToFace(const btVector3& windVelocity,int faceInde
const btScalar dt = m_sst.sdt;
const btScalar kLF = m_cfg.kLF;
const btScalar kDG = m_cfg.kDG;
- const btScalar kPR = m_cfg.kPR;
- const btScalar kVC = m_cfg.kVC;
+// const btScalar kPR = m_cfg.kPR;
+// const btScalar kVC = m_cfg.kVC;
const bool as_lift = kLF>0;
const bool as_drag = kDG>0;
const bool as_aero = as_lift || as_drag;
@@ -575,7 +587,7 @@ void btSoftBody::addAeroForceToFace(const btVector3& windVelocity,int faceInde
fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
// Check angle of attack
- // cos(10º) = 0.98480
+ // cos(10º) = 0.98480
if ( 0 < n_dot_v && n_dot_v < 0.98480f)
fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f-n_dot_v*n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
@@ -586,6 +598,18 @@ void btSoftBody::addAeroForceToFace(const btVector3& windVelocity,int faceInde
{
if (f.m_n[j]->m_im>0)
{
+ // Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
+ btVector3 del_v_by_fDrag = fDrag*f.m_n[j]->m_im*m_sst.sdt;
+ btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2();
+ btScalar v_len2 = f.m_n[j]->m_v.length2();
+
+ if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0)
+ {
+ btScalar del_v_by_fDrag_len = del_v_by_fDrag.length();
+ btScalar v_len = f.m_n[j]->m_v.length();
+ fDrag *= btScalar(0.8)*(v_len / del_v_by_fDrag_len);
+ }
+
f.m_n[j]->m_f += fDrag;
f.m_n[j]->m_f += fLift;
}
@@ -817,6 +841,27 @@ void btSoftBody::scale(const btVector3& scl)
}
//
+btScalar btSoftBody::getRestLengthScale()
+{
+ return m_restLengthScale;
+}
+
+//
+void btSoftBody::setRestLengthScale(btScalar restLengthScale)
+{
+ for(int i=0, ni=m_links.size(); i<ni; ++i)
+ {
+ Link& l=m_links[i];
+ l.m_rl = l.m_rl / m_restLengthScale * restLengthScale;
+ l.m_c1 = l.m_rl*l.m_rl;
+ }
+ m_restLengthScale = restLengthScale;
+
+ if (getActivationState() == ISLAND_SLEEPING)
+ activate();
+}
+
+//
void btSoftBody::setPose(bool bvolume,bool bframe)
{
m_pose.m_bvolume = bvolume;
@@ -863,9 +908,20 @@ void btSoftBody::setPose(bool bvolume,bool bframe)
m_pose.m_aqq[2]+=mq.z()*q;
}
m_pose.m_aqq=m_pose.m_aqq.inverse();
+
updateConstants();
}
+void btSoftBody::resetLinkRestLengths()
+{
+ for(int i=0, ni=m_links.size();i<ni;++i)
+ {
+ Link& l = m_links[i];
+ l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
+ l.m_c1 = l.m_rl*l.m_rl;
+ }
+}
+
//
btScalar btSoftBody::getVolume() const
{
@@ -1388,12 +1444,12 @@ void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut)
m=mc*f;
}
else
- { a.m_im/=0.5;m=1/a.m_im; }
+ { a.m_im/=0.5f;m=1/a.m_im; }
}
else
{
if(b.m_im>0)
- { b.m_im/=0.5;m=1/b.m_im; }
+ { b.m_im/=0.5f;m=1/b.m_im; }
else
m=0;
}
@@ -1473,7 +1529,7 @@ void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut)
{
const btVector3 v=m_nodes[i].m_v;
btScalar m=getMass(i);
- if(m>0) { m*=0.5;m_nodes[i].m_im/=0.5; }
+ if(m>0) { m*=0.5f;m_nodes[i].m_im/=0.5f; }
appendNode(x,m);
cnodes[i]=m_nodes.size()-1;
m_nodes[cnodes[i]].m_v=v;
@@ -1587,7 +1643,7 @@ bool btSoftBody::cutLink(int node0,int node1,btScalar position)
{
bool done=false;
int i,ni;
- const btVector3 d=m_nodes[node0].m_x-m_nodes[node1].m_x;
+// const btVector3 d=m_nodes[node0].m_x-m_nodes[node1].m_x;
const btVector3 x=Lerp(m_nodes[node0].m_x,m_nodes[node1].m_x,position);
const btVector3 v=Lerp(m_nodes[node0].m_v,m_nodes[node1].m_v,position);
const btScalar m=1;
@@ -2171,15 +2227,18 @@ btVector3 btSoftBody::evaluateCom() const
}
//
-bool btSoftBody::checkContact( btCollisionObject* colObj,
+bool btSoftBody::checkContact( const btCollisionObjectWrapper* colObjWrap,
const btVector3& x,
btScalar margin,
btSoftBody::sCti& cti) const
{
btVector3 nrm;
- btCollisionShape *shp = colObj->getCollisionShape();
- btRigidBody *tmpRigid = btRigidBody::upcast(colObj);
- const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObj->getWorldTransform();
+ const btCollisionShape *shp = colObjWrap->getCollisionShape();
+// const btRigidBody *tmpRigid = btRigidBody::upcast(colObjWrap->getCollisionObject());
+ //const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObjWrap->getWorldTransform();
+ const btTransform &wtr = colObjWrap->getWorldTransform();
+ //todo: check which transform is needed here
+
btScalar dst =
m_worldInfo->m_sparsesdf.Evaluate(
wtr.invXform(x),
@@ -2188,7 +2247,7 @@ bool btSoftBody::checkContact( btCollisionObject* colObj,
margin);
if(dst<0)
{
- cti.m_colObj = colObj;
+ cti.m_colObj = colObjWrap->getCollisionObject();
cti.m_normal = wtr.getBasis()*nrm;
cti.m_offset = -btDot( cti.m_normal, x - cti.m_normal * dst );
return(true);
@@ -2304,51 +2363,93 @@ void btSoftBody::updatePose()
}
//
-void btSoftBody::updateConstants()
+void btSoftBody::updateArea(bool averageArea)
{
int i,ni;
- /* Links */
- for(i=0,ni=m_links.size();i<ni;++i)
- {
- Link& l=m_links[i];
- Material& m=*l.m_material;
- l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
- l.m_c0 = (l.m_n[0]->m_im+l.m_n[1]->m_im)/m.m_kLST;
- l.m_c1 = l.m_rl*l.m_rl;
- }
- /* Faces */
+ /* Face area */
for(i=0,ni=m_faces.size();i<ni;++i)
{
Face& f=m_faces[i];
f.m_ra = AreaOf(f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x);
}
- /* Area's */
- btAlignedObjectArray<int> counts;
- counts.resize(m_nodes.size(),0);
- for(i=0,ni=m_nodes.size();i<ni;++i)
+
+ /* Node area */
+
+ if (averageArea)
{
- m_nodes[i].m_area = 0;
+ btAlignedObjectArray<int> counts;
+ counts.resize(m_nodes.size(),0);
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ m_nodes[i].m_area = 0;
+ }
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ btSoftBody::Face& f=m_faces[i];
+ for(int j=0;j<3;++j)
+ {
+ const int index=(int)(f.m_n[j]-&m_nodes[0]);
+ counts[index]++;
+ f.m_n[j]->m_area+=btFabs(f.m_ra);
+ }
+ }
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ if(counts[i]>0)
+ m_nodes[i].m_area/=(btScalar)counts[i];
+ else
+ m_nodes[i].m_area=0;
+ }
}
- for(i=0,ni=m_faces.size();i<ni;++i)
+ else
{
- btSoftBody::Face& f=m_faces[i];
- for(int j=0;j<3;++j)
+ // initialize node area as zero
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ m_nodes[i].m_area=0;
+ }
+
+ for(i=0,ni=m_faces.size();i<ni;++i)
{
- const int index=(int)(f.m_n[j]-&m_nodes[0]);
- counts[index]++;
- f.m_n[j]->m_area+=btFabs(f.m_ra);
+ btSoftBody::Face& f=m_faces[i];
+
+ for(int j=0;j<3;++j)
+ {
+ f.m_n[j]->m_area += f.m_ra;
+ }
+ }
+
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ m_nodes[i].m_area *= 0.3333333f;
}
}
- for(i=0,ni=m_nodes.size();i<ni;++i)
+}
+
+
+void btSoftBody::updateLinkConstants()
+{
+ int i,ni;
+
+ /* Links */
+ for(i=0,ni=m_links.size();i<ni;++i)
{
- if(counts[i]>0)
- m_nodes[i].m_area/=(btScalar)counts[i];
- else
- m_nodes[i].m_area=0;
+ Link& l=m_links[i];
+ Material& m=*l.m_material;
+ l.m_c0 = (l.m_n[0]->m_im+l.m_n[1]->m_im)/m.m_kLST;
}
}
+void btSoftBody::updateConstants()
+{
+ resetLinkRestLengths();
+ updateLinkConstants();
+ updateArea();
+}
+
+
+
//
void btSoftBody::initializeClusters()
{
@@ -2817,7 +2918,7 @@ void btSoftBody::applyForces()
{
BT_PROFILE("SoftBody applyForces");
- const btScalar dt = m_sst.sdt;
+// const btScalar dt = m_sst.sdt;
const btScalar kLF = m_cfg.kLF;
const btScalar kDG = m_cfg.kDG;
const btScalar kPR = m_cfg.kPR;
@@ -2828,10 +2929,10 @@ void btSoftBody::applyForces()
const bool as_volume = kVC>0;
const bool as_aero = as_lift ||
as_drag ;
- const bool as_vaero = as_aero &&
- (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
- const bool as_faero = as_aero &&
- (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
+ //const bool as_vaero = as_aero &&
+ // (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
+ //const bool as_faero = as_aero &&
+ // (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
const bool use_medium = as_aero;
const bool use_volume = as_pressure ||
as_volume ;
@@ -2874,7 +2975,7 @@ void btSoftBody::applyForces()
/* Per face forces */
for(i=0,ni=m_faces.size();i<ni;++i)
{
- btSoftBody::Face& f=m_faces[i];
+ // btSoftBody::Face& f=m_faces[i];
/* Aerodynamics */
addAeroForceToFace(m_windVelocity, i);
@@ -2910,9 +3011,8 @@ void btSoftBody::PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti)
{
const RContact& c = psb->m_rcontacts[i];
const sCti& cti = c.m_cti;
-
if (cti.m_colObj->hasContactResponse()) {
- btRigidBody* tmpRigid = btRigidBody::upcast(cti.m_colObj);
+ btRigidBody* tmpRigid = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
const btVector3 va = tmpRigid ? tmpRigid->getVelocityInLocalPoint(c.m_c1)*dt : btVector3(0,0,0);
const btVector3 vb = c.m_node->m_x-c.m_node->m_q;
const btVector3 vr = vb-va;
@@ -3033,7 +3133,7 @@ btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver)
}
//
-void btSoftBody::defaultCollisionHandler(btCollisionObject* pco)
+void btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap)
{
switch(m_cfg.collisions&fCollision::RVSmask)
@@ -3041,22 +3141,22 @@ void btSoftBody::defaultCollisionHandler(btCollisionObject* pco)
case fCollision::SDF_RS:
{
btSoftColliders::CollideSDF_RS docollide;
- btRigidBody* prb1=btRigidBody::upcast(pco);
- btTransform wtr=pco->getWorldTransform();
+ btRigidBody* prb1=(btRigidBody*) btRigidBody::upcast(pcoWrap->getCollisionObject());
+ btTransform wtr=pcoWrap->getWorldTransform();
- const btTransform ctr=pco->getWorldTransform();
+ const btTransform ctr=pcoWrap->getWorldTransform();
const btScalar timemargin=(wtr.getOrigin()-ctr.getOrigin()).length();
const btScalar basemargin=getCollisionShape()->getMargin();
btVector3 mins;
btVector3 maxs;
ATTRIBUTE_ALIGNED16(btDbvtVolume) volume;
- pco->getCollisionShape()->getAabb( pco->getWorldTransform(),
+ pcoWrap->getCollisionShape()->getAabb( pcoWrap->getWorldTransform(),
mins,
maxs);
volume=btDbvtVolume::FromMM(mins,maxs);
volume.Expand(btVector3(basemargin,basemargin,basemargin));
docollide.psb = this;
- docollide.m_colObj1 = pco;
+ docollide.m_colObj1Wrap = pcoWrap;
docollide.m_rigidBody = prb1;
docollide.dynmargin = basemargin+timemargin;
@@ -3067,7 +3167,7 @@ void btSoftBody::defaultCollisionHandler(btCollisionObject* pco)
case fCollision::CL_RS:
{
btSoftColliders::CollideCL_RS collider;
- collider.Process(this,pco);
+ collider.ProcessColObj(this,pcoWrap);
}
break;
}
@@ -3086,7 +3186,7 @@ void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
if (this!=psb || psb->m_cfg.collisions&fCollision::CL_SELF)
{
btSoftColliders::CollideCL_SS docollide;
- docollide.Process(this,psb);
+ docollide.ProcessSoftSoft(this,psb);
}
}
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.h b/extern/bullet2/src/BulletSoftBody/btSoftBody.h
index ba589486f26..2116c34f06d 100644
--- a/extern/bullet2/src/BulletSoftBody/btSoftBody.h
+++ b/extern/bullet2/src/BulletSoftBody/btSoftBody.h
@@ -69,7 +69,7 @@ struct btSoftBodyWorldInfo
class btSoftBody : public btCollisionObject
{
public:
- btAlignedObjectArray<class btCollisionObject*> m_collisionDisabledObjects;
+ btAlignedObjectArray<const class btCollisionObject*> m_collisionDisabledObjects;
// The solver object that handles this soft body
btSoftBodySolver *m_softBodySolver;
@@ -182,7 +182,7 @@ public:
/* sCti is Softbody contact info */
struct sCti
{
- btCollisionObject* m_colObj; /* Rigid body */
+ const btCollisionObject* m_colObj; /* Rigid body */
btVector3 m_normal; /* Outward normal */
btScalar m_offset; /* Offset from origin */
};
@@ -374,13 +374,13 @@ public:
{
Cluster* m_soft;
btRigidBody* m_rigid;
- btCollisionObject* m_collisionObject;
+ const btCollisionObject* m_collisionObject;
Body() : m_soft(0),m_rigid(0),m_collisionObject(0) {}
Body(Cluster* p) : m_soft(p),m_rigid(0),m_collisionObject(0) {}
- Body(btCollisionObject* colObj) : m_soft(0),m_collisionObject(colObj)
+ Body(const btCollisionObject* colObj) : m_soft(0),m_collisionObject(colObj)
{
- m_rigid = btRigidBody::upcast(m_collisionObject);
+ m_rigid = (btRigidBody*)btRigidBody::upcast(m_collisionObject);
}
void activate() const
@@ -671,6 +671,9 @@ public:
btTransform m_initialWorldTransform;
btVector3 m_windVelocity;
+
+ btScalar m_restLengthScale;
+
//
// Api
//
@@ -810,9 +813,15 @@ public:
void rotate( const btQuaternion& rot);
/* Scale */
void scale( const btVector3& scl);
+ /* Get link resting lengths scale */
+ btScalar getRestLengthScale();
+ /* Scale resting length of all springs */
+ void setRestLengthScale(btScalar restLength);
/* Set current state as pose */
void setPose( bool bvolume,
bool bframe);
+ /* Set current link lengths as resting lengths */
+ void resetLinkRestLengths();
/* Return the volume */
btScalar getVolume() const;
/* Cluster count */
@@ -867,7 +876,7 @@ public:
/* integrateMotion */
void integrateMotion();
/* defaultCollisionHandlers */
- void defaultCollisionHandler(btCollisionObject* pco);
+ void defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap);
void defaultCollisionHandler(btSoftBody* psb);
@@ -949,11 +958,13 @@ public:
btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const;
void initializeFaceTree();
btVector3 evaluateCom() const;
- bool checkContact(btCollisionObject* colObj,const btVector3& x,btScalar margin,btSoftBody::sCti& cti) const;
+ bool checkContact(const btCollisionObjectWrapper* colObjWrap,const btVector3& x,btScalar margin,btSoftBody::sCti& cti) const;
void updateNormals();
void updateBounds();
void updatePose();
void updateConstants();
+ void updateLinkConstants();
+ void updateArea(bool averageArea = true);
void initializeClusters();
void updateClusters();
void cleanupClusters();
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp
index d99be3b8138..9f0d44526bf 100644
--- a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp
+++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp
@@ -25,7 +25,7 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
-
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
#include "LinearMath/btIDebugDraw.h"
@@ -34,10 +34,10 @@ subject to the following restrictions:
#define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.06)//make this configurable
-btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
+btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped)
: btCollisionAlgorithm(ci),
m_isSwapped(isSwapped),
-m_btSoftBodyTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped)
+m_btSoftBodyTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped)
{
}
@@ -49,12 +49,12 @@ btSoftBodyConcaveCollisionAlgorithm::~btSoftBodyConcaveCollisionAlgorithm()
-btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped):
+btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped):
m_dispatcher(dispatcher),
m_dispatchInfoPtr(0)
{
- m_softBody = (btSoftBody*) (isSwapped? body1:body0);
- m_triBody = isSwapped? body0:body1;
+ m_softBody = (isSwapped? (btSoftBody*)body1Wrap->getCollisionObject():(btSoftBody*)body0Wrap->getCollisionObject());
+ m_triBody = isSwapped? body0Wrap->getCollisionObject():body1Wrap->getCollisionObject();
//
// create the manifold from the dispatcher 'manifold pool'
@@ -90,7 +90,7 @@ void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId,
{
//just for debugging purposes
//printf("triangle %d",m_triangleCount++);
- btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBody);
+
btCollisionAlgorithmConstructionInfo ci;
ci.m_dispatcher1 = m_dispatcher;
@@ -98,7 +98,7 @@ void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId,
if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe))
{
btVector3 color(1,1,0);
- btTransform& tr = ob->getWorldTransform();
+ const btTransform& tr = m_triBody->getWorldTransform();
m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color);
m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color);
m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
@@ -115,18 +115,18 @@ void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId,
btAssert(tm);
//copy over user pointers to temporary shape
- tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer());
-
- btCollisionShape* tmpShape = ob->getCollisionShape();
- ob->internalSetTemporaryCollisionShape( tm );
+ tm->setUserPointer(m_triBody->getCollisionShape()->getUserPointer());
+ btCollisionObjectWrapper softBody(0,m_softBody->getCollisionShape(),m_softBody,m_softBody->getWorldTransform(),-1,-1);
+ //btCollisionObjectWrapper triBody(0,tm, ob, btTransform::getIdentity());//ob->getWorldTransform());//??
+ btCollisionObjectWrapper triBody(0,tm, m_triBody, m_triBody->getWorldTransform(),partId, triangleIndex);
- btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);//m_manifoldPtr);
+ btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody,&triBody,0);//m_manifoldPtr);
- colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
+ colAlgo->processCollision(&softBody,&triBody,*m_dispatchInfoPtr,m_resultOut);
colAlgo->~btCollisionAlgorithm();
ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
- ob->internalSetTemporaryCollisionShape( tmpShape);
+
return;
}
@@ -158,24 +158,18 @@ void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId,
// tm.setMargin(m_collisionMarginTriangle);
//copy over user pointers to temporary shape
- tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer());
+ tm->setUserPointer(m_triBody->getCollisionShape()->getUserPointer());
- btCollisionShape* tmpShape = ob->getCollisionShape();
- ob->internalSetTemporaryCollisionShape( tm );
+
+ btCollisionObjectWrapper softBody(0,m_softBody->getCollisionShape(),m_softBody,m_softBody->getWorldTransform(),-1,-1);
+ btCollisionObjectWrapper triBody(0,tm, m_triBody, m_triBody->getWorldTransform(),partId, triangleIndex);//btTransform::getIdentity());//??
+ btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody,&triBody,0);//m_manifoldPtr);
- btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);//m_manifoldPtr);
- ///this should use the btDispatcher, so the actual registered algorithm is used
- // btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody);
-
- //m_resultOut->setShapeIdentifiersB(partId,triangleIndex);
- // cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
- colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
+ colAlgo->processCollision(&softBody,&triBody,*m_dispatchInfoPtr,m_resultOut);
colAlgo->~btCollisionAlgorithm();
ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
-
- ob->internalSetTemporaryCollisionShape( tmpShape );
triIndex.m_childShape = tm;
m_shapeCache.insert(triKey,triIndex);
@@ -187,7 +181,7 @@ void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId,
-void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btCollisionObjectWrapper* triBodyWrap, const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
m_dispatchInfoPtr = &dispatchInfo;
m_collisionMarginTriangle = collisionMarginTriangle+btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION);
@@ -204,7 +198,7 @@ void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMargin
softTransform.setOrigin(softBodyCenter);
btTransform convexInTriangleSpace;
- convexInTriangleSpace = m_triBody->getWorldTransform().inverse() * softTransform;
+ convexInTriangleSpace = triBodyWrap->getWorldTransform().inverse() * softTransform;
btTransformAabb(halfExtents,m_collisionMarginTriangle,convexInTriangleSpace,m_aabbMin,m_aabbMax);
}
@@ -214,33 +208,28 @@ void btSoftBodyConcaveCollisionAlgorithm::clearCache()
}
-void btSoftBodyConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btSoftBodyConcaveCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
//btCollisionObject* convexBody = m_isSwapped ? body1 : body0;
- btCollisionObject* triBody = m_isSwapped ? body0 : body1;
+ const btCollisionObjectWrapper* triBody = m_isSwapped ? body0Wrap : body1Wrap;
if (triBody->getCollisionShape()->isConcave())
{
- btCollisionObject* triOb = triBody;
- btConcaveShape* concaveShape = static_cast<btConcaveShape*>( triOb->getCollisionShape());
+ const btCollisionObject* triOb = triBody->getCollisionObject();
+ const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>( triOb->getCollisionShape());
// if (convexBody->getCollisionShape()->isConvex())
{
btScalar collisionMarginTriangle = concaveShape->getMargin();
// resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr);
- m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut);
-
- //Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here.
- //m_dispatcher->clearManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr);
-
- // m_btSoftBodyTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody);
-
+ m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,triBody,dispatchInfo,resultOut);
+
concaveShape->processAllTriangles( &m_btSoftBodyTriangleCallback,m_btSoftBodyTriangleCallback.getAabbMin(),m_btSoftBodyTriangleCallback.getAabbMax());
// resultOut->refreshContactPoints();
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h
index 8a09fff2a37..11c7b88f98e 100644
--- a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h
+++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h
@@ -65,7 +65,7 @@ struct btTriIndex
class btSoftBodyTriangleCallback : public btTriangleCallback
{
btSoftBody* m_softBody;
- btCollisionObject* m_triBody;
+ const btCollisionObject* m_triBody;
btVector3 m_aabbMin;
btVector3 m_aabbMax ;
@@ -83,9 +83,9 @@ public:
// btPersistentManifold* m_manifoldPtr;
- btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
+ btSoftBodyTriangleCallback(btDispatcher* dispatcher,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
- void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btCollisionObjectWrapper* triObjWrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual ~btSoftBodyTriangleCallback();
@@ -117,11 +117,11 @@ class btSoftBodyConcaveCollisionAlgorithm : public btCollisionAlgorithm
public:
- btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
+ btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped);
virtual ~btSoftBodyConcaveCollisionAlgorithm();
- virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
@@ -134,19 +134,19 @@ public:
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm));
- return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0,body1,false);
+ return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,false);
}
};
struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm));
- return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0,body1,true);
+ return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0Wrap,body1Wrap,true);
}
};
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyData.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyData.h
index 40dc65c3d8c..87d8841cfa4 100644
--- a/extern/bullet2/src/BulletSoftBody/btSoftBodyData.h
+++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyData.h
@@ -17,7 +17,7 @@ subject to the following restrictions:
#define BT_SOFTBODY_FLOAT_DATA
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-
+#include "BulletDynamics/Dynamics/btRigidBody.h"
struct SoftBodyMaterialData
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h
index 5ef8db19396..19d0543ef9e 100644
--- a/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h
+++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h
@@ -21,6 +21,7 @@ subject to the following restrictions:
#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btPolarDecomposition.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
@@ -614,32 +615,8 @@ private:
//
static inline int PolarDecompose( const btMatrix3x3& m,btMatrix3x3& q,btMatrix3x3& s)
{
- static const btScalar half=(btScalar)0.5;
- static const btScalar accuracy=(btScalar)0.0001;
- static const int maxiterations=16;
- int i=0;
- btScalar det=0;
- q = Mul(m,1/btVector3(m[0][0],m[1][1],m[2][2]).length());
- det = q.determinant();
- if(!btFuzzyZero(det))
- {
- for(;i<maxiterations;++i)
- {
- q=Mul(Add(q,Mul(q.adjoint(),1/det).transpose()),half);
- const btScalar ndet=q.determinant();
- if(Sq(ndet-det)>accuracy) det=ndet; else break;
- }
- /* Final orthogonalization */
- Orthogonalize(q);
- /* Compute 'S' */
- s=q.transpose()*m;
- }
- else
- {
- q.setIdentity();
- s.setIdentity();
- }
- return(i);
+ static const btPolarDecomposition polar;
+ return polar.decompose(m, q, s);
}
//
@@ -666,7 +643,7 @@ struct btSoftColliders
threshold =(btScalar)0;
}
bool SolveContact( const btGjkEpaSolver2::sResults& res,
- btSoftBody::Body ba,btSoftBody::Body bb,
+ btSoftBody::Body ba,const btSoftBody::Body bb,
btSoftBody::CJoint& joint)
{
if(res.distance<m_margin)
@@ -702,7 +679,7 @@ struct btSoftColliders
joint.m_normal = norm;
// printf("normal=%f,%f,%f\n",res.normal.getX(),res.normal.getY(),res.normal.getZ());
joint.m_delete = false;
- joint.m_friction = fv.length2()<(-rvac*friction)?1:friction;
+ joint.m_friction = fv.length2()<(rvac*friction*rvac*friction)?1:friction;
joint.m_massmatrix = ImpulseMatrix( ba.invMass(),ba.invWorldInertia(),joint.m_rpos[0],
bb.invMass(),bb.invWorldInertia(),joint.m_rpos[1]);
@@ -717,30 +694,30 @@ struct btSoftColliders
struct CollideCL_RS : ClusterBase
{
btSoftBody* psb;
-
- btCollisionObject* m_colObj;
+ const btCollisionObjectWrapper* m_colObjWrap;
+
void Process(const btDbvtNode* leaf)
{
btSoftBody::Cluster* cluster=(btSoftBody::Cluster*)leaf->data;
btSoftClusterCollisionShape cshape(cluster);
- const btConvexShape* rshape=(const btConvexShape*)m_colObj->getCollisionShape();
+ const btConvexShape* rshape=(const btConvexShape*)m_colObjWrap->getCollisionShape();
///don't collide an anchored cluster with a static/kinematic object
- if(m_colObj->isStaticOrKinematicObject() && cluster->m_containsAnchor)
+ if(m_colObjWrap->getCollisionObject()->isStaticOrKinematicObject() && cluster->m_containsAnchor)
return;
btGjkEpaSolver2::sResults res;
if(btGjkEpaSolver2::SignedDistance( &cshape,btTransform::getIdentity(),
- rshape,m_colObj->getWorldTransform(),
+ rshape,m_colObjWrap->getWorldTransform(),
btVector3(1,0,0),res))
{
btSoftBody::CJoint joint;
- if(SolveContact(res,cluster,m_colObj,joint))//prb,joint))
+ if(SolveContact(res,cluster,m_colObjWrap->getCollisionObject(),joint))//prb,joint))
{
btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint();
*pj=joint;psb->m_joints.push_back(pj);
- if(m_colObj->isStaticOrKinematicObject())
+ if(m_colObjWrap->getCollisionObject()->isStaticOrKinematicObject())
{
pj->m_erp *= psb->m_cfg.kSKHR_CL;
pj->m_split *= psb->m_cfg.kSK_SPLT_CL;
@@ -753,19 +730,19 @@ struct btSoftColliders
}
}
}
- void Process(btSoftBody* ps,btCollisionObject* colOb)
+ void ProcessColObj(btSoftBody* ps,const btCollisionObjectWrapper* colObWrap)
{
psb = ps;
- m_colObj = colOb;
+ m_colObjWrap = colObWrap;
idt = ps->m_sst.isdt;
- m_margin = m_colObj->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin();
+ m_margin = m_colObjWrap->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin();
///Bullet rigid body uses multiply instead of minimum to determine combined friction. Some customization would be useful.
- friction = btMin(psb->m_cfg.kDF,m_colObj->getFriction());
+ friction = btMin(psb->m_cfg.kDF,m_colObjWrap->getCollisionObject()->getFriction());
btVector3 mins;
btVector3 maxs;
ATTRIBUTE_ALIGNED16(btDbvtVolume) volume;
- colOb->getCollisionShape()->getAabb(colOb->getWorldTransform(),mins,maxs);
+ colObWrap->getCollisionShape()->getAabb(colObWrap->getWorldTransform(),mins,maxs);
volume=btDbvtVolume::FromMM(mins,maxs);
volume.Expand(btVector3(1,1,1)*m_margin);
ps->m_cdbvt.collideTV(ps->m_cdbvt.m_root,volume,*this);
@@ -815,7 +792,7 @@ struct btSoftColliders
}
}
- void Process(btSoftBody* psa,btSoftBody* psb)
+ void ProcessSoftSoft(btSoftBody* psa,btSoftBody* psb)
{
idt = psa->m_sst.isdt;
//m_margin = (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin())/2;
@@ -840,15 +817,16 @@ struct btSoftColliders
{
const btScalar m=n.m_im>0?dynmargin:stamargin;
btSoftBody::RContact c;
+
if( (!n.m_battach)&&
- psb->checkContact(m_colObj1,n.m_x,m,c.m_cti))
+ psb->checkContact(m_colObj1Wrap,n.m_x,m,c.m_cti))
{
const btScalar ima=n.m_im;
const btScalar imb= m_rigidBody? m_rigidBody->getInvMass() : 0.f;
const btScalar ms=ima+imb;
if(ms>0)
{
- const btTransform& wtr=m_rigidBody?m_rigidBody->getWorldTransform() : m_colObj1->getWorldTransform();
+ const btTransform& wtr=m_rigidBody?m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
static const btMatrix3x3 iwiStatic(0,0,0,0,0,0,0,0,0);
const btMatrix3x3& iwi=m_rigidBody?m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
const btVector3 ra=n.m_x-wtr.getOrigin();
@@ -857,13 +835,13 @@ struct btSoftColliders
const btVector3 vr=vb-va;
const btScalar dn=btDot(vr,c.m_cti.m_normal);
const btVector3 fv=vr-c.m_cti.m_normal*dn;
- const btScalar fc=psb->m_cfg.kDF*m_colObj1->getFriction();
+ const btScalar fc=psb->m_cfg.kDF*m_colObj1Wrap->getCollisionObject()->getFriction();
c.m_node = &n;
c.m_c0 = ImpulseMatrix(psb->m_sst.sdt,ima,imb,iwi,ra);
c.m_c1 = ra;
c.m_c2 = ima*psb->m_sst.sdt;
- c.m_c3 = fv.length2()<(btFabs(dn)*fc)?0:1-fc;
- c.m_c4 = m_colObj1->isStaticOrKinematicObject()?psb->m_cfg.kKHR:psb->m_cfg.kCHR;
+ c.m_c3 = fv.length2()<(dn*fc*dn*fc)?0:1-fc;
+ c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject()?psb->m_cfg.kKHR:psb->m_cfg.kCHR;
psb->m_rcontacts.push_back(c);
if (m_rigidBody)
m_rigidBody->activate();
@@ -871,7 +849,7 @@ struct btSoftColliders
}
}
btSoftBody* psb;
- btCollisionObject* m_colObj1;
+ const btCollisionObjectWrapper* m_colObj1Wrap;
btRigidBody* m_rigidBody;
btScalar dynmargin;
btScalar stamargin;
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodySolvers.h b/extern/bullet2/src/BulletSoftBody/btSoftBodySolvers.h
index 2fcd8b67616..6947bc27d28 100644
--- a/extern/bullet2/src/BulletSoftBody/btSoftBodySolvers.h
+++ b/extern/bullet2/src/BulletSoftBody/btSoftBodySolvers.h
@@ -85,7 +85,7 @@ public:
virtual void updateSoftBodies() = 0;
/** Process a collision between one of the world's soft bodies and another collision object */
- virtual void processCollision( btSoftBody *, btCollisionObject* ) = 0;
+ virtual void processCollision( btSoftBody *, const struct btCollisionObjectWrapper* ) = 0;
/** Process a collision between two soft bodies */
virtual void processCollision( btSoftBody*, btSoftBody* ) = 0;
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp
index bc374c805e7..01c148a2ca8 100644
--- a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp
+++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp
@@ -20,13 +20,14 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "btSoftBody.h"
#include "BulletSoftBody/btSoftBodySolvers.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
///TODO: include all the shapes that the softbody can collide with
///alternatively, implement special case collision algorithms (just like for rigid collision shapes)
//#include <stdio.h>
-btSoftRigidCollisionAlgorithm::btSoftRigidCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* /*col0*/,btCollisionObject* /*col1*/, bool isSwapped)
+btSoftRigidCollisionAlgorithm::btSoftRigidCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* ,const btCollisionObjectWrapper* , bool isSwapped)
: btCollisionAlgorithm(ci),
//m_ownManifold(false),
//m_manifoldPtr(mf),
@@ -52,18 +53,19 @@ btSoftRigidCollisionAlgorithm::~btSoftRigidCollisionAlgorithm()
#include <stdio.h>
-void btSoftRigidCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+void btSoftRigidCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)dispatchInfo;
(void)resultOut;
//printf("btSoftRigidCollisionAlgorithm\n");
-
- btSoftBody* softBody = m_isSwapped? (btSoftBody*)body1 : (btSoftBody*)body0;
- btCollisionObject* rigidCollisionObject = m_isSwapped? body0 : body1;
+// const btCollisionObjectWrapper* softWrap = m_isSwapped?body1Wrap:body0Wrap;
+// const btCollisionObjectWrapper* rigidWrap = m_isSwapped?body0Wrap:body1Wrap;
+ btSoftBody* softBody = m_isSwapped? (btSoftBody*)body1Wrap->getCollisionObject() : (btSoftBody*)body0Wrap->getCollisionObject();
+ const btCollisionObjectWrapper* rigidCollisionObjectWrap = m_isSwapped? body0Wrap : body1Wrap;
- if (softBody->m_collisionDisabledObjects.findLinearSearch(rigidCollisionObject)==softBody->m_collisionDisabledObjects.size())
+ if (softBody->m_collisionDisabledObjects.findLinearSearch(rigidCollisionObjectWrap->getCollisionObject())==softBody->m_collisionDisabledObjects.size())
{
- softBody->getSoftBodySolver()->processCollision(softBody, rigidCollisionObject);
+ softBody->getSoftBodySolver()->processCollision(softBody, rigidCollisionObjectWrap);
}
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h
index 7658e3c2252..a9b513e3639 100644
--- a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h
+++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h
@@ -39,11 +39,11 @@ class btSoftRigidCollisionAlgorithm : public btCollisionAlgorithm
public:
- btSoftRigidCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped);
+ btSoftRigidCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* col0,const btCollisionObjectWrapper* col1Wrap, bool isSwapped);
virtual ~btSoftRigidCollisionAlgorithm();
- virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
@@ -55,15 +55,15 @@ public:
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftRigidCollisionAlgorithm));
if (!m_swapped)
{
- return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0,body1,false);
+ return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,false);
} else
{
- return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0,body1,true);
+ return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0Wrap,body1Wrap,true);
}
}
};
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp
index 8f4be231c13..5f35935450c 100644
--- a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp
+++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp
@@ -353,6 +353,8 @@ void btSoftRigidDynamicsWorld::serialize(btSerializer* serializer)
serializer->startSerialization();
+ serializeDynamicsWorldInfo( serializer);
+
serializeSoftBodies(serializer);
serializeRigidBodies(serializer);
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp
index 1b8cfa72371..72043e69e2f 100644
--- a/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp
+++ b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp
@@ -19,10 +19,11 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletSoftBody/btSoftBodySolvers.h"
#include "btSoftBody.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
#define USE_PERSISTENT_CONTACTS 1
-btSoftSoftCollisionAlgorithm::btSoftSoftCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* /*obj0*/,btCollisionObject* /*obj1*/)
+btSoftSoftCollisionAlgorithm::btSoftSoftCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* /*obj0*/,const btCollisionObjectWrapper* /*obj1*/)
: btCollisionAlgorithm(ci)
//m_ownManifold(false),
//m_manifoldPtr(mf)
@@ -33,10 +34,10 @@ btSoftSoftCollisionAlgorithm::~btSoftSoftCollisionAlgorithm()
{
}
-void btSoftSoftCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
+void btSoftSoftCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
{
- btSoftBody* soft0 = (btSoftBody*)body0;
- btSoftBody* soft1 = (btSoftBody*)body1;
+ btSoftBody* soft0 = (btSoftBody*)body0Wrap->getCollisionObject();
+ btSoftBody* soft1 = (btSoftBody*)body1Wrap->getCollisionObject();
soft0->getSoftBodySolver()->processCollision(soft0, soft1);
}
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h
index 92d683c1dc8..43b1439cc53 100644
--- a/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h
+++ b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h
@@ -38,7 +38,7 @@ public:
btSoftSoftCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btCollisionAlgorithm(ci) {}
- virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
@@ -48,17 +48,17 @@ public:
manifoldArray.push_back(m_manifoldPtr);
}
- btSoftSoftCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
+ btSoftSoftCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
virtual ~btSoftSoftCollisionAlgorithm();
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap)
{
int bbsize = sizeof(btSoftSoftCollisionAlgorithm);
void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
- return new(ptr) btSoftSoftCollisionAlgorithm(0,ci,body0,body1);
+ return new(ptr) btSoftSoftCollisionAlgorithm(0,ci,body0Wrap,body1Wrap);
}
};
diff --git a/extern/bullet2/src/BulletSoftBody/btSparseSDF.h b/extern/bullet2/src/BulletSoftBody/btSparseSDF.h
index 90a26cdf7e3..180e3c218cc 100644
--- a/extern/bullet2/src/BulletSoftBody/btSparseSDF.h
+++ b/extern/bullet2/src/BulletSoftBody/btSparseSDF.h
@@ -58,7 +58,7 @@ struct btSparseSdf
int c[3];
int puid;
unsigned hash;
- btCollisionShape* pclient;
+ const btCollisionShape* pclient;
Cell* next;
};
//
@@ -152,7 +152,7 @@ struct btSparseSdf
}
//
btScalar Evaluate( const btVector3& x,
- btCollisionShape* shape,
+ const btCollisionShape* shape,
btVector3& normal,
btScalar margin)
{
@@ -248,14 +248,14 @@ struct btSparseSdf
}
//
static inline btScalar DistanceToShape(const btVector3& x,
- btCollisionShape* shape)
+ const btCollisionShape* shape)
{
btTransform unit;
unit.setIdentity();
if(shape->isConvex())
{
btGjkEpaSolver2::sResults res;
- btConvexShape* csh=static_cast<btConvexShape*>(shape);
+ const btConvexShape* csh=static_cast<const btConvexShape*>(shape);
return(btGjkEpaSolver2::SignedDistance(x,0,csh,unit,res));
}
return(0);
@@ -282,7 +282,7 @@ struct btSparseSdf
//
- static inline unsigned int Hash(int x,int y,int z,btCollisionShape* shape)
+ static inline unsigned int Hash(int x,int y,int z,const btCollisionShape* shape)
{
struct btS
{
@@ -292,7 +292,7 @@ struct btSparseSdf
btS myset;
- myset.x=x;myset.y=y;myset.z=z;myset.p=shape;
+ myset.x=x;myset.y=y;myset.z=z;myset.p=(void*)shape;
const void* ptr = &myset;
unsigned int result = HsiehHash<sizeof(btS)/4> (ptr);
diff --git a/extern/bullet2/src/LinearMath/btAabbUtil2.h b/extern/bullet2/src/LinearMath/btAabbUtil2.h
index 42b721dea22..d2997b4e65c 100644
--- a/extern/bullet2/src/LinearMath/btAabbUtil2.h
+++ b/extern/bullet2/src/LinearMath/btAabbUtil2.h
@@ -184,9 +184,7 @@ SIMD_FORCE_INLINE void btTransformAabb(const btVector3& halfExtents, btScalar ma
btVector3 halfExtentsWithMargin = halfExtents+btVector3(margin,margin,margin);
btMatrix3x3 abs_b = t.getBasis().absolute();
btVector3 center = t.getOrigin();
- btVector3 extent = btVector3(abs_b[0].dot(halfExtentsWithMargin),
- abs_b[1].dot(halfExtentsWithMargin),
- abs_b[2].dot(halfExtentsWithMargin));
+ btVector3 extent = halfExtentsWithMargin.dot3( abs_b[0], abs_b[1], abs_b[2] );
aabbMinOut = center - extent;
aabbMaxOut = center + extent;
}
@@ -203,9 +201,7 @@ SIMD_FORCE_INLINE void btTransformAabb(const btVector3& localAabbMin,const btVec
btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin);
btMatrix3x3 abs_b = trans.getBasis().absolute();
btVector3 center = trans(localCenter);
- btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
- abs_b[1].dot(localHalfExtents),
- abs_b[2].dot(localHalfExtents));
+ btVector3 extent = localHalfExtents.dot3( abs_b[0], abs_b[1], abs_b[2] );
aabbMinOut = center-extent;
aabbMaxOut = center+extent;
}
diff --git a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp
index c4c0ceb2ed2..a65296c6abe 100644
--- a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp
+++ b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp
@@ -119,7 +119,7 @@ void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filen
real = (char *)sAllocFunc(size + 2*sizeof(void *) + (alignment-1));
if (real) {
- ret = (void*) btAlignPointer((real + 2*sizeof(void *), alignment);
+ ret = (void*) btAlignPointer(real + 2*sizeof(void *), alignment);
*((void **)(ret)-1) = (void *)(real);
*((int*)(ret)-2) = size;
diff --git a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h
index 36090e13c89..24e59ab65d7 100644
--- a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h
+++ b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h
@@ -197,8 +197,26 @@ protected:
m_data[m_size].~T();
}
+
///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument.
///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations.
+ SIMD_FORCE_INLINE void resizeNoInitialize(int newsize)
+ {
+ int curSize = size();
+
+ if (newsize < curSize)
+ {
+ } else
+ {
+ if (newsize > size())
+ {
+ reserve(newsize);
+ }
+ //leave this uninitialized
+ }
+ m_size = newsize;
+ }
+
SIMD_FORCE_INLINE void resize(int newsize, const T& fillData=T())
{
int curSize = size();
@@ -226,7 +244,6 @@ protected:
m_size = newsize;
}
-
SIMD_FORCE_INLINE T& expandNonInitializing( )
{
int sz = size();
diff --git a/extern/bullet2/src/LinearMath/btConvexHull.cpp b/extern/bullet2/src/LinearMath/btConvexHull.cpp
index 532d76d881f..2ae855dbc1f 100644
--- a/extern/bullet2/src/LinearMath/btConvexHull.cpp
+++ b/extern/bullet2/src/LinearMath/btConvexHull.cpp
@@ -22,13 +22,6 @@ subject to the following restrictions:
-template <class T>
-void Swap(T &a,T &b)
-{
- T tmp = a;
- a=b;
- b=tmp;
-}
//----------------------------------
@@ -518,7 +511,7 @@ int4 HullLibrary::FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectAr
if(p3==p0||p3==p1||p3==p2)
return int4(-1,-1,-1,-1);
btAssert(!(p0==p1||p0==p2||p0==p3||p1==p2||p1==p3||p2==p3));
- if(btDot(verts[p3]-verts[p0],btCross(verts[p1]-verts[p0],verts[p2]-verts[p0])) <0) {Swap(p2,p3);}
+ if(btDot(verts[p3]-verts[p0],btCross(verts[p1]-verts[p0],verts[p2]-verts[p0])) <0) {btSwap(p2,p3);}
return int4(p0,p1,p2,p3);
}
@@ -570,7 +563,7 @@ int HullLibrary::calchullgen(btVector3 *verts,int verts_count, int vlimit)
vlimit-=4;
while(vlimit >0 && ((te=extrudable(epsilon)) != 0))
{
- int3 ti=*te;
+ //int3 ti=*te;
int v=te->vmax;
btAssert(v != -1);
btAssert(!isextreme[v]); // wtf we've already done this vertex
diff --git a/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp b/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp
index 4fd81dac107..3fd77df8da5 100644
--- a/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp
+++ b/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp
@@ -1931,11 +1931,15 @@ void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
}
}
-
-static bool pointCmp(const btConvexHullInternal::Point32& p, const btConvexHullInternal::Point32& q)
+class pointCmp
{
- return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z))));
-}
+ public:
+
+ bool operator() ( const btConvexHullInternal::Point32& p, const btConvexHullInternal::Point32& q ) const
+ {
+ return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z))));
+ }
+};
void btConvexHullInternal::compute(const void* coords, bool doubleCoords, int stride, int count)
{
@@ -2026,7 +2030,7 @@ void btConvexHullInternal::compute(const void* coords, bool doubleCoords, int st
points[i].index = i;
}
}
- points.quickSort(pointCmp);
+ points.quickSort(pointCmp());
vertexPool.reset();
vertexPool.setArraySize(count);
diff --git a/extern/bullet2/src/LinearMath/btDefaultMotionState.h b/extern/bullet2/src/LinearMath/btDefaultMotionState.h
index a6b7ef15ac8..c90b749230c 100644
--- a/extern/bullet2/src/LinearMath/btDefaultMotionState.h
+++ b/extern/bullet2/src/LinearMath/btDefaultMotionState.h
@@ -4,13 +4,15 @@
#include "btMotionState.h"
///The btDefaultMotionState provides a common implementation to synchronize world transforms with offsets.
-struct btDefaultMotionState : public btMotionState
+ATTRIBUTE_ALIGNED16(struct) btDefaultMotionState : public btMotionState
{
btTransform m_graphicsWorldTrans;
btTransform m_centerOfMassOffset;
btTransform m_startWorldTrans;
void* m_userPointer;
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btDefaultMotionState(const btTransform& startTrans = btTransform::getIdentity(),const btTransform& centerOfMassOffset = btTransform::getIdentity())
: m_graphicsWorldTrans(startTrans),
m_centerOfMassOffset(centerOfMassOffset),
diff --git a/extern/bullet2/src/LinearMath/btGrahamScan2dConvexHull.h b/extern/bullet2/src/LinearMath/btGrahamScan2dConvexHull.h
index d7bd3eb8911..e658c5cf062 100644
--- a/extern/bullet2/src/LinearMath/btGrahamScan2dConvexHull.h
+++ b/extern/bullet2/src/LinearMath/btGrahamScan2dConvexHull.h
@@ -21,9 +21,9 @@ subject to the following restrictions:
#include "btVector3.h"
#include "btAlignedObjectArray.h"
-struct GrahamVector2 : public btVector3
+struct GrahamVector3 : public btVector3
{
- GrahamVector2(const btVector3& org, int orgIndex)
+ GrahamVector3(const btVector3& org, int orgIndex)
:btVector3(org),
m_orgIndex(orgIndex)
{
@@ -39,7 +39,7 @@ struct btAngleCompareFunc {
: m_anchor(anchor)
{
}
- bool operator()(const GrahamVector2& a, const GrahamVector2& b) const {
+ bool operator()(const GrahamVector3& a, const GrahamVector3& b) const {
if (a.m_angle != b.m_angle)
return a.m_angle < b.m_angle;
else
@@ -56,31 +56,38 @@ struct btAngleCompareFunc {
}
};
-inline void GrahamScanConvexHull2D(btAlignedObjectArray<GrahamVector2>& originalPoints, btAlignedObjectArray<GrahamVector2>& hull)
+inline void GrahamScanConvexHull2D(btAlignedObjectArray<GrahamVector3>& originalPoints, btAlignedObjectArray<GrahamVector3>& hull, const btVector3& normalAxis)
{
+ btVector3 axis0,axis1;
+ btPlaneSpace1(normalAxis,axis0,axis1);
+
+
if (originalPoints.size()<=1)
{
for (int i=0;i<originalPoints.size();i++)
hull.push_back(originalPoints[0]);
return;
}
- //step1 : find anchor point with smallest x/y and move it to first location
- //also precompute angles
+ //step1 : find anchor point with smallest projection on axis0 and move it to first location
for (int i=0;i<originalPoints.size();i++)
{
- const btVector3& left = originalPoints[i];
- const btVector3& right = originalPoints[0];
- if (left.x() < right.x() || !(right.x() < left.x()) && left.y() < right.y())
+// const btVector3& left = originalPoints[i];
+// const btVector3& right = originalPoints[0];
+ btScalar projL = originalPoints[i].dot(axis0);
+ btScalar projR = originalPoints[0].dot(axis0);
+ if (projL < projR)
{
originalPoints.swap(0,i);
}
}
- for (int i=0;i<originalPoints.size();i++)
+ //also precompute angles
+ originalPoints[0].m_angle = -1e30f;
+ for (int i=1;i<originalPoints.size();i++)
{
- btVector3 xvec(1,0,0);
+ btVector3 xvec = axis0;
btVector3 ar = originalPoints[i]-originalPoints[0];
- originalPoints[i].m_angle = btCross(xvec, ar).dot(btVector3(0,0,1)) / ar.length();
+ originalPoints[i].m_angle = btCross(xvec, ar).dot(normalAxis) / ar.length();
}
//step 2: sort all points, based on 'angle' with this anchor
@@ -98,7 +105,7 @@ inline void GrahamScanConvexHull2D(btAlignedObjectArray<GrahamVector2>& original
while (!isConvex&& hull.size()>1) {
btVector3& a = hull[hull.size()-2];
btVector3& b = hull[hull.size()-1];
- isConvex = btCross(a-b,a-originalPoints[i]).dot(btVector3(0,0,1))> 0;
+ isConvex = btCross(a-b,a-originalPoints[i]).dot(normalAxis)> 0;
if (!isConvex)
hull.pop_back();
else
diff --git a/extern/bullet2/src/LinearMath/btIDebugDraw.h b/extern/bullet2/src/LinearMath/btIDebugDraw.h
index 935502f844f..a00d7763a75 100644
--- a/extern/bullet2/src/LinearMath/btIDebugDraw.h
+++ b/extern/bullet2/src/LinearMath/btIDebugDraw.h
@@ -280,6 +280,7 @@ class btIDebugDraw
}
}
+
virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btVector3& color)
{
drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMin[2]), color);
diff --git a/extern/bullet2/src/LinearMath/btMatrix3x3.h b/extern/bullet2/src/LinearMath/btMatrix3x3.h
index d0234a04369..d4f5c95aa64 100644
--- a/extern/bullet2/src/LinearMath/btMatrix3x3.h
+++ b/extern/bullet2/src/LinearMath/btMatrix3x3.h
@@ -18,6 +18,18 @@ subject to the following restrictions:
#include "btVector3.h"
#include "btQuaternion.h"
+#include <stdio.h>
+
+#ifdef BT_USE_SSE
+//const __m128 ATTRIBUTE_ALIGNED16(v2220) = {2.0f, 2.0f, 2.0f, 0.0f};
+const __m128 ATTRIBUTE_ALIGNED16(vMPPP) = {-0.0f, +0.0f, +0.0f, +0.0f};
+#endif
+
+#if defined(BT_USE_SSE) || defined(BT_USE_NEON)
+const btSimdFloat4 ATTRIBUTE_ALIGNED16(v1000) = {1.0f, 0.0f, 0.0f, 0.0f};
+const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0100) = {0.0f, 1.0f, 0.0f, 0.0f};
+const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0010) = {0.0f, 0.0f, 1.0f, 0.0f};
+#endif
#ifdef BT_USE_DOUBLE_PRECISION
#define btMatrix3x3Data btMatrix3x3DoubleData
@@ -28,7 +40,7 @@ subject to the following restrictions:
/**@brief The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with btQuaternion, btTransform and btVector3.
* Make sure to only include a pure orthogonal matrix without scaling. */
-class btMatrix3x3 {
+ATTRIBUTE_ALIGNED16(class) btMatrix3x3 {
///Data storage for the matrix, each vector is a row of the matrix
btVector3 m_el[3];
@@ -57,6 +69,42 @@ public:
yx, yy, yz,
zx, zy, zz);
}
+
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
+ SIMD_FORCE_INLINE btMatrix3x3 (const btSimdFloat4 v0, const btSimdFloat4 v1, const btSimdFloat4 v2 )
+ {
+ m_el[0].mVec128 = v0;
+ m_el[1].mVec128 = v1;
+ m_el[2].mVec128 = v2;
+ }
+
+ SIMD_FORCE_INLINE btMatrix3x3 (const btVector3& v0, const btVector3& v1, const btVector3& v2 )
+ {
+ m_el[0] = v0;
+ m_el[1] = v1;
+ m_el[2] = v2;
+ }
+
+ // Copy constructor
+ SIMD_FORCE_INLINE btMatrix3x3(const btMatrix3x3& rhs)
+ {
+ m_el[0].mVec128 = rhs.m_el[0].mVec128;
+ m_el[1].mVec128 = rhs.m_el[1].mVec128;
+ m_el[2].mVec128 = rhs.m_el[2].mVec128;
+ }
+
+ // Assignment Operator
+ SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& m)
+ {
+ m_el[0].mVec128 = m.m_el[0].mVec128;
+ m_el[1].mVec128 = m.m_el[1].mVec128;
+ m_el[2].mVec128 = m.m_el[2].mVec128;
+
+ return *this;
+ }
+
+#else
+
/** @brief Copy constructor */
SIMD_FORCE_INLINE btMatrix3x3 (const btMatrix3x3& other)
{
@@ -64,6 +112,7 @@ public:
m_el[1] = other.m_el[1];
m_el[2] = other.m_el[2];
}
+
/** @brief Assignment Operator */
SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& other)
{
@@ -73,6 +122,8 @@ public:
return *this;
}
+#endif
+
/** @brief Get a column of the matrix as a vector
* @param i Column number 0 indexed */
SIMD_FORCE_INLINE btVector3 getColumn(int i) const
@@ -155,14 +206,69 @@ public:
btScalar d = q.length2();
btFullAssert(d != btScalar(0.0));
btScalar s = btScalar(2.0) / d;
+
+ #if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vs, Q = q.get128();
+ __m128i Qi = btCastfTo128i(Q);
+ __m128 Y, Z;
+ __m128 V1, V2, V3;
+ __m128 V11, V21, V31;
+ __m128 NQ = _mm_xor_ps(Q, btvMzeroMask);
+ __m128i NQi = btCastfTo128i(NQ);
+
+ V1 = btCastiTo128f(_mm_shuffle_epi32 (Qi, BT_SHUFFLE(1,0,2,3))); // Y X Z W
+ V2 = _mm_shuffle_ps(NQ, Q, BT_SHUFFLE(0,0,1,3)); // -X -X Y W
+ V3 = btCastiTo128f(_mm_shuffle_epi32 (Qi, BT_SHUFFLE(2,1,0,3))); // Z Y X W
+ V1 = _mm_xor_ps(V1, vMPPP); // change the sign of the first element
+
+ V11 = btCastiTo128f(_mm_shuffle_epi32 (Qi, BT_SHUFFLE(1,1,0,3))); // Y Y X W
+ V21 = _mm_unpackhi_ps(Q, Q); // Z Z W W
+ V31 = _mm_shuffle_ps(Q, NQ, BT_SHUFFLE(0,2,0,3)); // X Z -X -W
+
+ V2 = V2 * V1; //
+ V1 = V1 * V11; //
+ V3 = V3 * V31; //
+
+ V11 = _mm_shuffle_ps(NQ, Q, BT_SHUFFLE(2,3,1,3)); // -Z -W Y W
+ V11 = V11 * V21; //
+ V21 = _mm_xor_ps(V21, vMPPP); // change the sign of the first element
+ V31 = _mm_shuffle_ps(Q, NQ, BT_SHUFFLE(3,3,1,3)); // W W -Y -W
+ V31 = _mm_xor_ps(V31, vMPPP); // change the sign of the first element
+ Y = btCastiTo128f(_mm_shuffle_epi32 (NQi, BT_SHUFFLE(3,2,0,3))); // -W -Z -X -W
+ Z = btCastiTo128f(_mm_shuffle_epi32 (Qi, BT_SHUFFLE(1,0,1,3))); // Y X Y W
+
+ vs = _mm_load_ss(&s);
+ V21 = V21 * Y;
+ V31 = V31 * Z;
+
+ V1 = V1 + V11;
+ V2 = V2 + V21;
+ V3 = V3 + V31;
+
+ vs = bt_splat3_ps(vs, 0);
+ // s ready
+ V1 = V1 * vs;
+ V2 = V2 * vs;
+ V3 = V3 * vs;
+
+ V1 = V1 + v1000;
+ V2 = V2 + v0100;
+ V3 = V3 + v0010;
+
+ m_el[0] = V1;
+ m_el[1] = V2;
+ m_el[2] = V3;
+ #else
btScalar xs = q.x() * s, ys = q.y() * s, zs = q.z() * s;
btScalar wx = q.w() * xs, wy = q.w() * ys, wz = q.w() * zs;
btScalar xx = q.x() * xs, xy = q.x() * ys, xz = q.x() * zs;
btScalar yy = q.y() * ys, yz = q.y() * zs, zz = q.z() * zs;
- setValue(btScalar(1.0) - (yy + zz), xy - wz, xz + wy,
+ setValue(
+ btScalar(1.0) - (yy + zz), xy - wz, xz + wy,
xy + wz, btScalar(1.0) - (xx + zz), yz - wx,
xz - wy, yz + wx, btScalar(1.0) - (xx + yy));
- }
+ #endif
+ }
/** @brief Set the matrix from euler angles using YPR around YXZ respectively
@@ -205,16 +311,29 @@ public:
/**@brief Set the matrix to the identity */
void setIdentity()
{
+#if (defined(BT_USE_SSE_IN_API)&& defined (BT_USE_SSE)) || defined(BT_USE_NEON)
+ m_el[0] = v1000;
+ m_el[1] = v0100;
+ m_el[2] = v0010;
+#else
setValue(btScalar(1.0), btScalar(0.0), btScalar(0.0),
btScalar(0.0), btScalar(1.0), btScalar(0.0),
btScalar(0.0), btScalar(0.0), btScalar(1.0));
+#endif
}
static const btMatrix3x3& getIdentity()
{
- static const btMatrix3x3 identityMatrix(btScalar(1.0), btScalar(0.0), btScalar(0.0),
+#if (defined(BT_USE_SSE_IN_API)&& defined (BT_USE_SSE)) || defined(BT_USE_NEON)
+ static const btMatrix3x3
+ identityMatrix(v1000, v0100, v0010);
+#else
+ static const btMatrix3x3
+ identityMatrix(
+ btScalar(1.0), btScalar(0.0), btScalar(0.0),
btScalar(0.0), btScalar(1.0), btScalar(0.0),
btScalar(0.0), btScalar(0.0), btScalar(1.0));
+#endif
return identityMatrix;
}
@@ -222,6 +341,40 @@ public:
* @param m The array to be filled */
void getOpenGLSubMatrix(btScalar *m) const
{
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 v0 = m_el[0].mVec128;
+ __m128 v1 = m_el[1].mVec128;
+ __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2
+ __m128 *vm = (__m128 *)m;
+ __m128 vT;
+
+ v2 = _mm_and_ps(v2, btvFFF0fMask); // x2 y2 z2 0
+
+ vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * *
+ v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1
+
+ v1 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(2, 3, 1, 3) ); // y0 y1 y2 0
+ v0 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(0, 1, 0, 3) ); // x0 x1 x2 0
+ v2 = btCastdTo128f(_mm_move_sd(btCastfTo128d(v2), btCastfTo128d(vT))); // z0 z1 z2 0
+
+ vm[0] = v0;
+ vm[1] = v1;
+ vm[2] = v2;
+#elif defined(BT_USE_NEON)
+ // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
+ static const uint32x2_t zMask = (const uint32x2_t) {-1, 0 };
+ float32x4_t *vm = (float32x4_t *)m;
+ float32x4x2_t top = vtrnq_f32( m_el[0].mVec128, m_el[1].mVec128 ); // {x0 x1 z0 z1}, {y0 y1 w0 w1}
+ float32x2x2_t bl = vtrn_f32( vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f) ); // {x2 0 }, {y2 0}
+ float32x4_t v0 = vcombine_f32( vget_low_f32(top.val[0]), bl.val[0] );
+ float32x4_t v1 = vcombine_f32( vget_low_f32(top.val[1]), bl.val[1] );
+ float32x2_t q = (float32x2_t) vand_u32( (uint32x2_t) vget_high_f32( m_el[2].mVec128), zMask );
+ float32x4_t v2 = vcombine_f32( vget_high_f32(top.val[0]), q ); // z0 z1 z2 0
+
+ vm[0] = v0;
+ vm[1] = v1;
+ vm[2] = v2;
+#else
m[0] = btScalar(m_el[0].x());
m[1] = btScalar(m_el[1].x());
m[2] = btScalar(m_el[2].x());
@@ -234,13 +387,67 @@ public:
m[9] = btScalar(m_el[1].z());
m[10] = btScalar(m_el[2].z());
m[11] = btScalar(0.0);
+#endif
}
/**@brief Get the matrix represented as a quaternion
* @param q The quaternion which will be set */
void getRotation(btQuaternion& q) const
{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
+ btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z();
+ btScalar s, x;
+
+ union {
+ btSimdFloat4 vec;
+ btScalar f[4];
+ } temp;
+
+ if (trace > btScalar(0.0))
+ {
+ x = trace + btScalar(1.0);
+
+ temp.f[0]=m_el[2].y() - m_el[1].z();
+ temp.f[1]=m_el[0].z() - m_el[2].x();
+ temp.f[2]=m_el[1].x() - m_el[0].y();
+ temp.f[3]=x;
+ //temp.f[3]= s * btScalar(0.5);
+ }
+ else
+ {
+ int i, j, k;
+ if(m_el[0].x() < m_el[1].y())
+ {
+ if( m_el[1].y() < m_el[2].z() )
+ { i = 2; j = 0; k = 1; }
+ else
+ { i = 1; j = 2; k = 0; }
+ }
+ else
+ {
+ if( m_el[0].x() < m_el[2].z())
+ { i = 2; j = 0; k = 1; }
+ else
+ { i = 0; j = 1; k = 2; }
+ }
+
+ x = m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0);
+
+ temp.f[3] = (m_el[k][j] - m_el[j][k]);
+ temp.f[j] = (m_el[j][i] + m_el[i][j]);
+ temp.f[k] = (m_el[k][i] + m_el[i][k]);
+ temp.f[i] = x;
+ //temp.f[i] = s * btScalar(0.5);
+ }
+
+ s = btSqrt(x);
+ q.set128(temp.vec);
+ s = btScalar(0.5) / s;
+
+ q *= s;
+#else
btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z();
+
btScalar temp[4];
if (trace > btScalar(0.0))
@@ -270,6 +477,7 @@ public:
temp[k] = (m_el[k][i] + m_el[i][k]) * s;
}
q.setValue(temp[0],temp[1],temp[2],temp[3]);
+#endif
}
/**@brief Get the matrix represented as euler angles around YXZ, roundtrip with setEulerYPR
@@ -376,9 +584,14 @@ public:
btMatrix3x3 scaled(const btVector3& s) const
{
- return btMatrix3x3(m_el[0].x() * s.x(), m_el[0].y() * s.y(), m_el[0].z() * s.z(),
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
+ return btMatrix3x3(m_el[0] * s, m_el[1] * s, m_el[2] * s);
+#else
+ return btMatrix3x3(
+ m_el[0].x() * s.x(), m_el[0].y() * s.y(), m_el[0].z() * s.z(),
m_el[1].x() * s.x(), m_el[1].y() * s.y(), m_el[1].z() * s.z(),
m_el[2].x() * s.x(), m_el[2].y() * s.y(), m_el[2].z() * s.z());
+#endif
}
/**@brief Return the determinant of the matrix */
@@ -527,15 +740,101 @@ public:
SIMD_FORCE_INLINE btMatrix3x3&
btMatrix3x3::operator*=(const btMatrix3x3& m)
{
- setValue(m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]),
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 rv00, rv01, rv02;
+ __m128 rv10, rv11, rv12;
+ __m128 rv20, rv21, rv22;
+ __m128 mv0, mv1, mv2;
+
+ rv02 = m_el[0].mVec128;
+ rv12 = m_el[1].mVec128;
+ rv22 = m_el[2].mVec128;
+
+ mv0 = _mm_and_ps(m[0].mVec128, btvFFF0fMask);
+ mv1 = _mm_and_ps(m[1].mVec128, btvFFF0fMask);
+ mv2 = _mm_and_ps(m[2].mVec128, btvFFF0fMask);
+
+ // rv0
+ rv00 = bt_splat_ps(rv02, 0);
+ rv01 = bt_splat_ps(rv02, 1);
+ rv02 = bt_splat_ps(rv02, 2);
+
+ rv00 = _mm_mul_ps(rv00, mv0);
+ rv01 = _mm_mul_ps(rv01, mv1);
+ rv02 = _mm_mul_ps(rv02, mv2);
+
+ // rv1
+ rv10 = bt_splat_ps(rv12, 0);
+ rv11 = bt_splat_ps(rv12, 1);
+ rv12 = bt_splat_ps(rv12, 2);
+
+ rv10 = _mm_mul_ps(rv10, mv0);
+ rv11 = _mm_mul_ps(rv11, mv1);
+ rv12 = _mm_mul_ps(rv12, mv2);
+
+ // rv2
+ rv20 = bt_splat_ps(rv22, 0);
+ rv21 = bt_splat_ps(rv22, 1);
+ rv22 = bt_splat_ps(rv22, 2);
+
+ rv20 = _mm_mul_ps(rv20, mv0);
+ rv21 = _mm_mul_ps(rv21, mv1);
+ rv22 = _mm_mul_ps(rv22, mv2);
+
+ rv00 = _mm_add_ps(rv00, rv01);
+ rv10 = _mm_add_ps(rv10, rv11);
+ rv20 = _mm_add_ps(rv20, rv21);
+
+ m_el[0].mVec128 = _mm_add_ps(rv00, rv02);
+ m_el[1].mVec128 = _mm_add_ps(rv10, rv12);
+ m_el[2].mVec128 = _mm_add_ps(rv20, rv22);
+
+#elif defined(BT_USE_NEON)
+
+ float32x4_t rv0, rv1, rv2;
+ float32x4_t v0, v1, v2;
+ float32x4_t mv0, mv1, mv2;
+
+ v0 = m_el[0].mVec128;
+ v1 = m_el[1].mVec128;
+ v2 = m_el[2].mVec128;
+
+ mv0 = (float32x4_t) vandq_s32((int32x4_t)m[0].mVec128, btvFFF0Mask);
+ mv1 = (float32x4_t) vandq_s32((int32x4_t)m[1].mVec128, btvFFF0Mask);
+ mv2 = (float32x4_t) vandq_s32((int32x4_t)m[2].mVec128, btvFFF0Mask);
+
+ rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
+ rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
+ rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
+
+ rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
+ rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
+ rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
+
+ rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
+ rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
+ rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
+
+ m_el[0].mVec128 = rv0;
+ m_el[1].mVec128 = rv1;
+ m_el[2].mVec128 = rv2;
+#else
+ setValue(
+ m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]),
m.tdotx(m_el[1]), m.tdoty(m_el[1]), m.tdotz(m_el[1]),
m.tdotx(m_el[2]), m.tdoty(m_el[2]), m.tdotz(m_el[2]));
+#endif
return *this;
}
SIMD_FORCE_INLINE btMatrix3x3&
btMatrix3x3::operator+=(const btMatrix3x3& m)
{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
+ m_el[0].mVec128 = m_el[0].mVec128 + m.m_el[0].mVec128;
+ m_el[1].mVec128 = m_el[1].mVec128 + m.m_el[1].mVec128;
+ m_el[2].mVec128 = m_el[2].mVec128 + m.m_el[2].mVec128;
+#else
setValue(
m_el[0][0]+m.m_el[0][0],
m_el[0][1]+m.m_el[0][1],
@@ -546,52 +845,89 @@ btMatrix3x3::operator+=(const btMatrix3x3& m)
m_el[2][0]+m.m_el[2][0],
m_el[2][1]+m.m_el[2][1],
m_el[2][2]+m.m_el[2][2]);
+#endif
return *this;
}
SIMD_FORCE_INLINE btMatrix3x3
operator*(const btMatrix3x3& m, const btScalar & k)
{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+ __m128 vk = bt_splat_ps(_mm_load_ss((float *)&k), 0x80);
+ return btMatrix3x3(
+ _mm_mul_ps(m[0].mVec128, vk),
+ _mm_mul_ps(m[1].mVec128, vk),
+ _mm_mul_ps(m[2].mVec128, vk));
+#elif defined(BT_USE_NEON)
+ return btMatrix3x3(
+ vmulq_n_f32(m[0].mVec128, k),
+ vmulq_n_f32(m[1].mVec128, k),
+ vmulq_n_f32(m[2].mVec128, k));
+#else
return btMatrix3x3(
m[0].x()*k,m[0].y()*k,m[0].z()*k,
m[1].x()*k,m[1].y()*k,m[1].z()*k,
m[2].x()*k,m[2].y()*k,m[2].z()*k);
+#endif
}
- SIMD_FORCE_INLINE btMatrix3x3
+SIMD_FORCE_INLINE btMatrix3x3
operator+(const btMatrix3x3& m1, const btMatrix3x3& m2)
{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
return btMatrix3x3(
- 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]);
+ m1[0].mVec128 + m2[0].mVec128,
+ m1[1].mVec128 + m2[1].mVec128,
+ m1[2].mVec128 + m2[2].mVec128);
+#else
+ return btMatrix3x3(
+ 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]);
+#endif
}
SIMD_FORCE_INLINE btMatrix3x3
operator-(const btMatrix3x3& m1, const btMatrix3x3& m2)
{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
return btMatrix3x3(
- 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]);
+ m1[0].mVec128 - m2[0].mVec128,
+ m1[1].mVec128 - m2[1].mVec128,
+ m1[2].mVec128 - m2[2].mVec128);
+#else
+ return btMatrix3x3(
+ 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]);
+#endif
}
SIMD_FORCE_INLINE btMatrix3x3&
btMatrix3x3::operator-=(const btMatrix3x3& m)
{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
+ m_el[0].mVec128 = m_el[0].mVec128 - m.m_el[0].mVec128;
+ m_el[1].mVec128 = m_el[1].mVec128 - m.m_el[1].mVec128;
+ m_el[2].mVec128 = m_el[2].mVec128 - m.m_el[2].mVec128;
+#else
setValue(
m_el[0][0]-m.m_el[0][0],
m_el[0][1]-m.m_el[0][1],
@@ -602,6 +938,7 @@ btMatrix3x3::operator-=(const btMatrix3x3& m)
m_el[2][0]-m.m_el[2][0],
m_el[2][1]-m.m_el[2][1],
m_el[2][2]-m.m_el[2][2]);
+#endif
return *this;
}
@@ -616,18 +953,59 @@ btMatrix3x3::determinant() const
SIMD_FORCE_INLINE btMatrix3x3
btMatrix3x3::absolute() const
{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+ return btMatrix3x3(
+ _mm_and_ps(m_el[0].mVec128, btvAbsfMask),
+ _mm_and_ps(m_el[1].mVec128, btvAbsfMask),
+ _mm_and_ps(m_el[2].mVec128, btvAbsfMask));
+#elif defined(BT_USE_NEON)
+ return btMatrix3x3(
+ (float32x4_t)vandq_s32((int32x4_t)m_el[0].mVec128, btv3AbsMask),
+ (float32x4_t)vandq_s32((int32x4_t)m_el[1].mVec128, btv3AbsMask),
+ (float32x4_t)vandq_s32((int32x4_t)m_el[2].mVec128, btv3AbsMask));
+#else
return btMatrix3x3(
- btFabs(m_el[0].x()), btFabs(m_el[0].y()), btFabs(m_el[0].z()),
- btFabs(m_el[1].x()), btFabs(m_el[1].y()), btFabs(m_el[1].z()),
- btFabs(m_el[2].x()), btFabs(m_el[2].y()), btFabs(m_el[2].z()));
+ btFabs(m_el[0].x()), btFabs(m_el[0].y()), btFabs(m_el[0].z()),
+ btFabs(m_el[1].x()), btFabs(m_el[1].y()), btFabs(m_el[1].z()),
+ btFabs(m_el[2].x()), btFabs(m_el[2].y()), btFabs(m_el[2].z()));
+#endif
}
SIMD_FORCE_INLINE btMatrix3x3
btMatrix3x3::transpose() const
{
- return btMatrix3x3(m_el[0].x(), m_el[1].x(), m_el[2].x(),
- m_el[0].y(), m_el[1].y(), m_el[2].y(),
- m_el[0].z(), m_el[1].z(), m_el[2].z());
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+ __m128 v0 = m_el[0].mVec128;
+ __m128 v1 = m_el[1].mVec128;
+ __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2
+ __m128 vT;
+
+ v2 = _mm_and_ps(v2, btvFFF0fMask); // x2 y2 z2 0
+
+ vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * *
+ v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1
+
+ v1 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(2, 3, 1, 3) ); // y0 y1 y2 0
+ v0 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(0, 1, 0, 3) ); // x0 x1 x2 0
+ v2 = btCastdTo128f(_mm_move_sd(btCastfTo128d(v2), btCastfTo128d(vT))); // z0 z1 z2 0
+
+
+ return btMatrix3x3( v0, v1, v2 );
+#elif defined(BT_USE_NEON)
+ // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
+ static const uint32x2_t zMask = (const uint32x2_t) {-1, 0 };
+ float32x4x2_t top = vtrnq_f32( m_el[0].mVec128, m_el[1].mVec128 ); // {x0 x1 z0 z1}, {y0 y1 w0 w1}
+ float32x2x2_t bl = vtrn_f32( vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f) ); // {x2 0 }, {y2 0}
+ float32x4_t v0 = vcombine_f32( vget_low_f32(top.val[0]), bl.val[0] );
+ float32x4_t v1 = vcombine_f32( vget_low_f32(top.val[1]), bl.val[1] );
+ float32x2_t q = (float32x2_t) vand_u32( (uint32x2_t) vget_high_f32( m_el[2].mVec128), zMask );
+ float32x4_t v2 = vcombine_f32( vget_high_f32(top.val[0]), q ); // z0 z1 z2 0
+ return btMatrix3x3( v0, v1, v2 );
+#else
+ return btMatrix3x3( m_el[0].x(), m_el[1].x(), m_el[2].x(),
+ m_el[0].y(), m_el[1].y(), m_el[2].y(),
+ m_el[0].z(), m_el[1].z(), m_el[2].z());
+#endif
}
SIMD_FORCE_INLINE btMatrix3x3
@@ -653,7 +1031,47 @@ btMatrix3x3::inverse() const
SIMD_FORCE_INLINE btMatrix3x3
btMatrix3x3::transposeTimes(const btMatrix3x3& m) const
{
- return btMatrix3x3(
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+ // zeros w
+// static const __m128i xyzMask = (const __m128i){ -1ULL, 0xffffffffULL };
+ __m128 row = m_el[0].mVec128;
+ __m128 m0 = _mm_and_ps( m.getRow(0).mVec128, btvFFF0fMask );
+ __m128 m1 = _mm_and_ps( m.getRow(1).mVec128, btvFFF0fMask);
+ __m128 m2 = _mm_and_ps( m.getRow(2).mVec128, btvFFF0fMask );
+ __m128 r0 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0));
+ __m128 r1 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0x55));
+ __m128 r2 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0xaa));
+ row = m_el[1].mVec128;
+ r0 = _mm_add_ps( r0, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0)));
+ r1 = _mm_add_ps( r1, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0x55)));
+ r2 = _mm_add_ps( r2, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0xaa)));
+ row = m_el[2].mVec128;
+ r0 = _mm_add_ps( r0, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0)));
+ r1 = _mm_add_ps( r1, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0x55)));
+ r2 = _mm_add_ps( r2, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0xaa)));
+ return btMatrix3x3( r0, r1, r2 );
+
+#elif defined BT_USE_NEON
+ // zeros w
+ static const uint32x4_t xyzMask = (const uint32x4_t){ -1, -1, -1, 0 };
+ float32x4_t m0 = (float32x4_t) vandq_u32( (uint32x4_t) m.getRow(0).mVec128, xyzMask );
+ float32x4_t m1 = (float32x4_t) vandq_u32( (uint32x4_t) m.getRow(1).mVec128, xyzMask );
+ float32x4_t m2 = (float32x4_t) vandq_u32( (uint32x4_t) m.getRow(2).mVec128, xyzMask );
+ float32x4_t row = m_el[0].mVec128;
+ float32x4_t r0 = vmulq_lane_f32( m0, vget_low_f32(row), 0);
+ float32x4_t r1 = vmulq_lane_f32( m0, vget_low_f32(row), 1);
+ float32x4_t r2 = vmulq_lane_f32( m0, vget_high_f32(row), 0);
+ row = m_el[1].mVec128;
+ r0 = vmlaq_lane_f32( r0, m1, vget_low_f32(row), 0);
+ r1 = vmlaq_lane_f32( r1, m1, vget_low_f32(row), 1);
+ r2 = vmlaq_lane_f32( r2, m1, vget_high_f32(row), 0);
+ row = m_el[2].mVec128;
+ r0 = vmlaq_lane_f32( r0, m2, vget_low_f32(row), 0);
+ r1 = vmlaq_lane_f32( r1, m2, vget_low_f32(row), 1);
+ r2 = vmlaq_lane_f32( r2, m2, vget_high_f32(row), 0);
+ return btMatrix3x3( r0, r1, r2 );
+#else
+ return btMatrix3x3(
m_el[0].x() * m[0].x() + m_el[1].x() * m[1].x() + m_el[2].x() * m[2].x(),
m_el[0].x() * m[0].y() + m_el[1].x() * m[1].y() + m_el[2].x() * m[2].y(),
m_el[0].x() * m[0].z() + m_el[1].x() * m[1].z() + m_el[2].x() * m[2].z(),
@@ -663,38 +1081,196 @@ btMatrix3x3::transposeTimes(const btMatrix3x3& m) const
m_el[0].z() * m[0].x() + m_el[1].z() * m[1].x() + m_el[2].z() * m[2].x(),
m_el[0].z() * m[0].y() + m_el[1].z() * m[1].y() + m_el[2].z() * m[2].y(),
m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].z());
+#endif
}
SIMD_FORCE_INLINE btMatrix3x3
btMatrix3x3::timesTranspose(const btMatrix3x3& m) const
{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+ __m128 a0 = m_el[0].mVec128;
+ __m128 a1 = m_el[1].mVec128;
+ __m128 a2 = m_el[2].mVec128;
+
+ btMatrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here
+ __m128 mx = mT[0].mVec128;
+ __m128 my = mT[1].mVec128;
+ __m128 mz = mT[2].mVec128;
+
+ __m128 r0 = _mm_mul_ps(mx, _mm_shuffle_ps(a0, a0, 0x00));
+ __m128 r1 = _mm_mul_ps(mx, _mm_shuffle_ps(a1, a1, 0x00));
+ __m128 r2 = _mm_mul_ps(mx, _mm_shuffle_ps(a2, a2, 0x00));
+ r0 = _mm_add_ps(r0, _mm_mul_ps(my, _mm_shuffle_ps(a0, a0, 0x55)));
+ r1 = _mm_add_ps(r1, _mm_mul_ps(my, _mm_shuffle_ps(a1, a1, 0x55)));
+ r2 = _mm_add_ps(r2, _mm_mul_ps(my, _mm_shuffle_ps(a2, a2, 0x55)));
+ r0 = _mm_add_ps(r0, _mm_mul_ps(mz, _mm_shuffle_ps(a0, a0, 0xaa)));
+ r1 = _mm_add_ps(r1, _mm_mul_ps(mz, _mm_shuffle_ps(a1, a1, 0xaa)));
+ r2 = _mm_add_ps(r2, _mm_mul_ps(mz, _mm_shuffle_ps(a2, a2, 0xaa)));
+ return btMatrix3x3( r0, r1, r2);
+
+#elif defined BT_USE_NEON
+ float32x4_t a0 = m_el[0].mVec128;
+ float32x4_t a1 = m_el[1].mVec128;
+ float32x4_t a2 = m_el[2].mVec128;
+
+ btMatrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here
+ float32x4_t mx = mT[0].mVec128;
+ float32x4_t my = mT[1].mVec128;
+ float32x4_t mz = mT[2].mVec128;
+
+ float32x4_t r0 = vmulq_lane_f32( mx, vget_low_f32(a0), 0);
+ float32x4_t r1 = vmulq_lane_f32( mx, vget_low_f32(a1), 0);
+ float32x4_t r2 = vmulq_lane_f32( mx, vget_low_f32(a2), 0);
+ r0 = vmlaq_lane_f32( r0, my, vget_low_f32(a0), 1);
+ r1 = vmlaq_lane_f32( r1, my, vget_low_f32(a1), 1);
+ r2 = vmlaq_lane_f32( r2, my, vget_low_f32(a2), 1);
+ r0 = vmlaq_lane_f32( r0, mz, vget_high_f32(a0), 0);
+ r1 = vmlaq_lane_f32( r1, mz, vget_high_f32(a1), 0);
+ r2 = vmlaq_lane_f32( r2, mz, vget_high_f32(a2), 0);
+ return btMatrix3x3( r0, r1, r2 );
+
+#else
return btMatrix3x3(
m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]),
m_el[1].dot(m[0]), m_el[1].dot(m[1]), m_el[1].dot(m[2]),
m_el[2].dot(m[0]), m_el[2].dot(m[1]), m_el[2].dot(m[2]));
-
+#endif
}
SIMD_FORCE_INLINE btVector3
operator*(const btMatrix3x3& m, const btVector3& v)
{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))|| defined (BT_USE_NEON)
+ return v.dot3(m[0], m[1], m[2]);
+#else
return btVector3(m[0].dot(v), m[1].dot(v), m[2].dot(v));
+#endif
}
SIMD_FORCE_INLINE btVector3
operator*(const btVector3& v, const btMatrix3x3& m)
{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+
+ const __m128 vv = v.mVec128;
+
+ __m128 c0 = bt_splat_ps( vv, 0);
+ __m128 c1 = bt_splat_ps( vv, 1);
+ __m128 c2 = bt_splat_ps( vv, 2);
+
+ c0 = _mm_mul_ps(c0, _mm_and_ps(m[0].mVec128, btvFFF0fMask) );
+ c1 = _mm_mul_ps(c1, _mm_and_ps(m[1].mVec128, btvFFF0fMask) );
+ c0 = _mm_add_ps(c0, c1);
+ c2 = _mm_mul_ps(c2, _mm_and_ps(m[2].mVec128, btvFFF0fMask) );
+
+ return btVector3(_mm_add_ps(c0, c2));
+#elif defined(BT_USE_NEON)
+ const float32x4_t vv = v.mVec128;
+ const float32x2_t vlo = vget_low_f32(vv);
+ const float32x2_t vhi = vget_high_f32(vv);
+
+ float32x4_t c0, c1, c2;
+
+ c0 = (float32x4_t) vandq_s32((int32x4_t)m[0].mVec128, btvFFF0Mask);
+ c1 = (float32x4_t) vandq_s32((int32x4_t)m[1].mVec128, btvFFF0Mask);
+ c2 = (float32x4_t) vandq_s32((int32x4_t)m[2].mVec128, btvFFF0Mask);
+
+ c0 = vmulq_lane_f32(c0, vlo, 0);
+ c1 = vmulq_lane_f32(c1, vlo, 1);
+ c2 = vmulq_lane_f32(c2, vhi, 0);
+ c0 = vaddq_f32(c0, c1);
+ c0 = vaddq_f32(c0, c2);
+
+ return btVector3(c0);
+#else
return btVector3(m.tdotx(v), m.tdoty(v), m.tdotz(v));
+#endif
}
SIMD_FORCE_INLINE btMatrix3x3
operator*(const btMatrix3x3& m1, const btMatrix3x3& m2)
{
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+
+ __m128 m10 = m1[0].mVec128;
+ __m128 m11 = m1[1].mVec128;
+ __m128 m12 = m1[2].mVec128;
+
+ __m128 m2v = _mm_and_ps(m2[0].mVec128, btvFFF0fMask);
+
+ __m128 c0 = bt_splat_ps( m10, 0);
+ __m128 c1 = bt_splat_ps( m11, 0);
+ __m128 c2 = bt_splat_ps( m12, 0);
+
+ c0 = _mm_mul_ps(c0, m2v);
+ c1 = _mm_mul_ps(c1, m2v);
+ c2 = _mm_mul_ps(c2, m2v);
+
+ m2v = _mm_and_ps(m2[1].mVec128, btvFFF0fMask);
+
+ __m128 c0_1 = bt_splat_ps( m10, 1);
+ __m128 c1_1 = bt_splat_ps( m11, 1);
+ __m128 c2_1 = bt_splat_ps( m12, 1);
+
+ c0_1 = _mm_mul_ps(c0_1, m2v);
+ c1_1 = _mm_mul_ps(c1_1, m2v);
+ c2_1 = _mm_mul_ps(c2_1, m2v);
+
+ m2v = _mm_and_ps(m2[2].mVec128, btvFFF0fMask);
+
+ c0 = _mm_add_ps(c0, c0_1);
+ c1 = _mm_add_ps(c1, c1_1);
+ c2 = _mm_add_ps(c2, c2_1);
+
+ m10 = bt_splat_ps( m10, 2);
+ m11 = bt_splat_ps( m11, 2);
+ m12 = bt_splat_ps( m12, 2);
+
+ m10 = _mm_mul_ps(m10, m2v);
+ m11 = _mm_mul_ps(m11, m2v);
+ m12 = _mm_mul_ps(m12, m2v);
+
+ c0 = _mm_add_ps(c0, m10);
+ c1 = _mm_add_ps(c1, m11);
+ c2 = _mm_add_ps(c2, m12);
+
+ return btMatrix3x3(c0, c1, c2);
+
+#elif defined(BT_USE_NEON)
+
+ float32x4_t rv0, rv1, rv2;
+ float32x4_t v0, v1, v2;
+ float32x4_t mv0, mv1, mv2;
+
+ v0 = m1[0].mVec128;
+ v1 = m1[1].mVec128;
+ v2 = m1[2].mVec128;
+
+ mv0 = (float32x4_t) vandq_s32((int32x4_t)m2[0].mVec128, btvFFF0Mask);
+ mv1 = (float32x4_t) vandq_s32((int32x4_t)m2[1].mVec128, btvFFF0Mask);
+ mv2 = (float32x4_t) vandq_s32((int32x4_t)m2[2].mVec128, btvFFF0Mask);
+
+ rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
+ rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
+ rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
+
+ rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
+ rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
+ rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
+
+ rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
+ rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
+ rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
+
+ return btMatrix3x3(rv0, rv1, rv2);
+
+#else
return btMatrix3x3(
m2.tdotx( m1[0]), m2.tdoty( m1[0]), m2.tdotz( m1[0]),
m2.tdotx( m1[1]), m2.tdoty( m1[1]), m2.tdotz( m1[1]),
m2.tdotx( m1[2]), m2.tdoty( m1[2]), m2.tdotz( m1[2]));
+#endif
}
/*
@@ -716,9 +1292,24 @@ m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]);
* It will test all elements are equal. */
SIMD_FORCE_INLINE bool operator==(const btMatrix3x3& m1, const btMatrix3x3& m2)
{
- return ( m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] &&
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+
+ __m128 c0, c1, c2;
+
+ c0 = _mm_cmpeq_ps(m1[0].mVec128, m2[0].mVec128);
+ c1 = _mm_cmpeq_ps(m1[1].mVec128, m2[1].mVec128);
+ c2 = _mm_cmpeq_ps(m1[2].mVec128, m2[2].mVec128);
+
+ c0 = _mm_and_ps(c0, c1);
+ c0 = _mm_and_ps(c0, c2);
+
+ return (0x7 == _mm_movemask_ps((__m128)c0));
+#else
+ return
+ ( m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] &&
m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == m2[2][1] &&
m1[0][2] == m2[0][2] && m1[1][2] == m2[1][2] && m1[2][2] == m2[2][2] );
+#endif
}
///for serialization
diff --git a/extern/bullet2/src/LinearMath/btPolarDecomposition.cpp b/extern/bullet2/src/LinearMath/btPolarDecomposition.cpp
new file mode 100644
index 00000000000..a4dca7fdd40
--- /dev/null
+++ b/extern/bullet2/src/LinearMath/btPolarDecomposition.cpp
@@ -0,0 +1,99 @@
+#include "btPolarDecomposition.h"
+#include "btMinMax.h"
+
+namespace
+{
+ btScalar abs_column_sum(const btMatrix3x3& a, int i)
+ {
+ return btFabs(a[0][i]) + btFabs(a[1][i]) + btFabs(a[2][i]);
+ }
+
+ btScalar abs_row_sum(const btMatrix3x3& a, int i)
+ {
+ return btFabs(a[i][0]) + btFabs(a[i][1]) + btFabs(a[i][2]);
+ }
+
+ btScalar p1_norm(const btMatrix3x3& a)
+ {
+ const btScalar sum0 = abs_column_sum(a,0);
+ const btScalar sum1 = abs_column_sum(a,1);
+ const btScalar sum2 = abs_column_sum(a,2);
+ return btMax(btMax(sum0, sum1), sum2);
+ }
+
+ btScalar pinf_norm(const btMatrix3x3& a)
+ {
+ const btScalar sum0 = abs_row_sum(a,0);
+ const btScalar sum1 = abs_row_sum(a,1);
+ const btScalar sum2 = abs_row_sum(a,2);
+ return btMax(btMax(sum0, sum1), sum2);
+ }
+}
+
+const btScalar btPolarDecomposition::DEFAULT_TOLERANCE = btScalar(0.0001);
+const unsigned int btPolarDecomposition::DEFAULT_MAX_ITERATIONS = 16;
+
+btPolarDecomposition::btPolarDecomposition(btScalar tolerance, unsigned int maxIterations)
+: m_tolerance(tolerance)
+, m_maxIterations(maxIterations)
+{
+}
+
+unsigned int btPolarDecomposition::decompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) const
+{
+ // Use the 'u' and 'h' matrices for intermediate calculations
+ u = a;
+ h = a.inverse();
+
+ for (unsigned int i = 0; i < m_maxIterations; ++i)
+ {
+ const btScalar h_1 = p1_norm(h);
+ const btScalar h_inf = pinf_norm(h);
+ const btScalar u_1 = p1_norm(u);
+ const btScalar u_inf = pinf_norm(u);
+
+ const btScalar h_norm = h_1 * h_inf;
+ const btScalar u_norm = u_1 * u_inf;
+
+ // The matrix is effectively singular so we cannot invert it
+ if (btFuzzyZero(h_norm) || btFuzzyZero(u_norm))
+ break;
+
+ const btScalar gamma = btPow(h_norm / u_norm, 0.25f);
+ const btScalar inv_gamma = btScalar(1.0) / gamma;
+
+ // Determine the delta to 'u'
+ const btMatrix3x3 delta = (u * (gamma - btScalar(2.0)) + h.transpose() * inv_gamma) * btScalar(0.5);
+
+ // Update the matrices
+ u += delta;
+ h = u.inverse();
+
+ // Check for convergence
+ if (p1_norm(delta) <= m_tolerance * u_1)
+ {
+ h = u.transpose() * a;
+ h = (h + h.transpose()) * 0.5;
+ return i;
+ }
+ }
+
+ // The algorithm has failed to converge to the specified tolerance, but we
+ // want to make sure that the matrices returned are in the right form.
+ h = u.transpose() * a;
+ h = (h + h.transpose()) * 0.5;
+
+ return m_maxIterations;
+}
+
+unsigned int btPolarDecomposition::maxIterations() const
+{
+ return m_maxIterations;
+}
+
+unsigned int polarDecompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h)
+{
+ static btPolarDecomposition polar;
+ return polar.decompose(a, u, h);
+}
+
diff --git a/extern/bullet2/src/LinearMath/btPolarDecomposition.h b/extern/bullet2/src/LinearMath/btPolarDecomposition.h
new file mode 100644
index 00000000000..56156676415
--- /dev/null
+++ b/extern/bullet2/src/LinearMath/btPolarDecomposition.h
@@ -0,0 +1,73 @@
+#ifndef POLARDECOMPOSITION_H
+#define POLARDECOMPOSITION_H
+
+#include "btMatrix3x3.h"
+
+/**
+ * This class is used to compute the polar decomposition of a matrix. In
+ * general, the polar decomposition factorizes a matrix, A, into two parts: a
+ * unitary matrix (U) and a positive, semi-definite Hermitian matrix (H).
+ * However, in this particular implementation the original matrix, A, is
+ * required to be a square 3x3 matrix with real elements. This means that U will
+ * be an orthogonal matrix and H with be a positive-definite, symmetric matrix.
+ */
+class btPolarDecomposition
+{
+ public:
+ static const btScalar DEFAULT_TOLERANCE;
+ static const unsigned int DEFAULT_MAX_ITERATIONS;
+
+ /**
+ * Creates an instance with optional parameters.
+ *
+ * @param tolerance - the tolerance used to determine convergence of the
+ * algorithm
+ * @param maxIterations - the maximum number of iterations used to achieve
+ * convergence
+ */
+ btPolarDecomposition(btScalar tolerance = DEFAULT_TOLERANCE,
+ unsigned int maxIterations = DEFAULT_MAX_ITERATIONS);
+
+ /**
+ * Decomposes a matrix into orthogonal and symmetric, positive-definite
+ * parts. If the number of iterations returned by this function is equal to
+ * the maximum number of iterations, the algorithm has failed to converge.
+ *
+ * @param a - the original matrix
+ * @param u - the resulting orthogonal matrix
+ * @param h - the resulting symmetric matrix
+ *
+ * @return the number of iterations performed by the algorithm.
+ */
+ unsigned int decompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) const;
+
+ /**
+ * Returns the maximum number of iterations that this algorithm will perform
+ * to achieve convergence.
+ *
+ * @return maximum number of iterations
+ */
+ unsigned int maxIterations() const;
+
+ private:
+ btScalar m_tolerance;
+ unsigned int m_maxIterations;
+};
+
+/**
+ * This functions decomposes the matrix 'a' into two parts: an orthogonal matrix
+ * 'u' and a symmetric, positive-definite matrix 'h'. If the number of
+ * iterations returned by this function is equal to
+ * btPolarDecomposition::DEFAULT_MAX_ITERATIONS, the algorithm has failed to
+ * converge.
+ *
+ * @param a - the original matrix
+ * @param u - the resulting orthogonal matrix
+ * @param h - the resulting symmetric matrix
+ *
+ * @return the number of iterations performed by the algorithm.
+ */
+unsigned int polarDecompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h);
+
+#endif // POLARDECOMPOSITION_H
+
diff --git a/extern/bullet2/src/LinearMath/btQuadWord.h b/extern/bullet2/src/LinearMath/btQuadWord.h
index d5e9daa45a2..11067ef47d9 100644
--- a/extern/bullet2/src/LinearMath/btQuadWord.h
+++ b/extern/bullet2/src/LinearMath/btQuadWord.h
@@ -20,6 +20,9 @@ subject to the following restrictions:
#include "btMinMax.h"
+
+
+
#if defined (__CELLOS_LV2) && defined (__SPU__)
#include <altivec.h>
#endif
@@ -47,11 +50,53 @@ public:
}
protected:
#else //__CELLOS_LV2__ __SPU__
+
+#if defined(BT_USE_SSE) || defined(BT_USE_NEON)
+ union {
+ btSimdFloat4 mVec128;
+ btScalar m_floats[4];
+ };
+public:
+ SIMD_FORCE_INLINE btSimdFloat4 get128() const
+ {
+ return mVec128;
+ }
+ SIMD_FORCE_INLINE void set128(btSimdFloat4 v128)
+ {
+ mVec128 = v128;
+ }
+#else
btScalar m_floats[4];
+#endif // BT_USE_SSE
+
#endif //__CELLOS_LV2__ __SPU__
public:
+#if defined(BT_USE_SSE) || defined(BT_USE_NEON)
+
+ // Set Vector
+ SIMD_FORCE_INLINE btQuadWord(const btSimdFloat4 vec)
+ {
+ mVec128 = vec;
+ }
+
+ // Copy constructor
+ SIMD_FORCE_INLINE btQuadWord(const btQuadWord& rhs)
+ {
+ mVec128 = rhs.mVec128;
+ }
+
+ // Assignment Operator
+ SIMD_FORCE_INLINE btQuadWord&
+ operator=(const btQuadWord& v)
+ {
+ mVec128 = v.mVec128;
+
+ return *this;
+ }
+
+#endif
/**@brief Return the x value */
SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
@@ -60,13 +105,13 @@ protected:
/**@brief Return the z value */
SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
/**@brief Set the x value */
- SIMD_FORCE_INLINE void setX(btScalar x) { m_floats[0] = x;};
+ SIMD_FORCE_INLINE void setX(btScalar _x) { m_floats[0] = _x;};
/**@brief Set the y value */
- SIMD_FORCE_INLINE void setY(btScalar y) { m_floats[1] = y;};
+ SIMD_FORCE_INLINE void setY(btScalar _y) { m_floats[1] = _y;};
/**@brief Set the z value */
- SIMD_FORCE_INLINE void setZ(btScalar z) { m_floats[2] = z;};
+ SIMD_FORCE_INLINE void setZ(btScalar _z) { m_floats[2] = _z;};
/**@brief Set the w value */
- SIMD_FORCE_INLINE void setW(btScalar w) { m_floats[3] = w;};
+ SIMD_FORCE_INLINE void setW(btScalar _w) { m_floats[3] = _w;};
/**@brief Return the x value */
SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
/**@brief Return the y value */
@@ -84,7 +129,14 @@ protected:
SIMD_FORCE_INLINE bool operator==(const btQuadWord& other) const
{
- return ((m_floats[3]==other.m_floats[3]) && (m_floats[2]==other.m_floats[2]) && (m_floats[1]==other.m_floats[1]) && (m_floats[0]==other.m_floats[0]));
+#ifdef BT_USE_SSE
+ return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
+#else
+ return ((m_floats[3]==other.m_floats[3]) &&
+ (m_floats[2]==other.m_floats[2]) &&
+ (m_floats[1]==other.m_floats[1]) &&
+ (m_floats[0]==other.m_floats[0]));
+#endif
}
SIMD_FORCE_INLINE bool operator!=(const btQuadWord& other) const
@@ -97,11 +149,11 @@ protected:
* @param y Value of y
* @param z Value of z
*/
- SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z)
+ SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z)
{
- m_floats[0]=x;
- m_floats[1]=y;
- m_floats[2]=z;
+ m_floats[0]=_x;
+ m_floats[1]=_y;
+ m_floats[2]=_z;
m_floats[3] = 0.f;
}
@@ -118,12 +170,12 @@ protected:
* @param z Value of z
* @param w Value of w
*/
- SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w)
+ SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z,const btScalar& _w)
{
- m_floats[0]=x;
- m_floats[1]=y;
- m_floats[2]=z;
- m_floats[3]=w;
+ m_floats[0]=_x;
+ m_floats[1]=_y;
+ m_floats[2]=_z;
+ m_floats[3]=_w;
}
/**@brief No initialization constructor */
SIMD_FORCE_INLINE btQuadWord()
@@ -136,9 +188,9 @@ protected:
* @param y Value of y
* @param z Value of z
*/
- SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z)
+ SIMD_FORCE_INLINE btQuadWord(const btScalar& _x, const btScalar& _y, const btScalar& _z)
{
- m_floats[0] = x, m_floats[1] = y, m_floats[2] = z, m_floats[3] = 0.0f;
+ m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = 0.0f;
}
/**@brief Initializing constructor
@@ -147,9 +199,9 @@ protected:
* @param z Value of z
* @param w Value of w
*/
- SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w)
+ SIMD_FORCE_INLINE btQuadWord(const btScalar& _x, const btScalar& _y, const btScalar& _z,const btScalar& _w)
{
- m_floats[0] = x, m_floats[1] = y, m_floats[2] = z, m_floats[3] = w;
+ m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = _w;
}
/**@brief Set each element to the max of the current values and the values of another btQuadWord
@@ -157,21 +209,33 @@ protected:
*/
SIMD_FORCE_INLINE void setMax(const btQuadWord& other)
{
- btSetMax(m_floats[0], other.m_floats[0]);
+ #ifdef BT_USE_SSE
+ mVec128 = _mm_max_ps(mVec128, other.mVec128);
+ #elif defined(BT_USE_NEON)
+ mVec128 = vmaxq_f32(mVec128, other.mVec128);
+ #else
+ btSetMax(m_floats[0], other.m_floats[0]);
btSetMax(m_floats[1], other.m_floats[1]);
btSetMax(m_floats[2], other.m_floats[2]);
btSetMax(m_floats[3], other.m_floats[3]);
- }
+ #endif
+ }
/**@brief Set each element to the min of the current values and the values of another btQuadWord
* @param other The other btQuadWord to compare with
*/
SIMD_FORCE_INLINE void setMin(const btQuadWord& other)
{
- btSetMin(m_floats[0], other.m_floats[0]);
+ #ifdef BT_USE_SSE
+ mVec128 = _mm_min_ps(mVec128, other.mVec128);
+ #elif defined(BT_USE_NEON)
+ mVec128 = vminq_f32(mVec128, other.mVec128);
+ #else
+ btSetMin(m_floats[0], other.m_floats[0]);
btSetMin(m_floats[1], other.m_floats[1]);
btSetMin(m_floats[2], other.m_floats[2]);
btSetMin(m_floats[3], other.m_floats[3]);
- }
+ #endif
+ }
diff --git a/extern/bullet2/src/LinearMath/btQuaternion.h b/extern/bullet2/src/LinearMath/btQuaternion.h
index ee79f6eaeee..7d7f25fb4d3 100644
--- a/extern/bullet2/src/LinearMath/btQuaternion.h
+++ b/extern/bullet2/src/LinearMath/btQuaternion.h
@@ -21,24 +21,65 @@ subject to the following restrictions:
#include "btVector3.h"
#include "btQuadWord.h"
+
+
+
+
+#ifdef BT_USE_SSE
+
+const __m128 ATTRIBUTE_ALIGNED16(vOnes) = {1.0f, 1.0f, 1.0f, 1.0f};
+
+#endif
+
+#if defined(BT_USE_SSE) || defined(BT_USE_NEON)
+
+const btSimdFloat4 ATTRIBUTE_ALIGNED16(vQInv) = {-0.0f, -0.0f, -0.0f, +0.0f};
+const btSimdFloat4 ATTRIBUTE_ALIGNED16(vPPPM) = {+0.0f, +0.0f, +0.0f, -0.0f};
+
+#endif
+
/**@brief The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatrix3x3, btVector3 and btTransform. */
class btQuaternion : public btQuadWord {
public:
/**@brief No initialization constructor */
btQuaternion() {}
+#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))|| defined(BT_USE_NEON)
+ // Set Vector
+ SIMD_FORCE_INLINE btQuaternion(const btSimdFloat4 vec)
+ {
+ mVec128 = vec;
+ }
+
+ // Copy constructor
+ SIMD_FORCE_INLINE btQuaternion(const btQuaternion& rhs)
+ {
+ mVec128 = rhs.mVec128;
+ }
+
+ // Assignment Operator
+ SIMD_FORCE_INLINE btQuaternion&
+ operator=(const btQuaternion& v)
+ {
+ mVec128 = v.mVec128;
+
+ return *this;
+ }
+
+#endif
+
// template <typename btScalar>
// explicit Quaternion(const btScalar *v) : Tuple4<btScalar>(v) {}
/**@brief Constructor from scalars */
- btQuaternion(const btScalar& x, const btScalar& y, const btScalar& z, const btScalar& w)
- : btQuadWord(x, y, z, w)
+ btQuaternion(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
+ : btQuadWord(_x, _y, _z, _w)
{}
/**@brief Axis angle Constructor
* @param axis The axis which the rotation is around
* @param angle The magnitude of the rotation around the angle (Radians) */
- btQuaternion(const btVector3& axis, const btScalar& angle)
+ btQuaternion(const btVector3& _axis, const btScalar& _angle)
{
- setRotation(axis, angle);
+ setRotation(_axis, _angle);
}
/**@brief Constructor from Euler angles
* @param yaw Angle around Y unless BT_EULER_DEFAULT_ZYX defined then Z
@@ -55,13 +96,13 @@ public:
/**@brief Set the rotation using axis angle notation
* @param axis The axis around which to rotate
* @param angle The magnitude of the rotation in Radians */
- void setRotation(const btVector3& axis, const btScalar& angle)
+ void setRotation(const btVector3& axis, const btScalar& _angle)
{
btScalar d = axis.length();
btAssert(d != btScalar(0.0));
- btScalar s = btSin(angle * btScalar(0.5)) / d;
+ btScalar s = btSin(_angle * btScalar(0.5)) / d;
setValue(axis.x() * s, axis.y() * s, axis.z() * s,
- btCos(angle * btScalar(0.5)));
+ btCos(_angle * btScalar(0.5)));
}
/**@brief Set the quaternion using Euler angles
* @param yaw Angle around Y
@@ -107,7 +148,16 @@ public:
* @param q The quaternion to add to this one */
SIMD_FORCE_INLINE btQuaternion& operator+=(const btQuaternion& q)
{
- m_floats[0] += q.x(); m_floats[1] += q.y(); m_floats[2] += q.z(); m_floats[3] += q.m_floats[3];
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ mVec128 = _mm_add_ps(mVec128, q.mVec128);
+#elif defined(BT_USE_NEON)
+ mVec128 = vaddq_f32(mVec128, q.mVec128);
+#else
+ m_floats[0] += q.x();
+ m_floats[1] += q.y();
+ m_floats[2] += q.z();
+ m_floats[3] += q.m_floats[3];
+#endif
return *this;
}
@@ -115,15 +165,35 @@ public:
* @param q The quaternion to subtract from this one */
btQuaternion& operator-=(const btQuaternion& q)
{
- m_floats[0] -= q.x(); m_floats[1] -= q.y(); m_floats[2] -= q.z(); m_floats[3] -= q.m_floats[3];
- return *this;
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ mVec128 = _mm_sub_ps(mVec128, q.mVec128);
+#elif defined(BT_USE_NEON)
+ mVec128 = vsubq_f32(mVec128, q.mVec128);
+#else
+ m_floats[0] -= q.x();
+ m_floats[1] -= q.y();
+ m_floats[2] -= q.z();
+ m_floats[3] -= q.m_floats[3];
+#endif
+ return *this;
}
/**@brief Scale this quaternion
* @param s The scalar to scale by */
btQuaternion& operator*=(const btScalar& s)
{
- m_floats[0] *= s; m_floats[1] *= s; m_floats[2] *= s; m_floats[3] *= s;
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = bt_pshufd_ps(vs, 0); // (S S S S)
+ mVec128 = _mm_mul_ps(mVec128, vs);
+#elif defined(BT_USE_NEON)
+ mVec128 = vmulq_n_f32(mVec128, s);
+#else
+ m_floats[0] *= s;
+ m_floats[1] *= s;
+ m_floats[2] *= s;
+ m_floats[3] *= s;
+#endif
return *this;
}
@@ -132,17 +202,111 @@ public:
* Equivilant to this = this * q */
btQuaternion& operator*=(const btQuaternion& q)
{
- setValue(m_floats[3] * q.x() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.z() - m_floats[2] * q.y(),
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vQ2 = q.get128();
+
+ __m128 A1 = bt_pshufd_ps(mVec128, BT_SHUFFLE(0,1,2,0));
+ __m128 B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3,3,3,0));
+
+ A1 = A1 * B1;
+
+ __m128 A2 = bt_pshufd_ps(mVec128, BT_SHUFFLE(1,2,0,1));
+ __m128 B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2,0,1,1));
+
+ A2 = A2 * B2;
+
+ B1 = bt_pshufd_ps(mVec128, BT_SHUFFLE(2,0,1,2));
+ B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1,2,0,2));
+
+ B1 = B1 * B2; // A3 *= B3
+
+ mVec128 = bt_splat_ps(mVec128, 3); // A0
+ mVec128 = mVec128 * vQ2; // A0 * B0
+
+ A1 = A1 + A2; // AB12
+ mVec128 = mVec128 - B1; // AB03 = AB0 - AB3
+ A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
+ mVec128 = mVec128+ A1; // AB03 + AB12
+
+#elif defined(BT_USE_NEON)
+
+ float32x4_t vQ1 = mVec128;
+ float32x4_t vQ2 = q.get128();
+ float32x4_t A0, A1, B1, A2, B2, A3, B3;
+ float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+ {
+ float32x2x2_t tmp;
+ tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
+
+ tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
+ }
+ vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+ A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
+ B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
+
+ A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+
+ A1 = vmulq_f32(A1, B1);
+ A2 = vmulq_f32(A2, B2);
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+ A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+ A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3
+
+ // change the sign of the last element
+ A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
+ A0 = vaddq_f32(A0, A1); // AB03 + AB12
+
+ mVec128 = A0;
+#else
+ setValue(
+ m_floats[3] * q.x() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.z() - m_floats[2] * q.y(),
m_floats[3] * q.y() + m_floats[1] * q.m_floats[3] + m_floats[2] * q.x() - m_floats[0] * q.z(),
m_floats[3] * q.z() + m_floats[2] * q.m_floats[3] + m_floats[0] * q.y() - m_floats[1] * q.x(),
m_floats[3] * q.m_floats[3] - m_floats[0] * q.x() - m_floats[1] * q.y() - m_floats[2] * q.z());
+#endif
return *this;
}
/**@brief Return the dot product between this quaternion and another
* @param q The other quaternion */
btScalar dot(const btQuaternion& q) const
{
- return m_floats[0] * q.x() + m_floats[1] * q.y() + m_floats[2] * q.z() + m_floats[3] * q.m_floats[3];
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vd;
+
+ vd = _mm_mul_ps(mVec128, q.mVec128);
+
+ __m128 t = _mm_movehl_ps(vd, vd);
+ vd = _mm_add_ps(vd, t);
+ t = _mm_shuffle_ps(vd, vd, 0x55);
+ vd = _mm_add_ss(vd, t);
+
+ return _mm_cvtss_f32(vd);
+#elif defined(BT_USE_NEON)
+ float32x4_t vd = vmulq_f32(mVec128, q.mVec128);
+ float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_high_f32(vd));
+ x = vpadd_f32(x, x);
+ return vget_lane_f32(x, 0);
+#else
+ return m_floats[0] * q.x() +
+ m_floats[1] * q.y() +
+ m_floats[2] * q.z() +
+ m_floats[3] * q.m_floats[3];
+#endif
}
/**@brief Return the length squared of the quaternion */
@@ -161,7 +325,25 @@ public:
* Such that x^2 + y^2 + z^2 +w^2 = 1 */
btQuaternion& normalize()
{
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vd;
+
+ vd = _mm_mul_ps(mVec128, mVec128);
+
+ __m128 t = _mm_movehl_ps(vd, vd);
+ vd = _mm_add_ps(vd, t);
+ t = _mm_shuffle_ps(vd, vd, 0x55);
+ vd = _mm_add_ss(vd, t);
+
+ vd = _mm_sqrt_ss(vd);
+ vd = _mm_div_ss(vOnes, vd);
+ vd = bt_pshufd_ps(vd, 0); // splat
+ mVec128 = _mm_mul_ps(mVec128, vd);
+
+ return *this;
+#else
return *this /= length();
+#endif
}
/**@brief Return a scaled version of this quaternion
@@ -169,10 +351,18 @@ public:
SIMD_FORCE_INLINE btQuaternion
operator*(const btScalar& s) const
{
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = bt_pshufd_ps(vs, 0x00); // (S S S S)
+
+ return btQuaternion(_mm_mul_ps(mVec128, vs));
+#elif defined(BT_USE_NEON)
+ return btQuaternion(vmulq_n_f32(mVec128, s));
+#else
return btQuaternion(x() * s, y() * s, z() * s, m_floats[3] * s);
+#endif
}
-
/**@brief Return an inversely scaled versionof this quaternion
* @param s The inverse scale factor */
btQuaternion operator/(const btScalar& s) const
@@ -223,7 +413,13 @@ public:
/**@brief Return the inverse of this quaternion */
btQuaternion inverse() const
{
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return btQuaternion(_mm_xor_ps(mVec128, vQInv));
+#elif defined(BT_USE_NEON)
+ return btQuaternion((btSimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)vQInv));
+#else
return btQuaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]);
+#endif
}
/**@brief Return the sum of this quaternion and the other
@@ -231,8 +427,14 @@ public:
SIMD_FORCE_INLINE btQuaternion
operator+(const btQuaternion& q2) const
{
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return btQuaternion(_mm_add_ps(mVec128, q2.mVec128));
+#elif defined(BT_USE_NEON)
+ return btQuaternion(vaddq_f32(mVec128, q2.mVec128));
+#else
const btQuaternion& q1 = *this;
return btQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_floats[3] + q2.m_floats[3]);
+#endif
}
/**@brief Return the difference between this quaternion and the other
@@ -240,16 +442,28 @@ public:
SIMD_FORCE_INLINE btQuaternion
operator-(const btQuaternion& q2) const
{
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return btQuaternion(_mm_sub_ps(mVec128, q2.mVec128));
+#elif defined(BT_USE_NEON)
+ return btQuaternion(vsubq_f32(mVec128, q2.mVec128));
+#else
const btQuaternion& q1 = *this;
return btQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_floats[3] - q2.m_floats[3]);
+#endif
}
/**@brief Return the negative of this quaternion
* This simply negates each element */
SIMD_FORCE_INLINE btQuaternion operator-() const
{
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return btQuaternion(_mm_xor_ps(mVec128, btvMzeroMask));
+#elif defined(BT_USE_NEON)
+ return btQuaternion((btSimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)btvMzeroMask) );
+#else
const btQuaternion& q2 = *this;
return btQuaternion( - q2.x(), - q2.y(), - q2.z(), - q2.m_floats[3]);
+#endif
}
/**@todo document this and it's use */
SIMD_FORCE_INLINE btQuaternion farthest( const btQuaternion& qd) const
@@ -284,7 +498,7 @@ public:
btAssert(magnitude > btScalar(0));
btScalar product = dot(q) / magnitude;
- if (btFabs(product) != btScalar(1))
+ if (btFabs(product) < btScalar(1))
{
// Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
const btScalar sign = (product < 0) ? btScalar(-1) : btScalar(1);
@@ -323,29 +537,257 @@ public:
/**@brief Return the product of two quaternions */
SIMD_FORCE_INLINE btQuaternion
-operator*(const btQuaternion& q1, const btQuaternion& q2) {
- return btQuaternion(q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(),
+operator*(const btQuaternion& q1, const btQuaternion& q2)
+{
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vQ1 = q1.get128();
+ __m128 vQ2 = q2.get128();
+ __m128 A0, A1, B1, A2, B2;
+
+ A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(0,1,2,0)); // X Y z x // vtrn
+ B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3,3,3,0)); // W W W X // vdup vext
+
+ A1 = A1 * B1;
+
+ A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1,2,0,1)); // Y Z X Y // vext
+ B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2,0,1,1)); // z x Y Y // vtrn vdup
+
+ A2 = A2 * B2;
+
+ B1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2,0,1,2)); // z x Y Z // vtrn vext
+ B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1,2,0,2)); // Y Z x z // vext vtrn
+
+ B1 = B1 * B2; // A3 *= B3
+
+ A0 = bt_splat_ps(vQ1, 3); // A0
+ A0 = A0 * vQ2; // A0 * B0
+
+ A1 = A1 + A2; // AB12
+ A0 = A0 - B1; // AB03 = AB0 - AB3
+
+ A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
+ A0 = A0 + A1; // AB03 + AB12
+
+ return btQuaternion(A0);
+
+#elif defined(BT_USE_NEON)
+
+ float32x4_t vQ1 = q1.get128();
+ float32x4_t vQ2 = q2.get128();
+ float32x4_t A0, A1, B1, A2, B2, A3, B3;
+ float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+ {
+ float32x2x2_t tmp;
+ tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
+
+ tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
+ }
+ vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+ A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
+ B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
+
+ A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+
+ A1 = vmulq_f32(A1, B1);
+ A2 = vmulq_f32(A2, B2);
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+ A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+ A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3
+
+ // change the sign of the last element
+ A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
+ A0 = vaddq_f32(A0, A1); // AB03 + AB12
+
+ return btQuaternion(A0);
+
+#else
+ return btQuaternion(
+ q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(),
q1.w() * q2.y() + q1.y() * q2.w() + q1.z() * q2.x() - q1.x() * q2.z(),
q1.w() * q2.z() + q1.z() * q2.w() + q1.x() * q2.y() - q1.y() * q2.x(),
q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z());
+#endif
}
SIMD_FORCE_INLINE btQuaternion
operator*(const btQuaternion& q, const btVector3& w)
{
- return btQuaternion( q.w() * w.x() + q.y() * w.z() - q.z() * w.y(),
- q.w() * w.y() + q.z() * w.x() - q.x() * w.z(),
- q.w() * w.z() + q.x() * w.y() - q.y() * w.x(),
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vQ1 = q.get128();
+ __m128 vQ2 = w.get128();
+ __m128 A1, B1, A2, B2, A3, B3;
+
+ A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(3,3,3,0));
+ B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(0,1,2,0));
+
+ A1 = A1 * B1;
+
+ A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1,2,0,1));
+ B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2,0,1,1));
+
+ A2 = A2 * B2;
+
+ A3 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2,0,1,2));
+ B3 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1,2,0,2));
+
+ A3 = A3 * B3; // A3 *= B3
+
+ A1 = A1 + A2; // AB12
+ A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
+ A1 = A1 - A3; // AB123 = AB12 - AB3
+
+ return btQuaternion(A1);
+
+#elif defined(BT_USE_NEON)
+
+ float32x4_t vQ1 = q.get128();
+ float32x4_t vQ2 = w.get128();
+ float32x4_t A1, B1, A2, B2, A3, B3;
+ float32x2_t vQ1wx, vQ2zx, vQ1yz, vQ2yz, vQ1zx, vQ2xz;
+
+ vQ1wx = vext_f32(vget_high_f32(vQ1), vget_low_f32(vQ1), 1);
+ {
+ float32x2x2_t tmp;
+
+ tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
+
+ tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
+ }
+
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+ A1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ1), 1), vQ1wx); // W W W X
+ B1 = vcombine_f32(vget_low_f32(vQ2), vQ2zx); // X Y z x
+
+ A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+
+ A1 = vmulq_f32(A1, B1);
+ A2 = vmulq_f32(A2, B2);
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+
+ // change the sign of the last element
+ A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
+
+ A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3
+
+ return btQuaternion(A1);
+
+#else
+ return btQuaternion(
+ q.w() * w.x() + q.y() * w.z() - q.z() * w.y(),
+ q.w() * w.y() + q.z() * w.x() - q.x() * w.z(),
+ q.w() * w.z() + q.x() * w.y() - q.y() * w.x(),
-q.x() * w.x() - q.y() * w.y() - q.z() * w.z());
+#endif
}
SIMD_FORCE_INLINE btQuaternion
operator*(const btVector3& w, const btQuaternion& q)
{
- return btQuaternion( w.x() * q.w() + w.y() * q.z() - w.z() * q.y(),
- w.y() * q.w() + w.z() * q.x() - w.x() * q.z(),
- w.z() * q.w() + w.x() * q.y() - w.y() * q.x(),
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vQ1 = w.get128();
+ __m128 vQ2 = q.get128();
+ __m128 A1, B1, A2, B2, A3, B3;
+
+ A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(0,1,2,0)); // X Y z x
+ B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3,3,3,0)); // W W W X
+
+ A1 = A1 * B1;
+
+ A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1,2,0,1));
+ B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2,0,1,1));
+
+ A2 = A2 *B2;
+
+ A3 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2,0,1,2));
+ B3 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1,2,0,2));
+
+ A3 = A3 * B3; // A3 *= B3
+
+ A1 = A1 + A2; // AB12
+ A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
+ A1 = A1 - A3; // AB123 = AB12 - AB3
+
+ return btQuaternion(A1);
+
+#elif defined(BT_USE_NEON)
+
+ float32x4_t vQ1 = w.get128();
+ float32x4_t vQ2 = q.get128();
+ float32x4_t A1, B1, A2, B2, A3, B3;
+ float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
+
+ {
+ float32x2x2_t tmp;
+
+ tmp = vtrn_f32( vget_high_f32(vQ1), vget_low_f32(vQ1) ); // {z x}, {w y}
+ vQ1zx = tmp.val[0];
+
+ tmp = vtrn_f32( vget_high_f32(vQ2), vget_low_f32(vQ2) ); // {z x}, {w y}
+ vQ2zx = tmp.val[0];
+ }
+ vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
+
+ vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
+
+ vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
+ vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
+
+ A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
+ B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
+
+ A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
+ B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
+
+ A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
+ B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
+
+ A1 = vmulq_f32(A1, B1);
+ A2 = vmulq_f32(A2, B2);
+ A3 = vmulq_f32(A3, B3); // A3 *= B3
+
+ A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
+
+ // change the sign of the last element
+ A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
+
+ A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3
+
+ return btQuaternion(A1);
+
+#else
+ return btQuaternion(
+ +w.x() * q.w() + w.y() * q.z() - w.z() * q.y(),
+ +w.y() * q.w() + w.z() * q.x() - w.x() * q.z(),
+ +w.z() * q.w() + w.x() * q.y() - w.y() * q.x(),
-w.x() * q.x() - w.y() * q.y() - w.z() * q.z());
+#endif
}
/**@brief Calculate the dot product between two quaternions */
@@ -365,7 +807,7 @@ length(const btQuaternion& q)
/**@brief Return the angle between two quaternions*/
SIMD_FORCE_INLINE btScalar
-angle(const btQuaternion& q1, const btQuaternion& q2)
+btAngle(const btQuaternion& q1, const btQuaternion& q2)
{
return q1.angle(q2);
}
@@ -393,7 +835,13 @@ quatRotate(const btQuaternion& rotation, const btVector3& v)
{
btQuaternion q = rotation * v;
q *= rotation.inverse();
+#if defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return btVector3(_mm_and_ps(q.get128(), btvFFF0fMask));
+#elif defined(BT_USE_NEON)
+ return btVector3((float32x4_t)vandq_s32((int32x4_t)q.get128(), btvFFF0Mask));
+#else
return btVector3(q.getX(),q.getY(),q.getZ());
+#endif
}
SIMD_FORCE_INLINE btQuaternion
@@ -427,4 +875,3 @@ shortestArcQuatNormalize2(btVector3& v0,btVector3& v1)
-
diff --git a/extern/bullet2/src/LinearMath/btScalar.h b/extern/bullet2/src/LinearMath/btScalar.h
index ecae972243c..aaa1d6de6b4 100644
--- a/extern/bullet2/src/LinearMath/btScalar.h
+++ b/extern/bullet2/src/LinearMath/btScalar.h
@@ -28,7 +28,7 @@ subject to the following restrictions:
#include <float.h>
/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
-#define BT_BULLET_VERSION 280
+#define BT_BULLET_VERSION 281
inline int btGetVersion()
{
@@ -68,7 +68,20 @@ inline int btGetVersion()
#else
#if (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION))
+ #if _MSC_VER>1400
+ #define BT_USE_SIMD_VECTOR3
+ #endif
+
#define BT_USE_SSE
+ #ifdef BT_USE_SSE
+ //BT_USE_SSE_IN_API is disabled under Windows by default, because
+ //it makes it harder to integrate Bullet into your application under Windows
+ //(structured embedding Bullet structs/classes need to be 16-byte aligned)
+ //with relatively little performance gain
+ //If you are not embedded Bullet data in your classes, or make sure that you align those classes on 16-byte boundaries
+ //you can manually enable this line or set it in the build system for a bit of performance gain (a few percent, dependent on usage)
+ //#define BT_USE_SSE_IN_API
+ #endif //BT_USE_SSE
#include <emmintrin.h>
#endif
@@ -76,9 +89,14 @@ inline int btGetVersion()
#endif //__MINGW32__
- #include <assert.h>
#ifdef BT_DEBUG
+ #ifdef _MSC_VER
+ #include <stdio.h>
+ #define btAssert(x) { if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);__debugbreak(); }}
+ #else//_MSC_VER
+ #include <assert.h>
#define btAssert assert
+ #endif//_MSC_VER
#else
#define btAssert(x)
#endif
@@ -143,11 +161,37 @@ inline int btGetVersion()
#else
//non-windows systems
-#if (defined (__APPLE__) && defined (__i386__) && (!defined (BT_USE_DOUBLE_PRECISION)))
- #define BT_USE_SSE
- #include <emmintrin.h>
+#if (defined (__APPLE__) && (!defined (BT_USE_DOUBLE_PRECISION)))
+ #if defined (__i386__) || defined (__x86_64__)
+ #define BT_USE_SIMD_VECTOR3
+ #define BT_USE_SSE
+ //BT_USE_SSE_IN_API is enabled on Mac OSX by default, because memory is automatically aligned on 16-byte boundaries
+ //if apps run into issues, we will disable the next line
+ #define BT_USE_SSE_IN_API
+ #ifdef BT_USE_SSE
+ // include appropriate SSE level
+ #if defined (__SSE4_1__)
+ #include <smmintrin.h>
+ #elif defined (__SSSE3__)
+ #include <tmmintrin.h>
+ #elif defined (__SSE3__)
+ #include <pmmintrin.h>
+ #else
+ #include <emmintrin.h>
+ #endif
+ #endif //BT_USE_SSE
+ #elif defined( __armv7__ )
+ #ifdef __clang__
+ #define BT_USE_NEON 1
+ #define BT_USE_SIMD_VECTOR3
+
+ #if defined BT_USE_NEON && defined (__clang__)
+ #include <arm_neon.h>
+ #endif//BT_USE_NEON
+ #endif //__clang__
+ #endif//__arm__
- #define SIMD_FORCE_INLINE inline
+ #define SIMD_FORCE_INLINE inline __attribute__ ((always_inline))
///@todo: check out alignment methods for other platforms/compilers
#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
@@ -157,10 +201,22 @@ inline int btGetVersion()
#endif
#if defined(DEBUG) || defined (_DEBUG)
+ #if defined (__i386__) || defined (__x86_64__)
+ #include <stdio.h>
+ #define btAssert(x)\
+ {\
+ if(!(x))\
+ {\
+ printf("Assert %s in line %d, file %s\n",#x, __LINE__, __FILE__);\
+ asm volatile ("int3");\
+ }\
+ }
+ #else//defined (__i386__) || defined (__x86_64__)
#define btAssert assert
- #else
+ #endif//defined (__i386__) || defined (__x86_64__)
+ #else//defined(DEBUG) || defined (_DEBUG)
#define btAssert(x)
- #endif
+ #endif//defined(DEBUG) || defined (_DEBUG)
//btFullAssert is optional, slows down a lot
#define btFullAssert(x)
@@ -210,6 +266,70 @@ typedef float btScalar;
#define BT_LARGE_FLOAT 1e18f
#endif
+#ifdef BT_USE_SSE
+typedef __m128 btSimdFloat4;
+#endif//BT_USE_SSE
+
+#if defined (BT_USE_SSE)
+//#if defined BT_USE_SSE_IN_API && defined (BT_USE_SSE)
+#ifdef _WIN32
+
+#ifndef BT_NAN
+static int btNanMask = 0x7F800001;
+#define BT_NAN (*(float*)&btNanMask)
+#endif
+
+#ifndef BT_INFINITY
+static int btInfinityMask = 0x7F800000;
+#define BT_INFINITY (*(float*)&btInfinityMask)
+#endif
+
+inline __m128 operator + (const __m128 A, const __m128 B)
+{
+ return _mm_add_ps(A, B);
+}
+
+inline __m128 operator - (const __m128 A, const __m128 B)
+{
+ return _mm_sub_ps(A, B);
+}
+
+inline __m128 operator * (const __m128 A, const __m128 B)
+{
+ return _mm_mul_ps(A, B);
+}
+
+#define btCastfTo128i(a) (_mm_castps_si128(a))
+#define btCastfTo128d(a) (_mm_castps_pd(a))
+#define btCastiTo128f(a) (_mm_castsi128_ps(a))
+#define btCastdTo128f(a) (_mm_castpd_ps(a))
+#define btCastdTo128i(a) (_mm_castpd_si128(a))
+#define btAssign128(r0,r1,r2,r3) _mm_setr_ps(r0,r1,r2,r3)
+
+#else//_WIN32
+
+#define btCastfTo128i(a) ((__m128i)(a))
+#define btCastfTo128d(a) ((__m128d)(a))
+#define btCastiTo128f(a) ((__m128) (a))
+#define btCastdTo128f(a) ((__m128) (a))
+#define btCastdTo128i(a) ((__m128i)(a))
+#define btAssign128(r0,r1,r2,r3) (__m128){r0,r1,r2,r3}
+#define BT_INFINITY INFINITY
+#define BT_NAN NAN
+#endif//_WIN32
+#endif //BT_USE_SSE_IN_API
+
+#ifdef BT_USE_NEON
+#include <arm_neon.h>
+
+typedef float32x4_t btSimdFloat4;
+#define BT_INFINITY INFINITY
+#define BT_NAN NAN
+#define btAssign128(r0,r1,r2,r3) (float32x4_t){r0,r1,r2,r3}
+#endif
+
+
+
#define BT_DECLARE_ALIGNED_ALLOCATOR() \
diff --git a/extern/bullet2/src/LinearMath/btSerializer.cpp b/extern/bullet2/src/LinearMath/btSerializer.cpp
index 49c25b7ea2a..d6b2b3a5a5c 100644
--- a/extern/bullet2/src/LinearMath/btSerializer.cpp
+++ b/extern/bullet2/src/LinearMath/btSerializer.cpp
@@ -1,841 +1,908 @@
char sBulletDNAstr[]= {
-83,68,78,65,78,65,77,69,44,1,0,0,109,95,115,105,122,101,0,109,
-95,99,97,112,97,99,105,116,121,0,42,109,95,100,97,116,97,0,109,95,
-99,111,108,108,105,115,105,111,110,83,104,97,112,101,115,0,109,95,99,111,
-108,108,105,115,105,111,110,79,98,106,101,99,116,115,0,109,95,99,111,110,
-115,116,114,97,105,110,116,115,0,42,102,105,114,115,116,0,42,108,97,115,
-116,0,109,95,102,108,111,97,116,115,91,52,93,0,109,95,101,108,91,51,
-93,0,109,95,98,97,115,105,115,0,109,95,111,114,105,103,105,110,0,109,
-95,114,111,111,116,78,111,100,101,73,110,100,101,120,0,109,95,115,117,98,
-116,114,101,101,83,105,122,101,0,109,95,113,117,97,110,116,105,122,101,100,
-65,97,98,98,77,105,110,91,51,93,0,109,95,113,117,97,110,116,105,122,
-101,100,65,97,98,98,77,97,120,91,51,93,0,109,95,97,97,98,98,77,
-105,110,79,114,103,0,109,95,97,97,98,98,77,97,120,79,114,103,0,109,
-95,101,115,99,97,112,101,73,110,100,101,120,0,109,95,115,117,98,80,97,
-114,116,0,109,95,116,114,105,97,110,103,108,101,73,110,100,101,120,0,109,
-95,112,97,100,91,52,93,0,109,95,101,115,99,97,112,101,73,110,100,101,
-120,79,114,84,114,105,97,110,103,108,101,73,110,100,101,120,0,109,95,98,
-118,104,65,97,98,98,77,105,110,0,109,95,98,118,104,65,97,98,98,77,
-97,120,0,109,95,98,118,104,81,117,97,110,116,105,122,97,116,105,111,110,
-0,109,95,99,117,114,78,111,100,101,73,110,100,101,120,0,109,95,117,115,
-101,81,117,97,110,116,105,122,97,116,105,111,110,0,109,95,110,117,109,67,
-111,110,116,105,103,117,111,117,115,76,101,97,102,78,111,100,101,115,0,109,
-95,110,117,109,81,117,97,110,116,105,122,101,100,67,111,110,116,105,103,117,
-111,117,115,78,111,100,101,115,0,42,109,95,99,111,110,116,105,103,117,111,
-117,115,78,111,100,101,115,80,116,114,0,42,109,95,113,117,97,110,116,105,
-122,101,100,67,111,110,116,105,103,117,111,117,115,78,111,100,101,115,80,116,
-114,0,42,109,95,115,117,98,84,114,101,101,73,110,102,111,80,116,114,0,
-109,95,116,114,97,118,101,114,115,97,108,77,111,100,101,0,109,95,110,117,
-109,83,117,98,116,114,101,101,72,101,97,100,101,114,115,0,42,109,95,110,
-97,109,101,0,109,95,115,104,97,112,101,84,121,112,101,0,109,95,112,97,
-100,100,105,110,103,91,52,93,0,109,95,99,111,108,108,105,115,105,111,110,
-83,104,97,112,101,68,97,116,97,0,109,95,108,111,99,97,108,83,99,97,
-108,105,110,103,0,109,95,112,108,97,110,101,78,111,114,109,97,108,0,109,
-95,112,108,97,110,101,67,111,110,115,116,97,110,116,0,109,95,105,109,112,
-108,105,99,105,116,83,104,97,112,101,68,105,109,101,110,115,105,111,110,115,
-0,109,95,99,111,108,108,105,115,105,111,110,77,97,114,103,105,110,0,109,
-95,112,97,100,100,105,110,103,0,109,95,112,111,115,0,109,95,114,97,100,
-105,117,115,0,109,95,99,111,110,118,101,120,73,110,116,101,114,110,97,108,
-83,104,97,112,101,68,97,116,97,0,42,109,95,108,111,99,97,108,80,111,
-115,105,116,105,111,110,65,114,114,97,121,80,116,114,0,109,95,108,111,99,
-97,108,80,111,115,105,116,105,111,110,65,114,114,97,121,83,105,122,101,0,
-109,95,118,97,108,117,101,0,109,95,112,97,100,91,50,93,0,109,95,118,
-97,108,117,101,115,91,51,93,0,109,95,112,97,100,0,42,109,95,118,101,
-114,116,105,99,101,115,51,102,0,42,109,95,118,101,114,116,105,99,101,115,
-51,100,0,42,109,95,105,110,100,105,99,101,115,51,50,0,42,109,95,51,
-105,110,100,105,99,101,115,49,54,0,42,109,95,51,105,110,100,105,99,101,
-115,56,0,42,109,95,105,110,100,105,99,101,115,49,54,0,109,95,110,117,
-109,84,114,105,97,110,103,108,101,115,0,109,95,110,117,109,86,101,114,116,
-105,99,101,115,0,42,109,95,109,101,115,104,80,97,114,116,115,80,116,114,
-0,109,95,115,99,97,108,105,110,103,0,109,95,110,117,109,77,101,115,104,
-80,97,114,116,115,0,109,95,109,101,115,104,73,110,116,101,114,102,97,99,
-101,0,42,109,95,113,117,97,110,116,105,122,101,100,70,108,111,97,116,66,
-118,104,0,42,109,95,113,117,97,110,116,105,122,101,100,68,111,117,98,108,
-101,66,118,104,0,42,109,95,116,114,105,97,110,103,108,101,73,110,102,111,
-77,97,112,0,109,95,112,97,100,51,91,52,93,0,109,95,116,114,105,109,
-101,115,104,83,104,97,112,101,68,97,116,97,0,109,95,116,114,97,110,115,
-102,111,114,109,0,42,109,95,99,104,105,108,100,83,104,97,112,101,0,109,
-95,99,104,105,108,100,83,104,97,112,101,84,121,112,101,0,109,95,99,104,
-105,108,100,77,97,114,103,105,110,0,42,109,95,99,104,105,108,100,83,104,
-97,112,101,80,116,114,0,109,95,110,117,109,67,104,105,108,100,83,104,97,
-112,101,115,0,109,95,117,112,65,120,105,115,0,109,95,102,108,97,103,115,
-0,109,95,101,100,103,101,86,48,86,49,65,110,103,108,101,0,109,95,101,
-100,103,101,86,49,86,50,65,110,103,108,101,0,109,95,101,100,103,101,86,
-50,86,48,65,110,103,108,101,0,42,109,95,104,97,115,104,84,97,98,108,
-101,80,116,114,0,42,109,95,110,101,120,116,80,116,114,0,42,109,95,118,
-97,108,117,101,65,114,114,97,121,80,116,114,0,42,109,95,107,101,121,65,
-114,114,97,121,80,116,114,0,109,95,99,111,110,118,101,120,69,112,115,105,
-108,111,110,0,109,95,112,108,97,110,97,114,69,112,115,105,108,111,110,0,
-109,95,101,113,117,97,108,86,101,114,116,101,120,84,104,114,101,115,104,111,
-108,100,0,109,95,101,100,103,101,68,105,115,116,97,110,99,101,84,104,114,
-101,115,104,111,108,100,0,109,95,122,101,114,111,65,114,101,97,84,104,114,
-101,115,104,111,108,100,0,109,95,110,101,120,116,83,105,122,101,0,109,95,
-104,97,115,104,84,97,98,108,101,83,105,122,101,0,109,95,110,117,109,86,
-97,108,117,101,115,0,109,95,110,117,109,75,101,121,115,0,109,95,103,105,
-109,112,97,99,116,83,117,98,84,121,112,101,0,42,109,95,117,110,115,99,
-97,108,101,100,80,111,105,110,116,115,70,108,111,97,116,80,116,114,0,42,
-109,95,117,110,115,99,97,108,101,100,80,111,105,110,116,115,68,111,117,98,
-108,101,80,116,114,0,109,95,110,117,109,85,110,115,99,97,108,101,100,80,
-111,105,110,116,115,0,109,95,112,97,100,100,105,110,103,51,91,52,93,0,
-42,109,95,98,114,111,97,100,112,104,97,115,101,72,97,110,100,108,101,0,
-42,109,95,99,111,108,108,105,115,105,111,110,83,104,97,112,101,0,42,109,
-95,114,111,111,116,67,111,108,108,105,115,105,111,110,83,104,97,112,101,0,
-109,95,119,111,114,108,100,84,114,97,110,115,102,111,114,109,0,109,95,105,
-110,116,101,114,112,111,108,97,116,105,111,110,87,111,114,108,100,84,114,97,
-110,115,102,111,114,109,0,109,95,105,110,116,101,114,112,111,108,97,116,105,
-111,110,76,105,110,101,97,114,86,101,108,111,99,105,116,121,0,109,95,105,
-110,116,101,114,112,111,108,97,116,105,111,110,65,110,103,117,108,97,114,86,
-101,108,111,99,105,116,121,0,109,95,97,110,105,115,111,116,114,111,112,105,
-99,70,114,105,99,116,105,111,110,0,109,95,99,111,110,116,97,99,116,80,
-114,111,99,101,115,115,105,110,103,84,104,114,101,115,104,111,108,100,0,109,
-95,100,101,97,99,116,105,118,97,116,105,111,110,84,105,109,101,0,109,95,
-102,114,105,99,116,105,111,110,0,109,95,114,101,115,116,105,116,117,116,105,
-111,110,0,109,95,104,105,116,70,114,97,99,116,105,111,110,0,109,95,99,
-99,100,83,119,101,112,116,83,112,104,101,114,101,82,97,100,105,117,115,0,
-109,95,99,99,100,77,111,116,105,111,110,84,104,114,101,115,104,111,108,100,
-0,109,95,104,97,115,65,110,105,115,111,116,114,111,112,105,99,70,114,105,
-99,116,105,111,110,0,109,95,99,111,108,108,105,115,105,111,110,70,108,97,
-103,115,0,109,95,105,115,108,97,110,100,84,97,103,49,0,109,95,99,111,
-109,112,97,110,105,111,110,73,100,0,109,95,97,99,116,105,118,97,116,105,
-111,110,83,116,97,116,101,49,0,109,95,105,110,116,101,114,110,97,108,84,
-121,112,101,0,109,95,99,104,101,99,107,67,111,108,108,105,100,101,87,105,
-116,104,0,109,95,99,111,108,108,105,115,105,111,110,79,98,106,101,99,116,
-68,97,116,97,0,109,95,105,110,118,73,110,101,114,116,105,97,84,101,110,
-115,111,114,87,111,114,108,100,0,109,95,108,105,110,101,97,114,86,101,108,
-111,99,105,116,121,0,109,95,97,110,103,117,108,97,114,86,101,108,111,99,
-105,116,121,0,109,95,97,110,103,117,108,97,114,70,97,99,116,111,114,0,
-109,95,108,105,110,101,97,114,70,97,99,116,111,114,0,109,95,103,114,97,
-118,105,116,121,0,109,95,103,114,97,118,105,116,121,95,97,99,99,101,108,
-101,114,97,116,105,111,110,0,109,95,105,110,118,73,110,101,114,116,105,97,
-76,111,99,97,108,0,109,95,116,111,116,97,108,70,111,114,99,101,0,109,
-95,116,111,116,97,108,84,111,114,113,117,101,0,109,95,105,110,118,101,114,
-115,101,77,97,115,115,0,109,95,108,105,110,101,97,114,68,97,109,112,105,
-110,103,0,109,95,97,110,103,117,108,97,114,68,97,109,112,105,110,103,0,
-109,95,97,100,100,105,116,105,111,110,97,108,68,97,109,112,105,110,103,70,
-97,99,116,111,114,0,109,95,97,100,100,105,116,105,111,110,97,108,76,105,
-110,101,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,108,100,
-83,113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,103,117,
-108,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,108,100,83,
-113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,103,117,108,
-97,114,68,97,109,112,105,110,103,70,97,99,116,111,114,0,109,95,108,105,
-110,101,97,114,83,108,101,101,112,105,110,103,84,104,114,101,115,104,111,108,
-100,0,109,95,97,110,103,117,108,97,114,83,108,101,101,112,105,110,103,84,
-104,114,101,115,104,111,108,100,0,109,95,97,100,100,105,116,105,111,110,97,
-108,68,97,109,112,105,110,103,0,109,95,110,117,109,67,111,110,115,116,114,
-97,105,110,116,82,111,119,115,0,110,117,98,0,42,109,95,114,98,65,0,
-42,109,95,114,98,66,0,109,95,111,98,106,101,99,116,84,121,112,101,0,
-109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,84,121,112,101,
-0,109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,73,100,0,
-109,95,110,101,101,100,115,70,101,101,100,98,97,99,107,0,109,95,97,112,
-112,108,105,101,100,73,109,112,117,108,115,101,0,109,95,100,98,103,68,114,
-97,119,83,105,122,101,0,109,95,100,105,115,97,98,108,101,67,111,108,108,
-105,115,105,111,110,115,66,101,116,119,101,101,110,76,105,110,107,101,100,66,
-111,100,105,101,115,0,109,95,111,118,101,114,114,105,100,101,78,117,109,83,
-111,108,118,101,114,73,116,101,114,97,116,105,111,110,115,0,109,95,98,114,
-101,97,107,105,110,103,73,109,112,117,108,115,101,84,104,114,101,115,104,111,
-108,100,0,109,95,105,115,69,110,97,98,108,101,100,0,109,95,116,121,112,
-101,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,109,95,112,105,
-118,111,116,73,110,65,0,109,95,112,105,118,111,116,73,110,66,0,109,95,
-114,98,65,70,114,97,109,101,0,109,95,114,98,66,70,114,97,109,101,0,
-109,95,117,115,101,82,101,102,101,114,101,110,99,101,70,114,97,109,101,65,
-0,109,95,97,110,103,117,108,97,114,79,110,108,121,0,109,95,101,110,97,
-98,108,101,65,110,103,117,108,97,114,77,111,116,111,114,0,109,95,109,111,
-116,111,114,84,97,114,103,101,116,86,101,108,111,99,105,116,121,0,109,95,
-109,97,120,77,111,116,111,114,73,109,112,117,108,115,101,0,109,95,108,111,
-119,101,114,76,105,109,105,116,0,109,95,117,112,112,101,114,76,105,109,105,
-116,0,109,95,108,105,109,105,116,83,111,102,116,110,101,115,115,0,109,95,
-98,105,97,115,70,97,99,116,111,114,0,109,95,114,101,108,97,120,97,116,
-105,111,110,70,97,99,116,111,114,0,109,95,115,119,105,110,103,83,112,97,
-110,49,0,109,95,115,119,105,110,103,83,112,97,110,50,0,109,95,116,119,
-105,115,116,83,112,97,110,0,109,95,100,97,109,112,105,110,103,0,109,95,
-108,105,110,101,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95,108,
-105,110,101,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,97,110,
-103,117,108,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95,97,110,
-103,117,108,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,117,115,
-101,76,105,110,101,97,114,82,101,102,101,114,101,110,99,101,70,114,97,109,
-101,65,0,109,95,117,115,101,79,102,102,115,101,116,70,111,114,67,111,110,
-115,116,114,97,105,110,116,70,114,97,109,101,0,109,95,54,100,111,102,68,
-97,116,97,0,109,95,115,112,114,105,110,103,69,110,97,98,108,101,100,91,
-54,93,0,109,95,101,113,117,105,108,105,98,114,105,117,109,80,111,105,110,
-116,91,54,93,0,109,95,115,112,114,105,110,103,83,116,105,102,102,110,101,
-115,115,91,54,93,0,109,95,115,112,114,105,110,103,68,97,109,112,105,110,
-103,91,54,93,0,109,95,108,105,110,101,97,114,83,116,105,102,102,110,101,
-115,115,0,109,95,97,110,103,117,108,97,114,83,116,105,102,102,110,101,115,
-115,0,109,95,118,111,108,117,109,101,83,116,105,102,102,110,101,115,115,0,
-42,109,95,109,97,116,101,114,105,97,108,0,109,95,112,111,115,105,116,105,
-111,110,0,109,95,112,114,101,118,105,111,117,115,80,111,115,105,116,105,111,
-110,0,109,95,118,101,108,111,99,105,116,121,0,109,95,97,99,99,117,109,
-117,108,97,116,101,100,70,111,114,99,101,0,109,95,110,111,114,109,97,108,
-0,109,95,97,114,101,97,0,109,95,97,116,116,97,99,104,0,109,95,110,
-111,100,101,73,110,100,105,99,101,115,91,50,93,0,109,95,114,101,115,116,
-76,101,110,103,116,104,0,109,95,98,98,101,110,100,105,110,103,0,109,95,
-110,111,100,101,73,110,100,105,99,101,115,91,51,93,0,109,95,114,101,115,
-116,65,114,101,97,0,109,95,99,48,91,52,93,0,109,95,110,111,100,101,
-73,110,100,105,99,101,115,91,52,93,0,109,95,114,101,115,116,86,111,108,
-117,109,101,0,109,95,99,49,0,109,95,99,50,0,109,95,99,48,0,109,
-95,108,111,99,97,108,70,114,97,109,101,0,42,109,95,114,105,103,105,100,
-66,111,100,121,0,109,95,110,111,100,101,73,110,100,101,120,0,109,95,97,
-101,114,111,77,111,100,101,108,0,109,95,98,97,117,109,103,97,114,116,101,
-0,109,95,100,114,97,103,0,109,95,108,105,102,116,0,109,95,112,114,101,
-115,115,117,114,101,0,109,95,118,111,108,117,109,101,0,109,95,100,121,110,
-97,109,105,99,70,114,105,99,116,105,111,110,0,109,95,112,111,115,101,77,
-97,116,99,104,0,109,95,114,105,103,105,100,67,111,110,116,97,99,116,72,
-97,114,100,110,101,115,115,0,109,95,107,105,110,101,116,105,99,67,111,110,
-116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,67,
-111,110,116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,97,110,99,
-104,111,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,82,105,
-103,105,100,67,108,117,115,116,101,114,72,97,114,100,110,101,115,115,0,109,
-95,115,111,102,116,75,105,110,101,116,105,99,67,108,117,115,116,101,114,72,
-97,114,100,110,101,115,115,0,109,95,115,111,102,116,83,111,102,116,67,108,
-117,115,116,101,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,
-82,105,103,105,100,67,108,117,115,116,101,114,73,109,112,117,108,115,101,83,
-112,108,105,116,0,109,95,115,111,102,116,75,105,110,101,116,105,99,67,108,
-117,115,116,101,114,73,109,112,117,108,115,101,83,112,108,105,116,0,109,95,
-115,111,102,116,83,111,102,116,67,108,117,115,116,101,114,73,109,112,117,108,
-115,101,83,112,108,105,116,0,109,95,109,97,120,86,111,108,117,109,101,0,
-109,95,116,105,109,101,83,99,97,108,101,0,109,95,118,101,108,111,99,105,
-116,121,73,116,101,114,97,116,105,111,110,115,0,109,95,112,111,115,105,116,
-105,111,110,73,116,101,114,97,116,105,111,110,115,0,109,95,100,114,105,102,
-116,73,116,101,114,97,116,105,111,110,115,0,109,95,99,108,117,115,116,101,
-114,73,116,101,114,97,116,105,111,110,115,0,109,95,114,111,116,0,109,95,
-115,99,97,108,101,0,109,95,97,113,113,0,109,95,99,111,109,0,42,109,
-95,112,111,115,105,116,105,111,110,115,0,42,109,95,119,101,105,103,104,116,
-115,0,109,95,110,117,109,80,111,115,105,116,105,111,110,115,0,109,95,110,
-117,109,87,101,105,103,116,115,0,109,95,98,118,111,108,117,109,101,0,109,
-95,98,102,114,97,109,101,0,109,95,102,114,97,109,101,120,102,111,114,109,
-0,109,95,108,111,99,105,105,0,109,95,105,110,118,119,105,0,109,95,118,
-105,109,112,117,108,115,101,115,91,50,93,0,109,95,100,105,109,112,117,108,
-115,101,115,91,50,93,0,109,95,108,118,0,109,95,97,118,0,42,109,95,
-102,114,97,109,101,114,101,102,115,0,42,109,95,110,111,100,101,73,110,100,
-105,99,101,115,0,42,109,95,109,97,115,115,101,115,0,109,95,110,117,109,
-70,114,97,109,101,82,101,102,115,0,109,95,110,117,109,78,111,100,101,115,
-0,109,95,110,117,109,77,97,115,115,101,115,0,109,95,105,100,109,97,115,
-115,0,109,95,105,109,97,115,115,0,109,95,110,118,105,109,112,117,108,115,
-101,115,0,109,95,110,100,105,109,112,117,108,115,101,115,0,109,95,110,100,
-97,109,112,105,110,103,0,109,95,108,100,97,109,112,105,110,103,0,109,95,
-97,100,97,109,112,105,110,103,0,109,95,109,97,116,99,104,105,110,103,0,
-109,95,109,97,120,83,101,108,102,67,111,108,108,105,115,105,111,110,73,109,
-112,117,108,115,101,0,109,95,115,101,108,102,67,111,108,108,105,115,105,111,
-110,73,109,112,117,108,115,101,70,97,99,116,111,114,0,109,95,99,111,110,
-116,97,105,110,115,65,110,99,104,111,114,0,109,95,99,111,108,108,105,100,
-101,0,109,95,99,108,117,115,116,101,114,73,110,100,101,120,0,42,109,95,
-98,111,100,121,65,0,42,109,95,98,111,100,121,66,0,109,95,114,101,102,
-115,91,50,93,0,109,95,99,102,109,0,109,95,101,114,112,0,109,95,115,
-112,108,105,116,0,109,95,100,101,108,101,116,101,0,109,95,114,101,108,80,
-111,115,105,116,105,111,110,91,50,93,0,109,95,98,111,100,121,65,116,121,
-112,101,0,109,95,98,111,100,121,66,116,121,112,101,0,109,95,106,111,105,
-110,116,84,121,112,101,0,42,109,95,112,111,115,101,0,42,42,109,95,109,
-97,116,101,114,105,97,108,115,0,42,109,95,110,111,100,101,115,0,42,109,
-95,108,105,110,107,115,0,42,109,95,102,97,99,101,115,0,42,109,95,116,
-101,116,114,97,104,101,100,114,97,0,42,109,95,97,110,99,104,111,114,115,
-0,42,109,95,99,108,117,115,116,101,114,115,0,42,109,95,106,111,105,110,
-116,115,0,109,95,110,117,109,77,97,116,101,114,105,97,108,115,0,109,95,
-110,117,109,76,105,110,107,115,0,109,95,110,117,109,70,97,99,101,115,0,
-109,95,110,117,109,84,101,116,114,97,104,101,100,114,97,0,109,95,110,117,
-109,65,110,99,104,111,114,115,0,109,95,110,117,109,67,108,117,115,116,101,
-114,115,0,109,95,110,117,109,74,111,105,110,116,115,0,109,95,99,111,110,
-102,105,103,0,84,89,80,69,72,0,0,0,99,104,97,114,0,117,99,104,
-97,114,0,115,104,111,114,116,0,117,115,104,111,114,116,0,105,110,116,0,
-108,111,110,103,0,117,108,111,110,103,0,102,108,111,97,116,0,100,111,117,
-98,108,101,0,118,111,105,100,0,80,111,105,110,116,101,114,65,114,114,97,
-121,0,98,116,80,104,121,115,105,99,115,83,121,115,116,101,109,0,76,105,
-115,116,66,97,115,101,0,98,116,86,101,99,116,111,114,51,70,108,111,97,
-116,68,97,116,97,0,98,116,86,101,99,116,111,114,51,68,111,117,98,108,
-101,68,97,116,97,0,98,116,77,97,116,114,105,120,51,120,51,70,108,111,
-97,116,68,97,116,97,0,98,116,77,97,116,114,105,120,51,120,51,68,111,
-117,98,108,101,68,97,116,97,0,98,116,84,114,97,110,115,102,111,114,109,
-70,108,111,97,116,68,97,116,97,0,98,116,84,114,97,110,115,102,111,114,
-109,68,111,117,98,108,101,68,97,116,97,0,98,116,66,118,104,83,117,98,
-116,114,101,101,73,110,102,111,68,97,116,97,0,98,116,79,112,116,105,109,
-105,122,101,100,66,118,104,78,111,100,101,70,108,111,97,116,68,97,116,97,
-0,98,116,79,112,116,105,109,105,122,101,100,66,118,104,78,111,100,101,68,
-111,117,98,108,101,68,97,116,97,0,98,116,81,117,97,110,116,105,122,101,
-100,66,118,104,78,111,100,101,68,97,116,97,0,98,116,81,117,97,110,116,
-105,122,101,100,66,118,104,70,108,111,97,116,68,97,116,97,0,98,116,81,
-117,97,110,116,105,122,101,100,66,118,104,68,111,117,98,108,101,68,97,116,
-97,0,98,116,67,111,108,108,105,115,105,111,110,83,104,97,112,101,68,97,
-116,97,0,98,116,83,116,97,116,105,99,80,108,97,110,101,83,104,97,112,
-101,68,97,116,97,0,98,116,67,111,110,118,101,120,73,110,116,101,114,110,
-97,108,83,104,97,112,101,68,97,116,97,0,98,116,80,111,115,105,116,105,
-111,110,65,110,100,82,97,100,105,117,115,0,98,116,77,117,108,116,105,83,
-112,104,101,114,101,83,104,97,112,101,68,97,116,97,0,98,116,73,110,116,
-73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114,116,73,110,116,
-73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114,116,73,110,116,
-73,110,100,101,120,84,114,105,112,108,101,116,68,97,116,97,0,98,116,67,
-104,97,114,73,110,100,101,120,84,114,105,112,108,101,116,68,97,116,97,0,
-98,116,77,101,115,104,80,97,114,116,68,97,116,97,0,98,116,83,116,114,
-105,100,105,110,103,77,101,115,104,73,110,116,101,114,102,97,99,101,68,97,
-116,97,0,98,116,84,114,105,97,110,103,108,101,77,101,115,104,83,104,97,
-112,101,68,97,116,97,0,98,116,84,114,105,97,110,103,108,101,73,110,102,
-111,77,97,112,68,97,116,97,0,98,116,83,99,97,108,101,100,84,114,105,
-97,110,103,108,101,77,101,115,104,83,104,97,112,101,68,97,116,97,0,98,
-116,67,111,109,112,111,117,110,100,83,104,97,112,101,67,104,105,108,100,68,
-97,116,97,0,98,116,67,111,109,112,111,117,110,100,83,104,97,112,101,68,
-97,116,97,0,98,116,67,121,108,105,110,100,101,114,83,104,97,112,101,68,
-97,116,97,0,98,116,67,97,112,115,117,108,101,83,104,97,112,101,68,97,
-116,97,0,98,116,84,114,105,97,110,103,108,101,73,110,102,111,68,97,116,
-97,0,98,116,71,73,109,112,97,99,116,77,101,115,104,83,104,97,112,101,
-68,97,116,97,0,98,116,67,111,110,118,101,120,72,117,108,108,83,104,97,
-112,101,68,97,116,97,0,98,116,67,111,108,108,105,115,105,111,110,79,98,
-106,101,99,116,68,111,117,98,108,101,68,97,116,97,0,98,116,67,111,108,
-108,105,115,105,111,110,79,98,106,101,99,116,70,108,111,97,116,68,97,116,
-97,0,98,116,82,105,103,105,100,66,111,100,121,70,108,111,97,116,68,97,
-116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,111,117,98,108,101,
-68,97,116,97,0,98,116,67,111,110,115,116,114,97,105,110,116,73,110,102,
-111,49,0,98,116,84,121,112,101,100,67,111,110,115,116,114,97,105,110,116,
-68,97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,97,116,97,
-0,98,116,80,111,105,110,116,50,80,111,105,110,116,67,111,110,115,116,114,
-97,105,110,116,70,108,111,97,116,68,97,116,97,0,98,116,80,111,105,110,
-116,50,80,111,105,110,116,67,111,110,115,116,114,97,105,110,116,68,111,117,
-98,108,101,68,97,116,97,0,98,116,72,105,110,103,101,67,111,110,115,116,
-114,97,105,110,116,68,111,117,98,108,101,68,97,116,97,0,98,116,72,105,
-110,103,101,67,111,110,115,116,114,97,105,110,116,70,108,111,97,116,68,97,
-116,97,0,98,116,67,111,110,101,84,119,105,115,116,67,111,110,115,116,114,
-97,105,110,116,68,97,116,97,0,98,116,71,101,110,101,114,105,99,54,68,
-111,102,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,98,116,71,
-101,110,101,114,105,99,54,68,111,102,83,112,114,105,110,103,67,111,110,115,
-116,114,97,105,110,116,68,97,116,97,0,98,116,83,108,105,100,101,114,67,
-111,110,115,116,114,97,105,110,116,68,97,116,97,0,83,111,102,116,66,111,
-100,121,77,97,116,101,114,105,97,108,68,97,116,97,0,83,111,102,116,66,
-111,100,121,78,111,100,101,68,97,116,97,0,83,111,102,116,66,111,100,121,
-76,105,110,107,68,97,116,97,0,83,111,102,116,66,111,100,121,70,97,99,
-101,68,97,116,97,0,83,111,102,116,66,111,100,121,84,101,116,114,97,68,
-97,116,97,0,83,111,102,116,82,105,103,105,100,65,110,99,104,111,114,68,
-97,116,97,0,83,111,102,116,66,111,100,121,67,111,110,102,105,103,68,97,
-116,97,0,83,111,102,116,66,111,100,121,80,111,115,101,68,97,116,97,0,
-83,111,102,116,66,111,100,121,67,108,117,115,116,101,114,68,97,116,97,0,
-98,116,83,111,102,116,66,111,100,121,74,111,105,110,116,68,97,116,97,0,
-98,116,83,111,102,116,66,111,100,121,70,108,111,97,116,68,97,116,97,0,
-84,76,69,78,1,0,1,0,2,0,2,0,4,0,4,0,4,0,4,0,
-8,0,0,0,12,0,36,0,8,0,16,0,32,0,48,0,96,0,64,0,
--128,0,20,0,48,0,80,0,16,0,84,0,-124,0,12,0,52,0,52,0,
-20,0,64,0,4,0,4,0,8,0,4,0,32,0,28,0,60,0,56,0,
-76,0,76,0,24,0,60,0,60,0,16,0,64,0,68,0,-56,1,-8,0,
--32,1,-104,3,8,0,52,0,0,0,84,0,116,0,92,1,-36,0,-44,0,
--4,0,92,1,-52,0,16,0,100,0,20,0,36,0,100,0,92,0,104,0,
--64,0,92,1,104,0,-92,1,83,84,82,67,61,0,0,0,10,0,3,0,
-4,0,0,0,4,0,1,0,9,0,2,0,11,0,3,0,10,0,3,0,
-10,0,4,0,10,0,5,0,12,0,2,0,9,0,6,0,9,0,7,0,
-13,0,1,0,7,0,8,0,14,0,1,0,8,0,8,0,15,0,1,0,
-13,0,9,0,16,0,1,0,14,0,9,0,17,0,2,0,15,0,10,0,
-13,0,11,0,18,0,2,0,16,0,10,0,14,0,11,0,19,0,4,0,
-4,0,12,0,4,0,13,0,2,0,14,0,2,0,15,0,20,0,6,0,
-13,0,16,0,13,0,17,0,4,0,18,0,4,0,19,0,4,0,20,0,
-0,0,21,0,21,0,6,0,14,0,16,0,14,0,17,0,4,0,18,0,
-4,0,19,0,4,0,20,0,0,0,21,0,22,0,3,0,2,0,14,0,
-2,0,15,0,4,0,22,0,23,0,12,0,13,0,23,0,13,0,24,0,
-13,0,25,0,4,0,26,0,4,0,27,0,4,0,28,0,4,0,29,0,
-20,0,30,0,22,0,31,0,19,0,32,0,4,0,33,0,4,0,34,0,
-24,0,12,0,14,0,23,0,14,0,24,0,14,0,25,0,4,0,26,0,
-4,0,27,0,4,0,28,0,4,0,29,0,21,0,30,0,22,0,31,0,
-4,0,33,0,4,0,34,0,19,0,32,0,25,0,3,0,0,0,35,0,
-4,0,36,0,0,0,37,0,26,0,5,0,25,0,38,0,13,0,39,0,
-13,0,40,0,7,0,41,0,0,0,21,0,27,0,5,0,25,0,38,0,
-13,0,39,0,13,0,42,0,7,0,43,0,4,0,44,0,28,0,2,0,
-13,0,45,0,7,0,46,0,29,0,4,0,27,0,47,0,28,0,48,0,
-4,0,49,0,0,0,37,0,30,0,1,0,4,0,50,0,31,0,2,0,
-2,0,50,0,0,0,51,0,32,0,2,0,2,0,52,0,0,0,51,0,
-33,0,2,0,0,0,52,0,0,0,53,0,34,0,8,0,13,0,54,0,
-14,0,55,0,30,0,56,0,32,0,57,0,33,0,58,0,31,0,59,0,
-4,0,60,0,4,0,61,0,35,0,4,0,34,0,62,0,13,0,63,0,
-4,0,64,0,0,0,37,0,36,0,7,0,25,0,38,0,35,0,65,0,
-23,0,66,0,24,0,67,0,37,0,68,0,7,0,43,0,0,0,69,0,
-38,0,2,0,36,0,70,0,13,0,39,0,39,0,4,0,17,0,71,0,
-25,0,72,0,4,0,73,0,7,0,74,0,40,0,4,0,25,0,38,0,
-39,0,75,0,4,0,76,0,7,0,43,0,41,0,3,0,27,0,47,0,
-4,0,77,0,0,0,37,0,42,0,3,0,27,0,47,0,4,0,77,0,
-0,0,37,0,43,0,4,0,4,0,78,0,7,0,79,0,7,0,80,0,
-7,0,81,0,37,0,14,0,4,0,82,0,4,0,83,0,43,0,84,0,
-4,0,85,0,7,0,86,0,7,0,87,0,7,0,88,0,7,0,89,0,
-7,0,90,0,4,0,91,0,4,0,92,0,4,0,93,0,4,0,94,0,
-0,0,37,0,44,0,5,0,25,0,38,0,35,0,65,0,13,0,39,0,
-7,0,43,0,4,0,95,0,45,0,5,0,27,0,47,0,13,0,96,0,
-14,0,97,0,4,0,98,0,0,0,99,0,46,0,24,0,9,0,100,0,
-9,0,101,0,25,0,102,0,0,0,35,0,18,0,103,0,18,0,104,0,
-14,0,105,0,14,0,106,0,14,0,107,0,8,0,108,0,8,0,109,0,
-8,0,110,0,8,0,111,0,8,0,112,0,8,0,113,0,8,0,114,0,
-4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0,4,0,119,0,
-4,0,120,0,4,0,121,0,0,0,37,0,47,0,23,0,9,0,100,0,
-9,0,101,0,25,0,102,0,0,0,35,0,17,0,103,0,17,0,104,0,
-13,0,105,0,13,0,106,0,13,0,107,0,7,0,108,0,7,0,109,0,
-7,0,110,0,7,0,111,0,7,0,112,0,7,0,113,0,7,0,114,0,
-4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0,4,0,119,0,
-4,0,120,0,4,0,121,0,48,0,21,0,47,0,122,0,15,0,123,0,
-13,0,124,0,13,0,125,0,13,0,126,0,13,0,127,0,13,0,-128,0,
-13,0,-127,0,13,0,-126,0,13,0,-125,0,13,0,-124,0,7,0,-123,0,
-7,0,-122,0,7,0,-121,0,7,0,-120,0,7,0,-119,0,7,0,-118,0,
-7,0,-117,0,7,0,-116,0,7,0,-115,0,4,0,-114,0,49,0,22,0,
-46,0,122,0,16,0,123,0,14,0,124,0,14,0,125,0,14,0,126,0,
-14,0,127,0,14,0,-128,0,14,0,-127,0,14,0,-126,0,14,0,-125,0,
-14,0,-124,0,8,0,-123,0,8,0,-122,0,8,0,-121,0,8,0,-120,0,
-8,0,-119,0,8,0,-118,0,8,0,-117,0,8,0,-116,0,8,0,-115,0,
-4,0,-114,0,0,0,37,0,50,0,2,0,4,0,-113,0,4,0,-112,0,
-51,0,13,0,52,0,-111,0,52,0,-110,0,0,0,35,0,4,0,-109,0,
-4,0,-108,0,4,0,-107,0,4,0,-106,0,7,0,-105,0,7,0,-104,0,
-4,0,-103,0,4,0,-102,0,7,0,-101,0,4,0,-100,0,53,0,3,0,
-51,0,-99,0,13,0,-98,0,13,0,-97,0,54,0,3,0,51,0,-99,0,
-14,0,-98,0,14,0,-97,0,55,0,13,0,51,0,-99,0,18,0,-96,0,
-18,0,-95,0,4,0,-94,0,4,0,-93,0,4,0,-92,0,7,0,-91,0,
-7,0,-90,0,7,0,-89,0,7,0,-88,0,7,0,-87,0,7,0,-86,0,
-7,0,-85,0,56,0,13,0,51,0,-99,0,17,0,-96,0,17,0,-95,0,
-4,0,-94,0,4,0,-93,0,4,0,-92,0,7,0,-91,0,7,0,-90,0,
-7,0,-89,0,7,0,-88,0,7,0,-87,0,7,0,-86,0,7,0,-85,0,
-57,0,11,0,51,0,-99,0,17,0,-96,0,17,0,-95,0,7,0,-84,0,
-7,0,-83,0,7,0,-82,0,7,0,-87,0,7,0,-86,0,7,0,-85,0,
-7,0,-81,0,0,0,21,0,58,0,9,0,51,0,-99,0,17,0,-96,0,
-17,0,-95,0,13,0,-80,0,13,0,-79,0,13,0,-78,0,13,0,-77,0,
-4,0,-76,0,4,0,-75,0,59,0,5,0,58,0,-74,0,4,0,-73,0,
-7,0,-72,0,7,0,-71,0,7,0,-70,0,60,0,9,0,51,0,-99,0,
-17,0,-96,0,17,0,-95,0,7,0,-80,0,7,0,-79,0,7,0,-78,0,
-7,0,-77,0,4,0,-76,0,4,0,-75,0,61,0,4,0,7,0,-69,0,
-7,0,-68,0,7,0,-67,0,4,0,78,0,62,0,10,0,61,0,-66,0,
-13,0,-65,0,13,0,-64,0,13,0,-63,0,13,0,-62,0,13,0,-61,0,
-7,0,-123,0,7,0,-60,0,4,0,-59,0,4,0,53,0,63,0,4,0,
-61,0,-66,0,4,0,-58,0,7,0,-57,0,4,0,-56,0,64,0,4,0,
-13,0,-61,0,61,0,-66,0,4,0,-55,0,7,0,-54,0,65,0,7,0,
-13,0,-53,0,61,0,-66,0,4,0,-52,0,7,0,-51,0,7,0,-50,0,
-7,0,-49,0,4,0,53,0,66,0,6,0,15,0,-48,0,13,0,-50,0,
-13,0,-47,0,52,0,-46,0,4,0,-45,0,7,0,-49,0,67,0,26,0,
-4,0,-44,0,7,0,-43,0,7,0,-81,0,7,0,-42,0,7,0,-41,0,
-7,0,-40,0,7,0,-39,0,7,0,-38,0,7,0,-37,0,7,0,-36,0,
-7,0,-35,0,7,0,-34,0,7,0,-33,0,7,0,-32,0,7,0,-31,0,
-7,0,-30,0,7,0,-29,0,7,0,-28,0,7,0,-27,0,7,0,-26,0,
-7,0,-25,0,4,0,-24,0,4,0,-23,0,4,0,-22,0,4,0,-21,0,
-4,0,116,0,68,0,12,0,15,0,-20,0,15,0,-19,0,15,0,-18,0,
-13,0,-17,0,13,0,-16,0,7,0,-15,0,4,0,-14,0,4,0,-13,0,
-4,0,-12,0,4,0,-11,0,7,0,-51,0,4,0,53,0,69,0,27,0,
-17,0,-10,0,15,0,-9,0,15,0,-8,0,13,0,-17,0,13,0,-7,0,
-13,0,-6,0,13,0,-5,0,13,0,-4,0,13,0,-3,0,4,0,-2,0,
-7,0,-1,0,4,0,0,1,4,0,1,1,4,0,2,1,7,0,3,1,
-7,0,4,1,4,0,5,1,4,0,6,1,7,0,7,1,7,0,8,1,
-7,0,9,1,7,0,10,1,7,0,11,1,7,0,12,1,4,0,13,1,
-4,0,14,1,4,0,15,1,70,0,12,0,9,0,16,1,9,0,17,1,
-13,0,18,1,7,0,19,1,7,0,20,1,7,0,21,1,4,0,22,1,
-13,0,23,1,4,0,24,1,4,0,25,1,4,0,26,1,4,0,53,0,
-71,0,19,0,47,0,122,0,68,0,27,1,61,0,28,1,62,0,29,1,
-63,0,30,1,64,0,31,1,65,0,32,1,66,0,33,1,69,0,34,1,
-70,0,35,1,4,0,36,1,4,0,1,1,4,0,37,1,4,0,38,1,
-4,0,39,1,4,0,40,1,4,0,41,1,4,0,42,1,67,0,43,1,
-};
+char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(63),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109),
+char(95),char(99),char(97),char(112),char(97),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(100),char(97),char(116),char(97),char(0),char(109),char(95),
+char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(115),char(0),char(109),char(95),char(99),char(111),
+char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),
+char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(115),char(0),char(42),char(102),char(105),char(114),char(115),char(116),char(0),char(42),char(108),char(97),char(115),
+char(116),char(0),char(109),char(95),char(102),char(108),char(111),char(97),char(116),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(108),char(91),char(51),
+char(93),char(0),char(109),char(95),char(98),char(97),char(115),char(105),char(115),char(0),char(109),char(95),char(111),char(114),char(105),char(103),char(105),char(110),char(0),char(109),
+char(95),char(114),char(111),char(111),char(116),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),
+char(116),char(114),char(101),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),
+char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(91),char(51),char(93),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),
+char(101),char(100),char(65),char(97),char(98),char(98),char(77),char(97),char(120),char(91),char(51),char(93),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),
+char(105),char(110),char(79),char(114),char(103),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),char(97),char(120),char(79),char(114),char(103),char(0),char(109),
+char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),char(80),char(97),
+char(114),char(116),char(0),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),
+char(95),char(112),char(97),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),
+char(120),char(79),char(114),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(98),
+char(118),char(104),char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(0),char(109),char(95),char(98),char(118),char(104),char(65),char(97),char(98),char(98),char(77),
+char(97),char(120),char(0),char(109),char(95),char(98),char(118),char(104),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),
+char(0),char(109),char(95),char(99),char(117),char(114),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(117),char(115),
+char(101),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(110),char(117),char(109),char(67),
+char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(76),char(101),char(97),char(102),char(78),char(111),char(100),char(101),char(115),char(0),char(109),
+char(95),char(110),char(117),char(109),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),
+char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(99),char(111),char(110),char(116),char(105),char(103),char(117),char(111),
+char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),
+char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),
+char(114),char(0),char(42),char(109),char(95),char(115),char(117),char(98),char(84),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(80),char(116),char(114),char(0),
+char(109),char(95),char(116),char(114),char(97),char(118),char(101),char(114),char(115),char(97),char(108),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(110),char(117),
+char(109),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(72),char(101),char(97),char(100),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(110),
+char(97),char(109),char(101),char(0),char(109),char(95),char(115),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(112),char(97),
+char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
+char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(83),char(99),char(97),
+char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(101),char(78),char(111),char(114),char(109),char(97),char(108),char(0),char(109),
+char(95),char(112),char(108),char(97),char(110),char(101),char(67),char(111),char(110),char(115),char(116),char(97),char(110),char(116),char(0),char(109),char(95),char(105),char(109),char(112),
+char(108),char(105),char(99),char(105),char(116),char(83),char(104),char(97),char(112),char(101),char(68),char(105),char(109),char(101),char(110),char(115),char(105),char(111),char(110),char(115),
+char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(109),
+char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(111),char(115),char(0),char(109),char(95),char(114),char(97),char(100),
+char(105),char(117),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),
+char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(42),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(80),char(111),
+char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(108),char(111),char(99),
+char(97),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(83),char(105),char(122),char(101),char(0),
+char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(0),char(109),char(95),char(112),char(97),char(100),char(91),char(50),char(93),char(0),char(109),char(95),char(118),
+char(97),char(108),char(117),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(112),char(97),char(100),char(0),char(42),char(109),char(95),char(118),char(101),
+char(114),char(116),char(105),char(99),char(101),char(115),char(51),char(102),char(0),char(42),char(109),char(95),char(118),char(101),char(114),char(116),char(105),char(99),char(101),char(115),
+char(51),char(100),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(51),char(50),char(0),char(42),char(109),char(95),char(51),
+char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(42),char(109),char(95),char(51),char(105),char(110),char(100),char(105),char(99),char(101),
+char(115),char(56),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(109),char(95),char(110),char(117),
+char(109),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(101),char(114),char(116),
+char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(115),char(80),char(116),char(114),
+char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(101),char(115),char(104),
+char(80),char(97),char(114),char(116),char(115),char(0),char(109),char(95),char(109),char(101),char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),
+char(101),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(70),char(108),char(111),char(97),char(116),char(66),
+char(118),char(104),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(68),char(111),char(117),char(98),char(108),
+char(101),char(66),char(118),char(104),char(0),char(42),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),
+char(77),char(97),char(112),char(0),char(109),char(95),char(112),char(97),char(100),char(51),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(114),char(105),char(109),
+char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(116),char(114),char(97),char(110),char(115),
+char(102),char(111),char(114),char(109),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(0),char(109),
+char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),
+char(105),char(108),char(100),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),
+char(97),char(112),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(104),char(105),char(108),char(100),char(83),char(104),char(97),
+char(112),char(101),char(115),char(0),char(109),char(95),char(117),char(112),char(65),char(120),char(105),char(115),char(0),char(109),char(95),char(102),char(108),char(97),char(103),char(115),
+char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(48),char(86),char(49),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),
+char(100),char(103),char(101),char(86),char(49),char(86),char(50),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),
+char(50),char(86),char(48),char(65),char(110),char(103),char(108),char(101),char(0),char(42),char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),
+char(101),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(110),char(101),char(120),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(118),
+char(97),char(108),char(117),char(101),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(107),char(101),char(121),char(65),
+char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(99),char(111),char(110),char(118),char(101),char(120),char(69),char(112),char(115),char(105),
+char(108),char(111),char(110),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(97),char(114),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),
+char(109),char(95),char(101),char(113),char(117),char(97),char(108),char(86),char(101),char(114),char(116),char(101),char(120),char(84),char(104),char(114),char(101),char(115),char(104),char(111),
+char(108),char(100),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(68),char(105),char(115),char(116),char(97),char(110),char(99),char(101),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(122),char(101),char(114),char(111),char(65),char(114),char(101),char(97),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),char(101),char(120),char(116),char(83),char(105),char(122),char(101),char(0),char(109),char(95),
+char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(110),char(117),char(109),char(86),
+char(97),char(108),char(117),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(75),char(101),char(121),char(115),char(0),char(109),char(95),char(103),char(105),
+char(109),char(112),char(97),char(99),char(116),char(83),char(117),char(98),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),
+char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(70),char(108),char(111),char(97),char(116),char(80),char(116),char(114),char(0),char(42),
+char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(68),char(111),char(117),char(98),
+char(108),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(85),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),
+char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(51),char(91),char(52),char(93),char(0),
+char(42),char(109),char(95),char(98),char(114),char(111),char(97),char(100),char(112),char(104),char(97),char(115),char(101),char(72),char(97),char(110),char(100),char(108),char(101),char(0),
+char(42),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(42),char(109),
+char(95),char(114),char(111),char(111),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),
+char(109),char(95),char(119),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),
+char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),
+char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),
+char(111),char(110),char(76),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(105),
+char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),
+char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),
+char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),
+char(114),char(111),char(99),char(101),char(115),char(115),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
+char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),char(111),char(110),char(84),char(105),char(109),char(101),char(0),char(109),char(95),
+char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(114),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),
+char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),
+char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(99),char(100),
+char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114),char(101),char(82),char(97),char(100),char(105),char(117),char(115),char(0),char(109),char(95),
+char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
+char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),char(114),char(105),char(99),char(116),
+char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(108),char(97),char(103),char(115),
+char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84),char(97),char(103),char(49),char(0),char(109),char(95),char(99),char(111),char(109),char(112),
+char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),char(111),char(110),
+char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(84),char(121),char(112),
+char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(87),char(105),char(116),char(104),
+char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(0),char(109),char(95),char(103),char(114),char(97),char(118),
+char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),
+char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(84),char(101),
+char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(86),char(101),
+char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),
+char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),
+char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(103),char(114),
+char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),char(101),char(108),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(0),char(109),
+char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(76),char(111),char(99),char(97),char(108),char(0),char(109),char(95),char(116),
+char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(84),char(111),char(114),
+char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),char(101),char(114),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(109),char(95),
+char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),
+char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),
+char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),
+char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(76),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),
+char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),
+char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),
+char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),
+char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),
+char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(101),char(101),char(112),
+char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),
+char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),
+char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),
+char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(82),char(111),char(119),char(115),char(0),
+char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),char(65),char(0),char(42),char(109),char(95),char(114),char(98),char(66),char(0),char(109),char(95),
+char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),
+char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),
+char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(100),char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),
+char(101),char(100),char(98),char(97),char(99),char(107),char(0),char(109),char(95),char(97),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),
+char(108),char(115),char(101),char(0),char(109),char(95),char(100),char(98),char(103),char(68),char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),
+char(100),char(105),char(115),char(97),char(98),char(108),char(101),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),
+char(119),char(101),char(101),char(110),char(76),char(105),char(110),char(107),char(101),char(100),char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),
+char(118),char(101),char(114),char(114),char(105),char(100),char(101),char(78),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),
+char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(98),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),
+char(117),char(108),char(115),char(101),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),
+char(97),char(98),char(108),char(101),char(100),char(0),char(109),char(95),char(116),char(121),char(112),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),
+char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(65),char(0),char(109),char(95),
+char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(98),char(65),char(70),char(114),char(97),char(109),char(101),char(0),
+char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(82),char(101),char(102),char(101),
+char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),
+char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),char(98),char(108),char(101),char(65),char(110),char(103),char(117),char(108),char(97),
+char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),char(116),char(111),char(114),char(84),char(97),char(114),char(103),char(101),char(116),
+char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(109),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(73),
+char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
+char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),char(109),char(105),char(116),
+char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(98),char(105),char(97),char(115),char(70),char(97),char(99),char(116),char(111),
+char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),char(105),char(111),char(110),char(70),char(97),char(99),char(116),char(111),char(114),
+char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),char(119),char(105),char(110),
+char(103),char(83),char(112),char(97),char(110),char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),char(110),char(0),char(109),
+char(95),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),
+char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),
+char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),
+char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),
+char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(115),char(101),char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),
+char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),
+char(102),char(102),char(115),char(101),char(116),char(70),char(111),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),
+char(97),char(109),char(101),char(0),char(109),char(95),char(54),char(100),char(111),char(102),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),
+char(105),char(110),char(103),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(91),char(54),char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),
+char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),
+char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),
+char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(91),char(54),char(93),char(0),char(109),char(95),char(116),char(97),
+char(117),char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69),char(114),
+char(114),char(111),char(114),char(82),char(101),char(100),char(117),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0),char(109),
+char(95),char(101),char(114),char(112),char(0),char(109),char(95),char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97),char(108),
+char(67),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80),char(101),
+char(110),char(101),char(116),char(114),char(97),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
+char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114),char(112),
+char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114),char(109),
+char(115),char(116),char(97),char(114),char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(97),char(120),
+char(71),char(121),char(114),char(111),char(115),char(99),char(111),char(112),char(105),char(99),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(115),char(105),
+char(110),char(103),char(108),char(101),char(65),char(120),char(105),char(115),char(82),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),
+char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),char(117),char(109),char(73),char(116),
+char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(77),char(111),char(100),
+char(101),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(110),char(103),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(82),char(101),
+char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
+char(95),char(109),char(105),char(110),char(105),char(109),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(66),char(97),char(116),char(99),char(104),char(83),
+char(105),char(122),char(101),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),
+char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),
+char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(118),char(111),
+char(108),char(117),char(109),char(101),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(116),
+char(101),char(114),char(105),char(97),char(108),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),
+char(114),char(101),char(118),char(105),char(111),char(117),char(115),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(118),char(101),
+char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(99),char(99),char(117),char(109),char(117),char(108),char(97),char(116),char(101),char(100),
+char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(110),char(111),char(114),char(109),char(97),char(108),char(0),char(109),char(95),char(97),char(114),char(101),
+char(97),char(0),char(109),char(95),char(97),char(116),char(116),char(97),char(99),char(104),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),
+char(105),char(99),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(76),char(101),char(110),char(103),char(116),char(104),
+char(0),char(109),char(95),char(98),char(98),char(101),char(110),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),
+char(100),char(105),char(99),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(65),char(114),char(101),char(97),char(0),
+char(109),char(95),char(99),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),
+char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),
+char(99),char(49),char(0),char(109),char(95),char(99),char(50),char(0),char(109),char(95),char(99),char(48),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),
+char(70),char(114),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(0),char(109),
+char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(97),char(101),char(114),char(111),char(77),char(111),char(100),
+char(101),char(108),char(0),char(109),char(95),char(98),char(97),char(117),char(109),char(103),char(97),char(114),char(116),char(101),char(0),char(109),char(95),char(100),char(114),char(97),
+char(103),char(0),char(109),char(95),char(108),char(105),char(102),char(116),char(0),char(109),char(95),char(112),char(114),char(101),char(115),char(115),char(117),char(114),char(101),char(0),
+char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(100),char(121),char(110),char(97),char(109),char(105),char(99),char(70),char(114),
+char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(111),char(115),char(101),char(77),char(97),char(116),char(99),char(104),char(0),char(109),
+char(95),char(114),char(105),char(103),char(105),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),
+char(115),char(0),char(109),char(95),char(107),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),
+char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),
+char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(72),char(97),char(114),
+char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),
+char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),
+char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),
+char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),
+char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),
+char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),
+char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),
+char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),
+char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),
+char(116),char(0),char(109),char(95),char(109),char(97),char(120),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(116),char(105),char(109),char(101),
+char(83),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(73),char(116),char(101),char(114),
+char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(73),char(116),char(101),
+char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(100),char(114),char(105),char(102),char(116),char(73),char(116),char(101),char(114),char(97),
+char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(116),char(101),char(114),char(97),
+char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(114),char(111),char(116),char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(101),char(0),
+char(109),char(95),char(97),char(113),char(113),char(0),char(109),char(95),char(99),char(111),char(109),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(105),char(116),
+char(105),char(111),char(110),char(115),char(0),char(42),char(109),char(95),char(119),char(101),char(105),char(103),char(104),char(116),char(115),char(0),char(109),char(95),char(110),char(117),
+char(109),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(87),char(101),char(105),char(103),
+char(116),char(115),char(0),char(109),char(95),char(98),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(98),char(102),char(114),char(97),char(109),
+char(101),char(0),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(120),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(108),char(111),char(99),
+char(105),char(105),char(0),char(109),char(95),char(105),char(110),char(118),char(119),char(105),char(0),char(109),char(95),char(118),char(105),char(109),char(112),char(117),char(108),char(115),
+char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),
+char(0),char(109),char(95),char(108),char(118),char(0),char(109),char(95),char(97),char(118),char(0),char(42),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(114),
+char(101),char(102),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(0),char(42),
+char(109),char(95),char(109),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(114),char(97),char(109),char(101),char(82),
+char(101),char(102),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(78),char(111),char(100),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),
+char(77),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(105),char(100),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(105),char(109),
+char(97),char(115),char(115),char(0),char(109),char(95),char(110),char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),
+char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(97),char(109),char(112),char(105),char(110),char(103),
+char(0),char(109),char(95),char(108),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(97),char(109),char(112),char(105),
+char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(116),char(99),char(104),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(120),char(83),
+char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),
+char(109),char(95),char(115),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),
+char(115),char(101),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(105),char(110),char(115),char(65),
+char(110),char(99),char(104),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(100),char(101),char(0),char(109),char(95),char(99),char(108),
+char(117),char(115),char(116),char(101),char(114),char(73),char(110),char(100),char(101),char(120),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(0),
+char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(0),char(109),char(95),char(114),char(101),char(102),char(115),char(91),char(50),char(93),char(0),char(109),
+char(95),char(99),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(100),char(101),char(108),char(101),char(116),
+char(101),char(0),char(109),char(95),char(114),char(101),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(91),char(50),char(93),char(0),char(109),
+char(95),char(98),char(111),char(100),char(121),char(65),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(116),char(121),
+char(112),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(112),char(111),
+char(115),char(101),char(0),char(42),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(42),char(109),char(95),
+char(110),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(115),char(0),char(42),char(109),char(95),char(102),char(97),
+char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(116),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(42),char(109),
+char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(42),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(115),
+char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(116),char(101),
+char(114),char(105),char(97),char(108),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(76),char(105),char(110),char(107),char(115),char(0),char(109),char(95),char(110),
+char(117),char(109),char(70),char(97),char(99),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(84),char(101),char(116),char(114),char(97),char(104),char(101),
+char(100),char(114),char(97),char(0),char(109),char(95),char(110),char(117),char(109),char(65),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(109),char(95),char(110),
+char(117),char(109),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(74),char(111),char(105),char(110),
+char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(102),char(105),char(103),char(0),char(84),char(89),char(80),char(69),char(76),char(0),char(0),char(0),
+char(99),char(104),char(97),char(114),char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104),
+char(111),char(114),char(116),char(0),char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102),
+char(108),char(111),char(97),char(116),char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105),
+char(110),char(116),char(101),char(114),char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83),
+char(121),char(115),char(116),char(101),char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99),
+char(116),char(111),char(114),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116),
+char(111),char(114),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),
+char(105),char(120),char(51),char(120),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),
+char(114),char(105),char(120),char(51),char(120),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),
+char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(66),char(118),char(104),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(70),
+char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),
+char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70),char(108),char(111),char(97),char(116),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
+char(110),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97),char(116),char(105),char(99),char(80),
+char(108),char(97),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),
+char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100),char(105),char(117),char(115),char(0),
+char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),
+char(116),char(97),char(0),char(98),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),
+char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(68),char(97),
+char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115),char(104),char(73),char(110),char(116),
+char(101),char(114),char(102),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),
+char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),
+char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),
+char(99),char(97),char(108),char(101),char(100),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),
+char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),
+char(112),char(101),char(67),char(104),char(105),char(108),char(100),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),
+char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121),char(108),char(105),char(110),char(100),
+char(101),char(114),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108),
+char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),
+char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),char(112),char(97),char(99),char(116),char(77),
+char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101),
+char(120),char(72),char(117),char(108),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),
+char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
+char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),
+char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),
+char(87),char(111),char(114),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),char(111),char(117),char(98),char(108),
+char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),
+char(100),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),
+char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
+char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49),
+char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),
+char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(97),char(116),char(97),char(0),char(98),
+char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),
+char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),
+char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),
+char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
+char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),
+char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),
+char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),
+char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),
+char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),
+char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),
+char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),
+char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),
+char(121),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(76),char(105),
+char(110),char(107),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(97),char(99),char(101),char(68),
+char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84),char(101),char(116),char(114),char(97),char(68),char(97),char(116),
+char(97),char(0),char(83),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110),char(99),char(104),char(111),char(114),char(68),char(97),char(116),
+char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110),char(102),char(105),char(103),char(68),char(97),char(116),char(97),
+char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
+char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(0),char(0),
+char(84),char(76),char(69),char(78),char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(4),char(0),
+char(8),char(0),char(0),char(0),char(12),char(0),char(36),char(0),char(8),char(0),char(16),char(0),char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0),
+char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(84),char(0),char(-124),char(0),char(12),char(0),char(52),char(0),char(52),char(0),
+char(20),char(0),char(64),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),char(32),char(0),char(28),char(0),char(60),char(0),char(56),char(0),
+char(76),char(0),char(76),char(0),char(24),char(0),char(60),char(0),char(60),char(0),char(16),char(0),char(64),char(0),char(68),char(0),char(-48),char(1),char(0),char(1),
+char(-72),char(0),char(-104),char(0),char(104),char(0),char(88),char(0),char(-24),char(1),char(-96),char(3),char(8),char(0),char(52),char(0),char(0),char(0),char(84),char(0),
+char(116),char(0),char(92),char(1),char(-36),char(0),char(-44),char(0),char(-4),char(0),char(92),char(1),char(-52),char(0),char(16),char(0),char(100),char(0),char(20),char(0),
+char(36),char(0),char(100),char(0),char(92),char(0),char(104),char(0),char(-64),char(0),char(92),char(1),char(104),char(0),char(-84),char(1),char(83),char(84),char(82),char(67),
+char(65),char(0),char(0),char(0),char(10),char(0),char(3),char(0),char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),char(9),char(0),char(2),char(0),
+char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0),char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),char(12),char(0),char(2),char(0),
+char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0),char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(14),char(0),char(1),char(0),
+char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0),char(13),char(0),char(9),char(0),char(16),char(0),char(1),char(0),char(14),char(0),char(9),char(0),
+char(17),char(0),char(2),char(0),char(15),char(0),char(10),char(0),char(13),char(0),char(11),char(0),char(18),char(0),char(2),char(0),char(16),char(0),char(10),char(0),
+char(14),char(0),char(11),char(0),char(19),char(0),char(4),char(0),char(4),char(0),char(12),char(0),char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),
+char(2),char(0),char(15),char(0),char(20),char(0),char(6),char(0),char(13),char(0),char(16),char(0),char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),
+char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(21),char(0),char(6),char(0),char(14),char(0),char(16),char(0),
+char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),
+char(22),char(0),char(3),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(4),char(0),char(22),char(0),char(23),char(0),char(12),char(0),
+char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0),char(13),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),
+char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(20),char(0),char(30),char(0),char(22),char(0),char(31),char(0),char(19),char(0),char(32),char(0),
+char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(24),char(0),char(12),char(0),char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),
+char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),
+char(21),char(0),char(30),char(0),char(22),char(0),char(31),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(19),char(0),char(32),char(0),
+char(25),char(0),char(3),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(36),char(0),char(0),char(0),char(37),char(0),char(26),char(0),char(5),char(0),
+char(25),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(40),char(0),char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),
+char(27),char(0),char(5),char(0),char(25),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),
+char(4),char(0),char(44),char(0),char(28),char(0),char(2),char(0),char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(29),char(0),char(4),char(0),
+char(27),char(0),char(47),char(0),char(28),char(0),char(48),char(0),char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(30),char(0),char(1),char(0),
+char(4),char(0),char(50),char(0),char(31),char(0),char(2),char(0),char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(32),char(0),char(2),char(0),
+char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0),char(33),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),
+char(34),char(0),char(8),char(0),char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),char(30),char(0),char(56),char(0),char(32),char(0),char(57),char(0),
+char(33),char(0),char(58),char(0),char(31),char(0),char(59),char(0),char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(35),char(0),char(4),char(0),
+char(34),char(0),char(62),char(0),char(13),char(0),char(63),char(0),char(4),char(0),char(64),char(0),char(0),char(0),char(37),char(0),char(36),char(0),char(7),char(0),
+char(25),char(0),char(38),char(0),char(35),char(0),char(65),char(0),char(23),char(0),char(66),char(0),char(24),char(0),char(67),char(0),char(37),char(0),char(68),char(0),
+char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0),char(38),char(0),char(2),char(0),char(36),char(0),char(70),char(0),char(13),char(0),char(39),char(0),
+char(39),char(0),char(4),char(0),char(17),char(0),char(71),char(0),char(25),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),
+char(40),char(0),char(4),char(0),char(25),char(0),char(38),char(0),char(39),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),
+char(41),char(0),char(3),char(0),char(27),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(42),char(0),char(3),char(0),
+char(27),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(43),char(0),char(4),char(0),char(4),char(0),char(78),char(0),
+char(7),char(0),char(79),char(0),char(7),char(0),char(80),char(0),char(7),char(0),char(81),char(0),char(37),char(0),char(14),char(0),char(4),char(0),char(82),char(0),
+char(4),char(0),char(83),char(0),char(43),char(0),char(84),char(0),char(4),char(0),char(85),char(0),char(7),char(0),char(86),char(0),char(7),char(0),char(87),char(0),
+char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),char(7),char(0),char(90),char(0),char(4),char(0),char(91),char(0),char(4),char(0),char(92),char(0),
+char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),char(0),char(0),char(37),char(0),char(44),char(0),char(5),char(0),char(25),char(0),char(38),char(0),
+char(35),char(0),char(65),char(0),char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(95),char(0),char(45),char(0),char(5),char(0),
+char(27),char(0),char(47),char(0),char(13),char(0),char(96),char(0),char(14),char(0),char(97),char(0),char(4),char(0),char(98),char(0),char(0),char(0),char(99),char(0),
+char(46),char(0),char(25),char(0),char(9),char(0),char(100),char(0),char(9),char(0),char(101),char(0),char(25),char(0),char(102),char(0),char(0),char(0),char(35),char(0),
+char(18),char(0),char(103),char(0),char(18),char(0),char(104),char(0),char(14),char(0),char(105),char(0),char(14),char(0),char(106),char(0),char(14),char(0),char(107),char(0),
+char(8),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(8),char(0),char(110),char(0),char(8),char(0),char(111),char(0),char(8),char(0),char(112),char(0),
+char(8),char(0),char(113),char(0),char(8),char(0),char(114),char(0),char(8),char(0),char(115),char(0),char(4),char(0),char(116),char(0),char(4),char(0),char(117),char(0),
+char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0),char(4),char(0),char(122),char(0),
+char(0),char(0),char(37),char(0),char(47),char(0),char(25),char(0),char(9),char(0),char(100),char(0),char(9),char(0),char(101),char(0),char(25),char(0),char(102),char(0),
+char(0),char(0),char(35),char(0),char(17),char(0),char(103),char(0),char(17),char(0),char(104),char(0),char(13),char(0),char(105),char(0),char(13),char(0),char(106),char(0),
+char(13),char(0),char(107),char(0),char(7),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(7),char(0),char(110),char(0),char(7),char(0),char(111),char(0),
+char(7),char(0),char(112),char(0),char(7),char(0),char(113),char(0),char(7),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(4),char(0),char(116),char(0),
+char(4),char(0),char(117),char(0),char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0),
+char(4),char(0),char(122),char(0),char(0),char(0),char(37),char(0),char(48),char(0),char(2),char(0),char(49),char(0),char(123),char(0),char(14),char(0),char(124),char(0),
+char(50),char(0),char(2),char(0),char(51),char(0),char(123),char(0),char(13),char(0),char(124),char(0),char(52),char(0),char(21),char(0),char(47),char(0),char(125),char(0),
+char(15),char(0),char(126),char(0),char(13),char(0),char(127),char(0),char(13),char(0),char(-128),char(0),char(13),char(0),char(-127),char(0),char(13),char(0),char(-126),char(0),
+char(13),char(0),char(124),char(0),char(13),char(0),char(-125),char(0),char(13),char(0),char(-124),char(0),char(13),char(0),char(-123),char(0),char(13),char(0),char(-122),char(0),
+char(7),char(0),char(-121),char(0),char(7),char(0),char(-120),char(0),char(7),char(0),char(-119),char(0),char(7),char(0),char(-118),char(0),char(7),char(0),char(-117),char(0),
+char(7),char(0),char(-116),char(0),char(7),char(0),char(-115),char(0),char(7),char(0),char(-114),char(0),char(7),char(0),char(-113),char(0),char(4),char(0),char(-112),char(0),
+char(53),char(0),char(22),char(0),char(46),char(0),char(125),char(0),char(16),char(0),char(126),char(0),char(14),char(0),char(127),char(0),char(14),char(0),char(-128),char(0),
+char(14),char(0),char(-127),char(0),char(14),char(0),char(-126),char(0),char(14),char(0),char(124),char(0),char(14),char(0),char(-125),char(0),char(14),char(0),char(-124),char(0),
+char(14),char(0),char(-123),char(0),char(14),char(0),char(-122),char(0),char(8),char(0),char(-121),char(0),char(8),char(0),char(-120),char(0),char(8),char(0),char(-119),char(0),
+char(8),char(0),char(-118),char(0),char(8),char(0),char(-117),char(0),char(8),char(0),char(-116),char(0),char(8),char(0),char(-115),char(0),char(8),char(0),char(-114),char(0),
+char(8),char(0),char(-113),char(0),char(4),char(0),char(-112),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(2),char(0),char(4),char(0),char(-111),char(0),
+char(4),char(0),char(-110),char(0),char(55),char(0),char(13),char(0),char(56),char(0),char(-109),char(0),char(56),char(0),char(-108),char(0),char(0),char(0),char(35),char(0),
+char(4),char(0),char(-107),char(0),char(4),char(0),char(-106),char(0),char(4),char(0),char(-105),char(0),char(4),char(0),char(-104),char(0),char(7),char(0),char(-103),char(0),
+char(7),char(0),char(-102),char(0),char(4),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),char(7),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),
+char(57),char(0),char(3),char(0),char(55),char(0),char(-97),char(0),char(13),char(0),char(-96),char(0),char(13),char(0),char(-95),char(0),char(58),char(0),char(3),char(0),
+char(55),char(0),char(-97),char(0),char(14),char(0),char(-96),char(0),char(14),char(0),char(-95),char(0),char(59),char(0),char(13),char(0),char(55),char(0),char(-97),char(0),
+char(18),char(0),char(-94),char(0),char(18),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),
+char(7),char(0),char(-89),char(0),char(7),char(0),char(-88),char(0),char(7),char(0),char(-87),char(0),char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),
+char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0),char(60),char(0),char(13),char(0),char(55),char(0),char(-97),char(0),char(17),char(0),char(-94),char(0),
+char(17),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),char(7),char(0),char(-89),char(0),
+char(7),char(0),char(-88),char(0),char(7),char(0),char(-87),char(0),char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),
+char(7),char(0),char(-83),char(0),char(61),char(0),char(11),char(0),char(55),char(0),char(-97),char(0),char(17),char(0),char(-94),char(0),char(17),char(0),char(-93),char(0),
+char(7),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),
+char(7),char(0),char(-83),char(0),char(7),char(0),char(-79),char(0),char(0),char(0),char(21),char(0),char(62),char(0),char(9),char(0),char(55),char(0),char(-97),char(0),
+char(17),char(0),char(-94),char(0),char(17),char(0),char(-93),char(0),char(13),char(0),char(-78),char(0),char(13),char(0),char(-77),char(0),char(13),char(0),char(-76),char(0),
+char(13),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(63),char(0),char(5),char(0),char(62),char(0),char(-72),char(0),
+char(4),char(0),char(-71),char(0),char(7),char(0),char(-70),char(0),char(7),char(0),char(-69),char(0),char(7),char(0),char(-68),char(0),char(64),char(0),char(9),char(0),
+char(55),char(0),char(-97),char(0),char(17),char(0),char(-94),char(0),char(17),char(0),char(-93),char(0),char(7),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),
+char(7),char(0),char(-76),char(0),char(7),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(49),char(0),char(22),char(0),
+char(8),char(0),char(-67),char(0),char(8),char(0),char(-79),char(0),char(8),char(0),char(110),char(0),char(8),char(0),char(-66),char(0),char(8),char(0),char(112),char(0),
+char(8),char(0),char(-65),char(0),char(8),char(0),char(-64),char(0),char(8),char(0),char(-63),char(0),char(8),char(0),char(-62),char(0),char(8),char(0),char(-61),char(0),
+char(8),char(0),char(-60),char(0),char(8),char(0),char(-59),char(0),char(8),char(0),char(-58),char(0),char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),
+char(8),char(0),char(-55),char(0),char(4),char(0),char(-54),char(0),char(4),char(0),char(-53),char(0),char(4),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),
+char(4),char(0),char(-50),char(0),char(0),char(0),char(37),char(0),char(51),char(0),char(22),char(0),char(7),char(0),char(-67),char(0),char(7),char(0),char(-79),char(0),
+char(7),char(0),char(110),char(0),char(7),char(0),char(-66),char(0),char(7),char(0),char(112),char(0),char(7),char(0),char(-65),char(0),char(7),char(0),char(-64),char(0),
+char(7),char(0),char(-63),char(0),char(7),char(0),char(-62),char(0),char(7),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),char(7),char(0),char(-59),char(0),
+char(7),char(0),char(-58),char(0),char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0),char(7),char(0),char(-55),char(0),char(4),char(0),char(-54),char(0),
+char(4),char(0),char(-53),char(0),char(4),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),char(4),char(0),char(-50),char(0),char(0),char(0),char(37),char(0),
+char(65),char(0),char(4),char(0),char(7),char(0),char(-49),char(0),char(7),char(0),char(-48),char(0),char(7),char(0),char(-47),char(0),char(4),char(0),char(78),char(0),
+char(66),char(0),char(10),char(0),char(65),char(0),char(-46),char(0),char(13),char(0),char(-45),char(0),char(13),char(0),char(-44),char(0),char(13),char(0),char(-43),char(0),
+char(13),char(0),char(-42),char(0),char(13),char(0),char(-41),char(0),char(7),char(0),char(-121),char(0),char(7),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),
+char(4),char(0),char(53),char(0),char(67),char(0),char(4),char(0),char(65),char(0),char(-46),char(0),char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),
+char(4),char(0),char(-36),char(0),char(68),char(0),char(4),char(0),char(13),char(0),char(-41),char(0),char(65),char(0),char(-46),char(0),char(4),char(0),char(-35),char(0),
+char(7),char(0),char(-34),char(0),char(69),char(0),char(7),char(0),char(13),char(0),char(-33),char(0),char(65),char(0),char(-46),char(0),char(4),char(0),char(-32),char(0),
+char(7),char(0),char(-31),char(0),char(7),char(0),char(-30),char(0),char(7),char(0),char(-29),char(0),char(4),char(0),char(53),char(0),char(70),char(0),char(6),char(0),
+char(15),char(0),char(-28),char(0),char(13),char(0),char(-30),char(0),char(13),char(0),char(-27),char(0),char(56),char(0),char(-26),char(0),char(4),char(0),char(-25),char(0),
+char(7),char(0),char(-29),char(0),char(71),char(0),char(26),char(0),char(4),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),char(7),char(0),char(-79),char(0),
+char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(7),char(0),char(-19),char(0),char(7),char(0),char(-18),char(0),
+char(7),char(0),char(-17),char(0),char(7),char(0),char(-16),char(0),char(7),char(0),char(-15),char(0),char(7),char(0),char(-14),char(0),char(7),char(0),char(-13),char(0),
+char(7),char(0),char(-12),char(0),char(7),char(0),char(-11),char(0),char(7),char(0),char(-10),char(0),char(7),char(0),char(-9),char(0),char(7),char(0),char(-8),char(0),
+char(7),char(0),char(-7),char(0),char(7),char(0),char(-6),char(0),char(7),char(0),char(-5),char(0),char(4),char(0),char(-4),char(0),char(4),char(0),char(-3),char(0),
+char(4),char(0),char(-2),char(0),char(4),char(0),char(-1),char(0),char(4),char(0),char(117),char(0),char(72),char(0),char(12),char(0),char(15),char(0),char(0),char(1),
+char(15),char(0),char(1),char(1),char(15),char(0),char(2),char(1),char(13),char(0),char(3),char(1),char(13),char(0),char(4),char(1),char(7),char(0),char(5),char(1),
+char(4),char(0),char(6),char(1),char(4),char(0),char(7),char(1),char(4),char(0),char(8),char(1),char(4),char(0),char(9),char(1),char(7),char(0),char(-31),char(0),
+char(4),char(0),char(53),char(0),char(73),char(0),char(27),char(0),char(17),char(0),char(10),char(1),char(15),char(0),char(11),char(1),char(15),char(0),char(12),char(1),
+char(13),char(0),char(3),char(1),char(13),char(0),char(13),char(1),char(13),char(0),char(14),char(1),char(13),char(0),char(15),char(1),char(13),char(0),char(16),char(1),
+char(13),char(0),char(17),char(1),char(4),char(0),char(18),char(1),char(7),char(0),char(19),char(1),char(4),char(0),char(20),char(1),char(4),char(0),char(21),char(1),
+char(4),char(0),char(22),char(1),char(7),char(0),char(23),char(1),char(7),char(0),char(24),char(1),char(4),char(0),char(25),char(1),char(4),char(0),char(26),char(1),
+char(7),char(0),char(27),char(1),char(7),char(0),char(28),char(1),char(7),char(0),char(29),char(1),char(7),char(0),char(30),char(1),char(7),char(0),char(31),char(1),
+char(7),char(0),char(32),char(1),char(4),char(0),char(33),char(1),char(4),char(0),char(34),char(1),char(4),char(0),char(35),char(1),char(74),char(0),char(12),char(0),
+char(9),char(0),char(36),char(1),char(9),char(0),char(37),char(1),char(13),char(0),char(38),char(1),char(7),char(0),char(39),char(1),char(7),char(0),char(-63),char(0),
+char(7),char(0),char(40),char(1),char(4),char(0),char(41),char(1),char(13),char(0),char(42),char(1),char(4),char(0),char(43),char(1),char(4),char(0),char(44),char(1),
+char(4),char(0),char(45),char(1),char(4),char(0),char(53),char(0),char(75),char(0),char(19),char(0),char(47),char(0),char(125),char(0),char(72),char(0),char(46),char(1),
+char(65),char(0),char(47),char(1),char(66),char(0),char(48),char(1),char(67),char(0),char(49),char(1),char(68),char(0),char(50),char(1),char(69),char(0),char(51),char(1),
+char(70),char(0),char(52),char(1),char(73),char(0),char(53),char(1),char(74),char(0),char(54),char(1),char(4),char(0),char(55),char(1),char(4),char(0),char(21),char(1),
+char(4),char(0),char(56),char(1),char(4),char(0),char(57),char(1),char(4),char(0),char(58),char(1),char(4),char(0),char(59),char(1),char(4),char(0),char(60),char(1),
+char(4),char(0),char(61),char(1),char(71),char(0),char(62),char(1),};
int sBulletDNAlen= sizeof(sBulletDNAstr);
-
- char sBulletDNAstr64[]= {
-83,68,78,65,78,65,77,69,44,1,0,0,109,95,115,105,122,101,0,109,
-95,99,97,112,97,99,105,116,121,0,42,109,95,100,97,116,97,0,109,95,
-99,111,108,108,105,115,105,111,110,83,104,97,112,101,115,0,109,95,99,111,
-108,108,105,115,105,111,110,79,98,106,101,99,116,115,0,109,95,99,111,110,
-115,116,114,97,105,110,116,115,0,42,102,105,114,115,116,0,42,108,97,115,
-116,0,109,95,102,108,111,97,116,115,91,52,93,0,109,95,101,108,91,51,
-93,0,109,95,98,97,115,105,115,0,109,95,111,114,105,103,105,110,0,109,
-95,114,111,111,116,78,111,100,101,73,110,100,101,120,0,109,95,115,117,98,
-116,114,101,101,83,105,122,101,0,109,95,113,117,97,110,116,105,122,101,100,
-65,97,98,98,77,105,110,91,51,93,0,109,95,113,117,97,110,116,105,122,
-101,100,65,97,98,98,77,97,120,91,51,93,0,109,95,97,97,98,98,77,
-105,110,79,114,103,0,109,95,97,97,98,98,77,97,120,79,114,103,0,109,
-95,101,115,99,97,112,101,73,110,100,101,120,0,109,95,115,117,98,80,97,
-114,116,0,109,95,116,114,105,97,110,103,108,101,73,110,100,101,120,0,109,
-95,112,97,100,91,52,93,0,109,95,101,115,99,97,112,101,73,110,100,101,
-120,79,114,84,114,105,97,110,103,108,101,73,110,100,101,120,0,109,95,98,
-118,104,65,97,98,98,77,105,110,0,109,95,98,118,104,65,97,98,98,77,
-97,120,0,109,95,98,118,104,81,117,97,110,116,105,122,97,116,105,111,110,
-0,109,95,99,117,114,78,111,100,101,73,110,100,101,120,0,109,95,117,115,
-101,81,117,97,110,116,105,122,97,116,105,111,110,0,109,95,110,117,109,67,
-111,110,116,105,103,117,111,117,115,76,101,97,102,78,111,100,101,115,0,109,
-95,110,117,109,81,117,97,110,116,105,122,101,100,67,111,110,116,105,103,117,
-111,117,115,78,111,100,101,115,0,42,109,95,99,111,110,116,105,103,117,111,
-117,115,78,111,100,101,115,80,116,114,0,42,109,95,113,117,97,110,116,105,
-122,101,100,67,111,110,116,105,103,117,111,117,115,78,111,100,101,115,80,116,
-114,0,42,109,95,115,117,98,84,114,101,101,73,110,102,111,80,116,114,0,
-109,95,116,114,97,118,101,114,115,97,108,77,111,100,101,0,109,95,110,117,
-109,83,117,98,116,114,101,101,72,101,97,100,101,114,115,0,42,109,95,110,
-97,109,101,0,109,95,115,104,97,112,101,84,121,112,101,0,109,95,112,97,
-100,100,105,110,103,91,52,93,0,109,95,99,111,108,108,105,115,105,111,110,
-83,104,97,112,101,68,97,116,97,0,109,95,108,111,99,97,108,83,99,97,
-108,105,110,103,0,109,95,112,108,97,110,101,78,111,114,109,97,108,0,109,
-95,112,108,97,110,101,67,111,110,115,116,97,110,116,0,109,95,105,109,112,
-108,105,99,105,116,83,104,97,112,101,68,105,109,101,110,115,105,111,110,115,
-0,109,95,99,111,108,108,105,115,105,111,110,77,97,114,103,105,110,0,109,
-95,112,97,100,100,105,110,103,0,109,95,112,111,115,0,109,95,114,97,100,
-105,117,115,0,109,95,99,111,110,118,101,120,73,110,116,101,114,110,97,108,
-83,104,97,112,101,68,97,116,97,0,42,109,95,108,111,99,97,108,80,111,
-115,105,116,105,111,110,65,114,114,97,121,80,116,114,0,109,95,108,111,99,
-97,108,80,111,115,105,116,105,111,110,65,114,114,97,121,83,105,122,101,0,
-109,95,118,97,108,117,101,0,109,95,112,97,100,91,50,93,0,109,95,118,
-97,108,117,101,115,91,51,93,0,109,95,112,97,100,0,42,109,95,118,101,
-114,116,105,99,101,115,51,102,0,42,109,95,118,101,114,116,105,99,101,115,
-51,100,0,42,109,95,105,110,100,105,99,101,115,51,50,0,42,109,95,51,
-105,110,100,105,99,101,115,49,54,0,42,109,95,51,105,110,100,105,99,101,
-115,56,0,42,109,95,105,110,100,105,99,101,115,49,54,0,109,95,110,117,
-109,84,114,105,97,110,103,108,101,115,0,109,95,110,117,109,86,101,114,116,
-105,99,101,115,0,42,109,95,109,101,115,104,80,97,114,116,115,80,116,114,
-0,109,95,115,99,97,108,105,110,103,0,109,95,110,117,109,77,101,115,104,
-80,97,114,116,115,0,109,95,109,101,115,104,73,110,116,101,114,102,97,99,
-101,0,42,109,95,113,117,97,110,116,105,122,101,100,70,108,111,97,116,66,
-118,104,0,42,109,95,113,117,97,110,116,105,122,101,100,68,111,117,98,108,
-101,66,118,104,0,42,109,95,116,114,105,97,110,103,108,101,73,110,102,111,
-77,97,112,0,109,95,112,97,100,51,91,52,93,0,109,95,116,114,105,109,
-101,115,104,83,104,97,112,101,68,97,116,97,0,109,95,116,114,97,110,115,
-102,111,114,109,0,42,109,95,99,104,105,108,100,83,104,97,112,101,0,109,
-95,99,104,105,108,100,83,104,97,112,101,84,121,112,101,0,109,95,99,104,
-105,108,100,77,97,114,103,105,110,0,42,109,95,99,104,105,108,100,83,104,
-97,112,101,80,116,114,0,109,95,110,117,109,67,104,105,108,100,83,104,97,
-112,101,115,0,109,95,117,112,65,120,105,115,0,109,95,102,108,97,103,115,
-0,109,95,101,100,103,101,86,48,86,49,65,110,103,108,101,0,109,95,101,
-100,103,101,86,49,86,50,65,110,103,108,101,0,109,95,101,100,103,101,86,
-50,86,48,65,110,103,108,101,0,42,109,95,104,97,115,104,84,97,98,108,
-101,80,116,114,0,42,109,95,110,101,120,116,80,116,114,0,42,109,95,118,
-97,108,117,101,65,114,114,97,121,80,116,114,0,42,109,95,107,101,121,65,
-114,114,97,121,80,116,114,0,109,95,99,111,110,118,101,120,69,112,115,105,
-108,111,110,0,109,95,112,108,97,110,97,114,69,112,115,105,108,111,110,0,
-109,95,101,113,117,97,108,86,101,114,116,101,120,84,104,114,101,115,104,111,
-108,100,0,109,95,101,100,103,101,68,105,115,116,97,110,99,101,84,104,114,
-101,115,104,111,108,100,0,109,95,122,101,114,111,65,114,101,97,84,104,114,
-101,115,104,111,108,100,0,109,95,110,101,120,116,83,105,122,101,0,109,95,
-104,97,115,104,84,97,98,108,101,83,105,122,101,0,109,95,110,117,109,86,
-97,108,117,101,115,0,109,95,110,117,109,75,101,121,115,0,109,95,103,105,
-109,112,97,99,116,83,117,98,84,121,112,101,0,42,109,95,117,110,115,99,
-97,108,101,100,80,111,105,110,116,115,70,108,111,97,116,80,116,114,0,42,
-109,95,117,110,115,99,97,108,101,100,80,111,105,110,116,115,68,111,117,98,
-108,101,80,116,114,0,109,95,110,117,109,85,110,115,99,97,108,101,100,80,
-111,105,110,116,115,0,109,95,112,97,100,100,105,110,103,51,91,52,93,0,
-42,109,95,98,114,111,97,100,112,104,97,115,101,72,97,110,100,108,101,0,
-42,109,95,99,111,108,108,105,115,105,111,110,83,104,97,112,101,0,42,109,
-95,114,111,111,116,67,111,108,108,105,115,105,111,110,83,104,97,112,101,0,
-109,95,119,111,114,108,100,84,114,97,110,115,102,111,114,109,0,109,95,105,
-110,116,101,114,112,111,108,97,116,105,111,110,87,111,114,108,100,84,114,97,
-110,115,102,111,114,109,0,109,95,105,110,116,101,114,112,111,108,97,116,105,
-111,110,76,105,110,101,97,114,86,101,108,111,99,105,116,121,0,109,95,105,
-110,116,101,114,112,111,108,97,116,105,111,110,65,110,103,117,108,97,114,86,
-101,108,111,99,105,116,121,0,109,95,97,110,105,115,111,116,114,111,112,105,
-99,70,114,105,99,116,105,111,110,0,109,95,99,111,110,116,97,99,116,80,
-114,111,99,101,115,115,105,110,103,84,104,114,101,115,104,111,108,100,0,109,
-95,100,101,97,99,116,105,118,97,116,105,111,110,84,105,109,101,0,109,95,
-102,114,105,99,116,105,111,110,0,109,95,114,101,115,116,105,116,117,116,105,
-111,110,0,109,95,104,105,116,70,114,97,99,116,105,111,110,0,109,95,99,
-99,100,83,119,101,112,116,83,112,104,101,114,101,82,97,100,105,117,115,0,
-109,95,99,99,100,77,111,116,105,111,110,84,104,114,101,115,104,111,108,100,
-0,109,95,104,97,115,65,110,105,115,111,116,114,111,112,105,99,70,114,105,
-99,116,105,111,110,0,109,95,99,111,108,108,105,115,105,111,110,70,108,97,
-103,115,0,109,95,105,115,108,97,110,100,84,97,103,49,0,109,95,99,111,
-109,112,97,110,105,111,110,73,100,0,109,95,97,99,116,105,118,97,116,105,
-111,110,83,116,97,116,101,49,0,109,95,105,110,116,101,114,110,97,108,84,
-121,112,101,0,109,95,99,104,101,99,107,67,111,108,108,105,100,101,87,105,
-116,104,0,109,95,99,111,108,108,105,115,105,111,110,79,98,106,101,99,116,
-68,97,116,97,0,109,95,105,110,118,73,110,101,114,116,105,97,84,101,110,
-115,111,114,87,111,114,108,100,0,109,95,108,105,110,101,97,114,86,101,108,
-111,99,105,116,121,0,109,95,97,110,103,117,108,97,114,86,101,108,111,99,
-105,116,121,0,109,95,97,110,103,117,108,97,114,70,97,99,116,111,114,0,
-109,95,108,105,110,101,97,114,70,97,99,116,111,114,0,109,95,103,114,97,
-118,105,116,121,0,109,95,103,114,97,118,105,116,121,95,97,99,99,101,108,
-101,114,97,116,105,111,110,0,109,95,105,110,118,73,110,101,114,116,105,97,
-76,111,99,97,108,0,109,95,116,111,116,97,108,70,111,114,99,101,0,109,
-95,116,111,116,97,108,84,111,114,113,117,101,0,109,95,105,110,118,101,114,
-115,101,77,97,115,115,0,109,95,108,105,110,101,97,114,68,97,109,112,105,
-110,103,0,109,95,97,110,103,117,108,97,114,68,97,109,112,105,110,103,0,
-109,95,97,100,100,105,116,105,111,110,97,108,68,97,109,112,105,110,103,70,
-97,99,116,111,114,0,109,95,97,100,100,105,116,105,111,110,97,108,76,105,
-110,101,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,108,100,
-83,113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,103,117,
-108,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,108,100,83,
-113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,103,117,108,
-97,114,68,97,109,112,105,110,103,70,97,99,116,111,114,0,109,95,108,105,
-110,101,97,114,83,108,101,101,112,105,110,103,84,104,114,101,115,104,111,108,
-100,0,109,95,97,110,103,117,108,97,114,83,108,101,101,112,105,110,103,84,
-104,114,101,115,104,111,108,100,0,109,95,97,100,100,105,116,105,111,110,97,
-108,68,97,109,112,105,110,103,0,109,95,110,117,109,67,111,110,115,116,114,
-97,105,110,116,82,111,119,115,0,110,117,98,0,42,109,95,114,98,65,0,
-42,109,95,114,98,66,0,109,95,111,98,106,101,99,116,84,121,112,101,0,
-109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,84,121,112,101,
-0,109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,73,100,0,
-109,95,110,101,101,100,115,70,101,101,100,98,97,99,107,0,109,95,97,112,
-112,108,105,101,100,73,109,112,117,108,115,101,0,109,95,100,98,103,68,114,
-97,119,83,105,122,101,0,109,95,100,105,115,97,98,108,101,67,111,108,108,
-105,115,105,111,110,115,66,101,116,119,101,101,110,76,105,110,107,101,100,66,
-111,100,105,101,115,0,109,95,111,118,101,114,114,105,100,101,78,117,109,83,
-111,108,118,101,114,73,116,101,114,97,116,105,111,110,115,0,109,95,98,114,
-101,97,107,105,110,103,73,109,112,117,108,115,101,84,104,114,101,115,104,111,
-108,100,0,109,95,105,115,69,110,97,98,108,101,100,0,109,95,116,121,112,
-101,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,109,95,112,105,
-118,111,116,73,110,65,0,109,95,112,105,118,111,116,73,110,66,0,109,95,
-114,98,65,70,114,97,109,101,0,109,95,114,98,66,70,114,97,109,101,0,
-109,95,117,115,101,82,101,102,101,114,101,110,99,101,70,114,97,109,101,65,
-0,109,95,97,110,103,117,108,97,114,79,110,108,121,0,109,95,101,110,97,
-98,108,101,65,110,103,117,108,97,114,77,111,116,111,114,0,109,95,109,111,
-116,111,114,84,97,114,103,101,116,86,101,108,111,99,105,116,121,0,109,95,
-109,97,120,77,111,116,111,114,73,109,112,117,108,115,101,0,109,95,108,111,
-119,101,114,76,105,109,105,116,0,109,95,117,112,112,101,114,76,105,109,105,
-116,0,109,95,108,105,109,105,116,83,111,102,116,110,101,115,115,0,109,95,
-98,105,97,115,70,97,99,116,111,114,0,109,95,114,101,108,97,120,97,116,
-105,111,110,70,97,99,116,111,114,0,109,95,115,119,105,110,103,83,112,97,
-110,49,0,109,95,115,119,105,110,103,83,112,97,110,50,0,109,95,116,119,
-105,115,116,83,112,97,110,0,109,95,100,97,109,112,105,110,103,0,109,95,
-108,105,110,101,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95,108,
-105,110,101,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,97,110,
-103,117,108,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95,97,110,
-103,117,108,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,117,115,
-101,76,105,110,101,97,114,82,101,102,101,114,101,110,99,101,70,114,97,109,
-101,65,0,109,95,117,115,101,79,102,102,115,101,116,70,111,114,67,111,110,
-115,116,114,97,105,110,116,70,114,97,109,101,0,109,95,54,100,111,102,68,
-97,116,97,0,109,95,115,112,114,105,110,103,69,110,97,98,108,101,100,91,
-54,93,0,109,95,101,113,117,105,108,105,98,114,105,117,109,80,111,105,110,
-116,91,54,93,0,109,95,115,112,114,105,110,103,83,116,105,102,102,110,101,
-115,115,91,54,93,0,109,95,115,112,114,105,110,103,68,97,109,112,105,110,
-103,91,54,93,0,109,95,108,105,110,101,97,114,83,116,105,102,102,110,101,
-115,115,0,109,95,97,110,103,117,108,97,114,83,116,105,102,102,110,101,115,
-115,0,109,95,118,111,108,117,109,101,83,116,105,102,102,110,101,115,115,0,
-42,109,95,109,97,116,101,114,105,97,108,0,109,95,112,111,115,105,116,105,
-111,110,0,109,95,112,114,101,118,105,111,117,115,80,111,115,105,116,105,111,
-110,0,109,95,118,101,108,111,99,105,116,121,0,109,95,97,99,99,117,109,
-117,108,97,116,101,100,70,111,114,99,101,0,109,95,110,111,114,109,97,108,
-0,109,95,97,114,101,97,0,109,95,97,116,116,97,99,104,0,109,95,110,
-111,100,101,73,110,100,105,99,101,115,91,50,93,0,109,95,114,101,115,116,
-76,101,110,103,116,104,0,109,95,98,98,101,110,100,105,110,103,0,109,95,
-110,111,100,101,73,110,100,105,99,101,115,91,51,93,0,109,95,114,101,115,
-116,65,114,101,97,0,109,95,99,48,91,52,93,0,109,95,110,111,100,101,
-73,110,100,105,99,101,115,91,52,93,0,109,95,114,101,115,116,86,111,108,
-117,109,101,0,109,95,99,49,0,109,95,99,50,0,109,95,99,48,0,109,
-95,108,111,99,97,108,70,114,97,109,101,0,42,109,95,114,105,103,105,100,
-66,111,100,121,0,109,95,110,111,100,101,73,110,100,101,120,0,109,95,97,
-101,114,111,77,111,100,101,108,0,109,95,98,97,117,109,103,97,114,116,101,
-0,109,95,100,114,97,103,0,109,95,108,105,102,116,0,109,95,112,114,101,
-115,115,117,114,101,0,109,95,118,111,108,117,109,101,0,109,95,100,121,110,
-97,109,105,99,70,114,105,99,116,105,111,110,0,109,95,112,111,115,101,77,
-97,116,99,104,0,109,95,114,105,103,105,100,67,111,110,116,97,99,116,72,
-97,114,100,110,101,115,115,0,109,95,107,105,110,101,116,105,99,67,111,110,
-116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,67,
-111,110,116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,97,110,99,
-104,111,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,82,105,
-103,105,100,67,108,117,115,116,101,114,72,97,114,100,110,101,115,115,0,109,
-95,115,111,102,116,75,105,110,101,116,105,99,67,108,117,115,116,101,114,72,
-97,114,100,110,101,115,115,0,109,95,115,111,102,116,83,111,102,116,67,108,
-117,115,116,101,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,
-82,105,103,105,100,67,108,117,115,116,101,114,73,109,112,117,108,115,101,83,
-112,108,105,116,0,109,95,115,111,102,116,75,105,110,101,116,105,99,67,108,
-117,115,116,101,114,73,109,112,117,108,115,101,83,112,108,105,116,0,109,95,
-115,111,102,116,83,111,102,116,67,108,117,115,116,101,114,73,109,112,117,108,
-115,101,83,112,108,105,116,0,109,95,109,97,120,86,111,108,117,109,101,0,
-109,95,116,105,109,101,83,99,97,108,101,0,109,95,118,101,108,111,99,105,
-116,121,73,116,101,114,97,116,105,111,110,115,0,109,95,112,111,115,105,116,
-105,111,110,73,116,101,114,97,116,105,111,110,115,0,109,95,100,114,105,102,
-116,73,116,101,114,97,116,105,111,110,115,0,109,95,99,108,117,115,116,101,
-114,73,116,101,114,97,116,105,111,110,115,0,109,95,114,111,116,0,109,95,
-115,99,97,108,101,0,109,95,97,113,113,0,109,95,99,111,109,0,42,109,
-95,112,111,115,105,116,105,111,110,115,0,42,109,95,119,101,105,103,104,116,
-115,0,109,95,110,117,109,80,111,115,105,116,105,111,110,115,0,109,95,110,
-117,109,87,101,105,103,116,115,0,109,95,98,118,111,108,117,109,101,0,109,
-95,98,102,114,97,109,101,0,109,95,102,114,97,109,101,120,102,111,114,109,
-0,109,95,108,111,99,105,105,0,109,95,105,110,118,119,105,0,109,95,118,
-105,109,112,117,108,115,101,115,91,50,93,0,109,95,100,105,109,112,117,108,
-115,101,115,91,50,93,0,109,95,108,118,0,109,95,97,118,0,42,109,95,
-102,114,97,109,101,114,101,102,115,0,42,109,95,110,111,100,101,73,110,100,
-105,99,101,115,0,42,109,95,109,97,115,115,101,115,0,109,95,110,117,109,
-70,114,97,109,101,82,101,102,115,0,109,95,110,117,109,78,111,100,101,115,
-0,109,95,110,117,109,77,97,115,115,101,115,0,109,95,105,100,109,97,115,
-115,0,109,95,105,109,97,115,115,0,109,95,110,118,105,109,112,117,108,115,
-101,115,0,109,95,110,100,105,109,112,117,108,115,101,115,0,109,95,110,100,
-97,109,112,105,110,103,0,109,95,108,100,97,109,112,105,110,103,0,109,95,
-97,100,97,109,112,105,110,103,0,109,95,109,97,116,99,104,105,110,103,0,
-109,95,109,97,120,83,101,108,102,67,111,108,108,105,115,105,111,110,73,109,
-112,117,108,115,101,0,109,95,115,101,108,102,67,111,108,108,105,115,105,111,
-110,73,109,112,117,108,115,101,70,97,99,116,111,114,0,109,95,99,111,110,
-116,97,105,110,115,65,110,99,104,111,114,0,109,95,99,111,108,108,105,100,
-101,0,109,95,99,108,117,115,116,101,114,73,110,100,101,120,0,42,109,95,
-98,111,100,121,65,0,42,109,95,98,111,100,121,66,0,109,95,114,101,102,
-115,91,50,93,0,109,95,99,102,109,0,109,95,101,114,112,0,109,95,115,
-112,108,105,116,0,109,95,100,101,108,101,116,101,0,109,95,114,101,108,80,
-111,115,105,116,105,111,110,91,50,93,0,109,95,98,111,100,121,65,116,121,
-112,101,0,109,95,98,111,100,121,66,116,121,112,101,0,109,95,106,111,105,
-110,116,84,121,112,101,0,42,109,95,112,111,115,101,0,42,42,109,95,109,
-97,116,101,114,105,97,108,115,0,42,109,95,110,111,100,101,115,0,42,109,
-95,108,105,110,107,115,0,42,109,95,102,97,99,101,115,0,42,109,95,116,
-101,116,114,97,104,101,100,114,97,0,42,109,95,97,110,99,104,111,114,115,
-0,42,109,95,99,108,117,115,116,101,114,115,0,42,109,95,106,111,105,110,
-116,115,0,109,95,110,117,109,77,97,116,101,114,105,97,108,115,0,109,95,
-110,117,109,76,105,110,107,115,0,109,95,110,117,109,70,97,99,101,115,0,
-109,95,110,117,109,84,101,116,114,97,104,101,100,114,97,0,109,95,110,117,
-109,65,110,99,104,111,114,115,0,109,95,110,117,109,67,108,117,115,116,101,
-114,115,0,109,95,110,117,109,74,111,105,110,116,115,0,109,95,99,111,110,
-102,105,103,0,84,89,80,69,72,0,0,0,99,104,97,114,0,117,99,104,
-97,114,0,115,104,111,114,116,0,117,115,104,111,114,116,0,105,110,116,0,
-108,111,110,103,0,117,108,111,110,103,0,102,108,111,97,116,0,100,111,117,
-98,108,101,0,118,111,105,100,0,80,111,105,110,116,101,114,65,114,114,97,
-121,0,98,116,80,104,121,115,105,99,115,83,121,115,116,101,109,0,76,105,
-115,116,66,97,115,101,0,98,116,86,101,99,116,111,114,51,70,108,111,97,
-116,68,97,116,97,0,98,116,86,101,99,116,111,114,51,68,111,117,98,108,
-101,68,97,116,97,0,98,116,77,97,116,114,105,120,51,120,51,70,108,111,
-97,116,68,97,116,97,0,98,116,77,97,116,114,105,120,51,120,51,68,111,
-117,98,108,101,68,97,116,97,0,98,116,84,114,97,110,115,102,111,114,109,
-70,108,111,97,116,68,97,116,97,0,98,116,84,114,97,110,115,102,111,114,
-109,68,111,117,98,108,101,68,97,116,97,0,98,116,66,118,104,83,117,98,
-116,114,101,101,73,110,102,111,68,97,116,97,0,98,116,79,112,116,105,109,
-105,122,101,100,66,118,104,78,111,100,101,70,108,111,97,116,68,97,116,97,
-0,98,116,79,112,116,105,109,105,122,101,100,66,118,104,78,111,100,101,68,
-111,117,98,108,101,68,97,116,97,0,98,116,81,117,97,110,116,105,122,101,
-100,66,118,104,78,111,100,101,68,97,116,97,0,98,116,81,117,97,110,116,
-105,122,101,100,66,118,104,70,108,111,97,116,68,97,116,97,0,98,116,81,
-117,97,110,116,105,122,101,100,66,118,104,68,111,117,98,108,101,68,97,116,
-97,0,98,116,67,111,108,108,105,115,105,111,110,83,104,97,112,101,68,97,
-116,97,0,98,116,83,116,97,116,105,99,80,108,97,110,101,83,104,97,112,
-101,68,97,116,97,0,98,116,67,111,110,118,101,120,73,110,116,101,114,110,
-97,108,83,104,97,112,101,68,97,116,97,0,98,116,80,111,115,105,116,105,
-111,110,65,110,100,82,97,100,105,117,115,0,98,116,77,117,108,116,105,83,
-112,104,101,114,101,83,104,97,112,101,68,97,116,97,0,98,116,73,110,116,
-73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114,116,73,110,116,
-73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114,116,73,110,116,
-73,110,100,101,120,84,114,105,112,108,101,116,68,97,116,97,0,98,116,67,
-104,97,114,73,110,100,101,120,84,114,105,112,108,101,116,68,97,116,97,0,
-98,116,77,101,115,104,80,97,114,116,68,97,116,97,0,98,116,83,116,114,
-105,100,105,110,103,77,101,115,104,73,110,116,101,114,102,97,99,101,68,97,
-116,97,0,98,116,84,114,105,97,110,103,108,101,77,101,115,104,83,104,97,
-112,101,68,97,116,97,0,98,116,84,114,105,97,110,103,108,101,73,110,102,
-111,77,97,112,68,97,116,97,0,98,116,83,99,97,108,101,100,84,114,105,
-97,110,103,108,101,77,101,115,104,83,104,97,112,101,68,97,116,97,0,98,
-116,67,111,109,112,111,117,110,100,83,104,97,112,101,67,104,105,108,100,68,
-97,116,97,0,98,116,67,111,109,112,111,117,110,100,83,104,97,112,101,68,
-97,116,97,0,98,116,67,121,108,105,110,100,101,114,83,104,97,112,101,68,
-97,116,97,0,98,116,67,97,112,115,117,108,101,83,104,97,112,101,68,97,
-116,97,0,98,116,84,114,105,97,110,103,108,101,73,110,102,111,68,97,116,
-97,0,98,116,71,73,109,112,97,99,116,77,101,115,104,83,104,97,112,101,
-68,97,116,97,0,98,116,67,111,110,118,101,120,72,117,108,108,83,104,97,
-112,101,68,97,116,97,0,98,116,67,111,108,108,105,115,105,111,110,79,98,
-106,101,99,116,68,111,117,98,108,101,68,97,116,97,0,98,116,67,111,108,
-108,105,115,105,111,110,79,98,106,101,99,116,70,108,111,97,116,68,97,116,
-97,0,98,116,82,105,103,105,100,66,111,100,121,70,108,111,97,116,68,97,
-116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,111,117,98,108,101,
-68,97,116,97,0,98,116,67,111,110,115,116,114,97,105,110,116,73,110,102,
-111,49,0,98,116,84,121,112,101,100,67,111,110,115,116,114,97,105,110,116,
-68,97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,97,116,97,
-0,98,116,80,111,105,110,116,50,80,111,105,110,116,67,111,110,115,116,114,
-97,105,110,116,70,108,111,97,116,68,97,116,97,0,98,116,80,111,105,110,
-116,50,80,111,105,110,116,67,111,110,115,116,114,97,105,110,116,68,111,117,
-98,108,101,68,97,116,97,0,98,116,72,105,110,103,101,67,111,110,115,116,
-114,97,105,110,116,68,111,117,98,108,101,68,97,116,97,0,98,116,72,105,
-110,103,101,67,111,110,115,116,114,97,105,110,116,70,108,111,97,116,68,97,
-116,97,0,98,116,67,111,110,101,84,119,105,115,116,67,111,110,115,116,114,
-97,105,110,116,68,97,116,97,0,98,116,71,101,110,101,114,105,99,54,68,
-111,102,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,98,116,71,
-101,110,101,114,105,99,54,68,111,102,83,112,114,105,110,103,67,111,110,115,
-116,114,97,105,110,116,68,97,116,97,0,98,116,83,108,105,100,101,114,67,
-111,110,115,116,114,97,105,110,116,68,97,116,97,0,83,111,102,116,66,111,
-100,121,77,97,116,101,114,105,97,108,68,97,116,97,0,83,111,102,116,66,
-111,100,121,78,111,100,101,68,97,116,97,0,83,111,102,116,66,111,100,121,
-76,105,110,107,68,97,116,97,0,83,111,102,116,66,111,100,121,70,97,99,
-101,68,97,116,97,0,83,111,102,116,66,111,100,121,84,101,116,114,97,68,
-97,116,97,0,83,111,102,116,82,105,103,105,100,65,110,99,104,111,114,68,
-97,116,97,0,83,111,102,116,66,111,100,121,67,111,110,102,105,103,68,97,
-116,97,0,83,111,102,116,66,111,100,121,80,111,115,101,68,97,116,97,0,
-83,111,102,116,66,111,100,121,67,108,117,115,116,101,114,68,97,116,97,0,
-98,116,83,111,102,116,66,111,100,121,74,111,105,110,116,68,97,116,97,0,
-98,116,83,111,102,116,66,111,100,121,70,108,111,97,116,68,97,116,97,0,
-84,76,69,78,1,0,1,0,2,0,2,0,4,0,4,0,4,0,4,0,
-8,0,0,0,16,0,48,0,16,0,16,0,32,0,48,0,96,0,64,0,
--128,0,20,0,48,0,80,0,16,0,96,0,-112,0,16,0,56,0,56,0,
-20,0,72,0,4,0,4,0,8,0,4,0,56,0,32,0,80,0,72,0,
-96,0,80,0,32,0,64,0,64,0,16,0,72,0,80,0,-40,1,8,1,
--16,1,-88,3,8,0,64,0,0,0,96,0,-128,0,104,1,-24,0,-32,0,
-8,1,104,1,-40,0,16,0,104,0,24,0,40,0,104,0,96,0,104,0,
--56,0,104,1,112,0,-40,1,83,84,82,67,61,0,0,0,10,0,3,0,
-4,0,0,0,4,0,1,0,9,0,2,0,11,0,3,0,10,0,3,0,
-10,0,4,0,10,0,5,0,12,0,2,0,9,0,6,0,9,0,7,0,
-13,0,1,0,7,0,8,0,14,0,1,0,8,0,8,0,15,0,1,0,
-13,0,9,0,16,0,1,0,14,0,9,0,17,0,2,0,15,0,10,0,
-13,0,11,0,18,0,2,0,16,0,10,0,14,0,11,0,19,0,4,0,
-4,0,12,0,4,0,13,0,2,0,14,0,2,0,15,0,20,0,6,0,
-13,0,16,0,13,0,17,0,4,0,18,0,4,0,19,0,4,0,20,0,
-0,0,21,0,21,0,6,0,14,0,16,0,14,0,17,0,4,0,18,0,
-4,0,19,0,4,0,20,0,0,0,21,0,22,0,3,0,2,0,14,0,
-2,0,15,0,4,0,22,0,23,0,12,0,13,0,23,0,13,0,24,0,
-13,0,25,0,4,0,26,0,4,0,27,0,4,0,28,0,4,0,29,0,
-20,0,30,0,22,0,31,0,19,0,32,0,4,0,33,0,4,0,34,0,
-24,0,12,0,14,0,23,0,14,0,24,0,14,0,25,0,4,0,26,0,
-4,0,27,0,4,0,28,0,4,0,29,0,21,0,30,0,22,0,31,0,
-4,0,33,0,4,0,34,0,19,0,32,0,25,0,3,0,0,0,35,0,
-4,0,36,0,0,0,37,0,26,0,5,0,25,0,38,0,13,0,39,0,
-13,0,40,0,7,0,41,0,0,0,21,0,27,0,5,0,25,0,38,0,
-13,0,39,0,13,0,42,0,7,0,43,0,4,0,44,0,28,0,2,0,
-13,0,45,0,7,0,46,0,29,0,4,0,27,0,47,0,28,0,48,0,
-4,0,49,0,0,0,37,0,30,0,1,0,4,0,50,0,31,0,2,0,
-2,0,50,0,0,0,51,0,32,0,2,0,2,0,52,0,0,0,51,0,
-33,0,2,0,0,0,52,0,0,0,53,0,34,0,8,0,13,0,54,0,
-14,0,55,0,30,0,56,0,32,0,57,0,33,0,58,0,31,0,59,0,
-4,0,60,0,4,0,61,0,35,0,4,0,34,0,62,0,13,0,63,0,
-4,0,64,0,0,0,37,0,36,0,7,0,25,0,38,0,35,0,65,0,
-23,0,66,0,24,0,67,0,37,0,68,0,7,0,43,0,0,0,69,0,
-38,0,2,0,36,0,70,0,13,0,39,0,39,0,4,0,17,0,71,0,
-25,0,72,0,4,0,73,0,7,0,74,0,40,0,4,0,25,0,38,0,
-39,0,75,0,4,0,76,0,7,0,43,0,41,0,3,0,27,0,47,0,
-4,0,77,0,0,0,37,0,42,0,3,0,27,0,47,0,4,0,77,0,
-0,0,37,0,43,0,4,0,4,0,78,0,7,0,79,0,7,0,80,0,
-7,0,81,0,37,0,14,0,4,0,82,0,4,0,83,0,43,0,84,0,
-4,0,85,0,7,0,86,0,7,0,87,0,7,0,88,0,7,0,89,0,
-7,0,90,0,4,0,91,0,4,0,92,0,4,0,93,0,4,0,94,0,
-0,0,37,0,44,0,5,0,25,0,38,0,35,0,65,0,13,0,39,0,
-7,0,43,0,4,0,95,0,45,0,5,0,27,0,47,0,13,0,96,0,
-14,0,97,0,4,0,98,0,0,0,99,0,46,0,24,0,9,0,100,0,
-9,0,101,0,25,0,102,0,0,0,35,0,18,0,103,0,18,0,104,0,
-14,0,105,0,14,0,106,0,14,0,107,0,8,0,108,0,8,0,109,0,
-8,0,110,0,8,0,111,0,8,0,112,0,8,0,113,0,8,0,114,0,
-4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0,4,0,119,0,
-4,0,120,0,4,0,121,0,0,0,37,0,47,0,23,0,9,0,100,0,
-9,0,101,0,25,0,102,0,0,0,35,0,17,0,103,0,17,0,104,0,
-13,0,105,0,13,0,106,0,13,0,107,0,7,0,108,0,7,0,109,0,
-7,0,110,0,7,0,111,0,7,0,112,0,7,0,113,0,7,0,114,0,
-4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0,4,0,119,0,
-4,0,120,0,4,0,121,0,48,0,21,0,47,0,122,0,15,0,123,0,
-13,0,124,0,13,0,125,0,13,0,126,0,13,0,127,0,13,0,-128,0,
-13,0,-127,0,13,0,-126,0,13,0,-125,0,13,0,-124,0,7,0,-123,0,
-7,0,-122,0,7,0,-121,0,7,0,-120,0,7,0,-119,0,7,0,-118,0,
-7,0,-117,0,7,0,-116,0,7,0,-115,0,4,0,-114,0,49,0,22,0,
-46,0,122,0,16,0,123,0,14,0,124,0,14,0,125,0,14,0,126,0,
-14,0,127,0,14,0,-128,0,14,0,-127,0,14,0,-126,0,14,0,-125,0,
-14,0,-124,0,8,0,-123,0,8,0,-122,0,8,0,-121,0,8,0,-120,0,
-8,0,-119,0,8,0,-118,0,8,0,-117,0,8,0,-116,0,8,0,-115,0,
-4,0,-114,0,0,0,37,0,50,0,2,0,4,0,-113,0,4,0,-112,0,
-51,0,13,0,52,0,-111,0,52,0,-110,0,0,0,35,0,4,0,-109,0,
-4,0,-108,0,4,0,-107,0,4,0,-106,0,7,0,-105,0,7,0,-104,0,
-4,0,-103,0,4,0,-102,0,7,0,-101,0,4,0,-100,0,53,0,3,0,
-51,0,-99,0,13,0,-98,0,13,0,-97,0,54,0,3,0,51,0,-99,0,
-14,0,-98,0,14,0,-97,0,55,0,13,0,51,0,-99,0,18,0,-96,0,
-18,0,-95,0,4,0,-94,0,4,0,-93,0,4,0,-92,0,7,0,-91,0,
-7,0,-90,0,7,0,-89,0,7,0,-88,0,7,0,-87,0,7,0,-86,0,
-7,0,-85,0,56,0,13,0,51,0,-99,0,17,0,-96,0,17,0,-95,0,
-4,0,-94,0,4,0,-93,0,4,0,-92,0,7,0,-91,0,7,0,-90,0,
-7,0,-89,0,7,0,-88,0,7,0,-87,0,7,0,-86,0,7,0,-85,0,
-57,0,11,0,51,0,-99,0,17,0,-96,0,17,0,-95,0,7,0,-84,0,
-7,0,-83,0,7,0,-82,0,7,0,-87,0,7,0,-86,0,7,0,-85,0,
-7,0,-81,0,0,0,21,0,58,0,9,0,51,0,-99,0,17,0,-96,0,
-17,0,-95,0,13,0,-80,0,13,0,-79,0,13,0,-78,0,13,0,-77,0,
-4,0,-76,0,4,0,-75,0,59,0,5,0,58,0,-74,0,4,0,-73,0,
-7,0,-72,0,7,0,-71,0,7,0,-70,0,60,0,9,0,51,0,-99,0,
-17,0,-96,0,17,0,-95,0,7,0,-80,0,7,0,-79,0,7,0,-78,0,
-7,0,-77,0,4,0,-76,0,4,0,-75,0,61,0,4,0,7,0,-69,0,
-7,0,-68,0,7,0,-67,0,4,0,78,0,62,0,10,0,61,0,-66,0,
-13,0,-65,0,13,0,-64,0,13,0,-63,0,13,0,-62,0,13,0,-61,0,
-7,0,-123,0,7,0,-60,0,4,0,-59,0,4,0,53,0,63,0,4,0,
-61,0,-66,0,4,0,-58,0,7,0,-57,0,4,0,-56,0,64,0,4,0,
-13,0,-61,0,61,0,-66,0,4,0,-55,0,7,0,-54,0,65,0,7,0,
-13,0,-53,0,61,0,-66,0,4,0,-52,0,7,0,-51,0,7,0,-50,0,
-7,0,-49,0,4,0,53,0,66,0,6,0,15,0,-48,0,13,0,-50,0,
-13,0,-47,0,52,0,-46,0,4,0,-45,0,7,0,-49,0,67,0,26,0,
-4,0,-44,0,7,0,-43,0,7,0,-81,0,7,0,-42,0,7,0,-41,0,
-7,0,-40,0,7,0,-39,0,7,0,-38,0,7,0,-37,0,7,0,-36,0,
-7,0,-35,0,7,0,-34,0,7,0,-33,0,7,0,-32,0,7,0,-31,0,
-7,0,-30,0,7,0,-29,0,7,0,-28,0,7,0,-27,0,7,0,-26,0,
-7,0,-25,0,4,0,-24,0,4,0,-23,0,4,0,-22,0,4,0,-21,0,
-4,0,116,0,68,0,12,0,15,0,-20,0,15,0,-19,0,15,0,-18,0,
-13,0,-17,0,13,0,-16,0,7,0,-15,0,4,0,-14,0,4,0,-13,0,
-4,0,-12,0,4,0,-11,0,7,0,-51,0,4,0,53,0,69,0,27,0,
-17,0,-10,0,15,0,-9,0,15,0,-8,0,13,0,-17,0,13,0,-7,0,
-13,0,-6,0,13,0,-5,0,13,0,-4,0,13,0,-3,0,4,0,-2,0,
-7,0,-1,0,4,0,0,1,4,0,1,1,4,0,2,1,7,0,3,1,
-7,0,4,1,4,0,5,1,4,0,6,1,7,0,7,1,7,0,8,1,
-7,0,9,1,7,0,10,1,7,0,11,1,7,0,12,1,4,0,13,1,
-4,0,14,1,4,0,15,1,70,0,12,0,9,0,16,1,9,0,17,1,
-13,0,18,1,7,0,19,1,7,0,20,1,7,0,21,1,4,0,22,1,
-13,0,23,1,4,0,24,1,4,0,25,1,4,0,26,1,4,0,53,0,
-71,0,19,0,47,0,122,0,68,0,27,1,61,0,28,1,62,0,29,1,
-63,0,30,1,64,0,31,1,65,0,32,1,66,0,33,1,69,0,34,1,
-70,0,35,1,4,0,36,1,4,0,1,1,4,0,37,1,4,0,38,1,
-4,0,39,1,4,0,40,1,4,0,41,1,4,0,42,1,67,0,43,1,
-};
+char sBulletDNAstr64[]= {
+char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(63),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109),
+char(95),char(99),char(97),char(112),char(97),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(100),char(97),char(116),char(97),char(0),char(109),char(95),
+char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(115),char(0),char(109),char(95),char(99),char(111),
+char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),
+char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(115),char(0),char(42),char(102),char(105),char(114),char(115),char(116),char(0),char(42),char(108),char(97),char(115),
+char(116),char(0),char(109),char(95),char(102),char(108),char(111),char(97),char(116),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(108),char(91),char(51),
+char(93),char(0),char(109),char(95),char(98),char(97),char(115),char(105),char(115),char(0),char(109),char(95),char(111),char(114),char(105),char(103),char(105),char(110),char(0),char(109),
+char(95),char(114),char(111),char(111),char(116),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),
+char(116),char(114),char(101),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),
+char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(91),char(51),char(93),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),
+char(101),char(100),char(65),char(97),char(98),char(98),char(77),char(97),char(120),char(91),char(51),char(93),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),
+char(105),char(110),char(79),char(114),char(103),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),char(97),char(120),char(79),char(114),char(103),char(0),char(109),
+char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),char(80),char(97),
+char(114),char(116),char(0),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),
+char(95),char(112),char(97),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),
+char(120),char(79),char(114),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(98),
+char(118),char(104),char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(0),char(109),char(95),char(98),char(118),char(104),char(65),char(97),char(98),char(98),char(77),
+char(97),char(120),char(0),char(109),char(95),char(98),char(118),char(104),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),
+char(0),char(109),char(95),char(99),char(117),char(114),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(117),char(115),
+char(101),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(110),char(117),char(109),char(67),
+char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(76),char(101),char(97),char(102),char(78),char(111),char(100),char(101),char(115),char(0),char(109),
+char(95),char(110),char(117),char(109),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),
+char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(99),char(111),char(110),char(116),char(105),char(103),char(117),char(111),
+char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),
+char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),
+char(114),char(0),char(42),char(109),char(95),char(115),char(117),char(98),char(84),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(80),char(116),char(114),char(0),
+char(109),char(95),char(116),char(114),char(97),char(118),char(101),char(114),char(115),char(97),char(108),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(110),char(117),
+char(109),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(72),char(101),char(97),char(100),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(110),
+char(97),char(109),char(101),char(0),char(109),char(95),char(115),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(112),char(97),
+char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
+char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(83),char(99),char(97),
+char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(101),char(78),char(111),char(114),char(109),char(97),char(108),char(0),char(109),
+char(95),char(112),char(108),char(97),char(110),char(101),char(67),char(111),char(110),char(115),char(116),char(97),char(110),char(116),char(0),char(109),char(95),char(105),char(109),char(112),
+char(108),char(105),char(99),char(105),char(116),char(83),char(104),char(97),char(112),char(101),char(68),char(105),char(109),char(101),char(110),char(115),char(105),char(111),char(110),char(115),
+char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(109),
+char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(111),char(115),char(0),char(109),char(95),char(114),char(97),char(100),
+char(105),char(117),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),
+char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(42),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(80),char(111),
+char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(108),char(111),char(99),
+char(97),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(83),char(105),char(122),char(101),char(0),
+char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(0),char(109),char(95),char(112),char(97),char(100),char(91),char(50),char(93),char(0),char(109),char(95),char(118),
+char(97),char(108),char(117),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(112),char(97),char(100),char(0),char(42),char(109),char(95),char(118),char(101),
+char(114),char(116),char(105),char(99),char(101),char(115),char(51),char(102),char(0),char(42),char(109),char(95),char(118),char(101),char(114),char(116),char(105),char(99),char(101),char(115),
+char(51),char(100),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(51),char(50),char(0),char(42),char(109),char(95),char(51),
+char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(42),char(109),char(95),char(51),char(105),char(110),char(100),char(105),char(99),char(101),
+char(115),char(56),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(109),char(95),char(110),char(117),
+char(109),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(101),char(114),char(116),
+char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(115),char(80),char(116),char(114),
+char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(101),char(115),char(104),
+char(80),char(97),char(114),char(116),char(115),char(0),char(109),char(95),char(109),char(101),char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),
+char(101),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(70),char(108),char(111),char(97),char(116),char(66),
+char(118),char(104),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(68),char(111),char(117),char(98),char(108),
+char(101),char(66),char(118),char(104),char(0),char(42),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),
+char(77),char(97),char(112),char(0),char(109),char(95),char(112),char(97),char(100),char(51),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(114),char(105),char(109),
+char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(116),char(114),char(97),char(110),char(115),
+char(102),char(111),char(114),char(109),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(0),char(109),
+char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),
+char(105),char(108),char(100),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),
+char(97),char(112),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(104),char(105),char(108),char(100),char(83),char(104),char(97),
+char(112),char(101),char(115),char(0),char(109),char(95),char(117),char(112),char(65),char(120),char(105),char(115),char(0),char(109),char(95),char(102),char(108),char(97),char(103),char(115),
+char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(48),char(86),char(49),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),
+char(100),char(103),char(101),char(86),char(49),char(86),char(50),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),
+char(50),char(86),char(48),char(65),char(110),char(103),char(108),char(101),char(0),char(42),char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),
+char(101),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(110),char(101),char(120),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(118),
+char(97),char(108),char(117),char(101),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(107),char(101),char(121),char(65),
+char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(99),char(111),char(110),char(118),char(101),char(120),char(69),char(112),char(115),char(105),
+char(108),char(111),char(110),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(97),char(114),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),
+char(109),char(95),char(101),char(113),char(117),char(97),char(108),char(86),char(101),char(114),char(116),char(101),char(120),char(84),char(104),char(114),char(101),char(115),char(104),char(111),
+char(108),char(100),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(68),char(105),char(115),char(116),char(97),char(110),char(99),char(101),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(122),char(101),char(114),char(111),char(65),char(114),char(101),char(97),char(84),char(104),char(114),
+char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),char(101),char(120),char(116),char(83),char(105),char(122),char(101),char(0),char(109),char(95),
+char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(110),char(117),char(109),char(86),
+char(97),char(108),char(117),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(75),char(101),char(121),char(115),char(0),char(109),char(95),char(103),char(105),
+char(109),char(112),char(97),char(99),char(116),char(83),char(117),char(98),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),
+char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(70),char(108),char(111),char(97),char(116),char(80),char(116),char(114),char(0),char(42),
+char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(68),char(111),char(117),char(98),
+char(108),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(85),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),
+char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(51),char(91),char(52),char(93),char(0),
+char(42),char(109),char(95),char(98),char(114),char(111),char(97),char(100),char(112),char(104),char(97),char(115),char(101),char(72),char(97),char(110),char(100),char(108),char(101),char(0),
+char(42),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(42),char(109),
+char(95),char(114),char(111),char(111),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),
+char(109),char(95),char(119),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),
+char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),
+char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),
+char(111),char(110),char(76),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(105),
+char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),
+char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),
+char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),
+char(114),char(111),char(99),char(101),char(115),char(115),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
+char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),char(111),char(110),char(84),char(105),char(109),char(101),char(0),char(109),char(95),
+char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(114),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),
+char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),
+char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(99),char(100),
+char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114),char(101),char(82),char(97),char(100),char(105),char(117),char(115),char(0),char(109),char(95),
+char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
+char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),char(114),char(105),char(99),char(116),
+char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(108),char(97),char(103),char(115),
+char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84),char(97),char(103),char(49),char(0),char(109),char(95),char(99),char(111),char(109),char(112),
+char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),char(111),char(110),
+char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(84),char(121),char(112),
+char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(87),char(105),char(116),char(104),
+char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(0),char(109),char(95),char(103),char(114),char(97),char(118),
+char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),
+char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(84),char(101),
+char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(86),char(101),
+char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),
+char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),
+char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(103),char(114),
+char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),char(101),char(108),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(0),char(109),
+char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(76),char(111),char(99),char(97),char(108),char(0),char(109),char(95),char(116),
+char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(84),char(111),char(114),
+char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),char(101),char(114),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(109),char(95),
+char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(110),char(103),char(117),
+char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),
+char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),
+char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(76),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),
+char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),
+char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),
+char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),
+char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),
+char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(101),char(101),char(112),
+char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),
+char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),
+char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),
+char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(82),char(111),char(119),char(115),char(0),
+char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),char(65),char(0),char(42),char(109),char(95),char(114),char(98),char(66),char(0),char(109),char(95),
+char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),
+char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),
+char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(100),char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),
+char(101),char(100),char(98),char(97),char(99),char(107),char(0),char(109),char(95),char(97),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),
+char(108),char(115),char(101),char(0),char(109),char(95),char(100),char(98),char(103),char(68),char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),
+char(100),char(105),char(115),char(97),char(98),char(108),char(101),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),
+char(119),char(101),char(101),char(110),char(76),char(105),char(110),char(107),char(101),char(100),char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),
+char(118),char(101),char(114),char(114),char(105),char(100),char(101),char(78),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),
+char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(98),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),
+char(117),char(108),char(115),char(101),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),
+char(97),char(98),char(108),char(101),char(100),char(0),char(109),char(95),char(116),char(121),char(112),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),
+char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(65),char(0),char(109),char(95),
+char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(98),char(65),char(70),char(114),char(97),char(109),char(101),char(0),
+char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(82),char(101),char(102),char(101),
+char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),
+char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),char(98),char(108),char(101),char(65),char(110),char(103),char(117),char(108),char(97),
+char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),char(116),char(111),char(114),char(84),char(97),char(114),char(103),char(101),char(116),
+char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(109),char(97),char(120),char(77),char(111),char(116),char(111),char(114),char(73),
+char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
+char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),char(109),char(105),char(116),
+char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(98),char(105),char(97),char(115),char(70),char(97),char(99),char(116),char(111),
+char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),char(105),char(111),char(110),char(70),char(97),char(99),char(116),char(111),char(114),
+char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),char(119),char(105),char(110),
+char(103),char(83),char(112),char(97),char(110),char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),char(110),char(0),char(109),
+char(95),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),
+char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),
+char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),
+char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),
+char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(115),char(101),char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),
+char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),
+char(102),char(102),char(115),char(101),char(116),char(70),char(111),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),
+char(97),char(109),char(101),char(0),char(109),char(95),char(54),char(100),char(111),char(102),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),
+char(105),char(110),char(103),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(91),char(54),char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),
+char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),
+char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),
+char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(91),char(54),char(93),char(0),char(109),char(95),char(116),char(97),
+char(117),char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69),char(114),
+char(114),char(111),char(114),char(82),char(101),char(100),char(117),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0),char(109),
+char(95),char(101),char(114),char(112),char(0),char(109),char(95),char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97),char(108),
+char(67),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80),char(101),
+char(110),char(101),char(116),char(114),char(97),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
+char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114),char(112),
+char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114),char(109),
+char(115),char(116),char(97),char(114),char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(97),char(120),
+char(71),char(121),char(114),char(111),char(115),char(99),char(111),char(112),char(105),char(99),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(115),char(105),
+char(110),char(103),char(108),char(101),char(65),char(120),char(105),char(115),char(82),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),
+char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),char(117),char(109),char(73),char(116),
+char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(77),char(111),char(100),
+char(101),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(110),char(103),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(82),char(101),
+char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
+char(95),char(109),char(105),char(110),char(105),char(109),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(66),char(97),char(116),char(99),char(104),char(83),
+char(105),char(122),char(101),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),
+char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),
+char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(118),char(111),
+char(108),char(117),char(109),char(101),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(116),
+char(101),char(114),char(105),char(97),char(108),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),
+char(114),char(101),char(118),char(105),char(111),char(117),char(115),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(118),char(101),
+char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(99),char(99),char(117),char(109),char(117),char(108),char(97),char(116),char(101),char(100),
+char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(110),char(111),char(114),char(109),char(97),char(108),char(0),char(109),char(95),char(97),char(114),char(101),
+char(97),char(0),char(109),char(95),char(97),char(116),char(116),char(97),char(99),char(104),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),
+char(105),char(99),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(76),char(101),char(110),char(103),char(116),char(104),
+char(0),char(109),char(95),char(98),char(98),char(101),char(110),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),
+char(100),char(105),char(99),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(65),char(114),char(101),char(97),char(0),
+char(109),char(95),char(99),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),
+char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),
+char(99),char(49),char(0),char(109),char(95),char(99),char(50),char(0),char(109),char(95),char(99),char(48),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),
+char(70),char(114),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(0),char(109),
+char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(97),char(101),char(114),char(111),char(77),char(111),char(100),
+char(101),char(108),char(0),char(109),char(95),char(98),char(97),char(117),char(109),char(103),char(97),char(114),char(116),char(101),char(0),char(109),char(95),char(100),char(114),char(97),
+char(103),char(0),char(109),char(95),char(108),char(105),char(102),char(116),char(0),char(109),char(95),char(112),char(114),char(101),char(115),char(115),char(117),char(114),char(101),char(0),
+char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(100),char(121),char(110),char(97),char(109),char(105),char(99),char(70),char(114),
+char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(111),char(115),char(101),char(77),char(97),char(116),char(99),char(104),char(0),char(109),
+char(95),char(114),char(105),char(103),char(105),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),
+char(115),char(0),char(109),char(95),char(107),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),
+char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),
+char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(72),char(97),char(114),
+char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),
+char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),
+char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),
+char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),
+char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(67),
+char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),
+char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),
+char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),
+char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),
+char(116),char(0),char(109),char(95),char(109),char(97),char(120),char(86),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(116),char(105),char(109),char(101),
+char(83),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(73),char(116),char(101),char(114),
+char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(73),char(116),char(101),
+char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(100),char(114),char(105),char(102),char(116),char(73),char(116),char(101),char(114),char(97),
+char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(116),char(101),char(114),char(97),
+char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(114),char(111),char(116),char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(101),char(0),
+char(109),char(95),char(97),char(113),char(113),char(0),char(109),char(95),char(99),char(111),char(109),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(105),char(116),
+char(105),char(111),char(110),char(115),char(0),char(42),char(109),char(95),char(119),char(101),char(105),char(103),char(104),char(116),char(115),char(0),char(109),char(95),char(110),char(117),
+char(109),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(87),char(101),char(105),char(103),
+char(116),char(115),char(0),char(109),char(95),char(98),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(98),char(102),char(114),char(97),char(109),
+char(101),char(0),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(120),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(108),char(111),char(99),
+char(105),char(105),char(0),char(109),char(95),char(105),char(110),char(118),char(119),char(105),char(0),char(109),char(95),char(118),char(105),char(109),char(112),char(117),char(108),char(115),
+char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),
+char(0),char(109),char(95),char(108),char(118),char(0),char(109),char(95),char(97),char(118),char(0),char(42),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(114),
+char(101),char(102),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(0),char(42),
+char(109),char(95),char(109),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(114),char(97),char(109),char(101),char(82),
+char(101),char(102),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(78),char(111),char(100),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),
+char(77),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(105),char(100),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(105),char(109),
+char(97),char(115),char(115),char(0),char(109),char(95),char(110),char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),
+char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(97),char(109),char(112),char(105),char(110),char(103),
+char(0),char(109),char(95),char(108),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),char(100),char(97),char(109),char(112),char(105),
+char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(116),char(99),char(104),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(120),char(83),
+char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),
+char(109),char(95),char(115),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),char(109),char(112),char(117),char(108),
+char(115),char(101),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(105),char(110),char(115),char(65),
+char(110),char(99),char(104),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(100),char(101),char(0),char(109),char(95),char(99),char(108),
+char(117),char(115),char(116),char(101),char(114),char(73),char(110),char(100),char(101),char(120),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(0),
+char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(0),char(109),char(95),char(114),char(101),char(102),char(115),char(91),char(50),char(93),char(0),char(109),
+char(95),char(99),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(100),char(101),char(108),char(101),char(116),
+char(101),char(0),char(109),char(95),char(114),char(101),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(91),char(50),char(93),char(0),char(109),
+char(95),char(98),char(111),char(100),char(121),char(65),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(116),char(121),
+char(112),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(112),char(111),
+char(115),char(101),char(0),char(42),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(42),char(109),char(95),
+char(110),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),char(115),char(0),char(42),char(109),char(95),char(102),char(97),
+char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(116),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(42),char(109),
+char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(42),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(115),
+char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(116),char(101),
+char(114),char(105),char(97),char(108),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(76),char(105),char(110),char(107),char(115),char(0),char(109),char(95),char(110),
+char(117),char(109),char(70),char(97),char(99),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(84),char(101),char(116),char(114),char(97),char(104),char(101),
+char(100),char(114),char(97),char(0),char(109),char(95),char(110),char(117),char(109),char(65),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(109),char(95),char(110),
+char(117),char(109),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(74),char(111),char(105),char(110),
+char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(102),char(105),char(103),char(0),char(84),char(89),char(80),char(69),char(76),char(0),char(0),char(0),
+char(99),char(104),char(97),char(114),char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104),
+char(111),char(114),char(116),char(0),char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102),
+char(108),char(111),char(97),char(116),char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105),
+char(110),char(116),char(101),char(114),char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83),
+char(121),char(115),char(116),char(101),char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99),
+char(116),char(111),char(114),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116),
+char(111),char(114),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),
+char(105),char(120),char(51),char(120),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),
+char(114),char(105),char(120),char(51),char(120),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),
+char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(66),char(118),char(104),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(70),
+char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),
+char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70),char(108),char(111),char(97),char(116),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(68),
+char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
+char(110),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97),char(116),char(105),char(99),char(80),
+char(108),char(97),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),
+char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100),char(105),char(117),char(115),char(0),
+char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),
+char(116),char(97),char(0),char(98),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(83),char(104),char(111),char(114),char(116),char(73),char(110),char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),
+char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),
+char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(68),char(97),
+char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115),char(104),char(73),char(110),char(116),
+char(101),char(114),char(102),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),
+char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),
+char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),
+char(99),char(97),char(108),char(101),char(100),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),
+char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),
+char(112),char(101),char(67),char(104),char(105),char(108),char(100),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),
+char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121),char(108),char(105),char(110),char(100),
+char(101),char(114),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108),
+char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),
+char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),char(112),char(97),char(99),char(116),char(77),
+char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101),
+char(120),char(72),char(117),char(108),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),
+char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
+char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),
+char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),
+char(87),char(111),char(114),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),
+char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),char(111),char(117),char(98),char(108),
+char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),
+char(100),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),
+char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),
+char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
+char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49),
+char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),
+char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(97),char(116),char(97),char(0),char(98),
+char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),
+char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),
+char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),
+char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
+char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),
+char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
+char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),
+char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),
+char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),
+char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),
+char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),
+char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),
+char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),
+char(121),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(76),char(105),
+char(110),char(107),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(97),char(99),char(101),char(68),
+char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84),char(101),char(116),char(114),char(97),char(68),char(97),char(116),
+char(97),char(0),char(83),char(111),char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110),char(99),char(104),char(111),char(114),char(68),char(97),char(116),
+char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110),char(102),char(105),char(103),char(68),char(97),char(116),char(97),
+char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
+char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
+char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(0),char(0),
+char(84),char(76),char(69),char(78),char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(4),char(0),
+char(8),char(0),char(0),char(0),char(16),char(0),char(48),char(0),char(16),char(0),char(16),char(0),char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0),
+char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(96),char(0),char(-112),char(0),char(16),char(0),char(56),char(0),char(56),char(0),
+char(20),char(0),char(72),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),char(56),char(0),char(32),char(0),char(80),char(0),char(72),char(0),
+char(96),char(0),char(80),char(0),char(32),char(0),char(64),char(0),char(64),char(0),char(16),char(0),char(72),char(0),char(80),char(0),char(-32),char(1),char(16),char(1),
+char(-72),char(0),char(-104),char(0),char(104),char(0),char(88),char(0),char(-8),char(1),char(-80),char(3),char(8),char(0),char(64),char(0),char(0),char(0),char(96),char(0),
+char(-128),char(0),char(104),char(1),char(-24),char(0),char(-32),char(0),char(8),char(1),char(104),char(1),char(-40),char(0),char(16),char(0),char(104),char(0),char(24),char(0),
+char(40),char(0),char(104),char(0),char(96),char(0),char(104),char(0),char(-56),char(0),char(104),char(1),char(112),char(0),char(-32),char(1),char(83),char(84),char(82),char(67),
+char(65),char(0),char(0),char(0),char(10),char(0),char(3),char(0),char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),char(9),char(0),char(2),char(0),
+char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0),char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),char(12),char(0),char(2),char(0),
+char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0),char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(14),char(0),char(1),char(0),
+char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0),char(13),char(0),char(9),char(0),char(16),char(0),char(1),char(0),char(14),char(0),char(9),char(0),
+char(17),char(0),char(2),char(0),char(15),char(0),char(10),char(0),char(13),char(0),char(11),char(0),char(18),char(0),char(2),char(0),char(16),char(0),char(10),char(0),
+char(14),char(0),char(11),char(0),char(19),char(0),char(4),char(0),char(4),char(0),char(12),char(0),char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),
+char(2),char(0),char(15),char(0),char(20),char(0),char(6),char(0),char(13),char(0),char(16),char(0),char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),
+char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(21),char(0),char(6),char(0),char(14),char(0),char(16),char(0),
+char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),
+char(22),char(0),char(3),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(4),char(0),char(22),char(0),char(23),char(0),char(12),char(0),
+char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0),char(13),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),
+char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(20),char(0),char(30),char(0),char(22),char(0),char(31),char(0),char(19),char(0),char(32),char(0),
+char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(24),char(0),char(12),char(0),char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),
+char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),
+char(21),char(0),char(30),char(0),char(22),char(0),char(31),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(19),char(0),char(32),char(0),
+char(25),char(0),char(3),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(36),char(0),char(0),char(0),char(37),char(0),char(26),char(0),char(5),char(0),
+char(25),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(40),char(0),char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),
+char(27),char(0),char(5),char(0),char(25),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),
+char(4),char(0),char(44),char(0),char(28),char(0),char(2),char(0),char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(29),char(0),char(4),char(0),
+char(27),char(0),char(47),char(0),char(28),char(0),char(48),char(0),char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(30),char(0),char(1),char(0),
+char(4),char(0),char(50),char(0),char(31),char(0),char(2),char(0),char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(32),char(0),char(2),char(0),
+char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0),char(33),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),
+char(34),char(0),char(8),char(0),char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),char(30),char(0),char(56),char(0),char(32),char(0),char(57),char(0),
+char(33),char(0),char(58),char(0),char(31),char(0),char(59),char(0),char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(35),char(0),char(4),char(0),
+char(34),char(0),char(62),char(0),char(13),char(0),char(63),char(0),char(4),char(0),char(64),char(0),char(0),char(0),char(37),char(0),char(36),char(0),char(7),char(0),
+char(25),char(0),char(38),char(0),char(35),char(0),char(65),char(0),char(23),char(0),char(66),char(0),char(24),char(0),char(67),char(0),char(37),char(0),char(68),char(0),
+char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0),char(38),char(0),char(2),char(0),char(36),char(0),char(70),char(0),char(13),char(0),char(39),char(0),
+char(39),char(0),char(4),char(0),char(17),char(0),char(71),char(0),char(25),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),
+char(40),char(0),char(4),char(0),char(25),char(0),char(38),char(0),char(39),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),
+char(41),char(0),char(3),char(0),char(27),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(42),char(0),char(3),char(0),
+char(27),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(43),char(0),char(4),char(0),char(4),char(0),char(78),char(0),
+char(7),char(0),char(79),char(0),char(7),char(0),char(80),char(0),char(7),char(0),char(81),char(0),char(37),char(0),char(14),char(0),char(4),char(0),char(82),char(0),
+char(4),char(0),char(83),char(0),char(43),char(0),char(84),char(0),char(4),char(0),char(85),char(0),char(7),char(0),char(86),char(0),char(7),char(0),char(87),char(0),
+char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),char(7),char(0),char(90),char(0),char(4),char(0),char(91),char(0),char(4),char(0),char(92),char(0),
+char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),char(0),char(0),char(37),char(0),char(44),char(0),char(5),char(0),char(25),char(0),char(38),char(0),
+char(35),char(0),char(65),char(0),char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(95),char(0),char(45),char(0),char(5),char(0),
+char(27),char(0),char(47),char(0),char(13),char(0),char(96),char(0),char(14),char(0),char(97),char(0),char(4),char(0),char(98),char(0),char(0),char(0),char(99),char(0),
+char(46),char(0),char(25),char(0),char(9),char(0),char(100),char(0),char(9),char(0),char(101),char(0),char(25),char(0),char(102),char(0),char(0),char(0),char(35),char(0),
+char(18),char(0),char(103),char(0),char(18),char(0),char(104),char(0),char(14),char(0),char(105),char(0),char(14),char(0),char(106),char(0),char(14),char(0),char(107),char(0),
+char(8),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(8),char(0),char(110),char(0),char(8),char(0),char(111),char(0),char(8),char(0),char(112),char(0),
+char(8),char(0),char(113),char(0),char(8),char(0),char(114),char(0),char(8),char(0),char(115),char(0),char(4),char(0),char(116),char(0),char(4),char(0),char(117),char(0),
+char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0),char(4),char(0),char(122),char(0),
+char(0),char(0),char(37),char(0),char(47),char(0),char(25),char(0),char(9),char(0),char(100),char(0),char(9),char(0),char(101),char(0),char(25),char(0),char(102),char(0),
+char(0),char(0),char(35),char(0),char(17),char(0),char(103),char(0),char(17),char(0),char(104),char(0),char(13),char(0),char(105),char(0),char(13),char(0),char(106),char(0),
+char(13),char(0),char(107),char(0),char(7),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(7),char(0),char(110),char(0),char(7),char(0),char(111),char(0),
+char(7),char(0),char(112),char(0),char(7),char(0),char(113),char(0),char(7),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(4),char(0),char(116),char(0),
+char(4),char(0),char(117),char(0),char(4),char(0),char(118),char(0),char(4),char(0),char(119),char(0),char(4),char(0),char(120),char(0),char(4),char(0),char(121),char(0),
+char(4),char(0),char(122),char(0),char(0),char(0),char(37),char(0),char(48),char(0),char(2),char(0),char(49),char(0),char(123),char(0),char(14),char(0),char(124),char(0),
+char(50),char(0),char(2),char(0),char(51),char(0),char(123),char(0),char(13),char(0),char(124),char(0),char(52),char(0),char(21),char(0),char(47),char(0),char(125),char(0),
+char(15),char(0),char(126),char(0),char(13),char(0),char(127),char(0),char(13),char(0),char(-128),char(0),char(13),char(0),char(-127),char(0),char(13),char(0),char(-126),char(0),
+char(13),char(0),char(124),char(0),char(13),char(0),char(-125),char(0),char(13),char(0),char(-124),char(0),char(13),char(0),char(-123),char(0),char(13),char(0),char(-122),char(0),
+char(7),char(0),char(-121),char(0),char(7),char(0),char(-120),char(0),char(7),char(0),char(-119),char(0),char(7),char(0),char(-118),char(0),char(7),char(0),char(-117),char(0),
+char(7),char(0),char(-116),char(0),char(7),char(0),char(-115),char(0),char(7),char(0),char(-114),char(0),char(7),char(0),char(-113),char(0),char(4),char(0),char(-112),char(0),
+char(53),char(0),char(22),char(0),char(46),char(0),char(125),char(0),char(16),char(0),char(126),char(0),char(14),char(0),char(127),char(0),char(14),char(0),char(-128),char(0),
+char(14),char(0),char(-127),char(0),char(14),char(0),char(-126),char(0),char(14),char(0),char(124),char(0),char(14),char(0),char(-125),char(0),char(14),char(0),char(-124),char(0),
+char(14),char(0),char(-123),char(0),char(14),char(0),char(-122),char(0),char(8),char(0),char(-121),char(0),char(8),char(0),char(-120),char(0),char(8),char(0),char(-119),char(0),
+char(8),char(0),char(-118),char(0),char(8),char(0),char(-117),char(0),char(8),char(0),char(-116),char(0),char(8),char(0),char(-115),char(0),char(8),char(0),char(-114),char(0),
+char(8),char(0),char(-113),char(0),char(4),char(0),char(-112),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(2),char(0),char(4),char(0),char(-111),char(0),
+char(4),char(0),char(-110),char(0),char(55),char(0),char(13),char(0),char(56),char(0),char(-109),char(0),char(56),char(0),char(-108),char(0),char(0),char(0),char(35),char(0),
+char(4),char(0),char(-107),char(0),char(4),char(0),char(-106),char(0),char(4),char(0),char(-105),char(0),char(4),char(0),char(-104),char(0),char(7),char(0),char(-103),char(0),
+char(7),char(0),char(-102),char(0),char(4),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),char(7),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),
+char(57),char(0),char(3),char(0),char(55),char(0),char(-97),char(0),char(13),char(0),char(-96),char(0),char(13),char(0),char(-95),char(0),char(58),char(0),char(3),char(0),
+char(55),char(0),char(-97),char(0),char(14),char(0),char(-96),char(0),char(14),char(0),char(-95),char(0),char(59),char(0),char(13),char(0),char(55),char(0),char(-97),char(0),
+char(18),char(0),char(-94),char(0),char(18),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),
+char(7),char(0),char(-89),char(0),char(7),char(0),char(-88),char(0),char(7),char(0),char(-87),char(0),char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),
+char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0),char(60),char(0),char(13),char(0),char(55),char(0),char(-97),char(0),char(17),char(0),char(-94),char(0),
+char(17),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(4),char(0),char(-90),char(0),char(7),char(0),char(-89),char(0),
+char(7),char(0),char(-88),char(0),char(7),char(0),char(-87),char(0),char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),
+char(7),char(0),char(-83),char(0),char(61),char(0),char(11),char(0),char(55),char(0),char(-97),char(0),char(17),char(0),char(-94),char(0),char(17),char(0),char(-93),char(0),
+char(7),char(0),char(-82),char(0),char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),
+char(7),char(0),char(-83),char(0),char(7),char(0),char(-79),char(0),char(0),char(0),char(21),char(0),char(62),char(0),char(9),char(0),char(55),char(0),char(-97),char(0),
+char(17),char(0),char(-94),char(0),char(17),char(0),char(-93),char(0),char(13),char(0),char(-78),char(0),char(13),char(0),char(-77),char(0),char(13),char(0),char(-76),char(0),
+char(13),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(63),char(0),char(5),char(0),char(62),char(0),char(-72),char(0),
+char(4),char(0),char(-71),char(0),char(7),char(0),char(-70),char(0),char(7),char(0),char(-69),char(0),char(7),char(0),char(-68),char(0),char(64),char(0),char(9),char(0),
+char(55),char(0),char(-97),char(0),char(17),char(0),char(-94),char(0),char(17),char(0),char(-93),char(0),char(7),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),
+char(7),char(0),char(-76),char(0),char(7),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(49),char(0),char(22),char(0),
+char(8),char(0),char(-67),char(0),char(8),char(0),char(-79),char(0),char(8),char(0),char(110),char(0),char(8),char(0),char(-66),char(0),char(8),char(0),char(112),char(0),
+char(8),char(0),char(-65),char(0),char(8),char(0),char(-64),char(0),char(8),char(0),char(-63),char(0),char(8),char(0),char(-62),char(0),char(8),char(0),char(-61),char(0),
+char(8),char(0),char(-60),char(0),char(8),char(0),char(-59),char(0),char(8),char(0),char(-58),char(0),char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),
+char(8),char(0),char(-55),char(0),char(4),char(0),char(-54),char(0),char(4),char(0),char(-53),char(0),char(4),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),
+char(4),char(0),char(-50),char(0),char(0),char(0),char(37),char(0),char(51),char(0),char(22),char(0),char(7),char(0),char(-67),char(0),char(7),char(0),char(-79),char(0),
+char(7),char(0),char(110),char(0),char(7),char(0),char(-66),char(0),char(7),char(0),char(112),char(0),char(7),char(0),char(-65),char(0),char(7),char(0),char(-64),char(0),
+char(7),char(0),char(-63),char(0),char(7),char(0),char(-62),char(0),char(7),char(0),char(-61),char(0),char(7),char(0),char(-60),char(0),char(7),char(0),char(-59),char(0),
+char(7),char(0),char(-58),char(0),char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0),char(7),char(0),char(-55),char(0),char(4),char(0),char(-54),char(0),
+char(4),char(0),char(-53),char(0),char(4),char(0),char(-52),char(0),char(4),char(0),char(-51),char(0),char(4),char(0),char(-50),char(0),char(0),char(0),char(37),char(0),
+char(65),char(0),char(4),char(0),char(7),char(0),char(-49),char(0),char(7),char(0),char(-48),char(0),char(7),char(0),char(-47),char(0),char(4),char(0),char(78),char(0),
+char(66),char(0),char(10),char(0),char(65),char(0),char(-46),char(0),char(13),char(0),char(-45),char(0),char(13),char(0),char(-44),char(0),char(13),char(0),char(-43),char(0),
+char(13),char(0),char(-42),char(0),char(13),char(0),char(-41),char(0),char(7),char(0),char(-121),char(0),char(7),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),
+char(4),char(0),char(53),char(0),char(67),char(0),char(4),char(0),char(65),char(0),char(-46),char(0),char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),
+char(4),char(0),char(-36),char(0),char(68),char(0),char(4),char(0),char(13),char(0),char(-41),char(0),char(65),char(0),char(-46),char(0),char(4),char(0),char(-35),char(0),
+char(7),char(0),char(-34),char(0),char(69),char(0),char(7),char(0),char(13),char(0),char(-33),char(0),char(65),char(0),char(-46),char(0),char(4),char(0),char(-32),char(0),
+char(7),char(0),char(-31),char(0),char(7),char(0),char(-30),char(0),char(7),char(0),char(-29),char(0),char(4),char(0),char(53),char(0),char(70),char(0),char(6),char(0),
+char(15),char(0),char(-28),char(0),char(13),char(0),char(-30),char(0),char(13),char(0),char(-27),char(0),char(56),char(0),char(-26),char(0),char(4),char(0),char(-25),char(0),
+char(7),char(0),char(-29),char(0),char(71),char(0),char(26),char(0),char(4),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),char(7),char(0),char(-79),char(0),
+char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(7),char(0),char(-19),char(0),char(7),char(0),char(-18),char(0),
+char(7),char(0),char(-17),char(0),char(7),char(0),char(-16),char(0),char(7),char(0),char(-15),char(0),char(7),char(0),char(-14),char(0),char(7),char(0),char(-13),char(0),
+char(7),char(0),char(-12),char(0),char(7),char(0),char(-11),char(0),char(7),char(0),char(-10),char(0),char(7),char(0),char(-9),char(0),char(7),char(0),char(-8),char(0),
+char(7),char(0),char(-7),char(0),char(7),char(0),char(-6),char(0),char(7),char(0),char(-5),char(0),char(4),char(0),char(-4),char(0),char(4),char(0),char(-3),char(0),
+char(4),char(0),char(-2),char(0),char(4),char(0),char(-1),char(0),char(4),char(0),char(117),char(0),char(72),char(0),char(12),char(0),char(15),char(0),char(0),char(1),
+char(15),char(0),char(1),char(1),char(15),char(0),char(2),char(1),char(13),char(0),char(3),char(1),char(13),char(0),char(4),char(1),char(7),char(0),char(5),char(1),
+char(4),char(0),char(6),char(1),char(4),char(0),char(7),char(1),char(4),char(0),char(8),char(1),char(4),char(0),char(9),char(1),char(7),char(0),char(-31),char(0),
+char(4),char(0),char(53),char(0),char(73),char(0),char(27),char(0),char(17),char(0),char(10),char(1),char(15),char(0),char(11),char(1),char(15),char(0),char(12),char(1),
+char(13),char(0),char(3),char(1),char(13),char(0),char(13),char(1),char(13),char(0),char(14),char(1),char(13),char(0),char(15),char(1),char(13),char(0),char(16),char(1),
+char(13),char(0),char(17),char(1),char(4),char(0),char(18),char(1),char(7),char(0),char(19),char(1),char(4),char(0),char(20),char(1),char(4),char(0),char(21),char(1),
+char(4),char(0),char(22),char(1),char(7),char(0),char(23),char(1),char(7),char(0),char(24),char(1),char(4),char(0),char(25),char(1),char(4),char(0),char(26),char(1),
+char(7),char(0),char(27),char(1),char(7),char(0),char(28),char(1),char(7),char(0),char(29),char(1),char(7),char(0),char(30),char(1),char(7),char(0),char(31),char(1),
+char(7),char(0),char(32),char(1),char(4),char(0),char(33),char(1),char(4),char(0),char(34),char(1),char(4),char(0),char(35),char(1),char(74),char(0),char(12),char(0),
+char(9),char(0),char(36),char(1),char(9),char(0),char(37),char(1),char(13),char(0),char(38),char(1),char(7),char(0),char(39),char(1),char(7),char(0),char(-63),char(0),
+char(7),char(0),char(40),char(1),char(4),char(0),char(41),char(1),char(13),char(0),char(42),char(1),char(4),char(0),char(43),char(1),char(4),char(0),char(44),char(1),
+char(4),char(0),char(45),char(1),char(4),char(0),char(53),char(0),char(75),char(0),char(19),char(0),char(47),char(0),char(125),char(0),char(72),char(0),char(46),char(1),
+char(65),char(0),char(47),char(1),char(66),char(0),char(48),char(1),char(67),char(0),char(49),char(1),char(68),char(0),char(50),char(1),char(69),char(0),char(51),char(1),
+char(70),char(0),char(52),char(1),char(73),char(0),char(53),char(1),char(74),char(0),char(54),char(1),char(4),char(0),char(55),char(1),char(4),char(0),char(21),char(1),
+char(4),char(0),char(56),char(1),char(4),char(0),char(57),char(1),char(4),char(0),char(58),char(1),char(4),char(0),char(59),char(1),char(4),char(0),char(60),char(1),
+char(4),char(0),char(61),char(1),char(71),char(0),char(62),char(1),};
int sBulletDNAlen64= sizeof(sBulletDNAstr64);
diff --git a/extern/bullet2/src/LinearMath/btSerializer.h b/extern/bullet2/src/LinearMath/btSerializer.h
index 76f3cf32f8e..c5bc96b7839 100644
--- a/extern/bullet2/src/LinearMath/btSerializer.h
+++ b/extern/bullet2/src/LinearMath/btSerializer.h
@@ -122,6 +122,7 @@ public:
#define BT_ARRAY_CODE BT_MAKE_ID('A','R','A','Y')
#define BT_SBMATERIAL_CODE BT_MAKE_ID('S','B','M','T')
#define BT_SBNODE_CODE BT_MAKE_ID('S','B','N','D')
+#define BT_DYNAMICSWORLD_CODE BT_MAKE_ID('D','W','L','D')
#define BT_DNA_CODE BT_MAKE_ID('D','N','A','1')
@@ -256,7 +257,7 @@ protected:
*/
intPtr = (int*)cp;
- assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
+ btAssert(strncmp(cp, "TYPE", 4)==0); intPtr++;
if (!littleEndian)
*intPtr = btSwapEndian(*intPtr);
@@ -284,7 +285,7 @@ protected:
// Parse type lens
intPtr = (int*)cp;
- assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
+ btAssert(strncmp(cp, "TLEN", 4)==0); intPtr++;
dataLen = (int)mTypes.size();
@@ -311,7 +312,7 @@ protected:
intPtr = (int*)shtPtr;
cp = (char*)intPtr;
- assert(strncmp(cp, "STRC", 4)==0); intPtr++;
+ btAssert(strncmp(cp, "STRC", 4)==0); intPtr++;
if (!littleEndian)
*intPtr = btSwapEndian(*intPtr);
@@ -438,7 +439,7 @@ public:
buffer[9] = '2';
buffer[10] = '8';
- buffer[11] = '0';
+ buffer[11] = '1';
}
diff --git a/extern/bullet2/src/LinearMath/btTransform.h b/extern/bullet2/src/LinearMath/btTransform.h
index 5e52d183acb..907627379bf 100644
--- a/extern/bullet2/src/LinearMath/btTransform.h
+++ b/extern/bullet2/src/LinearMath/btTransform.h
@@ -31,7 +31,7 @@ subject to the following restrictions:
/**@brief The btTransform class supports rigid transforms with only translation and rotation and no scaling/shear.
*It can be used in combination with btVector3, btQuaternion and btMatrix3x3 linear algebra classes. */
-class btTransform {
+ATTRIBUTE_ALIGNED16(class) btTransform {
///Storage for the rotation
btMatrix3x3 m_basis;
@@ -93,9 +93,7 @@ public:
/**@brief Return the transform of the vector */
SIMD_FORCE_INLINE btVector3 operator()(const btVector3& x) const
{
- return btVector3(m_basis[0].dot(x) + m_origin.x(),
- m_basis[1].dot(x) + m_origin.y(),
- m_basis[2].dot(x) + m_origin.z());
+ return x.dot3(m_basis[0], m_basis[1], m_basis[2]) + m_origin;
}
/**@brief Return the transform of the vector */
diff --git a/extern/bullet2/src/LinearMath/btVector3.cpp b/extern/bullet2/src/LinearMath/btVector3.cpp
new file mode 100644
index 00000000000..1c26e523d80
--- /dev/null
+++ b/extern/bullet2/src/LinearMath/btVector3.cpp
@@ -0,0 +1,1639 @@
+/*
+ Copyright (c) 2011 Apple Inc.
+ http://continuousphysics.com/Bullet/
+
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it freely,
+ subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ This source version has been altered.
+ */
+
+#if defined (_WIN32) || defined (__i386__)
+#define BT_USE_SSE_IN_API
+#endif
+
+
+#include "btVector3.h"
+
+
+
+#if defined BT_USE_SIMD_VECTOR3
+
+#if DEBUG
+#include <string.h>//for memset
+#endif
+
+
+#ifdef __APPLE__
+#include <stdint.h>
+typedef float float4 __attribute__ ((vector_size(16)));
+#else
+#define float4 __m128
+#endif
+//typedef uint32_t uint4 __attribute__ ((vector_size(16)));
+
+
+#if defined BT_USE_SSE || defined _WIN32
+
+#define LOG2_ARRAY_SIZE 6
+#define STACK_ARRAY_COUNT (1UL << LOG2_ARRAY_SIZE)
+
+#include <emmintrin.h>
+
+long _maxdot_large( const float *vv, const float *vec, unsigned long count, float *dotResult );
+long _maxdot_large( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ const float4 *vertices = (const float4*) vv;
+ static const unsigned char indexTable[16] = {-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
+ float4 dotMax = btAssign128( -BT_INFINITY, -BT_INFINITY, -BT_INFINITY, -BT_INFINITY );
+ float4 vvec = _mm_loadu_ps( vec );
+ float4 vHi = btCastiTo128f(_mm_shuffle_epi32( btCastfTo128i( vvec), 0xaa )); /// zzzz
+ float4 vLo = _mm_movelh_ps( vvec, vvec ); /// xyxy
+
+ long maxIndex = -1L;
+
+ size_t segment = 0;
+ float4 stack_array[ STACK_ARRAY_COUNT ];
+
+#if DEBUG
+ memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
+#endif
+
+ size_t index;
+ float4 max;
+ // Faster loop without cleanup code for full tiles
+ for ( segment = 0; segment + STACK_ARRAY_COUNT*4 <= count; segment += STACK_ARRAY_COUNT*4 )
+ {
+ max = dotMax;
+
+ for( index = 0; index < STACK_ARRAY_COUNT; index+= 4 )
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3]; vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+1] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+2] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+3] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way.
+ }
+
+ // If we found a new max
+ if( 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(max, dotMax)))
+ {
+ // copy the new max across all lanes of our max accumulator
+ max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0x4e));
+ max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0xb1));
+
+ dotMax = max;
+
+ // find first occurrence of that max
+ size_t test;
+ for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], max))); index++ ) // local_count must be a multiple of 4
+ {}
+ // record where it is.
+ maxIndex = 4*index + segment + indexTable[test];
+ }
+ }
+
+ // account for work we've already done
+ count -= segment;
+
+ // Deal with the last < STACK_ARRAY_COUNT vectors
+ max = dotMax;
+ index = 0;
+
+
+ if( btUnlikely( count > 16) )
+ {
+ for( ; index + 4 <= count / 4; index+=4 )
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3]; vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+1] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+2] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+3] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+
+ // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way.
+ }
+ }
+
+ size_t localCount = (count & -4L) - 4*index;
+ if( localCount )
+ {
+#ifdef __APPLE__
+ float4 t0, t1, t2, t3, t4;
+ float4 * sap = &stack_array[index + localCount / 4];
+ vertices += localCount; // counter the offset
+ size_t byteIndex = -(localCount) * sizeof(float);
+ //AT&T Code style assembly
+ asm volatile
+ ( ".align 4 \n\
+ 0: movaps %[max], %[t2] // move max out of the way to avoid propagating NaNs in max \n\
+ movaps (%[vertices], %[byteIndex], 4), %[t0] // vertices[0] \n\
+ movaps 16(%[vertices], %[byteIndex], 4), %[t1] // vertices[1] \n\
+ movaps %[t0], %[max] // vertices[0] \n\
+ movlhps %[t1], %[max] // x0y0x1y1 \n\
+ movaps 32(%[vertices], %[byteIndex], 4), %[t3] // vertices[2] \n\
+ movaps 48(%[vertices], %[byteIndex], 4), %[t4] // vertices[3] \n\
+ mulps %[vLo], %[max] // x0y0x1y1 * vLo \n\
+ movhlps %[t0], %[t1] // z0w0z1w1 \n\
+ movaps %[t3], %[t0] // vertices[2] \n\
+ movlhps %[t4], %[t0] // x2y2x3y3 \n\
+ mulps %[vLo], %[t0] // x2y2x3y3 * vLo \n\
+ movhlps %[t3], %[t4] // z2w2z3w3 \n\
+ shufps $0x88, %[t4], %[t1] // z0z1z2z3 \n\
+ mulps %[vHi], %[t1] // z0z1z2z3 * vHi \n\
+ movaps %[max], %[t3] // x0y0x1y1 * vLo \n\
+ shufps $0x88, %[t0], %[max] // x0x1x2x3 * vLo.x \n\
+ shufps $0xdd, %[t0], %[t3] // y0y1y2y3 * vLo.y \n\
+ addps %[t3], %[max] // x + y \n\
+ addps %[t1], %[max] // x + y + z \n\
+ movaps %[max], (%[sap], %[byteIndex]) // record result for later scrutiny \n\
+ maxps %[t2], %[max] // record max, restore max \n\
+ add $16, %[byteIndex] // advance loop counter\n\
+ jnz 0b \n\
+ "
+ : [max] "+x" (max), [t0] "=&x" (t0), [t1] "=&x" (t1), [t2] "=&x" (t2), [t3] "=&x" (t3), [t4] "=&x" (t4), [byteIndex] "+r" (byteIndex)
+ : [vLo] "x" (vLo), [vHi] "x" (vHi), [vertices] "r" (vertices), [sap] "r" (sap)
+ : "memory", "cc"
+ );
+ index += localCount/4;
+#else
+ {
+ for( unsigned int i=0; i<localCount/4; i++,index++)
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3];
+ vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+ }
+ }
+#endif //__APPLE__
+ }
+
+ // process the last few points
+ if( count & 3 )
+ {
+ float4 v0, v1, v2, x, y, z;
+ switch( count & 3 )
+ {
+ case 3:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+
+ // Calculate 3 dot products, transpose, duplicate v2
+ float4 lo0 = _mm_movelh_ps( v0, v1); // xyxy.lo
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z?z?.lo
+ lo0 = lo0*vLo;
+ z = _mm_shuffle_ps(hi0, v2, 0xa8 ); // z0z1z2z2
+ z = z*vHi;
+ float4 lo1 = _mm_movelh_ps(v2, v2); // xyxy
+ lo1 = lo1*vLo;
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ }
+ break;
+ case 2:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ float4 xy = _mm_movelh_ps(v0, v1);
+ z = _mm_movehl_ps(v1, v0);
+ xy = xy*vLo;
+ z = _mm_shuffle_ps( z, z, 0xa8);
+ x = _mm_shuffle_ps( xy, xy, 0xa8);
+ y = _mm_shuffle_ps( xy, xy, 0xfd);
+ z = z*vHi;
+ }
+ break;
+ case 1:
+ {
+ float4 xy = vertices[0];
+ z = _mm_shuffle_ps( xy, xy, 0xaa);
+ xy = xy*vLo;
+ z = z*vHi;
+ x = _mm_shuffle_ps(xy, xy, 0);
+ y = _mm_shuffle_ps(xy, xy, 0x55);
+ }
+ break;
+ }
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ max = _mm_max_ps( x, max ); // control the order here so that max is never NaN even if x is nan
+ index++;
+ }
+
+ // if we found a new max.
+ if( 0 == segment || 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(max, dotMax)))
+ { // we found a new max. Search for it
+ // find max across the max vector, place in all elements of max -- big latency hit here
+ max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0x4e));
+ max = _mm_max_ps(max, (float4) _mm_shuffle_ps( max, max, 0xb1));
+
+ // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
+ // this where it actually makes a difference is handled in the early out at the top of the function,
+ // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
+ // complexity, and removed it.
+
+ dotMax = max;
+
+ // scan for the first occurence of max in the array
+ size_t test;
+ for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], max))); index++ ) // local_count must be a multiple of 4
+ {}
+ maxIndex = 4*index + segment + indexTable[test];
+ }
+
+ _mm_store_ss( dotResult, dotMax);
+ return maxIndex;
+}
+
+long _mindot_large( const float *vv, const float *vec, unsigned long count, float *dotResult );
+
+long _mindot_large( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ const float4 *vertices = (const float4*) vv;
+ static const unsigned char indexTable[16] = {-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
+ float4 dotmin = btAssign128( BT_INFINITY, BT_INFINITY, BT_INFINITY, BT_INFINITY );
+ float4 vvec = _mm_loadu_ps( vec );
+ float4 vHi = btCastiTo128f(_mm_shuffle_epi32( btCastfTo128i( vvec), 0xaa )); /// zzzz
+ float4 vLo = _mm_movelh_ps( vvec, vvec ); /// xyxy
+
+ long minIndex = -1L;
+
+ size_t segment = 0;
+ float4 stack_array[ STACK_ARRAY_COUNT ];
+
+#if DEBUG
+ memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
+#endif
+
+ size_t index;
+ float4 min;
+ // Faster loop without cleanup code for full tiles
+ for ( segment = 0; segment + STACK_ARRAY_COUNT*4 <= count; segment += STACK_ARRAY_COUNT*4 )
+ {
+ min = dotmin;
+
+ for( index = 0; index < STACK_ARRAY_COUNT; index+= 4 )
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3]; vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+1] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+2] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+3] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way.
+ }
+
+ // If we found a new min
+ if( 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(min, dotmin)))
+ {
+ // copy the new min across all lanes of our min accumulator
+ min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0x4e));
+ min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0xb1));
+
+ dotmin = min;
+
+ // find first occurrence of that min
+ size_t test;
+ for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], min))); index++ ) // local_count must be a multiple of 4
+ {}
+ // record where it is.
+ minIndex = 4*index + segment + indexTable[test];
+ }
+ }
+
+ // account for work we've already done
+ count -= segment;
+
+ // Deal with the last < STACK_ARRAY_COUNT vectors
+ min = dotmin;
+ index = 0;
+
+
+ if(btUnlikely( count > 16) )
+ {
+ for( ; index + 4 <= count / 4; index+=4 )
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3]; vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+1] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+2] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+ v3 = vertices[3]; vertices += 4;
+
+ lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index+3] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+
+ // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way.
+ }
+ }
+
+ size_t localCount = (count & -4L) - 4*index;
+ if( localCount )
+ {
+
+
+#ifdef __APPLE__
+ vertices += localCount; // counter the offset
+ float4 t0, t1, t2, t3, t4;
+ size_t byteIndex = -(localCount) * sizeof(float);
+ float4 * sap = &stack_array[index + localCount / 4];
+
+ asm volatile
+ ( ".align 4 \n\
+ 0: movaps %[min], %[t2] // move min out of the way to avoid propagating NaNs in min \n\
+ movaps (%[vertices], %[byteIndex], 4), %[t0] // vertices[0] \n\
+ movaps 16(%[vertices], %[byteIndex], 4), %[t1] // vertices[1] \n\
+ movaps %[t0], %[min] // vertices[0] \n\
+ movlhps %[t1], %[min] // x0y0x1y1 \n\
+ movaps 32(%[vertices], %[byteIndex], 4), %[t3] // vertices[2] \n\
+ movaps 48(%[vertices], %[byteIndex], 4), %[t4] // vertices[3] \n\
+ mulps %[vLo], %[min] // x0y0x1y1 * vLo \n\
+ movhlps %[t0], %[t1] // z0w0z1w1 \n\
+ movaps %[t3], %[t0] // vertices[2] \n\
+ movlhps %[t4], %[t0] // x2y2x3y3 \n\
+ movhlps %[t3], %[t4] // z2w2z3w3 \n\
+ mulps %[vLo], %[t0] // x2y2x3y3 * vLo \n\
+ shufps $0x88, %[t4], %[t1] // z0z1z2z3 \n\
+ mulps %[vHi], %[t1] // z0z1z2z3 * vHi \n\
+ movaps %[min], %[t3] // x0y0x1y1 * vLo \n\
+ shufps $0x88, %[t0], %[min] // x0x1x2x3 * vLo.x \n\
+ shufps $0xdd, %[t0], %[t3] // y0y1y2y3 * vLo.y \n\
+ addps %[t3], %[min] // x + y \n\
+ addps %[t1], %[min] // x + y + z \n\
+ movaps %[min], (%[sap], %[byteIndex]) // record result for later scrutiny \n\
+ minps %[t2], %[min] // record min, restore min \n\
+ add $16, %[byteIndex] // advance loop counter\n\
+ jnz 0b \n\
+ "
+ : [min] "+x" (min), [t0] "=&x" (t0), [t1] "=&x" (t1), [t2] "=&x" (t2), [t3] "=&x" (t3), [t4] "=&x" (t4), [byteIndex] "+r" (byteIndex)
+ : [vLo] "x" (vLo), [vHi] "x" (vHi), [vertices] "r" (vertices), [sap] "r" (sap)
+ : "memory", "cc"
+ );
+ index += localCount/4;
+#else
+ {
+ for( unsigned int i=0; i<localCount/4; i++,index++)
+ { // do four dot products at a time. Carefully avoid touching the w element.
+ float4 v0 = vertices[0];
+ float4 v1 = vertices[1];
+ float4 v2 = vertices[2];
+ float4 v3 = vertices[3];
+ vertices += 4;
+
+ float4 lo0 = _mm_movelh_ps( v0, v1); // x0y0x1y1
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z0?0z1?1
+ float4 lo1 = _mm_movelh_ps( v2, v3); // x2y2x3y3
+ float4 hi1 = _mm_movehl_ps( v3, v2); // z2?2z3?3
+
+ lo0 = lo0*vLo;
+ lo1 = lo1*vLo;
+ float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
+ float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ z = z*vHi;
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that max is never NaN even if x is nan
+ }
+ }
+
+#endif
+ }
+
+ // process the last few points
+ if( count & 3 )
+ {
+ float4 v0, v1, v2, x, y, z;
+ switch( count & 3 )
+ {
+ case 3:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ v2 = vertices[2];
+
+ // Calculate 3 dot products, transpose, duplicate v2
+ float4 lo0 = _mm_movelh_ps( v0, v1); // xyxy.lo
+ float4 hi0 = _mm_movehl_ps( v1, v0); // z?z?.lo
+ lo0 = lo0*vLo;
+ z = _mm_shuffle_ps(hi0, v2, 0xa8 ); // z0z1z2z2
+ z = z*vHi;
+ float4 lo1 = _mm_movelh_ps(v2, v2); // xyxy
+ lo1 = lo1*vLo;
+ x = _mm_shuffle_ps(lo0, lo1, 0x88);
+ y = _mm_shuffle_ps(lo0, lo1, 0xdd);
+ }
+ break;
+ case 2:
+ {
+ v0 = vertices[0];
+ v1 = vertices[1];
+ float4 xy = _mm_movelh_ps(v0, v1);
+ z = _mm_movehl_ps(v1, v0);
+ xy = xy*vLo;
+ z = _mm_shuffle_ps( z, z, 0xa8);
+ x = _mm_shuffle_ps( xy, xy, 0xa8);
+ y = _mm_shuffle_ps( xy, xy, 0xfd);
+ z = z*vHi;
+ }
+ break;
+ case 1:
+ {
+ float4 xy = vertices[0];
+ z = _mm_shuffle_ps( xy, xy, 0xaa);
+ xy = xy*vLo;
+ z = z*vHi;
+ x = _mm_shuffle_ps(xy, xy, 0);
+ y = _mm_shuffle_ps(xy, xy, 0x55);
+ }
+ break;
+ }
+ x = x+y;
+ x = x+z;
+ stack_array[index] = x;
+ min = _mm_min_ps( x, min ); // control the order here so that min is never NaN even if x is nan
+ index++;
+ }
+
+ // if we found a new min.
+ if( 0 == segment || 0xf != _mm_movemask_ps( (float4) _mm_cmpeq_ps(min, dotmin)))
+ { // we found a new min. Search for it
+ // find min across the min vector, place in all elements of min -- big latency hit here
+ min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0x4e));
+ min = _mm_min_ps(min, (float4) _mm_shuffle_ps( min, min, 0xb1));
+
+ // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
+ // this where it actually makes a difference is handled in the early out at the top of the function,
+ // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
+ // complexity, and removed it.
+
+ dotmin = min;
+
+ // scan for the first occurence of min in the array
+ size_t test;
+ for( index = 0; 0 == (test=_mm_movemask_ps( _mm_cmpeq_ps( stack_array[index], min))); index++ ) // local_count must be a multiple of 4
+ {}
+ minIndex = 4*index + segment + indexTable[test];
+ }
+
+ _mm_store_ss( dotResult, dotmin);
+ return minIndex;
+}
+
+
+#elif defined BT_USE_NEON
+#define ARM_NEON_GCC_COMPATIBILITY 1
+#include <arm_neon.h>
+
+
+static long _maxdot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult );
+static long _maxdot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult );
+static long _maxdot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult );
+static long _mindot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult );
+static long _mindot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult );
+static long _mindot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult );
+
+long (*_maxdot_large)( const float *vv, const float *vec, unsigned long count, float *dotResult ) = _maxdot_large_sel;
+long (*_mindot_large)( const float *vv, const float *vec, unsigned long count, float *dotResult ) = _mindot_large_sel;
+
+extern "C" {int _get_cpu_capabilities( void );}
+
+static long _maxdot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ if( _get_cpu_capabilities() & 0x2000 )
+ _maxdot_large = _maxdot_large_v1;
+ else
+ _maxdot_large = _maxdot_large_v0;
+
+ return _maxdot_large(vv, vec, count, dotResult);
+}
+
+static long _mindot_large_sel( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ if( _get_cpu_capabilities() & 0x2000 )
+ _mindot_large = _mindot_large_v1;
+ else
+ _mindot_large = _mindot_large_v0;
+
+ return _mindot_large(vv, vec, count, dotResult);
+}
+
+
+
+#define vld1q_f32_aligned_postincrement( _ptr ) ({ float32x4_t _r; asm( "vld1.f32 {%0}, [%1, :128]!\n" : "=w" (_r), "+r" (_ptr) ); /*return*/ _r; })
+
+
+long _maxdot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ unsigned long i = 0;
+ float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
+ float32x2_t vLo = vget_low_f32(vvec);
+ float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
+ float32x2_t dotMaxLo = (float32x2_t) { -BT_INFINITY, -BT_INFINITY };
+ float32x2_t dotMaxHi = (float32x2_t) { -BT_INFINITY, -BT_INFINITY };
+ uint32x2_t indexLo = (uint32x2_t) {0, 1};
+ uint32x2_t indexHi = (uint32x2_t) {2, 3};
+ uint32x2_t iLo = (uint32x2_t) {-1, -1};
+ uint32x2_t iHi = (uint32x2_t) {-1, -1};
+ const uint32x2_t four = (uint32x2_t) {4,4};
+
+ for( ; i+8 <= count; i+= 8 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32( z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ float32x2_t rHi = vpadd_f32( xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
+ uint32x2_t maskHi = vcgt_f32( rHi, dotMaxHi );
+ dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+
+ v0 = vld1q_f32_aligned_postincrement( vv );
+ v1 = vld1q_f32_aligned_postincrement( vv );
+ v2 = vld1q_f32_aligned_postincrement( vv );
+ v3 = vld1q_f32_aligned_postincrement( vv );
+
+ xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ xy2 = vmul_f32( vget_low_f32(v2), vLo);
+ xy3 = vmul_f32( vget_low_f32(v3), vLo);
+
+ z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
+ zLo = vmul_f32( z0.val[0], vHi);
+ zHi = vmul_f32( z1.val[0], vHi);
+
+ rLo = vpadd_f32( xy0, xy1);
+ rHi = vpadd_f32( xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ maskLo = vcgt_f32( rLo, dotMaxLo );
+ maskHi = vcgt_f32( rHi, dotMaxHi );
+ dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+
+ for( ; i+4 <= count; i+= 4 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32( z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ float32x2_t rHi = vpadd_f32( xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
+ uint32x2_t maskHi = vcgt_f32( rHi, dotMaxHi );
+ dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+
+ switch( count & 3 )
+ {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32( vdup_lane_f32(vget_high_f32(v2), 0), vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ float32x2_t rHi = vpadd_f32( xy2, xy2);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
+ uint32x2_t maskHi = vcgt_f32( rHi, dotMaxHi );
+ dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
+ dotMaxHi = vbsl_f32( maskHi, rHi, dotMaxHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ }
+ break;
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ rLo = vadd_f32(rLo, zLo);
+
+ uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
+ dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
+ float32x2_t zLo = vmul_f32( z0, vHi);
+ float32x2_t rLo = vpadd_f32( xy0, xy0);
+ rLo = vadd_f32(rLo, zLo);
+ uint32x2_t maskLo = vcgt_f32( rLo, dotMaxLo );
+ dotMaxLo = vbsl_f32( maskLo, rLo, dotMaxLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vcgt_f32( dotMaxHi, dotMaxLo );
+ dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ // select best answer between even and odd results
+ dotMaxHi = vdup_lane_f32(dotMaxLo, 1);
+ iHi = vdup_lane_u32(iLo, 1);
+ mask = vcgt_f32( dotMaxHi, dotMaxLo );
+ dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ *dotResult = vget_lane_f32( dotMaxLo, 0);
+ return vget_lane_u32(iLo, 0);
+}
+
+
+long _maxdot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
+ float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
+ float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
+ const uint32x4_t four = (uint32x4_t){ 4, 4, 4, 4 };
+ uint32x4_t local_index = (uint32x4_t) {0, 1, 2, 3};
+ uint32x4_t index = (uint32x4_t) { -1, -1, -1, -1 };
+ float32x4_t maxDot = (float32x4_t) { -BT_INFINITY, -BT_INFINITY, -BT_INFINITY, -BT_INFINITY };
+
+ unsigned long i = 0;
+ for( ; i + 8 <= count; i += 8 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z1);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32( mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+
+ v0 = vld1q_f32_aligned_postincrement( vv );
+ v1 = vld1q_f32_aligned_postincrement( vv );
+ v2 = vld1q_f32_aligned_postincrement( vv );
+ v3 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ zb = vuzpq_f32( z0, z1);
+ z = vmulq_f32( zb.val[0], vHi);
+ xy = vuzpq_f32( xy0, xy1);
+ x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32( mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ for( ; i + 4 <= count; i += 4 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z1);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32( mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ switch (count & 3) {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v2));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v2));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z1);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32( mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z0);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32( mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v0));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ z = vmulq_f32( z, vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcgtq_f32(x, maxDot);
+ maxDot = vbslq_f32( mask, x, maxDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vcgt_f32( vget_high_f32(maxDot), vget_low_f32(maxDot));
+ float32x2_t maxDot2 = vbsl_f32(mask, vget_high_f32(maxDot), vget_low_f32(maxDot));
+ uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
+
+ // select best answer between even and odd results
+ float32x2_t maxDotO = vdup_lane_f32(maxDot2, 1);
+ uint32x2_t indexHi = vdup_lane_u32(index2, 1);
+ mask = vcgt_f32( maxDotO, maxDot2 );
+ maxDot2 = vbsl_f32(mask, maxDotO, maxDot2);
+ index2 = vbsl_u32(mask, indexHi, index2);
+
+ *dotResult = vget_lane_f32( maxDot2, 0);
+ return vget_lane_u32(index2, 0);
+
+}
+
+long _mindot_large_v0( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ unsigned long i = 0;
+ float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
+ float32x2_t vLo = vget_low_f32(vvec);
+ float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
+ float32x2_t dotMinLo = (float32x2_t) { BT_INFINITY, BT_INFINITY };
+ float32x2_t dotMinHi = (float32x2_t) { BT_INFINITY, BT_INFINITY };
+ uint32x2_t indexLo = (uint32x2_t) {0, 1};
+ uint32x2_t indexHi = (uint32x2_t) {2, 3};
+ uint32x2_t iLo = (uint32x2_t) {-1, -1};
+ uint32x2_t iHi = (uint32x2_t) {-1, -1};
+ const uint32x2_t four = (uint32x2_t) {4,4};
+
+ for( ; i+8 <= count; i+= 8 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32( z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ float32x2_t rHi = vpadd_f32( xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
+ uint32x2_t maskHi = vclt_f32( rHi, dotMinHi );
+ dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+
+ v0 = vld1q_f32_aligned_postincrement( vv );
+ v1 = vld1q_f32_aligned_postincrement( vv );
+ v2 = vld1q_f32_aligned_postincrement( vv );
+ v3 = vld1q_f32_aligned_postincrement( vv );
+
+ xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ xy2 = vmul_f32( vget_low_f32(v2), vLo);
+ xy3 = vmul_f32( vget_low_f32(v3), vLo);
+
+ z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
+ zLo = vmul_f32( z0.val[0], vHi);
+ zHi = vmul_f32( z1.val[0], vHi);
+
+ rLo = vpadd_f32( xy0, xy1);
+ rHi = vpadd_f32( xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ maskLo = vclt_f32( rLo, dotMinLo );
+ maskHi = vclt_f32( rHi, dotMinHi );
+ dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+
+ for( ; i+4 <= count; i+= 4 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
+ float32x2_t xy3 = vmul_f32( vget_low_f32(v3), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2x2_t z1 = vtrn_f32( vget_high_f32(v2), vget_high_f32(v3));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32( z1.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ float32x2_t rHi = vpadd_f32( xy2, xy3);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
+ uint32x2_t maskHi = vclt_f32( rHi, dotMinHi );
+ dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ indexLo = vadd_u32(indexLo, four);
+ indexHi = vadd_u32(indexHi, four);
+ }
+ switch( count & 3 )
+ {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+ float32x2_t xy2 = vmul_f32( vget_low_f32(v2), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+ float32x2_t zHi = vmul_f32( vdup_lane_f32(vget_high_f32(v2), 0), vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ float32x2_t rHi = vpadd_f32( xy2, xy2);
+ rLo = vadd_f32(rLo, zLo);
+ rHi = vadd_f32(rHi, zHi);
+
+ uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
+ uint32x2_t maskHi = vclt_f32( rHi, dotMinHi );
+ dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
+ dotMinHi = vbsl_f32( maskHi, rHi, dotMinHi);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ iHi = vbsl_u32(maskHi, indexHi, iHi);
+ }
+ break;
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t xy1 = vmul_f32( vget_low_f32(v1), vLo);
+
+ float32x2x2_t z0 = vtrn_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x2_t zLo = vmul_f32( z0.val[0], vHi);
+
+ float32x2_t rLo = vpadd_f32( xy0, xy1);
+ rLo = vadd_f32(rLo, zLo);
+
+ uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
+ dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x2_t xy0 = vmul_f32( vget_low_f32(v0), vLo);
+ float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
+ float32x2_t zLo = vmul_f32( z0, vHi);
+ float32x2_t rLo = vpadd_f32( xy0, xy0);
+ rLo = vadd_f32(rLo, zLo);
+ uint32x2_t maskLo = vclt_f32( rLo, dotMinLo );
+ dotMinLo = vbsl_f32( maskLo, rLo, dotMinLo);
+ iLo = vbsl_u32(maskLo, indexLo, iLo);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vclt_f32( dotMinHi, dotMinLo );
+ dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ // select best answer between even and odd results
+ dotMinHi = vdup_lane_f32(dotMinLo, 1);
+ iHi = vdup_lane_u32(iLo, 1);
+ mask = vclt_f32( dotMinHi, dotMinLo );
+ dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
+ iLo = vbsl_u32(mask, iHi, iLo);
+
+ *dotResult = vget_lane_f32( dotMinLo, 0);
+ return vget_lane_u32(iLo, 0);
+}
+
+long _mindot_large_v1( const float *vv, const float *vec, unsigned long count, float *dotResult )
+{
+ float32x4_t vvec = vld1q_f32_aligned_postincrement( vec );
+ float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
+ float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
+ const uint32x4_t four = (uint32x4_t){ 4, 4, 4, 4 };
+ uint32x4_t local_index = (uint32x4_t) {0, 1, 2, 3};
+ uint32x4_t index = (uint32x4_t) { -1, -1, -1, -1 };
+ float32x4_t minDot = (float32x4_t) { BT_INFINITY, BT_INFINITY, BT_INFINITY, BT_INFINITY };
+
+ unsigned long i = 0;
+ for( ; i + 8 <= count; i += 8 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z1);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32( mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+
+ v0 = vld1q_f32_aligned_postincrement( vv );
+ v1 = vld1q_f32_aligned_postincrement( vv );
+ v2 = vld1q_f32_aligned_postincrement( vv );
+ v3 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ zb = vuzpq_f32( z0, z1);
+ z = vmulq_f32( zb.val[0], vHi);
+ xy = vuzpq_f32( xy0, xy1);
+ x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32( mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ for( ; i + 4 <= count; i += 4 )
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v3 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v3));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v3));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z1);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32( mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+
+ switch (count & 3) {
+ case 3:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v2 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ float32x4_t xy1 = vcombine_f32( vget_low_f32(v2), vget_low_f32(v2));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+ float32x4_t z1 = vcombine_f32( vget_high_f32(v2), vget_high_f32(v2));
+
+ xy0 = vmulq_f32(xy0, vLo);
+ xy1 = vmulq_f32(xy1, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z1);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy1);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32( mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 2:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+ float32x4_t v1 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v1));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z0 = vcombine_f32( vget_high_f32(v0), vget_high_f32(v1));
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ float32x4x2_t zb = vuzpq_f32( z0, z0);
+ float32x4_t z = vmulq_f32( zb.val[0], vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32( mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ case 1:
+ {
+ float32x4_t v0 = vld1q_f32_aligned_postincrement( vv );
+
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t xy0 = vcombine_f32( vget_low_f32(v0), vget_low_f32(v0));
+ // the next two lines should resolve to a single vswp d, d
+ float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
+
+ xy0 = vmulq_f32(xy0, vLo);
+
+ z = vmulq_f32( z, vHi);
+ float32x4x2_t xy = vuzpq_f32( xy0, xy0);
+ float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
+ x = vaddq_f32(x, z);
+
+ uint32x4_t mask = vcltq_f32(x, minDot);
+ minDot = vbslq_f32( mask, x, minDot);
+ index = vbslq_u32(mask, local_index, index);
+ local_index = vaddq_u32(local_index, four);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+
+ // select best answer between hi and lo results
+ uint32x2_t mask = vclt_f32( vget_high_f32(minDot), vget_low_f32(minDot));
+ float32x2_t minDot2 = vbsl_f32(mask, vget_high_f32(minDot), vget_low_f32(minDot));
+ uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
+
+ // select best answer between even and odd results
+ float32x2_t minDotO = vdup_lane_f32(minDot2, 1);
+ uint32x2_t indexHi = vdup_lane_u32(index2, 1);
+ mask = vclt_f32( minDotO, minDot2 );
+ minDot2 = vbsl_f32(mask, minDotO, minDot2);
+ index2 = vbsl_u32(mask, indexHi, index2);
+
+ *dotResult = vget_lane_f32( minDot2, 0);
+ return vget_lane_u32(index2, 0);
+
+}
+
+#else
+ #error Unhandled __APPLE__ arch
+#endif
+
+#endif /* __APPLE__ */
+
+
diff --git a/extern/bullet2/src/LinearMath/btVector3.h b/extern/bullet2/src/LinearMath/btVector3.h
index d99b7c83ae3..1cf65358803 100644
--- a/extern/bullet2/src/LinearMath/btVector3.h
+++ b/extern/bullet2/src/LinearMath/btVector3.h
@@ -17,9 +17,10 @@ subject to the following restrictions:
#ifndef BT_VECTOR3_H
#define BT_VECTOR3_H
-
+//#include <stdint.h>
#include "btScalar.h"
#include "btMinMax.h"
+#include "btAlignedAllocator.h"
#ifdef BT_USE_DOUBLE_PRECISION
#define btVector3Data btVector3DoubleData
@@ -29,8 +30,46 @@ subject to the following restrictions:
#define btVector3DataName "btVector3FloatData"
#endif //BT_USE_DOUBLE_PRECISION
+#if defined BT_USE_SSE
+
+//typedef uint32_t __m128i __attribute__ ((vector_size(16)));
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4556) // value of intrinsic immediate argument '4294967239' is out of range '0 - 255'
+#endif
+
+
+#define BT_SHUFFLE(x,y,z,w) ((w)<<6 | (z)<<4 | (y)<<2 | (x))
+//#define bt_pshufd_ps( _a, _mask ) (__m128) _mm_shuffle_epi32((__m128i)(_a), (_mask) )
+#define bt_pshufd_ps( _a, _mask ) _mm_shuffle_ps((_a), (_a), (_mask) )
+#define bt_splat3_ps( _a, _i ) bt_pshufd_ps((_a), BT_SHUFFLE(_i,_i,_i, 3) )
+#define bt_splat_ps( _a, _i ) bt_pshufd_ps((_a), BT_SHUFFLE(_i,_i,_i,_i) )
+
+#define btv3AbsiMask (_mm_set_epi32(0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
+#define btvAbsMask (_mm_set_epi32( 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
+#define btvFFF0Mask (_mm_set_epi32(0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF))
+#define btv3AbsfMask btCastiTo128f(btv3AbsiMask)
+#define btvFFF0fMask btCastiTo128f(btvFFF0Mask)
+#define btvxyzMaskf btvFFF0fMask
+#define btvAbsfMask btCastiTo128f(btvAbsMask)
+
+
+
+const __m128 ATTRIBUTE_ALIGNED16(btvMzeroMask) = {-0.0f, -0.0f, -0.0f, -0.0f};
+const __m128 ATTRIBUTE_ALIGNED16(v1110) = {1.0f, 1.0f, 1.0f, 0.0f};
+const __m128 ATTRIBUTE_ALIGNED16(vHalf) = {0.5f, 0.5f, 0.5f, 0.5f};
+const __m128 ATTRIBUTE_ALIGNED16(v1_5) = {1.5f, 1.5f, 1.5f, 1.5f};
+
+#endif
+#ifdef BT_USE_NEON
+const float32x4_t ATTRIBUTE_ALIGNED16(btvMzeroMask) = (float32x4_t){-0.0f, -0.0f, -0.0f, -0.0f};
+const int32x4_t ATTRIBUTE_ALIGNED16(btvFFF0Mask) = (int32x4_t){0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0};
+const int32x4_t ATTRIBUTE_ALIGNED16(btvAbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF};
+const int32x4_t ATTRIBUTE_ALIGNED16(btv3AbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x0};
+
+#endif
/**@brief btVector3 can be used to represent 3D points and vectors.
* It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user
@@ -40,6 +79,8 @@ ATTRIBUTE_ALIGNED16(class) btVector3
{
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
#if defined (__SPU__) && defined (__CELLOS_LV2__)
btScalar m_floats[4];
public:
@@ -49,28 +90,31 @@ public:
}
public:
#else //__CELLOS_LV2__ __SPU__
-#ifdef BT_USE_SSE // _WIN32
- union {
- __m128 mVec128;
- btScalar m_floats[4];
- };
- SIMD_FORCE_INLINE __m128 get128() const
- {
- return mVec128;
- }
- SIMD_FORCE_INLINE void set128(__m128 v128)
- {
- mVec128 = v128;
- }
-#else
- btScalar m_floats[4];
-#endif
+ #if defined (BT_USE_SSE) || defined(BT_USE_NEON) // _WIN32 || ARM
+ union {
+ btSimdFloat4 mVec128;
+ btScalar m_floats[4];
+ };
+ SIMD_FORCE_INLINE btSimdFloat4 get128() const
+ {
+ return mVec128;
+ }
+ SIMD_FORCE_INLINE void set128(btSimdFloat4 v128)
+ {
+ mVec128 = v128;
+ }
+ #else
+ btScalar m_floats[4];
+ #endif
#endif //__CELLOS_LV2__ __SPU__
public:
/**@brief No initialization constructor */
- SIMD_FORCE_INLINE btVector3() {}
+ SIMD_FORCE_INLINE btVector3()
+ {
+
+ }
@@ -79,21 +123,50 @@ public:
* @param y Y value
* @param z Z value
*/
- SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z)
+ SIMD_FORCE_INLINE btVector3(const btScalar& _x, const btScalar& _y, const btScalar& _z)
{
- m_floats[0] = x;
- m_floats[1] = y;
- m_floats[2] = z;
- m_floats[3] = btScalar(0.);
+ m_floats[0] = _x;
+ m_floats[1] = _y;
+ m_floats[2] = _z;
+ m_floats[3] = btScalar(0.f);
}
-
+#if (defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE) )|| defined (BT_USE_NEON)
+ // Set Vector
+ SIMD_FORCE_INLINE btVector3( btSimdFloat4 v)
+ {
+ mVec128 = v;
+ }
+
+ // Copy constructor
+ SIMD_FORCE_INLINE btVector3(const btVector3& rhs)
+ {
+ mVec128 = rhs.mVec128;
+ }
+
+ // Assignment Operator
+ SIMD_FORCE_INLINE btVector3&
+ operator=(const btVector3& v)
+ {
+ mVec128 = v.mVec128;
+
+ return *this;
+ }
+#endif // #if defined (BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
+
/**@brief Add a vector to this one
* @param The vector to add to this one */
SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v)
{
-
- m_floats[0] += v.m_floats[0]; m_floats[1] += v.m_floats[1];m_floats[2] += v.m_floats[2];
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ mVec128 = _mm_add_ps(mVec128, v.mVec128);
+#elif defined(BT_USE_NEON)
+ mVec128 = vaddq_f32(mVec128, v.mVec128);
+#else
+ m_floats[0] += v.m_floats[0];
+ m_floats[1] += v.m_floats[1];
+ m_floats[2] += v.m_floats[2];
+#endif
return *this;
}
@@ -102,14 +175,33 @@ public:
* @param The vector to subtract */
SIMD_FORCE_INLINE btVector3& operator-=(const btVector3& v)
{
- m_floats[0] -= v.m_floats[0]; m_floats[1] -= v.m_floats[1];m_floats[2] -= v.m_floats[2];
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ mVec128 = _mm_sub_ps(mVec128, v.mVec128);
+#elif defined(BT_USE_NEON)
+ mVec128 = vsubq_f32(mVec128, v.mVec128);
+#else
+ m_floats[0] -= v.m_floats[0];
+ m_floats[1] -= v.m_floats[1];
+ m_floats[2] -= v.m_floats[2];
+#endif
return *this;
}
+
/**@brief Scale the vector
* @param s Scale factor */
SIMD_FORCE_INLINE btVector3& operator*=(const btScalar& s)
{
- m_floats[0] *= s; m_floats[1] *= s;m_floats[2] *= s;
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0)
+ mVec128 = _mm_mul_ps(mVec128, vs);
+#elif defined(BT_USE_NEON)
+ mVec128 = vmulq_n_f32(mVec128, s);
+#else
+ m_floats[0] *= s;
+ m_floats[1] *= s;
+ m_floats[2] *= s;
+#endif
return *this;
}
@@ -118,14 +210,42 @@ public:
SIMD_FORCE_INLINE btVector3& operator/=(const btScalar& s)
{
btFullAssert(s != btScalar(0.0));
+
+#if 0 //defined(BT_USE_SSE_IN_API)
+// this code is not faster !
+ __m128 vs = _mm_load_ss(&s);
+ vs = _mm_div_ss(v1110, vs);
+ vs = bt_pshufd_ps(vs, 0x00); // (S S S S)
+
+ mVec128 = _mm_mul_ps(mVec128, vs);
+
+ return *this;
+#else
return *this *= btScalar(1.0) / s;
+#endif
}
/**@brief Return the dot product
* @param v The other vector in the dot product */
SIMD_FORCE_INLINE btScalar dot(const btVector3& v) const
{
- return m_floats[0] * v.m_floats[0] + m_floats[1] * v.m_floats[1] +m_floats[2] * v.m_floats[2];
+#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vd = _mm_mul_ps(mVec128, v.mVec128);
+ __m128 z = _mm_movehl_ps(vd, vd);
+ __m128 y = _mm_shuffle_ps(vd, vd, 0x55);
+ vd = _mm_add_ss(vd, y);
+ vd = _mm_add_ss(vd, z);
+ return _mm_cvtss_f32(vd);
+#elif defined(BT_USE_NEON)
+ float32x4_t vd = vmulq_f32(mVec128, v.mVec128);
+ float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_low_f32(vd));
+ x = vadd_f32(x, vget_high_f32(vd));
+ return vget_lane_f32(x, 0);
+#else
+ return m_floats[0] * v.m_floats[0] +
+ m_floats[1] * v.m_floats[1] +
+ m_floats[2] * v.m_floats[2];
+#endif
}
/**@brief Return the length of the vector squared */
@@ -165,7 +285,44 @@ public:
* x^2 + y^2 + z^2 = 1 */
SIMD_FORCE_INLINE btVector3& normalize()
{
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ // dot product first
+ __m128 vd = _mm_mul_ps(mVec128, mVec128);
+ __m128 z = _mm_movehl_ps(vd, vd);
+ __m128 y = _mm_shuffle_ps(vd, vd, 0x55);
+ vd = _mm_add_ss(vd, y);
+ vd = _mm_add_ss(vd, z);
+
+ #if 0
+ vd = _mm_sqrt_ss(vd);
+ vd = _mm_div_ss(v1110, vd);
+ vd = bt_splat_ps(vd, 0x80);
+ mVec128 = _mm_mul_ps(mVec128, vd);
+ #else
+
+ // NR step 1/sqrt(x) - vd is x, y is output
+ y = _mm_rsqrt_ss(vd); // estimate
+
+ // one step NR
+ z = v1_5;
+ vd = _mm_mul_ss(vd, vHalf); // vd * 0.5
+ //x2 = vd;
+ vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0
+ vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0 * y0
+ z = _mm_sub_ss(z, vd); // 1.5 - vd * 0.5 * y0 * y0
+
+ y = _mm_mul_ss(y, z); // y0 * (1.5 - vd * 0.5 * y0 * y0)
+
+ y = bt_splat_ps(y, 0x80);
+ mVec128 = _mm_mul_ps(mVec128, y);
+
+ #endif
+
+
+ return *this;
+#else
return *this /= length();
+#endif
}
/**@brief Return a normalized version of this vector */
@@ -184,29 +341,112 @@ public:
btFullAssert(s != btScalar(0.0));
return btAcos(dot(v) / s);
}
+
/**@brief Return a vector will the absolute values of each element */
SIMD_FORCE_INLINE btVector3 absolute() const
{
+
+#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return btVector3(_mm_and_ps(mVec128, btv3AbsfMask));
+#elif defined(BT_USE_NEON)
+ return btVector3(vabsq_f32(mVec128));
+#else
return btVector3(
btFabs(m_floats[0]),
btFabs(m_floats[1]),
btFabs(m_floats[2]));
+#endif
}
+
/**@brief Return the cross product between this and another vector
* @param v The other vector */
SIMD_FORCE_INLINE btVector3 cross(const btVector3& v) const
{
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 T, V;
+
+ T = bt_pshufd_ps(mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+ V = bt_pshufd_ps(v.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+
+ V = _mm_mul_ps(V, mVec128);
+ T = _mm_mul_ps(T, v.mVec128);
+ V = _mm_sub_ps(V, T);
+
+ V = bt_pshufd_ps(V, BT_SHUFFLE(1, 2, 0, 3));
+ return btVector3(V);
+#elif defined(BT_USE_NEON)
+ float32x4_t T, V;
+ // form (Y, Z, X, _) of mVec128 and v.mVec128
+ float32x2_t Tlow = vget_low_f32(mVec128);
+ float32x2_t Vlow = vget_low_f32(v.mVec128);
+ T = vcombine_f32(vext_f32(Tlow, vget_high_f32(mVec128), 1), Tlow);
+ V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v.mVec128), 1), Vlow);
+
+ V = vmulq_f32(V, mVec128);
+ T = vmulq_f32(T, v.mVec128);
+ V = vsubq_f32(V, T);
+ Vlow = vget_low_f32(V);
+ // form (Y, Z, X, _);
+ V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow);
+ V = (float32x4_t)vandq_s32((int32x4_t)V, btvFFF0Mask);
+
+ return btVector3(V);
+#else
return btVector3(
- m_floats[1] * v.m_floats[2] -m_floats[2] * v.m_floats[1],
+ m_floats[1] * v.m_floats[2] - m_floats[2] * v.m_floats[1],
m_floats[2] * v.m_floats[0] - m_floats[0] * v.m_floats[2],
m_floats[0] * v.m_floats[1] - m_floats[1] * v.m_floats[0]);
+#endif
}
SIMD_FORCE_INLINE btScalar triple(const btVector3& v1, const btVector3& v2) const
{
- return m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) +
+#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ // cross:
+ __m128 T = _mm_shuffle_ps(v1.mVec128, v1.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+ __m128 V = _mm_shuffle_ps(v2.mVec128, v2.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
+
+ V = _mm_mul_ps(V, v1.mVec128);
+ T = _mm_mul_ps(T, v2.mVec128);
+ V = _mm_sub_ps(V, T);
+
+ V = _mm_shuffle_ps(V, V, BT_SHUFFLE(1, 2, 0, 3));
+
+ // dot:
+ V = _mm_mul_ps(V, mVec128);
+ __m128 z = _mm_movehl_ps(V, V);
+ __m128 y = _mm_shuffle_ps(V, V, 0x55);
+ V = _mm_add_ss(V, y);
+ V = _mm_add_ss(V, z);
+ return _mm_cvtss_f32(V);
+
+#elif defined(BT_USE_NEON)
+ // cross:
+ float32x4_t T, V;
+ // form (Y, Z, X, _) of mVec128 and v.mVec128
+ float32x2_t Tlow = vget_low_f32(v1.mVec128);
+ float32x2_t Vlow = vget_low_f32(v2.mVec128);
+ T = vcombine_f32(vext_f32(Tlow, vget_high_f32(v1.mVec128), 1), Tlow);
+ V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v2.mVec128), 1), Vlow);
+
+ V = vmulq_f32(V, v1.mVec128);
+ T = vmulq_f32(T, v2.mVec128);
+ V = vsubq_f32(V, T);
+ Vlow = vget_low_f32(V);
+ // form (Y, Z, X, _);
+ V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow);
+
+ // dot:
+ V = vmulq_f32(mVec128, V);
+ float32x2_t x = vpadd_f32(vget_low_f32(V), vget_low_f32(V));
+ x = vadd_f32(x, vget_high_f32(V));
+ return vget_lane_f32(x, 0);
+#else
+ return
+ m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) +
m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) +
m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]);
+#endif
}
/**@brief Return the axis with the smallest value
@@ -233,14 +473,31 @@ public:
return absolute().maxAxis();
}
+
SIMD_FORCE_INLINE void setInterpolate3(const btVector3& v0, const btVector3& v1, btScalar rt)
{
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vrt = _mm_load_ss(&rt); // (rt 0 0 0)
+ btScalar s = btScalar(1.0) - rt;
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0)
+ __m128 r0 = _mm_mul_ps(v0.mVec128, vs);
+ vrt = bt_pshufd_ps(vrt, 0x80); // (rt rt rt 0.0)
+ __m128 r1 = _mm_mul_ps(v1.mVec128, vrt);
+ __m128 tmp3 = _mm_add_ps(r0,r1);
+ mVec128 = tmp3;
+#elif defined(BT_USE_NEON)
+ mVec128 = vsubq_f32(v1.mVec128, v0.mVec128);
+ mVec128 = vmulq_n_f32(mVec128, rt);
+ mVec128 = vaddq_f32(mVec128, v0.mVec128);
+#else
btScalar s = btScalar(1.0) - rt;
m_floats[0] = s * v0.m_floats[0] + rt * v1.m_floats[0];
m_floats[1] = s * v0.m_floats[1] + rt * v1.m_floats[1];
m_floats[2] = s * v0.m_floats[2] + rt * v1.m_floats[2];
//don't do the unused w component
// m_co[3] = s * v0[3] + rt * v1[3];
+#endif
}
/**@brief Return the linear interpolation between this and another vector
@@ -248,16 +505,41 @@ public:
* @param t The ration of this to v (t = 0 => return this, t=1 => return other) */
SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v, const btScalar& t) const
{
- return btVector3(m_floats[0] + (v.m_floats[0] - m_floats[0]) * t,
- m_floats[1] + (v.m_floats[1] - m_floats[1]) * t,
- m_floats[2] + (v.m_floats[2] -m_floats[2]) * t);
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vt = _mm_load_ss(&t); // (t 0 0 0)
+ vt = bt_pshufd_ps(vt, 0x80); // (rt rt rt 0.0)
+ __m128 vl = _mm_sub_ps(v.mVec128, mVec128);
+ vl = _mm_mul_ps(vl, vt);
+ vl = _mm_add_ps(vl, mVec128);
+
+ return btVector3(vl);
+#elif defined(BT_USE_NEON)
+ float32x4_t vl = vsubq_f32(v.mVec128, mVec128);
+ vl = vmulq_n_f32(vl, t);
+ vl = vaddq_f32(vl, mVec128);
+
+ return btVector3(vl);
+#else
+ return
+ btVector3( m_floats[0] + (v.m_floats[0] - m_floats[0]) * t,
+ m_floats[1] + (v.m_floats[1] - m_floats[1]) * t,
+ m_floats[2] + (v.m_floats[2] - m_floats[2]) * t);
+#endif
}
/**@brief Elementwise multiply this vector by the other
* @param v The other vector */
SIMD_FORCE_INLINE btVector3& operator*=(const btVector3& v)
{
- m_floats[0] *= v.m_floats[0]; m_floats[1] *= v.m_floats[1];m_floats[2] *= v.m_floats[2];
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ mVec128 = _mm_mul_ps(mVec128, v.mVec128);
+#elif defined(BT_USE_NEON)
+ mVec128 = vmulq_f32(mVec128, v.mVec128);
+#else
+ m_floats[0] *= v.m_floats[0];
+ m_floats[1] *= v.m_floats[1];
+ m_floats[2] *= v.m_floats[2];
+#endif
return *this;
}
@@ -268,13 +550,13 @@ public:
/**@brief Return the z value */
SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
/**@brief Set the x value */
- SIMD_FORCE_INLINE void setX(btScalar x) { m_floats[0] = x;};
+ SIMD_FORCE_INLINE void setX(btScalar _x) { m_floats[0] = _x;};
/**@brief Set the y value */
- SIMD_FORCE_INLINE void setY(btScalar y) { m_floats[1] = y;};
+ SIMD_FORCE_INLINE void setY(btScalar _y) { m_floats[1] = _y;};
/**@brief Set the z value */
- SIMD_FORCE_INLINE void setZ(btScalar z) {m_floats[2] = z;};
+ SIMD_FORCE_INLINE void setZ(btScalar _z) { m_floats[2] = _z;};
/**@brief Set the w value */
- SIMD_FORCE_INLINE void setW(btScalar w) { m_floats[3] = w;};
+ SIMD_FORCE_INLINE void setW(btScalar _w) { m_floats[3] = _w;};
/**@brief Return the x value */
SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
/**@brief Return the y value */
@@ -292,7 +574,14 @@ public:
SIMD_FORCE_INLINE bool operator==(const btVector3& other) const
{
- return ((m_floats[3]==other.m_floats[3]) && (m_floats[2]==other.m_floats[2]) && (m_floats[1]==other.m_floats[1]) && (m_floats[0]==other.m_floats[0]));
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
+#else
+ return ((m_floats[3]==other.m_floats[3]) &&
+ (m_floats[2]==other.m_floats[2]) &&
+ (m_floats[1]==other.m_floats[1]) &&
+ (m_floats[0]==other.m_floats[0]));
+#endif
}
SIMD_FORCE_INLINE bool operator!=(const btVector3& other) const
@@ -300,103 +589,230 @@ public:
return !(*this == other);
}
- /**@brief Set each element to the max of the current values and the values of another btVector3
+ /**@brief Set each element to the max of the current values and the values of another btVector3
* @param other The other btVector3 to compare with
*/
- SIMD_FORCE_INLINE void setMax(const btVector3& other)
- {
- btSetMax(m_floats[0], other.m_floats[0]);
- btSetMax(m_floats[1], other.m_floats[1]);
- btSetMax(m_floats[2], other.m_floats[2]);
- btSetMax(m_floats[3], other.w());
- }
+ SIMD_FORCE_INLINE void setMax(const btVector3& other)
+ {
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ mVec128 = _mm_max_ps(mVec128, other.mVec128);
+#elif defined(BT_USE_NEON)
+ mVec128 = vmaxq_f32(mVec128, other.mVec128);
+#else
+ btSetMax(m_floats[0], other.m_floats[0]);
+ btSetMax(m_floats[1], other.m_floats[1]);
+ btSetMax(m_floats[2], other.m_floats[2]);
+ btSetMax(m_floats[3], other.w());
+#endif
+ }
+
/**@brief Set each element to the min of the current values and the values of another btVector3
* @param other The other btVector3 to compare with
*/
- SIMD_FORCE_INLINE void setMin(const btVector3& other)
- {
- btSetMin(m_floats[0], other.m_floats[0]);
- btSetMin(m_floats[1], other.m_floats[1]);
- btSetMin(m_floats[2], other.m_floats[2]);
- btSetMin(m_floats[3], other.w());
- }
-
- SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z)
- {
- m_floats[0]=x;
- m_floats[1]=y;
- m_floats[2]=z;
- m_floats[3] = btScalar(0.);
- }
-
- void getSkewSymmetricMatrix(btVector3* v0,btVector3* v1,btVector3* v2) const
- {
- v0->setValue(0. ,-z() ,y());
- v1->setValue(z() ,0. ,-x());
- v2->setValue(-y() ,x() ,0.);
- }
-
- void setZero()
- {
- setValue(btScalar(0.),btScalar(0.),btScalar(0.));
- }
-
- SIMD_FORCE_INLINE bool isZero() const
- {
- return m_floats[0] == btScalar(0) && m_floats[1] == btScalar(0) && m_floats[2] == btScalar(0);
- }
-
- SIMD_FORCE_INLINE bool fuzzyZero() const
- {
- return length2() < SIMD_EPSILON;
- }
-
- SIMD_FORCE_INLINE void serialize(struct btVector3Data& dataOut) const;
+ SIMD_FORCE_INLINE void setMin(const btVector3& other)
+ {
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ mVec128 = _mm_min_ps(mVec128, other.mVec128);
+#elif defined(BT_USE_NEON)
+ mVec128 = vminq_f32(mVec128, other.mVec128);
+#else
+ btSetMin(m_floats[0], other.m_floats[0]);
+ btSetMin(m_floats[1], other.m_floats[1]);
+ btSetMin(m_floats[2], other.m_floats[2]);
+ btSetMin(m_floats[3], other.w());
+#endif
+ }
- SIMD_FORCE_INLINE void deSerialize(const struct btVector3Data& dataIn);
+ SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z)
+ {
+ m_floats[0]=_x;
+ m_floats[1]=_y;
+ m_floats[2]=_z;
+ m_floats[3] = btScalar(0.f);
+ }
- SIMD_FORCE_INLINE void serializeFloat(struct btVector3FloatData& dataOut) const;
+ void getSkewSymmetricMatrix(btVector3* v0,btVector3* v1,btVector3* v2) const
+ {
+#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+
+ __m128 V = _mm_and_ps(mVec128, btvFFF0fMask);
+ __m128 V0 = _mm_xor_ps(btvMzeroMask, V);
+ __m128 V2 = _mm_movelh_ps(V0, V);
+
+ __m128 V1 = _mm_shuffle_ps(V, V0, 0xCE);
+
+ V0 = _mm_shuffle_ps(V0, V, 0xDB);
+ V2 = _mm_shuffle_ps(V2, V, 0xF9);
+
+ v0->mVec128 = V0;
+ v1->mVec128 = V1;
+ v2->mVec128 = V2;
+#else
+ v0->setValue(0. ,-z() ,y());
+ v1->setValue(z() ,0. ,-x());
+ v2->setValue(-y() ,x() ,0.);
+#endif
+ }
- SIMD_FORCE_INLINE void deSerializeFloat(const struct btVector3FloatData& dataIn);
+ void setZero()
+ {
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ mVec128 = (__m128)_mm_xor_ps(mVec128, mVec128);
+#elif defined(BT_USE_NEON)
+ int32x4_t vi = vdupq_n_s32(0);
+ mVec128 = vreinterpretq_f32_s32(vi);
+#else
+ setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+#endif
+ }
- SIMD_FORCE_INLINE void serializeDouble(struct btVector3DoubleData& dataOut) const;
+ SIMD_FORCE_INLINE bool isZero() const
+ {
+ return m_floats[0] == btScalar(0) && m_floats[1] == btScalar(0) && m_floats[2] == btScalar(0);
+ }
- SIMD_FORCE_INLINE void deSerializeDouble(const struct btVector3DoubleData& dataIn);
+ SIMD_FORCE_INLINE bool fuzzyZero() const
+ {
+ return length2() < SIMD_EPSILON;
+ }
+ SIMD_FORCE_INLINE void serialize(struct btVector3Data& dataOut) const;
+
+ SIMD_FORCE_INLINE void deSerialize(const struct btVector3Data& dataIn);
+
+ SIMD_FORCE_INLINE void serializeFloat(struct btVector3FloatData& dataOut) const;
+
+ SIMD_FORCE_INLINE void deSerializeFloat(const struct btVector3FloatData& dataIn);
+
+ SIMD_FORCE_INLINE void serializeDouble(struct btVector3DoubleData& dataOut) const;
+
+ SIMD_FORCE_INLINE void deSerializeDouble(const struct btVector3DoubleData& dataIn);
+
+ /**@brief returns index of maximum dot product between this and vectors in array[]
+ * @param array The other vectors
+ * @param array_count The number of other vectors
+ * @param dotOut The maximum dot product */
+ SIMD_FORCE_INLINE long maxDot( const btVector3 *array, long array_count, btScalar &dotOut ) const;
+
+ /**@brief returns index of minimum dot product between this and vectors in array[]
+ * @param array The other vectors
+ * @param array_count The number of other vectors
+ * @param dotOut The minimum dot product */
+ SIMD_FORCE_INLINE long minDot( const btVector3 *array, long array_count, btScalar &dotOut ) const;
+
+ /* create a vector as btVector3( this->dot( btVector3 v0 ), this->dot( btVector3 v1), this->dot( btVector3 v2 )) */
+ SIMD_FORCE_INLINE btVector3 dot3( const btVector3 &v0, const btVector3 &v1, const btVector3 &v2 ) const
+ {
+#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+
+ __m128 a0 = _mm_mul_ps( v0.mVec128, this->mVec128 );
+ __m128 a1 = _mm_mul_ps( v1.mVec128, this->mVec128 );
+ __m128 a2 = _mm_mul_ps( v2.mVec128, this->mVec128 );
+ __m128 b0 = _mm_unpacklo_ps( a0, a1 );
+ __m128 b1 = _mm_unpackhi_ps( a0, a1 );
+ __m128 b2 = _mm_unpacklo_ps( a2, _mm_setzero_ps() );
+ __m128 r = _mm_movelh_ps( b0, b2 );
+ r = _mm_add_ps( r, _mm_movehl_ps( b2, b0 ));
+ a2 = _mm_and_ps( a2, btvxyzMaskf);
+ r = _mm_add_ps( r, btCastdTo128f (_mm_move_sd( btCastfTo128d(a2), btCastfTo128d(b1) )));
+ return btVector3(r);
+
+#elif defined(BT_USE_NEON)
+ static const uint32x4_t xyzMask = (const uint32x4_t){ -1, -1, -1, 0 };
+ float32x4_t a0 = vmulq_f32( v0.mVec128, this->mVec128);
+ float32x4_t a1 = vmulq_f32( v1.mVec128, this->mVec128);
+ float32x4_t a2 = vmulq_f32( v2.mVec128, this->mVec128);
+ float32x2x2_t zLo = vtrn_f32( vget_high_f32(a0), vget_high_f32(a1));
+ a2 = (float32x4_t) vandq_u32((uint32x4_t) a2, xyzMask );
+ float32x2_t b0 = vadd_f32( vpadd_f32( vget_low_f32(a0), vget_low_f32(a1)), zLo.val[0] );
+ float32x2_t b1 = vpadd_f32( vpadd_f32( vget_low_f32(a2), vget_high_f32(a2)), vdup_n_f32(0.0f));
+ return btVector3( vcombine_f32(b0, b1) );
+#else
+ return btVector3( dot(v0), dot(v1), dot(v2));
+#endif
+ }
};
/**@brief Return the sum of two vectors (Point symantics)*/
SIMD_FORCE_INLINE btVector3
operator+(const btVector3& v1, const btVector3& v2)
{
- return btVector3(v1.m_floats[0] + v2.m_floats[0], v1.m_floats[1] + v2.m_floats[1], v1.m_floats[2] + v2.m_floats[2]);
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return btVector3(_mm_add_ps(v1.mVec128, v2.mVec128));
+#elif defined(BT_USE_NEON)
+ return btVector3(vaddq_f32(v1.mVec128, v2.mVec128));
+#else
+ return btVector3(
+ v1.m_floats[0] + v2.m_floats[0],
+ v1.m_floats[1] + v2.m_floats[1],
+ v1.m_floats[2] + v2.m_floats[2]);
+#endif
}
/**@brief Return the elementwise product of two vectors */
SIMD_FORCE_INLINE btVector3
operator*(const btVector3& v1, const btVector3& v2)
{
- return btVector3(v1.m_floats[0] * v2.m_floats[0], v1.m_floats[1] * v2.m_floats[1], v1.m_floats[2] * v2.m_floats[2]);
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return btVector3(_mm_mul_ps(v1.mVec128, v2.mVec128));
+#elif defined(BT_USE_NEON)
+ return btVector3(vmulq_f32(v1.mVec128, v2.mVec128));
+#else
+ return btVector3(
+ v1.m_floats[0] * v2.m_floats[0],
+ v1.m_floats[1] * v2.m_floats[1],
+ v1.m_floats[2] * v2.m_floats[2]);
+#endif
}
/**@brief Return the difference between two vectors */
SIMD_FORCE_INLINE btVector3
operator-(const btVector3& v1, const btVector3& v2)
{
- return btVector3(v1.m_floats[0] - v2.m_floats[0], v1.m_floats[1] - v2.m_floats[1], v1.m_floats[2] - v2.m_floats[2]);
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
+
+ // without _mm_and_ps this code causes slowdown in Concave moving
+ __m128 r = _mm_sub_ps(v1.mVec128, v2.mVec128);
+ return btVector3(_mm_and_ps(r, btvFFF0fMask));
+#elif defined(BT_USE_NEON)
+ float32x4_t r = vsubq_f32(v1.mVec128, v2.mVec128);
+ return btVector3((float32x4_t)vandq_s32((int32x4_t)r, btvFFF0Mask));
+#else
+ return btVector3(
+ v1.m_floats[0] - v2.m_floats[0],
+ v1.m_floats[1] - v2.m_floats[1],
+ v1.m_floats[2] - v2.m_floats[2]);
+#endif
}
+
/**@brief Return the negative of the vector */
SIMD_FORCE_INLINE btVector3
operator-(const btVector3& v)
{
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE))
+ __m128 r = _mm_xor_ps(v.mVec128, btvMzeroMask);
+ return btVector3(_mm_and_ps(r, btvFFF0fMask));
+#elif defined(BT_USE_NEON)
+ return btVector3((btSimdFloat4)veorq_s32((int32x4_t)v.mVec128, (int32x4_t)btvMzeroMask));
+#else
return btVector3(-v.m_floats[0], -v.m_floats[1], -v.m_floats[2]);
+#endif
}
/**@brief Return the vector scaled by s */
SIMD_FORCE_INLINE btVector3
operator*(const btVector3& v, const btScalar& s)
{
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
+ vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0)
+ return btVector3(_mm_mul_ps(v.mVec128, vs));
+#elif defined(BT_USE_NEON)
+ float32x4_t r = vmulq_n_f32(v.mVec128, s);
+ return btVector3((float32x4_t)vandq_s32((int32x4_t)r, btvFFF0Mask));
+#else
return btVector3(v.m_floats[0] * s, v.m_floats[1] * s, v.m_floats[2] * s);
+#endif
}
/**@brief Return the vector scaled by s */
@@ -411,14 +827,46 @@ SIMD_FORCE_INLINE btVector3
operator/(const btVector3& v, const btScalar& s)
{
btFullAssert(s != btScalar(0.0));
+#if 0 //defined(BT_USE_SSE_IN_API)
+// this code is not faster !
+ __m128 vs = _mm_load_ss(&s);
+ vs = _mm_div_ss(v1110, vs);
+ vs = bt_pshufd_ps(vs, 0x00); // (S S S S)
+
+ return btVector3(_mm_mul_ps(v.mVec128, vs));
+#else
return v * (btScalar(1.0) / s);
+#endif
}
/**@brief Return the vector inversely scaled by s */
SIMD_FORCE_INLINE btVector3
operator/(const btVector3& v1, const btVector3& v2)
{
- return btVector3(v1.m_floats[0] / v2.m_floats[0],v1.m_floats[1] / v2.m_floats[1],v1.m_floats[2] / v2.m_floats[2]);
+#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API)&& defined (BT_USE_SSE))
+ __m128 vec = _mm_div_ps(v1.mVec128, v2.mVec128);
+ vec = _mm_and_ps(vec, btvFFF0fMask);
+ return btVector3(vec);
+#elif defined(BT_USE_NEON)
+ float32x4_t x, y, v, m;
+
+ x = v1.mVec128;
+ y = v2.mVec128;
+
+ v = vrecpeq_f32(y); // v ~ 1/y
+ m = vrecpsq_f32(y, v); // m = (2-v*y)
+ v = vmulq_f32(v, m); // vv = v*m ~~ 1/y
+ m = vrecpsq_f32(y, v); // mm = (2-vv*y)
+ v = vmulq_f32(v, x); // x*vv
+ v = vmulq_f32(v, m); // (x*vv)*(2-vv*y) = x*(vv(2-vv*y)) ~~~ x/y
+
+ return btVector3(v);
+#else
+ return btVector3(
+ v1.m_floats[0] / v2.m_floats[0],
+ v1.m_floats[1] / v2.m_floats[1],
+ v1.m_floats[2] / v2.m_floats[2]);
+#endif
}
/**@brief Return the dot product between two vectors */
@@ -488,22 +936,133 @@ SIMD_FORCE_INLINE btScalar btVector3::distance(const btVector3& v) const
SIMD_FORCE_INLINE btVector3 btVector3::normalized() const
{
+#if defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ btVector3 norm = *this;
+
+ return norm.normalize();
+#else
return *this / length();
+#endif
}
-SIMD_FORCE_INLINE btVector3 btVector3::rotate( const btVector3& wAxis, const btScalar angle ) const
+SIMD_FORCE_INLINE btVector3 btVector3::rotate( const btVector3& wAxis, const btScalar _angle ) const
{
// wAxis must be a unit lenght vector
+#if defined BT_USE_SIMD_VECTOR3 && defined (BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+
+ __m128 O = _mm_mul_ps(wAxis.mVec128, mVec128);
+ btScalar ssin = btSin( _angle );
+ __m128 C = wAxis.cross( mVec128 ).mVec128;
+ O = _mm_and_ps(O, btvFFF0fMask);
+ btScalar scos = btCos( _angle );
+
+ __m128 vsin = _mm_load_ss(&ssin); // (S 0 0 0)
+ __m128 vcos = _mm_load_ss(&scos); // (S 0 0 0)
+
+ __m128 Y = bt_pshufd_ps(O, 0xC9); // (Y Z X 0)
+ __m128 Z = bt_pshufd_ps(O, 0xD2); // (Z X Y 0)
+ O = _mm_add_ps(O, Y);
+ vsin = bt_pshufd_ps(vsin, 0x80); // (S S S 0)
+ O = _mm_add_ps(O, Z);
+ vcos = bt_pshufd_ps(vcos, 0x80); // (S S S 0)
+
+ vsin = vsin * C;
+ O = O * wAxis.mVec128;
+ __m128 X = mVec128 - O;
+
+ O = O + vsin;
+ vcos = vcos * X;
+ O = O + vcos;
+
+ return btVector3(O);
+#else
btVector3 o = wAxis * wAxis.dot( *this );
- btVector3 x = *this - o;
- btVector3 y;
+ btVector3 _x = *this - o;
+ btVector3 _y;
- y = wAxis.cross( *this );
+ _y = wAxis.cross( *this );
- return ( o + x * btCos( angle ) + y * btSin( angle ) );
+ return ( o + _x * btCos( _angle ) + _y * btSin( _angle ) );
+#endif
+}
+
+SIMD_FORCE_INLINE long btVector3::maxDot( const btVector3 *array, long array_count, btScalar &dotOut ) const
+{
+#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
+ #if defined _WIN32 || defined (BT_USE_SSE)
+ const long scalar_cutoff = 10;
+ long _maxdot_large( const float *array, const float *vec, unsigned long array_count, float *dotOut );
+ #elif defined BT_USE_NEON
+ const long scalar_cutoff = 4;
+ extern long (*_maxdot_large)( const float *array, const float *vec, unsigned long array_count, float *dotOut );
+ #endif
+ if( array_count < scalar_cutoff )
+#endif
+ {
+ btScalar maxDot = -SIMD_INFINITY;
+ int i = 0;
+ int ptIndex = -1;
+ for( i = 0; i < array_count; i++ )
+ {
+ btScalar dot = array[i].dot(*this);
+
+ if( dot > maxDot )
+ {
+ maxDot = dot;
+ ptIndex = i;
+ }
+ }
+
+ dotOut = maxDot;
+ return ptIndex;
+ }
+#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
+ return _maxdot_large( (float*) array, (float*) &m_floats[0], array_count, &dotOut );
+#endif
}
+SIMD_FORCE_INLINE long btVector3::minDot( const btVector3 *array, long array_count, btScalar &dotOut ) const
+{
+#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
+ #if defined BT_USE_SSE
+ const long scalar_cutoff = 10;
+ long _mindot_large( const float *array, const float *vec, unsigned long array_count, float *dotOut );
+ #elif defined BT_USE_NEON
+ const long scalar_cutoff = 4;
+ extern long (*_mindot_large)( const float *array, const float *vec, unsigned long array_count, float *dotOut );
+ #else
+ #error unhandled arch!
+ #endif
+
+ if( array_count < scalar_cutoff )
+#endif
+ {
+ btScalar minDot = SIMD_INFINITY;
+ int i = 0;
+ int ptIndex = -1;
+
+ for( i = 0; i < array_count; i++ )
+ {
+ btScalar dot = array[i].dot(*this);
+
+ if( dot < minDot )
+ {
+ minDot = dot;
+ ptIndex = i;
+ }
+ }
+
+ dotOut = minDot;
+
+ return ptIndex;
+ }
+#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
+ return _mindot_large( (float*) array, (float*) &m_floats[0], array_count, &dotOut );
+#endif//BT_USE_SIMD_VECTOR3
+}
+
+
class btVector4 : public btVector3
{
public:
@@ -511,24 +1070,47 @@ public:
SIMD_FORCE_INLINE btVector4() {}
- SIMD_FORCE_INLINE btVector4(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w)
- : btVector3(x,y,z)
+ SIMD_FORCE_INLINE btVector4(const btScalar& _x, const btScalar& _y, const btScalar& _z,const btScalar& _w)
+ : btVector3(_x,_y,_z)
+ {
+ m_floats[3] = _w;
+ }
+
+#if (defined (BT_USE_SSE_IN_API)&& defined (BT_USE_SSE)) || defined (BT_USE_NEON)
+ SIMD_FORCE_INLINE btVector4(const btSimdFloat4 vec)
+ {
+ mVec128 = vec;
+ }
+
+ SIMD_FORCE_INLINE btVector4(const btVector3& rhs)
{
- m_floats[3] = w;
+ mVec128 = rhs.mVec128;
}
+ SIMD_FORCE_INLINE btVector4&
+ operator=(const btVector4& v)
+ {
+ mVec128 = v.mVec128;
+ return *this;
+ }
+#endif // #if defined (BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
SIMD_FORCE_INLINE btVector4 absolute4() const
{
+#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined (BT_USE_SSE)
+ return btVector4(_mm_and_ps(mVec128, btvAbsfMask));
+#elif defined(BT_USE_NEON)
+ return btVector4(vabsq_f32(mVec128));
+#else
return btVector4(
btFabs(m_floats[0]),
btFabs(m_floats[1]),
btFabs(m_floats[2]),
btFabs(m_floats[3]));
+#endif
}
-
btScalar getW() const { return m_floats[3];}
@@ -556,12 +1138,8 @@ public:
maxIndex = 3;
maxVal = m_floats[3];
}
-
-
-
return maxIndex;
-
}
@@ -591,7 +1169,6 @@ public:
}
return minIndex;
-
}
@@ -623,12 +1200,12 @@ public:
* @param z Value of z
* @param w Value of w
*/
- SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w)
+ SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z,const btScalar& _w)
{
- m_floats[0]=x;
- m_floats[1]=y;
- m_floats[2]=z;
- m_floats[3]=w;
+ m_floats[0]=_x;
+ m_floats[1]=_y;
+ m_floats[2]=_z;
+ m_floats[3]=_w;
}
@@ -762,5 +1339,4 @@ SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3Data& dataIn
m_floats[i] = dataIn.m_floats[i];
}
-
#endif //BT_VECTOR3_H
diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript
index 8a3db17f6d1..3ffff9c80fc 100644
--- a/extern/bullet2/src/SConscript
+++ b/extern/bullet2/src/SConscript
@@ -35,4 +35,7 @@ bullet2_src += env.Glob("BulletSoftBody/*.cpp")
incs = '. BulletCollision BulletDynamics LinearMath BulletSoftBody'
-env.BlenderLib ( libname = 'extern_bullet2', sources=bullet2_src, includes=Split(incs), defines=Split(defs), libtype=['extern','player'], priority=[20,137], compileflags=cflags )
+if sys.platform=='darwin' and env['CC'][:-2].endswith('4.6'): # workaround for an gcc-4.6 compiler bug
+ env.BlenderLib ( libname = 'extern_bullet2', sources=bullet2_src, includes=Split(incs), defines=Split(defs), libtype=['extern','player'], priority=[20,137], compileflags=cflags, cc_compilerchange='/usr/bin/gcc', cxx_compilerchange='/usr/bin/g++' )
+else:
+ env.BlenderLib ( libname = 'extern_bullet2', sources=bullet2_src, includes=Split(incs), defines=Split(defs), libtype=['extern','player'], priority=[20,137], compileflags=cflags )
diff --git a/extern/bullet2/src/btBulletCollisionCommon.h b/extern/bullet2/src/btBulletCollisionCommon.h
index 472690c1573..af981b5d36d 100644
--- a/extern/bullet2/src/btBulletCollisionCommon.h
+++ b/extern/bullet2/src/btBulletCollisionCommon.h
@@ -45,7 +45,6 @@ subject to the following restrictions:
///Narrowphase Collision Detector
#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
-//btSphereBoxCollisionAlgorithm is broken, use gjk for now
//#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h"
diff --git a/extern/bullet2/src/btBulletDynamicsCommon.h b/extern/bullet2/src/btBulletDynamicsCommon.h
index ccfad19b87a..dbd175c3fe6 100644
--- a/extern/bullet2/src/btBulletDynamicsCommon.h
+++ b/extern/bullet2/src/btBulletDynamicsCommon.h
@@ -32,6 +32,7 @@ subject to the following restrictions:
#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h"
#include "BulletDynamics/ConstraintSolver/btUniversalConstraint.h"
#include "BulletDynamics/ConstraintSolver/btHinge2Constraint.h"
+#include "BulletDynamics/ConstraintSolver/btGearConstraint.h"
#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
diff --git a/extern/carve/bundle.sh b/extern/carve/bundle.sh
index 63d32a5993d..c80bf645077 100755
--- a/extern/carve/bundle.sh
+++ b/extern/carve/bundle.sh
@@ -91,7 +91,7 @@ if(WITH_BOOST)
-DCARVE_SYSTEM_BOOST
)
- list(APPEND INC
+ list(APPEND INC_SYS
\${BOOST_INCLUDE_DIR}
)
endif()
diff --git a/extern/carve/files.txt b/extern/carve/files.txt
index c3cb9275950..1084c7f5c41 100644
--- a/extern/carve/files.txt
+++ b/extern/carve/files.txt
@@ -1,107 +1,109 @@
-include/carve/polyhedron_decl.hpp
-include/carve/geom2d.hpp
-include/carve/exact.hpp
-include/carve/triangulator_impl.hpp
-include/carve/collection.hpp
-include/carve/pointset.hpp
-include/carve/djset.hpp
-include/carve/kd_node.hpp
-include/carve/polyline.hpp
-include/carve/polyline_iter.hpp
-include/carve/geom3d.hpp
-include/carve/edge_decl.hpp
-include/carve/face_decl.hpp
+include/carve/vertex_impl.hpp
include/carve/aabb_impl.hpp
-include/carve/colour.hpp
+include/carve/csg.hpp
include/carve/pointset_iter.hpp
-include/carve/polyline_decl.hpp
-include/carve/rescale.hpp
-include/carve/mesh_impl.hpp
-include/carve/classification.hpp
-include/carve/util.hpp
-include/carve/triangulator.hpp
-include/carve/polyhedron_base.hpp
-include/carve/rtree.hpp
-include/carve/math.hpp
-include/carve/math_constants.hpp
-include/carve/octree_decl.hpp
-include/carve/input.hpp
-include/carve/mesh_ops.hpp
include/carve/debug_hooks.hpp
-include/carve/mesh_simplify.hpp
-include/carve/interpolator.hpp
-include/carve/poly_decl.hpp
-include/carve/csg.hpp
include/carve/mesh.hpp
-include/carve/carve.hpp
-include/carve/gnu_cxx.h
-include/carve/polyhedron_impl.hpp
-include/carve/poly_impl.hpp
-include/carve/aabb.hpp
+include/carve/triangulator_impl.hpp
+include/carve/edge_decl.hpp
+include/carve/collection/unordered.hpp
+include/carve/collection/unordered/tr1_impl.hpp
+include/carve/collection/unordered/fallback_impl.hpp
+include/carve/collection/unordered/std_impl.hpp
+include/carve/collection/unordered/vcpp_impl.hpp
+include/carve/collection/unordered/libstdcpp_impl.hpp
+include/carve/collection/unordered/boost_impl.hpp
include/carve/convex_hull.hpp
-include/carve/vertex_decl.hpp
+include/carve/geom.hpp
+include/carve/collection_types.hpp
+include/carve/cbrt.h
+include/carve/util.hpp
+include/carve/iobj.hpp
+include/carve/polyline_decl.hpp
+include/carve/polyline_impl.hpp
include/carve/win32.h
include/carve/edge_impl.hpp
-include/carve/tag.hpp
-include/carve/tree.hpp
-include/carve/heap.hpp
+include/carve/carve.hpp
+include/carve/polyline.hpp
+include/carve/config.h
+include/carve/face_decl.hpp
include/carve/matrix.hpp
-include/carve/poly.hpp
-include/carve/vector.hpp
-include/carve/intersection.hpp
-include/carve/faceloop.hpp
+include/carve/classification.hpp
include/carve/geom_impl.hpp
-include/carve/octree_impl.hpp
-include/carve/spacetree.hpp
-include/carve/collection/unordered/std_impl.hpp
-include/carve/collection/unordered/tr1_impl.hpp
-include/carve/collection/unordered/libstdcpp_impl.hpp
-include/carve/collection/unordered/boost_impl.hpp
-include/carve/collection/unordered/vcpp_impl.hpp
-include/carve/collection/unordered/fallback_impl.hpp
-include/carve/collection/unordered.hpp
+include/carve/faceloop.hpp
+include/carve/mesh_ops.hpp
+include/carve/tree.hpp
+include/carve/geom2d.hpp
include/carve/face_impl.hpp
+include/carve/polyhedron_decl.hpp
+include/carve/interpolator.hpp
+include/carve/poly_decl.hpp
+include/carve/mesh_impl.hpp
+include/carve/gnu_cxx.h
+include/carve/mesh_simplify.hpp
+include/carve/triangulator.hpp
include/carve/pointset_impl.hpp
-include/carve/cbrt.h
+include/carve/rtree.hpp
+include/carve/math_constants.hpp
+include/carve/vector.hpp
+include/carve/octree_impl.hpp
+include/carve/pointset.hpp
+include/carve/math.hpp
+include/carve/intersection.hpp
+include/carve/colour.hpp
+include/carve/kd_node.hpp
+include/carve/input.hpp
+include/carve/geom3d.hpp
+include/carve/exact.hpp
+include/carve/rescale.hpp
+include/carve/polyhedron_base.hpp
+include/carve/heap.hpp
+include/carve/spacetree.hpp
+include/carve/polyhedron_impl.hpp
include/carve/vcpp_config.h
-include/carve/geom.hpp
-include/carve/vertex_impl.hpp
-include/carve/polyline_impl.hpp
-include/carve/pointset_decl.hpp
-include/carve/timing.hpp
+include/carve/aabb.hpp
+include/carve/polyline_iter.hpp
+include/carve/djset.hpp
+include/carve/vertex_decl.hpp
include/carve/csg_triangulator.hpp
-include/carve/iobj.hpp
-include/carve/collection_types.hpp
-lib/carve.cpp
-lib/mesh.cpp
-lib/intersect_group.cpp
-lib/intersect_classify_common.hpp
-lib/intersect_classify_edge.cpp
-lib/intersect_classify_group.cpp
+include/carve/poly.hpp
+include/carve/external/boost/random.hpp
+include/carve/timing.hpp
+include/carve/octree_decl.hpp
+include/carve/pointset_decl.hpp
+include/carve/tag.hpp
+include/carve/collection.hpp
+include/carve/poly_impl.hpp
+lib/intersection.cpp
+lib/intersect.cpp
+lib/triangulator.cpp
+lib/intersect_debug.hpp
+lib/csg_collector.hpp
lib/csg_data.hpp
+lib/convex_hull.cpp
+lib/intersect_classify_common.hpp
+lib/intersect_common.hpp
lib/polyhedron.cpp
-lib/csg_collector.hpp
-lib/geom3d.cpp
lib/polyline.cpp
-lib/csg_collector.cpp
-lib/triangulator.cpp
-lib/intersect_face_division.cpp
-lib/intersect_half_classify_group.cpp
-lib/edge.cpp
-lib/math.cpp
+lib/pointset.cpp
lib/geom2d.cpp
+lib/math.cpp
+lib/intersect_half_classify_group.cpp
+lib/intersect_face_division.cpp
lib/tag.cpp
-lib/intersection.cpp
-lib/convex_hull.cpp
-lib/intersect_common.hpp
-lib/intersect_classify_common_impl.hpp
-lib/csg.cpp
-lib/intersect.cpp
+lib/aabb.cpp
+lib/intersect_classify_group.cpp
lib/csg_detail.hpp
-lib/face.cpp
-lib/pointset.cpp
+lib/mesh.cpp
lib/timing.cpp
-lib/octree.cpp
-lib/aabb.cpp
-lib/intersect_debug.hpp
+lib/geom3d.cpp
+lib/intersect_group.cpp
+lib/carve.cpp
+lib/intersect_classify_edge.cpp
+lib/csg.cpp
+lib/face.cpp
+lib/csg_collector.cpp
lib/intersect_debug.cpp
+lib/edge.cpp
+lib/intersect_classify_common_impl.hpp
+lib/octree.cpp
diff --git a/extern/carve/include/carve/csg_triangulator.hpp b/extern/carve/include/carve/csg_triangulator.hpp
index 740585571bf..5a40439271e 100644
--- a/extern/carve/include/carve/csg_triangulator.hpp
+++ b/extern/carve/include/carve/csg_triangulator.hpp
@@ -174,7 +174,7 @@ namespace carve {
double scoreQuad(edge_map_t::iterator i, edge_map_t &edge_map) {
if (!(*i).second.first || !(*i).second.second) return -1;
- return 0;
+ return -1;
}
carve::mesh::MeshSet<3>::face_t *mergeQuad(edge_map_t::iterator i, edge_map_t &edge_map) {
diff --git a/extern/carve/include/carve/geom3d.hpp b/extern/carve/include/carve/geom3d.hpp
index 90d0672b81e..faeb565b922 100644
--- a/extern/carve/include/carve/geom3d.hpp
+++ b/extern/carve/include/carve/geom3d.hpp
@@ -206,9 +206,22 @@ namespace carve {
* * +1, if a is ordered after b around, rotating about direction.
*/
inline int compareAngles(const Vector &direction, const Vector &base, const Vector &a, const Vector &b) {
- const double d1 = carve::geom3d::orient3d(carve::geom::VECTOR(0,0,0), direction, a, b);
- const double d2 = carve::geom3d::orient3d(carve::geom::VECTOR(0,0,0), direction, base, a);
- const double d3 = carve::geom3d::orient3d(carve::geom::VECTOR(0,0,0), direction, base, b);
+ // double d1 = carve::geom3d::orient3d(carve::geom::VECTOR(0,0,0), direction, a, b);
+ // double d2 = carve::geom3d::orient3d(carve::geom::VECTOR(0,0,0), direction, base, a);
+ // double d3 = carve::geom3d::orient3d(carve::geom::VECTOR(0,0,0), direction, base, b);
+
+#if defined(CARVE_USE_EXACT_PREDICATES)
+ // which is equivalent to the following (which eliminates a
+ // vector subtraction):
+ double d1 = carve::geom3d::orient3d(direction, b, a, carve::geom::VECTOR(0,0,0));
+ double d2 = carve::geom3d::orient3d(direction, a, base, carve::geom::VECTOR(0,0,0));
+ double d3 = carve::geom3d::orient3d(direction, b, base, carve::geom::VECTOR(0,0,0));
+#else
+ // dotcross = a . (b x c)
+ double d1 = carve::geom::dotcross(direction, b, a );
+ double d2 = carve::geom::dotcross(direction, a, base);
+ double d3 = carve::geom::dotcross(direction, b, base);
+#endif
// CASE: a and b are coplanar wrt. direction.
if (d1 == 0.0) {
diff --git a/extern/carve/include/carve/geom_impl.hpp b/extern/carve/include/carve/geom_impl.hpp
index 4463ba2bd88..044655b6c07 100644
--- a/extern/carve/include/carve/geom_impl.hpp
+++ b/extern/carve/include/carve/geom_impl.hpp
@@ -396,7 +396,7 @@ namespace carve {
// Compute a . (b x c)
return
(a.x * b.y * c.z + a.y * b.z * c.x + a.z * b.x * c.y) -
- (a.x * b.z * c.y + a.y * b.x * c.z + a.z * b.y * c.x);
+ (a.x * c.y * b.z + a.y * c.z * b.x + a.z * c.x * b.y);
}
diff --git a/extern/carve/include/carve/input.hpp b/extern/carve/include/carve/input.hpp
index a8bc8137d6c..4223955c0fd 100644
--- a/extern/carve/include/carve/input.hpp
+++ b/extern/carve/include/carve/input.hpp
@@ -17,6 +17,9 @@
#pragma once
+#include <map>
+#include <string>
+
#include <carve/carve.hpp>
#include <carve/poly.hpp>
#include <carve/mesh.hpp>
@@ -28,6 +31,50 @@
namespace carve {
namespace input {
+ typedef std::map<std::string, std::string> Options;
+
+ static inline Options opts() {
+ return Options();
+ }
+
+ static inline Options opts(const char **kv) {
+ Options r;
+ for (size_t i = 0; kv[i] != NULL; i += 2) {
+ r[kv[i]] = kv[i+1];
+ }
+ return r;
+ }
+
+ static inline Options opts(const std::string &k1, const std::string &v1) {
+ Options r;
+ r[k1] = v1;
+ return r;
+ }
+
+ static inline Options opts(const std::string &k1, const std::string &v1,
+ const std::string &k2, const std::string &v2) {
+ Options r;
+ r[k1] = v1;
+ r[k2] = v2;
+ return r;
+ }
+
+ static inline Options opts(const std::string &k1, const std::string &v1,
+ const std::string &k2, const std::string &v2,
+ const std::string &k3, const std::string &v3) {
+ Options r;
+ r[k1] = v1;
+ r[k2] = v2;
+ r[k3] = v3;
+ return r;
+ }
+
+ static inline bool _bool(const std::string &str, bool _default = false) {
+ if (str == "true") return true;
+ if (str == "false") return false;
+ return _default;
+ }
+
struct Data {
Data() {
}
@@ -126,12 +173,18 @@ namespace carve {
faceCount = 0;
}
- carve::poly::Polyhedron *create() const {
+ carve::poly::Polyhedron *create(const Options &options) const {
return new carve::poly::Polyhedron(points, faceCount, faceIndices);
}
- carve::mesh::MeshSet<3> *createMesh() const {
- return new carve::mesh::MeshSet<3>(points, faceCount, faceIndices);
+ carve::mesh::MeshSet<3> *createMesh(const Options &options) const {
+ Options::const_iterator i;
+ carve::mesh::MeshOptions opts;
+ i = options.find("avoid_cavities");
+ if (i != options.end()) {
+ opts.avoid_cavities(_bool((*i).second));
+ }
+ return new carve::mesh::MeshSet<3>(points, faceCount, faceIndices, opts);
}
};
@@ -159,7 +212,7 @@ namespace carve {
polylines.back().second.push_back(idx);
}
- carve::line::PolylineSet *create() const {
+ carve::line::PolylineSet *create(const Options &options) const {
carve::line::PolylineSet *p = new carve::line::PolylineSet(points);
for (std::list<polyline_data_t>::const_iterator i = polylines.begin();
@@ -181,7 +234,7 @@ namespace carve {
virtual ~PointSetData() {
}
- carve::point::PointSet *create() const {
+ carve::point::PointSet *create(const Options &options) const {
carve::point::PointSet *p = new carve::point::PointSet(points);
return p;
}
@@ -214,37 +267,37 @@ namespace carve {
}
template<typename T>
- static inline T *create(Data *d) {
+ static inline T *create(Data *d, const Options &options = Options()) {
return NULL;
}
};
template<>
- inline carve::mesh::MeshSet<3> *Input::create(Data *d) {
+ inline carve::mesh::MeshSet<3> *Input::create(Data *d, const Options &options) {
PolyhedronData *p = dynamic_cast<PolyhedronData *>(d);
if (p == NULL) return NULL;
- return p->createMesh();
+ return p->createMesh(options);
}
template<>
- inline carve::poly::Polyhedron *Input::create(Data *d) {
+ inline carve::poly::Polyhedron *Input::create(Data *d, const Options &options) {
PolyhedronData *p = dynamic_cast<PolyhedronData *>(d);
if (p == NULL) return NULL;
- return p->create();
+ return p->create(options);
}
template<>
- inline carve::line::PolylineSet *Input::create(Data *d) {
+ inline carve::line::PolylineSet *Input::create(Data *d, const Options &options) {
PolylineSetData *p = dynamic_cast<PolylineSetData *>(d);
if (p == NULL) return NULL;
- return p->create();
+ return p->create(options);
}
template<>
- inline carve::point::PointSet *Input::create(Data *d) {
+ inline carve::point::PointSet *Input::create(Data *d, const Options &options) {
PointSetData *p = dynamic_cast<PointSetData *>(d);
if (p == NULL) return NULL;
- return p->create();
+ return p->create(options);
}
}
diff --git a/extern/carve/include/carve/mesh.hpp b/extern/carve/include/carve/mesh.hpp
index d4170e55133..202337b64d3 100644
--- a/extern/carve/include/carve/mesh.hpp
+++ b/extern/carve/include/carve/mesh.hpp
@@ -464,8 +464,27 @@ namespace carve {
+ struct MeshOptions {
+ bool opt_avoid_cavities;
+
+ MeshOptions() :
+ opt_avoid_cavities(false) {
+ }
+
+ MeshOptions &avoid_cavities(bool val) {
+ opt_avoid_cavities = val;
+ return *this;
+ }
+ };
+
+
+
namespace detail {
class FaceStitcher {
+ FaceStitcher();
+ FaceStitcher(const FaceStitcher &);
+ FaceStitcher &operator=(const FaceStitcher &);
+
typedef Vertex<3> vertex_t;
typedef Edge<3> edge_t;
typedef Face<3> face_t;
@@ -475,6 +494,8 @@ namespace carve {
typedef std::unordered_map<vpair_t, edgelist_t, carve::mesh::hash_vertex_pair> edge_map_t;
typedef std::unordered_map<const vertex_t *, std::set<const vertex_t *> > edge_graph_t;
+ MeshOptions opts;
+
edge_map_t edges;
edge_map_t complex_edges;
@@ -570,6 +591,8 @@ namespace carve {
void build(iter_t begin, iter_t end, std::vector<Mesh<3> *> &meshes);
public:
+ FaceStitcher(const MeshOptions &_opts);
+
template<typename iter_t>
void create(iter_t begin, iter_t end, std::vector<Mesh<3> *> &meshes);
};
@@ -623,7 +646,7 @@ namespace carve {
~Mesh();
template<typename iter_t>
- static void create(iter_t begin, iter_t end, std::vector<Mesh<ndim> *> &meshes);
+ static void create(iter_t begin, iter_t end, std::vector<Mesh<ndim> *> &meshes, const MeshOptions &opts);
aabb_t getAABB() const {
return aabb_t(faces.begin(), faces.end());
@@ -692,7 +715,7 @@ namespace carve {
MeshSet &operator=(const MeshSet &);
template<typename iter_t>
- void _init_from_faces(iter_t begin, iter_t end);
+ void _init_from_faces(iter_t begin, iter_t end, const MeshOptions &opts);
public:
typedef Vertex<ndim> vertex_t;
@@ -781,13 +804,16 @@ namespace carve {
MeshSet(const std::vector<typename vertex_t::vector_t> &points,
size_t n_faces,
- const std::vector<int> &face_indices);
+ const std::vector<int> &face_indices,
+ const MeshOptions &opts = MeshOptions());
// Construct a mesh set from a set of disconnected faces. Takes
// posession of the face pointers.
- MeshSet(std::vector<face_t *> &faces);
+ MeshSet(std::vector<face_t *> &faces,
+ const MeshOptions &opts = MeshOptions());
- MeshSet(std::list<face_t *> &faces);
+ MeshSet(std::list<face_t *> &faces,
+ const MeshOptions &opts = MeshOptions());
MeshSet(std::vector<vertex_t> &_vertex_storage,
std::vector<mesh_t *> &_meshes);
@@ -817,6 +843,8 @@ namespace carve {
void collectVertices();
void canonicalize();
+
+ void separateMeshes();
};
diff --git a/extern/carve/include/carve/mesh_impl.hpp b/extern/carve/include/carve/mesh_impl.hpp
index d55df8c8130..56fb6788b62 100644
--- a/extern/carve/include/carve/mesh_impl.hpp
+++ b/extern/carve/include/carve/mesh_impl.hpp
@@ -676,7 +676,7 @@ namespace carve {
template<unsigned ndim>
template<typename iter_t>
- void Mesh<ndim>::create(iter_t begin, iter_t end, std::vector<Mesh<ndim> *> &meshes) {
+ void Mesh<ndim>::create(iter_t begin, iter_t end, std::vector<Mesh<ndim> *> &meshes, const MeshOptions &opts) {
meshes.clear();
}
@@ -684,15 +684,15 @@ namespace carve {
template<>
template<typename iter_t>
- void Mesh<3>::create(iter_t begin, iter_t end, std::vector<Mesh<3> *> &meshes) {
- detail::FaceStitcher().create(begin, end, meshes);
+ void Mesh<3>::create(iter_t begin, iter_t end, std::vector<Mesh<3> *> &meshes, const MeshOptions &opts) {
+ detail::FaceStitcher(opts).create(begin, end, meshes);
}
template<unsigned ndim>
template<typename iter_t>
- void MeshSet<ndim>::_init_from_faces(iter_t begin, iter_t end) {
+ void MeshSet<ndim>::_init_from_faces(iter_t begin, iter_t end, const MeshOptions &opts) {
typedef std::unordered_map<const vertex_t *, size_t> map_t;
map_t vmap;
@@ -723,7 +723,7 @@ namespace carve {
} while (e != f->edge);
}
- mesh_t::create(begin, end, meshes);
+ mesh_t::create(begin, end, meshes, opts);
for (size_t i = 0; i < meshes.size(); ++i) {
meshes[i]->meshset = this;
@@ -735,7 +735,8 @@ namespace carve {
template<unsigned ndim>
MeshSet<ndim>::MeshSet(const std::vector<typename MeshSet<ndim>::vertex_t::vector_t> &points,
size_t n_faces,
- const std::vector<int> &face_indices) {
+ const std::vector<int> &face_indices,
+ const MeshOptions &opts) {
vertex_storage.reserve(points.size());
std::vector<face_t *> faces;
faces.reserve(n_faces);
@@ -755,7 +756,7 @@ namespace carve {
faces.push_back(new face_t(v.begin(), v.end()));
}
CARVE_ASSERT(p == face_indices.size());
- mesh_t::create(faces.begin(), faces.end(), meshes);
+ mesh_t::create(faces.begin(), faces.end(), meshes, opts);
for (size_t i = 0; i < meshes.size(); ++i) {
meshes[i]->meshset = this;
@@ -765,15 +766,15 @@ namespace carve {
template<unsigned ndim>
- MeshSet<ndim>::MeshSet(std::vector<face_t *> &faces) {
- _init_from_faces(faces.begin(), faces.end());
+ MeshSet<ndim>::MeshSet(std::vector<face_t *> &faces, const MeshOptions &opts) {
+ _init_from_faces(faces.begin(), faces.end(), opts);
}
template<unsigned ndim>
- MeshSet<ndim>::MeshSet(std::list<face_t *> &faces) {
- _init_from_faces(faces.begin(), faces.end());
+ MeshSet<ndim>::MeshSet(std::list<face_t *> &faces, const MeshOptions &opts) {
+ _init_from_faces(faces.begin(), faces.end(), opts);
}
@@ -1010,5 +1011,41 @@ namespace carve {
vertex_storage.swap(vout);
}
+
+
+ template<unsigned ndim>
+ void MeshSet<ndim>::separateMeshes() {
+ size_t n;
+ typedef std::unordered_map<std::pair<mesh_t *, vertex_t *>, vertex_t *> vmap_t;
+ vmap_t vmap;
+ typename vmap_t::iterator vmap_iter;
+
+ for (face_iter i = faceBegin(); i != faceEnd(); ++i) {
+ face_t *f = *i;
+ for (typename face_t::edge_iter_t j = f->begin(); j != f->end(); ++j) {
+ edge_t &e = *j;
+ vmap[std::make_pair(f->mesh, e.vert)] = e.vert;
+ }
+ }
+
+ std::vector<vertex_t> vout;
+ vout.reserve(vmap.size());
+
+ for (n = 0, vmap_iter = vmap.begin(); vmap_iter != vmap.end(); ++vmap_iter, ++n) {
+ vout.push_back(*(*vmap_iter).second);
+ (*vmap_iter).second = & vout.back();
+ }
+
+ for (face_iter i = faceBegin(); i != faceEnd(); ++i) {
+ face_t *f = *i;
+ for (typename face_t::edge_iter_t j = f->begin(); j != f->end(); ++j) {
+ edge_t &e = *j;
+ e.vert = vmap[std::make_pair(f->mesh, e.vert)];
+ }
+ }
+
+ vertex_storage.swap(vout);
+ }
+
}
}
diff --git a/extern/carve/lib/intersect.cpp b/extern/carve/lib/intersect.cpp
index b92dbcfe24c..b468e4addc7 100644
--- a/extern/carve/lib/intersect.cpp
+++ b/extern/carve/lib/intersect.cpp
@@ -1320,8 +1320,8 @@ void carve::csg::CSG::calc(meshset_t *a,
}
#endif
- checkFaceLoopIntegrity(a_face_loops);
- checkFaceLoopIntegrity(b_face_loops);
+ // checkFaceLoopIntegrity(a_face_loops);
+ // checkFaceLoopIntegrity(b_face_loops);
#if defined(CARVE_DEBUG)
std::cerr << "classify" << std::endl;
diff --git a/extern/carve/lib/intersect_face_division.cpp b/extern/carve/lib/intersect_face_division.cpp
index c74b52dd557..75f7f790df6 100644
--- a/extern/carve/lib/intersect_face_division.cpp
+++ b/extern/carve/lib/intersect_face_division.cpp
@@ -719,6 +719,10 @@ namespace {
unassigned--;
}
}
+
+ if (!removed.size())
+ throw carve::exception("Failed to merge holes");
+
for (std::set<int>::iterator f = removed.begin(); f != removed.end(); ++f) {
for (unsigned i = 0; i < containing_faces.size(); ++i) {
containing_faces[i].erase(std::remove(containing_faces[i].begin(),
@@ -1107,7 +1111,7 @@ namespace {
// copy up to the end of the path.
if (pos < e1_1)
- std::copy(base_loop.begin() + pos, base_loop.begin() + e1_1, std::back_inserter(out));
+ std::copy(base_loop.begin() + pos, base_loop.begin() + e1_1, std::back_inserter(out));
CARVE_ASSERT(base_loop[e1_1] == p1.back());
std::copy(p1.rbegin(), p1.rend() - 1, std::back_inserter(out));
diff --git a/extern/carve/lib/mesh.cpp b/extern/carve/lib/mesh.cpp
index 55ab893c10a..ae91b385d44 100644
--- a/extern/carve/lib/mesh.cpp
+++ b/extern/carve/lib/mesh.cpp
@@ -243,15 +243,20 @@ namespace carve {
bool FaceStitcher::EdgeOrderData::Cmp::operator()(const EdgeOrderData &a, const EdgeOrderData &b) const {
int v = carve::geom3d::compareAngles(edge_dir, base_dir, a.face_dir, b.face_dir);
- double da = carve::geom3d::antiClockwiseAngle(base_dir, a.face_dir, edge_dir);
- double db = carve::geom3d::antiClockwiseAngle(base_dir, b.face_dir, edge_dir);
- int v0 = v;
- v = 0;
- if (da < db) v = -1;
- if (db < da) v = +1;
- if (v0 != v) {
- std::cerr << "v0= " << v0 << " v= " << v << " da= " << da << " db= " << db << " " << edge_dir << " " << base_dir << " " << a.face_dir << b.face_dir << std::endl;
+
+#if defined(CARVE_DEBUG)
+ {
+ double da = carve::geom3d::antiClockwiseAngle(base_dir, a.face_dir, edge_dir);
+ double db = carve::geom3d::antiClockwiseAngle(base_dir, b.face_dir, edge_dir);
+ int v_cmp = 0;
+ if (da < db) v_cmp = -1;
+ if (db < da) v_cmp = +1;
+ if (v_cmp != v) {
+ std::cerr << "v= " << v << " v_cmp= " << v_cmp << " da= " << da << " db= " << db << " edge_dir=" << edge_dir << " base_dir=" << base_dir << " a=" << a.face_dir << " b=" << b.face_dir << std::endl;
+ }
}
+#endif
+
if (v < 0) return true;
if (v == 0) {
if (a.is_reversed && !b.is_reversed) return true;
@@ -327,9 +332,14 @@ namespace carve {
CARVE_ASSERT(erev[0][i]->v2() == erev[j][i]->v2());
}
- std::sort(result[i].begin(),
- result[i].end(),
- EdgeOrderData::Cmp(base->v2()->v - base->v1()->v, result[i][0].face_dir));
+ geom::vector<3> sort_dir;
+ if (opts.opt_avoid_cavities) {
+ sort_dir = base->v1()->v - base->v2()->v;
+ } else {
+ sort_dir = base->v2()->v - base->v1()->v;
+ }
+
+ std::sort(result[i].begin(), result[i].end(), EdgeOrderData::Cmp(sort_dir, result[i][0].face_dir));
}
}
@@ -751,11 +761,15 @@ namespace carve {
}
}
}
+
+ FaceStitcher::FaceStitcher(const MeshOptions &_opts) : opts(_opts) {
+ }
}
}
+
// construct a MeshSet from a Polyhedron, maintaining on the
// connectivity information in the Polyhedron.
mesh::MeshSet<3> *meshFromPolyhedron(const poly::Polyhedron *poly, int manifold_id) {
diff --git a/extern/carve/lib/polyhedron.cpp b/extern/carve/lib/polyhedron.cpp
index 93e667ffaf7..43d08b81bfd 100644
--- a/extern/carve/lib/polyhedron.cpp
+++ b/extern/carve/lib/polyhedron.cpp
@@ -233,7 +233,7 @@ namespace carve {
}
std::vector<mesh::Mesh<3> *> meshes;
- mesh::Mesh<3>::create(mesh_faces.begin(), mesh_faces.end(), meshes);
+ mesh::Mesh<3>::create(mesh_faces.begin(), mesh_faces.end(), meshes, mesh::MeshOptions());
mesh::MeshSet<3> *meshset = new mesh::MeshSet<3>(vertex_storage, meshes);
manifold_is_closed.resize(meshset->meshes.size());
diff --git a/extern/carve/patches/series b/extern/carve/patches/series
index 585d90659bd..0b1f731805e 100644
--- a/extern/carve/patches/series
+++ b/extern/carve/patches/series
@@ -1,4 +1,3 @@
-strict_flags.patch
includes.patch
win32.patch
mesh_iterator.patch
diff --git a/extern/carve/patches/strict_flags.patch b/extern/carve/patches/strict_flags.patch
deleted file mode 100644
index c1046b78c5f..00000000000
--- a/extern/carve/patches/strict_flags.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-diff -r 47dfdaff1dd5 include/carve/csg_triangulator.hpp
---- a/include/carve/csg_triangulator.hpp Thu Jan 12 15:49:04 2012 -0500
-+++ b/include/carve/csg_triangulator.hpp Fri Jan 13 03:13:32 2012 +0600
-@@ -174,6 +174,7 @@
-
- double scoreQuad(edge_map_t::iterator i, edge_map_t &edge_map) {
- if (!(*i).second.first || !(*i).second.second) return -1;
-+ return 0;
- }
-
- carve::mesh::MeshSet<3>::face_t *mergeQuad(edge_map_t::iterator i, edge_map_t &edge_map) {
-diff -r 47dfdaff1dd5 lib/selfintersect.cpp
---- a/lib/selfintersect.cpp Thu Jan 12 15:49:04 2012 -0500
-+++ b/lib/selfintersect.cpp Fri Jan 13 03:13:32 2012 +0600
-@@ -465,6 +465,7 @@
-
- // returns true if no intersection, based upon edge^a_i and edge^b_j separating axis.
- bool sat_edge(const vec3 tri_a[3], const vec3 tri_b[3], unsigned i, unsigned j) {
-+ return false;
- }
-
-
diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt
index ebc5953d956..a4910d94a37 100644
--- a/extern/libmv/CMakeLists.txt
+++ b/extern/libmv/CMakeLists.txt
@@ -28,14 +28,11 @@
set(INC
.
- ../colamd/Include
third_party/ceres/include
)
set(INC_SYS
../Eigen3
- third_party/ssba
- third_party/ldl/Include
${PNG_INCLUDE_DIR}
${ZLIB_INCLUDE_DIRS}
)
@@ -47,9 +44,9 @@ set(SRC
libmv/multiview/conditioning.cc
libmv/multiview/euclidean_resection.cc
libmv/multiview/fundamental.cc
+ libmv/multiview/homography.cc
libmv/multiview/projection.cc
libmv/multiview/triangulation.cc
- libmv/multiview/homography.cc
libmv/numeric/numeric.cc
libmv/numeric/poly.cc
libmv/simple_pipeline/bundle.cc
@@ -62,7 +59,6 @@ set(SRC
libmv/simple_pipeline/pipeline.cc
libmv/simple_pipeline/reconstruction.cc
libmv/simple_pipeline/resect.cc
- libmv/simple_pipeline/rigid_registration.cc
libmv/simple_pipeline/tracks.cc
libmv/tracking/brute_region_tracker.cc
libmv/tracking/esm_region_tracker.cc
@@ -71,8 +67,8 @@ set(SRC
libmv/tracking/lmicklt_region_tracker.cc
libmv/tracking/pyramid_region_tracker.cc
libmv/tracking/retrack_region_tracker.cc
- libmv/tracking/trklt_region_tracker.cc
libmv/tracking/track_region.cc
+ libmv/tracking/trklt_region_tracker.cc
third_party/fast/fast_10.c
third_party/fast/fast_11.c
@@ -83,9 +79,6 @@ set(SRC
third_party/gflags/gflags.cc
third_party/gflags/gflags_completions.cc
third_party/gflags/gflags_reporting.cc
- third_party/ldl/Source/ldl.c
- third_party/ssba/Geometry/v3d_metricbundle.cpp
- third_party/ssba/Math/v3d_optimization.cpp
libmv-capi.h
libmv/base/id_generator.h
@@ -105,6 +98,7 @@ set(SRC
libmv/multiview/homography.h
libmv/multiview/homography_parameterization.h
libmv/multiview/nviewtriangulation.h
+ libmv/multiview/panography.h
libmv/multiview/projection.h
libmv/multiview/resection.h
libmv/multiview/triangulation.h
@@ -123,7 +117,6 @@ set(SRC
libmv/simple_pipeline/pipeline.h
libmv/simple_pipeline/reconstruction.h
libmv/simple_pipeline/resect.h
- libmv/simple_pipeline/rigid_registration.h
libmv/simple_pipeline/tracks.h
libmv/tracking/brute_region_tracker.h
libmv/tracking/esm_region_tracker.h
@@ -143,16 +136,8 @@ set(SRC
third_party/gflags/gflags/gflags.h
third_party/gflags/mutex.h
third_party/gflags/util.h
- third_party/ldl/Include/ldl.h
third_party/msinttypes/inttypes.h
third_party/msinttypes/stdint.h
- third_party/ssba/Geometry/v3d_cameramatrix.h
- third_party/ssba/Geometry/v3d_distortion.h
- third_party/ssba/Geometry/v3d_metricbundle.h
- third_party/ssba/Math/v3d_linear.h
- third_party/ssba/Math/v3d_linear_utils.h
- third_party/ssba/Math/v3d_mathutilities.h
- third_party/ssba/Math/v3d_optimization.h
)
if(WIN32)
@@ -191,14 +176,6 @@ if(WIN32)
third_party/msinttypes
)
endif()
-
- if(MSVC)
- set(MSVC_OFLAGS O1 O2 Ox)
- foreach(FLAG ${MSVC_OFLAGS})
- string(REPLACE "${FLAG}" "Od" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
- string(REPLACE "${FLAG}" "Od" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
- endforeach()
- endif()
else()
list(APPEND SRC
third_party/glog/src/demangle.cc
@@ -238,7 +215,6 @@ else()
endif()
add_definitions(
- -DV3DLIB_ENABLE_SUITESPARSE
-DGOOGLE_GLOG_DLL_DECL=
)
diff --git a/extern/libmv/ChangeLog b/extern/libmv/ChangeLog
index 02b79c93ec2..a4f25f83a1c 100644
--- a/extern/libmv/ChangeLog
+++ b/extern/libmv/ChangeLog
@@ -1,556 +1,800 @@
-commit b813dbe3f46bbbc7e73ac791d4665622e4fc7ba5
+commit 473996468a4e67e7c860169181a4ff31ce9b8c80
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Wed May 9 19:01:10 2012 +0600
+Date: Fri Mar 1 17:44:54 2013 +0600
- Modal solver: Detect rigid transformation between initial frame and current
- instead of detecting it between two neighbour frames.
-
- This prevents accumulation of error and seems to be working better in footages i've tested.
+ Fixed incorrect order of arguments passing
+ to EXPECT_EQ in keyframe selection tests.
-commit 9254621c76daaf239ec1f535e197ca792eea97b6
+commit d38ebb74693fdf5b8f0fecf62a3d8c9c53b0b84a
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Wed May 9 18:57:00 2012 +0600
+Date: Fri Mar 1 17:40:38 2013 +0600
- Backport changes made by Keir in Blender:
+ Modal (aka tripod) solver rework
- - Enhance logging in libmv's trackers.
- - Cleanups in brute_region_tracker.cc.
+ Several major things are done in this commit:
+
+ - First of all, logic of modal solver was changed.
+ We do not rely on only minimizer to take care of
+ guessing rotation for frame, but we're using
+ analytical rotation computation for point clouds
+ to obtain initial rotation.
+
+ Then this rotation is being refined using Ceres
+ minimizer and now instead of minimizing average
+ distance between points of point of two clouds,
+ minimization of reprojection error of point
+ cloud onto frame happens.
+
+ This gives quite a bit of precision improvement.
+
+ - Second bigger improvement here is using bundle
+ adjustment for a result of first step when we're
+ only estimating rotation between neighbor images
+ and reprojecting markers.
+
+ This averages error across the image sequence
+ avoiding error accumulation. Also, this will
+ tweak bundles themselves a bit for better match.
+
+ - And last bigger improvement here is support of
+ camera intrinsics refirenment.
+
+ This allowed to significantly improve solution
+ for real-life footage and results after such
+ refining are much more usable than it were before.
+
+ Thanks to Keir for the help and code review!
-commit d9c56b9d3c63f886d83129ca0ebed1e76d9c93d7
+commit 5d6c2e7a27bdd1a1b23bf289d70a9b8f62514c9a
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Apr 27 16:20:41 2012 +0600
+Date: Fri Mar 1 17:37:35 2013 +0600
- Fixes for MinGW64 support by Caleb Joseph with slight modifications by Antony Riakiotakis
+ Increase verbosity level for reprojected markers info
- - Functions snprintf and sincos shouldn't be redefined for MinGW64
- - Type pid_t shouldn't be re-defined for MinGW64
+ This information is useful, but in cases when you, say,
+ working on a bundler it's annoying to scroll all the
+ information up.
-commit e1902b6938676011607ac99986b8b140bdbf090e
+commit ac252bb1250b3028b9c94736b644e7ab4e7b14b8
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Apr 27 16:04:19 2012 +0600
+Date: Fri Mar 1 17:36:19 2013 +0600
- Fixes for Qt calibration tool
+ Move radial distortion code to own templated function
- - Passing directory with images via command line argument now isn't
- required -- it there's no such directory specified standard open
- dialog might be used for this (before application used to abort
- due to accessing to non-existing list element).
- - Conversion of source images to grayscale now happens correct.
- It was needed to build grayscale palette for 8bit indexed buffer.
+ This shall not lead to any functional changes, just
+ avoids radial distortion code duplicated in camera
+ intrinsics and bundling code.
+
+ For fancier bundle adjustment support of different
+ distortion models this is not actually enough and
+ would need to make some bigger changes, but this
+ changes makes code a bit easier to maintain already.
-commit 05f1a0a78ad8ff6646d1e8da97e6f7575b891536
+commit c253b794612dd529e1d3a9bd7a7c41c32c9a9abb
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Sat Apr 14 17:21:29 2012 +0600
+Date: Fri Mar 1 17:33:27 2013 +0600
- Make QtTracker compilable again porting it to recent API change and code cleanup:
+ Use threaded cost function, jacobian and linear solver
+ computation, so bundling is as fast as it could be with
+ current parameter block structure.
+
+commit 931fe37a10212b91b525d4f6eb753990a338b471
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Fri Mar 1 17:29:21 2013 +0600
+
+ Fixed comment for euclidean bundling,
+ which is now supports raidal bundling independently
+ from other intrinsics.
+
+commit 217d8e6edc3de1a853fb84275d2d2dd898e7529c
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Tue Feb 26 18:19:01 2013 +0600
+
+ Allow K1,K2 refirement combination
- - It was using SAD tracker with own API, now it's using standard RegionTracker API
- which should make it easier to switch between different trackers.
- - Restored LaplaceFilter from old SAD module which convolves images with the
- discrete laplacian operator.
+ It is now possible to refine only radial distortion
+ with new Ceres based bundler and this new combination
+ is already used in Blender.
-commit a44312a7beb2963b8e3bf8015c516d2eff40cc3d
+commit d8850addc944d400f7a9c358396c437d9e4acc70
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Thu Apr 12 13:56:02 2012 +0600
+Date: Tue Feb 26 18:17:09 2013 +0600
- Added solver for modal camera motion, currently supports only tripod solving
+ Switch euclidean intersection code to use Ceres
- This solver is intended to deal with such camera motions as tripod and panning,
- where it's impossible to reconstruct exact position of markers in 3d view.
+ Would not expect any significant changes in solver
+ behavior, but it could be more accurate in some cases.
- It projects markers onto sphere and uses rigid registration of rotation to
- find rotation angles which makes bundles from previous and current frame be
- as closest as it's possible.
+ Switching projective intersection to ceres is marked
+ as a TODO for now.
-commit fa3842e472e3b9c789e47bf6d8f592aa40a84f16
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Thu Apr 12 12:32:48 2012 +0600
+commit 6990b7946ec96b3cb2dcfc8a1beaaba9538b0802
+Author: Keir Mierle <mierle@gmail.com>
+Date: Mon Feb 25 20:00:48 2013 +0000
- implementation of some basic algorithms for point cloud orientation:
+ Switch motion tracker bundle adjustment to Ceres.
- - Implementation of rigid registration algorithm which searches transformation
- form one point cloud to another assuming that points in this clouds are
- already paired (points with the same index in different clouds belongs to
- the same pair) which minimizes average distance between points in pairs.
+ Patch originally written by me, then finished by Sergey. Big
+ thanks to Sergey for troopering through and fixing the many issues
+ with my original (not compilable) patch.
- Algorithm uses Levenberg-Marquardt solver to find such transformation.
+ The Ceres implementation uses 2 parameter blocks for each camera
+ (1 for rotation and 1 for translation), 1 parameter block for
+ common intrinsics (focal length etc) and 1 parameter block for
+ each track (e.g. bundle or 3D point).
- Supports registration of rotation-scale-transform (which is probably most
- common usage) and rotation only (which might be useful for basic modal
- tripod solver).
+ We turn on some fancy optimizer options to get better performance,
+ in particular:
- - Implementation of Iterative-Point-Clouds algorithm which searches
- transformation from one arbitrary point cloud to another making
- points as closest to each other as possible.
+ options.preconditioner_type = ceres::SCHUR_JACOBI;
+ options.linear_solver_type = ceres::ITERATIVE_SCHUR;
+ options.use_inner_iterations = true;
+ options.use_nonmonotonic_steps = true;
+ options.max_num_iterations = 100;
- This algorithm doesn't require points be initially paired, but for
- good result clouds should have rough initial orientation. If they're
- arbitrary oriented from the very beginning, algorithm might fail
- producing good resold.
+ Special thanks to Sameer Agarwal of Ceres fame for splitting out
+ the SCHUR_JACOBI preconditioner so that it didn't depend on
+ CHOLMOD. Previously we could not use that preconditioner in
+ Blender because CHOLMOD is too large of a dependency for Blender.
- Iteration is based on building pairs of closest to each other points
- and registering rigid transformation between them which incrementally
- constructs final result.
+ BundleIntrinsicsLogMessage:
+ - Moved bunch of if(foo) LG << "bar" into this function, to make
+ EuclideanBundleCommonIntrinsics a little bit easier to follow.
- TODO: building pairs might be speedup a lot using data structures like
- AABB trees, K-D trees or so.
+ EuclideanBundle:
+ - Fix RMSE logging.
-commit 9618d9a1d48bb3c28da605d9027f57a74f462785
+commit 1696342954614b54133780d74d6ee0fbcbe224f0
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Wed Apr 11 14:17:14 2012 +0600
+Date: Tue Feb 26 18:10:33 2013 +0600
- Added configuration file for glog to compile smooth on Hurd platform.
+ Upgrade ceres to latest upstream version
- Patch by Pino Toscano <pino@debian.org>, thanks!
+ This is needed because of some features of new Ceres
+ for further development.
-commit 63b2bd20237c8599fa73ce42556e4fb99b9f7cca
+commit 575336f794841ada90aacd783285014081b8318c
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Thu Mar 22 17:03:34 2012 +0600
+Date: Mon Jan 7 15:58:40 2013 +0600
- Trackers refactoring:
- - Deduplicate pattern sampling used in esm and lmicklt trackers
- and move SamplePattern to image/sample.h
- - Move computation of Pearson product-moment correlation into
- own function in new file image/correlation.h so all trackers
- can use it to check final correlation.
- - Remove SAD tracker. It's almost the same as brute tracker,
- with only two differences:
- 1. It does brute search of affine transformation which in some cases
- helps to track rotating features
- 2. It didn't use common tracker api which probably gave some speed
- advantage, but lead to a real headache to use it together with
- other trackers leading to duplicated code in 3d-party software.
+ Fixed for keyframe selection
+
+ - Calculate residuals for GRIC in pixel space rather than
+ in normalized space.
+
+ This seems to be how it's intended to be used.
+
+ Algebraic H and F will still use normalized coordinates which
+ are more stable, after this matrices are converted to pixel
+ space and Ceres refinement happens in pixel space.
+
+ - Standard deviation calculation was wrong in GRIC. It shouldn't
+ be deviation of residuals, but as per Torr it should be deviation
+ of measurement error, which is constant (in our case 0.1)
+
+ Not sure if using squared cost function is correct for GRIC,
+ but cost function is indeed squared and in most papers cost
+ function is used for GRIC. After some further tests we could
+ switch GRIC residuals to non-squared distance.
+
+ - Bring back rho part of GRIC, in unit tests it doesn't make
+ sense whether it's enabled or not, lets see how it'll behave
+ in real-life footage.
+
+ - Added one more unit test based on elevator scene and manual
+ keyframe selection.
-commit 9fe49c32e990f28c83f2bbb1d18057aed8879af7
+commit 24117f3c3fc5531beb6497d79bb6f1780a998081
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Mon Mar 12 09:36:15 2012 +0600
+Date: Sun Jan 6 19:07:06 2013 +0600
- Code cleanup: convert line endings to Unix style (native on my platform) so it
- wouldn't confuse other versioning systems used for project where libmv is bundled to,
+ Added test for keyframe selection based on manual selection
- Also change mode to +x for glog's windows-related script.
-
-commit fe74ae2b53769389b0ed9d7e604c8e60be81077d
-Author: Sergey I. Sharybin <g.ulairi@gmail.com>
-Date: Sun Mar 11 20:34:15 2012 +0600
-
- Replace "third_party/glog/src/glog/logging.h" with <glog/logging.h>
+ Additional changes:
- It was needed because of how build systems is setup in Blender but think
- this will be helpful change for other applications too because it makes
- it's easier to move libraries around and even use libraries installed
- on the operation system.
+ - Reduce minimal correspondence to match real-world manually
+ tracked footage
+
+ - Returned back squares to SymmetricEpipolarDistance and
+ SymmetricGeometricDistance -- this is actually a cost
+ functions, not distances and they shall be squared.
-commit 37fc726701479f2d321d6af878fa93f3176278d5
-Author: Sergey I. Sharybin <g.ulairi@gmail.com>
-Date: Sun Mar 11 19:27:41 2012 +0600
+commit 770eb0293b881c4c419c587a6cdb062c47ab6e44
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Fri Dec 21 00:43:30 2012 +0600
- Upgrade gflags and glog libraries - stage 2 (final)
+ Improvements for keyframe selection
- Changes to upstream code which are needed to make libmv compile smooth on all platforms
+ - Changed main keyframe selection cycle, so in cases there're no
+ more next keyframes for current keyframe could be found in the
+ image sequence, current keyframe would be moved forward and
+ search continues.
- * Replace <gflags/gflags.h> with "third_party/gflags/gflags/gflags.h" which is easier
- to setup things in libmv and also helps with setting up building libmv into
- external applications.
- * Replace "glog/logging.h" and "glog/logging.h" with <glog/logging.h> and <glog/logging.h>
- which is needed on Windows platform because otherwise files like logging.cc will be using
- relative path which points to headers used by linux instead of headers need to be used
- on Windows.
- * Replace _asm int 3 with __debugbreak(). Such assembler code is obsolete and doesn't work
- with 64bit versions of MSVC compilers.
- * Do not use stacktrace for MinGW and FreeBSD because it leads into issues accessing
- some specific data on this platforms.
- * Define HAVE_LIB_GFLAGS for Windows builds.
- * Do not define __declspec(dllimport) for MinGW platforms.
- * Setup proper includes and datatypes for int32, uint32, int64 and uint64 for MinGW
- * Do not define va_copy for MinGW platforms (it's already defined there).
- * Patch localtime_r to be working fine with MinGW, disable strerror_r for MinGW because
- of lack of needed functions.
-
-commit 8ed07abfa49d1e0511752021c972e0715e5a1383
-Author: Sergey I. Sharybin <g.ulairi@gmail.com>
-Date: Sun Mar 11 19:06:33 2012 +0600
-
- Upgrade gflags and glog libraries - stage 1
+ This helps in cases when there's poor motion in the beginning
+ of the sequence, then markers becomes occluded. There could be
+ good keyframes in the middle of the shot still.
- This commit copies sources from latest original release of gflags and glog
- over currently bundled versions of this libraries without any modifications.
+ - Extended keyframe_selection_test with real world cases.
- This revision can't b compiled, all needed changes to make new libraries working
- fine will be done with next commit to make it clear which changes were necessary
- for easier bundling further newer version and extract patches and put them to
- gflags/glog upstream repo.
+ - Moved correspondences constraint to the top, so no H/F estimation
+ happens if there's bad correspondence. Makes algorithm go a bit
+ faster.
- Such upgrade of libraries is needed to make it able to compile libmv
- with clang compilers. Currently used versions:
+ Strangely, but using non-squared distances makes neighbor frames
+ test fail, using squared distances makes this tests pass.
- - gflags is version 2.0
- - glog is version 0.3.2
+ However, using non-squared distances seems to be working better
+ in real tests i've been doing. So this requires more investigation/
-commit 75b9af405964ff2c7d3f0a44500e27e63b37c91b
+commit 7415c62fbda36c5bd1c291bc94d535a66da896d0
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 23:29:11 2012 +0600
+Date: Thu Dec 20 18:46:09 2012 +0600
- _USE_MATH_DEFINES is needed to define constants like M_E when building with msvc
- Occasionally was removed, but now added comment about this so hopefully it
- wouldn't removed again.
+ Cosmetic change to correspondences reports in keyframe selection
-commit f85b1232a9b929f69443b5eed6e7a39908cd6551
+commit ceaf80c987ec0338e7e83965bc808411453eb755
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 21:34:40 2012 +0600
+Date: Thu Dec 20 18:08:03 2012 +0600
- Picky edit: corrected mode for ssba readme file.
+ Various fixes:
+
+ - That was a typo in symmetric geometric cost functor, which
+ computed inverse distance in a wrong way.
+
+ - Fixed compilation of unit tests
+
+ - Added simple test for keyframe selection. Currently only
+ covers case that neighbor frames with only translation
+ (homography should be better than fundamental) are not
+ considered a keyframes.
+
+ Still need to be investigated why it only works if tracks
+ are in pixel space and why doesn't work in normalized space.
-commit f8c2b223f01551fd81a85f6d5221646165147035
+commit cfabdfe48df2add3d1f30cf4370efd0b31990ab0
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 21:32:05 2012 +0600
+Date: Thu Dec 20 05:46:53 2012 +0600
- Picky edits: corrected EOL
+ Assorted fixes for keyframe selection:
+
+ - Biggest error was in cost functors used for F and H refirement,
+ they were just wrong.
+
+ - Use natural logarithms, since it's actually makes sense from
+ math papers point of view and error is somewhere else.
+
+ - Disabled rho for GRIC, for now use non-clamped error for tests.
+
+ - Made SymmetricEpipolarDistance returning non-squared distance
+ Keyframe selection is currently the only used of this function
+ and it seems using non-squared distance makes much more sense.
+
+ Also would think to append suffix "Squared" to functions which
+ returns squared distances.
+
+ - Removed templated version of SymmetricEpipolarDistance, since
+ it's not needed actually.
+
+ This is actually even worse working than previous implementation,
+ but commit it needed for further review.
-commit 3f2a4205ec5adadcdfa306b161c705c868a7be93
+commit 35d8c57626ad74818f155e6e5960c663ea84e032
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 21:30:07 2012 +0600
+Date: Thu Dec 20 03:00:40 2012 +0600
- Fixed incorrect access to ucontext on linux. Caused by incorrect merge conflict resolve.
+ Euclidean resection cost function didn't use correct constructor
+
+ It was storing a reference to initial rotation passed by value,
+ leading to pointer being pointing to a stack variable, leading to
+ wrong memory access in residuals computing.
+
+ Apparently was visible in optimized builds only with inline
+ substitution allowed.
-commit d360a21a5aa125cf9e83dd26b302508688ff7007
+commit 0798d3162bb49cee7e1c423ceccbca1326ad5650
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 20:54:13 2012 +0600
+Date: Thu Dec 20 02:50:52 2012 +0600
- More Windows -> Unix EOL conversions
+ Automatic keyframe selection based on Pollefeys's criteria
+
+ This commit implements automatic keyframe selection algorithm
+ based on Pollefeys's criteria (F-GRIC is smaller than H-GRIC
+ and correspondence ratio is more then 90%).
+
+ It is implemented as a part of simple pipeline and returns
+ vector of keyframe images for a given Tracks structure.
+
+ For simple pipeline reconstruction two best keyframes are
+ expected to be selected from all detected candidates.
+ Criteria for this selection could be reprojection error of
+ solution from two candidate keyfames.
+
+ Unfortunately, it's not fully workable yet, hopefully would
+ be fixed soon.
-commit 18aeda58bec9556140ba617724e31ada6f5b67c0
+commit e943985552f0598ae122252876f305d72c25c2f9
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 20:15:42 2012 +0600
+Date: Thu Dec 6 17:47:11 2012 +0600
- Looks like this debug output was removed accidentally.
+ Camera Tracking: allow fallback to reprojection resection
+ by user demand
+
+ This fixes some "regressions" introduced in previous commit
+ which lead to much worse solution in some cases. Now it's
+ possible to bring old behavior back.
+
+ Perhaps it's more like temporal solution for time being smarter
+ solution is found. But finding such a solution isn't so fast,
+ so let's bring manual control over reprojection usage.
+
+ But anyway, imo it's now nice to have a structure which could
+ be used to pass different settings to the solver.
-commit 189dc0cacdee3c1eab68c43263ecb038ed244c09
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 20:11:56 2012 +0600
+commit 5a23d01dd531d1e0798298d17ba42a3397effb82
+Author: Keir Mierle <mierle@gmail.com>
+Date: Thu Sep 20 18:55:44 2012 +0000
- Made V3D verbose again by default
+ Make Euclidean resection "always" succeed.
+
+ The Euclidean resection code had a magical constant, 1e-3, used to
+ compare the results of solving an equation. This failure detection
+ was well-intended, trying to prevent poor solutions from getting
+ made without notifying the caller. Unfortunately in practice, this
+ threshold is too conservative. Furthermore, it is not clear the
+ threshold should exist at all; the purpose of the Euclidean
+ resection is to come up with the best solution it can; other
+ methods (e.g. reprojection error) should be used to compare
+ whether the method succeeded.
+
+ This commit changes the Euclidean EPnP code to always succeed,
+ causing the previous fallback to projective resection to never
+ run. In most cases, this will result in better reconstructions.
+
+ This should, in most cases, fix the dreaded "flipping" problem.
-commit 8b3422d3eec5e450d76243886bf07fb0a3e83a81
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 20:08:01 2012 +0600
+commit 57dad861d2a7f9d058c6d8edde1a2d51d7225a51
+Author: Keir Mierle <mierle@gmail.com>
+Date: Thu Sep 20 02:27:34 2012 +0000
- SAD tracker now can deal with pattern size any size,
- Very quick implementation came from Blender before Hybrid tracker was added.
- Better to be replaced with brute tracker.
+ Fix variable naming in the planar tracker.
-commit d547c9cfe37d5d3397d33c8b0e58471e1e1c1634
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 20:03:52 2012 +0600
+commit e9392fd3b46f5668662935696e7d9afac3390ca4
+Author: Keir Mierle <mierle@gmail.com>
+Date: Thu Sep 20 02:10:33 2012 +0000
+
+ Add smarter tolerance checking in the planar tracker.
+
+ The planar tracker uses Ceres for the refinement stage. During
+ refinement, Ceres iteratively updates the parameters with the
+ latest best guess. If the change in the parameters falls below a
+ threshold, Ceres will abort successfully ("converged").
+
+ For the case of pure translation tracking, the parameters are
+ exactly the two pixel shifts (dx, dy), and measuring the change in
+ these parameters gives a meaningful termination criterion.
+ However, for all the other parameterizations like affine, where
+ the parameterization involves affine parameters that have no
+ physical interpretation, Ceres is left with no way to terminate
+ the solver early. With the existing code, often many iterations
+ are run long after Ceres has found a solution sufficiently
+ accurate for all tracking needs. No one needs tracking with
+ a quadrillionth of a pixel accuracy; that time is wasted.
+
+ This patch extends the existing iteration callback that is passed
+ in to Ceres to check if the pattern has fallen out of the search
+ window, to also check if the optimizer has made a tiny step. In
+ particular, if the maximum shift of any patch corner between two
+ successful optimizer steps is less than a threshold (currently
+ 0.005 pixels), the track is declared successful and tracking
+ is terminated.
+
+ This leads to dramatic speed increases in some cases, with little
+ to no loss in track quality. This is especially apparent when
+ tracking patches with affine or perspective motion models. For
+ example, on some tracking cases I tried, the iterations Ceres took
+ went from 50 to 3.
+
+commit 36729c19bf90cb767e9adb96ba7dd48a5ace2be1
+Author: Keir Mierle <mierle@gmail.com>
+Date: Wed Sep 19 22:25:02 2012 +0000
- Just convert end of lines to unix style.
+ Detect too-small planar tracking patches.
+
+ The planar tracker did not detect very skinny patches which have
+ effectively zero area and are untrackable. This adds detection and
+ rejection of patterns with zero area. This fixes a crash found by
+ during Mango production.
-commit eb73ddbaec5b9e1ad30331bbf858a6ebc266c4aa
+commit 5cf2bae255a5a0f2e36ea0516670782cb88b589d
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 20:02:20 2012 +0600
+Date: Thu Dec 6 17:33:53 2012 +0600
- Made some function static. Resolves possible linking issues when building with MinGW.
+ Real fix for previous commit from Keir. He's comment;
+
+ Cleanup for when trackers fall out of the search window.
+
+ Sergey originally left a TODO() here, but his fix is the correct
+ one. I removed the TODO and fixed some comment issues.
-commit 2930681fafd86e4f4a958054b1db8bfff29623d1
+commit a11533918720e5b43dc1e95895db0eb36c8c06aa
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 19:59:45 2012 +0600
+Date: Thu Dec 6 17:31:16 2012 +0600
- Missed this in commit with improvements in camera intrinsics.
+ Fix crash when tracking in planar motion model (and maybe some other)
+
+ It was an Abort() caused by check for solver result not equal to USER_ABORT.
+
+ In some cases solver returns USER_ABORT due to BoundaryCheckingCallback
+ detects coordinates does not belong to image.
+
+ Somehow this callback wasn't called in previous version of Ceres and
+ in the same case marker was jumping. Now when the callback is called
+ it seems we could simply return failure of tracking without aborting
+ Blender.
+
+ Probably this is in fact some issue somewhere else, would double
+ check with Keir about this.
-commit 8d31bc767019b05c5bf8c9f309f9545b3428afa1
+commit 4be2306bcc664b259aaf7068b9f32ab60124a509
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 19:57:51 2012 +0600
+Date: Thu Dec 6 17:29:39 2012 +0600
- Another step of syncing codebase with Blender.
- Mainly fixes for freebsd/osx compilation and aligned memory allocation.
+ Resolved some compilation warnings (missed prototypes)
+
+ In some cases it was missed include of header file, in some other
+ cases symbol could be static.
-commit 3214a2df5bfd98021f25d0f1a626a86318bb245f
+commit bef729ba5c12683d13584d2a728b8b6506b7ca90
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 19:48:02 2012 +0600
+Date: Thu Dec 6 17:27:17 2012 +0600
- Support compilation on FreeBSD platform
+ Code cleanup: silence some -Wnarrowing warnings from C++11
-commit 0e5abe96f543687ccfb3a923ec639cb8f45d54f8
+commit add1415d896818367087c784a3013dd8f1bb2095
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 19:44:18 2012 +0600
+Date: Thu Dec 6 17:25:18 2012 +0600
- Implementation of basic system for progress reporting into callee stuff
-
- Implemented by using simple callbacks classes which are getting invoked from
- places where lots of calculation happens, so applications which are using
- libmv may display nice progress bar.
+ Changes to SamplePlanarPatch to support mask input and
+ added output for pattern center.
-commit c5e18fe35464618055e0e9761be8d22fae56db49
+commit daa354c0735b954b0cd7725626e9a3d67416d46b
Author: Keir Mierle <mierle@gmail.com>
-Date: Fri Feb 17 19:25:45 2012 +0600
+Date: Sat Jun 9 19:22:39 2012 +0000
- Add support for detecting tracking failure in the ESM tracker component of
- libmv. Since both KLT and Hybrid rely on ESM underneath, KLT and Hybrid now
- have a minimum correlation setting to match. With this fix, track failures
- should get detected quicker, with the issue that sometimes the tracker will
- give up too easily. That is fixable by reducing the required correlation (in
- the track properties).
+ Change libmv's bilinear sampling to assume the same
+ pixel conventions as Blender. This fixes the preview
+ widget in Blender, and should make tracking slightly
+ more accurate.
-commit ea0fed736ecdcc8c020227aeef8ef4cd3be5e63d
+commit 99b6222873fbfbe248316316956720376a58f438
Author: Keir Mierle <mierle@gmail.com>
-Date: Fri Feb 17 19:23:50 2012 +0600
-
- Add a new hybrid region tracker for motion tracking to libmv, and
- add it as an option (under "Hybrid") in the tracking settings. The
- region tracker is a combination of brute force tracking for coarse
- alignment, then refinement with the ESM/KLT algorithm already in
- libmv that gives excellent subpixel precision (typically 1/50'th
- of a pixel)
-
- This also adds a new "brute force" region tracker which does a
- brute force search through every pixel position in the destination
- for the pattern in the first frame. It leverages SSE if available,
- similar to the SAD tracker, to do this quickly. Currently it does
- some unnecessary conversions to/from floating point that will get
- fixed later.
-
- The hybrid tracker glues the two trackers (brute & ESM) together
- to get an overall better tracker. The algorithm is simple:
-
- 1. Track from frame 1 to frame 2 with the brute force tracker.
- This tries every possible pixel position for the pattern from
- frame 1 in frame 2. The position with the smallest
- sum-of-absolute-differences is chosen. By definition, this
- position is only accurate up to 1 pixel or so.
- 2. Using the result from 1, initialize a track with ESM. This does
- a least-squares fit with subpixel precision.
- 3. If the ESM shift was more than 2 pixels, report failure.
- 4. If the ESM track shifted less than 2 pixels, then the track is
- good and we're done. The rationale here is that if the
- refinement stage shifts more than 1 pixel, then the brute force
- result likely found some random position that's not a good fit.
-
-commit a07fff8431621c01d81ae52595d8dd91a295a776
-Author: Keir Mierle <mierle@gmail.com>
-Date: Fri Feb 17 19:19:58 2012 +0600
-
- Assorted camera tracker improvements
-
- - Add support for refining the camera's intrinsic parameters
- during a solve. Currently, refining supports only the following
- combinations of intrinsic parameters:
-
- f
- f, cx, cy
- f, cx, cy, k1, k2
- f, k1
- f, k1, k2
-
- This is not the same as autocalibration, since the user must
- still make a reasonable initial guess about the focal length and
- other parameters, whereas true autocalibration would eliminate
- the need for the user specify intrinsic parameters at all.
-
- However, the solver works well with only rough guesses for the
- focal length, so perhaps full autocalibation is not that
- important.
-
- Adding support for the last two combinations, (f, k1) and (f,
- k1, k2) required changes to the library libmv depends on for
- bundle adjustment, SSBA. These changes should get ported
- upstream not just to libmv but to SSBA as well.
-
- - Improved the region of convergence for bundle adjustment by
- increasing the number of Levenberg-Marquardt iterations from 50
- to 500. This way, the solver is able to crawl out of the bad
- local minima it gets stuck in when changing from, for example,
- bundling k1 and k2 to just k1 and resetting k2 to 0.
-
- - Add several new region tracker implementations. A region tracker
- is a libmv concept, which refers to tracking a template image
- pattern through frames. The impact to end users is that tracking
- should "just work better". I am reserving a more detailed
- writeup, and maybe a paper, for later.
-
- - Other libmv tweaks, such as detecting that a tracker is headed
- outside of the image bounds.
-
- This includes several changes made directly to the libmv extern
- code rather expecting to get those changes through normal libmv
- channels, because I, the libmv BDFL, decided it was faster to work
- on libmv directly in Blender, then later reverse-port the libmv
- changes from Blender back into libmv trunk. The interesting part
- is that I added a full Levenberg-Marquardt loop to the region
- tracking code, which should lead to a more stable solutions. I
- also added a hacky implementation of "Efficient Second-Order
- Minimization" for tracking, which works nicely. A more detailed
- quantitative evaluation will follow.
-
-commit 0bf66c009d5022eacfc473d247884a73ffeefa8f
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 19:13:49 2012 +0600
-
- Rest of compilation fix with FAST library.
-
-commit 71b578ca2ba34c528363c514cd1fcc85791d01f3
-Author: Keir Mierle <mierle@gmail.com>
-Date: Fri Feb 17 19:00:28 2012 +0600
+Date: Sat Jun 9 18:58:51 2012 +0000
- Improve the KLT tracking behaviour and UI
+ Add new warp regularization scheme for planar tracking.
- - Remove the overly-conservative use of libmv's re-track tracker. The re-track
- tracker would take a normal tracker such as TRKLT or KLT or pyramid KLT, and
- track from frame 1 to 2, then back from the position found in 2 back to 1.
- Then, when the reverse-track doesn't match the original track with high
- precision, the track is considered "failed". This is a good approach for
- fully automatic reconstruction, but is too conservative for supervised
- tracking.
+ This adds a new term to the tracking cost function that
+ restricts how much the optimizer can warp the patch (as
+ opposed to merely adjusting the translation). This should
+ reduce the "jumpiness" that is sometimes seen when doing
+ non-"Loc" tracks.
- The retrack-tracker will return when fully automatic tracking is added.
+ It is disabled in this commit; a subsequent commit will add
+ controls to the tracking dialog for this.
+
+commit a1c5a70badd11cba0470700bad2eac2b2bd30c86
+Author: Keir Mierle <mierle@gmail.com>
+Date: Sat Jun 9 06:55:21 2012 +0000
+
+ Planar tracker polish.
+
+ - Fixes the correlation checking code that was broken in the
+ previous commit. The bug was a transpose error.
+ - Fixes a memory leak of the warp functor, found by Sameer.
+ - Various cleanups done at Sameer's suggestion.
- - Always solve for (dx, dy) in the TRKLT loop even if the linear system is
- ill-conditioned. The client (Blender in this case) can still use the solved
- position, even though it is less reliable.
+ Thanks to Sameer Agarwal for a code review.
-commit 7d8a8762f2bc2e36f95b0b6f4fb4ca996f9f0db7
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 18:46:24 2012 +0600
+commit 2cb784caa854a77cdd43620ab133f26b87ed0d83
+Author: Keir Mierle <mierle@gmail.com>
+Date: Fri Jun 8 17:42:17 2012 +0000
- Changes in camera intrinsics distortion/undistortion:
+ Make planar tracking much faster.
+
+ - This makes planar tracking around 2-3x or more faster than
+ before, by rearranging how the sampling is done.
+ Previously, the source patch was sampled repeatedly on
+ every optimizer iteration; this was done for
+ implementation speed, but was wasteful in computation.
+
+ - This also contains some additions to Ceres to help
+ deailing with mixed numeric / automatic differentation. In
+ particular, there is now a "Chain::Rule" operator that
+ facilitates calling a function that takes Jet arguments,
+ yet does numeric derivatives internally. This is used to
+ mix the numeric differentation of the images with the warp
+ parameters, passed as jets by Ceres to the warp functor.
+
+ There is also a new "JetOps" object for doing operations
+ on types which may or may not be jets, such as scaling
+ the derivative part only, or extracting the scalar part
+ of a jet.
+
+ This patche is aimed at Ceres upstream.
+
+ - A new function for sampling a patch is now part of the
+ track_region.h API; this will get used to make the preview
+ widget properly show what is getting tracked. Currently
+ the preview widget does not handle perspective tracks.
+
+ Known issues:
- - Distortion/undistortion of scaled images wasn't happening right,
- because camera intrinsics are calibrated on an original frame which
- has got some particular resolution and trying to apply this model on
- an image with another resolution gives totally wrong result.
- This is needed to be able to do post-prccessing of render, running
- distortion on a scene which might be rendered with higher resolution
- than footage itself and then be scaled down.
- - Fixed incorrect calculation/applying of precomputed grid when
- distortion is high high enough and produces pixel offset higher
- than 127 pixels. This might be still not very distorted image,
- but if it's a 4K footage "normal" camera will easily give such
- a distortion.
- - Added support of overscan distortion/undistortion.
+ This patch introduces a bug such that the "Minimum
+ Correlation" flag does not work; if it is enabled, tracking
+ aborts immediately. The workaround for now is to disable the
+ correlation checking, and examine your tracks carefully. A
+ fix will get added shortly.
-commit ed080785d63bb8e3a13dde51a2dc94fe59b059bb
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 18:38:51 2012 +0600
+commit 81d028f13738ebe2304287dfce90e91bc782e2cf
+Author: Keir Mierle <mierle@gmail.com>
+Date: Fri May 18 20:04:43 2012 +0000
- Fast headers now can be included from C++ sources.
- Was needed to make it working fine when bundling in Blender but might also
- be needed to bundle into another applications.
+ Remove an unnecessary template<> line in libmv. Convert debug logs to LG.
-commit 5f5a7aa46a2d87b96c8098dfc8682f4d01b5cd40
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 18:36:16 2012 +0600
+commit 238aaba241ef99995d254aadc974db719da04b96
+Author: Keir Mierle <mierle@gmail.com>
+Date: Fri May 18 12:05:10 2012 +0000
- Bring back FAST detector which seems to be working much nicer than Morravec.
- Both of them are available in API.
+ Support normalization in the tracking prepass
+
+ The last tracker commit added normalized tracking. This makes
+ tracking patches undergoing uniform illumination change easier.
+ However, the prepass which computes a quick translation-only
+ estimate of the warp did not take this into account. This commit
+ fixes that.
+
+ This works reasonably well but in some examples the brute
+ initialization fails. I suspect this is due to the warped template
+ estimate in the current frame being too different from the
+ original, so there are multiple peaks in the normalized-SAD
+ correlation function.
+
+ The solution is to use the previous frame for the brute
+ initialization and the keyframe for refinement, but that requires
+ architecture changes.
-commit 2cab13c18216fb684b270cec077f7300262584af
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 18:27:36 2012 +0600
+commit 981ca4f6a679cd9ac3d086eae3cd946ce72ca8a5
+Author: Keir Mierle <mierle@gmail.com>
+Date: Fri May 18 02:12:47 2012 +0000
- Revert "Make CameraIntrinsics (and thus Qt tracker) compilable without linking libmv."
+ Add light-normalized tracking to the planar tracker
+
+ This commit adds the ability to normalize patterns by their
+ average value while tracking, to make them invariant to global
+ illumination changes.
- This reverts commit 81613ee0cc94b315f333c9632b18b95d426aad05.
+ To see this in action, check out the "Lobby" scene from Hollywood
+ VFX. If you track the markers that are shadowed by the actress,
+ previously they would not track. With the scale adaption on, the
+ tracker would shrink the area to compensate for the changed
+ illumination, losing the track. With "Normalize" turned on, the
+ patch is correctly tracked and scale is maintained.
- That commit made inverting intrinsics totally unworkable, so reverted this and
- made needed tweaks to qt-tracker project file to make it compilable (was needed
- to make it linking together with glog).
+ A remaining problem is that only the Ceres cost function is
+ updated to handle the normalization. The brute translation search
+ does not take this into account. Perhaps "Prepass" (see below)
+ should get disabled if normalization is enabled until I fix the
+ prepass to normalize as well.
- Conflicts:
+ There are a few other changes:
- src/ui/tracker/tracker.cc
- src/ui/tracker/tracker.pro
+ - Bail out of the sampling loop early if the mask is zero; this
+ saves expensive samples of the image derivatives.
+
+ - Fix a bug where the mask was ignored when sampling in the cost
+ functor.
-commit ec46cae041401b17afb4fe4d9c9343d10797090f
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 17:59:55 2012 +0600
+commit e9384b15fb2a6a5b81346d5758fa136f0911e945
+Author: Keir Mierle <mierle@gmail.com>
+Date: Thu May 17 23:53:32 2012 +0000
- Fix compilation error using official MinGW
+ Implement support for affine tracking in the planar tracker; cleanups.
-commit 6fbc370e922c47cfa35381662b6c439f4891ed74
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 17:38:20 2012 +0600
+commit 021d41eed8b4ce6a4e37786ccd357ed5dc83a13f
+Author: Keir Mierle <mierle@gmail.com>
+Date: Thu May 17 21:26:06 2012 +0000
- Fix compilation error with MSVC 2010 which is more picky for "missed" STL headers
+ For the planar tracker, initialize the warp from the four correspondences
+ after brute force translation search.
-commit be9e6b63691d83b551a085f0766878bd84220767
+commit 003d1bf6145cfd30938b35f6e10d43708dbf916c
Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 17:36:18 2012 +0600
+Date: Thu Dec 6 16:56:01 2012 +0600
- Fix compilation with MSVC where snprintf function is declared as unsafe and _snprintf should be used instead.
+ Correction to region tracker options initialization.
- Better to switch to own implementation will ensure string is correctly NULL-terminated.
+ Based on patch from Keir to Blender:
+ https://svn.blender.org/svnroot/bf-blender/branches/soc-2011-tomato@46743
-commit 1847d9e414ed763cd80668775d7d9f79575fc8ca
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 17:34:45 2012 +0600
+commit 6af47b218cfdf5219f0ebb3cb95459817cf9abf2
+Author: Keir Mierle <mierle@gmail.com>
+Date: Thu May 17 02:31:52 2012 +0000
- Fix compilation error on OSX caused by incorrect access to ucontext
+ Add new planar tracker features and use the new planar API
+
+ This commit removes the use of the legacy RegionTracker API from
+ Blender, and replaces it with the new TrackRegion API. This also
+ adds several features to the planar tracker in libmv:
+
+ - Do a brute-force initialization of tracking similar to "Hybrid"
+ mode in the stable release, but using all floats. This is slower
+ but more accurate. It is still necessary to evaluate if the
+ performance loss is worth it. In particular, this change is
+ necessary to support high bit depth imagery.
+
+ - Add support for masks over the search window. This is a step
+ towards supporting user-defined tracker masks. The tracker masks
+ will make it easy for users to make a mask for e.g. a ball.
+
+ - Add Pearson product moment correlation coefficient checking (aka
+ "Correlation" in the UI. This causes tracking failure if the
+ tracked patch is not linearly related to the template.
+
+ - Add support for warping a few points in addition to the supplied
+ points. This is useful because the tracking code deliberately
+ does not expose the underlying warp representation. Instead,
+ warps are specified in an aparametric way via the correspondences.
+
+ - Remove the "num_samples_xy" concept and replace it with
+ automatic determination of the number of samples. This makes the
+ API easier for users.
+
+ - Fix various bugs in the parameterizations.
+
+ There remains a bug with subpixel precision tracking when in
+ "keyframe" mode; this will get fixed shortly.
-commit 90579b6ffad07672172a1c240499615b30b25549
-Merge: b9aac30 531c79b
-Author: Sergey Sharybin <sergey.vfx@gmail.com>
-Date: Fri Feb 17 18:32:52 2012 +0600
+commit 16a46db104468cec80bd31ca9d5f8bffbe3e003e
+Author: Keir Mierle <mierle@gmail.com>
+Date: Mon May 14 12:15:38 2012 +0000
- Merge remote-tracking branch 'Matthias-Fauconneau/master' into devel
+ "Efficient Second-order Minimization" for the planar tracker
- Conflicts:
- src/libmv/tracking/CMakeLists.txt
+ This implements the "Efficient Second-order Minimization"
+ scheme, as supported by the existing translation tracker.
+ This increases the amount of per-iteration work, but
+ decreases the number of iterations required to converge and
+ also increases the size of the basin of attraction for the
+ optimization.
-commit b9aac30a9ca6bc8362c09a0e191040964f7c6de2
-Merge: 198894e 6969e1a
+commit 23243b1b1f3e1ab3ef862b47bca06ee876ac2cf4
Author: Keir Mierle <mierle@gmail.com>
-Date: Sat Nov 5 17:38:30 2011 -0700
+Date: Sun May 13 23:08:56 2012 +0000
- Merge pull request #3 from nathanwiegand/master
+ Add a planar tracking implementation to libmv
- Just a few tiny cleanups
+ This adds a new planar tracking implementation to libmv. The
+ tracker is based on Ceres[1], the new nonlinear minimizer that
+ myself and Sameer released from Google as open source. Since
+ the motion model is more involved, the interface is
+ different than the RegionTracker interface used previously
+ in Blender.
+
+ The ESM tracker, also known as the KLT tracker in the UI, is
+ temporarily changed to use the new Ceres-based planar
+ tracker in translation-only mode. Currently it is a bit
+ slower than ESM and also doesn't have all the bells and
+ whistles implemented. Those will come soon. Longer term,
+ both trackers will remain since Ceres is unlikely to be as
+ fast as ESM for pure translation solving, due to its
+ generality.
+
+ The next step is to implement a new tracking UI. The current
+ UI assumes a translational motion model; the new one must
+ support arbitrary perspective transforms of the pattern
+ regions.
+
+ [1] http://code.google.com/p/ceres-solver
-commit 6969e1a9534291a982749baa5a3672c97bfa506d
-Author: Nathan Wiegand <nathanwiegand@gmail.com>
-Date: Sat Nov 5 14:26:54 2011 -0700
+commit 52be92b53eb4decb1a316690b162196f227cc441
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Thu Dec 6 16:06:08 2012 +0600
+
+ Initial Ceres integration
+
+ Currently only put sources to src/third_party/ceres and made sure they're
+ not giving compilation issues.
+
+ Used Ceres upstream version 1.3.0.
+
+ Needed to make some modifications to it's CMakeLists.txt also to glog and
+ fglags. They're described in README.libmv of this libraries.
+
+ Basically:
+
+ - Added -fPIC to glog/gflags, so shared ceres library could be linked
+ statically against this libraries.
+
+ - Tweaked Ceres's build rules to use needed libraries from libmv's
+ third_party folder.
+
+commit b13f9d13122e091cb85855c2094386ccdef6e5a4
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Wed Dec 5 19:05:34 2012 +0600
- I've added cleaned up a few style issues here an there. Also, I've updated the CMakeLists.txt file so that it can build the image_io library. Note, it's only been tested on OSX 10.6
+ Update Eigen to version 3.1.2
+
+ Mainly because of lots of warnings generating by gcc-4.7 which are
+ resolved in newer eigen version.
-commit 4763f851299050140757bfaa069107a0cf639e56
-Author: Nathan Wiegand <nathanwiegand@gmail.com>
-Date: Fri Nov 4 23:59:08 2011 -0700
+commit 1f0dd94e8e37d3fe2df89282ec16a6a685fdde0b
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Fri May 25 16:36:44 2012 +0600
- Removed a superfulous comment
+ - Added avutil to qt-tracker linking when building with FFmpeg support.
+ On some platforms it seems to be required
+ - Synchronized QT Creator project for qt-tracker with changes in sources,
+ so no it might be compiled from QT Creator.
-commit a44577c0162e273681e4a9a3cc5f5b37d4315b67
-Author: Nathan Wiegand <nathanwiegand@gmail.com>
-Date: Fri Nov 4 23:55:52 2011 -0700
+commit b813dbe3f46bbbc7e73ac791d4665622e4fc7ba5
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Wed May 9 19:01:10 2012 +0600
- Removed a duplicate entry for an author.
+ Modal solver: Detect rigid transformation between initial frame and current
+ instead of detecting it between two neighbour frames.
+
+ This prevents accumulation of error and seems to be working better in footages i've tested.
-commit 198894e4c4f51c2c1784ad7c02eb45d2d1ada9bc
-Merge: c4c67db 6e797d6
-Author: Keir Mierle <mierle@gmail.com>
-Date: Fri Nov 4 21:47:05 2011 -0700
+commit 9254621c76daaf239ec1f535e197ca792eea97b6
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Wed May 9 18:57:00 2012 +0600
- Merge pull request #2 from nathanwiegand/master
+ Backport changes made by Keir in Blender:
- CMake changes for OSX
+ - Enhance logging in libmv's trackers.
+ - Cleanups in brute_region_tracker.cc.
-commit 6e797d678c4c19f6a9e21657d66183f412cc995b
-Author: Nathan Wiegand <nathanwiegand@gmail.com>
-Date: Fri Nov 4 21:43:28 2011 -0700
+commit d9c56b9d3c63f886d83129ca0ebed1e76d9c93d7
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Fri Apr 27 16:20:41 2012 +0600
- Uncomment the GUI part of the CMake file
+ Fixes for MinGW64 support by Caleb Joseph with slight modifications by Antony Riakiotakis
+
+ - Functions snprintf and sincos shouldn't be redefined for MinGW64
+ - Type pid_t shouldn't be re-defined for MinGW64
-commit 33ef88a33860345d8906f3c9dd22d8dbce3df53e
-Author: Nathan Wiegand <nathanwiegand@gmail.com>
-Date: Fri Nov 4 21:31:22 2011 -0700
+commit e1902b6938676011607ac99986b8b140bdbf090e
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Fri Apr 27 16:04:19 2012 +0600
- Fixed build error on OSX by adding 'glog' to the dependencies in the tracker CMake
+ Fixes for Qt calibration tool
+
+ - Passing directory with images via command line argument now isn't
+ required -- it there's no such directory specified standard open
+ dialog might be used for this (before application used to abort
+ due to accessing to non-existing list element).
+ - Conversion of source images to grayscale now happens correct.
+ It was needed to build grayscale palette for 8bit indexed buffer.
-commit 531c79bf95fddaaa70707d1abcd4fdafda16bbf0
-Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
-Date: Sat Aug 20 00:00:42 2011 +0200
+commit 05f1a0a78ad8ff6646d1e8da97e6f7575b891536
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Sat Apr 14 17:21:29 2012 +0600
- Display warped pattern in marker preview.
+ Make QtTracker compilable again porting it to recent API change and code cleanup:
+
+ - It was using SAD tracker with own API, now it's using standard RegionTracker API
+ which should make it easier to switch between different trackers.
+ - Restored LaplaceFilter from old SAD module which convolves images with the
+ discrete laplacian operator.
-commit bb5c27e671b6f8eb56ddf490f0795d59bede591b
-Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
-Date: Fri Aug 19 18:37:48 2011 +0200
+commit a44312a7beb2963b8e3bf8015c516d2eff40cc3d
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Thu Apr 12 13:56:02 2012 +0600
- Fix CMake build.
+ Added solver for modal camera motion, currently supports only tripod solving
+
+ This solver is intended to deal with such camera motions as tripod and panning,
+ where it's impossible to reconstruct exact position of markers in 3d view.
+
+ It projects markers onto sphere and uses rigid registration of rotation to
+ find rotation angles which makes bundles from previous and current frame be
+ as closest as it's possible.
diff --git a/extern/libmv/SConscript b/extern/libmv/SConscript
index b47086f3e91..d0015db42d7 100644
--- a/extern/libmv/SConscript
+++ b/extern/libmv/SConscript
@@ -11,11 +11,6 @@ Import('env')
defs = []
-cflags_libmv = Split(env['CFLAGS'])
-ccflags_libmv = Split(env['CCFLAGS'])
-cxxflags_libmv = Split(env['CXXFLAGS'])
-
-defs.append('V3DLIB_ENABLE_SUITESPARSE')
defs.append('GOOGLE_GLOG_DLL_DECL=')
src = env.Glob("*.cpp")
@@ -26,9 +21,6 @@ src += env.Glob('libmv/simple_pipeline/*.cc')
src += env.Glob('libmv/tracking/*.cc')
src += env.Glob('third_party/fast/*.c')
src += env.Glob('third_party/gflags/*.cc')
-src += env.Glob('third_party/ldl/Source/*.c')
-src += env.Glob('third_party/ssba/Geometry/*.cpp')
-src += env.Glob('third_party/ssba/Math/*.cpp')
incs = '. ../Eigen3 third_party/ceres/include'
incs += ' ' + env['BF_PNG_INC']
@@ -41,29 +33,10 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', '
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']
-
- if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
- cflags_libmv.append('/Od')
- ccflags_libmv.append('/Od')
- cxxflags_libmv.append('/Od')
-
- if not env['BF_DEBUG']:
- defs.append('NDEBUG')
- else:
- if not env['BF_DEBUG']:
- cflags_libmv += Split(env['REL_CFLAGS'])
- ccflags_libmv += Split(env['REL_CCFLAGS'])
- cxxflags_libmv += Split(env['REL_CXXFLAGS'])
else:
src += env.Glob("third_party/glog/src/*.cc")
incs += ' ./third_party/glog/src'
- if not env['BF_DEBUG']:
- cflags_libmv += Split(env['REL_CFLAGS'])
- ccflags_libmv += Split(env['REL_CCFLAGS'])
- cxxflags_libmv += Split(env['REL_CXXFLAGS'])
-
-incs += ' ./third_party/ssba ./third_party/ldl/Include ../colamd/Include'
-env.BlenderLib ( libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137], compileflags=cflags_libmv, cc_compileflags=ccflags_libmv, cxx_compileflags=cxxflags_libmv )
+env.BlenderLib ( libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137] )
SConscript(['third_party/SConscript'])
diff --git a/extern/libmv/bundle.sh b/extern/libmv/bundle.sh
index 1e386ec8096..a9edfde55bf 100755
--- a/extern/libmv/bundle.sh
+++ b/extern/libmv/bundle.sh
@@ -124,31 +124,15 @@ cat > CMakeLists.txt << EOF
set(INC
.
- ../colamd/Include
third_party/ceres/include
)
set(INC_SYS
../Eigen3
- third_party/ssba
- third_party/ldl/Include
\${PNG_INCLUDE_DIR}
\${ZLIB_INCLUDE_DIRS}
)
-
-# XXX - FIXME
-# this is a momentary hack to find unwind.h in 10.6.sdk
-if(APPLE)
- if(\${CMAKE_OSX_DEPLOYMENT_TARGET} STREQUAL "10.6")
- list(APPEND INC_SYS
- \${CMAKE_OSX_SYSROOT}/Developer/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin10/4.2.1/include
- )
- endif()
-endif()
-# XXX - END
-
-
set(SRC
libmv-capi.cpp
${sources}
@@ -197,14 +181,6 @@ if(WIN32)
third_party/msinttypes
)
endif()
-
- if(MSVC)
- set(MSVC_OFLAGS O1 O2 Ox)
- foreach(FLAG \${MSVC_OFLAGS})
- string(REPLACE "\${FLAG}" "Od" CMAKE_CXX_FLAGS_RELEASE "\${CMAKE_CXX_FLAGS_RELEASE}")
- string(REPLACE "\${FLAG}" "Od" CMAKE_C_FLAGS_RELWITHDEBINFO "\${CMAKE_C_FLAGS_RELWITHDEBINFO}")
- endforeach()
- endif()
else()
list(APPEND SRC
${third_glog_sources}
@@ -218,7 +194,6 @@ ${third_glog_headers}
endif()
add_definitions(
- -DV3DLIB_ENABLE_SUITESPARSE
-DGOOGLE_GLOG_DLL_DECL=
)
@@ -241,11 +216,6 @@ Import('env')
defs = []
-cflags_libmv = Split(env['CFLAGS'])
-ccflags_libmv = Split(env['CCFLAGS'])
-cxxflags_libmv = Split(env['CXXFLAGS'])
-
-defs.append('V3DLIB_ENABLE_SUITESPARSE')
defs.append('GOOGLE_GLOG_DLL_DECL=')
src = env.Glob("*.cpp")
@@ -262,30 +232,11 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', '
${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']
-
- if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
- cflags_libmv.append('/Od')
- ccflags_libmv.append('/Od')
- cxxflags_libmv.append('/Od')
-
- if not env['BF_DEBUG']:
- defs.append('NDEBUG')
- else:
- if not env['BF_DEBUG']:
- cflags_libmv += Split(env['REL_CFLAGS'])
- ccflags_libmv += Split(env['REL_CCFLAGS'])
- cxxflags_libmv += Split(env['REL_CXXFLAGS'])
else:
src += env.Glob("third_party/glog/src/*.cc")
incs += ' ./third_party/glog/src'
- if not env['BF_DEBUG']:
- cflags_libmv += Split(env['REL_CFLAGS'])
- ccflags_libmv += Split(env['REL_CCFLAGS'])
- cxxflags_libmv += Split(env['REL_CXXFLAGS'])
-
-incs += ' ./third_party/ssba ./third_party/ldl/Include ../colamd/Include'
-env.BlenderLib ( libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137], compileflags=cflags_libmv, cc_compileflags=ccflags_libmv, cxx_compileflags=cxxflags_libmv )
+env.BlenderLib ( libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137] )
SConscript(['third_party/SConscript'])
EOF
diff --git a/extern/libmv/files.txt b/extern/libmv/files.txt
index 85d09ce05b8..16afdb36371 100644
--- a/extern/libmv/files.txt
+++ b/extern/libmv/files.txt
@@ -17,7 +17,11 @@ libmv/multiview/euclidean_resection.cc
libmv/multiview/euclidean_resection.h
libmv/multiview/fundamental.cc
libmv/multiview/fundamental.h
+libmv/multiview/homography.cc
+libmv/multiview/homography.h
+libmv/multiview/homography_parameterization.h
libmv/multiview/nviewtriangulation.h
+libmv/multiview/panography.h
libmv/multiview/projection.cc
libmv/multiview/projection.h
libmv/multiview/resection.h
@@ -50,8 +54,6 @@ libmv/simple_pipeline/reconstruction.cc
libmv/simple_pipeline/reconstruction.h
libmv/simple_pipeline/resect.cc
libmv/simple_pipeline/resect.h
-libmv/simple_pipeline/rigid_registration.cc
-libmv/simple_pipeline/rigid_registration.h
libmv/simple_pipeline/tracks.cc
libmv/simple_pipeline/tracks.h
libmv/tracking/brute_region_tracker.cc
@@ -69,6 +71,8 @@ libmv/tracking/pyramid_region_tracker.h
libmv/tracking/region_tracker.h
libmv/tracking/retrack_region_tracker.cc
libmv/tracking/retrack_region_tracker.h
+libmv/tracking/track_region.cc
+libmv/tracking/track_region.h
libmv/tracking/trklt_region_tracker.cc
libmv/tracking/trklt_region_tracker.h
third_party/fast/fast_10.c
@@ -137,25 +141,6 @@ third_party/glog/src/windows/glog/vlog_is_on.h
third_party/glog/src/windows/port.cc
third_party/glog/src/windows/port.h
third_party/glog/src/windows/preprocess.sh
-third_party/ldl/CMakeLists.txt
-third_party/ldl/Doc/ChangeLog
-third_party/ldl/Doc/lesser.txt
-third_party/ldl/Include/ldl.h
-third_party/ldl/README.libmv
-third_party/ldl/README.txt
-third_party/ldl/Source/ldl.c
third_party/msinttypes/inttypes.h
third_party/msinttypes/README.libmv
third_party/msinttypes/stdint.h
-third_party/ssba/COPYING.TXT
-third_party/ssba/Geometry/v3d_cameramatrix.h
-third_party/ssba/Geometry/v3d_distortion.h
-third_party/ssba/Geometry/v3d_metricbundle.cpp
-third_party/ssba/Geometry/v3d_metricbundle.h
-third_party/ssba/Math/v3d_linear.h
-third_party/ssba/Math/v3d_linear_utils.h
-third_party/ssba/Math/v3d_mathutilities.h
-third_party/ssba/Math/v3d_optimization.cpp
-third_party/ssba/Math/v3d_optimization.h
-third_party/ssba/README.libmv
-third_party/ssba/README.TXT
diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp
index 8e483abd386..eccf6fb7cb6 100644
--- a/extern/libmv/libmv-capi.cpp
+++ b/extern/libmv/libmv-capi.cpp
@@ -34,21 +34,8 @@
#include "libmv-capi.h"
-#include "third_party/gflags/gflags/gflags.h"
-#include "glog/logging.h"
#include "libmv/logging/logging.h"
-#include "Math/v3d_optimization.h"
-
-#include "libmv/numeric/numeric.h"
-
-#include "libmv/tracking/esm_region_tracker.h"
-#include "libmv/tracking/brute_region_tracker.h"
-#include "libmv/tracking/hybrid_region_tracker.h"
-#include "libmv/tracking/klt_region_tracker.h"
-#include "libmv/tracking/trklt_region_tracker.h"
-#include "libmv/tracking/lmicklt_region_tracker.h"
-#include "libmv/tracking/pyramid_region_tracker.h"
#include "libmv/tracking/track_region.h"
#include "libmv/simple_pipeline/callbacks.h"
@@ -58,7 +45,6 @@
#include "libmv/simple_pipeline/detect.h"
#include "libmv/simple_pipeline/pipeline.h"
#include "libmv/simple_pipeline/camera_intrinsics.h"
-#include "libmv/simple_pipeline/rigid_registration.h"
#include "libmv/simple_pipeline/modal_solver.h"
#include <stdlib.h>
@@ -96,7 +82,6 @@ void libmv_initLogging(const char *argv0)
google::SetCommandLineOption("v", "0");
google::SetCommandLineOption("stderrthreshold", "7");
google::SetCommandLineOption("minloglevel", "7");
- V3D::optimizerVerbosenessLevel = 0;
}
void libmv_startDebugLogging(void)
@@ -105,7 +90,6 @@ void libmv_startDebugLogging(void)
google::SetCommandLineOption("v", "2");
google::SetCommandLineOption("stderrthreshold", "1");
google::SetCommandLineOption("minloglevel", "0");
- V3D::optimizerVerbosenessLevel = 1;
}
void libmv_setLoggingVerbosity(int verbosity)
@@ -114,54 +98,9 @@ void libmv_setLoggingVerbosity(int verbosity)
snprintf(val, sizeof(val), "%d", verbosity);
google::SetCommandLineOption("v", val);
- V3D::optimizerVerbosenessLevel = verbosity;
-}
-
-/* ************ RegionTracker ************ */
-
-libmv_RegionTracker *libmv_pyramidRegionTrackerNew(int max_iterations, int pyramid_level, int half_window_size, double minimum_correlation)
-{
- libmv::EsmRegionTracker *esm_region_tracker = new libmv::EsmRegionTracker;
- esm_region_tracker->half_window_size = half_window_size;
- esm_region_tracker->max_iterations = max_iterations;
- esm_region_tracker->min_determinant = 1e-4;
- esm_region_tracker->minimum_correlation = minimum_correlation;
-
- libmv::PyramidRegionTracker *pyramid_region_tracker =
- new libmv::PyramidRegionTracker(esm_region_tracker, pyramid_level);
-
- return (libmv_RegionTracker *)pyramid_region_tracker;
}
-libmv_RegionTracker *libmv_hybridRegionTrackerNew(int max_iterations, int half_window_size, double minimum_correlation)
-{
- libmv::EsmRegionTracker *esm_region_tracker = new libmv::EsmRegionTracker;
- esm_region_tracker->half_window_size = half_window_size;
- esm_region_tracker->max_iterations = max_iterations;
- esm_region_tracker->min_determinant = 1e-4;
- esm_region_tracker->minimum_correlation = minimum_correlation;
-
- libmv::BruteRegionTracker *brute_region_tracker = new libmv::BruteRegionTracker;
- brute_region_tracker->half_window_size = half_window_size;
-
- /* do not use correlation check for brute checker itself,
- * this check will happen in esm tracker */
- brute_region_tracker->minimum_correlation = 0.0;
-
- libmv::HybridRegionTracker *hybrid_region_tracker =
- new libmv::HybridRegionTracker(brute_region_tracker, esm_region_tracker);
-
- return (libmv_RegionTracker *)hybrid_region_tracker;
-}
-
-libmv_RegionTracker *libmv_bruteRegionTrackerNew(int half_window_size, double minimum_correlation)
-{
- libmv::BruteRegionTracker *brute_region_tracker = new libmv::BruteRegionTracker;
- brute_region_tracker->half_window_size = half_window_size;
- brute_region_tracker->minimum_correlation = minimum_correlation;
-
- return (libmv_RegionTracker *)brute_region_tracker;
-}
+/* ************ Utility ************ */
static void floatBufToImage(const float *buf, int width, int height, int channels, libmv::FloatImage *image)
{
@@ -303,7 +242,7 @@ static void saveBytesImage(const char *prefix, unsigned char *data, int width, i
}
{
- static int a= 0;
+ static int a = 0;
char buf[128];
snprintf(buf, sizeof(buf), "%s_%02d.png", prefix, ++a);
savePNGImage(row_pointers, width, height, 8, PNG_COLOR_TYPE_RGBA, buf);
@@ -316,43 +255,6 @@ static void saveBytesImage(const char *prefix, unsigned char *data, int width, i
}
#endif
-int libmv_regionTrackerTrack(libmv_RegionTracker *libmv_tracker, const float *ima1, const float *ima2,
- int width, int height, double x1, double y1, double *x2, double *y2)
-{
- libmv::RegionTracker *region_tracker = (libmv::RegionTracker *)libmv_tracker;
- libmv::FloatImage old_patch, new_patch;
-
- floatBufToImage(ima1, width, height, 1, &old_patch);
- floatBufToImage(ima2, width, height, 1, &new_patch);
-
-#if !defined(DUMP_FAILURE) && !defined(DUMP_ALWAYS)
- return region_tracker->Track(old_patch, new_patch, x1, y1, x2, y2);
-#else
- {
- /* double sx2 = *x2, sy2 = *y2; */
- int result = region_tracker->Track(old_patch, new_patch, x1, y1, x2, y2);
-
-#if defined(DUMP_ALWAYS)
- {
-#else
- if (!result) {
-#endif
- saveImage("old_patch", old_patch, x1, y1);
- saveImage("new_patch", new_patch, *x2, *y2);
- }
-
- return result;
- }
-#endif
-}
-
-void libmv_regionTrackerDestroy(libmv_RegionTracker *libmv_tracker)
-{
- libmv::RegionTracker *region_tracker= (libmv::RegionTracker *)libmv_tracker;
-
- delete region_tracker;
-}
-
/* ************ Planar tracker ************ */
/* TrackRegion (new planar tracker) */
@@ -523,12 +425,15 @@ int libmv_refineParametersAreValid(int parameters) {
LIBMV_REFINE_RADIAL_DISTORTION_K1 |
LIBMV_REFINE_RADIAL_DISTORTION_K2)) ||
(parameters == (LIBMV_REFINE_FOCAL_LENGTH |
- LIBMV_REFINE_RADIAL_DISTORTION_K1));
+ LIBMV_REFINE_RADIAL_DISTORTION_K1)) ||
+ (parameters == (LIBMV_REFINE_RADIAL_DISTORTION_K1 |
+ LIBMV_REFINE_RADIAL_DISTORTION_K2));
}
static void libmv_solveRefineIntrinsics(libmv::Tracks *tracks, libmv::CameraIntrinsics *intrinsics,
libmv::EuclideanReconstruction *reconstruction, int refine_intrinsics,
- reconstruct_progress_update_cb progress_update_callback, void *callback_customdata)
+ reconstruct_progress_update_cb progress_update_callback, void *callback_customdata,
+ int bundle_constraints = libmv::BUNDLE_NO_CONSTRAINTS)
{
/* only a few combinations are supported but trust the caller */
int libmv_refine_flags = 0;
@@ -549,43 +454,84 @@ static void libmv_solveRefineIntrinsics(libmv::Tracks *tracks, libmv::CameraIntr
progress_update_callback(callback_customdata, 1.0, "Refining solution");
libmv::EuclideanBundleCommonIntrinsics(*(libmv::Tracks *)tracks, libmv_refine_flags,
- reconstruction, intrinsics);
+ reconstruction, intrinsics, bundle_constraints);
}
-libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyframe1, int keyframe2,
- int refine_intrinsics, double focal_length, double principal_x, double principal_y,
- double k1, double k2, double k3, struct libmv_reconstructionOptions *options,
- reconstruct_progress_update_cb progress_update_callback, void *callback_customdata)
+static void cameraIntrinsicsFromOptions(libmv::CameraIntrinsics *camera_intrinsics,
+ libmv_cameraIntrinsicsOptions *camera_intrinsics_options)
+{
+ camera_intrinsics->SetFocalLength(camera_intrinsics_options->focal_length,
+ camera_intrinsics_options->focal_length);
+
+ camera_intrinsics->SetPrincipalPoint(camera_intrinsics_options->principal_point_x,
+ camera_intrinsics_options->principal_point_y);
+
+ camera_intrinsics->SetRadialDistortion(camera_intrinsics_options->k1,
+ camera_intrinsics_options->k2,
+ camera_intrinsics_options->k3);
+
+ camera_intrinsics->SetImageSize(camera_intrinsics_options->image_width,
+ camera_intrinsics_options->image_height);
+}
+
+static libmv::Tracks getNormalizedTracks(libmv::Tracks *tracks, libmv::CameraIntrinsics *camera_intrinsics)
+{
+ libmv::vector<libmv::Marker> markers = tracks->AllMarkers();
+
+ for (int i = 0; i < markers.size(); ++i) {
+ camera_intrinsics->InvertIntrinsics(markers[i].x, markers[i].y,
+ &(markers[i].x), &(markers[i].y));
+ }
+
+ return libmv::Tracks(markers);
+}
+
+static void finishReconstruction(libmv::Tracks *tracks, libmv::CameraIntrinsics *camera_intrinsics,
+ libmv_Reconstruction *libmv_reconstruction,
+ reconstruct_progress_update_cb progress_update_callback,
+ void *callback_customdata)
+{
+ libmv::EuclideanReconstruction *reconstruction = &libmv_reconstruction->reconstruction;
+
+ /* reprojection error calculation */
+ progress_update_callback(callback_customdata, 1.0, "Finishing solution");
+ libmv_reconstruction->tracks = *tracks;
+ libmv_reconstruction->error = libmv::EuclideanReprojectionError(*tracks, *reconstruction, *camera_intrinsics);
+}
+
+libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *libmv_tracks,
+ libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
+ libmv_reconstructionOptions *libmv_reconstruction_options,
+ reconstruct_progress_update_cb progress_update_callback,
+ void *callback_customdata)
{
- /* Invert the camera intrinsics. */
- libmv::vector<libmv::Marker> markers = ((libmv::Tracks*)tracks)->AllMarkers();
libmv_Reconstruction *libmv_reconstruction = new libmv_Reconstruction();
+
+ libmv::Tracks *tracks = ((libmv::Tracks *) libmv_tracks);
libmv::EuclideanReconstruction *reconstruction = &libmv_reconstruction->reconstruction;
- libmv::CameraIntrinsics *intrinsics = &libmv_reconstruction->intrinsics;
- libmv::ReconstructionOptions reconstruction_options;
+ libmv::CameraIntrinsics *camera_intrinsics = &libmv_reconstruction->intrinsics;
ReconstructUpdateCallback update_callback =
ReconstructUpdateCallback(progress_update_callback, callback_customdata);
- intrinsics->SetFocalLength(focal_length, focal_length);
- intrinsics->SetPrincipalPoint(principal_x, principal_y);
- intrinsics->SetRadialDistortion(k1, k2, k3);
+ cameraIntrinsicsFromOptions(camera_intrinsics, libmv_camera_intrinsics_options);
- reconstruction_options.success_threshold = options->success_threshold;
- reconstruction_options.use_fallback_reconstruction = options->use_fallback_reconstruction;
+ /* Invert the camera intrinsics */
+ libmv::Tracks normalized_tracks = getNormalizedTracks(tracks, camera_intrinsics);
- for (int i = 0; i < markers.size(); ++i) {
- intrinsics->InvertIntrinsics(markers[i].x,
- markers[i].y,
- &(markers[i].x),
- &(markers[i].y));
- }
+ /* actual reconstruction */
+ libmv::ReconstructionOptions reconstruction_options;
+ reconstruction_options.success_threshold = libmv_reconstruction_options->success_threshold;
+ reconstruction_options.use_fallback_reconstruction = libmv_reconstruction_options->use_fallback_reconstruction;
- libmv::Tracks normalized_tracks(markers);
+ int keyframe1 = libmv_reconstruction_options->keyframe1,
+ keyframe2 = libmv_reconstruction_options->keyframe2;
LG << "frames to init from: " << keyframe1 << " " << keyframe2;
+
libmv::vector<libmv::Marker> keyframe_markers =
normalized_tracks.MarkersForTracksInBothImages(keyframe1, keyframe2);
+
LG << "number of markers for init: " << keyframe_markers.size();
update_callback.invoke(0, "Initial reconstruction");
@@ -595,49 +541,61 @@ libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyfra
libmv::EuclideanCompleteReconstruction(reconstruction_options, normalized_tracks,
reconstruction, &update_callback);
- if (refine_intrinsics) {
- libmv_solveRefineIntrinsics((libmv::Tracks *)tracks, intrinsics, reconstruction,
- refine_intrinsics, progress_update_callback, callback_customdata);
+ /* refinement */
+ if (libmv_reconstruction_options->refine_intrinsics) {
+ libmv_solveRefineIntrinsics((libmv::Tracks *)tracks, camera_intrinsics, reconstruction,
+ libmv_reconstruction_options->refine_intrinsics,
+ progress_update_callback, callback_customdata);
}
- progress_update_callback(callback_customdata, 1.0, "Finishing solution");
- libmv_reconstruction->tracks = *(libmv::Tracks *)tracks;
- libmv_reconstruction->error = libmv::EuclideanReprojectionError(*(libmv::Tracks *)tracks, *reconstruction, *intrinsics);
+ /* finish reconstruction */
+ finishReconstruction(tracks, camera_intrinsics, libmv_reconstruction,
+ progress_update_callback, callback_customdata);
return (libmv_Reconstruction *)libmv_reconstruction;
}
-struct libmv_Reconstruction *libmv_solveModal(struct libmv_Tracks *tracks, double focal_length,
- double principal_x, double principal_y, double k1, double k2, double k3,
- reconstruct_progress_update_cb progress_update_callback, void *callback_customdata)
+struct libmv_Reconstruction *libmv_solveModal(struct libmv_Tracks *libmv_tracks,
+ libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
+ libmv_reconstructionOptions *libmv_reconstruction_options,
+ reconstruct_progress_update_cb progress_update_callback,
+ void *callback_customdata)
{
- /* Invert the camera intrinsics. */
- libmv::vector<libmv::Marker> markers = ((libmv::Tracks*)tracks)->AllMarkers();
libmv_Reconstruction *libmv_reconstruction = new libmv_Reconstruction();
+
+ libmv::Tracks *tracks = ((libmv::Tracks *) libmv_tracks);
libmv::EuclideanReconstruction *reconstruction = &libmv_reconstruction->reconstruction;
- libmv::CameraIntrinsics *intrinsics = &libmv_reconstruction->intrinsics;
+ libmv::CameraIntrinsics *camera_intrinsics = &libmv_reconstruction->intrinsics;
ReconstructUpdateCallback update_callback =
ReconstructUpdateCallback(progress_update_callback, callback_customdata);
- intrinsics->SetFocalLength(focal_length, focal_length);
- intrinsics->SetPrincipalPoint(principal_x, principal_y);
- intrinsics->SetRadialDistortion(k1, k2, k3);
-
- for (int i = 0; i < markers.size(); ++i) {
- intrinsics->InvertIntrinsics(markers[i].x,
- markers[i].y,
- &(markers[i].x),
- &(markers[i].y));
- }
+ cameraIntrinsicsFromOptions(camera_intrinsics, libmv_camera_intrinsics_options);
- libmv::Tracks normalized_tracks(markers);
+ /* Invert the camera intrinsics. */
+ libmv::Tracks normalized_tracks = getNormalizedTracks(tracks, camera_intrinsics);
+ /* Actual reconstruction. */
libmv::ModalSolver(normalized_tracks, reconstruction, &update_callback);
- progress_update_callback(callback_customdata, 1.0, "Finishing solution");
- libmv_reconstruction->tracks = *(libmv::Tracks *)tracks;
- libmv_reconstruction->error = libmv::EuclideanReprojectionError(*(libmv::Tracks *)tracks, *reconstruction, *intrinsics);
+ libmv::CameraIntrinsics empty_intrinsics;
+ libmv::EuclideanBundleCommonIntrinsics(normalized_tracks,
+ libmv::BUNDLE_NO_INTRINSICS,
+ reconstruction,
+ &empty_intrinsics,
+ libmv::BUNDLE_NO_TRANSLATION);
+
+ /* Refinement. */
+ if (libmv_reconstruction_options->refine_intrinsics) {
+ libmv_solveRefineIntrinsics((libmv::Tracks *)tracks, camera_intrinsics, reconstruction,
+ libmv_reconstruction_options->refine_intrinsics,
+ progress_update_callback, callback_customdata,
+ libmv::BUNDLE_NO_TRANSLATION);
+ }
+
+ /* Finish reconstruction. */
+ finishReconstruction(tracks, camera_intrinsics, libmv_reconstruction,
+ progress_update_callback, callback_customdata);
return (libmv_Reconstruction *)libmv_reconstruction;
}
@@ -863,17 +821,20 @@ struct libmv_CameraIntrinsics *libmv_ReconstructionExtractIntrinsics(struct libm
return (struct libmv_CameraIntrinsics *)&libmv_Reconstruction->intrinsics;
}
-struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNew(double focal_length, double principal_x, double principal_y,
- double k1, double k2, double k3, int width, int height)
+struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNewEmpty(void)
+{
+ libmv::CameraIntrinsics *camera_intrinsics = new libmv::CameraIntrinsics();
+
+ return (struct libmv_CameraIntrinsics *) camera_intrinsics;
+}
+
+struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNew(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options)
{
- libmv::CameraIntrinsics *intrinsics= new libmv::CameraIntrinsics();
+ libmv::CameraIntrinsics *camera_intrinsics = new libmv::CameraIntrinsics();
- intrinsics->SetFocalLength(focal_length, focal_length);
- intrinsics->SetPrincipalPoint(principal_x, principal_y);
- intrinsics->SetRadialDistortion(k1, k2, k3);
- intrinsics->SetImageSize(width, height);
+ cameraIntrinsicsFromOptions(camera_intrinsics, libmv_camera_intrinsics_options);
- return (struct libmv_CameraIntrinsics *) intrinsics;
+ return (struct libmv_CameraIntrinsics *) camera_intrinsics;
}
struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsCopy(struct libmv_CameraIntrinsics *libmvIntrinsics)
@@ -891,40 +852,70 @@ void libmv_CameraIntrinsicsDestroy(struct libmv_CameraIntrinsics *libmvIntrinsic
delete intrinsics;
}
-void libmv_CameraIntrinsicsUpdate(struct libmv_CameraIntrinsics *libmvIntrinsics, double focal_length,
- double principal_x, double principal_y, double k1, double k2, double k3, int width, int height)
+void libmv_CameraIntrinsicsUpdate(struct libmv_CameraIntrinsics *libmv_intrinsics,
+ libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options)
{
- libmv::CameraIntrinsics *intrinsics = (libmv::CameraIntrinsics *) libmvIntrinsics;
+ libmv::CameraIntrinsics *camera_intrinsics = (libmv::CameraIntrinsics *) libmv_intrinsics;
+
+ double focal_length = libmv_camera_intrinsics_options->focal_length;
+ double principal_x = libmv_camera_intrinsics_options->principal_point_x;
+ double principal_y = libmv_camera_intrinsics_options->principal_point_y;
+ double k1 = libmv_camera_intrinsics_options->k1;
+ double k2 = libmv_camera_intrinsics_options->k2;
+ double k3 = libmv_camera_intrinsics_options->k3;
+ int image_width = libmv_camera_intrinsics_options->image_width;
+ int image_height = libmv_camera_intrinsics_options->image_height;
+
+ /* try avoid unnecessary updates so pre-computed distortion grids are not freed */
- if (intrinsics->focal_length() != focal_length)
- intrinsics->SetFocalLength(focal_length, focal_length);
+ if (camera_intrinsics->focal_length() != focal_length)
+ camera_intrinsics->SetFocalLength(focal_length, focal_length);
+
+ if (camera_intrinsics->principal_point_x() != principal_x ||
+ camera_intrinsics->principal_point_y() != principal_y)
+ {
+ camera_intrinsics->SetPrincipalPoint(principal_x, principal_y);
+ }
+
+ if (camera_intrinsics->k1() != k1 ||
+ camera_intrinsics->k2() != k2 ||
+ camera_intrinsics->k3() != k3)
+ {
+ camera_intrinsics->SetRadialDistortion(k1, k2, k3);
+ }
- if (intrinsics->principal_point_x() != principal_x || intrinsics->principal_point_y() != principal_y)
- intrinsics->SetPrincipalPoint(principal_x, principal_y);
+ if (camera_intrinsics->image_width() != image_width ||
+ camera_intrinsics->image_height() != image_height)
+ {
+ camera_intrinsics->SetImageSize(image_width, image_height);
+ }
+}
- if (intrinsics->k1() != k1 || intrinsics->k2() != k2 || intrinsics->k3() != k3)
- intrinsics->SetRadialDistortion(k1, k2, k3);
+void libmv_CameraIntrinsicsSetThreads(struct libmv_CameraIntrinsics *libmv_intrinsics, int threads)
+{
+ libmv::CameraIntrinsics *camera_intrinsics = (libmv::CameraIntrinsics *) libmv_intrinsics;
- if (intrinsics->image_width() != width || intrinsics->image_height() != height)
- intrinsics->SetImageSize(width, height);
+ camera_intrinsics->SetThreads(threads);
}
-void libmv_CameraIntrinsicsExtract(struct libmv_CameraIntrinsics *libmvIntrinsics, double *focal_length,
- double *principal_x, double *principal_y, double *k1, double *k2, double *k3, int *width, int *height) {
- libmv::CameraIntrinsics *intrinsics= (libmv::CameraIntrinsics *) libmvIntrinsics;
- *focal_length = intrinsics->focal_length();
- *principal_x = intrinsics->principal_point_x();
- *principal_y = intrinsics->principal_point_y();
- *k1 = intrinsics->k1();
- *k2 = intrinsics->k2();
+void libmv_CameraIntrinsicsExtract(struct libmv_CameraIntrinsics *libmv_intrinsics, double *focal_length,
+ double *principal_x, double *principal_y, double *k1, double *k2, double *k3, int *width, int *height)
+{
+ libmv::CameraIntrinsics *camera_intrinsics = (libmv::CameraIntrinsics *) libmv_intrinsics;
+
+ *focal_length = camera_intrinsics->focal_length();
+ *principal_x = camera_intrinsics->principal_point_x();
+ *principal_y = camera_intrinsics->principal_point_y();
+ *k1 = camera_intrinsics->k1();
+ *k2 = camera_intrinsics->k2();
}
-void libmv_CameraIntrinsicsUndistortByte(struct libmv_CameraIntrinsics *libmvIntrinsics,
+void libmv_CameraIntrinsicsUndistortByte(struct libmv_CameraIntrinsics *libmv_intrinsics,
unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels)
{
- libmv::CameraIntrinsics *intrinsics = (libmv::CameraIntrinsics *) libmvIntrinsics;
+ libmv::CameraIntrinsics *camera_intrinsics = (libmv::CameraIntrinsics *) libmv_intrinsics;
- intrinsics->Undistort(src, dst, width, height, overscan, channels);
+ camera_intrinsics->Undistort(src, dst, width, height, overscan, channels);
}
void libmv_CameraIntrinsicsUndistortFloat(struct libmv_CameraIntrinsics *libmvIntrinsics,
@@ -950,139 +941,32 @@ void libmv_CameraIntrinsicsDistortFloat(struct libmv_CameraIntrinsics *libmvIntr
intrinsics->Distort(src, dst, width, height, overscan, channels);
}
-/* ************ distortion ************ */
-
-void libmv_undistortByte(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
- unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels)
-{
- libmv::CameraIntrinsics intrinsics;
-
- intrinsics.SetFocalLength(focal_length, focal_length);
- intrinsics.SetPrincipalPoint(principal_x, principal_y);
- intrinsics.SetRadialDistortion(k1, k2, k3);
-
- intrinsics.Undistort(src, dst, width, height, overscan, channels);
-}
-
-void libmv_undistortFloat(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
- float *src, float *dst, int width, int height, float overscan, int channels)
-{
- libmv::CameraIntrinsics intrinsics;
-
- intrinsics.SetFocalLength(focal_length, focal_length);
- intrinsics.SetPrincipalPoint(principal_x, principal_y);
- intrinsics.SetRadialDistortion(k1, k2, k3);
-
- intrinsics.Undistort(src, dst, width, height, overscan, channels);
-}
-
-void libmv_distortByte(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
- unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels)
-{
- libmv::CameraIntrinsics intrinsics;
-
- intrinsics.SetFocalLength(focal_length, focal_length);
- intrinsics.SetPrincipalPoint(principal_x, principal_y);
- intrinsics.SetRadialDistortion(k1, k2, k3);
-
- intrinsics.Distort(src, dst, width, height, overscan, channels);
-}
-
-void libmv_distortFloat(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
- float *src, float *dst, int width, int height, float overscan, int channels)
-{
- libmv::CameraIntrinsics intrinsics;
-
- intrinsics.SetFocalLength(focal_length, focal_length);
- intrinsics.SetPrincipalPoint(principal_x, principal_y);
- intrinsics.SetRadialDistortion(k1, k2, k3);
-
- intrinsics.Distort(src, dst, width, height, overscan, channels);
-}
-
/* ************ utils ************ */
-void libmv_applyCameraIntrinsics(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
- double x, double y, double *x1, double *y1)
+void libmv_applyCameraIntrinsics(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
+ double x, double y, double *x1, double *y1)
{
- libmv::CameraIntrinsics intrinsics;
+ libmv::CameraIntrinsics camera_intrinsics;
- intrinsics.SetFocalLength(focal_length, focal_length);
- intrinsics.SetPrincipalPoint(principal_x, principal_y);
- intrinsics.SetRadialDistortion(k1, k2, k3);
+ cameraIntrinsicsFromOptions(&camera_intrinsics, libmv_camera_intrinsics_options);
- if(focal_length) {
+ if (libmv_camera_intrinsics_options->focal_length) {
/* do a lens undistortion if focal length is non-zero only */
- intrinsics.ApplyIntrinsics(x, y, x1, y1);
+ camera_intrinsics.ApplyIntrinsics(x, y, x1, y1);
}
}
-void libmv_InvertIntrinsics(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
- double x, double y, double *x1, double *y1)
+void libmv_InvertIntrinsics(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
+ double x, double y, double *x1, double *y1)
{
- libmv::CameraIntrinsics intrinsics;
+ libmv::CameraIntrinsics camera_intrinsics;
- intrinsics.SetFocalLength(focal_length, focal_length);
- intrinsics.SetPrincipalPoint(principal_x, principal_y);
- intrinsics.SetRadialDistortion(k1, k2, k3);
+ cameraIntrinsicsFromOptions(&camera_intrinsics, libmv_camera_intrinsics_options);
- if(focal_length) {
+ if (libmv_camera_intrinsics_options->focal_length) {
/* do a lens distortion if focal length is non-zero only */
- intrinsics.InvertIntrinsics(x, y, x1, y1);
- }
-}
-
-/* ************ point clouds ************ */
-
-static void libmvTransformToMat4(libmv::Mat3 &R, libmv::Vec3 &S, libmv::Vec3 &t, double M[4][4])
-{
- for (int j = 0; j < 3; ++j)
- for (int k = 0; k < 3; ++k)
- M[j][k] = R(k, j) * S(j);
-
- for (int i = 0; i < 3; ++i) {
- M[3][0] = t(0);
- M[3][1] = t(1);
- M[3][2] = t(2);
-
- M[0][3] = M[1][3] = M[2][3] = 0;
- }
-
- M[3][3] = 1.0;
-}
-
-void libmv_rigidRegistration(float (*reference_points)[3], float (*points)[3], int total_points,
- int use_scale, int use_translation, double M[4][4])
-{
- libmv::Mat3 R;
- libmv::Vec3 S;
- libmv::Vec3 t;
- libmv::vector<libmv::Vec3> reference_points_vector, points_vector;
-
- for (int i = 0; i < total_points; i++) {
- reference_points_vector.push_back(libmv::Vec3(reference_points[i][0],
- reference_points[i][1],
- reference_points[i][2]));
-
- points_vector.push_back(libmv::Vec3(points[i][0],
- points[i][1],
- points[i][2]));
+ camera_intrinsics.InvertIntrinsics(x, y, x1, y1);
}
-
- if (use_scale && use_translation) {
- libmv::RigidRegistration(reference_points_vector, points_vector, R, S, t);
- }
- else if (use_translation) {
- S = libmv::Vec3(1.0, 1.0, 1.0);
- libmv::RigidRegistration(reference_points_vector, points_vector, R, t);
- }
- else {
- S = libmv::Vec3(1.0, 1.0, 1.0);
- t = libmv::Vec3::Zero();
- libmv::RigidRegistration(reference_points_vector, points_vector, R);
- }
-
- libmvTransformToMat4(R, S, t, M);
}
diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h
index e5885e7addf..c3debe45fd1 100644
--- a/extern/libmv/libmv-capi.h
+++ b/extern/libmv/libmv-capi.h
@@ -31,7 +31,6 @@
extern "C" {
#endif
-struct libmv_RegionTracker;
struct libmv_Tracks;
struct libmv_Reconstruction;
struct libmv_Features;
@@ -42,14 +41,6 @@ void libmv_initLogging(const char *argv0);
void libmv_startDebugLogging(void);
void libmv_setLoggingVerbosity(int verbosity);
-/* RegionTracker */
-struct libmv_RegionTracker *libmv_pyramidRegionTrackerNew(int max_iterations, int pyramid_level, int half_window_size, double minimum_correlation);
-struct libmv_RegionTracker *libmv_hybridRegionTrackerNew(int max_iterations, int half_window_size, double minimum_correlation);
-struct libmv_RegionTracker *libmv_bruteRegionTrackerNew(int half_window_size, double minimum_correlation);
-int libmv_regionTrackerTrack(struct libmv_RegionTracker *libmv_tracker, const float *ima1, const float *ima2,
- int width, int height, double x1, double y1, double *x2, double *y2);
-void libmv_regionTrackerDestroy(struct libmv_RegionTracker *libmv_tracker);
-
/* TrackRegion (new planar tracker) */
struct libmv_trackRegionOptions {
int motion_model;
@@ -86,28 +77,42 @@ void libmv_tracksInsert(struct libmv_Tracks *libmv_tracks, int image, int track,
void libmv_tracksDestroy(struct libmv_Tracks *libmv_tracks);
/* Reconstruction solver */
-#define LIBMV_REFINE_FOCAL_LENGTH (1<<0)
-#define LIBMV_REFINE_PRINCIPAL_POINT (1<<1)
-#define LIBMV_REFINE_RADIAL_DISTORTION_K1 (1<<2)
-#define LIBMV_REFINE_RADIAL_DISTORTION_K2 (1<<4)
-/* TODO: make keyframes/distortion model a part of options? */
-struct libmv_reconstructionOptions {
+#define LIBMV_REFINE_FOCAL_LENGTH (1 << 0)
+#define LIBMV_REFINE_PRINCIPAL_POINT (1 << 1)
+#define LIBMV_REFINE_RADIAL_DISTORTION_K1 (1 << 2)
+#define LIBMV_REFINE_RADIAL_DISTORTION_K2 (1 << 4)
+
+typedef struct libmv_cameraIntrinsicsOptions {
+ double focal_length;
+ double principal_point_x, principal_point_y;
+ double k1, k2, k3;
+ double p1, p2;
+ int image_width, image_height;
+} libmv_cameraIntrinsicsOptions;
+
+typedef struct libmv_reconstructionOptions {
+ int keyframe1, keyframe2;
+ int refine_intrinsics;
+
double success_threshold;
int use_fallback_reconstruction;
-};
+} libmv_reconstructionOptions;
typedef void (*reconstruct_progress_update_cb) (void *customdata, double progress, const char *message);
int libmv_refineParametersAreValid(int parameters);
-struct libmv_Reconstruction *libmv_solveReconstruction(struct libmv_Tracks *tracks, int keyframe1, int keyframe2,
- int refine_intrinsics, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
- struct libmv_reconstructionOptions *options, reconstruct_progress_update_cb progress_update_callback,
+struct libmv_Reconstruction *libmv_solveReconstruction(struct libmv_Tracks *libmv_tracks,
+ libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
+ libmv_reconstructionOptions *libmv_reconstruction_options,
+ reconstruct_progress_update_cb progress_update_callback,
+ void *callback_customdata);
+struct libmv_Reconstruction *libmv_solveModal(struct libmv_Tracks *libmv_tracks,
+ libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
+ libmv_reconstructionOptions *libmv_reconstruction_options,
+ reconstruct_progress_update_cb progress_update_callback,
void *callback_customdata);
-struct libmv_Reconstruction *libmv_solveModal(struct libmv_Tracks *tracks, double focal_length,
- double principal_x, double principal_y, double k1, double k2, double k3,
- reconstruct_progress_update_cb progress_update_callback, void *callback_customdata);
int libmv_reporojectionPointForTrack(struct libmv_Reconstruction *libmv_reconstruction, int track, double pos[3]);
double libmv_reporojectionErrorForTrack(struct libmv_Reconstruction *libmv_reconstruction, int track);
double libmv_reporojectionErrorForImage(struct libmv_Reconstruction *libmv_reconstruction, int image);
@@ -127,52 +132,40 @@ void libmv_destroyFeatures(struct libmv_Features *libmv_features);
/* camera intrinsics */
struct libmv_CameraIntrinsics *libmv_ReconstructionExtractIntrinsics(struct libmv_Reconstruction *libmv_Reconstruction);
-struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNew(double focal_length, double principal_x, double principal_y,
- double k1, double k2, double k3, int width, int height);
+struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNewEmpty(void);
-struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsCopy(struct libmv_CameraIntrinsics *libmvIntrinsics);
+struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNew(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options);
-void libmv_CameraIntrinsicsDestroy(struct libmv_CameraIntrinsics *libmvIntrinsics);
+struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsCopy(struct libmv_CameraIntrinsics *libmv_intrinsics);
-void libmv_CameraIntrinsicsUpdate(struct libmv_CameraIntrinsics *libmvIntrinsics, double focal_length,
- double principal_x, double principal_y, double k1, double k2, double k3, int width, int height);
+void libmv_CameraIntrinsicsDestroy(struct libmv_CameraIntrinsics *libmv_intrinsics);
-void libmv_CameraIntrinsicsExtract(struct libmv_CameraIntrinsics *libmvIntrinsics, double *focal_length,
- double *principal_x, double *principal_y, double *k1, double *k2, double *k3, int *width, int *height);
+void libmv_CameraIntrinsicsUpdate(struct libmv_CameraIntrinsics *libmv_intrinsics,
+ libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options);
-void libmv_CameraIntrinsicsUndistortByte(struct libmv_CameraIntrinsics *libmvIntrinsics,
- unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels);
+void libmv_CameraIntrinsicsSetThreads(struct libmv_CameraIntrinsics *libmv_intrinsics, int threads);
-void libmv_CameraIntrinsicsUndistortFloat(struct libmv_CameraIntrinsics *libmvIntrinsics,
- float *src, float *dst, int width, int height, float overscan, int channels);
+void libmv_CameraIntrinsicsExtract(struct libmv_CameraIntrinsics *libmv_intrinsics, double *focal_length,
+ double *principal_x, double *principal_y, double *k1, double *k2, double *k3, int *width, int *height);
-void libmv_CameraIntrinsicsDistortByte(struct libmv_CameraIntrinsics *libmvIntrinsics,
+void libmv_CameraIntrinsicsUndistortByte(struct libmv_CameraIntrinsics *libmv_intrinsics,
unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels);
-void libmv_CameraIntrinsicsDistortFloat(struct libmv_CameraIntrinsics *libmvIntrinsics,
+void libmv_CameraIntrinsicsUndistortFloat(struct libmv_CameraIntrinsics *libmv_intrinsics,
float *src, float *dst, int width, int height, float overscan, int channels);
-/* dsitortion */
-void libmv_undistortByte(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
+void libmv_CameraIntrinsicsDistortByte(struct libmv_CameraIntrinsics *libmv_intrinsics,
unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels);
-void libmv_undistortFloat(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
- float *src, float *dst, int width, int height, float overscan, int channels);
-void libmv_distortByte(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
- unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels);
-void libmv_distortFloat(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
+void libmv_CameraIntrinsicsDistortFloat(struct libmv_CameraIntrinsics *libmv_intrinsics,
float *src, float *dst, int width, int height, float overscan, int channels);
/* utils */
-void libmv_applyCameraIntrinsics(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
+void libmv_applyCameraIntrinsics(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
double x, double y, double *x1, double *y1);
-void libmv_InvertIntrinsics(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
+void libmv_InvertIntrinsics(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
double x, double y, double *x1, double *y1);
-/* point clouds */
-void libmv_rigidRegistration(float (*reference_points)[3], float (*points)[3], int total_points,
- int use_scale, int use_translation, double M[4][4]);
-
#ifdef __cplusplus
}
#endif
diff --git a/extern/libmv/libmv/multiview/euclidean_resection.cc b/extern/libmv/libmv/multiview/euclidean_resection.cc
index 2605bf04622..062c8b9067c 100644
--- a/extern/libmv/libmv/multiview/euclidean_resection.cc
+++ b/extern/libmv/libmv/multiview/euclidean_resection.cc
@@ -653,8 +653,8 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera,
// Finally, with all three solutions, select the (R, t) with the best RMSE.
VLOG(2) << "RMSE for solution 0: " << rmse(0);
- VLOG(2) << "RMSE for solution 1: " << rmse(0);
- VLOG(2) << "RMSE for solution 2: " << rmse(0);
+ VLOG(2) << "RMSE for solution 1: " << rmse(1);
+ VLOG(2) << "RMSE for solution 2: " << rmse(2);
size_t n = 0;
if (rmse(1) < rmse(0)) {
n = 1;
diff --git a/extern/libmv/libmv/multiview/homography.cc b/extern/libmv/libmv/multiview/homography.cc
index b5c483998d8..538c62598c0 100644
--- a/extern/libmv/libmv/multiview/homography.cc
+++ b/extern/libmv/libmv/multiview/homography.cc
@@ -264,4 +264,19 @@ bool Homography3DFromCorrespondencesLinear(const Mat &x1,
return false;
}
}
+
+double SymmetricGeometricDistance(Mat3 &H, Vec2 &x1, Vec2 &x2) {
+ Vec3 x(x1(0), x1(1), 1.0);
+ Vec3 y(x2(0), x2(1), 1.0);
+
+ Vec3 H_x = H * x;
+ Vec3 Hinv_y = H.inverse() * y;
+
+ H_x /= H_x(2);
+ Hinv_y /= Hinv_y(2);
+
+ return (H_x.head<2>() - y.head<2>()).squaredNorm() +
+ (Hinv_y.head<2>() - x.head<2>()).squaredNorm();
+}
+
} // namespace libmv
diff --git a/extern/libmv/libmv/multiview/homography.h b/extern/libmv/libmv/multiview/homography.h
index 786fd3df8ca..a295c4366b6 100644
--- a/extern/libmv/libmv/multiview/homography.h
+++ b/extern/libmv/libmv/multiview/homography.h
@@ -79,6 +79,14 @@ bool Homography3DFromCorrespondencesLinear(const Mat &x1,
Mat4 *H,
double expected_precision =
EigenDouble::dummy_precision());
+
+/**
+ * Calculate symmetric geometric cost:
+ *
+ * D(H * x1, x2)^2 + D(H^-1 * x2, x1)
+ */
+double SymmetricGeometricDistance(Mat3 &H, Vec2 &x1, Vec2 &x2);
+
} // namespace libmv
#endif // LIBMV_MULTIVIEW_HOMOGRAPHY_H_
diff --git a/extern/libmv/libmv/multiview/panography.h b/extern/libmv/libmv/multiview/panography.h
new file mode 100644
index 00000000000..6f01beb0ffd
--- /dev/null
+++ b/extern/libmv/libmv/multiview/panography.h
@@ -0,0 +1,181 @@
+// Copyright (c) 2009 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_MULTIVIEW_PANOGRAPHY_H
+#define LIBMV_MULTIVIEW_PANOGRAPHY_H
+
+#include "libmv/numeric/numeric.h"
+#include "libmv/numeric/poly.h"
+#include "libmv/base/vector.h"
+
+namespace libmv {
+
+static bool Build_Minimal2Point_PolynomialFactor(
+ const Mat & x1, const Mat & x2,
+ double * P) //P must be a double[4]
+{
+ assert(2 == x1.rows());
+ assert(2 == x1.cols());
+ assert(x1.rows() == x2.rows());
+ assert(x1.cols() == x2.cols());
+
+ // Setup the variable of the input problem:
+ Vec xx1 = (x1.col(0)).transpose();
+ Vec yx1 = (x1.col(1)).transpose();
+
+ double a12 = xx1.dot(yx1);
+ Vec xx2 = (x2.col(0)).transpose();
+ Vec yx2 = (x2.col(1)).transpose();
+ double b12 = xx2.dot(yx2);
+
+ double a1 = xx1.squaredNorm();
+ double a2 = yx1.squaredNorm();
+
+ double b1 = xx2.squaredNorm();
+ double b2 = yx2.squaredNorm();
+
+ // Build the 3rd degre polynomial in F^2.
+ //
+ // f^6 * p + f^4 * q + f^2* r + s = 0;
+ //
+ // Coefficients in ascending powers of alpha, i.e. P[N]*x^N.
+ // Run panography_coeffs.py to get the below coefficients.
+ P[0] = b1*b2*a12*a12-a1*a2*b12*b12;
+ P[1] = -2*a1*a2*b12+2*a12*b1*b2+b1*a12*a12+b2*a12*a12-a1*b12*b12-a2*b12*b12;
+ P[2] = b1*b2-a1*a2-2*a1*b12-2*a2*b12+2*a12*b1+2*a12*b2+a12*a12-b12*b12;
+ P[3] = b1+b2-2*b12-a1-a2+2*a12;
+
+ // If P[3] equal to 0 we get ill conditionned data
+ return (P[3] != 0.0);
+}
+
+// This implements a minimal solution (2 points) for panoramic stitching:
+//
+// http://www.cs.ubc.ca/~mbrown/minimal/minimal.html
+//
+// [1] M. Brown and R. Hartley and D. Nister. Minimal Solutions for Panoramic
+// Stitching. CVPR07.
+//
+// The 2-point algorithm solves for the rotation of the camera with a single
+// focal length (4 degrees of freedom).
+//
+// Compute from 1 to 3 possible focal lenght for 2 point correspondences.
+// Suppose that the cameras share the same optical center and focal lengths:
+//
+// Image 1 => H*x = x' => Image 2
+// x (u1j) x' (u2j)
+// a (u11) a' (u21)
+// b (u12) b' (u22)
+//
+// The return values are 1 to 3 possible values for the focal lengths such
+// that:
+//
+// [f 0 0]
+// K = [0 f 0]
+// [0 0 1]
+//
+static void F_FromCorrespondance_2points(const Mat &x1, const Mat &x2,
+ vector<double> *fs) {
+
+ // Build Polynomial factor to get squared focal value.
+ double P[4];
+ Build_Minimal2Point_PolynomialFactor(x1, x2, &P[0]);
+
+ // Solve it by using F = f^2 and a Cubic polynomial solver
+ //
+ // F^3 * p + F^2 * q + F^1 * r + s = 0
+ //
+ double roots[3];
+ int num_roots = SolveCubicPolynomial(P, roots);
+ for (int i = 0; i < num_roots; ++i) {
+ if (roots[i] > 0.0) {
+ fs->push_back(sqrt(roots[i]));
+ }
+ }
+}
+
+// Compute the 3x3 rotation matrix that fits two 3D point clouds in the least
+// square sense. The method is from:
+//
+// K. Arun,T. Huand and D. Blostein. Least-squares fitting of 2 3-D point
+// sets. IEEE Transactions on Pattern Analysis and Machine Intelligence,
+// 9:698-700, 1987.
+//
+// Given the calibration matrices K1, K2 solve for the rotation from
+// corresponding image rays.
+//
+// R = min || X2 - R * x1 ||.
+//
+// In case of panography, which is for a camera that shares the same camera
+// center,
+//
+// H = K2 * R * K1.inverse();
+//
+// For the full explanation, see Section 8, Solving for Rotation from [1].
+//
+// Parameters:
+//
+// x1 : Point cloud A (3D coords)
+// x2 : Point cloud B (3D coords)
+//
+// [f 0 0]
+// K1 = [0 f 0]
+// [0 0 1]
+//
+// K2 (the same form as K1, but may have different f)
+//
+// Returns: A rotation matrix that minimizes
+//
+// R = arg min || X2 - R * x1 ||
+//
+static void GetR_FixedCameraCenter(const Mat &x1, const Mat &x2,
+ const double focal,
+ Mat3 *R) {
+ assert(3 == x1.rows());
+ assert(2 <= x1.cols());
+ assert(x1.rows() == x2.rows());
+ assert(x1.cols() == x2.cols());
+
+ // Build simplified K matrix
+ Mat3 K( Mat3::Identity() * 1.0/focal );
+ K(2,2)= 1.0;
+
+ // Build the correlation matrix; equation (22) in [1].
+ Mat3 C = Mat3::Zero();
+ for(int i = 0; i < x1.cols(); ++i) {
+ Mat r1i = (K * x1.col(i)).normalized();
+ Mat r2i = (K * x2.col(i)).normalized();
+ C += r2i * r1i.transpose();
+ }
+
+ // Solve for rotation. Equations (24) and (25) in [1].
+ Eigen::JacobiSVD<Mat> svd(C, Eigen::ComputeThinU | Eigen::ComputeThinV);
+ Mat3 scale = Mat3::Identity();
+ scale(2,2) = ((svd.matrixU() * svd.matrixV().transpose()).determinant() > 0.0)
+ ? 1.0
+ : -1.0;
+
+ (*R) = svd.matrixU() * scale * svd.matrixV().transpose();
+}
+
+} // namespace libmv
+
+#endif // LIBMV_MULTIVIEW_PANOGRAPHY_H
diff --git a/extern/libmv/libmv/simple_pipeline/bundle.cc b/extern/libmv/libmv/simple_pipeline/bundle.cc
index d382cd5a4fc..3e36a78c9df 100644
--- a/extern/libmv/libmv/simple_pipeline/bundle.cc
+++ b/extern/libmv/libmv/simple_pipeline/bundle.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 libmv authors.
+// Copyright (c) 2011, 2012, 2013 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
@@ -18,10 +18,11 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
-#define V3DLIB_ENABLE_SUITESPARSE 1
-
#include <map>
+#include "ceres/ceres.h"
+#include "ceres/rotation.h"
+#include "libmv/base/scoped_ptr.h"
#include "libmv/base/vector.h"
#include "libmv/logging/logging.h"
#include "libmv/multiview/fundamental.h"
@@ -31,218 +32,340 @@
#include "libmv/simple_pipeline/bundle.h"
#include "libmv/simple_pipeline/reconstruction.h"
#include "libmv/simple_pipeline/tracks.h"
-#include "third_party/ssba/Geometry/v3d_cameramatrix.h"
-#include "third_party/ssba/Geometry/v3d_metricbundle.h"
-#include "third_party/ssba/Math/v3d_linear.h"
-#include "third_party/ssba/Math/v3d_linear_utils.h"
+
+#ifdef _OPENMP
+# include <omp.h>
+#endif
namespace libmv {
-void EuclideanBundle(const Tracks &tracks,
- EuclideanReconstruction *reconstruction) {
- CameraIntrinsics intrinsics;
- EuclideanBundleCommonIntrinsics(tracks,
- BUNDLE_NO_INTRINSICS,
- reconstruction,
- &intrinsics);
-}
+// The intrinsics need to get combined into a single parameter block; use these
+// enums to index instead of numeric constants.
+enum {
+ OFFSET_FOCAL_LENGTH,
+ OFFSET_PRINCIPAL_POINT_X,
+ OFFSET_PRINCIPAL_POINT_Y,
+ OFFSET_K1,
+ OFFSET_K2,
+ OFFSET_K3,
+ OFFSET_P1,
+ OFFSET_P2,
+};
-void EuclideanBundleCommonIntrinsics(const Tracks &tracks,
- int bundle_intrinsics,
- EuclideanReconstruction *reconstruction,
- CameraIntrinsics *intrinsics) {
- LG << "Original intrinsics: " << *intrinsics;
- vector<Marker> markers = tracks.AllMarkers();
+namespace {
- // "index" in this context is the index that V3D's optimizer will see. The
- // V3D index must be dense in that the cameras are numbered 0...n-1, which is
- // not the case for the "image" numbering that arises from the tracks
- // structure. The complicated mapping is necessary to convert between the two
- // representations.
- std::map<EuclideanCamera *, int> camera_to_index;
- std::map<EuclideanPoint *, int> point_to_index;
- vector<EuclideanCamera *> index_to_camera;
- vector<EuclideanPoint *> index_to_point;
- int num_cameras = 0;
- int num_points = 0;
- for (int i = 0; i < markers.size(); ++i) {
- const Marker &marker = markers[i];
- EuclideanCamera *camera = reconstruction->CameraForImage(marker.image);
- EuclideanPoint *point = reconstruction->PointForTrack(marker.track);
- if (camera && point) {
- if (camera_to_index.find(camera) == camera_to_index.end()) {
- camera_to_index[camera] = num_cameras;
- index_to_camera.push_back(camera);
- num_cameras++;
- }
- if (point_to_index.find(point) == point_to_index.end()) {
- point_to_index[point] = num_points;
- index_to_point.push_back(point);
- num_points++;
- }
- }
- }
+struct OpenCVReprojectionError {
+ OpenCVReprojectionError(double observed_x, double observed_y)
+ : observed_x(observed_x), observed_y(observed_y) {}
- // Convert libmv's K matrix to V3d's K matrix.
- V3D::Matrix3x3d v3d_K;
- for (int i = 0; i < 3; ++i) {
- for (int j = 0; j < 3; ++j) {
- v3d_K[i][j] = intrinsics->K()(i, j);
+ template <typename T>
+ bool operator()(const T* const intrinsics,
+ const T* const R, // Rotation 3x3 column-major.
+ const T* const t, // Translation 3x1.
+ const T* const X, // Point coordinates 3x1.
+ T* residuals) const {
+ // Unpack the intrinsics.
+ const T& focal_length = intrinsics[OFFSET_FOCAL_LENGTH];
+ const T& principal_point_x = intrinsics[OFFSET_PRINCIPAL_POINT_X];
+ const T& principal_point_y = intrinsics[OFFSET_PRINCIPAL_POINT_Y];
+ const T& k1 = intrinsics[OFFSET_K1];
+ const T& k2 = intrinsics[OFFSET_K2];
+ const T& k3 = intrinsics[OFFSET_K3];
+ const T& p1 = intrinsics[OFFSET_P1];
+ const T& p2 = intrinsics[OFFSET_P2];
+
+ // Compute projective coordinates: x = RX + t.
+ T x[3];
+ x[0] = R[0]*X[0] + R[3]*X[1] + R[6]*X[2] + t[0];
+ x[1] = R[1]*X[0] + R[4]*X[1] + R[7]*X[2] + t[1];
+ x[2] = R[2]*X[0] + R[5]*X[1] + R[8]*X[2] + t[2];
+
+ // Compute normalized coordinates: x /= x[2].
+ T xn = x[0] / x[2];
+ T yn = x[1] / x[2];
+
+ T predicted_x, predicted_y;
+
+ // EuclideanBundle uses empty intrinsics, which breaks undistortion code;
+ // so use an implied focal length of 1.0 if the focal length is exactly
+ // zero.
+ // TODO(keir): Figure out a better way to do this.
+ if (focal_length != T(0)) {
+ // Apply distortion to the normalized points to get (xd, yd).
+ // TODO(keir): Do early bailouts for zero distortion; these are expensive
+ // jet operations.
+
+ ApplyRadialDistortionCameraIntrinsics(focal_length,
+ focal_length,
+ principal_point_x,
+ principal_point_y,
+ k1, k2, k3,
+ p1, p2,
+ xn, yn,
+ &predicted_x,
+ &predicted_y);
+ } else {
+ predicted_x = xn;
+ predicted_y = yn;
}
+
+ // The error is the difference between the predicted and observed position.
+ residuals[0] = predicted_x - T(observed_x);
+ residuals[1] = predicted_y - T(observed_y);
+
+ return true;
}
- // Convert libmv's distortion to v3d distortion.
- V3D::StdDistortionFunction v3d_distortion;
- v3d_distortion.k1 = intrinsics->k1();
- v3d_distortion.k2 = intrinsics->k2();
- v3d_distortion.p1 = intrinsics->p1();
- v3d_distortion.p2 = intrinsics->p2();
-
- // Convert libmv's cameras to V3D's cameras.
- std::vector<V3D::CameraMatrix> v3d_cameras(index_to_camera.size());
- for (int k = 0; k < index_to_camera.size(); ++k) {
- V3D::Matrix3x3d R;
- V3D::Vector3d t;
-
- // Libmv's rotation matrix type.
- const Mat3 &R_libmv = index_to_camera[k]->R;
- const Vec3 &t_libmv = index_to_camera[k]->t;
-
- for (int i = 0; i < 3; ++i) {
- for (int j = 0; j < 3; ++j) {
- R[i][j] = R_libmv(i, j);
- }
- t[i] = t_libmv(i);
- }
- v3d_cameras[k].setIntrinsic(v3d_K);
- v3d_cameras[k].setRotation(R);
- v3d_cameras[k].setTranslation(t);
+ double observed_x;
+ double observed_y;
+};
+
+// TODO(keir): Get rid of the parameterization! Ceres will work much faster if
+// the rotation block is angle-axis and also the translation is merged into a
+// single parameter block.
+struct RotationMatrixPlus {
+ template<typename T>
+ bool operator()(const T* R_array, // Rotation 3x3 col-major.
+ const T* delta, // Angle-axis delta
+ T* R_plus_delta_array) const {
+ T angle_axis[3];
+
+ ceres::RotationMatrixToAngleAxis(R_array, angle_axis);
+
+ angle_axis[0] += delta[0];
+ angle_axis[1] += delta[1];
+ angle_axis[2] += delta[2];
+
+ ceres::AngleAxisToRotationMatrix(angle_axis, R_plus_delta_array);
+
+ return true;
}
- LG << "Number of cameras: " << index_to_camera.size();
-
- // Convert libmv's points to V3D's points.
- std::vector<V3D::Vector3d> v3d_points(index_to_point.size());
- for (int i = 0; i < index_to_point.size(); i++) {
- v3d_points[i][0] = index_to_point[i]->X(0);
- v3d_points[i][1] = index_to_point[i]->X(1);
- v3d_points[i][2] = index_to_point[i]->X(2);
+};
+
+// TODO(sergey): would be nice to have this in Ceres upstream
+template<typename PlusFunctor, int kGlobalSize, int kLocalSize>
+class AutodiffParameterization : public ceres::LocalParameterization {
+ public:
+ AutodiffParameterization(const PlusFunctor &plus_functor)
+ : plus_functor_(plus_functor) {}
+
+ virtual ~AutodiffParameterization() {}
+
+ virtual bool Plus(const double* x,
+ const double* delta,
+ double* x_plus_delta) const {
+ return plus_functor_(x, delta, x_plus_delta);
}
- LG << "Number of points: " << index_to_point.size();
- // Convert libmv's measurements to v3d measurements.
- int num_residuals = 0;
- std::vector<V3D::Vector2d> v3d_measurements;
- std::vector<int> v3d_camera_for_measurement;
- std::vector<int> v3d_point_for_measurement;
- for (int i = 0; i < markers.size(); ++i) {
- EuclideanCamera *camera = reconstruction->CameraForImage(markers[i].image);
- EuclideanPoint *point = reconstruction->PointForTrack(markers[i].track);
- if (!camera || !point) {
- continue;
- }
- V3D::Vector2d v3d_point;
- v3d_point[0] = markers[i].x;
- v3d_point[1] = markers[i].y;
- v3d_measurements.push_back(v3d_point);
- v3d_camera_for_measurement.push_back(camera_to_index[camera]);
- v3d_point_for_measurement.push_back(point_to_index[point]);
- num_residuals++;
+ virtual bool ComputeJacobian(const double* x, double* jacobian) const {
+ double zero_delta[kLocalSize] = { 0.0 };
+ double x_plus_delta[kGlobalSize];
+ const double* parameters[2] = { x, zero_delta };
+ double* jacobians_array[2] = { NULL, jacobian };
+
+ Plus(x, zero_delta, x_plus_delta);
+
+ return ceres::internal::AutoDiff<PlusFunctor,
+ double,
+ kGlobalSize, kLocalSize>
+ ::Differentiate(plus_functor_,
+ parameters,
+ kGlobalSize,
+ x_plus_delta,
+ jacobians_array);
+
+ return true;
}
- LG << "Number of residuals: " << num_residuals;
-
- // Convert from libmv's specification for which intrinsics to bundle to V3D's.
- int v3d_bundle_intrinsics;
+
+ virtual int GlobalSize() const { return kGlobalSize; }
+ virtual int LocalSize() const { return kLocalSize; }
+
+ private:
+ const PlusFunctor &plus_functor_;
+};
+
+void BundleIntrinsicsLogMessage(int bundle_intrinsics) {
if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) {
LG << "Bundling only camera positions.";
- v3d_bundle_intrinsics = V3D::FULL_BUNDLE_METRIC;
} else if (bundle_intrinsics == BUNDLE_FOCAL_LENGTH) {
LG << "Bundling f.";
- v3d_bundle_intrinsics = V3D::FULL_BUNDLE_FOCAL_LENGTH;
} else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
BUNDLE_PRINCIPAL_POINT)) {
LG << "Bundling f, px, py.";
- v3d_bundle_intrinsics = V3D::FULL_BUNDLE_FOCAL_LENGTH_PP;
} else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
BUNDLE_PRINCIPAL_POINT |
BUNDLE_RADIAL)) {
LG << "Bundling f, px, py, k1, k2.";
- v3d_bundle_intrinsics = V3D::FULL_BUNDLE_RADIAL;
} else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
BUNDLE_PRINCIPAL_POINT |
BUNDLE_RADIAL |
BUNDLE_TANGENTIAL)) {
LG << "Bundling f, px, py, k1, k2, p1, p2.";
- v3d_bundle_intrinsics = V3D::FULL_BUNDLE_RADIAL_TANGENTIAL;
} else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
BUNDLE_RADIAL |
BUNDLE_TANGENTIAL)) {
LG << "Bundling f, px, py, k1, k2, p1, p2.";
- v3d_bundle_intrinsics = V3D::FULL_BUNDLE_RADIAL_TANGENTIAL;
} else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
BUNDLE_RADIAL)) {
LG << "Bundling f, k1, k2.";
- v3d_bundle_intrinsics = V3D::FULL_BUNDLE_FOCAL_AND_RADIAL;
} else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
BUNDLE_RADIAL_K1)) {
LG << "Bundling f, k1.";
- v3d_bundle_intrinsics = V3D::FULL_BUNDLE_FOCAL_AND_RADIAL_K1;
+ } else if (bundle_intrinsics == (BUNDLE_RADIAL_K1 |
+ BUNDLE_RADIAL_K2)) {
+ LG << "Bundling k1, k2.";
} else {
LOG(FATAL) << "Unsupported bundle combination.";
}
+}
- // Ignore any outliers; assume supervised tracking.
- double v3d_inlier_threshold = 500000.0;
-
- // Finally, run the bundle adjustment.
- V3D::CommonInternalsMetricBundleOptimizer opt(v3d_bundle_intrinsics,
- v3d_inlier_threshold,
- v3d_K,
- v3d_distortion,
- v3d_cameras,
- v3d_points,
- v3d_measurements,
- v3d_camera_for_measurement,
- v3d_point_for_measurement);
- opt.maxIterations = 500;
- opt.minimize();
- if (opt.status == V3D::LEVENBERG_OPTIMIZER_TIMEOUT) {
- LG << "Bundle status: Timed out.";
- } else if (opt.status == V3D::LEVENBERG_OPTIMIZER_SMALL_UPDATE) {
- LG << "Bundle status: Small update.";
- } else if (opt.status == V3D::LEVENBERG_OPTIMIZER_CONVERGED) {
- LG << "Bundle status: Converged.";
- }
+} // namespace
- // Convert V3D's K matrix back to libmv's K matrix.
- Mat3 K;
- for (int i = 0; i < 3; ++i) {
- for (int j = 0; j < 3; ++j) {
- K(i, j) = v3d_K[i][j];
+void EuclideanBundle(const Tracks &tracks,
+ EuclideanReconstruction *reconstruction) {
+ CameraIntrinsics intrinsics;
+ EuclideanBundleCommonIntrinsics(tracks,
+ BUNDLE_NO_INTRINSICS,
+ reconstruction,
+ &intrinsics);
+}
+
+void EuclideanBundleCommonIntrinsics(const Tracks &tracks,
+ int bundle_intrinsics,
+ EuclideanReconstruction *reconstruction,
+ CameraIntrinsics *intrinsics,
+ int bundle_constraints) {
+ LG << "Original intrinsics: " << *intrinsics;
+ vector<Marker> markers = tracks.AllMarkers();
+
+ ceres::Problem::Options problem_options;
+ problem_options.local_parameterization_ownership =
+ ceres::DO_NOT_TAKE_OWNERSHIP;
+
+ ceres::Problem problem(problem_options);
+
+ // Residual blocks with 10 parameters are unwieldly with Ceres, so pack the
+ // intrinsics into a single block and rely on local parameterizations to
+ // control which intrinsics are allowed to vary.
+ double ceres_intrinsics[8];
+ ceres_intrinsics[OFFSET_FOCAL_LENGTH] = intrinsics->focal_length();
+ ceres_intrinsics[OFFSET_PRINCIPAL_POINT_X] = intrinsics->principal_point_x();
+ ceres_intrinsics[OFFSET_PRINCIPAL_POINT_Y] = intrinsics->principal_point_y();
+ ceres_intrinsics[OFFSET_K1] = intrinsics->k1();
+ ceres_intrinsics[OFFSET_K2] = intrinsics->k2();
+ ceres_intrinsics[OFFSET_K3] = intrinsics->k3();
+ ceres_intrinsics[OFFSET_P1] = intrinsics->p1();
+ ceres_intrinsics[OFFSET_P2] = intrinsics->p2();
+
+ RotationMatrixPlus rotation_matrix_plus;
+ AutodiffParameterization<RotationMatrixPlus, 9, 3>
+ rotation_parameterization(rotation_matrix_plus);
+
+ int num_residuals = 0;
+ for (int i = 0; i < markers.size(); ++i) {
+ const Marker &marker = markers[i];
+ EuclideanCamera *camera = reconstruction->CameraForImage(marker.image);
+ EuclideanPoint *point = reconstruction->PointForTrack(marker.track);
+ if (!camera || !point) {
+ continue;
}
- }
- intrinsics->SetK(K);
-
- // Convert V3D's distortion back to libmv's distortion.
- intrinsics->SetRadialDistortion(v3d_distortion.k1, v3d_distortion.k2, 0.0);
- intrinsics->SetTangentialDistortion(v3d_distortion.p1, v3d_distortion.p2);
-
- // Convert V3D's cameras back to libmv's cameras.
- for (int k = 0; k < num_cameras; k++) {
- V3D::Matrix3x4d const Rt = v3d_cameras[k].getOrientation();
- for (int i = 0; i < 3; ++i) {
- for (int j = 0; j < 3; ++j) {
- index_to_camera[k]->R(i, j) = Rt[i][j];
- }
- index_to_camera[k]->t(i) = Rt[i][3];
+
+ problem.AddResidualBlock(new ceres::AutoDiffCostFunction<
+ OpenCVReprojectionError, 2, 8, 9, 3, 3>(
+ new OpenCVReprojectionError(
+ marker.x,
+ marker.y)),
+ NULL,
+ ceres_intrinsics,
+ &camera->R(0, 0),
+ &camera->t(0),
+ &point->X(0));
+
+ // It's fine if the parameterization for one camera is set repeatedly.
+ problem.SetParameterization(&camera->R(0, 0),
+ &rotation_parameterization);
+
+ if (bundle_constraints & BUNDLE_NO_TRANSLATION) {
+ problem.SetParameterBlockConstant(&camera->t(0));
}
+
+ num_residuals++;
}
+ LG << "Number of residuals: " << num_residuals;
+
+ if(!num_residuals) {
+ LG << "Skipping running minimizer with zero residuals";
+ return;
+ }
+
+ BundleIntrinsicsLogMessage(bundle_intrinsics);
+
+ scoped_ptr<ceres::SubsetParameterization>
+ subset_parameterization(NULL);
+
+ if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) {
+ // No camera intrinsics are refining,
+ // set the whole parameter block as constant for best performance
+ problem.SetParameterBlockConstant(ceres_intrinsics);
+ } else {
+ // Set intrinsics not being bundles as constant
- // Convert V3D's points back to libmv's points.
- for (int k = 0; k < num_points; k++) {
- for (int i = 0; i < 3; ++i) {
- index_to_point[k]->X(i) = v3d_points[k][i];
+ std::vector<int> constant_intrinsics;
+#define MAYBE_SET_CONSTANT(bundle_enum, offset) \
+ if (!(bundle_intrinsics & bundle_enum)) { \
+ constant_intrinsics.push_back(offset); \
}
+ MAYBE_SET_CONSTANT(BUNDLE_FOCAL_LENGTH, OFFSET_FOCAL_LENGTH);
+ MAYBE_SET_CONSTANT(BUNDLE_PRINCIPAL_POINT, OFFSET_PRINCIPAL_POINT_X);
+ MAYBE_SET_CONSTANT(BUNDLE_PRINCIPAL_POINT, OFFSET_PRINCIPAL_POINT_Y);
+ MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K1, OFFSET_K1);
+ MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K2, OFFSET_K2);
+ MAYBE_SET_CONSTANT(BUNDLE_TANGENTIAL_P1, OFFSET_P1);
+ MAYBE_SET_CONSTANT(BUNDLE_TANGENTIAL_P2, OFFSET_P2);
+#undef MAYBE_SET_CONSTANT
+
+ // Always set K3 constant, it's not used at the moment.
+ constant_intrinsics.push_back(OFFSET_K3);
+
+ subset_parameterization.reset(
+ new ceres::SubsetParameterization(8, constant_intrinsics));
+
+ problem.SetParameterization(ceres_intrinsics, subset_parameterization.get());
}
+
+ ceres::Solver::Options options;
+ options.use_nonmonotonic_steps = true;
+ options.preconditioner_type = ceres::SCHUR_JACOBI;
+ options.linear_solver_type = ceres::ITERATIVE_SCHUR;
+ options.use_inner_iterations = true;
+ options.max_num_iterations = 100;
+
+#ifdef _OPENMP
+ options.num_threads = omp_get_max_threads();
+ options.num_linear_solver_threads = omp_get_max_threads();
+#endif
+
+ ceres::Solver::Summary summary;
+ ceres::Solve(options, &problem, &summary);
+
+ LG << "Final report:\n" << summary.FullReport();
+
+ // Copy intrinsics back.
+ if (bundle_intrinsics != BUNDLE_NO_INTRINSICS) {
+ intrinsics->SetFocalLength(ceres_intrinsics[OFFSET_FOCAL_LENGTH],
+ ceres_intrinsics[OFFSET_FOCAL_LENGTH]);
+
+ intrinsics->SetPrincipalPoint(ceres_intrinsics[OFFSET_PRINCIPAL_POINT_X],
+ ceres_intrinsics[OFFSET_PRINCIPAL_POINT_Y]);
+
+ intrinsics->SetRadialDistortion(ceres_intrinsics[OFFSET_K1],
+ ceres_intrinsics[OFFSET_K2],
+ ceres_intrinsics[OFFSET_K3]);
+
+ intrinsics->SetTangentialDistortion(ceres_intrinsics[OFFSET_P1],
+ ceres_intrinsics[OFFSET_P2]);
+ }
+
LG << "Final intrinsics: " << *intrinsics;
}
diff --git a/extern/libmv/libmv/simple_pipeline/bundle.h b/extern/libmv/libmv/simple_pipeline/bundle.h
index 55657cb2d92..573bcf4cc21 100644
--- a/extern/libmv/libmv/simple_pipeline/bundle.h
+++ b/extern/libmv/libmv/simple_pipeline/bundle.h
@@ -67,6 +67,11 @@ void EuclideanBundle(const Tracks &tracks,
BUNDLE_FOCAL_LENGTH | BUNDLE_PRINCIPAL_POINT
BUNDLE_FOCAL_LENGTH | BUNDLE_PRINCIPAL_POINT | BUNDLE_RADIAL
BUNDLE_FOCAL_LENGTH | BUNDLE_PRINCIPAL_POINT | BUNDLE_RADIAL | BUNDLE_TANGENTIAL
+ BUNDLE_RADIAL
+
+ Constraints denotes which blocks to keep constant during bundling.
+ For example it is useful to keep camera translations constant
+ when bundling tripod motions.
\note This assumes an outlier-free set of markers.
@@ -83,10 +88,15 @@ enum BundleIntrinsics {
BUNDLE_TANGENTIAL_P2 = 32,
BUNDLE_TANGENTIAL = 48,
};
+enum BundleConstraints {
+ BUNDLE_NO_CONSTRAINTS = 0,
+ BUNDLE_NO_TRANSLATION = 1,
+};
void EuclideanBundleCommonIntrinsics(const Tracks &tracks,
int bundle_intrinsics,
EuclideanReconstruction *reconstruction,
- CameraIntrinsics *intrinsics);
+ CameraIntrinsics *intrinsics,
+ int bundle_constraints = BUNDLE_NO_CONSTRAINTS);
/*!
Refine camera poses and 3D coordinates using bundle adjustment.
diff --git a/extern/libmv/libmv/simple_pipeline/camera_intrinsics.cc b/extern/libmv/libmv/simple_pipeline/camera_intrinsics.cc
index 6319846a079..543fddedd0c 100644
--- a/extern/libmv/libmv/simple_pipeline/camera_intrinsics.cc
+++ b/extern/libmv/libmv/simple_pipeline/camera_intrinsics.cc
@@ -62,7 +62,8 @@ CameraIntrinsics::CameraIntrinsics()
p1_(0),
p2_(0),
distort_(0),
- undistort_(0) {}
+ undistort_(0),
+ threads_(1) {}
CameraIntrinsics::CameraIntrinsics(const CameraIntrinsics &from)
: K_(from.K_),
@@ -72,7 +73,8 @@ CameraIntrinsics::CameraIntrinsics(const CameraIntrinsics &from)
k2_(from.k2_),
k3_(from.k3_),
p1_(from.p1_),
- p2_(from.p2_)
+ p2_(from.p2_),
+ threads_(from.threads_)
{
distort_ = copyGrid(from.distort_);
undistort_ = copyGrid(from.undistort_);
@@ -120,24 +122,25 @@ void CameraIntrinsics::SetTangentialDistortion(double p1, double p2) {
FreeLookupGrid();
}
+void CameraIntrinsics::SetThreads(int threads)
+{
+ threads_ = threads;
+}
+
void CameraIntrinsics::ApplyIntrinsics(double normalized_x,
double normalized_y,
double *image_x,
double *image_y) const {
- double x = normalized_x;
- double y = normalized_y;
-
- // Apply distortion to the normalized points to get (xd, yd).
- double r2 = x*x + y*y;
- double r4 = r2 * r2;
- double r6 = r4 * r2;
- double r_coeff = (1 + k1_*r2 + k2_*r4 + k3_*r6);
- double xd = x * r_coeff + 2*p1_*x*y + p2_*(r2 + 2*x*x);
- double yd = y * r_coeff + 2*p2_*x*y + p1_*(r2 + 2*y*y);
-
- // Apply focal length and principal point to get the final image coordinates.
- *image_x = focal_length_x() * xd + principal_point_x();
- *image_y = focal_length_y() * yd + principal_point_y();
+ ApplyRadialDistortionCameraIntrinsics(focal_length_x(),
+ focal_length_y(),
+ principal_point_x(),
+ principal_point_y(),
+ k1(), k2(), k3(),
+ p1(), p2(),
+ normalized_x,
+ normalized_y,
+ image_x,
+ image_y);
}
struct InvertIntrinsicsCostFunction {
@@ -192,6 +195,7 @@ void CameraIntrinsics::ComputeLookupGrid(Grid* grid, int width, int height, doub
double aspx = (double)w / image_width_;
double aspy = (double)h / image_height_;
+ #pragma omp parallel for schedule(dynamic) num_threads(threads_) if (threads_ > 1 && height > 100)
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
double src_x = (x - 0.5 * overscan * w) / aspx, src_y = (y - 0.5 * overscan * h) / aspy;
@@ -218,7 +222,8 @@ void CameraIntrinsics::ComputeLookupGrid(Grid* grid, int width, int height, doub
// TODO(MatthiasF): cubic B-Spline image sampling, bilinear lookup
template<typename T,int N>
static void Warp(const Grid* grid, const T* src, T* dst,
- int width, int height) {
+ int width, int height, int threads) {
+ #pragma omp parallel for schedule(dynamic) num_threads(threads) if (threads > 1 && height > 100)
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
Offset offset = grid->offset[y*width+x];
@@ -310,37 +315,37 @@ void CameraIntrinsics::CheckUndistortLookupGrid(int width, int height, double ov
void CameraIntrinsics::Distort(const float* src, float* dst, int width, int height, double overscan, int channels) {
CheckDistortLookupGrid(width, height, overscan);
- if(channels==1) Warp<float,1>(distort_,src,dst,width,height);
- else if(channels==2) Warp<float,2>(distort_,src,dst,width,height);
- else if(channels==3) Warp<float,3>(distort_,src,dst,width,height);
- else if(channels==4) Warp<float,4>(distort_,src,dst,width,height);
+ if(channels==1) Warp<float,1>(distort_,src,dst,width,height,threads_);
+ else if(channels==2) Warp<float,2>(distort_,src,dst,width,height,threads_);
+ else if(channels==3) Warp<float,3>(distort_,src,dst,width,height,threads_);
+ else if(channels==4) Warp<float,4>(distort_,src,dst,width,height,threads_);
//else assert("channels must be between 1 and 4");
}
void CameraIntrinsics::Distort(const unsigned char* src, unsigned char* dst, int width, int height, double overscan, int channels) {
CheckDistortLookupGrid(width, height, overscan);
- if(channels==1) Warp<unsigned char,1>(distort_,src,dst,width,height);
- else if(channels==2) Warp<unsigned char,2>(distort_,src,dst,width,height);
- else if(channels==3) Warp<unsigned char,3>(distort_,src,dst,width,height);
- else if(channels==4) Warp<unsigned char,4>(distort_,src,dst,width,height);
+ if(channels==1) Warp<unsigned char,1>(distort_,src,dst,width,height,threads_);
+ else if(channels==2) Warp<unsigned char,2>(distort_,src,dst,width,height,threads_);
+ else if(channels==3) Warp<unsigned char,3>(distort_,src,dst,width,height,threads_);
+ else if(channels==4) Warp<unsigned char,4>(distort_,src,dst,width,height,threads_);
//else assert("channels must be between 1 and 4");
}
void CameraIntrinsics::Undistort(const float* src, float* dst, int width, int height, double overscan, int channels) {
CheckUndistortLookupGrid(width, height, overscan);
- if(channels==1) Warp<float,1>(undistort_,src,dst,width,height);
- else if(channels==2) Warp<float,2>(undistort_,src,dst,width,height);
- else if(channels==3) Warp<float,3>(undistort_,src,dst,width,height);
- else if(channels==4) Warp<float,4>(undistort_,src,dst,width,height);
+ if(channels==1) Warp<float,1>(undistort_,src,dst,width,height,threads_);
+ else if(channels==2) Warp<float,2>(undistort_,src,dst,width,height,threads_);
+ else if(channels==3) Warp<float,3>(undistort_,src,dst,width,height,threads_);
+ else if(channels==4) Warp<float,4>(undistort_,src,dst,width,height,threads_);
//else assert("channels must be between 1 and 4");
}
void CameraIntrinsics::Undistort(const unsigned char* src, unsigned char* dst, int width, int height, double overscan, int channels) {
CheckUndistortLookupGrid(width, height, overscan);
- if(channels==1) Warp<unsigned char,1>(undistort_,src,dst,width,height);
- else if(channels==2) Warp<unsigned char,2>(undistort_,src,dst,width,height);
- else if(channels==3) Warp<unsigned char,3>(undistort_,src,dst,width,height);
- else if(channels==4) Warp<unsigned char,4>(undistort_,src,dst,width,height);
+ if(channels==1) Warp<unsigned char,1>(undistort_,src,dst,width,height,threads_);
+ else if(channels==2) Warp<unsigned char,2>(undistort_,src,dst,width,height,threads_);
+ else if(channels==3) Warp<unsigned char,3>(undistort_,src,dst,width,height,threads_);
+ else if(channels==4) Warp<unsigned char,4>(undistort_,src,dst,width,height,threads_);
//else assert("channels must be between 1 and 4");
}
diff --git a/extern/libmv/libmv/simple_pipeline/camera_intrinsics.h b/extern/libmv/libmv/simple_pipeline/camera_intrinsics.h
index e0556674ad5..632922c38ff 100644
--- a/extern/libmv/libmv/simple_pipeline/camera_intrinsics.h
+++ b/extern/libmv/libmv/simple_pipeline/camera_intrinsics.h
@@ -68,6 +68,9 @@ class CameraIntrinsics {
void SetTangentialDistortion(double p1, double p2);
+ /// Set number of threads using for buffer distortion/undistortion
+ void SetThreads(int threads);
+
/*!
Apply camera intrinsics to the normalized point to get image coordinates.
@@ -153,12 +156,45 @@ class CameraIntrinsics {
struct Grid *distort_;
struct Grid *undistort_;
+
+ int threads_;
};
/// A human-readable representation of the camera intrinsic parameters.
std::ostream& operator <<(std::ostream &os,
const CameraIntrinsics &intrinsics);
+// Apply camera intrinsics to the normalized point to get image coordinates.
+// This applies the radial lens distortion to a point which is in normalized
+// camera coordinates (i.e. the principal point is at (0, 0)) to get image
+// coordinates in pixels. Templated for use with autodifferentiation.
+template <typename T>
+inline void ApplyRadialDistortionCameraIntrinsics(T focal_length_x,
+ T focal_length_y,
+ T principal_point_x,
+ T principal_point_y,
+ T k1, T k2, T k3,
+ T p1, T p2,
+ T normalized_x,
+ T normalized_y,
+ T *image_x,
+ T *image_y) {
+ T x = normalized_x;
+ T y = normalized_y;
+
+ // Apply distortion to the normalized points to get (xd, yd).
+ T r2 = x*x + y*y;
+ T r4 = r2 * r2;
+ T r6 = r4 * r2;
+ T r_coeff = (T(1) + k1*r2 + k2*r4 + k3*r6);
+ T xd = x * r_coeff + T(2)*p1*x*y + p2*(r2 + T(2)*x*x);
+ T yd = y * r_coeff + T(2)*p2*x*y + p1*(r2 + T(2)*y*y);
+
+ // Apply focal length and principal point to get the final image coordinates.
+ *image_x = focal_length_x * xd + principal_point_x;
+ *image_y = focal_length_y * yd + principal_point_y;
+}
+
} // namespace libmv
#endif // LIBMV_SIMPLE_PIPELINE_CAMERA_INTRINSICS_H_
diff --git a/extern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc b/extern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc
index 9c06d1ef4e6..84d143b77d6 100644
--- a/extern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc
+++ b/extern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc
@@ -31,22 +31,6 @@
namespace libmv {
namespace {
-void CoordinatesForMarkersInImage(const vector<Marker> &markers,
- int image,
- Mat *coordinates) {
- vector<Vec2> coords;
- for (int i = 0; i < markers.size(); ++i) {
- const Marker &marker = markers[i];
- if (markers[i].image == image) {
- coords.push_back(Vec2(marker.x, marker.y));
- }
- }
- coordinates->resize(2, coords.size());
- for (int i = 0; i < coords.size(); i++) {
- coordinates->col(i) = coords[i];
- }
-}
-
void GetImagesInMarkers(const vector<Marker> &markers,
int *image1, int *image2) {
if (markers.size() < 2) {
diff --git a/extern/libmv/libmv/simple_pipeline/intersect.cc b/extern/libmv/libmv/simple_pipeline/intersect.cc
index 0c2f744dc1c..d0f139a991a 100644
--- a/extern/libmv/libmv/simple_pipeline/intersect.cc
+++ b/extern/libmv/libmv/simple_pipeline/intersect.cc
@@ -18,6 +18,8 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
+#include "libmv/simple_pipeline/intersect.h"
+
#include "libmv/base/vector.h"
#include "libmv/logging/logging.h"
#include "libmv/multiview/projection.h"
@@ -26,39 +28,41 @@
#include "libmv/multiview/projection.h"
#include "libmv/numeric/numeric.h"
#include "libmv/numeric/levenberg_marquardt.h"
-#include "libmv/simple_pipeline/intersect.h"
#include "libmv/simple_pipeline/reconstruction.h"
#include "libmv/simple_pipeline/tracks.h"
+#include "ceres/ceres.h"
+
namespace libmv {
namespace {
-struct EuclideanIntersectCostFunction {
+class EuclideanIntersectCostFunctor {
public:
- typedef Vec FMatrixType;
- typedef Vec3 XMatrixType;
+ EuclideanIntersectCostFunctor(const Marker &marker,
+ const EuclideanCamera &camera)
+ : marker_(marker), camera_(camera) {}
- EuclideanIntersectCostFunction(const vector<Marker> &markers,
- const EuclideanReconstruction &reconstruction)
- : markers(markers),
- reconstruction(reconstruction) {}
+ template<typename T>
+ bool operator()(const T *X, T *residuals) const {
+ typedef Eigen::Matrix<T, 3, 3> Mat3;
+ typedef Eigen::Matrix<T, 3, 1> Vec3;
- Vec operator()(const Vec3 &X) const {
- Vec residuals(2 * markers.size());
- residuals.setZero();
- for (int i = 0; i < markers.size(); ++i) {
- const EuclideanCamera &camera =
- *reconstruction.CameraForImage(markers[i].image);
- Vec3 projected = camera.R * X + camera.t;
- projected /= projected(2);
- residuals[2*i + 0] = projected(0) - markers[i].x;
- residuals[2*i + 1] = projected(1) - markers[i].y;
- }
- return residuals;
+ Vec3 x(X);
+ Mat3 R(camera_.R.cast<T>());
+ Vec3 t(camera_.t.cast<T>());
+
+ Vec3 projected = R * x + t;
+ projected /= projected(2);
+
+ residuals[0] = projected(0) - T(marker_.x);
+ residuals[1] = projected(1) - T(marker_.y);
+
+ return true;
}
- const vector<Marker> &markers;
- const EuclideanReconstruction &reconstruction;
+
+ const Marker &marker_;
+ const EuclideanCamera &camera_;
};
} // namespace
@@ -95,13 +99,35 @@ bool EuclideanIntersect(const vector<Marker> &markers,
Xp /= Xp(3);
Vec3 X = Xp.head<3>();
- typedef LevenbergMarquardt<EuclideanIntersectCostFunction> Solver;
+ ceres::Problem problem;
- EuclideanIntersectCostFunction triangulate_cost(markers, *reconstruction);
- Solver::SolverParameters params;
- Solver solver(triangulate_cost);
+ for (int i = 0; i < markers.size(); ++i) {
+ const Marker &marker = markers[i];
+ const EuclideanCamera &camera =
+ *reconstruction->CameraForImage(marker.image);
+
+ problem.AddResidualBlock(
+ new ceres::AutoDiffCostFunction<
+ EuclideanIntersectCostFunctor,
+ 2, /* num_residuals */
+ 3>(new EuclideanIntersectCostFunctor(marker, camera)),
+ NULL,
+ &X(0));
+ }
- Solver::Results results = solver.minimize(params, &X);
+ // Configure the solve.
+ ceres::Solver::Options solver_options;
+ solver_options.linear_solver_type = ceres::DENSE_QR;
+ solver_options.max_num_iterations = 50;
+ solver_options.update_state_every_iteration = true;
+ solver_options.parameter_tolerance = 1e-16;
+ solver_options.function_tolerance = 1e-16;
+
+ // Run the solve.
+ ceres::Solver::Summary summary;
+ ceres::Solve(solver_options, &problem, &summary);
+
+ VLOG(1) << "Summary:\n" << summary.FullReport();
// Try projecting the point; make sure it's in front of everyone.
for (int i = 0; i < cameras.size(); ++i) {
diff --git a/extern/libmv/libmv/simple_pipeline/modal_solver.cc b/extern/libmv/libmv/simple_pipeline/modal_solver.cc
index bb49b30dbce..d79c71508cc 100644
--- a/extern/libmv/libmv/simple_pipeline/modal_solver.cc
+++ b/extern/libmv/libmv/simple_pipeline/modal_solver.cc
@@ -18,11 +18,14 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
+#include "libmv/simple_pipeline/modal_solver.h"
+
#include <cstdio>
+#include "ceres/ceres.h"
+#include "ceres/rotation.h"
#include "libmv/logging/logging.h"
-#include "libmv/simple_pipeline/modal_solver.h"
-#include "libmv/simple_pipeline/rigid_registration.h"
+#include "libmv/multiview/panography.h"
#ifdef _MSC_VER
# define snprintf _snprintf
@@ -30,7 +33,8 @@
namespace libmv {
-static void ProjectMarkerOnSphere(Marker &marker, Vec3 &X) {
+namespace {
+void ProjectMarkerOnSphere(Marker &marker, Vec3 &X) {
X(0) = marker.x;
X(1) = marker.y;
X(2) = 1.0;
@@ -38,18 +42,60 @@ static void ProjectMarkerOnSphere(Marker &marker, Vec3 &X) {
X *= 5.0 / X.norm();
}
-static void ModalSolverLogProress(ProgressUpdateCallback *update_callback,
- double progress)
+void ModalSolverLogProress(ProgressUpdateCallback *update_callback,
+ double progress)
{
if (update_callback) {
char message[256];
- snprintf(message, sizeof(message), "Solving progress %d%%", (int)(progress * 100));
+ snprintf(message, sizeof(message), "Solving progress %d%%",
+ (int)(progress * 100));
update_callback->invoke(progress, message);
}
}
+struct ModalReprojectionError {
+ ModalReprojectionError(double observed_x, double observed_y, Vec3 &bundle)
+ : observed_x(observed_x), observed_y(observed_y), bundle(bundle) { }
+
+ template <typename T>
+ bool operator()(const T* quaternion, // Rotation quaternion
+ T* residuals) const {
+
+ T R[9];
+ ceres::QuaternionToRotation(quaternion, R);
+
+ // Convert bundle position from double to T.
+ T X[3];
+ X[0] = T(bundle(0));
+ X[1] = T(bundle(1));
+ X[2] = T(bundle(2));
+
+ // Compute projective coordinates: x = RX.
+ T x[3];
+ x[0] = R[0]*X[0] + R[3]*X[1] + R[6]*X[2];
+ x[1] = R[1]*X[0] + R[4]*X[1] + R[7]*X[2];
+ x[2] = R[2]*X[0] + R[5]*X[1] + R[8]*X[2];
+
+ // Compute normalized coordinates: x /= x[2].
+ T xn = x[0] / x[2];
+ T yn = x[1] / x[2];
+
+ // The error is the difference between reprojected
+ // and observed marker position.
+ residuals[0] = xn - T(observed_x);
+ residuals[1] = yn - T(observed_y);
+
+ return true;
+ }
+
+ double observed_x;
+ double observed_y;
+ Vec3 bundle;
+};
+} // namespace
+
void ModalSolver(Tracks &tracks,
EuclideanReconstruction *reconstruction,
ProgressUpdateCallback *update_callback) {
@@ -59,58 +105,132 @@ void ModalSolver(Tracks &tracks,
LG << "Max image: " << max_image;
LG << "Max track: " << max_track;
- Mat3 R = Mat3::Identity();
+ // For minimization we're using quaternions.
+ Vec3 zero_rotation = Vec3::Zero();
+ Vec4 quaternion;
+ ceres::AngleAxisToQuaternion(&zero_rotation(0), &quaternion(0));
for (int image = 0; image <= max_image; ++image) {
vector<Marker> all_markers = tracks.MarkersInImage(image);
ModalSolverLogProress(update_callback, (float) image / max_image);
- // Skip empty frames without doing anything
+ // Skip empty images without doing anything.
if (all_markers.size() == 0) {
- LG << "Skipping frame: " << image;
+ LG << "Skipping image: " << image;
continue;
}
- vector<Vec3> points, reference_points;
+ // STEP 1: Estimate rotation analytically.
+ Mat3 current_R;
+ ceres::QuaternionToRotation(&quaternion(0), &current_R(0, 0));
+
+ // Construct point cloud for current and previous images,
+ // using markers appear at current image for which we know
+ // 3D positions.
+ Mat x1, x2;
+ for (int i = 0; i < all_markers.size(); ++i) {
+ Marker &marker = all_markers[i];
+ EuclideanPoint *point = reconstruction->PointForTrack(marker.track);
+ if (point) {
+ Vec3 X;
+ ProjectMarkerOnSphere(marker, X);
- // Cnstruct pairs of markers from current and previous image,
- // to reproject them and find rigid transformation between
- // previous and current image
- for (int track = 0; track <= max_track; ++track) {
- EuclideanPoint *point = reconstruction->PointForTrack(track);
+ int last_column = x1.cols();
+ x1.conservativeResize(3, last_column + 1);
+ x2.conservativeResize(3, last_column + 1);
- if (point) {
- Marker marker = tracks.MarkerInImageForTrack(image, track);
+ x1.col(last_column) = current_R * point->X;
+ x2.col(last_column) = X;
+ }
+ }
- if (marker.image == image) {
- Vec3 X;
+ if (x1.cols() >= 2) {
+ Mat3 delta_R;
- LG << "Use track " << track << " for rigid registration between image " <<
- image - 1 << " and " << image;
+ // Compute delta rotation matrix for two point clouds.
+ // Could be a bit confusing at first glance, but order
+ // of clouds is indeed so.
+ GetR_FixedCameraCenter(x2, x1, 1.0, &delta_R);
- ProjectMarkerOnSphere(marker, X);
+ // Convert delta rotation form matrix to final image
+ // rotation stored in a quaternion
+ Vec3 delta_angle_axis;
+ ceres::RotationMatrixToAngleAxis(&delta_R(0, 0), &delta_angle_axis(0));
- points.push_back(point->X);
- reference_points.push_back(X);
- }
+ Vec3 current_angle_axis;
+ ceres::QuaternionToAngleAxis(&quaternion(0), &current_angle_axis(0));
+
+ Vec3 angle_axis = current_angle_axis + delta_angle_axis;
+
+ ceres::AngleAxisToQuaternion(&angle_axis(0), &quaternion(0));
+
+ LG << "Analytically computed quaternion "
+ << quaternion.transpose();
+ }
+
+ // STEP 2: Refine rotation with Ceres.
+ ceres::Problem problem;
+
+ ceres::LocalParameterization* quaternion_parameterization =
+ new ceres::QuaternionParameterization;
+
+ int num_residuals = 0;
+ for (int i = 0; i < all_markers.size(); ++i) {
+ Marker &marker = all_markers[i];
+ EuclideanPoint *point = reconstruction->PointForTrack(marker.track);
+
+ if (point) {
+ problem.AddResidualBlock(new ceres::AutoDiffCostFunction<
+ ModalReprojectionError,
+ 2, /* num_residuals */
+ 4>(new ModalReprojectionError(marker.x, marker.y,
+ point->X)),
+ NULL,
+ &quaternion(0));
+ num_residuals++;
+
+ problem.SetParameterization(&quaternion(0),
+ quaternion_parameterization);
}
}
- if (points.size()) {
- // Find rigid delta transformation to current image
- RigidRegistration(reference_points, points, R);
+ LG << "Number of residuals: " << num_residuals;
+
+ if (num_residuals) {
+ // Configure the solve.
+ ceres::Solver::Options solver_options;
+ solver_options.linear_solver_type = ceres::DENSE_QR;
+ solver_options.max_num_iterations = 50;
+ solver_options.update_state_every_iteration = true;
+ solver_options.gradient_tolerance = 1e-36;
+ solver_options.parameter_tolerance = 1e-36;
+ solver_options.function_tolerance = 1e-36;
+
+ // Run the solve.
+ ceres::Solver::Summary summary;
+ ceres::Solve(solver_options, &problem, &summary);
+
+ LG << "Summary:\n" << summary.FullReport();
+ LG << "Refined quaternion " << quaternion.transpose();
}
+ // Convert quaternion to rotation matrix.
+ Mat3 R;
+ ceres::QuaternionToRotation(&quaternion(0), &R(0, 0));
reconstruction->InsertCamera(image, R, Vec3::Zero());
- // Review if there's new tracks for which position might be reconstructed
+ // STEP 3: reproject all new markers appeared at image
+
+ // Check if there're new markers appeared on current image
+ // and reproject them on sphere to obtain 3D position/
for (int track = 0; track <= max_track; ++track) {
if (!reconstruction->PointForTrack(track)) {
Marker marker = tracks.MarkerInImageForTrack(image, track);
if (marker.image == image) {
- // New track appeared on this image, project it's position onto sphere
+ // New track appeared on this image,
+ // project it's position onto sphere.
LG << "Projecting track " << track << " at image " << image;
diff --git a/extern/libmv/libmv/simple_pipeline/pipeline.cc b/extern/libmv/libmv/simple_pipeline/pipeline.cc
index efceda5c455..463738e42bb 100644
--- a/extern/libmv/libmv/simple_pipeline/pipeline.cc
+++ b/extern/libmv/libmv/simple_pipeline/pipeline.cc
@@ -300,7 +300,7 @@ double InternalReprojectionError(const Tracks &image_tracks,
ex,
ey,
sqrt(ex*ex + ey*ey));
- LG << line;
+ VLOG(1) << line;
total_error += sqrt(ex*ex + ey*ey);
}
diff --git a/extern/libmv/libmv/simple_pipeline/rigid_registration.cc b/extern/libmv/libmv/simple_pipeline/rigid_registration.cc
deleted file mode 100644
index f7cb1e66e7d..00000000000
--- a/extern/libmv/libmv/simple_pipeline/rigid_registration.cc
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright (c) 2012 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.
-
-#include "libmv/simple_pipeline/rigid_registration.h"
-#include "libmv/numeric/levenberg_marquardt.h"
-
-namespace libmv {
-
-template<class RigidTransformation>
-struct RigidRegistrationCostFunction {
- public:
- typedef Vec FMatrixType;
- typedef RigidTransformation XMatrixType;
-
- RigidRegistrationCostFunction(const vector<Vec3> &reference_points,
- const vector<Vec3> &points):
- reference_points_(reference_points),
- points_(points) {}
-
- Vec CalculateResiduals(const Mat3 &R,
- const Vec3 &S,
- const Vec3 &t) const {
- Vec residuals(points_.size());
- residuals.setZero();
-
- // Convert scale vector to matrix
- Mat3 SMat = Mat3::Identity();
- SMat(0, 0) *= S(0);
- SMat(1, 1) *= S(1);
- SMat(2, 2) *= S(2);
-
- for (int i = 0; i < points_.size(); i++) {
- Vec3 transformed_point = R * SMat * points_[i] + t;
-
- double norm = (transformed_point - reference_points_[i]).norm();
-
- residuals(i) = norm * norm;
- }
-
- return residuals;
- }
-
- Vec operator()(const Vec9 &RSt) const {
- Mat3 R = RotationFromEulerVector(RSt.head<3>());
- Vec3 S = RSt.segment<3>(3);
- Vec3 t = RSt.tail<3>();
-
- return CalculateResiduals(R, S, t);
- }
-
- Vec operator()(const Vec3 &euler) const {
- Mat3 R = RotationFromEulerVector(euler);
-
- return CalculateResiduals(R, Vec3(1.0, 1.0, 1.0), Vec3::Zero());
- }
-
- Vec operator()(const Vec6 &Rt) const {
- Mat3 R = RotationFromEulerVector(Rt.head<3>());
- Vec3 t = Rt.tail<3>();
-
- return CalculateResiduals(R, Vec3(1.0, 1.0, 1.0), t);
- }
-
- private:
- vector<Vec3> reference_points_;
- vector<Vec3> points_;
-};
-
-static double RigidRegistrationError(const vector<Vec3> &reference_points,
- const vector<Vec3> &points,
- const Mat3 &R,
- const Vec3 &S,
- const Vec3 &t) {
- double error = 0.0;
-
- Mat3 SMat = Mat3::Identity();
- SMat(0, 0) *= S(0);
- SMat(1, 1) *= S(1);
- SMat(2, 2) *= S(2);
-
- for (int i = 0; i < points.size(); i++) {
- Vec3 new_point = R * SMat * points[i] + t;
-
- double norm = (new_point - reference_points[i]).norm();
- error += norm * norm;
- }
- error /= points.size();
-
- return error;
-}
-
-double RigidRegistration(const vector<Vec3> &reference_points,
- const vector<Vec3> &points,
- Mat3 &R,
- Vec3 &S,
- Vec3 &t) {
- typedef LevenbergMarquardt<RigidRegistrationCostFunction <Vec9> > Solver;
-
- RigidRegistrationCostFunction<Vec9> rigidregistration_cost(reference_points, points);
- Solver solver(rigidregistration_cost);
-
- Vec9 RSt = Vec9::Zero();
-
- RSt(3) = RSt(4) = RSt(5) = 1.0;
-
- Solver::SolverParameters params;
- /*Solver::Results results = */ solver.minimize(params, &RSt);
- /* TODO(sergey): better error handling here */
-
- LG << "Rigid registration completed, rotation is:" << RSt.head<3>().transpose()
- << ", scale is " << RSt.segment<3>(3).transpose()
- << ", translation is " << RSt.tail<3>().transpose();
-
- // Decompose individual rotation and translation
- R = RotationFromEulerVector(RSt.head<3>());
- S = RSt.segment<3>(3);
- t = RSt.tail<3>();
-
- return RigidRegistrationError(reference_points, points, R, S, t);
-}
-
-double RigidRegistration(const vector<Vec3> &reference_points,
- const vector<Vec3> &points,
- Mat3 &R,
- Vec3 &t) {
- typedef LevenbergMarquardt<RigidRegistrationCostFunction <Vec6> > Solver;
-
- RigidRegistrationCostFunction<Vec6> rigidregistration_cost(reference_points, points);
- Solver solver(rigidregistration_cost);
-
- Vec6 Rt = Vec6::Zero();
- Solver::SolverParameters params;
- /*Solver::Results results = */solver.minimize(params, &Rt);
- /* TODO(sergey): better error handling here */
-
- LG << "Rigid registration completed, rotation is:" << Rt.head<3>().transpose()
- << ", translation is " << Rt.tail<3>().transpose();
-
- R = RotationFromEulerVector(Rt.head<3>());
- t = Rt.tail<3>();
-
- return RigidRegistrationError(reference_points, points, R, Vec3(1.0, 1.0, 1.0), t);
-}
-
-double RigidRegistration(const vector<Vec3> &reference_points,
- const vector<Vec3> &points,
- Mat3 &R) {
- typedef LevenbergMarquardt<RigidRegistrationCostFunction <Vec3> > Solver;
-
- RigidRegistrationCostFunction<Vec3> rigidregistration_cost(reference_points, points);
- Solver solver(rigidregistration_cost);
-
- Vec3 euler = Vec3::Zero();
- Solver::SolverParameters params;
- /*Solver::Results results = */solver.minimize(params, &euler);
- /* TODO(sergey): better error handling here */
-
- LG << "Rigid registration completed, rotation is:" << euler.transpose();
-
- R = RotationFromEulerVector(euler);
-
- return RigidRegistrationError(reference_points, points, R, Vec3(1.0, 1.0, 1.0), Vec3::Zero());
-}
-
-} // namespace libmv
diff --git a/extern/libmv/libmv/simple_pipeline/rigid_registration.h b/extern/libmv/libmv/simple_pipeline/rigid_registration.h
deleted file mode 100644
index 21ea57af507..00000000000
--- a/extern/libmv/libmv/simple_pipeline/rigid_registration.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2012 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_SIMPLE_PIPELINE_RIGID_REGISTRATION_H_
-#define LIBMV_SIMPLE_PIPELINE_RIGID_REGISTRATION_H_
-
-#include "libmv/base/vector.h"
-#include "libmv/numeric/numeric.h"
-
-namespace libmv {
-
-/*!
- Searched for an affine transformation of rigid 3D object defined by it's
- vertices positions from it's current state called points to it's desired
- state called reference points.
-
- Returns rotation matrix, per-component scale vector and translation which
- transforms points to the mot close state to reference_points.
-
- Return value is an average squared distance between reference state
- and transformed one.
-
- Minimzation of distance between point pairs is used to register such a
- rigid transformation and algorithm assumes that pairs of points are
- defined by point's index in a vector, so points with the same index
- belongs to the same pair.
- */
-double RigidRegistration(const vector<Vec3> &reference_points,
- const vector<Vec3> &points,
- Mat3 &R,
- Vec3 &S,
- Vec3 &t);
-
-/*!
- * Same as RigidRegistration but provides registration of rotation and translation only
- */
-double RigidRegistration(const vector<Vec3> &reference_points,
- const vector<Vec3> &points,
- Mat3 &R,
- Vec3 &t);
-
-/*!
- * Same as RigidRegistration but provides registration of rotation only
- */
-double RigidRegistration(const vector<Vec3> &reference_points,
- const vector<Vec3> &points,
- Mat3 &R);
-
-} // namespace libmv
-
-#endif // LIBMV_SIMPLE_PIPELINE_RIGID_REGISTRATION_H_
diff --git a/extern/libmv/libmv/simple_pipeline/tracks.cc b/extern/libmv/libmv/simple_pipeline/tracks.cc
index 3fb8ddbe513..620f6fc880a 100644
--- a/extern/libmv/libmv/simple_pipeline/tracks.cc
+++ b/extern/libmv/libmv/simple_pipeline/tracks.cc
@@ -72,6 +72,16 @@ vector<Marker> Tracks::MarkersForTrack(int track) const {
return markers;
}
+vector<Marker> Tracks::MarkersInBothImages(int image1, int image2) const {
+ vector<Marker> markers;
+ for (int i = 0; i < markers_.size(); ++i) {
+ int image = markers_[i].image;
+ if (image == image1 || image == image2)
+ markers.push_back(markers_[i]);
+ }
+ return markers;
+}
+
vector<Marker> Tracks::MarkersForTracksInBothImages(int image1, int image2) const {
std::vector<int> image1_tracks;
std::vector<int> image2_tracks;
@@ -156,4 +166,20 @@ int Tracks::NumMarkers() const {
return markers_.size();
}
+void CoordinatesForMarkersInImage(const vector<Marker> &markers,
+ int image,
+ Mat *coordinates) {
+ vector<Vec2> coords;
+ for (int i = 0; i < markers.size(); ++i) {
+ const Marker &marker = markers[i];
+ if (markers[i].image == image) {
+ coords.push_back(Vec2(marker.x, marker.y));
+ }
+ }
+ coordinates->resize(2, coords.size());
+ for (int i = 0; i < coords.size(); i++) {
+ coordinates->col(i) = coords[i];
+ }
+}
+
} // namespace libmv
diff --git a/extern/libmv/libmv/simple_pipeline/tracks.h b/extern/libmv/libmv/simple_pipeline/tracks.h
index aa0fbaa6e4c..f9af3ada45b 100644
--- a/extern/libmv/libmv/simple_pipeline/tracks.h
+++ b/extern/libmv/libmv/simple_pipeline/tracks.h
@@ -22,6 +22,7 @@
#define LIBMV_SIMPLE_PIPELINE_TRACKS_H_
#include "libmv/base/vector.h"
+#include "libmv/numeric/numeric.h"
namespace libmv {
@@ -84,6 +85,9 @@ class Tracks {
/// Returns all the markers visible in \a image.
vector<Marker> MarkersInImage(int image) const;
+ /// Returns all the markers visible in \a image1 and \a image2.
+ vector<Marker> MarkersInBothImages(int image1, int image2) const;
+
/*!
Returns the markers in \a image1 and \a image2 which have a common track.
@@ -114,6 +118,10 @@ class Tracks {
vector<Marker> markers_;
};
+void CoordinatesForMarkersInImage(const vector<Marker> &markers,
+ int image,
+ Mat *coordinates);
+
} // namespace libmv
#endif // LIBMV_SIMPLE_PIPELINE_MARKERS_H_
diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc
index 472d58a1547..036b7c94966 100644
--- a/extern/libmv/libmv/tracking/track_region.cc
+++ b/extern/libmv/libmv/tracking/track_region.cc
@@ -1404,7 +1404,7 @@ void TemplatedTrackRegion(const FloatImage &image1,
// Configure the solve.
ceres::Solver::Options solver_options;
- solver_options.linear_solver_type = ceres::DENSE_NORMAL_CHOLESKY;
+ solver_options.linear_solver_type = ceres::DENSE_QR;
solver_options.max_num_iterations = options.max_iterations;
solver_options.update_state_every_iteration = true;
solver_options.parameter_tolerance = 1e-16;
diff --git a/extern/libmv/patches/series b/extern/libmv/patches/series
index 1db7983fdd0..e69de29bb2d 100644
--- a/extern/libmv/patches/series
+++ b/extern/libmv/patches/series
@@ -1 +0,0 @@
-v3d_verbosity.patch
diff --git a/extern/libmv/patches/v3d_verbosity.patch b/extern/libmv/patches/v3d_verbosity.patch
deleted file mode 100644
index f5c6afbd0b5..00000000000
--- a/extern/libmv/patches/v3d_verbosity.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff --git a/src/libmv/simple_pipeline/bundle.cc b/src/libmv/simple_pipeline/bundle.cc
-index fa0b6cc..d382cd5 100644
---- a/src/libmv/simple_pipeline/bundle.cc
-+++ b/src/libmv/simple_pipeline/bundle.cc
-@@ -194,7 +194,6 @@ void EuclideanBundleCommonIntrinsics(const Tracks &tracks,
- double v3d_inlier_threshold = 500000.0;
-
- // Finally, run the bundle adjustment.
-- V3D::optimizerVerbosenessLevel = 1;
- V3D::CommonInternalsMetricBundleOptimizer opt(v3d_bundle_intrinsics,
- v3d_inlier_threshold,
- v3d_K,
diff --git a/extern/libmv/third_party/ceres/CMakeLists.txt b/extern/libmv/third_party/ceres/CMakeLists.txt
index e2f06d74646..b71fe1d5cdb 100644
--- a/extern/libmv/third_party/ceres/CMakeLists.txt
+++ b/extern/libmv/third_party/ceres/CMakeLists.txt
@@ -31,6 +31,7 @@ set(INC
include
internal
../gflags
+ ../../
)
set(INC_SYS
@@ -53,6 +54,7 @@ set(SRC
internal/ceres/compressed_row_sparse_matrix.cc
internal/ceres/conditioned_cost_function.cc
internal/ceres/conjugate_gradients_solver.cc
+ internal/ceres/coordinate_descent_minimizer.cc
internal/ceres/corrector.cc
internal/ceres/cxsparse.cc
internal/ceres/dense_normal_cholesky_solver.cc
@@ -70,11 +72,18 @@ set(SRC
internal/ceres/linear_least_squares_problems.cc
internal/ceres/linear_operator.cc
internal/ceres/linear_solver.cc
+ internal/ceres/line_search.cc
+ internal/ceres/line_search_direction.cc
+ internal/ceres/line_search_minimizer.cc
internal/ceres/local_parameterization.cc
internal/ceres/loss_function.cc
+ internal/ceres/low_rank_inverse_hessian.cc
+ internal/ceres/minimizer.cc
internal/ceres/normal_prior.cc
+ internal/ceres/parameter_block_ordering.cc
internal/ceres/partitioned_matrix_view.cc
- internal/ceres/polynomial_solver.cc
+ internal/ceres/polynomial.cc
+ internal/ceres/preconditioner.cc
internal/ceres/problem.cc
internal/ceres/problem_impl.cc
internal/ceres/program.cc
@@ -83,7 +92,7 @@ set(SRC
internal/ceres/runtime_numeric_diff_cost_function.cc
internal/ceres/schur_complement_solver.cc
internal/ceres/schur_eliminator.cc
- internal/ceres/schur_ordering.cc
+ internal/ceres/schur_jacobi_preconditioner.cc
internal/ceres/scratch_evaluate_preparer.cc
internal/ceres/solver.cc
internal/ceres/solver_impl.cc
@@ -98,26 +107,34 @@ set(SRC
internal/ceres/types.cc
internal/ceres/visibility_based_preconditioner.cc
internal/ceres/visibility.cc
+ internal/ceres/wall_time.cc
include/ceres/autodiff_cost_function.h
include/ceres/ceres.h
include/ceres/conditioned_cost_function.h
include/ceres/cost_function.h
+ include/ceres/cost_function_to_functor.h
include/ceres/crs_matrix.h
+ include/ceres/dynamic_autodiff_cost_function.h
include/ceres/fpclassify.h
+ include/ceres/gradient_checker.h
include/ceres/internal/autodiff.h
include/ceres/internal/eigen.h
include/ceres/internal/fixed_array.h
include/ceres/internal/macros.h
include/ceres/internal/manual_constructor.h
+ include/ceres/internal/numeric_diff.h
include/ceres/internal/port.h
include/ceres/internal/scoped_ptr.h
+ include/ceres/internal/variadic_evaluate.h
include/ceres/iteration_callback.h
include/ceres/jet.h
include/ceres/local_parameterization.h
include/ceres/loss_function.h
include/ceres/normal_prior.h
include/ceres/numeric_diff_cost_function.h
+ include/ceres/numeric_diff_functor.h
+ include/ceres/ordered_groups.h
include/ceres/problem.h
include/ceres/rotation.h
include/ceres/sized_cost_function.h
@@ -140,6 +157,7 @@ set(SRC
internal/ceres/compressed_row_jacobian_writer.h
internal/ceres/compressed_row_sparse_matrix.h
internal/ceres/conjugate_gradients_solver.h
+ internal/ceres/coordinate_descent_minimizer.h
internal/ceres/corrector.h
internal/ceres/cxsparse.h
internal/ceres/dense_jacobian_writer.h
@@ -149,6 +167,7 @@ set(SRC
internal/ceres/detect_structure.h
internal/ceres/dogleg_strategy.h
internal/ceres/evaluator.h
+ internal/ceres/execution_summary.h
internal/ceres/file.h
internal/ceres/gradient_checking_cost_function.h
internal/ceres/graph_algorithms.h
@@ -160,13 +179,19 @@ set(SRC
internal/ceres/linear_least_squares_problems.h
internal/ceres/linear_operator.h
internal/ceres/linear_solver.h
+ internal/ceres/line_search_direction.h
+ internal/ceres/line_search.h
+ internal/ceres/line_search_minimizer.h
+ internal/ceres/low_rank_inverse_hessian.h
internal/ceres/map_util.h
internal/ceres/matrix_proto.h
internal/ceres/minimizer.h
internal/ceres/mutex.h
internal/ceres/parameter_block.h
+ internal/ceres/parameter_block_ordering.h
internal/ceres/partitioned_matrix_view.h
- internal/ceres/polynomial_solver.h
+ internal/ceres/polynomial.h
+ internal/ceres/preconditioner.h
internal/ceres/problem_impl.h
internal/ceres/program_evaluator.h
internal/ceres/program.h
@@ -177,7 +202,7 @@ set(SRC
internal/ceres/schur_complement_solver.h
internal/ceres/schur_eliminator.h
internal/ceres/schur_eliminator_impl.h
- internal/ceres/schur_ordering.h
+ internal/ceres/schur_jacobi_preconditioner.h
internal/ceres/scratch_evaluate_preparer.h
internal/ceres/solver_impl.h
internal/ceres/sparse_matrix.h
@@ -191,6 +216,7 @@ set(SRC
internal/ceres/trust_region_strategy.h
internal/ceres/visibility_based_preconditioner.h
internal/ceres/visibility.h
+ internal/ceres/wall_time.h
)
#if(FALSE)
@@ -235,8 +261,15 @@ add_definitions(
-DCERES_NO_CXSPARSE
-DCERES_NO_PROTOCOL_BUFFERS
-DCERES_RESTRICT_SCHUR_SPECIALIZATION
+ -DCERES_HAVE_RWLOCK
)
+if(WITH_OPENMP)
+ add_definitions(
+ -DCERES_USE_OPENMP
+ )
+endif()
+
if(MSVC10)
add_definitions(
-D"CERES_HASH_NAMESPACE_START=namespace std {"
diff --git a/extern/libmv/third_party/ceres/ChangeLog b/extern/libmv/third_party/ceres/ChangeLog
index 8b84328cf98..458a045d8be 100644
--- a/extern/libmv/third_party/ceres/ChangeLog
+++ b/extern/libmv/third_party/ceres/ChangeLog
@@ -1,524 +1,607 @@
-commit 552f9f85bba89f00ca307bc18fbda1dff23bd0e4
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Fri Aug 31 07:27:22 2012 -0700
+commit f46de9e697eb5b8756084615e29ded48600a4d39
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Thu Mar 21 15:31:35 2013 +0600
- Various minor bug fixes to the solver logic.
-
- 1. CostFunction returning false is handled better.
- If only the cost is being evaluated, it is possible to
- use the false value as an infinite value signal/outside
- a region of validity. This allows a weak form of constraint
- handling. Useful for example in handling infinities.
-
- 2. Changed the way how the slop around zero when model_cost
- is larger than the current cost. Relative instead of absolute
- tolerances are used. The same logic is propagated how the
- corresponding clamping of the model_cost is done.
+ Silent no previous declaration warning for FindParameterBlockOrDie
- 3. Fixed a minor indexing bug in nist.cc.
+ Use anonymous namespace for this. Also move some surrounding static
+ function to this anonymous namespace.
- 4. Some minor logging fixes to nist.cc to make it more
- compatible with the rest of ceres.
+ Change-Id: Ie235eb7936976563a9db115ec13c59e6e6869b96
+
+commit 16636efeffacdd69d075a60ea8a94d98fd81c6fd
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Thu Mar 21 15:12:01 2013 +0600
+
+ Compilation fix for msvc2010
- Together these changes, take the successful solve count from
- 41/54 to 46/54 and eliminate all NUMERICAL_FAILURE problems.
+ Usage of back_inserter requires <iterator> header when using msvc2010
- Change-Id: If94170ea4731af5b243805c0200963dd31aa94a7
+ Change-Id: I92ee1649795ce0468ce337fc414eb0ca6e90c51e
-commit 0b776b5cc9634d3b88d623905b96006f7647ce3e
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu Aug 30 15:26:17 2012 -0700
+commit ac0d416991274ed67fe85371f09b07f706a6db9a
+Author: Pablo Speciale <pablo.speciale@gmail.com>
+Date: Wed Mar 20 18:32:14 2013 -0700
- Update docs.
+ google-glog link wasn't working, 'http://' twice
- Change-Id: I69d50bcd37aed3bea2190ca614f023e83172901b
+ Change-Id: I9cd96d3609f9b1ba31cd480fef1702972be86741
-commit 2d7176ad7c8fb7238ca8abd6de73415d95877494
-Author: Petter Strandmark <petter.strandmark@gmail.com>
-Date: Thu Aug 30 19:51:24 2012 -0700
+commit 55b6c966c4f697cb5d11982201733aa3bce7a5a7
+Author: Pablo Speciale <pablo.speciale@gmail.com>
+Date: Wed Mar 20 17:44:04 2013 -0700
- max_consecutive_nonmonotonic_steps should be int
+ * Fixed the location of the Ceres doc (once installed with 'make install')
+ * Doing 'make ceres_docs' can be used to create the documentation (if the BUILD_DOCUMENTATION=ON)
+ * Included the copyright boilerplate for FindSphinx.cmake
- Found via Visual Studio warning.
-
- Change-Id: Id2cd7de562dfc8cd35df5d5f5220dd2d7350eb2c
+ Change-Id: Iea21eba9e68384b4fe72c85fa88c76b0ba8a7a1d
-commit 1a89bcc94e88933f89b20427a45bc40cdd23c056
+commit a986912555b304a47dd0c2a02892046fde15d091
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu Aug 30 15:26:17 2012 -0700
+Date: Wed Mar 20 11:50:34 2013 -0700
- Better reporting on the NIST problems.
+ Update version history
- Change-Id: I7cf774ec3242c0612dbe52fc233c3fc6cff3f031
+ Change-Id: I238279719219a26d0d1bb32e0610f41007d3dcef
-commit ea11704857a1e4a735e096896e4d775d83981499
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Wed Aug 29 18:18:48 2012 -0700
+commit 16dbf11626c52c013f1dca6375f993a554e31d51
+Author: Pablo Speciale <pablo.speciale@gmail.com>
+Date: Mon Mar 11 14:44:02 2013 -0700
- Basic harness for testing NIST problems.
+ Added CeresConfig.cmake based on this example:
+ https://projects.kde.org/projects/kde/kdeexamples/repository/revisions/master/show/buildsystem/HowToInstallALibrary
- Change-Id: I5baaa24dbf0506ceedf4a9be4ed17c84974d71a1
+ Change-Id: I130cac5d43d9fbbf359abc04d3691e25c4e2bb63
-commit 98bf14d2b95386c2c4a6c29154637943dae4c36c
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu Aug 30 10:26:44 2012 -0700
+commit 015d57f173fab7ea040ee01474101e208ff72be6
+Author: Pablo Speciale <pablo.speciale@gmail.com>
+Date: Tue Mar 19 14:05:14 2013 -0700
- Miscellaneous fixes.
+ Avoiding the Warning: "deprecated conversion from string constant to char*"
- Change-Id: I521e11f2d20bf24960bbc6b5dab4ec8bb1503d23
+ Change-Id: Ifa47f9b0724f79c5c695828628c89818ddefd844
-commit 1e3cbd9a4442cdd8fda43a7fb452f19dac8c74af
-Author: Petter Strandmark <strandmark@google.com>
-Date: Wed Aug 29 09:39:56 2012 -0700
+commit c51b11c1046366035e7da95e4d8a78100ef3f153
+Author: Pablo Speciale <pablo.speciale@gmail.com>
+Date: Tue Mar 12 00:56:56 2013 -0700
- Caching the symbolic Cholesky factorization when using CXSparse
+ Sphinx and CMake, based on this example:
+ http://ericscottbarr.com/blog/2012/03/sphinx-and-cmake-beautiful-documentation-for-c-projects/
- Average factorization times for bundle adjustment test problem:
- SuiteSparse: 0.2794 s.
- CXSparse: 0.4039 s.
- CXSparse cached: 0.2399 s.
+ The 'docs/CMakeLists.txt' file was deleted in this commit: 0abfb8f46f534b05413bb4d64b960d6fd0a9befb
- CXSparse will still be slower, though, because it has to compute
- the transpose and J^T * J.
+ Thanks to Arnaud Gelas, he has passed some links:
+ https://github.com/InsightSoftwareConsortium/ITKExamples/blob/master/CMake/FindSphinx.cmake
+ https://github.com/InsightSoftwareConsortium/ITKExamples/blob/master/CMakeLists.txt#L120-L154
- Change-Id: If9cdaa3dd520bee84b56e5fd4953b56a93db6bde
+ Change-Id: Ic65e7f8ec5280d1e71a897a144417a21761c5553
-commit 8b64140878ccd1e183d3715c38942a81fdecefde
+commit 793a339335d8d52279efb49bcd704d196646efb5
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Wed Aug 29 05:41:22 2012 -0700
+Date: Wed Mar 13 12:14:00 2013 -0700
- Documentation update
+ Make Android.mk play better with the external consraints
- Change-Id: I271a0422e7f6f42bcfd1dc6b5dc10c7a18f6a179
+ Change-Id: Ia0a1037d97c032a4ba1a9acbf4e04c192d12ee61
-commit a5353acd85a9fd19370b3d74035d87b0f0bac230
-Author: Petter Strandmark <petter.strandmark@gmail.com>
-Date: Tue Aug 28 18:16:41 2012 -0700
+commit 700d50d8074f0273b305fe6d9f795f1dcb988048
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Tue Mar 12 16:12:42 2013 -0700
- Adding gflags include to test_util.cc
-
- test_util seems to need gflags.
+ Lint cleanup from William Rucklidge
- Change-Id: I0c4757960f8ac69ad599c138aea58e3c88a4ea28
+ Change-Id: Iacbf77246109f687708696eee7fb6144d23e7ec5
-commit 87ca1b2ba28ec512752bbcf5fc994ce1434eb765
-Author: Petter Strandmark <petter.strandmark@gmail.com>
-Date: Tue Aug 28 18:05:20 2012 -0700
+commit 8140f0fc979f5728f37cfb68362f31e7e37b46bb
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Tue Mar 12 09:45:08 2013 -0700
- Changing random.h to use cstdlib for Windows compability.
+ Modularize the build.
- As discussed with Sameer today.
+ 1. Add -DLINE_SEARCH_MINIMIZER to CMake to make the line search
+ minimizer optional.
+ 2. Better handling of -DSUITESPARSE/-DCXSPARSE in top level cmake
+ file.
+ 3. Disable code which will never be used if SuiteSparse and/or
+ CXSparse is not available.
+ 4. Update build docs.
+ 5. Update jni/Android.mk
+ 6. Minor lint cleanup from William Rucklidge.
- Change-Id: If3d0284830c6591c71cc77b8400cafb45c0da61f
+ Change-Id: If60460a858000df82faed7a6bb056dd2bfdde562
-commit aeb00a07323808a0a1816e733ad18a87d5109ea3
-Author: Petter Strandmark <strandmark@google.com>
-Date: Mon Aug 27 22:22:57 2012 -0700
+commit c59c1e44727c62d43523b672c1c132865cd25784
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Mon Mar 11 17:28:38 2013 -0700
- Removing gomp for Visual Studio
+ Propagate ifdefs correctly to improve build efficiency.
- Linking currently fails in Visual Studio due to a missing library
- "gomp.lib". This is not needed in Visual Studio. OpenMP works
- without it.
+ With -DRESTRICT_SCHUR_SPECIALIZATIONS, now the various
+ specializations are empty, decreasing build time and
+ reducing the size of the static library.
- Change-Id: I39e204a8dd4f1b7425df7d4b222d86a8bb961432
+ Change-Id: I8ec431279741a9a83516a4167c54a364c4608143
-commit 6f362464ba99b800494d2f15c27768a342ddaa68
-Author: Markus Moll <markus.moll@esat.kuleuven.be>
-Date: Tue Aug 28 01:03:38 2012 +0200
+commit 32874b861fc54b33aa4272e8c81bb001aa1e1e60
+Author: Yuliy Schwartzburg <syx818@gmail.com>
+Date: Fri Mar 8 11:30:44 2013 +0100
- Add some tests for DoglegStrategy.
-
- Not necessarily a complete set.
+ Fix CMake "LIB_SUFFIX" for non-linux installations
- Change-Id: I14eb3a38c6fe976c8212f3934655411b6d1e0aa4
+ Change-Id: Ieb8a2825a4378b388149e7934ecc7b96ba5a29fa
-commit 122cf836a6dc9726489ce2fbecc6143bddc1caaf
+commit 58b8c68f29c2c15edbc5f77102796df661020312
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Fri Aug 24 16:28:27 2012 -0700
+Date: Sat Mar 9 17:17:43 2013 -0800
- Documentation update.
+ Clean up rotation.h
- Change-Id: I0a3c5ae4bc981a8f5bdd5a8905f923dc5f09a024
+ Change-Id: I3370c9883728cda068c9650a2c2a50641fd8299c
-commit 69081719f73da8de2935774a42d237837a91952a
-Author: Keir Mierle <mierle@gmail.com>
-Date: Mon Aug 27 13:28:56 2012 -0700
+commit 020d8e1e48f341f3b990ac449998d36aaca2771f
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Wed Mar 6 16:19:26 2013 -0800
- Remove unnecessary overload for hash<>
-
- The overload for pointers in hash tables was applied in normal
- usage of schur_ordering.cc. However, the tests did not include the
- overload since they only included collections_port.h. As a result,
- the routines in schur_ordering.cc were using a different hash
- function than that inside the tests.
+ Better error reporting in the modeling API.
- The fix is to remove the specialization. If this breaks one of the
- compiler configurations, we will find a workaround at that time.
+ More informative error when user passes an
+ unknown parameter block to Problem methods.
- Change-Id: Idbf60415d5e2aec0c865b514ad0c577d21b91405
+ Change-Id: I517360e4b0b55814904ca3e664877d76ad3f59e8
-commit 1762420b6ed76b1c4d30b913b2cac1927b666534
+commit 5e7ce8a950cf5794c63817827ce66a3a4e66e7b6
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Wed Aug 22 10:01:31 2012 -0700
+Date: Wed Mar 6 11:38:41 2013 -0800
- Update changelog.
+ Fix Problem::Evaluate documentation
- Change-Id: Idf5af69d5a9dbe35f58e30a8afcbfcd29bb7ebfe
+ Change-Id: I8c70a24743cff2d9cface99ef0f5d34c78f769c6
-commit 976ab7aca908309b8282cb40bc080ca859136854
-Author: Keir Mierle <mierle@gmail.com>
-Date: Thu Aug 23 18:21:36 2012 -0700
+commit 0a4f5f8f7428148f21183e743d091d2079406604
+Author: Taylor Braun-Jones <taylor@braun-jones.org>
+Date: Wed Mar 6 00:00:32 2013 -0500
- Remove Google-era vestigial unit test.
+ Fix operator() signature in several sections of the documentation
- Change-Id: Ia7a295a5c759a17c1675a3055d287d3e40e9e0fe
+ Change-Id: I73f9d150a738f7b136fbc1f98fc60b0f306bd7f9
-commit 6ad6257de0e2152ac5e77dc003758de45187d6ea
-Author: Keir Mierle <mierle@gmail.com>
-Date: Wed Aug 22 11:10:31 2012 -0700
+commit 2c648dbc43025927301684fc82d95ccf6b6c21bc
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Tue Mar 5 15:20:15 2013 -0800
- Add a workaround for an Android NDK compiler bug.
+ Make examples independent of ceres internals.
- On certain NDK build configurations, one of the innermost
- parts of the Schur eliminator would get compiled
- incorrectly. The compiler changed a -= to a +=.
+ Change-Id: I6b6913e067a86fea713646218c8da1439d349d74
+
+commit e7148795c3f2ce1f6625a7c81545707a6cbde3eb
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Mon Mar 4 10:17:30 2013 -0800
+
+ Fix a memory leak in CXSparse::SolveCholesky.
- The normal Ceres unit tests caught the problem; however,
- since it is not possible to build the tests with the NDK
- (only with the standalone toolchain) this was difficult to
- track down. Finding the issue involved pasting the schur
- eliminator unit test inside of solver_impl.cc and other such
- hacks.
+ Thanks to Alexander Mordvintsev for reporting this.
- Change-Id: Ie91bb545d74fe39f0c8cbd1a6eb69ee4d8b25fb2
+ Change-Id: I5c6be4d3d28f062e83a1ad41cb8089c19362a005
-commit aecb2dc92b4aa7f3bf77a1ac918e62953602392b
+commit 480f9b8551c02c429bc027197f3d868c5cc522c9
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Wed Aug 22 10:08:17 2012 -0700
+Date: Sun Mar 3 20:15:22 2013 -0800
- Fix relative path bug in bibtex call.
+ Add gerrit instructions to the docs.
- Change-Id: I0d31786564320a6831259bcdf4c75a6b665c43ad
+ Change-Id: Ic98f20273f3ccbaeb8b4ca00c4ce0042a0d262f8
-commit 1e2892009e591804df6286caebd5c960e7e3b099
+commit 7c60b5c2c6170f0f81a29dbaa2ca7d8031db843b
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Tue Aug 21 18:00:54 2012 -0700
+Date: Sun Mar 3 18:28:02 2013 -0800
- Update Summary::FullReport to report dogleg type.
+ version history update
- Change-Id: I0b4be8d7486c1c4b36b299693b3fe8b0d3426537
+ Change-Id: Ia92caeb0f6659667ce1e56eefd0e3c87b3f6e538
-commit 295ade1122a86b83e1ea605d5ca394f315874717
+commit a363a7b69c7b97e17ad671ba1aee30f201eafdd1
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Wed Aug 22 06:51:22 2012 -0700
+Date: Sun Mar 3 18:06:00 2013 -0800
- Fix Eigen3 Row/Column Major storage issue.
+ Multithread DENSE_SCHUR
- Eigen3 does not allow column vectors to be stored in row-major
- format. NumericDiffCostFunction by default stores its Jacobian
- matrices in row-major format. This works fine if the residual
- contains more than one variable. But if the residual block
- depends on one variable and has more than one residuals, the
- resulting Jacobian matrix is a column matrix in row-major format
- resulting in a compile time error.
+ Replace the global lock in BlockRandomAccessDenseMatrix
+ with a per cell lock.
- The fix is to check the template parameters and switch to column-major
- storage as needed.
+ Change-Id: Iddbe38616157b6e0d3770eede3335a056c3ba18c
+
+commit 31730ef55df802d1e251edab3bac3c0cdcb30647
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Thu Feb 28 11:20:28 2013 -0800
+
+ DenseSparseMatrix is now column-major.
+
+ 1. Introduce new typdefs in eigen.h to allow for column
+ major matrices.
+
+ 2. Clean up old unused typedefs, and the aligned typedefs
+ since they do not actually add any real performance.
+
+ 3. Made eigen.h conform to the google style guide by removing
+ the using directives. They were polluting the ceres namespace.
- Thanks to Lena Gieseke for reporting this.
+ 4. Made the template specialization generator work again.
- Change-Id: Icc51c5b38e1f3609e0e1ecb3c4e4a02aecd72c3b
+ Change-Id: Ic2268c784534b737ebd6e1a043e2a327adaeca37
-commit 9ad27e8e9fb1bbd2054e2f6ae37623e01428f1c0
-Author: Arnaud Gelas <arnaudgelas@gmail.com>
-Date: Tue Aug 21 09:56:30 2012 +0200
+commit f8e43f7f2724c5413015e1f113ce860ee8b30428
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Wed Feb 27 08:55:20 2013 -0800
- Add one uninstall target to remove all installed files
+ version history update
- Change-Id: Ifcf89a6c27b25f28403d95a50e29c093a525298f
+ Change-Id: Ibd412a9e5beac3b3ac3e15b26fb11aa061956095
-commit 0c3a748ee49e04fe334f8f5a433649d18003d550
-Author: Markus Moll <markus.moll@esat.kuleuven.be>
-Date: Tue Aug 21 14:44:59 2012 +0200
+commit fef82b3a7af1e44f18f5343601fb19a4dd6f89ad
+Author: Alex Stewart <alexs.mac@gmail.com>
+Date: Wed Feb 27 10:44:12 2013 +0000
- Allow equal lower and upper bound for diagonal scaling.
+ Bugfix - commenting-out unused member which results in build error on OS X with latest Xcode.
- This way, setting the lower and upper bound both to 1.0, one can disable
- the automatic trust region scaling.
+ - Build error due to -Werror,-Wunused-private-field clang args.
+ - Raised with gtest group (as it also occurs with latest gtest:master but for a different
+ variable) with patch, but they don't want to fix for compatibility with legacy compilers/OS
+ see here: https://groups.google.com/forum/?fromgroups=#!topic/googletestframework/S1KLl2jkzws
- Change-Id: Ifa317a6911b813a89c1cf7fdfde25af603705319
+ Change-Id: I99984bcd9d07f6eb0e3fac58e27ddf0ac9e54265
-commit 3d644b76adefac6475b91dc53c3ae5e01c4f4d66
-Author: Arnaud Gelas <arnaudgelas@gmail.com>
-Date: Thu Aug 16 17:33:21 2012 +0200
+commit 0bc3540b66cf9de4d4a317c6a760849aa66d414e
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Wed Feb 27 08:46:48 2013 -0800
- Install headers, libraries and pdf
-
- Headers are installed in ${CMAKE_INSTALL_PREFIX}/include/ceres
- Libraries are installed in ${CMAKE_INSTALL_PREFIX}/lib
- pdf is installed in ${CMAKE_INSTALL_PREFIX}/share/ceres/docs
+ Version history update
- Change-Id: Ic175f2c2f5fa86820a1e8c64c2ed171f4a302a68
+ Change-Id: I6f79dd87e45bedf4bcf821e7b44f8b9553c39a7b
-commit d2fb5adea4d8c2aeb43c4289c6976798a54d3cf1
-Author: Arnaud Gelas <arnaudgelas@gmail.com>
-Date: Fri Aug 17 10:11:02 2012 +0200
+commit b59ac43b9d1122da3d00882efa7c5d6833c06ea7
+Author: Alex Stewart <alexs.mac@gmail.com>
+Date: Wed Feb 27 09:10:19 2013 +0000
- Configure gerrit hook at CMake time
+ Issue 83 fix: use correct pthread linker flags with clang.
- If the source directory is a clone, at CMake time the commit-msg hook gets
- downloaded and installed in the right location.
+ 1. -lpthreads was previously added to the CMAKE_CXX_FLAGS which are
+ not passed to the linker thus linking would fail.
+ 2. Clang would emit a warning about -lpthreads being added to a
+ build instruction with -c (compile only).
- Change-Id: I5fee17d050ca22d8b92a49fdcc2a1cd6659f209b
+ This patch fixes both of these issues by adding -lpthreads to the
+ linker flags (and removes them from the CXX flags).
+
+ Change-Id: I5e54de3ab7eced177aa31f311926893598af5b56
-commit 73166098fc4b1072adc30321c666188a3909c43c
-Author: Arnaud Gelas <arnaudgelas@gmail.com>
-Date: Mon Aug 20 15:40:41 2012 +0200
+commit 6fb1024ed5b197da261f71d1bb02716661da2fff
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Tue Feb 26 22:20:18 2013 -0800
- Add one CMake option to build the examples.
+ Fix a small bug in evaluator.h
- Currently the examples are always built. For external projects, it is useful
- not to compile the examples.
-
- Change-Id: I41d3bde19c7e742818e60f78222d39c43992ca8b
+ Change-Id: I2c4b8637e0ac8645721109f8b6bb2396ce8bb37b
-commit 86d4f1ba41ef14eb1b6b61a7936af83387b35eb2
-Author: Keir Mierle <mierle@gmail.com>
-Date: Mon Aug 20 11:52:04 2012 -0700
+commit 039ff07dd1a02e6c9cff335551f05bfe8269224b
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Tue Feb 26 09:15:39 2013 -0800
- Add missing return statement.
+ Evaluate ResidualBlocks without LossFunction if needed.
- Change-Id: I5eaf718318e27040e3c97e32ee46cf0a11176a37
+ 1. Add the ability to evaluate the problem without loss function.
+ 2. Remove static Evaluator::Evaluate
+ 3. Refactor the common code from problem_test.cc and
+ evaluator_test.cc into evaluator_test_utils.cc
+
+ Change-Id: I1aa841580afe91d288fbb65288b0ffdd1e43e827
-commit 51eb229da34187a4e8ce73ed9cc0e731998bb2be
-Author: Keir Mierle <mierle@gmail.com>
-Date: Mon Aug 20 11:46:12 2012 -0700
+commit c3fd3b960e489348d5b2c8b8f0167760e52ecbd9
+Author: Taylor Braun-Jones <taylor@braun-jones.org>
+Date: Tue Feb 26 00:30:35 2013 -0500
- Add Program::ToString() to aid debugging.
+ Only use cmake28 macro for RHEL6
+
+ This makes it possible to use the same spec to build on Fedora. It drops any
+ chance of building on RHEL5, but I doubt that was possible anyway.
- Change-Id: I0ab37ed2fe0947ca87a152919d4e7dc9b56dedc6
+ Change-Id: Ia956eb6416504e520962ec2f617e03b40ca18203
-commit bcc7100635e2047dc2b77df19a4ded8a6ab4d4b9
-Author: Keir Mierle <mierle@gmail.com>
-Date: Mon Aug 20 11:45:04 2012 -0700
+commit b73148b9f38fe41032e696436566b78043a368db
+Author: Taylor Braun-Jones <taylor@braun-jones.org>
+Date: Mon Feb 25 02:34:00 2013 -0500
- Ignore minted.sty.
+ Remove -Wno-return-type-c-linkage option when using gcc
+
+ Only use this option when compiling with CLang which supports it.
- Change-Id: I2467a6f801812b9007b51bf14b00757f026e4322
+ Change-Id: I8555c16e82d61302f6a43672d0d63e5d4800c6b6
-commit 9705a736dd3d6fbead0d8a6ff77102c69bbcdc08
+commit ba9442160dabf612a1dc51baf098937459b4b5ca
Author: Keir Mierle <mierle@gmail.com>
-Date: Mon Aug 20 11:24:05 2012 -0700
+Date: Mon Feb 25 12:46:44 2013 -0800
- Add ParameterBlock::ToString() to aid debugging.
+ Add the number of effective parameters to the final report.
- Change-Id: Id3f5cb27b855c536dd65a986f345bd8eb2799dfa
-
-commit 0c714a70e6123ceb68e5cfcd3cfbee0d09deb1db
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Mon Aug 20 11:18:16 2012 -0700
-
- Fix blanks before private in loss_function.h
+ Here is an example report, obtained by running:
- Change-Id: I068bed6431bc7c9b7958af391655df61499000b2
-
-commit 51cf7cbe3bac45c6807c2703a2fc3175d76a1b47
-Author: Markus Moll <markus.moll@esat.kuleuven.be>
-Date: Mon Aug 20 20:10:20 2012 +0200
-
- Add the two-dimensional subspace search to DoglegStrategy
+ bin/Debug/bundle_adjuster \
+ --input=../ceres-solver/data/problem-16-22106-pre.txt \
+ --linear_solver=iterative_schur \
+ --num_iterations=1 \
+ --alsologtostderr \
+ --use_local_parameterization \
+ --use_quaternions
+
+ Note that effective parameters is less than parameters by 16, which is the
+ number of cameras. In this case the local parameterization has a 3 dimensional
+ tangent space for the 4-dimensional quaternions.
+
+ Ceres Solver Report
+ -------------------
+ Original Reduced
+ Parameter blocks 22138 22138
+ Parameters 66478 66478
+ Effective parameters 66462 66462
+ Residual blocks 83718 83718
+ Residual 167436 167436
+
+ Minimizer TRUST_REGION
+ Trust Region Strategy LEVENBERG_MARQUARDT
+
+ Given Used
+ Linear solver ITERATIVE_SCHUR ITERATIVE_SCHUR
+ Preconditioner JACOBI JACOBI
+ Threads: 1 1
+ Linear solver threads 1 1
+ Linear solver ordering AUTOMATIC 22106, 32
+
+ Cost:
+ Initial 4.185660e+06
+ Final 7.221647e+04
+ Change 4.113443e+06
+
+ Number of iterations:
+ Successful 1
+ Unsuccessful 0
+ Total 1
+
+ Time (in seconds):
+ Preprocessor 0.697
+
+ Residual Evaluations 0.063
+ Jacobian Evaluations 27.608
+ Linear Solver 13.360
+ Minimizer 43.973
+
+ Postprocessor 0.004
+ Total 44.756
- Change-Id: I5163744c100cdf07dd93343d0734ffe0e80364f3
+ Termination: NO_CONVERGENCE
+
+ Change-Id: I6b6b8ac24f71bd187e67d95651290917642be74f
-commit ad1f7b772e559a911ac3a3b078b0aee1836fe785
+commit 36dc14ddf2fd53238c2ce21f172aa1989b31c0fd
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Mon Aug 20 11:10:34 2012 -0700
+Date: Mon Feb 25 10:33:10 2013 -0800
- Add ArcTanLoss, TolerantLoss and ComposedLossFunction.
-
- Based on work by James Roseborough.
+ Fix a clang warning
- Change-Id: Idc4e0b099028f67702bfc7fe3e43dbd96b6f9256
+ Change-Id: I5ef32c6329f1f75efb30b16519b8de146a8339fa
-commit 05292bf8fc5208b86b4a13544615b584f6efa936
+commit 931c309b2734329ec6e5f0b88ce4a0b488ac47e5
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Mon Aug 20 07:40:45 2012 -0700
+Date: Mon Feb 25 09:46:21 2013 -0800
- Add a TrustRegionStrategy::Summary object.
+ Cleanup based on comments by William Rucklidge
- Change-Id: I7caee35a3408ee4a0ec16ba407410d822929340d
+ Change-Id: If269ba8e388965a8ea32260fd6f17a133a19ab9b
-commit b12b906c4d21c3949f0dce62c4c0d083c8edecf1
-Author: Arnaud Gelas <arnaudgelas@gmail.com>
-Date: Wed Aug 15 16:27:38 2012 +0200
+commit df36218c953e05d665df2cc96a6d7625e2307d97
+Author: Taylor Braun-Jones <taylor@braun-jones.org>
+Date: Fri Feb 15 18:28:11 2013 -0500
- Add one option to generate the PDF from CMake at build time
+ Add support for the CMake "LIB_SUFFIX" convention
- Make sure pygmentize is installed
+ Allows `make install` to work correctly on e.g. 64-bit systems where the
+ native libraries are installed to /usr/lib64
- Change-Id: I068ba45c33a8e96acc906a464b12d10d58b3e231
+ Change-Id: I71b4fae7b459c003cb5fac981278c668f2e29779
-commit b9f15a59361c609ffc4a328aea9be3d265b5da81
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Sat Aug 18 13:06:19 2012 -0700
+commit 70701745b85fef7eeba2c978ae849fd48927699c
+Author: Taylor Braun-Jones <taylor@braun-jones.org>
+Date: Fri Feb 15 19:09:48 2013 -0500
- Add a dense Cholesky factorization based linear solver.
+ Add RPM .spec file
- For problems with a small number of variables, but a large
- number of residuals, it is sometimes beneficial to use the
- Cholesky factorization on the normal equations, instead of
- the dense QR factorization of the Jacobian, even though it
- is numerically the better thing to do.
+ Tested on RHEL6.1 (with epel repository for dependencies).
- Change-Id: I3506b006195754018deec964e6e190b7e8c9ac8f
+ make_release checks that that the version string in the .spec file is in
+ sync with the rest of the project and reminds the user to bump the
+ release string if necessary and to build/upload the RPM package.
+
+ Change-Id: I5f454f2a7301d1e0e120cb3c0e13a68d03bca917
-commit b3fa009435acf476cd373052e62988f6437970b1
-Author: Arnaud Gelas <arnaudgelas@gmail.com>
-Date: Fri Aug 17 10:31:41 2012 +0200
+commit d2a5195b512164fec286c6a52b40d7766977caa3
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Sun Feb 24 15:09:17 2013 -0800
- Set CMAKE_*_OUTPUT_DIRECTORY
-
- Gather
- * all executables in ${CMAKE_BINARY_DIR}/bin
- * all libraries (static and dynamic) in ${CMAKE_BINARY_DIR}/lib
+ Version history update.
- Change-Id: Ibc2fa1adfb6f0aea65d66d570259b79546bf3b07
+ Change-Id: I477ec05a78ca4cd735a525253c9b6adfa3bddea7
-commit 1b8a4d5d11671ed83cf6077e363dd95333f08ef8
+commit 2160c5b757c44206c6face6ca62d381f1db7a291
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Fri Aug 17 16:49:11 2012 -0700
+Date: Sun Feb 24 14:15:45 2013 -0800
- Fix a minor bug in detect_structure logging.
+ Minor release script fixes.
- Change-Id: I117f7745e4c67595b3ff9244cde82b5b5b34ee4b
+ Change-Id: Ifd0a7f4f584c85d4d9574eca46094b372a8d7aff
-commit 31c1e784ab2cb9294c6e05414cf06aae2b3766de
-Author: Keir Mierle <mierle@gmail.com>
-Date: Fri Aug 17 16:16:32 2012 -0700
+commit b53c9667f508c125b8aa833e7a063fa44ef8a98e
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Mon Feb 25 01:14:26 2013 +0600
- Minor cleanups.
+ Solve No Previous Prototype GCC warning
+
+ In some cases there were missing includes of own
+ header files from implementation files.
+
+ In other cases moved function which are only used
+ within single file into an anonymous namespace.
- Change-Id: Ida4866997deeaa1bc2cebd6b69313a05ac82e457
+ Change-Id: I2c6b411bcfbc521e2a5f21265dc8e009a548b1c8
-commit e83f7879a8b21c6976e116958caf35bcdcf41cb0
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Fri Aug 17 15:34:42 2012 -0700
+commit 267ccc45a3e875bf87832a8ad615be690b4926d3
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Mon Feb 25 01:04:16 2013 +0600
- Fix SuiteSparse3 UFConfig.h detection really.
+ Fix for MinGW build on Windows
+
+ GG_LONGLONG and GG_ULONGLONG shall use LL and ULL suffixes,
+ since MinGW is actuall a GCC compiler.
- Change-Id: Id187102e755b7d778dff4363f22f9a4697ed12dd
+ Solved by checking whether compilation happens with MinGW
+ or not using standard MinGW's __MINGW32__ and __MINGW64__
+ definitions.
+
+ Change-Id: I789b34f6342a56ba42f4b280f7242700022ab7a1
-commit 96f25dc57658d296ee6b6633818b4f1e51d7d587
+commit 509f68cfe3fd13b794c4e67ff38c761407c858cf
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Fri Aug 17 15:34:42 2012 -0700
+Date: Wed Feb 20 01:39:03 2013 -0800
- Fix SuiteSparse3 UFConfig.h detection.
+ Problem::Evaluate implementation.
+
+ 1. Add Problem::Evaluate and tests.
+ 2. Remove Solver::Summary::initial/final_*
+ 3. Remove Solver::Options::return_* members.
+ 4. Various cpplint cleanups.
- Change-Id: Ia59aefdb0ad7f713f76ed79692f2db4fa2821e5b
+ Change-Id: I4266de53489896f72d9c6798c5efde6748d68a47
-commit c497bd6cd9aa944f518aa491d3bc645851ff9594
-Author: Markus Moll <markus.moll@esat.kuleuven.be>
-Date: Fri Aug 17 14:40:13 2012 +0200
+commit d4a0bf86d688d1b68e00ff302858de5a4e0d9727
+Author: Keir Mierle <mierle@gmail.com>
+Date: Sun Feb 24 10:35:44 2013 -0800
- Add UFconfig and/or SuiteSparse_config test to CMakeLists.txt
+ Fix threading build on Windows.
+
+ On Windows, including the "windows.h" header defines an enormous number of
+ symbols; some of which are macros with common names. In particular, "ERROR" and
+ "min" and "max" get defined. This causes clashes when user code references
+ these names in a context other than the intended use in windows.h.
+
+ To deal with this, the Microsoft engineers added the ability to control the
+ definition of these symbols by adding extra defines. In particular, including
+ windows.h in the following way
+
+ #define NOGDI
+ #define NOMINMAX
- SuiteSparse 4 requires linking to libsuitesparseconfig.a.
- Both SuiteSparse 3 and SuiteSparse 4 require an additional header
- (either UFconfig.h or SuiteSparse_config.h) that is not found if it is
- in a separate path. Therefore, add explicit checks.
+ will reduce the number of macros defined. This way they will not conflict with
+ other uses in Ceres. For example, numeric_limits<double>::max() is impossible
+ to call without defining NOMINMAX.
- Change-Id: I699902b5db4f1b7f17134b5a54f9aa681445e294
+ Change-Id: I166f5d3bb6dc0e2e4b2ebf800fb19e49206f7874
-commit 383c04f4236d92801c7c674892814362dedf7ad6
+commit beb4505311011130a7e54632137b0fbb5824cc9b
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Fri Aug 17 10:14:04 2012 -0700
+Date: Fri Feb 22 13:37:01 2013 -0800
- Fix QuaternionToAngleAxis to ensure rotations are between -pi and pi.
+ Minor fixes
- Thanks to Guoxuan Zhang for reporting this.
+ Based on William Rucklidge's review, including
+ a nasty bug in parameter block removal.
- Change-Id: I2831ca3a04d5dc6467849c290461adbe23faaea3
+ Change-Id: I3a692e589f600ff560ecae9fa85bb0b76063d403
-commit dd2b17d7dd9750801ba4720bdece2062e59b7ae3
+commit 9a88bd7c4b40e2a1e0cd9b0dc09a3517c467e04e
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu Aug 16 19:34:57 2012 -0700
+Date: Tue Feb 19 13:09:12 2013 -0800
- CERES_DONT_HAVE_PROTOCOL_BUFFERS -> CERES_NO_PROTOCOL_BUFFERS.
+ Minor bug fixes
- Change-Id: I6c9f50e4c006faf4e75a8f417455db18357f3187
+ Change-Id: I94e4521adf76a6c77db954c4a8955168e9d37b55
-commit 8b4cb7aa2c74a0da62c638b2023566aa242af995
+commit 956ed7e8f2054623615e6ae3601055d613897f26
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu Aug 16 19:26:55 2012 -0700
+Date: Tue Feb 19 07:06:15 2013 -0800
- Fix sparse linear algebra library logging in Summary::FullReport.
+ Various minor fixes.
- Change-Id: Id2c902dc86c00954fde7749c7b4a67dd94215a31
+ 1. Unused variable warnings and fixes.
+ 2. Minor documentation update.
+
+ Change-Id: I815588a5806df1030a7c8750f4fb594c503f8998
-commit 47d26bcd3b38b5ff53b34768c33b499d47b26bd0
-Author: Markus Moll <markus.moll@esat.kuleuven.be>
-Date: Thu Aug 16 00:23:38 2012 +0200
+commit 3e2c4ef9ad35e94198f4f3367b99fd91e26996a1
+Author: Keir Mierle <mierle@gmail.com>
+Date: Sun Feb 17 12:37:55 2013 -0800
- Do not implicitly negate the step in the TrustRegionMinimizer.
+ Add adapters for column/row-major matrices to rotation.h
- In the TrustRegionMinimizer, the step is currently implicitly negated.
- This is done so that the linearized residual is |r - J*step|^2, which
- corresponds to J*step = r, so neither J nor r have to be modified.
- However, it leads to the rather unintuitive situation that the strategy
- returns a step in positive gradient direction, which you would expect to
- increase the function value. One way is to rename the "step" parameter in
- the strategy to "negative_step" and document it.
- This patch instead moves the negation inside the strategy, just around
- the linear solver call, so that it is done in a local context and easier
- to document.
+ This patch introduces a matrix wrapper (MatrixAdapter) that allows to
+ transparently pass pointers to row-major or column-major matrices
+ to the conversion functions.
- Change-Id: Idb258149a01f61c64e22128ea221c5a30cd89c89
+ Change-Id: I7f1683a8722088cffcc542f593ce7eb46fca109b
-commit 51da590c8457e6664f76fe9813425a0c71351497
-Author: Markus Moll <markus.moll@esat.kuleuven.be>
-Date: Fri Aug 17 12:56:09 2012 +0200
+commit 04938efe4bedec112083c5ceb227ba004f96bd01
+Author: Keir Mierle <mierle@gmail.com>
+Date: Sun Feb 17 12:37:55 2013 -0800
- Remove tmp file
+ Add support for removing parameter and residual blocks.
+
+ This adds support for removing parameter and residual blocks.
+ There are two modes of operation: in the first, removals of
+ paremeter blocks are expensive, since each remove requires
+ scanning all residual blocks to find ones that depend on the
+ removed parameter. In the other, extra memory is sacrificed to
+ maintain a list of the residuals a parameter block depends on,
+ removing the need to scan. In both cases, removing residual blocks
+ is fast.
+
+ As a caveat, any removals destroys the ordering of the parameters,
+ so the residuals or jacobian returned from Solver::Solve() is
+ meaningless. There is some debate on the best way to handle this;
+ the details remain for a future change.
- Change-Id: I07496fafae7b0c5c12cc26ae336e0db3b5592735
+ This also adds some overhead, even in the case that fast removals
+ are not requested:
+
+ - 1 int32 to each residual, to track its position in the program.
+ - 1 pointer to each parameter, to store the dependent residuals.
+
+ Change-Id: I71dcac8656679329a15ee7fc12c0df07030c12af
-commit 7006a1f2b1701b8d89b8d1525fc0101943802221
+commit fa21df8cd969bb257b87c9ef7c0147d8d5ea8725
Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Thu Aug 16 18:04:22 2012 -0700
+Date: Mon Feb 18 08:48:52 2013 -0800
- Correct example code in Powell's function example.
+ Add script for building documentation.
- Thanks to Petter Strandmark for pointing this out.
+ Update make_release
- Change-Id: I967632235dccdb481396e94904bb911c9a1efe1e
-
-commit 57a44b27bc6fc95b4e70fdc25c25c9925a2072a0
-Author: Keir Mierle <mierle@gmail.com>
-Date: Thu Aug 16 17:04:50 2012 -0700
-
- Remove unnecessary flags in NDK build.
+ Minor documentation fixes.
- Change-Id: Ib5b4d0b7f2d898671252734978c789b8171d96a8
+ Change-Id: I1248ec3f58be66b5929aee6f2aa392c15d53ed83
-commit f21bee247251a8b2e836c215a84c4668c31d75cd
-Author: Keir Mierle <mierle@gmail.com>
-Date: Thu Aug 16 16:27:10 2012 -0700
+commit 290b975d1d4eba44205bbeb0fa6b3ce8a6fa4a0c
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Sun Feb 17 16:50:37 2013 -0800
- Fix for fpclassify.h NDK porting work.
+ Preconditioner refactoring.
+
+ 1. Added a Preconditioner interface.
+ 2. SCHUR_JACOBI is now its own class and is independent of
+ SuiteSparse.
- Change-Id: I69df1b4caf2941ed96a53e35e43ec54073f84f59
+ Change-Id: Id912ab19cf3736e61d1b90ddaf5bfba33e877ec4
-commit 8ceb02cb75b66602de44a35e413225386cb21c27
-Author: Keir Mierle <mierle@gmail.com>
-Date: Thu Aug 16 14:23:47 2012 -0700
+commit d010de543530001fa917501a13ba02879c8ea52f
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Fri Feb 15 14:26:56 2013 -0800
- Add Android NDK build files.
-
- This adds a Android.mk build that builds a Ceres static library
- suitable for embetting in larger Android applications. This is
- useful when needing to build Ceres without GPL'd components, since
- the standalone toolchain (needed for the CMake Android build) does
- not work with STLPort.
+ Solver::Summary::FullReport() supports line search now.
- Change-Id: I8d857237f6f82658741017d161b2e31d9a20e5a7
+ Change-Id: Ib08d300198b85d9732cfb5785af4235ca4bd5226
diff --git a/extern/libmv/third_party/ceres/SConscript b/extern/libmv/third_party/ceres/SConscript
index 6d0d2cd5c40..6e490cfd5cf 100644
--- a/extern/libmv/third_party/ceres/SConscript
+++ b/extern/libmv/third_party/ceres/SConscript
@@ -23,6 +23,10 @@ defs.append('CERES_NO_SUITESPARSE')
defs.append('CERES_NO_CXSPARSE')
defs.append('CERES_NO_PROTOCOL_BUFFERS')
defs.append('CERES_RESTRICT_SCHUR_SPECIALIZATION')
+defs.append('CERES_HAVE_RWLOCK')
+
+if env['WITH_BF_OPENMP']:
+ defs.append('CERES_USE_OPENMP')
if 'Mac OS X 10.5' in env['MACOSX_SDK_CHECK']:
defs.append('CERES_NO_TR1')
diff --git a/extern/libmv/third_party/ceres/bundle.sh b/extern/libmv/third_party/ceres/bundle.sh
index ccf6d0aca16..65af263f7c4 100755
--- a/extern/libmv/third_party/ceres/bundle.sh
+++ b/extern/libmv/third_party/ceres/bundle.sh
@@ -9,7 +9,8 @@ fi
repo="https://ceres-solver.googlesource.com/ceres-solver"
branch="master"
-tag="1.3.0"
+#tag="1.4.0"
+tag=""
tmp=`mktemp -d`
checkout="$tmp/ceres"
@@ -120,6 +121,7 @@ set(INC
include
internal
../gflags
+ ../../
)
set(INC_SYS
@@ -160,8 +162,15 @@ add_definitions(
-DCERES_NO_CXSPARSE
-DCERES_NO_PROTOCOL_BUFFERS
-DCERES_RESTRICT_SCHUR_SPECIALIZATION
+ -DCERES_HAVE_RWLOCK
)
+if(WITH_OPENMP)
+ add_definitions(
+ -DCERES_USE_OPENMP
+ )
+endif()
+
if(MSVC10)
add_definitions(
-D"CERES_HASH_NAMESPACE_START=namespace std {"
@@ -211,6 +220,10 @@ defs.append('CERES_NO_SUITESPARSE')
defs.append('CERES_NO_CXSPARSE')
defs.append('CERES_NO_PROTOCOL_BUFFERS')
defs.append('CERES_RESTRICT_SCHUR_SPECIALIZATION')
+defs.append('CERES_HAVE_RWLOCK')
+
+if env['WITH_BF_OPENMP']:
+ defs.append('CERES_USE_OPENMP')
if 'Mac OS X 10.5' in env['MACOSX_SDK_CHECK']:
defs.append('CERES_NO_TR1')
diff --git a/extern/libmv/third_party/ceres/files.txt b/extern/libmv/third_party/ceres/files.txt
index 55083572977..8f4b7b97b50 100644
--- a/extern/libmv/third_party/ceres/files.txt
+++ b/extern/libmv/third_party/ceres/files.txt
@@ -2,21 +2,28 @@ include/ceres/autodiff_cost_function.h
include/ceres/ceres.h
include/ceres/conditioned_cost_function.h
include/ceres/cost_function.h
+include/ceres/cost_function_to_functor.h
include/ceres/crs_matrix.h
+include/ceres/dynamic_autodiff_cost_function.h
include/ceres/fpclassify.h
+include/ceres/gradient_checker.h
include/ceres/internal/autodiff.h
include/ceres/internal/eigen.h
include/ceres/internal/fixed_array.h
include/ceres/internal/macros.h
include/ceres/internal/manual_constructor.h
+include/ceres/internal/numeric_diff.h
include/ceres/internal/port.h
include/ceres/internal/scoped_ptr.h
+include/ceres/internal/variadic_evaluate.h
include/ceres/iteration_callback.h
include/ceres/jet.h
include/ceres/local_parameterization.h
include/ceres/loss_function.h
include/ceres/normal_prior.h
include/ceres/numeric_diff_cost_function.h
+include/ceres/numeric_diff_functor.h
+include/ceres/ordered_groups.h
include/ceres/problem.h
include/ceres/rotation.h
include/ceres/sized_cost_function.h
@@ -54,6 +61,8 @@ internal/ceres/compressed_row_sparse_matrix.h
internal/ceres/conditioned_cost_function.cc
internal/ceres/conjugate_gradients_solver.cc
internal/ceres/conjugate_gradients_solver.h
+internal/ceres/coordinate_descent_minimizer.cc
+internal/ceres/coordinate_descent_minimizer.h
internal/ceres/corrector.cc
internal/ceres/corrector.h
internal/ceres/cxsparse.cc
@@ -71,6 +80,7 @@ internal/ceres/dogleg_strategy.cc
internal/ceres/dogleg_strategy.h
internal/ceres/evaluator.cc
internal/ceres/evaluator.h
+internal/ceres/execution_summary.h
internal/ceres/file.cc
internal/ceres/file.h
internal/ceres/generated/schur_eliminator_2_2_2.cc
@@ -107,18 +117,31 @@ internal/ceres/linear_operator.cc
internal/ceres/linear_operator.h
internal/ceres/linear_solver.cc
internal/ceres/linear_solver.h
+internal/ceres/line_search.cc
+internal/ceres/line_search_direction.cc
+internal/ceres/line_search_direction.h
+internal/ceres/line_search.h
+internal/ceres/line_search_minimizer.cc
+internal/ceres/line_search_minimizer.h
internal/ceres/local_parameterization.cc
internal/ceres/loss_function.cc
+internal/ceres/low_rank_inverse_hessian.cc
+internal/ceres/low_rank_inverse_hessian.h
internal/ceres/map_util.h
internal/ceres/matrix_proto.h
+internal/ceres/minimizer.cc
internal/ceres/minimizer.h
internal/ceres/mutex.h
internal/ceres/normal_prior.cc
internal/ceres/parameter_block.h
+internal/ceres/parameter_block_ordering.cc
+internal/ceres/parameter_block_ordering.h
internal/ceres/partitioned_matrix_view.cc
internal/ceres/partitioned_matrix_view.h
-internal/ceres/polynomial_solver.cc
-internal/ceres/polynomial_solver.h
+internal/ceres/polynomial.cc
+internal/ceres/polynomial.h
+internal/ceres/preconditioner.cc
+internal/ceres/preconditioner.h
internal/ceres/problem.cc
internal/ceres/problem_impl.cc
internal/ceres/problem_impl.h
@@ -137,8 +160,8 @@ internal/ceres/schur_complement_solver.h
internal/ceres/schur_eliminator.cc
internal/ceres/schur_eliminator.h
internal/ceres/schur_eliminator_impl.h
-internal/ceres/schur_ordering.cc
-internal/ceres/schur_ordering.h
+internal/ceres/schur_jacobi_preconditioner.cc
+internal/ceres/schur_jacobi_preconditioner.h
internal/ceres/scratch_evaluate_preparer.cc
internal/ceres/scratch_evaluate_preparer.h
internal/ceres/solver.cc
@@ -166,3 +189,5 @@ internal/ceres/visibility_based_preconditioner.cc
internal/ceres/visibility_based_preconditioner.h
internal/ceres/visibility.cc
internal/ceres/visibility.h
+internal/ceres/wall_time.cc
+internal/ceres/wall_time.h
diff --git a/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h
index da9ee2c7993..e758d3a2bd5 100644
--- a/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h
+++ b/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h
@@ -28,10 +28,10 @@
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
-// Helpers for making CostFunctions as needed by the least squares framework,
-// with Jacobians computed via automatic differentiation. For more information
-// on automatic differentation, see the wikipedia article at
-// http://en.wikipedia.org/wiki/Automatic_differentiation
+// Create CostFunctions as needed by the least squares framework, with
+// Jacobians computed via automatic differentiation. For more
+// information on automatic differentation, see the wikipedia article
+// at http://en.wikipedia.org/wiki/Automatic_differentiation
//
// To get an auto differentiated cost function, you must define a class with a
// templated operator() (a functor) that computes the cost function in terms of
@@ -57,8 +57,8 @@
// To write an auto-differentiable cost function for the above model, first
// define the object
//
-// class MyScalarCostFunction {
-// MyScalarCostFunction(double k): k_(k) {}
+// class MyScalarCostFunctor {
+// MyScalarCostFunctor(double k): k_(k) {}
//
// template <typename T>
// bool operator()(const T* const x , const T* const y, T* e) const {
@@ -80,32 +80,32 @@
// it can be constructed as follows.
//
// CostFunction* cost_function
-// = new AutoDiffCostFunction<MyScalarCostFunction, 1, 2, 2>(
-// new MyScalarCostFunction(1.0)); ^ ^ ^
-// | | |
-// Dimension of residual ------+ | |
-// Dimension of x ----------------+ |
-// Dimension of y -------------------+
+// = new AutoDiffCostFunction<MyScalarCostFunctor, 1, 2, 2>(
+// new MyScalarCostFunctor(1.0)); ^ ^ ^
+// | | |
+// Dimension of residual -----+ | |
+// Dimension of x ---------------+ |
+// Dimension of y ------------------+
//
// In this example, there is usually an instance for each measumerent of k.
//
// In the instantiation above, the template parameters following
-// "MyScalarCostFunction", "1, 2, 2", describe the functor as computing a
+// "MyScalarCostFunctor", "1, 2, 2", describe the functor as computing a
// 1-dimensional output from two arguments, both 2-dimensional.
//
// The autodiff cost function also supports cost functions with a
// runtime-determined number of residuals. For example:
//
// CostFunction* cost_function
-// = new AutoDiffCostFunction<MyScalarCostFunction, DYNAMIC, 2, 2>(
-// new CostFunctionWithDynamicNumResiduals(1.0), ^ ^ ^
-// runtime_number_of_residuals); <----+ | | |
-// | | | |
-// | | | |
-// Actual number of residuals ------+ | | |
-// Indicate dynamic number of residuals ---------+ | |
-// Dimension of x -------------------------------------+ |
-// Dimension of y ----------------------------------------+
+// = new AutoDiffCostFunction<MyScalarCostFunctor, DYNAMIC, 2, 2>(
+// new CostFunctorWithDynamicNumResiduals(1.0), ^ ^ ^
+// runtime_number_of_residuals); <----+ | | |
+// | | | |
+// | | | |
+// Actual number of residuals ------+ | | |
+// Indicate dynamic number of residuals --------+ | |
+// Dimension of x ------------------------------------+ |
+// Dimension of y ---------------------------------------+
//
// The framework can currently accommodate cost functions of up to 6 independent
// variables, and there is no limit on the dimensionality of each of them.
@@ -119,7 +119,7 @@
// functions is to get the sizing wrong. In particular, there is a tendency to
// set the template parameters to (dimension of residual, number of parameters)
// instead of passing a dimension parameter for *every parameter*. In the
-// example above, that would be <MyScalarCostFunction, 1, 2>, which is missing
+// example above, that would be <MyScalarCostFunctor, 1, 2>, which is missing
// the last '2' argument. Please be careful when setting the size parameters.
#ifndef CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_
@@ -154,16 +154,21 @@ template <typename CostFunctor,
int N2 = 0, // Number of parameters in block 2.
int N3 = 0, // Number of parameters in block 3.
int N4 = 0, // Number of parameters in block 4.
- int N5 = 0> // Number of parameters in block 5.
-class AutoDiffCostFunction :
- public SizedCostFunction<M, N0, N1, N2, N3, N4, N5> {
+ int N5 = 0, // Number of parameters in block 5.
+ int N6 = 0, // Number of parameters in block 6.
+ int N7 = 0, // Number of parameters in block 7.
+ int N8 = 0, // Number of parameters in block 8.
+ int N9 = 0> // Number of parameters in block 9.
+class AutoDiffCostFunction : public SizedCostFunction<M,
+ N0, N1, N2, N3, N4,
+ N5, N6, N7, N8, N9> {
public:
// Takes ownership of functor. Uses the template-provided value for the
// number of residuals ("M").
explicit AutoDiffCostFunction(CostFunctor* functor)
: functor_(functor) {
CHECK_NE(M, DYNAMIC) << "Can't run the fixed-size constructor if the "
- << "number of residuals is set to ceres::DYNAMIC.";
+ << "number of residuals is set to ceres::DYNAMIC.";
}
// Takes ownership of functor. Ignores the template-provided number of
@@ -174,8 +179,9 @@ class AutoDiffCostFunction :
AutoDiffCostFunction(CostFunctor* functor, int num_residuals)
: functor_(functor) {
CHECK_EQ(M, DYNAMIC) << "Can't run the dynamic-size constructor if the "
- << "number of residuals is not ceres::DYNAMIC.";
- SizedCostFunction<M, N0, N1, N2, N3, N4, N5>::set_num_residuals(num_residuals);
+ << "number of residuals is not ceres::DYNAMIC.";
+ SizedCostFunction<M, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>
+ ::set_num_residuals(num_residuals);
}
virtual ~AutoDiffCostFunction() {}
@@ -190,14 +196,15 @@ class AutoDiffCostFunction :
double** jacobians) const {
if (!jacobians) {
return internal::VariadicEvaluate<
- CostFunctor, double, N0, N1, N2, N3, N4, N5>
+ CostFunctor, double, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>
::Call(*functor_, parameters, residuals);
}
return internal::AutoDiff<CostFunctor, double,
- N0, N1, N2, N3, N4, N5>::Differentiate(
+ N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>::Differentiate(
*functor_,
parameters,
- SizedCostFunction<M, N0, N1, N2, N3, N4, N5>::num_residuals(),
+ SizedCostFunction<M, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>
+ ::num_residuals(),
residuals,
jacobians);
}
diff --git a/extern/libmv/third_party/ceres/include/ceres/ceres.h b/extern/libmv/third_party/ceres/include/ceres/ceres.h
index 22aaf8ff21a..7878806aa45 100644
--- a/extern/libmv/third_party/ceres/include/ceres/ceres.h
+++ b/extern/libmv/third_party/ceres/include/ceres/ceres.h
@@ -34,12 +34,20 @@
#ifndef CERES_PUBLIC_CERES_H_
#define CERES_PUBLIC_CERES_H_
+#define CERES_VERSION 1.5.0
+#define CERES_ABI_VERSION 1.5.0
+
#include "ceres/autodiff_cost_function.h"
#include "ceres/cost_function.h"
+#include "ceres/cost_function_to_functor.h"
+#include "ceres/crs_matrix.h"
#include "ceres/iteration_callback.h"
+#include "ceres/jet.h"
#include "ceres/local_parameterization.h"
#include "ceres/loss_function.h"
#include "ceres/numeric_diff_cost_function.h"
+#include "ceres/numeric_diff_functor.h"
+#include "ceres/ordered_groups.h"
#include "ceres/problem.h"
#include "ceres/sized_cost_function.h"
#include "ceres/solver.h"
diff --git a/extern/libmv/third_party/ceres/include/ceres/cost_function_to_functor.h b/extern/libmv/third_party/ceres/include/ceres/cost_function_to_functor.h
new file mode 100644
index 00000000000..fa1012de741
--- /dev/null
+++ b/extern/libmv/third_party/ceres/include/ceres/cost_function_to_functor.h
@@ -0,0 +1,752 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+//
+// CostFunctionToFunctor is an adapter class that allows users to use
+// CostFunction objects in templated functors which are to be used for
+// automatic differentiation. This allows the user to seamlessly mix
+// analytic, numeric and automatic differentiation.
+//
+// For example, let us assume that
+//
+// class IntrinsicProjection : public SizedCostFunction<2, 5, 3> {
+// public:
+// IntrinsicProjection(const double* observations);
+// virtual bool Evaluate(double const* const* parameters,
+// double* residuals,
+// double** jacobians) const;
+// };
+//
+// is a cost function that implements the projection of a point in its
+// local coordinate system onto its image plane and subtracts it from
+// the observed point projection. It can compute its residual and
+// either via analytic or numerical differentiation can compute its
+// jacobians.
+//
+// Now we would like to compose the action of this CostFunction with
+// the action of camera extrinsics, i.e., rotation and
+// translation. Say we have a templated function
+//
+// template<typename T>
+// void RotateAndTranslatePoint(const T* rotation,
+// const T* translation,
+// const T* point,
+// T* result);
+//
+// Then we can now do the following,
+//
+// struct CameraProjection {
+// CameraProjection(double* observation) {
+// intrinsic_projection_.reset(
+// new CostFunctionToFunctor<2, 5, 3>(
+// new IntrinsicProjection(observation_)));
+// }
+// template <typename T>
+// bool operator()(const T* rotation,
+// const T* translation,
+// const T* intrinsics,
+// const T* point,
+// T* residual) const {
+// T transformed_point[3];
+// RotateAndTranslatePoint(rotation, translation, point, transformed_point);
+//
+// // Note that we call intrinsic_projection_, just like it was
+// // any other templated functor.
+//
+// return (*intrinsic_projection_)(intrinsics, transformed_point, residual);
+// }
+//
+// private:
+// scoped_ptr<CostFunctionToFunctor<2,5,3> > intrinsic_projection_;
+// };
+
+#ifndef CERES_PUBLIC_COST_FUNCTION_TO_FUNCTOR_H_
+#define CERES_PUBLIC_COST_FUNCTION_TO_FUNCTOR_H_
+
+#include <numeric>
+#include <vector>
+
+#include "ceres/cost_function.h"
+#include "ceres/internal/fixed_array.h"
+#include "ceres/internal/port.h"
+#include "ceres/internal/scoped_ptr.h"
+
+namespace ceres {
+
+template <int kNumResiduals,
+ int N0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0,
+ int N5 = 0, int N6 = 0, int N7 = 0, int N8 = 0, int N9 = 0>
+class CostFunctionToFunctor {
+ public:
+ explicit CostFunctionToFunctor(CostFunction* cost_function)
+ : cost_function_(cost_function) {
+ CHECK_NOTNULL(cost_function);
+
+ CHECK_GE(kNumResiduals, 0);
+ CHECK_EQ(cost_function->num_residuals(), kNumResiduals);
+
+ // This block breaks the 80 column rule to keep it somewhat readable.
+ CHECK((!N1 && !N2 && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && !N2 && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && !N5 && !N6 && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && !N6 && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && (N8 > 0) && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && (N8 > 0) && (N9 > 0)))
+ << "Zero block cannot precede a non-zero block. Block sizes are "
+ << "(ignore trailing 0s): " << N0 << ", " << N1 << ", " << N2 << ", "
+ << N3 << ", " << N4 << ", " << N5 << ", " << N6 << ", " << N7 << ", "
+ << N8 << ", " << N9;
+
+ const vector<int16>& parameter_block_sizes =
+ cost_function->parameter_block_sizes();
+ const int num_parameter_blocks =
+ (N0 > 0) + (N1 > 0) + (N2 > 0) + (N3 > 0) + (N4 > 0) +
+ (N5 > 0) + (N6 > 0) + (N7 > 0) + (N8 > 0) + (N9 > 0);
+ CHECK_EQ(parameter_block_sizes.size(), num_parameter_blocks);
+
+ CHECK_EQ(N0, parameter_block_sizes[0]);
+ if (parameter_block_sizes.size() > 1) CHECK_EQ(N1, parameter_block_sizes[1]); // NOLINT
+ if (parameter_block_sizes.size() > 2) CHECK_EQ(N2, parameter_block_sizes[2]); // NOLINT
+ if (parameter_block_sizes.size() > 3) CHECK_EQ(N3, parameter_block_sizes[3]); // NOLINT
+ if (parameter_block_sizes.size() > 4) CHECK_EQ(N4, parameter_block_sizes[4]); // NOLINT
+ if (parameter_block_sizes.size() > 5) CHECK_EQ(N5, parameter_block_sizes[5]); // NOLINT
+ if (parameter_block_sizes.size() > 6) CHECK_EQ(N6, parameter_block_sizes[6]); // NOLINT
+ if (parameter_block_sizes.size() > 7) CHECK_EQ(N7, parameter_block_sizes[7]); // NOLINT
+ if (parameter_block_sizes.size() > 8) CHECK_EQ(N8, parameter_block_sizes[8]); // NOLINT
+ if (parameter_block_sizes.size() > 9) CHECK_EQ(N9, parameter_block_sizes[9]); // NOLINT
+
+ CHECK_EQ(accumulate(parameter_block_sizes.begin(),
+ parameter_block_sizes.end(), 0),
+ N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8 + N9);
+ }
+
+ bool operator()(const double* x0, double* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_EQ(N1, 0);
+ CHECK_EQ(N2, 0);
+ CHECK_EQ(N3, 0);
+ CHECK_EQ(N4, 0);
+ CHECK_EQ(N5, 0);
+ CHECK_EQ(N6, 0);
+ CHECK_EQ(N7, 0);
+ CHECK_EQ(N8, 0);
+ CHECK_EQ(N9, 0);
+
+ return cost_function_->Evaluate(&x0, residuals, NULL);
+ }
+
+ bool operator()(const double* x0,
+ const double* x1,
+ double* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_NE(N1, 0);
+ CHECK_EQ(N2, 0);
+ CHECK_EQ(N3, 0);
+ CHECK_EQ(N4, 0);
+ CHECK_EQ(N5, 0);
+ CHECK_EQ(N6, 0);
+ CHECK_EQ(N7, 0);
+ CHECK_EQ(N8, 0);
+ CHECK_EQ(N9, 0);
+ internal::FixedArray<const double*> parameter_blocks(2);
+ parameter_blocks[0] = x0;
+ parameter_blocks[1] = x1;
+ return cost_function_->Evaluate(parameter_blocks.get(), residuals, NULL);
+ }
+
+ bool operator()(const double* x0,
+ const double* x1,
+ const double* x2,
+ double* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_NE(N1, 0);
+ CHECK_NE(N2, 0);
+ CHECK_EQ(N3, 0);
+ CHECK_EQ(N4, 0);
+ CHECK_EQ(N5, 0);
+ CHECK_EQ(N6, 0);
+ CHECK_EQ(N7, 0);
+ CHECK_EQ(N8, 0);
+ CHECK_EQ(N9, 0);
+ internal::FixedArray<const double*> parameter_blocks(3);
+ parameter_blocks[0] = x0;
+ parameter_blocks[1] = x1;
+ parameter_blocks[2] = x2;
+ return cost_function_->Evaluate(parameter_blocks.get(), residuals, NULL);
+ }
+
+ bool operator()(const double* x0,
+ const double* x1,
+ const double* x2,
+ const double* x3,
+ double* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_NE(N1, 0);
+ CHECK_NE(N2, 0);
+ CHECK_NE(N3, 0);
+ CHECK_EQ(N4, 0);
+ CHECK_EQ(N5, 0);
+ CHECK_EQ(N6, 0);
+ CHECK_EQ(N7, 0);
+ CHECK_EQ(N8, 0);
+ CHECK_EQ(N9, 0);
+ internal::FixedArray<const double*> parameter_blocks(4);
+ parameter_blocks[0] = x0;
+ parameter_blocks[1] = x1;
+ parameter_blocks[2] = x2;
+ parameter_blocks[3] = x3;
+ return cost_function_->Evaluate(parameter_blocks.get(), residuals, NULL);
+ }
+
+ bool operator()(const double* x0,
+ const double* x1,
+ const double* x2,
+ const double* x3,
+ const double* x4,
+ double* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_NE(N1, 0);
+ CHECK_NE(N2, 0);
+ CHECK_NE(N3, 0);
+ CHECK_NE(N4, 0);
+ CHECK_EQ(N5, 0);
+ CHECK_EQ(N6, 0);
+ CHECK_EQ(N7, 0);
+ CHECK_EQ(N8, 0);
+ CHECK_EQ(N9, 0);
+ internal::FixedArray<const double*> parameter_blocks(5);
+ parameter_blocks[0] = x0;
+ parameter_blocks[1] = x1;
+ parameter_blocks[2] = x2;
+ parameter_blocks[3] = x3;
+ parameter_blocks[4] = x4;
+ return cost_function_->Evaluate(parameter_blocks.get(), residuals, NULL);
+ }
+
+ bool operator()(const double* x0,
+ const double* x1,
+ const double* x2,
+ const double* x3,
+ const double* x4,
+ const double* x5,
+ double* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_NE(N1, 0);
+ CHECK_NE(N2, 0);
+ CHECK_NE(N3, 0);
+ CHECK_NE(N4, 0);
+ CHECK_NE(N5, 0);
+ CHECK_EQ(N6, 0);
+ CHECK_EQ(N7, 0);
+ CHECK_EQ(N8, 0);
+ CHECK_EQ(N9, 0);
+ internal::FixedArray<const double*> parameter_blocks(6);
+ parameter_blocks[0] = x0;
+ parameter_blocks[1] = x1;
+ parameter_blocks[2] = x2;
+ parameter_blocks[3] = x3;
+ parameter_blocks[4] = x4;
+ parameter_blocks[5] = x5;
+ return cost_function_->Evaluate(parameter_blocks.get(), residuals, NULL);
+ }
+
+ bool operator()(const double* x0,
+ const double* x1,
+ const double* x2,
+ const double* x3,
+ const double* x4,
+ const double* x5,
+ const double* x6,
+ double* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_NE(N1, 0);
+ CHECK_NE(N2, 0);
+ CHECK_NE(N3, 0);
+ CHECK_NE(N4, 0);
+ CHECK_NE(N5, 0);
+ CHECK_NE(N6, 0);
+ CHECK_EQ(N7, 0);
+ CHECK_EQ(N8, 0);
+ CHECK_EQ(N9, 0);
+ internal::FixedArray<const double*> parameter_blocks(7);
+ parameter_blocks[0] = x0;
+ parameter_blocks[1] = x1;
+ parameter_blocks[2] = x2;
+ parameter_blocks[3] = x3;
+ parameter_blocks[4] = x4;
+ parameter_blocks[5] = x5;
+ parameter_blocks[6] = x6;
+ return cost_function_->Evaluate(parameter_blocks.get(), residuals, NULL);
+ }
+
+ bool operator()(const double* x0,
+ const double* x1,
+ const double* x2,
+ const double* x3,
+ const double* x4,
+ const double* x5,
+ const double* x6,
+ const double* x7,
+ double* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_NE(N1, 0);
+ CHECK_NE(N2, 0);
+ CHECK_NE(N3, 0);
+ CHECK_NE(N4, 0);
+ CHECK_NE(N5, 0);
+ CHECK_NE(N6, 0);
+ CHECK_NE(N7, 0);
+ CHECK_EQ(N8, 0);
+ CHECK_EQ(N9, 0);
+ internal::FixedArray<const double*> parameter_blocks(8);
+ parameter_blocks[0] = x0;
+ parameter_blocks[1] = x1;
+ parameter_blocks[2] = x2;
+ parameter_blocks[3] = x3;
+ parameter_blocks[4] = x4;
+ parameter_blocks[5] = x5;
+ parameter_blocks[6] = x6;
+ parameter_blocks[7] = x7;
+ return cost_function_->Evaluate(parameter_blocks.get(), residuals, NULL);
+ }
+
+ bool operator()(const double* x0,
+ const double* x1,
+ const double* x2,
+ const double* x3,
+ const double* x4,
+ const double* x5,
+ const double* x6,
+ const double* x7,
+ const double* x8,
+ double* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_NE(N1, 0);
+ CHECK_NE(N2, 0);
+ CHECK_NE(N3, 0);
+ CHECK_NE(N4, 0);
+ CHECK_NE(N5, 0);
+ CHECK_NE(N6, 0);
+ CHECK_NE(N7, 0);
+ CHECK_NE(N8, 0);
+ CHECK_EQ(N9, 0);
+ internal::FixedArray<const double*> parameter_blocks(9);
+ parameter_blocks[0] = x0;
+ parameter_blocks[1] = x1;
+ parameter_blocks[2] = x2;
+ parameter_blocks[3] = x3;
+ parameter_blocks[4] = x4;
+ parameter_blocks[5] = x5;
+ parameter_blocks[6] = x6;
+ parameter_blocks[7] = x7;
+ parameter_blocks[8] = x8;
+ return cost_function_->Evaluate(parameter_blocks.get(), residuals, NULL);
+ }
+
+ bool operator()(const double* x0,
+ const double* x1,
+ const double* x2,
+ const double* x3,
+ const double* x4,
+ const double* x5,
+ const double* x6,
+ const double* x7,
+ const double* x8,
+ const double* x9,
+ double* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_NE(N1, 0);
+ CHECK_NE(N2, 0);
+ CHECK_NE(N3, 0);
+ CHECK_NE(N4, 0);
+ CHECK_NE(N5, 0);
+ CHECK_NE(N6, 0);
+ CHECK_NE(N7, 0);
+ CHECK_NE(N8, 0);
+ CHECK_NE(N9, 0);
+ internal::FixedArray<const double*> parameter_blocks(10);
+ parameter_blocks[0] = x0;
+ parameter_blocks[1] = x1;
+ parameter_blocks[2] = x2;
+ parameter_blocks[3] = x3;
+ parameter_blocks[4] = x4;
+ parameter_blocks[5] = x5;
+ parameter_blocks[6] = x6;
+ parameter_blocks[7] = x7;
+ parameter_blocks[8] = x8;
+ parameter_blocks[9] = x9;
+ return cost_function_->Evaluate(parameter_blocks.get(), residuals, NULL);
+ }
+
+ template <typename JetT>
+ bool operator()(const JetT* x0, JetT* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_EQ(N1, 0);
+ CHECK_EQ(N2, 0);
+ CHECK_EQ(N3, 0);
+ CHECK_EQ(N4, 0);
+ CHECK_EQ(N5, 0);
+ CHECK_EQ(N6, 0);
+ CHECK_EQ(N7, 0);
+ CHECK_EQ(N8, 0);
+ CHECK_EQ(N9, 0);
+ return EvaluateWithJets(&x0, residuals);
+ }
+
+ template <typename JetT>
+ bool operator()(const JetT* x0,
+ const JetT* x1,
+ JetT* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_NE(N1, 0);
+ CHECK_EQ(N2, 0);
+ CHECK_EQ(N3, 0);
+ CHECK_EQ(N4, 0);
+ CHECK_EQ(N5, 0);
+ CHECK_EQ(N6, 0);
+ CHECK_EQ(N7, 0);
+ CHECK_EQ(N8, 0);
+ CHECK_EQ(N9, 0);
+ internal::FixedArray<const JetT*> jets(2);
+ jets[0] = x0;
+ jets[1] = x1;
+ return EvaluateWithJets(jets.get(), residuals);
+ }
+
+ template <typename JetT>
+ bool operator()(const JetT* x0,
+ const JetT* x1,
+ const JetT* x2,
+ JetT* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_NE(N1, 0);
+ CHECK_NE(N2, 0);
+ CHECK_EQ(N3, 0);
+ CHECK_EQ(N4, 0);
+ CHECK_EQ(N5, 0);
+ CHECK_EQ(N6, 0);
+ CHECK_EQ(N7, 0);
+ CHECK_EQ(N8, 0);
+ CHECK_EQ(N9, 0);
+ internal::FixedArray<const JetT*> jets(3);
+ jets[0] = x0;
+ jets[1] = x1;
+ jets[2] = x2;
+ return EvaluateWithJets(jets.get(), residuals);
+ }
+
+ template <typename JetT>
+ bool operator()(const JetT* x0,
+ const JetT* x1,
+ const JetT* x2,
+ const JetT* x3,
+ JetT* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_NE(N1, 0);
+ CHECK_NE(N2, 0);
+ CHECK_NE(N3, 0);
+ CHECK_EQ(N4, 0);
+ CHECK_EQ(N5, 0);
+ CHECK_EQ(N6, 0);
+ CHECK_EQ(N7, 0);
+ CHECK_EQ(N8, 0);
+ CHECK_EQ(N9, 0);
+ internal::FixedArray<const JetT*> jets(4);
+ jets[0] = x0;
+ jets[1] = x1;
+ jets[2] = x2;
+ jets[3] = x3;
+ return EvaluateWithJets(jets.get(), residuals);
+ }
+
+ template <typename JetT>
+ bool operator()(const JetT* x0,
+ const JetT* x1,
+ const JetT* x2,
+ const JetT* x3,
+ const JetT* x4,
+ JetT* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_NE(N1, 0);
+ CHECK_NE(N2, 0);
+ CHECK_NE(N3, 0);
+ CHECK_NE(N4, 0);
+ CHECK_EQ(N5, 0);
+ CHECK_EQ(N6, 0);
+ CHECK_EQ(N7, 0);
+ CHECK_EQ(N8, 0);
+ CHECK_EQ(N9, 0);
+ internal::FixedArray<const JetT*> jets(5);
+ jets[0] = x0;
+ jets[1] = x1;
+ jets[2] = x2;
+ jets[3] = x3;
+ jets[4] = x4;
+ return EvaluateWithJets(jets.get(), residuals);
+ }
+
+ template <typename JetT>
+ bool operator()(const JetT* x0,
+ const JetT* x1,
+ const JetT* x2,
+ const JetT* x3,
+ const JetT* x4,
+ const JetT* x5,
+ JetT* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_NE(N1, 0);
+ CHECK_NE(N2, 0);
+ CHECK_NE(N3, 0);
+ CHECK_NE(N4, 0);
+ CHECK_NE(N5, 0);
+ CHECK_EQ(N6, 0);
+ CHECK_EQ(N7, 0);
+ CHECK_EQ(N8, 0);
+ CHECK_EQ(N9, 0);
+ internal::FixedArray<const JetT*> jets(6);
+ jets[0] = x0;
+ jets[1] = x1;
+ jets[2] = x2;
+ jets[3] = x3;
+ jets[4] = x4;
+ jets[5] = x5;
+ return EvaluateWithJets(jets.get(), residuals);
+ }
+
+ template <typename JetT>
+ bool operator()(const JetT* x0,
+ const JetT* x1,
+ const JetT* x2,
+ const JetT* x3,
+ const JetT* x4,
+ const JetT* x5,
+ const JetT* x6,
+ JetT* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_NE(N1, 0);
+ CHECK_NE(N2, 0);
+ CHECK_NE(N3, 0);
+ CHECK_NE(N4, 0);
+ CHECK_NE(N5, 0);
+ CHECK_NE(N6, 0);
+ CHECK_EQ(N7, 0);
+ CHECK_EQ(N8, 0);
+ CHECK_EQ(N9, 0);
+ internal::FixedArray<const JetT*> jets(7);
+ jets[0] = x0;
+ jets[1] = x1;
+ jets[2] = x2;
+ jets[3] = x3;
+ jets[4] = x4;
+ jets[5] = x5;
+ jets[6] = x6;
+ return EvaluateWithJets(jets.get(), residuals);
+ }
+
+ template <typename JetT>
+ bool operator()(const JetT* x0,
+ const JetT* x1,
+ const JetT* x2,
+ const JetT* x3,
+ const JetT* x4,
+ const JetT* x5,
+ const JetT* x6,
+ const JetT* x7,
+ JetT* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_NE(N1, 0);
+ CHECK_NE(N2, 0);
+ CHECK_NE(N3, 0);
+ CHECK_NE(N4, 0);
+ CHECK_NE(N5, 0);
+ CHECK_NE(N6, 0);
+ CHECK_NE(N7, 0);
+ CHECK_EQ(N8, 0);
+ CHECK_EQ(N9, 0);
+ internal::FixedArray<const JetT*> jets(8);
+ jets[0] = x0;
+ jets[1] = x1;
+ jets[2] = x2;
+ jets[3] = x3;
+ jets[4] = x4;
+ jets[5] = x5;
+ jets[6] = x6;
+ jets[7] = x7;
+ return EvaluateWithJets(jets.get(), residuals);
+ }
+
+ template <typename JetT>
+ bool operator()(const JetT* x0,
+ const JetT* x1,
+ const JetT* x2,
+ const JetT* x3,
+ const JetT* x4,
+ const JetT* x5,
+ const JetT* x6,
+ const JetT* x7,
+ const JetT* x8,
+ JetT* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_NE(N1, 0);
+ CHECK_NE(N2, 0);
+ CHECK_NE(N3, 0);
+ CHECK_NE(N4, 0);
+ CHECK_NE(N5, 0);
+ CHECK_NE(N6, 0);
+ CHECK_NE(N7, 0);
+ CHECK_NE(N8, 0);
+ CHECK_EQ(N9, 0);
+ internal::FixedArray<const JetT*> jets(9);
+ jets[0] = x0;
+ jets[1] = x1;
+ jets[2] = x2;
+ jets[3] = x3;
+ jets[4] = x4;
+ jets[5] = x5;
+ jets[6] = x6;
+ jets[7] = x7;
+ jets[8] = x8;
+ return EvaluateWithJets(jets.get(), residuals);
+ }
+
+ template <typename JetT>
+ bool operator()(const JetT* x0,
+ const JetT* x1,
+ const JetT* x2,
+ const JetT* x3,
+ const JetT* x4,
+ const JetT* x5,
+ const JetT* x6,
+ const JetT* x7,
+ const JetT* x8,
+ const JetT* x9,
+ JetT* residuals) const {
+ CHECK_NE(N0, 0);
+ CHECK_NE(N1, 0);
+ CHECK_NE(N2, 0);
+ CHECK_NE(N3, 0);
+ CHECK_NE(N4, 0);
+ CHECK_NE(N5, 0);
+ CHECK_NE(N6, 0);
+ CHECK_NE(N7, 0);
+ CHECK_NE(N8, 0);
+ CHECK_NE(N9, 0);
+ internal::FixedArray<const JetT*> jets(10);
+ jets[0] = x0;
+ jets[1] = x1;
+ jets[2] = x2;
+ jets[3] = x3;
+ jets[4] = x4;
+ jets[5] = x5;
+ jets[6] = x6;
+ jets[7] = x7;
+ jets[8] = x8;
+ jets[9] = x9;
+ return EvaluateWithJets(jets.get(), residuals);
+ }
+
+ private:
+ template <typename JetT>
+ bool EvaluateWithJets(const JetT** inputs, JetT* output) const {
+ const int kNumParameters = N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8 + N9;
+ const vector<int16>& parameter_block_sizes =
+ cost_function_->parameter_block_sizes();
+ const int num_parameter_blocks = parameter_block_sizes.size();
+ const int num_residuals = cost_function_->num_residuals();
+
+ internal::FixedArray<double> parameters(kNumParameters);
+ internal::FixedArray<double*> parameter_blocks(num_parameter_blocks);
+ internal::FixedArray<double> jacobians(num_residuals * kNumParameters);
+ internal::FixedArray<double*> jacobian_blocks(num_parameter_blocks);
+ internal::FixedArray<double> residuals(num_residuals);
+
+ // Build a set of arrays to get the residuals and jacobians from
+ // the CostFunction wrapped by this functor.
+ double* parameter_ptr = parameters.get();
+ double* jacobian_ptr = jacobians.get();
+ for (int i = 0; i < num_parameter_blocks; ++i) {
+ parameter_blocks[i] = parameter_ptr;
+ jacobian_blocks[i] = jacobian_ptr;
+ for (int j = 0; j < parameter_block_sizes[i]; ++j) {
+ *parameter_ptr++ = inputs[i][j].a;
+ }
+ jacobian_ptr += num_residuals * parameter_block_sizes[i];
+ }
+
+ if (!cost_function_->Evaluate(parameter_blocks.get(),
+ residuals.get(),
+ jacobian_blocks.get())) {
+ return false;
+ }
+
+ // Now that we have the incoming Jets, which are carrying the
+ // partial derivatives of each of the inputs w.r.t to some other
+ // underlying parameters. The derivative of the outputs of the
+ // cost function w.r.t to the same underlying parameters can now
+ // be computed by applying the chain rule.
+ //
+ // d output[i] d output[i] d input[j]
+ // -------------- = sum_j ----------- * ------------
+ // d parameter[k] d input[j] d parameter[k]
+ //
+ // d input[j]
+ // -------------- = inputs[j], so
+ // d parameter[k]
+ //
+ // outputJet[i] = sum_k jacobian[i][k] * inputJet[k]
+ //
+ // The following loop, iterates over the residuals, computing one
+ // output jet at a time.
+ for (int i = 0; i < num_residuals; ++i) {
+ output[i].a = residuals[i];
+ output[i].v.setZero();
+
+ for (int j = 0; j < num_parameter_blocks; ++j) {
+ const int16 block_size = parameter_block_sizes[j];
+ for (int k = 0; k < parameter_block_sizes[j]; ++k) {
+ output[i].v +=
+ jacobian_blocks[j][i * block_size + k] * inputs[j][k].v;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private:
+ internal::scoped_ptr<CostFunction> cost_function_;
+};
+
+} // namespace ceres
+
+#endif // CERES_PUBLIC_COST_FUNCTION_TO_FUNCTOR_H_
diff --git a/extern/libmv/third_party/ceres/include/ceres/crs_matrix.h b/extern/libmv/third_party/ceres/include/ceres/crs_matrix.h
index c9fe8f78b7c..8c470cd33f2 100644
--- a/extern/libmv/third_party/ceres/include/ceres/crs_matrix.h
+++ b/extern/libmv/third_party/ceres/include/ceres/crs_matrix.h
@@ -44,17 +44,35 @@ struct CRSMatrix {
int num_rows;
int num_cols;
- // A compressed row matrix stores its contents in three arrays.
- // The non-zero pattern of the i^th row is given by
+ // A compressed row matrix stores its contents in three arrays,
+ // rows, cols and values.
//
- // rows[cols[i] ... cols[i + 1]]
+ // rows is a num_rows + 1 sized array that points into the cols and
+ // values array. For each row i:
//
- // and the corresponding values by
+ // cols[rows[i]] ... cols[rows[i + 1] - 1] are the indices of the
+ // non-zero columns of row i.
//
- // values[cols[i] ... cols[i + 1]]
+ // values[rows[i]] .. values[rows[i + 1] - 1] are the values of the
+ // corresponding entries.
//
- // Thus, cols is a vector of size num_cols + 1, and rows and values
- // have as many entries as number of non-zeros in the matrix.
+ // cols and values contain as many entries as there are non-zeros in
+ // the matrix.
+ //
+ // e.g, consider the 3x4 sparse matrix
+ //
+ // [ 0 10 0 4 ]
+ // [ 0 2 -3 2 ]
+ // [ 1 2 0 0 ]
+ //
+ // The three arrays will be:
+ //
+ //
+ // -row0- ---row1--- -row2-
+ // rows = [ 0, 2, 5, 7]
+ // cols = [ 1, 3, 1, 2, 3, 0, 1]
+ // values = [10, 4, 2, -3, 2, 1, 2]
+
vector<int> cols;
vector<int> rows;
vector<double> values;
diff --git a/extern/libmv/third_party/ceres/include/ceres/dynamic_autodiff_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/dynamic_autodiff_cost_function.h
new file mode 100644
index 00000000000..e4549c54b43
--- /dev/null
+++ b/extern/libmv/third_party/ceres/include/ceres/dynamic_autodiff_cost_function.h
@@ -0,0 +1,215 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: mierle@gmail.com (Keir Mierle)
+// sameeragarwal@google.com (Sameer Agarwal)
+// thadh@gmail.com (Thad Hughes)
+//
+// This autodiff implementation differs from the one found in
+// autodiff_cost_function.h by supporting autodiff on cost functions with
+// variable numbers of parameters with variable sizes. With the other
+// implementation, all the sizes (both the number of parameter blocks and the
+// size of each block) must be fixed at compile time.
+//
+// The functor API differs slightly from the API for fixed size autodiff; the
+// expected interface for the cost functors is:
+//
+// struct MyCostFunctor {
+// template<typename T>
+// bool operator()(T const* const* parameters, T* residuals) const {
+// // Use parameters[i] to access the i'th parameter block.
+// }
+// }
+//
+// Since the sizing of the parameters is done at runtime, you must also specify
+// the sizes after creating the dynamic autodiff cost function. For example:
+//
+// DynamicAutoDiffCostFunction<MyCostFunctor, 3> cost_function(
+// new MyCostFunctor());
+// cost_function.AddParameterBlock(5);
+// cost_function.AddParameterBlock(10);
+// cost_function.SetNumResiduals(21);
+//
+// Under the hood, the implementation evaluates the cost function multiple
+// times, computing a small set of the derivatives (four by default, controlled
+// by the Stride template parameter) with each pass. There is a tradeoff with
+// the size of the passes; you may want to experiment with the stride.
+
+#ifndef CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
+#define CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
+
+#include <cmath>
+#include <numeric>
+#include <vector>
+
+#include "ceres/cost_function.h"
+#include "ceres/internal/scoped_ptr.h"
+#include "ceres/jet.h"
+#include "glog/logging.h"
+
+namespace ceres {
+
+template <typename CostFunctor, int Stride = 4>
+class DynamicAutoDiffCostFunction : public CostFunction {
+ public:
+ explicit DynamicAutoDiffCostFunction(CostFunctor* functor)
+ : functor_(functor) {}
+
+ virtual ~DynamicAutoDiffCostFunction() {}
+
+ void AddParameterBlock(int size) {
+ mutable_parameter_block_sizes()->push_back(size);
+ }
+
+ void SetNumResiduals(int num_residuals) {
+ set_num_residuals(num_residuals);
+ }
+
+ virtual bool Evaluate(double const* const* parameters,
+ double* residuals,
+ double** jacobians) const {
+ CHECK_GT(num_residuals(), 0)
+ << "You must call DynamicAutoDiffCostFunction::SetNumResiduals() "
+ << "before DynamicAutoDiffCostFunction::Evaluate().";
+
+ if (jacobians == NULL) {
+ return (*functor_)(parameters, residuals);
+ }
+
+ // The difficulty with Jets, as implemented in Ceres, is that they were
+ // originally designed for strictly compile-sized use. At this point, there
+ // is a large body of code that assumes inside a cost functor it is
+ // acceptable to do e.g. T(1.5) and get an appropriately sized jet back.
+ //
+ // Unfortunately, it is impossible to communicate the expected size of a
+ // dynamically sized jet to the static instantiations that existing code
+ // depends on.
+ //
+ // To work around this issue, the solution here is to evaluate the
+ // jacobians in a series of passes, each one computing Stripe *
+ // num_residuals() derivatives. This is done with small, fixed-size jets.
+ const int num_parameter_blocks = parameter_block_sizes().size();
+ const int num_parameters = std::accumulate(parameter_block_sizes().begin(),
+ parameter_block_sizes().end(),
+ 0);
+
+ // Allocate scratch space for the strided evaluation.
+ vector<Jet<double, Stride> > input_jets(num_parameters);
+ vector<Jet<double, Stride> > output_jets(num_residuals());
+
+ // Make the parameter pack that is sent to the functor (reused).
+ vector<Jet<double, Stride>* > jet_parameters(num_parameter_blocks, NULL);
+ int num_active_parameters = 0;
+ int start_derivative_section = -1;
+ for (int i = 0, parameter_cursor = 0; i < num_parameter_blocks; ++i) {
+ jet_parameters[i] = &input_jets[parameter_cursor];
+
+ const int parameter_block_size = parameter_block_sizes()[i];
+ if (jacobians[i] != NULL) {
+ start_derivative_section =
+ (start_derivative_section == -1)
+ ? parameter_cursor
+ : start_derivative_section;
+ num_active_parameters += parameter_block_size;
+ }
+
+ for (int j = 0; j < parameter_block_size; ++j, parameter_cursor++) {
+ input_jets[parameter_cursor].a = parameters[i][j];
+ }
+ }
+
+ // Evaluate all of the strides. Each stride is a chunk of the derivative to
+ // evaluate, typically some size proportional to the size of the SIMD
+ // registers of the CPU.
+ int num_strides = static_cast<int>(ceil(num_active_parameters /
+ static_cast<float>(Stride)));
+
+ for (int pass = 0; pass < num_strides; ++pass) {
+ // Set most of the jet components to zero, except for
+ // non-constant #Stride parameters.
+ int active_parameter_count = 0;
+ int end_derivative_section = start_derivative_section;
+ for (int i = 0, parameter_cursor = 0; i < num_parameter_blocks; ++i) {
+ for (int j = 0; j < parameter_block_sizes()[i];
+ ++j, parameter_cursor++) {
+ input_jets[parameter_cursor].v.setZero();
+ if (parameter_cursor >= start_derivative_section &&
+ active_parameter_count < Stride) {
+ if (jacobians[i] != NULL) {
+ input_jets[parameter_cursor]
+ .v[parameter_cursor - start_derivative_section] = 1.0;
+ ++active_parameter_count;
+ }
+ ++end_derivative_section;
+ }
+ }
+ }
+
+ if (!(*functor_)(&jet_parameters[0], &output_jets[0])) {
+ return false;
+ }
+
+ // Copy the pieces of the jacobians into their final place.
+ active_parameter_count = 0;
+ for (int i = 0, parameter_cursor = 0; i < num_parameter_blocks; ++i) {
+ for (int j = 0; j < parameter_block_sizes()[i];
+ ++j, parameter_cursor++) {
+ if (parameter_cursor >= start_derivative_section &&
+ active_parameter_count < Stride) {
+ if (jacobians[i] != NULL) {
+ for (int k = 0; k < num_residuals(); ++k) {
+ jacobians[i][k * parameter_block_sizes()[i] + j] =
+ output_jets[k].v[parameter_cursor -
+ start_derivative_section];
+ }
+ ++active_parameter_count;
+ }
+ }
+ }
+ }
+
+ // Only copy the residuals over once (even though we compute them on
+ // every loop).
+ if (pass == num_strides - 1) {
+ for (int k = 0; k < num_residuals(); ++k) {
+ residuals[k] = output_jets[k].a;
+ }
+ }
+
+ start_derivative_section = end_derivative_section;
+ }
+ return true;
+ }
+
+ private:
+ internal::scoped_ptr<CostFunctor> functor_;
+};
+
+} // namespace ceres
+
+#endif // CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
diff --git a/extern/libmv/third_party/ceres/include/ceres/fpclassify.h b/extern/libmv/third_party/ceres/include/ceres/fpclassify.h
index 5a9ea1599d2..b730832fd4b 100644
--- a/extern/libmv/third_party/ceres/include/ceres/fpclassify.h
+++ b/extern/libmv/third_party/ceres/include/ceres/fpclassify.h
@@ -41,6 +41,8 @@
#include <float.h>
#endif
+#include <limits>
+
namespace ceres {
#if defined(_MSC_VER)
diff --git a/extern/libmv/third_party/ceres/include/ceres/gradient_checker.h b/extern/libmv/third_party/ceres/include/ceres/gradient_checker.h
new file mode 100644
index 00000000000..3ec8056a02d
--- /dev/null
+++ b/extern/libmv/third_party/ceres/include/ceres/gradient_checker.h
@@ -0,0 +1,222 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+// Copyright 2007 Google Inc. All Rights Reserved.
+//
+// Author: wjr@google.com (William Rucklidge)
+//
+// This file contains a class that exercises a cost function, to make sure
+// that it is computing reasonable derivatives. It compares the Jacobians
+// computed by the cost function with those obtained by finite
+// differences.
+
+#ifndef CERES_PUBLIC_GRADIENT_CHECKER_H_
+#define CERES_PUBLIC_GRADIENT_CHECKER_H_
+
+#include <cstddef>
+#include <algorithm>
+#include <vector>
+
+#include "ceres/internal/eigen.h"
+#include "ceres/internal/fixed_array.h"
+#include "ceres/internal/macros.h"
+#include "ceres/internal/scoped_ptr.h"
+#include "ceres/numeric_diff_cost_function.h"
+#include "glog/logging.h"
+
+namespace ceres {
+
+// An object that exercises a cost function, to compare the answers that it
+// gives with derivatives estimated using finite differencing.
+//
+// The only likely usage of this is for testing.
+//
+// How to use: Fill in an array of pointers to parameter blocks for your
+// CostFunction, and then call Probe(). Check that the return value is
+// 'true'. See prober_test.cc for an example.
+//
+// This is templated similarly to NumericDiffCostFunction, as it internally
+// uses that.
+template <typename CostFunctionToProbe,
+ int M = 0, int N0 = 0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0>
+class GradientChecker {
+ public:
+ // Here we stash some results from the probe, for later
+ // inspection.
+ struct GradientCheckResults {
+ // Computed cost.
+ Vector cost;
+
+ // The sizes of these matrices are dictated by the cost function's
+ // parameter and residual block sizes. Each vector's length will
+ // term->parameter_block_sizes().size(), and each matrix is the
+ // Jacobian of the residual with respect to the corresponding parameter
+ // block.
+
+ // Derivatives as computed by the cost function.
+ vector<Matrix> term_jacobians;
+
+ // Derivatives as computed by finite differencing.
+ vector<Matrix> finite_difference_jacobians;
+
+ // Infinity-norm of term_jacobians - finite_difference_jacobians.
+ double error_jacobians;
+ };
+
+ // Checks the Jacobian computed by a cost function.
+ //
+ // probe_point: The parameter values at which to probe.
+ // error_tolerance: A threshold for the infinity-norm difference
+ // between the Jacobians. If the Jacobians differ by more than
+ // this amount, then the probe fails.
+ //
+ // term: The cost function to test. Not retained after this call returns.
+ //
+ // results: On return, the two Jacobians (and other information)
+ // will be stored here. May be NULL.
+ //
+ // Returns true if no problems are detected and the difference between the
+ // Jacobians is less than error_tolerance.
+ static bool Probe(double const* const* probe_point,
+ double error_tolerance,
+ CostFunctionToProbe *term,
+ GradientCheckResults* results) {
+ CHECK_NOTNULL(probe_point);
+ CHECK_NOTNULL(term);
+ LOG(INFO) << "-------------------- Starting Probe() --------------------";
+
+ // We need a GradientCheckeresults, whether or not they supplied one.
+ internal::scoped_ptr<GradientCheckResults> owned_results;
+ if (results == NULL) {
+ owned_results.reset(new GradientCheckResults);
+ results = owned_results.get();
+ }
+
+ // Do a consistency check between the term and the template parameters.
+ CHECK_EQ(M, term->num_residuals());
+ const int num_residuals = M;
+ const vector<int16>& block_sizes = term->parameter_block_sizes();
+ const int num_blocks = block_sizes.size();
+
+ CHECK_LE(num_blocks, 5) << "Unable to test functions that take more "
+ << "than 5 parameter blocks";
+ if (N0) {
+ CHECK_EQ(N0, block_sizes[0]);
+ CHECK_GE(num_blocks, 1);
+ } else {
+ CHECK_LT(num_blocks, 1);
+ }
+ if (N1) {
+ CHECK_EQ(N1, block_sizes[1]);
+ CHECK_GE(num_blocks, 2);
+ } else {
+ CHECK_LT(num_blocks, 2);
+ }
+ if (N2) {
+ CHECK_EQ(N2, block_sizes[2]);
+ CHECK_GE(num_blocks, 3);
+ } else {
+ CHECK_LT(num_blocks, 3);
+ }
+ if (N3) {
+ CHECK_EQ(N3, block_sizes[3]);
+ CHECK_GE(num_blocks, 4);
+ } else {
+ CHECK_LT(num_blocks, 4);
+ }
+ if (N4) {
+ CHECK_EQ(N4, block_sizes[4]);
+ CHECK_GE(num_blocks, 5);
+ } else {
+ CHECK_LT(num_blocks, 5);
+ }
+
+ results->term_jacobians.clear();
+ results->term_jacobians.resize(num_blocks);
+ results->finite_difference_jacobians.clear();
+ results->finite_difference_jacobians.resize(num_blocks);
+
+ internal::FixedArray<double*> term_jacobian_pointers(num_blocks);
+ internal::FixedArray<double*>
+ finite_difference_jacobian_pointers(num_blocks);
+ for (int i = 0; i < num_blocks; i++) {
+ results->term_jacobians[i].resize(num_residuals, block_sizes[i]);
+ term_jacobian_pointers[i] = results->term_jacobians[i].data();
+ results->finite_difference_jacobians[i].resize(
+ num_residuals, block_sizes[i]);
+ finite_difference_jacobian_pointers[i] =
+ results->finite_difference_jacobians[i].data();
+ }
+ results->cost.resize(num_residuals, 1);
+
+ CHECK(term->Evaluate(probe_point, results->cost.data(),
+ term_jacobian_pointers.get()));
+ NumericDiffCostFunction<CostFunctionToProbe, CENTRAL, M, N0, N1, N2, N3, N4>
+ numeric_term(term, DO_NOT_TAKE_OWNERSHIP);
+ CHECK(numeric_term.Evaluate(probe_point, results->cost.data(),
+ finite_difference_jacobian_pointers.get()));
+
+ results->error_jacobians = 0;
+ for (int i = 0; i < num_blocks; i++) {
+ Matrix jacobian_difference = results->term_jacobians[i] -
+ results->finite_difference_jacobians[i];
+ results->error_jacobians =
+ std::max(results->error_jacobians,
+ jacobian_difference.lpNorm<Eigen::Infinity>());
+ }
+
+ LOG(INFO) << "========== term-computed derivatives ==========";
+ for (int i = 0; i < num_blocks; i++) {
+ LOG(INFO) << "term_computed block " << i;
+ LOG(INFO) << "\n" << results->term_jacobians[i];
+ }
+
+ LOG(INFO) << "========== finite-difference derivatives ==========";
+ for (int i = 0; i < num_blocks; i++) {
+ LOG(INFO) << "finite_difference block " << i;
+ LOG(INFO) << "\n" << results->finite_difference_jacobians[i];
+ }
+
+ LOG(INFO) << "========== difference ==========";
+ for (int i = 0; i < num_blocks; i++) {
+ LOG(INFO) << "difference block " << i;
+ LOG(INFO) << (results->term_jacobians[i] -
+ results->finite_difference_jacobians[i]);
+ }
+
+ LOG(INFO) << "||difference|| = " << results->error_jacobians;
+
+ return results->error_jacobians < error_tolerance;
+ }
+
+ private:
+ CERES_DISALLOW_IMPLICIT_CONSTRUCTORS(GradientChecker);
+};
+
+} // namespace ceres
+
+#endif // CERES_PUBLIC_GRADIENT_CHECKER_H_
diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h b/extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h
index 4f5081f8f66..2b32671c06d 100644
--- a/extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h
+++ b/extern/libmv/third_party/ceres/include/ceres/internal/autodiff.h
@@ -38,7 +38,7 @@
//
// struct F {
// template<typename T>
-// bool operator(const T *x, const T *y, ..., T *z) {
+// bool operator()(const T *x, const T *y, ..., T *z) {
// // Compute z[] based on x[], y[], ...
// // return true if computation succeeded, false otherwise.
// }
@@ -102,7 +102,7 @@
//
// struct F {
// template<typename T>
-// bool operator(const T *p, const T *q, T *z) {
+// bool operator()(const T *p, const T *q, T *z) {
// // ...
// }
// };
@@ -146,6 +146,7 @@
#include "ceres/jet.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/fixed_array.h"
+#include "ceres/internal/variadic_evaluate.h"
namespace ceres {
namespace internal {
@@ -191,134 +192,71 @@ inline void Take1stOrderPart(const int M, const JetT *src, T *dst) {
DCHECK(src);
DCHECK(dst);
for (int i = 0; i < M; ++i) {
- Eigen::Map<Eigen::Matrix<T, N, 1> >(dst + N * i, N) = src[i].v.template segment<N>(N0);
+ Eigen::Map<Eigen::Matrix<T, N, 1> >(dst + N * i, N) =
+ src[i].v.template segment<N>(N0);
}
}
-// This block of quasi-repeated code calls the user-supplied functor, which may
-// take a variable number of arguments. This is accomplished by specializing the
-// struct based on the size of the trailing parameters; parameters with 0 size
-// are assumed missing.
-//
-// Supporting variadic functions is the primary source of complexity in the
-// autodiff implementation.
-
-template<typename Functor, typename T,
- int N0, int N1, int N2, int N3, int N4, int N5>
-struct VariadicEvaluate {
- static bool Call(const Functor& functor, T const *const *input, T* output) {
- return functor(input[0],
- input[1],
- input[2],
- input[3],
- input[4],
- input[5],
- output);
- }
-};
-
-template<typename Functor, typename T,
- int N0, int N1, int N2, int N3, int N4>
-struct VariadicEvaluate<Functor, T, N0, N1, N2, N3, N4, 0> {
- static bool Call(const Functor& functor, T const *const *input, T* output) {
- return functor(input[0],
- input[1],
- input[2],
- input[3],
- input[4],
- output);
- }
-};
-
-template<typename Functor, typename T,
- int N0, int N1, int N2, int N3>
-struct VariadicEvaluate<Functor, T, N0, N1, N2, N3, 0, 0> {
- static bool Call(const Functor& functor, T const *const *input, T* output) {
- return functor(input[0],
- input[1],
- input[2],
- input[3],
- output);
- }
-};
-
-template<typename Functor, typename T,
- int N0, int N1, int N2>
-struct VariadicEvaluate<Functor, T, N0, N1, N2, 0, 0, 0> {
- static bool Call(const Functor& functor, T const *const *input, T* output) {
- return functor(input[0],
- input[1],
- input[2],
- output);
- }
-};
-
-template<typename Functor, typename T,
- int N0, int N1>
-struct VariadicEvaluate<Functor, T, N0, N1, 0, 0, 0, 0> {
- static bool Call(const Functor& functor, T const *const *input, T* output) {
- return functor(input[0],
- input[1],
- output);
- }
-};
-
-template<typename Functor, typename T, int N0>
-struct VariadicEvaluate<Functor, T, N0, 0, 0, 0, 0, 0> {
- static bool Call(const Functor& functor, T const *const *input, T* output) {
- return functor(input[0],
- output);
- }
-};
-
-// This is in a struct because default template parameters on a function are not
-// supported in C++03 (though it is available in C++0x). N0 through N5 are the
-// dimension of the input arguments to the user supplied functor.
+// This is in a struct because default template parameters on a
+// function are not supported in C++03 (though it is available in
+// C++0x). N0 through N5 are the dimension of the input arguments to
+// the user supplied functor.
template <typename Functor, typename T,
- int N0 = 0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0, int N5=0>
+ int N0 = 0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0,
+ int N5 = 0, int N6 = 0, int N7 = 0, int N8 = 0, int N9 = 0>
struct AutoDiff {
static bool Differentiate(const Functor& functor,
T const *const *parameters,
int num_outputs,
T *function_value,
T **jacobians) {
- typedef Jet<T, N0 + N1 + N2 + N3 + N4 + N5> JetT;
-
- DCHECK_GT(N0, 0)
- << "Cost functions must have at least one parameter block.";
- DCHECK((!N1 && !N2 && !N3 && !N4 && !N5) ||
- ((N1 > 0) && !N2 && !N3 && !N4 && !N5) ||
- ((N1 > 0) && (N2 > 0) && !N3 && !N4 && !N5) ||
- ((N1 > 0) && (N2 > 0) && (N3 > 0) && !N4 && !N5) ||
- ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && !N5) ||
- ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0)))
+ // This block breaks the 80 column rule to keep it somewhat readable.
+ DCHECK_GT(num_outputs, 0);
+ CHECK((!N1 && !N2 && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && !N2 && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && !N5 && !N6 && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && !N6 && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && (N8 > 0) && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && (N8 > 0) && (N9 > 0)))
<< "Zero block cannot precede a non-zero block. Block sizes are "
<< "(ignore trailing 0s): " << N0 << ", " << N1 << ", " << N2 << ", "
- << N3 << ", " << N4 << ", " << N5;
-
- DCHECK_GT(num_outputs, 0);
+ << N3 << ", " << N4 << ", " << N5 << ", " << N6 << ", " << N7 << ", "
+ << N8 << ", " << N9;
+ typedef Jet<T, N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8 + N9> JetT;
FixedArray<JetT, (256 * 7) / sizeof(JetT)> x(
- N0 + N1 + N2 + N3 + N4 + N5 + num_outputs);
+ N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8 + N9 + num_outputs);
- // It's ugly, but it works.
- const int jet0 = 0;
- const int jet1 = N0;
- const int jet2 = N0 + N1;
- const int jet3 = N0 + N1 + N2;
- const int jet4 = N0 + N1 + N2 + N3;
- const int jet5 = N0 + N1 + N2 + N3 + N4;
- const int jet6 = N0 + N1 + N2 + N3 + N4 + N5;
+ // These are the positions of the respective jets in the fixed array x.
+ const int jet0 = 0;
+ const int jet1 = N0;
+ const int jet2 = N0 + N1;
+ const int jet3 = N0 + N1 + N2;
+ const int jet4 = N0 + N1 + N2 + N3;
+ const int jet5 = N0 + N1 + N2 + N3 + N4;
+ const int jet6 = N0 + N1 + N2 + N3 + N4 + N5;
+ const int jet7 = N0 + N1 + N2 + N3 + N4 + N5 + N6;
+ const int jet8 = N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7;
+ const int jet9 = N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8;
- const JetT *unpacked_parameters[6] = {
+ const JetT *unpacked_parameters[10] = {
x.get() + jet0,
x.get() + jet1,
x.get() + jet2,
x.get() + jet3,
x.get() + jet4,
x.get() + jet5,
+ x.get() + jet6,
+ x.get() + jet7,
+ x.get() + jet8,
+ x.get() + jet9,
};
- JetT *output = x.get() + jet6;
+
+ JetT* output = x.get() + N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8 + N9;
#define CERES_MAKE_1ST_ORDER_PERTURBATION(i) \
if (N ## i) { \
@@ -333,10 +271,14 @@ struct AutoDiff {
CERES_MAKE_1ST_ORDER_PERTURBATION(3);
CERES_MAKE_1ST_ORDER_PERTURBATION(4);
CERES_MAKE_1ST_ORDER_PERTURBATION(5);
+ CERES_MAKE_1ST_ORDER_PERTURBATION(6);
+ CERES_MAKE_1ST_ORDER_PERTURBATION(7);
+ CERES_MAKE_1ST_ORDER_PERTURBATION(8);
+ CERES_MAKE_1ST_ORDER_PERTURBATION(9);
#undef CERES_MAKE_1ST_ORDER_PERTURBATION
if (!VariadicEvaluate<Functor, JetT,
- N0, N1, N2, N3, N4, N5>::Call(
+ N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>::Call(
functor, unpacked_parameters, output)) {
return false;
}
@@ -359,6 +301,10 @@ struct AutoDiff {
CERES_TAKE_1ST_ORDER_PERTURBATION(3);
CERES_TAKE_1ST_ORDER_PERTURBATION(4);
CERES_TAKE_1ST_ORDER_PERTURBATION(5);
+ CERES_TAKE_1ST_ORDER_PERTURBATION(6);
+ CERES_TAKE_1ST_ORDER_PERTURBATION(7);
+ CERES_TAKE_1ST_ORDER_PERTURBATION(8);
+ CERES_TAKE_1ST_ORDER_PERTURBATION(9);
#undef CERES_TAKE_1ST_ORDER_PERTURBATION
return true;
}
diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/eigen.h b/extern/libmv/third_party/ceres/include/ceres/internal/eigen.h
index be76f9eff98..85df54b8f99 100644
--- a/extern/libmv/third_party/ceres/include/ceres/internal/eigen.h
+++ b/extern/libmv/third_party/ceres/include/ceres/internal/eigen.h
@@ -35,27 +35,40 @@
namespace ceres {
-using Eigen::Dynamic;
-using Eigen::RowMajor;
-
-typedef Eigen::Matrix<double, Dynamic, 1> Vector;
-typedef Eigen::Matrix<double, Dynamic, Dynamic, RowMajor> Matrix;
+typedef Eigen::Matrix<double, Eigen::Dynamic, 1> Vector;
+typedef Eigen::Matrix<double,
+ Eigen::Dynamic,
+ Eigen::Dynamic,
+ Eigen::RowMajor> Matrix;
typedef Eigen::Map<Vector> VectorRef;
typedef Eigen::Map<Matrix> MatrixRef;
-typedef Eigen::Map<Matrix, Eigen::Aligned> AlignedMatrixRef;
typedef Eigen::Map<const Vector> ConstVectorRef;
-typedef Eigen::Map<const Matrix, Eigen::Aligned> ConstAlignedMatrixRef;
typedef Eigen::Map<const Matrix> ConstMatrixRef;
+// Column major matrices for DenseSparseMatrix/DenseQRSolver
+typedef Eigen::Matrix<double,
+ Eigen::Dynamic,
+ Eigen::Dynamic,
+ Eigen::ColMajor> ColMajorMatrix;
+
+typedef Eigen::Map<ColMajorMatrix, 0,
+ Eigen::Stride<Eigen::Dynamic, 1> > ColMajorMatrixRef;
+
+typedef Eigen::Map<const ColMajorMatrix,
+ 0,
+ Eigen::Stride<Eigen::Dynamic, 1> > ConstColMajorMatrixRef;
+
+
+
// C++ does not support templated typdefs, thus the need for this
// struct so that we can support statically sized Matrix and Maps.
template <int num_rows = Eigen::Dynamic, int num_cols = Eigen::Dynamic>
struct EigenTypes {
- typedef Eigen::Matrix <double, num_rows, num_cols, RowMajor>
+ typedef Eigen::Matrix <double, num_rows, num_cols, Eigen::RowMajor>
Matrix;
typedef Eigen::Map<
- Eigen::Matrix<double, num_rows, num_cols, RowMajor> >
+ Eigen::Matrix<double, num_rows, num_cols, Eigen::RowMajor> >
MatrixRef;
typedef Eigen::Matrix <double, num_rows, 1>
@@ -67,7 +80,7 @@ struct EigenTypes {
typedef Eigen::Map<
- const Eigen::Matrix<double, num_rows, num_cols, RowMajor> >
+ const Eigen::Matrix<double, num_rows, num_cols, Eigen::RowMajor> >
ConstMatrixRef;
typedef Eigen::Map <
diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h b/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h
index ce777d22dc7..fa4a339d757 100644
--- a/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h
+++ b/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h
@@ -168,11 +168,11 @@ inline FixedArray<T, S>::FixedArray(typename FixedArray<T, S>::size_type n)
array_((n <= kInlineElements
? reinterpret_cast<InnerContainer*>(inline_space_)
: new InnerContainer[n])) {
- DCHECK_GE(n, 0);
+ DCHECK_GE(n, size_t(0));
// Construct only the elements actually used.
if (array_ == reinterpret_cast<InnerContainer*>(inline_space_)) {
- for (int i = 0; i != size_; ++i) {
+ for (size_t i = 0; i != size_; ++i) {
inline_space_[i].Init();
}
}
@@ -183,7 +183,7 @@ inline FixedArray<T, S>::~FixedArray() {
if (array_ != reinterpret_cast<InnerContainer*>(inline_space_)) {
delete[] array_;
} else {
- for (int i = 0; i != size_; ++i) {
+ for (size_t i = 0; i != size_; ++i) {
inline_space_[i].Destroy();
}
}
diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/macros.h b/extern/libmv/third_party/ceres/include/ceres/internal/macros.h
index 83ec31193e7..388cf30fe70 100644
--- a/extern/libmv/third_party/ceres/include/ceres/internal/macros.h
+++ b/extern/libmv/third_party/ceres/include/ceres/internal/macros.h
@@ -132,16 +132,16 @@ char (&ArraySizeHelper(const T (&array)[N]))[N];
// - wan 2005-11-16
//
// Starting with Visual C++ 2005, WinNT.h includes ARRAYSIZE. However,
-// the definition comes from the over-broad windows.h header that
+// the definition comes from the over-broad windows.h header that
// introduces a macro, ERROR, that conflicts with the logging framework
// that Ceres uses. Instead, rename ARRAYSIZE to CERES_ARRAYSIZE.
-#define CERES_ARRAYSIZE(a) \
- ((sizeof(a) / sizeof(*(a))) / \
+#define CERES_ARRAYSIZE(a) \
+ ((sizeof(a) / sizeof(*(a))) / \
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
-// Tell the compiler to warn about unused return values for functions declared
-// with this macro. The macro should be used on function declarations
-// following the argument list:
+// Tell the compiler to warn about unused return values for functions
+// declared with this macro. The macro should be used on function
+// declarations following the argument list:
//
// Sprocket* AllocateSprocket() MUST_USE_RESULT;
//
diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h b/extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h
index 174d35ee2bd..7ea723d2a83 100644
--- a/extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h
+++ b/extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h
@@ -110,56 +110,61 @@ class ManualConstructor {
inline Type& operator*() { return *get(); }
inline const Type& operator*() const { return *get(); }
+ // This is needed to get around the strict aliasing warning GCC generates.
+ inline void* space() {
+ return reinterpret_cast<void*>(space_);
+ }
+
// You can pass up to four constructor arguments as arguments of Init().
inline void Init() {
- new(space_) Type;
+ new(space()) Type;
}
template <typename T1>
inline void Init(const T1& p1) {
- new(space_) Type(p1);
+ new(space()) Type(p1);
}
template <typename T1, typename T2>
inline void Init(const T1& p1, const T2& p2) {
- new(space_) Type(p1, p2);
+ new(space()) Type(p1, p2);
}
template <typename T1, typename T2, typename T3>
inline void Init(const T1& p1, const T2& p2, const T3& p3) {
- new(space_) Type(p1, p2, p3);
+ new(space()) Type(p1, p2, p3);
}
template <typename T1, typename T2, typename T3, typename T4>
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4) {
- new(space_) Type(p1, p2, p3, p4);
+ new(space()) Type(p1, p2, p3, p4);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5>
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5) {
- new(space_) Type(p1, p2, p3, p4, p5);
+ new(space()) Type(p1, p2, p3, p4, p5);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6>
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6) {
- new(space_) Type(p1, p2, p3, p4, p5, p6);
+ new(space()) Type(p1, p2, p3, p4, p5, p6);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7>
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6, const T7& p7) {
- new(space_) Type(p1, p2, p3, p4, p5, p6, p7);
+ new(space()) Type(p1, p2, p3, p4, p5, p6, p7);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8>
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6, const T7& p7, const T8& p8) {
- new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8);
+ new(space()) Type(p1, p2, p3, p4, p5, p6, p7, p8);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
@@ -167,7 +172,7 @@ class ManualConstructor {
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6, const T7& p7, const T8& p8,
const T9& p9) {
- new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9);
+ new(space()) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
@@ -175,7 +180,7 @@ class ManualConstructor {
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6, const T7& p7, const T8& p8,
const T9& p9, const T10& p10) {
- new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+ new(space()) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
@@ -184,7 +189,7 @@ class ManualConstructor {
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6, const T7& p7, const T8& p8,
const T9& p9, const T10& p10, const T11& p11) {
- new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
+ new(space()) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
}
inline void Destroy() {
diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/numeric_diff.h b/extern/libmv/third_party/ceres/include/ceres/internal/numeric_diff.h
new file mode 100644
index 00000000000..4058366c4a1
--- /dev/null
+++ b/extern/libmv/third_party/ceres/include/ceres/internal/numeric_diff.h
@@ -0,0 +1,199 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+// mierle@gmail.com (Keir Mierle)
+//
+// Finite differencing routine used by NumericDiffCostFunction.
+
+#ifndef CERES_PUBLIC_INTERNAL_NUMERIC_DIFF_H_
+#define CERES_PUBLIC_INTERNAL_NUMERIC_DIFF_H_
+
+#include <cstring>
+
+#include "Eigen/Dense"
+#include "ceres/cost_function.h"
+#include "ceres/internal/scoped_ptr.h"
+#include "ceres/internal/variadic_evaluate.h"
+#include "ceres/types.h"
+#include "glog/logging.h"
+
+
+namespace ceres {
+namespace internal {
+
+// Helper templates that allow evaluation of a variadic functor or a
+// CostFunction object.
+template <typename CostFunctor,
+ int N0, int N1, int N2, int N3, int N4,
+ int N5, int N6, int N7, int N8, int N9 >
+bool EvaluateImpl(const CostFunctor* functor,
+ double const* const* parameters,
+ double* residuals,
+ const void* /* NOT USED */) {
+ return VariadicEvaluate<CostFunctor,
+ double,
+ N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>::Call(
+ *functor,
+ parameters,
+ residuals);
+}
+
+template <typename CostFunctor,
+ int N0, int N1, int N2, int N3, int N4,
+ int N5, int N6, int N7, int N8, int N9 >
+bool EvaluateImpl(const CostFunctor* functor,
+ double const* const* parameters,
+ double* residuals,
+ const CostFunction* /* NOT USED */) {
+ return functor->Evaluate(parameters, residuals, NULL);
+}
+
+// This is split from the main class because C++ doesn't allow partial template
+// specializations for member functions. The alternative is to repeat the main
+// class for differing numbers of parameters, which is also unfortunate.
+template <typename CostFunctor,
+ NumericDiffMethod kMethod,
+ int kNumResiduals,
+ int N0, int N1, int N2, int N3, int N4,
+ int N5, int N6, int N7, int N8, int N9,
+ int kParameterBlock,
+ int kParameterBlockSize>
+struct NumericDiff {
+ // Mutates parameters but must restore them before return.
+ static bool EvaluateJacobianForParameterBlock(
+ const CostFunctor* functor,
+ double const* residuals_at_eval_point,
+ const double relative_step_size,
+ double **parameters,
+ double *jacobian) {
+ using Eigen::Map;
+ using Eigen::Matrix;
+ using Eigen::RowMajor;
+ using Eigen::ColMajor;
+
+ typedef Matrix<double, kNumResiduals, 1> ResidualVector;
+ typedef Matrix<double, kParameterBlockSize, 1> ParameterVector;
+ typedef Matrix<double, kNumResiduals, kParameterBlockSize,
+ (kParameterBlockSize == 1 &&
+ kNumResiduals > 1) ? ColMajor : RowMajor> JacobianMatrix;
+
+
+ Map<JacobianMatrix> parameter_jacobian(jacobian,
+ kNumResiduals,
+ kParameterBlockSize);
+
+ // Mutate 1 element at a time and then restore.
+ Map<ParameterVector> x_plus_delta(parameters[kParameterBlock],
+ kParameterBlockSize);
+ ParameterVector x(x_plus_delta);
+ ParameterVector step_size = x.array().abs() * relative_step_size;
+
+ // To handle cases where a parameter is exactly zero, instead use
+ // the mean step_size for the other dimensions. If all the
+ // parameters are zero, there's no good answer. Take
+ // relative_step_size as a guess and hope for the best.
+ const double fallback_step_size =
+ (step_size.sum() == 0)
+ ? relative_step_size
+ : step_size.sum() / step_size.rows();
+
+ // For each parameter in the parameter block, use finite differences to
+ // compute the derivative for that parameter.
+ for (int j = 0; j < kParameterBlockSize; ++j) {
+ const double delta =
+ (step_size(j) == 0.0) ? fallback_step_size : step_size(j);
+
+ x_plus_delta(j) = x(j) + delta;
+
+ double residuals[kNumResiduals]; // NOLINT
+
+ if (!EvaluateImpl<CostFunctor, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>(
+ functor, parameters, residuals, functor)) {
+ return false;
+ }
+
+ // Compute this column of the jacobian in 3 steps:
+ // 1. Store residuals for the forward part.
+ // 2. Subtract residuals for the backward (or 0) part.
+ // 3. Divide out the run.
+ parameter_jacobian.col(j) =
+ Map<const ResidualVector>(residuals, kNumResiduals);
+
+ double one_over_delta = 1.0 / delta;
+ if (kMethod == CENTRAL) {
+ // Compute the function on the other side of x(j).
+ x_plus_delta(j) = x(j) - delta;
+
+ if (!EvaluateImpl<CostFunctor, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>(
+ functor, parameters, residuals, functor)) {
+ return false;
+ }
+
+ parameter_jacobian.col(j) -=
+ Map<ResidualVector>(residuals, kNumResiduals, 1);
+ one_over_delta /= 2;
+ } else {
+ // Forward difference only; reuse existing residuals evaluation.
+ parameter_jacobian.col(j) -=
+ Map<const ResidualVector>(residuals_at_eval_point, kNumResiduals);
+ }
+ x_plus_delta(j) = x(j); // Restore x_plus_delta.
+
+ // Divide out the run to get slope.
+ parameter_jacobian.col(j) *= one_over_delta;
+ }
+ return true;
+ }
+};
+
+template <typename CostFunctor,
+ NumericDiffMethod kMethod,
+ int kNumResiduals,
+ int N0, int N1, int N2, int N3, int N4,
+ int N5, int N6, int N7, int N8, int N9,
+ int kParameterBlock>
+struct NumericDiff<CostFunctor, kMethod, kNumResiduals,
+ N0, N1, N2, N3, N4, N5, N6, N7, N8, N9,
+ kParameterBlock, 0> {
+ // Mutates parameters but must restore them before return.
+ static bool EvaluateJacobianForParameterBlock(
+ const CostFunctor* functor,
+ double const* residuals_at_eval_point,
+ const double relative_step_size,
+ double **parameters,
+ double *jacobian) {
+ LOG(FATAL) << "Control should never reach here.";
+ return true;
+ }
+};
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_PUBLIC_INTERNAL_NUMERIC_DIFF_H_
diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/scoped_ptr.h b/extern/libmv/third_party/ceres/include/ceres/internal/scoped_ptr.h
index 44f198b339d..5dfb551243c 100644
--- a/extern/libmv/third_party/ceres/include/ceres/internal/scoped_ptr.h
+++ b/extern/libmv/third_party/ceres/include/ceres/internal/scoped_ptr.h
@@ -38,6 +38,7 @@
#include <assert.h>
#include <stdlib.h>
#include <cstddef>
+#include <algorithm>
namespace ceres {
namespace internal {
@@ -49,18 +50,17 @@ template <class C> class scoped_array;
template <class C>
scoped_ptr<C> make_scoped_ptr(C *);
-// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
-// automatically deletes the pointer it holds (if any). That is, scoped_ptr<T>
-// owns the T object that it points to. Like a T*, a scoped_ptr<T> may hold
-// either NULL or a pointer to a T object. Also like T*, scoped_ptr<T> is
-// thread-compatible, and once you dereference it, you get the threadsafety
-// guarantees of T.
+// A scoped_ptr<T> is like a T*, except that the destructor of
+// scoped_ptr<T> automatically deletes the pointer it holds (if
+// any). That is, scoped_ptr<T> owns the T object that it points
+// to. Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to
+// a T object. Also like T*, scoped_ptr<T> is thread-compatible, and
+// once you dereference it, you get the threadsafety guarantees of T.
//
// The size of a scoped_ptr is small: sizeof(scoped_ptr<C>) == sizeof(C*)
template <class C>
class scoped_ptr {
public:
-
// The element type
typedef C element_type;
@@ -193,7 +193,6 @@ scoped_ptr<C> make_scoped_ptr(C *p) {
template <class C>
class scoped_array {
public:
-
// The element type
typedef C element_type;
diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/variadic_evaluate.h b/extern/libmv/third_party/ceres/include/ceres/internal/variadic_evaluate.h
new file mode 100644
index 00000000000..4b1e4bdc65a
--- /dev/null
+++ b/extern/libmv/third_party/ceres/include/ceres/internal/variadic_evaluate.h
@@ -0,0 +1,182 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+// mierle@gmail.com (Keir Mierle)
+
+#ifndef CERES_PUBLIC_INTERNAL_VARIADIC_EVALUATE_H_
+#define CERES_PUBLIC_INTERNAL_VARIADIC_EVALUATE_H_
+
+#include <stddef.h>
+
+#include <glog/logging.h>
+#include "ceres/jet.h"
+#include "ceres/internal/eigen.h"
+#include "ceres/internal/fixed_array.h"
+
+namespace ceres {
+namespace internal {
+
+// This block of quasi-repeated code calls the user-supplied functor, which may
+// take a variable number of arguments. This is accomplished by specializing the
+// struct based on the size of the trailing parameters; parameters with 0 size
+// are assumed missing.
+template<typename Functor, typename T, int N0, int N1, int N2, int N3, int N4,
+ int N5, int N6, int N7, int N8, int N9>
+struct VariadicEvaluate {
+ static bool Call(const Functor& functor, T const *const *input, T* output) {
+ return functor(input[0],
+ input[1],
+ input[2],
+ input[3],
+ input[4],
+ input[5],
+ input[6],
+ input[7],
+ input[8],
+ input[9],
+ output);
+ }
+};
+
+template<typename Functor, typename T, int N0, int N1, int N2, int N3, int N4,
+ int N5, int N6, int N7, int N8>
+struct VariadicEvaluate<Functor, T, N0, N1, N2, N3, N4, N5, N6, N7, N8, 0> {
+ static bool Call(const Functor& functor, T const *const *input, T* output) {
+ return functor(input[0],
+ input[1],
+ input[2],
+ input[3],
+ input[4],
+ input[5],
+ input[6],
+ input[7],
+ input[8],
+ output);
+ }
+};
+
+template<typename Functor, typename T, int N0, int N1, int N2, int N3, int N4,
+ int N5, int N6, int N7>
+struct VariadicEvaluate<Functor, T, N0, N1, N2, N3, N4, N5, N6, N7, 0, 0> {
+ static bool Call(const Functor& functor, T const *const *input, T* output) {
+ return functor(input[0],
+ input[1],
+ input[2],
+ input[3],
+ input[4],
+ input[5],
+ input[6],
+ input[7],
+ output);
+ }
+};
+
+template<typename Functor, typename T, int N0, int N1, int N2, int N3, int N4,
+ int N5, int N6>
+struct VariadicEvaluate<Functor, T, N0, N1, N2, N3, N4, N5, N6, 0, 0, 0> {
+ static bool Call(const Functor& functor, T const *const *input, T* output) {
+ return functor(input[0],
+ input[1],
+ input[2],
+ input[3],
+ input[4],
+ input[5],
+ input[6],
+ output);
+ }
+};
+
+template<typename Functor, typename T, int N0, int N1, int N2, int N3, int N4,
+ int N5>
+struct VariadicEvaluate<Functor, T, N0, N1, N2, N3, N4, N5, 0, 0, 0, 0> {
+ static bool Call(const Functor& functor, T const *const *input, T* output) {
+ return functor(input[0],
+ input[1],
+ input[2],
+ input[3],
+ input[4],
+ input[5],
+ output);
+ }
+};
+
+template<typename Functor, typename T, int N0, int N1, int N2, int N3, int N4>
+struct VariadicEvaluate<Functor, T, N0, N1, N2, N3, N4, 0, 0, 0, 0, 0> {
+ static bool Call(const Functor& functor, T const *const *input, T* output) {
+ return functor(input[0],
+ input[1],
+ input[2],
+ input[3],
+ input[4],
+ output);
+ }
+};
+
+template<typename Functor, typename T, int N0, int N1, int N2, int N3>
+struct VariadicEvaluate<Functor, T, N0, N1, N2, N3, 0, 0, 0, 0, 0, 0> {
+ static bool Call(const Functor& functor, T const *const *input, T* output) {
+ return functor(input[0],
+ input[1],
+ input[2],
+ input[3],
+ output);
+ }
+};
+
+template<typename Functor, typename T, int N0, int N1, int N2>
+struct VariadicEvaluate<Functor, T, N0, N1, N2, 0, 0, 0, 0, 0, 0, 0> {
+ static bool Call(const Functor& functor, T const *const *input, T* output) {
+ return functor(input[0],
+ input[1],
+ input[2],
+ output);
+ }
+};
+
+template<typename Functor, typename T, int N0, int N1>
+struct VariadicEvaluate<Functor, T, N0, N1, 0, 0, 0, 0, 0, 0, 0, 0> {
+ static bool Call(const Functor& functor, T const *const *input, T* output) {
+ return functor(input[0],
+ input[1],
+ output);
+ }
+};
+
+template<typename Functor, typename T, int N0>
+struct VariadicEvaluate<Functor, T, N0, 0, 0, 0, 0, 0, 0, 0, 0, 0> {
+ static bool Call(const Functor& functor, T const *const *input, T* output) {
+ return functor(input[0],
+ output);
+ }
+};
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_PUBLIC_INTERNAL_VARIADIC_EVALUATE_H_
diff --git a/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h b/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h
index 29157d380f2..0dc4c96b441 100644
--- a/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h
+++ b/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h
@@ -42,6 +42,23 @@ namespace ceres {
// This struct describes the state of the optimizer after each
// iteration of the minimization.
struct IterationSummary {
+ IterationSummary()
+ : iteration(0),
+ step_is_valid(false),
+ step_is_nonmonotonic(false),
+ step_is_successful(false),
+ cost(0.0),
+ cost_change(0.0),
+ gradient_max_norm(0.0),
+ step_norm(0.0),
+ eta(0.0),
+ step_size(0.0),
+ line_search_function_evaluations(0),
+ linear_solver_iterations(0),
+ iteration_time_in_seconds(0.0),
+ step_solver_time_in_seconds(0.0),
+ cumulative_time_in_seconds(0.0) {}
+
// Current iteration number.
int32 iteration;
@@ -51,7 +68,22 @@ struct IterationSummary {
// Note: step_is_valid is false when iteration = 0.
bool step_is_valid;
- // Whether or not the algorithm made progress in this iteration.
+ // Step did not reduce the value of the objective function
+ // sufficiently, but it was accepted because of the relaxed
+ // acceptance criterion used by the non-monotonic trust region
+ // algorithm.
+ //
+ // Note: step_is_nonmonotonic is false when iteration = 0;
+ bool step_is_nonmonotonic;
+
+ // Whether or not the minimizer accepted this step or not. If the
+ // ordinary trust region algorithm is used, this means that the
+ // relative reduction in the objective function value was greater
+ // than Solver::Options::min_relative_decrease. However, if the
+ // non-monotonic trust region algorithm is used
+ // (Solver::Options:use_nonmonotonic_steps = true), then even if the
+ // relative decrease is not sufficient, the algorithm may accept the
+ // step and the step is declared successful.
//
// Note: step_is_successful is false when iteration = 0.
bool step_is_successful;
@@ -60,8 +92,7 @@ struct IterationSummary {
double cost;
// Change in the value of the objective function in this
- // iteration. This can be positive or negative. Negative change
- // means that the step was not successful.
+ // iteration. This can be positive or negative.
double cost_change;
// Infinity norm of the gradient vector.
@@ -87,6 +118,12 @@ struct IterationSummary {
// ignore it.
double eta;
+ // Step sized computed by the line search algorithm.
+ double step_size;
+
+ // Number of function evaluations used by the line search algorithm.
+ int line_search_function_evaluations;
+
// Number of iterations taken by the linear solver to solve for the
// Newton step.
int linear_solver_iterations;
diff --git a/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h
index 8544e44d0bc..555bc3d073f 100644
--- a/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h
+++ b/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h
@@ -27,19 +27,109 @@
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
+// sameeragarwal@google.com (Sameer Agarwal)
//
// Create CostFunctions as needed by the least squares framework with jacobians
// computed via numeric (a.k.a. finite) differentiation. For more details see
// http://en.wikipedia.org/wiki/Numerical_differentiation.
//
-// To get a numerically differentiated cost function, define a subclass of
-// CostFunction such that the Evaluate() function ignores the jacobian
-// parameter. The numeric differentiation wrapper will fill in the jacobian
-// parameter if nececssary by repeatedly calling the Evaluate() function with
-// small changes to the appropriate parameters, and computing the slope. For
-// performance, the numeric differentiation wrapper class is templated on the
-// concrete cost function, even though it could be implemented only in terms of
-// the virtual CostFunction interface.
+// To get an numerically differentiated cost function, you must define
+// a class with a operator() (a functor) that computes the residuals.
+//
+// The function must write the computed value in the last argument (the only
+// non-const one) and return true to indicate success.
+//
+// For example, consider a scalar error e = k - x'y, where both x and y are
+// two-dimensional column vector parameters, the prime sign indicates
+// transposition, and k is a constant. The form of this error, which is the
+// difference between a constant and an expression, is a common pattern in least
+// squares problems. For example, the value x'y might be the model expectation
+// for a series of measurements, where there is an instance of the cost function
+// for each measurement k.
+//
+// The actual cost added to the total problem is e^2, or (k - x'k)^2; however,
+// the squaring is implicitly done by the optimization framework.
+//
+// To write an numerically-differentiable cost function for the above model, first
+// define the object
+//
+// class MyScalarCostFunctor {
+// MyScalarCostFunctor(double k): k_(k) {}
+//
+// bool operator()(const double* const x,
+// const double* const y,
+// double* residuals) const {
+// residuals[0] = k_ - x[0] * y[0] + x[1] * y[1];
+// return true;
+// }
+//
+// private:
+// double k_;
+// };
+//
+// Note that in the declaration of operator() the input parameters x
+// and y come first, and are passed as const pointers to arrays of
+// doubles. If there were three input parameters, then the third input
+// parameter would come after y. The output is always the last
+// parameter, and is also a pointer to an array. In the example above,
+// the residual is a scalar, so only residuals[0] is set.
+//
+// Then given this class definition, the numerically differentiated
+// cost function with central differences used for computing the
+// derivative can be constructed as follows.
+//
+// CostFunction* cost_function
+// = new NumericDiffCostFunction<MyScalarCostFunctor, CENTRAL, 1, 2, 2>(
+// new MyScalarCostFunctor(1.0)); ^ ^ ^
+// | | | |
+// Finite Differencing Scheme -+ | | |
+// Dimension of residual ----------+ | |
+// Dimension of x --------------------+ |
+// Dimension of y -----------------------+
+//
+// In this example, there is usually an instance for each measumerent of k.
+//
+// In the instantiation above, the template parameters following
+// "MyScalarCostFunctor", "1, 2, 2", describe the functor as computing
+// a 1-dimensional output from two arguments, both 2-dimensional.
+//
+// The framework can currently accommodate cost functions of up to 10
+// independent variables, and there is no limit on the dimensionality
+// of each of them.
+//
+// The central difference method is considerably more accurate at the cost of
+// twice as many function evaluations than forward difference. Consider using
+// central differences begin with, and only after that works, trying forward
+// difference to improve performance.
+//
+// TODO(sameeragarwal): Add support for dynamic number of residuals.
+//
+// WARNING #1: A common beginner's error when first using
+// NumericDiffCostFunction is to get the sizing wrong. In particular,
+// there is a tendency to set the template parameters to (dimension of
+// residual, number of parameters) instead of passing a dimension
+// parameter for *every parameter*. In the example above, that would
+// be <MyScalarCostFunctor, 1, 2>, which is missing the last '2'
+// argument. Please be careful when setting the size parameters.
+//
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+//
+// ALTERNATE INTERFACE
+//
+// For a variety of reason, including compatibility with legacy code,
+// NumericDiffCostFunction can also take CostFunction objects as
+// input. The following describes how.
+//
+// To get a numerically differentiated cost function, define a
+// subclass of CostFunction such that the Evaluate() function ignores
+// the jacobian parameter. The numeric differentiation wrapper will
+// fill in the jacobian parameter if nececssary by repeatedly calling
+// the Evaluate() function with small changes to the appropriate
+// parameters, and computing the slope. For performance, the numeric
+// differentiation wrapper class is templated on the concrete cost
+// function, even though it could be implemented only in terms of the
+// virtual CostFunction interface.
//
// The numerically differentiated version of a cost function for a cost function
// can be constructed as follows:
@@ -51,233 +141,153 @@
// where MyCostFunction has 1 residual and 2 parameter blocks with sizes 4 and 8
// respectively. Look at the tests for a more detailed example.
//
-// The central difference method is considerably more accurate at the cost of
-// twice as many function evaluations than forward difference. Consider using
-// central differences begin with, and only after that works, trying forward
-// difference to improve performance.
-//
// TODO(keir): Characterize accuracy; mention pitfalls; provide alternatives.
#ifndef CERES_PUBLIC_NUMERIC_DIFF_COST_FUNCTION_H_
#define CERES_PUBLIC_NUMERIC_DIFF_COST_FUNCTION_H_
-#include <cstring>
#include <glog/logging.h>
#include "Eigen/Dense"
+#include "ceres/cost_function.h"
+#include "ceres/internal/numeric_diff.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/sized_cost_function.h"
#include "ceres/types.h"
namespace ceres {
-enum NumericDiffMethod {
- CENTRAL,
- FORWARD
-};
-
-// This is split from the main class because C++ doesn't allow partial template
-// specializations for member functions. The alternative is to repeat the main
-// class for differing numbers of parameters, which is also unfortunate.
-template <typename CostFunctionNoJacobian,
- int num_residuals,
- int parameter_block_size,
- int parameter_block,
- NumericDiffMethod method>
-struct Differencer {
- // Mutates parameters but must restore them before return.
- static bool EvaluateJacobianForParameterBlock(
- const CostFunctionNoJacobian *function,
- double const* residuals_at_eval_point,
- double **parameters,
- double **jacobians) {
- using Eigen::Map;
- using Eigen::Matrix;
- using Eigen::RowMajor;
- using Eigen::ColMajor;
-
- typedef Matrix<double, num_residuals, 1> ResidualVector;
- typedef Matrix<double, parameter_block_size, 1> ParameterVector;
- typedef Matrix<double, num_residuals, parameter_block_size,
- (parameter_block_size == 1 &&
- num_residuals > 1) ? ColMajor : RowMajor> JacobianMatrix;
-
- Map<JacobianMatrix> parameter_jacobian(jacobians[parameter_block],
- num_residuals,
- parameter_block_size);
-
- // Mutate 1 element at a time and then restore.
- Map<ParameterVector> x_plus_delta(parameters[parameter_block],
- parameter_block_size);
- ParameterVector x(x_plus_delta);
-
- // TODO(keir): Pick a smarter number! In theory a good choice is sqrt(eps) *
- // x, which for doubles means about 1e-8 * x. However, I have found this
- // number too optimistic. This number should be exposed for users to change.
- const double kRelativeStepSize = 1e-6;
-
- ParameterVector step_size = x.array().abs() * kRelativeStepSize;
-
- // To handle cases where a parameter is exactly zero, instead use the mean
- // step_size for the other dimensions.
- double fallback_step_size = step_size.sum() / step_size.rows();
- if (fallback_step_size == 0.0) {
- // If all the parameters are zero, there's no good answer. Take
- // kRelativeStepSize as a guess and hope for the best.
- fallback_step_size = kRelativeStepSize;
- }
-
- // For each parameter in the parameter block, use finite differences to
- // compute the derivative for that parameter.
- for (int j = 0; j < parameter_block_size; ++j) {
- if (step_size(j) == 0.0) {
- // The parameter is exactly zero, so compromise and use the mean
- // step_size from the other parameters. This can break in many cases,
- // but it's hard to pick a good number without problem specific
- // knowledge.
- step_size(j) = fallback_step_size;
- }
- x_plus_delta(j) = x(j) + step_size(j);
-
- double residuals[num_residuals]; // NOLINT
- if (!function->Evaluate(parameters, residuals, NULL)) {
- // Something went wrong; bail.
- return false;
- }
-
- // Compute this column of the jacobian in 3 steps:
- // 1. Store residuals for the forward part.
- // 2. Subtract residuals for the backward (or 0) part.
- // 3. Divide out the run.
- parameter_jacobian.col(j) =
- Map<const ResidualVector>(residuals, num_residuals);
-
- double one_over_h = 1 / step_size(j);
- if (method == CENTRAL) {
- // Compute the function on the other side of x(j).
- x_plus_delta(j) = x(j) - step_size(j);
-
- if (!function->Evaluate(parameters, residuals, NULL)) {
- // Something went wrong; bail.
- return false;
- }
- parameter_jacobian.col(j) -=
- Map<ResidualVector>(residuals, num_residuals, 1);
- one_over_h /= 2;
- } else {
- // Forward difference only; reuse existing residuals evaluation.
- parameter_jacobian.col(j) -=
- Map<const ResidualVector>(residuals_at_eval_point, num_residuals);
- }
- x_plus_delta(j) = x(j); // Restore x_plus_delta.
-
- // Divide out the run to get slope.
- parameter_jacobian.col(j) *= one_over_h;
- }
- return true;
- }
-};
-
-// Prevent invalid instantiations.
-template <typename CostFunctionNoJacobian,
- int num_residuals,
- int parameter_block,
- NumericDiffMethod method>
-struct Differencer<CostFunctionNoJacobian,
- num_residuals,
- 0 /* parameter_block_size */,
- parameter_block,
- method> {
- static bool EvaluateJacobianForParameterBlock(
- const CostFunctionNoJacobian *function,
- double const* residuals_at_eval_point,
- double **parameters,
- double **jacobians) {
- LOG(FATAL) << "Shouldn't get here.";
- return true;
- }
-};
-
-template <typename CostFunctionNoJacobian,
- NumericDiffMethod method = CENTRAL, int M = 0,
- int N0 = 0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0, int N5 = 0>
+template <typename CostFunctor,
+ NumericDiffMethod method = CENTRAL,
+ int kNumResiduals = 0, // Number of residuals, or ceres::DYNAMIC
+ int N0 = 0, // Number of parameters in block 0.
+ int N1 = 0, // Number of parameters in block 1.
+ int N2 = 0, // Number of parameters in block 2.
+ int N3 = 0, // Number of parameters in block 3.
+ int N4 = 0, // Number of parameters in block 4.
+ int N5 = 0, // Number of parameters in block 5.
+ int N6 = 0, // Number of parameters in block 6.
+ int N7 = 0, // Number of parameters in block 7.
+ int N8 = 0, // Number of parameters in block 8.
+ int N9 = 0> // Number of parameters in block 9.
class NumericDiffCostFunction
- : public SizedCostFunction<M, N0, N1, N2, N3, N4, N5> {
+ : public SizedCostFunction<kNumResiduals,
+ N0, N1, N2, N3, N4,
+ N5, N6, N7, N8, N9> {
public:
- NumericDiffCostFunction(CostFunctionNoJacobian* function,
- Ownership ownership)
- : function_(function), ownership_(ownership) {}
+ NumericDiffCostFunction(CostFunctor* functor,
+ const double relative_step_size = 1e-6)
+ :functor_(functor),
+ ownership_(TAKE_OWNERSHIP),
+ relative_step_size_(relative_step_size) {}
- virtual ~NumericDiffCostFunction() {
+ NumericDiffCostFunction(CostFunctor* functor,
+ Ownership ownership,
+ const double relative_step_size = 1e-6)
+ : functor_(functor),
+ ownership_(ownership),
+ relative_step_size_(relative_step_size) {}
+
+ ~NumericDiffCostFunction() {
if (ownership_ != TAKE_OWNERSHIP) {
- function_.release();
+ functor_.release();
}
}
virtual bool Evaluate(double const* const* parameters,
double* residuals,
double** jacobians) const {
+ using internal::FixedArray;
+ using internal::NumericDiff;
+
+ const int kNumParameters = N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8 + N9;
+ const int kNumParameterBlocks =
+ (N0 > 0) + (N1 > 0) + (N2 > 0) + (N3 > 0) + (N4 > 0) +
+ (N5 > 0) + (N6 > 0) + (N7 > 0) + (N8 > 0) + (N9 > 0);
+
// Get the function value (residuals) at the the point to evaluate.
- bool success = function_->Evaluate(parameters, residuals, NULL);
- if (!success) {
- // Something went wrong; ignore the jacobian.
+ if (!internal::EvaluateImpl<CostFunctor,
+ N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>(
+ functor_.get(),
+ parameters,
+ residuals,
+ functor_.get())) {
return false;
}
+
if (!jacobians) {
- // Nothing to do; just forward.
return true;
}
// Create a copy of the parameters which will get mutated.
- const int kParametersSize = N0 + N1 + N2 + N3 + N4 + N5;
- double parameters_copy[kParametersSize];
- double *parameters_references_copy[6];
- parameters_references_copy[0] = &parameters_copy[0];
- parameters_references_copy[1] = &parameters_copy[0] + N0;
- parameters_references_copy[2] = &parameters_copy[0] + N0 + N1;
- parameters_references_copy[3] = &parameters_copy[0] + N0 + N1 + N2;
- parameters_references_copy[4] = &parameters_copy[0] + N0 + N1 + N2 + N3;
- parameters_references_copy[5] =
- &parameters_copy[0] + N0 + N1 + N2 + N3 + N4;
+ FixedArray<double> parameters_copy(kNumParameters);
+ FixedArray<double*> parameters_reference_copy(kNumParameterBlocks);
+
+ parameters_reference_copy[0] = parameters_copy.get();
+ if (N1) parameters_reference_copy[1] = parameters_reference_copy[0] + N0;
+ if (N2) parameters_reference_copy[2] = parameters_reference_copy[1] + N1;
+ if (N3) parameters_reference_copy[3] = parameters_reference_copy[2] + N2;
+ if (N4) parameters_reference_copy[4] = parameters_reference_copy[3] + N3;
+ if (N5) parameters_reference_copy[5] = parameters_reference_copy[4] + N4;
+ if (N6) parameters_reference_copy[6] = parameters_reference_copy[5] + N5;
+ if (N7) parameters_reference_copy[7] = parameters_reference_copy[6] + N6;
+ if (N7) parameters_reference_copy[8] = parameters_reference_copy[7] + N7;
+ if (N8) parameters_reference_copy[9] = parameters_reference_copy[8] + N8;
+
+#define COPY_PARAMETER_BLOCK(block) \
+ if (N ## block) memcpy(parameters_reference_copy[block], \
+ parameters[block], \
+ sizeof(double) * N ## block); // NOLINT
-#define COPY_PARAMETER_BLOCK(block) \
- if (N ## block) memcpy(parameters_references_copy[block], \
- parameters[block], \
- sizeof(double) * N ## block); // NOLINT
COPY_PARAMETER_BLOCK(0);
COPY_PARAMETER_BLOCK(1);
COPY_PARAMETER_BLOCK(2);
COPY_PARAMETER_BLOCK(3);
COPY_PARAMETER_BLOCK(4);
COPY_PARAMETER_BLOCK(5);
+ COPY_PARAMETER_BLOCK(6);
+ COPY_PARAMETER_BLOCK(7);
+ COPY_PARAMETER_BLOCK(8);
+ COPY_PARAMETER_BLOCK(9);
+
#undef COPY_PARAMETER_BLOCK
-#define EVALUATE_JACOBIAN_FOR_BLOCK(block) \
- if (N ## block && jacobians[block]) { \
- if (!Differencer<CostFunctionNoJacobian, /* NOLINT */ \
- M, \
- N ## block, \
- block, \
- method>::EvaluateJacobianForParameterBlock( \
- function_.get(), \
- residuals, \
- parameters_references_copy, \
- jacobians)) { \
- return false; \
- } \
+#define EVALUATE_JACOBIAN_FOR_BLOCK(block) \
+ if (N ## block && jacobians[block] != NULL) { \
+ if (!NumericDiff<CostFunctor, \
+ method, \
+ kNumResiduals, \
+ N0, N1, N2, N3, N4, N5, N6, N7, N8, N9, \
+ block, \
+ N ## block >::EvaluateJacobianForParameterBlock( \
+ functor_.get(), \
+ residuals, \
+ relative_step_size_, \
+ parameters_reference_copy.get(), \
+ jacobians[block])) { \
+ return false; \
+ } \
}
+
EVALUATE_JACOBIAN_FOR_BLOCK(0);
EVALUATE_JACOBIAN_FOR_BLOCK(1);
EVALUATE_JACOBIAN_FOR_BLOCK(2);
EVALUATE_JACOBIAN_FOR_BLOCK(3);
EVALUATE_JACOBIAN_FOR_BLOCK(4);
EVALUATE_JACOBIAN_FOR_BLOCK(5);
+ EVALUATE_JACOBIAN_FOR_BLOCK(6);
+ EVALUATE_JACOBIAN_FOR_BLOCK(7);
+ EVALUATE_JACOBIAN_FOR_BLOCK(8);
+ EVALUATE_JACOBIAN_FOR_BLOCK(9);
+
#undef EVALUATE_JACOBIAN_FOR_BLOCK
+
return true;
}
private:
- internal::scoped_ptr<CostFunctionNoJacobian> function_;
+ internal::scoped_ptr<CostFunctor> functor_;
Ownership ownership_;
+ const double relative_step_size_;
};
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/include/ceres/numeric_diff_functor.h b/extern/libmv/third_party/ceres/include/ceres/numeric_diff_functor.h
new file mode 100644
index 00000000000..039e1a17aa7
--- /dev/null
+++ b/extern/libmv/third_party/ceres/include/ceres/numeric_diff_functor.h
@@ -0,0 +1,346 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+//
+// A wrapper class that takes a variadic functor evaluating a
+// function, numerically differentiates it and makes it available as a
+// templated functor so that it can be easily used as part of Ceres'
+// automatic differentiation framework.
+//
+// For example:
+//
+// For example, let us assume that
+//
+// struct IntrinsicProjection
+// IntrinsicProjection(const double* observations);
+// bool operator()(const double* calibration,
+// const double* point,
+// double* residuals);
+// };
+//
+// is a functor that implements the projection of a point in its local
+// coordinate system onto its image plane and subtracts it from the
+// observed point projection.
+//
+// Now we would like to compose the action of this functor with the
+// action of camera extrinsics, i.e., rotation and translation, which
+// is given by the following templated function
+//
+// template<typename T>
+// void RotateAndTranslatePoint(const T* rotation,
+// const T* translation,
+// const T* point,
+// T* result);
+//
+// To compose the extrinsics and intrinsics, we can construct a
+// CameraProjection functor as follows.
+//
+// struct CameraProjection {
+// typedef NumericDiffFunctor<IntrinsicProjection, CENTRAL, 2, 5, 3>
+// IntrinsicProjectionFunctor;
+//
+// CameraProjection(double* observation) {
+// intrinsic_projection_.reset(
+// new IntrinsicProjectionFunctor(observation)) {
+// }
+//
+// template <typename T>
+// bool operator()(const T* rotation,
+// const T* translation,
+// const T* intrinsics,
+// const T* point,
+// T* residuals) const {
+// T transformed_point[3];
+// RotateAndTranslatePoint(rotation, translation, point, transformed_point);
+// return (*intrinsic_projection_)(intrinsics, transformed_point, residual);
+// }
+//
+// private:
+// scoped_ptr<IntrinsicProjectionFunctor> intrinsic_projection_;
+// };
+//
+// Here, we made the choice of using CENTRAL differences to compute
+// the jacobian of IntrinsicProjection.
+//
+// Now, we are ready to construct an automatically differentiated cost
+// function as
+//
+// CostFunction* cost_function =
+// new AutoDiffCostFunction<CameraProjection, 2, 3, 3, 5>(
+// new CameraProjection(observations));
+//
+// cost_function now seamlessly integrates automatic differentiation
+// of RotateAndTranslatePoint with a numerically differentiated
+// version of IntrinsicProjection.
+
+#ifndef CERES_PUBLIC_NUMERIC_DIFF_FUNCTOR_H_
+#define CERES_PUBLIC_NUMERIC_DIFF_FUNCTOR_H_
+
+#include "ceres/numeric_diff_cost_function.h"
+#include "ceres/types.h"
+#include "ceres/cost_function_to_functor.h"
+
+namespace ceres {
+
+template<typename Functor,
+ NumericDiffMethod kMethod = CENTRAL,
+ int kNumResiduals = 0,
+ int N0 = 0, int N1 = 0 , int N2 = 0, int N3 = 0, int N4 = 0,
+ int N5 = 0, int N6 = 0 , int N7 = 0, int N8 = 0, int N9 = 0>
+class NumericDiffFunctor {
+ public:
+ // relative_step_size controls the step size used by the numeric
+ // differentiation process.
+ explicit NumericDiffFunctor(double relative_step_size = 1e-6)
+ : functor_(
+ new NumericDiffCostFunction<Functor,
+ kMethod,
+ kNumResiduals,
+ N0, N1, N2, N3, N4,
+ N5, N6, N7, N8, N9>(new Functor,
+ relative_step_size)) {
+ }
+
+ NumericDiffFunctor(Functor* functor, double relative_step_size = 1e-6)
+ : functor_(new NumericDiffCostFunction<Functor,
+ kMethod,
+ kNumResiduals,
+ N0, N1, N2, N3, N4,
+ N5, N6, N7, N8, N9>(
+ functor, relative_step_size)) {
+ }
+
+ bool operator()(const double* x0, double* residuals) const {
+ return functor_(x0, residuals);
+ }
+
+ bool operator()(const double* x0,
+ const double* x1,
+ double* residuals) const {
+ return functor_(x0, x1, residuals);
+ }
+
+ bool operator()(const double* x0,
+ const double* x1,
+ const double* x2,
+ double* residuals) const {
+ return functor_(x0, x1, x2, residuals);
+ }
+
+ bool operator()(const double* x0,
+ const double* x1,
+ const double* x2,
+ const double* x3,
+ double* residuals) const {
+ return functor_(x0, x1, x2, x3, residuals);
+ }
+
+ bool operator()(const double* x0,
+ const double* x1,
+ const double* x2,
+ const double* x3,
+ const double* x4,
+ double* residuals) const {
+ return functor_(x0, x1, x2, x3, x4, residuals);
+ }
+
+ bool operator()(const double* x0,
+ const double* x1,
+ const double* x2,
+ const double* x3,
+ const double* x4,
+ const double* x5,
+ double* residuals) const {
+ return functor_(x0, x1, x2, x3, x4, x5, residuals);
+ }
+
+ bool operator()(const double* x0,
+ const double* x1,
+ const double* x2,
+ const double* x3,
+ const double* x4,
+ const double* x5,
+ const double* x6,
+ double* residuals) const {
+ return functor_(x0, x1, x2, x3, x4, x5, x6, residuals);
+ }
+
+ bool operator()(const double* x0,
+ const double* x1,
+ const double* x2,
+ const double* x3,
+ const double* x4,
+ const double* x5,
+ const double* x6,
+ const double* x7,
+ double* residuals) const {
+ return functor_(x0, x1, x2, x3, x4, x5, x6, x7, residuals);
+ }
+
+ bool operator()(const double* x0,
+ const double* x1,
+ const double* x2,
+ const double* x3,
+ const double* x4,
+ const double* x5,
+ const double* x6,
+ const double* x7,
+ const double* x8,
+ double* residuals) const {
+ return functor_(x0, x1, x2, x3, x4, x5, x6, x7, x8, residuals);
+ }
+
+ bool operator()(const double* x0,
+ const double* x1,
+ const double* x2,
+ const double* x3,
+ const double* x4,
+ const double* x5,
+ const double* x6,
+ const double* x7,
+ const double* x8,
+ const double* x9,
+ double* residuals) const {
+ return functor_(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, residuals);
+ }
+
+ template <typename T>
+ bool operator()(const T* x0, T* residuals) const {
+ return functor_(x0, residuals);
+ }
+
+ template <typename T>
+ bool operator()(const T* x0,
+ const T* x1,
+ T* residuals) const {
+ return functor_(x0, x1, residuals);
+ }
+
+ template <typename T>
+ bool operator()(const T* x0,
+ const T* x1,
+ const T* x2,
+ T* residuals) const {
+ return functor_(x0, x1, x2, residuals);
+ }
+
+ template <typename T>
+ bool operator()(const T* x0,
+ const T* x1,
+ const T* x2,
+ const T* x3,
+ T* residuals) const {
+ return functor_(x0, x1, x2, x3, residuals);
+ }
+
+ template <typename T>
+ bool operator()(const T* x0,
+ const T* x1,
+ const T* x2,
+ const T* x3,
+ const T* x4,
+ T* residuals) const {
+ return functor_(x0, x1, x2, x3, x4, residuals);
+ }
+
+ template <typename T>
+ bool operator()(const T* x0,
+ const T* x1,
+ const T* x2,
+ const T* x3,
+ const T* x4,
+ const T* x5,
+ T* residuals) const {
+ return functor_(x0, x1, x2, x3, x4, x5, residuals);
+ }
+
+ template <typename T>
+ bool operator()(const T* x0,
+ const T* x1,
+ const T* x2,
+ const T* x3,
+ const T* x4,
+ const T* x5,
+ const T* x6,
+ T* residuals) const {
+ return functor_(x0, x1, x2, x3, x4, x5, x6, residuals);
+ }
+
+ template <typename T>
+ bool operator()(const T* x0,
+ const T* x1,
+ const T* x2,
+ const T* x3,
+ const T* x4,
+ const T* x5,
+ const T* x6,
+ const T* x7,
+ T* residuals) const {
+ return functor_(x0, x1, x2, x3, x4, x5, x6, x7, residuals);
+ }
+
+ template <typename T>
+ bool operator()(const T* x0,
+ const T* x1,
+ const T* x2,
+ const T* x3,
+ const T* x4,
+ const T* x5,
+ const T* x6,
+ const T* x7,
+ const T* x8,
+ T* residuals) const {
+ return functor_(x0, x1, x2, x3, x4, x5, x6, x7, x8, residuals);
+ }
+
+ template <typename T>
+ bool operator()(const T* x0,
+ const T* x1,
+ const T* x2,
+ const T* x3,
+ const T* x4,
+ const T* x5,
+ const T* x6,
+ const T* x7,
+ const T* x8,
+ const T* x9,
+ T* residuals) const {
+ return functor_(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, residuals);
+ }
+
+
+ private:
+ CostFunctionToFunctor<kNumResiduals,
+ N0, N1, N2, N3, N4,
+ N5, N6, N7, N8, N9> functor_;
+};
+
+} // namespace ceres
+
+#endif // CERES_PUBLIC_NUMERIC_DIFF_FUNCTOR_H_
diff --git a/extern/libmv/third_party/ceres/include/ceres/ordered_groups.h b/extern/libmv/third_party/ceres/include/ceres/ordered_groups.h
new file mode 100644
index 00000000000..e373d35b9d7
--- /dev/null
+++ b/extern/libmv/third_party/ceres/include/ceres/ordered_groups.h
@@ -0,0 +1,176 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#ifndef CERES_PUBLIC_ORDERED_GROUPS_H_
+#define CERES_PUBLIC_ORDERED_GROUPS_H_
+
+#include <map>
+#include <set>
+#include "ceres/internal/port.h"
+
+namespace ceres {
+
+// A class for storing and manipulating an ordered collection of
+// groups/sets with the following semantics:
+//
+// Group ids are non-negative integer values. Elements are any type
+// that can serve as a key in a map or an element of a set.
+//
+// An element can only belong to one group at a time. A group may
+// contain an arbitrary number of elements.
+//
+// Groups are ordered by their group id.
+template <typename T>
+class OrderedGroups {
+ public:
+ // Add an element to a group. If a group with this id does not
+ // exist, one is created. This method can be called any number of
+ // times for the same element. Group ids should be non-negative
+ // numbers.
+ //
+ // Return value indicates if adding the element was a success.
+ bool AddElementToGroup(const T element, const int group) {
+ if (group < 0) {
+ return false;
+ }
+
+ typename map<T, int>::const_iterator it = element_to_group_.find(element);
+ if (it != element_to_group_.end()) {
+ if (it->second == group) {
+ // Element is already in the right group, nothing to do.
+ return true;
+ }
+
+ group_to_elements_[it->second].erase(element);
+ if (group_to_elements_[it->second].size() == 0) {
+ group_to_elements_.erase(it->second);
+ }
+ }
+
+ element_to_group_[element] = group;
+ group_to_elements_[group].insert(element);
+ return true;
+ }
+
+ void Clear() {
+ group_to_elements_.clear();
+ element_to_group_.clear();
+ }
+
+ // Remove the element, no matter what group it is in. If the element
+ // is not a member of any group, calling this method will result in
+ // a crash.
+ //
+ // Return value indicates if the element was actually removed.
+ bool Remove(const T element) {
+ const int current_group = GroupId(element);
+ if (current_group < 0) {
+ return false;
+ }
+
+ group_to_elements_[current_group].erase(element);
+
+ if (group_to_elements_[current_group].size() == 0) {
+ // If the group is empty, then get rid of it.
+ group_to_elements_.erase(current_group);
+ }
+
+ element_to_group_.erase(element);
+ return true;
+ }
+
+ // Reverse the order of the groups in place.
+ void Reverse() {
+ typename map<int, set<T> >::reverse_iterator it =
+ group_to_elements_.rbegin();
+ map<int, set<T> > new_group_to_elements;
+ new_group_to_elements[it->first] = it->second;
+
+ int new_group_id = it->first + 1;
+ for (++it; it != group_to_elements_.rend(); ++it) {
+ for (typename set<T>::const_iterator element_it = it->second.begin();
+ element_it != it->second.end();
+ ++element_it) {
+ element_to_group_[*element_it] = new_group_id;
+ }
+ new_group_to_elements[new_group_id] = it->second;
+ new_group_id++;
+ }
+
+ group_to_elements_.swap(new_group_to_elements);
+ }
+
+ // Return the group id for the element. If the element is not a
+ // member of any group, return -1.
+ int GroupId(const T element) const {
+ typename map<T, int>::const_iterator it = element_to_group_.find(element);
+ if (it == element_to_group_.end()) {
+ return -1;
+ }
+ return it->second;
+ }
+
+ bool IsMember(const T element) const {
+ typename map<T, int>::const_iterator it = element_to_group_.find(element);
+ return (it != element_to_group_.end());
+ }
+
+ // This function always succeeds, i.e., implicitly there exists a
+ // group for every integer.
+ int GroupSize(const int group) const {
+ typename map<int, set<T> >::const_iterator it =
+ group_to_elements_.find(group);
+ return (it == group_to_elements_.end()) ? 0 : it->second.size();
+ }
+
+ int NumElements() const {
+ return element_to_group_.size();
+ }
+
+ // Number of groups with one or more elements.
+ int NumGroups() const {
+ return group_to_elements_.size();
+ }
+
+ const map<int, set<T> >& group_to_elements() const {
+ return group_to_elements_;
+ }
+
+ private:
+ map<int, set<T> > group_to_elements_;
+ map<T, int> element_to_group_;
+};
+
+// Typedef for the most commonly used version of OrderedGroups.
+typedef OrderedGroups<double*> ParameterBlockOrdering;
+
+} // namespace ceres
+
+#endif // CERES_PUBLIC_ORDERED_GROUP_H_
diff --git a/extern/libmv/third_party/ceres/include/ceres/problem.h b/extern/libmv/third_party/ceres/include/ceres/problem.h
index 2b08c6723e8..0a449cb99f1 100644
--- a/extern/libmv/third_party/ceres/include/ceres/problem.h
+++ b/extern/libmv/third_party/ceres/include/ceres/problem.h
@@ -39,11 +39,12 @@
#include <set>
#include <vector>
-#include <glog/logging.h>
#include "ceres/internal/macros.h"
#include "ceres/internal/port.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/types.h"
+#include "glog/logging.h"
+
namespace ceres {
@@ -51,6 +52,7 @@ class CostFunction;
class LossFunction;
class LocalParameterization;
class Solver;
+struct CRSMatrix;
namespace internal {
class Preprocessor;
@@ -59,10 +61,9 @@ class ParameterBlock;
class ResidualBlock;
} // namespace internal
-// A ResidualBlockId is a handle clients can use to delete residual
-// blocks after creating them. They are opaque for any purposes other
-// than that.
-typedef const internal::ResidualBlock* ResidualBlockId;
+// A ResidualBlockId is an opaque handle clients can use to remove residual
+// blocks from a Problem after adding them.
+typedef internal::ResidualBlock* ResidualBlockId;
// A class to represent non-linear least squares problems. Such
// problems have a cost function that is a sum of error terms (known
@@ -122,7 +123,9 @@ class Problem {
Options()
: cost_function_ownership(TAKE_OWNERSHIP),
loss_function_ownership(TAKE_OWNERSHIP),
- local_parameterization_ownership(TAKE_OWNERSHIP) {}
+ local_parameterization_ownership(TAKE_OWNERSHIP),
+ enable_fast_parameter_block_removal(false),
+ disable_all_safety_checks(false) {}
// These flags control whether the Problem object owns the cost
// functions, loss functions, and parameterizations passed into
@@ -134,6 +137,29 @@ class Problem {
Ownership cost_function_ownership;
Ownership loss_function_ownership;
Ownership local_parameterization_ownership;
+
+ // If true, trades memory for a faster RemoveParameterBlock() operation.
+ //
+ // RemoveParameterBlock() takes time proportional to the size of the entire
+ // Problem. If you only remove parameter blocks from the Problem
+ // occassionaly, this may be acceptable. However, if you are modifying the
+ // Problem frequently, and have memory to spare, then flip this switch to
+ // make RemoveParameterBlock() take time proportional to the number of
+ // residual blocks that depend on it. The increase in memory usage is an
+ // additonal hash set per parameter block containing all the residuals that
+ // depend on the parameter block.
+ bool enable_fast_parameter_block_removal;
+
+ // By default, Ceres performs a variety of safety checks when constructing
+ // the problem. There is a small but measurable performance penalty to
+ // these checks, typically around 5% of construction time. If you are sure
+ // your problem construction is correct, and 5% of the problem construction
+ // time is truly an overhead you want to avoid, then you can set
+ // disable_all_safety_checks to true.
+ //
+ // WARNING: Do not set this to true, unless you are absolutely sure of what
+ // you are doing.
+ bool disable_all_safety_checks;
};
// The default constructor is equivalent to the
@@ -208,6 +234,27 @@ class Problem {
LossFunction* loss_function,
double* x0, double* x1, double* x2,
double* x3, double* x4, double* x5);
+ ResidualBlockId AddResidualBlock(CostFunction* cost_function,
+ LossFunction* loss_function,
+ double* x0, double* x1, double* x2,
+ double* x3, double* x4, double* x5,
+ double* x6);
+ ResidualBlockId AddResidualBlock(CostFunction* cost_function,
+ LossFunction* loss_function,
+ double* x0, double* x1, double* x2,
+ double* x3, double* x4, double* x5,
+ double* x6, double* x7);
+ ResidualBlockId AddResidualBlock(CostFunction* cost_function,
+ LossFunction* loss_function,
+ double* x0, double* x1, double* x2,
+ double* x3, double* x4, double* x5,
+ double* x6, double* x7, double* x8);
+ ResidualBlockId AddResidualBlock(CostFunction* cost_function,
+ LossFunction* loss_function,
+ double* x0, double* x1, double* x2,
+ double* x3, double* x4, double* x5,
+ double* x6, double* x7, double* x8,
+ double* x9);
// Add a parameter block with appropriate size to the problem.
// Repeated calls with the same arguments are ignored. Repeated
@@ -223,6 +270,33 @@ class Problem {
int size,
LocalParameterization* local_parameterization);
+ // Remove a parameter block from the problem. The parameterization of the
+ // parameter block, if it exists, will persist until the deletion of the
+ // problem (similar to cost/loss functions in residual block removal). Any
+ // residual blocks that depend on the parameter are also removed, as
+ // described above in RemoveResidualBlock().
+ //
+ // If Problem::Options::enable_fast_parameter_block_removal is true, then the
+ // removal is fast (almost constant time). Otherwise, removing a parameter
+ // block will incur a scan of the entire Problem object.
+ //
+ // WARNING: Removing a residual or parameter block will destroy the implicit
+ // ordering, rendering the jacobian or residuals returned from the solver
+ // uninterpretable. If you depend on the evaluated jacobian, do not use
+ // remove! This may change in a future release.
+ void RemoveParameterBlock(double* values);
+
+ // Remove a residual block from the problem. Any parameters that the residual
+ // block depends on are not removed. The cost and loss functions for the
+ // residual block will not get deleted immediately; won't happen until the
+ // problem itself is deleted.
+ //
+ // WARNING: Removing a residual or parameter block will destroy the implicit
+ // ordering, rendering the jacobian or residuals returned from the solver
+ // uninterpretable. If you depend on the evaluated jacobian, do not use
+ // remove! This may change in a future release.
+ void RemoveResidualBlock(ResidualBlockId residual_block);
+
// Hold the indicated parameter block constant during optimization.
void SetParameterBlockConstant(double* values);
@@ -254,6 +328,86 @@ class Problem {
// sizes of all of the residual blocks.
int NumResiduals() const;
+ // Options struct to control Problem::Evaluate.
+ struct EvaluateOptions {
+ EvaluateOptions()
+ : apply_loss_function(true),
+ num_threads(1) {
+ }
+
+ // The set of parameter blocks for which evaluation should be
+ // performed. This vector determines the order that parameter
+ // blocks occur in the gradient vector and in the columns of the
+ // jacobian matrix. If parameter_blocks is empty, then it is
+ // assumed to be equal to vector containing ALL the parameter
+ // blocks. Generally speaking the parameter blocks will occur in
+ // the order in which they were added to the problem. But, this
+ // may change if the user removes any parameter blocks from the
+ // problem.
+ //
+ // NOTE: This vector should contain the same pointers as the ones
+ // used to add parameter blocks to the Problem. These parameter
+ // block should NOT point to new memory locations. Bad things will
+ // happen otherwise.
+ vector<double*> parameter_blocks;
+
+ // The set of residual blocks to evaluate. This vector determines
+ // the order in which the residuals occur, and how the rows of the
+ // jacobian are ordered. If residual_blocks is empty, then it is
+ // assumed to be equal to the vector containing all the residual
+ // blocks. If this vector is empty, then it is assumed to be equal
+ // to a vector containing ALL the residual blocks. Generally
+ // speaking the residual blocks will occur in the order in which
+ // they were added to the problem. But, this may change if the
+ // user removes any residual blocks from the problem.
+ vector<ResidualBlockId> residual_blocks;
+
+ // Even though the residual blocks in the problem may contain loss
+ // functions, setting apply_loss_function to false will turn off
+ // the application of the loss function to the output of the cost
+ // function. This is of use for example if the user wishes to
+ // analyse the solution quality by studying the distribution of
+ // residuals before and after the solve.
+ bool apply_loss_function;
+
+ int num_threads;
+ };
+
+ // Evaluate Problem. Any of the output pointers can be NULL. Which
+ // residual blocks and parameter blocks are used is controlled by
+ // the EvaluateOptions struct above.
+ //
+ // Note 1: The evaluation will use the values stored in the memory
+ // locations pointed to by the parameter block pointers used at the
+ // time of the construction of the problem. i.e.,
+ //
+ // Problem problem;
+ // double x = 1;
+ // problem.AddResidualBlock(new MyCostFunction, NULL, &x);
+ //
+ // double cost = 0.0;
+ // problem.Evaluate(Problem::EvaluateOptions(), &cost, NULL, NULL, NULL);
+ //
+ // The cost is evaluated at x = 1. If you wish to evaluate the
+ // problem at x = 2, then
+ //
+ // x = 2;
+ // problem.Evaluate(Problem::EvaluateOptions(), &cost, NULL, NULL, NULL);
+ //
+ // is the way to do so.
+ //
+ // Note 2: If no local parameterizations are used, then the size of
+ // the gradient vector (and the number of columns in the jacobian)
+ // is the sum of the sizes of all the parameter blocks. If a
+ // parameter block has a local parameterization, then it contributes
+ // "LocalSize" entries to the gradient vector (and the number of
+ // columns in the jacobian).
+ bool Evaluate(const EvaluateOptions& options,
+ double* cost,
+ vector<double>* residuals,
+ vector<double>* gradient,
+ CRSMatrix* jacobian);
+
private:
friend class Solver;
internal::scoped_ptr<internal::ProblemImpl> problem_impl_;
diff --git a/extern/libmv/third_party/ceres/include/ceres/rotation.h b/extern/libmv/third_party/ceres/include/ceres/rotation.h
index 0d8a390d5d1..ea0b76947eb 100644
--- a/extern/libmv/third_party/ceres/include/ceres/rotation.h
+++ b/extern/libmv/third_party/ceres/include/ceres/rotation.h
@@ -51,6 +51,31 @@
namespace ceres {
+// Trivial wrapper to index linear arrays as matrices, given a fixed
+// column and row stride. When an array "T* array" is wrapped by a
+//
+// (const) MatrixAdapter<T, row_stride, col_stride> M"
+//
+// the expression M(i, j) is equivalent to
+//
+// arrary[i * row_stride + j * col_stride]
+//
+// Conversion functions to and from rotation matrices accept
+// MatrixAdapters to permit using row-major and column-major layouts,
+// and rotation matrices embedded in larger matrices (such as a 3x4
+// projection matrix).
+template <typename T, int row_stride, int col_stride>
+struct MatrixAdapter;
+
+// Convenience functions to create a MatrixAdapter that treats the
+// array pointed to by "pointer" as a 3x3 (contiguous) column-major or
+// row-major matrix.
+template <typename T>
+MatrixAdapter<T, 1, 3> ColumnMajorAdapter3x3(T* pointer);
+
+template <typename T>
+MatrixAdapter<T, 3, 1> RowMajorAdapter3x3(T* pointer);
+
// Convert a value in combined axis-angle representation to a quaternion.
// The value angle_axis is a triple whose norm is an angle in radians,
// and whose direction is aligned with the axis of rotation,
@@ -58,7 +83,7 @@ namespace ceres {
// The implementation may be used with auto-differentiation up to the first
// derivative, higher derivatives may have unexpected results near the origin.
template<typename T>
-void AngleAxisToQuaternion(T const* angle_axis, T* quaternion);
+void AngleAxisToQuaternion(const T* angle_axis, T* quaternion);
// Convert a quaternion to the equivalent combined axis-angle representation.
// The value quaternion must be a unit quaternion - it is not normalized first,
@@ -67,15 +92,26 @@ void AngleAxisToQuaternion(T const* angle_axis, T* quaternion);
// The implemention may be used with auto-differentiation up to the first
// derivative, higher derivatives may have unexpected results near the origin.
template<typename T>
-void QuaternionToAngleAxis(T const* quaternion, T* angle_axis);
+void QuaternionToAngleAxis(const T* quaternion, T* angle_axis);
// Conversions between 3x3 rotation matrix (in column major order) and
// axis-angle rotation representations. Templated for use with
// autodifferentiation.
template <typename T>
-void RotationMatrixToAngleAxis(T const * R, T * angle_axis);
+void RotationMatrixToAngleAxis(const T* R, T* angle_axis);
+
+template <typename T, int row_stride, int col_stride>
+void RotationMatrixToAngleAxis(
+ const MatrixAdapter<const T, row_stride, col_stride>& R,
+ T* angle_axis);
+
template <typename T>
-void AngleAxisToRotationMatrix(T const * angle_axis, T * R);
+void AngleAxisToRotationMatrix(const T* angle_axis, T* R);
+
+template <typename T, int row_stride, int col_stride>
+void AngleAxisToRotationMatrix(
+ const T* angle_axis,
+ const MatrixAdapter<T, row_stride, col_stride>& R);
// Conversions between 3x3 rotation matrix (in row major order) and
// Euler angle (in degrees) rotation representations.
@@ -86,6 +122,11 @@ void AngleAxisToRotationMatrix(T const * angle_axis, T * R);
template <typename T>
void EulerAnglesToRotationMatrix(const T* euler, int row_stride, T* R);
+template <typename T, int row_stride, int col_stride>
+void EulerAnglesToRotationMatrix(
+ const T* euler,
+ const MatrixAdapter<T, row_stride, col_stride>& R);
+
// Convert a 4-vector to a 3x3 scaled rotation matrix.
//
// The choice of rotation is such that the quaternion [1 0 0 0] goes to an
@@ -108,11 +149,21 @@ void EulerAnglesToRotationMatrix(const T* euler, int row_stride, T* R);
template <typename T> inline
void QuaternionToScaledRotation(const T q[4], T R[3 * 3]);
+template <typename T, int row_stride, int col_stride> inline
+void QuaternionToScaledRotation(
+ const T q[4],
+ const MatrixAdapter<T, row_stride, col_stride>& R);
+
// Same as above except that the rotation matrix is normalized by the
// Frobenius norm, so that R * R' = I (and det(R) = 1).
template <typename T> inline
void QuaternionToRotation(const T q[4], T R[3 * 3]);
+template <typename T, int row_stride, int col_stride> inline
+void QuaternionToRotation(
+ const T q[4],
+ const MatrixAdapter<T, row_stride, col_stride>& R);
+
// Rotates a point pt by a quaternion q:
//
// result = R(q) * pt
@@ -146,6 +197,28 @@ void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]);
// --- IMPLEMENTATION
+template<typename T, int row_stride, int col_stride>
+struct MatrixAdapter {
+ T* pointer_;
+ explicit MatrixAdapter(T* pointer)
+ : pointer_(pointer)
+ {}
+
+ T& operator()(int r, int c) const {
+ return pointer_[r * row_stride + c * col_stride];
+ }
+};
+
+template <typename T>
+MatrixAdapter<T, 1, 3> ColumnMajorAdapter3x3(T* pointer) {
+ return MatrixAdapter<T, 1, 3>(pointer);
+}
+
+template <typename T>
+MatrixAdapter<T, 3, 1> RowMajorAdapter3x3(T* pointer) {
+ return MatrixAdapter<T, 3, 1>(pointer);
+}
+
template<typename T>
inline void AngleAxisToQuaternion(const T* angle_axis, T* quaternion) {
const T& a0 = angle_axis[0];
@@ -227,18 +300,25 @@ inline void QuaternionToAngleAxis(const T* quaternion, T* angle_axis) {
// occurs and deals with them by taking code paths that are guaranteed
// to not perform division by a small number.
template <typename T>
-inline void RotationMatrixToAngleAxis(const T * R, T * angle_axis) {
+inline void RotationMatrixToAngleAxis(const T* R, T* angle_axis) {
+ RotationMatrixToAngleAxis(ColumnMajorAdapter3x3(R), angle_axis);
+}
+
+template <typename T, int row_stride, int col_stride>
+void RotationMatrixToAngleAxis(
+ const MatrixAdapter<const T, row_stride, col_stride>& R,
+ T* angle_axis) {
// x = k * 2 * sin(theta), where k is the axis of rotation.
- angle_axis[0] = R[5] - R[7];
- angle_axis[1] = R[6] - R[2];
- angle_axis[2] = R[1] - R[3];
+ angle_axis[0] = R(2, 1) - R(1, 2);
+ angle_axis[1] = R(0, 2) - R(2, 0);
+ angle_axis[2] = R(1, 0) - R(0, 1);
static const T kOne = T(1.0);
static const T kTwo = T(2.0);
// Since the right hand side may give numbers just above 1.0 or
// below -1.0 leading to atan misbehaving, we threshold.
- T costheta = std::min(std::max((R[0] + R[4] + R[8] - kOne) / kTwo,
+ T costheta = std::min(std::max((R(0, 0) + R(1, 1) + R(2, 2) - kOne) / kTwo,
T(-1.0)),
kOne);
@@ -296,7 +376,7 @@ inline void RotationMatrixToAngleAxis(const T * R, T * angle_axis) {
// with the sign of sin(theta). If they are the same, then
// angle_axis[i] should be positive, otherwise negative.
for (int i = 0; i < 3; ++i) {
- angle_axis[i] = theta * sqrt((R[i*4] - costheta) * inv_one_minus_costheta);
+ angle_axis[i] = theta * sqrt((R(i, i) - costheta) * inv_one_minus_costheta);
if (((sintheta < 0.0) && (angle_axis[i] > 0.0)) ||
((sintheta > 0.0) && (angle_axis[i] < 0.0))) {
angle_axis[i] = -angle_axis[i];
@@ -305,7 +385,14 @@ inline void RotationMatrixToAngleAxis(const T * R, T * angle_axis) {
}
template <typename T>
-inline void AngleAxisToRotationMatrix(const T * angle_axis, T * R) {
+inline void AngleAxisToRotationMatrix(const T* angle_axis, T* R) {
+ AngleAxisToRotationMatrix(angle_axis, ColumnMajorAdapter3x3(R));
+}
+
+template <typename T, int row_stride, int col_stride>
+void AngleAxisToRotationMatrix(
+ const T* angle_axis,
+ const MatrixAdapter<T, row_stride, col_stride>& R) {
static const T kOne = T(1.0);
const T theta2 = DotProduct(angle_axis, angle_axis);
if (theta2 > 0.0) {
@@ -320,33 +407,41 @@ inline void AngleAxisToRotationMatrix(const T * angle_axis, T * R) {
const T costheta = cos(theta);
const T sintheta = sin(theta);
- R[0] = costheta + wx*wx*(kOne - costheta);
- R[1] = wz*sintheta + wx*wy*(kOne - costheta);
- R[2] = -wy*sintheta + wx*wz*(kOne - costheta);
- R[3] = wx*wy*(kOne - costheta) - wz*sintheta;
- R[4] = costheta + wy*wy*(kOne - costheta);
- R[5] = wx*sintheta + wy*wz*(kOne - costheta);
- R[6] = wy*sintheta + wx*wz*(kOne - costheta);
- R[7] = -wx*sintheta + wy*wz*(kOne - costheta);
- R[8] = costheta + wz*wz*(kOne - costheta);
+ R(0, 0) = costheta + wx*wx*(kOne - costheta);
+ R(1, 0) = wz*sintheta + wx*wy*(kOne - costheta);
+ R(2, 0) = -wy*sintheta + wx*wz*(kOne - costheta);
+ R(0, 1) = wx*wy*(kOne - costheta) - wz*sintheta;
+ R(1, 1) = costheta + wy*wy*(kOne - costheta);
+ R(2, 1) = wx*sintheta + wy*wz*(kOne - costheta);
+ R(0, 2) = wy*sintheta + wx*wz*(kOne - costheta);
+ R(1, 2) = -wx*sintheta + wy*wz*(kOne - costheta);
+ R(2, 2) = costheta + wz*wz*(kOne - costheta);
} else {
// At zero, we switch to using the first order Taylor expansion.
- R[0] = kOne;
- R[1] = -angle_axis[2];
- R[2] = angle_axis[1];
- R[3] = angle_axis[2];
- R[4] = kOne;
- R[5] = -angle_axis[0];
- R[6] = -angle_axis[1];
- R[7] = angle_axis[0];
- R[8] = kOne;
+ R(0, 0) = kOne;
+ R(1, 0) = -angle_axis[2];
+ R(2, 0) = angle_axis[1];
+ R(0, 1) = angle_axis[2];
+ R(1, 1) = kOne;
+ R(2, 1) = -angle_axis[0];
+ R(0, 2) = -angle_axis[1];
+ R(1, 2) = angle_axis[0];
+ R(2, 2) = kOne;
}
}
template <typename T>
inline void EulerAnglesToRotationMatrix(const T* euler,
- const int row_stride,
+ const int row_stride_parameter,
T* R) {
+ CHECK_EQ(row_stride_parameter, 3);
+ EulerAnglesToRotationMatrix(euler, RowMajorAdapter3x3(R));
+}
+
+template <typename T, int row_stride, int col_stride>
+void EulerAnglesToRotationMatrix(
+ const T* euler,
+ const MatrixAdapter<T, row_stride, col_stride>& R) {
const double kPi = 3.14159265358979323846;
const T degrees_to_radians(kPi / 180.0);
@@ -361,26 +456,28 @@ inline void EulerAnglesToRotationMatrix(const T* euler,
const T c3 = cos(pitch);
const T s3 = sin(pitch);
- // Rows of the rotation matrix.
- T* R1 = R;
- T* R2 = R1 + row_stride;
- T* R3 = R2 + row_stride;
-
- R1[0] = c1*c2;
- R1[1] = -s1*c3 + c1*s2*s3;
- R1[2] = s1*s3 + c1*s2*c3;
+ R(0, 0) = c1*c2;
+ R(0, 1) = -s1*c3 + c1*s2*s3;
+ R(0, 2) = s1*s3 + c1*s2*c3;
- R2[0] = s1*c2;
- R2[1] = c1*c3 + s1*s2*s3;
- R2[2] = -c1*s3 + s1*s2*c3;
+ R(1, 0) = s1*c2;
+ R(1, 1) = c1*c3 + s1*s2*s3;
+ R(1, 2) = -c1*s3 + s1*s2*c3;
- R3[0] = -s2;
- R3[1] = c2*s3;
- R3[2] = c2*c3;
+ R(2, 0) = -s2;
+ R(2, 1) = c2*s3;
+ R(2, 2) = c2*c3;
}
template <typename T> inline
void QuaternionToScaledRotation(const T q[4], T R[3 * 3]) {
+ QuaternionToScaledRotation(q, RowMajorAdapter3x3(R));
+}
+
+template <typename T, int row_stride, int col_stride> inline
+void QuaternionToScaledRotation(
+ const T q[4],
+ const MatrixAdapter<T, row_stride, col_stride>& R) {
// Make convenient names for elements of q.
T a = q[0];
T b = q[1];
@@ -399,21 +496,29 @@ void QuaternionToScaledRotation(const T q[4], T R[3 * 3]) {
T cd = c * d;
T dd = d * d;
- R[0] = aa + bb - cc - dd; R[1] = T(2) * (bc - ad); R[2] = T(2) * (ac + bd); // NOLINT
- R[3] = T(2) * (ad + bc); R[4] = aa - bb + cc - dd; R[5] = T(2) * (cd - ab); // NOLINT
- R[6] = T(2) * (bd - ac); R[7] = T(2) * (ab + cd); R[8] = aa - bb - cc + dd; // NOLINT
+ R(0, 0) = aa + bb - cc - dd; R(0, 1) = T(2) * (bc - ad); R(0, 2) = T(2) * (ac + bd); // NOLINT
+ R(1, 0) = T(2) * (ad + bc); R(1, 1) = aa - bb + cc - dd; R(1, 2) = T(2) * (cd - ab); // NOLINT
+ R(2, 0) = T(2) * (bd - ac); R(2, 1) = T(2) * (ab + cd); R(2, 2) = aa - bb - cc + dd; // NOLINT
}
template <typename T> inline
void QuaternionToRotation(const T q[4], T R[3 * 3]) {
+ QuaternionToRotation(q, RowMajorAdapter3x3(R));
+}
+
+template <typename T, int row_stride, int col_stride> inline
+void QuaternionToRotation(const T q[4],
+ const MatrixAdapter<T, row_stride, col_stride>& R) {
QuaternionToScaledRotation(q, R);
T normalizer = q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3];
CHECK_NE(normalizer, T(0));
normalizer = T(1) / normalizer;
- for (int i = 0; i < 9; ++i) {
- R[i] *= normalizer;
+ for (int i = 0; i < 3; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ R(i, j) *= normalizer;
+ }
}
}
@@ -433,7 +538,6 @@ void UnitQuaternionRotatePoint(const T q[4], const T pt[3], T result[3]) {
result[2] = T(2) * ((t7 - t3) * pt[0] + (t2 + t9) * pt[1] + (t5 + t8) * pt[2]) + pt[2]; // NOLINT
}
-
template <typename T> inline
void QuaternionRotatePoint(const T q[4], const T pt[3], T result[3]) {
// 'scale' is 1 / norm(q).
diff --git a/extern/libmv/third_party/ceres/include/ceres/sized_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/sized_cost_function.h
index 2894a9fba5c..6bfc1af31a2 100644
--- a/extern/libmv/third_party/ceres/include/ceres/sized_cost_function.h
+++ b/extern/libmv/third_party/ceres/include/ceres/sized_cost_function.h
@@ -45,25 +45,29 @@
namespace ceres {
template<int kNumResiduals,
- int N0 = 0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0, int N5 = 0>
+ int N0 = 0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0,
+ int N5 = 0, int N6 = 0, int N7 = 0, int N8 = 0, int N9 = 0>
class SizedCostFunction : public CostFunction {
public:
SizedCostFunction() {
- // Sanity checking.
CHECK(kNumResiduals > 0 || kNumResiduals == DYNAMIC)
<< "Cost functions must have at least one residual block.";
- CHECK_GT(N0, 0)
- << "Cost functions must have at least one parameter block.";
- CHECK((!N1 && !N2 && !N3 && !N4 && !N5) ||
- ((N1 > 0) && !N2 && !N3 && !N4 && !N5) ||
- ((N1 > 0) && (N2 > 0) && !N3 && !N4 && !N5) ||
- ((N1 > 0) && (N2 > 0) && (N3 > 0) && !N4 && !N5) ||
- ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && !N5) ||
- ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0)))
+ // This block breaks the 80 column rule to keep it somewhat readable.
+ CHECK((!N1 && !N2 && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && !N2 && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && !N5 && !N6 && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && !N6 && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && !N7 && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && !N8 && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && (N8 > 0) && !N9) ||
+ ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && (N8 > 0) && (N9 > 0)))
<< "Zero block cannot precede a non-zero block. Block sizes are "
<< "(ignore trailing 0s): " << N0 << ", " << N1 << ", " << N2 << ", "
- << N3 << ", " << N4 << ", " << N5;
+ << N3 << ", " << N4 << ", " << N5 << ", " << N6 << ", " << N7 << ", "
+ << N8 << ", " << N9;
set_num_residuals(kNumResiduals);
@@ -75,6 +79,10 @@ class SizedCostFunction : public CostFunction {
ADD_PARAMETER_BLOCK(N3);
ADD_PARAMETER_BLOCK(N4);
ADD_PARAMETER_BLOCK(N5);
+ ADD_PARAMETER_BLOCK(N6);
+ ADD_PARAMETER_BLOCK(N7);
+ ADD_PARAMETER_BLOCK(N8);
+ ADD_PARAMETER_BLOCK(N9);
#undef ADD_PARAMETER_BLOCK
}
diff --git a/extern/libmv/third_party/ceres/include/ceres/solver.h b/extern/libmv/third_party/ceres/include/ceres/solver.h
index 31d5e8d7987..8c2ff32d80b 100644
--- a/extern/libmv/third_party/ceres/include/ceres/solver.h
+++ b/extern/libmv/third_party/ceres/include/ceres/solver.h
@@ -38,6 +38,7 @@
#include "ceres/internal/macros.h"
#include "ceres/internal/port.h"
#include "ceres/iteration_callback.h"
+#include "ceres/ordered_groups.h"
#include "ceres/types.h"
namespace ceres {
@@ -57,6 +58,11 @@ class Solver {
struct Options {
// Default constructor that sets up a generic sparse problem.
Options() {
+ minimizer_type = TRUST_REGION;
+ line_search_direction_type = LBFGS;
+ line_search_type = ARMIJO;
+ nonlinear_conjugate_gradient_type = FLETCHER_REEVES;
+ max_lbfgs_rank = 20;
trust_region_strategy_type = LEVENBERG_MARQUARDT;
dogleg_type = TRADITIONAL_DOGLEG;
use_nonmonotonic_steps = false;
@@ -89,27 +95,21 @@ class Solver {
#endif
num_linear_solver_threads = 1;
- num_eliminate_blocks = 0;
- ordering_type = NATURAL;
#if defined(CERES_NO_SUITESPARSE)
use_block_amd = false;
#else
use_block_amd = true;
#endif
-
+ linear_solver_ordering = NULL;
+ use_inner_iterations = false;
+ inner_iteration_ordering = NULL;
linear_solver_min_num_iterations = 1;
linear_solver_max_num_iterations = 500;
eta = 1e-1;
jacobi_scaling = true;
logging_type = PER_MINIMIZER_ITERATION;
minimizer_progress_to_stdout = false;
- return_initial_residuals = false;
- return_initial_gradient = false;
- return_initial_jacobian = false;
- return_final_residuals = false;
- return_final_gradient = false;
- return_final_jacobian = false;
lsqp_dump_directory = "/tmp";
lsqp_dump_format_type = TEXTFILE;
check_gradients = false;
@@ -118,8 +118,64 @@ class Solver {
update_state_every_iteration = false;
}
+ ~Options();
// Minimizer options ----------------------------------------
+ // Ceres supports the two major families of optimization strategies -
+ // Trust Region and Line Search.
+ //
+ // 1. The line search approach first finds a descent direction
+ // along which the objective function will be reduced and then
+ // computes a step size that decides how far should move along
+ // that direction. The descent direction can be computed by
+ // various methods, such as gradient descent, Newton's method and
+ // Quasi-Newton method. The step size can be determined either
+ // exactly or inexactly.
+ //
+ // 2. The trust region approach approximates the objective
+ // function using using a model function (often a quadratic) over
+ // a subset of the search space known as the trust region. If the
+ // model function succeeds in minimizing the true objective
+ // function the trust region is expanded; conversely, otherwise it
+ // is contracted and the model optimization problem is solved
+ // again.
+ //
+ // Trust region methods are in some sense dual to line search methods:
+ // trust region methods first choose a step size (the size of the
+ // trust region) and then a step direction while line search methods
+ // first choose a step direction and then a step size.
+ MinimizerType minimizer_type;
+
+ LineSearchDirectionType line_search_direction_type;
+ LineSearchType line_search_type;
+ NonlinearConjugateGradientType nonlinear_conjugate_gradient_type;
+
+ // The LBFGS hessian approximation is a low rank approximation to
+ // the inverse of the Hessian matrix. The rank of the
+ // approximation determines (linearly) the space and time
+ // complexity of using the approximation. Higher the rank, the
+ // better is the quality of the approximation. The increase in
+ // quality is however is bounded for a number of reasons.
+ //
+ // 1. The method only uses secant information and not actual
+ // derivatives.
+ //
+ // 2. The Hessian approximation is constrained to be positive
+ // definite.
+ //
+ // So increasing this rank to a large number will cost time and
+ // space complexity without the corresponding increase in solution
+ // quality. There are no hard and fast rules for choosing the
+ // maximum rank. The best choice usually requires some problem
+ // specific experimentation.
+ //
+ // For more theoretical and implementation details of the LBFGS
+ // method, please see:
+ //
+ // Nocedal, J. (1980). "Updating Quasi-Newton Matrices with
+ // Limited Storage". Mathematics of Computation 35 (151): 773–782.
+ int max_lbfgs_rank;
+
TrustRegionStrategyType trust_region_strategy_type;
// Type of dogleg strategy to use.
@@ -229,29 +285,76 @@ class Solver {
// using this setting.
int num_linear_solver_threads;
- // For Schur reduction based methods, the first 0 to num blocks are
- // eliminated using the Schur reduction. For example, when solving
- // traditional structure from motion problems where the parameters are in
- // two classes (cameras and points) then num_eliminate_blocks would be the
- // number of points.
- //
- // This parameter is used in conjunction with the ordering.
- // Applies to: Preprocessor and linear least squares solver.
- int num_eliminate_blocks;
-
- // Internally Ceres reorders the parameter blocks to help the
- // various linear solvers. This parameter allows the user to
- // influence the re-ordering strategy used. For structure from
- // motion problems use SCHUR, for other problems NATURAL (default)
- // is a good choice. In case you wish to specify your own ordering
- // scheme, for example in conjunction with num_eliminate_blocks,
- // use USER.
- OrderingType ordering_type;
-
- // The ordering of the parameter blocks. The solver pays attention
- // to it if the ordering_type is set to USER and the vector is
- // non-empty.
- vector<double*> ordering;
+ // The order in which variables are eliminated in a linear solver
+ // can have a significant of impact on the efficiency and accuracy
+ // of the method. e.g., when doing sparse Cholesky factorization,
+ // there are matrices for which a good ordering will give a
+ // Cholesky factor with O(n) storage, where as a bad ordering will
+ // result in an completely dense factor.
+ //
+ // Ceres allows the user to provide varying amounts of hints to
+ // the solver about the variable elimination ordering to use. This
+ // can range from no hints, where the solver is free to decide the
+ // best possible ordering based on the user's choices like the
+ // linear solver being used, to an exact order in which the
+ // variables should be eliminated, and a variety of possibilities
+ // in between.
+ //
+ // Instances of the ParameterBlockOrdering class are used to
+ // communicate this information to Ceres.
+ //
+ // Formally an ordering is an ordered partitioning of the
+ // parameter blocks, i.e, each parameter block belongs to exactly
+ // one group, and each group has a unique non-negative integer
+ // associated with it, that determines its order in the set of
+ // groups.
+ //
+ // Given such an ordering, Ceres ensures that the parameter blocks in
+ // the lowest numbered group are eliminated first, and then the
+ // parmeter blocks in the next lowest numbered group and so on. Within
+ // each group, Ceres is free to order the parameter blocks as it
+ // chooses.
+ //
+ // If NULL, then all parameter blocks are assumed to be in the
+ // same group and the solver is free to decide the best
+ // ordering.
+ //
+ // e.g. Consider the linear system
+ //
+ // x + y = 3
+ // 2x + 3y = 7
+ //
+ // There are two ways in which it can be solved. First eliminating x
+ // from the two equations, solving for y and then back substituting
+ // for x, or first eliminating y, solving for x and back substituting
+ // for y. The user can construct three orderings here.
+ //
+ // {0: x}, {1: y} - eliminate x first.
+ // {0: y}, {1: x} - eliminate y first.
+ // {0: x, y} - Solver gets to decide the elimination order.
+ //
+ // Thus, to have Ceres determine the ordering automatically using
+ // heuristics, put all the variables in group 0 and to control the
+ // ordering for every variable, create groups 0..N-1, one per
+ // variable, in the desired order.
+ //
+ // Bundle Adjustment
+ // -----------------
+ //
+ // A particular case of interest is bundle adjustment, where the user
+ // has two options. The default is to not specify an ordering at all,
+ // the solver will see that the user wants to use a Schur type solver
+ // and figure out the right elimination ordering.
+ //
+ // But if the user already knows what parameter blocks are points and
+ // what are cameras, they can save preprocessing time by partitioning
+ // the parameter blocks into two groups, one for the points and one
+ // for the cameras, where the group containing the points has an id
+ // smaller than the group containing cameras.
+ //
+ // Once assigned, Solver::Options owns this pointer and will
+ // deallocate the memory when destroyed.
+ ParameterBlockOrdering* linear_solver_ordering;
// By virtue of the modeling layer in Ceres being block oriented,
// all the matrices used by Ceres are also block oriented. When
@@ -267,6 +370,77 @@ class Solver {
// sparse_linear_algebra_library = SUITE_SPARSE.
bool use_block_amd;
+ // Some non-linear least squares problems have additional
+ // structure in the way the parameter blocks interact that it is
+ // beneficial to modify the way the trust region step is computed.
+ //
+ // e.g., consider the following regression problem
+ //
+ // y = a_1 exp(b_1 x) + a_2 exp(b_3 x^2 + c_1)
+ //
+ // Given a set of pairs{(x_i, y_i)}, the user wishes to estimate
+ // a_1, a_2, b_1, b_2, and c_1.
+ //
+ // Notice here that the expression on the left is linear in a_1
+ // and a_2, and given any value for b_1, b_2 and c_1, it is
+ // possible to use linear regression to estimate the optimal
+ // values of a_1 and a_2. Indeed, its possible to analytically
+ // eliminate the variables a_1 and a_2 from the problem all
+ // together. Problems like these are known as separable least
+ // squares problem and the most famous algorithm for solving them
+ // is the Variable Projection algorithm invented by Golub &
+ // Pereyra.
+ //
+ // Similar structure can be found in the matrix factorization with
+ // missing data problem. There the corresponding algorithm is
+ // known as Wiberg's algorithm.
+ //
+ // Ruhe & Wedin (Algorithms for Separable Nonlinear Least Squares
+ // Problems, SIAM Reviews, 22(3), 1980) present an analyis of
+ // various algorithms for solving separable non-linear least
+ // squares problems and refer to "Variable Projection" as
+ // Algorithm I in their paper.
+ //
+ // Implementing Variable Projection is tedious and expensive, and
+ // they present a simpler algorithm, which they refer to as
+ // Algorithm II, where once the Newton/Trust Region step has been
+ // computed for the whole problem (a_1, a_2, b_1, b_2, c_1) and
+ // additional optimization step is performed to estimate a_1 and
+ // a_2 exactly.
+ //
+ // This idea can be generalized to cases where the residual is not
+ // linear in a_1 and a_2, i.e., Solve for the trust region step
+ // for the full problem, and then use it as the starting point to
+ // further optimize just a_1 and a_2. For the linear case, this
+ // amounts to doing a single linear least squares solve. For
+ // non-linear problems, any method for solving the a_1 and a_2
+ // optimization problems will do. The only constraint on a_1 and
+ // a_2 is that they do not co-occur in any residual block.
+ //
+ // This idea can be further generalized, by not just optimizing
+ // (a_1, a_2), but decomposing the graph corresponding to the
+ // Hessian matrix's sparsity structure in a collection of
+ // non-overlapping independent sets and optimizing each of them.
+ //
+ // Setting "use_inner_iterations" to true enables the use of this
+ // non-linear generalization of Ruhe & Wedin's Algorithm II. This
+ // version of Ceres has a higher iteration complexity, but also
+ // displays better convergence behaviour per iteration. Setting
+ // Solver::Options::num_threads to the maximum number possible is
+ // highly recommended.
+ bool use_inner_iterations;
+
+ // If inner_iterations is true, then the user has two choices.
+ //
+ // 1. Let the solver heuristically decide which parameter blocks
+ // to optimize in each inner iteration. To do this leave
+ // Solver::Options::inner_iteration_ordering untouched.
+ //
+ // 2. Specify a collection of of ordered independent sets. Where
+ // the lower numbered groups are optimized before the higher
+ // number groups. Each group must be an independent set.
+ ParameterBlockOrdering* inner_iteration_ordering;
+
// Minimum number of iterations for which the linear solver should
// run, even if the convergence criterion is satisfied.
int linear_solver_min_num_iterations;
@@ -301,14 +475,6 @@ class Solver {
// is sent to STDOUT.
bool minimizer_progress_to_stdout;
- bool return_initial_residuals;
- bool return_initial_gradient;
- bool return_initial_jacobian;
-
- bool return_final_residuals;
- bool return_final_gradient;
- bool return_final_jacobian;
-
// List of iterations at which the optimizer should dump the
// linear least squares problem to disk. Useful for testing and
// benchmarking. If empty (default), no problems are dumped.
@@ -398,6 +564,8 @@ class Solver {
string FullReport() const;
// Minimizer summary -------------------------------------------------
+ MinimizerType minimizer_type;
+
SolverTerminationType termination_type;
// If the solver did not run, or there was a failure, a
@@ -414,54 +582,6 @@ class Solver {
// blocks that they depend on were fixed.
double fixed_cost;
- // Vectors of residuals before and after the optimization. The
- // entries of these vectors are in the order in which
- // ResidualBlocks were added to the Problem object.
- //
- // Whether the residual vectors are populated with values is
- // controlled by Solver::Options::return_initial_residuals and
- // Solver::Options::return_final_residuals respectively.
- vector<double> initial_residuals;
- vector<double> final_residuals;
-
- // Gradient vectors, before and after the optimization. The rows
- // are in the same order in which the ParameterBlocks were added
- // to the Problem object.
- //
- // NOTE: Since AddResidualBlock adds ParameterBlocks to the
- // Problem automatically if they do not already exist, if you wish
- // to have explicit control over the ordering of the vectors, then
- // use Problem::AddParameterBlock to explicitly add the
- // ParameterBlocks in the order desired.
- //
- // Whether the vectors are populated with values is controlled by
- // Solver::Options::return_initial_gradient and
- // Solver::Options::return_final_gradient respectively.
- vector<double> initial_gradient;
- vector<double> final_gradient;
-
- // Jacobian matrices before and after the optimization. The rows
- // of these matrices are in the same order in which the
- // ResidualBlocks were added to the Problem object. The columns
- // are in the same order in which the ParameterBlocks were added
- // to the Problem object.
- //
- // NOTE: Since AddResidualBlock adds ParameterBlocks to the
- // Problem automatically if they do not already exist, if you wish
- // to have explicit control over the column ordering of the
- // matrix, then use Problem::AddParameterBlock to explicitly add
- // the ParameterBlocks in the order desired.
- //
- // The Jacobian matrices are stored as compressed row sparse
- // matrices. Please see ceres/crs_matrix.h for more details of the
- // format.
- //
- // Whether the Jacboan matrices are populated with values is
- // controlled by Solver::Options::return_initial_jacobian and
- // Solver::Options::return_final_jacobian respectively.
- CRSMatrix initial_jacobian;
- CRSMatrix final_jacobian;
-
vector<IterationSummary> iterations;
int num_successful_steps;
@@ -484,14 +604,20 @@ class Solver {
// Some total of all time spent inside Ceres when Solve is called.
double total_time_in_seconds;
+ double linear_solver_time_in_seconds;
+ double residual_evaluation_time_in_seconds;
+ double jacobian_evaluation_time_in_seconds;
+
// Preprocessor summary.
int num_parameter_blocks;
int num_parameters;
+ int num_effective_parameters;
int num_residual_blocks;
int num_residuals;
int num_parameter_blocks_reduced;
int num_parameters_reduced;
+ int num_effective_parameters_reduced;
int num_residual_blocks_reduced;
int num_residuals_reduced;
@@ -507,12 +633,23 @@ class Solver {
LinearSolverType linear_solver_type_given;
LinearSolverType linear_solver_type_used;
+ vector<int> linear_solver_ordering_given;
+ vector<int> linear_solver_ordering_used;
+
PreconditionerType preconditioner_type;
- OrderingType ordering_type;
TrustRegionStrategyType trust_region_strategy_type;
DoglegType dogleg_type;
+ bool inner_iterations;
+
SparseLinearAlgebraLibraryType sparse_linear_algebra_library;
+
+ LineSearchDirectionType line_search_direction_type;
+ LineSearchType line_search_type;
+ int max_lbfgs_rank;
+
+ vector<int> inner_iteration_ordering_given;
+ vector<int> inner_iteration_ordering_used;
};
// Once a least squares problem has been built, this function takes
diff --git a/extern/libmv/third_party/ceres/include/ceres/types.h b/extern/libmv/third_party/ceres/include/ceres/types.h
index 3980885b53c..5512340f7b3 100644
--- a/extern/libmv/third_party/ceres/include/ceres/types.h
+++ b/extern/libmv/third_party/ceres/include/ceres/types.h
@@ -37,6 +37,8 @@
#ifndef CERES_PUBLIC_TYPES_H_
#define CERES_PUBLIC_TYPES_H_
+#include "ceres/internal/port.h"
+
namespace ceres {
// Basic integer types. These typedefs are in the Ceres namespace to avoid
@@ -99,8 +101,7 @@ enum PreconditionerType {
JACOBI,
// Block diagonal of the Schur complement. This preconditioner may
- // only be used with the ITERATIVE_SCHUR solver. Requires
- // SuiteSparse/CHOLMOD.
+ // only be used with the ITERATIVE_SCHUR solver.
SCHUR_JACOBI,
// Visibility clustering based preconditioners.
@@ -143,18 +144,6 @@ enum LinearSolverTerminationType {
FAILURE
};
-enum OrderingType {
- // The order in which the parameter blocks were defined.
- NATURAL,
-
- // Use the ordering specificed in the vector ordering.
- USER,
-
- // Automatically figure out the best ordering to use the schur
- // complement based solver.
- SCHUR
-};
-
// Logging options
// The options get progressively noisier.
enum LoggingType {
@@ -162,6 +151,55 @@ enum LoggingType {
PER_MINIMIZER_ITERATION
};
+enum MinimizerType {
+ LINE_SEARCH,
+ TRUST_REGION
+};
+
+enum LineSearchDirectionType {
+ // Negative of the gradient.
+ STEEPEST_DESCENT,
+
+ // A generalization of the Conjugate Gradient method to non-linear
+ // functions. The generalization can be performed in a number of
+ // different ways, resulting in a variety of search directions. The
+ // precise choice of the non-linear conjugate gradient algorithm
+ // used is determined by NonlinerConjuateGradientType.
+ NONLINEAR_CONJUGATE_GRADIENT,
+
+ // A limited memory approximation to the inverse Hessian is
+ // maintained and used to compute a quasi-Newton step.
+ //
+ // For more details see
+ //
+ // Nocedal, J. (1980). "Updating Quasi-Newton Matrices with Limited
+ // Storage". Mathematics of Computation 35 (151): 773–782.
+ //
+ // Byrd, R. H.; Nocedal, J.; Schnabel, R. B. (1994).
+ // "Representations of Quasi-Newton Matrices and their use in
+ // Limited Memory Methods". Mathematical Programming 63 (4):
+ // 129–156.
+ LBFGS,
+};
+
+// Nonliner conjugate gradient methods are a generalization of the
+// method of Conjugate Gradients for linear systems. The
+// generalization can be carried out in a number of different ways
+// leading to number of different rules for computing the search
+// direction. Ceres provides a number of different variants. For more
+// details see Numerical Optimization by Nocedal & Wright.
+enum NonlinearConjugateGradientType {
+ FLETCHER_REEVES,
+ POLAK_RIBIRERE,
+ HESTENES_STIEFEL,
+};
+
+enum LineSearchType {
+ // Backtracking line search with polynomial interpolation or
+ // bisection.
+ ARMIJO,
+};
+
// Ceres supports different strategies for computing the trust region
// step.
enum TrustRegionStrategyType {
@@ -296,18 +334,54 @@ enum DimensionType {
DYNAMIC = -1
};
+enum NumericDiffMethod {
+ CENTRAL,
+ FORWARD
+};
+
const char* LinearSolverTypeToString(LinearSolverType type);
+bool StringToLinearSolverType(string value, LinearSolverType* type);
+
const char* PreconditionerTypeToString(PreconditionerType type);
+bool StringToPreconditionerType(string value, PreconditionerType* type);
+
const char* SparseLinearAlgebraLibraryTypeToString(
SparseLinearAlgebraLibraryType type);
+bool StringToSparseLinearAlgebraLibraryType(
+ string value,
+ SparseLinearAlgebraLibraryType* type);
+
+const char* TrustRegionStrategyTypeToString(TrustRegionStrategyType type);
+bool StringToTrustRegionStrategyType(string value,
+ TrustRegionStrategyType* type);
+
+const char* DoglegTypeToString(DoglegType type);
+bool StringToDoglegType(string value, DoglegType* type);
+
+const char* MinimizerTypeToString(MinimizerType type);
+bool StringToMinimizerType(string value, MinimizerType* type);
+
+const char* LineSearchDirectionTypeToString(LineSearchDirectionType type);
+bool StringToLineSearchDirectionType(string value,
+ LineSearchDirectionType* type);
+
+const char* LineSearchTypeToString(LineSearchType type);
+bool StringToLineSearchType(string value, LineSearchType* type);
+
+const char* NonlinearConjugateGradientTypeToString(
+ NonlinearConjugateGradientType type);
+bool StringToNonlinearConjugateGradientType(
+ string value, NonlinearConjugateGradientType* type);
+
const char* LinearSolverTerminationTypeToString(
LinearSolverTerminationType type);
-const char* OrderingTypeToString(OrderingType type);
+
const char* SolverTerminationTypeToString(SolverTerminationType type);
-const char* SparseLinearAlgebraLibraryTypeToString(
- SparseLinearAlgebraLibraryType type);
-const char* TrustRegionStrategyTypeToString( TrustRegionStrategyType type);
+
bool IsSchurType(LinearSolverType type);
+bool IsSparseLinearAlgebraLibraryTypeAvailable(
+ SparseLinearAlgebraLibraryType type);
+
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/array_utils.h b/extern/libmv/third_party/ceres/internal/ceres/array_utils.h
index 99cc8d8ebbf..742f439d886 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/array_utils.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/array_utils.h
@@ -28,7 +28,7 @@
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
-// Utility routines for validating arrays.
+// Utility routines for validating arrays.
//
// These are useful for detecting two common class of errors.
//
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 474c37f7ca4..1d5f9d77ab0 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
@@ -40,10 +40,10 @@
namespace ceres {
namespace internal {
-BlockJacobiPreconditioner::BlockJacobiPreconditioner(const LinearOperator& A)
+BlockJacobiPreconditioner::BlockJacobiPreconditioner(
+ const BlockSparseMatrixBase& A)
: num_rows_(A.num_rows()),
- block_structure_(
- *(down_cast<const BlockSparseMatrix*>(&A)->block_structure())) {
+ 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) {
@@ -64,11 +64,10 @@ BlockJacobiPreconditioner::BlockJacobiPreconditioner(const LinearOperator& A)
}
}
-BlockJacobiPreconditioner::~BlockJacobiPreconditioner() {
-}
+BlockJacobiPreconditioner::~BlockJacobiPreconditioner() {}
-void BlockJacobiPreconditioner::Update(const LinearOperator& matrix, const double* D) {
- const BlockSparseMatrix& A = *(down_cast<const BlockSparseMatrix*>(&matrix));
+bool BlockJacobiPreconditioner::Update(const BlockSparseMatrixBase& A,
+ const double* D) {
const CompressedRowBlockStructure* bs = A.block_structure();
// Compute the diagonal blocks by block inner products.
@@ -107,16 +106,19 @@ void BlockJacobiPreconditioner::Update(const LinearOperator& matrix, const doubl
MatrixRef block(blocks_[c], size, size);
if (D != NULL) {
- block.diagonal() += ConstVectorRef(D + position, size).array().square().matrix();
+ block.diagonal() +=
+ ConstVectorRef(D + position, size).array().square().matrix();
}
block = block.selfadjointView<Eigen::Upper>()
.ldlt()
.solve(Matrix::Identity(size, size));
}
+ return true;
}
-void BlockJacobiPreconditioner::RightMultiply(const double* x, double* y) const {
+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;
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 91cfeddb688..ed5eebc8dc6 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
@@ -32,38 +32,33 @@
#define CERES_INTERNAL_BLOCK_JACOBI_PRECONDITIONER_H_
#include <vector>
-#include "ceres/linear_operator.h"
+#include "ceres/preconditioner.h"
namespace ceres {
namespace internal {
-class CompressedRowBlockStructure;
+class BlockSparseMatrixBase;
+struct CompressedRowBlockStructure;
class LinearOperator;
-class SparseMatrix;
-// A block Jacobi preconditioner. This is intended for use with conjugate
-// gradients, or other iterative symmetric solvers. To use the preconditioner,
-// create one by passing a BlockSparseMatrix as the linear operator "A" to the
-// constructor. This fixes the sparsity pattern to the pattern of the matrix
-// A^TA.
+// A block Jacobi preconditioner. This is intended for use with
+// conjugate gradients, or other iterative symmetric solvers. To use
+// the preconditioner, create one by passing a BlockSparseMatrix "A"
+// to the constructor. This fixes the sparsity pattern to the pattern
+// of the matrix A^TA.
//
// Before each use of the preconditioner in a solve with conjugate gradients,
// update the matrix by running Update(A, D). The values of the matrix A are
// inspected to construct the preconditioner. The vector D is applied as the
// D^TD diagonal term.
-class BlockJacobiPreconditioner : public LinearOperator {
+class BlockJacobiPreconditioner : public Preconditioner {
public:
// A must remain valid while the BlockJacobiPreconditioner is.
- BlockJacobiPreconditioner(const LinearOperator& A);
+ explicit BlockJacobiPreconditioner(const BlockSparseMatrixBase& A);
virtual ~BlockJacobiPreconditioner();
- // Update the preconditioner with the values found in A. The sparsity pattern
- // must match that of the A passed to the constructor. D is a vector that
- // must have the same number of rows as A, and is applied as a diagonal in
- // addition to the block diagonals of A.
- void Update(const LinearOperator& A, const double* D);
-
- // LinearOperator interface.
+ // Preconditioner interface
+ virtual bool Update(const BlockSparseMatrixBase& A, const double* D);
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_; }
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc
index 0f95e8932b8..e5822792fa1 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc
@@ -28,28 +28,33 @@
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
-#include "glog/logging.h"
#include "ceres/block_random_access_dense_matrix.h"
#include <vector>
#include "ceres/internal/eigen.h"
#include "ceres/internal/scoped_ptr.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
BlockRandomAccessDenseMatrix::BlockRandomAccessDenseMatrix(
const vector<int>& blocks) {
- block_layout_.resize(blocks.size(), 0);
+ const int num_blocks = blocks.size();
+ block_layout_.resize(num_blocks, 0);
num_rows_ = 0;
- for (int i = 0; i < blocks.size(); ++i) {
+ for (int i = 0; i < num_blocks; ++i) {
block_layout_[i] = num_rows_;
num_rows_ += blocks[i];
}
values_.reset(new double[num_rows_ * num_rows_]);
- CHECK_NOTNULL(values_.get());
- cell_info_.values = values_.get();
+
+ cell_infos_.reset(new CellInfo[num_blocks * num_blocks]);
+ for (int i = 0; i < num_blocks * num_blocks; ++i) {
+ cell_infos_[i].values = values_.get();
+ }
+
SetZero();
}
@@ -68,7 +73,7 @@ CellInfo* BlockRandomAccessDenseMatrix::GetCell(const int row_block_id,
*col = block_layout_[col_block_id];
*row_stride = num_rows_;
*col_stride = num_rows_;
- return &cell_info_;
+ return &cell_infos_[row_block_id * block_layout_.size() + col_block_id];
}
// Assume that the user does not hold any locks on any cell blocks
diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h
index 9f27a4c30f3..d160fd96013 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h
@@ -84,10 +84,10 @@ class BlockRandomAccessDenseMatrix : public BlockRandomAccessMatrix {
double* mutable_values() { return values_.get(); }
private:
- CellInfo cell_info_;
int num_rows_;
vector<int> block_layout_;
scoped_array<double> values_;
+ scoped_array<CellInfo> cell_infos_;
CERES_DISALLOW_COPY_AND_ASSIGN(BlockRandomAccessDenseMatrix);
};
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 9ed62ce948b..f789436364a 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
@@ -28,7 +28,6 @@
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
-#include "glog/logging.h"
#include "ceres/block_random_access_sparse_matrix.h"
#include <algorithm>
@@ -40,6 +39,7 @@
#include "ceres/mutex.h"
#include "ceres/triplet_sparse_matrix.h"
#include "ceres/types.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc
index d0dc1e670c2..653194571b1 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc
@@ -29,6 +29,8 @@
// Author: David Gallup (dgallup@google.com)
// Sameer Agarwal (sameeragarwal@google.com)
+#ifndef CERES_NO_SUITESPARSE
+
#include "ceres/canonical_views_clustering.h"
#include "ceres/collections_port.h"
@@ -236,3 +238,5 @@ void CanonicalViewsClustering::ComputeClusterMembership(
} // namespace internal
} // namespace ceres
+
+#endif // CERES_NO_SUITESPARSE
diff --git a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h
index 2d1eb403995..48d1ed210c9 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h
@@ -41,18 +41,20 @@
#ifndef CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_
#define CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_
+#ifndef CERES_NO_SUITESPARSE
+
#include <vector>
-#include <glog/logging.h>
#include "ceres/collections_port.h"
#include "ceres/graph.h"
-#include "ceres/map_util.h"
#include "ceres/internal/macros.h"
+#include "ceres/map_util.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
-class CanonicalViewsClusteringOptions;
+struct CanonicalViewsClusteringOptions;
// Compute a partitioning of the vertices of the graph using the
// canonical views clustering algorithm.
@@ -130,4 +132,5 @@ struct CanonicalViewsClusteringOptions {
} // namespace internal
} // namespace ceres
+#endif // CERES_NO_SUITESPARSE
#endif // CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.cc
index ccc8026f9f7..e2e799fe607 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.cc
@@ -30,25 +30,28 @@
#include "ceres/cgnr_solver.h"
-#include "glog/logging.h"
-#include "ceres/linear_solver.h"
+#include "ceres/block_jacobi_preconditioner.h"
#include "ceres/cgnr_linear_operator.h"
#include "ceres/conjugate_gradients_solver.h"
-#include "ceres/block_jacobi_preconditioner.h"
+#include "ceres/linear_solver.h"
+#include "ceres/wall_time.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
CgnrSolver::CgnrSolver(const LinearSolver::Options& options)
: options_(options),
- jacobi_preconditioner_(NULL) {
+ preconditioner_(NULL) {
}
-LinearSolver::Summary CgnrSolver::Solve(
- LinearOperator* A,
+LinearSolver::Summary CgnrSolver::SolveImpl(
+ BlockSparseMatrixBase* A,
const double* b,
const LinearSolver::PerSolveOptions& per_solve_options,
double* x) {
+ EventLogger event_logger("CgnrSolver::Solve");
+
// Form z = Atb.
scoped_array<double> z(new double[A->num_cols()]);
std::fill(z.get(), z.get() + A->num_cols(), 0.0);
@@ -57,11 +60,11 @@ LinearSolver::Summary CgnrSolver::Solve(
// Precondition if necessary.
LinearSolver::PerSolveOptions cg_per_solve_options = per_solve_options;
if (options_.preconditioner_type == JACOBI) {
- if (jacobi_preconditioner_.get() == NULL) {
- jacobi_preconditioner_.reset(new BlockJacobiPreconditioner(*A));
+ if (preconditioner_.get() == NULL) {
+ preconditioner_.reset(new BlockJacobiPreconditioner(*A));
}
- jacobi_preconditioner_->Update(*A, per_solve_options.D);
- cg_per_solve_options.preconditioner = jacobi_preconditioner_.get();
+ preconditioner_->Update(*A, per_solve_options.D);
+ cg_per_solve_options.preconditioner = preconditioner_.get();
} else if (options_.preconditioner_type != IDENTITY) {
LOG(FATAL) << "CGNR only supports IDENTITY and JACOBI preconditioners.";
}
@@ -69,11 +72,14 @@ LinearSolver::Summary CgnrSolver::Solve(
// Solve (AtA + DtD)x = z (= Atb).
std::fill(x, x + A->num_cols(), 0.0);
CgnrLinearOperator lhs(*A, per_solve_options.D);
+ event_logger.AddEvent("Setup");
+
ConjugateGradientsSolver conjugate_gradient_solver(options_);
- return conjugate_gradient_solver.Solve(&lhs,
- z.get(),
- cg_per_solve_options,
- x);
+ LinearSolver::Summary summary =
+ conjugate_gradient_solver.Solve(&lhs, z.get(), cg_per_solve_options, x);
+ event_logger.AddEvent("Solve");
+
+ return summary;
}
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h b/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h
index 877b4c4ceea..d560a9de58d 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h
@@ -37,6 +37,8 @@
namespace ceres {
namespace internal {
+class Preconditioner;
+
class BlockJacobiPreconditioner;
// A conjugate gradients on the normal equations solver. This directly solves
@@ -46,17 +48,18 @@ class BlockJacobiPreconditioner;
//
// as required for solving for x in the least squares sense. Currently only
// block diagonal preconditioning is supported.
-class CgnrSolver : public LinearSolver {
+class CgnrSolver : public BlockSparseMatrixBaseSolver {
public:
explicit CgnrSolver(const LinearSolver::Options& options);
- virtual Summary Solve(LinearOperator* A,
- const double* b,
- const LinearSolver::PerSolveOptions& per_solve_options,
- double* x);
+ virtual Summary SolveImpl(
+ BlockSparseMatrixBase* A,
+ const double* b,
+ const LinearSolver::PerSolveOptions& per_solve_options,
+ double* x);
private:
const LinearSolver::Options options_;
- scoped_ptr<BlockJacobiPreconditioner> jacobi_preconditioner_;
+ scoped_ptr<Preconditioner> preconditioner_;
CERES_DISALLOW_COPY_AND_ASSIGN(CgnrSolver);
};
diff --git a/extern/libmv/third_party/ceres/internal/ceres/collections_port.h b/extern/libmv/third_party/ceres/internal/ceres/collections_port.h
index c2fce9033cd..715c975e00e 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/collections_port.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/collections_port.h
@@ -37,7 +37,7 @@
# include <map>
# include <set>
#else
-# if defined(_MSC_VER) && _MSC_VER <= 1600
+# if defined(_MSC_VER)
# include <unordered_map>
# include <unordered_set>
# else
diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc
index 912c4845441..bbadb772805 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc
@@ -135,7 +135,8 @@ SparseMatrix* CompressedRowJacobianWriter::CreateJacobian() const {
// Populate the row and column block vectors for use by block
// oriented ordering algorithms. This is useful when
// Solver::Options::use_block_amd = true.
- const vector<ParameterBlock*>& parameter_blocks = program_->parameter_blocks();
+ const vector<ParameterBlock*>& parameter_blocks =
+ program_->parameter_blocks();
vector<int>& col_blocks = *(jacobian->mutable_col_blocks());
col_blocks.resize(parameter_blocks.size());
for (int i = 0; i < parameter_blocks.size(); ++i) {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h
index 6a9d82842e5..c9c904bf63c 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h
@@ -32,17 +32,18 @@
#define CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_
#include <vector>
-#include <glog/logging.h>
-#include "ceres/sparse_matrix.h"
-#include "ceres/triplet_sparse_matrix.h"
+
#include "ceres/internal/eigen.h"
#include "ceres/internal/macros.h"
#include "ceres/internal/port.h"
+#include "ceres/sparse_matrix.h"
+#include "ceres/triplet_sparse_matrix.h"
#include "ceres/types.h"
+#include "glog/logging.h"
namespace ceres {
-class CRSMatrix;
+struct CRSMatrix;
namespace internal {
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
new file mode 100644
index 00000000000..c4da987919a
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.cc
@@ -0,0 +1,236 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#include "ceres/coordinate_descent_minimizer.h"
+
+#ifdef CERES_USE_OPENMP
+#include <omp.h>
+#endif
+
+#include <iterator>
+#include <numeric>
+#include <vector>
+#include "ceres/evaluator.h"
+#include "ceres/linear_solver.h"
+#include "ceres/minimizer.h"
+#include "ceres/ordered_groups.h"
+#include "ceres/parameter_block.h"
+#include "ceres/problem_impl.h"
+#include "ceres/program.h"
+#include "ceres/residual_block.h"
+#include "ceres/solver.h"
+#include "ceres/solver_impl.h"
+#include "ceres/trust_region_minimizer.h"
+#include "ceres/trust_region_strategy.h"
+
+namespace ceres {
+namespace internal {
+
+CoordinateDescentMinimizer::~CoordinateDescentMinimizer() {
+}
+
+bool CoordinateDescentMinimizer::Init(
+ const Program& program,
+ const ProblemImpl::ParameterMap& parameter_map,
+ const ParameterBlockOrdering& ordering,
+ string* error) {
+ parameter_blocks_.clear();
+ independent_set_offsets_.clear();
+ independent_set_offsets_.push_back(0);
+
+ // Serialize the OrderedGroups into a vector of parameter block
+ // offsets for parallel access.
+ map<ParameterBlock*, int> parameter_block_index;
+ map<int, set<double*> > group_to_elements = ordering.group_to_elements();
+ for (map<int, set<double*> >::const_iterator it = group_to_elements.begin();
+ it != group_to_elements.end();
+ ++it) {
+ for (set<double*>::const_iterator ptr_it = it->second.begin();
+ ptr_it != it->second.end();
+ ++ptr_it) {
+ parameter_blocks_.push_back(parameter_map.find(*ptr_it)->second);
+ parameter_block_index[parameter_blocks_.back()] =
+ parameter_blocks_.size() - 1;
+ }
+ independent_set_offsets_.push_back(
+ independent_set_offsets_.back() + it->second.size());
+ }
+
+ // The ordering does not have to contain all parameter blocks, so
+ // assign zero offsets/empty independent sets to these parameter
+ // blocks.
+ const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks();
+ for (int i = 0; i < parameter_blocks.size(); ++i) {
+ if (!ordering.IsMember(parameter_blocks[i]->mutable_user_state())) {
+ parameter_blocks_.push_back(parameter_blocks[i]);
+ independent_set_offsets_.push_back(independent_set_offsets_.back());
+ }
+ }
+
+ // Compute the set of residual blocks that depend on each parameter
+ // block.
+ residual_blocks_.resize(parameter_block_index.size());
+ const vector<ResidualBlock*>& residual_blocks = program.residual_blocks();
+ for (int i = 0; i < residual_blocks.size(); ++i) {
+ ResidualBlock* residual_block = residual_blocks[i];
+ const int num_parameter_blocks = residual_block->NumParameterBlocks();
+ for (int j = 0; j < num_parameter_blocks; ++j) {
+ ParameterBlock* parameter_block = residual_block->parameter_blocks()[j];
+ const map<ParameterBlock*, int>::const_iterator it =
+ parameter_block_index.find(parameter_block);
+ if (it != parameter_block_index.end()) {
+ residual_blocks_[it->second].push_back(residual_block);
+ }
+ }
+ }
+
+ evaluator_options_.linear_solver_type = DENSE_QR;
+ evaluator_options_.num_eliminate_blocks = 0;
+ evaluator_options_.num_threads = 1;
+
+ return true;
+}
+
+void CoordinateDescentMinimizer::Minimize(
+ const Minimizer::Options& options,
+ double* parameters,
+ Solver::Summary* summary) {
+ // Set the state and mark all parameter blocks constant.
+ for (int i = 0; i < parameter_blocks_.size(); ++i) {
+ ParameterBlock* parameter_block = parameter_blocks_[i];
+ parameter_block->SetState(parameters + parameter_block->state_offset());
+ parameter_block->SetConstant();
+ }
+
+ scoped_array<LinearSolver*> linear_solvers(
+ new LinearSolver*[options.num_threads]);
+
+ LinearSolver::Options linear_solver_options;
+ linear_solver_options.type = DENSE_QR;
+
+ for (int i = 0; i < options.num_threads; ++i) {
+ linear_solvers[i] = LinearSolver::Create(linear_solver_options);
+ }
+
+ 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
+ // size zero.
+ if (independent_set_offsets_[i] == independent_set_offsets_[i + 1]) {
+ continue;
+ }
+
+ // 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)
+ for (int j = independent_set_offsets_[i];
+ j < independent_set_offsets_[i + 1];
+ ++j) {
+#ifdef CERES_USE_OPENMP
+ int thread_id = omp_get_thread_num();
+#else
+ int thread_id = 0;
+#endif
+
+ ParameterBlock* parameter_block = parameter_blocks_[j];
+ const int old_index = parameter_block->index();
+ const int old_delta_offset = parameter_block->delta_offset();
+ parameter_block->SetVarying();
+ parameter_block->set_index(0);
+ parameter_block->set_delta_offset(0);
+
+ Program inner_program;
+ inner_program.mutable_parameter_blocks()->push_back(parameter_block);
+ *inner_program.mutable_residual_blocks() = residual_blocks_[j];
+
+ // TODO(sameeragarwal): Better error handling. Right now we
+ // assume that this is not going to lead to problems of any
+ // sort. Basically we should be checking for numerical failure
+ // of some sort.
+ //
+ // On the other hand, if the optimization is a failure, that in
+ // some ways is fine, since it won't change the parameters and
+ // we are fine.
+ Solver::Summary inner_summary;
+ Solve(&inner_program,
+ linear_solvers[thread_id],
+ parameters + parameter_block->state_offset(),
+ &inner_summary);
+
+ parameter_block->set_index(old_index);
+ parameter_block->set_delta_offset(old_delta_offset);
+ parameter_block->SetState(parameters + parameter_block->state_offset());
+ parameter_block->SetConstant();
+ }
+ }
+
+ for (int i = 0; i < parameter_blocks_.size(); ++i) {
+ parameter_blocks_[i]->SetVarying();
+ }
+
+ for (int i = 0; i < options.num_threads; ++i) {
+ delete linear_solvers[i];
+ }
+}
+
+// Solve the optimization problem for one parameter block.
+void CoordinateDescentMinimizer::Solve(Program* program,
+ LinearSolver* linear_solver,
+ double* parameter,
+ Solver::Summary* summary) {
+ *summary = Solver::Summary();
+ summary->initial_cost = 0.0;
+ summary->fixed_cost = 0.0;
+ summary->final_cost = 0.0;
+ string error;
+
+ scoped_ptr<Evaluator> evaluator(
+ Evaluator::Create(evaluator_options_, program, &error));
+ CHECK_NOTNULL(evaluator.get());
+
+ scoped_ptr<SparseMatrix> jacobian(evaluator->CreateJacobian());
+ CHECK_NOTNULL(jacobian.get());
+
+ TrustRegionStrategy::Options trs_options;
+ trs_options.linear_solver = linear_solver;
+
+ scoped_ptr<TrustRegionStrategy>trust_region_strategy(
+ CHECK_NOTNULL(TrustRegionStrategy::Create(trs_options)));
+
+ Minimizer::Options minimizer_options;
+ minimizer_options.evaluator = evaluator.get();
+ minimizer_options.jacobian = jacobian.get();
+ minimizer_options.trust_region_strategy = trust_region_strategy.get();
+
+ TrustRegionMinimizer minimizer;
+ minimizer.Minimize(minimizer_options, parameter, summary);
+}
+
+} // namespace internal
+} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.h b/extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.h
new file mode 100644
index 00000000000..3dcf8faee59
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.h
@@ -0,0 +1,88 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#ifndef CERES_INTERNAL_COORDINATE_DESCENT_MINIMIZER_H_
+#define CERES_INTERNAL_COORDINATE_DESCENT_MINIMIZER_H_
+
+#include <vector>
+
+#include "ceres/evaluator.h"
+#include "ceres/minimizer.h"
+#include "ceres/problem_impl.h"
+#include "ceres/program.h"
+#include "ceres/solver.h"
+
+namespace ceres {
+namespace internal {
+
+// Given a Program, and a ParameterBlockOrdering which partitions
+// (non-exhaustively) the Hessian matrix into independent sets,
+// perform coordinate descent on the parameter blocks in the
+// ordering. The independent set structure allows for all parameter
+// blocks in the same independent set to be optimized in parallel, and
+// the order of the independent set determines the order in which the
+// parameter block groups are optimized.
+//
+// The minimizer assumes that none of the parameter blocks in the
+// program are constant.
+class CoordinateDescentMinimizer : public Minimizer {
+ public:
+ bool Init(const Program& program,
+ const ProblemImpl::ParameterMap& parameter_map,
+ const ParameterBlockOrdering& ordering,
+ string* error);
+
+ // Minimizer interface.
+ virtual ~CoordinateDescentMinimizer();
+ virtual void Minimize(const Minimizer::Options& options,
+ double* parameters,
+ Solver::Summary* summary);
+
+ private:
+ void Solve(Program* program,
+ LinearSolver* linear_solver,
+ double* parameters,
+ Solver::Summary* summary);
+
+ vector<ParameterBlock*> parameter_blocks_;
+ vector<vector<ResidualBlock*> > residual_blocks_;
+ // The optimization is performed in rounds. In each round all the
+ // parameter blocks that form one independent set are optimized in
+ // parallel. This array, marks the boundaries of the independent
+ // sets in parameter_blocks_.
+ vector<int> independent_set_offsets_;
+
+ Evaluator::Options evaluator_options_;
+};
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_INTERNAL_COORDINATE_DESCENT_MINIMIZER_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/corrector.cc b/extern/libmv/third_party/ceres/internal/ceres/corrector.cc
index eff4dff8566..c3858abd2f4 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/corrector.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/corrector.cc
@@ -113,12 +113,19 @@ void Corrector::CorrectJacobian(int nrow, int ncol,
double* residuals, double* jacobian) {
DCHECK(residuals != NULL);
DCHECK(jacobian != NULL);
- ConstVectorRef r_ref(residuals, nrow);
- MatrixRef j_ref(jacobian, nrow, ncol);
- // Equation 11 in BANS.
- j_ref = sqrt_rho1_ * (j_ref - alpha_sq_norm_ *
- r_ref * (r_ref.transpose() * j_ref));
+ if (nrow == 1) {
+ // Specialization for the case where the residual is a scalar.
+ VectorRef j_ref(jacobian, ncol);
+ j_ref *= sqrt_rho1_ * (1.0 - alpha_sq_norm_ * pow(*residuals, 2));
+ } else {
+ ConstVectorRef r_ref(residuals, nrow);
+ MatrixRef j_ref(jacobian, nrow, ncol);
+
+ // Equation 11 in BANS.
+ j_ref = sqrt_rho1_ * (j_ref - alpha_sq_norm_ *
+ r_ref * (r_ref.transpose() * j_ref));
+ }
}
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/cxsparse.cc b/extern/libmv/third_party/ceres/internal/ceres/cxsparse.cc
index ca36ce07614..3fbc2717f64 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/cxsparse.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/cxsparse.cc
@@ -39,7 +39,7 @@
namespace ceres {
namespace internal {
-CXSparse::CXSparse() : scratch_size_(0), scratch_(NULL) {
+CXSparse::CXSparse() : scratch_(NULL), scratch_size_(0) {
}
CXSparse::~CXSparse() {
@@ -57,6 +57,7 @@ bool CXSparse::SolveCholesky(cs_di* A,
cs_free(scratch_);
}
scratch_ = reinterpret_cast<CS_ENTRY*>(cs_malloc(A->n, sizeof(CS_ENTRY)));
+ scratch_size_ = A->n;
}
// Solve using Cholesky factorization
@@ -116,12 +117,12 @@ cs_di* CXSparse::CreateSparseMatrix(TripletSparseMatrix* tsm) {
return cs_compress(&tsm_wrapper);
}
-void CXSparse::Free(cs_di* factor) {
- cs_free(factor);
+void CXSparse::Free(cs_di* sparse_matrix) {
+ cs_di_spfree(sparse_matrix);
}
-void CXSparse::Free(cs_dis* factor) {
- cs_sfree(factor);
+void CXSparse::Free(cs_dis* symbolic_factorization) {
+ cs_di_sfree(symbolic_factorization);
}
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/cxsparse.h b/extern/libmv/third_party/ceres/internal/ceres/cxsparse.h
index d3b64fcd1a5..dd5eadc8da8 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/cxsparse.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/cxsparse.h
@@ -72,9 +72,8 @@ class CXSparse {
// The returned matrix should be deallocated with Free when not used anymore.
cs_dis* AnalyzeCholesky(cs_di* A);
- // Deallocates the memory of a matrix obtained from AnalyzeCholesky.
- void Free(cs_di* factor);
- void Free(cs_dis* factor);
+ void Free(cs_di* sparse_matrix);
+ void Free(cs_dis* symbolic_factorization);
private:
// Cached scratch space
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_jacobian_writer.h b/extern/libmv/third_party/ceres/internal/ceres/dense_jacobian_writer.h
index 1177b83a556..be743a8591c 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/dense_jacobian_writer.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/dense_jacobian_writer.h
@@ -62,7 +62,8 @@ class DenseJacobianWriter {
SparseMatrix* CreateJacobian() const {
return new DenseSparseMatrix(program_->NumResiduals(),
- program_->NumEffectiveParameters());
+ program_->NumEffectiveParameters(),
+ true);
}
void Write(int residual_id,
@@ -87,10 +88,10 @@ class DenseJacobianWriter {
continue;
}
- int parameter_block_size = parameter_block->LocalSize();
- MatrixRef parameter_jacobian(jacobians[j],
- num_residuals,
- parameter_block_size);
+ const int parameter_block_size = parameter_block->LocalSize();
+ ConstMatrixRef parameter_jacobian(jacobians[j],
+ num_residuals,
+ parameter_block_size);
dense_jacobian->mutable_matrix().block(
residual_offset,
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.cc
index f6bb99abf63..96f55115a67 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.cc
@@ -34,10 +34,11 @@
#include "Eigen/Dense"
#include "ceres/dense_sparse_matrix.h"
-#include "ceres/linear_solver.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/scoped_ptr.h"
+#include "ceres/linear_solver.h"
#include "ceres/types.h"
+#include "ceres/wall_time.h"
namespace ceres {
namespace internal {
@@ -51,13 +52,16 @@ LinearSolver::Summary DenseNormalCholeskySolver::SolveImpl(
const double* b,
const LinearSolver::PerSolveOptions& per_solve_options,
double* x) {
+ EventLogger event_logger("DenseNormalCholeskySolver::Solve");
+
const int num_rows = A->num_rows();
const int num_cols = A->num_cols();
- ConstAlignedMatrixRef Aref = A->matrix();
+ ConstColMajorMatrixRef Aref = A->matrix();
Matrix lhs(num_cols, num_cols);
lhs.setZero();
+ event_logger.AddEvent("Setup");
// lhs += A'A
//
// Using rankUpdate instead of GEMM, exposes the fact that its the
@@ -73,12 +77,13 @@ LinearSolver::Summary DenseNormalCholeskySolver::SolveImpl(
lhs += D.array().square().matrix().asDiagonal();
}
- VectorRef(x, num_cols) =
- lhs.selfadjointView<Eigen::Upper>().ldlt().solve(rhs);
-
LinearSolver::Summary summary;
summary.num_iterations = 1;
summary.termination_type = TOLERANCE;
+ VectorRef(x, num_cols) =
+ lhs.selfadjointView<Eigen::Upper>().ldlt().solve(rhs);
+ event_logger.AddEvent("Solve");
+
return summary;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc
index 2b329ee0e9c..1fb9709b42a 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc
@@ -34,10 +34,11 @@
#include "Eigen/Dense"
#include "ceres/dense_sparse_matrix.h"
-#include "ceres/linear_solver.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/scoped_ptr.h"
+#include "ceres/linear_solver.h"
#include "ceres/types.h"
+#include "ceres/wall_time.h"
namespace ceres {
namespace internal {
@@ -50,10 +51,10 @@ LinearSolver::Summary DenseQRSolver::SolveImpl(
const double* b,
const LinearSolver::PerSolveOptions& per_solve_options,
double* x) {
+ EventLogger event_logger("DenseQRSolver::Solve");
+
const int num_rows = A->num_rows();
const int num_cols = A->num_cols();
- VLOG(2) << "DenseQRSolver: "
- << num_rows << " x " << num_cols << " system.";
if (per_solve_options.D != NULL) {
// Temporarily append a diagonal block to the A matrix, but undo
@@ -62,18 +63,18 @@ LinearSolver::Summary DenseQRSolver::SolveImpl(
}
// rhs = [b;0] to account for the additional rows in the lhs.
- Vector rhs(num_rows + ((per_solve_options.D != NULL) ? num_cols : 0));
- rhs.setZero();
- rhs.head(num_rows) = ConstVectorRef(b, num_rows);
+ const int augmented_num_rows =
+ num_rows + ((per_solve_options.D != NULL) ? num_cols : 0);
+ if (rhs_.rows() != augmented_num_rows) {
+ rhs_.resize(augmented_num_rows);
+ rhs_.setZero();
+ }
+ rhs_.head(num_rows) = ConstVectorRef(b, num_rows);
+ event_logger.AddEvent("Setup");
// Solve the system.
- VectorRef(x, num_cols) = A->matrix().colPivHouseholderQr().solve(rhs);
-
- VLOG(3) << "A:\n" << A->matrix();
- VLOG(3) << "x:\n" << VectorRef(x, num_cols);
- VLOG(3) << "b:\n" << rhs;
- VLOG(3) << "error: " << (A->matrix() * VectorRef(x, num_cols) - rhs).norm();
-
+ VectorRef(x, num_cols) = A->matrix().colPivHouseholderQr().solve(rhs_);
+ event_logger.AddEvent("Solve");
if (per_solve_options.D != NULL) {
// Undo the modifications to the matrix A.
@@ -86,6 +87,8 @@ LinearSolver::Summary DenseQRSolver::SolveImpl(
LinearSolver::Summary summary;
summary.num_iterations = 1;
summary.termination_type = TOLERANCE;
+
+ event_logger.AddEvent("TearDown");
return summary;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h
index dd683a8c4ea..f78fa72c5f3 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h
@@ -33,6 +33,7 @@
#define CERES_INTERNAL_DENSE_QR_SOLVER_H_
#include "ceres/linear_solver.h"
+#include "ceres/internal/eigen.h"
#include "ceres/internal/macros.h"
namespace ceres {
@@ -90,6 +91,7 @@ class DenseQRSolver: public DenseSparseMatrixSolver {
double* x);
const LinearSolver::Options options_;
+ Vector rhs_;
CERES_DISALLOW_COPY_AND_ASSIGN(DenseQRSolver);
};
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc
index 86730cc101b..9d58031ccfc 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc
@@ -42,11 +42,24 @@ namespace internal {
DenseSparseMatrix::DenseSparseMatrix(int num_rows, int num_cols)
: has_diagonal_appended_(false),
has_diagonal_reserved_(false) {
- // Allocate enough space for the diagonal.
m_.resize(num_rows, num_cols);
m_.setZero();
}
+DenseSparseMatrix::DenseSparseMatrix(int num_rows,
+ int num_cols,
+ bool reserve_diagonal)
+ : has_diagonal_appended_(false),
+ has_diagonal_reserved_(reserve_diagonal) {
+ if (reserve_diagonal) {
+ // Allocate enough space for the diagonal.
+ m_.resize(num_rows + num_cols, num_cols);
+ } else {
+ m_.resize(num_rows, num_cols);
+ }
+ m_.setZero();
+}
+
DenseSparseMatrix::DenseSparseMatrix(const TripletSparseMatrix& m)
: m_(Eigen::MatrixXd::Zero(m.num_rows(), m.num_cols())),
has_diagonal_appended_(false),
@@ -61,7 +74,7 @@ DenseSparseMatrix::DenseSparseMatrix(const TripletSparseMatrix& m)
}
}
-DenseSparseMatrix::DenseSparseMatrix(const Matrix& m)
+DenseSparseMatrix::DenseSparseMatrix(const ColMajorMatrix& m)
: m_(m),
has_diagonal_appended_(false),
has_diagonal_reserved_(false) {
@@ -105,7 +118,7 @@ void DenseSparseMatrix::ScaleColumns(const double* scale) {
}
void DenseSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const {
- *dense_matrix = m_;
+ *dense_matrix = m_.block(0, 0, num_rows(), num_cols());
}
#ifndef CERES_NO_PROTOCOL_BUFFERS
@@ -127,7 +140,7 @@ void DenseSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const {
void DenseSparseMatrix::AppendDiagonal(double *d) {
CHECK(!has_diagonal_appended_);
if (!has_diagonal_reserved_) {
- Matrix tmp = m_;
+ ColMajorMatrix tmp = m_;
m_.resize(m_.rows() + m_.cols(), m_.cols());
m_.setZero();
m_.block(0, 0, tmp.rows(), tmp.cols()) = tmp;
@@ -163,22 +176,27 @@ int DenseSparseMatrix::num_nonzeros() const {
return m_.rows() * m_.cols();
}
-ConstAlignedMatrixRef DenseSparseMatrix::matrix() const {
- if (has_diagonal_reserved_ && !has_diagonal_appended_) {
- return ConstAlignedMatrixRef(
- m_.data(), m_.rows() - m_.cols(), m_.cols());
- }
- return ConstAlignedMatrixRef(m_.data(), m_.rows(), m_.cols());
+ConstColMajorMatrixRef DenseSparseMatrix::matrix() const {
+ return ConstColMajorMatrixRef(
+ m_.data(),
+ ((has_diagonal_reserved_ && !has_diagonal_appended_)
+ ? m_.rows() - m_.cols()
+ : m_.rows()),
+ m_.cols(),
+ Eigen::Stride<Eigen::Dynamic, 1>(m_.rows(), 1));
}
-AlignedMatrixRef DenseSparseMatrix::mutable_matrix() {
- if (has_diagonal_reserved_ && !has_diagonal_appended_) {
- return AlignedMatrixRef(
- m_.data(), m_.rows() - m_.cols(), m_.cols());
- }
- return AlignedMatrixRef(m_.data(), m_.rows(), m_.cols());
+ColMajorMatrixRef DenseSparseMatrix::mutable_matrix() {
+ return ColMajorMatrixRef(
+ m_.data(),
+ ((has_diagonal_reserved_ && !has_diagonal_appended_)
+ ? m_.rows() - m_.cols()
+ : m_.rows()),
+ m_.cols(),
+ Eigen::Stride<Eigen::Dynamic, 1>(m_.rows(), 1));
}
+
void DenseSparseMatrix::ToTextFile(FILE* file) const {
CHECK_NOTNULL(file);
const int active_rows =
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h
index e7ad14d0ee6..6c7b60ade13 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h
@@ -51,12 +51,13 @@ class DenseSparseMatrix : public SparseMatrix {
// Build a matrix with the same content as the TripletSparseMatrix
// m. This assumes that m does not have any repeated entries.
explicit DenseSparseMatrix(const TripletSparseMatrix& m);
- explicit DenseSparseMatrix(const Matrix& m);
+ explicit DenseSparseMatrix(const ColMajorMatrix& m);
#ifndef CERES_NO_PROTOCOL_BUFFERS
explicit DenseSparseMatrix(const SparseMatrixProto& proto);
#endif
DenseSparseMatrix(int num_rows, int num_cols);
+ DenseSparseMatrix(int num_rows, int num_cols, bool reserve_diagonal);
virtual ~DenseSparseMatrix() {}
@@ -77,8 +78,8 @@ class DenseSparseMatrix : public SparseMatrix {
virtual const double* values() const { return m_.data(); }
virtual double* mutable_values() { return m_.data(); }
- ConstAlignedMatrixRef matrix() const;
- AlignedMatrixRef mutable_matrix();
+ ConstColMajorMatrixRef matrix() const;
+ ColMajorMatrixRef mutable_matrix();
// Only one diagonal can be appended at a time. The diagonal is appended to
// as a new set of rows, e.g.
@@ -105,7 +106,7 @@ class DenseSparseMatrix : public SparseMatrix {
void RemoveDiagonal();
private:
- Matrix m_;
+ ColMajorMatrix m_;
bool has_diagonal_appended_;
bool has_diagonal_reserved_;
};
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.cc b/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.cc
index 668fa54b8b8..a330ad2c7a2 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.cc
@@ -35,7 +35,7 @@
#include "ceres/array_utils.h"
#include "ceres/internal/eigen.h"
#include "ceres/linear_solver.h"
-#include "ceres/polynomial_solver.h"
+#include "ceres/polynomial.h"
#include "ceres/sparse_matrix.h"
#include "ceres/trust_region_strategy.h"
#include "ceres/types.h"
@@ -87,7 +87,7 @@ TrustRegionStrategy::Summary DoglegStrategy::ComputeStep(
// Gauss-Newton and gradient vectors are always available, only a
// new interpolant need to be computed. For the subspace case,
// the subspace and the two-dimensional model are also still valid.
- switch(dogleg_type_) {
+ switch (dogleg_type_) {
case TRADITIONAL_DOGLEG:
ComputeTraditionalDoglegStep(step);
break;
@@ -135,7 +135,7 @@ TrustRegionStrategy::Summary DoglegStrategy::ComputeStep(
summary.termination_type = linear_solver_summary.termination_type;
if (linear_solver_summary.termination_type != FAILURE) {
- switch(dogleg_type_) {
+ switch (dogleg_type_) {
// Interpolate the Cauchy point and the Gauss-Newton step.
case TRADITIONAL_DOGLEG:
ComputeTraditionalDoglegStep(step);
@@ -415,15 +415,15 @@ Vector DoglegStrategy::MakePolynomialForBoundaryConstrainedProblem() const {
const double trB = subspace_B_.trace();
const double r2 = radius_ * radius_;
Matrix2d B_adj;
- B_adj << subspace_B_(1,1) , -subspace_B_(0,1),
- -subspace_B_(1,0) , subspace_B_(0,0);
+ B_adj << subspace_B_(1, 1) , -subspace_B_(0, 1),
+ -subspace_B_(1, 0) , subspace_B_(0, 0);
Vector polynomial(5);
polynomial(0) = r2;
polynomial(1) = 2.0 * r2 * trB;
- polynomial(2) = r2 * ( trB * trB + 2.0 * detB ) - subspace_g_.squaredNorm();
- polynomial(3) = -2.0 * ( subspace_g_.transpose() * B_adj * subspace_g_
- - r2 * detB * trB );
+ polynomial(2) = r2 * (trB * trB + 2.0 * detB) - subspace_g_.squaredNorm();
+ polynomial(3) = -2.0 * (subspace_g_.transpose() * B_adj * subspace_g_
+ - r2 * detB * trB);
polynomial(4) = r2 * detB * detB - (B_adj * subspace_g_).squaredNorm();
return polynomial;
@@ -598,7 +598,7 @@ void DoglegStrategy::StepAccepted(double step_quality) {
// Reduce the regularization multiplier, in the hope that whatever
// was causing the rank deficiency has gone away and we can return
// to doing a pure Gauss-Newton solve.
- mu_ = max(min_mu_, 2.0 * mu_ / mu_increase_factor_ );
+ mu_ = max(min_mu_, 2.0 * mu_ / mu_increase_factor_);
reuse_ = false;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.h b/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.h
index bff1689aa4a..7131467d6ce 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.h
@@ -53,8 +53,8 @@ namespace internal {
// This finds the exact optimum over the two-dimensional subspace
// spanned by the two Dogleg vectors.
class DoglegStrategy : public TrustRegionStrategy {
-public:
- DoglegStrategy(const TrustRegionStrategy::Options& options);
+ public:
+ explicit DoglegStrategy(const TrustRegionStrategy::Options& options);
virtual ~DoglegStrategy() {}
// TrustRegionStrategy interface
diff --git a/extern/libmv/third_party/ceres/internal/ceres/evaluator.cc b/extern/libmv/third_party/ceres/internal/ceres/evaluator.cc
index a3ce6f04bd4..31a417689e8 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/evaluator.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/evaluator.cc
@@ -72,76 +72,5 @@ Evaluator* Evaluator::Create(const Evaluator::Options& options,
}
}
-bool Evaluator::Evaluate(Program* program,
- int num_threads,
- double* cost,
- vector<double>* residuals,
- vector<double>* gradient,
- CRSMatrix* output_jacobian) {
- CHECK_GE(num_threads, 1)
- << "This is a Ceres bug; please contact the developers!";
- CHECK_NOTNULL(cost);
-
- // Setup the Parameter indices and offsets before an evaluator can
- // be constructed and used.
- program->SetParameterOffsetsAndIndex();
-
- Evaluator::Options evaluator_options;
- evaluator_options.linear_solver_type = SPARSE_NORMAL_CHOLESKY;
- evaluator_options.num_threads = num_threads;
-
- string error;
- scoped_ptr<Evaluator> evaluator(
- Evaluator::Create(evaluator_options, program, &error));
- if (evaluator.get() == NULL) {
- LOG(ERROR) << "Unable to create an Evaluator object. "
- << "Error: " << error
- << "This is a Ceres bug; please contact the developers!";
- return false;
- }
-
- if (residuals !=NULL) {
- residuals->resize(evaluator->NumResiduals());
- }
-
- if (gradient != NULL) {
- gradient->resize(evaluator->NumEffectiveParameters());
- }
-
- scoped_ptr<CompressedRowSparseMatrix> jacobian;
- if (output_jacobian != NULL) {
- jacobian.reset(
- down_cast<CompressedRowSparseMatrix*>(evaluator->CreateJacobian()));
- }
-
- // Point the state pointers to the user state pointers. This is
- // needed so that we can extract a parameter vector which is then
- // passed to Evaluator::Evaluate.
- program->SetParameterBlockStatePtrsToUserStatePtrs();
-
- // Copy the value of the parameter blocks into a vector, since the
- // Evaluate::Evaluate method needs its input as such. The previous
- // call to SetParameterBlockStatePtrsToUserStatePtrs ensures that
- // these values are the ones corresponding to the actual state of
- // the parameter blocks, rather than the temporary state pointer
- // used for evaluation.
- Vector parameters(program->NumParameters());
- program->ParameterBlocksToStateVector(parameters.data());
-
- if (!evaluator->Evaluate(parameters.data(),
- cost,
- residuals != NULL ? &(*residuals)[0] : NULL,
- gradient != NULL ? &(*gradient)[0] : NULL,
- jacobian.get())) {
- return false;
- }
-
- if (output_jacobian != NULL) {
- jacobian->ToCRSMatrix(output_jacobian);
- }
-
- return true;
-}
-
} // namespace internal
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/evaluator.h b/extern/libmv/third_party/ceres/internal/ceres/evaluator.h
index 6aa30d7b739..3d2546224b8 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/evaluator.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/evaluator.h
@@ -32,14 +32,17 @@
#ifndef CERES_INTERNAL_EVALUATOR_H_
#define CERES_INTERNAL_EVALUATOR_H_
+#include <map>
#include <string>
#include <vector>
+
+#include "ceres/execution_summary.h"
#include "ceres/internal/port.h"
#include "ceres/types.h"
namespace ceres {
-class CRSMatrix;
+struct CRSMatrix;
namespace internal {
@@ -69,7 +72,6 @@ class Evaluator {
Program* program,
string* error);
-
// This is used for computing the cost, residual and Jacobian for
// returning to the user. For actually solving the optimization
// problem, the optimization algorithm uses the ProgramEvaluator
@@ -113,6 +115,18 @@ class Evaluator {
// Schur complement based methods.
virtual SparseMatrix* CreateJacobian() const = 0;
+
+ // Options struct to control Evaluator::Evaluate;
+ struct EvaluateOptions {
+ EvaluateOptions()
+ : apply_loss_function(true) {
+ }
+
+ // If false, the loss function correction is not applied to the
+ // residual blocks.
+ bool apply_loss_function;
+ };
+
// Evaluate the cost function for the given state. Returns the cost,
// residuals, and jacobian in the corresponding arguments. Both residuals and
// jacobian are optional; to avoid computing them, pass NULL.
@@ -122,12 +136,29 @@ class Evaluator {
//
// state is an array of size NumParameters(), cost is a pointer to a single
// double, and residuals is an array of doubles of size NumResiduals().
- virtual bool Evaluate(const double* state,
+ virtual bool Evaluate(const EvaluateOptions& evaluate_options,
+ const double* state,
double* cost,
double* residuals,
double* gradient,
SparseMatrix* jacobian) = 0;
+ // Variant of Evaluator::Evaluate where the user wishes to use the
+ // default EvaluateOptions struct. This is mostly here as a
+ // convenience method.
+ bool Evaluate(const double* state,
+ double* cost,
+ double* residuals,
+ double* gradient,
+ SparseMatrix* jacobian) {
+ return Evaluate(EvaluateOptions(),
+ state,
+ cost,
+ residuals,
+ gradient,
+ jacobian);
+ }
+
// Make a change delta (of size NumEffectiveParameters()) to state (of size
// NumParameters()) and store the result in state_plus_delta.
//
@@ -152,6 +183,18 @@ class Evaluator {
// The number of residuals in the optimization problem.
virtual int NumResiduals() const = 0;
+
+ // The following two methods return copies instead of references so
+ // that the base class implementation does not have to worry about
+ // life time issues. Further, these calls are not expected to be
+ // frequent or performance sensitive.
+ virtual map<string, int> CallStatistics() const {
+ return map<string, int>();
+ }
+
+ virtual map<string, double> TimeStatistics() const {
+ return map<string, double>();
+ }
};
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/execution_summary.h b/extern/libmv/third_party/ceres/internal/ceres/execution_summary.h
new file mode 100644
index 00000000000..29bdc69ecd7
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/execution_summary.h
@@ -0,0 +1,90 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#ifndef CERES_INTERNAL_EXECUTION_SUMMARY_H_
+#define CERES_INTERNAL_EXECUTION_SUMMARY_H_
+
+#include <map>
+#include <string>
+
+#include "ceres/internal/port.h"
+#include "ceres/wall_time.h"
+#include "ceres/mutex.h"
+
+namespace ceres {
+namespace internal {
+
+// Struct used by various objects to report statistics and other
+// information about their execution. e.g., ExecutionSummary::times
+// can be used for reporting times associated with various activities.
+class ExecutionSummary {
+ public:
+ void IncrementTimeBy(const string& name, const double value) {
+ CeresMutexLock l(&times_mutex_);
+ times_[name] += value;
+ }
+
+ void IncrementCall(const string& name) {
+ CeresMutexLock l(&calls_mutex_);
+ calls_[name] += 1;
+ }
+
+ const map<string, double>& times() const { return times_; }
+ const map<string, int>& calls() const { return calls_; }
+
+ private:
+ Mutex times_mutex_;
+ map<string, double> times_;
+
+ Mutex calls_mutex_;
+ map<string, int> calls_;
+};
+
+class ScopedExecutionTimer {
+ public:
+ ScopedExecutionTimer(const string& name, ExecutionSummary* summary)
+ : start_time_(WallTimeInSeconds()),
+ name_(name),
+ summary_(summary) {}
+
+ ~ScopedExecutionTimer() {
+ summary_->IncrementTimeBy(name_, WallTimeInSeconds() - start_time_);
+ }
+
+ private:
+ const double start_time_;
+ const string name_;
+ ExecutionSummary* summary_;
+};
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_INTERNAL_EXECUTION_SUMMARY_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/file.cc b/extern/libmv/third_party/ceres/internal/ceres/file.cc
index 6fe7557246d..5226c85e6ee 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/file.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/file.cc
@@ -30,8 +30,9 @@
//
// Really simple file IO.
+#include "ceres/file.h"
+
#include <cstdio>
-#include "file.h"
#include "glog/logging.h"
namespace ceres {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generate_eliminator_specialization.py b/extern/libmv/third_party/ceres/internal/ceres/generate_eliminator_specialization.py
index af9873f94c0..caeca69fb80 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/generate_eliminator_specialization.py
+++ b/extern/libmv/third_party/ceres/internal/ceres/generate_eliminator_specialization.py
@@ -1,33 +1,31 @@
-// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
-// http://code.google.com/p/ceres-solver/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// * Neither the name of Google Inc. nor the names of its contributors may be
-// used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-//
+# Ceres Solver - A fast non-linear least squares minimizer
+# Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
+# http://code.google.com/p/ceres-solver/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of Google Inc. nor the names of its contributors may be
+# used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
#
-# Copyright 2011 Google Inc. All Rights Reserved.
# Author: sameeragarwal@google.com (Sameer Agarwal)
#
# Script for explicitly generating template specialization of the
@@ -54,21 +52,47 @@
SPECIALIZATIONS = [(2, 2, 2),
(2, 2, 3),
(2, 2, 4),
- (2, 2, "Dynamic"),
+ (2, 2, "Eigen::Dynamic"),
(2, 3, 3),
(2, 3, 4),
(2, 3, 9),
- (2, 3, "Dynamic"),
+ (2, 3, "Eigen::Dynamic"),
(2, 4, 3),
(2, 4, 4),
- (2, 4, "Dynamic"),
+ (2, 4, "Eigen::Dynamic"),
(4, 4, 2),
(4, 4, 3),
(4, 4, 4),
- (4, 4, "Dynamic"),
- ("Dynamic", "Dynamic", "Dynamic")]
-
-SPECIALIZATION_FILE = """// Copyright 2011 Google Inc. All Rights Reserved.
+ (4, 4, "Eigen::Dynamic"),
+ ("Eigen::Dynamic", "Eigen::Dynamic", "Eigen::Dynamic")]
+HEADER = """// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Template specialization of SchurEliminator.
@@ -80,8 +104,11 @@ SPECIALIZATION_FILE = """// Copyright 2011 Google Inc. All Rights Reserved.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
-// This file is generated using generate_eliminator_specializations.py.
+// This file is generated using generate_eliminator_specialization.py.
// Editing it manually is not recommended.
+"""
+
+DYNAMIC_FILE = """
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
@@ -93,22 +120,26 @@ template class SchurEliminator<%s, %s, %s>;
} // namespace internal
} // namespace ceres
-
"""
-FACTORY_FILE_HEADER = """// Copyright 2011 Google Inc. All Rights Reserved.
-// Author: sameeragarwal@google.com (Sameer Agarwal)
-//
-// ========================================
-// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
-// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
-// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
-// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
-//=========================================
-//
-// This file is generated using generate_template_specializations.py.
-// Editing it manually is not recommended.
+SPECIALIZATION_FILE = """
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+#include "ceres/schur_eliminator_impl.h"
+#include "ceres/internal/eigen.h"
+
+namespace ceres {
+namespace internal {
+
+template class SchurEliminator<%s, %s, %s>;
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
+"""
+
+FACTORY_FILE_HEADER = """
#include "ceres/linear_solver.h"
#include "ceres/schur_eliminator.h"
#include "ceres/internal/eigen.h"
@@ -134,7 +165,7 @@ FACTORY_FOOTER = """
<< options.row_block_size << ","
<< options.e_block_size << ","
<< options.f_block_size << ">";
- return new SchurEliminator<Dynamic, Dynamic, Dynamic>(options);
+ return new SchurEliminator<Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic>(options);
}
} // namespace internal
@@ -143,7 +174,7 @@ FACTORY_FOOTER = """
def SuffixForSize(size):
- if size == "Dynamic":
+ if size == "Eigen::Dynamic":
return "d"
return str(size)
@@ -159,6 +190,7 @@ def Specialize():
Generate specialization code and the conditionals to instantiate it.
"""
f = open("schur_eliminator.cc", "w")
+ f.write(HEADER)
f.write(FACTORY_FILE_HEADER)
for row_block_size, e_block_size, f_block_size in SPECIALIZATIONS:
@@ -167,9 +199,15 @@ def Specialize():
e_block_size,
f_block_size) + ".cc"
fptr = open(output, "w")
- fptr.write(SPECIALIZATION_FILE % (row_block_size,
- e_block_size,
- f_block_size))
+ fptr.write(HEADER)
+
+ template = SPECIALIZATION_FILE
+ if (row_block_size == "Eigen::Dynamic" and
+ e_block_size == "Eigen::Dynamic" and
+ f_block_size == "Eigen::Dynamic"):
+ template = DYNAMIC_FILE
+
+ fptr.write(template % (row_block_size, e_block_size, f_block_size))
fptr.close()
f.write(FACTORY_CONDITIONAL % (row_block_size,
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_2.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_2.cc
index 5529386e485..7f9ce1431b9 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_2.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_2.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,8 @@
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
@@ -51,3 +53,4 @@ template class SchurEliminator<2, 2, 2>;
} // namespace internal
} // namespace ceres
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_3.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_3.cc
index fd7af95192e..d9ab1ddf2c1 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_3.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_3.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,8 @@
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
@@ -51,3 +53,4 @@ template class SchurEliminator<2, 2, 3>;
} // namespace internal
} // namespace ceres
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_4.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_4.cc
index 109483e9fc0..a268810a829 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_4.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_4.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,8 @@
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
@@ -51,3 +53,4 @@ template class SchurEliminator<2, 2, 4>;
} // namespace internal
} // namespace ceres
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_d.cc
index b93e82fe2fa..46f9492e830 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_d.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_2_d.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -40,14 +40,17 @@
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
-template class SchurEliminator<2, 2, Dynamic>;
+template class SchurEliminator<2, 2, Eigen::Dynamic>;
} // namespace internal
} // namespace ceres
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_3.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_3.cc
index 86352c07304..ce53c6c07eb 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_3.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_3.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,8 @@
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
@@ -51,3 +53,4 @@ template class SchurEliminator<2, 3, 3>;
} // namespace internal
} // namespace ceres
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_4.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_4.cc
index 200df7f5931..7f6d41d7763 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_4.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_4.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,8 @@
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
@@ -51,3 +53,4 @@ template class SchurEliminator<2, 3, 4>;
} // namespace internal
} // namespace ceres
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_9.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_9.cc
index 1fda3434bef..10f84afaaf0 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_9.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_9.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,8 @@
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
@@ -51,3 +53,4 @@ template class SchurEliminator<2, 3, 9>;
} // namespace internal
} // namespace ceres
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_d.cc
index 385cd2d70c9..047d473140a 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_d.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_3_d.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -40,14 +40,17 @@
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
-template class SchurEliminator<2, 3, Dynamic>;
+template class SchurEliminator<2, 3, Eigen::Dynamic>;
} // namespace internal
} // namespace ceres
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_3.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_3.cc
index 7b15d6366ac..12fdb861b34 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_3.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_3.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,8 @@
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
@@ -51,3 +53,4 @@ template class SchurEliminator<2, 4, 3>;
} // namespace internal
} // namespace ceres
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_4.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_4.cc
index 29a610d743e..0e29dc1781a 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_4.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_4.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,8 @@
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
@@ -51,3 +53,4 @@ template class SchurEliminator<2, 4, 4>;
} // namespace internal
} // namespace ceres
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_d.cc
index a3bc4dc6f83..4d4ac56537f 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_d.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_2_4_d.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -40,14 +40,17 @@
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
-template class SchurEliminator<2, 4, Dynamic>;
+template class SchurEliminator<2, 4, Eigen::Dynamic>;
} // namespace internal
} // namespace ceres
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_2.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_2.cc
index f71a4f62944..4ad7d4162c0 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_2.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_2.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,8 @@
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
@@ -51,3 +53,4 @@ template class SchurEliminator<4, 4, 2>;
} // namespace internal
} // namespace ceres
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_3.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_3.cc
index 52259fb1a67..87f2fc58b58 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_3.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_3.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,8 @@
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
@@ -51,3 +53,4 @@ template class SchurEliminator<4, 4, 3>;
} // namespace internal
} // namespace ceres
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_4.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_4.cc
index 775424e6c8f..8b3f5703b95 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_4.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_4.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,8 @@
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
@@ -51,3 +53,4 @@ template class SchurEliminator<4, 4, 4>;
} // namespace internal
} // namespace ceres
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_d.cc
index 97cde594059..b21feb2d3b3 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_d.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_4_4_d.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -40,14 +40,17 @@
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
+#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION
+
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
-template class SchurEliminator<4, 4, Dynamic>;
+template class SchurEliminator<4, 4, Eigen::Dynamic>;
} // namespace internal
} // namespace ceres
+#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION
diff --git a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_d_d_d.cc b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_d_d_d.cc
index 4cba32e26c8..d483db7b578 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_d_d_d.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/generated/schur_eliminator_d_d_d.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -40,14 +40,14 @@
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
+
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
-template class SchurEliminator<Dynamic, Dynamic, Dynamic>;
+template class SchurEliminator<Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic>;
} // namespace internal
} // namespace ceres
-
diff --git a/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc b/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc
index 7fb3ed7b3a8..3edf95da6e0 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc
@@ -154,8 +154,8 @@ class GradientCheckingCostFunction : public CostFunction {
"Jacobian for " "block %d: (%ld by %ld)) "
"==========\n",
k,
- term_jacobians[k].rows(),
- term_jacobians[k].cols());
+ static_cast<long>(term_jacobians[k].rows()),
+ static_cast<long>(term_jacobians[k].cols()));
// The funny spacing creates appropriately aligned column headers.
m += " block row col user dx/dy num diff dx/dy "
"abs error relative error parameter residual\n";
diff --git a/extern/libmv/third_party/ceres/internal/ceres/graph.h b/extern/libmv/third_party/ceres/internal/ceres/graph.h
index 2c0f6d28e54..5f92d4d4df2 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/graph.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/graph.h
@@ -32,12 +32,13 @@
#define CERES_INTERNAL_GRAPH_H_
#include <limits>
-#include <glog/logging.h>
+#include <utility>
#include "ceres/integral_types.h"
#include "ceres/map_util.h"
#include "ceres/collections_port.h"
#include "ceres/internal/macros.h"
#include "ceres/types.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
@@ -65,6 +66,28 @@ class Graph {
AddVertex(vertex, 1.0);
}
+ bool RemoveVertex(const Vertex& vertex) {
+ if (vertices_.find(vertex) == vertices_.end()) {
+ return false;
+ }
+
+ vertices_.erase(vertex);
+ vertex_weights_.erase(vertex);
+ const HashSet<Vertex>& sinks = edges_[vertex];
+ for (typename HashSet<Vertex>::const_iterator it = sinks.begin();
+ it != sinks.end(); ++it) {
+ if (vertex < *it) {
+ edge_weights_.erase(make_pair(vertex, *it));
+ } else {
+ edge_weights_.erase(make_pair(*it, vertex));
+ }
+ edges_[*it].erase(vertex);
+ }
+
+ edges_.erase(vertex);
+ return true;
+ }
+
// Add a weighted edge between the vertex1 and vertex2. Calling
// AddEdge on a pair of vertices which do not exist in the graph yet
// will result in undefined behavior.
diff --git a/extern/libmv/third_party/ceres/internal/ceres/graph_algorithms.h b/extern/libmv/third_party/ceres/internal/ceres/graph_algorithms.h
index 3b42d936336..2e6eec0e6d8 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/graph_algorithms.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/graph_algorithms.h
@@ -33,10 +33,12 @@
#ifndef CERES_INTERNAL_GRAPH_ALGORITHMS_H_
#define CERES_INTERNAL_GRAPH_ALGORITHMS_H_
+#include <algorithm>
#include <vector>
-#include <glog/logging.h>
+#include <utility>
#include "ceres/collections_port.h"
#include "ceres/graph.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc
index 679c41f2431..cf5562ac771 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc
@@ -33,6 +33,7 @@
#include <algorithm>
#include <cstring>
#include <vector>
+
#include "Eigen/Dense"
#include "ceres/block_sparse_matrix.h"
#include "ceres/block_structure.h"
@@ -41,9 +42,12 @@
#include "ceres/internal/eigen.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/linear_solver.h"
+#include "ceres/preconditioner.h"
+#include "ceres/schur_jacobi_preconditioner.h"
#include "ceres/triplet_sparse_matrix.h"
#include "ceres/types.h"
#include "ceres/visibility_based_preconditioner.h"
+#include "ceres/wall_time.h"
#include "glog/logging.h"
namespace ceres {
@@ -62,12 +66,14 @@ LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl(
const double* b,
const LinearSolver::PerSolveOptions& per_solve_options,
double* x) {
+ EventLogger event_logger("IterativeSchurComplementSolver::Solve");
+
CHECK_NOTNULL(A->block_structure());
// Initialize a ImplicitSchurComplement object.
if (schur_complement_ == NULL) {
schur_complement_.reset(
- new ImplicitSchurComplement(options_.num_eliminate_blocks,
+ new ImplicitSchurComplement(options_.elimination_groups[0],
options_.preconditioner_type == JACOBI));
}
schur_complement_->Init(*A, per_solve_options.D, b);
@@ -89,44 +95,58 @@ LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl(
cg_per_solve_options.r_tolerance = per_solve_options.r_tolerance;
cg_per_solve_options.q_tolerance = per_solve_options.q_tolerance;
- bool is_preconditioner_good = false;
+ Preconditioner::Options preconditioner_options;
+ preconditioner_options.type = options_.preconditioner_type;
+ preconditioner_options.sparse_linear_algebra_library =
+ options_.sparse_linear_algebra_library;
+ preconditioner_options.use_block_amd = options_.use_block_amd;
+ preconditioner_options.num_threads = options_.num_threads;
+ preconditioner_options.row_block_size = options_.row_block_size;
+ preconditioner_options.e_block_size = options_.e_block_size;
+ preconditioner_options.f_block_size = options_.f_block_size;
+ preconditioner_options.elimination_groups = options_.elimination_groups;
+
switch (options_.preconditioner_type) {
case IDENTITY:
- is_preconditioner_good = true;
break;
case JACOBI:
- // We need to strip the constness of the block_diagonal_FtF_inverse
- // matrix here because the only other way to initialize the struct
- // cg_solve_options would be to add a constructor to it. We know
- // that the only method ever called on the preconditioner is the
- // RightMultiply which is a const method so we don't need to worry
- // about the object getting modified.
- cg_per_solve_options.preconditioner =
- const_cast<BlockSparseMatrix*>(
- schur_complement_->block_diagonal_FtF_inverse());
- is_preconditioner_good = true;
+ preconditioner_.reset(
+ new SparseMatrixPreconditionerWrapper(
+ schur_complement_->block_diagonal_FtF_inverse()));
break;
case SCHUR_JACOBI:
+ if (preconditioner_.get() == NULL) {
+ preconditioner_.reset(
+ new SchurJacobiPreconditioner(
+ *A->block_structure(), preconditioner_options));
+ }
+ break;
case CLUSTER_JACOBI:
case CLUSTER_TRIDIAGONAL:
- if (visibility_based_preconditioner_.get() == NULL) {
- visibility_based_preconditioner_.reset(
- new VisibilityBasedPreconditioner(*A->block_structure(), options_));
+ if (preconditioner_.get() == NULL) {
+ preconditioner_.reset(
+ new VisibilityBasedPreconditioner(
+ *A->block_structure(), preconditioner_options));
}
- is_preconditioner_good =
- visibility_based_preconditioner_->Update(*A, per_solve_options.D);
- cg_per_solve_options.preconditioner =
- visibility_based_preconditioner_.get();
break;
default:
LOG(FATAL) << "Unknown Preconditioner Type";
}
+ bool preconditioner_update_was_successful = true;
+ if (preconditioner_.get() != NULL) {
+ preconditioner_update_was_successful =
+ preconditioner_->Update(*A, per_solve_options.D);
+ cg_per_solve_options.preconditioner = preconditioner_.get();
+ }
+
+ event_logger.AddEvent("Setup");
+
LinearSolver::Summary cg_summary;
cg_summary.num_iterations = 0;
cg_summary.termination_type = FAILURE;
- if (is_preconditioner_good) {
+ if (preconditioner_update_was_successful) {
cg_summary = cg_solver.Solve(schur_complement_.get(),
schur_complement_->rhs().data(),
cg_per_solve_options,
@@ -138,6 +158,8 @@ LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl(
}
VLOG(2) << "CG Iterations : " << cg_summary.num_iterations;
+
+ event_logger.AddEvent("Solve");
return cg_summary;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.h b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.h
index cfeb65e1eec..f8abe04c142 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.h
@@ -39,13 +39,12 @@
namespace ceres {
namespace internal {
-class BlockSparseMatrix;
class BlockSparseMatrixBase;
class ImplicitSchurComplement;
-class VisibilityBasedPreconditioner;
+class Preconditioner;
// This class implements an iterative solver for the linear least
-// squares problems that have a bi-partitte sparsity structure common
+// squares problems that have a bi-partite sparsity structure common
// to Structure from Motion problems.
//
// The algorithm used by this solver was developed in a series of
@@ -70,9 +69,7 @@ class VisibilityBasedPreconditioner;
// "Iterative Methods for Sparse Linear Systems".
class IterativeSchurComplementSolver : public BlockSparseMatrixBaseSolver {
public:
- explicit IterativeSchurComplementSolver(
- const LinearSolver::Options& options);
-
+ explicit IterativeSchurComplementSolver(const LinearSolver::Options& options);
virtual ~IterativeSchurComplementSolver();
private:
@@ -84,8 +81,9 @@ class IterativeSchurComplementSolver : public BlockSparseMatrixBaseSolver {
LinearSolver::Options options_;
scoped_ptr<internal::ImplicitSchurComplement> schur_complement_;
- scoped_ptr<VisibilityBasedPreconditioner> visibility_based_preconditioner_;
+ scoped_ptr<Preconditioner> preconditioner_;
Vector reduced_linear_system_solution_;
+ CERES_DISALLOW_COPY_AND_ASSIGN(IterativeSchurComplementSolver);
};
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.h b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.h
index 90c21789797..344e3285422 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.h
@@ -43,8 +43,9 @@ namespace internal {
//
// http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf
class LevenbergMarquardtStrategy : public TrustRegionStrategy {
-public:
- LevenbergMarquardtStrategy(const TrustRegionStrategy::Options& options);
+ public:
+ explicit LevenbergMarquardtStrategy(
+ const TrustRegionStrategy::Options& options);
virtual ~LevenbergMarquardtStrategy();
// TrustRegionStrategy interface
diff --git a/extern/libmv/third_party/ceres/internal/ceres/line_search.cc b/extern/libmv/third_party/ceres/internal/ceres/line_search.cc
new file mode 100644
index 00000000000..437f742607f
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/line_search.cc
@@ -0,0 +1,214 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#ifndef CERES_NO_LINE_SEARCH_MINIMIZER
+#include "ceres/line_search.h"
+
+#include <glog/logging.h>
+#include "ceres/fpclassify.h"
+#include "ceres/evaluator.h"
+#include "ceres/internal/eigen.h"
+#include "ceres/polynomial.h"
+
+
+namespace ceres {
+namespace internal {
+namespace {
+
+FunctionSample ValueSample(const double x, const double value) {
+ FunctionSample sample;
+ sample.x = x;
+ sample.value = value;
+ sample.value_is_valid = true;
+ return sample;
+};
+
+FunctionSample ValueAndGradientSample(const double x,
+ const double value,
+ const double gradient) {
+ FunctionSample sample;
+ sample.x = x;
+ sample.value = value;
+ sample.gradient = gradient;
+ sample.value_is_valid = true;
+ sample.gradient_is_valid = true;
+ return sample;
+};
+
+} // namespace
+
+LineSearchFunction::LineSearchFunction(Evaluator* evaluator)
+ : evaluator_(evaluator),
+ position_(evaluator->NumParameters()),
+ direction_(evaluator->NumEffectiveParameters()),
+ evaluation_point_(evaluator->NumParameters()),
+ scaled_direction_(evaluator->NumEffectiveParameters()),
+ gradient_(evaluator->NumEffectiveParameters()) {
+}
+
+void LineSearchFunction::Init(const Vector& position,
+ const Vector& direction) {
+ position_ = position;
+ direction_ = direction;
+}
+
+bool LineSearchFunction::Evaluate(const double x, double* f, double* g) {
+ scaled_direction_ = x * direction_;
+ if (!evaluator_->Plus(position_.data(),
+ scaled_direction_.data(),
+ evaluation_point_.data())) {
+ return false;
+ }
+
+ if (g == NULL) {
+ return (evaluator_->Evaluate(evaluation_point_.data(),
+ f, NULL, NULL, NULL) &&
+ IsFinite(*f));
+ }
+
+ if (!evaluator_->Evaluate(evaluation_point_.data(),
+ f,
+ NULL,
+ gradient_.data(), NULL)) {
+ return false;
+ }
+
+ *g = direction_.dot(gradient_);
+ return IsFinite(*f) && IsFinite(*g);
+}
+
+void ArmijoLineSearch::Search(const LineSearch::Options& options,
+ const double initial_step_size,
+ const double initial_cost,
+ const double initial_gradient,
+ Summary* summary) {
+ *CHECK_NOTNULL(summary) = LineSearch::Summary();
+ Function* function = options.function;
+
+ double previous_step_size = 0.0;
+ double previous_cost = 0.0;
+ double previous_gradient = 0.0;
+ bool previous_step_size_is_valid = false;
+
+ double step_size = initial_step_size;
+ double cost = 0.0;
+ double gradient = 0.0;
+ bool step_size_is_valid = false;
+
+ ++summary->num_evaluations;
+ step_size_is_valid =
+ function->Evaluate(step_size,
+ &cost,
+ options.interpolation_degree < 2 ? NULL : &gradient);
+ while (!step_size_is_valid || cost > (initial_cost
+ + options.sufficient_decrease
+ * initial_gradient
+ * step_size)) {
+ // If step_size_is_valid is not true we treat it as if the cost at
+ // that point is not large enough to satisfy the sufficient
+ // decrease condition.
+
+ const double current_step_size = step_size;
+ // Backtracking search. Each iteration of this loop finds a new point
+
+ if ((options.interpolation_degree == 0) || !step_size_is_valid) {
+ // Backtrack by halving the step_size;
+ step_size *= 0.5;
+ } else {
+ // Backtrack by interpolating the function and gradient values
+ // and minimizing the corresponding polynomial.
+
+ vector<FunctionSample> samples;
+ samples.push_back(ValueAndGradientSample(0.0,
+ initial_cost,
+ initial_gradient));
+
+ if (options.interpolation_degree == 1) {
+ // Two point interpolation using function values and the
+ // initial gradient.
+ samples.push_back(ValueSample(step_size, cost));
+
+ if (options.use_higher_degree_interpolation_when_possible &&
+ summary->num_evaluations > 1 &&
+ previous_step_size_is_valid) {
+ // Three point interpolation, using function values and the
+ // initial gradient.
+ samples.push_back(ValueSample(previous_step_size, previous_cost));
+ }
+ } else {
+ // Two point interpolation using the function values and the gradients.
+ samples.push_back(ValueAndGradientSample(step_size,
+ cost,
+ gradient));
+
+ if (options.use_higher_degree_interpolation_when_possible &&
+ summary->num_evaluations > 1 &&
+ previous_step_size_is_valid) {
+ // Three point interpolation using the function values and
+ // the gradients.
+ samples.push_back(ValueAndGradientSample(previous_step_size,
+ previous_cost,
+ previous_gradient));
+ }
+ }
+
+ double min_value;
+ MinimizeInterpolatingPolynomial(samples, 0.0, current_step_size,
+ &step_size, &min_value);
+ step_size =
+ min(max(step_size,
+ options.min_relative_step_size_change * current_step_size),
+ options.max_relative_step_size_change * current_step_size);
+ }
+
+ previous_step_size = current_step_size;
+ previous_cost = cost;
+ previous_gradient = gradient;
+
+ if (fabs(initial_gradient) * step_size < options.step_size_threshold) {
+ LOG(WARNING) << "Line search failed: step_size too small: " << step_size;
+ return;
+ }
+
+ ++summary->num_evaluations;
+ step_size_is_valid =
+ function->Evaluate(step_size,
+ &cost,
+ options.interpolation_degree < 2 ? NULL : &gradient);
+ }
+
+ summary->optimal_step_size = step_size;
+ summary->success = true;
+}
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_NO_LINE_SEARCH_MINIMIZER
diff --git a/extern/libmv/third_party/ceres/internal/ceres/line_search.h b/extern/libmv/third_party/ceres/internal/ceres/line_search.h
new file mode 100644
index 00000000000..95bf56e2a6b
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/line_search.h
@@ -0,0 +1,215 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Interface for and implementation of various Line search algorithms.
+
+#ifndef CERES_INTERNAL_LINE_SEARCH_H_
+#define CERES_INTERNAL_LINE_SEARCH_H_
+
+#ifndef CERES_NO_LINE_SEARCH_MINIMIZER
+
+#include <glog/logging.h>
+#include <vector>
+#include "ceres/internal/eigen.h"
+#include "ceres/internal/port.h"
+
+namespace ceres {
+namespace internal {
+
+class Evaluator;
+
+// Line search is another name for a one dimensional optimization
+// algorithm. The name "line search" comes from the fact one
+// dimensional optimization problems that arise as subproblems of
+// general multidimensional optimization problems.
+//
+// While finding the exact minimum of a one dimensionl function is
+// hard, instances of LineSearch find a point that satisfies a
+// sufficient decrease condition. Depending on the particular
+// condition used, we get a variety of different line search
+// algorithms, e.g., Armijo, Wolfe etc.
+class LineSearch {
+ public:
+ class Function;
+
+ struct Options {
+ Options()
+ : interpolation_degree(1),
+ use_higher_degree_interpolation_when_possible(false),
+ sufficient_decrease(1e-4),
+ min_relative_step_size_change(1e-3),
+ max_relative_step_size_change(0.6),
+ step_size_threshold(1e-9),
+ function(NULL) {}
+
+ // TODO(sameeragarwal): Replace this with enums which are common
+ // across various line searches.
+ //
+ // Degree of the polynomial used to approximate the objective
+ // function. Valid values are {0, 1, 2}.
+ //
+ // For Armijo line search
+ //
+ // 0: Bisection based backtracking search.
+ // 1: Quadratic interpolation.
+ // 2: Cubic interpolation.
+ int interpolation_degree;
+
+ // Usually its possible to increase the degree of the
+ // interpolation polynomial by storing and using an extra point.
+ bool use_higher_degree_interpolation_when_possible;
+
+ // Armijo line search parameters.
+
+ // Solving the line search problem exactly is computationally
+ // prohibitive. Fortunately, line search based optimization
+ // algorithms can still guarantee convergence if instead of an
+ // exact solution, the line search algorithm returns a solution
+ // which decreases the value of the objective function
+ // sufficiently. More precisely, we are looking for a step_size
+ // s.t.
+ //
+ // f(step_size) <= f(0) + sufficient_decrease * f'(0) * step_size
+ double sufficient_decrease;
+
+ // In each iteration of the Armijo line search,
+ //
+ // new_step_size >= min_relative_step_size_change * step_size
+ double min_relative_step_size_change;
+
+ // In each iteration of the Armijo line search,
+ //
+ // new_step_size <= max_relative_step_size_change * step_size
+ double max_relative_step_size_change;
+
+ // If during the line search, the step_size falls below this
+ // value, it is truncated to zero.
+ double step_size_threshold;
+
+ // The one dimensional function that the line search algorithm
+ // minimizes.
+ Function* function;
+ };
+
+ // An object used by the line search to access the function values
+ // and gradient of the one dimensional function being optimized.
+ //
+ // In practice, this object will provide access to the objective
+ // function value and the directional derivative of the underlying
+ // optimization problem along a specific search direction.
+ //
+ // See LineSearchFunction for an example implementation.
+ class Function {
+ public:
+ virtual ~Function() {}
+ // Evaluate the line search objective
+ //
+ // f(x) = p(position + x * direction)
+ //
+ // Where, p is the objective function of the general optimization
+ // problem.
+ //
+ // g is the gradient f'(x) at x.
+ //
+ // f must not be null. The gradient is computed only if g is not null.
+ virtual bool Evaluate(double x, double* f, double* g) = 0;
+ };
+
+ // Result of the line search.
+ struct Summary {
+ Summary()
+ : success(false),
+ optimal_step_size(0.0),
+ num_evaluations(0) {}
+
+ bool success;
+ double optimal_step_size;
+ int num_evaluations;
+ };
+
+ virtual ~LineSearch() {}
+
+ // Perform the line search.
+ //
+ // initial_step_size must be a positive number.
+ //
+ // initial_cost and initial_gradient are the values and gradient of
+ // the function at zero.
+ // summary must not be null and will contain the result of the line
+ // search.
+ //
+ // Summary::success is true if a non-zero step size is found.
+ virtual void Search(const LineSearch::Options& options,
+ double initial_step_size,
+ double initial_cost,
+ double initial_gradient,
+ Summary* summary) = 0;
+};
+
+class LineSearchFunction : public LineSearch::Function {
+ public:
+ explicit LineSearchFunction(Evaluator* evaluator);
+ virtual ~LineSearchFunction() {}
+ void Init(const Vector& position, const Vector& direction);
+ virtual bool Evaluate(const double x, double* f, double* g);
+
+ private:
+ Evaluator* evaluator_;
+ Vector position_;
+ Vector direction_;
+
+ // evaluation_point = Evaluator::Plus(position_, x * direction_);
+ Vector evaluation_point_;
+
+ // scaled_direction = x * direction_;
+ Vector scaled_direction_;
+ Vector gradient_;
+};
+
+// Backtracking and interpolation based Armijo line search. This
+// implementation is based on the Armijo line search that ships in the
+// minFunc package by Mark Schmidt.
+//
+// For more details: http://www.di.ens.fr/~mschmidt/Software/minFunc.html
+class ArmijoLineSearch : public LineSearch {
+ public:
+ virtual ~ArmijoLineSearch() {}
+ virtual void Search(const LineSearch::Options& options,
+ double initial_step_size,
+ double initial_cost,
+ double initial_gradient,
+ Summary* summary);
+};
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_NO_LINE_SEARCH_MINIMIZER
+#endif // CERES_INTERNAL_LINE_SEARCH_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/line_search_direction.cc b/extern/libmv/third_party/ceres/internal/ceres/line_search_direction.cc
new file mode 100644
index 00000000000..b8b582c3fb1
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/line_search_direction.cc
@@ -0,0 +1,149 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#ifndef CERES_NO_LINE_SEARCH_MINIMIZER
+
+#include "ceres/line_search_direction.h"
+#include "ceres/line_search_minimizer.h"
+#include "ceres/low_rank_inverse_hessian.h"
+#include "ceres/internal/eigen.h"
+#include "glog/logging.h"
+
+namespace ceres {
+namespace internal {
+
+class SteepestDescent : public LineSearchDirection {
+ public:
+ virtual ~SteepestDescent() {}
+ bool NextDirection(const LineSearchMinimizer::State& previous,
+ const LineSearchMinimizer::State& current,
+ Vector* search_direction) {
+ *search_direction = -current.gradient;
+ return true;
+ }
+};
+
+class NonlinearConjugateGradient : public LineSearchDirection {
+ public:
+ NonlinearConjugateGradient(const NonlinearConjugateGradientType type,
+ const double function_tolerance)
+ : type_(type),
+ function_tolerance_(function_tolerance) {
+ }
+
+ bool NextDirection(const LineSearchMinimizer::State& previous,
+ const LineSearchMinimizer::State& current,
+ Vector* search_direction) {
+ double beta = 0.0;
+ Vector gradient_change;
+ switch (type_) {
+ case FLETCHER_REEVES:
+ beta = current.gradient_squared_norm / previous.gradient_squared_norm;
+ break;
+ case POLAK_RIBIRERE:
+ gradient_change = current.gradient - previous.gradient;
+ beta = (current.gradient.dot(gradient_change) /
+ previous.gradient_squared_norm);
+ break;
+ case HESTENES_STIEFEL:
+ gradient_change = current.gradient - previous.gradient;
+ beta = (current.gradient.dot(gradient_change) /
+ previous.search_direction.dot(gradient_change));
+ break;
+ default:
+ LOG(FATAL) << "Unknown nonlinear conjugate gradient type: " << type_;
+ }
+
+ *search_direction = -current.gradient + beta * previous.search_direction;
+ const double directional_derivative =
+ current.gradient.dot(*search_direction);
+ if (directional_derivative > -function_tolerance_) {
+ LOG(WARNING) << "Restarting non-linear conjugate gradients: "
+ << directional_derivative;
+ *search_direction = -current.gradient;
+ };
+
+ return true;
+ }
+
+ private:
+ const NonlinearConjugateGradientType type_;
+ const double function_tolerance_;
+};
+
+class LBFGS : public LineSearchDirection {
+ public:
+ LBFGS(const int num_parameters, const int max_lbfgs_rank)
+ : low_rank_inverse_hessian_(num_parameters, max_lbfgs_rank) {}
+
+ virtual ~LBFGS() {}
+
+ bool NextDirection(const LineSearchMinimizer::State& previous,
+ const LineSearchMinimizer::State& current,
+ Vector* search_direction) {
+ low_rank_inverse_hessian_.Update(
+ previous.search_direction * previous.step_size,
+ current.gradient - previous.gradient);
+ search_direction->setZero();
+ low_rank_inverse_hessian_.RightMultiply(current.gradient.data(),
+ search_direction->data());
+ *search_direction *= -1.0;
+ return true;
+ }
+
+ private:
+ LowRankInverseHessian low_rank_inverse_hessian_;
+};
+
+LineSearchDirection*
+LineSearchDirection::Create(const LineSearchDirection::Options& options) {
+ if (options.type == STEEPEST_DESCENT) {
+ return new SteepestDescent;
+ }
+
+ if (options.type == NONLINEAR_CONJUGATE_GRADIENT) {
+ return new NonlinearConjugateGradient(
+ options.nonlinear_conjugate_gradient_type,
+ options.function_tolerance);
+ }
+
+ if (options.type == ceres::LBFGS) {
+ return new ceres::internal::LBFGS(options.num_parameters,
+ options.max_lbfgs_rank);
+ }
+
+ LOG(ERROR) << "Unknown line search direction type: " << options.type;
+ return NULL;
+}
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_NO_LINE_SEARCH_MINIMIZER
diff --git a/extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.h b/extern/libmv/third_party/ceres/internal/ceres/line_search_direction.h
index 1cf07ddb549..08747544bbe 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/line_search_direction.h
@@ -26,40 +26,48 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
-// Author: moll.markus@arcor.de (Markus Moll)
+// Author: sameeragarwal@google.com (Sameer Agarwal)
-#ifndef CERES_INTERNAL_POLYNOMIAL_SOLVER_H_
-#define CERES_INTERNAL_POLYNOMIAL_SOLVER_H_
+#ifndef CERES_INTERNAL_LINE_SEARCH_DIRECTION_H_
+#define CERES_INTERNAL_LINE_SEARCH_DIRECTION_H_
+
+#ifndef CERES_NO_LINE_SEARCH_MINIMIZER
#include "ceres/internal/eigen.h"
+#include "ceres/line_search_minimizer.h"
+#include "ceres/types.h"
namespace ceres {
namespace internal {
-// Use the companion matrix eigenvalues to determine the roots of the polynomial
-//
-// sum_{i=0}^N polynomial(i) x^{N-i}.
-//
-// This function returns true on success, false otherwise.
-// Failure indicates that the polynomial is invalid (of size 0) or
-// that the eigenvalues of the companion matrix could not be computed.
-// On failure, a more detailed message will be written to LOG(ERROR).
-// If real is not NULL, the real parts of the roots will be returned in it.
-// Likewise, if imaginary is not NULL, imaginary parts will be returned in it.
-bool FindPolynomialRoots(const Vector& polynomial,
- Vector* real,
- Vector* imaginary);
+class LineSearchDirection {
+ public:
+ struct Options {
+ Options()
+ : num_parameters(0),
+ type(LBFGS),
+ nonlinear_conjugate_gradient_type(FLETCHER_REEVES),
+ function_tolerance(1e-12),
+ max_lbfgs_rank(20) {
+ }
+
+ int num_parameters;
+ LineSearchDirectionType type;
+ NonlinearConjugateGradientType nonlinear_conjugate_gradient_type;
+ double function_tolerance;
+ int max_lbfgs_rank;
+ };
+
+ static LineSearchDirection* Create(const Options& options);
-// Evaluate the polynomial at x using the Horner scheme.
-inline double EvaluatePolynomial(const Vector& polynomial, double x) {
- double v = 0.0;
- for (int i = 0; i < polynomial.size(); ++i) {
- v = v * x + polynomial(i);
- }
- return v;
-}
+ virtual ~LineSearchDirection() {}
+ virtual bool NextDirection(const LineSearchMinimizer::State& previous,
+ const LineSearchMinimizer::State& current,
+ Vector* search_direction) = 0;
+};
} // namespace internal
} // namespace ceres
-#endif // CERES_INTERNAL_POLYNOMIAL_SOLVER_H_
+#endif // CERES_NO_LINE_SEARCH_MINIMIZER
+#endif // CERES_INTERNAL_LINE_SEARCH_DIRECTION_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.cc b/extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.cc
new file mode 100644
index 00000000000..684a7369b3a
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.cc
@@ -0,0 +1,287 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Generic loop for line search based optimization algorithms.
+//
+// This is primarily inpsired by the minFunc packaged written by Mark
+// Schmidt.
+//
+// http://www.di.ens.fr/~mschmidt/Software/minFunc.html
+//
+// For details on the theory and implementation see "Numerical
+// Optimization" by Nocedal & Wright.
+
+#ifndef CERES_NO_LINE_SEARCH_MINIMIZER
+
+#include "ceres/line_search_minimizer.h"
+
+#include <algorithm>
+#include <cstdlib>
+#include <cmath>
+#include <string>
+#include <vector>
+
+#include "Eigen/Dense"
+#include "ceres/array_utils.h"
+#include "ceres/evaluator.h"
+#include "ceres/internal/eigen.h"
+#include "ceres/internal/port.h"
+#include "ceres/internal/scoped_ptr.h"
+#include "ceres/line_search.h"
+#include "ceres/line_search_direction.h"
+#include "ceres/stringprintf.h"
+#include "ceres/types.h"
+#include "ceres/wall_time.h"
+#include "glog/logging.h"
+
+namespace ceres {
+namespace internal {
+namespace {
+// Small constant for various floating point issues.
+// TODO(sameeragarwal): Change to a better name if this has only one
+// use.
+const double kEpsilon = 1e-12;
+
+bool Evaluate(Evaluator* evaluator,
+ const Vector& x,
+ LineSearchMinimizer::State* state) {
+ const bool status = evaluator->Evaluate(x.data(),
+ &(state->cost),
+ NULL,
+ state->gradient.data(),
+ NULL);
+ if (status) {
+ state->gradient_squared_norm = state->gradient.squaredNorm();
+ state->gradient_max_norm = state->gradient.lpNorm<Eigen::Infinity>();
+ }
+
+ return status;
+}
+
+} // namespace
+
+void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
+ double* parameters,
+ Solver::Summary* summary) {
+ double start_time = WallTimeInSeconds();
+ double iteration_start_time = start_time;
+
+ Evaluator* evaluator = CHECK_NOTNULL(options.evaluator);
+ const int num_parameters = evaluator->NumParameters();
+ const int num_effective_parameters = evaluator->NumEffectiveParameters();
+
+ summary->termination_type = NO_CONVERGENCE;
+ summary->num_successful_steps = 0;
+ summary->num_unsuccessful_steps = 0;
+
+ VectorRef x(parameters, num_parameters);
+
+ State current_state(num_parameters, num_effective_parameters);
+ State previous_state(num_parameters, num_effective_parameters);
+
+ Vector delta(num_effective_parameters);
+ Vector x_plus_delta(num_parameters);
+
+ IterationSummary iteration_summary;
+ iteration_summary.iteration = 0;
+ iteration_summary.step_is_valid = false;
+ iteration_summary.step_is_successful = false;
+ iteration_summary.cost_change = 0.0;
+ iteration_summary.gradient_max_norm = 0.0;
+ iteration_summary.step_norm = 0.0;
+ iteration_summary.linear_solver_iterations = 0;
+ iteration_summary.step_solver_time_in_seconds = 0;
+
+ // Do initial cost and Jacobian evaluation.
+ if (!Evaluate(evaluator, x, &current_state)) {
+ LOG(WARNING) << "Terminating: Cost and gradient evaluation failed.";
+ summary->termination_type = NUMERICAL_FAILURE;
+ return;
+ }
+
+ summary->initial_cost = current_state.cost + summary->fixed_cost;
+ iteration_summary.cost = current_state.cost + summary->fixed_cost;
+
+ iteration_summary.gradient_max_norm = current_state.gradient_max_norm;
+
+ // The initial gradient max_norm is bounded from below so that we do
+ // not divide by zero.
+ const double initial_gradient_max_norm =
+ max(iteration_summary.gradient_max_norm, kEpsilon);
+ const double absolute_gradient_tolerance =
+ options.gradient_tolerance * initial_gradient_max_norm;
+
+ if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) {
+ summary->termination_type = GRADIENT_TOLERANCE;
+ VLOG(1) << "Terminating: Gradient tolerance reached."
+ << "Relative gradient max norm: "
+ << iteration_summary.gradient_max_norm / initial_gradient_max_norm
+ << " <= " << options.gradient_tolerance;
+ return;
+ }
+
+ iteration_summary.iteration_time_in_seconds =
+ WallTimeInSeconds() - iteration_start_time;
+ iteration_summary.cumulative_time_in_seconds =
+ WallTimeInSeconds() - start_time
+ + summary->preprocessor_time_in_seconds;
+ summary->iterations.push_back(iteration_summary);
+
+ LineSearchDirection::Options line_search_direction_options;
+ line_search_direction_options.num_parameters = num_effective_parameters;
+ line_search_direction_options.type = options.line_search_direction_type;
+ line_search_direction_options.nonlinear_conjugate_gradient_type =
+ options.nonlinear_conjugate_gradient_type;
+ line_search_direction_options.max_lbfgs_rank = options.max_lbfgs_rank;
+ scoped_ptr<LineSearchDirection> line_search_direction(
+ LineSearchDirection::Create(line_search_direction_options));
+
+ LineSearchFunction line_search_function(evaluator);
+ LineSearch::Options line_search_options;
+ line_search_options.function = &line_search_function;
+
+ // TODO(sameeragarwal): Make this parameterizable over different
+ // line searches.
+ ArmijoLineSearch line_search;
+ LineSearch::Summary line_search_summary;
+
+ while (true) {
+ if (!RunCallbacks(options.callbacks, iteration_summary, summary)) {
+ return;
+ }
+
+ iteration_start_time = WallTimeInSeconds();
+ if (iteration_summary.iteration >= options.max_num_iterations) {
+ summary->termination_type = NO_CONVERGENCE;
+ VLOG(1) << "Terminating: Maximum number of iterations reached.";
+ break;
+ }
+
+ const double total_solver_time = iteration_start_time - start_time +
+ summary->preprocessor_time_in_seconds;
+ if (total_solver_time >= options.max_solver_time_in_seconds) {
+ summary->termination_type = NO_CONVERGENCE;
+ VLOG(1) << "Terminating: Maximum solver time reached.";
+ break;
+ }
+
+ iteration_summary = IterationSummary();
+ iteration_summary.iteration = summary->iterations.back().iteration + 1;
+
+ bool line_search_status = true;
+ if (iteration_summary.iteration == 1) {
+ current_state.search_direction = -current_state.gradient;
+ } else {
+ line_search_status = line_search_direction->NextDirection(
+ previous_state,
+ current_state,
+ &current_state.search_direction);
+ }
+
+ if (!line_search_status) {
+ LOG(WARNING) << "Line search direction computation failed. "
+ "Resorting to steepest descent.";
+ current_state.search_direction = -current_state.gradient;
+ }
+
+ line_search_function.Init(x, current_state.search_direction);
+ current_state.directional_derivative =
+ current_state.gradient.dot(current_state.search_direction);
+
+ // TODO(sameeragarwal): Refactor this into its own object and add
+ // explanations for the various choices.
+ const double initial_step_size = (iteration_summary.iteration == 1)
+ ? min(1.0, 1.0 / current_state.gradient_max_norm)
+ : min(1.0, 2.0 * (current_state.cost - previous_state.cost) /
+ current_state.directional_derivative);
+
+ line_search.Search(line_search_options,
+ initial_step_size,
+ current_state.cost,
+ current_state.directional_derivative,
+ &line_search_summary);
+
+ current_state.step_size = line_search_summary.optimal_step_size;
+ delta = current_state.step_size * current_state.search_direction;
+
+ previous_state = current_state;
+
+ // TODO(sameeragarwal): Collect stats.
+ if (!evaluator->Plus(x.data(), delta.data(), x_plus_delta.data()) ||
+ !Evaluate(evaluator, x_plus_delta, &current_state)) {
+ LOG(WARNING) << "Evaluation failed.";
+ } else {
+ x = x_plus_delta;
+ }
+
+ iteration_summary.gradient_max_norm = current_state.gradient_max_norm;
+ if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) {
+ summary->termination_type = GRADIENT_TOLERANCE;
+ VLOG(1) << "Terminating: Gradient tolerance reached."
+ << "Relative gradient max norm: "
+ << iteration_summary.gradient_max_norm / initial_gradient_max_norm
+ << " <= " << options.gradient_tolerance;
+ break;
+ }
+
+ iteration_summary.cost_change = previous_state.cost - current_state.cost;
+ const double absolute_function_tolerance =
+ options.function_tolerance * previous_state.cost;
+ if (fabs(iteration_summary.cost_change) < absolute_function_tolerance) {
+ VLOG(1) << "Terminating. Function tolerance reached. "
+ << "|cost_change|/cost: "
+ << fabs(iteration_summary.cost_change) / previous_state.cost
+ << " <= " << options.function_tolerance;
+ summary->termination_type = FUNCTION_TOLERANCE;
+ return;
+ }
+
+ iteration_summary.cost = current_state.cost + summary->fixed_cost;
+ iteration_summary.step_norm = delta.norm();
+ iteration_summary.step_is_valid = true;
+ iteration_summary.step_is_successful = true;
+ iteration_summary.step_norm = delta.norm();
+ iteration_summary.step_size = current_state.step_size;
+ iteration_summary.line_search_function_evaluations =
+ line_search_summary.num_evaluations;
+ iteration_summary.iteration_time_in_seconds =
+ WallTimeInSeconds() - iteration_start_time;
+ iteration_summary.cumulative_time_in_seconds =
+ WallTimeInSeconds() - start_time
+ + summary->preprocessor_time_in_seconds;
+
+ summary->iterations.push_back(iteration_summary);
+ }
+}
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_NO_LINE_SEARCH_MINIMIZER
diff --git a/extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.h b/extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.h
new file mode 100644
index 00000000000..59f5c3fb9a4
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.h
@@ -0,0 +1,80 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#ifndef CERES_INTERNAL_LINE_SEARCH_MINIMIZER_H_
+#define CERES_INTERNAL_LINE_SEARCH_MINIMIZER_H_
+
+#ifndef CERES_NO_LINE_SEARCH_MINIMIZER
+
+#include "ceres/minimizer.h"
+#include "ceres/solver.h"
+#include "ceres/types.h"
+#include "ceres/internal/eigen.h"
+#include "glog/logging.h"
+
+namespace ceres {
+namespace internal {
+
+// Generic line search minimization algorithm.
+//
+// For example usage, see SolverImpl::Minimize.
+class LineSearchMinimizer : public Minimizer {
+ public:
+ struct State {
+ State(int num_parameters,
+ int num_effective_parameters)
+ : cost(0.0),
+ gradient(num_effective_parameters),
+ gradient_squared_norm(0.0),
+ search_direction(num_effective_parameters),
+ directional_derivative(0.0),
+ step_size(0.0) {
+ }
+
+ double cost;
+ Vector gradient;
+ double gradient_squared_norm;
+ double gradient_max_norm;
+ Vector search_direction;
+ double directional_derivative;
+ double step_size;
+ };
+
+ ~LineSearchMinimizer() {}
+ virtual void Minimize(const Minimizer::Options& options,
+ double* parameters,
+ Solver::Summary* summary);
+};
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_NO_LINE_SEARCH_MINIMIZER
+#endif // CERES_INTERNAL_LINE_SEARCH_MINIMIZER_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc
index a91e254a663..6c886a1be38 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc
@@ -573,13 +573,14 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem3() {
return problem;
}
-static bool DumpLinearLeastSquaresProblemToConsole(const string& directory,
- int iteration,
- const SparseMatrix* A,
- const double* D,
- const double* b,
- const double* x,
- int num_eliminate_blocks) {
+namespace {
+bool DumpLinearLeastSquaresProblemToConsole(const string& directory,
+ int iteration,
+ const SparseMatrix* A,
+ const double* D,
+ const double* b,
+ const double* x,
+ int num_eliminate_blocks) {
CHECK_NOTNULL(A);
Matrix AA;
A->ToDenseMatrix(&AA);
@@ -601,13 +602,13 @@ static bool DumpLinearLeastSquaresProblemToConsole(const string& directory,
};
#ifndef CERES_NO_PROTOCOL_BUFFERS
-static bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
- int iteration,
- const SparseMatrix* A,
- const double* D,
- const double* b,
- const double* x,
- int num_eliminate_blocks) {
+bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
+ int iteration,
+ const SparseMatrix* A,
+ const double* D,
+ const double* b,
+ const double* x,
+ int num_eliminate_blocks) {
CHECK_NOTNULL(A);
LinearLeastSquaresProblemProto lsqp;
A->ToProto(lsqp.mutable_a());
@@ -641,13 +642,13 @@ static bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& director
return true;
}
#else
-static bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
- int iteration,
- const SparseMatrix* A,
- const double* D,
- const double* b,
- const double* x,
- int num_eliminate_blocks) {
+bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
+ int iteration,
+ const SparseMatrix* A,
+ const double* D,
+ const double* b,
+ const double* x,
+ int num_eliminate_blocks) {
LOG(ERROR) << "Dumping least squares problems is only "
<< "supported when Ceres is compiled with "
<< "protocol buffer support.";
@@ -655,9 +656,9 @@ static bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& director
}
#endif
-static void WriteArrayToFileOrDie(const string& filename,
- const double* x,
- const int size) {
+void WriteArrayToFileOrDie(const string& filename,
+ const double* x,
+ const int size) {
CHECK_NOTNULL(x);
VLOG(2) << "Writing array to: " << filename;
FILE* fptr = fopen(filename.c_str(), "w");
@@ -668,13 +669,13 @@ static void WriteArrayToFileOrDie(const string& filename,
fclose(fptr);
}
-static bool DumpLinearLeastSquaresProblemToTextFile(const string& directory,
- int iteration,
- const SparseMatrix* A,
- const double* D,
- const double* b,
- const double* x,
- int num_eliminate_blocks) {
+bool DumpLinearLeastSquaresProblemToTextFile(const string& directory,
+ int iteration,
+ const SparseMatrix* A,
+ const double* D,
+ const double* b,
+ const double* x,
+ int num_eliminate_blocks) {
CHECK_NOTNULL(A);
string format_string = JoinPath(directory,
"lm_iteration_%03d");
@@ -732,9 +733,10 @@ static bool DumpLinearLeastSquaresProblemToTextFile(const string& directory,
WriteStringToFileOrDie(matlab_script, matlab_filename);
return true;
}
+} // namespace
bool DumpLinearLeastSquaresProblem(const string& directory,
- int iteration,
+ int iteration,
DumpFormatType dump_format_type,
const SparseMatrix* A,
const double* D,
@@ -742,18 +744,18 @@ bool DumpLinearLeastSquaresProblem(const string& directory,
const double* x,
int num_eliminate_blocks) {
switch (dump_format_type) {
- case (CONSOLE):
+ case CONSOLE:
return DumpLinearLeastSquaresProblemToConsole(directory,
iteration,
A, D, b, x,
num_eliminate_blocks);
- case (PROTOBUF):
+ case PROTOBUF:
return DumpLinearLeastSquaresProblemToProtocolBuffer(
directory,
iteration,
A, D, b, x,
num_eliminate_blocks);
- case (TEXTFILE):
+ case TEXTFILE:
return DumpLinearLeastSquaresProblemToTextFile(directory,
iteration,
A, D, b, x,
diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.h b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.h
index 553cc0d3db3..c76ae91c7d8 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.h
@@ -74,7 +74,7 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem3();
// Write the linear least squares problem to disk. The exact format
// depends on dump_format_type.
bool DumpLinearLeastSquaresProblem(const string& directory,
- int iteration,
+ int iteration,
DumpFormatType dump_format_type,
const SparseMatrix* A,
const double* D,
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 31f88740b9f..f4bd0fb6f9f 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h
@@ -35,14 +35,16 @@
#define CERES_INTERNAL_LINEAR_SOLVER_H_
#include <cstddef>
-
-#include <glog/logging.h>
+#include <map>
+#include <vector>
#include "ceres/block_sparse_matrix.h"
#include "ceres/casts.h"
#include "ceres/compressed_row_sparse_matrix.h"
#include "ceres/dense_sparse_matrix.h"
+#include "ceres/execution_summary.h"
#include "ceres/triplet_sparse_matrix.h"
#include "ceres/types.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
@@ -76,11 +78,10 @@ class LinearSolver {
min_num_iterations(1),
max_num_iterations(1),
num_threads(1),
- num_eliminate_blocks(0),
residual_reset_period(10),
- row_block_size(Dynamic),
- e_block_size(Dynamic),
- f_block_size(Dynamic) {
+ row_block_size(Eigen::Dynamic),
+ e_block_size(Eigen::Dynamic),
+ f_block_size(Eigen::Dynamic) {
}
LinearSolverType type;
@@ -100,15 +101,23 @@ class LinearSolver {
// If possible, how many threads can the solver use.
int num_threads;
- // Eliminate 0 to num_eliminate_blocks - 1 from the Normal
- // equations to form a schur complement. Only used by the Schur
- // complement based solver. The most common use for this parameter
- // is in the case of structure from motion problems where we have
- // camera blocks and point blocks. Then setting the
- // num_eliminate_blocks to the number of points allows the solver
- // to use the Schur complement trick. For more details see the
- // description of this parameter in solver.h.
- int num_eliminate_blocks;
+ // Hints about the order in which the parameter blocks should be
+ // eliminated by the linear solver.
+ //
+ // For example if elimination_groups is a vector of size k, then
+ // the linear solver is informed that it should eliminate the
+ // parameter blocks 0 ... elimination_groups[0] - 1 first, and
+ // then elimination_groups[0] ... elimination_groups[1] - 1 and so
+ // on. Within each elimination group, the linear solver is free to
+ // choose how the parameter blocks are ordered. Different linear
+ // solvers have differing requirements on elimination_groups.
+ //
+ // The most common use is for Schur type solvers, where there
+ // should be at least two elimination groups and the first
+ // elimination group must form an independent set in the normal
+ // equations. The first elimination group corresponds to the
+ // num_eliminate_blocks in the Schur type solvers.
+ vector<int> elimination_groups;
// Iterative solvers, e.g. Preconditioned Conjugate Gradients
// maintain a cheap estimate of the residual which may become
@@ -247,6 +256,18 @@ class LinearSolver {
const PerSolveOptions& per_solve_options,
double* x) = 0;
+ // The following two methods return copies instead of references so
+ // that the base class implementation does not have to worry about
+ // life time issues. Further, these calls are not expected to be
+ // frequent or performance sensitive.
+ virtual map<string, int> CallStatistics() const {
+ return map<string, int>();
+ }
+
+ virtual map<string, double> TimeStatistics() const {
+ return map<string, double>();
+ }
+
// Factory
static LinearSolver* Create(const Options& options);
};
@@ -267,18 +288,29 @@ class TypedLinearSolver : public LinearSolver {
const double* b,
const LinearSolver::PerSolveOptions& per_solve_options,
double* x) {
+ ScopedExecutionTimer total_time("LinearSolver::Solve", &execution_summary_);
CHECK_NOTNULL(A);
CHECK_NOTNULL(b);
CHECK_NOTNULL(x);
return SolveImpl(down_cast<MatrixType*>(A), b, per_solve_options, x);
}
+ virtual map<string, int> CallStatistics() const {
+ return execution_summary_.calls();
+ }
+
+ virtual map<string, double> TimeStatistics() const {
+ return execution_summary_.times();
+ }
+
private:
virtual LinearSolver::Summary SolveImpl(
MatrixType* A,
const double* b,
const LinearSolver::PerSolveOptions& per_solve_options,
double* x) = 0;
+
+ ExecutionSummary execution_summary_;
};
// Linear solvers that depend on acccess to the low level structure of
diff --git a/extern/libmv/third_party/ceres/internal/ceres/low_rank_inverse_hessian.cc b/extern/libmv/third_party/ceres/internal/ceres/low_rank_inverse_hessian.cc
new file mode 100644
index 00000000000..3fe113f1afb
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/low_rank_inverse_hessian.cc
@@ -0,0 +1,109 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#include "ceres/internal/eigen.h"
+#include "ceres/low_rank_inverse_hessian.h"
+#include "glog/logging.h"
+
+namespace ceres {
+namespace internal {
+
+LowRankInverseHessian::LowRankInverseHessian(int num_parameters,
+ int max_num_corrections)
+ : num_parameters_(num_parameters),
+ max_num_corrections_(max_num_corrections),
+ num_corrections_(0),
+ diagonal_(1.0),
+ delta_x_history_(num_parameters, max_num_corrections),
+ delta_gradient_history_(num_parameters, max_num_corrections),
+ delta_x_dot_delta_gradient_(max_num_corrections) {
+}
+
+bool LowRankInverseHessian::Update(const Vector& delta_x,
+ const Vector& delta_gradient) {
+ const double delta_x_dot_delta_gradient = delta_x.dot(delta_gradient);
+ if (delta_x_dot_delta_gradient <= 1e-10) {
+ VLOG(2) << "Skipping LBFGS Update. " << delta_x_dot_delta_gradient;
+ return false;
+ }
+
+ if (num_corrections_ == max_num_corrections_) {
+ // TODO(sameeragarwal): This can be done more efficiently using
+ // a circular buffer/indexing scheme, but for simplicity we will
+ // do the expensive copy for now.
+ delta_x_history_.block(0, 0, num_parameters_, max_num_corrections_ - 2) =
+ delta_x_history_
+ .block(0, 1, num_parameters_, max_num_corrections_ - 1);
+
+ delta_gradient_history_
+ .block(0, 0, num_parameters_, max_num_corrections_ - 2) =
+ delta_gradient_history_
+ .block(0, 1, num_parameters_, max_num_corrections_ - 1);
+
+ delta_x_dot_delta_gradient_.head(num_corrections_ - 2) =
+ delta_x_dot_delta_gradient_.tail(num_corrections_ - 1);
+ } else {
+ ++num_corrections_;
+ }
+
+ delta_x_history_.col(num_corrections_ - 1) = delta_x;
+ delta_gradient_history_.col(num_corrections_ - 1) = delta_gradient;
+ delta_x_dot_delta_gradient_(num_corrections_ - 1) =
+ delta_x_dot_delta_gradient;
+ diagonal_ = delta_x_dot_delta_gradient / delta_gradient.squaredNorm();
+ return true;
+}
+
+void LowRankInverseHessian::RightMultiply(const double* x_ptr,
+ double* y_ptr) const {
+ ConstVectorRef gradient(x_ptr, num_parameters_);
+ VectorRef search_direction(y_ptr, num_parameters_);
+
+ search_direction = gradient;
+
+ Vector alpha(num_corrections_);
+
+ for (int i = num_corrections_ - 1; i >= 0; --i) {
+ alpha(i) = delta_x_history_.col(i).dot(search_direction) /
+ delta_x_dot_delta_gradient_(i);
+ search_direction -= alpha(i) * delta_gradient_history_.col(i);
+ }
+
+ search_direction *= diagonal_;
+
+ for (int i = 0; i < num_corrections_; ++i) {
+ const double beta = delta_gradient_history_.col(i).dot(search_direction) /
+ delta_x_dot_delta_gradient_(i);
+ search_direction += delta_x_history_.col(i) * (alpha(i) - beta);
+ }
+}
+
+} // namespace internal
+} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/low_rank_inverse_hessian.h b/extern/libmv/third_party/ceres/internal/ceres/low_rank_inverse_hessian.h
new file mode 100644
index 00000000000..6f3fc0c9d00
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/low_rank_inverse_hessian.h
@@ -0,0 +1,99 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Limited memory positive definite approximation to the inverse
+// Hessian, using the LBFGS algorithm
+
+#ifndef CERES_INTERNAL_LOW_RANK_INVERSE_HESSIAN_H_
+#define CERES_INTERNAL_LOW_RANK_INVERSE_HESSIAN_H_
+
+#include "ceres/internal/eigen.h"
+#include "ceres/linear_operator.h"
+
+namespace ceres {
+namespace internal {
+
+// LowRankInverseHessian is a positive definite approximation to the
+// Hessian using the limited memory variant of the
+// Broyden-Fletcher-Goldfarb-Shanno (BFGS)secant formula for
+// approximating the Hessian.
+//
+// Other update rules like the Davidon-Fletcher-Powell (DFP) are
+// possible, but the BFGS rule is considered the best performing one.
+//
+// The limited memory variant was developed by Nocedal and further
+// enhanced with scaling rule by Byrd, Nocedal and Schanbel.
+//
+// Nocedal, J. (1980). "Updating Quasi-Newton Matrices with Limited
+// Storage". Mathematics of Computation 35 (151): 773–782.
+//
+// Byrd, R. H.; Nocedal, J.; Schnabel, R. B. (1994).
+// "Representations of Quasi-Newton Matrices and their use in
+// Limited Memory Methods". Mathematical Programming 63 (4):
+class LowRankInverseHessian : public LinearOperator {
+ public:
+ // num_parameters is the row/column size of the Hessian.
+ // max_num_corrections is the rank of the Hessian approximation.
+ // The approximation uses:
+ // 2 * max_num_corrections * num_parameters + max_num_corrections
+ // doubles.
+ LowRankInverseHessian(int num_parameters, int max_num_corrections);
+ virtual ~LowRankInverseHessian() {}
+
+ // Update the low rank approximation. delta_x is the change in the
+ // domain of Hessian, and delta_gradient is the change in the
+ // gradient. The update copies the delta_x and delta_gradient
+ // vectors, and gets rid of the oldest delta_x and delta_gradient
+ // vectors if the number of corrections is already equal to
+ // max_num_corrections.
+ bool Update(const Vector& delta_x, const Vector& delta_gradient);
+
+ // LinearOperator interface
+ virtual void RightMultiply(const double* x, double* y) const;
+ virtual void LeftMultiply(const double* x, double* y) const {
+ RightMultiply(x, y);
+ }
+ virtual int num_rows() const { return num_parameters_; }
+ virtual int num_cols() const { return num_parameters_; }
+
+ private:
+ const int num_parameters_;
+ const int max_num_corrections_;
+ int num_corrections_;
+ double diagonal_;
+ Matrix delta_x_history_;
+ Matrix delta_gradient_history_;
+ Vector delta_x_dot_delta_gradient_;
+};
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_INTERNAL_LOW_RANK_INVERSE_HESSIAN_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/map_util.h b/extern/libmv/third_party/ceres/internal/ceres/map_util.h
index ddf1252f674..929c6b36982 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/map_util.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/map_util.h
@@ -35,6 +35,7 @@
#include <utility>
#include "ceres/internal/port.h"
+#include "glog/logging.h"
namespace ceres {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/minimizer.cc b/extern/libmv/third_party/ceres/internal/ceres/minimizer.cc
new file mode 100644
index 00000000000..2e2c15ac612
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/minimizer.cc
@@ -0,0 +1,67 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#include "ceres/minimizer.h"
+#include "ceres/types.h"
+#include "glog/logging.h"
+
+namespace ceres {
+namespace internal {
+
+Minimizer::~Minimizer() {}
+
+bool Minimizer::RunCallbacks(const vector<IterationCallback*> callbacks,
+ const IterationSummary& iteration_summary,
+ Solver::Summary* summary) {
+ CallbackReturnType status = SOLVER_CONTINUE;
+ int i = 0;
+ while (status == SOLVER_CONTINUE && i < callbacks.size()) {
+ status = (*callbacks[i])(iteration_summary);
+ ++i;
+ }
+ switch (status) {
+ case SOLVER_CONTINUE:
+ return true;
+ case SOLVER_TERMINATE_SUCCESSFULLY:
+ summary->termination_type = USER_SUCCESS;
+ VLOG(1) << "Terminating: User callback returned USER_SUCCESS.";
+ return false;
+ case SOLVER_ABORT:
+ summary->termination_type = USER_ABORT;
+ VLOG(1) << "Terminating: User callback returned USER_ABORT.";
+ return false;
+ default:
+ LOG(FATAL) << "Unknown type of user callback status";
+ }
+ return false;
+}
+
+} // namespace internal
+} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/minimizer.h b/extern/libmv/third_party/ceres/internal/ceres/minimizer.h
index cfc98a3ebd0..708974d63c2 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/minimizer.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/minimizer.h
@@ -32,8 +32,9 @@
#define CERES_INTERNAL_MINIMIZER_H_
#include <vector>
-#include "ceres/solver.h"
+#include "ceres/internal/port.h"
#include "ceres/iteration_callback.h"
+#include "ceres/solver.h"
namespace ceres {
namespace internal {
@@ -59,6 +60,7 @@ class Minimizer {
}
void Init(const Solver::Options& options) {
+ num_threads = options.num_threads;
max_num_iterations = options.max_num_iterations;
max_solver_time_in_seconds = options.max_solver_time_in_seconds;
max_step_solver_retries = 5;
@@ -74,18 +76,24 @@ class Minimizer {
lsqp_dump_directory = options.lsqp_dump_directory;
lsqp_iterations_to_dump = options.lsqp_iterations_to_dump;
lsqp_dump_format_type = options.lsqp_dump_format_type;
- num_eliminate_blocks = options.num_eliminate_blocks;
max_num_consecutive_invalid_steps =
options.max_num_consecutive_invalid_steps;
min_trust_region_radius = options.min_trust_region_radius;
+ line_search_direction_type = options.line_search_direction_type;
+ line_search_type = options.line_search_type;
+ nonlinear_conjugate_gradient_type =
+ options.nonlinear_conjugate_gradient_type;
+ max_lbfgs_rank = options.max_lbfgs_rank;
evaluator = NULL;
trust_region_strategy = NULL;
jacobian = NULL;
callbacks = options.callbacks;
+ inner_iteration_minimizer = NULL;
}
int max_num_iterations;
double max_solver_time_in_seconds;
+ int num_threads;
// Number of times the linear solver should be retried in case of
// numerical failure. The retries are done by exponentially scaling up
@@ -104,9 +112,12 @@ class Minimizer {
vector<int> lsqp_iterations_to_dump;
DumpFormatType lsqp_dump_format_type;
string lsqp_dump_directory;
- int num_eliminate_blocks;
int max_num_consecutive_invalid_steps;
int min_trust_region_radius;
+ LineSearchDirectionType line_search_direction_type;
+ LineSearchType line_search_type;
+ NonlinearConjugateGradientType nonlinear_conjugate_gradient_type;
+ int max_lbfgs_rank;
// List of callbacks that are executed by the Minimizer at the end
// of each iteration.
@@ -128,10 +139,15 @@ class Minimizer {
// and will remain constant for the life time of the
// optimization. The Options struct does not own this pointer.
SparseMatrix* jacobian;
+
+ Minimizer* inner_iteration_minimizer;
};
- virtual ~Minimizer() {}
+ static bool RunCallbacks(const vector<IterationCallback*> callbacks,
+ const IterationSummary& iteration_summary,
+ Solver::Summary* summary);
+ virtual ~Minimizer();
// Note: The minimizer is expected to update the state of the
// parameters array every iteration. This is required for the
// StateUpdatingCallback to work.
diff --git a/extern/libmv/third_party/ceres/internal/ceres/mutex.h b/extern/libmv/third_party/ceres/internal/ceres/mutex.h
index 5090a71b78d..0c48ed352b5 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/mutex.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/mutex.h
@@ -107,10 +107,12 @@
# define _WIN32_WINNT 0x0400
# endif
# endif
+// Unfortunately, windows.h defines a bunch of macros with common
+// names. Two in particular need avoiding: ERROR and min/max.
// To avoid macro definition of ERROR.
-# define CERES_NOGDI
+# define NOGDI
// To avoid macro definition of min/max.
-# define CERES_NOMINMAX
+# define NOMINMAX
# include <windows.h>
typedef CRITICAL_SECTION MutexType;
#elif defined(CERES_HAVE_PTHREAD) && defined(CERES_HAVE_RWLOCK)
@@ -273,7 +275,8 @@ void Mutex::ReaderUnlock() { Unlock(); }
// "MutexLock(x) COMPILE_ASSERT(false)". To work around this, "Ceres" is
// prefixed to the class names; this permits defining the classes.
-// CeresMutexLock(mu) acquires mu when constructed and releases it when destroyed.
+// CeresMutexLock(mu) acquires mu when constructed and releases it
+// when destroyed.
class CeresMutexLock {
public:
explicit CeresMutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); }
diff --git a/extern/libmv/third_party/ceres/internal/ceres/parameter_block.h b/extern/libmv/third_party/ceres/internal/ceres/parameter_block.h
index f20805ca873..b1e8d938b8a 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/parameter_block.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/parameter_block.h
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@
#include <cstdlib>
#include <string>
#include "ceres/array_utils.h"
+#include "ceres/collections_port.h"
#include "ceres/integral_types.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/port.h"
@@ -46,6 +47,7 @@ namespace ceres {
namespace internal {
class ProblemImpl;
+class ResidualBlock;
// The parameter block encodes the location of the user's original value, and
// also the "current state" of the parameter. The evaluator uses whatever is in
@@ -58,13 +60,29 @@ class ProblemImpl;
// responsible for the proper disposal of the local parameterization.
class ParameterBlock {
public:
- ParameterBlock(double* user_state, int size) {
- Init(user_state, size, NULL);
+ // TODO(keir): Decide what data structure is best here. Should this be a set?
+ // Probably not, because sets are memory inefficient. However, if it's a
+ // vector, you can get into pathological linear performance when removing a
+ // residual block from a problem where all the residual blocks depend on one
+ // parameter; for example, shared focal length in a bundle adjustment
+ // problem. It might be worth making a custom structure that is just an array
+ // when it is small, but transitions to a hash set when it has more elements.
+ //
+ // For now, use a hash set.
+ typedef HashSet<ResidualBlock*> ResidualBlockSet;
+
+ // Create a parameter block with the user state, size, and index specified.
+ // The size is the size of the parameter block and the index is the position
+ // of the parameter block inside a Program (if any).
+ ParameterBlock(double* user_state, int size, int index) {
+ Init(user_state, size, index, NULL);
}
+
ParameterBlock(double* user_state,
int size,
+ int index,
LocalParameterization* local_parameterization) {
- Init(user_state, size, local_parameterization);
+ Init(user_state, size, index, local_parameterization);
}
// The size of the parameter block.
@@ -187,12 +205,43 @@ class ParameterBlock {
delta_offset_);
}
+ void EnableResidualBlockDependencies() {
+ CHECK(residual_blocks_.get() == NULL)
+ << "Ceres bug: There is already a residual block collection "
+ << "for parameter block: " << ToString();
+ residual_blocks_.reset(new ResidualBlockSet);
+ }
+
+ void AddResidualBlock(ResidualBlock* residual_block) {
+ CHECK(residual_blocks_.get() != NULL)
+ << "Ceres bug: The residual block collection is null for parameter "
+ << "block: " << ToString();
+ residual_blocks_->insert(residual_block);
+ }
+
+ void RemoveResidualBlock(ResidualBlock* residual_block) {
+ CHECK(residual_blocks_.get() != NULL)
+ << "Ceres bug: The residual block collection is null for parameter "
+ << "block: " << ToString();
+ CHECK(residual_blocks_->find(residual_block) != residual_blocks_->end())
+ << "Ceres bug: Missing residual for parameter block: " << ToString();
+ residual_blocks_->erase(residual_block);
+ }
+
+ // This is only intended for iterating; perhaps this should only expose
+ // .begin() and .end().
+ ResidualBlockSet* mutable_residual_blocks() {
+ return residual_blocks_.get();
+ }
+
private:
void Init(double* user_state,
int size,
+ int index,
LocalParameterization* local_parameterization) {
user_state_ = user_state;
size_ = size;
+ index_ = index;
is_constant_ = false;
state_ = user_state_;
@@ -201,7 +250,6 @@ class ParameterBlock {
SetParameterization(local_parameterization);
}
- index_ = -1;
state_offset_ = -1;
delta_offset_ = -1;
}
@@ -261,6 +309,9 @@ class ParameterBlock {
// The offset of this parameter block inside a larger delta vector.
int32 delta_offset_;
+ // If non-null, contains the residual blocks this parameter block is in.
+ scoped_ptr<ResidualBlockSet> residual_blocks_;
+
// Necessary so ProblemImpl can clean up the parameterizations.
friend class ProblemImpl;
};
diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc b/extern/libmv/third_party/ceres/internal/ceres/parameter_block_ordering.cc
index 1cdff4e6dec..e8f626f8e80 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/parameter_block_ordering.cc
@@ -28,7 +28,7 @@
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
-#include "ceres/schur_ordering.h"
+#include "ceres/parameter_block_ordering.h"
#include "ceres/graph.h"
#include "ceres/graph_algorithms.h"
@@ -46,8 +46,7 @@ int ComputeSchurOrdering(const Program& program,
vector<ParameterBlock*>* ordering) {
CHECK_NOTNULL(ordering)->clear();
- scoped_ptr<Graph< ParameterBlock*> > graph(
- CHECK_NOTNULL(CreateHessianGraph(program)));
+ scoped_ptr<Graph< ParameterBlock*> > graph(CreateHessianGraph(program));
int independent_set_size = IndependentSetOrdering(*graph, ordering);
const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks();
@@ -62,9 +61,31 @@ int ComputeSchurOrdering(const Program& program,
return independent_set_size;
}
+void ComputeRecursiveIndependentSetOrdering(const Program& program,
+ ParameterBlockOrdering* ordering) {
+ CHECK_NOTNULL(ordering)->Clear();
+ const vector<ParameterBlock*> parameter_blocks = program.parameter_blocks();
+ scoped_ptr<Graph< ParameterBlock*> > graph(CreateHessianGraph(program));
+
+ int num_covered = 0;
+ int round = 0;
+ while (num_covered < parameter_blocks.size()) {
+ vector<ParameterBlock*> independent_set_ordering;
+ const int independent_set_size =
+ IndependentSetOrdering(*graph, &independent_set_ordering);
+ for (int i = 0; i < independent_set_size; ++i) {
+ ParameterBlock* parameter_block = independent_set_ordering[i];
+ ordering->AddElementToGroup(parameter_block->mutable_user_state(), round);
+ graph->RemoveVertex(parameter_block);
+ }
+ num_covered += independent_set_size;
+ ++round;
+ }
+}
+
Graph<ParameterBlock*>*
CreateHessianGraph(const Program& program) {
- Graph<ParameterBlock*>* graph = new Graph<ParameterBlock*>;
+ Graph<ParameterBlock*>* graph = CHECK_NOTNULL(new Graph<ParameterBlock*>);
const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks();
for (int i = 0; i < parameter_blocks.size(); ++i) {
ParameterBlock* parameter_block = parameter_blocks[i];
diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.h b/extern/libmv/third_party/ceres/internal/ceres/parameter_block_ordering.h
index 1f9a4ff354f..a5277a44c70 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/parameter_block_ordering.h
@@ -27,14 +27,12 @@
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
-//
-// Compute a parameter block ordering for use with the Schur
-// complement based algorithms.
-#ifndef CERES_INTERNAL_SCHUR_ORDERING_H_
-#define CERES_INTERNAL_SCHUR_ORDERING_H_
+#ifndef CERES_INTERNAL_PARAMETER_BLOCK_ORDERING_H_
+#define CERES_INTERNAL_PARAMETER_BLOCK_ORDERING_H_
#include <vector>
+#include "ceres/ordered_groups.h"
#include "ceres/graph.h"
#include "ceres/types.h"
@@ -60,6 +58,12 @@ class ParameterBlock;
int ComputeSchurOrdering(const Program& program,
vector<ParameterBlock* >* ordering);
+// Use an approximate independent set ordering to decompose the
+// parameter blocks of a problem in a sequence of independent
+// sets. The ordering covers all the non-constant parameter blocks in
+// the program.
+void ComputeRecursiveIndependentSetOrdering(const Program& program,
+ ParameterBlockOrdering* ordering);
// Builds a graph on the parameter blocks of a Problem, whose
// structure reflects the sparsity structure of the Hessian. Each
@@ -71,4 +75,4 @@ Graph<ParameterBlock*>* CreateHessianGraph(const Program& program);
} // namespace internal
} // namespace ceres
-#endif // CERES_INTERNAL_SCHUR_ORDERING_H_
+#endif // CERES_INTERNAL_PARAMETER_BLOCK_ORDERING_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/polynomial.cc
index 20c01566a89..3238b89670e 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/polynomial.cc
@@ -27,11 +27,14 @@
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: moll.markus@arcor.de (Markus Moll)
+// sameeragarwal@google.com (Sameer Agarwal)
-#include "ceres/polynomial_solver.h"
+#include "ceres/polynomial.h"
#include <cmath>
#include <cstddef>
+#include <vector>
+
#include "Eigen/Dense"
#include "ceres/internal/port.h"
#include "glog/logging.h"
@@ -159,8 +162,7 @@ bool FindPolynomialRoots(const Vector& polynomial_in,
BalanceCompanionMatrix(&companion_matrix);
// Find its (complex) eigenvalues.
- Eigen::EigenSolver<Matrix> solver(companion_matrix,
- Eigen::EigenvaluesOnly);
+ Eigen::EigenSolver<Matrix> solver(companion_matrix, false);
if (solver.info() != Eigen::Success) {
LOG(ERROR) << "Failed to extract eigenvalues from companion matrix.";
return false;
@@ -180,5 +182,138 @@ bool FindPolynomialRoots(const Vector& polynomial_in,
return true;
}
+Vector DifferentiatePolynomial(const Vector& polynomial) {
+ const int degree = polynomial.rows() - 1;
+ CHECK_GE(degree, 0);
+
+ // Degree zero polynomials are constants, and their derivative does
+ // not result in a smaller degree polynomial, just a degree zero
+ // polynomial with value zero.
+ if (degree == 0) {
+ return Eigen::VectorXd::Zero(1);
+ }
+
+ Vector derivative(degree);
+ for (int i = 0; i < degree; ++i) {
+ derivative(i) = (degree - i) * polynomial(i);
+ }
+
+ return derivative;
+}
+
+void MinimizePolynomial(const Vector& polynomial,
+ const double x_min,
+ const double x_max,
+ double* optimal_x,
+ double* optimal_value) {
+ // Find the minimum of the polynomial at the two ends.
+ //
+ // We start by inspecting the middle of the interval. Technically
+ // this is not needed, but we do this to make this code as close to
+ // the minFunc package as possible.
+ *optimal_x = (x_min + x_max) / 2.0;
+ *optimal_value = EvaluatePolynomial(polynomial, *optimal_x);
+
+ const double x_min_value = EvaluatePolynomial(polynomial, x_min);
+ if (x_min_value < *optimal_value) {
+ *optimal_value = x_min_value;
+ *optimal_x = x_min;
+ }
+
+ const double x_max_value = EvaluatePolynomial(polynomial, x_max);
+ if (x_max_value < *optimal_value) {
+ *optimal_value = x_max_value;
+ *optimal_x = x_max;
+ }
+
+ // If the polynomial is linear or constant, we are done.
+ if (polynomial.rows() <= 2) {
+ return;
+ }
+
+ const Vector derivative = DifferentiatePolynomial(polynomial);
+ Vector roots_real;
+ if (!FindPolynomialRoots(derivative, &roots_real, NULL)) {
+ LOG(WARNING) << "Unable to find the critical points of "
+ << "the interpolating polynomial.";
+ return;
+ }
+
+ // This is a bit of an overkill, as some of the roots may actually
+ // have a complex part, but its simpler to just check these values.
+ for (int i = 0; i < roots_real.rows(); ++i) {
+ const double root = roots_real(i);
+ if ((root < x_min) || (root > x_max)) {
+ continue;
+ }
+
+ const double value = EvaluatePolynomial(polynomial, root);
+ if (value < *optimal_value) {
+ *optimal_value = value;
+ *optimal_x = root;
+ }
+ }
+}
+
+Vector FindInterpolatingPolynomial(const vector<FunctionSample>& samples) {
+ const int num_samples = samples.size();
+ int num_constraints = 0;
+ for (int i = 0; i < num_samples; ++i) {
+ if (samples[i].value_is_valid) {
+ ++num_constraints;
+ }
+ if (samples[i].gradient_is_valid) {
+ ++num_constraints;
+ }
+ }
+
+ const int degree = num_constraints - 1;
+ Matrix lhs = Matrix::Zero(num_constraints, num_constraints);
+ Vector rhs = Vector::Zero(num_constraints);
+
+ int row = 0;
+ for (int i = 0; i < num_samples; ++i) {
+ const FunctionSample& sample = samples[i];
+ if (sample.value_is_valid) {
+ for (int j = 0; j <= degree; ++j) {
+ lhs(row, j) = pow(sample.x, degree - j);
+ }
+ rhs(row) = sample.value;
+ ++row;
+ }
+
+ if (sample.gradient_is_valid) {
+ for (int j = 0; j < degree; ++j) {
+ lhs(row, j) = (degree - j) * pow(sample.x, degree - j - 1);
+ }
+ rhs(row) = sample.gradient;
+ ++row;
+ }
+ }
+
+ return lhs.fullPivLu().solve(rhs);
+}
+
+void MinimizeInterpolatingPolynomial(const vector<FunctionSample>& samples,
+ double x_min,
+ double x_max,
+ double* optimal_x,
+ double* optimal_value) {
+ const Vector polynomial = FindInterpolatingPolynomial(samples);
+ MinimizePolynomial(polynomial, x_min, x_max, optimal_x, optimal_value);
+ for (int i = 0; i < samples.size(); ++i) {
+ const FunctionSample& sample = samples[i];
+ if ((sample.x < x_min) || (sample.x > x_max)) {
+ continue;
+ }
+
+ const double value = EvaluatePolynomial(polynomial, sample.x);
+ if (value < *optimal_value) {
+ *optimal_x = sample.x;
+ *optimal_value = value;
+ }
+ }
+}
+
} // namespace internal
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/polynomial.h b/extern/libmv/third_party/ceres/internal/ceres/polynomial.h
new file mode 100644
index 00000000000..42ffdcb13c5
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/polynomial.h
@@ -0,0 +1,134 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: moll.markus@arcor.de (Markus Moll)
+// sameeragarwal@google.com (Sameer Agarwal)
+
+#ifndef CERES_INTERNAL_POLYNOMIAL_SOLVER_H_
+#define CERES_INTERNAL_POLYNOMIAL_SOLVER_H_
+
+#include <vector>
+#include "ceres/internal/eigen.h"
+#include "ceres/internal/port.h"
+
+namespace ceres {
+namespace internal {
+
+// All polynomials are assumed to be the form
+//
+// sum_{i=0}^N polynomial(i) x^{N-i}.
+//
+// and are given by a vector of coefficients of size N + 1.
+
+// Evaluate the polynomial at x using the Horner scheme.
+inline double EvaluatePolynomial(const Vector& polynomial, double x) {
+ double v = 0.0;
+ for (int i = 0; i < polynomial.size(); ++i) {
+ v = v * x + polynomial(i);
+ }
+ return v;
+}
+
+// Use the companion matrix eigenvalues to determine the roots of the
+// polynomial.
+//
+// This function returns true on success, false otherwise.
+// Failure indicates that the polynomial is invalid (of size 0) or
+// that the eigenvalues of the companion matrix could not be computed.
+// On failure, a more detailed message will be written to LOG(ERROR).
+// If real is not NULL, the real parts of the roots will be returned in it.
+// Likewise, if imaginary is not NULL, imaginary parts will be returned in it.
+bool FindPolynomialRoots(const Vector& polynomial,
+ Vector* real,
+ Vector* imaginary);
+
+// Return the derivative of the given polynomial. It is assumed that
+// the input polynomial is at least of degree zero.
+Vector DifferentiatePolynomial(const Vector& polynomial);
+
+// Find the minimum value of the polynomial in the interval [x_min,
+// x_max]. The minimum is obtained by computing all the roots of the
+// derivative of the input polynomial. All real roots within the
+// interval [x_min, x_max] are considered as well as the end points
+// x_min and x_max. Since polynomials are differentiable functions,
+// this ensures that the true minimum is found.
+void MinimizePolynomial(const Vector& polynomial,
+ double x_min,
+ double x_max,
+ double* optimal_x,
+ double* optimal_value);
+
+// Structure for storing sample values of a function.
+//
+// Clients can use this struct to communicate the value of the
+// function and or its gradient at a given point x.
+struct FunctionSample {
+ FunctionSample()
+ : x(0.0),
+ value(0.0),
+ value_is_valid(false),
+ gradient(0.0),
+ gradient_is_valid(false) {
+ }
+
+ double x;
+ double value; // value = f(x)
+ bool value_is_valid;
+ double gradient; // gradient = f'(x)
+ bool gradient_is_valid;
+};
+
+// Given a set of function value and/or gradient samples, find a
+// polynomial whose value and gradients are exactly equal to the ones
+// in samples.
+//
+// Generally speaking,
+//
+// degree = # values + # gradients - 1
+//
+// Of course its possible to sample a polynomial any number of times,
+// in which case, generally speaking the spurious higher order
+// coefficients will be zero.
+Vector FindInterpolatingPolynomial(const vector<FunctionSample>& samples);
+
+// Interpolate the function described by samples with a polynomial,
+// and minimize it on the interval [x_min, x_max]. Depending on the
+// input samples, it is possible that the interpolation or the root
+// finding algorithms may fail due to numerical difficulties. But the
+// function is guaranteed to return its best guess of an answer, by
+// considering the samples and the end points as possible solutions.
+void MinimizeInterpolatingPolynomial(const vector<FunctionSample>& samples,
+ double x_min,
+ double x_max,
+ double* optimal_x,
+ double* optimal_value);
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_INTERNAL_POLYNOMIAL_SOLVER_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/preconditioner.cc b/extern/libmv/third_party/ceres/internal/ceres/preconditioner.cc
new file mode 100644
index 00000000000..05e539f9fb1
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/preconditioner.cc
@@ -0,0 +1,63 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#include "ceres/preconditioner.h"
+#include "glog/logging.h"
+
+namespace ceres {
+namespace internal {
+
+Preconditioner::~Preconditioner() {
+}
+
+SparseMatrixPreconditionerWrapper::SparseMatrixPreconditionerWrapper(
+ const SparseMatrix* matrix)
+ : matrix_(CHECK_NOTNULL(matrix)) {
+}
+
+SparseMatrixPreconditionerWrapper::~SparseMatrixPreconditionerWrapper() {
+}
+
+bool SparseMatrixPreconditionerWrapper::Update(const BlockSparseMatrixBase& A,
+ const double* D) {
+ return true;
+}
+
+void SparseMatrixPreconditionerWrapper::RightMultiply(const double* x,
+ double* y) const {
+ matrix_->RightMultiply(x, y);
+}
+
+int SparseMatrixPreconditionerWrapper::num_rows() const {
+ return matrix_->num_rows();
+}
+
+} // namespace internal
+} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/preconditioner.h b/extern/libmv/third_party/ceres/internal/ceres/preconditioner.h
new file mode 100644
index 00000000000..bfc8464db17
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/preconditioner.h
@@ -0,0 +1,148 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#ifndef CERES_INTERNAL_PRECONDITIONER_H_
+#define CERES_INTERNAL_PRECONDITIONER_H_
+
+#include <vector>
+#include "ceres/linear_operator.h"
+#include "ceres/sparse_matrix.h"
+
+namespace ceres {
+namespace internal {
+
+class BlockSparseMatrixBase;
+class SparseMatrix;
+
+class Preconditioner : public LinearOperator {
+ public:
+ struct Options {
+ Options()
+ : type(JACOBI),
+ sparse_linear_algebra_library(SUITE_SPARSE),
+ use_block_amd(true),
+ num_threads(1),
+ row_block_size(Eigen::Dynamic),
+ e_block_size(Eigen::Dynamic),
+ f_block_size(Eigen::Dynamic) {
+ }
+
+ PreconditionerType type;
+
+ SparseLinearAlgebraLibraryType sparse_linear_algebra_library;
+
+ // See solver.h for explanation of this option.
+ bool use_block_amd;
+
+ // If possible, how many threads the preconditioner can use.
+ int num_threads;
+
+ // Hints about the order in which the parameter blocks should be
+ // eliminated by the linear solver.
+ //
+ // For example if elimination_groups is a vector of size k, then
+ // the linear solver is informed that it should eliminate the
+ // parameter blocks 0 ... elimination_groups[0] - 1 first, and
+ // then elimination_groups[0] ... elimination_groups[1] - 1 and so
+ // on. Within each elimination group, the linear solver is free to
+ // choose how the parameter blocks are ordered. Different linear
+ // solvers have differing requirements on elimination_groups.
+ //
+ // The most common use is for Schur type solvers, where there
+ // should be at least two elimination groups and the first
+ // elimination group must form an independent set in the normal
+ // equations. The first elimination group corresponds to the
+ // num_eliminate_blocks in the Schur type solvers.
+ vector<int> elimination_groups;
+
+ // If the block sizes in a BlockSparseMatrix are fixed, then in
+ // some cases the Schur complement based solvers can detect and
+ // specialize on them.
+ //
+ // It is expected that these parameters are set programmatically
+ // rather than manually.
+ //
+ // Please see schur_complement_solver.h and schur_eliminator.h for
+ // more details.
+ int row_block_size;
+ int e_block_size;
+ int f_block_size;
+ };
+
+ virtual ~Preconditioner();
+
+ // Update the numerical value of the preconditioner for the linear
+ // system:
+ //
+ // | A | x = |b|
+ // |diag(D)| |0|
+ //
+ // for some vector b. It is important that the matrix A have the
+ // same block structure as the one used to construct this object.
+ //
+ // D can be NULL, in which case its interpreted as a diagonal matrix
+ // of size zero.
+ virtual bool Update(const BlockSparseMatrixBase& A, const double* D) = 0;
+
+ // LinearOperator interface. Since the operator is symmetric,
+ // LeftMultiply and num_cols are just calls to RightMultiply and
+ // num_rows respectively. Update() must be called before
+ // RightMultiply can be called.
+ virtual void RightMultiply(const double* x, double* y) const = 0;
+ virtual void LeftMultiply(const double* x, double* y) const {
+ return RightMultiply(x, y);
+ }
+
+ virtual int num_rows() const = 0;
+ virtual int num_cols() const {
+ return num_rows();
+ }
+};
+
+// Wrap a SparseMatrix object as a preconditioner.
+class SparseMatrixPreconditionerWrapper : public Preconditioner {
+ public:
+ // Wrapper does NOT take ownership of the matrix pointer.
+ explicit SparseMatrixPreconditionerWrapper(const SparseMatrix* matrix);
+ virtual ~SparseMatrixPreconditionerWrapper();
+
+ // Preconditioner interface
+ virtual bool Update(const BlockSparseMatrixBase& A, const double* D);
+ virtual void RightMultiply(const double* x, double* y) const;
+ virtual int num_rows() const;
+
+ private:
+ const SparseMatrix* matrix_;
+};
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_INTERNAL_PRECONDITIONER_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem.cc b/extern/libmv/third_party/ceres/internal/ceres/problem.cc
index b8c25d9db84..43e78835b15 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/problem.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/problem.cc
@@ -32,12 +32,11 @@
#include "ceres/problem.h"
#include <vector>
+#include "ceres/crs_matrix.h"
#include "ceres/problem_impl.h"
namespace ceres {
-class ResidualBlock;
-
Problem::Problem() : problem_impl_(new internal::ProblemImpl) {}
Problem::Problem(const Problem::Options& options)
: problem_impl_(new internal::ProblemImpl(options)) {}
@@ -106,6 +105,47 @@ ResidualBlockId Problem::AddResidualBlock(
x0, x1, x2, x3, x4, x5);
}
+ResidualBlockId Problem::AddResidualBlock(
+ CostFunction* cost_function,
+ LossFunction* loss_function,
+ double* x0, double* x1, double* x2, double* x3, double* x4, double* x5,
+ double* x6) {
+ return problem_impl_->AddResidualBlock(cost_function,
+ loss_function,
+ x0, x1, x2, x3, x4, x5, x6);
+}
+
+ResidualBlockId Problem::AddResidualBlock(
+ CostFunction* cost_function,
+ LossFunction* loss_function,
+ double* x0, double* x1, double* x2, double* x3, double* x4, double* x5,
+ double* x6, double* x7) {
+ return problem_impl_->AddResidualBlock(cost_function,
+ loss_function,
+ x0, x1, x2, x3, x4, x5, x6, x7);
+}
+
+ResidualBlockId Problem::AddResidualBlock(
+ CostFunction* cost_function,
+ LossFunction* loss_function,
+ double* x0, double* x1, double* x2, double* x3, double* x4, double* x5,
+ double* x6, double* x7, double* x8) {
+ return problem_impl_->AddResidualBlock(cost_function,
+ loss_function,
+ x0, x1, x2, x3, x4, x5, x6, x7, x8);
+}
+
+ResidualBlockId Problem::AddResidualBlock(
+ CostFunction* cost_function,
+ LossFunction* loss_function,
+ double* x0, double* x1, double* x2, double* x3, double* x4, double* x5,
+ double* x6, double* x7, double* x8, double* x9) {
+ return problem_impl_->AddResidualBlock(
+ cost_function,
+ loss_function,
+ x0, x1, x2, x3, x4, x5, x6, x7, x8, x9);
+}
+
void Problem::AddParameterBlock(double* values, int size) {
problem_impl_->AddParameterBlock(values, size);
}
@@ -116,6 +156,14 @@ void Problem::AddParameterBlock(double* values,
problem_impl_->AddParameterBlock(values, size, local_parameterization);
}
+void Problem::RemoveResidualBlock(ResidualBlockId residual_block) {
+ problem_impl_->RemoveResidualBlock(residual_block);
+}
+
+void Problem::RemoveParameterBlock(double* values) {
+ problem_impl_->RemoveParameterBlock(values);
+}
+
void Problem::SetParameterBlockConstant(double* values) {
problem_impl_->SetParameterBlockConstant(values);
}
@@ -130,6 +178,18 @@ void Problem::SetParameterization(
problem_impl_->SetParameterization(values, local_parameterization);
}
+bool Problem::Evaluate(const EvaluateOptions& evaluate_options,
+ double* cost,
+ vector<double>* residuals,
+ vector<double>* gradient,
+ CRSMatrix* jacobian) {
+ return problem_impl_->Evaluate(evaluate_options,
+ cost,
+ residuals,
+ gradient,
+ jacobian);
+}
+
int Problem::NumParameterBlocks() const {
return problem_impl_->NumParameterBlocks();
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc
index c186f527be8..69d672ed9c6 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc
@@ -33,11 +33,16 @@
#include <algorithm>
#include <cstddef>
+#include <iterator>
#include <set>
#include <string>
#include <utility>
#include <vector>
+#include "ceres/casts.h"
+#include "ceres/compressed_row_sparse_matrix.h"
#include "ceres/cost_function.h"
+#include "ceres/crs_matrix.h"
+#include "ceres/evaluator.h"
#include "ceres/loss_function.h"
#include "ceres/map_util.h"
#include "ceres/parameter_block.h"
@@ -52,18 +57,28 @@ namespace internal {
typedef map<double*, internal::ParameterBlock*> ParameterMap;
+namespace {
+internal::ParameterBlock* FindParameterBlockOrDie(
+ const ParameterMap& parameter_map,
+ double* parameter_block) {
+ ParameterMap::const_iterator it = parameter_map.find(parameter_block);
+ CHECK(it != parameter_map.end())
+ << "Parameter block not found: " << parameter_block;
+ return it->second;
+}
+
// Returns true if two regions of memory, a and b, with sizes size_a and size_b
// respectively, overlap.
-static bool RegionsAlias(const double* a, int size_a,
- const double* b, int size_b) {
+bool RegionsAlias(const double* a, int size_a,
+ const double* b, int size_b) {
return (a < b) ? b < (a + size_a)
: a < (b + size_b);
}
-static void CheckForNoAliasing(double* existing_block,
- int existing_block_size,
- double* new_block,
- int new_block_size) {
+void CheckForNoAliasing(double* existing_block,
+ int existing_block_size,
+ double* new_block,
+ int new_block_size) {
CHECK(!RegionsAlias(existing_block, existing_block_size,
new_block, new_block_size))
<< "Aliasing detected between existing parameter block at memory "
@@ -73,54 +88,105 @@ static void CheckForNoAliasing(double* existing_block,
<< "size " << new_block_size << ".";
}
-static ParameterBlock* InternalAddParameterBlock(
- double* values,
- int size,
- ParameterMap* parameter_map,
- vector<ParameterBlock*>* parameter_blocks) {
- CHECK(values) << "Null pointer passed to AddParameterBlock for a parameter "
- << "with size " << size;
+} // namespace
+
+ParameterBlock* ProblemImpl::InternalAddParameterBlock(double* values,
+ int size) {
+ CHECK(values != NULL) << "Null pointer passed to AddParameterBlock "
+ << "for a parameter with size " << size;
// Ignore the request if there is a block for the given pointer already.
- ParameterMap::iterator it = parameter_map->find(values);
- if (it != parameter_map->end()) {
- int existing_size = it->second->Size();
- CHECK(size == existing_size)
- << "Tried adding a parameter block with the same double pointer, "
- << values << ", twice, but with different block sizes. Original "
- << "size was " << existing_size << " but new size is "
- << size;
+ ParameterMap::iterator it = parameter_block_map_.find(values);
+ if (it != parameter_block_map_.end()) {
+ if (!options_.disable_all_safety_checks) {
+ int existing_size = it->second->Size();
+ CHECK(size == existing_size)
+ << "Tried adding a parameter block with the same double pointer, "
+ << values << ", twice, but with different block sizes. Original "
+ << "size was " << existing_size << " but new size is "
+ << size;
+ }
return it->second;
}
- // Before adding the parameter block, also check that it doesn't alias any
- // other parameter blocks.
- if (!parameter_map->empty()) {
- ParameterMap::iterator lb = parameter_map->lower_bound(values);
-
- // If lb is not the first block, check the previous block for aliasing.
- if (lb != parameter_map->begin()) {
- ParameterMap::iterator previous = lb;
- --previous;
- CheckForNoAliasing(previous->first,
- previous->second->Size(),
- values,
- size);
- }
- // If lb is not off the end, check lb for aliasing.
- if (lb != parameter_map->end()) {
- CheckForNoAliasing(lb->first,
- lb->second->Size(),
- values,
- size);
+ if (!options_.disable_all_safety_checks) {
+ // Before adding the parameter block, also check that it doesn't alias any
+ // other parameter blocks.
+ if (!parameter_block_map_.empty()) {
+ ParameterMap::iterator lb = parameter_block_map_.lower_bound(values);
+
+ // If lb is not the first block, check the previous block for aliasing.
+ if (lb != parameter_block_map_.begin()) {
+ ParameterMap::iterator previous = lb;
+ --previous;
+ CheckForNoAliasing(previous->first,
+ previous->second->Size(),
+ values,
+ size);
+ }
+
+ // If lb is not off the end, check lb for aliasing.
+ if (lb != parameter_block_map_.end()) {
+ CheckForNoAliasing(lb->first,
+ lb->second->Size(),
+ values,
+ size);
+ }
}
}
- ParameterBlock* new_parameter_block = new ParameterBlock(values, size);
- (*parameter_map)[values] = new_parameter_block;
- parameter_blocks->push_back(new_parameter_block);
+
+ // Pass the index of the new parameter block as well to keep the index in
+ // sync with the position of the parameter in the program's parameter vector.
+ ParameterBlock* new_parameter_block =
+ new ParameterBlock(values, size, program_->parameter_blocks_.size());
+
+ // For dynamic problems, add the list of dependent residual blocks, which is
+ // empty to start.
+ if (options_.enable_fast_parameter_block_removal) {
+ new_parameter_block->EnableResidualBlockDependencies();
+ }
+ parameter_block_map_[values] = new_parameter_block;
+ program_->parameter_blocks_.push_back(new_parameter_block);
return new_parameter_block;
}
+// Deletes the residual block in question, assuming there are no other
+// references to it inside the problem (e.g. by another parameter). Referenced
+// cost and loss functions are tucked away for future deletion, since it is not
+// possible to know whether other parts of the problem depend on them without
+// doing a full scan.
+void ProblemImpl::DeleteBlock(ResidualBlock* residual_block) {
+ // The const casts here are legit, since ResidualBlock holds these
+ // pointers as const pointers but we have ownership of them and
+ // have the right to destroy them when the destructor is called.
+ if (options_.cost_function_ownership == TAKE_OWNERSHIP &&
+ residual_block->cost_function() != NULL) {
+ cost_functions_to_delete_.push_back(
+ const_cast<CostFunction*>(residual_block->cost_function()));
+ }
+ if (options_.loss_function_ownership == TAKE_OWNERSHIP &&
+ residual_block->loss_function() != NULL) {
+ loss_functions_to_delete_.push_back(
+ const_cast<LossFunction*>(residual_block->loss_function()));
+ }
+ delete residual_block;
+}
+
+// Deletes the parameter block in question, assuming there are no other
+// references to it inside the problem (e.g. by any residual blocks).
+// Referenced parameterizations are tucked away for future deletion, since it
+// is not possible to know whether other parts of the problem depend on them
+// without doing a full scan.
+void ProblemImpl::DeleteBlock(ParameterBlock* parameter_block) {
+ if (options_.local_parameterization_ownership == TAKE_OWNERSHIP &&
+ parameter_block->local_parameterization() != NULL) {
+ local_parameterizations_to_delete_.push_back(
+ parameter_block->mutable_local_parameterization());
+ }
+ parameter_block_map_.erase(parameter_block->mutable_user_state());
+ delete parameter_block;
+}
+
ProblemImpl::ProblemImpl() : program_(new internal::Program) {}
ProblemImpl::ProblemImpl(const Problem::Options& options)
: options_(options),
@@ -128,48 +194,28 @@ ProblemImpl::ProblemImpl(const Problem::Options& options)
ProblemImpl::~ProblemImpl() {
// Collect the unique cost/loss functions and delete the residuals.
- set<CostFunction*> cost_functions;
- set<LossFunction*> loss_functions;
+ const int num_residual_blocks = program_->residual_blocks_.size();
+ cost_functions_to_delete_.reserve(num_residual_blocks);
+ loss_functions_to_delete_.reserve(num_residual_blocks);
for (int i = 0; i < program_->residual_blocks_.size(); ++i) {
- ResidualBlock* residual_block = program_->residual_blocks_[i];
-
- // The const casts here are legit, since ResidualBlock holds these
- // pointers as const pointers but we have ownership of them and
- // have the right to destroy them when the destructor is called.
- if (options_.cost_function_ownership == TAKE_OWNERSHIP) {
- cost_functions.insert(
- const_cast<CostFunction*>(residual_block->cost_function()));
- }
- if (options_.loss_function_ownership == TAKE_OWNERSHIP) {
- loss_functions.insert(
- const_cast<LossFunction*>(residual_block->loss_function()));
- }
-
- delete residual_block;
+ DeleteBlock(program_->residual_blocks_[i]);
}
// Collect the unique parameterizations and delete the parameters.
- set<LocalParameterization*> local_parameterizations;
for (int i = 0; i < program_->parameter_blocks_.size(); ++i) {
- ParameterBlock* parameter_block = program_->parameter_blocks_[i];
-
- if (options_.local_parameterization_ownership == TAKE_OWNERSHIP) {
- local_parameterizations.insert(parameter_block->local_parameterization_);
- }
-
- delete parameter_block;
+ DeleteBlock(program_->parameter_blocks_[i]);
}
// Delete the owned cost/loss functions and parameterizations.
- STLDeleteContainerPointers(local_parameterizations.begin(),
- local_parameterizations.end());
- STLDeleteContainerPointers(cost_functions.begin(),
- cost_functions.end());
- STLDeleteContainerPointers(loss_functions.begin(),
- loss_functions.end());
+ STLDeleteUniqueContainerPointers(local_parameterizations_to_delete_.begin(),
+ local_parameterizations_to_delete_.end());
+ STLDeleteUniqueContainerPointers(cost_functions_to_delete_.begin(),
+ cost_functions_to_delete_.end());
+ STLDeleteUniqueContainerPointers(loss_functions_to_delete_.begin(),
+ loss_functions_to_delete_.end());
}
-const ResidualBlock* ProblemImpl::AddResidualBlock(
+ResidualBlock* ProblemImpl::AddResidualBlock(
CostFunction* cost_function,
LossFunction* loss_function,
const vector<double*>& parameter_blocks) {
@@ -180,25 +226,28 @@ const ResidualBlock* ProblemImpl::AddResidualBlock(
// Check the sizes match.
const vector<int16>& parameter_block_sizes =
cost_function->parameter_block_sizes();
- CHECK_EQ(parameter_block_sizes.size(), parameter_blocks.size())
- << "Number of blocks input is different than the number of blocks "
- << "that the cost function expects.";
-
- // Check for duplicate parameter blocks.
- vector<double*> sorted_parameter_blocks(parameter_blocks);
- sort(sorted_parameter_blocks.begin(), sorted_parameter_blocks.end());
- vector<double*>::const_iterator duplicate_items =
- unique(sorted_parameter_blocks.begin(),
- sorted_parameter_blocks.end());
- if (duplicate_items != sorted_parameter_blocks.end()) {
- string blocks;
- for (int i = 0; i < parameter_blocks.size(); ++i) {
- blocks += internal::StringPrintf(" %p ", parameter_blocks[i]);
- }
- LOG(FATAL) << "Duplicate parameter blocks in a residual parameter "
- << "are not allowed. Parameter block pointers: ["
- << blocks << "]";
+ if (!options_.disable_all_safety_checks) {
+ CHECK_EQ(parameter_block_sizes.size(), parameter_blocks.size())
+ << "Number of blocks input is different than the number of blocks "
+ << "that the cost function expects.";
+
+ // Check for duplicate parameter blocks.
+ vector<double*> sorted_parameter_blocks(parameter_blocks);
+ sort(sorted_parameter_blocks.begin(), sorted_parameter_blocks.end());
+ vector<double*>::const_iterator duplicate_items =
+ unique(sorted_parameter_blocks.begin(),
+ sorted_parameter_blocks.end());
+ if (duplicate_items != sorted_parameter_blocks.end()) {
+ string blocks;
+ for (int i = 0; i < parameter_blocks.size(); ++i) {
+ blocks += StringPrintf(" %p ", parameter_blocks[i]);
+ }
+
+ LOG(FATAL) << "Duplicate parameter blocks in a residual parameter "
+ << "are not allowed. Parameter block pointers: ["
+ << blocks << "]";
+ }
}
// Add parameter blocks and convert the double*'s to parameter blocks.
@@ -206,33 +255,42 @@ const ResidualBlock* ProblemImpl::AddResidualBlock(
for (int i = 0; i < parameter_blocks.size(); ++i) {
parameter_block_ptrs[i] =
InternalAddParameterBlock(parameter_blocks[i],
- parameter_block_sizes[i],
- &parameter_block_map_,
- &program_->parameter_blocks_);
+ parameter_block_sizes[i]);
}
- // Check that the block sizes match the block sizes expected by the
- // cost_function.
- for (int i = 0; i < parameter_block_ptrs.size(); ++i) {
- CHECK_EQ(cost_function->parameter_block_sizes()[i],
- parameter_block_ptrs[i]->Size())
- << "The cost function expects parameter block " << i
- << " of size " << cost_function->parameter_block_sizes()[i]
- << " but was given a block of size "
- << parameter_block_ptrs[i]->Size();
+ if (!options_.disable_all_safety_checks) {
+ // Check that the block sizes match the block sizes expected by the
+ // cost_function.
+ for (int i = 0; i < parameter_block_ptrs.size(); ++i) {
+ CHECK_EQ(cost_function->parameter_block_sizes()[i],
+ parameter_block_ptrs[i]->Size())
+ << "The cost function expects parameter block " << i
+ << " of size " << cost_function->parameter_block_sizes()[i]
+ << " but was given a block of size "
+ << parameter_block_ptrs[i]->Size();
+ }
}
ResidualBlock* new_residual_block =
new ResidualBlock(cost_function,
loss_function,
- parameter_block_ptrs);
+ parameter_block_ptrs,
+ program_->residual_blocks_.size());
+
+ // Add dependencies on the residual to the parameter blocks.
+ if (options_.enable_fast_parameter_block_removal) {
+ for (int i = 0; i < parameter_blocks.size(); ++i) {
+ parameter_block_ptrs[i]->AddResidualBlock(new_residual_block);
+ }
+ }
+
program_->residual_blocks_.push_back(new_residual_block);
return new_residual_block;
}
// Unfortunately, macros don't help much to reduce this code, and var args don't
// work because of the ambiguous case that there is no loss function.
-const ResidualBlock* ProblemImpl::AddResidualBlock(
+ResidualBlock* ProblemImpl::AddResidualBlock(
CostFunction* cost_function,
LossFunction* loss_function,
double* x0) {
@@ -241,7 +299,7 @@ const ResidualBlock* ProblemImpl::AddResidualBlock(
return AddResidualBlock(cost_function, loss_function, residual_parameters);
}
-const ResidualBlock* ProblemImpl::AddResidualBlock(
+ResidualBlock* ProblemImpl::AddResidualBlock(
CostFunction* cost_function,
LossFunction* loss_function,
double* x0, double* x1) {
@@ -251,7 +309,7 @@ const ResidualBlock* ProblemImpl::AddResidualBlock(
return AddResidualBlock(cost_function, loss_function, residual_parameters);
}
-const ResidualBlock* ProblemImpl::AddResidualBlock(
+ResidualBlock* ProblemImpl::AddResidualBlock(
CostFunction* cost_function,
LossFunction* loss_function,
double* x0, double* x1, double* x2) {
@@ -262,7 +320,7 @@ const ResidualBlock* ProblemImpl::AddResidualBlock(
return AddResidualBlock(cost_function, loss_function, residual_parameters);
}
-const ResidualBlock* ProblemImpl::AddResidualBlock(
+ResidualBlock* ProblemImpl::AddResidualBlock(
CostFunction* cost_function,
LossFunction* loss_function,
double* x0, double* x1, double* x2, double* x3) {
@@ -274,7 +332,7 @@ const ResidualBlock* ProblemImpl::AddResidualBlock(
return AddResidualBlock(cost_function, loss_function, residual_parameters);
}
-const ResidualBlock* ProblemImpl::AddResidualBlock(
+ResidualBlock* ProblemImpl::AddResidualBlock(
CostFunction* cost_function,
LossFunction* loss_function,
double* x0, double* x1, double* x2, double* x3, double* x4) {
@@ -287,7 +345,7 @@ const ResidualBlock* ProblemImpl::AddResidualBlock(
return AddResidualBlock(cost_function, loss_function, residual_parameters);
}
-const ResidualBlock* ProblemImpl::AddResidualBlock(
+ResidualBlock* ProblemImpl::AddResidualBlock(
CostFunction* cost_function,
LossFunction* loss_function,
double* x0, double* x1, double* x2, double* x3, double* x4, double* x5) {
@@ -301,12 +359,78 @@ const ResidualBlock* ProblemImpl::AddResidualBlock(
return AddResidualBlock(cost_function, loss_function, residual_parameters);
}
+ResidualBlock* ProblemImpl::AddResidualBlock(
+ CostFunction* cost_function,
+ LossFunction* loss_function,
+ double* x0, double* x1, double* x2, double* x3, double* x4, double* x5,
+ double* x6) {
+ vector<double*> residual_parameters;
+ residual_parameters.push_back(x0);
+ residual_parameters.push_back(x1);
+ residual_parameters.push_back(x2);
+ residual_parameters.push_back(x3);
+ residual_parameters.push_back(x4);
+ residual_parameters.push_back(x5);
+ residual_parameters.push_back(x6);
+ return AddResidualBlock(cost_function, loss_function, residual_parameters);
+}
+
+ResidualBlock* ProblemImpl::AddResidualBlock(
+ CostFunction* cost_function,
+ LossFunction* loss_function,
+ double* x0, double* x1, double* x2, double* x3, double* x4, double* x5,
+ double* x6, double* x7) {
+ vector<double*> residual_parameters;
+ residual_parameters.push_back(x0);
+ residual_parameters.push_back(x1);
+ residual_parameters.push_back(x2);
+ residual_parameters.push_back(x3);
+ residual_parameters.push_back(x4);
+ residual_parameters.push_back(x5);
+ residual_parameters.push_back(x6);
+ residual_parameters.push_back(x7);
+ return AddResidualBlock(cost_function, loss_function, residual_parameters);
+}
+
+ResidualBlock* ProblemImpl::AddResidualBlock(
+ CostFunction* cost_function,
+ LossFunction* loss_function,
+ double* x0, double* x1, double* x2, double* x3, double* x4, double* x5,
+ double* x6, double* x7, double* x8) {
+ vector<double*> residual_parameters;
+ residual_parameters.push_back(x0);
+ residual_parameters.push_back(x1);
+ residual_parameters.push_back(x2);
+ residual_parameters.push_back(x3);
+ residual_parameters.push_back(x4);
+ residual_parameters.push_back(x5);
+ residual_parameters.push_back(x6);
+ residual_parameters.push_back(x7);
+ residual_parameters.push_back(x8);
+ return AddResidualBlock(cost_function, loss_function, residual_parameters);
+}
+
+ResidualBlock* ProblemImpl::AddResidualBlock(
+ CostFunction* cost_function,
+ LossFunction* loss_function,
+ double* x0, double* x1, double* x2, double* x3, double* x4, double* x5,
+ double* x6, double* x7, double* x8, double* x9) {
+ vector<double*> residual_parameters;
+ residual_parameters.push_back(x0);
+ residual_parameters.push_back(x1);
+ residual_parameters.push_back(x2);
+ residual_parameters.push_back(x3);
+ residual_parameters.push_back(x4);
+ residual_parameters.push_back(x5);
+ residual_parameters.push_back(x6);
+ residual_parameters.push_back(x7);
+ residual_parameters.push_back(x8);
+ residual_parameters.push_back(x9);
+ return AddResidualBlock(cost_function, loss_function, residual_parameters);
+}
void ProblemImpl::AddParameterBlock(double* values, int size) {
- InternalAddParameterBlock(values,
- size,
- &parameter_block_map_,
- &program_->parameter_blocks_);
+ InternalAddParameterBlock(values, size);
}
void ProblemImpl::AddParameterBlock(
@@ -314,30 +438,263 @@ void ProblemImpl::AddParameterBlock(
int size,
LocalParameterization* local_parameterization) {
ParameterBlock* parameter_block =
- InternalAddParameterBlock(values,
- size,
- &parameter_block_map_,
- &program_->parameter_blocks_);
+ InternalAddParameterBlock(values, size);
if (local_parameterization != NULL) {
parameter_block->SetParameterization(local_parameterization);
}
}
+// Delete a block from a vector of blocks, maintaining the indexing invariant.
+// This is done in constant time by moving an element from the end of the
+// vector over the element to remove, then popping the last element. It
+// destroys the ordering in the interest of speed.
+template<typename Block>
+void ProblemImpl::DeleteBlockInVector(vector<Block*>* mutable_blocks,
+ Block* block_to_remove) {
+ CHECK_EQ((*mutable_blocks)[block_to_remove->index()], block_to_remove)
+ << "You found a Ceres bug! Block: " << block_to_remove->ToString();
+
+ // Prepare the to-be-moved block for the new, lower-in-index position by
+ // setting the index to the blocks final location.
+ Block* tmp = mutable_blocks->back();
+ tmp->set_index(block_to_remove->index());
+
+ // Overwrite the to-be-deleted residual block with the one at the end.
+ (*mutable_blocks)[block_to_remove->index()] = tmp;
+
+ DeleteBlock(block_to_remove);
+
+ // The block is gone so shrink the vector of blocks accordingly.
+ mutable_blocks->pop_back();
+}
+
+void ProblemImpl::RemoveResidualBlock(ResidualBlock* residual_block) {
+ CHECK_NOTNULL(residual_block);
+
+ // If needed, remove the parameter dependencies on this residual block.
+ if (options_.enable_fast_parameter_block_removal) {
+ const int num_parameter_blocks_for_residual =
+ residual_block->NumParameterBlocks();
+ for (int i = 0; i < num_parameter_blocks_for_residual; ++i) {
+ residual_block->parameter_blocks()[i]
+ ->RemoveResidualBlock(residual_block);
+ }
+ }
+ DeleteBlockInVector(program_->mutable_residual_blocks(), residual_block);
+}
+
+void ProblemImpl::RemoveParameterBlock(double* values) {
+ ParameterBlock* parameter_block =
+ FindParameterBlockOrDie(parameter_block_map_, values);
+
+ if (options_.enable_fast_parameter_block_removal) {
+ // Copy the dependent residuals from the parameter block because the set of
+ // dependents will change after each call to RemoveResidualBlock().
+ vector<ResidualBlock*> residual_blocks_to_remove(
+ parameter_block->mutable_residual_blocks()->begin(),
+ parameter_block->mutable_residual_blocks()->end());
+ for (int i = 0; i < residual_blocks_to_remove.size(); ++i) {
+ RemoveResidualBlock(residual_blocks_to_remove[i]);
+ }
+ } else {
+ // Scan all the residual blocks to remove ones that depend on the parameter
+ // block. Do the scan backwards since the vector changes while iterating.
+ const int num_residual_blocks = NumResidualBlocks();
+ for (int i = num_residual_blocks - 1; i >= 0; --i) {
+ ResidualBlock* residual_block =
+ (*(program_->mutable_residual_blocks()))[i];
+ const int num_parameter_blocks = residual_block->NumParameterBlocks();
+ for (int j = 0; j < num_parameter_blocks; ++j) {
+ if (residual_block->parameter_blocks()[j] == parameter_block) {
+ RemoveResidualBlock(residual_block);
+ // The parameter blocks are guaranteed unique.
+ break;
+ }
+ }
+ }
+ }
+ DeleteBlockInVector(program_->mutable_parameter_blocks(), parameter_block);
+}
+
void ProblemImpl::SetParameterBlockConstant(double* values) {
- FindOrDie(parameter_block_map_, values)->SetConstant();
+ FindParameterBlockOrDie(parameter_block_map_, values)->SetConstant();
}
void ProblemImpl::SetParameterBlockVariable(double* values) {
- FindOrDie(parameter_block_map_, values)->SetVarying();
+ FindParameterBlockOrDie(parameter_block_map_, values)->SetVarying();
}
void ProblemImpl::SetParameterization(
double* values,
LocalParameterization* local_parameterization) {
- FindOrDie(parameter_block_map_, values)
+ FindParameterBlockOrDie(parameter_block_map_, values)
->SetParameterization(local_parameterization);
}
+bool ProblemImpl::Evaluate(const Problem::EvaluateOptions& evaluate_options,
+ double* cost,
+ vector<double>* residuals,
+ vector<double>* gradient,
+ CRSMatrix* jacobian) {
+ if (cost == NULL &&
+ residuals == NULL &&
+ gradient == NULL &&
+ jacobian == NULL) {
+ LOG(INFO) << "Nothing to do.";
+ return true;
+ }
+
+ // If the user supplied residual blocks, then use them, otherwise
+ // take the residual blocks from the underlying program.
+ Program program;
+ *program.mutable_residual_blocks() =
+ ((evaluate_options.residual_blocks.size() > 0)
+ ? evaluate_options.residual_blocks : program_->residual_blocks());
+
+ const vector<double*>& parameter_block_ptrs =
+ evaluate_options.parameter_blocks;
+
+ vector<ParameterBlock*> variable_parameter_blocks;
+ vector<ParameterBlock*>& parameter_blocks =
+ *program.mutable_parameter_blocks();
+
+ if (parameter_block_ptrs.size() == 0) {
+ // The user did not provide any parameter blocks, so default to
+ // using all the parameter blocks in the order that they are in
+ // the underlying program object.
+ parameter_blocks = program_->parameter_blocks();
+ } else {
+ // The user supplied a vector of parameter blocks. Using this list
+ // requires a number of steps.
+
+ // 1. Convert double* into ParameterBlock*
+ parameter_blocks.resize(parameter_block_ptrs.size());
+ for (int i = 0; i < parameter_block_ptrs.size(); ++i) {
+ parameter_blocks[i] =
+ FindParameterBlockOrDie(parameter_block_map_,
+ parameter_block_ptrs[i]);
+ }
+
+ // 2. The user may have only supplied a subset of parameter
+ // blocks, so identify the ones that are not supplied by the user
+ // and are NOT constant. These parameter blocks are stored in
+ // variable_parameter_blocks.
+ //
+ // To ensure that the parameter blocks are not included in the
+ // columns of the jacobian, we need to make sure that they are
+ // constant during evaluation and then make them variable again
+ // after we are done.
+ vector<ParameterBlock*> all_parameter_blocks(program_->parameter_blocks());
+ vector<ParameterBlock*> included_parameter_blocks(
+ program.parameter_blocks());
+
+ vector<ParameterBlock*> excluded_parameter_blocks;
+ sort(all_parameter_blocks.begin(), all_parameter_blocks.end());
+ sort(included_parameter_blocks.begin(), included_parameter_blocks.end());
+ set_difference(all_parameter_blocks.begin(),
+ all_parameter_blocks.end(),
+ included_parameter_blocks.begin(),
+ included_parameter_blocks.end(),
+ back_inserter(excluded_parameter_blocks));
+
+ variable_parameter_blocks.reserve(excluded_parameter_blocks.size());
+ for (int i = 0; i < excluded_parameter_blocks.size(); ++i) {
+ ParameterBlock* parameter_block = excluded_parameter_blocks[i];
+ if (!parameter_block->IsConstant()) {
+ variable_parameter_blocks.push_back(parameter_block);
+ parameter_block->SetConstant();
+ }
+ }
+ }
+
+ // Setup the Parameter indices and offsets before an evaluator can
+ // be constructed and used.
+ program.SetParameterOffsetsAndIndex();
+
+ Evaluator::Options evaluator_options;
+
+ // Even though using SPARSE_NORMAL_CHOLESKY requires SuiteSparse or
+ // CXSparse, here it just being used for telling the evaluator to
+ // use a SparseRowCompressedMatrix for the jacobian. This is because
+ // the Evaluator decides the storage for the Jacobian based on the
+ // type of linear solver being used.
+ evaluator_options.linear_solver_type = SPARSE_NORMAL_CHOLESKY;
+ evaluator_options.num_threads = evaluate_options.num_threads;
+
+ string error;
+ scoped_ptr<Evaluator> evaluator(
+ Evaluator::Create(evaluator_options, &program, &error));
+ if (evaluator.get() == NULL) {
+ LOG(ERROR) << "Unable to create an Evaluator object. "
+ << "Error: " << error
+ << "This is a Ceres bug; please contact the developers!";
+
+ // Make the parameter blocks that were temporarily marked
+ // constant, variable again.
+ for (int i = 0; i < variable_parameter_blocks.size(); ++i) {
+ variable_parameter_blocks[i]->SetVarying();
+ }
+ return false;
+ }
+
+ if (residuals !=NULL) {
+ residuals->resize(evaluator->NumResiduals());
+ }
+
+ if (gradient != NULL) {
+ gradient->resize(evaluator->NumEffectiveParameters());
+ }
+
+ scoped_ptr<CompressedRowSparseMatrix> tmp_jacobian;
+ if (jacobian != NULL) {
+ tmp_jacobian.reset(
+ down_cast<CompressedRowSparseMatrix*>(evaluator->CreateJacobian()));
+ }
+
+ // Point the state pointers to the user state pointers. This is
+ // needed so that we can extract a parameter vector which is then
+ // passed to Evaluator::Evaluate.
+ program.SetParameterBlockStatePtrsToUserStatePtrs();
+
+ // Copy the value of the parameter blocks into a vector, since the
+ // Evaluate::Evaluate method needs its input as such. The previous
+ // call to SetParameterBlockStatePtrsToUserStatePtrs ensures that
+ // these values are the ones corresponding to the actual state of
+ // the parameter blocks, rather than the temporary state pointer
+ // used for evaluation.
+ Vector parameters(program.NumParameters());
+ program.ParameterBlocksToStateVector(parameters.data());
+
+ double tmp_cost = 0;
+
+ Evaluator::EvaluateOptions evaluator_evaluate_options;
+ evaluator_evaluate_options.apply_loss_function =
+ evaluate_options.apply_loss_function;
+ bool status = evaluator->Evaluate(evaluator_evaluate_options,
+ parameters.data(),
+ &tmp_cost,
+ residuals != NULL ? &(*residuals)[0] : NULL,
+ gradient != NULL ? &(*gradient)[0] : NULL,
+ tmp_jacobian.get());
+
+ // Make the parameter blocks that were temporarily marked constant,
+ // variable again.
+ for (int i = 0; i < variable_parameter_blocks.size(); ++i) {
+ variable_parameter_blocks[i]->SetVarying();
+ }
+
+ if (status) {
+ if (cost != NULL) {
+ *cost = tmp_cost;
+ }
+ if (jacobian != NULL) {
+ tmp_jacobian->ToCRSMatrix(jacobian);
+ }
+ }
+
+ return status;
+}
+
int ProblemImpl::NumParameterBlocks() const {
return program_->NumParameterBlocks();
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h
index 2ca055448c3..ccc315de6b6 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h
@@ -53,6 +53,7 @@ namespace ceres {
class CostFunction;
class LossFunction;
class LocalParameterization;
+struct CRSMatrix;
namespace internal {
@@ -93,14 +94,46 @@ class ProblemImpl {
LossFunction* loss_function,
double* x0, double* x1, double* x2,
double* x3, double* x4, double* x5);
+ ResidualBlockId AddResidualBlock(CostFunction* cost_function,
+ LossFunction* loss_function,
+ double* x0, double* x1, double* x2,
+ double* x3, double* x4, double* x5,
+ double* x6);
+ ResidualBlockId AddResidualBlock(CostFunction* cost_function,
+ LossFunction* loss_function,
+ double* x0, double* x1, double* x2,
+ double* x3, double* x4, double* x5,
+ double* x6, double* x7);
+ ResidualBlockId AddResidualBlock(CostFunction* cost_function,
+ LossFunction* loss_function,
+ double* x0, double* x1, double* x2,
+ double* x3, double* x4, double* x5,
+ double* x6, double* x7, double* x8);
+ ResidualBlockId AddResidualBlock(CostFunction* cost_function,
+ LossFunction* loss_function,
+ double* x0, double* x1, double* x2,
+ double* x3, double* x4, double* x5,
+ double* x6, double* x7, double* x8,
+ double* x9);
void AddParameterBlock(double* values, int size);
void AddParameterBlock(double* values,
int size,
LocalParameterization* local_parameterization);
+
+ void RemoveResidualBlock(ResidualBlock* residual_block);
+ void RemoveParameterBlock(double* values);
+
void SetParameterBlockConstant(double* values);
void SetParameterBlockVariable(double* values);
void SetParameterization(double* values,
LocalParameterization* local_parameterization);
+
+ bool Evaluate(const Problem::EvaluateOptions& options,
+ double* cost,
+ vector<double>* residuals,
+ vector<double>* gradient,
+ CRSMatrix* jacobian);
+
int NumParameterBlocks() const;
int NumParameters() const;
int NumResidualBlocks() const;
@@ -112,12 +145,41 @@ class ProblemImpl {
const ParameterMap& parameter_map() const { return parameter_block_map_; }
private:
+ ParameterBlock* InternalAddParameterBlock(double* values, int size);
+
+ bool InternalEvaluate(Program* program,
+ double* cost,
+ vector<double>* residuals,
+ vector<double>* gradient,
+ CRSMatrix* jacobian);
+
+ // Delete the arguments in question. These differ from the Remove* functions
+ // in that they do not clean up references to the block to delete; they
+ // merely delete them.
+ template<typename Block>
+ void DeleteBlockInVector(vector<Block*>* mutable_blocks,
+ Block* block_to_remove);
+ void DeleteBlock(ResidualBlock* residual_block);
+ void DeleteBlock(ParameterBlock* parameter_block);
+
const Problem::Options options_;
// The mapping from user pointers to parameter blocks.
map<double*, ParameterBlock*> parameter_block_map_;
+ // The actual parameter and residual blocks.
internal::scoped_ptr<internal::Program> program_;
+
+ // When removing residual and parameter blocks, cost/loss functions and
+ // parameterizations have ambiguous ownership. Instead of scanning the entire
+ // problem to see if the cost/loss/parameterization is shared with other
+ // residual or parameter blocks, buffer them until destruction.
+ //
+ // TODO(keir): See if it makes sense to use sets instead.
+ vector<CostFunction*> cost_functions_to_delete_;
+ vector<LossFunction*> loss_functions_to_delete_;
+ vector<LocalParameterization*> local_parameterizations_to_delete_;
+
CERES_DISALLOW_COPY_AND_ASSIGN(ProblemImpl);
};
diff --git a/extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h b/extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h
index 6c48e7d7643..de56ac25ff6 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h
@@ -83,11 +83,14 @@
#include <omp.h>
#endif
+#include <map>
+#include <vector>
+#include "ceres/execution_summary.h"
+#include "ceres/internal/eigen.h"
+#include "ceres/internal/scoped_ptr.h"
#include "ceres/parameter_block.h"
#include "ceres/program.h"
#include "ceres/residual_block.h"
-#include "ceres/internal/eigen.h"
-#include "ceres/internal/scoped_ptr.h"
namespace ceres {
namespace internal {
@@ -117,11 +120,18 @@ class ProgramEvaluator : public Evaluator {
return jacobian_writer_.CreateJacobian();
}
- bool Evaluate(const double* state,
+ bool Evaluate(const Evaluator::EvaluateOptions& evaluate_options,
+ const double* state,
double* cost,
double* residuals,
double* gradient,
SparseMatrix* jacobian) {
+ ScopedExecutionTimer total_timer("Evaluator::Total", &execution_summary_);
+ ScopedExecutionTimer call_type_timer(gradient == NULL && jacobian == NULL
+ ? "Evaluator::Residual"
+ : "Evaluator::Jacobian",
+ &execution_summary_);
+
// The parameters are stateful, so set the state before evaluating.
if (!program_->StateVectorToParameterBlocks(state)) {
return false;
@@ -129,7 +139,7 @@ class ProgramEvaluator : public Evaluator {
if (residuals != NULL) {
VectorRef(residuals, program_->NumResiduals()).setZero();
- }
+ }
if (jacobian != NULL) {
jacobian->SetZero();
@@ -138,6 +148,10 @@ class ProgramEvaluator : public Evaluator {
// Each thread gets it's own cost and evaluate scratch space.
for (int i = 0; i < options_.num_threads; ++i) {
evaluate_scratch_[i].cost = 0.0;
+ if (gradient != NULL) {
+ VectorRef(evaluate_scratch_[i].gradient.get(),
+ program_->NumEffectiveParameters()).setZero();
+ }
}
// This bool is used to disable the loop if an error is encountered
@@ -183,6 +197,7 @@ class ProgramEvaluator : public Evaluator {
// Evaluate the cost, residuals, and jacobians.
double block_cost;
if (!residual_block->Evaluate(
+ evaluate_options.apply_loss_function,
&block_cost,
block_residuals,
block_jacobians,
@@ -262,6 +277,14 @@ class ProgramEvaluator : public Evaluator {
return program_->NumResiduals();
}
+ virtual map<string, int> CallStatistics() const {
+ return execution_summary_.calls();
+ }
+
+ virtual map<string, double> TimeStatistics() const {
+ return execution_summary_.times();
+ }
+
private:
// Per-thread scratch space needed to evaluate and store each residual block.
struct EvaluateScratch {
@@ -327,6 +350,7 @@ class ProgramEvaluator : public Evaluator {
scoped_array<EvaluatePreparer> evaluate_preparers_;
scoped_array<EvaluateScratch> evaluate_scratch_;
vector<int> residual_layout_;
+ ::ceres::internal::ExecutionSummary execution_summary_;
};
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/residual_block.cc b/extern/libmv/third_party/ceres/internal/ceres/residual_block.cc
index bdb88b1dd97..b91b0ed7843 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/residual_block.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/residual_block.cc
@@ -49,18 +49,21 @@ namespace internal {
ResidualBlock::ResidualBlock(const CostFunction* cost_function,
const LossFunction* loss_function,
- const vector<ParameterBlock*>& parameter_blocks)
+ const vector<ParameterBlock*>& parameter_blocks,
+ int index)
: cost_function_(cost_function),
loss_function_(loss_function),
parameter_blocks_(
new ParameterBlock* [
- cost_function->parameter_block_sizes().size()]) {
+ cost_function->parameter_block_sizes().size()]),
+ index_(index) {
std::copy(parameter_blocks.begin(),
parameter_blocks.end(),
parameter_blocks_.get());
}
-bool ResidualBlock::Evaluate(double* cost,
+bool ResidualBlock::Evaluate(const bool apply_loss_function,
+ double* cost,
double* residuals,
double** jacobians,
double* scratch) const {
@@ -152,7 +155,7 @@ bool ResidualBlock::Evaluate(double* cost,
}
}
- if (loss_function_ == NULL) {
+ if (loss_function_ == NULL || !apply_loss_function) {
*cost = 0.5 * squared_norm;
return true;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/residual_block.h b/extern/libmv/third_party/ceres/internal/ceres/residual_block.h
index e0a06e78958..9c3671bb0a4 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/residual_block.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/residual_block.h
@@ -34,11 +34,13 @@
#ifndef CERES_INTERNAL_RESIDUAL_BLOCK_H_
#define CERES_INTERNAL_RESIDUAL_BLOCK_H_
+#include <string>
#include <vector>
#include "ceres/cost_function.h"
#include "ceres/internal/port.h"
#include "ceres/internal/scoped_ptr.h"
+#include "ceres/stringprintf.h"
#include "ceres/types.h"
namespace ceres {
@@ -64,9 +66,13 @@ class ParameterBlock;
// loss functions, and parameter blocks.
class ResidualBlock {
public:
+ // Construct the residual block with the given cost/loss functions. Loss may
+ // be null. The index is the index of the residual block in the Program's
+ // residual_blocks array.
ResidualBlock(const CostFunction* cost_function,
const LossFunction* loss_function,
- const vector<ParameterBlock*>& parameter_blocks);
+ const vector<ParameterBlock*>& parameter_blocks,
+ int index);
// Evaluates the residual term, storing the scalar cost in *cost, the residual
// components in *residuals, and the jacobians between the parameters and
@@ -87,11 +93,16 @@ class ResidualBlock {
// parameterizations applied already; for example, the jacobian for a
// 4-dimensional quaternion parameter using the "QuaternionParameterization"
// is num_residuals by 3 instead of num_residuals by 4.
- bool Evaluate(double* cost,
+ //
+ // apply_loss_function as the name implies allows the user to switch
+ // the application of the loss function on and off.
+ bool Evaluate(bool apply_loss_function,
+ double* cost,
double* residuals,
double** jacobians,
double* scratch) const;
+
const CostFunction* cost_function() const { return cost_function_; }
const LossFunction* loss_function() const { return loss_function_; }
@@ -112,10 +123,23 @@ class ResidualBlock {
// The minimum amount of scratch space needed to pass to Evaluate().
int NumScratchDoublesForEvaluate() const;
+ // This residual block's index in an array.
+ int index() const { return index_; }
+ void set_index(int index) { index_ = index; }
+
+ string ToString() {
+ return StringPrintf("{residual block; index=%d}", index_);
+ }
+
private:
const CostFunction* cost_function_;
const LossFunction* loss_function_;
scoped_array<ParameterBlock*> parameter_blocks_;
+
+ // The index of the residual, typically in a Program. This is only to permit
+ // switching from a ResidualBlock* to an index in the Program's array, needed
+ // to do efficient removals.
+ int32 index_;
};
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc b/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc
index 9442bb2a1c1..4d88a9f4f8a 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc
@@ -63,7 +63,8 @@ void InvalidateEvaluation(const ResidualBlock& block,
// Utility routine to print an array of doubles to a string. If the
// array pointer is NULL, it is treated as an array of zeros.
-static void AppendArrayToString(const int size, const double* x, string* result) {
+namespace {
+void AppendArrayToString(const int size, const double* x, string* result) {
for (int i = 0; i < size; ++i) {
if (x == NULL) {
StringAppendF(result, "Not Computed ");
@@ -76,6 +77,7 @@ static void AppendArrayToString(const int size, const double* x, string* result)
}
}
}
+} // namespace
string EvaluationToString(const ResidualBlock& block,
double const* const* parameters,
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 2cbe78d133a..e1be4e2a78a 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
@@ -38,22 +38,21 @@
#endif // CERES_NO_CXSPARSE
#include "Eigen/Dense"
-#include "glog/logging.h"
#include "ceres/block_random_access_dense_matrix.h"
#include "ceres/block_random_access_matrix.h"
#include "ceres/block_random_access_sparse_matrix.h"
#include "ceres/block_sparse_matrix.h"
#include "ceres/block_structure.h"
#include "ceres/detect_structure.h"
+#include "ceres/internal/eigen.h"
+#include "ceres/internal/port.h"
+#include "ceres/internal/scoped_ptr.h"
#include "ceres/linear_solver.h"
#include "ceres/schur_complement_solver.h"
#include "ceres/suitesparse.h"
#include "ceres/triplet_sparse_matrix.h"
-#include "ceres/internal/eigen.h"
-#include "ceres/internal/port.h"
-#include "ceres/internal/scoped_ptr.h"
#include "ceres/types.h"
-
+#include "ceres/wall_time.h"
namespace ceres {
namespace internal {
@@ -63,43 +62,39 @@ LinearSolver::Summary SchurComplementSolver::SolveImpl(
const double* b,
const LinearSolver::PerSolveOptions& per_solve_options,
double* x) {
- const time_t start_time = time(NULL);
+ EventLogger event_logger("SchurComplementSolver::Solve");
+
if (eliminator_.get() == NULL) {
InitStorage(A->block_structure());
DetectStructure(*A->block_structure(),
- options_.num_eliminate_blocks,
+ options_.elimination_groups[0],
&options_.row_block_size,
&options_.e_block_size,
&options_.f_block_size);
eliminator_.reset(CHECK_NOTNULL(SchurEliminatorBase::Create(options_)));
- eliminator_->Init(options_.num_eliminate_blocks, A->block_structure());
+ eliminator_->Init(options_.elimination_groups[0], A->block_structure());
};
- const time_t init_time = time(NULL);
fill(x, x + A->num_cols(), 0.0);
+ event_logger.AddEvent("Setup");
LinearSolver::Summary summary;
summary.num_iterations = 1;
summary.termination_type = FAILURE;
eliminator_->Eliminate(A, b, per_solve_options.D, lhs_.get(), rhs_.get());
- const time_t eliminate_time = time(NULL);
+ event_logger.AddEvent("Eliminate");
double* reduced_solution = x + A->num_cols() - lhs_->num_cols();
const bool status = SolveReducedLinearSystem(reduced_solution);
- const time_t solve_time = time(NULL);
+ event_logger.AddEvent("ReducedSolve");
if (!status) {
return summary;
}
eliminator_->BackSubstitute(A, b, per_solve_options.D, reduced_solution, x);
- const time_t backsubstitute_time = time(NULL);
summary.termination_type = TOLERANCE;
- VLOG(2) << "time (sec) total: " << (backsubstitute_time - start_time)
- << " init: " << (init_time - start_time)
- << " eliminate: " << (eliminate_time - init_time)
- << " solve: " << (solve_time - eliminate_time)
- << " backsubstitute: " << (backsubstitute_time - solve_time);
+ event_logger.AddEvent("BackSubstitute");
return summary;
}
@@ -107,7 +102,7 @@ LinearSolver::Summary SchurComplementSolver::SolveImpl(
// complement.
void DenseSchurComplementSolver::InitStorage(
const CompressedRowBlockStructure* bs) {
- const int num_eliminate_blocks = options().num_eliminate_blocks;
+ const int num_eliminate_blocks = options().elimination_groups[0];
const int num_col_blocks = bs->cols.size();
vector<int> blocks(num_col_blocks - num_eliminate_blocks, 0);
@@ -146,6 +141,7 @@ bool DenseSchurComplementSolver::SolveReducedLinearSystem(double* solution) {
return true;
}
+#if !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARE)
SparseSchurComplementSolver::SparseSchurComplementSolver(
const LinearSolver::Options& options)
@@ -179,7 +175,7 @@ SparseSchurComplementSolver::~SparseSchurComplementSolver() {
// initialize a BlockRandomAccessSparseMatrix object.
void SparseSchurComplementSolver::InitStorage(
const CompressedRowBlockStructure* bs) {
- const int num_eliminate_blocks = options().num_eliminate_blocks;
+ const int num_eliminate_blocks = options().elimination_groups[0];
const int num_col_blocks = bs->cols.size();
const int num_row_blocks = bs->rows.size();
@@ -268,8 +264,6 @@ bool SparseSchurComplementSolver::SolveReducedLinearSystem(double* solution) {
// CHOLMOD's sparse cholesky factorization routines.
bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse(
double* solution) {
- const time_t start_time = time(NULL);
-
TripletSparseMatrix* tsm =
const_cast<TripletSparseMatrix*>(
down_cast<const BlockRandomAccessSparseMatrix*>(lhs())->matrix());
@@ -286,11 +280,9 @@ bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse(
// The matrix is symmetric, and the upper triangular part of the
// matrix contains the values.
cholmod_lhs->stype = 1;
- const time_t lhs_time = time(NULL);
cholmod_dense* cholmod_rhs =
ss_.CreateDenseVector(const_cast<double*>(rhs()), num_rows, num_rows);
- const time_t rhs_time = time(NULL);
// Symbolic factorization is computed if we don't already have one handy.
if (factor_ == NULL) {
@@ -301,38 +293,28 @@ bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse(
}
if (VLOG_IS_ON(2)) {
- cholmod_print_common("Symbolic Analysis", ss_.mutable_cc());
+ cholmod_print_common(const_cast<char*>("Symbolic Analysis"), ss_.mutable_cc());
}
}
CHECK_NOTNULL(factor_);
- const time_t symbolic_time = time(NULL);
cholmod_dense* cholmod_solution =
ss_.SolveCholesky(cholmod_lhs, factor_, cholmod_rhs);
- const time_t solve_time = time(NULL);
-
ss_.Free(cholmod_lhs);
cholmod_lhs = NULL;
ss_.Free(cholmod_rhs);
cholmod_rhs = NULL;
if (cholmod_solution == NULL) {
- LOG(ERROR) << "CHOLMOD solve failed.";
+ LOG(WARNING) << "CHOLMOD solve failed.";
return false;
}
VectorRef(solution, num_rows)
= VectorRef(static_cast<double*>(cholmod_solution->x), num_rows);
ss_.Free(cholmod_solution);
- const time_t final_time = time(NULL);
- VLOG(2) << "time: " << (final_time - start_time)
- << " lhs : " << (lhs_time - start_time)
- << " rhs: " << (rhs_time - lhs_time)
- << " analyze: " << (symbolic_time - rhs_time)
- << " factor_and_solve: " << (solve_time - symbolic_time)
- << " cleanup: " << (final_time - solve_time);
return true;
}
#else
@@ -384,5 +366,6 @@ bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingCXSparse(
}
#endif // CERES_NO_CXPARSE
+#endif // !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARE)
} // 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 ea1b3184c33..7c8d2e7ce38 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
@@ -33,6 +33,7 @@
#include <set>
#include <utility>
+#include <vector>
#include "ceres/block_random_access_matrix.h"
#include "ceres/block_sparse_matrix.h"
@@ -97,13 +98,14 @@ class BlockSparseMatrixBase;
// The two solvers can be instantiated by calling
// LinearSolver::CreateLinearSolver with LinearSolver::Options::type
// set to DENSE_SCHUR and SPARSE_SCHUR
-// respectively. LinearSolver::Options::num_eliminate_blocks should be
+// respectively. LinearSolver::Options::elimination_groups[0] should be
// at least 1.
class SchurComplementSolver : public BlockSparseMatrixBaseSolver {
public:
explicit SchurComplementSolver(const LinearSolver::Options& options)
: options_(options) {
- CHECK_GT(options.num_eliminate_blocks, 0);
+ CHECK_GT(options.elimination_groups.size(), 1);
+ CHECK_GT(options.elimination_groups[0], 0);
}
// LinearSolver methods
@@ -149,7 +151,7 @@ class DenseSchurComplementSolver : public SchurComplementSolver {
CERES_DISALLOW_COPY_AND_ASSIGN(DenseSchurComplementSolver);
};
-
+#if !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARE)
// Sparse Cholesky factorization based solver.
class SparseSchurComplementSolver : public SchurComplementSolver {
public:
@@ -180,6 +182,7 @@ class SparseSchurComplementSolver : public SchurComplementSolver {
CERES_DISALLOW_COPY_AND_ASSIGN(SparseSchurComplementSolver);
};
+#endif // !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARE)
} // namespace internal
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.cc b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.cc
index 44f5be3b4e9..31f83547b5f 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.cc
@@ -1,5 +1,5 @@
// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
+// Copyright 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
@@ -28,6 +28,8 @@
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
+// Template specialization of SchurEliminator.
+//
// ========================================
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
@@ -35,7 +37,7 @@
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
-// This file is generated using generate_template_specializations.py.
+// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
#include "ceres/linear_solver.h"
@@ -65,8 +67,8 @@ SchurEliminatorBase::Create(const LinearSolver::Options& options) {
}
if ((options.row_block_size == 2) &&
(options.e_block_size == 2) &&
- (options.f_block_size == Dynamic)) {
- return new SchurEliminator<2, 2, Dynamic>(options);
+ (options.f_block_size == Eigen::Dynamic)) {
+ return new SchurEliminator<2, 2, Eigen::Dynamic>(options);
}
if ((options.row_block_size == 2) &&
(options.e_block_size == 3) &&
@@ -85,8 +87,8 @@ SchurEliminatorBase::Create(const LinearSolver::Options& options) {
}
if ((options.row_block_size == 2) &&
(options.e_block_size == 3) &&
- (options.f_block_size == Dynamic)) {
- return new SchurEliminator<2, 3, Dynamic>(options);
+ (options.f_block_size == Eigen::Dynamic)) {
+ return new SchurEliminator<2, 3, Eigen::Dynamic>(options);
}
if ((options.row_block_size == 2) &&
(options.e_block_size == 4) &&
@@ -100,8 +102,8 @@ SchurEliminatorBase::Create(const LinearSolver::Options& options) {
}
if ((options.row_block_size == 2) &&
(options.e_block_size == 4) &&
- (options.f_block_size == Dynamic)) {
- return new SchurEliminator<2, 4, Dynamic>(options);
+ (options.f_block_size == Eigen::Dynamic)) {
+ return new SchurEliminator<2, 4, Eigen::Dynamic>(options);
}
if ((options.row_block_size == 4) &&
(options.e_block_size == 4) &&
@@ -120,13 +122,13 @@ SchurEliminatorBase::Create(const LinearSolver::Options& options) {
}
if ((options.row_block_size == 4) &&
(options.e_block_size == 4) &&
- (options.f_block_size == Dynamic)) {
- return new SchurEliminator<4, 4, Dynamic>(options);
+ (options.f_block_size == Eigen::Dynamic)) {
+ return new SchurEliminator<4, 4, Eigen::Dynamic>(options);
}
- if ((options.row_block_size == Dynamic) &&
- (options.e_block_size == Dynamic) &&
- (options.f_block_size == Dynamic)) {
- return new SchurEliminator<Dynamic, Dynamic, Dynamic>(options);
+ if ((options.row_block_size == Eigen::Dynamic) &&
+ (options.e_block_size == Eigen::Dynamic) &&
+ (options.f_block_size == Eigen::Dynamic)) {
+ return new SchurEliminator<Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic>(options);
}
#endif
@@ -134,7 +136,7 @@ SchurEliminatorBase::Create(const LinearSolver::Options& options) {
<< options.row_block_size << ","
<< options.e_block_size << ","
<< options.f_block_size << ">";
- return new SchurEliminator<Dynamic, Dynamic, Dynamic>(options);
+ return new SchurEliminator<Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic>(options);
}
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.h b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.h
index c24fe435f54..877621bb48c 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator.h
@@ -213,9 +213,9 @@ class SchurEliminatorBase {
//
// This implementation is mulithreaded using OpenMP. The level of
// parallelism is controlled by LinearSolver::Options::num_threads.
-template <int kRowBlockSize = Dynamic,
- int kEBlockSize = Dynamic,
- int kFBlockSize = Dynamic >
+template <int kRowBlockSize = Eigen::Dynamic,
+ int kEBlockSize = Eigen::Dynamic,
+ int kFBlockSize = Eigen::Dynamic >
class SchurEliminator : public SchurEliminatorBase {
public:
explicit SchurEliminator(const LinearSolver::Options& options)
diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h
index 6120db9b009..339c44bc41c 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h
@@ -50,7 +50,6 @@
#include <algorithm>
#include <map>
-#include <glog/logging.h>
#include "Eigen/Dense"
#include "ceres/block_random_access_matrix.h"
#include "ceres/block_sparse_matrix.h"
@@ -60,6 +59,7 @@
#include "ceres/stl_util.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/scoped_ptr.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
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
new file mode 100644
index 00000000000..33a666ed037
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.cc
@@ -0,0 +1,145 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+
+#include "ceres/schur_jacobi_preconditioner.h"
+
+#include <utility>
+#include <vector>
+#include "Eigen/Dense"
+#include "ceres/block_random_access_sparse_matrix.h"
+#include "ceres/block_sparse_matrix.h"
+#include "ceres/collections_port.h"
+#include "ceres/detect_structure.h"
+#include "ceres/internal/scoped_ptr.h"
+#include "ceres/linear_solver.h"
+#include "ceres/schur_eliminator.h"
+#include "glog/logging.h"
+
+namespace ceres {
+namespace internal {
+
+SchurJacobiPreconditioner::SchurJacobiPreconditioner(
+ const CompressedRowBlockStructure& bs,
+ const Preconditioner::Options& options)
+ : options_(options) {
+ CHECK_GT(options_.elimination_groups.size(), 1);
+ CHECK_GT(options_.elimination_groups[0], 0);
+ const int num_blocks = bs.cols.size() - options_.elimination_groups[0];
+ CHECK_GT(num_blocks, 0)
+ << "Jacobian should have atleast 1 f_block for "
+ << "SCHUR_JACOBI preconditioner.";
+
+ block_size_.resize(num_blocks);
+ set<pair<int, int> > block_pairs;
+
+ int num_block_diagonal_entries = 0;
+ for (int i = 0; i < num_blocks; ++i) {
+ block_size_[i] = bs.cols[i + options_.elimination_groups[0]].size;
+ block_pairs.insert(make_pair(i, i));
+ num_block_diagonal_entries += block_size_[i] * block_size_[i];
+ }
+
+ m_.reset(new BlockRandomAccessSparseMatrix(block_size_, block_pairs));
+ InitEliminator(bs);
+}
+
+SchurJacobiPreconditioner::~SchurJacobiPreconditioner() {
+}
+
+// Initialize the SchurEliminator.
+void SchurJacobiPreconditioner::InitEliminator(
+ const CompressedRowBlockStructure& bs) {
+ LinearSolver::Options eliminator_options;
+
+ eliminator_options.elimination_groups = options_.elimination_groups;
+ eliminator_options.num_threads = options_.num_threads;
+
+ DetectStructure(bs, options_.elimination_groups[0],
+ &eliminator_options.row_block_size,
+ &eliminator_options.e_block_size,
+ &eliminator_options.f_block_size);
+
+ eliminator_.reset(SchurEliminatorBase::Create(eliminator_options));
+ eliminator_->Init(options_.elimination_groups[0], &bs);
+}
+
+// Update the values of the preconditioner matrix and factorize it.
+bool SchurJacobiPreconditioner::Update(const BlockSparseMatrixBase& A,
+ const double* D) {
+ const int num_rows = m_->num_rows();
+ CHECK_GT(num_rows, 0);
+
+ // We need a dummy rhs vector and a dummy b vector since the Schur
+ // eliminator combines the computation of the reduced camera matrix
+ // with the computation of the right hand side of that linear
+ // system.
+ //
+ // TODO(sameeragarwal): Perhaps its worth refactoring the
+ // SchurEliminator::Eliminate function to allow NULL for the rhs. As
+ // of now it does not seem to be worth the effort.
+ Vector rhs = Vector::Zero(m_->num_rows());
+ Vector b = Vector::Zero(A.num_rows());
+
+ // Compute a subset of the entries of the Schur complement.
+ eliminator_->Eliminate(&A, b.data(), D, m_.get(), rhs.data());
+ return true;
+}
+
+void SchurJacobiPreconditioner::RightMultiply(const double* x,
+ double* y) const {
+ CHECK_NOTNULL(x);
+ CHECK_NOTNULL(y);
+
+ const double* lhs_values =
+ down_cast<BlockRandomAccessSparseMatrix*>(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>()
+ .ldlt()
+ .solve(ConstVectorRef(x, block_size));
+
+ x += block_size;
+ y += block_size;
+ lhs_values += block_size * block_size;
+ }
+}
+
+int SchurJacobiPreconditioner::num_rows() const {
+ return m_->num_rows();
+}
+
+} // namespace internal
+} // namespace ceres
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
new file mode 100644
index 00000000000..3addd73abd2
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.h
@@ -0,0 +1,110 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+//
+// Detailed descriptions of these preconditions beyond what is
+// documented here can be found in
+//
+// Bundle Adjustment in the Large
+// S. Agarwal, N. Snavely, S. Seitz & R. Szeliski, ECCV 2010
+// http://www.cs.washington.edu/homes/sagarwal/bal.pdf
+
+#ifndef CERES_INTERNAL_SCHUR_JACOBI_PRECONDITIONER_H_
+#define CERES_INTERNAL_SCHUR_JACOBI_PRECONDITIONER_H_
+
+#include <set>
+#include <vector>
+#include <utility>
+#include "ceres/collections_port.h"
+#include "ceres/internal/macros.h"
+#include "ceres/internal/scoped_ptr.h"
+#include "ceres/preconditioner.h"
+
+namespace ceres {
+namespace internal {
+
+class BlockRandomAccessSparseMatrix;
+class BlockSparseMatrixBase;
+struct CompressedRowBlockStructure;
+class SchurEliminatorBase;
+
+// This class implements the SCHUR_JACOBI preconditioner for Structure
+// from Motion/Bundle Adjustment problems. Full mathematical details
+// can be found in
+//
+// Bundle Adjustment in the Large
+// S. Agarwal, N. Snavely, S. Seitz & R. Szeliski, ECCV 2010
+// http://www.cs.washington.edu/homes/sagarwal/bal.pdf
+//
+// Example usage:
+//
+// Preconditioner::Options options;
+// options.preconditioner_type = SCHUR_JACOBI;
+// options.elimination_groups.push_back(num_points);
+// options.elimination_groups.push_back(num_cameras);
+// SchurJacobiPreconditioner preconditioner(
+// *A.block_structure(), options);
+// preconditioner.Update(A, NULL);
+// preconditioner.RightMultiply(x, y);
+//
+class SchurJacobiPreconditioner : public Preconditioner {
+ public:
+ // Initialize the symbolic structure of the preconditioner. bs is
+ // the block structure of the linear system to be solved. It is used
+ // to determine the sparsity structure of the preconditioner matrix.
+ //
+ // It has the same structural requirement as other Schur complement
+ // based solvers. Please see schur_eliminator.h for more details.
+ SchurJacobiPreconditioner(const CompressedRowBlockStructure& bs,
+ const Preconditioner::Options& options);
+ virtual ~SchurJacobiPreconditioner();
+
+ // Preconditioner interface.
+ virtual bool Update(const BlockSparseMatrixBase& A, const double* D);
+ virtual void RightMultiply(const double* x, double* y) const;
+ virtual int num_rows() const;
+
+ private:
+ void InitEliminator(const CompressedRowBlockStructure& bs);
+
+ Preconditioner::Options options_;
+
+ // Sizes of the blocks in the schur complement.
+ vector<int> block_size_;
+ scoped_ptr<SchurEliminatorBase> eliminator_;
+
+ // Preconditioner matrix.
+ scoped_ptr<BlockRandomAccessSparseMatrix> m_;
+ CERES_DISALLOW_COPY_AND_ASSIGN(SchurJacobiPreconditioner);
+};
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_INTERNAL_SCHUR_JACOBI_PRECONDITIONER_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver.cc b/extern/libmv/third_party/ceres/internal/ceres/solver.cc
index 66ca93283a1..ea9ff1f488b 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/solver.cc
@@ -37,20 +37,41 @@
#include "ceres/program.h"
#include "ceres/solver_impl.h"
#include "ceres/stringprintf.h"
+#include "ceres/wall_time.h"
namespace ceres {
+namespace {
+
+void StringifyOrdering(const vector<int>& ordering, string* report) {
+ if (ordering.size() == 0) {
+ internal::StringAppendF(report, "AUTOMATIC");
+ return;
+ }
+
+ for (int i = 0; i < ordering.size() - 1; ++i) {
+ internal::StringAppendF(report, "%d, ", ordering[i]);
+ }
+ internal::StringAppendF(report, "%d", ordering.back());
+}
+
+} // namespace
+
+Solver::Options::~Options() {
+ delete linear_solver_ordering;
+ delete inner_iteration_ordering;
+}
Solver::~Solver() {}
-// TODO(sameeragarwal): Use subsecond timers.
void Solver::Solve(const Solver::Options& options,
Problem* problem,
Solver::Summary* summary) {
- time_t start_time_seconds = time(NULL);
+ double start_time_seconds = internal::WallTimeInSeconds();
internal::ProblemImpl* problem_impl =
CHECK_NOTNULL(problem)->problem_impl_.get();
internal::SolverImpl::Solve(options, problem_impl, summary);
- summary->total_time_in_seconds = time(NULL) - start_time_seconds;
+ summary->total_time_in_seconds =
+ internal::WallTimeInSeconds() - start_time_seconds;
}
void Solve(const Solver::Options& options,
@@ -63,7 +84,8 @@ void Solve(const Solver::Options& options,
Solver::Summary::Summary()
// Invalid values for most fields, to ensure that we are not
// accidentally reporting default values.
- : termination_type(DID_NOT_RUN),
+ : minimizer_type(TRUST_REGION),
+ termination_type(DID_NOT_RUN),
initial_cost(-1.0),
final_cost(-1.0),
fixed_cost(-1.0),
@@ -73,16 +95,19 @@ Solver::Summary::Summary()
minimizer_time_in_seconds(-1.0),
postprocessor_time_in_seconds(-1.0),
total_time_in_seconds(-1.0),
+ linear_solver_time_in_seconds(-1.0),
+ residual_evaluation_time_in_seconds(-1.0),
+ jacobian_evaluation_time_in_seconds(-1.0),
num_parameter_blocks(-1),
num_parameters(-1),
+ num_effective_parameters(-1),
num_residual_blocks(-1),
num_residuals(-1),
num_parameter_blocks_reduced(-1),
num_parameters_reduced(-1),
+ num_effective_parameters_reduced(-1),
num_residual_blocks_reduced(-1),
num_residuals_reduced(-1),
- num_eliminate_blocks_given(-1),
- num_eliminate_blocks_used(-1),
num_threads_given(-1),
num_threads_used(-1),
num_linear_solver_threads_given(-1),
@@ -90,9 +115,11 @@ Solver::Summary::Summary()
linear_solver_type_given(SPARSE_NORMAL_CHOLESKY),
linear_solver_type_used(SPARSE_NORMAL_CHOLESKY),
preconditioner_type(IDENTITY),
- ordering_type(NATURAL),
trust_region_strategy_type(LEVENBERG_MARQUARDT),
- sparse_linear_algebra_library(SUITE_SPARSE) {
+ inner_iterations(false),
+ sparse_linear_algebra_library(SUITE_SPARSE),
+ line_search_direction_type(LBFGS),
+ line_search_type(ARMIJO) {
}
string Solver::Summary::BriefReport() const {
@@ -121,6 +148,8 @@ string Solver::Summary::BriefReport() const {
return report;
};
+using internal::StringAppendF;
+
string Solver::Summary::FullReport() const {
string report =
"\n"
@@ -128,124 +157,216 @@ string Solver::Summary::FullReport() const {
"-------------------\n";
if (termination_type == DID_NOT_RUN) {
- internal::StringAppendF(&report, " Original\n");
- internal::StringAppendF(&report, "Parameter blocks % 10d\n",
- num_parameter_blocks);
- internal::StringAppendF(&report, "Parameters % 10d\n",
- num_parameters);
- internal::StringAppendF(&report, "Residual blocks % 10d\n",
- num_residual_blocks);
- internal::StringAppendF(&report, "Residuals % 10d\n\n",
- num_residuals);
+ StringAppendF(&report, " Original\n");
+ StringAppendF(&report, "Parameter blocks % 10d\n", num_parameter_blocks);
+ StringAppendF(&report, "Parameters % 10d\n", num_parameters);
+ if (num_effective_parameters != num_parameters) {
+ StringAppendF(&report, "Effective parameters% 10d\n", num_parameters);
+ }
+
+ StringAppendF(&report, "Residual blocks % 10d\n",
+ num_residual_blocks);
+ StringAppendF(&report, "Residuals % 10d\n\n",
+ num_residuals);
} else {
- internal::StringAppendF(&report, "%45s %21s\n", "Original", "Reduced");
- internal::StringAppendF(&report, "Parameter blocks % 25d% 25d\n",
- num_parameter_blocks, num_parameter_blocks_reduced);
- internal::StringAppendF(&report, "Parameters % 25d% 25d\n",
- num_parameters, num_parameters_reduced);
- internal::StringAppendF(&report, "Residual blocks % 25d% 25d\n",
- num_residual_blocks, num_residual_blocks_reduced);
- internal::StringAppendF(&report, "Residual % 25d% 25d\n\n",
- num_residuals, num_residuals_reduced);
+ StringAppendF(&report, "%45s %21s\n", "Original", "Reduced");
+ StringAppendF(&report, "Parameter blocks % 25d% 25d\n",
+ num_parameter_blocks, num_parameter_blocks_reduced);
+ StringAppendF(&report, "Parameters % 25d% 25d\n",
+ num_parameters, num_parameters_reduced);
+ if (num_effective_parameters_reduced != num_parameters_reduced) {
+ StringAppendF(&report, "Effective parameters% 25d% 25d\n",
+ num_effective_parameters, num_effective_parameters_reduced);
+ }
+ StringAppendF(&report, "Residual blocks % 25d% 25d\n",
+ num_residual_blocks, num_residual_blocks_reduced);
+ StringAppendF(&report, "Residual % 25d% 25d\n",
+ num_residuals, num_residuals_reduced);
}
- internal::StringAppendF(&report, "%45s %21s\n", "Given", "Used");
- internal::StringAppendF(&report, "Linear solver %25s%25s\n",
- LinearSolverTypeToString(linear_solver_type_given),
- LinearSolverTypeToString(linear_solver_type_used));
+ // TODO(sameeragarwal): Refactor this into separate functions.
- if (linear_solver_type_given == CGNR ||
- linear_solver_type_given == ITERATIVE_SCHUR) {
- internal::StringAppendF(&report, "Preconditioner %25s%25s\n",
- PreconditionerTypeToString(preconditioner_type),
- PreconditionerTypeToString(preconditioner_type));
- } else {
- internal::StringAppendF(&report, "Preconditioner %25s%25s\n",
- "N/A", "N/A");
- }
+ if (minimizer_type == TRUST_REGION) {
+ StringAppendF(&report, "\nMinimizer %19s\n",
+ "TRUST_REGION");
+ if (linear_solver_type_used == SPARSE_NORMAL_CHOLESKY ||
+ linear_solver_type_used == SPARSE_SCHUR ||
+ (linear_solver_type_used == ITERATIVE_SCHUR &&
+ (preconditioner_type == CLUSTER_JACOBI ||
+ preconditioner_type == CLUSTER_TRIDIAGONAL))) {
+ StringAppendF(&report, "\nSparse Linear Algebra Library %15s\n",
+ SparseLinearAlgebraLibraryTypeToString(
+ sparse_linear_algebra_library));
+ }
+
+ StringAppendF(&report, "Trust Region Strategy %19s",
+ TrustRegionStrategyTypeToString(
+ trust_region_strategy_type));
+ if (trust_region_strategy_type == DOGLEG) {
+ if (dogleg_type == TRADITIONAL_DOGLEG) {
+ StringAppendF(&report, " (TRADITIONAL)");
+ } else {
+ StringAppendF(&report, " (SUBSPACE)");
+ }
+ }
+ StringAppendF(&report, "\n");
+ StringAppendF(&report, "\n");
- internal::StringAppendF(&report, "Ordering %25s%25s\n",
- OrderingTypeToString(ordering_type),
- OrderingTypeToString(ordering_type));
+ StringAppendF(&report, "%45s %21s\n", "Given", "Used");
+ StringAppendF(&report, "Linear solver %25s%25s\n",
+ LinearSolverTypeToString(linear_solver_type_given),
+ LinearSolverTypeToString(linear_solver_type_used));
- if (IsSchurType(linear_solver_type_given)) {
- if (ordering_type == SCHUR) {
- internal::StringAppendF(&report, "num_eliminate_blocks%25s% 25d\n",
- "N/A",
- num_eliminate_blocks_used);
+ if (linear_solver_type_given == CGNR ||
+ linear_solver_type_given == ITERATIVE_SCHUR) {
+ StringAppendF(&report, "Preconditioner %25s%25s\n",
+ PreconditionerTypeToString(preconditioner_type),
+ PreconditionerTypeToString(preconditioner_type));
} else {
- internal::StringAppendF(&report, "num_eliminate_blocks% 25d% 25d\n",
- num_eliminate_blocks_given,
- num_eliminate_blocks_used);
+ StringAppendF(&report, "Preconditioner %25s%25s\n",
+ "N/A", "N/A");
}
- }
- internal::StringAppendF(&report, "Threads: % 25d% 25d\n",
- num_threads_given, num_threads_used);
- internal::StringAppendF(&report, "Linear solver threads % 23d% 25d\n",
- num_linear_solver_threads_given,
- num_linear_solver_threads_used);
-
- if (linear_solver_type_used == SPARSE_NORMAL_CHOLESKY ||
- linear_solver_type_used == SPARSE_SCHUR ||
- (linear_solver_type_used == ITERATIVE_SCHUR &&
- (preconditioner_type == SCHUR_JACOBI ||
- preconditioner_type == CLUSTER_JACOBI ||
- preconditioner_type == CLUSTER_TRIDIAGONAL))) {
- internal::StringAppendF(&report, "\nSparse Linear Algebra Library %15s\n",
- SparseLinearAlgebraLibraryTypeToString(
- sparse_linear_algebra_library));
- }
+ StringAppendF(&report, "Threads: % 25d% 25d\n",
+ num_threads_given, num_threads_used);
+ StringAppendF(&report, "Linear solver threads % 23d% 25d\n",
+ num_linear_solver_threads_given,
+ num_linear_solver_threads_used);
- internal::StringAppendF(&report, "Trust Region Strategy %19s",
- TrustRegionStrategyTypeToString(
- trust_region_strategy_type));
- if (trust_region_strategy_type == DOGLEG) {
- if (dogleg_type == TRADITIONAL_DOGLEG) {
- internal::StringAppendF(&report, " (TRADITIONAL)");
+ if (IsSchurType(linear_solver_type_used)) {
+ string given;
+ StringifyOrdering(linear_solver_ordering_given, &given);
+ string used;
+ StringifyOrdering(linear_solver_ordering_used, &used);
+ StringAppendF(&report,
+ "Linear solver ordering %22s %24s\n",
+ given.c_str(),
+ used.c_str());
+ }
+
+ if (inner_iterations) {
+ string given;
+ StringifyOrdering(inner_iteration_ordering_given, &given);
+ string used;
+ StringifyOrdering(inner_iteration_ordering_used, &used);
+ StringAppendF(&report,
+ "Inner iteration ordering %20s %24s\n",
+ given.c_str(),
+ used.c_str());
+ }
+
+ if (termination_type == DID_NOT_RUN) {
+ CHECK(!error.empty())
+ << "Solver terminated with DID_NOT_RUN but the solver did not "
+ << "return a reason. This is a Ceres error. Please report this "
+ << "to the Ceres team";
+ StringAppendF(&report, "Termination: %20s\n",
+ "DID_NOT_RUN");
+ StringAppendF(&report, "Reason: %s\n", error.c_str());
+ return report;
+ }
+
+ StringAppendF(&report, "\nCost:\n");
+ StringAppendF(&report, "Initial % 30e\n", initial_cost);
+ if (termination_type != NUMERICAL_FAILURE &&
+ termination_type != USER_ABORT) {
+ StringAppendF(&report, "Final % 30e\n", final_cost);
+ StringAppendF(&report, "Change % 30e\n",
+ initial_cost - final_cost);
+ }
+
+ StringAppendF(&report, "\nNumber of iterations:\n");
+ StringAppendF(&report, "Successful % 20d\n",
+ num_successful_steps);
+ StringAppendF(&report, "Unsuccessful % 20d\n",
+ num_unsuccessful_steps);
+ StringAppendF(&report, "Total % 20d\n",
+ num_successful_steps + num_unsuccessful_steps);
+
+ StringAppendF(&report, "\nTime (in seconds):\n");
+ StringAppendF(&report, "Preprocessor %25.3f\n",
+ preprocessor_time_in_seconds);
+ StringAppendF(&report, "\n Residual Evaluations %22.3f\n",
+ residual_evaluation_time_in_seconds);
+ StringAppendF(&report, " Jacobian Evaluations %22.3f\n",
+ jacobian_evaluation_time_in_seconds);
+ StringAppendF(&report, " Linear Solver %23.3f\n",
+ linear_solver_time_in_seconds);
+ StringAppendF(&report, "Minimizer %25.3f\n\n",
+ minimizer_time_in_seconds);
+
+ StringAppendF(&report, "Postprocessor %24.3f\n",
+ postprocessor_time_in_seconds);
+
+ StringAppendF(&report, "Total %25.3f\n\n",
+ total_time_in_seconds);
+
+ StringAppendF(&report, "Termination: %25s\n",
+ SolverTerminationTypeToString(termination_type));
+ } else {
+ // LINE_SEARCH
+ StringAppendF(&report, "\nMinimizer %19s\n", "LINE_SEARCH");
+ if (line_search_direction_type == LBFGS) {
+ StringAppendF(&report, "Line search direction %19s(%d)\n",
+ LineSearchDirectionTypeToString(line_search_direction_type),
+ max_lbfgs_rank);
} else {
- internal::StringAppendF(&report, " (SUBSPACE)");
+ StringAppendF(&report, "Line search direction %19s\n",
+ LineSearchDirectionTypeToString(
+ line_search_direction_type));
}
- }
- internal::StringAppendF(&report, "\n");
+ StringAppendF(&report, "Line search type %19s\n",
+ LineSearchTypeToString(line_search_type));
+ StringAppendF(&report, "\n");
- if (termination_type == DID_NOT_RUN) {
- CHECK(!error.empty())
- << "Solver terminated with DID_NOT_RUN but the solver did not "
- << "return a reason. This is a Ceres error. Please report this "
- << "to the Ceres team";
- internal::StringAppendF(&report, "Termination: %20s\n",
- "DID_NOT_RUN");
- internal::StringAppendF(&report, "Reason: %s\n", error.c_str());
- return report;
- }
+ StringAppendF(&report, "%45s %21s\n", "Given", "Used");
+ StringAppendF(&report, "Threads: % 25d% 25d\n",
+ num_threads_given, num_threads_used);
- internal::StringAppendF(&report, "\nCost:\n");
- internal::StringAppendF(&report, "Initial % 30e\n", initial_cost);
- if (termination_type != NUMERICAL_FAILURE && termination_type != USER_ABORT) {
- internal::StringAppendF(&report, "Final % 30e\n", final_cost);
- internal::StringAppendF(&report, "Change % 30e\n",
- initial_cost - final_cost);
+ if (termination_type == DID_NOT_RUN) {
+ CHECK(!error.empty())
+ << "Solver terminated with DID_NOT_RUN but the solver did not "
+ << "return a reason. This is a Ceres error. Please report this "
+ << "to the Ceres team";
+ StringAppendF(&report, "Termination: %20s\n",
+ "DID_NOT_RUN");
+ StringAppendF(&report, "Reason: %s\n", error.c_str());
+ return report;
+ }
+
+ StringAppendF(&report, "\nCost:\n");
+ StringAppendF(&report, "Initial % 30e\n", initial_cost);
+ if (termination_type != NUMERICAL_FAILURE &&
+ termination_type != USER_ABORT) {
+ StringAppendF(&report, "Final % 30e\n", final_cost);
+ StringAppendF(&report, "Change % 30e\n",
+ initial_cost - final_cost);
+ }
+
+ StringAppendF(&report, "\nNumber of iterations: % 20d\n",
+ static_cast<int>(iterations.size() - 1));
+
+ StringAppendF(&report, "\nTime (in seconds):\n");
+ StringAppendF(&report, "Preprocessor %25.3f\n",
+ preprocessor_time_in_seconds);
+ StringAppendF(&report, "\n Residual Evaluations %22.3f\n",
+ residual_evaluation_time_in_seconds);
+ StringAppendF(&report, " Jacobian Evaluations %22.3f\n",
+ jacobian_evaluation_time_in_seconds);
+ StringAppendF(&report, "Minimizer %25.3f\n\n",
+ minimizer_time_in_seconds);
+
+ StringAppendF(&report, "Postprocessor %24.3f\n",
+ postprocessor_time_in_seconds);
+
+ StringAppendF(&report, "Total %25.3f\n\n",
+ total_time_in_seconds);
+
+ StringAppendF(&report, "Termination: %25s\n",
+ SolverTerminationTypeToString(termination_type));
}
- internal::StringAppendF(&report, "\nNumber of iterations:\n");
- internal::StringAppendF(&report, "Successful % 20d\n",
- num_successful_steps);
- internal::StringAppendF(&report, "Unsuccessful % 20d\n",
- num_unsuccessful_steps);
- internal::StringAppendF(&report, "Total % 20d\n",
- num_successful_steps + num_unsuccessful_steps);
- internal::StringAppendF(&report, "\nTime (in seconds):\n");
- internal::StringAppendF(&report, "Preprocessor % 25e\n",
- preprocessor_time_in_seconds);
- internal::StringAppendF(&report, "Minimizer % 25e\n",
- minimizer_time_in_seconds);
- internal::StringAppendF(&report, "Total % 25e\n",
- total_time_in_seconds);
-
- internal::StringAppendF(&report, "Termination: %25s\n",
- SolverTerminationTypeToString(termination_type));
return report;
};
diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc
index 8ef5b98e35f..ffc347ec9f0 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc
@@ -33,21 +33,25 @@
#include <cstdio>
#include <iostream> // NOLINT
#include <numeric>
+#include "ceres/coordinate_descent_minimizer.h"
#include "ceres/evaluator.h"
#include "ceres/gradient_checking_cost_function.h"
#include "ceres/iteration_callback.h"
#include "ceres/levenberg_marquardt_strategy.h"
#include "ceres/linear_solver.h"
+#include "ceres/line_search_minimizer.h"
#include "ceres/map_util.h"
#include "ceres/minimizer.h"
+#include "ceres/ordered_groups.h"
#include "ceres/parameter_block.h"
+#include "ceres/parameter_block_ordering.h"
#include "ceres/problem.h"
#include "ceres/problem_impl.h"
#include "ceres/program.h"
#include "ceres/residual_block.h"
-#include "ceres/schur_ordering.h"
#include "ceres/stringprintf.h"
#include "ceres/trust_region_minimizer.h"
+#include "ceres/wall_time.h"
namespace ceres {
namespace internal {
@@ -73,14 +77,24 @@ class StateUpdatingCallback : public IterationCallback {
double* parameters_;
};
+void SetSummaryFinalCost(Solver::Summary* summary) {
+ summary->final_cost = summary->initial_cost;
+ // We need the loop here, instead of just looking at the last
+ // iteration because the minimizer maybe making non-monotonic steps.
+ for (int i = 0; i < summary->iterations.size(); ++i) {
+ const IterationSummary& iteration_summary = summary->iterations[i];
+ summary->final_cost = min(iteration_summary.cost, summary->final_cost);
+ }
+}
+
// Callback for logging the state of the minimizer to STDERR or STDOUT
// depending on the user's preferences and logging level.
-class LoggingCallback : public IterationCallback {
+class TrustRegionLoggingCallback : public IterationCallback {
public:
- explicit LoggingCallback(bool log_to_stdout)
+ explicit TrustRegionLoggingCallback(bool log_to_stdout)
: log_to_stdout_(log_to_stdout) {}
- ~LoggingCallback() {}
+ ~TrustRegionLoggingCallback() {}
CallbackReturnType operator()(const IterationSummary& summary) {
const char* kReportRowFormat =
@@ -109,6 +123,42 @@ class LoggingCallback : public IterationCallback {
const bool log_to_stdout_;
};
+// Callback for logging the state of the minimizer to STDERR or STDOUT
+// depending on the user's preferences and logging level.
+class LineSearchLoggingCallback : public IterationCallback {
+ public:
+ explicit LineSearchLoggingCallback(bool log_to_stdout)
+ : log_to_stdout_(log_to_stdout) {}
+
+ ~LineSearchLoggingCallback() {}
+
+ CallbackReturnType operator()(const IterationSummary& summary) {
+ const char* kReportRowFormat =
+ "% 4d: f:% 8e d:% 3.2e g:% 3.2e h:% 3.2e "
+ "s:% 3.2e e:% 3d it:% 3.2e tt:% 3.2e";
+ string output = StringPrintf(kReportRowFormat,
+ summary.iteration,
+ summary.cost,
+ summary.cost_change,
+ summary.gradient_max_norm,
+ summary.step_norm,
+ summary.step_size,
+ summary.line_search_function_evaluations,
+ summary.iteration_time_in_seconds,
+ summary.cumulative_time_in_seconds);
+ if (log_to_stdout_) {
+ cout << output << endl;
+ } else {
+ VLOG(1) << output;
+ }
+ return SOLVER_CONTINUE;
+ }
+
+ private:
+ const bool log_to_stdout_;
+};
+
+
// Basic callback to record the execution of the solver to a file for
// offline analysis.
class FileLoggingCallback : public IterationCallback {
@@ -137,14 +187,34 @@ class FileLoggingCallback : public IterationCallback {
FILE* fptr_;
};
+// Iterate over each of the groups in order of their priority and fill
+// summary with their sizes.
+void SummarizeOrdering(ParameterBlockOrdering* ordering,
+ vector<int>* summary) {
+ CHECK_NOTNULL(summary)->clear();
+ if (ordering == NULL) {
+ return;
+ }
+
+ const map<int, set<double*> >& group_to_elements =
+ ordering->group_to_elements();
+ for (map<int, set<double*> >::const_iterator it = group_to_elements.begin();
+ it != group_to_elements.end();
+ ++it) {
+ summary->push_back(it->second.size());
+ }
+}
+
} // namespace
-void SolverImpl::Minimize(const Solver::Options& options,
- Program* program,
- Evaluator* evaluator,
- LinearSolver* linear_solver,
- double* parameters,
- Solver::Summary* summary) {
+void SolverImpl::TrustRegionMinimize(
+ const Solver::Options& options,
+ Program* program,
+ CoordinateDescentMinimizer* inner_iteration_minimizer,
+ Evaluator* evaluator,
+ LinearSolver* linear_solver,
+ double* parameters,
+ Solver::Summary* summary) {
Minimizer::Options minimizer_options(options);
// TODO(sameeragarwal): Add support for logging the configuration
@@ -156,7 +226,8 @@ void SolverImpl::Minimize(const Solver::Options& options,
file_logging_callback.get());
}
- LoggingCallback logging_callback(options.minimizer_progress_to_stdout);
+ TrustRegionLoggingCallback logging_callback(
+ options.minimizer_progress_to_stdout);
if (options.logging_type != SILENT) {
minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(),
&logging_callback);
@@ -172,7 +243,9 @@ void SolverImpl::Minimize(const Solver::Options& options,
minimizer_options.evaluator = evaluator;
scoped_ptr<SparseMatrix> jacobian(evaluator->CreateJacobian());
+
minimizer_options.jacobian = jacobian.get();
+ minimizer_options.inner_iteration_minimizer = inner_iteration_minimizer;
TrustRegionStrategy::Options trust_region_strategy_options;
trust_region_strategy_options.linear_solver = linear_solver;
@@ -189,78 +262,147 @@ void SolverImpl::Minimize(const Solver::Options& options,
minimizer_options.trust_region_strategy = strategy.get();
TrustRegionMinimizer minimizer;
- time_t minimizer_start_time = time(NULL);
+ double minimizer_start_time = WallTimeInSeconds();
minimizer.Minimize(minimizer_options, parameters, summary);
- summary->minimizer_time_in_seconds = time(NULL) - minimizer_start_time;
+ summary->minimizer_time_in_seconds =
+ WallTimeInSeconds() - minimizer_start_time;
}
-void SolverImpl::Solve(const Solver::Options& original_options,
- ProblemImpl* original_problem_impl,
+#ifndef CERES_NO_LINE_SEARCH_MINIMIZER
+void SolverImpl::LineSearchMinimize(
+ const Solver::Options& options,
+ Program* program,
+ Evaluator* evaluator,
+ double* parameters,
+ Solver::Summary* summary) {
+ Minimizer::Options minimizer_options(options);
+
+ // TODO(sameeragarwal): Add support for logging the configuration
+ // and more detailed stats.
+ scoped_ptr<IterationCallback> file_logging_callback;
+ if (!options.solver_log.empty()) {
+ file_logging_callback.reset(new FileLoggingCallback(options.solver_log));
+ minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(),
+ file_logging_callback.get());
+ }
+
+ LineSearchLoggingCallback logging_callback(
+ options.minimizer_progress_to_stdout);
+ if (options.logging_type != SILENT) {
+ minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(),
+ &logging_callback);
+ }
+
+ StateUpdatingCallback updating_callback(program, parameters);
+ if (options.update_state_every_iteration) {
+ // This must get pushed to the front of the callbacks so that it is run
+ // before any of the user callbacks.
+ minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(),
+ &updating_callback);
+ }
+
+ minimizer_options.evaluator = evaluator;
+
+ LineSearchMinimizer minimizer;
+ double minimizer_start_time = WallTimeInSeconds();
+ minimizer.Minimize(minimizer_options, parameters, summary);
+ summary->minimizer_time_in_seconds =
+ WallTimeInSeconds() - minimizer_start_time;
+}
+#endif // CERES_NO_LINE_SEARCH_MINIMIZER
+
+void SolverImpl::Solve(const Solver::Options& options,
+ ProblemImpl* problem_impl,
Solver::Summary* summary) {
- time_t solver_start_time = time(NULL);
- Solver::Options options(original_options);
+ if (options.minimizer_type == TRUST_REGION) {
+ TrustRegionSolve(options, problem_impl, summary);
+ } else {
+#ifndef CERES_NO_LINE_SEARCH_MINIMIZER
+ LineSearchSolve(options, problem_impl, summary);
+#else
+ LOG(FATAL) << "Ceres Solver was compiled with -DLINE_SEARCH_MINIMIZER=OFF";
+#endif
+ }
+}
+
+void SolverImpl::TrustRegionSolve(const Solver::Options& original_options,
+ ProblemImpl* original_problem_impl,
+ Solver::Summary* summary) {
+ EventLogger event_logger("TrustRegionSolve");
+ double solver_start_time = WallTimeInSeconds();
+
Program* original_program = original_problem_impl->mutable_program();
ProblemImpl* problem_impl = original_problem_impl;
+
// Reset the summary object to its default values.
*CHECK_NOTNULL(summary) = Solver::Summary();
+ summary->minimizer_type = TRUST_REGION;
+ summary->num_parameter_blocks = problem_impl->NumParameterBlocks();
+ summary->num_parameters = problem_impl->NumParameters();
+ summary->num_effective_parameters =
+ original_program->NumEffectiveParameters();
+ summary->num_residual_blocks = problem_impl->NumResidualBlocks();
+ summary->num_residuals = problem_impl->NumResiduals();
+
+ // Empty programs are usually a user error.
+ if (summary->num_parameter_blocks == 0) {
+ summary->error = "Problem contains no parameter blocks.";
+ LOG(ERROR) << summary->error;
+ return;
+ }
+
+ if (summary->num_residual_blocks == 0) {
+ summary->error = "Problem contains no residual blocks.";
+ LOG(ERROR) << summary->error;
+ return;
+ }
+
+ SummarizeOrdering(original_options.linear_solver_ordering,
+ &(summary->linear_solver_ordering_given));
+
+ SummarizeOrdering(original_options.inner_iteration_ordering,
+ &(summary->inner_iteration_ordering_given));
+
+ Solver::Options options(original_options);
+ options.linear_solver_ordering = NULL;
+ options.inner_iteration_ordering = NULL;
#ifndef CERES_USE_OPENMP
if (options.num_threads > 1) {
LOG(WARNING)
<< "OpenMP support is not compiled into this binary; "
- << "only options.num_threads=1 is supported. Switching"
+ << "only options.num_threads=1 is supported. Switching "
<< "to single threaded mode.";
options.num_threads = 1;
}
if (options.num_linear_solver_threads > 1) {
LOG(WARNING)
<< "OpenMP support is not compiled into this binary; "
- << "only options.num_linear_solver_threads=1 is supported. Switching"
+ << "only options.num_linear_solver_threads=1 is supported. Switching "
<< "to single threaded mode.";
options.num_linear_solver_threads = 1;
}
#endif
- summary->linear_solver_type_given = options.linear_solver_type;
- summary->num_eliminate_blocks_given = original_options.num_eliminate_blocks;
summary->num_threads_given = original_options.num_threads;
- summary->num_linear_solver_threads_given =
- original_options.num_linear_solver_threads;
- summary->ordering_type = original_options.ordering_type;
+ summary->num_threads_used = options.num_threads;
- summary->num_parameter_blocks = problem_impl->NumParameterBlocks();
- summary->num_parameters = problem_impl->NumParameters();
- summary->num_residual_blocks = problem_impl->NumResidualBlocks();
- summary->num_residuals = problem_impl->NumResiduals();
+ if (options.lsqp_iterations_to_dump.size() > 0) {
+ LOG(WARNING) << "Dumping linear least squares problems to disk is"
+ " currently broken. Ignoring Solver::Options::lsqp_iterations_to_dump";
+ }
- summary->num_threads_used = options.num_threads;
- summary->sparse_linear_algebra_library =
- options.sparse_linear_algebra_library;
- summary->trust_region_strategy_type = options.trust_region_strategy_type;
- summary->dogleg_type = options.dogleg_type;
+ event_logger.AddEvent("Init");
- // Evaluate the initial cost, residual vector and the jacobian
- // matrix if requested by the user. The initial cost needs to be
- // computed on the original unpreprocessed problem, as it is used to
- // determine the value of the "fixed" part of the objective function
- // after the problem has undergone reduction.
- Evaluator::Evaluate(
- original_program,
- options.num_threads,
- &(summary->initial_cost),
- options.return_initial_residuals ? &summary->initial_residuals : NULL,
- options.return_initial_gradient ? &summary->initial_gradient : NULL,
- options.return_initial_jacobian ? &summary->initial_jacobian : NULL);
- original_program->SetParameterBlockStatePtrsToUserStatePtrs();
+ original_program->SetParameterBlockStatePtrsToUserStatePtrs();
+ event_logger.AddEvent("SetParameterBlockPtrs");
// If the user requests gradient checking, construct a new
// ProblemImpl by wrapping the CostFunctions of problem_impl inside
// GradientCheckingCostFunction and replacing problem_impl with
// gradient_checking_problem_impl.
scoped_ptr<ProblemImpl> gradient_checking_problem_impl;
- // Save the original problem impl so we don't use the gradient
- // checking one when computing the residuals.
if (options.check_gradients) {
VLOG(1) << "Checking Gradients";
gradient_checking_problem_impl.reset(
@@ -269,45 +411,348 @@ void SolverImpl::Solve(const Solver::Options& original_options,
options.numeric_derivative_relative_step_size,
options.gradient_check_relative_precision));
- // From here on, problem_impl will point to the GradientChecking version.
+ // From here on, problem_impl will point to the gradient checking
+ // version.
problem_impl = gradient_checking_problem_impl.get();
}
+ if (original_options.linear_solver_ordering != NULL) {
+ if (!IsOrderingValid(original_options, problem_impl, &summary->error)) {
+ LOG(ERROR) << summary->error;
+ return;
+ }
+ event_logger.AddEvent("CheckOrdering");
+ options.linear_solver_ordering =
+ new ParameterBlockOrdering(*original_options.linear_solver_ordering);
+ event_logger.AddEvent("CopyOrdering");
+ } else {
+ options.linear_solver_ordering = new ParameterBlockOrdering;
+ const ProblemImpl::ParameterMap& parameter_map =
+ problem_impl->parameter_map();
+ for (ProblemImpl::ParameterMap::const_iterator it = parameter_map.begin();
+ it != parameter_map.end();
+ ++it) {
+ options.linear_solver_ordering->AddElementToGroup(it->first, 0);
+ }
+ event_logger.AddEvent("ConstructOrdering");
+ }
+
// Create the three objects needed to minimize: the transformed program, the
// evaluator, and the linear solver.
-
scoped_ptr<Program> reduced_program(CreateReducedProgram(&options,
problem_impl,
&summary->fixed_cost,
&summary->error));
+
+ event_logger.AddEvent("CreateReducedProgram");
if (reduced_program == NULL) {
return;
}
+ SummarizeOrdering(options.linear_solver_ordering,
+ &(summary->linear_solver_ordering_used));
+
summary->num_parameter_blocks_reduced = reduced_program->NumParameterBlocks();
summary->num_parameters_reduced = reduced_program->NumParameters();
+ summary->num_effective_parameters_reduced =
+ reduced_program->NumEffectiveParameters();
summary->num_residual_blocks_reduced = reduced_program->NumResidualBlocks();
summary->num_residuals_reduced = reduced_program->NumResiduals();
+ if (summary->num_parameter_blocks_reduced == 0) {
+ summary->preprocessor_time_in_seconds =
+ WallTimeInSeconds() - solver_start_time;
+
+ double post_process_start_time = WallTimeInSeconds();
+ LOG(INFO) << "Terminating: FUNCTION_TOLERANCE reached. "
+ << "No non-constant parameter blocks found.";
+
+ summary->initial_cost = summary->fixed_cost;
+ summary->final_cost = summary->fixed_cost;
+
+ // FUNCTION_TOLERANCE is the right convergence here, as we know
+ // that the objective function is constant and cannot be changed
+ // any further.
+ summary->termination_type = FUNCTION_TOLERANCE;
+
+ // Ensure the program state is set to the user parameters on the way out.
+ original_program->SetParameterBlockStatePtrsToUserStatePtrs();
+
+ summary->postprocessor_time_in_seconds =
+ WallTimeInSeconds() - post_process_start_time;
+ return;
+ }
+
scoped_ptr<LinearSolver>
linear_solver(CreateLinearSolver(&options, &summary->error));
+ event_logger.AddEvent("CreateLinearSolver");
+ if (linear_solver == NULL) {
+ return;
+ }
+
+ summary->linear_solver_type_given = original_options.linear_solver_type;
summary->linear_solver_type_used = options.linear_solver_type;
+
summary->preconditioner_type = options.preconditioner_type;
- summary->num_eliminate_blocks_used = options.num_eliminate_blocks;
+
+ summary->num_linear_solver_threads_given =
+ original_options.num_linear_solver_threads;
summary->num_linear_solver_threads_used = options.num_linear_solver_threads;
- if (linear_solver == NULL) {
+ summary->sparse_linear_algebra_library =
+ options.sparse_linear_algebra_library;
+
+ summary->trust_region_strategy_type = options.trust_region_strategy_type;
+ summary->dogleg_type = options.dogleg_type;
+
+ // Only Schur types require the lexicographic reordering.
+ if (IsSchurType(options.linear_solver_type)) {
+ const int num_eliminate_blocks =
+ options.linear_solver_ordering
+ ->group_to_elements().begin()
+ ->second.size();
+ if (!LexicographicallyOrderResidualBlocks(num_eliminate_blocks,
+ reduced_program.get(),
+ &summary->error)) {
+ return;
+ }
+ }
+
+ scoped_ptr<Evaluator> evaluator(CreateEvaluator(options,
+ problem_impl->parameter_map(),
+ reduced_program.get(),
+ &summary->error));
+
+ event_logger.AddEvent("CreateEvaluator");
+
+ if (evaluator == NULL) {
+ return;
+ }
+
+ scoped_ptr<CoordinateDescentMinimizer> inner_iteration_minimizer;
+ if (options.use_inner_iterations) {
+ if (reduced_program->parameter_blocks().size() < 2) {
+ LOG(WARNING) << "Reduced problem only contains one parameter block."
+ << "Disabling inner iterations.";
+ } else {
+ inner_iteration_minimizer.reset(
+ CreateInnerIterationMinimizer(original_options,
+ *reduced_program,
+ problem_impl->parameter_map(),
+ summary));
+ if (inner_iteration_minimizer == NULL) {
+ LOG(ERROR) << summary->error;
+ return;
+ }
+ }
+ }
+
+ event_logger.AddEvent("CreateIIM");
+
+ // The optimizer works on contiguous parameter vectors; allocate some.
+ Vector parameters(reduced_program->NumParameters());
+
+ // Collect the discontiguous parameters into a contiguous state vector.
+ reduced_program->ParameterBlocksToStateVector(parameters.data());
+
+ Vector original_parameters = parameters;
+
+ double minimizer_start_time = WallTimeInSeconds();
+ summary->preprocessor_time_in_seconds =
+ minimizer_start_time - solver_start_time;
+
+ // Run the optimization.
+ TrustRegionMinimize(options,
+ reduced_program.get(),
+ inner_iteration_minimizer.get(),
+ evaluator.get(),
+ linear_solver.get(),
+ parameters.data(),
+ summary);
+ event_logger.AddEvent("Minimize");
+
+ SetSummaryFinalCost(summary);
+
+ // If the user aborted mid-optimization or the optimization
+ // terminated because of a numerical failure, then return without
+ // updating user state.
+ if (summary->termination_type == USER_ABORT ||
+ summary->termination_type == NUMERICAL_FAILURE) {
+ return;
+ }
+
+ double post_process_start_time = WallTimeInSeconds();
+
+ // Push the contiguous optimized parameters back to the user's
+ // parameters.
+ reduced_program->StateVectorToParameterBlocks(parameters.data());
+ reduced_program->CopyParameterBlockStateToUserState();
+
+ // Ensure the program state is set to the user parameters on the way
+ // out.
+ original_program->SetParameterBlockStatePtrsToUserStatePtrs();
+
+ const map<string, double>& linear_solver_time_statistics =
+ linear_solver->TimeStatistics();
+ summary->linear_solver_time_in_seconds =
+ FindWithDefault(linear_solver_time_statistics,
+ "LinearSolver::Solve",
+ 0.0);
+
+ const map<string, double>& evaluator_time_statistics =
+ evaluator->TimeStatistics();
+
+ summary->residual_evaluation_time_in_seconds =
+ FindWithDefault(evaluator_time_statistics, "Evaluator::Residual", 0.0);
+ summary->jacobian_evaluation_time_in_seconds =
+ FindWithDefault(evaluator_time_statistics, "Evaluator::Jacobian", 0.0);
+
+ // Stick a fork in it, we're done.
+ summary->postprocessor_time_in_seconds =
+ WallTimeInSeconds() - post_process_start_time;
+ event_logger.AddEvent("PostProcess");
+}
+
+
+#ifndef CERES_NO_LINE_SEARCH_MINIMIZER
+void SolverImpl::LineSearchSolve(const Solver::Options& original_options,
+ ProblemImpl* original_problem_impl,
+ Solver::Summary* summary) {
+ double solver_start_time = WallTimeInSeconds();
+
+ Program* original_program = original_problem_impl->mutable_program();
+ ProblemImpl* problem_impl = original_problem_impl;
+
+ // Reset the summary object to its default values.
+ *CHECK_NOTNULL(summary) = Solver::Summary();
+
+ summary->minimizer_type = LINE_SEARCH;
+ summary->line_search_direction_type =
+ original_options.line_search_direction_type;
+ summary->max_lbfgs_rank = original_options.max_lbfgs_rank;
+ summary->line_search_type = original_options.line_search_type;
+ summary->num_parameter_blocks = problem_impl->NumParameterBlocks();
+ summary->num_parameters = problem_impl->NumParameters();
+ summary->num_residual_blocks = problem_impl->NumResidualBlocks();
+ summary->num_residuals = problem_impl->NumResiduals();
+
+ // Empty programs are usually a user error.
+ if (summary->num_parameter_blocks == 0) {
+ summary->error = "Problem contains no parameter blocks.";
+ LOG(ERROR) << summary->error;
return;
}
- if (!MaybeReorderResidualBlocks(options,
- reduced_program.get(),
- &summary->error)) {
+ if (summary->num_residual_blocks == 0) {
+ summary->error = "Problem contains no residual blocks.";
+ LOG(ERROR) << summary->error;
return;
}
- scoped_ptr<Evaluator> evaluator(
- CreateEvaluator(options, reduced_program.get(), &summary->error));
+ Solver::Options options(original_options);
+
+ // This ensures that we get a Block Jacobian Evaluator along with
+ // none of the Schur nonsense. This file will have to be extensively
+ // refactored to deal with the various bits of cleanups related to
+ // line search.
+ options.linear_solver_type = CGNR;
+
+ options.linear_solver_ordering = NULL;
+ options.inner_iteration_ordering = NULL;
+
+#ifndef CERES_USE_OPENMP
+ if (options.num_threads > 1) {
+ LOG(WARNING)
+ << "OpenMP support is not compiled into this binary; "
+ << "only options.num_threads=1 is supported. Switching "
+ << "to single threaded mode.";
+ options.num_threads = 1;
+ }
+#endif // CERES_USE_OPENMP
+
+ summary->num_threads_given = original_options.num_threads;
+ summary->num_threads_used = options.num_threads;
+
+ if (original_options.linear_solver_ordering != NULL) {
+ if (!IsOrderingValid(original_options, problem_impl, &summary->error)) {
+ LOG(ERROR) << summary->error;
+ return;
+ }
+ options.linear_solver_ordering =
+ new ParameterBlockOrdering(*original_options.linear_solver_ordering);
+ } else {
+ options.linear_solver_ordering = new ParameterBlockOrdering;
+ const ProblemImpl::ParameterMap& parameter_map =
+ problem_impl->parameter_map();
+ for (ProblemImpl::ParameterMap::const_iterator it = parameter_map.begin();
+ it != parameter_map.end();
+ ++it) {
+ options.linear_solver_ordering->AddElementToGroup(it->first, 0);
+ }
+ }
+
+ original_program->SetParameterBlockStatePtrsToUserStatePtrs();
+
+ // If the user requests gradient checking, construct a new
+ // ProblemImpl by wrapping the CostFunctions of problem_impl inside
+ // GradientCheckingCostFunction and replacing problem_impl with
+ // gradient_checking_problem_impl.
+ scoped_ptr<ProblemImpl> gradient_checking_problem_impl;
+ if (options.check_gradients) {
+ VLOG(1) << "Checking Gradients";
+ gradient_checking_problem_impl.reset(
+ CreateGradientCheckingProblemImpl(
+ problem_impl,
+ options.numeric_derivative_relative_step_size,
+ options.gradient_check_relative_precision));
+
+ // From here on, problem_impl will point to the gradient checking
+ // version.
+ problem_impl = gradient_checking_problem_impl.get();
+ }
+
+ // Create the three objects needed to minimize: the transformed program, the
+ // evaluator, and the linear solver.
+ scoped_ptr<Program> reduced_program(CreateReducedProgram(&options,
+ problem_impl,
+ &summary->fixed_cost,
+ &summary->error));
+ if (reduced_program == NULL) {
+ return;
+ }
+
+ summary->num_parameter_blocks_reduced = reduced_program->NumParameterBlocks();
+ summary->num_parameters_reduced = reduced_program->NumParameters();
+ summary->num_residual_blocks_reduced = reduced_program->NumResidualBlocks();
+ summary->num_residuals_reduced = reduced_program->NumResiduals();
+
+ if (summary->num_parameter_blocks_reduced == 0) {
+ summary->preprocessor_time_in_seconds =
+ WallTimeInSeconds() - solver_start_time;
+
+ LOG(INFO) << "Terminating: FUNCTION_TOLERANCE reached. "
+ << "No non-constant parameter blocks found.";
+
+ // FUNCTION_TOLERANCE is the right convergence here, as we know
+ // that the objective function is constant and cannot be changed
+ // any further.
+ summary->termination_type = FUNCTION_TOLERANCE;
+
+ const double post_process_start_time = WallTimeInSeconds();
+
+ SetSummaryFinalCost(summary);
+
+ // Ensure the program state is set to the user parameters on the way out.
+ original_program->SetParameterBlockStatePtrsToUserStatePtrs();
+ summary->postprocessor_time_in_seconds =
+ WallTimeInSeconds() - post_process_start_time;
+ return;
+ }
+
+ scoped_ptr<Evaluator> evaluator(CreateEvaluator(options,
+ problem_impl->parameter_map(),
+ reduced_program.get(),
+ &summary->error));
if (evaluator == NULL) {
return;
}
@@ -318,17 +763,18 @@ void SolverImpl::Solve(const Solver::Options& original_options,
// Collect the discontiguous parameters into a contiguous state vector.
reduced_program->ParameterBlocksToStateVector(parameters.data());
- time_t minimizer_start_time = time(NULL);
+ Vector original_parameters = parameters;
+
+ const double minimizer_start_time = WallTimeInSeconds();
summary->preprocessor_time_in_seconds =
minimizer_start_time - solver_start_time;
// Run the optimization.
- Minimize(options,
- reduced_program.get(),
- evaluator.get(),
- linear_solver.get(),
- parameters.data(),
- summary);
+ LineSearchMinimize(options,
+ reduced_program.get(),
+ evaluator.get(),
+ parameters.data(),
+ summary);
// If the user aborted mid-optimization or the optimization
// terminated because of a numerical failure, then return without
@@ -338,35 +784,100 @@ void SolverImpl::Solve(const Solver::Options& original_options,
return;
}
- time_t post_process_start_time = time(NULL);
+ const double post_process_start_time = WallTimeInSeconds();
// Push the contiguous optimized parameters back to the user's parameters.
reduced_program->StateVectorToParameterBlocks(parameters.data());
reduced_program->CopyParameterBlockStateToUserState();
- // Evaluate the final cost, residual vector and the jacobian
- // matrix if requested by the user.
- Evaluator::Evaluate(
- original_program,
- options.num_threads,
- &summary->final_cost,
- options.return_final_residuals ? &summary->final_residuals : NULL,
- options.return_final_gradient ? &summary->final_gradient : NULL,
- options.return_final_jacobian ? &summary->final_jacobian : NULL);
+ SetSummaryFinalCost(summary);
// Ensure the program state is set to the user parameters on the way out.
original_program->SetParameterBlockStatePtrsToUserStatePtrs();
+
+ const map<string, double>& evaluator_time_statistics =
+ evaluator->TimeStatistics();
+
+ summary->residual_evaluation_time_in_seconds =
+ FindWithDefault(evaluator_time_statistics, "Evaluator::Residual", 0.0);
+ summary->jacobian_evaluation_time_in_seconds =
+ FindWithDefault(evaluator_time_statistics, "Evaluator::Jacobian", 0.0);
+
// Stick a fork in it, we're done.
- summary->postprocessor_time_in_seconds = time(NULL) - post_process_start_time;
+ summary->postprocessor_time_in_seconds =
+ WallTimeInSeconds() - post_process_start_time;
+}
+#endif // CERES_NO_LINE_SEARCH_MINIMIZER
+
+bool SolverImpl::IsOrderingValid(const Solver::Options& options,
+ const ProblemImpl* problem_impl,
+ string* error) {
+ if (options.linear_solver_ordering->NumElements() !=
+ problem_impl->NumParameterBlocks()) {
+ *error = "Number of parameter blocks in user supplied ordering "
+ "does not match the number of parameter blocks in the problem";
+ return false;
+ }
+
+ const Program& program = problem_impl->program();
+ const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks();
+ for (vector<ParameterBlock*>::const_iterator it = parameter_blocks.begin();
+ it != parameter_blocks.end();
+ ++it) {
+ if (!options.linear_solver_ordering
+ ->IsMember(const_cast<double*>((*it)->user_state()))) {
+ *error = "Problem contains a parameter block that is not in "
+ "the user specified ordering.";
+ return false;
+ }
+ }
+
+ if (IsSchurType(options.linear_solver_type) &&
+ options.linear_solver_ordering->NumGroups() > 1) {
+ const vector<ResidualBlock*>& residual_blocks = program.residual_blocks();
+ const set<double*>& e_blocks =
+ options.linear_solver_ordering->group_to_elements().begin()->second;
+ if (!IsParameterBlockSetIndependent(e_blocks, residual_blocks)) {
+ *error = "The user requested the use of a Schur type solver. "
+ "But the first elimination group in the ordering is not an "
+ "independent set.";
+ return false;
+ }
+ }
+ return true;
}
+bool SolverImpl::IsParameterBlockSetIndependent(
+ const set<double*>& parameter_block_ptrs,
+ const vector<ResidualBlock*>& residual_blocks) {
+ // Loop over each residual block and ensure that no two parameter
+ // blocks in the same residual block are part of
+ // parameter_block_ptrs as that would violate the assumption that it
+ // is an independent set in the Hessian matrix.
+ for (vector<ResidualBlock*>::const_iterator it = residual_blocks.begin();
+ it != residual_blocks.end();
+ ++it) {
+ ParameterBlock* const* parameter_blocks = (*it)->parameter_blocks();
+ const int num_parameter_blocks = (*it)->NumParameterBlocks();
+ int count = 0;
+ for (int i = 0; i < num_parameter_blocks; ++i) {
+ count += parameter_block_ptrs.count(
+ parameter_blocks[i]->mutable_user_state());
+ }
+ if (count > 1) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
// Strips varying parameters and residuals, maintaining order, and updating
// num_eliminate_blocks.
bool SolverImpl::RemoveFixedBlocksFromProgram(Program* program,
- int* num_eliminate_blocks,
+ ParameterBlockOrdering* ordering,
double* fixed_cost,
string* error) {
- int original_num_eliminate_blocks = *num_eliminate_blocks;
vector<ParameterBlock*>* parameter_blocks =
program->mutable_parameter_blocks();
@@ -410,8 +921,11 @@ bool SolverImpl::RemoveFixedBlocksFromProgram(Program* program,
// The residual is constant and will be removed, so its cost is
// added to the variable fixed_cost.
double cost = 0.0;
- if (!residual_block->Evaluate(
- &cost, NULL, NULL, residual_block_evaluate_scratch.get())) {
+ if (!residual_block->Evaluate(true,
+ &cost,
+ NULL,
+ NULL,
+ residual_block_evaluate_scratch.get())) {
*error = StringPrintf("Evaluation of the residual %d failed during "
"removal of fixed residual blocks.", i);
return false;
@@ -423,7 +937,7 @@ bool SolverImpl::RemoveFixedBlocksFromProgram(Program* program,
}
// Filter out unused or fixed parameter blocks, and update
- // num_eliminate_blocks as necessary.
+ // the ordering.
{
vector<ParameterBlock*>* parameter_blocks =
program->mutable_parameter_blocks();
@@ -432,8 +946,8 @@ bool SolverImpl::RemoveFixedBlocksFromProgram(Program* program,
ParameterBlock* parameter_block = (*parameter_blocks)[i];
if (parameter_block->index() == 1) {
(*parameter_blocks)[j++] = parameter_block;
- } else if (i < original_num_eliminate_blocks) {
- (*num_eliminate_blocks)--;
+ } else {
+ ordering->Remove(parameter_block->mutable_user_state());
}
}
parameter_blocks->resize(j);
@@ -451,70 +965,127 @@ Program* SolverImpl::CreateReducedProgram(Solver::Options* options,
ProblemImpl* problem_impl,
double* fixed_cost,
string* error) {
+ EventLogger event_logger("CreateReducedProgram");
+
+ CHECK_NOTNULL(options->linear_solver_ordering);
Program* original_program = problem_impl->mutable_program();
scoped_ptr<Program> transformed_program(new Program(*original_program));
+ event_logger.AddEvent("TransformedProgram");
- if (options->ordering_type == USER &&
- !ApplyUserOrdering(*problem_impl,
- options->ordering,
- transformed_program.get(),
- error)) {
- return NULL;
- }
-
- if (options->ordering_type == SCHUR && options->num_eliminate_blocks != 0) {
- *error = "Can't specify SCHUR ordering and num_eliminate_blocks "
- "at the same time; SCHUR ordering determines "
- "num_eliminate_blocks automatically.";
- return NULL;
- }
-
- if (options->ordering_type == SCHUR && options->ordering.size() != 0) {
- *error = "Can't specify SCHUR ordering type and the ordering "
- "vector at the same time; SCHUR ordering determines "
- "a suitable parameter ordering automatically.";
- return NULL;
- }
+ ParameterBlockOrdering* linear_solver_ordering =
+ options->linear_solver_ordering;
- int num_eliminate_blocks = options->num_eliminate_blocks;
+ const int min_group_id =
+ linear_solver_ordering->group_to_elements().begin()->first;
+ const int original_num_groups = linear_solver_ordering->NumGroups();
if (!RemoveFixedBlocksFromProgram(transformed_program.get(),
- &num_eliminate_blocks,
+ linear_solver_ordering,
fixed_cost,
error)) {
return NULL;
}
+ event_logger.AddEvent("RemoveFixedBlocks");
+
if (transformed_program->NumParameterBlocks() == 0) {
+ if (transformed_program->NumResidualBlocks() > 0) {
+ *error = "Zero parameter blocks but non-zero residual blocks"
+ " in the reduced program. Congratulations, you found a "
+ "Ceres bug! Please report this error to the developers.";
+ return NULL;
+ }
+
LOG(WARNING) << "No varying parameter blocks to optimize; "
<< "bailing early.";
return transformed_program.release();
}
- if (options->ordering_type == SCHUR) {
+ // If the user supplied an linear_solver_ordering with just one
+ // group, it is equivalent to the user supplying NULL as
+ // ordering. Ceres is completely free to choose the parameter block
+ // ordering as it sees fit. For Schur type solvers, this means that
+ // the user wishes for Ceres to identify the e_blocks, which we do
+ // by computing a maximal independent set.
+ if (original_num_groups == 1 && IsSchurType(options->linear_solver_type)) {
vector<ParameterBlock*> schur_ordering;
- num_eliminate_blocks = ComputeSchurOrdering(*transformed_program,
- &schur_ordering);
+ const int num_eliminate_blocks = ComputeSchurOrdering(*transformed_program,
+ &schur_ordering);
CHECK_EQ(schur_ordering.size(), transformed_program->NumParameterBlocks())
<< "Congratulations, you found a Ceres bug! Please report this error "
<< "to the developers.";
- // Replace the transformed program's ordering with the schur ordering.
- swap(*transformed_program->mutable_parameter_blocks(), schur_ordering);
+ for (int i = 0; i < schur_ordering.size(); ++i) {
+ linear_solver_ordering->AddElementToGroup(
+ schur_ordering[i]->mutable_user_state(),
+ (i < num_eliminate_blocks) ? 0 : 1);
+ }
+ }
+ event_logger.AddEvent("SchurOrdering");
+
+ if (!ApplyUserOrdering(problem_impl->parameter_map(),
+ linear_solver_ordering,
+ transformed_program.get(),
+ error)) {
+ return NULL;
}
- options->num_eliminate_blocks = num_eliminate_blocks;
- CHECK_GE(options->num_eliminate_blocks, 0)
- << "Congratulations, you found a Ceres bug! Please report this error "
- << "to the developers.";
+ event_logger.AddEvent("ApplyOrdering");
+
+ // If the user requested the use of a Schur type solver, and
+ // supplied a non-NULL linear_solver_ordering object with more than
+ // one elimination group, then it can happen that after all the
+ // parameter blocks which are fixed or unused have been removed from
+ // the program and the ordering, there are no more parameter blocks
+ // in the first elimination group.
+ //
+ // In such a case, the use of a Schur type solver is not possible,
+ // as they assume there is at least one e_block. Thus, we
+ // automatically switch to one of the other solvers, depending on
+ // the user's indicated preferences.
+ if (IsSchurType(options->linear_solver_type) &&
+ original_num_groups > 1 &&
+ linear_solver_ordering->GroupSize(min_group_id) == 0) {
+ string msg = "No e_blocks remaining. Switching from ";
+ if (options->linear_solver_type == SPARSE_SCHUR) {
+ options->linear_solver_type = SPARSE_NORMAL_CHOLESKY;
+ msg += "SPARSE_SCHUR to SPARSE_NORMAL_CHOLESKY.";
+ } else if (options->linear_solver_type == DENSE_SCHUR) {
+ // TODO(sameeragarwal): This is probably not a great choice.
+ // Ideally, we should have a DENSE_NORMAL_CHOLESKY, that can
+ // take a BlockSparseMatrix as input.
+ options->linear_solver_type = DENSE_QR;
+ msg += "DENSE_SCHUR to DENSE_QR.";
+ } else if (options->linear_solver_type == ITERATIVE_SCHUR) {
+ msg += StringPrintf("ITERATIVE_SCHUR with %s preconditioner "
+ "to CGNR with JACOBI preconditioner.",
+ PreconditionerTypeToString(
+ options->preconditioner_type));
+ options->linear_solver_type = CGNR;
+ if (options->preconditioner_type != IDENTITY) {
+ // CGNR currently only supports the JACOBI preconditioner.
+ options->preconditioner_type = JACOBI;
+ }
+ }
+
+ LOG(WARNING) << msg;
+ }
+
+ event_logger.AddEvent("AlternateSolver");
- // Since the transformed program is the "active" program, and it is mutated,
- // update the parameter offsets and indices.
+ // Since the transformed program is the "active" program, and it is
+ // mutated, update the parameter offsets and indices.
transformed_program->SetParameterOffsetsAndIndex();
+
+ event_logger.AddEvent("SetOffsets");
return transformed_program.release();
}
LinearSolver* SolverImpl::CreateLinearSolver(Solver::Options* options,
string* error) {
+ CHECK_NOTNULL(options);
+ CHECK_NOTNULL(options->linear_solver_ordering);
+ CHECK_NOTNULL(error);
+
if (options->trust_region_strategy_type == DOGLEG) {
if (options->linear_solver_type == ITERATIVE_SCHUR ||
options->linear_solver_type == CGNR) {
@@ -532,6 +1103,18 @@ LinearSolver* SolverImpl::CreateLinearSolver(Solver::Options* options,
"SuiteSparse was not enabled when Ceres was built.";
return NULL;
}
+
+ if (options->preconditioner_type == CLUSTER_JACOBI) {
+ *error = "CLUSTER_JACOBI preconditioner not suppored. Please build Ceres "
+ "with SuiteSparse support.";
+ return NULL;
+ }
+
+ if (options->preconditioner_type == CLUSTER_TRIDIAGONAL) {
+ *error = "CLUSTER_TRIDIAGONAL preconditioner not suppored. Please build "
+ "Ceres with SuiteSparse support.";
+ return NULL;
+ }
#endif
#ifdef CERES_NO_CXSPARSE
@@ -543,6 +1126,13 @@ LinearSolver* SolverImpl::CreateLinearSolver(Solver::Options* options,
}
#endif
+#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE)
+ if (options->linear_solver_type == SPARSE_SCHUR) {
+ *error = "Can't use SPARSE_SCHUR because neither SuiteSparse nor"
+ "CXSparse was enabled when Ceres was compiled.";
+ return NULL;
+ }
+#endif
if (options->linear_solver_max_num_iterations <= 0) {
*error = "Solver::Options::linear_solver_max_num_iterations is 0.";
@@ -568,116 +1158,69 @@ LinearSolver* SolverImpl::CreateLinearSolver(Solver::Options* options,
linear_solver_options.preconditioner_type = options->preconditioner_type;
linear_solver_options.sparse_linear_algebra_library =
options->sparse_linear_algebra_library;
- linear_solver_options.use_block_amd = options->use_block_amd;
-
-#ifdef CERES_NO_SUITESPARSE
- if (linear_solver_options.preconditioner_type == SCHUR_JACOBI) {
- *error = "SCHUR_JACOBI preconditioner not suppored. Please build Ceres "
- "with SuiteSparse support.";
- return NULL;
- }
-
- if (linear_solver_options.preconditioner_type == CLUSTER_JACOBI) {
- *error = "CLUSTER_JACOBI preconditioner not suppored. Please build Ceres "
- "with SuiteSparse support.";
- return NULL;
- }
-
- if (linear_solver_options.preconditioner_type == CLUSTER_TRIDIAGONAL) {
- *error = "CLUSTER_TRIDIAGONAL preconditioner not suppored. Please build "
- "Ceres with SuiteSparse support.";
- return NULL;
- }
-#endif
linear_solver_options.num_threads = options->num_linear_solver_threads;
- linear_solver_options.num_eliminate_blocks =
- options->num_eliminate_blocks;
+ options->num_linear_solver_threads = linear_solver_options.num_threads;
- if ((linear_solver_options.num_eliminate_blocks == 0) &&
- IsSchurType(linear_solver_options.type)) {
-#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE)
- LOG(INFO) << "No elimination block remaining switching to DENSE_QR.";
- linear_solver_options.type = DENSE_QR;
-#else
- LOG(INFO) << "No elimination block remaining "
- << "switching to SPARSE_NORMAL_CHOLESKY.";
- linear_solver_options.type = SPARSE_NORMAL_CHOLESKY;
-#endif
+ linear_solver_options.use_block_amd = options->use_block_amd;
+ const map<int, set<double*> >& groups =
+ options->linear_solver_ordering->group_to_elements();
+ for (map<int, set<double*> >::const_iterator it = groups.begin();
+ it != groups.end();
+ ++it) {
+ linear_solver_options.elimination_groups.push_back(it->second.size());
}
-
-#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE)
- if (linear_solver_options.type == SPARSE_SCHUR) {
- *error = "Can't use SPARSE_SCHUR because neither SuiteSparse nor"
- "CXSparse was enabled when Ceres was compiled.";
- return NULL;
+ // Schur type solvers, expect at least two elimination groups. If
+ // there is only one elimination group, then CreateReducedProgram
+ // guarantees that this group only contains e_blocks. Thus we add a
+ // dummy elimination group with zero blocks in it.
+ if (IsSchurType(linear_solver_options.type) &&
+ linear_solver_options.elimination_groups.size() == 1) {
+ linear_solver_options.elimination_groups.push_back(0);
}
-#endif
-
- // The matrix used for storing the dense Schur complement has a
- // single lock guarding the whole matrix. Running the
- // SchurComplementSolver with multiple threads leads to maximum
- // contention and slowdown. If the problem is large enough to
- // benefit from a multithreaded schur eliminator, you should be
- // using a SPARSE_SCHUR solver anyways.
- if ((linear_solver_options.num_threads > 1) &&
- (linear_solver_options.type == DENSE_SCHUR)) {
- LOG(WARNING) << "Warning: Solver::Options::num_linear_solver_threads = "
- << options->num_linear_solver_threads
- << " with DENSE_SCHUR will result in poor performance; "
- << "switching to single-threaded.";
- linear_solver_options.num_threads = 1;
- }
-
- options->linear_solver_type = linear_solver_options.type;
- options->num_linear_solver_threads = linear_solver_options.num_threads;
return LinearSolver::Create(linear_solver_options);
}
-bool SolverImpl::ApplyUserOrdering(const ProblemImpl& problem_impl,
- vector<double*>& ordering,
- Program* program,
- string* error) {
- if (ordering.size() != program->NumParameterBlocks()) {
+bool SolverImpl::ApplyUserOrdering(
+ const ProblemImpl::ParameterMap& parameter_map,
+ const ParameterBlockOrdering* ordering,
+ Program* program,
+ string* error) {
+ if (ordering->NumElements() != program->NumParameterBlocks()) {
*error = StringPrintf("User specified ordering does not have the same "
"number of parameters as the problem. The problem"
- "has %d blocks while the ordering has %ld blocks.",
+ "has %d blocks while the ordering has %d blocks.",
program->NumParameterBlocks(),
- ordering.size());
+ ordering->NumElements());
return false;
}
- // Ensure that there are no duplicates in the user's ordering.
- {
- vector<double*> ordering_copy(ordering);
- sort(ordering_copy.begin(), ordering_copy.end());
- if (unique(ordering_copy.begin(), ordering_copy.end())
- != ordering_copy.end()) {
- *error = "User specified ordering contains duplicates.";
- return false;
- }
- }
-
vector<ParameterBlock*>* parameter_blocks =
program->mutable_parameter_blocks();
-
- fill(parameter_blocks->begin(),
- parameter_blocks->end(),
- static_cast<ParameterBlock*>(NULL));
-
- const ProblemImpl::ParameterMap& parameter_map = problem_impl.parameter_map();
- for (int i = 0; i < ordering.size(); ++i) {
- ProblemImpl::ParameterMap::const_iterator it =
- parameter_map.find(ordering[i]);
- if (it == parameter_map.end()) {
- *error = StringPrintf("User specified ordering contains a pointer "
- "to a double that is not a parameter block in the "
- "problem. The invalid double is at position %d "
- " in options.ordering.", i);
- return false;
+ parameter_blocks->clear();
+
+ const map<int, set<double*> >& groups =
+ ordering->group_to_elements();
+
+ for (map<int, set<double*> >::const_iterator group_it = groups.begin();
+ group_it != groups.end();
+ ++group_it) {
+ const set<double*>& group = group_it->second;
+ for (set<double*>::const_iterator parameter_block_ptr_it = group.begin();
+ parameter_block_ptr_it != group.end();
+ ++parameter_block_ptr_it) {
+ ProblemImpl::ParameterMap::const_iterator parameter_block_it =
+ parameter_map.find(*parameter_block_ptr_it);
+ if (parameter_block_it == parameter_map.end()) {
+ *error = StringPrintf("User specified ordering contains a pointer "
+ "to a double that is not a parameter block in "
+ "the problem. The invalid double is in group: %d",
+ group_it->first);
+ return false;
+ }
+ parameter_blocks->push_back(parameter_block_it->second);
}
- (*parameter_blocks)[i] = it->second;
}
return true;
}
@@ -704,36 +1247,31 @@ static int MinParameterBlock(const ResidualBlock* residual_block,
// Reorder the residuals for program, if necessary, so that the residuals
// involving each E block occur together. This is a necessary condition for the
// Schur eliminator, which works on these "row blocks" in the jacobian.
-bool SolverImpl::MaybeReorderResidualBlocks(const Solver::Options& options,
- Program* program,
- string* error) {
- // Only Schur types require the lexicographic reordering.
- if (!IsSchurType(options.linear_solver_type)) {
- return true;
- }
-
- CHECK_NE(0, options.num_eliminate_blocks)
- << "Congratulations, you found a Ceres bug! Please report this error "
- << "to the developers.";
+bool SolverImpl::LexicographicallyOrderResidualBlocks(
+ const int num_eliminate_blocks,
+ Program* program,
+ string* error) {
+ CHECK_GE(num_eliminate_blocks, 1)
+ << "Congratulations, you found a Ceres bug! Please report this error "
+ << "to the developers.";
// Create a histogram of the number of residuals for each E block. There is an
// extra bucket at the end to catch all non-eliminated F blocks.
- vector<int> residual_blocks_per_e_block(options.num_eliminate_blocks + 1);
+ vector<int> residual_blocks_per_e_block(num_eliminate_blocks + 1);
vector<ResidualBlock*>* residual_blocks = program->mutable_residual_blocks();
vector<int> min_position_per_residual(residual_blocks->size());
for (int i = 0; i < residual_blocks->size(); ++i) {
ResidualBlock* residual_block = (*residual_blocks)[i];
- int position = MinParameterBlock(residual_block,
- options.num_eliminate_blocks);
+ int position = MinParameterBlock(residual_block, num_eliminate_blocks);
min_position_per_residual[i] = position;
- DCHECK_LE(position, options.num_eliminate_blocks);
+ DCHECK_LE(position, num_eliminate_blocks);
residual_blocks_per_e_block[position]++;
}
// Run a cumulative sum on the histogram, to obtain offsets to the start of
// each histogram bucket (where each bucket is for the residuals for that
// E-block).
- vector<int> offsets(options.num_eliminate_blocks + 1);
+ vector<int> offsets(num_eliminate_blocks + 1);
std::partial_sum(residual_blocks_per_e_block.begin(),
residual_blocks_per_e_block.end(),
offsets.begin());
@@ -772,7 +1310,7 @@ bool SolverImpl::MaybeReorderResidualBlocks(const Solver::Options& options,
// Sanity check #1: The difference in bucket offsets should match the
// histogram sizes.
- for (int i = 0; i < options.num_eliminate_blocks; ++i) {
+ for (int i = 0; i < num_eliminate_blocks; ++i) {
CHECK_EQ(residual_blocks_per_e_block[i], offsets[i + 1] - offsets[i])
<< "Congratulations, you found a Ceres bug! Please report this error "
<< "to the developers.";
@@ -789,15 +1327,76 @@ bool SolverImpl::MaybeReorderResidualBlocks(const Solver::Options& options,
return true;
}
-Evaluator* SolverImpl::CreateEvaluator(const Solver::Options& options,
- Program* program,
- string* error) {
+Evaluator* SolverImpl::CreateEvaluator(
+ const Solver::Options& options,
+ const ProblemImpl::ParameterMap& parameter_map,
+ Program* program,
+ string* error) {
Evaluator::Options evaluator_options;
evaluator_options.linear_solver_type = options.linear_solver_type;
- evaluator_options.num_eliminate_blocks = options.num_eliminate_blocks;
+ evaluator_options.num_eliminate_blocks =
+ (options.linear_solver_ordering->NumGroups() > 0 &&
+ IsSchurType(options.linear_solver_type))
+ ? (options.linear_solver_ordering
+ ->group_to_elements().begin()
+ ->second.size())
+ : 0;
evaluator_options.num_threads = options.num_threads;
return Evaluator::Create(evaluator_options, program, error);
}
+CoordinateDescentMinimizer* SolverImpl::CreateInnerIterationMinimizer(
+ const Solver::Options& options,
+ const Program& program,
+ const ProblemImpl::ParameterMap& parameter_map,
+ Solver::Summary* summary) {
+ scoped_ptr<CoordinateDescentMinimizer> inner_iteration_minimizer(
+ new CoordinateDescentMinimizer);
+ scoped_ptr<ParameterBlockOrdering> inner_iteration_ordering;
+ ParameterBlockOrdering* ordering_ptr = NULL;
+
+ if (options.inner_iteration_ordering == NULL) {
+ // Find a recursive decomposition of the Hessian matrix as a set
+ // of independent sets of decreasing size and invert it. This
+ // seems to work better in practice, i.e., Cameras before
+ // points.
+ inner_iteration_ordering.reset(new ParameterBlockOrdering);
+ ComputeRecursiveIndependentSetOrdering(program,
+ inner_iteration_ordering.get());
+ inner_iteration_ordering->Reverse();
+ ordering_ptr = inner_iteration_ordering.get();
+ } else {
+ const map<int, set<double*> >& group_to_elements =
+ options.inner_iteration_ordering->group_to_elements();
+
+ // Iterate over each group and verify that it is an independent
+ // set.
+ map<int, set<double*> >::const_iterator it = group_to_elements.begin();
+ for ( ; it != group_to_elements.end(); ++it) {
+ if (!IsParameterBlockSetIndependent(it->second,
+ program.residual_blocks())) {
+ summary->error =
+ StringPrintf("The user-provided "
+ "parameter_blocks_for_inner_iterations does not "
+ "form an independent set. Group Id: %d", it->first);
+ return NULL;
+ }
+ }
+ ordering_ptr = options.inner_iteration_ordering;
+ }
+
+ if (!inner_iteration_minimizer->Init(program,
+ parameter_map,
+ *ordering_ptr,
+ &summary->error)) {
+ return NULL;
+ }
+
+ summary->inner_iterations = true;
+ SummarizeOrdering(ordering_ptr, &(summary->inner_iteration_ordering_used));
+
+ return inner_iteration_minimizer.release();
+}
+
} // namespace internal
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h
index 11b44de6f42..c05483021a4 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h
@@ -31,17 +31,20 @@
#ifndef CERES_INTERNAL_SOLVER_IMPL_H_
#define CERES_INTERNAL_SOLVER_IMPL_H_
+#include <set>
#include <string>
#include <vector>
#include "ceres/internal/port.h"
+#include "ceres/ordered_groups.h"
+#include "ceres/problem_impl.h"
#include "ceres/solver.h"
namespace ceres {
namespace internal {
+class CoordinateDescentMinimizer;
class Evaluator;
class LinearSolver;
-class ProblemImpl;
class Program;
class SolverImpl {
@@ -52,10 +55,38 @@ class SolverImpl {
ProblemImpl* problem_impl,
Solver::Summary* summary);
+ static void TrustRegionSolve(const Solver::Options& options,
+ ProblemImpl* problem_impl,
+ Solver::Summary* summary);
+
+ // Run the TrustRegionMinimizer for the given evaluator and configuration.
+ static void TrustRegionMinimize(
+ const Solver::Options &options,
+ Program* program,
+ CoordinateDescentMinimizer* inner_iteration_minimizer,
+ Evaluator* evaluator,
+ LinearSolver* linear_solver,
+ double* parameters,
+ Solver::Summary* summary);
+
+#ifndef CERES_NO_LINE_SEARCH_MINIMIZER
+ static void LineSearchSolve(const Solver::Options& options,
+ ProblemImpl* problem_impl,
+ Solver::Summary* summary);
+
+ // Run the LineSearchMinimizer for the given evaluator and configuration.
+ static void LineSearchMinimize(const Solver::Options &options,
+ Program* program,
+ Evaluator* evaluator,
+ double* parameters,
+ Solver::Summary* summary);
+#endif // CERES_NO_LINE_SEARCH_MINIMIZER
+
// Create the transformed Program, which has all the fixed blocks
// and residuals eliminated, and in the case of automatic schur
// ordering, has the E blocks first in the resulting program, with
// options.num_eliminate_blocks set appropriately.
+ //
// If fixed_cost is not NULL, the residual blocks that are removed
// are evaluated and the sum of their cost is returned in fixed_cost.
static Program* CreateReducedProgram(Solver::Options* options,
@@ -71,46 +102,55 @@ class SolverImpl {
static LinearSolver* CreateLinearSolver(Solver::Options* options,
string* error);
- // Reorder the parameter blocks in program using the vector
- // ordering. A return value of true indicates success and false
- // indicates an error was encountered whose cause is logged to
- // LOG(ERROR).
- static bool ApplyUserOrdering(const ProblemImpl& problem_impl,
- vector<double*>& ordering,
+ // Reorder the parameter blocks in program using the ordering. A
+ // return value of true indicates success and false indicates an
+ // error was encountered whose cause is logged to LOG(ERROR).
+ static bool ApplyUserOrdering(const ProblemImpl::ParameterMap& parameter_map,
+ const ParameterBlockOrdering* ordering,
Program* program,
string* error);
+
// Reorder the residuals for program, if necessary, so that the
- // residuals involving each E block occur together. This is a
- // necessary condition for the Schur eliminator, which works on
- // these "row blocks" in the jacobian.
- static bool MaybeReorderResidualBlocks(const Solver::Options& options,
- Program* program,
- string* error);
+ // residuals involving e block (i.e., the first num_eliminate_block
+ // parameter blocks) occur together. This is a necessary condition
+ // for the Schur eliminator.
+ static bool LexicographicallyOrderResidualBlocks(
+ const int num_eliminate_blocks,
+ Program* program,
+ string* error);
// Create the appropriate evaluator for the transformed program.
- static Evaluator* CreateEvaluator(const Solver::Options& options,
- Program* program,
- string* error);
-
- // Run the minimization for the given evaluator and configuration.
- static void Minimize(const Solver::Options &options,
- Program* program,
- Evaluator* evaluator,
- LinearSolver* linear_solver,
- double* parameters,
- Solver::Summary* summary);
+ static Evaluator* CreateEvaluator(
+ const Solver::Options& options,
+ const ProblemImpl::ParameterMap& parameter_map,
+ Program* program,
+ string* error);
// Remove the fixed or unused parameter blocks and residuals
// depending only on fixed parameters from the problem. Also updates
// num_eliminate_blocks, since removed parameters changes the point
- // at which the eliminated blocks is valid.
- // If fixed_cost is not NULL, the residual blocks that are removed
- // are evaluated and the sum of their cost is returned in fixed_cost.
+ // at which the eliminated blocks is valid. If fixed_cost is not
+ // NULL, the residual blocks that are removed are evaluated and the
+ // sum of their cost is returned in fixed_cost.
static bool RemoveFixedBlocksFromProgram(Program* program,
- int* num_eliminate_blocks,
+ ParameterBlockOrdering* ordering,
double* fixed_cost,
string* error);
+
+ static bool IsOrderingValid(const Solver::Options& options,
+ const ProblemImpl* problem_impl,
+ string* error);
+
+ static bool IsParameterBlockSetIndependent(
+ const set<double*>& parameter_block_ptrs,
+ const vector<ResidualBlock*>& residual_blocks);
+
+ static CoordinateDescentMinimizer* CreateInnerIterationMinimizer(
+ const Solver::Options& options,
+ const Program& program,
+ const ProblemImpl::ParameterMap& parameter_map,
+ Solver::Summary* summary);
};
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc
index 9e00b4402dc..195cacb984c 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc
@@ -28,6 +28,8 @@
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
+#if !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARSE)
+
#include "ceres/sparse_normal_cholesky_solver.h"
#include <algorithm>
@@ -39,12 +41,13 @@
#endif
#include "ceres/compressed_row_sparse_matrix.h"
+#include "ceres/internal/eigen.h"
+#include "ceres/internal/scoped_ptr.h"
#include "ceres/linear_solver.h"
#include "ceres/suitesparse.h"
#include "ceres/triplet_sparse_matrix.h"
-#include "ceres/internal/eigen.h"
-#include "ceres/internal/scoped_ptr.h"
#include "ceres/types.h"
+#include "ceres/wall_time.h"
namespace ceres {
namespace internal {
@@ -103,6 +106,8 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingCXSparse(
const double* b,
const LinearSolver::PerSolveOptions& per_solve_options,
double * x) {
+ EventLogger event_logger("SparseNormalCholeskySolver::CXSparse::Solve");
+
LinearSolver::Summary summary;
summary.num_iterations = 1;
const int num_cols = A->num_cols();
@@ -129,25 +134,34 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingCXSparse(
// off of Jt to compute the Cholesky factorization of the normal
// equations.
cs_di* A2 = cs_transpose(&At, 1);
- cs_di* AtA = cs_multiply(&At,A2);
+ cs_di* AtA = cs_multiply(&At, A2);
cxsparse_.Free(A2);
if (per_solve_options.D != NULL) {
A->DeleteRows(num_cols);
}
+ event_logger.AddEvent("Setup");
+
// Compute symbolic factorization if not available.
if (cxsparse_factor_ == NULL) {
cxsparse_factor_ = CHECK_NOTNULL(cxsparse_.AnalyzeCholesky(AtA));
}
+ event_logger.AddEvent("Analysis");
+
+
// Solve the linear system.
if (cxsparse_.SolveCholesky(AtA, cxsparse_factor_, Atb.data())) {
VectorRef(x, Atb.rows()) = Atb;
summary.termination_type = TOLERANCE;
}
+ event_logger.AddEvent("Solve");
+
cxsparse_.Free(AtA);
+
+ event_logger.AddEvent("Teardown");
return summary;
}
#else
@@ -169,9 +183,9 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse(
const double* b,
const LinearSolver::PerSolveOptions& per_solve_options,
double * x) {
- const time_t start_time = time(NULL);
- const int num_cols = A->num_cols();
+ EventLogger event_logger("SparseNormalCholeskySolver::SuiteSparse::Solve");
+ const int num_cols = A->num_cols();
LinearSolver::Summary summary;
Vector Atb = Vector::Zero(num_cols);
A->LeftMultiply(b, Atb.data());
@@ -189,7 +203,7 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse(
CHECK_NOTNULL(lhs.get());
cholmod_dense* rhs = ss_.CreateDenseVector(Atb.data(), num_cols, num_cols);
- const time_t init_time = time(NULL);
+ event_logger.AddEvent("Setup");
if (factor_ == NULL) {
if (options_.use_block_amd) {
@@ -201,16 +215,15 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse(
}
if (VLOG_IS_ON(2)) {
- cholmod_print_common("Symbolic Analysis", ss_.mutable_cc());
+ cholmod_print_common(const_cast<char*>("Symbolic Analysis"), ss_.mutable_cc());
}
}
CHECK_NOTNULL(factor_);
-
- const time_t symbolic_time = time(NULL);
+ event_logger.AddEvent("Analysis");
cholmod_dense* sol = ss_.SolveCholesky(lhs.get(), factor_, rhs);
- const time_t solve_time = time(NULL);
+ event_logger.AddEvent("Solve");
ss_.Free(rhs);
rhs = NULL;
@@ -228,12 +241,7 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse(
summary.termination_type = TOLERANCE;
}
- const time_t cleanup_time = time(NULL);
- VLOG(2) << "time (sec) total: " << (cleanup_time - start_time)
- << " init: " << (init_time - start_time)
- << " symbolic: " << (symbolic_time - init_time)
- << " solve: " << (solve_time - symbolic_time)
- << " cleanup: " << (cleanup_time - solve_time);
+ event_logger.AddEvent("Teardown");
return summary;
}
#else
@@ -251,3 +259,5 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse(
} // namespace internal
} // namespace ceres
+
+#endif // !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARSE)
diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h
index 40d9e0a0327..ebb32e61939 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h
@@ -34,9 +34,11 @@
#ifndef CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_
#define CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_
+#if !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARSE)
+
#include "ceres/cxsparse.h"
-#include "ceres/linear_solver.h"
#include "ceres/internal/macros.h"
+#include "ceres/linear_solver.h"
#include "ceres/suitesparse.h"
namespace ceres {
@@ -90,4 +92,5 @@ class SparseNormalCholeskySolver : public CompressedRowSparseMatrixSolver {
} // namespace internal
} // namespace ceres
+#endif // !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARSE)
#endif // CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/split.cc b/extern/libmv/third_party/ceres/internal/ceres/split.cc
index c65c8a5bb5d..3edbc281340 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/split.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/split.cc
@@ -28,10 +28,11 @@
//
// Author: keir@google.com (Keir Mierle)
+#include "ceres/split.h"
+
#include <string>
#include <vector>
#include <iterator>
-#include "ceres/split.h"
#include "ceres/internal/port.h"
namespace ceres {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/split.h b/extern/libmv/third_party/ceres/internal/ceres/split.h
index ec579e974da..4df48c3a7cd 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/split.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/split.h
@@ -2,7 +2,7 @@
// Author: keir@google.com (Keir Mierle)
#ifndef CERES_INTERNAL_SPLIT_H_
-#define VISION_OPTIMIZATION_LEAST_SQUARES_INTERNAL_SPLIT_H_
+#define CERES_INTERNAL_SPLIT_H_
#include <string>
#include <vector>
diff --git a/extern/libmv/third_party/ceres/internal/ceres/stl_util.h b/extern/libmv/third_party/ceres/internal/ceres/stl_util.h
index a1a19e8b3ce..08f15ec8398 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/stl_util.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/stl_util.h
@@ -31,6 +31,8 @@
#ifndef CERES_INTERNAL_STL_UTIL_H_
#define CERES_INTERNAL_STL_UTIL_H_
+#include <algorithm>
+
namespace ceres {
// STLDeleteContainerPointers()
@@ -53,6 +55,20 @@ void STLDeleteContainerPointers(ForwardIterator begin,
}
}
+// Variant of STLDeleteContainerPointers which allows the container to
+// contain duplicates.
+template <class ForwardIterator>
+void STLDeleteUniqueContainerPointers(ForwardIterator begin,
+ ForwardIterator end) {
+ sort(begin, end);
+ ForwardIterator new_end = unique(begin, end);
+ while (begin != new_end) {
+ ForwardIterator temp = begin;
+ ++begin;
+ delete *temp;
+ }
+}
+
// STLDeleteElements() deletes all the elements in an STL container and clears
// the container. This function is suitable for use with a vector, set,
// hash_set, or any other STL container which defines sensible begin(), end(),
diff --git a/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc
index 396a48b7d97..ce204674dce 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc
@@ -28,13 +28,14 @@
//
// Author: Sanjay Ghemawat
+#include "ceres/stringprintf.h"
+
#include <cerrno>
#include <cstdarg> // For va_list and related operations
#include <cstdio> // MSVC requires this for _vsnprintf
#include <string>
#include <vector>
-#include "ceres/stringprintf.h"
#include "ceres/internal/port.h"
namespace ceres {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/stringprintf.h b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.h
index f2f907ab32d..cd1be142aed 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/stringprintf.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.h
@@ -65,17 +65,17 @@ namespace internal {
// Return a C++ string.
extern string StringPrintf(const char* format, ...)
// Tell the compiler to do printf format string checking.
- CERES_PRINTF_ATTRIBUTE(1,2);
+ CERES_PRINTF_ATTRIBUTE(1, 2);
// Store result into a supplied string and return it.
extern const string& SStringPrintf(string* dst, const char* format, ...)
// Tell the compiler to do printf format string checking.
- CERES_PRINTF_ATTRIBUTE(2,3);
+ CERES_PRINTF_ATTRIBUTE(2, 3);
// Append result to a supplied string.
extern void StringAppendF(string* dst, const char* format, ...)
// Tell the compiler to do printf format string checking.
- CERES_PRINTF_ATTRIBUTE(2,3);
+ CERES_PRINTF_ATTRIBUTE(2, 3);
// Lower-level routine that takes a va_list and appends to a specified string.
// All other routines are just convenience wrappers around it.
diff --git a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc
index cf3c48f84e6..d200aeb82f3 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc
@@ -135,10 +135,11 @@ cholmod_factor* SuiteSparse::BlockAnalyzeCholesky(
return AnalyzeCholeskyWithUserOrdering(A, ordering);
}
-cholmod_factor* SuiteSparse::AnalyzeCholeskyWithUserOrdering(cholmod_sparse* A,
- const vector<int>& ordering) {
+cholmod_factor* SuiteSparse::AnalyzeCholeskyWithUserOrdering(
+ cholmod_sparse* A,
+ const vector<int>& ordering) {
CHECK_EQ(ordering.size(), A->nrow);
- cc_.nmethods = 1 ;
+ cc_.nmethods = 1;
cc_.method[0].ordering = CHOLMOD_GIVEN;
cholmod_factor* factor =
cholmod_analyze_p(A, const_cast<int*>(&ordering[0]), NULL, 0, &cc_);
diff --git a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h
index eb691c0c0ed..3fe79080d5d 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h
@@ -39,9 +39,9 @@
#include <string>
#include <vector>
-#include <glog/logging.h>
-#include "cholmod.h"
#include "ceres/internal/port.h"
+#include "cholmod.h"
+#include "glog/logging.h"
namespace ceres {
namespace internal {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc
index ed8677ea18a..a09f38ee24e 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc
@@ -71,7 +71,8 @@ TripletSparseMatrix::TripletSparseMatrix(int num_rows,
}
TripletSparseMatrix::TripletSparseMatrix(const TripletSparseMatrix& orig)
- : num_rows_(orig.num_rows_),
+ : SparseMatrix(),
+ num_rows_(orig.num_rows_),
num_cols_(orig.num_cols_),
max_num_nonzeros_(orig.max_num_nonzeros_),
num_nonzeros_(orig.num_nonzeros_),
diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc b/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc
index 76c4f8a7580..981c60a12e7 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc
@@ -45,8 +45,10 @@
#include "ceres/internal/scoped_ptr.h"
#include "ceres/linear_least_squares_problems.h"
#include "ceres/sparse_matrix.h"
+#include "ceres/stringprintf.h"
#include "ceres/trust_region_strategy.h"
#include "ceres/types.h"
+#include "ceres/wall_time.h"
#include "glog/logging.h"
namespace ceres {
@@ -56,28 +58,13 @@ namespace {
const double kEpsilon = 1e-12;
} // namespace
-// Execute the list of IterationCallbacks sequentially. If any one of
-// the callbacks does not return SOLVER_CONTINUE, then stop and return
-// its status.
-CallbackReturnType TrustRegionMinimizer::RunCallbacks(
- const IterationSummary& iteration_summary) {
- for (int i = 0; i < options_.callbacks.size(); ++i) {
- const CallbackReturnType status =
- (*options_.callbacks[i])(iteration_summary);
- if (status != SOLVER_CONTINUE) {
- return status;
- }
- }
- return SOLVER_CONTINUE;
-}
-
// Compute a scaling vector that is used to improve the conditioning
// of the Jacobian.
void TrustRegionMinimizer::EstimateScale(const SparseMatrix& jacobian,
double* scale) const {
jacobian.SquaredColumnNorm(scale);
for (int i = 0; i < jacobian.num_cols(); ++i) {
- scale[i] = 1.0 / (kEpsilon + sqrt(scale[i]));
+ scale[i] = 1.0 / (1.0 + sqrt(scale[i]));
}
}
@@ -96,29 +83,19 @@ bool TrustRegionMinimizer::MaybeDumpLinearLeastSquaresProblem(
// moved inside TrustRegionStrategy, its not clear how we dump the
// regularization vector/matrix anymore.
//
- // Doing this right requires either an API change to the
- // TrustRegionStrategy and/or how LinearLeastSquares problems are
- // stored on disk.
+ // Also num_eliminate_blocks is not visible to the trust region
+ // minimizer either.
//
- // For now, we will just not dump the regularizer.
- return (!binary_search(options_.lsqp_iterations_to_dump.begin(),
- options_.lsqp_iterations_to_dump.end(),
- iteration) ||
- DumpLinearLeastSquaresProblem(options_.lsqp_dump_directory,
- iteration,
- options_.lsqp_dump_format_type,
- jacobian,
- NULL,
- residuals,
- step,
- options_.num_eliminate_blocks));
+ // Both of these indicate that this is the wrong place for this
+ // code, and going forward this should needs fixing/refactoring.
+ return true;
}
void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
double* parameters,
Solver::Summary* summary) {
- time_t start_time = time(NULL);
- time_t iteration_start_time = start_time;
+ double start_time = WallTimeInSeconds();
+ double iteration_start_time = start_time;
Init(options);
summary->termination_type = NO_CONVERGENCE;
@@ -149,7 +126,6 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
iteration_summary.iteration = 0;
iteration_summary.step_is_valid = false;
iteration_summary.step_is_successful = false;
- iteration_summary.cost = summary->initial_cost;
iteration_summary.cost_change = 0.0;
iteration_summary.gradient_max_norm = 0.0;
iteration_summary.step_norm = 0.0;
@@ -169,6 +145,9 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
return;
}
+ summary->initial_cost = cost + summary->fixed_cost;
+ iteration_summary.cost = cost + summary->fixed_cost;
+
int num_consecutive_nonmonotonic_steps = 0;
double minimum_cost = cost;
double reference_cost = cost;
@@ -189,45 +168,34 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
// The initial gradient max_norm is bounded from below so that we do
// not divide by zero.
- const double gradient_max_norm_0 =
+ const double initial_gradient_max_norm =
max(iteration_summary.gradient_max_norm, kEpsilon);
const double absolute_gradient_tolerance =
- options_.gradient_tolerance * gradient_max_norm_0;
+ options_.gradient_tolerance * initial_gradient_max_norm;
if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) {
summary->termination_type = GRADIENT_TOLERANCE;
VLOG(1) << "Terminating: Gradient tolerance reached."
<< "Relative gradient max norm: "
- << iteration_summary.gradient_max_norm / gradient_max_norm_0
+ << iteration_summary.gradient_max_norm / initial_gradient_max_norm
<< " <= " << options_.gradient_tolerance;
return;
}
iteration_summary.iteration_time_in_seconds =
- time(NULL) - iteration_start_time;
- iteration_summary.cumulative_time_in_seconds = time(NULL) - start_time +
- summary->preprocessor_time_in_seconds;
+ WallTimeInSeconds() - iteration_start_time;
+ iteration_summary.cumulative_time_in_seconds =
+ WallTimeInSeconds() - start_time
+ + summary->preprocessor_time_in_seconds;
summary->iterations.push_back(iteration_summary);
- // Call the various callbacks.
- switch (RunCallbacks(iteration_summary)) {
- case SOLVER_TERMINATE_SUCCESSFULLY:
- summary->termination_type = USER_SUCCESS;
- VLOG(1) << "Terminating: User callback returned USER_SUCCESS.";
- return;
- case SOLVER_ABORT:
- summary->termination_type = USER_ABORT;
- VLOG(1) << "Terminating: User callback returned USER_ABORT.";
- return;
- case SOLVER_CONTINUE:
- break;
- default:
- LOG(FATAL) << "Unknown type of user callback status";
- }
-
int num_consecutive_invalid_steps = 0;
while (true) {
- iteration_start_time = time(NULL);
+ if (!RunCallbacks(options.callbacks, iteration_summary, summary)) {
+ return;
+ }
+
+ iteration_start_time = WallTimeInSeconds();
if (iteration_summary.iteration >= options_.max_num_iterations) {
summary->termination_type = NO_CONVERGENCE;
VLOG(1) << "Terminating: Maximum number of iterations reached.";
@@ -248,7 +216,7 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
iteration_summary.step_is_valid = false;
iteration_summary.step_is_successful = false;
- const time_t strategy_start_time = time(NULL);
+ const double strategy_start_time = WallTimeInSeconds();
TrustRegionStrategy::PerSolveOptions per_solve_options;
per_solve_options.eta = options_.eta;
TrustRegionStrategy::Summary strategy_summary =
@@ -258,7 +226,7 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
trust_region_step.data());
iteration_summary.step_solver_time_in_seconds =
- time(NULL) - strategy_start_time;
+ WallTimeInSeconds() - strategy_start_time;
iteration_summary.linear_solver_iterations =
strategy_summary.num_iterations;
@@ -270,23 +238,24 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
<< options.lsqp_dump_directory << "but failed.";
}
- double new_model_cost = 0.0;
+ double model_cost_change = 0.0;
if (strategy_summary.termination_type != FAILURE) {
- // new_model_cost = 1/2 |f + J * step|^2
- model_residuals = residuals;
+ // new_model_cost
+ // = 1/2 [f + J * step]^2
+ // = 1/2 [ f'f + 2f'J * step + step' * J' * J * step ]
+ // model_cost_change
+ // = cost - new_model_cost
+ // = f'f/2 - 1/2 [ f'f + 2f'J * step + step' * J' * J * step]
+ // = -f'J * step - step' * J' * J * step / 2
+ model_residuals.setZero();
jacobian->RightMultiply(trust_region_step.data(), model_residuals.data());
- new_model_cost = model_residuals.squaredNorm() / 2.0;
-
- // In exact arithmetic, this would never be the case. But poorly
- // conditioned matrices can give rise to situations where the
- // new_model_cost can actually be larger than half the squared
- // norm of the residual vector. We allow for small tolerance
- // around cost and beyond that declare the step to be invalid.
- if ((1.0 - new_model_cost / cost) < -kEpsilon) {
+ model_cost_change = -(residuals.dot(model_residuals) +
+ model_residuals.squaredNorm() / 2.0);
+
+ if (model_cost_change < 0.0) {
VLOG(1) << "Invalid step: current_cost: " << cost
- << " new_model_cost " << new_model_cost
- << " absolute difference " << (cost - new_model_cost)
- << " relative difference " << (1.0 - new_model_cost/cost);
+ << " absolute difference " << model_cost_change
+ << " relative difference " << (model_cost_change / cost);
} else {
iteration_summary.step_is_valid = true;
}
@@ -299,10 +268,12 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
if (++num_consecutive_invalid_steps >=
options_.max_num_consecutive_invalid_steps) {
summary->termination_type = NUMERICAL_FAILURE;
- LOG(WARNING) << "Terminating. Number of successive invalid steps more "
- << "than "
- << "Solver::Options::max_num_consecutive_invalid_steps: "
- << options_.max_num_consecutive_invalid_steps;
+ summary->error = StringPrintf(
+ "Terminating. Number of successive invalid steps more "
+ "than Solver::Options::max_num_consecutive_invalid_steps: %d",
+ options_.max_num_consecutive_invalid_steps);
+
+ LOG(WARNING) << summary->error;
return;
}
@@ -311,7 +282,7 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
// as an unsuccessful iteration. Since the various callbacks are
// still executed, we are going to fill the iteration summary
// with data that assumes a step of length zero and no progress.
- iteration_summary.cost = cost;
+ iteration_summary.cost = cost + summary->fixed_cost;
iteration_summary.cost_change = 0.0;
iteration_summary.gradient_max_norm =
summary->iterations.back().gradient_max_norm;
@@ -322,51 +293,19 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
// The step is numerically valid, so now we can judge its quality.
num_consecutive_invalid_steps = 0;
- // We allow some slop around 0, and clamp the model_cost_change
- // at kEpsilon * min(1.0, cost) from below.
- //
- // In exact arithmetic this should never be needed, as we are
- // guaranteed to new_model_cost <= cost. However, due to various
- // numerical issues, it is possible that new_model_cost is
- // nearly equal to cost, and the difference is a small negative
- // number. To make sure that the relative_decrease computation
- // remains sane, as clamp the difference (cost - new_model_cost)
- // from below at a small positive number.
- //
- // This number is the minimum of kEpsilon * (cost, 1.0), which
- // ensures that it will never get too large in absolute value,
- // while scaling down proportionally with the magnitude of the
- // cost. This is important for problems where the minimum of the
- // objective function is near zero.
- const double model_cost_change =
- max(kEpsilon * min(1.0, cost), cost - new_model_cost);
-
// Undo the Jacobian column scaling.
delta = (trust_region_step.array() * scale.array()).matrix();
- iteration_summary.step_norm = delta.norm();
-
- // Convergence based on parameter_tolerance.
- const double step_size_tolerance = options_.parameter_tolerance *
- (x_norm + options_.parameter_tolerance);
- if (iteration_summary.step_norm <= step_size_tolerance) {
- VLOG(1) << "Terminating. Parameter tolerance reached. "
- << "relative step_norm: "
- << iteration_summary.step_norm /
- (x_norm + options_.parameter_tolerance)
- << " <= " << options_.parameter_tolerance;
- summary->termination_type = PARAMETER_TOLERANCE;
- return;
- }
-
if (!evaluator->Plus(x.data(), delta.data(), x_plus_delta.data())) {
summary->termination_type = NUMERICAL_FAILURE;
- LOG(WARNING) << "Terminating. Failed to compute "
- << "Plus(x, delta, x_plus_delta).";
+ summary->error =
+ "Terminating. Failed to compute Plus(x, delta, x_plus_delta).";
+
+ LOG(WARNING) << summary->error;
return;
}
// Try this step.
- double new_cost;
+ double new_cost = numeric_limits<double>::max();
if (!evaluator->Evaluate(x_plus_delta.data(),
&new_cost,
NULL, NULL, NULL)) {
@@ -375,6 +314,45 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
LOG(WARNING) << "Step failed to evaluate. "
<< "Treating it as step with infinite cost";
new_cost = numeric_limits<double>::max();
+ } else {
+ // Check if performing an inner iteration will make it better.
+ if (options.inner_iteration_minimizer != NULL) {
+ const double x_plus_delta_cost = new_cost;
+ Vector inner_iteration_x = x_plus_delta;
+ Solver::Summary inner_iteration_summary;
+ options.inner_iteration_minimizer->Minimize(options,
+ inner_iteration_x.data(),
+ &inner_iteration_summary);
+ if (!evaluator->Evaluate(inner_iteration_x.data(),
+ &new_cost,
+ NULL, NULL, NULL)) {
+ VLOG(2) << "Inner iteration failed.";
+ new_cost = x_plus_delta_cost;
+ } else {
+ x_plus_delta = inner_iteration_x;
+ // Boost the model_cost_change, since the inner iteration
+ // improvements are not accounted for by the trust region.
+ model_cost_change += x_plus_delta_cost - new_cost;
+ VLOG(2) << "Inner iteration succeeded; current cost: " << cost
+ << " x_plus_delta_cost: " << x_plus_delta_cost
+ << " new_cost: " << new_cost;
+ }
+ }
+ }
+
+ iteration_summary.step_norm = (x - x_plus_delta).norm();
+
+ // Convergence based on parameter_tolerance.
+ const double step_size_tolerance = options_.parameter_tolerance *
+ (x_norm + options_.parameter_tolerance);
+ if (iteration_summary.step_norm <= step_size_tolerance) {
+ VLOG(1) << "Terminating. Parameter tolerance reached. "
+ << "relative step_norm: "
+ << iteration_summary.step_norm /
+ (x_norm + options_.parameter_tolerance)
+ << " <= " << options_.parameter_tolerance;
+ summary->termination_type = PARAMETER_TOLERANCE;
+ return;
}
VLOG(2) << "old cost: " << cost << " new cost: " << new_cost;
@@ -421,6 +399,7 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
accumulated_candidate_model_cost_change += model_cost_change;
accumulated_reference_model_cost_change += model_cost_change;
if (relative_decrease <= options_.min_relative_decrease) {
+ iteration_summary.step_is_nonmonotonic = true;
VLOG(2) << "Non-monotonic step! "
<< " relative_decrease: " << relative_decrease
<< " historical_relative_decrease: "
@@ -443,7 +422,9 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
NULL,
jacobian)) {
summary->termination_type = NUMERICAL_FAILURE;
- LOG(WARNING) << "Terminating: Residual and Jacobian evaluation failed.";
+ summary->error =
+ "Terminating: Residual and Jacobian evaluation failed.";
+ LOG(WARNING) << summary->error;
return;
}
@@ -455,7 +436,8 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
summary->termination_type = GRADIENT_TOLERANCE;
VLOG(1) << "Terminating: Gradient tolerance reached."
<< "Relative gradient max norm: "
- << iteration_summary.gradient_max_norm / gradient_max_norm_0
+ << (iteration_summary.gradient_max_norm /
+ initial_gradient_max_norm)
<< " <= " << options_.gradient_tolerance;
return;
}
@@ -523,25 +505,11 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
}
iteration_summary.iteration_time_in_seconds =
- time(NULL) - iteration_start_time;
- iteration_summary.cumulative_time_in_seconds = time(NULL) - start_time +
- summary->preprocessor_time_in_seconds;
+ WallTimeInSeconds() - iteration_start_time;
+ iteration_summary.cumulative_time_in_seconds =
+ WallTimeInSeconds() - start_time
+ + summary->preprocessor_time_in_seconds;
summary->iterations.push_back(iteration_summary);
-
- switch (RunCallbacks(iteration_summary)) {
- case SOLVER_TERMINATE_SUCCESSFULLY:
- summary->termination_type = USER_SUCCESS;
- VLOG(1) << "Terminating: User callback returned USER_SUCCESS.";
- return;
- case SOLVER_ABORT:
- summary->termination_type = USER_ABORT;
- VLOG(1) << "Terminating: User callback returned USER_ABORT.";
- return;
- case SOLVER_CONTINUE:
- break;
- default:
- LOG(FATAL) << "Unknown type of user callback status";
- }
}
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.h b/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.h
index a4f5ba3674d..9a022843233 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.h
@@ -39,8 +39,7 @@ namespace ceres {
namespace internal {
// Generic trust region minimization algorithm. The heavy lifting is
-// done by a TrustRegionStrategy object passed in as one of the
-// arguments to the Minimize method.
+// done by a TrustRegionStrategy object passed in as part of options.
//
// For example usage, see SolverImpl::Minimize.
class TrustRegionMinimizer : public Minimizer {
@@ -53,11 +52,10 @@ class TrustRegionMinimizer : public Minimizer {
private:
void Init(const Minimizer::Options& options);
void EstimateScale(const SparseMatrix& jacobian, double* scale) const;
- CallbackReturnType RunCallbacks(const IterationSummary& iteration_summary);
- bool MaybeDumpLinearLeastSquaresProblem( const int iteration,
- const SparseMatrix* jacobian,
- const double* residuals,
- const double* step) const;
+ bool MaybeDumpLinearLeastSquaresProblem(const int iteration,
+ const SparseMatrix* jacobian,
+ const double* residuals,
+ const double* step) const;
Minimizer::Options options_;
};
diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.cc b/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.cc
index 89bc19d084b..c68269d0449 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.cc
@@ -1,3 +1,35 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012, 2013 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//
+// Author: sameeragarwal@google.com (Sameer Agarwal)
+// keir@google.com (Keir Mierle)
+
#include "ceres/trust_region_strategy.h"
#include "ceres/dogleg_strategy.h"
#include "ceres/levenberg_marquardt_strategy.h"
diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.h b/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.h
index 391da97d5eb..f150594bbd2 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.h
@@ -52,7 +52,7 @@ class SparseMatrix;
// radius to scale the damping term, which controls the step size, but
// does not set a hard limit on its size.
class TrustRegionStrategy {
-public:
+ public:
struct Options {
Options()
: trust_region_strategy_type(LEVENBERG_MARQUARDT),
diff --git a/extern/libmv/third_party/ceres/internal/ceres/types.cc b/extern/libmv/third_party/ceres/internal/ceres/types.cc
index 05e573ff6d5..2e19322cc76 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/types.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/types.cc
@@ -28,15 +28,23 @@
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
+#include <algorithm>
+#include <cctype>
#include <string>
#include "ceres/types.h"
+#include "glog/logging.h"
namespace ceres {
#define CASESTR(x) case x: return #x
+#define STRENUM(x) if (value == #x) { *type = x; return true;}
-const char* LinearSolverTypeToString(LinearSolverType solver_type) {
- switch (solver_type) {
+static void UpperCase(string* input) {
+ std::transform(input->begin(), input->end(), input->begin(), ::toupper);
+}
+
+const char* LinearSolverTypeToString(LinearSolverType type) {
+ switch (type) {
CASESTR(DENSE_NORMAL_CHOLESKY);
CASESTR(DENSE_QR);
CASESTR(SPARSE_NORMAL_CHOLESKY);
@@ -49,9 +57,20 @@ const char* LinearSolverTypeToString(LinearSolverType solver_type) {
}
}
-const char* PreconditionerTypeToString(
- PreconditionerType preconditioner_type) {
- switch (preconditioner_type) {
+bool StringToLinearSolverType(string value, LinearSolverType* type) {
+ UpperCase(&value);
+ STRENUM(DENSE_NORMAL_CHOLESKY);
+ STRENUM(DENSE_QR);
+ STRENUM(SPARSE_NORMAL_CHOLESKY);
+ STRENUM(DENSE_SCHUR);
+ STRENUM(SPARSE_SCHUR);
+ STRENUM(ITERATIVE_SCHUR);
+ STRENUM(CGNR);
+ return false;
+}
+
+const char* PreconditionerTypeToString(PreconditionerType type) {
+ switch (type) {
CASESTR(IDENTITY);
CASESTR(JACOBI);
CASESTR(SCHUR_JACOBI);
@@ -62,9 +81,19 @@ const char* PreconditionerTypeToString(
}
}
+bool StringToPreconditionerType(string value, PreconditionerType* type) {
+ UpperCase(&value);
+ STRENUM(IDENTITY);
+ STRENUM(JACOBI);
+ STRENUM(SCHUR_JACOBI);
+ STRENUM(CLUSTER_JACOBI);
+ STRENUM(CLUSTER_TRIDIAGONAL);
+ return false;
+}
+
const char* SparseLinearAlgebraLibraryTypeToString(
- SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type) {
- switch (sparse_linear_algebra_library_type) {
+ SparseLinearAlgebraLibraryType type) {
+ switch (type) {
CASESTR(SUITE_SPARSE);
CASESTR(CX_SPARSE);
default:
@@ -72,19 +101,121 @@ const char* SparseLinearAlgebraLibraryTypeToString(
}
}
-const char* OrderingTypeToString(OrderingType ordering_type) {
- switch (ordering_type) {
- CASESTR(NATURAL);
- CASESTR(USER);
- CASESTR(SCHUR);
+
+bool StringToSparseLinearAlgebraLibraryType(
+ string value,
+ SparseLinearAlgebraLibraryType* type) {
+ UpperCase(&value);
+ STRENUM(SUITE_SPARSE);
+ STRENUM(CX_SPARSE);
+ return false;
+}
+
+const char* TrustRegionStrategyTypeToString(TrustRegionStrategyType type) {
+ switch (type) {
+ CASESTR(LEVENBERG_MARQUARDT);
+ CASESTR(DOGLEG);
+ default:
+ return "UNKNOWN";
+ }
+}
+
+bool StringToTrustRegionStrategyType(string value,
+ TrustRegionStrategyType* type) {
+ UpperCase(&value);
+ STRENUM(LEVENBERG_MARQUARDT);
+ STRENUM(DOGLEG);
+ return false;
+}
+
+const char* DoglegTypeToString(DoglegType type) {
+ switch (type) {
+ CASESTR(TRADITIONAL_DOGLEG);
+ CASESTR(SUBSPACE_DOGLEG);
+ default:
+ return "UNKNOWN";
+ }
+}
+
+bool StringToDoglegType(string value, DoglegType* type) {
+ UpperCase(&value);
+ STRENUM(TRADITIONAL_DOGLEG);
+ STRENUM(SUBSPACE_DOGLEG);
+ return false;
+}
+
+const char* MinimizerTypeToString(MinimizerType type) {
+ switch (type) {
+ CASESTR(TRUST_REGION);
+ CASESTR(LINE_SEARCH);
+ default:
+ return "UNKNOWN";
+ }
+}
+
+bool StringToMinimizerType(string value, MinimizerType* type) {
+ UpperCase(&value);
+ STRENUM(TRUST_REGION);
+ STRENUM(LINE_SEARCH);
+ return false;
+}
+
+const char* LineSearchDirectionTypeToString(LineSearchDirectionType type) {
+ switch (type) {
+ CASESTR(STEEPEST_DESCENT);
+ CASESTR(NONLINEAR_CONJUGATE_GRADIENT);
+ CASESTR(LBFGS);
+ default:
+ return "UNKNOWN";
+ }
+}
+
+bool StringToLineSearchDirectionType(string value,
+ LineSearchDirectionType* type) {
+ UpperCase(&value);
+ STRENUM(STEEPEST_DESCENT);
+ STRENUM(NONLINEAR_CONJUGATE_GRADIENT);
+ STRENUM(LBFGS);
+ return false;
+}
+
+const char* LineSearchTypeToString(LineSearchType type) {
+ switch (type) {
+ CASESTR(ARMIJO);
default:
return "UNKNOWN";
}
}
-const char* SolverTerminationTypeToString(
- SolverTerminationType termination_type) {
- switch (termination_type) {
+bool StringToLineSearchType(string value, LineSearchType* type) {
+ UpperCase(&value);
+ STRENUM(ARMIJO);
+ return false;
+}
+
+const char* NonlinearConjugateGradientTypeToString(
+ NonlinearConjugateGradientType type) {
+ switch (type) {
+ CASESTR(FLETCHER_REEVES);
+ CASESTR(POLAK_RIBIRERE);
+ CASESTR(HESTENES_STIEFEL);
+ default:
+ return "UNKNOWN";
+ }
+}
+
+bool StringToNonlinearConjugateGradientType(
+ string value,
+ NonlinearConjugateGradientType* type) {
+ UpperCase(&value);
+ STRENUM(FLETCHER_REEVES);
+ STRENUM(POLAK_RIBIRERE);
+ STRENUM(HESTENES_STIEFEL);
+ return false;
+}
+
+const char* SolverTerminationTypeToString(SolverTerminationType type) {
+ switch (type) {
CASESTR(NO_CONVERGENCE);
CASESTR(FUNCTION_TOLERANCE);
CASESTR(GRADIENT_TOLERANCE);
@@ -98,29 +229,20 @@ const char* SolverTerminationTypeToString(
}
}
-#if 0 /* UNUSED */
-static const char* SparseLinearAlgebraTypeToString(
- SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type) {
- switch (sparse_linear_algebra_library_type) {
- CASESTR(CX_SPARSE);
- CASESTR(SUITE_SPARSE);
- default:
- return "UNKNOWN";
- }
-}
-#endif
-
-const char* TrustRegionStrategyTypeToString(
- TrustRegionStrategyType trust_region_strategy_type) {
- switch (trust_region_strategy_type) {
- CASESTR(LEVENBERG_MARQUARDT);
- CASESTR(DOGLEG);
+const char* LinearSolverTerminationTypeToString(
+ LinearSolverTerminationType type) {
+ switch (type) {
+ CASESTR(TOLERANCE);
+ CASESTR(MAX_ITERATIONS);
+ CASESTR(STAGNATION);
+ CASESTR(FAILURE);
default:
return "UNKNOWN";
}
}
#undef CASESTR
+#undef STRENUM
bool IsSchurType(LinearSolverType type) {
return ((type == SPARSE_SCHUR) ||
@@ -128,4 +250,26 @@ bool IsSchurType(LinearSolverType type) {
(type == ITERATIVE_SCHUR));
}
+bool IsSparseLinearAlgebraLibraryTypeAvailable(
+ SparseLinearAlgebraLibraryType type) {
+ if (type == SUITE_SPARSE) {
+#ifdef CERES_NO_SUITESPARSE
+ return false;
+#else
+ return true;
+#endif
+ }
+
+ if (type == CX_SPARSE) {
+#ifdef CERES_NO_CXSPARSE
+ return false;
+#else
+ return true;
+#endif
+ }
+
+ LOG(WARNING) << "Unknown sparse linear algebra library " << type;
+ return false;
+}
+
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility.cc b/extern/libmv/third_party/ceres/internal/ceres/visibility.cc
index 564cc54493e..fcd793c00a8 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/visibility.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/visibility.cc
@@ -28,6 +28,10 @@
//
// Author: kushalav@google.com (Avanish Kushal)
+#ifndef CERES_NO_SUITESPARSE
+
+#include "ceres/visibility.h"
+
#include <cmath>
#include <ctime>
#include <algorithm>
@@ -36,7 +40,6 @@
#include <utility>
#include "ceres/block_structure.h"
#include "ceres/collections_port.h"
-#include "ceres/visibility.h"
#include "ceres/graph.h"
#include "glog/logging.h"
@@ -138,7 +141,8 @@ Graph<int>* CreateSchurComplementGraph(const vector<set<int> >& visibility) {
const int count = it->second;
// Static cast necessary for Windows.
const double weight = static_cast<double>(count) /
- (sqrt(static_cast<double>(visibility[camera1].size() * visibility[camera2].size())));
+ (sqrt(static_cast<double>(
+ visibility[camera1].size() * visibility[camera2].size())));
graph->AddEdge(camera1, camera2, weight);
}
@@ -148,3 +152,5 @@ Graph<int>* CreateSchurComplementGraph(const vector<set<int> >& visibility) {
} // namespace internal
} // namespace ceres
+
+#endif
diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility.h b/extern/libmv/third_party/ceres/internal/ceres/visibility.h
index 692dd87201e..2d1e6f85ddf 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/visibility.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/visibility.h
@@ -35,6 +35,8 @@
#ifndef CERES_INTERNAL_VISIBILITY_H_
#define CERES_INTERNAL_VISIBILITY_H_
+#ifndef CERES_NO_SUITESPARSE
+
#include <set>
#include <vector>
#include "ceres/graph.h"
@@ -42,7 +44,7 @@
namespace ceres {
namespace internal {
-class CompressedRowBlockStructure;
+struct CompressedRowBlockStructure;
// Given a compressed row block structure, computes the set of
// e_blocks "visible" to each f_block. If an e_block co-occurs with an
@@ -74,4 +76,5 @@ Graph<int>* CreateSchurComplementGraph(const vector<set<int> >& visibility);
} // namespace internal
} // namespace ceres
+#endif // CERES_NO_SUITESPARSE
#endif // CERES_INTERNAL_VISIBILITY_H_
diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc
index 4caad03d7a1..1678d0072e5 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc
@@ -28,6 +28,8 @@
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
+#ifndef CERES_NO_SUITESPARSE
+
#include "ceres/visibility_based_preconditioner.h"
#include <algorithm>
@@ -62,20 +64,19 @@ namespace internal {
static const double kSizePenaltyWeight = 3.0;
static const double kSimilarityPenaltyWeight = 0.0;
-#ifndef CERES_NO_SUITESPARSE
VisibilityBasedPreconditioner::VisibilityBasedPreconditioner(
const CompressedRowBlockStructure& bs,
- const LinearSolver::Options& options)
+ const Preconditioner::Options& options)
: options_(options),
num_blocks_(0),
num_clusters_(0),
factor_(NULL) {
- CHECK_GT(options_.num_eliminate_blocks, 0);
- CHECK(options_.preconditioner_type == SCHUR_JACOBI ||
- options_.preconditioner_type == CLUSTER_JACOBI ||
- options_.preconditioner_type == CLUSTER_TRIDIAGONAL)
- << "Unknown preconditioner type: " << options_.preconditioner_type;
- num_blocks_ = bs.cols.size() - options_.num_eliminate_blocks;
+ CHECK_GT(options_.elimination_groups.size(), 1);
+ CHECK_GT(options_.elimination_groups[0], 0);
+ CHECK(options_.type == CLUSTER_JACOBI ||
+ options_.type == CLUSTER_TRIDIAGONAL)
+ << "Unknown preconditioner type: " << options_.type;
+ num_blocks_ = bs.cols.size() - options_.elimination_groups[0];
CHECK_GT(num_blocks_, 0)
<< "Jacobian should have atleast 1 f_block for "
<< "visibility based preconditioning.";
@@ -83,14 +84,11 @@ VisibilityBasedPreconditioner::VisibilityBasedPreconditioner(
// Vector of camera block sizes
block_size_.resize(num_blocks_);
for (int i = 0; i < num_blocks_; ++i) {
- block_size_[i] = bs.cols[i + options_.num_eliminate_blocks].size;
+ block_size_[i] = bs.cols[i + options_.elimination_groups[0]].size;
}
const time_t start_time = time(NULL);
- switch (options_.preconditioner_type) {
- case SCHUR_JACOBI:
- ComputeSchurJacobiSparsity(bs);
- break;
+ switch (options_.type) {
case CLUSTER_JACOBI:
ComputeClusterJacobiSparsity(bs);
break;
@@ -130,24 +128,6 @@ VisibilityBasedPreconditioner::~VisibilityBasedPreconditioner() {
}
}
-// Determine the sparsity structure of the SCHUR_JACOBI
-// preconditioner. SCHUR_JACOBI is an extreme case of a visibility
-// based preconditioner where each camera block corresponds to a
-// cluster and there is no interaction between clusters.
-void VisibilityBasedPreconditioner::ComputeSchurJacobiSparsity(
- const CompressedRowBlockStructure& bs) {
- num_clusters_ = num_blocks_;
- cluster_membership_.resize(num_blocks_);
- cluster_pairs_.clear();
-
- // Each camea block is a member of its own cluster and the only
- // cluster pairs are the self edges (i,i).
- for (int i = 0; i < num_clusters_; ++i) {
- cluster_membership_[i] = i;
- cluster_pairs_.insert(make_pair(i, i));
- }
-}
-
// Determine the sparsity structure of the CLUSTER_JACOBI
// preconditioner. It clusters cameras using their scene
// visibility. The clusters form the diagonal blocks of the
@@ -155,7 +135,7 @@ void VisibilityBasedPreconditioner::ComputeSchurJacobiSparsity(
void VisibilityBasedPreconditioner::ComputeClusterJacobiSparsity(
const CompressedRowBlockStructure& bs) {
vector<set<int> > visibility;
- ComputeVisibility(bs, options_.num_eliminate_blocks, &visibility);
+ ComputeVisibility(bs, options_.elimination_groups[0], &visibility);
CHECK_EQ(num_blocks_, visibility.size());
ClusterCameras(visibility);
cluster_pairs_.clear();
@@ -173,7 +153,7 @@ void VisibilityBasedPreconditioner::ComputeClusterJacobiSparsity(
void VisibilityBasedPreconditioner::ComputeClusterTridiagonalSparsity(
const CompressedRowBlockStructure& bs) {
vector<set<int> > visibility;
- ComputeVisibility(bs, options_.num_eliminate_blocks, &visibility);
+ ComputeVisibility(bs, options_.elimination_groups[0], &visibility);
CHECK_EQ(num_blocks_, visibility.size());
ClusterCameras(visibility);
@@ -253,7 +233,7 @@ void VisibilityBasedPreconditioner::ComputeBlockPairsInPreconditioner(
int r = 0;
const int num_row_blocks = bs.rows.size();
- const int num_eliminate_blocks = options_.num_eliminate_blocks;
+ const int num_eliminate_blocks = options_.elimination_groups[0];
// Iterate over each row of the matrix. The block structure of the
// matrix is assumed to be sorted in order of the e_blocks/point
@@ -331,16 +311,16 @@ void VisibilityBasedPreconditioner::ComputeBlockPairsInPreconditioner(
void VisibilityBasedPreconditioner::InitEliminator(
const CompressedRowBlockStructure& bs) {
LinearSolver::Options eliminator_options;
- eliminator_options.num_eliminate_blocks = options_.num_eliminate_blocks;
+ eliminator_options.elimination_groups = options_.elimination_groups;
eliminator_options.num_threads = options_.num_threads;
- DetectStructure(bs, options_.num_eliminate_blocks,
+ DetectStructure(bs, options_.elimination_groups[0],
&eliminator_options.row_block_size,
&eliminator_options.e_block_size,
&eliminator_options.f_block_size);
eliminator_.reset(SchurEliminatorBase::Create(eliminator_options));
- eliminator_->Init(options_.num_eliminate_blocks, &bs);
+ eliminator_->Init(options_.elimination_groups[0], &bs);
}
// Update the values of the preconditioner matrix and factorize it.
@@ -364,13 +344,13 @@ bool VisibilityBasedPreconditioner::Update(const BlockSparseMatrixBase& A,
// Compute a subset of the entries of the Schur complement.
eliminator_->Eliminate(&A, b.data(), D, m_.get(), rhs.data());
- // Try factorizing the matrix. For SCHUR_JACOBI and CLUSTER_JACOBI,
- // this should always succeed modulo some numerical/conditioning
- // problems. For CLUSTER_TRIDIAGONAL, in general the preconditioner
- // matrix as constructed is not positive definite. However, we will
- // go ahead and try factorizing it. If it works, great, otherwise we
- // scale all the cells in the preconditioner corresponding to the
- // edges in the degree-2 forest and that guarantees positive
+ // Try factorizing the matrix. For CLUSTER_JACOBI, this should
+ // always succeed modulo some numerical/conditioning problems. For
+ // CLUSTER_TRIDIAGONAL, in general the preconditioner matrix as
+ // constructed is not positive definite. However, we will go ahead
+ // and try factorizing it. If it works, great, otherwise we scale
+ // all the cells in the preconditioner corresponding to the edges in
+ // the degree-2 forest and that guarantees positive
// definiteness. The proof of this fact can be found in Lemma 1 in
// "Visibility Based Preconditioning for Bundle Adjustment".
//
@@ -380,10 +360,10 @@ bool VisibilityBasedPreconditioner::Update(const BlockSparseMatrixBase& A,
// The scaling only affects the tri-diagonal case, since
// ScaleOffDiagonalBlocks only pays attenion to the cells that
- // belong to the edges of the degree-2 forest. In the SCHUR_JACOBI
- // and the CLUSTER_JACOBI cases, the preconditioner is guaranteed to
- // be positive semidefinite.
- if (!status && options_.preconditioner_type == CLUSTER_TRIDIAGONAL) {
+ // belong to the edges of the degree-2 forest. In the CLUSTER_JACOBI
+ // case, the preconditioner is guaranteed to be positive
+ // semidefinite.
+ if (!status && options_.type == CLUSTER_TRIDIAGONAL) {
VLOG(1) << "Unscaled factorization failed. Retrying with off-diagonal "
<< "scaling";
ScaleOffDiagonalCells();
@@ -448,7 +428,7 @@ bool VisibilityBasedPreconditioner::Factorize() {
}
if (VLOG_IS_ON(2)) {
- cholmod_print_common("Symbolic Analysis", ss_.mutable_cc());
+ cholmod_print_common(const_cast<char*>("Symbolic Analysis"), ss_.mutable_cc());
}
}
@@ -605,7 +585,7 @@ void VisibilityBasedPreconditioner::FlattenMembershipMap(
}
}
-#endif // CERES_NO_SUITESPARSE
-
} // namespace internal
} // namespace ceres
+
+#endif // CERES_NO_SUITESPARSE
diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h
index 888c65eba3a..dae498730aa 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h
@@ -29,25 +29,20 @@
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Preconditioners for linear systems that arise in Structure from
-// Motion problems. VisibilityBasedPreconditioner implements three
-// preconditioners:
+// Motion problems. VisibilityBasedPreconditioner implements:
//
-// SCHUR_JACOBI
// CLUSTER_JACOBI
// CLUSTER_TRIDIAGONAL
//
// Detailed descriptions of these preconditions beyond what is
// documented here can be found in
//
-// Bundle Adjustment in the Large
-// S. Agarwal, N. Snavely, S. Seitz & R. Szeliski, ECCV 2010
-// http://www.cs.washington.edu/homes/sagarwal/bal.pdf
-//
// Visibility Based Preconditioning for Bundle Adjustment
-// A. Kushal & S. Agarwal, submitted to CVPR 2012
+// A. Kushal & S. Agarwal, CVPR 2012.
+//
// http://www.cs.washington.edu/homes/sagarwal/vbp.pdf
//
-// The three preconditioners share enough code that its most efficient
+// The two preconditioners share enough code that its most efficient
// to implement them as part of the same code base.
#ifndef CERES_INTERNAL_VISIBILITY_BASED_PRECONDITIONER_H_
@@ -58,36 +53,26 @@
#include <utility>
#include "ceres/collections_port.h"
#include "ceres/graph.h"
-#include "ceres/linear_solver.h"
-#include "ceres/linear_operator.h"
-#include "ceres/suitesparse.h"
#include "ceres/internal/macros.h"
#include "ceres/internal/scoped_ptr.h"
+#include "ceres/preconditioner.h"
+#include "ceres/suitesparse.h"
namespace ceres {
namespace internal {
class BlockRandomAccessSparseMatrix;
class BlockSparseMatrixBase;
-class CompressedRowBlockStructure;
+struct CompressedRowBlockStructure;
class SchurEliminatorBase;
-// This class implements three preconditioners for Structure from
-// Motion/Bundle Adjustment problems. The name
+// This class implements visibility based preconditioners for
+// Structure from Motion/Bundle Adjustment problems. The name
// VisibilityBasedPreconditioner comes from the fact that the sparsity
// structure of the preconditioner matrix is determined by analyzing
// the visibility structure of the scene, i.e. which cameras see which
// points.
//
-// Strictly speaking, SCHUR_JACOBI is not a visibility based
-// preconditioner but it is an extreme case of CLUSTER_JACOBI, where
-// every cluster contains exactly one camera block. Treating it as a
-// special case of CLUSTER_JACOBI makes it easy to implement as part
-// of the same code base with no significant loss of performance.
-//
-// In the following, we will only discuss CLUSTER_JACOBI and
-// CLUSTER_TRIDIAGONAL.
-//
// The key idea of visibility based preconditioning is to identify
// cameras that we expect have strong interactions, and then using the
// entries in the Schur complement matrix corresponding to these
@@ -130,15 +115,15 @@ class SchurEliminatorBase;
//
// LinearSolver::Options options;
// options.preconditioner_type = CLUSTER_JACOBI;
-// options.num_eliminate_blocks = num_points;
+// options.elimination_groups.push_back(num_points);
+// options.elimination_groups.push_back(num_cameras);
// VisibilityBasedPreconditioner preconditioner(
// *A.block_structure(), options);
// preconditioner.Update(A, NULL);
// preconditioner.RightMultiply(x, y);
//
-
#ifndef CERES_NO_SUITESPARSE
-class VisibilityBasedPreconditioner : public LinearOperator {
+class VisibilityBasedPreconditioner : public Preconditioner {
public:
// Initialize the symbolic structure of the preconditioner. bs is
// the block structure of the linear system to be solved. It is used
@@ -146,48 +131,17 @@ class VisibilityBasedPreconditioner : public LinearOperator {
//
// It has the same structural requirement as other Schur complement
// based solvers. Please see schur_eliminator.h for more details.
- //
- // LinearSolver::Options::num_eliminate_blocks should be set to the
- // number of e_blocks in the block structure.
- //
- // TODO(sameeragarwal): The use of LinearSolver::Options should
- // ultimately be replaced with Preconditioner::Options and some sort
- // of preconditioner factory along the lines of
- // LinearSolver::CreateLinearSolver. I will wait to do this till I
- // create a general purpose block Jacobi preconditioner for general
- // sparse problems along with a CGLS solver.
VisibilityBasedPreconditioner(const CompressedRowBlockStructure& bs,
- const LinearSolver::Options& options);
+ const Preconditioner::Options& options);
virtual ~VisibilityBasedPreconditioner();
- // Update the numerical value of the preconditioner for the linear
- // system:
- //
- // | A | x = |b|
- // |diag(D)| |0|
- //
- // for some vector b. It is important that the matrix A have the
- // same block structure as the one used to construct this object.
- //
- // D can be NULL, in which case its interpreted as a diagonal matrix
- // of size zero.
- bool Update(const BlockSparseMatrixBase& A, const double* D);
-
-
- // LinearOperator interface. Since the operator is symmetric,
- // LeftMultiply and num_cols are just calls to RightMultiply and
- // num_rows respectively. Update() must be called before
- // RightMultiply can be called.
+ // Preconditioner interface
+ virtual bool Update(const BlockSparseMatrixBase& A, const double* D);
virtual void RightMultiply(const double* x, double* y) const;
- virtual void LeftMultiply(const double* x, double* y) const {
- RightMultiply(x, y);
- }
virtual int num_rows() const;
- virtual int num_cols() const { return num_rows(); }
friend class VisibilityBasedPreconditionerTest;
private:
- void ComputeSchurJacobiSparsity(const CompressedRowBlockStructure& bs);
void ComputeClusterJacobiSparsity(const CompressedRowBlockStructure& bs);
void ComputeClusterTridiagonalSparsity(const CompressedRowBlockStructure& bs);
void InitStorage(const CompressedRowBlockStructure& bs);
@@ -207,7 +161,7 @@ class VisibilityBasedPreconditioner : public LinearOperator {
bool IsBlockPairInPreconditioner(int block1, int block2) const;
bool IsBlockPairOffDiagonal(int block1, int block2) const;
- LinearSolver::Options options_;
+ Preconditioner::Options options_;
// Number of parameter blocks in the schur complement.
int num_blocks_;
@@ -249,10 +203,10 @@ class VisibilityBasedPreconditioner : public LinearOperator {
#else // SuiteSparse
// If SuiteSparse is not compiled in, the preconditioner is not
// available.
-class VisibilityBasedPreconditioner : public LinearOperator {
+class VisibilityBasedPreconditioner : public Preconditioner {
public:
VisibilityBasedPreconditioner(const CompressedRowBlockStructure& bs,
- const LinearSolver::Options& options) {
+ const Preconditioner::Options& options) {
LOG(FATAL) << "Visibility based preconditioning is not available. Please "
"build Ceres with SuiteSparse.";
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/wall_time.cc b/extern/libmv/third_party/ceres/internal/ceres/wall_time.cc
new file mode 100644
index 00000000000..e63d20c0ab1
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/wall_time.cc
@@ -0,0 +1,96 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: strandmark@google.com (Petter Strandmark)
+
+#include "ceres/wall_time.h"
+
+#ifdef CERES_USE_OPENMP
+#include <omp.h>
+#else
+#include <ctime>
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <sys/time.h>
+#endif
+
+namespace ceres {
+namespace internal {
+
+double WallTimeInSeconds() {
+#ifdef CERES_USE_OPENMP
+ return omp_get_wtime();
+#else
+#ifdef _WIN32
+ return static_cast<double>(std::time(NULL));
+#else
+ timeval time_val;
+ gettimeofday(&time_val, NULL);
+ return (time_val.tv_sec + time_val.tv_usec * 1e-6);
+#endif
+#endif
+}
+
+EventLogger::EventLogger(const string& logger_name)
+ : start_time_(WallTimeInSeconds()),
+ last_event_time_(start_time_),
+ events_("") {
+ StringAppendF(&events_,
+ "\n%s\n Delta Cumulative\n",
+ logger_name.c_str());
+}
+
+EventLogger::~EventLogger() {
+ if (VLOG_IS_ON(3)) {
+ AddEvent("Total");
+ VLOG(2) << "\n" << events_ << "\n";
+ }
+}
+
+void EventLogger::AddEvent(const string& event_name) {
+ if (!VLOG_IS_ON(3)) {
+ return;
+ }
+
+ const double current_time = WallTimeInSeconds();
+ const double relative_time_delta = current_time - last_event_time_;
+ const double absolute_time_delta = current_time - start_time_;
+ last_event_time_ = current_time;
+
+ StringAppendF(&events_,
+ " %25s : %10.5f %10.5f\n",
+ event_name.c_str(),
+ relative_time_delta,
+ absolute_time_delta);
+}
+
+} // namespace internal
+} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/wall_time.h b/extern/libmv/third_party/ceres/internal/ceres/wall_time.h
new file mode 100644
index 00000000000..45f65ca1aa5
--- /dev/null
+++ b/extern/libmv/third_party/ceres/internal/ceres/wall_time.h
@@ -0,0 +1,88 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+// used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: strandmark@google.com (Petter Strandmark)
+
+#ifndef CERES_INTERNAL_WALL_TIME_H_
+#define CERES_INTERNAL_WALL_TIME_H_
+
+#include <map>
+
+#include "ceres/internal/port.h"
+#include "ceres/stringprintf.h"
+#include "glog/logging.h"
+
+namespace ceres {
+namespace internal {
+
+// Returns time, in seconds, from some arbitrary starting point. If
+// OpenMP is available then the high precision openmp_get_wtime()
+// function is used. Otherwise on unixes, gettimeofday is used. The
+// granularity is in seconds on windows systems.
+double WallTimeInSeconds();
+
+// Log a series of events, recording for each event the time elapsed
+// since the last event and since the creation of the object.
+//
+// The information is output to VLOG(3) upon destruction. A
+// name::Total event is added as the final event right before
+// destruction.
+//
+// Example usage:
+//
+// void Foo() {
+// EventLogger event_logger("Foo");
+// Bar1();
+// event_logger.AddEvent("Bar1")
+// Bar2();
+// event_logger.AddEvent("Bar2")
+// Bar3();
+// }
+//
+// Will produce output that looks like
+//
+// Foo
+// Bar1: time1 time1
+// Bar2: time2 time1 + time2;
+// Total: time3 time1 + time2 + time3;
+class EventLogger {
+ public:
+ explicit EventLogger(const string& logger_name);
+ ~EventLogger();
+ void AddEvent(const string& event_name);
+
+ private:
+ const double start_time_;
+ double last_event_time_;
+ string events_;
+};
+
+} // namespace internal
+} // namespace ceres
+
+#endif // CERES_INTERNAL_WALL_TIME_H_
diff --git a/extern/libmv/third_party/ceres/mkfiles.sh b/extern/libmv/third_party/ceres/mkfiles.sh
index d335829aa2c..d335829aa2c 100755..100644
--- a/extern/libmv/third_party/ceres/mkfiles.sh
+++ b/extern/libmv/third_party/ceres/mkfiles.sh
diff --git a/extern/libmv/third_party/ceres/patches/collections_port.h.mingw.patch b/extern/libmv/third_party/ceres/patches/collections_port.h.mingw.patch
deleted file mode 100644
index c01a17c7992..00000000000
--- a/extern/libmv/third_party/ceres/patches/collections_port.h.mingw.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/internal/ceres/collections_port.h b/internal/ceres/collections_port.h
-index a356cc0..c2fce90 100644
---- a/internal/ceres/collections_port.h
-+++ b/internal/ceres/collections_port.h
-@@ -77,7 +77,7 @@ struct HashMap : std::tr1::unordered_map<K, V> {};
- template<typename K>
- struct HashSet : std::tr1::unordered_set<K> {};
-
--#ifdef _WIN32
-+#if defined(_WIN32) && !defined(__MINGW64__) && !defined(__MINGW32__)
- #define GG_LONGLONG(x) x##I64
- #define GG_ULONGLONG(x) x##UI64
- #else
diff --git a/extern/libmv/third_party/ceres/patches/msvc_glog_fix.patch b/extern/libmv/third_party/ceres/patches/msvc_glog_fix.patch
deleted file mode 100644
index f3200fb8e0a..00000000000
--- a/extern/libmv/third_party/ceres/patches/msvc_glog_fix.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-diff --git a/internal/ceres/block_random_access_dense_matrix.cc b/internal/ceres/block_random_access_dense_matrix.cc
-index aedfc74..0f95e89 100644
---- a/internal/ceres/block_random_access_dense_matrix.cc
-+++ b/internal/ceres/block_random_access_dense_matrix.cc
-@@ -28,12 +28,12 @@
- //
- // Author: sameeragarwal@google.com (Sameer Agarwal)
-
-+#include "glog/logging.h"
- #include "ceres/block_random_access_dense_matrix.h"
-
- #include <vector>
- #include "ceres/internal/eigen.h"
- #include "ceres/internal/scoped_ptr.h"
--#include "glog/logging.h"
-
- namespace ceres {
- namespace internal {
-diff --git a/internal/ceres/block_random_access_sparse_matrix.cc b/internal/ceres/block_random_access_sparse_matrix.cc
-index f789436..9ed62ce 100644
---- a/internal/ceres/block_random_access_sparse_matrix.cc
-+++ b/internal/ceres/block_random_access_sparse_matrix.cc
-@@ -28,6 +28,7 @@
- //
- // Author: sameeragarwal@google.com (Sameer Agarwal)
-
-+#include "glog/logging.h"
- #include "ceres/block_random_access_sparse_matrix.h"
-
- #include <algorithm>
-@@ -39,7 +40,6 @@
- #include "ceres/mutex.h"
- #include "ceres/triplet_sparse_matrix.h"
- #include "ceres/types.h"
--#include "glog/logging.h"
-
- namespace ceres {
- namespace internal {
-diff --git a/internal/ceres/schur_complement_solver.cc b/internal/ceres/schur_complement_solver.cc
-index b9224d8..2cbe78d 100644
---- a/internal/ceres/schur_complement_solver.cc
-+++ b/internal/ceres/schur_complement_solver.cc
-@@ -38,6 +38,7 @@
- #endif // CERES_NO_CXSPARSE
-
- #include "Eigen/Dense"
-+#include "glog/logging.h"
- #include "ceres/block_random_access_dense_matrix.h"
- #include "ceres/block_random_access_matrix.h"
- #include "ceres/block_random_access_sparse_matrix.h"
diff --git a/extern/libmv/third_party/ceres/patches/no_previous_declaration_fix.patch b/extern/libmv/third_party/ceres/patches/no_previous_declaration_fix.patch
deleted file mode 100644
index 03f1c500d9a..00000000000
--- a/extern/libmv/third_party/ceres/patches/no_previous_declaration_fix.patch
+++ /dev/null
@@ -1,199 +0,0 @@
-diff --git a/internal/ceres/file.cc b/internal/ceres/file.cc
-index 387f359..6fe7557 100644
---- a/internal/ceres/file.cc
-+++ b/internal/ceres/file.cc
-@@ -31,6 +31,7 @@
- // Really simple file IO.
-
- #include <cstdio>
-+#include "file.h"
- #include "glog/logging.h"
-
- namespace ceres {
-diff --git a/internal/ceres/linear_least_squares_problems.cc b/internal/ceres/linear_least_squares_problems.cc
-index 3e3bcd0..a91e254 100644
---- a/internal/ceres/linear_least_squares_problems.cc
-+++ b/internal/ceres/linear_least_squares_problems.cc
-@@ -573,13 +573,13 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem3() {
- return problem;
- }
-
--bool DumpLinearLeastSquaresProblemToConsole(const string& directory,
-- int iteration,
-- const SparseMatrix* A,
-- const double* D,
-- const double* b,
-- const double* x,
-- int num_eliminate_blocks) {
-+static bool DumpLinearLeastSquaresProblemToConsole(const string& directory,
-+ int iteration,
-+ const SparseMatrix* A,
-+ const double* D,
-+ const double* b,
-+ const double* x,
-+ int num_eliminate_blocks) {
- CHECK_NOTNULL(A);
- Matrix AA;
- A->ToDenseMatrix(&AA);
-@@ -601,13 +601,13 @@ bool DumpLinearLeastSquaresProblemToConsole(const string& directory,
- };
-
- #ifndef CERES_NO_PROTOCOL_BUFFERS
--bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
-- int iteration,
-- const SparseMatrix* A,
-- const double* D,
-- const double* b,
-- const double* x,
-- int num_eliminate_blocks) {
-+static bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
-+ int iteration,
-+ const SparseMatrix* A,
-+ const double* D,
-+ const double* b,
-+ const double* x,
-+ int num_eliminate_blocks) {
- CHECK_NOTNULL(A);
- LinearLeastSquaresProblemProto lsqp;
- A->ToProto(lsqp.mutable_a());
-@@ -641,13 +641,13 @@ bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
- return true;
- }
- #else
--bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
-- int iteration,
-- const SparseMatrix* A,
-- const double* D,
-- const double* b,
-- const double* x,
-- int num_eliminate_blocks) {
-+static bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
-+ int iteration,
-+ const SparseMatrix* A,
-+ const double* D,
-+ const double* b,
-+ const double* x,
-+ int num_eliminate_blocks) {
- LOG(ERROR) << "Dumping least squares problems is only "
- << "supported when Ceres is compiled with "
- << "protocol buffer support.";
-@@ -655,9 +655,9 @@ bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory,
- }
- #endif
-
--void WriteArrayToFileOrDie(const string& filename,
-- const double* x,
-- const int size) {
-+static void WriteArrayToFileOrDie(const string& filename,
-+ const double* x,
-+ const int size) {
- CHECK_NOTNULL(x);
- VLOG(2) << "Writing array to: " << filename;
- FILE* fptr = fopen(filename.c_str(), "w");
-@@ -668,13 +668,13 @@ void WriteArrayToFileOrDie(const string& filename,
- fclose(fptr);
- }
-
--bool DumpLinearLeastSquaresProblemToTextFile(const string& directory,
-- int iteration,
-- const SparseMatrix* A,
-- const double* D,
-- const double* b,
-- const double* x,
-- int num_eliminate_blocks) {
-+static bool DumpLinearLeastSquaresProblemToTextFile(const string& directory,
-+ int iteration,
-+ const SparseMatrix* A,
-+ const double* D,
-+ const double* b,
-+ const double* x,
-+ int num_eliminate_blocks) {
- CHECK_NOTNULL(A);
- string format_string = JoinPath(directory,
- "lm_iteration_%03d");
-diff --git a/internal/ceres/residual_block_utils.cc b/internal/ceres/residual_block_utils.cc
-index ff18e21..9442bb2 100644
---- a/internal/ceres/residual_block_utils.cc
-+++ b/internal/ceres/residual_block_utils.cc
-@@ -63,7 +63,7 @@ void InvalidateEvaluation(const ResidualBlock& block,
-
- // Utility routine to print an array of doubles to a string. If the
- // array pointer is NULL, it is treated as an array of zeros.
--void AppendArrayToString(const int size, const double* x, string* result) {
-+static void AppendArrayToString(const int size, const double* x, string* result) {
- for (int i = 0; i < size; ++i) {
- if (x == NULL) {
- StringAppendF(result, "Not Computed ");
-diff --git a/internal/ceres/solver_impl.cc b/internal/ceres/solver_impl.cc
-index 2802a75..8ef5b98 100644
---- a/internal/ceres/solver_impl.cc
-+++ b/internal/ceres/solver_impl.cc
-@@ -685,8 +685,8 @@ bool SolverImpl::ApplyUserOrdering(const ProblemImpl& problem_impl,
- // Find the minimum index of any parameter block to the given residual.
- // Parameter blocks that have indices greater than num_eliminate_blocks are
- // considered to have an index equal to num_eliminate_blocks.
--int MinParameterBlock(const ResidualBlock* residual_block,
-- int num_eliminate_blocks) {
-+static int MinParameterBlock(const ResidualBlock* residual_block,
-+ int num_eliminate_blocks) {
- int min_parameter_block_position = num_eliminate_blocks;
- for (int i = 0; i < residual_block->NumParameterBlocks(); ++i) {
- ParameterBlock* parameter_block = residual_block->parameter_blocks()[i];
-diff --git a/internal/ceres/split.cc b/internal/ceres/split.cc
-index 4fa1bd4..c65c8a5 100644
---- a/internal/ceres/split.cc
-+++ b/internal/ceres/split.cc
-@@ -31,6 +31,7 @@
- #include <string>
- #include <vector>
- #include <iterator>
-+#include "ceres/split.h"
- #include "ceres/internal/port.h"
-
- namespace ceres {
-diff --git a/internal/ceres/stringprintf.cc b/internal/ceres/stringprintf.cc
-index c0f3522..396a48b 100644
---- a/internal/ceres/stringprintf.cc
-+++ b/internal/ceres/stringprintf.cc
-@@ -34,6 +34,7 @@
- #include <string>
- #include <vector>
-
-+#include "ceres/stringprintf.h"
- #include "ceres/internal/port.h"
-
- namespace ceres {
-diff --git a/internal/ceres/types.cc b/internal/ceres/types.cc
-index 2e950c5..05e573f 100644
---- a/internal/ceres/types.cc
-+++ b/internal/ceres/types.cc
-@@ -98,7 +98,8 @@ const char* SolverTerminationTypeToString(
- }
- }
-
--const char* SparseLinearAlgebraTypeToString(
-+#if 0 /* UNUSED */
-+static const char* SparseLinearAlgebraTypeToString(
- SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type) {
- switch (sparse_linear_algebra_library_type) {
- CASESTR(CX_SPARSE);
-@@ -107,6 +108,7 @@ const char* SparseLinearAlgebraTypeToString(
- return "UNKNOWN";
- }
- }
-+#endif
-
- const char* TrustRegionStrategyTypeToString(
- TrustRegionStrategyType trust_region_strategy_type) {
-diff --git a/internal/ceres/visibility.cc b/internal/ceres/visibility.cc
-index 9d80654..564cc54 100644
---- a/internal/ceres/visibility.cc
-+++ b/internal/ceres/visibility.cc
-@@ -36,6 +36,7 @@
- #include <utility>
- #include "ceres/block_structure.h"
- #include "ceres/collections_port.h"
-+#include "ceres/visibility.h"
- #include "ceres/graph.h"
- #include "glog/logging.h"
-
diff --git a/extern/libmv/third_party/ceres/patches/series b/extern/libmv/third_party/ceres/patches/series
index a6874318923..e69de29bb2d 100644
--- a/extern/libmv/third_party/ceres/patches/series
+++ b/extern/libmv/third_party/ceres/patches/series
@@ -1,3 +0,0 @@
-collections_port.h.mingw.patch
-msvc_glog_fix.patch
-no_previous_declaration_fix.patch \ No newline at end of file
diff --git a/extern/libmv/third_party/gflags/README.libmv b/extern/libmv/third_party/gflags/README.libmv
index 673099ce618..b310c57ac34 100644
--- a/extern/libmv/third_party/gflags/README.libmv
+++ b/extern/libmv/third_party/gflags/README.libmv
@@ -11,4 +11,6 @@ Local modifications:
- 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.
+- Added -fPIC flag, so shared libraries from Ceres could be linked against static glog
+
TODO(keir): Import and use gflags for Windows from upstream.
diff --git a/extern/libmv/third_party/glog/README.libmv b/extern/libmv/third_party/glog/README.libmv
index 025a70b76a5..345bc9f5969 100644
--- a/extern/libmv/third_party/glog/README.libmv
+++ b/extern/libmv/third_party/glog/README.libmv
@@ -22,3 +22,4 @@ Upgrading Notes
* Do not define va_copy for MinGW platforms (it's already defined there).
* Patch localtime_r to be working fine with MinGW, disable strerror_r for MinGW because
of lack of needed functions.
+* Added -fPIC flag, so shared libraries from Ceres could be linked against static glog
diff --git a/extern/libmv/third_party/ldl/CMakeLists.txt b/extern/libmv/third_party/ldl/CMakeLists.txt
deleted file mode 100644
index db2d40e2612..00000000000
--- a/extern/libmv/third_party/ldl/CMakeLists.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-include_directories(../ufconfig)
-include_directories(Include)
-add_library(ldl Source/ldl.c)
-
-LIBMV_INSTALL_THIRD_PARTY_LIB(ldl)
diff --git a/extern/libmv/third_party/ldl/Doc/ChangeLog b/extern/libmv/third_party/ldl/Doc/ChangeLog
deleted file mode 100644
index 48c322d3e77..00000000000
--- a/extern/libmv/third_party/ldl/Doc/ChangeLog
+++ /dev/null
@@ -1,39 +0,0 @@
-May 31, 2007: version 2.0.0
-
- * C-callable 64-bit version added
-
- * ported to 64-bit MATLAB
-
- * subdirectories added (Source/, Include/, Lib/, Demo/, Doc/, MATLAB/)
-
-Dec 12, 2006: version 1.3.4
-
- * minor MATLAB cleanup
-
-Sept 11, 2006: version 1.3.1
-
- * The ldl m-file renamed to ldlsparse, to avoid name conflict with the
- new MATLAB ldl function (in MATLAB 7.3).
-
-Apr 30, 2006: version 1.3
-
- * requires AMD v2.0. ldlmain.c demo program modified, since AMD can now
- handle jumbled matrices. Minor change to Makefile.
-
-Aug 30, 2005:
-
- * Makefile changed to use ../UFconfig/UFconfig.mk. License changed to
- GNU LGPL.
-
-July 4, 2005:
-
- * user guide added. Since no changes to the code were made,
- the version number (1.1) and code release date (Apr 22, 2005)
- were left unchanged.
-
-Apr. 22, 2005: LDL v1.1 released.
-
- * No real changes were made. The code was revised so
- that each routine fits on a single page in the documentation.
-
-Dec 31, 2003: LDL v1.0 released.
diff --git a/extern/libmv/third_party/ldl/Doc/lesser.txt b/extern/libmv/third_party/ldl/Doc/lesser.txt
deleted file mode 100644
index 8add30ad590..00000000000
--- a/extern/libmv/third_party/ldl/Doc/lesser.txt
+++ /dev/null
@@ -1,504 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library 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.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
diff --git a/extern/libmv/third_party/ldl/Include/ldl.h b/extern/libmv/third_party/ldl/Include/ldl.h
deleted file mode 100644
index 5840be322f7..00000000000
--- a/extern/libmv/third_party/ldl/Include/ldl.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/* ========================================================================== */
-/* === ldl.h: include file for the LDL package ============================= */
-/* ========================================================================== */
-
-/* LDL Copyright (c) Timothy A Davis,
- * University of Florida. All Rights Reserved. See README for the License.
- */
-
-#include "UFconfig.h"
-
-#ifdef LDL_LONG
-#define LDL_int UF_long
-#define LDL_ID UF_long_id
-
-#define LDL_symbolic ldl_l_symbolic
-#define LDL_numeric ldl_l_numeric
-#define LDL_lsolve ldl_l_lsolve
-#define LDL_dsolve ldl_l_dsolve
-#define LDL_ltsolve ldl_l_ltsolve
-#define LDL_perm ldl_l_perm
-#define LDL_permt ldl_l_permt
-#define LDL_valid_perm ldl_l_valid_perm
-#define LDL_valid_matrix ldl_l_valid_matrix
-
-#else
-#define LDL_int int
-#define LDL_ID "%d"
-
-#define LDL_symbolic ldl_symbolic
-#define LDL_numeric ldl_numeric
-#define LDL_lsolve ldl_lsolve
-#define LDL_dsolve ldl_dsolve
-#define LDL_ltsolve ldl_ltsolve
-#define LDL_perm ldl_perm
-#define LDL_permt ldl_permt
-#define LDL_valid_perm ldl_valid_perm
-#define LDL_valid_matrix ldl_valid_matrix
-
-#endif
-
-/* ========================================================================== */
-/* === int version ========================================================== */
-/* ========================================================================== */
-
-void ldl_symbolic (int n, int Ap [ ], int Ai [ ], int Lp [ ],
- int Parent [ ], int Lnz [ ], int Flag [ ], int P [ ], int Pinv [ ]) ;
-
-int ldl_numeric (int n, int Ap [ ], int Ai [ ], double Ax [ ],
- int Lp [ ], int Parent [ ], int Lnz [ ], int Li [ ], double Lx [ ],
- double D [ ], double Y [ ], int Pattern [ ], int Flag [ ],
- int P [ ], int Pinv [ ]) ;
-
-void ldl_lsolve (int n, double X [ ], int Lp [ ], int Li [ ],
- double Lx [ ]) ;
-
-void ldl_dsolve (int n, double X [ ], double D [ ]) ;
-
-void ldl_ltsolve (int n, double X [ ], int Lp [ ], int Li [ ],
- double Lx [ ]) ;
-
-void ldl_perm (int n, double X [ ], double B [ ], int P [ ]) ;
-void ldl_permt (int n, double X [ ], double B [ ], int P [ ]) ;
-
-int ldl_valid_perm (int n, int P [ ], int Flag [ ]) ;
-int ldl_valid_matrix ( int n, int Ap [ ], int Ai [ ]) ;
-
-/* ========================================================================== */
-/* === long version ========================================================= */
-/* ========================================================================== */
-
-void ldl_l_symbolic (UF_long n, UF_long Ap [ ], UF_long Ai [ ], UF_long Lp [ ],
- UF_long Parent [ ], UF_long Lnz [ ], UF_long Flag [ ], UF_long P [ ],
- UF_long Pinv [ ]) ;
-
-UF_long ldl_l_numeric (UF_long n, UF_long Ap [ ], UF_long Ai [ ], double Ax [ ],
- UF_long Lp [ ], UF_long Parent [ ], UF_long Lnz [ ], UF_long Li [ ],
- double Lx [ ], double D [ ], double Y [ ], UF_long Pattern [ ],
- UF_long Flag [ ], UF_long P [ ], UF_long Pinv [ ]) ;
-
-void ldl_l_lsolve (UF_long n, double X [ ], UF_long Lp [ ], UF_long Li [ ],
- double Lx [ ]) ;
-
-void ldl_l_dsolve (UF_long n, double X [ ], double D [ ]) ;
-
-void ldl_l_ltsolve (UF_long n, double X [ ], UF_long Lp [ ], UF_long Li [ ],
- double Lx [ ]) ;
-
-void ldl_l_perm (UF_long n, double X [ ], double B [ ], UF_long P [ ]) ;
-void ldl_l_permt (UF_long n, double X [ ], double B [ ], UF_long P [ ]) ;
-
-UF_long ldl_l_valid_perm (UF_long n, UF_long P [ ], UF_long Flag [ ]) ;
-UF_long ldl_l_valid_matrix ( UF_long n, UF_long Ap [ ], UF_long Ai [ ]) ;
-
-/* ========================================================================== */
-/* === LDL version ========================================================== */
-/* ========================================================================== */
-
-#define LDL_DATE "Nov 1, 2007"
-#define LDL_VERSION_CODE(main,sub) ((main) * 1000 + (sub))
-#define LDL_MAIN_VERSION 2
-#define LDL_SUB_VERSION 0
-#define LDL_SUBSUB_VERSION 1
-#define LDL_VERSION LDL_VERSION_CODE(LDL_MAIN_VERSION,LDL_SUB_VERSION)
-
diff --git a/extern/libmv/third_party/ldl/README.libmv b/extern/libmv/third_party/ldl/README.libmv
deleted file mode 100644
index 64ece48a390..00000000000
--- a/extern/libmv/third_party/ldl/README.libmv
+++ /dev/null
@@ -1,10 +0,0 @@
-Project: LDL
-URL: http://www.cise.ufl.edu/research/sparse/ldl/
-License: LGPL2.1
-Upstream version: 2.0.1 (despite the ChangeLog saying 2.0.0)
-
-Local modifications:
-
- * Deleted everything except ldl.c, ldl.h, the license, the ChangeLog, and the
- README.
-
diff --git a/extern/libmv/third_party/ldl/README.txt b/extern/libmv/third_party/ldl/README.txt
deleted file mode 100644
index 7be8dd1f001..00000000000
--- a/extern/libmv/third_party/ldl/README.txt
+++ /dev/null
@@ -1,136 +0,0 @@
-LDL Version 2.0: a sparse LDL' factorization and solve package.
- Written in C, with both a C and MATLAB mexFunction interface.
-
-These routines are not terrifically fast (they do not use dense matrix kernels),
-but the code is very short and concise. The purpose is to illustrate the
-algorithms in a very concise and readable manner, primarily for educational
-purposes. Although the code is very concise, this package is slightly faster
-than the built-in sparse Cholesky factorization in MATLAB 6.5 (chol), when
-using the same input permutation.
-
-Requires UFconfig, in the ../UFconfig directory relative to this directory.
-
-Quick start (Unix, or Windows with Cygwin):
-
- To compile, test, and install LDL, you may wish to first obtain a copy of
- AMD v2.0 from http://www.cise.ufl.edu/research/sparse, and place it in the
- ../AMD directory, relative to this directory. Next, type "make", which
- will compile the LDL library and three demo main programs (one of which
- requires AMD). It will also compile the LDL MATLAB mexFunction (if you
- have MATLAB). Typing "make clean" will remove non-essential files.
- AMD v2.0 or later is required. Its use is optional.
-
-Quick start (for MATLAB users);
-
- To compile, test, and install the LDL mexFunctions (ldlsparse and
- ldlsymbol), start MATLAB in this directory and type ldl_install.
- This works on any system supported by MATLAB.
-
---------------------------------------------------------------------------------
-
-LDL Copyright (c) 2005 by Timothy A. Davis. All Rights Reserved.
-
-LDL License:
-
- Your use or distribution of LDL or any modified version of
- LDL implies that you agree to this License.
-
- This library 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.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
- USA
-
- Permission is hereby granted to use or copy this program under the
- terms of the GNU LGPL, provided that the Copyright, this License,
- and the Availability of the original version is retained on all copies.
- User documentation of any code that uses this code or any modified
- version of this code must cite the Copyright, this License, the
- Availability note, and "Used by permission." Permission to modify
- the code and to distribute modified code is granted, provided the
- Copyright, this License, and the Availability note are retained,
- and a notice that the code was modified is included.
-
-Availability:
-
- http://www.cise.ufl.edu/research/sparse/ldl
-
-Acknowledgements:
-
- This work was supported by the National Science Foundation, under
- grant CCR-0203270.
-
- Portions of this work were done while on sabbatical at Stanford University
- and Lawrence Berkeley National Laboratory (with funding from the SciDAC
- program). I would like to thank Gene Golub, Esmond Ng, and Horst Simon
- for making this sabbatical possible. I would like to thank Pete Stewart
- for his comments on a draft of this software and paper.
-
---------------------------------------------------------------------------------
-Files and directories in this distribution:
---------------------------------------------------------------------------------
-
- Documentation, and compiling:
-
- README.txt this file
- Makefile for compiling LDL
- ChangeLog changes since V1.0 (Dec 31, 2003)
- License license
- lesser.txt the GNU LGPL license
-
- ldl_userguide.pdf user guide in PDF
- ldl_userguide.ps user guide in postscript
- ldl_userguide.tex user guide in Latex
- ldl.bib bibliography for user guide
-
- The LDL library itself:
-
- ldl.c the C-callable routines
- ldl.h include file for any code that calls LDL
-
- A simple C main program that demonstrates how to use LDL:
-
- ldlsimple.c a stand-alone C program, uses the basic features of LDL
- ldlsimple.out output of ldlsimple
-
- ldllsimple.c long integer version of ldlsimple.c
-
- Demo C program, for testing LDL and providing an example of its use
-
- ldlmain.c a stand-alone C main program that uses and tests LDL
- Matrix a directory containing matrices used by ldlmain.c
- ldlmain.out output of ldlmain
- ldlamd.out output of ldlamd (ldlmain.c compiled with AMD)
- ldllamd.out output of ldllamd (ldlmain.c compiled with AMD, long)
-
- MATLAB-related, not required for use in a regular C program
-
- Contents.m a list of the MATLAB-callable routines
- ldl.m MATLAB help file for the LDL mexFunction
- ldldemo.m MATLAB demo of how to use the LDL mexFunction
- ldldemo.out diary output of ldldemo
- ldltest.m to test the LDL mexFunction
- ldltest.out diary output of ldltest
- ldlmex.c the LDL mexFunction for MATLAB
- ldlrow.m the numerical algorithm that LDL is based on
- ldlmain2.m compiles and runs ldlmain.c as a MATLAB mexFunction
- ldlmain2.out output of ldlmain2.m
- ldlsymbolmex.c symbolic factorization using LDL (see SYMBFACT, ETREE)
- ldlsymbol.m help file for the LDLSYMBOL mexFunction
-
- ldl_install.m compile, install, and test LDL functions
- ldl_make.m compile LDL (ldlsparse and ldlsymbol)
-
- ldlsparse.m help for ldlsparse
-
-See ldl.c for a description of how to use the code from a C program. Type
-"help ldl" in MATLAB for information on how to use LDL in a MATLAB program.
diff --git a/extern/libmv/third_party/ldl/Source/ldl.c b/extern/libmv/third_party/ldl/Source/ldl.c
deleted file mode 100644
index a9b35c846ef..00000000000
--- a/extern/libmv/third_party/ldl/Source/ldl.c
+++ /dev/null
@@ -1,507 +0,0 @@
-/* ========================================================================== */
-/* === ldl.c: sparse LDL' factorization and solve package =================== */
-/* ========================================================================== */
-
-/* LDL: a simple set of routines for sparse LDL' factorization. These routines
- * are not terrifically fast (they do not use dense matrix kernels), but the
- * code is very short. The purpose is to illustrate the algorithms in a very
- * concise manner, primarily for educational purposes. Although the code is
- * very concise, this package is slightly faster than the built-in sparse
- * Cholesky factorization in MATLAB 7.0 (chol), when using the same input
- * permutation.
- *
- * The routines compute the LDL' factorization of a real sparse symmetric
- * matrix A (or PAP' if a permutation P is supplied), and solve upper
- * and lower triangular systems with the resulting L and D factors. If A is
- * positive definite then the factorization will be accurate. A can be
- * indefinite (with negative values on the diagonal D), but in this case no
- * guarantee of accuracy is provided, since no numeric pivoting is performed.
- *
- * The n-by-n sparse matrix A is in compressed-column form. The nonzero values
- * in column j are stored in Ax [Ap [j] ... Ap [j+1]-1], with corresponding row
- * indices in Ai [Ap [j] ... Ap [j+1]-1]. Ap [0] = 0 is required, and thus
- * nz = Ap [n] is the number of nonzeros in A. Ap is an int array of size n+1.
- * The int array Ai and the double array Ax are of size nz. This data structure
- * is identical to the one used by MATLAB, except for the following
- * generalizations. The row indices in each column of A need not be in any
- * particular order, although they must be in the range 0 to n-1. Duplicate
- * entries can be present; any duplicates are summed. That is, if row index i
- * appears twice in a column j, then the value of A (i,j) is the sum of the two
- * entries. The data structure used here for the input matrix A is more
- * flexible than MATLAB's, which requires sorted columns with no duplicate
- * entries.
- *
- * Only the diagonal and upper triangular part of A (or PAP' if a permutation
- * P is provided) is accessed. The lower triangular parts of the matrix A or
- * PAP' can be present, but they are ignored.
- *
- * The optional input permutation is provided as an array P of length n. If
- * P [k] = j, the row and column j of A is the kth row and column of PAP'.
- * If P is present then the factorization is LDL' = PAP' or L*D*L' = A(P,P) in
- * 0-based MATLAB notation. If P is not present (a null pointer) then no
- * permutation is performed, and the factorization is LDL' = A.
- *
- * The lower triangular matrix L is stored in the same compressed-column
- * form (an int Lp array of size n+1, an int Li array of size Lp [n], and a
- * double array Lx of the same size as Li). It has a unit diagonal, which is
- * not stored. The row indices in each column of L are always returned in
- * ascending order, with no duplicate entries. This format is compatible with
- * MATLAB, except that it would be more convenient for MATLAB to include the
- * unit diagonal of L. Doing so here would add additional complexity to the
- * code, and is thus omitted in the interest of keeping this code short and
- * readable.
- *
- * The elimination tree is held in the Parent [0..n-1] array. It is normally
- * not required by the user, but it is required by ldl_numeric. The diagonal
- * matrix D is held as an array D [0..n-1] of size n.
- *
- * --------------------
- * C-callable routines:
- * --------------------
- *
- * ldl_symbolic: Given the pattern of A, computes the Lp and Parent arrays
- * required by ldl_numeric. Takes time proportional to the number of
- * nonzeros in L. Computes the inverse Pinv of P if P is provided.
- * Also returns Lnz, the count of nonzeros in each column of L below
- * the diagonal (this is not required by ldl_numeric).
- * ldl_numeric: Given the pattern and numerical values of A, the Lp array,
- * the Parent array, and P and Pinv if applicable, computes the
- * pattern and numerical values of L and D.
- * ldl_lsolve: Solves Lx=b for a dense vector b.
- * ldl_dsolve: Solves Dx=b for a dense vector b.
- * ldl_ltsolve: Solves L'x=b for a dense vector b.
- * ldl_perm: Computes x=Pb for a dense vector b.
- * ldl_permt: Computes x=P'b for a dense vector b.
- * ldl_valid_perm: checks the validity of a permutation vector
- * ldl_valid_matrix: checks the validity of the sparse matrix A
- *
- * ----------------------------
- * Limitations of this package:
- * ----------------------------
- *
- * In the interest of keeping this code simple and readable, ldl_symbolic and
- * ldl_numeric assume their inputs are valid. You can check your own inputs
- * prior to calling these routines with the ldl_valid_perm and ldl_valid_matrix
- * routines. Except for the two ldl_valid_* routines, no routine checks to see
- * if the array arguments are present (non-NULL). Like all C routines, no
- * routine can determine if the arrays are long enough and don't overlap.
- *
- * The ldl_numeric does check the numerical factorization, however. It returns
- * n if the factorization is successful. If D (k,k) is zero, then k is
- * returned, and L is only partially computed.
- *
- * No pivoting to control fill-in is performed, which is often critical for
- * obtaining good performance. I recommend that you compute the permutation P
- * using AMD or SYMAMD (approximate minimum degree ordering routines), or an
- * appropriate graph-partitioning based ordering. See the ldldemo.m routine for
- * an example in MATLAB, and the ldlmain.c stand-alone C program for examples of
- * how to find P. Routines for manipulating compressed-column matrices are
- * available in UMFPACK. AMD, SYMAMD, UMFPACK, and this LDL package are all
- * available at http://www.cise.ufl.edu/research/sparse.
- *
- * -------------------------
- * Possible simplifications:
- * -------------------------
- *
- * These routines could be made even simpler with a few additional assumptions.
- * If no input permutation were performed, the caller would have to permute the
- * matrix first, but the computation of Pinv, and the use of P and Pinv could be
- * removed. If only the diagonal and upper triangular part of A or PAP' are
- * present, then the tests in the "if (i < k)" statement in ldl_symbolic and
- * "if (i <= k)" in ldl_numeric, are always true, and could be removed (i can
- * equal k in ldl_symbolic, but then the body of the if statement would
- * correctly do no work since Flag [k] == k). If we could assume that no
- * duplicate entries are present, then the statement Y [i] += Ax [p] could be
- * replaced with Y [i] = Ax [p] in ldl_numeric.
- *
- * --------------------------
- * Description of the method:
- * --------------------------
- *
- * LDL computes the symbolic factorization by finding the pattern of L one row
- * at a time. It does this based on the following theory. Consider a sparse
- * system Lx=b, where L, x, and b, are all sparse, and where L comes from a
- * Cholesky (or LDL') factorization. The elimination tree (etree) of L is
- * defined as follows. The parent of node j is the smallest k > j such that
- * L (k,j) is nonzero. Node j has no parent if column j of L is completely zero
- * below the diagonal (j is a root of the etree in this case). The nonzero
- * pattern of x is the union of the paths from each node i to the root, for
- * each nonzero b (i). To compute the numerical solution to Lx=b, we can
- * traverse the columns of L corresponding to nonzero values of x. This
- * traversal does not need to be done in the order 0 to n-1. It can be done in
- * any "topological" order, such that x (i) is computed before x (j) if i is a
- * descendant of j in the elimination tree.
- *
- * The row-form of the LDL' factorization is shown in the MATLAB function
- * ldlrow.m in this LDL package. Note that row k of L is found via a sparse
- * triangular solve of L (1:k-1, 1:k-1) \ A (1:k-1, k), to use 1-based MATLAB
- * notation. Thus, we can start with the nonzero pattern of the kth column of
- * A (above the diagonal), follow the paths up to the root of the etree of the
- * (k-1)-by-(k-1) leading submatrix of L, and obtain the pattern of the kth row
- * of L. Note that we only need the leading (k-1)-by-(k-1) submatrix of L to
- * do this. The elimination tree can be constructed as we go.
- *
- * The symbolic factorization does the same thing, except that it discards the
- * pattern of L as it is computed. It simply counts the number of nonzeros in
- * each column of L and then constructs the Lp index array when it's done. The
- * symbolic factorization does not need to do this in topological order.
- * Compare ldl_symbolic with the first part of ldl_numeric, and note that the
- * while (len > 0) loop is not present in ldl_symbolic.
- *
- * LDL Version 1.3, Copyright (c) 2006 by Timothy A Davis,
- * University of Florida. All Rights Reserved. Developed while on sabbatical
- * at Stanford University and Lawrence Berkeley National Laboratory. Refer to
- * the README file for the License. Available at
- * http://www.cise.ufl.edu/research/sparse.
- */
-
-#include "ldl.h"
-
-/* ========================================================================== */
-/* === ldl_symbolic ========================================================= */
-/* ========================================================================== */
-
-/* The input to this routine is a sparse matrix A, stored in column form, and
- * an optional permutation P. The output is the elimination tree
- * and the number of nonzeros in each column of L. Parent [i] = k if k is the
- * parent of i in the tree. The Parent array is required by ldl_numeric.
- * Lnz [k] gives the number of nonzeros in the kth column of L, excluding the
- * diagonal.
- *
- * One workspace vector (Flag) of size n is required.
- *
- * If P is NULL, then it is ignored. The factorization will be LDL' = A.
- * Pinv is not computed. In this case, neither P nor Pinv are required by
- * ldl_numeric.
- *
- * If P is not NULL, then it is assumed to be a valid permutation. If
- * row and column j of A is the kth pivot, the P [k] = j. The factorization
- * will be LDL' = PAP', or A (p,p) in MATLAB notation. The inverse permutation
- * Pinv is computed, where Pinv [j] = k if P [k] = j. In this case, both P
- * and Pinv are required as inputs to ldl_numeric.
- *
- * The floating-point operation count of the subsequent call to ldl_numeric
- * is not returned, but could be computed after ldl_symbolic is done. It is
- * the sum of (Lnz [k]) * (Lnz [k] + 2) for k = 0 to n-1.
- */
-
-void LDL_symbolic
-(
- LDL_int n, /* A and L are n-by-n, where n >= 0 */
- LDL_int Ap [ ], /* input of size n+1, not modified */
- LDL_int Ai [ ], /* input of size nz=Ap[n], not modified */
- LDL_int Lp [ ], /* output of size n+1, not defined on input */
- LDL_int Parent [ ], /* output of size n, not defined on input */
- LDL_int Lnz [ ], /* output of size n, not defined on input */
- LDL_int Flag [ ], /* workspace of size n, not defn. on input or output */
- LDL_int P [ ], /* optional input of size n */
- LDL_int Pinv [ ] /* optional output of size n (used if P is not NULL) */
-)
-{
- LDL_int i, k, p, kk, p2 ;
- if (P)
- {
- /* If P is present then compute Pinv, the inverse of P */
- for (k = 0 ; k < n ; k++)
- {
- Pinv [P [k]] = k ;
- }
- }
- for (k = 0 ; k < n ; k++)
- {
- /* L(k,:) pattern: all nodes reachable in etree from nz in A(0:k-1,k) */
- Parent [k] = -1 ; /* parent of k is not yet known */
- Flag [k] = k ; /* mark node k as visited */
- Lnz [k] = 0 ; /* count of nonzeros in column k of L */
- kk = (P) ? (P [k]) : (k) ; /* kth original, or permuted, column */
- p2 = Ap [kk+1] ;
- for (p = Ap [kk] ; p < p2 ; p++)
- {
- /* A (i,k) is nonzero (original or permuted A) */
- i = (Pinv) ? (Pinv [Ai [p]]) : (Ai [p]) ;
- if (i < k)
- {
- /* follow path from i to root of etree, stop at flagged node */
- for ( ; Flag [i] != k ; i = Parent [i])
- {
- /* find parent of i if not yet determined */
- if (Parent [i] == -1) Parent [i] = k ;
- Lnz [i]++ ; /* L (k,i) is nonzero */
- Flag [i] = k ; /* mark i as visited */
- }
- }
- }
- }
- /* construct Lp index array from Lnz column counts */
- Lp [0] = 0 ;
- for (k = 0 ; k < n ; k++)
- {
- Lp [k+1] = Lp [k] + Lnz [k] ;
- }
-}
-
-
-/* ========================================================================== */
-/* === ldl_numeric ========================================================== */
-/* ========================================================================== */
-
-/* Given a sparse matrix A (the arguments n, Ap, Ai, and Ax) and its symbolic
- * analysis (Lp and Parent, and optionally P and Pinv), compute the numeric LDL'
- * factorization of A or PAP'. The outputs of this routine are arguments Li,
- * Lx, and D. It also requires three size-n workspaces (Y, Pattern, and Flag).
- */
-
-LDL_int LDL_numeric /* returns n if successful, k if D (k,k) is zero */
-(
- LDL_int n, /* A and L are n-by-n, where n >= 0 */
- LDL_int Ap [ ], /* input of size n+1, not modified */
- LDL_int Ai [ ], /* input of size nz=Ap[n], not modified */
- double Ax [ ], /* input of size nz=Ap[n], not modified */
- LDL_int Lp [ ], /* input of size n+1, not modified */
- LDL_int Parent [ ], /* input of size n, not modified */
- LDL_int Lnz [ ], /* output of size n, not defn. on input */
- LDL_int Li [ ], /* output of size lnz=Lp[n], not defined on input */
- double Lx [ ], /* output of size lnz=Lp[n], not defined on input */
- double D [ ], /* output of size n, not defined on input */
- double Y [ ], /* workspace of size n, not defn. on input or output */
- LDL_int Pattern [ ],/* workspace of size n, not defn. on input or output */
- LDL_int Flag [ ], /* workspace of size n, not defn. on input or output */
- LDL_int P [ ], /* optional input of size n */
- LDL_int Pinv [ ] /* optional input of size n */
-)
-{
- double yi, l_ki ;
- LDL_int i, k, p, kk, p2, len, top ;
- for (k = 0 ; k < n ; k++)
- {
- /* compute nonzero Pattern of kth row of L, in topological order */
- Y [k] = 0.0 ; /* Y(0:k) is now all zero */
- top = n ; /* stack for pattern is empty */
- Flag [k] = k ; /* mark node k as visited */
- Lnz [k] = 0 ; /* count of nonzeros in column k of L */
- kk = (P) ? (P [k]) : (k) ; /* kth original, or permuted, column */
- p2 = Ap [kk+1] ;
- for (p = Ap [kk] ; p < p2 ; p++)
- {
- i = (Pinv) ? (Pinv [Ai [p]]) : (Ai [p]) ; /* get A(i,k) */
- if (i <= k)
- {
- Y [i] += Ax [p] ; /* scatter A(i,k) into Y (sum duplicates) */
- for (len = 0 ; Flag [i] != k ; i = Parent [i])
- {
- Pattern [len++] = i ; /* L(k,i) is nonzero */
- Flag [i] = k ; /* mark i as visited */
- }
- while (len > 0) Pattern [--top] = Pattern [--len] ;
- }
- }
- /* compute numerical values kth row of L (a sparse triangular solve) */
- D [k] = Y [k] ; /* get D(k,k) and clear Y(k) */
- Y [k] = 0.0 ;
- for ( ; top < n ; top++)
- {
- i = Pattern [top] ; /* Pattern [top:n-1] is pattern of L(:,k) */
- yi = Y [i] ; /* get and clear Y(i) */
- Y [i] = 0.0 ;
- p2 = Lp [i] + Lnz [i] ;
- for (p = Lp [i] ; p < p2 ; p++)
- {
- Y [Li [p]] -= Lx [p] * yi ;
- }
- l_ki = yi / D [i] ; /* the nonzero entry L(k,i) */
- D [k] -= l_ki * yi ;
- Li [p] = k ; /* store L(k,i) in column form of L */
- Lx [p] = l_ki ;
- Lnz [i]++ ; /* increment count of nonzeros in col i */
- }
- if (D [k] == 0.0) return (k) ; /* failure, D(k,k) is zero */
- }
- return (n) ; /* success, diagonal of D is all nonzero */
-}
-
-
-/* ========================================================================== */
-/* === ldl_lsolve: solve Lx=b ============================================== */
-/* ========================================================================== */
-
-void LDL_lsolve
-(
- LDL_int n, /* L is n-by-n, where n >= 0 */
- double X [ ], /* size n. right-hand-side on input, soln. on output */
- LDL_int Lp [ ], /* input of size n+1, not modified */
- LDL_int Li [ ], /* input of size lnz=Lp[n], not modified */
- double Lx [ ] /* input of size lnz=Lp[n], not modified */
-)
-{
- LDL_int j, p, p2 ;
- for (j = 0 ; j < n ; j++)
- {
- p2 = Lp [j+1] ;
- for (p = Lp [j] ; p < p2 ; p++)
- {
- X [Li [p]] -= Lx [p] * X [j] ;
- }
- }
-}
-
-
-/* ========================================================================== */
-/* === ldl_dsolve: solve Dx=b ============================================== */
-/* ========================================================================== */
-
-void LDL_dsolve
-(
- LDL_int n, /* D is n-by-n, where n >= 0 */
- double X [ ], /* size n. right-hand-side on input, soln. on output */
- double D [ ] /* input of size n, not modified */
-)
-{
- LDL_int j ;
- for (j = 0 ; j < n ; j++)
- {
- X [j] /= D [j] ;
- }
-}
-
-
-/* ========================================================================== */
-/* === ldl_ltsolve: solve L'x=b ============================================ */
-/* ========================================================================== */
-
-void LDL_ltsolve
-(
- LDL_int n, /* L is n-by-n, where n >= 0 */
- double X [ ], /* size n. right-hand-side on input, soln. on output */
- LDL_int Lp [ ], /* input of size n+1, not modified */
- LDL_int Li [ ], /* input of size lnz=Lp[n], not modified */
- double Lx [ ] /* input of size lnz=Lp[n], not modified */
-)
-{
- int j, p, p2 ;
- for (j = n-1 ; j >= 0 ; j--)
- {
- p2 = Lp [j+1] ;
- for (p = Lp [j] ; p < p2 ; p++)
- {
- X [j] -= Lx [p] * X [Li [p]] ;
- }
- }
-}
-
-
-/* ========================================================================== */
-/* === ldl_perm: permute a vector, x=Pb ===================================== */
-/* ========================================================================== */
-
-void LDL_perm
-(
- LDL_int n, /* size of X, B, and P */
- double X [ ], /* output of size n. */
- double B [ ], /* input of size n. */
- LDL_int P [ ] /* input permutation array of size n. */
-)
-{
- LDL_int j ;
- for (j = 0 ; j < n ; j++)
- {
- X [j] = B [P [j]] ;
- }
-}
-
-
-/* ========================================================================== */
-/* === ldl_permt: permute a vector, x=P'b =================================== */
-/* ========================================================================== */
-
-void LDL_permt
-(
- LDL_int n, /* size of X, B, and P */
- double X [ ], /* output of size n. */
- double B [ ], /* input of size n. */
- LDL_int P [ ] /* input permutation array of size n. */
-)
-{
- LDL_int j ;
- for (j = 0 ; j < n ; j++)
- {
- X [P [j]] = B [j] ;
- }
-}
-
-
-/* ========================================================================== */
-/* === ldl_valid_perm: check if a permutation vector is valid =============== */
-/* ========================================================================== */
-
-LDL_int LDL_valid_perm /* returns 1 if valid, 0 otherwise */
-(
- LDL_int n,
- LDL_int P [ ], /* input of size n, a permutation of 0:n-1 */
- LDL_int Flag [ ] /* workspace of size n */
-)
-{
- LDL_int j, k ;
- if (n < 0 || !Flag)
- {
- return (0) ; /* n must be >= 0, and Flag must be present */
- }
- if (!P)
- {
- return (1) ; /* If NULL, P is assumed to be the identity perm. */
- }
- for (j = 0 ; j < n ; j++)
- {
- Flag [j] = 0 ; /* clear the Flag array */
- }
- for (k = 0 ; k < n ; k++)
- {
- j = P [k] ;
- if (j < 0 || j >= n || Flag [j] != 0)
- {
- return (0) ; /* P is not valid */
- }
- Flag [j] = 1 ;
- }
- return (1) ; /* P is valid */
-}
-
-
-/* ========================================================================== */
-/* === ldl_valid_matrix: check if a sparse matrix is valid ================== */
-/* ========================================================================== */
-
-/* This routine checks to see if a sparse matrix A is valid for input to
- * ldl_symbolic and ldl_numeric. It returns 1 if the matrix is valid, 0
- * otherwise. A is in sparse column form. The numerical values in column j
- * are stored in Ax [Ap [j] ... Ap [j+1]-1], with row indices in
- * Ai [Ap [j] ... Ap [j+1]-1]. The Ax array is not checked.
- */
-
-LDL_int LDL_valid_matrix
-(
- LDL_int n,
- LDL_int Ap [ ],
- LDL_int Ai [ ]
-)
-{
- LDL_int j, p ;
- if (n < 0 || !Ap || !Ai || Ap [0] != 0)
- {
- return (0) ; /* n must be >= 0, and Ap and Ai must be present */
- }
- for (j = 0 ; j < n ; j++)
- {
- if (Ap [j] > Ap [j+1])
- {
- return (0) ; /* Ap must be monotonically nondecreasing */
- }
- }
- for (p = 0 ; p < Ap [n] ; p++)
- {
- if (Ai [p] < 0 || Ai [p] >= n)
- {
- return (0) ; /* row indices must be in the range 0 to n-1 */
- }
- }
- return (1) ; /* matrix is valid */
-}
diff --git a/extern/libmv/third_party/ssba/COPYING.TXT b/extern/libmv/third_party/ssba/COPYING.TXT
deleted file mode 100644
index fc8a5de7edf..00000000000
--- a/extern/libmv/third_party/ssba/COPYING.TXT
+++ /dev/null
@@ -1,165 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-
- This version of the GNU Lesser General Public License incorporates
-the terms and conditions of version 3 of the GNU General Public
-License, supplemented by the additional permissions listed below.
-
- 0. Additional Definitions.
-
- As used herein, "this License" refers to version 3 of the GNU Lesser
-General Public License, and the "GNU GPL" refers to version 3 of the GNU
-General Public License.
-
- "The Library" refers to a covered work governed by this License,
-other than an Application or a Combined Work as defined below.
-
- An "Application" is any work that makes use of an interface provided
-by the Library, but which is not otherwise based on the Library.
-Defining a subclass of a class defined by the Library is deemed a mode
-of using an interface provided by the Library.
-
- A "Combined Work" is a work produced by combining or linking an
-Application with the Library. The particular version of the Library
-with which the Combined Work was made is also called the "Linked
-Version".
-
- The "Minimal Corresponding Source" for a Combined Work means the
-Corresponding Source for the Combined Work, excluding any source code
-for portions of the Combined Work that, considered in isolation, are
-based on the Application, and not on the Linked Version.
-
- The "Corresponding Application Code" for a Combined Work means the
-object code and/or source code for the Application, including any data
-and utility programs needed for reproducing the Combined Work from the
-Application, but excluding the System Libraries of the Combined Work.
-
- 1. Exception to Section 3 of the GNU GPL.
-
- You may convey a covered work under sections 3 and 4 of this License
-without being bound by section 3 of the GNU GPL.
-
- 2. Conveying Modified Versions.
-
- If you modify a copy of the Library, and, in your modifications, a
-facility refers to a function or data to be supplied by an Application
-that uses the facility (other than as an argument passed when the
-facility is invoked), then you may convey a copy of the modified
-version:
-
- a) under this License, provided that you make a good faith effort to
- ensure that, in the event an Application does not supply the
- function or data, the facility still operates, and performs
- whatever part of its purpose remains meaningful, or
-
- b) under the GNU GPL, with none of the additional permissions of
- this License applicable to that copy.
-
- 3. Object Code Incorporating Material from Library Header Files.
-
- The object code form of an Application may incorporate material from
-a header file that is part of the Library. You may convey such object
-code under terms of your choice, provided that, if the incorporated
-material is not limited to numerical parameters, data structure
-layouts and accessors, or small macros, inline functions and templates
-(ten or fewer lines in length), you do both of the following:
-
- a) Give prominent notice with each copy of the object code that the
- Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the object code with a copy of the GNU GPL and this license
- document.
-
- 4. Combined Works.
-
- You may convey a Combined Work under terms of your choice that,
-taken together, effectively do not restrict modification of the
-portions of the Library contained in the Combined Work and reverse
-engineering for debugging such modifications, if you also do each of
-the following:
-
- a) Give prominent notice with each copy of the Combined Work that
- the Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the Combined Work with a copy of the GNU GPL and this license
- document.
-
- c) For a Combined Work that displays copyright notices during
- execution, include the copyright notice for the Library among
- these notices, as well as a reference directing the user to the
- copies of the GNU GPL and this license document.
-
- d) Do one of the following:
-
- 0) Convey the Minimal Corresponding Source under the terms of this
- License, and the Corresponding Application Code in a form
- suitable for, and under terms that permit, the user to
- recombine or relink the Application with a modified version of
- the Linked Version to produce a modified Combined Work, in the
- manner specified by section 6 of the GNU GPL for conveying
- Corresponding Source.
-
- 1) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (a) uses at run time
- a copy of the Library already present on the user's computer
- system, and (b) will operate properly with a modified version
- of the Library that is interface-compatible with the Linked
- Version.
-
- e) Provide Installation Information, but only if you would otherwise
- be required to provide such information under section 6 of the
- GNU GPL, and only to the extent that such information is
- necessary to install and execute a modified version of the
- Combined Work produced by recombining or relinking the
- Application with a modified version of the Linked Version. (If
- you use option 4d0, the Installation Information must accompany
- the Minimal Corresponding Source and Corresponding Application
- Code. If you use option 4d1, you must provide the Installation
- Information in the manner specified by section 6 of the GNU GPL
- for conveying Corresponding Source.)
-
- 5. Combined Libraries.
-
- You may place library facilities that are a work based on the
-Library side by side in a single library together with other library
-facilities that are not Applications and are not covered by this
-License, and convey such a combined library under terms of your
-choice, if you do both of the following:
-
- a) Accompany the combined library with a copy of the same work based
- on the Library, uncombined with any other library facilities,
- conveyed under the terms of this License.
-
- b) Give prominent notice with the combined library that part of it
- is a work based on the Library, and explaining where to find the
- accompanying uncombined form of the same work.
-
- 6. Revised Versions of the GNU Lesser General Public License.
-
- The Free Software Foundation may publish revised and/or new versions
-of the GNU Lesser General Public License from time to time. Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Library as you received it specifies that a certain numbered version
-of the GNU Lesser General Public License "or any later version"
-applies to it, you have the option of following the terms and
-conditions either of that published version or of any later version
-published by the Free Software Foundation. If the Library as you
-received it does not specify a version number of the GNU Lesser
-General Public License, you may choose any version of the GNU Lesser
-General Public License ever published by the Free Software Foundation.
-
- If the Library as you received it specifies that a proxy can decide
-whether future versions of the GNU Lesser General Public License shall
-apply, that proxy's public statement of acceptance of any version is
-permanent authorization for you to choose that version for the
-Library.
diff --git a/extern/libmv/third_party/ssba/Geometry/v3d_cameramatrix.h b/extern/libmv/third_party/ssba/Geometry/v3d_cameramatrix.h
deleted file mode 100644
index 448ae9714e5..00000000000
--- a/extern/libmv/third_party/ssba/Geometry/v3d_cameramatrix.h
+++ /dev/null
@@ -1,204 +0,0 @@
-// -*- C++ -*-
-/*
-Copyright (c) 2008 University of North Carolina at Chapel Hill
-
-This file is part of SSBA (Simple Sparse Bundle Adjustment).
-
-SSBA 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 3 of the License, or (at your option) any
-later version.
-
-SSBA is distributed in the hope that 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.
-
-You should have received a copy of the GNU Lesser General Public License along
-with SSBA. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef V3D_CAMERA_MATRIX_H
-#define V3D_CAMERA_MATRIX_H
-
-#include "Math/v3d_linear.h"
-#include "Geometry/v3d_distortion.h"
-
-namespace V3D
-{
-
- struct CameraMatrix
- {
- CameraMatrix()
- {
- makeIdentityMatrix(_K);
- makeIdentityMatrix(_R);
- makeZeroVector(_T);
- this->updateCachedValues(true, true);
- }
-
- CameraMatrix(double f, double cx, double cy)
- {
- makeIdentityMatrix(_K);
- _K[0][0] = f;
- _K[1][1] = f;
- _K[0][2] = cx;
- _K[1][2] = cy;
- makeIdentityMatrix(_R);
- makeZeroVector(_T);
- this->updateCachedValues(true, true);
- }
-
- CameraMatrix(Matrix3x3d const& K,
- Matrix3x3d const& R,
- Vector3d const& T)
- : _K(K), _R(R), _T(T)
- {
- this->updateCachedValues(true, true);
- }
-
- void setIntrinsic(Matrix3x3d const& K) { _K = K; this->updateCachedValues(true, false); }
- void setRotation(Matrix3x3d const& R) { _R = R; this->updateCachedValues(false, true); }
- void setTranslation(Vector3d const& T) { _T = T; this->updateCachedValues(false, true); }
-
- template <typename Mat>
- void setOrientation(Mat const& RT)
- {
- _R[0][0] = RT[0][0]; _R[0][1] = RT[0][1]; _R[0][2] = RT[0][2];
- _R[1][0] = RT[1][0]; _R[1][1] = RT[1][1]; _R[1][2] = RT[1][2];
- _R[2][0] = RT[2][0]; _R[2][1] = RT[2][1]; _R[2][2] = RT[2][2];
- _T[0] = RT[0][3]; _T[1] = RT[1][3]; _T[2] = RT[2][3];
- this->updateCachedValues(false, true);
- }
-
- Matrix3x3d const& getIntrinsic() const { return _K; }
- Matrix3x3d const& getRotation() const { return _R; }
- Vector3d const& getTranslation() const { return _T; }
-
- Matrix3x4d getOrientation() const
- {
- Matrix3x4d RT;
- RT[0][0] = _R[0][0]; RT[0][1] = _R[0][1]; RT[0][2] = _R[0][2];
- RT[1][0] = _R[1][0]; RT[1][1] = _R[1][1]; RT[1][2] = _R[1][2];
- RT[2][0] = _R[2][0]; RT[2][1] = _R[2][1]; RT[2][2] = _R[2][2];
- RT[0][3] = _T[0]; RT[1][3] = _T[1]; RT[2][3] = _T[2];
- return RT;
- }
-
- Matrix3x4d getProjection() const
- {
- Matrix3x4d const RT = this->getOrientation();
- return _K * RT;
- }
-
- double getFocalLength() const { return _K[0][0]; }
- double getAspectRatio() const { return _K[1][1] / _K[0][0]; }
-
- Vector2d getPrincipalPoint() const
- {
- Vector2d pp;
- pp[0] = _K[0][2];
- pp[1] = _K[1][2];
- return pp;
- }
-
- Vector2d projectPoint(Vector3d const& X) const
- {
- Vector3d q = _K*(_R*X + _T);
- Vector2d res;
- res[0] = q[0]/q[2]; res[1] = q[1]/q[2];
- return res;
- }
-
- template <typename Distortion>
- Vector2d projectPoint(Distortion const& distortion, Vector3d const& X) const
- {
- Vector3d XX = _R*X + _T;
- Vector2d p;
- p[0] = XX[0] / XX[2];
- p[1] = XX[1] / XX[2];
- p = distortion(p);
-
- Vector2d res;
- res[0] = _K[0][0] * p[0] + _K[0][1] * p[1] + _K[0][2];
- res[1] = _K[1][1] * p[1] + _K[1][2];
- return res;
- }
-
- Vector3d unprojectPixel(Vector2d const &p, double depth = 1) const
- {
- Vector3d pp;
- pp[0] = p[0]; pp[1] = p[1]; pp[2] = 1.0;
- Vector3d ray = _invK * pp;
- ray[0] *= depth/ray[2];
- ray[1] *= depth/ray[2];
- ray[2] = depth;
- ray = _Rt * ray;
- return _center + ray;
- }
-
- Vector3d transformPointIntoCameraSpace(Vector3d const& p) const
- {
- return _R*p + _T;
- }
-
- Vector3d transformPointFromCameraSpace(Vector3d const& p) const
- {
- return _Rt*(p-_T);
- }
-
- Vector3d transformDirectionFromCameraSpace(Vector3d const& dir) const
- {
- return _Rt*dir;
- }
-
- Vector3d const& cameraCenter() const
- {
- return _center;
- }
-
- Vector3d opticalAxis() const
- {
- return this->transformDirectionFromCameraSpace(makeVector3(0.0, 0.0, 1.0));
- }
-
- Vector3d upVector() const
- {
- return this->transformDirectionFromCameraSpace(makeVector3(0.0, 1.0, 0.0));
- }
-
- Vector3d rightVector() const
- {
- return this->transformDirectionFromCameraSpace(makeVector3(1.0, 0.0, 0.0));
- }
-
- Vector3d getRay(Vector2d const& p) const
- {
- Vector3d pp = makeVector3(p[0], p[1], 1.0);
- Vector3d ray = _invK * pp;
- ray = _Rt * ray;
- normalizeVector(ray);
- return ray;
- }
-
- protected:
- void updateCachedValues(bool intrinsic, bool orientation)
- {
- if (intrinsic) _invK = invertedMatrix(_K);
-
- if (orientation)
- {
- makeTransposedMatrix(_R, _Rt);
- _center = _Rt * (-1.0 * _T);
- }
- }
-
- Matrix3x3d _K, _R;
- Vector3d _T;
- Matrix3x3d _invK, _Rt;
- Vector3d _center;
- }; // end struct CameraMatrix
-
-} // end namespace V3D
-
-#endif
diff --git a/extern/libmv/third_party/ssba/Geometry/v3d_distortion.h b/extern/libmv/third_party/ssba/Geometry/v3d_distortion.h
deleted file mode 100644
index d0816558314..00000000000
--- a/extern/libmv/third_party/ssba/Geometry/v3d_distortion.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// -*- C++ -*-
-/*
-Copyright (c) 2008 University of North Carolina at Chapel Hill
-
-This file is part of SSBA (Simple Sparse Bundle Adjustment).
-
-SSBA 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 3 of the License, or (at your option) any
-later version.
-
-SSBA is distributed in the hope that 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.
-
-You should have received a copy of the GNU Lesser General Public License along
-with SSBA. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef V3D_DISTORTION_H
-#define V3D_DISTORTION_H
-
-#include "Math/v3d_linear.h"
-#include "Math/v3d_linear_utils.h"
-
-namespace V3D
-{
-
- struct StdDistortionFunction
- {
- double k1, k2, p1, p2;
-
- StdDistortionFunction()
- : k1(0), k2(0), p1(0), p2(0)
- { }
-
- Vector2d operator()(Vector2d const& xu) const
- {
- double const r2 = xu[0]*xu[0] + xu[1]*xu[1];
- double const r4 = r2*r2;
- double const kr = 1 + k1*r2 + k2*r4;
-
- Vector2d xd;
- xd[0] = kr * xu[0] + 2*p1*xu[0]*xu[1] + p2*(r2 + 2*xu[0]*xu[0]);
- xd[1] = kr * xu[1] + 2*p2*xu[0]*xu[1] + p1*(r2 + 2*xu[1]*xu[1]);
- return xd;
- }
-
- Matrix2x2d derivativeWrtRadialParameters(Vector2d const& xu) const
- {
- double const r2 = xu[0]*xu[0] + xu[1]*xu[1];
- double const r4 = r2*r2;
- //double const kr = 1 + k1*r2 + k2*r4;
-
- Matrix2x2d deriv;
-
- deriv[0][0] = xu[0] * r2; // d xd/d k1
- deriv[0][1] = xu[0] * r4; // d xd/d k2
- deriv[1][0] = xu[1] * r2; // d yd/d k1
- deriv[1][1] = xu[1] * r4; // d yd/d k2
- return deriv;
- }
-
- Matrix2x2d derivativeWrtTangentialParameters(Vector2d const& xu) const
- {
- double const r2 = xu[0]*xu[0] + xu[1]*xu[1];
- //double const r4 = r2*r2;
- //double const kr = 1 + k1*r2 + k2*r4;
-
- Matrix2x2d deriv;
- deriv[0][0] = 2*xu[0]*xu[1]; // d xd/d p1
- deriv[0][1] = r2 + 2*xu[0]*xu[0]; // d xd/d p2
- deriv[1][0] = r2 + 2*xu[1]*xu[1]; // d yd/d p1
- deriv[1][1] = deriv[0][0]; // d yd/d p2
- return deriv;
- }
-
- Matrix2x2d derivativeWrtUndistortedPoint(Vector2d const& xu) const
- {
- double const r2 = xu[0]*xu[0] + xu[1]*xu[1];
- double const r4 = r2*r2;
- double const kr = 1 + k1*r2 + k2*r4;
- double const dkr = 2*k1 + 4*k2*r2;
-
- Matrix2x2d deriv;
- deriv[0][0] = kr + xu[0] * xu[0] * dkr + 2*p1*xu[1] + 6*p2*xu[0]; // d xd/d xu
- deriv[0][1] = xu[0] * xu[1] * dkr + 2*p1*xu[0] + 2*p2*xu[1]; // d xd/d yu
- deriv[1][0] = deriv[0][1]; // d yd/d xu
- deriv[1][1] = kr + xu[1] * xu[1] * dkr + 6*p1*xu[1] + 2*p2*xu[0]; // d yd/d yu
- return deriv;
- }
- }; // end struct StdDistortionFunction
-
-} // end namespace V3D
-
-#endif
diff --git a/extern/libmv/third_party/ssba/Geometry/v3d_metricbundle.cpp b/extern/libmv/third_party/ssba/Geometry/v3d_metricbundle.cpp
deleted file mode 100644
index 7eb2dfac5d9..00000000000
--- a/extern/libmv/third_party/ssba/Geometry/v3d_metricbundle.cpp
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
-Copyright (c) 2008 University of North Carolina at Chapel Hill
-
-This file is part of SSBA (Simple Sparse Bundle Adjustment).
-
-SSBA 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 3 of the License, or (at your option) any
-later version.
-
-SSBA is distributed in the hope that 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.
-
-You should have received a copy of the GNU Lesser General Public License along
-with SSBA. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "Geometry/v3d_metricbundle.h"
-
-#if defined(V3DLIB_ENABLE_SUITESPARSE)
-
-namespace
-{
-
- typedef V3D::InlineMatrix<double, 2, 4> Matrix2x4d;
- typedef V3D::InlineMatrix<double, 4, 2> Matrix4x2d;
- typedef V3D::InlineMatrix<double, 2, 6> Matrix2x6d;
-
-} // end namespace <>
-
-namespace V3D
-{
-
- void
- MetricBundleOptimizerBase::updateParametersA(VectorArray<double> const& deltaAi)
- {
- Vector3d T, omega;
- Matrix3x3d R0, dR;
-
- for (int i = _nNonvaryingA; i < _nParametersA; ++i)
- {
- T = _cams[i].getTranslation();
- T[0] += deltaAi[i][0];
- T[1] += deltaAi[i][1];
- T[2] += deltaAi[i][2];
- _cams[i].setTranslation(T);
-
- // Create incremental rotation using Rodriguez formula.
- R0 = _cams[i].getRotation();
- omega[0] = deltaAi[i][3];
- omega[1] = deltaAi[i][4];
- omega[2] = deltaAi[i][5];
- createRotationMatrixRodriguez(omega, dR);
- _cams[i].setRotation(dR * R0);
- } // end for (i)
- } // end MetricBundleOptimizerBase::updateParametersA()
-
- void
- MetricBundleOptimizerBase::updateParametersB(VectorArray<double> const& deltaBj)
- {
- for (int j = _nNonvaryingB; j < _nParametersB; ++j)
- {
- _Xs[j][0] += deltaBj[j][0];
- _Xs[j][1] += deltaBj[j][1];
- _Xs[j][2] += deltaBj[j][2];
- }
- } // end MetricBundleOptimizerBase::updateParametersB()
-
- void
- MetricBundleOptimizerBase::poseDerivatives(int i, int j, Vector3d& XX,
- Matrix3x6d& d_dRT, Matrix3x3d& d_dX) const
- {
- XX = _cams[i].transformPointIntoCameraSpace(_Xs[j]);
-
- // See Frank Dellaerts bundle adjustment tutorial.
- // d(dR * R0 * X + t)/d omega = -[R0 * X]_x
- Matrix3x3d J;
- makeCrossProductMatrix(XX - _cams[i].getTranslation(), J);
- scaleMatrixIP(-1.0, J);
-
- // Now the transformation from world coords into camera space is xx = Rx + T
- // Hence the derivative of x wrt. T is just the identity matrix.
- makeIdentityMatrix(d_dRT);
- copyMatrixSlice(J, 0, 0, 3, 3, d_dRT, 0, 3);
-
- // The derivative of Rx+T wrt x is just R.
- copyMatrix(_cams[i].getRotation(), d_dX);
- } // end MetricBundleOptimizerBase::poseDerivatives()
-
-
-//----------------------------------------------------------------------
-
- void
- StdMetricBundleOptimizer::fillJacobians(Matrix<double>& Ak,
- Matrix<double>& Bk,
- Matrix<double>& Ck,
- int i, int j, int k)
- {
- Vector3d XX;
- Matrix3x6d d_dRT;
- Matrix3x3d d_dX;
- this->poseDerivatives(i, j, XX, d_dRT, d_dX);
-
- double const f = _cams[i].getFocalLength();
- double const ar = _cams[i].getAspectRatio();
-
- Matrix2x3d dp_dX;
- double const bx = f / (XX[2] * XX[2]);
- double const by = ar * bx;
- dp_dX[0][0] = bx * XX[2]; dp_dX[0][1] = 0; dp_dX[0][2] = -bx * XX[0];
- dp_dX[1][0] = 0; dp_dX[1][1] = by * XX[2]; dp_dX[1][2] = -by * XX[1];
-
- multiply_A_B(dp_dX, d_dRT, Ak);
- multiply_A_B(dp_dX, d_dX, Bk);
- } // end StdMetricBundleOptimizer::fillJacobians()
-
- //----------------------------------------------------------------------
-
- void
- CommonInternalsMetricBundleOptimizer::fillJacobians(Matrix<double>& Ak,
- Matrix<double>& Bk,
- Matrix<double>& Ck,
- int i, int j, int k)
- {
- double const focalLength = _K[0][0];
-
- Vector3d XX;
- Matrix3x6d dXX_dRT;
- Matrix3x3d dXX_dX;
- this->poseDerivatives(i, j, XX, dXX_dRT, dXX_dX);
-
- Vector2d xu; // undistorted image point
- xu[0] = XX[0] / XX[2];
- xu[1] = XX[1] / XX[2];
-
- Vector2d const xd = _distortion(xu); // distorted image point
-
- Matrix2x2d dp_dxd;
- dp_dxd[0][0] = focalLength; dp_dxd[0][1] = 0;
- dp_dxd[1][0] = 0; dp_dxd[1][1] = _cachedAspectRatio * focalLength;
-
- {
- // First, lets do the derivative wrt the structure and motion parameters.
- Matrix2x3d dxu_dXX;
- dxu_dXX[0][0] = 1.0f / XX[2]; dxu_dXX[0][1] = 0; dxu_dXX[0][2] = -XX[0]/(XX[2]*XX[2]);
- dxu_dXX[1][0] = 0; dxu_dXX[1][1] = 1.0f / XX[2]; dxu_dXX[1][2] = -XX[1]/(XX[2]*XX[2]);
-
- Matrix2x2d dxd_dxu = _distortion.derivativeWrtUndistortedPoint(xu);
-
- Matrix2x2d dp_dxu = dp_dxd * dxd_dxu;
- Matrix2x3d dp_dXX = dp_dxu * dxu_dXX;
-
- multiply_A_B(dp_dXX, dXX_dRT, Ak);
- multiply_A_B(dp_dXX, dXX_dX, Bk);
- } // end scope
-
- switch (_mode)
- {
- case FULL_BUNDLE_FOCAL_AND_RADIAL_K1:
- {
- // Focal length.
- Ck[0][0] = xd[0];
- Ck[1][0] = xd[1];
-
- // For radial, k1 only.
- Matrix2x2d dxd_dk1k2 = _distortion.derivativeWrtRadialParameters(xu);
- Matrix2x2d d_dk1k2 = dp_dxd * dxd_dk1k2;
- Ck[0][1] = d_dk1k2[0][0];
- Ck[1][1] = d_dk1k2[1][0];
- break;
- }
- case FULL_BUNDLE_FOCAL_AND_RADIAL:
- {
- // Focal length.
- Ck[0][0] = xd[0];
- Ck[1][0] = xd[1];
-
- // Radial k1 and k2.
- Matrix2x2d dxd_dk1k2 = _distortion.derivativeWrtRadialParameters(xu);
- Matrix2x2d d_dk1k2 = dp_dxd * dxd_dk1k2;
- copyMatrixSlice(d_dk1k2, 0, 0, 2, 2, Ck, 0, 1);
- break;
- }
- case FULL_BUNDLE_RADIAL_TANGENTIAL:
- {
- Matrix2x2d dxd_dp1p2 = _distortion.derivativeWrtTangentialParameters(xu);
- Matrix2x2d d_dp1p2 = dp_dxd * dxd_dp1p2;
- copyMatrixSlice(d_dp1p2, 0, 0, 2, 2, Ck, 0, 5);
- // No break here!
- }
- case FULL_BUNDLE_RADIAL:
- {
- Matrix2x2d dxd_dk1k2 = _distortion.derivativeWrtRadialParameters(xu);
- Matrix2x2d d_dk1k2 = dp_dxd * dxd_dk1k2;
- copyMatrixSlice(d_dk1k2, 0, 0, 2, 2, Ck, 0, 3);
- // No break here!
- }
- case FULL_BUNDLE_FOCAL_LENGTH_PP:
- {
- Ck[0][1] = 1; Ck[0][2] = 0;
- Ck[1][1] = 0; Ck[1][2] = 1;
- // No break here!
- }
- case FULL_BUNDLE_FOCAL_LENGTH:
- {
- Ck[0][0] = xd[0];
- Ck[1][0] = xd[1];
- }
- case FULL_BUNDLE_METRIC:
- {
- }
- } // end switch
- } // end CommonInternalsMetricBundleOptimizer::fillJacobians()
-
- void
- CommonInternalsMetricBundleOptimizer::updateParametersC(Vector<double> const& deltaC)
- {
- switch (_mode)
- {
- case FULL_BUNDLE_FOCAL_AND_RADIAL_K1:
- {
- _K[0][0] += deltaC[0];
- _K[1][1] = _cachedAspectRatio * _K[0][0];
- _distortion.k1 += deltaC[1];
- break;
- }
- case FULL_BUNDLE_FOCAL_AND_RADIAL:
- {
- _K[0][0] += deltaC[0];
- _K[1][1] = _cachedAspectRatio * _K[0][0];
- _distortion.k1 += deltaC[1];
- _distortion.k2 += deltaC[2];
- break;
- }
- case FULL_BUNDLE_RADIAL_TANGENTIAL:
- {
- _distortion.p1 += deltaC[5];
- _distortion.p2 += deltaC[6];
- // No break here!
- }
- case FULL_BUNDLE_RADIAL:
- {
- _distortion.k1 += deltaC[3];
- _distortion.k2 += deltaC[4];
- // No break here!
- }
- case FULL_BUNDLE_FOCAL_LENGTH_PP:
- {
- _K[0][2] += deltaC[1];
- _K[1][2] += deltaC[2];
- // No break here!
- }
- case FULL_BUNDLE_FOCAL_LENGTH:
- {
- _K[0][0] += deltaC[0];
- _K[1][1] = _cachedAspectRatio * _K[0][0];
- }
- case FULL_BUNDLE_METRIC:
- {
- }
- } // end switch
- } // end CommonInternalsMetricBundleOptimizer::updateParametersC()
-
- //----------------------------------------------------------------------
-
- void
- VaryingInternalsMetricBundleOptimizer::fillJacobians(Matrix<double>& Ak,
- Matrix<double>& Bk,
- Matrix<double>& Ck,
- int i, int j, int k)
- {
- Vector3d XX;
- Matrix3x6d dXX_dRT;
- Matrix3x3d dXX_dX;
- this->poseDerivatives(i, j, XX, dXX_dRT, dXX_dX);
-
- Vector2d xu; // undistorted image point
- xu[0] = XX[0] / XX[2];
- xu[1] = XX[1] / XX[2];
-
- Vector2d const xd = _distortions[i](xu); // distorted image point
-
- double const focalLength = _cams[i].getFocalLength();
- double const aspectRatio = _cams[i].getAspectRatio();
-
- Matrix2x2d dp_dxd;
- dp_dxd[0][0] = focalLength; dp_dxd[0][1] = 0;
- dp_dxd[1][0] = 0; dp_dxd[1][1] = aspectRatio * focalLength;
-
- {
- // First, lets do the derivative wrt the structure and motion parameters.
- Matrix2x3d dxu_dXX;
- dxu_dXX[0][0] = 1.0f / XX[2]; dxu_dXX[0][1] = 0; dxu_dXX[0][2] = -XX[0]/(XX[2]*XX[2]);
- dxu_dXX[1][0] = 0; dxu_dXX[1][1] = 1.0f / XX[2]; dxu_dXX[1][2] = -XX[1]/(XX[2]*XX[2]);
-
- Matrix2x2d dxd_dxu = _distortions[i].derivativeWrtUndistortedPoint(xu);
-
- Matrix2x2d dp_dxu = dp_dxd * dxd_dxu;
- Matrix2x3d dp_dXX = dp_dxu * dxu_dXX;
-
- Matrix2x6d dp_dRT;
-
- multiply_A_B(dp_dXX, dXX_dRT, dp_dRT);
- copyMatrixSlice(dp_dRT, 0, 0, 2, 6, Ak, 0, 0);
- multiply_A_B(dp_dXX, dXX_dX, Bk);
- } // end scope
-
- switch (_mode)
- {
- case FULL_BUNDLE_RADIAL_TANGENTIAL:
- {
- Matrix2x2d dxd_dp1p2 = _distortions[i].derivativeWrtTangentialParameters(xu);
- Matrix2x2d d_dp1p2 = dp_dxd * dxd_dp1p2;
- copyMatrixSlice(d_dp1p2, 0, 0, 2, 2, Ak, 0, 11);
- // No break here!
- }
- case FULL_BUNDLE_RADIAL:
- {
- Matrix2x2d dxd_dk1k2 = _distortions[i].derivativeWrtRadialParameters(xu);
- Matrix2x2d d_dk1k2 = dp_dxd * dxd_dk1k2;
- copyMatrixSlice(d_dk1k2, 0, 0, 2, 2, Ak, 0, 9);
- // No break here!
- }
- case FULL_BUNDLE_FOCAL_LENGTH_PP:
- {
- Ak[0][7] = 1; Ak[0][8] = 0;
- Ak[1][7] = 0; Ak[1][8] = 1;
- // No break here!
- }
- case FULL_BUNDLE_FOCAL_LENGTH:
- {
- Ak[0][6] = xd[0];
- Ak[1][6] = xd[1];
- }
- case FULL_BUNDLE_METRIC:
- {
- }
- } // end switch
- } // end VaryingInternalsMetricBundleOptimizer::fillJacobians()
-
- void
- VaryingInternalsMetricBundleOptimizer::updateParametersA(VectorArray<double> const& deltaAi)
- {
- Vector3d T, omega;
- Matrix3x3d R0, dR, K;
-
- for (int i = _nNonvaryingA; i < _nParametersA; ++i)
- {
- Vector<double> const& deltaA = deltaAi[i];
-
- T = _cams[i].getTranslation();
- T[0] += deltaA[0];
- T[1] += deltaA[1];
- T[2] += deltaA[2];
- _cams[i].setTranslation(T);
-
- // Create incremental rotation using Rodriguez formula.
- R0 = _cams[i].getRotation();
- omega[0] = deltaA[3];
- omega[1] = deltaA[4];
- omega[2] = deltaA[5];
- createRotationMatrixRodriguez(omega, dR);
- _cams[i].setRotation(dR * R0);
-
- K = _cams[i].getIntrinsic();
-
- switch (_mode)
- {
- case FULL_BUNDLE_RADIAL_TANGENTIAL:
- {
- _distortions[i].p1 += deltaA[11];
- _distortions[i].p2 += deltaA[12];
- // No break here!
- }
- case FULL_BUNDLE_RADIAL:
- {
- _distortions[i].k1 += deltaA[9];
- _distortions[i].k2 += deltaA[10];
- // No break here!
- }
- case FULL_BUNDLE_FOCAL_LENGTH_PP:
- {
- K[0][2] += deltaA[7];
- K[1][2] += deltaA[8];
- // No break here!
- }
- case FULL_BUNDLE_FOCAL_LENGTH:
- {
- double const ar = K[1][1] / K[0][0];
- K[0][0] += deltaA[6];
- K[1][1] = ar * K[0][0];
- }
- case FULL_BUNDLE_METRIC:
- {
- }
- } // end switch
- _cams[i].setIntrinsic(K);
- } // end for (i)
- } // end VaryingInternalsMetricBundleOptimizer::updateParametersC()
-
-} // end namespace V3D
-
-#endif // defined(V3DLIB_ENABLE_SUITESPARSE)
diff --git a/extern/libmv/third_party/ssba/Geometry/v3d_metricbundle.h b/extern/libmv/third_party/ssba/Geometry/v3d_metricbundle.h
deleted file mode 100644
index 339e174ed9e..00000000000
--- a/extern/libmv/third_party/ssba/Geometry/v3d_metricbundle.h
+++ /dev/null
@@ -1,352 +0,0 @@
-// -*- C++ -*-
-/*
-Copyright (c) 2008 University of North Carolina at Chapel Hill
-
-This file is part of SSBA (Simple Sparse Bundle Adjustment).
-
-SSBA 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 3 of the License, or (at your option) any
-later version.
-
-SSBA is distributed in the hope that 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.
-
-You should have received a copy of the GNU Lesser General Public License along
-with SSBA. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef V3D_METRICBUNDLE_H
-#define V3D_METRICBUNDLE_H
-
-# if defined(V3DLIB_ENABLE_SUITESPARSE)
-
-#include "Math/v3d_optimization.h"
-#include "Math/v3d_linear.h"
-#include "Math/v3d_linear_utils.h"
-#include "Geometry/v3d_cameramatrix.h"
-#include "Geometry/v3d_distortion.h"
-
-namespace V3D
-{
-
- // This structure provides some helper functions common to all metric BAs
- struct MetricBundleOptimizerBase : public SparseLevenbergOptimizer
- {
- typedef SparseLevenbergOptimizer Base;
-
- MetricBundleOptimizerBase(double inlierThreshold,
- vector<CameraMatrix>& cams,
- vector<Vector3d >& Xs,
- vector<Vector2d > const& measurements,
- vector<int> const& corrspondingView,
- vector<int> const& corrspondingPoint,
- int nAddParamsA, int nParamsC)
- : SparseLevenbergOptimizer(2, cams.size(), 6+nAddParamsA, Xs.size(), 3, nParamsC,
- corrspondingView, corrspondingPoint),
- _cams(cams), _Xs(Xs), _measurements(measurements),
- _savedTranslations(cams.size()), _savedRotations(cams.size()),
- _savedXs(Xs.size()),
- _inlierThreshold(inlierThreshold), _cachedParamLength(0.0)
- {
- // Since we assume that BA does not alter the inputs too much,
- // we compute the overall length of the parameter vector in advance
- // and return that value as the result of getParameterLength().
- for (int i = _nNonvaryingA; i < _nParametersA; ++i)
- {
- _cachedParamLength += sqrNorm_L2(_cams[i].getTranslation());
- _cachedParamLength += 3.0; // Assume eye(3) for R.
- }
- for (int j = _nNonvaryingB; j < _nParametersB; ++j)
- _cachedParamLength += sqrNorm_L2(_Xs[j]);
-
- _cachedParamLength = sqrt(_cachedParamLength);
- }
-
- // Huber robust cost function.
- virtual void fillWeights(VectorArray<double> const& residual, Vector<double>& w)
- {
- for (unsigned int k = 0; k < w.size(); ++k)
- {
- Vector<double> const& r = residual[k];
- double const e = norm_L2(r);
- w[k] = (e < _inlierThreshold) ? 1.0 : sqrt(_inlierThreshold / e);
- } // end for (k)
- }
-
- virtual double getParameterLength() const
- {
- return _cachedParamLength;
- }
-
- virtual void updateParametersA(VectorArray<double> const& deltaAi);
- virtual void updateParametersB(VectorArray<double> const& deltaBj);
- virtual void updateParametersC(Vector<double> const& deltaC)
- {
- (void)deltaC;
- }
-
- virtual void saveAllParameters()
- {
- for (int i = _nNonvaryingA; i < _nParametersA; ++i)
- {
- _savedTranslations[i] = _cams[i].getTranslation();
- _savedRotations[i] = _cams[i].getRotation();
- }
- _savedXs = _Xs;
- }
-
- virtual void restoreAllParameters()
- {
- for (int i = _nNonvaryingA; i < _nParametersA; ++i)
- {
- _cams[i].setTranslation(_savedTranslations[i]);
- _cams[i].setRotation(_savedRotations[i]);
- }
- _Xs = _savedXs;
- }
-
- protected:
- typedef InlineMatrix<double, 3, 6> Matrix3x6d;
-
- void poseDerivatives(int i, int j, Vector3d& XX,
- Matrix3x6d& d_dRT, Matrix3x3d& d_dX) const;
-
- vector<CameraMatrix>& _cams;
- vector<Vector3d>& _Xs;
-
- vector<Vector2d> const& _measurements;
-
- vector<Vector3d> _savedTranslations;
- vector<Matrix3x3d> _savedRotations;
- vector<Vector3d> _savedXs;
-
- double const _inlierThreshold;
- double _cachedParamLength;
- }; // end struct MetricBundleOptimizerBase
-
- struct StdMetricBundleOptimizer : public MetricBundleOptimizerBase
- {
- typedef MetricBundleOptimizerBase Base;
-
- StdMetricBundleOptimizer(double inlierThreshold,
- vector<CameraMatrix>& cams,
- vector<Vector3d >& Xs,
- vector<Vector2d > const& measurements,
- vector<int> const& corrspondingView,
- vector<int> const& corrspondingPoint)
- : MetricBundleOptimizerBase(inlierThreshold, cams, Xs, measurements,
- corrspondingView, corrspondingPoint, 0, 0)
- { }
-
- virtual void evalResidual(VectorArray<double>& e)
- {
- for (unsigned int k = 0; k < e.count(); ++k)
- {
- int const i = _correspondingParamA[k];
- int const j = _correspondingParamB[k];
-
- Vector2d const q = _cams[i].projectPoint(_Xs[j]);
- e[k][0] = q[0] - _measurements[k][0];
- e[k][1] = q[1] - _measurements[k][1];
- }
- }
-
- virtual void fillJacobians(Matrix<double>& Ak, Matrix<double>& Bk, Matrix<double>& Ck,
- int i, int j, int k);
- }; // end struct StdMetricBundleOptimizer
-
-//----------------------------------------------------------------------
-
- enum
- {
- FULL_BUNDLE_METRIC = 0,
- FULL_BUNDLE_FOCAL_LENGTH = 1, // f
- FULL_BUNDLE_FOCAL_LENGTH_PP = 2, // f, cx, cy
- FULL_BUNDLE_RADIAL = 3, // f, cx, cy, k1, k2
- FULL_BUNDLE_RADIAL_TANGENTIAL = 4, // f, cx, cy, k1, k2, p1, p2
- FULL_BUNDLE_FOCAL_AND_RADIAL_K1 = 5, // f, k1
- FULL_BUNDLE_FOCAL_AND_RADIAL = 6, // f, k1, k2
- };
-
- struct CommonInternalsMetricBundleOptimizer : public MetricBundleOptimizerBase
- {
- static int globalParamDimensionFromMode(int mode)
- {
- switch (mode)
- {
- case FULL_BUNDLE_METRIC: return 0;
- case FULL_BUNDLE_FOCAL_LENGTH: return 1;
- case FULL_BUNDLE_FOCAL_LENGTH_PP: return 3;
- case FULL_BUNDLE_RADIAL: return 5;
- case FULL_BUNDLE_RADIAL_TANGENTIAL: return 7;
- case FULL_BUNDLE_FOCAL_AND_RADIAL_K1: return 2;
- case FULL_BUNDLE_FOCAL_AND_RADIAL: return 3;
- }
- return 0;
- }
-
- typedef MetricBundleOptimizerBase Base;
-
- CommonInternalsMetricBundleOptimizer(int mode,
- double inlierThreshold,
- Matrix3x3d& K,
- StdDistortionFunction& distortion,
- vector<CameraMatrix>& cams,
- vector<Vector3d >& Xs,
- vector<Vector2d > const& measurements,
- vector<int> const& corrspondingView,
- vector<int> const& corrspondingPoint)
- : MetricBundleOptimizerBase(inlierThreshold, cams, Xs, measurements,
- corrspondingView, corrspondingPoint,
- 0, globalParamDimensionFromMode(mode)),
- _mode(mode), _K(K), _distortion(distortion)
- {
- _cachedAspectRatio = K[1][1] / K[0][0];
- }
-
- Vector2d projectPoint(Vector3d const& X, int i) const
- {
- Vector3d const XX = _cams[i].transformPointIntoCameraSpace(X);
- Vector2d p;
- p[0] = XX[0] / XX[2];
- p[1] = XX[1] / XX[2];
- p = _distortion(p);
- Vector2d res;
- res[0] = _K[0][0] * p[0] + _K[0][1] * p[1] + _K[0][2];
- res[1] = _K[1][1] * p[1] + _K[1][2];
- return res;
- }
-
- virtual void evalResidual(VectorArray<double>& e)
- {
- for (unsigned int k = 0; k < e.count(); ++k)
- {
- int const i = _correspondingParamA[k];
- int const j = _correspondingParamB[k];
-
- Vector2d const q = this->projectPoint(_Xs[j], i);
- e[k][0] = q[0] - _measurements[k][0];
- e[k][1] = q[1] - _measurements[k][1];
- }
- }
-
- virtual void fillJacobians(Matrix<double>& Ak, Matrix<double>& Bk, Matrix<double>& Ck,
- int i, int j, int k);
-
- virtual void updateParametersC(Vector<double> const& deltaC);
-
- virtual void saveAllParameters()
- {
- Base::saveAllParameters();
- _savedK = _K;
- _savedDistortion = _distortion;
- }
-
- virtual void restoreAllParameters()
- {
- Base::restoreAllParameters();
- _K = _savedK;
- _distortion = _savedDistortion;
- }
-
- protected:
- int _mode;
- Matrix3x3d& _K;
- StdDistortionFunction& _distortion;
-
- Matrix3x3d _savedK;
- StdDistortionFunction _savedDistortion;
- double _cachedAspectRatio;
- }; // end struct CommonInternalsMetricBundleOptimizer
-
-//----------------------------------------------------------------------
-
- struct VaryingInternalsMetricBundleOptimizer : public MetricBundleOptimizerBase
- {
- static int extParamDimensionFromMode(int mode)
- {
- switch (mode)
- {
- case FULL_BUNDLE_METRIC: return 0;
- case FULL_BUNDLE_FOCAL_LENGTH: return 1;
- case FULL_BUNDLE_FOCAL_LENGTH_PP: return 3;
- case FULL_BUNDLE_RADIAL: return 5;
- case FULL_BUNDLE_RADIAL_TANGENTIAL: return 7;
- case FULL_BUNDLE_FOCAL_AND_RADIAL_K1: return 2;
- case FULL_BUNDLE_FOCAL_AND_RADIAL: return 3;
- }
- return 0;
- }
-
- typedef MetricBundleOptimizerBase Base;
-
- VaryingInternalsMetricBundleOptimizer(int mode,
- double inlierThreshold,
- std::vector<StdDistortionFunction>& distortions,
- vector<CameraMatrix>& cams,
- vector<Vector3d >& Xs,
- vector<Vector2d > const& measurements,
- vector<int> const& corrspondingView,
- vector<int> const& corrspondingPoint)
- : MetricBundleOptimizerBase(inlierThreshold, cams, Xs, measurements,
- corrspondingView, corrspondingPoint,
- extParamDimensionFromMode(mode), 0),
- _mode(mode), _distortions(distortions),
- _savedKs(cams.size()), _savedDistortions(cams.size())
- { }
-
- Vector2d projectPoint(Vector3d const& X, int i) const
- {
- return _cams[i].projectPoint(_distortions[i], X);
- }
-
- virtual void evalResidual(VectorArray<double>& e)
- {
- for (unsigned int k = 0; k < e.count(); ++k)
- {
- int const i = _correspondingParamA[k];
- int const j = _correspondingParamB[k];
-
- Vector2d const q = this->projectPoint(_Xs[j], i);
- e[k][0] = q[0] - _measurements[k][0];
- e[k][1] = q[1] - _measurements[k][1];
- }
- }
-
- virtual void fillJacobians(Matrix<double>& Ak, Matrix<double>& Bk, Matrix<double>& Ck,
- int i, int j, int k);
-
- virtual void updateParametersA(VectorArray<double> const& deltaAi);
-
- virtual void saveAllParameters()
- {
- Base::saveAllParameters();
- for (int i = _nNonvaryingA; i < _nParametersA; ++i)
- _savedKs[i] = _cams[i].getIntrinsic();
- std::copy(_distortions.begin(), _distortions.end(), _savedDistortions.begin());
- }
-
- virtual void restoreAllParameters()
- {
- Base::restoreAllParameters();
- for (int i = _nNonvaryingA; i < _nParametersA; ++i)
- _cams[i].setIntrinsic(_savedKs[i]);
- std::copy(_savedDistortions.begin(), _savedDistortions.end(), _distortions.begin());
- }
-
- protected:
- int _mode;
- std::vector<StdDistortionFunction>& _distortions;
-
- std::vector<Matrix3x3d> _savedKs;
- std::vector<StdDistortionFunction> _savedDistortions;
- }; // end struct VaryingInternalsMetricBundleOptimizer
-
-} // end namespace V3D
-
-# endif
-
-#endif
diff --git a/extern/libmv/third_party/ssba/Math/v3d_linear.h b/extern/libmv/third_party/ssba/Math/v3d_linear.h
deleted file mode 100644
index 7d6e898169c..00000000000
--- a/extern/libmv/third_party/ssba/Math/v3d_linear.h
+++ /dev/null
@@ -1,923 +0,0 @@
-// -*- C++ -*-
-/*
-Copyright (c) 2008 University of North Carolina at Chapel Hill
-
-This file is part of SSBA (Simple Sparse Bundle Adjustment).
-
-SSBA 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 3 of the License, or (at your option) any
-later version.
-
-SSBA is distributed in the hope that 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.
-
-You should have received a copy of the GNU Lesser General Public License along
-with SSBA. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef V3D_LINEAR_H
-#define V3D_LINEAR_H
-
-#include <cassert>
-#include <algorithm>
-#include <vector>
-#include <cmath>
-
-namespace V3D
-{
- using namespace std;
-
- //! Unboxed vector type
- template <typename Elem, int Size>
- struct InlineVectorBase
- {
- typedef Elem value_type;
- typedef Elem element_type;
-
- typedef Elem const * const_iterator;
- typedef Elem * iterator;
-
- static unsigned int size() { return Size; }
-
- Elem& operator[](unsigned int i) { return _vec[i]; }
- Elem operator[](unsigned int i) const { return _vec[i]; }
-
- Elem& operator()(unsigned int i) { return _vec[i-1]; }
- Elem operator()(unsigned int i) const { return _vec[i-1]; }
-
- const_iterator begin() const { return _vec; }
- iterator begin() { return _vec; }
- const_iterator end() const { return _vec + Size; }
- iterator end() { return _vec + Size; }
-
- void newsize(unsigned int sz) const
- {
- assert(sz == Size);
- }
-
- protected:
- Elem _vec[Size];
- };
-
- //! Boxed (heap allocated) vector.
- template <typename Elem>
- struct VectorBase
- {
- typedef Elem value_type;
- typedef Elem element_type;
-
- typedef Elem const * const_iterator;
- typedef Elem * iterator;
-
- VectorBase()
- : _size(0), _ownsVec(true), _vec(0)
- { }
-
- VectorBase(unsigned int size)
- : _size(size), _ownsVec(true), _vec(0)
- {
- if (size > 0) _vec = new Elem[size];
- }
-
- VectorBase(unsigned int size, Elem * values)
- : _size(size), _ownsVec(false), _vec(values)
- { }
-
- VectorBase(VectorBase<Elem> const& a)
- : _size(0), _ownsVec(true), _vec(0)
- {
- _size = a._size;
- if (_size == 0) return;
- _vec = new Elem[_size];
- std::copy(a._vec, a._vec + _size, _vec);
- }
-
- ~VectorBase() { if (_ownsVec && _vec != 0) delete [] _vec; }
-
- VectorBase& operator=(VectorBase<Elem> const& a)
- {
- if (this == &a) return *this;
-
- this->newsize(a._size);
- std::copy(a._vec, a._vec + _size, _vec);
- return *this;
- }
-
- unsigned int size() const { return _size; }
-
- VectorBase<Elem>& newsize(unsigned int sz)
- {
- if (sz == _size) return *this;
- assert(_ownsVec);
-
- __destroy();
- _size = sz;
- if (_size > 0) _vec = new Elem[_size];
-
- return *this;
- }
-
-
- Elem& operator[](unsigned int i) { return _vec[i]; }
- Elem operator[](unsigned int i) const { return _vec[i]; }
-
- Elem& operator()(unsigned int i) { return _vec[i-1]; }
- Elem operator()(unsigned int i) const { return _vec[i-1]; }
-
- const_iterator begin() const { return _vec; }
- iterator begin() { return _vec; }
- const_iterator end() const { return _vec + _size; }
- iterator end() { return _vec + _size; }
-
- protected:
- void __destroy()
- {
- assert(_ownsVec);
-
- if (_vec != 0) delete [] _vec;
- _size = 0;
- _vec = 0;
- }
-
- unsigned int _size;
- bool _ownsVec;
- Elem * _vec;
- };
-
- template <typename Elem, int Rows, int Cols>
- struct InlineMatrixBase
- {
- typedef Elem value_type;
- typedef Elem element_type;
-
- typedef Elem * iterator;
- typedef Elem const * const_iterator;
-
- static unsigned int num_rows() { return Rows; }
- static unsigned int num_cols() { return Cols; }
-
- Elem * operator[](unsigned int row) { return _m[row]; }
- Elem const * operator[](unsigned int row) const { return _m[row]; }
-
- Elem& operator()(unsigned int row, unsigned int col) { return _m[row-1][col-1]; }
- Elem operator()(unsigned int row, unsigned int col) const { return _m[row-1][col-1]; }
-
- template <typename Vec>
- void getRowSlice(unsigned int row, unsigned int first, unsigned int last, Vec& dst) const
- {
- for (unsigned int c = first; c < last; ++c) dst[c-first] = _m[row][c];
- }
-
- template <typename Vec>
- void getColumnSlice(unsigned int first, unsigned int len, unsigned int col, Vec& dst) const
- {
- for (unsigned int r = 0; r < len; ++r) dst[r] = _m[r+first][col];
- }
-
- void newsize(unsigned int rows, unsigned int cols) const
- {
- assert(rows == Rows && cols == Cols);
- }
-
- const_iterator begin() const { return &_m[0][0]; }
- iterator begin() { return &_m[0][0]; }
- const_iterator end() const { return &_m[0][0] + Rows*Cols; }
- iterator end() { return &_m[0][0] + Rows*Cols; }
-
- protected:
- Elem _m[Rows][Cols];
- };
-
- template <typename Elem>
- struct MatrixBase
- {
- typedef Elem value_type;
- typedef Elem element_type;
-
- typedef Elem const * const_iterator;
- typedef Elem * iterator;
-
- MatrixBase()
- : _rows(0), _cols(0), _ownsData(true), _m(0)
- { }
-
- MatrixBase(unsigned int rows, unsigned int cols)
- : _rows(rows), _cols(cols), _ownsData(true), _m(0)
- {
- if (_rows * _cols == 0) return;
- _m = new Elem[rows*cols];
- }
-
- MatrixBase(unsigned int rows, unsigned int cols, Elem * values)
- : _rows(rows), _cols(cols), _ownsData(false), _m(values)
- { }
-
- MatrixBase(MatrixBase<Elem> const& a)
- : _ownsData(true), _m(0)
- {
- _rows = a._rows; _cols = a._cols;
- if (_rows * _cols == 0) return;
- _m = new Elem[_rows*_cols];
- std::copy(a._m, a._m+_rows*_cols, _m);
- }
-
- ~MatrixBase()
- {
- if (_ownsData && _m != 0) delete [] _m;
- }
-
- MatrixBase& operator=(MatrixBase<Elem> const& a)
- {
- if (this == &a) return *this;
-
- this->newsize(a.num_rows(), a.num_cols());
-
- std::copy(a._m, a._m+_rows*_cols, _m);
- return *this;
- }
-
- void newsize(unsigned int rows, unsigned int cols)
- {
- if (rows == _rows && cols == _cols) return;
-
- assert(_ownsData);
-
- __destroy();
-
- _rows = rows;
- _cols = cols;
- if (_rows * _cols == 0) return;
- _m = new Elem[rows*cols];
- }
-
- unsigned int num_rows() const { return _rows; }
- unsigned int num_cols() const { return _cols; }
-
- Elem * operator[](unsigned int row) { return _m + row*_cols; }
- Elem const * operator[](unsigned int row) const { return _m + row*_cols; }
-
- Elem& operator()(unsigned int row, unsigned int col) { return _m[(row-1)*_cols + col-1]; }
- Elem operator()(unsigned int row, unsigned int col) const { return _m[(row-1)*_cols + col-1]; }
-
- const_iterator begin() const { return _m; }
- iterator begin() { return _m; }
- const_iterator end() const { return _m + _rows*_cols; }
- iterator end() { return _m + _rows*_cols; }
-
- template <typename Vec>
- void getRowSlice(unsigned int row, unsigned int first, unsigned int last, Vec& dst) const
- {
- Elem const * v = (*this)[row];
- for (unsigned int c = first; c < last; ++c) dst[c-first] = v[c];
- }
-
- template <typename Vec>
- void getColumnSlice(unsigned int first, unsigned int len, unsigned int col, Vec& dst) const
- {
- for (unsigned int r = 0; r < len; ++r) dst[r] = _m[r+first][col];
- }
-
- protected:
- void __destroy()
- {
- assert(_ownsData);
- if (_m != 0) delete [] _m;
- _m = 0;
- _rows = _cols = 0;
- }
-
- unsigned int _rows, _cols;
- bool _ownsData;
- Elem * _m;
- };
-
- template <typename T>
- struct CCS_Matrix
- {
- CCS_Matrix()
- : _rows(0), _cols(0)
- { }
-
- CCS_Matrix(int const rows, int const cols, vector<pair<int, int> > const& nonZeros)
- : _rows(rows), _cols(cols)
- {
- this->initialize(nonZeros);
- }
-
- CCS_Matrix(CCS_Matrix const& b)
- : _rows(b._rows), _cols(b._cols),
- _colStarts(b._colStarts), _rowIdxs(b._rowIdxs), _destIdxs(b._destIdxs), _values(b._values)
- { }
-
- CCS_Matrix& operator=(CCS_Matrix const& b)
- {
- if (this == &b) return *this;
- _rows = b._rows;
- _cols = b._cols;
- _colStarts = b._colStarts;
- _rowIdxs = b._rowIdxs;
- _destIdxs = b._destIdxs;
- _values = b._values;
- return *this;
- }
-
- void create(int const rows, int const cols, vector<pair<int, int> > const& nonZeros)
- {
- _rows = rows;
- _cols = cols;
- this->initialize(nonZeros);
- }
-
- unsigned int num_rows() const { return _rows; }
- unsigned int num_cols() const { return _cols; }
-
- int getNonzeroCount() const { return _values.size(); }
-
- T const * getValues() const { return &_values[0]; }
- T * getValues() { return &_values[0]; }
-
- int const * getDestIndices() const { return &_destIdxs[0]; }
- int const * getColumnStarts() const { return &_colStarts[0]; }
- int const * getRowIndices() const { return &_rowIdxs[0]; }
-
- void getRowRange(unsigned int col, unsigned int& firstRow, unsigned int& lastRow) const
- {
- firstRow = _rowIdxs[_colStarts[col]];
- lastRow = _rowIdxs[_colStarts[col+1]-1]+1;
- }
-
- template <typename Vec>
- void getColumnSlice(unsigned int first, unsigned int len, unsigned int col, Vec& dst) const
- {
- unsigned int const last = first + len;
-
- for (int r = 0; r < len; ++r) dst[r] = 0; // Fill vector with zeros
-
- int const colStart = _colStarts[col];
- int const colEnd = _colStarts[col+1];
-
- int i = colStart;
- int r;
- // Skip rows less than the given start row
- while (i < colEnd && (r = _rowIdxs[i]) < first) ++i;
-
- // Copy elements until the final row
- while (i < colEnd && (r = _rowIdxs[i]) < last)
- {
- dst[r-first] = _values[i];
- ++i;
- }
- } // end getColumnSlice()
-
- int getColumnNonzeroCount(unsigned int col) const
- {
- int const colStart = _colStarts[col];
- int const colEnd = _colStarts[col+1];
- return colEnd - colStart;
- }
-
- template <typename VecA, typename VecB>
- void getSparseColumn(unsigned int col, VecA& rows, VecB& values) const
- {
- int const colStart = _colStarts[col];
- int const colEnd = _colStarts[col+1];
- int const nnz = colEnd - colStart;
-
- for (int i = 0; i < nnz; ++i)
- {
- rows[i] = _rowIdxs[colStart + i];
- values[i] = _values[colStart + i];
- }
- }
-
- protected:
- struct NonzeroInfo
- {
- int row, col, serial;
-
- // Sort wrt the column first
- bool operator<(NonzeroInfo const& rhs) const
- {
- if (col < rhs.col) return true;
- if (col > rhs.col) return false;
- return row < rhs.row;
- }
- };
-
- void initialize(std::vector<std::pair<int, int> > const& nonZeros)
- {
- using namespace std;
-
- int const nnz = nonZeros.size();
-
- _colStarts.resize(_cols + 1);
- _rowIdxs.resize(nnz);
-
- vector<NonzeroInfo> nz(nnz);
- for (int k = 0; k < nnz; ++k)
- {
- nz[k].row = nonZeros[k].first;
- nz[k].col = nonZeros[k].second;
- nz[k].serial = k;
- }
-
- // Sort in column major order
- std::sort(nz.begin(), nz.end());
-
- for (size_t k = 0; k < nnz; ++k) _rowIdxs[k] = nz[k].row;
-
- int curCol = -1;
- for (int k = 0; k < nnz; ++k)
- {
- NonzeroInfo const& el = nz[k];
- if (el.col != curCol)
- {
- // Update empty cols between
- for (int c = curCol+1; c < el.col; ++c) _colStarts[c] = k;
-
- curCol = el.col;
- _colStarts[curCol] = k;
- } // end if
- } // end for (k)
-
- // Update remaining columns
- for (int c = curCol+1; c <= _cols; ++c) _colStarts[c] = nnz;
-
- _destIdxs.resize(nnz);
- for (int k = 0; k < nnz; ++k) _destIdxs[nz[k].serial] = k;
-
- _values.resize(nnz);
- } // end initialize()
-
- int _rows, _cols;
- std::vector<int> _colStarts;
- std::vector<int> _rowIdxs;
- std::vector<int> _destIdxs;
- std::vector<T> _values;
- }; // end struct CCS_Matrix
-
-//----------------------------------------------------------------------
-
- template <typename Vec, typename Elem>
- inline void
- fillVector(Vec& v, Elem val)
- {
- // We do not use std::fill since we rely only on size() and operator[] member functions.
- for (unsigned int i = 0; i < v.size(); ++i) v[i] = val;
- }
-
- template <typename Vec>
- inline void
- makeZeroVector(Vec& v)
- {
- fillVector(v, 0);
- }
-
- template <typename VecA, typename VecB>
- inline void
- copyVector(VecA const& src, VecB& dst)
- {
- assert(src.size() == dst.size());
- // We do not use std::fill since we rely only on size() and operator[] member functions.
- for (unsigned int i = 0; i < src.size(); ++i) dst[i] = src[i];
- }
-
- template <typename VecA, typename VecB>
- inline void
- copyVectorSlice(VecA const& src, unsigned int srcStart, unsigned int srcLen,
- VecB& dst, unsigned int dstStart)
- {
- unsigned int const end = std::min(srcStart + srcLen, src.size());
- unsigned int const sz = dst.size();
- unsigned int i0, i1;
- for (i0 = srcStart, i1 = dstStart; i0 < end && i1 < sz; ++i0, ++i1) dst[i1] = src[i0];
- }
-
- template <typename Vec>
- inline typename Vec::value_type
- norm_L1(Vec const& v)
- {
- typename Vec::value_type res(0);
- for (unsigned int i = 0; i < v.size(); ++i) res += fabs(v[i]);
- return res;
- }
-
- template <typename Vec>
- inline typename Vec::value_type
- norm_Linf(Vec const& v)
- {
- typename Vec::value_type res(0);
- for (unsigned int i = 0; i < v.size(); ++i) res = std::max(res, fabs(v[i]));
- return res;
- }
-
- template <typename Vec>
- inline typename Vec::value_type
- norm_L2(Vec const& v)
- {
- typename Vec::value_type res(0);
- for (unsigned int i = 0; i < v.size(); ++i) res += v[i]*v[i];
- return sqrt((double)res);
- }
-
- template <typename Vec>
- inline typename Vec::value_type
- sqrNorm_L2(Vec const& v)
- {
- typename Vec::value_type res(0);
- for (unsigned int i = 0; i < v.size(); ++i) res += v[i]*v[i];
- return res;
- }
-
- template <typename Vec>
- inline void
- normalizeVector(Vec& v)
- {
- typename Vec::value_type norm(norm_L2(v));
- for (unsigned int i = 0; i < v.size(); ++i) v[i] /= norm;
- }
-
- template<typename VecA, typename VecB>
- inline typename VecA::value_type
- innerProduct(VecA const& a, VecB const& b)
- {
- assert(a.size() == b.size());
- typename VecA::value_type res(0);
- for (unsigned int i = 0; i < a.size(); ++i) res += a[i] * b[i];
- return res;
- }
-
- template <typename Elem, typename VecA, typename VecB>
- inline void
- scaleVector(Elem s, VecA const& v, VecB& dst)
- {
- for (unsigned int i = 0; i < v.size(); ++i) dst[i] = s * v[i];
- }
-
- template <typename Elem, typename Vec>
- inline void
- scaleVectorIP(Elem s, Vec& v)
- {
- typedef typename Vec::value_type Elem2;
- for (unsigned int i = 0; i < v.size(); ++i)
- v[i] = (Elem2)(v[i] * s);
- }
-
- template <typename VecA, typename VecB, typename VecC>
- inline void
- makeCrossProductVector(VecA const& v, VecB const& w, VecC& dst)
- {
- assert(v.size() == 3);
- assert(w.size() == 3);
- assert(dst.size() == 3);
- dst[0] = v[1]*w[2] - v[2]*w[1];
- dst[1] = v[2]*w[0] - v[0]*w[2];
- dst[2] = v[0]*w[1] - v[1]*w[0];
- }
-
- template <typename VecA, typename VecB, typename VecC>
- inline void
- addVectors(VecA const& v, VecB const& w, VecC& dst)
- {
- assert(v.size() == w.size());
- assert(v.size() == dst.size());
- for (unsigned int i = 0; i < v.size(); ++i) dst[i] = v[i] + w[i];
- }
-
- template <typename VecA, typename VecB, typename VecC>
- inline void
- subtractVectors(VecA const& v, VecB const& w, VecC& dst)
- {
- assert(v.size() == w.size());
- assert(v.size() == dst.size());
- for (unsigned int i = 0; i < v.size(); ++i) dst[i] = v[i] - w[i];
- }
-
- template <typename MatA, typename MatB>
- inline void
- copyMatrix(MatA const& src, MatB& dst)
- {
- unsigned int const rows = src.num_rows();
- unsigned int const cols = src.num_cols();
- assert(dst.num_rows() == rows);
- assert(dst.num_cols() == cols);
- for (unsigned int c = 0; c < cols; ++c)
- for (unsigned int r = 0; r < rows; ++r) dst[r][c] = src[r][c];
- }
-
- template <typename MatA, typename MatB>
- inline void
- copyMatrixSlice(MatA const& src, unsigned int rowStart, unsigned int colStart, unsigned int rowLen, unsigned int colLen,
- MatB& dst, unsigned int dstRow, unsigned int dstCol)
- {
- unsigned int const rows = dst.num_rows();
- unsigned int const cols = dst.num_cols();
-
- unsigned int const rowEnd = std::min(rowStart + rowLen, src.num_rows());
- unsigned int const colEnd = std::min(colStart + colLen, src.num_cols());
-
- unsigned int c0, c1, r0, r1;
-
- for (c0 = colStart, c1 = dstCol; c0 < colEnd && c1 < cols; ++c0, ++c1)
- for (r0 = rowStart, r1 = dstRow; r0 < rowEnd && r1 < rows; ++r0, ++r1)
- dst[r1][c1] = src[r0][c0];
- }
-
- template <typename MatA, typename MatB>
- inline void
- makeTransposedMatrix(MatA const& src, MatB& dst)
- {
- unsigned int const rows = src.num_rows();
- unsigned int const cols = src.num_cols();
- assert(dst.num_cols() == rows);
- assert(dst.num_rows() == cols);
- for (unsigned int c = 0; c < cols; ++c)
- for (unsigned int r = 0; r < rows; ++r) dst[c][r] = src[r][c];
- }
-
- template <typename Mat>
- inline void
- fillMatrix(Mat& m, typename Mat::value_type val)
- {
- unsigned int const rows = m.num_rows();
- unsigned int const cols = m.num_cols();
- for (unsigned int c = 0; c < cols; ++c)
- for (unsigned int r = 0; r < rows; ++r) m[r][c] = val;
- }
-
- template <typename Mat>
- inline void
- makeZeroMatrix(Mat& m)
- {
- fillMatrix(m, 0);
- }
-
- template <typename Mat>
- inline void
- makeIdentityMatrix(Mat& m)
- {
- makeZeroMatrix(m);
- unsigned int const rows = m.num_rows();
- unsigned int const cols = m.num_cols();
- unsigned int n = std::min(rows, cols);
- for (unsigned int i = 0; i < n; ++i)
- m[i][i] = 1;
- }
-
- template <typename Mat, typename Vec>
- inline void
- makeCrossProductMatrix(Vec const& v, Mat& m)
- {
- assert(v.size() == 3);
- assert(m.num_rows() == 3);
- assert(m.num_cols() == 3);
- m[0][0] = 0; m[0][1] = -v[2]; m[0][2] = v[1];
- m[1][0] = v[2]; m[1][1] = 0; m[1][2] = -v[0];
- m[2][0] = -v[1]; m[2][1] = v[0]; m[2][2] = 0;
- }
-
- template <typename Mat, typename Vec>
- inline void
- makeOuterProductMatrix(Vec const& v, Mat& m)
- {
- assert(m.num_cols() == m.num_rows());
- assert(v.size() == m.num_cols());
- unsigned const sz = v.size();
- for (unsigned r = 0; r < sz; ++r)
- for (unsigned c = 0; c < sz; ++c) m[r][c] = v[r]*v[c];
- }
-
- template <typename Mat, typename VecA, typename VecB>
- inline void
- makeOuterProductMatrix(VecA const& u, VecB const& v, Mat& m)
- {
- assert(m.num_cols() == m.num_rows());
- assert(u.size() == m.num_cols());
- assert(v.size() == m.num_cols());
- unsigned const sz = u.size();
- for (unsigned r = 0; r < sz; ++r)
- for (unsigned c = 0; c < sz; ++c) m[r][c] = u[r]*v[c];
- }
-
- template <typename MatA, typename MatB, typename MatC>
- void addMatrices(MatA const& a, MatB const& b, MatC& dst)
- {
- assert(a.num_cols() == b.num_cols());
- assert(a.num_rows() == b.num_rows());
- assert(dst.num_cols() == a.num_cols());
- assert(dst.num_rows() == a.num_rows());
-
- unsigned int const rows = a.num_rows();
- unsigned int const cols = a.num_cols();
-
- for (unsigned r = 0; r < rows; ++r)
- for (unsigned c = 0; c < cols; ++c) dst[r][c] = a[r][c] + b[r][c];
- }
-
- template <typename MatA, typename MatB>
- void addMatricesIP(MatA const& a, MatB& dst)
- {
- assert(dst.num_cols() == a.num_cols());
- assert(dst.num_rows() == a.num_rows());
-
- unsigned int const rows = a.num_rows();
- unsigned int const cols = a.num_cols();
-
- for (unsigned r = 0; r < rows; ++r)
- for (unsigned c = 0; c < cols; ++c) dst[r][c] += a[r][c];
- }
-
- template <typename MatA, typename MatB, typename MatC>
- void subtractMatrices(MatA const& a, MatB const& b, MatC& dst)
- {
- assert(a.num_cols() == b.num_cols());
- assert(a.num_rows() == b.num_rows());
- assert(dst.num_cols() == a.num_cols());
- assert(dst.num_rows() == a.num_rows());
-
- unsigned int const rows = a.num_rows();
- unsigned int const cols = a.num_cols();
-
- for (unsigned r = 0; r < rows; ++r)
- for (unsigned c = 0; c < cols; ++c) dst[r][c] = a[r][c] - b[r][c];
- }
-
- template <typename MatA, typename Elem, typename MatB>
- inline void
- makeScaledMatrix(MatA const& m, Elem scale, MatB& dst)
- {
- unsigned int const rows = m.num_rows();
- unsigned int const cols = m.num_cols();
- for (unsigned int c = 0; c < cols; ++c)
- for (unsigned int r = 0; r < rows; ++r) dst[r][c] = m[r][c] * scale;
- }
-
- template <typename Mat, typename Elem>
- inline void
- scaleMatrixIP(Elem scale, Mat& m)
- {
- unsigned int const rows = m.num_rows();
- unsigned int const cols = m.num_cols();
- for (unsigned int c = 0; c < cols; ++c)
- for (unsigned int r = 0; r < rows; ++r) m[r][c] *= scale;
- }
-
- template <typename Mat, typename VecA, typename VecB>
- inline void
- multiply_A_v(Mat const& m, VecA const& in, VecB& dst)
- {
- unsigned int const rows = m.num_rows();
- unsigned int const cols = m.num_cols();
- assert(in.size() == cols);
- assert(dst.size() == rows);
-
- makeZeroVector(dst);
-
- for (unsigned int r = 0; r < rows; ++r)
- for (unsigned int c = 0; c < cols; ++c) dst[r] += m[r][c] * in[c];
- }
-
- template <typename Mat, typename VecA, typename VecB>
- inline void
- multiply_A_v_projective(Mat const& m, VecA const& in, VecB& dst)
- {
- unsigned int const rows = m.num_rows();
- unsigned int const cols = m.num_cols();
- assert(in.size() == cols-1);
- assert(dst.size() == rows-1);
-
- typename VecB::value_type w = m(rows-1, cols-1);
- unsigned int r, i;
- for (i = 0; i < cols-1; ++i) w += m(rows-1, i) * in[i];
- for (r = 0; r < rows-1; ++r) dst[r] = m(r, cols-1);
- for (r = 0; r < rows-1; ++r)
- for (unsigned int c = 0; c < cols-1; ++c) dst[r] += m[r][c] * in[c];
- for (i = 0; i < rows-1; ++i) dst[i] /= w;
- }
-
- template <typename Mat, typename VecA, typename VecB>
- inline void
- multiply_A_v_affine(Mat const& m, VecA const& in, VecB& dst)
- {
- unsigned int const rows = m.num_rows();
- unsigned int const cols = m.num_cols();
- assert(in.size() == cols-1);
- assert(dst.size() == rows);
-
- unsigned int r;
-
- for (r = 0; r < rows; ++r) dst[r] = m(r, cols-1);
- for (r = 0; r < rows; ++r)
- for (unsigned int c = 0; c < cols-1; ++c) dst[r] += m[r][c] * in[c];
- }
-
- template <typename Mat, typename VecA, typename VecB>
- inline void
- multiply_At_v(Mat const& m, VecA const& in, VecB& dst)
- {
- unsigned int const rows = m.num_rows();
- unsigned int const cols = m.num_cols();
- assert(in.size() == rows);
- assert(dst.size() == cols);
-
- makeZeroVector(dst);
- for (unsigned int c = 0; c < cols; ++c)
- for (unsigned int r = 0; r < rows; ++r) dst[c] += m[r][c] * in[r];
- }
-
- template <typename MatA, typename MatB>
- inline void
- multiply_At_A(MatA const& a, MatB& dst)
- {
- assert(dst.num_rows() == a.num_cols());
- assert(dst.num_cols() == a.num_cols());
-
- typedef typename MatB::value_type Elem;
-
- Elem accum;
- for (unsigned int r = 0; r < a.num_cols(); ++r)
- for (unsigned int c = 0; c < a.num_cols(); ++c)
- {
- accum = 0;
- for (unsigned int k = 0; k < a.num_rows(); ++k) accum += a[k][r] * a[k][c];
- dst[r][c] = accum;
- }
- }
-
- template <typename MatA, typename MatB, typename MatC>
- inline void
- multiply_A_B(MatA const& a, MatB const& b, MatC& dst)
- {
- assert(a.num_cols() == b.num_rows());
- assert(dst.num_rows() == a.num_rows());
- assert(dst.num_cols() == b.num_cols());
-
- typedef typename MatC::value_type Elem;
-
- Elem accum;
- for (unsigned int r = 0; r < a.num_rows(); ++r)
- for (unsigned int c = 0; c < b.num_cols(); ++c)
- {
- accum = 0;
- for (unsigned int k = 0; k < a.num_cols(); ++k) accum += a[r][k] * b[k][c];
- dst[r][c] = accum;
- }
- }
-
- template <typename MatA, typename MatB, typename MatC>
- inline void
- multiply_At_B(MatA const& a, MatB const& b, MatC& dst)
- {
- assert(a.num_rows() == b.num_rows());
- assert(dst.num_rows() == a.num_cols());
- assert(dst.num_cols() == b.num_cols());
-
- typedef typename MatC::value_type Elem;
-
- Elem accum;
- for (unsigned int r = 0; r < a.num_cols(); ++r)
- for (unsigned int c = 0; c < b.num_cols(); ++c)
- {
- accum = 0;
- for (unsigned int k = 0; k < a.num_rows(); ++k) accum += a[k][r] * b[k][c];
- dst[r][c] = accum;
- }
- }
-
- template <typename MatA, typename MatB, typename MatC>
- inline void
- multiply_A_Bt(MatA const& a, MatB const& b, MatC& dst)
- {
- assert(a.num_cols() == b.num_cols());
- assert(dst.num_rows() == a.num_rows());
- assert(dst.num_cols() == b.num_rows());
-
- typedef typename MatC::value_type Elem;
-
- Elem accum;
- for (unsigned int r = 0; r < a.num_rows(); ++r)
- for (unsigned int c = 0; c < b.num_rows(); ++c)
- {
- accum = 0;
- for (unsigned int k = 0; k < a.num_cols(); ++k) accum += a[r][k] * b[c][k];
- dst[r][c] = accum;
- }
- }
-
- template <typename Mat>
- inline void
- transposeMatrixIP(Mat& a)
- {
- assert(a.num_rows() == a.num_cols());
-
- for (unsigned int r = 0; r < a.num_rows(); ++r)
- for (unsigned int c = 0; c < r; ++c)
- std::swap(a[r][c], a[c][r]);
- }
-
-} // end namespace V3D
-
-#endif
diff --git a/extern/libmv/third_party/ssba/Math/v3d_linear_utils.h b/extern/libmv/third_party/ssba/Math/v3d_linear_utils.h
deleted file mode 100644
index 969ec99694f..00000000000
--- a/extern/libmv/third_party/ssba/Math/v3d_linear_utils.h
+++ /dev/null
@@ -1,391 +0,0 @@
-// -*- C++ -*-
-/*
-Copyright (c) 2008 University of North Carolina at Chapel Hill
-
-This file is part of SSBA (Simple Sparse Bundle Adjustment).
-
-SSBA 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 3 of the License, or (at your option) any
-later version.
-
-SSBA is distributed in the hope that 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.
-
-You should have received a copy of the GNU Lesser General Public License along
-with SSBA. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef V3D_LINEAR_UTILS_H
-#define V3D_LINEAR_UTILS_H
-
-#include "Math/v3d_linear.h"
-
-#include <iostream>
-
-namespace V3D
-{
-
- template <typename Elem, int Size>
- struct InlineVector : public InlineVectorBase<Elem, Size>
- {
- }; // end struct InlineVector
-
- template <typename Elem>
- struct Vector : public VectorBase<Elem>
- {
- Vector()
- : VectorBase<Elem>()
- { }
-
- Vector(unsigned int size)
- : VectorBase<Elem>(size)
- { }
-
- Vector(unsigned int size, Elem * values)
- : VectorBase<Elem>(size, values)
- { }
-
- Vector(Vector<Elem> const& a)
- : VectorBase<Elem>(a)
- { }
-
- Vector<Elem>& operator=(Vector<Elem> const& a)
- {
- (VectorBase<Elem>::operator=)(a);
- return *this;
- }
-
- Vector<Elem>& operator+=(Vector<Elem> const& rhs)
- {
- addVectorsIP(rhs, *this);
- return *this;
- }
-
- Vector<Elem>& operator*=(Elem scale)
- {
- scaleVectorsIP(scale, *this);
- return *this;
- }
-
- Vector<Elem> operator+(Vector<Elem> const& rhs) const
- {
- Vector<Elem> res(this->size());
- addVectors(*this, rhs, res);
- return res;
- }
-
- Vector<Elem> operator-(Vector<Elem> const& rhs) const
- {
- Vector<Elem> res(this->size());
- subtractVectors(*this, rhs, res);
- return res;
- }
-
- Elem operator*(Vector<Elem> const& rhs) const
- {
- return innerProduct(*this, rhs);
- }
-
- }; // end struct Vector
-
- template <typename Elem, int Rows, int Cols>
- struct InlineMatrix : public InlineMatrixBase<Elem, Rows, Cols>
- {
- }; // end struct InlineMatrix
-
- template <typename Elem>
- struct Matrix : public MatrixBase<Elem>
- {
- Matrix()
- : MatrixBase<Elem>()
- { }
-
- Matrix(unsigned int rows, unsigned int cols)
- : MatrixBase<Elem>(rows, cols)
- { }
-
- Matrix(unsigned int rows, unsigned int cols, Elem * values)
- : MatrixBase<Elem>(rows, cols, values)
- { }
-
- Matrix(Matrix<Elem> const& a)
- : MatrixBase<Elem>(a)
- { }
-
- Matrix<Elem>& operator=(Matrix<Elem> const& a)
- {
- (MatrixBase<Elem>::operator=)(a);
- return *this;
- }
-
- Matrix<Elem>& operator+=(Matrix<Elem> const& rhs)
- {
- addMatricesIP(rhs, *this);
- return *this;
- }
-
- Matrix<Elem>& operator*=(Elem scale)
- {
- scaleMatrixIP(scale, *this);
- return *this;
- }
-
- Matrix<Elem> operator+(Matrix<Elem> const& rhs) const
- {
- Matrix<Elem> res(this->num_rows(), this->num_cols());
- addMatrices(*this, rhs, res);
- return res;
- }
-
- Matrix<Elem> operator-(Matrix<Elem> const& rhs) const
- {
- Matrix<Elem> res(this->num_rows(), this->num_cols());
- subtractMatrices(*this, rhs, res);
- return res;
- }
-
- }; // end struct Matrix
-
-//----------------------------------------------------------------------
-
- typedef InlineVector<float, 2> Vector2f;
- typedef InlineVector<double, 2> Vector2d;
- typedef InlineVector<float, 3> Vector3f;
- typedef InlineVector<double, 3> Vector3d;
- typedef InlineVector<float, 4> Vector4f;
- typedef InlineVector<double, 4> Vector4d;
-
- typedef InlineMatrix<float, 2, 2> Matrix2x2f;
- typedef InlineMatrix<double, 2, 2> Matrix2x2d;
- typedef InlineMatrix<float, 3, 3> Matrix3x3f;
- typedef InlineMatrix<double, 3, 3> Matrix3x3d;
- typedef InlineMatrix<float, 4, 4> Matrix4x4f;
- typedef InlineMatrix<double, 4, 4> Matrix4x4d;
-
- typedef InlineMatrix<float, 2, 3> Matrix2x3f;
- typedef InlineMatrix<double, 2, 3> Matrix2x3d;
- typedef InlineMatrix<float, 3, 4> Matrix3x4f;
- typedef InlineMatrix<double, 3, 4> Matrix3x4d;
-
- template <typename Elem>
- struct VectorArray
- {
- VectorArray(unsigned count, unsigned size)
- : _count(count), _size(size), _values(0), _vectors(0)
- {
- unsigned const nTotal = _count * _size;
- if (count > 0) _vectors = new Vector<Elem>[count];
- if (nTotal > 0) _values = new Elem[nTotal];
- for (unsigned i = 0; i < _count; ++i) new (&_vectors[i]) Vector<Elem>(_size, _values + i*_size);
- }
-
- VectorArray(unsigned count, unsigned size, Elem initVal)
- : _count(count), _size(size), _values(0), _vectors(0)
- {
- unsigned const nTotal = _count * _size;
- if (count > 0) _vectors = new Vector<Elem>[count];
- if (nTotal > 0) _values = new Elem[nTotal];
- for (unsigned i = 0; i < _count; ++i) new (&_vectors[i]) Vector<Elem>(_size, _values + i*_size);
- std::fill(_values, _values + nTotal, initVal);
- }
-
- ~VectorArray()
- {
- delete [] _values;
- delete [] _vectors;
- }
-
- unsigned count() const { return _count; }
- unsigned size() const { return _size; }
-
- //! Get the submatrix at position ix
- Vector<Elem> const& operator[](unsigned ix) const
- {
- return _vectors[ix];
- }
-
- //! Get the submatrix at position ix
- Vector<Elem>& operator[](unsigned ix)
- {
- return _vectors[ix];
- }
-
- protected:
- unsigned _count, _size;
- Elem * _values;
- Vector<Elem> * _vectors;
-
- private:
- VectorArray(VectorArray const&);
- void operator=(VectorArray const&);
- };
-
- template <typename Elem>
- struct MatrixArray
- {
- MatrixArray(unsigned count, unsigned nRows, unsigned nCols)
- : _count(count), _rows(nRows), _columns(nCols), _values(0), _matrices(0)
- {
- unsigned const nTotal = _count * _rows * _columns;
- if (count > 0) _matrices = new Matrix<Elem>[count];
- if (nTotal > 0) _values = new double[nTotal];
- for (unsigned i = 0; i < _count; ++i)
- new (&_matrices[i]) Matrix<Elem>(_rows, _columns, _values + i*(_rows*_columns));
- }
-
- ~MatrixArray()
- {
- delete [] _matrices;
- delete [] _values;
- }
-
- //! Get the submatrix at position ix
- Matrix<Elem> const& operator[](unsigned ix) const
- {
- return _matrices[ix];
- }
-
- //! Get the submatrix at position ix
- Matrix<Elem>& operator[](unsigned ix)
- {
- return _matrices[ix];
- }
-
- unsigned count() const { return _count; }
- unsigned num_rows() const { return _rows; }
- unsigned num_cols() const { return _columns; }
-
- protected:
- unsigned _count, _rows, _columns;
- double * _values;
- Matrix<Elem> * _matrices;
-
- private:
- MatrixArray(MatrixArray const&);
- void operator=(MatrixArray const&);
- };
-
-//----------------------------------------------------------------------
-
- template <typename Elem, int Size>
- inline InlineVector<Elem, Size>
- operator+(InlineVector<Elem, Size> const& v, InlineVector<Elem, Size> const& w)
- {
- InlineVector<Elem, Size> res;
- addVectors(v, w, res);
- return res;
- }
-
- template <typename Elem, int Size>
- inline InlineVector<Elem, Size>
- operator-(InlineVector<Elem, Size> const& v, InlineVector<Elem, Size> const& w)
- {
- InlineVector<Elem, Size> res;
- subtractVectors(v, w, res);
- return res;
- }
-
- template <typename Elem, int Size>
- inline InlineVector<Elem, Size>
- operator*(Elem scale, InlineVector<Elem, Size> const& v)
- {
- InlineVector<Elem, Size> res;
- scaleVector(scale, v, res);
- return res;
- }
-
- template <typename Elem, int Rows, int Cols>
- inline InlineVector<Elem, Rows>
- operator*(InlineMatrix<Elem, Rows, Cols> const& A, InlineVector<Elem, Cols> const& v)
- {
- InlineVector<Elem, Rows> res;
- multiply_A_v(A, v, res);
- return res;
- }
-
- template <typename Elem, int RowsA, int ColsA, int ColsB>
- inline InlineMatrix<Elem, RowsA, ColsB>
- operator*(InlineMatrix<Elem, RowsA, ColsA> const& A, InlineMatrix<Elem, ColsA, ColsB> const& B)
- {
- InlineMatrix<Elem, RowsA, ColsB> res;
- multiply_A_B(A, B, res);
- return res;
- }
-
- template <typename Elem, int Rows, int Cols>
- inline InlineMatrix<Elem, Cols, Rows>
- transposedMatrix(InlineMatrix<Elem, Rows, Cols> const& A)
- {
- InlineMatrix<Elem, Cols, Rows> At;
- makeTransposedMatrix(A, At);
- return At;
- }
-
- template <typename Elem>
- inline InlineMatrix<Elem, 3, 3>
- invertedMatrix(InlineMatrix<Elem, 3, 3> const& A)
- {
- Elem a = A[0][0], b = A[0][1], c = A[0][2];
- Elem d = A[1][0], e = A[1][1], f = A[1][2];
- Elem g = A[2][0], h = A[2][1], i = A[2][2];
-
- Elem const det = a*e*i + b*f*g + c*d*h - c*e*g - b*d*i - a*f*h;
-
- InlineMatrix<Elem, 3, 3> res;
- res[0][0] = e*i-f*h; res[0][1] = c*h-b*i; res[0][2] = b*f-c*e;
- res[1][0] = f*g-d*i; res[1][1] = a*i-c*g; res[1][2] = c*d-a*f;
- res[2][0] = d*h-e*g; res[2][1] = b*g-a*h; res[2][2] = a*e-b*d;
-
- scaleMatrixIP(1.0/det, res);
- return res;
- }
-
- template <typename Elem>
- inline InlineVector<Elem, 2>
- makeVector2(Elem a, Elem b)
- {
- InlineVector<Elem, 2> res;
- res[0] = a; res[1] = b;
- return res;
- }
-
- template <typename Elem>
- inline InlineVector<Elem, 3>
- makeVector3(Elem a, Elem b, Elem c)
- {
- InlineVector<Elem, 3> res;
- res[0] = a; res[1] = b; res[2] = c;
- return res;
- }
-
- template <typename Vec>
- inline void
- displayVector(Vec const& v)
- {
- using namespace std;
-
- for (int r = 0; r < v.size(); ++r)
- cout << v[r] << " ";
- cout << endl;
- }
-
- template <typename Mat>
- inline void
- displayMatrix(Mat const& A)
- {
- using namespace std;
-
- for (int r = 0; r < A.num_rows(); ++r)
- {
- for (int c = 0; c < A.num_cols(); ++c)
- cout << A[r][c] << " ";
- cout << endl;
- }
- }
-
-} // end namespace V3D
-
-#endif
diff --git a/extern/libmv/third_party/ssba/Math/v3d_mathutilities.h b/extern/libmv/third_party/ssba/Math/v3d_mathutilities.h
deleted file mode 100644
index 9e38b92a94b..00000000000
--- a/extern/libmv/third_party/ssba/Math/v3d_mathutilities.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// -*- C++ -*-
-/*
-Copyright (c) 2008 University of North Carolina at Chapel Hill
-
-This file is part of SSBA (Simple Sparse Bundle Adjustment).
-
-SSBA 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 3 of the License, or (at your option) any
-later version.
-
-SSBA is distributed in the hope that 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.
-
-You should have received a copy of the GNU Lesser General Public License along
-with SSBA. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef V3D_MATH_UTILITIES_H
-#define V3D_MATH_UTILITIES_H
-
-#include "Math/v3d_linear.h"
-#include "Math/v3d_linear_utils.h"
-
-#include <vector>
-
-namespace V3D
-{
-
- template <typename Vec, typename Mat>
- inline void
- createRotationMatrixRodriguez(Vec const& omega, Mat& R)
- {
- assert(omega.size() == 3);
- assert(R.num_rows() == 3);
- assert(R.num_cols() == 3);
-
- double const theta = norm_L2(omega);
- makeIdentityMatrix(R);
- if (fabs(theta) > 1e-6)
- {
- Matrix3x3d J, J2;
- makeCrossProductMatrix(omega, J);
- multiply_A_B(J, J, J2);
- double const c1 = sin(theta)/theta;
- double const c2 = (1-cos(theta))/(theta*theta);
- for (int i = 0; i < 3; ++i)
- for (int j = 0; j < 3; ++j)
- R[i][j] += c1*J[i][j] + c2*J2[i][j];
- }
- } // end createRotationMatrixRodriguez()
-
- template <typename T> inline double sqr(T x) { return x*x; }
-
-} // namespace V3D
-
-#endif
diff --git a/extern/libmv/third_party/ssba/Math/v3d_optimization.cpp b/extern/libmv/third_party/ssba/Math/v3d_optimization.cpp
deleted file mode 100644
index 234815fcd1f..00000000000
--- a/extern/libmv/third_party/ssba/Math/v3d_optimization.cpp
+++ /dev/null
@@ -1,955 +0,0 @@
-/*
-Copyright (c) 2008 University of North Carolina at Chapel Hill
-
-This file is part of SSBA (Simple Sparse Bundle Adjustment).
-
-SSBA 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 3 of the License, or (at your option) any
-later version.
-
-SSBA is distributed in the hope that 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.
-
-You should have received a copy of the GNU Lesser General Public License along
-with SSBA. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "Math/v3d_optimization.h"
-
-#if defined(V3DLIB_ENABLE_SUITESPARSE)
-//# include "COLAMD/Include/colamd.h"
-# include "colamd.h"
-extern "C"
-{
-//# include "LDL/Include/ldl.h"
-# include "ldl.h"
-}
-#endif
-
-#include <iostream>
-#include <map>
-
-#define USE_BLOCK_REORDERING 1
-#define USE_MULTIPLICATIVE_UPDATE 1
-
-using namespace std;
-
-namespace
-{
-
- using namespace V3D;
-
- inline double
- squaredResidual(VectorArray<double> const& e)
- {
- int const N = e.count();
- int const M = e.size();
-
- double res = 0.0;
-
- for (int n = 0; n < N; ++n)
- for (int m = 0; m < M; ++m)
- res += e[n][m] * e[n][m];
-
- return res;
- } // end squaredResidual()
-
-} // end namespace <>
-
-namespace V3D
-{
-
- int optimizerVerbosenessLevel = 0;
-
-#if defined(V3DLIB_ENABLE_SUITESPARSE)
-
- void
- SparseLevenbergOptimizer::setupSparseJtJ()
- {
- int const nVaryingA = _nParametersA - _nNonvaryingA;
- int const nVaryingB = _nParametersB - _nNonvaryingB;
- int const nVaryingC = _paramDimensionC - _nNonvaryingC;
-
- int const bColumnStart = nVaryingA*_paramDimensionA;
- int const cColumnStart = bColumnStart + nVaryingB*_paramDimensionB;
- int const nColumns = cColumnStart + nVaryingC;
-
- _jointNonzerosW.clear();
- _jointIndexW.resize(_nMeasurements);
-#if 1
- {
- map<pair<int, int>, int> jointNonzeroMap;
- for (size_t k = 0; k < _nMeasurements; ++k)
- {
- int const i = _correspondingParamA[k] - _nNonvaryingA;
- int const j = _correspondingParamB[k] - _nNonvaryingB;
- if (i >= 0 && j >= 0)
- {
- map<pair<int, int>, int>::const_iterator p = jointNonzeroMap.find(make_pair(i, j));
- if (p == jointNonzeroMap.end())
- {
- jointNonzeroMap.insert(make_pair(make_pair(i, j), _jointNonzerosW.size()));
- _jointIndexW[k] = _jointNonzerosW.size();
- _jointNonzerosW.push_back(make_pair(i, j));
- }
- else
- {
- _jointIndexW[k] = (*p).second;
- } // end if
- } // end if
- } // end for (k)
- } // end scope
-#else
- for (size_t k = 0; k < _nMeasurements; ++k)
- {
- int const i = _correspondingParamA[k] - _nNonvaryingA;
- int const j = _correspondingParamB[k] - _nNonvaryingB;
- if (i >= 0 && j >= 0)
- {
- _jointIndexW[k] = _jointNonzerosW.size();
- _jointNonzerosW.push_back(make_pair(i, j));
- }
- } // end for (k)
-#endif
-
-#if defined(USE_BLOCK_REORDERING)
- int const bBlockColumnStart = nVaryingA;
- int const cBlockColumnStart = bBlockColumnStart + nVaryingB;
-
- int const nBlockColumns = cBlockColumnStart + ((nVaryingC > 0) ? 1 : 0);
-
- //cout << "nBlockColumns = " << nBlockColumns << endl;
-
- // For the column reordering we treat the columns belonging to one set
- // of parameters as one (logical) column.
-
- // Determine non-zeros of JtJ (we forget about the non-zero diagonal for now)
- // Only consider nonzeros of Ai^t * Bj induced by the measurements.
- vector<pair<int, int> > nz_blockJtJ(_jointNonzerosW.size());
- for (int k = 0; k < _jointNonzerosW.size(); ++k)
- {
- nz_blockJtJ[k].first = _jointNonzerosW[k].second + bBlockColumnStart;
- nz_blockJtJ[k].second = _jointNonzerosW[k].first;
- }
-
- if (nVaryingC > 0)
- {
- // We assume, that the global unknowns are linked to every other variable.
- for (int i = 0; i < nVaryingA; ++i)
- nz_blockJtJ.push_back(make_pair(cBlockColumnStart, i));
- for (int j = 0; j < nVaryingB; ++j)
- nz_blockJtJ.push_back(make_pair(cBlockColumnStart, j + bBlockColumnStart));
- } // end if
-
- int const nnzBlock = nz_blockJtJ.size();
-
- vector<int> permBlockJtJ(nBlockColumns + 1);
-
- if (nnzBlock > 0)
- {
-// cout << "nnzBlock = " << nnzBlock << endl;
-
- CCS_Matrix<int> blockJtJ(nBlockColumns, nBlockColumns, nz_blockJtJ);
-
-// cout << " nz_blockJtJ: " << endl;
-// for (size_t k = 0; k < nz_blockJtJ.size(); ++k)
-// cout << " " << nz_blockJtJ[k].first << ":" << nz_blockJtJ[k].second << endl;
-// cout << endl;
-
- int * colStarts = (int *)blockJtJ.getColumnStarts();
- int * rowIdxs = (int *)blockJtJ.getRowIndices();
-
-// cout << "blockJtJ_colStarts = ";
-// for (int k = 0; k <= nBlockColumns; ++k) cout << colStarts[k] << " ";
-// cout << endl;
-
-// cout << "blockJtJ_rowIdxs = ";
-// for (int k = 0; k < nnzBlock; ++k) cout << rowIdxs[k] << " ";
-// cout << endl;
-
- int stats[COLAMD_STATS];
- symamd(nBlockColumns, rowIdxs, colStarts, &permBlockJtJ[0], (double *) NULL, stats, &calloc, &free);
- if (optimizerVerbosenessLevel >= 2) symamd_report(stats);
- }
- else
- {
- for (int k = 0; k < permBlockJtJ.size(); ++k) permBlockJtJ[k] = k;
- } // end if
-
-// cout << "permBlockJtJ = ";
-// for (int k = 0; k < permBlockJtJ.size(); ++k)
-// cout << permBlockJtJ[k] << " ";
-// cout << endl;
-
- // From the determined symbolic permutation with logical variables, determine the actual ordering
- _perm_JtJ.resize(nVaryingA*_paramDimensionA + nVaryingB*_paramDimensionB + nVaryingC + 1);
-
- int curDstCol = 0;
- for (int k = 0; k < permBlockJtJ.size()-1; ++k)
- {
- int const srcCol = permBlockJtJ[k];
- if (srcCol < nVaryingA)
- {
- for (int n = 0; n < _paramDimensionA; ++n)
- _perm_JtJ[curDstCol + n] = srcCol*_paramDimensionA + n;
- curDstCol += _paramDimensionA;
- }
- else if (srcCol >= bBlockColumnStart && srcCol < cBlockColumnStart)
- {
- int const bStart = nVaryingA*_paramDimensionA;
- int const j = srcCol - bBlockColumnStart;
-
- for (int n = 0; n < _paramDimensionB; ++n)
- _perm_JtJ[curDstCol + n] = bStart + j*_paramDimensionB + n;
- curDstCol += _paramDimensionB;
- }
- else if (srcCol == cBlockColumnStart)
- {
- int const cStart = nVaryingA*_paramDimensionA + nVaryingB*_paramDimensionB;
-
- for (int n = 0; n < nVaryingC; ++n)
- _perm_JtJ[curDstCol + n] = cStart + n;
- curDstCol += nVaryingC;
- }
- else
- {
- cerr << "Should not reach " << __LINE__ << ":" << __LINE__ << "!" << endl;
- assert(false);
- }
- }
-#else
- vector<pair<int, int> > nz, nzL;
- this->serializeNonZerosJtJ(nz);
-
- for (int k = 0; k < nz.size(); ++k)
- {
- // Swap rows and columns, since serializeNonZerosJtJ() generates the
- // upper triangular part but symamd wants the lower triangle.
- nzL.push_back(make_pair(nz[k].second, nz[k].first));
- }
-
- _perm_JtJ.resize(nColumns+1);
-
- if (nzL.size() > 0)
- {
- CCS_Matrix<int> symbJtJ(nColumns, nColumns, nzL);
-
- int * colStarts = (int *)symbJtJ.getColumnStarts();
- int * rowIdxs = (int *)symbJtJ.getRowIndices();
-
-// cout << "symbJtJ_colStarts = ";
-// for (int k = 0; k <= nColumns; ++k) cout << colStarts[k] << " ";
-// cout << endl;
-
-// cout << "symbJtJ_rowIdxs = ";
-// for (int k = 0; k < nzL.size(); ++k) cout << rowIdxs[k] << " ";
-// cout << endl;
-
- int stats[COLAMD_STATS];
- symamd(nColumns, rowIdxs, colStarts, &_perm_JtJ[0], (double *) NULL, stats, &calloc, &free);
- if (optimizerVerbosenessLevel >= 2) symamd_report(stats);
- }
- else
- {
- for (int k = 0; k < _perm_JtJ.size(); ++k) _perm_JtJ[k] = k;
- } //// end if
-#endif
- _perm_JtJ.back() = _perm_JtJ.size() - 1;
-
-// cout << "_perm_JtJ = ";
-// for (int k = 0; k < _perm_JtJ.size(); ++k) cout << _perm_JtJ[k] << " ";
-// cout << endl;
-
- // Finally, compute the inverse of the full permutation.
- _invPerm_JtJ.resize(_perm_JtJ.size());
- for (size_t k = 0; k < _perm_JtJ.size(); ++k)
- _invPerm_JtJ[_perm_JtJ[k]] = k;
-
- vector<pair<int, int> > nz_JtJ;
- this->serializeNonZerosJtJ(nz_JtJ);
-
- for (int k = 0; k < nz_JtJ.size(); ++k)
- {
- int const i = nz_JtJ[k].first;
- int const j = nz_JtJ[k].second;
-
- int pi = _invPerm_JtJ[i];
- int pj = _invPerm_JtJ[j];
- // Swap values if in lower triangular part
- if (pi > pj) std::swap(pi, pj);
- nz_JtJ[k].first = pi;
- nz_JtJ[k].second = pj;
- }
-
- int const nnz = nz_JtJ.size();
-
-// cout << "nz_JtJ = ";
-// for (int k = 0; k < nnz; ++k) cout << nz_JtJ[k].first << ":" << nz_JtJ[k].second << " ";
-// cout << endl;
-
- _JtJ.create(nColumns, nColumns, nz_JtJ);
-
-// cout << "_colStart_JtJ = ";
-// for (int k = 0; k < _JtJ.num_cols(); ++k) cout << _JtJ.getColumnStarts()[k] << " ";
-// cout << endl;
-
-// cout << "_rowIdxs_JtJ = ";
-// for (int k = 0; k < nnz; ++k) cout << _JtJ.getRowIndices()[k] << " ";
-// cout << endl;
-
- vector<int> workFlags(nColumns);
-
- _JtJ_Lp.resize(nColumns+1);
- _JtJ_Parent.resize(nColumns);
- _JtJ_Lnz.resize(nColumns);
-
- ldl_symbolic(nColumns, (int *)_JtJ.getColumnStarts(), (int *)_JtJ.getRowIndices(),
- &_JtJ_Lp[0], &_JtJ_Parent[0], &_JtJ_Lnz[0],
- &workFlags[0], NULL, NULL);
-
- if (optimizerVerbosenessLevel >= 1)
- cout << "SparseLevenbergOptimizer: Nonzeros in LDL decomposition: " << _JtJ_Lp[nColumns] << endl;
-
- } // end SparseLevenbergOptimizer::setupSparseJtJ()
-
- void
- SparseLevenbergOptimizer::serializeNonZerosJtJ(vector<pair<int, int> >& dst) const
- {
- int const nVaryingA = _nParametersA - _nNonvaryingA;
- int const nVaryingB = _nParametersB - _nNonvaryingB;
- int const nVaryingC = _paramDimensionC - _nNonvaryingC;
-
- int const bColumnStart = nVaryingA*_paramDimensionA;
- int const cColumnStart = bColumnStart + nVaryingB*_paramDimensionB;
-
- dst.clear();
-
- // Add the diagonal block matrices (only the upper triangular part).
-
- // Ui submatrices of JtJ
- for (int i = 0; i < nVaryingA; ++i)
- {
- int const i0 = i * _paramDimensionA;
-
- for (int c = 0; c < _paramDimensionA; ++c)
- for (int r = 0; r <= c; ++r)
- dst.push_back(make_pair(i0 + r, i0 + c));
- }
-
- // Vj submatrices of JtJ
- for (int j = 0; j < nVaryingB; ++j)
- {
- int const j0 = j*_paramDimensionB + bColumnStart;
-
- for (int c = 0; c < _paramDimensionB; ++c)
- for (int r = 0; r <= c; ++r)
- dst.push_back(make_pair(j0 + r, j0 + c));
- }
-
- // Z submatrix of JtJ
- for (int c = 0; c < nVaryingC; ++c)
- for (int r = 0; r <= c; ++r)
- dst.push_back(make_pair(cColumnStart + r, cColumnStart + c));
-
- // Add the elements i and j linked by an observation k
- // W submatrix of JtJ
- for (size_t n = 0; n < _jointNonzerosW.size(); ++n)
- {
- int const i0 = _jointNonzerosW[n].first;
- int const j0 = _jointNonzerosW[n].second;
- int const r0 = i0*_paramDimensionA;
- int const c0 = j0*_paramDimensionB + bColumnStart;
-
- for (int r = 0; r < _paramDimensionA; ++r)
- for (int c = 0; c < _paramDimensionB; ++c)
- dst.push_back(make_pair(r0 + r, c0 + c));
- } // end for (n)
-
- if (nVaryingC > 0)
- {
- // Finally, add the dense columns linking i (resp. j) with the global parameters.
- // X submatrix of JtJ
- for (int i = 0; i < nVaryingA; ++i)
- {
- int const i0 = i*_paramDimensionA;
-
- for (int r = 0; r < _paramDimensionA; ++r)
- for (int c = 0; c < nVaryingC; ++c)
- dst.push_back(make_pair(i0 + r, cColumnStart + c));
- }
-
- // Y submatrix of JtJ
- for (int j = 0; j < nVaryingB; ++j)
- {
- int const j0 = j*_paramDimensionB + bColumnStart;
-
- for (int r = 0; r < _paramDimensionB; ++r)
- for (int c = 0; c < nVaryingC; ++c)
- dst.push_back(make_pair(j0 + r, cColumnStart + c));
- }
- } // end if
- } // end SparseLevenbergOptimizer::serializeNonZerosJtJ()
-
- void
- SparseLevenbergOptimizer::fillSparseJtJ(MatrixArray<double> const& Ui,
- MatrixArray<double> const& Vj,
- MatrixArray<double> const& Wn,
- Matrix<double> const& Z,
- Matrix<double> const& X,
- Matrix<double> const& Y)
- {
- int const nVaryingA = _nParametersA - _nNonvaryingA;
- int const nVaryingB = _nParametersB - _nNonvaryingB;
- int const nVaryingC = _paramDimensionC - _nNonvaryingC;
-
- int const bColumnStart = nVaryingA*_paramDimensionA;
- int const cColumnStart = bColumnStart + nVaryingB*_paramDimensionB;
-
- int const nCols = _JtJ.num_cols();
- int const nnz = _JtJ.getNonzeroCount();
-
- // The following has to replicate the procedure as in serializeNonZerosJtJ()
-
- int serial = 0;
-
- double * values = _JtJ.getValues();
- int const * destIdxs = _JtJ.getDestIndices();
-
- // Add the diagonal block matrices (only the upper triangular part).
-
- // Ui submatrices of JtJ
- for (int i = 0; i < nVaryingA; ++i)
- {
- int const i0 = i * _paramDimensionA;
-
- for (int c = 0; c < _paramDimensionA; ++c)
- for (int r = 0; r <= c; ++r, ++serial)
- values[destIdxs[serial]] = Ui[i][r][c];
- }
-
- // Vj submatrices of JtJ
- for (int j = 0; j < nVaryingB; ++j)
- {
- int const j0 = j*_paramDimensionB + bColumnStart;
-
- for (int c = 0; c < _paramDimensionB; ++c)
- for (int r = 0; r <= c; ++r, ++serial)
- values[destIdxs[serial]] = Vj[j][r][c];
- }
-
- // Z submatrix of JtJ
- for (int c = 0; c < nVaryingC; ++c)
- for (int r = 0; r <= c; ++r, ++serial)
- values[destIdxs[serial]] = Z[r][c];
-
- // Add the elements i and j linked by an observation k
- // W submatrix of JtJ
- for (size_t n = 0; n < _jointNonzerosW.size(); ++n)
- {
- for (int r = 0; r < _paramDimensionA; ++r)
- for (int c = 0; c < _paramDimensionB; ++c, ++serial)
- values[destIdxs[serial]] = Wn[n][r][c];
- } // end for (k)
-
- if (nVaryingC > 0)
- {
- // Finally, add the dense columns linking i (resp. j) with the global parameters.
- // X submatrix of JtJ
- for (int i = 0; i < nVaryingA; ++i)
- {
- int const r0 = i * _paramDimensionA;
- for (int r = 0; r < _paramDimensionA; ++r)
- for (int c = 0; c < nVaryingC; ++c, ++serial)
- values[destIdxs[serial]] = X[r0+r][c];
- }
-
- // Y submatrix of JtJ
- for (int j = 0; j < nVaryingB; ++j)
- {
- int const r0 = j * _paramDimensionB;
- for (int r = 0; r < _paramDimensionB; ++r)
- for (int c = 0; c < nVaryingC; ++c, ++serial)
- values[destIdxs[serial]] = Y[r0+r][c];
- }
- } // end if
- } // end SparseLevenbergOptimizer::fillSparseJtJ()
-
- void
- SparseLevenbergOptimizer::minimize()
- {
- status = LEVENBERG_OPTIMIZER_TIMEOUT;
- bool computeDerivatives = true;
-
- int const nVaryingA = _nParametersA - _nNonvaryingA;
- int const nVaryingB = _nParametersB - _nNonvaryingB;
- int const nVaryingC = _paramDimensionC - _nNonvaryingC;
-
- if (nVaryingA == 0 && nVaryingB == 0 && nVaryingC == 0)
- {
- // No degrees of freedom, nothing to optimize.
- status = LEVENBERG_OPTIMIZER_CONVERGED;
- return;
- }
-
- this->setupSparseJtJ();
-
- Vector<double> weights(_nMeasurements);
-
- MatrixArray<double> Ak(_nMeasurements, _measurementDimension, _paramDimensionA);
- MatrixArray<double> Bk(_nMeasurements, _measurementDimension, _paramDimensionB);
- MatrixArray<double> Ck(_nMeasurements, _measurementDimension, _paramDimensionC);
-
- MatrixArray<double> Ui(nVaryingA, _paramDimensionA, _paramDimensionA);
- MatrixArray<double> Vj(nVaryingB, _paramDimensionB, _paramDimensionB);
-
- // Wn = Ak^t*Bk
- MatrixArray<double> Wn(_jointNonzerosW.size(), _paramDimensionA, _paramDimensionB);
-
- Matrix<double> Z(nVaryingC, nVaryingC);
-
- // X = A^t*C
- Matrix<double> X(nVaryingA*_paramDimensionA, nVaryingC);
- // Y = B^t*C
- Matrix<double> Y(nVaryingB*_paramDimensionB, nVaryingC);
-
- VectorArray<double> residuals(_nMeasurements, _measurementDimension);
- VectorArray<double> residuals2(_nMeasurements, _measurementDimension);
-
- VectorArray<double> diagUi(nVaryingA, _paramDimensionA);
- VectorArray<double> diagVj(nVaryingB, _paramDimensionB);
- Vector<double> diagZ(nVaryingC);
-
- VectorArray<double> At_e(nVaryingA, _paramDimensionA);
- VectorArray<double> Bt_e(nVaryingB, _paramDimensionB);
- Vector<double> Ct_e(nVaryingC);
-
- Vector<double> Jt_e(nVaryingA*_paramDimensionA + nVaryingB*_paramDimensionB + nVaryingC);
-
- Vector<double> delta(nVaryingA*_paramDimensionA + nVaryingB*_paramDimensionB + nVaryingC);
- Vector<double> deltaPerm(nVaryingA*_paramDimensionA + nVaryingB*_paramDimensionB + nVaryingC);
-
- VectorArray<double> deltaAi(_nParametersA, _paramDimensionA);
- VectorArray<double> deltaBj(_nParametersB, _paramDimensionB);
- Vector<double> deltaC(_paramDimensionC);
-
- double err = 0.0;
-
- for (currentIteration = 0; currentIteration < maxIterations; ++currentIteration)
- {
- if (optimizerVerbosenessLevel >= 2)
- cout << "SparseLevenbergOptimizer: currentIteration: " << currentIteration << endl;
- if (computeDerivatives)
- {
- this->evalResidual(residuals);
- this->fillWeights(residuals, weights);
- for (int k = 0; k < _nMeasurements; ++k)
- scaleVectorIP(weights[k], residuals[k]);
-
- err = squaredResidual(residuals);
-
- if (optimizerVerbosenessLevel >= 1) cout << "SparseLevenbergOptimizer: |residual|^2 = " << err << endl;
- if (optimizerVerbosenessLevel >= 2) cout << "SparseLevenbergOptimizer: lambda = " << lambda << endl;
-
- for (int k = 0; k < residuals.count(); ++k) scaleVectorIP(-1.0, residuals[k]);
-
- this->setupJacobianGathering();
- this->fillAllJacobians(weights, Ak, Bk, Ck);
-
- // Compute the different parts of J^t*e
- if (nVaryingA > 0)
- {
- for (int i = 0; i < nVaryingA; ++i) makeZeroVector(At_e[i]);
-
- Vector<double> tmp(_paramDimensionA);
-
- for (int k = 0; k < _nMeasurements; ++k)
- {
- int const i = _correspondingParamA[k] - _nNonvaryingA;
- if (i < 0) continue;
- multiply_At_v(Ak[k], residuals[k], tmp);
- addVectors(tmp, At_e[i], At_e[i]);
- } // end for (k)
- } // end if
-
- if (nVaryingB > 0)
- {
- for (int j = 0; j < nVaryingB; ++j) makeZeroVector(Bt_e[j]);
-
- Vector<double> tmp(_paramDimensionB);
-
- for (int k = 0; k < _nMeasurements; ++k)
- {
- int const j = _correspondingParamB[k] - _nNonvaryingB;
- if (j < 0) continue;
- multiply_At_v(Bk[k], residuals[k], tmp);
- addVectors(tmp, Bt_e[j], Bt_e[j]);
- } // end for (k)
- } // end if
-
- if (nVaryingC > 0)
- {
- makeZeroVector(Ct_e);
-
- Vector<double> tmp(_paramDimensionC);
-
- for (int k = 0; k < _nMeasurements; ++k)
- {
- multiply_At_v(Ck[k], residuals[k], tmp);
- for (int l = 0; l < nVaryingC; ++l) Ct_e[l] += tmp[_nNonvaryingC + l];
- }
- } // end if
-
- int pos = 0;
- for (int i = 0; i < nVaryingA; ++i)
- for (int l = 0; l < _paramDimensionA; ++l, ++pos)
- Jt_e[pos] = At_e[i][l];
- for (int j = 0; j < nVaryingB; ++j)
- for (int l = 0; l < _paramDimensionB; ++l, ++pos)
- Jt_e[pos] = Bt_e[j][l];
- for (int l = 0; l < nVaryingC; ++l, ++pos)
- Jt_e[pos] = Ct_e[l];
-
-// cout << "Jt_e = ";
-// for (int k = 0; k < Jt_e.size(); ++k) cout << Jt_e[k] << " ";
-// cout << endl;
-
- if (this->applyGradientStoppingCriteria(norm_Linf(Jt_e)))
- {
- status = LEVENBERG_OPTIMIZER_CONVERGED;
- goto end;
- }
-
- // The lhs J^t*J consists of several parts:
- // [ U W X ]
- // J^t*J = [ W^t V Y ]
- // [ X^t Y^t Z ],
- // where U, V and W are block-sparse matrices (due to the sparsity of A and B).
- // X, Y and Z contain only a few columns (the number of global parameters).
-
- if (nVaryingA > 0)
- {
- // Compute Ui
- Matrix<double> U(_paramDimensionA, _paramDimensionA);
-
- for (int i = 0; i < nVaryingA; ++i) makeZeroMatrix(Ui[i]);
-
- for (int k = 0; k < _nMeasurements; ++k)
- {
- int const i = _correspondingParamA[k] - _nNonvaryingA;
- if (i < 0) continue;
- multiply_At_A(Ak[k], U);
- addMatricesIP(U, Ui[i]);
- } // end for (k)
- } // end if
-
- if (nVaryingB > 0)
- {
- // Compute Vj
- Matrix<double> V(_paramDimensionB, _paramDimensionB);
-
- for (int j = 0; j < nVaryingB; ++j) makeZeroMatrix(Vj[j]);
-
- for (int k = 0; k < _nMeasurements; ++k)
- {
- int const j = _correspondingParamB[k] - _nNonvaryingB;
- if (j < 0) continue;
- multiply_At_A(Bk[k], V);
- addMatricesIP(V, Vj[j]);
- } // end for (k)
- } // end if
-
- if (nVaryingC > 0)
- {
- Matrix<double> ZZ(_paramDimensionC, _paramDimensionC);
- Matrix<double> Zsum(_paramDimensionC, _paramDimensionC);
-
- makeZeroMatrix(Zsum);
-
- for (int k = 0; k < _nMeasurements; ++k)
- {
- multiply_At_A(Ck[k], ZZ);
- addMatricesIP(ZZ, Zsum);
- } // end for (k)
-
- // Ignore the non-varying parameters
- for (int i = 0; i < nVaryingC; ++i)
- for (int j = 0; j < nVaryingC; ++j)
- Z[i][j] = Zsum[i+_nNonvaryingC][j+_nNonvaryingC];
- } // end if
-
- if (nVaryingA > 0 && nVaryingB > 0)
- {
- for (int n = 0; n < Wn.count(); ++n) makeZeroMatrix(Wn[n]);
-
- Matrix<double> W(_paramDimensionA, _paramDimensionB);
-
- for (int k = 0; k < _nMeasurements; ++k)
- {
- int const n = _jointIndexW[k];
- if (n >= 0)
- {
- int const i0 = _jointNonzerosW[n].first;
- int const j0 = _jointNonzerosW[n].second;
-
- multiply_At_B(Ak[k], Bk[k], W);
- addMatricesIP(W, Wn[n]);
- } // end if
- } // end for (k)
- } // end if
-
- if (nVaryingA > 0 && nVaryingC > 0)
- {
- Matrix<double> XX(_paramDimensionA, _paramDimensionC);
-
- makeZeroMatrix(X);
-
- for (int k = 0; k < _nMeasurements; ++k)
- {
- int const i = _correspondingParamA[k] - _nNonvaryingA;
- // Ignore the non-varying parameters
- if (i < 0) continue;
-
- multiply_At_B(Ak[k], Ck[k], XX);
-
- for (int r = 0; r < _paramDimensionA; ++r)
- for (int c = 0; c < nVaryingC; ++c)
- X[r+i*_paramDimensionA][c] += XX[r][c+_nNonvaryingC];
- } // end for (k)
- } // end if
-
- if (nVaryingB > 0 && nVaryingC > 0)
- {
- Matrix<double> YY(_paramDimensionB, _paramDimensionC);
-
- makeZeroMatrix(Y);
-
- for (int k = 0; k < _nMeasurements; ++k)
- {
- int const j = _correspondingParamB[k] - _nNonvaryingB;
- // Ignore the non-varying parameters
- if (j < 0) continue;
-
- multiply_At_B(Bk[k], Ck[k], YY);
-
- for (int r = 0; r < _paramDimensionB; ++r)
- for (int c = 0; c < nVaryingC; ++c)
- Y[r+j*_paramDimensionB][c] += YY[r][c+_nNonvaryingC];
- } // end for (k)
- } // end if
-
- if (currentIteration == 0)
- {
- // Initialize lambda as tau*max(JtJ[i][i])
- double maxEl = -1e30;
- if (nVaryingA > 0)
- {
- for (int i = 0; i < nVaryingA; ++i)
- for (int l = 0; l < _paramDimensionA; ++l)
- maxEl = std::max(maxEl, Ui[i][l][l]);
- }
- if (nVaryingB > 0)
- {
- for (int j = 0; j < nVaryingB; ++j)
- for (int l = 0; l < _paramDimensionB; ++l)
- maxEl = std::max(maxEl, Vj[j][l][l]);
- }
- if (nVaryingC > 0)
- {
- for (int l = 0; l < nVaryingC; ++l)
- maxEl = std::max(maxEl, Z[l][l]);
- }
-
- lambda = tau * maxEl;
- if (optimizerVerbosenessLevel >= 2)
- cout << "SparseLevenbergOptimizer: initial lambda = " << lambda << endl;
- } // end if (currentIteration == 0)
- } // end if (computeDerivatives)
-
- for (int i = 0; i < nVaryingA; ++i)
- {
- for (int l = 0; l < _paramDimensionA; ++l) diagUi[i][l] = Ui[i][l][l];
- } // end for (i)
-
- for (int j = 0; j < nVaryingB; ++j)
- {
- for (int l = 0; l < _paramDimensionB; ++l) diagVj[j][l] = Vj[j][l][l];
- } // end for (j)
-
- for (int l = 0; l < nVaryingC; ++l) diagZ[l] = Z[l][l];
-
- // Augment the diagonals with lambda (either by the standard additive update or by multiplication).
-#if !defined(USE_MULTIPLICATIVE_UPDATE)
- for (int i = 0; i < nVaryingA; ++i)
- for (unsigned l = 0; l < _paramDimensionA; ++l)
- Ui[i][l][l] += lambda;
-
- for (int j = 0; j < nVaryingB; ++j)
- for (unsigned l = 0; l < _paramDimensionB; ++l)
- Vj[j][l][l] += lambda;
-
- for (unsigned l = 0; l < nVaryingC; ++l)
- Z[l][l] += lambda;
-#else
- for (int i = 0; i < nVaryingA; ++i)
- for (unsigned l = 0; l < _paramDimensionA; ++l)
- Ui[i][l][l] = std::max(Ui[i][l][l] * (1.0 + lambda), 1e-15);
-
- for (int j = 0; j < nVaryingB; ++j)
- for (unsigned l = 0; l < _paramDimensionB; ++l)
- Vj[j][l][l] = std::max(Vj[j][l][l] * (1.0 + lambda), 1e-15);
-
- for (unsigned l = 0; l < nVaryingC; ++l)
- Z[l][l] = std::max(Z[l][l] * (1.0 + lambda), 1e-15);
-#endif
-
- this->fillSparseJtJ(Ui, Vj, Wn, Z, X, Y);
-
- bool success = true;
- double rho = 0.0;
- {
- int const nCols = _JtJ_Parent.size();
- int const nnz = _JtJ.getNonzeroCount();
- int const lnz = _JtJ_Lp.back();
-
- vector<int> Li(lnz);
- vector<double> Lx(lnz);
- vector<double> D(nCols), Y(nCols);
- vector<int> workPattern(nCols), workFlag(nCols);
-
- int * colStarts = (int *)_JtJ.getColumnStarts();
- int * rowIdxs = (int *)_JtJ.getRowIndices();
- double * values = _JtJ.getValues();
-
- int const d = ldl_numeric(nCols, colStarts, rowIdxs, values,
- &_JtJ_Lp[0], &_JtJ_Parent[0], &_JtJ_Lnz[0],
- &Li[0], &Lx[0], &D[0],
- &Y[0], &workPattern[0], &workFlag[0],
- NULL, NULL);
-
- if (d == nCols)
- {
- ldl_perm(nCols, &deltaPerm[0], &Jt_e[0], &_perm_JtJ[0]);
- ldl_lsolve(nCols, &deltaPerm[0], &_JtJ_Lp[0], &Li[0], &Lx[0]);
- ldl_dsolve(nCols, &deltaPerm[0], &D[0]);
- ldl_ltsolve(nCols, &deltaPerm[0], &_JtJ_Lp[0], &Li[0], &Lx[0]);
- ldl_permt(nCols, &delta[0], &deltaPerm[0], &_perm_JtJ[0]);
- }
- else
- {
- if (optimizerVerbosenessLevel >= 2)
- cout << "SparseLevenbergOptimizer: LDL decomposition failed. Increasing lambda." << endl;
- success = false;
- }
- }
-
- if (success)
- {
- double const deltaSqrLength = sqrNorm_L2(delta);
-
- if (optimizerVerbosenessLevel >= 2)
- cout << "SparseLevenbergOptimizer: ||delta||^2 = " << deltaSqrLength << endl;
-
- double const paramLength = this->getParameterLength();
- if (this->applyUpdateStoppingCriteria(paramLength, sqrt(deltaSqrLength)))
- {
- status = LEVENBERG_OPTIMIZER_SMALL_UPDATE;
- goto end;
- }
-
- // Copy the updates from delta to the respective arrays
- int pos = 0;
-
- for (int i = 0; i < _nNonvaryingA; ++i) makeZeroVector(deltaAi[i]);
- for (int i = _nNonvaryingA; i < _nParametersA; ++i)
- for (int l = 0; l < _paramDimensionA; ++l, ++pos)
- deltaAi[i][l] = delta[pos];
-
- for (int j = 0; j < _nNonvaryingB; ++j) makeZeroVector(deltaBj[j]);
- for (int j = _nNonvaryingB; j < _nParametersB; ++j)
- for (int l = 0; l < _paramDimensionB; ++l, ++pos)
- deltaBj[j][l] = delta[pos];
-
- makeZeroVector(deltaC);
- for (int l = _nNonvaryingC; l < _paramDimensionC; ++l, ++pos)
- deltaC[l] = delta[pos];
-
- saveAllParameters();
- if (nVaryingA > 0) updateParametersA(deltaAi);
- if (nVaryingB > 0) updateParametersB(deltaBj);
- if (nVaryingC > 0) updateParametersC(deltaC);
-
- this->evalResidual(residuals2);
- for (int k = 0; k < _nMeasurements; ++k)
- scaleVectorIP(weights[k], residuals2[k]);
-
- double const newErr = squaredResidual(residuals2);
- rho = err - newErr;
- if (optimizerVerbosenessLevel >= 2)
- cout << "SparseLevenbergOptimizer: |new residual|^2 = " << newErr << endl;
-
-#if !defined(USE_MULTIPLICATIVE_UPDATE)
- double const denom1 = lambda * deltaSqrLength;
-#else
- double denom1 = 0.0f;
- for (int i = _nNonvaryingA; i < _nParametersA; ++i)
- for (int l = 0; l < _paramDimensionA; ++l)
- denom1 += deltaAi[i][l] * deltaAi[i][l] * diagUi[i-_nNonvaryingA][l];
-
- for (int j = _nNonvaryingB; j < _nParametersB; ++j)
- for (int l = 0; l < _paramDimensionB; ++l)
- denom1 += deltaBj[j][l] * deltaBj[j][l] * diagVj[j-_nNonvaryingB][l];
-
- for (int l = _nNonvaryingC; l < _paramDimensionC; ++l)
- denom1 += deltaC[l] * deltaC[l] * diagZ[l-_nNonvaryingC];
-
- denom1 *= lambda;
-#endif
- double const denom2 = innerProduct(delta, Jt_e);
- rho = rho / (denom1 + denom2);
- if (optimizerVerbosenessLevel >= 2)
- cout << "SparseLevenbergOptimizer: rho = " << rho
- << " denom1 = " << denom1 << " denom2 = " << denom2 << endl;
- } // end if (success)
-
- if (success && rho > 0)
- {
- if (optimizerVerbosenessLevel >= 2)
- cout << "SparseLevenbergOptimizer: Improved solution - decreasing lambda." << endl;
- // Improvement in the new solution
- decreaseLambda(rho);
- computeDerivatives = true;
- }
- else
- {
- if (optimizerVerbosenessLevel >= 2)
- cout << "SparseLevenbergOptimizer: Inferior solution - increasing lambda." << endl;
- restoreAllParameters();
- increaseLambda();
- computeDerivatives = false;
-
- // Restore diagonal elements in Ui, Vj and Z.
- for (int i = 0; i < nVaryingA; ++i)
- {
- for (int l = 0; l < _paramDimensionA; ++l) Ui[i][l][l] = diagUi[i][l];
- } // end for (i)
-
- for (int j = 0; j < nVaryingB; ++j)
- {
- for (int l = 0; l < _paramDimensionB; ++l) Vj[j][l][l] = diagVj[j][l];
- } // end for (j)
-
- for (int l = 0; l < nVaryingC; ++l) Z[l][l] = diagZ[l];
- } // end if
- } // end for
-
- end:;
- if (optimizerVerbosenessLevel >= 2)
- cout << "Leaving SparseLevenbergOptimizer::minimize()." << endl;
- } // end SparseLevenbergOptimizer::minimize()
-
-#endif // defined(V3DLIB_ENABLE_SUITESPARSE)
-
-} // end namespace V3D
diff --git a/extern/libmv/third_party/ssba/Math/v3d_optimization.h b/extern/libmv/third_party/ssba/Math/v3d_optimization.h
deleted file mode 100644
index 27d2e12287f..00000000000
--- a/extern/libmv/third_party/ssba/Math/v3d_optimization.h
+++ /dev/null
@@ -1,273 +0,0 @@
-// -*- C++ -*-
-/*
-Copyright (c) 2008 University of North Carolina at Chapel Hill
-
-This file is part of SSBA (Simple Sparse Bundle Adjustment).
-
-SSBA 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 3 of the License, or (at your option) any
-later version.
-
-SSBA is distributed in the hope that 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.
-
-You should have received a copy of the GNU Lesser General Public License along
-with SSBA. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef V3D_OPTIMIZATION_H
-#define V3D_OPTIMIZATION_H
-
-#include "Math/v3d_linear.h"
-#include "Math/v3d_mathutilities.h"
-
-#include <vector>
-#include <iostream>
-
-namespace V3D
-{
-
- enum
- {
- LEVENBERG_OPTIMIZER_TIMEOUT = 0,
- LEVENBERG_OPTIMIZER_SMALL_UPDATE = 1,
- LEVENBERG_OPTIMIZER_CONVERGED = 2
- };
-
- extern int optimizerVerbosenessLevel;
-
- struct LevenbergOptimizerCommon
- {
- LevenbergOptimizerCommon()
- : status(LEVENBERG_OPTIMIZER_TIMEOUT), currentIteration(0), maxIterations(50),
- tau(1e-3), lambda(1e-3),
- gradientThreshold(1e-10), updateThreshold(1e-10),
- _nu(2.0)
- { }
- virtual ~LevenbergOptimizerCommon() {}
-
- // See Madsen et al., "Methods for non-linear least squares problems."
- virtual void increaseLambda()
- {
- lambda *= _nu; _nu *= 2.0;
- }
-
- virtual void decreaseLambda(double const rho)
- {
- double const r = 2*rho - 1.0;
- lambda *= std::max(1.0/3.0, 1 - r*r*r);
- if (lambda < 1e-10) lambda = 1e-10;
- _nu = 2;
- }
-
- bool applyGradientStoppingCriteria(double maxGradient) const
- {
- return maxGradient < gradientThreshold;
- }
-
- bool applyUpdateStoppingCriteria(double paramLength, double updateLength) const
- {
- return updateLength < updateThreshold * (paramLength + updateThreshold);
- }
-
- int status;
- int currentIteration, maxIterations;
- double tau, lambda;
- double gradientThreshold, updateThreshold;
-
- protected:
- double _nu;
- }; // end struct LevenbergOptimizerCommon
-
-# if defined(V3DLIB_ENABLE_SUITESPARSE)
-
- struct SparseLevenbergOptimizer : public LevenbergOptimizerCommon
- {
- SparseLevenbergOptimizer(int measurementDimension,
- int nParametersA, int paramDimensionA,
- int nParametersB, int paramDimensionB,
- int paramDimensionC,
- std::vector<int> const& correspondingParamA,
- std::vector<int> const& correspondingParamB)
- : LevenbergOptimizerCommon(),
- _nMeasurements(correspondingParamA.size()),
- _measurementDimension(measurementDimension),
- _nParametersA(nParametersA), _paramDimensionA(paramDimensionA),
- _nParametersB(nParametersB), _paramDimensionB(paramDimensionB),
- _paramDimensionC(paramDimensionC),
- _nNonvaryingA(0), _nNonvaryingB(0), _nNonvaryingC(0),
- _correspondingParamA(correspondingParamA),
- _correspondingParamB(correspondingParamB)
- {
- assert(correspondingParamA.size() == correspondingParamB.size());
- }
-
- ~SparseLevenbergOptimizer() { }
-
- void setNonvaryingCounts(int nNonvaryingA, int nNonvaryingB, int nNonvaryingC)
- {
- _nNonvaryingA = nNonvaryingA;
- _nNonvaryingB = nNonvaryingB;
- _nNonvaryingC = nNonvaryingC;
- }
-
- void getNonvaryingCounts(int& nNonvaryingA, int& nNonvaryingB, int& nNonvaryingC) const
- {
- nNonvaryingA = _nNonvaryingA;
- nNonvaryingB = _nNonvaryingB;
- nNonvaryingC = _nNonvaryingC;
- }
-
- void minimize();
-
- virtual void evalResidual(VectorArray<double>& residuals) = 0;
-
- virtual void fillWeights(VectorArray<double> const& residuals, Vector<double>& w)
- {
- (void)residuals;
- std::fill(w.begin(), w.end(), 1.0);
- }
-
- void fillAllJacobians(Vector<double> const& w,
- MatrixArray<double>& Ak,
- MatrixArray<double>& Bk,
- MatrixArray<double>& Ck)
- {
- int const nVaryingA = _nParametersA - _nNonvaryingA;
- int const nVaryingB = _nParametersB - _nNonvaryingB;
- int const nVaryingC = _paramDimensionC - _nNonvaryingC;
-
- for (unsigned k = 0; k < _nMeasurements; ++k)
- {
- int const i = _correspondingParamA[k];
- int const j = _correspondingParamB[k];
-
- if (i < _nNonvaryingA && j < _nNonvaryingB) continue;
-
- fillJacobians(Ak[k], Bk[k], Ck[k], i, j, k);
- } // end for (k)
-
- if (nVaryingA > 0)
- {
- for (unsigned k = 0; k < _nMeasurements; ++k)
- scaleMatrixIP(w[k], Ak[k]);
- }
- if (nVaryingB > 0)
- {
- for (unsigned k = 0; k < _nMeasurements; ++k)
- scaleMatrixIP(w[k], Bk[k]);
- }
- if (nVaryingC > 0)
- {
- for (unsigned k = 0; k < _nMeasurements; ++k)
- scaleMatrixIP(w[k], Ck[k]);
- }
- } // end fillAllJacobians()
-
- virtual void setupJacobianGathering() { }
-
- virtual void fillJacobians(Matrix<double>& Ak, Matrix<double>& Bk, Matrix<double>& Ck,
- int i, int j, int k) = 0;
-
- virtual double getParameterLength() const = 0;
-
- virtual void updateParametersA(VectorArray<double> const& deltaAi) = 0;
- virtual void updateParametersB(VectorArray<double> const& deltaBj) = 0;
- virtual void updateParametersC(Vector<double> const& deltaC) = 0;
- virtual void saveAllParameters() = 0;
- virtual void restoreAllParameters() = 0;
-
- int currentIteration, maxIterations;
-
- protected:
- void serializeNonZerosJtJ(std::vector<std::pair<int, int> >& dst) const;
- void setupSparseJtJ();
- void fillSparseJtJ(MatrixArray<double> const& Ui, MatrixArray<double> const& Vj, MatrixArray<double> const& Wk,
- Matrix<double> const& Z, Matrix<double> const& X, Matrix<double> const& Y);
-
- int const _nMeasurements, _measurementDimension;
- int const _nParametersA, _paramDimensionA;
- int const _nParametersB, _paramDimensionB;
- int const _paramDimensionC;
-
- int _nNonvaryingA, _nNonvaryingB, _nNonvaryingC;
-
- std::vector<int> const& _correspondingParamA;
- std::vector<int> const& _correspondingParamB;
-
- std::vector<pair<int, int> > _jointNonzerosW;
- std::vector<int> _jointIndexW;
-
- std::vector<int> _JtJ_Lp, _JtJ_Parent, _JtJ_Lnz;
- std::vector<int> _perm_JtJ, _invPerm_JtJ;
-
- CCS_Matrix<double> _JtJ;
- }; // end struct SparseLevenbergOptimizer
-
- struct StdSparseLevenbergOptimizer : public SparseLevenbergOptimizer
- {
- StdSparseLevenbergOptimizer(int measurementDimension,
- int nParametersA, int paramDimensionA,
- int nParametersB, int paramDimensionB,
- int paramDimensionC,
- std::vector<int> const& correspondingParamA,
- std::vector<int> const& correspondingParamB)
- : SparseLevenbergOptimizer(measurementDimension, nParametersA, paramDimensionA,
- nParametersB, paramDimensionB, paramDimensionC,
- correspondingParamA, correspondingParamB),
- curParametersA(nParametersA, paramDimensionA), savedParametersA(nParametersA, paramDimensionA),
- curParametersB(nParametersB, paramDimensionB), savedParametersB(nParametersB, paramDimensionB),
- curParametersC(paramDimensionC), savedParametersC(paramDimensionC)
- { }
-
- virtual double getParameterLength() const
- {
- double res = 0.0;
- for (int i = 0; i < _nParametersA; ++i) res += sqrNorm_L2(curParametersA[i]);
- for (int j = 0; j < _nParametersB; ++j) res += sqrNorm_L2(curParametersB[j]);
- res += sqrNorm_L2(curParametersC);
- return sqrt(res);
- }
-
- virtual void updateParametersA(VectorArray<double> const& deltaAi)
- {
- for (int i = 0; i < _nParametersA; ++i) addVectors(deltaAi[i], curParametersA[i], curParametersA[i]);
- }
-
- virtual void updateParametersB(VectorArray<double> const& deltaBj)
- {
- for (int j = 0; j < _nParametersB; ++j) addVectors(deltaBj[j], curParametersB[j], curParametersB[j]);
- }
-
- virtual void updateParametersC(Vector<double> const& deltaC)
- {
- addVectors(deltaC, curParametersC, curParametersC);
- }
-
- virtual void saveAllParameters()
- {
- for (int i = 0; i < _nParametersA; ++i) savedParametersA[i] = curParametersA[i];
- for (int j = 0; j < _nParametersB; ++j) savedParametersB[j] = curParametersB[j];
- savedParametersC = curParametersC;
- }
-
- virtual void restoreAllParameters()
- {
- for (int i = 0; i < _nParametersA; ++i) curParametersA[i] = savedParametersA[i];
- for (int j = 0; j < _nParametersB; ++j) curParametersB[j] = savedParametersB[j];
- curParametersC = savedParametersC;
- }
-
- VectorArray<double> curParametersA, savedParametersA;
- VectorArray<double> curParametersB, savedParametersB;
- Vector<double> curParametersC, savedParametersC;
- }; // end struct StdSparseLevenbergOptimizer
-
-# endif
-
-} // end namespace V3D
-
-#endif
diff --git a/extern/libmv/third_party/ssba/README.TXT b/extern/libmv/third_party/ssba/README.TXT
deleted file mode 100644
index 734962b1df8..00000000000
--- a/extern/libmv/third_party/ssba/README.TXT
+++ /dev/null
@@ -1,92 +0,0 @@
-Description
-
-This is an implementation of a sparse Levenberg-Marquardt optimization
-procedure and several bundle adjustment modules based on it. There are three
-versions of bundle adjustment:
-1) Pure metric adjustment. Camera poses have 6 dof and 3D points have 3 dof.
-2) Common, but adjustable intrinsic and distortion parameters. This is useful,
- if the set of images are taken with the same camera under constant zoom
- settings.
-3) Variable intrinsics and distortion parameters for each view. This addresses
- the "community photo collection" setting, where each image is captured with
- a different camera and/or with varying zoom setting.
-
-There are two demo applications in the Apps directory, bundle_common and
-bundle_varying, which correspond to item 2) and 3) above.
-
-The input data file for both applications is a text file with the following
-numerical values:
-
-First, the number of 3D points, views and 2D measurements:
-<M> <N> <K>
-Then, the values of the intrinsic matrix
- [ fx skew cx ]
-K = [ 0 fy cy ]
- [ 0 0 1 ],
-and the distortion parameters according to the convention of the Bouget
-toolbox:
-
- <fx> <skew> <cx> <fy> <cy> <k1> <k2> <p1> <p2>
-
-For the bundle_varying application this is given <N> times, one for each
-camera/view.
-Then the <M> 3D point positions are given:
-
- <point-id> <X> <Y> <Z>
-
-Note: the point-ids need not to be exactly from 0 to M-1, any (unique) ids
-will do.
-The camera poses are given subsequently:
-
- <view-id> <12 entries of the RT matrix>
-
-There is a lot of confusion how to specify the orientation of cameras. We use
-projection matrix notation, i.e. P = K [R|T], and a 3D point X in world
-coordinates is transformed into the camera coordinate system by XX=R*X+T.
-
-Finally, the <K> 2d image measurements (given in pixels) are provided:
-
- <view-id> <point-id> <x> <y> 1
-
-See the example in the Dataset folder.
-
-
-Performance
-
-This software is able to perform successful loop closing for a video sequence
-containing 1745 views, 37920 3D points and 627228 image measurements in about
-16min on a 2.2 GHz Core 2. The footprint in memory was <700MB.
-
-
-Requirements
-
-Solving the augmented normal equation in the LM optimizer is done with LDL, a
-Cholsky like decomposition method for sparse matrices (see
-http://www.cise.ufl.edu/research/sparse/ldl). The appropriate column
-reordering is done with COLAMD (see
-http://www.cise.ufl.edu/research/sparse/colamd). Both packages are licensed
-under the GNU LGPL.
-
-This software was developed under Linux, but should compile equally well on
-other operating systems.
-
--Christopher Zach (cmzach@cs.unc.edu)
-
-/*
-Copyright (c) 2008 University of North Carolina at Chapel Hill
-
-This file is part of SSBA (Simple Sparse Bundle Adjustment).
-
-SSBA 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 3 of the License, or (at your option) any
-later version.
-
-SSBA is distributed in the hope that 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.
-
-You should have received a copy of the GNU Lesser General Public License along
-with SSBA. If not, see <http://www.gnu.org/licenses/>.
-*/
diff --git a/extern/libmv/third_party/ssba/README.libmv b/extern/libmv/third_party/ssba/README.libmv
deleted file mode 100644
index 45e0a31f6fc..00000000000
--- a/extern/libmv/third_party/ssba/README.libmv
+++ /dev/null
@@ -1,23 +0,0 @@
-Project: SSBA
-URL: http://www.cs.unc.edu/~cmzach/opensource.html
-License: LGPL3
-Upstream version: 1.0
-
-Local modifications:
-
- * Added
- SET(CMAKE_CXX_FLAGS "")
- to CMakeLists.txt to prevent warnings from being treated as errors.
- * Fixed "unused variable" in the header files. Warnings in the cpps files
- are still there.
- * Fixed a bug in CameraMatrix::opticalAxis() in file
- Geometry/v3d_cameramatrix.h
- * Deleted the Dataset directory.
- * Added '#include <string>' to ssba/Apps/bundle_common.cpp and
- ssba/Apps/bundle_varying.cpp to stop undefined references to strcmp
- * Removed unnecessary elements from the CMakeLists.txt file, including the
- obsoleted local_config.cmake and friends.
- * Added a virtual destructor to V3D::LevenbergOptimizerCommon in
- Math/v3d_optimization.h
- * Added /EHsc WIN32-specific flag to CMakeLists.txt
- * Remove unused variable Vector3d np in bundle_common.cpp and bundle_varying (in main() function).
diff --git a/extern/lzo/minilzo/COPYING b/extern/lzo/minilzo/COPYING
index 5ee49f42e91..d159169d105 100644
--- a/extern/lzo/minilzo/COPYING
+++ b/extern/lzo/minilzo/COPYING
@@ -1,8 +1,8 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
+the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
@@ -55,7 +55,7 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
-
+
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
@@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
-
+
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
-
+
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
-
+
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@@ -278,7 +278,7 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
-
+
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
@@ -291,7 +291,7 @@ convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
- Copyright (C) 19yy <name of author>
+ Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -303,17 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
- Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
@@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
+library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
diff --git a/extern/lzo/minilzo/README.LZO b/extern/lzo/minilzo/README.LZO
index 3700f28e310..058eace70a0 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.03
- Date : 30 Apr 2008
+ Version : 2.06
+ Date : 12 Aug 2011
I've created miniLZO for projects where it is inconvenient to
include (or require) the full LZO source code just because you
@@ -24,10 +24,10 @@
To use miniLZO just copy these files into your source directory, add
minilzo.c to your Makefile and #include minilzo.h from your program.
- Note: you also must distribute this file (`README.LZO') with your project.
+ Note: you also must distribute this file ('README.LZO') with your project.
- minilzo.o compiles to about 6 kB (using gcc or Visual C on a i386), and
- the sources are about 30 kB when packed with zip - so there's no more
+ minilzo.o compiles to about 6 KiB (using gcc or Visual C on an i386), and
+ the sources are about 30 KiB when packed with zip - so there's no more
excuse that your application doesn't support data compression :-)
For more information, documentation, example programs and other support
@@ -49,15 +49,15 @@
out-of-the-box on most machines.
If you are running on a very unusual architecture and lzo_init() fails then
- you should first recompile with `-DLZO_DEBUG' to see what causes the failure.
- The most probable case is something like `sizeof(char *) != sizeof(long)'.
+ you should first recompile with '-DLZO_DEBUG' to see what causes the failure.
+ The most probable case is something like 'sizeof(void *) != sizeof(size_t)'.
After identifying the problem you can compile by adding some defines
- like `-DSIZEOF_CHAR_P=8' to your Makefile.
+ like '-DSIZEOF_VOID_P=8' to your Makefile.
The best solution is (of course) using Autoconf - if your project uses
- Autoconf anyway just add `-DMINILZO_HAVE_CONFIG_H' to your compiler
+ Autoconf anyway just add '-DMINILZO_HAVE_CONFIG_H' to your compiler
flags when compiling minilzo.c. See the LZO distribution for an example
- how to set up configure.in.
+ how to set up configure.ac.
Appendix B: list of public functions available in miniLZO
@@ -87,7 +87,7 @@
lzo_memset()
- Appendix C: suggested macros for `configure.in' when using Autoconf
+ Appendix C: suggested macros for 'configure.ac' when using Autoconf
-------------------------------------------------------------------
Checks for typedefs and structures
AC_CHECK_TYPE(ptrdiff_t,long)
@@ -110,8 +110,9 @@
Appendix D: Copyright
---------------------
- LZO and miniLZO are Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003, 2004, 2005, 2006, 2007, 2008 Markus Franz Xaver Johannes Oberhumer
+ 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 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 cc437f1ebfe..23c6ca93fcc 100644
--- a/extern/lzo/minilzo/lzoconf.h
+++ b/extern/lzo/minilzo/lzoconf.h
@@ -1,7 +1,10 @@
-/* lzoconf.h -- configuration for the LZO real-time data compression library
+/* lzoconf.h -- configuration of the LZO data compression library
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
@@ -39,11 +42,11 @@
#ifndef __LZOCONF_H_INCLUDED
-#define __LZOCONF_H_INCLUDED
+#define __LZOCONF_H_INCLUDED 1
-#define LZO_VERSION 0x2030
-#define LZO_VERSION_STRING "2.03"
-#define LZO_VERSION_DATE "Apr 30 2008"
+#define LZO_VERSION 0x2060
+#define LZO_VERSION_STRING "2.06"
+#define LZO_VERSION_DATE "Aug 12 2011"
/* internal Autoconf configuration file - only used when building LZO */
#if defined(LZO_HAVE_CONFIG_H)
@@ -157,6 +160,27 @@ extern "C" {
# 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)
# define lzo_xint lzo_uint
@@ -167,12 +191,12 @@ extern "C" {
/* 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
+# define __LZO_MMODEL /*empty*/
# elif defined(LZO_HAVE_MM_HUGE_PTR)
# define __LZO_MMODEL_HUGE 1
# define __LZO_MMODEL __huge
# else
-# define __LZO_MMODEL
+# define __LZO_MMODEL /*empty*/
# endif
#endif
@@ -184,12 +208,16 @@ extern "C" {
#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_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 *' */
+/* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */
#define lzo_byte unsigned char __LZO_MMODEL
typedef int lzo_bool;
@@ -215,10 +243,10 @@ typedef int lzo_bool;
/* DLL export information */
#if !defined(__LZO_EXPORT1)
-# define __LZO_EXPORT1
+# define __LZO_EXPORT1 /*empty*/
#endif
#if !defined(__LZO_EXPORT2)
-# define __LZO_EXPORT2
+# define __LZO_EXPORT2 /*empty*/
#endif
/* __cdecl calling convention for public C and assembly functions */
@@ -306,7 +334,7 @@ struct lzo_callback_t
*/
#define LZO_E_OK 0
#define LZO_E_ERROR (-1)
-#define LZO_E_OUT_OF_MEMORY (-2) /* [not used right now] */
+#define LZO_E_OUT_OF_MEMORY (-2) /* [lzo_alloc_func_t failure] */
#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */
#define LZO_E_INPUT_OVERRUN (-4)
#define LZO_E_OUTPUT_OVERRUN (-5)
@@ -314,6 +342,7 @@ struct lzo_callback_t
#define LZO_E_EOF_NOT_FOUND (-7)
#define LZO_E_INPUT_NOT_CONSUMED (-8)
#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */
+#define LZO_E_INVALID_ARGUMENT (-10)
#ifndef lzo_sizeof_dict_t
@@ -341,32 +370,32 @@ LZO_EXTERN(const lzo_charp) _lzo_version_date(void);
/* string functions */
LZO_EXTERN(int)
-lzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len);
+ lzo_memcmp(const lzo_voidp a, const lzo_voidp b, lzo_uint len);
LZO_EXTERN(lzo_voidp)
-lzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len);
+ lzo_memcpy(lzo_voidp dst, const lzo_voidp src, lzo_uint len);
LZO_EXTERN(lzo_voidp)
-lzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len);
+ lzo_memmove(lzo_voidp dst, const lzo_voidp src, lzo_uint len);
LZO_EXTERN(lzo_voidp)
-lzo_memset(lzo_voidp _s, int _c, lzo_uint _len);
+ lzo_memset(lzo_voidp buf, int c, lzo_uint len);
/* checksum functions */
LZO_EXTERN(lzo_uint32)
-lzo_adler32(lzo_uint32 _adler, const lzo_bytep _buf, lzo_uint _len);
+ 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_crc32(lzo_uint32 c, const lzo_bytep buf, lzo_uint len);
LZO_EXTERN(const lzo_uint32p)
-lzo_get_crc32_table(void);
+ 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_uint32 u32; long l; } lzo_align_t;
+typedef union { void *vp; lzo_bytep bp; lzo_uint u; lzo_uint32 u32; unsigned long l; } 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 _ptr, lzo_uint _size);
-#define LZO_PTR_ALIGN_UP(_ptr,_size) \
- ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size)))
+/* 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);
+#define LZO_PTR_ALIGN_UP(p,size) \
+ ((p) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(p),(lzo_uint)(size)))
/***********************************************************************
@@ -395,8 +424,8 @@ LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp _ptr, lzo_uint _size);
# define __LZO_WIN 1
#endif
-#define __LZO_CMODEL
-#define __LZO_DMODEL
+#define __LZO_CMODEL /*empty*/
+#define __LZO_DMODEL /*empty*/
#define __LZO_ENTRY __LZO_CDECL
#define LZO_EXTERN_CDECL LZO_EXTERN
#define LZO_ALIGN LZO_PTR_ALIGN_UP
diff --git a/extern/lzo/minilzo/lzodefs.h b/extern/lzo/minilzo/lzodefs.h
index 180563723e5..0e40e332a8d 100644
--- a/extern/lzo/minilzo/lzodefs.h
+++ b/extern/lzo/minilzo/lzodefs.h
@@ -2,6 +2,9 @@
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
@@ -121,7 +124,7 @@
#endif
#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL)
# define ptrdiff_t long
-# define _PTRDIFF_T_DEFINED
+# define _PTRDIFF_T_DEFINED 1
#endif
#if (UINT_MAX == LZO_0xffffL)
# undef __LZO_RENAME_A
@@ -265,9 +268,9 @@
# define LZO_EXTERN_C extern
#endif
#if !defined(__LZO_OS_OVERRIDE)
-#if defined(LZO_OS_FREESTANDING)
+#if (LZO_OS_FREESTANDING)
# define LZO_INFO_OS "freestanding"
-#elif defined(LZO_OS_EMBEDDED)
+#elif (LZO_OS_EMBEDDED)
# define LZO_INFO_OS "embedded"
#elif 1 && defined(__IAR_SYSTEMS_ICC__)
# define LZO_OS_EMBEDDED 1
@@ -476,12 +479,27 @@
# define LZO_CC_PELLESC 1
# define LZO_INFO_CC "Pelles C"
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__)
-#elif defined(__llvm__) && defined(__GNUC__) && defined(__VERSION__)
-# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
-# define LZO_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+#elif defined(__clang__) && defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+# if defined(__GNUC_PATCHLEVEL__)
+# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+# else
+# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+# endif
+# if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
+# define LZO_CC_CLANG_CLANG (__clang_major__ * 0x10000L + __clang_minor__ * 0x100 + __clang_patchlevel__)
+# else
+# define LZO_CC_CLANG_CLANG 0x010000L
+# 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__)
# else
-# define LZO_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 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__)
@@ -502,6 +520,10 @@
# define LZO_CC_AZTECC 1
# define LZO_INFO_CC "Aztec C"
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__)
+#elif defined(__CODEGEARC__)
+# define LZO_CC_CODEGEARC 1
+# define LZO_INFO_CC "CodeGear C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CODEGEARC__)
#elif defined(__BORLANDC__)
# define LZO_CC_BORLANDC 1
# define LZO_INFO_CC "Borland C"
@@ -632,7 +654,7 @@
#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER)
# error "LZO_CC_MSC: _MSC_FULL_VER is not defined"
#endif
-#if !defined(__LZO_ARCH_OVERRIDE) && !defined(LZO_ARCH_GENERIC) && defined(_CRAY)
+#if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY)
# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY)
# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E)
# define LZO_ARCH_CRAY_MPP 1
@@ -642,7 +664,7 @@
# endif
#endif
#if !defined(__LZO_ARCH_OVERRIDE)
-#if defined(LZO_ARCH_GENERIC)
+#if (LZO_ARCH_GENERIC)
# define LZO_INFO_ARCH "generic"
#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
# define LZO_ARCH_I086 1
@@ -677,6 +699,9 @@
#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__)
# define LZO_ARCH_AVR 1
# define LZO_INFO_ARCH "avr"
+#elif defined(__avr32__) || defined(__AVR32__)
+# define LZO_ARCH_AVR32 1
+# define LZO_INFO_ARCH "avr32"
#elif defined(__bfin__)
# define LZO_ARCH_BLACKFIN 1
# define LZO_INFO_ARCH "blackfin"
@@ -799,10 +824,10 @@
# define LZO_ARCH_I086PM 1
# define LZO_ARCH_IA16PM 1
#endif
-#if defined(LZO_ARCH_ARM_THUMB) && !defined(LZO_ARCH_ARM)
+#if (LZO_ARCH_ARM_THUMB) && !(LZO_ARCH_ARM)
# error "this should not happen"
#endif
-#if defined(LZO_ARCH_I086PM) && !defined(LZO_ARCH_I086)
+#if (LZO_ARCH_I086PM) && !(LZO_ARCH_I086)
# error "this should not happen"
#endif
#if (LZO_ARCH_I086)
@@ -875,7 +900,7 @@
#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295))
# undef LZO_HAVE_MM_HUGE_ARRAY
#endif
-#if (LZO_ARCH_I086PM) && !defined(LZO_HAVE_MM_HUGE_PTR)
+#if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR)
# if (LZO_OS_DOS16)
# error "this should not happen"
# elif (LZO_CC_ZORTECHC)
@@ -1091,7 +1116,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_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#elif (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
@@ -1125,12 +1150,12 @@ extern "C" {
#endif
#endif
#endif
-#if defined(__cplusplus) && defined(LZO_CC_GNUC)
+#if defined(__cplusplus) && (LZO_CC_GNUC)
# if (LZO_CC_GNUC < 0x020800ul)
# undef LZO_SIZEOF_LONG_LONG
# endif
#endif
-#if defined(LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG)
+#if (LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG)
# undef LZO_SIZEOF_LONG_LONG
#endif
#if !defined(LZO_SIZEOF_VOID_P)
@@ -1229,15 +1254,17 @@ extern "C" {
# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T
#endif
#endif
-#if defined(LZO_ABI_NEUTRAL_ENDIAN)
+#if (LZO_ABI_NEUTRAL_ENDIAN)
# undef LZO_ABI_BIG_ENDIAN
# undef LZO_ABI_LITTLE_ENDIAN
-#elif !defined(LZO_ABI_BIG_ENDIAN) && !defined(LZO_ABI_LITTLE_ENDIAN)
+#elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN)
#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP)
# define LZO_ABI_BIG_ENDIAN 1
+#elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64)
+# 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_M68K || LZO_ARCH_S390)
+#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390)
# define LZO_ABI_BIG_ENDIAN 1
#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__)
# if (__LITTLE_ENDIAN__ == 1)
@@ -1259,14 +1286,14 @@ extern "C" {
# define LZO_ABI_LITTLE_ENDIAN 1
#endif
#endif
-#if defined(LZO_ABI_BIG_ENDIAN) && defined(LZO_ABI_LITTLE_ENDIAN)
+#if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN)
# error "this should not happen"
#endif
-#if defined(LZO_ABI_BIG_ENDIAN)
+#if (LZO_ABI_BIG_ENDIAN)
# define LZO_INFO_ABI_ENDIAN "be"
-#elif defined(LZO_ABI_LITTLE_ENDIAN)
+#elif (LZO_ABI_LITTLE_ENDIAN)
# define LZO_INFO_ABI_ENDIAN "le"
-#elif defined(LZO_ABI_NEUTRAL_ENDIAN)
+#elif (LZO_ABI_NEUTRAL_ENDIAN)
# define LZO_INFO_ABI_ENDIAN "neutral"
#endif
#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2)
@@ -1292,15 +1319,15 @@ extern "C" {
# define LZO_INFO_ABI_PM "ip32l64"
#endif
#if !defined(__LZO_LIBC_OVERRIDE)
-#if defined(LZO_LIBC_NAKED)
+#if (LZO_LIBC_NAKED)
# define LZO_INFO_LIBC "naked"
-#elif defined(LZO_LIBC_FREESTANDING)
+#elif (LZO_LIBC_FREESTANDING)
# define LZO_INFO_LIBC "freestanding"
-#elif defined(LZO_LIBC_MOSTLY_FREESTANDING)
+#elif (LZO_LIBC_MOSTLY_FREESTANDING)
# define LZO_INFO_LIBC "mfreestanding"
-#elif defined(LZO_LIBC_ISOC90)
+#elif (LZO_LIBC_ISOC90)
# define LZO_INFO_LIBC "isoc90"
-#elif defined(LZO_LIBC_ISOC99)
+#elif (LZO_LIBC_ISOC99)
# define LZO_INFO_LIBC "isoc99"
#elif defined(__dietlibc__)
# define LZO_LIBC_DIETLIBC 1
@@ -1332,22 +1359,24 @@ extern "C" {
#if !defined(__lzo_gnuc_extension__)
#if (LZO_CC_GNUC >= 0x020800ul)
# define __lzo_gnuc_extension__ __extension__
-#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
# define __lzo_gnuc_extension__ __extension__
#else
-# define __lzo_gnuc_extension__
+# 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_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+#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)
@@ -1358,7 +1387,7 @@ extern "C" {
# define __lzo_constructor __attribute__((__constructor__,__used__))
#elif (LZO_CC_GNUC >= 0x020700ul)
# define __lzo_constructor __attribute__((__constructor__))
-#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
# define __lzo_constructor __attribute__((__constructor__))
#endif
#endif
@@ -1370,14 +1399,14 @@ extern "C" {
# define __lzo_destructor __attribute__((__destructor__,__used__))
#elif (LZO_CC_GNUC >= 0x020700ul)
# define __lzo_destructor __attribute__((__destructor__))
-#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#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 defined(__lzo_HAVE_destructor) && !defined(__lzo_HAVE_constructor)
+#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor)
# error "this should not happen"
#endif
#if !defined(__lzo_inline)
@@ -1386,7 +1415,7 @@ extern "C" {
# define __lzo_inline inline
#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550))
# define __lzo_inline __inline
-#elif (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+#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
@@ -1396,6 +1425,8 @@ extern "C" {
# 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
@@ -1403,7 +1434,7 @@ extern "C" {
#if defined(__lzo_inline)
# define __lzo_HAVE_inline 1
#else
-# define __lzo_inline
+# define __lzo_inline /*empty*/
#endif
#if !defined(__lzo_forceinline)
#if (LZO_CC_GNUC >= 0x030200ul)
@@ -1412,16 +1443,18 @@ extern "C" {
# 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_LLVM || LZO_CC_PATHSCALE)
+#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__))
#endif
#endif
#if defined(__lzo_forceinline)
# define __lzo_HAVE_forceinline 1
#else
-# define __lzo_forceinline
+# define __lzo_forceinline /*empty*/
#endif
#if !defined(__lzo_noinline)
#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul)
@@ -1432,7 +1465,7 @@ extern "C" {
# define __lzo_noinline __declspec(noinline)
#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC)
# define __lzo_noinline __attribute__((__noinline__))
-#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#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)
@@ -1441,14 +1474,16 @@ extern "C" {
# else
# define __lzo_noinline __declspec(noinline)
# 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
+# define __lzo_noinline /*empty*/
#endif
-#if (defined(__lzo_HAVE_forceinline) || defined(__lzo_HAVE_noinline)) && !defined(__lzo_HAVE_inline)
+#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline)
# error "this should not happen"
#endif
#if !defined(__lzo_noreturn)
@@ -1458,7 +1493,7 @@ extern "C" {
# define __lzo_noreturn __declspec(noreturn)
#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC)
# define __lzo_noreturn __attribute__((__noreturn__))
-#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#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)
@@ -1467,16 +1502,16 @@ extern "C" {
#if defined(__lzo_noreturn)
# define __lzo_HAVE_noreturn 1
#else
-# define __lzo_noreturn
+# 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 >= 800) && LZO_CC_SYNTAX_GNUC)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 900) && LZO_CC_SYNTAX_GNUC)
# define __lzo_nothrow __attribute__((__nothrow__))
-#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#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)
@@ -1485,14 +1520,14 @@ extern "C" {
#if defined(__lzo_nothrow)
# define __lzo_HAVE_nothrow 1
#else
-# define __lzo_nothrow
+# 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_LLVM)
+#elif (LZO_CC_CLANG || LZO_CC_LLVM)
# define __lzo_restrict __restrict__
#elif (LZO_CC_MSC && (_MSC_VER >= 1400))
# define __lzo_restrict __restrict
@@ -1501,7 +1536,7 @@ extern "C" {
#if defined(__lzo_restrict)
# define __lzo_HAVE_restrict 1
#else
-# define __lzo_restrict
+# define __lzo_restrict /*empty*/
#endif
#if !defined(__lzo_likely) && !defined(__lzo_unlikely)
#if (LZO_CC_GNUC >= 0x030200ul)
@@ -1510,7 +1545,7 @@ extern "C" {
#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_LLVM || LZO_CC_PATHSCALE)
+#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
@@ -1530,7 +1565,7 @@ extern "C" {
# 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_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# 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
@@ -1549,7 +1584,7 @@ extern "C" {
# 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_LLVM)
+# 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
@@ -1564,7 +1599,7 @@ extern "C" {
#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_INTELC || LZO_CC_WATCOMC)
+# 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
@@ -1579,6 +1614,15 @@ extern "C" {
# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init
# 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)))))
+# 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)];
@@ -1607,7 +1651,7 @@ extern "C" {
# 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
+# 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
@@ -1648,24 +1692,24 @@ extern "C" {
# define __lzo_cdecl cdecl
#endif
#if !defined(__lzo_cdecl)
-# define __lzo_cdecl
+# define __lzo_cdecl /*empty*/
#endif
#if !defined(__lzo_cdecl_atexit)
-# define __lzo_cdecl_atexit
+# define __lzo_cdecl_atexit /*empty*/
#endif
#if !defined(__lzo_cdecl_main)
-# define __lzo_cdecl_main
+# define __lzo_cdecl_main /*empty*/
#endif
#if !defined(__lzo_cdecl_qsort)
-# define __lzo_cdecl_qsort
+# define __lzo_cdecl_qsort /*empty*/
#endif
#if !defined(__lzo_cdecl_sighandler)
-# define __lzo_cdecl_sighandler
+# define __lzo_cdecl_sighandler /*empty*/
#endif
#if !defined(__lzo_cdecl_va)
# define __lzo_cdecl_va __lzo_cdecl
#endif
-#if !defined(LZO_CFG_NO_WINDOWS_H)
+#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__)
@@ -1711,7 +1755,7 @@ extern "C" {
#elif (LZO_ARCH_POWERPC)
# define LZO_OPT_PREFER_PREINC 1
# define LZO_OPT_PREFER_PREDEC 1
-# if defined(LZO_ABI_BIG_ENDIAN)
+# if (LZO_ABI_BIG_ENDIAN)
# define LZO_OPT_UNALIGNED16 1
# define LZO_OPT_UNALIGNED32 1
# endif
@@ -1725,28 +1769,29 @@ extern "C" {
# define LZO_OPT_PREFER_POSTINC 1
# define LZO_OPT_PREFER_PREDEC 1
#endif
-#if !defined(LZO_CFG_NO_INLINE_ASM)
-#if defined(LZO_CC_LLVM)
+#ifndef LZO_CFG_NO_INLINE_ASM
+#if (LZO_CC_LLVM)
# define LZO_CFG_NO_INLINE_ASM 1
#endif
#endif
-#if !defined(LZO_CFG_NO_UNALIGNED)
-#if defined(LZO_ABI_NEUTRAL_ENDIAN) || defined(LZO_ARCH_GENERIC)
+#ifndef LZO_CFG_NO_UNALIGNED
+#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC)
# define LZO_CFG_NO_UNALIGNED 1
#endif
#endif
-#if defined(LZO_CFG_NO_UNALIGNED)
+#if (LZO_CFG_NO_UNALIGNED)
# undef LZO_OPT_UNALIGNED16
# undef LZO_OPT_UNALIGNED32
# undef LZO_OPT_UNALIGNED64
#endif
-#if defined(LZO_CFG_NO_INLINE_ASM)
+#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_INTELC || LZO_CC_PATHSCALE))
+#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_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
+#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)
diff --git a/extern/lzo/minilzo/minilzo.c b/extern/lzo/minilzo/minilzo.c
index 6a62b31b94a..34ce0f090bd 100644
--- a/extern/lzo/minilzo/minilzo.c
+++ b/extern/lzo/minilzo/minilzo.c
@@ -2,6 +2,9 @@
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
@@ -43,8 +46,7 @@
* http://www.oberhumer.com/opensource/lzo/
*/
-#define __LZO_IN_MINILZO
-#define LZO_BUILD
+#define __LZO_IN_MINILZO 1
#if defined(LZO_CFG_FREESTANDING)
# undef MINILZO_HAVE_CONFIG_H
@@ -142,7 +144,7 @@
#endif
#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL)
# define ptrdiff_t long
-# define _PTRDIFF_T_DEFINED
+# define _PTRDIFF_T_DEFINED 1
#endif
#if (UINT_MAX == LZO_0xffffL)
# undef __LZO_RENAME_A
@@ -286,9 +288,9 @@
# define LZO_EXTERN_C extern
#endif
#if !defined(__LZO_OS_OVERRIDE)
-#if defined(LZO_OS_FREESTANDING)
+#if (LZO_OS_FREESTANDING)
# define LZO_INFO_OS "freestanding"
-#elif defined(LZO_OS_EMBEDDED)
+#elif (LZO_OS_EMBEDDED)
# define LZO_INFO_OS "embedded"
#elif 1 && defined(__IAR_SYSTEMS_ICC__)
# define LZO_OS_EMBEDDED 1
@@ -497,12 +499,27 @@
# define LZO_CC_PELLESC 1
# define LZO_INFO_CC "Pelles C"
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__)
-#elif defined(__llvm__) && defined(__GNUC__) && defined(__VERSION__)
-# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
-# define LZO_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+#elif defined(__clang__) && defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__)
+# if defined(__GNUC_PATCHLEVEL__)
+# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
+# else
+# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+# endif
+# if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
+# define LZO_CC_CLANG_CLANG (__clang_major__ * 0x10000L + __clang_minor__ * 0x100 + __clang_patchlevel__)
# else
-# define LZO_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100)
+# define LZO_CC_CLANG_CLANG 0x010000L
# 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__)
+# else
+# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 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__)
@@ -523,6 +540,10 @@
# define LZO_CC_AZTECC 1
# define LZO_INFO_CC "Aztec C"
# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__)
+#elif defined(__CODEGEARC__)
+# define LZO_CC_CODEGEARC 1
+# define LZO_INFO_CC "CodeGear C"
+# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CODEGEARC__)
#elif defined(__BORLANDC__)
# define LZO_CC_BORLANDC 1
# define LZO_INFO_CC "Borland C"
@@ -653,7 +674,7 @@
#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER)
# error "LZO_CC_MSC: _MSC_FULL_VER is not defined"
#endif
-#if !defined(__LZO_ARCH_OVERRIDE) && !defined(LZO_ARCH_GENERIC) && defined(_CRAY)
+#if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY)
# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY)
# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E)
# define LZO_ARCH_CRAY_MPP 1
@@ -663,7 +684,7 @@
# endif
#endif
#if !defined(__LZO_ARCH_OVERRIDE)
-#if defined(LZO_ARCH_GENERIC)
+#if (LZO_ARCH_GENERIC)
# define LZO_INFO_ARCH "generic"
#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16)
# define LZO_ARCH_I086 1
@@ -698,6 +719,9 @@
#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__)
# define LZO_ARCH_AVR 1
# define LZO_INFO_ARCH "avr"
+#elif defined(__avr32__) || defined(__AVR32__)
+# define LZO_ARCH_AVR32 1
+# define LZO_INFO_ARCH "avr32"
#elif defined(__bfin__)
# define LZO_ARCH_BLACKFIN 1
# define LZO_INFO_ARCH "blackfin"
@@ -820,10 +844,10 @@
# define LZO_ARCH_I086PM 1
# define LZO_ARCH_IA16PM 1
#endif
-#if defined(LZO_ARCH_ARM_THUMB) && !defined(LZO_ARCH_ARM)
+#if (LZO_ARCH_ARM_THUMB) && !(LZO_ARCH_ARM)
# error "this should not happen"
#endif
-#if defined(LZO_ARCH_I086PM) && !defined(LZO_ARCH_I086)
+#if (LZO_ARCH_I086PM) && !(LZO_ARCH_I086)
# error "this should not happen"
#endif
#if (LZO_ARCH_I086)
@@ -896,7 +920,7 @@
#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295))
# undef LZO_HAVE_MM_HUGE_ARRAY
#endif
-#if (LZO_ARCH_I086PM) && !defined(LZO_HAVE_MM_HUGE_PTR)
+#if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR)
# if (LZO_OS_DOS16)
# error "this should not happen"
# elif (LZO_CC_ZORTECHC)
@@ -1112,7 +1136,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_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#elif (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
@@ -1146,12 +1170,12 @@ extern "C" {
#endif
#endif
#endif
-#if defined(__cplusplus) && defined(LZO_CC_GNUC)
+#if defined(__cplusplus) && (LZO_CC_GNUC)
# if (LZO_CC_GNUC < 0x020800ul)
# undef LZO_SIZEOF_LONG_LONG
# endif
#endif
-#if defined(LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG)
+#if (LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG)
# undef LZO_SIZEOF_LONG_LONG
#endif
#if !defined(LZO_SIZEOF_VOID_P)
@@ -1250,15 +1274,17 @@ extern "C" {
# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T
#endif
#endif
-#if defined(LZO_ABI_NEUTRAL_ENDIAN)
+#if (LZO_ABI_NEUTRAL_ENDIAN)
# undef LZO_ABI_BIG_ENDIAN
# undef LZO_ABI_LITTLE_ENDIAN
-#elif !defined(LZO_ABI_BIG_ENDIAN) && !defined(LZO_ABI_LITTLE_ENDIAN)
+#elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN)
#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP)
# define LZO_ABI_BIG_ENDIAN 1
+#elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64)
+# 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_M68K || LZO_ARCH_S390)
+#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390)
# define LZO_ABI_BIG_ENDIAN 1
#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__)
# if (__LITTLE_ENDIAN__ == 1)
@@ -1280,14 +1306,14 @@ extern "C" {
# define LZO_ABI_LITTLE_ENDIAN 1
#endif
#endif
-#if defined(LZO_ABI_BIG_ENDIAN) && defined(LZO_ABI_LITTLE_ENDIAN)
+#if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN)
# error "this should not happen"
#endif
-#if defined(LZO_ABI_BIG_ENDIAN)
+#if (LZO_ABI_BIG_ENDIAN)
# define LZO_INFO_ABI_ENDIAN "be"
-#elif defined(LZO_ABI_LITTLE_ENDIAN)
+#elif (LZO_ABI_LITTLE_ENDIAN)
# define LZO_INFO_ABI_ENDIAN "le"
-#elif defined(LZO_ABI_NEUTRAL_ENDIAN)
+#elif (LZO_ABI_NEUTRAL_ENDIAN)
# define LZO_INFO_ABI_ENDIAN "neutral"
#endif
#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2)
@@ -1313,15 +1339,15 @@ extern "C" {
# define LZO_INFO_ABI_PM "ip32l64"
#endif
#if !defined(__LZO_LIBC_OVERRIDE)
-#if defined(LZO_LIBC_NAKED)
+#if (LZO_LIBC_NAKED)
# define LZO_INFO_LIBC "naked"
-#elif defined(LZO_LIBC_FREESTANDING)
+#elif (LZO_LIBC_FREESTANDING)
# define LZO_INFO_LIBC "freestanding"
-#elif defined(LZO_LIBC_MOSTLY_FREESTANDING)
+#elif (LZO_LIBC_MOSTLY_FREESTANDING)
# define LZO_INFO_LIBC "mfreestanding"
-#elif defined(LZO_LIBC_ISOC90)
+#elif (LZO_LIBC_ISOC90)
# define LZO_INFO_LIBC "isoc90"
-#elif defined(LZO_LIBC_ISOC99)
+#elif (LZO_LIBC_ISOC99)
# define LZO_INFO_LIBC "isoc99"
#elif defined(__dietlibc__)
# define LZO_LIBC_DIETLIBC 1
@@ -1353,22 +1379,24 @@ extern "C" {
#if !defined(__lzo_gnuc_extension__)
#if (LZO_CC_GNUC >= 0x020800ul)
# define __lzo_gnuc_extension__ __extension__
-#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
# define __lzo_gnuc_extension__ __extension__
#else
-# define __lzo_gnuc_extension__
+# 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_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+#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)
@@ -1379,7 +1407,7 @@ extern "C" {
# define __lzo_constructor __attribute__((__constructor__,__used__))
#elif (LZO_CC_GNUC >= 0x020700ul)
# define __lzo_constructor __attribute__((__constructor__))
-#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE)
# define __lzo_constructor __attribute__((__constructor__))
#endif
#endif
@@ -1391,14 +1419,14 @@ extern "C" {
# define __lzo_destructor __attribute__((__destructor__,__used__))
#elif (LZO_CC_GNUC >= 0x020700ul)
# define __lzo_destructor __attribute__((__destructor__))
-#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#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 defined(__lzo_HAVE_destructor) && !defined(__lzo_HAVE_constructor)
+#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor)
# error "this should not happen"
#endif
#if !defined(__lzo_inline)
@@ -1407,7 +1435,7 @@ extern "C" {
# define __lzo_inline inline
#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550))
# define __lzo_inline __inline
-#elif (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI)
+#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
@@ -1417,6 +1445,8 @@ extern "C" {
# 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
@@ -1424,7 +1454,7 @@ extern "C" {
#if defined(__lzo_inline)
# define __lzo_HAVE_inline 1
#else
-# define __lzo_inline
+# define __lzo_inline /*empty*/
#endif
#if !defined(__lzo_forceinline)
#if (LZO_CC_GNUC >= 0x030200ul)
@@ -1433,16 +1463,18 @@ extern "C" {
# 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_LLVM || LZO_CC_PATHSCALE)
+#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__))
#endif
#endif
#if defined(__lzo_forceinline)
# define __lzo_HAVE_forceinline 1
#else
-# define __lzo_forceinline
+# define __lzo_forceinline /*empty*/
#endif
#if !defined(__lzo_noinline)
#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul)
@@ -1453,7 +1485,7 @@ extern "C" {
# define __lzo_noinline __declspec(noinline)
#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC)
# define __lzo_noinline __attribute__((__noinline__))
-#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#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)
@@ -1462,14 +1494,16 @@ extern "C" {
# else
# define __lzo_noinline __declspec(noinline)
# 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
+# define __lzo_noinline /*empty*/
#endif
-#if (defined(__lzo_HAVE_forceinline) || defined(__lzo_HAVE_noinline)) && !defined(__lzo_HAVE_inline)
+#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline)
# error "this should not happen"
#endif
#if !defined(__lzo_noreturn)
@@ -1479,7 +1513,7 @@ extern "C" {
# define __lzo_noreturn __declspec(noreturn)
#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC)
# define __lzo_noreturn __attribute__((__noreturn__))
-#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#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)
@@ -1488,16 +1522,16 @@ extern "C" {
#if defined(__lzo_noreturn)
# define __lzo_HAVE_noreturn 1
#else
-# define __lzo_noreturn
+# 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 >= 800) && LZO_CC_SYNTAX_GNUC)
+#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 900) && LZO_CC_SYNTAX_GNUC)
# define __lzo_nothrow __attribute__((__nothrow__))
-#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE)
+#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)
@@ -1506,14 +1540,14 @@ extern "C" {
#if defined(__lzo_nothrow)
# define __lzo_HAVE_nothrow 1
#else
-# define __lzo_nothrow
+# 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_LLVM)
+#elif (LZO_CC_CLANG || LZO_CC_LLVM)
# define __lzo_restrict __restrict__
#elif (LZO_CC_MSC && (_MSC_VER >= 1400))
# define __lzo_restrict __restrict
@@ -1522,7 +1556,7 @@ extern "C" {
#if defined(__lzo_restrict)
# define __lzo_HAVE_restrict 1
#else
-# define __lzo_restrict
+# define __lzo_restrict /*empty*/
#endif
#if !defined(__lzo_likely) && !defined(__lzo_unlikely)
#if (LZO_CC_GNUC >= 0x030200ul)
@@ -1531,7 +1565,7 @@ extern "C" {
#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_LLVM || LZO_CC_PATHSCALE)
+#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
@@ -1551,7 +1585,7 @@ extern "C" {
# 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_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE)
+# 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
@@ -1570,7 +1604,7 @@ extern "C" {
# 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_LLVM)
+# 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
@@ -1585,7 +1619,7 @@ extern "C" {
#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_INTELC || LZO_CC_WATCOMC)
+# 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
@@ -1600,6 +1634,15 @@ extern "C" {
# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init
# 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)))))
+# 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)];
@@ -1628,7 +1671,7 @@ extern "C" {
# 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
+# 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
@@ -1669,24 +1712,24 @@ extern "C" {
# define __lzo_cdecl cdecl
#endif
#if !defined(__lzo_cdecl)
-# define __lzo_cdecl
+# define __lzo_cdecl /*empty*/
#endif
#if !defined(__lzo_cdecl_atexit)
-# define __lzo_cdecl_atexit
+# define __lzo_cdecl_atexit /*empty*/
#endif
#if !defined(__lzo_cdecl_main)
-# define __lzo_cdecl_main
+# define __lzo_cdecl_main /*empty*/
#endif
#if !defined(__lzo_cdecl_qsort)
-# define __lzo_cdecl_qsort
+# define __lzo_cdecl_qsort /*empty*/
#endif
#if !defined(__lzo_cdecl_sighandler)
-# define __lzo_cdecl_sighandler
+# define __lzo_cdecl_sighandler /*empty*/
#endif
#if !defined(__lzo_cdecl_va)
# define __lzo_cdecl_va __lzo_cdecl
#endif
-#if !defined(LZO_CFG_NO_WINDOWS_H)
+#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__)
@@ -1732,7 +1775,7 @@ extern "C" {
#elif (LZO_ARCH_POWERPC)
# define LZO_OPT_PREFER_PREINC 1
# define LZO_OPT_PREFER_PREDEC 1
-# if defined(LZO_ABI_BIG_ENDIAN)
+# if (LZO_ABI_BIG_ENDIAN)
# define LZO_OPT_UNALIGNED16 1
# define LZO_OPT_UNALIGNED32 1
# endif
@@ -1746,28 +1789,29 @@ extern "C" {
# define LZO_OPT_PREFER_POSTINC 1
# define LZO_OPT_PREFER_PREDEC 1
#endif
-#if !defined(LZO_CFG_NO_INLINE_ASM)
-#if defined(LZO_CC_LLVM)
+#ifndef LZO_CFG_NO_INLINE_ASM
+#if (LZO_CC_LLVM)
# define LZO_CFG_NO_INLINE_ASM 1
#endif
#endif
-#if !defined(LZO_CFG_NO_UNALIGNED)
-#if defined(LZO_ABI_NEUTRAL_ENDIAN) || defined(LZO_ARCH_GENERIC)
+#ifndef LZO_CFG_NO_UNALIGNED
+#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC)
# define LZO_CFG_NO_UNALIGNED 1
#endif
#endif
-#if defined(LZO_CFG_NO_UNALIGNED)
+#if (LZO_CFG_NO_UNALIGNED)
# undef LZO_OPT_UNALIGNED16
# undef LZO_OPT_UNALIGNED32
# undef LZO_OPT_UNALIGNED64
#endif
-#if defined(LZO_CFG_NO_INLINE_ASM)
+#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_INTELC || LZO_CC_PATHSCALE))
+#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_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE))
+#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)
@@ -1830,34 +1874,34 @@ extern "C" {
#undef LZO_HAVE_CONFIG_H
#include "minilzo.h"
-#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x2030)
+#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x2060)
# error "version mismatch in miniLZO source files"
#endif
#ifdef MINILZO_HAVE_CONFIG_H
-# define LZO_HAVE_CONFIG_H
+# define LZO_HAVE_CONFIG_H 1
#endif
#ifndef __LZO_CONF_H
-#define __LZO_CONF_H
+#define __LZO_CONF_H 1
#if !defined(__LZO_IN_MINILZO)
-#if defined(LZO_CFG_FREESTANDING)
+#if (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 defined(LZO_CFG_NO_UNALIGNED)
+#if (LZO_CFG_NO_UNALIGNED)
# define ACC_CFG_NO_UNALIGNED 1
#endif
-#if defined(LZO_ARCH_GENERIC)
+#if (LZO_ARCH_GENERIC)
# define ACC_ARCH_GENERIC 1
#endif
-#if defined(LZO_ABI_NEUTRAL_ENDIAN)
+#if (LZO_ABI_NEUTRAL_ENDIAN)
# define ACC_ABI_NEUTRAL_ENDIAN 1
#endif
-#if defined(LZO_HAVE_CONFIG_H)
+#if (LZO_HAVE_CONFIG_H)
# define ACC_CONFIG_NO_HEADER 1
#endif
#if defined(LZO_CFG_EXTRA_CONFIG_HEADER)
@@ -1886,11 +1930,14 @@ extern "C" {
#endif
#if (LZO_CC_SUNPROC)
+#if !defined(__cplusplus)
# pragma error_messages(off,E_END_OF_LOOP_CODE_NOT_REACHED)
# pragma error_messages(off,E_LOOP_NOT_ENTERED_AT_TOP)
+# pragma error_messages(off,E_STATEMENT_NOT_REACHED)
+#endif
#endif
-#if defined(__LZO_MMODEL_HUGE) && (!LZO_HAVE_MM_HUGE_PTR)
+#if (__LZO_MMODEL_HUGE) && !(LZO_HAVE_MM_HUGE_PTR)
# error "this should not happen - check defines for __huge"
#endif
@@ -1955,40 +2002,44 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp))
#include <string.h>
#endif
-#if defined(LZO_CFG_FREESTANDING)
+#if (LZO_CFG_FREESTANDING)
# undef HAVE_MEMCMP
# undef HAVE_MEMCPY
# undef HAVE_MEMMOVE
# undef HAVE_MEMSET
#endif
-#if !defined(HAVE_MEMCMP)
+#if !(HAVE_MEMCMP)
# undef memcmp
# define memcmp(a,b,c) lzo_memcmp(a,b,c)
-#elif !defined(__LZO_MMODEL_HUGE)
+#elif !(__LZO_MMODEL_HUGE)
+# undef lzo_memcmp
# define lzo_memcmp(a,b,c) memcmp(a,b,c)
#endif
-#if !defined(HAVE_MEMCPY)
+#if !(HAVE_MEMCPY)
# undef memcpy
# define memcpy(a,b,c) lzo_memcpy(a,b,c)
-#elif !defined(__LZO_MMODEL_HUGE)
+#elif !(__LZO_MMODEL_HUGE)
+# undef lzo_memcpy
# define lzo_memcpy(a,b,c) memcpy(a,b,c)
#endif
-#if !defined(HAVE_MEMMOVE)
+#if !(HAVE_MEMMOVE)
# undef memmove
# define memmove(a,b,c) lzo_memmove(a,b,c)
-#elif !defined(__LZO_MMODEL_HUGE)
+#elif !(__LZO_MMODEL_HUGE)
+# undef lzo_memmove
# define lzo_memmove(a,b,c) memmove(a,b,c)
#endif
-#if !defined(HAVE_MEMSET)
+#if !(HAVE_MEMSET)
# undef memset
# define memset(a,b,c) lzo_memset(a,b,c)
-#elif !defined(__LZO_MMODEL_HUGE)
+#elif !(__LZO_MMODEL_HUGE)
+# undef lzo_memset
# define lzo_memset(a,b,c) memset(a,b,c)
#endif
#undef NDEBUG
-#if defined(LZO_CFG_FREESTANDING)
+#if (LZO_CFG_FREESTANDING)
# undef LZO_DEBUG
# define NDEBUG 1
# undef assert
@@ -2008,13 +2059,24 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp))
#endif
#if !defined(__lzo_inline)
-# define __lzo_inline
+# define __lzo_inline /*empty*/
#endif
#if !defined(__lzo_forceinline)
-# define __lzo_forceinline
+# define __lzo_forceinline /*empty*/
#endif
#if !defined(__lzo_noinline)
-# define __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
#if 1
@@ -2050,24 +2112,69 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp))
#endif
#endif
-#if 1 && !defined(LZO_CFG_NO_UNALIGNED)
-#if 1 && (LZO_ARCH_AMD64 || LZO_ARCH_I386)
+#if 1 && (LZO_ARCH_AMD64 || LZO_ARCH_I386 || LZO_ARCH_POWERPC)
# if (LZO_SIZEOF_SHORT == 2)
-# define LZO_UNALIGNED_OK_2
+# define LZO_UNALIGNED_OK_2 1
# endif
# if (LZO_SIZEOF_INT == 4)
-# define LZO_UNALIGNED_OK_4
+# define LZO_UNALIGNED_OK_4 1
# endif
#endif
+#if 1 && (LZO_ARCH_AMD64)
+# if defined(LZO_UINT64_MAX)
+# define LZO_UNALIGNED_OK_8 1
+# endif
#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(short) == 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
#endif
-#if defined(LZO_UNALIGNED_OK_4)
- LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32) == 4)
-#elif defined(LZO_ALIGNED_OK_4)
- LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32) == 4)
+#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
#define MEMCPY8_DS(dest,src,len) \
@@ -2079,19 +2186,17 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp))
#define MEMCPY_DS(dest,src,len) \
do *dest++ = *src++; while (--len > 0)
-__LZO_EXTERN_C int __lzo_init_done;
-__LZO_EXTERN_C const char __lzo_copyright[];
LZO_EXTERN(const lzo_bytep) lzo_copyright(void);
#ifndef __LZO_PTR_H
-#define __LZO_PTR_H
+#define __LZO_PTR_H 1
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(lzo_uintptr_t)
-# if defined(__LZO_MMODEL_HUGE)
+# if (__LZO_MMODEL_HUGE)
# define lzo_uintptr_t unsigned long
# else
# define lzo_uintptr_t acc_uintptr_t
@@ -2140,6 +2245,10 @@ typedef union
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
ptrdiff_t a_ptrdiff_t;
lzo_uintptr_t a_lzo_uintptr_t;
lzo_voidp a_lzo_voidp;
@@ -2161,14 +2270,19 @@ lzo_full_align_t;
#endif
-#define LZO_DETERMINISTIC
+#ifndef LZO_DETERMINISTIC
+#define LZO_DETERMINISTIC 1
+#endif
-#define LZO_DICT_USE_PTR
+#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 defined(LZO_DICT_USE_PTR)
+#if (LZO_DICT_USE_PTR)
# define lzo_dict_t const lzo_bytep
# define lzo_dict_p lzo_dict_t __LZO_MMODEL *
#else
@@ -2216,22 +2330,22 @@ __lzo_align_gap(const lzo_voidp ptr, lzo_uint size)
}
#endif
+#if !defined(MINILZO_CFG_SKIP_LZO_UTIL)
/* If you use the LZO library in a product, I would appreciate that you
* keep this copyright string in the executable of your product.
*/
-const char __lzo_copyright[] =
+static const char __lzo_copyright[] =
#if !defined(__LZO_IN_MINLZO)
LZO_VERSION_STRING;
#else
"\r\n\n"
"LZO data compression library.\n"
- "$Copyright: LZO (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Markus Franz Xaver Johannes Oberhumer\n"
+ "$Copyright: LZO Copyright (C) 1996-2011 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"
- "$Built: " __DATE__ " " __TIME__ " $\n"
"$Info: " LZO_INFO_STRING " $\n";
#endif
@@ -2321,6 +2435,7 @@ lzo_adler32(lzo_uint32 adler, const lzo_bytep buf, lzo_uint len)
#undef LZO_DO8
#undef LZO_DO16
+#endif
#if !defined(MINILZO_CFG_SKIP_LZO_STRING)
#undef lzo_memcmp
#undef lzo_memcpy
@@ -2343,7 +2458,7 @@ lzo_adler32(lzo_uint32 adler, const lzo_bytep buf, lzo_uint len)
#endif
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) || !defined(HAVE_MEMCMP)
+#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;
if __lzo_likely(len > 0) do
@@ -2360,7 +2475,7 @@ 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) || !defined(HAVE_MEMCPY)
+#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;
if (!(len > 0) || p1 == p2)
@@ -2375,7 +2490,7 @@ 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) || !defined(HAVE_MEMMOVE)
+#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;
if (!(len > 0) || p1 == p2)
@@ -2401,7 +2516,7 @@ LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemmove) (lzo_hvoid_p dest, const lzo_hvoid_p sr
}
LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int c, lzo_hsize_t len)
{
-#if (LZO_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMSET)
+#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMSET)
lzo_hbyte_p p = (lzo_hbyte_p) s;
if __lzo_likely(len > 0) do
*p++ = (unsigned char) c;
@@ -2413,6 +2528,7 @@ LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int c, lzo_hsize_t len)
}
#undef LZOLIB_PUBLIC
#endif
+#if !defined(MINILZO_CFG_SKIP_LZO_INIT)
#if !defined(__LZO_IN_MINILZO)
@@ -2426,6 +2542,11 @@ LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int c, lzo_hsize_t len)
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)
@@ -2440,40 +2561,158 @@ LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int c, lzo_hsize_t len)
#endif
#undef ACCCHK_ASSERT
+#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
+
+#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
+#endif
+
+#if 0
+#define u2p(ptr,off) ((lzo_voidp) (((lzo_bytep)(lzo_voidp)(ptr)) + (off)))
+#else
+static __lzo_noinline lzo_voidp u2p(lzo_voidp ptr, lzo_uint off)
+{
+ return (lzo_voidp) ((lzo_bytep) ptr + off);
+}
+#endif
+
LZO_PUBLIC(int)
_lzo_config_check(void)
{
lzo_bool r = 1;
- union { unsigned char c[2*sizeof(lzo_xint)]; lzo_xint l[2]; } u;
- lzo_uintptr_t p;
-
+ 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;
+ lzo_voidp p;
+
+ 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)
- u.l[0] = u.l[1] = 0; u.c[sizeof(lzo_xint) - 1] = 128;
- r &= (u.l[0] == 128);
+ 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)
- u.l[0] = u.l[1] = 0; u.c[0] = 128;
- r &= (u.l[0] == 128);
+ 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)
- p = (lzo_uintptr_t) (const lzo_voidp) &u.c[0];
- u.l[0] = u.l[1] = 0;
- r &= ((* (const lzo_ushortp) (p+1)) == 0);
+ u.a[0] = u.a[1] = 0;
+ u.b[0] = 1; u.b[sizeof(unsigned short) + 1] = 2;
+ p = u2p(&u, 1);
+ r &= ((* (lzo_ushortp) p) == 0);
#endif
#if defined(LZO_UNALIGNED_OK_4)
- p = (lzo_uintptr_t) (const lzo_voidp) &u.c[0];
- u.l[0] = u.l[1] = 0;
- r &= ((* (const lzo_uint32p) (p+1)) == 0);
+ u.a[0] = u.a[1] = 0;
+ u.b[0] = 3; u.b[sizeof(lzo_uint32) + 1] = 4;
+ p = u2p(&u, 1);
+ r &= ((* (lzo_uint32p) p) == 0);
+#endif
+#if defined(LZO_UNALIGNED_OK_8)
+ u.c[0] = u.c[1] = 0;
+ u.b[0] = 5; u.b[sizeof(lzo_uint64) + 1] = 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
- LZO_UNUSED(u); LZO_UNUSED(p);
return r == 1 ? LZO_E_OK : LZO_E_ERROR;
}
-int __lzo_init_done = 0;
-
LZO_PUBLIC(int)
__lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5,
int s6, int s7, int s8, int s9)
@@ -2489,8 +2728,6 @@ __lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5,
#endif
#undef ACCCHK_ASSERT
- __lzo_init_done = 1;
-
if (v == 0)
return LZO_E_ERROR;
@@ -2532,27 +2769,47 @@ int __far __pascal LibMain ( int a, short b, short c, long d )
#endif
-#define do_compress _lzo1x_1_do_compress
+#endif
+
+#define LZO1X 1
+#define LZO_EOF_CODE 1
+#define M2_MAX_OFFSET 0x0800
#if !defined(MINILZO_CFG_SKIP_LZO1X_1_COMPRESS)
-#define LZO_NEED_DICT_H
+#if 1 && defined(UA_GET32)
+#undef LZO_DICT_USE_PTR
+#define LZO_DICT_USE_PTR 0
+#undef lzo_dict_t
+#define lzo_dict_t unsigned short
+#endif
+
+#define LZO_NEED_DICT_H 1
+#ifndef D_BITS
#define D_BITS 14
+#endif
#define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5)
#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f)
+#if 1
+#define DINDEX(dv,p) DM(((DMUL(0x1824429d,dv)) >> (32-D_BITS)))
+#else
+#define DINDEX(dv,p) DM((dv) + ((dv) >> (32-D_BITS)))
+#endif
#ifndef __LZO_CONFIG1X_H
-#define __LZO_CONFIG1X_H
+#define __LZO_CONFIG1X_H 1
#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z)
-# define LZO1X
+# define LZO1X 1
#endif
#if !defined(__LZO_IN_MINILZO)
#include "lzo/lzo1x.h"
#endif
-#define LZO_EOF_CODE
+#ifndef LZO_EOF_CODE
+#define LZO_EOF_CODE 1
+#endif
#undef LZO_DETERMINISTIC
#define M1_MAX_OFFSET 0x0400
@@ -2592,7 +2849,7 @@ int __far __pascal LibMain ( int a, short b, short c, long d )
#define DL_MIN_LEN M2_MIN_LEN
#ifndef __LZO_DICT_H
-#define __LZO_DICT_H
+#define __LZO_DICT_H 1
#ifdef __cplusplus
extern "C" {
@@ -2633,10 +2890,10 @@ extern "C" {
#if (D_BITS != DL_BITS + DD_BITS)
# error "D_BITS does not match"
#endif
-#if (D_BITS < 8 || D_BITS > 18)
+#if (D_BITS < 6 || D_BITS > 18)
# error "invalid D_BITS"
#endif
-#if (DL_BITS < 8 || DL_BITS > 20)
+#if (DL_BITS < 6 || DL_BITS > 20)
# error "invalid DL_BITS"
#endif
#if (DD_BITS < 0 || DD_BITS > 6)
@@ -2695,14 +2952,14 @@ extern "C" {
# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT))
#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL)
-# define __LZO_HASH_INCREMENTAL
+# define __LZO_HASH_INCREMENTAL 1
# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT)
# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2])
# define _DINDEX(dv,p) (dv)
# define DVAL_LOOKAHEAD DL_MIN_LEN
#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A)
-# define __LZO_HASH_INCREMENTAL
+# define __LZO_HASH_INCREMENTAL 1
# define DVAL_FIRST(dv,p) dv = _DV_A((p),5)
# define DVAL_NEXT(dv,p) \
dv ^= (lzo_xint)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2])
@@ -2710,7 +2967,7 @@ extern "C" {
# define DVAL_LOOKAHEAD DL_MIN_LEN
#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B)
-# define __LZO_HASH_INCREMENTAL
+# define __LZO_HASH_INCREMENTAL 1
# define DVAL_FIRST(dv,p) dv = _DV_B((p),5)
# define DVAL_NEXT(dv,p) \
dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_xint)(p[2]) << (2*5)))
@@ -2739,7 +2996,12 @@ extern "C" {
#if !defined(DVAL_ASSERT)
#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG)
-static void DVAL_ASSERT(lzo_xint dv, const lzo_bytep p)
+#if (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_LLVM)
+static void __attribute__((__unused__))
+#else
+static void
+#endif
+DVAL_ASSERT(lzo_xint dv, const lzo_bytep p)
{
lzo_xint df;
DVAL_FIRST(df,(p));
@@ -2750,11 +3012,11 @@ static void DVAL_ASSERT(lzo_xint dv, const lzo_bytep p)
#endif
#endif
-#if defined(LZO_DICT_USE_PTR)
+#if (LZO_DICT_USE_PTR)
# define DENTRY(p,in) (p)
# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex]
#else
-# define DENTRY(p,in) ((lzo_uint) ((p)-(in)))
+# define DENTRY(p,in) ((lzo_dict_t) pd(p, in))
# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex]
#endif
@@ -2775,7 +3037,7 @@ static void DVAL_ASSERT(lzo_xint dv, const lzo_bytep p)
#endif
-#if defined(LZO_DICT_USE_PTR)
+#if (LZO_DICT_USE_PTR)
#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \
(m_pos == NULL || (m_off = pd(ip, m_pos)) > max_offset)
@@ -2784,7 +3046,7 @@ static void DVAL_ASSERT(lzo_xint dv, const lzo_bytep p)
(BOUNDS_CHECKING_OFF_IN_EXPR(( \
m_pos = ip - (lzo_uint) PTR_DIFF(ip,m_pos), \
PTR_LT(m_pos,in) || \
- (m_off = (lzo_uint) PTR_DIFF(ip,m_pos)) <= 0 || \
+ (m_off = (lzo_uint) PTR_DIFF(ip,m_pos)) == 0 || \
m_off > max_offset )))
#else
@@ -2801,7 +3063,7 @@ static void DVAL_ASSERT(lzo_xint dv, const lzo_bytep p)
#endif
-#if defined(LZO_DETERMINISTIC)
+#if (LZO_DETERMINISTIC)
# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET
#else
# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET
@@ -2817,17 +3079,99 @@ static void DVAL_ASSERT(lzo_xint dv, const lzo_bytep p)
#endif
+#define LZO_DETERMINISTIC !(LZO_DICT_USE_PTR)
+
+#ifndef DO_COMPRESS
#define DO_COMPRESS lzo1x_1_compress
+#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
+#endif
static __lzo_noinline lzo_uint
do_compress ( const lzo_bytep in , lzo_uint in_len,
lzo_bytep out, lzo_uintp out_len,
- lzo_voidp wrkmem )
+ lzo_uint ti, lzo_voidp wrkmem)
{
register 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 - M2_MAX_LEN - 5;
+ const lzo_bytep const ip_end = in + in_len - 20;
const lzo_bytep ii;
lzo_dict_p const dict = (lzo_dict_p) wrkmem;
@@ -2835,14 +3179,17 @@ do_compress ( const lzo_bytep in , lzo_uint in_len,
ip = in;
ii = ip;
- ip += 4;
+ ip += ti < 4 ? 4 - ti : 0;
for (;;)
{
- register const lzo_bytep m_pos;
- lzo_uint m_off;
+ const lzo_bytep m_pos;
+#if !(LZO_DETERMINISTIC)
+ LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0);
lzo_uint m_len;
lzo_uint dindex;
-
+next:
+ if __lzo_unlikely(ip >= ip_end)
+ break;
DINDEX1(dindex,ip);
GINDEX(m_pos,m_off,dict,dindex,in);
if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET))
@@ -2860,200 +3207,245 @@ do_compress ( const lzo_bytep in , lzo_uint in_len,
goto literal;
try_match:
-#if 1 && defined(LZO_UNALIGNED_OK_2)
- if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip)
+#if defined(UA_GET32)
+ if (UA_GET32(m_pos) != UA_GET32(ip))
#else
- if (m_pos[0] != ip[0] || m_pos[1] != ip[1])
+ if (m_pos[0] != ip[0] || m_pos[1] != ip[1] || m_pos[2] != ip[2] || m_pos[3] != ip[3])
#endif
{
+literal:
+ UPDATE_I(dict,0,dindex,ip,in);
+ ip += 1 + ((ip - ii) >> 5);
+ continue;
}
- else
- {
- if __lzo_likely(m_pos[2] == ip[2])
- {
-#if 0
- if (m_off <= M2_MAX_OFFSET)
- goto match;
- if (lit <= 3)
- goto match;
- if (lit == 3)
- {
- assert(op - 2 > out); op[-2] |= LZO_BYTE(3);
- *op++ = *ii++; *op++ = *ii++; *op++ = *ii++;
- goto code_match;
- }
- if (m_pos[3] == ip[3])
-#endif
- goto match;
- }
- else
- {
-#if 0
-#if 0
- if (m_off <= M1_MAX_OFFSET && lit > 0 && lit <= 3)
+ UPDATE_I(dict,0,dindex,ip,in);
#else
- if (m_off <= M1_MAX_OFFSET && lit == 3)
-#endif
- {
- register lzo_uint t;
-
- t = lit;
- assert(op - 2 > out); op[-2] |= LZO_BYTE(t);
- do *op++ = *ii++; while (--t > 0);
- assert(ii == ip);
- m_off -= 1;
- *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2));
- *op++ = LZO_BYTE(m_off >> 2);
- ip += 2;
- goto match_done;
- }
-#endif
- }
- }
-
+ lzo_uint m_off;
+ lzo_uint m_len;
+ {
+ lzo_uint32 dv;
+ lzo_uint dindex;
literal:
- UPDATE_I(dict,0,dindex,ip,in);
- ++ip;
+ ip += 1 + ((ip - ii) >> 5);
+next:
if __lzo_unlikely(ip >= ip_end)
break;
- continue;
-
-match:
+ dv = UA_GET32(ip);
+ dindex = DINDEX(dv,ip);
+ GINDEX(m_off,m_pos,in+dict,dindex,in);
UPDATE_I(dict,0,dindex,ip,in);
- if (pd(ip,ii) > 0)
- {
- register lzo_uint t = pd(ip,ii);
+ if __lzo_unlikely(dv != UA_GET32(m_pos))
+ goto literal;
+ }
+#endif
+ ii -= ti; ti = 0;
+ {
+ register lzo_uint t = pd(ip,ii);
+ if (t != 0)
+ {
if (t <= 3)
{
- assert(op - 2 > out);
op[-2] |= LZO_BYTE(t);
+#if defined(UA_COPY32)
+ UA_COPY32(op, ii);
+ op += t;
+#else
+ { do *op++ = *ii++; while (--t > 0); }
+#endif
}
- else if (t <= 18)
+#if defined(UA_COPY32) || defined(UA_COPY64)
+ 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
+ op += t;
+ }
+#endif
else
{
- register lzo_uint tt = t - 18;
-
- *op++ = 0;
- while (tt > 255)
+ if (t <= 18)
+ *op++ = LZO_BYTE(t - 3);
+ else
{
- tt -= 255;
+ register 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
+ }
+ assert(tt > 0);
+ *op++ = LZO_BYTE(tt);
}
- assert(tt > 0);
- *op++ = LZO_BYTE(tt);
+#if defined(UA_COPY32) || defined(UA_COPY64)
+ 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
+ op += 16; ii += 16; t -= 16;
+ } while (t >= 16); if (t > 0)
+#endif
+ { do *op++ = *ii++; while (--t > 0); }
}
- do *op++ = *ii++; while (--t > 0);
}
-
- assert(ii == ip);
- ip += 3;
- if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ ||
- m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++
-#ifdef LZO1Y
- || m_pos[ 9] != *ip++ || m_pos[10] != *ip++ || m_pos[11] != *ip++
- || m_pos[12] != *ip++ || m_pos[13] != *ip++ || m_pos[14] != *ip++
+ }
+ m_len = 4;
+ {
+#if defined(UA_GET64)
+ lzo_uint64 v;
+ v = UA_GET64(ip + m_len) ^ UA_GET64(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);
+ 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;
+#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)
+ if ((v & UCHAR_MAX) == 0) do {
+ v >>= CHAR_BIT;
+ m_len += 1;
+ } while ((v & UCHAR_MAX) == 0);
+#else
+ if (ip[m_len] == m_pos[m_len]) do {
+ 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);
+ if __lzo_unlikely(v == 0) {
+ do {
+ m_len += 4;
+ v = UA_GET32(ip + m_len) ^ UA_GET32(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;
+#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)
+ if ((v & UCHAR_MAX) == 0) do {
+ v >>= CHAR_BIT;
+ m_len += 1;
+ } while ((v & UCHAR_MAX) == 0);
+#else
+ if (ip[m_len] == m_pos[m_len]) do {
+ m_len += 1;
+ } while (ip[m_len] == m_pos[m_len]);
+#endif
+#else
+ if __lzo_unlikely(ip[m_len] == m_pos[m_len]) {
+ do {
+ m_len += 1;
+ if __lzo_unlikely(ip + m_len >= ip_end)
+ goto m_len_done;
+ } while (ip[m_len] == m_pos[m_len]);
+ }
#endif
- )
+ }
+m_len_done:
+ m_off = pd(ip,m_pos);
+ ip += m_len;
+ ii = ip;
+ if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
{
- --ip;
- m_len = pd(ip, ii);
- assert(m_len >= 3); assert(m_len <= M2_MAX_LEN);
-
- if (m_off <= M2_MAX_OFFSET)
- {
- m_off -= 1;
+ m_off -= 1;
#if defined(LZO1X)
- *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2));
- *op++ = LZO_BYTE(m_off >> 3);
+ *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2));
+ *op++ = LZO_BYTE(m_off >> 3);
#elif defined(LZO1Y)
- *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2));
- *op++ = LZO_BYTE(m_off >> 2);
+ *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2));
+ *op++ = LZO_BYTE(m_off >> 2);
#endif
- }
- else if (m_off <= M3_MAX_OFFSET)
- {
- m_off -= 1;
+ }
+ else if (m_off <= M3_MAX_OFFSET)
+ {
+ m_off -= 1;
+ if (m_len <= M3_MAX_LEN)
*op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
- goto m3_m4_offset;
- }
else
-#if defined(LZO1X)
{
- m_off -= 0x4000;
- assert(m_off > 0); assert(m_off <= 0x7fff);
- *op++ = LZO_BYTE(M4_MARKER |
- ((m_off & 0x4000) >> 11) | (m_len - 2));
- goto m3_m4_offset;
- }
-#elif defined(LZO1Y)
- goto m4_match;
+ m_len -= M3_MAX_LEN;
+ *op++ = M3_MARKER | 0;
+ 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
+ }
+ *op++ = LZO_BYTE(m_len);
+ }
+ *op++ = LZO_BYTE(m_off << 2);
+ *op++ = LZO_BYTE(m_off >> 6);
}
else
{
- {
- const lzo_bytep end = in_end;
- const lzo_bytep m = m_pos + M2_MAX_LEN + 1;
- while (ip < end && *m == *ip)
- m++, ip++;
- m_len = pd(ip, ii);
- }
- assert(m_len > M2_MAX_LEN);
-
- if (m_off <= M3_MAX_OFFSET)
- {
- m_off -= 1;
- if (m_len <= 33)
- *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
- else
- {
- m_len -= 33;
- *op++ = M3_MARKER | 0;
- goto m3_m4_len;
- }
- }
+ m_off -= 0x4000;
+ if (m_len <= M4_MAX_LEN)
+ *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8) | (m_len - 2));
else
{
-#if defined(LZO1Y)
-m4_match:
-#endif
- m_off -= 0x4000;
- assert(m_off > 0); assert(m_off <= 0x7fff);
- if (m_len <= M4_MAX_LEN)
- *op++ = LZO_BYTE(M4_MARKER |
- ((m_off & 0x4000) >> 11) | (m_len - 2));
- else
+ m_len -= M4_MAX_LEN;
+ *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8));
+ while __lzo_unlikely(m_len > 255)
{
- m_len -= M4_MAX_LEN;
- *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11));
-m3_m4_len:
- while (m_len > 255)
- {
- m_len -= 255;
- *op++ = 0;
- }
- assert(m_len > 0);
- *op++ = LZO_BYTE(m_len);
+ m_len -= 255;
+#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400))
+ * (volatile unsigned char *) op++ = 0;
+#else
+ *op++ = 0;
+#endif
}
+ *op++ = LZO_BYTE(m_len);
}
-
-m3_m4_offset:
- *op++ = LZO_BYTE((m_off & 63) << 2);
+ *op++ = LZO_BYTE(m_off << 2);
*op++ = LZO_BYTE(m_off >> 6);
}
-
-#if 0
-match_done:
-#endif
- ii = ip;
- if __lzo_unlikely(ip >= ip_end)
- break;
+ goto next;
}
*out_len = pd(op, out);
- return pd(in_end,ii);
+ return pd(in_end,ii-ti);
}
LZO_PUBLIC(int)
@@ -3061,16 +3453,30 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len,
lzo_bytep out, lzo_uintp out_len,
lzo_voidp wrkmem )
{
+ const lzo_bytep ip = in;
lzo_bytep op = out;
- lzo_uint t;
+ lzo_uint l = in_len;
+ lzo_uint t = 0;
- if __lzo_unlikely(in_len <= M2_MAX_LEN + 5)
- t = in_len;
- else
+ while (l > 20)
{
- t = do_compress(in,in_len,op,out_len,wrkmem);
+ lzo_uint ll = l;
+ lzo_uintptr_t ll_end;
+#if 0 || (LZO_DETERMINISTIC)
+ ll = LZO_MIN(ll, 49152);
+#endif
+ ll_end = (lzo_uintptr_t)ip + ll;
+ if ((ll_end + ((t + ll) >> 5)) <= ll_end || (const lzo_bytep)(ll_end + ((t + ll) >> 5)) <= ip + ll)
+ break;
+#if (LZO_DETERMINISTIC)
+ lzo_memset(wrkmem, 0, ((lzo_uint)1 << D_BITS) * sizeof(lzo_dict_t));
+#endif
+ t = do_compress(ip,ll,op,out_len,t,wrkmem);
+ ip += ll;
op += *out_len;
+ l -= ll;
}
+ t += l;
if (t > 0)
{
@@ -3090,7 +3496,12 @@ 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
}
assert(tt > 0);
*op++ = LZO_BYTE(tt);
@@ -3126,7 +3537,7 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len,
# define LZO_TEST_OVERRUN_OUTPUT 2
# endif
# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND)
-# define LZO_TEST_OVERRUN_LOOKBEHIND
+# define LZO_TEST_OVERRUN_LOOKBEHIND 1
# endif
#endif
@@ -3177,42 +3588,32 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len,
#endif
#if defined(TEST_IP)
-# define HAVE_TEST_IP
+# define HAVE_TEST_IP 1
#else
# define TEST_IP 1
#endif
#if defined(TEST_OP)
-# define HAVE_TEST_OP
+# define HAVE_TEST_OP 1
#else
# define TEST_OP 1
#endif
#if defined(NEED_IP)
-# define HAVE_NEED_IP
+# define HAVE_NEED_IP 1
#else
# define NEED_IP(x) ((void) 0)
#endif
#if defined(NEED_OP)
-# define HAVE_NEED_OP
+# define HAVE_NEED_OP 1
#else
# define NEED_OP(x) ((void) 0)
#endif
#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP)
-# define HAVE_ANY_IP
+# define HAVE_ANY_IP 1
#endif
#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP)
-# define HAVE_ANY_OP
-#endif
-
-#undef __COPY4
-#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src)
-
-#undef COPY4
-#if defined(LZO_UNALIGNED_OK_4)
-# define COPY4(dst,src) __COPY4(dst,src)
-#elif defined(LZO_ALIGNED_OK_4)
-# define COPY4(dst,src) __COPY4((lzo_uintptr_t)(dst),(lzo_uintptr_t)(src))
+# define HAVE_ANY_OP 1
#endif
#if defined(DO_DECOMPRESS)
@@ -3291,19 +3692,36 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
t += 15 + *ip++;
}
assert(t > 0); NEED_OP(t+3); NEED_IP(t+4);
-#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4)
+ t += 3;
+ if (t >= 8) do
+ {
+ UA_COPY64(op,ip);
+ op += 8; ip += 8; t -= 8;
+ } while (t >= 8);
+ if (t >= 4)
+ {
+ UA_COPY32(op,ip);
+ op += 4; ip += 4; t -= 4;
+ }
+ if (t > 0)
+ {
+ *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)
if (PTR_ALIGNED2_4(op,ip))
{
#endif
- COPY4(op,ip);
+ UA_COPY32(op,ip);
op += 4; ip += 4;
if (--t > 0)
{
if (t >= 4)
{
do {
- COPY4(op,ip);
+ UA_COPY32(op,ip);
op += 4; ip += 4; t -= 4;
} while (t >= 4);
if (t > 0) do *op++ = *ip++; while (--t > 0);
@@ -3316,7 +3734,7 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
else
#endif
#endif
-#if !defined(LZO_UNALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4) && !defined(LZO_UNALIGNED_OK_8)
{
*op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
do *op++ = *ip++; while (--t > 0);
@@ -3437,7 +3855,7 @@ match:
}
#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
m_pos = op - 1;
- m_pos -= (* (const lzo_ushortp) ip) >> 2;
+ m_pos -= UA_GET16(ip) >> 2;
#else
m_pos = op - 1;
m_pos -= (ip[0] >> 2) + (ip[1] << 6);
@@ -3482,7 +3900,7 @@ match:
#if defined(LZO1Z)
m_pos -= (ip[0] << 6) + (ip[1] >> 2);
#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
- m_pos -= (* (const lzo_ushortp) ip) >> 2;
+ m_pos -= UA_GET16(ip) >> 2;
#else
m_pos -= (ip[0] >> 2) + (ip[1] << 6);
#endif
@@ -3530,7 +3948,28 @@ match:
#else
TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
-#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4)
+ if (op - m_pos >= 8)
+ {
+ t += (3 - 1);
+ if (t >= 8) do
+ {
+ UA_COPY64(op,m_pos);
+ op += 8; m_pos += 8; t -= 8;
+ } while (t >= 8);
+ if (t >= 4)
+ {
+ UA_COPY32(op,m_pos);
+ op += 4; m_pos += 4; t -= 4;
+ }
+ if (t > 0)
+ {
+ *op++ = m_pos[0];
+ if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } }
+ }
+ }
+ else
+#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
#if !defined(LZO_UNALIGNED_OK_4)
if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos))
{
@@ -3539,10 +3978,10 @@ match:
if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
{
#endif
- COPY4(op,m_pos);
+ UA_COPY32(op,m_pos);
op += 4; m_pos += 4; t -= 4 - (3 - 1);
do {
- COPY4(op,m_pos);
+ UA_COPY32(op,m_pos);
op += 4; m_pos += 4; t -= 4;
} while (t >= 4);
if (t > 0) do *op++ = *m_pos++; while (--t > 0);
@@ -3610,7 +4049,7 @@ lookbehind_overrun:
#endif
-#define LZO_TEST_OVERRUN
+#define LZO_TEST_OVERRUN 1
#undef DO_DECOMPRESS
#define DO_DECOMPRESS lzo1x_decompress_safe
@@ -3624,7 +4063,7 @@ lookbehind_overrun:
# define LZO_TEST_OVERRUN_OUTPUT 2
# endif
# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND)
-# define LZO_TEST_OVERRUN_LOOKBEHIND
+# define LZO_TEST_OVERRUN_LOOKBEHIND 1
# endif
#endif
@@ -3675,42 +4114,32 @@ lookbehind_overrun:
#endif
#if defined(TEST_IP)
-# define HAVE_TEST_IP
+# define HAVE_TEST_IP 1
#else
# define TEST_IP 1
#endif
#if defined(TEST_OP)
-# define HAVE_TEST_OP
+# define HAVE_TEST_OP 1
#else
# define TEST_OP 1
#endif
#if defined(NEED_IP)
-# define HAVE_NEED_IP
+# define HAVE_NEED_IP 1
#else
# define NEED_IP(x) ((void) 0)
#endif
#if defined(NEED_OP)
-# define HAVE_NEED_OP
+# define HAVE_NEED_OP 1
#else
# define NEED_OP(x) ((void) 0)
#endif
#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP)
-# define HAVE_ANY_IP
+# define HAVE_ANY_IP 1
#endif
#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP)
-# define HAVE_ANY_OP
-#endif
-
-#undef __COPY4
-#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src)
-
-#undef COPY4
-#if defined(LZO_UNALIGNED_OK_4)
-# define COPY4(dst,src) __COPY4(dst,src)
-#elif defined(LZO_ALIGNED_OK_4)
-# define COPY4(dst,src) __COPY4((lzo_uintptr_t)(dst),(lzo_uintptr_t)(src))
+# define HAVE_ANY_OP 1
#endif
#if defined(DO_DECOMPRESS)
@@ -3789,19 +4218,36 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
t += 15 + *ip++;
}
assert(t > 0); NEED_OP(t+3); NEED_IP(t+4);
-#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4)
+ t += 3;
+ if (t >= 8) do
+ {
+ UA_COPY64(op,ip);
+ op += 8; ip += 8; t -= 8;
+ } while (t >= 8);
+ if (t >= 4)
+ {
+ UA_COPY32(op,ip);
+ op += 4; ip += 4; t -= 4;
+ }
+ if (t > 0)
+ {
+ *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)
if (PTR_ALIGNED2_4(op,ip))
{
#endif
- COPY4(op,ip);
+ UA_COPY32(op,ip);
op += 4; ip += 4;
if (--t > 0)
{
if (t >= 4)
{
do {
- COPY4(op,ip);
+ UA_COPY32(op,ip);
op += 4; ip += 4; t -= 4;
} while (t >= 4);
if (t > 0) do *op++ = *ip++; while (--t > 0);
@@ -3814,7 +4260,7 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
else
#endif
#endif
-#if !defined(LZO_UNALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4) && !defined(LZO_UNALIGNED_OK_8)
{
*op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
do *op++ = *ip++; while (--t > 0);
@@ -3935,7 +4381,7 @@ match:
}
#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
m_pos = op - 1;
- m_pos -= (* (const lzo_ushortp) ip) >> 2;
+ m_pos -= UA_GET16(ip) >> 2;
#else
m_pos = op - 1;
m_pos -= (ip[0] >> 2) + (ip[1] << 6);
@@ -3980,7 +4426,7 @@ match:
#if defined(LZO1Z)
m_pos -= (ip[0] << 6) + (ip[1] >> 2);
#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
- m_pos -= (* (const lzo_ushortp) ip) >> 2;
+ m_pos -= UA_GET16(ip) >> 2;
#else
m_pos -= (ip[0] >> 2) + (ip[1] << 6);
#endif
@@ -4028,7 +4474,28 @@ match:
#else
TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
-#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4)
+ if (op - m_pos >= 8)
+ {
+ t += (3 - 1);
+ if (t >= 8) do
+ {
+ UA_COPY64(op,m_pos);
+ op += 8; m_pos += 8; t -= 8;
+ } while (t >= 8);
+ if (t >= 4)
+ {
+ UA_COPY32(op,m_pos);
+ op += 4; m_pos += 4; t -= 4;
+ }
+ if (t > 0)
+ {
+ *op++ = m_pos[0];
+ if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } }
+ }
+ }
+ else
+#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
#if !defined(LZO_UNALIGNED_OK_4)
if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos))
{
@@ -4037,10 +4504,10 @@ match:
if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
{
#endif
- COPY4(op,m_pos);
+ UA_COPY32(op,m_pos);
op += 4; m_pos += 4; t -= 4 - (3 - 1);
do {
- COPY4(op,m_pos);
+ UA_COPY32(op,m_pos);
op += 4; m_pos += 4; t -= 4;
} while (t >= 4);
if (t > 0) do *op++ = *m_pos++; while (--t > 0);
diff --git a/extern/lzo/minilzo/minilzo.h b/extern/lzo/minilzo/minilzo.h
index 93916bc89b2..f2c104856e3 100644
--- a/extern/lzo/minilzo/minilzo.h
+++ b/extern/lzo/minilzo/minilzo.h
@@ -2,6 +2,9 @@
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
@@ -45,9 +48,9 @@
#ifndef __MINILZO_H
-#define __MINILZO_H
+#define __MINILZO_H 1
-#define MINILZO_VERSION 0x2030
+#define MINILZO_VERSION 0x2060
#ifdef __LZOCONF_H
# error "you cannot use both LZO and miniLZO"
@@ -103,7 +106,6 @@ lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
#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/CMakeLists.txt b/extern/rangetree/CMakeLists.txt
new file mode 100644
index 00000000000..ba682233381
--- /dev/null
+++ b/extern/rangetree/CMakeLists.txt
@@ -0,0 +1,31 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+)
+
+set(SRC
+ range_tree.hh
+ range_tree_c_api.h
+
+ range_tree_c_api.cc
+)
+
+blender_add_lib(extern_rangetree "${SRC}" "${INC}" "")
+
diff --git a/extern/rangetree/README.org b/extern/rangetree/README.org
new file mode 100644
index 00000000000..46a4cedaf8f
--- /dev/null
+++ b/extern/rangetree/README.org
@@ -0,0 +1,13 @@
+* Overview
+ Basic class for storing non-overlapping scalar ranges. Underlying
+ representation is a C++ STL set for fast lookups.
+
+* License
+ GPL version 2 or later (see COPYING)
+
+* Author Note
+ This implementation is intended for storing free unique IDs in a new
+ undo system for BMesh in Blender, but could be useful elsewhere.
+
+* Website
+ https://github.com/nicholasbishop/RangeTree
diff --git a/extern/rangetree/SConscript b/extern/rangetree/SConscript
new file mode 100644
index 00000000000..787decd599e
--- /dev/null
+++ b/extern/rangetree/SConscript
@@ -0,0 +1,9 @@
+2#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.cc')
+
+incs = '.'
+defs = ''
+
+env.BlenderLib ('extern_rangetree', sources, Split(incs), Split(defs), libtype=['extern'], priority=[100] )
diff --git a/extern/rangetree/range_tree.hh b/extern/rangetree/range_tree.hh
new file mode 100644
index 00000000000..2a47c5a1d93
--- /dev/null
+++ b/extern/rangetree/range_tree.hh
@@ -0,0 +1,228 @@
+/* This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#include <cassert>
+#include <climits>
+#include <iostream>
+#include <set>
+
+#ifndef RANGE_TREE_DEBUG_PRINT_FUNCTION
+# define RANGE_TREE_DEBUG_PRINT_FUNCTION 0
+#endif
+
+template <typename T>
+struct RangeTree {
+ struct Range {
+ Range(T min_, T max_)
+ : min(min_), max(max_), single(min_ == max_) {
+ assert(min_ <= max_);
+ }
+
+ Range(T t)
+ : min(t), max(t), single(true)
+ {}
+
+ bool operator<(const Range& v) const {
+ return max < v.min;
+ }
+
+ const T min;
+ const T max;
+ const bool single;
+ };
+
+ typedef std::set<Range> Tree;
+ typedef typename Tree::iterator TreeIter;
+ typedef typename Tree::reverse_iterator TreeIterReverse;
+ typedef typename Tree::const_iterator TreeIterConst;
+
+ /* Initialize with a single range from 'min' to 'max', inclusive. */
+ RangeTree(T min, T max) {
+ tree.insert(Range(min, max));
+ }
+
+ /* Initialize with a single range from 0 to 'max', inclusive. */
+ RangeTree(T max) {
+ tree.insert(Range(0, max));
+ }
+
+ RangeTree(const RangeTree<T>& src) {
+ tree = src.tree;
+ }
+
+ /* Remove 't' from the associated range in the tree. Precondition:
+ a range including 't' must exist in the tree. */
+ void take(T t) {
+ #if RANGE_TREE_DEBUG_PRINT_FUNCTION
+ std::cout << __func__ << "(" << t << ")\n";
+ #endif
+
+ /* Find the range that includes 't' and its neighbors */
+ TreeIter iter = tree.find(Range(t));
+ assert(iter != tree.end());
+ Range cur = *iter;
+ TreeIter prev = iter;
+ TreeIter next = iter;
+ --prev;
+ ++next;
+
+ /* Remove the original range (note that this does not
+ invalidate the prev/next iterators) */
+ tree.erase(iter);
+
+ /* Construct two new ranges that together cover the original
+ range, except for 't' */
+ if (t > cur.min)
+ tree.insert(Range(cur.min, t - 1));
+ if (t + 1 <= cur.max)
+ tree.insert(Range(t + 1, cur.max));
+ }
+
+ /* Take the first element out of the first range in the
+ tree. Precondition: tree must not be empty. */
+ T take_any() {
+ #if RANGE_TREE_DEBUG_PRINT_FUNCTION
+ std::cout << __func__ << "()\n";
+ #endif
+
+ /* Find the first element */
+ TreeIter iter = tree.begin();
+ assert(iter != tree.end());
+ T first = iter->min;
+
+ /* Take the first element */
+ take(first);
+ return first;
+ }
+
+ /* Return 't' to the tree, either expanding/merging existing
+ ranges or adding a range to cover it. Precondition: 't' cannot
+ be in an existing range. */
+ void release(T t) {
+ #if RANGE_TREE_DEBUG_PRINT_FUNCTION
+ std::cout << __func__ << "(" << t << ")\n";
+ #endif
+
+ /* TODO: these cases should be simplified/unified */
+
+ TreeIter right = tree.upper_bound(t);
+ if (right != tree.end()) {
+ TreeIter left = right;
+ if (left != tree.begin())
+ --left;
+
+ if (left == right) {
+ /* 't' lies before any existing ranges */
+ if (t + 1 == left->min) {
+ /* 't' lies directly before the first range,
+ resize and replace that range */
+ const Range r(t, left->max);
+ tree.erase(left);
+ tree.insert(r);
+ }
+ else {
+ /* There's a gap between 't' and the first range,
+ add a new range */
+ tree.insert(Range(t));
+ }
+ }
+ else if ((left->max + 1 == t) &&
+ (t + 1 == right->min)) {
+ /* 't' fills a hole. Remove left and right, and insert a
+ new range that covers both. */
+ const Range r(left->min, right->max);
+ tree.erase(left);
+ tree.erase(right);
+ tree.insert(r);
+ }
+ else if (left->max + 1 == t) {
+ /* 't' lies directly after 'left' range, resize and
+ replace that range */
+ const Range r(left->min, t);
+ tree.erase(left);
+ tree.insert(r);
+ }
+ else if (t + 1 == right->min) {
+ /* 't' lies directly before 'right' range, resize and
+ replace that range */
+ const Range r(t, right->max);
+ tree.erase(right);
+ tree.insert(r);
+ }
+ else {
+ /* There's a gap between 't' and both adjacent ranges,
+ add a new range */
+ tree.insert(Range(t));
+ }
+ }
+ else {
+ /* 't' lies after any existing ranges */
+ right = tree.end();
+ right--;
+ if (right->max + 1 == t) {
+ /* 't' lies directly after last range, resize and
+ replace that range */
+ const Range r(right->min, t);
+ tree.erase(right);
+ tree.insert(r);
+ }
+ else {
+ /* There's a gap between the last range and 't', add a
+ new range */
+ tree.insert(Range(t));
+ }
+ }
+ }
+
+ bool has(T t) const {
+ TreeIterConst iter = tree.find(Range(t));
+ return (iter != tree.end()) && (t <= iter->max);
+ }
+
+ bool has_range(T min, T max) const {
+ TreeIterConst iter = tree.find(Range(min, max));
+ return (iter != tree.end()) && (min == iter->min && max == iter->max);
+ }
+
+ bool empty() const {
+ return tree.empty();
+ }
+
+ int size() const {
+ return tree.size();
+ }
+
+ void print() const {
+ std::cout << "RangeTree:\n";
+ for (TreeIterConst iter = tree.begin(); iter != tree.end(); ++iter) {
+ const Range& r = *iter;
+ if (r.single)
+ std::cout << " [" << r.min << "]\n";
+ else
+ std::cout << " [" << r.min << ", " << r.max << "]\n";
+ }
+ if (empty())
+ std::cout << " <empty>";
+ std::cout << "\n";
+ }
+
+ unsigned int allocation_lower_bound() const {
+ return tree.size() * sizeof(Range);
+ }
+
+private:
+ Tree tree;
+};
diff --git a/extern/rangetree/range_tree_c_api.cc b/extern/rangetree/range_tree_c_api.cc
new file mode 100644
index 00000000000..56f2d90d329
--- /dev/null
+++ b/extern/rangetree/range_tree_c_api.cc
@@ -0,0 +1,86 @@
+/* This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#include "range_tree.hh"
+
+/* Give RangeTreeUInt a real type rather than the opaque struct type
+ defined for external use. */
+#define RANGE_TREE_C_API_INTERNAL
+typedef RangeTree<unsigned> RangeTreeUInt;
+
+#include "range_tree_c_api.h"
+
+RangeTreeUInt *range_tree_uint_alloc(unsigned min, unsigned max)
+{
+ return new RangeTreeUInt(min, max);
+}
+
+RangeTreeUInt *range_tree_uint_copy(RangeTreeUInt *src)
+{
+ return new RangeTreeUInt(*src);
+}
+
+void range_tree_uint_free(RangeTreeUInt *rt)
+{
+ delete rt;
+}
+
+void range_tree_uint_take(RangeTreeUInt *rt, unsigned v)
+{
+ rt->take(v);
+}
+
+unsigned range_tree_uint_take_any(RangeTreeUInt *rt)
+{
+ return rt->take_any();
+}
+
+void range_tree_uint_release(RangeTreeUInt *rt, unsigned v)
+{
+ rt->release(v);
+}
+
+int 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)
+{
+ return rt->has_range(vmin, vmax);
+}
+
+int range_tree_uint_empty(const RangeTreeUInt *rt)
+{
+ return rt->empty();
+}
+
+unsigned range_tree_uint_size(const RangeTreeUInt *rt)
+{
+ return rt->size();
+}
+
+void range_tree_uint_print(const RangeTreeUInt *rt)
+{
+ rt->print();
+}
+
+unsigned int range_tree_uint_allocation_lower_bound(const RangeTreeUInt *rt)
+{
+ return rt->allocation_lower_bound();
+}
diff --git a/extern/rangetree/range_tree_c_api.h b/extern/rangetree/range_tree_c_api.h
new file mode 100644
index 00000000000..af6a7b161a8
--- /dev/null
+++ b/extern/rangetree/range_tree_c_api.h
@@ -0,0 +1,60 @@
+/* This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#ifndef RANGE_TREE_C_API_H
+#define RANGE_TREE_C_API_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Simple C-accessible wrapper for RangeTree<unsigned> */
+
+#ifndef RANGE_TREE_C_API_INTERNAL
+typedef struct RangeTreeUInt RangeTreeUInt;
+#endif
+
+RangeTreeUInt *range_tree_uint_alloc(unsigned min, unsigned max);
+
+RangeTreeUInt *range_tree_uint_copy(RangeTreeUInt *src);
+
+void range_tree_uint_free(RangeTreeUInt *rt);
+
+void range_tree_uint_take(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);
+
+int range_tree_uint_has_range(const RangeTreeUInt *rt,
+ unsigned vmin,
+ unsigned vmax);
+
+int range_tree_uint_empty(const RangeTreeUInt *rt);
+
+unsigned range_tree_uint_size(const RangeTreeUInt *rt);
+
+void range_tree_uint_print(const RangeTreeUInt *rt);
+
+unsigned int range_tree_uint_allocation_lower_bound(const RangeTreeUInt *rt);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DUALCON_H__ */
diff --git a/extern/wcwidth/CMakeLists.txt b/extern/wcwidth/CMakeLists.txt
new file mode 100644
index 00000000000..724c5ea5d74
--- /dev/null
+++ b/extern/wcwidth/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) 2013, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+)
+
+set(INC_SYS
+
+)
+
+set(SRC
+ wcwidth.c
+
+ wcwidth.h
+)
+
+blender_add_lib(extern_wcwidth "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/extern/wcwidth/SConscript b/extern/wcwidth/SConscript
new file mode 100644
index 00000000000..14fdaf3f738
--- /dev/null
+++ b/extern/wcwidth/SConscript
@@ -0,0 +1,9 @@
+#!/usr/bin/python
+
+Import('env')
+
+sources = env.Glob('*.c')
+
+incs = '.'
+
+env.BlenderLib ( 'extern_wcwidth', sources, Split(incs), [], libtype=['extern','player'], priority=[10, 185])
diff --git a/extern/wcwidth/wcwidth.c b/extern/wcwidth/wcwidth.c
new file mode 100644
index 00000000000..61e822ad679
--- /dev/null
+++ b/extern/wcwidth/wcwidth.c
@@ -0,0 +1,309 @@
+/*
+ * This is an implementation of wcwidth() and wcswidth() (defined in
+ * IEEE Std 1002.1-2001) for Unicode.
+ *
+ * http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html
+ * http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html
+ *
+ * In fixed-width output devices, Latin characters all occupy a single
+ * "cell" position of equal width, whereas ideographic CJK characters
+ * occupy two such cells. Interoperability between terminal-line
+ * applications and (teletype-style) character terminals using the
+ * UTF-8 encoding requires agreement on which character should advance
+ * the cursor by how many cell positions. No established formal
+ * standards exist at present on which Unicode character shall occupy
+ * how many cell positions on character terminals. These routines are
+ * a first attempt of defining such behavior based on simple rules
+ * applied to data provided by the Unicode Consortium.
+ *
+ * For some graphical characters, the Unicode standard explicitly
+ * defines a character-cell width via the definition of the East Asian
+ * FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes.
+ * In all these cases, there is no ambiguity about which width a
+ * terminal shall use. For characters in the East Asian Ambiguous (A)
+ * class, the width choice depends purely on a preference of backward
+ * compatibility with either historic CJK or Western practice.
+ * Choosing single-width for these characters is easy to justify as
+ * the appropriate long-term solution, as the CJK practice of
+ * displaying these characters as double-width comes from historic
+ * implementation simplicity (8-bit encoded characters were displayed
+ * single-width and 16-bit ones double-width, even for Greek,
+ * Cyrillic, etc.) and not any typographic considerations.
+ *
+ * Much less clear is the choice of width for the Not East Asian
+ * (Neutral) class. Existing practice does not dictate a width for any
+ * of these characters. It would nevertheless make sense
+ * typographically to allocate two character cells to characters such
+ * as for instance EM SPACE or VOLUME INTEGRAL, which cannot be
+ * represented adequately with a single-width glyph. The following
+ * routines at present merely assign a single-cell width to all
+ * neutral characters, in the interest of simplicity. This is not
+ * entirely satisfactory and should be reconsidered before
+ * establishing a formal standard in this area. At the moment, the
+ * decision which Not East Asian (Neutral) characters should be
+ * represented by double-width glyphs cannot yet be answered by
+ * applying a simple rule from the Unicode database content. Setting
+ * up a proper standard for the behavior of UTF-8 character terminals
+ * will require a careful analysis not only of each Unicode character,
+ * but also of each presentation form, something the author of these
+ * routines has avoided to do so far.
+ *
+ * http://www.unicode.org/unicode/reports/tr11/
+ *
+ * Markus Kuhn -- 2007-05-26 (Unicode 5.0)
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * for any purpose and without fee is hereby granted. The author
+ * disclaims all warranties with regard to this software.
+ *
+ * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
+ */
+
+#include <wchar.h>
+
+struct interval {
+ int first;
+ int last;
+};
+
+/* auxiliary function for binary search in interval table */
+static int bisearch(wchar_t ucs, const struct interval *table, int max) {
+ int min = 0;
+ int mid;
+
+ if (ucs < table[0].first || ucs > table[max].last)
+ return 0;
+ while (max >= min) {
+ mid = (min + max) / 2;
+ if (ucs > table[mid].last)
+ min = mid + 1;
+ else if (ucs < table[mid].first)
+ max = mid - 1;
+ else
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* The following two functions define the column width of an ISO 10646
+ * character as follows:
+ *
+ * - The null character (U+0000) has a column width of 0.
+ *
+ * - Other C0/C1 control characters and DEL will lead to a return
+ * value of -1.
+ *
+ * - Non-spacing and enclosing combining characters (general
+ * category code Mn or Me in the Unicode database) have a
+ * column width of 0.
+ *
+ * - SOFT HYPHEN (U+00AD) has a column width of 1.
+ *
+ * - Other format characters (general category code Cf in the Unicode
+ * database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
+ *
+ * - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
+ * have a column width of 0.
+ *
+ * - Spacing characters in the East Asian Wide (W) or East Asian
+ * Full-width (F) category as defined in Unicode Technical
+ * Report #11 have a column width of 2.
+ *
+ * - All remaining characters (including all printable
+ * ISO 8859-1 and WGL4 characters, Unicode control characters,
+ * etc.) have a column width of 1.
+ *
+ * This implementation assumes that wchar_t characters are encoded
+ * in ISO 10646.
+ */
+
+int mk_wcwidth(wchar_t ucs)
+{
+ /* sorted list of non-overlapping intervals of non-spacing characters */
+ /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
+ static const struct interval combining[] = {
+ { 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 },
+ { 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
+ { 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 },
+ { 0x0610, 0x0615 }, { 0x064B, 0x065E }, { 0x0670, 0x0670 },
+ { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
+ { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },
+ { 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0901, 0x0902 },
+ { 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D },
+ { 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 },
+ { 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD },
+ { 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C },
+ { 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D },
+ { 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC },
+ { 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD },
+ { 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C },
+ { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D },
+ { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 },
+ { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 },
+ { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC },
+ { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
+ { 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D },
+ { 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 },
+ { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E },
+ { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC },
+ { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 },
+ { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E },
+ { 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 },
+ { 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 },
+ { 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 },
+ { 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x135F, 0x135F },
+ { 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 },
+ { 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD },
+ { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD },
+ { 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 },
+ { 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B },
+ { 0x1A17, 0x1A18 }, { 0x1B00, 0x1B03 }, { 0x1B34, 0x1B34 },
+ { 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, { 0x1B42, 0x1B42 },
+ { 0x1B6B, 0x1B73 }, { 0x1DC0, 0x1DCA }, { 0x1DFE, 0x1DFF },
+ { 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 },
+ { 0x206A, 0x206F }, { 0x20D0, 0x20EF }, { 0x302A, 0x302F },
+ { 0x3099, 0x309A }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B },
+ { 0xA825, 0xA826 }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F },
+ { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB },
+ { 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F },
+ { 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x1D167, 0x1D169 },
+ { 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD },
+ { 0x1D242, 0x1D244 }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F },
+ { 0xE0100, 0xE01EF }
+ };
+
+ /* test for 8-bit control characters */
+ if (ucs == 0)
+ return 0;
+ if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
+ return -1;
+
+ /* binary search in table of non-spacing characters */
+ if (bisearch(ucs, combining,
+ sizeof(combining) / sizeof(struct interval) - 1))
+ return 0;
+
+ /* if we arrive here, ucs is not a combining or C0/C1 control character */
+
+ return 1 +
+ (ucs >= 0x1100 &&
+ (ucs <= 0x115f || /* Hangul Jamo init. consonants */
+ ucs == 0x2329 || ucs == 0x232a ||
+ (ucs >= 0x2e80 && ucs <= 0xa4cf &&
+ ucs != 0x303f) || /* CJK ... Yi */
+ (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
+ (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
+ (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
+ (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
+ (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
+ (ucs >= 0xffe0 && ucs <= 0xffe6) ||
+ (ucs >= 0x20000 && ucs <= 0x2fffd) ||
+ (ucs >= 0x30000 && ucs <= 0x3fffd)));
+}
+
+
+int mk_wcswidth(const wchar_t *pwcs, size_t n)
+{
+ int w, width = 0;
+
+ for (;*pwcs && n-- > 0; pwcs++)
+ if ((w = mk_wcwidth(*pwcs)) < 0)
+ return -1;
+ else
+ width += w;
+
+ return width;
+}
+
+
+/*
+ * The following functions are the same as mk_wcwidth() and
+ * mk_wcswidth(), except that spacing characters in the East Asian
+ * Ambiguous (A) category as defined in Unicode Technical Report #11
+ * have a column width of 2. This variant might be useful for users of
+ * CJK legacy encodings who want to migrate to UCS without changing
+ * the traditional terminal character-width behaviour. It is not
+ * otherwise recommended for general use.
+ */
+int mk_wcwidth_cjk(wchar_t ucs)
+{
+ /* sorted list of non-overlapping intervals of East Asian Ambiguous
+ * characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
+ static const struct interval ambiguous[] = {
+ { 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 },
+ { 0x00AA, 0x00AA }, { 0x00AE, 0x00AE }, { 0x00B0, 0x00B4 },
+ { 0x00B6, 0x00BA }, { 0x00BC, 0x00BF }, { 0x00C6, 0x00C6 },
+ { 0x00D0, 0x00D0 }, { 0x00D7, 0x00D8 }, { 0x00DE, 0x00E1 },
+ { 0x00E6, 0x00E6 }, { 0x00E8, 0x00EA }, { 0x00EC, 0x00ED },
+ { 0x00F0, 0x00F0 }, { 0x00F2, 0x00F3 }, { 0x00F7, 0x00FA },
+ { 0x00FC, 0x00FC }, { 0x00FE, 0x00FE }, { 0x0101, 0x0101 },
+ { 0x0111, 0x0111 }, { 0x0113, 0x0113 }, { 0x011B, 0x011B },
+ { 0x0126, 0x0127 }, { 0x012B, 0x012B }, { 0x0131, 0x0133 },
+ { 0x0138, 0x0138 }, { 0x013F, 0x0142 }, { 0x0144, 0x0144 },
+ { 0x0148, 0x014B }, { 0x014D, 0x014D }, { 0x0152, 0x0153 },
+ { 0x0166, 0x0167 }, { 0x016B, 0x016B }, { 0x01CE, 0x01CE },
+ { 0x01D0, 0x01D0 }, { 0x01D2, 0x01D2 }, { 0x01D4, 0x01D4 },
+ { 0x01D6, 0x01D6 }, { 0x01D8, 0x01D8 }, { 0x01DA, 0x01DA },
+ { 0x01DC, 0x01DC }, { 0x0251, 0x0251 }, { 0x0261, 0x0261 },
+ { 0x02C4, 0x02C4 }, { 0x02C7, 0x02C7 }, { 0x02C9, 0x02CB },
+ { 0x02CD, 0x02CD }, { 0x02D0, 0x02D0 }, { 0x02D8, 0x02DB },
+ { 0x02DD, 0x02DD }, { 0x02DF, 0x02DF }, { 0x0391, 0x03A1 },
+ { 0x03A3, 0x03A9 }, { 0x03B1, 0x03C1 }, { 0x03C3, 0x03C9 },
+ { 0x0401, 0x0401 }, { 0x0410, 0x044F }, { 0x0451, 0x0451 },
+ { 0x2010, 0x2010 }, { 0x2013, 0x2016 }, { 0x2018, 0x2019 },
+ { 0x201C, 0x201D }, { 0x2020, 0x2022 }, { 0x2024, 0x2027 },
+ { 0x2030, 0x2030 }, { 0x2032, 0x2033 }, { 0x2035, 0x2035 },
+ { 0x203B, 0x203B }, { 0x203E, 0x203E }, { 0x2074, 0x2074 },
+ { 0x207F, 0x207F }, { 0x2081, 0x2084 }, { 0x20AC, 0x20AC },
+ { 0x2103, 0x2103 }, { 0x2105, 0x2105 }, { 0x2109, 0x2109 },
+ { 0x2113, 0x2113 }, { 0x2116, 0x2116 }, { 0x2121, 0x2122 },
+ { 0x2126, 0x2126 }, { 0x212B, 0x212B }, { 0x2153, 0x2154 },
+ { 0x215B, 0x215E }, { 0x2160, 0x216B }, { 0x2170, 0x2179 },
+ { 0x2190, 0x2199 }, { 0x21B8, 0x21B9 }, { 0x21D2, 0x21D2 },
+ { 0x21D4, 0x21D4 }, { 0x21E7, 0x21E7 }, { 0x2200, 0x2200 },
+ { 0x2202, 0x2203 }, { 0x2207, 0x2208 }, { 0x220B, 0x220B },
+ { 0x220F, 0x220F }, { 0x2211, 0x2211 }, { 0x2215, 0x2215 },
+ { 0x221A, 0x221A }, { 0x221D, 0x2220 }, { 0x2223, 0x2223 },
+ { 0x2225, 0x2225 }, { 0x2227, 0x222C }, { 0x222E, 0x222E },
+ { 0x2234, 0x2237 }, { 0x223C, 0x223D }, { 0x2248, 0x2248 },
+ { 0x224C, 0x224C }, { 0x2252, 0x2252 }, { 0x2260, 0x2261 },
+ { 0x2264, 0x2267 }, { 0x226A, 0x226B }, { 0x226E, 0x226F },
+ { 0x2282, 0x2283 }, { 0x2286, 0x2287 }, { 0x2295, 0x2295 },
+ { 0x2299, 0x2299 }, { 0x22A5, 0x22A5 }, { 0x22BF, 0x22BF },
+ { 0x2312, 0x2312 }, { 0x2460, 0x24E9 }, { 0x24EB, 0x254B },
+ { 0x2550, 0x2573 }, { 0x2580, 0x258F }, { 0x2592, 0x2595 },
+ { 0x25A0, 0x25A1 }, { 0x25A3, 0x25A9 }, { 0x25B2, 0x25B3 },
+ { 0x25B6, 0x25B7 }, { 0x25BC, 0x25BD }, { 0x25C0, 0x25C1 },
+ { 0x25C6, 0x25C8 }, { 0x25CB, 0x25CB }, { 0x25CE, 0x25D1 },
+ { 0x25E2, 0x25E5 }, { 0x25EF, 0x25EF }, { 0x2605, 0x2606 },
+ { 0x2609, 0x2609 }, { 0x260E, 0x260F }, { 0x2614, 0x2615 },
+ { 0x261C, 0x261C }, { 0x261E, 0x261E }, { 0x2640, 0x2640 },
+ { 0x2642, 0x2642 }, { 0x2660, 0x2661 }, { 0x2663, 0x2665 },
+ { 0x2667, 0x266A }, { 0x266C, 0x266D }, { 0x266F, 0x266F },
+ { 0x273D, 0x273D }, { 0x2776, 0x277F }, { 0xE000, 0xF8FF },
+ { 0xFFFD, 0xFFFD }, { 0xF0000, 0xFFFFD }, { 0x100000, 0x10FFFD }
+ };
+
+ /* binary search in table of non-spacing characters */
+ if (bisearch(ucs, ambiguous,
+ sizeof(ambiguous) / sizeof(struct interval) - 1))
+ return 2;
+
+ return mk_wcwidth(ucs);
+}
+
+
+int mk_wcswidth_cjk(const wchar_t *pwcs, size_t n)
+{
+ int w, width = 0;
+
+ for (;*pwcs && n-- > 0; pwcs++)
+ if ((w = mk_wcwidth_cjk(*pwcs)) < 0)
+ return -1;
+ else
+ width += w;
+
+ return width;
+}
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.cpp b/extern/wcwidth/wcwidth.h
index 58b94df6221..e327921b6ea 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsController.cpp
+++ b/extern/wcwidth/wcwidth.h
@@ -15,24 +15,22 @@
* 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.
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
* All rights reserved.
*
- * The Original Code is: all of this file.
- *
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file gameengine/Physics/common/PHY_IPhysicsController.cpp
- * \ingroup phys
- */
-
-#include "PHY_IPhysicsController.h"
+#ifndef __WCWIDTH_H__
+#define __WCWIDTH_H__
-PHY_IPhysicsController::~PHY_IPhysicsController()
-{
+#include <wchar.h>
-}
+int mk_wcwidth(wchar_t ucs);
+int mk_wcswidth(const wchar_t *pwcs, size_t n);
+int mk_wcwidth_cjk(wchar_t ucs);
+int mk_wcswidth_cjk(const wchar_t *pwcs, size_t n);
+#endif
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index be797c45ba1..bb8cd7aaf70 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -69,6 +69,14 @@ if(WITH_INTERNATIONAL)
add_subdirectory(locale)
endif()
+if(WITH_BULLET)
+ add_subdirectory(rigidbody)
+endif()
+
+if(WITH_COMPOSITOR)
+ add_subdirectory(opencl)
+endif()
+
# only windows needs utf16 converter
if(WIN32)
add_subdirectory(utfconv)
diff --git a/intern/SConscript b/intern/SConscript
index 5360ce4ea88..828c1adc20d 100644
--- a/intern/SConscript
+++ b/intern/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
SConscript(['audaspace/SConscript',
@@ -33,6 +59,12 @@ if env['WITH_BF_BOOLEAN']:
if env['WITH_BF_INTERNATIONAL']:
SConscript(['locale/SConscript'])
+if env['WITH_BF_BULLET']:
+ SConscript (['rigidbody/SConscript'])
+
+if env['WITH_BF_COMPOSITOR']:
+ SConscript (['opencl/SConscript'])
+
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-mingw', 'linuxcross', 'win64-vc'):
SConscript(['utfconv/SConscript'])
diff --git a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h
index d9df65f03eb..66f82ba1a01 100644
--- a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h
+++ b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h
@@ -77,7 +77,7 @@ public:
AUD_CallbackIIRFilterReader(boost::shared_ptr<AUD_IReader> reader, int in, int out,
doFilterIIR doFilter,
endFilterIIR endFilter = 0,
- void* data = 0);
+ void* data = NULL);
virtual ~AUD_CallbackIIRFilterReader();
diff --git a/intern/audaspace/FX/AUD_IDynamicIIRFilterCalculator.h b/intern/audaspace/FX/AUD_IDynamicIIRFilterCalculator.h
index 29b87e57ad0..2e0d8418571 100644
--- a/intern/audaspace/FX/AUD_IDynamicIIRFilterCalculator.h
+++ b/intern/audaspace/FX/AUD_IDynamicIIRFilterCalculator.h
@@ -40,6 +40,8 @@
class AUD_IDynamicIIRFilterCalculator
{
public:
+ virtual ~AUD_IDynamicIIRFilterCalculator() {}
+
/**
* Recalculates the filter coefficients.
* \param rate The sample rate of the audio data.
diff --git a/intern/audaspace/SConscript b/intern/audaspace/SConscript
index e2b6efacc96..ba549530e64 100644
--- a/intern/audaspace/SConscript
+++ b/intern/audaspace/SConscript
@@ -1,4 +1,25 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN LGPL LICENSE BLOCK *****
+#
+# Copyright 2009 Jrg Hermann Mller
+#
+# This file is part of AudaSpace.
+#
+# AudaSpace 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 3 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 Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+#
+# ***** END LGPL LICENSE BLOCK *****
Import ('env')
diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
index 0a3d0f8e85a..47bfe4e69b9 100644
--- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
+++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
@@ -107,7 +107,7 @@ void AUD_FFMPEGReader::init()
m_position = 0;
m_pkgbuf_left = 0;
- if(av_find_stream_info(m_formatCtx)<0)
+ if(avformat_find_stream_info(m_formatCtx, NULL) < 0)
AUD_THROW(AUD_ERROR_FFMPEG, streaminfo_error);
// find audio stream and codec
@@ -133,7 +133,12 @@ void AUD_FFMPEGReader::init()
if(!aCodec)
AUD_THROW(AUD_ERROR_FFMPEG, nodecoder_error);
- if(avcodec_open(m_codecCtx, aCodec)<0)
+#ifdef FFMPEG_SAMPLE_FMT_S16P_SUPPORTED
+ if(m_codecCtx->sample_fmt == AV_SAMPLE_FMT_S16P)
+ m_codecCtx->request_sample_fmt = AV_SAMPLE_FMT_S16;
+#endif
+
+ if(avcodec_open2(m_codecCtx, aCodec, NULL) < 0)
AUD_THROW(AUD_ERROR_FFMPEG, codecopen_error);
// XXX this prints file information to stdout:
@@ -236,14 +241,7 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(boost::shared_ptr<AUD_Buffer> buffer) :
AUD_FFMPEGReader::~AUD_FFMPEGReader()
{
avcodec_close(m_codecCtx);
-
- if(m_aviocontext)
- {
- avformat_close_input(&m_formatCtx);
- av_free(m_aviocontext);
- }
- else
- av_close_input_file(m_formatCtx);
+ avformat_close_input(&m_formatCtx);
}
int AUD_FFMPEGReader::read_packet(void* opaque, uint8_t* buf, int buf_size)
diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp
index 2b34348da81..55040e4db8e 100644
--- a/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp
+++ b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp
@@ -55,10 +55,15 @@ AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs,
{
static const char* formats[] = { NULL, "ac3", "flac", "matroska", "mp2", "mp3", "ogg", "wav" };
- if(avformat_alloc_output_context2(&m_formatCtx, NULL, formats[format], filename.c_str()))
- AUD_THROW(AUD_ERROR_FFMPEG, context_error);
+ m_formatCtx = avformat_alloc_context();
+ if (!m_formatCtx) AUD_THROW(AUD_ERROR_FFMPEG, context_error);
- m_outputFmt = m_formatCtx->oformat;
+ strcpy(m_formatCtx->filename, filename.c_str());
+ m_outputFmt = m_formatCtx->oformat = av_guess_format(formats[format], filename.c_str(), NULL);
+ if (!m_outputFmt) {
+ avformat_free_context(m_formatCtx);
+ AUD_THROW(AUD_ERROR_FFMPEG, context_error);
+ }
switch(codec)
{
@@ -116,7 +121,7 @@ AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs,
if(m_outputFmt->audio_codec == CODEC_ID_NONE)
AUD_THROW(AUD_ERROR_SPECS, codec_error);
- m_stream = av_new_stream(m_formatCtx, 0);
+ m_stream = avformat_new_stream(m_formatCtx, NULL);
if(!m_stream)
AUD_THROW(AUD_ERROR_FFMPEG, stream_error);
@@ -164,7 +169,7 @@ AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs,
if(!codec)
AUD_THROW(AUD_ERROR_FFMPEG, codec_error);
- if(avcodec_open(m_codecCtx, codec))
+ if(avcodec_open2(m_codecCtx, codec, NULL))
AUD_THROW(AUD_ERROR_FFMPEG, codec_error);
m_output_buffer.resize(FF_MIN_BUFFER_SIZE);
diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp
index 3150c1af011..e15964151c9 100644
--- a/intern/audaspace/intern/AUD_C-API.cpp
+++ b/intern/audaspace/intern/AUD_C-API.cpp
@@ -26,15 +26,14 @@
* \ingroup audaspaceintern
*/
-
// needed for INT64_C
#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS
#endif
#ifdef WITH_PYTHON
-#include "AUD_PyInit.h"
-#include "AUD_PyAPI.h"
+# include "AUD_PyInit.h"
+# include "AUD_PyAPI.h"
#endif
#include <set>
diff --git a/intern/audaspace/intern/AUD_Sequencer.h b/intern/audaspace/intern/AUD_Sequencer.h
index 9fdf537ff97..1066eeae8e3 100644
--- a/intern/audaspace/intern/AUD_Sequencer.h
+++ b/intern/audaspace/intern/AUD_Sequencer.h
@@ -100,7 +100,7 @@ public:
* \param muted Whether the whole scene is muted.
*/
AUD_Sequencer(AUD_Specs specs, float fps, bool muted);
- ~AUD_Sequencer();
+ virtual ~AUD_Sequencer();
/**
* Locks the sequence.
diff --git a/intern/bsp/SConscript b/intern/bsp/SConscript
index d3f7cf1c6ec..92c8ee48b33 100644
--- a/intern/bsp/SConscript
+++ b/intern/bsp/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('intern/*.cpp')
diff --git a/intern/bsp/intern/CSG_BooleanOps.cpp b/intern/bsp/intern/CSG_BooleanOps.cpp
index 4f71e7992a1..f74dfc3c253 100644
--- a/intern/bsp/intern/CSG_BooleanOps.cpp
+++ b/intern/bsp/intern/CSG_BooleanOps.cpp
@@ -88,16 +88,16 @@ CSG_PerformBooleanOperation(
BoolOpType boolType;
- switch( op_type ) {
- case e_csg_union:
- boolType = BOP_UNION;
- break;
- case e_csg_difference:
- boolType = BOP_DIFFERENCE;
- break;
- default:
- boolType = BOP_INTERSECTION;
- break;
+ switch (op_type) {
+ case e_csg_union:
+ boolType = BOP_UNION;
+ break;
+ case e_csg_difference:
+ boolType = BOP_DIFFERENCE;
+ break;
+ default:
+ boolType = BOP_INTERSECTION;
+ break;
}
BoolOpState boolOpResult;
diff --git a/intern/container/SConscript b/intern/container/SConscript
index 8edf86d7d4a..1f943157d6a 100644
--- a/intern/container/SConscript
+++ b/intern/container/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('intern/*.cpp')
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index 12829f15aed..226218ae512 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -13,10 +13,12 @@ if(WITH_RAYOPTIMIZATION AND SUPPORT_SSE_BUILD)
endif()
if(WIN32 AND MSVC)
- set(CYCLES_OPTIMIZED_KERNEL_FLAGS "/arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc")
+ set(CYCLES_SSE2_KERNEL_FLAGS "/arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc")
+ set(CYCLES_SSE3_KERNEL_FLAGS "/arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:fast -D_CRT_SECURE_NO_WARNINGS /EHsc")
elseif(CMAKE_COMPILER_IS_GNUCC)
- set(CYCLES_OPTIMIZED_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mfpmath=sse")
+ set(CYCLES_SSE2_KERNEL_FLAGS "-ffast-math -msse -msse2 -mfpmath=sse")
+ set(CYCLES_SSE3_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mfpmath=sse")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math")
endif()
@@ -44,13 +46,10 @@ endif()
if(WITH_CYCLES_OSL)
add_definitions(-DWITH_OSL)
+ add_definitions(-DOSL_STATIC_LIBRARY)
include_directories(${OSL_INCLUDES})
endif()
-if(WITH_CYCLES_CUDA_BINARIES)
- add_definitions(-DWITH_CUDA_BINARIES)
-endif()
-
add_definitions(-DWITH_OPENCL)
add_definitions(-DWITH_CUDA)
add_definitions(-DWITH_MULTI)
@@ -68,7 +67,7 @@ if(WITH_CYCLES_BLENDER)
add_subdirectory(blender)
endif()
-if(WITH_CYCLES_TEST)
+if(WITH_CYCLES_TEST OR WITH_CYCLES_NETWORK)
add_subdirectory(app)
endif()
diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript
index a0e2650ddc6..7b4d2db6861 100644
--- a/intern/cycles/SConscript
+++ b/intern/cycles/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/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): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
from os import path
Import('env')
@@ -10,12 +36,15 @@ sources = cycles.Glob('bvh/*.cpp') + cycles.Glob('device/*.cpp') + cycles.Glob('
sources.remove(path.join('util', 'util_view.cpp'))
sources.remove(path.join('render', 'film_response.cpp'))
-sources.remove(path.join('kernel', 'kernel_optimized.cpp'))
+sources.remove(path.join('kernel', 'kernel_sse2.cpp'))
+sources.remove(path.join('kernel', 'kernel_sse3.cpp'))
incs = []
defs = []
cxxflags = Split(env['CXXFLAGS'])
+defs.append('GLEW_STATIC')
+
defs.append('CCL_NAMESPACE_BEGIN=namespace ccl {')
defs.append('CCL_NAMESPACE_END=}')
@@ -25,11 +54,9 @@ defs.append('WITH_CUDA')
if env['WITH_BF_CYCLES_OSL']:
defs.append('WITH_OSL')
+ defs.append('OSL_STATIC_LIBRARY')
incs.append(cycles['BF_OSL_INC'])
-if env['WITH_BF_CYCLES_CUDA_BINARIES']:
- defs.append('WITH_CUDA_BINARIES')
-
incs.extend('. bvh render device kernel kernel/osl kernel/svm util subd'.split())
incs.extend('#intern/guardedalloc #source/blender/makesrna #source/blender/makesdna'.split())
incs.extend('#source/blender/blenloader ../../source/blender/makesrna/intern'.split())
@@ -49,21 +76,29 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', '
# optimized kernel
if env['WITH_BF_RAYOPTIMIZATION']:
- optim_cxxflags = Split(env['CXXFLAGS'])
+ sse2_cxxflags = Split(env['CXXFLAGS'])
+ sse3_cxxflags = Split(env['CXXFLAGS'])
if env['OURPLATFORM'] == 'win32-vc':
- optim_cxxflags.append('/arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc'.split())
+ sse2_cxxflags.append('/arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc'.split())
+ sse3_cxxflags.append('/arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc'.split())
elif env['OURPLATFORM'] == 'win64-vc':
- optim_cxxflags.append('-D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc'.split())
+ sse2_cxxflags.append('-D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc'.split())
+ sse3_cxxflags.append('-D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc'.split())
else:
- optim_cxxflags.append('-ffast-math -msse -msse2 -msse3 -mfpmath=sse'.split())
+ sse2_cxxflags.append('-ffast-math -msse -msse2 -mfpmath=sse'.split())
+ sse3_cxxflags.append('-ffast-math -msse -msse2 -msse3 -mfpmath=sse'.split())
defs.append('WITH_OPTIMIZED_KERNEL')
optim_defs = defs[:]
- optim_sources = [path.join('kernel', 'kernel_optimized.cpp')]
- cycles_optim = cycles.Clone()
- cycles_optim.BlenderLib('bf_intern_cycles_optimized', optim_sources, incs, optim_defs, libtype=['intern'], priority=[10], cxx_compileflags=optim_cxxflags)
+ cycles_sse3 = cycles.Clone()
+ sse3_sources = [path.join('kernel', 'kernel_sse3.cpp')]
+ cycles_sse3.BlenderLib('bf_intern_cycles_sse3', sse3_sources, incs, optim_defs, libtype=['intern'], priority=[10], cxx_compileflags=sse3_cxxflags)
+
+ cycles_sse2 = cycles.Clone()
+ sse2_sources = [path.join('kernel', 'kernel_sse2.cpp')]
+ cycles_sse2.BlenderLib('bf_intern_cycles_sse2', sse2_sources, incs, optim_defs, libtype=['intern'], priority=[10], cxx_compileflags=sse2_cxxflags)
cycles.BlenderLib('bf_intern_cycles', sources, incs, defs, libtype=['intern'], priority=[0], cxx_compileflags=cxxflags)
diff --git a/intern/cycles/app/cycles_server.cpp b/intern/cycles/app/cycles_server.cpp
index e6a13e04b48..f94a29b9451 100644
--- a/intern/cycles/app/cycles_server.cpp
+++ b/intern/cycles/app/cycles_server.cpp
@@ -23,7 +23,9 @@
#include "util_args.h"
#include "util_foreach.h"
#include "util_path.h"
+#include "util_stats.h"
#include "util_string.h"
+#include "util_task.h"
using namespace ccl;
@@ -32,29 +34,29 @@ int main(int argc, const char **argv)
path_init();
/* device types */
- string devices = "";
+ string devicelist = "";
string devicename = "cpu";
bool list = false;
vector<DeviceType>& types = Device::available_types();
foreach(DeviceType type, types) {
- if(devices != "")
- devices += ", ";
+ if(devicelist != "")
+ devicelist += ", ";
- devices += Device::string_from_type(type);
+ devicelist += Device::string_from_type(type);
}
/* parse options */
ArgParse ap;
ap.options ("Usage: cycles_server [options]",
- "--device %s", &devicename, ("Devices to use: " + devices).c_str(),
+ "--device %s", &devicename, ("Devices to use: " + devicelist).c_str(),
"--list-devices", &list, "List information about all available devices",
NULL);
if(ap.parse(argc, argv) < 0) {
- fprintf(stderr, "%s\n", ap.error_message().c_str());
+ fprintf(stderr, "%s\n", ap.geterror().c_str());
ap.usage();
exit(EXIT_FAILURE);
}
@@ -84,13 +86,18 @@ int main(int argc, const char **argv)
}
}
+ TaskScheduler::init();
+
while(1) {
- Device *device = Device::create(device_info);
- printf("Cycles Server with device: %s\n", device->description().c_str());
+ Stats stats;
+ Device *device = Device::create(device_info, stats);
+ printf("Cycles Server with device: %s\n", device->info.description.c_str());
device->server_run();
delete device;
}
+ TaskScheduler::exit();
+
return 0;
}
diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp
index 5de9d71b8cc..40fbb7af556 100644
--- a/intern/cycles/app/cycles_xml.cpp
+++ b/intern/cycles/app/cycles_xml.cpp
@@ -233,16 +233,16 @@ static void xml_read_film(const XMLReadState& state, pugi::xml_node node)
float aspect = (float)cam->width/(float)cam->height;
if(cam->width >= cam->height) {
- cam->left = -aspect;
- cam->right = aspect;
- cam->bottom = -1.0f;
- cam->top = 1.0f;
+ cam->viewplane.left = -aspect;
+ cam->viewplane.right = aspect;
+ cam->viewplane.bottom = -1.0f;
+ cam->viewplane.top = 1.0f;
}
else {
- cam->left = -1.0f;
- cam->right = 1.0f;
- cam->bottom = -1.0f/aspect;
- cam->top = 1.0f/aspect;
+ cam->viewplane.left = -1.0f;
+ cam->viewplane.right = 1.0f;
+ cam->viewplane.bottom = -1.0f/aspect;
+ cam->viewplane.top = 1.0f/aspect;
}
cam->need_update = true;
diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt
index 292c37d6b61..710e8ba6a90 100644
--- a/intern/cycles/blender/CMakeLists.txt
+++ b/intern/cycles/blender/CMakeLists.txt
@@ -24,6 +24,7 @@ set(SRC
blender_mesh.cpp
blender_object.cpp
blender_particles.cpp
+ blender_curves.cpp
blender_python.cpp
blender_session.cpp
blender_shader.cpp
@@ -38,7 +39,6 @@ set(SRC
set(ADDON_FILES
addon/__init__.py
addon/engine.py
- addon/enums.py
addon/osl.py
addon/presets.py
addon/properties.py
diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py
index 0fad2ac5618..526c5658b93 100644
--- a/intern/cycles/blender/addon/__init__.py
+++ b/intern/cycles/blender/addon/__init__.py
@@ -21,7 +21,7 @@
bl_info = {
"name": "Cycles Render Engine",
"author": "",
- "blender": (2, 6, 3),
+ "blender": (2, 66, 0),
"location": "Info header, render engine menu",
"description": "Cycles Render Engine integration",
"warning": "",
@@ -31,16 +31,17 @@ bl_info = {
"category": "Render"}
import bpy
-from . import ui, properties, engine, presets
+
+from . import engine
class CyclesRender(bpy.types.RenderEngine):
bl_idname = 'CYCLES'
bl_label = "Cycles Render"
bl_use_shading_nodes = True
+ bl_use_preview = True
def __init__(self):
- engine.init()
self.session = None
def __del__(self):
@@ -48,28 +49,28 @@ class CyclesRender(bpy.types.RenderEngine):
# final render
def update(self, data, scene):
- if not self.session:
- engine.create(self, data, scene)
+ if self.is_preview:
+ if not self.session:
+ use_osl = bpy.context.scene.cycles.shading_system
+
+ engine.create(self, data, scene,
+ None, None, None, use_osl)
else:
- engine.reset(self, data, scene)
+ if not self.session:
+ engine.create(self, data, scene)
+ else:
+ engine.reset(self, data, scene)
engine.update(self, data, scene)
def render(self, scene):
engine.render(self)
- # preview render
- # def preview_update(self, context, id):
- # pass
- #
- # def preview_render(self):
- # pass
-
# viewport render
def view_update(self, context):
if not self.session:
engine.create(self, context.blend_data, context.scene,
- context.region, context.space_data, context.region_data)
+ context.region, context.space_data, context.region_data)
engine.update(self, context.blend_data, context.scene)
def view_draw(self, context):
@@ -84,6 +85,12 @@ class CyclesRender(bpy.types.RenderEngine):
def register():
+ from . import ui
+ from . import properties
+ from . import presets
+
+ engine.init()
+
properties.register()
ui.register()
presets.register()
@@ -91,8 +98,11 @@ def register():
def unregister():
+ from . import ui
+ from . import properties
+ from . import presets
+
ui.unregister()
properties.unregister()
presets.unregister()
bpy.utils.unregister_module(__name__)
-
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index ca5cbee9325..8958ca3e42e 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -18,10 +18,9 @@
# <pep8 compliant>
-import bpy
-
def init():
+ import bpy
import _cycles
import os.path
@@ -31,7 +30,8 @@ def init():
_cycles.init(path, user_path)
-def create(engine, data, scene, region=0, v3d=0, rv3d=0):
+def create(engine, data, scene, region=0, v3d=0, rv3d=0, preview_osl=False):
+ import bpy
import _cycles
data = data.as_pointer()
@@ -44,7 +44,7 @@ def create(engine, data, scene, region=0, v3d=0, rv3d=0):
if rv3d:
rv3d = rv3d.as_pointer()
- engine.session = _cycles.create(engine.as_pointer(), userpref, data, scene, region, v3d, rv3d)
+ engine.session = _cycles.create(engine.as_pointer(), userpref, data, scene, region, v3d, rv3d, preview_osl)
def free(engine):
@@ -90,4 +90,3 @@ def available_devices():
def with_osl():
import _cycles
return _cycles.with_osl
-
diff --git a/intern/cycles/blender/addon/enums.py b/intern/cycles/blender/addon/enums.py
deleted file mode 100644
index 82b48973ca1..00000000000
--- a/intern/cycles/blender/addon/enums.py
+++ /dev/null
@@ -1,63 +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.
-#
-
-# <pep8 compliant>
-
-from . import engine
-
-devices = (
- ('CPU', "CPU", "Use CPU for rendering"),
- ('GPU', "GPU Compute", "Use GPU compute device for rendering, configured in user preferences"))
-
-feature_set = (
- ('SUPPORTED', "Supported", "Only use finished and supported features"),
- ('EXPERIMENTAL', "Experimental", "Use experimental and incomplete features that might be broken or change in the future"),
- )
-
-shading_systems = (
- ('GPU_COMPATIBLE', "GPU Compatible", "Restricted shading system compatible with GPU rendering"),
- ('OSL', "Open Shading Language", "Open Shading Language shading system that only runs on the CPU"),
- )
-
-displacement_methods = (
- ('BUMP', "Bump", "Bump mapping to simulate the appearance of displacement"),
- ('TRUE', "True", "Use true displacement only, requires fine subdivision"),
- ('BOTH', "Both", "Combination of displacement and bump mapping"),
- )
-
-bvh_types = (
- ('DYNAMIC_BVH', "Dynamic BVH", "Objects can be individually updated, at the cost of slower render time"),
- ('STATIC_BVH', "Static BVH", "Any object modification requires a complete BVH rebuild, but renders faster"),
- )
-
-filter_types = (
- ('BOX', "Box", "Box filter"),
- ('GAUSSIAN', "Gaussian", "Gaussian filter"),
- )
-
-aperture_types = (
- ('RADIUS', "Radius", "Directly change the size of the aperture"),
- ('FSTOP', "F/stop", "Change the size of the aperture by f/stops"),
- )
-
-panorama_types = (
- ('EQUIRECTANGULAR', "Equirectangular", "Render the scene with a spherical camera, also known as Lat Long panorama"),
- ('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"),
- )
diff --git a/intern/cycles/blender/addon/osl.py b/intern/cycles/blender/addon/osl.py
index 79ce3df20c3..0a67edac1e3 100644
--- a/intern/cycles/blender/addon/osl.py
+++ b/intern/cycles/blender/addon/osl.py
@@ -18,10 +18,13 @@
# <pep8 compliant>
-import bpy, _cycles, os, tempfile
+import bpy
+import _cycles
+
-# compile .osl file with given filepath to temporary .oso file
def osl_compile(input_path, report):
+ """compile .osl file with given filepath to temporary .oso file"""
+ import tempfile
output_file = tempfile.NamedTemporaryFile(mode='w', suffix=".oso", delete=False)
output_path = output_file.name
output_file.close()
@@ -33,9 +36,12 @@ def osl_compile(input_path, report):
return ok, output_path
-# compile and update shader script node
+
def update_script_node(node, report):
- import os, shutil
+ """compile and update shader script node"""
+ import os
+ import shutil
+ import tempfile
if node.mode == 'EXTERNAL':
# compile external script file
@@ -103,7 +109,7 @@ def update_script_node(node, report):
report({'ERROR'}, "Can't read OSO bytecode to store in node at %r" % oso_path)
ok = False
-
+
else:
report({'WARNING'}, "No text or file specified in node, nothing to compile")
return
@@ -125,4 +131,3 @@ def update_script_node(node, report):
pass
return ok
-
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 0b8ca6e0fbe..09db010363e 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -25,9 +25,87 @@ from bpy.props import (BoolProperty,
IntProperty,
PointerProperty)
-import math
-
-from . import enums
+# enums
+
+enum_devices = (
+ ('CPU', "CPU", "Use CPU for rendering"),
+ ('GPU', "GPU Compute", "Use GPU compute device for rendering, configured in user preferences"))
+
+enum_feature_set = (
+ ('SUPPORTED', "Supported", "Only use finished and supported features"),
+ ('EXPERIMENTAL', "Experimental", "Use experimental and incomplete features that might be broken or change in the future"),
+ )
+
+enum_displacement_methods = (
+ ('BUMP', "Bump", "Bump mapping to simulate the appearance of displacement"),
+ ('TRUE', "True", "Use true displacement only, requires fine subdivision"),
+ ('BOTH', "Both", "Combination of displacement and bump mapping"),
+ )
+
+enum_bvh_types = (
+ ('DYNAMIC_BVH', "Dynamic BVH", "Objects can be individually updated, at the cost of slower render time"),
+ ('STATIC_BVH', "Static BVH", "Any object modification requires a complete BVH rebuild, but renders faster"),
+ )
+
+enum_filter_types = (
+ ('BOX', "Box", "Box filter"),
+ ('GAUSSIAN', "Gaussian", "Gaussian filter"),
+ )
+
+enum_aperture_types = (
+ ('RADIUS', "Radius", "Directly change the size of the aperture"),
+ ('FSTOP', "F/stop", "Change the size of the aperture by f/stops"),
+ )
+
+enum_panorama_types = (
+ ('EQUIRECTANGULAR', "Equirectangular", "Render the scene with a spherical camera, also known as Lat Long panorama"),
+ ('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"),
+ )
+
+enum_curve_presets = (
+ ('CUSTOM', "Custom", "Set general parameters"),
+ ('FAST_PLANES', "Fast Planes", "Use camera facing triangles (fast but memory intensive)"),
+ ('TANGENT_SHADING', "Tangent Normal", "Use planar line segments and tangent normals"),
+ ('TRUE_NORMAL', "True Normal", "Use true normals with line segments(good for thin strands)"),
+ ('ACCURATE_PRESET', "Accurate", "Use best line segment settings (suitable for glass materials)"),
+ ('SMOOTH_CURVES', "Smooth Curves", "Use smooth cardinal curves (slowest)"),
+ )
+
+enum_curve_primitives = (
+ ('TRIANGLES', "Triangles", "Create triangle geometry around strands"),
+ ('LINE_SEGMENTS', "Line Segments", "Use line segment primitives"),
+ ('CURVE_SEGMENTS', "Curve Segments", "Use segmented cardinal curve primitives"),
+ ('CURVE_RIBBONS', "Curve Ribbons", "Use smooth cardinal curve ribbon primitives"),
+ )
+
+enum_triangle_curves = (
+ ('CAMERA_TRIANGLES', "Planes", "Create individual triangles forming planes that face camera"),
+ ('RIBBON_TRIANGLES', "Ribbons", "Create individual triangles forming ribbon"),
+ ('TESSELLATED_TRIANGLES', "Tessellated", "Create mesh surrounding each strand"),
+ )
+
+enum_line_curves = (
+ ('ACCURATE', "Accurate", "Always take into consideration strand width for intersections"),
+ ('QT_CORRECTED', "Corrected", "Ignore width for initial intersection and correct later"),
+ ('ENDCORRECTED', "Correct found", "Ignore width for all intersections and only correct closest"),
+ ('QT_UNCORRECTED', "Uncorrected", "Calculate intersections without considering width"),
+ )
+
+enum_curves_interpolation = (
+ ('LINEAR', "Linear interpolation", "Use Linear interpolation between segments"),
+ ('CARDINAL', "Cardinal interpolation", "Use cardinal interpolation between segments"),
+ ('BSPLINE', "B-spline interpolation", "Use b-spline interpolation between segments"),
+ )
+
+enum_tile_order = (
+ ('CENTER', "Center", "Render from center to the edges"),
+ ('RIGHT_TO_LEFT', "Right to Left", "Render from right to left"),
+ ('LEFT_TO_RIGHT', "Left to Right", "Render from left to right"),
+ ('TOP_TO_BOTTOM', "Top to Bottom", "Render from top to bottom"),
+ ('BOTTOM_TO_TOP', "Bottom to Top", "Render from bottom to top"),
+ )
class CyclesRenderSettings(bpy.types.PropertyGroup):
@@ -41,20 +119,18 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
cls.device = EnumProperty(
name="Device",
description="Device to use for rendering",
- items=enums.devices,
+ items=enum_devices,
default='CPU',
)
cls.feature_set = EnumProperty(
name="Feature Set",
description="Feature set to use for rendering",
- items=enums.feature_set,
+ items=enum_feature_set,
default='SUPPORTED',
)
- cls.shading_system = EnumProperty(
- name="Shading System",
- description="Shading system to use for rendering",
- items=enums.shading_systems,
- default='GPU_COMPATIBLE',
+ cls.shading_system = BoolProperty(
+ name="Open Shading Language",
+ description="Use Open Shading Language (CPU rendering only)",
)
cls.progressive = BoolProperty(
@@ -205,14 +281,14 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
)
cls.film_transparent = BoolProperty(
name="Transparent",
- description="World background is transparent",
+ description="World background is transparent with premultiplied alpha",
default=False,
)
cls.filter_type = EnumProperty(
name="Filter Type",
description="Pixel filter type",
- items=enums.filter_types,
+ items=enum_filter_types,
default='GAUSSIAN',
)
cls.filter_width = FloatProperty(
@@ -275,7 +351,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
cls.debug_bvh_type = EnumProperty(
name="Viewport BVH Type",
description="Choose between faster updates, or faster render",
- items=enums.bvh_types,
+ items=enum_bvh_types,
default='DYNAMIC_BVH',
)
cls.debug_use_spatial_splits = BoolProperty(
@@ -288,6 +364,12 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
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",
+ items=enum_tile_order,
+ default='CENTER',
+ )
cls.use_progressive_refine = BoolProperty(
name="Progressive Refine",
description="Instead of rendering each tile until it is finished, "
@@ -305,6 +387,8 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
class CyclesCameraSettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
+ import math
+
bpy.types.Camera.cycles = PointerProperty(
name="Cycles Camera Settings",
description="Cycles camera settings",
@@ -314,7 +398,7 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
cls.aperture_type = EnumProperty(
name="Aperture Type",
description="Use F/stop number or aperture radius",
- items=enums.aperture_types,
+ items=enum_aperture_types,
default='RADIUS',
)
cls.aperture_fstop = FloatProperty(
@@ -332,6 +416,7 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
default=0.0,
step=1,
precision=4,
+ subtype = 'DISTANCE'
)
cls.aperture_blades = IntProperty(
name="Aperture Blades",
@@ -349,7 +434,7 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
cls.panorama_type = EnumProperty(
name="Panorama Type",
description="Distortion to use for the calculation",
- items=enums.panorama_types,
+ items=enum_panorama_types,
default='FISHEYE_EQUISOLID',
)
cls.fisheye_fov = FloatProperty(
@@ -380,8 +465,8 @@ class CyclesMaterialSettings(bpy.types.PropertyGroup):
type=cls,
)
cls.sample_as_light = BoolProperty(
- name="Sample as Lamp",
- description="Use direct light sampling for this material, "
+ name="Multiple Importance Sample",
+ description="Use multiple importance sampling for this material, "
"disabling may reduce overall noise for large "
"objects that emit little light compared to other light sources",
default=True,
@@ -417,6 +502,12 @@ class CyclesLampSettings(bpy.types.PropertyGroup):
min=1, max=10000,
default=1,
)
+ 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,
+ )
@classmethod
def unregister(cls):
@@ -432,8 +523,8 @@ class CyclesWorldSettings(bpy.types.PropertyGroup):
type=cls,
)
cls.sample_as_light = BoolProperty(
- name="Sample as Lamp",
- description="Use direct light sampling for the environment, "
+ name="Multiple Importance Sample",
+ description="Use multiple importance sampling for the environment, "
"enabling for non-solid colors is recommended",
default=False,
)
@@ -518,7 +609,7 @@ class CyclesMeshSettings(bpy.types.PropertyGroup):
cls.displacement_method = EnumProperty(
name="Displacement Method",
description="Method to use for the displacement",
- items=enums.displacement_methods,
+ items=enum_displacement_methods,
default='BUMP',
)
cls.use_subdivision = BoolProperty(
@@ -540,6 +631,162 @@ class CyclesMeshSettings(bpy.types.PropertyGroup):
del bpy.types.MetaBall.cycles
+class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
+ @classmethod
+ def register(cls):
+ bpy.types.Scene.cycles_curves = PointerProperty(
+ name="Cycles Hair Rendering Settings",
+ description="Cycles hair rendering settings",
+ type=cls,
+ )
+ cls.preset = EnumProperty(
+ name="Mode",
+ description="Hair rendering mode",
+ items=enum_curve_presets,
+ default='TRUE_NORMAL',
+ )
+ cls.primitive = EnumProperty(
+ name="Primitive",
+ description="Type of primitive used for hair rendering",
+ items=enum_curve_primitives,
+ default='LINE_SEGMENTS',
+ )
+ cls.triangle_method = EnumProperty(
+ name="Mesh Geometry",
+ description="Method for creating triangle geometry",
+ items=enum_triangle_curves,
+ default='CAMERA_TRIANGLES',
+ )
+ cls.line_method = EnumProperty(
+ name="Intersection Method",
+ description="Method for line segment intersection",
+ items=enum_line_curves,
+ default='ACCURATE',
+ )
+ cls.interpolation = EnumProperty(
+ name="Interpolation",
+ description="Interpolation method",
+ items=enum_curves_interpolation,
+ default='BSPLINE',
+ )
+ cls.use_backfacing = BoolProperty(
+ name="Check back-faces",
+ description="Test back-faces of strands",
+ default=False,
+ )
+ cls.use_encasing = BoolProperty(
+ name="Exclude encasing",
+ description="Ignore strands encasing a ray's initial location",
+ default=True,
+ )
+ cls.use_tangent_normal_geometry = BoolProperty(
+ name="Tangent normal geometry",
+ description="Use the tangent normal for actual normal",
+ default=False,
+ )
+ cls.use_tangent_normal = BoolProperty(
+ name="Tangent normal default",
+ description="Use the tangent normal for all normals",
+ default=False,
+ )
+ cls.use_tangent_normal_correction = BoolProperty(
+ name="Strand slope correction",
+ description="Correct the tangent normal for the strand's slope",
+ default=False,
+ )
+ cls.use_parents = BoolProperty(
+ name="Use parent strands",
+ description="Use parents with children",
+ default=False,
+ )
+ cls.use_smooth = BoolProperty(
+ name="Smooth Strands",
+ description="Use vertex normals",
+ default=True,
+ )
+ cls.use_joined = BoolProperty(
+ name="Join",
+ description="Fill gaps between segments (requires more memory)",
+ default=False,
+ )
+ cls.use_curves = BoolProperty(
+ name="Use Cycles Hair Rendering",
+ description="Activate Cycles hair rendering for particle system",
+ default=True,
+ )
+ cls.segments = IntProperty(
+ name="Segments",
+ description="Number of segments between path keys (note that this combines with the 'draw step' value)",
+ min=1, max=64,
+ default=1,
+ )
+ cls.resolution = IntProperty(
+ name="Resolution",
+ description="Resolution of generated mesh",
+ min=3, max=64,
+ default=3,
+ )
+ cls.normalmix = FloatProperty(
+ name="Normal mix",
+ description="Scale factor for tangent normal removal (zero gives ray normal)",
+ min=0, max=2.0,
+ default=1,
+ )
+ cls.encasing_ratio = FloatProperty(
+ name="Encasing ratio",
+ description="Scale factor for encasing strand width",
+ min=0, max=100.0,
+ default=1.01,
+ )
+ cls.subdivisions = IntProperty(
+ name="Subdivisions",
+ description="Number of subdivisions used in Cardinal curve intersection (power of 2)",
+ min=0, max=24,
+ default=3,
+ )
+
+ @classmethod
+ def unregister(cls):
+ del bpy.types.Scene.cycles_curves
+
+
+class CyclesCurveSettings(bpy.types.PropertyGroup):
+ @classmethod
+ def register(cls):
+ bpy.types.ParticleSettings.cycles = PointerProperty(
+ name="Cycles Hair Settings",
+ description="Cycles hair settings",
+ type=cls,
+ )
+ cls.root_width = FloatProperty(
+ name="Root Size Multiplier",
+ description="Multiplier of particle size for the strand's width at root",
+ min=0.0, max=1000.0,
+ default=1.0,
+ )
+ cls.tip_width = FloatProperty(
+ name="Tip Size Multiplier",
+ description="Multiplier of particle size for the strand's width at tip",
+ min=0.0, max=1000.0,
+ default=0.0,
+ )
+ cls.shape = FloatProperty(
+ name="Strand Shape",
+ description="Strand shape parameter",
+ min=-1.0, max=1.0,
+ default=0.0,
+ )
+ cls.use_closetip = BoolProperty(
+ name="Close tip",
+ description="Set tip radius to zero",
+ default=True,
+ )
+
+ @classmethod
+ def unregister(cls):
+ del bpy.types.ParticleSettings.cycles
+
+
def register():
bpy.utils.register_class(CyclesRenderSettings)
bpy.utils.register_class(CyclesCameraSettings)
@@ -548,6 +795,8 @@ def register():
bpy.utils.register_class(CyclesWorldSettings)
bpy.utils.register_class(CyclesVisibilitySettings)
bpy.utils.register_class(CyclesMeshSettings)
+ bpy.utils.register_class(CyclesCurveRenderSettings)
+ bpy.utils.register_class(CyclesCurveSettings)
def unregister():
@@ -558,3 +807,5 @@ def unregister():
bpy.utils.unregister_class(CyclesWorldSettings)
bpy.utils.unregister_class(CyclesMeshSettings)
bpy.utils.unregister_class(CyclesVisibilitySettings)
+ bpy.utils.unregister_class(CyclesCurveRenderSettings)
+ bpy.utils.unregister_class(CyclesCurveSettings)
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index ba931469e8a..0d1437e13e4 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -22,8 +22,6 @@ import bpy
from bpy.types import Panel, Menu
-from . import enums, engine
-
class CYCLES_MT_integrator_presets(Menu):
bl_label = "Integrator Presets"
@@ -193,7 +191,8 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
sub.prop(rd, "threads")
sub = col.column(align=True)
- sub.label(text="Tile Size:")
+ sub.label(text="Tiles:")
+ sub.prop(cscene, "tile_order", text="")
sub.prop(rd, "tile_x", text="X")
sub.prop(rd, "tile_y", text="Y")
@@ -220,11 +219,34 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
sub.label(text="Final Render:")
sub.prop(rd, "use_persistent_data", text="Persistent Images")
+
+class CyclesRender_PT_opengl(CyclesButtonsPanel, Panel):
+ bl_label = "OpenGL Render"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+ rd = context.scene.render
+
+ split = layout.split()
+
+ col = split.column()
+ col.prop(rd, "use_antialiasing")
+ sub = col.row()
+ sub.active = rd.use_antialiasing
+ sub.prop(rd, "antialiasing_samples", expand=True)
+
+ col = split.column()
+ col.label(text="Alpha:")
+ col.prop(rd, "alpha_mode", text="")
+
+
class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
bl_label = "Layers"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
+ bl_options = {'HIDE_HEADER'}
+ bl_context = "render_layer"
+ COMPAT_ENGINES = {'CYCLES'}
def draw(self, context):
layout = self.layout
@@ -233,7 +255,7 @@ class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
rd = scene.render
row = layout.row()
- row.template_list(rd, "layers", rd.layers, "active_index", rows=2)
+ row.template_list("RENDERLAYER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=2)
col = row.column(align=True)
col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
@@ -241,9 +263,24 @@ class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
row = layout.row()
rl = rd.layers.active
- row.prop(rl, "name")
+ if rl:
+ row.prop(rl, "name")
row.prop(rd, "use_single_layer", text="", icon_only=True)
+
+class CyclesRender_PT_layer_options(CyclesButtonsPanel, Panel):
+ bl_label = "Layer"
+ bl_options = {'DEFAULT_CLOSED'}
+ bl_context = "render_layer"
+ COMPAT_ENGINES = {'CYCLES'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+ rd = scene.render
+ rl = rd.layers.active
+
split = layout.split()
col = split.column()
@@ -265,6 +302,20 @@ class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
col.prop(rl, "samples")
col.prop(rl, "use_sky", "Use Environment")
+
+class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
+ bl_label = "Render Passes"
+ bl_options = {'DEFAULT_CLOSED'}
+ bl_context = "render_layer"
+ COMPAT_ENGINES = {'CYCLES'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+ rd = scene.render
+ rl = rd.layers.active
+
split = layout.split()
col = split.column()
@@ -379,7 +430,7 @@ class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
if ob:
row = layout.row()
- row.template_list(ob, "material_slots", ob, "active_material_index", rows=2)
+ row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=2)
col = row.column(align=True)
col.operator("object.material_slot_add", icon='ZOOMIN', text="")
@@ -515,7 +566,7 @@ def panel_node_draw(layout, id_data, output_type, input_name):
node = find_node(id_data, output_type)
if not node:
- layout.label(text="No output node.")
+ layout.label(text="No output node")
else:
input = find_node_input(node, input_name)
layout.template_node_view(ntree, node, input)
@@ -523,6 +574,19 @@ def panel_node_draw(layout, id_data, output_type, input_name):
return True
+class CyclesLamp_PT_preview(CyclesButtonsPanel, Panel):
+ bl_label = "Preview"
+ bl_context = "data"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ return context.lamp and CyclesButtonsPanel.poll(context)
+
+ def draw(self, context):
+ self.layout.template_preview(context.lamp)
+
+
class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
bl_label = "Lamp"
bl_context = "data"
@@ -562,8 +626,10 @@ class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
col = split.column()
col.prop(clamp, "cast_shadow")
+ layout.prop(clamp, "use_multiple_importance_sampling")
+
if lamp.type == 'HEMI':
- layout.label(text="Not supported, interpreted as sun lamp.")
+ layout.label(text="Not supported, interpreted as sun lamp")
class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
@@ -607,6 +673,19 @@ class CyclesLamp_PT_spot(CyclesButtonsPanel, Panel):
col.prop(lamp, "show_cone")
+class CyclesWorld_PT_preview(CyclesButtonsPanel, Panel):
+ bl_label = "Preview"
+ bl_context = "world"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ return context.world and CyclesButtonsPanel.poll(context)
+
+ def draw(self, context):
+ self.layout.template_preview(context.world)
+
+
class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel):
bl_label = "Surface"
bl_context = "world"
@@ -693,6 +772,19 @@ class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
sub.prop(cworld, "samples")
+class CyclesMaterial_PT_preview(CyclesButtonsPanel, Panel):
+ bl_label = "Preview"
+ bl_context = "material"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ return context.material and CyclesButtonsPanel.poll(context)
+
+ def draw(self, context):
+ self.layout.template_preview(context.material)
+
+
class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
bl_label = "Surface"
bl_context = "material"
@@ -769,9 +861,10 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
col.prop(mat, "diffuse_color", text="Viewport Color")
col = split.column()
- col.prop(cmat, "sample_as_light")
col.prop(mat, "pass_index")
+ layout.prop(cmat, "sample_as_light")
+
class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
bl_label = ""
@@ -809,24 +902,8 @@ class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
split = layout.split(percentage=0.2)
split.label(text="Type:")
split.prop(tex, "type", text="")
-
-
-class CyclesTexture_PT_nodes(CyclesButtonsPanel, Panel):
- bl_label = "Nodes"
- bl_context = "texture"
-
- @classmethod
- def poll(cls, context):
- tex = context.texture
- return (tex and tex.use_nodes) and CyclesButtonsPanel.poll(context)
-
- def draw(self, context):
- layout = self.layout
-
- tex = context.texture
- panel_node_draw(layout, tex, 'OUTPUT_TEXTURE', 'Color')
-
-
+
+
class CyclesTexture_PT_node(CyclesButtonsPanel, Panel):
bl_label = "Node"
bl_context = "texture"
@@ -850,14 +927,12 @@ class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
- tex = context.texture
node = context.texture_node
- return (node or (tex and tex.use_nodes)) and CyclesButtonsPanel.poll(context)
+ return node and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
-
- # tex = context.texture
+
node = context.texture_node
mapping = node.texture_mapping
@@ -883,15 +958,13 @@ class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
- # tex = context.texture
# node = context.texture_node
return False
- #return (node or (tex and tex.use_nodes)) and CyclesButtonsPanel.poll(context)
+ #return node and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
-
- # tex = context.texture
+
node = context.texture_node
mapping = node.color_mapping
@@ -917,6 +990,132 @@ class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
layout.template_color_ramp(mapping, "color_ramp", expand=True)
+class CyclesParticle_PT_textures(CyclesButtonsPanel, Panel):
+ bl_label = "Textures"
+ bl_context = "particle"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ psys = context.particle_system
+ return psys and CyclesButtonsPanel.poll(context)
+
+ def draw(self, context):
+ layout = self.layout
+
+ psys = context.particle_system
+ part = psys.settings
+
+ row = layout.row()
+ row.template_list("TEXTURE_UL_texslots", "", part, "texture_slots", part, "active_texture_index", rows=2)
+
+ col = row.column(align=True)
+ col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
+ col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
+ col.menu("TEXTURE_MT_specials", icon='DOWNARROW_HLT', text="")
+
+ if not part.active_texture:
+ layout.template_ID(part, "active_texture", new="texture.new")
+ else:
+ slot = part.texture_slots[part.active_texture_index]
+ layout.template_ID(slot, "texture", new="texture.new")
+
+
+class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel):
+ bl_label = "Cycles Hair Rendering"
+ bl_context = "particle"
+
+ @classmethod
+ def poll(cls, context):
+ scene = context.scene
+ cscene = scene.cycles
+ psys = context.particle_system
+ device_type = context.user_preferences.system.compute_device_type
+ experimental = ((cscene.feature_set == 'EXPERIMENTAL') and (cscene.device == 'CPU' or device_type == 'NONE'))
+ return CyclesButtonsPanel.poll(context) and experimental and psys
+
+ def draw_header(self, context):
+ ccscene = context.scene.cycles_curves
+ self.layout.prop(ccscene, "use_curves", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+ ccscene = scene.cycles_curves
+
+ layout.active = ccscene.use_curves
+
+ layout.prop(ccscene, "preset", text="Mode")
+
+ if ccscene.preset == 'CUSTOM':
+ layout.prop(ccscene, "primitive", text="Primitive")
+
+ if ccscene.primitive == 'TRIANGLES':
+ layout.prop(ccscene, "triangle_method", text="Method")
+ if ccscene.triangle_method == 'TESSELLATED_TRIANGLES':
+ layout.prop(ccscene, "resolution", text="Resolution")
+ layout.prop(ccscene, "use_smooth", text="Smooth")
+ elif ccscene.primitive == 'LINE_SEGMENTS':
+ layout.prop(ccscene, "use_backfacing", text="Check back-faces")
+
+ row = layout.row()
+ row.prop(ccscene, "use_encasing", text="Exclude encasing")
+ sub = row.row()
+ sub.active = ccscene.use_encasing
+ sub.prop(ccscene, "encasing_ratio", text="Ratio for encasing")
+
+ layout.prop(ccscene, "line_method", text="Method")
+ layout.prop(ccscene, "use_tangent_normal", text="Use tangent normal as default")
+ layout.prop(ccscene, "use_tangent_normal_geometry", text="Use tangent normal geometry")
+ layout.prop(ccscene, "use_tangent_normal_correction", text="Correct tangent normal for slope")
+ layout.prop(ccscene, "interpolation", text="Interpolation")
+
+ row = layout.row()
+ row.prop(ccscene, "segments", text="Segments")
+ row.prop(ccscene, "normalmix", text="Ray Mix")
+ elif ccscene.primitive in {'CURVE_SEGMENTS', 'CURVE_RIBBONS'}:
+ layout.prop(ccscene, "subdivisions", text="Curve subdivisions")
+ layout.prop(ccscene, "use_backfacing", text="Check back-faces")
+
+ layout.prop(ccscene, "interpolation", text="Interpolation")
+ row = layout.row()
+ row.prop(ccscene, "segments", text="Segments")
+
+ row = layout.row()
+ row.prop(ccscene, "use_parents", text="Include parents")
+
+
+class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
+ bl_label = "Cycles Hair Settings"
+ bl_context = "particle"
+
+ @classmethod
+ def poll(cls, context):
+ scene = context.scene
+ cscene = scene.cycles
+ ccscene = scene.cycles_curves
+ use_curves = ccscene.use_curves and context.particle_system
+ device_type = context.user_preferences.system.compute_device_type
+ experimental = cscene.feature_set == 'EXPERIMENTAL' and (cscene.device == 'CPU' or device_type == 'NONE')
+ return CyclesButtonsPanel.poll(context) and experimental and use_curves
+
+ def draw(self, context):
+ layout = self.layout
+
+ psys = context.particle_settings
+ cpsys = psys.cycles
+
+ row = layout.row()
+ row.prop(cpsys, "shape", text="Shape")
+ row.prop(cpsys, "use_closetip", text="Close tip")
+
+ layout.label(text="Width multiplier:")
+ row = layout.row()
+ row.prop(cpsys, "root_width", text="Root")
+ row.prop(cpsys, "tip_width", text="Tip")
+
+
class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
bl_label = "Simplify"
bl_context = "scene"
@@ -933,13 +1132,9 @@ class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
layout.active = rd.use_simplify
- split = layout.split()
-
- col = split.column()
- col.prop(rd, "simplify_subdivision", text="Subdivision")
-
- col = split.column()
- col.prop(rd, "simplify_child_particles", text="Child Particles")
+ row = layout.row()
+ row.prop(rd, "simplify_subdivision", text="Subdivision")
+ row.prop(rd, "simplify_child_particles", text="Child Particles")
def draw_device(self, context):
@@ -947,6 +1142,7 @@ def draw_device(self, context):
layout = self.layout
if scene.render.engine == 'CYCLES':
+ from . import engine
cscene = scene.cycles
layout.prop(cscene, "feature_set")
@@ -976,73 +1172,89 @@ def draw_pause(self, context):
def get_panels():
+ types = bpy.types
return (
- bpy.types.RENDER_PT_render,
- bpy.types.RENDER_PT_output,
- bpy.types.RENDER_PT_encoding,
- bpy.types.RENDER_PT_dimensions,
- bpy.types.RENDER_PT_stamp,
- bpy.types.SCENE_PT_scene,
- bpy.types.SCENE_PT_audio,
- bpy.types.SCENE_PT_unit,
- bpy.types.SCENE_PT_keying_sets,
- bpy.types.SCENE_PT_keying_set_paths,
- bpy.types.SCENE_PT_physics,
- bpy.types.WORLD_PT_context_world,
- bpy.types.DATA_PT_context_mesh,
- bpy.types.DATA_PT_context_camera,
- bpy.types.DATA_PT_context_lamp,
- bpy.types.DATA_PT_context_speaker,
- bpy.types.DATA_PT_texture_space,
- bpy.types.DATA_PT_curve_texture_space,
- bpy.types.DATA_PT_mball_texture_space,
- bpy.types.DATA_PT_vertex_groups,
- bpy.types.DATA_PT_shape_keys,
- bpy.types.DATA_PT_uv_texture,
- bpy.types.DATA_PT_vertex_colors,
- bpy.types.DATA_PT_camera,
- bpy.types.DATA_PT_camera_display,
- bpy.types.DATA_PT_lens,
- bpy.types.DATA_PT_speaker,
- bpy.types.DATA_PT_distance,
- bpy.types.DATA_PT_cone,
- bpy.types.DATA_PT_customdata,
- bpy.types.DATA_PT_custom_props_mesh,
- bpy.types.DATA_PT_custom_props_camera,
- bpy.types.DATA_PT_custom_props_lamp,
- bpy.types.DATA_PT_custom_props_speaker,
- bpy.types.TEXTURE_PT_clouds,
- bpy.types.TEXTURE_PT_wood,
- bpy.types.TEXTURE_PT_marble,
- bpy.types.TEXTURE_PT_magic,
- bpy.types.TEXTURE_PT_blend,
- bpy.types.TEXTURE_PT_stucci,
- bpy.types.TEXTURE_PT_image,
- bpy.types.TEXTURE_PT_image_sampling,
- bpy.types.TEXTURE_PT_image_mapping,
- bpy.types.TEXTURE_PT_musgrave,
- bpy.types.TEXTURE_PT_voronoi,
- bpy.types.TEXTURE_PT_distortednoise,
- bpy.types.TEXTURE_PT_voxeldata,
- bpy.types.TEXTURE_PT_pointdensity,
- bpy.types.TEXTURE_PT_pointdensity_turbulence,
- bpy.types.TEXTURE_PT_mapping,
- bpy.types.TEXTURE_PT_influence,
- bpy.types.PARTICLE_PT_context_particles,
- bpy.types.PARTICLE_PT_emission,
- bpy.types.PARTICLE_PT_hair_dynamics,
- bpy.types.PARTICLE_PT_cache,
- bpy.types.PARTICLE_PT_velocity,
- bpy.types.PARTICLE_PT_rotation,
- bpy.types.PARTICLE_PT_physics,
- bpy.types.PARTICLE_PT_boidbrain,
- bpy.types.PARTICLE_PT_render,
- bpy.types.PARTICLE_PT_draw,
- bpy.types.PARTICLE_PT_children,
- bpy.types.PARTICLE_PT_field_weights,
- bpy.types.PARTICLE_PT_force_fields,
- bpy.types.PARTICLE_PT_vertexgroups,
- bpy.types.PARTICLE_PT_custom_props,
+ types.RENDER_PT_render,
+ types.RENDER_PT_output,
+ types.RENDER_PT_encoding,
+ types.RENDER_PT_dimensions,
+ types.RENDER_PT_stamp,
+ types.SCENE_PT_scene,
+ types.SCENE_PT_color_management,
+ types.SCENE_PT_custom_props,
+ types.SCENE_PT_audio,
+ types.SCENE_PT_unit,
+ types.SCENE_PT_keying_sets,
+ types.SCENE_PT_keying_set_paths,
+ types.SCENE_PT_physics,
+ types.WORLD_PT_context_world,
+ types.WORLD_PT_custom_props,
+ types.DATA_PT_context_mesh,
+ types.DATA_PT_context_camera,
+ types.DATA_PT_context_lamp,
+ types.DATA_PT_context_speaker,
+ types.DATA_PT_texture_space,
+ types.DATA_PT_curve_texture_space,
+ types.DATA_PT_mball_texture_space,
+ types.DATA_PT_vertex_groups,
+ types.DATA_PT_shape_keys,
+ types.DATA_PT_uv_texture,
+ types.DATA_PT_vertex_colors,
+ types.DATA_PT_camera,
+ types.DATA_PT_camera_display,
+ types.DATA_PT_lens,
+ types.DATA_PT_speaker,
+ types.DATA_PT_distance,
+ types.DATA_PT_cone,
+ types.DATA_PT_customdata,
+ types.DATA_PT_custom_props_mesh,
+ types.DATA_PT_custom_props_camera,
+ types.DATA_PT_custom_props_lamp,
+ types.DATA_PT_custom_props_speaker,
+ types.DATA_PT_custom_props_arm,
+ types.DATA_PT_custom_props_curve,
+ types.DATA_PT_custom_props_lattice,
+ types.DATA_PT_custom_props_metaball,
+ types.TEXTURE_PT_custom_props,
+ types.TEXTURE_PT_clouds,
+ types.TEXTURE_PT_wood,
+ types.TEXTURE_PT_marble,
+ types.TEXTURE_PT_magic,
+ types.TEXTURE_PT_blend,
+ types.TEXTURE_PT_stucci,
+ types.TEXTURE_PT_image,
+ types.TEXTURE_PT_image_sampling,
+ types.TEXTURE_PT_image_mapping,
+ types.TEXTURE_PT_musgrave,
+ types.TEXTURE_PT_voronoi,
+ types.TEXTURE_PT_distortednoise,
+ types.TEXTURE_PT_voxeldata,
+ types.TEXTURE_PT_pointdensity,
+ types.TEXTURE_PT_pointdensity_turbulence,
+ types.TEXTURE_PT_mapping,
+ types.TEXTURE_PT_influence,
+ types.TEXTURE_PT_colors,
+ types.PARTICLE_PT_context_particles,
+ types.PARTICLE_PT_custom_props,
+ types.PARTICLE_PT_emission,
+ types.PARTICLE_PT_hair_dynamics,
+ types.PARTICLE_PT_cache,
+ types.PARTICLE_PT_velocity,
+ types.PARTICLE_PT_rotation,
+ types.PARTICLE_PT_physics,
+ types.SCENE_PT_rigid_body_world,
+ types.SCENE_PT_rigid_body_cache,
+ types.SCENE_PT_rigid_body_field_weights,
+ types.PARTICLE_PT_boidbrain,
+ types.PARTICLE_PT_render,
+ types.PARTICLE_PT_draw,
+ types.PARTICLE_PT_children,
+ types.PARTICLE_PT_field_weights,
+ types.PARTICLE_PT_force_fields,
+ types.PARTICLE_PT_vertexgroups,
+ types.MATERIAL_PT_custom_props,
+ types.BONE_PT_custom_props,
+ types.OBJECT_PT_custom_props,
)
diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp
index 0cbd2a0291f..6797ed6b71e 100644
--- a/intern/cycles/blender/blender_camera.cpp
+++ b/intern/cycles/blender/blender_camera.cpp
@@ -65,7 +65,7 @@ struct BlenderCamera {
Transform matrix;
};
-static void blender_camera_init(BlenderCamera *bcam, BL::Scene b_scene)
+static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings b_render, BL::Scene b_scene)
{
memset(bcam, 0, sizeof(BlenderCamera));
@@ -82,10 +82,8 @@ static void blender_camera_init(BlenderCamera *bcam, BL::Scene b_scene)
bcam->pano_viewplane.top = 1.0f;
/* render resolution */
- BL::RenderSettings r = b_scene.render();
-
- bcam->full_width = (int)(r.resolution_x()*r.resolution_percentage()/100);
- bcam->full_height = (int)(r.resolution_y()*r.resolution_percentage()/100);
+ bcam->full_width = (int)(b_render.resolution_x()*b_render.resolution_percentage()/100);
+ bcam->full_height = (int)(b_render.resolution_y()*b_render.resolution_percentage()/100);
}
static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera)
@@ -158,7 +156,12 @@ static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob, boo
if(aperture_type == 1) {
float fstop = RNA_float_get(&ccamera, "aperture_fstop");
- bcam->aperturesize = (bcam->lens*1e-3f)/(2.0f*max(fstop, 1e-5f));
+ fstop = max(fstop, 1e-5f);
+
+ if(bcam->type == CAMERA_ORTHOGRAPHIC)
+ bcam->aperturesize = 1.0f/(2.0f*fstop);
+ else
+ bcam->aperturesize = (bcam->lens*1e-3f)/(2.0f*fstop);
}
else
bcam->aperturesize = RNA_float_get(&ccamera, "aperture_size");
@@ -351,24 +354,22 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int
/* Sync Render Camera */
-void BlenderSync::sync_camera(BL::Object b_override, int width, int height)
+void BlenderSync::sync_camera(BL::RenderSettings b_render, BL::Object b_override, int width, int height)
{
BlenderCamera bcam;
- blender_camera_init(&bcam, b_scene);
+ blender_camera_init(&bcam, b_render, b_scene);
/* pixel aspect */
- BL::RenderSettings r = b_scene.render();
-
- bcam.pixelaspect.x = r.pixel_aspect_x();
- bcam.pixelaspect.y = r.pixel_aspect_y();
- bcam.shuttertime = r.motion_blur_shutter();
+ bcam.pixelaspect.x = b_render.pixel_aspect_x();
+ bcam.pixelaspect.y = b_render.pixel_aspect_y();
+ bcam.shuttertime = b_render.motion_blur_shutter();
/* border */
- if(r.use_border()) {
- bcam.border.left = r.border_min_x();
- bcam.border.right = r.border_max_x();
- bcam.border.bottom = r.border_min_y();
- bcam.border.top = r.border_max_y();
+ if(b_render.use_border()) {
+ 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();
}
/* camera object */
@@ -406,7 +407,7 @@ void BlenderSync::sync_camera_motion(BL::Object b_ob, int motion)
/* Sync 3D View Camera */
-static void blender_camera_view_subset(BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d,
+static void blender_camera_view_subset(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)
@@ -428,7 +429,7 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL:
/* in panorama camera view, we map viewplane to camera border */
BoundBox2D view_box, cam_box;
- blender_camera_view_subset(b_scene, b_ob, b_v3d, b_rv3d, width, height,
+ blender_camera_view_subset(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);
@@ -466,16 +467,15 @@ 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::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d,
+static void blender_camera_view_subset(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)
{
-// BL::RenderSettings r = b_scene.render(); /* UNUSED */
BoundBox2D cam, view;
float view_aspect, cam_aspect, sensor_size;
/* get viewport viewplane */
BlenderCamera view_bcam;
- blender_camera_init(&view_bcam, b_scene);
+ 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_viewplane(&view_bcam, width, height,
@@ -483,7 +483,7 @@ static void blender_camera_view_subset(BL::Scene b_scene, BL::Object b_ob, BL::S
/* get camera viewplane */
BlenderCamera cam_bcam;
- blender_camera_init(&cam_bcam, b_scene);
+ blender_camera_init(&cam_bcam, b_render, b_scene);
blender_camera_from_object(&cam_bcam, b_ob, true);
blender_camera_viewplane(&cam_bcam, cam_bcam.full_width, cam_bcam.full_height,
@@ -494,10 +494,9 @@ static void blender_camera_view_subset(BL::Scene b_scene, BL::Object b_ob, BL::S
*cam_box = cam * (1.0f/cam_aspect);
}
-static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d,
+static void blender_camera_border(BlenderCamera *bcam, BL::RenderSettings b_render, BL::Scene b_scene, BL::SpaceView3D b_v3d,
BL::RegionView3D b_rv3d, int width, int height)
{
- BL::RenderSettings r = b_scene.render();
bool is_camera_view;
/* camera view? */
@@ -517,7 +516,7 @@ static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::Sp
return;
}
}
- else if(!r.use_border())
+ else if(!b_render.use_border())
return;
BL::Object b_ob = (b_v3d.lock_camera_and_layers())? b_scene.camera(): b_v3d.camera();
@@ -525,15 +524,15 @@ static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::Sp
if(!b_ob)
return;
- bcam->border.left = r.border_min_x();
- bcam->border.right = r.border_max_x();
- bcam->border.bottom = r.border_min_y();
- bcam->border.top = r.border_max_y();
+ 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_scene, b_ob, b_v3d, b_rv3d, width, height,
+ 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 */
@@ -544,14 +543,14 @@ static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::Sp
void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height)
{
BlenderCamera bcam;
- blender_camera_init(&bcam, b_scene);
+ 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, b_v3d, b_rv3d, width, height);
+ blender_camera_border(&bcam, b_scene.render(), b_scene, b_v3d, b_rv3d, width, height);
blender_camera_sync(scene->camera, &bcam, width, height);
}
-BufferParams BlenderSync::get_buffer_params(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::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, Camera *cam, int width, int height)
{
BufferParams params;
bool use_border = false;
@@ -562,7 +561,7 @@ BufferParams BlenderSync::get_buffer_params(BL::Scene b_scene, BL::SpaceView3D b
if(b_v3d && b_rv3d && b_rv3d.view_perspective() != BL::RegionView3D::view_perspective_CAMERA)
use_border = b_v3d.use_render_border();
else
- use_border = b_scene.render().use_border();
+ use_border = b_render.use_border();
if(use_border) {
/* border render */
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
new file mode 100644
index 00000000000..768a5a6ee3a
--- /dev/null
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -0,0 +1,1175 @@
+/*
+ * 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.
+ */
+
+#include "attribute.h"
+#include "mesh.h"
+#include "object.h"
+#include "scene.h"
+#include "curves.h"
+
+#include "blender_sync.h"
+#include "blender_util.h"
+
+#include "util_foreach.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Utilities */
+
+/* Hair curve functions */
+
+void curveinterp_v3_v3v3v3v3(float3 *p, float3 *v1, float3 *v2, float3 *v3, float3 *v4, const float w[4]);
+void interp_weights(float t, float data[4], int type);
+float shaperadius(float shape, float root, float tip, float time);
+void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyloc, float *time, ParticleCurveData *CData, int interpolation);
+bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents, bool background, int uv_num);
+bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents, bool background, int vcol_num);
+bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents, bool background);
+void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments);
+void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments, float3 RotCam);
+void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments);
+void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int resolution, int segments);
+void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments, int vert_offset, int resol, float3 *uvdata);
+void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments, int vert_offset, int resol, float3 *fdata);
+
+ParticleCurveData::ParticleCurveData()
+{
+}
+
+ParticleCurveData::~ParticleCurveData()
+{
+ psys_firstcurve.clear();
+ psys_curvenum.clear();
+ psys_shader.clear();
+ psys_rootradius.clear();
+ psys_tipradius.clear();
+ psys_shape.clear();
+
+ curve_firstkey.clear();
+ curve_keynum.clear();
+ curve_length.clear();
+ curve_uv.clear();
+ curve_vcol.clear();
+
+ curvekey_co.clear();
+ curvekey_time.clear();
+}
+
+void interp_weights(float t, float data[4], int type)
+{
+ float t2, t3, fc;
+
+ if(type == CURVE_LINEAR) {
+ data[0] = 0.0f;
+ data[1] = -t + 1.0f;
+ data[2] = t;
+ data[3] = 0.0f;
+ }
+ else if(type == CURVE_CARDINAL) {
+ t2 = t * t;
+ t3 = t2 * t;
+ fc = 0.71f;
+
+ data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t;
+ data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f;
+ data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
+ data[3] = fc * t3 - fc * t2;
+ }
+ else if(type == CURVE_BSPLINE) {
+ t2 = t * t;
+ t3 = t2 * t;
+
+ data[0] = -0.16666666f * t3 + 0.5f * t2 - 0.5f * t + 0.16666666f;
+ data[1] = 0.5f * t3 - t2 + 0.66666666f;
+ data[2] = -0.5f * t3 + 0.5f * t2 + 0.5f * t + 0.16666666f;
+ data[3] = 0.16666666f * t3;
+ }
+}
+
+void curveinterp_v3_v3v3v3v3(float3 *p, float3 *v1, float3 *v2, float3 *v3, float3 *v4, const float w[4])
+{
+ p->x = v1->x * w[0] + v2->x * w[1] + v3->x * w[2] + v4->x * w[3];
+ p->y = v1->y * w[0] + v2->y * w[1] + v3->y * w[2] + v4->y * w[3];
+ p->z = v1->z * w[0] + v2->z * w[1] + v3->z * w[2] + v4->z * w[3];
+}
+
+float shaperadius(float shape, float root, float tip, float time)
+{
+ float radius = 1.0f - time;
+ if(shape != 0.0f) {
+ if(shape < 0.0f)
+ radius = (float)pow(1.0f - time, 1.f + shape);
+ else
+ radius = (float)pow(1.0f - time, 1.f / (1.f - shape));
+ }
+ return (radius * (root - tip)) + tip;
+}
+
+/* curve functions */
+
+void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyloc, float *time, ParticleCurveData *CData, int interpolation)
+{
+ float3 ckey_loc1 = CData->curvekey_co[key];
+ float3 ckey_loc2 = ckey_loc1;
+ float3 ckey_loc3 = CData->curvekey_co[key+1];
+ float3 ckey_loc4 = ckey_loc3;
+
+ if(key > CData->curve_firstkey[curve])
+ ckey_loc1 = CData->curvekey_co[key - 1];
+
+ if(key < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)
+ ckey_loc4 = CData->curvekey_co[key + 2];
+
+
+ float time1 = CData->curvekey_time[key]/CData->curve_length[curve];
+ float time2 = CData->curvekey_time[key + 1]/CData->curve_length[curve];
+
+ float dfra = (time2 - time1) / (float)segno;
+
+ if(time)
+ *time = (dfra * seg) + time1;
+
+ float t[4];
+
+ interp_weights((float)seg / (float)segno, t, interpolation);
+
+ if(keyloc)
+ curveinterp_v3_v3v3v3v3(keyloc, &ckey_loc1, &ckey_loc2, &ckey_loc3, &ckey_loc4, t);
+}
+
+bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents, bool background)
+{
+
+ int curvenum = 0;
+ int keyno = 0;
+
+ if(!(mesh && b_mesh && b_ob && CData))
+ return false;
+
+ Transform tfm = get_transform(b_ob->matrix_world());
+ Transform itfm = transform_quick_inverse(tfm);
+
+ 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) && (background ? b_mod->show_render() : b_mod->show_viewport())) {
+ BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
+
+ BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
+
+ BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+
+ if((b_psys.settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys.settings().type()==BL::ParticleSettings::type_HAIR)) {
+
+ int mi = clamp(b_psys.settings().material()-1, 0, mesh->used_shaders.size()-1);
+ int shader = mesh->used_shaders[mi];
+ int draw_step = background ? b_psys.settings().render_step() : b_psys.settings().draw_step();
+ int ren_step = (int)pow((float)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_psys.settings().draw_percentage() / 100.0f);
+ int totcurves = totchild;
+
+ if(use_parents || b_psys.settings().child_type() == 0)
+ totcurves += totparts;
+
+ if(totcurves == 0)
+ continue;
+
+ PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles");
+
+ CData->psys_firstcurve.push_back(curvenum);
+ CData->psys_curvenum.push_back(totcurves);
+ CData->psys_shader.push_back(shader);
+
+ float radius = b_psys.settings().particle_size() * 0.5f;
+
+ CData->psys_rootradius.push_back(radius * get_float(cpsys, "root_width"));
+ CData->psys_tipradius.push_back(radius * get_float(cpsys, "tip_width"));
+ CData->psys_shape.push_back(get_float(cpsys, "shape"));
+ CData->psys_closetip.push_back(get_boolean(cpsys, "use_closetip"));
+
+ int pa_no = 0;
+ if(!use_parents && !(b_psys.settings().child_type() == 0))
+ pa_no = totparts;
+
+ for(; pa_no < totparts+totchild; pa_no++) {
+
+ CData->curve_firstkey.push_back(keyno);
+ CData->curve_keynum.push_back(ren_step+1);
+
+ float curve_length = 0.0f;
+ float3 pcKey;
+ for(int step_no = 0; step_no <= ren_step; step_no++) {
+ float nco[3];
+ b_psys.co_hair(*b_ob, psmd, pa_no, step_no, nco);
+ float3 cKey = make_float3(nco[0],nco[1],nco[2]);
+ cKey = transform_point(&itfm, cKey);
+ if(step_no > 0)
+ curve_length += len(cKey - pcKey);
+ CData->curvekey_co.push_back(cKey);
+ CData->curvekey_time.push_back(curve_length);
+ pcKey = cKey;
+ keyno++;
+ }
+ CData->curve_length.push_back(curve_length);
+
+ curvenum++;
+
+ }
+ }
+
+ }
+ }
+
+ return true;
+
+}
+
+bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents, bool background, int uv_num)
+{
+#if 0
+ int keyno = 0;
+#endif
+
+ if(!(mesh && b_mesh && b_ob && CData))
+ return false;
+
+#if 0
+ Transform tfm = get_transform(b_ob->matrix_world());
+ Transform itfm = transform_quick_inverse(tfm);
+#endif
+
+ CData->curve_uv.clear();
+
+ 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) && (background ? b_mod->show_render() : b_mod->show_viewport())) {
+ BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
+
+ BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
+
+ BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+
+ if((b_psys.settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys.settings().type()==BL::ParticleSettings::type_HAIR)) {
+#if 0
+ int mi = clamp(b_psys.settings().material()-1, 0, mesh->used_shaders.size()-1);
+ int shader = mesh->used_shaders[mi];
+#endif
+
+ int totparts = b_psys.particles.length();
+ int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_psys.settings().draw_percentage() / 100.0f);
+ int totcurves = totchild;
+
+ if (use_parents || b_psys.settings().child_type() == 0)
+ totcurves += totparts;
+
+ if (totcurves == 0)
+ continue;
+
+ int pa_no = 0;
+ if(!use_parents && !(b_psys.settings().child_type() == 0))
+ pa_no = totparts;
+
+ BL::ParticleSystem::particles_iterator b_pa;
+ b_psys.particles.begin(b_pa);
+ for(; pa_no < totparts+totchild; pa_no++) {
+
+ /*add uvs*/
+ BL::Mesh::tessface_uv_textures_iterator l;
+ b_mesh->tessface_uv_textures.begin(l);
+
+ float3 uv = make_float3(0.0f, 0.0f, 0.0f);
+ if(b_mesh->tessface_uv_textures.length())
+ b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uv_num, &uv.x);
+ CData->curve_uv.push_back(uv);
+
+ if(pa_no < totparts && b_pa != b_psys.particles.end())
+ ++b_pa;
+
+ }
+ }
+
+ }
+ }
+
+ return true;
+
+}
+
+bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents, bool background, int vcol_num)
+{
+#if 0
+ int keyno = 0;
+#endif
+ if(!(mesh && b_mesh && b_ob && CData))
+ return false;
+
+#if 0
+ Transform tfm = get_transform(b_ob->matrix_world());
+ Transform itfm = transform_quick_inverse(tfm);
+#endif
+
+ CData->curve_vcol.clear();
+
+ 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) && (background ? b_mod->show_render() : b_mod->show_viewport())) {
+ BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
+
+ BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
+
+ BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+
+ if((b_psys.settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys.settings().type()==BL::ParticleSettings::type_HAIR)) {
+#if 0
+ int mi = clamp(b_psys.settings().material()-1, 0, mesh->used_shaders.size()-1);
+ int shader = mesh->used_shaders[mi];
+#endif
+ int totparts = b_psys.particles.length();
+ int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_psys.settings().draw_percentage() / 100.0f);
+ int totcurves = totchild;
+
+ if (use_parents || b_psys.settings().child_type() == 0)
+ totcurves += totparts;
+
+ if (totcurves == 0)
+ continue;
+
+ int pa_no = 0;
+ if(!use_parents && !(b_psys.settings().child_type() == 0))
+ pa_no = totparts;
+
+ BL::ParticleSystem::particles_iterator b_pa;
+ b_psys.particles.begin(b_pa);
+ for(; pa_no < totparts+totchild; pa_no++) {
+
+ /*add uvs*/
+ BL::Mesh::tessface_vertex_colors_iterator l;
+ b_mesh->tessface_vertex_colors.begin(l);
+
+ float3 vcol = make_float3(0.0f, 0.0f, 0.0f);
+ if(b_mesh->tessface_vertex_colors.length())
+ b_psys.mcol_on_emitter(psmd, *b_pa, pa_no, vcol_num, &vcol.x);
+ CData->curve_vcol.push_back(vcol);
+
+ if(pa_no < totparts && b_pa != b_psys.particles.end())
+ ++b_pa;
+
+ }
+ }
+
+ }
+ }
+
+ return true;
+
+}
+
+static void set_resolution(Mesh *mesh, BL::Mesh *b_mesh, 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()))) {
+ 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);
+ }
+ }
+}
+
+void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments, float3 RotCam)
+{
+ int vertexno = mesh->verts.size();
+ int vertexindex = vertexno;
+
+ for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
+ for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+
+ for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+ int subv = 1;
+ float3 xbasis;
+
+ float3 v1;
+
+ if(curvekey == CData->curve_firstkey[curve]) {
+ subv = 0;
+ v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey];
+ }
+ else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)
+ v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[max(curvekey - 2, CData->curve_firstkey[curve])];
+ else
+ v1 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey - 1];
+
+
+ for (; subv <= segments; subv++) {
+
+ float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
+ float time = 0.0f;
+
+ if ((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
+ ickey_loc = CData->curvekey_co[curvekey];
+ else
+ InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
+
+ float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
+
+ if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
+ radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
+
+ if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
+ radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
+
+ xbasis = normalize(cross(RotCam - ickey_loc,v1));
+ float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
+ float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
+ mesh->verts.push_back(ickey_loc_shfl);
+ mesh->verts.push_back(ickey_loc_shfr);
+ if(subv!=0) {
+ mesh->add_triangle(vertexindex-2, vertexindex, vertexindex-1, CData->psys_shader[sys], use_smooth);
+ mesh->add_triangle(vertexindex+1, vertexindex-1, vertexindex, CData->psys_shader[sys], use_smooth);
+ }
+ vertexindex += 2;
+ }
+ }
+ }
+ }
+
+ mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
+ mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+ mesh->add_face_normals();
+ mesh->add_vertex_normals();
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+
+ /* texture coords still needed */
+}
+
+void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments)
+{
+ int vertexno = mesh->verts.size();
+ int vertexindex = vertexno;
+
+ for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
+ for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+
+ float3 firstxbasis = cross(make_float3(1.0f,0.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]);
+ if(len_squared(firstxbasis)!= 0.0f)
+ firstxbasis = normalize(firstxbasis);
+ else
+ firstxbasis = normalize(cross(make_float3(0.0f,1.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]));
+
+ for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+ float3 xbasis = firstxbasis;
+ float3 v1;
+ float3 v2;
+
+ if(curvekey == CData->curve_firstkey[curve]) {
+ v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
+ v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+ }
+ else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
+ v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+ v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
+ }
+ else {
+ v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+ v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+ }
+
+ xbasis = cross(v1,v2);
+
+ if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
+ firstxbasis = normalize(xbasis);
+ break;
+ }
+ }
+
+ for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+ int subv = 1;
+ float3 v1;
+ float3 v2;
+ float3 xbasis;
+
+ if(curvekey == CData->curve_firstkey[curve]) {
+ subv = 0;
+ v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
+ v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+ }
+ else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
+ v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+ v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
+ }
+ else {
+ v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+ v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+ }
+
+ xbasis = cross(v1,v2);
+
+ if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
+ xbasis = normalize(xbasis);
+ firstxbasis = xbasis;
+ }
+ else
+ xbasis = firstxbasis;
+
+ for (; subv <= segments; subv++) {
+
+ float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
+ float time = 0.0f;
+
+ if ((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
+ ickey_loc = CData->curvekey_co[curvekey];
+ else
+ InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
+
+ float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
+
+ if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
+ radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
+
+ if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
+ radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
+
+ float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
+ float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
+ mesh->verts.push_back(ickey_loc_shfl);
+ mesh->verts.push_back(ickey_loc_shfr);
+ if(subv!=0) {
+ mesh->add_triangle(vertexindex-2, vertexindex, vertexindex-1, CData->psys_shader[sys], use_smooth);
+ mesh->add_triangle(vertexindex+1, vertexindex-1, vertexindex, CData->psys_shader[sys], use_smooth);
+ }
+ vertexindex += 2;
+ }
+ }
+ }
+ }
+
+ mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
+ mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+ mesh->add_face_normals();
+ mesh->add_vertex_normals();
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+ /* texture coords still needed */
+
+}
+
+void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int resolution, int segments)
+{
+ int vertexno = mesh->verts.size();
+ int vertexindex = vertexno;
+
+ for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
+ for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+
+ float3 firstxbasis = cross(make_float3(1.0f,0.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]);
+ if(len_squared(firstxbasis)!= 0.0f)
+ firstxbasis = normalize(firstxbasis);
+ else
+ firstxbasis = normalize(cross(make_float3(0.0f,1.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]));
+
+
+ for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+ float3 xbasis = firstxbasis;
+ float3 v1;
+ float3 v2;
+
+ if(curvekey == CData->curve_firstkey[curve]) {
+ v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
+ v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+ }
+ else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
+ v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+ v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
+ }
+ else {
+ v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+ v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+ }
+
+ xbasis = cross(v1,v2);
+
+ if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
+ firstxbasis = normalize(xbasis);
+ break;
+ }
+ }
+
+ for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+ int subv = 1;
+ float3 xbasis;
+ float3 ybasis;
+ float3 v1;
+ float3 v2;
+
+ if(curvekey == CData->curve_firstkey[curve]) {
+ subv = 0;
+ v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
+ v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+ }
+ else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
+ v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+ v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
+ }
+ else {
+ v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+ v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+ }
+
+ xbasis = cross(v1,v2);
+
+ if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
+ xbasis = normalize(xbasis);
+ firstxbasis = xbasis;
+ }
+ else
+ xbasis = firstxbasis;
+
+ ybasis = normalize(cross(xbasis,v2));
+
+ for (; subv <= segments; subv++) {
+
+ float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
+ float time = 0.0f;
+
+ if ((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
+ ickey_loc = CData->curvekey_co[curvekey];
+ else
+ InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
+
+ float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
+
+ if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments))
+ radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
+
+ if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
+ radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
+
+ float angle = 2 * M_PI_F / (float)resolution;
+ for(int section = 0 ; section < resolution; section++) {
+ float3 ickey_loc_shf = ickey_loc + radius * (cosf(angle * section) * xbasis + sinf(angle * section) * ybasis);
+ mesh->verts.push_back(ickey_loc_shf);
+ }
+
+ if(subv!=0) {
+ for(int section = 0 ; section < resolution - 1; section++) {
+ mesh->add_triangle(vertexindex - resolution + section, vertexindex + section, vertexindex - resolution + section + 1, CData->psys_shader[sys], use_smooth);
+ mesh->add_triangle(vertexindex + section + 1, vertexindex - resolution + section + 1, vertexindex + section, CData->psys_shader[sys], use_smooth);
+ }
+ mesh->add_triangle(vertexindex-1, vertexindex + resolution - 1, vertexindex - resolution, CData->psys_shader[sys], use_smooth);
+ mesh->add_triangle(vertexindex, vertexindex - resolution , vertexindex + resolution - 1, CData->psys_shader[sys], use_smooth);
+ }
+ vertexindex += resolution;
+ }
+ }
+ }
+ }
+
+ mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
+ mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+ mesh->add_face_normals();
+ mesh->add_vertex_normals();
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+
+ /* texture coords still needed */
+}
+
+static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments)
+{
+ int num_keys = 0;
+ int num_curves = 0;
+
+ if(!(mesh->curves.empty() && mesh->curve_keys.empty()))
+ return;
+
+ Attribute *attr_intercept = NULL;
+
+ if(mesh->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT))
+ attr_intercept = mesh->curve_attributes.add(ATTR_STD_CURVE_INTERCEPT);
+
+ for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
+
+ if(CData->psys_curvenum[sys] == 0)
+ continue;
+
+ for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+
+ if(CData->curve_keynum[curve] <= 1)
+ continue;
+
+ size_t num_curve_keys = 0;
+
+ for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+ int subv = 1;
+ if(curvekey == CData->curve_firstkey[curve])
+ subv = 0;
+
+ for (; subv <= segments; subv++) {
+
+ float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
+ float time = 0.0f;
+
+ if((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
+ ickey_loc = CData->curvekey_co[curvekey];
+ else
+ InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
+
+ float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
+
+ if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
+ radius =0.0f;
+
+ mesh->add_curve_key(ickey_loc, radius);
+ if(attr_intercept)
+ attr_intercept->add(time);
+
+ num_curve_keys++;
+ }
+ }
+
+ mesh->add_curve(num_keys, num_curve_keys, CData->psys_shader[sys]);
+ num_keys += num_curve_keys;
+ num_curves++;
+ }
+ }
+
+ /* check allocation*/
+ if((mesh->curve_keys.size() != num_keys) || (mesh->curves.size() != num_curves)) {
+ /* allocation failed -> clear data */
+ mesh->curve_keys.clear();
+ mesh->curves.clear();
+ mesh->curve_attributes.clear();
+ }
+}
+
+void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments, int vert_offset, int resol, float3 *uvdata)
+{
+ if(uvdata == NULL)
+ return;
+
+ float time = 0.0f;
+ float prevtime = 0.0f;
+
+ int vertexindex = vert_offset;
+
+ for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
+ for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+
+ for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+ int subv = 1;
+
+ if (curvekey == CData->curve_firstkey[curve])
+ subv = 0;
+
+ for (; subv <= segments; subv++) {
+
+ float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
+
+ InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
+
+ if(subv!=0) {
+ for(int section = 0 ; section < resol; section++) {
+ uvdata[vertexindex] = CData->curve_uv[curve];
+ uvdata[vertexindex].z = prevtime;
+ vertexindex++;
+ uvdata[vertexindex] = CData->curve_uv[curve];
+ uvdata[vertexindex].z = time;
+ vertexindex++;
+ uvdata[vertexindex] = CData->curve_uv[curve];
+ uvdata[vertexindex].z = prevtime;
+ vertexindex++;
+ uvdata[vertexindex] = CData->curve_uv[curve];
+ uvdata[vertexindex].z = time;
+ vertexindex++;
+ uvdata[vertexindex] = CData->curve_uv[curve];
+ uvdata[vertexindex].z = prevtime;
+ vertexindex++;
+ uvdata[vertexindex] = CData->curve_uv[curve];
+ uvdata[vertexindex].z = time;
+ vertexindex++;
+ }
+ }
+
+ prevtime = time;
+ }
+ }
+ }
+ }
+
+}
+
+void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments, int vert_offset, int resol, float3 *fdata)
+{
+ if(fdata == NULL)
+ return;
+
+ float time = 0.0f;
+// float prevtime = 0.0f; // UNUSED
+
+ int vertexindex = vert_offset;
+
+ for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
+ for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+
+ for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+ int subv = 1;
+
+ if (curvekey == CData->curve_firstkey[curve])
+ subv = 0;
+
+ for (; subv <= segments; subv++) {
+
+ float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
+
+ InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
+
+ if(subv!=0) {
+ for(int section = 0 ; section < resol; section++) {
+ fdata[vertexindex] = color_srgb_to_scene_linear(CData->curve_vcol[curve]);
+ vertexindex++;
+ fdata[vertexindex] = color_srgb_to_scene_linear(CData->curve_vcol[curve]);
+ vertexindex++;
+ fdata[vertexindex] = color_srgb_to_scene_linear(CData->curve_vcol[curve]);
+ vertexindex++;
+ fdata[vertexindex] = color_srgb_to_scene_linear(CData->curve_vcol[curve]);
+ vertexindex++;
+ fdata[vertexindex] = color_srgb_to_scene_linear(CData->curve_vcol[curve]);
+ vertexindex++;
+ fdata[vertexindex] = color_srgb_to_scene_linear(CData->curve_vcol[curve]);
+ vertexindex++;
+ }
+ }
+
+ // prevtime = time; // UNUSED
+ }
+ }
+ }
+ }
+
+}
+
+/* Hair Curve Sync */
+
+void BlenderSync::sync_curve_settings()
+{
+ PointerRNA csscene = RNA_pointer_get(&b_scene.ptr, "cycles_curves");
+
+ int preset = get_enum(csscene, "preset");
+
+ CurveSystemManager *curve_system_manager = scene->curve_system_manager;
+ CurveSystemManager prev_curve_system_manager = *curve_system_manager;
+
+ curve_system_manager->use_curves = get_boolean(csscene, "use_curves");
+
+ if(preset == CURVE_CUSTOM) {
+ /*custom properties*/
+ curve_system_manager->primitive = get_enum(csscene, "primitive");
+ curve_system_manager->line_method = get_enum(csscene, "line_method");
+ curve_system_manager->interpolation = get_enum(csscene, "interpolation");
+ curve_system_manager->triangle_method = get_enum(csscene, "triangle_method");
+ curve_system_manager->resolution = get_int(csscene, "resolution");
+ curve_system_manager->segments = get_int(csscene, "segments");
+ curve_system_manager->use_smooth = get_boolean(csscene, "use_smooth");
+ curve_system_manager->subdivisions = get_int(csscene, "subdivisions");
+
+ curve_system_manager->normalmix = get_float(csscene, "normalmix");
+ curve_system_manager->encasing_ratio = get_float(csscene, "encasing_ratio");
+
+ curve_system_manager->use_parents = get_boolean(csscene, "use_parents");
+ curve_system_manager->use_encasing = get_boolean(csscene, "use_encasing");
+ curve_system_manager->use_backfacing = get_boolean(csscene, "use_backfacing");
+ curve_system_manager->use_joined = get_boolean(csscene, "use_joined");
+ curve_system_manager->use_tangent_normal = get_boolean(csscene, "use_tangent_normal");
+ curve_system_manager->use_tangent_normal_geometry = get_boolean(csscene, "use_tangent_normal_geometry");
+ curve_system_manager->use_tangent_normal_correction = get_boolean(csscene, "use_tangent_normal_correction");
+ }
+ else {
+ curve_system_manager->primitive = CURVE_LINE_SEGMENTS;
+ curve_system_manager->interpolation = CURVE_CARDINAL;
+ curve_system_manager->normalmix = 1.0f;
+ curve_system_manager->encasing_ratio = 1.01f;
+ curve_system_manager->use_parents = false;
+ curve_system_manager->segments = 1;
+ curve_system_manager->use_joined = false;
+
+ switch(preset) {
+ case CURVE_FAST_PLANES:
+ /*camera facing planes*/
+ curve_system_manager->primitive = CURVE_TRIANGLES;
+ curve_system_manager->triangle_method = CURVE_CAMERA_TRIANGLES;
+ curve_system_manager->use_smooth = true;
+ curve_system_manager->resolution = 1;
+ break;
+ case CURVE_TANGENT_SHADING:
+ /*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 = true;
+ curve_system_manager->use_tangent_normal_geometry = true;
+ curve_system_manager->use_tangent_normal_correction = false;
+ break;
+ case CURVE_TRUE_NORMAL:
+ /*True Normal*/
+ curve_system_manager->line_method = CURVE_CORRECTED;
+ curve_system_manager->use_encasing = true;
+ curve_system_manager->use_backfacing = false;
+ curve_system_manager->use_tangent_normal = false;
+ curve_system_manager->use_tangent_normal_geometry = false;
+ curve_system_manager->use_tangent_normal_correction = false;
+ break;
+ case CURVE_ACCURATE_PRESET:
+ /*Accurate*/
+ curve_system_manager->line_method = CURVE_ACCURATE;
+ curve_system_manager->use_encasing = false;
+ curve_system_manager->use_backfacing = true;
+ curve_system_manager->use_tangent_normal = false;
+ curve_system_manager->use_tangent_normal_geometry = false;
+ curve_system_manager->use_tangent_normal_correction = false;
+ break;
+ case CURVE_SMOOTH_CURVES:
+ /*Cardinal curves preset*/
+ curve_system_manager->primitive = CURVE_SEGMENTS;
+ curve_system_manager->use_backfacing = true;
+ curve_system_manager->subdivisions = 4;
+ break;
+ }
+
+ }
+
+ if(curve_system_manager->modified_mesh(prev_curve_system_manager))
+ {
+ BL::BlendData::objects_iterator b_ob;
+
+ for(b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) {
+ if(object_is_mesh(*b_ob)) {
+ BL::Object::particle_systems_iterator b_psys;
+ for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) {
+ if((b_psys->settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys->settings().type()==BL::ParticleSettings::type_HAIR)) {
+ BL::ID key = BKE_object_is_modified(*b_ob)? *b_ob: b_ob->data();
+ mesh_map.set_recalc(key);
+ object_map.set_recalc(*b_ob);
+ }
+ }
+ }
+ }
+ }
+
+ if(curve_system_manager->modified(prev_curve_system_manager))
+ curve_system_manager->tag_update(scene);
+
+}
+
+void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool object_updated)
+{
+ /* Clear stored curve data */
+ mesh->curve_keys.clear();
+ mesh->curves.clear();
+ mesh->curve_attributes.clear();
+
+ /* obtain general settings */
+ bool use_curves = scene->curve_system_manager->use_curves;
+
+ if(!(use_curves && b_ob.mode() == b_ob.mode_OBJECT)) {
+ mesh->compute_bounds();
+ return;
+ }
+
+ int primitive = scene->curve_system_manager->primitive;
+ int interpolation = scene->curve_system_manager->interpolation;
+ int triangle_method = scene->curve_system_manager->triangle_method;
+ int resolution = scene->curve_system_manager->resolution;
+ int segments = scene->curve_system_manager->segments;
+ bool use_smooth = scene->curve_system_manager->use_smooth;
+ bool use_parents = scene->curve_system_manager->use_parents;
+ bool export_tgs = scene->curve_system_manager->use_joined;
+ size_t vert_num = mesh->verts.size();
+ size_t tri_num = mesh->triangles.size();
+ int used_res = 1;
+
+ /* extract particle hair data - should be combined with connecting to mesh later*/
+
+ ParticleCurveData CData;
+
+ if(!preview)
+ set_resolution(mesh, &b_mesh, &b_ob, &b_scene, true);
+
+ ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, use_parents, !preview);
+
+ /* obtain camera parameters */
+ BL::Object b_CamOb = b_scene.camera();
+ float3 RotCam = make_float3(0.0f, 0.0f, 0.0f);
+ if(b_CamOb) {
+ Transform ctfm = get_transform(b_CamOb.matrix_world());
+ Transform tfm = get_transform(b_ob.matrix_world());
+ Transform itfm = transform_quick_inverse(tfm);
+ RotCam = transform_point(&itfm, make_float3(ctfm.x.w, ctfm.y.w, ctfm.z.w));
+ }
+
+ /* add hair geometry to mesh */
+ if(primitive == CURVE_TRIANGLES){
+ if(triangle_method == CURVE_CAMERA_TRIANGLES)
+ ExportCurveTrianglePlanes(mesh, &CData, interpolation, use_smooth, segments, RotCam);
+ else if(triangle_method == CURVE_RIBBON_TRIANGLES)
+ ExportCurveTriangleRibbons(mesh, &CData, interpolation, use_smooth, segments);
+ else {
+ ExportCurveTriangleGeometry(mesh, &CData, interpolation, use_smooth, resolution, segments);
+ used_res = resolution;
+ }
+ }
+ else {
+ ExportCurveSegments(scene, mesh, &CData, interpolation, segments);
+ int ckey_num = mesh->curve_keys.size();
+
+ /*export tangents or curve data? - not functional yet*/
+ if(export_tgs && ckey_num > 1) {
+ Attribute *attr_tangent = mesh->curve_attributes.add(ATTR_STD_CURVE_TANGENT);
+ float3 *data_tangent = attr_tangent->data_float3();
+
+ for(int ck = 0; ck < ckey_num; ck++) {
+ float3 tg = normalize(normalize(mesh->curve_keys[min(ck + 1, ckey_num - 1)].co - mesh->curve_keys[ck].co) -
+ normalize(mesh->curve_keys[max(ck - 1, 0)].co - mesh->curve_keys[ck].co));
+
+ data_tangent[ck] = tg;
+ }
+ }
+ }
+
+
+ /* generated coordinates from first key. we should ideally get this from
+ * blender to handle deforming objects */
+ {
+ if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
+ float3 loc, size;
+ mesh_texture_space(b_mesh, loc, size);
+
+ if(primitive == CURVE_TRIANGLES) {
+ Attribute *attr_generated = mesh->attributes.add(ATTR_STD_GENERATED);
+ float3 *generated = attr_generated->data_float3();
+
+ for(size_t i = vert_num; i < mesh->verts.size(); i++)
+ generated[i] = mesh->verts[i]*size - loc;
+ }
+ else {
+ Attribute *attr_generated = mesh->curve_attributes.add(ATTR_STD_GENERATED);
+ float3 *generated = attr_generated->data_float3();
+ size_t i = 0;
+
+ foreach(Mesh::Curve& curve, mesh->curves) {
+ float3 co = mesh->curve_keys[curve.first_key].co;
+ generated[i++] = co*size - loc;
+ }
+ }
+ }
+ }
+
+ /* create vertex color attributes */
+ {
+ BL::Mesh::tessface_vertex_colors_iterator l;
+ int vcol_num = 0;
+
+ for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l, vcol_num++) {
+ if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
+ continue;
+
+ ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, use_parents, !preview, vcol_num);
+
+ if(primitive == CURVE_TRIANGLES) {
+
+ Attribute *attr_vcol = mesh->attributes.add(
+ ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER);
+
+ float3 *fdata = attr_vcol->data_float3();
+
+ ExportCurveTriangleVcol(mesh, &CData, interpolation, segments, tri_num * 3, used_res, fdata);
+ }
+ else {
+ Attribute *attr_vcol = mesh->curve_attributes.add(
+ ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CURVE);
+
+ float3 *fdata = attr_vcol->data_float3();
+
+ if(fdata) {
+ for(size_t curve = 0; curve < CData.curve_vcol.size() ;curve++)
+ fdata[curve] = color_srgb_to_scene_linear(CData.curve_vcol[curve]);
+ }
+ }
+ }
+ }
+
+ /* create UV attributes */
+ {
+ BL::Mesh::tessface_uv_textures_iterator l;
+ int uv_num = 0;
+
+ for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l, uv_num++) {
+ 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_uv;
+
+ ObtainCacheParticleUV(mesh, &b_mesh, &b_ob, &CData, use_parents, !preview, uv_num);
+
+ if(primitive == CURVE_TRIANGLES) {
+ if(active_render)
+ attr_uv = mesh->attributes.add(std, name);
+ else
+ attr_uv = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
+
+ float3 *uv = attr_uv->data_float3();
+
+ ExportCurveTriangleUV(mesh, &CData, interpolation, segments, tri_num * 3, used_res, uv);
+ }
+ else {
+ if(active_render)
+ attr_uv = mesh->curve_attributes.add(std, name);
+ else
+ attr_uv = mesh->curve_attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
+
+ float3 *uv = attr_uv->data_float3();
+
+ if(uv) {
+ for(size_t curve = 0; curve < CData.curve_uv.size(); curve++)
+ uv[curve] = CData.curve_uv[curve];
+ }
+ }
+ }
+ }
+ }
+
+ if(!preview)
+ set_resolution(mesh, &b_mesh, &b_ob, &b_scene, false);
+
+ mesh->compute_bounds();
+}
+
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index c9748756d43..10e3946dbd2 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -147,7 +147,7 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_la
if(active_render)
attr = mesh->attributes.add(ATTR_STD_UV_TANGENT, name);
else
- attr = mesh->attributes.add(name, TypeDesc::TypeVector, Attribute::CORNER);
+ attr = mesh->attributes.add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
float3 *tangent = attr->data_float3();
@@ -161,7 +161,7 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_la
if(active_render)
attr_sign = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign);
else
- attr_sign = mesh->attributes.add(name_sign, TypeDesc::TypeFloat, Attribute::CORNER);
+ attr_sign = mesh->attributes.add(name_sign, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
tangent_sign = attr_sign->data_float();
}
@@ -223,10 +223,19 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
int shader = used_shaders[mi];
bool smooth = f->use_smooth();
- mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
-
- if(n == 4)
- mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);
+ if(n == 4) {
+ if(len_squared(cross(mesh->verts[vi[1]] - mesh->verts[vi[0]], mesh->verts[vi[2]] - mesh->verts[vi[0]])) == 0.0f ||
+ len_squared(cross(mesh->verts[vi[2]] - mesh->verts[vi[0]], mesh->verts[vi[3]] - mesh->verts[vi[0]])) == 0.0f) {
+ mesh->add_triangle(vi[0], vi[1], vi[3], shader, smooth);
+ mesh->add_triangle(vi[2], vi[3], vi[1], shader, smooth);
+ }
+ else {
+ mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
+ mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);
+ }
+ }
+ else
+ mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
nverts.push_back(n);
}
@@ -240,7 +249,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
continue;
Attribute *attr = mesh->attributes.add(
- ustring(l->name().c_str()), TypeDesc::TypeColor, Attribute::CORNER);
+ ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER);
BL::MeshColorLayer::data_iterator c;
float3 *fdata = attr->data_float3();
@@ -279,7 +288,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
if(active_render)
attr = mesh->attributes.add(std, name);
else
- attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER);
+ attr = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
BL::MeshTextureFaceLayer::data_iterator t;
float3 *fdata = attr->data_float3();
@@ -304,7 +313,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
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) || mesh->need_attribute(scene, std)) {
+ 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));
@@ -319,14 +328,9 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
* is available in the api. */
if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED);
- float3 loc = get_float3(b_mesh.texspace_location());
- float3 size = get_float3(b_mesh.texspace_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);
+ float3 loc, size;
+ mesh_texture_space(b_mesh, loc, size);
float3 *generated = attr->data_float3();
size_t i = 0;
@@ -376,7 +380,7 @@ static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, con
/* Sync */
-Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated)
+Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tris)
{
/* test if we can instance or if the object is modified */
BL::ID b_ob_data = b_ob.data();
@@ -431,20 +435,28 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated)
mesh_synced.insert(mesh);
/* create derived mesh */
- BL::Mesh b_mesh = object_to_mesh(b_ob, b_scene, true, !preview);
+ BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_scene, true, !preview);
PointerRNA cmesh = RNA_pointer_get(&b_ob_data.ptr, "cycles");
vector<Mesh::Triangle> oldtriangle = mesh->triangles;
+
+ /* compares curve_keys rather than strands in order to handle quick hair adjustsments in dynamic BVH - other methods could probably do this better*/
+ vector<Mesh::CurveKey> oldcurve_keys = mesh->curve_keys;
mesh->clear();
mesh->used_shaders = used_shaders;
mesh->name = ustring(b_ob_data.name().c_str());
if(b_mesh) {
- if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision"))
- create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders);
- else
- create_mesh(scene, mesh, b_mesh, used_shaders);
+ if(!(hide_tris && experimental && is_cpu)) {
+ if(cmesh.data && experimental && RNA_boolean_get(&cmesh, "use_subdivision"))
+ create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders);
+ else
+ create_mesh(scene, mesh, b_mesh, used_shaders);
+ }
+
+ if(experimental && is_cpu)
+ sync_curves(mesh, b_mesh, b_ob, object_updated);
/* free derived mesh */
b_data.meshes.remove(b_mesh);
@@ -452,7 +464,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated)
/* displacement method */
if(cmesh.data) {
- int method = RNA_enum_get(&cmesh, "displacement_method");
+ const int method = RNA_enum_get(&cmesh, "displacement_method");
if(method == 0 || !experimental)
mesh->displacement_method = Mesh::DISPLACE_BUMP;
@@ -471,6 +483,13 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated)
if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(Mesh::Triangle)*oldtriangle.size()) != 0)
rebuild = true;
}
+
+ if(oldcurve_keys.size() != mesh->curve_keys.size())
+ rebuild = true;
+ else if(oldcurve_keys.size()) {
+ if(memcmp(&oldcurve_keys[0], &mesh->curve_keys[0], sizeof(Mesh::CurveKey)*oldcurve_keys.size()) != 0)
+ rebuild = true;
+ }
mesh->tag_update(scene, rebuild);
@@ -488,7 +507,7 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion)
return;
/* get derived mesh */
- BL::Mesh b_mesh = object_to_mesh(b_ob, b_scene, true, !preview);
+ BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_scene, true, !preview);
if(b_mesh) {
BL::Mesh::vertices_iterator v;
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 38f27bcf2af..33546bfa25e 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -127,8 +127,8 @@ void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSI
case BL::Lamp::type_AREA: {
BL::AreaLamp b_area_lamp(b_lamp);
light->size = 1.0f;
- light->axisu = make_float3(tfm.x.x, tfm.y.x, tfm.z.x);
- light->axisv = make_float3(tfm.x.y, tfm.y.y, tfm.z.y);
+ light->axisu = transform_get_column(&tfm, 0);
+ light->axisv = transform_get_column(&tfm, 1);
light->sizeu = b_area_lamp.size();
if(b_area_lamp.shape() == BL::AreaLamp::shape_RECTANGLE)
light->sizev = b_area_lamp.size_y();
@@ -140,8 +140,8 @@ void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSI
}
/* location and (inverted!) direction */
- light->co = make_float3(tfm.x.w, tfm.y.w, tfm.z.w);
- light->dir = -make_float3(tfm.x.z, tfm.y.z, tfm.z.z);
+ light->co = transform_get_column(&tfm, 3);
+ light->dir = -transform_get_column(&tfm, 2);
/* shader */
vector<uint> used_shaders;
@@ -156,6 +156,7 @@ void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSI
/* shadow */
PointerRNA clamp = RNA_pointer_get(&b_lamp.ptr, "cycles");
light->cast_shadow = get_boolean(clamp, "cast_shadow");
+ light->use_mis = get_boolean(clamp, "use_multiple_importance_sampling");
light->samples = get_int(clamp, "samples");
/* tag */
@@ -196,7 +197,7 @@ 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, int motion)
+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, int motion, bool hide_tris)
{
BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent);
@@ -247,7 +248,7 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
bool use_holdout = (layer_flag & render_layer.holdout_layer) != 0;
/* mesh sync */
- object->mesh = sync_mesh(b_ob, object_updated);
+ object->mesh = sync_mesh(b_ob, object_updated, hide_tris);
/* sspecial case not tracked by object update flags */
if(use_holdout != object->use_holdout) {
@@ -310,13 +311,48 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
return object;
}
-static bool object_dupli_hide_original(BL::Object::dupli_type_enum dupli_type)
+static bool object_render_hide_original(BL::Object::dupli_type_enum dupli_type)
{
return (dupli_type == BL::Object::dupli_type_VERTS ||
dupli_type == BL::Object::dupli_type_FACES ||
dupli_type == BL::Object::dupli_type_FRAMES);
}
+static bool object_render_hide(BL::Object b_ob, bool top_level, bool parent_hide, bool& hide_triangles)
+{
+ /* check if we should render or hide particle emitter */
+ BL::Object::particle_systems_iterator b_psys;
+
+ bool hair_present = false;
+ bool show_emitter = false;
+ bool hide = false;
+
+ for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) {
+ if((b_psys->settings().render_type() == BL::ParticleSettings::render_type_PATH) &&
+ (b_psys->settings().type()==BL::ParticleSettings::type_HAIR))
+ hair_present = true;
+
+ if(b_psys->settings().use_render_emitter()) {
+ hide = false;
+ show_emitter = true;
+ }
+ }
+
+ /* duplicators hidden by default, except dupliframes which duplicate self */
+ if(b_ob.is_duplicator())
+ if(top_level || b_ob.dupli_type() != BL::Object::dupli_type_FRAMES)
+ hide = true;
+
+ /* hide original object for duplis */
+ BL::Object parent = b_ob.parent();
+ if(parent && object_render_hide_original(parent.dupli_type()))
+ if(parent_hide)
+ hide = true;
+
+ hide_triangles = (hair_present && !show_emitter);
+ return hide && !show_emitter;
+}
+
/* Object Loop */
void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
@@ -352,9 +388,6 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
progress.set_sync_status("Synchronizing object", (*b_ob).name());
if(b_ob->is_duplicator()) {
- /* duplicators hidden by default */
- hide = true;
-
/* dupli objects */
b_ob->dupli_list_create(b_scene, 2);
@@ -364,33 +397,16 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
Transform tfm = get_transform(b_dup->matrix());
BL::Object b_dup_ob = b_dup->object();
bool dup_hide = (b_v3d)? b_dup_ob.hide(): b_dup_ob.hide_render();
- bool emitter_hide = false;
-
- if(b_dup_ob.is_duplicator()) {
- /* duplicators hidden by default, except dupliframes which duplicate self */
- if(b_dup_ob.dupli_type() != BL::Object::dupli_type_FRAMES)
- emitter_hide = true;
-
- /* check if we should render or hide particle emitter */
- BL::Object::particle_systems_iterator b_psys;
- for(b_dup_ob.particle_systems.begin(b_psys); b_psys != b_dup_ob.particle_systems.end(); ++b_psys)
- if(b_psys->settings().use_render_emitter())
- emitter_hide = false;
- }
-
- /* hide original object for duplis */
- BL::Object parent = b_dup_ob.parent();
- if(parent && object_dupli_hide_original(parent.dupli_type()))
- if(b_dup->type() == BL::DupliObject::type_GROUP)
- dup_hide = true;
+ bool in_dupli_group = (b_dup->type() == BL::DupliObject::type_GROUP);
+ bool hide_tris;
- if(!(b_dup->hide() || dup_hide || emitter_hide)) {
+ if(!(b_dup->hide() || dup_hide || object_render_hide(b_dup_ob, false, in_dupli_group, hide_tris))) {
/* the persistent_id allows us to match dupli objects
* between frames and updates */
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);
+ Object *object = sync_object(*b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion, hide_tris);
/* sync possible particle data, note particle_id
* starts counting at 1, first is dummy particle */
@@ -409,22 +425,13 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
b_ob->dupli_list_clear();
}
- /* check if we should render or hide particle emitter */
- BL::Object::particle_systems_iterator b_psys;
-
- for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys)
- if(b_psys->settings().use_render_emitter())
- hide = false;
-
- /* hide original object for duplis */
- BL::Object parent = b_ob->parent();
- if(parent && object_dupli_hide_original(parent.dupli_type()))
- hide = true;
+ /* test if object needs to be hidden */
+ bool hide_tris;
- if(!hide) {
+ 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);
+ sync_object(*b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion, hide_tris);
}
}
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index d164920ceff..f7a05463f66 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -52,8 +52,9 @@ static PyObject *init_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, "OOOOOOO", &pyengine, &pyuserpref, &pydata, &pyscene, &pyregion, &pyv3d, &pyrv3d))
+ if(!PyArg_ParseTuple(args, "OOOOOOOi", &pyengine, &pyuserpref, &pydata, &pyscene, &pyregion, &pyv3d, &pyrv3d, &preview_osl))
return NULL;
/* RNA */
@@ -91,14 +92,22 @@ static PyObject *create_func(PyObject *self, PyObject *args)
Py_BEGIN_ALLOW_THREADS
if(rv3d) {
- /* interactive session */
+ /* interactive viewport session */
int width = region.width();
int height = region.height();
session = new BlenderSession(engine, userpref, data, scene, v3d, rv3d, width, height);
}
else {
- /* offline session */
+ /* override some settings for preview */
+ if(engine.is_preview()) {
+ PointerRNA cscene = RNA_pointer_get(&sceneptr, "cycles");
+
+ RNA_boolean_set(&cscene, "shading_system", preview_osl);
+ RNA_boolean_set(&cscene, "use_progressive_refine", true);
+ }
+
+ /* offline session or preview render */
session = new BlenderSession(engine, userpref, data, scene);
}
@@ -198,6 +207,7 @@ static PyObject *available_devices_func(PyObject *self, PyObject *args)
}
#ifdef WITH_OSL
+
static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
{
PyObject *pynodegroup, *pynode;
@@ -239,17 +249,19 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
continue;
/* determine socket type */
- BL::NodeSocket::type_enum socket_type;
- float default_float4[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ std::string socket_type;
+ BL::NodeSocket::type_enum data_type = BL::NodeSocket::type_VALUE;
+ float4 default_float4 = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
float default_float = 0.0f;
int default_int = 0;
std::string default_string = "";
if(param->isclosure) {
- socket_type = BL::NodeSocket::type_SHADER;
+ socket_type = "NodeSocketShader";
}
else if(param->type.vecsemantics == TypeDesc::COLOR) {
- socket_type = BL::NodeSocket::type_RGBA;
+ socket_type = "NodeSocketColor";
+ data_type = BL::NodeSocket::type_RGBA;
if(param->validdefault) {
default_float4[0] = param->fdefault[0];
@@ -260,7 +272,8 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
else if(param->type.vecsemantics == TypeDesc::POINT ||
param->type.vecsemantics == TypeDesc::VECTOR ||
param->type.vecsemantics == TypeDesc::NORMAL) {
- socket_type = BL::NodeSocket::type_VECTOR;
+ socket_type = "NodeSocketVector";
+ data_type = BL::NodeSocket::type_VECTOR;
if(param->validdefault) {
default_float4[0] = param->fdefault[0];
@@ -270,17 +283,20 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
}
else if(param->type.aggregate == TypeDesc::SCALAR) {
if(param->type.basetype == TypeDesc::INT) {
- socket_type = BL::NodeSocket::type_INT;
+ socket_type = "NodeSocketInt";
+ data_type = BL::NodeSocket::type_INT;
if(param->validdefault)
default_int = param->idefault[0];
}
else if(param->type.basetype == TypeDesc::FLOAT) {
- socket_type = BL::NodeSocket::type_VALUE;
+ socket_type = "NodeSocketFloat";
+ data_type = BL::NodeSocket::type_VALUE;
if(param->validdefault)
default_float = param->fdefault[0];
}
else if(param->type.basetype == TypeDesc::STRING) {
- socket_type = BL::NodeSocket::type_STRING;
+ socket_type = "NodeSocketString";
+ data_type = BL::NodeSocket::type_STRING;
if(param->validdefault)
default_string = param->sdefault[0];
}
@@ -291,38 +307,52 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
continue;
/* find socket socket */
- BL::NodeSocket b_sock = b_node.find_socket(param->name.c_str(), param->isoutput);
-
- /* remove if type no longer matches */
- if(b_sock && b_sock.type() != socket_type) {
- b_node.remove_socket(b_sock);
- b_sock = BL::NodeSocket(PointerRNA_NULL);
+ BL::NodeSocket b_sock(PointerRNA_NULL);
+ if (param->isoutput) {
+ b_sock = b_node.outputs[param->name];
+
+ /* remove if type no longer matches */
+ if(b_sock && b_sock.bl_idname() != socket_type) {
+ b_node.outputs.remove(b_sock);
+ b_sock = BL::NodeSocket(PointerRNA_NULL);
+ }
+
+ if (!b_sock) {
+ /* create new socket */
+ b_sock = b_node.outputs.create(socket_type.c_str(), param->name.c_str(), param->name.c_str());
+ }
+ }
+ else {
+ b_sock = b_node.inputs[param->name];
+
+ /* remove if type no longer matches */
+ if(b_sock && b_sock.bl_idname() != socket_type) {
+ b_node.inputs.remove(b_sock);
+ b_sock = BL::NodeSocket(PointerRNA_NULL);
+ }
+
+ if (!b_sock) {
+ /* create new socket */
+ b_sock = b_node.inputs.create(socket_type.c_str(), param->name.c_str(), param->name.c_str());
+ }
}
- /* create new socket */
- if(!b_sock) {
- b_sock = b_node.add_socket(param->name.c_str(), socket_type, param->isoutput);
-
- /* set default value */
- if(socket_type == BL::NodeSocket::type_VALUE) {
- BL::NodeSocketFloatNone b_float_sock(b_sock.ptr);
- b_float_sock.default_value(default_float);
+ /* set default value */
+ if(b_sock) {
+ if(data_type == BL::NodeSocket::type_VALUE) {
+ set_float(b_sock.ptr, "default_value", default_float);
}
- else if(socket_type == BL::NodeSocket::type_INT) {
- BL::NodeSocketIntNone b_int_sock(b_sock.ptr);
- b_int_sock.default_value(default_int);
+ else if(data_type == BL::NodeSocket::type_INT) {
+ set_int(b_sock.ptr, "default_value", default_int);
}
- else if(socket_type == BL::NodeSocket::type_RGBA) {
- BL::NodeSocketRGBA b_rgba_sock(b_sock.ptr);
- b_rgba_sock.default_value(default_float4);
+ else if(data_type == BL::NodeSocket::type_RGBA) {
+ set_float4(b_sock.ptr, "default_value", default_float4);
}
- else if(socket_type == BL::NodeSocket::type_VECTOR) {
- BL::NodeSocketVectorNone b_vector_sock(b_sock.ptr);
- b_vector_sock.default_value(default_float4);
+ else if(data_type == BL::NodeSocket::type_VECTOR) {
+ set_float3(b_sock.ptr, "default_value", float4_to_float3(default_float4));
}
- else if(socket_type == BL::NodeSocket::type_STRING) {
- BL::NodeSocketStringNone b_string_sock(b_sock.ptr);
- b_string_sock.default_value(default_string);
+ else if(data_type == BL::NodeSocket::type_STRING) {
+ set_string(b_sock.ptr, "default_value", default_string);
}
}
@@ -340,7 +370,7 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
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.remove_socket(*b_input);
+ b_node.inputs.remove(*b_input);
removed = true;
break;
}
@@ -348,7 +378,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) {
if(used_sockets.find(b_output->ptr.data) == used_sockets.end()) {
- b_node.remove_socket(*b_output);
+ b_node.outputs.remove(*b_output);
removed = true;
break;
}
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index b8ed942f5b6..8eec383850e 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -41,13 +41,13 @@ CCL_NAMESPACE_BEGIN
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_scene(b_scene_),
+: b_engine(b_engine_), b_userpref(b_userpref_), b_data(b_data_), b_render(b_engine_.render()), b_scene(b_scene_),
b_v3d(PointerRNA_NULL), b_rv3d(PointerRNA_NULL)
{
/* offline render */
- width = b_engine.resolution_x();
- height = b_engine.resolution_y();
+ width = (int)(b_render.resolution_x()*b_render.resolution_percentage()/100);
+ height = (int)(b_render.resolution_y()*b_render.resolution_percentage()/100);
background = true;
last_redraw_time = 0.0f;
@@ -58,10 +58,11 @@ BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::UserPreferences b
BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::UserPreferences b_userpref_,
BL::BlendData b_data_, BL::Scene b_scene_,
BL::SpaceView3D b_v3d_, BL::RegionView3D b_rv3d_, int width_, int height_)
-: b_engine(b_engine_), b_userpref(b_userpref_), b_data(b_data_), b_scene(b_scene_),
+: b_engine(b_engine_), b_userpref(b_userpref_), b_data(b_data_), b_render(b_scene_.render()), b_scene(b_scene_),
b_v3d(b_v3d_), b_rv3d(b_rv3d_)
{
/* 3d view render */
+
width = width_;
height = height_;
background = false;
@@ -96,32 +97,41 @@ void BlenderSession::create_session()
session->set_pause(BlenderSync::get_session_pause(b_scene, background));
/* create sync */
- sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
+ sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress, session_params.device.type == DEVICE_CPU);
sync->sync_data(b_v3d, b_engine.camera_override());
if(b_rv3d)
sync->sync_view(b_v3d, b_rv3d, width, height);
else
- sync->sync_camera(b_engine.camera_override(), width, height);
+ sync->sync_camera(b_render, b_engine.camera_override(), width, height);
/* set buffer parameters */
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_v3d, b_rv3d, scene->camera, width, height);
+ BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, 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);
+
+ /* setup callbacks for builtin image support */
+ scene->image_manager->builtin_image_info_cb = function_bind(&BlenderSession::builtin_image_info, this, _1, _2, _3, _4, _5, _6);
+ scene->image_manager->builtin_image_pixels_cb = function_bind(&BlenderSession::builtin_image_pixels, this, _1, _2, _3);
+ scene->image_manager->builtin_image_float_pixels_cb = function_bind(&BlenderSession::builtin_image_float_pixels, this, _1, _2, _3);
}
void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_)
{
b_data = b_data_;
+ 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);
- width = b_engine.resolution_x();
- height = b_engine.resolution_y();
+ width = b_render.resolution_x();
+ height = b_render.resolution_y();
if(scene->params.modified(scene_params) ||
- session->params.modified(session_params))
+ session->params.modified(session_params) ||
+ !scene_params.persistent_data)
{
/* if scene or session parameters changed, it's easier to simply re-create
* them rather than trying to distinguish which settings need to be updated
@@ -137,18 +147,22 @@ void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_)
session->progress.reset();
scene->reset();
+ session->tile_manager.set_tile_order(session_params.tile_order);
+
/* peak memory usage should show current render peak, not peak for all renders
* made by this render session
*/
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);
+ sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress, session_params.device.type == DEVICE_CPU);
sync->sync_data(b_v3d, b_engine.camera_override());
- sync->sync_camera(b_engine.camera_override(), width, height);
+ sync->sync_camera(b_render, b_engine.camera_override(), width, height);
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, PointerRNA_NULL, PointerRNA_NULL, scene->camera, width, height);
+ BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, 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);
}
void BlenderSession::free_session()
@@ -252,7 +266,15 @@ void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_upda
if (do_update_only) {
/* update only needed */
- update_render_result(b_rr, b_rlay, rtile);
+
+ 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
+ */
+ update_render_result(b_rr, b_rlay, rtile);
+ }
+
end_render_result(b_engine, b_rr, true);
}
else {
@@ -269,7 +291,14 @@ void BlenderSession::write_render_tile(RenderTile& rtile)
void BlenderSession::update_render_tile(RenderTile& rtile)
{
- do_write_update_render_tile(rtile, true);
+ /* use final write for preview renders, otherwise render result wouldn't be
+ * be updated in blender side
+ * would need to be investigated a bit further, but for now shall be fine
+ */
+ if (!b_engine.is_preview())
+ do_write_update_render_tile(rtile, true);
+ else
+ do_write_update_render_tile(rtile, false);
}
void BlenderSession::render()
@@ -280,7 +309,7 @@ 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_scene, b_v3d, b_rv3d, scene->camera, width, height);
+ BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height);
/* render each layer */
BL::RenderSettings r = b_scene.render();
@@ -384,8 +413,10 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::Re
int components = b_pass.channels();
/* copy pixels */
- if(buffers->get_pass_rect(pass_type, exposure, rtile.sample, components, &pixels[0]))
- b_pass.rect(&pixels[0]);
+ if(!buffers->get_pass_rect(pass_type, exposure, rtile.sample, components, &pixels[0]))
+ memset(&pixels[0], 0, pixels.size()*sizeof(float));
+
+ b_pass.rect(&pixels[0]);
}
}
@@ -442,14 +473,14 @@ void BlenderSession::synchronize()
if(b_rv3d)
sync->sync_view(b_v3d, b_rv3d, width, height);
else
- sync->sync_camera(b_engine.camera_override(), width, height);
+ sync->sync_camera(b_render, b_engine.camera_override(), width, height);
/* unlock */
session->scene->mutex.unlock();
/* reset if needed */
if(scene->need_reset()) {
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_v3d, b_rv3d, scene->camera, width, height);
+ BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height);
session->reset(buffer_params, session_params.samples);
}
}
@@ -467,11 +498,10 @@ bool BlenderSession::draw(int w, int h)
}
else {
/* update camera from 3d view */
- bool need_update = scene->camera->need_update;
sync->sync_view(b_v3d, b_rv3d, w, h);
- if(scene->camera->need_update && !need_update)
+ if(scene->camera->need_update)
reset = true;
session->scene->mutex.unlock();
@@ -487,17 +517,20 @@ 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_scene, b_v3d, b_rv3d, scene->camera, w, h);
+ BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, w, h);
session->reset(buffer_params, session_params.samples);
}
}
+ else {
+ tag_update();
+ }
/* update status and progress for 3d view draw */
update_status_progress();
/* draw */
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_v3d, b_rv3d, scene->camera, width, height);
+ BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height);
return !session->draw(buffer_params);
}
@@ -593,5 +626,120 @@ void BlenderSession::test_cancel()
session->progress.set_cancel("Cancelled");
}
+/* builtin image file name is actually an image datablock name with
+ * absolute sequence frame number concatenated via '@' character
+ *
+ * this function splits frame from builtin name
+ */
+int BlenderSession::builtin_image_frame(const string &builtin_name)
+{
+ int last = builtin_name.find_last_of('@');
+ return atoi(builtin_name.substr(last + 1, builtin_name.size() - last - 1).c_str());
+}
+
+void BlenderSession::builtin_image_info(const string &builtin_name, void *builtin_data, bool &is_float, int &width, int &height, int &channels)
+{
+ PointerRNA ptr;
+ RNA_id_pointer_create((ID*)builtin_data, &ptr);
+ BL::Image b_image(ptr);
+
+ if(b_image) {
+ is_float = b_image.is_float();
+ width = b_image.size()[0];
+ height = b_image.size()[1];
+ channels = b_image.channels();
+ }
+ else {
+ is_float = false;
+ width = 0;
+ height = 0;
+ channels = 0;
+ }
+}
+
+bool BlenderSession::builtin_image_pixels(const string &builtin_name, void *builtin_data, unsigned char *pixels)
+{
+ int frame = builtin_image_frame(builtin_name);
+
+ PointerRNA ptr;
+ RNA_id_pointer_create((ID*)builtin_data, &ptr);
+ BL::Image b_image(ptr);
+
+ if(b_image) {
+ int width = b_image.size()[0];
+ int height = b_image.size()[1];
+ int channels = b_image.channels();
+
+ unsigned char *image_pixels;
+ image_pixels = image_get_pixels_for_frame(b_image, frame);
+
+ if(image_pixels) {
+ memcpy(pixels, image_pixels, width * height * channels * sizeof(unsigned char));
+ MEM_freeN(image_pixels);
+ }
+ else {
+ if(channels == 1) {
+ memset(pixels, 0, width * height * sizeof(unsigned char));
+ }
+ else {
+ unsigned char *cp = pixels;
+ for(int i = 0; i < width * height; i++, cp += channels) {
+ cp[0] = 255;
+ cp[1] = 0;
+ cp[2] = 255;
+ if(channels == 4)
+ cp[3] = 255;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void *builtin_data, float *pixels)
+{
+ int frame = builtin_image_frame(builtin_name);
+
+ PointerRNA ptr;
+ RNA_id_pointer_create((ID*)builtin_data, &ptr);
+ BL::Image b_image(ptr);
+
+ if(b_image) {
+ int width = b_image.size()[0];
+ int height = b_image.size()[1];
+ int channels = b_image.channels();
+
+ float *image_pixels;
+ image_pixels = image_get_float_pixels_for_frame(b_image, frame);
+
+ if(image_pixels) {
+ memcpy(pixels, image_pixels, width * height * channels * sizeof(float));
+ MEM_freeN(image_pixels);
+ }
+ else {
+ if(channels == 1) {
+ memset(pixels, 0, width * height * sizeof(float));
+ }
+ else {
+ float *fp = pixels;
+ for(int i = 0; i < width * height; i++, fp += channels) {
+ fp[0] = 1.0f;
+ fp[1] = 0.0f;
+ fp[2] = 1.0f;
+ if(channels == 4)
+ fp[3] = 1.0f;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h
index 7f3973ae873..a25030df4f4 100644
--- a/intern/cycles/blender/blender_session.h
+++ b/intern/cycles/blender/blender_session.h
@@ -80,6 +80,7 @@ public:
BL::RenderEngine b_engine;
BL::UserPreferences b_userpref;
BL::BlendData b_data;
+ BL::RenderSettings b_render;
BL::Scene b_scene;
BL::SpaceView3D b_v3d;
BL::RegionView3D b_rv3d;
@@ -93,6 +94,11 @@ public:
protected:
void do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile, bool do_update_only);
void do_write_update_render_tile(RenderTile& rtile, bool do_update_only);
+
+ int builtin_image_frame(const string &builtin_name);
+ void builtin_image_info(const string &builtin_name, void *builtin_data, bool &is_float, int &width, int &height, int &channels);
+ bool builtin_image_pixels(const string &builtin_name, void *builtin_data, unsigned char *pixels);
+ bool builtin_image_float_pixels(const string &builtin_name, void *builtin_data, float *pixels);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 848a9a199f9..b451764c347 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -31,9 +31,9 @@
CCL_NAMESPACE_BEGIN
-typedef map<void*, ShaderNode*> PtrNodeMap;
-typedef pair<ShaderNode*, std::string> SocketPair;
-typedef map<void*, SocketPair> PtrSockMap;
+typedef map<void*, ShaderInput*> PtrInputMap;
+typedef map<void*, ShaderOutput*> PtrOutputMap;
+typedef map<std::string, ProxyNode*> ProxyMap;
/* Find */
@@ -55,83 +55,88 @@ void BlenderSync::find_shader(BL::ID id, vector<uint>& used_shaders, int default
static BL::NodeSocket get_node_output(BL::Node b_node, const string& name)
{
BL::Node::outputs_iterator b_out;
-
+
for(b_node.outputs.begin(b_out); b_out != b_node.outputs.end(); ++b_out)
if(b_out->name() == name)
return *b_out;
-
+
assert(0);
-
+
return *b_out;
}
static float3 get_node_output_rgba(BL::Node b_node, const string& name)
{
- BL::NodeSocketRGBA sock(get_node_output(b_node, name));
- return get_float3(sock.default_value());
+ BL::NodeSocket b_sock = get_node_output(b_node, name);
+ float value[4];
+ RNA_float_get_array(&b_sock.ptr, "default_value", value);
+ return make_float3(value[0], value[1], value[2]);
}
static float get_node_output_value(BL::Node b_node, const string& name)
{
- BL::NodeSocketFloatNone sock(get_node_output(b_node, name));
- return sock.default_value();
+ BL::NodeSocket b_sock = get_node_output(b_node, name);
+ return RNA_float_get(&b_sock.ptr, "default_value");
}
-static ShaderSocketType convert_socket_type(BL::NodeSocket::type_enum b_type)
+static float3 get_node_output_vector(BL::Node b_node, const string& name)
{
- switch (b_type) {
- case BL::NodeSocket::type_VALUE:
- return SHADER_SOCKET_FLOAT;
- case BL::NodeSocket::type_INT:
- return SHADER_SOCKET_INT;
- case BL::NodeSocket::type_VECTOR:
- return SHADER_SOCKET_VECTOR;
- case BL::NodeSocket::type_RGBA:
- return SHADER_SOCKET_COLOR;
- case BL::NodeSocket::type_SHADER:
- return SHADER_SOCKET_CLOSURE;
- case BL::NodeSocket::type_STRING:
- return SHADER_SOCKET_STRING;
-
- case BL::NodeSocket::type_BOOLEAN:
- case BL::NodeSocket::type_MESH:
- default:
- return SHADER_SOCKET_FLOAT;
+ BL::NodeSocket b_sock = get_node_output(b_node, name);
+ float value[3];
+ RNA_float_get_array(&b_sock.ptr, "default_value", value);
+ return make_float3(value[0], value[1], value[2]);
+}
+
+static ShaderSocketType convert_socket_type(BL::NodeSocket b_socket)
+{
+ switch (b_socket.type()) {
+ case BL::NodeSocket::type_VALUE:
+ return SHADER_SOCKET_FLOAT;
+ case BL::NodeSocket::type_INT:
+ return SHADER_SOCKET_INT;
+ case BL::NodeSocket::type_VECTOR:
+ return SHADER_SOCKET_VECTOR;
+ case BL::NodeSocket::type_RGBA:
+ return SHADER_SOCKET_COLOR;
+ case BL::NodeSocket::type_STRING:
+ return SHADER_SOCKET_STRING;
+ case BL::NodeSocket::type_SHADER:
+ return SHADER_SOCKET_CLOSURE;
+
+ default:
+ return SHADER_SOCKET_UNDEFINED;
}
}
-static void set_default_value(ShaderInput *input, BL::NodeSocket sock, BL::BlendData b_data, BL::ID b_id)
+static void set_default_value(ShaderInput *input, BL::Node b_node, BL::NodeSocket b_sock, BL::BlendData b_data, BL::ID b_id)
{
/* copy values for non linked inputs */
switch(input->type) {
case SHADER_SOCKET_FLOAT: {
- BL::NodeSocketFloatNone value_sock(sock);
- input->set(value_sock.default_value());
+ input->set(get_float(b_sock.ptr, "default_value"));
break;
}
case SHADER_SOCKET_INT: {
- BL::NodeSocketIntNone value_sock(sock);
- input->set((float)value_sock.default_value());
+ input->set((float)get_int(b_sock.ptr, "default_value"));
break;
}
case SHADER_SOCKET_COLOR: {
- BL::NodeSocketRGBA rgba_sock(sock);
- input->set(get_float3(rgba_sock.default_value()));
+ input->set(float4_to_float3(get_float4(b_sock.ptr, "default_value")));
break;
}
case SHADER_SOCKET_NORMAL:
case SHADER_SOCKET_POINT:
case SHADER_SOCKET_VECTOR: {
- BL::NodeSocketVectorNone vec_sock(sock);
- input->set(get_float3(vec_sock.default_value()));
+ input->set(get_float3(b_sock.ptr, "default_value"));
break;
}
case SHADER_SOCKET_STRING: {
- BL::NodeSocketStringNone string_sock(sock);
- input->set((ustring)blender_absolute_path(b_data, b_id, string_sock.default_value()));
+ input->set((ustring)blender_absolute_path(b_data, b_id, get_string(b_sock.ptr, "default_value")));
break;
}
+
case SHADER_SOCKET_CLOSURE:
+ case SHADER_SOCKET_UNDEFINED:
break;
}
}
@@ -171,291 +176,226 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
{
ShaderNode *node = NULL;
- switch(b_node.type()) {
- /* not supported */
- case BL::ShaderNode::type_GEOMETRY: break;
- case BL::ShaderNode::type_MATERIAL: break;
- case BL::ShaderNode::type_MATERIAL_EXT: break;
- case BL::ShaderNode::type_OUTPUT: break;
- case BL::ShaderNode::type_SQUEEZE: break;
- case BL::ShaderNode::type_TEXTURE: break;
- case BL::ShaderNode::type_FRAME: break;
- /* handled outside this function */
- case BL::ShaderNode::type_GROUP: break;
- /* existing blender nodes */
- case BL::ShaderNode::type_REROUTE: {
- BL::Node::inputs_iterator b_input;
- b_node.inputs.begin(b_input);
- BL::Node::outputs_iterator b_output;
- b_node.outputs.begin(b_output);
- ProxyNode *proxy = new ProxyNode(convert_socket_type(b_input->type()), convert_socket_type(b_output->type()));
- node = proxy;
- break;
- }
- case BL::ShaderNode::type_CURVE_VEC: {
- 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;
- break;
- }
- case BL::ShaderNode::type_CURVE_RGB: {
- 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;
- break;
- }
- case BL::ShaderNode::type_VALTORGB: {
- RGBRampNode *ramp = new RGBRampNode();
- BL::ShaderNodeValToRGB b_ramp_node(b_node);
- colorramp_to_array(b_ramp_node.color_ramp(), ramp->ramp, RAMP_TABLE_SIZE);
- node = ramp;
- break;
- }
- case BL::ShaderNode::type_RGB: {
- ColorNode *color = new ColorNode();
- color->value = get_node_output_rgba(b_node, "Color");
- node = color;
- break;
- }
- case BL::ShaderNode::type_VALUE: {
- ValueNode *value = new ValueNode();
- value->value = get_node_output_value(b_node, "Value");
- node = value;
- break;
- }
- case BL::ShaderNode::type_CAMERA: {
- node = new CameraNode();
- break;
- }
- case BL::ShaderNode::type_INVERT: {
- node = new InvertNode();
- break;
- }
- case BL::ShaderNode::type_GAMMA: {
- node = new GammaNode();
- break;
- }
- case BL::ShaderNode::type_BRIGHTCONTRAST: {
- node = new BrightContrastNode();
- break;
- }
- case BL::ShaderNode::type_MIX_RGB: {
- BL::ShaderNodeMixRGB b_mix_node(b_node);
- MixNode *mix = new MixNode();
- mix->type = MixNode::type_enum[b_mix_node.blend_type()];
+ /* existing blender nodes */
+ 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)) {
+ 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)) {
+ RGBRampNode *ramp = new RGBRampNode();
+ BL::ShaderNodeValToRGB b_ramp_node(b_node);
+ colorramp_to_array(b_ramp_node.color_ramp(), ramp->ramp, RAMP_TABLE_SIZE);
+ node = ramp;
+ }
+ 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)) {
+ ValueNode *value = new ValueNode();
+ value->value = get_node_output_value(b_node, "Value");
+ node = value;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeCameraData)) {
+ node = new CameraNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeInvert)) {
+ node = new InvertNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeGamma)) {
+ node = new GammaNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBrightContrast)) {
+ node = new BrightContrastNode();
+ }
+ 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()];
mix->use_clamp = b_mix_node.use_clamp();
- node = mix;
- break;
- }
- case BL::ShaderNode::type_SEPRGB: {
- node = new SeparateRGBNode();
- break;
- }
- case BL::ShaderNode::type_COMBRGB: {
- node = new CombineRGBNode();
- break;
- }
- case BL::ShaderNode::type_HUE_SAT: {
- node = new HSVNode();
- break;
- }
- case BL::ShaderNode::type_RGBTOBW: {
- node = new ConvertNode(SHADER_SOCKET_COLOR, SHADER_SOCKET_FLOAT);
- break;
- }
- case BL::ShaderNode::type_MATH: {
- BL::ShaderNodeMath b_math_node(b_node);
- MathNode *math = new MathNode();
- math->type = MathNode::type_enum[b_math_node.operation()];
+ node = mix;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeSeparateRGB)) {
+ node = new SeparateRGBNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeCombineRGB)) {
+ node = new CombineRGBNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeHueSaturation)) {
+ node = new HSVNode();
+ }
+ 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)) {
+ 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;
- break;
- }
- case BL::ShaderNode::type_VECT_MATH: {
- BL::ShaderNodeVectorMath b_vector_math_node(b_node);
- VectorMathNode *vmath = new VectorMathNode();
- vmath->type = VectorMathNode::type_enum[b_vector_math_node.operation()];
- node = vmath;
- break;
- }
- case BL::ShaderNode::type_NORMAL: {
- BL::Node::outputs_iterator out_it;
- b_node.outputs.begin(out_it);
- BL::NodeSocketVectorNone vec_sock(*out_it);
-
- NormalNode *norm = new NormalNode();
- norm->direction = get_float3(vec_sock.default_value());
-
- node = norm;
- break;
- }
- case BL::ShaderNode::type_MAPPING: {
- BL::ShaderNodeMapping b_mapping_node(b_node);
- MappingNode *mapping = new MappingNode();
-
- get_tex_mapping(&mapping->tex_mapping, b_mapping_node);
-
- node = mapping;
- break;
- }
-
- /* new nodes */
- case BL::ShaderNode::type_OUTPUT_MATERIAL:
- case BL::ShaderNode::type_OUTPUT_WORLD:
- case BL::ShaderNode::type_OUTPUT_LAMP: {
- node = graph->output();
- break;
- }
- case BL::ShaderNode::type_FRESNEL: {
- node = new FresnelNode();
- break;
- }
- case BL::ShaderNode::type_LAYER_WEIGHT: {
- node = new LayerWeightNode();
- break;
- }
- case BL::ShaderNode::type_ADD_SHADER: {
- node = new AddClosureNode();
- break;
- }
- case BL::ShaderNode::type_MIX_SHADER: {
- node = new MixClosureNode();
- break;
- }
- case BL::ShaderNode::type_ATTRIBUTE: {
- BL::ShaderNodeAttribute b_attr_node(b_node);
- AttributeNode *attr = new AttributeNode();
- attr->attribute = b_attr_node.attribute_name();
- node = attr;
- break;
- }
- case BL::ShaderNode::type_BACKGROUND: {
- node = new BackgroundNode();
- break;
- }
- case BL::ShaderNode::type_HOLDOUT: {
- node = new HoldoutNode();
- break;
- }
- case BL::ShaderNode::type_BSDF_ANISOTROPIC: {
- node = new WardBsdfNode();
- break;
- }
- case BL::ShaderNode::type_BSDF_DIFFUSE: {
- node = new DiffuseBsdfNode();
- break;
- }
- case BL::ShaderNode::type_BSDF_GLOSSY: {
- BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
- GlossyBsdfNode *glossy = new GlossyBsdfNode();
-
- switch(b_glossy_node.distribution()) {
- case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
- glossy->distribution = ustring("Sharp");
- break;
- case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN:
- glossy->distribution = ustring("Beckmann");
- break;
- case BL::ShaderNodeBsdfGlossy::distribution_GGX:
- glossy->distribution = ustring("GGX");
- break;
- }
- node = glossy;
- break;
- }
- case BL::ShaderNode::type_BSDF_GLASS: {
- BL::ShaderNodeBsdfGlass b_glass_node(b_node);
- GlassBsdfNode *glass = new GlassBsdfNode();
- switch(b_glass_node.distribution()) {
- case BL::ShaderNodeBsdfGlass::distribution_SHARP:
- glass->distribution = ustring("Sharp");
- break;
- case BL::ShaderNodeBsdfGlass::distribution_BECKMANN:
- glass->distribution = ustring("Beckmann");
- break;
- case BL::ShaderNodeBsdfGlass::distribution_GGX:
- glass->distribution = ustring("GGX");
- break;
- }
- node = glass;
- break;
- }
- case BL::ShaderNode::type_BSDF_REFRACTION: {
- BL::ShaderNodeBsdfRefraction b_refraction_node(b_node);
- RefractionBsdfNode *refraction = new RefractionBsdfNode();
- switch(b_refraction_node.distribution()) {
- case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
- refraction->distribution = ustring("Sharp");
- break;
- case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN:
- refraction->distribution = ustring("Beckmann");
- break;
- case BL::ShaderNodeBsdfRefraction::distribution_GGX:
- refraction->distribution = ustring("GGX");
- break;
- }
- node = refraction;
- break;
- }
- case BL::ShaderNode::type_BSDF_TRANSLUCENT: {
- node = new TranslucentBsdfNode();
- break;
- }
- case BL::ShaderNode::type_BSDF_TRANSPARENT: {
- node = new TransparentBsdfNode();
- break;
- }
- case BL::ShaderNode::type_BSDF_VELVET: {
- node = new VelvetBsdfNode();
- break;
- }
- case BL::ShaderNode::type_EMISSION: {
- node = new EmissionNode();
- break;
- }
- case BL::ShaderNode::type_AMBIENT_OCCLUSION: {
- node = new AmbientOcclusionNode();
- break;
- }
- case BL::ShaderNode::type_VOLUME_ISOTROPIC: {
- node = new IsotropicVolumeNode();
- break;
- }
- case BL::ShaderNode::type_VOLUME_TRANSPARENT: {
- node = new TransparentVolumeNode();
+ node = math;
+ }
+ 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_ShaderNodeNormal)) {
+ BL::Node::outputs_iterator out_it;
+ b_node.outputs.begin(out_it);
+ BL::NodeSocket vec_sock(*out_it);
+
+ NormalNode *norm = new NormalNode();
+ norm->direction = get_node_output_vector(b_node, "Normal");
+ node = norm;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeMapping)) {
+ BL::ShaderNodeMapping b_mapping_node(b_node);
+ MappingNode *mapping = new MappingNode();
+
+ get_tex_mapping(&mapping->tex_mapping, b_mapping_node);
+
+ node = mapping;
+ }
+ /* new nodes */
+ else if (b_node.is_a(&RNA_ShaderNodeOutputMaterial)
+ || b_node.is_a(&RNA_ShaderNodeOutputWorld)
+ || b_node.is_a(&RNA_ShaderNodeOutputLamp)) {
+ node = graph->output();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeFresnel)) {
+ node = new FresnelNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeLayerWeight)) {
+ node = new LayerWeightNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeAddShader)) {
+ node = new AddClosureNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeMixShader)) {
+ node = new MixClosureNode();
+ }
+ 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)) {
+ node = new BackgroundNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeHoldout)) {
+ node = new HoldoutNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) {
+ node = new WardBsdfNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) {
+ node = new DiffuseBsdfNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) {
+ BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
+ GlossyBsdfNode *glossy = new GlossyBsdfNode();
+
+ switch(b_glossy_node.distribution()) {
+ case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
+ glossy->distribution = ustring("Sharp");
break;
- }
- case BL::ShaderNode::type_NEW_GEOMETRY: {
- node = new GeometryNode();
+ case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN:
+ glossy->distribution = ustring("Beckmann");
break;
- }
- case BL::ShaderNode::type_LIGHT_PATH: {
- node = new LightPathNode();
+ case BL::ShaderNodeBsdfGlossy::distribution_GGX:
+ glossy->distribution = ustring("GGX");
break;
}
- case BL::ShaderNode::type_LIGHT_FALLOFF: {
- node = new LightFalloffNode();
+ node = glossy;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfGlass)) {
+ BL::ShaderNodeBsdfGlass b_glass_node(b_node);
+ GlassBsdfNode *glass = new GlassBsdfNode();
+ switch(b_glass_node.distribution()) {
+ case BL::ShaderNodeBsdfGlass::distribution_SHARP:
+ glass->distribution = ustring("Sharp");
break;
- }
- case BL::ShaderNode::type_OBJECT_INFO: {
- node = new ObjectInfoNode();
+ case BL::ShaderNodeBsdfGlass::distribution_BECKMANN:
+ glass->distribution = ustring("Beckmann");
break;
- }
- case BL::ShaderNode::type_PARTICLE_INFO: {
- node = new ParticleInfoNode();
+ case BL::ShaderNodeBsdfGlass::distribution_GGX:
+ glass->distribution = ustring("GGX");
break;
}
- case BL::ShaderNode::type_BUMP: {
- node = new BumpNode();
- break;
+ node = glass;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfRefraction)) {
+ BL::ShaderNodeBsdfRefraction b_refraction_node(b_node);
+ RefractionBsdfNode *refraction = new RefractionBsdfNode();
+ switch(b_refraction_node.distribution()) {
+ case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
+ refraction->distribution = ustring("Sharp");
+ break;
+ case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN:
+ refraction->distribution = ustring("Beckmann");
+ break;
+ case BL::ShaderNodeBsdfRefraction::distribution_GGX:
+ refraction->distribution = ustring("GGX");
+ break;
}
- case BL::ShaderNode::type_SCRIPT: {
+ node = refraction;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) {
+ node = new TranslucentBsdfNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfTransparent)) {
+ node = new TransparentBsdfNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfVelvet)) {
+ node = new VelvetBsdfNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeEmission)) {
+ node = new EmissionNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) {
+ node = new AmbientOcclusionNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeVolumeIsotropic)) {
+ node = new IsotropicVolumeNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeVolumeTransparent)) {
+ node = new TransparentVolumeNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeNewGeometry)) {
+ node = new GeometryNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeLightPath)) {
+ node = new LightPathNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeLightFalloff)) {
+ node = new LightFalloffNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeObjectInfo)) {
+ node = new ObjectInfoNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeParticleInfo)) {
+ node = new ParticleInfoNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeHairInfo)) {
+ node = new HairInfoNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBump)) {
+ node = new BumpNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeScript)) {
#ifdef WITH_OSL
- if(!scene->shader_manager->use_osl())
- break;
-
+ if(scene->shader_manager->use_osl()) {
/* create script node */
BL::ShaderNodeScript b_script_node(b_node);
OSLScriptNode *script_node = new OSLScriptNode();
@@ -468,29 +408,31 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
* Note 2: ShaderInput/ShaderOutput store shallow string copies only!
* 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) {
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->type()));
- set_default_value(input, *b_input, b_data, b_ntree);
+ 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);
}
-
+
BL::Node::outputs_iterator 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->type()));
+ script_node->add_output(script_node->output_names.back().c_str(),
+ convert_socket_type(*b_output));
}
-
+
/* load bytecode or filepath */
OSLShaderManager *manager = (OSLShaderManager*)scene->shader_manager;
string bytecode_hash = b_script_node.bytecode_hash();
-
+
if(!bytecode_hash.empty()) {
/* loaded bytecode if not already done */
if(!manager->shader_test_loaded(bytecode_hash))
manager->shader_load_bytecode(bytecode_hash, b_script_node.bytecode());
-
+
script_node->bytecode_hash = bytecode_hash;
}
else {
@@ -499,138 +441,157 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
}
node = script_node;
-#endif
-
- break;
}
- case BL::ShaderNode::type_TEX_IMAGE: {
- BL::ShaderNodeTexImage b_image_node(b_node);
- BL::Image b_image(b_image_node.image());
- ImageTextureNode *image = new ImageTextureNode();
- /* todo: handle generated/builtin images */
- if(b_image && b_image.source() != BL::Image::source_MOVIE) {
+#endif
+ }
+ 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();
+ if(b_image) {
+ /* builtin images will use callback-based reading because
+ * they could only be loaded correct from blender side
+ */
+ bool is_builtin = b_image.packed_file() ||
+ b_image.source() == BL::Image::source_GENERATED ||
+ b_image.source() == BL::Image::source_MOVIE;
+
+ if(is_builtin) {
+ /* for builtin images we're using image datablock name to find an image to
+ * read pixels from later
+ *
+ * also store frame number as well, so there's no differences in handling
+ * builtin names for packed images and movies
+ */
+ int scene_frame = b_scene.frame_current();
+ int image_frame = image_user_frame_number(b_image_node.image_user(), scene_frame);
+ image->filename = b_image.name() + "@" + string_printf("%d", image_frame);
+ image->builtin_data = b_image.ptr.data;
+ }
+ else {
image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current());
- image->animated = b_image_node.image_user().use_auto_refresh();
+ image->builtin_data = NULL;
}
- image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
- image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()];
- image->projection_blend = b_image_node.projection_blend();
- get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping());
- node = image;
- break;
+
+ image->animated = b_image_node.image_user().use_auto_refresh();
}
- case BL::ShaderNode::type_TEX_ENVIRONMENT: {
- BL::ShaderNodeTexEnvironment b_env_node(b_node);
- BL::Image b_image(b_env_node.image());
- EnvironmentTextureNode *env = new EnvironmentTextureNode();
- if(b_image && b_image.source() != BL::Image::source_MOVIE) {
+ image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
+ image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()];
+ 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)) {
+ 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;
+
+ if(is_builtin) {
+ int scene_frame = b_scene.frame_current();
+ int image_frame = image_user_frame_number(b_env_node.image_user(), scene_frame);
+ env->filename = b_image.name() + "@" + string_printf("%d", image_frame);
+ env->builtin_data = b_image.ptr.data;
+ }
+ else {
env->filename = image_user_file_path(b_env_node.image_user(), b_image, b_scene.frame_current());
env->animated = b_env_node.image_user().use_auto_refresh();
+ env->builtin_data = NULL;
}
- env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()];
- env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()];
- get_tex_mapping(&env->tex_mapping, b_env_node.texture_mapping());
- node = env;
- break;
- }
- case BL::ShaderNode::type_TEX_GRADIENT: {
- 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;
- break;
- }
- case BL::ShaderNode::type_TEX_VORONOI: {
- 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;
- break;
- }
- case BL::ShaderNode::type_TEX_MAGIC: {
- 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;
- break;
- }
- case BL::ShaderNode::type_TEX_WAVE: {
- 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;
- break;
- }
- case BL::ShaderNode::type_TEX_CHECKER: {
- BL::ShaderNodeTexChecker b_checker_node(b_node);
- CheckerTextureNode *checker = new CheckerTextureNode();
- get_tex_mapping(&checker->tex_mapping, b_checker_node.texture_mapping());
- node = checker;
- break;
- }
- case BL::ShaderNode::type_TEX_BRICK: {
- BL::ShaderNodeTexBrick b_brick_node(b_node);
- BrickTextureNode *brick = new BrickTextureNode();
- brick->offset = b_brick_node.offset();
- brick->offset_frequency = b_brick_node.offset_frequency();
- brick->squash = b_brick_node.squash();
- brick->squash_frequency = b_brick_node.squash_frequency();
- get_tex_mapping(&brick->tex_mapping, b_brick_node.texture_mapping());
- node = brick;
- break;
- }
- case BL::ShaderNode::type_TEX_NOISE: {
- BL::ShaderNodeTexNoise b_noise_node(b_node);
- NoiseTextureNode *noise = new NoiseTextureNode();
- get_tex_mapping(&noise->tex_mapping, b_noise_node.texture_mapping());
- node = noise;
- break;
- }
- case BL::ShaderNode::type_TEX_MUSGRAVE: {
- 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;
- break;
- }
- case BL::ShaderNode::type_TEX_COORD: {
- BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
- TextureCoordinateNode *tex_coord = new TextureCoordinateNode();
- tex_coord->from_dupli = b_tex_coord_node.from_dupli();
- node = tex_coord;
- break;
- }
- case BL::ShaderNode::type_TEX_SKY: {
- BL::ShaderNodeTexSky b_sky_node(b_node);
- SkyTextureNode *sky = new SkyTextureNode();
- sky->sun_direction = get_float3(b_sky_node.sun_direction());
- sky->turbidity = b_sky_node.turbidity();
- get_tex_mapping(&sky->tex_mapping, b_sky_node.texture_mapping());
- node = sky;
- break;
- }
- case BL::ShaderNode::type_NORMAL_MAP: {
- 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;
- break;
- }
- case BL::ShaderNode::type_TANGENT: {
- BL::ShaderNodeTangent b_tangent_node(b_node);
- TangentNode *tangent = new TangentNode();
- tangent->direction_type = TangentNode::direction_type_enum[(int)b_tangent_node.direction_type()];
- tangent->axis = TangentNode::axis_enum[(int)b_tangent_node.axis()];
- tangent->attribute = b_tangent_node.uv_map();
- node = tangent;
- break;
}
+ env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()];
+ env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()];
+ get_tex_mapping(&env->tex_mapping, b_env_node.texture_mapping());
+ node = env;
+ }
+ 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)) {
+ 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)) {
+ 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)) {
+ 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)) {
+ 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)) {
+ BL::ShaderNodeTexBrick b_brick_node(b_node);
+ BrickTextureNode *brick = new BrickTextureNode();
+ brick->offset = b_brick_node.offset();
+ brick->offset_frequency = b_brick_node.offset_frequency();
+ brick->squash = b_brick_node.squash();
+ brick->squash_frequency = b_brick_node.squash_frequency();
+ get_tex_mapping(&brick->tex_mapping, b_brick_node.texture_mapping());
+ node = brick;
+ }
+ 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)) {
+ 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)) {
+ BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
+ TextureCoordinateNode *tex_coord = new TextureCoordinateNode();
+ tex_coord->from_dupli = b_tex_coord_node.from_dupli();
+ node = tex_coord;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexSky)) {
+ BL::ShaderNodeTexSky b_sky_node(b_node);
+ SkyTextureNode *sky = new SkyTextureNode();
+ sky->sun_direction = get_float3(b_sky_node.sun_direction());
+ sky->turbidity = b_sky_node.turbidity();
+ get_tex_mapping(&sky->tex_mapping, b_sky_node.texture_mapping());
+ node = sky;
+ }
+ 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)) {
+ BL::ShaderNodeTangent b_tangent_node(b_node);
+ TangentNode *tangent = new TangentNode();
+ tangent->direction_type = TangentNode::direction_type_enum[(int)b_tangent_node.direction_type()];
+ tangent->axis = TangentNode::axis_enum[(int)b_tangent_node.axis()];
+ tangent->attribute = b_tangent_node.uv_map();
+ node = tangent;
}
if(node && node != graph->output())
@@ -639,18 +600,16 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
return node;
}
-static SocketPair node_socket_map_pair(PtrNodeMap& node_map, BL::Node b_node, BL::NodeSocket b_socket)
+static ShaderInput *node_find_input_by_name(ShaderNode *node, BL::Node b_node, BL::NodeSocket b_socket)
{
BL::Node::inputs_iterator b_input;
- BL::Node::outputs_iterator b_output;
string name = b_socket.name();
bool found = false;
int counter = 0, total = 0;
-
- /* find in inputs */
- 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++;
}
@@ -658,128 +617,144 @@ static SocketPair node_socket_map_pair(PtrNodeMap& node_map, BL::Node b_node, BL
if(b_input->ptr.data == b_socket.ptr.data)
found = true;
}
+
+ /* rename if needed */
+ if (name == "Shader")
+ name = "Closure";
+
+ if (total > 1)
+ name = string_printf("%s%d", name.c_str(), counter);
+
+ return node->input(name.c_str());
+}
- if(!found) {
- /* find in outputs */
- found = false;
- 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)
- counter++;
- total++;
- }
-
- if(b_output->ptr.data == b_socket.ptr.data)
- found = true;
+static ShaderOutput *node_find_output_by_name(ShaderNode *node, BL::Node b_node, BL::NodeSocket b_socket)
+{
+ BL::Node::outputs_iterator b_output;
+ string name = b_socket.name();
+ 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)
+ counter++;
+ total++;
}
- }
+ if(b_output->ptr.data == b_socket.ptr.data)
+ found = true;
+ }
+
/* 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 SocketPair(node_map[b_node.ptr.data], name);
+
+ 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, PtrSockMap& sockets_map)
+static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, ProxyMap &proxy_map)
{
/* add nodes */
BL::ShaderNodeTree::nodes_iterator b_node;
- PtrNodeMap node_map;
- PtrSockMap proxy_map;
+ PtrInputMap input_map;
+ PtrOutputMap output_map;
+
+ BL::Node::inputs_iterator b_input;
+ BL::Node::outputs_iterator b_output;
for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
- if(b_node->mute()) {
- BL::Node::inputs_iterator b_input;
- BL::Node::outputs_iterator b_output;
- bool found_match = false;
-
- /* this is slightly different than blender logic, we just connect a
- * single pair for of input/output, but works ok for the node we have */
- for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
- if(b_input->is_linked()) {
- for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
- if(b_output->is_linked() && b_input->type() == b_output->type()) {
- ProxyNode *proxy = new ProxyNode(convert_socket_type(b_input->type()), convert_socket_type(b_output->type()));
- graph->add(proxy);
-
- proxy_map[b_input->ptr.data] = SocketPair(proxy, proxy->inputs[0]->name);
- proxy_map[b_output->ptr.data] = SocketPair(proxy, proxy->outputs[0]->name);
- found_match = true;
-
- break;
- }
- }
- }
-
- if(found_match)
- break;
+ 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) {
+ ProxyNode *proxy = new ProxyNode(convert_socket_type(b_link->to_socket()));
+
+ input_map[b_link->from_socket().ptr.data] = proxy->inputs[0];
+ output_map[b_link->to_socket().ptr.data] = proxy->outputs[0];
+
+ graph->add(proxy);
}
}
- else if(b_node->is_a(&RNA_NodeGroup)) {
- /* add proxy converter nodes for inputs and outputs */
+ else if (b_node->is_a(&RNA_ShaderNodeGroup)) {
+
BL::NodeGroup b_gnode(*b_node);
BL::ShaderNodeTree b_group_ntree(b_gnode.node_tree());
- if (!b_group_ntree)
- continue;
-
- BL::Node::inputs_iterator b_input;
- BL::Node::outputs_iterator b_output;
-
- PtrSockMap group_sockmap;
+ ProxyMap group_proxy_map;
+ /* Add a proxy node for each socket
+ * Do this even if the node group has no internal tree,
+ * so that links have something to connect to and assert won't fail.
+ */
for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
- ShaderSocketType extern_type = convert_socket_type(b_input->type());
- ShaderSocketType intern_type = convert_socket_type(b_input->group_socket().type());
- ShaderNode *proxy = graph->add(new ProxyNode(extern_type, intern_type));
+ ProxyNode *proxy = new ProxyNode(convert_socket_type(*b_input));
+ graph->add(proxy);
- /* map the external node socket to the proxy node socket */
- proxy_map[b_input->ptr.data] = SocketPair(proxy, proxy->inputs[0]->name);
- /* map the internal group socket to the proxy node socket */
- group_sockmap[b_input->group_socket().ptr.data] = SocketPair(proxy, proxy->outputs[0]->name);
+ /* register the proxy node for internal binding */
+ group_proxy_map[b_input->identifier()] = proxy;
- /* default input values of the group node */
- set_default_value(proxy->inputs[0], *b_input, b_data, b_group_ntree);
+ input_map[b_input->ptr.data] = proxy->inputs[0];
+
+ set_default_value(proxy->inputs[0], *b_node, *b_input, b_data, b_ntree);
}
-
for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
- ShaderSocketType extern_type = convert_socket_type(b_output->type());
- ShaderSocketType intern_type = convert_socket_type(b_output->group_socket().type());
- ShaderNode *proxy = graph->add(new ProxyNode(intern_type, extern_type));
+ ProxyNode *proxy = new ProxyNode(convert_socket_type(*b_output));
+ graph->add(proxy);
- /* map the external node socket to the proxy node socket */
- proxy_map[b_output->ptr.data] = SocketPair(proxy, proxy->outputs[0]->name);
- /* map the internal group socket to the proxy node socket */
- group_sockmap[b_output->group_socket().ptr.data] = SocketPair(proxy, proxy->inputs[0]->name);
+ /* register the proxy node for internal binding */
+ group_proxy_map[b_output->identifier()] = proxy;
- /* default input values of internal, unlinked group outputs */
- set_default_value(proxy->inputs[0], b_output->group_socket(), b_data, b_group_ntree);
+ output_map[b_output->ptr.data] = proxy->outputs[0];
}
- add_nodes(scene, b_data, b_scene, graph, b_group_ntree, group_sockmap);
+ if (b_group_ntree)
+ add_nodes(scene, b_data, b_scene, graph, b_group_ntree, group_proxy_map);
+ }
+ 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::iterator proxy_it = proxy_map.find(b_output->identifier());
+ if (proxy_it != proxy_map.end()) {
+ ProxyNode *proxy = proxy_it->second;
+
+ output_map[b_output->ptr.data] = proxy->outputs[0];
+ }
+ }
+ }
+ 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()) {
+ /* map each socket to a proxy node */
+ for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
+ ProxyMap::iterator proxy_it = proxy_map.find(b_input->identifier());
+ if (proxy_it != proxy_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);
+ }
+ }
+ }
}
else {
ShaderNode *node = add_node(scene, b_data, b_scene, graph, b_ntree, BL::ShaderNode(*b_node));
if(node) {
- BL::Node::inputs_iterator b_input;
-
- node_map[b_node->ptr.data] = node;
-
+ /* map node sockets for linking */
for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
- SocketPair pair = node_socket_map_pair(node_map, *b_node, *b_input);
- ShaderInput *input = pair.first->input(pair.second.c_str());
+ ShaderInput *input = node_find_input_by_name(node, *b_node, *b_input);
+ input_map[b_input->ptr.data] = input;
- assert(input);
-
- /* copy values for non linked inputs */
- set_default_value(input, *b_input, b_data, b_ntree);
+ set_default_value(input, *b_node, *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);
+ output_map[b_output->ptr.data] = output;
}
}
}
@@ -790,44 +765,23 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha
for(b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) {
/* get blender link data */
- BL::Node b_from_node = b_link->from_node();
- BL::Node b_to_node = b_link->to_node();
-
BL::NodeSocket b_from_sock = b_link->from_socket();
BL::NodeSocket b_to_sock = b_link->to_socket();
- SocketPair from_pair, to_pair;
-
- /* links without a node pointer are connections to group inputs/outputs */
-
- /* from sock */
- if(b_from_node) {
- if (b_from_node.mute() || b_from_node.is_a(&RNA_NodeGroup))
- from_pair = proxy_map[b_from_sock.ptr.data];
- else
- from_pair = node_socket_map_pair(node_map, b_from_node, b_from_sock);
- }
- else
- from_pair = sockets_map[b_from_sock.ptr.data];
-
- /* to sock */
- if(b_to_node) {
- if (b_to_node.mute() || b_to_node.is_a(&RNA_NodeGroup))
- to_pair = proxy_map[b_to_sock.ptr.data];
- else
- to_pair = node_socket_map_pair(node_map, b_to_node, b_to_sock);
- }
- else
- to_pair = sockets_map[b_to_sock.ptr.data];
+ ShaderOutput *output = 0;
+ ShaderInput *input = 0;
+
+ PtrOutputMap::iterator output_it = output_map.find(b_from_sock.ptr.data);
+ 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())
+ input = input_it->second;
/* either node may be NULL when the node was not exported, typically
* because the node type is not supported */
- if(from_pair.first && to_pair.first) {
- ShaderOutput *output = from_pair.first->output(from_pair.second.c_str());
- ShaderInput *input = to_pair.first->input(to_pair.second.c_str());
-
+ if(output && input)
graph->connect(output, input);
- }
}
}
@@ -852,10 +806,10 @@ void BlenderSync::sync_materials(bool update_all)
/* create nodes */
if(b_mat->use_nodes() && b_mat->node_tree()) {
- PtrSockMap sock_to_node;
+ ProxyMap proxy_map;
BL::ShaderNodeTree b_ntree(b_mat->node_tree());
- add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node);
+ add_nodes(scene, b_data, b_scene, graph, b_ntree, proxy_map);
}
else {
ShaderNode *closure, *out;
@@ -893,10 +847,10 @@ void BlenderSync::sync_world(bool update_all)
/* create nodes */
if(b_world && b_world.use_nodes() && b_world.node_tree()) {
- PtrSockMap sock_to_node;
+ ProxyMap proxy_map;
BL::ShaderNodeTree b_ntree(b_world.node_tree());
- add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node);
+ add_nodes(scene, b_data, b_scene, graph, b_ntree, proxy_map);
}
else if(b_world) {
ShaderNode *closure, *out;
@@ -952,10 +906,10 @@ void BlenderSync::sync_lamps(bool update_all)
if(b_lamp->use_nodes() && b_lamp->node_tree()) {
shader->name = b_lamp->name().c_str();
- PtrSockMap sock_to_node;
+ ProxyMap proxy_map;
BL::ShaderNodeTree b_ntree(b_lamp->node_tree());
- add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node);
+ add_nodes(scene, b_data, b_scene, graph, b_ntree, proxy_map);
}
else {
ShaderNode *closure, *out;
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index d0e8b508df6..f6ff78ab2ac 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -28,6 +28,7 @@
#include "object.h"
#include "scene.h"
#include "shader.h"
+#include "curves.h"
#include "device.h"
@@ -41,7 +42,7 @@ CCL_NAMESPACE_BEGIN
/* Constructor */
-BlenderSync::BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_, Scene *scene_, bool preview_, Progress &progress_)
+BlenderSync::BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_, Scene *scene_, bool preview_, Progress &progress_, bool is_cpu_)
: b_engine(b_engine_),
b_data(b_data_), b_scene(b_scene_),
shader_map(&scene_->shaders),
@@ -56,6 +57,7 @@ BlenderSync::BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::
{
scene = scene_;
preview = preview_;
+ is_cpu = is_cpu_;
}
BlenderSync::~BlenderSync()
@@ -141,6 +143,7 @@ void BlenderSync::sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, const
sync_integrator();
sync_film();
sync_shaders();
+ sync_curve_settings();
sync_objects(b_v3d);
sync_motion(b_v3d, b_override);
}
@@ -289,7 +292,7 @@ SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background)
BL::RenderSettings r = b_scene.render();
SceneParams params;
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- int shadingsystem = RNA_enum_get(&cscene, "shading_system");
+ int shadingsystem = RNA_boolean_get(&cscene, "shading_system");
if(shadingsystem == 0)
params.shadingsystem = SceneParams::SVM;
@@ -304,7 +307,10 @@ SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background)
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;
- params.persistent_images = (background)? r.use_persistent_data(): false;
+ if(background && params.shadingsystem != SceneParams::OSL)
+ params.persistent_data = r.use_persistent_data();
+ else
+ params.persistent_data = false;
return params;
}
@@ -331,7 +337,13 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use
/* device default CPU */
params.device = devices[0];
- if(RNA_enum_get(&cscene, "device") != 0) {
+ if(RNA_enum_get(&cscene, "device") == 2) {
+ /* find network device */
+ foreach(DeviceInfo& info, devices)
+ if(info.type == DEVICE_NETWORK)
+ params.device = info;
+ }
+ else if(RNA_enum_get(&cscene, "device") == 1) {
/* find GPU device with given id */
PointerRNA systemptr = b_userpref.system().ptr;
PropertyRNA *deviceprop = RNA_struct_find_property(&systemptr, "compute_device");
@@ -350,22 +362,22 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use
params.background = background;
/* samples */
- if(get_boolean(cscene, "progressive")) {
+ if(get_boolean(cscene, "progressive") == 0 && params.device.type == DEVICE_CPU){
if(background) {
- params.samples = get_int(cscene, "samples");
+ params.samples = get_int(cscene, "aa_samples");
}
else {
- params.samples = get_int(cscene, "preview_samples");
+ params.samples = get_int(cscene, "preview_aa_samples");
if(params.samples == 0)
params.samples = INT_MAX;
}
}
else {
if(background) {
- params.samples = get_int(cscene, "aa_samples");
+ params.samples = get_int(cscene, "samples");
}
else {
- params.samples = get_int(cscene, "preview_aa_samples");
+ params.samples = get_int(cscene, "preview_samples");
if(params.samples == 0)
params.samples = INT_MAX;
}
@@ -387,6 +399,8 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use
params.tile_size = make_int2(tile_x, tile_y);
}
+
+ params.tile_order = RNA_enum_get(&cscene, "tile_order");
params.start_resolution = get_int(cscene, "preview_start_resolution");
@@ -414,7 +428,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use
params.progressive = true;
/* shading system - scene level needs full refresh */
- int shadingsystem = RNA_enum_get(&cscene, "shading_system");
+ int shadingsystem = RNA_boolean_get(&cscene, "shading_system");
if(shadingsystem == 0)
params.shadingsystem = SessionParams::SVM;
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index d3d21fbdf72..43073ed9dee 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -50,13 +50,13 @@ class ShaderNode;
class BlenderSync {
public:
- BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data, BL::Scene b_scene, Scene *scene_, bool preview_, Progress &progress_);
+ BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data, BL::Scene b_scene, Scene *scene_, bool preview_, Progress &progress_, bool is_cpu_);
~BlenderSync();
/* sync */
bool sync_recalc();
void sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, const char *layer = 0);
- void sync_camera(BL::Object b_override, int width, int height);
+ void sync_camera(BL::RenderSettings b_render, BL::Object b_override, int width, int height);
void sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height);
int get_layer_samples() { return render_layer.samples; }
@@ -64,7 +64,7 @@ public:
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 bool get_session_pause(BL::Scene b_scene, bool background);
- static BufferParams get_buffer_params(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::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, Camera *cam, int width, int height);
private:
/* sync */
@@ -78,10 +78,12 @@ private:
void sync_world(bool update_all);
void sync_render_layers(BL::SpaceView3D b_v3d, const char *layer);
void sync_shaders();
+ void sync_curve_settings();
void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree);
- Mesh *sync_mesh(BL::Object b_ob, bool object_updated);
- Object *sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_object, Transform& tfm, uint layer_flag, int motion);
+ 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 object_updated);
+ Object *sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_object, Transform& tfm, uint layer_flag, int motion, 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();
void sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion);
@@ -113,6 +115,7 @@ private:
Scene *scene;
bool preview;
bool experimental;
+ bool is_cpu;
struct RenderLayerInfo {
RenderLayerInfo()
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index fbcbe15ec5a..bd4852d08e1 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -33,13 +33,15 @@ extern "C" {
void BLI_timestr(double _time, char *str);
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);
+float *BKE_image_get_float_pixels_for_frame(void *image, int frame);
}
CCL_NAMESPACE_BEGIN
-static inline BL::Mesh object_to_mesh(BL::Object self, BL::Scene scene, bool apply_modifiers, bool render)
+static inline BL::Mesh object_to_mesh(BL::BlendData data, BL::Object object, BL::Scene scene, bool apply_modifiers, bool render)
{
- return self.to_mesh(scene, apply_modifiers, (render)? 2: 1);
+ return data.meshes.new_from_object(scene, object, apply_modifiers, (render)? 2: 1, true);
}
static inline void colorramp_to_array(BL::ColorRamp ramp, float4 *data, int size)
@@ -100,6 +102,22 @@ static inline string image_user_file_path(BL::ImageUser iuser, BL::Image ima, in
return string(filepath);
}
+static inline int image_user_frame_number(BL::ImageUser iuser, int cfra)
+{
+ BKE_image_user_frame_calc(iuser.ptr.data, cfra, 0);
+ return iuser.frame_current();
+}
+
+static inline unsigned char *image_get_pixels_for_frame(BL::Image image, int frame)
+{
+ return BKE_image_get_pixels_for_frame(image.ptr.data, frame);
+}
+
+static inline float *image_get_float_pixels_for_frame(BL::Image image, int frame)
+{
+ return BKE_image_get_float_pixels_for_frame(image.ptr.data, frame);
+}
+
/* Utilities */
static inline Transform get_transform(BL::Array<float, 16> array)
@@ -184,30 +202,60 @@ static inline uint get_layer(BL::Array<int, 20> array, BL::Array<int, 8> local_a
return layer;
}
-#if 0
static inline float3 get_float3(PointerRNA& ptr, const char *name)
{
float3 f;
RNA_float_get_array(&ptr, name, &f.x);
return f;
}
-#endif
+
+static inline void set_float3(PointerRNA& ptr, const char *name, float3 value)
+{
+ RNA_float_set_array(&ptr, name, &value.x);
+}
+
+static inline float4 get_float4(PointerRNA& ptr, const char *name)
+{
+ float4 f;
+ RNA_float_get_array(&ptr, name, &f.x);
+ return f;
+}
+
+static inline void set_float4(PointerRNA& ptr, const char *name, float4 value)
+{
+ RNA_float_set_array(&ptr, name, &value.x);
+}
static inline bool get_boolean(PointerRNA& ptr, const char *name)
{
return RNA_boolean_get(&ptr, name)? true: false;
}
+static inline void set_boolean(PointerRNA& ptr, const char *name, bool value)
+{
+ RNA_boolean_set(&ptr, name, (int)value);
+}
+
static inline float get_float(PointerRNA& ptr, const char *name)
{
return RNA_float_get(&ptr, name);
}
+static inline void set_float(PointerRNA& ptr, const char *name, float value)
+{
+ RNA_float_set(&ptr, name, value);
+}
+
static inline int get_int(PointerRNA& ptr, const char *name)
{
return RNA_int_get(&ptr, name);
}
+static inline void set_int(PointerRNA& ptr, const char *name, int value)
+{
+ RNA_int_set(&ptr, name, value);
+}
+
static inline int get_enum(PointerRNA& ptr, const char *name)
{
return RNA_enum_get(&ptr, name);
@@ -224,6 +272,32 @@ static inline string get_enum_identifier(PointerRNA& ptr, const char *name)
return string(identifier);
}
+static inline void set_enum(PointerRNA& ptr, const char *name, int value)
+{
+ RNA_enum_set(&ptr, name, value);
+}
+
+static inline void set_enum(PointerRNA& ptr, const char *name, const string &identifier)
+{
+ RNA_enum_set_identifier(&ptr, name, identifier.c_str());
+}
+
+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)
+ MEM_freeN(cstr);
+
+ return str;
+}
+
+static inline void set_string(PointerRNA& ptr, const char *name, const string &value)
+{
+ RNA_string_set(&ptr, name, value.c_str());
+}
+
/* Relative Paths */
static inline string blender_absolute_path(BL::BlendData b_data, BL::ID b_id, const string& path)
@@ -242,6 +316,20 @@ static inline string blender_absolute_path(BL::BlendData b_data, BL::ID b_id, co
return path;
}
+/* Texture Space */
+
+static inline void mesh_texture_space(BL::Mesh b_mesh, float3& loc, float3& size)
+{
+ loc = get_float3(b_mesh.texspace_location());
+ size = get_float3(b_mesh.texspace_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);
+}
+
/* ID Map
*
* Utility class to keep in sync with blender data.
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index b58a34f9942..f11b3c4c0bc 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -18,6 +18,7 @@
#include "mesh.h"
#include "object.h"
#include "scene.h"
+#include "curves.h"
#include "bvh.h"
#include "bvh_build.h"
@@ -29,6 +30,7 @@
#include "util_foreach.h"
#include "util_map.h"
#include "util_progress.h"
+#include "util_system.h"
#include "util_types.h"
CCL_NAMESPACE_BEGIN
@@ -70,11 +72,14 @@ BVH *BVH::create(const BVHParams& params, const vector<Object*>& objects)
bool BVH::cache_read(CacheData& key)
{
+ key.add(system_cpu_bits());
key.add(&params, sizeof(params));
foreach(Object *ob, objects) {
key.add(ob->mesh->verts);
key.add(ob->mesh->triangles);
+ key.add(ob->mesh->curve_keys);
+ key.add(ob->mesh->curves);
key.add(&ob->bounds, sizeof(ob->bounds));
key.add(&ob->visibility, sizeof(ob->visibility));
key.add(&ob->mesh->transform_applied, sizeof(bool));
@@ -91,6 +96,7 @@ bool BVH::cache_read(CacheData& key)
value.read(pack.nodes);
value.read(pack.object_node);
value.read(pack.tri_woop);
+ value.read(pack.prim_segment);
value.read(pack.prim_visibility);
value.read(pack.prim_index);
value.read(pack.prim_object);
@@ -112,6 +118,7 @@ void BVH::cache_write(CacheData& key)
value.add(pack.nodes);
value.add(pack.object_node);
value.add(pack.tri_woop);
+ value.add(pack.prim_segment);
value.add(pack.prim_visibility);
value.add(pack.prim_index);
value.add(pack.prim_object);
@@ -157,10 +164,11 @@ void BVH::build(Progress& progress)
}
/* build nodes */
+ vector<int> prim_segment;
vector<int> prim_index;
vector<int> prim_object;
- BVHBuild bvh_build(objects, prim_index, prim_object, params, progress);
+ BVHBuild bvh_build(objects, prim_segment, prim_index, prim_object, params, progress);
BVHNode *root = bvh_build.run();
if(progress.get_cancel()) {
@@ -169,6 +177,7 @@ void BVH::build(Progress& progress)
}
/* todo: get rid of this copy */
+ pack.prim_segment = prim_segment;
pack.prim_index = prim_index;
pack.prim_object = prim_object;
@@ -182,8 +191,8 @@ void BVH::build(Progress& progress)
}
/* pack triangles */
- progress.set_substatus("Packing BVH triangles");
- pack_triangles();
+ progress.set_substatus("Packing BVH triangles and strands");
+ pack_primitives();
if(progress.get_cancel()) {
root->deleteSubtree();
@@ -215,8 +224,8 @@ void BVH::build(Progress& progress)
void BVH::refit(Progress& progress)
{
- progress.set_substatus("Packing BVH triangles");
- pack_triangles();
+ progress.set_substatus("Packing BVH primitives");
+ pack_primitives();
if(progress.get_cancel()) return;
@@ -263,7 +272,52 @@ void BVH::pack_triangle(int idx, float4 woop[3])
}
}
-void BVH::pack_triangles()
+/* 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 = pack.prim_segment[idx];
+ int k0 = mesh->curves[tidx].first_key + segment;
+ int k1 = mesh->curves[tidx].first_key + segment + 1;
+ float3 v0 = mesh->curve_keys[k0].co;
+ float3 v1 = mesh->curve_keys[k1].co;
+
+ 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);
+ */
+ Attribute *attr_tangent = mesh->curve_attributes.find(ATTR_STD_CURVE_TANGENT);
+ float3 tg0 = make_float3(1.0f, 0.0f, 0.0f);
+ float3 tg1 = make_float3(1.0f, 0.0f, 0.0f);
+
+ if(attr_tangent) {
+ const float3 *data_tangent = attr_tangent->data_float3();
+
+ tg0 = data_tangent[k0];
+ tg1 = data_tangent[k1];
+ }
+
+ 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;
size_t tidx_size = pack.prim_index.size();
@@ -277,13 +331,21 @@ void BVH::pack_triangles()
if(pack.prim_index[i] != -1) {
float4 woop[3];
- pack_triangle(i, woop);
+ if(pack.prim_segment[i] != ~0)
+ pack_curve_segment(i, woop);
+ else
+ pack_triangle(i, woop);
+
memcpy(&pack.tri_woop[i * nsize], woop, sizeof(float4)*3);
int tob = pack.prim_object[i];
Object *ob = objects[tob];
pack.prim_visibility[i] = ob->visibility;
}
+ else {
+ memset(&pack.tri_woop[i * nsize], 0, sizeof(float4)*3);
+ pack.prim_visibility[i] = 0;
+ }
}
}
@@ -300,11 +362,15 @@ void BVH::pack_instances(size_t nodes_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 */
for(size_t i = 0; i < pack.prim_index.size(); i++)
- if(pack.prim_index[i] != -1)
- pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset;
+ if(pack.prim_index[i] != -1) {
+ if(pack.prim_segment[i] != ~0)
+ pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset;
+ else
+ pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset;
+ }
/* track offsets of instanced BVH data in global array */
- size_t tri_offset = pack.prim_index.size();
+ size_t prim_offset = pack.prim_index.size();
size_t nodes_offset = nodes_size;
/* clear array that gives the node indexes for instanced objects */
@@ -339,6 +405,7 @@ void BVH::pack_instances(size_t nodes_size)
mesh_map.clear();
pack.prim_index.resize(prim_index_size);
+ pack.prim_segment.resize(prim_index_size);
pack.prim_object.resize(prim_index_size);
pack.prim_visibility.resize(prim_index_size);
pack.tri_woop.resize(tri_woop_size);
@@ -346,6 +413,7 @@ void BVH::pack_instances(size_t nodes_size)
pack.object_node.resize(objects.size());
int *pack_prim_index = (pack.prim_index.size())? &pack.prim_index[0]: NULL;
+ int *pack_prim_segment = (pack.prim_segment.size())? &pack.prim_segment[0]: NULL;
int *pack_prim_object = (pack.prim_object.size())? &pack.prim_object[0]: NULL;
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;
@@ -376,6 +444,7 @@ void BVH::pack_instances(size_t nodes_size)
int noffset = nodes_offset/nsize;
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])
@@ -389,10 +458,16 @@ void BVH::pack_instances(size_t nodes_size)
if(bvh->pack.prim_index.size()) {
size_t bvh_prim_index_size = bvh->pack.prim_index.size();
int *bvh_prim_index = &bvh->pack.prim_index[0];
+ int *bvh_prim_segment = &bvh->pack.prim_segment[0];
uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0];
for(size_t i = 0; i < bvh_prim_index_size; i++) {
- pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset;
+ if(bvh->pack.prim_segment[i] != ~0)
+ pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset;
+ else
+ pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset;
+
+ pack_prim_segment[pack_prim_index_offset] = bvh_prim_segment[i];
pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i];
pack_prim_object[pack_prim_index_offset] = 0; // unused for instances
pack_prim_index_offset++;
@@ -401,13 +476,13 @@ void BVH::pack_instances(size_t nodes_size)
/* merge triangle intersection data */
if(bvh->pack.tri_woop.size()) {
- memcpy(pack_tri_woop+pack_tri_woop_offset, &bvh->pack.tri_woop[0],
+ memcpy(pack_tri_woop + pack_tri_woop_offset, &bvh->pack.tri_woop[0],
bvh->pack.tri_woop.size()*sizeof(float4));
pack_tri_woop_offset += bvh->pack.tri_woop.size();
}
/* merge nodes */
- if( bvh->pack.nodes.size()) {
+ if(bvh->pack.nodes.size()) {
size_t nsize_bbox = (use_qbvh)? nsize-2: nsize-1;
int4 *bvh_nodes = &bvh->pack.nodes[0];
size_t bvh_nodes_size = bvh->pack.nodes.size();
@@ -420,8 +495,8 @@ void BVH::pack_instances(size_t nodes_size)
int4 data = bvh_nodes[i + nsize_bbox];
if(bvh_is_leaf && bvh_is_leaf[j]) {
- data.x += tri_offset;
- data.y += tri_offset;
+ data.x += prim_offset;
+ data.y += prim_offset;
}
else {
data.x += (data.x < 0)? -noffset: noffset;
@@ -443,7 +518,7 @@ void BVH::pack_instances(size_t nodes_size)
}
nodes_offset += bvh->pack.nodes.size();
- tri_offset += bvh->pack.prim_index.size();
+ prim_offset += bvh->pack.prim_index.size();
}
}
@@ -544,25 +619,49 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
if(leaf) {
/* refit leaf node */
- for(int tri = c0; tri < c1; tri++) {
- int tidx = pack.prim_index[tri];
- int tob = pack.prim_object[tri];
+ for(int prim = c0; prim < c1; prim++) {
+ int pidx = pack.prim_index[prim];
+ int tob = pack.prim_object[prim];
Object *ob = objects[tob];
- if(tidx == -1) {
+ if(pidx == -1) {
/* object instance */
bbox.grow(ob->bounds);
}
else {
- /* triangles */
+ /* primitives */
const Mesh *mesh = ob->mesh;
- int tri_offset = (params.top_level)? mesh->tri_offset: 0;
- const int *vidx = mesh->triangles[tidx - tri_offset].v;
- const float3 *vpos = &mesh->verts[0];
- bbox.grow(vpos[vidx[0]]);
- bbox.grow(vpos[vidx[1]]);
- bbox.grow(vpos[vidx[2]]);
+ if(pack.prim_segment[prim] != ~0) {
+ /* curves */
+ int str_offset = (params.top_level)? mesh->curve_offset: 0;
+ int k0 = mesh->curves[pidx - str_offset].first_key + pack.prim_segment[prim]; // XXX!
+ int k1 = k0 + 1;
+
+ float3 p[4];
+ p[0] = mesh->curve_keys[max(k0 - 1,mesh->curves[pidx - str_offset].first_key)].co;
+ p[1] = mesh->curve_keys[k0].co;
+ p[2] = mesh->curve_keys[k1].co;
+ p[3] = mesh->curve_keys[min(k1 + 1,mesh->curves[pidx - str_offset].first_key + mesh->curves[pidx - str_offset].num_keys - 1)].co;
+ float3 lower;
+ float3 upper;
+ curvebounds(&lower.x, &upper.x, p, 0);
+ curvebounds(&lower.y, &upper.y, p, 1);
+ curvebounds(&lower.z, &upper.z, p, 2);
+ float mr = max(mesh->curve_keys[k0].radius,mesh->curve_keys[k1].radius);
+ bbox.grow(lower, mr);
+ bbox.grow(upper, mr);
+ }
+ else {
+ /* triangles */
+ int tri_offset = (params.top_level)? mesh->tri_offset: 0;
+ const int *vidx = mesh->triangles[pidx - tri_offset].v;
+ const float3 *vpos = &mesh->verts[0];
+
+ bbox.grow(vpos[vidx[0]]);
+ bbox.grow(vpos[vidx[1]]);
+ bbox.grow(vpos[vidx[2]]);
+ }
}
visibility |= ob->visibility;
diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h
index 549f1e3ac1d..00c146143b8 100644
--- a/intern/cycles/bvh/bvh.h
+++ b/intern/cycles/bvh/bvh.h
@@ -51,7 +51,9 @@ struct PackedBVH {
/* object index to BVH node index mapping for instances */
array<int> object_node;
/* precomputed triangle intersection data, one triangle is 4x float4 */
- array<float4> tri_woop;
+ array<float4> tri_woop;
+ /* primitive type - triangle or strand (should be moved to flag?) */
+ array<int> prim_segment;
/* visibility visibilitys for primitives */
array<uint> prim_visibility;
/* mapping from BVH primitive index to true primitive index, as primitives
@@ -101,9 +103,10 @@ protected:
bool cache_read(CacheData& key);
void cache_write(CacheData& key);
- /* triangles */
- void pack_triangles();
+ /* 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);
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index 705b805a3a9..022c4c8d294 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -24,6 +24,7 @@
#include "mesh.h"
#include "object.h"
#include "scene.h"
+#include "curves.h"
#include "util_debug.h"
#include "util_foreach.h"
@@ -48,9 +49,10 @@ public:
/* Constructor / Destructor */
BVHBuild::BVHBuild(const vector<Object*>& objects_,
- vector<int>& prim_index_, vector<int>& prim_object_,
+ vector<int>& prim_segment_, vector<int>& prim_index_, vector<int>& prim_object_,
const BVHParams& params_, Progress& progress_)
: objects(objects_),
+ prim_segment(prim_segment_),
prim_index(prim_index_),
prim_object(prim_object_),
params(params_),
@@ -73,25 +75,64 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
BoundBox bounds = BoundBox::empty;
for(int k = 0; k < 3; k++) {
- float3 pt = mesh->verts[t.v[k]];
- bounds.grow(pt);
+ float3 co = mesh->verts[t.v[k]];
+ bounds.grow(co);
}
if(bounds.valid()) {
- references.push_back(BVHReference(bounds, j, i));
+ references.push_back(BVHReference(bounds, j, i, ~0));
root.grow(bounds);
center.grow(bounds.center2());
}
}
+
+ for(uint j = 0; j < mesh->curves.size(); j++) {
+ Mesh::Curve curve = mesh->curves[j];
+
+ for(int k = 0; k < curve.num_keys - 1; k++) {
+ BoundBox bounds = BoundBox::empty;
+
+ float3 co[4];
+ co[0] = mesh->curve_keys[max(curve.first_key + k - 1,curve.first_key)].co;
+ co[1] = mesh->curve_keys[curve.first_key + k].co;
+ co[2] = mesh->curve_keys[curve.first_key + k + 1].co;
+ co[3] = mesh->curve_keys[min(curve.first_key + k + 2, curve.first_key + curve.num_keys - 1)].co;
+
+ float3 lower;
+ float3 upper;
+ curvebounds(&lower.x, &upper.x, co, 0);
+ curvebounds(&lower.y, &upper.y, co, 1);
+ curvebounds(&lower.z, &upper.z, co, 2);
+ float mr = max(mesh->curve_keys[curve.first_key + k].radius, mesh->curve_keys[curve.first_key + k + 1].radius);
+ bounds.grow(lower, mr);
+ bounds.grow(upper, mr);
+
+ if(bounds.valid()) {
+ references.push_back(BVHReference(bounds, j, i, k));
+ root.grow(bounds);
+ center.grow(bounds.center2());
+ }
+ }
+ }
}
void BVHBuild::add_reference_object(BoundBox& root, BoundBox& center, Object *ob, int i)
{
- references.push_back(BVHReference(ob->bounds, -1, i));
+ references.push_back(BVHReference(ob->bounds, -1, i, false));
root.grow(ob->bounds);
center.grow(ob->bounds.center2());
}
+static size_t count_curve_segments(Mesh *mesh)
+{
+ size_t num = 0, num_curves = mesh->curves.size();
+
+ for(size_t i = 0; i < num_curves; i++)
+ num += mesh->curves[i].num_keys - 1;
+
+ return num;
+}
+
void BVHBuild::add_references(BVHRange& root)
{
/* reserve space for references */
@@ -99,13 +140,17 @@ void BVHBuild::add_references(BVHRange& root)
foreach(Object *ob, objects) {
if(params.top_level) {
- if(ob->mesh->transform_applied)
+ if(ob->mesh->transform_applied) {
num_alloc_references += ob->mesh->triangles.size();
+ num_alloc_references += count_curve_segments(ob->mesh);
+ }
else
num_alloc_references++;
}
- else
+ else {
num_alloc_references += ob->mesh->triangles.size();
+ num_alloc_references += count_curve_segments(ob->mesh);
+ }
}
references.reserve(num_alloc_references);
@@ -162,6 +207,7 @@ BVHNode* BVHBuild::run()
progress_total = references.size();
progress_original_total = progress_total;
+ prim_segment.resize(references.size());
prim_index.resize(references.size());
prim_object.resize(references.size());
@@ -319,10 +365,12 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
if(start == prim_index.size()) {
assert(params.use_spatial_split);
+ prim_segment.push_back(ref->prim_segment());
prim_index.push_back(ref->prim_index());
prim_object.push_back(ref->prim_object());
}
else {
+ prim_segment[start] = ref->prim_segment();
prim_index[start] = ref->prim_index();
prim_object[start] = ref->prim_object();
}
@@ -345,6 +393,7 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
{
+ vector<int>& p_segment = prim_segment;
vector<int>& p_index = prim_index;
vector<int>& p_object = prim_object;
BoundBox bounds = BoundBox::empty;
@@ -358,10 +407,12 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
if(range.start() + num == prim_index.size()) {
assert(params.use_spatial_split);
+ p_segment.push_back(ref.prim_segment());
p_index.push_back(ref.prim_index());
p_object.push_back(ref.prim_object());
}
else {
+ p_segment[range.start() + num] = ref.prim_segment();
p_index[range.start() + num] = ref.prim_index();
p_object[range.start() + num] = ref.prim_object();
}
diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h
index 44ef918b326..3df4da1739a 100644
--- a/intern/cycles/bvh/bvh_build.h
+++ b/intern/cycles/bvh/bvh_build.h
@@ -44,6 +44,7 @@ public:
/* Constructor/Destructor */
BVHBuild(
const vector<Object*>& objects,
+ vector<int>& prim_segment,
vector<int>& prim_index,
vector<int>& prim_object,
const BVHParams& params,
@@ -87,6 +88,7 @@ protected:
int num_original_references;
/* output primitive indexes and objects */
+ vector<int>& prim_segment;
vector<int>& prim_index;
vector<int>& prim_object;
diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h
index a78496d841d..f7bc79f71e6 100644
--- a/intern/cycles/bvh/bvh_params.h
+++ b/intern/cycles/bvh/bvh_params.h
@@ -98,19 +98,22 @@ class BVHReference
public:
__forceinline BVHReference() {}
- __forceinline BVHReference(const BoundBox& bounds_, int prim_index_, int prim_object_)
+ __forceinline BVHReference(const BoundBox& bounds_, int prim_index_, int prim_object_, int prim_segment)
: rbounds(bounds_)
{
rbounds.min.w = __int_as_float(prim_index_);
rbounds.max.w = __int_as_float(prim_object_);
+ segment = prim_segment;
}
__forceinline const BoundBox& bounds() const { return rbounds; }
__forceinline int prim_index() const { return __float_as_int(rbounds.min.w); }
__forceinline int prim_object() const { return __float_as_int(rbounds.max.w); }
+ __forceinline int prim_segment() const { return segment; }
protected:
BoundBox rbounds;
+ uint segment;
};
/* BVH Range
diff --git a/intern/cycles/bvh/bvh_sort.cpp b/intern/cycles/bvh/bvh_sort.cpp
index bef384be592..91994be5b96 100644
--- a/intern/cycles/bvh/bvh_sort.cpp
+++ b/intern/cycles/bvh/bvh_sort.cpp
@@ -43,6 +43,8 @@ public:
else if(ra.prim_object() > rb.prim_object()) return false;
else if(ra.prim_index() < rb.prim_index()) return true;
else if(ra.prim_index() > rb.prim_index()) return false;
+ else if(ra.prim_segment() < rb.prim_segment()) return true;
+ else if(ra.prim_segment() > rb.prim_segment()) return false;
return false;
}
diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp
index 263c5834428..03ff69d7b6d 100644
--- a/intern/cycles/bvh/bvh_split.cpp
+++ b/intern/cycles/bvh/bvh_split.cpp
@@ -252,14 +252,41 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
/* loop over vertices/edges. */
Object *ob = builder->objects[ref.prim_object()];
const Mesh *mesh = ob->mesh;
- 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];
+
+ if (ref.prim_segment() == ~0) {
+ 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 + ref.prim_segment();
+ const int k1 = k0 + 1;
+ const float3* v0 = &mesh->curve_keys[k0].co;
+ const float3* v1 = &mesh->curve_keys[k1].co;
+
float v0p = (*v0)[dim];
float v1p = (*v1)[dim];
@@ -270,6 +297,12 @@ 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));
@@ -284,9 +317,9 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
left_bounds.intersect(ref.bounds());
right_bounds.intersect(ref.bounds());
- /* set referecnes */
- left = BVHReference(left_bounds, ref.prim_index(), ref.prim_object());
- right = BVHReference(right_bounds, ref.prim_index(), ref.prim_object());
+ /* set references */
+ left = BVHReference(left_bounds, ref.prim_index(), ref.prim_object(), ref.prim_segment());
+ right = BVHReference(right_bounds, ref.prim_index(), ref.prim_object(), ref.prim_segment());
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt
index 0071bbe5cdc..fe2368b7ea8 100644
--- a/intern/cycles/device/CMakeLists.txt
+++ b/intern/cycles/device/CMakeLists.txt
@@ -18,11 +18,16 @@ set(SRC
device_cpu.cpp
device_cuda.cpp
device_multi.cpp
- device_network.cpp
device_opencl.cpp
device_task.cpp
)
+if(WITH_NETWORK)
+ list(APPEND SRC
+ device_network.cpp
+ )
+endif()
+
set(SRC_HEADERS
device.h
device_memory.h
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index 9840687b76a..7b31b9ba157 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -84,6 +84,7 @@ public:
/* info */
DeviceInfo info;
virtual const string& error_message() { return error_msg; }
+ bool have_error() { return !error_message().empty(); }
/* statistics */
Stats &stats;
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index a1d7706a34e..47f3273fdfa 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -58,7 +58,8 @@ public:
#endif
/* do now to avoid thread issues */
- system_cpu_support_optimized();
+ system_cpu_support_sse2();
+ system_cpu_support_sse3();
}
~CPUDevice()
@@ -66,11 +67,6 @@ public:
task_pool.stop();
}
- bool support_advanced_shading()
- {
- return true;
- }
-
void mem_alloc(device_memory& mem, MemoryType type)
{
mem.device_pointer = mem.data_pointer;
@@ -170,7 +166,26 @@ public:
int end_sample = tile.start_sample + tile.num_samples;
#ifdef WITH_OPTIMIZED_KERNEL
- if(system_cpu_support_optimized()) {
+ if(system_cpu_support_sse3()) {
+ for(int sample = start_sample; sample < end_sample; sample++) {
+ if (task.get_cancel() || task_pool.cancelled()) {
+ 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_sse2()) {
for(int sample = start_sample; sample < end_sample; sample++) {
if (task.get_cancel() || task_pool.cancelled()) {
if(task.need_finish_queue == false)
@@ -179,7 +194,7 @@ public:
for(int y = tile.y; y < tile.y + tile.h; y++) {
for(int x = tile.x; x < tile.x + tile.w; x++) {
- kernel_cpu_optimized_path_trace(&kg, render_buffer, rng_state,
+ kernel_cpu_sse2_path_trace(&kg, render_buffer, rng_state,
sample, x, y, tile.offset, tile.stride);
}
}
@@ -227,10 +242,16 @@ public:
void thread_tonemap(DeviceTask& task)
{
#ifdef WITH_OPTIMIZED_KERNEL
- if(system_cpu_support_optimized()) {
+ 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_optimized_tonemap(&kernel_globals, (uchar4*)task.rgba, (float*)task.buffer,
+ kernel_cpu_sse3_tonemap(&kernel_globals, (uchar4*)task.rgba, (float*)task.buffer,
+ task.sample, task.resolution, x, y, task.offset, task.stride);
+ }
+ else 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_tonemap(&kernel_globals, (uchar4*)task.rgba, (float*)task.buffer,
task.sample, task.resolution, x, y, task.offset, task.stride);
}
else
@@ -252,9 +273,17 @@ public:
#endif
#ifdef WITH_OPTIMIZED_KERNEL
- if(system_cpu_support_optimized()) {
+ if(system_cpu_support_sse3()) {
+ for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
+ kernel_cpu_sse3_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x);
+
+ if(task_pool.cancelled())
+ break;
+ }
+ }
+ else if(system_cpu_support_sse2()) {
for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
- kernel_cpu_optimized_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x);
+ kernel_cpu_sse2_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x);
if(task_pool.cancelled())
break;
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index 14f8cfa8767..e3291cc6d88 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -109,11 +109,11 @@ public:
}
}
-#ifdef NDEBUG
+/*#ifdef NDEBUG
#define cuda_abort()
#else
#define cuda_abort() abort()
-#endif
+#endif*/
#define cuda_assert(stmt) \
{ \
@@ -124,23 +124,25 @@ public:
if(error_msg == "") \
error_msg = message; \
fprintf(stderr, "%s\n", message.c_str()); \
- cuda_abort(); \
+ /*cuda_abort();*/ \
} \
}
- bool cuda_error(CUresult result)
+ bool cuda_error_(CUresult result, const string& stmt)
{
if(result == CUDA_SUCCESS)
return false;
- string message = string_printf("CUDA error: %s", cuda_error_string(result));
+ string message = string_printf("CUDA error at %s: %s", stmt.c_str(), cuda_error_string(result));
if(error_msg == "")
error_msg = message;
fprintf(stderr, "%s\n", message.c_str());
return true;
}
- void cuda_error(const string& message)
+#define cuda_error(stmt) cuda_error_(stmt, #stmt)
+
+ void cuda_error_message(const string& message)
{
if(error_msg == "")
error_msg = message;
@@ -187,7 +189,7 @@ public:
}
}
- if(cuda_error(result))
+ if(cuda_error_(result, "cuCtxCreate"))
return;
cuda_pop_context();
@@ -207,8 +209,8 @@ public:
int major, minor;
cuDeviceComputeCapability(&major, &minor, cuDevId);
- if(major <= 1 && minor <= 2) {
- cuda_error(string_printf("CUDA device supported only with compute capability 1.3 or up, found %d.%d.", major, minor));
+ if(major < 2) {
+ cuda_error_message(string_printf("CUDA device supported only with compute capability 2.0 or up, found %d.%d.", major, minor));
return false;
}
}
@@ -238,18 +240,21 @@ public:
if(path_exists(cubin))
return cubin;
-#if defined(WITH_CUDA_BINARIES) && defined(_WIN32)
- if(major <= 1 && minor <= 2)
- cuda_error(string_printf("CUDA device supported only compute capability 1.3 or up, found %d.%d.", major, minor));
- else
- cuda_error(string_printf("CUDA binary kernel for this graphics card compute capability (%d.%d) not found.", major, minor));
- return "";
-#else
+#ifdef _WIN32
+ if(cuHavePrecompiledKernels()) {
+ if(major < 2)
+ cuda_error_message(string_printf("CUDA device requires compute capability 2.0 or up, found %d.%d. Your GPU is not supported.", major, minor));
+ else
+ cuda_error_message(string_printf("CUDA binary kernel for this graphics card compute capability (%d.%d) not found.", major, minor));
+ return "";
+ }
+#endif
+
/* if not, find CUDA compiler */
string nvcc = cuCompilerPath();
if(nvcc == "") {
- cuda_error("CUDA nvcc compiler not found. Install CUDA toolkit in default location.");
+ cuda_error_message("CUDA nvcc compiler not found. Install CUDA toolkit in default location.");
return "";
}
@@ -269,20 +274,19 @@ public:
nvcc.c_str(), major, minor, machine, kernel.c_str(), cubin.c_str(), maxreg, include.c_str());
if(system(command.c_str()) == -1) {
- cuda_error("Failed to execute compilation command, see console for details.");
+ cuda_error_message("Failed to execute compilation command, see console for details.");
return "";
}
/* verify if compilation succeeded */
if(!path_exists(cubin)) {
- cuda_error("CUDA kernel compilation failed, see console for details.");
+ cuda_error_message("CUDA kernel compilation failed, see console for details.");
return "";
}
printf("Kernel compilation finished in %.2lfs.\n", time_dt() - starttime);
return cubin;
-#endif
}
bool load_kernels(bool experimental)
@@ -290,7 +294,8 @@ public:
/* check if cuda init succeeded */
if(cuContext == 0)
return false;
-
+
+ /* check if GPU is supported with current feature set */
if(!support_device(experimental))
return false;
@@ -304,8 +309,8 @@ public:
cuda_push_context();
CUresult result = cuModuleLoad(&cuModule, cubin.c_str());
- if(cuda_error(result))
- cuda_error(string_printf("Failed loading CUDA kernel %s.", cubin.c_str()));
+ if(cuda_error_(result, "cuModuleLoad"))
+ cuda_error_message(string_printf("Failed loading CUDA kernel %s.", cubin.c_str()));
cuda_pop_context();
@@ -326,7 +331,8 @@ public:
void mem_copy_to(device_memory& mem)
{
cuda_push_context();
- cuda_assert(cuMemcpyHtoD(cuda_device_ptr(mem.device_pointer), (void*)mem.data_pointer, mem.memory_size()))
+ if(mem.device_pointer)
+ cuda_assert(cuMemcpyHtoD(cuda_device_ptr(mem.device_pointer), (void*)mem.data_pointer, mem.memory_size()))
cuda_pop_context();
}
@@ -336,8 +342,13 @@ public:
size_t size = elem*w*h;
cuda_push_context();
- cuda_assert(cuMemcpyDtoH((uchar*)mem.data_pointer + offset,
- (CUdeviceptr)((uchar*)mem.device_pointer + offset), size))
+ if(mem.device_pointer) {
+ cuda_assert(cuMemcpyDtoH((uchar*)mem.data_pointer + offset,
+ (CUdeviceptr)((uchar*)mem.device_pointer + offset), size))
+ }
+ else {
+ memset((char*)mem.data_pointer + offset, 0, size);
+ }
cuda_pop_context();
}
@@ -346,7 +357,8 @@ public:
memset((void*)mem.data_pointer, 0, mem.memory_size());
cuda_push_context();
- cuda_assert(cuMemsetD8(cuda_device_ptr(mem.device_pointer), 0, mem.memory_size()))
+ if(mem.device_pointer)
+ cuda_assert(cuMemsetD8(cuda_device_ptr(mem.device_pointer), 0, mem.memory_size()))
cuda_pop_context();
}
@@ -390,13 +402,18 @@ public:
default: assert(0); return;
}
- CUtexref texref;
+ CUtexref texref = NULL;
cuda_push_context();
cuda_assert(cuModuleGetTexRef(&texref, cuModule, name))
+ if(!texref) {
+ cuda_pop_context();
+ return;
+ }
+
if(interpolation) {
- CUarray handle;
+ CUarray handle = NULL;
CUDA_ARRAY_DESCRIPTOR desc;
desc.Width = mem.data_width;
@@ -406,6 +423,11 @@ public:
cuda_assert(cuArrayCreate(&handle, &desc))
+ if(!handle) {
+ cuda_pop_context();
+ return;
+ }
+
if(mem.data_height > 1) {
CUDA_MEMCPY2D param;
memset(&param, 0, sizeof(param));
@@ -481,6 +503,9 @@ public:
void path_trace(RenderTile& rtile, int sample)
{
+ if(have_error())
+ return;
+
cuda_push_context();
CUfunction cuPathTrace;
@@ -546,6 +571,9 @@ public:
void tonemap(DeviceTask& task, device_ptr buffer, device_ptr rgba)
{
+ if(have_error())
+ return;
+
cuda_push_context();
CUfunction cuFilmConvert;
@@ -615,6 +643,9 @@ public:
void shader(DeviceTask& task)
{
+ if(have_error())
+ return;
+
cuda_push_context();
CUfunction cuDisplace;
@@ -709,7 +740,7 @@ public:
CUresult result = cuGraphicsGLRegisterBuffer(&pmem.cuPBOresource, pmem.cuPBO, CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE);
- if(!cuda_error(result)) {
+ if(result == CUDA_SUCCESS) {
cuda_pop_context();
mem.device_pointer = pmem.cuTexId;
diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp
index a5e0d39df73..201f04bc5d8 100644
--- a/intern/cycles/device/device_network.cpp
+++ b/intern/cycles/device/device_network.cpp
@@ -31,6 +31,8 @@ class NetworkDevice : public Device
public:
boost::asio::io_service io_service;
tcp::socket socket;
+ device_ptr mem_counter;
+ DeviceTask the_task; /* todo: handle multiple tasks */
NetworkDevice(Stats &stats, const char *address)
: Device(stats), socket(io_service)
@@ -49,75 +51,72 @@ public:
socket.close();
socket.connect(*endpoint_iterator++, error);
}
+
if(error)
throw boost::system::system_error(error);
+
+ mem_counter = 0;
}
~NetworkDevice()
{
+ RPCSend snd(socket, "stop");
+ snd.write();
}
void mem_alloc(device_memory& mem, MemoryType type)
{
-#if 0
+ mem.device_pointer = ++mem_counter;
+
RPCSend snd(socket, "mem_alloc");
- snd.archive & size & type;
+ snd.add(mem);
+ snd.add(type);
snd.write();
-
- RPCReceive rcv(socket);
-
- device_ptr mem;
- *rcv.archive & mem;
-
- return mem;
-#endif
}
void mem_copy_to(device_memory& mem)
{
-#if 0
RPCSend snd(socket, "mem_copy_to");
- snd.archive & mem & size;
+ snd.add(mem);
snd.write();
- snd.write_buffer(host, size);
-#endif
+ snd.write_buffer((void*)mem.data_pointer, mem.memory_size());
}
void mem_copy_from(device_memory& mem, int y, int w, int h, int elem)
{
-#if 0
RPCSend snd(socket, "mem_copy_from");
- snd.archive & mem & offset & size;
+ snd.add(mem);
+ snd.add(y);
+ snd.add(w);
+ snd.add(h);
+ snd.add(elem);
snd.write();
RPCReceive rcv(socket);
- rcv.read_buffer(host, size);
-#endif
+ rcv.read_buffer((void*)mem.data_pointer, mem.memory_size());
}
void mem_zero(device_memory& mem)
{
-#if 0
RPCSend snd(socket, "mem_zero");
- snd.archive & mem & size;
+ snd.add(mem);
snd.write();
-#endif
}
void mem_free(device_memory& mem)
{
-#if 0
- if(mem) {
+ if(mem.device_pointer) {
RPCSend snd(socket, "mem_free");
- snd.archive & mem;
+ snd.add(mem);
snd.write();
+
+ mem.device_pointer = 0;
}
-#endif
}
void const_copy_to(const char *name, void *host, size_t size)
@@ -126,79 +125,102 @@ public:
string name_string(name);
- snd.archive & name_string & size;
+ snd.add(name_string);
+ snd.add(size);
snd.write();
snd.write_buffer(host, size);
}
void tex_alloc(const char *name, device_memory& mem, bool interpolation, bool periodic)
{
-#if 0
+ mem.device_pointer = ++mem_counter;
+
RPCSend snd(socket, "tex_alloc");
string name_string(name);
- snd.archive & name_string & width & height & datatype & components & interpolation;
+ snd.add(name_string);
+ snd.add(mem);
+ snd.add(interpolation);
+ snd.add(periodic);
snd.write();
-
- size_t size = width*height*components*datatype_size(datatype);
- snd.write_buffer(host, size);
-
- RPCReceive rcv(socket);
-
- device_ptr mem;
- *rcv.archive & mem;
-
- return mem;
-#endif
+ snd.write_buffer((void*)mem.data_pointer, mem.memory_size());
}
void tex_free(device_memory& mem)
{
-#if 0
- if(mem) {
+ if(mem.device_pointer) {
RPCSend snd(socket, "tex_free");
- snd.archive & mem;
+ snd.add(mem);
snd.write();
+
+ mem.device_pointer = 0;
}
-#endif
}
- void path_trace(int x, int y, int w, int h, device_ptr buffer, device_ptr rng_state, int sample)
+ void task_add(DeviceTask& task)
{
-#if 0
- RPCSend snd(socket, "path_trace");
+ the_task = task;
- snd.archive & x & y & w & h & buffer & rng_state & sample;
+ RPCSend snd(socket, "task_add");
+ snd.add(task);
snd.write();
-#endif
}
- void tonemap(int x, int y, int w, int h, device_ptr rgba, device_ptr buffer, int sample, int resolution)
+ void task_wait()
{
-#if 0
- RPCSend snd(socket, "tonemap");
-
- snd.archive & x & y & w & h & rgba & buffer & sample & resolution;
+ RPCSend snd(socket, "task_wait");
snd.write();
-#endif
- }
- void task_add(DeviceTask& task)
- {
- if(task.type == DeviceTask::TONEMAP)
- tonemap(task.x, task.y, task.w, task.h, task.rgba, task.buffer, task.sample, task.resolution);
- else if(task.type == DeviceTask::PATH_TRACE)
- path_trace(task.x, task.y, task.w, task.h, task.buffer, task.rng_state, task.sample);
- }
+ list<RenderTile> the_tiles;
- void task_wait()
- {
+ /* todo: run this threaded for connecting to multiple clients */
+ for(;;) {
+ RPCReceive rcv(socket);
+ RenderTile tile;
+
+ if(rcv.name == "acquire_tile") {
+ /* todo: watch out for recursive calls! */
+ if(the_task.acquire_tile(this, tile)) { /* write return as bool */
+ the_tiles.push_back(tile);
+
+ RPCSend snd(socket, "acquire_tile");
+ snd.add(tile);
+ snd.write();
+ }
+ else {
+ RPCSend snd(socket, "acquire_tile_none");
+ snd.write();
+ }
+ }
+ else if(rcv.name == "release_tile") {
+ rcv.read(tile);
+
+ for(list<RenderTile>::iterator it = the_tiles.begin(); it != the_tiles.end(); it++) {
+ if(tile.x == it->x && tile.y == it->y && tile.start_sample == it->start_sample) {
+ tile.buffers = it->buffers;
+ the_tiles.erase(it);
+ break;
+ }
+ }
+
+ assert(tile.buffers != NULL);
+
+ the_task.release_tile(tile);
+
+ RPCSend snd(socket, "release_tile");
+ snd.write();
+ }
+ else if(rcv.name == "task_wait_done")
+ break;
+ }
}
void task_cancel()
{
+ RPCSend snd(socket, "task_cancel");
+ snd.write();
}
};
@@ -215,166 +237,309 @@ void device_network_info(vector<DeviceInfo>& devices)
info.description = "Network Device";
info.id = "NETWORK";
info.num = 0;
+ info.advanced_shading = true; /* todo: get this info from device */
+ info.pack_images = false;
devices.push_back(info);
}
-void Device::server_run()
-{
- try
+class DeviceServer {
+public:
+ DeviceServer(Device *device_, tcp::socket& socket_)
+ : device(device_), socket(socket_)
{
- /* starts thread that responds to discovery requests */
- ServerDiscovery discovery;
+ }
- for(;;)
- {
+ void listen()
+ {
+ /* receive remote function calls */
+ for(;;) {
+ RPCReceive rcv(socket);
- /* accept connection */
- boost::asio::io_service io_service;
- tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), SERVER_PORT));
+ if(rcv.name == "stop")
+ break;
- tcp::socket socket(io_service);
- acceptor.accept(socket);
+ process(rcv);
+ }
+ }
- /* receive remote function calls */
- for(;;) {
- RPCReceive rcv(socket);
+protected:
+ void process(RPCReceive& rcv)
+ {
+ // fprintf(stderr, "receive process %s\n", rcv.name.c_str());
- if(rcv.name == "description") {
- string desc = description();
+ if(rcv.name == "mem_alloc") {
+ MemoryType type;
+ network_device_memory mem;
+ device_ptr remote_pointer;
- RPCSend snd(socket);
- snd.archive & desc;
- snd.write();
- }
- else if(rcv.name == "mem_alloc") {
-#if 0
- MemoryType type;
- size_t size;
- device_ptr mem;
+ rcv.read(mem);
+ rcv.read(type);
- *rcv.archive & size & type;
- mem = mem_alloc(size, type);
+ /* todo: CPU needs mem.data_pointer */
- RPCSend snd(socket);
- snd.archive & mem;
- snd.write();
-#endif
- }
- else if(rcv.name == "mem_copy_to") {
-#if 0
- device_ptr mem;
- size_t size;
+ remote_pointer = mem.device_pointer;
- *rcv.archive & mem & size;
+ mem_data[remote_pointer] = vector<uint8_t>();
+ mem_data[remote_pointer].resize(mem.memory_size());
+ if(mem.memory_size())
+ mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
+ else
+ mem.data_pointer = 0;
- vector<char> host_vector(size);
- rcv.read_buffer(&host_vector[0], size);
+ device->mem_alloc(mem, type);
- mem_copy_to(mem, &host_vector[0], size);
-#endif
- }
- else if(rcv.name == "mem_copy_from") {
-#if 0
- device_ptr mem;
- size_t offset, size;
+ ptr_map[remote_pointer] = mem.device_pointer;
+ ptr_imap[mem.device_pointer] = remote_pointer;
+ }
+ else if(rcv.name == "mem_copy_to") {
+ network_device_memory mem;
- *rcv.archive & mem & offset & size;
+ rcv.read(mem);
- vector<char> host_vector(size);
+ device_ptr remote_pointer = mem.device_pointer;
+ mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
- mem_copy_from(&host_vector[0], mem, offset, size);
+ rcv.read_buffer((uint8_t*)mem.data_pointer, mem.memory_size());
- RPCSend snd(socket);
- snd.write();
- snd.write_buffer(&host_vector[0], size);
-#endif
- }
- else if(rcv.name == "mem_zero") {
-#if 0
- device_ptr mem;
- size_t size;
+ mem.device_pointer = ptr_map[remote_pointer];
- *rcv.archive & mem & size;
- mem_zero(mem, size);
-#endif
- }
- else if(rcv.name == "mem_free") {
-#if 0
- device_ptr mem;
+ device->mem_copy_to(mem);
+ }
+ else if(rcv.name == "mem_copy_from") {
+ network_device_memory mem;
+ int y, w, h, elem;
- *rcv.archive & mem;
- mem_free(mem);
-#endif
- }
- else if(rcv.name == "const_copy_to") {
- string name_string;
- size_t size;
+ rcv.read(mem);
+ rcv.read(y);
+ rcv.read(w);
+ rcv.read(h);
+ rcv.read(elem);
- *rcv.archive & name_string & size;
+ device_ptr remote_pointer = mem.device_pointer;
+ mem.device_pointer = ptr_map[remote_pointer];
+ mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
- vector<char> host_vector(size);
- rcv.read_buffer(&host_vector[0], size);
+ device->mem_copy_from(mem, y, w, h, elem);
- const_copy_to(name_string.c_str(), &host_vector[0], size);
- }
- else if(rcv.name == "tex_alloc") {
-#if 0
- string name_string;
- DataType datatype;
- device_ptr mem;
- size_t width, height;
- int components;
- bool interpolation;
+ RPCSend snd(socket);
+ snd.write();
+ snd.write_buffer((uint8_t*)mem.data_pointer, mem.memory_size());
+ }
+ else if(rcv.name == "mem_zero") {
+ network_device_memory mem;
+
+ rcv.read(mem);
+ device_ptr remote_pointer = mem.device_pointer;
+ mem.device_pointer = ptr_map[mem.device_pointer];
+ mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
+
+ device->mem_zero(mem);
+ }
+ else if(rcv.name == "mem_free") {
+ network_device_memory mem;
+ device_ptr remote_pointer;
- *rcv.archive & name_string & width & height & datatype & components & interpolation;
+ rcv.read(mem);
- size_t size = width*height*components*datatype_size(datatype);
+ remote_pointer = mem.device_pointer;
+ mem.device_pointer = ptr_map[mem.device_pointer];
+ ptr_map.erase(remote_pointer);
+ ptr_imap.erase(mem.device_pointer);
+ mem_data.erase(remote_pointer);
- vector<char> host_vector(size);
- rcv.read_buffer(&host_vector[0], size);
+ device->mem_free(mem);
+ }
+ else if(rcv.name == "const_copy_to") {
+ string name_string;
+ size_t size;
- mem = tex_alloc(name_string.c_str(), &host_vector[0], width, height, datatype, components, interpolation);
+ rcv.read(name_string);
+ rcv.read(size);
- RPCSend snd(socket);
- snd.archive & mem;
- snd.write();
-#endif
- }
- else if(rcv.name == "tex_free") {
-#if 0
- device_ptr mem;
+ vector<char> host_vector(size);
+ rcv.read_buffer(&host_vector[0], size);
- *rcv.archive & mem;
- tex_free(mem);
-#endif
- }
- else if(rcv.name == "path_trace") {
-#if 0
- device_ptr buffer, rng_state;
- int x, y, w, h;
- int sample;
-
- *rcv.archive & x & y & w & h & buffer & rng_state & sample;
- path_trace(x, y, w, h, buffer, rng_state, sample);
-#endif
- }
- else if(rcv.name == "tonemap") {
-#if 0
- device_ptr rgba, buffer;
- int x, y, w, h;
- int sample, resolution;
-
- *rcv.archive & x & y & w & h & rgba & buffer & sample & resolution;
- tonemap(x, y, w, h, rgba, buffer, sample, resolution);
-#endif
- }
+ device->const_copy_to(name_string.c_str(), &host_vector[0], size);
+ }
+ else if(rcv.name == "tex_alloc") {
+ network_device_memory mem;
+ string name;
+ bool interpolation;
+ bool periodic;
+ device_ptr remote_pointer;
+
+ rcv.read(name);
+ rcv.read(mem);
+ rcv.read(interpolation);
+ rcv.read(periodic);
+
+ remote_pointer = mem.device_pointer;
+
+ mem_data[remote_pointer] = vector<uint8_t>();
+ mem_data[remote_pointer].resize(mem.memory_size());
+ if(mem.memory_size())
+ mem.data_pointer = (device_ptr)&(mem_data[remote_pointer][0]);
+ else
+ mem.data_pointer = 0;
+
+ rcv.read_buffer((uint8_t*)mem.data_pointer, mem.memory_size());
+
+ device->tex_alloc(name.c_str(), mem, interpolation, periodic);
+
+ ptr_map[remote_pointer] = mem.device_pointer;
+ ptr_imap[mem.device_pointer] = remote_pointer;
+ }
+ else if(rcv.name == "tex_free") {
+ network_device_memory mem;
+ device_ptr remote_pointer;
+
+ rcv.read(mem);
+
+ remote_pointer = mem.device_pointer;
+ mem.device_pointer = ptr_map[mem.device_pointer];
+ ptr_map.erase(remote_pointer);
+ ptr_map.erase(mem.device_pointer);
+ mem_data.erase(remote_pointer);
+
+ device->tex_free(mem);
+ }
+ else if(rcv.name == "task_add") {
+ DeviceTask task;
+
+ rcv.read(task);
+
+ if(task.buffer) task.buffer = ptr_map[task.buffer];
+ if(task.rgba) task.rgba = ptr_map[task.rgba];
+ if(task.shader_input) task.shader_input = ptr_map[task.shader_input];
+ if(task.shader_output) task.shader_output = ptr_map[task.shader_output];
+
+ task.acquire_tile = function_bind(&DeviceServer::task_acquire_tile, this, _1, _2);
+ task.release_tile = function_bind(&DeviceServer::task_release_tile, this, _1);
+ task.update_progress_sample = function_bind(&DeviceServer::task_update_progress_sample, this);
+ task.update_tile_sample = function_bind(&DeviceServer::task_update_tile_sample, this, _1);
+ task.get_cancel = function_bind(&DeviceServer::task_get_cancel, this);
+
+ device->task_add(task);
+ }
+ else if(rcv.name == "task_wait") {
+ device->task_wait();
+
+ RPCSend snd(socket, "task_wait_done");
+ snd.write();
+ }
+ else if(rcv.name == "task_cancel") {
+ device->task_cancel();
+ }
+ }
+
+ bool task_acquire_tile(Device *device, RenderTile& tile)
+ {
+ thread_scoped_lock acquire_lock(acquire_mutex);
+
+ bool result = false;
+
+ RPCSend snd(socket, "acquire_tile");
+ snd.write();
+
+ while(1) {
+ RPCReceive rcv(socket);
+
+ if(rcv.name == "acquire_tile") {
+ rcv.read(tile);
+
+ if(tile.buffer) tile.buffer = ptr_map[tile.buffer];
+ if(tile.rng_state) tile.rng_state = ptr_map[tile.rng_state];
+ if(tile.rgba) tile.rgba = ptr_map[tile.rgba];
+
+ result = true;
+ break;
}
+ else if(rcv.name == "acquire_tile_none")
+ break;
+ else
+ process(rcv);
}
+
+ return result;
+ }
+
+ void task_update_progress_sample()
+ {
+ ; /* skip */
}
- catch(exception& e)
+
+ void task_update_tile_sample(RenderTile&)
{
- cerr << "Network server exception: " << e.what() << endl;
+ ; /* skip */
+ }
+
+ void task_release_tile(RenderTile& tile)
+ {
+ thread_scoped_lock acquire_lock(acquire_mutex);
+
+ if(tile.buffer) tile.buffer = ptr_imap[tile.buffer];
+ if(tile.rng_state) tile.rng_state = ptr_imap[tile.rng_state];
+ if(tile.rgba) tile.rgba = ptr_imap[tile.rgba];
+
+ RPCSend snd(socket, "release_tile");
+ snd.add(tile);
+ snd.write();
+
+ while(1) {
+ RPCReceive rcv(socket);
+
+ if(rcv.name == "release_tile")
+ break;
+ else
+ process(rcv);
+ }
+ }
+
+ bool task_get_cancel()
+ {
+ return false;
+ }
+
+ /* properties */
+ Device *device;
+ tcp::socket& socket;
+
+ /* mapping of remote to local pointer */
+ map<device_ptr, device_ptr> ptr_map;
+ map<device_ptr, device_ptr> ptr_imap;
+ map<device_ptr, vector<uint8_t> > mem_data;
+
+ thread_mutex acquire_mutex;
+
+ /* todo: free memory and device (osl) on network error */
+};
+
+void Device::server_run()
+{
+ try {
+ /* starts thread that responds to discovery requests */
+ ServerDiscovery discovery;
+
+ for(;;) {
+ /* accept connection */
+ boost::asio::io_service io_service;
+ tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), SERVER_PORT));
+
+ tcp::socket socket(io_service);
+ acceptor.accept(socket);
+
+ string remote_address = socket.remote_endpoint().address().to_string();
+ printf("Connected to remote client at: %s\n", remote_address.c_str());
+
+ DeviceServer server(this, socket);
+ server.listen();
+
+ printf("Disconnected.\n");
+ }
+ }
+ catch(exception& e) {
+ fprintf(stderr, "Network server exception: %s\n", e.what());
}
}
diff --git a/intern/cycles/device/device_network.h b/intern/cycles/device/device_network.h
index e3afe46d2b0..b74329888d3 100644
--- a/intern/cycles/device/device_network.h
+++ b/intern/cycles/device/device_network.h
@@ -31,15 +31,17 @@
#include <iostream>
+#include "buffers.h"
+
#include "util_foreach.h"
#include "util_list.h"
+#include "util_map.h"
#include "util_string.h"
CCL_NAMESPACE_BEGIN
using std::cout;
using std::cerr;
-using std::endl;
using std::hex;
using std::setw;
using std::exception;
@@ -51,13 +53,63 @@ static const int DISCOVER_PORT = 5121;
static const string DISCOVER_REQUEST_MSG = "REQUEST_RENDER_SERVER_IP";
static const string DISCOVER_REPLY_MSG = "REPLY_RENDER_SERVER_IP";
-typedef struct RPCSend {
+/* Serialization of device memory */
+
+class network_device_memory : public device_memory
+{
+public:
+ network_device_memory() {}
+ ~network_device_memory() { device_pointer = 0; };
+
+ vector<char> local_data;
+};
+
+/* Remote procedure call Send */
+
+class RPCSend {
+public:
RPCSend(tcp::socket& socket_, const string& name_ = "")
- : name(name_), socket(socket_), archive(archive_stream)
+ : name(name_), socket(socket_), archive(archive_stream), sent(false)
{
archive & name_;
}
+ ~RPCSend()
+ {
+ if(!sent)
+ fprintf(stderr, "Error: RPC %s not sent\n", name.c_str());
+ }
+
+ void add(const device_memory& mem)
+ {
+ archive & mem.data_type & mem.data_elements & mem.data_size;
+ archive & mem.data_width & mem.data_height & mem.device_pointer;
+ }
+
+ template<typename T> void add(const T& data)
+ {
+ archive & data;
+ }
+
+ void add(const DeviceTask& task)
+ {
+ int type = (int)task.type;
+
+ archive & type & task.x & task.y & task.w & task.h;
+ archive & task.rgba & task.buffer & task.sample & task.num_samples;
+ archive & task.resolution & task.offset & task.stride;
+ archive & task.shader_input & task.shader_output & task.shader_eval_type;
+ archive & task.shader_x & task.shader_w;
+ }
+
+ void add(const RenderTile& tile)
+ {
+ archive & tile.x & tile.y & tile.w & tile.h;
+ archive & tile.start_sample & tile.num_samples & tile.sample;
+ archive & tile.resolution & tile.offset & tile.stride;
+ archive & tile.buffer & tile.rng_state & tile.rgba;
+ }
+
void write()
{
boost::system::error_code error;
@@ -84,6 +136,8 @@ typedef struct RPCSend {
if(error.value())
cout << "Network send error: " << error.message() << "\n";
+
+ sent = true;
}
void write_buffer(void *buffer, size_t size)
@@ -98,13 +152,18 @@ typedef struct RPCSend {
cout << "Network send error: " << error.message() << "\n";
}
+protected:
string name;
tcp::socket& socket;
ostringstream archive_stream;
boost::archive::text_oarchive archive;
-} RPCSend;
+ bool sent;
+};
+
+/* Remote procedure call Receive */
-typedef struct RPCReceive {
+class RPCReceive {
+public:
RPCReceive(tcp::socket& socket_)
: socket(socket_), archive_stream(NULL), archive(NULL)
{
@@ -151,6 +210,19 @@ typedef struct RPCReceive {
delete archive_stream;
}
+ void read(network_device_memory& mem)
+ {
+ *archive & mem.data_type & mem.data_elements & mem.data_size;
+ *archive & mem.data_width & mem.data_height & mem.device_pointer;
+
+ mem.data_pointer = 0;
+ }
+
+ template<typename T> void read(T& data)
+ {
+ *archive & data;
+ }
+
void read_buffer(void *buffer, size_t size)
{
size_t len = boost::asio::read(socket, boost::asio::buffer(buffer, size));
@@ -159,12 +231,39 @@ typedef struct RPCReceive {
cout << "Network receive error: buffer size doesn't match expected size\n";
}
+ void read(DeviceTask& task)
+ {
+ int type;
+
+ *archive & type & task.x & task.y & task.w & task.h;
+ *archive & task.rgba & task.buffer & task.sample & task.num_samples;
+ *archive & task.resolution & task.offset & task.stride;
+ *archive & task.shader_input & task.shader_output & task.shader_eval_type;
+ *archive & task.shader_x & task.shader_w;
+
+ task.type = (DeviceTask::Type)type;
+ }
+
+ void read(RenderTile& tile)
+ {
+ *archive & tile.x & tile.y & tile.w & tile.h;
+ *archive & tile.start_sample & tile.num_samples & tile.sample;
+ *archive & tile.resolution & tile.offset & tile.stride;
+ *archive & tile.buffer & tile.rng_state & tile.rgba;
+
+ tile.buffers = NULL;
+ }
+
string name;
+
+protected:
tcp::socket& socket;
string archive_str;
istringstream *archive_stream;
boost::archive::text_iarchive *archive;
-} RPCReceive;
+};
+
+/* Server auto discovery */
class ServerDiscovery {
public:
diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp
index 69287f1a8bd..3ab5d9ee69b 100644
--- a/intern/cycles/device/device_opencl.cpp
+++ b/intern/cycles/device/device_opencl.cpp
@@ -303,7 +303,7 @@ public:
string build_options = " -cl-fast-relaxed-math ";
if(platform_name == "NVIDIA CUDA")
- build_options += "-D__KERNEL_SHADING__ -D__KERNEL_OPENCL_NVIDIA__ -cl-nv-maxrregcount=24 -cl-nv-verbose ";
+ build_options += "-D__KERNEL_OPENCL_NVIDIA__ -cl-nv-maxrregcount=24 -cl-nv-verbose ";
else if(platform_name == "Apple")
build_options += "-D__CL_NO_FLOAT3__ -D__KERNEL_OPENCL_APPLE__ ";
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index b7878e9b00f..e83756b7c8a 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -12,7 +12,8 @@ set(INC_SYS
set(SRC
kernel.cpp
- kernel_optimized.cpp
+ kernel_sse2.cpp
+ kernel_sse3.cpp
kernel.cl
kernel.cu
)
@@ -20,12 +21,12 @@ set(SRC
set(SRC_HEADERS
kernel.h
kernel_accumulate.h
- kernel_attribute.h
kernel_bvh.h
kernel_camera.h
kernel_compat_cpu.h
kernel_compat_cuda.h
kernel_compat_opencl.h
+ kernel_curve.h
kernel_differential.h
kernel_displace.h
kernel_emission.h
@@ -37,6 +38,7 @@ set(SRC_HEADERS
kernel_object.h
kernel_passes.h
kernel_path.h
+ kernel_primitive.h
kernel_projection.h
kernel_random.h
kernel_shader.h
@@ -55,7 +57,9 @@ set(SRC_CLOSURE_HEADERS
closure/bsdf_phong_ramp.h
closure/bsdf_reflection.h
closure/bsdf_refraction.h
+ closure/bsdf_toon.h
closure/bsdf_transparent.h
+ closure/bsdf_util.h
closure/bsdf_ward.h
closure/bsdf_westin.h
closure/emissive.h
@@ -64,7 +68,6 @@ set(SRC_CLOSURE_HEADERS
set(SRC_SVM_HEADERS
svm/svm.h
svm/svm_attribute.h
- svm/svm_bsdf.h
svm/svm_camera.h
svm/svm_closure.h
svm/svm_convert.h
@@ -147,7 +150,8 @@ include_directories(SYSTEM ${INC_SYS})
add_library(cycles_kernel ${SRC} ${SRC_HEADERS} ${SRC_CLOSURE_HEADERS} ${SRC_SVM_HEADERS})
if(WITH_CYCLES_OPTIMIZED_KERNEL)
- set_source_files_properties(kernel_optimized.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_OPTIMIZED_KERNEL_FLAGS}")
+ set_source_files_properties(kernel_sse2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS}")
+ set_source_files_properties(kernel_sse3.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS}")
endif()
if(WITH_CYCLES_CUDA)
diff --git a/intern/cycles/kernel/SConscript b/intern/cycles/kernel/SConscript
index 730f758194e..3a46d10dee1 100644
--- a/intern/cycles/kernel/SConscript
+++ b/intern/cycles/kernel/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/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): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
import sys
import os
import Blender as B
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index cfb6321a918..f26aefe7fd3 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -1,137 +1,296 @@
/*
- * Adapted from Open Shading Language with this license:
+ * Copyright 2011, Blender Foundation.
*
- * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
- * All Rights Reserved.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
*
- * Modifications Copyright 2011, Blender Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * 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.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __OSL_BSDF_H__
-#define __OSL_BSDF_H__
+#include "../closure/bsdf_ashikhmin_velvet.h"
+#include "../closure/bsdf_diffuse.h"
+#include "../closure/bsdf_oren_nayar.h"
+#include "../closure/bsdf_phong_ramp.h"
+#include "../closure/bsdf_diffuse_ramp.h"
+#include "../closure/bsdf_microfacet.h"
+#include "../closure/bsdf_reflection.h"
+#include "../closure/bsdf_refraction.h"
+#include "../closure/bsdf_transparent.h"
+#ifdef __ANISOTROPIC__
+#include "../closure/bsdf_ward.h"
+#endif
+#include "../closure/bsdf_westin.h"
CCL_NAMESPACE_BEGIN
-__device float fresnel_dielectric(float eta, const float3 N,
- const float3 I, float3 *R, float3 *T,
-#ifdef __RAY_DIFFERENTIALS__
- const float3 dIdx, const float3 dIdy,
- float3 *dRdx, float3 *dRdy,
- float3 *dTdx, float3 *dTdy,
-#endif
- bool *is_inside)
+__device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf)
{
- float cos = dot(N, I), neta;
- float3 Nn;
- // compute reflection
- *R = (2 * cos)* N - I;
-#ifdef __RAY_DIFFERENTIALS__
- *dRdx = (2 * dot(N, dIdx)) * N - dIdx;
- *dRdy = (2 * dot(N, dIdy)) * N - dIdy;
+ int label;
+
+#ifdef __OSL__
+ if(kg->osl && sc->prim)
+ return OSLShader::bsdf_sample(sd, sc, randu, randv, *eval, *omega_in, *domega_in, *pdf);
#endif
- // check which side of the surface we are on
- if(cos > 0) {
- // we are on the outside of the surface, going in
- neta = 1 / eta;
- Nn = N;
- *is_inside = false;
- }
- else {
- // we are inside the surface,
- cos = -cos;
- neta = eta;
- Nn = -N;
- *is_inside = true;
- }
- *R = (2 * cos)* Nn - I;
- float arg = 1 -(neta * neta *(1 -(cos * cos)));
- if(arg < 0) {
- *T = make_float3(0.0f, 0.0f, 0.0f);
-#ifdef __RAY_DIFFERENTIALS__
- *dTdx = make_float3(0.0f, 0.0f, 0.0f);
- *dTdy = make_float3(0.0f, 0.0f, 0.0f);
+
+ switch(sc->type) {
+ case CLOSURE_BSDF_DIFFUSE_ID:
+ label = bsdf_diffuse_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;
+#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,
+ 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,
+ 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,
+ 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,
+ 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,
+ 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,
+ 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,
+ eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ break;
+ case CLOSURE_BSDF_MICROFACET_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+ label = bsdf_microfacet_ggx_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_MICROFACET_BECKMANN_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+ label = bsdf_microfacet_beckmann_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;
+#ifdef __ANISOTROPIC__
+ case CLOSURE_BSDF_WARD_ID:
+ label = bsdf_ward_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ break;
#endif
- return 1; // total internal reflection
- }
- else {
- float dnp = sqrtf(arg);
- float nK = (neta * cos)- dnp;
- *T = -(neta * I)+(nK * Nn);
-#ifdef __RAY_DIFFERENTIALS__
- *dTdx = -(neta * dIdx) + ((neta - neta * neta * cos / dnp) * dot(dIdx, Nn)) * Nn;
- *dTdy = -(neta * dIdy) + ((neta - neta * neta * cos / dnp) * dot(dIdy, Nn)) * Nn;
+ case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
+ label = bsdf_ashikhmin_velvet_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ 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,
+ eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ break;
#endif
- // compute Fresnel terms
- float cosTheta1 = cos; // N.R
- float cosTheta2 = -dot(Nn, *T);
- float pPara = (cosTheta1 - eta * cosTheta2)/(cosTheta1 + eta * cosTheta2);
- float pPerp = (eta * cosTheta1 - cosTheta2)/(eta * cosTheta1 + cosTheta2);
- return 0.5f * (pPara * pPara + pPerp * pPerp);
+ default:
+ label = LABEL_NONE;
+ break;
}
+
+ return label;
}
-__device float fresnel_dielectric_cos(float cosi, float eta)
+__device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, float *pdf)
{
- // compute fresnel reflectance without explicitly computing
- // the refracted direction
- float c = fabsf(cosi);
- float g = eta * eta - 1 + c * c;
- if(g > 0) {
- g = sqrtf(g);
- float A = (g - c)/(g + c);
- float B = (c *(g + c)- 1)/(c *(g - c)+ 1);
- return 0.5f * A * A *(1 + B * B);
+ float3 eval;
+
+#ifdef __OSL__
+ if(kg->osl && sc->prim)
+ return OSLShader::bsdf_eval(sd, sc, omega_in, *pdf);
+#endif
+
+ if(dot(sd->Ng, omega_in) >= 0.0f) {
+ switch(sc->type) {
+ case CLOSURE_BSDF_DIFFUSE_ID:
+ eval = bsdf_diffuse_eval_reflect(sc, 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);
+ break;
+ /*case CLOSURE_BSDF_PHONG_RAMP_ID:
+ eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
+ eval = bsdf_diffuse_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;*/
+ case CLOSURE_BSDF_TRANSLUCENT_ID:
+ eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_REFLECTION_ID:
+ eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_REFRACTION_ID:
+ eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_TRANSPARENT_ID:
+ eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_MICROFACET_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+ eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+ eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+#ifdef __ANISOTROPIC__
+ case CLOSURE_BSDF_WARD_ID:
+ eval = bsdf_ward_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+#endif
+ case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
+ eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ 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);
+ break;
+#endif
+ default:
+ eval = make_float3(0.0f, 0.0f, 0.0f);
+ break;
+ }
+ }
+ else {
+ switch(sc->type) {
+ case CLOSURE_BSDF_DIFFUSE_ID:
+ eval = bsdf_diffuse_eval_transmit(sc, 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);
+ break;
+ case CLOSURE_BSDF_TRANSLUCENT_ID:
+ eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_REFLECTION_ID:
+ eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_REFRACTION_ID:
+ eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_TRANSPARENT_ID:
+ eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_MICROFACET_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+ eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+ eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+#ifdef __ANISOTROPIC__
+ case CLOSURE_BSDF_WARD_ID:
+ eval = bsdf_ward_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+#endif
+ case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
+ eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ 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);
+ break;
+#endif
+ default:
+ eval = make_float3(0.0f, 0.0f, 0.0f);
+ break;
+ }
}
- return 1.0f; // TIR(no refracted component)
-}
-__device float fresnel_conductor(float cosi, float eta, float k)
-{
- float tmp_f = eta * eta + k * k;
- float tmp = tmp_f * cosi * cosi;
- float Rparl2 = (tmp - (2.0f * eta * cosi) + 1)/
- (tmp + (2.0f * eta * cosi) + 1);
- float Rperp2 = (tmp_f - (2.0f * eta * cosi) + cosi * cosi)/
- (tmp_f + (2.0f * eta * cosi) + cosi * cosi);
- return(Rparl2 + Rperp2) * 0.5f;
+ return eval;
}
-__device float smooth_step(float edge0, float edge1, float x)
+__device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
{
- float result;
- if(x < edge0) result = 0.0f;
- else if(x >= edge1) result = 1.0f;
- else {
- float t = (x - edge0)/(edge1 - edge0);
- result = (3.0f-2.0f*t)*(t*t);
+#ifdef __OSL__
+ if(kg->osl && sc->prim) {
+ OSLShader::bsdf_blur(sc, roughness);
+ return;
+ }
+#endif
+
+ switch(sc->type) {
+ case CLOSURE_BSDF_DIFFUSE_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;
+ case CLOSURE_BSDF_MICROFACET_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+ bsdf_microfacet_ggx_blur(sc, roughness);
+ break;
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+ bsdf_microfacet_beckmann_blur(sc, roughness);
+ break;
+#ifdef __ANISOTROPIC__
+ case CLOSURE_BSDF_WARD_ID:
+ bsdf_ward_blur(sc, roughness);
+ break;
+#endif
+ case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
+ bsdf_ashikhmin_velvet_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;
+#endif
+ default:
+ break;
}
- return result;
}
CCL_NAMESPACE_END
-#endif /* __OSL_BSDF_H__ */
-
diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h
index 016fd73204e..60f809159ac 100644
--- a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h
+++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h
@@ -134,8 +134,6 @@ __device int bsdf_ashikhmin_velvet_sample(const ShaderClosure *sc, float3 Ng, fl
// TODO: find a better approximation for the retroreflective bounce
*domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
*domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
- *domega_in_dx *= 125.0f;
- *domega_in_dy *= 125.0f;
#endif
}
else
diff --git a/intern/cycles/kernel/closure/bsdf_diffuse.h b/intern/cycles/kernel/closure/bsdf_diffuse.h
index 88b40e3d479..46318ecd138 100644
--- a/intern/cycles/kernel/closure/bsdf_diffuse.h
+++ b/intern/cycles/kernel/closure/bsdf_diffuse.h
@@ -74,8 +74,6 @@ __device int bsdf_diffuse_sample(const ShaderClosure *sc, float3 Ng, float3 I, f
// 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;
- *domega_in_dx *= 125.0f;
- *domega_in_dy *= 125.0f;
#endif
}
else
@@ -126,10 +124,8 @@ __device int bsdf_translucent_sample(const ShaderClosure *sc, float3 Ng, float3
*eval = make_float3(*pdf, *pdf, *pdf);
#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;
- *domega_in_dx *= -125.0f;
- *domega_in_dy *= -125.0f;
+ *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
+ *domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
#endif
}
else {
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index a564b99e759..019ec105111 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -199,12 +199,6 @@ __device int bsdf_microfacet_ggx_sample(const ShaderClosure *sc, float3 Ng, floa
#ifdef __RAY_DIFFERENTIALS__
*domega_in_dx = (2 * dot(m, dIdx)) * m - dIdx;
*domega_in_dy = (2 * dot(m, dIdy)) * m - dIdy;
- // Since there is some blur to this reflection, make the
- // derivatives a bit bigger. In theory this varies with the
- // roughness but the exact relationship is complex and
- // requires more ops than are practical.
- *domega_in_dx *= 10.0f;
- *domega_in_dy *= 10.0f;
#endif
}
}
@@ -251,14 +245,6 @@ __device int bsdf_microfacet_ggx_sample(const ShaderClosure *sc, float3 Ng, floa
// eq. 38 and eq. 17
*pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2;
*eval = make_float3(out, out, out);
-#ifdef __RAY_DIFFERENTIALS__
- // Since there is some blur to this refraction, make the
- // derivatives a bit bigger. In theory this varies with the
- // roughness but the exact relationship is complex and
- // requires more ops than are practical.
- *domega_in_dx *= 10.0f;
- *domega_in_dy *= 10.0f;
-#endif
}
}
}
@@ -430,12 +416,6 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderClosure *sc, float3 Ng,
#ifdef __RAY_DIFFERENTIALS__
*domega_in_dx = (2 * dot(m, dIdx)) * m - dIdx;
*domega_in_dy = (2 * dot(m, dIdy)) * m - dIdy;
- // Since there is some blur to this reflection, make the
- // derivatives a bit bigger. In theory this varies with the
- // roughness but the exact relationship is complex and
- // requires more ops than are practical.
- *domega_in_dx *= 10.0f;
- *domega_in_dy *= 10.0f;
#endif
}
}
@@ -486,14 +466,6 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderClosure *sc, float3 Ng,
// eq. 38 and eq. 17
*pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2;
*eval = make_float3(out, out, out);
-#ifdef __RAY_DIFFERENTIALS__
- // Since there is some blur to this refraction, make the
- // derivatives a bit bigger. In theory this varies with the
- // roughness but the exact relationship is complex and
- // requires more ops than are practical.
- *domega_in_dx *= 10.0f;
- *domega_in_dy *= 10.0f;
-#endif
}
}
}
diff --git a/intern/cycles/kernel/closure/bsdf_oren_nayar.h b/intern/cycles/kernel/closure/bsdf_oren_nayar.h
index 066937da6eb..770f06dddc5 100644
--- a/intern/cycles/kernel/closure/bsdf_oren_nayar.h
+++ b/intern/cycles/kernel/closure/bsdf_oren_nayar.h
@@ -81,8 +81,6 @@ __device int bsdf_oren_nayar_sample(const ShaderClosure *sc, float3 Ng, float3 I
// TODO: find a better approximation for the bounce
*domega_in_dx = (2.0f * dot(sc->N, dIdx)) * sc->N - dIdx;
*domega_in_dy = (2.0f * dot(sc->N, dIdy)) * sc->N - dIdy;
- *domega_in_dx *= 125.0f;
- *domega_in_dy *= 125.0f;
#endif
}
else {
diff --git a/intern/cycles/kernel/closure/bsdf_phong_ramp.h b/intern/cycles/kernel/closure/bsdf_phong_ramp.h
index 575a798aed4..2f57fc1693f 100644
--- a/intern/cycles/kernel/closure/bsdf_phong_ramp.h
+++ b/intern/cycles/kernel/closure/bsdf_phong_ramp.h
@@ -119,15 +119,6 @@ __device int bsdf_phong_ramp_sample(const ShaderClosure *sc, const float3 colors
*pdf = (m_exponent + 1) * common;
float out = cosNI * (m_exponent + 2) * common;
*eval = bsdf_phong_ramp_get_color(sc, colors, cosp) * out;
-
-#ifdef __RAY_DIFFERENTIALS__
- // Since there is some blur to this reflection, make the
- // derivatives a bit bigger. In theory this varies with the
- // exponent but the exact relationship is complex and
- // requires more ops than are practical.
- *domega_in_dx *= 10;
- *domega_in_dy *= 10;
-#endif
}
}
}
diff --git a/intern/cycles/kernel/closure/bsdf_toon.h b/intern/cycles/kernel/closure/bsdf_toon.h
new file mode 100644
index 00000000000..40001bf7531
--- /dev/null
+++ b/intern/cycles/kernel/closure/bsdf_toon.h
@@ -0,0 +1,206 @@
+/*
+ * 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_TOON_H__
+#define __BSDF_TOON_H__
+
+CCL_NAMESPACE_BEGIN
+
+/* DIFFUSE TOON */
+
+__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);
+
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
+}
+
+__device void bsdf_diffuse_toon_blur(ShaderClosure *sc, float roughness)
+{
+}
+
+__device float3 bsdf_toon_get_intensity(float max_angle, float smooth, float angle)
+{
+ float is;
+
+ if(angle < max_angle)
+ is = 1.0f;
+ else if(angle < (max_angle + smooth) && smooth != 0.0f)
+ is = (1.0f - (angle - max_angle)/smooth);
+ else
+ is = 0.0f;
+
+ return make_float3(is, is, is);
+}
+
+__device float bsdf_toon_get_sample_angle(float max_angle, float smooth)
+{
+ return fminf(max_angle + smooth, M_PI_2_F);
+}
+
+__device float3 bsdf_diffuse_toon_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+{
+ float max_angle = sc->data0*M_PI_2_F;
+ float smooth = sc->data1*M_PI_2_F;
+ float angle = safe_acosf(fmaxf(dot(sc->N, omega_in), 0.0f));
+
+ float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
+
+ if(eval.x > 0.0f) {
+ float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
+
+ *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
+ return *pdf * eval;
+ }
+
+ return make_float3(0.0f, 0.0f, 0.0f);
+}
+
+__device float3 bsdf_diffuse_toon_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+{
+ return make_float3(0.0f, 0.0f, 0.0f);
+}
+
+__device int bsdf_diffuse_toon_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 max_angle = sc->data0*M_PI_2_F;
+ float smooth = sc->data1*M_PI_2_F;
+ float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
+ float angle = sample_angle*randu;
+
+ if(sample_angle > 0.0f) {
+ sample_uniform_cone(sc->N, sample_angle, randu, randv, omega_in, pdf);
+
+ if(dot(Ng, *omega_in) > 0.0f) {
+ *eval = *pdf * bsdf_toon_get_intensity(max_angle, smooth, angle);
+
+#ifdef __RAY_DIFFERENTIALS__
+ // TODO: find a better approximation for the bounce
+ *domega_in_dx = (2.0f * dot(sc->N, dIdx)) * sc->N - dIdx;
+ *domega_in_dy = (2.0f * dot(sc->N, dIdy)) * sc->N - dIdy;
+#endif
+ }
+ else
+ *pdf = 0.0f;
+ }
+
+ return LABEL_REFLECT | LABEL_DIFFUSE;
+
+}
+
+/* SPECULAR TOON */
+
+__device int bsdf_specular_toon_setup(ShaderClosure *sc)
+{
+ sc->type = CLOSURE_BSDF_SPECULAR_TOON_ID;
+ sc->data0 = clamp(sc->data0, 0.0f, 1.0f);
+ sc->data1 = clamp(sc->data1, 0.0f, 1.0f);
+
+ return SD_BSDF|SD_BSDF_HAS_EVAL;
+}
+
+__device void bsdf_specular_toon_blur(ShaderClosure *sc, float roughness)
+{
+}
+
+__device float3 bsdf_specular_toon_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+{
+ float max_angle = sc->data0*M_PI_2_F;
+ float smooth = sc->data1*M_PI_2_F;
+ float cosNI = dot(sc->N, omega_in);
+ float cosNO = dot(sc->N, I);
+
+ if(cosNI > 0 && cosNO > 0) {
+ /* reflect the view vector */
+ float3 R = (2 * cosNO) * sc->N - I;
+ float cosRI = dot(R, omega_in);
+
+ float angle = safe_acosf(fmaxf(cosRI, 0.0f));
+
+ float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
+ float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
+
+ *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
+ return *pdf * eval;
+ }
+
+ return make_float3(0.0f, 0.0f, 0.0f);
+}
+
+__device float3 bsdf_specular_toon_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+{
+ return make_float3(0.0f, 0.0f, 0.0f);
+}
+
+__device int bsdf_specular_toon_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 max_angle = sc->data0*M_PI_2_F;
+ float smooth = sc->data1*M_PI_2_F;
+ float cosNO = dot(sc->N, I);
+
+ if(cosNO > 0) {
+ /* reflect the view vector */
+ float3 R = (2 * cosNO) * sc->N - I;
+
+ float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
+ float angle = sample_angle*randu;
+
+ sample_uniform_cone(R, sample_angle, randu, randv, omega_in, pdf);
+
+ if(dot(Ng, *omega_in) > 0.0f) {
+ float cosNI = dot(sc->N, *omega_in);
+
+ /* make sure the direction we chose is still in the right hemisphere */
+ if(cosNI > 0) {
+ *eval = *pdf * bsdf_toon_get_intensity(max_angle, smooth, angle);
+
+#ifdef __RAY_DIFFERENTIALS__
+ *domega_in_dx = (2 * dot(sc->N, dIdx)) * sc->N - dIdx;
+ *domega_in_dy = (2 * dot(sc->N, dIdy)) * sc->N - dIdy;
+#endif
+ }
+ else
+ *pdf = 0.0f;
+ }
+ else
+ *pdf = 0.0f;
+ }
+
+ return LABEL_GLOSSY | LABEL_REFLECT;
+}
+
+CCL_NAMESPACE_END
+
+#endif /* __BSDF_TOON_H__ */
+
diff --git a/intern/cycles/kernel/closure/bsdf_util.h b/intern/cycles/kernel/closure/bsdf_util.h
new file mode 100644
index 00000000000..cfb6321a918
--- /dev/null
+++ b/intern/cycles/kernel/closure/bsdf_util.h
@@ -0,0 +1,137 @@
+/*
+ * 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 __OSL_BSDF_H__
+#define __OSL_BSDF_H__
+
+CCL_NAMESPACE_BEGIN
+
+__device float fresnel_dielectric(float eta, const float3 N,
+ const float3 I, float3 *R, float3 *T,
+#ifdef __RAY_DIFFERENTIALS__
+ const float3 dIdx, const float3 dIdy,
+ float3 *dRdx, float3 *dRdy,
+ float3 *dTdx, float3 *dTdy,
+#endif
+ bool *is_inside)
+{
+ float cos = dot(N, I), neta;
+ float3 Nn;
+ // compute reflection
+ *R = (2 * cos)* N - I;
+#ifdef __RAY_DIFFERENTIALS__
+ *dRdx = (2 * dot(N, dIdx)) * N - dIdx;
+ *dRdy = (2 * dot(N, dIdy)) * N - dIdy;
+#endif
+ // check which side of the surface we are on
+ if(cos > 0) {
+ // we are on the outside of the surface, going in
+ neta = 1 / eta;
+ Nn = N;
+ *is_inside = false;
+ }
+ else {
+ // we are inside the surface,
+ cos = -cos;
+ neta = eta;
+ Nn = -N;
+ *is_inside = true;
+ }
+ *R = (2 * cos)* Nn - I;
+ float arg = 1 -(neta * neta *(1 -(cos * cos)));
+ if(arg < 0) {
+ *T = make_float3(0.0f, 0.0f, 0.0f);
+#ifdef __RAY_DIFFERENTIALS__
+ *dTdx = make_float3(0.0f, 0.0f, 0.0f);
+ *dTdy = make_float3(0.0f, 0.0f, 0.0f);
+#endif
+ return 1; // total internal reflection
+ }
+ else {
+ float dnp = sqrtf(arg);
+ float nK = (neta * cos)- dnp;
+ *T = -(neta * I)+(nK * Nn);
+#ifdef __RAY_DIFFERENTIALS__
+ *dTdx = -(neta * dIdx) + ((neta - neta * neta * cos / dnp) * dot(dIdx, Nn)) * Nn;
+ *dTdy = -(neta * dIdy) + ((neta - neta * neta * cos / dnp) * dot(dIdy, Nn)) * Nn;
+#endif
+ // compute Fresnel terms
+ float cosTheta1 = cos; // N.R
+ float cosTheta2 = -dot(Nn, *T);
+ float pPara = (cosTheta1 - eta * cosTheta2)/(cosTheta1 + eta * cosTheta2);
+ float pPerp = (eta * cosTheta1 - cosTheta2)/(eta * cosTheta1 + cosTheta2);
+ return 0.5f * (pPara * pPara + pPerp * pPerp);
+ }
+}
+
+__device float fresnel_dielectric_cos(float cosi, float eta)
+{
+ // compute fresnel reflectance without explicitly computing
+ // the refracted direction
+ float c = fabsf(cosi);
+ float g = eta * eta - 1 + c * c;
+ if(g > 0) {
+ g = sqrtf(g);
+ float A = (g - c)/(g + c);
+ float B = (c *(g + c)- 1)/(c *(g - c)+ 1);
+ return 0.5f * A * A *(1 + B * B);
+ }
+ return 1.0f; // TIR(no refracted component)
+}
+
+__device float fresnel_conductor(float cosi, float eta, float k)
+{
+ float tmp_f = eta * eta + k * k;
+ float tmp = tmp_f * cosi * cosi;
+ float Rparl2 = (tmp - (2.0f * eta * cosi) + 1)/
+ (tmp + (2.0f * eta * cosi) + 1);
+ float Rperp2 = (tmp_f - (2.0f * eta * cosi) + cosi * cosi)/
+ (tmp_f + (2.0f * eta * cosi) + cosi * cosi);
+ return(Rparl2 + Rperp2) * 0.5f;
+}
+
+__device float smooth_step(float edge0, float edge1, float x)
+{
+ float result;
+ if(x < edge0) result = 0.0f;
+ else if(x >= edge1) result = 1.0f;
+ else {
+ float t = (x - edge0)/(edge1 - edge0);
+ result = (3.0f-2.0f*t)*(t*t);
+ }
+ return result;
+}
+
+CCL_NAMESPACE_END
+
+#endif /* __OSL_BSDF_H__ */
+
diff --git a/intern/cycles/kernel/closure/bsdf_ward.h b/intern/cycles/kernel/closure/bsdf_ward.h
index dbddcf20dba..c95b0e3f7a0 100644
--- a/intern/cycles/kernel/closure/bsdf_ward.h
+++ b/intern/cycles/kernel/closure/bsdf_ward.h
@@ -182,12 +182,6 @@ __device int bsdf_ward_sample(const ShaderClosure *sc, float3 Ng, float3 I, floa
#ifdef __RAY_DIFFERENTIALS__
*domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
*domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
- // Since there is some blur to this reflection, make the
- // derivatives a bit bigger. In theory this varies with the
- // roughness but the exact relationship is complex and
- // requires more ops than are practical.
- *domega_in_dx *= 10.0f;
- *domega_in_dy *= 10.0f;
#endif
}
}
diff --git a/intern/cycles/kernel/closure/bsdf_westin.h b/intern/cycles/kernel/closure/bsdf_westin.h
index 968173208b4..29bfa85bcc1 100644
--- a/intern/cycles/kernel/closure/bsdf_westin.h
+++ b/intern/cycles/kernel/closure/bsdf_westin.h
@@ -108,14 +108,6 @@ __device int bsdf_westin_backscatter_sample(const ShaderClosure *sc, float3 Ng,
*pdf = 0.5f * M_1_PI_F * powf(cosTheta, m_invroughness);
*pdf = (m_invroughness + 1) * (*pdf);
*eval = make_float3(*pdf, *pdf, *pdf);
-#ifdef __RAY_DIFFERENTIALS__
- // Since there is some blur to this reflection, make the
- // derivatives a bit bigger. In theory this varies with the
- // exponent but the exact relationship is complex and
- // requires more ops than are practical.
- *domega_in_dx *= 10.0f;
- *domega_in_dy *= 10.0f;
-#endif
}
}
}
@@ -176,8 +168,6 @@ __device int bsdf_westin_sheen_sample(const ShaderClosure *sc, float3 Ng, float3
// 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;
- *domega_in_dx *= 125.0f;
- *domega_in_dy *= 125.0f;
#endif
}
else {
diff --git a/intern/cycles/kernel/closure/emissive.h b/intern/cycles/kernel/closure/emissive.h
index cbf9d9a4efb..33b1b695a9a 100644
--- a/intern/cycles/kernel/closure/emissive.h
+++ b/intern/cycles/kernel/closure/emissive.h
@@ -49,17 +49,12 @@ __device void emissive_sample(const float3 Ng, float randu, float randv,
/* todo: not implemented and used yet */
}
-__device float3 emissive_eval(const float3 Ng, const float3 I)
+__device float3 emissive_simple_eval(const float3 Ng, const float3 I)
{
float res = emissive_pdf(Ng, I);
return make_float3(res, res, res);
}
-__device float3 svm_emissive_eval(ShaderData *sd, ShaderClosure *sc)
-{
- return emissive_eval(sd->Ng, sd->I);
-}
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/closure/volume.h b/intern/cycles/kernel/closure/volume.h
index 734f9111ab6..0b553f38a25 100644
--- a/intern/cycles/kernel/closure/volume.h
+++ b/intern/cycles/kernel/closure/volume.h
@@ -53,8 +53,13 @@ __device float3 volume_transparent_eval_phase(const ShaderClosure *sc, const flo
/* VOLUME CLOSURE */
-__device float3 volume_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
+__device float3 volume_eval_phase(KernelGlobals *kg, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
{
+#ifdef __OSL__
+ if(kg->osl && sc->prim)
+ return OSLShader::volume_eval_phase(sc, omega_in, omega_out);
+#endif
+
float3 eval;
switch(sc->type) {
diff --git a/intern/cycles/kernel/kernel.h b/intern/cycles/kernel/kernel.h
index 26c0bcd6d1a..20ea5a61906 100644
--- a/intern/cycles/kernel/kernel.h
+++ b/intern/cycles/kernel/kernel.h
@@ -44,11 +44,18 @@ void kernel_cpu_shader(KernelGlobals *kg, uint4 *input, float4 *output,
int type, int i);
#ifdef WITH_OPTIMIZED_KERNEL
-void kernel_cpu_optimized_path_trace(KernelGlobals *kg, float *buffer, unsigned int *rng_state,
+void kernel_cpu_sse2_path_trace(KernelGlobals *kg, float *buffer, unsigned int *rng_state,
int sample, int x, int y, int offset, int stride);
-void kernel_cpu_optimized_tonemap(KernelGlobals *kg, uchar4 *rgba, float *buffer,
+void kernel_cpu_sse2_tonemap(KernelGlobals *kg, uchar4 *rgba, float *buffer,
int sample, int resolution, int x, int y, int offset, int stride);
-void kernel_cpu_optimized_shader(KernelGlobals *kg, uint4 *input, float4 *output,
+void kernel_cpu_sse2_shader(KernelGlobals *kg, uint4 *input, float4 *output,
+ int type, int i);
+
+void kernel_cpu_sse3_path_trace(KernelGlobals *kg, float *buffer, unsigned int *rng_state,
+ int sample, int x, int y, int offset, int stride);
+void kernel_cpu_sse3_tonemap(KernelGlobals *kg, uchar4 *rgba, float *buffer,
+ int sample, int resolution, int x, int y, int offset, int stride);
+void kernel_cpu_sse3_shader(KernelGlobals *kg, uint4 *input, float4 *output,
int type, int i);
#endif
diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h
index d99beb8905a..1cf230634fc 100644
--- a/intern/cycles/kernel/kernel_accumulate.h
+++ b/intern/cycles/kernel/kernel_accumulate.h
@@ -133,6 +133,10 @@ __device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
+ L->path_diffuse = make_float3(0.0f, 0.0f, 0.0f);
+ L->path_glossy = make_float3(0.0f, 0.0f, 0.0f);
+ L->path_transmission = make_float3(0.0f, 0.0f, 0.0f);
+
L->emission = make_float3(0.0f, 0.0f, 0.0f);
L->background = make_float3(0.0f, 0.0f, 0.0f);
L->ao = make_float3(0.0f, 0.0f, 0.0f);
@@ -156,11 +160,11 @@ __device_inline void path_radiance_bsdf_bounce(PathRadiance *L, float3 *throughp
/* first on directly visible surface */
float3 value = *throughput*inverse_pdf;
- L->indirect_diffuse = bsdf_eval->diffuse*value;
- L->indirect_glossy = bsdf_eval->glossy*value;
- L->indirect_transmission = bsdf_eval->transmission*value;
+ L->path_diffuse = bsdf_eval->diffuse*value;
+ L->path_glossy = bsdf_eval->glossy*value;
+ L->path_transmission = bsdf_eval->transmission*value;
- *throughput = L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission;
+ *throughput = L->path_diffuse + L->path_glossy + L->path_transmission;
L->direct_throughput = *throughput;
}
@@ -216,7 +220,7 @@ __device_inline void path_radiance_accum_ao(PathRadiance *L, float3 throughput,
#endif
}
-__device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughput, BsdfEval *bsdf_eval, float3 shadow, int bounce, bool is_lamp)
+__device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughput, BsdfEval *bsdf_eval, float3 shadow, float shadow_fac, int bounce, bool is_lamp)
{
#ifdef __PASSES__
if(L->use_light_pass) {
@@ -229,9 +233,9 @@ __device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughpu
if(is_lamp) {
float3 sum = throughput*(bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission);
- L->shadow.x += shadow.x;
- L->shadow.y += shadow.y;
- L->shadow.z += shadow.z;
+ L->shadow.x += shadow.x*shadow_fac;
+ L->shadow.y += shadow.y*shadow_fac;
+ L->shadow.z += shadow.z*shadow_fac;
L->shadow.w += average(sum);
}
}
@@ -266,22 +270,45 @@ __device_inline void path_radiance_accum_background(PathRadiance *L, float3 thro
#endif
}
-__device_inline float3 path_radiance_sum(KernelGlobals *kg, PathRadiance *L)
+__device_inline void path_radiance_sum_indirect(PathRadiance *L)
{
#ifdef __PASSES__
+ /* this division is a bit ugly, but means we only have to keep track of
+ * only a single throughput further along the path, here we recover just
+ * the indirect parth that is not influenced by any particular BSDF type */
if(L->use_light_pass) {
- /* this division is a bit ugly, but means we only have to keep track of
- * only a single throughput further along the path, here we recover just
- * the indirect parth that is not influenced by any particular BSDF type */
L->direct_emission = safe_divide_color(L->direct_emission, L->direct_throughput);
- L->direct_diffuse += L->indirect_diffuse*L->direct_emission;
- L->direct_glossy += L->indirect_glossy*L->direct_emission;
- L->direct_transmission += L->indirect_transmission*L->direct_emission;
+ L->direct_diffuse += L->path_diffuse*L->direct_emission;
+ L->direct_glossy += L->path_glossy*L->direct_emission;
+ L->direct_transmission += L->path_transmission*L->direct_emission;
L->indirect = safe_divide_color(L->indirect, L->direct_throughput);
- L->indirect_diffuse *= L->indirect;
- L->indirect_glossy *= L->indirect;
- L->indirect_transmission *= L->indirect;
+ L->indirect_diffuse += L->path_diffuse*L->indirect;
+ L->indirect_glossy += L->path_glossy*L->indirect;
+ L->indirect_transmission += L->path_transmission*L->indirect;
+ }
+#endif
+}
+
+__device_inline void path_radiance_reset_indirect(PathRadiance *L)
+{
+#ifdef __PASSES__
+ if(L->use_light_pass) {
+ L->path_diffuse = make_float3(0.0f, 0.0f, 0.0f);
+ L->path_glossy = make_float3(0.0f, 0.0f, 0.0f);
+ L->path_transmission = make_float3(0.0f, 0.0f, 0.0f);
+
+ L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
+ L->indirect = make_float3(0.0f, 0.0f, 0.0f);
+ }
+#endif
+}
+
+__device_inline float3 path_radiance_sum(KernelGlobals *kg, PathRadiance *L)
+{
+#ifdef __PASSES__
+ if(L->use_light_pass) {
+ path_radiance_sum_indirect(L);
float3 L_sum = L->emission
+ L->direct_diffuse + L->direct_glossy + L->direct_transmission
diff --git a/intern/cycles/kernel/kernel_attribute.h b/intern/cycles/kernel/kernel_attribute.h
deleted file mode 100644
index b7ad731c883..00000000000
--- a/intern/cycles/kernel/kernel_attribute.h
+++ /dev/null
@@ -1,50 +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.
- */
-
-#ifndef __KERNEL_ATTRIBUTE_CL__
-#define __KERNEL_ATTRIBUTE_CL__
-
-CCL_NAMESPACE_BEGIN
-
-/* note: declared in kernel.h, have to add it here because kernel.h is not available */
-bool kernel_osl_use(KernelGlobals *kg);
-
-__device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id)
-{
-#ifdef __OSL__
- if (kg->osl) {
- return OSLShader::find_attribute(kg, sd, id);
- }
- else
-#endif
- {
- /* for SVM, find attribute by unique id */
- uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
- uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
-
- while(attr_map.x != id)
- attr_map = kernel_tex_fetch(__attributes_map, ++attr_offset);
-
- /* return result */
- return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
- }
-}
-
-CCL_NAMESPACE_END
-
-#endif /* __KERNEL_ATTRIBUTE_CL__ */
diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h
index d70485fd6cf..2b9ebf35d0c 100644
--- a/intern/cycles/kernel/kernel_bvh.h
+++ b/intern/cycles/kernel/kernel_bvh.h
@@ -126,21 +126,21 @@ __device_inline void bvh_node_intersect(KernelGlobals *kg,
/* intersect ray against child nodes */
float3 ood = P * idir;
- float c0lox = n0xy.x * idir.x - ood.x;
- float c0hix = n0xy.y * idir.x - ood.x;
- float c0loy = n0xy.z * idir.y - ood.y;
- float c0hiy = n0xy.w * idir.y - ood.y;
- float c0loz = nz.x * idir.z - ood.z;
- float c0hiz = nz.y * idir.z - ood.z;
+ NO_EXTENDED_PRECISION float c0lox = n0xy.x * idir.x - ood.x;
+ NO_EXTENDED_PRECISION float c0hix = n0xy.y * idir.x - ood.x;
+ NO_EXTENDED_PRECISION float c0loy = n0xy.z * idir.y - ood.y;
+ NO_EXTENDED_PRECISION float c0hiy = n0xy.w * idir.y - ood.y;
+ NO_EXTENDED_PRECISION float c0loz = nz.x * idir.z - ood.z;
+ NO_EXTENDED_PRECISION float c0hiz = nz.y * idir.z - ood.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);
- float c1loz = nz.z * idir.z - ood.z;
- float c1hiz = nz.w * idir.z - ood.z;
- float c1lox = n1xy.x * idir.x - ood.x;
- float c1hix = n1xy.y * idir.x - ood.x;
- float c1loy = n1xy.z * idir.y - ood.y;
- float c1hiy = n1xy.w * idir.y - ood.y;
+ NO_EXTENDED_PRECISION float c1loz = nz.z * idir.z - ood.z;
+ NO_EXTENDED_PRECISION float c1hiz = nz.w * idir.z - ood.z;
+ NO_EXTENDED_PRECISION float c1lox = n1xy.x * idir.x - ood.x;
+ NO_EXTENDED_PRECISION float c1hix = n1xy.y * idir.x - ood.x;
+ NO_EXTENDED_PRECISION float c1loy = n1xy.z * idir.y - ood.y;
+ NO_EXTENDED_PRECISION float c1hiy = n1xy.w * idir.y - ood.y;
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);
@@ -205,7 +205,457 @@ __device_inline void bvh_triangle_intersect(KernelGlobals *kg, Intersection *ise
}
}
-__device_inline bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect)
+#ifdef __HAIR__
+__device_inline void curvebounds(float *lower, float *upper, float *extremta, float *extrema, float *extremtb, float *extremb, float p0, float p1, float p2, float p3)
+{
+ float halfdiscroot = (p2 * p2 - 3 * p3 * p1);
+ float ta = -1.0f;
+ float tb = -1.0f;
+ *extremta = -1.0f;
+ *extremtb = -1.0f;
+ *upper = p0;
+ *lower = p0 + p1 + p2 + p3;
+ *extrema = *upper;
+ *extremb = *lower;
+ if(*lower >= *upper) {
+ *upper = *lower;
+ *lower = p0;
+ }
+
+ if(halfdiscroot >= 0) {
+ halfdiscroot = sqrt(halfdiscroot);
+ ta = (-p2 - halfdiscroot) / (3 * p3);
+ tb = (-p2 + halfdiscroot) / (3 * p3);
+ }
+
+ float t2;
+ float t3;
+ if(ta > 0.0f && ta < 1.0f) {
+ t2 = ta * ta;
+ t3 = t2 * ta;
+ *extremta = ta;
+ *extrema = p3 * t3 + p2 * t2 + p1 * ta + p0;
+ if(*extrema > *upper) {
+ *upper = *extrema;
+ }
+ if(*extrema < *lower) {
+ *lower = *extrema;
+ }
+ }
+ if(tb > 0.0f && tb < 1.0f) {
+ t2 = tb * tb;
+ t3 = t2 * tb;
+ *extremtb = tb;
+ *extremb = p3 * t3 + p2 * t2 + p1 * tb + p0;
+ if(*extremb >= *upper) {
+ *upper = *extremb;
+ }
+ if(*extremb <= *lower) {
+ *lower = *extremb;
+ }
+ }
+}
+
+__device_inline void bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersection *isect,
+ float3 P, float3 idir, uint visibility, int object, int curveAddr, int segment)
+{
+ int depth = kernel_data.curve_kernel_data.subdivisions;
+
+ /* curve Intersection check */
+ float3 dir = 1.0f/idir;
+
+ int flags = kernel_data.curve_kernel_data.curveflags;
+
+ int prim = kernel_tex_fetch(__prim_index, curveAddr);
+
+ float3 curve_coef[4];
+ float r_st,r_en;
+
+ /*obtain curve parameters*/
+ {
+ /*ray transform created - this shold be created at beginning of intersection loop*/
+ Transform htfm;
+ float d = sqrtf(dir.x * dir.x + dir.z * dir.z);
+ htfm = make_transform(
+ dir.z / d, 0, -dir.x /d, 0,
+ -dir.x * dir.y /d, d, -dir.y * dir.z /d, 0,
+ dir.x, dir.y, dir.z, 0,
+ 0, 0, 0, 1) * make_transform(
+ 1, 0, 0, -P.x,
+ 0, 1, 0, -P.y,
+ 0, 0, 1, -P.z,
+ 0, 0, 0, 1);
+
+ float4 v00 = kernel_tex_fetch(__curves, prim);
+
+ int k0 = __float_as_int(v00.x) + segment;
+ int k1 = k0 + 1;
+
+ int ka = max(k0 - 1,__float_as_int(v00.x));
+ int kb = min(k1 + 1,__float_as_int(v00.x) + __float_as_int(v00.y) - 1);
+
+ float4 P0 = kernel_tex_fetch(__curve_keys, ka);
+ float4 P1 = kernel_tex_fetch(__curve_keys, k0);
+ float4 P2 = kernel_tex_fetch(__curve_keys, k1);
+ float4 P3 = kernel_tex_fetch(__curve_keys, kb);
+
+ float3 p0 = transform_point(&htfm, float4_to_float3(P0));
+ float3 p1 = transform_point(&htfm, float4_to_float3(P1));
+ float3 p2 = transform_point(&htfm, float4_to_float3(P2));
+ float3 p3 = transform_point(&htfm, float4_to_float3(P3));
+
+ float fc = 0.71f;
+ curve_coef[0] = p1;
+ curve_coef[1] = -fc*p0 + fc*p2;
+ curve_coef[2] = 2.0f * fc * p0 + (fc - 3.0f) * p1 + (3.0f - 2.0f * fc) * p2 - fc * p3;
+ curve_coef[3] = -fc * p0 + (2.0f - fc) * p1 + (fc - 2.0f) * p2 + fc * p3;
+ r_st = P1.w;
+ r_en = P2.w;
+ }
+
+
+ float r_curr = max(r_st, r_en);
+
+ /*find bounds - this is slow for cubic curves*/
+ float upper,lower;
+ float xextrem[4];
+ curvebounds(&lower, &upper, &xextrem[0], &xextrem[1], &xextrem[2], &xextrem[3], curve_coef[0].x, curve_coef[1].x, curve_coef[2].x, curve_coef[3].x);
+ if(lower > r_curr || upper < -r_curr)
+ return;
+
+ float yextrem[4];
+ curvebounds(&lower, &upper, &yextrem[0], &yextrem[1], &yextrem[2], &yextrem[3], curve_coef[0].y, curve_coef[1].y, curve_coef[2].y, curve_coef[3].y);
+ if(lower > r_curr || upper < -r_curr)
+ return;
+
+ float zextrem[4];
+ curvebounds(&lower, &upper, &zextrem[0], &zextrem[1], &zextrem[2], &zextrem[3], curve_coef[0].z, curve_coef[1].z, curve_coef[2].z, curve_coef[3].z);
+ if(lower - r_curr > isect->t || upper + r_curr < 0.0f)
+ return;
+
+ /*setup recurrent loop*/
+ int level = 1 << depth;
+ int tree = 0;
+ float resol = 1.0f / (float)level;
+
+ /*begin loop*/
+ while(!(tree >> (depth))) {
+ float i_st = tree * resol;
+ float i_en = i_st + (level * resol);
+ float3 p_st = ((curve_coef[3] * i_st + curve_coef[2]) * i_st + curve_coef[1]) * i_st + curve_coef[0];
+ float3 p_en = ((curve_coef[3] * i_en + curve_coef[2]) * i_en + curve_coef[1]) * i_en + curve_coef[0];
+
+ float bminx = min(p_st.x, p_en.x);
+ float bmaxx = max(p_st.x, p_en.x);
+ float bminy = min(p_st.y, p_en.y);
+ float bmaxy = max(p_st.y, p_en.y);
+ float bminz = min(p_st.z, p_en.z);
+ float bmaxz = max(p_st.z, p_en.z);
+
+ if(xextrem[0] >= i_st && xextrem[0] <= i_en) {
+ bminx = min(bminx,xextrem[1]);
+ bmaxx = max(bmaxx,xextrem[1]);
+ }
+ if(xextrem[2] >= i_st && xextrem[2] <= i_en) {
+ bminx = min(bminx,xextrem[3]);
+ bmaxx = max(bmaxx,xextrem[3]);
+ }
+ if(yextrem[0] >= i_st && yextrem[0] <= i_en) {
+ bminy = min(bminy,yextrem[1]);
+ bmaxy = max(bmaxy,yextrem[1]);
+ }
+ if(yextrem[2] >= i_st && yextrem[2] <= i_en) {
+ bminy = min(bminy,yextrem[3]);
+ bmaxy = max(bmaxy,yextrem[3]);
+ }
+ if(zextrem[0] >= i_st && zextrem[0] <= i_en) {
+ bminz = min(bminz,zextrem[1]);
+ bmaxz = max(bmaxz,zextrem[1]);
+ }
+ if(zextrem[2] >= i_st && zextrem[2] <= i_en) {
+ bminz = min(bminz,zextrem[3]);
+ bmaxz = max(bmaxz,zextrem[3]);
+ }
+
+ float r1 = r_st + (r_en - r_st) * i_st;
+ float r2 = r_st + (r_en - r_st) * i_en;
+ r_curr = max(r1, r2);
+
+ if (bminz - r_curr > isect->t || bmaxz + r_curr < 0.0f|| bminx > r_curr || bmaxx < -r_curr || bminy > r_curr || bmaxy < -r_curr) {
+ /* the bounding box does not overlap the square centered at O.*/
+ tree += level;
+ level = tree & -tree;
+ }
+ else if (level == 1) {
+
+ /* the maximum recursion depth is reached.
+ * check if dP0.(Q-P0)>=0 and dPn.(Pn-Q)>=0.
+ * dP* is reversed if necessary.*/
+ float t = isect->t;
+ float u = 0.0f;
+ if(flags & CURVE_KN_RIBBONS) {
+ float3 tg = (p_en - p_st);
+ float w = tg.x * tg.x + tg.y * tg.y;
+ 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);
+
+ /* compute u on the curve segment.*/
+ u = i_st * (1 - w) + i_en * w;
+ r_curr = r_st + (r_en - r_st) * u;
+ /* compare x-y distances.*/
+ float3 p_curr = ((curve_coef[3] * u + curve_coef[2]) * u + curve_coef[1]) * u + curve_coef[0];
+
+ float3 dp_st = (3 * curve_coef[3] * i_st + 2 * curve_coef[2]) * i_st + curve_coef[1];
+ if (dot(tg, dp_st)< 0)
+ dp_st *= -1;
+ if (dot(dp_st, -p_st) + p_curr.z * dp_st.z < 0) {
+ tree++;
+ level = tree & -tree;
+ continue;
+ }
+ float3 dp_en = (3 * curve_coef[3] * i_en + 2 * curve_coef[2]) * i_en + curve_coef[1];
+ if (dot(tg, dp_en) < 0)
+ dp_en *= -1;
+ if (dot(dp_en, p_en) - p_curr.z * dp_en.z < 0) {
+ tree++;
+ level = tree & -tree;
+ continue;
+ }
+
+ if (p_curr.x * p_curr.x + p_curr.y * p_curr.y >= r_curr * r_curr || p_curr.z <= 0.0f) {
+ tree++;
+ level = tree & -tree;
+ continue;
+ }
+ /* compare z distances.*/
+ if (isect->t < p_curr.z) {
+ tree++;
+ level = tree & -tree;
+ continue;
+ }
+ t = p_curr.z;
+ }
+ else {
+ float l = len(p_en - p_st);
+ float3 tg = (p_en - p_st) / l;
+ float gd = (r2 - r1) / l;
+ float difz = -dot(p_st,tg);
+ float cyla = 1.0f - (tg.z * tg.z * (1 + gd*gd));
+ float halfb = (-p_st.z - tg.z*(difz + gd*(difz*gd + r1)));
+ float tcentre = -halfb/cyla;
+ float zcentre = difz + (tg.z * tcentre);
+ float3 tdif = - p_st;
+ tdif.z += tcentre;
+ float tdifz = dot(tdif,tg);
+ float tb = 2*(tdif.z - tg.z*(tdifz + gd*(tdifz*gd + r1)));
+ float tc = dot(tdif,tdif) - tdifz * tdifz * (1 + gd*gd) - r1*r1 - 2*r1*tdifz*gd;
+ float td = tb*tb - 4*cyla*tc;
+ if (td < 0.0f){
+ tree++;
+ level = tree & -tree;
+ continue;
+ }
+
+ float rootd = sqrtf(td);
+ float correction = ((-tb - rootd)/(2*cyla));
+ t = tcentre + correction;
+ float w = (zcentre + (tg.z * correction))/l;
+
+ float3 dp_st = (3 * curve_coef[3] * i_st + 2 * curve_coef[2]) * i_st + curve_coef[1];
+ if (dot(tg, dp_st)< 0)
+ dp_st *= -1;
+ float3 dp_en = (3 * curve_coef[3] * i_en + 2 * curve_coef[2]) * i_en + curve_coef[1];
+ if (dot(tg, dp_en) < 0)
+ dp_en *= -1;
+
+
+ if(flags & CURVE_KN_BACKFACING && (dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 || isect->t < t || t <= 0.0f)) {
+ correction = ((-tb + rootd)/(2*cyla));
+ t = tcentre + correction;
+ w = (zcentre + (tg.z * correction))/l;
+ }
+
+ 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;
+ }
+
+ w = clamp((float)w, 0.0f, 1.0f);
+ /* compute u on the curve segment.*/
+ u = i_st * (1 - w) + i_en * w;
+
+ }
+ /* we found a new intersection.*/
+#ifdef __VISIBILITY_FLAG__
+ /* visibility flag test. we do it here under the assumption
+ * that most triangles are culled by node flags */
+ if(kernel_tex_fetch(__prim_visibility, curveAddr) & visibility)
+#endif
+ {
+ /* record intersection */
+ isect->prim = curveAddr;
+ isect->segment = segment;
+ isect->object = object;
+ isect->u = u;
+ isect->v = 0.0f;
+ isect->t = t;
+ }
+
+ tree++;
+ level = tree & -tree;
+ }
+ else {
+ /* split the curve into two curves and process */
+ level = level >> 1;
+ }
+ }
+}
+
+__device_inline void bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
+ float3 P, float3 idir, uint visibility, int object, int curveAddr, int segment)
+{
+ /* curve Intersection check */
+
+ int flags = kernel_data.curve_kernel_data.curveflags;
+
+ int prim = kernel_tex_fetch(__prim_index, curveAddr);
+ float4 v00 = kernel_tex_fetch(__curves, prim);
+
+ int k0 = __float_as_int(v00.x) + segment;
+ int k1 = k0 + 1;
+
+ float4 P1 = kernel_tex_fetch(__curve_keys, k0);
+ float4 P2 = kernel_tex_fetch(__curve_keys, k1);
+
+ float r1 = P1.w;
+ float r2 = P2.w;
+ float mr = max(r1,r2);
+ float3 p1 = float4_to_float3(P1);
+ float3 p2 = float4_to_float3(P2);
+ float3 dif = P - p1;
+ float3 dir = 1.0f/idir;
+ float l = len(p2 - p1);
+
+ float sp_r = mr + 0.5f * l;
+ float3 sphere_dif = P - ((p1 + p2) * 0.5f);
+ float sphere_b = dot(dir,sphere_dif);
+ sphere_dif = sphere_dif - sphere_b * dir;
+ sphere_b = dot(dir,sphere_dif);
+ float sdisc = sphere_b * sphere_b - len_squared(sphere_dif) + sp_r * sp_r;
+ if(sdisc < 0.0f)
+ return;
+
+ /* obtain parameters and test midpoint distance for suitable modes*/
+ float3 tg = (p2 - p1) / l;
+ float gd = (r2 - r1) / l;
+ float dirz = dot(dir,tg);
+ float difz = dot(dif,tg);
+
+ float a = 1.0f - (dirz*dirz*(1 + gd*gd));
+ float halfb = (dot(dir,dif) - dirz*(difz + gd*(difz*gd + r1)));
+
+ float tcentre = -halfb/a;
+ float zcentre = difz + (dirz * tcentre);
+
+ if((tcentre > isect->t) && !(flags & CURVE_KN_ACCURATE))
+ return;
+ if((zcentre < 0 || zcentre > l) && !(flags & CURVE_KN_ACCURATE) && !(flags & CURVE_KN_INTERSECTCORRECTION))
+ return;
+
+ /* test minimum separation*/
+ float3 cprod = cross(tg, dir);
+ float3 cprod2 = cross(tg, dif);
+ float cprodsq = len_squared(cprod);
+ float cprod2sq = len_squared(cprod2);
+ float distscaled = dot(cprod,dif);
+
+ if(cprodsq == 0)
+ distscaled = cprod2sq;
+ else
+ distscaled = (distscaled*distscaled)/cprodsq;
+
+ if(distscaled > mr*mr)
+ return;
+
+ /* calculate true intersection*/
+ float3 tdif = P - p1 + tcentre * dir;
+ float tdifz = dot(tdif,tg);
+ float tb = 2*(dot(dir,tdif) - dirz*(tdifz + gd*(tdifz*gd + r1)));
+ float tc = dot(tdif,tdif) - tdifz * tdifz * (1 + gd*gd) - r1*r1 - 2*r1*tdifz*gd;
+ float td = tb*tb - 4*a*tc;
+
+ if (td < 0.0f)
+ return;
+
+ float rootd = 0.0f;
+ float correction = 0.0f;
+ if(flags & CURVE_KN_ACCURATE) {
+ rootd = sqrtf(td);
+ correction = ((-tb - rootd)/(2*a));
+ }
+
+ float t = tcentre + correction;
+
+ if(t < isect->t) {
+
+ if(flags & CURVE_KN_INTERSECTCORRECTION) {
+ rootd = sqrtf(td);
+ correction = ((-tb - rootd)/(2*a));
+ t = tcentre + correction;
+ }
+
+ float z = zcentre + (dirz * correction);
+ bool backface = false;
+
+ if(flags & CURVE_KN_BACKFACING && (t < 0.0f || z < 0 || z > l)) {
+ backface = true;
+ correction = ((-tb + rootd)/(2*a));
+ t = tcentre + correction;
+ z = zcentre + (dirz * correction);
+ }
+
+ if(t > 0.0f && t < isect->t && z >= 0 && z <= l) {
+
+ if (flags & CURVE_KN_ENCLOSEFILTER) {
+
+ float enc_ratio = kernel_data.curve_kernel_data.encasing_ratio;
+ if((dot(P - p1, tg) > -r1 * enc_ratio) && (dot(P - p2, tg) < r2 * enc_ratio)) {
+ float a2 = 1.0f - (dirz*dirz*(1 + gd*gd*enc_ratio*enc_ratio));
+ float c2 = dot(dif,dif) - difz * difz * (1 + gd*gd*enc_ratio*enc_ratio) - r1*r1*enc_ratio*enc_ratio - 2*r1*difz*gd*enc_ratio;
+ if(a2*c2 < 0.0f)
+ return;
+ }
+ }
+
+#ifdef __VISIBILITY_FLAG__
+ /* visibility flag test. we do it here under the assumption
+ * that most triangles are culled by node flags */
+ if(kernel_tex_fetch(__prim_visibility, curveAddr) & visibility)
+#endif
+ {
+ /* record intersection */
+ isect->prim = curveAddr;
+ isect->segment = segment;
+ isect->object = object;
+ isect->u = z/l;
+ isect->v = td/(4*a*a);
+ isect->t = t;
+
+ if(backface)
+ isect->u = -isect->u;
+ }
+ }
+ }
+}
+#endif
+
+__device bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect)
{
/* traversal stack in CUDA thread-local memory */
int traversalStack[BVH_STACK_SIZE];
@@ -281,10 +731,20 @@ __device_inline bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint
nodeAddr = traversalStack[stackPtr];
--stackPtr;
- /* triangle intersection */
+ /* primitive intersection */
while(primAddr < primAddr2) {
- /* intersect ray against triangle */
- bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
+ /* intersect ray against primitive */
+#ifdef __HAIR__
+ uint segment = kernel_tex_fetch(__prim_segment, primAddr);
+ if(segment != ~0) {
+ if(kernel_data.curve_kernel_data.curveflags & CURVE_KN_INTERPOLATE)
+ bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment);
+ else
+ bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment);
+ }
+ else
+#endif
+ bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
/* shadow ray early termination */
if(visibility == PATH_RAY_SHADOW_OPAQUE && isect->prim != ~0)
@@ -325,7 +785,7 @@ __device_inline bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint
}
#ifdef __OBJECT_MOTION__
-__device_inline bool bvh_intersect_motion(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect)
+__device bool bvh_intersect_motion(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect)
{
/* traversal stack in CUDA thread-local memory */
int traversalStack[BVH_STACK_SIZE];
@@ -401,10 +861,20 @@ __device_inline bool bvh_intersect_motion(KernelGlobals *kg, const Ray *ray, con
nodeAddr = traversalStack[stackPtr];
--stackPtr;
- /* triangle intersection */
+ /* primitive intersection */
while(primAddr < primAddr2) {
- /* intersect ray against triangle */
- bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
+ /* intersect ray against primitive */
+#ifdef __HAIR__
+ uint segment = kernel_tex_fetch(__prim_segment, primAddr);
+ if(segment != ~0) {
+ if(kernel_data.curve_kernel_data.curveflags & CURVE_KN_INTERPOLATE)
+ bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment);
+ else
+ bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, segment);
+ }
+ else
+#endif
+ bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
/* shadow ray early termination */
if(visibility == PATH_RAY_SHADOW_OPAQUE && isect->prim != ~0)
@@ -457,12 +927,15 @@ __device_inline float3 ray_offset(float3 P, float3 Ng)
{
#ifdef __INTERSECTION_REFINE__
const float epsilon_f = 1e-5f;
+ /* ideally this should match epsilon_f, but instancing/mblur
+ * precision makes it problematic */
+ const float epsilon_test = 1.0f;
const int epsilon_i = 32;
float3 res;
/* x component */
- if(fabsf(P.x) < epsilon_f) {
+ if(fabsf(P.x) < epsilon_test) {
res.x = P.x + Ng.x*epsilon_f;
}
else {
@@ -472,7 +945,7 @@ __device_inline float3 ray_offset(float3 P, float3 Ng)
}
/* y component */
- if(fabsf(P.y) < epsilon_f) {
+ if(fabsf(P.y) < epsilon_test) {
res.y = P.y + Ng.y*epsilon_f;
}
else {
@@ -482,7 +955,7 @@ __device_inline float3 ray_offset(float3 P, float3 Ng)
}
/* z component */
- if(fabsf(P.z) < epsilon_f) {
+ if(fabsf(P.z) < epsilon_test) {
res.z = P.z + Ng.z*epsilon_f;
}
else {
@@ -542,5 +1015,159 @@ __device_inline float3 bvh_triangle_refine(KernelGlobals *kg, ShaderData *sd, co
#endif
}
+#ifdef __HAIR__
+
+__device_inline float3 curvetangent(float t, float3 p0, float3 p1, float3 p2, float3 p3)
+{
+ float fc = 0.71f;
+ float data[4];
+ float t2 = t * t;
+ data[0] = -3.0f * fc * t2 + 4.0f * fc * t - fc;
+ data[1] = 3.0f * (2.0f - fc) * t2 + 2.0f * (fc - 3.0f) * t;
+ data[2] = 3.0f * (fc - 2.0f) * t2 + 2.0f * (3.0f - 2.0f * fc) * t + fc;
+ data[3] = 3.0f * fc * t2 - 2.0f * fc * t;
+ return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
+}
+
+__device_inline float3 curvepoint(float t, float3 p0, float3 p1, float3 p2, float3 p3)
+{
+ float data[4];
+ float fc = 0.71f;
+ float t2 = t * t;
+ float t3 = t2 * t;
+ data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t;
+ data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f;
+ data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
+ data[3] = fc * t3 - fc * t2;
+ return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
+}
+
+__device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray, float t)
+{
+ int flag = kernel_data.curve_kernel_data.curveflags;
+ float3 P = ray->P;
+ float3 D = ray->D;
+
+ if(isect->object != ~0) {
+#ifdef __OBJECT_MOTION__
+ Transform tfm = sd->ob_itfm;
+#else
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
+#endif
+
+ P = transform_point(&tfm, P);
+ D = transform_direction(&tfm, D*t);
+ D = normalize_len(D, &t);
+ }
+
+ int prim = kernel_tex_fetch(__prim_index, isect->prim);
+ float4 v00 = kernel_tex_fetch(__curves, prim);
+
+ int k0 = __float_as_int(v00.x) + isect->segment;
+ int k1 = k0 + 1;
+
+ float4 P1 = kernel_tex_fetch(__curve_keys, k0);
+ float4 P2 = kernel_tex_fetch(__curve_keys, k1);
+ float l = 1.0f;
+ float3 tg = normalize_len(float4_to_float3(P2 - P1),&l);
+ float r1 = P1.w;
+ float r2 = P2.w;
+ float gd = ((r2 - r1)/l);
+
+ P = P + D*t;
+
+ if(flag & CURVE_KN_INTERPOLATE) {
+ int ka = max(k0 - 1,__float_as_int(v00.x));
+ int kb = min(k1 + 1,__float_as_int(v00.x) + __float_as_int(v00.y) - 1);
+
+ float4 P0 = kernel_tex_fetch(__curve_keys, ka);
+ float4 P3 = kernel_tex_fetch(__curve_keys, kb);
+
+ float3 p[4];
+ p[0] = float4_to_float3(P0);
+ p[1] = float4_to_float3(P1);
+ p[2] = float4_to_float3(P2);
+ p[3] = float4_to_float3(P3);
+
+ tg = normalize(curvetangent(isect->u,p[0],p[1],p[2],p[3]));
+ float3 p_curr = curvepoint(isect->u,p[0],p[1],p[2],p[3]);
+
+#ifdef __UV__
+ sd->u = isect->u;
+ sd->v = 0.0f;
+#endif
+
+ if(kernel_data.curve_kernel_data.curveflags & CURVE_KN_RIBBONS)
+ sd->Ng = normalize(-(D - tg * (dot(tg,D))));
+ else {
+ sd->Ng = normalize(P - p_curr);
+ sd->Ng = sd->Ng - gd * tg;
+ sd->Ng = normalize(sd->Ng);
+ }
+ sd->N = sd->Ng;
+ }
+ else {
+ float3 dif = P - float4_to_float3(P1);
+
+#ifdef __UV__
+ sd->u = dot(dif,tg)/l;
+ sd->v = 0.0f;
+#endif
+
+ if (flag & CURVE_KN_TRUETANGENTGNORMAL) {
+ sd->Ng = -(D - tg * (dot(tg,D) * kernel_data.curve_kernel_data.normalmix));
+ sd->Ng = normalize(sd->Ng);
+ if (flag & CURVE_KN_NORMALCORRECTION) {
+ sd->Ng = sd->Ng - gd * tg;
+ sd->Ng = normalize(sd->Ng);
+ }
+ }
+ else {
+ sd->Ng = (dif - tg * sd->u * l) / (P1.w + sd->u * l * gd);
+ if (gd != 0.0f) {
+ sd->Ng = sd->Ng - gd * tg ;
+ sd->Ng = normalize(sd->Ng);
+ }
+ }
+
+ sd->N = sd->Ng;
+
+ if (flag & CURVE_KN_TANGENTGNORMAL && !(flag & CURVE_KN_TRUETANGENTGNORMAL)) {
+ sd->N = -(D - tg * (dot(tg,D) * kernel_data.curve_kernel_data.normalmix));
+ sd->N = normalize(sd->N);
+ if (flag & CURVE_KN_NORMALCORRECTION) {
+ sd->N = sd->N - gd * tg;
+ sd->N = normalize(sd->N);
+ }
+ }
+ if (!(flag & CURVE_KN_TANGENTGNORMAL) && flag & CURVE_KN_TRUETANGENTGNORMAL) {
+ sd->N = (dif - tg * sd->u * l) / (P1.w + sd->u * l * gd);
+ if (gd != 0.0f) {
+ sd->N = sd->N - gd * tg ;
+ sd->N = normalize(sd->N);
+ }
+ }
+ }
+
+#ifdef __DPDU__
+ /* dPdu/dPdv */
+ sd->dPdu = tg;
+ sd->dPdv = cross(tg,sd->Ng);
+#endif
+
+ if(isect->object != ~0) {
+#ifdef __OBJECT_MOTION__
+ Transform tfm = sd->ob_tfm;
+#else
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
+#endif
+
+ P = transform_point(&tfm, P);
+ }
+
+ return P;
+}
+#endif
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h
index 97d37a8b3f4..02f64cd649a 100644
--- a/intern/cycles/kernel/kernel_camera.h
+++ b/intern/cycles/kernel/kernel_camera.h
@@ -94,7 +94,7 @@ __device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float
/* Orthographic Camera */
-__device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, float raster_y, Ray *ray)
+__device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, Ray *ray)
{
/* create ray form raster position */
Transform rastertocamera = kernel_data.cam.rastertocamera;
@@ -103,6 +103,22 @@ __device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, floa
ray->P = Pcamera;
ray->D = make_float3(0.0f, 0.0f, 1.0f);
+ /* modify ray for depth of field */
+ float aperturesize = kernel_data.cam.aperturesize;
+
+ if(aperturesize > 0.0f) {
+ /* sample point on aperture */
+ float2 lensuv = camera_sample_aperture(kg, lens_u, lens_v)*aperturesize;
+
+ /* compute point on plane of focus */
+ float ft = kernel_data.cam.focaldistance/ray->D.z;
+ float3 Pfocus = ray->P + ray->D*ft;
+
+ /* update ray for effect of lens */
+ ray->P = make_float3(lensuv.x, lensuv.y, 0.0f);
+ ray->D = normalize(Pfocus - ray->P);
+ }
+
/* transform ray from camera to world */
Transform cameratoworld = kernel_data.cam.cameratoworld;
@@ -199,7 +215,6 @@ __device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float ra
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;
-
#endif
}
@@ -214,7 +229,7 @@ __device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, flo
#ifdef __CAMERA_MOTION__
/* motion blur */
- if(kernel_data.cam.shuttertime == 0.0f)
+ if(kernel_data.cam.shuttertime == -1.0f)
ray->time = TIME_INVALID;
else
ray->time = 0.5f + 0.5f*(time - 0.5f)*kernel_data.cam.shuttertime;
@@ -224,7 +239,7 @@ __device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, flo
if(kernel_data.cam.type == CAMERA_PERSPECTIVE)
camera_sample_perspective(kg, raster_x, raster_y, lens_u, lens_v, ray);
else if(kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
- camera_sample_orthographic(kg, raster_x, raster_y, ray);
+ camera_sample_orthographic(kg, raster_x, raster_y, lens_u, lens_v, ray);
else
camera_sample_panorama(kg, raster_x, raster_y, lens_u, lens_v, ray);
}
diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h
index 45f653a686c..01bb78e8e1c 100644
--- a/intern/cycles/kernel/kernel_compat_cpu.h
+++ b/intern/cycles/kernel/kernel_compat_cpu.h
@@ -112,8 +112,8 @@ template<typename T> struct texture_image {
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
int ix, iy, nix, niy;
- float tx = frac(x*width, &ix);
- float ty = frac(y*height, &iy);
+ float tx = frac(x*width - 0.5f, &ix);
+ float ty = frac(y*height - 0.5f, &iy);
if(periodic) {
ix = wrap_periodic(ix, width);
diff --git a/intern/cycles/kernel/kernel_compat_cuda.h b/intern/cycles/kernel/kernel_compat_cuda.h
index 40bae069dea..9fd065c3cda 100644
--- a/intern/cycles/kernel/kernel_compat_cuda.h
+++ b/intern/cycles/kernel/kernel_compat_cuda.h
@@ -37,6 +37,7 @@
#define __global
#define __shared __shared__
#define __constant
+#define __may_alias
/* No assert supported for CUDA */
diff --git a/intern/cycles/kernel/kernel_compat_opencl.h b/intern/cycles/kernel/kernel_compat_opencl.h
index a9d18588cc8..abb2f094f5c 100644
--- a/intern/cycles/kernel/kernel_compat_opencl.h
+++ b/intern/cycles/kernel/kernel_compat_opencl.h
@@ -40,6 +40,7 @@
#define __device
#define __device_inline __device
#define __device_noinline __device __noinline
+#define __may_alias
/* no assert in opencl */
#define kernel_assert(cond)
diff --git a/intern/cycles/kernel/kernel_curve.h b/intern/cycles/kernel/kernel_curve.h
new file mode 100644
index 00000000000..e065717888c
--- /dev/null
+++ b/intern/cycles/kernel/kernel_curve.h
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+#ifdef __HAIR__
+
+/* curve attributes */
+
+__device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
+{
+ if(elem == ATTR_ELEMENT_CURVE) {
+#ifdef __RAY_DIFFERENTIALS__
+ if(dx) *dx = 0.0f;
+ if(dy) *dy = 0.0f;
+#endif
+
+ return kernel_tex_fetch(__attributes_float, offset + sd->prim);
+ }
+ else if(elem == ATTR_ELEMENT_CURVE_KEY) {
+ float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+ int k0 = __float_as_int(curvedata.x) + sd->segment;
+ 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(dy) *dy = 0.0f;
+#endif
+
+ return (1.0f - sd->u)*f0 + sd->u*f1;
+ }
+ else {
+#ifdef __RAY_DIFFERENTIALS__
+ if(dx) *dx = 0.0f;
+ if(dy) *dy = 0.0f;
+#endif
+
+ return 0.0f;
+ }
+}
+
+__device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
+{
+ if(elem == ATTR_ELEMENT_CURVE) {
+ /* idea: we can't derive any useful differentials here, but for tiled
+ * mipmap image caching it would be useful to avoid reading the highest
+ * detail level always. maybe a derivative based on the hair density
+ * could be computed somehow? */
+#ifdef __RAY_DIFFERENTIALS__
+ if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
+ if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
+#endif
+
+ return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->prim));
+ }
+ else if(elem == ATTR_ELEMENT_CURVE_KEY) {
+ float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+ int k0 = __float_as_int(curvedata.x) + sd->segment;
+ 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(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
+#endif
+
+ return (1.0f - sd->u)*f0 + sd->u*f1;
+ }
+ else {
+#ifdef __RAY_DIFFERENTIALS__
+ if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
+ if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
+#endif
+
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
+}
+
+/* hair info node functions */
+
+__device float curve_thickness(KernelGlobals *kg, ShaderData *sd)
+{
+ float r = 0.0f;
+
+ if(sd->segment != ~0) {
+ float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+ int k0 = __float_as_int(curvedata.x) + sd->segment;
+ int k1 = k0 + 1;
+
+ float4 P1 = kernel_tex_fetch(__curve_keys, k0);
+ float4 P2 = kernel_tex_fetch(__curve_keys, k1);
+ r = (P2.w - P1.w) * sd->u + P1.w;
+ }
+
+ return r*2.0f;
+}
+
+__device float3 curve_tangent_normal(KernelGlobals *kg, ShaderData *sd)
+{
+ float3 tgN = make_float3(0.0f,0.0f,0.0f);
+
+ if(sd->segment != ~0) {
+ float normalmix = kernel_data.curve_kernel_data.normalmix;
+
+ tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu,-sd->I) * normalmix / len_squared(sd->dPdu)));
+ tgN = normalize(tgN);
+
+ /* need to find suitable scaled gd for corrected normal */
+#if 0
+ if (kernel_data.curve_kernel_data.use_tangent_normal_correction)
+ tgN = normalize(tgN - gd * sd->dPdu);
+#endif
+ }
+
+ return tgN;
+}
+
+#endif
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/kernel_displace.h b/intern/cycles/kernel/kernel_displace.h
index a55f7a7fd75..fc2be342e02 100644
--- a/intern/cycles/kernel/kernel_displace.h
+++ b/intern/cycles/kernel/kernel_displace.h
@@ -35,7 +35,7 @@ __device void kernel_shader_evaluate(KernelGlobals *kg, uint4 *input, float4 *ou
/* evaluate */
float3 P = sd.P;
- shader_eval_displacement(kg, &sd);
+ shader_eval_displacement(kg, &sd, SHADER_CONTEXT_MAIN);
out = sd.P - P;
}
else { // SHADER_EVAL_BACKGROUND
@@ -63,7 +63,7 @@ __device void kernel_shader_evaluate(KernelGlobals *kg, uint4 *input, float4 *ou
/* evaluate */
int flag = 0; /* we can't know which type of BSDF this is for */
- out = shader_eval_background(kg, &sd, flag);
+ out = shader_eval_background(kg, &sd, flag, SHADER_CONTEXT_MAIN);
}
shader_release(kg, &sd);
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index 6d650a0158d..9787af535bb 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -20,7 +20,7 @@ CCL_NAMESPACE_BEGIN
/* Direction Emission */
-__device float3 direct_emissive_eval(KernelGlobals *kg, float rando,
+__device_noinline float3 direct_emissive_eval(KernelGlobals *kg, float rando,
LightSample *ls, float u, float v, float3 I, float t, float time)
{
/* setup shading at emitter */
@@ -42,17 +42,23 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando,
ray.time = time;
#endif
shader_setup_from_background(kg, &sd, &ray);
- eval = shader_eval_background(kg, &sd, 0);
+ 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, u, v, t, time);
+#ifdef __HAIR__
+ if(ls->type == LIGHT_STRAND)
+ shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v, t, time, ls->prim);
+ else
+#endif
+ shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v, t, time);
+
ls->Ng = 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, rando, 0);
+ shader_eval_surface(kg, &sd, rando, 0, SHADER_CONTEXT_EMISSION);
/* evaluate emissive closure */
if(sd.flag & SD_EMISSION)
@@ -60,37 +66,33 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando,
else
eval = make_float3(0.0f, 0.0f, 0.0f);
}
+
+ eval *= ls->eval_fac;
shader_release(kg, &sd);
return eval;
}
-__device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
+__device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
float randt, float rando, float randu, float randv, Ray *ray, BsdfEval *eval,
bool *is_lamp)
{
LightSample ls;
- float pdf = -1.0f;
-
#ifdef __NON_PROGRESSIVE__
if(lindex != -1) {
/* sample position on a specified light */
- light_select(kg, lindex, randu, randv, sd->P, &ls, &pdf);
+ light_select(kg, lindex, randu, randv, sd->P, &ls);
}
else
#endif
{
/* sample a light and position on int */
- light_sample(kg, randt, randu, randv, sd->time, sd->P, &ls, &pdf);
+ light_sample(kg, randt, randu, randv, sd->time, sd->P, &ls);
}
- /* compute pdf */
- if(pdf < 0.0f)
- pdf = light_sample_pdf(kg, &ls, -ls.D, ls.t);
-
- if(pdf == 0.0f)
+ if(ls.pdf == 0.0f)
return false;
/* evaluate closure */
@@ -106,13 +108,13 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
shader_bsdf_eval(kg, sd, ls.D, eval, &bsdf_pdf);
- if(ls.prim != ~0 || ls.type == LIGHT_BACKGROUND) {
+ if(ls.shader & SHADER_USE_MIS) {
/* multiple importance sampling */
- float mis_weight = power_heuristic(pdf, bsdf_pdf);
+ float mis_weight = power_heuristic(ls.pdf, bsdf_pdf);
light_eval *= mis_weight;
}
- bsdf_eval_mul(eval, light_eval*(ls.eval_fac/pdf));
+ bsdf_eval_mul(eval, light_eval/ls.pdf);
if(bsdf_eval_is_zero(eval))
return false;
@@ -138,19 +140,24 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
ray->t = 0.0f;
}
- *is_lamp = (ls.prim == ~0);
+ /* return if it's a lamp for shadow pass */
+ *is_lamp = (ls.prim == ~0 && ls.type != LIGHT_BACKGROUND);
return true;
}
-/* Indirect Emission */
+/* Indirect Primitive Emission */
-__device float3 indirect_emission(KernelGlobals *kg, ShaderData *sd, float t, int path_flag, float bsdf_pdf)
+__device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, ShaderData *sd, float t, int path_flag, float bsdf_pdf)
{
/* evaluate emissive closure */
float3 L = shader_emissive_eval(kg, sd);
+#ifdef __HAIR__
+ if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT) && (sd->segment == ~0)) {
+#else
if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_SAMPLE_AS_LIGHT)) {
+#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);
@@ -162,15 +169,44 @@ __device float3 indirect_emission(KernelGlobals *kg, ShaderData *sd, float t, in
return L;
}
+/* Indirect Lamp Emission */
+
+__device_noinline bool indirect_lamp_emission(KernelGlobals *kg, Ray *ray, int path_flag, float bsdf_pdf, float randt, float3 *emission)
+{
+ LightSample ls;
+ int lamp = lamp_light_eval_sample(kg, randt);
+
+ if(lamp == ~0)
+ return false;
+
+ if(!lamp_light_eval(kg, lamp, ray->P, ray->D, ray->t, &ls))
+ return false;
+
+ /* todo: missing texture coordinates */
+ float u = 0.0f;
+ float v = 0.0f;
+ float3 L = direct_emissive_eval(kg, 0.0f, &ls, u, v, -ray->D, ls.t, ray->time);
+
+ if(!(path_flag & PATH_RAY_MIS_SKIP)) {
+ /* multiple importance sampling, get regular light pdf,
+ * and compute weight with respect to BSDF pdf */
+ float mis_weight = power_heuristic(bsdf_pdf, ls.pdf);
+ L *= mis_weight;
+ }
+
+ *emission = L;
+ return true;
+}
+
/* Indirect Background */
-__device float3 indirect_background(KernelGlobals *kg, Ray *ray, int path_flag, float bsdf_pdf)
+__device_noinline float3 indirect_background(KernelGlobals *kg, Ray *ray, int path_flag, float bsdf_pdf)
{
#ifdef __BACKGROUND__
/* evaluate background closure */
ShaderData sd;
shader_setup_from_background(kg, &sd, ray);
- float3 L = shader_eval_background(kg, &sd, path_flag);
+ float3 L = shader_eval_background(kg, &sd, path_flag, SHADER_CONTEXT_EMISSION);
shader_release(kg, &sd);
#ifdef __BACKGROUND_MIS__
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 97ae2d3db87..f6fbd3599ad 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -18,49 +18,26 @@
CCL_NAMESPACE_BEGIN
+/* Light Sample result */
+
typedef struct LightSample {
- float3 P;
- float3 D;
- float3 Ng;
- float t;
- float eval_fac;
- int object;
- int prim;
- int shader;
- LightType type;
+ float3 P; /* position on light, or direction for distant light */
+ float3 Ng; /* normal on light */
+ float3 D; /* direction from shading point to light */
+ float t; /* distance to light (FLT_MAX for distant light) */
+ float pdf; /* light sampling probability density function */
+ float eval_fac; /* intensity multiplier */
+ int object; /* object id for triangle/curve lights */
+ int prim; /* primitive id for triangle/curve ligths */
+ int shader; /* shader id */
+ int lamp; /* lamp id */
+ LightType type; /* type of light */
} LightSample;
-/* Regular Light */
-
-__device float3 disk_light_sample(float3 v, float randu, float randv)
-{
- float3 ru, rv;
-
- make_orthonormals(v, &ru, &rv);
- to_unit_disk(&randu, &randv);
-
- return ru*randu + rv*randv;
-}
-
-__device float3 distant_light_sample(float3 D, float size, float randu, float randv)
-{
- return normalize(D + disk_light_sample(D, randu, randv)*size);
-}
-
-__device float3 sphere_light_sample(float3 P, float3 center, float size, float randu, float randv)
-{
- return disk_light_sample(normalize(P - center), randu, randv)*size;
-}
-
-__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;
-}
+/* Background Light */
#ifdef __BACKGROUND_MIS__
+
__device float3 background_light_sample(KernelGlobals *kg, float randu, float randv, float *pdf)
{
/* for the following, the CDF values are actually a pair of floats, with the
@@ -169,33 +146,105 @@ __device float background_light_pdf(KernelGlobals *kg, float3 direction)
}
#endif
-__device void regular_light_sample(KernelGlobals *kg, int point,
- float randu, float randv, float3 P, LightSample *ls, float *pdf)
+/* Regular Light */
+
+__device float3 disk_light_sample(float3 v, float randu, float randv)
+{
+ float3 ru, rv;
+
+ make_orthonormals(v, &ru, &rv);
+ to_unit_disk(&randu, &randv);
+
+ return ru*randu + rv*randv;
+}
+
+__device float3 distant_light_sample(float3 D, float radius, float randu, float randv)
+{
+ return normalize(D + disk_light_sample(D, randu, randv)*radius);
+}
+
+__device float3 sphere_light_sample(float3 P, float3 center, float radius, float randu, float randv)
+{
+ return disk_light_sample(normalize(P - center), randu, randv)*radius;
+}
+
+__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;
+}
+
+__device float spot_light_attenuation(float4 data1, float4 data2, LightSample *ls)
+{
+ float3 dir = make_float3(data2.y, data2.z, data2.w);
+ float3 I = ls->Ng;
+
+ float spot_angle = data1.w;
+ float spot_smooth = data2.x;
+
+ float attenuation = dot(dir, I);
+
+ if(attenuation <= spot_angle) {
+ attenuation = 0.0f;
+ }
+ else {
+ float t = attenuation - spot_angle;
+
+ if(t < spot_smooth && spot_smooth != 0.0f)
+ attenuation *= smoothstepf(t/spot_smooth);
+ }
+
+ return attenuation;
+}
+
+__device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3 I, float t)
+{
+ float cos_pi = dot(Ng, I);
+
+ if(cos_pi <= 0.0f)
+ return 0.0f;
+
+ return t*t/cos_pi;
+}
+
+__device void lamp_light_sample(KernelGlobals *kg, int lamp,
+ float randu, float randv, float3 P, LightSample *ls)
{
- float4 data0 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 0);
- float4 data1 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 1);
+ float4 data0 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 0);
+ float4 data1 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 1);
LightType type = (LightType)__float_as_int(data0.x);
ls->type = type;
+ ls->shader = __float_as_int(data1.x);
+ ls->object = ~0;
+ ls->prim = ~0;
+ ls->lamp = lamp;
if(type == LIGHT_DISTANT) {
/* distant light */
- float3 D = make_float3(data0.y, data0.z, data0.w);
- float size = data1.y;
+ float3 lightD = make_float3(data0.y, data0.z, data0.w);
+ float3 D = lightD;
+ float radius = data1.y;
+ float invarea = data1.w;
- if(size > 0.0f)
- D = distant_light_sample(D, size, randu, randv);
+ if(radius > 0.0f)
+ D = distant_light_sample(D, radius, randu, randv);
ls->P = D;
ls->Ng = D;
ls->D = -D;
ls->t = FLT_MAX;
- ls->eval_fac = 1.0f;
+
+ float costheta = dot(lightD, D);
+ ls->pdf = invarea/(costheta*costheta*costheta);
+ ls->eval_fac = ls->pdf*kernel_data.integrator.inv_pdf_lights;
}
#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, pdf);
+ float3 D = background_light_sample(kg, randu, randv, &ls->pdf);
ls->P = D;
ls->Ng = D;
@@ -207,125 +256,266 @@ __device void regular_light_sample(KernelGlobals *kg, int point,
else {
ls->P = make_float3(data0.y, data0.z, data0.w);
- if(type == LIGHT_POINT) {
- float size = data1.y;
-
- /* sphere light */
- if(size > 0.0f)
- ls->P += sphere_light_sample(P, ls->P, size, randu, randv);
-
- ls->Ng = normalize(P - ls->P);
- ls->eval_fac = 0.25f*M_1_PI_F;
- }
- else if(type == LIGHT_SPOT) {
- float4 data2 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 2);
- float size = data1.y;
-
- /* spot light */
- if(size > 0.0f)
- ls->P += sphere_light_sample(P, ls->P, size, randu, randv);
+ if(type == LIGHT_POINT || type == LIGHT_SPOT) {
+ float radius = data1.y;
- float3 dir = make_float3(data1.z, data1.w, data2.x);
- float3 I = normalize(P - ls->P);
+ if(radius > 0.0f)
+ /* sphere light */
+ ls->P += sphere_light_sample(P, ls->P, radius, randu, randv);
- float spot_angle = data2.y;
- float spot_smooth = data2.z;
+ ls->D = normalize_len(ls->P - P, &ls->t);
+ ls->Ng = -ls->D;
- float eval_fac = dot(dir, I);
+ float invarea = data1.z;
+ ls->eval_fac = (0.25f*M_1_PI_F)*invarea;
+ ls->pdf = invarea;
- if(eval_fac <= spot_angle) {
- eval_fac = 0.0f;
+ if(type == LIGHT_SPOT) {
+ /* spot light attentuation */
+ float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2);
+ ls->eval_fac *= spot_light_attenuation(data1, data2, ls);
}
- else {
- float t = eval_fac - spot_angle;
-
- if(t < spot_smooth && spot_smooth != 0.0f)
- eval_fac *= smoothstepf(t/spot_smooth);
- }
-
- ls->Ng = I;
- ls->eval_fac = eval_fac*0.25f*M_1_PI_F;
}
else {
/* area light */
- float4 data2 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 2);
- float4 data3 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 3);
+ float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2);
+ float4 data3 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 3);
- float3 axisu = make_float3(data1.y, data1.z, data2.w);
+ float3 axisu = make_float3(data1.y, data1.z, data1.w);
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->Ng = D;
- ls->eval_fac = 0.25f;
+ ls->D = normalize_len(ls->P - P, &ls->t);
+
+ float invarea = data2.x;
+
+ ls->eval_fac = 0.25f*invarea;
+ ls->pdf = invarea;
}
- ls->t = 0.0f;
+ ls->eval_fac *= kernel_data.integrator.inv_pdf_lights;
+ ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
}
+}
+__device 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);
+
+ LightType type = (LightType)__float_as_int(data0.x);
+ ls->type = type;
ls->shader = __float_as_int(data1.x);
ls->object = ~0;
ls->prim = ~0;
-}
+ ls->lamp = lamp;
-__device float regular_light_pdf(KernelGlobals *kg,
- const float3 Ng, const float3 I, float t)
-{
- float pdf = kernel_data.integrator.pdf_lights;
+ if(!(ls->shader & SHADER_USE_MIS))
+ return false;
- if(t == FLT_MAX)
- return pdf;
+ if(type == LIGHT_DISTANT) {
+ /* distant light */
+ float radius = data1.y;
+
+ if(radius == 0.0f)
+ return false;
+ if(t != FLT_MAX)
+ return false;
+
+ /* a distant light is infinitely far away, but equivalent to a disk
+ * shaped light exactly 1 unit away from the current shading point.
+ *
+ * radius t^2/cos(theta)
+ * <----------> t = sqrt(1^2 + tan(theta)^2)
+ * tan(th) area = radius*radius*pi
+ * <----->
+ * \ | (1 + tan(theta)^2)/cos(theta)
+ * \ | (1 + tan(acos(cos(theta)))^2)/cos(theta)
+ * t \th| 1 simplifies to
+ * \-| 1/(cos(theta)^3)
+ * \| magic!
+ * P
+ */
+
+ float3 lightD = make_float3(data0.y, data0.z, data0.w);
+ float costheta = dot(-lightD, D);
+ float cosangle = data1.z;
+
+ if(costheta < cosangle)
+ return false;
+
+ ls->P = -D;
+ ls->Ng = -D;
+ ls->D = D;
+ ls->t = FLT_MAX;
- float cos_pi = dot(Ng, I);
+ float invarea = data1.w;
+ ls->pdf = invarea/(costheta*costheta*costheta);
+ ls->eval_fac = ls->pdf;
+ }
+ else if(type == LIGHT_POINT || type == LIGHT_SPOT) {
+ float3 lightP = make_float3(data0.y, data0.z, data0.w);
+ float radius = data1.y;
- if(cos_pi <= 0.0f)
- return 0.0f;
+ /* sphere light */
+ if(radius == 0.0f)
+ return false;
- return t*t*pdf/cos_pi;
+ if(!ray_aligned_disk_intersect(P, D, t,
+ lightP, radius, &ls->P, &ls->t))
+ return false;
+
+ ls->Ng = -D;
+ ls->D = D;
+
+ float invarea = data1.z;
+ ls->eval_fac = (0.25f*M_1_PI_F)*invarea;
+ ls->pdf = invarea;
+
+ if(type == LIGHT_SPOT) {
+ /* spot light attentuation */
+ float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2);
+ ls->eval_fac *= spot_light_attenuation(data1, data2, ls);
+
+ if(ls->eval_fac == 0.0f)
+ return false;
+ }
+ }
+ else if(type == LIGHT_AREA) {
+ /* area light */
+ float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2);
+ float4 data3 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 3);
+
+ float invarea = data2.x;
+ if(invarea == 0.0f)
+ return false;
+
+ float3 axisu = make_float3(data1.y, data1.z, data1.w);
+ float3 axisv = make_float3(data2.y, data2.z, data2.w);
+ float3 Ng = make_float3(data3.y, data3.z, data3.w);
+
+ /* one sided */
+ if(dot(D, Ng) >= 0.0f)
+ return false;
+
+ ls->P = make_float3(data0.y, data0.z, data0.w);
+
+ if(!ray_quad_intersect(P, D, t,
+ ls->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;
+ }
+ else
+ return false;
+
+ /* compute pdf */
+ if(ls->t != FLT_MAX)
+ ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
+ ls->eval_fac *= kernel_data.integrator.inv_pdf_lights;
+
+ return true;
}
/* Triangle Light */
-__device void triangle_light_sample(KernelGlobals *kg, int prim, int object,
- float randu, float randv, float time, LightSample *ls)
+__device void object_transform_light_sample(KernelGlobals *kg, LightSample *ls, int object, float time)
{
- /* triangle, so get position, normal, shader */
- ls->P = triangle_sample_MT(kg, prim, randu, randv);
- ls->Ng = triangle_normal_MT(kg, prim, &ls->shader);
- ls->object = object;
- ls->prim = prim;
- ls->t = 0.0f;
- ls->type = LIGHT_AREA;
- ls->eval_fac = 1.0f;
-
#ifdef __INSTANCING__
/* instance transform */
- if(ls->object >= 0) {
+ if(object >= 0) {
#ifdef __OBJECT_MOTION__
Transform itfm;
Transform tfm = object_fetch_transform_motion_test(kg, object, time, &itfm);
#else
- Transform tfm = object_fetch_transform(kg, ls->object, OBJECT_TRANSFORM);
- Transform itfm = object_fetch_transform(kg, ls->object, OBJECT_INVERSE_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
+ Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
#endif
ls->P = transform_point(&tfm, ls->P);
- ls->Ng = normalize(transform_direction_transposed(&itfm, ls->Ng));
+ ls->Ng = normalize(transform_direction(&tfm, ls->Ng));
}
#endif
}
+__device void triangle_light_sample(KernelGlobals *kg, int prim, int object,
+ float randu, float randv, float time, LightSample *ls)
+{
+ /* triangle, so get position, normal, shader */
+ ls->P = triangle_sample_MT(kg, prim, randu, randv);
+ ls->Ng = triangle_normal_MT(kg, prim, &ls->shader);
+ ls->object = object;
+ ls->prim = prim;
+ ls->lamp = ~0;
+ ls->shader |= SHADER_USE_MIS;
+ ls->t = 0.0f;
+ ls->type = LIGHT_TRIANGLE;
+ ls->eval_fac = 1.0f;
+
+ object_transform_light_sample(kg, ls, object, time);
+}
+
__device float triangle_light_pdf(KernelGlobals *kg,
const float3 Ng, const float3 I, float t)
{
+ float pdf = kernel_data.integrator.pdf_triangles;
float cos_pi = fabsf(dot(Ng, I));
if(cos_pi == 0.0f)
return 0.0f;
- return (t*t*kernel_data.integrator.pdf_triangles)/cos_pi;
+ return t*t*pdf/cos_pi;
}
+/* Curve Light */
+
+#ifdef __HAIR__
+
+__device void curve_segment_light_sample(KernelGlobals *kg, int prim, int object,
+ int segment, float randu, float randv, float time, LightSample *ls)
+{
+ /* this strand code needs completion */
+ float4 v00 = kernel_tex_fetch(__curves, prim);
+
+ int k0 = __float_as_int(v00.x) + segment;
+ int k1 = k0 + 1;
+
+ float4 P1 = kernel_tex_fetch(__curve_keys, k0);
+ float4 P2 = kernel_tex_fetch(__curve_keys, k1);
+
+ float l = len(P2 - P1);
+
+ float r1 = P1.w;
+ float r2 = P2.w;
+ float3 tg = float4_to_float3(P2 - P1) / l;
+ float3 xc = make_float3(tg.x * tg.z, tg.y * tg.z, -(tg.x * tg.x + tg.y * tg.y));
+ if (dot(xc, xc) == 0.0f)
+ xc = make_float3(tg.x * tg.y, -(tg.x * tg.x + tg.z * tg.z), tg.z * tg.y);
+ xc = normalize(xc);
+ float3 yc = cross(tg, xc);
+ float gd = ((r2 - r1)/l);
+
+ /* normal currently ignores gradient */
+ ls->Ng = sinf(2 * M_PI_F * randv) * xc + cosf(2 * M_PI_F * randv) * yc;
+ ls->P = randu * l * tg + (gd * l + r1) * ls->Ng;
+ ls->object = object;
+ ls->prim = prim;
+ ls->lamp = ~0;
+ ls->t = 0.0f;
+ ls->type = LIGHT_STRAND;
+ ls->eval_fac = 1.0f;
+ ls->shader = __float_as_int(v00.z) | SHADER_USE_MIS;
+
+ object_transform_light_sample(kg, ls, object, time);
+}
+
+#endif
+
/* Light Distribution */
__device int light_distribution_sample(KernelGlobals *kg, float randt)
@@ -357,7 +547,7 @@ __device int light_distribution_sample(KernelGlobals *kg, float randt)
/* Generic Light */
-__device void light_sample(KernelGlobals *kg, float randt, float randu, float randv, float time, float3 P, LightSample *ls, float *pdf)
+__device void light_sample(KernelGlobals *kg, float randt, float randu, float randv, float time, float3 P, LightSample *ls)
{
/* sample index */
int index = light_distribution_sample(kg, randt);
@@ -368,28 +558,25 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra
if(prim >= 0) {
int object = __float_as_int(l.w);
- triangle_light_sample(kg, prim, object, randu, randv, time, ls);
+#ifdef __HAIR__
+ int segment = __float_as_int(l.z);
+#endif
+
+#ifdef __HAIR__
+ if (segment != ~0)
+ curve_segment_light_sample(kg, prim, object, segment, randu, randv, time, ls);
+ else
+#endif
+ triangle_light_sample(kg, prim, object, randu, randv, time, ls);
+
+ /* compute incoming direction, distance and pdf */
+ ls->D = normalize_len(ls->P - P, &ls->t);
+ ls->pdf = triangle_light_pdf(kg, ls->Ng, -ls->D, ls->t);
}
else {
- int point = -prim-1;
- regular_light_sample(kg, point, randu, randv, P, ls, pdf);
+ int lamp = -prim-1;
+ lamp_light_sample(kg, lamp, randu, randv, P, ls);
}
-
- /* compute incoming direction and distance */
- if(ls->t != FLT_MAX)
- ls->D = normalize_len(ls->P - P, &ls->t);
-}
-
-__device float light_sample_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t)
-{
- float pdf;
-
- if(ls->prim != ~0)
- pdf = triangle_light_pdf(kg, ls->Ng, I, t);
- else
- pdf = regular_light_pdf(kg, ls->Ng, I, t);
-
- return pdf;
}
__device int light_select_num_samples(KernelGlobals *kg, int index)
@@ -398,18 +585,26 @@ __device int light_select_num_samples(KernelGlobals *kg, int index)
return __float_as_int(data3.x);
}
-__device void light_select(KernelGlobals *kg, int index, float randu, float randv, float3 P, LightSample *ls, float *pdf)
+__device void light_select(KernelGlobals *kg, int index, float randu, float randv, float3 P, LightSample *ls)
{
- regular_light_sample(kg, index, randu, randv, P, ls, pdf);
-
- /* compute incoming direction and distance */
- if(ls->t != FLT_MAX)
- ls->D = normalize_len(ls->P - P, &ls->t);
+ lamp_light_sample(kg, index, randu, randv, P, ls);
}
-__device float light_select_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t)
+__device int lamp_light_eval_sample(KernelGlobals *kg, float randt)
{
- return regular_light_pdf(kg, ls->Ng, I, t);
+ /* 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 ~0;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_montecarlo.h b/intern/cycles/kernel/kernel_montecarlo.h
index 48d1aa64c9f..fb66501c336 100644
--- a/intern/cycles/kernel/kernel_montecarlo.h
+++ b/intern/cycles/kernel/kernel_montecarlo.h
@@ -105,6 +105,22 @@ __device_inline void sample_uniform_hemisphere(const float3 N,
*pdf = 0.5f * M_1_PI_F;
}
+__device_inline void sample_uniform_cone(const float3 N, float angle,
+ float randu, float randv,
+ float3 *omega_in, float *pdf)
+{
+ float z = cosf(angle*randu);
+ float r = sqrtf(max(0.0f, 1.0f - z*z));
+ float phi = 2.0f * M_PI_F * randv;
+ float x = r * cosf(phi);
+ float y = r * sinf(phi);
+
+ float3 T, B;
+ make_orthonormals (N, &T, &B);
+ *omega_in = x * T + y * B + z * N;
+ *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(angle));
+}
+
__device float3 sample_uniform_sphere(float u1, float u2)
{
float z = 1.0f - 2.0f*u1;
diff --git a/intern/cycles/kernel/kernel_object.h b/intern/cycles/kernel/kernel_object.h
index 2b38544e527..40aa4753daa 100644
--- a/intern/cycles/kernel/kernel_object.h
+++ b/intern/cycles/kernel/kernel_object.h
@@ -20,11 +20,16 @@ CCL_NAMESPACE_BEGIN
enum ObjectTransform {
OBJECT_TRANSFORM = 0,
- OBJECT_INVERSE_TRANSFORM = 3,
- OBJECT_PROPERTIES = 6,
- OBJECT_TRANSFORM_MOTION_PRE = 8,
- OBJECT_TRANSFORM_MOTION_POST = 12,
- OBJECT_DUPLI = 16
+ OBJECT_TRANSFORM_MOTION_PRE = 0,
+ OBJECT_INVERSE_TRANSFORM = 4,
+ OBJECT_TRANSFORM_MOTION_POST = 4,
+ OBJECT_PROPERTIES = 8,
+ OBJECT_DUPLI = 9
+};
+
+enum ObjectVectorTransform {
+ OBJECT_VECTOR_MOTION_PRE = 0,
+ OBJECT_VECTOR_MOTION_POST = 3
};
__device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, enum ObjectTransform type)
@@ -40,6 +45,19 @@ __device_inline Transform object_fetch_transform(KernelGlobals *kg, int object,
return tfm;
}
+__device_inline Transform object_fetch_vector_transform(KernelGlobals *kg, int object, enum ObjectVectorTransform type)
+{
+ int offset = object*OBJECT_VECTOR_SIZE + (int)type;
+
+ Transform tfm;
+ tfm.x = kernel_tex_fetch(__objects_vector, offset + 0);
+ tfm.y = kernel_tex_fetch(__objects_vector, offset + 1);
+ tfm.z = kernel_tex_fetch(__objects_vector, offset + 2);
+ tfm.w = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
+
+ return tfm;
+}
+
#ifdef __OBJECT_MOTION__
__device_inline Transform object_fetch_transform_motion(KernelGlobals *kg, int object, float time)
{
diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h
index 7f8b611ba14..57dbdc2ffc1 100644
--- a/intern/cycles/kernel/kernel_passes.h
+++ b/intern/cycles/kernel/kernel_passes.h
@@ -70,11 +70,11 @@ __device_inline void kernel_write_data_passes(KernelGlobals *kg, __global float
kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, sample, normal);
}
if(flag & PASS_UV) {
- float3 uv = triangle_uv(kg, sd);
+ float3 uv = primitive_uv(kg, sd);
kernel_write_pass_float3(buffer + kernel_data.film.pass_uv, sample, uv);
}
if(flag & PASS_MOTION) {
- float4 speed = triangle_motion_vector(kg, sd);
+ float4 speed = primitive_motion_vector(kg, sd);
kernel_write_pass_float4(buffer + kernel_data.film.pass_motion, sample, speed);
kernel_write_pass_float(buffer + kernel_data.film.pass_motion_weight, sample, 1.0f);
}
@@ -125,14 +125,7 @@ __device_inline void kernel_write_light_passes(KernelGlobals *kg, __global float
kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_color, sample, L->color_transmission);
if(flag & PASS_SHADOW) {
float4 shadow = L->shadow;
-
- /* bit of an ugly hack to compensate for emitting triangles influencing
- * amount of samples we get for this pass */
- if(kernel_data.integrator.progressive && kernel_data.integrator.pdf_triangles != 0.0f)
- shadow.w = 0.5f;
- else
- shadow.w = 1.0f;
-
+ shadow.w = kernel_data.film.pass_shadow_scale;
kernel_write_pass_float4(buffer + kernel_data.film.pass_shadow, sample, shadow);
}
#endif
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 3588b09c790..865ba7ca676 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -24,14 +24,11 @@
#include "kernel_montecarlo.h"
#include "kernel_projection.h"
#include "kernel_object.h"
-#include "kernel_attribute.h"
-#include "kernel_projection.h"
#include "kernel_triangle.h"
-#ifdef __QBVH__
-#include "kernel_qbvh.h"
-#else
+#include "kernel_curve.h"
+#include "kernel_primitive.h"
+#include "kernel_projection.h"
#include "kernel_bvh.h"
-#endif
#include "kernel_accumulate.h"
#include "kernel_camera.h"
#include "kernel_shader.h"
@@ -207,7 +204,7 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra
ShaderData sd;
shader_setup_from_ray(kg, &sd, &isect, ray);
- shader_eval_surface(kg, &sd, 0.0f, PATH_RAY_SHADOW);
+ shader_eval_surface(kg, &sd, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
throughput *= shader_bsdf_transparency(kg, &sd);
@@ -237,6 +234,9 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
float min_ray_pdf = FLT_MAX;
float ray_pdf = 0.0f;
+#ifdef __LAMP_MIS__
+ float ray_t = 0.0f;
+#endif
PathState state;
int rng_offset = PRNG_BASE_NUM;
@@ -247,8 +247,29 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
/* intersect scene */
Intersection isect;
uint visibility = path_state_ray_visibility(kg, &state);
+ bool hit = scene_intersect(kg, &ray, visibility, &isect);
- if(!scene_intersect(kg, &ray, visibility, &isect)) {
+#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 - ray_t*ray.D;
+ ray_t += isect.t;
+ light_ray.D = ray.D;
+ light_ray.t = ray_t;
+ light_ray.time = ray.time;
+
+ /* intersect with lamp */
+ float light_t = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT);
+ float3 emission;
+
+ if(indirect_lamp_emission(kg, &light_ray, state.flag, ray_pdf, light_t, &emission))
+ path_radiance_accum_emission(&L, throughput, emission, state.bounce);
+ }
+#endif
+
+ if(!hit) {
/* eval background shader if nothing hit */
if(kernel_data.background.transparent && (state.flag & PATH_RAY_CAMERA)) {
L_transparent += average(throughput);
@@ -272,7 +293,7 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
ShaderData sd;
shader_setup_from_ray(kg, &sd, &isect, &ray);
float rbsdf = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF);
- shader_eval_surface(kg, &sd, rbsdf, state.flag);
+ shader_eval_surface(kg, &sd, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
kernel_write_data_passes(kg, buffer, &L, &sd, sample, state.flag, throughput);
@@ -312,7 +333,8 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
#ifdef __EMISSION__
/* emission */
if(sd.flag & SD_EMISSION) {
- float3 emission = indirect_emission(kg, &sd, isect.t, state.flag, ray_pdf);
+ /* todo: is isect.t wrong here for transparent surfaces? */
+ float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, ray_pdf);
path_radiance_accum_emission(&L, throughput, emission, state.bounce);
}
#endif
@@ -385,7 +407,7 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
if(!shadow_blocked(kg, &state, &light_ray, &shadow)) {
/* accumulate */
- path_radiance_accum_light(&L, throughput, &L_light, shadow, state.bounce, is_lamp);
+ path_radiance_accum_light(&L, throughput, &L_light, shadow, 1.0f, state.bounce, is_lamp);
}
}
}
@@ -421,6 +443,9 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
/* set labels */
if(!(label & LABEL_TRANSPARENT)) {
ray_pdf = bsdf_pdf;
+#ifdef __LAMP_MIS__
+ ray_t = 0.0f;
+#endif
min_ray_pdf = fminf(bsdf_pdf, min_ray_pdf);
}
@@ -456,15 +481,41 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
#ifdef __NON_PROGRESSIVE__
__device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray ray, __global float *buffer,
- float3 throughput, float min_ray_pdf, float ray_pdf, PathState state, int rng_offset, PathRadiance *L)
+ float3 throughput, float throughput_normalize,
+ float min_ray_pdf, float ray_pdf, PathState state, int rng_offset, PathRadiance *L)
{
+#ifdef __LAMP_MIS__
+ float ray_t = 0.0f;
+#endif
+
/* path iteration */
for(;; rng_offset += PRNG_BOUNCE_NUM) {
/* intersect scene */
Intersection isect;
uint visibility = path_state_ray_visibility(kg, &state);
+ bool hit = scene_intersect(kg, &ray, visibility, &isect);
- if(!scene_intersect(kg, &ray, visibility, &isect)) {
+#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 - ray_t*ray.D;
+ ray_t += isect.t;
+ light_ray.D = ray.D;
+ light_ray.t = ray_t;
+ light_ray.time = ray.time;
+
+ /* intersect with lamp */
+ float light_t = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT);
+ float3 emission;
+
+ if(indirect_lamp_emission(kg, &light_ray, state.flag, ray_pdf, light_t, &emission))
+ path_radiance_accum_emission(L, throughput, emission, state.bounce);
+ }
+#endif
+
+ if(!hit) {
#ifdef __BACKGROUND__
/* sample background shader */
float3 L_background = indirect_background(kg, &ray, state.flag, ray_pdf);
@@ -478,7 +529,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray
ShaderData sd;
shader_setup_from_ray(kg, &sd, &isect, &ray);
float rbsdf = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF);
- shader_eval_surface(kg, &sd, rbsdf, state.flag);
+ shader_eval_surface(kg, &sd, rbsdf, state.flag, SHADER_CONTEXT_INDIRECT);
shader_merge_closures(kg, &sd);
/* blurring of bsdf after bounces, for rays that have a small likelihood
@@ -495,7 +546,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray
#ifdef __EMISSION__
/* emission */
if(sd.flag & SD_EMISSION) {
- float3 emission = indirect_emission(kg, &sd, isect.t, state.flag, ray_pdf);
+ float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, ray_pdf);
path_radiance_accum_emission(L, throughput, emission, state.bounce);
}
#endif
@@ -503,7 +554,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray
/* path termination. this is a strange place to put the termination, it's
* mainly due to the mixed in MIS that we use. gives too many unneeded
* shader evaluations, only need emission if we are going to terminate */
- float probability = path_state_terminate_probability(kg, &state, throughput);
+ float probability = path_state_terminate_probability(kg, &state, throughput*throughput_normalize);
float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE);
if(terminate >= probability) {
@@ -569,7 +620,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray
if(!shadow_blocked(kg, &state, &light_ray, &shadow)) {
/* accumulate */
- path_radiance_accum_light(L, throughput, &L_light, shadow, state.bounce, is_lamp);
+ path_radiance_accum_light(L, throughput, &L_light, shadow, 1.0f, state.bounce, is_lamp);
}
}
}
@@ -605,6 +656,9 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray
/* set labels */
if(!(label & LABEL_TRANSPARENT)) {
ray_pdf = bsdf_pdf;
+#ifdef __LAMP_MIS__
+ ray_t = 0.0f;
+#endif
min_ray_pdf = fminf(bsdf_pdf, min_ray_pdf);
}
@@ -666,7 +720,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam
ShaderData sd;
shader_setup_from_ray(kg, &sd, &isect, &ray);
float rbsdf = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF);
- shader_eval_surface(kg, &sd, rbsdf, state.flag);
+ shader_eval_surface(kg, &sd, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
shader_merge_closures(kg, &sd);
kernel_write_data_passes(kg, buffer, &L, &sd, sample, state.flag, throughput);
@@ -696,7 +750,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam
#ifdef __EMISSION__
/* emission */
if(sd.flag & SD_EMISSION) {
- float3 emission = indirect_emission(kg, &sd, isect.t, state.flag, ray_pdf);
+ float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, ray_pdf);
path_radiance_accum_emission(&L, throughput, emission, state.bounce);
}
#endif
@@ -783,7 +837,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam
if(!shadow_blocked(kg, &state, &light_ray, &shadow)) {
/* accumulate */
- path_radiance_accum_light(&L, throughput*num_samples_inv, &L_light, shadow, state.bounce, is_lamp);
+ path_radiance_accum_light(&L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state.bounce, is_lamp);
}
}
}
@@ -812,7 +866,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam
if(!shadow_blocked(kg, &state, &light_ray, &shadow)) {
/* accumulate */
- path_radiance_accum_light(&L, throughput*num_samples_inv, &L_light, shadow, state.bounce, is_lamp);
+ path_radiance_accum_light(&L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state.bounce, is_lamp);
}
}
}
@@ -884,8 +938,14 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam
bsdf_ray.time = sd.time;
#endif
- kernel_path_indirect(kg, rng, sample*num_samples, bsdf_ray, buffer,
- tp*num_samples_inv, min_ray_pdf, bsdf_pdf, ps, rng_offset+PRNG_BOUNCE_NUM, &L);
+ kernel_path_indirect(kg, rng, sample*num_samples + j, bsdf_ray, buffer,
+ tp*num_samples_inv, num_samples,
+ min_ray_pdf, bsdf_pdf, ps, rng_offset+PRNG_BOUNCE_NUM, &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);
}
}
diff --git a/intern/cycles/kernel/kernel_primitive.h b/intern/cycles/kernel/kernel_primitive.h
new file mode 100644
index 00000000000..323394cd9dc
--- /dev/null
+++ b/intern/cycles/kernel/kernel_primitive.h
@@ -0,0 +1,185 @@
+/*
+ * 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.
+ */
+
+#ifndef __KERNEL_ATTRIBUTE_CL__
+#define __KERNEL_ATTRIBUTE_CL__
+
+CCL_NAMESPACE_BEGIN
+
+/* attribute lookup */
+
+__device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id, AttributeElement *elem)
+{
+ if(sd->object == ~0)
+ return (int)ATTR_STD_NOT_FOUND;
+
+#ifdef __OSL__
+ if (kg->osl) {
+ return OSLShader::find_attribute(kg, sd, id, elem);
+ }
+ else
+#endif
+ {
+ /* for SVM, find attribute by unique id */
+ uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
+#ifdef __HAIR__
+ attr_offset = (sd->segment == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
+#endif
+ 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;
+ }
+}
+
+__device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
+{
+#ifdef __HAIR__
+ if(sd->segment == ~0)
+#endif
+ return triangle_attribute_float(kg, sd, elem, offset, dx, dy);
+#ifdef __HAIR__
+ else
+ return curve_attribute_float(kg, sd, elem, offset, dx, dy);
+#endif
+}
+
+__device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
+{
+#ifdef __HAIR__
+ if(sd->segment == ~0)
+#endif
+ return triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
+#ifdef __HAIR__
+ else
+ return curve_attribute_float3(kg, sd, elem, offset, dx, dy);
+#endif
+}
+
+__device float3 primitive_uv(KernelGlobals *kg, ShaderData *sd)
+{
+ AttributeElement elem_uv;
+ int offset_uv = find_attribute(kg, sd, ATTR_STD_UV, &elem_uv);
+
+ if(offset_uv == ATTR_STD_NOT_FOUND)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ float3 uv = primitive_attribute_float3(kg, sd, elem_uv, offset_uv, NULL, NULL);
+ uv.z = 1.0f;
+ return uv;
+}
+
+__device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
+{
+#ifdef __HAIR__
+ if(sd->segment != ~0)
+ return normalize(sd->dPdu);
+#endif
+
+ /* try to create spherical tangent from generated coordinates */
+ AttributeElement attr_elem;
+ int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED, &attr_elem);
+
+ if(attr_offset != ATTR_STD_NOT_FOUND) {
+ 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)));
+ }
+ else {
+ /* otherwise use surface derivatives */
+ return normalize(sd->dPdu);
+ }
+}
+
+/* motion */
+
+__device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd)
+{
+ float3 motion_pre = sd->P, motion_post = sd->P;
+
+ /* deformation motion */
+ AttributeElement elem_pre, elem_post;
+ int offset_pre = find_attribute(kg, sd, ATTR_STD_MOTION_PRE, &elem_pre);
+ int offset_post = find_attribute(kg, sd, ATTR_STD_MOTION_POST, &elem_post);
+
+ if(offset_pre != ATTR_STD_NOT_FOUND)
+ motion_pre = primitive_attribute_float3(kg, sd, elem_pre, offset_pre, NULL, NULL);
+ if(offset_post != ATTR_STD_NOT_FOUND)
+ motion_post = primitive_attribute_float3(kg, sd, elem_post, offset_post, NULL, NULL);
+
+ /* 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);
+ motion_pre = transform_point(&tfm, motion_pre);
+
+ tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_POST);
+ motion_post = transform_point(&tfm, motion_post);
+
+ float3 P;
+
+ /* 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) {
+ tfm = kernel_data.cam.worldtoraster;
+ P = transform_perspective(&tfm, sd->P);
+
+ tfm = kernel_data.cam.motion.pre;
+ motion_pre = transform_perspective(&tfm, motion_pre);
+
+ tfm = kernel_data.cam.motion.post;
+ motion_post = transform_perspective(&tfm, motion_post);
+ }
+ else {
+ tfm = kernel_data.cam.worldtocamera;
+ P = normalize(transform_point(&tfm, sd->P));
+ P = float2_to_float3(direction_to_panorama(kg, P));
+ P.x *= kernel_data.cam.width;
+ P.y *= kernel_data.cam.height;
+
+ tfm = kernel_data.cam.motion.pre;
+ motion_pre = normalize(transform_point(&tfm, motion_pre));
+ motion_pre = float2_to_float3(direction_to_panorama(kg, motion_pre));
+ motion_pre.x *= kernel_data.cam.width;
+ motion_pre.y *= kernel_data.cam.height;
+
+ tfm = kernel_data.cam.motion.post;
+ motion_post = normalize(transform_point(&tfm, motion_post));
+ motion_post = float2_to_float3(direction_to_panorama(kg, motion_post));
+ motion_post.x *= kernel_data.cam.width;
+ motion_post.y *= kernel_data.cam.height;
+ }
+
+ motion_pre = motion_pre - P;
+ motion_post = P - motion_post;
+
+ return make_float4(motion_pre.x, motion_pre.y, motion_post.x, motion_post.y);
+}
+
+CCL_NAMESPACE_END
+
+#endif /* __KERNEL_ATTRIBUTE_CL__ */
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 98a7ec59d7b..df86b352697 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -26,11 +26,11 @@
*
*/
+#include "closure/bsdf_util.h"
#include "closure/bsdf.h"
#include "closure/emissive.h"
#include "closure/volume.h"
-#include "svm/svm_bsdf.h"
#include "svm/svm.h"
CCL_NAMESPACE_BEGIN
@@ -53,32 +53,14 @@ __device_noinline void shader_setup_object_transforms(KernelGlobals *kg, ShaderD
}
#endif
-__device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
+__device_noinline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
const Intersection *isect, const Ray *ray)
{
-#ifdef __OSL__
- if (kg->osl)
- OSLShader::init(kg, sd);
-#endif
-
- /* fetch triangle data */
- int prim = kernel_tex_fetch(__prim_index, isect->prim);
- float4 Ns = kernel_tex_fetch(__tri_normal, prim);
- float3 Ng = make_float3(Ns.x, Ns.y, Ns.z);
- int shader = __float_as_int(Ns.w);
-
- /* triangle */
#ifdef __INSTANCING__
sd->object = (isect->object == ~0)? kernel_tex_fetch(__prim_object, isect->prim): isect->object;
#endif
- sd->prim = prim;
-#ifdef __UV__
- sd->u = isect->u;
- sd->v = isect->v;
-#endif
- sd->flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*2);
- sd->flag |= kernel_tex_fetch(__object_flag, sd->object);
+ sd->flag = kernel_tex_fetch(__object_flag, sd->object);
/* matrices and time */
#ifdef __OBJECT_MOTION__
@@ -86,23 +68,63 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
sd->time = ray->time;
#endif
- /* vectors */
- sd->P = bvh_triangle_refine(kg, sd, isect, ray);
- sd->Ng = Ng;
- sd->N = Ng;
- sd->I = -ray->D;
- sd->shader = shader;
+ sd->prim = kernel_tex_fetch(__prim_index, isect->prim);
sd->ray_length = isect->t;
- /* smooth normal */
- if(sd->shader & SHADER_SMOOTH_NORMAL)
- sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
+#ifdef __HAIR__
+ if(kernel_tex_fetch(__prim_segment, isect->prim) != ~0) {
+ /* Strand Shader setting*/
+ float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+
+ sd->shader = __float_as_int(curvedata.z);
+ sd->segment = isect->segment;
+
+ float tcorr = isect->t;
+ if(kernel_data.curve_kernel_data.curveflags & CURVE_KN_POSTINTERSECTCORRECTION) {
+ tcorr = (isect->u < 0)? tcorr + sqrtf(isect->v) : tcorr - sqrtf(isect->v);
+ sd->ray_length = tcorr;
+ }
+
+ sd->P = bvh_curve_refine(kg, sd, isect, ray, tcorr);
+ }
+ else {
+#endif
+ /* fetch triangle data */
+ float4 Ns = kernel_tex_fetch(__tri_normal, sd->prim);
+ float3 Ng = make_float3(Ns.x, Ns.y, Ns.z);
+ sd->shader = __float_as_int(Ns.w);
+
+#ifdef __HAIR__
+ sd->segment = ~0;
+#endif
+
+#ifdef __UV__
+ sd->u = isect->u;
+ sd->v = isect->v;
+#endif
+
+ /* vectors */
+ sd->P = bvh_triangle_refine(kg, sd, isect, ray);
+ sd->Ng = Ng;
+ sd->N = Ng;
+
+ /* smooth normal */
+ if(sd->shader & SHADER_SMOOTH_NORMAL)
+ sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
#ifdef __DPDU__
- /* dPdu/dPdv */
- triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim);
+ /* dPdu/dPdv */
+ triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim);
#endif
+#ifdef __HAIR__
+ }
+#endif
+
+ sd->I = -ray->D;
+
+ sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
+
#ifdef __INSTANCING__
if(isect->object != ~0) {
/* instance transform */
@@ -138,26 +160,25 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
/* ShaderData setup from position sampled on mesh */
-__device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
+__device_noinline void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
const float3 P, const float3 Ng, const float3 I,
- int shader, int object, int prim, float u, float v, float t, float time)
+ int shader, int object, int prim, float u, float v, float t, float time, int segment = ~0)
{
-#ifdef __OSL__
- if (kg->osl)
- OSLShader::init(kg, sd);
-#endif
-
/* vectors */
sd->P = P;
sd->N = Ng;
sd->Ng = Ng;
sd->I = I;
sd->shader = shader;
+#ifdef __HAIR__
+ sd->segment = segment;
+#endif
/* primitive */
#ifdef __INSTANCING__
sd->object = object;
#endif
+ /* currently no access to bvh prim index for strand sd->prim - this will cause errors with needs fixing*/
sd->prim = prim;
#ifdef __UV__
sd->u = u;
@@ -193,8 +214,13 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
#endif
/* smooth normal */
+#ifdef __HAIR__
+ if(sd->shader & SHADER_SMOOTH_NORMAL && sd->segment == ~0) {
+ sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
+#else
if(sd->shader & SHADER_SMOOTH_NORMAL) {
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
+#endif
#ifdef __INSTANCING__
if(instanced)
@@ -204,10 +230,17 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
#ifdef __DPDU__
/* dPdu/dPdv */
+#ifdef __HAIR__
+ if(sd->prim == ~0 || sd->segment != ~0) {
+ sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
+ sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
+ }
+#else
if(sd->prim == ~0) {
sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
}
+#endif
else {
triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim);
@@ -250,7 +283,7 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
/* ShaderData setup for displacement */
-__device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
+__device_noinline void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
int object, int prim, float u, float v)
{
/* Note: no OSLShader::init call here, this is done in shader_setup_from_sample! */
@@ -273,11 +306,6 @@ __device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
__device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData *sd, const Ray *ray)
{
-#ifdef __OSL__
- if (kg->osl)
- OSLShader::init(kg, sd);
-#endif
-
/* vectors */
sd->P = ray->D;
sd->N = -sd->P;
@@ -294,6 +322,9 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
sd->object = ~0;
#endif
sd->prim = ~0;
+#ifdef __HAIR__
+ sd->segment = ~0;
+#endif
#ifdef __UV__
sd->u = 0.0f;
sd->v = 0.0f;
@@ -320,36 +351,8 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
#ifdef __MULTI_CLOSURE__
-#ifdef __OSL__
-__device_inline void _shader_bsdf_multi_eval_osl(const ShaderData *sd, const float3 omega_in, float *pdf,
- int skip_bsdf, BsdfEval *bsdf_eval, float sum_pdf, float sum_sample_weight)
-{
- for(int i = 0; i< sd->num_closure; i++) {
- if(i == skip_bsdf)
- continue;
-
- const ShaderClosure *sc = &sd->closure[i];
-
- if(CLOSURE_IS_BSDF(sc->type)) {
- float bsdf_pdf = 0.0f;
-
- float3 eval = OSLShader::bsdf_eval(sd, sc, omega_in, bsdf_pdf);
-
- if(bsdf_pdf != 0.0f) {
- bsdf_eval_accum(bsdf_eval, sc->type, eval*sc->weight);
- sum_pdf += bsdf_pdf*sc->sample_weight;
- }
-
- sum_sample_weight += sc->sample_weight;
- }
- }
-
- *pdf = (sum_sample_weight > 0.0f)? sum_pdf/sum_sample_weight: 0.0f;
-}
-#endif
-
-__device_inline void _shader_bsdf_multi_eval_svm(const ShaderData *sd, const float3 omega_in, float *pdf,
- int skip_bsdf, BsdfEval *bsdf_eval, float sum_pdf, float sum_sample_weight)
+__device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, const ShaderData *sd, const float3 omega_in, float *pdf,
+ int skip_bsdf, BsdfEval *result_eval, float sum_pdf, float sum_sample_weight)
{
for(int i = 0; i< sd->num_closure; i++) {
if(i == skip_bsdf)
@@ -359,11 +362,10 @@ __device_inline void _shader_bsdf_multi_eval_svm(const ShaderData *sd, const flo
if(CLOSURE_IS_BSDF(sc->type)) {
float bsdf_pdf = 0.0f;
-
- float3 eval = svm_bsdf_eval(sd, sc, omega_in, &bsdf_pdf);
+ float3 eval = bsdf_eval(kg, sd, sc, omega_in, &bsdf_pdf);
if(bsdf_pdf != 0.0f) {
- bsdf_eval_accum(bsdf_eval, sc->type, eval*sc->weight);
+ bsdf_eval_accum(result_eval, sc->type, eval*sc->weight);
sum_pdf += bsdf_pdf*sc->sample_weight;
}
@@ -382,17 +384,12 @@ __device void shader_bsdf_eval(KernelGlobals *kg, const ShaderData *sd,
#ifdef __MULTI_CLOSURE__
bsdf_eval_init(eval, NBUILTIN_CLOSURES, make_float3(0.0f, 0.0f, 0.0f), kernel_data.film.use_light_pass);
-#ifdef __OSL__
- if (kg->osl)
- return _shader_bsdf_multi_eval_osl(sd, omega_in, pdf, -1, eval, 0.0f, 0.0f);
- else
-#endif
- return _shader_bsdf_multi_eval_svm(sd, omega_in, pdf, -1, eval, 0.0f, 0.0f);
+ return _shader_bsdf_multi_eval(kg, sd, omega_in, pdf, -1, eval, 0.0f, 0.0f);
#else
const ShaderClosure *sc = &sd->closure;
*pdf = 0.0f;
- *eval = svm_bsdf_eval(sd, sc, omega_in, pdf)*sc->weight;
+ *eval = bsdf_eval(kg, sd, sc, omega_in, pdf)*sc->weight;
#endif
}
@@ -439,24 +436,14 @@ __device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
float3 eval;
*pdf = 0.0f;
-#ifdef __OSL__
- if (kg->osl)
- label = OSLShader::bsdf_sample(sd, sc, randu, randv, eval, *omega_in, *domega_in, *pdf);
- else
-#endif
- label = svm_bsdf_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
+ label = bsdf_sample(kg, sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
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) {
float sweight = sc->sample_weight;
-#ifdef __OSL__
- if (kg->osl)
- _shader_bsdf_multi_eval_osl(sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight);
- else
-#endif
- _shader_bsdf_multi_eval_svm(sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight);
+ _shader_bsdf_multi_eval(kg, sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight);
}
}
@@ -464,7 +451,7 @@ __device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
#else
/* sample the single closure that we picked */
*pdf = 0.0f;
- int label = svm_bsdf_sample(sd, &sd->closure, randu, randv, bsdf_eval, omega_in, domega_in, pdf);
+ int label = bsdf_sample(kg, sd, &sd->closure, randu, randv, bsdf_eval, omega_in, domega_in, pdf);
*bsdf_eval *= sd->closure.weight;
return label;
#endif
@@ -478,12 +465,7 @@ __device int shader_bsdf_sample_closure(KernelGlobals *kg, const ShaderData *sd,
float3 eval;
*pdf = 0.0f;
-#ifdef __OSL__
- if (kg->osl)
- label = OSLShader::bsdf_sample(sd, sc, randu, randv, eval, *omega_in, *domega_in, *pdf);
- else
-#endif
- label = svm_bsdf_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
+ label = bsdf_sample(kg, sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
if(*pdf != 0.0f)
bsdf_eval_init(bsdf_eval, sc->type, eval*sc->weight, kernel_data.film.use_light_pass);
@@ -497,17 +479,11 @@ __device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughnes
for(int i = 0; i< sd->num_closure; i++) {
ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_BSDF(sc->type)) {
-#ifdef __OSL__
- if (kg->osl)
- OSLShader::bsdf_blur(sc, roughness);
- else
-#endif
- svm_bsdf_blur(sc, roughness);
- }
+ if(CLOSURE_IS_BSDF(sc->type))
+ bsdf_blur(kg, sc, roughness);
}
#else
- svm_bsdf_blur(&sd->closure, roughness);
+ bsdf_blur(kg, &sd->closure, roughness);
#endif
}
@@ -635,6 +611,16 @@ __device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_facto
/* Emission */
+__device float3 emissive_eval(KernelGlobals *kg, ShaderData *sd, ShaderClosure *sc)
+{
+#ifdef __OSL__
+ if(kg->osl && sc->prim)
+ return OSLShader::emissive_eval(sd, sc);
+#endif
+
+ return emissive_simple_eval(sd->Ng, sd->I);
+}
+
__device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
{
float3 eval;
@@ -644,18 +630,11 @@ __device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
for(int i = 0; i < sd->num_closure; i++) {
ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_EMISSION(sc->type)) {
-#ifdef __OSL__
- if (kg->osl)
- eval += OSLShader::emissive_eval(sd, sc)*sc->weight;
- else
-#endif
- eval += svm_emissive_eval(sd, sc)*sc->weight;
-
- }
+ if(CLOSURE_IS_EMISSION(sc->type))
+ eval += emissive_eval(kg, sd, sc)*sc->weight;
}
#else
- eval = svm_emissive_eval(sd, &sd->closure)*sd->closure.weight;
+ eval = emissive_eval(kg, sd, &sd->closure)*sd->closure.weight;
#endif
return eval;
@@ -687,11 +666,11 @@ __device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
/* Surface Evaluation */
__device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
- float randb, int path_flag)
+ float randb, int path_flag, ShaderContext ctx)
{
#ifdef __OSL__
if (kg->osl)
- OSLShader::eval_surface(kg, sd, randb, path_flag);
+ OSLShader::eval_surface(kg, sd, randb, path_flag, ctx);
else
#endif
{
@@ -706,11 +685,11 @@ __device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
/* Background Evaluation */
-__device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag)
+__device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag, ShaderContext ctx)
{
#ifdef __OSL__
if (kg->osl)
- return OSLShader::eval_background(kg, sd, path_flag);
+ return OSLShader::eval_background(kg, sd, path_flag, ctx);
else
#endif
@@ -753,31 +732,25 @@ __device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd,
for(int i = 0; i< sd->num_closure; i++) {
const ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_VOLUME(sc->type)) {
-#ifdef __OSL__
- if (kg->osl)
- eval += OSLShader::volume_eval_phase(sc, omega_in, omega_out);
- else
-#endif
- eval += volume_eval_phase(sc, omega_in, omega_out);
- }
+ if(CLOSURE_IS_VOLUME(sc->type))
+ eval += volume_eval_phase(kg, sc, omega_in, omega_out);
}
return eval;
#else
- return volume_eval_phase(&sd->closure, omega_in, omega_out);
+ return volume_eval_phase(kg, &sd->closure, omega_in, omega_out);
#endif
}
/* Volume Evaluation */
__device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd,
- float randb, int path_flag)
+ float randb, int path_flag, ShaderContext ctx)
{
#ifdef __SVM__
#ifdef __OSL__
if (kg->osl)
- OSLShader::eval_volume(kg, sd, randb, path_flag);
+ OSLShader::eval_volume(kg, sd, randb, path_flag, ctx);
else
#endif
svm_eval_nodes(kg, sd, SHADER_TYPE_VOLUME, randb, path_flag);
@@ -786,13 +759,13 @@ __device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd,
/* Displacement Evaluation */
-__device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd)
+__device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderContext ctx)
{
/* this will modify sd->P */
#ifdef __SVM__
#ifdef __OSL__
if (kg->osl)
- OSLShader::eval_displacement(kg, sd);
+ OSLShader::eval_displacement(kg, sd, ctx);
else
#endif
svm_eval_nodes(kg, sd, SHADER_TYPE_DISPLACEMENT, 0.0f, 0);
@@ -805,8 +778,20 @@ __device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd)
__device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect)
{
int prim = kernel_tex_fetch(__prim_index, isect->prim);
- float4 Ns = kernel_tex_fetch(__tri_normal, prim);
- int shader = __float_as_int(Ns.w);
+ int shader = 0;
+
+#ifdef __HAIR__
+ if(kernel_tex_fetch(__prim_segment, isect->prim) == ~0) {
+#endif
+ float4 Ns = kernel_tex_fetch(__tri_normal, prim);
+ shader = __float_as_int(Ns.w);
+#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);
return (flag & SD_HAS_SURFACE_TRANSPARENT) != 0;
@@ -818,7 +803,6 @@ __device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect)
#ifdef __NON_PROGRESSIVE__
__device void shader_merge_closures(KernelGlobals *kg, ShaderData *sd)
{
-#ifndef __OSL__
/* merge identical closures, better when we sample a single closure at a time */
for(int i = 0; i < sd->num_closure; i++) {
ShaderClosure *sci = &sd->closure[i];
@@ -826,7 +810,11 @@ __device void shader_merge_closures(KernelGlobals *kg, ShaderData *sd)
for(int j = i + 1; j < sd->num_closure; j++) {
ShaderClosure *scj = &sd->closure[j];
+#ifdef __OSL__
+ if(!sci->prim && sci->type == scj->type && sci->data0 == scj->data0 && sci->data1 == scj->data1) {
+#else
if(sci->type == scj->type && sci->data0 == scj->data0 && sci->data1 == scj->data1) {
+#endif
sci->weight += scj->weight;
sci->sample_weight += scj->sample_weight;
@@ -838,7 +826,6 @@ __device void shader_merge_closures(KernelGlobals *kg, ShaderData *sd)
}
}
}
-#endif
}
#endif
@@ -846,10 +833,7 @@ __device void shader_merge_closures(KernelGlobals *kg, ShaderData *sd)
__device void shader_release(KernelGlobals *kg, ShaderData *sd)
{
-#ifdef __OSL__
- if (kg->osl)
- OSLShader::release(kg, sd);
-#endif
+ /* nothing to do currently */
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_sse2.cpp b/intern/cycles/kernel/kernel_sse2.cpp
new file mode 100644
index 00000000000..e9d482ae5cf
--- /dev/null
+++ b/intern/cycles/kernel/kernel_sse2.cpp
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+/* Optimized CPU kernel entry points. This file is compiled with SSE2
+ * optimization flags and nearly all functions inlined, while kernel.cpp
+ * is compiled without for other CPU's. */
+
+#ifdef WITH_OPTIMIZED_KERNEL
+
+#include "kernel.h"
+#include "kernel_compat_cpu.h"
+#include "kernel_math.h"
+#include "kernel_types.h"
+#include "kernel_globals.h"
+#include "kernel_film.h"
+#include "kernel_path.h"
+#include "kernel_displace.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Path Tracing */
+
+void kernel_cpu_sse2_path_trace(KernelGlobals *kg, float *buffer, unsigned int *rng_state, int sample, int x, int y, int offset, int stride)
+{
+ kernel_path_trace(kg, buffer, rng_state, sample, x, y, offset, stride);
+}
+
+/* Tonemapping */
+
+void kernel_cpu_sse2_tonemap(KernelGlobals *kg, uchar4 *rgba, float *buffer, int sample, int resolution, int x, int y, int offset, int stride)
+{
+ kernel_film_tonemap(kg, rgba, buffer, sample, resolution, x, y, offset, stride);
+}
+
+/* Shader Evaluate */
+
+void kernel_cpu_sse2_shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int i)
+{
+ kernel_shader_evaluate(kg, input, output, (ShaderEvalType)type, i);
+}
+
+CCL_NAMESPACE_END
+
+#endif
+
diff --git a/intern/cycles/kernel/kernel_optimized.cpp b/intern/cycles/kernel/kernel_sse3.cpp
index 0b662095133..9a8b389cf68 100644
--- a/intern/cycles/kernel/kernel_optimized.cpp
+++ b/intern/cycles/kernel/kernel_sse3.cpp
@@ -35,21 +35,21 @@ CCL_NAMESPACE_BEGIN
/* Path Tracing */
-void kernel_cpu_optimized_path_trace(KernelGlobals *kg, float *buffer, unsigned int *rng_state, int sample, int x, int y, int offset, int stride)
+void kernel_cpu_sse3_path_trace(KernelGlobals *kg, float *buffer, unsigned int *rng_state, int sample, int x, int y, int offset, int stride)
{
kernel_path_trace(kg, buffer, rng_state, sample, x, y, offset, stride);
}
/* Tonemapping */
-void kernel_cpu_optimized_tonemap(KernelGlobals *kg, uchar4 *rgba, float *buffer, int sample, int resolution, int x, int y, int offset, int stride)
+void kernel_cpu_sse3_tonemap(KernelGlobals *kg, uchar4 *rgba, float *buffer, int sample, int resolution, int x, int y, int offset, int stride)
{
kernel_film_tonemap(kg, rgba, buffer, sample, resolution, x, y, offset, stride);
}
/* Shader Evaluate */
-void kernel_cpu_optimized_shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int i)
+void kernel_cpu_sse3_shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int i)
{
kernel_shader_evaluate(kg, input, output, (ShaderEvalType)type, i);
}
diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h
index 4855a948c6e..e27de95e7ab 100644
--- a/intern/cycles/kernel/kernel_textures.h
+++ b/intern/cycles/kernel/kernel_textures.h
@@ -27,6 +27,7 @@
/* bvh */
KERNEL_TEX(float4, texture_float4, __bvh_nodes)
KERNEL_TEX(float4, texture_float4, __tri_woop)
+KERNEL_TEX(uint, texture_uint, __prim_segment)
KERNEL_TEX(uint, texture_uint, __prim_visibility)
KERNEL_TEX(uint, texture_uint, __prim_index)
KERNEL_TEX(uint, texture_uint, __prim_object)
@@ -34,6 +35,7 @@ KERNEL_TEX(uint, texture_uint, __object_node)
/* objects */
KERNEL_TEX(float4, texture_float4, __objects)
+KERNEL_TEX(float4, texture_float4, __objects_vector)
/* triangles */
KERNEL_TEX(float4, texture_float4, __tri_normal)
@@ -41,6 +43,10 @@ KERNEL_TEX(float4, texture_float4, __tri_vnormal)
KERNEL_TEX(float4, texture_float4, __tri_vindex)
KERNEL_TEX(float4, texture_float4, __tri_verts)
+/* curves */
+KERNEL_TEX(float4, texture_float4, __curves)
+KERNEL_TEX(float4, texture_float4, __curve_keys)
+
/* attributes */
KERNEL_TEX(uint4, texture_uint4, __attributes_map)
KERNEL_TEX(float, texture_float, __attributes_float)
diff --git a/intern/cycles/kernel/kernel_triangle.h b/intern/cycles/kernel/kernel_triangle.h
index 0db447289c8..d346137760f 100644
--- a/intern/cycles/kernel/kernel_triangle.h
+++ b/intern/cycles/kernel/kernel_triangle.h
@@ -190,82 +190,5 @@ __device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData *s
}
}
-/* motion */
-
-__device float4 triangle_motion_vector(KernelGlobals *kg, ShaderData *sd)
-{
- float3 motion_pre = sd->P, motion_post = sd->P;
-
- /* deformation motion */
- int offset_pre = find_attribute(kg, sd, ATTR_STD_MOTION_PRE);
- int offset_post = find_attribute(kg, sd, ATTR_STD_MOTION_POST);
-
- if(offset_pre != ATTR_STD_NOT_FOUND)
- motion_pre = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_pre, NULL, NULL);
- if(offset_post != ATTR_STD_NOT_FOUND)
- motion_post = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_post, NULL, NULL);
-
- /* 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_transform(kg, sd->object, OBJECT_TRANSFORM_MOTION_PRE);
- motion_pre = transform_point(&tfm, motion_pre);
-
- tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM_MOTION_POST);
- motion_post = transform_point(&tfm, motion_post);
-
- float3 P;
-
- /* 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) {
- tfm = kernel_data.cam.worldtoraster;
- P = transform_perspective(&tfm, sd->P);
-
- tfm = kernel_data.cam.motion.pre;
- motion_pre = transform_perspective(&tfm, motion_pre);
-
- tfm = kernel_data.cam.motion.post;
- motion_post = transform_perspective(&tfm, motion_post);
- }
- else {
- tfm = kernel_data.cam.worldtocamera;
- P = normalize(transform_point(&tfm, sd->P));
- P = float2_to_float3(direction_to_panorama(kg, P));
- P.x *= kernel_data.cam.width;
- P.y *= kernel_data.cam.height;
-
- tfm = kernel_data.cam.motion.pre;
- motion_pre = normalize(transform_point(&tfm, motion_pre));
- motion_pre = float2_to_float3(direction_to_panorama(kg, motion_pre));
- motion_pre.x *= kernel_data.cam.width;
- motion_pre.y *= kernel_data.cam.height;
-
- tfm = kernel_data.cam.motion.post;
- motion_post = normalize(transform_point(&tfm, motion_post));
- motion_post = float2_to_float3(direction_to_panorama(kg, motion_post));
- motion_post.x *= kernel_data.cam.width;
- motion_post.y *= kernel_data.cam.height;
- }
-
- motion_pre = motion_pre - P;
- motion_post = P - motion_post;
-
- return make_float4(motion_pre.x, motion_pre.y, motion_post.x, motion_post.y);
-}
-
-__device float3 triangle_uv(KernelGlobals *kg, ShaderData *sd)
-{
- int offset_uv = find_attribute(kg, sd, ATTR_STD_UV);
-
- if(offset_uv == ATTR_STD_NOT_FOUND)
- return make_float3(0.0f, 0.0f, 0.0f);
-
- float3 uv = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, offset_uv, NULL, NULL);
- uv.z = 1.0f;
- return uv;
-}
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index e3a766e56b1..ddbda9240fb 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -29,7 +29,8 @@
CCL_NAMESPACE_BEGIN
/* constants */
-#define OBJECT_SIZE 18
+#define OBJECT_SIZE 11
+#define OBJECT_VECTOR_SIZE 6
#define LIGHT_SIZE 4
#define FILTER_TABLE_SIZE 256
#define RAMP_TABLE_SIZE 256
@@ -42,10 +43,11 @@ CCL_NAMESPACE_BEGIN
#ifdef __KERNEL_CPU__
#define __KERNEL_SHADING__
#define __KERNEL_ADV_SHADING__
+#define __NON_PROGRESSIVE__
+#define __HAIR__
#ifdef WITH_OSL
#define __OSL__
#endif
-#define __NON_PROGRESSIVE__
#endif
#ifdef __KERNEL_CUDA__
@@ -110,12 +112,12 @@ CCL_NAMESPACE_BEGIN
#define __TRANSPARENT_SHADOWS__
#define __PASSES__
#define __BACKGROUND_MIS__
+#define __LAMP_MIS__
#define __AO__
-#define __CAMERA_MOTION__
#define __ANISOTROPIC__
+#define __CAMERA_MOTION__
#define __OBJECT_MOTION__
#endif
-
//#define __SOBOL_FULL_SCREEN__
/* Shader Evaluation */
@@ -253,6 +255,10 @@ typedef struct PathRadiance {
float3 indirect_glossy;
float3 indirect_transmission;
+ float3 path_diffuse;
+ float3 path_glossy;
+ float3 path_transmission;
+
float4 shadow;
} PathRadiance;
@@ -279,8 +285,9 @@ typedef enum ShaderFlag {
SHADER_SMOOTH_NORMAL = (1 << 31),
SHADER_CAST_SHADOW = (1 << 30),
SHADER_AREA_LIGHT = (1 << 29),
+ SHADER_USE_MIS = (1 << 28),
- SHADER_MASK = ~(SHADER_SMOOTH_NORMAL|SHADER_CAST_SHADOW|SHADER_AREA_LIGHT)
+ SHADER_MASK = ~(SHADER_SMOOTH_NORMAL|SHADER_CAST_SHADOW|SHADER_AREA_LIGHT|SHADER_USE_MIS)
} ShaderFlag;
/* Light Type */
@@ -291,7 +298,9 @@ typedef enum LightType {
LIGHT_BACKGROUND,
LIGHT_AREA,
LIGHT_AO,
- LIGHT_SPOT
+ LIGHT_SPOT,
+ LIGHT_TRIANGLE,
+ LIGHT_STRAND
} LightType;
/* Camera Type */
@@ -342,21 +351,47 @@ typedef struct Intersection {
float t, u, v;
int prim;
int object;
+ int segment;
} Intersection;
/* Attributes */
+#define ATTR_PRIM_TYPES 2
+#define ATTR_PRIM_CURVE 1
+
typedef enum AttributeElement {
+ ATTR_ELEMENT_NONE,
+ ATTR_ELEMENT_VALUE,
ATTR_ELEMENT_FACE,
ATTR_ELEMENT_VERTEX,
ATTR_ELEMENT_CORNER,
- ATTR_ELEMENT_VALUE,
- ATTR_ELEMENT_NONE
+ ATTR_ELEMENT_CURVE,
+ ATTR_ELEMENT_CURVE_KEY
} AttributeElement;
+typedef enum AttributeStandard {
+ ATTR_STD_NONE = 0,
+ ATTR_STD_VERTEX_NORMAL,
+ ATTR_STD_FACE_NORMAL,
+ ATTR_STD_UV,
+ ATTR_STD_UV_TANGENT,
+ ATTR_STD_UV_TANGENT_SIGN,
+ ATTR_STD_GENERATED,
+ ATTR_STD_POSITION_UNDEFORMED,
+ ATTR_STD_POSITION_UNDISPLACED,
+ ATTR_STD_MOTION_PRE,
+ ATTR_STD_MOTION_POST,
+ ATTR_STD_PARTICLE,
+ ATTR_STD_CURVE_TANGENT,
+ ATTR_STD_CURVE_INTERCEPT,
+ ATTR_STD_NUM,
+
+ ATTR_STD_NOT_FOUND = ~0
+} AttributeStandard;
+
/* Closure data */
-#define MAX_CLOSURE 8
+#define MAX_CLOSURE 16
typedef struct ShaderClosure {
ClosureType type;
@@ -379,6 +414,18 @@ typedef struct ShaderClosure {
#endif
} ShaderClosure;
+/* Shader Context
+ *
+ * For OSL we recycle a fixed number of contexts for speed */
+
+typedef enum ShaderContext {
+ SHADER_CONTEXT_MAIN = 0,
+ SHADER_CONTEXT_INDIRECT = 1,
+ SHADER_CONTEXT_EMISSION = 2,
+ SHADER_CONTEXT_SHADOW = 3,
+ SHADER_CONTEXT_NUM = 4
+} ShaderContext;
+
/* Shader Data
*
* Main shader state at a point on the surface or in a volume. All coordinates
@@ -423,6 +470,11 @@ typedef struct ShaderData {
/* primitive id if there is one, ~0 otherwise */
int prim;
+
+#ifdef __HAIR__
+ /* for curves, segment number in curve, ~0 for triangles */
+ int segment;
+#endif
/* parametric coordinates
* - barycentric weights for triangles */
float u, v;
@@ -466,11 +518,6 @@ typedef struct ShaderData {
/* Closure data, with a single sampled closure for low memory usage */
ShaderClosure closure;
#endif
-
-#ifdef __OSL__
- /* OSL context */
- void *osl_ctx;
-#endif
} ShaderData;
/* Constrant Kernel Data
@@ -563,9 +610,9 @@ typedef struct KernelFilm {
int pass_ao;
int pass_shadow;
+ float pass_shadow_scale;
int pass_pad1;
int pass_pad2;
- int pass_pad3;
} KernelFilm;
typedef struct KernelBackground {
@@ -596,6 +643,7 @@ typedef struct KernelIntegrator {
int num_all_lights;
float pdf_triangles;
float pdf_lights;
+ float inv_pdf_lights;
int pdf_background_res;
/* bounces */
@@ -631,7 +679,7 @@ typedef struct KernelIntegrator {
int transmission_samples;
int ao_samples;
int mesh_light_samples;
- int pad1, pad2;
+ int use_lamp_mis;
} KernelIntegrator;
typedef struct KernelBVH {
@@ -642,6 +690,30 @@ typedef struct KernelBVH {
int pad2;
} KernelBVH;
+typedef enum CurveFlag {
+ /* runtime flags */
+ CURVE_KN_BACKFACING = 1, /* backside of cylinder? */
+ CURVE_KN_ENCLOSEFILTER = 2, /* don't consider strands surrounding start point? */
+ CURVE_KN_CURVEDATA = 4, /* curve data available? */
+ CURVE_KN_INTERPOLATE = 8, /* render as a curve? - not supported yet */
+ CURVE_KN_ACCURATE = 16, /* use accurate intersections test? */
+ CURVE_KN_INTERSECTCORRECTION = 32, /* correct for width after determing closest midpoint? */
+ CURVE_KN_POSTINTERSECTCORRECTION = 64, /* correct for width after intersect? */
+ CURVE_KN_NORMALCORRECTION = 128, /* correct tangent normal for slope? */
+ CURVE_KN_TRUETANGENTGNORMAL = 256, /* use tangent normal for geometry? */
+ CURVE_KN_TANGENTGNORMAL = 512, /* use tangent normal for shader? */
+ CURVE_KN_RIBBONS = 1024, /* use flat curve ribbons */
+} CurveFlag;
+
+typedef struct KernelCurves {
+ /* strand intersect and normal parameters - many can be changed to flags*/
+ float normalmix;
+ float encasing_ratio;
+ int curveflags;
+ int subdivisions;
+
+} KernelCurves;
+
typedef struct KernelData {
KernelCamera cam;
KernelFilm film;
@@ -649,6 +721,7 @@ typedef struct KernelData {
KernelSunSky sunsky;
KernelIntegrator integrator;
KernelBVH bvh;
+ KernelCurves curve_kernel_data;
} KernelData;
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt
index 80653f24338..5a27f7823e4 100644
--- a/intern/cycles/kernel/osl/CMakeLists.txt
+++ b/intern/cycles/kernel/osl/CMakeLists.txt
@@ -16,6 +16,7 @@ set(SRC
background.cpp
bsdf_diffuse_ramp.cpp
bsdf_phong_ramp.cpp
+ bsdf_toon.cpp
emissive.cpp
osl_closures.cpp
osl_services.cpp
diff --git a/intern/cycles/kernel/osl/SConscript b/intern/cycles/kernel/osl/SConscript
index d4b42d2becb..09899567128 100644
--- a/intern/cycles/kernel/osl/SConscript
+++ b/intern/cycles/kernel/osl/SConscript
@@ -1,4 +1,29 @@
-#!/usr/bin/python
+#!/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): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
Import('env')
@@ -21,6 +46,7 @@ defs.append('WITH_OSL')
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
cxxflags.append('-DBOOST_NO_RTTI -DBOOST_NO_TYPEID'.split())
incs.append(env['BF_PTHREADS_INC'])
+ defs.append('OSL_STATIC_LIBRARY')
else:
cxxflags.append('-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID'.split())
diff --git a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
index 7189f99a822..a320bea118a 100644
--- a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
+++ b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
@@ -55,7 +55,7 @@ public:
void setup()
{
- sc.N = TO_FLOAT3(N);
+ sc.prim = this;
m_shaderdata_flag = bsdf_diffuse_ramp_setup(&sc);
for(int i = 0; i < 8; i++)
@@ -101,7 +101,7 @@ public:
ClosureParam *closure_bsdf_diffuse_ramp_params()
{
static ClosureParam params[] = {
- CLOSURE_VECTOR_PARAM(DiffuseRampClosure, N),
+ CLOSURE_FLOAT3_PARAM(DiffuseRampClosure, sc.N),
CLOSURE_COLOR_ARRAY_PARAM(DiffuseRampClosure, colors, 8),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(DiffuseRampClosure)
diff --git a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
index fb144be7e50..ef656ee7d5f 100644
--- a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
+++ b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
@@ -54,7 +54,7 @@ public:
void setup()
{
- sc.N = TO_FLOAT3(N);
+ sc.prim = this;
m_shaderdata_flag = bsdf_phong_ramp_setup(&sc);
for(int i = 0; i < 8; i++)
@@ -100,7 +100,7 @@ public:
ClosureParam *closure_bsdf_phong_ramp_params()
{
static ClosureParam params[] = {
- CLOSURE_VECTOR_PARAM(PhongRampClosure, N),
+ CLOSURE_FLOAT3_PARAM(PhongRampClosure, sc.N),
CLOSURE_FLOAT_PARAM(PhongRampClosure, sc.data0),
CLOSURE_COLOR_ARRAY_PARAM(PhongRampClosure, colors, 8),
CLOSURE_STRING_KEYPARAM("label"),
diff --git a/intern/cycles/kernel/osl/bsdf_toon.cpp b/intern/cycles/kernel/osl/bsdf_toon.cpp
new file mode 100644
index 00000000000..d409b2cedaf
--- /dev/null
+++ b/intern/cycles/kernel/osl/bsdf_toon.cpp
@@ -0,0 +1,179 @@
+/*
+ * 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.
+ */
+
+#include <OpenImageIO/fmath.h>
+
+#include <OSL/genclosure.h>
+
+#include "osl_closures.h"
+
+#include "kernel_types.h"
+#include "kernel_montecarlo.h"
+#include "closure/bsdf_toon.h"
+
+CCL_NAMESPACE_BEGIN
+
+using namespace OSL;
+
+/* DIFFUSE TOON */
+
+class DiffuseToonClosure : public CBSDFClosure {
+public:
+ DiffuseToonClosure() : CBSDFClosure(LABEL_DIFFUSE) {}
+
+ size_t memsize() const { return sizeof(*this); }
+ const char *name() const { return "diffuse_toon"; }
+
+ void setup()
+ {
+ sc.prim = this;
+ m_shaderdata_flag = bsdf_diffuse_toon_setup(&sc);
+ }
+
+ bool mergeable(const ClosurePrimitive *other) const
+ {
+ return false;
+ }
+
+ void blur(float roughness)
+ {
+ bsdf_diffuse_toon_blur(&sc, roughness);
+ }
+
+ void print_on(std::ostream &out) const
+ {
+ out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))";
+ }
+
+ float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const
+ {
+ return bsdf_diffuse_toon_eval_reflect(&sc, omega_out, omega_in, &pdf);
+ }
+
+ float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const
+ {
+ return bsdf_diffuse_toon_eval_transmit(&sc, omega_out, omega_in, &pdf);
+ }
+
+ int sample(const float3 &Ng,
+ const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy,
+ float randu, float randv,
+ float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy,
+ float &pdf, float3 &eval) const
+ {
+ return bsdf_diffuse_toon_sample(&sc, Ng, omega_out, domega_out_dx, domega_out_dy,
+ randu, randv, &eval, &omega_in, &domega_in_dx, &domega_in_dy, &pdf);
+ }
+};
+
+ClosureParam *closure_bsdf_diffuse_toon_params()
+{
+ static ClosureParam params[] = {
+ CLOSURE_FLOAT3_PARAM(DiffuseToonClosure, sc.N),
+ CLOSURE_FLOAT_PARAM(DiffuseToonClosure, sc.data0),
+ CLOSURE_FLOAT_PARAM(DiffuseToonClosure, sc.data1),
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(DiffuseToonClosure)
+ };
+ return params;
+}
+
+CLOSURE_PREPARE(closure_bsdf_diffuse_toon_prepare, DiffuseToonClosure)
+
+/* SPECULAR TOON */
+
+class SpecularToonClosure : public CBSDFClosure {
+public:
+ SpecularToonClosure() : CBSDFClosure(LABEL_GLOSSY) {}
+
+ size_t memsize() const { return sizeof(*this); }
+ const char *name() const { return "specular_toon"; }
+
+ void setup()
+ {
+ sc.prim = this;
+ m_shaderdata_flag = bsdf_specular_toon_setup(&sc);
+ }
+
+ bool mergeable(const ClosurePrimitive *other) const
+ {
+ return false;
+ }
+
+ void blur(float roughness)
+ {
+ bsdf_specular_toon_blur(&sc, roughness);
+ }
+
+ void print_on(std::ostream &out) const
+ {
+ out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))";
+ }
+
+ float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const
+ {
+ return bsdf_specular_toon_eval_reflect(&sc, omega_out, omega_in, &pdf);
+ }
+
+ float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const
+ {
+ return bsdf_specular_toon_eval_transmit(&sc, omega_out, omega_in, &pdf);
+ }
+
+ int sample(const float3 &Ng,
+ const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy,
+ float randu, float randv,
+ float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy,
+ float &pdf, float3 &eval) const
+ {
+ return bsdf_specular_toon_sample(&sc, Ng, omega_out, domega_out_dx, domega_out_dy,
+ randu, randv, &eval, &omega_in, &domega_in_dx, &domega_in_dy, &pdf);
+ }
+};
+
+ClosureParam *closure_bsdf_specular_toon_params()
+{
+ static ClosureParam params[] = {
+ CLOSURE_FLOAT3_PARAM(SpecularToonClosure, sc.N),
+ CLOSURE_FLOAT_PARAM(SpecularToonClosure, sc.data0),
+ CLOSURE_FLOAT_PARAM(SpecularToonClosure, sc.data1),
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(SpecularToonClosure)
+ };
+ return params;
+}
+
+CLOSURE_PREPARE(closure_bsdf_specular_toon_prepare, SpecularToonClosure)
+
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/osl/emissive.cpp b/intern/cycles/kernel/osl/emissive.cpp
index 37e3e37c00a..7d9fa81dbdd 100644
--- a/intern/cycles/kernel/osl/emissive.cpp
+++ b/intern/cycles/kernel/osl/emissive.cpp
@@ -65,7 +65,7 @@ public:
Color3 eval(const Vec3 &Ng, const Vec3 &omega_out) const
{
- float3 result = emissive_eval(TO_FLOAT3(Ng), TO_FLOAT3(omega_out));
+ float3 result = emissive_simple_eval(TO_FLOAT3(Ng), TO_FLOAT3(omega_out));
return TO_COLOR3(result);
}
diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp
index 1f71fde549e..9e65cda1e8f 100644
--- a/intern/cycles/kernel/osl/osl_closures.cpp
+++ b/intern/cycles/kernel/osl/osl_closures.cpp
@@ -43,12 +43,11 @@
#include "kernel_types.h"
#include "kernel_montecarlo.h"
-#include "closure/bsdf.h"
+#include "closure/bsdf_util.h"
#include "closure/bsdf_ashikhmin_velvet.h"
#include "closure/bsdf_diffuse.h"
#include "closure/bsdf_microfacet.h"
#include "closure/bsdf_oren_nayar.h"
-#include "closure/bsdf_phong_ramp.h"
#include "closure/bsdf_reflection.h"
#include "closure/bsdf_refraction.h"
#include "closure/bsdf_transparent.h"
@@ -62,34 +61,34 @@ using namespace OSL;
/* BSDF class definitions */
BSDF_CLOSURE_CLASS_BEGIN(Diffuse, diffuse, diffuse, LABEL_DIFFUSE)
- CLOSURE_VECTOR_PARAM(DiffuseClosure, N),
+ CLOSURE_FLOAT3_PARAM(DiffuseClosure, sc.N),
BSDF_CLOSURE_CLASS_END(Diffuse, diffuse)
BSDF_CLOSURE_CLASS_BEGIN(Translucent, translucent, translucent, LABEL_DIFFUSE)
- CLOSURE_VECTOR_PARAM(TranslucentClosure, N),
+ CLOSURE_FLOAT3_PARAM(TranslucentClosure, sc.N),
BSDF_CLOSURE_CLASS_END(Translucent, translucent)
BSDF_CLOSURE_CLASS_BEGIN(OrenNayar, oren_nayar, oren_nayar, LABEL_DIFFUSE)
- CLOSURE_VECTOR_PARAM(OrenNayarClosure, N),
+ CLOSURE_FLOAT3_PARAM(OrenNayarClosure, sc.N),
CLOSURE_FLOAT_PARAM(OrenNayarClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(OrenNayar, oren_nayar)
BSDF_CLOSURE_CLASS_BEGIN(Reflection, reflection, reflection, LABEL_SINGULAR)
- CLOSURE_VECTOR_PARAM(ReflectionClosure, N),
+ CLOSURE_FLOAT3_PARAM(ReflectionClosure, sc.N),
BSDF_CLOSURE_CLASS_END(Reflection, reflection)
BSDF_CLOSURE_CLASS_BEGIN(Refraction, refraction, refraction, LABEL_SINGULAR)
- CLOSURE_VECTOR_PARAM(RefractionClosure, N),
+ CLOSURE_FLOAT3_PARAM(RefractionClosure, sc.N),
CLOSURE_FLOAT_PARAM(RefractionClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(Refraction, refraction)
BSDF_CLOSURE_CLASS_BEGIN(WestinBackscatter, westin_backscatter, westin_backscatter, LABEL_GLOSSY)
- CLOSURE_VECTOR_PARAM(WestinBackscatterClosure, N),
+ 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_VECTOR_PARAM(WestinSheenClosure, N),
+ CLOSURE_FLOAT3_PARAM(WestinSheenClosure, sc.N),
CLOSURE_FLOAT_PARAM(WestinSheenClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(WestinSheen, westin_sheen)
@@ -97,35 +96,35 @@ BSDF_CLOSURE_CLASS_BEGIN(Transparent, transparent, transparent, LABEL_SINGULAR)
BSDF_CLOSURE_CLASS_END(Transparent, transparent)
BSDF_CLOSURE_CLASS_BEGIN(AshikhminVelvet, ashikhmin_velvet, ashikhmin_velvet, LABEL_DIFFUSE)
- CLOSURE_VECTOR_PARAM(AshikhminVelvetClosure, N),
+ CLOSURE_FLOAT3_PARAM(AshikhminVelvetClosure, sc.N),
CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(AshikhminVelvet, ashikhmin_velvet)
BSDF_CLOSURE_CLASS_BEGIN(Ward, ward, ward, LABEL_GLOSSY)
- CLOSURE_VECTOR_PARAM(WardClosure, N),
- CLOSURE_VECTOR_PARAM(WardClosure, T),
+ CLOSURE_FLOAT3_PARAM(WardClosure, sc.N),
+ CLOSURE_FLOAT3_PARAM(WardClosure, sc.T),
CLOSURE_FLOAT_PARAM(WardClosure, sc.data0),
CLOSURE_FLOAT_PARAM(WardClosure, sc.data1),
BSDF_CLOSURE_CLASS_END(Ward, ward)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGX, microfacet_ggx, microfacet_ggx, LABEL_GLOSSY)
- CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure, N),
+ CLOSURE_FLOAT3_PARAM(MicrofacetGGXClosure, sc.N),
CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(MicrofacetGGX, microfacet_ggx)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmann, microfacet_beckmann, microfacet_beckmann, LABEL_GLOSSY)
- CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure, N),
+ CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannClosure, sc.N),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(MicrofacetBeckmann, microfacet_beckmann)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXRefraction, microfacet_ggx_refraction, microfacet_ggx, LABEL_GLOSSY)
- CLOSURE_VECTOR_PARAM(MicrofacetGGXRefractionClosure, N),
+ CLOSURE_FLOAT3_PARAM(MicrofacetGGXRefractionClosure, sc.N),
CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, sc.data0),
CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, sc.data1),
BSDF_CLOSURE_CLASS_END(MicrofacetGGXRefraction, microfacet_ggx_refraction)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction, microfacet_beckmann, LABEL_GLOSSY)
- CLOSURE_VECTOR_PARAM(MicrofacetBeckmannRefractionClosure, N),
+ CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannRefractionClosure, sc.N),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, sc.data0),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, sc.data1),
BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction)
@@ -194,10 +193,14 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
closure_holdout_params(), closure_holdout_prepare);
register_closure(ss, "ambient_occlusion", id++,
closure_ambient_occlusion_params(), closure_ambient_occlusion_prepare);
- register_closure(ss, "phong_ramp", id++,
- closure_bsdf_phong_ramp_params(), closure_bsdf_phong_ramp_prepare);
register_closure(ss, "diffuse_ramp", id++,
closure_bsdf_diffuse_ramp_params(), closure_bsdf_diffuse_ramp_prepare);
+ register_closure(ss, "phong_ramp", id++,
+ closure_bsdf_phong_ramp_params(), closure_bsdf_phong_ramp_prepare);
+ register_closure(ss, "diffuse_toon", id++,
+ closure_bsdf_diffuse_toon_params(), closure_bsdf_diffuse_toon_prepare);
+ register_closure(ss, "specular_toon", id++,
+ closure_bsdf_specular_toon_params(), closure_bsdf_specular_toon_prepare);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h
index 5cd333c806e..daccc03ede2 100644
--- a/intern/cycles/kernel/osl/osl_closures.h
+++ b/intern/cycles/kernel/osl/osl_closures.h
@@ -47,15 +47,19 @@ OSL::ClosureParam *closure_emission_params();
OSL::ClosureParam *closure_background_params();
OSL::ClosureParam *closure_holdout_params();
OSL::ClosureParam *closure_ambient_occlusion_params();
-OSL::ClosureParam *closure_bsdf_phong_ramp_params();
OSL::ClosureParam *closure_bsdf_diffuse_ramp_params();
+OSL::ClosureParam *closure_bsdf_phong_ramp_params();
+OSL::ClosureParam *closure_bsdf_diffuse_toon_params();
+OSL::ClosureParam *closure_bsdf_specular_toon_params();
void closure_emission_prepare(OSL::RendererServices *, int id, void *data);
void closure_background_prepare(OSL::RendererServices *, int id, void *data);
void closure_holdout_prepare(OSL::RendererServices *, int id, void *data);
void closure_ambient_occlusion_prepare(OSL::RendererServices *, int id, void *data);
-void closure_bsdf_phong_ramp_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_bsdf_diffuse_toon_prepare(OSL::RendererServices *, int id, void *data);
+void closure_bsdf_specular_toon_prepare(OSL::RendererServices *, int id, void *data);
enum {
AmbientOcclusion = 100
@@ -70,8 +74,11 @@ void name(RendererServices *, int id, void *data) \
#define CLOSURE_PREPARE_STATIC(name, classname) static CLOSURE_PREPARE(name, classname)
-#define TO_VEC3(v) (*(OSL::Vec3 *)&(v))
-#define TO_COLOR3(v) (*(OSL::Color3 *)&(v))
+#define CLOSURE_FLOAT3_PARAM(st, fld) \
+ { TypeDesc::TypeVector, reckless_offsetof(st, fld), NULL, sizeof(OSL::Vec3) }
+
+#define TO_VEC3(v) OSL::Vec3(v.x, v.y, v.z)
+#define TO_COLOR3(v) OSL::Color3(v.x, v.y, v.z)
#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2])
/* BSDF */
@@ -79,7 +86,6 @@ void name(RendererServices *, int id, void *data) \
class CBSDFClosure : public OSL::ClosurePrimitive {
public:
ShaderClosure sc;
- OSL::Vec3 N, T;
CBSDFClosure(int scattering) : OSL::ClosurePrimitive(BSDF),
m_scattering_label(scattering), m_shaderdata_flag(0) { }
@@ -87,7 +93,6 @@ public:
int scattering() const { return m_scattering_label; }
int shaderdata_flag() const { return m_shaderdata_flag; }
- ClosureType shaderclosure_type() const { return sc.type; }
virtual void blur(float roughness) = 0;
virtual float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0;
@@ -114,8 +119,7 @@ public: \
\
void setup() \
{ \
- sc.N = TO_FLOAT3(N); \
- sc.T = TO_FLOAT3(T); \
+ sc.prim = NULL; \
m_shaderdata_flag = bsdf_##lower##_setup(&sc); \
} \
\
diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h
index 1a2a210de88..fb569117698 100644
--- a/intern/cycles/kernel/osl/osl_globals.h
+++ b/intern/cycles/kernel/osl/osl_globals.h
@@ -75,10 +75,21 @@ struct OSLGlobals {
vector<ustring> object_names;
};
+/* trace() call result */
+struct OSLTraceData {
+ Ray ray;
+ Intersection isect;
+ ShaderData sd;
+ bool setup;
+ bool init;
+};
+
/* thread key for thread specific data lookup */
struct OSLThreadData {
OSL::ShaderGlobals globals;
OSL::PerThreadInfo *thread_info;
+ OSLTraceData tracedata;
+ OSL::ShadingContext *context[SHADER_CONTEXT_NUM];
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index b584a54b1b7..92a023bd765 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -37,9 +37,10 @@
#include "kernel_differential.h"
#include "kernel_object.h"
#include "kernel_bvh.h"
-#include "kernel_attribute.h"
-#include "kernel_projection.h"
#include "kernel_triangle.h"
+#include "kernel_curve.h"
+#include "kernel_primitive.h"
+#include "kernel_projection.h"
#include "kernel_accumulate.h"
#include "kernel_shader.h"
@@ -47,7 +48,7 @@ CCL_NAMESPACE_BEGIN
/* RenderServices implementation */
-#define TO_MATRIX44(m) (*(OSL::Matrix44 *)&(m))
+#define COPY_MATRIX44(m1, m2) memcpy(m1, m2, sizeof(*m2))
/* static ustrings */
ustring OSLRenderServices::u_distance("distance");
@@ -74,6 +75,11 @@ ustring OSLRenderServices::u_geom_numpolyvertices("geom:numpolyvertices");
ustring OSLRenderServices::u_geom_trianglevertices("geom:trianglevertices");
ustring OSLRenderServices::u_geom_polyvertices("geom:polyvertices");
ustring OSLRenderServices::u_geom_name("geom:name");
+#ifdef __HAIR__
+ustring OSLRenderServices::u_is_curve("geom:is_curve");
+ustring OSLRenderServices::u_curve_thickness("geom:curve_thickness");
+ustring OSLRenderServices::u_curve_tangent_normal("geom:curve_tangent_normal");
+#endif
ustring OSLRenderServices::u_path_ray_length("path:ray_length");
ustring OSLRenderServices::u_trace("trace");
ustring OSLRenderServices::u_hit("hit");
@@ -121,7 +127,7 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr
Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
#endif
tfm = transform_transpose(tfm);
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
@@ -151,7 +157,7 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::Transform
Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
#endif
itfm = transform_transpose(itfm);
- result = TO_MATRIX44(itfm);
+ COPY_MATRIX44(&result, &itfm);
return true;
}
@@ -166,22 +172,22 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from, float ti
if (from == u_ndc) {
Transform tfm = transform_transpose(transform_quick_inverse(kernel_data.cam.worldtondc));
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
else if (from == u_raster) {
Transform tfm = transform_transpose(kernel_data.cam.rastertoworld);
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
else if (from == u_screen) {
Transform tfm = transform_transpose(kernel_data.cam.screentoworld);
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
else if (from == u_camera) {
Transform tfm = transform_transpose(kernel_data.cam.cameratoworld);
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
@@ -194,22 +200,22 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to, fl
if (to == u_ndc) {
Transform tfm = transform_transpose(kernel_data.cam.worldtondc);
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
else if (to == u_raster) {
Transform tfm = transform_transpose(kernel_data.cam.worldtoraster);
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
else if (to == u_screen) {
Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen);
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
else if (to == u_camera) {
Transform tfm = transform_transpose(kernel_data.cam.worldtocamera);
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
@@ -232,7 +238,7 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr
Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
#endif
tfm = transform_transpose(tfm);
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
@@ -257,7 +263,7 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::Transform
Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
#endif
tfm = transform_transpose(tfm);
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
@@ -272,22 +278,22 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from)
if (from == u_ndc) {
Transform tfm = transform_transpose(transform_quick_inverse(kernel_data.cam.worldtondc));
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
else if (from == u_raster) {
Transform tfm = transform_transpose(kernel_data.cam.rastertoworld);
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
else if (from == u_screen) {
Transform tfm = transform_transpose(kernel_data.cam.screentoworld);
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
else if (from == u_camera) {
Transform tfm = transform_transpose(kernel_data.cam.cameratoworld);
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
@@ -300,22 +306,22 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to)
if (to == u_ndc) {
Transform tfm = transform_transpose(kernel_data.cam.worldtondc);
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
else if (to == u_raster) {
Transform tfm = transform_transpose(kernel_data.cam.worldtoraster);
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
else if (to == u_screen) {
Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen);
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
else if (to == u_camera) {
Transform tfm = transform_transpose(kernel_data.cam.worldtocamera);
- result = TO_MATRIX44(tfm);
+ COPY_MATRIX44(&result, &tfm);
return true;
}
@@ -495,14 +501,14 @@ static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OS
attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor)
{
float3 fval[3];
- fval[0] = triangle_attribute_float3(kg, sd, attr.elem, attr.offset,
- (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
+ 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) {
float fval[3];
- fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset,
- (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
+ fval[0] = primitive_attribute_float(kg, sd, attr.elem, attr.offset,
+ (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
return set_attribute_float(fval, type, derivatives, val);
}
else {
@@ -593,10 +599,17 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
float3 f = particle_angular_velocity(kg, particle_id);
return set_attribute_float3(f, type, derivatives, val);
}
+
+ /* Geometry Attributes */
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->segment == ~0) {
+#else
+ ) {
+#endif
float3 P[3];
triangle_vertices(kg, sd->prim, P);
@@ -612,6 +625,22 @@ 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);
}
+
+#ifdef __HAIR__
+ /* Hair Attributes */
+ else if (name == u_is_curve) {
+ float f = (sd->segment != ~0);
+ return set_attribute_float(f, type, derivatives, val);
+ }
+ 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) {
+ float3 f = curve_tangent_normal(kg, sd);
+ return set_attribute_float3(f, type, derivatives, val);
+ }
+#endif
else
return false;
}
@@ -634,24 +663,34 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
{
KernelGlobals *kg = kernel_globals;
ShaderData *sd = (ShaderData *)renderstate;
- int object = sd->object;
- int tri = sd->prim;
+ int object, prim, segment;
/* lookup of attribute on another object */
- if (object_name != u_empty) {
+ if (object_name != u_empty || sd == NULL) {
OSLGlobals::ObjectNameMap::iterator it = kg->osl->object_name_map.find(object_name);
if (it == kg->osl->object_name_map.end())
return false;
object = it->second;
- tri = ~0;
+ prim = ~0;
+ segment = ~0;
}
- else if (object == ~0) {
- return get_background_attribute(kg, sd, name, type, derivatives, val);
+ else {
+ object = sd->object;
+ prim = sd->prim;
+#ifdef __HAIR__
+ segment = sd->segment;
+#else
+ segment = ~0;
+#endif
+
+ if (object == ~0)
+ return get_background_attribute(kg, sd, name, type, derivatives, val);
}
/* find attribute on object */
+ object = object*ATTR_PRIM_TYPES + (segment != ~0);
OSLGlobals::AttributeMap& attribute_map = kg->osl->attribute_map[object];
OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);
@@ -660,7 +699,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
if (attr.elem != ATTR_ELEMENT_VALUE) {
/* triangle and vertex attributes */
- if (tri != ~0)
+ if (prim != ~0)
return get_mesh_attribute(kg, sd, attr, type, derivatives, val);
}
else {
@@ -815,13 +854,10 @@ bool OSLRenderServices::trace(TraceOpt &options, OSL::ShaderGlobals *sg,
ray.dD.dy = TO_FLOAT3(dRdy);
/* allocate trace data */
- TraceData *tracedata = new TraceData();
+ OSLTraceData *tracedata = (OSLTraceData*)sg->tracedata;
tracedata->ray = ray;
tracedata->setup = false;
-
- if(sg->tracedata)
- delete (TraceData*)sg->tracedata;
- sg->tracedata = tracedata;
+ tracedata->init = true;
/* raytrace */
return scene_intersect(kernel_globals, &ray, ~0, &tracedata->isect);
@@ -831,9 +867,9 @@ bool OSLRenderServices::trace(TraceOpt &options, OSL::ShaderGlobals *sg,
bool OSLRenderServices::getmessage(OSL::ShaderGlobals *sg, ustring source, ustring name,
TypeDesc type, void *val, bool derivatives)
{
- TraceData *tracedata = (TraceData*)sg->tracedata;
+ OSLTraceData *tracedata = (OSLTraceData*)sg->tracedata;
- if(source == u_trace && tracedata) {
+ if(source == u_trace && tracedata->init) {
if(name == u_hit) {
return set_attribute_int((tracedata->isect.prim != ~0), type, derivatives, val);
}
diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h
index e687700b383..50c50b9952c 100644
--- a/intern/cycles/kernel/osl/osl_services.h
+++ b/intern/cycles/kernel/osl/osl_services.h
@@ -106,13 +106,6 @@ public:
static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ustring name,
TypeDesc type, bool derivatives, void *val);
- struct TraceData {
- Ray ray;
- Intersection isect;
- ShaderData sd;
- bool setup;
- };
-
static ustring u_distance;
static ustring u_index;
static ustring u_camera;
@@ -137,6 +130,9 @@ public:
static ustring u_geom_trianglevertices;
static ustring u_geom_polyvertices;
static ustring u_geom_name;
+ static ustring u_is_curve;
+ static ustring u_curve_thickness;
+ static ustring u_curve_tangent_normal;
static ustring u_path_ray_length;
static ustring u_trace;
static ustring u_hit;
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index 32712b25e92..a32c526a2be 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -26,9 +26,10 @@
#include "osl_services.h"
#include "osl_shader.h"
-#include "util_attribute.h"
#include "util_foreach.h"
+#include "attribute.h"
+
#include <OSL/oslexec.h>
CCL_NAMESPACE_BEGIN
@@ -51,8 +52,13 @@ void OSLShader::thread_init(KernelGlobals *kg, KernelGlobals *kernel_globals, OS
OSLThreadData *tdata = new OSLThreadData();
memset(&tdata->globals, 0, sizeof(OSL::ShaderGlobals));
+ tdata->globals.tracedata = &tdata->tracedata;
+ tdata->globals.flipHandedness = false;
tdata->thread_info = ss->create_thread_info();
+ for(int i = 0; i < SHADER_CONTEXT_NUM; i++)
+ tdata->context[i] = ss->get_context(tdata->thread_info);
+
kg->osl_ss = (OSLShadingSystem*)ss;
kg->osl_tdata = tdata;
}
@@ -65,6 +71,9 @@ void OSLShader::thread_free(KernelGlobals *kg)
OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
OSLThreadData *tdata = kg->osl_tdata;
+ for(int i = 0; i < SHADER_CONTEXT_NUM; i++)
+ ss->release_context(tdata->context[i]);
+
ss->destroy_thread_info(tdata->thread_info);
delete tdata;
@@ -77,8 +86,10 @@ void OSLShader::thread_free(KernelGlobals *kg)
/* Globals */
static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd,
- int path_flag, OSL::ShaderGlobals *globals)
+ int path_flag, OSLThreadData *tdata)
{
+ OSL::ShaderGlobals *globals = &tdata->globals;
+
/* copy from shader data to shader globals */
globals->P = TO_VEC3(sd->P);
globals->dPdx = TO_VEC3(sd->dP.dx);
@@ -100,15 +111,11 @@ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd,
globals->time = sd->time;
/* booleans */
- globals->raytype = path_flag; /* todo: add our own ray types */
+ globals->raytype = path_flag;
globals->backfacing = (sd->flag & SD_BACKFACING);
- /* don't know yet if we need this */
- globals->flipHandedness = false;
-
/* shader data to be used in services callbacks */
globals->renderstate = sd;
- globals->tracedata = NULL;
/* hacky, we leave it to services to fetch actual object matrix */
globals->shader2common = sd;
@@ -116,6 +123,9 @@ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd,
/* must be set to NULL before execute */
globals->Ci = NULL;
+
+ /* clear trace data */
+ tdata->tracedata.init = false;
}
/* Surface */
@@ -132,14 +142,10 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
if (prim) {
ShaderClosure sc;
- sc.prim = prim;
sc.weight = weight;
switch (prim->category()) {
case OSL::ClosurePrimitive::BSDF: {
- if (sd->num_closure == MAX_CLOSURE)
- return;
-
CBSDFClosure *bsdf = (CBSDFClosure *)prim;
int scattering = bsdf->scattering();
@@ -151,8 +157,13 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
float sample_weight = fabsf(average(weight));
sc.sample_weight = sample_weight;
- sc.type = bsdf->shaderclosure_type();
- sc.N = bsdf->sc.N; /* needed for AO */
+
+ 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.prim = bsdf->sc.prim;
/* add */
if(sc.sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE) {
@@ -162,14 +173,12 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
break;
}
case OSL::ClosurePrimitive::Emissive: {
- if (sd->num_closure == MAX_CLOSURE)
- return;
-
/* sample weight */
float sample_weight = fabsf(average(weight));
sc.sample_weight = sample_weight;
sc.type = CLOSURE_EMISSION_ID;
+ sc.prim = NULL;
/* flag */
if(sd->num_closure < MAX_CLOSURE) {
@@ -179,14 +188,12 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
break;
}
case AmbientOcclusion: {
- if (sd->num_closure == MAX_CLOSURE)
- return;
-
/* sample weight */
float sample_weight = fabsf(average(weight));
sc.sample_weight = sample_weight;
sc.type = CLOSURE_AMBIENT_OCCLUSION_ID;
+ sc.prim = NULL;
if(sd->num_closure < MAX_CLOSURE) {
sd->closure[sd->num_closure++] = sc;
@@ -195,11 +202,9 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
break;
}
case OSL::ClosurePrimitive::Holdout:
- if (sd->num_closure == MAX_CLOSURE)
- return;
-
sc.sample_weight = 0.0f;
sc.type = CLOSURE_HOLDOUT_ID;
+ sc.prim = NULL;
if(sd->num_closure < MAX_CLOSURE) {
sd->closure[sd->num_closure++] = sc;
@@ -226,26 +231,20 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
}
}
-void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag)
+void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag, ShaderContext ctx)
{
- /* gather pointers */
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
- OSLThreadData *tdata = kg->osl_tdata;
- OSL::ShaderGlobals *globals = &tdata->globals;
- OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx;
-
/* setup shader globals from shader data */
- shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
+ OSLThreadData *tdata = kg->osl_tdata;
+ shaderdata_to_shaderglobals(kg, sd, path_flag, tdata);
/* execute shader for this point */
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
+ OSL::ShaderGlobals *globals = &tdata->globals;
+ OSL::ShadingContext *octx = tdata->context[(int)ctx];
int shader = sd->shader & SHADER_MASK;
if (kg->osl->surface_state[shader])
- ss->execute(*ctx, *(kg->osl->surface_state[shader]), *globals);
-
- /* free trace data */
- if(globals->tracedata)
- delete (OSLRenderServices::TraceData*)globals->tracedata;
+ ss->execute(*octx, *(kg->osl->surface_state[shader]), *globals);
/* flatten closure tree */
sd->num_closure = 0;
@@ -287,24 +286,19 @@ static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure)
return make_float3(0.0f, 0.0f, 0.0f);
}
-float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag)
+float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag, ShaderContext ctx)
{
- /* gather pointers */
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
- OSLThreadData *tdata = kg->osl_tdata;
- OSL::ShaderGlobals *globals = &tdata->globals;
- OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx;
-
/* setup shader globals from shader data */
- shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
+ OSLThreadData *tdata = kg->osl_tdata;
+ shaderdata_to_shaderglobals(kg, sd, path_flag, tdata);
/* execute shader for this point */
- if (kg->osl->background_state)
- ss->execute(*ctx, *(kg->osl->background_state), *globals);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
+ OSL::ShaderGlobals *globals = &tdata->globals;
+ OSL::ShadingContext *octx = tdata->context[(int)ctx];
- /* free trace data */
- if(globals->tracedata)
- delete (OSLRenderServices::TraceData*)globals->tracedata;
+ if (kg->osl->background_state)
+ ss->execute(*octx, *(kg->osl->background_state), *globals);
/* return background color immediately */
if (globals->Ci)
@@ -327,19 +321,16 @@ static void flatten_volume_closure_tree(ShaderData *sd,
if (prim) {
ShaderClosure sc;
- sc.prim = prim;
sc.weight = weight;
switch (prim->category()) {
case OSL::ClosurePrimitive::Volume: {
- if (sd->num_closure == MAX_CLOSURE)
- return;
-
/* sample weight */
float sample_weight = fabsf(average(weight));
sc.sample_weight = sample_weight;
sc.type = CLOSURE_VOLUME_ID;
+ sc.prim = NULL;
/* add */
if(sc.sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE)
@@ -368,26 +359,20 @@ static void flatten_volume_closure_tree(ShaderData *sd,
}
}
-void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag)
+void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag, ShaderContext ctx)
{
- /* gather pointers */
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
- OSLThreadData *tdata = kg->osl_tdata;
- OSL::ShaderGlobals *globals = &tdata->globals;
- OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx;
-
/* setup shader globals from shader data */
- shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
+ OSLThreadData *tdata = kg->osl_tdata;
+ shaderdata_to_shaderglobals(kg, sd, path_flag, tdata);
/* execute shader */
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
+ OSL::ShaderGlobals *globals = &tdata->globals;
+ OSL::ShadingContext *octx = tdata->context[(int)ctx];
int shader = sd->shader & SHADER_MASK;
if (kg->osl->volume_state[shader])
- ss->execute(*ctx, *(kg->osl->volume_state[shader]), *globals);
-
- /* free trace data */
- if(globals->tracedata)
- delete (OSLRenderServices::TraceData*)globals->tracedata;
+ ss->execute(*octx, *(kg->osl->volume_state[shader]), *globals);
if (globals->Ci)
flatten_volume_closure_tree(sd, globals->Ci);
@@ -395,46 +380,25 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int
/* Displacement */
-void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd)
+void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderContext ctx)
{
- /* gather pointers */
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
- OSLThreadData *tdata = kg->osl_tdata;
- OSL::ShaderGlobals *globals = &tdata->globals;
- OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx;
-
/* setup shader globals from shader data */
- shaderdata_to_shaderglobals(kg, sd, 0, globals);
+ OSLThreadData *tdata = kg->osl_tdata;
+ shaderdata_to_shaderglobals(kg, sd, 0, tdata);
/* execute shader */
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
+ OSL::ShaderGlobals *globals = &tdata->globals;
+ OSL::ShadingContext *octx = tdata->context[(int)ctx];
int shader = sd->shader & SHADER_MASK;
if (kg->osl->displacement_state[shader])
- ss->execute(*ctx, *(kg->osl->displacement_state[shader]), *globals);
-
- /* free trace data */
- if(globals->tracedata)
- delete (OSLRenderServices::TraceData*)globals->tracedata;
+ ss->execute(*octx, *(kg->osl->displacement_state[shader]), *globals);
/* get back position */
sd->P = TO_FLOAT3(globals->P);
}
-void OSLShader::init(KernelGlobals *kg, ShaderData *sd)
-{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
- OSLThreadData *tdata = kg->osl_tdata;
-
- sd->osl_ctx = ss->get_context(tdata->thread_info);
-}
-
-void OSLShader::release(KernelGlobals *kg, ShaderData *sd)
-{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
-
- ss->release_context((OSL::ShadingContext *)sd->osl_ctx);
-}
-
/* BSDF Closure */
int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3& eval, float3& omega_in, differential3& domega_in, float& pdf)
@@ -490,15 +454,21 @@ float3 OSLShader::volume_eval_phase(const ShaderClosure *sc, const float3 omega_
/* Attributes */
-int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id)
+int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem)
{
/* for OSL, a hash map is used to lookup the attribute by name. */
- OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[sd->object];
- ustring stdname(std::string("std::") + std::string(attribute_standard_name((AttributeStandard)id)));
+ int object = sd->object*ATTR_PRIM_TYPES;
+#ifdef __HAIR__
+ if(sd->segment != ~0) object += ATTR_PRIM_CURVE;
+#endif
+
+ OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[object];
+ 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()) {
const OSLGlobals::Attribute &osl_attr = it->second;
+ *elem = osl_attr.elem;
/* return result */
return (osl_attr.elem == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : osl_attr.offset;
}
diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h
index e614f240dc1..2062c651162 100644
--- a/intern/cycles/kernel/osl/osl_shader.h
+++ b/intern/cycles/kernel/osl/osl_shader.h
@@ -55,10 +55,10 @@ public:
static void thread_free(KernelGlobals *kg);
/* eval */
- static void eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag);
- static float3 eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag);
- static void eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag);
- static void eval_displacement(KernelGlobals *kg, ShaderData *sd);
+ static void eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag, ShaderContext ctx);
+ static float3 eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag, ShaderContext ctx);
+ static void eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag, ShaderContext ctx);
+ static void eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderContext ctx);
/* sample & eval */
static int bsdf_sample(const ShaderData *sd, const ShaderClosure *sc,
@@ -73,12 +73,8 @@ public:
static float3 volume_eval_phase(const ShaderClosure *sc,
const float3 omega_in, const float3 omega_out);
- /* release */
- static void init(KernelGlobals *kg, ShaderData *sd);
- static void release(KernelGlobals *kg, ShaderData *sd);
-
/* attributes */
- static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id);
+ static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt
index 70fc8610c98..acae46f1615 100644
--- a/intern/cycles/kernel/shaders/CMakeLists.txt
+++ b/intern/cycles/kernel/shaders/CMakeLists.txt
@@ -27,6 +27,7 @@ set(SRC_OSL
node_glass_bsdf.osl
node_glossy_bsdf.osl
node_gradient_texture.osl
+ node_hair_info.osl
node_holdout.osl
node_hsv.osl
node_image_texture.osl
diff --git a/intern/cycles/kernel/shaders/SConscript b/intern/cycles/kernel/shaders/SConscript
index 36b86d7b4f6..daf2b67ad2b 100644
--- a/intern/cycles/kernel/shaders/SConscript
+++ b/intern/cycles/kernel/shaders/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/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): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
import sys
import os
import Blender as B
diff --git a/intern/cycles/kernel/shaders/node_geometry.osl b/intern/cycles/kernel/shaders/node_geometry.osl
index d1c11b70081..3d5d67360ce 100644
--- a/intern/cycles/kernel/shaders/node_geometry.osl
+++ b/intern/cycles/kernel/shaders/node_geometry.osl
@@ -56,8 +56,7 @@ shader node_geometry(
0.0, 0.0, 0.0, 0.0,
0.5, -0.5, 0.0, 1.0);
- vector T = transform(project, generated);
- T = transform("object", "world", T);
+ vector T = transform("object", "world", transform(project, generated));
Tangent = cross(Normal, normalize(cross(T, Normal)));
}
else {
diff --git a/intern/cycles/kernel/shaders/node_hair_info.osl b/intern/cycles/kernel/shaders/node_hair_info.osl
new file mode 100644
index 00000000000..cbb3b98383f
--- /dev/null
+++ b/intern/cycles/kernel/shaders/node_hair_info.osl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2012, 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.
+ */
+
+#include "stdosl.h"
+
+shader node_hair_info(
+ output float IsStrand = 0.0,
+ output float Intercept = 0.0,
+ output float Thickness = 0.0,
+ output normal TangentNormal = N)
+{
+ getattribute("geom:is_curve", IsStrand);
+ getattribute("geom:curve_intercept", Intercept);
+ getattribute("geom:curve_thickness", Thickness);
+ getattribute("geom:curve_tangent_normal", TangentNormal);
+}
+
diff --git a/intern/cycles/kernel/shaders/node_mapping.osl b/intern/cycles/kernel/shaders/node_mapping.osl
index 92df043b39d..787f65217aa 100644
--- a/intern/cycles/kernel/shaders/node_mapping.osl
+++ b/intern/cycles/kernel/shaders/node_mapping.osl
@@ -28,9 +28,8 @@ shader node_mapping(
{
point p = transform(Matrix, VectorIn);
- if(use_minmax)
+ if (use_minmax)
p = min(max(mapping_min, p), mapping_max);
VectorOut = p;
}
-
diff --git a/intern/cycles/kernel/shaders/node_math.osl b/intern/cycles/kernel/shaders/node_math.osl
index 24dce898fd2..2ec1a5f0a32 100644
--- a/intern/cycles/kernel/shaders/node_math.osl
+++ b/intern/cycles/kernel/shaders/node_math.osl
@@ -49,37 +49,37 @@ shader node_math(
if (type == "Add")
Value = Value1 + Value2;
- if (type == "Subtract")
+ else if (type == "Subtract")
Value = Value1 - Value2;
- if (type == "Multiply")
+ else if (type == "Multiply")
Value = Value1 * Value2;
- if (type == "Divide")
+ else if (type == "Divide")
Value = safe_divide(Value1, Value2);
- if (type == "Sine")
+ else if (type == "Sine")
Value = sin(Value1);
- if (type == "Cosine")
+ else if (type == "Cosine")
Value = cos(Value1);
- if (type == "Tangent")
+ else if (type == "Tangent")
Value = tan(Value1);
- if (type == "Arcsine")
+ else if (type == "Arcsine")
Value = asin(Value1);
- if (type == "Arccosine")
+ else if (type == "Arccosine")
Value = acos(Value1);
- if (type == "Arctangent")
+ else if (type == "Arctangent")
Value = atan(Value1);
- if (type == "Power")
+ else if (type == "Power")
Value = pow(Value1, Value2);
- if (type == "Logarithm")
+ else if (type == "Logarithm")
Value = safe_log(Value1, Value2);
- if (type == "Minimum")
+ else if (type == "Minimum")
Value = min(Value1, Value2);
- if (type == "Maximum")
+ else if (type == "Maximum")
Value = max(Value1, Value2);
- if (type == "Round")
+ else if (type == "Round")
Value = floor(Value1 + 0.5);
- if (type == "Less Than")
+ else if (type == "Less Than")
Value = Value1 < Value2;
- if (type == "Greater Than")
+ else if (type == "Greater Than")
Value = Value1 > Value2;
if (Clamp)
diff --git a/intern/cycles/kernel/shaders/node_musgrave_texture.osl b/intern/cycles/kernel/shaders/node_musgrave_texture.osl
index 541f26b4e56..8675c23d0d8 100644
--- a/intern/cycles/kernel/shaders/node_musgrave_texture.osl
+++ b/intern/cycles/kernel/shaders/node_musgrave_texture.osl
@@ -37,14 +37,14 @@ float noise_musgrave_fBm(point p, string basis, float H, float lacunarity, float
int i;
for (i = 0; i < (int)octaves; i++) {
- value += noise("perlin", p) * pwr;
+ value += safe_noise(p, 0) * pwr;
pwr *= pwHL;
p *= lacunarity;
}
rmd = octaves - floor(octaves);
if (rmd != 0.0)
- value += rmd * noise("perlin", p) * pwr;
+ value += rmd * safe_noise(p, 0) * pwr;
return value;
}
@@ -65,14 +65,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 * noise("perlin", p) + 1.0);
+ value *= (pwr * safe_noise(p, 0) + 1.0);
pwr *= pwHL;
p *= lacunarity;
}
rmd = octaves - floor(octaves);
if (rmd != 0.0)
- value *= (rmd * pwr * noise("perlin", p) + 1.0); /* correct? */
+ value *= (rmd * pwr * safe_noise(p, 0) + 1.0); /* correct? */
return value;
}
@@ -93,11 +93,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 + noise("perlin", p);
+ value = offset + safe_noise(p, 0);
p *= lacunarity;
for (i = 1; i < (int)octaves; i++) {
- increment = (noise("perlin", p) + offset) * pwr * value;
+ increment = (safe_noise(p, 0) + offset) * pwr * value;
value += increment;
pwr *= pwHL;
p *= lacunarity;
@@ -105,7 +105,7 @@ float noise_musgrave_hetero_terrain(point p, string basis, float H, float lacuna
rmd = octaves - floor(octaves);
if (rmd != 0.0) {
- increment = (noise("perlin", p) + offset) * pwr * value;
+ increment = (safe_noise(p, 0) + offset) * pwr * value;
value += rmd * increment;
}
@@ -128,7 +128,7 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H,
float pwr = pwHL;
int i;
- result = noise("perlin", p) + offset;
+ result = safe_noise(p, 0) + offset;
weight = gain * result;
p *= lacunarity;
@@ -136,7 +136,7 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H,
if (weight > 1.0)
weight = 1.0;
- signal = (noise("perlin", p) + offset) * pwr;
+ signal = (safe_noise(p, 0) + offset) * pwr;
pwr *= pwHL;
result += weight * signal;
weight *= gain * signal;
@@ -145,7 +145,7 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H,
rmd = octaves - floor(octaves);
if (rmd != 0.0)
- result += rmd * ((noise("perlin", p) + offset) * pwr);
+ result += rmd * ((safe_noise(p, 0) + offset) * pwr);
return result;
}
@@ -166,7 +166,7 @@ float noise_musgrave_ridged_multi_fractal(point p, string basis, float H,
float pwr = pwHL;
int i;
- signal = offset - fabs(noise("perlin", p));
+ signal = offset - fabs(safe_noise(p, 0));
signal *= signal;
result = signal;
weight = 1.0;
@@ -174,7 +174,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(noise("perlin", p));
+ signal = offset - fabs(safe_noise(p, 0));
signal *= signal;
signal *= weight;
result += signal * pwr;
diff --git a/intern/cycles/kernel/shaders/node_normal_map.osl b/intern/cycles/kernel/shaders/node_normal_map.osl
index dc25eb8539f..21382fab06f 100644
--- a/intern/cycles/kernel/shaders/node_normal_map.osl
+++ b/intern/cycles/kernel/shaders/node_normal_map.osl
@@ -31,15 +31,23 @@ shader node_normal_map(
if (space == "Tangent") {
vector tangent;
+ vector ninterp;
float tangent_sign;
- getattribute(attr_name, tangent);
- getattribute(attr_sign_name, tangent_sign);
+ // get _unnormalized_ interpolated normal and tangent
+ if(!getattribute(attr_name, tangent) ||
+ !getattribute(attr_sign_name, tangent_sign) ||
+ !getattribute("geom:N", ninterp)) {
+ Normal = normal(0, 0, 0);
+ }
+ else {
+ // apply normal map
+ vector B = tangent_sign * cross(ninterp, tangent);
+ Normal = normalize(mcolor[0] * tangent + mcolor[1] * B + mcolor[2] * ninterp);
- tangent = transform("object", "world", tangent);
-
- vector B = tangent_sign * cross(NormalIn, tangent);
- Normal = normalize(mcolor[0] * tangent + mcolor[1] * B + mcolor[2] * NormalIn);
+ // transform to world space
+ Normal = normalize(transform("object", "world", Normal));
+ }
}
else if (space == "Object")
Normal = normalize(transform("object", "world", vector(mcolor)));
diff --git a/intern/cycles/kernel/shaders/node_texture.h b/intern/cycles/kernel/shaders/node_texture.h
index 1b3ba8207ab..f2aedb098d4 100644
--- a/intern/cycles/kernel/shaders/node_texture.h
+++ b/intern/cycles/kernel/shaders/node_texture.h
@@ -18,24 +18,22 @@
float voronoi_distance(string distance_metric, vector d, float e)
{
- float result = 0.0;
-
if (distance_metric == "Distance Squared")
- result = dot(d, d);
+ return dot(d, d);
if (distance_metric == "Actual Distance")
- result = length(d);
+ return length(d);
if (distance_metric == "Manhattan")
- result = fabs(d[0]) + fabs(d[1]) + fabs(d[2]);
+ return fabs(d[0]) + fabs(d[1]) + fabs(d[2]);
if (distance_metric == "Chebychev")
- result = max(fabs(d[0]), max(fabs(d[1]), fabs(d[2])));
+ return max(fabs(d[0]), max(fabs(d[1]), fabs(d[2])));
if (distance_metric == "Minkovsky 1/2")
- result = sqrt(fabs(d[0])) + sqrt(fabs(d[1])) + sqrt(fabs(d[1]));
+ return sqrt(fabs(d[0])) + sqrt(fabs(d[1])) + sqrt(fabs(d[1]));
if (distance_metric == "Minkovsky 4")
- result = sqrt(sqrt(dot(d * d, d * d)));
+ return sqrt(sqrt(dot(d * d, d * d)));
if (distance_metric == "Minkovsky")
- result = pow(pow(fabs(d[0]), e) + pow(fabs(d[1]), e) + pow(fabs(d[2]), e), 1.0 / e);
+ return pow(pow(fabs(d[0]), e) + pow(fabs(d[1]), e) + pow(fabs(d[2]), e), 1.0 / e);
- return result;
+ return 0.0;
}
/* Voronoi / Worley like */
@@ -151,28 +149,45 @@ float voronoi_CrS(point p) { return 2.0 * voronoi_Cr(p) - 1.0; }
/* Noise Bases */
-float noise_basis(point p, string basis)
+float safe_noise(point p, int type)
{
- float result = 0.0;
+ float f = 0.0;
+
+ /* Perlin noise in range -1..1 */
+ if (type == 0)
+ f = noise("perlin", p);
+
+ /* Perlin noise in range 0..1 */
+ else
+ f = noise(p);
+
+ /* can happen for big coordinates, things even out to 0.5 then anyway */
+ if(!isfinite(f))
+ return 0.5;
+
+ return f;
+}
+float noise_basis(point p, string basis)
+{
if (basis == "Perlin")
- result = noise(p); /* returns perlin noise in range 0..1 */
+ return safe_noise(p, 1);
if (basis == "Voronoi F1")
- result = voronoi_F1S(p);
+ return voronoi_F1S(p);
if (basis == "Voronoi F2")
- result = voronoi_F2S(p);
+ return voronoi_F2S(p);
if (basis == "Voronoi F3")
- result = voronoi_F3S(p);
+ return voronoi_F3S(p);
if (basis == "Voronoi F4")
- result = voronoi_F4S(p);
+ return voronoi_F4S(p);
if (basis == "Voronoi F2-F1")
- result = voronoi_F1F2S(p);
+ return voronoi_F1F2S(p);
if (basis == "Voronoi Crackle")
- result = voronoi_CrS(p);
+ return voronoi_CrS(p);
if (basis == "Cell Noise")
- result = cellnoise(p);
+ return cellnoise(p);
- return result;
+ return 0.0;
}
/* Soft/Hard Noise */
@@ -190,24 +205,24 @@ float noise_wave(string wave, float a)
float result = 0.0;
if (wave == "Sine") {
- result = 0.5 + 0.5 * sin(a);
+ return 0.5 + 0.5 * sin(a);
}
- else if (wave == "Saw") {
+ if (wave == "Saw") {
float b = 2 * M_PI;
int n = (int)(a / b);
a -= n * b;
if (a < 0) a += b;
- result = a / b;
+ return a / b;
}
- else if (wave == "Tri") {
+ if (wave == "Tri") {
float b = 2 * M_PI;
float rmax = 1.0;
- result = rmax - 2.0 * fabs(floor((a * (1.0 / b)) + 0.5) - (a * (1.0 / b)));
+ return rmax - 2.0 * fabs(floor((a * (1.0 / b)) + 0.5) - (a * (1.0 / b)));
}
- return result;
+ return 0.0;
}
/* Turbulence */
diff --git a/intern/cycles/kernel/shaders/node_vector_math.osl b/intern/cycles/kernel/shaders/node_vector_math.osl
index f22a6e8441a..4c94fc659c2 100644
--- a/intern/cycles/kernel/shaders/node_vector_math.osl
+++ b/intern/cycles/kernel/shaders/node_vector_math.osl
@@ -29,23 +29,23 @@ shader node_vector_math(
Vector = Vector1 + Vector2;
Value = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2])) / 3.0;
}
- if (type == "Subtract") {
+ else if (type == "Subtract") {
Vector = Vector1 - Vector2;
Value = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2])) / 3.0;
}
- if (type == "Average") {
+ else if (type == "Average") {
Value = length(Vector1 + Vector2);
Vector = normalize(Vector1 + Vector2);
}
- if (type == "Dot Product") {
+ else if (type == "Dot Product") {
Value = dot(Vector1, Vector2);
}
- if (type == "Cross Product") {
+ else if (type == "Cross Product") {
vector c = cross(Vector1, Vector2);
Value = length(c);
Vector = normalize(c);
}
- if (type == "Normalize") {
+ else if (type == "Normalize") {
Value = length(Vector1);
Vector = normalize(Vector1);
}
diff --git a/intern/cycles/kernel/shaders/node_wave_texture.osl b/intern/cycles/kernel/shaders/node_wave_texture.osl
index 11c4689196d..12b837bc448 100644
--- a/intern/cycles/kernel/shaders/node_wave_texture.osl
+++ b/intern/cycles/kernel/shaders/node_wave_texture.osl
@@ -27,7 +27,6 @@ float wave(point p, float scale, string type, float detail, float distortion, fl
float y = p[1] * scale;
float z = p[2] * scale;
- float result = 0.0;
float n = 0.0;
if (type == "Bands") {
@@ -40,9 +39,7 @@ float wave(point p, float scale, string type, float detail, float distortion, fl
if (distortion != 0.0) {
n = n + (distortion * noise_turbulence(p * dscale, "Perlin", detail, 0));
}
- result = noise_wave("Sine", n);
-
- return result;
+ return noise_wave("Sine", n);
}
shader node_wave_texture(
@@ -63,6 +60,6 @@ shader node_wave_texture(
p = transform(mapping, p);
Fac = wave(p, Scale, Type, Detail, Distortion, DetailScale);
- Color = color(Fac, Fac, Fac);
+ Color = Fac;
}
diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h
index f4c0d0734bc..f340eaff95f 100644
--- a/intern/cycles/kernel/shaders/stdosl.h
+++ b/intern/cycles/kernel/shaders/stdosl.h
@@ -161,7 +161,15 @@ vector cross (vector a, vector b) BUILTIN;
float dot (vector a, vector b) BUILTIN;
float length (vector v) BUILTIN;
float distance (point a, point b) BUILTIN;
-float distance (point a, point b, point q) BUILTIN;
+float distance (point a, point b, point q)
+{
+ vector d = b - a;
+ float dd = dot(d, d);
+ if(dd == 0.0)
+ return distance(q, a);
+ float t = dot(q - a, d)/dd;
+ return distance(q, a + clamp(t, 0.0, 1.0)*d);
+}
normal normalize (normal v) BUILTIN;
vector normalize (vector v) BUILTIN;
vector faceforward (vector N, vector I, vector Nref) BUILTIN;
@@ -305,7 +313,7 @@ color transformc (string to, color x)
r = color (dot (vector(0.299, 0.587, 0.114), (vector)x),
dot (vector(0.596, -0.275, -0.321), (vector)x),
dot (vector(0.212, -0.523, 0.311), (vector)x));
- else if (to == "xyz")
+ else if (to == "XYZ")
r = color (dot (vector(0.412453, 0.357580, 0.180423), (vector)x),
dot (vector(0.212671, 0.715160, 0.072169), (vector)x),
dot (vector(0.019334, 0.119193, 0.950227), (vector)x));
@@ -367,7 +375,7 @@ color transformc (string from, string to, color x)
r = color (dot (vector(1, 0.9557, 0.6199), (vector)x),
dot (vector(1, -0.2716, -0.6469), (vector)x),
dot (vector(1, -1.1082, 1.7051), (vector)x));
- else if (from == "xyz")
+ else if (from == "XYZ")
r = color (dot (vector( 3.240479, -1.537150, -0.498535), (vector)x),
dot (vector(-0.969256, 1.875991, 0.041556), (vector)x),
dot (vector( 0.055648, -0.204043, 1.057311), (vector)x));
@@ -410,6 +418,8 @@ int startswith (string s, string prefix) BUILTIN;
int endswith (string s, string suffix) BUILTIN;
string substr (string s, int start, int len) BUILTIN;
string substr (string s, int start) { return substr (s, start, strlen(s)); }
+float strtof (string str) BUILTIN;
+int strtoi (string str) BUILTIN;
// Define concat in terms of shorter concat
string concat (string a, string b, string c) {
@@ -433,8 +443,10 @@ string concat (string a, string b, string c, string d, string e, string f) {
closure color diffuse(normal N) BUILTIN;
closure color oren_nayar(normal N, float sigma) BUILTIN;
-closure color phong_ramp(normal N, float exponent, color colors[8]) BUILTIN;
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 specular_toon(normal N, float size, float smooth) BUILTIN;
closure color translucent(normal N) BUILTIN;
closure color reflection(normal N) BUILTIN;
closure color refraction(normal N, float eta) BUILTIN;
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index ec7978066c2..1f4857c0924 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -301,6 +301,12 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
case NODE_PARTICLE_INFO:
svm_node_particle_info(kg, sd, stack, node.y, node.z);
break;
+#ifdef __HAIR__
+ case NODE_HAIR_INFO:
+ svm_node_hair_info(kg, sd, stack, node.y, node.z);
+ break;
+#endif
+
#endif
case NODE_CONVERT:
svm_node_convert(sd, stack, node.y, node.z, node.w);
diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h
index ed70a6dc423..2beec995151 100644
--- a/intern/cycles/kernel/svm/svm_attribute.h
+++ b/intern/cycles/kernel/svm/svm_attribute.h
@@ -28,10 +28,15 @@ __device void svm_node_attr_init(KernelGlobals *kg, ShaderData *sd,
/* find attribute by unique id */
uint id = node.y;
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
+#ifdef __HAIR__
+ attr_offset = (sd->segment == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
+#endif
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
-
- while(attr_map.x != id)
- 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);
+ }
/* return result */
*elem = (AttributeElement)attr_map.y;
@@ -61,21 +66,21 @@ __device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, uin
/* fetch and store attribute */
if(type == NODE_ATTR_FLOAT) {
if(mesh_type == NODE_ATTR_FLOAT) {
- float f = triangle_attribute_float(kg, sd, elem, offset, NULL, NULL);
+ float f = primitive_attribute_float(kg, sd, elem, offset, NULL, NULL);
stack_store_float(stack, out_offset, f);
}
else {
- float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, NULL);
+ float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
stack_store_float(stack, out_offset, average(f));
}
}
else {
if(mesh_type == NODE_ATTR_FLOAT3) {
- float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, NULL);
+ float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
stack_store_float3(stack, out_offset, f);
}
else {
- float f = triangle_attribute_float(kg, sd, elem, offset, NULL, NULL);
+ float f = primitive_attribute_float(kg, sd, elem, offset, NULL, NULL);
stack_store_float3(stack, out_offset, make_float3(f, f, f));
}
}
@@ -94,24 +99,24 @@ __device void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *st
if(type == NODE_ATTR_FLOAT) {
if(mesh_type == NODE_ATTR_FLOAT) {
float dx;
- float f = triangle_attribute_float(kg, sd, elem, offset, &dx, NULL);
+ float f = primitive_attribute_float(kg, sd, elem, offset, &dx, NULL);
stack_store_float(stack, out_offset, f+dx);
}
else {
float3 dx;
- float3 f = triangle_attribute_float3(kg, sd, elem, offset, &dx, NULL);
+ float3 f = primitive_attribute_float3(kg, sd, elem, offset, &dx, NULL);
stack_store_float(stack, out_offset, average(f+dx));
}
}
else {
if(mesh_type == NODE_ATTR_FLOAT3) {
float3 dx;
- float3 f = triangle_attribute_float3(kg, sd, elem, offset, &dx, NULL);
+ float3 f = primitive_attribute_float3(kg, sd, elem, offset, &dx, NULL);
stack_store_float3(stack, out_offset, f+dx);
}
else {
float dx;
- float f = triangle_attribute_float(kg, sd, elem, offset, &dx, NULL);
+ float f = primitive_attribute_float(kg, sd, elem, offset, &dx, NULL);
stack_store_float3(stack, out_offset, make_float3(f+dx, f+dx, f+dx));
}
}
@@ -130,24 +135,24 @@ __device void svm_node_attr_bump_dy(KernelGlobals *kg, ShaderData *sd, float *st
if(type == NODE_ATTR_FLOAT) {
if(mesh_type == NODE_ATTR_FLOAT) {
float dy;
- float f = triangle_attribute_float(kg, sd, elem, offset, NULL, &dy);
+ float f = primitive_attribute_float(kg, sd, elem, offset, NULL, &dy);
stack_store_float(stack, out_offset, f+dy);
}
else {
float3 dy;
- float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, &dy);
+ float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, &dy);
stack_store_float(stack, out_offset, average(f+dy));
}
}
else {
if(mesh_type == NODE_ATTR_FLOAT3) {
float3 dy;
- float3 f = triangle_attribute_float3(kg, sd, elem, offset, NULL, &dy);
+ float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, &dy);
stack_store_float3(stack, out_offset, f+dy);
}
else {
float dy;
- float f = triangle_attribute_float(kg, sd, elem, offset, NULL, &dy);
+ float f = primitive_attribute_float(kg, sd, elem, offset, NULL, &dy);
stack_store_float3(stack, out_offset, make_float3(f+dy, f+dy, f+dy));
}
}
diff --git a/intern/cycles/kernel/svm/svm_bsdf.h b/intern/cycles/kernel/svm/svm_bsdf.h
deleted file mode 100644
index a9524f3ed37..00000000000
--- a/intern/cycles/kernel/svm/svm_bsdf.h
+++ /dev/null
@@ -1,279 +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.
- */
-
-#include "../closure/bsdf_ashikhmin_velvet.h"
-#include "../closure/bsdf_diffuse.h"
-#include "../closure/bsdf_oren_nayar.h"
-#include "../closure/bsdf_phong_ramp.h"
-#include "../closure/bsdf_diffuse_ramp.h"
-#include "../closure/bsdf_microfacet.h"
-#include "../closure/bsdf_reflection.h"
-#include "../closure/bsdf_refraction.h"
-#include "../closure/bsdf_transparent.h"
-#ifdef __ANISOTROPIC__
-#include "../closure/bsdf_ward.h"
-#endif
-#include "../closure/bsdf_westin.h"
-
-CCL_NAMESPACE_BEGIN
-
-__device int svm_bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf)
-{
- int label;
-
- switch(sc->type) {
- case CLOSURE_BSDF_DIFFUSE_ID:
- label = bsdf_diffuse_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;
-#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,
- 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,
- 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,
- 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,
- 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,
- 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,
- 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,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_MICROFACET_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- label = bsdf_microfacet_ggx_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_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- label = bsdf_microfacet_beckmann_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;
-#ifdef __ANISOTROPIC__
- case CLOSURE_BSDF_WARD_ID:
- label = bsdf_ward_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
-#endif
- case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- label = bsdf_ashikhmin_velvet_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- 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,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
-#endif
- default:
- label = LABEL_NONE;
- break;
- }
-
- return label;
-}
-
-__device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, float *pdf)
-{
- float3 eval;
-
- if(dot(sd->Ng, omega_in) >= 0.0f) {
- switch(sc->type) {
- case CLOSURE_BSDF_DIFFUSE_ID:
- eval = bsdf_diffuse_eval_reflect(sc, 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);
- break;
- /*case CLOSURE_BSDF_PHONG_RAMP_ID:
- eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
- eval = bsdf_diffuse_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
- break;*/
- case CLOSURE_BSDF_TRANSLUCENT_ID:
- eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_REFLECTION_ID:
- eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_REFRACTION_ID:
- eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_TRANSPARENT_ID:
- eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_MICROFACET_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
-#ifdef __ANISOTROPIC__
- case CLOSURE_BSDF_WARD_ID:
- eval = bsdf_ward_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
-#endif
- case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- 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);
- break;
-#endif
- default:
- eval = make_float3(0.0f, 0.0f, 0.0f);
- break;
- }
- }
- else {
- switch(sc->type) {
- case CLOSURE_BSDF_DIFFUSE_ID:
- eval = bsdf_diffuse_eval_transmit(sc, 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);
- break;
- case CLOSURE_BSDF_TRANSLUCENT_ID:
- eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_REFLECTION_ID:
- eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_REFRACTION_ID:
- eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_TRANSPARENT_ID:
- eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_MICROFACET_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
-#ifdef __ANISOTROPIC__
- case CLOSURE_BSDF_WARD_ID:
- eval = bsdf_ward_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
-#endif
- case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- 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);
- break;
-#endif
- default:
- eval = make_float3(0.0f, 0.0f, 0.0f);
- break;
- }
- }
-
- return eval;
-}
-
-__device void svm_bsdf_blur(ShaderClosure *sc, float roughness)
-{
- switch(sc->type) {
- case CLOSURE_BSDF_DIFFUSE_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;
- case CLOSURE_BSDF_MICROFACET_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- bsdf_microfacet_ggx_blur(sc, roughness);
- break;
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- bsdf_microfacet_beckmann_blur(sc, roughness);
- break;
-#ifdef __ANISOTROPIC__
- case CLOSURE_BSDF_WARD_ID:
- bsdf_ward_blur(sc, roughness);
- break;
-#endif
- case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- bsdf_ashikhmin_velvet_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;
-#endif
- default:
- break;
- }
-}
-
-CCL_NAMESPACE_END
-
diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h
index c4d03c1f948..a04f4ea0fa7 100644
--- a/intern/cycles/kernel/svm/svm_geometry.h
+++ b/intern/cycles/kernel/svm/svm_geometry.h
@@ -28,23 +28,7 @@ __device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack,
case NODE_GEOM_P: data = sd->P; break;
case NODE_GEOM_N: data = sd->N; break;
#ifdef __DPDU__
- case NODE_GEOM_T: {
- /* try to create spherical tangent from generated coordinates */
- int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_GENERATED): ATTR_STD_NOT_FOUND;
-
- if(attr_offset != ATTR_STD_NOT_FOUND) {
- data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
- data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f);
- object_normal_transform(kg, sd, &data);
- data = cross(sd->N, normalize(cross(data, sd->N)));;
- }
- else {
- /* otherwise use surface derivatives */
- data = normalize(sd->dPdu);
- }
-
- break;
- }
+ 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;
@@ -160,5 +144,36 @@ __device void svm_node_particle_info(KernelGlobals *kg, ShaderData *sd, float *s
}
}
+#ifdef __HAIR__
+
+/* Hair Info */
+
+__device void svm_node_hair_info(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
+{
+ float data;
+ float3 data3;
+
+ switch(type) {
+ case NODE_INFO_CURVE_IS_STRAND: {
+ data = (sd->segment != ~0);
+ stack_store_float(stack, out_offset, data);
+ break;
+ }
+ case NODE_INFO_CURVE_INTERCEPT:
+ break; /* handled as attribute */
+ case NODE_INFO_CURVE_THICKNESS: {
+ data = curve_thickness(kg, sd);
+ stack_store_float(stack, out_offset, data);
+ break;
+ }
+ case NODE_INFO_CURVE_TANGENT_NORMAL: {
+ data3 = curve_tangent_normal(kg, sd);
+ stack_store_float3(stack, out_offset, data3);
+ break;
+ }
+ }
+}
+#endif
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_math.h b/intern/cycles/kernel/svm/svm_math.h
index db3b8d3f763..c7cd5200cd0 100644
--- a/intern/cycles/kernel/svm/svm_math.h
+++ b/intern/cycles/kernel/svm/svm_math.h
@@ -18,73 +18,6 @@
CCL_NAMESPACE_BEGIN
-__device float safe_asinf(float a)
-{
- if(a <= -1.0f)
- return -M_PI_2_F;
- else if(a >= 1.0f)
- return M_PI_2_F;
-
- return asinf(a);
-}
-
-__device float safe_acosf(float a)
-{
- if(a <= -1.0f)
- return M_PI_F;
- else if(a >= 1.0f)
- return 0.0f;
-
- return acosf(a);
-}
-
-__device float compatible_powf(float x, float y)
-{
- /* GPU pow doesn't accept negative x, do manual checks here */
- if(x < 0.0f) {
- if(fmod(-y, 2.0f) == 0.0f)
- return powf(-x, y);
- else
- return -powf(-x, y);
- }
- else if(x == 0.0f)
- return 0.0f;
-
- return powf(x, y);
-}
-
-__device float safe_powf(float a, float b)
-{
- if(b == 0.0f)
- return 1.0f;
- if(a == 0.0f)
- return 0.0f;
- if(a < 0.0f && b != (int)b)
- return 0.0f;
-
- return compatible_powf(a, b);
-}
-
-__device float safe_logf(float a, float b)
-{
- if(a < 0.0f || b < 0.0f)
- return 0.0f;
-
- return logf(a)/logf(b);
-}
-
-__device float safe_divide(float a, float b)
-{
- float result;
-
- if(b == 0.0f)
- result = 0.0f;
- else
- result = a/b;
-
- return result;
-}
-
__device float svm_math(NodeMath type, float Fac1, float Fac2)
{
float Fac;
diff --git a/intern/cycles/kernel/svm/svm_noise.h b/intern/cycles/kernel/svm/svm_noise.h
index 224a1d96543..5ead6486dd6 100644
--- a/intern/cycles/kernel/svm/svm_noise.h
+++ b/intern/cycles/kernel/svm/svm_noise.h
@@ -84,9 +84,8 @@ __device uint phash(int kx, int ky, int kz, int3 p)
__device float floorfrac(float x, int* i)
{
- float f = floorf(x);
- *i = (int)f;
- return x - f;
+ *i = quick_floor(x);
+ return x - *i;
}
__device float fade(float t)
@@ -133,7 +132,10 @@ __device_noinline float perlin(float x, float y, float z)
grad (hash (X+1, Y , Z+1), fx-1.0f, fy , fz-1.0f )),
nerp (u, grad (hash (X , Y+1, Z+1), fx , fy-1.0f, fz-1.0f ),
grad (hash (X+1, Y+1, Z+1), fx-1.0f, fy-1.0f, fz-1.0f ))));
- return scale3(result);
+ float r = scale3(result);
+
+ /* can happen for big coordinates, things even out to 0.0 then anyway */
+ return (isfinite(r))? r: 0.0f;
}
__device_noinline float perlin_periodic(float x, float y, float z, float3 pperiod)
@@ -162,7 +164,10 @@ __device_noinline float perlin_periodic(float x, float y, float z, float3 pperio
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 ))));
- return scale3(result);
+ float r = scale3(result);
+
+ /* can happen for big coordinates, things even out to 0.0 then anyway */
+ return (isfinite(r))? r: 0.0f;
}
/* perlin noise in range 0..1 */
diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h
index 9f2d3367420..d793169261d 100644
--- a/intern/cycles/kernel/svm/svm_tex_coord.h
+++ b/intern/cycles/kernel/svm/svm_tex_coord.h
@@ -248,23 +248,27 @@ __device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stac
}
/* first try to get tangent attribute */
- int attr_offset = find_attribute(kg, sd, node.z);
- int attr_sign_offset = find_attribute(kg, sd, node.w);
+ AttributeElement attr_elem, attr_sign_elem, attr_normal_elem;
+ int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
+ int attr_sign_offset = find_attribute(kg, sd, node.w, &attr_sign_elem);
+ int attr_normal_offset = find_attribute(kg, sd, ATTR_STD_VERTEX_NORMAL, &attr_normal_elem);
- if(attr_offset == ATTR_STD_NOT_FOUND || attr_sign_offset == ATTR_STD_NOT_FOUND) {
+ if(attr_offset == ATTR_STD_NOT_FOUND || attr_sign_offset == ATTR_STD_NOT_FOUND || attr_normal_offset == ATTR_STD_NOT_FOUND) {
stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
return;
}
- /* ensure orthogonal and normalized (interpolation breaks it) */
- float3 tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL);
- float sign = triangle_attribute_float(kg, sd, ATTR_ELEMENT_CORNER, attr_sign_offset, NULL, NULL);
+ /* get _unnormalized_ interpolated normal and tangent */
+ float3 tangent = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
+ float sign = primitive_attribute_float(kg, sd, attr_sign_elem, attr_sign_offset, NULL, NULL);
+ float3 normal = primitive_attribute_float3(kg, sd, attr_normal_elem, attr_normal_offset, NULL, NULL);
- object_normal_transform(kg, sd, &tangent);
- tangent = cross(sd->N, normalize(cross(tangent, sd->N)));;
+ /* apply normal map */
+ float3 B = sign * cross(normal, tangent);
+ N = normalize(color.x * tangent + color.y * B + color.z * normal);
- float3 B = sign * cross(sd->N, tangent);
- N = normalize(color.x * tangent + color.y * B + color.z * sd->N);
+ /* transform to world space */
+ object_normal_transform(kg, sd, &N);
}
else {
/* object, world space */
@@ -295,22 +299,24 @@ __device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack,
if(direction_type == NODE_TANGENT_UVMAP) {
/* UV map */
- int attr_offset = find_attribute(kg, sd, node.z);
+ AttributeElement attr_elem;
+ int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
if(attr_offset == ATTR_STD_NOT_FOUND)
tangent = make_float3(0.0f, 0.0f, 0.0f);
else
- tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL);
+ tangent = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
}
else {
/* radial */
- int attr_offset = find_attribute(kg, sd, node.z);
+ AttributeElement attr_elem;
+ int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
float3 generated;
if(attr_offset == ATTR_STD_NOT_FOUND)
generated = sd->P;
else
- generated = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
+ generated = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
if(axis == NODE_TANGENT_AXIS_X)
tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f));
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index 0830a700281..57177eec48f 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -97,7 +97,8 @@ typedef enum NodeType {
NODE_CLOSURE_SET_NORMAL,
NODE_CLOSURE_AMBIENT_OCCLUSION,
NODE_TANGENT,
- NODE_NORMAL_MAP
+ NODE_NORMAL_MAP,
+ NODE_HAIR_INFO
} NodeType;
typedef enum NodeAttributeType {
@@ -132,6 +133,13 @@ typedef enum NodeParticleInfo {
NODE_INFO_PAR_ANGULAR_VELOCITY
} NodeParticleInfo;
+typedef enum NodeHairInfo {
+ NODE_INFO_CURVE_IS_STRAND,
+ NODE_INFO_CURVE_INTERCEPT,
+ NODE_INFO_CURVE_THICKNESS,
+ NODE_INFO_CURVE_TANGENT_NORMAL
+} NodeHairInfo;
+
typedef enum NodeLightPath {
NODE_LP_camera = 0,
NODE_LP_shadow,
@@ -314,6 +322,7 @@ typedef enum ClosureType {
CLOSURE_BSDF_DIFFUSE_ID,
CLOSURE_BSDF_OREN_NAYAR_ID,
CLOSURE_BSDF_DIFFUSE_RAMP_ID,
+ CLOSURE_BSDF_DIFFUSE_TOON_ID,
CLOSURE_BSDF_GLOSSY_ID,
CLOSURE_BSDF_REFLECTION_ID,
@@ -323,6 +332,7 @@ typedef enum ClosureType {
CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
CLOSURE_BSDF_WESTIN_SHEEN_ID,
CLOSURE_BSDF_PHONG_RAMP_ID,
+ CLOSURE_BSDF_SPECULAR_TOON_ID,
CLOSURE_BSDF_TRANSMISSION_ID,
CLOSURE_BSDF_TRANSLUCENT_ID,
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index 7907061c19c..d67a686d1e8 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -31,6 +31,7 @@ set(SRC
object.cpp
osl.cpp
particles.cpp
+ curves.cpp
scene.cpp
session.cpp
shader.cpp
@@ -56,6 +57,7 @@ set(SRC_HEADERS
object.h
osl.h
particles.h
+ curves.h
scene.h
session.h
shader.h
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index 95941c14b6c..b6f6ba47fe8 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -26,7 +26,7 @@ CCL_NAMESPACE_BEGIN
/* Attribute */
-void Attribute::set(ustring name_, TypeDesc type_, Element element_)
+void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
{
name = name_;
type = type_;
@@ -39,12 +39,30 @@ void Attribute::set(ustring name_, TypeDesc type_, Element element_)
type == TypeDesc::TypeNormal);
}
-void Attribute::reserve(int numverts, int numtris)
+void Attribute::reserve(int numverts, int numtris, int numcurves, int numkeys)
{
- buffer.resize(buffer_size(numverts, numtris), 0);
+ buffer.resize(buffer_size(numverts, numtris, numcurves, numkeys), 0);
}
-size_t Attribute::data_sizeof()
+void Attribute::add(const float& f)
+{
+ char *data = (char*)&f;
+ size_t size = sizeof(f);
+
+ for(size_t i = 0; i < size; i++)
+ buffer.push_back(data[i]);
+}
+
+void Attribute::add(const float3& f)
+{
+ char *data = (char*)&f;
+ size_t size = sizeof(f);
+
+ for(size_t i = 0; i < size; i++)
+ buffer.push_back(data[i]);
+}
+
+size_t Attribute::data_sizeof() const
{
if(type == TypeDesc::TypeFloat)
return sizeof(float);
@@ -52,19 +70,27 @@ size_t Attribute::data_sizeof()
return sizeof(float3);
}
-size_t Attribute::element_size(int numverts, int numtris)
+size_t Attribute::element_size(int numverts, int numtris, int numcurves, int numkeys) const
{
- if(element == VERTEX)
+ if(element == ATTR_ELEMENT_VALUE)
+ return 1;
+ if(element == ATTR_ELEMENT_VERTEX)
return numverts;
- else if(element == FACE)
+ else if(element == ATTR_ELEMENT_FACE)
return numtris;
- else
+ else if(element == ATTR_ELEMENT_CORNER)
return numtris*3;
+ else if(element == ATTR_ELEMENT_CURVE)
+ return numcurves;
+ else if(element == ATTR_ELEMENT_CURVE_KEY)
+ return numkeys;
+
+ return 0;
}
-size_t Attribute::buffer_size(int numverts, int numtris)
+size_t Attribute::buffer_size(int numverts, int numtris, int numcurves, int numkeys) const
{
- return element_size(numverts, numtris)*data_sizeof();
+ return element_size(numverts, numtris, numcurves, numkeys)*data_sizeof();
}
bool Attribute::same_storage(TypeDesc a, TypeDesc b)
@@ -84,18 +110,51 @@ bool Attribute::same_storage(TypeDesc a, TypeDesc b)
return false;
}
+const char *Attribute::standard_name(AttributeStandard std)
+{
+ if(std == ATTR_STD_VERTEX_NORMAL)
+ return "N";
+ else if(std == ATTR_STD_FACE_NORMAL)
+ return "Ng";
+ else if(std == ATTR_STD_UV)
+ return "uv";
+ else if(std == ATTR_STD_GENERATED)
+ return "generated";
+ else if(std == ATTR_STD_UV_TANGENT)
+ return "tangent";
+ else if(std == ATTR_STD_UV_TANGENT_SIGN)
+ return "tangent_sign";
+ else if(std == ATTR_STD_POSITION_UNDEFORMED)
+ return "undeformed";
+ else if(std == ATTR_STD_POSITION_UNDISPLACED)
+ return "undisplaced";
+ else if(std == ATTR_STD_MOTION_PRE)
+ return "motion_pre";
+ else if(std == ATTR_STD_MOTION_POST)
+ return "motion_post";
+ else if(std == ATTR_STD_PARTICLE)
+ return "particle";
+ else if(std == ATTR_STD_CURVE_TANGENT)
+ return "curve_tangent";
+ else if(std == ATTR_STD_CURVE_INTERCEPT)
+ return "curve_intercept";
+
+ return "";
+}
+
/* Attribute Set */
AttributeSet::AttributeSet()
{
- mesh = NULL;
+ triangle_mesh = NULL;
+ curve_mesh = NULL;
}
AttributeSet::~AttributeSet()
{
}
-Attribute *AttributeSet::add(ustring name, TypeDesc type, Attribute::Element element)
+Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element)
{
Attribute *attr = find(name);
@@ -111,24 +170,22 @@ Attribute *AttributeSet::add(ustring name, TypeDesc type, Attribute::Element ele
attributes.push_back(Attribute());
attr = &attributes.back();
- if(element == Attribute::VERTEX)
- attr->set(name, type, element);
- else if(element == Attribute::FACE)
- attr->set(name, type, element);
- else if(element == Attribute::CORNER)
- attr->set(name, type, element);
+ attr->set(name, type, element);
- if(mesh)
- attr->reserve(mesh->verts.size(), mesh->triangles.size());
+ /* this is weak .. */
+ if(triangle_mesh)
+ attr->reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0);
+ if(curve_mesh)
+ attr->reserve(0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size());
return attr;
}
-Attribute *AttributeSet::find(ustring name)
+Attribute *AttributeSet::find(ustring name) const
{
- foreach(Attribute& attr, attributes)
+ foreach(const Attribute& attr, attributes)
if(attr.name == name)
- return &attr;
+ return (Attribute*)&attr;
return NULL;
}
@@ -154,41 +211,59 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
Attribute *attr = NULL;
if(name == ustring())
- name = attribute_standard_name(std);
-
- if(std == ATTR_STD_VERTEX_NORMAL)
- attr = add(name, TypeDesc::TypeNormal, Attribute::VERTEX);
- else if(std == ATTR_STD_FACE_NORMAL)
- attr = add(name, TypeDesc::TypeNormal, Attribute::FACE);
- else if(std == ATTR_STD_UV)
- attr = add(name, TypeDesc::TypePoint, Attribute::CORNER);
- else if(std == ATTR_STD_UV_TANGENT)
- attr = add(name, TypeDesc::TypeVector, Attribute::CORNER);
- else if(std == ATTR_STD_UV_TANGENT_SIGN)
- attr = add(name, TypeDesc::TypeFloat, Attribute::CORNER);
- else if(std == ATTR_STD_GENERATED)
- attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
- else if(std == ATTR_STD_POSITION_UNDEFORMED)
- attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
- else if(std == ATTR_STD_POSITION_UNDISPLACED)
- attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
- else if(std == ATTR_STD_MOTION_PRE)
- attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
- else if(std == ATTR_STD_MOTION_POST)
- attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
- else
- assert(0);
+ name = Attribute::standard_name(std);
+
+ if(triangle_mesh) {
+ if(std == ATTR_STD_VERTEX_NORMAL)
+ attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
+ else if(std == ATTR_STD_FACE_NORMAL)
+ attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
+ else if(std == ATTR_STD_UV)
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
+ else if(std == ATTR_STD_UV_TANGENT)
+ attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
+ else if(std == ATTR_STD_UV_TANGENT_SIGN)
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
+ else if(std == ATTR_STD_GENERATED)
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+ else if(std == ATTR_STD_POSITION_UNDEFORMED)
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+ else if(std == ATTR_STD_POSITION_UNDISPLACED)
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+ else if(std == ATTR_STD_MOTION_PRE)
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+ else if(std == ATTR_STD_MOTION_POST)
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+ else
+ assert(0);
+ }
+ else if(curve_mesh) {
+ if(std == ATTR_STD_UV)
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
+ else if(std == ATTR_STD_GENERATED)
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
+ else if(std == ATTR_STD_MOTION_PRE)
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY);
+ else if(std == ATTR_STD_MOTION_POST)
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY);
+ else if(std == ATTR_STD_CURVE_TANGENT)
+ attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CURVE_KEY);
+ else if(std == ATTR_STD_CURVE_INTERCEPT)
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
+ else
+ assert(0);
+ }
attr->std = std;
return attr;
}
-Attribute *AttributeSet::find(AttributeStandard std)
+Attribute *AttributeSet::find(AttributeStandard std) const
{
- foreach(Attribute& attr, attributes)
+ foreach(const Attribute& attr, attributes)
if(attr.std == std)
- return &attr;
+ return (Attribute*)&attr;
return NULL;
}
@@ -217,10 +292,14 @@ Attribute *AttributeSet::find(AttributeRequest& req)
return find(req.std);
}
-void AttributeSet::reserve(int numverts, int numtris)
+void AttributeSet::reserve()
{
- foreach(Attribute& attr, attributes)
- attr.reserve(numverts, numtris);
+ foreach(Attribute& attr, attributes) {
+ if(triangle_mesh)
+ attr.reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0);
+ if(curve_mesh)
+ attr.reserve(0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size());
+ }
}
void AttributeSet::clear()
@@ -235,9 +314,13 @@ AttributeRequest::AttributeRequest(ustring name_)
name = name_;
std = ATTR_STD_NONE;
- type = TypeDesc::TypeFloat;
- element = ATTR_ELEMENT_NONE;
- offset = 0;
+ triangle_type = TypeDesc::TypeFloat;
+ triangle_element = ATTR_ELEMENT_NONE;
+ triangle_offset = 0;
+
+ curve_type = TypeDesc::TypeFloat;
+ curve_element = ATTR_ELEMENT_NONE;
+ curve_offset = 0;
}
AttributeRequest::AttributeRequest(AttributeStandard std_)
@@ -245,9 +328,13 @@ AttributeRequest::AttributeRequest(AttributeStandard std_)
name = ustring();
std = std_;
- type = TypeDesc::TypeFloat;
- element = ATTR_ELEMENT_NONE;
- offset = 0;
+ triangle_type = TypeDesc::TypeFloat;
+ triangle_element = ATTR_ELEMENT_NONE;
+ triangle_offset = 0;
+
+ curve_type = TypeDesc::TypeFloat;
+ curve_element = ATTR_ELEMENT_NONE;
+ curve_offset = 0;
}
/* AttributeRequestSet */
diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h
index d05952edfd7..6c0c06d0425 100644
--- a/intern/cycles/render/attribute.h
+++ b/intern/cycles/render/attribute.h
@@ -21,7 +21,6 @@
#include "kernel_types.h"
-#include "util_attribute.h"
#include "util_list.h"
#include "util_param.h"
#include "util_types.h"
@@ -42,36 +41,34 @@ class Mesh;
class Attribute {
public:
- enum Element {
- VERTEX,
- FACE,
- CORNER
- };
-
ustring name;
AttributeStandard std;
TypeDesc type;
vector<char> buffer;
- Element element;
+ AttributeElement element;
Attribute() {}
- void set(ustring name, TypeDesc type, Element element);
- void reserve(int numverts, int numfaces);
+ void set(ustring name, TypeDesc type, AttributeElement element);
+ void reserve(int numverts, int numfaces, int numcurves, int numkeys);
- size_t data_sizeof();
- size_t element_size(int numverts, int numfaces);
- size_t buffer_size(int numverts, int numfaces);
+ size_t data_sizeof() const;
+ size_t element_size(int numverts, int numfaces, int numcurves, int numkeys) const;
+ size_t buffer_size(int numverts, int numfaces, int numcurves, int numkeys) const;
char *data() { return (buffer.size())? &buffer[0]: NULL; };
float3 *data_float3() { return (float3*)data(); }
float *data_float() { return (float*)data(); }
const char *data() const { return (buffer.size())? &buffer[0]: NULL; }
- const float3 *data_float3() const { return (float3*)data(); }
- const float *data_float() const { return (float*)data(); }
+ const float3 *data_float3() const { return (const float3*)data(); }
+ const float *data_float() const { return (const float*)data(); }
+
+ void add(const float& f);
+ void add(const float3& f);
static bool same_storage(TypeDesc a, TypeDesc b);
+ static const char *standard_name(AttributeStandard std);
};
/* Attribute Set
@@ -80,23 +77,24 @@ public:
class AttributeSet {
public:
- Mesh *mesh;
+ Mesh *triangle_mesh;
+ Mesh *curve_mesh;
list<Attribute> attributes;
AttributeSet();
~AttributeSet();
- Attribute *add(ustring name, TypeDesc type, Attribute::Element element);
- Attribute *find(ustring name);
+ Attribute *add(ustring name, TypeDesc type, AttributeElement element);
+ Attribute *find(ustring name) const;
void remove(ustring name);
Attribute *add(AttributeStandard std, ustring name = ustring());
- Attribute *find(AttributeStandard std);
+ Attribute *find(AttributeStandard std) const;
void remove(AttributeStandard std);
Attribute *find(AttributeRequest& req);
- void reserve(int numverts, int numfaces);
+ void reserve();
void clear();
};
@@ -104,7 +102,7 @@ public:
*
* Request from a shader to use a certain attribute, so we can figure out
* which ones we need to export from the host app end store for the kernel.
- * The attribute is found either by name or by standard. */
+ * The attribute is found either by name or by standard attribute type. */
class AttributeRequest {
public:
@@ -112,9 +110,9 @@ public:
AttributeStandard std;
/* temporary variables used by MeshManager */
- TypeDesc type;
- AttributeElement element;
- int offset;
+ TypeDesc triangle_type, curve_type;
+ AttributeElement triangle_element, curve_element;
+ int triangle_offset, curve_offset;
AttributeRequest(ustring name_);
AttributeRequest(AttributeStandard std);
diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp
index 3b61ccd176d..572cfae45cd 100644
--- a/intern/cycles/render/buffers.cpp
+++ b/intern/cycles/render/buffers.cpp
@@ -83,6 +83,7 @@ RenderTile::RenderTile()
w = 0;
h = 0;
+ sample = 0;
start_sample = 0;
num_samples = 0;
resolution = 0;
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index a78ede979b2..3ca19496b72 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -216,9 +216,9 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
/* motion blur */
#ifdef __CAMERA_MOTION__
- kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime: 0.0f;
+ kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime: -1.0f;
#else
- kcam->shuttertime = 0.0f;
+ kcam->shuttertime = -1.0f;
#endif
/* type */
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index 9696161180d..197a4da588c 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -90,7 +90,7 @@ public:
Transform worldtocamera;
Transform rastertocamera;
- Transform cameratoraster;;
+ Transform cameratoraster;
float3 dx;
float3 dy;
diff --git a/intern/cycles/render/curves.cpp b/intern/cycles/render/curves.cpp
new file mode 100644
index 00000000000..9fa867ae723
--- /dev/null
+++ b/intern/cycles/render/curves.cpp
@@ -0,0 +1,210 @@
+/*
+ * 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.
+ */
+
+#include "device.h"
+#include "curves.h"
+#include "mesh.h"
+#include "object.h"
+#include "scene.h"
+
+#include "util_foreach.h"
+#include "util_map.h"
+#include "util_progress.h"
+#include "util_vector.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Curve functions */
+
+void curvebounds(float *lower, float *upper, float3 *p, int dim)
+{
+ float *p0 = &p[0].x;
+ float *p1 = &p[1].x;
+ float *p2 = &p[2].x;
+ float *p3 = &p[3].x;
+ float fc = 0.71f;
+ float curve_coef[4];
+ curve_coef[0] = p1[dim];
+ curve_coef[1] = -fc*p0[dim] + fc*p2[dim];
+ curve_coef[2] = 2.0f * fc * p0[dim] + (fc - 3.0f) * p1[dim] + (3.0f - 2.0f * fc) * p2[dim] - fc * p3[dim];
+ curve_coef[3] = -fc * p0[dim] + (2.0f - fc) * p1[dim] + (fc - 2.0f) * p2[dim] + fc * p3[dim];
+ float discroot = curve_coef[2] * curve_coef[2] - 3 * curve_coef[3] * curve_coef[1];
+ float ta = -1.0f;
+ float tb = -1.0f;
+ if(discroot >= 0) {
+ discroot = sqrt(discroot);
+ ta = (-curve_coef[2] - discroot) / (3 * curve_coef[3]);
+ tb = (-curve_coef[2] + discroot) / (3 * curve_coef[3]);
+ ta = (ta > 1.0f || ta < 0.0f) ? -1.0f : ta;
+ tb = (tb > 1.0f || tb < 0.0f) ? -1.0f : tb;
+ }
+
+ *upper = max(p1[dim],p2[dim]);
+ *lower = min(p1[dim],p2[dim]);
+ float exa = p1[dim];
+ float exb = p2[dim];
+ float t2;
+ float t3;
+ if(ta >= 0.0f) {
+ t2 = ta * ta;
+ t3 = t2 * ta;
+ exa = curve_coef[3] * t3 + curve_coef[2] * t2 + curve_coef[1] * ta + curve_coef[0];
+ }
+ if(tb >= 0.0f) {
+ t2 = tb * tb;
+ t3 = t2 * tb;
+ exb = curve_coef[3] * t3 + curve_coef[2] * t2 + curve_coef[1] * tb + curve_coef[0];
+ }
+ *upper = max(*upper, max(exa,exb));
+ *lower = min(*lower, min(exa,exb));
+
+}
+
+/* Hair System Manager */
+
+CurveSystemManager::CurveSystemManager()
+{
+ primitive = CURVE_LINE_SEGMENTS;
+ line_method = CURVE_CORRECTED;
+ interpolation = CURVE_CARDINAL;
+ triangle_method = CURVE_CAMERA_TRIANGLES;
+ resolution = 3;
+ segments = 1;
+ subdivisions = 3;
+
+ normalmix = 1.0f;
+ encasing_ratio = 1.01f;
+
+ use_curves = true;
+ use_smooth = true;
+ use_parents = false;
+ use_encasing = true;
+ use_backfacing = false;
+ use_joined = false;
+ use_tangent_normal = false;
+ use_tangent_normal_geometry = false;
+ use_tangent_normal_correction = false;
+
+ need_update = true;
+ need_mesh_update = false;
+}
+
+CurveSystemManager::~CurveSystemManager()
+{
+}
+
+void CurveSystemManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+{
+ if(!need_update)
+ return;
+
+ device_free(device, dscene);
+
+ progress.set_status("Updating Hair settings", "Copying Hair settings to device");
+
+ KernelCurves *kcurve= &dscene->data.curve_kernel_data;
+
+ kcurve->curveflags = 0;
+
+ if(use_curves) {
+ if(primitive == CURVE_SEGMENTS || primitive == CURVE_RIBBONS)
+ kcurve->curveflags |= CURVE_KN_INTERPOLATE;
+ if(primitive == CURVE_RIBBONS)
+ kcurve->curveflags |= CURVE_KN_RIBBONS;
+
+ if(line_method == CURVE_ACCURATE)
+ kcurve->curveflags |= CURVE_KN_ACCURATE;
+ if(line_method == CURVE_CORRECTED)
+ kcurve->curveflags |= CURVE_KN_INTERSECTCORRECTION;
+ if(line_method == CURVE_POSTCORRECTED)
+ kcurve->curveflags |= CURVE_KN_POSTINTERSECTCORRECTION;
+
+ if(use_tangent_normal)
+ kcurve->curveflags |= CURVE_KN_TANGENTGNORMAL;
+ if(use_tangent_normal_correction)
+ kcurve->curveflags |= CURVE_KN_NORMALCORRECTION;
+ if(use_tangent_normal_geometry)
+ kcurve->curveflags |= CURVE_KN_TRUETANGENTGNORMAL;
+ if(use_joined)
+ kcurve->curveflags |= CURVE_KN_CURVEDATA;
+ if(use_backfacing)
+ kcurve->curveflags |= CURVE_KN_BACKFACING;
+ if(use_encasing)
+ kcurve->curveflags |= CURVE_KN_ENCLOSEFILTER;
+
+ kcurve->normalmix = normalmix;
+ kcurve->encasing_ratio = encasing_ratio;
+ kcurve->subdivisions = subdivisions;
+ }
+
+ if(progress.get_cancel()) return;
+
+ need_update = false;
+}
+
+void CurveSystemManager::device_free(Device *device, DeviceScene *dscene)
+{
+
+}
+
+bool CurveSystemManager::modified(const CurveSystemManager& CurveSystemManager)
+{
+ return !(line_method == CurveSystemManager.line_method &&
+ interpolation == CurveSystemManager.interpolation &&
+ primitive == CurveSystemManager.primitive &&
+ use_encasing == CurveSystemManager.use_encasing &&
+ use_tangent_normal == CurveSystemManager.use_tangent_normal &&
+ use_tangent_normal_correction == CurveSystemManager.use_tangent_normal_correction &&
+ use_tangent_normal_geometry == CurveSystemManager.use_tangent_normal_geometry &&
+ encasing_ratio == CurveSystemManager.encasing_ratio &&
+ use_backfacing == CurveSystemManager.use_backfacing &&
+ normalmix == CurveSystemManager.normalmix &&
+ use_smooth == CurveSystemManager.use_smooth &&
+ triangle_method == CurveSystemManager.triangle_method &&
+ resolution == CurveSystemManager.resolution &&
+ use_curves == CurveSystemManager.use_curves &&
+ use_joined == CurveSystemManager.use_joined &&
+ segments == CurveSystemManager.segments &&
+ use_parents == CurveSystemManager.use_parents &&
+ subdivisions == CurveSystemManager.subdivisions);
+}
+
+bool CurveSystemManager::modified_mesh(const CurveSystemManager& CurveSystemManager)
+{
+ return !(primitive == CurveSystemManager.primitive &&
+ interpolation == CurveSystemManager.interpolation &&
+ use_parents == CurveSystemManager.use_parents &&
+ use_smooth == CurveSystemManager.use_smooth &&
+ triangle_method == CurveSystemManager.triangle_method &&
+ resolution == CurveSystemManager.resolution &&
+ use_curves == CurveSystemManager.use_curves &&
+ use_joined == CurveSystemManager.use_joined &&
+ segments == CurveSystemManager.segments);
+}
+
+void CurveSystemManager::tag_update(Scene *scene)
+{
+ need_update = true;
+}
+
+void CurveSystemManager::tag_update_mesh()
+{
+ need_mesh_update = true;
+}
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h
new file mode 100644
index 00000000000..3527998339c
--- /dev/null
+++ b/intern/cycles/render/curves.h
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+#ifndef __CURVES_H__
+#define __CURVES_H__
+
+#include "util_types.h"
+#include "util_vector.h"
+
+CCL_NAMESPACE_BEGIN
+
+class Device;
+class DeviceScene;
+class Progress;
+class Scene;
+
+void curvebounds(float *lower, float *upper, float3 *p, int dim);
+
+typedef enum curve_presets {
+ CURVE_CUSTOM,
+ CURVE_FAST_PLANES,
+ CURVE_TANGENT_SHADING,
+ CURVE_TRUE_NORMAL,
+ CURVE_ACCURATE_PRESET,
+ CURVE_SMOOTH_CURVES
+} curve_presets;
+
+typedef enum curve_primitives {
+ CURVE_TRIANGLES,
+ CURVE_LINE_SEGMENTS,
+ CURVE_SEGMENTS,
+ CURVE_RIBBONS
+} curve_primitives;
+
+typedef enum curve_triangles {
+ CURVE_CAMERA_TRIANGLES,
+ CURVE_RIBBON_TRIANGLES,
+ CURVE_TESSELATED_TRIANGLES
+} curve_triangles;
+
+typedef enum curve_lines {
+ CURVE_ACCURATE,
+ CURVE_CORRECTED,
+ CURVE_POSTCORRECTED,
+ CURVE_UNCORRECTED
+} curve_lines;
+
+typedef enum curve_interpolation {
+ CURVE_LINEAR,
+ CURVE_CARDINAL,
+ CURVE_BSPLINE
+} curve_interpolation;
+
+class ParticleCurveData {
+
+public:
+
+ ParticleCurveData();
+ ~ParticleCurveData();
+
+ vector<int> psys_firstcurve;
+ vector<int> psys_curvenum;
+ vector<int> psys_shader;
+
+ vector<float> psys_rootradius;
+ vector<float> psys_tipradius;
+ vector<float> psys_shape;
+ vector<bool> psys_closetip;
+
+ vector<int> curve_firstkey;
+ vector<int> curve_keynum;
+ vector<float> curve_length;
+ vector<float3> curve_uv;
+ vector<float3> curve_vcol;
+
+ vector<float3> curvekey_co;
+ vector<float> curvekey_time;
+};
+
+/* HairSystem Manager */
+
+class CurveSystemManager {
+public:
+
+ int primitive;
+ int line_method;
+ int interpolation;
+ int triangle_method;
+ int resolution;
+ int segments;
+ int subdivisions;
+
+ float normalmix;
+ float encasing_ratio;
+
+ bool use_curves;
+ bool use_smooth;
+ bool use_parents;
+ bool use_encasing;
+ bool use_backfacing;
+ bool use_tangent_normal;
+ bool use_tangent_normal_correction;
+ bool use_tangent_normal_geometry;
+ bool use_joined;
+
+ bool need_update;
+ bool need_mesh_update;
+
+ CurveSystemManager();
+ ~CurveSystemManager();
+
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
+ void device_free(Device *device, DeviceScene *dscene);
+ bool modified(const CurveSystemManager& CurveSystemManager);
+ bool modified_mesh(const CurveSystemManager& CurveSystemManager);
+
+ void tag_update(Scene *scene);
+ void tag_update_mesh();
+};
+
+CCL_NAMESPACE_END
+
+#endif /* __CURVES_H__ */
+
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index 14b219383d0..af27b46771c 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -708,7 +708,8 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
value2_in->value.x = 1.0f;
weight_out = math_node->output("Value");
- disconnect(weight_in);
+ if(weight_in->link)
+ disconnect(weight_in);
}
/* connected to closure mix weight */
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index b79167839ab..c6b9ae08508 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -43,6 +43,8 @@ class OSLCompiler;
* Data type for inputs and outputs */
enum ShaderSocketType {
+ SHADER_SOCKET_UNDEFINED,
+
SHADER_SOCKET_FLOAT,
SHADER_SOCKET_INT,
SHADER_SOCKET_COLOR,
@@ -183,6 +185,9 @@ public:
virtual void compile(SVMCompiler& compiler) = 0;
virtual void compile(OSLCompiler& compiler) = 0;
+ virtual bool has_surface_emission() { return false; }
+ virtual bool has_surface_transparent() { return false; }
+
vector<ShaderInput*> inputs;
vector<ShaderOutput*> outputs;
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 230a12f9ff2..8e844bc788e 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -85,10 +85,24 @@ bool ImageManager::set_animation_frame_update(int frame)
return false;
}
-bool ImageManager::is_float_image(const string& filename)
+bool ImageManager::is_float_image(const string& filename, void *builtin_data, bool& is_linear)
{
- ImageInput *in = ImageInput::create(filename);
bool is_float = false;
+ is_linear = false;
+
+ if(builtin_data) {
+ if(builtin_image_info_cb) {
+ int width, height, channels;
+ builtin_image_info_cb(filename, builtin_data, is_float, width, height, channels);
+ }
+
+ if(is_float)
+ is_linear = true;
+
+ return is_float;
+ }
+
+ ImageInput *in = ImageInput::create(filename);
if(in) {
ImageSpec spec;
@@ -96,14 +110,30 @@ bool ImageManager::is_float_image(const string& filename)
if(in->open(filename, spec)) {
/* check the main format, and channel formats;
* if any take up more than one byte, we'll need a float texture slot */
- if(spec.format.basesize() > 1)
+ if(spec.format.basesize() > 1) {
is_float = true;
+ is_linear = true;
+ }
for(size_t channel = 0; channel < spec.channelformats.size(); channel++) {
- if(spec.channelformats[channel].basesize() > 1)
+ if(spec.channelformats[channel].basesize() > 1) {
is_float = true;
+ is_linear = true;
+ }
}
+ /* basic color space detection, not great but better than nothing
+ * before we do OpenColorIO integration */
+ if(is_float) {
+ string colorspace = spec.get_string_attribute("oiio:ColorSpace");
+
+ is_linear = !(colorspace == "sRGB" ||
+ colorspace == "GammaCorrected" ||
+ strcmp(in->format_name(), "png") == 0);
+ }
+ else
+ is_linear = false;
+
in->close();
}
@@ -113,13 +143,13 @@ bool ImageManager::is_float_image(const string& filename)
return is_float;
}
-int ImageManager::add_image(const string& filename, bool animated, bool& is_float)
+int ImageManager::add_image(const string& filename, void *builtin_data, bool animated, bool& is_float, bool& is_linear)
{
Image *img;
size_t slot;
/* load image info and find out if we need a float texture */
- is_float = (pack_images)? false: is_float_image(filename);
+ is_float = (pack_images)? false: is_float_image(filename, builtin_data, is_linear);
if(is_float) {
/* find existing image */
@@ -150,6 +180,7 @@ int ImageManager::add_image(const string& filename, bool animated, bool& is_floa
/* add new image */
img = new Image();
img->filename = filename;
+ img->builtin_data = builtin_data;
img->need_load = true;
img->animated = animated;
img->users = 1;
@@ -184,6 +215,7 @@ int ImageManager::add_image(const string& filename, bool animated, bool& is_floa
/* add new image */
img = new Image();
img->filename = filename;
+ img->builtin_data = builtin_data;
img->need_load = true;
img->animated = animated;
img->users = 1;
@@ -197,12 +229,12 @@ int ImageManager::add_image(const string& filename, bool animated, bool& is_floa
return slot;
}
-void ImageManager::remove_image(const string& filename)
+void ImageManager::remove_image(const string& filename, void *builtin_data)
{
size_t slot;
for(slot = 0; slot < images.size(); slot++) {
- if(images[slot] && images[slot]->filename == filename) {
+ if(images[slot] && images[slot]->filename == filename && images[slot]->builtin_data == builtin_data) {
/* decrement user count */
images[slot]->users--;
assert(images[slot]->users >= 0);
@@ -220,7 +252,7 @@ void ImageManager::remove_image(const string& filename)
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] && float_images[slot]->filename == filename) {
+ if(float_images[slot] && float_images[slot]->filename == filename && float_images[slot]->builtin_data == builtin_data) {
/* decrement user count */
float_images[slot]->users--;
assert(float_images[slot]->users >= 0);
@@ -242,27 +274,43 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
if(img->filename == "")
return false;
- /* load image from file through OIIO */
- ImageInput *in = ImageInput::create(img->filename);
+ ImageInput *in = NULL;
+ int width, height, components;
- if(!in)
- return false;
+ if(!img->builtin_data) {
+ /* load image from file through OIIO */
+ in = ImageInput::create(img->filename);
- ImageSpec spec;
+ if(!in)
+ return false;
- if(!in->open(img->filename, spec)) {
- delete in;
- return false;
+ ImageSpec spec;
+
+ if(!in->open(img->filename, spec)) {
+ delete in;
+ return false;
+ }
+
+ width = spec.width;
+ height = spec.height;
+ components = spec.nchannels;
+ }
+ else {
+ /* load image using builtin images callbacks */
+ if(!builtin_image_info_cb || !builtin_image_pixels_cb)
+ return false;
+
+ bool is_float;
+ builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, components);
}
/* we only handle certain number of components */
- int width = spec.width;
- int height = spec.height;
- int components = spec.nchannels;
-
if(!(components == 1 || components == 3 || components == 4)) {
- in->close();
- delete in;
+ if(in) {
+ in->close();
+ delete in;
+ }
+
return false;
}
@@ -270,14 +318,19 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
uchar *pixels = (uchar*)tex_img.resize(width, height);
int scanlinesize = width*components*sizeof(uchar);
- in->read_image(TypeDesc::UINT8,
- (uchar*)pixels + (height-1)*scanlinesize,
- AutoStride,
- -scanlinesize,
- AutoStride);
+ if(in) {
+ in->read_image(TypeDesc::UINT8,
+ (uchar*)pixels + (height-1)*scanlinesize,
+ AutoStride,
+ -scanlinesize,
+ AutoStride);
- in->close();
- delete in;
+ in->close();
+ delete in;
+ }
+ else {
+ builtin_image_pixels_cb(img->filename, img->builtin_data, pixels);
+ }
if(components == 3) {
for(int i = width*height-1; i >= 0; i--) {
@@ -304,27 +357,42 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
if(img->filename == "")
return false;
- /* load image from file through OIIO */
- ImageInput *in = ImageInput::create(img->filename);
+ ImageInput *in = NULL;
+ int width, height, components;
- if(!in)
- return false;
+ if(!img->builtin_data) {
+ /* load image from file through OIIO */
+ in = ImageInput::create(img->filename);
- ImageSpec spec;
+ if(!in)
+ return false;
- if(!in->open(img->filename, spec)) {
- delete in;
- return false;
+ ImageSpec spec;
+
+ if(!in->open(img->filename, spec)) {
+ delete in;
+ return false;
+ }
+
+ /* we only handle certain number of components */
+ width = spec.width;
+ height = spec.height;
+ components = spec.nchannels;
}
+ else {
+ /* load image using builtin images callbacks */
+ if(!builtin_image_info_cb || !builtin_image_float_pixels_cb)
+ return false;
- /* we only handle certain number of components */
- int width = spec.width;
- int height = spec.height;
- int components = spec.nchannels;
+ bool is_float;
+ builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, components);
+ }
if(!(components == 1 || components == 3 || components == 4)) {
- in->close();
- delete in;
+ if(in) {
+ in->close();
+ delete in;
+ }
return false;
}
@@ -332,14 +400,19 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
float *pixels = (float*)tex_img.resize(width, height);
int scanlinesize = width*components*sizeof(float);
- in->read_image(TypeDesc::FLOAT,
- (uchar*)pixels + (height-1)*scanlinesize,
- AutoStride,
- -scanlinesize,
- AutoStride);
+ if(in) {
+ in->read_image(TypeDesc::FLOAT,
+ (uchar*)pixels + (height-1)*scanlinesize,
+ AutoStride,
+ -scanlinesize,
+ AutoStride);
- in->close();
- delete in;
+ in->close();
+ delete in;
+ }
+ else {
+ builtin_image_float_pixels_cb(img->filename, img->builtin_data, pixels);
+ }
if(components == 3) {
for(int i = width*height-1; i >= 0; i--) {
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index 4d177174971..b20ff23fbbb 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -51,9 +51,9 @@ public:
ImageManager();
~ImageManager();
- int add_image(const string& filename, bool animated, bool& is_float);
- void remove_image(const string& filename);
- bool is_float_image(const string& filename);
+ int add_image(const string& filename, void *builtin_data, bool animated, bool& is_float, bool& is_linear);
+ void remove_image(const string& filename, void *builtin_data);
+ bool is_float_image(const string& filename, void *builtin_data, bool& is_linear);
void device_update(Device *device, DeviceScene *dscene, Progress& progress);
void device_free(Device *device, DeviceScene *dscene);
@@ -65,6 +65,9 @@ public:
bool need_update;
+ boost::function<void(const string &filename, void *data, bool &is_float, int &width, int &height, 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;
private:
int tex_num_images;
int tex_num_float_images;
@@ -74,6 +77,7 @@ private:
struct Image {
string filename;
+ void *builtin_data;
bool need_load;
bool animated;
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 4173da453fd..4c3c0c7f6a4 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -115,6 +115,8 @@ Light::Light()
spot_smooth = 0.0f;
cast_shadow = true;
+ use_mis = false;
+
shader = 0;
samples = 1;
}
@@ -141,7 +143,9 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
/* count */
size_t num_lights = scene->lights.size();
+ size_t num_background_lights = 0;
size_t num_triangles = 0;
+ size_t num_curve_segments = 0;
foreach(Object *object, scene->objects) {
Mesh *mesh = object->mesh;
@@ -169,10 +173,19 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
if(shader->sample_as_light && shader->has_surface_emission)
num_triangles++;
}
+
+ /* disabled for curves */
+#if 0
+ foreach(Mesh::Curve& curve, mesh->curves) {
+ Shader *shader = scene->shaders[curve.shader];
+
+ if(shader->sample_as_light && shader->has_surface_emission)
+ num_curve_segments += curve.num_segments();
+#endif
}
}
- size_t num_distribution = num_triangles;
+ size_t num_distribution = num_triangles + num_curve_segments;
num_distribution += num_lights;
/* emission area */
@@ -188,8 +201,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
bool have_emission = false;
/* skip if we are not visible for BSDFs */
- if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT)))
+ if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) {
+ j++;
continue;
+ }
/* skip if we have no emission shaders */
foreach(uint sindex, mesh->used_shaders) {
@@ -216,7 +231,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
if(shader->sample_as_light && shader->has_surface_emission) {
distribution[offset].x = totarea;
distribution[offset].y = __int_as_float(i + mesh->tri_offset);
- distribution[offset].z = 1.0f;
+ distribution[offset].z = __int_as_float(~0);
distribution[offset].w = __int_as_float(object_id);
offset++;
@@ -234,6 +249,40 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
totarea += triangle_area(p1, p2, p3);
}
}
+
+ /*sample as light disabled for strands*/
+#if 0
+ size_t i = 0;
+
+ foreach(Mesh::Curve& curve, mesh->curves) {
+ Shader *shader = scene->shaders[curve.shader];
+ int first_key = curve.first_key;
+
+ if(shader->sample_as_light && shader->has_surface_emission) {
+ for(int j = 0; j < curve.num_segments(); j++) {
+ distribution[offset].x = totarea;
+ distribution[offset].y = __int_as_float(i + mesh->curve_offset); // XXX fix kernel code
+ distribution[offset].z = __int_as_float(j);
+ distribution[offset].w = __int_as_float(object_id);
+ offset++;
+
+ float3 p1 = mesh->curve_keys[first_key + j].loc;
+ float r1 = mesh->curve_keys[first_key + j].radius;
+ float3 p2 = mesh->curve_keys[first_key + j + 1].loc;
+ float r2 = mesh->curve_keys[first_key + j + 1].radius;
+
+ if(!transform_applied) {
+ p1 = transform_point(&tfm, p1);
+ p2 = transform_point(&tfm, p2);
+ }
+
+ totarea += M_PI_F * (r1 + r2) * len(p1 - p2);
+ }
+ }
+
+ i++;
+ }
+#endif
}
if(progress.get_cancel()) return;
@@ -245,13 +294,21 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
/* point lights */
float lightarea = (totarea > 0.0f)? totarea/scene->lights.size(): 1.0f;
+ bool use_lamp_mis = false;
for(int i = 0; i < scene->lights.size(); i++, offset++) {
+ Light *light = scene->lights[i];
+
distribution[offset].x = totarea;
distribution[offset].y = __int_as_float(~(int)i);
distribution[offset].z = 1.0f;
- distribution[offset].w = scene->lights[i]->size;
+ distribution[offset].w = light->size;
totarea += lightarea;
+
+ if(light->size > 0.0f && light->use_mis)
+ use_lamp_mis = true;
+ if(light->type == LIGHT_BACKGROUND)
+ num_background_lights++;
}
/* normalize cumulative distribution functions */
@@ -270,15 +327,17 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
/* update device */
KernelIntegrator *kintegrator = &dscene->data.integrator;
+ KernelFilm *kfilm = &dscene->data.film;
kintegrator->use_direct_light = (totarea > 0.0f);
if(kintegrator->use_direct_light) {
/* number of emissives */
- kintegrator->num_distribution = (totarea > 0.0f)? num_distribution: 0;
+ kintegrator->num_distribution = num_distribution;
/* precompute pdfs */
kintegrator->pdf_triangles = 0.0f;
kintegrator->pdf_lights = 0.0f;
+ kintegrator->inv_pdf_lights = 0.0f;
/* sample one, with 0.5 probability of light or triangle */
kintegrator->num_all_lights = num_lights;
@@ -293,8 +352,22 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
kintegrator->pdf_lights = 1.0f/num_lights;
if(trianglearea > 0.0f)
kintegrator->pdf_lights *= 0.5f;
+
+ kintegrator->inv_pdf_lights = 1.0f/kintegrator->pdf_lights;
}
+ kintegrator->use_lamp_mis = use_lamp_mis;
+
+ /* bit of an ugly hack to compensate for emitting triangles influencing
+ * amount of samples we get for this pass */
+ kfilm->pass_shadow_scale = 1.0f;
+
+ if(kintegrator->pdf_triangles != 0.0f)
+ kfilm->pass_shadow_scale *= 0.5f;
+
+ if(num_background_lights < num_lights)
+ kfilm->pass_shadow_scale *= (float)(num_lights - num_background_lights)/(float)num_lights;
+
/* CDF */
device->tex_alloc("__light_distribution", dscene->light_distribution);
}
@@ -305,6 +378,9 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
kintegrator->num_all_lights = 0;
kintegrator->pdf_triangles = 0.0f;
kintegrator->pdf_lights = 0.0f;
+ kintegrator->inv_pdf_lights = 0.0f;
+ kintegrator->use_lamp_mis = false;
+ kfilm->pass_shadow_scale = 1.0f;
}
}
@@ -431,21 +507,37 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
if(light->type == LIGHT_POINT) {
shader_id &= ~SHADER_AREA_LIGHT;
+ float radius = light->size;
+ float invarea = (radius > 0.0f)? 1.0f/(M_PI_F*radius*radius): 1.0f;
+
+ 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), light->size, 0.0f, 0.0f);
+ 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);
}
else if(light->type == LIGHT_DISTANT) {
shader_id &= ~SHADER_AREA_LIGHT;
+ float radius = light->size;
+ float angle = atanf(radius);
+ float cosangle = cosf(angle);
+ float area = M_PI_F*radius*radius;
+ float invarea = (area > 0.0f)? 1.0f/area: 1.0f;
+
+ 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), light->size, 0.0f, 0.0f);
+ 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);
}
else if(light->type == LIGHT_BACKGROUND) {
shader_id &= ~SHADER_AREA_LIGHT;
+ shader_id |= SHADER_USE_MIS;
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);
@@ -455,21 +547,31 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
else if(light->type == LIGHT_AREA) {
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;
+
+ 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(0.0f, axisv.x, axisv.y, axisv.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);
}
else if(light->type == LIGHT_SPOT) {
shader_id &= ~SHADER_AREA_LIGHT;
+ float radius = light->size;
+ float invarea = (radius > 0.0f)? 1.0f/(M_PI_F*radius*radius): 1.0f;
float spot_angle = cosf(light->spot_angle*0.5f);
float spot_smooth = (1.0f - spot_angle)*light->spot_smooth;
+ 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), light->size, dir.x, dir.y);
- light_data[i*LIGHT_SIZE + 2] = make_float4(dir.z, spot_angle, spot_smooth, 0.0f);
+ 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);
}
}
diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h
index 3cedde2596e..acd1692a41f 100644
--- a/intern/cycles/render/light.h
+++ b/intern/cycles/render/light.h
@@ -52,6 +52,7 @@ public:
float spot_smooth;
bool cast_shadow;
+ bool use_mis;
int shader;
int samples;
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index bc782a78c60..8d12ace4252 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -43,6 +43,7 @@ Mesh::Mesh()
need_update = true;
transform_applied = false;
transform_negative_scaled = false;
+ transform_normal = transform_identity();
displacement_method = DISPLACE_BUMP;
bounds = BoundBox::empty;
@@ -51,7 +52,11 @@ Mesh::Mesh()
tri_offset = 0;
vert_offset = 0;
- attributes.mesh = this;
+ curve_offset = 0;
+ curvekey_offset = 0;
+
+ attributes.triangle_mesh = this;
+ curve_attributes.curve_mesh = this;
}
Mesh::~Mesh()
@@ -59,14 +64,18 @@ Mesh::~Mesh()
delete bvh;
}
-void Mesh::reserve(int numverts, int numtris)
+void Mesh::reserve(int numverts, int numtris, int numcurves, int numcurvekeys)
{
/* reserve space to add verts and triangles later */
verts.resize(numverts);
triangles.resize(numtris);
shader.resize(numtris);
smooth.resize(numtris);
- attributes.reserve(numverts, numtris);
+ curve_keys.resize(numcurvekeys);
+ curves.resize(numcurves);
+
+ attributes.reserve();
+ curve_attributes.reserve();
}
void Mesh::clear()
@@ -77,33 +86,61 @@ void Mesh::clear()
shader.clear();
smooth.clear();
+ curve_keys.clear();
+ curves.clear();
+
attributes.clear();
+ curve_attributes.clear();
used_shaders.clear();
transform_applied = false;
transform_negative_scaled = false;
+ transform_normal = transform_identity();
}
void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_)
{
- Triangle t;
- t.v[0] = v0;
- t.v[1] = v1;
- t.v[2] = v2;
+ Triangle tri;
+ tri.v[0] = v0;
+ tri.v[1] = v1;
+ tri.v[2] = v2;
- triangles.push_back(t);
+ triangles.push_back(tri);
shader.push_back(shader_);
smooth.push_back(smooth_);
}
+void Mesh::add_curve_key(float3 co, float radius)
+{
+ CurveKey key;
+ key.co = co;
+ key.radius = radius;
+
+ curve_keys.push_back(key);
+}
+
+void Mesh::add_curve(int first_key, int num_keys, int shader)
+{
+ Curve curve;
+ curve.first_key = first_key;
+ curve.num_keys = num_keys;
+ curve.shader = shader;
+
+ curves.push_back(curve);
+}
+
void Mesh::compute_bounds()
{
BoundBox bnds = BoundBox::empty;
size_t verts_size = verts.size();
+ size_t curve_keys_size = curve_keys.size();
for(size_t i = 0; i < verts_size; i++)
bnds.grow(verts[i]);
+ for(size_t i = 0; i < curve_keys_size; i++)
+ bnds.grow(curve_keys[i].co, curve_keys[i].radius);
+
/* happens mostly on empty meshes */
if(!bnds.valid())
bnds.grow(make_float3(0.0f, 0.0f, 0.0f));
@@ -116,7 +153,7 @@ void Mesh::add_face_normals()
/* don't compute if already there */
if(attributes.find(ATTR_STD_FACE_NORMAL))
return;
-
+
/* get attributes */
Attribute *attr_fN = attributes.add(ATTR_STD_FACE_NORMAL);
float3 *fN = attr_fN->data_float3();
@@ -135,12 +172,25 @@ void Mesh::add_face_normals()
float3 v1 = verts_ptr[t.v[1]];
float3 v2 = verts_ptr[t.v[2]];
- fN[i] = normalize(cross(v1 - v0, v2 - v0));
+ float3 norm = cross(v1 - v0, v2 - v0);
+ float normlen = len(norm);
+ if(normlen == 0.0f)
+ fN[i] = make_float3(0.0f, 0.0f, 0.0f);
+ else
+ fN[i] = norm / normlen;
if(flip)
fN[i] = -fN[i];
}
}
+
+ /* expected to be in local space */
+ if(transform_applied) {
+ Transform ntfm = transform_inverse(transform_normal);
+
+ for(size_t i = 0; i < triangles_size; i++)
+ fN[i] = normalize(transform_direction(&ntfm, fN[i]));
+ }
}
void Mesh::add_vertex_normals()
@@ -148,7 +198,7 @@ void Mesh::add_vertex_normals()
/* don't compute if already there */
if(attributes.find(ATTR_STD_VERTEX_NORMAL))
return;
-
+
/* get attributes */
Attribute *attr_fN = attributes.find(ATTR_STD_FACE_NORMAL);
Attribute *attr_vN = attributes.add(ATTR_STD_VERTEX_NORMAL);
@@ -192,10 +242,18 @@ void Mesh::pack_normals(Scene *scene, float4 *normal, float4 *vnormal)
size_t triangles_size = triangles.size();
uint *shader_ptr = (shader.size())? &shader[0]: NULL;
+ bool do_transform = transform_applied;
+ Transform ntfm = transform_normal;
+
for(size_t i = 0; i < triangles_size; i++) {
- normal[i].x = fN[i].x;
- normal[i].y = fN[i].y;
- normal[i].z = fN[i].z;
+ float3 fNi = fN[i];
+
+ if(do_transform)
+ fNi = normalize(transform_direction(&ntfm, fNi));
+
+ normal[i].x = fNi.x;
+ normal[i].y = fNi.y;
+ normal[i].z = fNi.z;
/* stuff shader id in here too */
if(shader_ptr[i] != last_shader || last_smooth != smooth[i]) {
@@ -209,8 +267,14 @@ void Mesh::pack_normals(Scene *scene, float4 *normal, float4 *vnormal)
size_t verts_size = verts.size();
- for(size_t i = 0; i < verts_size; i++)
- vnormal[i] = make_float4(vN[i].x, vN[i].y, vN[i].z, 0.0f);
+ for(size_t i = 0; i < verts_size; i++) {
+ float3 vNi = vN[i];
+
+ if(do_transform)
+ vNi = normalize(transform_direction(&ntfm, vNi));
+
+ vnormal[i] = make_float4(vNi.x, vNi.y, vNi.z, 0.0f);
+ }
}
void Mesh::pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset)
@@ -243,6 +307,43 @@ void Mesh::pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset)
}
}
+void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset)
+{
+ size_t curve_keys_size = curve_keys.size();
+ CurveKey *keys_ptr = NULL;
+
+ /* pack curve keys */
+ if(curve_keys_size) {
+ keys_ptr = &curve_keys[0];
+
+ for(size_t i = 0; i < curve_keys_size; i++) {
+ float3 p = keys_ptr[i].co;
+ float radius = keys_ptr[i].radius;
+
+ curve_key_co[i] = make_float4(p.x, p.y, p.z, radius);
+ }
+ }
+
+ /* pack curve segments */
+ size_t curve_num = curves.size();
+
+ if(curve_num) {
+ Curve *curve_ptr = &curves[0];
+ int shader_id = 0;
+
+ for(size_t i = 0; i < curve_num; i++) {
+ Curve curve = curve_ptr[i];
+ shader_id = scene->shader_manager->get_shader_id(curve.shader, this, false);
+
+ curve_data[i] = make_float4(
+ __int_as_float(curve.first_key + curvekey_offset),
+ __int_as_float(curve.num_keys),
+ __int_as_float(shader_id),
+ 0.0f);
+ }
+ }
+}
+
void Mesh::compute_bvh(SceneParams *params, Progress *progress, int n, int total)
{
if(progress->get_cancel())
@@ -327,7 +428,7 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
og->attribute_map.clear();
og->object_names.clear();
- og->attribute_map.resize(scene->objects.size());
+ og->attribute_map.resize(scene->objects.size()*ATTR_PRIM_TYPES);
for(size_t i = 0; i < scene->objects.size(); i++) {
/* set object name to object index map */
@@ -343,7 +444,8 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
osl_attr.elem = ATTR_ELEMENT_VALUE;
osl_attr.value = attr;
- og->attribute_map[i][attr.name()] = osl_attr;
+ og->attribute_map[i*ATTR_PRIM_TYPES][attr.name()] = osl_attr;
+ og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][attr.name()] = osl_attr;
}
/* find mesh attributes */
@@ -357,27 +459,46 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
/* set object attributes */
foreach(AttributeRequest& req, attributes.requests) {
- if(req.element == ATTR_ELEMENT_NONE)
- continue;
-
OSLGlobals::Attribute osl_attr;
- osl_attr.elem = req.element;
- osl_attr.offset = req.offset;
-
- if(req.type == TypeDesc::TypeFloat)
- osl_attr.type = TypeDesc::TypeFloat;
- else
- osl_attr.type = TypeDesc::TypeColor;
-
- if(req.std != ATTR_STD_NONE) {
- /* if standard attribute, add lookup by geom: name convention */
- ustring stdname(string("geom:") + string(attribute_standard_name(req.std)));
- og->attribute_map[i][stdname] = osl_attr;
+ if(req.triangle_element != ATTR_ELEMENT_NONE) {
+ osl_attr.elem = req.triangle_element;
+ osl_attr.offset = req.triangle_offset;
+
+ if(req.triangle_type == TypeDesc::TypeFloat)
+ osl_attr.type = TypeDesc::TypeFloat;
+ else
+ osl_attr.type = TypeDesc::TypeColor;
+
+ if(req.std != ATTR_STD_NONE) {
+ /* if standard attribute, add lookup by geom: name convention */
+ ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
+ og->attribute_map[i*ATTR_PRIM_TYPES][stdname] = osl_attr;
+ }
+ else if(req.name != ustring()) {
+ /* add lookup by mesh attribute name */
+ og->attribute_map[i*ATTR_PRIM_TYPES][req.name] = osl_attr;
+ }
}
- else if(req.name != ustring()) {
- /* add lookup by mesh attribute name */
- og->attribute_map[i][req.name] = osl_attr;
+
+ if(req.curve_element != ATTR_ELEMENT_NONE) {
+ osl_attr.elem = req.curve_element;
+ osl_attr.offset = req.curve_offset;
+
+ if(req.curve_type == TypeDesc::TypeFloat)
+ osl_attr.type = TypeDesc::TypeFloat;
+ else
+ osl_attr.type = TypeDesc::TypeColor;
+
+ if(req.std != ATTR_STD_NONE) {
+ /* if standard attribute, add lookup by geom: name convention */
+ ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
+ og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][stdname] = osl_attr;
+ }
+ else if(req.name != ustring()) {
+ /* add lookup by mesh attribute name */
+ og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][req.name] = osl_attr;
+ }
}
}
}
@@ -393,7 +514,7 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
int attr_map_stride = 0;
for(size_t i = 0; i < scene->meshes.size(); i++)
- attr_map_stride = max(attr_map_stride, mesh_attributes[i].size()+1);
+ attr_map_stride = max(attr_map_stride, (mesh_attributes[i].size() + 1)*ATTR_PRIM_TYPES);
if(attr_map_stride == 0)
return;
@@ -404,12 +525,13 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
for(size_t i = 0; i < scene->objects.size(); i++) {
Object *object = scene->objects[i];
+ Mesh *mesh = object->mesh;
/* find mesh attributes */
size_t j;
for(j = 0; j < scene->meshes.size(); j++)
- if(scene->meshes[j] == object->mesh)
+ if(scene->meshes[j] == mesh)
break;
AttributeRequestSet& attributes = mesh_attributes[j];
@@ -425,14 +547,29 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
else
id = scene->shader_manager->get_attribute_id(req.std);
- attr_map[index].x = id;
- attr_map[index].y = req.element;
- attr_map[index].z = as_uint(req.offset);
+ if(mesh->triangles.size()) {
+ attr_map[index].x = id;
+ attr_map[index].y = req.triangle_element;
+ attr_map[index].z = as_uint(req.triangle_offset);
- if(req.type == TypeDesc::TypeFloat)
- attr_map[index].w = NODE_ATTR_FLOAT;
- else
- attr_map[index].w = NODE_ATTR_FLOAT3;
+ if(req.triangle_type == TypeDesc::TypeFloat)
+ attr_map[index].w = NODE_ATTR_FLOAT;
+ else
+ attr_map[index].w = NODE_ATTR_FLOAT3;
+ }
+
+ index++;
+
+ if(mesh->curves.size()) {
+ attr_map[index].x = id;
+ attr_map[index].y = req.curve_element;
+ attr_map[index].z = as_uint(req.curve_offset);
+
+ if(req.curve_type == TypeDesc::TypeFloat)
+ attr_map[index].w = NODE_ATTR_FLOAT;
+ else
+ attr_map[index].w = NODE_ATTR_FLOAT3;
+ }
index++;
}
@@ -442,6 +579,15 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
attr_map[index].y = 0;
attr_map[index].z = 0;
attr_map[index].w = 0;
+
+ index++;
+
+ attr_map[index].x = ATTR_STD_NONE;
+ attr_map[index].y = 0;
+ attr_map[index].z = 0;
+ attr_map[index].w = 0;
+
+ index++;
}
/* copy to device */
@@ -449,6 +595,60 @@ 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,
+ Attribute *mattr, TypeDesc& type, int& offset, AttributeElement& element)
+{
+ if(mattr) {
+ /* store element and type */
+ element = mattr->element;
+ type = mattr->type;
+
+ /* store attribute data in arrays */
+ size_t size = mattr->element_size(
+ mesh->verts.size(),
+ mesh->triangles.size(),
+ mesh->curves.size(),
+ mesh->curve_keys.size());
+
+ if(mattr->type == TypeDesc::TypeFloat) {
+ float *data = mattr->data_float();
+ offset = attr_float.size();
+
+ attr_float.resize(attr_float.size() + size);
+
+ for(size_t k = 0; k < size; k++)
+ attr_float[offset+k] = data[k];
+ }
+ else {
+ float3 *data = mattr->data_float3();
+ offset = attr_float3.size();
+
+ attr_float3.resize(attr_float3.size() + size);
+
+ for(size_t k = 0; k < size; k++)
+ attr_float3[offset+k] = float3_to_float4(data[k]);
+ }
+
+ /* mesh vertex/curve index is global, not per object, so we sneak
+ * a correction for that in here */
+ if(element == ATTR_ELEMENT_VERTEX)
+ offset -= mesh->vert_offset;
+ else if(element == ATTR_ELEMENT_FACE)
+ offset -= mesh->tri_offset;
+ else if(element == ATTR_ELEMENT_CORNER)
+ offset -= 3*mesh->tri_offset;
+ else if(element == ATTR_ELEMENT_CURVE)
+ offset -= mesh->curve_offset;
+ else if(element == ATTR_ELEMENT_CURVE_KEY)
+ offset -= mesh->curvekey_offset;
+ }
+ else {
+ /* attribute not found */
+ element = ATTR_ELEMENT_NONE;
+ offset = 0;
+ }
+}
+
void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
progress.set_status("Updating Mesh", "Computing attributes");
@@ -482,66 +682,24 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
/* 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 *mattr = mesh->attributes.find(req);
-
- /* todo: get rid of this exception */
- if(!mattr && req.std == ATTR_STD_GENERATED) {
- mattr = mesh->attributes.add(ATTR_STD_GENERATED);
+ Attribute *triangle_mattr = mesh->attributes.find(req);
+ Attribute *curve_mattr = mesh->curve_attributes.find(req);
+
+ /* todo: get rid of this exception, it's only here for giving some
+ * working texture coordinate for subdivision as we can't preserve
+ * any attributes yet */
+ if(!triangle_mattr && req.std == ATTR_STD_GENERATED) {
+ triangle_mattr = mesh->attributes.add(ATTR_STD_GENERATED);
if(mesh->verts.size())
- memcpy(mattr->data_float3(), &mesh->verts[0], sizeof(float3)*mesh->verts.size());
- }
-
- /* attribute not found */
- if(!mattr) {
- req.element = ATTR_ELEMENT_NONE;
- req.offset = 0;
- continue;
- }
-
- /* we abuse AttributeRequest to pass on info like element and
- * offset, it doesn't really make sense but is convenient */
-
- /* store element and type */
- if(mattr->element == Attribute::VERTEX)
- req.element = ATTR_ELEMENT_VERTEX;
- else if(mattr->element == Attribute::FACE)
- req.element = ATTR_ELEMENT_FACE;
- else if(mattr->element == Attribute::CORNER)
- req.element = ATTR_ELEMENT_CORNER;
-
- req.type = mattr->type;
-
- /* store attribute data in arrays */
- size_t size = mattr->element_size(mesh->verts.size(), mesh->triangles.size());
-
- if(mattr->type == TypeDesc::TypeFloat) {
- float *data = mattr->data_float();
- req.offset = attr_float.size();
-
- attr_float.resize(attr_float.size() + size);
-
- for(size_t k = 0; k < size; k++)
- attr_float[req.offset+k] = data[k];
+ memcpy(triangle_mattr->data_float3(), &mesh->verts[0], sizeof(float3)*mesh->verts.size());
}
- else {
- float3 *data = mattr->data_float3();
- req.offset = attr_float3.size();
- attr_float3.resize(attr_float3.size() + size);
-
- for(size_t k = 0; k < size; k++)
- attr_float3[req.offset+k] = float3_to_float4(data[k]);
- }
-
- /* mesh vertex/triangle index is global, not per object, so we sneak
- * a correction for that in here */
- if(req.element == ATTR_ELEMENT_VERTEX)
- req.offset -= mesh->vert_offset;
- else if(mattr->element == Attribute::FACE)
- req.offset -= mesh->tri_offset;
- else if(mattr->element == Attribute::CORNER)
- req.offset -= 3*mesh->tri_offset;
+ update_attribute_element_offset(mesh, attr_float, attr_float3, triangle_mattr,
+ req.triangle_type, req.triangle_offset, req.triangle_element);
+ update_attribute_element_offset(mesh, attr_float, attr_float3, curve_mattr,
+ req.curve_type, req.curve_offset, req.curve_element);
+
if(progress.get_cancel()) return;
}
}
@@ -573,39 +731,62 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene
size_t vert_size = 0;
size_t tri_size = 0;
+ size_t curve_key_size = 0;
+ size_t curve_size = 0;
+
foreach(Mesh *mesh, scene->meshes) {
mesh->vert_offset = vert_size;
mesh->tri_offset = tri_size;
+ mesh->curvekey_offset = curve_key_size;
+ mesh->curve_offset = curve_size;
+
vert_size += mesh->verts.size();
tri_size += mesh->triangles.size();
+
+ curve_key_size += mesh->curve_keys.size();
+ curve_size += mesh->curves.size();
}
- if(tri_size == 0)
- return;
+ if(tri_size != 0) {
+ /* normals */
+ progress.set_status("Updating Mesh", "Computing normals");
- /* normals */
- progress.set_status("Updating Mesh", "Computing normals");
+ float4 *normal = dscene->tri_normal.resize(tri_size);
+ float4 *vnormal = dscene->tri_vnormal.resize(vert_size);
+ float4 *tri_verts = dscene->tri_verts.resize(vert_size);
+ float4 *tri_vindex = dscene->tri_vindex.resize(tri_size);
- float4 *normal = dscene->tri_normal.resize(tri_size);
- float4 *vnormal = dscene->tri_vnormal.resize(vert_size);
- float4 *tri_verts = dscene->tri_verts.resize(vert_size);
- float4 *tri_vindex = dscene->tri_vindex.resize(tri_size);
+ foreach(Mesh *mesh, scene->meshes) {
+ mesh->pack_normals(scene, &normal[mesh->tri_offset], &vnormal[mesh->vert_offset]);
+ mesh->pack_verts(&tri_verts[mesh->vert_offset], &tri_vindex[mesh->tri_offset], mesh->vert_offset);
- foreach(Mesh *mesh, scene->meshes) {
- mesh->pack_normals(scene, &normal[mesh->tri_offset], &vnormal[mesh->vert_offset]);
- mesh->pack_verts(&tri_verts[mesh->vert_offset], &tri_vindex[mesh->tri_offset], mesh->vert_offset);
+ if(progress.get_cancel()) return;
+ }
- if(progress.get_cancel()) return;
+ /* vertex coordinates */
+ progress.set_status("Updating Mesh", "Copying Mesh to device");
+
+ device->tex_alloc("__tri_normal", dscene->tri_normal);
+ device->tex_alloc("__tri_vnormal", dscene->tri_vnormal);
+ device->tex_alloc("__tri_verts", dscene->tri_verts);
+ device->tex_alloc("__tri_vindex", dscene->tri_vindex);
}
- /* vertex coordinates */
- progress.set_status("Updating Mesh", "Copying Mesh to device");
+ if(curve_size != 0) {
+ progress.set_status("Updating Mesh", "Copying Strands to device");
+
+ float4 *curve_keys = dscene->curve_keys.resize(curve_key_size);
+ float4 *curves = dscene->curves.resize(curve_size);
- device->tex_alloc("__tri_normal", dscene->tri_normal);
- device->tex_alloc("__tri_vnormal", dscene->tri_vnormal);
- device->tex_alloc("__tri_verts", dscene->tri_verts);
- device->tex_alloc("__tri_vindex", dscene->tri_vindex);
+ foreach(Mesh *mesh, scene->meshes) {
+ mesh->pack_curves(scene, &curve_keys[mesh->curvekey_offset], &curves[mesh->curve_offset], mesh->curvekey_offset);
+ if(progress.get_cancel()) return;
+ }
+
+ device->tex_alloc("__curve_keys", dscene->curve_keys);
+ device->tex_alloc("__curves", dscene->curves);
+ }
}
void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
@@ -642,6 +823,10 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
dscene->tri_woop.reference(&pack.tri_woop[0], pack.tri_woop.size());
device->tex_alloc("__tri_woop", dscene->tri_woop);
}
+ if(pack.prim_segment.size()) {
+ dscene->prim_segment.reference((uint*)&pack.prim_segment[0], pack.prim_segment.size());
+ device->tex_alloc("__prim_segment", dscene->prim_segment);
+ }
if(pack.prim_visibility.size()) {
dscene->prim_visibility.reference((uint*)&pack.prim_visibility[0], pack.prim_visibility.size());
device->tex_alloc("__prim_visibility", dscene->prim_visibility);
@@ -751,6 +936,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
device->tex_free(dscene->bvh_nodes);
device->tex_free(dscene->object_node);
device->tex_free(dscene->tri_woop);
+ device->tex_free(dscene->prim_segment);
device->tex_free(dscene->prim_visibility);
device->tex_free(dscene->prim_index);
device->tex_free(dscene->prim_object);
@@ -758,6 +944,8 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
device->tex_free(dscene->tri_vnormal);
device->tex_free(dscene->tri_vindex);
device->tex_free(dscene->tri_verts);
+ device->tex_free(dscene->curves);
+ device->tex_free(dscene->curve_keys);
device->tex_free(dscene->attributes_map);
device->tex_free(dscene->attributes_float);
device->tex_free(dscene->attributes_float3);
@@ -765,6 +953,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
dscene->bvh_nodes.clear();
dscene->object_node.clear();
dscene->tri_woop.clear();
+ dscene->prim_segment.clear();
dscene->prim_visibility.clear();
dscene->prim_index.clear();
dscene->prim_object.clear();
@@ -772,9 +961,21 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
dscene->tri_vnormal.clear();
dscene->tri_vindex.clear();
dscene->tri_verts.clear();
+ dscene->curves.clear();
+ dscene->curve_keys.clear();
dscene->attributes_map.clear();
dscene->attributes_float.clear();
dscene->attributes_float3.clear();
+
+#ifdef WITH_OSL
+ OSLGlobals *og = (OSLGlobals*)device->osl_memory();
+
+ if(og) {
+ og->object_name_map.clear();
+ og->attribute_map.clear();
+ og->object_names.clear();
+ }
+#endif
}
void MeshManager::tag_update(Scene *scene)
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index 637143f5adf..dca1b00e1ff 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -50,6 +50,21 @@ public:
int v[3];
};
+ /* Mesh Curve */
+ struct Curve {
+ int first_key;
+ int num_keys;
+ uint shader;
+ uint pad;
+
+ int num_segments() { return num_keys - 1; }
+ };
+
+ struct CurveKey {
+ float3 co;
+ float radius;
+ };
+
/* Displacement */
enum DisplacementMethod {
DISPLACE_BUMP,
@@ -65,12 +80,17 @@ public:
vector<uint> shader;
vector<bool> smooth;
+ vector<CurveKey> curve_keys;
+ vector<Curve> curves;
+
vector<uint> used_shaders;
AttributeSet attributes;
+ AttributeSet curve_attributes;
BoundBox bounds;
bool transform_applied;
bool transform_negative_scaled;
+ Transform transform_normal;
DisplacementMethod displacement_method;
/* Update Flags */
@@ -82,13 +102,18 @@ public:
size_t tri_offset;
size_t vert_offset;
+ size_t curve_offset;
+ size_t curvekey_offset;
+
/* Functions */
Mesh();
~Mesh();
- void reserve(int numverts, int numfaces);
+ void reserve(int numverts, int numfaces, int numcurves, int numcurvekeys);
void clear();
void add_triangle(int v0, int v1, int v2, int shader, bool smooth);
+ void add_curve_key(float3 loc, float radius);
+ void add_curve(int first_key, int num_keys, int shader);
void compute_bounds();
void add_face_normals();
@@ -96,6 +121,7 @@ public:
void pack_normals(Scene *scene, float4 *normal, float4 *vnormal);
void pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset);
+ void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset);
void compute_bvh(SceneParams *params, Progress *progress, int n, int total);
bool need_attribute(Scene *scene, AttributeStandard std);
diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp
index dea694a811e..04267697b29 100644
--- a/intern/cycles/render/mesh_displace.cpp
+++ b/intern/cycles/render/mesh_displace.cpp
@@ -19,6 +19,7 @@
#include "device.h"
#include "mesh.h"
+#include "object.h"
#include "scene.h"
#include "shader.h"
@@ -41,11 +42,24 @@ bool MeshManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress& p
if(!has_displacement)
return false;
+ string msg = string_printf("Computing Displacement %s", mesh->name.c_str());
+ progress.set_status("Updating Mesh", msg);
+
+ /* find object index. todo: is arbitrary */
+ size_t object_index = ~0;
+
+ for(size_t i = 0; i < scene->objects.size(); i++) {
+ if(scene->objects[i]->mesh == mesh) {
+ object_index = i;
+ break;
+ }
+ }
+
/* setup input for device task */
vector<bool> done(mesh->verts.size(), false);
device_vector<uint4> d_input;
uint4 *d_input_data = d_input.resize(mesh->verts.size());
- size_t d_input_offset = 0;
+ size_t d_input_size = 0;
for(size_t i = 0; i < mesh->triangles.size(); i++) {
Mesh::Triangle t = mesh->triangles[i];
@@ -61,8 +75,8 @@ bool MeshManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress& p
done[t.v[j]] = true;
/* set up object, primitive and barycentric coordinates */
- /* when used, non-instanced convention: object = -object-1; */
- int object = ~0; /* todo */
+ /* when used, non-instanced convention: object = ~object */
+ int object = ~object_index;
int prim = mesh->tri_offset + i;
float u, v;
@@ -81,16 +95,16 @@ bool MeshManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress& p
/* back */
uint4 in = make_uint4(object, prim, __float_as_int(u), __float_as_int(v));
- d_input_data[d_input_offset++] = in;
+ d_input_data[d_input_size++] = in;
}
}
- if(d_input_offset == 0)
+ if(d_input_size == 0)
return false;
/* run device task */
device_vector<float4> d_output;
- d_output.resize(d_input.size());
+ d_output.resize(d_input_size);
device->mem_alloc(d_input, MEM_READ_ONLY);
device->mem_copy_to(d_input);
@@ -101,7 +115,7 @@ bool MeshManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress& p
task.shader_output = d_output.device_pointer;
task.shader_eval_type = SHADER_EVAL_DISPLACE;
task.shader_x = 0;
- task.shader_w = d_input.size();
+ task.shader_w = d_output.size();
device->task_add(task);
device->task_wait();
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index aef28449e44..398b9f0a758 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -141,9 +141,11 @@ ImageTextureNode::ImageTextureNode()
image_manager = NULL;
slot = -1;
is_float = -1;
+ is_linear = false;
filename = "";
+ builtin_data = NULL;
color_space = ustring("Color");
- projection = ustring("Flat");;
+ projection = ustring("Flat");
projection_blend = 0.0f;
animated = false;
@@ -155,7 +157,7 @@ ImageTextureNode::ImageTextureNode()
ImageTextureNode::~ImageTextureNode()
{
if(image_manager)
- image_manager->remove_image(filename);
+ image_manager->remove_image(filename, builtin_data);
}
ShaderNode *ImageTextureNode::clone() const
@@ -164,6 +166,7 @@ ShaderNode *ImageTextureNode::clone() const
node->image_manager = NULL;
node->slot = -1;
node->is_float = -1;
+ node->is_linear = false;
return node;
}
@@ -176,7 +179,7 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
image_manager = compiler.image_manager;
if(is_float == -1) {
bool is_float_bool;
- slot = image_manager->add_image(filename, animated, is_float_bool);
+ slot = image_manager->add_image(filename, builtin_data, animated, is_float_bool, is_linear);
is_float = (int)is_float_bool;
}
@@ -188,7 +191,7 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
if(slot != -1) {
compiler.stack_assign(vector_in);
- int srgb = (is_float || color_space != "Color")? 0: 1;
+ int srgb = (is_linear || color_space != "Color")? 0: 1;
int vector_offset = vector_in->stack_offset;
if(!tex_mapping.skip()) {
@@ -237,10 +240,10 @@ void ImageTextureNode::compile(OSLCompiler& compiler)
tex_mapping.compile(compiler);
if(is_float == -1)
- is_float = (int)image_manager->is_float_image(filename);
+ is_float = (int)image_manager->is_float_image(filename, NULL, is_linear);
compiler.parameter("filename", filename.c_str());
- if(is_float || color_space != "Color")
+ if(is_linear || color_space != "Color")
compiler.parameter("color_space", "Linear");
else
compiler.parameter("color_space", "sRGB");
@@ -270,7 +273,9 @@ EnvironmentTextureNode::EnvironmentTextureNode()
image_manager = NULL;
slot = -1;
is_float = -1;
+ is_linear = false;
filename = "";
+ builtin_data = NULL;
color_space = ustring("Color");
projection = ustring("Equirectangular");
animated = false;
@@ -283,7 +288,7 @@ EnvironmentTextureNode::EnvironmentTextureNode()
EnvironmentTextureNode::~EnvironmentTextureNode()
{
if(image_manager)
- image_manager->remove_image(filename);
+ image_manager->remove_image(filename, builtin_data);
}
ShaderNode *EnvironmentTextureNode::clone() const
@@ -292,6 +297,7 @@ ShaderNode *EnvironmentTextureNode::clone() const
node->image_manager = NULL;
node->slot = -1;
node->is_float = -1;
+ node->is_linear = false;
return node;
}
@@ -304,7 +310,7 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler)
image_manager = compiler.image_manager;
if(slot == -1) {
bool is_float_bool;
- slot = image_manager->add_image(filename, animated, is_float_bool);
+ slot = image_manager->add_image(filename, builtin_data, animated, is_float_bool, is_linear);
is_float = (int)is_float_bool;
}
@@ -316,7 +322,7 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler)
if(slot != -1) {
compiler.stack_assign(vector_in);
- int srgb = (is_float || color_space != "Color")? 0: 1;
+ int srgb = (is_linear || color_space != "Color")? 0: 1;
int vector_offset = vector_in->stack_offset;
if(!tex_mapping.skip()) {
@@ -354,11 +360,11 @@ void EnvironmentTextureNode::compile(OSLCompiler& compiler)
tex_mapping.compile(compiler);
if(is_float == -1)
- is_float = (int)image_manager->is_float_image(filename);
+ is_float = (int)image_manager->is_float_image(filename, NULL, is_linear);
compiler.parameter("filename", filename.c_str());
compiler.parameter("projection", projection);
- if(is_float || color_space != "Color")
+ if(is_linear || color_space != "Color")
compiler.parameter("color_space", "Linear");
else
compiler.parameter("color_space", "sRGB");
@@ -1236,15 +1242,14 @@ void ConvertNode::compile(OSLCompiler& compiler)
/* Proxy */
-ProxyNode::ProxyNode(ShaderSocketType from_, ShaderSocketType to_)
+ProxyNode::ProxyNode(ShaderSocketType type_)
: ShaderNode("proxy")
{
- from = from_;
- to = to_;
+ type = type_;
special_type = SHADER_SPECIAL_TYPE_PROXY;
- add_input("Input", from);
- add_output("Output", to);
+ add_input("Input", type);
+ add_output("Output", type);
}
void ProxyNode::compile(SVMCompiler& compiler)
@@ -2240,6 +2245,63 @@ void ParticleInfoNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_particle_info");
}
+/* Hair Info */
+
+HairInfoNode::HairInfoNode()
+: ShaderNode("hair_info")
+{
+ add_output("Is Strand", SHADER_SOCKET_FLOAT);
+ add_output("Intercept", SHADER_SOCKET_FLOAT);
+ add_output("Thickness", SHADER_SOCKET_FLOAT);
+ add_output("Tangent Normal", SHADER_SOCKET_NORMAL);
+}
+
+void HairInfoNode::attributes(AttributeRequestSet *attributes)
+{
+ ShaderOutput *intercept_out = output("Intercept");
+
+ if(!intercept_out->links.empty())
+ attributes->add(ATTR_STD_CURVE_INTERCEPT);
+
+ ShaderNode::attributes(attributes);
+}
+
+void HairInfoNode::compile(SVMCompiler& compiler)
+{
+ ShaderOutput *out;
+
+ out = output("Is Strand");
+ if(!out->links.empty()) {
+ compiler.stack_assign(out);
+ compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_IS_STRAND, out->stack_offset);
+ }
+
+ out = output("Intercept");
+ if(!out->links.empty()) {
+ int attr = compiler.attribute(ATTR_STD_CURVE_INTERCEPT);
+ compiler.stack_assign(out);
+ compiler.add_node(NODE_ATTR, attr, out->stack_offset, NODE_ATTR_FLOAT);
+ }
+
+ out = output("Thickness");
+ if(!out->links.empty()) {
+ compiler.stack_assign(out);
+ compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_THICKNESS, out->stack_offset);
+ }
+
+ out = output("Tangent Normal");
+ if(!out->links.empty()) {
+ compiler.stack_assign(out);
+ compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_TANGENT_NORMAL, out->stack_offset);
+ }
+
+}
+
+void HairInfoNode::compile(OSLCompiler& compiler)
+{
+ compiler.add(this, "node_hair_info");
+}
+
/* Value */
ValueNode::ValueNode()
@@ -3198,6 +3260,8 @@ void NormalMapNode::attributes(AttributeRequestSet *attributes)
attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
attributes->add(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
}
+
+ attributes->add(ATTR_STD_VERTEX_NORMAL);
}
ShaderNode::attributes(attributes);
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 5e357cff56c..1efe4ae076d 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -26,7 +26,7 @@
CCL_NAMESPACE_BEGIN
class ImageManager;
-class Shadr;
+class Shader;
/* Texture Mapping */
@@ -69,7 +69,9 @@ public:
ImageManager *image_manager;
int slot;
int is_float;
+ bool is_linear;
string filename;
+ void *builtin_data;
ustring color_space;
ustring projection;
float projection_blend;
@@ -88,7 +90,9 @@ public:
ImageManager *image_manager;
int slot;
int is_float;
+ bool is_linear;
string filename;
+ void *builtin_data;
ustring color_space;
ustring projection;
bool animated;
@@ -186,10 +190,10 @@ public:
class ProxyNode : public ShaderNode {
public:
- ProxyNode(ShaderSocketType from, ShaderSocketType to);
+ ProxyNode(ShaderSocketType type);
SHADER_NODE_BASE_CLASS(ProxyNode)
- ShaderSocketType from, to;
+ ShaderSocketType type;
};
class BsdfNode : public ShaderNode {
@@ -220,6 +224,8 @@ public:
class TransparentBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(TransparentBsdfNode)
+
+ bool has_surface_transparent() { return true; }
};
class VelvetBsdfNode : public BsdfNode {
@@ -255,6 +261,8 @@ class EmissionNode : public ShaderNode {
public:
SHADER_NODE_CLASS(EmissionNode)
+ bool has_surface_emission() { return true; }
+
bool total_power;
};
@@ -327,6 +335,13 @@ public:
void attributes(AttributeRequestSet *attributes);
};
+class HairInfoNode : public ShaderNode {
+public:
+ SHADER_NODE_CLASS(HairInfoNode)
+
+ void attributes(AttributeRequestSet *attributes);
+};
+
class ValueNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ValueNode)
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index bd9f16d64ef..17008b7a7f3 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -19,6 +19,7 @@
#include "device.h"
#include "light.h"
#include "mesh.h"
+#include "curves.h"
#include "object.h"
#include "scene.h"
@@ -45,6 +46,7 @@ Object::Object()
motion.post = transform_identity();
use_motion = false;
use_holdout = false;
+ curverender = false;
}
Object::~Object()
@@ -82,34 +84,31 @@ void Object::apply_transform()
{
if(!mesh || tfm == transform_identity())
return;
-
+
+ float3 c0 = transform_get_column(&tfm, 0);
+ float3 c1 = transform_get_column(&tfm, 1);
+ float3 c2 = transform_get_column(&tfm, 2);
+ float scalar = pow(fabsf(dot(cross(c0, c1), c2)), 1.0f/3.0f);
+
for(size_t i = 0; i < mesh->verts.size(); i++)
mesh->verts[i] = transform_point(&tfm, mesh->verts[i]);
- Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL);
- Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
+ for(size_t i = 0; i < mesh->curve_keys.size(); i++) {
+ mesh->curve_keys[i].co = transform_point(&tfm, mesh->curve_keys[i].co);
+ /* scale for strand radius - only correct for uniform transforms*/
+ mesh->curve_keys[i].radius *= scalar;
+ }
- Transform ntfm = transform_transpose(transform_inverse(tfm));
+ /* store matrix to transform later. when accessing these as attributes we
+ * do not want the transform to be applied for consistency between static
+ * and dynamic BVH, so we do it on packing. */
+ mesh->transform_normal = transform_transpose(transform_inverse(tfm));
/* we keep normals pointing in same direction on negative scale, notify
* mesh about this in it (re)calculates normals */
if(transform_negative_scale(tfm))
mesh->transform_negative_scaled = true;
- if(attr_fN) {
- float3 *fN = attr_fN->data_float3();
-
- for(size_t i = 0; i < mesh->triangles.size(); i++)
- fN[i] = transform_direction(&ntfm, fN[i]);
- }
-
- if(attr_vN) {
- float3 *vN = attr_vN->data_float3();
-
- for(size_t i = 0; i < mesh->verts.size(); i++)
- vN[i] = transform_direction(&ntfm, vN[i]);
- }
-
if(bounds.valid()) {
mesh->compute_bounds();
compute_bounds(false, 0.0f);
@@ -133,6 +132,7 @@ void Object::tag_update(Scene *scene)
}
}
+ scene->curve_system_manager->need_update = true;
scene->mesh_manager->need_update = true;
scene->object_manager->need_update = true;
}
@@ -150,12 +150,17 @@ ObjectManager::~ObjectManager()
void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, uint *object_flag, Progress& progress)
{
- float4 *objects = dscene->objects.resize(OBJECT_SIZE*scene->objects.size());
+ float4 *objects;
+ float4 *objects_vector = NULL;
int i = 0;
map<Mesh*, float> surface_area_map;
Scene::MotionType need_motion = scene->need_motion(device->info.advanced_shading);
bool have_motion = false;
+ objects = dscene->objects.resize(OBJECT_SIZE*scene->objects.size());
+ if(need_motion == Scene::MOTION_PASS)
+ objects_vector = dscene->objects_vector.resize(OBJECT_VECTOR_SIZE*scene->objects.size());
+
foreach(Object *ob, scene->objects) {
Mesh *mesh = ob->mesh;
uint flag = 0;
@@ -184,6 +189,20 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
surface_area += triangle_area(p1, p2, p3);
}
+ foreach(Mesh::Curve& curve, mesh->curves) {
+ int first_key = curve.first_key;
+
+ for(int i = 0; i < curve.num_segments(); i++) {
+ float3 p1 = mesh->curve_keys[first_key + i].co;
+ float r1 = mesh->curve_keys[first_key + i].radius;
+ float3 p2 = mesh->curve_keys[first_key + i + 1].co;
+ float r2 = mesh->curve_keys[first_key + i + 1].radius;
+
+ /* currently ignores segment overlaps*/
+ surface_area += M_PI_F *(r1 + r2) * len(p1 - p2);
+ }
+ }
+
surface_area_map[mesh] = surface_area;
}
else
@@ -199,14 +218,31 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
surface_area += triangle_area(p1, p2, p3);
}
+
+ foreach(Mesh::Curve& curve, mesh->curves) {
+ int first_key = curve.first_key;
+
+ for(int i = 0; i < curve.num_segments(); i++) {
+ float3 p1 = mesh->curve_keys[first_key + i].co;
+ float r1 = mesh->curve_keys[first_key + i].radius;
+ float3 p2 = mesh->curve_keys[first_key + i + 1].co;
+ float r2 = mesh->curve_keys[first_key + i + 1].radius;
+
+ p1 = transform_point(&tfm, p1);
+ p2 = transform_point(&tfm, p2);
+
+ /* currently ignores segment overlaps*/
+ surface_area += M_PI_F *(r1 + r2) * len(p1 - p2);
+ }
+ }
}
/* pack in texture */
int offset = i*OBJECT_SIZE;
memcpy(&objects[offset], &tfm, sizeof(float4)*3);
- memcpy(&objects[offset+3], &itfm, sizeof(float4)*3);
- objects[offset+6] = make_float4(surface_area, pass_id, random_number, __int_as_float(ob->particle_id));
+ memcpy(&objects[offset+4], &itfm, sizeof(float4)*3);
+ objects[offset+8] = make_float4(surface_area, pass_id, random_number, __int_as_float(ob->particle_id));
if(need_motion == Scene::MOTION_PASS) {
/* motion transformations, is world/object space depending if mesh
@@ -220,8 +256,8 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
if(!mesh->attributes.find(ATTR_STD_MOTION_POST))
mtfm_post = mtfm_post * itfm;
- memcpy(&objects[offset+8], &mtfm_pre, sizeof(float4)*4);
- memcpy(&objects[offset+12], &mtfm_post, sizeof(float4)*4);
+ 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);
}
#ifdef __OBJECT_MOTION__
else if(need_motion == Scene::MOTION_BLUR) {
@@ -230,20 +266,16 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
DecompMotionTransform decomp;
transform_motion_decompose(&decomp, &ob->motion, &ob->tfm);
- memcpy(&objects[offset+8], &decomp, sizeof(float4)*8);
+ memcpy(&objects[offset], &decomp, sizeof(float4)*8);
flag |= SD_OBJECT_MOTION;
have_motion = true;
}
- else {
- float4 no_motion = make_float4(FLT_MAX);
- memcpy(&objects[offset+8], &no_motion, sizeof(float4)*8);
- }
}
#endif
/* dupli object coords */
- objects[offset+16] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f);
- objects[offset+17] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f);
+ objects[offset+9] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f);
+ objects[offset+10] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f);
/* object flag */
if(ob->use_holdout)
@@ -256,6 +288,8 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
}
device->tex_alloc("__objects", dscene->objects);
+ if(need_motion == Scene::MOTION_PASS)
+ device->tex_alloc("__objects_vector", dscene->objects_vector);
dscene->data.bvh.have_motion = have_motion;
}
@@ -267,6 +301,8 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc
device_free(device, dscene);
+ need_update = false;
+
if(scene->objects.size() == 0)
return;
@@ -288,8 +324,6 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc
/* allocate object flag */
device->tex_alloc("__object_flag", dscene->object_flag);
-
- need_update = false;
}
void ObjectManager::device_free(Device *device, DeviceScene *dscene)
@@ -297,6 +331,9 @@ void ObjectManager::device_free(Device *device, DeviceScene *dscene)
device->tex_free(dscene->objects);
dscene->objects.clear();
+ device->tex_free(dscene->objects_vector);
+ dscene->objects_vector.clear();
+
device->tex_free(dscene->object_flag);
dscene->object_flag.clear();
}
@@ -349,6 +386,7 @@ void ObjectManager::apply_static_transforms(Scene *scene, uint *object_flag, Pro
void ObjectManager::tag_update(Scene *scene)
{
need_update = true;
+ scene->curve_system_manager->need_update = true;
scene->mesh_manager->need_update = true;
scene->light_manager->need_update = true;
}
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index 9c9b11bc29c..9ba500ca4d6 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -48,6 +48,7 @@ public:
MotionTransform motion;
bool use_motion;
bool use_holdout;
+ bool curverender;
float3 dupli_generated;
float2 dupli_uv;
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index b3b838be25b..f5585babf5c 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -47,17 +47,27 @@ OSLShaderManager::OSLShaderManager()
{
services = new OSLRenderServices();
- shading_system_init();
texture_system_init();
+ shading_system_init();
}
OSLShaderManager::~OSLShaderManager()
{
OSL::ShadingSystem::destroy(ss);
OSL::TextureSystem::destroy(ts);
+
delete services;
}
+void OSLShaderManager::reset(Scene *scene)
+{
+ OSL::ShadingSystem::destroy(ss);
+ delete services;
+
+ services = new OSLRenderServices();
+ shading_system_init();
+}
+
void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
if(!need_update)
@@ -76,18 +86,19 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
if(progress.get_cancel()) return;
- if(shader->sample_as_light && shader->has_surface_emission)
- scene->light_manager->need_update = true;
-
OSLCompiler compiler((void*)this, (void*)ss, scene->image_manager);
compiler.background = (shader == scene->shaders[scene->default_background]);
compiler.compile(og, shader);
+
+ if(shader->sample_as_light && shader->has_surface_emission)
+ scene->light_manager->need_update = true;
}
/* setup shader engine */
og->ss = ss;
og->ts = ts;
og->services = services;
+
int background_id = scene->shader_manager->get_shader_id(scene->default_background);
og->background_state = og->surface_state[background_id & SHADER_MASK];
og->use = true;
@@ -202,8 +213,14 @@ static string shader_filepath_hash(const string& filepath, uint64_t modified_tim
const char *OSLShaderManager::shader_test_loaded(const string& hash)
{
- set<string>::iterator it = loaded_shaders.find(hash);
- return (it == loaded_shaders.end())? NULL: it->c_str();
+ map<string, OSLShaderInfo>::iterator it = loaded_shaders.find(hash);
+ return (it == loaded_shaders.end())? NULL: it->first.c_str();
+}
+
+OSLShaderInfo *OSLShaderManager::shader_loaded_info(const string& hash)
+{
+ map<string, OSLShaderInfo>::iterator it = loaded_shaders.find(hash);
+ return (it == loaded_shaders.end())? NULL: &it->second;
}
const char *OSLShaderManager::shader_load_filepath(string filepath)
@@ -261,7 +278,8 @@ const char *OSLShaderManager::shader_load_filepath(string filepath)
if(!path_read_text(filepath, bytecode)) {
fprintf(stderr, "Cycles shader graph: failed to read file %s\n", filepath.c_str());
- loaded_shaders.insert(bytecode_hash); /* to avoid repeat tries */
+ OSLShaderInfo info;
+ loaded_shaders[bytecode_hash] = info; /* to avoid repeat tries */
return NULL;
}
@@ -306,7 +324,13 @@ const char *OSLShaderManager::shader_load_bytecode(const string& hash, const str
{
load_memory_shader(ss, hash.c_str(), bytecode.c_str());
- return loaded_shaders.insert(hash).first->c_str();
+ /* this is a bit weak, but works */
+ OSLShaderInfo info;
+ info.has_surface_emission = (bytecode.find("\"emission\"") != string::npos);
+ info.has_surface_transparent = (bytecode.find("\"transparent\"") != string::npos);
+ loaded_shaders[hash] = info;
+
+ return loaded_shaders.find(hash)->first.c_str();
}
/* Graph Compiler */
@@ -444,6 +468,7 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
parameter(param_name.c_str(), input->value_string);
break;
case SHADER_SOCKET_CLOSURE:
+ case SHADER_SOCKET_UNDEFINED:
break;
}
}
@@ -477,6 +502,16 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
ss->ConnectShaders(id_from.c_str(), param_from.c_str(), id_to.c_str(), param_to.c_str());
}
}
+
+ /* test if we shader contains specific closures */
+ OSLShaderInfo *info = ((OSLShaderManager*)manager)->shader_loaded_info(name);
+
+ if(info) {
+ if(info->has_surface_emission)
+ current_shader->has_surface_emission = true;
+ if(info->has_surface_transparent)
+ current_shader->has_surface_transparent = true;
+ }
}
void OSLCompiler::parameter(const char *name, float f)
@@ -632,9 +667,9 @@ void OSLCompiler::generate_nodes(const set<ShaderNode*>& nodes)
node->compile(*this);
done.insert(node);
- if(node->name == ustring("emission"))
+ if(node->has_surface_emission())
current_shader->has_surface_emission = true;
- if(node->name == ustring("transparent"))
+ if(node->has_surface_transparent())
current_shader->has_surface_transparent = true;
}
else
diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h
index 9b58745bd46..4b4ed6cba00 100644
--- a/intern/cycles/render/osl.h
+++ b/intern/cycles/render/osl.h
@@ -36,7 +36,7 @@ class Device;
class DeviceScene;
class ImageManager;
class OSLRenderServices;
-class OSLGlobals;
+struct OSLGlobals;
class Scene;
class ShaderGraph;
class ShaderNode;
@@ -45,6 +45,18 @@ class ShaderOutput;
#ifdef WITH_OSL
+/* OSL Shader Info
+ * to auto detect closures in the shader for MIS and transparent shadows */
+
+struct OSLShaderInfo {
+ OSLShaderInfo()
+ : has_surface_emission(false), has_surface_transparent(false)
+ {}
+
+ bool has_surface_emission;
+ bool has_surface_transparent;
+};
+
/* Shader Manage */
class OSLShaderManager : public ShaderManager {
@@ -52,6 +64,8 @@ public:
OSLShaderManager();
~OSLShaderManager();
+ void reset(Scene *scene);
+
bool use_osl() { return true; }
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
@@ -65,6 +79,7 @@ public:
const char *shader_test_loaded(const string& hash);
const char *shader_load_bytecode(const string& hash, const string& bytecode);
const char *shader_load_filepath(string filepath);
+ OSLShaderInfo *shader_loaded_info(const string& hash);
protected:
void texture_system_init();
@@ -74,7 +89,7 @@ protected:
OSL::TextureSystem *ts;
OSLRenderServices *services;
OSL::ErrorHandler errhandler;
- set<string> loaded_shaders;
+ map<string, OSLShaderInfo> loaded_shaders;
};
#endif
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 8085cfdd3e6..7b82a91cae8 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -29,6 +29,7 @@
#include "mesh.h"
#include "object.h"
#include "particles.h"
+#include "curves.h"
#include "scene.h"
#include "svm.h"
#include "osl.h"
@@ -54,6 +55,7 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
integrator = new Integrator();
image_manager = new ImageManager();
particle_system_manager = new ParticleSystemManager();
+ curve_system_manager = new CurveSystemManager();
/* OSL only works on the CPU */
if(device_info_.type == DEVICE_CPU)
@@ -83,6 +85,12 @@ void Scene::free_memory(bool final)
foreach(ParticleSystem *p, particle_systems)
delete p;
+ shaders.clear();
+ meshes.clear();
+ objects.clear();
+ lights.clear();
+ particle_systems.clear();
+
if(device) {
camera->device_free(device, &dscene);
filter->device_free(device, &dscene);
@@ -96,8 +104,9 @@ void Scene::free_memory(bool final)
light_manager->device_free(device, &dscene);
particle_system_manager->device_free(device, &dscene);
+ curve_system_manager->device_free(device, &dscene);
- if(!params.persistent_images || final)
+ if(!params.persistent_data || final)
image_manager->device_free(device, &dscene);
}
@@ -112,15 +121,9 @@ void Scene::free_memory(bool final)
delete shader_manager;
delete light_manager;
delete particle_system_manager;
+ delete curve_system_manager;
delete image_manager;
}
- else {
- shaders.clear();
- meshes.clear();
- objects.clear();
- lights.clear();
- particle_systems.clear();
- }
}
void Scene::device_update(Device *device_, Progress& progress)
@@ -165,6 +168,11 @@ void Scene::device_update(Device *device_, Progress& progress)
if(progress.get_cancel()) return;
+ progress.set_status("Updating Hair Systems");
+ curve_system_manager->device_update(device, &dscene, this, progress);
+
+ if(progress.get_cancel()) return;
+
progress.set_status("Updating Meshes");
mesh_manager->device_update(device, &dscene, this, progress);
@@ -242,11 +250,13 @@ bool Scene::need_reset()
|| filter->need_update
|| integrator->need_update
|| shader_manager->need_update
- || particle_system_manager->need_update);
+ || particle_system_manager->need_update
+ || curve_system_manager->need_update);
}
void Scene::reset()
{
+ shader_manager->reset(this);
shader_manager->add_default(this);
/* ensure all objects are updated */
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 92ef692b4b9..fc6b538af03 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -25,7 +25,6 @@
#include "kernel_types.h"
-#include "util_attribute.h"
#include "util_param.h"
#include "util_string.h"
#include "util_thread.h"
@@ -50,6 +49,7 @@ class Object;
class ObjectManager;
class ParticleSystemManager;
class ParticleSystem;
+class CurveSystemManager;
class Shader;
class ShaderManager;
class Progress;
@@ -62,6 +62,7 @@ public:
device_vector<float4> bvh_nodes;
device_vector<uint> object_node;
device_vector<float4> tri_woop;
+ device_vector<uint> prim_segment;
device_vector<uint> prim_visibility;
device_vector<uint> prim_index;
device_vector<uint> prim_object;
@@ -72,8 +73,12 @@ public:
device_vector<float4> tri_vindex;
device_vector<float4> tri_verts;
+ device_vector<float4> curves;
+ device_vector<float4> curve_keys;
+
/* objects */
device_vector<float4> objects;
+ device_vector<float4> objects_vector;
/* attributes */
device_vector<uint4> attributes_map;
@@ -120,7 +125,7 @@ public:
bool use_bvh_cache;
bool use_bvh_spatial_split;
bool use_qbvh;
- bool persistent_images;
+ bool persistent_data;
SceneParams()
{
@@ -141,7 +146,7 @@ public:
&& use_bvh_cache == params.use_bvh_cache
&& use_bvh_spatial_split == params.use_bvh_spatial_split
&& use_qbvh == params.use_qbvh
- && persistent_images == params.persistent_images); }
+ && persistent_data == params.persistent_data); }
};
/* Scene */
@@ -169,6 +174,7 @@ public:
MeshManager *mesh_manager;
ObjectManager *object_manager;
ParticleSystemManager *particle_system_manager;
+ CurveSystemManager *curve_system_manager;
/* default shaders */
int default_surface;
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 1d1a3d54893..6ed14452c6b 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -41,7 +41,7 @@ CCL_NAMESPACE_BEGIN
Session::Session(const SessionParams& params_)
: params(params_),
tile_manager(params.progressive, params.samples, params.tile_size, params.start_resolution,
- params.background == false || params.progressive_refine, params.background,
+ params.background == false || params.progressive_refine, params.background, params.tile_order,
max(params.device.multi_devices.size(), 1)),
stats()
{
@@ -132,6 +132,8 @@ bool Session::ready_to_reset()
void Session::reset_gpu(BufferParams& buffer_params, int samples)
{
+ thread_scoped_lock pause_lock(pause_mutex);
+
/* block for buffer acces and reset immediately. we can't do this
* in the thread, because we need to allocate an OpenGL buffer, and
* that only works in the main thread */
@@ -208,7 +210,12 @@ void Session::run_gpu()
* wait for pause condition notify to wake up again */
thread_scoped_lock pause_lock(pause_mutex);
- if(pause || no_tiles) {
+ if(!pause && !tile_manager.done()) {
+ /* reset could have happened after no_tiles was set, before this lock.
+ * in this case we shall not wait for pause condition
+ */
+ }
+ else if(pause || no_tiles) {
update_status_time(pause, no_tiles);
while(1) {
@@ -295,6 +302,7 @@ void Session::run_gpu()
void Session::reset_cpu(BufferParams& buffer_params, int samples)
{
thread_scoped_lock reset_lock(delayed_reset.mutex);
+ thread_scoped_lock pause_lock(pause_mutex);
display_outdated = true;
reset_time = time_dt();
@@ -357,7 +365,7 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
tile_lock.unlock();
- /* in case of a permant buffer, return it, otherwise we will allocate
+ /* in case of a permanent buffer, return it, otherwise we will allocate
* a new temporary buffer */
if(!params.background) {
tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride);
@@ -381,7 +389,7 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
buffer_params.get_offset_stride(rtile.offset, rtile.stride);
- RenderBuffers *tilebuffers = new RenderBuffers(tile_device);
+ RenderBuffers *tilebuffers;
/* allocate buffers */
if(params.progressive_refine) {
@@ -411,6 +419,12 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
rtile.rgba = 0;
rtile.buffers = tilebuffers;
+ /* this will tag tile as IN PROGRESS in blender-side render pipeline,
+ * which is needed to highlight currently rendering tile before first
+ * sample was processed for it
+ */
+ update_tile_sample(rtile);
+
return true;
}
@@ -478,7 +492,16 @@ void Session::run_cpu()
* wait for pause condition notify to wake up again */
thread_scoped_lock pause_lock(pause_mutex);
- if(pause || no_tiles) {
+ if(!pause && delayed_reset.do_reset) {
+ /* reset once to start */
+ thread_scoped_lock reset_lock(delayed_reset.mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex);
+ thread_scoped_lock display_lock(display_mutex);
+
+ reset_(delayed_reset.params, delayed_reset.samples);
+ delayed_reset.do_reset = false;
+ }
+ else if(pause || no_tiles) {
update_status_time(pause, no_tiles);
while(1) {
@@ -546,7 +569,7 @@ void Session::run_cpu()
}
else if(need_tonemap) {
/* tonemap only if we do not reset, we don't we don't
- * wan't to show the result of an incomplete sample*/
+ * want to show the result of an incomplete sample*/
tonemap();
}
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index cfc1502287d..27073d2fd9c 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -51,6 +51,7 @@ public:
bool experimental;
int samples;
int2 tile_size;
+ int tile_order;
int start_resolution;
int threads;
diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h
index d4421002ceb..b38e098e3cb 100644
--- a/intern/cycles/render/shader.h
+++ b/intern/cycles/render/shader.h
@@ -110,6 +110,8 @@ public:
static ShaderManager *create(Scene *scene, int shadingsystem);
virtual ~ShaderManager();
+ virtual void reset(Scene *scene) = 0;
+
virtual bool use_osl() { return false; }
/* device update */
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 4acd174e60f..5cb11a4ec1a 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -40,6 +40,10 @@ SVMShaderManager::~SVMShaderManager()
{
}
+void SVMShaderManager::reset(Scene *scene)
+{
+}
+
void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
if(!need_update)
@@ -478,9 +482,9 @@ void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*>& done)
stack_clear_users(node, done);
stack_clear_temporary(node);
- if(node->name == ustring("emission"))
+ if(node->has_surface_emission())
current_shader->has_surface_emission = true;
- if(node->name == ustring("transparent"))
+ if(node->has_surface_transparent())
current_shader->has_surface_transparent = true;
/* end node is added outside of this */
@@ -538,9 +542,9 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don
mix_weight_offset = SVM_STACK_INVALID;
- if(node->name == ustring("emission"))
+ if(node->has_surface_emission())
current_shader->has_surface_emission = true;
- if(node->name == ustring("transparent"))
+ if(node->has_surface_transparent())
current_shader->has_surface_transparent = true;
}
diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h
index 0b15c5aaa1e..c1ce619e12a 100644
--- a/intern/cycles/render/svm.h
+++ b/intern/cycles/render/svm.h
@@ -45,6 +45,8 @@ public:
SVMShaderManager();
~SVMShaderManager();
+ void reset(Scene *scene);
+
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
void device_free(Device *device, DeviceScene *dscene);
};
diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp
index bbcdb47260e..d62ecd8a88c 100644
--- a/intern/cycles/render/tile.cpp
+++ b/intern/cycles/render/tile.cpp
@@ -24,10 +24,11 @@
CCL_NAMESPACE_BEGIN
TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int start_resolution_,
- bool preserve_tile_device_, bool background_, int num_devices_)
+ bool preserve_tile_device_, bool background_, int tile_order_, int num_devices_)
{
progressive = progressive_;
tile_size = tile_size_;
+ tile_order = tile_order_;
start_resolution = start_resolution_;
num_devices = num_devices_;
preserve_tile_device = preserve_tile_device_;
@@ -165,6 +166,20 @@ void TileManager::set_tiles()
state.buffer.full_height = max(1, params.full_height/resolution);
}
+list<Tile>::iterator TileManager::next_viewport_tile(int device)
+{
+ list<Tile>::iterator iter;
+
+ int logical_device = preserve_tile_device? device: 0;
+
+ for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
+ if(iter->device == logical_device && iter->rendering == false)
+ return iter;
+ }
+
+ return state.tiles.end();
+}
+
list<Tile>::iterator TileManager::next_center_tile(int device)
{
list<Tile>::iterator iter, best = state.tiles.end();
@@ -210,28 +225,53 @@ list<Tile>::iterator TileManager::next_center_tile(int device)
return best;
}
-list<Tile>::iterator TileManager::next_simple_tile(int device)
+list<Tile>::iterator TileManager::next_simple_tile(int device, int tile_order)
{
- list<Tile>::iterator iter;
+ list<Tile>::iterator iter, best = state.tiles.end();
+ int resolution = state.resolution_divider;
int logical_device = preserve_tile_device? device: 0;
+ int64_t cordx = max(1, params.width/resolution);
+ int64_t cordy = max(1, params.height/resolution);
+ int64_t mindist = cordx * cordy;
+
for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
- if(iter->device == logical_device && iter->rendering == false)
- return iter;
+ if(iter->device == logical_device && iter->rendering == false) {
+ Tile &cur_tile = *iter;
+
+ int64_t distx = cordx;
+
+ if (tile_order == TileManager::RIGHT_TO_LEFT)
+ distx = cordx - cur_tile.x;
+ else if (tile_order == TileManager::LEFT_TO_RIGHT)
+ distx = cordx + cur_tile.x;
+ else if (tile_order == TileManager::TOP_TO_BOTTOM)
+ distx = cordx - cur_tile.y;
+ else /* TileManager::BOTTOM_TO_TOP */
+ distx = cordx + cur_tile.y;
+
+ if(distx < mindist) {
+ best = iter;
+ mindist = distx;
+ }
+ }
}
- return state.tiles.end();
+ return best;
}
bool TileManager::next_tile(Tile& tile, int device)
{
list<Tile>::iterator tile_it;
-
- if(background)
- tile_it = next_center_tile(device);
+ if (background) {
+ if(tile_order == TileManager::CENTER)
+ tile_it = next_center_tile(device);
+ else
+ tile_it = next_simple_tile(device, tile_order);
+ }
else
- tile_it = next_simple_tile(device);
+ tile_it = next_viewport_tile(device);
if(tile_it != state.tiles.end()) {
tile_it->rendering = true;
diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h
index 6f7a8f20734..99cffb49c08 100644
--- a/intern/cycles/render/tile.h
+++ b/intern/cycles/render/tile.h
@@ -59,7 +59,7 @@ public:
} state;
TileManager(bool progressive, int num_samples, int2 tile_size, int start_resolution,
- bool preserve_tile_device, bool background, int num_devices = 1);
+ bool preserve_tile_device, bool background, int tile_order, int num_devices = 1);
~TileManager();
void reset(BufferParams& params, int num_samples);
@@ -68,12 +68,23 @@ public:
bool next_tile(Tile& tile, int device = 0);
bool done();
+ void set_tile_order(int tile_order_) { tile_order = tile_order_; }
protected:
+ /* Note: this should match enum_tile_order in properties.py */
+ enum {
+ CENTER = 0,
+ RIGHT_TO_LEFT = 1,
+ LEFT_TO_RIGHT = 2,
+ TOP_TO_BOTTOM = 3,
+ BOTTOM_TO_TOP = 4
+ } TileOrder;
+
void set_tiles();
bool progressive;
int num_samples;
int2 tile_size;
+ int tile_order;
int start_resolution;
int num_devices;
@@ -106,9 +117,12 @@ protected:
* mimics behavior of blender internal's tile order
*/
list<Tile>::iterator next_center_tile(int device);
+
+ /* returns simple tile order */
+ list<Tile>::iterator next_simple_tile(int device, int tile_order);
- /* returns first unhandled tile starting from left bottom corner of the image */
- list<Tile>::iterator next_simple_tile(int device);
+ /* returns first unhandled tile (for viewport) */
+ list<Tile>::iterator next_viewport_tile(int device);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp
index 6920df9954c..48e6808bc38 100644
--- a/intern/cycles/subd/subd_dice.cpp
+++ b/intern/cycles/subd/subd_dice.cpp
@@ -47,7 +47,7 @@ void EdgeDice::reserve(int num_verts, int num_tris)
vert_offset = mesh->verts.size();
tri_offset = mesh->triangles.size();
- mesh->reserve(vert_offset + num_verts, tri_offset + num_tris);
+ mesh->reserve(vert_offset + num_verts, tri_offset + num_tris, 0, 0);
Attribute *attr_vN = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt
index dce417704cc..bcaaa9a71b9 100644
--- a/intern/cycles/util/CMakeLists.txt
+++ b/intern/cycles/util/CMakeLists.txt
@@ -9,7 +9,6 @@ set(INC_SYS
)
set(SRC
- util_attribute.cpp
util_cache.cpp
util_cuda.cpp
util_dynlib.cpp
@@ -33,7 +32,6 @@ endif()
set(SRC_HEADERS
util_algorithm.h
util_args.h
- util_attribute.h
util_boundbox.h
util_cache.h
util_cuda.h
diff --git a/intern/cycles/util/util_attribute.cpp b/intern/cycles/util/util_attribute.cpp
deleted file mode 100644
index 057fb6213e9..00000000000
--- a/intern/cycles/util/util_attribute.cpp
+++ /dev/null
@@ -1,51 +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.
- */
-
-#include "util_attribute.h"
-
-CCL_NAMESPACE_BEGIN
-
-const char *attribute_standard_name(AttributeStandard std)
-{
- if(std == ATTR_STD_VERTEX_NORMAL)
- return "N";
- else if(std == ATTR_STD_FACE_NORMAL)
- return "Ng";
- else if(std == ATTR_STD_UV)
- return "uv";
- else if(std == ATTR_STD_GENERATED)
- return "generated";
- else if(std == ATTR_STD_UV_TANGENT)
- return "tangent";
- else if(std == ATTR_STD_UV_TANGENT_SIGN)
- return "tangent_sign";
- else if(std == ATTR_STD_POSITION_UNDEFORMED)
- return "undeformed";
- else if(std == ATTR_STD_POSITION_UNDISPLACED)
- return "undisplaced";
- else if(std == ATTR_STD_MOTION_PRE)
- return "motion_pre";
- else if(std == ATTR_STD_MOTION_POST)
- return "motion_post";
- else if(std == ATTR_STD_PARTICLE)
- return "particle";
-
- return "";
-}
-
-CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_boundbox.h b/intern/cycles/util/util_boundbox.h
index 6dd1c6c71e8..7564c1f3c5c 100644
--- a/intern/cycles/util/util_boundbox.h
+++ b/intern/cycles/util/util_boundbox.h
@@ -61,8 +61,17 @@ public:
__forceinline void grow(const float3& pt)
{
- min = ccl::min(min, pt);
- max = ccl::max(max, pt);
+ /* the order of arguments to min is such that if pt is nan, it will not
+ * influence the resulting bounding box */
+ min = ccl::min(pt, min);
+ max = ccl::max(pt, max);
+ }
+
+ __forceinline void grow(const float3& pt, float border)
+ {
+ float3 shift = {border, border, border, 0.0f};
+ min = ccl::min(pt - shift, min);
+ max = ccl::max(pt + shift, max);
}
__forceinline void grow(const BoundBox& bbox)
diff --git a/intern/cycles/util/util_cache.h b/intern/cycles/util/util_cache.h
index e8f111a5397..deff05fff16 100644
--- a/intern/cycles/util/util_cache.h
+++ b/intern/cycles/util/util_cache.h
@@ -72,7 +72,7 @@ public:
buffers.push_back(buffer);
}
- void add(void *data, size_t size)
+ void add(const void *data, size_t size)
{
if(size) {
CacheBuffer buffer(data, size);
@@ -80,19 +80,19 @@ public:
}
}
- void add(int& data)
+ void add(const int& data)
{
CacheBuffer buffer(&data, sizeof(int));
buffers.push_back(buffer);
}
- void add(float& data)
+ void add(const float& data)
{
CacheBuffer buffer(&data, sizeof(float));
buffers.push_back(buffer);
}
- void add(size_t& data)
+ void add(const size_t& data)
{
CacheBuffer buffer(&data, sizeof(size_t));
buffers.push_back(buffer);
diff --git a/intern/cycles/util/util_cuda.cpp b/intern/cycles/util/util_cuda.cpp
index 2716f00e173..6c9ee7c548f 100644
--- a/intern/cycles/util/util_cuda.cpp
+++ b/intern/cycles/util/util_cuda.cpp
@@ -376,28 +376,30 @@ bool cuLibraryInit()
/* cuda 4.0 */
CUDA_LIBRARY_FIND(cuCtxSetCurrent);
-#ifndef WITH_CUDA_BINARIES
-#ifdef _WIN32
- return false; /* runtime build doesn't work at the moment */
-#else
- if(cuCompilerPath() == "")
- return false;
-#endif
+ if(cuHavePrecompiledKernels())
+ result = true;
+#ifndef _WIN32
+ else if(cuCompilerPath() != "")
+ result = true;
#endif
- /* success */
- result = true;
-
return result;
}
+bool cuHavePrecompiledKernels()
+{
+ string cubins_path = path_get("lib");
+
+ return path_exists(cubins_path);
+}
+
string cuCompilerPath()
{
#ifdef _WIN32
- const char *defaultpath = "C:/CUDA/bin";
+ const char *defaultpaths[] = {"C:/CUDA/bin", NULL};
const char *executable = "nvcc.exe";
#else
- const char *defaultpath = "/usr/local/cuda/bin";
+ const char *defaultpaths[] = {"/Developer/NVIDIA/CUDA-4.2/bin", "/usr/local/cuda-4.2/bin", "/usr/local/cuda/bin", NULL};
const char *executable = "nvcc";
#endif
@@ -405,13 +407,17 @@ string cuCompilerPath()
string nvcc;
- if(binpath)
+ if(binpath) {
nvcc = path_join(binpath, executable);
- else
- nvcc = path_join(defaultpath, executable);
+ if(path_exists(nvcc))
+ return nvcc;
+ }
- if(path_exists(nvcc))
- return nvcc;
+ for(int i = 0; defaultpaths[i]; i++) {
+ nvcc = path_join(defaultpaths[i], executable);
+ if(path_exists(nvcc))
+ return nvcc;
+ }
#ifndef _WIN32
{
diff --git a/intern/cycles/util/util_cuda.h b/intern/cycles/util/util_cuda.h
index d9d956b7bd9..55feb3f84cb 100644
--- a/intern/cycles/util/util_cuda.h
+++ b/intern/cycles/util/util_cuda.h
@@ -30,6 +30,7 @@ CCL_NAMESPACE_BEGIN
* matrixMulDynlinkJIT in the CUDA SDK. */
bool cuLibraryInit();
+bool cuHavePrecompiledKernels();
string cuCompilerPath();
CCL_NAMESPACE_END
@@ -38,7 +39,7 @@ CCL_NAMESPACE_END
#define CUDA_VERSION 3020
-#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64)
+#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) || defined(__LP64__)
typedef unsigned long long CUdeviceptr;
#else
typedef unsigned int CUdeviceptr;
@@ -205,7 +206,8 @@ typedef enum CUjit_target_enum
CU_TARGET_COMPUTE_13,
CU_TARGET_COMPUTE_20,
CU_TARGET_COMPUTE_21,
- CU_TARGET_COMPUTE_30
+ CU_TARGET_COMPUTE_30,
+ CU_TARGET_COMPUTE_35
} CUjit_target;
typedef enum CUjit_fallback_enum
diff --git a/intern/cycles/util/util_dynlib.cpp b/intern/cycles/util/util_dynlib.cpp
index 5836073a07a..3eaa16ab37d 100644
--- a/intern/cycles/util/util_dynlib.cpp
+++ b/intern/cycles/util/util_dynlib.cpp
@@ -22,7 +22,7 @@
#ifdef _WIN32
-#include <Windows.h>
+#include <windows.h>
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index 70adee4385b..c37fa1a4dc6 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -1092,6 +1092,199 @@ __device_inline float3 rotate_around_axis(float3 p, float3 axis, float angle)
return r;
}
+/* NaN-safe math ops */
+
+__device float safe_asinf(float a)
+{
+ if(a <= -1.0f)
+ return -M_PI_2_F;
+ else if(a >= 1.0f)
+ return M_PI_2_F;
+
+ return asinf(a);
+}
+
+__device float safe_acosf(float a)
+{
+ if(a <= -1.0f)
+ return M_PI_F;
+ else if(a >= 1.0f)
+ return 0.0f;
+
+ return acosf(a);
+}
+
+__device float compatible_powf(float x, float y)
+{
+ /* GPU pow doesn't accept negative x, do manual checks here */
+ if(x < 0.0f) {
+ if(fmod(-y, 2.0f) == 0.0f)
+ return powf(-x, y);
+ else
+ return -powf(-x, y);
+ }
+ else if(x == 0.0f)
+ return 0.0f;
+
+ return powf(x, y);
+}
+
+__device float safe_powf(float a, float b)
+{
+ if(b == 0.0f)
+ return 1.0f;
+ if(a == 0.0f)
+ return 0.0f;
+ if(a < 0.0f && b != (int)b)
+ return 0.0f;
+
+ return compatible_powf(a, b);
+}
+
+__device float safe_logf(float a, float b)
+{
+ if(a < 0.0f || b < 0.0f)
+ return 0.0f;
+
+ return logf(a)/logf(b);
+}
+
+__device float safe_divide(float a, float b)
+{
+ float result;
+
+ if(b == 0.0f)
+ result = 0.0f;
+ else
+ result = a/b;
+
+ return result;
+}
+
+/* Ray Intersection */
+
+__device bool ray_sphere_intersect(
+ float3 ray_P, float3 ray_D, float ray_t,
+ float3 sphere_P, float sphere_radius,
+ float3 *isect_P, float *isect_t)
+{
+ float3 d = sphere_P - ray_P;
+ float radiussq = sphere_radius*sphere_radius;
+ float tsq = dot(d, d);
+
+ if(tsq > radiussq) { /* ray origin outside sphere */
+ float tp = dot(d, ray_D);
+
+ if(tp < 0.0f) /* dir points away from sphere */
+ return false;
+
+ float dsq = tsq - tp*tp; /* pythagoras */
+
+ if(dsq > radiussq) /* closest point on ray outside sphere */
+ return false;
+
+ float t = tp - sqrtf(radiussq - dsq); /* pythagoras */
+
+ if(t < ray_t) {
+ *isect_t = t;
+ *isect_P = ray_P + ray_D*t;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+__device bool ray_aligned_disk_intersect(
+ float3 ray_P, float3 ray_D, float ray_t,
+ float3 disk_P, float disk_radius,
+ float3 *isect_P, float *isect_t)
+{
+ /* aligned disk normal */
+ float disk_t;
+ float3 disk_N = normalize_len(ray_P - disk_P, &disk_t);
+ float div = dot(ray_D, disk_N);
+
+ if(div == 0.0f)
+ return false;
+
+ /* compute t to intersection point */
+ float t = -disk_t/div;
+ if(t < 0.0f || t > ray_t)
+ return false;
+
+ /* test if within radius */
+ float3 P = ray_P + ray_D*t;
+ if(len_squared(P - disk_P) > disk_radius*disk_radius)
+ return false;
+
+ *isect_P = P;
+ *isect_t = t;
+
+ return true;
+}
+
+__device bool ray_triangle_intersect(
+ float3 ray_P, float3 ray_D, float ray_t,
+ float3 v0, float3 v1, float3 v2,
+ float3 *isect_P, float *isect_t)
+{
+ /* Calculate intersection */
+ float3 e1 = v1 - v0;
+ float3 e2 = v2 - v0;
+ float3 s1 = cross(ray_D, e2);
+
+ const float divisor = dot(s1, e1);
+ if(divisor == 0.0f)
+ return false;
+
+ const float invdivisor = 1.0f/divisor;
+
+ /* compute first barycentric coordinate */
+ const float3 d = ray_P - v0;
+ const float u = dot(d, s1)*invdivisor;
+ if(u < 0.0f)
+ return false;
+
+ /* Compute second barycentric coordinate */
+ const float3 s2 = cross(d, e1);
+ const float v = dot(ray_D, s2)*invdivisor;
+ if(v < 0.0f)
+ return false;
+
+ const float b0 = 1.0f - u - v;
+ if(b0 < 0.0f)
+ return false;
+
+ /* compute t to intersection point */
+ const float t = dot(e2, s2)*invdivisor;
+ if(t < 0.0f || t > ray_t)
+ return false;
+
+ *isect_t = t;
+ *isect_P = ray_P + ray_D*t;
+
+ return true;
+}
+
+__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;
+ float3 v2 = quad_P + quad_u*0.5f + quad_v*0.5f;
+ float3 v3 = quad_P - quad_u*0.5f + quad_v*0.5f;
+
+ if(ray_triangle_intersect(ray_P, ray_D, ray_t, v0, v1, v2, isect_P, isect_t))
+ return true;
+ else if(ray_triangle_intersect(ray_P, ray_D, ray_t, v0, v2, v3, isect_P, isect_t))
+ return true;
+
+ return false;
+}
+
CCL_NAMESPACE_END
#endif /* __UTIL_MATH_H__ */
diff --git a/intern/cycles/util/util_system.cpp b/intern/cycles/util/util_system.cpp
index 2d9f0fffae6..4fda090e09e 100644
--- a/intern/cycles/util/util_system.cpp
+++ b/intern/cycles/util/util_system.cpp
@@ -136,7 +136,7 @@ struct CPUCapabilities {
bool fma4;
};
-bool system_cpu_support_optimized()
+static CPUCapabilities& system_cpu_capabilities()
{
static CPUCapabilities caps;
static bool caps_init = false;
@@ -182,7 +182,18 @@ bool system_cpu_support_optimized()
caps_init = true;
}
- /* optimization flags use these */
+ return caps;
+}
+
+bool system_cpu_support_sse2()
+{
+ CPUCapabilities& caps = system_cpu_capabilities();
+ return caps.sse && caps.sse2;
+}
+
+bool system_cpu_support_sse3()
+{
+ CPUCapabilities& caps = system_cpu_capabilities();
return caps.sse && caps.sse2 && caps.sse3;
}
diff --git a/intern/cycles/util/util_system.h b/intern/cycles/util/util_system.h
index f25e009a250..257112883d1 100644
--- a/intern/cycles/util/util_system.h
+++ b/intern/cycles/util/util_system.h
@@ -26,7 +26,8 @@ CCL_NAMESPACE_BEGIN
int system_cpu_thread_count();
string system_cpu_brand_string();
int system_cpu_bits();
-bool system_cpu_support_optimized();
+bool system_cpu_support_sse2();
+bool system_cpu_support_sse3();
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp
index 8c4ec312256..43f15ba0ce6 100644
--- a/intern/cycles/util/util_task.cpp
+++ b/intern/cycles/util/util_task.cpp
@@ -152,7 +152,6 @@ void TaskPool::num_increase()
thread_mutex TaskScheduler::mutex;
int TaskScheduler::users = 0;
vector<thread*> TaskScheduler::threads;
-vector<int> TaskScheduler::thread_level;
volatile bool TaskScheduler::do_exit = false;
list<TaskScheduler::Entry> TaskScheduler::queue;
@@ -179,12 +178,9 @@ void TaskScheduler::init(int num_threads)
/* launch threads that will be waiting for work */
threads.resize(num_threads);
- thread_level.resize(num_threads);
- for(size_t i = 0; i < threads.size(); i++) {
+ for(size_t i = 0; i < threads.size(); i++)
threads[i] = new thread(function_bind(&TaskScheduler::thread_run, i));
- thread_level[i] = 0;
- }
}
users++;
@@ -208,7 +204,6 @@ void TaskScheduler::exit()
}
threads.clear();
- thread_level.clear();
}
}
diff --git a/intern/cycles/util/util_task.h b/intern/cycles/util/util_task.h
index b795ca7524b..5bca3f255af 100644
--- a/intern/cycles/util/util_task.h
+++ b/intern/cycles/util/util_task.h
@@ -111,7 +111,6 @@ protected:
static thread_mutex mutex;
static int users;
static vector<thread*> threads;
- static vector<int> thread_level;
static volatile bool do_exit;
static list<Entry> queue;
diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h
index a1c12ddf0e1..1f19f85f894 100644
--- a/intern/cycles/util/util_transform.h
+++ b/intern/cycles/util/util_transform.h
@@ -45,7 +45,7 @@ typedef struct Transform {
*
* For the DecompMotionTransform we drop scale from pre/post. */
-typedef struct MotionTransform {
+typedef struct __may_alias MotionTransform {
Transform pre;
Transform mid;
Transform post;
diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h
index 3d246104ddc..bb6de1197e7 100644
--- a/intern/cycles/util/util_types.h
+++ b/intern/cycles/util/util_types.h
@@ -39,12 +39,14 @@
#if defined(_WIN32) && !defined(FREE_WINDOWS)
#define __device_inline static __forceinline
#define __align(...) __declspec(align(__VA_ARGS__))
+#define __may_alias
#else
#define __device_inline static inline __attribute__((always_inline))
#ifndef FREE_WINDOWS64
#define __forceinline inline __attribute__((always_inline))
#endif
#define __align(...) __attribute__((aligned(__VA_ARGS__)))
+#define __may_alias __attribute__((__may_alias__))
#endif
#endif
@@ -446,24 +448,6 @@ __device_inline int4 make_int4(const float3& f)
#endif
-typedef enum AttributeStandard {
- ATTR_STD_NONE = 0,
- ATTR_STD_VERTEX_NORMAL,
- ATTR_STD_FACE_NORMAL,
- ATTR_STD_UV,
- ATTR_STD_UV_TANGENT,
- ATTR_STD_UV_TANGENT_SIGN,
- ATTR_STD_GENERATED,
- ATTR_STD_POSITION_UNDEFORMED,
- ATTR_STD_POSITION_UNDISPLACED,
- ATTR_STD_MOTION_PRE,
- ATTR_STD_MOTION_POST,
- ATTR_STD_PARTICLE,
- ATTR_STD_NUM,
-
- ATTR_STD_NOT_FOUND = ~0
-} AttributeStandard;
-
CCL_NAMESPACE_END
#endif /* __UTIL_TYPES_H__ */
diff --git a/intern/dualcon/SConscript b/intern/dualcon/SConscript
index 481e9ae7f5c..34df21a74c3 100644
--- a/intern/dualcon/SConscript
+++ b/intern/dualcon/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('intern/*.cpp')
diff --git a/intern/dualcon/intern/MemoryAllocator.h b/intern/dualcon/intern/MemoryAllocator.h
index b704542d27b..e673d9498d2 100644
--- a/intern/dualcon/intern/MemoryAllocator.h
+++ b/intern/dualcon/intern/MemoryAllocator.h
@@ -43,6 +43,8 @@
class VirtualMemoryAllocator
{
public:
+virtual ~VirtualMemoryAllocator() {}
+
virtual void *allocate( ) = 0;
virtual void deallocate(void *obj) = 0;
virtual void destroy( ) = 0;
diff --git a/intern/elbeem/SConscript b/intern/elbeem/SConscript
index 9c035c0c285..133f02e41bc 100644
--- a/intern/elbeem/SConscript
+++ b/intern/elbeem/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
import sys
import os
Import('env')
diff --git a/intern/elbeem/intern/ntl_geometrymodel.cpp b/intern/elbeem/intern/ntl_geometrymodel.cpp
index 13220736b8e..62e4441bad7 100644
--- a/intern/elbeem/intern/ntl_geometrymodel.cpp
+++ b/intern/elbeem/intern/ntl_geometrymodel.cpp
@@ -215,7 +215,6 @@ void ntlGeometryObjModel::calcTriangleDivs(vector<ntlVec3Gfx> &verts, vector<ntl
errMsg("ntlGeometryObjModel","calcTriangleDivs special!");
mTriangleDivs1.resize( tris.size() );
mTriangleDivs2.resize( tris.size() );
- mTriangleDivs3.resize( tris.size() );
for(size_t i=0; i<tris.size(); i++) {
ntlVec3Gfx p0 = verts[ tris[i].getPoints()[0] ];
ntlVec3Gfx p1 = verts[ tris[i].getPoints()[1] ];
@@ -223,10 +222,9 @@ void ntlGeometryObjModel::calcTriangleDivs(vector<ntlVec3Gfx> &verts, vector<ntl
ntlVec3Gfx side1 = p1 - p0;
ntlVec3Gfx side2 = p2 - p0;
ntlVec3Gfx side3 = p1 - p2;
- int divs1=0, divs2=0, divs3=0;
+ int divs1=0, divs2=0;
if(normNoSqrt(side1) > fsTri*fsTri) { divs1 = (int)(norm(side1)/fsTri); }
if(normNoSqrt(side2) > fsTri*fsTri) { divs2 = (int)(norm(side2)/fsTri); }
- //if(normNoSqrt(side3) > fsTri*fsTri) { divs3 = (int)(norm(side3)/fsTri); }
// special handling
// warning, requires objmodel triangle treatment (no verts dups)
@@ -237,17 +235,15 @@ void ntlGeometryObjModel::calcTriangleDivs(vector<ntlVec3Gfx> &verts, vector<ntl
p1 = sverts[s].mVerts[ tris[i].getPoints()[1] ];
p2 = sverts[s].mVerts[ tris[i].getPoints()[2] ];
side1 = p1 - p0; side2 = p2 - p0; side3 = p1 - p2;
- int tdivs1=0, tdivs2=0, tdivs3=0;
+ int tdivs1=0, tdivs2=0;
if(normNoSqrt(side1) > fsTri*fsTri) { tdivs1 = (int)(norm(side1)/fsTri); }
if(normNoSqrt(side2) > fsTri*fsTri) { tdivs2 = (int)(norm(side2)/fsTri); }
if(tdivs1>divs1) divs1=tdivs1;
if(tdivs2>divs2) divs2=tdivs2;
- if(tdivs3>divs3) divs3=tdivs3;
}
} // */
mTriangleDivs1[i] = divs1;
mTriangleDivs2[i] = divs2;
- mTriangleDivs3[i] = divs3;
}
}
diff --git a/intern/elbeem/intern/ntl_geometryobject.cpp b/intern/elbeem/intern/ntl_geometryobject.cpp
index 1e08cb96a95..9b17b1854f2 100644
--- a/intern/elbeem/intern/ntl_geometryobject.cpp
+++ b/intern/elbeem/intern/ntl_geometryobject.cpp
@@ -42,7 +42,7 @@ ntlGeometryObject::ntlGeometryObject() :
mMovPoints(), mMovNormals(),
mHaveCachedMov(false),
mCachedMovPoints(), mCachedMovNormals(),
- mTriangleDivs1(), mTriangleDivs2(), mTriangleDivs3(),
+ mTriangleDivs1(), mTriangleDivs2(),
mMovPntsInited(-100.0), mMaxMovPnt(-1),
mcGeoActive(1.),
mCpsTimeStart(0.), mCpsTimeEnd(1.0), mCpsQuality(10.),
@@ -434,7 +434,6 @@ void ntlGeometryObject::applyTransformation(double t, vector<ntlVec3Gfx> *verts,
void ntlGeometryObject::calcTriangleDivs(vector<ntlVec3Gfx> &verts, vector<ntlTriangle> &tris, gfxReal fsTri) {
mTriangleDivs1.resize( tris.size() );
mTriangleDivs2.resize( tris.size() );
- mTriangleDivs3.resize( tris.size() );
//fsTri *= 2.; // DEBUG! , wrong init!
@@ -444,14 +443,12 @@ void ntlGeometryObject::calcTriangleDivs(vector<ntlVec3Gfx> &verts, vector<ntlTr
const ntlVec3Gfx p2 = verts[ tris[i].getPoints()[2] ];
const ntlVec3Gfx side1 = p1 - p0;
const ntlVec3Gfx side2 = p2 - p0;
- const ntlVec3Gfx side3 = p1 - p2;
- int divs1=0, divs2=0, divs3=0;
+ int divs1=0, divs2=0;
if(normNoSqrt(side1) > fsTri*fsTri) { divs1 = (int)(norm(side1)/fsTri); }
if(normNoSqrt(side2) > fsTri*fsTri) { divs2 = (int)(norm(side2)/fsTri); }
mTriangleDivs1[i] = divs1;
mTriangleDivs2[i] = divs2;
- mTriangleDivs3[i] = divs3;
}
}
diff --git a/intern/elbeem/intern/ntl_geometryobject.h b/intern/elbeem/intern/ntl_geometryobject.h
index fca539b8402..677f132f4c3 100644
--- a/intern/elbeem/intern/ntl_geometryobject.h
+++ b/intern/elbeem/intern/ntl_geometryobject.h
@@ -223,7 +223,7 @@ class ntlGeometryObject : public ntlGeometryClass
vector<ntlVec3Gfx> mCachedMovPoints;
vector<ntlVec3Gfx> mCachedMovNormals;
/*! precomputed triangle divisions */
- vector<int> mTriangleDivs1,mTriangleDivs2,mTriangleDivs3;
+ vector<int> mTriangleDivs1,mTriangleDivs2;
/*! inited? */
float mMovPntsInited;
/*! point with max. distance from center */
diff --git a/intern/elbeem/intern/ntl_ray.cpp b/intern/elbeem/intern/ntl_ray.cpp
index 7f5aedc53c6..1083fcdb68b 100644
--- a/intern/elbeem/intern/ntl_ray.cpp
+++ b/intern/elbeem/intern/ntl_ray.cpp
@@ -677,7 +677,6 @@ const ntlColor ntlRay::shade() //const
ntlScene::ntlScene( ntlRenderGlobals *glob, bool del ) :
mpGlob( glob ), mSceneDel(del),
mpTree( NULL ),
- mDisplayListId( -1 ),
mSceneBuilt( false ), mFirstInitDone( false )
{
}
diff --git a/intern/elbeem/intern/ntl_ray.h b/intern/elbeem/intern/ntl_ray.h
index 71fcd5f71c2..5f6d34e3020 100644
--- a/intern/elbeem/intern/ntl_ray.h
+++ b/intern/elbeem/intern/ntl_ray.h
@@ -404,9 +404,6 @@ private:
/*! Tree to store quickly intersect triangles */
ntlTree *mpTree;
- /*! id of dislpay list for raytracer stuff */
- int mDisplayListId;
-
/*! was the scene successfully built? only then getObject(i) requests are valid */
bool mSceneBuilt;
diff --git a/intern/elbeem/intern/solver_main.cpp b/intern/elbeem/intern/solver_main.cpp
index b9436e84922..99278657fd9 100644
--- a/intern/elbeem/intern/solver_main.cpp
+++ b/intern/elbeem/intern/solver_main.cpp
@@ -1170,7 +1170,6 @@ LbmFsgrSolver::standingFluidPreinit()
LbmFloat lcsmqo;
# if OPT3D==1
LbmFloat lcsmqadd, lcsmeq[LBM_DFNUM], lcsmomega;
- CellFlagType nbored=0;
# endif // OPT3D==true
GRID_LOOP_START();
diff --git a/intern/elbeem/intern/solver_util.cpp b/intern/elbeem/intern/solver_util.cpp
index 935a910e7d5..6eca427c787 100644
--- a/intern/elbeem/intern/solver_util.cpp
+++ b/intern/elbeem/intern/solver_util.cpp
@@ -731,15 +731,15 @@ void LbmFsgrSolver::advanceParticles() {
if(mPartUsePhysModel) {
LbmFloat radius = p->getSize() * minDropSize;
- LbmVec velPart = vec2L(p->getVel()) *cellsize/timestep; // L2RW, lattice velocity
- LbmVec velWater = LbmVec(vx,vy,vz) *cellsize/timestep;// L2RW, fluid velocity
- LbmVec velRel = velWater - velPart;
+ //LbmVec velPart = vec2L(p->getVel()) *cellsize/timestep; // L2RW, lattice velocity
+ //LbmVec velWater = LbmVec(vx,vy,vz) *cellsize/timestep;// L2RW, fluid velocity
+ //LbmVec velRel = velWater - velPart;
//LbmFloat velRelNorm = norm(velRel);
- LbmFloat pvolume = rhoAir * 4.0/3.0 * M_PI* radius*radius*radius; // volume: 4/3 pi r^3
+ //LbmFloat pvolume = rhoAir * 4.0/3.0 * M_PI* radius*radius*radius; // volume: 4/3 pi r^3
- LbmVec fb = -rwgrav* pvolume *rhoWater;
- LbmVec fd = velRel*6.0*M_PI*radius* (1e-3); //viscWater;
- LbmVec change = (fb+fd) *10.0*timestep *(timestep/cellsize);
+ //LbmVec fb = -rwgrav* pvolume *rhoWater;
+ //LbmVec fd = velRel*6.0*M_PI*radius* (1e-3); //viscWater;
+ //LbmVec change = (fb+fd) *10.0*timestep *(timestep/cellsize);
/*if(debugOutCounter<0) {
errMsg("PIT","BTEST1 vol="<<pvolume<<" radius="<<radius<<" vn="<<velRelNorm<<" velPart="<<velPart<<" velRel"<<velRel);
errMsg("PIT","BTEST2 cellsize="<<cellsize<<" timestep="<<timestep<<" viscW="<<viscWater<<" ss/mb="<<(timestep/(pvolume*rhoAir)));
diff --git a/intern/ffmpeg/ffmpeg_compat.h b/intern/ffmpeg/ffmpeg_compat.h
index 37cde2c2837..8663c96a22e 100644
--- a/intern/ffmpeg/ffmpeg_compat.h
+++ b/intern/ffmpeg/ffmpeg_compat.h
@@ -33,6 +33,7 @@
#include <libavcodec/avcodec.h>
#include <libavutil/rational.h>
#include <libavutil/opt.h>
+#include <libavutil/mathematics.h>
#if (LIBAVFORMAT_VERSION_MAJOR > 52) || ((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 101))
#define FFMPEG_HAVE_PARSE_UTILS 1
@@ -73,12 +74,71 @@
#if ((LIBAVUTIL_VERSION_MAJOR > 51) || (LIBAVUTIL_VERSION_MAJOR == 51) && (LIBAVUTIL_VERSION_MINOR >= 32))
#define FFMPEG_FFV1_ALPHA_SUPPORTED
+#define FFMPEG_SAMPLE_FMT_S16P_SUPPORTED
+#endif
+
+#if ((LIBAVUTIL_VERSION_MAJOR < 51) || (LIBAVUTIL_VERSION_MAJOR == 51) && (LIBAVUTIL_VERSION_MINOR < 22))
+static inline
+int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
+{
+ const AVOption *rv = NULL;
+ av_set_string3(obj, name, val, 1, &rv);
+ return rv != NULL;
+}
+
+static inline
+int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
+{
+ const AVOption *rv = NULL;
+ rv = av_set_int(obj, name, val);
+ return rv != NULL;
+}
+
+static inline
+int av_opt_set_double(void *obj, const char *name, double val, int search_flags)
+{
+ const AVOption *rv = NULL;
+ rv = av_set_double(obj, name, val);
+ return rv != NULL;
+}
+
+#define AV_OPT_TYPE_INT FF_OPT_TYPE_INT
+#define AV_OPT_TYPE_INT64 FF_OPT_TYPE_INT64
+#define AV_OPT_TYPE_STRING FF_OPT_TYPE_STRING
+#define AV_OPT_TYPE_CONST FF_OPT_TYPE_CONST
+#define AV_OPT_TYPE_DOUBLE FF_OPT_TYPE_DOUBLE
+#define AV_OPT_TYPE_FLOAT FF_OPT_TYPE_FLOAT
#endif
#if ((LIBAVFORMAT_VERSION_MAJOR < 53) || ((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR < 24)) || ((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR < 24) && (LIBAVFORMAT_VERSION_MICRO < 2)))
#define avformat_close_input(x) av_close_input_file(*(x))
#endif
+#if ((LIBAVCODEC_VERSION_MAJOR < 53) || (LIBAVCODEC_VERSION_MAJOR == 53 && LIBAVCODEC_VERSION_MINOR < 35))
+static inline
+int avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options)
+{
+ /* TODO: no options are taking into account */
+ return avcodec_open(avctx, codec);
+}
+#endif
+
+#if ((LIBAVFORMAT_VERSION_MAJOR < 53) || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR < 21))
+static inline
+AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c)
+{
+ /* TODO: no codec is taking into account */
+ return av_new_stream(s, 0);
+}
+
+static inline
+int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
+{
+ /* TODO: no options are taking into account */
+ return av_find_stream_info(ic);
+}
+#endif
+
#if ((LIBAVFORMAT_VERSION_MAJOR > 53) || ((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR > 32)) || ((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR == 24) && (LIBAVFORMAT_VERSION_MICRO >= 100)))
static inline
void my_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index ea09987c564..12dd4c0d3eb 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -271,6 +271,9 @@ elseif(UNIX)
if(WITH_X11_XINPUT)
add_definitions(-DWITH_X11_XINPUT)
+ list(APPEND INC_SYS
+ ${X11_Xinput_INCLUDE_PATH}
+ )
endif()
elseif(WIN32)
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index f886dfd9d7d..a92d0d33b65 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -149,6 +149,20 @@ extern void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle,
GHOST_TUns32 *height);
/**
+ * Returns the dimensions of all displays combine
+ * (the current workspace).
+ * No need to worrky about overlapping monitors.
+ * \param systemhandle The handle to the system
+ * \param width A pointer the width gets put in
+ * \param height A pointer the height gets put in
+ * \return void.
+ */
+extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
+ GHOST_TUns32 *width,
+ GHOST_TUns32 *height);
+
+
+/**
* Create a new window.
* The new window is added to the list of windows managed.
* Never explicitly delete the window, use disposeWindow() instead.
@@ -852,6 +866,16 @@ extern int GHOST_toggleConsole(int action);
*/
extern int GHOST_confirmQuit(GHOST_WindowHandle windowhandle);
+/**
+ * Use native pixel size (MacBook pro 'retina'), if supported.
+ */
+extern int GHOST_UseNativePixels(void);
+
+/**
+ * If window was opened using native pixel size, it returns scaling factor.
+ */
+extern float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle);
+
#ifdef __cplusplus
}
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
index ad5d2379787..137926b033c 100644
--- a/intern/ghost/GHOST_ISystem.h
+++ b/intern/ghost/GHOST_ISystem.h
@@ -201,7 +201,7 @@ public:
virtual GHOST_ITimerTask *installTimer(GHOST_TUns64 delay,
GHOST_TUns64 interval,
GHOST_TimerProcPtr timerProc,
- GHOST_TUserDataPtr userData = 0) = 0;
+ GHOST_TUserDataPtr userData = NULL) = 0;
/**
* Removes a timer.
@@ -227,6 +227,12 @@ public:
virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const = 0;
/**
+ * Returns the combine dimensions of all monitors.
+ * \return The dimension of the workspace.
+ */
+ virtual void getAllDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const = 0;
+
+ /**
* Create a new window.
* The new window is added to the list of windows managed.
* Never explicitly delete the window, use disposeWindow() instead.
@@ -243,12 +249,13 @@ public:
* \return The new window (or 0 if creation failed).
*/
virtual 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 GHOST_TUns16 numOfAASamples = 0,
- const GHOST_TEmbedderWindowID parentWindow = 0) = 0;
+ 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,
+ const GHOST_TEmbedderWindowID parentWindow = 0) = 0;
/**
* Dispose a window.
@@ -271,8 +278,9 @@ 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,
- const bool stereoVisual, const GHOST_TUns16 numOfAASamples = 0) = 0;
+ virtual GHOST_TSuccess beginFullScreen(
+ const GHOST_DisplaySetting& setting, GHOST_IWindow **window,
+ const bool stereoVisual, const GHOST_TUns16 numOfAASamples = 0) = 0;
/**
* Updates the resolution while in fullscreen mode.
@@ -281,7 +289,8 @@ public:
*
* \return Indication of success.
*/
- virtual GHOST_TSuccess updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window) = 0;
+ virtual GHOST_TSuccess updateFullScreen(
+ const GHOST_DisplaySetting& setting, GHOST_IWindow **window) = 0;
/**
* Ends full screen mode.
@@ -294,6 +303,11 @@ public:
* \return The current status.
*/
virtual bool getFullScreen(void) = 0;
+
+ /**
+ * Native pixel size support (MacBook 'retina').
+ */
+ virtual bool useNativePixel(void) = 0;
/***************************************************************************************
* Event management functionality
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
index 88f130aabe8..a2d3e9b91fb 100644
--- a/intern/ghost/GHOST_IWindow.h
+++ b/intern/ghost/GHOST_IWindow.h
@@ -305,6 +305,13 @@ public:
*/
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;
+ virtual GHOST_TSuccess endFullScreen() const = 0;
+
+ virtual float getNativePixelSize(void) = 0;
+
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IWindow")
#endif
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 868d787b5f9..35dff73f4af 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -183,6 +183,7 @@ typedef enum {
GHOST_kEventDraggingDropDone,
GHOST_kEventOpenMainFile, // Needed for Cocoa to open double-clicked .blend file at startup
+ GHOST_kEventNativeResolutionChange, // Needed for Cocoa when window moves to other display
GHOST_kEventTimer,
diff --git a/intern/ghost/SConscript b/intern/ghost/SConscript
index 44882a64286..7e142c4aeab 100644
--- a/intern/ghost/SConscript
+++ b/intern/ghost/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
import sys
import os
@@ -93,7 +119,7 @@ else:
if env['WITH_BF_3DMOUSE']:
defs.append('WITH_INPUT_NDOF')
- if env['OURPLATFORM']=='linux':
+ if env['OURPLATFORM'] in ('linux','darwin'):
incs += ' ' + env['BF_3DMOUSE_INC']
else:
sources.remove('intern' + os.sep + 'GHOST_NDOFManager.cpp')
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index 88d02c46f61..b73ff26c259 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -123,7 +123,14 @@ void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle,
system->getMainDisplayDimensions(*width, *height);
}
+void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
+ GHOST_TUns32 *width,
+ GHOST_TUns32 *height)
+{
+ GHOST_ISystem *system = (GHOST_ISystem *) systemhandle;
+ system->getAllDisplayDimensions(*width, *height);
+}
GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
const char *title,
@@ -145,7 +152,8 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
bstereoVisual = false;
return (GHOST_WindowHandle) system->createWindow(title, left, top, width, height,
- state, type, bstereoVisual, numOfAASamples);
+ state, type, bstereoVisual, false,
+ numOfAASamples);
}
GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandle)
@@ -878,3 +886,18 @@ int GHOST_confirmQuit(GHOST_WindowHandle windowhandle)
GHOST_ISystem *system = GHOST_ISystem::getSystem();
return system->confirmQuit((GHOST_IWindow *) windowhandle);
}
+
+int GHOST_UseNativePixels(void)
+{
+ GHOST_ISystem *system = GHOST_ISystem::getSystem();
+ return system->useNativePixel();
+}
+
+float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
+ if (window)
+ return window->getNativePixelSize();
+ return 1.0f;
+}
+
diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h
index f0db1b3de8d..9292235a9c7 100644
--- a/intern/ghost/intern/GHOST_Debug.h
+++ b/intern/ghost/intern/GHOST_Debug.h
@@ -58,12 +58,23 @@
# define GHOST_PRINTF(x, ...)
#endif // GHOST_DEBUG
-
-#ifdef GHOST_DEBUG
+#ifdef WITH_ASSERT_ABORT
+# include <stdio.h> //for fprintf()
+# include <stdlib.h> //for abort()
+# define GHOST_ASSERT(x, info) \
+ { \
+ if (!(x)) { \
+ fprintf(stderr, "GHOST_ASSERT failed: "); \
+ fprintf(stderr, info); \
+ fprintf(stderr, "\n"); \
+ abort(); \
+ } \
+ } (void)0
+#elif defined(GHOST_DEBUG)
# define GHOST_ASSERT(x, info) \
{ \
if (!(x)) { \
- GHOST_PRINT("assertion failed: "); \
+ GHOST_PRINT("GHOST_ASSERT failed: "); \
GHOST_PRINT(info); \
GHOST_PRINT("\n"); \
} \
diff --git a/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp b/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp
index 3f7d2102dac..25e9123dae6 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp
+++ b/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp
@@ -150,7 +150,7 @@ GHOST_TSuccess GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(GHOST_TUns8
#endif // GHOST_DEBUG
CGDisplayErr err = ::CGDisplaySwitchToMode(m_displayIDs[display], displayModeValues);
-
+
return err == CGDisplayNoErr ? GHOST_kSuccess : GHOST_kFailure;
}
@@ -158,19 +158,18 @@ GHOST_TSuccess GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(GHOST_TUns8
long GHOST_DisplayManagerCarbon::getValue(CFDictionaryRef values, CFStringRef key) const
{
CFNumberRef numberValue = (CFNumberRef) CFDictionaryGetValue(values, key);
-
+
if (!numberValue)
{
return -1;
}
-
+
long intValue;
-
+
if (!CFNumberGetValue(numberValue, kCFNumberLongType, &intValue))
{
return -1;
}
-
+
return intValue;
}
-
diff --git a/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp b/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp
index 86f0380c8d6..0d077ebc204 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp
+++ b/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp
@@ -39,7 +39,7 @@ GHOST_DisplayManagerSDL::GHOST_DisplayManagerSDL(GHOST_SystemSDL *system)
GHOST_DisplayManager(),
m_system(system)
{
- memset(&m_mode, 0, sizeof m_mode);
+ memset(&m_mode, 0, sizeof(m_mode));
}
GHOST_TSuccess
diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
index 83df9971158..0bfc67a9126 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
+++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
@@ -52,11 +52,15 @@ GHOST_DisplayManagerWin32::GHOST_DisplayManagerWin32(void)
GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplays(GHOST_TUns8& numDisplays) const
{
- // We do not support multiple monitors at the moment
numDisplays = ::GetSystemMetrics(SM_CMONITORS);
return numDisplays > 0 ? GHOST_kSuccess : GHOST_kFailure;
}
+static BOOL get_dd(DWORD d, DISPLAY_DEVICE* dd)
+{
+ dd->cb = sizeof(DISPLAY_DEVICE);
+ return ::EnumDisplayDevices(NULL, d, dd, 0);
+}
/*
* When you call EnumDisplaySettings with iModeNum set to zero, the operating system
@@ -67,10 +71,12 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplays(GHOST_TUns8& numDisplay
*/
GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const
{
- GHOST_ASSERT((display == kMainDisplay), "GHOST_DisplayManagerWin32::getNumDisplaySettings(): only main displlay is supported");
+ DISPLAY_DEVICE display_device;
+ if (!get_dd(display, &display_device)) return GHOST_kFailure;
+
numSettings = 0;
DEVMODE dm;
- while (::EnumDisplaySettings(NULL, numSettings, &dm)) {
+ while (::EnumDisplaySettings(display_device.DeviceName, numSettings, &dm)) {
numSettings++;
}
return GHOST_kSuccess;
@@ -79,10 +85,12 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplaySettings(GHOST_TUns8 disp
GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const
{
- GHOST_ASSERT((display == kMainDisplay), "GHOST_DisplayManagerWin32::getDisplaySetting(): only main display is supported");
+ DISPLAY_DEVICE display_device;
+ if (!get_dd(display, &display_device)) return GHOST_kFailure;
+
GHOST_TSuccess success;
DEVMODE dm;
- if (::EnumDisplaySettings(NULL, index, &dm)) {
+ if (::EnumDisplaySettings(display_device.DeviceName, index, &dm)) {
#ifdef GHOST_DEBUG
printf("display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency);
#endif // GHOST_DEBUG
@@ -112,23 +120,23 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(GHOST_TUns8 display,
GHOST_TSuccess GHOST_DisplayManagerWin32::getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const
{
- GHOST_ASSERT((display == kMainDisplay), "GHOST_DisplayManagerWin32::getCurrentDisplaySetting(): only main display is supported");
- return getDisplaySetting(kMainDisplay, ENUM_CURRENT_SETTINGS, setting);
+ return getDisplaySetting(display, ENUM_CURRENT_SETTINGS, setting);
}
GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting)
{
- GHOST_ASSERT((display == kMainDisplay), "GHOST_DisplayManagerWin32::setCurrentDisplaySetting(): only main display is supported");
+ DISPLAY_DEVICE display_device;
+ if (!get_dd(display, &display_device)) return GHOST_kFailure;
GHOST_DisplaySetting match;
findMatch(display, setting, match);
DEVMODE dm;
int i = 0;
- while (::EnumDisplaySettings(NULL, i++, &dm)) {
- if ((dm.dmBitsPerPel == match.bpp) &&
- (dm.dmPelsWidth == match.xPixels) &&
- (dm.dmPelsHeight == match.yPixels) &&
+ while (::EnumDisplaySettings(display_device.DeviceName, i++, &dm)) {
+ if ((dm.dmBitsPerPel == match.bpp ) &&
+ (dm.dmPelsWidth == match.xPixels) &&
+ (dm.dmPelsHeight == match.yPixels) &&
(dm.dmDisplayFrequency == match.frequency))
{
break;
diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp
index 754218191a5..7830f42cbb7 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp
+++ b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp
@@ -40,7 +40,6 @@
#include "GHOST_SystemX11.h"
-
GHOST_DisplayManagerX11::
GHOST_DisplayManagerX11(
GHOST_SystemX11 *system
@@ -82,9 +81,9 @@ getNumDisplaySettings(
return GHOST_kFailure;
}
- /* The X11 man page says vidmodes needs to be freed, but doing so causes a
- * segfault. - z0r */
- XF86VidModeGetAllModeLines(dpy, DefaultScreen(dpy), &numSettings, &vidmodes);
+ if (XF86VidModeGetAllModeLines(dpy, DefaultScreen(dpy), &numSettings, &vidmodes)) {
+ XFree(vidmodes);
+ }
#else
/* We only have one X11 setting at the moment. */
@@ -95,6 +94,17 @@ getNumDisplaySettings(
return GHOST_kSuccess;
}
+/* from SDL2 */
+#ifdef WITH_X11_XF86VMODE
+static int
+calculate_rate(XF86VidModeModeInfo *info)
+{
+ return (info->htotal
+ && info->vtotal) ? (1000 * info->dotclock / (info->htotal *
+ info->vtotal)) : 0;
+}
+#endif
+
GHOST_TSuccess
GHOST_DisplayManagerX11::
getDisplaySetting(
@@ -102,51 +112,46 @@ getDisplaySetting(
GHOST_TInt32 index,
GHOST_DisplaySetting& setting) const
{
+ Display *dpy = m_system->getXDisplay();
+
+ if (dpy == NULL)
+ return GHOST_kFailure;
#ifdef WITH_X11_XF86VMODE
int majorVersion, minorVersion;
- XF86VidModeModeInfo **vidmodes;
- Display *dpy = m_system->getXDisplay();
- int numSettings;
GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
- if (dpy == NULL)
- return GHOST_kFailure;
-
majorVersion = minorVersion = 0;
- if (!XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion)) {
- fprintf(stderr, "Error: XF86VidMode extension missing!\n");
- return GHOST_kFailure;
- }
+ if (XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion)) {
+ XF86VidModeModeInfo **vidmodes;
+ int numSettings;
- /* The X11 man page says vidmodes needs to be freed, but doing so causes a
- * segfault. - z0r */
- XF86VidModeGetAllModeLines(dpy, DefaultScreen(dpy), &numSettings, &vidmodes);
- GHOST_ASSERT(index < numSettings, "Requested setting outside of valid range.\n");
-
- setting.xPixels = vidmodes[index]->hdisplay;
- setting.yPixels = vidmodes[index]->vdisplay;
- setting.bpp = DefaultDepth(dpy, DefaultScreen(dpy));
+ if (XF86VidModeGetAllModeLines(dpy, DefaultScreen(dpy), &numSettings, &vidmodes)) {
+ GHOST_ASSERT(index < numSettings, "Requested setting outside of valid range.\n");
-#else
- GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
- GHOST_ASSERT(index < 1, "Requested setting outside of valid range.\n");
-
- Display *x_display = m_system->getXDisplay();
+ setting.xPixels = vidmodes[index]->hdisplay;
+ setting.yPixels = vidmodes[index]->vdisplay;
+ setting.bpp = DefaultDepth(dpy, DefaultScreen(dpy));
+ setting.frequency = calculate_rate(vidmodes[index]);
+ XFree(vidmodes);
- if (x_display == NULL) {
- return GHOST_kFailure;
+ return GHOST_kSuccess;
+ }
}
+ else {
+ fprintf(stderr, "Warning: XF86VidMode extension missing!\n");
+ /* fallback to non xf86vmode below */
+ }
+#endif /* WITH_X11_XF86VMODE */
- setting.xPixels = DisplayWidth(x_display, DefaultScreen(x_display));
- setting.yPixels = DisplayHeight(x_display, DefaultScreen(x_display));
- setting.bpp = DefaultDepth(x_display, DefaultScreen(x_display));
-#endif
+ GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
+ GHOST_ASSERT(index < 1, "Requested setting outside of valid range.\n");
- /* Don't think it's possible to get this value from X!
- * So let's guess!! */
- setting.frequency = 60;
+ setting.xPixels = DisplayWidth(dpy, DefaultScreen(dpy));
+ setting.yPixels = DisplayHeight(dpy, DefaultScreen(dpy));
+ setting.bpp = DefaultDepth(dpy, DefaultScreen(dpy));
+ setting.frequency = 60.0f;
return GHOST_kSuccess;
}
@@ -171,15 +176,13 @@ setCurrentDisplaySetting(
const GHOST_DisplaySetting& setting)
{
#ifdef WITH_X11_XF86VMODE
- /* Mode switching code ported from Quake 2:
- * ftp: ftp.idsoftware.com/idstuff/source/q2source-3.21.zip
- * See linux/gl_glx.c:GLimp_SetMode
+ /* Mode switching code ported from SDL:
+ * See: src/video/x11/SDL_x11modes.c:set_best_resolution
*/
int majorVersion, minorVersion;
XF86VidModeModeInfo **vidmodes;
Display *dpy = m_system->getXDisplay();
int scrnum, num_vidmodes;
- int best_fit, best_dist, dist, x, y;
if (dpy == NULL)
return GHOST_kFailure;
@@ -197,41 +200,62 @@ setCurrentDisplaySetting(
majorVersion, minorVersion);
# endif
- /* The X11 man page says vidmodes needs to be freed, but doing so causes a
- * segfault. - z0r */
- XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes);
+ if (XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes)) {
+ int best_fit = -1;
+
+ for (int i = 0; i < num_vidmodes; i++) {
+ if (vidmodes[i]->hdisplay < setting.xPixels ||
+ vidmodes[i]->vdisplay < setting.yPixels)
+ {
+ continue;
+ }
+
+ if (best_fit == -1 ||
+ (vidmodes[i]->hdisplay < vidmodes[best_fit]->hdisplay) ||
+ (vidmodes[i]->hdisplay == vidmodes[best_fit]->hdisplay &&
+ vidmodes[i]->vdisplay < vidmodes[best_fit]->vdisplay))
+ {
+ best_fit = i;
+ continue;
+ }
+
+ if ((vidmodes[i]->hdisplay == vidmodes[best_fit]->hdisplay) &&
+ (vidmodes[i]->vdisplay == vidmodes[best_fit]->vdisplay))
+ {
+ if (!setting.frequency) {
+ /* Higher is better, right? */
+ if (calculate_rate(vidmodes[i]) >
+ calculate_rate(vidmodes[best_fit]))
+ {
+ best_fit = i;
+ }
+ }
+ else {
+ if (abs(calculate_rate(vidmodes[i]) - (int)setting.frequency) <
+ abs(calculate_rate(vidmodes[best_fit]) - (int)setting.frequency))
+ {
+ best_fit = i;
+ }
+ }
+ }
+ }
- best_dist = 9999999;
- best_fit = -1;
+ if (best_fit != -1) {
+ # ifdef _DEBUG
+ printf("Switching to video mode %dx%d %dx%d %d\n",
+ vidmodes[best_fit]->hdisplay, vidmodes[best_fit]->vdisplay,
+ vidmodes[best_fit]->htotal, vidmodes[best_fit]->vtotal,
+ calculate_rate(vidmodes[best_fit]));
+ # endif
- for (int i = 0; i < num_vidmodes; i++) {
- if (setting.xPixels > vidmodes[i]->hdisplay ||
- setting.yPixels > vidmodes[i]->vdisplay)
- continue;
+ /* change to the mode */
+ XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]);
- x = setting.xPixels - vidmodes[i]->hdisplay;
- y = setting.yPixels - vidmodes[i]->vdisplay;
- dist = (x * x) + (y * y);
- if (dist < best_dist) {
- best_dist = dist;
- best_fit = i;
+ /* Move the viewport to top left */
+ XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
}
- }
-
- if (best_fit != -1) {
-# ifdef _DEBUG
- int actualWidth, actualHeight;
- actualWidth = vidmodes[best_fit]->hdisplay;
- actualHeight = vidmodes[best_fit]->vdisplay;
- printf("Switching to video mode %dx%d\n",
- actualWidth, actualHeight);
-# endif
- /* change to the mode */
- XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]);
-
- /* Move the viewport to top left */
- XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
+ XFree(vidmodes);
}
else {
return GHOST_kFailure;
@@ -245,7 +269,3 @@ setCurrentDisplaySetting(
return GHOST_kSuccess;
#endif
}
-
-
-
-
diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.cpp b/intern/ghost/intern/GHOST_DropTargetWin32.cpp
index 89e9a91b34c..5288b77a3c6 100644
--- a/intern/ghost/intern/GHOST_DropTargetWin32.cpp
+++ b/intern/ghost/intern/GHOST_DropTargetWin32.cpp
@@ -32,7 +32,7 @@
#include "GHOST_Debug.h"
#include "GHOST_DropTargetWin32.h"
-#include <ShellApi.h>
+#include <shellapi.h>
#include "utf_winfunc.h"
#include "utfconv.h"
diff --git a/intern/ghost/intern/GHOST_Event.h b/intern/ghost/intern/GHOST_Event.h
index c9a51f29559..ea4d603be83 100644
--- a/intern/ghost/intern/GHOST_Event.h
+++ b/intern/ghost/intern/GHOST_Event.h
@@ -51,7 +51,7 @@ public:
* \param window The generating window (or NULL if system event).
*/
GHOST_Event(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow *window)
- : m_type(type), m_time(msec), m_window(window), m_data(0)
+ : m_type(type), m_time(msec), m_window(window), m_data(NULL)
{
}
diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp
index 014eef85aa8..2fddfe22c85 100644
--- a/intern/ghost/intern/GHOST_EventManager.cpp
+++ b/intern/ghost/intern/GHOST_EventManager.cpp
@@ -81,7 +81,7 @@ GHOST_TUns32 GHOST_EventManager::getNumEvents(GHOST_TEventType type)
GHOST_IEvent *GHOST_EventManager::peekEvent()
{
- GHOST_IEvent *event = 0;
+ GHOST_IEvent *event = NULL;
if (m_events.empty() == false) {
event = m_events.back();
}
diff --git a/intern/ghost/intern/GHOST_EventManager.h b/intern/ghost/intern/GHOST_EventManager.h
index fea8214c7f2..8e513b4ee76 100644
--- a/intern/ghost/intern/GHOST_EventManager.h
+++ b/intern/ghost/intern/GHOST_EventManager.h
@@ -141,7 +141,7 @@ public:
virtual void
removeTypeEvents(
GHOST_TEventType type,
- GHOST_IWindow *window = 0
+ GHOST_IWindow *window = NULL
);
protected:
diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm
index d29dd4dd3e8..0d009e17561 100644
--- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm
+++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm
@@ -27,7 +27,7 @@
#include "GHOST_SystemCocoa.h"
extern "C" {
- #include <3DconnexionClient/ConnexionClientAPI.h>
+ #include <ConnexionClientAPI.h>
#include <stdio.h>
}
diff --git a/intern/ghost/intern/GHOST_Path-api.cpp b/intern/ghost/intern/GHOST_Path-api.cpp
index 2bc58517e75..04f6788f5b7 100644
--- a/intern/ghost/intern/GHOST_Path-api.cpp
+++ b/intern/ghost/intern/GHOST_Path-api.cpp
@@ -29,6 +29,7 @@
* \ingroup GHOST
*/
+#include <cstdio>
#include "intern/GHOST_Debug.h"
#include "GHOST_Types.h"
@@ -48,19 +49,19 @@ GHOST_TSuccess GHOST_DisposeSystemPaths(void)
const GHOST_TUns8 *GHOST_getSystemDir(int version, const char *versionstr)
{
GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get();
- return systemPaths ? systemPaths->getSystemDir(version, versionstr) : 0;
+ return systemPaths ? systemPaths->getSystemDir(version, versionstr) : NULL;
}
const GHOST_TUns8 *GHOST_getUserDir(int version, const char *versionstr)
{
GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get();
- return systemPaths ? systemPaths->getUserDir(version, versionstr) : 0; /* shouldn't be NULL */
+ return systemPaths ? systemPaths->getUserDir(version, versionstr) : NULL; /* shouldn't be NULL */
}
const GHOST_TUns8 *GHOST_getBinaryDir()
{
GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get();
- return systemPaths ? systemPaths->getBinaryDir() : 0; /* shouldn't be NULL */
+ return systemPaths ? systemPaths->getBinaryDir() : NULL; /* shouldn't be NULL */
}
void GHOST_addToSystemRecentFiles(const char *filename)
diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp
index 8c6491bcbfd..023c5958c4f 100644
--- a/intern/ghost/intern/GHOST_System.cpp
+++ b/intern/ghost/intern/GHOST_System.cpp
@@ -45,10 +45,11 @@
GHOST_System::GHOST_System()
- : m_displayManager(0),
- m_timerManager(0),
- m_windowManager(0),
- m_eventManager(0)
+ : m_nativePixel(false),
+ m_displayManager(NULL),
+ m_timerManager(NULL),
+ m_windowManager(NULL),
+ m_eventManager(NULL)
#ifdef WITH_INPUT_NDOF
, m_ndofManager(0)
#endif
@@ -151,7 +152,7 @@ GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting& setting
success = m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, setting);
if (success == GHOST_kSuccess) {
//GHOST_PRINT("GHOST_System::beginFullScreen(): creating full-screen window\n");
- success = createFullScreenWindow((GHOST_Window **)window, stereoVisual, numOfAASamples);
+ success = createFullScreenWindow((GHOST_Window **)window, setting, stereoVisual, numOfAASamples);
if (success == GHOST_kSuccess) {
m_windowManager->beginFullScreen(*window, stereoVisual);
}
@@ -323,19 +324,19 @@ GHOST_TSuccess GHOST_System::exit()
}
if (m_displayManager) {
delete m_displayManager;
- m_displayManager = 0;
+ m_displayManager = NULL;
}
if (m_windowManager) {
delete m_windowManager;
- m_windowManager = 0;
+ m_windowManager = NULL;
}
if (m_timerManager) {
delete m_timerManager;
- m_timerManager = 0;
+ m_timerManager = NULL;
}
if (m_eventManager) {
delete m_eventManager;
- m_eventManager = 0;
+ m_eventManager = NULL;
}
#ifdef WITH_INPUT_NDOF
if (m_ndofManager) {
@@ -346,26 +347,22 @@ GHOST_TSuccess GHOST_System::exit()
return GHOST_kSuccess;
}
-
-GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, const bool stereoVisual, const GHOST_TUns16 numOfAASamples)
+GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, const GHOST_DisplaySetting &settings,
+ const bool stereoVisual, const GHOST_TUns16 numOfAASamples)
{
- GHOST_TSuccess success;
+ /* 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");
- GHOST_DisplaySetting settings;
-
- success = m_displayManager->getCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, settings);
- if (success) {
- //GHOST_PRINT("GHOST_System::createFullScreenWindow(): creating full-screen window\n");
- *window = (GHOST_Window *)createWindow(
- STR_String(""),
- 0, 0, settings.xPixels, settings.yPixels,
- GHOST_kWindowStateFullScreen,
- GHOST_kDrawingContextTypeOpenGL,
- stereoVisual,
- numOfAASamples);
- success = *window == 0 ? GHOST_kFailure : GHOST_kSuccess;
- }
- return success;
+ //GHOST_PRINT("GHOST_System::createFullScreenWindow(): creating full-screen window\n");
+ *window = (GHOST_Window *)createWindow(
+ STR_String(""),
+ 0, 0, settings.xPixels, settings.yPixels,
+ GHOST_kWindowStateNormal,
+ GHOST_kDrawingContextTypeOpenGL,
+ stereoVisual,
+ true, /* exclusive */
+ numOfAASamples);
+ return (*window == NULL) ? GHOST_kFailure : GHOST_kSuccess;
}
@@ -373,3 +370,10 @@ int GHOST_System::confirmQuit(GHOST_IWindow *window) const
{
return 1;
}
+
+bool GHOST_System::useNativePixel(void)
+{
+ m_nativePixel = true;
+ return 1;
+}
+
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index d2e3377f6ce..57aa0a31c94 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -100,7 +100,7 @@ public:
virtual GHOST_ITimerTask *installTimer(GHOST_TUns64 delay,
GHOST_TUns64 interval,
GHOST_TimerProcPtr timerProc,
- GHOST_TUserDataPtr userData = 0);
+ GHOST_TUserDataPtr userData = NULL);
/**
* Removes a timer.
@@ -167,6 +167,13 @@ public:
*/
virtual bool getFullScreen(void);
+
+ /**
+ * Native pixel size support (MacBook 'retina').
+ * \return The pixel size in float.
+ */
+ virtual bool useNativePixel(void);
+ bool m_nativePixel;
/***************************************************************************************
* Event management functionality
@@ -323,7 +330,7 @@ protected:
* \param window The window created.
* \return Indication of success.
*/
- virtual GHOST_TSuccess createFullScreenWindow(GHOST_Window **window,
+ virtual GHOST_TSuccess createFullScreenWindow(GHOST_Window **window, const GHOST_DisplaySetting &settings,
const bool stereoVisual, const GHOST_TUns16 numOfAASamples = 0);
/** The display manager (platform dependant). */
@@ -350,6 +357,7 @@ protected:
/** Settings of the display before the display went fullscreen. */
GHOST_DisplaySetting m_preFullScreenSetting;
+
};
inline GHOST_TimerManager *GHOST_System::getTimerManager() const
diff --git a/intern/ghost/intern/GHOST_SystemCarbon.cpp b/intern/ghost/intern/GHOST_SystemCarbon.cpp
index f5784c7d451..f7e035e890d 100644
--- a/intern/ghost/intern/GHOST_SystemCarbon.cpp
+++ b/intern/ghost/intern/GHOST_SystemCarbon.cpp
@@ -396,6 +396,11 @@ void GHOST_SystemCarbon::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUn
height = bnds.bottom - bnds.top;
}
+void GHOST_SystemCarbon::getAllDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
+{
+ /* TODO */
+ getMainDisplayDimensions(width, height);
+}
GHOST_IWindow *GHOST_SystemCarbon::createWindow(
const STR_String& title,
@@ -406,6 +411,7 @@ GHOST_IWindow *GHOST_SystemCarbon::createWindow(
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
bool stereoVisual,
+ const bool exclusive,
const GHOST_TUns16 numOfAASamples,
const GHOST_TEmbedderWindowID parentWindow)
{
diff --git a/intern/ghost/intern/GHOST_SystemCarbon.h b/intern/ghost/intern/GHOST_SystemCarbon.h
index 61e5a086a0f..9faf5423205 100644
--- a/intern/ghost/intern/GHOST_SystemCarbon.h
+++ b/intern/ghost/intern/GHOST_SystemCarbon.h
@@ -91,6 +91,12 @@ public:
* \return The dimension of the main display.
*/
virtual 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;
/**
* Create a new window.
@@ -115,6 +121,7 @@ public:
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
const bool stereoVisual,
+ const bool exclusive = false,
const GHOST_TUns16 numOfAASamples = 0,
const GHOST_TEmbedderWindowID parentWindow = 0
);
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index 9162b7ce4e0..cbb61f6e6ea 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -89,6 +89,11 @@ public:
*/
virtual 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;
+
/**
* Create a new window.
* The new window is added to the list of windows managed.
@@ -114,6 +119,7 @@ public:
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
const bool stereoVisual = false,
+ const bool exclusive = false,
const GHOST_TUns16 numOfAASamples = 0,
const GHOST_TEmbedderWindowID parentWindow = 0
);
@@ -296,8 +302,6 @@ protected:
/** Multitouch trackpad availability */
bool m_hasMultiTouchTrackpad;
- /** Multitouch gesture in progress, useful to distinguish trackpad from mouse scroll events */
- bool m_isGestureInProgress;
};
#endif // __GHOST_SYSTEMCOCOA_H__
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 16edb4af575..e4f859217cd 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -56,7 +56,7 @@
#include "AssertMacros.h"
#pragma mark KeyMap, mouse converters
-#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+#if MAC_OS_X_VERSION_MIN_REQUIRED <= 1040
/* Keycodes not defined in Tiger */
/*
* Summary:
@@ -360,7 +360,7 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
return (GHOST_TKey) (recvChar - 'a' + GHOST_kKeyA);
}
else {
-#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+#if MAC_OS_X_VERSION_MIN_REQUIRED <= 1040
KeyboardLayoutRef keyLayout;
UCKeyboardLayout *uchrData;
@@ -423,7 +423,7 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
#pragma mark defines for 10.6 api not documented in 10.5
-#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+#if MAC_OS_X_VERSION_MIN_REQUIRED <= 1040
enum {
/* The following event types are available on some hardware on 10.5.2 and later */
NSEventTypeGesture = 29,
@@ -500,6 +500,7 @@ int cocoa_request_qtcodec_settings(bContext *C, wmOperator *op)
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
- (void)applicationWillTerminate:(NSNotification *)aNotification;
- (void)applicationWillBecomeActive:(NSNotification *)aNotification;
+- (void)toggleFullScreen:(NSNotification *)notification;
@end
@implementation CocoaAppDelegate : NSObject
@@ -536,12 +537,19 @@ int cocoa_request_qtcodec_settings(bContext *C, wmOperator *op)
{
systemCocoa->handleApplicationBecomeActiveEvent();
}
+
+- (void)toggleFullScreen:(NSNotification *)notification
+{
+}
+
@end
+
#pragma mark initialization/finalization
+const char *user_locale; // Global current user locale
GHOST_SystemCocoa::GHOST_SystemCocoa()
{
@@ -551,7 +559,6 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
char *rstring = NULL;
m_modifierMask =0;
- m_isGestureInProgress = false;
m_cursorDelta_x=0;
m_cursorDelta_y=0;
m_outsideLoopEventProcessed = false;
@@ -575,18 +582,19 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
rstring = (char*)malloc( len );
sysctl( mib, 2, rstring, &len, NULL, 0 );
- //Hack on MacBook revision, as multitouch avail. function missing
- //MacbookAir or MacBook version >= 5 (retina is MacBookPro10,1)
- if (strstr(rstring,"MacBookAir") ||
- (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9')) ||
- (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-4]>='1') && (rstring[strlen(rstring)-4]<='9')))
- m_hasMultiTouchTrackpad = true;
- else m_hasMultiTouchTrackpad = false;
+ m_hasMultiTouchTrackpad = false;
free( rstring );
rstring = NULL;
m_ignoreWindowSizedMessages = false;
+
+ //Get current locale
+ CFLocaleRef myCFLocale = CFLocaleCopyCurrent();
+ NSLocale * myNSLocale = (NSLocale *) myCFLocale;
+ [myNSLocale autorelease];
+ NSString *nsIdentifier = [myNSLocale localeIdentifier];
+ user_locale = [nsIdentifier UTF8String];
}
GHOST_SystemCocoa::~GHOST_SystemCocoa()
@@ -654,6 +662,11 @@ GHOST_TSuccess GHOST_SystemCocoa::init()
[windowMenu addItemWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""];
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 // make it build with 10.6 deployment target, but as it is not available in 10.6, it will get weaklinked
+ menuItem = [windowMenu addItemWithTitle:@"Enter Full Screen" action:@selector(toggleFullScreen:) keyEquivalent:@"f" ];
+ [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
+#endif
+
menuItem = [windowMenu addItemWithTitle:@"Close" action:@selector(performClose:) keyEquivalent:@"w"];
[menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
@@ -726,6 +739,11 @@ void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns
[pool drain];
}
+void GHOST_SystemCocoa::getAllDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
+{
+ /* TODO! */
+ getMainDisplayDimensions(width, height);
+}
GHOST_IWindow* GHOST_SystemCocoa::createWindow(
const STR_String& title,
@@ -736,6 +754,7 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow(
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
bool stereoVisual,
+ const bool exclusive,
const GHOST_TUns16 numOfAASamples,
const GHOST_TEmbedderWindowID parentWindow
)
@@ -1030,8 +1049,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType,
if (!validWindow(window)) {
return GHOST_kFailure;
}
- switch(eventType)
- {
+ switch (eventType) {
case GHOST_kEventWindowClose:
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) );
break;
@@ -1045,6 +1063,10 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType,
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:
@@ -1058,9 +1080,16 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType,
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;
+ //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;
@@ -1077,8 +1106,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
if (!validWindow(window)) {
return GHOST_kFailure;
}
- switch(eventType)
- {
+ switch (eventType) {
case GHOST_kEventDraggingEntered:
case GHOST_kEventDraggingUpdated:
case GHOST_kEventDraggingExited:
@@ -1388,7 +1416,13 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr, short eventT
switch (eventType) {
case NSTabletPoint:
- ct.Pressure = [event pressure];
+ // workaround 2 cornercases:
+ // 1. if [event isEnteringProximity] was not triggered since program-start
+ // 2. device is not sending [event pointingDeviceType], due no eraser
+ if (ct.Active == GHOST_kTabletModeNone)
+ ct.Active = GHOST_kTabletModeStylus;
+
+ ct.Pressure = sqrtf(powf([event pressure], 5 )); // experimental: change sensivity curve
ct.Xtilt = [event tilt].x;
ct.Ytilt = [event tilt].y;
break;
@@ -1446,17 +1480,47 @@ 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,
+};
+typedef NSUInteger NSEventPhase;
+
+@interface NSEvent (AvailableOn1070AndLater)
+- (BOOL)hasPreciseScrollingDeltas;
+- (CGFloat)scrollingDeltaX;
+- (CGFloat)scrollingDeltaY;
+- (NSEventPhase)momentumPhase;
+- (BOOL)isDirectionInvertedFromDevice;
+- (NSEventPhase)phase;
+@end
+#endif
+
GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
{
NSEvent *event = (NSEvent *)eventPtr;
GHOST_WindowCocoa* window;
+ CocoaWindow *cocoawindow;
+ /* [event window] returns other windows if mouse-over, that's OSX input standard
+ however, if mouse exits window(s), the windows become inactive, until you click.
+ We then fall back to the active window from ghost */
window = (GHOST_WindowCocoa*)m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]);
if (!window) {
- //printf("\nW failure for event 0x%x",[event type]);
- return GHOST_kFailure;
+ window = (GHOST_WindowCocoa*)m_windowManager->getActiveWindow();
+ if (!window) {
+ //printf("\nW failure for event 0x%x",[event type]);
+ return GHOST_kFailure;
+ }
}
+ cocoawindow = (CocoaWindow *)window->getOSWindow();
+
switch ([event type]) {
case NSLeftMouseDown:
case NSRightMouseDown:
@@ -1509,7 +1573,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
break;
case GHOST_kGrabWrap: //Wrap cursor at area/window boundaries
{
- NSPoint mousePos = [event locationInWindow];
+ NSPoint mousePos = [cocoawindow mouseLocationOutsideOfEventStream];
GHOST_TInt32 x_mouse= mousePos.x;
GHOST_TInt32 y_mouse= mousePos.y;
GHOST_TInt32 x_accum, y_accum, x_cur, y_cur, x, y;
@@ -1555,9 +1619,9 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
default:
{
//Normal cursor operation: send mouse position in window
- NSPoint mousePos = [event locationInWindow];
+ NSPoint mousePos = [cocoawindow mouseLocationOutsideOfEventStream];
GHOST_TInt32 x, y;
-
+
window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
pushEvent(new GHOST_EventCursor([event timestamp] * 1000, GHOST_kEventCursorMove, window, x, y));
@@ -1569,10 +1633,24 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
}
break;
+ /* these events only happen on swiping trackpads or tablets */
+ /* warning: using tablet + trackpad at same time frustrates this static variable */
+ case NSEventTypeBeginGesture:
+ m_hasMultiTouchTrackpad = 1;
+ break;
+ case NSEventTypeEndGesture:
+ m_hasMultiTouchTrackpad = 0;
+ break;
+
case NSScrollWheel:
{
- /* Send trackpad event if inside a trackpad gesture, send wheel event otherwise */
- if (!m_hasMultiTouchTrackpad || !m_isGestureInProgress) {
+ int *momentum = NULL;
+
+ if ([event respondsToSelector:@selector(momentumPhase)])
+ momentum = (int *)[event momentumPhase];
+
+ /* standard scrollwheel case, if no swiping happened, and no momentum (kinetic scroll) works */
+ if (!m_hasMultiTouchTrackpad && momentum == NULL) {
GHOST_TInt32 delta;
double deltaF = [event deltaY];
@@ -1584,11 +1662,28 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
pushEvent(new GHOST_EventWheel([event timestamp] * 1000, window, delta));
}
else {
- NSPoint mousePos = [event locationInWindow];
+ NSPoint mousePos = [cocoawindow mouseLocationOutsideOfEventStream];
GHOST_TInt32 x, y;
- double dx = [event deltaX];
- double dy = -[event deltaY];
+ double dx;
+ double dy;
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
+ int phase = [event phase];
+ /* with 10.7 nice scrolling deltas are supported */
+ dx = [event scrollingDeltaX];
+ dy = [event scrollingDeltaY];
+
+ /* however, wacom tablet (intuos5) needs old deltas, it then has momentum and phase at zero */
+ if (phase == 0 && momentum==NULL) {
+ dx = [event deltaX];
+ dy = [event deltaY];
+ }
+
+#else
+ /* trying to pretend you have nice scrolls... */
+ dx = [event deltaX];
+ dy = -[event deltaY];
const double deltaMax = 50.0;
if ((dx == 0) && (dy == 0)) break;
@@ -1605,9 +1700,10 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
else dy += 0.5;
if (dy < -deltaMax) dy= -deltaMax;
else if (dy > deltaMax) dy= deltaMax;
-
- window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
+
dy = -dy;
+#endif
+ window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000, window, GHOST_kTrackpadEventScroll, x, y, dx, dy));
}
@@ -1616,7 +1712,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
case NSEventTypeMagnify:
{
- NSPoint mousePos = [event locationInWindow];
+ NSPoint mousePos = [cocoawindow mouseLocationOutsideOfEventStream];
GHOST_TInt32 x, y;
window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000, window, GHOST_kTrackpadEventMagnify, x, y,
@@ -1626,18 +1722,12 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
case NSEventTypeRotate:
{
- NSPoint mousePos = [event locationInWindow];
+ NSPoint mousePos = [cocoawindow mouseLocationOutsideOfEventStream];
GHOST_TInt32 x, y;
window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000, window, GHOST_kTrackpadEventRotate, x, y,
-[event rotation] * 5.0, 0));
}
- case NSEventTypeBeginGesture:
- m_isGestureInProgress = true;
- break;
- case NSEventTypeEndGesture:
- m_isGestureInProgress = false;
- break;
default:
return GHOST_kFailure;
break;
@@ -1709,7 +1799,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
//printf("Key down rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c utf8=%s\n",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii, utf8_buf);
}
else {
- pushEvent( new GHOST_EventKey([event timestamp] * 1000, GHOST_kEventKeyUp, window, keyCode, 0, '\0') );
+ pushEvent( new GHOST_EventKey([event timestamp] * 1000, GHOST_kEventKeyUp, window, keyCode, 0, NULL) );
//printf("Key up rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c utf8=%s\n",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii, utf8_buf);
}
break;
diff --git a/intern/ghost/intern/GHOST_SystemNULL.h b/intern/ghost/intern/GHOST_SystemNULL.h
index 63e3b5bc828..7021dea36dd 100644
--- a/intern/ghost/intern/GHOST_SystemNULL.h
+++ b/intern/ghost/intern/GHOST_SystemNULL.h
@@ -38,7 +38,7 @@ class GHOST_WindowNULL;
class GHOST_SystemNULL : public GHOST_System {
public:
- GHOST_SystemNULL( ) : GHOST_System() { /* nop */ }
+ GHOST_SystemNULL() : GHOST_System() { /* nop */ }
~GHOST_SystemNULL() { /* nop */ }
bool processEvents(bool waitForEvent) { return false; }
int toggleConsole(int action) { return 0; }
@@ -46,11 +46,12 @@ public:
GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const { return GHOST_kSuccess; }
GHOST_TUns8 *getClipboard(bool selection) const { return NULL; }
void putClipboard(GHOST_TInt8 *buffer, bool selection) const { /* nop */ }
- GHOST_TUns64 getMilliSeconds( ) const { return 0; }
- GHOST_TUns8 getNumDisplays( ) const { return GHOST_TUns8(1); }
- GHOST_TSuccess getCursorPosition( GHOST_TInt32& x, GHOST_TInt32& y ) const { return GHOST_kFailure; }
- GHOST_TSuccess setCursorPosition( GHOST_TInt32 x, GHOST_TInt32 y ) { return GHOST_kFailure; }
- void getMainDisplayDimensions( GHOST_TUns32& width, GHOST_TUns32& height ) const { /* nop */ }
+ GHOST_TUns64 getMilliSeconds() const { return 0; }
+ GHOST_TUns8 getNumDisplays() const { return GHOST_TUns8(1); }
+ GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const { return GHOST_kFailure; }
+ GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) { return GHOST_kFailure; }
+ void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const { /* nop */ }
+ void getAllDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const { /* nop */ }
GHOST_TSuccess init() {
GHOST_TSuccess success = GHOST_System::init();
@@ -82,11 +83,4 @@ public:
}
};
-#endif
-
-
-
-
-
-
-
+#endif /* __GHOST_SYSTEMNULL_H__ */
diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp
index fdc4f33b784..98d52c20ba1 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.cpp
+++ b/intern/ghost/intern/GHOST_SystemSDL.cpp
@@ -27,6 +27,7 @@
#include <assert.h>
#include "GHOST_SystemSDL.h"
+#include "GHOST_WindowSDL.h"
#include "GHOST_WindowManager.h"
@@ -66,14 +67,19 @@ GHOST_SystemSDL::createWindow(const STR_String& title,
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- bool stereoVisual,
+ const bool stereoVisual,
+ const bool exclusive,
const GHOST_TUns16 numOfAASamples,
const GHOST_TEmbedderWindowID parentWindow
)
{
GHOST_WindowSDL *window = NULL;
- window = new GHOST_WindowSDL(this, title, left, top, width, height, state, parentWindow, type, stereoVisual, numOfAASamples);
+ window = new GHOST_WindowSDL(this, title,
+ left, top, width, height,
+ state, parentWindow, type,
+ stereoVisual, exclusive,
+ numOfAASamples);
if (window) {
if (GHOST_kWindowStateFullScreen == state) {
@@ -114,6 +120,20 @@ GHOST_SystemSDL::init() {
return GHOST_kFailure;
}
+/**
+ * Returns the dimensions of the main display on this system.
+ * \return The dimension of the main display.
+ */
+void
+GHOST_SystemSDL::getAllDisplayDimensions(GHOST_TUns32& width,
+ GHOST_TUns32& height) const
+{
+ SDL_DisplayMode mode;
+ SDL_GetDesktopDisplayMode(0, &mode); /* note, always 0 display */
+ width = mode.w;
+ height = mode.h;
+}
+
void
GHOST_SystemSDL::getMainDisplayDimensions(GHOST_TUns32& width,
GHOST_TUns32& height) const
diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h
index 43c9129fdd8..5ad4fe09833 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.h
+++ b/intern/ghost/intern/GHOST_SystemSDL.h
@@ -88,6 +88,10 @@ public:
GHOST_TInt32 y);
void
+ getAllDisplayDimensions(GHOST_TUns32& width,
+ GHOST_TUns32& height) const;
+
+ void
getMainDisplayDimensions(GHOST_TUns32& width,
GHOST_TUns32& height) const;
@@ -104,9 +108,10 @@ private:
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- bool stereoVisual,
- const GHOST_TUns16 numOfAASamples,
- const GHOST_TEmbedderWindowID parentWindow
+ const bool stereoVisual,
+ const bool exclusive = false,
+ const GHOST_TUns16 numOfAASamples = 0,
+ const GHOST_TEmbedderWindowID parentWindow = 0
);
/* SDL specific */
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 46c71f57c6f..a6e14ac362e 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -215,12 +215,17 @@ void GHOST_SystemWin32::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns
height = ::GetSystemMetrics(SM_CYSCREEN);
}
+void GHOST_SystemWin32::getAllDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
+{
+ width = ::GetSystemMetrics(SM_CXVIRTUALSCREEN);
+ height = ::GetSystemMetrics(SM_CYVIRTUALSCREEN);
+}
GHOST_IWindow *GHOST_SystemWin32::createWindow(
const STR_String& title,
GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height,
GHOST_TWindowState state, GHOST_TDrawingContextType type,
- bool stereoVisual, const GHOST_TUns16 numOfAASamples, const GHOST_TEmbedderWindowID parentWindow)
+ bool stereoVisual, 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);
@@ -291,6 +296,9 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent)
// Process all the events waiting for us
while (::PeekMessageW(&msg, 0, 0, 0, PM_REMOVE) != 0) {
+ // TranslateMessage doesn't alter the message, and doesn't change our raw keyboard data.
+ // Needed for MapVirtualKey or if we ever need to get chars from wm_ime_char or similar.
+ ::TranslateMessage(&msg);
::DispatchMessageW(&msg);
anyProcessed = true;
}
@@ -724,13 +732,17 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINP
int r;
GetKeyboardState((PBYTE)state);
- if ((r = ToUnicodeEx(vk, 0, state, utf16, 2, 0, system->m_keylayout))) {
- if ((r > 0 && r < 3)) {
- utf16[r] = 0;
- conv_utf_16_to_8(utf16, utf8_char, 6);
- }
- else if (r == -1) {
- utf8_char[0] = '\0';
+ // don't call ToUnicodeEx on dead keys as it clears the buffer and so won't allow diacritical composition.
+ if (MapVirtualKeyW(vk,2) != 0) {
+ // todo: ToUnicodeEx can respond with up to 4 utf16 chars (only 2 here). Could be up to 24 utf8 bytes.
+ if ((r = ToUnicodeEx(vk, raw.data.keyboard.MakeCode, state, utf16, 2, 0, system->m_keylayout))) {
+ if ((r > 0 && r < 3)) {
+ utf16[r] = 0;
+ conv_utf_16_to_8(utf16, utf8_char, 6);
+ }
+ else if (r == -1) {
+ utf8_char[0] = '\0';
+ }
}
}
@@ -761,6 +773,7 @@ GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_
if (type == GHOST_kEventWindowActivate) {
system->getWindowManager()->setActiveWindow(window);
+ ((GHOST_WindowWin32*)window)->bringTabletContextToFront();
}
return new GHOST_Event(system->getMilliSeconds(), type, window);
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index 6a756d35872..c4b81677c18 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -100,7 +100,13 @@ public:
* \return The dimension of the main display.
*/
virtual 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;
+
/**
* Create a new window.
* The new window is added to the list of windows managed.
@@ -122,6 +128,7 @@ public:
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,
const GHOST_TEmbedderWindowID parentWindow = 0);
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index 2d3cc4f88dc..d00265fbd9b 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -69,8 +69,13 @@
#include <stdio.h> /* for fprintf only */
#include <cstdlib> /* for exit */
-static GHOST_TKey
-convertXKey(KeySym key);
+/* for debugging - so we can breakpoint X11 errors */
+// #define USE_X11_ERROR_HANDLERS
+
+/* see [#34039] Fix Alt key glitch on Unity desktop */
+#define USE_UNITY_WORKAROUND
+
+static GHOST_TKey convertXKey(KeySym key);
/* these are for copy and select copy */
static char *txt_cut_buffer = NULL;
@@ -91,6 +96,11 @@ GHOST_SystemX11(
abort(); /* was return before, but this would just mean it will crash later */
}
+#ifdef USE_X11_ERROR_HANDLERS
+ (void) XSetErrorHandler(GHOST_X11_ApplicationErrorHandler);
+ (void) XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler);
+#endif
+
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
/* note -- don't open connection to XIM server here, because the locale
* has to be set before opening the connection but setlocale() has not
@@ -99,32 +109,37 @@ GHOST_SystemX11(
m_xim = NULL;
#endif
- m_delete_window_atom
- = XInternAtom(m_display, "WM_DELETE_WINDOW", True);
-
- m_wm_protocols = XInternAtom(m_display, "WM_PROTOCOLS", False);
- m_wm_take_focus = XInternAtom(m_display, "WM_TAKE_FOCUS", False);
- m_wm_state = XInternAtom(m_display, "WM_STATE", False);
- m_wm_change_state = XInternAtom(m_display, "WM_CHANGE_STATE", False);
- m_net_state = XInternAtom(m_display, "_NET_WM_STATE", False);
- m_net_max_horz = XInternAtom(m_display,
- "_NET_WM_STATE_MAXIMIZED_HORZ", False);
- m_net_max_vert = XInternAtom(m_display,
- "_NET_WM_STATE_MAXIMIZED_VERT", False);
- m_net_fullscreen = XInternAtom(m_display,
- "_NET_WM_STATE_FULLSCREEN", False);
- m_motif = XInternAtom(m_display, "_MOTIF_WM_HINTS", False);
- m_targets = XInternAtom(m_display, "TARGETS", False);
- m_string = XInternAtom(m_display, "STRING", False);
- m_compound_text = XInternAtom(m_display, "COMPOUND_TEXT", False);
- m_text = XInternAtom(m_display, "TEXT", False);
- m_clipboard = XInternAtom(m_display, "CLIPBOARD", False);
- m_primary = XInternAtom(m_display, "PRIMARY", False);
- m_xclip_out = XInternAtom(m_display, "XCLIP_OUT", False);
- m_incr = XInternAtom(m_display, "INCR", False);
- m_utf8_string = XInternAtom(m_display, "UTF8_STRING", False);
- m_last_warp = 0;
+#define GHOST_INTERN_ATOM_IF_EXISTS(atom) { m_atom.atom = XInternAtom(m_display, #atom , True); } (void)0
+#define GHOST_INTERN_ATOM(atom) { m_atom.atom = XInternAtom(m_display, #atom , False); } (void)0
+
+ GHOST_INTERN_ATOM_IF_EXISTS(WM_DELETE_WINDOW);
+ GHOST_INTERN_ATOM(WM_PROTOCOLS);
+ GHOST_INTERN_ATOM(WM_TAKE_FOCUS);
+ GHOST_INTERN_ATOM(WM_STATE);
+ GHOST_INTERN_ATOM(WM_CHANGE_STATE);
+ GHOST_INTERN_ATOM(_NET_WM_STATE);
+ GHOST_INTERN_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
+ GHOST_INTERN_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
+
+ GHOST_INTERN_ATOM(_NET_WM_STATE_FULLSCREEN);
+ GHOST_INTERN_ATOM(_MOTIF_WM_HINTS);
+ GHOST_INTERN_ATOM(TARGETS);
+ GHOST_INTERN_ATOM(STRING);
+ GHOST_INTERN_ATOM(COMPOUND_TEXT);
+ GHOST_INTERN_ATOM(TEXT);
+ GHOST_INTERN_ATOM(CLIPBOARD);
+ GHOST_INTERN_ATOM(PRIMARY);
+ GHOST_INTERN_ATOM(XCLIP_OUT);
+ GHOST_INTERN_ATOM(INCR);
+ GHOST_INTERN_ATOM(UTF8_STRING);
+#ifdef WITH_X11_XINPUT
+ m_atom.TABLET = XInternAtom(m_display, XI_TABLET, False);
+#endif
+#undef GHOST_INTERN_ATOM_IF_EXISTS
+#undef GHOST_INTERN_ATOM
+
+ m_last_warp = 0;
/* compute the initial time */
timeval tv;
@@ -132,7 +147,7 @@ GHOST_SystemX11(
GHOST_ASSERT(false, "Could not instantiate timer!");
}
- /* Taking care not to overflow the tv.tv_sec*1000 */
+ /* Taking care not to overflow the tv.tv_sec * 1000 */
m_start_time = GHOST_TUns64(tv.tv_sec) * 1000 + tv.tv_usec / 1000;
@@ -146,6 +161,12 @@ GHOST_SystemX11(
XkbSetDetectableAutoRepeat(m_display, true, NULL);
}
+#ifdef WITH_X11_XINPUT
+ /* initialize incase X11 fails to load */
+ memset(&m_xtablet, 0, sizeof(m_xtablet));
+
+ initXInputDevices();
+#endif
}
GHOST_SystemX11::
@@ -157,6 +178,15 @@ GHOST_SystemX11::
}
#endif
+#ifdef WITH_X11_XINPUT
+ /* close tablet devices */
+ if (m_xtablet.StylusDevice)
+ XCloseDevice(m_display, m_xtablet.StylusDevice);
+
+ if (m_xtablet.EraserDevice)
+ XCloseDevice(m_display, m_xtablet.EraserDevice);
+#endif /* WITH_X11_XINPUT */
+
XCloseDisplay(m_display);
}
@@ -190,7 +220,7 @@ getMilliSeconds() const
GHOST_ASSERT(false, "Could not compute time!");
}
- /* Taking care not to overflow the tv.tv_sec*1000 */
+ /* Taking care not to overflow the tv.tv_sec * 1000 */
return GHOST_TUns64(tv.tv_sec) * 1000 + tv.tv_usec / 1000 - m_start_time;
}
@@ -212,6 +242,25 @@ getMainDisplayDimensions(
GHOST_TUns32& height) const
{
if (m_display) {
+ /* note, for this to work as documented,
+ * we would need to use Xinerama check r54370 for code that did thia,
+ * we've since removed since its not worth the extra dep - campbell */
+ getAllDisplayDimensions(width, height);
+ }
+}
+
+
+/**
+ * Returns the dimensions of the main display on this system.
+ * \return The dimension of the main display.
+ */
+void
+GHOST_SystemX11::
+getAllDisplayDimensions(
+ GHOST_TUns32& width,
+ GHOST_TUns32& height) const
+{
+ if (m_display) {
width = DisplayWidth(m_display, DefaultScreen(m_display));
height = DisplayHeight(m_display, DefaultScreen(m_display));
}
@@ -229,6 +278,8 @@ getMainDisplayDimensions(
* \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 parentWindow Parent (embedder) window
* \return The new window (or 0 if creation failed).
@@ -243,7 +294,8 @@ createWindow(
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- bool stereoVisual,
+ const bool stereoVisual,
+ const bool exclusive,
const GHOST_TUns16 numOfAASamples,
const GHOST_TEmbedderWindowID parentWindow)
{
@@ -256,7 +308,9 @@ createWindow(
window = new GHOST_WindowX11(this, m_display, title,
left, top, width, height,
- state, parentWindow, type, stereoVisual, numOfAASamples);
+ state, parentWindow, type,
+ stereoVisual, exclusive,
+ numOfAASamples);
if (window) {
/* Both are now handle in GHOST_WindowX11.cpp
@@ -474,6 +528,54 @@ processEvents(
processEvent(&xevent);
anyProcessed = true;
+
+
+#ifdef USE_UNITY_WORKAROUND
+ /* note: processEvent() can't include this code because
+ * KeymapNotify event have no valid window information. */
+
+ /* the X server generates KeymapNotify event immediately after
+ * every EnterNotify and FocusIn event. we handle this event
+ * to correct modifier states. */
+ if (xevent.type == FocusIn) {
+ /* use previous event's window, because KeymapNotify event
+ * has no window information. */
+ GHOST_WindowX11 *window = findGhostWindow(xevent.xany.window);
+ if (window && XPending(m_display) >= 2) {
+ XNextEvent(m_display, &xevent);
+
+ if (xevent.type == KeymapNotify) {
+ XEvent xev_next;
+
+ /* check if KeyPress or KeyRelease event was generated
+ * in order to confirm the window is active. */
+ XPeekEvent(m_display, &xev_next);
+
+ if (xev_next.type == KeyPress || xev_next.type == KeyRelease) {
+ /* XK_Hyper_L/R currently unused */
+ const static KeySym modifiers[8] = {XK_Shift_L, XK_Shift_R,
+ XK_Control_L, XK_Control_R,
+ XK_Alt_L, XK_Alt_R,
+ XK_Super_L, XK_Super_R};
+
+ for (int i = 0; i < (sizeof(modifiers) / sizeof(*modifiers)); i++) {
+ KeyCode kc = XKeysymToKeycode(m_display, modifiers[i]);
+ if (((xevent.xkeymap.key_vector[kc >> 3] >> (kc & 7)) & 1) != 0) {
+ pushEvent(new GHOST_EventKey(
+ getMilliSeconds(),
+ GHOST_kEventKeyDown,
+ window,
+ convertXKey(modifiers[i]),
+ '\0',
+ NULL));
+ }
+ }
+ }
+ }
+ }
+ }
+#endif /* USE_UNITY_WORKAROUND */
+
}
if (generateWindowExposeEvents()) {
@@ -494,12 +596,52 @@ processEvents(
#ifdef WITH_X11_XINPUT
/* set currently using tablet mode (stylus or eraser) depending on device ID */
-static void setTabletMode(GHOST_WindowX11 *window, XID deviceid)
+static void setTabletMode(GHOST_SystemX11 *system, GHOST_WindowX11 *window, XID deviceid)
+{
+ if (deviceid == system->GetXTablet().StylusID)
+ window->GetTabletData()->Active = GHOST_kTabletModeStylus;
+ else if (deviceid == system->GetXTablet().EraserID)
+ window->GetTabletData()->Active = GHOST_kTabletModeEraser;
+}
+#endif /* WITH_X11_XINPUT */
+
+#ifdef WITH_X11_XINPUT
+static bool checkTabletProximity(Display *display, XDevice *device)
{
- if (deviceid == window->GetXTablet().StylusID)
- window->GetXTablet().CommonData.Active = GHOST_kTabletModeStylus;
- else if (deviceid == window->GetXTablet().EraserID)
- window->GetXTablet().CommonData.Active = GHOST_kTabletModeEraser;
+ /* we could have true/false/not-found return value, but for now false is OK */
+
+ /* see: state.c from xinput, to get more data out of the device */
+ XDeviceState *state;
+
+ if (device == NULL) {
+ return false;
+ }
+
+ state = XQueryDeviceState(display, device);
+
+ if (state) {
+ XInputClass *cls = state->data;
+ // printf("%d class%s :\n", state->num_classes,
+ // (state->num_classes > 1) ? "es" : "");
+ for (int loop = 0; loop < state->num_classes; loop++) {
+ switch (cls->c_class) {
+ case ValuatorClass:
+ XValuatorState *val_state = (XValuatorState *)cls;
+ // printf("ValuatorClass Mode=%s Proximity=%s\n",
+ // val_state->mode & 1 ? "Absolute" : "Relative",
+ // val_state->mode & 2 ? "Out" : "In");
+
+ if ((val_state->mode & 2) == 0) {
+ XFreeDeviceState(state);
+ return true;
+ }
+ break;
+ }
+ cls = (XInputClass *) ((char *)cls + cls->length);
+ }
+ XFreeDeviceState(state);
+ }
+ return false;
}
#endif /* WITH_X11_XINPUT */
@@ -512,7 +654,23 @@ GHOST_SystemX11::processEvent(XEvent *xe)
if (!window) {
return;
}
-
+
+#ifdef WITH_X11_XINPUT
+ /* Proximity-Out Events are not reliable, if the tablet is active - check on each event
+ * this adds a little overhead but only while the tablet is in use.
+ * in the futire we could have a ghost call window->CheckTabletProximity()
+ * but for now enough parts of the code are checking 'Active'
+ * - campbell */
+ if (window->GetTabletData()->Active != GHOST_kTabletModeNone) {
+ if (checkTabletProximity(xe->xany.display, m_xtablet.StylusDevice) == false &&
+ checkTabletProximity(xe->xany.display, m_xtablet.EraserDevice) == false)
+ {
+ // printf("proximity disable\n");
+ window->GetTabletData()->Active = GHOST_kTabletModeNone;
+ }
+ }
+#endif /* WITH_X11_XINPUT */
+
switch (xe->type) {
case Expose:
{
@@ -537,7 +695,7 @@ GHOST_SystemX11::processEvent(XEvent *xe)
XMotionEvent &xme = xe->xmotion;
#ifdef WITH_X11_XINPUT
- bool is_tablet = window->GetXTablet().CommonData.Active != GHOST_kTabletModeNone;
+ bool is_tablet = window->GetTabletData()->Active != GHOST_kTabletModeNone;
#else
bool is_tablet = false;
#endif
@@ -811,7 +969,7 @@ GHOST_SystemX11::processEvent(XEvent *xe)
{
XClientMessageEvent & xcme = xe->xclient;
- if (((Atom)xcme.data.l[0]) == m_delete_window_atom) {
+ if (((Atom)xcme.data.l[0]) == m_atom.WM_DELETE_WINDOW) {
g_event = new
GHOST_Event(
getMilliSeconds(),
@@ -819,7 +977,7 @@ GHOST_SystemX11::processEvent(XEvent *xe)
window
);
}
- else if (((Atom)xcme.data.l[0]) == m_wm_take_focus) {
+ else if (((Atom)xcme.data.l[0]) == m_atom.WM_TAKE_FOCUS) {
XWindowAttributes attr;
Window fwin;
int revert_to;
@@ -983,31 +1141,31 @@ GHOST_SystemX11::processEvent(XEvent *xe)
default: {
#ifdef WITH_X11_XINPUT
- if (xe->type == window->GetXTablet().MotionEvent) {
+ if (xe->type == m_xtablet.MotionEvent) {
XDeviceMotionEvent *data = (XDeviceMotionEvent *)xe;
/* stroke might begin without leading ProxyIn event,
* this happens when window is opened when stylus is already hovering
* around tablet surface */
- setTabletMode(window, data->deviceid);
+ setTabletMode(this, window, data->deviceid);
- window->GetXTablet().CommonData.Pressure =
- data->axis_data[2] / ((float)window->GetXTablet().PressureLevels);
+ window->GetTabletData()->Pressure =
+ data->axis_data[2] / ((float)m_xtablet.PressureLevels);
/* the (short) cast and the &0xffff is bizarre and unexplained anywhere,
* but I got garbage data without it. Found it in the xidump.c source --matt */
- window->GetXTablet().CommonData.Xtilt =
- (short)(data->axis_data[3] & 0xffff) / ((float)window->GetXTablet().XtiltLevels);
- window->GetXTablet().CommonData.Ytilt =
- (short)(data->axis_data[4] & 0xffff) / ((float)window->GetXTablet().YtiltLevels);
+ window->GetTabletData()->Xtilt =
+ (short)(data->axis_data[3] & 0xffff) / ((float)m_xtablet.XtiltLevels);
+ window->GetTabletData()->Ytilt =
+ (short)(data->axis_data[4] & 0xffff) / ((float)m_xtablet.YtiltLevels);
}
- else if (xe->type == window->GetXTablet().ProxInEvent) {
+ else if (xe->type == m_xtablet.ProxInEvent) {
XProximityNotifyEvent *data = (XProximityNotifyEvent *)xe;
- setTabletMode(window, data->deviceid);
+ setTabletMode(this, window, data->deviceid);
}
- else if (xe->type == window->GetXTablet().ProxOutEvent) {
- window->GetXTablet().CommonData.Active = GHOST_kTabletModeNone;
+ else if (xe->type == m_xtablet.ProxOutEvent) {
+ window->GetTabletData()->Active = GHOST_kTabletModeNone;
}
#endif // WITH_X11_XINPUT
break;
@@ -1372,7 +1530,7 @@ void GHOST_SystemX11::getClipboard_xcout(XEvent evt,
}
/* Send a selection request */
- XConvertSelection(m_display, sel, target, m_xclip_out, win, CurrentTime);
+ XConvertSelection(m_display, sel, target, m_atom.XCLIP_OUT, win, CurrentTime);
*context = XCLIB_XCOUT_SENTCONVSEL;
return;
@@ -1380,28 +1538,28 @@ void GHOST_SystemX11::getClipboard_xcout(XEvent evt,
if (evt.type != SelectionNotify)
return;
- if (target == m_utf8_string && evt.xselection.property == None) {
+ if (target == m_atom.UTF8_STRING && evt.xselection.property == None) {
*context = XCLIB_XCOUT_FALLBACK_UTF8;
return;
}
- else if (target == m_compound_text && evt.xselection.property == None) {
+ else if (target == m_atom.COMPOUND_TEXT && evt.xselection.property == None) {
*context = XCLIB_XCOUT_FALLBACK_COMP;
return;
}
- else if (target == m_text && evt.xselection.property == None) {
+ else if (target == m_atom.TEXT && evt.xselection.property == None) {
*context = XCLIB_XCOUT_FALLBACK_TEXT;
return;
}
/* find the size and format of the data in property */
- XGetWindowProperty(m_display, win, m_xclip_out, 0, 0, False,
+ XGetWindowProperty(m_display, win, m_atom.XCLIP_OUT, 0, 0, False,
AnyPropertyType, &pty_type, &pty_format,
&pty_items, &pty_size, &buffer);
XFree(buffer);
- if (pty_type == m_incr) {
+ if (pty_type == m_atom.INCR) {
/* start INCR mechanism by deleting property */
- XDeleteProperty(m_display, win, m_xclip_out);
+ XDeleteProperty(m_display, win, m_atom.XCLIP_OUT);
XFlush(m_display);
*context = XCLIB_XCOUT_INCR;
return;
@@ -1416,12 +1574,12 @@ void GHOST_SystemX11::getClipboard_xcout(XEvent evt,
}
// not using INCR mechanism, just read the property
- XGetWindowProperty(m_display, win, m_xclip_out, 0, (long) pty_size,
+ XGetWindowProperty(m_display, win, m_atom.XCLIP_OUT, 0, (long) pty_size,
False, AnyPropertyType, &pty_type,
&pty_format, &pty_items, &pty_size, &buffer);
/* finished with property, delete it */
- XDeleteProperty(m_display, win, m_xclip_out);
+ XDeleteProperty(m_display, win, m_atom.XCLIP_OUT);
/* copy the buffer to the pointer for returned data */
ltxt = (unsigned char *) malloc(pty_items);
@@ -1454,7 +1612,7 @@ void GHOST_SystemX11::getClipboard_xcout(XEvent evt,
return;
/* check size and format of the property */
- XGetWindowProperty(m_display, win, m_xclip_out, 0, 0, False,
+ XGetWindowProperty(m_display, win, m_atom.XCLIP_OUT, 0, 0, False,
AnyPropertyType, &pty_type, &pty_format,
&pty_items, &pty_size, &buffer);
@@ -1463,14 +1621,14 @@ void GHOST_SystemX11::getClipboard_xcout(XEvent evt,
* to tell the other X client that we have read
* it and to send the next property */
XFree(buffer);
- XDeleteProperty(m_display, win, m_xclip_out);
+ XDeleteProperty(m_display, win, m_atom.XCLIP_OUT);
return;
}
if (pty_size == 0) {
/* no more data, exit from loop */
XFree(buffer);
- XDeleteProperty(m_display, win, m_xclip_out);
+ XDeleteProperty(m_display, win, m_atom.XCLIP_OUT);
*context = XCLIB_XCOUT_NONE;
/* this means that an INCR transfer is now
@@ -1482,7 +1640,7 @@ void GHOST_SystemX11::getClipboard_xcout(XEvent evt,
/* if we have come this far, the property contains
* text, we know the size. */
- XGetWindowProperty(m_display, win, m_xclip_out, 0, (long) pty_size,
+ XGetWindowProperty(m_display, win, m_atom.XCLIP_OUT, 0, (long) pty_size,
False, AnyPropertyType, &pty_type, &pty_format,
&pty_items, &pty_size, &buffer);
@@ -1503,7 +1661,7 @@ void GHOST_SystemX11::getClipboard_xcout(XEvent evt,
XFree(buffer);
/* delete property to get the next item */
- XDeleteProperty(m_display, win, m_xclip_out);
+ XDeleteProperty(m_display, win, m_atom.XCLIP_OUT);
XFlush(m_display);
return;
}
@@ -1513,7 +1671,7 @@ void GHOST_SystemX11::getClipboard_xcout(XEvent evt,
GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const
{
Atom sseln;
- Atom target = m_utf8_string;
+ Atom target = m_atom.UTF8_STRING;
Window owner;
/* from xclip.c doOut() v0.11 */
@@ -1523,9 +1681,9 @@ GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const
unsigned int context = XCLIB_XCOUT_NONE;
if (selection == True)
- sseln = m_primary;
+ sseln = m_atom.PRIMARY;
else
- sseln = m_clipboard;
+ sseln = m_atom.CLIPBOARD;
vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
@@ -1535,7 +1693,7 @@ GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const
/* check if we are the owner. */
owner = XGetSelectionOwner(m_display, sseln);
if (owner == win) {
- if (sseln == m_clipboard) {
+ if (sseln == m_atom.CLIPBOARD) {
sel_buf = (unsigned char *)malloc(strlen(txt_cut_buffer) + 1);
strcpy((char *)sel_buf, txt_cut_buffer);
return sel_buf;
@@ -1560,19 +1718,19 @@ GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const
/* fallback is needed. set XA_STRING to target and restart the loop. */
if (context == XCLIB_XCOUT_FALLBACK) {
context = XCLIB_XCOUT_NONE;
- target = m_string;
+ target = m_atom.STRING;
continue;
}
else if (context == XCLIB_XCOUT_FALLBACK_UTF8) {
/* utf8 fail, move to compouned text. */
context = XCLIB_XCOUT_NONE;
- target = m_compound_text;
+ target = m_atom.COMPOUND_TEXT;
continue;
}
else if (context == XCLIB_XCOUT_FALLBACK_COMP) {
/* compouned text faile, move to text. */
context = XCLIB_XCOUT_NONE;
- target = m_text;
+ target = m_atom.TEXT;
continue;
}
@@ -1589,7 +1747,7 @@ GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const
memcpy((char *)tmp_data, (char *)sel_buf, sel_len);
tmp_data[sel_len] = '\0';
- if (sseln == m_string)
+ if (sseln == m_atom.STRING)
XFree(sel_buf);
else
free(sel_buf);
@@ -1610,8 +1768,8 @@ void GHOST_SystemX11::putClipboard(GHOST_TInt8 *buffer, bool selection) const
if (buffer) {
if (selection == False) {
- XSetSelectionOwner(m_display, m_clipboard, m_window, CurrentTime);
- owner = XGetSelectionOwner(m_display, m_clipboard);
+ XSetSelectionOwner(m_display, m_atom.CLIPBOARD, m_window, CurrentTime);
+ owner = XGetSelectionOwner(m_display, m_atom.CLIPBOARD);
if (txt_cut_buffer)
free((void *)txt_cut_buffer);
@@ -1619,8 +1777,8 @@ void GHOST_SystemX11::putClipboard(GHOST_TInt8 *buffer, bool selection) const
strcpy(txt_cut_buffer, buffer);
}
else {
- XSetSelectionOwner(m_display, m_primary, m_window, CurrentTime);
- owner = XGetSelectionOwner(m_display, m_primary);
+ XSetSelectionOwner(m_display, m_atom.PRIMARY, m_window, CurrentTime);
+ owner = XGetSelectionOwner(m_display, m_atom.PRIMARY);
if (txt_select_buffer)
free((void *)txt_select_buffer);
@@ -1648,3 +1806,208 @@ GHOST_TSuccess GHOST_SystemX11::pushDragDropEvent(GHOST_TEventType eventType,
);
}
#endif
+
+#ifdef WITH_X11_XINPUT
+/*
+ * 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)
+{
+ fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n",
+ theEvent->error_code, theEvent->request_code);
+
+ /* No exit! - but keep lint happy */
+ return 0;
+}
+
+int GHOST_X11_ApplicationIOErrorHandler(Display *display)
+{
+ fprintf(stderr, "Ignoring Xlib error: error IO\n");
+
+ /* No exit! - but keep lint happy */
+ return 0;
+}
+
+/* These C functions are copied from Wine 1.1.13's wintab.c */
+#define BOOL int
+#define TRUE 1
+#define FALSE 0
+
+static bool match_token(const char *haystack, const char *needle)
+{
+ const char *p, *q;
+ for (p = haystack; *p; )
+ {
+ while (*p && isspace(*p))
+ p++;
+ if (!*p)
+ break;
+
+ for (q = needle; *q && *p && tolower(*p) == tolower(*q); q++)
+ p++;
+ if (!*q && (isspace(*p) || !*p))
+ return TRUE;
+
+ while (*p && !isspace(*p))
+ p++;
+ }
+ return FALSE;
+}
+
+
+/* Determining if an X device is a Tablet style device is an imperfect science.
+ * We rely on common conventions around device names as well as the type reported
+ * by Wacom tablets. This code will likely need to be expanded for alternate tablet types
+ *
+ * Wintab refers to any device that interacts with the tablet as a cursor,
+ * (stylus, eraser, tablet mouse, airbrush, etc)
+ * this is not to be confused with wacom x11 configuration "cursor" device.
+ * Wacoms x11 config "cursor" refers to its device slot (which we mirror with
+ * our gSysCursors) for puck like devices (tablet mice essentially).
+ */
+#if 0 // unused
+static BOOL is_tablet_cursor(const char *name, const char *type)
+{
+ int i;
+ static const char *tablet_cursor_whitelist[] = {
+ "wacom",
+ "wizardpen",
+ "acecad",
+ "tablet",
+ "cursor",
+ "stylus",
+ "eraser",
+ "pad",
+ NULL
+ };
+
+ for (i = 0; tablet_cursor_whitelist[i] != NULL; i++) {
+ if (name && match_token(name, tablet_cursor_whitelist[i]))
+ return TRUE;
+ if (type && match_token(type, tablet_cursor_whitelist[i]))
+ return TRUE;
+ }
+ return FALSE;
+}
+#endif
+static BOOL is_stylus(const char *name, const char *type)
+{
+ int i;
+ static const char *tablet_stylus_whitelist[] = {
+ "stylus",
+ "wizardpen",
+ "acecad",
+ NULL
+ };
+
+ for (i = 0; tablet_stylus_whitelist[i] != NULL; i++) {
+ if (name && match_token(name, tablet_stylus_whitelist[i]))
+ return TRUE;
+ if (type && match_token(type, tablet_stylus_whitelist[i]))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static BOOL is_eraser(const char *name, const char *type)
+{
+ if (name && match_token(name, "eraser"))
+ return TRUE;
+ if (type && match_token(type, "eraser"))
+ return TRUE;
+ return FALSE;
+}
+#undef BOOL
+#undef TRUE
+#undef FALSE
+/* end code copied from wine */
+
+void GHOST_SystemX11::initXInputDevices()
+{
+ static XErrorHandler old_handler = (XErrorHandler) 0;
+ static XIOErrorHandler old_handler_io = (XIOErrorHandler) 0;
+
+ XExtensionVersion *version = XGetExtensionVersion(m_display, INAME);
+
+ if (version && (version != (XExtensionVersion *)NoSuchExtension)) {
+ if (version->present) {
+ int device_count;
+ XDeviceInfo *device_info = XListInputDevices(m_display, &device_count);
+ m_xtablet.StylusDevice = NULL;
+ m_xtablet.EraserDevice = NULL;
+
+ /* Install our error handler to override Xlib's termination behavior */
+ old_handler = XSetErrorHandler(GHOST_X11_ApplicationErrorHandler);
+ old_handler_io = XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler);
+
+ for (int i = 0; i < device_count; ++i) {
+ char *device_type = device_info[i].type ? XGetAtomName(m_display, device_info[i].type) : NULL;
+
+// printf("Tablet type:'%s', name:'%s', index:%d\n", device_type, device_info[i].name, i);
+
+
+ if ((m_xtablet.StylusDevice == NULL) &&
+ (is_stylus(device_info[i].name, device_type) || (device_info[i].type == m_atom.TABLET)))
+ {
+// printf("\tfound stylus\n");
+ m_xtablet.StylusID = device_info[i].id;
+ m_xtablet.StylusDevice = XOpenDevice(m_display, m_xtablet.StylusID);
+
+ if (m_xtablet.StylusDevice != NULL) {
+ /* Find how many pressure levels tablet has */
+ XAnyClassPtr ici = device_info[i].inputclassinfo;
+ for (int j = 0; j < m_xtablet.StylusDevice->num_classes; ++j) {
+ if (ici->c_class == ValuatorClass) {
+// printf("\t\tfound ValuatorClass\n");
+ XValuatorInfo *xvi = (XValuatorInfo *)ici;
+ m_xtablet.PressureLevels = xvi->axes[2].max_value;
+
+ if (xvi->num_axes > 3) {
+ /* this is assuming that the tablet has the same tilt resolution in both
+ * positive and negative directions. It would be rather weird if it didn't.. */
+ m_xtablet.XtiltLevels = xvi->axes[3].max_value;
+ m_xtablet.YtiltLevels = xvi->axes[4].max_value;
+ }
+ else {
+ m_xtablet.XtiltLevels = 0;
+ m_xtablet.YtiltLevels = 0;
+ }
+
+ break;
+ }
+
+ ici = (XAnyClassPtr)(((char *)ici) + ici->length);
+ }
+ }
+ else {
+ m_xtablet.StylusID = 0;
+ }
+ }
+ else if ((m_xtablet.EraserDevice == NULL) &&
+ (is_eraser(device_info[i].name, device_type)))
+ {
+// printf("\tfound eraser\n");
+ m_xtablet.EraserID = device_info[i].id;
+ m_xtablet.EraserDevice = XOpenDevice(m_display, m_xtablet.EraserID);
+ if (m_xtablet.EraserDevice == NULL) m_xtablet.EraserID = 0;
+ }
+
+ if (device_type) {
+ XFree((void *)device_type);
+ }
+ }
+
+ /* Restore handler */
+ (void) XSetErrorHandler(old_handler);
+ (void) XSetIOErrorHandler(old_handler_io);
+
+ XFreeDeviceList(device_info);
+ }
+ XFree(version);
+ }
+}
+
+#endif /* WITH_X11_XINPUT */
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index 02c0109085a..6a492f64b41 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -39,11 +39,19 @@
#include "GHOST_System.h"
#include "../GHOST_Types.h"
+// For tablets
+#ifdef WITH_X11_XINPUT
+# include <X11/extensions/XInput.h>
+#endif
+
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
# define GHOST_X11_RES_NAME "Blender" /* res_name */
# define GHOST_X11_RES_CLASS "Blender" /* res_class */
#endif
+/* generic error handlers */
+int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent);
+int GHOST_X11_ApplicationIOErrorHandler(Display *display);
class GHOST_WindowX11;
@@ -109,6 +117,16 @@ public:
) const;
/**
+ * Returns the dimensions of all displays on this system.
+ * \return The dimension of the main display.
+ */
+ void
+ getAllDisplayDimensions(
+ GHOST_TUns32& width,
+ GHOST_TUns32& height
+ ) const;
+
+ /**
* Create a new window.
* The new window is added to the list of windows managed.
* Never explicitly delete the window, use disposeWindow() instead.
@@ -119,7 +137,9 @@ 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 stereoVisual Create a stereo visual for quad buffered stereo.
+ * \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).
*/
@@ -133,6 +153,7 @@ public:
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
const bool stereoVisual,
+ const bool exclusive = false,
const GHOST_TUns16 numOfAASamples = 0,
const GHOST_TEmbedderWindowID parentWindow = 0
);
@@ -256,33 +277,59 @@ public:
return 0;
}
- /**
- * Atom used for ICCCM, WM-spec and Motif.
- * We only need get this atom at the start, it's relative
- * to the display not the window and are public for every
- * window that need it.
- */
- Atom m_wm_state;
- Atom m_wm_change_state;
- Atom m_net_state;
- Atom m_net_max_horz;
- Atom m_net_max_vert;
- Atom m_net_fullscreen;
- Atom m_motif;
- Atom m_wm_take_focus;
- Atom m_wm_protocols;
- Atom m_delete_window_atom;
-
- /* Atoms for Selection, copy & paste. */
- Atom m_targets;
- Atom m_string;
- Atom m_compound_text;
- Atom m_text;
- Atom m_clipboard;
- Atom m_primary;
- Atom m_xclip_out;
- Atom m_incr;
- Atom m_utf8_string;
+#ifdef WITH_X11_XINPUT
+ typedef struct GHOST_TabletX11 {
+ XDevice *StylusDevice;
+ XDevice *EraserDevice;
+
+ XID StylusID, EraserID;
+
+ int MotionEvent;
+ int ProxInEvent;
+ int ProxOutEvent;
+
+ int PressureLevels;
+ int XtiltLevels, YtiltLevels;
+ } GHOST_TabletX11;
+
+ GHOST_TabletX11 &GetXTablet()
+ {
+ return m_xtablet;
+ }
+#endif // WITH_X11_XINPUT
+
+ struct {
+ /**
+ * Atom used for ICCCM, WM-spec and Motif.
+ * We only need get this atom at the start, it's relative
+ * to the display not the window and are public for every
+ * window that need it.
+ */
+ Atom WM_STATE;
+ Atom WM_CHANGE_STATE;
+ Atom _NET_WM_STATE;
+ Atom _NET_WM_STATE_MAXIMIZED_HORZ;
+ Atom _NET_WM_STATE_MAXIMIZED_VERT;
+ Atom _NET_WM_STATE_FULLSCREEN;
+ Atom _MOTIF_WM_HINTS;
+ Atom WM_TAKE_FOCUS;
+ Atom WM_PROTOCOLS;
+ Atom WM_DELETE_WINDOW;
+
+ /* Atoms for Selection, copy & paste. */
+ Atom TARGETS;
+ Atom STRING;
+ Atom COMPOUND_TEXT;
+ Atom TEXT;
+ Atom CLIPBOARD;
+ Atom PRIMARY;
+ Atom XCLIP_OUT;
+ Atom INCR;
+ Atom UTF8_STRING;
+#ifdef WITH_X11_XINPUT
+ Atom TABLET;
+#endif
+ } m_atom;
private:
@@ -291,6 +338,11 @@ private:
XIM m_xim;
#endif
+#ifdef WITH_X11_XINPUT
+ /* Tablet devices */
+ GHOST_TabletX11 m_xtablet;
+#endif
+
/// The vector of windows that need to be updated.
std::vector<GHOST_WindowX11 *> m_dirty_windows;
@@ -313,6 +365,10 @@ private:
bool openX11_IM();
#endif
+#ifdef WITH_X11_XINPUT
+ void initXInputDevices();
+#endif
+
GHOST_WindowX11 *
findGhostWindow(
Window xwind
diff --git a/intern/ghost/intern/GHOST_TimerManager.cpp b/intern/ghost/intern/GHOST_TimerManager.cpp
index 601359984de..8cba0608f2b 100644
--- a/intern/ghost/intern/GHOST_TimerManager.cpp
+++ b/intern/ghost/intern/GHOST_TimerManager.cpp
@@ -90,7 +90,7 @@ GHOST_TSuccess GHOST_TimerManager::removeTimer(GHOST_TimerTask *timer)
// Remove the timer task
m_timers.erase(iter);
delete timer;
- timer = 0;
+ timer = NULL;
success = GHOST_kSuccess;
}
else {
diff --git a/intern/ghost/intern/GHOST_TimerTask.h b/intern/ghost/intern/GHOST_TimerTask.h
index 0731bc066af..e8f5ecd9fbb 100644
--- a/intern/ghost/intern/GHOST_TimerTask.h
+++ b/intern/ghost/intern/GHOST_TimerTask.h
@@ -54,7 +54,7 @@ public:
GHOST_TimerTask(GHOST_TUns64 start,
GHOST_TUns64 interval,
GHOST_TimerProcPtr timerProc,
- GHOST_TUserDataPtr userData = 0)
+ GHOST_TUserDataPtr userData = NULL)
: m_start(start),
m_interval(interval),
m_next(start),
diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp
index fd3ff4f85f0..6c2d7350cd9 100644
--- a/intern/ghost/intern/GHOST_Window.cpp
+++ b/intern/ghost/intern/GHOST_Window.cpp
@@ -45,6 +45,7 @@ GHOST_Window::GHOST_Window(
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
const bool stereoVisual,
+ const bool exclusive,
const GHOST_TUns16 numOfAASamples)
:
m_drawingContextType(type),
@@ -61,6 +62,8 @@ GHOST_Window::GHOST_Window(
m_cursorGrabAccumPos[0] = 0;
m_cursorGrabAccumPos[1] = 0;
+
+ m_nativePixelSize = 1.0f;
m_fullScreen = state == GHOST_kWindowStateFullScreen;
if (m_fullScreen) {
@@ -194,3 +197,4 @@ bool GHOST_Window::getModifiedState()
{
return m_isUnsavedChanges;
}
+
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index fd870327fd4..588de0911e3 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -80,6 +80,8 @@ public:
* \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 exclusive Use to show the window ontop and ignore others
+ * (used fullscreen).
* \param numOfAASamples Number of samples used for AA (zero if no AA)
*/
GHOST_Window(
@@ -88,6 +90,7 @@ public:
GHOST_TWindowState state,
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
const bool stereoVisual = false,
+ const bool exclusive = false,
const GHOST_TUns16 numOfAASamples = 0);
/**
@@ -257,6 +260,13 @@ public:
{
m_userData = userData;
}
+
+ virtual float getNativePixelSize(void)
+ {
+ if (m_nativePixelSize > 0.0f)
+ return m_nativePixelSize;
+ return 1.0f;
+ }
protected:
/**
@@ -351,6 +361,9 @@ protected:
GHOST_TUns32 m_fullScreenWidth;
/** Full-screen height */
GHOST_TUns32 m_fullScreenHeight;
+
+ /* OSX only, retina screens */
+ float m_nativePixelSize;
};
diff --git a/intern/ghost/intern/GHOST_WindowCarbon.cpp b/intern/ghost/intern/GHOST_WindowCarbon.cpp
index 99d8854667e..36d45b4790c 100644
--- a/intern/ghost/intern/GHOST_WindowCarbon.cpp
+++ b/intern/ghost/intern/GHOST_WindowCarbon.cpp
@@ -182,7 +182,8 @@ GHOST_WindowCarbon::GHOST_WindowCarbon(
(SInt32) this); // Store a pointer to the class in the refCon
#endif
//GHOST_PRINT("GHOST_WindowCarbon::GHOST_WindowCarbon(): creating full-screen OpenGL context\n");
- setDrawingContextType(GHOST_kDrawingContextTypeOpenGL);; installDrawingContext(GHOST_kDrawingContextTypeOpenGL);
+ setDrawingContextType(GHOST_kDrawingContextTypeOpenGL);
+ installDrawingContext(GHOST_kDrawingContextTypeOpenGL);
updateDrawingContext();
activateDrawingContext();
diff --git a/intern/ghost/intern/GHOST_WindowCarbon.h b/intern/ghost/intern/GHOST_WindowCarbon.h
index d25d57156f6..16f305e93c5 100644
--- a/intern/ghost/intern/GHOST_WindowCarbon.h
+++ b/intern/ghost/intern/GHOST_WindowCarbon.h
@@ -220,6 +220,11 @@ public:
{
return m_tablet;
}
+
+ GHOST_TSuccess beginFullScreen() const {return GHOST_kFailure;}
+
+ GHOST_TSuccess endFullScreen() const {return GHOST_kFailure;}
+
protected:
/**
* Tries to install a rendering context in this window.
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h
index 3e5c675d4a7..fe0830edeae 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.h
+++ b/intern/ghost/intern/GHOST_WindowCocoa.h
@@ -262,6 +262,15 @@ public:
* Hides the progress bar icon
*/
virtual GHOST_TSuccess endProgressBar();
+
+
+ virtual void setNativePixelSize(void);
+
+ GHOST_TSuccess beginFullScreen() const {return GHOST_kFailure;}
+
+ GHOST_TSuccess endFullScreen() const {return GHOST_kFailure;}
+
+
protected:
/**
* Tries to install a rendering context in this window.
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index a483c030b31..795b5200ae2 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -28,7 +28,7 @@
#include <Cocoa/Cocoa.h>
-#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5
+#if MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
//Use of the SetSystemUIMode function (64bit compatible)
#include <Carbon/Carbon.h>
#endif
@@ -58,24 +58,24 @@ extern "C" {
extern void wm_draw_update(bContext *C);
};*/
@interface CocoaWindowDelegate : NSObject
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
<NSWindowDelegate>
-#endif
{
GHOST_SystemCocoa *systemCocoa;
GHOST_WindowCocoa *associatedWindow;
}
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa;
-- (void)windowWillClose:(NSNotification *)notification;
- (void)windowDidBecomeKey:(NSNotification *)notification;
- (void)windowDidResignKey:(NSNotification *)notification;
- (void)windowDidExpose:(NSNotification *)notification;
- (void)windowDidResize:(NSNotification *)notification;
- (void)windowDidMove:(NSNotification *)notification;
- (void)windowWillMove:(NSNotification *)notification;
+- (BOOL)windowShouldClose:(id)sender;
+- (void)windowDidChangeBackingProperties:(NSNotification *)notification;
@end
+
@implementation CocoaWindowDelegate : NSObject
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa
{
@@ -83,11 +83,6 @@ extern "C" {
associatedWindow = winCocoa;
}
-- (void)windowWillClose:(NSNotification *)notification
-{
- systemCocoa->handleWindowEvent(GHOST_kEventWindowClose, associatedWindow);
-}
-
- (void)windowDidBecomeKey:(NSNotification *)notification
{
systemCocoa->handleWindowEvent(GHOST_kEventWindowActivate, associatedWindow);
@@ -115,12 +110,12 @@ extern "C" {
- (void)windowDidResize:(NSNotification *)notification
{
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
//if (![[notification object] inLiveResize]) {
//Send event only once, at end of resize operation (when user has released mouse button)
#endif
systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, associatedWindow);
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
//}
#endif
/* Live resize ugly patch. Needed because live resize runs in a modal loop, not letting main loop run
@@ -132,6 +127,19 @@ extern "C" {
wm_draw_update(ghostC);
}*/
}
+
+- (void)windowDidChangeBackingProperties:(NSNotification *)notification
+{
+ systemCocoa->handleWindowEvent(GHOST_kEventNativeResolutionChange, associatedWindow);
+}
+
+- (BOOL)windowShouldClose:(id)sender;
+{
+ //Let Blender close the window rather than closing immediately
+ systemCocoa->handleWindowEvent(GHOST_kEventWindowClose, associatedWindow);
+ return false;
+}
+
@end
#pragma mark NSWindow subclass
@@ -287,7 +295,7 @@ extern "C" {
}
}
-#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
+#if MAC_OS_X_VERSION_MIN_REQUIRED <= 1040
//Cmd+key are handled differently before 10.5
- (BOOL)performKeyEquivalent:(NSEvent *)theEvent
{
@@ -425,6 +433,14 @@ extern "C" {
#pragma mark initialization / finalization
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
+@interface NSView (NSOpenGLSurfaceResolution)
+- (BOOL)wantsBestResolutionOpenGLSurface;
+- (void)setWantsBestResolutionOpenGLSurface:(BOOL)flag;
+- (NSRect)convertRectToBacking:(NSRect)bounds;
+@end
+#endif
+
NSOpenGLContext* GHOST_WindowCocoa::s_firstOpenGLcontext = nil;
GHOST_WindowCocoa::GHOST_WindowCocoa(
@@ -498,6 +514,8 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize;
pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
+ pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccumSize;
+ pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo;
@@ -540,6 +558,9 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize;
pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
+
+ pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccumSize;
+ pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo;
@@ -571,13 +592,20 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
[m_window setContentView:m_openGLView];
[m_window setInitialFirstResponder:m_openGLView];
- [m_window setReleasedWhenClosed:NO]; //To avoid bad pointer exception in case of user closing the window
-
[m_window makeKeyAndOrderFront:nil];
setDrawingContextType(type);
updateDrawingContext();
activateDrawingContext();
+
+ if (m_systemCocoa->m_nativePixel) {
+ if ([m_openGLView respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) {
+ [m_openGLView setWantsBestResolutionOpenGLSurface:YES];
+
+ NSRect backingBounds = [m_openGLView convertRectToBacking:[m_openGLView bounds]];
+ m_nativePixelSize = (float)backingBounds.size.width / (float)rect.size.width;
+ }
+ }
m_tablet.Active = GHOST_kTabletModeNone;
@@ -587,9 +615,20 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
[m_window setAcceptsMouseMovedEvents:YES];
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
+ NSView *view = [m_window contentView];
+ [view setAcceptsTouchEvents:YES];
+#endif
+
[m_window registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType,
NSStringPboardType, NSTIFFPboardType, nil]];
-
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
+ if (state != GHOST_kWindowStateFullScreen) {
+ [m_window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
+ }
+#endif
+
if (state == GHOST_kWindowStateFullScreen)
setState(GHOST_kWindowStateFullScreen);
@@ -609,20 +648,20 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa()
[m_openGLView release];
if (m_window) {
- // previously we called [m_window release], but on 10.8 this does not
- // remove the window from [NSApp orderedWindows] and perhaps other
- // places, leading to crashes. so instead we set setReleasedWhenClosed
- // back to YES right before closing
- [m_window setReleasedWhenClosed:YES];
[m_window close];
- m_window = nil;
}
- //Check for other blender opened windows and make the frontmost key
+ // Check for other blender opened windows and make the frontmost key
+ // Note: for some reason the closed window is still in the list
NSArray *windowsList = [NSApp orderedWindows];
- if ([windowsList count]) {
- [[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil];
+ for (int a = 0; a < [windowsList count]; a++) {
+ if (m_window != (CocoaWindow *)[windowsList objectAtIndex:a]) {
+ [[windowsList objectAtIndex:a] makeKeyWindow];
+ break;
+ }
}
+ m_window = nil;
+
[pool drain];
}
@@ -888,6 +927,19 @@ NSScreen* GHOST_WindowCocoa::getScreen()
return [m_window screen];
}
+/* called for event, when window leaves monitor to another */
+void GHOST_WindowCocoa::setNativePixelSize(void)
+{
+ /* make sure 10.6 keeps running */
+ if ([m_openGLView respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) {
+ NSRect backingBounds = [m_openGLView convertRectToBacking:[m_openGLView bounds]];
+
+ GHOST_Rect rect;
+ getClientBounds(rect);
+
+ m_nativePixelSize = (float)backingBounds.size.width / (float)rect.getWidth();
+ }
+}
/**
* \note Fullscreen switch is not actual fullscreen with display capture.
@@ -916,11 +968,11 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
* doesn't know view/window difference. */
m_fullScreen = true;
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
//10.6 provides Cocoa functions to autoshow menu bar, and to change a window style
- //Hide menu & dock if needed
+ //Hide menu & dock if on primary screen. else only menu
if ([[m_window screen] isEqual:[[NSScreen screens] objectAtIndex:0]]) {
- [NSApp setPresentationOptions:(NSApplicationPresentationHideDock | NSApplicationPresentationAutoHideMenuBar)];
+ [NSApp setPresentationOptions:(NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar)];
}
//Make window borderless and enlarge it
[m_window setStyleMask:NSBorderlessWindowMask];
@@ -943,7 +995,6 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
//Copy current window parameters
[tmpWindow setTitle:[m_window title]];
[tmpWindow setRepresentedFilename:[m_window representedFilename]];
- [tmpWindow setReleasedWhenClosed:NO];
[tmpWindow setAcceptsMouseMovedEvents:YES];
[tmpWindow setDelegate:[m_window delegate]];
[tmpWindow setSystemAndWindowCocoa:[m_window systemCocoa] windowCocoa:this];
@@ -956,9 +1007,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
//Show the new window
[tmpWindow makeKeyAndOrderFront:m_openGLView];
//Close and release old window
- [m_window setDelegate:nil]; // To avoid the notification of "window closed" event
[m_window close];
- [m_window release];
m_window = tmpWindow;
#endif
@@ -975,7 +1024,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
m_fullScreen = false;
//Exit fullscreen
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
//Show again menu & dock if needed
if ([[m_window screen] isEqual:[NSScreen mainScreen]]) {
[NSApp setPresentationOptions:NSApplicationPresentationDefault];
@@ -1001,7 +1050,6 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
//Copy current window parameters
[tmpWindow setTitle:[m_window title]];
[tmpWindow setRepresentedFilename:[m_window representedFilename]];
- [tmpWindow setReleasedWhenClosed:NO];
[tmpWindow setAcceptsMouseMovedEvents:YES];
[tmpWindow setDelegate:[m_window delegate]];
[tmpWindow setSystemAndWindowCocoa:[m_window systemCocoa] windowCocoa:this];
@@ -1016,9 +1064,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
//Show the new window
[tmpWindow makeKeyAndOrderFront:nil];
//Close and release old window
- [m_window setDelegate:nil]; // To avoid the notification of "window closed" event
[m_window close];
- [m_window release];
m_window = tmpWindow;
#endif
diff --git a/intern/ghost/intern/GHOST_WindowManager.cpp b/intern/ghost/intern/GHOST_WindowManager.cpp
index daf1c2f2d22..1f20e01ca73 100644
--- a/intern/ghost/intern/GHOST_WindowManager.cpp
+++ b/intern/ghost/intern/GHOST_WindowManager.cpp
@@ -130,12 +130,12 @@ GHOST_TSuccess GHOST_WindowManager::beginFullScreen(GHOST_IWindow *window,
m_fullScreenWindow = window;
m_activeWindowBeforeFullScreen = getActiveWindow();
setActiveWindow(m_fullScreenWindow);
+ m_fullScreenWindow->beginFullScreen();
success = GHOST_kSuccess;
}
return success;
}
-
GHOST_TSuccess GHOST_WindowManager::endFullScreen(void)
{
GHOST_TSuccess success = GHOST_kFailure;
@@ -143,6 +143,7 @@ GHOST_TSuccess GHOST_WindowManager::endFullScreen(void)
if (m_fullScreenWindow != 0) {
//GHOST_PRINT("GHOST_WindowManager::endFullScreen(): deleting full-screen window\n");
setWindowInactive(m_fullScreenWindow);
+ m_fullScreenWindow->endFullScreen();
delete m_fullScreenWindow;
//GHOST_PRINT("GHOST_WindowManager::endFullScreen(): done\n");
m_fullScreenWindow = 0;
diff --git a/intern/ghost/intern/GHOST_WindowSDL.cpp b/intern/ghost/intern/GHOST_WindowSDL.cpp
index 6641b28a20e..47f41ea40a9 100644
--- a/intern/ghost/intern/GHOST_WindowSDL.cpp
+++ b/intern/ghost/intern/GHOST_WindowSDL.cpp
@@ -41,10 +41,11 @@ GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system,
const GHOST_TEmbedderWindowID parentWindow,
GHOST_TDrawingContextType type,
const bool stereoVisual,
+ const bool exclusive,
const GHOST_TUns16 numOfAASamples
)
:
- GHOST_Window(width, height, state, type, stereoVisual, numOfAASamples),
+ GHOST_Window(width, height, state, type, stereoVisual, exclusive, numOfAASamples),
m_system(system),
m_invalid_window(false),
m_sdl_custom_cursor(NULL)
diff --git a/intern/ghost/intern/GHOST_WindowSDL.h b/intern/ghost/intern/GHOST_WindowSDL.h
index a39d9878ddd..8260a318cea 100644
--- a/intern/ghost/intern/GHOST_WindowSDL.h
+++ b/intern/ghost/intern/GHOST_WindowSDL.h
@@ -41,6 +41,7 @@ extern "C" {
#endif
class STR_String;
+class GHOST_SystemSDL;
class GHOST_WindowSDL : public GHOST_Window
{
@@ -64,9 +65,10 @@ public:
GHOST_TUns32 width, GHOST_TUns32 height,
GHOST_TWindowState state,
const GHOST_TEmbedderWindowID parentWindow,
- GHOST_TDrawingContextType type,
- const bool stereoVisual,
- const GHOST_TUns16 numOfAASamples
+ GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
+ const bool stereoVisual = false,
+ const bool exclusive = false,
+ const GHOST_TUns16 numOfAASamples = 0
);
~GHOST_WindowSDL();
@@ -166,6 +168,11 @@ protected:
return GHOST_kSuccess;
}
+ // TODO
+ GHOST_TSuccess beginFullScreen() const { return GHOST_kFailure; }
+
+ GHOST_TSuccess endFullScreen() const { return GHOST_kFailure; }
+
};
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index fead1884f8a..b1a9ca52605 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -104,13 +104,14 @@ static PIXELFORMATDESCRIPTOR sPreferredFormat = {
* can't be in multiple-devices configuration. */
static int is_crappy_intel_card(void)
{
- int crappy = 0;
- const char *vendor = (const char *)glGetString(GL_VENDOR);
+ static short is_crappy = -1;
- if (strstr(vendor, "Intel"))
- crappy = 1;
+ if (is_crappy == -1) {
+ const char *vendor = (const char *)glGetString(GL_VENDOR);
+ is_crappy = (strstr(vendor, "Intel") != NULL);
+ }
- return crappy;
+ return is_crappy;
}
GHOST_WindowWin32::GHOST_WindowWin32(
@@ -470,38 +471,22 @@ void GHOST_WindowWin32::getWindowBounds(GHOST_Rect& bounds) const
void GHOST_WindowWin32::getClientBounds(GHOST_Rect& bounds) const
{
RECT rect;
- GHOST_TWindowState state = this->getState();
- LONG_PTR result = ::GetWindowLongPtr(m_hWnd, GWL_STYLE);
- int sm_cysizeframe = GetSystemMetrics(SM_CYSIZEFRAME);
- ::GetWindowRect(m_hWnd, &rect);
+ POINT coord;
+ ::GetClientRect(m_hWnd, &rect);
- if ((result & (WS_POPUP | WS_MAXIMIZE)) != (WS_POPUP | WS_MAXIMIZE)) {
- if (state == GHOST_kWindowStateMaximized) {
- // in maximized state we don't have borders on the window
- bounds.m_b = rect.bottom - GetSystemMetrics(SM_CYCAPTION) - sm_cysizeframe * 2;
- bounds.m_l = rect.left + sm_cysizeframe;
- bounds.m_r = rect.right - sm_cysizeframe;
- bounds.m_t = rect.top;
- }
- else if (state == GHOST_kWindowStateEmbedded) {
- bounds.m_b = rect.bottom;
- bounds.m_l = rect.left;
- bounds.m_r = rect.right;
- bounds.m_t = rect.top;
- }
- else {
- bounds.m_b = rect.bottom - GetSystemMetrics(SM_CYCAPTION) - sm_cysizeframe * 2;
- bounds.m_l = rect.left;
- bounds.m_r = rect.right - sm_cysizeframe * 2;
- bounds.m_t = rect.top;
- }
- }
- else {
- bounds.m_b = rect.bottom;
- bounds.m_l = rect.left;
- bounds.m_r = rect.right;
- bounds.m_t = rect.top;
- }
+ coord.x = rect.left;
+ coord.y = rect.top;
+ ::ClientToScreen(m_hWnd, &coord);
+
+ bounds.m_l = coord.x;
+ bounds.m_t = coord.y;
+
+ coord.x = rect.right;
+ coord.y = rect.bottom;
+ ::ClientToScreen(m_hWnd, &coord);
+
+ bounds.m_r = coord.x;
+ bounds.m_b = coord.y;
}
@@ -712,6 +697,7 @@ GHOST_TSuccess GHOST_WindowWin32::initMultisample(PIXELFORMATDESCRIPTOR pfd)
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
WGL_COLOR_BITS_ARB, pfd.cColorBits,
WGL_DEPTH_BITS_ARB, pfd.cDepthBits,
+ WGL_ALPHA_BITS_ARB, pfd.cAlphaBits,
WGL_STENCIL_BITS_ARB, pfd.cStencilBits,
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
@@ -1192,6 +1178,16 @@ void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam)
}
}
+void GHOST_WindowWin32::bringTabletContextToFront()
+{
+ if (m_wintab) {
+ GHOST_WIN32_WTOverlap fpWTOverlap = (GHOST_WIN32_WTOverlap) ::GetProcAddress(m_wintab, "WTOverlap");
+ if (fpWTOverlap) {
+ fpWTOverlap(m_tablet, TRUE);
+ }
+ }
+}
+
/** Reverse the bits in a GHOST_TUns8 */
static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch)
{
@@ -1311,6 +1307,9 @@ static int WeightPixelFormat(PIXELFORMATDESCRIPTOR& pfd)
weight += pfd.cColorBits - 8;
+ if (pfd.cAlphaBits > 0)
+ weight ++;
+
/* want swap copy capability -- it matters a lot */
if (pfd.dwFlags & PFD_SWAP_COPY) weight += 16;
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index 9e4377b8225..2af4b703930 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -58,6 +58,7 @@ typedef UINT (API * GHOST_WIN32_WTInfo)(UINT, UINT, LPVOID);
typedef HCTX (API * GHOST_WIN32_WTOpen)(HWND, LPLOGCONTEXTA, BOOL);
typedef BOOL (API * GHOST_WIN32_WTClose)(HCTX);
typedef BOOL (API * GHOST_WIN32_WTPacket)(HCTX, UINT, LPVOID);
+typedef BOOL (API * GHOST_WIN32_WTOverlap)(HCTX, BOOL);
/**
* GHOST window on M$ Windows OSs.
@@ -273,6 +274,11 @@ public:
void processWin32TabletInitEvent();
void processWin32TabletEvent(WPARAM wParam, LPARAM lParam);
+ void bringTabletContextToFront();
+
+ GHOST_TSuccess beginFullScreen() const {return GHOST_kFailure;}
+
+ GHOST_TSuccess endFullScreen() const {return GHOST_kFailure;}
protected:
GHOST_TSuccess initMultisample(PIXELFORMATDESCRIPTOR pfd);
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index 156bc86869a..6c17e9e7159 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -79,74 +79,73 @@ typedef struct {
// #define _NET_WM_STATE_TOGGLE 2 // UNUSED
/*
- import bpy
- I = bpy.data.images['blender.png'] # the 48x48 icon
-
- # Write to a file that can be
- # used within static unsigned char BLENDER_ICON_48x48x24[] = {...}
- f = open('/myicon.txt', 'w')
- for j in xrange(48):
- for k in xrange(48):
- v = I.getPixelI(j,47-k)
- v.pop()
- for p in v:
- f.write(str(hex(p))+',')
-
- f.write('\n')
+ * import bpy
+ * ima = bpy.data.images["blender.png"]
+ * w, h = ima.size
+ * print("%d,%d," % (w, h))
+ * for y in range(h - 1, -1, -1):
+ * px = []
+ * for x in range(w):
+ * p = ((y * w) + x) * 4
+ * rgba = ima.pixels[p : p + 4]
+ * rgba = rgba[2], rgba[1], rgba[0], rgba[3]
+ * px.append(sum((int(p * 255) << (8 * i)) for i, p in enumerate(rgba)))
+ * print(", ".join([str(p) for p in px]), end=",\n")
*/
/* See the python script above to regenerate the 48x48 icon within blender */
#define BLENDER_ICON_WIDTH 48
#define BLENDER_ICON_HEIGHT 48
-static unsigned char BLENDER_ICON_48x48x24[] = {
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x4f, 0x2a, 0xd, 0xa7, 0x5b, 0x1f, 0xb8, 0x66, 0x22, 0x6c, 0x3b, 0x14, 0x5, 0x3, 0x1, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x6f, 0x3a, 0x13, 0xea, 0x7f, 0x2c, 0xee, 0x7e, 0x2b, 0xee, 0x7e, 0x2b, 0xef, 0x85, 0x2e, 0x5f, 0x35, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x43, 0x22, 0xb, 0xed, 0x7f, 0x2c, 0xed, 0x7c, 0x2b, 0xee, 0x7f, 0x2c, 0xee, 0x80, 0x2c, 0xee, 0x80, 0x2c, 0xa8, 0x5f, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x2e, 0x16, 0x6, 0xd0, 0x6f, 0x26, 0xed, 0x7b, 0x2a, 0xed, 0x7d, 0x2b, 0xee, 0x7f, 0x2c, 0xee, 0x80, 0x2c, 0xee, 0x82, 0x2d, 0x9a, 0x57, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x17, 0xb, 0x4, 0xb9, 0x60, 0x21, 0xed, 0x7a, 0x2a, 0xed, 0x7b, 0x2a, 0xed, 0x7e, 0x2b, 0xee, 0x7f, 0x2c, 0xee, 0x7f, 0x2c, 0xee, 0x86, 0x2e, 0x4e, 0x2b, 0xe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x1, 0x0, 0x0, 0x96, 0x4d, 0x19, 0xee, 0x7a, 0x2a, 0xed, 0x79, 0x2a, 0xed, 0x7c, 0x2b, 0xed, 0x7e, 0x2b, 0xed, 0x7e, 0x2b, 0xef, 0x83, 0x2d, 0x98, 0x55, 0x1c, 0x3, 0x1, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x20, 0xf, 0x5, 0x4b, 0x27, 0xe, 0x21, 0x11, 0x5, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x67, 0x34, 0x11, 0xed, 0x7b, 0x2a, 0xec, 0x79, 0x29, 0xed, 0x7b, 0x2a, 0xed, 0x7c, 0x2b, 0xed, 0x7d, 0x2b, 0xee, 0x7f, 0x2c, 0xbb, 0x69, 0x24, 0x11, 0x9, 0x3, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x38, 0x1c, 0x9, 0xc9, 0x6d, 0x2c, 0xf1, 0x86, 0x36, 0xd7, 0x79, 0x2a, 0x22, 0x12, 0x5, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x3b, 0x1d, 0x9, 0xe0, 0x74, 0x27, 0xed, 0x7a, 0x2a, 0xed, 0x7c, 0x2a, 0xed, 0x7d, 0x2b, 0xed, 0x7d, 0x2b, 0xed, 0x7d, 0x2b, 0xdc, 0x7a, 0x2a, 0x1e, 0xf, 0x5, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xa6, 0x56, 0x23, 0xee, 0x83, 0x3b, 0xed, 0x7d, 0x2c, 0xf0, 0x85, 0x2e, 0x75, 0x43, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x25, 0x12, 0x5, 0xc9, 0x68, 0x24, 0xed, 0x7b, 0x2a, 0xed, 0x7d, 0x2b, 0xed, 0x7e, 0x2b, 0xee, 0x7e, 0x2c, 0xed, 0x7d, 0x2b, 0xe3, 0x7d, 0x2b, 0x3b, 0x1f, 0xa, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x1c, 0xd, 0x4, 0xd9, 0x74, 0x35, 0xee, 0x83, 0x3a, 0xee, 0x7f, 0x2b, 0xf0, 0x86, 0x2e, 0x83, 0x4d, 0x1a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xa, 0x5, 0x1, 0xa1, 0x54, 0x1c, 0xee, 0x7e, 0x2c, 0xed, 0x7e, 0x2c, 0xed, 0x7f, 0x2c, 0xed, 0x80, 0x2c, 0xed, 0x7f, 0x2b, 0xec, 0x81, 0x2d, 0x60, 0x33, 0x11, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x24, 0x11, 0x5, 0xe0, 0x7a, 0x38, 0xee, 0x84, 0x3a, 0xee, 0x82, 0x2c, 0xf0, 0x88, 0x2f, 0x82, 0x4d, 0x1a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x6f, 0x39, 0x13, 0xef, 0x82, 0x30, 0xed, 0x82, 0x2f, 0xee, 0x82, 0x2e, 0xee, 0x82, 0x2d, 0xee, 0x81, 0x2c, 0xf0, 0x83, 0x2d, 0x88, 0x49, 0x18, 0x3, 0x2, 0x1, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x24, 0x11, 0x5, 0xe0, 0x7c, 0x3a, 0xee, 0x86, 0x3b, 0xee, 0x84, 0x2d, 0xf1, 0x8b, 0x30, 0x82, 0x4d, 0x1a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x54, 0x2b, 0xf, 0xe9, 0x80, 0x30, 0xee, 0x87, 0x33, 0xef, 0x88, 0x32, 0xef, 0x88, 0x30, 0xee, 0x85, 0x2f, 0xef, 0x83, 0x2e, 0xae, 0x5f, 0x20, 0x4, 0x2, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x24, 0x11, 0x5, 0xe0, 0x7e, 0x3d, 0xef, 0x8a, 0x3d, 0xef, 0x88, 0x2e, 0xf1, 0x8d, 0x31, 0x81, 0x4d, 0x1a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x29, 0x15, 0x7, 0xd2, 0x74, 0x2d, 0xf0, 0x8b, 0x36, 0xf0, 0x8d, 0x35, 0xef, 0x8d, 0x35, 0xef, 0x8b, 0x33, 0xef, 0x88, 0x30, 0xc4, 0x6d, 0x26, 0x18, 0xc, 0x4, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x24, 0x11, 0x5, 0xe1, 0x80, 0x3f, 0xf0, 0x8d, 0x3f, 0xef, 0x8a, 0x2f, 0xf1, 0x8f, 0x32, 0x81, 0x4e, 0x1a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0x3, 0x0, 0xb1, 0x61, 0x26, 0xf1, 0x8e, 0x3a, 0xf1, 0x90, 0x3a, 0xf0, 0x90, 0x38, 0xf0, 0x90, 0x36, 0xef, 0x8e, 0x35, 0xd3, 0x7a, 0x2c, 0x22, 0x11, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x24, 0x12, 0x5, 0xe1, 0x83, 0x42, 0xf0, 0x90, 0x42, 0xf0, 0x8d, 0x30, 0xf2, 0x92, 0x33, 0x80, 0x4e, 0x1b, 0x0, 0x0, 0x0, 0x3, 0x2, 0x0, 0x81, 0x45, 0x1b, 0xf1, 0x90, 0x3e, 0xf1, 0x94, 0x3d, 0xf1, 0x95, 0x3c, 0xf0, 0x94, 0x3b, 0xf0, 0x92, 0x39, 0xf0, 0x90, 0x35, 0xd0, 0x7b, 0x2b, 0xc2, 0x6e, 0x26, 0xbe, 0x6c, 0x25, 0x94, 0x54, 0x1c, 0x5b, 0x33, 0x11, 0x1a, 0xe, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x25, 0x14, 0x6, 0xe2, 0x86, 0x44, 0xf1, 0x94, 0x45, 0xf0, 0x90, 0x31, 0xf2, 0x94, 0x33, 0x80, 0x4e, 0x1b, 0x0, 0x0, 0x0, 0x60, 0x34, 0x14, 0xed, 0x8c, 0x3e, 0xf0, 0x96, 0x42, 0xf1, 0x97, 0x40, 0xf1, 0x95, 0x3f, 0xf0, 0x91, 0x39, 0xef, 0x8e, 0x33, 0xef, 0x8d, 0x31, 0xf0, 0x8d, 0x31, 0xef, 0x8c, 0x30, 0xef, 0x8c, 0x30, 0xf0, 0x8d, 0x31, 0xf1, 0x8e, 0x31, 0xe1, 0x85, 0x2e, 0x92, 0x55, 0x1d, 0x25, 0x14, 0x7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x26, 0x14, 0x6, 0xe2, 0x89, 0x46, 0xf2, 0x97, 0x47, 0xf1, 0x92, 0x32, 0xf2, 0x96, 0x34, 0x80, 0x4e, 0x1a, 0x32, 0x1a, 0xa, 0xe3, 0x87, 0x3d, 0xf1, 0x97, 0x45, 0xf1, 0x98, 0x44, 0xf1, 0x95, 0x41, 0xf0, 0x90, 0x39, 0xef, 0x8d, 0x30, 0xef, 0x8f, 0x31, 0xf0, 0x90, 0x32, 0xf0, 0x92, 0x33, 0xf1, 0x93, 0x33, 0xf1, 0x94, 0x34, 0xf1, 0x94, 0x34, 0xf0, 0x93, 0x34, 0xf0, 0x91, 0x32, 0xf1, 0x91, 0x33, 0xe2, 0x8a, 0x30, 0x6b, 0x3f, 0x15, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x26, 0x14, 0x6, 0xe3, 0x8b, 0x49, 0xf2, 0x9a, 0x49, 0xf1, 0x93, 0x32, 0xf2, 0x98, 0x35, 0x8f, 0x57, 0x1d, 0xcf, 0x7c, 0x38, 0xf2, 0x99, 0x48, 0xf1, 0x98, 0x47, 0xf1, 0x96, 0x44, 0xf0, 0x90, 0x39, 0xef, 0x8d, 0x31, 0xf0, 0x90, 0x31, 0xf0, 0x92, 0x33, 0xf1, 0x94, 0x33, 0xf1, 0x96, 0x35, 0xf1, 0x98, 0x35, 0xf1, 0x9a, 0x36, 0xf1, 0x9c, 0x37, 0xf2, 0x9d, 0x37, 0xf2, 0x9c, 0x37, 0xf2, 0x99, 0x36, 0xf0, 0x94, 0x34, 0xf3, 0x97, 0x35, 0x9f, 0x60, 0x21, 0x13, 0xb, 0x3, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x26, 0x14, 0x6, 0xe3, 0x8d, 0x4b, 0xf2, 0x9b, 0x4c, 0xf1, 0x93, 0x32, 0xf1, 0x97, 0x35, 0xea, 0x98, 0x43, 0xf2, 0x9d, 0x4d, 0xf1, 0x9a, 0x4b, 0xf1, 0x99, 0x49, 0xf0, 0x93, 0x3d, 0xf0, 0x8d, 0x30, 0xf0, 0x90, 0x32, 0xf0, 0x92, 0x32, 0xf0, 0x94, 0x34, 0xf1, 0x96, 0x34, 0xf1, 0x98, 0x36, 0xf1, 0x9a, 0x36, 0xf2, 0x9c, 0x38, 0xf2, 0x9f, 0x38, 0xf2, 0xa2, 0x39, 0xf3, 0xa2, 0x39, 0xf3, 0xa2, 0x39, 0xf2, 0x9f, 0x38, 0xf1, 0x99, 0x35, 0xf2, 0x97, 0x35, 0xba, 0x74, 0x29, 0x13, 0xb, 0x4, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x26, 0x14, 0x6, 0xe4, 0x8e, 0x4d, 0xf2, 0x9d, 0x4e, 0xf1, 0x93, 0x32, 0xf2, 0x9d, 0x3f, 0xf3, 0xa4, 0x54, 0xf2, 0x9d, 0x50, 0xf1, 0x9b, 0x4d, 0xf2, 0x98, 0x46, 0xef, 0x8d, 0x31, 0xf0, 0x8f, 0x31, 0xf0, 0x91, 0x32, 0xf0, 0x93, 0x32, 0xf1, 0x94, 0x32, 0xf1, 0x95, 0x32, 0xf1, 0x98, 0x34, 0xf1, 0x9b, 0x36, 0xf2, 0x9e, 0x38, 0xf2, 0xa1, 0x39, 0xf2, 0xa4, 0x3a, 0xf3, 0xa6, 0x3b, 0xf4, 0xa8, 0x3c, 0xf3, 0xa7, 0x3c, 0xf3, 0xa4, 0x3a, 0xf2, 0x9c, 0x37, 0xf2, 0x99, 0x36, 0xa9, 0x69, 0x25, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x26, 0x14, 0x6, 0xe4, 0x90, 0x50, 0xf2, 0x9e, 0x51, 0xf1, 0x95, 0x35, 0xf4, 0xa6, 0x54, 0xf3, 0xa2, 0x55, 0xf2, 0x9e, 0x51, 0xf2, 0x9c, 0x4e, 0xf0, 0x8f, 0x35, 0xf0, 0x8e, 0x31, 0xf0, 0x90, 0x32, 0xf3, 0xa5, 0x56, 0xf7, 0xc4, 0x8e, 0xfa, 0xd8, 0xb6, 0xfb, 0xdf, 0xc2, 0xfa, 0xd8, 0xb2, 0xf7, 0xc4, 0x89, 0xf4, 0xae, 0x59, 0xf2, 0xa1, 0x38, 0xf3, 0xa5, 0x3b, 0xf4, 0xa8, 0x3c, 0xf4, 0xab, 0x3d, 0xf4, 0xac, 0x3e, 0xf4, 0xab, 0x3d, 0xf3, 0xa7, 0x3b, 0xf2, 0x9e, 0x38, 0xf4, 0x9e, 0x38, 0x6f, 0x45, 0x17, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x19, 0xc, 0x5, 0x63, 0x36, 0x18, 0x3f, 0x20, 0x9, 0x2, 0x1, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x26, 0x14, 0x6, 0xe4, 0x91, 0x52, 0xf3, 0xa2, 0x55, 0xf2, 0x9d, 0x43, 0xf4, 0xa7, 0x5b, 0xf3, 0xa2, 0x57, 0xf3, 0xa0, 0x55, 0xf1, 0x97, 0x43, 0xf0, 0x8d, 0x30, 0xf2, 0x9d, 0x4c, 0xfa, 0xda, 0xbc, 0xfe, 0xfb, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfb, 0xf6, 0xfa, 0xdc, 0xb5, 0xf4, 0xae, 0x4e, 0xf4, 0xa9, 0x3c, 0xf4, 0xac, 0x3d, 0xf4, 0xae, 0x3f, 0xf4, 0xaf, 0x3f, 0xf4, 0xad, 0x3f, 0xf3, 0xa8, 0x3d, 0xf2, 0x9d, 0x38, 0xe2, 0x94, 0x34, 0x23, 0x14, 0x6, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x11, 0x8, 0x3, 0x9e, 0x62, 0x39, 0xf2, 0x91, 0x4e, 0xe7, 0x79, 0x29, 0x48, 0x25, 0xc, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x27, 0x13, 0x6, 0xe5, 0x93, 0x54, 0xf3, 0xa7, 0x59, 0xf4, 0xa6, 0x56, 0xf4, 0xa7, 0x5d, 0xf3, 0xa4, 0x59, 0xf3, 0xa2, 0x57, 0xf1, 0x90, 0x36, 0xf4, 0xa7, 0x5d, 0xfe, 0xf4, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xf2, 0xe3, 0xf6, 0xb8, 0x5f, 0xf4, 0xac, 0x3e, 0xf4, 0xaf, 0x3f, 0xf4, 0xb1, 0x40, 0xf4, 0xb2, 0x40, 0xf5, 0xaf, 0x3f, 0xf3, 0xa6, 0x3c, 0xf3, 0x9f, 0x38, 0x90, 0x5d, 0x21, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x3d, 0x1f, 0xf, 0xed, 0x9c, 0x6a, 0xef, 0x8b, 0x4a, 0xec, 0x78, 0x29, 0xe4, 0x79, 0x2a, 0x29, 0x15, 0x7, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0x28, 0x14, 0x6, 0xe6, 0x97, 0x57, 0xf5, 0xad, 0x63, 0xf5, 0xac, 0x62, 0xf4, 0xa8, 0x5f, 0xf4, 0xa6, 0x5c, 0xf3, 0xa0, 0x53, 0xf4, 0xa9, 0x64, 0xfe, 0xf8, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xf2, 0xf7, 0xfa, 0xed, 0xf4, 0xf8, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xf7, 0xed, 0xf5, 0xb5, 0x53, 0xf5, 0xb0, 0x3f, 0xf5, 0xb3, 0x41, 0xf5, 0xb4, 0x42, 0xf5, 0xb3, 0x41, 0xf4, 0xad, 0x3f, 0xf3, 0xa1, 0x39, 0xe4, 0x98, 0x37, 0x1d, 0x11, 0x5, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x43, 0x23, 0x10, 0xf2, 0xa1, 0x70, 0xf1, 0x99, 0x61, 0xec, 0x78, 0x2a, 0xed, 0x7b, 0x2a, 0xc4, 0x69, 0x23, 0x15, 0xa, 0x3, 0x0, 0x0, 0x0, 0x1d, 0xf, 0x5, 0xe7, 0x9b, 0x5b, 0xf5, 0xb1, 0x68, 0xf5, 0xad, 0x65, 0xf4, 0xaa, 0x62, 0xf4, 0xa8, 0x5f, 0xf3, 0xa4, 0x59, 0xfd, 0xec, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfd, 0xfe, 0xc3, 0xda, 0xe9, 0x5c, 0x9a, 0xc5, 0x2a, 0x7b, 0xb4, 0x17, 0x6f, 0xae, 0x36, 0x81, 0xb8, 0x91, 0xbb, 0xd9, 0xf0, 0xf6, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xe7, 0xc7, 0xf5, 0xb2, 0x43, 0xf6, 0xb3, 0x41, 0xf5, 0xb5, 0x43, 0xf5, 0xb6, 0x43, 0xf5, 0xb3, 0x42, 0xf4, 0xa8, 0x3c, 0xf4, 0xa2, 0x3a, 0x66, 0x41, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x22, 0x10, 0x7, 0xd6, 0x88, 0x5b, 0xf2, 0xa5, 0x76, 0xee, 0x84, 0x3f, 0xed, 0x7a, 0x2a, 0xee, 0x80, 0x2c, 0xa5, 0x59, 0x1e, 0x7, 0x3, 0x1, 0x19, 0xd, 0x4, 0xe7, 0x9e, 0x5e, 0xf6, 0xb2, 0x6b, 0xf5, 0xae, 0x67, 0xf5, 0xac, 0x65, 0xf4, 0xa9, 0x61, 0xf8, 0xcc, 0xa1, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfd, 0xfe, 0xfe, 0x97, 0xbf, 0xdb, 0x33, 0x83, 0xbb, 0x24, 0x7e, 0xb9, 0x3, 0x6a, 0xae, 0x0, 0x66, 0xab, 0x0, 0x64, 0xa9, 0x1, 0x63, 0xa9, 0x3c, 0x87, 0xbd, 0xee, 0xf5, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfd, 0xf8, 0xc7, 0x76, 0xf6, 0xb4, 0x41, 0xf5, 0xb7, 0x43, 0xf6, 0xb8, 0x44, 0xf6, 0xb6, 0x43, 0xf5, 0xae, 0x3f, 0xf3, 0xa2, 0x3a, 0xac, 0x71, 0x29, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x52, 0x2c, 0x16, 0xf0, 0xa1, 0x71, 0xf2, 0xa2, 0x6f, 0xed, 0x7e, 0x32, 0xed, 0x7e, 0x2b, 0xef, 0x82, 0x2d, 0x8a, 0x49, 0x18, 0x1b, 0xe, 0x4, 0xe7, 0xa2, 0x61, 0xf6, 0xb3, 0x6e, 0xf6, 0xb0, 0x6a, 0xf5, 0xae, 0x67, 0xf5, 0xab, 0x64, 0xfe, 0xf4, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb4, 0xd1, 0xe5, 0x3e, 0x8d, 0xc3, 0x37, 0x8e, 0xc5, 0x16, 0x7a, 0xb9, 0x0, 0x6b, 0xaf, 0x0, 0x68, 0xac, 0x0, 0x65, 0xaa, 0x0, 0x65, 0xab, 0x0, 0x66, 0xac, 0x4d, 0x93, 0xc4, 0xf8, 0xfb, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xe7, 0xc5, 0xf6, 0xb3, 0x40, 0xf6, 0xb7, 0x43, 0xf6, 0xb9, 0x44, 0xf6, 0xb8, 0x45, 0xf5, 0xb2, 0x41, 0xf3, 0xa5, 0x3b, 0xe2, 0x98, 0x37, 0x3, 0x1, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x86, 0x4e, 0x2e, 0xf3, 0xa6, 0x77, 0xf1, 0x9e, 0x66, 0xed, 0x7e, 0x2d, 0xee, 0x82, 0x2c, 0xf0, 0x85, 0x2d, 0x7e, 0x47, 0x17, 0xe8, 0xa6, 0x64, 0xf6, 0xb5, 0x70, 0xf6, 0xb2, 0x6d, 0xf5, 0xb0, 0x6a, 0xf7, 0xbb, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xfb, 0xfd, 0x5b, 0x9c, 0xca, 0x42, 0x96, 0xcb, 0x3c, 0x93, 0xc9, 0x9, 0x73, 0xb6, 0x0, 0x6b, 0xb0, 0x0, 0x69, 0xad, 0x0, 0x66, 0xab, 0x0, 0x66, 0xab, 0x0, 0x67, 0xad, 0x4, 0x6a, 0xaf, 0xbb, 0xd7, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xf8, 0xee, 0xf6, 0xb9, 0x4f, 0xf6, 0xb7, 0x44, 0xf6, 0xba, 0x45, 0xf6, 0xba, 0x45, 0xf5, 0xb5, 0x43, 0xf4, 0xa8, 0x3d, 0xf5, 0xa7, 0x3d, 0x1b, 0xf, 0x4, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x11, 0x8, 0x3, 0xb0, 0x6d, 0x45, 0xf4, 0xaa, 0x7b, 0xf1, 0x9a, 0x5b, 0xee, 0x82, 0x2d, 0xef, 0x86, 0x2e, 0xee, 0x91, 0x36, 0xf5, 0xb5, 0x70, 0xf6, 0xb7, 0x73, 0xf6, 0xb4, 0x70, 0xf5, 0xb1, 0x6c, 0xf9, 0xcc, 0xa1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd1, 0xe2, 0xef, 0x4b, 0x97, 0xca, 0x47, 0x9a, 0xce, 0x3f, 0x95, 0xcb, 0x3, 0x71, 0xb5, 0x0, 0x6c, 0xb0, 0x0, 0x69, 0xae, 0x0, 0x67, 0xac, 0x0, 0x66, 0xac, 0x0, 0x67, 0xad, 0x0, 0x69, 0xaf, 0x66, 0xa5, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfa, 0xf8, 0xc3, 0x67, 0xf6, 0xb8, 0x44, 0xf6, 0xba, 0x45, 0xf6, 0xbb, 0x46, 0xf6, 0xb7, 0x44, 0xf4, 0xab, 0x3e, 0xf8, 0xab, 0x3f, 0x2a, 0x19, 0x8, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x2b, 0x15, 0x9, 0xd4, 0x8a, 0x5c, 0xf4, 0xac, 0x7c, 0xf1, 0x98, 0x54, 0xee, 0x85, 0x2e, 0xf1, 0x93, 0x38, 0xf6, 0xba, 0x75, 0xf6, 0xb9, 0x75, 0xf6, 0xb6, 0x72, 0xf6, 0xb3, 0x6f, 0xfa, 0xd5, 0xb1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb0, 0xcf, 0xe5, 0x51, 0x9e, 0xcf, 0x4b, 0x9d, 0xd0, 0x43, 0x97, 0xcc, 0x3, 0x71, 0xb5, 0x0, 0x6d, 0xb1, 0x0, 0x6a, 0xae, 0x0, 0x67, 0xac, 0x0, 0x67, 0xad, 0x0, 0x68, 0xae, 0x0, 0x6a, 0xb0, 0x3b, 0x8c, 0xc2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xf9, 0xc9, 0x77, 0xf6, 0xb8, 0x44, 0xf6, 0xba, 0x45, 0xf6, 0xbc, 0x46, 0xf6, 0xb8, 0x44, 0xf4, 0xad, 0x3f, 0xf8, 0xac, 0x3f, 0x2a, 0x1a, 0x8, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x47, 0x26, 0x12, 0xee, 0xa3, 0x72, 0xf4, 0xae, 0x7b, 0xf1, 0x97, 0x4e, 0xf1, 0x92, 0x38, 0xf6, 0xbb, 0x78, 0xf6, 0xbb, 0x78, 0xf6, 0xb7, 0x75, 0xf6, 0xb5, 0x71, 0xfa, 0xd6, 0xb2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0xcd, 0xe4, 0x54, 0xa0, 0xd1, 0x4e, 0xa0, 0xd1, 0x48, 0x9b, 0xce, 0xb, 0x76, 0xb8, 0x0, 0x6d, 0xb2, 0x0, 0x6a, 0xaf, 0x0, 0x68, 0xad, 0x0, 0x68, 0xad, 0x0, 0x69, 0xae, 0x0, 0x6b, 0xb1, 0x36, 0x89, 0xc1, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xf9, 0xc9, 0x76, 0xf6, 0xb9, 0x44, 0xf6, 0xbb, 0x46, 0xf6, 0xbc, 0x47, 0xf6, 0xb9, 0x44, 0xf4, 0xad, 0x3f, 0xf8, 0xad, 0x40, 0x2a, 0x1a, 0x8, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x70, 0x42, 0x26, 0xf4, 0xad, 0x7b, 0xf5, 0xb1, 0x7d, 0xf3, 0x9f, 0x50, 0xf7, 0xbc, 0x7b, 0xf7, 0xbc, 0x7b, 0xf6, 0xb9, 0x78, 0xf6, 0xb7, 0x74, 0xf9, 0xd0, 0xa6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xda, 0xeb, 0x56, 0xa0, 0xd0, 0x51, 0xa1, 0xd2, 0x4a, 0x9c, 0xcf, 0x20, 0x82, 0xbf, 0x0, 0x6e, 0xb2, 0x0, 0x6b, 0xb0, 0x0, 0x68, 0xae, 0x0, 0x68, 0xae, 0x0, 0x69, 0xaf, 0x0, 0x6b, 0xb1, 0x50, 0x98, 0xc9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xf9, 0xf8, 0xc3, 0x66, 0xf6, 0xb9, 0x45, 0xf7, 0xbb, 0x46, 0xf6, 0xbc, 0x47, 0xf6, 0xb8, 0x45, 0xf4, 0xad, 0x3f, 0xf8, 0xac, 0x3f, 0x2a, 0x19, 0x7, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xc, 0x5, 0x0, 0xa5, 0x67, 0x40, 0xf5, 0xb1, 0x7f, 0xf5, 0xb7, 0x7e, 0xf7, 0xbf, 0x80, 0xf7, 0xbe, 0x7d, 0xf7, 0xbb, 0x7b, 0xf6, 0xb9, 0x78, 0xf8, 0xc2, 0x8b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xee, 0xf5, 0xf9, 0x5b, 0xa0, 0xce, 0x53, 0xa2, 0xd2, 0x4c, 0x9e, 0xd0, 0x3c, 0x93, 0xc8, 0x6, 0x71, 0xb4, 0x0, 0x6c, 0xb0, 0x0, 0x69, 0xae, 0x0, 0x69, 0xae, 0x0, 0x6a, 0xaf, 0x0, 0x6b, 0xb1, 0x9b, 0xc5, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xf7, 0xec, 0xf6, 0xba, 0x4e, 0xf6, 0xb9, 0x45, 0xf7, 0xbb, 0x46, 0xf6, 0xbc, 0x47, 0xf5, 0xb7, 0x44, 0xf4, 0xab, 0x3e, 0xf5, 0xa8, 0x3e, 0x18, 0xd, 0x4, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x1f, 0x10, 0x7, 0xc9, 0x84, 0x56, 0xf5, 0xb5, 0x81, 0xf7, 0xbf, 0x82, 0xf8, 0xc0, 0x80, 0xf7, 0xbd, 0x7d, 0xf7, 0xba, 0x7a, 0xf6, 0xb8, 0x77, 0xfe, 0xf5, 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9a, 0xc2, 0xdf, 0x55, 0x9f, 0xd0, 0x4e, 0x9f, 0xd0, 0x47, 0x99, 0xcc, 0x2a, 0x87, 0xc1, 0x3, 0x6d, 0xb1, 0x0, 0x69, 0xaf, 0x0, 0x6a, 0xaf, 0x0, 0x6a, 0xb0, 0x27, 0x80, 0xbc, 0xec, 0xf4, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xe5, 0xbf, 0xf6, 0xb6, 0x42, 0xf6, 0xba, 0x46, 0xf7, 0xbb, 0x46, 0xf7, 0xbb, 0x47, 0xf5, 0xb5, 0x43, 0xf3, 0xa8, 0x3d, 0xdd, 0x97, 0x37, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x32, 0x1a, 0xb, 0xe4, 0x9d, 0x6a, 0xf7, 0xbd, 0x84, 0xf8, 0xc1, 0x83, 0xf8, 0xbe, 0x80, 0xf7, 0xbd, 0x7d, 0xf7, 0xba, 0x79, 0xfa, 0xd9, 0xb6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf6, 0xfa, 0x74, 0xac, 0xd4, 0x4f, 0x9b, 0xcd, 0x48, 0x99, 0xcc, 0x41, 0x94, 0xc8, 0x2c, 0x85, 0xbe, 0xb, 0x70, 0xb3, 0x1, 0x6a, 0xb0, 0xb, 0x6e, 0xb2, 0xbf, 0xd9, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfd, 0xf8, 0xc8, 0x74, 0xf6, 0xb7, 0x44, 0xf6, 0xba, 0x46, 0xf7, 0xbb, 0x46, 0xf7, 0xb9, 0x46, 0xf6, 0xb2, 0x42, 0xf4, 0xa7, 0x3d, 0xa6, 0x70, 0x29, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x4f, 0x2e, 0x18, 0xef, 0xaf, 0x78, 0xf8, 0xc1, 0x85, 0xf8, 0xc0, 0x82, 0xf7, 0xbe, 0x7f, 0xf7, 0xbc, 0x7d, 0xf7, 0xbe, 0x81, 0xfe, 0xf3, 0xe8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xf7, 0xfa, 0x91, 0xbd, 0xdb, 0x4f, 0x97, 0xc8, 0x40, 0x8e, 0xc3, 0x37, 0x8a, 0xc0, 0x34, 0x88, 0xbf, 0x57, 0x9c, 0xca, 0xcc, 0xe1, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xe4, 0xbf, 0xf5, 0xb6, 0x45, 0xf6, 0xb8, 0x45, 0xf6, 0xba, 0x46, 0xf7, 0xba, 0x46, 0xf6, 0xb7, 0x45, 0xf5, 0xad, 0x3f, 0xf4, 0xa9, 0x40, 0x5c, 0x3d, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x85, 0x55, 0x31, 0xf7, 0xbd, 0x84, 0xf8, 0xc2, 0x85, 0xf8, 0xc0, 0x82, 0xf7, 0xbe, 0x80, 0xf7, 0xbc, 0x7d, 0xf9, 0xcb, 0x99, 0xfe, 0xf9, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xfe, 0xfe, 0xe5, 0xef, 0xf6, 0xc1, 0xda, 0xeb, 0xba, 0xd5, 0xe9, 0xd8, 0xe8, 0xf2, 0xf9, 0xfb, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xf3, 0xe4, 0xf6, 0xb9, 0x51, 0xf5, 0xb5, 0x43, 0xf6, 0xb8, 0x45, 0xf6, 0xb9, 0x46, 0xf6, 0xb8, 0x46, 0xf6, 0xb3, 0x43, 0xf4, 0xa7, 0x3e, 0xdf, 0x9d, 0x43, 0x17, 0xd, 0x4, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x14, 0xa, 0x4, 0xb2, 0x7b, 0x4b, 0xf8, 0xc2, 0x88, 0xf8, 0xc1, 0x85, 0xf7, 0xbf, 0x82, 0xf7, 0xbe, 0x80, 0xf7, 0xbd, 0x7d, 0xf9, 0xca, 0x97, 0xfe, 0xf9, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xf2, 0xe1, 0xf7, 0xbc, 0x5d, 0xf5, 0xb3, 0x42, 0xf5, 0xb6, 0x44, 0xf5, 0xb7, 0x45, 0xf6, 0xb8, 0x45, 0xf6, 0xb5, 0x44, 0xf5, 0xad, 0x40, 0xf6, 0xae, 0x4c, 0x88, 0x5d, 0x27, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x1d, 0x10, 0x6, 0xdb, 0xa0, 0x68, 0xf8, 0xc3, 0x88, 0xf7, 0xc1, 0x85, 0xf7, 0xc0, 0x82, 0xf7, 0xbf, 0x80, 0xf7, 0xbe, 0x7e, 0xf8, 0xc4, 0x88, 0xfc, 0xe6, 0xcc, 0xfe, 0xfb, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfa, 0xf3, 0xfa, 0xda, 0xa9, 0xf5, 0xb3, 0x4a, 0xf5, 0xb2, 0x42, 0xf5, 0xb3, 0x43, 0xf5, 0xb6, 0x44, 0xf5, 0xb7, 0x45, 0xf5, 0xb5, 0x44, 0xf5, 0xb0, 0x42, 0xf5, 0xad, 0x4d, 0xdd, 0x9e, 0x4a, 0x19, 0xf, 0x5, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x50, 0x33, 0x19, 0xec, 0xb4, 0x7a, 0xf8, 0xc2, 0x87, 0xf7, 0xc1, 0x85, 0xf7, 0xc1, 0x83, 0xf7, 0xc0, 0x80, 0xf7, 0xc0, 0x7f, 0xf7, 0xc0, 0x7c, 0xf7, 0xc2, 0x7e, 0xf8, 0xcc, 0x92, 0xfa, 0xda, 0xb0, 0xfb, 0xdf, 0xb9, 0xfa, 0xd9, 0xad, 0xf7, 0xc8, 0x84, 0xf5, 0xb4, 0x54, 0xf4, 0xad, 0x3f, 0xf4, 0xaf, 0x41, 0xf5, 0xb2, 0x42, 0xf5, 0xb4, 0x43, 0xf5, 0xb5, 0x44, 0xf5, 0xb4, 0x44, 0xf5, 0xb2, 0x46, 0xf5, 0xb2, 0x54, 0xf5, 0xb4, 0x5a, 0x5e, 0x3e, 0x1a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x71, 0x4b, 0x29, 0xf8, 0xc0, 0x86, 0xf7, 0xc3, 0x87, 0xf7, 0xc2, 0x85, 0xf7, 0xc1, 0x83, 0xf7, 0xc2, 0x82, 0xf7, 0xc2, 0x7f, 0xf7, 0xc2, 0x7e, 0xf6, 0xc0, 0x76, 0xf4, 0xb4, 0x59, 0xf3, 0xa8, 0x3e, 0xf3, 0xa7, 0x39, 0xf3, 0xa9, 0x3d, 0xf4, 0xab, 0x3e, 0xf4, 0xad, 0x40, 0xf4, 0xb0, 0x41, 0xf4, 0xb2, 0x42, 0xf5, 0xb2, 0x42, 0xf5, 0xb3, 0x45, 0xf6, 0xb7, 0x54, 0xf6, 0xb7, 0x60, 0xf6, 0xb5, 0x5f, 0x9d, 0x6b, 0x31, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x8b, 0x5f, 0x36, 0xf9, 0xc1, 0x87, 0xf7, 0xc3, 0x88, 0xf8, 0xc3, 0x86, 0xf7, 0xc3, 0x84, 0xf8, 0xc3, 0x81, 0xf7, 0xc4, 0x80, 0xf7, 0xc4, 0x7e, 0xf7, 0xc4, 0x7d, 0xf7, 0xc3, 0x7a, 0xf6, 0xbd, 0x6c, 0xf5, 0xb7, 0x5c, 0xf5, 0xb5, 0x54, 0xf5, 0xb4, 0x50, 0xf5, 0xb6, 0x52, 0xf6, 0xb9, 0x58, 0xf6, 0xbd, 0x62, 0xf7, 0xbf, 0x6a, 0xf6, 0xba, 0x66, 0xf6, 0xb6, 0x63, 0xab, 0x78, 0x39, 0xa, 0x6, 0x2, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x83, 0x58, 0x32, 0xf0, 0xb9, 0x7f, 0xf7, 0xc3, 0x88, 0xf7, 0xc3, 0x86, 0xf8, 0xc4, 0x84, 0xf7, 0xc5, 0x82, 0xf7, 0xc5, 0x80, 0xf7, 0xc5, 0x7f, 0xf8, 0xc5, 0x7d, 0xf7, 0xc4, 0x7b, 0xf7, 0xc4, 0x79, 0xf7, 0xc4, 0x78, 0xf7, 0xc3, 0x76, 0xf7, 0xc3, 0x74, 0xf7, 0xc2, 0x71, 0xf6, 0xbe, 0x6d, 0xf6, 0xba, 0x6a, 0xf4, 0xb6, 0x65, 0x8a, 0x5e, 0x2c, 0xc, 0x7, 0x3, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x4f, 0x33, 0x1a, 0xd2, 0x99, 0x60, 0xf8, 0xc4, 0x89, 0xf8, 0xc3, 0x86, 0xf8, 0xc4, 0x84, 0xf7, 0xc5, 0x82, 0xf7, 0xc5, 0x80, 0xf7, 0xc5, 0x7f, 0xf7, 0xc4, 0x7e, 0xf7, 0xc4, 0x7b, 0xf7, 0xc3, 0x79, 0xf7, 0xc2, 0x77, 0xf6, 0xc0, 0x74, 0xf6, 0xbd, 0x71, 0xf6, 0xbb, 0x6e, 0xe1, 0xa4, 0x59, 0x5c, 0x3d, 0x1b, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xe, 0x6, 0x0, 0x72, 0x4b, 0x28, 0xd0, 0x9a, 0x62, 0xf7, 0xbf, 0x80, 0xf8, 0xc4, 0x85, 0xf7, 0xc3, 0x82, 0xf7, 0xc3, 0x80, 0xf7, 0xc3, 0x7e, 0xf7, 0xc1, 0x7c, 0xf6, 0xc0, 0x7a, 0xf7, 0xbf, 0x78, 0xf8, 0xbc, 0x72, 0xde, 0xa2, 0x5d, 0x80, 0x57, 0x2b, 0x13, 0xb, 0x4, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x19, 0xe, 0x5, 0x44, 0x2c, 0x15, 0x81, 0x59, 0x32, 0xb2, 0x80, 0x4c, 0xcb, 0x95, 0x5b, 0xd2, 0x9c, 0x5f, 0xcd, 0x97, 0x5a, 0xb9, 0x86, 0x4d, 0x8b, 0x61, 0x34, 0x4a, 0x30, 0x17, 0x15, 0xc, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
- 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x3, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0xff,
+static long BLENDER_ICON_48x48x32[] = {
+ 48,48,
+ 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,
+ 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,
+ 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,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 131820800, 1305304320, 2547014912, 1808620800, 432823296, 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, 3218103552, 4074070530, 4276450320, 4124995601, 4090518785, 1624202496, 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, 1053710848, 4140916224, 4294348072, 4294483011, 4294483268, 4294153273, 4107626765, 2765053184, 146759680, 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, 282025984, 4124007680, 4293884685, 4294482752, 4294483785, 4294483785, 4294417734, 4141905692, 3671088640, 600596224, 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, 1573804544, 4124073472, 4293555207, 4294416700, 4294484558, 4294484558, 4294484558, 4260005935, 4073807875, 1355766784, 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, 936140032, 3973012736, 4192300034, 4294415154, 4294485331, 4294485074, 4294485074, 4294088514, 4107560459, 2463128832, 79642624, 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, 399726848, 3452984576, 4107887616, 4294281765, 4294485590, 4294485591, 4294485590, 4294418767, 4124931612, 3469762048, 449730560, 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, 97281536, 2597412096, 4107427584, 4293951767, 4294485590, 4294551642, 4294486105, 4294485847, 4226320176, 4023344642, 1120754944, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 1389190400, 2949668096, 4073741568, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4158482693, 4294484301, 4294552415, 4294552157, 4294551899, 4294486105, 4293957442, 4124206089, 2144427008, 33488896, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 1171217408, 4107361792, 4293425685, 4294218035, 4294482753, 4294483268, 4294483783, 4294484043, 4294484558, 4294484817, 4294485331, 4294485591, 4294486105, 4294551899, 4294552157, 4294552415, 4294552672, 4294552673, 4294552930, 4294552674, 4294552674, 4294553188, 4294553190, 4294552932, 4294552674, 4294552415, 4294552156, 4294551642, 4294287696, 4124733464, 3234946560, 315970816, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 3838860800, 4293620999, 4294416700, 4294482753, 4294483269, 4294483784, 4294484300, 4294484816, 4294485331, 4294485591, 4294551642, 4294552157, 4294552672, 4294552931, 4294553446, 4294553704, 4294553962, 4294554220, 4294554221, 4294554221, 4294554220, 4294554220, 4294553962, 4294553704, 4294553190, 4294552931, 4294552416, 4294552157, 4294551642, 4294485590, 4192502315, 3939458305, 919624192, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 3838860800, 4293751810, 4294415669, 4294482753, 4294483268, 4294483784, 4294484300, 4294484816, 4294485331, 4294485591, 4294551642, 4294552157, 4294552932, 4294553447, 4294553962, 4294554220, 4294554479, 4294554737, 4294554994, 4294554994, 4294554994, 4294554737, 4294554479, 4294554220, 4294553705, 4294553446, 4294552931, 4294552416, 4294552156, 4294486105, 4294485589, 4293824827, 4124140038, 1741708800, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 2463128832, 4191905024, 4294145792, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294345234, 4294553447, 4294554221, 4294554736, 4294620787, 4294621045, 4294621047, 4294621303, 4294621047, 4294621045, 4294554995, 4294554737, 4294554220, 4294553705, 4294553190, 4294552930, 4294552414, 4294551899, 4294485847, 4294485590, 4294155594, 4141050128, 1573936384, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 248011520, 2983288320, 4191116288, 4174405120, 4174405120, 4174405120, 4174405120, 4174405120, 4174405120, 4174405120, 4174405120, 4207959552, 4294214422, 4294554220, 4294554736, 4294620787, 4294621046, 4294621562, 4294621820, 4294690967, 4294761660, 4294830292, 4294899180, 4294966780, 4294898406, 4294829002, 4294759597, 4294621304, 4294552416, 4294551900, 4294485848, 4294485332, 4294485590, 4294221646, 4140984079, 1204641024, 4671303, 4671303, 4671303, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 79642624, 282025984, 282025984, 282025984, 282025984, 282025984, 282025984, 1540316160, 4124007680, 4226185237, 4294552156, 4294554221, 4294554737, 4294620789, 4294621561, 4294623367, 4294829774, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294966778, 4294759856, 4294552674, 4294486105, 4294485589, 4294484817, 4294551127, 4294089804, 4090651658, 885939456, 4671303, 4671303, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 97281536, 2513394688, 4124139264, 4293888040, 4294552931, 4294553705, 4294554478, 4294554737, 4294621045, 4294692513, 4294900470, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294898922, 4294621046, 4294485589, 4294484817, 4294484558, 4294551383, 4293891393, 4023344385, 432823296, 4671303, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 583752192, 3604045056, 4124796420, 4294285115, 4294552672, 4294553189, 4294553704, 4294554220, 4294554736, 4294623367, 4294769142, 4294835709, 4294835709, 4294835709, 4293192946, 4289446870, 4287803851, 4286620866, 4287738058, 4289446871, 4293850103, 4294901502, 4294901502, 4294901502, 4294898406, 4294552157, 4294484816, 4294484301, 4294484299, 4294486105, 4192502057, 2530172416, 4671303, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 1473075968, 4090518784, 4259673101, 4294484042, 4294551899, 4294552415, 4294552931, 4294553447, 4294553962, 4294554995, 4294700770, 4294704123, 4294704123, 4294769916, 4290169563, 4286555330, 4286423745, 4286292416, 4286095038, 4285897917, 4285635259, 4285766844, 4291155427, 4294769916, 4294769916, 4294769916, 4294628011, 4294278923, 4294278408, 4294278149, 4294279181, 4294149404, 4140784896, 365846784, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 163992832, 2731564288, 4124205057, 4293952286, 4294484816, 4294485590, 4294551642, 4294552157, 4294552673, 4294553188, 4294553704, 4294561702, 4294572537, 4294572537, 4294638330, 4291023841, 4286226623, 4286226623, 4286160831, 4286029502, 4285832381, 4285700795, 4284977846, 4282414755, 4280706199, 4290629597, 4294572537, 4294572537, 4294572537, 4294350393, 4294277376, 4294277376, 4294277633, 4294413864, 4158482692, 1875663872, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 718166784, 3738197248, 4141705477, 4294283568, 4294484815, 4294484816, 4294485332, 4294485848, 4294551899, 4294552158, 4294552673, 4294553188, 4294500036, 4294440951, 4294506744, 4294243830, 4286292159, 4285963709, 4285898173, 4285832381, 4285766588, 4285372345, 4282349219, 4279391885, 4279063179, 4279063179, 4281954719, 4294375158, 4294375158, 4294375158, 4294357617, 4294277376, 4294277376, 4294277376, 4294346781, 4293557270, 3218103552, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 1691311104, 4124007936, 4276647182, 4294416701, 4294483784, 4294484043, 4294484558, 4294485073, 4294485332, 4294485848, 4294551899, 4294552158, 4294552672, 4294372579, 4294375158, 4294375158, 4291943654, 4285569467, 4285635003, 4285569467, 4285503674, 4282875047, 4279654800, 4279063179, 4279063179, 4279063179, 4279063179, 4279128971, 4292732137, 4294177779, 4294177779, 4294233511, 4294277376, 4294277376, 4294277376, 4294344717, 4294217516, 4140784640, 50298880, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 232284672, 2949668096, 4107559426, 4294017820, 4294416960, 4294482753, 4294483268, 4294416959, 4294413348, 4294347296, 4294417474, 4294485332, 4294485848, 4294551642, 4294487137, 4294177779, 4294243572, 4294243572, 4290958047, 4285306552, 4285306553, 4284583603, 4280509077, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4291417567, 4293980400, 4294046193, 4294107085, 4294277376, 4294277376, 4294277376, 4294277376, 4294416185, 4207959811, 232284672, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 852253696, 3855638016, 4158614278, 4294348586, 4294416701, 4294416443, 4294416958, 4294415411, 4294280731, 4108283403, 4243290129, 4294414638, 4294484817, 4294485331, 4294485590, 4294485848, 4294174941, 4294111986, 4294111986, 4292206309, 4284977846, 4283137961, 4279457678, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279457422, 4293454571, 4293848814, 4293848814, 4294035617, 4294277376, 4294277376, 4294277376, 4294277376, 4294416443, 4140916998, 365846784, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 1909480704, 4124073472, 4293490704, 4294415154, 4294415669, 4294415669, 4294416184, 4294414123, 4294083611, 4090914310, 4040055808, 4293161999, 4294414379, 4294484557, 4294484815, 4294485074, 4294485331, 4294104247, 4293914607, 4293914607, 4293783279, 4283334569, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4284057260, 4293585642, 4293651435, 4293651435, 4293962857, 4294277376, 4294277376, 4294277376, 4294277376, 4294416959, 4124205832, 499800064, 4671303,
+ 4671303, 4671303, 298998272, 3150929152, 4107690755, 4294018076, 4294415410, 4294414636, 4294414638, 4294415153, 4294413606, 4293886234, 4124205059, 2110675968, 2060409856, 4225921807, 4294414895, 4294483785, 4294484043, 4294484557, 4294484815, 4294164622, 4293783021, 4293717228, 4293388263, 4290299602, 4279326093, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4280245907, 4292205535, 4293454056, 4293454056, 4293454056, 4294086704, 4294277376, 4294277376, 4294277376, 4294277891, 4294417992, 4207894017, 97281536, 4671303,
+ 4671303, 50298880, 3503250688, 4192169224, 4294282278, 4294414381, 4294347813, 4294413865, 4294414122, 4294348070, 4259937303, 4090519041, 1305304320, 4671303, 1238260480, 4024002053, 4294415926, 4294483269, 4294483527, 4294483784, 4294484043, 4294419022, 4293712069, 4293190884, 4293059298, 4293059298, 4289905102, 4281297305, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4282677154, 4291351001, 4293256677, 4293256677, 4293256677, 4293639310, 4294277376, 4294277376, 4294277376, 4294277376, 4294345490, 4294022463, 3671088640, 4671303, 4671303,
+ 4671303, 2077187328, 4107822598, 4294348586, 4294347555, 4294347039, 4294347554, 4294348069, 4294348327, 4175590163, 3872349440, 718166784, 4671303, 4671303, 449730560, 4124073472, 4294414379, 4294417217, 4294483010, 4294483268, 4294483269, 4294415927, 4294084898, 4292925905, 4292861919, 4292861919, 4292927712, 4292533470, 4288656582, 4286094006, 4284517036, 4286685370, 4289379531, 4292927713, 4293059298, 4293059298, 4293059298, 4293251260, 4294212873, 4294277376, 4294277376, 4294277376, 4294277376, 4294414896, 4259939884, 2681167104, 4671303, 4671303,
+ 97281536, 4191116288, 4294084386, 4294413347, 4294346265, 4294346780, 4294413091, 4294282281, 4124732172, 3335609856, 315970816, 4671303, 4671303, 4671303, 16777216, 3452853504, 4293624609, 4294415670, 4294416702, 4294416959, 4294414121, 4294277634, 4294277376, 4293825597, 4292793547, 4292664540, 4292730333, 4292730333, 4292730333, 4292730333, 4292796126, 4292796126, 4292796126, 4292796126, 4292861919, 4292861919, 4293120190, 4294085156, 4294277376, 4294277376, 4294277376, 4294277376, 4294278149, 4294485332, 4074071305, 969825792, 4671303, 4671303,
+ 198270208, 4224605184, 4294282535, 4294413347, 4294346524, 4294348070, 4294085417, 4107559687, 2563792384, 79642624, 4671303, 4671303, 83886080, 184549376, 268435456, 1605258752, 4074137355, 4294416185, 4294346522, 4294278666, 4294277376, 4294277376, 4294277376, 4294277376, 4294213647, 4293243263, 4292532696, 4292532954, 4292532954, 4292598747, 4292598747, 4292598747, 4292598747, 4292664540, 4292794579, 4293568616, 4294212357, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294414895, 4293890877, 3570425344, 4671303, 4671303, 4671303,
+ 4671303, 3352387072, 4192301839, 4294282279, 4294019626, 4192302873, 4124139523, 1708088576, 4671303, 4671303, 67108864, 184549376, 285212672, 385875968, 486539264, 638387968, 3888864256, 4276847393, 4294414896, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4293954086, 4293502050, 4293179274, 4292855728, 4292662218, 4292920489, 4293243778, 4293501275, 4294083608, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294345491, 4294420571, 4107626251, 1322146816, 4671303, 4671303, 4671303,
+ 4671303, 382819584, 3134217472, 4191116288, 3939458560, 2211470592, 533617152, 4671303, 4671303, 117440512, 218103808, 335544320, 436207616, 553648128, 654311424, 771751936, 1534079488, 4157496833, 4294219326, 4294346523, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294278150, 4294485590, 4175527207, 2932497152, 117440512, 4671303, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 50298880, 33488896, 4671303, 4671303, 4671303, 83886080, 201326592, 318767104, 436207616, 553648128, 671088640, 788529152, 889192448, 1006632960, 2493203712, 4157958415, 4294352457, 4294347039, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294278924, 4294486105, 4260073533, 3872218112, 525476096, 218103808, 100663296, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 16777216, 134217728, 251658240, 369098752, 486539264, 603979776, 721420288, 855638016, 973078528, 1090519040, 1207959552, 2930002688, 4174604044, 4294221386, 4294414637, 4294277634, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294346522, 4294552931, 4226189107, 3888929792, 997536768, 385875968, 251658240, 150994944, 16777216, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 16777216, 134217728, 251658240, 369098752, 486539264, 603979776, 721420288, 855638016, 956301312, 1073741824, 1191182336, 1325400064, 2693873664, 4191117319, 4293891393, 4294485073, 4294347296, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294344717, 4294484299, 4294421863, 4208884260, 3687340544, 910958848, 503316480, 385875968, 251658240, 134217728, 16777216, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 83886080, 201326592, 318767104, 436207616, 536870912, 671088640, 771751936, 889192448, 989855744, 1107296256, 1207959552, 1325400064, 2187996928, 3972487680, 4191711513, 4294156111, 4294485591, 4294415926, 4294346007, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294278408, 4294414379, 4294484817, 4294554221, 4259941691, 4157628420, 2746568960, 807735296, 553648128, 436207616, 318767104, 218103808, 83886080, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 100663296, 218103808, 318767104, 436207616, 536870912, 637534208, 754974720, 855638016, 956301312, 1040187392, 1140850688, 1224736768, 1342833408, 2677293568, 4174142464, 4157959447, 4276718648, 4294288986, 4294554220, 4294552415, 4294485074, 4294484300, 4294551641, 4294553705, 4294554738, 4294025043, 4175528237, 4174405895, 3384956928, 1264790528, 654311424, 553648128, 436207616, 335544320, 218103808, 117440512, 4671303, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 50331648, 167772160, 268435456, 385875968, 469762048, 553648128, 654311424, 738197504, 822083584, 905969664, 973078528, 1023410176, 1090519040, 1208878848, 2054632960, 3165868032, 4123810816, 4224671493, 4157762069, 4124604196, 4141644844, 4124471839, 4174538769, 4241448451, 3586611712, 2275493888, 1078731776, 671088640, 570425344, 486539264, 385875968, 285212672, 184549376, 67108864, 4671303, 4671303, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 67108864, 167772160, 251658240, 335544320, 419430400, 503316480, 570425344, 637534208, 704643072, 738197504, 788529152, 822083584, 855638016, 872415232, 889192448, 1042616320, 1365125376, 1702770688, 1821064448, 1467299072, 1095443200, 738985472, 637534208, 587202560, 503316480, 436207616, 352321536, 268435456, 184549376, 67108864, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
+ 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 16777216, 67108864, 150994944, 234881024, 301989888, 352321536, 402653184, 452984832, 486539264, 520093696, 536870912, 553648128, 570425344, 570425344, 553648128, 536870912, 520093696, 486539264, 452984832, 402653184, 352321536, 301989888, 234881024, 167772160, 67108864, 16777216, 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, 50331648, 83886080, 134217728, 167772160, 201326592, 218103808, 234881024, 251658240, 251658240, 234881024, 218103808, 201326592, 167772160, 134217728, 83886080, 50331648, 16777216, 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, 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, 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, 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, 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, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
};
@@ -165,9 +164,10 @@ GHOST_WindowX11(
const GHOST_TEmbedderWindowID parentWindow,
GHOST_TDrawingContextType type,
const bool stereoVisual,
+ const bool exclusive,
const GHOST_TUns16 numOfAASamples
) :
- GHOST_Window(width, height, state, type, stereoVisual, numOfAASamples),
+ GHOST_Window(width, height, state, type, stereoVisual, exclusive, numOfAASamples),
m_context(NULL),
m_display(display),
m_normal_state(GHOST_kWindowStateNormal),
@@ -186,11 +186,6 @@ GHOST_WindowX11(
int natom;
int glxVersionMajor, glxVersionMinor; /* As in GLX major.minor */
-#ifdef WITH_X11_XINPUT
- /* initialize incase X11 fails to load */
- memset(&m_xtablet, 0, sizeof(m_xtablet));
-#endif
-
m_visual = NULL;
if (!glXQueryVersion(m_display, &glxVersionMajor, &glxVersionMinor)) {
@@ -218,6 +213,7 @@ GHOST_WindowX11(
attributes[i++] = GLX_BLUE_SIZE; attributes[i++] = 1;
attributes[i++] = GLX_GREEN_SIZE; attributes[i++] = 1;
attributes[i++] = GLX_DEPTH_SIZE; attributes[i++] = 1;
+ attributes[i++] = GLX_ALPHA_SIZE; attributes[i++] = 1;
/* GLX >= 1.4 required for multi-sample */
if (samples && (glxVersionMajor >= 1) && (glxVersionMinor >= 4)) {
attributes[i++] = GLX_SAMPLE_BUFFERS; attributes[i++] = 1;
@@ -258,6 +254,7 @@ GHOST_WindowX11(
* This seems pretty much a legacy feature as we are in rgba mode anyway. */
XSetWindowAttributes xattributes;
+ unsigned int xattributes_valuemask = (CWBorderPixel | CWColormap | CWEventMask);
memset(&xattributes, 0, sizeof(xattributes));
xattributes.colormap = XCreateColormap(m_display,
@@ -271,15 +268,19 @@ GHOST_WindowX11(
/* Specify which events we are interested in hearing. */
xattributes.event_mask =
- ExposureMask | StructureNotifyMask |
- KeyPressMask | KeyReleaseMask |
- EnterWindowMask | LeaveWindowMask |
- ButtonPressMask | ButtonReleaseMask |
- PointerMotionMask | FocusChangeMask | PropertyChangeMask;
+ ExposureMask | StructureNotifyMask |
+ KeyPressMask | KeyReleaseMask |
+ EnterWindowMask | LeaveWindowMask |
+ ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask | FocusChangeMask |
+ PropertyChangeMask | KeymapStateMask;
+
+ if (exclusive) {
+ xattributes_valuemask |= CWOverrideRedirect;
+ xattributes.override_redirect = True;
+ }
/* create the window! */
-
- ;
if (parentWindow == 0) {
m_window = XCreateWindow(m_display,
RootWindow(m_display, m_visual->screen),
@@ -291,7 +292,7 @@ GHOST_WindowX11(
m_visual->depth,
InputOutput,
m_visual->visual,
- CWBorderPixel | CWColormap | CWEventMask,
+ xattributes_valuemask,
&xattributes
);
}
@@ -320,7 +321,7 @@ GHOST_WindowX11(
m_visual->depth,
InputOutput,
m_visual->visual,
- CWBorderPixel | CWColormap | CWEventMask,
+ xattributes_valuemask,
&xattributes
);
@@ -334,6 +335,26 @@ GHOST_WindowX11(
GHOST_PRINT("Set drop target\n");
#endif
+ if (state == GHOST_kWindowStateMaximized || state == GHOST_kWindowStateFullScreen) {
+ Atom _NET_WM_STATE = XInternAtom(m_display, "_NET_WM_STATE", False);
+ Atom _NET_WM_STATE_MAXIMIZED_VERT = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
+ Atom _NET_WM_STATE_MAXIMIZED_HORZ = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
+ Atom _NET_WM_STATE_FULLSCREEN = XInternAtom(m_display, "_NET_WM_STATE_FULLSCREEN", False);
+ Atom atoms[2];
+ int count = 0;
+
+ if (state == GHOST_kWindowStateMaximized) {
+ atoms[count++] = _NET_WM_STATE_MAXIMIZED_VERT;
+ atoms[count++] = _NET_WM_STATE_MAXIMIZED_HORZ;
+ }
+ else {
+ atoms[count++] = _NET_WM_STATE_FULLSCREEN;
+ }
+
+ XChangeProperty(m_display, m_window, _NET_WM_STATE, XA_ATOM, 32,
+ PropModeReplace, (unsigned char *)atoms, count);
+ m_post_init = False;
+ }
/*
* One of the problem with WM-spec is that can't set a property
* to a window that isn't mapped. That is why we can't "just
@@ -345,7 +366,7 @@ GHOST_WindowX11(
* So, m_post_init indicate that we need wait for the MapNotify
* event and then set the Window state to the m_post_state.
*/
- if ((state != GHOST_kWindowStateNormal) && (state != GHOST_kWindowStateMinimized)) {
+ else if ((state != GHOST_kWindowStateNormal) && (state != GHOST_kWindowStateMinimized)) {
m_post_init = True;
m_post_state = state;
}
@@ -381,16 +402,16 @@ GHOST_WindowX11(
XFree(xclasshint);
/* The basic for a good ICCCM "work" */
- if (m_system->m_wm_protocols) {
+ if (m_system->m_atom.WM_PROTOCOLS) {
natom = 0;
- if (m_system->m_delete_window_atom) {
- atoms[natom] = m_system->m_delete_window_atom;
+ if (m_system->m_atom.WM_DELETE_WINDOW) {
+ atoms[natom] = m_system->m_atom.WM_DELETE_WINDOW;
natom++;
}
- if (m_system->m_wm_take_focus) {
- atoms[natom] = m_system->m_wm_take_focus;
+ if (m_system->m_atom.WM_TAKE_FOCUS) {
+ atoms[natom] = m_system->m_atom.WM_TAKE_FOCUS;
natom++;
}
@@ -404,63 +425,28 @@ GHOST_WindowX11(
m_xic = NULL;
#endif
- /* Set the window icon */
+ /* Set the window hints */
XWMHints *xwmhints = XAllocWMHints();
- XImage *x_image, *mask_image;
- Pixmap icon_pixmap, mask_pixmap;
- icon_pixmap = XCreatePixmap(display, m_window, BLENDER_ICON_WIDTH, BLENDER_ICON_HEIGHT, 24);
- mask_pixmap = XCreatePixmap(display, m_window, BLENDER_ICON_WIDTH, BLENDER_ICON_HEIGHT, 1);
- GC gc_icon = XCreateGC(display, icon_pixmap, 0, NULL);
- GC gc_mask = XCreateGC(display, mask_pixmap, 0, NULL);
-
- x_image = XCreateImage(display, m_visual->visual, 24, ZPixmap, 0, NULL, BLENDER_ICON_WIDTH, BLENDER_ICON_HEIGHT, 32, 0);
- mask_image = XCreateImage(display, m_visual->visual, 1, ZPixmap, 0, NULL, BLENDER_ICON_WIDTH, BLENDER_ICON_HEIGHT, 8, 0);
-
- x_image->data = (char *)calloc(x_image->bytes_per_line * BLENDER_ICON_HEIGHT, 1);
- mask_image->data = (char *)calloc(mask_image->bytes_per_line * BLENDER_ICON_HEIGHT, 1);
-
- /* copy the BLENDER_ICON_48x48x24 into the XImage */
- unsigned char *col = BLENDER_ICON_48x48x24;
- int px, py;
- for (px = 0; px < BLENDER_ICON_WIDTH; px++) {
- for (py = 0; py < BLENDER_ICON_HEIGHT; py++, col += 3) {
- /* mask out pink */
- if (col[0] == 255 && col[1] == 0 && col[2] == 255) {
-#if 0
- /* instead, use calloc above */
- XPutPixel(x_image, px, py, 0); /* avoid uninitialized memory, otherwise not needed */
- XPutPixel(mask_image, px, py, 0);
-#endif
- }
- else {
- XPutPixel(x_image, px, py, (col[0] << 16) + (col[1] << 8) + col[2]);
- XPutPixel(mask_image, px, py, 1);
- }
- }
- }
-
- XPutImage(display, icon_pixmap, gc_icon, x_image, 0, 0, 0, 0, BLENDER_ICON_WIDTH, BLENDER_ICON_HEIGHT);
- XPutImage(display, mask_pixmap, gc_mask, mask_image, 0, 0, 0, 0, BLENDER_ICON_WIDTH, BLENDER_ICON_HEIGHT);
-
- /* Now the pixmap is ok to assign to the window as a hint */
- xwmhints->icon_pixmap = icon_pixmap;
- xwmhints->icon_mask = mask_pixmap;
- XFreeGC(display, gc_icon);
- XFreeGC(display, gc_mask);
- XDestroyImage(x_image); /* frees x_image->data too */
- XDestroyImage(mask_image);
-
xwmhints->initial_state = NormalState;
xwmhints->input = True;
- xwmhints->flags = InputHint | IconPixmapHint | IconMaskHint | StateHint;
+ xwmhints->flags = InputHint | StateHint;
XSetWMHints(display, m_window, xwmhints);
XFree(xwmhints);
+ /* done setting the hints */
+
+ /* 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 */
setTitle(title);
#ifdef WITH_X11_XINPUT
initXInputDevices();
+
+ m_tabletData.Active = GHOST_kTabletModeNone;
#endif
/* now set up the rendering context. */
@@ -469,7 +455,12 @@ GHOST_WindowX11(
GHOST_PRINT("Created window\n");
}
- XMapWindow(m_display, m_window);
+ if (exclusive) {
+ XMapRaised(m_display, m_window);
+ }
+ else {
+ XMapWindow(m_display, m_window);
+ }
GHOST_PRINT("Mapped window\n");
XFlush(m_display);
@@ -511,206 +502,36 @@ bool GHOST_WindowX11::createX11_XIC()
EnterWindowMask | LeaveWindowMask |
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | FocusChangeMask |
- PropertyChangeMask | fevent);
+ PropertyChangeMask | KeymapStateMask | fevent);
return true;
}
#endif
#ifdef WITH_X11_XINPUT
-/*
- * 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.
- */
-static int ApplicationErrorHandler(Display *display, XErrorEvent *theEvent)
-{
- fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n",
- theEvent->error_code, theEvent->request_code);
-
- /* No exit! - but keep lint happy */
- return 0;
-}
-
-/* These C functions are copied from Wine 1.1.13's wintab.c */
-#define BOOL int
-#define TRUE 1
-#define FALSE 0
-
-static bool match_token(const char *haystack, const char *needle)
-{
- const char *p, *q;
- for (p = haystack; *p; )
- {
- while (*p && isspace(*p))
- p++;
- if (!*p)
- break;
-
- for (q = needle; *q && *p && tolower(*p) == tolower(*q); q++)
- p++;
- if (!*q && (isspace(*p) || !*p))
- return TRUE;
-
- while (*p && !isspace(*p))
- p++;
- }
- return FALSE;
-}
-
-
-/* Determining if an X device is a Tablet style device is an imperfect science.
- * We rely on common conventions around device names as well as the type reported
- * by Wacom tablets. This code will likely need to be expanded for alternate tablet types
- *
- * Wintab refers to any device that interacts with the tablet as a cursor,
- * (stylus, eraser, tablet mouse, airbrush, etc)
- * this is not to be confused with wacom x11 configuration "cursor" device.
- * Wacoms x11 config "cursor" refers to its device slot (which we mirror with
- * our gSysCursors) for puck like devices (tablet mice essentially).
- */
-#if 0 // unused
-static BOOL is_tablet_cursor(const char *name, const char *type)
-{
- int i;
- static const char *tablet_cursor_whitelist[] = {
- "wacom",
- "wizardpen",
- "acecad",
- "tablet",
- "cursor",
- "stylus",
- "eraser",
- "pad",
- NULL
- };
-
- for (i = 0; tablet_cursor_whitelist[i] != NULL; i++) {
- if (name && match_token(name, tablet_cursor_whitelist[i]))
- return TRUE;
- if (type && match_token(type, tablet_cursor_whitelist[i]))
- return TRUE;
- }
- return FALSE;
-}
-#endif
-static BOOL is_stylus(const char *name, const char *type)
-{
- int i;
- static const char *tablet_stylus_whitelist[] = {
- "stylus",
- "wizardpen",
- "acecad",
- NULL
- };
-
- for (i = 0; tablet_stylus_whitelist[i] != NULL; i++) {
- if (name && match_token(name, tablet_stylus_whitelist[i]))
- return TRUE;
- if (type && match_token(type, tablet_stylus_whitelist[i]))
- return TRUE;
- }
-
- return FALSE;
-}
-
-static BOOL is_eraser(const char *name, const char *type)
-{
- if (name && match_token(name, "eraser"))
- return TRUE;
- if (type && match_token(type, "eraser"))
- return TRUE;
- return FALSE;
-}
-#undef BOOL
-#undef TRUE
-#undef FALSE
-/* end code copied from wine */
-
void GHOST_WindowX11::initXInputDevices()
{
- static XErrorHandler old_handler = (XErrorHandler) 0;
XExtensionVersion *version = XGetExtensionVersion(m_display, INAME);
if (version && (version != (XExtensionVersion *)NoSuchExtension)) {
if (version->present) {
- int device_count;
- XDeviceInfo *device_info = XListInputDevices(m_display, &device_count);
- m_xtablet.StylusDevice = NULL;
- m_xtablet.EraserDevice = NULL;
- m_xtablet.CommonData.Active = GHOST_kTabletModeNone;
-
- /* Install our error handler to override Xlib's termination behavior */
- old_handler = XSetErrorHandler(ApplicationErrorHandler);
-
- for (int i = 0; i < device_count; ++i) {
- char *device_type = device_info[i].type ? XGetAtomName(m_display, device_info[i].type) : NULL;
-
-// printf("Tablet type:'%s', name:'%s', index:%d\n", device_type, device_info[i].name, i);
-
-
- if (m_xtablet.StylusDevice == NULL && is_stylus(device_info[i].name, device_type)) {
-// printf("\tfound stylus\n");
- m_xtablet.StylusID = device_info[i].id;
- m_xtablet.StylusDevice = XOpenDevice(m_display, m_xtablet.StylusID);
-
- if (m_xtablet.StylusDevice != NULL) {
- /* Find how many pressure levels tablet has */
- XAnyClassPtr ici = device_info[i].inputclassinfo;
- for (int j = 0; j < m_xtablet.StylusDevice->num_classes; ++j) {
- if (ici->c_class == ValuatorClass) {
-// printf("\t\tfound ValuatorClass\n");
- XValuatorInfo *xvi = (XValuatorInfo *)ici;
- m_xtablet.PressureLevels = xvi->axes[2].max_value;
-
- /* this is assuming that the tablet has the same tilt resolution in both
- * positive and negative directions. It would be rather weird if it didn't.. */
- m_xtablet.XtiltLevels = xvi->axes[3].max_value;
- m_xtablet.YtiltLevels = xvi->axes[4].max_value;
- break;
- }
-
- ici = (XAnyClassPtr)(((char *)ici) + ici->length);
- }
- }
- else {
- m_xtablet.StylusID = 0;
- }
- }
- else if (m_xtablet.EraserDevice == NULL && is_eraser(device_info[i].name, device_type)) {
-// printf("\tfound eraser\n");
- m_xtablet.EraserID = device_info[i].id;
- m_xtablet.EraserDevice = XOpenDevice(m_display, m_xtablet.EraserID);
- if (m_xtablet.EraserDevice == NULL) m_xtablet.EraserID = 0;
- }
-
- if (device_type) {
- XFree((void *)device_type);
- }
- }
-
- /* Restore handler */
- (void) XSetErrorHandler(old_handler);
-
- XFreeDeviceList(device_info);
-
-
+ GHOST_SystemX11::GHOST_TabletX11 &xtablet = m_system->GetXTablet();
XEventClass xevents[10], ev;
int dcount = 0;
- if (m_xtablet.StylusDevice) {
- DeviceMotionNotify(m_xtablet.StylusDevice, m_xtablet.MotionEvent, ev);
+ if (xtablet.StylusDevice) {
+ DeviceMotionNotify(xtablet.StylusDevice, xtablet.MotionEvent, ev);
if (ev) xevents[dcount++] = ev;
- ProximityIn(m_xtablet.StylusDevice, m_xtablet.ProxInEvent, ev);
+ ProximityIn(xtablet.StylusDevice, xtablet.ProxInEvent, ev);
if (ev) xevents[dcount++] = ev;
- ProximityOut(m_xtablet.StylusDevice, m_xtablet.ProxOutEvent, ev);
+ ProximityOut(xtablet.StylusDevice, xtablet.ProxOutEvent, ev);
if (ev) xevents[dcount++] = ev;
}
- if (m_xtablet.EraserDevice) {
- DeviceMotionNotify(m_xtablet.EraserDevice, m_xtablet.MotionEvent, ev);
+ if (xtablet.EraserDevice) {
+ DeviceMotionNotify(xtablet.EraserDevice, xtablet.MotionEvent, ev);
if (ev) xevents[dcount++] = ev;
- ProximityIn(m_xtablet.EraserDevice, m_xtablet.ProxInEvent, ev);
+ ProximityIn(xtablet.EraserDevice, xtablet.ProxInEvent, ev);
if (ev) xevents[dcount++] = ev;
- ProximityOut(m_xtablet.EraserDevice, m_xtablet.ProxOutEvent, ev);
+ ProximityOut(xtablet.EraserDevice, xtablet.ProxOutEvent, ev);
if (ev) xevents[dcount++] = ev;
}
@@ -898,7 +719,7 @@ void GHOST_WindowX11::icccmSetState(int state)
xev.xclient.display = m_display;
xev.xclient.window = m_window;
xev.xclient.format = 32;
- xev.xclient.message_type = m_system->m_wm_change_state;
+ 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)),
False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
@@ -912,8 +733,8 @@ int GHOST_WindowX11::icccmGetState(void) const
int format_ret, st;
prop_ret = NULL;
- st = XGetWindowProperty(m_display, m_window, m_system->m_wm_state, 0,
- 0x7fffffff, False, m_system->m_wm_state, &type_ret,
+ st = XGetWindowProperty(m_display, m_window, m_system->m_atom.WM_STATE, 0,
+ 0x7fffffff, False, m_system->m_atom.WM_STATE, &type_ret,
&format_ret, &num_ret, &bytes_after, &prop_ret);
if ((st == Success) && (prop_ret) && (num_ret == 2))
@@ -934,7 +755,7 @@ void GHOST_WindowX11::netwmMaximized(bool set)
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.window = m_window;
- xev.xclient.message_type = m_system->m_net_state;
+ xev.xclient.message_type = m_system->m_atom._NET_WM_STATE;
xev.xclient.format = 32;
if (set == True)
@@ -942,8 +763,8 @@ void GHOST_WindowX11::netwmMaximized(bool set)
else
xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
- xev.xclient.data.l[1] = m_system->m_net_max_horz;
- xev.xclient.data.l[2] = m_system->m_net_max_vert;
+ xev.xclient.data.l[1] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_HORZ;
+ 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)),
@@ -960,15 +781,15 @@ bool GHOST_WindowX11::netwmIsMaximized(void) const
prop_ret = NULL;
st = False;
- ret = XGetWindowProperty(m_display, m_window, m_system->m_net_state, 0,
+ ret = XGetWindowProperty(m_display, m_window, m_system->m_atom._NET_WM_STATE, 0,
0x7fffffff, False, XA_ATOM, &type_ret, &format_ret,
&num_ret, &bytes_after, &prop_ret);
if ((ret == Success) && (prop_ret) && (format_ret == 32)) {
count = 0;
for (i = 0; i < num_ret; i++) {
- if (((unsigned long *) prop_ret)[i] == m_system->m_net_max_horz)
+ if (((unsigned long *) prop_ret)[i] == m_system->m_atom._NET_WM_STATE_MAXIMIZED_HORZ)
count++;
- if (((unsigned long *) prop_ret)[i] == m_system->m_net_max_vert)
+ if (((unsigned long *) prop_ret)[i] == m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT)
count++;
if (count == 2) {
st = True;
@@ -990,7 +811,7 @@ void GHOST_WindowX11::netwmFullScreen(bool set)
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.window = m_window;
- xev.xclient.message_type = m_system->m_net_state;
+ xev.xclient.message_type = m_system->m_atom._NET_WM_STATE;
xev.xclient.format = 32;
if (set == True)
@@ -998,7 +819,7 @@ void GHOST_WindowX11::netwmFullScreen(bool set)
else
xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
- xev.xclient.data.l[1] = m_system->m_net_fullscreen;
+ xev.xclient.data.l[1] = m_system->m_atom._NET_WM_STATE_FULLSCREEN;
xev.xclient.data.l[2] = 0;
xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0;
@@ -1016,12 +837,12 @@ bool GHOST_WindowX11::netwmIsFullScreen(void) const
prop_ret = NULL;
st = False;
- ret = XGetWindowProperty(m_display, m_window, m_system->m_net_state, 0,
+ ret = XGetWindowProperty(m_display, m_window, m_system->m_atom._NET_WM_STATE, 0,
0x7fffffff, False, XA_ATOM, &type_ret, &format_ret,
&num_ret, &bytes_after, &prop_ret);
if ((ret == Success) && (prop_ret) && (format_ret == 32)) {
for (i = 0; i < num_ret; i++) {
- if (((unsigned long *) prop_ret)[i] == m_system->m_net_fullscreen) {
+ if (((unsigned long *) prop_ret)[i] == m_system->m_atom._NET_WM_STATE_FULLSCREEN) {
st = True;
break;
}
@@ -1043,8 +864,8 @@ void GHOST_WindowX11::motifFullScreen(bool set)
else
hints.decorations = 1;
- XChangeProperty(m_display, m_window, m_system->m_motif,
- m_system->m_motif, 32, PropModeReplace,
+ XChangeProperty(m_display, m_window, m_system->m_atom._MOTIF_WM_HINTS,
+ m_system->m_atom._MOTIF_WM_HINTS, 32, PropModeReplace,
(unsigned char *) &hints, 4);
}
@@ -1059,8 +880,8 @@ bool GHOST_WindowX11::motifIsFullScreen(void) const
prop_ret = NULL;
state = False;
- st = XGetWindowProperty(m_display, m_window, m_system->m_motif, 0,
- 0x7fffffff, False, m_system->m_motif,
+ st = XGetWindowProperty(m_display, m_window, m_system->m_atom._MOTIF_WM_HINTS, 0,
+ 0x7fffffff, False, m_system->m_atom._MOTIF_WM_HINTS,
&type_ret, &format_ret, &num_ret,
&bytes_after, &prop_ret);
if ((st == Success) && (prop_ret)) {
@@ -1089,12 +910,12 @@ GHOST_TWindowState GHOST_WindowX11::getState() const
*/
if ((state == IconicState) || (state == WithdrawnState))
state_ret = GHOST_kWindowStateMinimized;
- else if (netwmIsMaximized() == True)
- state_ret = GHOST_kWindowStateMaximized;
else if (netwmIsFullScreen() == True)
state_ret = GHOST_kWindowStateFullScreen;
else if (motifIsFullScreen() == True)
state_ret = GHOST_kWindowStateFullScreen;
+ else if (netwmIsMaximized() == True)
+ state_ret = GHOST_kWindowStateMaximized;
return (state_ret);
}
@@ -1341,15 +1162,6 @@ GHOST_WindowX11::
XFreeCursor(m_display, m_custom_cursor);
}
-#ifdef WITH_X11_XINPUT
- /* close tablet devices */
- if (m_xtablet.StylusDevice)
- XCloseDevice(m_display, m_xtablet.StylusDevice);
-
- if (m_xtablet.EraserDevice)
- XCloseDevice(m_display, m_xtablet.EraserDevice);
-#endif /* WITH_X11_XINPUT */
-
if (m_context != s_firstContext) {
glXDestroyContext(m_display, m_context);
}
@@ -1392,6 +1204,15 @@ installDrawingContext(
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);
+#endif
+
m_context = glXCreateContext(m_display, m_visual, s_firstContext, True);
if (m_context != NULL) {
if (!s_firstContext) {
@@ -1406,12 +1227,18 @@ installDrawingContext(
success = GHOST_kFailure;
}
+#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;
}
@@ -1645,3 +1472,44 @@ setWindowCustomCursorShape(
return GHOST_kSuccess;
}
+
+
+GHOST_TSuccess
+GHOST_WindowX11::
+beginFullScreen() const
+{
+ {
+ Window root_return;
+ int x_return, y_return;
+ unsigned int w_return, h_return, border_w_return, depth_return;
+
+ XGetGeometry(m_display, m_window, &root_return, &x_return, &y_return,
+ &w_return, &h_return, &border_w_return, &depth_return);
+
+ m_system->setCursorPosition(w_return / 2, h_return / 2);
+ }
+
+
+ /* Grab Keyboard & Mouse */
+ int err;
+
+ err = XGrabKeyboard(m_display, m_window, False,
+ GrabModeAsync, GrabModeAsync, CurrentTime);
+ if (err != GrabSuccess) printf("XGrabKeyboard failed %d\n", err);
+
+ err = XGrabPointer(m_display, m_window, False, PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
+ GrabModeAsync, GrabModeAsync, m_window, None, CurrentTime);
+ if (err != GrabSuccess) printf("XGrabPointer failed %d\n", err);
+
+ return GHOST_kSuccess;
+}
+
+GHOST_TSuccess
+GHOST_WindowX11::
+endFullScreen() const
+{
+ XUngrabKeyboard(m_display, CurrentTime);
+ XUngrabPointer(m_display, CurrentTime);
+
+ return GHOST_kSuccess;
+}
diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h
index 5b2ffced29c..b8471b41a11 100644
--- a/intern/ghost/intern/GHOST_WindowX11.h
+++ b/intern/ghost/intern/GHOST_WindowX11.h
@@ -87,6 +87,7 @@ public:
const GHOST_TEmbedderWindowID parentWindow,
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
const bool stereoVisual = false,
+ const bool exclusive = false,
const GHOST_TUns16 numOfAASamples = 0
);
@@ -196,32 +197,9 @@ public:
getXWindow(
);
#ifdef WITH_X11_XINPUT
- class XTablet
+ GHOST_TabletData *GetTabletData()
{
-public:
- GHOST_TabletData CommonData;
-
- XDevice *StylusDevice;
- XDevice *EraserDevice;
-
- XID StylusID, EraserID;
-
- int MotionEvent;
- int ProxInEvent;
- int ProxOutEvent;
-
- int PressureLevels;
- int XtiltLevels, YtiltLevels;
- };
-
- XTablet& GetXTablet()
- {
- return m_xtablet;
- }
-
- const GHOST_TabletData *GetTabletData()
- {
- return &m_xtablet.CommonData;
+ return &m_tabletData;
}
#else // WITH_X11_XINPUT
const GHOST_TabletData *GetTabletData()
@@ -253,6 +231,10 @@ public:
bool m_post_init;
GHOST_TWindowState m_post_state;
+ GHOST_TSuccess beginFullScreen() const;
+
+ GHOST_TSuccess endFullScreen() const;
+
protected:
/**
* Tries to install a rendering context in this window.
@@ -387,8 +369,7 @@ private:
#endif
#ifdef WITH_X11_XINPUT
- /* Tablet devices */
- XTablet m_xtablet;
+ GHOST_TabletData m_tabletData;
#endif
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h
index 6973c19dea9..dd22cf7c484 100644
--- a/intern/guardedalloc/MEM_guardedalloc.h
+++ b/intern/guardedalloc/MEM_guardedalloc.h
@@ -165,7 +165,7 @@ extern "C" {
void MEM_printmemlist(void);
/** calls the function on all allocated memory blocks. */
- void MEM_callbackmemlist(void (*func)(void*));
+ void MEM_callbackmemlist(void (*func)(void *));
/** Print statistics about memory usage */
void MEM_printmemlist_stats(void);
diff --git a/intern/guardedalloc/SConscript b/intern/guardedalloc/SConscript
index 74d6e07269f..0712e1c4489 100644
--- a/intern/guardedalloc/SConscript
+++ b/intern/guardedalloc/SConscript
@@ -1,4 +1,29 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
Import('env')
diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c
index 4a79f5d0de1..93cb2f6d4d1 100644
--- a/intern/guardedalloc/intern/mallocn.c
+++ b/intern/guardedalloc/intern/mallocn.c
@@ -52,6 +52,10 @@
# include <sys/mman.h>
#endif
+#if defined(_MSC_VER)
+# define __func__ __FUNCTION__
+#endif
+
#include "MEM_guardedalloc.h"
/* Only for debugging:
@@ -68,6 +72,17 @@
//#define DEBUG_MEMCOUNTER
+/* Only for debugging:
+ * defining DEBUG_THREADS will enable check whether memory manager
+ * is locked with a mutex when allocation is called from non-main
+ * thread.
+ *
+ * This helps troubleshooting memory issues caused by the fact
+ * guarded allocator is not thread-safe, however this check will
+ * fail to check allocations from openmp threads.
+ */
+//#define DEBUG_THREADS
+
#ifdef DEBUG_MEMCOUNTER
/* set this to the value that isn't being freed */
# define DEBUG_MEMCOUNTER_ERROR_VAL 0
@@ -110,6 +125,24 @@ typedef struct MemHead {
#endif
} MemHead;
+/* for openmp threading asserts, saves time troubleshooting
+ * we may need to extend this if blender code starts using MEM_
+ * functions inside OpenMP correctly with omp_set_lock() */
+
+#if 0 /* disable for now, only use to debug openmp code which doesn lock threads for malloc */
+#if defined(_OPENMP) && defined(DEBUG)
+# include <assert.h>
+# include <omp.h>
+# define DEBUG_OMP_MALLOC
+#endif
+#endif
+
+#ifdef DEBUG_THREADS
+# include <assert.h>
+# include <pthread.h>
+static pthread_t mainid;
+#endif
+
typedef struct MemTail {
int tag3, pad;
} MemTail;
@@ -194,6 +227,24 @@ static void print_error(const char *str, ...)
static void mem_lock_thread(void)
{
+#ifdef DEBUG_THREADS
+ static int initialized = 0;
+
+ if (initialized == 0) {
+ /* assume first allocation happens from main thread */
+ mainid = pthread_self();
+ initialized = 1;
+ }
+
+ if (!pthread_equal(pthread_self(), mainid) && thread_lock_callback == NULL) {
+ assert(!"Memory function is called from non-main thread without lock");
+ }
+#endif
+
+#ifdef DEBUG_OMP_MALLOC
+ assert(omp_in_parallel() == 0);
+#endif
+
if (thread_lock_callback)
thread_lock_callback();
}
@@ -214,8 +265,7 @@ int MEM_check_memory_integrity(void)
err_val = check_memlist(listend);
- if (err_val == NULL) return 0;
- return 1;
+ return (err_val != NULL);
}
@@ -314,6 +364,9 @@ void *MEM_reallocN(void *vmemh, size_t len)
MEM_freeN(vmemh);
}
+ else {
+ newp = MEM_mallocN(len, __func__);
+ }
return newp;
}
@@ -345,6 +398,9 @@ void *MEM_recallocN(void *vmemh, size_t len)
MEM_freeN(vmemh);
}
+ else {
+ newp = MEM_callocN(len, __func__);
+ }
return newp;
}
@@ -546,6 +602,8 @@ void MEM_printmemlist_stats(void)
qsort(printblock, totpb, sizeof(MemPrintBlock), compare_len);
printf("\ntotal memory len: %.3f MB\n",
(double)mem_in_use / (double)(1024 * 1024));
+ printf("peak memory len: %.3f MB\n",
+ (double)peak_mem / (double)(1024 * 1024));
printf(" ITEMS TOTAL-MiB AVERAGE-KiB TYPE\n");
for (a = 0, pb = printblock; a < totpb; a++, pb++) {
printf("%6d (%8.3f %8.3f) %s\n",
diff --git a/intern/iksolver/SConscript b/intern/iksolver/SConscript
index b88d3b1b713..ba973ad5fd5 100644
--- a/intern/iksolver/SConscript
+++ b/intern/iksolver/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('intern/*.cpp')
diff --git a/intern/iksolver/intern/IK_Solver.cpp b/intern/iksolver/intern/IK_Solver.cpp
index c1a4ffcb1e8..65ea4d64ab1 100644
--- a/intern/iksolver/intern/IK_Solver.cpp
+++ b/intern/iksolver/intern/IK_Solver.cpp
@@ -348,6 +348,7 @@ float IK_SolverGetPoleAngle(IK_Solver *solver)
return qsolver->solver.GetPoleAngle();
}
+#if 0
static void IK_SolverAddCenterOfMass(IK_Solver *solver, IK_Segment *root, float goal[3], float weight)
{
if (solver == NULL || root == NULL)
@@ -363,6 +364,7 @@ static void IK_SolverAddCenterOfMass(IK_Solver *solver, IK_Segment *root, float
com->SetWeight(weight);
qsolver->tasks.push_back(com);
}
+#endif
int IK_Solve(IK_Solver *solver, float tolerance, int max_iterations)
{
diff --git a/intern/itasc/Armature.cpp b/intern/itasc/Armature.cpp
index 78780ed8ba3..e6f5fda4066 100644
--- a/intern/itasc/Armature.cpp
+++ b/intern/itasc/Armature.cpp
@@ -32,7 +32,9 @@ Armature::Armature():
m_qCCh(-1),
m_qCTs(0),
m_yCCh(-1),
+#if 0
m_yCTs(0),
+#endif
m_qKdl(),
m_oldqKdl(),
m_newqKdl(),
@@ -168,7 +170,7 @@ bool Armature::popQ(CacheTS timestamp)
{
if (m_qCCh >= 0) {
double* item;
- item = (double*)m_cache->getPreviousCacheItem(this, m_qCCh, &timestamp);
+ item = (double *)m_cache->getPreviousCacheItem(this, m_qCCh, &timestamp);
if (item && m_qCTs != timestamp) {
double* q = m_qKdl(0);
memcpy(q, item, m_qKdl.rows()*sizeof(double));
@@ -696,8 +698,8 @@ void Armature::updateControlOutput(const Timestamp& timestamp)
JointConstraint_struct* pConstraint = *it;
unsigned int nr, i;
for (i=0, nr = pConstraint->segment->second.q_nr; i<pConstraint->v_nr; i++, nr++) {
- *(double*)&pConstraint->value[i].y = m_qKdl[nr];
- *(double*)&pConstraint->value[i].ydot = m_qdotKdl[nr];
+ *(double *)&pConstraint->value[i].y = m_qKdl[nr];
+ *(double *)&pConstraint->value[i].ydot = m_qdotKdl[nr];
}
if (pConstraint->function && (pConstraint->substep || (!timestamp.reiterate && !timestamp.substep))) {
(*pConstraint->function)(timestamp, pConstraint->values, pConstraint->v_nr, pConstraint->param);
diff --git a/intern/itasc/Armature.hpp b/intern/itasc/Armature.hpp
index 63d1899f4e9..3167247ab03 100644
--- a/intern/itasc/Armature.hpp
+++ b/intern/itasc/Armature.hpp
@@ -111,7 +111,9 @@ private:
int m_qCCh;
CacheTS m_qCTs;
int m_yCCh;
+#if 0
CacheTS m_yCTs;
+#endif
JntArray m_qKdl;
JntArray m_oldqKdl;
JntArray m_newqKdl;
diff --git a/intern/itasc/SConscript b/intern/itasc/SConscript
index c1ad931c665..208fee5f2d3 100644
--- a/intern/itasc/SConscript
+++ b/intern/itasc/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.cpp')
diff --git a/intern/itasc/kdl/chain.hpp b/intern/itasc/kdl/chain.hpp
index fde9d4ed23e..1776737fc7d 100644
--- a/intern/itasc/kdl/chain.hpp
+++ b/intern/itasc/kdl/chain.hpp
@@ -36,7 +36,7 @@ namespace KDL {
class Chain {
private:
#if defined(__APPLE__)
-# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5
+# if MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
std::vector<Segment> segments;
# else
// Eigen allocator is needed for alignment of Eigen data types
diff --git a/intern/itasc/kdl/segment.cpp b/intern/itasc/kdl/segment.cpp
index f963559c4c8..fbb775f6682 100644
--- a/intern/itasc/kdl/segment.cpp
+++ b/intern/itasc/kdl/segment.cpp
@@ -25,13 +25,13 @@
namespace KDL {
Segment::Segment(const Joint& _joint, const Frame& _f_tip, const Inertia& _M):
- joint(_joint),M(_M),
+ M(_M),joint(_joint),
f_tip(_f_tip)
{
}
Segment::Segment(const Segment& in):
- joint(in.joint),M(in.M),
+ M(in.M),joint(in.joint),
f_tip(in.f_tip)
{
}
diff --git a/intern/itasc/kdl/tree.hpp b/intern/itasc/kdl/tree.hpp
index a020c6cf2cf..82794f96b94 100644
--- a/intern/itasc/kdl/tree.hpp
+++ b/intern/itasc/kdl/tree.hpp
@@ -28,7 +28,7 @@
#include <string>
#include <map>
#if defined(__APPLE__)
-# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5
+# if MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
//no include
# else
# include <Eigen/Core>
@@ -42,7 +42,7 @@ namespace KDL
//Forward declaration
class TreeElement;
#if defined(__APPLE__)
-# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5
+# if MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
typedef std::map<std::string,TreeElement> SegmentMap;
# else
// Eigen allocator is needed for alignment of Eigen data types
diff --git a/intern/locale/SConscript b/intern/locale/SConscript
index df745f093ea..f60bd90fb38 100644
--- a/intern/locale/SConscript
+++ b/intern/locale/SConscript
@@ -1,4 +1,29 @@
-#!/usr/bin/python
+#!/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) 2012, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Bastien Montagne.
+#
+# ***** END GPL LICENSE BLOCK *****
Import('env')
diff --git a/intern/locale/boost_locale_wrapper.cpp b/intern/locale/boost_locale_wrapper.cpp
index 939c66bad13..81c348e52f1 100644
--- a/intern/locale/boost_locale_wrapper.cpp
+++ b/intern/locale/boost_locale_wrapper.cpp
@@ -33,6 +33,7 @@
static std::string messages_path;
static std::string default_domain;
+static std::string locale_str;
void bl_locale_init(const char *_messages_path, const char *_default_domain)
{
@@ -52,47 +53,52 @@ void bl_locale_init(const char *_messages_path, const char *_default_domain)
void bl_locale_set(const char *locale)
{
boost::locale::generator gen;
+ std::locale _locale;
// Specify location of dictionaries.
gen.add_messages_path(messages_path);
gen.add_messages_domain(default_domain);
- //gen.set_default_messages_domain(default_domain);
+ //gen.set_default_messages_domain(default_domain);
- if (locale && locale[0]) {
- std::locale::global(gen(locale));
- }
- else {
-#if defined (__APPLE__)
- // workaround to get osx system locale from user defaults
- FILE* fp;
- std::string locale_osx = "";
- char result[16];
- int result_len = 0;
-
- fp = popen("defaults read .GlobalPreferences AppleLocale", "r");
-
- if(fp) {
- result_len = fread(result, 1, sizeof(result) - 1, fp);
-
- if(result_len > 0) {
- result[result_len-1] = '\0'; // \0 terminate and remove \n
- locale_osx = std::string(result) + std::string(".UTF-8");
- }
-
- pclose(fp);
+ try {
+ if (locale && locale[0]) {
+ _locale = gen(locale);
+ std::locale::global(_locale);
}
-
- if(locale_osx == "")
- fprintf(stderr, "Locale set: failed to read AppleLocale read from defaults\n");
-
- std::locale::global(gen(locale_osx.c_str()));
+ else {
+#ifdef __APPLE__
+ extern const char *user_locale; // pulled from Ghost_SystemCocoa
+ std::string locale_osx = user_locale + std::string(".UTF-8");
+ _locale = gen(locale_osx.c_str());
+ std::locale::global(_locale);
#else
- std::locale::global(gen(""));
+ _locale = gen("");
+ std::locale::global(_locale);
#endif
+ }
+ // Note: boost always uses "C" LC_NUMERIC by default!
+ }
+ catch(std::exception const &e) {
+ std::cout << "bl_locale_set(" << locale << "): " << e.what() << " \n";
+ }
+
+ /* Generate the locale string (useful to know which locale we are actually using in case of "default" one). */
+#define LOCALE_INFO std::use_facet<boost::locale::info>(_locale)
+
+ locale_str = LOCALE_INFO.language();
+ if (LOCALE_INFO.country() != "") {
+ locale_str += "_" + LOCALE_INFO.country();
+ }
+ if (LOCALE_INFO.variant() != "") {
+ locale_str += "@" + LOCALE_INFO.variant();
}
- // Note: boost always uses "C" LC_NUMERIC by default!
}
-const char* bl_locale_pgettext(const char *msgctxt, const char *msgid)
+const char *bl_locale_get(void)
+{
+ return locale_str.c_str();
+}
+
+const char *bl_locale_pgettext(const char *msgctxt, const char *msgid)
{
// Note: We cannot use short stuff like boost::locale::gettext, because those return
// std::basic_string objects, which c_ptr()-returned char* is no more valid
@@ -107,8 +113,7 @@ const char* bl_locale_pgettext(const char *msgctxt, const char *msgid)
return msgid;
}
catch(std::exception const &e) {
-// std::cout << "boost_locale_pgettext: " << e.what() << " \n";
+// std::cout << "bl_locale_pgettext(" << msgctxt << ", " << msgid << "): " << e.what() << " \n";
return msgid;
}
-}
-
+} \ No newline at end of file
diff --git a/intern/locale/boost_locale_wrapper.h b/intern/locale/boost_locale_wrapper.h
index e7956d216f1..ff3645a5983 100644
--- a/intern/locale/boost_locale_wrapper.h
+++ b/intern/locale/boost_locale_wrapper.h
@@ -40,8 +40,9 @@ extern "C" {
void bl_locale_init(const char *messages_path, const char *default_domain);
void bl_locale_set(const char *locale);
-const char* bl_locale_pgettext(const char *msgctxt, const char *msgid);
-
+const char *bl_locale_get(void);
+const char *bl_locale_pgettext(const char *msgctxt, const char *msgid);
+
#ifdef __cplusplus
}
#endif
diff --git a/intern/memutil/MEM_Allocator.h b/intern/memutil/MEM_Allocator.h
index 0020094ebbb..b4c0559b511 100644
--- a/intern/memutil/MEM_Allocator.h
+++ b/intern/memutil/MEM_Allocator.h
@@ -63,7 +63,7 @@ struct MEM_Allocator
// NB: __n is permitted to be 0. The C++ standard says nothing
// about what the return value is when __n == 0.
_Tp* allocate(size_type __n, const void* = 0) {
- _Tp* __ret = 0;
+ _Tp* __ret = NULL;
if (__n)
__ret = static_cast<_Tp*>(
MEM_mallocN(__n * sizeof(_Tp),
diff --git a/intern/memutil/MEM_CacheLimiter.h b/intern/memutil/MEM_CacheLimiter.h
index daf66dc05b1..dec4d0b1c30 100644
--- a/intern/memutil/MEM_CacheLimiter.h
+++ b/intern/memutil/MEM_CacheLimiter.h
@@ -108,7 +108,7 @@ public:
bool destroy_if_possible() {
if (can_destroy()) {
delete data;
- data = 0;
+ data = NULL;
unmanage();
return true;
}
@@ -161,6 +161,13 @@ public:
delete handle;
}
+ size_t get_memory_in_use() {
+ if (getDataSize)
+ return total_size();
+ else
+ return MEM_get_memory_in_use();
+ }
+
void enforce_limits() {
size_t max = MEM_CacheLimiter_get_maximum();
size_t mem_in_use, cur_size;
@@ -169,12 +176,7 @@ public:
return;
}
- if (getDataSize) {
- mem_in_use = total_size();
- }
- else {
- mem_in_use = MEM_get_memory_in_use();
- }
+ mem_in_use = get_memory_in_use();
if (mem_in_use <= max) {
return;
diff --git a/intern/memutil/MEM_CacheLimiterC-Api.h b/intern/memutil/MEM_CacheLimiterC-Api.h
index c05c9d61ea2..7579dbdd4d1 100644
--- a/intern/memutil/MEM_CacheLimiterC-Api.h
+++ b/intern/memutil/MEM_CacheLimiterC-Api.h
@@ -49,7 +49,7 @@ typedef int (*MEM_CacheLimiter_ItemPriority_Func) (void*, int);
#ifndef __MEM_CACHELIMITER_H__
void MEM_CacheLimiter_set_maximum(size_t m);
-int MEM_CacheLimiter_get_maximum(void);
+size_t MEM_CacheLimiter_get_maximum(void);
#endif /* __MEM_CACHELIMITER_H__ */
/**
@@ -145,6 +145,8 @@ void *MEM_CacheLimiter_get(MEM_CacheLimiterHandleC *handle);
void MEM_CacheLimiter_ItemPriority_Func_set(MEM_CacheLimiterC *This,
MEM_CacheLimiter_ItemPriority_Func item_priority_func);
+size_t MEM_CacheLimiter_get_memory_in_use(MEM_CacheLimiterC *This);
+
#ifdef __cplusplus
}
#endif
diff --git a/intern/memutil/SConscript b/intern/memutil/SConscript
index c9a03982615..95fa39eb9c5 100644
--- a/intern/memutil/SConscript
+++ b/intern/memutil/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('intern/*.cpp')
diff --git a/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp b/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp
index 7a19543b2db..0e11fbed4e7 100644
--- a/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp
+++ b/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp
@@ -128,7 +128,7 @@ MEM_CacheLimiterCClass::~MEM_CacheLimiterCClass()
{
// should not happen, but don't leak memory in this case...
for (list_t::iterator it = cclass_list.begin(); it != cclass_list.end(); it++) {
- (*it)->set_data(0);
+ (*it)->set_data(NULL);
delete *it;
}
@@ -202,3 +202,8 @@ void MEM_CacheLimiter_ItemPriority_Func_set(MEM_CacheLimiterC *This,
{
cast(This)->get_cache()->set_item_priority_func(item_priority_func);
}
+
+size_t MEM_CacheLimiter_get_memory_in_use(MEM_CacheLimiterC *This)
+{
+ return cast(This)->get_cache()->get_memory_in_use();
+}
diff --git a/intern/mikktspace/SConscript b/intern/mikktspace/SConscript
index 8f31f21a26f..fcb257a4ea0 100644
--- a/intern/mikktspace/SConscript
+++ b/intern/mikktspace/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Daniel Genrich
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = ['mikktspace.c']
diff --git a/intern/moto/SConscript b/intern/moto/SConscript
index ba257a33b14..34a0afe27f8 100644
--- a/intern/moto/SConscript
+++ b/intern/moto/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('intern/*.cpp')
diff --git a/source/blender/opencl/CMakeLists.txt b/intern/opencl/CMakeLists.txt
index b3c76db1bca..03855cfdf8b 100644
--- a/source/blender/opencl/CMakeLists.txt
+++ b/intern/opencl/CMakeLists.txt
@@ -39,4 +39,4 @@ set(SRC
)
-blender_add_lib(bf_opencl "${SRC}" "${INC}" "${INC_SYS}")
+blender_add_lib(bf_intern_opencl "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/opencl/OCL_opencl.h b/intern/opencl/OCL_opencl.h
index 4ee167b2fb4..4ee167b2fb4 100644
--- a/source/blender/opencl/OCL_opencl.h
+++ b/intern/opencl/OCL_opencl.h
diff --git a/intern/opencl/SConscript b/intern/opencl/SConscript
new file mode 100644
index 00000000000..41a6d720098
--- /dev/null
+++ b/intern/opencl/SConscript
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+Import ('env')
+
+sources = env.Glob('intern/*.c')
+
+incs = '.'
+
+env.BlenderLib ( 'bf_intern_opencl', sources, Split(incs), libtype=['core','player'], priority = [192,192] )
diff --git a/source/blender/opencl/intern/OCL_opencl.c b/intern/opencl/intern/OCL_opencl.c
index e3130e16bde..e3130e16bde 100644
--- a/source/blender/opencl/intern/OCL_opencl.c
+++ b/intern/opencl/intern/OCL_opencl.c
diff --git a/source/blender/opencl/intern/clew.c b/intern/opencl/intern/clew.c
index d68eb17288f..d68eb17288f 100644
--- a/source/blender/opencl/intern/clew.c
+++ b/intern/opencl/intern/clew.c
diff --git a/source/blender/opencl/intern/clew.h b/intern/opencl/intern/clew.h
index bb7e0134dcf..bb7e0134dcf 100644
--- a/source/blender/opencl/intern/clew.h
+++ b/intern/opencl/intern/clew.h
diff --git a/intern/opencolorio/SConscript b/intern/opencolorio/SConscript
index a4d21f3e440..6e7c467f64f 100644
--- a/intern/opencolorio/SConscript
+++ b/intern/opencolorio/SConscript
@@ -1,4 +1,29 @@
-#!/usr/bin/python
+#!/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) 2012, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Sergey Sharybin.
+#
+# ***** END GPL LICENSE BLOCK *****
Import('env')
diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc
index 44c02d1442b..d01d8d4c8f4 100644
--- a/intern/opencolorio/fallback_impl.cc
+++ b/intern/opencolorio/fallback_impl.cc
@@ -331,7 +331,7 @@ void FallbackImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr *)
}
OCIO_PackedImageDesc *FallbackImpl::createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels,
- long chanStrideBytes, long xStrideBytes, long yStrideBytes)
+ long chanStrideBytes, long xStrideBytes, long yStrideBytes)
{
OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription*)MEM_callocN(sizeof(OCIO_PackedImageDescription), "OCIO_PackedImageDescription");
diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc
index 18fa4b7cb1b..4f839a61fad 100644
--- a/intern/opencolorio/ocio_capi.cc
+++ b/intern/opencolorio/ocio_capi.cc
@@ -238,12 +238,12 @@ void OCIO_displayTransformRelease(OCIO_DisplayTransformRcPtr *dt)
}
OCIO_PackedImageDesc *OCIO_createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels,
- long chanStrideBytes, long xStrideBytes, long yStrideBytes)
+ long chanStrideBytes, long xStrideBytes, long yStrideBytes)
{
return impl->createOCIO_PackedImageDesc(data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes);
}
-void OCIO_OCIO_PackedImageDescRelease(OCIO_PackedImageDesc* id)
+void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc* id)
{
impl->OCIO_PackedImageDescRelease(id);
}
diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h
index 0ce5f8a1456..19fd8fe643b 100644
--- a/intern/opencolorio/ocio_capi.h
+++ b/intern/opencolorio/ocio_capi.h
@@ -105,9 +105,9 @@ void OCIO_displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_Const
void OCIO_displayTransformRelease(OCIO_DisplayTransformRcPtr *dt);
OCIO_PackedImageDesc *OCIO_createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels,
- long chanStrideBytes, long xStrideBytes, long yStrideBytes);
+ long chanStrideBytes, long xStrideBytes, long yStrideBytes);
-void OCIO_OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p);
+void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p);
OCIO_ExponentTransformRcPtr *OCIO_createExponentTransform(void);
void OCIO_exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent);
diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc
index 2d73d2ff56b..b073a038f0d 100644
--- a/intern/opencolorio/ocio_impl.cc
+++ b/intern/opencolorio/ocio_impl.cc
@@ -479,7 +479,7 @@ void OCIOImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr *dt)
}
OCIO_PackedImageDesc *OCIOImpl::createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels,
- long chanStrideBytes, long xStrideBytes, long yStrideBytes)
+ long chanStrideBytes, long xStrideBytes, long yStrideBytes)
{
try {
void *mem = MEM_mallocN(sizeof(PackedImageDesc), __func__);
diff --git a/intern/opencolorio/ocio_impl.h b/intern/opencolorio/ocio_impl.h
index 64cf5ec3322..b6bbc912e5b 100644
--- a/intern/opencolorio/ocio_impl.h
+++ b/intern/opencolorio/ocio_impl.h
@@ -30,7 +30,7 @@
class IOCIOImpl {
public:
- virtual ~IOCIOImpl() {};
+ virtual ~IOCIOImpl() {}
virtual OCIO_ConstConfigRcPtr *getCurrentConfig(void) = 0;
virtual void setCurrentConfig(const OCIO_ConstConfigRcPtr *config) = 0;
@@ -99,7 +99,7 @@ public:
class FallbackImpl : public IOCIOImpl {
public:
- FallbackImpl() {};
+ FallbackImpl() {}
OCIO_ConstConfigRcPtr *getCurrentConfig(void);
void setCurrentConfig(const OCIO_ConstConfigRcPtr *config);
diff --git a/intern/opennl/SConscript b/intern/opennl/SConscript
index a0f02735748..f47dd560779 100644
--- a/intern/opennl/SConscript
+++ b/intern/opennl/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('intern/*.c') + env.Glob('superlu/*.c')
diff --git a/intern/raskter/SConscript b/intern/raskter/SConscript
index 7ad505d70e4..c7bf647b0e2 100644
--- a/intern/raskter/SConscript
+++ b/intern/raskter/SConscript
@@ -1,4 +1,29 @@
-#!/usr/bin/python
+#!/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) 2012, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Peter Larabell
+#
+# ***** END GPL LICENSE BLOCK *****
Import ('env')
diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c
index 21153082324..4f65f877316 100644
--- a/intern/raskter/raskter.c
+++ b/intern/raskter/raskter.c
@@ -420,7 +420,7 @@ int PLX_raskterize(float(*base_verts)[2], int num_base_verts,
{
int i; /* i: Loop counter. */
struct PolyVert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */
- struct r_FillContext ctx = {0};
+ struct r_FillContext ctx = {NULL};
const float buf_x_f = (float)(buf_x);
const float buf_y_f = (float)(buf_y);
/*
diff --git a/source/gameengine/Physics/common/CMakeLists.txt b/intern/rigidbody/CMakeLists.txt
index 400e475f8a2..bea3075f6be 100644
--- a/source/gameengine/Physics/common/CMakeLists.txt
+++ b/intern/rigidbody/CMakeLists.txt
@@ -19,13 +19,11 @@
#
# The Original Code is: all of this file.
#
-# Contributor(s): Jacques Beaurain.
-#
# ***** END GPL LICENSE BLOCK *****
set(INC
.
- ../Dummy
+ ../../extern/bullet2/src
)
set(INC_SYS
@@ -33,22 +31,9 @@ set(INC_SYS
)
set(SRC
- PHY_IMotionState.cpp
- PHY_IController.cpp
- PHY_IPhysicsController.cpp
- PHY_IGraphicController.cpp
- PHY_IPhysicsEnvironment.cpp
- PHY_IVehicle.cpp
-
- PHY_DynamicTypes.h
- PHY_ICharacter.h
- PHY_IController.h
- PHY_IGraphicController.h
- PHY_IMotionState.h
- PHY_IPhysicsController.h
- PHY_IPhysicsEnvironment.h
- PHY_IVehicle.h
- PHY_Pro.h
+ rb_bullet_api.cpp
+
+ RBI_api.h
)
-blender_add_lib(ge_phys_common "${SRC}" "${INC}" "${INC_SYS}")
+blender_add_lib(bf_intern_rigidbody "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/rigidbody/RBI_api.h b/intern/rigidbody/RBI_api.h
new file mode 100644
index 00000000000..e7c88d96873
--- /dev/null
+++ b/intern/rigidbody/RBI_api.h
@@ -0,0 +1,315 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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): Joshua Leung, Sergej Reich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file RBI_api.h
+ * \ingroup RigidBody
+ * \brief Rigid Body API for interfacing with external Physics Engines
+ */
+
+#ifndef __RB_API_H__
+#define __RB_API_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* API Notes:
+ * Currently, this API is optimised for Bullet RigidBodies, and doesn't
+ * take into account other Physics Engines. Some tweaking may be necessary
+ * to allow other systems to be used, in particular there may be references
+ * to datatypes that aren't used here...
+ *
+ * -- Joshua Leung (22 June 2010)
+ */
+
+/* ********************************** */
+/* Partial Type Defines - Aliases for the type of data we store */
+
+// ----------
+
+/* Dynamics World */
+typedef struct rbDynamicsWorld rbDynamicsWorld;
+
+/* Rigid Body */
+typedef struct rbRigidBody rbRigidBody;
+
+/* Collision Shape */
+typedef struct rbCollisionShape rbCollisionShape;
+
+/* Mesh Data (for Collision Shapes of Meshes) */
+typedef struct rbMeshData rbMeshData;
+
+/* Constraint */
+typedef struct rbConstraint rbConstraint;
+
+/* ********************************** */
+/* Dynamics World Methods */
+
+/* Setup ---------------------------- */
+
+/* Create a new dynamics world instance */
+// TODO: add args to set the type of constraint solvers, etc.
+extern rbDynamicsWorld *RB_dworld_new(const float gravity[3]);
+
+/* Delete the given dynamics world, and free any extra data it may require */
+extern void RB_dworld_delete(rbDynamicsWorld *world);
+
+/* Settings ------------------------- */
+
+/* Gravity */
+extern void RB_dworld_get_gravity(rbDynamicsWorld *world, float g_out[3]);
+extern void RB_dworld_set_gravity(rbDynamicsWorld *world, const float g_in[3]);
+
+/* Constraint Solver */
+extern void RB_dworld_set_solver_iterations(rbDynamicsWorld *world, int num_solver_iterations);
+/* Split Impulse */
+extern void RB_dworld_set_split_impulse(rbDynamicsWorld *world, int split_impulse);
+
+/* Simulation ----------------------- */
+
+/* Step the simulation by the desired amount (in seconds) with extra controls on substep sizes and maximum substeps */
+extern void RB_dworld_step_simulation(rbDynamicsWorld *world, float timeStep, int maxSubSteps, float timeSubStep);
+
+/* Export -------------------------- */
+
+/* Exports the dynamics world to physics simulator's serialisation format */
+void RB_dworld_export(rbDynamicsWorld *world, const char *filename);
+
+/* ********************************** */
+/* Rigid Body Methods */
+
+/* Setup ---------------------------- */
+
+/* Add RigidBody to dynamics world */
+extern void RB_dworld_add_body(rbDynamicsWorld *world, rbRigidBody *body, int col_groups);
+
+/* Remove RigidBody from dynamics world */
+extern void RB_dworld_remove_body(rbDynamicsWorld *world, rbRigidBody *body);
+
+/* ............ */
+
+/* Create new RigidBody instance */
+extern rbRigidBody *RB_body_new(rbCollisionShape *shape, const float loc[3], const float rot[4]);
+
+/* Delete the given RigidBody instance */
+extern void RB_body_delete(rbRigidBody *body);
+
+/* Settings ------------------------- */
+
+/* 'Type' */
+extern void RB_body_set_type(rbRigidBody *body, int type, float mass);
+
+/* ............ */
+
+/* Collision Shape */
+extern void RB_body_set_collision_shape(rbRigidBody *body, rbCollisionShape *shape);
+
+/* ............ */
+
+/* Mass */
+extern float RB_body_get_mass(rbRigidBody *body);
+extern void RB_body_set_mass(rbRigidBody *body, float value);
+
+/* Friction */
+extern float RB_body_get_friction(rbRigidBody *body);
+extern void RB_body_set_friction(rbRigidBody *body, float value);
+
+/* Restitution */
+extern float RB_body_get_restitution(rbRigidBody *body);
+extern void RB_body_set_restitution(rbRigidBody *body, float value);
+
+/* Damping */
+extern float RB_body_get_linear_damping(rbRigidBody *body);
+extern void RB_body_set_linear_damping(rbRigidBody *body, float value);
+
+extern float RB_body_get_angular_damping(rbRigidBody *body);
+extern void RB_body_set_angular_damping(rbRigidBody *body, float value);
+
+extern void RB_body_set_damping(rbRigidBody *object, float linear, float angular);
+
+/* Sleeping Thresholds */
+extern float RB_body_get_linear_sleep_thresh(rbRigidBody *body);
+extern void RB_body_set_linear_sleep_thresh(rbRigidBody *body, float value);
+
+extern float RB_body_get_angular_sleep_thresh(rbRigidBody *body);
+extern void RB_body_set_angular_sleep_thresh(rbRigidBody *body, float value);
+
+extern void RB_body_set_sleep_thresh(rbRigidBody *body, float linear, float angular);
+
+/* Linear Velocity */
+extern void RB_body_get_linear_velocity(rbRigidBody *body, float v_out[3]);
+extern void RB_body_set_linear_velocity(rbRigidBody *body, const float v_in[3]);
+
+/* Angular Velocity */
+extern void RB_body_get_angular_velocity(rbRigidBody *body, float v_out[3]);
+extern void RB_body_set_angular_velocity(rbRigidBody *body, const float v_in[3]);
+
+/* Linear/Angular Factor, used to lock translation/roation axes */
+extern void RB_body_set_linear_factor(rbRigidBody *object, float x, float y, float z);
+extern void RB_body_set_angular_factor(rbRigidBody *object, float x, float y, float z);
+
+/* Kinematic State */
+extern void RB_body_set_kinematic_state(rbRigidBody *body, int kinematic);
+
+/* RigidBody Interface - Rigid Body Activation States */
+extern int RB_body_get_activation_state(rbRigidBody *body);
+extern void RB_body_set_activation_state(rbRigidBody *body, int use_deactivation);
+extern void RB_body_activate(rbRigidBody *body);
+extern void RB_body_deactivate(rbRigidBody *body);
+
+
+/* Simulation ----------------------- */
+
+/* Get current transform matrix of RigidBody to use in Blender (OpenGL format) */
+extern void RB_body_get_transform_matrix(rbRigidBody *body, float m_out[4][4]);
+
+/* Set RigidBody's location and rotation */
+extern void RB_body_set_loc_rot(rbRigidBody *body, const float loc[3], const float rot[4]);
+/* Set RigidBody's local scaling */
+extern void RB_body_set_scale(rbRigidBody *body, const float scale[3]);
+
+/* ............ */
+
+/* Get RigidBody's position as vector */
+void RB_body_get_position(rbRigidBody *body, float v_out[3]);
+/* Get RigidBody's orientation as quaternion */
+void RB_body_get_orientation(rbRigidBody *body, float v_out[4]);
+
+/* ............ */
+
+extern void RB_body_apply_central_force(rbRigidBody *body, const float v_in[3]);
+
+/* ********************************** */
+/* Collision Shape Methods */
+
+/* Setup (Standard Shapes) ----------- */
+
+extern rbCollisionShape *RB_shape_new_box(float x, float y, float z);
+extern rbCollisionShape *RB_shape_new_sphere(float radius);
+extern rbCollisionShape *RB_shape_new_capsule(float radius, float height);
+extern rbCollisionShape *RB_shape_new_cone(float radius, float height);
+extern rbCollisionShape *RB_shape_new_cylinder(float radius, float height);
+
+/* Setup (Convex Hull) ------------ */
+
+extern rbCollisionShape *RB_shape_new_convex_hull(float *verts, int stride, int count, float margin, bool *can_embed);
+
+/* Setup (Triangle Mesh) ---------- */
+
+/* 1 */
+extern rbMeshData *RB_trimesh_data_new(void);
+extern void RB_trimesh_add_triangle(rbMeshData *mesh, const float v1[3], const float v2[3], const float v3[3]);
+/* 2a - Triangle Meshes */
+extern rbCollisionShape *RB_shape_new_trimesh(rbMeshData *mesh);
+/* 2b - GImpact Meshes */
+extern rbCollisionShape *RB_shape_new_gimpact_mesh(rbMeshData *mesh);
+
+
+/* Cleanup --------------------------- */
+
+extern void RB_shape_delete(rbCollisionShape *shape);
+
+/* Settings --------------------------- */
+
+/* Collision Margin */
+extern float RB_shape_get_margin(rbCollisionShape *shape);
+extern void RB_shape_set_margin(rbCollisionShape *shape, float value);
+
+/* ********************************** */
+/* Constraints */
+
+/* Setup ----------------------------- */
+
+/* Add Rigid Body Constraint to simulation world */
+extern void RB_dworld_add_constraint(rbDynamicsWorld *world, rbConstraint *con, int disable_collisions);
+
+/* Remove Rigid Body Constraint from simulation world */
+extern void RB_dworld_remove_constraint(rbDynamicsWorld *world, rbConstraint *con);
+
+extern rbConstraint *RB_constraint_new_point(float pivot[3], rbRigidBody *rb1, rbRigidBody *rb2);
+extern rbConstraint *RB_constraint_new_fixed(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2);
+extern rbConstraint *RB_constraint_new_hinge(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2);
+extern rbConstraint *RB_constraint_new_slider(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2);
+extern rbConstraint *RB_constraint_new_piston(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2);
+extern rbConstraint *RB_constraint_new_6dof(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2);
+extern rbConstraint *RB_constraint_new_6dof_spring(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2);
+extern rbConstraint *RB_constraint_new_motor(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2);
+
+/* ............ */
+
+/* Cleanup --------------------------- */
+
+extern void RB_constraint_delete(rbConstraint *con);
+
+/* Settings --------------------------- */
+
+/* Enable or disable constraint */
+extern void RB_constraint_set_enabled(rbConstraint *con, int enabled);
+
+/* Limits */
+#define RB_LIMIT_LIN_X 0
+#define RB_LIMIT_LIN_Y 1
+#define RB_LIMIT_LIN_Z 2
+#define RB_LIMIT_ANG_X 3
+#define RB_LIMIT_ANG_Y 4
+#define RB_LIMIT_ANG_Z 5
+/* Bullet uses the following convention:
+ * - lower limit == upper limit -> axis is locked
+ * - lower limit > upper limit -> axis is free
+ * - lower limit < upper limit -> axis is limited in given range
+ */
+extern void RB_constraint_set_limits_hinge(rbConstraint *con, float lower, float upper);
+extern void RB_constraint_set_limits_slider(rbConstraint *con, float lower, float upper);
+extern void RB_constraint_set_limits_piston(rbConstraint *con, float lin_lower, float lin_upper, float ang_lower, float ang_upper);
+extern void RB_constraint_set_limits_6dof(rbConstraint *con, int axis, float lower, float upper);
+
+/* 6dof spring specific */
+extern void RB_constraint_set_stiffness_6dof_spring(rbConstraint *con, int axis, float stiffness);
+extern void RB_constraint_set_damping_6dof_spring(rbConstraint *con, int axis, float damping);
+extern void RB_constraint_set_spring_6dof_spring(rbConstraint *con, int axis, int enable);
+extern void RB_constraint_set_equilibrium_6dof_spring(rbConstraint *con);
+
+/* motors */
+extern void RB_constraint_set_enable_motor(rbConstraint *con, int enable_lin, int enable_ang);
+extern void RB_constraint_set_max_impulse_motor(rbConstraint *con, float max_impulse_lin, float max_impulse_ang);
+extern void RB_constraint_set_target_velocity_motor(rbConstraint *con, float velocity_lin, float velocity_ang);
+
+/* Set number of constraint solver iterations made per step, this overrided world setting
+ * To use default set it to -1 */
+extern void RB_constraint_set_solver_iterations(rbConstraint *con, int num_solver_iterations);
+
+/* Set breaking impulse threshold, if constraint shouldn't break it can be set to FLT_MAX */
+extern void RB_constraint_set_breaking_threshold(rbConstraint *con, float threshold);
+
+/* ********************************** */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __RB_API_H__ */
+
diff --git a/intern/rigidbody/SConscript b/intern/rigidbody/SConscript
new file mode 100644
index 00000000000..977281f8eef
--- /dev/null
+++ b/intern/rigidbody/SConscript
@@ -0,0 +1,42 @@
+#!/usr/bin/python
+# $Id: SConscript $
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2010, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Joshua Leung
+#
+# ***** END GPL LICENSE BLOCK *****
+
+Import('env')
+
+# XXX: we need a contingency plan for when not compiling with Bullet,
+# since this module will always get included...
+# This problem will also apply to other engines at a later date too...
+sources = env.Glob('*.cpp')
+
+incs = [
+ '.',
+ '../../extern/bullet2/src',
+ ]
+
+env.BlenderLib('bf_intern_rigidbody', sources=sources,
+ includes=incs, defines=[],
+ libtype=['core', 'player'], priority=[180, 30])
diff --git a/intern/rigidbody/rb_bullet_api.cpp b/intern/rigidbody/rb_bullet_api.cpp
new file mode 100644
index 00000000000..e9e5e2a5e32
--- /dev/null
+++ b/intern/rigidbody/rb_bullet_api.cpp
@@ -0,0 +1,995 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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): Joshua Leung, Sergej Reich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file rb_bullet_api.cpp
+ * \ingroup RigidBody
+ * \brief Rigid Body API implementation for Bullet
+ */
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/* This file defines the "RigidBody interface" for the
+ * Bullet Physics Engine. This API is designed to be used
+ * from C-code in Blender as part of the Rigid Body simulation
+ * system.
+ *
+ * It is based on the Bullet C-API, but is heavily modified to
+ * give access to more data types and to offer a nicer interface.
+ *
+ * -- Joshua Leung, June 2010
+ */
+
+#include <stdio.h>
+
+#include "RBI_api.h"
+
+#include "btBulletDynamicsCommon.h"
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btConvexHullComputer.h"
+
+#include "BulletCollision/Gimpact/btGImpactShape.h"
+#include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h"
+#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
+
+struct rbDynamicsWorld {
+ btDiscreteDynamicsWorld *dynamicsWorld;
+ btDefaultCollisionConfiguration *collisionConfiguration;
+ btDispatcher *dispatcher;
+ btBroadphaseInterface *pairCache;
+ btConstraintSolver *constraintSolver;
+ btOverlapFilterCallback *filterCallback;
+};
+struct rbRigidBody {
+ btRigidBody *body;
+ int col_groups;
+};
+
+struct rbCollisionShape {
+ btCollisionShape *cshape;
+ btTriangleMesh *mesh;
+};
+
+struct rbFilterCallback : public btOverlapFilterCallback
+{
+ virtual bool needBroadphaseCollision(btBroadphaseProxy *proxy0, btBroadphaseProxy *proxy1) const
+ {
+ rbRigidBody *rb0 = (rbRigidBody *)((btRigidBody *)proxy0->m_clientObject)->getUserPointer();
+ rbRigidBody *rb1 = (rbRigidBody *)((btRigidBody *)proxy1->m_clientObject)->getUserPointer();
+
+ bool collides;
+ collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
+ collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+ collides = collides && (rb0->col_groups & rb1->col_groups);
+
+ return collides;
+ }
+};
+
+static inline void copy_v3_btvec3(float vec[3], const btVector3 &btvec)
+{
+ vec[0] = (float)btvec[0];
+ vec[1] = (float)btvec[1];
+ vec[2] = (float)btvec[2];
+}
+static inline void copy_quat_btquat(float quat[4], const btQuaternion &btquat)
+{
+ quat[0] = btquat.getW();
+ quat[1] = btquat.getX();
+ quat[2] = btquat.getY();
+ quat[3] = btquat.getZ();
+}
+
+/* ********************************** */
+/* Dynamics World Methods */
+
+/* Setup ---------------------------- */
+
+rbDynamicsWorld *RB_dworld_new(const float gravity[3])
+{
+ rbDynamicsWorld *world = new rbDynamicsWorld;
+
+ /* collision detection/handling */
+ world->collisionConfiguration = new btDefaultCollisionConfiguration();
+
+ world->dispatcher = new btCollisionDispatcher(world->collisionConfiguration);
+ btGImpactCollisionAlgorithm::registerAlgorithm((btCollisionDispatcher *)world->dispatcher); // XXX: experimental
+
+ world->pairCache = new btDbvtBroadphase();
+
+ world->filterCallback = new rbFilterCallback();
+ world->pairCache->getOverlappingPairCache()->setOverlapFilterCallback(world->filterCallback);
+
+ /* constraint solving */
+ world->constraintSolver = new btSequentialImpulseConstraintSolver();
+
+ /* world */
+ world->dynamicsWorld = new btDiscreteDynamicsWorld(world->dispatcher,
+ world->pairCache,
+ world->constraintSolver,
+ world->collisionConfiguration);
+
+ RB_dworld_set_gravity(world, gravity);
+
+ return world;
+}
+
+void RB_dworld_delete(rbDynamicsWorld *world)
+{
+ /* bullet doesn't like if we free these in a different order */
+ delete world->dynamicsWorld;
+ delete world->constraintSolver;
+ delete world->pairCache;
+ delete world->dispatcher;
+ delete world->collisionConfiguration;
+ delete world->filterCallback;
+ delete world;
+}
+
+/* Settings ------------------------- */
+
+/* Gravity */
+void RB_dworld_get_gravity(rbDynamicsWorld *world, float g_out[3])
+{
+ copy_v3_btvec3(g_out, world->dynamicsWorld->getGravity());
+}
+
+void RB_dworld_set_gravity(rbDynamicsWorld *world, const float g_in[3])
+{
+ world->dynamicsWorld->setGravity(btVector3(g_in[0], g_in[1], g_in[2]));
+}
+
+/* Constraint Solver */
+void RB_dworld_set_solver_iterations(rbDynamicsWorld *world, int num_solver_iterations)
+{
+ btContactSolverInfo& info = world->dynamicsWorld->getSolverInfo();
+
+ info.m_numIterations = num_solver_iterations;
+}
+
+/* Split Impulse */
+void RB_dworld_set_split_impulse(rbDynamicsWorld *world, int split_impulse)
+{
+ btContactSolverInfo& info = world->dynamicsWorld->getSolverInfo();
+
+ info.m_splitImpulse = split_impulse;
+}
+
+/* Simulation ----------------------- */
+
+void RB_dworld_step_simulation(rbDynamicsWorld *world, float timeStep, int maxSubSteps, float timeSubStep)
+{
+ world->dynamicsWorld->stepSimulation(timeStep, maxSubSteps, timeSubStep);
+}
+
+/* Export -------------------------- */
+
+/* Exports entire dynamics world to Bullet's "*.bullet" binary format
+ * which is similar to Blender's SDNA system...
+ * < rbDynamicsWorld: dynamics world to write to file
+ * < filename: assumed to be a valid filename, with .bullet extension
+ */
+void RB_dworld_export(rbDynamicsWorld *world, const char *filename)
+{
+ //create a large enough buffer. There is no method to pre-calculate the buffer size yet.
+ int maxSerializeBufferSize = 1024 * 1024 * 5;
+
+ btDefaultSerializer *serializer = new btDefaultSerializer(maxSerializeBufferSize);
+ world->dynamicsWorld->serialize(serializer);
+
+ FILE *file = fopen(filename, "wb");
+ fwrite(serializer->getBufferPointer(), serializer->getCurrentBufferSize(), 1, file);
+ fclose(file);
+}
+
+/* ********************************** */
+/* Rigid Body Methods */
+
+/* Setup ---------------------------- */
+
+void RB_dworld_add_body(rbDynamicsWorld *world, rbRigidBody *object, int col_groups)
+{
+ btRigidBody *body = object->body;
+ object->col_groups = col_groups;
+
+ world->dynamicsWorld->addRigidBody(body);
+}
+
+void RB_dworld_remove_body(rbDynamicsWorld *world, rbRigidBody *object)
+{
+ btRigidBody *body = object->body;
+
+ world->dynamicsWorld->removeRigidBody(body);
+}
+
+/* ............ */
+
+rbRigidBody *RB_body_new(rbCollisionShape *shape, const float loc[3], const float rot[4])
+{
+ rbRigidBody *object = new rbRigidBody;
+ /* current transform */
+ btTransform trans;
+ trans.setOrigin(btVector3(loc[0], loc[1], loc[2]));
+ trans.setRotation(btQuaternion(rot[1], rot[2], rot[3], rot[0]));
+
+ /* create motionstate, which is necessary for interpolation (includes reverse playback) */
+ btDefaultMotionState *motionState = new btDefaultMotionState(trans);
+
+ /* make rigidbody */
+ btRigidBody::btRigidBodyConstructionInfo rbInfo(1.0f, motionState, shape->cshape);
+
+ object->body = new btRigidBody(rbInfo);
+
+ object->body->setUserPointer(object);
+
+ return object;
+}
+
+void RB_body_delete(rbRigidBody *object)
+{
+ btRigidBody *body = object->body;
+
+ /* motion state */
+ btMotionState *ms = body->getMotionState();
+ if (ms)
+ delete ms;
+
+ /* collision shape is done elsewhere... */
+
+ /* body itself */
+
+ /* manually remove constraint refs of the rigid body, normally this happens when removing constraints from the world
+ * but since we delete everything when the world is rebult, we need to do it manually here */
+ for (int i = body->getNumConstraintRefs() - 1; i >= 0; i--) {
+ btTypedConstraint *con = body->getConstraintRef(i);
+ body->removeConstraintRef(con);
+ }
+
+ delete body;
+ delete object;
+}
+
+/* Settings ------------------------- */
+
+void RB_body_set_collision_shape(rbRigidBody *object, rbCollisionShape *shape)
+{
+ btRigidBody *body = object->body;
+
+ /* set new collision shape */
+ body->setCollisionShape(shape->cshape);
+
+ /* recalculate inertia, since that depends on the collision shape... */
+ RB_body_set_mass(object, RB_body_get_mass(object));
+}
+
+/* ............ */
+
+float RB_body_get_mass(rbRigidBody *object)
+{
+ btRigidBody *body = object->body;
+
+ /* there isn't really a mass setting, but rather 'inverse mass'
+ * which we convert back to mass by taking the reciprocal again
+ */
+ float value = (float)body->getInvMass();
+
+ if (value)
+ value = 1.0 / value;
+
+ return value;
+}
+
+void RB_body_set_mass(rbRigidBody *object, float value)
+{
+ btRigidBody *body = object->body;
+ btVector3 localInertia(0, 0, 0);
+
+ /* calculate new inertia if non-zero mass */
+ if (value) {
+ btCollisionShape *shape = body->getCollisionShape();
+ shape->calculateLocalInertia(value, localInertia);
+ }
+
+ body->setMassProps(value, localInertia);
+ body->updateInertiaTensor();
+}
+
+
+float RB_body_get_friction(rbRigidBody *object)
+{
+ btRigidBody *body = object->body;
+ return body->getFriction();
+}
+
+void RB_body_set_friction(rbRigidBody *object, float value)
+{
+ btRigidBody *body = object->body;
+ body->setFriction(value);
+}
+
+
+float RB_body_get_restitution(rbRigidBody *object)
+{
+ btRigidBody *body = object->body;
+ return body->getRestitution();
+}
+
+void RB_body_set_restitution(rbRigidBody *object, float value)
+{
+ btRigidBody *body = object->body;
+ body->setRestitution(value);
+}
+
+
+float RB_body_get_linear_damping(rbRigidBody *object)
+{
+ btRigidBody *body = object->body;
+ return body->getLinearDamping();
+}
+
+void RB_body_set_linear_damping(rbRigidBody *object, float value)
+{
+ RB_body_set_damping(object, value, RB_body_get_linear_damping(object));
+}
+
+float RB_body_get_angular_damping(rbRigidBody *object)
+{
+ btRigidBody *body = object->body;
+ return body->getAngularDamping();
+}
+
+void RB_body_set_angular_damping(rbRigidBody *object, float value)
+{
+ RB_body_set_damping(object, RB_body_get_linear_damping(object), value);
+}
+
+void RB_body_set_damping(rbRigidBody *object, float linear, float angular)
+{
+ btRigidBody *body = object->body;
+ body->setDamping(linear, angular);
+}
+
+
+float RB_body_get_linear_sleep_thresh(rbRigidBody *object)
+{
+ btRigidBody *body = object->body;
+ return body->getLinearSleepingThreshold();
+}
+
+void RB_body_set_linear_sleep_thresh(rbRigidBody *object, float value)
+{
+ RB_body_set_sleep_thresh(object, value, RB_body_get_angular_sleep_thresh(object));
+}
+
+float RB_body_get_angular_sleep_thresh(rbRigidBody *object)
+{
+ btRigidBody *body = object->body;
+ return body->getAngularSleepingThreshold();
+}
+
+void RB_body_set_angular_sleep_thresh(rbRigidBody *object, float value)
+{
+ RB_body_set_sleep_thresh(object, RB_body_get_linear_sleep_thresh(object), value);
+}
+
+void RB_body_set_sleep_thresh(rbRigidBody *object, float linear, float angular)
+{
+ btRigidBody *body = object->body;
+ body->setSleepingThresholds(linear, angular);
+}
+
+/* ............ */
+
+void RB_body_get_linear_velocity(rbRigidBody *object, float v_out[3])
+{
+ btRigidBody *body = object->body;
+
+ copy_v3_btvec3(v_out, body->getLinearVelocity());
+}
+
+void RB_body_set_linear_velocity(rbRigidBody *object, const float v_in[3])
+{
+ btRigidBody *body = object->body;
+
+ body->setLinearVelocity(btVector3(v_in[0], v_in[1], v_in[2]));
+}
+
+
+void RB_body_get_angular_velocity(rbRigidBody *object, float v_out[3])
+{
+ btRigidBody *body = object->body;
+
+ copy_v3_btvec3(v_out, body->getAngularVelocity());
+}
+
+void RB_body_set_angular_velocity(rbRigidBody *object, const float v_in[3])
+{
+ btRigidBody *body = object->body;
+
+ body->setAngularVelocity(btVector3(v_in[0], v_in[1], v_in[2]));
+}
+
+void RB_body_set_linear_factor(rbRigidBody *object, float x, float y, float z)
+{
+ btRigidBody *body = object->body;
+ body->setLinearFactor(btVector3(x, y, z));
+}
+
+void RB_body_set_angular_factor(rbRigidBody *object, float x, float y, float z)
+{
+ btRigidBody *body = object->body;
+ body->setAngularFactor(btVector3(x, y, z));
+}
+
+/* ............ */
+
+void RB_body_set_kinematic_state(rbRigidBody *object, int kinematic)
+{
+ btRigidBody *body = object->body;
+ if (kinematic)
+ body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
+ else
+ body->setCollisionFlags(body->getCollisionFlags() & ~btCollisionObject::CF_KINEMATIC_OBJECT);
+}
+
+/* ............ */
+
+void RB_body_set_activation_state(rbRigidBody *object, int use_deactivation)
+{
+ btRigidBody *body = object->body;
+ if (use_deactivation)
+ body->forceActivationState(ACTIVE_TAG);
+ else
+ body->setActivationState(DISABLE_DEACTIVATION);
+}
+void RB_body_activate(rbRigidBody *object)
+{
+ btRigidBody *body = object->body;
+ body->setActivationState(ACTIVE_TAG);
+}
+void RB_body_deactivate(rbRigidBody *object)
+{
+ btRigidBody *body = object->body;
+ body->setActivationState(ISLAND_SLEEPING);
+}
+
+/* ............ */
+
+
+
+/* Simulation ----------------------- */
+
+/* The transform matrices Blender uses are OpenGL-style matrices,
+ * while Bullet uses the Right-Handed coordinate system style instead.
+ */
+
+void RB_body_get_transform_matrix(rbRigidBody *object, float m_out[4][4])
+{
+ btRigidBody *body = object->body;
+ btMotionState *ms = body->getMotionState();
+
+ btTransform trans;
+ ms->getWorldTransform(trans);
+
+ trans.getOpenGLMatrix((btScalar *)m_out);
+}
+
+void RB_body_set_loc_rot(rbRigidBody *object, const float loc[3], const float rot[4])
+{
+ btRigidBody *body = object->body;
+ btMotionState *ms = body->getMotionState();
+
+ /* set transform matrix */
+ btTransform trans;
+ trans.setOrigin(btVector3(loc[0], loc[1], loc[2]));
+ trans.setRotation(btQuaternion(rot[1], rot[2], rot[3], rot[0]));
+
+ ms->setWorldTransform(trans);
+}
+
+void RB_body_set_scale(rbRigidBody *object, const float scale[3])
+{
+ btRigidBody *body = object->body;
+
+ /* apply scaling factor from matrix above to the collision shape */
+ btCollisionShape *cshape = body->getCollisionShape();
+ if (cshape) {
+ cshape->setLocalScaling(btVector3(scale[0], scale[1], scale[2]));
+
+ /* GIimpact shapes have to be updated to take scaling into account */
+ if (cshape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
+ ((btGImpactMeshShape *)cshape)->updateBound();
+ }
+}
+
+/* ............ */
+/* Read-only state info about status of simulation */
+
+void RB_body_get_position(rbRigidBody *object, float v_out[3])
+{
+ btRigidBody *body = object->body;
+
+ copy_v3_btvec3(v_out, body->getWorldTransform().getOrigin());
+}
+
+void RB_body_get_orientation(rbRigidBody *object, float v_out[4])
+{
+ btRigidBody *body = object->body;
+
+ copy_quat_btquat(v_out, body->getWorldTransform().getRotation());
+}
+
+/* ............ */
+/* Overrides for simulation */
+
+void RB_body_apply_central_force(rbRigidBody *object, const float v_in[3])
+{
+ btRigidBody *body = object->body;
+
+ body->applyCentralForce(btVector3(v_in[0], v_in[1], v_in[2]));
+}
+
+/* ********************************** */
+/* Collision Shape Methods */
+
+/* Setup (Standard Shapes) ----------- */
+
+rbCollisionShape *RB_shape_new_box(float x, float y, float z)
+{
+ rbCollisionShape *shape = new rbCollisionShape;
+ shape->cshape = new btBoxShape(btVector3(x, y, z));
+ shape->mesh = NULL;
+ return shape;
+}
+
+rbCollisionShape *RB_shape_new_sphere(float radius)
+{
+ rbCollisionShape *shape = new rbCollisionShape;
+ shape->cshape = new btSphereShape(radius);
+ shape->mesh = NULL;
+ return shape;
+}
+
+rbCollisionShape *RB_shape_new_capsule(float radius, float height)
+{
+ rbCollisionShape *shape = new rbCollisionShape;
+ shape->cshape = new btCapsuleShapeZ(radius, height);
+ shape->mesh = NULL;
+ return shape;
+}
+
+rbCollisionShape *RB_shape_new_cone(float radius, float height)
+{
+ rbCollisionShape *shape = new rbCollisionShape;
+ shape->cshape = new btConeShapeZ(radius, height);
+ shape->mesh = NULL;
+ return shape;
+}
+
+rbCollisionShape *RB_shape_new_cylinder(float radius, float height)
+{
+ rbCollisionShape *shape = new rbCollisionShape;
+ shape->cshape = new btCylinderShapeZ(btVector3(radius, radius, height));
+ shape->mesh = NULL;
+ return shape;
+}
+
+/* Setup (Convex Hull) ------------ */
+
+rbCollisionShape *RB_shape_new_convex_hull(float *verts, int stride, int count, float margin, bool *can_embed)
+{
+ btConvexHullComputer hull_computer = btConvexHullComputer();
+
+ // try to embed the margin, if that fails don't shrink the hull
+ if (hull_computer.compute(verts, stride, count, margin, 0.0f) < 0.0f) {
+ hull_computer.compute(verts, stride, count, 0.0f, 0.0f);
+ *can_embed = false;
+ }
+
+ rbCollisionShape *shape = new rbCollisionShape;
+ btConvexHullShape *hull_shape = new btConvexHullShape(&(hull_computer.vertices[0].getX()), hull_computer.vertices.size());
+
+ shape->cshape = hull_shape;
+ shape->mesh = NULL;
+ return shape;
+}
+
+/* Setup (Triangle Mesh) ---------- */
+
+/* Need to call rbTriMeshNewData() followed by rbTriMeshAddTriangle() several times
+ * to set up the mesh buffer BEFORE calling rbShapeNewTriMesh(). Otherwise,
+ * we get nasty crashes...
+ */
+
+rbMeshData *RB_trimesh_data_new()
+{
+ // XXX: welding threshold?
+ return (rbMeshData *) new btTriangleMesh(true, false);
+}
+
+void RB_trimesh_add_triangle(rbMeshData *mesh, const float v1[3], const float v2[3], const float v3[3])
+{
+ btTriangleMesh *meshData = reinterpret_cast<btTriangleMesh*>(mesh);
+
+ /* cast vertices to usable forms for Bt-API */
+ btVector3 vtx1((btScalar)v1[0], (btScalar)v1[1], (btScalar)v1[2]);
+ btVector3 vtx2((btScalar)v2[0], (btScalar)v2[1], (btScalar)v2[2]);
+ btVector3 vtx3((btScalar)v3[0], (btScalar)v3[1], (btScalar)v3[2]);
+
+ /* add to the mesh
+ * - remove duplicated verts is enabled
+ */
+ meshData->addTriangle(vtx1, vtx2, vtx3, false);
+}
+
+rbCollisionShape *RB_shape_new_trimesh(rbMeshData *mesh)
+{
+ rbCollisionShape *shape = new rbCollisionShape;
+ btTriangleMesh *tmesh = reinterpret_cast<btTriangleMesh*>(mesh);
+
+ /* triangle-mesh we create is a BVH wrapper for triangle mesh data (for faster lookups) */
+ // RB_TODO perhaps we need to allow saving out this for performance when rebuilding?
+ btBvhTriangleMeshShape *unscaledShape = new btBvhTriangleMeshShape(tmesh, true, true);
+
+ shape->cshape = new btScaledBvhTriangleMeshShape(unscaledShape, btVector3(1.0f, 1.0f, 1.0f));
+ shape->mesh = tmesh;
+ return shape;
+}
+
+rbCollisionShape *RB_shape_new_gimpact_mesh(rbMeshData *mesh)
+{
+ rbCollisionShape *shape = new rbCollisionShape;
+ /* interpret mesh buffer as btTriangleIndexVertexArray (i.e. an impl of btStridingMeshInterface) */
+ btTriangleMesh *tmesh = reinterpret_cast<btTriangleMesh*>(mesh);
+
+ btGImpactMeshShape *gimpactShape = new btGImpactMeshShape(tmesh);
+ gimpactShape->updateBound(); // TODO: add this to the update collision margin call?
+
+ shape->cshape = gimpactShape;
+ shape->mesh = tmesh;
+ return shape;
+}
+
+/* Cleanup --------------------------- */
+
+void RB_shape_delete(rbCollisionShape *shape)
+{
+ if (shape->cshape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE) {
+ btBvhTriangleMeshShape *child_shape = ((btScaledBvhTriangleMeshShape *)shape->cshape)->getChildShape();
+ if (child_shape)
+ delete child_shape;
+ }
+ if (shape->mesh)
+ delete shape->mesh;
+ delete shape->cshape;
+ delete shape;
+}
+
+/* Settings --------------------------- */
+
+float RB_shape_get_margin(rbCollisionShape *shape)
+{
+ return shape->cshape->getMargin();
+}
+
+void RB_shape_set_margin(rbCollisionShape *shape, float value)
+{
+ shape->cshape->setMargin(value);
+}
+
+/* ********************************** */
+/* Constraints */
+
+/* Setup ----------------------------- */
+
+void RB_dworld_add_constraint(rbDynamicsWorld *world, rbConstraint *con, int disable_collisions)
+{
+ btTypedConstraint *constraint = reinterpret_cast<btTypedConstraint*>(con);
+
+ world->dynamicsWorld->addConstraint(constraint, disable_collisions);
+}
+
+void RB_dworld_remove_constraint(rbDynamicsWorld *world, rbConstraint *con)
+{
+ btTypedConstraint *constraint = reinterpret_cast<btTypedConstraint*>(con);
+
+ world->dynamicsWorld->removeConstraint(constraint);
+}
+
+/* ............ */
+
+static void make_constraint_transforms(btTransform &transform1, btTransform &transform2, btRigidBody *body1, btRigidBody *body2, float pivot[3], float orn[4])
+{
+ btTransform pivot_transform = btTransform();
+ pivot_transform.setOrigin(btVector3(pivot[0], pivot[1], pivot[2]));
+ pivot_transform.setRotation(btQuaternion(orn[1], orn[2], orn[3], orn[0]));
+
+ transform1 = body1->getWorldTransform().inverse() * pivot_transform;
+ transform2 = body2->getWorldTransform().inverse() * pivot_transform;
+}
+
+rbConstraint *RB_constraint_new_point(float pivot[3], rbRigidBody *rb1, rbRigidBody *rb2)
+{
+ btRigidBody *body1 = rb1->body;
+ btRigidBody *body2 = rb2->body;
+
+ btVector3 pivot1 = body1->getWorldTransform().inverse() * btVector3(pivot[0], pivot[1], pivot[2]);
+ btVector3 pivot2 = body2->getWorldTransform().inverse() * btVector3(pivot[0], pivot[1], pivot[2]);
+
+ btTypedConstraint *con = new btPoint2PointConstraint(*body1, *body2, pivot1, pivot2);
+
+ return (rbConstraint *)con;
+}
+
+rbConstraint *RB_constraint_new_fixed(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
+{
+ btRigidBody *body1 = rb1->body;
+ btRigidBody *body2 = rb2->body;
+ btTransform transform1;
+ btTransform transform2;
+
+ make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn);
+
+ btGeneric6DofConstraint *con = new btGeneric6DofConstraint(*body1, *body2, transform1, transform2, true);
+
+ /* lock all axes */
+ for (int i = 0; i < 6; i++)
+ con->setLimit(i, 0, 0);
+
+ return (rbConstraint *)con;
+}
+
+rbConstraint *RB_constraint_new_hinge(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
+{
+ btRigidBody *body1 = rb1->body;
+ btRigidBody *body2 = rb2->body;
+ btTransform transform1;
+ btTransform transform2;
+
+ make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn);
+
+ btHingeConstraint *con = new btHingeConstraint(*body1, *body2, transform1, transform2);
+
+ return (rbConstraint *)con;
+}
+
+rbConstraint *RB_constraint_new_slider(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
+{
+ btRigidBody *body1 = rb1->body;
+ btRigidBody *body2 = rb2->body;
+ btTransform transform1;
+ btTransform transform2;
+
+ make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn);
+
+ btSliderConstraint *con = new btSliderConstraint(*body1, *body2, transform1, transform2, true);
+
+ return (rbConstraint *)con;
+}
+
+rbConstraint *RB_constraint_new_piston(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
+{
+ btRigidBody *body1 = rb1->body;
+ btRigidBody *body2 = rb2->body;
+ btTransform transform1;
+ btTransform transform2;
+
+ make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn);
+
+ btSliderConstraint *con = new btSliderConstraint(*body1, *body2, transform1, transform2, true);
+ con->setUpperAngLimit(-1.0f); // unlock rotation axis
+
+ return (rbConstraint *)con;
+}
+
+rbConstraint *RB_constraint_new_6dof(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
+{
+ btRigidBody *body1 = rb1->body;
+ btRigidBody *body2 = rb2->body;
+ btTransform transform1;
+ btTransform transform2;
+
+ make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn);
+
+ btTypedConstraint *con = new btGeneric6DofConstraint(*body1, *body2, transform1, transform2, true);
+
+ return (rbConstraint *)con;
+}
+
+rbConstraint *RB_constraint_new_6dof_spring(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
+{
+ btRigidBody *body1 = rb1->body;
+ btRigidBody *body2 = rb2->body;
+ btTransform transform1;
+ btTransform transform2;
+
+ make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn);
+
+ btTypedConstraint *con = new btGeneric6DofSpringConstraint(*body1, *body2, transform1, transform2, true);
+
+ return (rbConstraint *)con;
+}
+
+rbConstraint *RB_constraint_new_motor(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
+{
+ btRigidBody *body1 = rb1->body;
+ btRigidBody *body2 = rb2->body;
+ btTransform transform1;
+ btTransform transform2;
+
+ make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn);
+
+ btGeneric6DofConstraint *con = new btGeneric6DofConstraint(*body1, *body2, transform1, transform2, true);
+
+ /* unlock constraint axes */
+ for (int i = 0; i < 6; i++) {
+ con->setLimit(i, 0.0f, -1.0f);
+ }
+ /* unlock motor axes */
+ con->getTranslationalLimitMotor()->m_upperLimit.setValue(-1.0f, -1.0f, -1.0f);
+
+ return (rbConstraint*)con;
+}
+
+/* Cleanup ----------------------------- */
+
+void RB_constraint_delete(rbConstraint *con)
+{
+ btTypedConstraint *constraint = reinterpret_cast<btTypedConstraint*>(con);
+ delete constraint;
+}
+
+/* Settings ------------------------- */
+
+void RB_constraint_set_enabled(rbConstraint *con, int enabled)
+{
+ btTypedConstraint *constraint = reinterpret_cast<btTypedConstraint*>(con);
+
+ constraint->setEnabled(enabled);
+}
+
+void RB_constraint_set_limits_hinge(rbConstraint *con, float lower, float upper)
+{
+ btHingeConstraint *constraint = reinterpret_cast<btHingeConstraint*>(con);
+
+ // RB_TODO expose these
+ float softness = 0.9f;
+ float bias_factor = 0.3f;
+ float relaxation_factor = 1.0f;
+
+ constraint->setLimit(lower, upper, softness, bias_factor, relaxation_factor);
+}
+
+void RB_constraint_set_limits_slider(rbConstraint *con, float lower, float upper)
+{
+ btSliderConstraint *constraint = reinterpret_cast<btSliderConstraint*>(con);
+
+ constraint->setLowerLinLimit(lower);
+ constraint->setUpperLinLimit(upper);
+}
+
+void RB_constraint_set_limits_piston(rbConstraint *con, float lin_lower, float lin_upper, float ang_lower, float ang_upper)
+{
+ btSliderConstraint *constraint = reinterpret_cast<btSliderConstraint*>(con);
+
+ constraint->setLowerLinLimit(lin_lower);
+ constraint->setUpperLinLimit(lin_upper);
+ constraint->setLowerAngLimit(ang_lower);
+ constraint->setUpperAngLimit(ang_upper);
+}
+
+void RB_constraint_set_limits_6dof(rbConstraint *con, int axis, float lower, float upper)
+{
+ btGeneric6DofConstraint *constraint = reinterpret_cast<btGeneric6DofConstraint*>(con);
+
+ constraint->setLimit(axis, lower, upper);
+}
+
+void RB_constraint_set_stiffness_6dof_spring(rbConstraint *con, int axis, float stiffness)
+{
+ btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con);
+
+ constraint->setStiffness(axis, stiffness);
+}
+
+void RB_constraint_set_damping_6dof_spring(rbConstraint *con, int axis, float damping)
+{
+ btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con);
+
+ // invert damping range so that 0 = no damping
+ constraint->setDamping(axis, 1.0f - damping);
+}
+
+void RB_constraint_set_spring_6dof_spring(rbConstraint *con, int axis, int enable)
+{
+ btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con);
+
+ constraint->enableSpring(axis, enable);
+}
+
+void RB_constraint_set_equilibrium_6dof_spring(rbConstraint *con)
+{
+ btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con);
+
+ constraint->setEquilibriumPoint();
+}
+
+void RB_constraint_set_solver_iterations(rbConstraint *con, int num_solver_iterations)
+{
+ btTypedConstraint *constraint = reinterpret_cast<btTypedConstraint*>(con);
+
+ constraint->setOverrideNumSolverIterations(num_solver_iterations);
+}
+
+void RB_constraint_set_breaking_threshold(rbConstraint *con, float threshold)
+{
+ btTypedConstraint *constraint = reinterpret_cast<btTypedConstraint*>(con);
+
+ constraint->setBreakingImpulseThreshold(threshold);
+}
+
+void RB_constraint_set_enable_motor(rbConstraint *con, int enable_lin, int enable_ang)
+{
+ btGeneric6DofConstraint *constraint = reinterpret_cast<btGeneric6DofConstraint*>(con);
+
+ constraint->getTranslationalLimitMotor()->m_enableMotor[0] = enable_lin;
+ constraint->getRotationalLimitMotor(0)->m_enableMotor = enable_ang;
+}
+
+void RB_constraint_set_max_impulse_motor(rbConstraint *con, float max_impulse_lin, float max_impulse_ang)
+{
+ btGeneric6DofConstraint *constraint = reinterpret_cast<btGeneric6DofConstraint*>(con);
+
+ constraint->getTranslationalLimitMotor()->m_maxMotorForce.setX(max_impulse_lin);
+ constraint->getRotationalLimitMotor(0)->m_maxMotorForce = max_impulse_ang;
+}
+
+void RB_constraint_set_target_velocity_motor(rbConstraint *con, float velocity_lin, float velocity_ang)
+{
+ btGeneric6DofConstraint *constraint = reinterpret_cast<btGeneric6DofConstraint*>(con);
+
+ constraint->getTranslationalLimitMotor()->m_targetVelocity.setX(velocity_lin);
+ constraint->getRotationalLimitMotor(0)->m_targetVelocity = velocity_ang;
+}
+
+/* ********************************** */
diff --git a/intern/smoke/CMakeLists.txt b/intern/smoke/CMakeLists.txt
index 3b8a4c06e69..b6338f90ebc 100644
--- a/intern/smoke/CMakeLists.txt
+++ b/intern/smoke/CMakeLists.txt
@@ -29,7 +29,7 @@ set(INC
)
set(INC_SYS
- ../../extern/bullet2/src
+ ${BULLET_INCLUDE_DIRS}
${PNG_INCLUDE_DIR}
${ZLIB_INCLUDE_DIRS}
)
diff --git a/intern/smoke/SConscript b/intern/smoke/SConscript
index 0511257d319..c4a579b22b3 100644
--- a/intern/smoke/SConscript
+++ b/intern/smoke/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Daniel Genrich
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('intern/*.cpp')
diff --git a/intern/smoke/intern/FFT_NOISE.h b/intern/smoke/intern/FFT_NOISE.h
index 8b7e4f2728b..0d8be7db602 100644
--- a/intern/smoke/intern/FFT_NOISE.h
+++ b/intern/smoke/intern/FFT_NOISE.h
@@ -94,9 +94,9 @@ static void generatTile_FFT(float* const noiseTileData, std::string filename)
for (int x = 0; x < xRes; x++)
{
int index = x + y * xRes + z * xRes * yRes;
- float diff[] = {abs(x - xRes/2),
- abs(y - yRes/2),
- abs(z - zRes/2)};
+ float diff[] = {(float)abs(x - xRes / 2),
+ (float)abs(y - yRes / 2),
+ (float)abs(z - zRes / 2)};
float radius = sqrtf(diff[0] * diff[0] +
diff[1] * diff[1] +
diff[2] * diff[2]) / (xRes / 2);
diff --git a/intern/smoke/intern/FLUID_3D.cpp b/intern/smoke/intern/FLUID_3D.cpp
index 4eb11a46f5b..5f0b2439200 100644
--- a/intern/smoke/intern/FLUID_3D.cpp
+++ b/intern/smoke/intern/FLUID_3D.cpp
@@ -1055,7 +1055,7 @@ void FLUID_3D::project()
for (x = 1; x < _xRes - 1; x++, index++)
{
float vMask[3] = {1.0f, 1.0f, 1.0f}, vObst[3] = {0, 0, 0};
- float vR = 0.0f, vL = 0.0f, vT = 0.0f, vB = 0.0f, vD = 0.0f, vU = 0.0f;
+ // float vR = 0.0f, vL = 0.0f, vT = 0.0f, vB = 0.0f, vD = 0.0f, vU = 0.0f; // UNUSED
float pC = _pressure[index]; // center
float pR = _pressure[index + 1]; // right
@@ -1654,7 +1654,7 @@ void FLUID_3D::processBurn(float *fuel, float *smoke, float *react, float *flame
fuel[index] -= burning_rate * dt;
if (fuel[index] < 0.0f) fuel[index] = 0.0f;
/* process reaction coordinate */
- if (orig_fuel) {
+ if (orig_fuel > FLT_EPSILON) {
react[index] *= fuel[index]/orig_fuel;
react_coord = react[index];
}
@@ -1681,7 +1681,7 @@ void FLUID_3D::processBurn(float *fuel, float *smoke, float *react, float *flame
heat[index] = (1.0f-flame[index])*ignition_point + flame[index]*temp_max;
/* mix new color */
- if (r && smoke_emit) {
+ if (r && smoke_emit > FLT_EPSILON) {
float smoke_factor = smoke[index]/(orig_smoke+smoke_emit);
r[index] = (r[index] + _flame_smoke_color[0] * smoke_emit) * smoke_factor;
g[index] = (g[index] + _flame_smoke_color[1] * smoke_emit) * smoke_factor;
diff --git a/intern/smoke/intern/FLUID_3D.h b/intern/smoke/intern/FLUID_3D.h
index 8cadf3bc989..d98a39930de 100644
--- a/intern/smoke/intern/FLUID_3D.h
+++ b/intern/smoke/intern/FLUID_3D.h
@@ -41,9 +41,9 @@
using namespace std;
using namespace BasicVector;
-class WTURBULENCE;
+struct WTURBULENCE;
-class FLUID_3D
+struct FLUID_3D
{
public:
FLUID_3D(int *res, float dx, float dtdef, int init_heat, int init_fire, int init_colors);
diff --git a/intern/smoke/intern/FLUID_3D_STATIC.cpp b/intern/smoke/intern/FLUID_3D_STATIC.cpp
index ac485ad983a..e0a31a9d0c1 100644
--- a/intern/smoke/intern/FLUID_3D_STATIC.cpp
+++ b/intern/smoke/intern/FLUID_3D_STATIC.cpp
@@ -200,13 +200,15 @@ void FLUID_3D::setZeroZ(float* field, Vec3Int res, int zBegin, int zEnd)
const int totalCells = res[0] * res[1] * res[2];
int index = 0;
- if ((zBegin == 0))
- for (int y = 0; y < res[1]; y++)
- for (int x = 0; x < res[0]; x++, index++)
- {
- // front slab
- field[index] = 0.0f;
- }
+ if (zBegin == 0)
+ {
+ for (int y = 0; y < res[1]; y++)
+ for (int x = 0; x < res[0]; x++, index++)
+ {
+ // front slab
+ field[index] = 0.0f;
+ }
+ }
if (zEnd == res[2])
{
@@ -265,27 +267,29 @@ void FLUID_3D::copyBorderZ(float* field, Vec3Int res, int zBegin, int zEnd)
const int totalCells = res[0] * res[1] * res[2];
int index=0;
- if ((zBegin == 0))
- for (int y = 0; y < res[1]; y++)
- for (int x = 0; x < res[0]; x++, index++)
- {
- field[index] = field[index + slabSize];
- }
+ if (zBegin == 0)
+ {
+ for (int y = 0; y < res[1]; y++)
+ for (int x = 0; x < res[0]; x++, index++)
+ {
+ field[index] = field[index + slabSize];
+ }
+ }
- if ((zEnd == res[2]))
+ if (zEnd == res[2])
{
- index=0;
- int indexx=0;
- const int cellsslab = totalCells - slabSize;
+ index=0;
+ int indexx=0;
+ const int cellsslab = totalCells - slabSize;
- for (int y = 0; y < res[1]; y++)
- for (int x = 0; x < res[0]; x++, index++)
- {
- // back slab
- indexx = index + cellsslab;
- field[indexx] = field[indexx - slabSize];
- }
+ for (int y = 0; y < res[1]; y++)
+ for (int x = 0; x < res[0]; x++, index++)
+ {
+ // back slab
+ indexx = index + cellsslab;
+ field[indexx] = field[indexx - slabSize];
+ }
}
}
diff --git a/intern/smoke/intern/WAVELET_NOISE.h b/intern/smoke/intern/WAVELET_NOISE.h
index fce901b68aa..1b2fbfab58c 100644
--- a/intern/smoke/intern/WAVELET_NOISE.h
+++ b/intern/smoke/intern/WAVELET_NOISE.h
@@ -45,6 +45,8 @@
#include <MERSENNETWISTER.h>
+#include <string.h>
+
#ifdef WIN32
#include <float.h>
#define isnan _isnan
diff --git a/intern/smoke/intern/WTURBULENCE.h b/intern/smoke/intern/WTURBULENCE.h
index 1655bd95d32..4e76466bde5 100644
--- a/intern/smoke/intern/WTURBULENCE.h
+++ b/intern/smoke/intern/WTURBULENCE.h
@@ -32,7 +32,7 @@ class SIMPLE_PARSER;
///////////////////////////////////////////////////////////////////////////////
/// Main WTURBULENCE class, stores large density array etc.
///////////////////////////////////////////////////////////////////////////////
-class WTURBULENCE
+struct WTURBULENCE
{
public:
// both config files can be NULL, altCfg might override values from noiseCfg
diff --git a/intern/smoke/intern/smoke_API.cpp b/intern/smoke/intern/smoke_API.cpp
index 6011de0bddb..67f1ea29533 100644
--- a/intern/smoke/intern/smoke_API.cpp
+++ b/intern/smoke/intern/smoke_API.cpp
@@ -172,17 +172,25 @@ extern "C" void smoke_export(FLUID_3D *fluid, float *dt, float *dx, float **dens
float **heatold, float **vx, float **vy, float **vz, float **r, float **g, float **b, unsigned char **obstacles)
{
*dens = fluid->_density;
- *fuel = fluid->_fuel;
- *react = fluid->_react;
- *flame = fluid->_flame;
- *heat = fluid->_heat;
- *heatold = fluid->_heatOld;
+ if(fuel)
+ *fuel = fluid->_fuel;
+ if(react)
+ *react = fluid->_react;
+ if(flame)
+ *flame = fluid->_flame;
+ if(heat)
+ *heat = fluid->_heat;
+ if(heatold)
+ *heatold = fluid->_heatOld;
*vx = fluid->_xVelocity;
*vy = fluid->_yVelocity;
*vz = fluid->_zVelocity;
- *r = fluid->_color_r;
- *g = fluid->_color_g;
- *b = fluid->_color_b;
+ if(r)
+ *r = fluid->_color_r;
+ if(g)
+ *g = fluid->_color_g;
+ if(b)
+ *b = fluid->_color_b;
*obstacles = fluid->_obstacles;
*dt = fluid->_dt;
*dx = fluid->_dx;
@@ -195,12 +203,18 @@ extern "C" void smoke_turbulence_export(WTURBULENCE *wt, float **dens, float **r
return;
*dens = wt->_densityBig;
- *fuel = wt->_fuelBig;
- *react = wt->_reactBig;
- *flame = wt->_flameBig;
- *r = wt->_color_rBig;
- *g = wt->_color_gBig;
- *b = wt->_color_bBig;
+ if(fuel)
+ *fuel = wt->_fuelBig;
+ if(react)
+ *react = wt->_reactBig;
+ if(flame)
+ *flame = wt->_flameBig;
+ if(r)
+ *r = wt->_color_rBig;
+ if(g)
+ *g = wt->_color_gBig;
+ if(b)
+ *b = wt->_color_bBig;
*tcu = wt->_tcU;
*tcv = wt->_tcV;
*tcw = wt->_tcW;
diff --git a/intern/string/SConscript b/intern/string/SConscript
index dac0ead8e61..8e14605b15d 100644
--- a/intern/string/SConscript
+++ b/intern/string/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('intern/*.cpp')
diff --git a/intern/string/STR_String.h b/intern/string/STR_String.h
index a3d367a6fef..4607db45c7c 100644
--- a/intern/string/STR_String.h
+++ b/intern/string/STR_String.h
@@ -187,11 +187,11 @@ public:
inline friend bool operator>=(rcSTR_String lhs, const char *rhs) { return (strcmp(lhs, rhs)>=0); }
inline friend bool operator>=(const char *lhs, rcSTR_String rhs) { return (strcmp(lhs, rhs)>=0); }
inline friend bool operator==(rcSTR_String lhs, rcSTR_String rhs) { return ((lhs.Length() == rhs.Length()) && (memcmp(lhs, rhs, lhs.Length()) == 0)); }
- inline friend bool operator==(rcSTR_String lhs, const char *rhs) { return (memcmp(lhs, rhs, lhs.Length() + 1) == 0); }
- inline friend bool operator==(const char *lhs, rcSTR_String rhs) { return (memcmp(lhs, rhs, rhs.Length() + 1) == 0); }
- inline friend bool operator!=(rcSTR_String lhs, rcSTR_String rhs) { return ((lhs.Length() != rhs.Length()) || (memcmp(lhs, rhs, lhs.Length())!=0)); }
- inline friend bool operator!=(rcSTR_String lhs, const char *rhs) { return (memcmp(lhs, rhs, lhs.Length() + 1) != 0); }
- inline friend bool operator!=(const char *lhs, rcSTR_String rhs) { return (memcmp(lhs, rhs, rhs.Length() + 1) != 0); }
+ inline friend bool operator==(rcSTR_String lhs, const char *rhs) { return (strncmp(lhs, rhs, lhs.Length() + 1) == 0); }
+ inline friend bool operator==(const char *lhs, rcSTR_String rhs) { return (strncmp(lhs, rhs, rhs.Length() + 1) == 0); }
+ inline friend bool operator!=(rcSTR_String lhs, rcSTR_String rhs) { return ((lhs.Length() != rhs.Length()) || (memcmp(lhs, rhs, lhs.Length()) != 0)); }
+ inline friend bool operator!=(rcSTR_String lhs, const char *rhs) { return (strncmp(lhs, rhs, lhs.Length() + 1) != 0); }
+ inline friend bool operator!=(const char *lhs, rcSTR_String rhs) { return (strncmp(lhs, rhs, rhs.Length() + 1) != 0); }
// serializing
//int Serialize(pCStream stream);
diff --git a/intern/string/intern/STR_String.cpp b/intern/string/intern/STR_String.cpp
index 283b44380ee..4ea451311e4 100644
--- a/intern/string/intern/STR_String.cpp
+++ b/intern/string/intern/STR_String.cpp
@@ -106,7 +106,7 @@ STR_String::STR_String(const char *str)
this->m_data[this->m_len] = 0;
}
else {
- this->m_data = 0;
+ this->m_data = NULL;
this->m_len = 0;
this->m_max = 8;
}
diff --git a/intern/utfconv/SConscript b/intern/utfconv/SConscript
index 19a698b6a0b..875f6154d55 100644
--- a/intern/utfconv/SConscript
+++ b/intern/utfconv/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = ['utfconv.c']
diff --git a/intern/utfconv/utf_winfunc.c b/intern/utfconv/utf_winfunc.c
index 18f0e808562..3d7fb11309a 100644
--- a/intern/utfconv/utf_winfunc.c
+++ b/intern/utfconv/utf_winfunc.c
@@ -29,7 +29,7 @@
#include "utf_winfunc.h"
#include <io.h>
-#include <Windows.h>
+#include <windows.h>
#include <wchar.h>
@@ -75,6 +75,20 @@ int uopen(const char *filename, int oflag, int pmode)
return f;
}
+int uaccess(const char *filename, int mode)
+{
+ int r = -1;
+ UTF16_ENCODE(filename);
+
+ if (filename_16) {
+ r = _waccess(filename_16, mode);
+ }
+
+ UTF16_UN_ENCODE(filename);
+
+ return r;
+}
+
int urename(const char *oldname, const char *newname )
{
int r = -1;
@@ -123,7 +137,7 @@ void u_free_getenv(char *val)
free(val);
}
-int uput_getenv(const char *varname, char * value, size_t buffsize)
+int uput_getenv(const char *varname, char *value, size_t buffsize)
{
int r = 0;
wchar_t * str;
diff --git a/intern/utfconv/utf_winfunc.h b/intern/utfconv/utf_winfunc.h
index e92e7953cfc..45f6844af5a 100644
--- a/intern/utfconv/utf_winfunc.h
+++ b/intern/utfconv/utf_winfunc.h
@@ -32,6 +32,7 @@
FILE * ufopen(const char * filename, const char * mode);
int uopen(const char *filename, int oflag, int pmode);
+int uaccess(const char *filename, int mode);
int urename(const char *oldname, const char *newname );
char * u_alloc_getenv(const char *varname);
diff --git a/release/bin/blender-softwaregl b/release/bin/blender-softwaregl
index 970a7870760..63e6d9a9658 100755..100644
--- a/release/bin/blender-softwaregl
+++ b/release/bin/blender-softwaregl
@@ -1,25 +1,25 @@
-#!/bin/sh
-BF_DIST_BIN=`dirname "$0"`
-BF_PROGRAM="blender" # BF_PROGRAM=`basename "$0"`-bin
-exitcode=0
-
-LD_LIBRARY_PATH=${BF_DIST_BIN}/lib:${LD_LIBRARY_PATH}
-
-if [ -n "$LD_LIBRARYN32_PATH" ]; then
- LD_LIBRARYN32_PATH=${BF_DIST_BIN}/lib:${LD_LIBRARYN32_PATH}
-fi
-if [ -n "$LD_LIBRARYN64_PATH" ]; then
- LD_LIBRARYN64_PATH=${BF_DIST_BIN}/lib:${LD_LIBRARYN64_PATH}
-fi
-if [ -n "$LD_LIBRARY_PATH_64" ]; then
- LD_LIBRARY_PATH_64=${BF_DIST_BIN}/lib:${LD_LIBRARY_PATH_64}
-fi
-
-# Workaround for half-transparent windows when compiz is enabled
-XLIB_SKIP_ARGB_VISUALS=1
-
-export LD_LIBRARY_PATH LD_LIBRARYN32_PATH LD_LIBRARYN64_PATH LD_LIBRARY_PATH_64 LD_PRELOAD XLIB_SKIP_ARGB_VISUALS
-
-"$BF_DIST_BIN/$BF_PROGRAM" ${1+"$@"}
-exitcode=$?
-exit $exitcode
+#!/bin/sh
+BF_DIST_BIN=`dirname "$0"`
+BF_PROGRAM="blender" # BF_PROGRAM=`basename "$0"`-bin
+exitcode=0
+
+LD_LIBRARY_PATH=${BF_DIST_BIN}/lib:${LD_LIBRARY_PATH}
+
+if [ -n "$LD_LIBRARYN32_PATH" ]; then
+ LD_LIBRARYN32_PATH=${BF_DIST_BIN}/lib:${LD_LIBRARYN32_PATH}
+fi
+if [ -n "$LD_LIBRARYN64_PATH" ]; then
+ LD_LIBRARYN64_PATH=${BF_DIST_BIN}/lib:${LD_LIBRARYN64_PATH}
+fi
+if [ -n "$LD_LIBRARY_PATH_64" ]; then
+ LD_LIBRARY_PATH_64=${BF_DIST_BIN}/lib:${LD_LIBRARY_PATH_64}
+fi
+
+# Workaround for half-transparent windows when compiz is enabled
+XLIB_SKIP_ARGB_VISUALS=1
+
+export LD_LIBRARY_PATH LD_LIBRARYN32_PATH LD_LIBRARYN64_PATH LD_LIBRARY_PATH_64 LD_PRELOAD XLIB_SKIP_ARGB_VISUALS
+
+"$BF_DIST_BIN/$BF_PROGRAM" ${1+"$@"}
+exitcode=$?
+exit $exitcode
diff --git a/release/darwin/blender.app/Contents/Info.plist b/release/darwin/blender.app/Contents/Info.plist
index 064ffe5bc3f..ecea0e3ec76 100644
--- a/release/darwin/blender.app/Contents/Info.plist
+++ b/release/darwin/blender.app/Contents/Info.plist
@@ -50,5 +50,7 @@
</dict>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
+ <key>NSHighResolutionCapable</key>
+ <true/>
</dict>
</plist>
diff --git a/release/darwin/blender.app/Contents/MacOS/blender b/release/darwin/blender.app/Contents/MacOS/blender
index 5e05e74a307..48cdce85287 100644
--- a/release/darwin/blender.app/Contents/MacOS/blender
+++ b/release/darwin/blender.app/Contents/MacOS/blender
@@ -1 +1 @@
-placeholder
+placeholder
diff --git a/release/darwin/blenderplayer.app/Contents/Info.plist b/release/darwin/blenderplayer.app/Contents/Info.plist
index c7b9ceb568e..91eb2d7e84d 100644
--- a/release/darwin/blenderplayer.app/Contents/Info.plist
+++ b/release/darwin/blenderplayer.app/Contents/Info.plist
@@ -45,5 +45,7 @@
</array>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
+ <key>NSHighResolutionCapable</key>
+ <true/>
</dict>
</plist>
diff --git a/release/darwin/blenderplayer.app/Contents/MacOS/blenderplayer b/release/darwin/blenderplayer.app/Contents/MacOS/blenderplayer
index 5e05e74a307..48cdce85287 100644
--- a/release/darwin/blenderplayer.app/Contents/MacOS/blenderplayer
+++ b/release/darwin/blenderplayer.app/Contents/MacOS/blenderplayer
@@ -1 +1 @@
-placeholder
+placeholder
diff --git a/release/datafiles/LICENSE-bmonofont-i18n.ttf.txt b/release/datafiles/LICENSE-bmonofont-i18n.ttf.txt
new file mode 100644
index 00000000000..d972108816b
--- /dev/null
+++ b/release/datafiles/LICENSE-bmonofont-i18n.ttf.txt
@@ -0,0 +1,90 @@
+Blender Mono I18n font includes glyphs imported from the following fonts:
+
+1. DejaVu Sans Mono
+2. M+ 1M Regular
+3. Wen Quan Yi Micro Hei Mono
+4. Droid Sans Hebrew Regular (with some edits)
+
+These were merged using FontForge in the above order. For each glyph,
+a license of the font from which it was imported is applied.
+
+----------------------------------------------------------------------
+Summary of Copyrights and Licenses
+
+(1) DejaVu Sans Mono
+
+Copyright: 2003 Bitstream, Inc. (Bitstream font glyphs)
+ 2006 Tavmjong Bah (Arev font glyphs)
+ DejaVu changes are in public domain
+
+License:
+ DejaVu font glyphs are same as bmonofont.ttf. See LICENSE-bfont.ttf.txt.
+
+(2) M+ 1M Regular
+
+Copyright: 2002-2012 M+ FONTS PROJECT
+
+License:
+ These fonts are free software.
+ Unlimited permission is granted to use, copy, and distribute it, with or
+ without modification, either commercially and noncommercially.
+ THESE FONTS ARE PROVIDED "AS IS" WITHOUT WARRANTY.
+
+(3) Wen Quan Yi Micro Hei Mono
+
+Copyright: 2007 Google Corporation (Digitized data)
+ 2008-2009 WenQuanYi Project Board of Trustees
+ 2008-2009 mozbug and Qianqian Fang (Droid Sans Fallback extension interface)
+
+License: Apache-2.0 or GPL-3 with font embedding exception
+ See Appendices A and B.
+
+(4) Droid Sans Hebrew Regular
+
+Copyright: 2011 Google Corporation
+
+License: Apache-2.0
+ See Appendix A.
+
+----------------------------------------------------------------------
+Appendix A. Apache License Version 2.0
+
+ 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.
+
+----------------------------------------------------------------------
+Appendix B. GNU GPL Version 3 with font embedding exception
+
+GPL-3:
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Font embedding exception:
+ As a special exception, if you create a document which uses this
+ font, and embed this font or unaltered portions of this font into
+ the document, this font does not by itself cause the resulting
+ document to be covered by the GNU General Public License. This
+ exception does not however invalidate any other reasons why the
+ document might be covered by the GNU General Public License. If you
+ 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.
diff --git a/release/datafiles/LICENSE-droidsans.ttf.txt b/release/datafiles/LICENSE-droidsans.ttf.txt
new file mode 100644
index 00000000000..1f090edd309
--- /dev/null
+++ b/release/datafiles/LICENSE-droidsans.ttf.txt
@@ -0,0 +1,83 @@
+Blender Main I18n font ("droidsans.ttf") includes glyphs imported from the following fonts:
+
+1. DejaVu Sans
+2. Droid Sans Regular
+3. Samyak-devanagari
+4. Droid Sans Hebrew Regular
+5. Droid Sans Ethiopic Regular
+
+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.
+
+----------------------------------------------------------------------
+Summary of Copyrights and Licenses
+
+(1) DejaVu Sans
+
+Copyright: 2003 Bitstream, Inc. (Bitstream font glyphs)
+ 2006 Tavmjong Bah (Arev font glyphs)
+ DejaVu changes are in public domain
+
+License:
+ DejaVu font glyphs are same as bfont.ttf. See LICENSE-bfont.ttf.txt.
+
+(2), (4), (5) Droid Sans Fonts family
+
+Copyright:
+ Copyright © 2006, 2007, 2008, 2009, 2010 Google Corp.
+ Droid is a trademark of Google Corp.
+
+License: Apache-2.0
+ See Appendix A.
+
+(3) Samyak-devanagari
+Copyright: 2005-2006, Rahul Bhalerao <b.rahul.pm@gmail.com>
+ 2005-2006, Bageshri Salvi <sbageshri@gmail.com>
+ 2005-2006, Pravin Satpute <pravin.d.s@gmail.com>
+ 2005-2006, Sandeep Shedmake <Sandeep.shedmake@gmail.com>
+
+License: GPL-3 with font embedding exception
+ See Appendices B.
+
+----------------------------------------------------------------------
+Appendix A. Apache License Version 2.0
+
+ 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.
+
+----------------------------------------------------------------------
+Appendix B. GNU GPL Version 3 with font embedding exception
+
+GPL-3:
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Font embedding exception:
+ As a special exception, if you create a document which uses this
+ font, and embed this font or unaltered portions of this font into
+ the document, this font does not by itself cause the resulting
+ document to be covered by the GNU General Public License. This
+ exception does not however invalidate any other reasons why the
+ document might be covered by the GNU General Public License. If you
+ 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.
diff --git a/release/datafiles/blender_icons.png b/release/datafiles/blender_icons.png
deleted file mode 100644
index b0d5e825738..00000000000
--- a/release/datafiles/blender_icons.png
+++ /dev/null
Binary files differ
diff --git a/release/datafiles/blender_icons.sh b/release/datafiles/blender_icons.sh
new file mode 100755
index 00000000000..f923f02aee1
--- /dev/null
+++ b/release/datafiles/blender_icons.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# This script updates icons from the SVG file
+
+inkscape blender_icons.svg --export-dpi=90 --without-gui --export-png=blender_icons16.png
+inkscape blender_icons.svg --export-dpi=180 --without-gui --export-png=blender_icons32.png
diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg
new file mode 100644
index 00000000000..2d31301cee2
--- /dev/null
+++ b/release/datafiles/blender_icons.svg
@@ -0,0 +1,85288 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="602"
+ height="640"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.48.3.1 r9886"
+ version="1.0"
+ sodipodi:docname="blender_icons.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ style="display:inline;enable-background:new"
+ inkscape:export-filename="blender_icons16.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <title
+ id="title49470">Blender icons v. 2.5.08</title>
+ <defs
+ id="defs4">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 320 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="602 : 320 : 1"
+ inkscape:persp3d-origin="301 : 213.33333 : 1"
+ id="perspective29908" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient18134">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop18136" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop18138" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18118">
+ <stop
+ style="stop-color:#d297eb;stop-opacity:1;"
+ offset="0"
+ id="stop18120" />
+ <stop
+ style="stop-color:#a329d6;stop-opacity:1;"
+ offset="1"
+ id="stop18122" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18103">
+ <stop
+ id="stop18105"
+ offset="0"
+ style="stop-color:#42035d;stop-opacity:1" />
+ <stop
+ id="stop18108"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16367">
+ <stop
+ id="stop16369"
+ offset="0"
+ style="stop-color:#3c3c3c;stop-opacity:1" />
+ <stop
+ id="stop16371"
+ offset="1"
+ style="stop-color:#5a5a5a;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15806">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0"
+ id="stop15808" />
+ <stop
+ style="stop-color:#000000;stop-opacity:1"
+ offset="1"
+ id="stop15810" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient15796">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15798" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15800" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16595">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop16597" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop16599" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15647">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop15649" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop15651" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient30139">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop30141" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop30143" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient30131">
+ <stop
+ style="stop-color:#999999;stop-opacity:1;"
+ offset="0"
+ id="stop30133" />
+ <stop
+ style="stop-color:#999999;stop-opacity:0;"
+ offset="1"
+ id="stop30135" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient30122">
+ <stop
+ style="stop-color:#1e1e1e;stop-opacity:1;"
+ offset="0"
+ id="stop30124" />
+ <stop
+ style="stop-color:#1e1e1e;stop-opacity:0;"
+ offset="1"
+ id="stop30127" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient30390">
+ <stop
+ style="stop-color:#3d3d3d;stop-opacity:1"
+ offset="0"
+ id="stop30392" />
+ <stop
+ style="stop-color:#5d5d5d;stop-opacity:1"
+ offset="1"
+ id="stop30394" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient29870">
+ <stop
+ id="stop29872"
+ offset="0"
+ style="stop-color:#989898;stop-opacity:1" />
+ <stop
+ id="stop29874"
+ offset="1"
+ style="stop-color:#3d3d3d;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient29757">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop29759" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop29761" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16772">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop16774" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop16776" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16764">
+ <stop
+ style="stop-color:#1e1e1e;stop-opacity:1;"
+ offset="0"
+ id="stop16766" />
+ <stop
+ style="stop-color:#1e1e1e;stop-opacity:0;"
+ offset="1"
+ id="stop16768" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16723">
+ <stop
+ style="stop-color:#343434;stop-opacity:0.61960787;"
+ offset="0"
+ id="stop16725" />
+ <stop
+ style="stop-color:#3d3d3d;stop-opacity:1;"
+ offset="1"
+ id="stop16727" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient107519">
+ <stop
+ style="stop-color:#f8c5bd;stop-opacity:1"
+ offset="0"
+ id="stop107521" />
+ <stop
+ style="stop-color:#a42f0e;stop-opacity:1"
+ offset="1"
+ id="stop107523" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient107148">
+ <stop
+ id="stop107150"
+ offset="0"
+ style="stop-color:#ee7b68;stop-opacity:1" />
+ <stop
+ id="stop107152"
+ offset="1"
+ style="stop-color:#a42f0e;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient107142">
+ <stop
+ id="stop107144"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ <stop
+ id="stop107146"
+ offset="1"
+ style="stop-color:#f18d73;stop-opacity:0.2079646" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient106427">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop106429" />
+ <stop
+ style="stop-color:#030303;stop-opacity:1"
+ offset="1"
+ id="stop106431" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16504">
+ <stop
+ id="stop16506"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ <stop
+ id="stop16508"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient17602">
+ <stop
+ id="stop17604"
+ offset="0"
+ style="stop-color:#592e00;stop-opacity:1" />
+ <stop
+ id="stop17606"
+ offset="1"
+ style="stop-color:#9e5200;stop-opacity:0.57431373" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient17596">
+ <stop
+ style="stop-color:#ee7b00;stop-opacity:1"
+ offset="0"
+ id="stop17598" />
+ <stop
+ style="stop-color:#ffc280;stop-opacity:1"
+ offset="1"
+ id="stop17600" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient17438">
+ <stop
+ style="stop-color:#ff9f37;stop-opacity:1"
+ offset="0"
+ id="stop17440" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop17442" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient17430">
+ <stop
+ style="stop-color:#ff9f37;stop-opacity:1"
+ offset="0"
+ id="stop17432" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop17434" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient30958">
+ <stop
+ id="stop30960"
+ offset="0"
+ style="stop-color:#fff9cf;stop-opacity:1;" />
+ <stop
+ id="stop30962"
+ offset="1"
+ style="stop-color:#c7bc52;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient29312">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop29314" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop29316" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient29304">
+ <stop
+ style="stop-color:#11233f;stop-opacity:1;"
+ offset="0"
+ id="stop29306" />
+ <stop
+ style="stop-color:#162d50;stop-opacity:0;"
+ offset="1"
+ id="stop29308" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient27896">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop27898" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop27900" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient27854">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop27856" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop27858" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24343">
+ <stop
+ id="stop24345"
+ offset="0"
+ style="stop-color:#184990;stop-opacity:1;" />
+ <stop
+ id="stop24347"
+ offset="1"
+ style="stop-color:#c1d5f3;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient25417">
+ <stop
+ id="stop25419"
+ offset="0"
+ style="stop-color:#60553b;stop-opacity:1;" />
+ <stop
+ id="stop25421"
+ offset="1"
+ style="stop-color:#b0a17f;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient25108">
+ <stop
+ id="stop25110"
+ offset="0"
+ style="stop-color:white;stop-opacity:1;" />
+ <stop
+ id="stop25112"
+ offset="1"
+ style="stop-color:#c6c6c6;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient43807">
+ <stop
+ style="stop-color:#e31b1b;stop-opacity:1;"
+ offset="0"
+ id="stop43809" />
+ <stop
+ style="stop-color:#930000;stop-opacity:1;"
+ offset="1"
+ id="stop43811" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient38845">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop38847" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop38849" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient38831">
+ <stop
+ style="stop-color:#182b42;stop-opacity:1;"
+ offset="0"
+ id="stop38833" />
+ <stop
+ id="stop38836"
+ offset="0.38971797"
+ style="stop-color:#598ac7;stop-opacity:1;" />
+ <stop
+ style="stop-color:#f1f1f1;stop-opacity:1;"
+ offset="1"
+ id="stop38838" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient38256">
+ <stop
+ id="stop38258"
+ offset="0"
+ style="stop-color:#e7e0c7;stop-opacity:1;" />
+ <stop
+ id="stop38260"
+ offset="1"
+ style="stop-color:#f1eddf;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient71814">
+ <stop
+ style="stop-color:#6e0d00;stop-opacity:1;"
+ offset="0"
+ id="stop71816" />
+ <stop
+ style="stop-color:#6f2913;stop-opacity:0;"
+ offset="1"
+ id="stop71818" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37667">
+ <stop
+ id="stop37669"
+ offset="0"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ id="stop37671"
+ offset="1"
+ style="stop-color:black;stop-opacity:0" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient39080">
+ <stop
+ style="stop-color:#1a2a3d;stop-opacity:1;"
+ offset="0"
+ id="stop39082" />
+ <stop
+ id="stop39084"
+ offset="0.5"
+ style="stop-color:#95b0d1;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop39086" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient40809">
+ <stop
+ style="stop-color:#0059d7;stop-opacity:1;"
+ offset="0"
+ id="stop40811" />
+ <stop
+ style="stop-color:#b7d4ff;stop-opacity:1;"
+ offset="1"
+ id="stop40813" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient40703">
+ <stop
+ style="stop-color:#143564;stop-opacity:1;"
+ offset="0"
+ id="stop40705" />
+ <stop
+ style="stop-color:#c1d7f8;stop-opacity:1;"
+ offset="1"
+ id="stop40707" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37925">
+ <stop
+ id="stop37927"
+ offset="0"
+ style="stop-color:#e7cbab;stop-opacity:1;" />
+ <stop
+ id="stop37929"
+ offset="1"
+ style="stop-color:#af7333;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient36273">
+ <stop
+ id="stop36275"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop36277"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient35411">
+ <stop
+ id="stop35414"
+ offset="0"
+ style="stop-color:#2b5385;stop-opacity:1;" />
+ <stop
+ id="stop35416"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient31356">
+ <stop
+ id="stop31358"
+ offset="0"
+ style="stop-color:#1a1a1a;stop-opacity:1" />
+ <stop
+ id="stop31360"
+ offset="1"
+ style="stop-color:#1a1a1a;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient28107"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7228842,8.5733105e-8,-9.4831885e-8,0.7995973,71.917045,14.582004)"
+ cx="256.49512"
+ cy="81.396774"
+ fx="256.49512"
+ fy="81.396774"
+ r="3.779551" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient28105"
+ gradientUnits="userSpaceOnUse"
+ x1="875.73486"
+ y1="422.77902"
+ x2="885.04938"
+ y2="427.01648" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient28887"
+ id="linearGradient28103"
+ gradientUnits="userSpaceOnUse"
+ x1="873.09998"
+ y1="422.09964"
+ x2="881.01172"
+ y2="429.23453" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient28101"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.6572588,1.2500456,-1.6473175,2.2058465,774.83033,-697.31982)"
+ cx="76.180473"
+ cy="500.20651"
+ fx="76.180473"
+ fy="500.20651"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient28099"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <linearGradient
+ id="linearGradient28887">
+ <stop
+ style="stop-color:#2158a7;stop-opacity:1;"
+ offset="0"
+ id="stop28889" />
+ <stop
+ style="stop-color:#2f73d5;stop-opacity:0.19607843;"
+ offset="1"
+ id="stop28891" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24168">
+ <stop
+ id="stop24170"
+ offset="0"
+ style="stop-color:#182437;stop-opacity:1;" />
+ <stop
+ id="stop24172"
+ offset="1"
+ style="stop-color:#2b4163;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24144">
+ <stop
+ id="stop24146"
+ offset="0"
+ style="stop-color:#3d361a;stop-opacity:1;" />
+ <stop
+ style="stop-color:#d1c595;stop-opacity:1;"
+ offset="0.17958513"
+ id="stop24148" />
+ <stop
+ id="stop24150"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24101">
+ <stop
+ style="stop-color:#643400;stop-opacity:1;"
+ offset="0"
+ id="stop24103" />
+ <stop
+ id="stop24105"
+ offset="0.22606115"
+ style="stop-color:#ed983d;stop-opacity:1;" />
+ <stop
+ style="stop-color:#fff0d5;stop-opacity:1;"
+ offset="1"
+ id="stop24107" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24081">
+ <stop
+ id="stop24083"
+ offset="0"
+ style="stop-color:#b45d00;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ff982a;stop-opacity:1;"
+ offset="0.3167825"
+ id="stop24085" />
+ <stop
+ id="stop24087"
+ offset="1"
+ style="stop-color:#ffedd5;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient23302">
+ <stop
+ id="stop23304"
+ offset="0"
+ style="stop-color:#b45d00;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ff982a;stop-opacity:1;"
+ offset="0.39332664"
+ id="stop23306" />
+ <stop
+ id="stop23308"
+ offset="1"
+ style="stop-color:#ffedd5;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient24735">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop24737" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop24739" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24727">
+ <stop
+ style="stop-color:#3d361a;stop-opacity:1;"
+ offset="0"
+ id="stop24729" />
+ <stop
+ id="stop24731"
+ offset="0.77520341"
+ style="stop-color:#d1c595;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop24733" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24711">
+ <stop
+ style="stop-color:#3d361a;stop-opacity:1;"
+ offset="0"
+ id="stop24713" />
+ <stop
+ id="stop24715"
+ offset="0.21609697"
+ style="stop-color:#d1c595;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop24717" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24695">
+ <stop
+ style="stop-color:#3d361a;stop-opacity:1;"
+ offset="0"
+ id="stop24697" />
+ <stop
+ id="stop24699"
+ offset="0.60401857"
+ style="stop-color:#d1c595;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop24701" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24687">
+ <stop
+ style="stop-color:#3d361a;stop-opacity:1;"
+ offset="0"
+ id="stop24689" />
+ <stop
+ id="stop24691"
+ offset="0.59630167"
+ style="stop-color:#d1c595;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop24693" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24679">
+ <stop
+ style="stop-color:#3d361a;stop-opacity:1;"
+ offset="0"
+ id="stop24681" />
+ <stop
+ id="stop24683"
+ offset="0.45537567"
+ style="stop-color:#d1c595;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop24685" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24671">
+ <stop
+ style="stop-color:#3d361a;stop-opacity:1;"
+ offset="0"
+ id="stop24673" />
+ <stop
+ id="stop24675"
+ offset="0.29527253"
+ style="stop-color:#d1c595;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop24677" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient23705">
+ <stop
+ id="stop23707"
+ offset="0"
+ style="stop-color:#d4d2bf;stop-opacity:1;" />
+ <stop
+ id="stop23709"
+ offset="1"
+ style="stop-color:#857f5d;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient23906">
+ <stop
+ id="stop23908"
+ offset="0"
+ style="stop-color:#ff921d;stop-opacity:1;" />
+ <stop
+ id="stop23910"
+ offset="1"
+ style="stop-color:#ffa751;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient42459">
+ <stop
+ style="stop-color:#e7dfab;stop-opacity:1;"
+ offset="0"
+ id="stop42461" />
+ <stop
+ style="stop-color:#af9d33;stop-opacity:1;"
+ offset="1"
+ id="stop42463" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient41723"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(744,397)"
+ x1="-287"
+ y1="-276.1875"
+ x2="-281.4375"
+ y2="-271.9375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient41721"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.695652,0,0,0.869703,342.06514,-90.66358)"
+ x1="171.42436"
+ y1="259.71194"
+ x2="170.20523"
+ y2="244.96393" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24246"
+ gradientUnits="userSpaceOnUse"
+ x1="426.12415"
+ y1="179.12074"
+ x2="425"
+ y2="179.12285" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24143"
+ id="linearGradient24244"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(186,-105)"
+ x1="246.12868"
+ y1="283.63254"
+ x2="237.75459"
+ y2="266.34406" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24278"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(744,397)"
+ x1="-287.56247"
+ y1="-276.71042"
+ x2="-282.59851"
+ y2="-271.35284" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient24276"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.695652,0,0,0.869703,342.06514,-90.66358)"
+ x1="190.33647"
+ y1="266.7905"
+ x2="170.9689"
+ y2="247.58694" />
+ <linearGradient
+ id="linearGradient24143">
+ <stop
+ id="stop24145"
+ offset="0"
+ style="stop-color:#3d361a;stop-opacity:1;" />
+ <stop
+ style="stop-color:#d1c595;stop-opacity:1;"
+ offset="0.5"
+ id="stop24669" />
+ <stop
+ id="stop24147"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24687"
+ id="linearGradient24238"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,304.84783,-86.57833)"
+ x1="120.2969"
+ y1="281.26645"
+ x2="116.37123"
+ y2="260.21841" />
+ <linearGradient
+ id="linearGradient24642">
+ <stop
+ style="stop-color:#d0dbe8;stop-opacity:1;"
+ offset="0"
+ id="stop24644" />
+ <stop
+ style="stop-color:#6ca3e9;stop-opacity:0;"
+ offset="1"
+ id="stop24646" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24632">
+ <stop
+ style="stop-color:#28394f;stop-opacity:1;"
+ offset="0"
+ id="stop24634" />
+ <stop
+ id="stop24636"
+ offset="0.17637014"
+ style="stop-color:#0d386a;stop-opacity:0.78431374;" />
+ <stop
+ id="stop24638"
+ offset="0.35274029"
+ style="stop-color:#18437d;stop-opacity:0.47058824;" />
+ <stop
+ style="stop-color:#154e94;stop-opacity:0;"
+ offset="1"
+ id="stop24640" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22562"
+ id="radialGradient23167"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9934369,-0.1143813,0.1033636,0.8977446,-30.451879,30.134649)"
+ cx="-0.10810681"
+ cy="294.60239"
+ fx="-0.10810681"
+ fy="294.60239"
+ r="6.6750002" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient23201"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-61,0)"
+ x1="22.75"
+ y1="245"
+ x2="24.25"
+ y2="245" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient23199"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1,0)"
+ x1="22.75"
+ y1="245"
+ x2="24.5"
+ y2="245" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask23189">
+ <g
+ transform="translate(-28,49)"
+ id="g23193">
+ <rect
+ y="237"
+ x="22"
+ height="16"
+ width="9"
+ id="rect23195"
+ style="fill:url(#linearGradient23199);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ transform="scale(-1,1)"
+ style="fill:url(#linearGradient23201);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23197"
+ width="9"
+ height="16"
+ x="-38"
+ y="237" />
+ </g>
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24208"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-46.000005,-117)"
+ x1="257.75"
+ y1="388"
+ x2="272"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24206"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-54.000005,-120)"
+ x1="258.52756"
+ y1="388"
+ x2="279"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24204"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-48.983883,-126)"
+ x1="259.75"
+ y1="388"
+ x2="273"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24202"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-52.983883,-129)"
+ x1="258"
+ y1="388"
+ x2="273"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23379"
+ gradientUnits="userSpaceOnUse"
+ x1="126.37032"
+ y1="110.87843"
+ x2="139.86742"
+ y2="126.57021" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15437"
+ id="linearGradient23377"
+ gradientUnits="userSpaceOnUse"
+ x1="137.88235"
+ y1="124.67203"
+ x2="131.3092"
+ y2="117.24104" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13938"
+ id="linearGradient23375"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9995363,0,0,-1.0036971,220.01067,167.35026)"
+ x1="52.06274"
+ y1="96.767769"
+ x2="44.999863"
+ y2="103.57072" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14232"
+ id="linearGradient23373"
+ gradientUnits="userSpaceOnUse"
+ x1="122.38876"
+ y1="108.82882"
+ x2="133.88583"
+ y2="121.20407" />
+ <linearGradient
+ id="linearGradient23974">
+ <stop
+ id="stop23976"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop23978"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient40983">
+ <stop
+ style="stop-color:#6a9ae0;stop-opacity:1;"
+ offset="0"
+ id="stop40985" />
+ <stop
+ style="stop-color:#5189db;stop-opacity:0;"
+ offset="1"
+ id="stop40987" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23280"
+ gradientUnits="userSpaceOnUse"
+ x1="127.60629"
+ y1="112.12571"
+ x2="140.72693"
+ y2="126.72997" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23278"
+ gradientUnits="userSpaceOnUse"
+ x1="125.01582"
+ y1="110.86718"
+ x2="132.46898"
+ y2="119.54019" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient23276"
+ gradientUnits="userSpaceOnUse"
+ x1="139.37782"
+ y1="126.3454"
+ x2="131.71249"
+ y2="118.34238" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14418"
+ id="linearGradient23274"
+ gradientUnits="userSpaceOnUse"
+ x1="144.8255"
+ y1="132.15414"
+ x2="130.10634"
+ y2="117.10313" />
+ <linearGradient
+ id="linearGradient30777"
+ inkscape:collect="always">
+ <stop
+ id="stop30779"
+ offset="0"
+ style="stop-color:#acacac;stop-opacity:1" />
+ <stop
+ id="stop30781"
+ offset="1"
+ style="stop-color:black;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient29485">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop29487" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop29489" />
+ </linearGradient>
+ <filter
+ inkscape:collect="always"
+ x="-0.55821538"
+ width="2.1164308"
+ y="-1.0219563"
+ height="3.0439126"
+ id="filter20578"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="2.0410255"
+ id="feGaussianBlur20580" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath20586">
+ <path
+ sodipodi:type="arc"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path34889"
+ sodipodi:cx="53"
+ sodipodi:cy="554"
+ sodipodi:rx="4.5"
+ sodipodi:ry="2.25"
+ d="m 57.5,554 a 4.5,2.25 0 1 1 -9,0 4.5,2.25 0 1 1 9,0 z"
+ transform="matrix(1.870472,0.1894819,-0.6587894,2.4281336,319.59052,-798.11661)" />
+ </clipPath>
+ <radialGradient
+ id="aigrd2"
+ cx="20.892099"
+ cy="114.5684"
+ r="5.256"
+ fx="20.892099"
+ fy="114.5684"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ offset="0"
+ style="stop-color:#F0F0F0"
+ id="stop15566" />
+ <stop
+ offset="1.0000000"
+ style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
+ id="stop15568" />
+ </radialGradient>
+ <filter
+ inkscape:collect="always"
+ x="-0.45600089"
+ width="1.9120018"
+ y="-0.50666559"
+ height="2.0133312"
+ id="filter63011"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.899998"
+ id="feGaussianBlur63013" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath13106">
+ <path
+ style="fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ id="path34850"
+ 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" />
+ </clipPath>
+ <linearGradient
+ id="linearGradient58334">
+ <stop
+ id="stop58336"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.87628865;" />
+ <stop
+ id="stop58338"
+ offset="1.0000000"
+ style="stop-color:#fffffe;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient8864">
+ <stop
+ id="stop8866"
+ offset="0"
+ style="stop-color:#b43214;stop-opacity:1;" />
+ <stop
+ id="stop8868"
+ offset="1"
+ style="stop-color:#e86830;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient20324">
+ <stop
+ id="stop20326"
+ offset="0"
+ style="stop-color:#35241b;stop-opacity:1;" />
+ <stop
+ style="stop-color:#69390e;stop-opacity:0.8392157;"
+ offset="0.17637014"
+ id="stop20328" />
+ <stop
+ style="stop-color:#6c5b15;stop-opacity:0.67843139;"
+ offset="0.35274029"
+ id="stop20330" />
+ <stop
+ id="stop20332"
+ offset="1"
+ style="stop-color:#947b15;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37623">
+ <stop
+ id="stop37625"
+ offset="0"
+ style="stop-color:#e5e1ca;stop-opacity:1;" />
+ <stop
+ id="stop37627"
+ offset="1"
+ style="stop-color:#d6ca22;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient36116">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop36118" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop36120" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22852"
+ gradientUnits="userSpaceOnUse"
+ x1="133.94305"
+ y1="116.00471"
+ x2="117.29694"
+ y2="133.14267" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient22850"
+ gradientUnits="userSpaceOnUse"
+ x1="136.55727"
+ y1="125.87247"
+ x2="129.70895"
+ y2="118.00132" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22896"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.01387,0)"
+ x1="441.98615"
+ y1="77.44017"
+ x2="424.75217"
+ y2="75.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22846"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.01387,0)"
+ x1="438.61115"
+ y1="78"
+ x2="424.75217"
+ y2="75.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22844"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.01387,0)"
+ x1="437.98615"
+ y1="77"
+ x2="424.75217"
+ y2="75.5" />
+ <linearGradient
+ id="linearGradient22562">
+ <stop
+ style="stop-color:#001e50;stop-opacity:1;"
+ offset="0"
+ id="stop22564" />
+ <stop
+ style="stop-color:#1e3e70;stop-opacity:0;"
+ offset="1"
+ id="stop22566" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22562"
+ id="linearGradient22842"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(399.01387,-202)"
+ x1="28.4375"
+ y1="277"
+ x2="23.25"
+ y2="276.92188" />
+ <linearGradient
+ id="linearGradient22556">
+ <stop
+ id="stop22558"
+ offset="0"
+ style="stop-color:#6a9bef;stop-opacity:1" />
+ <stop
+ style="stop-color:#bccee8;stop-opacity:0.58450705;"
+ offset="0.77941167"
+ id="stop22568" />
+ <stop
+ id="stop22560"
+ offset="1"
+ style="stop-color:#ccdaed;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22556"
+ id="linearGradient22840"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.785748,0,0,0.78488,265.93616,46.1048)"
+ x1="210.08989"
+ y1="38.088879"
+ x2="199.27217"
+ y2="38.088879" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="radialGradient22838"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8128508,0,0,0.8128508,80.474142,14.46897)"
+ cx="430.00003"
+ cy="77.3125"
+ fx="430.00003"
+ fy="77.3125"
+ r="8" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22882"
+ id="linearGradient22848"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1929722,0,0,0.5,-462.63135,-59)"
+ x1="24"
+ y1="285"
+ x2="31.538462"
+ y2="285" />
+ <linearGradient
+ id="linearGradient22882">
+ <stop
+ style="stop-color:#323232;stop-opacity:0;"
+ offset="0"
+ id="stop22884" />
+ <stop
+ id="stop22886"
+ offset="0.21233012"
+ style="stop-color:#323232;stop-opacity:0.49803922;" />
+ <stop
+ id="stop22888"
+ offset="0.54086536"
+ style="stop-color:#323232;stop-opacity:1;" />
+ <stop
+ style="stop-color:#323232;stop-opacity:0.49803922;"
+ offset="0.83381736"
+ id="stop22890" />
+ <stop
+ style="stop-color:#323232;stop-opacity:0;"
+ offset="1"
+ id="stop22892" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22882"
+ id="linearGradient22880"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0369025,0,0,1.5,-458.38567,-344)"
+ x1="23.959812"
+ y1="285"
+ x2="31.498274"
+ y2="285" />
+ <linearGradient
+ id="linearGradient35407">
+ <stop
+ id="stop35409"
+ offset="0"
+ style="stop-color:#a17306;stop-opacity:1;" />
+ <stop
+ style="stop-color:#cca649;stop-opacity:1;"
+ offset="0.43277758"
+ id="stop35411" />
+ <stop
+ id="stop35413"
+ offset="1"
+ style="stop-color:#f9f5e9;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient35391">
+ <stop
+ id="stop35393"
+ offset="0"
+ style="stop-color:#322800;stop-opacity:1;" />
+ <stop
+ id="stop35395"
+ offset="1"
+ style="stop-color:#6e4800;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient34157">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop34159" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop34161" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38256"
+ id="linearGradient22457"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-18)"
+ x1="-25.5"
+ y1="36.828632"
+ x2="-25.5"
+ y2="26.027344" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22455"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-354,-314.00002)"
+ x1="308"
+ y1="323"
+ x2="343.26239"
+ y2="340" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22453"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-18)"
+ x1="-27.299919"
+ y1="37"
+ x2="-25.5"
+ y2="23.414351" />
+ <linearGradient
+ id="linearGradient21609">
+ <stop
+ id="stop21611"
+ offset="0"
+ style="stop-color:black;stop-opacity:1" />
+ <stop
+ id="stop21613"
+ offset="1"
+ style="stop-color:white;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient21609"
+ id="linearGradient20961"
+ gradientUnits="userSpaceOnUse"
+ x1="162"
+ y1="103.71875"
+ x2="165"
+ y2="103.75" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask20957">
+ <rect
+ y="101"
+ x="162"
+ height="5"
+ width="8"
+ id="rect20959"
+ style="fill:url(#linearGradient20961);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32335"
+ gradientUnits="userSpaceOnUse"
+ x1="285.39999"
+ y1="323.80002"
+ x2="286.60001"
+ y2="325" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22081"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-157.00004,-233.00002)"
+ x1="308"
+ y1="323"
+ x2="337.80573"
+ y2="337.517" />
+ <filter
+ inkscape:collect="always"
+ id="filter23214"
+ x="-0.48015866"
+ width="1.9603173"
+ y="-0.47984189"
+ height="1.9596838"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.53351805"
+ id="feGaussianBlur23216" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient19900">
+ <stop
+ style="stop-color:#1a1a1a;stop-opacity:1;"
+ offset="0"
+ id="stop19902" />
+ <stop
+ style="stop-color:#1a1a1a;stop-opacity:0;"
+ offset="1"
+ id="stop19904" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18105">
+ <stop
+ id="stop18107"
+ offset="0"
+ style="stop-color:#162d50;stop-opacity:1" />
+ <stop
+ id="stop18109"
+ offset="1"
+ style="stop-color:#1e3e70;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18056">
+ <stop
+ id="stop18058"
+ offset="0"
+ style="stop-color:#162d50;stop-opacity:1" />
+ <stop
+ id="stop18060"
+ offset="1"
+ style="stop-color:#295498;stop-opacity:0.34057972;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient21327">
+ <stop
+ style="stop-color:#1e3e70;stop-opacity:1;"
+ offset="0"
+ id="stop21329" />
+ <stop
+ style="stop-color:#1e3e70;stop-opacity:0;"
+ offset="1"
+ id="stop21331" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient19625">
+ <stop
+ id="stop19627"
+ offset="0"
+ style="stop-color:#2258a6;stop-opacity:1;" />
+ <stop
+ id="stop19629"
+ offset="1"
+ style="stop-color:#c1d7f8;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35391"
+ id="linearGradient20217"
+ x1="408.75"
+ y1="-35.483223"
+ x2="408.75"
+ y2="-40.000008"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient18821">
+ <stop
+ style="stop-color:#fc6b58;stop-opacity:1;"
+ offset="0"
+ id="stop18823" />
+ <stop
+ style="stop-color:#fc6b58;stop-opacity:0;"
+ offset="1"
+ id="stop18825" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient22187"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <linearGradient
+ id="linearGradient29149">
+ <stop
+ id="stop29151"
+ offset="0"
+ style="stop-color:#76adff;stop-opacity:1;" />
+ <stop
+ id="stop29153"
+ offset="1"
+ style="stop-color:#a5c9ff;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient21820"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient21818"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.4624192,0,0,1.4467089,-36.975824,-224.99718)"
+ cx="79.959885"
+ cy="503.81497"
+ fx="79.959885"
+ fy="503.81497"
+ r="2.9089756" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient21816"
+ gradientUnits="userSpaceOnUse"
+ x1="89.526657"
+ y1="511.42972"
+ x2="78.000008"
+ y2="501.04794" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient21814"
+ gradientUnits="userSpaceOnUse"
+ x1="80.768944"
+ y1="504.67188"
+ x2="76.885078"
+ y2="501.58331" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262"
+ id="radialGradient21741"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3949409,0.3949425,-0.4243709,0.4254619,321.60762,256.85923)"
+ cx="75.95578"
+ cy="492.15359"
+ fx="75.95578"
+ fy="492.15359"
+ r="3.1650217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15809"
+ id="linearGradient21773"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9281768,0,0,0.9971589,401.42265,-484.56523)"
+ x1="88.874489"
+ y1="502.71924"
+ x2="41.311054"
+ y2="501.10059" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient21776"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8666667,0,0,0.9166667,406.13333,-443.79167)"
+ x1="108"
+ y1="500"
+ x2="54.8125"
+ y2="500" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262"
+ id="radialGradient22166"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8886193,0.8021825,-0.8051059,0.8972684,411.80247,-8.668512)"
+ cx="74.518959"
+ cy="499.99969"
+ fx="74.518959"
+ fy="499.99969"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient22164"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.4624192,0,0,1.4467089,-36.975824,-224.99718)"
+ cx="79.959885"
+ cy="503.81497"
+ fx="79.959885"
+ fy="503.81497"
+ r="2.9089756" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22162"
+ gradientUnits="userSpaceOnUse"
+ x1="89.526657"
+ y1="511.42972"
+ x2="78.000008"
+ y2="501.04794" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient22160"
+ gradientUnits="userSpaceOnUse"
+ x1="80.768944"
+ y1="504.67188"
+ x2="76.885078"
+ y2="501.58331" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262"
+ id="radialGradient22158"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3949409,0.3949425,-0.4243709,0.4254619,321.60762,256.85923)"
+ cx="75.95578"
+ cy="492.15359"
+ fx="75.95578"
+ fy="492.15359"
+ r="3.1650217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15809"
+ id="linearGradient22156"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.9971589,396,-484.56523)"
+ x1="88.874489"
+ y1="502.71924"
+ x2="41.311054"
+ y2="501.10059" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient22154"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8666667,0,0,0.9166667,406.13333,-443.79167)"
+ x1="108"
+ y1="500"
+ x2="54.8125"
+ y2="500" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient15809">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop15811" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop15813" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15437">
+ <stop
+ id="stop15439"
+ offset="0"
+ style="stop-color:#20529e;stop-opacity:1;" />
+ <stop
+ id="stop15441"
+ offset="1"
+ style="stop-color:#1d3f71;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15425">
+ <stop
+ style="stop-color:#8c0000;stop-opacity:1;"
+ offset="0"
+ id="stop15427" />
+ <stop
+ style="stop-color:#c80000;stop-opacity:0;"
+ offset="1"
+ id="stop15429" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient14262">
+ <stop
+ id="stop14264"
+ offset="0"
+ style="stop-color:#2661b6;stop-opacity:1;" />
+ <stop
+ id="stop14266"
+ offset="1"
+ style="stop-color:#c1d7f8;stop-opacity:0;" />
+ </linearGradient>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath17188">
+ <path
+ style="fill:#d3d7cf;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 240.5,-19.90625 c -1.87005,0 -3.40625,1.536202 -3.40625,3.40625 l 0,2 c 0,1.87005 1.53621,3.40625 3.40625,3.40625 l 0,-2.8125 c -0.33932,0 -0.59375,-0.254431 -0.59375,-0.59375 l 0,-2 c 0,-0.339319 0.25443,-0.59375 0.59375,-0.59375 l 0,-2.8125 z"
+ id="path17190" />
+ </clipPath>
+ <linearGradient
+ id="linearGradient18344">
+ <stop
+ style="stop-color:#6c6c6c;stop-opacity:1;"
+ offset="0"
+ id="stop18346" />
+ <stop
+ style="stop-color:#f0f0f0;stop-opacity:1;"
+ offset="1"
+ id="stop18348" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient5060">
+ <stop
+ id="stop5062"
+ offset="0"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ id="stop5064"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient27957">
+ <stop
+ id="stop27959"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:0;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0.59290552"
+ id="stop27963" />
+ <stop
+ id="stop27961"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient23647">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop23649" />
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="1"
+ id="stop23651" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient23390">
+ <stop
+ style="stop-color:#000000;stop-opacity:1.0000000"
+ offset="0.0000000"
+ id="stop23392" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1.0000000"
+ offset="1.0000000"
+ id="stop23400" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16359">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop16361" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop16363" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15746"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.207032,0,0,0.903901,679.26,-38.98429)"
+ x1="386.09836"
+ y1="230.09529"
+ x2="388.35962"
+ y2="248.10277" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15744"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.207032,0,0,0.903901,679.30638,-38.92179)"
+ x1="390.61163"
+ y1="229.34804"
+ x2="390.55936"
+ y2="248.24983" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15683"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.203777,0,0,0.903901,837.9645,-18.01568)"
+ x1="383.67041"
+ y1="225.94354"
+ x2="385.60632"
+ y2="248.55901" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15681"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.207032,0,0,0.903901,839.2424,-18.01568)"
+ x1="391.80222"
+ y1="230.5647"
+ x2="387.94211"
+ y2="247.83209" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient13545"
+ gradientUnits="userSpaceOnUse"
+ x1="126.37006"
+ y1="112.31642"
+ x2="137.11284"
+ y2="126.19643" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient15878"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ id="linearGradient20756">
+ <stop
+ style="stop-color:#932200;stop-opacity:1;"
+ offset="0"
+ id="stop20758" />
+ <stop
+ style="stop-color:#f8420a;stop-opacity:1;"
+ offset="1"
+ id="stop20760" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20756"
+ id="linearGradient13543"
+ gradientUnits="userSpaceOnUse"
+ x1="126.45676"
+ y1="110.59049"
+ x2="134.94949"
+ y2="122.08995" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15693"
+ 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"
+ id="linearGradient15691"
+ 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"
+ id="linearGradient15689"
+ 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"
+ id="linearGradient15687"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.222225,0,0,1,-87.33412,169)"
+ x1="217.22589"
+ y1="107.25085"
+ x2="235.90916"
+ y2="121" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15854"
+ gradientUnits="userSpaceOnUse"
+ x1="381.56296"
+ y1="234.59885"
+ x2="393"
+ y2="247.99632" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31456"
+ id="linearGradient13639"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8329616,0,0,0.8433415,58.576199,29.193917)"
+ x1="399.987"
+ y1="259.26602"
+ x2="385.88068"
+ y2="241.70195" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23178"
+ id="linearGradient52023"
+ gradientUnits="userSpaceOnUse"
+ x1="390.75"
+ y1="244.5312"
+ x2="395.9375"
+ y2="250.9062" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31456"
+ id="linearGradient14661"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8329616,0,0,0.8433415,58.576199,29.193917)"
+ x1="400.88739"
+ y1="257.4874"
+ x2="385.88068"
+ y2="241.70195" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23178"
+ id="linearGradient52025"
+ gradientUnits="userSpaceOnUse"
+ x1="391.01859"
+ y1="241.86644"
+ x2="396.79285"
+ y2="247.83134" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31456"
+ id="linearGradient15995"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8329616,0,0,0.8433415,58.576199,29.193917)"
+ x1="399.08661"
+ y1="257.41327"
+ x2="385.88068"
+ y2="241.70195" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15993"
+ gradientUnits="userSpaceOnUse"
+ x1="381.5"
+ y1="231.7812"
+ x2="393.4375"
+ y2="247.1562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15997"
+ gradientUnits="userSpaceOnUse"
+ x1="381.5"
+ y1="231.7812"
+ x2="393.4375"
+ y2="247.1562" />
+ <linearGradient
+ id="linearGradient47130">
+ <stop
+ style="stop-color:#ed7b00;stop-opacity:1;"
+ offset="0"
+ id="stop47132" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop47134" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23178"
+ id="linearGradient52027"
+ gradientUnits="userSpaceOnUse"
+ x1="329.28757"
+ y1="244.97151"
+ x2="339.84518"
+ y2="254.18553" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15436"
+ gradientUnits="userSpaceOnUse"
+ x1="319.75095"
+ y1="234.63918"
+ x2="333.94208"
+ y2="248.68198" />
+ <linearGradient
+ id="linearGradient32842">
+ <stop
+ style="stop-color:#183e75;stop-opacity:1;"
+ offset="0"
+ id="stop32844" />
+ <stop
+ style="stop-color:#1d3f71;stop-opacity:0;"
+ offset="1"
+ id="stop32846" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient13900"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.2541045,-1.3755453,0.900369,1.4754358,-3699.4512,2858.7)"
+ cx="2357.1072"
+ cy="826.77924"
+ fx="2357.1072"
+ fy="826.77924"
+ r="6.1896501" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40983"
+ id="linearGradient38692"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(2226.9963,823)"
+ x1="130.70599"
+ y1="18.44199"
+ x2="130.70599"
+ y2="21.94199" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15717"
+ gradientUnits="userSpaceOnUse"
+ x1="328.38852"
+ y1="33.505165"
+ x2="331.44778"
+ y2="36.739578" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15715"
+ gradientUnits="userSpaceOnUse"
+ x1="320.2735"
+ y1="25.109356"
+ x2="332.41409"
+ y2="37.468754" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15713"
+ gradientUnits="userSpaceOnUse"
+ x1="329.18762"
+ y1="34.005215"
+ x2="331.44778"
+ y2="36.739578" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15711"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(2.011921e-5,12.000013)"
+ x1="326.483"
+ y1="31.446384"
+ x2="337.3125"
+ y2="41.875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15709"
+ gradientUnits="userSpaceOnUse"
+ x1="332.49747"
+ y1="38.166924"
+ x2="326.41843"
+ y2="31.22842" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15707"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(2.011921e-5,12.000013)"
+ x1="323.37836"
+ y1="30.3883"
+ x2="343.5636"
+ y2="53.758793" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15646"
+ gradientUnits="userSpaceOnUse"
+ x1="279.00009"
+ y1="-16.62501"
+ x2="291.93054"
+ y2="-6.3206272" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15644"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.000006,0,0,1,258.9997,-253)"
+ x1="25.437477"
+ y1="238.54002"
+ x2="51.01355"
+ y2="263.79816" />
+ <linearGradient
+ id="linearGradient20973">
+ <stop
+ id="stop20975"
+ offset="0"
+ style="stop-color:#15ff00;stop-opacity:1;" />
+ <stop
+ id="stop20977"
+ offset="1"
+ style="stop-color:#15ff00;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient20962">
+ <stop
+ style="stop-color:#00a8ff;stop-opacity:1;"
+ offset="0"
+ id="stop20965" />
+ <stop
+ style="stop-color:#00a8ff;stop-opacity:0;"
+ offset="1"
+ id="stop20967" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient20036">
+ <stop
+ style="stop-color:#ffb55e;stop-opacity:1;"
+ offset="0"
+ id="stop20038" />
+ <stop
+ style="stop-color:#ff8400;stop-opacity:0;"
+ offset="1"
+ id="stop20040" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15574"
+ gradientUnits="userSpaceOnUse"
+ x1="197.63152"
+ y1="169.14206"
+ x2="190.41687"
+ y2="160.02296" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15358"
+ gradientUnits="userSpaceOnUse"
+ x1="47.655102"
+ y1="93.805557"
+ x2="59.057678"
+ y2="105.27895"
+ gradientTransform="matrix(1.1000194,0,0,1.0998287,-4.6508478,-9.2334126)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15356"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9995967,0,0,1.0002103,-78.949724,-0.02739749)"
+ x1="109.04134"
+ y1="75.666725"
+ x2="135.45256"
+ y2="103.11092" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15362"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient15360"
+ gradientUnits="userSpaceOnUse"
+ x1="124.40742"
+ y1="111.98244"
+ x2="135.36497"
+ y2="120.87388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient21531"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2859754,0,0,1,39.669142,20)"
+ x1="348.06064"
+ y1="220.55545"
+ x2="363.71661"
+ y2="239.94608" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient14517"
+ gradientUnits="userSpaceOnUse"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="18.01141"
+ y2="84.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient14511"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="3.3959732"
+ y1="216.62332"
+ x2="35.029804"
+ y2="248.37102" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient16069"
+ gradientUnits="userSpaceOnUse"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="17.011419"
+ y2="82.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient16067"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2859754,0,0,1,-440.36032,-147)"
+ x1="348.06064"
+ y1="220.55545"
+ x2="363.71661"
+ y2="239.94608" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient16063"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="6.9917974"
+ y1="219.61856"
+ x2="35.029804"
+ y2="248.37102" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient16154"
+ gradientUnits="userSpaceOnUse"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="18.51141"
+ y2="85.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient16150"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="3.8504581"
+ y1="217.4549"
+ x2="33.15686"
+ y2="247.71701" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15734"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8520698,0,0,0.7746114,324.58589,47.486124)"
+ x1="9.5404434"
+ y1="223.47467"
+ x2="35.029804"
+ y2="248.37102" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient16174"
+ gradientUnits="userSpaceOnUse"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="18.51141"
+ y2="85.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient16170"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="2.911078"
+ y1="217.3624"
+ x2="33.15686"
+ y2="247.71701" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15736"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8520698,0,0,0.7746114,324.58589,47.486124)"
+ x1="9.5404434"
+ y1="223.47467"
+ x2="35.029804"
+ y2="248.37102" />
+ <linearGradient
+ id="linearGradient13998">
+ <stop
+ id="stop14000"
+ offset="0"
+ style="stop-color:#f57d07;stop-opacity:1;" />
+ <stop
+ id="stop14002"
+ offset="1"
+ style="stop-color:white;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15705"
+ gradientUnits="userSpaceOnUse"
+ x1="148.71947"
+ y1="166.53206"
+ x2="147"
+ y2="165" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15703"
+ gradientUnits="userSpaceOnUse"
+ x1="146.80022"
+ y1="158.34668"
+ x2="150.08357"
+ y2="162.03282" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15701"
+ gradientUnits="userSpaceOnUse"
+ x1="148.71947"
+ y1="166.53206"
+ x2="147"
+ y2="165" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15699"
+ gradientUnits="userSpaceOnUse"
+ x1="122.84515"
+ y1="126.83902"
+ x2="149.88129"
+ y2="164.94562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15742"
+ gradientUnits="userSpaceOnUse"
+ x1="392.0101"
+ y1="224.99998"
+ x2="392.0101"
+ y2="249.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15721"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(19.97577,-6.0080883)"
+ x1="227.57907"
+ y1="118.47696"
+ x2="235"
+ y2="118.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15719"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(19.97577,-6.0080883)"
+ x1="222.4996"
+ y1="110.37873"
+ x2="233.08319"
+ y2="121" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15723"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-6.0080883)"
+ x1="230.95012"
+ y1="100.89436"
+ x2="230.74091"
+ y2="124.09359" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15778"
+ gradientUnits="userSpaceOnUse"
+ x1="126.37006"
+ y1="112.31642"
+ x2="135.54141"
+ y2="122.0597" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient15780"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15776"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,10.767079)"
+ x1="132.35471"
+ y1="246.32236"
+ x2="129.81586"
+ y2="243.70523" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15774"
+ gradientUnits="userSpaceOnUse"
+ x1="103.53399"
+ y1="88.301094"
+ x2="136.3542"
+ y2="123.17216" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15450"
+ gradientUnits="userSpaceOnUse"
+ x1="126.37006"
+ y1="112.31642"
+ x2="144.22272"
+ y2="129.82761" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient15452"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient15448"
+ gradientUnits="userSpaceOnUse"
+ x1="132.12782"
+ y1="246.32236"
+ x2="129.24866"
+ y2="243.31177" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15446"
+ gradientUnits="userSpaceOnUse"
+ x1="87.969383"
+ y1="69.87941"
+ x2="135.40274"
+ y2="121.19196" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15124"
+ gradientUnits="userSpaceOnUse"
+ x1="328.38852"
+ y1="33.505165"
+ x2="331.44778"
+ y2="36.739578" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30208"
+ id="linearGradient15122"
+ gradientUnits="userSpaceOnUse"
+ x1="328.95557"
+ y1="33.94022"
+ x2="331.74063"
+ y2="37.044456" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient16025"
+ gradientUnits="userSpaceOnUse"
+ x1="192.11751"
+ y1="122.12527"
+ x2="184.43379"
+ y2="112.34031" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15580"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.395521,0,0,-0.3955,275.223,171.0515)"
+ x1="213.51967"
+ y1="121.417"
+ x2="204.05295"
+ y2="111.7235" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15578"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.607961,0,0,0.607967,64.49194,51.63899)"
+ x1="213.53587"
+ y1="122.66508"
+ x2="203.33264"
+ y2="112.67535" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15748"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,-241.7085,428.4841)"
+ x1="349.04059"
+ y1="143.70836"
+ x2="336.72485"
+ y2="117.00745" />
+ <linearGradient
+ id="linearGradient10585">
+ <stop
+ id="stop10587"
+ offset="0.0000000"
+ style="stop-color:#d7d7d7;stop-opacity:1.0000000;" />
+ <stop
+ id="stop10595"
+ offset="1.0000000"
+ style="stop-color:#000000;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4138">
+ <stop
+ style="stop-color:#6c432f;stop-opacity:1;"
+ offset="0"
+ id="stop4140" />
+ <stop
+ style="stop-color:#c0966d;stop-opacity:1;"
+ offset="1"
+ id="stop4142" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient31320">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop31322" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop31324" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient12678">
+ <stop
+ id="stop12680"
+ offset="0"
+ style="stop-color:#d40000;stop-opacity:1" />
+ <stop
+ id="stop12682"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient13991"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(1.691866,0.00341)"
+ x1="86.452194"
+ y1="101.22832"
+ x2="110.48556"
+ y2="81.14637" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient13520"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(1.401389,-3.2412)"
+ x1="130.59862"
+ y1="121.2412"
+ x2="142.29109"
+ y2="133.53448" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23215"
+ x1="147.07098"
+ y1="134.18185"
+ x2="129.67148"
+ y2="115.54105"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient23178">
+ <stop
+ style="stop-color:#ff992b;stop-opacity:1;"
+ offset="0"
+ id="stop23180" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop23182" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient13973">
+ <stop
+ style="stop-color:#3c4c18;stop-opacity:1;"
+ offset="0"
+ id="stop13975" />
+ <stop
+ style="stop-color:#9aff31;stop-opacity:0;"
+ offset="1"
+ id="stop13977" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient13938">
+ <stop
+ id="stop13940"
+ offset="0"
+ style="stop-color:#6e0c00;stop-opacity:1;" />
+ <stop
+ id="stop13942"
+ offset="1"
+ style="stop-color:#ee3800;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient14232">
+ <stop
+ style="stop-color:#fff32a;stop-opacity:1;"
+ offset="0"
+ id="stop14234" />
+ <stop
+ style="stop-color:#fff551;stop-opacity:0;"
+ offset="1"
+ id="stop14236" />
+ </linearGradient>
+ <filter
+ inkscape:collect="always"
+ id="filter13996"
+ x="-0.23644176"
+ width="1.4728835"
+ y="-0.24368355"
+ height="1.4873672"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.29550651"
+ id="feGaussianBlur13998" />
+ </filter>
+ <linearGradient
+ id="linearGradient14418">
+ <stop
+ id="stop14420"
+ offset="0"
+ style="stop-color:#fa2509;stop-opacity:1;" />
+ <stop
+ id="stop14422"
+ offset="1"
+ style="stop-color:#fa2509;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient14935"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-26,2.9206276e-6)"
+ x1="474"
+ y1="73.999992"
+ x2="477.25"
+ y2="77.499992" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient14841"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-6,1.4603138e-6)"
+ x1="474.84375"
+ y1="75"
+ x2="477.5"
+ y2="77.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient18852"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-22)"
+ x1="148.15451"
+ y1="-216.25"
+ x2="157.91019"
+ y2="-216.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient18850"
+ gradientUnits="userSpaceOnUse"
+ x1="107.15463"
+ y1="-227.83138"
+ x2="105.81714"
+ y2="-219.8996" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient18848"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(20.000285,-20.002166)"
+ x1="123.36729"
+ y1="-219.24783"
+ x2="136.51436"
+ y2="-217.99782" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient18845"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(20.000285,-20.002166)"
+ x1="135.30351"
+ y1="-219.54408"
+ x2="123.63815"
+ y2="-219.49783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient18843"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-22)"
+ x1="157.97339"
+ y1="-215.99998"
+ x2="146.36111"
+ y2="-215.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient18901"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(279.04534,461.00001)"
+ x1="151"
+ y1="-234"
+ x2="149.95467"
+ y2="-239.14549" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient18904"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(280.04419,461)"
+ x1="151"
+ y1="-234"
+ x2="150.25"
+ y2="-236.85815" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient18898"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(280.99885,461)"
+ x1="150.11926"
+ y1="-235.21587"
+ x2="145.20955"
+ y2="-241.85452" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient18896"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(280,461)"
+ x1="150.95467"
+ y1="-234.00002"
+ x2="147.41411"
+ y2="-239.28557" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient17819"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(280,459)"
+ x1="150.95467"
+ y1="-234.00002"
+ x2="147.41411"
+ y2="-239.28557" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient17817"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(280,461)"
+ x1="150.95467"
+ y1="-234.00002"
+ x2="147.41411"
+ y2="-239.28557" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient17535"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-22)"
+ x1="148.15451"
+ y1="-216.25"
+ x2="157.91019"
+ y2="-216.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient17533"
+ gradientUnits="userSpaceOnUse"
+ x1="107.15463"
+ y1="-227.83138"
+ x2="105.81714"
+ y2="-219.8996" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient17531"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(20.000285,-20.002166)"
+ x1="123.36729"
+ y1="-219.24783"
+ x2="136.51436"
+ y2="-217.99782" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient17529"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(20.000285,-20.002166)"
+ x1="135.30351"
+ y1="-219.54408"
+ x2="123.63815"
+ y2="-219.49783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient17527"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-22)"
+ x1="157.97339"
+ y1="-215.99998"
+ x2="146.36111"
+ y2="-215.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient18207">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop18209" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1"
+ id="stop18211" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18207"
+ id="linearGradient18213"
+ x1="481.46063"
+ y1="219"
+ x2="519.44189"
+ y2="218.48816"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient17506"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-22)"
+ x1="148.15451"
+ y1="-216.25"
+ x2="157.91019"
+ y2="-216.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient17504"
+ gradientUnits="userSpaceOnUse"
+ x1="107.15463"
+ y1="-227.83138"
+ x2="105.81714"
+ y2="-219.8996" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient17502"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(20.000285,-20.002166)"
+ x1="123.36729"
+ y1="-219.24783"
+ x2="136.51436"
+ y2="-217.99782" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient17500"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(20.000285,-20.002166)"
+ x1="135.30351"
+ y1="-219.54408"
+ x2="123.63815"
+ y2="-219.49783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient17498"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-22)"
+ x1="157.97339"
+ y1="-215.99998"
+ x2="146.36111"
+ y2="-215.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient18670"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2078427,0,0,1.0516432,-357.40769,69.427229)"
+ x1="362.28571"
+ y1="-45.098213"
+ x2="352.46426"
+ y2="-54.124699" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask18666">
+ <rect
+ y="6"
+ x="62.921577"
+ height="14.000001"
+ width="15.098035"
+ id="rect18668"
+ style="fill:url(#linearGradient18670);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient15592"
+ gradientUnits="userSpaceOnUse"
+ x1="127.50285"
+ y1="114.74636"
+ x2="132.35237"
+ y2="118.69846" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient15590"
+ gradientUnits="userSpaceOnUse"
+ x1="127.50285"
+ y1="114.74636"
+ x2="135.54628"
+ y2="120.58403" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient15596"
+ gradientUnits="userSpaceOnUse"
+ x1="124.52369"
+ y1="112.22441"
+ x2="131.10667"
+ y2="118.10129" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient15594"
+ gradientUnits="userSpaceOnUse"
+ x1="127.50285"
+ y1="114.74636"
+ x2="134.62978"
+ y2="120.14633" />
+ <filter
+ inkscape:collect="always"
+ x="-0.71999419"
+ width="2.4399884"
+ y="-0.72000581"
+ height="2.4400115"
+ id="filter31351"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.83077614"
+ id="feGaussianBlur31353" />
+ </filter>
+ <linearGradient
+ id="linearGradient14219">
+ <stop
+ id="stop14221"
+ offset="0"
+ style="stop-color:#ff8605;stop-opacity:1;" />
+ <stop
+ id="stop14223"
+ offset="1"
+ style="stop-color:#9c6700;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient31456">
+ <stop
+ style="stop-color:#2b1600;stop-opacity:1;"
+ offset="0"
+ id="stop31458" />
+ <stop
+ style="stop-color:#6e3900;stop-opacity:0;"
+ offset="1"
+ id="stop31460" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient19425">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop19427" />
+ <stop
+ id="stop19431"
+ offset="0.63109845"
+ style="stop-color:#fffffe;stop-opacity:0.65789473;" />
+ <stop
+ style="stop-color:#fffffe;stop-opacity:0.0000000;"
+ offset="1.0000000"
+ id="stop19429" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient30208">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop30210" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop30212" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15782"
+ gradientUnits="userSpaceOnUse"
+ x1="125.19086"
+ y1="125.66204"
+ x2="132.98256"
+ y2="118" />
+ <linearGradient
+ id="linearGradient9030">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop9032" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop9034" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37542">
+ <stop
+ id="stop37544"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient30124">
+ <stop
+ style="stop-color:#1d4a8c;stop-opacity:1;"
+ offset="0"
+ id="stop30126" />
+ <stop
+ style="stop-color:#c1d4f2;stop-opacity:1;"
+ offset="1"
+ id="stop30128" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15893">
+ <stop
+ style="stop-color:#2968c3;stop-opacity:1;"
+ offset="0"
+ id="stop15895" />
+ <stop
+ id="stop15897"
+ offset="0.37679368"
+ style="stop-color:#b5ccf0;stop-opacity:1;" />
+ <stop
+ style="stop-color:#b5ccf0;stop-opacity:1;"
+ offset="0.59786767"
+ id="stop15899" />
+ <stop
+ style="stop-color:#2968c3;stop-opacity:1;"
+ offset="1"
+ id="stop15901" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient24000">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop24002" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop24004" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient32998">
+ <stop
+ style="stop-color:#2968c3;stop-opacity:1;"
+ offset="0"
+ id="stop33000" />
+ <stop
+ style="stop-color:#c1d7f8;stop-opacity:1;"
+ offset="1"
+ id="stop33002" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient21364"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,-32.5,115.5045)"
+ x1="261.83936"
+ y1="11.593864"
+ x2="277.86761"
+ y2="29.392145" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient21366"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,-32.9445,114.0045)"
+ x1="272.05627"
+ y1="24.537012"
+ x2="283.42514"
+ y2="37.115723" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient21368"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(124,-102.00001)"
+ x1="85.1875"
+ y1="239.125"
+ x2="92.8125"
+ y2="245.625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient21370"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,-32.5,115.5045)"
+ x1="261.83936"
+ y1="11.593864"
+ x2="277.86761"
+ y2="29.392145" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient21372"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,-32.9445,114.0045)"
+ x1="272.05627"
+ y1="24.537012"
+ x2="283.42514"
+ y2="37.115723" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient21374"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(124,-102.00001)"
+ x1="85.1875"
+ y1="239.125"
+ x2="92.8125"
+ y2="245.625" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="radialGradient21517"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.891843,0,0,0.909224,-173.99085,171.21624)"
+ cx="350.5"
+ cy="14.5"
+ fx="350.5"
+ fy="14.5"
+ r="6.9000001" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient21641"
+ gradientUnits="userSpaceOnUse"
+ x1="127.50285"
+ y1="114.74636"
+ x2="133.62564"
+ y2="120.24665" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient21643"
+ gradientUnits="userSpaceOnUse"
+ x1="126.15096"
+ y1="113.21745"
+ x2="132"
+ y2="118" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient20796"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(159.9998,-41.00751)"
+ x1="261.44702"
+ y1="234.6606"
+ x2="274.30609"
+ y2="247.73561" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient20798"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(199.9999,105.99249)"
+ x1="235.46884"
+ y1="103"
+ x2="228.71886"
+ y2="94.53125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient21862"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="3.2344713"
+ y1="215.76874"
+ x2="33.15686"
+ y2="247.71701" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient21864"
+ gradientUnits="userSpaceOnUse"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="19.011419"
+ y2="86" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient21902"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="3.3268692"
+ y1="215.35608"
+ x2="33.15686"
+ y2="247.71701" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient21904"
+ gradientUnits="userSpaceOnUse"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="18.51141"
+ y2="85.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient31646"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.000006,0,0,1,258.9997,-237)"
+ x1="24.374985"
+ y1="238.33629"
+ x2="55.384842"
+ y2="269.1373" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31648"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,16)"
+ x1="278.55817"
+ y1="-16.978563"
+ x2="291.577"
+ y2="-5.8786855" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20036"
+ id="radialGradient31650"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.816279,0,-3.646264e-6,0.779872,56.32029,28.34496)"
+ cx="306.55292"
+ cy="11.818644"
+ fx="306.55292"
+ fy="11.818644"
+ r="4.25" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14418"
+ id="radialGradient31652"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.580596,1.138426,-0.692447,0.961382,-175.3891,-329.6844)"
+ cx="312.80765"
+ cy="10.620173"
+ fx="312.80765"
+ fy="10.620173"
+ r="4.25" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20962"
+ id="radialGradient31654"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.48445,-0.00657397,0.00734631,1.660903,-154.1629,19.305572)"
+ cx="313.74268"
+ cy="15.619254"
+ fx="313.74268"
+ fy="15.619254"
+ r="4.25" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20973"
+ id="radialGradient31656"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.756245,0,-3.378096e-6,0.722516,72.63115,31.07857)"
+ cx="309.0571"
+ cy="15.518281"
+ fx="309.0571"
+ fy="15.518281"
+ r="4.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient31664"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8579582,0,0,0.9285714,7.397998,-211.96428)"
+ x1="-6.3249049"
+ y1="205.0083"
+ x2="32.351238"
+ y2="248.75177" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient31666"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.9569715,-1,0,259,351.18743)"
+ x1="347.6467"
+ y1="216.75188"
+ x2="345.98633"
+ y2="243.92201" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31668"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166667,0,0,0.9166667,24.364541,-55.041665)"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="18.01141"
+ y2="84.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient31672"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.9297203,-1.2117965,0,305.73028,342.22894)"
+ x1="346.15555"
+ y1="218.2382"
+ x2="346.58698"
+ y2="238.44429" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31694"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166695,0,0,0.9203753,-10.025729,345.78566)"
+ x1="80.60067"
+ y1="108.47212"
+ x2="68.0271"
+ y2="94.239906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13938"
+ id="linearGradient31696"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-15.983875,338)"
+ x1="70.55275"
+ y1="97.5"
+ x2="79.355118"
+ y2="107.18619" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31698"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9998599,0,0,0.9960071,-15.972985,338.41149)"
+ x1="64.998215"
+ y1="90.951675"
+ x2="86.00116"
+ y2="112.03586" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient31932"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,105.5221,92.482413)"
+ x1="257.0376"
+ y1="10.838325"
+ x2="277.61203"
+ y2="31.019331" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient31934"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7827973,0,0,0.9989462,77.082208,42.08484)"
+ x1="332.03717"
+ y1="68.624634"
+ x2="346.08932"
+ y2="83.002625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31936"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(262,-125)"
+ x1="79.329903"
+ y1="236"
+ x2="92.8125"
+ y2="245.625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24000"
+ id="linearGradient33666"
+ gradientUnits="userSpaceOnUse"
+ x1="124.14184"
+ y1="126.23546"
+ x2="132"
+ y2="118" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient33668"
+ gradientUnits="userSpaceOnUse"
+ x1="125.45158"
+ y1="125.94608"
+ x2="133.53401"
+ y2="116.55647" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient33670"
+ gradientUnits="userSpaceOnUse"
+ x1="142.97318"
+ y1="107.64013"
+ x2="130.82327"
+ y2="119.554" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient33681"
+ gradientUnits="userSpaceOnUse"
+ x1="139.93341"
+ y1="110.56118"
+ x2="132"
+ y2="118.66972" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient32842"
+ id="linearGradient33700"
+ gradientUnits="userSpaceOnUse"
+ x1="149.55772"
+ y1="98.630066"
+ x2="123.9021"
+ y2="127.60542" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient10540"
+ gradientUnits="userSpaceOnUse"
+ x1="130.95198"
+ y1="117.09563"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient11333"
+ gradientUnits="userSpaceOnUse"
+ x1="119.1647"
+ y1="106.08605"
+ x2="133.01006"
+ y2="119.79803" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient28057"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-425,393.99999)"
+ x1="225.6198"
+ y1="5.7625732"
+ x2="236.47855"
+ y2="14.103563" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30208"
+ id="linearGradient28077"
+ x1="306.26187"
+ y1="272"
+ x2="307"
+ y2="263.55374"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient28474"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,10)"
+ x1="431.05026"
+ y1="121.42467"
+ x2="446.26407"
+ y2="110.49417" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient28528"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,10)"
+ x1="442.69827"
+ y1="107.56771"
+ x2="450.27414"
+ y2="122.95798" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient28530"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-474,158.25)"
+ x1="437.57828"
+ y1="104.34499"
+ x2="447.96875"
+ y2="117.90625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient28532"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,10)"
+ x1="-38.103703"
+ y1="266.11719"
+ x2="-20.826464"
+ y2="253.23859" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient10982"
+ x1="207.04637"
+ y1="182.09375"
+ x2="213.7883"
+ y2="182.52524"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient10984"
+ x1="212.04637"
+ y1="182.09375"
+ x2="222.35799"
+ y2="182.77524"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient11762"
+ x1="371.98389"
+ y1="203"
+ x2="376.48389"
+ y2="203"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient11764"
+ x1="366.98389"
+ y1="203"
+ x2="370.98389"
+ y2="202.75"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient11766"
+ x1="391.62881"
+ y1="243.48854"
+ x2="386.13718"
+ y2="244.68996"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient12427"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.050372,0,0,1.050372,-3.551238,-0.730396)"
+ cx="70.5"
+ cy="14.5"
+ fx="70.5"
+ fy="14.5"
+ r="1.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14219"
+ id="radialGradient12429"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5007214,0.3131662,-0.3623683,0.5793905,300.02235,-93.056748)"
+ cx="70.470596"
+ cy="14.649424"
+ fx="70.470596"
+ fy="14.649424"
+ r="5.5192375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16359"
+ id="linearGradient12602"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,456.04574,-116.51416)"
+ x1="88.079262"
+ y1="66.110847"
+ x2="95.954262"
+ y2="58.272621" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31456"
+ id="linearGradient12114"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1438.0001,-418)"
+ x1="1663.8125"
+ y1="722"
+ x2="1661.8125"
+ y2="726.37006" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19425"
+ id="radialGradient12116"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.1378252,-0.2988982,2.5269117,1.1651875,-1830.2675,-33.64056)"
+ cx="1662.2664"
+ cy="722.19189"
+ fx="1662.2664"
+ fy="722.19189"
+ r="5.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient12118"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,-1397.7474,-388.72044)"
+ x1="1984.5453"
+ y1="828.21777"
+ x2="1978.11"
+ y2="829.35315" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30208"
+ id="linearGradient12213"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1297,-948)"
+ x1="1663.8125"
+ y1="722"
+ x2="1661.8125"
+ y2="726.37006" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19425"
+ id="radialGradient12215"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.1378252,-0.2988982,2.5269117,1.1651875,-1689.2674,-563.64056)"
+ cx="1662.2664"
+ cy="722.19189"
+ fx="1662.2664"
+ fy="722.19189"
+ r="5.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient12217"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,-1256.7473,-918.72044)"
+ x1="1984.3658"
+ y1="827.77124"
+ x2="1979.2772"
+ y2="827.32849" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient12305"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2000005,0,0,1.1997014,-125.70008,-191.68873)"
+ x1="257.24991"
+ y1="147.38998"
+ x2="262.24991"
+ y2="152.46707" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient12307"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2000005,0,0,1.1997014,-125.70008,-191.68873)"
+ x1="258.08322"
+ y1="147.87068"
+ x2="264.16571"
+ y2="153.8233" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient13046"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(360,-161.99999)"
+ x1="-80"
+ y1="151"
+ x2="-80"
+ y2="152.24998" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask13041">
+ <rect
+ style="fill:url(#linearGradient13046);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect13043"
+ width="7"
+ height="8"
+ x="276"
+ y="-12" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient13056"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(360,-145.93749)"
+ x1="-80"
+ y1="151"
+ x2="-80"
+ y2="152.24998" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask13052">
+ <rect
+ y="4.0625"
+ x="276"
+ height="8"
+ width="7"
+ id="rect13054"
+ style="fill:url(#linearGradient13056);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="scale(1,-1)" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient14167"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-636.98388,52.01562)"
+ x1="443.86667"
+ y1="133.98936"
+ x2="451.98389"
+ y2="143.58749" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4138"
+ id="linearGradient14169"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-635.98388,53.01562)"
+ x1="456.03769"
+ y1="135.76678"
+ x2="453.61005"
+ y2="133.00301" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient14171"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-636.98388,52.01562)"
+ x1="449.14645"
+ y1="136.18045"
+ x2="453.24457"
+ y2="138.7879" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4138"
+ id="linearGradient14173"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-635.98388,53.01562)"
+ x1="456.03769"
+ y1="135.76678"
+ x2="454.31345"
+ y2="133.62801" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient13112"
+ gradientUnits="userSpaceOnUse"
+ x1="133.42287"
+ y1="120.62622"
+ x2="126.67323"
+ y2="113.20281" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient13114"
+ gradientUnits="userSpaceOnUse"
+ x1="120.77391"
+ y1="106.19939"
+ x2="144.64095"
+ y2="129.62753" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient16027"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8289081,0,0,2.1560411,236.27148,-864.45588)"
+ x1="212"
+ y1="435.59741"
+ x2="211.99998"
+ y2="435.32159" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23647"
+ id="linearGradient16031"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1035181,0,0,1,158.18497,-359.77344)"
+ x1="229.6875"
+ y1="440.51562"
+ x2="238.53125"
+ y2="440.57812" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23390"
+ id="radialGradient16034"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.8126517,-0.04317018,0.04642643,1.9485655,-18.817545,-774.28453)"
+ cx="224.32494"
+ cy="441.84744"
+ fx="224.32494"
+ fy="441.84744"
+ r="6.7191267" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30208"
+ id="linearGradient16036"
+ gradientUnits="userSpaceOnUse"
+ x1="211.99998"
+ y1="435.7319"
+ x2="211.99998"
+ y2="436.07974"
+ gradientTransform="matrix(0.9803611,0,0,2.1560411,204.16345,-864.45588)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23647"
+ id="linearGradient16039"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(182,-359.75)"
+ x1="221.96414"
+ y1="439.75"
+ x2="238.87605"
+ y2="448.88205" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient17337"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.0041772,0,0,0.9688607,-81.584854,117.13687)"
+ x1="-4.9152389"
+ y1="252.69086"
+ x2="-45.689278"
+ y2="252.63284" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient17339"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9993234,0,0,1.0050357,-171.92846,305.72314)"
+ x1="107.96875"
+ y1="53.875"
+ x2="117"
+ y2="60.125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient17656"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0008786,0,0,1.081555,-21.021535,-187.45087)"
+ x1="-12.839478"
+ y1="201"
+ x2="44.522621"
+ y2="256.70349" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient17658"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.099576,0,0,1.0999923,190.46996,204.85062)"
+ x1="9.6310225"
+ y1="76"
+ x2="15"
+ y2="81" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient17712"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.0041772,0,0,0.9688607,370.43125,-83.863716)"
+ x1="-5.6700387"
+ y1="250.87607"
+ x2="-46.452946"
+ y2="251.42462" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient17714"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9993234,0,0,1.0050357,280.08766,104.72255)"
+ x1="102.61966"
+ y1="50.742527"
+ x2="117"
+ y2="60.125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient12655"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8193413,0,0,0.8193419,-388.72692,-564.02452)"
+ x1="150.4086"
+ y1="104.61366"
+ x2="151.40744"
+ y2="105.64391" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30208"
+ id="linearGradient12658"
+ gradientUnits="userSpaceOnUse"
+ x1="150.4086"
+ y1="104.61366"
+ x2="151.40744"
+ y2="105.64391"
+ gradientTransform="matrix(0.8193413,0,0,0.8193419,141.28585,391.96271)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30208"
+ id="linearGradient13511"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8193413,0,0,0.8193419,141.28585,391.96271)"
+ x1="150.4086"
+ y1="104.61366"
+ x2="151.40744"
+ y2="105.64391" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient13513"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8193413,0,0,0.8193419,-388.72692,-564.02452)"
+ x1="150.4086"
+ y1="104.61366"
+ x2="151.40744"
+ y2="105.64391" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30208"
+ id="linearGradient13527"
+ gradientUnits="userSpaceOnUse"
+ x1="328.95557"
+ y1="33.94022"
+ x2="331.74063"
+ y2="37.044456" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient13529"
+ gradientUnits="userSpaceOnUse"
+ x1="328.38852"
+ y1="33.505165"
+ x2="331.44778"
+ y2="36.739578" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient14568"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(68.016116,127.00002)"
+ x1="97.983887"
+ y1="127.99998"
+ x2="88.983887"
+ y2="115.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient14570"
+ gradientUnits="userSpaceOnUse"
+ x1="94.485573"
+ y1="122.13319"
+ x2="89.207298"
+ y2="125.83332" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient14572"
+ gradientUnits="userSpaceOnUse"
+ x1="88.560204"
+ y1="127.88263"
+ x2="94.011101"
+ y2="123.83599" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient47130"
+ id="linearGradient13699"
+ x1="-162.89217"
+ y1="245"
+ x2="-174.18907"
+ y2="224.99274"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13998"
+ id="linearGradient26282"
+ gradientUnits="userSpaceOnUse"
+ x1="13.5"
+ y1="57.827747"
+ x2="11.472005"
+ y2="53.875874" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13998"
+ id="linearGradient26284"
+ gradientUnits="userSpaceOnUse"
+ x1="-18.600719"
+ y1="501.96539"
+ x2="-26.642899"
+ y2="487.60382" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient26286"
+ gradientUnits="userSpaceOnUse"
+ x1="15.027407"
+ y1="60.637787"
+ x2="13.5"
+ y2="57.750687" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient26288"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.03018343,0.1408617)"
+ x1="-32.067383"
+ y1="490.70178"
+ x2="-22.25"
+ y2="500" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient14198"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(218.01612,129)"
+ x1="87.03125"
+ y1="241"
+ x2="92.8125"
+ y2="245.625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient14204"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,61.53822,346.48241)"
+ x1="246.89435"
+ y1="-4.4418921"
+ x2="277.68143"
+ y2="30.743095" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15195"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166695,0,0,0.9203753,-10.025729,345.78566)"
+ x1="80.60067"
+ y1="108.47212"
+ x2="68.0271"
+ y2="94.239906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient71814"
+ id="linearGradient15209"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-15.983875,338)"
+ x1="70.55275"
+ y1="97.5"
+ x2="79.355118"
+ y2="107.18619" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15211"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9998599,0,0,0.9960071,-15.972985,338.41149)"
+ x1="61.465469"
+ y1="88.058716"
+ x2="86.00116"
+ y2="112.03586" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15363"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9999519,0,0,0.9998051,-33.993941,254.01926)"
+ x1="101.21339"
+ y1="68.783279"
+ x2="135.45256"
+ y2="103.11092" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15365"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1004102,0,0,1.0993832,40.331334,244.81698)"
+ x1="47.655102"
+ y1="93.805557"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10585"
+ id="linearGradient15367"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.032977,0,0,1,128.82015,107.77516)"
+ x1="12.330792"
+ y1="246.97107"
+ x2="41.654194"
+ y2="247.3784" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18207"
+ id="linearGradient15383"
+ gradientUnits="userSpaceOnUse"
+ x1="-132.24858"
+ y1="313.87549"
+ x2="-171.01999"
+ y2="223.69542" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient14377"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(1.691866,0.00341)"
+ x1="86.452194"
+ y1="101.22832"
+ x2="110.48556"
+ y2="81.14637" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient16638"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(42,0)"
+ x1="108"
+ y1="500"
+ x2="54.8125"
+ y2="500" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15809"
+ id="linearGradient16640"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(42,0)"
+ x1="85.874489"
+ y1="501.74075"
+ x2="26.561054"
+ y2="498.48148" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient16642"
+ gradientUnits="userSpaceOnUse"
+ x1="80.768944"
+ y1="504.67188"
+ x2="76.885078"
+ y2="501.58331" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient16644"
+ gradientUnits="userSpaceOnUse"
+ x1="89.526657"
+ y1="511.42972"
+ x2="78.000008"
+ y2="501.04794" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262"
+ id="radialGradient16646"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3949409,0.3949425,-0.4243709,0.4254619,300.60762,256.85923)"
+ cx="75.95578"
+ cy="492.15359"
+ fx="75.95578"
+ fy="492.15359"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient16648"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.4624192,0,0,1.4467089,-36.975824,-224.99718)"
+ cx="79.959885"
+ cy="503.81497"
+ fx="79.959885"
+ fy="503.81497"
+ r="2.9089756" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262"
+ id="radialGradient16650"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8886193,0.8021825,-0.8051059,0.8972684,411.80247,-8.668512)"
+ cx="74.518959"
+ cy="499.99969"
+ fx="74.518959"
+ fy="499.99969"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient32447"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.054749"
+ cy="499.87418"
+ fx="75.054749"
+ fy="499.87418"
+ r="3.1650217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30231"
+ gradientUnits="userSpaceOnUse"
+ x1="441.48248"
+ y1="105.03784"
+ x2="446.73828"
+ y2="111.74544" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24101"
+ id="linearGradient30233"
+ gradientUnits="userSpaceOnUse"
+ x1="445.37457"
+ y1="112.86145"
+ x2="425.92511"
+ y2="84.928581" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30235"
+ gradientUnits="userSpaceOnUse"
+ x1="440.68439"
+ y1="106.0996"
+ x2="446.00906"
+ y2="110.93529" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30237"
+ gradientUnits="userSpaceOnUse"
+ x1="440.34833"
+ y1="105.74502"
+ x2="445.36435"
+ y2="110.27587" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30239"
+ gradientUnits="userSpaceOnUse"
+ x1="440.7211"
+ y1="104.97093"
+ x2="445.36435"
+ y2="110.27587" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23302"
+ id="linearGradient30241"
+ gradientUnits="userSpaceOnUse"
+ x1="414.99771"
+ y1="-35"
+ x2="414.99771"
+ y2="-36.625011" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24081"
+ id="linearGradient30243"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.004608,0)"
+ x1="416.00461"
+ y1="-34"
+ x2="415.94211"
+ y2="-37.718761" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient30245"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.004608,0)"
+ x1="416.5"
+ y1="-29.933779"
+ x2="416.5"
+ y2="-37.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient30247"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1,0)"
+ x1="416.41162"
+ y1="-34.342831"
+ x2="416.46497"
+ y2="-39.140816" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30249"
+ gradientUnits="userSpaceOnUse"
+ x1="409.00003"
+ y1="-40.99012"
+ x2="413.49658"
+ y2="-34.707108" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30326"
+ gradientUnits="userSpaceOnUse"
+ x1="446.05634"
+ y1="112.72269"
+ x2="436.76331"
+ y2="100.6615" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30328"
+ gradientUnits="userSpaceOnUse"
+ x1="440.03735"
+ y1="103.53646"
+ x2="446.73828"
+ y2="111.74544" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30330"
+ gradientUnits="userSpaceOnUse"
+ x1="447.06949"
+ y1="114.61743"
+ x2="432.36887"
+ y2="94.07222" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30332"
+ gradientUnits="userSpaceOnUse"
+ x1="438.92477"
+ y1="103.46223"
+ x2="446.00906"
+ y2="110.93529" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30334"
+ gradientUnits="userSpaceOnUse"
+ x1="439.0434"
+ y1="104.06953"
+ x2="445.36435"
+ y2="110.27587" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30336"
+ gradientUnits="userSpaceOnUse"
+ x1="439.04333"
+ y1="104.0401"
+ x2="445.36435"
+ y2="110.27587" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30338"
+ gradientUnits="userSpaceOnUse"
+ x1="415.00003"
+ y1="-33.99012"
+ x2="415"
+ y2="-36.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30340"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.004608,0)"
+ x1="415.41223"
+ y1="-31.506163"
+ x2="415.45193"
+ y2="-37.520515" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient30342"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.004608,0)"
+ x1="416.5"
+ y1="-29.933779"
+ x2="416.5"
+ y2="-37.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient30344"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1,0)"
+ x1="416.5"
+ y1="-33.8125"
+ x2="416.46497"
+ y2="-39.140816" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30346"
+ gradientUnits="userSpaceOnUse"
+ x1="409.00003"
+ y1="-40.99012"
+ x2="413.49658"
+ y2="-34.707108" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient30348"
+ gradientUnits="userSpaceOnUse"
+ x1="408.75"
+ y1="-35.483223"
+ x2="408.75"
+ y2="-40.000008" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30394"
+ gradientUnits="userSpaceOnUse"
+ x1="446.05634"
+ y1="112.72269"
+ x2="436.76331"
+ y2="100.6615" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30396"
+ gradientUnits="userSpaceOnUse"
+ x1="440.03735"
+ y1="103.53646"
+ x2="446.73828"
+ y2="111.74544" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30398"
+ gradientUnits="userSpaceOnUse"
+ x1="447.06949"
+ y1="114.61743"
+ x2="432.36887"
+ y2="94.07222" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30400"
+ gradientUnits="userSpaceOnUse"
+ x1="438.92477"
+ y1="103.46223"
+ x2="446.00906"
+ y2="110.93529" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30402"
+ gradientUnits="userSpaceOnUse"
+ x1="439.0434"
+ y1="104.06953"
+ x2="445.36435"
+ y2="110.27587" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30404"
+ gradientUnits="userSpaceOnUse"
+ x1="439.04333"
+ y1="104.0401"
+ x2="445.36435"
+ y2="110.27587" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30406"
+ gradientUnits="userSpaceOnUse"
+ x1="415.00003"
+ y1="-33.99012"
+ x2="415"
+ y2="-36.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30408"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.004608,0)"
+ x1="415.41223"
+ y1="-31.506163"
+ x2="415.45193"
+ y2="-37.520515" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient30410"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.004608,0)"
+ x1="416.5"
+ y1="-29.933779"
+ x2="416.5"
+ y2="-37.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient30412"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1,0)"
+ x1="416.5"
+ y1="-33.8125"
+ x2="416.46497"
+ y2="-39.140816" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30414"
+ gradientUnits="userSpaceOnUse"
+ x1="409.00003"
+ y1="-40.99012"
+ x2="413.49658"
+ y2="-34.707108" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient30416"
+ gradientUnits="userSpaceOnUse"
+ x1="408.75"
+ 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">
+ <path
+ sodipodi:nodetypes="cccc"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:none"
+ d="m -44,358 0,14 14,-14 -14,0 z"
+ id="path17572" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient18682"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8461524,0,0,0.9230835,365.8517,-147.63686)"
+ x1="27.405855"
+ y1="189.20862"
+ x2="35.029804"
+ y2="248.37102" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient18690"
+ gradientUnits="userSpaceOnUse"
+ x1="29.972469"
+ y1="164"
+ x2="29.972469"
+ y2="168"
+ gradientTransform="translate(359.05264,-81.98142)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient18752"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="30.435225"
+ y1="202.99998"
+ x2="30.435225"
+ y2="251.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient18756"
+ gradientUnits="userSpaceOnUse"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="16.733877"
+ y2="88"
+ gradientTransform="matrix(1,0,0,1.2222204,0,-15.888744)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient18779"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6923077,0,0,-0.6923079,29.049874,351.11545)"
+ x1="7.9951181"
+ y1="264.90152"
+ x2="32.267426"
+ y2="237.9342" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient18823"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-122.98388,276)"
+ x1="-55.936718"
+ y1="77.808868"
+ x2="-55.844753"
+ y2="84.217026" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient18831"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5384613,0,0,0.538461,-189.69233,224.07704)"
+ x1="29.142912"
+ y1="161.42842"
+ x2="29.142912"
+ y2="252.42851" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient18841"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.462416,0,0,0.538461,-193.81309,224.07705)"
+ x1="29.871567"
+ y1="153.99983"
+ x2="29.871567"
+ y2="252.4285" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient18846"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.462416,0,0,0.461541,-193.81309,236.42243)"
+ x1="29.871567"
+ y1="174.58366"
+ x2="29.871567"
+ y2="259.08319" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient18854"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2500001,0,0,2.2000001,-102.35484,177)"
+ x1="-55.936718"
+ y1="77.808868"
+ x2="-55.844753"
+ y2="84.217026" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient18858"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.8000001,-122.98388,285.5)"
+ x1="-55.936718"
+ y1="77.808868"
+ x2="-55.844753"
+ y2="84.217026" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient18862"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.0000001,0,0,1.6000003,163.54205,53.499972)"
+ x1="-60.266121"
+ y1="74.0625"
+ x2="-54.766121"
+ y2="84.6875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient32725"
+ gradientUnits="userSpaceOnUse"
+ x1="-88.0625"
+ y1="364"
+ x2="-44.983891"
+ y2="411.9375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32727"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166695,0,0,0.9203753,-117.02574,313.78567)"
+ x1="80.60067"
+ y1="108.47212"
+ x2="68.0271"
+ y2="94.239906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient32729"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6666675,0,0,0.6666633,-101.32265,336.66698)"
+ x1="61.983898"
+ y1="88.999977"
+ x2="89.770271"
+ y2="121.709" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32731"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9998599,0,0,0.9960071,-122.97299,306.4115)"
+ x1="61.465469"
+ y1="88.058716"
+ x2="86.00116"
+ y2="112.03586" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient32749"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.081988,0,0,1.0833333,-123.05997,-52.467545)"
+ x1="326.72092"
+ y1="33.927608"
+ x2="352.03485"
+ y2="60.463093" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient32751"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-15.983875,338)"
+ x1="-46.417774"
+ y1="1.9796312"
+ x2="-21.988398"
+ y2="27" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32753"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0983862,0,0,1.0999999,-128.47957,-53.059225)"
+ x1="324.13901"
+ y1="28.882492"
+ x2="333.96365"
+ y2="39.250004" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient17135"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(18,0)"
+ x1="-51.6875"
+ y1="442.6875"
+ x2="-42.377892"
+ y2="452.20007" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient17177"
+ gradientUnits="userSpaceOnUse"
+ x1="28.322077"
+ y1="160.10768"
+ x2="32.679554"
+ y2="164.34546" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient17179"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-6.8461644e-7,-1.8,1.1087755,0.00352366,-193.46828,187.54551)"
+ cx="4.351675"
+ cy="81.592964"
+ fx="4.351675"
+ fy="81.592964"
+ r="5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18344"
+ id="radialGradient17181"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.5123107,0.9569981,-0.5028837,0.7946898,-131.57281,-236.33663)"
+ cx="244.14325"
+ cy="-14.13948"
+ fx="244.14325"
+ fy="-14.13948"
+ r="3.4000001" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient17214"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="29.352921"
+ y1="199"
+ x2="29.352921"
+ y2="250" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient17216"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2222204,0,-15.888744)"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="16.733877"
+ y2="88" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient17218"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2859748,0,0,1,-272.87621,148)"
+ x1="348.06064"
+ y1="220.55545"
+ x2="363.71661"
+ y2="239.94608" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient17220"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4289612,0,0,1,-326.93899,144.5)"
+ x1="348.06064"
+ y1="220.55545"
+ x2="363.71661"
+ y2="239.94608" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient17222"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="29.352921"
+ y1="199"
+ x2="29.352921"
+ y2="250" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient17224"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2222204,0,-15.888744)"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="16.733877"
+ y2="88" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient17226"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2868892,0,0,1,-644.69395,148)"
+ x1="348.06064"
+ y1="220.55545"
+ x2="363.71661"
+ y2="239.94608" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient17242"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="9.5404434"
+ y1="223.47467"
+ x2="36.247395"
+ y2="249.62102" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient17244"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2222204,0,-15.888744)"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="16.733877"
+ y2="88" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient18712"
+ 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
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient18721"
+ 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"
+ id="linearGradient18728"
+ 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"
+ id="linearGradient18765"
+ 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="#linearGradient34157"
+ id="linearGradient35488"
+ gradientUnits="userSpaceOnUse"
+ x1="270.66064"
+ y1="68.113258"
+ x2="257.38638"
+ y2="81.382545" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35490"
+ gradientUnits="userSpaceOnUse"
+ x1="256.38586"
+ y1="80.515495"
+ x2="262.43726"
+ y2="74.562462" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient35492"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient35494"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient35967"
+ cx="257.35309"
+ cy="79.598709"
+ fx="257.35309"
+ fy="79.598709"
+ r="3.779551"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.656002,0,0,0.656002,88.923481,27.003843)" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath18524">
+ <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.1435655,0,0,1.1436475,512.11415,45.72091)"
+ 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="path18526"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.69954133;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.3473305"
+ inkscape:transform-center-y="-6.3853012" />
+ </clipPath>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask18634">
+ <path
+ sodipodi:nodetypes="ccccscc"
+ style="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"
+ d="m 207,134 0,14 11,0 0,-7.5625 c -1.97252,-0.24738 -3.5,-1.89814 -3.5,-3.9375 0,-0.94675 0.35614,-1.81444 0.90625,-2.5 L 207,134 z"
+ id="path18636" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient18478"
+ gradientUnits="userSpaceOnUse"
+ x1="172.5625"
+ y1="601.5"
+ x2="159.13864"
+ y2="585.28772" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient18480"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-97.983877,565.25)"
+ x1="249.64528"
+ y1="1.5973248"
+ x2="271.98389"
+ y2="35.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35583"
+ gradientUnits="userSpaceOnUse"
+ x1="-0.78523314"
+ y1="-33.408295"
+ x2="4.952816"
+ y2="-27.882322" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35585"
+ gradientUnits="userSpaceOnUse"
+ x1="-0.78523314"
+ y1="-33.408295"
+ x2="3.1666665"
+ y2="-29.550003" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35587"
+ gradientUnits="userSpaceOnUse"
+ x1="-3.5"
+ y1="-35.5"
+ x2="2.6932251"
+ y2="-29.488832" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35589"
+ gradientUnits="userSpaceOnUse"
+ x1="4.9341426"
+ y1="-29.678047"
+ x2="4.8398785e-16"
+ y2="-32.351803" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35591"
+ gradientUnits="userSpaceOnUse"
+ x1="0.5079475"
+ y1="-32.317398"
+ x2="4.2000003"
+ y2="-28.597046" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient35593"
+ gradientUnits="userSpaceOnUse"
+ x1="2.8144052"
+ y1="-28.1"
+ x2="-4.375"
+ y2="-36.441402" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35595"
+ gradientUnits="userSpaceOnUse"
+ x1="-2.7708333"
+ y1="-35.5"
+ x2="1.1666667"
+ y2="-32" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient35740"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707654,0,0,0.707942,-206.46148,-296.13985)"
+ x1="35.597904"
+ y1="158.14117"
+ x2="10.490564"
+ y2="176.41806" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient35742"
+ gradientUnits="userSpaceOnUse"
+ x1="58.060974"
+ y1="-23.721956"
+ x2="40"
+ y2="-35" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35744"
+ gradientUnits="userSpaceOnUse"
+ x1="46.1875"
+ y1="-28.59375"
+ x2="41.099998"
+ y2="-33.59375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient36116"
+ id="linearGradient35746"
+ gradientUnits="userSpaceOnUse"
+ x1="46"
+ y1="-32"
+ x2="43.883884"
+ y2="-33.939339" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35748"
+ gradientUnits="userSpaceOnUse"
+ x1="41"
+ y1="-29"
+ x2="43"
+ y2="-27" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35750"
+ gradientUnits="userSpaceOnUse"
+ x1="48.662914"
+ y1="-27.071922"
+ x2="43.47097"
+ y2="-32.337086" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35752"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(6.3,-4.7)"
+ x1="39.200001"
+ y1="-30.799999"
+ x2="41.200001"
+ y2="-28.640625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35754"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(5.315625,-3.75)"
+ x1="39.200001"
+ y1="-30.799999"
+ x2="41.325001"
+ y2="-28.765625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35756"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(3.3,0.3)"
+ x1="38.700001"
+ y1="-31.299999"
+ x2="40.012501"
+ y2="-29.799999" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35772"
+ gradientUnits="userSpaceOnUse"
+ x1="51.912914"
+ y1="-24.696922"
+ x2="40.75"
+ y2="-35.75"
+ gradientTransform="translate(-0.75,4.75)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient51774"
+ gradientUnits="userSpaceOnUse"
+ x1="135.32962"
+ y1="120.04005"
+ x2="130.7244"
+ y2="116.31882" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient51776"
+ gradientUnits="userSpaceOnUse"
+ x1="130.9015"
+ y1="115.23484"
+ x2="143.88347"
+ y2="129.27184" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient8864"
+ id="linearGradient51804"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9993234,0,0,1.0050357,111.43697,300.37199)"
+ x1="107.78085"
+ y1="50.778313"
+ x2="111.53449"
+ y2="46.679707" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient51806"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9993234,0,0,1.0050357,111.55698,300.497)"
+ x1="115.37703"
+ y1="51.021076"
+ x2="112.87534"
+ y2="51.021076" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient51808"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9993234,0,0,1.0050357,111.35699,300.55457)"
+ x1="110.57378"
+ y1="50.963791"
+ x2="108.07208"
+ y2="50.963791" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient51810"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5192341,-0.5192341,0.5184617,0.5184617,100.36783,218.31526)"
+ x1="-13.691219"
+ y1="241.78653"
+ x2="0.92051411"
+ y2="237.27565" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient51812"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5192341,-0.5192341,0.5184617,0.5184617,100.13133,218.33837)"
+ x1="-9.0782614"
+ y1="249.96617"
+ x2="-2.9318311"
+ y2="240.68927" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient68937"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(439.89375,-187.79999)"
+ x1="-5.3499999"
+ y1="251.51265"
+ x2="-8.5254431"
+ y2="248.125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient68939"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(439.89375,-187.79999)"
+ x1="-10.35"
+ y1="245.89999"
+ x2="-13.091064"
+ y2="242.8" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient68941"
+ gradientUnits="userSpaceOnUse"
+ x1="-41.065678"
+ y1="240.10526"
+ x2="-15.758821"
+ y2="244.11874" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient68943"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(440.2082,-188.0039)"
+ x1="-10.991813"
+ y1="237.9574"
+ x2="-7.0786314"
+ y2="246.7774" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient68945"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(439.9582,-188.0039)"
+ x1="-5.1338587"
+ y1="244.08765"
+ x2="-14.193665"
+ y2="251.35759" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient8864"
+ id="linearGradient68947"
+ gradientUnits="userSpaceOnUse"
+ x1="-15.6"
+ y1="247.38559"
+ x2="-3.321322"
+ y2="245.68124" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient68949"
+ gradientUnits="userSpaceOnUse"
+ x1="-5.3499999"
+ y1="251.51265"
+ x2="-8.7065439"
+ y2="248.125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient68951"
+ gradientUnits="userSpaceOnUse"
+ x1="-10.35"
+ y1="245.89999"
+ x2="-13.125"
+ y2="242.81946" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient68953"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.25,0.2058042)"
+ x1="-12.538609"
+ y1="240.79787"
+ x2="0.92051411"
+ y2="237.27565" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient68955"
+ gradientUnits="userSpaceOnUse"
+ x1="-7.20822"
+ y1="247.4906"
+ x2="-1.7751017"
+ y2="239.86711" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient69009"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.5466301,0,0,1.6489946,-293.01107,-16.485383)"
+ x1="582"
+ y1="49.294117"
+ x2="582"
+ y2="47.176472" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask69005">
+ <rect
+ style="fill:url(#linearGradient69009);fill-opacity:1;display:inline"
+ id="rect69007"
+ width="24.746082"
+ height="26.383913"
+ x="596.30127"
+ y="39.580433" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient20269"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(12.999999,359)"
+ x1="247"
+ y1="99"
+ x2="247"
+ y2="94" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient20275"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(15.081669,359)"
+ x1="245.63066"
+ y1="106.28436"
+ x2="245.80791"
+ y2="94.440376" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient20283"
+ x1="263.5"
+ y1="455.25"
+ x2="263.5"
+ y2="460.5"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient20303"
+ gradientUnits="userSpaceOnUse"
+ x1="264"
+ y1="452"
+ x2="264"
+ y2="460.6622"
+ gradientTransform="matrix(1,0,0,0.6,-5,182.8)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient20309"
+ x1="268"
+ y1="462"
+ x2="256"
+ y2="459"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#aigrd2"
+ id="radialGradient21565"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2798768,0,0,0.279916,6.0465962,-0.3619733)"
+ cx="20.892099"
+ cy="114.5684"
+ fx="20.892099"
+ fy="114.5684"
+ r="5.256" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#aigrd2"
+ id="radialGradient21567"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2798768,0,0,0.279916,6.0465962,-0.3619733)"
+ cx="20.892099"
+ cy="114.5684"
+ fx="20.892099"
+ fy="114.5684"
+ r="5.256" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient21594"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)"
+ x1="236.94902"
+ y1="-14.103641"
+ x2="276.89801"
+ y2="32.076183" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient21596"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-47.00001,58.00194)"
+ x1="160.14388"
+ y1="376.27383"
+ x2="174.29811"
+ y2="383.69843" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient21647"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)"
+ x1="236.94902"
+ y1="-14.103641"
+ x2="276.89801"
+ y2="31.515814" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient21649"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-47.00001,58.00194)"
+ x1="160.14388"
+ y1="376.27383"
+ x2="174.29811"
+ y2="383.69843" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient21977"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)"
+ x1="236.94902"
+ y1="-14.103641"
+ x2="276.89801"
+ y2="31.515814" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient21979"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-47.00001,58.00194)"
+ x1="160.14388"
+ y1="376.27383"
+ x2="174.29811"
+ y2="383.69843" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath22590">
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22592"
+ width="12"
+ height="14"
+ x="-30"
+ y="490.00012" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter22979"
+ x="-0.95999229"
+ width="2.9199846"
+ y="-0.96000773"
+ height="2.9200156"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1077015"
+ id="feGaussianBlur22981" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter22999"
+ x="-0.95999229"
+ width="2.9199846"
+ y="-0.96000773"
+ height="2.9200156"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1077015"
+ id="feGaussianBlur23001" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter23007"
+ x="-0.95999229"
+ width="2.9199846"
+ y="-0.96000773"
+ height="2.9200156"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1077015"
+ id="feGaussianBlur23009" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter23015"
+ x="-0.95999229"
+ width="2.9199846"
+ y="-0.96000773"
+ height="2.9200156"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1077015"
+ id="feGaussianBlur23017" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient23595"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.1666667,-737,357.33333)"
+ x1="771.0965"
+ y1="354.28479"
+ x2="772"
+ y2="358.85715" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask23591">
+ <rect
+ mask="none"
+ style="fill:url(#linearGradient23595);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23593"
+ width="11"
+ height="14"
+ x="30"
+ y="768" />
+ </mask>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath23877">
+ <rect
+ transform="scale(1,-1)"
+ y="-540"
+ x="952"
+ height="6"
+ width="15"
+ id="rect23879"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient23978"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)"
+ x1="236.94902"
+ y1="-14.103641"
+ x2="276.89801"
+ y2="31.515814" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient23980"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-47.00001,58.00194)"
+ x1="160.14388"
+ y1="376.27383"
+ x2="174.29811"
+ y2="383.69843" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31320"
+ id="linearGradient23982"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.733333,808.99997,-697.8)"
+ x1="150.5"
+ y1="239.9987"
+ x2="150.5"
+ y2="237" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29485"
+ id="linearGradient23986"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,1,0,715,364)"
+ x1="147.0625"
+ y1="243.76387"
+ x2="142.9375"
+ y2="243.69914" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30777"
+ id="linearGradient23988"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2857143,364,645.14283)"
+ x1="148"
+ y1="244.11113"
+ x2="144"
+ y2="244.11113" />
+ <linearGradient
+ id="linearGradient3564"
+ inkscape:collect="always">
+ <stop
+ id="stop3566"
+ offset="0"
+ style="stop-color:white;stop-opacity:1;" />
+ <stop
+ id="stop3568"
+ offset="1"
+ style="stop-color:white;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient39155">
+ <stop
+ id="stop39157"
+ offset="0"
+ style="stop-color:white;stop-opacity:1;" />
+ <stop
+ id="stop39159"
+ offset="1"
+ style="stop-color:#dadada;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient39171"
+ inkscape:collect="always">
+ <stop
+ id="stop39173"
+ offset="0"
+ style="stop-color:white;stop-opacity:1;" />
+ <stop
+ id="stop39175"
+ offset="1"
+ style="stop-color:white;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient21442"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient39155"
+ id="linearGradient21444"
+ gradientUnits="userSpaceOnUse"
+ x1="31.1875"
+ y1="18.875"
+ x2="29.875"
+ y2="34.375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3564"
+ id="linearGradient21446"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.06818845,0,0,0.06818845,22.51112,27.02885)"
+ x1="185.9903"
+ y1="193.33229"
+ x2="190.46461"
+ y2="-458.05771" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient39171"
+ id="radialGradient21448"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.647222,0,0,1.26792,-15.47413,-5.79794)"
+ cx="26.109201"
+ cy="19.668886"
+ fx="26.109201"
+ fy="19.668886"
+ r="20.278975" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient22274"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)"
+ x1="236.94902"
+ y1="-14.103641"
+ x2="276.89801"
+ y2="32.076183" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient22276"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-47.00001,58.00194)"
+ x1="160.14388"
+ y1="376.27383"
+ x2="174.29811"
+ y2="383.69843" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38718"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="121.22078"
+ y2="56.357628" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38721"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(207,-246.99988)"
+ x1="-56.5"
+ y1="342.0625"
+ x2="-49"
+ y2="341" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient39281"
+ gradientUnits="userSpaceOnUse"
+ x1="171"
+ y1="71"
+ x2="177"
+ y2="77" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39283"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1944456,0,0,1.2000039,-34.222431,-14.950295)"
+ x1="175.17659"
+ y1="74.972061"
+ x2="176.40117"
+ y2="76.182281" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient39285"
+ gradientUnits="userSpaceOnUse"
+ x1="165.19363"
+ y1="64.53186"
+ x2="176.15442"
+ y2="76.210785" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39287"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1718933,0,0,1.127086,-30.219387,-9.3173845)"
+ x1="172.30418"
+ y1="69.838829"
+ x2="176.84593"
+ y2="75.947906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient39289"
+ gradientUnits="userSpaceOnUse"
+ x1="171"
+ y1="70"
+ x2="177"
+ y2="77" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39291"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1718933,0,0,1.127086,-30.219387,-9.3173845)"
+ x1="175.1628"
+ y1="74.125008"
+ x2="176.84593"
+ y2="75.947906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient39293"
+ gradientUnits="userSpaceOnUse"
+ x1="171"
+ y1="70"
+ x2="177"
+ y2="77" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39295"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1718933,0,0,1.127086,-30.219387,-9.3173845)"
+ x1="175.1628"
+ y1="74.125008"
+ x2="176.84593"
+ y2="75.947906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39008"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="117.12428"
+ y2="61.720783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39010"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39012"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,13)"
+ x1="-56.8125"
+ y1="329.06256"
+ x2="-47.214466"
+ y2="329.26965" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39014"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="117.12428"
+ y2="61.720783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39016"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39018"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,13)"
+ x1="-56.8125"
+ y1="329.06256"
+ x2="-47.214466"
+ y2="329.26965" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39020"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="117.12428"
+ y2="61.720783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39022"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39024"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.7972867,61.99991,2.2419)"
+ x1="260.67468"
+ y1="108.02418"
+ x2="273.9993"
+ y2="126.37626" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39026"
+ x1="1127.7983"
+ y1="448.375"
+ x2="1153.0486"
+ y2="430.25"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14418"
+ id="linearGradient57417"
+ gradientUnits="userSpaceOnUse"
+ x1="146.82516"
+ y1="134.65511"
+ x2="130.10634"
+ y2="117.10313" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient57419"
+ gradientUnits="userSpaceOnUse"
+ x1="139.37782"
+ y1="126.3454"
+ x2="131.71249"
+ y2="118.34238" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient57421"
+ gradientUnits="userSpaceOnUse"
+ x1="125.01582"
+ y1="110.86718"
+ x2="132.46898"
+ y2="119.54019" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient57423"
+ gradientUnits="userSpaceOnUse"
+ x1="127.60629"
+ y1="112.12571"
+ x2="140.72693"
+ y2="126.72997" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient57454"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(258.00306,-231.00101)"
+ x1="75.25"
+ y1="393.25"
+ x2="73.5"
+ y2="391.5" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask57450">
+ <rect
+ y="154.99899"
+ x="326.00305"
+ height="15"
+ width="15"
+ id="rect57452"
+ style="fill:url(#linearGradient57454);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient22891"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.728189,0,0,1.727271,-357.88848,243.63713)"
+ x1="174.99828"
+ y1="12.918247"
+ x2="167.59578"
+ y2="12.551482" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30124"
+ id="linearGradient22893"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.728189,0,0,1.727271,-357.88848,243.63713)"
+ x1="169.47711"
+ y1="10.424105"
+ x2="169.47711"
+ y2="8.1183796" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30124"
+ id="linearGradient22895"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.728189,0,0,1.727271,237.88848,243.63713)"
+ x1="169.41847"
+ y1="10.306772"
+ x2="169.4877"
+ y2="7.9604731" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22897"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-215.00008,249.00001)"
+ x1="145.00008"
+ y1="11.99999"
+ x2="160.31258"
+ y2="19.34374" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22899"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-215.00008,249.00001)"
+ x1="149.00008"
+ y1="10.924165"
+ x2="171.37508"
+ y2="19.12499" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient32842"
+ id="linearGradient22901"
+ gradientUnits="userSpaceOnUse"
+ x1="-68.25"
+ y1="263"
+ x2="-56"
+ y2="265.53439" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22903"
+ gradientUnits="userSpaceOnUse"
+ x1="-66"
+ y1="264"
+ x2="-57"
+ y2="264.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient32998"
+ id="linearGradient22905"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.728189,0,0,1.727271,-357.88848,243.63713)"
+ x1="176.42079"
+ y1="12.946938"
+ x2="169.47711"
+ y2="12.36799" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient22933"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(15.081669,359)"
+ x1="245.63066"
+ y1="106.28436"
+ x2="245.80791"
+ y2="94.440376" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22935"
+ gradientUnits="userSpaceOnUse"
+ x1="268"
+ y1="462"
+ x2="256"
+ y2="459" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient22937"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(12.999999,359)"
+ x1="247"
+ y1="99"
+ x2="247"
+ y2="94" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22939"
+ gradientUnits="userSpaceOnUse"
+ x1="263.5"
+ y1="455.25"
+ x2="263.5"
+ y2="460.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22941"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.6,-5,182.8)"
+ x1="264"
+ y1="452"
+ x2="264"
+ y2="460.6622" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22970"
+ x1="-197.84375"
+ y1="399.90625"
+ x2="-191"
+ y2="409"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19625"
+ id="linearGradient23241"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-6,0)"
+ x1="480.09564"
+ y1="163.08553"
+ x2="476.76578"
+ y2="162.94037" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient23243"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(342.00029,383.00889)"
+ x1="123.36729"
+ y1="-219.24783"
+ x2="134.30893"
+ y2="-218.00888" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient12678"
+ id="radialGradient23245"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0982561,0,0,1.2662999,-45.858153,-42.45126)"
+ cx="470.15939"
+ cy="164.46814"
+ fx="470.15939"
+ fy="164.46814"
+ r="3.500145" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient23247"
+ gradientUnits="userSpaceOnUse"
+ x1="128.7561"
+ y1="115.77483"
+ x2="132.35237"
+ y2="118.69846" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient23250"
+ gradientUnits="userSpaceOnUse"
+ x1="127.30917"
+ y1="111.48133"
+ x2="138.30522"
+ y2="124.69373" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient23445"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-6,0)"
+ x1="480.09564"
+ y1="163.08553"
+ x2="475.50031"
+ y2="162.92206" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient23447"
+ 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="#linearGradient23974"
+ id="linearGradient23531"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.728189,0,0,1.727271,-142.8884,-5.3628832)"
+ x1="172.37032"
+ y1="12.147777"
+ x2="175.38158"
+ y2="15.699567" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23533"
+ gradientUnits="userSpaceOnUse"
+ x1="155.82454"
+ y1="16.845156"
+ x2="158.41653"
+ y2="19.99999" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient40843"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.727201,9.075096e-6,0,1.728246,-147.7149,-10.37485)"
+ x1="171.03941"
+ y1="11.121979"
+ x2="175.33569"
+ y2="16.202652" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient40845"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.728189,0,0,1.727271,-142.8884,-5.3628832)"
+ x1="172.18394"
+ y1="11.912162"
+ x2="176.46956"
+ y2="16.427906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40847"
+ gradientUnits="userSpaceOnUse"
+ x1="156.00008"
+ y1="16.99999"
+ x2="159.00008"
+ y2="19.99999" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient40965"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-20,14)"
+ x1="62.107086"
+ y1="223.54628"
+ x2="96.812675"
+ y2="258.38593" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient32842"
+ id="linearGradient40967"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-21,0)"
+ x1="79.04213"
+ y1="253.5"
+ x2="60.155113"
+ y2="234.7775" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient24098"
+ x1="208.25"
+ y1="-133.89581"
+ x2="204.01923"
+ y2="-111.15749"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23510"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1000194,0,0,1.0998287,-4.3008215,-8.6726798)"
+ x1="47.655102"
+ y1="93.805557"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient23512"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.728189,0,0,1.727271,-142.53857,-4.802156)"
+ x1="110.16959"
+ y1="57.061836"
+ x2="117.55341"
+ y2="64.995972" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23514"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1000194,0,0,1.0998287,-4.3010161,-8.6726854)"
+ x1="47.612946"
+ y1="93.555946"
+ x2="54.252415"
+ y2="100.44998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23550"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(1,0.01738631)"
+ x1="468.07968"
+ y1="275.27036"
+ x2="510"
+ y2="266.99997" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18105"
+ id="linearGradient23555"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(1,3.959006e-5)"
+ x1="492.95264"
+ y1="267.42996"
+ x2="496.73859"
+ y2="270.36874" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient23581"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9993234,0,0,1.0050357,404.07104,216.722)"
+ x1="116.75796"
+ y1="52.264809"
+ x2="103.18628"
+ y2="55.747272" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient21327"
+ id="linearGradient23585"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(1,-1.0000037)"
+ x1="500.71924"
+ y1="270.24997"
+ x2="477"
+ y2="274" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient32842"
+ id="radialGradient23610"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5274943,0,0,0.7696585,194.81546,86.715119)"
+ cx="412.10059"
+ cy="375.96332"
+ fx="412.10059"
+ fy="375.96332"
+ r="4.4262571" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24343"
+ id="radialGradient23612"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0009003,-1.5278593,1.1592123,0.7594114,-59.938837,957.7287)"
+ cx="409.55594"
+ cy="52.367992"
+ fx="409.55594"
+ fy="52.367992"
+ r="3.8798895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23562"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1004102,0,0,1.0993832,461.68129,182.37748)"
+ x1="47.612946"
+ y1="93.555946"
+ x2="56.524509"
+ y2="101.25028" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient23565"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.728803,0,0,1.7265713,323.39462,186.24644)"
+ x1="115.45872"
+ y1="58.869785"
+ x2="106.20376"
+ y2="58.354706" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient22847"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.728803,0,0,1.7265713,347.39462,166.24644)"
+ x1="110.54202"
+ y1="56.645538"
+ x2="115.53827"
+ y2="63.567348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22849"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2445337,0,0,1.5876961,523.20711,115.4619)"
+ x1="47.655102"
+ y1="93.805557"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22851"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1004102,0,0,1.0993832,503.28129,157.47747)"
+ x1="29.506693"
+ y1="100.66651"
+ x2="34.276955"
+ y2="105.98901" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24052"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="117.12428"
+ y2="61.720783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24054"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24056"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,13)"
+ x1="-56.8125"
+ y1="329.06256"
+ x2="-47.214466"
+ y2="329.26965" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient24066"
+ x1="202.5"
+ y1="143.84116"
+ x2="202.5"
+ y2="132.60213"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-259,202)" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient23738"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.050372,0,0,1.050372,-3.551238,-0.730396)"
+ cx="70.5"
+ cy="14.5"
+ fx="70.5"
+ fy="14.5"
+ r="1.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient23750"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.172144,59.49999,53.45766)"
+ x1="445.5"
+ y1="148.90862"
+ x2="433.5"
+ y2="148.69533" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient23752"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6499984,0,0,0.5439483,434.02514,137.87435)"
+ x1="113.71248"
+ y1="158.24995"
+ x2="91.499992"
+ y2="158.24994" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23754"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0052083,0,0,0.5057472,778.49218,365.83334)"
+ x1="-285.65732"
+ y1="-274.23453"
+ x2="-279.44821"
+ y2="-268.04858" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23914"
+ gradientUnits="userSpaceOnUse"
+ x1="29.200638"
+ y1="160.18758"
+ x2="32.928555"
+ y2="164.13913" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient23916"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.02887268,-1.2550276,0.795821,0.01830762,8.763469,168.20647)"
+ cx="11.708446"
+ cy="81.275032"
+ fx="11.708446"
+ fy="81.275032"
+ r="5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient23918"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.01269957,-0.9297674,1.1086869,0.01514236,-16.51473,165.70609)"
+ cx="4.7455525"
+ cy="82.433929"
+ fx="4.7455525"
+ fy="82.433929"
+ r="5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient24460"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(383,-37.999994)"
+ x1="-80"
+ y1="151"
+ x2="-80"
+ y2="152.24998" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask24456">
+ <rect
+ y="108"
+ x="299"
+ height="17"
+ width="7"
+ id="rect24458"
+ style="fill:url(#linearGradient24460);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ mask="none" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient24470"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(360,-142.95536)"
+ x1="-80"
+ y1="151"
+ x2="-80"
+ y2="152.24998" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask24466">
+ <rect
+ transform="scale(1,-1)"
+ style="fill:url(#linearGradient24470);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24468"
+ width="7"
+ height="9"
+ x="276"
+ y="4.0625" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient23971"
+ gradientUnits="userSpaceOnUse"
+ x1="154.24324"
+ y1="-11.628862"
+ x2="134.08138"
+ y2="-22.846634" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient23973"
+ gradientUnits="userSpaceOnUse"
+ x1="134.12642"
+ y1="-21.522242"
+ x2="132.29695"
+ y2="-23.945318" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient23975"
+ gradientUnits="userSpaceOnUse"
+ x1="134.6615"
+ y1="-21.3074"
+ x2="131.69801"
+ y2="-24.343456" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient24099"
+ x1="137.5"
+ y1="-18"
+ x2="135.25"
+ y2="-21"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient24539"
+ 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"
+ id="linearGradient24541"
+ 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"
+ id="linearGradient24543"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-6,0)"
+ x1="483.00034"
+ y1="163"
+ x2="476.68781"
+ y2="162.85956" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient24545"
+ 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"
+ id="linearGradient24547"
+ gradientUnits="userSpaceOnUse"
+ x1="475.00034"
+ y1="155"
+ x2="469.75034"
+ y2="155" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient24549"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-6,-6e-5)"
+ x1="442.81525"
+ y1="290.49384"
+ x2="436.5"
+ y2="290.5249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18105"
+ id="linearGradient24551"
+ gradientUnits="userSpaceOnUse"
+ x1="445.99902"
+ y1="288.5"
+ x2="407.3793"
+ y2="288.5" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath24168">
+ <path
+ style="fill:#808080;fill-rule:evenodd;stroke:none"
+ d="m 134.27489,222.11125 c -3.9249,-6.46418 -7.61892,6.46419 -11.54381,0 l 0,0 -1.61614,0 0,8.77283 14.77608,0 0,-8.77283 -1.61613,0 z"
+ id="path24170"
+ sodipodi:nodetypes="cccccccc" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient24112"
+ gradientUnits="userSpaceOnUse"
+ x1="124.40742"
+ y1="111.98244"
+ x2="135.36497"
+ y2="120.87388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24114"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient24116"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,1)"
+ x1="302.84085"
+ y1="243.23151"
+ x2="308.82889"
+ y2="244.70323" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24118"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6879084,0,0,0.6879446,216.19282,166.82605)"
+ x1="121.7408"
+ y1="115.90587"
+ x2="130.01318"
+ y2="116.60553" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient24121"
+ gradientUnits="userSpaceOnUse"
+ x1="135.698"
+ y1="122.92034"
+ x2="129.70906"
+ y2="117.15551" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24123"
+ gradientUnits="userSpaceOnUse"
+ x1="125.81818"
+ y1="111.81818"
+ x2="143.88347"
+ y2="129.27184" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient24189"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-93.937441,254)"
+ x1="162.61801"
+ y1="4.5569806"
+ x2="180.11391"
+ y2="23.410421" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24192"
+ gradientUnits="userSpaceOnUse"
+ x1="167.43744"
+ y1="23.749996"
+ x2="175.06059"
+ y2="32.144764"
+ gradientTransform="translate(-94.937441,240)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient24209"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-93.937441,254)"
+ x1="166.86487"
+ y1="12.306217"
+ x2="173.93744"
+ y2="19" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24268"
+ gradientUnits="userSpaceOnUse"
+ x1="186.74992"
+ y1="10.795519"
+ x2="189.24992"
+ y2="9.0189686"
+ gradientTransform="matrix(1,0,0,-0.985055,75.000075,275.63418)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient24272"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2000005,0,0,1.1817719,-50.700005,86.809844)"
+ x1="258.08322"
+ y1="148.24248"
+ x2="264.99994"
+ y2="154.24899" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient24277"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2000005,0,0,1.1817719,-50.700005,86.809844)"
+ x1="258.08322"
+ y1="148.24248"
+ x2="264.99994"
+ y2="154.24899" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient21327"
+ id="linearGradient24395"
+ x1="-27.5"
+ y1="268.76776"
+ x2="-39.875"
+ y2="277.4375"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15893"
+ id="linearGradient41127"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,594,-42.40625)"
+ x1="409.45645"
+ y1="52.77837"
+ x2="402.30673"
+ y2="55.86327" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27957"
+ id="linearGradient41129"
+ gradientUnits="userSpaceOnUse"
+ x1="180.20316"
+ y1="8.0551176"
+ x2="192.75177"
+ y2="12.942369" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient41170"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.9846154,-138.98388,3.9846124)"
+ x1="266.93381"
+ y1="199.60616"
+ x2="291.45029"
+ y2="230.76723" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient41172"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.01612278,0)"
+ x1="268.21783"
+ y1="200.66605"
+ x2="284.9375"
+ y2="224.1875" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient41174"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.25,0,0,1.375,-66.483877,-73.5)"
+ cx="269.99997"
+ cy="197"
+ fx="269.99997"
+ fy="197"
+ r="2" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42069"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.9846154,-138.98388,3.9846124)"
+ x1="266.93381"
+ y1="199.60616"
+ x2="291.45029"
+ y2="230.76723" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient42091"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.25,0,0,1.375,-66.483877,-73.5)"
+ cx="269.99997"
+ cy="197"
+ fx="269.99997"
+ fy="197"
+ r="2" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient42093"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.01612278,0)"
+ x1="276.39999"
+ y1="215.3125"
+ x2="265.70886"
+ y2="196.576" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient42115"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.25,0,0,1.375,-66.483877,-73.5)"
+ cx="269.99997"
+ cy="197"
+ fx="269.99997"
+ fy="197"
+ r="2" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42121"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(60,-342)"
+ x1="206"
+ y1="535"
+ x2="212"
+ y2="549" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42155"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.9846154,-138.98388,3.9846124)"
+ x1="263"
+ y1="193.93752"
+ x2="296.25"
+ y2="239.89455" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42290"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.01612278,0)"
+ x1="265.98389"
+ y1="195"
+ x2="290.98389"
+ y2="232" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient42292"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.25,0,0,1.375,-66.483877,-73.5)"
+ cx="269.99997"
+ cy="197"
+ fx="269.99997"
+ fy="197"
+ r="2" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient40722"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9819031,0,0,0.9481466,-88.271503,-83.584533)"
+ x1="1.6577729"
+ y1="253.01927"
+ x2="-57.772419"
+ y2="253.62515" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40724"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.977157,0,0,0.9835482,0.06815071,100.43848)"
+ x1="107.84375"
+ y1="57.374996"
+ x2="116.99999"
+ y2="60.125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient40734"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,13)"
+ x1="241.17908"
+ y1="214.40446"
+ x2="279.89563"
+ y2="254.94975" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient40736"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6025789,0,0,0.668336,263.48819,85.675422)"
+ x1="49.543404"
+ y1="230.81766"
+ x2="73.932747"
+ y2="247.27646" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40738"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9120445,0,0,1,25.749745,8.9261515)"
+ x1="305.12527"
+ y1="239.03134"
+ x2="308.97327"
+ y2="242" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient40740"
+ 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
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40742"
+ 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
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient40758"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(15.997359,-17.993456)"
+ x1="199.4335"
+ y1="294.81082"
+ x2="196.00264"
+ y2="259.99347" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40760"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7501745,0,0,1.0021005,51.339144,-0.5240716)"
+ x1="207.19595"
+ y1="249.22464"
+ x2="207.81319"
+ y2="250.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40762"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7501745,0,0,1.0021005,59.339161,-0.5240716)"
+ x1="207.19595"
+ y1="249.22464"
+ x2="207.81319"
+ y2="250.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient40788"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,-7.152175,20.92167)"
+ x1="146.51619"
+ y1="217.52046"
+ x2="174.56255"
+ y2="252.52081" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient40790"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(81.000002,13.499998)"
+ x1="87.765625"
+ y1="242.39062"
+ x2="96"
+ y2="251.40294" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18056"
+ id="linearGradient40792"
+ gradientUnits="userSpaceOnUse"
+ x1="170.42908"
+ y1="237.25"
+ x2="170.71698"
+ y2="249.15927" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient40794"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,10)"
+ x1="168.5625"
+ y1="249.55817"
+ x2="168.5"
+ y2="240.10249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40545"
+ gradientUnits="userSpaceOnUse"
+ x1="279.38629"
+ y1="-16.946415"
+ x2="293.80472"
+ y2="-2.5475447" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40547"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9230687,0,0,0.9230801,261.38476,-234.15464)"
+ x1="43.921535"
+ y1="261.52924"
+ x2="29.429007"
+ y2="243.98439" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient23775"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.9230769,0,0,-0.9258123,59.615385,471.81593)"
+ x1="-0.71355486"
+ y1="209.97131"
+ x2="37.5"
+ y2="252.16492" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient23777"
+ gradientUnits="userSpaceOnUse"
+ x1="72.698921"
+ y1="599.20789"
+ x2="77.111115"
+ y2="604.11108" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient23351"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,82.8792,399.00004)"
+ x1="-7.445384"
+ y1="204.24995"
+ x2="33.682159"
+ y2="250.99995" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23353"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(80.02752,483.00004)"
+ x1="29.972469"
+ y1="164"
+ x2="36.972481"
+ y2="168.00002" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient23355"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-224,-1290)"
+ x1="113"
+ y1="646"
+ x2="111"
+ y2="644" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23357"
+ gradientUnits="userSpaceOnUse"
+ x1="113"
+ y1="646"
+ x2="111.5"
+ y2="644.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23599"
+ x1="191"
+ y1="158.72728"
+ x2="196.59441"
+ y2="167.67831"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.89375,0,0,0.89375,20.29375,17.10625)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient22692"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6363637,0.6315788,0,-191.68403,523.2955)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient22695"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6363637,0,0,-0.6315788,314.2955,837.68414)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient22698"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6363637,-0.6315788,0,628.68411,331.70458)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient22701"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6363637,0,0,0.6315788,122.70458,17.31597)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient22704"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6363637,0,0,-0.6315788,311.11368,825.05254)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient22707"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6363637,0.6315788,0,-179.05245,520.11368)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient22711"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6363637,-0.6315788,0,616.05253,334.8864)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient22715"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6363637,0,0,0.6315788,125.8864,29.94755)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23132"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6357342,-0.636363,0,628.0905,358.45254)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23134"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.636363,0,0,-0.6357342,320.09081,851.14655)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23136"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6357342,0.636363,0,-173.09051,543.4512)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23138"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.636363,0,0,0.6357342,134.90918,50.757191)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23140"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.636363,0,0,0.6357342,131.72737,31.593709)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23142"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6357342,-0.636363,0,640.81777,348.82507)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23144"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.636363,0,0,-0.6357342,131.72737,857.41243)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23147"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6357342,0.636363,0,-185.81777,540.18107)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23177"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,850,297)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23179"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,-1,366,1072)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23181"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,-409,588)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23183"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(75,-187)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23185"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(70,-207)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23187"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,870,292)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23189"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,70,1092)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23191"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,-429,593)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23231"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.8181822,0.8181823,0,-304.90941,555.63645)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23235"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8181823,0,0,-0.8181822,103.36356,963.90937)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23239"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.8181822,-0.8181823,0,757.9094,309.36361)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23244"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8181823,0,0,0.8181822,103.36356,-98.909308)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23248"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8181823,0,0,0.8181822,107.45448,-82.54566)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23251"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.8181822,0.8181823,0,-288.54575,551.54554)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23254"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.8181823,0,0,-0.8181822,345.54553,947.54573)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23257"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.8181822,-0.8181823,0,741.54576,313.45452)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23563"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.8181822,-0.8181823,0,741.54576,313.45452)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23566"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.8181823,0,0,-0.8181822,345.54553,947.54573)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23568"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.8181822,0.8181823,0,-288.54575,551.54554)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23570"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8181823,0,0,0.8181822,107.45448,-82.54566)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23572"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8181823,0,0,0.8181822,103.36356,-98.909308)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23574"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.8181822,-0.8181823,0,757.9094,309.36361)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23576"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8181823,0,0,-0.8181822,103.36356,963.90937)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23578"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.8181822,0.8181823,0,-304.90941,555.63645)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23580"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,850,297)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23582"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,-1,366,1072)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23587"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,-409,588)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23589"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(75,-187)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23591"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(70,-207)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23593"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,870,292)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23597"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,70,1092)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23600"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,-429,593)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23602"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6363637,0,0,0.6315788,125.8864,29.94755)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23606"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6363637,-0.6315788,0,616.05253,334.8864)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23608"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6363637,0.6315788,0,-179.05245,520.11368)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23610"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6363637,0,0,-0.6315788,311.11368,825.05254)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23612"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6363637,0,0,0.6315788,122.70458,17.31597)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23616"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6363637,-0.6315788,0,628.68411,331.70458)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23618"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6363637,0,0,-0.6315788,314.2955,837.68414)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23620"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6363637,0.6315788,0,-191.68403,523.2955)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23622"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6357342,-0.636363,0,628.0905,358.45254)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23624"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.636363,0,0,-0.6357342,320.09081,851.14655)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23626"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6357342,0.636363,0,-173.09051,543.4512)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23628"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.636363,0,0,0.6357342,134.90918,50.757191)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23630"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.636363,0,0,0.6357342,131.72737,31.593709)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23632"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6357342,-0.636363,0,640.81777,348.82507)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23635"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.636363,0,0,-0.6357342,131.72737,857.41243)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23637"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6357342,0.636363,0,-185.81777,540.18107)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23797"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.8181822,-0.8181823,0,741.54576,313.45452)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23799"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.8181823,0,0,-0.8181822,345.54553,947.54573)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23801"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.8181822,0.8181823,0,-288.54575,551.54554)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23803"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8181823,0,0,0.8181822,107.45448,-82.54566)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23805"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8181823,0,0,0.8181822,103.36356,-98.909308)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23807"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.8181822,-0.8181823,0,757.9094,309.36361)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23809"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8181823,0,0,-0.8181822,103.36356,963.90937)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23811"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.8181822,0.8181823,0,-304.90941,555.63645)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23813"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,850,297)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23815"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,-1,366,1072)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23817"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,-409,588)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23819"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(75,-187)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23821"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(70,-207)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23823"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,870,292)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23825"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,70,1092)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23827"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,-429,593)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23829"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6363637,0,0,0.6315788,125.8864,29.94755)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23831"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6363637,-0.6315788,0,616.05253,334.8864)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23833"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6363637,0.6315788,0,-179.05245,520.11368)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23835"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6363637,0,0,-0.6315788,311.11368,825.05254)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23837"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6363637,0,0,0.6315788,122.70458,17.31597)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23839"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6363637,-0.6315788,0,628.68411,331.70458)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23841"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6363637,0,0,-0.6315788,314.2955,837.68414)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23843"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6363637,0.6315788,0,-191.68403,523.2955)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23845"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6357342,-0.636363,0,628.0905,358.45254)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23847"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.636363,0,0,-0.6357342,320.09081,851.14655)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23849"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6357342,0.636363,0,-173.09051,543.4512)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23851"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.636363,0,0,0.6357342,134.90918,50.757191)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23853"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.636363,0,0,0.6357342,131.72737,31.593709)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23856"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6357342,-0.636363,0,640.81777,348.82507)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23858"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.636363,0,0,-0.6357342,131.72737,857.41243)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23860"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6357342,0.636363,0,-185.81777,540.18107)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42685"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-52.983883,-129)"
+ x1="258"
+ y1="388"
+ x2="273"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42687"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-48.983883,-126)"
+ x1="259.75"
+ y1="388"
+ x2="273"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42689"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-54.000005,-120)"
+ x1="258.52756"
+ y1="388"
+ x2="279"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42691"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-46.000005,-117)"
+ x1="257.75"
+ y1="388"
+ x2="272"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23705"
+ id="linearGradient22892"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(220,-20.00667)"
+ x1="29.4034"
+ y1="100.99999"
+ x2="34.095703"
+ y2="101.15624" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient22917"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2,0,0,0.7333333,-467,262.53823)"
+ x1="250.5"
+ y1="90.253998"
+ x2="250.5"
+ y2="95.252274" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient22922"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4564959,0.09949388,-0.06177986,1.3917691,-283.96093,-143.81911)"
+ cx="135.14931"
+ cy="332.10181"
+ fx="135.14931"
+ fy="332.10181"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22928"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8750002,0,0,0.83767,7.3124969,247.00379)"
+ x1="27.166666"
+ y1="90.504448"
+ x2="35.166668"
+ y2="101.14744" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient22950"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.53241"
+ cy="500.20956"
+ fx="75.53241"
+ fy="500.20956"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient22952"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6595012,0.7907318,-0.8990144,0.7498135,144.69896,-187.59854)"
+ cx="262.67139"
+ cy="74.072273"
+ fx="262.67139"
+ fy="74.072273"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24168"
+ id="linearGradient22954"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.75,0,0,0.7516675,227.625,0.9640803)"
+ x1="20.125"
+ y1="88.642494"
+ x2="34.125"
+ y2="104.89799" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient23727"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.3687636,0.09935874,-0.05957343,1.3898788,-272.60513,-143.17133)"
+ cx="140.33667"
+ cy="333.05716"
+ fx="140.33667"
+ fy="333.05716"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37925"
+ id="linearGradient23890"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(220,-20.00667)"
+ x1="29.4034"
+ y1="100.99999"
+ x2="34.095703"
+ y2="101.15624" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22562"
+ id="linearGradient23892"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.75,0,0,0.7516675,227.625,0.9640803)"
+ x1="20.125"
+ y1="88.642494"
+ x2="34.125"
+ y2="104.89799" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23906"
+ id="radialGradient23894"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0553103,1.0606182,-1.2516598,1.280294,67.321819,-297.60493)"
+ cx="262.07156"
+ cy="74.306007"
+ fx="262.07156"
+ fy="74.306007"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23896"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8750002,0,0,0.83767,7.3124969,247.00379)"
+ x1="27.166666"
+ y1="90.504448"
+ x2="35.166668"
+ y2="101.14744" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14232"
+ id="radialGradient23898"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.53241"
+ cy="500.20956"
+ fx="75.53241"
+ fy="500.20956"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient23900"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4564959,0.09949388,-0.06177986,1.3917691,-283.96093,-143.81911)"
+ cx="135.14931"
+ cy="332.10181"
+ fx="135.14931"
+ fy="332.10181"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient23902"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2,0,0,0.7333333,-467,262.53823)"
+ x1="250.5"
+ y1="90.253998"
+ x2="250.5"
+ y2="95.252274" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient23904"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.3687636,0.09935874,-0.05957343,1.3898788,-272.60513,-143.17133)"
+ cx="140.33667"
+ cy="333.05716"
+ fx="140.33667"
+ fy="333.05716"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient42459"
+ id="linearGradient24090"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(220,-20.00667)"
+ x1="29.4034"
+ y1="100.99999"
+ x2="34.095703"
+ y2="101.15624" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22562"
+ id="linearGradient24092"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.75,0,0,0.7516675,227.625,0.9640803)"
+ x1="20.125"
+ y1="88.642494"
+ x2="34.125"
+ y2="104.89799" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient24094"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6595012,0.7907318,-0.8990144,0.7498135,144.69896,-187.59854)"
+ cx="263.21707"
+ cy="74.441246"
+ fx="263.21707"
+ fy="74.441246"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24096"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8750002,0,0,0.83767,7.3124969,247.00379)"
+ x1="27.166666"
+ y1="90.504448"
+ x2="35.166668"
+ y2="101.14744" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient24098"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.53241"
+ cy="500.20956"
+ fx="75.53241"
+ fy="500.20956"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient24100"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4564959,0.09949388,-0.06177986,1.3917691,-283.96093,-143.81911)"
+ cx="135.14931"
+ cy="332.10181"
+ fx="135.14931"
+ fy="332.10181"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient24102"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2,0,0,0.7333333,-467,262.53823)"
+ x1="250.5"
+ y1="90.253998"
+ x2="250.5"
+ y2="95.252274" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient24104"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.3687636,0.09935874,-0.05957343,1.3898788,-272.60513,-143.17133)"
+ cx="140.33667"
+ cy="333.05716"
+ fx="140.33667"
+ fy="333.05716"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24317"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.831045,0,0,0.776773,36.146465,141.05131)"
+ x1="71.762154"
+ y1="239.83469"
+ x2="76.956871"
+ y2="252.05081" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24319"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.831045,0,0,0.776773,36.165705,133.02478)"
+ x1="72.340698"
+ y1="243.03008"
+ x2="73.234337"
+ y2="246.81651" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24321"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.831045,0,0,0.776773,36.165705,133.02478)"
+ x1="66.954422"
+ y1="240.03282"
+ x2="68.458534"
+ y2="246.96069" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24362"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-335,238.99245)"
+ x1="426.12415"
+ y1="179.12074"
+ x2="425"
+ y2="179.12285" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24143"
+ id="linearGradient24367"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-149,133.99245)"
+ x1="244.37868"
+ y1="285.00754"
+ x2="237.75459"
+ y2="266.34406" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24695"
+ id="linearGradient24374"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,-30.15217,152.41412)"
+ x1="120.97597"
+ y1="281.26645"
+ x2="116.37123"
+ y2="260.21841" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient24436"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,-150.99992,596.00357)"
+ x1="199.87271"
+ y1="272.29477"
+ x2="212.22493"
+ y2="287.50357" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24727"
+ id="linearGradient24809"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,765.84783,-274.57833)"
+ x1="59.158501"
+ y1="437.02835"
+ x2="45.021851"
+ y2="349.81818" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24735"
+ id="linearGradient24811"
+ gradientUnits="userSpaceOnUse"
+ x1="807"
+ y1="101.5"
+ x2="841"
+ y2="101.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24711"
+ id="linearGradient24813"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,767.34783,-275.07833)"
+ x1="63.539974"
+ y1="421.80756"
+ x2="63.407566"
+ y2="347.78201" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient24815"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-127,4e-6)"
+ x1="954"
+ y1="102"
+ x2="936"
+ y2="114.99999" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24727"
+ id="linearGradient24839"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,765.84783,-274.57833)"
+ x1="59.158501"
+ y1="437.02835"
+ x2="45.021851"
+ y2="349.81818" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24735"
+ id="linearGradient24841"
+ gradientUnits="userSpaceOnUse"
+ x1="807"
+ y1="101.5"
+ x2="841"
+ y2="101.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24144"
+ id="linearGradient24843"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,767.34783,-275.07833)"
+ x1="64.019142"
+ y1="419.06366"
+ x2="63.407566"
+ y2="347.78201" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient24845"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-127,4e-6)"
+ x1="954"
+ y1="102"
+ x2="936"
+ y2="114.99999" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24727"
+ id="linearGradient24867"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,765.84783,-274.57833)"
+ x1="59.158501"
+ y1="437.02835"
+ x2="45.021851"
+ y2="349.81818" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24735"
+ id="linearGradient24869"
+ gradientUnits="userSpaceOnUse"
+ x1="807"
+ y1="101.5"
+ x2="841"
+ y2="101.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24711"
+ id="linearGradient24871"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,767.34783,-275.07833)"
+ x1="63.659767"
+ y1="422.46088"
+ x2="63.407566"
+ y2="347.78201" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient24873"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-127,4e-6)"
+ x1="954"
+ y1="102"
+ x2="936"
+ y2="114.99999" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24679"
+ id="linearGradient25073"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,-30.15217,152.41412)"
+ x1="121.79003"
+ y1="283.00519"
+ x2="114.66669"
+ y2="250.69945" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24671"
+ id="linearGradient25075"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-149,133.99245)"
+ x1="243.25"
+ y1="283.94504"
+ x2="235"
+ y2="253.00755" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient25077"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-335,238.99245)"
+ x1="426.12415"
+ y1="179.12074"
+ x2="425"
+ y2="179.12285" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24679"
+ id="linearGradient42055"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,-30.15217,152.41412)"
+ x1="120.94298"
+ y1="281.27435"
+ x2="114.66669"
+ y2="250.69945" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24671"
+ id="linearGradient42057"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-149,133.99245)"
+ x1="243.25"
+ y1="283.94504"
+ x2="235"
+ y2="253.00755" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42059"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-335,238.99245)"
+ x1="426.12415"
+ y1="179.12074"
+ x2="425"
+ y2="179.12285" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24101"
+ id="linearGradient24132"
+ gradientUnits="userSpaceOnUse"
+ x1="445.77841"
+ y1="113.24564"
+ x2="426.11459"
+ y2="84.777061" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient24599"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1489145,-0.69297,0.4772363,0.7912359,-113.08929,303.20064)"
+ cx="269.71231"
+ cy="237.2262"
+ fx="269.71231"
+ fy="237.2262"
+ r="7.03125" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient24632"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7236207,-0.7167103,1.004637,1.0143218,-131.254,253.93955)"
+ cx="262.83905"
+ cy="245.91792"
+ fx="262.83905"
+ fy="245.91792"
+ r="7.03125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31456"
+ id="linearGradient24797"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9897912,0,0,0.9897912,2.2765631,2.9503441)"
+ x1="311.3967"
+ y1="310.77368"
+ x2="309.02371"
+ y2="308.51169" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24820"
+ x1="311.37668"
+ y1="311.88205"
+ x2="307.5"
+ y2="308.21875"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20036"
+ id="radialGradient43962"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4011721,0.3766097,-0.7099042,0.7562044,179.21454,-58.566632)"
+ cx="207.04807"
+ cy="78.473343"
+ fx="207.04807"
+ fy="78.473343"
+ r="3.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20036"
+ id="radialGradient43964"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4543499,0.4687811,-0.6244606,0.6052369,161.562,-65.729731)"
+ cx="206.39249"
+ cy="78.443413"
+ fx="206.39249"
+ fy="78.443413"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient62436"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1,0)"
+ x1="248.69196"
+ y1="279.72827"
+ x2="269.3085"
+ y2="303.10999" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient62558"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,1,0,-33.03632,32.03632)"
+ x1="289.61554"
+ y1="320.55179"
+ x2="250.22783"
+ y2="282.28745" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient62560"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,59,638)"
+ x1="354.50601"
+ y1="283.61511"
+ x2="327.92044"
+ y2="300.96124" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25381"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1,21)"
+ x1="342"
+ y1="288.5"
+ x2="344.5"
+ y2="288.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25383"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,638,-40)"
+ x1="342"
+ y1="288.5"
+ x2="344.5"
+ y2="288.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25385"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,-1,699,599)"
+ x1="342"
+ y1="288.5"
+ x2="344.5"
+ y2="288.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25387"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,60,660)"
+ x1="342"
+ y1="288.5"
+ x2="344.5"
+ y2="288.5" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask25369">
+ <g
+ id="g25371"
+ transform="translate(-21,-21)">
+ <path
+ style="fill:url(#linearGradient25381);fill-rule:evenodd;stroke:none"
+ d="m 341,302 8,8 -8,8 0,-16 z"
+ id="path25373"
+ sodipodi:nodetypes="cccc"
+ inkscape:transform-center-x="4" />
+ <path
+ inkscape:transform-center-y="-4"
+ sodipodi:nodetypes="cccc"
+ id="path25375"
+ d="m 357,302 -8,8 -8,-8 16,0 z"
+ style="fill:url(#linearGradient25383);fill-rule:evenodd;stroke:none" />
+ <path
+ inkscape:transform-center-x="-4"
+ sodipodi:nodetypes="cccc"
+ id="path25377"
+ d="m 357,318 -8,-8 8,-8 0,16 z"
+ style="fill:url(#linearGradient25385);fill-rule:evenodd;stroke:none" />
+ <path
+ inkscape:transform-center-y="4"
+ sodipodi:nodetypes="cccc"
+ id="path25379"
+ d="m 341,318 8,-8 8,8 -16,0 z"
+ style="fill:url(#linearGradient25387);fill-rule:evenodd;stroke:none" />
+ </g>
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25573"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1,21)"
+ x1="342"
+ y1="288.5"
+ x2="344.01321"
+ y2="288.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25575"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,638,-40)"
+ x1="342"
+ y1="288.5"
+ x2="344.5"
+ y2="288.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25577"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,-1,699,599)"
+ x1="342"
+ y1="288.5"
+ x2="344.5"
+ y2="288.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25579"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,60,660)"
+ x1="342"
+ y1="288.5"
+ x2="344.5"
+ y2="288.5" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask25561">
+ <g
+ transform="translate(-21,-21)"
+ id="g25563">
+ <path
+ inkscape:transform-center-x="4"
+ sodipodi:nodetypes="cccc"
+ id="path25565"
+ d="m 341,302 8,8 -8,8 0,-16 z"
+ style="fill:url(#linearGradient25573);fill-rule:evenodd;stroke:none" />
+ <path
+ style="fill:url(#linearGradient25575);fill-rule:evenodd;stroke:none"
+ d="m 357,302 -8,8 -8,-8 16,0 z"
+ id="path25567"
+ sodipodi:nodetypes="cccc"
+ inkscape:transform-center-y="-4" />
+ <path
+ style="fill:url(#linearGradient25577);fill-rule:evenodd;stroke:none"
+ d="m 357,318 -8,-8 8,-8 0,16 z"
+ id="path25569"
+ sodipodi:nodetypes="cccc"
+ inkscape:transform-center-x="-4" />
+ <path
+ style="fill:url(#linearGradient25579);fill-rule:evenodd;stroke:none"
+ d="m 341,318 8,-8 8,8 -16,0 z"
+ id="path25571"
+ sodipodi:nodetypes="cccc"
+ inkscape:transform-center-y="4" />
+ </g>
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25872"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,513.5,328.50451)"
+ x1="253.78497"
+ y1="3.6831069"
+ x2="278.25537"
+ y2="30.023426" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334"
+ id="linearGradient25874"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(670,111)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25886"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,673.5,170.50451)"
+ x1="243.92192"
+ y1="-2.6686089"
+ x2="275.10107"
+ y2="26.600887" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334"
+ id="linearGradient25888"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(830,-47)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13998"
+ id="linearGradient25890"
+ gradientUnits="userSpaceOnUse"
+ x1="13.5"
+ y1="57.827747"
+ x2="11.472005"
+ y2="53.875874" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13998"
+ id="linearGradient25892"
+ gradientUnits="userSpaceOnUse"
+ x1="-18.600719"
+ y1="501.96539"
+ x2="-26.642899"
+ y2="487.60382" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient25894"
+ gradientUnits="userSpaceOnUse"
+ x1="15.027407"
+ y1="60.637787"
+ x2="13.5"
+ y2="57.750687" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient25897"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.03018343,0.1408617)"
+ x1="-32.067383"
+ y1="490.70178"
+ x2="-22.25"
+ y2="500" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient25899"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-72.000001)"
+ x1="753.39417"
+ y1="299.83005"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24679"
+ id="linearGradient25927"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,-30.15217,152.41412)"
+ x1="121.79003"
+ y1="283.00519"
+ x2="114.66669"
+ y2="250.69945" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24671"
+ id="linearGradient25929"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-149,133.99245)"
+ x1="243.25"
+ y1="283.94504"
+ x2="235"
+ y2="253.00755" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient25931"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-335,238.99245)"
+ x1="426.12415"
+ y1="179.12074"
+ x2="425"
+ y2="179.12285" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25957"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,673.5,170.50451)"
+ x1="253.78497"
+ y1="3.6831069"
+ x2="278.25537"
+ y2="30.023426" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334"
+ id="linearGradient25959"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(830,-47)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient25961"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-136,-112)"
+ x1="753.39417"
+ y1="299.83005"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25982"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,673.5,170.50451)"
+ x1="253.78497"
+ y1="3.6831069"
+ x2="278.25537"
+ y2="30.023426" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334"
+ id="linearGradient25984"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(830,-47)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient25986"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-136,-88.000005)"
+ x1="753.39417"
+ y1="299.83005"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient26011"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,673.5,170.50451)"
+ x1="253.78497"
+ y1="3.6831069"
+ x2="278.25537"
+ y2="30.023426" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334"
+ id="linearGradient26013"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(830,-47)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient26015"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-112,-76.000004)"
+ x1="753.39417"
+ y1="299.83005"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient26077"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,82.8792,399.00004)"
+ x1="-7.445384"
+ y1="204.24995"
+ x2="33.682159"
+ y2="250.99995" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient26079"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(80.02752,483.00004)"
+ x1="29.972469"
+ y1="164"
+ x2="36.972481"
+ y2="168.00002" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient26081"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-224,-1290)"
+ x1="113"
+ y1="646"
+ x2="111"
+ y2="644" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient26083"
+ gradientUnits="userSpaceOnUse"
+ x1="113"
+ y1="646"
+ x2="111.5"
+ y2="644.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient26126"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.831045,0,0,0.776773,36.146465,141.05131)"
+ x1="71.762154"
+ y1="239.83469"
+ x2="76.956871"
+ y2="252.05081" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient26128"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.831045,0,0,0.776773,36.165705,133.02478)"
+ x1="72.340698"
+ y1="243.03008"
+ x2="73.234337"
+ y2="246.81651" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient26130"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.831045,0,0,0.776773,36.165705,133.02478)"
+ x1="68.383354"
+ y1="239.95235"
+ x2="69.285805"
+ y2="247.29691" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient27973"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.39459,-0.991726,0.917787,0.36517,234.80511,750.0215)"
+ cx="450.06522"
+ cy="25.190212"
+ fx="450.06522"
+ fy="25.190212"
+ r="5.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient27975"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.121304,-0.696283,0.871429,0.151818,359.51331,621.7)"
+ cx="450.72842"
+ cy="19.250505"
+ fx="450.72842"
+ fy="19.250505"
+ r="5.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27977"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,883.51417,295)"
+ x1="456.81198"
+ y1="15.545153"
+ x2="441.9628"
+ y2="13.21724" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient28099"
+ gradientUnits="userSpaceOnUse"
+ x1="62.793919"
+ y1="133.73566"
+ x2="64.109718"
+ y2="135.18265" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient28107"
+ gradientUnits="userSpaceOnUse"
+ x1="461.66425"
+ y1="16.23234"
+ x2="432.875"
+ y2="14.936845"
+ gradientTransform="translate(-19,294.91429)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient27448"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-19,294.91429)"
+ x1="461.66425"
+ y1="16.23234"
+ x2="432.875"
+ y2="14.936845" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27450"
+ gradientUnits="userSpaceOnUse"
+ x1="62.793919"
+ y1="133.73566"
+ x2="64.109718"
+ y2="135.18265" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient27452"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.39459,-0.991726,0.917787,0.36517,234.80511,750.0215)"
+ cx="450.06522"
+ cy="25.190212"
+ fx="450.06522"
+ fy="25.190212"
+ r="5.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient27454"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.121304,-0.696283,0.871429,0.151818,359.51331,621.7)"
+ cx="450.72842"
+ cy="19.250505"
+ fx="450.72842"
+ fy="19.250505"
+ r="5.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27456"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,883.51417,295)"
+ x1="456.81198"
+ y1="15.545153"
+ x2="441.9628"
+ y2="13.21724" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27540"
+ gradientUnits="userSpaceOnUse"
+ x1="332.49747"
+ y1="38.166924"
+ x2="326.41843"
+ y2="31.22842" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27542"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(2.011921e-5,12.000013)"
+ x1="326.483"
+ y1="31.446384"
+ x2="337.3125"
+ y2="41.875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27544"
+ gradientUnits="userSpaceOnUse"
+ x1="329.18762"
+ y1="34.005215"
+ x2="331.44778"
+ y2="36.739578" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23705"
+ id="linearGradient27598"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(220,-20.00667)"
+ x1="29.4034"
+ y1="100.99999"
+ x2="34.095703"
+ y2="101.15624" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24168"
+ id="linearGradient27600"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.75,0,0,0.7516675,227.625,0.9640803)"
+ x1="20.125"
+ y1="88.642494"
+ x2="34.125"
+ y2="104.89799" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient27602"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6595012,0.7907318,-0.8990144,0.7498135,144.69896,-187.59854)"
+ cx="261.98364"
+ cy="74.083908"
+ fx="261.98364"
+ fy="74.083908"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27604"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8750002,0,0,0.83767,7.3124969,247.00379)"
+ x1="27.166666"
+ y1="90.504448"
+ x2="35.166668"
+ y2="101.14744" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient27606"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.53241"
+ cy="500.20956"
+ fx="75.53241"
+ fy="500.20956"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient27608"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4564959,0.09949388,-0.06177986,1.3917691,-283.96093,-143.81911)"
+ cx="135.14931"
+ cy="332.10181"
+ fx="135.14931"
+ fy="332.10181"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient27610"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2,0,0,0.7333333,-467,262.53823)"
+ x1="250.5"
+ y1="90.253998"
+ x2="250.5"
+ y2="95.252274" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient27612"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.3687636,0.09935874,-0.05957343,1.3898788,-272.60513,-143.17133)"
+ cx="140.33667"
+ cy="333.05716"
+ fx="140.33667"
+ fy="333.05716"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient34157"
+ id="linearGradient30389"
+ gradientUnits="userSpaceOnUse"
+ x1="270.60007"
+ y1="68.519989"
+ x2="258.00165"
+ y2="81.245804" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30391"
+ gradientUnits="userSpaceOnUse"
+ x1="256.67459"
+ y1="80.395966"
+ x2="262.88068"
+ y2="74.415245" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient30393"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4829018,0,0,0.4829018,133.47136,40.782399)"
+ cx="257.35309"
+ cy="79.598709"
+ fx="257.35309"
+ fy="79.598709"
+ r="3.779551" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient30395"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient30397"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient29129"
+ gradientUnits="userSpaceOnUse"
+ x1="732.9375"
+ y1="412.8125"
+ x2="753.40625"
+ y2="418.33594" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27767"
+ gradientUnits="userSpaceOnUse"
+ x1="125.99933"
+ y1="111.2683"
+ x2="134.91479"
+ y2="122.36016" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27769"
+ gradientUnits="userSpaceOnUse"
+ x1="126.72586"
+ y1="112.53999"
+ x2="134.91479"
+ y2="122.36016" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13973"
+ id="linearGradient27771"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(19.367382,0)"
+ x1="112.18942"
+ y1="114.71685"
+ x2="99.628899"
+ y2="99.029617" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27773"
+ gradientUnits="userSpaceOnUse"
+ x1="127.63637"
+ y1="114.2303"
+ x2="143.69765"
+ y2="131.03783" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="radialGradient31865"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.986122,0,0,0.986122,2.8033684,0.804927)"
+ cx="202"
+ cy="58"
+ fx="202"
+ fy="58"
+ r="7" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask31861">
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#radialGradient31865);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path31863"
+ sodipodi:cx="202"
+ sodipodi:cy="58"
+ sodipodi:rx="11"
+ sodipodi:ry="11"
+ d="m 213,58 a 11,11 0 1 1 -22,0 11,11 0 1 1 22,0 z" />
+ </mask>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath31849">
+ <path
+ style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 232.13187,93.950853 4.84276,0 4.23742,4.237465 0,4.842822 -9.08018,0 0,-9.080287 0,0 z"
+ id="path31851"
+ sodipodi:nodetypes="cccccc" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ id="filter30544"
+ x="-0.11968782"
+ width="1.2393756"
+ y="-0.12031381"
+ height="1.2406276"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.59634694"
+ id="feGaussianBlur30546" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter30552"
+ x="-0.12"
+ width="1.24"
+ y="-0.12"
+ height="1.24"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.4"
+ id="feGaussianBlur30554" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter30556"
+ x="-0.12"
+ width="1.24"
+ y="-0.12"
+ height="1.24"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.4"
+ id="feGaussianBlur30558" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter30564"
+ x="-0.12000064"
+ width="1.2400013"
+ y="-0.11999936"
+ height="1.2399987"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.36320908"
+ id="feGaussianBlur30566" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter30580"
+ x="-0.11981065"
+ width="1.2396213"
+ y="-0.12018995"
+ height="1.2403799"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.479335"
+ id="feGaussianBlur30582" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient32298"
+ gradientUnits="userSpaceOnUse"
+ x1="-117.5"
+ y1="431.5"
+ x2="-119.5"
+ y2="429.5"
+ gradientTransform="translate(258,-96.99999)" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask32294">
+ <rect
+ y="323"
+ x="134"
+ height="16"
+ width="9"
+ id="rect32296"
+ style="fill:url(#linearGradient32298);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </mask>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient32241"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.050372,0,0,1.050372,-3.551238,-0.730396)"
+ cx="70.5"
+ cy="14.5"
+ fx="70.5"
+ fy="14.5"
+ r="1.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient32243"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5399935,0.3131662,-0.3907892,0.5793905,38.141764,-16.056748)"
+ cx="70.470596"
+ cy="14.649424"
+ fx="70.470596"
+ fy="14.649424"
+ r="5.5192375" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient53119"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.684011,0.3442329,-1.2972142,1.1562236,739.67527,-1155.7895)"
+ cx="975.50568"
+ cy="690.68732"
+ fx="975.50568"
+ fy="690.68732"
+ r="2.333364" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient53121"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.821004,429.95027,-161.55482)"
+ x1="108.71671"
+ y1="171.25618"
+ x2="105.85706"
+ y2="168.04703" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20756"
+ id="linearGradient53123"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.8956408,540.31118,-183.20693)"
+ x1="-26.313976"
+ y1="178.07901"
+ x2="-28.432825"
+ y2="175.87964" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient53125"
+ gradientUnits="userSpaceOnUse"
+ x1="510.29913"
+ y1="-20.435461"
+ x2="505.9494"
+ y2="-17.546936" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient53127"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,-346.7085,428.4841)"
+ x1="352.98236"
+ y1="314.11398"
+ x2="353.72073"
+ y2="297.92099" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13938"
+ id="linearGradient53129"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-15.983875,338)"
+ x1="362.79037"
+ y1="-159.88834"
+ x2="373.83752"
+ y2="-150.41035" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient53131"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9900316,0,0,1,2.450297,0.00704954)"
+ x1="343.51892"
+ y1="175.19124"
+ x2="350.97491"
+ y2="183.3365" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient53133"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.684011,0.3442329,-1.2972142,1.1562236,739.67527,-1155.7895)"
+ cx="975.50568"
+ cy="690.68732"
+ fx="975.50568"
+ fy="690.68732"
+ r="2.333364" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient53135"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.821004,429.95027,-161.55482)"
+ x1="108.71671"
+ y1="171.25618"
+ x2="105.85706"
+ y2="168.04703" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20756"
+ id="linearGradient53137"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.8956408,540.31118,-183.20693)"
+ x1="-26.313976"
+ y1="178.07901"
+ x2="-28.432825"
+ y2="175.87964" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient53139"
+ gradientUnits="userSpaceOnUse"
+ x1="510.29913"
+ y1="-20.435461"
+ x2="505.9494"
+ y2="-17.546936" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient53141"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.684011,0.3442329,-1.2972142,1.1562236,739.67527,-1155.7895)"
+ cx="975.50568"
+ cy="690.68732"
+ fx="975.50568"
+ fy="690.68732"
+ r="2.333364" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient53143"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.821004,429.95027,-161.55482)"
+ x1="108.71671"
+ y1="171.25618"
+ x2="105.85706"
+ y2="168.04703" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20756"
+ id="linearGradient53145"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.8956408,540.31118,-183.20693)"
+ x1="-26.313976"
+ y1="178.07901"
+ x2="-28.432825"
+ y2="175.87964" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient53147"
+ gradientUnits="userSpaceOnUse"
+ x1="510.29913"
+ y1="-20.435461"
+ x2="505.9494"
+ y2="-17.546936" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient42459"
+ id="linearGradient53149"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(220,-20.00667)"
+ x1="29.4034"
+ y1="100.99999"
+ x2="34.095703"
+ y2="101.15624" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22562"
+ id="linearGradient53151"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.75,0,0,0.7516675,227.625,0.9640803)"
+ x1="20.125"
+ y1="88.642494"
+ x2="34.125"
+ y2="104.89799" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient53153"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6595012,0.7907318,-0.8990144,0.7498135,144.69896,-187.59854)"
+ cx="261.98364"
+ cy="74.083908"
+ fx="261.98364"
+ fy="74.083908"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient53155"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.75,0,0,0.7516675,115.625,254.97076)"
+ x1="27.166666"
+ y1="90.504448"
+ x2="35.166668"
+ y2="101.14744" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient53157"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.53241"
+ cy="500.20956"
+ fx="75.53241"
+ fy="500.20956"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient53159"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.1055676,0.08927896,-0.05295416,1.2488779,-134.03789,-95.726825)"
+ cx="135.14931"
+ cy="332.10181"
+ fx="135.14931"
+ fy="332.10181"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient53161"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-112,237.00668)"
+ x1="250.5"
+ y1="90.253998"
+ x2="250.5"
+ y2="95.252274" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient53163"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.1055676,0.08927896,-0.05295416,1.2488779,-134.03789,-95.726825)"
+ cx="140.33667"
+ cy="333.05716"
+ fx="140.33667"
+ fy="333.05716"
+ r="3.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient53165"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.684011,0.3442329,-1.2972142,1.1562236,739.67527,-1155.7895)"
+ cx="975.50568"
+ cy="690.68732"
+ fx="975.50568"
+ fy="690.68732"
+ r="2.333364" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient53167"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.821004,429.95027,-161.55482)"
+ x1="108.71671"
+ y1="171.25618"
+ x2="105.85706"
+ y2="168.04703" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20756"
+ id="linearGradient53169"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.8956408,540.31118,-183.20693)"
+ x1="-26.313976"
+ y1="178.07901"
+ x2="-28.432825"
+ y2="175.87964" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient53171"
+ gradientUnits="userSpaceOnUse"
+ x1="510.29913"
+ y1="-20.435461"
+ x2="505.9494"
+ y2="-17.546936" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23178"
+ id="linearGradient50870"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(2e-6,0)"
+ x1="-22.902081"
+ y1="448"
+ x2="-14.000002"
+ y2="448" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient33427"
+ gradientUnits="userSpaceOnUse"
+ x1="124.40742"
+ y1="111.98244"
+ x2="136.04924"
+ y2="121.25749" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient33429"
+ gradientUnits="userSpaceOnUse"
+ x1="132"
+ y1="117.26753"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient33585"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7071068,-0.7071068,0.7071067,0.7071067,-140.04288,401.30258)"
+ x1="458.99997"
+ y1="89.363937"
+ x2="452.63602"
+ y2="90.071045" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31356"
+ id="linearGradient33831"
+ gradientUnits="userSpaceOnUse"
+ x1="134.00002"
+ y1="116"
+ x2="142.00002"
+ y2="108" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient33833"
+ gradientUnits="userSpaceOnUse"
+ x1="124.75568"
+ y1="112.24533"
+ x2="132.97911"
+ y2="120.16792" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient33835"
+ gradientUnits="userSpaceOnUse"
+ x1="132"
+ y1="117.26753"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient37472"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,-32.5,115.5045)"
+ x1="254.19829"
+ y1="2.1803131"
+ x2="277.86761"
+ y2="29.392145" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37475"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(124,-102.00001)"
+ x1="85.1875"
+ y1="239.125"
+ x2="92.8125"
+ y2="245.625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient37477"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,-32.5,115.5045)"
+ x1="261.83936"
+ y1="11.593864"
+ x2="275.62497"
+ y2="26.679274" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37479"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(124,-102.00001)"
+ x1="85.1875"
+ y1="239.125"
+ x2="92.8125"
+ y2="245.625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient34157"
+ id="linearGradient37481"
+ gradientUnits="userSpaceOnUse"
+ x1="270.60007"
+ y1="68.519989"
+ x2="258.00165"
+ y2="81.245804" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37483"
+ gradientUnits="userSpaceOnUse"
+ x1="256.67459"
+ y1="80.395966"
+ x2="262.88068"
+ y2="74.415245" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient37485"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4829018,0,0,0.4829018,133.47136,40.782399)"
+ cx="257.35309"
+ cy="79.598709"
+ fx="257.35309"
+ fy="79.598709"
+ r="3.779551" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient37487"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient37489"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient37491"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.5793179,0,-1.0159927e-7,-1.6412688,666.67947,207.37331)"
+ cx="258.47122"
+ cy="78.512764"
+ fx="258.47122"
+ fy="78.512764"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient34157"
+ id="linearGradient37493"
+ gradientUnits="userSpaceOnUse"
+ x1="270.66064"
+ y1="68.113258"
+ x2="257.38638"
+ y2="81.382545" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37495"
+ gradientUnits="userSpaceOnUse"
+ x1="256.38586"
+ y1="80.515495"
+ x2="262.43726"
+ y2="74.562462" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient37497"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient37499"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient37501"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.08933014,-0.7764284,0.7350832,-0.08334857,57.410559,233.30156)"
+ cx="135.83771"
+ cy="117.97826"
+ fx="135.83771"
+ fy="117.97826"
+ r="8" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37503"
+ gradientUnits="userSpaceOnUse"
+ x1="121.19734"
+ y1="105.94044"
+ x2="148.06364"
+ y2="137.6748" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient34157"
+ id="linearGradient37505"
+ gradientUnits="userSpaceOnUse"
+ x1="270.66064"
+ y1="68.113258"
+ x2="257.38638"
+ y2="81.382545" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37507"
+ gradientUnits="userSpaceOnUse"
+ x1="256.38586"
+ y1="80.515495"
+ x2="262.43726"
+ y2="74.562462" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient37509"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient37511"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient37513"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.3336259,0,-8.5793649e-8,-1.3859393,603.17514,187.32668)"
+ cx="258.47122"
+ cy="78.512764"
+ fx="258.47122"
+ fy="78.512764"
+ r="3.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient37515"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.3648614,0,-8.7803051e-8,-1.4184,611.24862,189.87526)"
+ cx="258.47122"
+ cy="78.512764"
+ fx="258.47122"
+ fy="78.512764"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient34157"
+ id="linearGradient37517"
+ gradientUnits="userSpaceOnUse"
+ x1="270.66064"
+ y1="68.113258"
+ x2="257.38638"
+ y2="81.382545" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37519"
+ gradientUnits="userSpaceOnUse"
+ x1="256.38586"
+ y1="80.515495"
+ x2="262.43726"
+ y2="74.562462" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient37521"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient37523"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30124"
+ id="linearGradient37525"
+ gradientUnits="userSpaceOnUse"
+ x1="337.34329"
+ y1="43.328976"
+ x2="330.27045"
+ y2="35.276588" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37527"
+ gradientUnits="userSpaceOnUse"
+ x1="329.9158"
+ y1="35.5"
+ x2="335.27429"
+ y2="41.570362" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37529"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0028571,0,0,0.9943503,-0.4404318,0.129119)"
+ x1="166.89752"
+ y1="9.0567484"
+ x2="193.26451"
+ y2="38.642647" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37531"
+ gradientUnits="userSpaceOnUse"
+ x1="127.93343"
+ y1="122.8346"
+ x2="133.77768"
+ y2="116.99384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37533"
+ gradientUnits="userSpaceOnUse"
+ x1="141.60255"
+ y1="108.39205"
+ x2="132"
+ y2="118.66972" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37535"
+ gradientUnits="userSpaceOnUse"
+ x1="122.86111"
+ y1="127.14286"
+ x2="133.77768"
+ y2="116.99384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37537"
+ gradientUnits="userSpaceOnUse"
+ x1="141.60255"
+ y1="108.39205"
+ x2="132"
+ y2="118.66972" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37539"
+ gradientUnits="userSpaceOnUse"
+ x1="266"
+ y1="659"
+ x2="285"
+ y2="659" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35391"
+ id="linearGradient37541"
+ gradientUnits="userSpaceOnUse"
+ x1="244.21062"
+ y1="600.74884"
+ x2="244.21062"
+ y2="602.96759" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35407"
+ id="linearGradient37543"
+ gradientUnits="userSpaceOnUse"
+ x1="235.29379"
+ y1="588.43396"
+ x2="245.93307"
+ y2="604.52502" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37545"
+ gradientUnits="userSpaceOnUse"
+ x1="510.25"
+ y1="36"
+ x2="494"
+ y2="36"
+ gradientTransform="matrix(-1,0,0,1,992,0)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37547"
+ gradientUnits="userSpaceOnUse"
+ x1="492"
+ y1="33"
+ x2="503"
+ y2="43"
+ gradientTransform="matrix(-1,0,0,1,992,0)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37549"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,551,105)"
+ x1="497.3125"
+ y1="35"
+ x2="483"
+ y2="35" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37551"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,551,105)"
+ x1="497.3125"
+ y1="35"
+ x2="483"
+ y2="35" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37553"
+ gradientUnits="userSpaceOnUse"
+ x1="86.248604"
+ y1="32"
+ x2="68"
+ y2="12" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37555"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,1)"
+ x1="81"
+ y1="27"
+ x2="64.5"
+ y2="9.0000019" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient37557"
+ gradientUnits="userSpaceOnUse"
+ x1="70.78582"
+ y1="15.659542"
+ x2="79.465332"
+ y2="24.480759" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="radialGradient37559"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5997527,0.4726093,-0.6665451,0.8458611,35.480681,-28.765852)"
+ cx="63.013588"
+ cy="14.60904"
+ fx="63.013588"
+ fy="14.60904"
+ r="6.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37571"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8666667,0,0,0.9166667,406.13333,-443.79167)"
+ x1="108"
+ y1="500"
+ x2="54.8125"
+ y2="500" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15809"
+ id="linearGradient37573"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.9971589,396,-484.56523)"
+ x1="83.261826"
+ y1="502.54196"
+ x2="41.311054"
+ y2="501.10059" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262"
+ id="radialGradient37575"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3949409,0.3949425,-0.4243709,0.4254619,321.60762,256.85923)"
+ cx="75.95578"
+ cy="492.15359"
+ fx="75.95578"
+ fy="492.15359"
+ r="3.1650217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37578"
+ gradientUnits="userSpaceOnUse"
+ x1="80.768944"
+ y1="504.67188"
+ x2="76.885078"
+ y2="501.58331" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37580"
+ gradientUnits="userSpaceOnUse"
+ x1="89.526657"
+ y1="511.42972"
+ x2="78.000008"
+ y2="501.04794" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient37582"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.2665671,0.04035316,-0.03648524,1.99062,-82.893589,-502.25433)"
+ cx="79.959885"
+ cy="503.81497"
+ fx="79.959885"
+ fy="503.81497"
+ r="2.9089756" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient37584"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient37586"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37588"
+ gradientUnits="userSpaceOnUse"
+ x1="264.10001"
+ y1="330.10001"
+ x2="264.89999"
+ y2="330.89999" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14232"
+ id="linearGradient37590"
+ gradientUnits="userSpaceOnUse"
+ x1="122.38876"
+ y1="108.82882"
+ x2="133.88583"
+ y2="121.20407" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient37592"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9995363,0,0,-1.0036971,220.01067,167.35026)"
+ x1="51.37524"
+ y1="96.955269"
+ x2="44.999863"
+ y2="103.57072" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15437"
+ id="linearGradient37594"
+ gradientUnits="userSpaceOnUse"
+ x1="137.88235"
+ y1="124.67203"
+ x2="131.3092"
+ y2="117.24104" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37596"
+ gradientUnits="userSpaceOnUse"
+ x1="126.37032"
+ y1="110.87843"
+ x2="139.86742"
+ y2="126.57021" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient37608"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.684011,0.3442329,-1.2972142,1.1562236,739.67527,-1155.7895)"
+ cx="975.50568"
+ cy="690.68732"
+ fx="975.50568"
+ fy="690.68732"
+ r="2.333364" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient37610"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.821004,429.95027,-161.55482)"
+ x1="108.71671"
+ y1="171.25618"
+ x2="105.85706"
+ y2="168.04703" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20756"
+ id="linearGradient37612"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.8956408,540.31118,-183.20693)"
+ x1="-26.313976"
+ y1="178.07901"
+ x2="-28.432825"
+ y2="175.87964" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37614"
+ gradientUnits="userSpaceOnUse"
+ x1="510.29913"
+ y1="-20.435461"
+ x2="505.9494"
+ y2="-17.546936" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient37636"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,-241.7085,428.4841)"
+ x1="387.30396"
+ y1="126.23978"
+ x2="332.88193"
+ y2="123.61623" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient37638"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,-346.7085,428.4841)"
+ x1="352.98236"
+ y1="314.11398"
+ x2="353.72073"
+ y2="297.92099" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37640"
+ gradientUnits="userSpaceOnUse"
+ x1="121.19734"
+ y1="105.94044"
+ x2="148.06364"
+ y2="137.6748" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient42322"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9995967,0,0,1.0002103,-78.949724,-0.02739749)"
+ x1="109.04134"
+ y1="75.666725"
+ x2="135.45256"
+ y2="103.11092" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42324"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1000194,0,0,1.0998287,-4.6508478,-9.2334126)"
+ x1="47.655102"
+ y1="93.805557"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient42326"
+ gradientUnits="userSpaceOnUse"
+ x1="124.8772"
+ y1="110.75571"
+ x2="133.97179"
+ y2="117.77643" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient42328"
+ gradientUnits="userSpaceOnUse"
+ x1="129.32576"
+ y1="223.61363"
+ x2="123.33967"
+ y2="217.06438" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42330"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="142.64723"
+ y2="129.05313" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient42332"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.0041772,0,0,0.9688607,-81.584854,117.13687)"
+ x1="-4.9152389"
+ y1="252.69086"
+ x2="-45.689278"
+ y2="252.63284" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42334"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9993234,0,0,1.0050357,-171.92846,305.72314)"
+ x1="107.96875"
+ y1="53.875"
+ x2="117"
+ y2="60.125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42336"
+ gradientUnits="userSpaceOnUse"
+ x1="154.24324"
+ y1="-11.628862"
+ x2="134.08138"
+ y2="-22.846634" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42338"
+ gradientUnits="userSpaceOnUse"
+ x1="137.5"
+ y1="-18"
+ x2="135.25"
+ y2="-21" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42340"
+ gradientUnits="userSpaceOnUse"
+ x1="134.12642"
+ y1="-21.522242"
+ x2="132.29695"
+ y2="-23.945318" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42342"
+ gradientUnits="userSpaceOnUse"
+ x1="134.6615"
+ y1="-21.3074"
+ x2="131.69801"
+ y2="-24.343456" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient42344"
+ gradientUnits="userSpaceOnUse"
+ x1="-69.457596"
+ y1="31.914484"
+ x2="-76.564636"
+ y2="28.695114" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42346"
+ gradientUnits="userSpaceOnUse"
+ x1="-57.780041"
+ y1="48.005856"
+ x2="-78.812721"
+ y2="31" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient42348"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9995967,0,0,1.0002103,-78.949724,-0.02739749)"
+ x1="109.04134"
+ y1="75.666725"
+ x2="135.45256"
+ y2="103.11092" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42350"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3000195,0,0,0.2998291,32.548709,64.760571)"
+ x1="51.497997"
+ y1="97.491707"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42352"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3000195,0,0,0.1998289,32.548709,79.011866)"
+ x1="51.497997"
+ y1="94.987144"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42354"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3000195,0,0,0.1998289,32.548709,83.013491)"
+ x1="51.497997"
+ y1="94.987129"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42356"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2,0,0,0.1998289,42.197983,83.013493)"
+ x1="48.998543"
+ y1="94.987114"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42358"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2,0,0,0.1998289,42.197981,79.010163)"
+ x1="48.99855"
+ y1="94.995667"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42360"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2,0,0,0.2999998,42.19798,64.743076)"
+ x1="48.998554"
+ y1="97.494553"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42362"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2,0,0,0.1998289,46.196563,83.013493)"
+ x1="48.998539"
+ y1="94.987114"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42364"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2,0,0,0.1998289,46.196561,79.010163)"
+ x1="48.998547"
+ y1="94.995667"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42366"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2,0,0,0.2999998,46.19656,64.743076)"
+ x1="48.998554"
+ y1="97.494553"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient42368"
+ gradientUnits="userSpaceOnUse"
+ x1="-109.125"
+ y1="52.625"
+ x2="-121.73741"
+ y2="38.387074" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient42370"
+ gradientUnits="userSpaceOnUse"
+ x1="112.48699"
+ y1="99.873772"
+ x2="136.44698"
+ y2="123.20583" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42372"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient42374"
+ gradientUnits="userSpaceOnUse"
+ x1="102.83286"
+ y1="85.825607"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42376"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-41,98)"
+ x1="-170.25"
+ y1="65.5"
+ x2="-181.375"
+ y2="65.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42378"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6962506,0,0,0.8034158,-66.833415,127.95312)"
+ x1="-223.42456"
+ y1="43.134327"
+ x2="-202.33263"
+ y2="39.110355" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42380"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6962506,0,0,0.8034158,-66.833415,127.95312)"
+ x1="-219.98772"
+ y1="40.355042"
+ x2="-220.82353"
+ y2="27.996962" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42382"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9098462,0,0,0.9414558,-57.134785,102.33514)"
+ x1="-177.6924"
+ y1="63.26775"
+ x2="-170.82031"
+ y2="62.441177" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42384"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2857143,0,0,0.787037,-92.714287,177.80092)"
+ x1="-101"
+ y1="-16"
+ x2="-93.75"
+ y2="-16.264704" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42386"
+ gradientUnits="userSpaceOnUse"
+ x1="-211.04486"
+ y1="193.68091"
+ x2="-219.5"
+ y2="185.8125" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="radialGradient42388"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.6261963,-1.575549,0.4790575,0.7985147,261.90894,-304.15053)"
+ cx="-216.5222"
+ cy="188.13423"
+ fx="-216.5222"
+ fy="188.13423"
+ r="6.9375" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="radialGradient42390"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4767928,-0.2294888,0.06653313,0.7180687,315.70283,0.01290384)"
+ cx="-221.88463"
+ cy="182.64247"
+ fx="-221.88463"
+ fy="182.64247"
+ r="3.4576657" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42392"
+ gradientUnits="userSpaceOnUse"
+ x1="-225.00002"
+ y1="38.277779"
+ x2="-213"
+ y2="44.732624" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="radialGradient42394"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1226244,0.04761823,-0.1611956,3.8002759,59.188894,-553.59611)"
+ cx="-215.0979"
+ cy="201.01204"
+ fx="-215.0979"
+ fy="201.01204"
+ r="5.8999949" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42396"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,4)"
+ x1="-224"
+ y1="201"
+ x2="-214.39445"
+ y2="195.27762" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient42398"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1142111,0,0,-1,-174.01401,596.00357)"
+ x1="209.05762"
+ y1="290.00357"
+ x2="215.34009"
+ y2="277.00357" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient42400"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1142111,0,0,-1,-174.01401,596.00357)"
+ x1="178.77469"
+ y1="550.50702"
+ x2="198.57239"
+ y2="559.03442" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42402"
+ gradientUnits="userSpaceOnUse"
+ x1="132"
+ y1="120.4313"
+ x2="93.029579"
+ y2="78.9655" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient42404"
+ gradientUnits="userSpaceOnUse"
+ x1="112.48699"
+ y1="99.873772"
+ x2="136.44698"
+ y2="123.20583" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42406"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient42408"
+ gradientUnits="userSpaceOnUse"
+ x1="102.83286"
+ y1="85.825607"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42410"
+ gradientUnits="userSpaceOnUse"
+ x1="132"
+ y1="120.4313"
+ x2="93.029579"
+ y2="78.9655" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient42412"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1142111,0,0,-1,-174.01401,596.00357)"
+ x1="178.77469"
+ y1="550.50702"
+ x2="198.57239"
+ y2="559.03442" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient42414"
+ gradientUnits="userSpaceOnUse"
+ x1="112.48699"
+ y1="99.873772"
+ x2="133.62697"
+ y2="120.49951" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42416"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient42418"
+ gradientUnits="userSpaceOnUse"
+ x1="102.83286"
+ y1="85.825607"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42420"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-120,79)"
+ x1="-170.25"
+ y1="65.5"
+ x2="-181.375"
+ y2="65.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42422"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6962506,0,0,0.8034158,-145.83341,108.95312)"
+ x1="-223.42456"
+ y1="43.134327"
+ x2="-202.33263"
+ y2="39.110355" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42424"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6962506,0,0,0.8034158,-145.83341,108.95312)"
+ x1="-219.98772"
+ y1="40.355042"
+ x2="-220.82353"
+ y2="27.996962" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42426"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9098462,0,0,0.9414558,-136.13478,83.33514)"
+ x1="-177.6924"
+ y1="63.26775"
+ x2="-170.82031"
+ y2="62.441177" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42428"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2857143,0,0,0.787037,-171.71429,158.80092)"
+ x1="-101"
+ y1="-16"
+ x2="-93.75"
+ y2="-16.264704" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30208"
+ id="linearGradient42430"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1297,-948)"
+ x1="1664.4413"
+ y1="720.01788"
+ x2="1661.8125"
+ y2="726.37006" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19425"
+ id="radialGradient42432"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.1378252,-0.2988982,2.5269117,1.1651875,-1689.2674,-563.64056)"
+ cx="1662.2664"
+ cy="722.19189"
+ fx="1662.2664"
+ fy="722.19189"
+ r="5.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42434"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,-1256.7473,-918.72044)"
+ x1="1984.3658"
+ y1="827.77124"
+ x2="1977.4047"
+ y2="829.72656" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42436"
+ gradientUnits="userSpaceOnUse"
+ x1="-211.04486"
+ y1="193.68091"
+ x2="-219.5"
+ y2="185.8125" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="radialGradient42438"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.6261963,-1.575549,0.4790575,0.7985147,261.90894,-304.15053)"
+ cx="-216.5222"
+ cy="188.13423"
+ fx="-216.5222"
+ fy="188.13423"
+ r="6.9375" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="radialGradient42440"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4767928,-0.2294888,0.06653313,0.7180687,315.70283,0.01290384)"
+ cx="-221.88463"
+ cy="182.64247"
+ fx="-221.88463"
+ fy="182.64247"
+ r="3.4576657" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42442"
+ gradientUnits="userSpaceOnUse"
+ x1="-225.00002"
+ y1="38.277779"
+ x2="-213"
+ y2="44.732624" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient42444"
+ gradientUnits="userSpaceOnUse"
+ x1="124.8772"
+ y1="110.75571"
+ x2="133.97179"
+ y2="117.77643" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42446"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="142.64723"
+ y2="129.05313" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient42448"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1658027,0,0,1.1657997,-354.28972,51.94393)"
+ x1="129.32576"
+ y1="223.61363"
+ x2="123.33967"
+ y2="217.06438" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42462"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425"
+ id="linearGradient42464"
+ gradientUnits="userSpaceOnUse"
+ x1="123.26987"
+ y1="108.56933"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42466"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient42468"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.8370074,0,0,0.8129865,84.784966,-149.92038)"
+ x1="-4.9152389"
+ y1="252.69086"
+ x2="-45.689278"
+ y2="252.63284" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42470"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,11.285548,8.325368)"
+ x1="111.03847"
+ y1="57.034107"
+ x2="117.16058"
+ y2="60.591385" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42472"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425"
+ id="linearGradient42474"
+ gradientUnits="userSpaceOnUse"
+ x1="123.26987"
+ y1="108.56933"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42477"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42479"
+ gradientUnits="userSpaceOnUse"
+ x1="-92.587807"
+ y1="-18.005362"
+ x2="-100.62162"
+ y2="-17.998919" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42481"
+ gradientUnits="userSpaceOnUse"
+ x1="-101"
+ y1="-16"
+ x2="-93"
+ y2="-17" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient42483"
+ gradientUnits="userSpaceOnUse"
+ x1="-87.491188"
+ y1="-22.830606"
+ x2="-102.96513"
+ y2="-22.166544" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42485"
+ gradientUnits="userSpaceOnUse"
+ x1="-98.997849"
+ y1="-23.173643"
+ x2="-98.997849"
+ y2="-25.872688" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42487"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425"
+ id="linearGradient42489"
+ gradientUnits="userSpaceOnUse"
+ x1="123.26987"
+ y1="108.56933"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42491"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient42493"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5290924,0,0,0.5294132,-17.313533,46.110999)"
+ x1="109.04134"
+ y1="75.666725"
+ x2="135.45256"
+ y2="103.11092" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42495"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5350034,0,0,0.5349052,24.446207,45.843517)"
+ x1="47.655102"
+ y1="93.805557"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42497"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425"
+ id="linearGradient42499"
+ gradientUnits="userSpaceOnUse"
+ x1="123.26987"
+ y1="108.56933"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42501"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient42503"
+ gradientUnits="userSpaceOnUse"
+ x1="124.8772"
+ y1="110.75571"
+ x2="133.97179"
+ y2="117.77643" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42505"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="142.64723"
+ y2="129.05313" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42507"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425"
+ id="linearGradient42509"
+ gradientUnits="userSpaceOnUse"
+ x1="123.26987"
+ y1="108.56933"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42511"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient42513"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4749148,1.0023386,-1.2226848,-0.4749148,213.62384,41.735193)"
+ x1="118.95689"
+ y1="106.42961"
+ x2="135.14919"
+ y2="119.05286" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42515"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5333554,1.1220467,-1.1447545,-0.5333554,196.63818,32.816067)"
+ x1="130.39502"
+ y1="116.31751"
+ x2="147.95374"
+ y2="134.687" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18207"
+ id="linearGradient42517"
+ gradientUnits="userSpaceOnUse"
+ x1="-132.24858"
+ y1="313.87549"
+ x2="-171.01999"
+ y2="223.69542" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42519"
+ gradientUnits="userSpaceOnUse"
+ x1="114.15679"
+ y1="100.93772"
+ x2="137.5759"
+ y2="124.47867" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42521"
+ gradientUnits="userSpaceOnUse"
+ x1="131.12576"
+ y1="118"
+ x2="140.19273"
+ y2="125.82862" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient42523"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42525"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9050931,-7.9558708e-4,0.00612764,0.9147058,26.488451,35.562258)"
+ x1="299.70026"
+ y1="408.49368"
+ x2="322.08145"
+ y2="429.53806" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35406"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425"
+ id="linearGradient35408"
+ gradientUnits="userSpaceOnUse"
+ x1="119.94563"
+ y1="100.51657"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35410"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9897912,0,0,0.9897912,2.2765631,2.9503441)"
+ x1="311.90765"
+ y1="311.2269"
+ x2="308.84512"
+ y2="308.51169" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient35412"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1377775,-0.7111077,0.4395239,0.7032404,-101.13916,328.96745)"
+ cx="269.71231"
+ cy="237.2262"
+ fx="269.71231"
+ fy="237.2262"
+ r="7.03125" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient35414"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.706663,-1.1377794,0.5688915,0.8533318,-282.47828,404.20327)"
+ cx="262.83905"
+ cy="245.91792"
+ fx="262.83905"
+ fy="245.91792"
+ r="7.03125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35416"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425"
+ id="linearGradient35418"
+ gradientUnits="userSpaceOnUse"
+ x1="119.94563"
+ y1="100.51657"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35420"
+ gradientUnits="userSpaceOnUse"
+ x1="220.14905"
+ y1="291.80676"
+ x2="226.09999"
+ y2="286.2493" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35422"
+ gradientUnits="userSpaceOnUse"
+ x1="223.12212"
+ y1="296.15784"
+ x2="219.06912"
+ y2="291.99768" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35424"
+ gradientUnits="userSpaceOnUse"
+ x1="217.56451"
+ y1="290.56451"
+ x2="224.01613"
+ y2="297.01614" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient35426"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3677588,0.3783715,-0.5696226,0.5536455,304.13863,47.532824)"
+ cx="219.00334"
+ cy="291.33972"
+ fx="219.00334"
+ fy="291.33972"
+ r="4" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35468"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425"
+ id="linearGradient35470"
+ gradientUnits="userSpaceOnUse"
+ x1="119.94563"
+ y1="100.51657"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35472"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9897912,0,0,0.9897912,2.2765631,2.9503441)"
+ x1="311.90765"
+ y1="311.2269"
+ x2="308.84512"
+ y2="308.51169" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient35474"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1377775,-0.7111077,0.4395239,0.7032404,-101.13916,328.96745)"
+ cx="269.71231"
+ cy="237.2262"
+ fx="269.71231"
+ fy="237.2262"
+ r="7.03125" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient35476"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.706663,-1.1377794,0.5688915,0.8533318,-282.47828,404.20327)"
+ cx="262.83905"
+ cy="245.91792"
+ fx="262.83905"
+ fy="245.91792"
+ r="7.03125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35478"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425"
+ id="linearGradient35480"
+ gradientUnits="userSpaceOnUse"
+ x1="119.94563"
+ y1="100.51657"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35482"
+ gradientUnits="userSpaceOnUse"
+ x1="220.14905"
+ y1="291.80676"
+ x2="226.09999"
+ y2="286.2493" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35484"
+ gradientUnits="userSpaceOnUse"
+ x1="223.12212"
+ y1="296.15784"
+ x2="219.06912"
+ y2="291.99768" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35486"
+ gradientUnits="userSpaceOnUse"
+ x1="217.56451"
+ y1="290.56451"
+ x2="224.01613"
+ y2="297.01614" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient35488"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3677588,0.3783715,-0.5696226,0.5536455,304.13863,47.532824)"
+ cx="219.00334"
+ cy="291.33972"
+ fx="219.00334"
+ fy="291.33972"
+ r="4" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient34618"
+ gradientUnits="userSpaceOnUse"
+ x1="125.59209"
+ y1="112.6446"
+ x2="133.11621"
+ y2="119.21729" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient34620"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="141.83322"
+ y2="132.30261" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35411"
+ id="linearGradient35446"
+ gradientUnits="userSpaceOnUse"
+ x1="31"
+ y1="60.000004"
+ x2="34"
+ y2="54.000004" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35411"
+ id="linearGradient35448"
+ gradientUnits="userSpaceOnUse"
+ x1="135.46967"
+ y1="118"
+ x2="121.4286"
+ y2="101.14284" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35411"
+ id="linearGradient35450"
+ gradientUnits="userSpaceOnUse"
+ x1="133.60002"
+ y1="118"
+ x2="128.8"
+ y2="114.8" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35411"
+ id="linearGradient35452"
+ gradientUnits="userSpaceOnUse"
+ x1="132.30316"
+ y1="123.05057"
+ x2="128.8"
+ y2="114.8" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35411"
+ id="linearGradient35454"
+ gradientUnits="userSpaceOnUse"
+ x1="136.35806"
+ y1="124.27161"
+ x2="130.48389"
+ y2="118" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35718"
+ x1="28.130203"
+ y1="65.791054"
+ x2="32.5"
+ y2="55.066181"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient36452"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.050372,0,0,1.050372,-3.551238,-0.730396)"
+ cx="70.5"
+ cy="14.5"
+ fx="70.5"
+ fy="14.5"
+ r="1.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient36273"
+ id="linearGradient36454"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4000084,0,0,0.4000084,137.60085,-8.4035259)"
+ x1="-103.37495"
+ y1="417.87503"
+ x2="-101.49999"
+ y2="419.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient36273"
+ id="linearGradient36456"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4000084,0,0,0.4000084,131.60084,3.5964741)"
+ x1="-103.37495"
+ y1="417.87503"
+ x2="-101.49999"
+ y2="419.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient36273"
+ id="linearGradient36458"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4000084,0,0,0.4000084,143.60084,3.5964739)"
+ x1="-103.37495"
+ y1="417.87503"
+ x2="-101.49999"
+ y2="419.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient37095"
+ gradientUnits="userSpaceOnUse"
+ x1="125.75312"
+ y1="111.40558"
+ x2="143.16118"
+ y2="129.27902" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient37097"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0028571,0,0,0.9943503,-0.4404318,0.129119)"
+ x1="185.89514"
+ y1="30.343155"
+ x2="197.03207"
+ y2="42.717522" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient36648"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-3,3)"
+ x1="188"
+ y1="40.25"
+ x2="180.8125"
+ y2="32.46875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient36650"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-3,3)"
+ x1="187.8125"
+ y1="33.9375"
+ x2="184.25"
+ y2="30.15625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36652"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-3.0999952,2.9000005)"
+ x1="177.85001"
+ y1="33.537502"
+ x2="186.00626"
+ y2="43.381248" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19900"
+ id="linearGradient36654"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9643891,0,0,0.9772371,6.188671,1.0072576)"
+ x1="182.20605"
+ y1="39.645184"
+ x2="172.36885"
+ y2="31.368597" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36656"
+ gradientUnits="userSpaceOnUse"
+ x1="181.14906"
+ y1="32.701904"
+ x2="186.00002"
+ y2="37.415516" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19900"
+ id="linearGradient36658"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9643891,0,0,0.9772371,9.438677,-2.4927424)"
+ x1="181.9404"
+ y1="40.924297"
+ x2="175.82253"
+ y2="34.272892" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36468"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166695,0,0,0.9203753,-10.025729,345.78566)"
+ x1="80.60067"
+ y1="108.47212"
+ x2="68.0271"
+ y2="94.239906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13938"
+ id="linearGradient36470"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-15.983875,338)"
+ x1="68.361542"
+ y1="95.337166"
+ x2="88.785263"
+ y2="116.62141" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36472"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9998599,0,0,0.9960071,-15.972985,338.41149)"
+ x1="58.761654"
+ y1="84.330009"
+ x2="81.383331"
+ y2="108.06429" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36713"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="117.12428"
+ y2="61.720783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36715"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36717"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,13)"
+ x1="-56.8125"
+ y1="329.06256"
+ x2="-47.214466"
+ y2="329.26965" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36719"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="117.12428"
+ y2="61.720783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36721"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36723"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,13)"
+ x1="-56.8125"
+ y1="329.06256"
+ x2="-47.214466"
+ y2="329.26965" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36725"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="117.12428"
+ y2="61.720783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36727"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36729"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.7972867,61.99991,2.2419)"
+ x1="260.67468"
+ y1="108.02418"
+ x2="273.9993"
+ y2="126.37626" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient37396"
+ gradientUnits="userSpaceOnUse"
+ x1="389.73953"
+ y1="220.84622"
+ x2="389.59052"
+ y2="248.09296"
+ gradientTransform="matrix(-1,0,0,1,780.92531,0)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37398"
+ gradientUnits="userSpaceOnUse"
+ x1="389.51059"
+ y1="241.72565"
+ x2="388.20074"
+ y2="242.55887"
+ gradientTransform="matrix(-1,0,0,1,780.92531,0)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient38570"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-2,0)"
+ x1="-20"
+ y1="283"
+ x2="-20"
+ y2="284.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient38572"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-2,-582)"
+ x1="-20"
+ y1="283"
+ x2="-20"
+ y2="284.5" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask38561">
+ <g
+ id="g38563">
+ <rect
+ y="278"
+ x="-23"
+ height="13"
+ width="16"
+ id="rect38565"
+ style="fill:url(#linearGradient38570);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:url(#linearGradient38572);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect38567"
+ width="16"
+ height="13"
+ x="-23"
+ y="-304" />
+ </g>
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-7">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-1" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-2" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610-7-6">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-4-1" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-0-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069-4-2">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-8-3" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-8-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient11871-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop11873-5" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop11875-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-7-6"
+ id="linearGradient39048"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,-83,199)"
+ x1="96"
+ y1="42"
+ x2="68"
+ y2="12" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-4-2"
+ id="linearGradient39050"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,-83,199)"
+ x1="65"
+ y1="20"
+ x2="66"
+ y2="12" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient11871-4"
+ id="linearGradient39052"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,-83,199)"
+ x1="67.25"
+ y1="18"
+ x2="68"
+ y2="16" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35411-4-27"
+ id="linearGradient39835-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8422958,0,0,0.8364537,82.535678,2.9394266)"
+ x1="89.975014"
+ y1="-32.339718"
+ x2="88.492455"
+ y2="-33.303608" />
+ <linearGradient
+ id="linearGradient35411-4-27">
+ <stop
+ id="stop35414-0-9"
+ offset="0"
+ style="stop-color:#2b5385;stop-opacity:1;" />
+ <stop
+ id="stop35416-9-5"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35411-8-1-3"
+ id="linearGradient39837-4"
+ gradientUnits="userSpaceOnUse"
+ x1="131.02808"
+ y1="123.49161"
+ x2="128.7139"
+ y2="115.97001" />
+ <linearGradient
+ id="linearGradient35411-8-1-3">
+ <stop
+ id="stop35414-2-7-1"
+ offset="0"
+ style="stop-color:#2b5385;stop-opacity:1;" />
+ <stop
+ id="stop35416-4-1-2"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35411-8-1-3"
+ id="linearGradient39839-3"
+ gradientUnits="userSpaceOnUse"
+ x1="136.35806"
+ y1="124.27161"
+ x2="130.48389"
+ y2="118" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974-5-4"
+ id="linearGradient39841-3"
+ gradientUnits="userSpaceOnUse"
+ x1="115.15884"
+ y1="88.476723"
+ x2="109.18613"
+ y2="82.308861" />
+ <linearGradient
+ id="linearGradient23974-5-4">
+ <stop
+ id="stop23976-27-1"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop23978-6-1"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-8"
+ id="linearGradient39843-3"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21,0)"
+ x1="101"
+ y1="84.25"
+ x2="97.75"
+ y2="81.5" />
+ <linearGradient
+ id="linearGradient1610-8">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-7" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-77"
+ id="linearGradient39845-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21,0)"
+ x1="87.44548"
+ y1="81.439644"
+ x2="96.592278"
+ y2="89.708977" />
+ <linearGradient
+ id="linearGradient319-77">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-31" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22882"
+ id="linearGradient41540"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0369025,0,0,1.5,-458.38567,-344)"
+ x1="23.959812"
+ y1="285"
+ x2="31.498274"
+ y2="285" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22882"
+ id="linearGradient41542"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1929722,0,0,0.5,-462.63135,-59)"
+ x1="24"
+ y1="285"
+ x2="31.538462"
+ y2="285" />
+ <linearGradient
+ id="linearGradient23974-4">
+ <stop
+ id="stop23976-20"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop23978-9"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-37"
+ id="linearGradient32529-7"
+ gradientUnits="userSpaceOnUse"
+ x1="139.2112"
+ y1="111.35809"
+ x2="125.18381"
+ y2="128" />
+ <linearGradient
+ id="linearGradient319-37">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-2" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-60" />
+ </linearGradient>
+ <linearGradient
+ y2="125.77761"
+ x2="139.07738"
+ y1="115.76797"
+ x1="129.62384"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient41582"
+ xlink:href="#linearGradient23974-4"
+ inkscape:collect="always" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="radialGradient41666"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8128508,0,0,0.8128508,80.474142,14.46897)"
+ cx="430.00003"
+ cy="77.3125"
+ fx="430.00003"
+ fy="77.3125"
+ r="8" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient41668"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.785748,0,0,0.78488,265.93616,46.1048)"
+ x1="210.08989"
+ y1="38.088879"
+ x2="199.27217"
+ y2="38.088879" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient41670"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(399.01387,-202)"
+ x1="28.4375"
+ y1="277"
+ x2="23.25"
+ y2="276.92188" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient41672"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.01387,0)"
+ x1="437.98615"
+ y1="77"
+ x2="424.75217"
+ y2="75.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient41674"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.01387,0)"
+ x1="438.61115"
+ y1="78"
+ x2="424.75217"
+ y2="75.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient41676"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.01387,0)"
+ x1="441.98615"
+ y1="77.44017"
+ x2="424.75217"
+ y2="75.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42432"
+ gradientUnits="userSpaceOnUse"
+ x1="258.94861"
+ y1="285.63672"
+ x2="237.92474"
+ y2="261.44183" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient42435"
+ gradientUnits="userSpaceOnUse"
+ x1="135.45557"
+ y1="122.90726"
+ x2="130.54761"
+ y2="116.54932" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42437"
+ gradientUnits="userSpaceOnUse"
+ x1="125.81818"
+ y1="111.81818"
+ x2="143.88347"
+ y2="129.27184" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath42711">
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect42713"
+ width="8.7252884"
+ height="17.464855"
+ x="127.4093"
+ y="214.76154" />
+ </clipPath>
+ <linearGradient
+ id="linearGradient38796-7-9">
+ <stop
+ style="stop-color:#fc9694;stop-opacity:1;"
+ offset="0"
+ id="stop38798-6-8" />
+ <stop
+ style="stop-color:#e71609;stop-opacity:1;"
+ offset="1"
+ id="stop38800-1-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610-87">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-78" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-3" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24679-1">
+ <stop
+ style="stop-color:#3d361a;stop-opacity:1;"
+ offset="0"
+ id="stop24681-0" />
+ <stop
+ id="stop24683-7"
+ offset="0.45537567"
+ style="stop-color:#d1c595;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop24685-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38719"
+ gradientUnits="userSpaceOnUse"
+ x1="125.99933"
+ y1="111.2683"
+ x2="134.91479"
+ y2="122.36016" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38722"
+ gradientUnits="userSpaceOnUse"
+ x1="126.72586"
+ y1="112.53999"
+ x2="134.91479"
+ y2="122.36016" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13973"
+ id="linearGradient38724"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(19.367382,0)"
+ x1="111.46314"
+ y1="113.45913"
+ x2="99.628899"
+ y2="99.029617" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38726"
+ gradientUnits="userSpaceOnUse"
+ x1="127.63637"
+ y1="114.2303"
+ x2="143.69765"
+ y2="131.03783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38005"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-157.00004,-233.00002)"
+ x1="308"
+ y1="323"
+ x2="337.80573"
+ y2="337.517" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38007"
+ gradientUnits="userSpaceOnUse"
+ x1="285.39999"
+ y1="323.80002"
+ x2="286.60001"
+ y2="325" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath43368-1">
+ <rect
+ style="fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect43370-7"
+ width="16"
+ height="16"
+ x="-79"
+ y="26" />
+ </clipPath>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43276-0"
+ id="radialGradient43410-4"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4098275,-0.6406034,2.5104141,1.6060416,-127.46107,-65.792415)"
+ cx="-67.890839"
+ cy="33.548397"
+ fx="-67.890839"
+ fy="33.548397"
+ r="3.1501868" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient43276-0">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop43278-9" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop43280-4" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43276-0"
+ id="radialGradient43412-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4098275,-0.7183766,2.5885772,1.4767588,-130.41049,-65.518114)"
+ cx="-74.960228"
+ cy="34.896461"
+ fx="-74.960228"
+ fy="34.896461"
+ r="3.1501868" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38796-7-9"
+ id="linearGradient40270"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-21)"
+ x1="59.622501"
+ y1="54.1525"
+ x2="60.981617"
+ y2="55.566177" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-87"
+ id="linearGradient40272"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.5,-21)"
+ x1="60.25"
+ y1="56.5"
+ x2="57.789688"
+ y2="54.130001" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-87"
+ id="linearGradient40274"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.5,-21)"
+ x1="60.25"
+ y1="56.5"
+ x2="56"
+ y2="52.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-87"
+ id="linearGradient40276"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1.54625,-1)"
+ x1="63.666252"
+ y1="37.960625"
+ x2="60.676094"
+ y2="34.685287" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24679-1"
+ id="linearGradient40278"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-21)"
+ x1="52.17437"
+ y1="65.644958"
+ x2="50.371208"
+ y2="62.960247" />
+ <linearGradient
+ id="linearGradient24143-0">
+ <stop
+ id="stop24145-0"
+ offset="0"
+ style="stop-color:#2c2c2c;stop-opacity:1;" />
+ <stop
+ style="stop-color:#b3b3b3;stop-opacity:1;"
+ offset="0.5"
+ id="stop24669-1" />
+ <stop
+ id="stop24147-4"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-3-7"
+ id="linearGradient39686-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(22,0)"
+ x1="-70.605209"
+ y1="-121.58411"
+ x2="-28.177105"
+ y2="-89.026711" />
+ <linearGradient
+ id="linearGradient1610-3-7">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-1-4" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-6-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-5-9-4"
+ id="linearGradient39688-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(22,0)"
+ x1="-74"
+ y1="-124"
+ x2="-55.5975"
+ y2="-103.2075" />
+ <linearGradient
+ id="linearGradient319-5-9-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-761-8-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-89-24-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37542-6">
+ <stop
+ id="stop37544-18"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-92"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16500-3">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-3" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-41" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient9030-1">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop9032-9" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop9034-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient59371">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop59373" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop59375" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-9-1"
+ id="linearGradient42965-7"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(301.02752,449.99999)"
+ x1="25.963812"
+ y1="155.66899"
+ x2="29.972469"
+ y2="168" />
+ <linearGradient
+ id="linearGradient319-9-1">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-92-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-55-5" />
+ </linearGradient>
+ <filter
+ inkscape:collect="always"
+ id="filter24186-3-2"
+ x="-0.12810811"
+ width="1.2562162"
+ y="-0.11285714"
+ height="1.2257143"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.395"
+ id="feGaussianBlur24188-3-7" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-06-1"
+ id="linearGradient42967-6"
+ gradientUnits="userSpaceOnUse"
+ x1="335.96875"
+ y1="607.09375"
+ x2="337.04251"
+ y2="628.20752" />
+ <linearGradient
+ id="linearGradient1610-06-1">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-8-4" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-1-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient41266"
+ gradientUnits="userSpaceOnUse"
+ x1="98.858559"
+ y1="80.045052"
+ x2="135.00615"
+ y2="122.92735" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient41268"
+ gradientUnits="userSpaceOnUse"
+ x1="130.75166"
+ y1="245.03757"
+ x2="129.24866"
+ y2="243.31177" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient41270"
+ gradientUnits="userSpaceOnUse"
+ x1="126.37006"
+ y1="112.31642"
+ x2="144.22272"
+ y2="129.82761" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient41272"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient40918"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(146.00001,-20)"
+ x1="108"
+ y1="500"
+ x2="54.8125"
+ y2="500" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15809"
+ id="linearGradient40920"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(146.00001,-20)"
+ x1="88.874489"
+ y1="502.71924"
+ x2="41.311054"
+ y2="501.10059" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient40922"
+ gradientUnits="userSpaceOnUse"
+ x1="80.768944"
+ y1="504.67188"
+ x2="76.885078"
+ y2="501.58331" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40924"
+ gradientUnits="userSpaceOnUse"
+ x1="89.526657"
+ y1="511.42972"
+ x2="78.000008"
+ y2="501.04794" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262"
+ id="radialGradient40926"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3949409,0.3949425,-0.4243709,0.4254619,404.60763,237.35923)"
+ cx="75.95578"
+ cy="492.15359"
+ fx="75.95578"
+ fy="492.15359"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient40928"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.9435203,-2.1990242,1.1704696,1.0049395,-665.14472,173.40654)"
+ cx="79.959885"
+ cy="503.81497"
+ fx="79.959885"
+ fy="503.81497"
+ r="2.9089756" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262"
+ id="radialGradient40930"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8886193,0.8021825,-0.8051059,0.8972684,411.80247,-8.668512)"
+ cx="74.518959"
+ cy="499.99969"
+ fx="74.518959"
+ fy="499.99969"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient40932"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.054749"
+ cy="499.87418"
+ fx="75.054749"
+ fy="499.87418"
+ r="3.1650217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-6"
+ id="linearGradient36549"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.1511102,0,0,-1.1511102,152.68442,762.00423)"
+ x1="-16.608393"
+ y1="199.5118"
+ x2="30.713354"
+ y2="245.13458" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-3"
+ id="radialGradient36551"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6959954,0.116912,-0.04402498,0.2620878,107.60035,414.99606)"
+ cx="32.193073"
+ cy="243.37001"
+ fx="32.193073"
+ fy="243.37001"
+ r="6.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24143-0"
+ id="linearGradient36553"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.9999993,0,0,-0.9821923,147.99998,720.60935)"
+ x1="32.204613"
+ y1="233.6039"
+ x2="35.615856"
+ y2="251.99768" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-3"
+ id="linearGradient36555"
+ gradientUnits="userSpaceOnUse"
+ x1="148.76726"
+ y1="134.53409"
+ x2="114.11786"
+ y2="101.28939" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40809"
+ id="linearGradient36557"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7500336,0,0,0.8546123,-239.89087,340.17205)"
+ x1="481.60803"
+ y1="163.09677"
+ x2="477.10818"
+ y2="163.00024" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient59371"
+ id="linearGradient36559"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7500181,0,0,0.8546123,-235.38338,339.18935)"
+ x1="473.79471"
+ y1="164.64572"
+ x2="463.90472"
+ y2="160.80888" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030-1"
+ id="linearGradient36561"
+ gradientUnits="userSpaceOnUse"
+ x1="129.74713"
+ y1="118"
+ x2="144.33401"
+ y2="132.61403" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-3"
+ id="linearGradient36563"
+ gradientUnits="userSpaceOnUse"
+ x1="138.46678"
+ y1="124.90586"
+ x2="126.18426"
+ y2="116.14438" />
+ <linearGradient
+ id="linearGradient9030-7-8-6">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop9032-4-9-2" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop9034-0-2-3" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient40809-2-2">
+ <stop
+ style="stop-color:#0059d7;stop-opacity:1;"
+ offset="0"
+ id="stop40811-1-6" />
+ <stop
+ style="stop-color:#b7d4ff;stop-opacity:1;"
+ offset="1"
+ id="stop40813-4-2" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient20055-7-5-5">
+ <stop
+ id="stop20057-1-7-7"
+ offset="0"
+ style="stop-color:#0a2a5a;stop-opacity:1;" />
+ <stop
+ id="stop20059-1-6-8"
+ offset="1"
+ style="stop-color:#3771c8;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16500-4-9-7">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-8-5-8" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-8-4-0" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37829">
+ <stop
+ id="stop37831"
+ offset="0"
+ style="stop-color:#3d361a;stop-opacity:1;" />
+ <stop
+ style="stop-color:#d1c595;stop-opacity:1;"
+ offset="0.5"
+ id="stop37833" />
+ <stop
+ id="stop37835"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient40578-4-8">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop40580-8-9" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop40582-6-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient39254"
+ 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="#linearGradient40578-4-8"
+ id="radialGradient39256"
+ 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="#linearGradient58334"
+ id="linearGradient39258"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(670,-33)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39260"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-95.999998)"
+ x1="754.28558"
+ y1="300.83292"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ id="linearGradient40455-7">
+ <stop
+ id="stop40457-6"
+ offset="0"
+ style="stop-color:#fff991;stop-opacity:1;" />
+ <stop
+ id="stop40459-1"
+ offset="1"
+ style="stop-color:#fffbb9;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient36657"
+ 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="#linearGradient40578-4-8"
+ id="radialGradient36659"
+ 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="#linearGradient58334"
+ id="linearGradient36661"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(670,-33)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient36663"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-95.999998)"
+ x1="754.28558"
+ y1="300.83292"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37829"
+ id="linearGradient37089"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.9999993,0,0,-0.9821923,165.4,716.20935)"
+ x1="261.17639"
+ y1="247.85646"
+ x2="253.86414"
+ y2="288.70752" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient39080"
+ id="linearGradient37091"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.888884,0,0,-0.8730569,136.66557,688.20759)"
+ x1="261.60016"
+ y1="247.008"
+ x2="263.60016"
+ y2="262.27994" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030-7-8-6"
+ id="linearGradient37093"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-124.99991,219.9903)"
+ x1="19.923029"
+ y1="232.59058"
+ x2="50.485012"
+ y2="265.9697" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40809-2-2"
+ id="linearGradient37096"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7500336,0,0,0.8546123,-239.89087,340.17205)"
+ x1="199.26254"
+ y1="144.5041"
+ x2="193.7029"
+ y2="144.5041" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20055-7-5-5"
+ id="linearGradient37098"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-670.99999,411.99999)"
+ x1="579.625"
+ y1="54.299286"
+ x2="576.4375"
+ y2="49.84375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-4-9-7"
+ id="linearGradient37100"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-670.99999,411.99999)"
+ x1="582.79974"
+ y1="56.363762"
+ x2="575.70361"
+ y2="49.87711" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030-7-8-6"
+ id="linearGradient37102"
+ gradientUnits="userSpaceOnUse"
+ x1="129.74713"
+ y1="118"
+ x2="144.33401"
+ y2="132.61403" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-4-9-7"
+ id="linearGradient37104"
+ gradientUnits="userSpaceOnUse"
+ x1="140.78264"
+ y1="123.96156"
+ x2="132.25548"
+ y2="116.40535" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40455-7"
+ id="radialGradient37553"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7881042,0.01544832,-0.01690407,0.7184169,-16.705439,29.204304)"
+ cx="-73.135666"
+ cy="95.970413"
+ fx="-73.135666"
+ fy="95.970413"
+ r="4.9999957" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37667"
+ id="radialGradient37555"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4604901,-0.4901463,0.6187826,0.5813434,279.52277,457.42224)"
+ cx="756.98285"
+ cy="206.8443"
+ fx="756.98285"
+ fy="206.8443"
+ r="6.9000001" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334"
+ id="linearGradient37558"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(670,-33)"
+ x1="89.012573"
+ y1="243.96121"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient37561"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(1,-94.999998)"
+ x1="754.28558"
+ y1="300.83292"
+ x2="758.62622"
+ y2="305.53677" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40455-7-1"
+ id="radialGradient37553-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7881042,0.01544832,-0.01690407,0.7184169,-16.705439,29.204304)"
+ cx="-73.227486"
+ cy="95.949913"
+ fx="-73.227486"
+ fy="95.949913"
+ r="4.9999957" />
+ <linearGradient
+ id="linearGradient40455-7-1">
+ <stop
+ id="stop40457-6-6"
+ offset="0"
+ style="stop-color:#fff991;stop-opacity:1;" />
+ <stop
+ id="stop40459-1-8"
+ offset="1"
+ style="stop-color:#fffbb9;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40578-4-8-7"
+ id="radialGradient37555-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4769848,-0.5257394,0.6056598,0.5494938,269.68012,490.96577)"
+ cx="756.83508"
+ cy="206.40076"
+ fx="756.83508"
+ fy="206.40076"
+ r="6.9000001" />
+ <linearGradient
+ id="linearGradient40578-4-8-7">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop40580-8-9-6" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop40582-6-8-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334-9"
+ id="linearGradient37558-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(670,-33)"
+ x1="89.012573"
+ y1="243.96121"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ id="linearGradient58334-9">
+ <stop
+ id="stop58336-27"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.87628865;" />
+ <stop
+ id="stop58338-9"
+ offset="1.0000000"
+ style="stop-color:#fffffe;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-4">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-31" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-23" />
+ </linearGradient>
+ <linearGradient
+ y2="305"
+ x2="758"
+ y1="300.83292"
+ x1="754.28558"
+ gradientTransform="translate(1,-94.999998)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient37610-3"
+ xlink:href="#linearGradient16500-4"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient71834"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166695,0,0,0.9203753,-10.025729,345.78566)"
+ x1="80.60067"
+ y1="108.47212"
+ x2="68.0271"
+ y2="94.239906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient71814"
+ id="linearGradient71836"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-15.983875,338)"
+ x1="70.55275"
+ y1="97.5"
+ x2="79.355118"
+ y2="107.18619" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient71838"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9998599,0,0,0.9960071,-15.972985,338.41149)"
+ x1="61.465469"
+ y1="88.058716"
+ x2="86.00116"
+ y2="112.03586" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38256"
+ id="linearGradient37188"
+ gradientUnits="userSpaceOnUse"
+ x1="-22"
+ y1="36.47311"
+ x2="-18.85"
+ y2="22.485678"
+ gradientTransform="translate(522.00015,466)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37191"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(168.00015,169.99998)"
+ x1="308"
+ y1="323"
+ x2="343.26239"
+ y2="340" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37201"
+ gradientUnits="userSpaceOnUse"
+ x1="-26"
+ y1="38"
+ x2="-27"
+ y2="30.200407"
+ gradientTransform="translate(522.00015,466)" />
+ <linearGradient
+ id="linearGradient1610-7409">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-488" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-2" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient40578-4-8-5">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop40580-8-9-5" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop40582-6-8-17" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient58334-1">
+ <stop
+ id="stop58336-5"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.87628865;" />
+ <stop
+ id="stop58338-27"
+ offset="1.0000000"
+ style="stop-color:#fffffe;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-14">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-23" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-22" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-7409"
+ id="linearGradient37317"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,513.5,184.50451)"
+ x1="253.78497"
+ y1="3.6831069"
+ x2="272.92456"
+ y2="26.239208" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40578-4-8-5"
+ id="radialGradient37319"
+ 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="#linearGradient58334-1"
+ id="linearGradient37321"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(670,-33)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-14"
+ id="linearGradient37323"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-95.999998)"
+ x1="754.1275"
+ y1="301.01553"
+ x2="758.77625"
+ y2="305.51749" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient37338"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(461.00015,453)"
+ x1="37"
+ y1="53"
+ x2="36.74033"
+ y2="44.322407" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37132"
+ gradientUnits="userSpaceOnUse"
+ x1="510.25"
+ y1="36"
+ x2="494"
+ y2="36"
+ gradientTransform="matrix(-1,0,0,1,992,0)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37134"
+ gradientUnits="userSpaceOnUse"
+ x1="492"
+ y1="33"
+ x2="503"
+ y2="43"
+ gradientTransform="matrix(-1,0,0,1,992,0)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37136"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,551,105)"
+ x1="497.3125"
+ y1="35"
+ x2="483"
+ y2="35" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37138"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,551,105)"
+ x1="497.3125"
+ y1="35"
+ x2="483"
+ y2="35" />
+ <linearGradient
+ id="linearGradient40455-7-1-7">
+ <stop
+ id="stop40457-6-6-4"
+ offset="0"
+ style="stop-color:#fff991;stop-opacity:1;" />
+ <stop
+ id="stop40459-1-8-0"
+ offset="1"
+ style="stop-color:#fffbb9;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient38362"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,2.85168,-84)"
+ x1="-9.3937483"
+ y1="203.3882"
+ x2="28.275171"
+ y2="249.73875" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40455-7-1-7"
+ id="radialGradient38364"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1033468,0.01995877,-0.02366572,0.9281732,7.8124646,13.285893)"
+ cx="-73.972397"
+ cy="94.935921"
+ fx="-73.972397"
+ fy="94.935921"
+ r="4.9999957" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38367"
+ gradientUnits="userSpaceOnUse"
+ x1="19.210167"
+ y1="143.17894"
+ x2="38.580528"
+ y2="167.11429"
+ gradientTransform="matrix(1,0,0,0.8461542,0,25.615323)" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath43368-7">
+ <rect
+ style="fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect43370-1"
+ width="16"
+ height="16"
+ x="-79"
+ y="26" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient43276-6">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop43278-0" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop43280-49" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43276-6"
+ id="radialGradient38734"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4098275,-0.6406034,2.5104141,1.6060416,-127.46107,-65.792415)"
+ cx="-67.890839"
+ cy="33.548397"
+ fx="-67.890839"
+ fy="33.548397"
+ r="3.1501868" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43276-6"
+ id="radialGradient38736"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4098275,-0.7183766,2.5885772,1.4767588,-130.41049,-65.518114)"
+ cx="-74.960228"
+ cy="34.896461"
+ fx="-74.960228"
+ fy="34.896461"
+ r="3.1501868" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38049"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="121.22078"
+ y2="56.357628" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38051"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(207,-246.99988)"
+ x1="-56.5"
+ y1="342.0625"
+ x2="-49"
+ y2="341" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37530"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="121.22078"
+ y2="56.357628" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37534"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(207,-246.99988)"
+ x1="-56.5"
+ y1="342.0625"
+ x2="-49"
+ y2="341" />
+ <linearGradient
+ id="linearGradient1610-6">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-18" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-92" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069-9">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-5" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-43" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9"
+ id="linearGradient38254"
+ gradientUnits="userSpaceOnUse"
+ x1="124.19057"
+ y1="111.30384"
+ x2="134.62978"
+ y2="120.14633" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-6"
+ id="linearGradient37509"
+ gradientUnits="userSpaceOnUse"
+ x1="189.76083"
+ y1="248.13905"
+ x2="116.05637"
+ y2="183.6826" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9"
+ id="linearGradient37613"
+ gradientUnits="userSpaceOnUse"
+ x1="123.80045"
+ y1="111.03492"
+ x2="132.99687"
+ y2="118.98331" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-6"
+ id="linearGradient37615"
+ gradientUnits="userSpaceOnUse"
+ x1="189.76083"
+ y1="248.13905"
+ x2="116.05637"
+ y2="183.6826" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425-4-9-8"
+ id="linearGradient38073-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,22)"
+ x1="-14.752135"
+ y1="101.82622"
+ x2="-45.074585"
+ y2="68.279541" />
+ <linearGradient
+ id="linearGradient15425-4-9-8">
+ <stop
+ style="stop-color:#960000;stop-opacity:1;"
+ offset="0"
+ id="stop15427-5-8-24" />
+ <stop
+ style="stop-color:#c80000;stop-opacity:0;"
+ offset="1"
+ id="stop15429-8-2-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060-1"
+ id="linearGradient38075-5"
+ gradientUnits="userSpaceOnUse"
+ x1="137.33838"
+ y1="124.67571"
+ x2="131.35606"
+ y2="118.00494" />
+ <linearGradient
+ id="linearGradient5060-1">
+ <stop
+ id="stop5062-7"
+ offset="0"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ id="stop5064-1"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-52"
+ id="linearGradient38077-1"
+ gradientUnits="userSpaceOnUse"
+ x1="127.15736"
+ y1="111.48302"
+ x2="146.01884"
+ y2="136.15825" />
+ <linearGradient
+ id="linearGradient319-52">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-7614" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-232" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425-4-9-8"
+ id="linearGradient38079-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,22)"
+ x1="-15"
+ y1="101"
+ x2="-22"
+ y2="94" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14418-6"
+ id="linearGradient14433-1"
+ gradientUnits="userSpaceOnUse"
+ x1="139.29807"
+ y1="127.35454"
+ x2="130.33557"
+ y2="115.81818" />
+ <linearGradient
+ id="linearGradient14418-6">
+ <stop
+ id="stop14420-8"
+ offset="0"
+ style="stop-color:#fa2509;stop-opacity:1;" />
+ <stop
+ id="stop14422-5"
+ offset="1"
+ style="stop-color:#fa2509;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-52"
+ id="linearGradient14435-7"
+ gradientUnits="userSpaceOnUse"
+ x1="125.36379"
+ y1="110.81054"
+ x2="135.22182"
+ y2="120.76331" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-52"
+ id="linearGradient14437-6"
+ gradientUnits="userSpaceOnUse"
+ x1="125.81818"
+ y1="111.81818"
+ x2="141.43347"
+ y2="127.52184" />
+ <filter
+ inkscape:collect="always"
+ id="filter15421-1"
+ x="-0.23999846"
+ width="1.4799969"
+ y="-0.24000154"
+ height="1.4800031"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.29233622"
+ id="feGaussianBlur15423-8" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-2"
+ id="linearGradient14439-9"
+ gradientUnits="userSpaceOnUse"
+ x1="125.20553"
+ y1="111.38132"
+ x2="132.35237"
+ y2="118.69846" />
+ <linearGradient
+ id="linearGradient10069-2">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-79" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-52"
+ id="linearGradient14441-4"
+ gradientUnits="userSpaceOnUse"
+ x1="125.81818"
+ y1="111.81818"
+ x2="143.88347"
+ y2="129.27184" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient48327-1"
+ id="radialGradient38306-3"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4461753,0.01083717,0.0036163,6.752143,-191.34795,-740.3814)"
+ cx="131.99811"
+ cy="126.63337"
+ fx="131.99811"
+ fy="126.63337"
+ r="9.1978254" />
+ <linearGradient
+ id="linearGradient48327-1">
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="0"
+ id="stop48329-23" />
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="1"
+ id="stop48331-3" />
+ </linearGradient>
+ <linearGradient
+ y2="118.69846"
+ x2="132.35237"
+ y1="111.38132"
+ x1="125.20553"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient37646-4"
+ xlink:href="#linearGradient10069-74-1"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient10069-74-1">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-0-1" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-9-3" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-7409-3-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-48-8-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-82-6-27" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-7409-3-7"
+ id="linearGradient38313-7"
+ gradientUnits="userSpaceOnUse"
+ x1="125.81818"
+ y1="111.81818"
+ x2="143.88347"
+ y2="129.27184" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-7409-3-7"
+ id="linearGradient37677"
+ gradientUnits="userSpaceOnUse"
+ x1="130.60338"
+ y1="115.87343"
+ x2="143.88347"
+ y2="129.27184" />
+ <linearGradient
+ id="linearGradient319-19">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-865" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-02" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069-8-3-3">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-9-8-7" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-2-7-1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-95-2-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-43-7-3" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-12-7-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient21327-6">
+ <stop
+ style="stop-color:#1e3e70;stop-opacity:1;"
+ offset="0"
+ id="stop21329-3" />
+ <stop
+ style="stop-color:#1e3e70;stop-opacity:0;"
+ offset="1"
+ id="stop21331-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient20055-8-4">
+ <stop
+ id="stop20057-8-0"
+ offset="0"
+ style="stop-color:#0a2a5a;stop-opacity:1;" />
+ <stop
+ id="stop20059-2-0"
+ offset="1"
+ style="stop-color:#3771c8;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient39088">
+ <stop
+ id="stop39090"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop39092"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610-83">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-24" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-11" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069-95">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-10" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-64" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient11871-3">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop11873-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop11875-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069-3">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-87" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-42" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40171"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="120.06789"
+ y2="54.6674" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40173"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40175"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,13)"
+ x1="-56.8125"
+ y1="329.06256"
+ x2="-47.214466"
+ y2="329.26965" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40280"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="120.06789"
+ y2="54.6674" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40282"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40284"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,13)"
+ x1="-56.8125"
+ y1="329.06256"
+ x2="-47.214466"
+ y2="329.26965" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient38689"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-420,490.00041)"
+ x1="301.5"
+ y1="-105.87541"
+ x2="340"
+ y2="-65.250412" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient38693"
+ gradientUnits="userSpaceOnUse"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient38695"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(6,0)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient38697"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,6)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient38701"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(6,6)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-7"
+ id="linearGradient38703"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(24,-6)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38706"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,-1,-157,821.03125)"
+ x1="-90.5"
+ y1="413.51562"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient38720"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3846148,0,0,1,-211.38442,490.00041)"
+ x1="301.5"
+ y1="-105.87541"
+ x2="340"
+ y2="-65.250412" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient38723"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(8,0)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient38725"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(8,6)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-7"
+ id="linearGradient38727"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(24,-6)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38729"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,-1,-156,821.03125)"
+ x1="-89.75"
+ y1="413.98114"
+ x2="-86.75"
+ y2="416.32614" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-7"
+ id="linearGradient38731"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(24,-2.4825165)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38736"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,-1,-156,824.54874)"
+ x1="-89.75"
+ y1="413.98114"
+ x2="-86.75"
+ y2="416.32614" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient39199"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-420,490.00041)"
+ x1="301.5"
+ y1="-105.87541"
+ x2="340"
+ y2="-65.250412" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39201"
+ gradientUnits="userSpaceOnUse"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39203"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(6,0)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39205"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,6)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39207"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(6,6)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient39246"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-420,490.00041)"
+ x1="301.5"
+ y1="-105.87541"
+ x2="340"
+ y2="-65.250412" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39248"
+ gradientUnits="userSpaceOnUse"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39252"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(6,0)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39255"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,6)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39259"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(6,6)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-83"
+ id="linearGradient38961"
+ gradientUnits="userSpaceOnUse"
+ x1="488.5"
+ y1="568"
+ x2="495"
+ y2="568" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask38956">
+ <rect
+ style="fill:url(#linearGradient38961);stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect38958"
+ width="16"
+ height="12"
+ x="488"
+ y="560"
+ rx="0"
+ ry="0" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-83"
+ id="linearGradient39115"
+ gradientUnits="userSpaceOnUse"
+ x1="487.2518"
+ y1="531.95105"
+ x2="490.65796"
+ y2="580.63715" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient11871-3"
+ id="linearGradient39117"
+ gradientUnits="userSpaceOnUse"
+ x1="496.49335"
+ y1="537.78113"
+ x2="498.40021"
+ y2="540.13623" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient11871-3"
+ id="linearGradient39119"
+ gradientUnits="userSpaceOnUse"
+ x1="495.85294"
+ y1="541.69116"
+ x2="495.25"
+ y2="539.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-3"
+ id="linearGradient39122"
+ gradientUnits="userSpaceOnUse"
+ x1="494.38467"
+ y1="532.42651"
+ x2="496.21078"
+ y2="541.02698" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40703"
+ id="linearGradient39261"
+ gradientUnits="userSpaceOnUse"
+ x1="122.25188"
+ y1="106.08706"
+ x2="147.08464"
+ y2="134.12131" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39263"
+ gradientUnits="userSpaceOnUse"
+ x1="116.75861"
+ y1="97.375854"
+ x2="145.729"
+ y2="137.52937" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient39265"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ id="linearGradient319-46">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-03" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-62" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-46"
+ id="linearGradient39508"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-20,0)"
+ x1="39.102718"
+ y1="641.73358"
+ x2="58.680996"
+ y2="661.93829" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43807"
+ id="linearGradient39518"
+ gradientUnits="userSpaceOnUse"
+ x1="648.09674"
+ y1="355.85541"
+ x2="634.09503"
+ y2="341.23715" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient39088"
+ id="linearGradient39520"
+ gradientUnits="userSpaceOnUse"
+ x1="696.63055"
+ y1="403.93069"
+ x2="643.71313"
+ y2="349.93216" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-95"
+ id="linearGradient39523"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8461524,0,0,0.8461523,99.385524,54.308237)"
+ x1="633.10468"
+ y1="338.95337"
+ x2="649.69073"
+ y2="354.92981" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39716"
+ gradientUnits="userSpaceOnUse"
+ x1="121.80637"
+ y1="106.4641"
+ x2="142.1468"
+ y2="132.44617" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient39718"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40189"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9998599,0,0,0.9960071,131.027,-79.5885)"
+ x1="57.347244"
+ y1="82.75322"
+ x2="86.00116"
+ y2="112.03586" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40202"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166695,0,0,0.9203753,136.97426,-72.21433)"
+ x1="80.60067"
+ y1="108.47212"
+ x2="68.0271"
+ y2="94.239906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40295"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166695,0,0,0.9203753,136.97426,-72.21433)"
+ x1="80.60067"
+ y1="108.47212"
+ x2="68.0271"
+ y2="94.239906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40297"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9998599,0,0,0.9960071,131.027,-79.5885)"
+ x1="57.347244"
+ y1="82.75322"
+ x2="86.00116"
+ y2="112.03586" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask40306">
+ <path
+ id="path40308"
+ d="m 195,11.00001 0,14 0.5,0 13.5,-13.5 0,-0.5 -14,0 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:none"
+ sodipodi:nodetypes="cccccc" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40703-5-5"
+ id="linearGradient39261-4-5"
+ gradientUnits="userSpaceOnUse"
+ x1="128.09367"
+ y1="112.43961"
+ x2="145.20987"
+ y2="133.4879" />
+ <linearGradient
+ id="linearGradient40703-5-5">
+ <stop
+ style="stop-color:#143564;stop-opacity:1;"
+ offset="0"
+ id="stop40705-8-2" />
+ <stop
+ style="stop-color:#c1d7f8;stop-opacity:1;"
+ offset="1"
+ id="stop40707-8-7" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient38252-9">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop38254-3" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop38256-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-74-9-1"
+ id="linearGradient40511-7-9-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,-270.46874,9.59825)"
+ x1="256.14325"
+ y1="5.6181068"
+ x2="278.79254"
+ y2="29.688427" />
+ <linearGradient
+ id="linearGradient1610-74-9-1">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-0-8-7" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-9-3-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334-8-6-5"
+ id="linearGradient40507-4-8-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-114,-208)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ id="linearGradient58334-8-6-5">
+ <stop
+ id="stop58336-8-9-2"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.87628865;" />
+ <stop
+ id="stop58338-24-8-7"
+ offset="1.0000000"
+ style="stop-color:#fffffe;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-5-6-1"
+ id="radialGradient40649-2-6-6"
+ cx="-27.749987"
+ cy="32.615383"
+ fx="-27.749987"
+ fy="32.615383"
+ r="5.5"
+ gradientTransform="matrix(0.4545454,0.3636364,-0.3862167,0.4827711,-2.5397644,26.345139)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-5-6-1">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-17-2-4" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-11-3-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-5-6-1"
+ id="linearGradient40502-7-8-3"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-784,-271)"
+ x1="754"
+ y1="300.5"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-5-6-2"
+ id="linearGradient40635-7-2-2"
+ gradientUnits="userSpaceOnUse"
+ x1="125.99933"
+ y1="111.2683"
+ x2="134.91479"
+ y2="122.36016" />
+ <linearGradient
+ id="linearGradient319-5-6-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-761-2-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-89-7-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-5-6-2"
+ id="linearGradient40637-9-5-8"
+ gradientUnits="userSpaceOnUse"
+ x1="126.72586"
+ y1="112.53999"
+ x2="134.91479"
+ y2="122.36016" />
+ <filter
+ inkscape:collect="always"
+ id="filter13996-9-7-7"
+ x="-0.23644176"
+ width="1.4728835"
+ y="-0.24368355"
+ height="1.4873672"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.29550651"
+ id="feGaussianBlur13998-5-8-6" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13973-3-7-8"
+ id="linearGradient40639-1-2-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(19.367382,0)"
+ x1="111.2239"
+ y1="112.62726"
+ x2="99.628899"
+ y2="99.029617" />
+ <linearGradient
+ id="linearGradient13973-3-7-8">
+ <stop
+ style="stop-color:#3c4c18;stop-opacity:1;"
+ offset="0"
+ id="stop13975-1-8-9" />
+ <stop
+ style="stop-color:#9aff31;stop-opacity:0;"
+ offset="1"
+ id="stop13977-2-0-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-5-6-2"
+ id="linearGradient40641-9-2-7"
+ gradientUnits="userSpaceOnUse"
+ x1="127.63637"
+ y1="114.2303"
+ x2="143.69765"
+ y2="131.03783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-74-9-1"
+ id="linearGradient41638-8-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,-270.46874,9.59825)"
+ x1="256.14325"
+ y1="5.6181068"
+ x2="278.79254"
+ y2="29.688427" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334-8-6-5"
+ id="linearGradient41640-2-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-114,-208)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-5-6-1"
+ id="radialGradient41642-5-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4545454,0.3636364,-0.3862167,0.4827711,-2.5397644,26.345139)"
+ cx="-27.749987"
+ cy="32.615383"
+ fx="-27.749987"
+ fy="32.615383"
+ r="5.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-5-6-1"
+ id="linearGradient41644-5-4"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-784,-271)"
+ x1="754"
+ y1="300.5"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-3-0-7-6"
+ id="linearGradient40875-3-9-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.695652,0,0,0.869703,-44.93485,-114.66358)"
+ x1="188.77448"
+ y1="259.745"
+ x2="164.0939"
+ y2="242.22473" />
+ <linearGradient
+ id="linearGradient37542-3-0-7-6">
+ <stop
+ id="stop37544-1-6-6-5"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-2-1-7-0"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-34-8-7-0"
+ id="linearGradient40877-5-5-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(357.00001,373)"
+ x1="-287.75"
+ y1="-276.75"
+ x2="-276"
+ y2="-264.875" />
+ <linearGradient
+ id="linearGradient319-34-8-7-0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-11-9-8-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-38-3-1-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-3-0-7-6"
+ id="linearGradient40879-9-8-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.608695,0,0,0.760996,-26.1305,-84.76968)"
+ x1="130.70929"
+ y1="210.78392"
+ x2="171.50414"
+ y2="248.54021" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-34-8-7-0"
+ id="linearGradient40881-8-0-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(361.00001,376)"
+ x1="-283"
+ y1="-272"
+ x2="-277.01501"
+ y2="-267.26749" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-7-6-7-4"
+ id="radialGradient40883-4-0-3"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.06118084,-0.8594818,2.4629674,-0.1753088,-259.40057,190.15309)"
+ cx="77.721619"
+ cy="104.09358"
+ fx="77.721619"
+ fy="104.09358"
+ r="3.9999998" />
+ <linearGradient
+ id="linearGradient10069-7-6-7-4">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-81-3-2-4" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-6-7-5-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-3-0-7-6"
+ id="linearGradient39136-2-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.695652,0,0,0.869703,-44.93485,-114.66358)"
+ x1="188.77448"
+ y1="259.745"
+ x2="164.0939"
+ y2="242.22473" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-34-8-7-0"
+ id="linearGradient39138-8-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(357.00001,373)"
+ x1="-287.75"
+ y1="-276.75"
+ x2="-276"
+ y2="-264.875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-3-0-7-6"
+ id="linearGradient39140-6-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.608695,0,0,0.760996,-26.1305,-84.76968)"
+ x1="130.70929"
+ y1="210.78392"
+ x2="174.35753"
+ y2="250.6842" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-34-8-7-0"
+ id="linearGradient39143-0-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(361.00001,376)"
+ x1="-283"
+ y1="-272"
+ x2="-277.01501"
+ y2="-267.26749" />
+ <linearGradient
+ id="linearGradient319-17-1-6">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-115-1-5" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-27-3-7" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-17-1-6"
+ id="linearGradient40679"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.7972867,-259.00009,90.24189)"
+ x1="255.63673"
+ y1="99.513062"
+ x2="275.1503"
+ y2="129.36641" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient25417"
+ id="linearGradient40731"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.997161,-259.00079,67.35344)"
+ x1="280.0918"
+ y1="129.28557"
+ x2="267.20212"
+ y2="116.41341" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-17-1-6"
+ id="linearGradient40733"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.7972867,-259.00009,90.24189)"
+ x1="255.63673"
+ y1="99.513062"
+ x2="275.1503"
+ y2="129.36641" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-17-1-6-7"
+ id="linearGradient40733-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.7972867,-259.00009,90.24189)"
+ x1="255.63673"
+ y1="99.513062"
+ x2="275.1503"
+ y2="129.36641" />
+ <linearGradient
+ id="linearGradient319-17-1-6-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-115-1-5-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-27-3-7-7" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-17-1-6-8"
+ id="linearGradient40733-03"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.7972867,-259.00009,90.24189)"
+ x1="255.63673"
+ y1="99.513062"
+ x2="275.1503"
+ y2="129.36641" />
+ <linearGradient
+ id="linearGradient319-17-1-6-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-115-1-5-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-27-3-7-1" />
+ </linearGradient>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath40897">
+ <rect
+ y="198"
+ x="-41"
+ height="16"
+ width="15"
+ id="rect40899"
+ style="opacity:0.45;fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="scale(-1,1)" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath40902">
+ <rect
+ y="197"
+ x="-22"
+ height="17"
+ width="15"
+ id="rect40904"
+ style="opacity:0.45;fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="scale(-1,1)" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient38478"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(254.01612,-211.00101)"
+ x1="96.824379"
+ y1="393.90298"
+ x2="94.246101"
+ y2="391.21976" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask38474">
+ <rect
+ style="fill:url(#linearGradient38478);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect38476"
+ width="15"
+ height="15"
+ x="343.01611"
+ y="174.99901" />
+ </mask>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient44318"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.050372,0,0,1.050372,-3.551238,-0.730396)"
+ cx="70.5"
+ cy="14.5"
+ fx="70.5"
+ fy="14.5"
+ r="1.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient44320"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5399935,0.3131662,-0.3907892,0.5793905,38.141764,-16.056748)"
+ cx="70.470596"
+ cy="14.649424"
+ fx="70.470596"
+ fy="14.649424"
+ r="5.5192375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-19"
+ id="linearGradient42988"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="121.22078"
+ y2="56.357628" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-19"
+ id="linearGradient42990"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(207,-246.99988)"
+ x1="-56.5"
+ y1="342.0625"
+ x2="-49"
+ y2="341" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-8-3-3"
+ id="linearGradient42992"
+ gradientUnits="userSpaceOnUse"
+ x1="126.55782"
+ y1="113.57294"
+ x2="132.41052"
+ y2="118.81034" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-95-2-7"
+ id="linearGradient42994"
+ gradientUnits="userSpaceOnUse"
+ x1="132"
+ y1="117.26753"
+ x2="142.72656"
+ y2="127.72736" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-8-3-3"
+ id="linearGradient42996"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(4.9999967,20)"
+ x1="-114.75"
+ y1="546.5"
+ x2="-110.5"
+ y2="542.5" />
+ <linearGradient
+ id="linearGradient44627">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop44629" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop44631" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069-9-7-4-74">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-5-4-5-0" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-43-0-5-9" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient44939-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop44941-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop44943-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient44402"
+ gradientUnits="userSpaceOnUse"
+ x1="351.15625"
+ y1="108.35222"
+ x2="345.40625"
+ y2="108.00847" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient44404"
+ gradientUnits="userSpaceOnUse"
+ x1="351.71875"
+ y1="106.93575"
+ x2="347.1875"
+ y2="106.7795" />
+ <filter
+ inkscape:collect="always"
+ id="filter44473"
+ x="-0.12578467"
+ width="1.2515693"
+ y="-0.11472401"
+ height="1.229448"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.81235925"
+ id="feGaussianBlur44475" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter44477"
+ x="-0.12176471"
+ width="1.2435294"
+ y="-0.11828571"
+ height="1.2365714"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.8625"
+ id="feGaussianBlur44479" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient44485"
+ gradientUnits="userSpaceOnUse"
+ x1="279.75"
+ y1="101.5"
+ x2="284.5"
+ y2="106.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient44942"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-21)"
+ x1="351.71875"
+ y1="106.93575"
+ x2="339.125"
+ y2="105.092" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient44944"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,-1,698,183)"
+ x1="351.15625"
+ y1="108.35222"
+ x2="336.40625"
+ y2="106.19597" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient44950"
+ gradientUnits="userSpaceOnUse"
+ x1="279"
+ y1="102"
+ x2="281.75"
+ y2="102"
+ gradientTransform="matrix(-1,0,0,1,593.02125,-1.8e-6)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient44954"
+ gradientUnits="userSpaceOnUse"
+ x1="279.75"
+ y1="101.5"
+ x2="283"
+ y2="105.5"
+ gradientTransform="matrix(0,1,1,0,225,-182.99437)" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath45147">
+ <path
+ sodipodi:nodetypes="ccccccccccccccccccccccc"
+ id="path45149"
+ d="m 5,261 13,0 0,1 -1,0 0,1 1,0 0,1 -1,0 0,1 -1,0 0,2 2,0 0,-1 1,0 0,-1 1,0 0,1 1,0 0,-1 1,0 0,13 -17,0 0,-17 z"
+ style="opacity:0.2;fill:#3771c8;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.0999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient45220"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,221,10)"
+ x1="115.84575"
+ y1="10.8125"
+ x2="106.125"
+ y2="19.9375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38252-9"
+ id="linearGradient45283"
+ gradientUnits="userSpaceOnUse"
+ x1="125.86876"
+ y1="111.85698"
+ x2="130.88379"
+ y2="121.70699" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38252-9"
+ id="linearGradient45285"
+ gradientUnits="userSpaceOnUse"
+ x1="134.78751"
+ y1="122.29202"
+ x2="132.60205"
+ y2="117.96092" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-4-74"
+ id="radialGradient45309"
+ cx="336.42892"
+ cy="611.10455"
+ fx="336.42892"
+ fy="611.10455"
+ r="5.9852905"
+ gradientTransform="matrix(1.0070601,0.03386866,-0.03770425,1.1211085,20.665977,-85.772965)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44627"
+ id="linearGradient43826"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,1444.9824,-215)"
+ x1="689.47357"
+ y1="427"
+ x2="685.47357"
+ y2="427" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask43822">
+ <rect
+ y="208"
+ x="754"
+ height="9"
+ width="12"
+ id="rect43824"
+ style="opacity:0.93999993;fill:url(#linearGradient43826);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient43856"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,61.53822,346.48241)"
+ x1="246.89435"
+ y1="-4.4418921"
+ x2="277.68143"
+ y2="30.743095" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient43858"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(218.01612,129)"
+ x1="87.03125"
+ y1="241"
+ x2="92.8125"
+ y2="245.625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient46780"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,140,-415)"
+ x1="172.5625"
+ y1="601.5"
+ x2="159.13864"
+ y2="585.28772" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient46782"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,237.98388,150.25)"
+ x1="249.64528"
+ y1="1.5973248"
+ x2="271.98389"
+ y2="35.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient46784"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,140,-415)"
+ x1="172.5625"
+ y1="601.5"
+ x2="159.13864"
+ y2="585.28772" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient46786"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,237.98388,150.25)"
+ x1="249.64528"
+ y1="1.5973248"
+ x2="271.98389"
+ y2="35.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient46818"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,140,-415)"
+ x1="172.5625"
+ y1="601.5"
+ x2="159.13864"
+ y2="585.28772" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient46820"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,237.98388,150.25)"
+ x1="249.64528"
+ y1="1.5973248"
+ x2="271.98389"
+ y2="35.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient46822"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,140,-415)"
+ x1="172.5625"
+ y1="601.5"
+ x2="159.13864"
+ y2="585.28772" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient46824"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,237.98388,150.25)"
+ x1="249.64528"
+ y1="1.5973248"
+ x2="271.98389"
+ y2="35.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient46990"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,140,-415)"
+ x1="172.5625"
+ y1="601.5"
+ x2="159.13864"
+ y2="585.28772" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient46992"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,237.98388,150.25)"
+ x1="249.64528"
+ y1="1.5973248"
+ x2="271.98389"
+ y2="35.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient46994"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,140,-415)"
+ x1="172.5625"
+ y1="601.5"
+ x2="159.13864"
+ y2="585.28772" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient46996"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,237.98388,150.25)"
+ x1="249.64528"
+ y1="1.5973248"
+ x2="271.98389"
+ y2="35.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient46998"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,140,-415)"
+ x1="172.5625"
+ y1="601.5"
+ x2="159.13864"
+ y2="585.28772" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient47000"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,237.98388,150.25)"
+ x1="249.64528"
+ y1="1.5973248"
+ x2="271.98389"
+ y2="35.75" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient25048"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5274943,0,0,0.7696585,194.81546,86.715119)"
+ cx="412.10059"
+ cy="375.96332"
+ fx="412.10059"
+ fy="375.96332"
+ r="4.4262571" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient25108"
+ id="linearGradient25106"
+ gradientUnits="userSpaceOnUse"
+ x1="408.91928"
+ y1="373.01221"
+ x2="410.55432"
+ y2="375.5058" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient25108"
+ id="linearGradient25117"
+ gradientUnits="userSpaceOnUse"
+ x1="411.05389"
+ y1="375.39175"
+ x2="407.62576"
+ y2="370.21317" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient25449"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,-346.7085,428.4841)"
+ x1="352.98236"
+ y1="314.11398"
+ x2="353.72073"
+ y2="297.92099" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient25108"
+ id="linearGradient25451"
+ gradientUnits="userSpaceOnUse"
+ x1="436.54755"
+ y1="524.30481"
+ x2="434.49387"
+ y2="519.46057" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient25108"
+ id="linearGradient25453"
+ gradientUnits="userSpaceOnUse"
+ x1="432.0849"
+ y1="524.97125"
+ x2="433"
+ y2="526" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient25457"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5274943,0,0,0.7696585,194.81546,86.715119)"
+ cx="410.73904"
+ cy="370.11554"
+ fx="410.73904"
+ fy="370.11554"
+ r="4.4262571" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient23543"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,1,0,225,-182.99437)"
+ x1="279.75"
+ y1="101.5"
+ x2="283"
+ y2="105.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient23557"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,1,0,225,-182.99437)"
+ x1="279"
+ y1="102"
+ x2="281.75"
+ y2="102" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient23559"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,1,0,225,-182.99437)"
+ x1="292.25"
+ y1="106.5"
+ x2="289.5"
+ y2="109.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24343"
+ id="linearGradient24341"
+ x1="413.9498"
+ y1="386.45807"
+ x2="406.7699"
+ y2="374.42419"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24343"
+ id="linearGradient24349"
+ gradientUnits="userSpaceOnUse"
+ x1="403.9577"
+ y1="367.62839"
+ x2="413.98795"
+ y2="374.07153" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient21327-6"
+ id="radialGradient24354"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6402148,-1.1088846,0.8413297,0.4857498,104.42892,800.46622)"
+ cx="409.55594"
+ cy="52.367992"
+ fx="409.55594"
+ fy="52.367992"
+ r="3.8798895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient34157"
+ id="linearGradient24511"
+ gradientUnits="userSpaceOnUse"
+ x1="270.66064"
+ y1="68.113258"
+ x2="257.38638"
+ y2="81.382545" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24513"
+ gradientUnits="userSpaceOnUse"
+ x1="256.90005"
+ y1="80.100891"
+ x2="262.43726"
+ y2="74.562462" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient24515"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient24517"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient24519"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6691529,0,4.3047361e-8,0.6954014,84.50351,24.951375)"
+ cx="259.02887"
+ cy="77.962585"
+ fx="259.02887"
+ fy="77.962585"
+ r="3.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient24523"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.3879142,0,8.9286134e-8,1.4423572,-101.87942,-32.970267)"
+ cx="259.55096"
+ cy="77.188034"
+ fx="259.55096"
+ fy="77.188034"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30321"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)"
+ x1="240.70209"
+ y1="-9.4293213"
+ x2="276.89801"
+ y2="31.515814" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient30323"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-47.00001,58.00194)"
+ x1="160.14388"
+ y1="376.27383"
+ x2="174.29811"
+ y2="383.69843" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30368"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)"
+ x1="236.94902"
+ y1="-14.103641"
+ x2="276.89801"
+ y2="31.515814" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient30370"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-47.00001,58.00194)"
+ x1="160.14388"
+ y1="376.27383"
+ x2="174.29811"
+ y2="383.69843" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30208"
+ id="linearGradient25056"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1297,-948)"
+ x1="1663.8125"
+ y1="722"
+ x2="1661.8125"
+ y2="726.37006" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19425"
+ id="radialGradient25058"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.1378252,-0.2988982,2.5269117,1.1651875,-1689.2674,-563.64056)"
+ cx="1662.2664"
+ cy="722.19189"
+ fx="1662.2664"
+ fy="722.19189"
+ r="5.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient25060"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,-1256.7473,-918.72044)"
+ x1="1984.3658"
+ y1="827.77124"
+ x2="1979.2772"
+ y2="827.32849" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient29407"
+ gradientUnits="userSpaceOnUse"
+ x1="98.858559"
+ y1="80.045052"
+ x2="135.00615"
+ y2="122.92735" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient29409"
+ gradientUnits="userSpaceOnUse"
+ x1="130.75166"
+ y1="245.03757"
+ x2="129.24866"
+ y2="243.31177" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient29411"
+ gradientUnits="userSpaceOnUse"
+ x1="126.37006"
+ y1="112.31642"
+ x2="144.22272"
+ y2="129.82761" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient29413"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ id="linearGradient44939-8-7-1-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop44941-8-4-5-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop44943-2-0-2-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-7"
+ id="linearGradient37396-1"
+ gradientUnits="userSpaceOnUse"
+ x1="389.73953"
+ y1="220.84622"
+ x2="389.59052"
+ y2="248.09296"
+ gradientTransform="matrix(-1,0,0,1,780.92531,0)" />
+ <linearGradient
+ id="linearGradient37542-7">
+ <stop
+ id="stop37544-40"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-94"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-5"
+ id="linearGradient15742-5"
+ 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="linearGradient37542-5">
+ <stop
+ id="stop37544-1"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-71"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27854"
+ id="linearGradient27860"
+ x1="392.02036"
+ y1="241.13428"
+ x2="386.30408"
+ y2="241.31801"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient27872"
+ gradientUnits="userSpaceOnUse"
+ x1="392.0101"
+ y1="224.99998"
+ x2="392.0101"
+ y2="249.99998"
+ gradientTransform="matrix(-1,0,0,1,782.02022,0)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27854"
+ id="linearGradient27874"
+ 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"
+ xlink:href="#linearGradient37542-5"
+ id="linearGradient27886"
+ 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
+ inkscape:collect="always"
+ xlink:href="#linearGradient27896"
+ id="linearGradient27902"
+ x1="388.70071"
+ y1="244.85669"
+ x2="391.17557"
+ y2="249.54126"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient10069-9-71">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-5-1" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-43-5" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient23974-2">
+ <stop
+ id="stop23976-2"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop23978-1"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath28964">
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ sodipodi:nodetypes="ccccc"
+ style="fill:url(#linearGradient28968);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;enable-background:new"
+ d="m 117.50984,228.63415 0,-15.01646 11.71735,5.49383 0,15.38271 -11.71735,-5.86008 z"
+ id="path28966" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974-2"
+ id="linearGradient28968"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.4646688,0,0,1.4650206,168.77325,-157.03253)"
+ x1="-38.103703"
+ y1="266.11719"
+ x2="-20.826464"
+ y2="253.23859" />
+ <linearGradient
+ id="linearGradient319-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-761" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-7"
+ id="linearGradient29424"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.4646688,0,0,1.4650206,168.77325,-157.03253)"
+ x1="-26.511335"
+ y1="257.99881"
+ x2="-30.075666"
+ y2="259.87677" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask29419">
+ <path
+ id="path29422"
+ d="m 117.50984,229.00041 0,-15.38272 11.71735,5.49383 0,15.74897 -11.71735,-5.86008 z"
+ style="opacity:0.5;fill:url(#linearGradient29424);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;enable-background:new"
+ sodipodi:nodetypes="ccccc"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient29988"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,10)"
+ x1="-35.153767"
+ y1="271.58572"
+ x2="-23.636715"
+ y2="252.03563" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-5"
+ id="linearGradient29990"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-113.93222,176.71918)"
+ x1="446.93222"
+ y1="105.28082"
+ x2="441.93222"
+ y2="120.28082" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-71"
+ id="linearGradient29994"
+ gradientUnits="userSpaceOnUse"
+ x1="123.80045"
+ y1="111.03492"
+ x2="131.72171"
+ y2="118.18078" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient21327-6-8"
+ id="linearGradient29773-5"
+ gradientUnits="userSpaceOnUse"
+ x1="124.78239"
+ y1="111.13178"
+ x2="132.99687"
+ y2="118.98331" />
+ <linearGradient
+ id="linearGradient21327-6-8">
+ <stop
+ style="stop-color:#1e3e70;stop-opacity:1;"
+ offset="0"
+ id="stop21329-3-4" />
+ <stop
+ style="stop-color:#1e3e70;stop-opacity:0;"
+ offset="1"
+ id="stop21331-4-0" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient28526">
+ <stop
+ id="stop28528"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop28530"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-62">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-90" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610-52-2">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-32-8" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-46-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-62-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-90-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-4-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient29334"
+ gradientUnits="userSpaceOnUse"
+ x1="121.74819"
+ y1="104.14172"
+ x2="140.18503"
+ y2="126.89457" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient29336"
+ gradientUnits="userSpaceOnUse"
+ x1="155.10138"
+ y1="91.071259"
+ x2="122.40444"
+ y2="127.60542" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24000"
+ id="linearGradient29338"
+ gradientUnits="userSpaceOnUse"
+ x1="124.66362"
+ y1="126.19594"
+ x2="132"
+ y2="118" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient29340"
+ gradientUnits="userSpaceOnUse"
+ x1="124.28249"
+ y1="126.88889"
+ x2="133.53401"
+ y2="116.55647" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient29342"
+ gradientUnits="userSpaceOnUse"
+ x1="147.25899"
+ y1="101.45953"
+ x2="130.82327"
+ y2="119.554" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient28574"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,-1,0,449.99999,1678)"
+ x1="1138.1963"
+ y1="287.70486"
+ x2="1146.6705"
+ y2="288.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient28577"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,-1,0,558.99999,1286)"
+ x1="757.2467"
+ y1="367.52411"
+ x2="740.30865"
+ y2="405.3895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient28580"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,-1,0,558.99999,1288)"
+ x1="745.48267"
+ y1="396.45972"
+ x2="737.62225"
+ y2="401.90442" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient28583"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,-239.00001,1286)"
+ x1="743"
+ y1="402"
+ x2="752"
+ y2="400" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38845"
+ id="linearGradient28589"
+ gradientUnits="userSpaceOnUse"
+ x1="162.41054"
+ y1="413.87982"
+ x2="161.83331"
+ y2="406.47784"
+ gradientTransform="matrix(0,1,-1,0,574.99991,384.00001)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38831"
+ id="linearGradient28593"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,-1,0,558.99999,1288)"
+ x1="743.87036"
+ y1="396.04428"
+ x2="744.1059"
+ y2="423.54419" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient28600"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,719.99999,383.00001)"
+ x1="148.56801"
+ y1="544.21143"
+ x2="163.11441"
+ y2="569.18829" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38831"
+ id="linearGradient28603"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,-1,0,449.99999,1678)"
+ x1="1141.2856"
+ y1="288.19919"
+ x2="1146.2682"
+ y2="291.35333" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-52-2"
+ id="radialGradient29805"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.94105289,0.01178942,-0.01073736,0.8570756,238.4669,249.70522)"
+ cx="-30.028414"
+ cy="19.425121"
+ fx="-30.028414"
+ fy="19.425121"
+ r="7" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask29801">
+ <rect
+ style="opacity:0.35;color:#000000;fill:url(#radialGradient29805);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.71217775;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ id="rect29803"
+ width="15"
+ height="16"
+ x="204"
+ y="257" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-7"
+ id="linearGradient29884"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,780.92531,0)"
+ x1="389.73953"
+ y1="220.84622"
+ x2="389.59052"
+ y2="248.09296" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient29886"
+ gradientUnits="userSpaceOnUse"
+ x1="391.62881"
+ y1="243.48854"
+ x2="386.13718"
+ y2="244.68996" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath50172-0">
+ <path
+ id="path50174-8"
+ d="m -177.34375,498 a 1.001098,1.001098 0 1 0 0.0937,2 l 3.65625,0 -4.25,5.9375 a 1.0001,1.0001 0 0 0 -0.1875,0.59375 l 0,0.5 a 1.0001,1.0001 0 0 0 1,1 L -171.75,508 a 1.0001,1.0001 0 1 0 0,-2 l -3.6875,0.0312 4.25,-5.9375 A 1.0001,1.0001 0 0 0 -171,499.5 l 0,-0.5 a 1.0001,1.0001 0 0 0 -1,-1 l -5.25,0 a 1.0001,1.0001 0 0 0 -0.0937,0 z"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans" />
+ </clipPath>
+ <filter
+ color-interpolation-filters="sRGB"
+ inkscape:collect="always"
+ id="filter50168-9"
+ x="-0.26459751"
+ width="1.529195"
+ y="-0.21958679"
+ height="1.4391736">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.0769376"
+ id="feGaussianBlur50170-2" />
+ </filter>
+ <radialGradient
+ id="radialGradient16142-7"
+ cx="20.892099"
+ cy="64.567902"
+ r="5.257"
+ fx="20.892099"
+ fy="64.567902"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ offset="0"
+ style="stop-color:#F0F0F0"
+ id="stop16144-4" />
+ <stop
+ offset="1"
+ style="stop-color:#474747"
+ id="stop16146-0" />
+ </radialGradient>
+ <linearGradient
+ id="linearGradient37542-78">
+ <stop
+ id="stop37544-2"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-78"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient9030-2">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop9032-0" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop9034-89" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37542-04-82">
+ <stop
+ id="stop37544-9-0"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-4-5"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient9030-38-2">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop9032-6-7" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop9034-9-6" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient30766-8"
+ inkscape:collect="always">
+ <stop
+ id="stop30768-7"
+ offset="0"
+ style="stop-color:#be0000;stop-opacity:1" />
+ <stop
+ id="stop30770-8"
+ offset="1"
+ style="stop-color:#ff5108;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient30752-0">
+ <stop
+ style="stop-color:#0c1b63;stop-opacity:1;"
+ offset="0"
+ id="stop30754-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1"
+ id="stop30756-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32140"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-64,-10)"
+ x1="18.773417"
+ y1="6.2494373"
+ x2="6.9718256"
+ y2="17.82831" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32142"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.701513,0.712657,0.712657,0.701513,50.5916,-449.6745)"
+ x1="385.62408"
+ y1="244.3396"
+ x2="401.63013"
+ y2="244.38875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32144"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-65.00001,-10.749995)"
+ x1="61.032951"
+ y1="5.9830923"
+ x2="46.491322"
+ y2="20.147326" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32146"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.199998,0,0,1.199999,-74.19988,-12.499988)"
+ x1="59.02124"
+ y1="6.0129876"
+ x2="44.509518"
+ y2="20.110929" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32148"
+ gradientUnits="userSpaceOnUse"
+ x1="47.348152"
+ y1="-25.553123"
+ x2="53.567928"
+ y2="-31.095215" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#radialGradient16142-7"
+ id="linearGradient31946"
+ gradientUnits="userSpaceOnUse"
+ x1="-176.1799"
+ y1="508.33572"
+ x2="-193.07495"
+ y2="482.27924" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#radialGradient16142"
+ id="linearGradient31948"
+ gradientUnits="userSpaceOnUse"
+ x1="-178.00789"
+ y1="505.36523"
+ x2="-194.90294"
+ y2="479.30875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-78"
+ id="linearGradient31950"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,-7.152175,20.92167)"
+ x1="155.37498"
+ y1="230.51552"
+ x2="181.25543"
+ y2="269.24564" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030-2"
+ id="linearGradient31952"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(81.000002,13.499998)"
+ x1="87.765625"
+ y1="242.39062"
+ x2="96"
+ y2="251.40294" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-04-82"
+ id="linearGradient31954"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,-354.13606,119.42158)"
+ x1="148.47061"
+ y1="217.28368"
+ x2="171.77303"
+ y2="250.87756" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030-38-2"
+ id="linearGradient31956"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(81.000002,13.499998)"
+ x1="-259.99872"
+ y1="340.81195"
+ x2="-253.90541"
+ y2="345.10736" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30766-8"
+ id="linearGradient31958"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0017964,0,0,0.99629977,-0.31613165,0.94171311)"
+ x1="167.51979"
+ y1="252.44223"
+ x2="170.78137"
+ y2="261.69635" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030-2"
+ id="linearGradient31960"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(81.000002,13.499998)"
+ x1="87.473038"
+ y1="238.21507"
+ x2="89.889603"
+ y2="243.80345" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30752-0"
+ id="linearGradient31962"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,10)"
+ x1="168.53265"
+ y1="244.52007"
+ x2="168.53265"
+ y2="239.5473" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient31964"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-237.5,45.5045)"
+ x1="263.35254"
+ y1="19.495501"
+ x2="275.43362"
+ y2="28.583914" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient31966"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-238,44.0045)"
+ x1="271.69839"
+ y1="22.713789"
+ x2="283.37738"
+ y2="36.874088" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient31968"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-243.5,51.5045)"
+ x1="260.25369"
+ y1="11.017987"
+ x2="275.43362"
+ y2="28.583914" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient31970"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-244,50.0045)"
+ x1="271.69839"
+ y1="22.713789"
+ x2="283.37738"
+ y2="36.874088" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31972"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-57.00003,-165.99191)"
+ x1="85.853188"
+ y1="239.5473"
+ x2="90.563423"
+ y2="242.99191" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31974"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-51,-172)"
+ x1="88"
+ y1="240.90625"
+ x2="92.8125"
+ y2="245.625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient28526"
+ id="linearGradient32236"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(423,225)"
+ x1="-175.72238"
+ y1="66.323799"
+ x2="-183.03308"
+ y2="66.235535" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20055-8-4"
+ id="linearGradient32238"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(423,225)"
+ x1="-174.51762"
+ y1="66.654762"
+ x2="-183.58472"
+ y2="65.917358" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-62"
+ id="linearGradient32240"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9098462,0,0,0.9414558,406.86085,228.58514)"
+ x1="-180.7581"
+ y1="63.445515"
+ x2="-169.07387"
+ y2="62.182106" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-62-8"
+ id="linearGradient32242"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2857143,0,0,0.787037,371.28571,304.80092)"
+ x1="-101"
+ y1="-16"
+ x2="-96.861107"
+ y2="-15.138513" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-62-8"
+ id="linearGradient32244"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2857143,0,0,0.787037,371.28571,304.80092)"
+ x1="-101"
+ y1="-16"
+ x2="-96.705353"
+ y2="-15.562586" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29312"
+ id="linearGradient32246"
+ gradientUnits="userSpaceOnUse"
+ x1="242.99834"
+ y1="291.5047"
+ x2="244.75"
+ y2="291.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29304"
+ id="linearGradient32248"
+ gradientUnits="userSpaceOnUse"
+ x1="245.20622"
+ y1="294.49902"
+ x2="243.5"
+ y2="294.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32296"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-52.983883,-129)"
+ x1="258"
+ y1="388"
+ x2="273"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32299"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-48.983883,-126)"
+ x1="259.75"
+ y1="388"
+ x2="273"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32301"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-47.000005,-120)"
+ x1="257.75"
+ y1="388"
+ x2="272"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32303"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166695,0,0,0.9203753,-9.025729,344.78566)"
+ x1="80.60067"
+ y1="108.47212"
+ x2="68.0271"
+ y2="94.239906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13938"
+ id="linearGradient32305"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-14.983875,337)"
+ x1="68.361542"
+ y1="95.337166"
+ x2="88.785263"
+ y2="116.62141" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32307"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9998599,0,0,0.9960071,-15.972985,338.41149)"
+ x1="58.761654"
+ y1="84.330009"
+ x2="81.383331"
+ y2="108.06429" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient32353"
+ gradientUnits="userSpaceOnUse"
+ x1="114.15679"
+ y1="100.93772"
+ x2="137.5759"
+ y2="124.47867" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32355"
+ gradientUnits="userSpaceOnUse"
+ x1="131.12576"
+ y1="118"
+ x2="140.19273"
+ y2="125.82862" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32357"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9050931,-7.9558708e-4,0.00612764,0.9147058,39.488451,313.56226)"
+ x1="299.70026"
+ y1="408.49368"
+ x2="322.08145"
+ y2="429.53806" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32359"
+ gradientUnits="userSpaceOnUse"
+ x1="131.12576"
+ y1="118"
+ x2="140.19273"
+ y2="125.82862" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient32426"
+ gradientUnits="userSpaceOnUse"
+ x1="114.15679"
+ y1="100.93772"
+ x2="137.5759"
+ y2="124.47867" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32428"
+ gradientUnits="userSpaceOnUse"
+ x1="131.12576"
+ y1="118"
+ x2="140.19273"
+ y2="125.82862" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient32430"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32432"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.77915445,-6.9426235e-4,0.00527501,0.79821029,158.94945,341.39422)"
+ x1="299.70026"
+ y1="408.49368"
+ x2="322.08145"
+ y2="429.53806" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8-7-1-7"
+ id="linearGradient32434"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,73,792.5)"
+ x1="346"
+ y1="128.5"
+ x2="368"
+ y2="123.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31019"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,257.1483,118.6716)"
+ x1="85.548706"
+ y1="100.22395"
+ x2="85.347076"
+ y2="113.09817" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31025"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.72300056,-0.72300056,0.72300056,0.72300056,254.24127,118.38327)"
+ x1="85.548706"
+ y1="100.22395"
+ x2="85.347076"
+ y2="113.09817" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31055"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,257.1483,118.6716)"
+ x1="85.548706"
+ y1="100.22395"
+ x2="85.347076"
+ y2="113.09817" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31057"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.72300056,-0.72300056,0.72300056,0.72300056,254.24127,118.38327)"
+ x1="85.548706"
+ y1="100.22395"
+ x2="85.347076"
+ y2="113.09817" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31151"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,257.1483,118.6716)"
+ x1="85.548706"
+ y1="100.22395"
+ x2="85.347076"
+ y2="113.09817" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31153"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.72300056,-0.72300056,0.72300056,0.72300056,254.24127,118.38327)"
+ x1="85.548706"
+ y1="100.22395"
+ x2="84.95932"
+ y2="122.23821" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30958"
+ id="linearGradient31155"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,257.14826,118.6716)"
+ x1="85.861206"
+ y1="99.348953"
+ x2="85.60022"
+ y2="105.88815" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30958"
+ id="linearGradient31157"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.74301467,-0.74301467,0.74301467,0.74301467,250.58064,118.02214)"
+ x1="85.861206"
+ y1="99.348953"
+ x2="85.60022"
+ y2="105.88815" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-7409-7-7-19-1"
+ id="linearGradient32854-6-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.1666676,0,0,-1.1666676,119.15081,827.66691)"
+ x1="262.04343"
+ y1="233.0448"
+ x2="273.85818"
+ y2="247.32738" />
+ <linearGradient
+ id="linearGradient37542-7409-7-7-19-1">
+ <stop
+ id="stop37544-48-6-1-8-9"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-82-1-0-6-8"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8-4-7-8-3-0-3"
+ id="linearGradient32856-3-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.53706486,0,0,0.53706486,-249.10439,522.04547)"
+ x1="97.616623"
+ y1="39.47208"
+ x2="94.157646"
+ y2="35.759052" />
+ <linearGradient
+ id="linearGradient44939-8-4-7-8-3-0-3">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop44941-8-5-40-2-4-2-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop44943-2-5-9-4-9-8-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-5-4-6-5-0-3"
+ id="linearGradient32858-7-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.53706486,0,0,0.53706486,144.9138,-563.9364)"
+ x1="97.616623"
+ y1="39.47208"
+ x2="94.157646"
+ y2="35.759052" />
+ <linearGradient
+ id="linearGradient10069-9-7-5-4-6-5-0-3">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-5-4-58-5-9-1-2-1" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-43-0-4-0-8-0-4-9" />
+ </linearGradient>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask52637-8-8">
+ <rect
+ mask="none"
+ style="fill:url(#radialGradient52641-2-8);fill-opacity:1;stroke:none;stroke-width:2.79999995000000010;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect52639-8-9"
+ width="7.9918551"
+ height="8.9366941"
+ x="-354"
+ y="458"
+ rx="0"
+ ry="0" />
+ </mask>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-7409-7-7-0-9-9"
+ id="radialGradient52641-2-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.39420438,-0.08239205,0.27256031,1.3040635,-361.27885,-161.73915)"
+ cx="-302.79681"
+ cy="462.0358"
+ fx="-302.79681"
+ fy="462.0358"
+ r="8" />
+ <linearGradient
+ id="linearGradient37542-7409-7-7-0-9-9">
+ <stop
+ id="stop37544-48-6-1-4-1-1"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-82-1-0-9-3-3"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-31-8-9-1"
+ id="linearGradient52998-5-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-42,0)"
+ x1="-307"
+ y1="475"
+ x2="-303.00003"
+ y2="463.92236" />
+ <linearGradient
+ id="linearGradient319-31-8-9-1">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-23-2-8-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-34-4-4-2" />
+ </linearGradient>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask52879-0-5">
+ <rect
+ mask="none"
+ style="fill:url(#radialGradient52883-6-8);fill-opacity:1;stroke:none;stroke-width:2.79999995000000010;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect52881-7-3"
+ width="7.9918551"
+ height="8.9366941"
+ x="-354.95001"
+ y="458"
+ rx="0"
+ ry="0" />
+ </mask>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-7409-7-7-0-9-9"
+ id="radialGradient52883-6-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.39420438,-0.08239205,0.27256031,1.3040635,-362.22886,-161.73912)"
+ cx="-302.79681"
+ cy="462.0358"
+ fx="-302.79681"
+ fy="462.0358"
+ r="8" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-31-8-9-1"
+ id="linearGradient53000-3-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-42,0)"
+ x1="-308.7684"
+ y1="476.0105"
+ x2="-304.76843"
+ y2="464.93286" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient34488-1-8"
+ id="linearGradient53002-6-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-839.95,-273.25)"
+ x1="469.49295"
+ y1="-101.22778"
+ x2="470.7515"
+ y2="-102.52942" />
+ <linearGradient
+ id="linearGradient34488-1-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop34490-0-5-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop34492-4-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient32877-9-6-8"
+ id="linearGradient32896-0-4"
+ gradientUnits="userSpaceOnUse"
+ x1="-217.1391"
+ y1="626.39844"
+ x2="-213.69197"
+ y2="623.21643" />
+ <linearGradient
+ id="linearGradient32877-9-6-8">
+ <stop
+ style="stop-color:#b3b3b3;stop-opacity:1;"
+ offset="0"
+ id="stop32879-8-1-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop32881-4-3-9" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient33058-4-9-5"
+ id="linearGradient32899-8-3"
+ gradientUnits="userSpaceOnUse"
+ x1="-180.37465"
+ y1="650.94128"
+ x2="-177.70576"
+ y2="653.27765" />
+ <linearGradient
+ id="linearGradient33058-4-9-5">
+ <stop
+ style="stop-color:#e5250b;stop-opacity:1;"
+ offset="0"
+ id="stop33060-3-3-9" />
+ <stop
+ style="stop-color:#460000;stop-opacity:1;"
+ offset="1"
+ id="stop33062-9-4-7" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8-4-8-6-8"
+ id="radialGradient32901-4-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1748275,-1.7208853,0.51495275,0.35155123,-289.20197,69.961171)"
+ cx="-197.66467"
+ cy="630.61389"
+ fx="-197.66467"
+ fy="630.61389"
+ r="7.03125" />
+ <linearGradient
+ id="linearGradient44939-8-4-8-6-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop44941-8-5-0-0-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop44943-2-5-8-6-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient33058-2-7-1-7"
+ id="linearGradient32903-6-4"
+ gradientUnits="userSpaceOnUse"
+ x1="-218.31921"
+ y1="624.84143"
+ x2="-215.31401"
+ y2="628.46533" />
+ <linearGradient
+ id="linearGradient33058-2-7-1-7">
+ <stop
+ style="stop-color:#e5250b;stop-opacity:1;"
+ offset="0"
+ id="stop33060-1-8-8-5" />
+ <stop
+ style="stop-color:#460000;stop-opacity:1;"
+ offset="1"
+ id="stop33062-4-3-4-5" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8-4-8-6-8"
+ id="radialGradient32905-9-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.62164476,0.39733376,-0.55111069,0.86222272,269.0477,166.72227)"
+ cx="-202.18748"
+ cy="627"
+ fx="-202.18748"
+ fy="627"
+ r="7.03125" />
+ <linearGradient
+ y2="-102.52942"
+ x2="470.73633"
+ y1="-101.3037"
+ x1="469.52335"
+ gradientTransform="translate(-829.95,-273.25)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient58927"
+ xlink:href="#linearGradient34488-1-8"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-71-6-9-7"
+ id="linearGradient21875-7-1-0-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)"
+ x1="236.94902"
+ y1="-14.103641"
+ x2="278.34866"
+ y2="32.902874" />
+ <linearGradient
+ id="linearGradient1610-71-6-9-7">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-26-8-5-4" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-04-8-8-0" />
+ </linearGradient>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath13106-9-2-9-9">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ id="path34850-4-7-0-4"
+ 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" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ x="-0.45600089"
+ width="1.9120018"
+ y="-0.50666559"
+ height="2.0133312"
+ id="filter63011-6-7-0-8"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.899998"
+ id="feGaussianBlur63013-0-1-0-8" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060-6-6-2-4"
+ id="linearGradient21877-3-2-7-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-47.00001,58.00194)"
+ x1="160.14388"
+ y1="376.27383"
+ x2="174.29811"
+ y2="383.69843" />
+ <linearGradient
+ id="linearGradient5060-6-6-2-4">
+ <stop
+ id="stop5062-2-0-5-5"
+ offset="0"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ id="stop5064-4-4-5-5"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4671-6-4-1-7"
+ id="linearGradient34959-9-2-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.562541,0,0,0.567972,-9.399749,-5.305317)"
+ x1="1666.1765"
+ y1="639.65356"
+ x2="1659.0875"
+ y2="629.23273" />
+ <linearGradient
+ id="linearGradient4671-6-4-1-7">
+ <stop
+ id="stop4673-7-6-4-1"
+ offset="0"
+ style="stop-color:#ffd43b;stop-opacity:1;" />
+ <stop
+ id="stop4675-8-0-8-1"
+ offset="1"
+ style="stop-color:#ffe873;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4689-1-6-4-2"
+ id="linearGradient34961-3-6-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.562541,0,0,0.567972,-9.399749,-5.305317)"
+ x1="1641.4773"
+ y1="607.50525"
+ x2="1663.2872"
+ y2="626.40344" />
+ <linearGradient
+ id="linearGradient4689-1-6-4-2">
+ <stop
+ id="stop4691-6-2-6-7"
+ offset="0"
+ style="stop-color:#5a9fd4;stop-opacity:1;" />
+ <stop
+ id="stop4693-0-4-8-6"
+ offset="1"
+ style="stop-color:#306998;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-5-1-4-8-9-88-8-4"
+ id="linearGradient34963-5-9-1"
+ gradientUnits="userSpaceOnUse"
+ x1="922.89703"
+ y1="339.66599"
+ x2="924.10608"
+ y2="344.10001" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3966-5-1-4-8-9-88-8-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3968-7-9-0-8-2-1-3-2" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3970-6-6-6-2-8-2-5-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-5-1-4-8-9-88-8-4"
+ id="linearGradient34965-1-5-2"
+ gradientUnits="userSpaceOnUse"
+ x1="919.09998"
+ y1="345.42163"
+ x2="922.104"
+ y2="355.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-5-1-4-8-9-8-9-5-5"
+ id="linearGradient34967-4-1-8"
+ gradientUnits="userSpaceOnUse"
+ x1="922.64624"
+ y1="342.71866"
+ x2="921.82654"
+ y2="341.98108" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3966-5-1-4-8-9-8-9-5-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3968-7-9-0-8-2-9-8-5-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3970-6-6-6-2-8-0-2-8-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-5-1-4-8-9-88-8-4"
+ id="linearGradient34969-4-4-1"
+ gradientUnits="userSpaceOnUse"
+ x1="917.75"
+ y1="355.5"
+ x2="917.25"
+ y2="353" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-5-1-4-8-9-88-8-4"
+ id="linearGradient34971-5-0-9"
+ gradientUnits="userSpaceOnUse"
+ x1="923"
+ y1="343.75"
+ x2="923"
+ y2="344.75" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-5-1-4-8-9-88-8-4"
+ id="radialGradient34973-2-5-7"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4166677,-7.678944e-6,1.853542e-6,0.58333478,-1309.0016,145.80659)"
+ cx="924"
+ cy="349.20001"
+ fx="924"
+ fy="349.20001"
+ r="6" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-5-1-4-8-9-88-8-4"
+ id="linearGradient34975-9-4-9"
+ gradientUnits="userSpaceOnUse"
+ x1="921.34045"
+ y1="341.34042"
+ x2="922.16492"
+ y2="342.16492" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3944-4-6-7-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3946-2-4-4-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3948-3-5-0-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3952-2-6-4-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3954-1-1-8-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3956-6-5-8-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3966-5-1-45-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3968-7-9-5-5" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3970-6-6-1-5" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610-1-1-9-4-7-1">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-74-7-2-2-2-1" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-09-4-7-5-1-5" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient40578-4-8-4-0-5-2-4-7">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop40580-8-9-8-9-4-6-9-6" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop40582-6-8-8-4-3-8-9-1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient58334-24-8-2-6-0-2">
+ <stop
+ id="stop58336-55-8-3-6-3-3"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.87628865;" />
+ <stop
+ id="stop58338-17-2-3-3-0-2"
+ offset="1.0000000"
+ style="stop-color:#fffffe;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-11-1-4-3-1">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-5-1-5-5-6" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-27-3-6-0-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3944-1-7-5-7-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3946-7-4-3-6-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3948-1-2-5-7-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3952-5-7-6-8-9">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3954-2-9-1-3-2" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3956-7-3-4-6-7" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3966-8-9-6-4-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3968-2-8-2-4-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3970-4-6-6-1-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-4"
+ id="linearGradient15131"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9999519,0,0,0.9998051,-33.244333,253.26813)"
+ x1="101.21339"
+ y1="68.783279"
+ x2="135.45256"
+ y2="103.11092" />
+ <linearGradient
+ id="linearGradient37542-4">
+ <stop
+ id="stop37544-180"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-62"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-2"
+ id="linearGradient15133"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0910287,0,0,1.0900105,41.555722,244.97315)"
+ x1="47.655102"
+ y1="93.805557"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ id="linearGradient319-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-72" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10585-5"
+ id="linearGradient15135"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.032977,0,0,1,128.82015,107.77516)"
+ x1="12.330792"
+ y1="246.97107"
+ x2="41.654194"
+ y2="247.3784" />
+ <linearGradient
+ id="linearGradient10585-5">
+ <stop
+ id="stop10587-5"
+ offset="0.0000000"
+ style="stop-color:#d7d7d7;stop-opacity:1.0000000;" />
+ <stop
+ id="stop10595-5"
+ offset="1.0000000"
+ style="stop-color:#000000;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-0"
+ id="linearGradient15123"
+ 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" />
+ <linearGradient
+ id="linearGradient1610-0">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-6" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-42" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40578-4-8-0"
+ id="radialGradient15125"
+ 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
+ id="linearGradient40578-4-8-0">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop40580-8-9-61" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop40582-6-8-7" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334-46"
+ id="linearGradient15127"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(670,-33)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ id="linearGradient58334-46">
+ <stop
+ id="stop58336-9"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.87628865;" />
+ <stop
+ id="stop58338-5"
+ offset="1.0000000"
+ style="stop-color:#fffffe;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-46"
+ id="linearGradient15129"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-95.999998)"
+ x1="754.28558"
+ y1="300.83292"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-46">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-4" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-19-0-4"
+ id="linearGradient14559-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="117.12428"
+ y2="56.069553" />
+ <linearGradient
+ id="linearGradient319-19-0-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-865-0-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-02-0-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-19-0-4"
+ id="linearGradient14561-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(207,-246.99988)"
+ x1="-56.5"
+ y1="342.0625"
+ x2="-49"
+ y2="341" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14482-2"
+ id="linearGradient14563-3"
+ gradientUnits="userSpaceOnUse"
+ x1="149.55806"
+ y1="94.884857"
+ x2="149.53032"
+ y2="101.436" />
+ <linearGradient
+ id="linearGradient14482-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop14484-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop14486-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-95-2-7-1-2"
+ id="linearGradient14565-5"
+ gradientUnits="userSpaceOnUse"
+ x1="132"
+ y1="117.26753"
+ x2="142.72656"
+ y2="127.72736" />
+ <linearGradient
+ id="linearGradient319-95-2-7-1-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.75675678;"
+ offset="0"
+ id="stop320-43-7-3-3-3" />
+ <stop
+ style="stop-color:#915515;stop-opacity:0;"
+ offset="1"
+ id="stop321-12-7-4-1-9" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-8-3-3-0-3"
+ id="linearGradient14567-8"
+ gradientUnits="userSpaceOnUse"
+ x1="126.55782"
+ y1="113.57294"
+ x2="132.41052"
+ y2="118.81034" />
+ <linearGradient
+ id="linearGradient10069-8-3-3-0-3">
+ <stop
+ style="stop-color:#764511;stop-opacity:1;"
+ offset="0"
+ id="stop10071-9-8-7-1-8" />
+ <stop
+ style="stop-color:#915515;stop-opacity:0;"
+ offset="1"
+ id="stop10073-2-7-1-0-5" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-19-0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-865-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-02-0" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient14482">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop14484" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop14486" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-95-2-7-1">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.75675678;"
+ offset="0"
+ id="stop320-43-7-3-3" />
+ <stop
+ style="stop-color:#915515;stop-opacity:0;"
+ offset="1"
+ id="stop321-12-7-4-1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069-8-3-3-0">
+ <stop
+ style="stop-color:#764511;stop-opacity:1;"
+ offset="0"
+ id="stop10071-9-8-7-1" />
+ <stop
+ style="stop-color:#915515;stop-opacity:0;"
+ offset="1"
+ id="stop10073-2-7-1-0" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15098">
+ <stop
+ style="stop-color:#646464;stop-opacity:1;"
+ offset="0"
+ id="stop15100" />
+ <stop
+ style="stop-color:#fcfcfc;stop-opacity:1;"
+ offset="1"
+ id="stop15102" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13998-7-0"
+ id="linearGradient26282-0-8"
+ gradientUnits="userSpaceOnUse"
+ x1="13.5"
+ y1="57.827747"
+ x2="11.472005"
+ y2="53.875874" />
+ <linearGradient
+ id="linearGradient13998-7-0">
+ <stop
+ id="stop14000-1-1"
+ offset="0"
+ style="stop-color:#f57d07;stop-opacity:1;" />
+ <stop
+ id="stop14002-0-0"
+ offset="1"
+ style="stop-color:white;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13998-7-0"
+ id="linearGradient26284-9-6"
+ gradientUnits="userSpaceOnUse"
+ x1="-18.600719"
+ y1="501.96539"
+ x2="-26.642899"
+ y2="487.60382" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-7-2"
+ id="linearGradient26286-4-5"
+ gradientUnits="userSpaceOnUse"
+ x1="15.027407"
+ y1="60.637787"
+ x2="13.5"
+ y2="57.750687" />
+ <linearGradient
+ id="linearGradient319-7-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-5-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-5-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-7-2"
+ id="linearGradient26288-9-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.03018343,0.1408617)"
+ x1="-32.067383"
+ y1="490.70178"
+ x2="-22.25"
+ y2="500" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13998-7"
+ id="linearGradient26282-0"
+ gradientUnits="userSpaceOnUse"
+ x1="13.5"
+ y1="57.827747"
+ x2="11.472005"
+ y2="53.875874" />
+ <linearGradient
+ id="linearGradient13998-7">
+ <stop
+ id="stop14000-1"
+ offset="0"
+ style="stop-color:#f57d07;stop-opacity:1;" />
+ <stop
+ id="stop14002-0"
+ offset="1"
+ style="stop-color:white;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13998-7"
+ id="linearGradient26284-9"
+ gradientUnits="userSpaceOnUse"
+ x1="-18.600719"
+ y1="501.96539"
+ x2="-26.642899"
+ y2="487.60382" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-7"
+ id="linearGradient26286-4"
+ gradientUnits="userSpaceOnUse"
+ x1="15.027407"
+ y1="60.637787"
+ x2="13.5"
+ y2="57.750687" />
+ <linearGradient
+ id="linearGradient319-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-5" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-7"
+ id="linearGradient26288-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.03018343,0.1408617)"
+ x1="-32.067383"
+ y1="490.70178"
+ x2="-22.25"
+ y2="500" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-4-74-8"
+ id="radialGradient45309-0"
+ cx="336.42892"
+ cy="611.10455"
+ fx="336.42892"
+ fy="611.10455"
+ r="5.9852905"
+ gradientTransform="matrix(1.0070601,0.03386866,-0.03770425,1.1211085,20.665977,-85.772965)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient10069-9-7-4-74-8">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-5-4-5-0-1" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-43-0-5-9-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-9-1-2"
+ id="linearGradient42965-7-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(301.02752,449.99999)"
+ x1="25.963812"
+ y1="155.66899"
+ x2="29.972469"
+ y2="168" />
+ <linearGradient
+ id="linearGradient319-9-1-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-92-1-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-55-5-8" />
+ </linearGradient>
+ <filter
+ inkscape:collect="always"
+ id="filter24186-3-2-5"
+ x="-0.12810811"
+ width="1.2562162"
+ y="-0.11285714"
+ height="1.2257143"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.395"
+ id="feGaussianBlur24188-3-7-6" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-06-1-5"
+ id="linearGradient42967-6-4"
+ gradientUnits="userSpaceOnUse"
+ x1="335.96875"
+ y1="607.09375"
+ x2="337.04251"
+ y2="628.20752" />
+ <linearGradient
+ id="linearGradient1610-06-1-5">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-8-4-2" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-1-2-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-12-5"
+ id="linearGradient42487-4-5"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ id="linearGradient319-12-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-34-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-81-9" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425-8-7"
+ id="linearGradient42489-5-9"
+ gradientUnits="userSpaceOnUse"
+ x1="123.26987"
+ y1="108.56933"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ id="linearGradient15425-8-7">
+ <stop
+ style="stop-color:#8c0000;stop-opacity:1;"
+ offset="0"
+ id="stop15427-5-9" />
+ <stop
+ style="stop-color:#c80000;stop-opacity:0;"
+ offset="1"
+ id="stop15429-7-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-12-5"
+ id="linearGradient42491-0-9"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425-8-7"
+ id="linearGradient17232-8"
+ gradientUnits="userSpaceOnUse"
+ x1="123.26987"
+ y1="108.56933"
+ x2="141.64546"
+ y2="130.81215" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-35-31-8"
+ id="radialGradient37501-4-6-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.08933014,-0.7764284,0.7350832,-0.08334857,57.410559,233.30156)"
+ cx="135.83771"
+ cy="117.97826"
+ fx="135.83771"
+ fy="117.97826"
+ r="8" />
+ <linearGradient
+ id="linearGradient319-35-31-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-38-14-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-94-6-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-35-31-8"
+ id="linearGradient37503-1-1-1"
+ gradientUnits="userSpaceOnUse"
+ x1="121.19734"
+ y1="105.94044"
+ x2="148.06364"
+ y2="137.6748" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-35-08-1"
+ id="radialGradient37501-4-9-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.08933014,-0.7764284,0.7350832,-0.08334857,57.410559,233.30156)"
+ cx="135.83771"
+ cy="117.97826"
+ fx="135.83771"
+ fy="117.97826"
+ r="8" />
+ <linearGradient
+ id="linearGradient319-35-08-1">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-38-1-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-94-1-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-35-08-1"
+ id="linearGradient37503-1-9-9"
+ gradientUnits="userSpaceOnUse"
+ x1="121.19734"
+ y1="105.94044"
+ x2="148.06364"
+ y2="137.6748" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-35-0"
+ id="radialGradient37501-4-64"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.08933014,-0.7764284,0.7350832,-0.08334857,57.410559,233.30156)"
+ cx="135.83771"
+ cy="117.97826"
+ fx="135.83771"
+ fy="117.97826"
+ r="8" />
+ <linearGradient
+ id="linearGradient319-35-0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-38-15" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-94-19" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-35-0"
+ id="linearGradient37503-1-7"
+ gradientUnits="userSpaceOnUse"
+ x1="121.19734"
+ y1="105.94044"
+ x2="148.06364"
+ y2="137.6748" />
+ <linearGradient
+ id="linearGradient18105-2-9">
+ <stop
+ id="stop18107-8-4"
+ offset="0"
+ style="stop-color:#162d50;stop-opacity:1" />
+ <stop
+ id="stop18109-1-4"
+ offset="1"
+ style="stop-color:#1e3e70;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15531-9-5">
+ <stop
+ style="stop-color:#20539d;stop-opacity:1"
+ offset="0"
+ id="stop15534-1-3" />
+ <stop
+ style="stop-color:#bdc9df;stop-opacity:1"
+ offset="1"
+ id="stop15537-7-5" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient23974-27-5">
+ <stop
+ id="stop23976-25-8"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop23978-48-3"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient27277-1-8">
+ <stop
+ id="stop27279-5-2"
+ offset="0"
+ style="stop-color:#444444;stop-opacity:1;" />
+ <stop
+ id="stop27281-4-1"
+ offset="1"
+ style="stop-color:#adadad;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient21327-63-5">
+ <stop
+ style="stop-color:#1e3e70;stop-opacity:1;"
+ offset="0"
+ id="stop21329-9-2" />
+ <stop
+ style="stop-color:#1e3e70;stop-opacity:0;"
+ offset="1"
+ id="stop21331-6-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient27301-6-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop27303-3-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop27305-7-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15530-7"
+ id="linearGradient15537-5"
+ x1="223.00443"
+ y1="252.2876"
+ x2="222.72559"
+ y2="247.07268"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1.1092502,-0.02900917)" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient15530-7">
+ <stop
+ style="stop-color:#16396d;stop-opacity:1"
+ offset="0"
+ id="stop15533-4" />
+ <stop
+ style="stop-color:#739ad4;stop-opacity:1"
+ offset="1"
+ id="stop15535-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37542-40-9">
+ <stop
+ id="stop37544-6-0"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1" />
+ <stop
+ id="stop37546-3-3"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-84-1">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-78-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-30-96" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-84-3-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-78-3-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-30-9-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38342-8"
+ id="linearGradient15502-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1386698,0,0,1.1421744,-30.9218,-35.447285)"
+ x1="214.40482"
+ y1="253.6573"
+ x2="225.75406"
+ y2="244.98485" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient38342-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop38344-5" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop38346-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15482-65"
+ id="linearGradient15474-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.625,0,0,1,355.875,184)"
+ x1="-174.15565"
+ y1="68.784225"
+ x2="-185.42635"
+ y2="63.762562" />
+ <linearGradient
+ id="linearGradient15482-65">
+ <stop
+ id="stop15484-4"
+ offset="0"
+ style="stop-color:#2869ab;stop-opacity:1" />
+ <stop
+ id="stop15486-2"
+ offset="1"
+ style="stop-color:#a7c8f0;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-6-11"
+ id="linearGradient15467-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.56865388,0,0,0.77023595,345.79076,197.07321)"
+ x1="-182.5201"
+ y1="63.631611"
+ x2="-170.82031"
+ y2="62.441177" />
+ <linearGradient
+ id="linearGradient319-6-11">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-73-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-51-9" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15595-7"
+ id="linearGradient15601-9"
+ x1="248.04936"
+ y1="256.02081"
+ x2="238.4982"
+ y2="243.66418"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient15595-7">
+ <stop
+ style="stop-color:#1b4685;stop-opacity:1;"
+ offset="0"
+ id="stop15597-5" />
+ <stop
+ style="stop-color:#183e75;stop-opacity:0;"
+ offset="1"
+ id="stop15599-3" />
+ </linearGradient>
+ <linearGradient
+ y2="65.529938"
+ x2="-162.92078"
+ y1="62.360832"
+ x1="-191.30537"
+ gradientTransform="matrix(0.56865388,0,0,0.9414558,346.44835,191.39968)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient15576-5"
+ xlink:href="#linearGradient319-6-1-5"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient319-6-1-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-73-4-5" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-51-8-0" />
+ </linearGradient>
+ <linearGradient
+ gradientTransform="translate(-0.04936017,-0.02079917)"
+ inkscape:collect="always"
+ xlink:href="#linearGradient15614-7"
+ id="linearGradient15620-8"
+ x1="194.98087"
+ y1="238.83058"
+ x2="195.88264"
+ y2="253.1198"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient15614-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15616-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15618-7" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-64-7"
+ id="linearGradient42432-3-3"
+ gradientUnits="userSpaceOnUse"
+ x1="248.20378"
+ y1="275.71143"
+ x2="238.40068"
+ y2="262.12378" />
+ <linearGradient
+ id="linearGradient1610-64-7">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-8-1" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-29-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15275-9"
+ id="linearGradient15281-5"
+ gradientUnits="userSpaceOnUse"
+ x1="238.25577"
+ y1="263.93561"
+ x2="244.04422"
+ y2="281.74426" />
+ <linearGradient
+ id="linearGradient15275-9">
+ <stop
+ id="stop15277-2"
+ offset="0"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ id="stop15279-1"
+ offset="1"
+ style="stop-color:white;stop-opacity:1;" />
+ </linearGradient>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath42711-8-1">
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect42713-4-3"
+ width="8.7252884"
+ height="17.464855"
+ x="127.4093"
+ y="214.76154" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15361-7"
+ id="linearGradient15368-7"
+ x1="132.26923"
+ y1="125.62637"
+ x2="132.11778"
+ y2="119.48639"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient15361-7">
+ <stop
+ style="stop-color:#2766a6;stop-opacity:1;"
+ offset="0"
+ id="stop15363-7" />
+ <stop
+ style="stop-color:#6ba2e5;stop-opacity:1;"
+ offset="1"
+ id="stop15365-9" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15320-0"
+ id="linearGradient15326-8"
+ x1="134.91025"
+ y1="122.37094"
+ x2="129.09338"
+ y2="113.63851"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient15320-0">
+ <stop
+ style="stop-color:#0868f5;stop-opacity:1;"
+ offset="0"
+ id="stop15322-3" />
+ <stop
+ style="stop-color:#fbfdfe;stop-opacity:1;"
+ offset="1"
+ id="stop15324-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient23974-0-2">
+ <stop
+ id="stop23976-22-8"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop23978-4-5"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient31320-4-3">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop31322-9-2" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop31324-3-5" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient14262-95-2">
+ <stop
+ id="stop14264-2-2"
+ offset="0"
+ style="stop-color:#2661b6;stop-opacity:1;" />
+ <stop
+ id="stop14266-7-2"
+ offset="1"
+ style="stop-color:#c1d7f8;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-40-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-95-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-16-1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient23974-28-0-5">
+ <stop
+ id="stop23976-64-2-3"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop23978-5-3-7"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-23-4"
+ id="radialGradient53141-5-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.684011,0.3442329,-1.2972142,1.1562236,739.67527,-1155.7895)"
+ cx="975.50568"
+ cy="690.68732"
+ fx="975.50568"
+ fy="690.68732"
+ r="2.333364" />
+ <linearGradient
+ id="linearGradient319-23-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-65-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-3-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974-48-9"
+ id="linearGradient53143-6-3"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.821004,429.95027,-161.55482)"
+ x1="108.71671"
+ y1="171.25618"
+ x2="105.85706"
+ y2="168.04703" />
+ <linearGradient
+ id="linearGradient23974-48-9">
+ <stop
+ id="stop23976-13-7"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop23978-28-3"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20756-2-0"
+ id="linearGradient53145-1-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.8956408,540.31118,-183.20693)"
+ x1="-27.086565"
+ y1="177.33885"
+ x2="-28.929489"
+ y2="175.48488" />
+ <linearGradient
+ id="linearGradient20756-2-0">
+ <stop
+ style="stop-color:#2968c3;stop-opacity:1;"
+ offset="0"
+ id="stop20758-7-2" />
+ <stop
+ style="stop-color:#b5ccf0;stop-opacity:1;"
+ offset="1"
+ id="stop20760-0-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-23-4"
+ id="linearGradient53147-9-4"
+ gradientUnits="userSpaceOnUse"
+ x1="510.29913"
+ y1="-20.435461"
+ x2="505.9494"
+ y2="-17.546936" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient28399-4"
+ id="linearGradient28405-0"
+ x1="329.46249"
+ y1="-104.63468"
+ x2="331.51218"
+ y2="-102.69718"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient28399-4">
+ <stop
+ style="stop-color:#0b1728;stop-opacity:1;"
+ offset="0"
+ id="stop28401-2" />
+ <stop
+ style="stop-color:#0b1728;stop-opacity:0;"
+ offset="1"
+ id="stop28403-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974-1-2"
+ id="linearGradient18721-1-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.004219,0,0,0.980922,244.3928,19.4113)"
+ x1="-87.329895"
+ y1="-122.61974"
+ x2="-80.592239"
+ y2="-126.83872" />
+ <linearGradient
+ id="linearGradient23974-1-2">
+ <stop
+ id="stop23976-3-3"
+ offset="0"
+ style="stop-color:#3e7dd7;stop-opacity:0" />
+ <stop
+ style="stop-color:#8faedb;stop-opacity:1"
+ offset="0.48394433"
+ id="stop28407-8" />
+ <stop
+ id="stop23978-26-7"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31320-0-3"
+ id="linearGradient18728-6-0"
+ 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-0-3">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop31322-4-5" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop31324-9-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262-97-5"
+ id="linearGradient18765-0-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.004219,0,0,0.980922,309.42934,-349.44584)"
+ x1="-20.377066"
+ y1="250.63214"
+ x2="-23.077509"
+ y2="252.61113" />
+ <linearGradient
+ id="linearGradient14262-97-5">
+ <stop
+ id="stop14264-0-6"
+ offset="0"
+ style="stop-color:#2661b6;stop-opacity:1;" />
+ <stop
+ id="stop14266-6-3"
+ offset="1"
+ style="stop-color:#c1d7f8;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-406-5"
+ id="linearGradient18712-0-7"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="111.30827"
+ y1="56.21777"
+ x2="106.06621"
+ y2="52.58638" />
+ <linearGradient
+ id="linearGradient319-406-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0"
+ offset="0"
+ id="stop320-76-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1"
+ id="stop321-36-7" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15539-2"
+ id="linearGradient15545-5"
+ x1="220.10603"
+ y1="248.22742"
+ x2="219.99527"
+ y2="254.01555"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1.1092502,-0.02900917)" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient15539-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15541-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15543-1" />
+ </linearGradient>
+ <linearGradient
+ gradientTransform="translate(-0.04936017,-0.02079917)"
+ inkscape:collect="always"
+ xlink:href="#linearGradient15547-6"
+ id="linearGradient15553-4"
+ x1="216.16943"
+ y1="248.86955"
+ x2="216.65909"
+ y2="252.40509"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient15547-6">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15549-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15551-1" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38363-7"
+ id="radialGradient15517-8"
+ cx="217.74739"
+ cy="253.99704"
+ fx="217.74739"
+ fy="253.99704"
+ r="9.0099697"
+ gradientTransform="matrix(2.3861605,-0.28739765,0.07141566,0.59293888,-320.08363,164.28237)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient38363-7">
+ <stop
+ id="stop38365-1"
+ offset="0"
+ style="stop-color:#1d4d91;stop-opacity:1" />
+ <stop
+ style="stop-color:#658fd4;stop-opacity:1;"
+ offset="0.44217443"
+ id="stop15519-3" />
+ <stop
+ id="stop38367-1"
+ offset="1"
+ style="stop-color:#c3d7ff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38342-8"
+ id="linearGradient38716-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1386698,0,0,1.1421744,-30.97116,-35.468084)"
+ x1="209.90396"
+ y1="249.06081"
+ x2="234.13614"
+ y2="251.62866" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-56-4"
+ id="linearGradient17222-4-4"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="29.352921"
+ y1="199"
+ x2="29.352921"
+ y2="250" />
+ <linearGradient
+ id="linearGradient37542-56-4">
+ <stop
+ id="stop37544-88-5"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-9-2"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-528-2"
+ id="linearGradient17224-0-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2222204,0,-15.888744)"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="16.733877"
+ y2="88" />
+ <linearGradient
+ id="linearGradient319-528-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-68-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-86-7" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069-24-4">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-3-2" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-4-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-67-6"
+ id="linearGradient42519-8-7"
+ gradientUnits="userSpaceOnUse"
+ x1="114.15679"
+ y1="100.93772"
+ x2="137.5759"
+ y2="124.47867" />
+ <linearGradient
+ id="linearGradient1610-67-6">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-75-5" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-31-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030-41-5"
+ id="linearGradient42523-5-8"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ id="linearGradient9030-41-5">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop9032-2-0" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop9034-10-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-76-2"
+ id="linearGradient42521-3-0"
+ gradientUnits="userSpaceOnUse"
+ x1="131.12576"
+ y1="118"
+ x2="140.19273"
+ y2="125.82862" />
+ <linearGradient
+ id="linearGradient319-76-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-3-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-18-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24679-9-1"
+ id="linearGradient25927-1-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,-30.15217,152.41412)"
+ x1="121.79003"
+ y1="283.00519"
+ x2="114.66669"
+ y2="250.69945" />
+ <linearGradient
+ id="linearGradient24679-9-1">
+ <stop
+ style="stop-color:#3d361a;stop-opacity:1;"
+ offset="0"
+ id="stop24681-7-0" />
+ <stop
+ id="stop24683-6-7"
+ offset="0.45537567"
+ style="stop-color:#d1c595;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop24685-4-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24671-1-3"
+ id="linearGradient25929-7-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-149,133.99245)"
+ x1="243.25"
+ y1="283.94504"
+ x2="235"
+ y2="253.00755" />
+ <linearGradient
+ id="linearGradient24671-1-3">
+ <stop
+ style="stop-color:#3d361a;stop-opacity:1;"
+ offset="0"
+ id="stop24673-7-4" />
+ <stop
+ id="stop24675-7-4"
+ offset="0.29527253"
+ style="stop-color:#d1c595;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop24677-5-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-16-6"
+ id="linearGradient15963-3"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-335,238.99245)"
+ x1="425.5929"
+ y1="179.08949"
+ x2="425"
+ y2="179.12285" />
+ <linearGradient
+ id="linearGradient319-16-6">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-683-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-08-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-86-8"
+ id="linearGradient15744-9-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.207032,0,0,0.903901,679.30638,-38.92179)"
+ x1="390.61163"
+ y1="229.34804"
+ x2="390.55936"
+ y2="248.24983" />
+ <linearGradient
+ id="linearGradient37542-86-8">
+ <stop
+ id="stop37544-39-4"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-7-6"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-0-3"
+ id="linearGradient10982-8-5"
+ x1="207.04637"
+ y1="182.09375"
+ x2="213.7883"
+ y2="182.52524"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient319-0-3">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-15-31" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-26-3" />
+ </linearGradient>
+ <linearGradient
+ y2="121"
+ x2="235.90916"
+ y1="107.25085"
+ x1="217.22589"
+ gradientTransform="matrix(1.0222226,0,0,0.73333282,-29.133504,-14.766607)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient16268-9"
+ xlink:href="#linearGradient37542-86-0-1"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient37542-86-0-1">
+ <stop
+ id="stop37544-39-8-4"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-7-1-1"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ y2="118.5"
+ x2="235"
+ y1="118.5"
+ x1="228.5468"
+ gradientTransform="matrix(0,1.253963,1,0,-46.30656,-81.941791)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient16302-5"
+ xlink:href="#linearGradient319-0-2-5"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient319-0-2-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-15-0-3" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-26-9-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-86-2-7"
+ id="linearGradient15744-9-0-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.207032,0,0,0.903901,679.30638,-38.92179)"
+ x1="388.85464"
+ y1="230.24152"
+ x2="390.55936"
+ y2="248.24983" />
+ <linearGradient
+ id="linearGradient37542-86-2-7">
+ <stop
+ id="stop37544-39-5-3"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-7-2-9"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-0-4-4"
+ id="linearGradient10982-8-9-5"
+ x1="207.04637"
+ y1="182.09375"
+ x2="213.7883"
+ y2="182.52524"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient319-0-4-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-15-3-2" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-26-2-9" />
+ </linearGradient>
+ <linearGradient
+ y2="121"
+ x2="235.90916"
+ y1="107.25085"
+ x1="217.22589"
+ gradientTransform="matrix(1.0222226,0,0,0.73333282,-29.2335,-145.66661)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient16268-5-0"
+ xlink:href="#linearGradient37542-86-0-6-8"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient37542-86-0-6-8">
+ <stop
+ id="stop37544-39-8-7-4"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-7-1-5-6"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ y2="118.5"
+ x2="235"
+ y1="118.5"
+ x1="228.5468"
+ gradientTransform="matrix(0,1.253963,-1,0,177.20656,-82.04179)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient16302-3-4"
+ xlink:href="#linearGradient319-0-2-3-8"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient319-0-2-3-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-15-0-0-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-26-9-5-3" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15859-1">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop15861-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop15863-7" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17523-0-7-7"
+ id="linearGradient27998-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(214.99838,108.99542)"
+ x1="87.765633"
+ y1="16.828125"
+ x2="85.033081"
+ y2="18.891191" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient17523-0-7-7">
+ <stop
+ style="stop-color:#323232;stop-opacity:1;"
+ offset="0"
+ id="stop17525-0-3-1" />
+ <stop
+ style="stop-color:#323232;stop-opacity:0;"
+ offset="1"
+ id="stop17527-5-9-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17515-1-4-4"
+ id="linearGradient28000-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(206.99837,-42.004575)"
+ x1="95.812523"
+ y1="167.78125"
+ x2="93.152969"
+ y2="169.77431" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient17515-1-4-4">
+ <stop
+ style="stop-color:#8c8c8c;stop-opacity:1;"
+ offset="0"
+ id="stop17517-7-4-5" />
+ <stop
+ style="stop-color:#8c8c8c;stop-opacity:0;"
+ offset="1"
+ id="stop17519-6-7-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17532-0-9-1"
+ id="linearGradient28002-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(206.99837,-42.004575)"
+ x1="95.322037"
+ y1="167.49391"
+ x2="92.640839"
+ y2="169.55806" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient17532-0-9-1">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop17534-2-2-5" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop17536-3-0-8" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-5-1-4-8"
+ id="radialGradient28004-7"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.050372,0,0,1.050372,-3.551238,-0.730396)"
+ cx="70.5"
+ cy="14.5"
+ fx="70.5"
+ fy="14.5"
+ r="1.5" />
+ <linearGradient
+ id="linearGradient10069-5-1-4-8">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-9-18-9-9" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-8-252-1-7" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient36273-9-4-2-3"
+ id="linearGradient28006-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4000084,0,0,0.4000084,344.60085,-50.387906)"
+ x1="-103.37495"
+ y1="417.87503"
+ x2="-101.49999"
+ y2="419.75" />
+ <linearGradient
+ id="linearGradient36273-9-4-2-3">
+ <stop
+ id="stop36275-9-0-3-3"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop36277-1-3-5-2"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient36273-9-4-22-0"
+ id="linearGradient28008-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4000084,0,0,0.4000084,350.57878,-38.420763)"
+ x1="-103.37495"
+ y1="417.87503"
+ x2="-101.49999"
+ y2="419.75" />
+ <linearGradient
+ id="linearGradient36273-9-4-22-0">
+ <stop
+ id="stop36275-9-0-6-7"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop36277-1-3-6-9"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17523-8"
+ id="linearGradient27963-5"
+ gradientUnits="userSpaceOnUse"
+ x1="87.765633"
+ y1="16.828125"
+ x2="85.033081"
+ y2="18.891191" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient17523-8">
+ <stop
+ style="stop-color:#323232;stop-opacity:1;"
+ offset="0"
+ id="stop17525-7" />
+ <stop
+ style="stop-color:#323232;stop-opacity:0;"
+ offset="1"
+ id="stop17527-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17515-0"
+ id="linearGradient27965-1"
+ gradientUnits="userSpaceOnUse"
+ x1="95.812523"
+ y1="167.78125"
+ x2="93.152969"
+ y2="169.77431" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient17515-0">
+ <stop
+ style="stop-color:#8c8c8c;stop-opacity:1;"
+ offset="0"
+ id="stop17517-3" />
+ <stop
+ style="stop-color:#8c8c8c;stop-opacity:0;"
+ offset="1"
+ id="stop17519-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17532-4"
+ id="linearGradient27967-9"
+ gradientUnits="userSpaceOnUse"
+ x1="95.322037"
+ y1="167.49391"
+ x2="92.640839"
+ y2="169.55806" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient17532-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop17534-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop17536-4" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-5-1-8"
+ id="radialGradient27969-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.050372,0,0,1.050372,-3.551238,-0.730396)"
+ cx="70.5"
+ cy="14.5"
+ fx="70.5"
+ fy="14.5"
+ r="1.5" />
+ <linearGradient
+ id="linearGradient10069-5-1-8">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-9-18-3" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-8-252-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient36273-9-4-8"
+ id="linearGradient27971-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4000084,0,0,0.4000084,137.60085,-8.4035259)"
+ x1="-103.37495"
+ y1="417.87503"
+ x2="-101.49999"
+ y2="419.75" />
+ <linearGradient
+ id="linearGradient36273-9-4-8">
+ <stop
+ id="stop36275-9-0-0"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop36277-1-3-8"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient36273-9-4-8"
+ id="linearGradient27973-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4000084,0,0,0.4000084,143.60084,3.5964739)"
+ x1="-103.37495"
+ y1="417.87503"
+ x2="-101.49999"
+ y2="419.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17523-0-5"
+ id="linearGradient17973-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(176.0221,109.0221)"
+ x1="87.765633"
+ y1="16.828125"
+ x2="85.033081"
+ y2="18.891191" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient17523-0-5">
+ <stop
+ style="stop-color:#323232;stop-opacity:1;"
+ offset="0"
+ id="stop17525-0-6" />
+ <stop
+ style="stop-color:#323232;stop-opacity:0;"
+ offset="1"
+ id="stop17527-5-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17515-1-9"
+ id="linearGradient17975-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(168.02209,-41.977903)"
+ x1="95.812523"
+ y1="167.78125"
+ x2="93.152969"
+ y2="169.77431" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient17515-1-9">
+ <stop
+ style="stop-color:#8c8c8c;stop-opacity:1;"
+ offset="0"
+ id="stop17517-7-9" />
+ <stop
+ style="stop-color:#8c8c8c;stop-opacity:0;"
+ offset="1"
+ id="stop17519-6-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17532-0-8"
+ id="linearGradient17977-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(168.02209,-41.977903)"
+ x1="95.322037"
+ y1="167.49391"
+ x2="92.640839"
+ y2="169.55806" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient17532-0-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop17534-2-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop17536-3-8" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-5-12"
+ id="radialGradient17979-7"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.050372,0,0,1.050372,-3.551238,-0.730396)"
+ cx="70.5"
+ cy="14.5"
+ fx="70.5"
+ fy="14.5"
+ r="1.5" />
+ <linearGradient
+ id="linearGradient10069-5-12">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-9-7" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-8-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient36273-9-9"
+ id="linearGradient17981-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4000084,0,0,0.4000084,305.60083,-50.403526)"
+ x1="-103.37495"
+ y1="417.87503"
+ x2="-101.49999"
+ y2="419.75" />
+ <linearGradient
+ id="linearGradient36273-9-9">
+ <stop
+ id="stop36275-9-8"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop36277-1-35"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient36273-9-9"
+ id="linearGradient17983-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4000084,0,0,0.4000084,311.60082,-38.403526)"
+ x1="-103.37495"
+ y1="417.87503"
+ x2="-101.49999"
+ y2="419.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030-4-6-0"
+ id="linearGradient32430-7-9-7"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ id="linearGradient9030-4-6-0">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop9032-3-3-8" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop9034-1-6-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8-7-1-7-2-5-2"
+ id="linearGradient32434-5-8-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,73,792.5)"
+ x1="346"
+ y1="128.5"
+ x2="368"
+ y2="123.5" />
+ <linearGradient
+ id="linearGradient44939-8-7-1-7-2-5-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop44941-8-4-5-4-7-8-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop44943-2-0-2-0-1-0-2" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40455-7-1-6-0"
+ id="radialGradient15137-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7881042,0.01544832,-0.01690407,0.7184169,-16.705439,29.204304)"
+ cx="-73.227486"
+ cy="95.949913"
+ fx="-73.227486"
+ fy="95.949913"
+ r="4.9999957" />
+ <linearGradient
+ id="linearGradient40455-7-1-6-0">
+ <stop
+ id="stop40457-6-6-8-7"
+ offset="0"
+ style="stop-color:#fff991;stop-opacity:1;" />
+ <stop
+ id="stop40459-1-8-7-9"
+ offset="1"
+ style="stop-color:#fffbb9;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40578-4-8-7-5-3"
+ id="radialGradient15139-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4769848,-0.5257394,0.6056598,0.5494938,269.68012,490.96577)"
+ cx="756.83508"
+ cy="206.40076"
+ fx="756.83508"
+ fy="206.40076"
+ r="6.9000001" />
+ <linearGradient
+ id="linearGradient40578-4-8-7-5-3">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop40580-8-9-6-1-7" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop40582-6-8-1-8-7" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334-9-6-7"
+ id="linearGradient15141-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(670,-33)"
+ x1="89.012573"
+ y1="243.96121"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ id="linearGradient58334-9-6-7">
+ <stop
+ id="stop58336-27-3-0"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.87628865;" />
+ <stop
+ id="stop58338-9-5-0"
+ offset="1.0000000"
+ style="stop-color:#fffffe;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-4-1-4"
+ id="linearGradient15143-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(1,-94.999998)"
+ x1="754.28558"
+ y1="300.83292"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-4-1-4">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-31-1-1" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-23-1-2" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient44939-8-6-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop44941-8-0-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop44943-2-7-6" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient44939-8-0-9">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop44941-8-1-2" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop44943-2-3-1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient25108-1-0">
+ <stop
+ id="stop25110-8-5"
+ offset="0"
+ style="stop-color:white;stop-opacity:1;" />
+ <stop
+ id="stop25112-1-0"
+ offset="1"
+ style="stop-color:#c6c6c6;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient44939-8-7-1-7-2-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop44941-8-4-5-4-7-86" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop44943-2-0-2-0-1-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8-7-1-7-2-4"
+ id="linearGradient55624"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,73,792.5)"
+ x1="346"
+ y1="128.5"
+ x2="368"
+ y2="123.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15098"
+ id="linearGradient55656"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,221,10)"
+ x1="115.01612"
+ y1="12"
+ x2="106.125"
+ y2="19.9375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient25108-1-0"
+ id="linearGradient55785"
+ gradientUnits="userSpaceOnUse"
+ x1="436.54755"
+ y1="524.30481"
+ x2="434.49387"
+ y2="519.46057" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient25108-1-0"
+ id="linearGradient55787"
+ gradientUnits="userSpaceOnUse"
+ x1="432.0849"
+ y1="524.97125"
+ x2="433"
+ y2="526" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-19-0"
+ id="linearGradient55950"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="117.12428"
+ y2="56.069553" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-19-0"
+ id="linearGradient55952"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(207,-246.99988)"
+ x1="-56.5"
+ y1="342.0625"
+ x2="-49"
+ y2="341" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14482"
+ id="linearGradient55954"
+ gradientUnits="userSpaceOnUse"
+ x1="149.55806"
+ y1="94.884857"
+ x2="149.53032"
+ y2="101.436" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-95-2-7-1"
+ id="linearGradient55956"
+ gradientUnits="userSpaceOnUse"
+ x1="132"
+ y1="117.26753"
+ x2="142.72656"
+ y2="127.72736" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-8-3-3-0"
+ id="linearGradient55958"
+ gradientUnits="userSpaceOnUse"
+ x1="126.55782"
+ y1="113.57294"
+ x2="132.41052"
+ y2="118.81034" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8-0-9"
+ id="linearGradient55988"
+ gradientUnits="userSpaceOnUse"
+ x1="279.75"
+ y1="101.5"
+ x2="284.5"
+ y2="106.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8-6-2"
+ id="linearGradient55990"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,593.02125,-1.8e-6)"
+ x1="279"
+ y1="102"
+ x2="281.75"
+ y2="102" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient56084"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(210.99996,-273.00002)"
+ x1="308"
+ y1="323"
+ x2="343.26239"
+ y2="340" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-08"
+ id="linearGradient56084-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(210.99996,-273.00002)"
+ x1="308"
+ y1="323"
+ x2="343.26239"
+ y2="340" />
+ <linearGradient
+ id="linearGradient319-08">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-36" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-21" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-08"
+ id="linearGradient29129-4"
+ gradientUnits="userSpaceOnUse"
+ x1="732.9375"
+ y1="412.8125"
+ x2="753.40625"
+ y2="418.33594" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-71"
+ id="linearGradient56084-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(210.99996,-273.00002)"
+ x1="308"
+ y1="323"
+ x2="343.26239"
+ y2="340" />
+ <linearGradient
+ id="linearGradient319-71">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-33" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-9" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-71"
+ id="linearGradient29129-1"
+ gradientUnits="userSpaceOnUse"
+ x1="732.9375"
+ y1="412.8125"
+ x2="753.40625"
+ y2="418.33594" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-24-4"
+ id="linearGradient56401"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2868892,0,0,1,-249.7433,-143.02079)"
+ x1="348.06064"
+ y1="220.55545"
+ x2="363.71661"
+ y2="239.94608" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-76-2"
+ id="linearGradient56428"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9050931,-7.9558708e-4,0.00612764,0.9147058,27.439091,-300.45853)"
+ x1="299.70026"
+ y1="408.49368"
+ x2="322.08145"
+ y2="429.53806" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15859-1"
+ id="linearGradient14951"
+ gradientUnits="userSpaceOnUse"
+ x1="4.1933641"
+ y1="199.12067"
+ x2="17.16466"
+ y2="211.01585" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15859-1-3"
+ id="linearGradient14951-4"
+ gradientUnits="userSpaceOnUse"
+ x1="12.602254"
+ y1="206.13333"
+ x2="26.167894"
+ y2="220.66356" />
+ <linearGradient
+ id="linearGradient15859-1-3">
+ <stop
+ style="stop-color:#ff992b;stop-opacity:1"
+ offset="0"
+ id="stop15861-1-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop15863-7-73" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974-28-0-5"
+ id="linearGradient15989"
+ gradientUnits="userSpaceOnUse"
+ x1="94.485573"
+ y1="122.13319"
+ x2="89.207298"
+ y2="125.83332" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31320-4-3"
+ id="linearGradient15994"
+ 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="#linearGradient319-40-7"
+ id="linearGradient16002"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,69.29396,203.19342)"
+ x1="103.65562"
+ y1="49.547874"
+ x2="120.79755"
+ y2="57.84819" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262-95-2"
+ id="linearGradient16005"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.004219,0,0,0.980922,139.37998,3.53336)"
+ x1="-26.207859"
+ y1="252.77303"
+ x2="-5.4963508"
+ y2="253.15045" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974-0-2"
+ id="linearGradient16010"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.004219,0,0,0.980922,74.34344,372.3905)"
+ x1="-88.73024"
+ y1="-120.6127"
+ x2="-78.787354"
+ y2="-128.30418" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27301-6-2"
+ id="linearGradient16558"
+ gradientUnits="userSpaceOnUse"
+ x1="497"
+ y1="264"
+ x2="507.125"
+ y2="276.75"
+ gradientTransform="translate(-0.04936017,-0.04091017)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient21327-63-5"
+ id="linearGradient16561"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.04935997,0.97920913)"
+ x1="500.71924"
+ y1="270.24997"
+ x2="477"
+ y2="274" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27277-1-8"
+ id="linearGradient16564"
+ 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="#linearGradient23974-27-5"
+ id="linearGradient16567"
+ 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="#linearGradient15531-9-5"
+ id="linearGradient16570"
+ 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="#linearGradient18105-2-9"
+ id="linearGradient16573"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.04935997,1.9792524)"
+ x1="492.95264"
+ y1="267.42996"
+ x2="496.73859"
+ y2="270.36874" />
+ <linearGradient
+ id="linearGradient1610-3-7-4">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-1-4-3" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-6-0-9" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-5-9-4-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-761-8-8-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-89-24-8-9" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-3-7-4"
+ id="linearGradient16887"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(22,0)"
+ x1="-70.605209"
+ y1="-121.58411"
+ x2="-28.177105"
+ y2="-89.026711" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-5-9-4-2"
+ id="linearGradient16889"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(22,0)"
+ x1="-74"
+ y1="-124"
+ x2="-55.5975"
+ y2="-103.2075" />
+ <linearGradient
+ id="linearGradient319-95">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-242" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-44" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-43"
+ id="linearGradient22933-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(15.081669,359)"
+ x1="245.63066"
+ y1="106.28436"
+ x2="245.80791"
+ y2="94.440376" />
+ <linearGradient
+ id="linearGradient37542-43">
+ <stop
+ id="stop37544-7"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-12"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-48"
+ id="linearGradient22935-6"
+ gradientUnits="userSpaceOnUse"
+ x1="268"
+ y1="462"
+ x2="256"
+ y2="459" />
+ <linearGradient
+ id="linearGradient319-48">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-64" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-59"
+ id="linearGradient22937-4"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(12.999999,359)"
+ x1="247"
+ y1="99"
+ x2="247"
+ y2="94" />
+ <linearGradient
+ id="linearGradient10069-59">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-30" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-48"
+ id="linearGradient22939-8"
+ gradientUnits="userSpaceOnUse"
+ x1="263.5"
+ y1="455.25"
+ x2="263.5"
+ y2="460.5" />
+ <linearGradient
+ y2="460.6622"
+ x2="264"
+ y1="452"
+ x1="264"
+ gradientTransform="matrix(1,0,0,0.6,-5,182.8)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient17039"
+ xlink:href="#linearGradient319-48"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-43-6"
+ id="linearGradient22933-6-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(15.081669,359)"
+ x1="245.63066"
+ y1="106.28436"
+ x2="245.80791"
+ y2="94.440376" />
+ <linearGradient
+ id="linearGradient37542-43-6">
+ <stop
+ id="stop37544-7-2"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-12-6"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-48-6"
+ id="linearGradient22935-6-2"
+ gradientUnits="userSpaceOnUse"
+ x1="268"
+ y1="462"
+ x2="256"
+ y2="459" />
+ <linearGradient
+ id="linearGradient319-48-6">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-64-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-6-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-59-3"
+ id="linearGradient22937-4-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(12.999999,359)"
+ x1="247"
+ y1="99"
+ x2="247"
+ y2="94" />
+ <linearGradient
+ id="linearGradient10069-59-3">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-30-1" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-3-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-48-6"
+ id="linearGradient22939-8-6"
+ gradientUnits="userSpaceOnUse"
+ x1="263.5"
+ y1="455.25"
+ x2="263.5"
+ y2="460.5" />
+ <linearGradient
+ y2="460.6622"
+ x2="264"
+ y1="452"
+ x1="264"
+ gradientTransform="matrix(1,0,0,0.6,-5,182.8)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient17172"
+ xlink:href="#linearGradient319-48-6"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient319-48-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-64-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-6-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-43-3"
+ id="linearGradient22933-6-87"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(15.081669,359)"
+ x1="245.63066"
+ y1="106.28436"
+ x2="245.80791"
+ y2="94.440376" />
+ <linearGradient
+ id="linearGradient37542-43-3">
+ <stop
+ id="stop37544-7-8"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-12-4"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-48-5"
+ id="linearGradient22935-6-22"
+ gradientUnits="userSpaceOnUse"
+ x1="268"
+ y1="462"
+ x2="256"
+ y2="459" />
+ <linearGradient
+ id="linearGradient319-48-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-64-3" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-6-50" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-59-8"
+ id="linearGradient22937-4-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(12.999999,359)"
+ x1="247"
+ y1="99"
+ x2="247"
+ y2="94" />
+ <linearGradient
+ id="linearGradient10069-59-8">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-30-2" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-3-06" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-48-5"
+ id="linearGradient22939-8-3"
+ gradientUnits="userSpaceOnUse"
+ x1="263.5"
+ y1="455.25"
+ x2="263.5"
+ y2="460.5" />
+ <linearGradient
+ y2="460.6622"
+ x2="264"
+ y1="452"
+ x1="264"
+ gradientTransform="matrix(1,0,0,0.6,-5,182.8)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient17172-9"
+ xlink:href="#linearGradient319-48-5"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17438"
+ id="linearGradient17582"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-42,-19)"
+ x1="267.125"
+ y1="462.1875"
+ x2="267.25"
+ y2="450" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17596"
+ id="linearGradient17584"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-26.918331,340)"
+ x1="245.91833"
+ y1="101"
+ x2="246.02513"
+ y2="94.443054" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-48-4"
+ id="linearGradient17586"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-42,-19)"
+ x1="268"
+ y1="462"
+ x2="256"
+ y2="459" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17602"
+ id="linearGradient17588"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-29.000001,340)"
+ x1="247"
+ y1="102"
+ x2="247"
+ y2="95.409012" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient17430"
+ id="linearGradient17590"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-42,-19)"
+ x1="270.5"
+ y1="464.0625"
+ x2="270.125"
+ y2="447.0625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-48-4"
+ id="linearGradient17592"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-42,-19)"
+ x1="263.5"
+ y1="455.25"
+ x2="263.5"
+ y2="460.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-48-4"
+ id="linearGradient17594"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.6,-47,163.8)"
+ x1="264"
+ y1="452"
+ x2="264"
+ y2="460.6622" />
+ <linearGradient
+ id="linearGradient37542-1">
+ <stop
+ id="stop37544-62"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-4"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-75">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-39" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-1"
+ id="linearGradient17715"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.88913256,0,0,0.96231883,-17.039429,-158.76811)"
+ x1="30.435225"
+ y1="202.99998"
+ x2="30.435225"
+ y2="251.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-75"
+ id="linearGradient17717"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.92839719,0,0,1.1347062,0.81276468,-9.2113636)"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="18.903511"
+ y2="81.589714" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-95"
+ id="linearGradient17932"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,627.46943,130.00389)"
+ x1="86.452194"
+ y1="101.22832"
+ x2="110.48556"
+ y2="81.14637" />
+ <linearGradient
+ id="linearGradient37542-49">
+ <stop
+ id="stop37544-8"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-99"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-995">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-08" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-273" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-49"
+ id="linearGradient20080"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.172144,-379,416.1659)"
+ x1="42.033173"
+ y1="164.51399"
+ x2="75.32457"
+ y2="164.51399" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-995"
+ id="linearGradient20084"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.3333334,0,0,0.8333334,685.50001,836.08335)"
+ x1="-285.65732"
+ y1="-274.23453"
+ x2="-279.44821"
+ y2="-268.04858" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-49-3"
+ id="linearGradient20080-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.172144,-379,416.1659)"
+ x1="42.033173"
+ y1="164.51399"
+ x2="75.32457"
+ y2="164.51399" />
+ <linearGradient
+ id="linearGradient37542-49-3">
+ <stop
+ id="stop37544-8-7"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-99-8"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-49-3"
+ id="linearGradient20082-4"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(216,445.00002)"
+ x1="118.1319"
+ y1="157.11609"
+ x2="85.577972"
+ y2="157.54283" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-995-3"
+ id="linearGradient20084-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.3333334,0,0,0.8333334,685.50001,836.08335)"
+ x1="-285.65732"
+ y1="-274.23453"
+ x2="-279.44821"
+ y2="-268.04858" />
+ <linearGradient
+ id="linearGradient319-995-3">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-08-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-273-9" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-49"
+ id="linearGradient20199"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(209.99848,445.06252)"
+ x1="118.1319"
+ y1="157.11609"
+ x2="85.577972"
+ y2="157.54283" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-66-0-4-7"
+ id="linearGradient16783-1-6-0-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707654,0,0,0.707942,290.55464,214.86015)"
+ x1="35.597904"
+ y1="158.14117"
+ x2="17.012707"
+ y2="172.79289" />
+ <linearGradient
+ id="linearGradient37542-66-0-4-7">
+ <stop
+ id="stop37544-85-0-9-9"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-15-9-5-7"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4343-1-1-9-1"
+ id="linearGradient16778-3-5-3-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5990464,-0.03583042,0.03242597,0.6546824,306.65287,109.38342)"
+ x1="-12.264804"
+ y1="333.22653"
+ x2="-10.869003"
+ y2="334.86029" />
+ <linearGradient
+ id="linearGradient4343-1-1-9-1">
+ <stop
+ id="stop4345-2-9-5-6"
+ offset="0"
+ style="stop-color:white;stop-opacity:1;" />
+ <stop
+ id="stop4347-1-5-5-1"
+ offset="1"
+ style="stop-color:#fff9f9;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-73-3-4-6"
+ id="linearGradient16775-4-9-5-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(497.01612,511)"
+ x1="-190.37566"
+ y1="-180.13821"
+ x2="-189.34792"
+ y2="-182" />
+ <linearGradient
+ id="linearGradient319-73-3-4-6">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-87-5-2-2" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-66-3-7-3" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-65-4-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-14-9-5" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-49-3-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-65-4-8"
+ id="linearGradient17904-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-97,-102)"
+ x1="386.88852"
+ y1="409.84152"
+ x2="389.14081"
+ y2="412.45016" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-65-4-8"
+ id="linearGradient17893-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-106,-102)"
+ x1="387"
+ y1="409.86362"
+ x2="388.86676"
+ y2="411.88974" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-65-4-8"
+ id="linearGradient18148"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-102,-94)"
+ x1="387"
+ y1="410"
+ x2="388.78125"
+ y2="411.78125" />
+ <linearGradient
+ id="linearGradient23974-3">
+ <stop
+ id="stop23976-6"
+ offset="0"
+ style="stop-color:#a3a3a3;stop-opacity:1" />
+ <stop
+ id="stop23978-2"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-47">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-85" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-48" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient23974-3-78">
+ <stop
+ id="stop23976-6-5"
+ offset="0"
+ style="stop-color:#a3a3a3;stop-opacity:1" />
+ <stop
+ id="stop23978-2-4"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16504-0">
+ <stop
+ id="stop16506-3"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ <stop
+ id="stop16508-0"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-47-9">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-85-3" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-48-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-36-6-5"
+ id="linearGradient17833-9"
+ gradientUnits="userSpaceOnUse"
+ x1="209"
+ y1="238"
+ x2="226.625"
+ y2="251.71078"
+ gradientTransform="translate(144,188)" />
+ <linearGradient
+ id="linearGradient1610-36-6-5">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-1-9-6" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-5-9-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-36-6-7"
+ id="linearGradient17833-8"
+ gradientUnits="userSpaceOnUse"
+ x1="209"
+ y1="238"
+ x2="226.625"
+ y2="251.71078"
+ gradientTransform="translate(144,188)" />
+ <linearGradient
+ id="linearGradient1610-36-6-7">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-1-9-4" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-5-9-87" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-96"
+ id="linearGradient20796-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(159.9998,-41.00751)"
+ x1="261.44702"
+ y1="234.6606"
+ x2="274.30609"
+ y2="247.73561" />
+ <linearGradient
+ id="linearGradient37542-96">
+ <stop
+ id="stop37544-7-1"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-0"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-37"
+ id="linearGradient20798-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(199.9999,105.99249)"
+ x1="235.46884"
+ y1="103"
+ x2="228.71886"
+ y2="94.53125" />
+ <linearGradient
+ id="linearGradient10069-37">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-0" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-9"
+ id="linearGradient39254-3"
+ 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" />
+ <linearGradient
+ id="linearGradient1610-9">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-4-7" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-09" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40578-4-8-9"
+ id="radialGradient39256-2"
+ 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
+ id="linearGradient40578-4-8-9">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop40580-8-9-0" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop40582-6-8-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334-2"
+ id="linearGradient39258-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(670,-33)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ id="linearGradient58334-2">
+ <stop
+ id="stop58336-97"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.87628865;" />
+ <stop
+ id="stop58338-90"
+ 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="linearGradient16151"
+ xlink:href="#linearGradient16500-49"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-49">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-16" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-7409-7-7-19-1-1"
+ id="linearGradient79029"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.1666676,0,0,-1.1666676,795.08409,370.66085)"
+ x1="262.04343"
+ y1="233.0448"
+ x2="273.85818"
+ y2="247.32738" />
+ <linearGradient
+ id="linearGradient37542-7409-7-7-19-1-1">
+ <stop
+ id="stop37544-48-6-1-8-9-3"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-82-1-0-6-8-2"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8-4-7-8-3-0-3-6"
+ id="linearGradient79025"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.53706486,0,0,0.53706486,426.82889,65.03941)"
+ x1="97.616623"
+ y1="39.47208"
+ x2="94.157646"
+ y2="35.759052" />
+ <linearGradient
+ id="linearGradient44939-8-4-7-8-3-0-3-6">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop44941-8-5-40-2-4-2-4-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop44943-2-5-9-4-9-8-0-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-5-4-6-5-0-3-6"
+ id="linearGradient79020"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.53706486,0,0,-0.53706486,531.01948,106.93034)"
+ x1="97.616623"
+ y1="39.47208"
+ x2="94.157646"
+ y2="35.759052" />
+ <linearGradient
+ id="linearGradient10069-9-7-5-4-6-5-0-3-6">
+ <stop
+ style="stop-color:#252525;stop-opacity:1"
+ offset="0"
+ id="stop10071-5-4-58-5-9-1-2-1-9" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-43-0-4-0-8-0-4-9-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient81143-4"
+ id="linearGradient80406-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.58017143,0,0,0.92830994,410.31278,270.33169)"
+ x1="-187.57428"
+ y1="63.340904"
+ x2="-157.37125"
+ y2="79.243309" />
+ <linearGradient
+ id="linearGradient81143-4">
+ <stop
+ style="stop-color:#2561b7;stop-opacity:1"
+ offset="0"
+ id="stop81145-0" />
+ <stop
+ style="stop-color:#f9fbff;stop-opacity:1"
+ offset="1"
+ id="stop81147-7" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15487-1-8-4-3"
+ id="linearGradient80403-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.92827429,0,0,0.92830994,60.469415,101.37929)"
+ x1="254.19243"
+ y1="237.48314"
+ x2="273.92343"
+ y2="254.49823" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient15487-1-8-4-3">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15489-3-2-3-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15491-4-4-1-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-40-9"
+ id="linearGradient81258"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.99995186,0,0,0.99980511,154.9567,150.99846)"
+ x1="123.80291"
+ y1="90.165237"
+ x2="142.64377"
+ y2="105.8204" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-84-1"
+ id="linearGradient81260"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1004102,0,0,1.0993832,229.31341,141.82572)"
+ x1="45.107925"
+ y1="91.099701"
+ x2="51.546276"
+ y2="96.026611" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-84-3-2"
+ id="linearGradient81262"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1004102,0,0,1.0993832,235.27474,141.76351)"
+ x1="46.007988"
+ y1="90.678802"
+ x2="50.907307"
+ y2="95.401253" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14829"
+ id="linearGradient14814"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4126967,0,0,2.7035619,-722.19531,285.57729)"
+ x1="236.94902"
+ y1="-14.103641"
+ x2="276.89801"
+ y2="32.076183" />
+ <linearGradient
+ id="linearGradient14829">
+ <stop
+ id="stop14831"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop14833"
+ offset="1"
+ style="stop-color:#757575;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14632"
+ id="linearGradient14816"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-214.43013,42.779961)"
+ x1="148.54834"
+ y1="301.96149"
+ x2="166.33298"
+ y2="317.25269" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient14632">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop14634" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop14636" />
+ </linearGradient>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath13106-0">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ id="path34850-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" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ x="-0.45600089"
+ width="1.9120018"
+ y="-0.50666559"
+ height="2.0133312"
+ id="filter63011-8"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.899998"
+ id="feGaussianBlur63013-0" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060-9"
+ id="linearGradient14818"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-233.12445,-35.715412)"
+ x1="160.14388"
+ y1="376.27383"
+ x2="174.29811"
+ y2="383.69843" />
+ <linearGradient
+ id="linearGradient5060-9">
+ <stop
+ id="stop5062-0"
+ offset="0"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ id="stop5064-7"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821-9"
+ id="radialGradient14820"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <linearGradient
+ id="linearGradient18821-9">
+ <stop
+ style="stop-color:#fc6b58;stop-opacity:1;"
+ offset="0"
+ id="stop18823-1" />
+ <stop
+ style="stop-color:#fc6b58;stop-opacity:0;"
+ offset="1"
+ id="stop18825-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient39155-5"
+ id="linearGradient14822"
+ gradientUnits="userSpaceOnUse"
+ x1="31.1875"
+ y1="18.875"
+ x2="29.875"
+ y2="34.375" />
+ <linearGradient
+ id="linearGradient39155-5">
+ <stop
+ id="stop39157-4"
+ offset="0"
+ style="stop-color:white;stop-opacity:1;" />
+ <stop
+ id="stop39159-1"
+ offset="1"
+ style="stop-color:#dadada;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3564-9"
+ id="linearGradient14825"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.06818845,0,0,0.06818845,22.51112,27.02885)"
+ x1="185.9903"
+ y1="193.33229"
+ x2="190.46461"
+ y2="-458.05771" />
+ <linearGradient
+ id="linearGradient3564-9"
+ inkscape:collect="always">
+ <stop
+ id="stop3566-9"
+ offset="0"
+ style="stop-color:white;stop-opacity:1;" />
+ <stop
+ id="stop3568-2"
+ offset="1"
+ style="stop-color:white;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient39171-8"
+ id="radialGradient14827"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.647222,0,0,1.26792,-15.47413,-5.79794)"
+ cx="26.109201"
+ cy="19.668886"
+ fx="26.109201"
+ fy="19.668886"
+ r="20.278975" />
+ <linearGradient
+ id="linearGradient39171-8"
+ inkscape:collect="always">
+ <stop
+ id="stop39173-9"
+ offset="0"
+ style="stop-color:white;stop-opacity:1;" />
+ <stop
+ id="stop39175-5"
+ offset="1"
+ style="stop-color:white;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14829"
+ id="linearGradient14800"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,-169.92789,274.92229)"
+ x1="243.92192"
+ y1="-2.6686089"
+ x2="275.10107"
+ y2="26.600887" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14605"
+ id="linearGradient14802"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-13.427886,57.417785)"
+ x1="87"
+ y1="241.125"
+ x2="90.764404"
+ y2="243.87347" />
+ <linearGradient
+ id="linearGradient14605">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.56485355;"
+ offset="0"
+ id="stop14607" />
+ <stop
+ style="stop-color:#fffffe;stop-opacity:0;"
+ offset="1"
+ id="stop14609" />
+ </linearGradient>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath22590-7">
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22592-5-0"
+ width="12"
+ height="14"
+ x="-30"
+ y="490.00012" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13998-5"
+ id="linearGradient14804"
+ gradientUnits="userSpaceOnUse"
+ x1="13.5"
+ y1="57.827747"
+ x2="11.472005"
+ y2="53.875874" />
+ <linearGradient
+ id="linearGradient13998-5">
+ <stop
+ id="stop14000-00"
+ offset="0"
+ style="stop-color:#f57d07;stop-opacity:1;" />
+ <stop
+ id="stop14002-54"
+ offset="1"
+ style="stop-color:white;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13998-5"
+ id="linearGradient14806"
+ gradientUnits="userSpaceOnUse"
+ x1="-18.600719"
+ y1="501.96539"
+ x2="-26.642899"
+ y2="487.60382" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-53"
+ id="linearGradient14808"
+ gradientUnits="userSpaceOnUse"
+ x1="15.027407"
+ y1="60.637787"
+ x2="13.5"
+ y2="57.750687" />
+ <linearGradient
+ id="linearGradient319-53">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-1-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-61" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-53"
+ id="linearGradient14810"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.03018343,0.1408617)"
+ x1="-32.067383"
+ y1="490.70178"
+ x2="-22.25"
+ y2="500" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-1">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-41" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-4" />
+ </linearGradient>
+ <linearGradient
+ y2="305"
+ x2="758"
+ y1="299.83005"
+ x1="753.39417"
+ gradientTransform="translate(-683.42789,-5.5822151)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient20368"
+ xlink:href="#linearGradient16500-1"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-41-8-0-7-1"
+ id="linearGradient16663-3-0-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-6.0080883)"
+ x1="184.95361"
+ y1="115.79691"
+ x2="235.24524"
+ y2="119.04691" />
+ <linearGradient
+ id="linearGradient37542-41-8-0-7-1">
+ <stop
+ id="stop37544-5-2-6-6-5"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-8-6-8-7-2"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-41-8-0-7-4"
+ id="linearGradient16663-3-0-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-6.0080883)"
+ x1="179.3838"
+ y1="116.92558"
+ x2="235.24524"
+ y2="119.04691" />
+ <linearGradient
+ id="linearGradient37542-41-8-0-7-4">
+ <stop
+ id="stop37544-5-2-6-6-9"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-8-6-8-7-3"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-7-8-6-0"
+ id="radialGradient106344-5"
+ cx="386.68588"
+ cy="247.46175"
+ fx="386.68588"
+ fy="247.46175"
+ r="2.3794625"
+ gradientTransform="matrix(4.5687397,-0.29531319,0.13355055,5.747731,-1415.8878,-1055.5606)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient37542-7-8-6-0">
+ <stop
+ id="stop37544-40-1-3-9"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop37546-94-7-0-7"
+ offset="1"
+ style="stop-color:#030303;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ y2="245.04375"
+ x2="400.77301"
+ y1="243.97655"
+ x1="385.67264"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient106307-2"
+ xlink:href="#linearGradient319-488-8-2"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient319-488-8-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-13-8-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-67-2-2" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient106427"
+ id="radialGradient106433"
+ cx="383.96912"
+ cy="249.87636"
+ fx="383.96912"
+ fy="249.87636"
+ r="2.3794624"
+ gradientTransform="matrix(4.5686863,-0.29541184,0.13359632,5.7477127,-1403.7889,-1070.199)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-7-8-6-0-8"
+ id="radialGradient106344-5-2"
+ cx="386.68588"
+ cy="247.46175"
+ fx="386.68588"
+ fy="247.46175"
+ r="2.3794625"
+ gradientTransform="matrix(4.5687397,-0.29531319,0.13355055,5.747731,-1415.8878,-1055.5606)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient37542-7-8-6-0-8">
+ <stop
+ id="stop37544-40-1-3-9-3"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop37546-94-7-0-7-1"
+ offset="1"
+ style="stop-color:#030303;stop-opacity:1" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient106427-3"
+ id="radialGradient106433-4"
+ cx="383.96912"
+ cy="249.87636"
+ fx="383.96912"
+ fy="249.87636"
+ r="2.3794625"
+ gradientTransform="matrix(4.5686863,-0.29541184,0.13359632,5.7477127,-1403.7889,-1070.199)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient106427-3">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop106429-1" />
+ <stop
+ style="stop-color:#030303;stop-opacity:1"
+ offset="1"
+ id="stop106431-0" />
+ </linearGradient>
+ <linearGradient
+ y2="245.04375"
+ x2="400.77301"
+ y1="243.97655"
+ x1="385.67264"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient106307-2-4"
+ xlink:href="#linearGradient319-488-8-2-0"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient319-488-8-2-0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-13-8-8-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-67-2-2-9" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610-36-6-7-9">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-1-9-4-5" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-5-9-87-3" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610-36-6-7-9-4">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-1-9-4-5-0" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-5-9-87-3-7" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-36-6-7-9"
+ id="linearGradient106628"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(64,338)"
+ x1="209"
+ y1="238"
+ x2="226.625"
+ y2="251.71078" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-36-6-7-9-4"
+ id="linearGradient106641"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(39.8125,337.625)"
+ x1="209"
+ y1="238"
+ x2="226.625"
+ y2="251.71078" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-1-1-9-4-7-1"
+ id="linearGradient106804"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,513.5,184.50451)"
+ x1="253.78497"
+ y1="3.6831069"
+ x2="278.40161"
+ y2="29.679312" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40578-4-8-4-0-5-2-4-7"
+ id="radialGradient106806"
+ 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="#linearGradient58334-24-8-2-6-0-2"
+ id="linearGradient106808"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(670,-33)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-11-1-4-3-1"
+ id="linearGradient106810"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-95.999998)"
+ x1="754.28558"
+ y1="300.83292"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3944-1-7-5-7-7"
+ id="linearGradient106812"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-251,440.9872)"
+ x1="215.99414"
+ y1="592.95746"
+ x2="218.99957"
+ y2="601.36218" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3952-5-7-6-8-9"
+ id="linearGradient106814"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-251,440.9872)"
+ x1="213.00005"
+ y1="597.41553"
+ x2="216.00003"
+ y2="604.375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-8-9-6-4-5"
+ id="linearGradient106816"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-251,440.9872)"
+ x1="218.06126"
+ y1="601.83856"
+ x2="219.5"
+ y2="606.11218" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-8-9-6-4-5"
+ id="linearGradient106818"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-251,440.9872)"
+ x1="219"
+ y1="604.31494"
+ x2="221"
+ y2="609.36218" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3944-4-6-7-7"
+ id="linearGradient106820"
+ gradientUnits="userSpaceOnUse"
+ x1="215.99414"
+ y1="592.95746"
+ x2="218.99957"
+ y2="601.36218" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3952-2-6-4-4"
+ id="linearGradient106822"
+ gradientUnits="userSpaceOnUse"
+ x1="213.00005"
+ y1="597.41553"
+ x2="216.00003"
+ y2="604.375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-5-1-45-4"
+ id="linearGradient106824"
+ gradientUnits="userSpaceOnUse"
+ x1="218.06126"
+ y1="601.83856"
+ x2="219.5"
+ y2="606.11218" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-5-1-45-4"
+ id="linearGradient106826"
+ gradientUnits="userSpaceOnUse"
+ x1="219"
+ y1="604.31494"
+ x2="221"
+ y2="609.36218" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient107148"
+ id="radialGradient107138"
+ gradientUnits="userSpaceOnUse"
+ cx="12.465761"
+ cy="353.51611"
+ fx="12.465761"
+ fy="353.51611"
+ r="2.91875"
+ gradientTransform="matrix(0.84360011,0.04170664,-0.04937856,0.99878013,19.37109,-0.08239219)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient107142"
+ id="linearGradient107140"
+ gradientUnits="userSpaceOnUse"
+ x1="11.695067"
+ y1="352.60217"
+ x2="16.773348"
+ y2="358.90598" />
+ <radialGradient
+ r="2.91875"
+ fy="353.59497"
+ fx="12.128428"
+ cy="353.59497"
+ cx="12.128428"
+ gradientTransform="matrix(0.2864009,1.1071441,-1.0639391,0.27522442,384.79448,242.64422)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient107490"
+ xlink:href="#linearGradient107519"
+ inkscape:collect="always" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15097-0-8"
+ id="radialGradient15836-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.14826933,2.1671891,-2.0135104,-0.13775545,-42.975294,-475.30953)"
+ cx="327.72662"
+ cy="-102.09388"
+ fx="327.72662"
+ fy="-102.09388"
+ r="3.3160801" />
+ <linearGradient
+ id="linearGradient15097-0-8">
+ <stop
+ style="stop-color:#c4c4c4;stop-opacity:1"
+ offset="0"
+ id="stop15099-1-83" />
+ <stop
+ style="stop-color:#868686;stop-opacity:1"
+ offset="1"
+ id="stop15101-9-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974-5-2-6-6"
+ id="linearGradient15851-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.2185076,0,0,1.1902393,14.075854,397.20828)"
+ x1="-88.73024"
+ y1="-120.6127"
+ x2="-78.787354"
+ y2="-128.30418" />
+ <linearGradient
+ id="linearGradient23974-5-2-6-6">
+ <stop
+ id="stop23976-9-2-7-6"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop23978-3-1-6-0"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31320-5-2-6-7"
+ id="linearGradient15818-5"
+ 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-5-2-6-7">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop31322-5-4-5-8" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop31324-0-8-5-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262-9-5-9-4"
+ id="linearGradient15846-4"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.2185076,0,0,1.1902393,92.990431,-50.358654)"
+ x1="-20.864969"
+ y1="250.35432"
+ x2="-34.640823"
+ y2="264.67712" />
+ <linearGradient
+ id="linearGradient14262-9-5-9-4">
+ <stop
+ id="stop14264-5-2-9-0"
+ offset="0"
+ style="stop-color:#2661b6;stop-opacity:1;" />
+ <stop
+ id="stop14266-0-4-4-2"
+ offset="1"
+ style="stop-color:#c1d7f8;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-92-8-5-0"
+ id="linearGradient15843-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.99098745,0,0,1.0233007,7.9488742,191.90653)"
+ x1="113.17896"
+ y1="49.395184"
+ x2="111.81031"
+ y2="62.520573" />
+ <linearGradient
+ id="linearGradient319-92-8-5-0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-40-7-9-3" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-93-7-0-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-92-8-5-0"
+ id="linearGradient16562-7"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.99098745,0,0,1.0233007,7.9488742,191.90653)"
+ x1="114.36164"
+ y1="22.752264"
+ x2="104.74062"
+ y2="65.241188" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15959-9-5"
+ id="linearGradient15773-7"
+ gradientUnits="userSpaceOnUse"
+ x1="113.07384"
+ y1="252.04327"
+ x2="119.9112"
+ y2="249.41632"
+ gradientTransform="matrix(1.2133883,0,0,1.2133883,-25.22919,-53.154498)" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient15959-9-5">
+ <stop
+ style="stop-color:#4d4d4d;stop-opacity:1;"
+ offset="0"
+ id="stop15961-9-6" />
+ <stop
+ style="stop-color:#4d4d4d;stop-opacity:0;"
+ offset="1"
+ id="stop15963-8-7" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16723"
+ id="linearGradient16730"
+ x1="112.5"
+ y1="252.5"
+ x2="116.5"
+ y2="250"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16764"
+ id="linearGradient16800"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,112.64335,0.1875)"
+ x1="63.643349"
+ y1="354.8125"
+ x2="60.996902"
+ y2="359.97281" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16772"
+ id="linearGradient16802"
+ gradientUnits="userSpaceOnUse"
+ x1="63.847855"
+ y1="353.1496"
+ x2="61.116474"
+ 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"
+ gradientTransform="translate(220,-20.00667)"
+ x1="29.4034"
+ y1="100.99999"
+ x2="34.095703"
+ y2="101.15624" />
+ <linearGradient
+ id="linearGradient23705-0">
+ <stop
+ id="stop23707-9"
+ offset="0"
+ style="stop-color:#d4d2bf;stop-opacity:1;" />
+ <stop
+ id="stop23709-4"
+ offset="1"
+ style="stop-color:#857f5d;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24168-8"
+ id="linearGradient22954-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.75,0,0,0.7516675,227.625,0.9640803)"
+ x1="20.125"
+ y1="88.642494"
+ x2="34.125"
+ y2="104.89799" />
+ <linearGradient
+ id="linearGradient24168-8">
+ <stop
+ id="stop24170-2"
+ offset="0"
+ style="stop-color:#182437;stop-opacity:1;" />
+ <stop
+ id="stop24172-4"
+ offset="1"
+ style="stop-color:#2b4163;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-51"
+ id="radialGradient22952-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6595012,0.7907318,-0.8990144,0.7498135,144.69896,-187.59854)"
+ cx="262.67139"
+ cy="74.072273"
+ fx="262.67139"
+ fy="74.072273"
+ r="3.5" />
+ <linearGradient
+ id="linearGradient319-51">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-51"
+ id="linearGradient22928-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8750002,0,0,0.83767,7.3124969,247.00379)"
+ x1="27.166666"
+ y1="90.504448"
+ x2="35.166668"
+ y2="101.14744" />
+ <linearGradient
+ id="linearGradient29791">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop29793" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop29795" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821-2"
+ id="radialGradient22950-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.53241"
+ cy="500.20956"
+ fx="75.53241"
+ fy="500.20956"
+ r="3.1650217" />
+ <linearGradient
+ id="linearGradient18821-2">
+ <stop
+ style="stop-color:#fc6b58;stop-opacity:1;"
+ offset="0"
+ id="stop18823-7" />
+ <stop
+ style="stop-color:#fc6b58;stop-opacity:0;"
+ offset="1"
+ id="stop18825-6" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-51"
+ id="radialGradient22922-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4564959,0.09949388,-0.06177986,1.3917691,-283.96093,-143.81911)"
+ cx="135.14931"
+ cy="332.10181"
+ fx="135.14931"
+ fy="332.10181"
+ r="3.5" />
+ <linearGradient
+ id="linearGradient29802">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop29804" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop29806" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060-2"
+ id="linearGradient22917-4"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2,0,0,0.7333333,-467,262.53823)"
+ x1="250.5"
+ y1="90.253998"
+ x2="250.5"
+ y2="95.252274" />
+ <linearGradient
+ id="linearGradient5060-2">
+ <stop
+ id="stop5062-3"
+ offset="0"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ id="stop5064-2"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-51"
+ id="radialGradient23727-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.3687636,0.09935874,-0.05957343,1.3898788,-272.60513,-143.17133)"
+ cx="140.33667"
+ cy="333.05716"
+ fx="140.33667"
+ fy="333.05716"
+ r="3.5" />
+ <linearGradient
+ id="linearGradient29813">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop29815" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop29817" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient107519"
+ id="radialGradient30077"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2864009,1.1071441,-1.0639391,0.27522442,384.79448,242.64422)"
+ cx="12.128428"
+ cy="353.59497"
+ fx="12.128428"
+ fy="353.59497"
+ r="2.91875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16764"
+ id="linearGradient30079"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,112.64335,0.1875)"
+ x1="63.643349"
+ y1="354.8125"
+ x2="60.996902"
+ y2="359.97281" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16772"
+ id="linearGradient30081"
+ gradientUnits="userSpaceOnUse"
+ x1="63.847855"
+ y1="353.1496"
+ x2="61.116474"
+ y2="360.82117" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient107519"
+ id="radialGradient30090"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2864009,1.1071441,-1.0639391,0.27522442,384.79448,242.64422)"
+ cx="12.128428"
+ cy="353.59497"
+ fx="12.128428"
+ fy="353.59497"
+ r="2.91875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16764"
+ id="linearGradient30092"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,112.64335,0.1875)"
+ x1="63.643349"
+ y1="354.8125"
+ x2="60.996902"
+ y2="359.97281" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16772"
+ id="linearGradient30094"
+ gradientUnits="userSpaceOnUse"
+ x1="63.847855"
+ y1="353.1496"
+ x2="61.116474"
+ y2="360.82117" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16772"
+ id="linearGradient30097"
+ gradientUnits="userSpaceOnUse"
+ x1="63.847855"
+ y1="353.1496"
+ x2="61.116474"
+ y2="360.82117"
+ gradientTransform="matrix(-1,0,0,1,112.28991,0.1875)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16764"
+ id="linearGradient30100"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,112.28991,0.1875)"
+ x1="63.643349"
+ y1="354.8125"
+ x2="60.996902"
+ y2="359.97281" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30122"
+ id="linearGradient30129"
+ x1="48.5"
+ y1="354.75"
+ x2="51"
+ y2="360.25"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30131"
+ id="linearGradient30137"
+ x1="60.289909"
+ y1="361.0625"
+ x2="63.789909"
+ y2="354.0625"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30139"
+ id="linearGradient30145"
+ x1="63.789909"
+ y1="355.0625"
+ x2="61.039909"
+ y2="360.0625"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-36-6-7-9-4-3"
+ id="linearGradient106641-3"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(39.8125,337.625)"
+ x1="209"
+ y1="238"
+ x2="226.625"
+ y2="251.71078" />
+ <linearGradient
+ id="linearGradient1610-36-6-7-9-4-3">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-1-9-4-5-0-6" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-5-9-87-3-7-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27496"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="121.22078"
+ y2="56.357628" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27498"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(207,-246.99988)"
+ x1="-56.5"
+ y1="342.0625"
+ x2="-49"
+ y2="341" />
+ <linearGradient
+ id="linearGradient37542-9">
+ <stop
+ id="stop37544-6"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-7"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15541">
+ <stop
+ id="stop15543"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop15545"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-1">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-0" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37542-41-8-0-7-1-3">
+ <stop
+ id="stop37544-5-2-6-6-5-3"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-8-6-8-7-2-0"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-1-7"
+ id="linearGradient15721-8-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(19.97577,-6.0080883)"
+ x1="227.57907"
+ y1="118.47696"
+ x2="235"
+ y2="118.5" />
+ <linearGradient
+ id="linearGradient319-1-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-4-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-0-0" />
+ </linearGradient>
+ <linearGradient
+ y2="118.5"
+ x2="235"
+ y1="118.47696"
+ x1="227.57907"
+ gradientTransform="translate(265.62095,336.21475)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient15670-3"
+ xlink:href="#linearGradient319-1-7-2"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient319-1-7-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-4-4-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-0-0-5" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37542-41-8-0-7-4-0">
+ <stop
+ id="stop37544-5-2-6-6-9-0"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-8-6-8-7-3-2"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15647-2">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop15649-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop15651-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-1-7-0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-4-4-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-0-0-2" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-1-7-2-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-4-4-0-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-0-0-5-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15647-1">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop15649-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop15651-2" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-1-7-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-4-4-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-0-0-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-1-7-2-7"
+ id="linearGradient15975-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(267.4022,339.9335)"
+ x1="227.57907"
+ y1="118.47696"
+ x2="235"
+ y2="118.5" />
+ <linearGradient
+ id="linearGradient319-1-7-2-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-4-4-0-2" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-0-0-5-5" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15647-3">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop15649-12" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop15651-7" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-1-7-1">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-4-4-00" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-0-0-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-1-7-2-9">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-4-4-0-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-0-0-5-9" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37542-7-0">
+ <stop
+ id="stop37544-40-9"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-94-1"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-3">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-3" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-06" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15647-14">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop15649-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop15651-72" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-1-7-02">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-4-4-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-0-0-48" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-1-7-2-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-4-4-0-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-0-0-5-7" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610-04">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-8" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069-7">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-9" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-28">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-23" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-2" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16389">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop16391" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop16393" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15647-14-2">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop15649-7-5" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop15651-72-3" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-1-7-02-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-4-4-8-3" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-0-0-48-7" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-1-7-2-4-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-4-4-0-4-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-0-0-5-7-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-1-7-5"
+ id="linearGradient16591-3"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(266.10421,337.79176)"
+ x1="224.37904"
+ y1="118.78525"
+ x2="236.37904"
+ y2="118.78525" />
+ <linearGradient
+ id="linearGradient319-1-7-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-4-4-3" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-0-0-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15796"
+ id="linearGradient15802"
+ x1="192.4323"
+ y1="348.13098"
+ x2="208.33328"
+ y2="359.81409"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15806"
+ id="linearGradient15804"
+ x1="212.0226"
+ y1="361.34204"
+ x2="194.68611"
+ y2="348.34918"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient319-715">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-74" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-58" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15840">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15842" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15844" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15847">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15849" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15851" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-75">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-17" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-64" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15858">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15860" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15862" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient5060-97">
+ <stop
+ id="stop5062-5"
+ offset="0"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ id="stop5064-5"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15869">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15871" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15873" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-8"
+ id="linearGradient35740-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707654,0,0,0.707942,-206.46148,-296.13985)"
+ x1="35.597904"
+ y1="158.14117"
+ x2="10.490564"
+ y2="176.41806" />
+ <linearGradient
+ id="linearGradient37542-8">
+ <stop
+ id="stop37544-64"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-5"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-93"
+ id="linearGradient35742-9"
+ gradientUnits="userSpaceOnUse"
+ x1="58.060974"
+ y1="-23.721956"
+ x2="40"
+ y2="-35" />
+ <linearGradient
+ id="linearGradient1610-93">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-83" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-75"
+ id="linearGradient35744-6"
+ gradientUnits="userSpaceOnUse"
+ x1="46.1875"
+ y1="-28.59375"
+ x2="41.099998"
+ y2="-33.59375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient36116-7"
+ id="linearGradient35746-7"
+ gradientUnits="userSpaceOnUse"
+ x1="46"
+ y1="-32"
+ x2="43.883884"
+ y2="-33.939339" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient36116-7">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop36118-4" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop36120-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-75"
+ id="linearGradient35750-3"
+ gradientUnits="userSpaceOnUse"
+ x1="48.662914"
+ y1="-27.071922"
+ x2="43.47097"
+ y2="-32.337086" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-715"
+ id="linearGradient35752-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(6.3,-4.7)"
+ x1="39.200001"
+ y1="-30.799999"
+ x2="41.200001"
+ y2="-28.640625" />
+ <linearGradient
+ id="linearGradient15902">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15904" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15906" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-715"
+ id="linearGradient35754-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(5.315625,-3.75)"
+ x1="39.200001"
+ y1="-30.799999"
+ x2="41.325001"
+ y2="-28.765625" />
+ <linearGradient
+ id="linearGradient15909">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15911" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15913" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-715"
+ id="linearGradient35756-7"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(3.3,0.3)"
+ x1="38.700001"
+ y1="-31.299999"
+ x2="40.012501"
+ y2="-29.799999" />
+ <linearGradient
+ id="linearGradient15916">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15918" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15920" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-75"
+ id="linearGradient35772-6"
+ gradientUnits="userSpaceOnUse"
+ x1="51.912914"
+ y1="-24.696922"
+ x2="40.75"
+ y2="-35.75"
+ gradientTransform="translate(-0.75,4.75)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-715"
+ id="linearGradient35748-0"
+ gradientUnits="userSpaceOnUse"
+ x1="41"
+ y1="-29"
+ x2="43"
+ y2="-27" />
+ <linearGradient
+ id="linearGradient15930">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15932" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15934" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-715"
+ id="linearGradient16186"
+ gradientUnits="userSpaceOnUse"
+ x1="41"
+ y1="-29"
+ x2="43"
+ y2="-27"
+ gradientTransform="translate(412,489)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-75"
+ id="linearGradient16189"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(411.25,493.75)"
+ x1="51.912914"
+ y1="-24.696922"
+ x2="40.75"
+ y2="-35.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-715"
+ id="linearGradient16194"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(415.3,489.3)"
+ x1="38.700001"
+ y1="-31.299999"
+ x2="40.012501"
+ y2="-29.799999" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-715"
+ id="linearGradient16197"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(417.31562,485.25)"
+ x1="39.200001"
+ y1="-30.799999"
+ x2="41.325001"
+ y2="-28.765625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-715"
+ id="linearGradient16200"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(418.3,484.3)"
+ x1="39.200001"
+ y1="-30.799999"
+ x2="41.200001"
+ y2="-28.640625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-75"
+ id="linearGradient16203"
+ gradientUnits="userSpaceOnUse"
+ x1="48.662914"
+ y1="-27.071922"
+ x2="43.47097"
+ y2="-32.337086"
+ gradientTransform="translate(412,489)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient36116-7"
+ id="linearGradient16208"
+ gradientUnits="userSpaceOnUse"
+ x1="46"
+ y1="-32"
+ x2="43.883884"
+ y2="-33.939339"
+ gradientTransform="translate(412,489)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-75"
+ id="linearGradient16211"
+ gradientUnits="userSpaceOnUse"
+ x1="46.1875"
+ y1="-28.59375"
+ x2="41.099998"
+ y2="-33.59375"
+ gradientTransform="translate(412,489)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-93"
+ id="linearGradient16214"
+ gradientUnits="userSpaceOnUse"
+ x1="58.060974"
+ y1="-23.721956"
+ x2="40"
+ y2="-35"
+ gradientTransform="translate(412,489)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-715"
+ id="linearGradient16252"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(417.31562,485.25)"
+ x1="39.200001"
+ y1="-30.799999"
+ x2="41.325001"
+ y2="-28.765625" />
+ <linearGradient
+ id="linearGradient319-6">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-87" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-64" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15804-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15806" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15808-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15811">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15813-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15815" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15818">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15820" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15822" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15825">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15827" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15829" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-6"
+ id="linearGradient15998"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-65.00001,-10.749995)"
+ x1="61.032951"
+ y1="5.9830923"
+ x2="46.491322"
+ y2="20.147326" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-6"
+ id="linearGradient16000"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.199998,0,0,1.199999,-74.19988,-12.499988)"
+ x1="59.02124"
+ y1="6.0129876"
+ x2="44.509518"
+ y2="20.110929" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-6"
+ id="linearGradient16003"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-64,-10)"
+ x1="18.773417"
+ y1="6.2494373"
+ x2="6.9718256"
+ y2="17.82831" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-6"
+ id="linearGradient16006"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.701513,0.712657,0.712657,0.701513,50.5916,-449.6745)"
+ x1="385.62408"
+ y1="244.3396"
+ x2="401.63013"
+ y2="244.38875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-6"
+ id="linearGradient16056"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-64,-10)"
+ x1="18.773417"
+ y1="6.2494373"
+ x2="6.9718256"
+ y2="17.82831" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-6"
+ id="linearGradient16058"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.701513,0.712657,0.712657,0.701513,50.5916,-449.6745)"
+ x1="385.62408"
+ y1="244.3396"
+ x2="401.63013"
+ y2="244.38875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-6"
+ id="linearGradient16084"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-65.00001,-10.749995)"
+ x1="61.032951"
+ y1="5.9830923"
+ x2="46.491322"
+ y2="20.147326" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-6"
+ id="linearGradient16086"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.199998,0,0,1.199999,-74.19988,-12.499988)"
+ x1="59.02124"
+ y1="6.0129876"
+ x2="44.509518"
+ y2="20.110929" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient25417-9"
+ id="linearGradient40731-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.997161,-259.00079,67.35344)"
+ x1="280.0918"
+ y1="129.28557"
+ x2="267.20212"
+ y2="116.41341" />
+ <linearGradient
+ id="linearGradient25417-9">
+ <stop
+ id="stop25419-9"
+ offset="0"
+ style="stop-color:#60553b;stop-opacity:1;" />
+ <stop
+ id="stop25421-2"
+ offset="1"
+ style="stop-color:#b0a17f;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-17-1-6-6"
+ id="linearGradient40733-04"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.7972867,-259.00009,90.24189)"
+ x1="255.63673"
+ y1="99.513062"
+ x2="275.1503"
+ y2="129.36641" />
+ <linearGradient
+ id="linearGradient319-17-1-6-6">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-115-1-5-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-27-3-7-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-6-1">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-87-5" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-64-0" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16451">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop16453" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop16455" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-6-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-87-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-64-1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16520">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop16522" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop16524" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-6-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-87-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-64-3" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-6-9">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-87-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-64-2" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16838">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop16840" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop16842" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-6-40">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-87-2" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-64-5" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16838-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop16840-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop16842-8" />
+ </linearGradient>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask18666-3">
+ <rect
+ y="6"
+ x="62.921577"
+ height="14.000001"
+ width="15.098035"
+ id="rect18668-4"
+ style="fill:url(#linearGradient18670-3);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.50000000000000000;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-08"
+ id="linearGradient18670-3"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2078427,0,0,1.0516432,-357.40769,69.427229)"
+ x1="362.28571"
+ y1="-45.098213"
+ x2="352.46426"
+ y2="-54.124699" />
+ <linearGradient
+ id="linearGradient1610-08">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-2" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-48" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069-33">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-7" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-36" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient17205">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop17207" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop17209" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37542-0">
+ <stop
+ id="stop37544-77"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-2"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-14">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-27" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-629" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient23974-0">
+ <stop
+ id="stop23976-205"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop23978-6"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-5-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-761-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-8-1" />
+ </linearGradient>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath28964-0">
+ <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:url(#linearGradient28968);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;enable-background:new"
+ d="m 117.50984,228.63415 0,-15.01646 11.71735,5.49383 0,15.38271 -11.71735,-5.86008 z"
+ id="path28966-5" />
+ </clipPath>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask29419-5">
+ <path
+ inkscape:connector-curvature="0"
+ id="path29422-9"
+ d="m 117.50984,229.00041 0,-15.38272 11.71735,5.49383 0,15.74897 -11.71735,-5.86008 z"
+ style="opacity:0.50000000000000000;fill:url(#linearGradient29424-4);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;enable-background:new"
+ sodipodi:nodetypes="ccccc"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-7-8"
+ id="linearGradient29424-4"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.4646688,0,0,1.4650206,168.77325,-157.03253)"
+ x1="-26.511335"
+ y1="257.99881"
+ x2="-30.075666"
+ y2="259.87677" />
+ <linearGradient
+ id="linearGradient37542-7-8">
+ <stop
+ id="stop37544-40-5"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-94-0"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient21327-6-8-9">
+ <stop
+ style="stop-color:#1e3e70;stop-opacity:1;"
+ offset="0"
+ id="stop21329-3-4-7" />
+ <stop
+ style="stop-color:#1e3e70;stop-opacity:0;"
+ offset="1"
+ id="stop21331-4-0-6" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069-9-71-7">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-5-1-6" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-43-5-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069-9-71-7-2">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-5-1-6-2" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-43-5-4-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18118-8">
+ <stop
+ style="stop-color:#cd8ce9;stop-opacity:1"
+ offset="0"
+ id="stop18120-5" />
+ <stop
+ style="stop-color:#9425c1;stop-opacity:1"
+ offset="1"
+ id="stop18122-5" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18103-9">
+ <stop
+ id="stop18105-3"
+ offset="0"
+ style="stop-color:#42035d;stop-opacity:1" />
+ <stop
+ id="stop18108-4"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18134-9"
+ id="linearGradient18140-0"
+ x1="121.48092"
+ y1="105.24046"
+ x2="137.67349"
+ y2="126.34584"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient18134-9">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop18136-5" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop18138-9" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18118-8"
+ id="radialGradient18260"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6671799,6.7886038e-8,-6.7869731e-8,0.66734014,43.604995,38.604049)"
+ cx="129.99182"
+ cy="114.84092"
+ fx="129.99182"
+ fy="114.84092"
+ r="8.781251" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18134-9"
+ id="linearGradient18262"
+ gradientUnits="userSpaceOnUse"
+ x1="121.48092"
+ y1="105.24046"
+ x2="137.67349"
+ y2="126.34584" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18103"
+ id="linearGradient18264"
+ gradientUnits="userSpaceOnUse"
+ x1="123.80045"
+ y1="111.03492"
+ x2="130.94904"
+ y2="118.11919" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18118"
+ id="radialGradient18266"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.09893643,0.88659058,-0.70877161,0.07913125,199.3109,-8.5183197)"
+ cx="129.83784"
+ cy="115.58929"
+ fx="129.83784"
+ fy="115.58929"
+ r="8.7812506" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18134"
+ id="linearGradient18268"
+ gradientUnits="userSpaceOnUse"
+ x1="121.48092"
+ y1="105.24046"
+ x2="136.95143"
+ y2="123.69764" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath31849-4">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 232.13187,93.950853 4.84276,0 4.23742,4.237465 0,4.842822 -9.08018,0 0,-9.080287 0,0 z"
+ id="path31851-6"
+ sodipodi:nodetypes="cccccc" />
+ </clipPath>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18118-8-8"
+ id="radialGradient18260-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6671799,6.7886038e-8,-6.7869731e-8,0.66734014,43.604995,38.604049)"
+ cx="129.99182"
+ cy="114.84092"
+ fx="129.99182"
+ fy="114.84092"
+ r="8.781251" />
+ <linearGradient
+ id="linearGradient18118-8-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop18120-5-0" />
+ <stop
+ style="stop-color:#7b7b7b;stop-opacity:1;"
+ offset="1"
+ id="stop18122-5-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18134-9-1"
+ id="linearGradient18262-3"
+ gradientUnits="userSpaceOnUse"
+ x1="121.48092"
+ y1="105.24046"
+ x2="137.67349"
+ y2="126.34584" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient18134-9-1">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop18136-5-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop18138-9-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18103-1"
+ id="linearGradient18264-4"
+ gradientUnits="userSpaceOnUse"
+ x1="123.80045"
+ y1="111.03492"
+ x2="130.94904"
+ y2="118.11919" />
+ <linearGradient
+ id="linearGradient18103-1">
+ <stop
+ id="stop18105-2"
+ offset="0"
+ style="stop-color:#42035d;stop-opacity:1" />
+ <stop
+ id="stop18108-8"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18118-0"
+ id="radialGradient18266-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.09893643,0.88659058,-0.70877161,0.07913125,199.3109,-8.5183197)"
+ cx="129.83784"
+ cy="115.58929"
+ fx="129.83784"
+ fy="115.58929"
+ r="8.781251" />
+ <linearGradient
+ id="linearGradient18118-0">
+ <stop
+ style="stop-color:#d297eb;stop-opacity:1;"
+ offset="0"
+ id="stop18120-4" />
+ <stop
+ style="stop-color:#a329d6;stop-opacity:1;"
+ offset="1"
+ id="stop18122-52" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18134-0"
+ id="linearGradient18268-0"
+ gradientUnits="userSpaceOnUse"
+ x1="121.48092"
+ y1="105.24046"
+ x2="136.95143"
+ y2="123.69764" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient18134-0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop18136-2" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop18138-5" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18118-8"
+ id="radialGradient19005"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6671799,6.7886038e-8,-6.7869731e-8,0.66734014,43.604995,38.604049)"
+ cx="129.99182"
+ cy="114.84092"
+ fx="129.99182"
+ fy="114.84092"
+ r="8.781251" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18134-9"
+ id="linearGradient19007"
+ gradientUnits="userSpaceOnUse"
+ x1="121.48092"
+ y1="105.24046"
+ x2="137.67349"
+ y2="126.34584" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18103"
+ id="linearGradient19009"
+ gradientUnits="userSpaceOnUse"
+ x1="123.80045"
+ y1="111.03492"
+ x2="130.94904"
+ y2="118.11919" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18118"
+ id="radialGradient19011"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.09893643,0.88659058,-0.70877161,0.07913125,199.3109,-8.5183197)"
+ cx="129.83784"
+ cy="115.58929"
+ fx="129.83784"
+ fy="115.58929"
+ r="8.7812506" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18134"
+ id="linearGradient19013"
+ gradientUnits="userSpaceOnUse"
+ x1="121.48092"
+ y1="105.24046"
+ x2="136.95143"
+ y2="123.69764" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18118-8"
+ id="radialGradient19034"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6671799,6.7886038e-8,-6.7869731e-8,0.66734014,43.604995,38.604049)"
+ cx="129.99182"
+ cy="114.84092"
+ fx="129.99182"
+ fy="114.84092"
+ r="8.781251" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18134-9"
+ id="linearGradient19036"
+ gradientUnits="userSpaceOnUse"
+ x1="121.48092"
+ y1="105.24046"
+ x2="137.67349"
+ y2="126.34584" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18103"
+ id="linearGradient19038"
+ gradientUnits="userSpaceOnUse"
+ x1="123.80045"
+ y1="111.03492"
+ x2="130.94904"
+ y2="118.11919" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18118"
+ id="radialGradient19040"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.09893643,0.88659058,-0.70877161,0.07913125,199.3109,-8.5183197)"
+ cx="129.83784"
+ cy="115.58929"
+ fx="129.83784"
+ fy="115.58929"
+ r="8.7812506" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18134"
+ id="linearGradient19042"
+ gradientUnits="userSpaceOnUse"
+ x1="121.48092"
+ y1="105.24046"
+ x2="136.95143"
+ y2="123.69764" />
+ <linearGradient
+ id="linearGradient40455-7-1-5">
+ <stop
+ id="stop40457-6-6-2"
+ offset="0"
+ style="stop-color:#fff991;stop-opacity:1;" />
+ <stop
+ id="stop40459-1-8-5"
+ offset="1"
+ style="stop-color:#fffbb9;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient40578-4-8-7-6">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop40580-8-9-6-8" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop40582-6-8-1-2" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient58334-9-6">
+ <stop
+ id="stop58336-27-0"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.87628865;" />
+ <stop
+ id="stop58338-9-7"
+ 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(1,-94.999998)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient37610-3-9"
+ xlink:href="#linearGradient16500-4-9"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-4-9">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-31-5" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-23-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient40455-7-1-5-1">
+ <stop
+ id="stop40457-6-6-2-9"
+ offset="0"
+ style="stop-color:#fff991;stop-opacity:1;" />
+ <stop
+ id="stop40459-1-8-5-0"
+ offset="1"
+ style="stop-color:#fffbb9;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient40578-4-8-7-6-5">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop40580-8-9-6-8-2" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop40582-6-8-1-2-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient58334-9-6-3">
+ <stop
+ id="stop58336-27-0-6"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.87628865;" />
+ <stop
+ id="stop58338-9-7-0"
+ 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(1,-94.999998)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient15428-6"
+ xlink:href="#linearGradient16500-4-9-3"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-4-9-3">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-31-5-8" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-23-4-6" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37542-8-6">
+ <stop
+ id="stop37544-64-8"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-5-9"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610-93-2">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-83-7" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-0-7" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-715-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-74-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-58-1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15669">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15671" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15673" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15683-0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15685" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15687" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-715-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-74-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-58-2" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15876">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15878" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15880" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15883">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15885" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15887" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15894">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15896" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15898" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient5060-97-8">
+ <stop
+ id="stop5062-5-3"
+ offset="0"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ id="stop5064-5-0"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15905">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15907" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15909" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37542-8-7">
+ <stop
+ id="stop37544-64-6"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-5-6"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610-93-1">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-83-5" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-0-1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-715-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-74-63" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-58-9" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16099">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop16101" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop16103-5" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16113">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop16115" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop16117" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37542-8-78">
+ <stop
+ id="stop37544-64-1"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-5-0"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610-93-9">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-83-8" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-0-3" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-715-9">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-74-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-58-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16099-6">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop16101-5" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop16103-7" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16113-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop16115-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop16117-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15806"
+ id="linearGradient15581"
+ gradientUnits="userSpaceOnUse"
+ x1="212.0226"
+ y1="361.34204"
+ x2="189.32315"
+ y2="340.89514" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15796"
+ id="linearGradient15583"
+ gradientUnits="userSpaceOnUse"
+ x1="192.4323"
+ y1="348.13098"
+ x2="208.33328"
+ y2="359.81409" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15796"
+ id="linearGradient16354"
+ gradientUnits="userSpaceOnUse"
+ x1="189.32315"
+ y1="340.89514"
+ x2="205.17293"
+ y2="357.81213" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15806"
+ id="linearGradient16399"
+ gradientUnits="userSpaceOnUse"
+ x1="212.0226"
+ y1="361.34204"
+ x2="189.32315"
+ y2="340.89514" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15796"
+ id="linearGradient16401"
+ gradientUnits="userSpaceOnUse"
+ x1="189.32315"
+ y1="340.89514"
+ x2="205.17293"
+ y2="357.81213" />
+ <linearGradient
+ id="linearGradient319-57">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-20" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-83" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15625">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15627" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15629" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15632">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15634" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15636" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient23974-3-78-2">
+ <stop
+ id="stop23976-6-5-7"
+ offset="0"
+ style="stop-color:#a3a3a3;stop-opacity:1" />
+ <stop
+ id="stop23978-2-4-4"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16504-0-4">
+ <stop
+ id="stop16506-3-6"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ <stop
+ id="stop16508-0-1"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-47-9-0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-85-3-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-48-3-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-12-5-0"
+ id="linearGradient42487-4-5-2"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ id="linearGradient319-12-5-0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-34-1-3" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-81-9-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425-8-7-5"
+ id="linearGradient42489-5-9-1"
+ gradientUnits="userSpaceOnUse"
+ x1="123.26987"
+ y1="108.56933"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ id="linearGradient15425-8-7-5">
+ <stop
+ style="stop-color:#8c0000;stop-opacity:1;"
+ offset="0"
+ id="stop15427-5-9-7" />
+ <stop
+ style="stop-color:#c80000;stop-opacity:0;"
+ offset="1"
+ id="stop15429-7-2-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-12-5-0"
+ id="linearGradient42491-0-9-1"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ id="linearGradient15695">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop15697" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop15699" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425-8-7-5"
+ id="linearGradient17232-8-1"
+ gradientUnits="userSpaceOnUse"
+ x1="123.26987"
+ y1="108.56933"
+ x2="141.64546"
+ y2="130.81215" />
+ <linearGradient
+ id="linearGradient15702">
+ <stop
+ style="stop-color:#8c0000;stop-opacity:1;"
+ offset="0"
+ id="stop15704" />
+ <stop
+ style="stop-color:#c80000;stop-opacity:0;"
+ offset="1"
+ id="stop15706" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-0"
+ id="linearGradient42326-4"
+ gradientUnits="userSpaceOnUse"
+ x1="124.8772"
+ y1="110.75571"
+ x2="133.97179"
+ y2="117.77643" />
+ <linearGradient
+ id="linearGradient10069-0">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-75" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-44"
+ id="linearGradient42328-9"
+ gradientUnits="userSpaceOnUse"
+ x1="129.32576"
+ y1="223.61363"
+ x2="123.33967"
+ y2="217.06438" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-44">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-2" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-9" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-54"
+ id="linearGradient42330-3"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="142.64723"
+ y2="129.05313" />
+ <linearGradient
+ id="linearGradient319-54">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-68" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-7" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-54"
+ id="linearGradient16613"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="142.64723"
+ y2="129.05313" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-07"
+ id="linearGradient14167-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-636.98388,52.01562)"
+ x1="443.86667"
+ y1="133.98936"
+ x2="451.98389"
+ y2="143.58749" />
+ <linearGradient
+ id="linearGradient37542-07">
+ <stop
+ id="stop37544-66"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-6"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4138-3"
+ id="linearGradient14169-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-635.98388,53.01562)"
+ x1="456.03769"
+ y1="135.76678"
+ x2="453.61005"
+ y2="133.00301" />
+ <linearGradient
+ id="linearGradient4138-3">
+ <stop
+ style="stop-color:#6c432f;stop-opacity:1;"
+ offset="0"
+ id="stop4140-2" />
+ <stop
+ style="stop-color:#c0966d;stop-opacity:1;"
+ offset="1"
+ id="stop4142-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-07"
+ id="linearGradient14171-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-636.98388,52.01562)"
+ x1="449.14645"
+ y1="136.18045"
+ x2="453.24457"
+ y2="138.7879" />
+ <linearGradient
+ id="linearGradient16636">
+ <stop
+ id="stop16638"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop16640"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4138-3"
+ id="linearGradient14173-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-635.98388,53.01562)"
+ x1="456.03769"
+ y1="135.76678"
+ x2="454.31345"
+ y2="133.62801" />
+ <linearGradient
+ id="linearGradient16643">
+ <stop
+ style="stop-color:#6c432f;stop-opacity:1;"
+ offset="0"
+ id="stop16645" />
+ <stop
+ style="stop-color:#c0966d;stop-opacity:1;"
+ offset="1"
+ id="stop16647" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-2"
+ id="linearGradient14167-87"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-636.98388,52.01562)"
+ x1="443.86667"
+ y1="133.98936"
+ x2="451.98389"
+ y2="143.58749" />
+ <linearGradient
+ id="linearGradient37542-2">
+ <stop
+ id="stop37544-5"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-1"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4138-39"
+ id="linearGradient14169-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-635.98388,53.01562)"
+ x1="456.03769"
+ y1="135.76678"
+ x2="453.61005"
+ y2="133.00301" />
+ <linearGradient
+ id="linearGradient4138-39">
+ <stop
+ style="stop-color:#6c432f;stop-opacity:1;"
+ offset="0"
+ id="stop4140-0" />
+ <stop
+ style="stop-color:#c0966d;stop-opacity:1;"
+ offset="1"
+ id="stop4142-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-2"
+ id="linearGradient14171-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-636.98388,52.01562)"
+ x1="449.14645"
+ y1="136.18045"
+ x2="453.24457"
+ y2="138.7879" />
+ <linearGradient
+ id="linearGradient16738">
+ <stop
+ id="stop16740"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop16742"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4138-39"
+ id="linearGradient14173-89"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-635.98388,53.01562)"
+ x1="456.03769"
+ y1="135.76678"
+ x2="454.31345"
+ y2="133.62801" />
+ <linearGradient
+ id="linearGradient16745">
+ <stop
+ style="stop-color:#6c432f;stop-opacity:1;"
+ offset="0"
+ id="stop16747" />
+ <stop
+ style="stop-color:#c0966d;stop-opacity:1;"
+ offset="1"
+ id="stop16749" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-07-7"
+ id="linearGradient14167-8-4"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-636.98388,52.01562)"
+ x1="443.86667"
+ y1="133.98936"
+ x2="451.98389"
+ y2="143.58749" />
+ <linearGradient
+ id="linearGradient37542-07-7">
+ <stop
+ id="stop37544-66-6"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-6-7"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4138-3-7"
+ id="linearGradient14169-0-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-635.98388,53.01562)"
+ x1="456.03769"
+ y1="135.76678"
+ x2="453.61005"
+ y2="133.00301" />
+ <linearGradient
+ id="linearGradient4138-3-7">
+ <stop
+ style="stop-color:#6c432f;stop-opacity:1;"
+ offset="0"
+ id="stop4140-2-0" />
+ <stop
+ style="stop-color:#c0966d;stop-opacity:1;"
+ offset="1"
+ id="stop4142-0-7" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-07-7"
+ id="linearGradient14171-2-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-636.98388,52.01562)"
+ x1="449.14645"
+ y1="136.18045"
+ x2="453.24457"
+ y2="138.7879" />
+ <linearGradient
+ id="linearGradient16840">
+ <stop
+ id="stop16842-2"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop16844"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4138-3-7"
+ id="linearGradient14173-8-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-635.98388,53.01562)"
+ x1="456.03769"
+ y1="135.76678"
+ x2="454.31345"
+ y2="133.62801" />
+ <linearGradient
+ id="linearGradient16847">
+ <stop
+ style="stop-color:#6c432f;stop-opacity:1;"
+ offset="0"
+ id="stop16849" />
+ <stop
+ style="stop-color:#c0966d;stop-opacity:1;"
+ offset="1"
+ id="stop16851" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-9"
+ id="linearGradient42346-4"
+ gradientUnits="userSpaceOnUse"
+ x1="-57.780041"
+ y1="48.005856"
+ x2="-78.812721"
+ y2="31" />
+ <linearGradient
+ id="linearGradient319-9">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-98" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-56" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-9"
+ id="linearGradient42344-3"
+ gradientUnits="userSpaceOnUse"
+ x1="-69.457596"
+ y1="31.914484"
+ x2="-76.564636"
+ y2="28.695114" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-9">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-21" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-22"
+ id="linearGradient42346-5"
+ gradientUnits="userSpaceOnUse"
+ x1="-57.780041"
+ y1="48.005856"
+ x2="-78.812721"
+ y2="31" />
+ <linearGradient
+ id="linearGradient319-22">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-61" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-3" />
+ </linearGradient>
+ <linearGradient
+ y2="31"
+ x2="-78.812721"
+ y1="48.005856"
+ x1="-57.780041"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient17071"
+ xlink:href="#linearGradient319-22"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient319-91">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-01" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient13938-6">
+ <stop
+ id="stop13940-6"
+ offset="0"
+ style="stop-color:#6e0c00;stop-opacity:1;" />
+ <stop
+ id="stop13942-0"
+ offset="1"
+ style="stop-color:#ee3800;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient29073">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop29075" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop29077" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16595-2">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop16597-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop16599-9" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-1-7-5-6">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-4-4-3-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-0-0-8-6" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610-3">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-3" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient40578-4-8-1">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop40580-8-9-2" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop40582-6-8-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient58334-93">
+ <stop
+ id="stop58336-4"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.87628865;" />
+ <stop
+ id="stop58338-1"
+ offset="1.0000000"
+ style="stop-color:#fffffe;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-5"
+ id="linearGradient39260-4"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-95.999998)"
+ x1="754.28558"
+ y1="300.83292"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-5">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-311" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-5" />
+ </linearGradient>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask43050-6">
+ <rect
+ y="-122"
+ x="-24"
+ height="14"
+ width="16"
+ id="rect43052-3"
+ style="opacity:0.5;fill:url(#linearGradient43054-6);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44627-7"
+ id="linearGradient43054-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.3333333,0,0,1.2727273,2.6666667,29.454545)"
+ x1="-4.2231579"
+ y1="-92.440941"
+ x2="-18.697306"
+ y2="-115.04018" />
+ <linearGradient
+ id="linearGradient44627-7">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop44629-4" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop44631-0" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-5-1-8-2-5"
+ id="radialGradient24295-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1558466,-0.5928702,0.3902392,0.7608013,47.408342,-36.891937)"
+ cx="-14.226811"
+ cy="-115.06647"
+ fx="-14.226811"
+ fy="-115.06647"
+ r="7.1500001" />
+ <linearGradient
+ id="linearGradient10069-9-5-1-8-2-5">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-5-43-3-0-0-4" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-43-1-8-2-5-2" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-5-1-8-2-5"
+ id="radialGradient24297-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3236133,-0.01520056,0.01787935,0.3806433,-7.6938144,-72.764853)"
+ cx="-20.110701"
+ cy="-125.53457"
+ fx="-20.110701"
+ fy="-125.53457"
+ r="7.1500001" />
+ <linearGradient
+ id="linearGradient13837">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop13839" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop13841" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-4-74-1"
+ id="radialGradient24299-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.0312701,-2.5000045,2.468554,-0.03087567,251.90641,-216.06454)"
+ cx="-39.154209"
+ cy="-118.1383"
+ fx="-39.154209"
+ fy="-118.1383"
+ r="1" />
+ <linearGradient
+ id="linearGradient10069-9-7-4-74-1">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-5-4-5-0-5" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-43-0-5-9-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-4-74-1"
+ id="linearGradient33126-9"
+ gradientUnits="userSpaceOnUse"
+ x1="110.81759"
+ y1="99.274445"
+ x2="131.81595"
+ y2="116.38528" />
+ <linearGradient
+ id="linearGradient13848">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop13850" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop13852" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8-5"
+ id="linearGradient33128-2"
+ gradientUnits="userSpaceOnUse"
+ x1="128.0486"
+ y1="112.48544"
+ x2="135.0885"
+ y2="121.2344" />
+ <linearGradient
+ id="linearGradient44939-8-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop44941-8-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop44943-2-7" />
+ </linearGradient>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask48816-8">
+ <rect
+ y="-84"
+ x="-44"
+ height="14"
+ width="13"
+ id="rect48818-4"
+ style="opacity:0.85;fill:url(#radialGradient48820-9);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
+ </mask>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44627-7"
+ id="radialGradient48820-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.0769231,0,5.9230769)"
+ cx="-31"
+ cy="-83.5"
+ fx="-31"
+ fy="-83.5"
+ r="6.5" />
+ <linearGradient
+ id="linearGradient13861">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop13863" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop13865" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-4-4"
+ id="linearGradient24279-6"
+ gradientUnits="userSpaceOnUse"
+ x1="122.80294"
+ y1="107.95783"
+ x2="133.00108"
+ y2="118.79662" />
+ <linearGradient
+ id="linearGradient10069-9-7-4-4">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-5-4-5-8" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-43-0-5-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-09"
+ id="linearGradient24281-3"
+ gradientUnits="userSpaceOnUse"
+ x1="127.94764"
+ y1="111.77869"
+ x2="139.37589"
+ y2="126.95278" />
+ <linearGradient
+ id="linearGradient44939-09">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop44941-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop44943-0" />
+ </linearGradient>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask13875">
+ <rect
+ y="-84"
+ x="-44"
+ height="14"
+ width="13"
+ id="rect13877"
+ style="opacity:0.85;fill:url(#radialGradient48820-9);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
+ </mask>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44627-7"
+ id="radialGradient13879"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.0769231,0,5.9230769)"
+ cx="-31"
+ cy="-83.5"
+ fx="-31"
+ fy="-83.5"
+ r="6.5" />
+ <linearGradient
+ id="linearGradient13881">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop13883" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop13885" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-4-4"
+ id="linearGradient24283-7"
+ gradientUnits="userSpaceOnUse"
+ x1="122.80294"
+ y1="107.95783"
+ x2="133.00108"
+ y2="118.79662" />
+ <linearGradient
+ id="linearGradient13888">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop13890" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop13892" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-09"
+ id="linearGradient24285-8"
+ gradientUnits="userSpaceOnUse"
+ x1="127.94764"
+ y1="111.77869"
+ x2="139.90622"
+ y2="126.33406" />
+ <linearGradient
+ id="linearGradient13895">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop13897" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop13899" />
+ </linearGradient>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask28585-8">
+ <rect
+ style="opacity:0.85;fill:url(#radialGradient28589-9);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ id="rect28587-2"
+ width="13"
+ height="14"
+ x="-44"
+ y="-84" />
+ </mask>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44627-7"
+ id="radialGradient28589-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.0769231,0,5.9230769)"
+ cx="-30.28125"
+ cy="-84.341515"
+ fx="-30.28125"
+ fy="-84.341515"
+ r="6.5" />
+ <linearGradient
+ id="linearGradient13904">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop13906" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop13908" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-4-4"
+ id="linearGradient24287-1"
+ gradientUnits="userSpaceOnUse"
+ x1="122.80294"
+ y1="107.95783"
+ x2="133.00108"
+ y2="118.79662" />
+ <linearGradient
+ id="linearGradient13911">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop13913" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop13915" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-09"
+ id="linearGradient24289-3"
+ gradientUnits="userSpaceOnUse"
+ x1="127.94764"
+ y1="111.77869"
+ x2="141.05528"
+ y2="129.25089" />
+ <linearGradient
+ id="linearGradient13918">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop13920" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop13922" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-4-4"
+ id="linearGradient24241-6"
+ gradientUnits="userSpaceOnUse"
+ x1="128.72093"
+ y1="113.87833"
+ x2="134.73141"
+ y2="121.3562" />
+ <linearGradient
+ id="linearGradient13925">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop13927" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop13929" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-09"
+ id="linearGradient24243-1"
+ gradientUnits="userSpaceOnUse"
+ x1="127.94764"
+ y1="111.77869"
+ x2="140.59081"
+ y2="129.0453" />
+ <linearGradient
+ id="linearGradient13932">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop13934" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop13936" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-4-4"
+ id="linearGradient24245-3"
+ gradientUnits="userSpaceOnUse"
+ x1="122.85946"
+ y1="108.45374"
+ x2="132.08098"
+ y2="118.71043" />
+ <linearGradient
+ id="linearGradient13939">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop13941" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop13943" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-09"
+ id="linearGradient24247-8"
+ gradientUnits="userSpaceOnUse"
+ x1="127.94764"
+ y1="111.77869"
+ x2="142.87355"
+ y2="131.66185" />
+ <linearGradient
+ id="linearGradient13946">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop13948" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop13950" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43271-3"
+ id="linearGradient24249-9"
+ gradientUnits="userSpaceOnUse"
+ x1="-38.5"
+ y1="-52.5"
+ x2="-37"
+ y2="-54" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient43271-3">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop43273-4" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop43275-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43271-3"
+ id="linearGradient24251-6"
+ gradientUnits="userSpaceOnUse"
+ x1="-43.5"
+ y1="-56"
+ x2="-39"
+ y2="-52" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-09"
+ id="linearGradient24253-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2489483,0,0,0.2448135,-72.383415,-81.330431)"
+ x1="135.91603"
+ y1="121.04676"
+ x2="125.4409"
+ y2="99.924934" />
+ <linearGradient
+ id="linearGradient13964">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop13966" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop13968" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43271-3"
+ id="linearGradient24255-6"
+ gradientUnits="userSpaceOnUse"
+ x1="130.92398"
+ y1="110.40864"
+ x2="122.93221"
+ y2="108.93221" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-4-4"
+ id="linearGradient24257-6"
+ gradientUnits="userSpaceOnUse"
+ x1="122.80294"
+ y1="107.95783"
+ x2="133.00108"
+ y2="118.79662" />
+ <linearGradient
+ id="linearGradient13978">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop13980" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop13982" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-09"
+ id="linearGradient24259-1"
+ gradientUnits="userSpaceOnUse"
+ x1="127.94764"
+ y1="111.77869"
+ x2="144.59082"
+ y2="133.6703" />
+ <linearGradient
+ id="linearGradient13985">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop13987" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop13989" />
+ </linearGradient>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask43040-7">
+ <rect
+ style="opacity:0.5;fill:url(#linearGradient43044-5);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect43042-9"
+ width="15"
+ height="16"
+ x="-45.04018"
+ y="-24"
+ rx="0"
+ ry="0" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43760-6-4"
+ id="linearGradient43044-5"
+ gradientUnits="userSpaceOnUse"
+ x1="-44.709698"
+ y1="-8.4836445"
+ x2="-37.784756"
+ y2="-18.517523"
+ gradientTransform="translate(-0.04018164,0)" />
+ <linearGradient
+ id="linearGradient43760-6-4">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop43762-7-3" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop43764-8-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030-71-3"
+ id="linearGradient24236-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,-242.99992,269.00357)"
+ x1="202.85626"
+ y1="276.47174"
+ x2="212.82164"
+ y2="288.37567" />
+ <linearGradient
+ id="linearGradient9030-71-3">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop9032-15-3" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop9034-276-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-5-1-1"
+ id="linearGradient24239-1"
+ gradientUnits="userSpaceOnUse"
+ x1="125.93652"
+ y1="111.8362"
+ x2="132.65851"
+ y2="117.92533" />
+ <linearGradient
+ id="linearGradient10069-9-5-1-1">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-5-43-3-3" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-43-1-8-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-5-1-1"
+ id="linearGradient24230-5"
+ gradientUnits="userSpaceOnUse"
+ x1="117.00603"
+ y1="104.51898"
+ x2="132.99687"
+ y2="118.98331" />
+ <linearGradient
+ id="linearGradient14006">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop14008" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop14010" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-2-8"
+ id="linearGradient24232-9"
+ gradientUnits="userSpaceOnUse"
+ x1="128.0486"
+ y1="112.48544"
+ x2="139.58116"
+ y2="126.8241" />
+ <linearGradient
+ id="linearGradient44939-2-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop44941-7-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop44943-7-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-5-1-1"
+ id="linearGradient24234-7"
+ gradientUnits="userSpaceOnUse"
+ x1="117.00603"
+ y1="104.51898"
+ x2="132.99687"
+ y2="118.98331" />
+ <linearGradient
+ id="linearGradient14017">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop14019" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop14021" />
+ </linearGradient>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask45865-7">
+ <g
+ id="g45867-3"
+ transform="translate(-14,0)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cssssssc"
+ id="path45869-7"
+ d="m -25.801826,-135.3217 c -0.907684,-0.32824 -0.906457,-1.55361 -0.440107,-2.23642 0.834186,-1.22138 2.593738,-1.15244 3.63669,-0.26277 1.530569,1.30563 1.388406,3.6923 0.08107,5.09763 -1.742467,1.8731 -4.73519,1.65156 -6.47424,-0.0993 -2.188413,-2.20322 -1.889457,-5.85971 0.277965,-7.95885 2.625036,-2.54234 6.931515,-2.199 9.311783,0.46129 2.764074,3.08924 2.372937,7.82808 -0.06591,10.77438"
+ style="fill:none;stroke:#ffffff;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ mask="none" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path45871-2"
+ d="m -19.40866,-140.32008 c 2.764074,3.08924 2.372937,7.82808 -0.06591,10.77438"
+ style="fill:none;stroke:url(#linearGradient45875-0);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"
+ mask="none"
+ style="fill:none;stroke:url(#radialGradient45877-1);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 -25.801826,-135.3217 c -0.907684,-0.32824 -0.906457,-1.55361 -0.440107,-2.23642 0.834186,-1.22138 2.593738,-1.15244 3.63669,-0.26277"
+ id="path45873-6"
+ sodipodi:nodetypes="css" />
+ </g>
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43760-7"
+ id="linearGradient45875-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(14,0)"
+ x1="-34.051685"
+ y1="-129.32457"
+ x2="-32.542458"
+ y2="-139.90228" />
+ <linearGradient
+ id="linearGradient43760-7">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop43762-79" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop43764-3" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43760-7"
+ id="radialGradient45877-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.1099414,-0.9422316,0.4519816,0.05273803,38.220416,-152.21215)"
+ cx="-25.452209"
+ cy="-136.46503"
+ fx="-25.452209"
+ fy="-136.46503"
+ r="8.0066185" />
+ <linearGradient
+ id="linearGradient14033">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop14035" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop14037" />
+ </linearGradient>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask45447-7">
+ <rect
+ ry="0"
+ style="opacity:0.8;fill:url(#radialGradient45451-2);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect45449-4"
+ width="15"
+ height="15"
+ x="216"
+ y="366" />
+ </mask>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43760-7"
+ id="radialGradient45451-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.9952162,167.99999,-60.91415)"
+ cx="59.000011"
+ cy="440.0191"
+ fx="59.000011"
+ fy="440.0191"
+ r="6.5080619" />
+ <linearGradient
+ id="linearGradient14042">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop14044" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop14046" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-42-9"
+ id="linearGradient24218-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166695,0,0,0.9203753,-10.025729,345.78566)"
+ x1="80.60067"
+ y1="108.47212"
+ x2="68.0271"
+ y2="94.239906" />
+ <linearGradient
+ id="linearGradient319-42-9">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-32-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-21-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-0"
+ id="linearGradient24220-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-15.983875,338)"
+ x1="70.55275"
+ y1="97.5"
+ x2="79.355118"
+ y2="107.18619" />
+ <linearGradient
+ id="linearGradient10069-9-7-0">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-5-4-2" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-43-0-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-42-9"
+ id="linearGradient24222-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9998599,0,0,0.9960071,-15.972985,338.41149)"
+ x1="61.465469"
+ y1="88.058716"
+ x2="86.00116"
+ y2="112.03586" />
+ <linearGradient
+ id="linearGradient14057">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop14059" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop14061" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-0"
+ id="radialGradient24224-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.9952162,0,2.085841)"
+ cx="60.007744"
+ cy="441.04678"
+ fx="60.007744"
+ fy="441.04678"
+ r="6.5080619" />
+ <linearGradient
+ id="linearGradient14064">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop14066" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop14068" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-4-4"
+ id="linearGradient24226-2"
+ gradientUnits="userSpaceOnUse"
+ x1="113.01286"
+ y1="99.778664"
+ x2="132"
+ y2="118" />
+ <linearGradient
+ id="linearGradient14071">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop14073" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop14075" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-09"
+ id="linearGradient24228-5"
+ gradientUnits="userSpaceOnUse"
+ x1="128.0486"
+ y1="112.48544"
+ x2="136.08115"
+ y2="122.99075" />
+ <linearGradient
+ id="linearGradient14078">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop14080" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop14082" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-4-4"
+ id="linearGradient24214-1"
+ gradientUnits="userSpaceOnUse"
+ x1="118.73534"
+ y1="106.55459"
+ x2="133.00108"
+ y2="118.79662" />
+ <linearGradient
+ id="linearGradient14085">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop14087" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop14089" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-09"
+ id="linearGradient24216-4"
+ gradientUnits="userSpaceOnUse"
+ x1="127.94764"
+ y1="111.77869"
+ x2="140.59081"
+ y2="129.0453" />
+ <linearGradient
+ id="linearGradient14092">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop14094" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop14096" />
+ </linearGradient>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath43135-6">
+ <path
+ inkscape:connector-curvature="0"
+ id="path43137-1"
+ d="m -46,52 16,-16 -16,0 0,16 z"
+ style="opacity:0.5;fill:#ffff00;fill-rule:evenodd;stroke:none" />
+ </clipPath>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask43188-4">
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.5;fill:url(#linearGradient43192-3);fill-rule:evenodd;stroke:none"
+ d="m -46,52 16,-16 -16,0 0,16 z"
+ id="path43190-2" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-5-2"
+ id="linearGradient43192-3"
+ gradientUnits="userSpaceOnUse"
+ x1="-47"
+ y1="44"
+ x2="-43"
+ y2="44" />
+ <linearGradient
+ id="linearGradient1610-5-2">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-17-2" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-115-1" />
+ </linearGradient>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath43178-6">
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.5;fill:#ffff00;fill-rule:evenodd;stroke:none"
+ d="m -30,36 -1,0 -15,15 0,1 16,0 0,-16 z"
+ id="path43180-8"
+ sodipodi:nodetypes="cccccc" />
+ </clipPath>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask43182-5">
+ <path
+ inkscape:connector-curvature="0"
+ id="path43184-7"
+ d="m -46,52 0,-1 15,-15 1,0 0,16 -16,0 z"
+ style="opacity:0.5;fill:url(#linearGradient43186-6);fill-rule:evenodd;stroke:none"
+ sodipodi:nodetypes="cccccc" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-5-2"
+ id="linearGradient43186-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,-1,0,6,6)"
+ x1="-47"
+ y1="44"
+ x2="-43"
+ y2="44" />
+ <linearGradient
+ id="linearGradient14111">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop14113" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop14115" />
+ </linearGradient>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath14117">
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.5;fill:#ffff00;fill-rule:evenodd;stroke:none"
+ d="m -30,36 -1,0 -15,15 0,1 16,0 0,-16 z"
+ id="path14119"
+ sodipodi:nodetypes="cccccc" />
+ </clipPath>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask14121">
+ <path
+ inkscape:connector-curvature="0"
+ id="path14123"
+ d="m -46,52 0,-1 15,-15 1,0 0,16 -16,0 z"
+ style="opacity:0.5;fill:url(#linearGradient43186-6);fill-rule:evenodd;stroke:none"
+ sodipodi:nodetypes="cccccc" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-5-2"
+ id="linearGradient14125"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,-1,0,6,6)"
+ x1="-47"
+ y1="44"
+ x2="-43"
+ y2="44" />
+ <linearGradient
+ id="linearGradient14127">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop14129" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop14131" />
+ </linearGradient>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath14133">
+ <path
+ inkscape:connector-curvature="0"
+ id="path14135"
+ d="m -46,52 16,-16 -16,0 0,16 z"
+ style="opacity:0.5;fill:#ffff00;fill-rule:evenodd;stroke:none" />
+ </clipPath>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask14137">
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.5;fill:url(#linearGradient43192-3);fill-rule:evenodd;stroke:none"
+ d="m -46,52 16,-16 -16,0 0,16 z"
+ id="path14139" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-5-2"
+ id="linearGradient14141"
+ gradientUnits="userSpaceOnUse"
+ x1="-47"
+ y1="44"
+ x2="-43"
+ y2="44" />
+ <linearGradient
+ id="linearGradient14143">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop14145" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop14147" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-4-74-1"
+ id="linearGradient24210-1"
+ gradientUnits="userSpaceOnUse"
+ x1="110.81759"
+ y1="99.274445"
+ x2="131.81595"
+ y2="116.38528" />
+ <linearGradient
+ id="linearGradient14150">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop14152" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop14154" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8-5"
+ id="linearGradient24212-8"
+ gradientUnits="userSpaceOnUse"
+ x1="128.0486"
+ y1="112.48544"
+ x2="135.0885"
+ y2="121.2344" />
+ <linearGradient
+ id="linearGradient14157">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop14159" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop14161" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44627-7"
+ id="linearGradient24044-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21,0)"
+ x1="44.380783"
+ y1="251.66991"
+ x2="36.415714"
+ y2="247.47705" />
+ <linearGradient
+ id="linearGradient14164">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop14166" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop14168" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44627-7"
+ id="linearGradient24046-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21,0)"
+ x1="35.434578"
+ y1="250.11682"
+ x2="34"
+ y2="244" />
+ <linearGradient
+ id="linearGradient14171-1">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop14173" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop14175" />
+ </linearGradient>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask25021-4">
+ <rect
+ style="fill:url(#radialGradient25025-8);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25023-8"
+ width="13"
+ height="14"
+ x="26"
+ y="243" />
+ </mask>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44627-7"
+ id="radialGradient25025-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8918342,0,0,0.8918344,-15.699877,27.900732)"
+ cx="49"
+ cy="254.64285"
+ fx="49"
+ fy="254.64285"
+ r="6.5" />
+ <linearGradient
+ id="linearGradient14180">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop14182" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop14184" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44627-7"
+ id="radialGradient24048-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0474269,0.00526965,-0.00503098,0.9999873,-0.01415572,-0.141212)"
+ cx="27.411026"
+ cy="255.58899"
+ fx="27.411026"
+ fy="255.58899"
+ r="5.9250002" />
+ <linearGradient
+ id="linearGradient14187">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop14189" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop14191" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44627-7"
+ id="radialGradient24050-4"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0474269,0.00526965,-0.00503098,0.9999873,-0.01415572,-0.141212)"
+ cx="27.411026"
+ cy="255.58899"
+ fx="27.411026"
+ fy="255.58899"
+ r="5.9250002" />
+ <linearGradient
+ id="linearGradient14194">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop14196" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop14198" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8-5"
+ id="linearGradient24053-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21,0)"
+ x1="44.751385"
+ y1="254.98178"
+ x2="34.110981"
+ y2="244.60397" />
+ <linearGradient
+ id="linearGradient14201">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop14203" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop14205" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-4-74-1"
+ id="linearGradient24055-1"
+ gradientUnits="userSpaceOnUse"
+ x1="110.81759"
+ y1="99.274445"
+ x2="131.81595"
+ y2="116.38528" />
+ <linearGradient
+ id="linearGradient14208">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop14210" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop14212" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8-5"
+ id="linearGradient24057-7"
+ gradientUnits="userSpaceOnUse"
+ x1="128.0486"
+ y1="112.48544"
+ x2="137.44791"
+ y2="125.06842" />
+ <linearGradient
+ id="linearGradient14215">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop14217" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop14219" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-5-5"
+ id="linearGradient24022-6"
+ gradientUnits="userSpaceOnUse"
+ x1="-33.912659"
+ y1="-143.20003"
+ x2="-35.580078"
+ y2="-159.1228" />
+ <linearGradient
+ id="linearGradient10069-9-7-5-5">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-5-4-58-7" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-43-0-4-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-5-2"
+ id="linearGradient24024-4"
+ gradientUnits="userSpaceOnUse"
+ x1="-41.5"
+ y1="-161.74199"
+ x2="-40.654259"
+ y2="-147.07195" />
+ <linearGradient
+ id="linearGradient14226">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop14228" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop14230" />
+ </linearGradient>
+ <linearGradient
+ y2="-156.42979"
+ x2="-37.567211"
+ y1="-148.8125"
+ x1="-34.09375"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient61917"
+ xlink:href="#linearGradient319-76-2-0"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient319-76-2-0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-142-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-32-0" />
+ </linearGradient>
+ <linearGradient
+ y2="-156.42979"
+ x2="-37.567211"
+ y1="-148.8125"
+ x1="-34.09375"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient14482-7"
+ xlink:href="#linearGradient319-76-2-0"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient10069-8">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-91" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-30" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-50">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-368" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-54" />
+ </linearGradient>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10000"
+ objecttolerance="10000"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4"
+ inkscape:cx="208.64962"
+ inkscape:cy="493.26154"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1360"
+ inkscape:window-height="684"
+ inkscape:window-x="0"
+ inkscape:window-y="31"
+ inkscape:snap-nodes="false"
+ inkscape:snap-bbox="true"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:object-nodes="false"
+ inkscape:object-paths="false"
+ inkscape:snap-intersection-line-segments="true"
+ inkscape:snap-intersection-grid-guide="false"
+ inkscape:window-maximized="1"
+ inkscape:bbox-paths="false"
+ inkscape:snap-global="true"
+ inkscape:snap-bbox-midpoints="false"
+ inkscape:snap-grids="true"
+ inkscape:snap-to-guides="false"
+ inkscape:snap-page="false"
+ units="pt"
+ inkscape:snap-center="false"
+ inkscape:snap-object-midpoints="true">
+ <inkscape:grid
+ type="xygrid"
+ id="grid17394"
+ visible="true"
+ enabled="true"
+ spacingx="0.25px"
+ spacingy="0.25px"
+ empspacing="4"
+ color="#808080"
+ opacity="0.09803922"
+ dotted="false"
+ empcolor="#7f7f7f"
+ empopacity="0.25098039"
+ snapvisiblegridlinesonly="true"
+ originx="0px"
+ originy="-2.7755576e-17px" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Blender icons v. 2.5.08</dc:title>
+ <dc:date>21.05.2012</dc:date>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Andrzej Ambroż</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:rights>
+ <cc:Agent>
+ <dc:title>Andrzej Ambroż</dc:title>
+ </cc:Agent>
+ </dc:rights>
+ <dc:publisher>
+ <cc:Agent>
+ <dc:title>Andrzej Ambroż</dc:title>
+ </cc:Agent>
+ </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>
+ </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
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="bckgrnd"
+ style="display:none"
+ sodipodi:insensitive="true">
+ <rect
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect20607"
+ width="1083.874"
+ height="650"
+ x="-4"
+ y="-4" />
+ </g>
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#1a1a1a;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"
+ id="path23417"
+ sodipodi:nodetypes="cc"
+ d="" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path23347"
+ sodipodi:nodetypes="cc"
+ d="" />
+ <g
+ inkscape:groupmode="layer"
+ id="layer5"
+ inkscape:label="grid"
+ style="opacity:0.3;display:inline"
+ sodipodi:insensitive="true">
+ <g
+ id="g40174"
+ transform="translate(0,2)">
+ <g
+ id="g22995">
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22955"
+ width="1"
+ height="7"
+ x="422"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="401"
+ height="7"
+ width="1"
+ id="rect22957"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22959"
+ width="1"
+ height="7"
+ x="380"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="359"
+ height="7"
+ width="1"
+ id="rect22961"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22963"
+ width="1"
+ height="7"
+ x="338"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="317"
+ height="7"
+ width="1"
+ id="rect22965"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22967"
+ width="1"
+ height="7"
+ x="296"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="275"
+ height="7"
+ width="1"
+ id="rect22969"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22971"
+ width="1"
+ height="7"
+ x="254"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="233"
+ height="7"
+ width="1"
+ id="rect22973"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22975"
+ width="1"
+ height="7"
+ x="212"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="191"
+ height="7"
+ width="1"
+ id="rect22977"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22979"
+ width="1"
+ height="7"
+ x="170"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="149"
+ height="7"
+ width="1"
+ id="rect22981"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22983"
+ width="1"
+ height="7"
+ x="128"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="107"
+ height="7"
+ width="1"
+ id="rect22985"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22987"
+ width="1"
+ height="7"
+ x="86"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="65"
+ height="7"
+ width="1"
+ id="rect22989"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22991"
+ width="1"
+ height="7"
+ x="44"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="23"
+ height="7"
+ width="1"
+ id="rect22993"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="506"
+ height="7"
+ width="1"
+ id="rect23024"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23026"
+ width="1"
+ height="7"
+ x="485"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="464"
+ height="7"
+ width="1"
+ id="rect23028"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23030"
+ width="1"
+ height="7"
+ x="443"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect10985"
+ width="1"
+ height="7"
+ x="527"
+ y="0"
+ rx="0"
+ ry="0" />
+ </g>
+ <g
+ id="g24954">
+ <g
+ id="g23711"
+ transform="translate(0,462)">
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23713"
+ width="6"
+ height="1"
+ x="0"
+ y="26"
+ rx="0"
+ ry="0" />
+ <g
+ id="g23715">
+ <path
+ id="path23717"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23719"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23721"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23723"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23725"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23727"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23729"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23731"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23733"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23735"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23737"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23739"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23741"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23743"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23745"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23747"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23749"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23751"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23753"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23755"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23757"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23759"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23761"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23763"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path10987"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g23765"
+ transform="translate(0,441)">
+ <rect
+ ry="0"
+ rx="0"
+ y="26"
+ x="0"
+ height="1"
+ width="6"
+ id="rect23767"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g23769">
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23771"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23773"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23775"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23777"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23779"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23781"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23783"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23785"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23787"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23789"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23791"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23793"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23795"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23797"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23799"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23801"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23803"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23805"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23807"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23809"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23811"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23813"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23815"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23817"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10990"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g23819"
+ transform="translate(0,420)">
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23821"
+ width="6"
+ height="1"
+ x="0"
+ y="26"
+ rx="0"
+ ry="0" />
+ <g
+ id="g23823">
+ <path
+ id="path23825"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23827"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23829"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23831"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23833"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23835"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23837"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23839"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23841"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23843"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23845"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23847"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23849"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23851"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23853"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23855"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23857"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23859"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23861"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23863"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23865"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23867"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23869"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23871"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path10992"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g23873"
+ transform="translate(0,399)">
+ <rect
+ ry="0"
+ rx="0"
+ y="26"
+ x="0"
+ height="1"
+ width="6"
+ id="rect23875"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g23877">
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23879"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23881"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23883"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23885"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23887"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23889"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23891"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23893"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23895"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23897"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23899"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23901"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23903"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23905"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23907"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23909"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23911"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23913"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23915"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23917"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23919"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23921"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23923"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23925"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10994"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g23927"
+ transform="translate(0,378)">
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23929"
+ width="6"
+ height="1"
+ x="0"
+ y="26"
+ rx="0"
+ ry="0" />
+ <g
+ id="g23931">
+ <path
+ id="path23933"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23935"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23937"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23939"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23941"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23943"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23945"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23947"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23949"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23951"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23953"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23955"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23957"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23959"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23961"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23963"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23965"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23967"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23969"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23971"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23973"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23975"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23977"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23979"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path10996"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g23981"
+ transform="translate(0,357)">
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23983"
+ width="6"
+ height="1"
+ x="0"
+ y="26"
+ rx="0"
+ ry="0" />
+ <g
+ id="g23985">
+ <path
+ id="path23987"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23989"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23991"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23993"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23995"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path23997"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23999"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24001"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24003"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24005"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24007"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24009"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24011"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24013"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24015"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24017"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24019"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24021"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24023"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24025"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24027"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24029"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24031"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24033"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path10998"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24035"
+ transform="translate(0,336)">
+ <rect
+ ry="0"
+ rx="0"
+ y="26"
+ x="0"
+ height="1"
+ width="6"
+ id="rect24037"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g24039">
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24041"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24043"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24045"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24047"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24049"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24051"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24053"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24055"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24057"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24059"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24061"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24063"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24065"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24067"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24069"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24071"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24073"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24075"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24077"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24079"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24081"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24083"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24085"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24087"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path11000"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24089"
+ transform="translate(0,315)">
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24091"
+ width="6"
+ height="1"
+ x="0"
+ y="26"
+ rx="0"
+ ry="0" />
+ <g
+ id="g24093">
+ <path
+ id="path24095"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24097"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24099"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24101"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24103"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24105"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24107"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24109"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24111"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24113"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24115"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24117"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24119"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24121"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24123"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24125"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24127"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24129"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24131"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24133"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24135"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24137"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24139"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24141"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path11002"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24143"
+ transform="translate(0,294)">
+ <rect
+ ry="0"
+ rx="0"
+ y="26"
+ x="0"
+ height="1"
+ width="6"
+ id="rect24145"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g24147">
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24149"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24151"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24153"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24155"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24157"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24159"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24161"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24163"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24165"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24167"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24169"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24171"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24173"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24175"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24177"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24179"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24181"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24183"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24185"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24187"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24189"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24191"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24193"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24195"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path11004"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24197"
+ transform="translate(0,273)">
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24199"
+ width="6"
+ height="1"
+ x="0"
+ y="26"
+ rx="0"
+ ry="0" />
+ <g
+ id="g24201">
+ <path
+ id="path24203"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24205"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24207"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24209"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24211"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24213"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24215"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24217"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24219"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24221"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24223"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24225"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24227"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24229"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24231"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24233"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24235"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24237"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24239"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24241"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24243"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24245"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24247"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24249"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path11006"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24251"
+ transform="translate(0,252)">
+ <rect
+ ry="0"
+ rx="0"
+ y="26"
+ x="0"
+ height="1"
+ width="6"
+ id="rect24253"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g24255">
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24257"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24259"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24261"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24263"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24265"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24267"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24269"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24271"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24273"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24275"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24277"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24279"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24281"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24283"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24285"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24287"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24289"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24291"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24293"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24295"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24297"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24299"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24301"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24303"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path11008"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24305"
+ transform="translate(0,231)">
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24307"
+ width="6"
+ height="1"
+ x="0"
+ y="26"
+ rx="0"
+ ry="0" />
+ <g
+ id="g24309">
+ <path
+ id="path24311"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24313"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24315"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24317"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24319"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24321"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24323"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24325"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24327"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24329"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24331"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24333"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24335"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24337"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24339"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24341"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24343"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24345"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24347"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24349"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24351"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24353"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24355"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24357"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path11010"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24359"
+ transform="translate(0,210)">
+ <rect
+ ry="0"
+ rx="0"
+ y="26"
+ x="0"
+ height="1"
+ width="6"
+ id="rect24361"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g24363">
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24365"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24367"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24369"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24371"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24373"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24375"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24377"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24379"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24381"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24383"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24385"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24387"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24389"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24391"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24393"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24395"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24397"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24399"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24401"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24403"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24405"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24407"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24409"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24411"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path11012"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24413"
+ transform="translate(0,189)">
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24415"
+ width="6"
+ height="1"
+ x="0"
+ y="26"
+ rx="0"
+ ry="0" />
+ <g
+ id="g24417">
+ <path
+ id="path24419"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24421"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24423"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24425"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24427"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24429"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24431"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24433"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24435"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24437"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24439"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24441"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24443"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24445"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24447"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24449"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24451"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24453"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24455"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24457"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24459"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24461"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24463"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24465"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path11014"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24467"
+ transform="translate(0,168)">
+ <rect
+ ry="0"
+ rx="0"
+ y="26"
+ x="0"
+ height="1"
+ width="6"
+ id="rect24469"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g24471">
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24473"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24475"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24477"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24479"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24481"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24483"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24485"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24487"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24489"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24491"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24493"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24495"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24497"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24499"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24501"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24503"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24505"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24507"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24509"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24511"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24513"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24515"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24517"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24519"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path11016"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24521"
+ transform="translate(0,147)">
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24523"
+ width="6"
+ height="1"
+ x="0"
+ y="26"
+ rx="0"
+ ry="0" />
+ <g
+ id="g24525">
+ <path
+ id="path24527"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24529"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24531"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24533"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24535"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24537"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24539"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24541"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24543"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24545"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24547"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24549"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24551"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24553"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24555"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24557"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24559"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24561"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24563"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24565"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24567"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24569"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24571"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24573"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path11018"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24575"
+ transform="translate(0,126)">
+ <rect
+ ry="0"
+ rx="0"
+ y="26"
+ x="0"
+ height="1"
+ width="6"
+ id="rect24577"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g24579">
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24581"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24583"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24585"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24587"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24589"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24591"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24593"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24595"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24597"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24599"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24601"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24603"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24605"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24607"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24609"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24611"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24613"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24615"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24617"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24619"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24621"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24623"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24625"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24627"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path11020"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24630"
+ transform="translate(0,105)">
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24632"
+ width="6"
+ height="1"
+ x="0"
+ y="26"
+ rx="0"
+ ry="0" />
+ <g
+ id="g24634">
+ <path
+ id="path24636"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24638"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24640"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24642"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24644"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24646"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24648"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24650"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24652"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24654"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24656"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24658"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24660"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24662"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24664"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24666"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24668"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24670"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24672"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24674"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24676"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24678"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24680"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24682"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path11022"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24684"
+ transform="translate(0,84)">
+ <rect
+ ry="0"
+ rx="0"
+ y="26"
+ x="0"
+ height="1"
+ width="6"
+ id="rect24686"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g24688">
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24690"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24692"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24694"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24696"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24698"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24700"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24702"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24704"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24706"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24708"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24710"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24712"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24714"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24716"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24718"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24720"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24722"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24724"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24726"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24728"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24730"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24732"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24734"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24736"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path11024"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24738"
+ transform="translate(0,63)">
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24740"
+ width="6"
+ height="1"
+ x="0"
+ y="26"
+ rx="0"
+ ry="0" />
+ <g
+ id="g24742">
+ <path
+ id="path24744"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24746"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24748"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24750"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24752"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24754"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24756"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24758"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24760"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24762"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24764"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24766"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24768"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24770"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24772"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24774"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24776"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24778"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24780"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24782"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24784"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24786"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24788"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24790"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path11026"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24792"
+ transform="translate(0,42)">
+ <rect
+ ry="0"
+ rx="0"
+ y="26"
+ x="0"
+ height="1"
+ width="6"
+ id="rect24794"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g24796">
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24798"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24800"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24802"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24804"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24806"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24808"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24810"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24812"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24814"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24816"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24818"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24820"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24822"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24824"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24826"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24828"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24830"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24832"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24834"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24836"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24838"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24840"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24842"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24844"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path11028"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24846"
+ transform="translate(0,21)">
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24848"
+ width="6"
+ height="1"
+ x="0"
+ y="26"
+ rx="0"
+ ry="0" />
+ <g
+ id="g24850">
+ <path
+ id="path24852"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24854"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24856"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24858"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24860"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24862"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24864"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24866"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24868"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24870"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24872"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24874"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24876"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24878"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24880"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24882"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24884"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24886"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24888"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24890"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24892"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24894"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24896"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24898"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path11030"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24900">
+ <rect
+ ry="0"
+ rx="0"
+ y="26"
+ x="0"
+ height="1"
+ width="6"
+ id="rect24902"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g24904">
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24906"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24908"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24910"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24912"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24914"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24916"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24918"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24920"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24922"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24924"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24926"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24928"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24930"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24932"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24934"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24936"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24938"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24940"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24942"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24944"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24946"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24948"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path24950"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24952"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path11032"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(0,483)"
+ id="g39833">
+ <rect
+ ry="0"
+ rx="0"
+ y="26"
+ x="0"
+ height="1"
+ width="6"
+ id="rect39835"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g39837">
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39840"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39842"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39844"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39846"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39848"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39850"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39852"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39854"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39856"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39858"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39860"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39862"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39864"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39866"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39868"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39870"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39872"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39874"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39876"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39878"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39880"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39882"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39884"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39888"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39890"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g39892"
+ transform="translate(0,504)">
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect39894"
+ width="6"
+ height="1"
+ x="0"
+ y="26"
+ rx="0"
+ ry="0" />
+ <g
+ id="g39896">
+ <path
+ id="path39898"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39900"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39902"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39904"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39907"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39909"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39911"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39913"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39915"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39917"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39919"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39921"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39923"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39925"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39927"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39929"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39931"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39933"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39935"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39937"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39939"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39941"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39943"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39945"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39947"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(0,525)"
+ id="g39949">
+ <rect
+ ry="0"
+ rx="0"
+ y="26"
+ x="0"
+ height="1"
+ width="6"
+ id="rect39951"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g39953">
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39955"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39957"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39959"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39961"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39963"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39965"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39967"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39969"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39971"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39973"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39975"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39977"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39979"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39981"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39983"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39985"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39987"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39989"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39991"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39993"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39995"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39997"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path39999"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40001"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40003"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g40005"
+ transform="translate(0,546)">
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40007"
+ width="6"
+ height="1"
+ x="0"
+ y="26"
+ rx="0"
+ ry="0" />
+ <g
+ id="g40009">
+ <path
+ id="path40011"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40013"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40015"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40017"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40019"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40021"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40023"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40025"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40027"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40029"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40031"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40033"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40035"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40038"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40040"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40042"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40044"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40046"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40048"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40050"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40052"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40054"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40056"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40058"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40060"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(0,567)"
+ id="g40062">
+ <rect
+ ry="0"
+ rx="0"
+ y="26"
+ x="0"
+ height="1"
+ width="6"
+ id="rect40064"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g40066">
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40068"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40070"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40072"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40074"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40076"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40078"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40080"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40082"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40084"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40086"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40088"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40090"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40092"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40094"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40096"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40098"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40100"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40102"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40104"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40106"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40108"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40110"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40112"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40114"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40116"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g40118"
+ transform="translate(0,588)">
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40120"
+ width="6"
+ height="1"
+ x="0"
+ y="26"
+ rx="0"
+ ry="0" />
+ <g
+ id="g40122">
+ <path
+ id="path40124"
+ d="m 506,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 485,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40126"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40128"
+ d="m 464,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 443,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40130"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40132"
+ d="m 422,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 401,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40134"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40136"
+ d="m 380,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 359,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40138"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40140"
+ d="m 338,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 317,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40142"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40144"
+ d="m 296,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 275,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40146"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40148"
+ d="m 254,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 233,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40150"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40152"
+ d="m 212,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 191,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40154"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40156"
+ d="m 170,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 149,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40158"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40160"
+ d="m 128,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 107,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40162"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40164"
+ d="m 86,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 65,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40166"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40168"
+ d="m 44,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 23,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40170"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 527,20 0,6 -6,0 0,1 6,0 0,6 1,0 0,-6 6,0 0,-1 -6,0 0,-6 -1,0 z"
+ id="path40172"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ transform="translate(0,633)"
+ id="g25954">
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="422"
+ height="7"
+ width="1"
+ id="rect25956"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25958"
+ width="1"
+ height="7"
+ x="401"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="380"
+ height="7"
+ width="1"
+ id="rect25960"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25962"
+ width="1"
+ height="7"
+ x="359"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="338"
+ height="7"
+ width="1"
+ id="rect25964"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25966"
+ width="1"
+ height="7"
+ x="317"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="296"
+ height="7"
+ width="1"
+ id="rect25968"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25970"
+ width="1"
+ height="7"
+ x="275"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="254"
+ height="7"
+ width="1"
+ id="rect25972"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25974"
+ width="1"
+ height="7"
+ x="233"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="212"
+ height="7"
+ width="1"
+ id="rect25976"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25978"
+ width="1"
+ height="7"
+ x="191"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="170"
+ height="7"
+ width="1"
+ id="rect25980"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25982"
+ width="1"
+ height="7"
+ x="149"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="128"
+ height="7"
+ width="1"
+ id="rect25984"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25986"
+ width="1"
+ height="7"
+ x="107"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="86"
+ height="7"
+ width="1"
+ id="rect25988"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25990"
+ width="1"
+ height="7"
+ x="65"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="44"
+ height="7"
+ width="1"
+ id="rect25992"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25994"
+ width="1"
+ height="7"
+ x="23"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25996"
+ width="1"
+ height="7"
+ x="506"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="485"
+ height="7"
+ width="1"
+ id="rect25998"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect26000"
+ width="1"
+ height="7"
+ x="464"
+ y="0"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="443"
+ height="7"
+ width="1"
+ id="rect26002"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ ry="0"
+ rx="0"
+ y="0"
+ x="527"
+ height="7"
+ width="1"
+ id="rect11034"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+ <g
+ id="g30515"
+ transform="translate(-121.95685,2)">
+ <rect
+ ry="0"
+ rx="0"
+ y="488"
+ x="665.95685"
+ height="1"
+ width="6"
+ id="rect26734"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect26788"
+ width="6"
+ height="1"
+ x="665.95685"
+ y="467"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="446"
+ x="665.95685"
+ height="1"
+ width="6"
+ id="rect26842"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect26896"
+ width="6"
+ height="1"
+ x="665.95685"
+ y="425"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="404"
+ x="665.95685"
+ height="1"
+ width="6"
+ id="rect26950"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ ry="0"
+ rx="0"
+ y="383"
+ x="665.95685"
+ height="1"
+ width="6"
+ id="rect27004"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect27058"
+ width="6"
+ height="1"
+ x="665.95685"
+ y="362"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="341"
+ x="665.95685"
+ height="1"
+ width="6"
+ id="rect27112"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect27166"
+ width="6"
+ height="1"
+ x="665.95685"
+ y="320"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="299"
+ x="665.95685"
+ height="1"
+ width="6"
+ id="rect27220"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect27274"
+ width="6"
+ height="1"
+ x="665.95685"
+ y="278"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="257"
+ x="665.95685"
+ height="1"
+ width="6"
+ id="rect27328"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect27382"
+ width="6"
+ height="1"
+ x="665.95685"
+ y="236"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="215"
+ x="665.95685"
+ height="1"
+ width="6"
+ id="rect27436"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect27490"
+ width="6"
+ height="1"
+ x="665.95685"
+ y="194"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="173"
+ x="665.95685"
+ height="1"
+ width="6"
+ id="rect27544"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect27598"
+ width="6"
+ height="1"
+ x="665.95685"
+ y="152"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="131"
+ x="665.95685"
+ height="1"
+ width="6"
+ id="rect27652"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect27706"
+ width="6"
+ height="1"
+ x="665.95685"
+ y="110"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="89"
+ x="665.95685"
+ height="1"
+ width="6"
+ id="rect27760"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect27814"
+ width="6"
+ height="1"
+ x="665.95685"
+ y="68"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="47"
+ x="665.95685"
+ height="1"
+ width="6"
+ id="rect27868"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect27922"
+ width="6"
+ height="1"
+ x="665.95685"
+ y="26"
+ rx="0"
+ ry="0" />
+ </g>
+ <rect
+ style="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="rect28448"
+ width="0"
+ height="0"
+ x="217.25"
+ y="263.5" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer4"
+ inkscape:label="sheet layout"
+ style="display:inline"
+ sodipodi:insensitive="true">
+ <path
+ inkscape:connector-curvature="0"
+ id="path19551-18-8"
+ d="m 585,613.25 1,0 0,0.5 1,0 0,-0.5 1,0 0,0.75 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,0.75 -1,0 0,-0.5 -1,0 0,0.5 -1,0 0,1.5 z m 1,-0.25 0,-1 1,0 0,1 -1,0 z m 2,0 0,-1 1,0 0,1 -1,0 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path19551-18-1"
+ d="m 907.75,209 0,1 -0.5,0 0,1 0.5,0 0,1 -0.75,0 0,1 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-1 -0.75,0 0,-1 0.5,0 0,-1 -0.5,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z m 0,2 1,0 0,1 -1,0 0,-1 z"
+ 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" />
+ <g
+ style="opacity:0.3;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ transform="translate(21,0)"
+ id="g28552-1">
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 536,14 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ id="path28554-7"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 539,14 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path28556-4"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 544,14 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m 0,1 0,1 1,0 0,-1 -1,0 z m -2,-1 0,-3 -1,0 0,3 1,0 z"
+ id="path28558-0"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 553,14 0,1.75 -1,0 0,1.25 -1,0 0,2 1,0 0,-1.75 1,0 0,-1.25 1,0 0,-2 -1,0 z"
+ id="path28560-9"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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="rect28562-4"
+ width="1"
+ height="1"
+ x="548"
+ y="18" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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="rect28564-8"
+ width="1"
+ height="5"
+ x="557"
+ y="14" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 559,14 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,-1 -1,0 z m 1,0 1,0 0,3 1,0 0,-5 -1,0 0,1 -1,0 0,1 z"
+ id="path28566-8"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 565.75,14 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ id="path28568-2"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 570,14 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 0,-1.25 -1,0 0,1.25 -1,0 0,-3 2,0 0,-1 -2,0 z"
+ id="path28570-4"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 573,14 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path28572-5"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="opacity:0.3;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ transform="translate(21.98523,3)"
+ id="g28574-5">
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 534,74 0,5 1,0 0,-2 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path28576-1"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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="rect28578-7"
+ width="1"
+ height="5"
+ x="538"
+ y="74" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 540,74 0,5 1,0 2,0 0,-1 -2,0 0,-4 -1,0 z"
+ id="path28580-1"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path28582-1"
+ d="m 544,74 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path28584-5"
+ d="m 551,74 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path28586-2"
+ d="m 554,74 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 558,74 0,5 1,0 2,0 0,-1 -2,0 0,-4 -1,0 z"
+ id="path28588-7"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 562,74 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path28590-6"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 567,74 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ id="path28592-1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 570,74 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ id="path28594-4"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="opacity:0.3;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ transform="translate(21,0)"
+ id="g28596-2">
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 535,119 0,1 2,0 0,1 1,0 0,-1.25 -1,0 0,-0.75 -2,0 z m 2,2 -1,0 0,1 1,0 0,-1 z m 0,1 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.25 -1,0 z"
+ id="path28598-3"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 539,119 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ id="path28600-2"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 545,119 0,3.25 1,0 0,1.75 1,0 0,-1.75 1,0 0,-3.25 -1,0 0,3 -1,0 0,-3 -1,0 z"
+ id="path28602-2"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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="rect28604-1"
+ width="1"
+ height="5"
+ x="549"
+ y="119" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 551,119 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path28606-6"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 555,119 0,3.25 1,0 0,1.75 1,0 0,-1.75 1,0 0,1.75 1,0 0,-1.75 1,0 0,-3.25 -1,0 0,3 -1,0 0,-2 -1,0 0,2 -1,0 0,-3 -1,0 z"
+ id="path28608-8"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="opacity:0.3;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ transform="translate(16,1)"
+ id="g28610-5">
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 540,160 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path28612-7"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 544,160 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ id="path28614-6"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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="rect28616-1"
+ width="1"
+ height="5"
+ x="548"
+ y="160" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 550,160 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ id="path28618-8"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="160"
+ x="554"
+ height="5"
+ width="1"
+ id="rect28620-9"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 556,160 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ id="path28622-2"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 562,160 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 0,-1.25 -0.99999,0 0,1.25 -1.00001,0 0,-3 2,0 0,-1 -2,0 z"
+ id="path28624-7"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="opacity:0.3;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ transform="translate(21,0)"
+ id="g28626-9">
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 535.75,224 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ id="path28628-5"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 539,224 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ id="path28630-4"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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="rect28632-3"
+ width="1"
+ height="5"
+ x="544"
+ y="224" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 546,224 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,-1 -1,0 z m 1,0 1,0 0,3 1,0 0,-5 -1,0 0,1 -1,0 0,1 z"
+ id="path28634-1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 552.75,224 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ id="path28636-2"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 556,224 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ id="path28638-3"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="224"
+ x="560"
+ height="5"
+ width="1"
+ id="rect28640-3"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 563,224 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ id="path28642-4"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 567,224 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ id="path28644-1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="opacity:0.3;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ transform="translate(22,-10)"
+ id="g28646-1">
+ <path
+ id="path28648-3"
+ d="m 535,267 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,-1 -1,0 z m 1,0 1,0 0,3 1,0 0,-5 -1,0 0,1 -1,0 0,1 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path28650-8"
+ d="m 542,267 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 546,267 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ id="path28652-7"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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="rect28654-4"
+ width="1"
+ height="5"
+ x="550"
+ y="267" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 552,267 0,5 1,0 0,-2 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path28656-2"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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="rect28658-7"
+ width="1"
+ height="5"
+ x="556"
+ y="267" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 558,267 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path28660-7"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 562,267 0,5 1,0 0,-2 1,0 0,2 1,0 0,-2 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ id="path28662-9"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 567,267 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ id="path28664-3"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="opacity:0.3;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ transform="translate(25,-1)"
+ id="g28666-1">
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 532,36 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ id="path28668-9"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 539.75,36 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ id="path28670-8"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 543,36 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ id="path28672-6"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 547,36 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path28674-5"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path28676-0"
+ d="m 555,36 0,1.75 -1,0 0,1.25 -1,0 0,2 1,0 0,-1.75 1,0 0,-1.25 1,0 0,-2 -1,0 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 558,36 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ id="path28678-2"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 562,36 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path28680-8"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path28682-6"
+ d="m 566,36 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"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path28684-0"
+ d="m 570,36 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 535,36 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ id="path28686-2"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="opacity:0.3;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ transform="translate(19,125)"
+ id="g28688-4">
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 538,299 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ id="path28690-8"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 542,299 0,4.25 1,0 0,0.75 2,0 0,-0.75 1,0 0,-4.25 -1,0 0,4 -2,0 0,-4 -1,0 z"
+ id="path28692-6"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 547,299 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ id="path28694-5"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 551,299 0,5 1,0 2,0 0,-1 -2,0 0,-4 -1,0 z"
+ id="path28696-0"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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="rect28698-9"
+ width="1"
+ height="5"
+ x="555"
+ y="299" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 557,299 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ id="path28700-0"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 562,299 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path28702-0"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 566,299 0,5 1,0 0,-2 1,0 0,2 1,0 0,-2 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ id="path28704-6"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="opacity:0.3;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ transform="translate(21,128)"
+ id="g28706-1">
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 539.75,359 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ id="path28708-3"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 535,359 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ id="path28710-8"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 543,359 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ id="path28712-9"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path28714-3"
+ d="m 547.75,359 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="opacity:0.3;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ transform="translate(22,125)"
+ id="g28716-4">
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 545,393 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ id="path28718-4"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 549,393 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path28720-6"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 534,393 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,-1 -1,0 z m 1,0 1,0 0,3 1,0 0,-5 -1,0 0,1 -1,0 0,1 z"
+ id="path28722-0"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 541,393 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ id="path28724-6"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 554,393 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ id="path28726-6"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="opacity:0.3;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ transform="translate(22.01477,127)"
+ id="g28728-1">
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 538,412 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ id="path28730-8"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 534,412 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path28732-4"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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="rect28734-9"
+ width="1"
+ height="5"
+ x="542"
+ y="412" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 549,412 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ id="path28736-6"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 553,412 0,5 1,0 0,-2 1,0 0,2 1,0 0,-2 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ id="path28738-3"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 558,412 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ id="path28740-7"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 544,412 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ id="path28742-8"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="opacity:0.3;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ transform="translate(22.01477,127)"
+ id="g28744-8">
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 534,434 0,5 1,0 1,0 0,-0.5 1,0 0,-1.5 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z m 0,2 1,0 0,1 -1,0 0,-1 z"
+ id="path28746-2"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 556,434 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ id="path28748-9"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 552,434 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ id="path28750-1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 562,434 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ id="path28752-3"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 543,434 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ id="path28754-5"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 538,434 0,4.25 1,0 0,0.75 2,0 0,-0.75 1,0 0,-4.25 -1,0 0,4 -2,0 0,-4 -1,0 z"
+ id="path28756-9"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path28758-8"
+ d="m 547,434 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="opacity:0.3;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ transform="translate(19,127)"
+ id="g28760-4">
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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="rect28762-0"
+ width="1"
+ height="5"
+ x="542"
+ y="486" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;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 537,486 0,4.25 1,0 0,0.75 2,0 0,-0.75 1,0 0,-4.25 -1,0 0,4 -2,0 0,-4 -1,0 z"
+ id="path28764-7"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g10763-6"
+ transform="translate(21,0)">
+ <path
+ id="path10757-3"
+ d="m 536,14 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10759-6"
+ d="m 539,14 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10761-1"
+ d="m 544,14 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m 0,1 0,1 1,0 0,-1 -1,0 z m -2,-1 0,-3 -1,0 0,3 1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10763-5"
+ d="m 553,14 0,1.75 -1,0 0,1.25 -1,0 0,2 1,0 0,-1.75 1,0 0,-1.25 1,0 0,-2 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="18"
+ x="548"
+ height="1"
+ width="1"
+ id="rect10765-4"
+ 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
+ y="14"
+ x="557"
+ height="5"
+ width="1"
+ id="rect10767-2"
+ 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" />
+ <path
+ id="path10769-0"
+ d="m 559,14 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,-1 -1,0 z m 1,0 1,0 0,3 1,0 0,-5 -1,0 0,1 -1,0 0,1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10771-9"
+ d="m 565.75,14 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10773-7"
+ d="m 570,14 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 0,-1.25 -1,0 0,1.25 -1,0 0,-3 2,0 0,-1 -2,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10775-3"
+ d="m 573,14 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g10815-7"
+ transform="translate(21.98523,3)">
+ <path
+ id="path10799-2"
+ d="m 534,74 0,5 1,0 0,-2 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="74"
+ x="538"
+ height="5"
+ width="1"
+ id="rect10801-6"
+ 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" />
+ <path
+ id="path10803-0"
+ d="m 540,74 0,5 1,0 2,0 0,-1 -2,0 0,-4 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 544,74 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path10805-1"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 551,74 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ id="path10807-6"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 554,74 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path10809-5"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10811-7"
+ d="m 558,74 0,5 1,0 2,0 0,-1 -2,0 0,-4 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10813-5"
+ d="m 562,74 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10815-4"
+ d="m 567,74 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10817-1"
+ d="m 570,74 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g10827-2"
+ transform="translate(21,0)">
+ <path
+ id="path10672-0"
+ d="m 535,119 0,1 2,0 0,1 1,0 0,-1.25 -1,0 0,-0.75 -2,0 z m 2,2 -1,0 0,1 1,0 0,-1 z m 0,1 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.25 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10678-0"
+ d="m 539,119 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10680-1"
+ d="m 545,119 0,3.25 1,0 0,1.75 1,0 0,-1.75 1,0 0,-3.25 -1,0 0,3 -1,0 0,-3 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="119"
+ x="549"
+ height="5"
+ width="1"
+ id="rect10682-4"
+ 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" />
+ <path
+ id="path10684-6"
+ d="m 551,119 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10686-0"
+ d="m 555,119 0,3.25 1,0 0,1.75 1,0 0,-1.75 1,0 0,1.75 1,0 0,-1.75 1,0 0,-3.25 -1,0 0,3 -1,0 0,-2 -1,0 0,2 -1,0 0,-3 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g10835-7"
+ transform="translate(16,1)">
+ <path
+ id="path10688-1"
+ d="m 540,160 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10690-7"
+ d="m 544,160 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="160"
+ x="548"
+ height="5"
+ width="1"
+ id="rect10692-7"
+ 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" />
+ <path
+ id="path10694-7"
+ d="m 550,160 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <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="rect10696-7"
+ width="1"
+ height="5"
+ x="554"
+ y="160" />
+ <path
+ id="path10698-3"
+ d="m 556,160 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10700-3"
+ d="m 562,160 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 0,-1.25 -0.99999,0 0,1.25 -1.00001,0 0,-3 2,0 0,-1 -2,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g10846-5"
+ transform="translate(21,0)">
+ <path
+ id="path10703-9"
+ d="m 535.75,224 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10705-9"
+ d="m 539,224 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="224"
+ x="544"
+ height="5"
+ width="1"
+ id="rect10708-8"
+ 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" />
+ <path
+ id="path10711-1"
+ d="m 546,224 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,-1 -1,0 z m 1,0 1,0 0,3 1,0 0,-5 -1,0 0,1 -1,0 0,1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10714-8"
+ d="m 552.75,224 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10716-2"
+ d="m 556,224 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <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="rect10718-6"
+ width="1"
+ height="5"
+ x="560"
+ y="224" />
+ <path
+ id="path10734-6"
+ d="m 563,224 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10736-0"
+ d="m 567,224 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g10857-3"
+ transform="translate(22,-10)">
+ <path
+ 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"
+ d="m 535,267 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,-1 -1,0 z m 1,0 1,0 0,3 1,0 0,-5 -1,0 0,1 -1,0 0,1 z"
+ id="path10744-8"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 542,267 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ id="path10746-0"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10748-1"
+ d="m 546,267 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="267"
+ x="550"
+ height="5"
+ width="1"
+ id="rect10750-2"
+ 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" />
+ <path
+ id="path10752-5"
+ d="m 552,267 0,5 1,0 0,-2 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="267"
+ x="556"
+ height="5"
+ width="1"
+ id="rect10754-0"
+ 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" />
+ <path
+ id="path10756-9"
+ d="m 558,267 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10758-4"
+ d="m 562,267 0,5 1,0 0,-2 1,0 0,2 1,0 0,-2 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10760-7"
+ d="m 567,267 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g10803-8"
+ transform="translate(25,-1)">
+ <path
+ id="path10777-3"
+ d="m 532,36 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10781-5"
+ d="m 539.75,36 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10783-1"
+ d="m 543,36 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10785-2"
+ d="m 547,36 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 555,36 0,1.75 -1,0 0,1.25 -1,0 0,2 1,0 0,-1.75 1,0 0,-1.25 1,0 0,-2 -1,0 z"
+ id="path10787-0"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10789-1"
+ d="m 558,36 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10791-6"
+ d="m 562,36 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 566,36 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"
+ id="path10795-4"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 570,36 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ id="path10797-0"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10800-6"
+ d="m 535,36 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g10885-1"
+ transform="translate(19,125)">
+ <path
+ id="path10869-8"
+ d="m 538,299 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10871-9"
+ d="m 542,299 0,4.25 1,0 0,0.75 2,0 0,-0.75 1,0 0,-4.25 -1,0 0,4 -2,0 0,-4 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10873-8"
+ d="m 547,299 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10875-4"
+ d="m 551,299 0,5 1,0 2,0 0,-1 -2,0 0,-4 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="299"
+ x="555"
+ height="5"
+ width="1"
+ id="rect10877-1"
+ 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" />
+ <path
+ id="path10879-4"
+ d="m 557,299 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10881-3"
+ d="m 562,299 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10883-9"
+ d="m 566,299 0,5 1,0 0,-2 1,0 0,2 1,0 0,-2 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g10921-8"
+ transform="translate(21,128)">
+ <path
+ id="path10895-8"
+ d="m 539.75,359 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10897-0"
+ d="m 535,359 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10899-8"
+ d="m 543,359 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 547.75,359 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ id="path10901-7"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g10914-7"
+ transform="translate(22,125)">
+ <path
+ id="path10903-8"
+ d="m 545,393 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10906-3"
+ d="m 549,393 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10908-8"
+ d="m 534,393 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,-1 -1,0 z m 1,0 1,0 0,3 1,0 0,-5 -1,0 0,1 -1,0 0,1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10910-3"
+ d="m 541,393 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10912-7"
+ d="m 554,393 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g10942-1"
+ transform="translate(22.01477,127)">
+ <path
+ id="path10928-0"
+ d="m 538,412 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10930-7"
+ d="m 534,412 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="412"
+ x="542"
+ height="5"
+ width="1"
+ id="rect10932-3"
+ 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" />
+ <path
+ id="path10934-4"
+ d="m 549,412 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10936-9"
+ d="m 553,412 0,5 1,0 0,-2 1,0 0,2 1,0 0,-2 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10938-6"
+ d="m 558,412 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10940-5"
+ d="m 544,412 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g10966-1"
+ transform="translate(22.01477,127)">
+ <path
+ id="path10951-0"
+ d="m 534,434 0,5 1,0 1,0 0,-0.5 1,0 0,-1.5 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z m 0,2 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10953-9"
+ d="m 556,434 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10956-9"
+ d="m 552,434 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10958-6"
+ d="m 562,434 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10960-8"
+ d="m 543,434 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10962-3"
+ d="m 538,434 0,4.25 1,0 0,0.75 2,0 0,-0.75 1,0 0,-4.25 -1,0 0,4 -2,0 0,-4 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 547,434 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ id="path10964-4"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g10980-8"
+ transform="translate(19,127)">
+ <rect
+ y="486"
+ x="542"
+ height="5"
+ width="1"
+ id="rect10975-4"
+ 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" />
+ <path
+ id="path10978-9"
+ d="m 537,486 0,4.25 1,0 0,0.75 2,0 0,-0.75 1,0 0,-4.25 -1,0 0,4 -2,0 0,-4 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="opacity:0.4;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 544,133 0,1 9,0 0,62 -9,0 0,1 9,0 1,0 0,-33 1,0 0,-1 -1,0 0,-30 -1,0 -9,0 z"
+ id="rect11044-9"
+ sodipodi:nodetypes="ccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <a
+ style="display:inline;enable-background:new"
+ id="a28530-2">
+ <g
+ style="fill:#b3b3b3"
+ transform="translate(-3e-6,1)"
+ id="g11054-5">
+ <path
+ id="path19464-5"
+ d="m 1.75,13 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path19466-3"
+ d="m 1,34 0,5 1,0 1,0 0,-0.5 1,0 0,-1.5 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 L 3,34 2,34 1,34 z m 1,1 1,0 0,1 -1,0 0,-1 z m 0,2 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path19468-3"
+ d="m 2,55.25 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path19470-3"
+ d="m 1,76 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 L 3,76 1,76 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path19472-7"
+ d="m 1,98 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path19474-4"
+ d="m 1,118 0,5 1,0 0,-2 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path19476-3"
+ d="m 2,139 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 0,-1.25 -1,0 0,1.25 -1,0 0,-3 2,0 0,-1 -2,0 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path19478-8"
+ d="m 1,160 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ style="fill:#b3b3b3;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
+ y="182"
+ x="2"
+ height="5"
+ width="1"
+ id="rect19480-0"
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ id="path19482-8"
+ d="m 3,202 0,4 -1,0 0,-1 -1,0 0,1 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-4 -1,0 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path19484-8"
+ d="m 1,223 0,5 1,0 0,-1.75 1,0 0,-1.5 -1,0 0,-1.75 -1,0 z m 2,1.75 1,0 0,-1.75 -1,0 0,1.75 z m 0,1.5 0,1.75 1,0 0,-1.75 -1,0 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path19486-0"
+ d="m 1,244 0,5 1,0 2,0 0,-1 -2,0 0,-4 -1,0 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path19488-6"
+ d="m 3e-6,265 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 0,0 z m 2,2 0,1 1,0 0,-1 -1,0 z m 1,0 1,0 0,3 1,0 0,-5 -1,0 0,1 -1,0 0,1 0,0 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path19490-8"
+ d="m 1,286 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path19492-1"
+ d="m 2,307 0,1 1,0 0,-1 -1,0 z m 1,1 0,3 1,0 0,-3 -1,0 z m 0,3 -1,0 0,1 1,0 0,-1 z m -1,0 0,-3 -1,0 0,3 1,0 z"
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="cccccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path19494-9"
+ d="m 1,328 0,5 1,0 0,-2 1.25,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path19496-8"
+ d="m 2,349 0,1 1,0 0,-1 -1,0 z m 1,1 0,3 1,0 0,-3 -1,0 z m 0,3 -1,0 0,1 1,0 0,-1 z m 0,1 0,1 1,0 0,-1 -1,0 z m -1,-1 0,-3 -1,0 0,3 1,0 z"
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccccccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path19498-9"
+ d="m 1,370 0,5 1,0 0,-2 1,0 0,2 1,0 0,-2 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path19500-7"
+ d="m 2,391 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path19502-2"
+ d="m 1,412 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path19504-2"
+ d="m 1,434 0,4.25 1,0 0,0.75 2,0 0,-0.75 1,0 0,-4.25 -1,0 0,4 -2,0 0,-4 -1,0 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path19506-8"
+ d="m 1,455 0,3.25 1,0 0,1.75 1,0 0,-1.75 1,0 0,-3.25 -1,0 0,3 -1,0 0,-3 -1,0 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path19508-2"
+ d="m 3e-6,475 0,3.25 1,0 0,1.75 1,0 0,-1.75 0.999997,0 0,1.75 1.000003,0 0,-1.75 1,0 0,-3.25 -1,0 0,3 L 3,478 l 0,-2 -0.999997,0 0,2 -1,0 0,-3 -1,0 0,0 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 1,497 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"
+ id="rect19510-8"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 1.750003,556 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 0,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ id="path38399-9"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 1.000003,577 0,5 1,0 1,0 0,-0.5 1,0 0,-1.5 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 0,0 z m 1,1 1,0 0,1 -1,0 0,-1 z m 0,2 1,0 0,1 -1,0 0,-1 z"
+ id="path38401-0"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 2.000003,598.25 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 0,0 z"
+ id="path38403-7"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 1.000003,619 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 0,0 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ id="path38405-8"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path38411-1"
+ d="m 1.750003,563 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 0,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path38413-5"
+ d="m 1.750003,584 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 0,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 1.750003,605 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 0,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ id="path38415-8"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path38417-6"
+ d="m 1.750003,626 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 0,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path38419-1"
+ d="m 548.75,556 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path38421-2"
+ d="m 548,577 0,5 1,0 1,0 0,-0.5 1,0 0,-1.5 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z m 0,2 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path38423-4"
+ d="m 549,598.25 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ id="path38425-2"
+ d="m 548,619 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 548.75,563 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ id="path38427-5"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 548.75,584 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ id="path38429-8"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path38431-6"
+ d="m 548.75,605 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#b3b3b3;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" />
+ <path
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 548.75,626 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ id="path38433-2"
+ inkscape:connector-curvature="0" />
+ </g>
+ </a>
+ <path
+ inkscape:connector-curvature="0"
+ id="path19537-6"
+ d="m 12,2 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="fill:#b3b3b3;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="path19539-5"
+ d="m 33,2 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 L 35,2 33,2 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ style="fill:#b3b3b3;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="path19541-3"
+ d="m 54,2 0,1 2,0 0,1 1,0 0,-1.25 -1,0 L 56,2 54,2 z m 2,2 -1,0 0,1 1,0 0,-1 z m 0,1 0,1 -2,0 0,1 2,0 0,-0.75 1,0 L 57,5 56,5 z"
+ style="fill:#b3b3b3;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="path19543-9"
+ d="m 75,2 0,3 1,0 1,0 0,2 1,0 0,-4 -1,0 0,1 -1,0 0,-2 -1,0 z"
+ style="fill:#b3b3b3;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="path19545-2"
+ d="m 96,2 0,3 1,0 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ style="fill:#b3b3b3;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="path19547-4"
+ d="m 118,2 0,0.75 -1,0 0,3.25 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-1 -0.75,0 0,-1 -1.25,0 0,-1 1.5,0 0,-1 -1.5,0 z m 0,3 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#b3b3b3;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="path19549-6"
+ d="m 138,2 0,1 2,0 0,1 -1,0 0,3 1,0 0,-2.75 1,0 0,-1.25 0,-1 -3,0 z"
+ style="fill:#b3b3b3;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="path19551-18"
+ d="m 159.75,2 0,1 -0.5,0 0,1 0.5,0 0,1 -0.75,0 0,1 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-1 -0.75,0 0,-1 0.5,0 0,-1 -0.5,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z m 0,2 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#b3b3b3;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="path19553-2"
+ d="m 180.75,2 0,1 -0.75,0 0,1 0.75,0 0,1 1.25,0 0,1 -1.5,0 0,1 1.5,0 0,-0.75 1,0 0,-3.25 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#b3b3b3;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"
+ sodipodi:nodetypes="cccccccccccccccccc"
+ id="path19555-1"
+ d="m 202.75,2 0,1 -0.75,0 0,3 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-3 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,3 -1,0 0,-3 z"
+ style="fill:#b3b3b3;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="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 514,2 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ id="path19559-1" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 476,2 0,1 2,0 0,1 1,0 0,-1.25 -1,0 0,-0.75 -2,0 z m 2,2 -1,0 0,1 1,0 0,-1 z m 0,1 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.25 -1,0 z"
+ id="path19561-9" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 497,2 0,3 1,0 1,0 0,2 1,0 0,-4 -1,0 0,1 -1,0 0,-2 -1,0 z"
+ id="path19563-7" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 518,2 0,3 1,0 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path19565-6" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path19577-2"
+ d="m 200,2 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="fill:#b3b3b3;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="path19579-9"
+ d="m 244,2 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ style="fill:#b3b3b3;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="path19581-5"
+ d="m 265,2 0,1 2,0 0,1 1,0 0,-1.25 -1,0 0,-0.75 -2,0 z m 2,2 -1,0 0,1 1,0 0,-1 z m 0,1 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.25 -1,0 z"
+ style="fill:#b3b3b3;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="path19583-2"
+ d="m 286,2 0,3 1,0 1,0 0,2 1,0 0,-4 -1,0 0,1 -1,0 0,-2 -1,0 z"
+ style="fill:#b3b3b3;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="path19585-0"
+ d="m 307,2 0,3 1,0 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ style="fill:#b3b3b3;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="path19587-0"
+ d="m 329,2 0,0.75 -1,0 0,3.25 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-1 -0.75,0 0,-1 -1.25,0 0,-1 1.5,0 0,-1 -1.5,0 z m 0,3 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#b3b3b3;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="path19589-3"
+ d="m 349,2 0,1 2,0 0,1 -1,0 0,3 1,0 0,-2.75 1,0 0,-1.25 0,-1 -3,0 z"
+ style="fill:#b3b3b3;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="path19591-9"
+ d="m 370.75,2 0,1 -0.5,0 0,1 0.5,0 0,1 -0.75,0 0,1 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-1 -0.75,0 0,-1 0.5,0 0,-1 -0.5,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z m 0,2 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#b3b3b3;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="path19593-1"
+ d="m 391.75,2 0,1 -0.75,0 0,1 0.75,0 0,1 1.25,0 0,1 -1.5,0 0,1 1.5,0 0,-0.75 1,0 0,-3.25 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#b3b3b3;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="path19595-8"
+ d="m 413.75,2 0,1 -0.75,0 0,3 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-3 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,3 -1,0 0,-3 z m 0.25,1 0,1 0.5,0 0,-1 -0.5,0 z"
+ style="fill:#b3b3b3;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="path19597-1"
+ d="m 221,2 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="fill:#b3b3b3;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="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 224,2 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ id="path19599-9" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path19601-5"
+ d="m 242,2 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="fill:#b3b3b3;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="path19603-3"
+ d="m 263,2 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="fill:#b3b3b3;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="path19605-2"
+ d="m 284,2 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="fill:#b3b3b3;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="path19607-5"
+ d="m 305,2 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="fill:#b3b3b3;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="path19609-2"
+ d="m 326,2 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="fill:#b3b3b3;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="path19611-5"
+ d="m 347,2 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="fill:#b3b3b3;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="path19613-8"
+ d="m 368,2 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="fill:#b3b3b3;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="path19615-6"
+ d="m 389,2 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="fill:#b3b3b3;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="path19617-7"
+ d="m 409,2 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ style="fill:#b3b3b3;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="path19619-7"
+ d="m 435,2 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="fill:#b3b3b3;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="path19621-2"
+ d="m 430,2 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ style="fill:#b3b3b3;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="path19623-2"
+ d="m 451,2 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ style="fill:#b3b3b3;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="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 455,2 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ id="path19625-9" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path19627-4"
+ d="m 472,2 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ style="fill:#b3b3b3;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="path19629-1"
+ d="m 493,2 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ style="fill:#b3b3b3;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="path11036-9"
+ d="m 536,2 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ style="fill:#b3b3b3;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="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 541,2 0,0.75 -1,0 0,3.25 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-1 -0.75,0 0,-1 -1.25,0 0,-1 1.5,0 0,-1 -1.5,0 z m 0,3 1,0 0,1 -1,0 0,-1 z"
+ id="path11038-6" />
+ <g
+ id="g11125-9"
+ transform="translate(547,1)"
+ style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate">
+ <path
+ id="path11128-8"
+ d="m 1.75,13 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path11130-2"
+ d="m 1,34 0,5 1,0 1,0 0,-0.5 1,0 0,-1.5 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 L 3,34 2,34 1,34 z m 1,1 1,0 0,1 -1,0 0,-1 z m 0,2 1,0 0,1 -1,0 0,-1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path11132-5"
+ d="m 2,55.25 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path11134-5"
+ d="m 1,76 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 L 3,76 1,76 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path11136-4"
+ d="m 1,98 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path11138-9"
+ d="m 1,118 0,5 1,0 0,-2 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path11140-1"
+ d="m 2,139 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 0,-1.25 -1,0 0,1.25 -1,0 0,-3 2,0 0,-1 -2,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path11142-2"
+ d="m 1,160 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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
+ y="182"
+ x="2"
+ height="5"
+ width="1"
+ id="rect11144-5"
+ style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ id="path11146-0"
+ d="m 3,202 0,4 -1,0 0,-1 -1,0 0,1 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-4 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path11148-8"
+ d="m 1,223 0,5 1,0 0,-1.75 1,0 0,-1.5 -1,0 0,-1.75 -1,0 z m 2,1.75 1,0 0,-1.75 -1,0 0,1.75 z m 0,1.5 0,1.75 1,0 0,-1.75 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path11150-3"
+ d="m 1,244 0,5 1,0 2,0 0,-1 -2,0 0,-4 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path11152-9"
+ d="m 1,265 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,-1 -1,0 z m 1,0 1,0 0,3 1,0 0,-5 -1,0 0,1 -1,0 0,1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path11154-3"
+ d="m 1,286 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path11156-9"
+ d="m 2,307 0,1 1,0 0,-1 -1,0 z m 1,1 0,3 1,0 0,-3 -1,0 z m 0,3 -1,0 0,1 1,0 0,-1 z m -1,0 0,-3 -1,0 0,3 1,0 z"
+ style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="cccccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path11158-6"
+ d="m 1,328 0,5 1,0 0,-2 1.25,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path11160-7"
+ d="m 2,349 0,1 1,0 0,-1 -1,0 z m 1,1 0,3 1,0 0,-3 -1,0 z m 0,3 -1,0 0,1 1,0 0,-1 z m 0,1 0,1 1,0 0,-1 -1,0 z m -1,-1 0,-3 -1,0 0,3 1,0 z"
+ style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccccccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path11162-9"
+ d="m 1,370 0,5 1,0 0,-2 1,0 0,2 1,0 0,-2 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path11164-9"
+ d="m 2,391 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path11166-7"
+ d="m 1,412 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path11168-6"
+ d="m 1,434 0,4.25 1,0 0,0.75 2,0 0,-0.75 1,0 0,-4.25 -1,0 0,4 -2,0 0,-4 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path11170-9"
+ d="m 1,455 0,3.25 1,0 0,1.75 1,0 0,-1.75 1,0 0,-3.25 -1,0 0,3 -1,0 0,-3 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path11172-3"
+ d="m 3e-6,474.75 0,3.25 1,0 0,1.75 1,0 0,-1.75 L 3,478 l 0,1.75 1.000003,0 0,-1.75 1,0 0,-3.25 -1,0 0,3 -1.000003,0 0,-2 -0.999997,0 0,2 -1,0 0,-3 -1,0 0,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 1,497 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"
+ id="path11174-5"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path38393-7"
+ d="m 1,518 0,2.25 1,0 0,2.75 1,0 0,-2.75 1,0 0,-2.25 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path38395-6"
+ d="m 1,539 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"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 548,518 0,2.25 1,0 0,2.75 1,0 0,-2.75 1,0 0,-2.25 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ id="path38435-6"
+ inkscape:connector-curvature="0" />
+ <path
+ style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 548,539 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"
+ id="path38437-5"
+ inkscape:connector-curvature="0" />
+ <g
+ style="color:#000000;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="g41041-8"
+ transform="translate(0,634)">
+ <path
+ id="path41043-2"
+ d="m 12,1 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41045-5"
+ d="m 33,1 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 L 35,1 33,1 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41047-4"
+ d="m 54,1 0,1 2,0 0,1 1,0 0,-1.25 -1,0 L 56,1 54,1 z m 2,2 -1,0 0,1 1,0 0,-1 z m 0,1 0,1 -2,0 0,1 2,0 0,-0.75 1,0 L 57,4 56,4 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41049-4"
+ d="m 75,1 0,3 1,0 1,0 0,2 1,0 0,-4 -1,0 0,1 -1,0 0,-2 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41051-1"
+ d="m 96,1 0,3 1,0 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41053-6"
+ d="m 118,1 0,0.75 -1,0 0,3.25 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-1 -0.75,0 0,-1 -1.25,0 0,-1 1.5,0 0,-1 -1.5,0 z m 0,3 1,0 0,1 -1,0 0,-1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41055-1"
+ d="m 138,1 0,1 2,0 0,1 -1,0 0,3 1,0 0,-2.75 1,0 0,-1.25 0,-1 -3,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41057-6"
+ d="m 159.75,1 0,1 -0.5,0 0,1 0.5,0 0,1 -0.75,0 0,1 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-1 -0.75,0 0,-1 0.5,0 0,-1 -0.5,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z m 0,2 1,0 0,1 -1,0 0,-1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41059-3"
+ d="m 180.75,1 0,1 -0.75,0 0,1 0.75,0 0,1 1.25,0 0,1 -1.5,0 0,1 1.5,0 0,-0.75 1,0 0,-3.25 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ sodipodi:nodetypes="cccccccccccccccccc"
+ id="path41061-3"
+ d="m 202.75,1 0,1 -0.75,0 0,3 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-3 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,3 -1,0 0,-3 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 514,1 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ id="path41063-5"
+ inkscape:connector-curvature="0" />
+ <path
+ style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 476,1 0,1 2,0 0,1 1,0 0,-1.25 -1,0 0,-0.75 -2,0 z m 2,2 -1,0 0,1 1,0 0,-1 z m 0,1 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.25 -1,0 z"
+ id="path41065-5"
+ inkscape:connector-curvature="0" />
+ <path
+ style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 497,1 0,3 1,0 1,0 0,2 1,0 0,-4 -1,0 0,1 -1,0 0,-2 -1,0 z"
+ id="path41067-3"
+ inkscape:connector-curvature="0" />
+ <path
+ style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 518,1 0,3 1,0 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path41069-2"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41071-8"
+ d="m 200,1 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41073-2"
+ d="m 244,1 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41075-5"
+ d="m 265,1 0,1 2,0 0,1 1,0 0,-1.25 -1,0 0,-0.75 -2,0 z m 2,2 -1,0 0,1 1,0 0,-1 z m 0,1 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.25 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41077-3"
+ d="m 286,1 0,3 1,0 1,0 0,2 1,0 0,-4 -1,0 0,1 -1,0 0,-2 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41079-6"
+ d="m 307,1 0,3 1,0 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41081-1"
+ d="m 329,1 0,0.75 -1,0 0,3.25 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-1 -0.75,0 0,-1 -1.25,0 0,-1 1.5,0 0,-1 -1.5,0 z m 0,3 1,0 0,1 -1,0 0,-1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41083-8"
+ d="m 349,1 0,1 2,0 0,1 -1,0 0,3 1,0 0,-2.75 1,0 0,-1.25 0,-1 -3,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41085-6"
+ d="m 370.75,1 0,1 -0.5,0 0,1 0.5,0 0,1 -0.75,0 0,1 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-1 -0.75,0 0,-1 0.5,0 0,-1 -0.5,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z m 0,2 1,0 0,1 -1,0 0,-1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41087-2"
+ d="m 391.75,1 0,1 -0.75,0 0,1 0.75,0 0,1 1.25,0 0,1 -1.5,0 0,1 1.5,0 0,-0.75 1,0 0,-3.25 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41089-1"
+ d="m 413.75,1 0,1 -0.75,0 0,3 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-3 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,3 -1,0 0,-3 z m 0.25,1 0,1 0.5,0 0,-1 -0.5,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41091-4"
+ d="m 221,1 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 224,1 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ id="path41093-6"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41095-2"
+ d="m 242,1 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41097-9"
+ d="m 263,1 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41099-1"
+ d="m 284,1 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41101-5"
+ d="m 305,1 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41103-0"
+ d="m 326,1 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41105-3"
+ d="m 347,1 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41107-6"
+ d="m 368,1 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41109-4"
+ d="m 389,1 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41111-9"
+ d="m 409,1 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41113-2"
+ d="m 435,1 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41116-9"
+ d="m 430,1 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41118-3"
+ d="m 451,1 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 455,1 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ id="path41120-4"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41122-4"
+ d="m 472,1 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41124-0"
+ d="m 493,1 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ id="path41126-5"
+ d="m 536,1 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ style="color:#000000;fill:#b3b3b3;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" />
+ <path
+ style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 541,1 0,0.75 -1,0 0,3.25 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-1 -0.75,0 0,-1 -1.25,0 0,-1 1.5,0 0,-1 -1.5,0 z m 0,3 1,0 0,1 -1,0 0,-1 z"
+ id="path41128-9"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ id="path30643-6"
+ d="m 585,617.25 1,0 0,0.75 3,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -3,0 0,0.75 -1,0 0,1.5 z m 1,-0.25 0,-1 3,0 0,1 -3,0 z m 1,-0.25 1,0 0,-0.5 -1,0 0,0.5 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path30647-3"
+ d="m 585,630 1,0 0,-2 1,0 0,1 1,0 0,-1 -0.75,0 0,-1 -1.5,0 0,1 -0.75,0 0,2 z m 3,-1 0,1 1,0 1,0 0,-3 -1,0 0,2 -1,0 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path30649-4"
+ d="m 585,624 3,0 0,-1 0,-1 1,0 0,2 1,0 0,-2 -0.75,0 0,-1 -1.5,0 0,1 -0.75,0 0,1 -1,0 0,-2 -1,0 0,2 0,1 z"
+ 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
+ y="589"
+ x="-626"
+ height="1"
+ width="1"
+ id="rect30651-2"
+ 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"
+ transform="matrix(0,-1,1,0,0,0)" />
+ <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="rect30653-8"
+ width="1"
+ height="1"
+ x="-620"
+ y="589"
+ transform="matrix(0,-1,1,0,0,0)" />
+ <rect
+ y="589"
+ x="-634"
+ height="1"
+ width="1"
+ id="rect30725-87"
+ 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"
+ transform="matrix(0,-1,1,0,0,0)" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path30723-5"
+ d="m 587,638 2.25,0 0,-1 0.75,0 0,-1 -0.75,0 0,-1 -2.25,0 0,1 2,0 0,1 -2,0 0,1 z"
+ 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"
+ sodipodi:nodetypes="ccccccccccccc" />
+ <path
+ id="path30643-7-0"
+ d="m 903.75,209 0,1 -0.75,0 0,3 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-3 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,3 -1,0 0,-3 z m 0.25,1 0,1 0.5,0 0,-1 -0.5,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path30647-6-1"
+ d="m 891,209 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path30649-7-4"
+ d="m 897,209 0,3 1,0 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="213"
+ x="895"
+ height="1"
+ width="1"
+ id="rect30651-8-6"
+ 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:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect30653-7-0"
+ width="1"
+ height="1"
+ x="901"
+ y="213" />
+ <rect
+ y="213"
+ x="887"
+ height="1"
+ width="1"
+ id="rect30725-8-7"
+ 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" />
+ <path
+ id="path30723-1-1"
+ d="m 883,211 0,2.25 1,0 0,0.75 1,0 0,-0.75 1,0 0,-2.25 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ 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"
+ sodipodi:nodetypes="ccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(810,316)"
+ id="g72798"
+ style="opacity:0.5;display:inline;enable-background:new">
+ <g
+ id="g72716">
+ <path
+ id="path72434"
+ d="m 186,-127 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 0,-1.25 -1,0 0,1.25 -1,0 0,-3 2,0 0,-1 -2,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="-127"
+ x="219"
+ height="5"
+ width="1"
+ id="rect72436"
+ 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" />
+ <path
+ id="path72438"
+ d="m 144,-127 0,4 -1,0 0,-1 -1,0 0,1 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-4 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path72440"
+ d="m 189,-127 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path72442"
+ d="m 165,-127 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path72446"
+ d="m 130,-127 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path72448"
+ d="m 154,-127 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path72450"
+ d="m 133,-127 0,4.25 1,0 0,0.75 2,0 0,-0.75 1,0 0,-4.25 -1,0 0,4 -2,0 0,-4 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path72452"
+ d="m 138,-127 0,5 1,0 1,0 0,-0.5 1,0 0,-1.5 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z m 0,2 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path72454"
+ d="m 151,-127 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path72456"
+ d="m 146,-127 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 209,-127 0,5 1,0 2,0 0,-1 -2,0 0,-4 -1,0 z"
+ id="path72458"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 160,-127 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z"
+ id="path72460" />
+ <path
+ id="path72462"
+ d="m 171,-127 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path72464"
+ d="m 175,-127 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 179,-127 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path72466" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 194,-127 0,4.25 1,0 0,0.75 2,0 0,-0.75 1,0 0,-4.25 -1,0 0,4 -2,0 0,-4 -1,0 z"
+ id="path72468" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 202,-127 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 0,-1.25 -1,0 0,1.25 -1,0 0,-3 2,0 0,-1 -2,0 z"
+ id="path72470" />
+ <path
+ id="path72472"
+ d="m 205,-127 0,5 1,0 0,-2 1.25,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path72474"
+ d="m 215,-127 0,5 1,0 2,0 0,-1 -2,0 0,-4 -1,0 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 222,-127 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ id="path72476" />
+ <path
+ id="path72478"
+ d="m 225,-127 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 229,-127 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ id="path72480" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 235,-127 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ id="path72482" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 238,-127 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path72484" />
+ <path
+ id="path72486"
+ d="m 242.75,-123 0,1 -0.75,0 0,1 1,0 0,-1 1,0 0,-1 -1.25,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32008-7"
+ d="m 72,-127 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32010-4"
+ d="m 76,-127 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ 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
+ y="-127"
+ x="80"
+ height="5"
+ width="1"
+ id="rect32012-0"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32015-9"
+ d="m 83,-127 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32017-4"
+ d="m 89,-127 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32019-8"
+ d="m 97,-127 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32021-8"
+ d="m 93,-127 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32023-2"
+ d="m 102,-127 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32026-4"
+ d="m 106,-127 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 110,-127 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ id="path32029-5" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 115,-127 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z"
+ id="path32031-5" />
+ <rect
+ y="-127"
+ x="121"
+ height="5"
+ width="1"
+ id="rect32033-1"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 124,-127 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ id="path32035-7" />
+ </g>
+ <g
+ id="g72757">
+ <path
+ id="path72562"
+ d="m 78,-119 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="-119"
+ x="82"
+ height="5"
+ width="1"
+ id="rect72564"
+ 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" />
+ <path
+ id="path72576"
+ d="m 72,-119 0,3.25 1,0 0,1.75 1,0 0,-1.75 1,0 0,1.75 1,0 0,-1.75 1,0 0,-3.25 -1,0 0,3 -1,0 0,-2 -1,0 0,2 -1,0 0,-3 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path72578"
+ d="m 130,-119 0,2.25 1,0 0,2.75 1,0 0,-2.75 1,0 0,-2.25 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path72580"
+ d="m 94.75,-119 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path72582"
+ d="m 85,-119 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 88,-119 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ id="path72588" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 99,-119 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ id="path72590" />
+ <path
+ id="path72592"
+ d="m 103,-119 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 107,-119 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ id="path72594" />
+ <path
+ id="path72596"
+ d="m 111,-119 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,-1 -1,0 z m 1,0 1,0 0,3 1,0 0,-5 -1,0 0,1 -1,0 0,1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 117,-119 0,5 1,0 0,-2 1.25,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ id="path72598" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 121.75,-119 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ id="path72600" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 125,-119 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ id="path72602" />
+ <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="rect72604"
+ width="1"
+ height="5"
+ x="136"
+ y="-119" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 138,-119 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z"
+ id="path72606" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 144.75,-119 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ id="path72608" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path72610"
+ d="m 148,-119 0,5 1,0 2,0 0,-1 -2,0 0,-4 -1,0 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 153,-119 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ id="path72612" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 157,-119 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ id="path72614" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 163,-119 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 0,-1.25 -1,0 0,1.25 -1,0 0,-3 2,0 0,-1 -2,0 z"
+ id="path72616" />
+ <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="rect72618"
+ width="1"
+ height="5"
+ x="174"
+ y="-119" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 168,-119 0,3.25 1,0 0,1.75 1,0 0,-1.75 1,0 0,1.75 1,0 0,-1.75 1,0 0,-3.25 -1,0 0,3 -1,0 0,-2 -1,0 0,2 -1,0 0,-3 -1,0 z"
+ id="path72620" />
+ <path
+ id="path72622"
+ d="m 180,-119 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path72624"
+ d="m 176,-119 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32207-9-7"
+ d="m 187,-119 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32209-6-7"
+ d="m 191,-119 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32211-3-7"
+ d="m 195,-119 0,5 1,0 0,-2 1.25,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32213-7-3"
+ d="m 199,-119 0,2.25 1,0 0,2.75 1,0 0,-2.75 1,0 0,-2.25 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32216-8-3"
+ d="m 203,-119 0,5 1,0 0,-2 1,0 0,2 1,0 0,-2 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ 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:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect32218-8-5"
+ width="1"
+ height="5"
+ x="207"
+ y="-119" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32220-2-9"
+ d="m 210,-119 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 0,-1.25 -1,0 0,1.25 -1,0 0,-3 2,0 0,-1 -2,0 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32222-9-9"
+ d="m 213,-119 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32224-1-8"
+ d="m 217,-119 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z"
+ 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" />
+ <path
+ id="path72678"
+ d="m 225,-119 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 235,-119 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ id="path72680"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="-119"
+ x="223"
+ height="5"
+ width="1"
+ id="rect72682"
+ 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
+ y="-115"
+ x="239"
+ height="1"
+ width="1"
+ id="rect72684"
+ 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" />
+ <path
+ id="path72686"
+ d="m 230,-119 0,5 1,0 0,-2 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(810,316)"
+ style="display:inline;enable-background:new"
+ id="g72880">
+ <g
+ transform="translate(231,-90)"
+ id="g32242-4">
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m -12.25,-17 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ id="path32244-2" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m -9,-17 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,-1 -1,0 z m 1,0 1,0 0,3 1,0 0,-5 -1,0 0,1 -1,0 0,1 z"
+ id="path32246-0" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m -3,-17 0,5 1,0 1,0 0,-0.5 1,0 0,-1.5 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z m 0,2 1,0 0,1 -1,0 0,-1 z"
+ id="path32248-9" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 1,-17 0,5 1,0 0,-2 1,0 0,2 1,0 0,-2 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ id="path32250-7" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 6,-17 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ id="path32252-3" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 10,-17 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"
+ id="path32254-7" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m -43.25,-17 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ id="path32256-2" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32258-6"
+ d="m -40,-17 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32260-0"
+ d="m -35,-17 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m -31,-17 0,5 1,0 0,-2 1,0 0,2 1,0 0,-2 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ id="path32262-1" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m -27,-17 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"
+ id="path32264-6" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32266-5"
+ d="m -23,-17 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32268-7"
+ d="m -17,-17 0,4 -1,0 0,-1 -1,0 0,1 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-4 -1,0 z"
+ 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
+ y="-19"
+ x="11"
+ height="1"
+ width="1"
+ id="rect32270-5"
+ 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" />
+ </g>
+ <g
+ id="g21967-4"
+ transform="translate(111.96875,-88)">
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 48,-20 0,0.75 -1,0 0,0.25 -0.25,0 0,1 -0.75,0 0,3 0.75,0 0,1 0.25,0 0,0.25 1,0 0,0.75 3,0 0,-0.75 1,0 0,-0.25 0.25,0 0,-1 0.75,0 0,-3 -0.75,0 0,-1 -0.25,0 0,-0.25 -1,0 0,-0.75 -3,0 z m 0,1 3,0 0,1 1,0 0,3 -1,0 0,1 -3,0 0,-1 -1,0 0,-3 1,0 0,-1 z"
+ id="path32272-1"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path32274-2"
+ d="m 49,-18 0,0.75 -1,0 0,1.5 1,0 0,0.75 1.25,0 0,-1 -1.25,0 0,-1 1.25,0 0,-1 -1.25,0 z"
+ 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"
+ sodipodi:nodetypes="ccccccccccccc" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 171.71875,-107 0,1 -0.75,0 0,3 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-3 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,3 -1,0 0,-3 z m 0.25,1 0,1 0.5,0 0,-1 -0.5,0 z"
+ id="path72688" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 175.96875,-107 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ id="path72690" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 177.96875,-107 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ id="path72692" />
+ <path
+ id="path72694"
+ d="m 166.96875,-107 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 182.96875,-106 0,1 1,0 0,-1 -1,0 z m -0.21875,3 0,1 -0.75,0 0,1 1,0 0,-1 1,0 0,-1 -1.25,0 z"
+ id="path72696" />
+ </g>
+ <g
+ style="opacity:0.4;display:inline;enable-background:new"
+ id="g73280"
+ transform="matrix(0,-1,1,0,722,710)">
+ <g
+ id="g73282">
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 186,-127 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 0,-1.25 -1,0 0,1.25 -1,0 0,-3 2,0 0,-1 -2,0 z"
+ id="path73284" />
+ <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="rect73286"
+ width="1"
+ height="5"
+ x="219"
+ y="-127" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 144,-127 0,4 -1,0 0,-1 -1,0 0,1 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-4 -1,0 z"
+ id="path73288" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 189,-127 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ id="path73290" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 165,-127 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ id="path73292" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 130,-127 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ id="path73294" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 154,-127 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z"
+ id="path73296" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 133,-127 0,4.25 1,0 0,0.75 2,0 0,-0.75 1,0 0,-4.25 -1,0 0,4 -2,0 0,-4 -1,0 z"
+ id="path73298" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 138,-127 0,5 1,0 1,0 0,-0.5 1,0 0,-1.5 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z m 0,2 1,0 0,1 -1,0 0,-1 z"
+ id="path73300" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 151,-127 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ id="path73302" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 146,-127 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path73304" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path73306"
+ d="m 209,-127 0,5 1,0 2,0 0,-1 -2,0 0,-4 -1,0 z"
+ 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" />
+ <path
+ id="path73308"
+ d="m 160,-127 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 171,-127 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z"
+ id="path73310" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 175,-127 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ id="path73312" />
+ <path
+ id="path73314"
+ d="m 179,-127 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73316"
+ d="m 194,-127 0,4.25 1,0 0,0.75 2,0 0,-0.75 1,0 0,-4.25 -1,0 0,4 -2,0 0,-4 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73318"
+ d="m 202,-127 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 0,-1.25 -1,0 0,1.25 -1,0 0,-3 2,0 0,-1 -2,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 205,-127 0,5 1,0 0,-2 1.25,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ id="path73320" />
+ <path
+ 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"
+ d="m 215,-127 0,5 1,0 2,0 0,-1 -2,0 0,-4 -1,0 z"
+ id="path73322"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73324"
+ d="m 222,-127 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 225,-127 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path73326" />
+ <path
+ id="path73328"
+ d="m 229,-127 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73330"
+ d="m 235,-127 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73332"
+ d="m 238,-127 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 242.75,-123 0,1 -0.75,0 0,1 1,0 0,-1 1,0 0,-1 -1.25,0 z"
+ id="path73334" />
+ <path
+ 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"
+ d="m 72,-127 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z"
+ id="path73336"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 76,-127 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ id="path73338"
+ inkscape:connector-curvature="0" />
+ <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="rect73340"
+ width="1"
+ height="5"
+ x="80"
+ y="-127" />
+ <path
+ 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"
+ d="m 83,-127 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ id="path73342"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 89,-127 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ id="path73344"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 97,-127 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ id="path73346"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 93,-127 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ id="path73348"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 102,-127 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z"
+ id="path73350"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 106,-127 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path73352"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73354"
+ d="m 110,-127 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73356"
+ d="m 115,-127 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <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="rect73358"
+ width="1"
+ height="5"
+ x="121"
+ y="-127" />
+ <path
+ id="path73360"
+ d="m 124,-127 0,0.75 -1,0 0,1.5 1,0 0,0.75 1,0 0,1 -2,0 0,1 2,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -1,0 0,-1 1.5,0 0,-1 -1.5,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g73362"
+ transform="translate(175,-8)">
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 78,-119 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ id="path73364" />
+ <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="rect73366"
+ width="1"
+ height="5"
+ x="82"
+ y="-119" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 72,-119 0,3.25 1,0 0,1.75 1,0 0,-1.75 1,0 0,1.75 1,0 0,-1.75 1,0 0,-3.25 -1,0 0,3 -1,0 0,-2 -1,0 0,2 -1,0 0,-3 -1,0 z"
+ id="path73368" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 130,-119 0,2.25 1,0 0,2.75 1,0 0,-2.75 1,0 0,-2.25 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ id="path73370" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 94.75,-119 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ id="path73372" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 85,-119 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ id="path73374" />
+ <path
+ id="path73376"
+ d="m 88,-119 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73378"
+ d="m 99,-119 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 103,-119 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ id="path73380" />
+ <path
+ id="path73382"
+ d="m 107,-119 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 111,-119 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,-1 -1,0 z m 1,0 1,0 0,3 1,0 0,-5 -1,0 0,1 -1,0 0,1 z"
+ id="path73384" />
+ <path
+ id="path73386"
+ d="m 117,-119 0,5 1,0 0,-2 1.25,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73388"
+ d="m 121.75,-119 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73390"
+ d="m 125,-119 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="-119"
+ x="136"
+ height="5"
+ width="1"
+ id="rect73392"
+ 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" />
+ <path
+ id="path73394"
+ d="m 138,-119 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73396"
+ d="m 144.75,-119 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 148,-119 0,5 1,0 2,0 0,-1 -2,0 0,-4 -1,0 z"
+ id="path73398"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73400"
+ d="m 153,-119 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73402"
+ d="m 157,-119 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73404"
+ d="m 163,-119 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 0,-1.25 -1,0 0,1.25 -1,0 0,-3 2,0 0,-1 -2,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="-119"
+ x="174"
+ height="5"
+ width="1"
+ id="rect73406"
+ 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" />
+ <path
+ id="path73408"
+ d="m 168,-119 0,3.25 1,0 0,1.75 1,0 0,-1.75 1,0 0,1.75 1,0 0,-1.75 1,0 0,-3.25 -1,0 0,3 -1,0 0,-2 -1,0 0,2 -1,0 0,-3 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 180,-119 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ id="path73410" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 176,-119 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z"
+ id="path73412" />
+ <path
+ 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"
+ d="m 187,-119 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 -2,0 0,-3 2,0 0,-1 -2,0 z"
+ id="path73414"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 191,-119 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ id="path73416"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 195,-119 0,5 1,0 0,-2 1.25,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ id="path73418"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 199,-119 0,2.25 1,0 0,2.75 1,0 0,-2.75 1,0 0,-2.25 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ id="path73420"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 203,-119 0,5 1,0 0,-2 1,0 0,2 1,0 0,-2 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ id="path73422"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="-119"
+ x="207"
+ height="5"
+ width="1"
+ id="rect73424"
+ 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" />
+ <path
+ 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"
+ d="m 210,-119 0,0.75 -1,0 0,3.5 1,0 0,0.75 2,0 0,-1 0,-1.25 -1,0 0,1.25 -1,0 0,-3 2,0 0,-1 -2,0 z"
+ id="path73426"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 213,-119 0,5 1,0 0,-2 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ id="path73428"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 217,-119 0,1 1,0 0,4 1,0 0,-4 1,0 0,-1 -3,0 0,0 z"
+ id="path73430"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 225,-119 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ id="path73432" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path73434"
+ d="m 235,-119 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ 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:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect73436"
+ width="1"
+ height="5"
+ x="223"
+ y="-119" />
+ <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="rect73438"
+ width="1"
+ height="1"
+ x="239"
+ y="-115" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 230,-119 0,5 1,0 0,-2 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path73440" />
+ </g>
+ </g>
+ <g
+ id="g73442"
+ style="display:inline;enable-background:new"
+ transform="matrix(0,-1,1,0,692,540.96875)">
+ <g
+ id="g73444"
+ transform="translate(231,-90)">
+ <path
+ id="path73446"
+ d="m -12.25,-17 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73448"
+ d="m -9,-17 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,-1 -1,0 z m 1,0 1,0 0,3 1,0 0,-5 -1,0 0,1 -1,0 0,1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73450"
+ d="m -3,-17 0,5 1,0 1,0 0,-0.5 1,0 0,-1.5 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z m 0,2 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73452"
+ d="m 1,-17 0,5 1,0 0,-2 1,0 0,2 1,0 0,-2 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73454"
+ d="m 6,-17 0,1 2,0 0,-1 -2,0 z m 2,1 0,3 1,0 0,-3 -1,0 z m 0,3 -2,0 0,1 2,0 0,-1 z m -2,0 0,-3 -1,0 0,3 1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73456"
+ d="m 10,-17 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"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73458"
+ d="m -43.25,-17 0,1 -0.75,0 0,4 1,0 0,-2 1,0 0,2 1,0 0,-4 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m -40,-17 0,5 1,0 0,-3 1,0 0,-1 -1,0 0,-1 -1,0 z m 2,2 0,1 1,0 0,2 1,0 0,-5 -1,0 0,2 -1,0 z"
+ id="path73460"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m -35,-17 0,1 0,3 0,1 2,0 0,-0.75 1,0 0,-3.5 -1,0 0,-0.75 -2,0 z m 1,1 1,0 0,3 -1,0 0,-3 z"
+ id="path73462"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73464"
+ d="m -31,-17 0,5 1,0 0,-2 1,0 0,2 1,0 0,-2 -0.75,0 0,-1 0.75,0 0,-1.25 -1,0 0,-0.75 -1,0 -1,0 z m 1,1 1,0 0,1 -1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73466"
+ d="m -27,-17 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"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m -23,-17 0,5 1,0 2,0 0,-1 -2,0 0,-1 1,0 0,-1 -1,0 0,-1 2,0 0,-1 -2,0 -1,0 z"
+ id="path73468"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m -17,-17 0,4 -1,0 0,-1 -1,0 0,1 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-4 -1,0 z"
+ id="path73470"
+ inkscape:connector-curvature="0" />
+ <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="rect73472"
+ width="1"
+ height="1"
+ x="11"
+ y="-19" />
+ </g>
+ <g
+ transform="translate(111.96875,-88)"
+ id="g73474">
+ <path
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccc"
+ id="path73476"
+ d="m 48,-20 0,0.75 -1,0 0,0.25 -0.25,0 0,1 -0.75,0 0,3 0.75,0 0,1 0.25,0 0,0.25 1,0 0,0.75 3,0 0,-0.75 1,0 0,-0.25 0.25,0 0,-1 0.75,0 0,-3 -0.75,0 0,-1 -0.25,0 0,-0.25 -1,0 0,-0.75 -3,0 z m 0,1 3,0 0,1 1,0 0,3 -1,0 0,1 -3,0 0,-1 -1,0 0,-3 1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccccc"
+ 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"
+ d="m 49,-18 0,0.75 -1,0 0,1.5 1,0 0,0.75 1.25,0 0,-1 -1.25,0 0,-1 1.25,0 0,-1 -1.25,0 z"
+ id="path73478"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path73480"
+ d="m 171.71875,-107 0,1 -0.75,0 0,3 0.75,0 0,1 1.5,0 0,-1 0.75,0 0,-3 -0.75,0 0,-1 -1.5,0 z m 0.25,1 1,0 0,3 -1,0 0,-3 z m 0.25,1 0,1 0.5,0 0,-1 -0.5,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73482"
+ d="m 175.96875,-107 0,1 -1,0 0,1 1,0 0,3 1,0 0,-5 -1,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path73484"
+ d="m 177.96875,-107 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 166.96875,-107 0,1 2,0 0,1 -1,0 0,1 1,0 0,-0.75 1,0 0,-1.5 -1,0 0,-0.75 -2,0 z m 1,3 -1,0 0,1 0,1 3,0 0,-1 -2,0 0,-1 z"
+ id="path73486" />
+ <path
+ id="path73488"
+ d="m 182.96875,-106 0,1 1,0 0,-1 -1,0 z m -0.21875,3 0,1 -0.75,0 0,1 1,0 0,-1 1,0 0,-1 -1.25,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="opacity:0.4;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 545,238 0,1 9,0 0,41 -9,0 0,1 9,0 1,0 0,-21 1,0 0,-1 -1,0 0,-21 -1,0 z"
+ id="rect11044-9-4"
+ sodipodi:nodetypes="ccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ inkscape:label="ICONS"
+ inkscape:groupmode="layer"
+ id="layer1"
+ style="display:inline">
+ <g
+ transform="matrix(0,1,1,0,-174,194)"
+ style="display:inline;enable-background:new"
+ id="g106468-0">
+ <g
+ 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.9535916,0,0,1.1712921,1176.1968,319.2322)"
+ id="g29877-5-3-1-8"
+ style="display:inline;enable-background:new">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path29879-5-0-9-1"
+ d="m 392.96689,241.84215 -0.56915,0 -3.5287,2.84782 0,1.13912 3.5287,2.84781 0.56915,0 0,-6.83475 0,0 0,0 z"
+ style="color:#000000;fill:url(#radialGradient106344-5-2);fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient106433-4);stroke-width:0.66107476px;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
+ sodipodi:nodetypes="cccc"
+ id="path29881-5-6-0-4"
+ d="m 392.96688,248.67221 -0.57173,0 -3.51515,-2.83619 -0.008,-1.21916"
+ style="fill:none;stroke:url(#linearGradient106307-2-4);stroke-width:0.66107482px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ y="598"
+ x="404"
+ height="16"
+ width="16"
+ id="rect24491-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" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ inkscape:export-ydpi="90"
+ 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">
+ <g
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="/home/georg/Arbeitsfläche/2012/Blender Coding/Patch #2a/icon_redone 4 (alpha).png"
+ id="g14715"
+ transform="translate(-320.42789,5.4177849)"
+ style="display:inline">
+ <rect
+ style="opacity:0;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect14717"
+ width="16"
+ height="16"
+ x="389"
+ y="289"
+ rx="0.80014729"
+ ry="0" />
+ <g
+ transform="translate(-177,71)"
+ id="g14719">
+ <g
+ transform="translate(480,287.5)"
+ id="g14721"
+ 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
+ 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"
+ transform="translate(-118.5,-200.5)"
+ id="g14723" />
+ </g>
+ <g
+ style="fill:#000000"
+ transform="translate(1,24)"
+ id="g14725" />
+ </g>
+ </g>
+ <rect
+ style="opacity:0;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect14727"
+ width="16"
+ height="16"
+ x="68.572113"
+ y="294.41779"
+ rx="0"
+ inkscape:export-filename="/home/georg/Arbeitsfläche/2012/Blender Coding/Patch #2a/icon_redone 4 (alpha).png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient14800);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 72.738774,294.91779 10.33334,0 0,14.99999 -13,0 -1e-5,-11.99999 2.66667,-3 z"
+ id="path14729"
+ sodipodi:nodetypes="cccccc"
+ inkscape:export-filename="/home/georg/Arbeitsfläche/2012/Blender Coding/Patch #2a/icon_redone 4 (alpha).png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path14731"
+ style="fill:none;stroke:url(#linearGradient14802);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 71.072114,299.41778 0,9.5 m 3.5,-13 7.5,0"
+ sodipodi:nodetypes="cccc"
+ inkscape:export-filename="/home/georg/Arbeitsfläche/2012/Blender Coding/Patch #2a/icon_redone 4 (alpha).png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path14733"
+ d="m 69.572114,298.41778 4,0 0,-4 -4,4 z"
+ style="fill:#ffffff;fill-opacity:0.75490196;fill-rule:evenodd;stroke:none;display:inline"
+ inkscape:export-filename="/home/georg/Arbeitsfläche/2012/Blender Coding/Patch #2a/icon_redone 4 (alpha).png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path14735"
+ 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 70.072114,297.41779 0,12.49999 13,0 0,-14.99999 -10.5,0 -2.5,2.5 z"
+ inkscape:export-filename="/home/georg/Arbeitsfläche/2012/Blender Coding/Patch #2a/icon_redone 4 (alpha).png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <g
+ clip-path="url(#clipPath22590-7)"
+ mask="none"
+ transform="translate(100.57211,-194.58234)"
+ id="g14737"
+ style="display:inline"
+ inkscape:export-filename="/home/georg/Arbeitsfläche/2012/Blender Coding/Patch #2a/icon_redone 4 (alpha).png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <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="rect14739"
+ width="16"
+ height="16"
+ x="-29"
+ y="491.00012" />
+ <g
+ id="g14741">
+ <g
+ id="g14743">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ d="M -15.594023,497.94339 -20.25,493.5"
+ 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:0.34386529;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path14745" />
+ <path
+ transform="matrix(3.625,0,0,3.1690202,-67.8125,318.31703)"
+ d="m 14.5,57.5 a 1,1.0000004 0 1 1 -2,0 1,1.0000004 0 1 1 2,0 z"
+ sodipodi:ry="1.0000004"
+ sodipodi:rx="1"
+ sodipodi:cy="57.5"
+ sodipodi:cx="13.5"
+ id="path14747"
+ style="fill:none;stroke:#000000;stroke-width:1.32768786;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.10397505;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path14749"
+ 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:0.34386529;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -25.5,496.5 7.5,0 m -8.5,5.00012 3.5,-3.5"
+ sodipodi:nodetypes="cccc" />
+ </g>
+ <path
+ transform="matrix(3.5999897,0,0,3.1249932,-67.499871,320.6879)"
+ d="m 14.5,57.5 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="57.5"
+ sodipodi:cx="13.5"
+ id="path14751"
+ style="fill:none;stroke:url(#linearGradient14804);stroke-width:0.92424375;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.10397505;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ d="m -25.5,496.5 7.984366,-0.0226 M -26.5,501.50012 -21.5,496.5 m 5.996227,1.44466 L -20.25,493.5"
+ style="fill:none;stroke:url(#linearGradient14806);stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.34386529;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path14753" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path14755"
+ sodipodi:cx="13.5"
+ sodipodi:cy="57.5"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 14.5,57.5 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 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 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="57.5"
+ sodipodi:cx="13.5"
+ id="path14757"
+ style="fill:#2c5aa0;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient14808);stroke-width:0.22536004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.10397505;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path14759"
+ sodipodi:cx="13.5"
+ sodipodi:cy="57.5"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 14.5,57.5 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ transform="matrix(4.7519907,0,0,4.1435313,-83.051884,262.12196)" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ d="m -20.515634,493.80534 c -0.07079,-0.45769 0.0843,-0.63855 0.5,-0.5 m -6.734366,7.94478 3.280183,-3.10926 m -2,-2 6.25,0"
+ style="fill:none;stroke:url(#linearGradient14810);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ id="path14761" />
+ </g>
+ </g>
+ <path
+ style="fill:none;stroke:url(#linearGradient20368);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 74.072114,296.91778 0,2 -2,0"
+ id="path14763"
+ inkscape:connector-curvature="0"
+ inkscape:export-filename="/home/georg/Arbeitsfläche/2012/Blender Coding/Patch #2a/icon_redone 4 (alpha).png"
+ inkscape:export-xdpi="90"
+ 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 a 15.467961,5.3033009 0 1 1 -30.935922,0 15.467961,5.3033009 0 1 1 30.935922,0 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 1 1 -23.125,0 11.5625,10.125 0 1 1 23.125,0 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"
+ 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="rect18813"
+ width="16"
+ height="16"
+ x="257"
+ y="176" />
+ <g
+ transform="translate(254.01612,148.99638)"
+ id="g10120"
+ style="display:inline">
+ <path
+ sodipodi:nodetypes="czc"
+ style="fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 4.4999991,39.491912 c 4.0000009,0 3.4999969,-7 5.9999989,-7 2.500002,0 2.000002,7 5.999999,7"
+ id="path10122"
+ 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="path10124"
+ d="m 4.4999991,39.491912 c 4.0000009,0 3.4999969,-7 5.9999989,-7 2.500002,0 2.000002,7 5.999999,7"
+ style="fill:none;stroke:#e6e6e6;stroke-width:1.39999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="czc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g20291"
+ 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="rect18821"
+ width="16"
+ height="16"
+ x="341"
+ y="176" />
+ <g
+ transform="translate(258.01612,148.99638)"
+ id="g10158"
+ style="display:inline">
+ <path
+ style="fill:none;stroke:#000000;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 85.500006,38.5 90.478251,33.099997 95.456495,38.5"
+ id="path10160"
+ 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="path10162"
+ d="M 85.500006,38.5 90.478251,33.099997 95.456495,38.5"
+ style="fill:none;stroke:#e6e6e6;stroke-width:1.5;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>
+ </g>
+ <g
+ id="g20301"
+ transform="translate(0,2)">
+ <rect
+ y="176"
+ x="320"
+ height="16"
+ width="16"
+ id="rect18819"
+ 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(257.01612,148.99638)"
+ id="g10164"
+ style="display:inline">
+ <path
+ id="path10166"
+ d="M 65.500015,38.5 C 68.5,37 70,35 70.560871,31.5 71,35 72.5,37 75.621727,38.5"
+ style="fill:none;stroke:#000000;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"
+ sodipodi:nodetypes="ccc"
+ 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"
+ sodipodi:nodetypes="ccc"
+ style="fill:none;stroke:#e6e6e6;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 65.500015,38.5 C 68.5,37 70,35 70.560871,31.5 71,35 72.5,37 75.621727,38.5"
+ id="path10168"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g20337"
+ transform="translate(0,2)">
+ <rect
+ y="176"
+ x="278"
+ height="16"
+ width="16"
+ id="rect18815"
+ 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(255.01612,148.99638)"
+ id="g10170"
+ style="display:inline">
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:#000000;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="path10172"
+ sodipodi:cx="30.5"
+ sodipodi:cy="40"
+ sodipodi:rx="6"
+ sodipodi:ry="6"
+ d="m 36.5,40 a 6,6 0 1 1 -12,0"
+ sodipodi:start="0"
+ sodipodi:end="3.1415927"
+ 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"
+ transform="matrix(1,0,0,-1,0,78.5)" />
+ <path
+ transform="matrix(1,0,0,-1,0,78.5)"
+ 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"
+ sodipodi:end="3.1415927"
+ sodipodi:start="0"
+ d="m 36.5,40 a 6,6 0 1 1 -12,0"
+ sodipodi:ry="6"
+ sodipodi:rx="6"
+ sodipodi:cy="40"
+ sodipodi:cx="30.5"
+ id="path10174"
+ style="fill:none;stroke:#e6e6e6;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"
+ sodipodi:type="arc" />
+ </g>
+ </g>
+ <g
+ id="g20311"
+ 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="rect18817"
+ width="16"
+ height="16"
+ x="299"
+ y="176" />
+ <g
+ transform="translate(256.01612,148.99638)"
+ id="g10176"
+ style="display:inline">
+ <path
+ sodipodi:open="true"
+ sodipodi:end="3.1415927"
+ sodipodi:start="0"
+ d="m 36.5,40 a 6,6 0 1 1 -12,0"
+ sodipodi:ry="6"
+ sodipodi:rx="6"
+ sodipodi:cy="40"
+ sodipodi:cx="30.5"
+ id="path10178"
+ style="fill:none;stroke:#000000;stroke-width:2.65631413;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: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"
+ transform="matrix(0.833333,0,0,-1.333333,25.08333,92.82524)" />
+ <path
+ transform="matrix(0.833333,0,0,-1.333333,25.08333,92.82524)"
+ 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:#e6e6e6;stroke-width:1.32815707;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="path10181"
+ sodipodi:cx="30.5"
+ sodipodi:cy="40"
+ sodipodi:rx="6"
+ sodipodi:ry="6"
+ d="m 36.5,40 a 6,6 0 1 1 -12,0"
+ sodipodi:start="0"
+ sodipodi:end="3.1415927"
+ sodipodi:open="true" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g18862"
+ transform="translate(259,151)">
+ <rect
+ y="28"
+ x="103"
+ height="16"
+ width="16"
+ id="rect18823"
+ 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.01612368,-0.00361762)"
+ id="g10183"
+ style="display:inline">
+ <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="path10185"
+ d="m 104.5,37.503635 0,-4.000017 12,0 0,4"
+ style="fill:none;stroke:#000000;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"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ style="fill:none;stroke:#d7d7d7;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 104.5,37.503635 0,-4.000017 12,0 0,4"
+ id="path10187"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g18856"
+ 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"
+ id="rect18825"
+ width="16"
+ height="16"
+ x="123"
+ y="28" />
+ <g
+ transform="translate(0.01612368,-0.00361762)"
+ id="g10189"
+ style="display:inline">
+ <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="cssssc"
+ style="fill:none;stroke:#000000;stroke-width:2.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 124.5,39.491912 c 0.99099,0 0.85013,-1.626312 1.08378,-2.386485 0.35579,-1.15753 1.07105,-1.19962 1.4919,-0.197292 1.2357,2.943014 1.5163,-5.054472 2.42432,-6.416223 1.00014,-1.499896 0.90687,8.170836 3,4 1.95704,-3.899658 1.50039,4.999088 4,5"
+ id="path10191"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path10193"
+ d="m 124.5,39.491912 c 0.99099,0 0.85013,-1.626312 1.08378,-2.386485 0.35579,-1.15753 1.07105,-1.19962 1.4919,-0.197292 1.2357,2.943014 1.5163,-5.054472 2.42432,-6.416223 1.00014,-1.499896 0.90687,8.170836 3,4 1.95704,-3.899658 1.50039,4.999088 4,5"
+ style="fill:none;stroke:#e6e6e6;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"
+ sodipodi:nodetypes="cssssc"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g33683"
+ transform="translate(0,2)">
+ <rect
+ y="176"
+ x="446"
+ height="16"
+ width="16"
+ id="rect18831"
+ 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(263.91329,149.04559)"
+ id="g11360"
+ style="display:inline">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient37097);fill-opacity:1;fill-rule:nonzero;stroke:#11243e;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 190.07108,29.454411 c -3.02619,0 -5.48439,2.463313 -5.48438,5.5 0,3.036688 2.45819,5.500001 5.48438,5.5 3.02619,0 5.48437,-2.46331 5.48437,-5.5 0,-3.036689 -2.45818,-5.500001 -5.48437,-5.5 z m 0,2.98305 c 1.36546,0 2.53849,1.100464 2.53848,2.454803 0,1.354341 -1.17303,2.501413 -2.53848,2.501412 -1.36546,0 -2.47581,-1.14707 -2.47581,-2.501412 0,-1.354341 1.11035,-2.454805 2.47581,-2.454803 z"
+ id="path11362"
+ 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="csssccsssc" />
+ <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"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path11364"
+ style="fill:none;stroke:url(#linearGradient15782);stroke-width:1.77120221;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:type="arc"
+ transform="matrix(0.566689,0,0,-0.562497,115.2063,101.3747)" />
+ <path
+ transform="matrix(0.4330916,0,0,-0.424074,132.95389,85.01929)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient33681);stroke-width:2.33340454;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="path11366"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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"
+ 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="rect18829"
+ width="16"
+ height="16"
+ x="425"
+ y="176" />
+ <g
+ transform="translate(263,148.99995)"
+ id="g11368"
+ style="display:inline">
+ <g
+ id="g11370"
+ 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.786268,0,0,0.7877987,82.392071,-41.848894)">
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient37095);fill-opacity:1;fill-rule:nonzero;stroke:#11243e;stroke-width:1.16319752;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="path11372"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.874026,0,0,0.873701,-3.948211,-5.552958)" />
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path11374"
+ style="fill:none;stroke:url(#linearGradient33700);stroke-width:3.20095801;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.398744,0,0,-0.395524,58.82401,144.1804)" />
+ </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"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path11376"
+ style="fill:none;stroke:url(#linearGradient33666);stroke-width:5.31599474;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:type="arc"
+ transform="matrix(0.186538,0,0,-0.189699,145.3693,57.36304)" />
+ <path
+ transform="matrix(0.566689,0,0,-0.562497,95.23056,101.3747)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient33668);stroke-width:1.77120221;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="path11378"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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" />
+ <path
+ transform="matrix(0.424906,0,0,-0.424074,114.01316,85.183325)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient33670);stroke-width:2.35577321;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="path11380"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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"
+ 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"
+ id="rect17412"
+ width="16.000002"
+ height="16"
+ x="5"
+ y="302" />
+ <g
+ transform="translate(-316.99999,374)"
+ id="g19609"
+ style="display:inline">
+ <path
+ sodipodi:nodetypes="cccccc"
+ 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="path17384"
+ style="fill:none;stroke:#2c1700;stroke-width:3.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ d="m 330.02726,-62.5 4.63639,3 m -4.63639,-3 -4.63634,3 m 4.60909,-3 0,-6"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccccccc"
+ 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:#2c1700;stroke-width:1.80000007;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 329,-70 0,2 1.99999,0 0,-2 L 329,-70 z m -5,10 10e-6,2 2,0 -10e-6,-2 -2,0 z m 9.99999,0 0,2 2,0 0,-2 -2,0 z"
+ id="path17386"
+ 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"
+ transform="matrix(1.0911926,0,0,1.176776,253.08415,-79.548088)"
+ d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 z"
+ sodipodi:ry="1.5"
+ sodipodi:rx="1.5"
+ sodipodi:cy="14.5"
+ sodipodi:cx="70.5"
+ id="path17388"
+ style="fill:url(#radialGradient12427);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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"
+ sodipodi:nodetypes="cccc"
+ d="m 330.02726,-62.5 4.63639,3"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffddb9;stroke-width:1.89999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path17390"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 330.02724,-62.5 4.63639,3 m -4.63639,-3 -4.63634,3 m 4.60909,-3 0,-6"
+ style="opacity:0.8;fill:none;stroke:url(#radialGradient12429);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path17392"
+ 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="cccccc"
+ 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"
+ sodipodi:nodetypes="ccccc"
+ id="path17394"
+ d="m 333.99999,-60 0,2 2,0 0,-2 -2,0 z"
+ style="fill:#ffca91;fill-opacity:1;fill-rule:nonzero;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"
+ sodipodi:nodetypes="cccc"
+ id="path17396"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#be6200;stroke-width:1.89999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ d="m 330.02726,-62.5 -4.63634,3"
+ 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"
+ sodipodi:nodetypes="cc"
+ id="path17398"
+ style="fill:none;stroke:#ff921d;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ d="m 330.00001,-62.5 0,-6"
+ 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"
+ sodipodi:nodetypes="ccccc"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 329,-70 0,2 1.99999,0 0,-2 L 329,-70 z"
+ id="path17400"
+ 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"
+ sodipodi:nodetypes="ccccc"
+ style="fill:#e07400;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 324.00001,-60 0,2 1.99999,0 0,-2 -1.99999,0 z"
+ id="path17402"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="-63.75"
+ x="328.25"
+ height="3.5"
+ width="3.5000002"
+ id="rect17404"
+ style="opacity:0.05;fill:#552c00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="ccc"
+ id="path17406"
+ d="m 324.49999,-58.5 0,-1 1,0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1.00000083px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ 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:#ffe680;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00000107px;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 329.49999,-68.5 0,-0.967392 0.99998,0"
+ id="path17408"
+ sodipodi:nodetypes="ccc"
+ 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"
+ sodipodi:nodetypes="ccc"
+ id="path17410"
+ d="m 334.5,-58.499999 0,-1 1,0"
+ style="opacity:0.5;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00000107px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 334,-60.5 -3,-1.870665"
+ id="path17415"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.3;fill:#d4aa00;fill-opacity:1;fill-rule:evenodd;stroke:#784e21;stroke-width:1.00000036px;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 333.5,-59.499999 0,-1 1,0"
+ id="path17417"
+ sodipodi:nodetypes="ccc"
+ 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
+ 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="cc"
+ id="path17419"
+ d="m 329.49999,-67.5 1,0"
+ style="opacity:0.4;fill:#d4aa00;fill-opacity:1;fill-rule:evenodd;stroke:#8c5b27;stroke-width:1.00000107px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ 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"
+ sodipodi:nodetypes="ccc"
+ id="path17421"
+ d="m 326.49995,-59.500011 0,-1 -1,0"
+ style="opacity:0.4;fill:#d4aa00;fill-opacity:1;fill-rule:evenodd;stroke:#8c5b27;stroke-width:1.00000036px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.27999998;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 326,-60.5 3,-1.870665"
+ id="path17423"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path17425"
+ d="m 329.5,-67.5 0,4"
+ style="opacity:0.25;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="-63"
+ x="329.06403"
+ height="2"
+ width="2"
+ id="rect17427"
+ style="fill:#fff1d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+ <g
+ id="g24997"
+ transform="translate(0,128)">
+ <rect
+ ry="0"
+ rx="0"
+ y="302"
+ x="47"
+ height="16"
+ width="16"
+ id="rect17065"
+ 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="g24983">
+ <rect
+ rx="1.4999387"
+ ry="1.4999387"
+ y="313.5"
+ x="49.5"
+ height="3"
+ width="2.9998772"
+ id="rect17067"
+ 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="rect17069"
+ width="2.9998772"
+ height="3"
+ x="52.500122"
+ y="303.5"
+ ry="1.4999387"
+ rx="1.4999387" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="csc"
+ id="path17071"
+ d="m 51,315 c 4.5365,0 8.5,-3 8.5,-6 0,-1.75 -1.25,-4 -5.5,-4"
+ style="fill:none;stroke:#2b1600;stroke-width:3.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"
+ inkscape:connector-curvature="0" />
+ <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 51,315 c 4.49647,0 8.5,-3 8.5,-6 0,-1.75 -1.25,-4 -5.5,-4"
+ id="path17073"
+ sodipodi:nodetypes="csc"
+ 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"
+ 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\jendrzych's iconset.png"
+ sodipodi:nodetypes="csc"
+ id="path17075"
+ d="m 51,315 c 4.49647,0 8.5,-3 8.5,-6 0,-1.75 -1.25,-4 -5.5,-4"
+ style="fill:none;stroke:url(#linearGradient24436);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"
+ 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="path17077"
+ d="m 51.999878,314 c -0.67541,0 -1.35081,10e-6 -2.02623,10e-6 0,0.66939 0,1.33877 0,2.00817 0.67542,0 1.35082,-10e-6 2.02623,-10e-6 0,-0.66939 0,-1.33878 0,-2.00817 z"
+ style="fill:#ffca91;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="fill:#ffad55;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 55,304 c -0.65334,0 -1.30668,10e-6 -1.96003,10e-6 0,0.66667 0,1.33332 0,1.99999 0.65335,0 1.30669,-10e-6 1.96003,-10e-6 0,-0.66666 0,-1.33332 0,-1.99999 z"
+ id="path17081"
+ 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.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 53.5,305.5 0,-1 1,0"
+ id="path17083"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path17085"
+ d="m 50.473648,315.5 0,-1 1,0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ 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="path17087"
+ d="m 53,315.66293 c -0.32001,0 -0.64002,-1e-5 -0.96003,-1e-5 0,-0.55431 0,-1.1086 0,-1.66292 0.32001,0 0.64002,10e-6 0.96003,10e-6 0,0.55431 0,1.10861 0,1.66292 z"
+ style="opacity:0.25;fill:#783e00;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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="path17089"
+ d="m 56,306.51208 c -0.32001,0 -0.64002,-1e-5 -0.96003,-1e-5 0,-0.63982 0,-1.27964 0,-1.91948 0.32001,0 0.64002,1e-5 0.96003,1e-5 0,0.63983 0,1.27966 0,1.91948 z"
+ style="opacity:0.15;fill:#783e00;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.5;fill:#783e00;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 53,316 c -0.32001,0 -0.64002,0 -0.96003,0 0,-0.21055 0,-0.42107 0,-0.63162 0.32001,0 0.64002,0 0.96003,0 0,0.21055 0,0.42107 0,0.63162 z"
+ id="path17091"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g10687"
+ 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"
+ id="rect17348"
+ width="16"
+ height="16"
+ x="47"
+ y="281"
+ rx="0"
+ ry="0" />
+ <g
+ id="g10677">
+ <g
+ id="g18285"
+ style="opacity:0.7;display:inline"
+ transform="translate(-290.00001,409.99343)">
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="csc"
+ id="path18233"
+ d="m 341.00001,-115.99343 c 4.5365,0 8.49999,-2.75 8.49999,-5.75 0,-1.75 -1.25,-4 -5.5,-4"
+ style="fill:none;stroke:#1a1a1a;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#cccccc;stroke-width:1.5;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 341.00001,-115.99343 c 4.49647,0 8.49999,-2.75 8.49999,-5.75 0,-1.75 -1.25,-4 -5.5,-4"
+ id="path18235"
+ sodipodi:nodetypes="csc"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline"
+ id="g17345"
+ transform="translate(-189.02763,408)">
+ <rect
+ rx="1.4999387"
+ ry="1.4999387"
+ y="-115.5"
+ x="238.52776"
+ height="3"
+ width="2.9998772"
+ id="rect17355"
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path17358"
+ d="m 241.02763,-115 c -0.66667,0 -1.33332,1e-5 -2,1e-5 0,0.66939 0,1.33877 0,2.00817 0.66668,0 1.33333,-10e-6 2,-10e-6 0,-0.66939 0,-1.33878 0,-2.00817 z"
+ style="fill:#ffffff;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" />
+ <rect
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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="rect17360"
+ width="2.9998772"
+ height="3"
+ x="241.52776"
+ y="-125.5"
+ ry="1.4999387"
+ rx="1.4999387" />
+ <path
+ style="fill:#ffffff;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 244.02763,-125 c -0.65334,0 -1.30668,1e-5 -1.96003,1e-5 0,0.66667 0,1.33332 0,1.99999 0.65335,0 1.30669,-1e-5 1.96003,-1e-5 0,-0.66666 0,-1.33332 0,-1.99999 z"
+ id="path17362"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g21376"
+ 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="rect21362"
+ width="16"
+ height="16"
+ x="131"
+ y="71" />
+ <g
+ transform="translate(-71,-61)"
+ id="g9875"
+ style="display:inline">
+ <g
+ id="g9889"
+ transform="translate(0,1.00001)">
+ <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="path9891"
+ d="m 210,135.5 6.5,0 0,11 -9,0 0,-8.5 2.5,-2.5 z"
+ style="fill:url(#linearGradient21370);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient21372);stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(1.2999758,0,0,1.2999988,271.54887,-199.56022)"
+ sodipodi:nodetypes="ccc"
+ id="path9893"
+ style="opacity:0.7;fill:none;stroke:#000000;stroke-width:0.76923829px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1;display:inline;filter:url(#filter31351)"
+ d="M -48.500031,260.50809 -46.5,260.5 l -3.1e-5,-1.99191"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path9895"
+ d="m 207,138.99999 4,0 0,-4 -4,4 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ 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 207.5,138 0,8.5 9,0 0,-11 -6.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="path9897"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path9899"
+ style="fill:none;stroke:url(#linearGradient21374);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 208.5,139.49999 0,6.00001 m 3,-9.00001 4,0"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g9877"
+ transform="translate(-4,-3)"
+ style="opacity:0.4">
+ <path
+ style="fill:url(#linearGradient21364);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient21366);stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;display:inline"
+ d="m 210,135.5 6.5,0 0,11 -9,0 0,-8.5 2.5,-2.5 z"
+ id="path9879"
+ 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
+ d="M -48.500031,260.50809 -46.5,260.5 l -3.1e-5,-1.99191"
+ style="opacity:0.7;fill:none;stroke:#000000;stroke-width:0.76923829px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1;display:inline;filter:url(#filter31351)"
+ id="path9881"
+ sodipodi:nodetypes="ccc"
+ transform="matrix(1.2999758,0,0,1.2999988,271.54887,-199.56022)"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 207,138.99999 4,0 0,-4 -4,4 z"
+ id="path9883"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path9885"
+ 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 207.5,138 0,8.5 9,0 0,-11 -6.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"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 208.5,139.49999 0,6.00001 m 3,-9.00001 4,0"
+ style="fill:none;stroke:url(#linearGradient21368);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ id="path9887"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g10203"
+ transform="translate(-211.20006,170)" />
+ <g
+ id="g21567"
+ transform="translate(-0.9687515,1.9789998)">
+ <g
+ transform="matrix(1.0019536,0,0,1,-173.76637,169.95095)"
+ id="g10199"
+ style="stroke:none">
+ <rect
+ y="6.0700502"
+ x="325.10001"
+ height="15.979"
+ width="16.000004"
+ id="rect10201"
+ style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ </g>
+ <g
+ id="g21550">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path10205"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.38667691;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:type="arc"
+ transform="matrix(0.5769158,0,0,0.5769218,86.73182,118.78861)" />
+ <g
+ 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"
+ transform="matrix(0.769221,0,0,0.769229,59.2704,9.1909)"
+ id="g10207"
+ style="display:inline">
+ <path
+ transform="matrix(0.75,0,0,0.75,29.5,135)"
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.38667703;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path10209"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(-0.683022,-0.07745026,0.0778507,-0.683064,209.4726,314.325)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path10211"
+ style="opacity:0.4;fill:url(#linearGradient21641);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:type="arc" />
+ </g>
+ <g
+ 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="g10213"
+ transform="translate(-215.99994,222.97281)"
+ style="display:inline">
+ <rect
+ style="opacity:0.1;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;display:inline"
+ id="rect10215"
+ width="3.0000761"
+ height="2.9999874"
+ x="372.49994"
+ y="-43.495766"
+ transform="matrix(1,5.251142e-6,0,1,0,0)" />
+ <rect
+ transform="matrix(1,-5.25127e-6,0,-1,0,0)"
+ y="40.991806"
+ x="372.99994"
+ height="2.0000756"
+ width="2.0000861"
+ id="rect10217"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" />
+ <rect
+ style="fill:#d5e5ff;fill-opacity:1;fill-rule:nonzero;stroke:#0055d4;stroke-width:0.99999875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;display:inline"
+ id="rect10219"
+ width="3.0000761"
+ height="2.9999874"
+ x="372.49994"
+ y="-43.49577"
+ transform="matrix(1,5.251142e-6,0,1,0,0)" />
+ </g>
+ <g
+ style="display:inline"
+ id="g10221"
+ transform="matrix(0.769221,0,0,0.769229,64.0398,14.9217)"
+ 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: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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path10224"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.91227174;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.7125226,0,0,0.7125021,34.447023,139.42475)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.4;fill:url(#linearGradient21643);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path10226"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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)" />
+ </g>
+ <g
+ 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="display:inline"
+ transform="translate(-211.00001,228.97281)"
+ id="g10228">
+ <rect
+ transform="matrix(1,5.251142e-6,0,1,0,0)"
+ y="-43.495766"
+ x="372.49994"
+ height="2.9999874"
+ width="3.0000761"
+ id="rect10230"
+ style="opacity:0.1;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;display:inline" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="rect10232"
+ width="2.0000861"
+ height="2.0000756"
+ x="372.99994"
+ y="40.991806"
+ transform="matrix(1,-5.25127e-6,0,-1,0,0)" />
+ <rect
+ transform="matrix(1,5.251142e-6,0,1,0,0)"
+ y="-43.49577"
+ x="372.49994"
+ height="2.9999874"
+ width="3.0000761"
+ id="rect10234"
+ style="fill:#d5e5ff;fill-opacity:1;fill-rule:nonzero;stroke:#0055d4;stroke-width:0.99999875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;display:inline" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g21647"
+ 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"
+ id="rect21645"
+ width="16"
+ height="16"
+ x="173"
+ y="176" />
+ <g
+ transform="translate(-209.00002,169.98079)"
+ id="g10236"
+ 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
+ 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"
+ transform="matrix(0.769221,0,0,0.769229,289.2704,-160.7881)"
+ id="g10238"
+ style="display:inline">
+ <path
+ transform="matrix(0.75,0,0,0.75,29.5,135)"
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.38667703;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path10240"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(-0.683022,-0.07745026,0.0778507,-0.683064,209.4726,314.325)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path10242"
+ style="opacity:0.4;fill:url(#linearGradient15590);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:type="arc" />
+ </g>
+ <g
+ style="display:inline"
+ id="g10244"
+ transform="matrix(0.769221,0,0,0.769229,294.0398,-155.0573)"
+ 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: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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path10246"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.38667703;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.75,0,0,0.75,29.5,135)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.4;fill:url(#linearGradient15592);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path10248"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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)" />
+ </g>
+ <g
+ 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="g10250"
+ transform="translate(16.000061,55.993807)"
+ style="display:inline">
+ <rect
+ style="opacity:0.25;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;display:inline"
+ id="rect10252"
+ width="3.0000761"
+ height="2.9999874"
+ x="372.49994"
+ y="-43.495766"
+ transform="matrix(1,5.251142e-6,0,1,0,0)" />
+ <rect
+ transform="matrix(1,-5.25127e-6,0,-1,0,0)"
+ y="40.991806"
+ x="372.99994"
+ height="2.0000756"
+ width="2.0000861"
+ id="rect10254"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" />
+ <rect
+ style="fill:#d5e5ff;fill-opacity:1;fill-rule:nonzero;stroke:#0055d4;stroke-width:0.99999875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;display:inline"
+ id="rect10256"
+ width="3.0000761"
+ height="2.9999874"
+ x="372.49994"
+ y="-43.49577"
+ transform="matrix(1,5.251142e-6,0,1,0,0)" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g21623"
+ transform="translate(-0.9999786,1.9982099)">
+ <g
+ transform="matrix(0.9999986,0,0,1,-170.19957,169.98079)"
+ id="g10260">
+ <g
+ transform="translate(39.10005,-0.04905017)"
+ id="g10262">
+ <rect
+ y="6.0700502"
+ x="325.10001"
+ height="15.979"
+ width="16.000025"
+ id="rect10264"
+ style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ </g>
+ <g
+ id="g10266" />
+ </g>
+ <g
+ id="g21602">
+ <path
+ transform="matrix(0.5769158,0,0,0.5769218,128.71244,118.78864)"
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.38667691;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="path10268"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ style="opacity:0.45;display:inline"
+ id="g10270"
+ transform="matrix(0.769221,0,0,0.769229,101.2704,9.19269)"
+ 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">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path10272"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.38667703;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.75,0,0,0.75,29.5,135)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.4;fill:url(#linearGradient15594);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path10275"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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)" />
+ </g>
+ <g
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ transform="matrix(0.769221,0,0,0.769229,106.0398,14.92349)"
+ id="g10277"
+ style="display:inline">
+ <path
+ transform="matrix(0.7119136,0,0,0.7119136,34.527408,139.4942)"
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.91303903;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="path10279"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(-0.683022,-0.07745026,0.0778507,-0.683064,209.4726,314.28576)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path10281"
+ style="opacity:0.4;fill:url(#linearGradient15596);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:type="arc" />
+ </g>
+ <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"
+ transform="matrix(1,5.251142e-6,0,1,0,0)"
+ y="179.47975"
+ x="198.49991"
+ height="2.9999874"
+ width="3.0000761"
+ id="rect10283"
+ style="opacity:0.05;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#6a6a6a;stroke-width:0.99999875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;display:inline" />
+ <rect
+ style="opacity:0.1;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;display:inline"
+ id="rect10285"
+ width="3.0000761"
+ height="2.9999874"
+ x="203.49991"
+ y="185.47972"
+ transform="matrix(1,5.251142e-6,0,1,0,0)" />
+ <rect
+ transform="matrix(1,-5.25127e-6,0,-1,0,0)"
+ y="-187.9819"
+ x="203.99991"
+ height="2.0000756"
+ width="2.0000861"
+ id="rect10287"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" />
+ <rect
+ style="fill:#d5e5ff;fill-opacity:1;fill-rule:nonzero;stroke:#0055d4;stroke-width:0.99999875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;display:inline"
+ id="rect10289"
+ width="3.0000761"
+ height="2.9999874"
+ x="203.49991"
+ y="185.47972"
+ transform="matrix(1,5.251142e-6,0,1,0,0)" />
+ </g>
+ </g>
+ <g
+ id="g21519"
+ transform="translate(0,2)">
+ <rect
+ style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="rect10293"
+ width="16"
+ height="16"
+ x="131"
+ y="176" />
+ <g
+ transform="translate(0.8812553,-0.8570429)"
+ id="g21511">
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ d="m 142.1,184.4 2.5,0 m -9.5,0 -2.5,0 m 6,-3.5 0,-2.5 m 0,9.5 0,2.5"
+ style="fill:none;stroke:#000000;stroke-width:3.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path10295"
+ 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"
+ d="m 141.08637,118 a 9.0863705,9.0860729 0 1 1 -18.17274,0 9.0863705,9.0860729 0 1 1 18.17274,0 z"
+ sodipodi:ry="9.0860729"
+ sodipodi:rx="9.0863705"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path10297"
+ style="fill:none;stroke:#000000;stroke-width:8.3510685;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.383132,0,0,0.383237,88.0266,139.17807)" />
+ <path
+ id="path10299"
+ style="fill:none;stroke:url(#radialGradient21517);stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 142.1,184.4 2.5,0 m -9.5,0 -2.5,0 m 6,-3.5 0,-2.5 m 0,9.5 0,2.5"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(0.383132,0,0,0.383237,88.0266,139.17807)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:#ffffff;stroke-width:4.69747591;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path10301"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="9.0863705"
+ sodipodi:ry="9.0860729"
+ d="m 141.08637,118 a 9.0863705,9.0860729 0 1 1 -18.17274,0 9.0863705,9.0860729 0 1 1 18.17274,0 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"
+ 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="rect22465"
+ width="16"
+ height="16"
+ x="425"
+ y="113" />
+ <g
+ id="g14791"
+ transform="translate(-38,43.987183)"
+ style="display:inline">
+ <rect
+ style="fill:#f09432;fill-opacity:1;fill-rule:nonzero;stroke:#462400;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:6.18177886;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect14793"
+ width="4.0018005"
+ height="3.9871812"
+ x="468.5"
+ y="74.512817"
+ rx="1.4768832"
+ ry="1.4768832" />
+ <rect
+ y="75.5"
+ x="469.5018"
+ height="2.012816"
+ width="1.9981995"
+ id="rect14795"
+ style="fill:none;stroke:url(#linearGradient14841);stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:6.18177886;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ ry="0.49075836"
+ rx="0.49075836" />
+ </g>
+ </g>
+ <g
+ id="g11718"
+ transform="translate(0,2)">
+ <rect
+ y="113"
+ x="404"
+ height="16"
+ width="16"
+ id="rect22463"
+ 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="g14927"
+ transform="translate(-39,43.987183)"
+ style="opacity:0.9;display:inline">
+ <rect
+ ry="1.5045315"
+ rx="1.5045315"
+ y="74.512817"
+ x="448.5"
+ height="3.9871812"
+ width="4.0018005"
+ id="rect14929"
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:6.18177886;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:none;stroke:url(#linearGradient14935);stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:6.18177886;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect14931"
+ width="1.9981995"
+ height="2.012816"
+ x="449.5018"
+ y="75.5"
+ rx="0.5299269"
+ ry="0.5299269" />
+ </g>
+ </g>
+ <g
+ id="g11764"
+ transform="translate(0,2)">
+ <rect
+ y="113"
+ x="341"
+ height="16"
+ width="16"
+ id="rect22331"
+ 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(-81,-103)"
+ id="g22313"
+ style="display:inline">
+ <g
+ id="g22243">
+ <g
+ transform="translate(-0.9546587,1e-5)"
+ id="g18888"
+ style="opacity:0.85">
+ <path
+ sodipodi:nodetypes="cssc"
+ d="m 430.45466,223.24999 c -2.76033,0 -5,1.88345 -5,3.25 0,1.5 2.5,3 5.5,3 0.15891,0 4,0.25 6,-2.5"
+ style="fill:none;stroke:url(#linearGradient18896);stroke-width:3.29999995;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="path18757"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path18762"
+ style="fill:none;stroke:url(#linearGradient18898);stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;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 434.20466,226.49999 3.25115,2e-5 -10e-4,2.99998"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ d="m 433.25,226.5 3.25,0 0,2.99999"
+ style="fill:none;stroke:url(#linearGradient18904);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;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="path18764"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path18766"
+ style="fill:none;stroke:url(#linearGradient18901);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;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 429.5,223.25 c -2.76033,0 -5,1.88345 -5,3.25 0,1.5 2.5,3 5.5,3 0,0 4,0.25 6,-2.5"
+ sodipodi:nodetypes="cssc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(278.02661,459.99999)"
+ id="g18768">
+ <path
+ id="path18770"
+ d="m 151,-240.5 c -2.48519,0 -4.49999,0.89481 -4.5,2 l 0,1 c 0,1.10519 2.0148,2 4.5,2 2.48519,0 4.5,-0.8948 4.5,-2 l 0,-1 c 0,-1.10519 -2.01481,-2 -4.5,-2 z"
+ style="fill:url(#linearGradient18843);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.68242937;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient18845);fill-opacity:1;fill-rule:nonzero;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 151.00029,-243.51106 c -1.9309,0 -3.5,0.66961 -3.5,1.5 L 147.5,-240 c 0,0.83039 1.5691,1.5 3.5,1.5 1.9309,0 3.5,-0.66961 3.5,-1.5 l 2.9e-4,-2.01106 c 0,-0.83039 -1.5691,-1.5 -3.5,-1.5 z"
+ id="path18779"
+ sodipodi:nodetypes="cccsccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient18848);stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 148.5,-241.75 0,2.70352 c 0.0622,0.056 0.19266,0.12733 0.40625,0.21875 0.46667,0.19974 1.2423,0.32773 2.09375,0.32773 0.85145,0 1.62708,-0.12799 2.09375,-0.32773 0.21359,-0.0914 0.34401,-0.16271 0.40625,-0.21875 l 0,-2.70352"
+ id="path18787"
+ sodipodi:nodetypes="ccssscc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient18850);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.73959124;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path18789"
+ sodipodi:cx="108"
+ sodipodi:cy="-222"
+ sodipodi:rx="3.3084693"
+ sodipodi:ry="1.2798798"
+ d="m 111.30847,-222 a 3.3084693,1.2798798 0 1 1 -6.61694,0 3.3084693,1.2798798 0 1 1 6.61694,0 z"
+ transform="matrix(1.0307577,0,0,0.9140456,39.651558,-39.251735)" />
+ <path
+ sodipodi:nodetypes="cssss"
+ id="path18791"
+ d="m 154.5,-239 c 0,0.18405 -0.0775,0.36038 -0.21919,0.52335 -0.49587,0.57019 -1.77826,0.97665 -3.28081,0.97665 -1.48659,0 -2.75767,-0.39787 -3.26474,-0.95854 C 147.58334,-238.62651 147.5,-238.80911 147.5,-239"
+ style="fill:none;stroke:url(#linearGradient18852);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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path18798"
+ d="m 151,-243.5 c -1.9309,1e-5 -3.52661,0.41962 -3.52661,1.25001 L 147.5,-239.75 c -0.61542,0.34205 -1,0.77768 -1,1.25 l -0.0266,1.25001 c 0,1.10519 2.04141,1.74999 4.52661,1.74999 2.48519,0 4.47339,-0.64479 4.47339,-1.74999 L 155.5,-238.5 c 0,-0.47232 -0.38458,-0.90795 -1,-1.25 l -0.0266,-2.49999 c 0,-0.83038 -1.54249,-1.25001 -3.47339,-1.25001 l -1e-5,0 z"
+ style="fill:none;stroke:#000000;stroke-width:0.60000002;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="cccccsccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="csssc"
+ id="path18800"
+ d="m 148.5,-239.04648 c 0.0622,0.056 0.19266,0.12733 0.40625,0.21875 0.46667,0.19974 1.2423,0.32773 2.09375,0.32773 0.85145,0 1.62708,-0.12799 2.09375,-0.32773 0.21359,-0.0914 0.34401,-0.16271 0.40625,-0.21875"
+ style="fill:none;stroke:#0066ff;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g11730"
+ transform="translate(0,2)">
+ <rect
+ y="113"
+ x="383"
+ height="16"
+ width="16"
+ id="rect22455"
+ 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(-79,-103)"
+ id="g22283"
+ style="display:inline">
+ <g
+ transform="translate(318.02661,459.99999)"
+ id="g17510">
+ <path
+ id="path17512"
+ d="m 151,-240.5 c -2.48519,0 -4.49999,0.89481 -4.5,2 l 0,1 c 0,1.10519 2.0148,2 4.5,2 2.48519,0 4.5,-0.8948 4.5,-2 l 0,-1 c 0,-1.10519 -2.01481,-2 -4.5,-2 z"
+ style="fill:url(#linearGradient17527);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.68242937;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient17529);fill-opacity:1;fill-rule:nonzero;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 151.00029,-243.51106 c -1.9309,0 -3.5,0.66961 -3.5,1.5 L 147.5,-240 c 0,0.83039 1.5691,1.5 3.5,1.5 1.9309,0 3.5,-0.66961 3.5,-1.5 l 2.9e-4,-2.01106 c 0,-0.83039 -1.5691,-1.5 -3.5,-1.5 z"
+ id="path17514"
+ sodipodi:nodetypes="cccsccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient17531);stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 148.5,-241.75 0,2.70352 c 0.0622,0.056 0.19266,0.12733 0.40625,0.21875 0.46667,0.19974 1.2423,0.32773 2.09375,0.32773 0.85145,0 1.62708,-0.12799 2.09375,-0.32773 0.21359,-0.0914 0.34401,-0.16271 0.40625,-0.21875 l 0,-2.70352"
+ id="path17516"
+ sodipodi:nodetypes="ccssscc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient17533);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.73959124;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path17518"
+ sodipodi:cx="108"
+ sodipodi:cy="-222"
+ sodipodi:rx="3.3084693"
+ sodipodi:ry="1.2798798"
+ d="m 111.30847,-222 a 3.3084693,1.2798798 0 1 1 -6.61694,0 3.3084693,1.2798798 0 1 1 6.61694,0 z"
+ transform="matrix(1.0307577,0,0,0.9140456,39.651558,-39.251735)" />
+ <path
+ sodipodi:nodetypes="cssss"
+ id="path17520"
+ d="m 154.5,-239 c 0,0.18405 -0.0775,0.36038 -0.21919,0.52335 -0.49587,0.57019 -1.77826,0.97665 -3.28081,0.97665 -1.48659,0 -2.75767,-0.39787 -3.26474,-0.95854 C 147.58334,-238.62651 147.5,-238.80911 147.5,-239"
+ style="fill:none;stroke:url(#linearGradient17535);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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path17522"
+ d="m 151,-243.5 c -1.9309,1e-5 -3.52661,0.41962 -3.52661,1.25001 L 147.5,-239.75 c -0.61542,0.34205 -1,0.77768 -1,1.25 l -0.0266,1.25001 c 0,1.10519 2.04141,1.74999 4.52661,1.74999 2.48519,0 4.47339,-0.64479 4.47339,-1.74999 L 155.5,-238.5 c 0,-0.47232 -0.38458,-0.90795 -1,-1.25 l -0.0266,-2.49999 c 0,-0.83038 -1.54249,-1.25001 -3.47339,-1.25001 l -1e-5,0 z"
+ style="fill:none;stroke:#000000;stroke-width:0.60000002;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="cccccsccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="csssc"
+ id="path17524"
+ d="m 148.5,-239.04648 c 0.0622,0.056 0.19266,0.12733 0.40625,0.21875 0.46667,0.19974 1.2423,0.32773 2.09375,0.32773 0.85145,0 1.62708,-0.12799 2.09375,-0.32773 0.21359,-0.0914 0.34401,-0.16271 0.40625,-0.21875"
+ style="fill:none;stroke:#0066ff;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g22254">
+ <g
+ transform="translate(20.029029,0)"
+ style="opacity:0.85"
+ id="g17822">
+ <path
+ d="m 446.75,226.25 -2.25,2.25 2.25,2.25 m 7.5,-4.5 2.25,2.25 -2.25,2.25"
+ style="fill:none;stroke:url(#linearGradient17817);stroke-width:2.5999999;stroke-linecap:round;stroke-linejoin:miter;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="path17811"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path17809"
+ d="m 444.54256,228.5 11.66489,0 0,0"
+ style="fill:none;stroke:url(#linearGradient17819);stroke-width:2.5;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" />
+ </g>
+ <g
+ transform="translate(20.029029,0)"
+ id="g17801">
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 444.54256,228.5 11.95744,0"
+ id="path17024"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path17796"
+ style="fill:none;stroke:#ffffff;stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 446.75,226.25 -2.25,2.25 2.25,2.25 m 7.5,-4.5 2.25,2.25 -2.25,2.25"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ id="g11749"
+ 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="rect22453"
+ width="16"
+ height="16"
+ x="362"
+ y="113" />
+ <g
+ transform="translate(-81,-103)"
+ id="g22300"
+ style="display:inline">
+ <g
+ id="g17482"
+ transform="translate(298.02661,466.04648)">
+ <path
+ style="fill:url(#linearGradient17498);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.68242937;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 151,-240.5 c -2.48519,0 -4.49999,0.89481 -4.5,2 l 0,1 c 0,1.10519 2.0148,2 4.5,2 2.48519,0 4.5,-0.8948 4.5,-2 l 0,-1 c 0,-1.10519 -2.01481,-2 -4.5,-2 z"
+ id="path17484"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccsccc"
+ id="path17486"
+ d="m 151.00029,-243.51106 c -1.9309,0 -3.5,0.66961 -3.5,1.5 L 147.5,-240 c 0,0.83039 1.5691,1.5 3.5,1.5 1.9309,0 3.5,-0.66961 3.5,-1.5 l 2.9e-4,-2.01106 c 0,-0.83039 -1.5691,-1.5 -3.5,-1.5 z"
+ style="fill:url(#linearGradient17500);fill-opacity:1;fill-rule:nonzero;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccssscc"
+ id="path17488"
+ d="m 148.5,-241.75 0,2.70352 c 0.0622,0.056 0.19266,0.12733 0.40625,0.21875 0.46667,0.19974 1.2423,0.32773 2.09375,0.32773 0.85145,0 1.62708,-0.12799 2.09375,-0.32773 0.21359,-0.0914 0.34401,-0.16271 0.40625,-0.21875 l 0,-2.70352"
+ style="fill:none;stroke:url(#linearGradient17502);stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(1.0307577,0,0,0.9140456,39.651558,-39.251735)"
+ d="m 111.30847,-222 a 3.3084693,1.2798798 0 1 1 -6.61694,0 3.3084693,1.2798798 0 1 1 6.61694,0 z"
+ sodipodi:ry="1.2798798"
+ sodipodi:rx="3.3084693"
+ sodipodi:cy="-222"
+ sodipodi:cx="108"
+ id="path17490"
+ style="fill:url(#linearGradient17504);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.73959124;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ style="fill:none;stroke:url(#linearGradient17506);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"
+ d="m 154.5,-239 c 0,0.18405 -0.0775,0.36038 -0.21919,0.52335 -0.49587,0.57019 -1.77826,0.97665 -3.28081,0.97665 -1.48659,0 -2.75767,-0.39787 -3.26474,-0.95854 C 147.58334,-238.62651 147.5,-238.80911 147.5,-239"
+ id="path17492"
+ sodipodi:nodetypes="cssss"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccsccccc"
+ style="fill:none;stroke:#000000;stroke-width:0.60000002;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 151,-243.5 c -1.9309,1e-5 -3.52661,0.41962 -3.52661,1.25001 L 147.5,-239.75 c -0.61542,0.34205 -1,0.77768 -1,1.25 l -0.0266,1.25001 c 0,1.10519 2.04141,1.74999 4.52661,1.74999 2.48519,0 4.47339,-0.64479 4.47339,-1.74999 L 155.5,-238.5 c 0,-0.47232 -0.38458,-0.90795 -1,-1.25 l -0.0266,-2.49999 c 0,-0.83038 -1.54249,-1.25001 -3.47339,-1.25001 l -1e-5,0 z"
+ id="path17494"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 148.5,-239.04648 c 0.0622,0.056 0.19266,0.12733 0.40625,0.21875 0.46667,0.19974 1.2423,0.32773 2.09375,0.32773 0.85145,0 1.62708,-0.12799 2.09375,-0.32773 0.21359,-0.0914 0.34401,-0.16271 0.40625,-0.21875"
+ id="path17496"
+ sodipodi:nodetypes="csssc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g22250">
+ <path
+ style="opacity:0.85;fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 456.5,218.5 c -1.25,-1.5 -3.5,-1.5 -5,1 -1.5,-2.5 -3.75,-2.5 -5,-1"
+ id="path17828"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path17826"
+ d="m 456.5,218.5 c -1.25,-1.5 -3.5,-1.5 -5,1 -1.5,-2.5 -3.75,-2.5 -5,-1"
+ style="fill:url(#linearGradient18213);fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g23801"
+ 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="rect22457"
+ width="16"
+ height="16"
+ x="320"
+ y="113" />
+ <g
+ mask="url(#mask18666)"
+ style="display:inline"
+ 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="g18026"
+ transform="matrix(0.927273,0,0,1,260.65455,106)">
+ <path
+ sodipodi:nodetypes="cccccc"
+ d="m 70.499967,14.5 4.284298,2.5 m -4.284298,-2.5 -4.34315,2.5 m 4.313724,-2.5 0,-4.5"
+ style="fill:none;stroke:#000000;stroke-width:3.42696857;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path18028"
+ 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
+ id="path18030"
+ d="m 69.39211,8 0,2 2.156862,0 0,-2 -2.156862,0 z m -4.313742,8 1.8e-5,2 2.156862,0 -1.8e-5,-2 -2.156862,0 z m 8.627466,0 0,2 2.156862,0 0,-2 -2.156862,0 z"
+ style="fill:#acc373;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.55771327;stroke-linecap:square;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"
+ sodipodi:nodetypes="ccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#radialGradient23738);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path18032"
+ sodipodi:cx="70.5"
+ sodipodi:cy="14.5"
+ sodipodi:rx="1.5"
+ sodipodi:ry="1.5"
+ d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 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"
+ inkscape:export-ydpi="90" />
+ <path
+ id="path18035"
+ style="fill:none;stroke:#91ae42;stroke-width:2.07695079;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ d="M 70.470541,14.5 74.784265,17"
+ sodipodi:nodetypes="cc"
+ 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:#91ae42;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 73.705834,16 0,2 2.156862,0 0,-2 -2.156862,0 z"
+ id="path18037"
+ sodipodi:nodetypes="ccccc"
+ 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
+ id="path18039"
+ d="m 69.39211,8 0,2 2.156862,0 0,-2 -2.156862,0 z"
+ style="fill:#4989e9;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:nodetypes="ccccc"
+ 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
+ id="path18041"
+ d="m 65.078405,16 0,2 2.156844,0 0,-2 -2.156844,0 z"
+ style="fill:#ef6529;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:nodetypes="ccccc"
+ 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
+ d="M 70.470541,14.5 66.156817,17"
+ style="fill:none;stroke:#ef6529;stroke-width:2.07695079;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path18043"
+ sodipodi:nodetypes="cc"
+ 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
+ d="m 70.470541,14.5 0,-4.5"
+ style="fill:none;stroke:#4989e9;stroke-width:2.07695079;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path18045"
+ sodipodi:nodetypes="cc"
+ 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
+ transform="matrix(0.699335,0,0,0.602252,21.19685,5.767346)"
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path18047"
+ sodipodi:cx="70.5"
+ sodipodi:cy="14.5"
+ sodipodi:rx="1.5"
+ sodipodi:ry="1.5"
+ d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 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
+ style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:1.03847623px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ d="m 65.617602,17.5 0,-1 1.078431,0"
+ id="path18049"
+ sodipodi:nodetypes="ccc"
+ 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="ccc"
+ id="path18051"
+ d="m 69.93132,9.5 0,-0.9673924 1.078413,0"
+ style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:1.03847599px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ 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.5;fill:none;stroke:#ffffff;stroke-width:1.03847647px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ d="m 74.24505,17.500004 0,-1 1.078431,0"
+ id="path18053"
+ sodipodi:nodetypes="ccc"
+ 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" />
+ </g>
+ <g
+ transform="translate(-162,-102)"
+ id="g18124">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.70588235;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 495.5,226 c 0,0 0,-1.75 0,-1.75 0,-0.96333 -0.75,-1.75 -2,-1.75 -1.25,0 -2,0.78667 -2,1.75 l 0,1.75"
+ id="path18055"
+ sodipodi:nodetypes="csccc"
+ 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
+ y="225.48849"
+ x="489.5"
+ height="5.0114956"
+ width="7.9999995"
+ id="rect18057"
+ style="fill:url(#linearGradient23750);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.70588235;stroke-dasharray:none;stroke-dashoffset:0;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="csccc"
+ id="path18059"
+ d="m 495.5,226 c 0,0 0,-1.75 0,-1.75 0,-0.96333 -0.75,-1.75 -2,-1.75 -1.25,0 -2,0.78667 -2,1.75 l 0,1.75"
+ style="fill:none;stroke:url(#linearGradient23752);stroke-width:1.39999998;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:none;stroke:url(#linearGradient23754);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="rect18061"
+ width="6.0312495"
+ height="3.0344827"
+ x="490.5"
+ y="226.5"
+ rx="0"
+ 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"
+ 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"
+ id="rect20632"
+ width="16"
+ height="16"
+ x="68"
+ y="428" />
+ <g
+ style="display:inline"
+ transform="translate(-15.161301,338)"
+ 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="g10762">
+ <path
+ d="m 86.5,100.53983 4.342131,0.008 c 5.188235,0.0101 5.335295,-2.04831 3.335293,-4.04831 -0.964875,-0.964875 -4.5,-4 1.500002,-5 M 88.840543,97.588774 86.5,100.53983 M 88.828993,103.5 86.5,100.53983"
+ 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:7.40000034;display:inline"
+ id="path10764"
+ sodipodi:nodetypes="czszcccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czszcccc"
+ id="path10766"
+ style="fill:none;stroke:url(#linearGradient13991);stroke-width:1.50000143;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000034;display:inline"
+ d="m 86.5,100.53983 4.342131,0.008 C 96.03037,100.55844 96.17743,98.5 94.177424,96.5 c -0.964875,-0.964875 -4.5,-4 1.500002,-5 M 88.840543,97.588774 86.5,100.53983 M 88.828993,103.5 86.5,100.53983"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g10534"
+ transform="translate(0,128.00001)">
+ <rect
+ y="428"
+ x="193.9839"
+ height="16"
+ width="16"
+ id="rect20642"
+ 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(-29.016109,339.00751)"
+ id="g20606">
+ <g
+ transform="translate(-199.98388,-106)"
+ id="g10953">
+ <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="cccccccccccccccccccccccccccccccccccccc"
+ style="fill:none;stroke:#000000;stroke-width:1.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 429.9998,196.99249 0,1.625 c -0.53409,0.12195 -1.02562,0.33162 -1.46875,0.625 l -1.53125,-1.25 -1,1 1.25,1.53125 c -0.29338,0.44313 -0.50305,0.93466 -0.625,1.46875 l -1.625,0 0,2 1.625,0 c 0.12195,0.53409 0.33162,1.02562 0.625,1.46875 l -1.25,1.53125 1,1 1.53125,-1.25 c 0.44313,0.29338 0.93466,0.50305 1.46875,0.625 l 0,1.625 2,0 0,-1.625 c 0.53409,-0.12195 1.02562,-0.33162 1.46875,-0.625 l 1.53125,1.25 1,-1 -1.25,-1.53125 c 0.29338,-0.44313 0.50305,-0.93466 0.625,-1.46875 l 1.625,0 0,-2 -1.625,0 c -0.12195,-0.53409 -0.33162,-1.02562 -0.625,-1.46875 l 1.25,-1.53125 -1,-1 -1.53125,1.25 c -0.44313,-0.29338 -0.93466,-0.50305 -1.46875,-0.625 l 0,-1.625 -2,0 z m -1,4 4,0 0,4 -4,0 0,-4 z"
+ id="path10955"
+ 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"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccc"
+ id="path10957"
+ d="m 429.9998,196.99249 0,1.625 c -0.53409,0.12195 -1.02562,0.33162 -1.46875,0.625 l -1.53125,-1.25 -1,1 1.25,1.53125 c -0.29338,0.44313 -0.50305,0.93466 -0.625,1.46875 l -1.625,0 0,2 1.625,0 c 0.12195,0.53409 0.33162,1.02562 0.625,1.46875 l -1.25,1.53125 1,1 1.53125,-1.25 c 0.44313,0.29338 0.93466,0.50305 1.46875,0.625 l 0,1.625 2,0 0,-1.625 c 0.53409,-0.12195 1.02562,-0.33162 1.46875,-0.625 l 1.53125,1.25 1,-1 -1.25,-1.53125 c 0.29338,-0.44313 0.50305,-0.93466 0.625,-1.46875 l 1.625,0 0,-2 -1.625,0 c -0.12195,-0.53409 -0.33162,-1.02562 -0.625,-1.46875 l 1.5,-1.78125 -1,-1 -1.78125,1.5 c -0.44313,-0.29338 -0.93466,-0.50305 -1.46875,-0.625 l 0,-1.625 -2,0 z m -1,4 4,0 0,4 -4,0 0,-4 z"
+ style="fill:url(#linearGradient20796);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 434.9998,198.49249 -1.5,1.25 m -2,-2.25 -1,0 0,1.5 c -0.35104,0.0802 -1.01806,0.29269 -1.5172,0.50569 m -1.49,1.50752 c -0.20864,0.49552 -0.41426,1.14284 -0.4928,1.48679 l -1.5,0 0,1 m 1.5,-5 -0.5,0.5 m 1.25,6.5 -1.25,1.5 m 6.5,-5.5 0,3.5 -3.5,0 m -3,-6 0.5,-0.5 1.5,1.25"
+ style="fill:none;stroke:#f9f9f9;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0"
+ id="path10959"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-199.98388,-106)"
+ id="g10961">
+ <rect
+ ry="0"
+ rx="0"
+ y="202.46629"
+ x="430.49979"
+ height="8.1236582"
+ width="7.0000763"
+ id="rect10963"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;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" />
+ <path
+ d="m 432.53795,204.5065 2.96201,0 m -2.96201,1.993 2.96201,0 m -2.96201,1.993 2.96201,0"
+ style="fill:none;stroke:#000000;stroke-width:0.99999988px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ id="path10965"
+ 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" />
+ <rect
+ ry="0"
+ rx="0"
+ y="202.48912"
+ x="430.49661"
+ height="8.0067444"
+ width="7.0067482"
+ id="rect10967"
+ style="fill:none;stroke:url(#linearGradient20798);stroke-width:0.99325603;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\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g10512"
+ 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"
+ id="rect20640"
+ width="16"
+ height="16"
+ x="173"
+ y="428" />
+ <g
+ transform="translate(-29.98389,338.00045)"
+ 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="g11077"
+ style="display:inline">
+ <g
+ id="g11079"
+ 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"
+ transform="matrix(0.965527,0,0,0.993394,8.273839,0.460629)">
+ <g
+ id="g11081"
+ transform="matrix(1.086383,0,0,1.082072,-19.43307,-7.852041)">
+ <g
+ 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"
+ transform="matrix(0.833341,0,0,0.829252,85.1747,-87.30584)"
+ id="g11083" />
+ <g
+ style="stroke:#000000;stroke-width:1.13287878;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="g11085"
+ transform="matrix(0.833341,0,0,0.829252,85.1747,-87.30584)"
+ 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
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path23208"
+ style="fill:#dad727;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.92361271;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"
+ 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.929498,0,0,0.910458,28.4835,116.0319)" />
+ <path
+ transform="matrix(0.8580178,0,0,0.8424365,37.918882,124.05843)"
+ 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:type="arc"
+ style="fill:url(#linearGradient23215);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.92361271;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path23213"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z" />
+ </g>
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 210.20333,98.981214 0,-1.914298 1.90698,0 0,1.914298 -1.90698,0 z"
+ id="path11089"
+ sodipodi:nodetypes="ccccc"
+ 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" />
+ <g
+ id="g11091">
+ <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="ccccc"
+ inkscape:transform-center-y="-3.3687892"
+ id="path11093"
+ d="m 208.05857,93.345302 2.18641,2.891627 c 0.50125,-0.147037 1.16637,-0.122617 1.82389,-0.02056 l 2.18648,-2.87107 c -1.9067,-1.162873 -4.29008,-1.162873 -6.19678,0 l 0,3e-6 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;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"
+ sodipodi:nodetypes="ccccc"
+ inkscape:transform-center-y="2.4548853"
+ id="path11095"
+ d="m 208.53524,102.88086 1.43003,-3.336509 c -0.67737,-0.380664 -0.53518,-1.067385 -0.59136,-1.547136 l -3.93706,-4.21e-4 c 0,2.093176 1.43003,4.186346 3.09839,4.884066 l 0,0 0,0 0,0 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ inkscape:transform-center-x="3.3187399"
+ 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"
+ inkscape:transform-center-x="-3.318739"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 213.77867,102.88086 -1.43002,-3.336509 c 0.67738,-0.380664 0.53486,-1.067385 0.59105,-1.547136 l 3.93736,-4.21e-4 c 0,2.325746 -1.43003,4.186346 -3.09839,4.884066 z"
+ id="path11097"
+ inkscape:transform-center-y="2.4548853"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <path
+ d="m 139.7074,118 a 7.7074003,7.7241406 0 1 1 -15.4148,0 7.7074003,7.7241406 0 1 1 15.4148,0 z"
+ sodipodi:ry="7.7241406"
+ sodipodi:rx="7.7074003"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path11099"
+ style="fill:none;stroke:url(#linearGradient13520);stroke-width:1.40287328;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:type="arc"
+ 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"
+ transform="matrix(0.713599,0,0,0.712048,116.8049,13.97832)" />
+ <g
+ 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"
+ transform="translate(-160.2001,83.979)"
+ id="g11101">
+ <g
+ transform="translate(39.10005,-0.04905017)"
+ id="g11103" />
+ <g
+ id="g11105" />
+ </g>
+ <g
+ id="g11107"
+ style="opacity:0.3;display:inline"
+ transform="matrix(1.0489321,0,0,1.0749238,-10.489315,-7.3395414)">
+ <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="ccccc"
+ inkscape:transform-center-y="-3.3687892"
+ id="path11109"
+ d="m 208.05857,93.345302 2.18641,2.891627 c 0.50125,-0.147037 1.16637,-0.122617 1.82389,-0.02056 l 2.18648,-2.87107 c -1.9067,-1.162873 -4.29008,-1.162873 -6.19678,0 l 0,3e-6 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;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"
+ sodipodi:nodetypes="ccccc"
+ inkscape:transform-center-y="2.4548853"
+ id="path11111"
+ d="m 208.53524,102.88086 1.43003,-3.336509 c -0.67737,-0.380664 -0.53518,-1.067385 -0.59136,-1.547136 l -3.93706,-4.21e-4 c 0,2.093176 1.43003,4.186346 3.09839,4.884066 l 0,0 0,0 0,0 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ inkscape:transform-center-x="3.3187399"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g21197"
+ 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"
+ id="rect21195"
+ width="16"
+ height="16"
+ x="363"
+ y="174" />
+ <g
+ transform="matrix(0.68898,0.688545,-0.68898,0.688545,503.65632,-65.53941)"
+ id="g11065"
+ style="display:inline">
+ <path
+ sodipodi:nodetypes="ccczcczccccscsccscscc"
+ id="path11067"
+ d="m 85.658035,278.19867 c 1.5,0 2.00279,1.00232 2.00279,2.00232 l 1.14e-4,0.36297 c 0,0.75 -0.916764,1.9289 -1.666764,1.9289 -0.75,0 -0.858674,0.24559 -2.129469,-1.0252 -0.5,0 -0.22594,-2.3e-4 -0.72594,-2.3e-4 -1.269993,1.26999 -1.394591,1.02543 -2.144591,1.02543 -0.75,0 -1.681542,-1.18154 -1.681542,-1.93154 l -1.15e-4,-0.36297 c 0,-1 0.489879,-2.00105 1.989879,-2.00105 l -0.01948,-5.74221 c -1.5,0 -1.97318,-1.05691 -1.973496,-2.05693 l -1.14e-4,-0.36297 c 0,-0.75 0.855204,-1.89751 1.666764,-1.9289 0.71584,-0.0277 0.873337,-0.24811 2.144133,1.02268 l 0.725939,2.3e-4 c 1.088566,-1.08856 1.396658,-1.02291 2.129928,-1.02291 0.75,0 1.681542,1.18154 1.681542,1.93154 l 1.15e-4,0.36297 c 1.58e-4,0.5 -0.519172,2.05566 -2.019172,2.05566 l 0.01948,5.74221 -10e-7,0 0,0 0,0 z"
+ style="fill:url(#linearGradient15748);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.821307;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1.02663434px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 82.032098,271.66942 0.0023,7.25939"
+ id="path11069"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#646464;fill-opacity:0.75;fill-rule:evenodd;stroke:#646464;stroke-width:1.02663434px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 85.299056,272.39639 -1,0"
+ id="path11071"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path11073"
+ d="m 85.310309,278.21333 -1,0"
+ style="fill:#646464;fill-opacity:0.75;fill-rule:evenodd;stroke:#646464;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1.02663434px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 82.397361,278.92893 c -2.4948,-0.75001 -2.539872,2.90296 -0.906565,2.72199"
+ id="path11075"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path24253"
+ d="m 82.395068,271.66953 c -2.548534,0.53612 -2.178736,-2.90444 -0.908284,-2.72256"
+ style="fill:none;stroke:#ffffff;stroke-width:1.02663434px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:transform-center-x="-0.32852741"
+ inkscape:transform-center-y="-1.3911103"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.6;fill:#646464;fill-opacity:0.75;fill-rule:evenodd;stroke:#646464;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 82.5437,278.0941 -1,0"
+ id="path24290"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24294"
+ d="m 82.532207,272.51355 -1,0"
+ style="opacity:0.6;fill:#646464;fill-opacity:0.75;fill-rule:evenodd;stroke:#646464;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path33682"
+ d="m 84.394211,280.56292 0.726168,0.72617"
+ style="fill:none;stroke:#ffffff;stroke-width:1.02663434px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1.02663434px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 84.390887,270.0368 0.72571,-0.72571"
+ id="path33684"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g24682"
+ transform="translate(-166,402)">
+ <rect
+ y="217"
+ x="402"
+ height="16"
+ width="16"
+ id="rect24679"
+ 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="g9450"
+ 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.6171649,0,0,0.6170324,328.7006,73.30195)"
+ style="opacity:0.8;display:inline">
+ <g
+ style="display:inline"
+ id="g9452"
+ 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">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path9454"
+ style="fill:url(#linearGradient15446);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.00075221;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 m 3.23019,3.23013 0,-6.46025"
+ style="fill:none;stroke:url(#linearGradient15448);stroke-width:4.86145973;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
+ id="path9456"
+ 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 130.96632,248.2677 0,-6.46025"
+ style="fill:none;stroke:#000000;stroke-width:2.10663271;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path9458"
+ inkscape:connector-curvature="0" />
+ <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.784039,0,0,0.779055,-3.508124,71.29625)"
+ id="g9460"
+ style="fill:none;stroke:url(#linearGradient15452);stroke-width:1.91174495;stroke-opacity:1;display:inline">
+ <path
+ transform="matrix(0.8478042,0,0,0.8531716,59.60482,122.34129)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient15450);stroke-width:2.43795967;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path9462"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ id="path9465"
+ style="fill:none;stroke:#000000;stroke-width:2.10663271;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 134.19651,245.03757 -6.46038,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"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g24609"
+ transform="translate(307.00001,487.05412)">
+ <rect
+ y="111"
+ x="202"
+ height="16"
+ width="16"
+ id="rect24481"
+ 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(1.7e-4,10.00012)"
+ id="g9996"
+ style="display:inline">
+ <path
+ style="fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.91431391;marker:none;visibility:visible;display:inline;overflow:visible"
+ d="m 209.99983,115.99988 c 3.86419,0 6.99999,-3.13578 6.99999,-6.99996 0,-3.86418 -3.1358,-6.99997 -6.99999,-6.99997 -3.86419,0 -6.99998,3.13579 -6.99998,6.99997 0,3.86418 3.13579,6.99996 6.99998,6.99996 z m 0,-4.66664 c -1.45833,0 -2.33333,-0.875 -2.33333,-2.33332 0,-1.45833 0.875,-2.33332 2.33333,-2.33332 1.45833,0 2.33333,0.87499 2.33333,2.33332 0,1.45832 -0.875,2.33332 -2.33333,2.33332 z"
+ id="path9998"
+ sodipodi:nodetypes="csssccsssc"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g10000"
+ transform="matrix(-2.005135,0,0,-2.005129,595.3141,357.6101)">
+ <path
+ style="fill:none;stroke:url(#linearGradient15578);stroke-width:0.59846401;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"
+ d="m 192.16369,120.79528 c -1.76189,0 -3.19179,1.42994 -3.1918,3.19182 0,1.76188 1.42991,3.19183 3.1918,3.19183 1.76188,0 3.19179,-1.42995 3.1918,-3.19183 0,-1.76188 -1.42992,-3.19182 -3.1918,-3.19182 l 0,0 0,0 0,0 z"
+ id="path10002"
+ sodipodi:nodetypes="csssc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="csssc"
+ id="path10004"
+ d="m 192.16376,122.51797 c -0.81098,0 -1.46916,0.65815 -1.46916,1.46907 0,0.81094 0.65818,1.46907 1.46916,1.46907 0.81097,0 1.46913,-0.65813 1.46913,-1.46907 0,-0.81092 -0.65816,-1.46907 -1.46913,-1.46907 z"
+ style="fill:none;stroke:url(#linearGradient15580);stroke-width:0.59846407;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g106468">
+ <g
+ 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.9535916,0,0,1.1712921,1176.1968,319.2322)"
+ id="g29877-5-3-1"
+ style="display:inline;enable-background:new">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path29879-5-0-9"
+ d="m 392.96689,241.84215 -0.56915,0 -3.5287,2.84782 0,1.13912 3.5287,2.84781 0.56915,0 0,-6.83475 0,0 0,0 z"
+ style="color:#000000;fill:url(#radialGradient106344-5);fill-opacity:1;fill-rule:evenodd;stroke:url(#radialGradient106433);stroke-width:0.66107476px;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
+ sodipodi:nodetypes="cccc"
+ id="path29881-5-6-0"
+ d="m 392.96688,248.67221 -0.57173,0 -3.51515,-2.83619 -0.008,-1.21916"
+ style="fill:none;stroke:url(#linearGradient106307-2);stroke-width:0.66107482px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ y="598"
+ x="404"
+ height="16"
+ width="16"
+ id="rect24491"
+ 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">
+ <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"
+ id="rect29875"
+ width="16"
+ height="16"
+ x="619"
+ y="-441" />
+ <g
+ 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(0,-2.196282,-1.316799,0,755.9575,1484.5661)"
+ id="g29877"
+ style="display:inline">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path29879"
+ d="m 392.96689,241.84215 -0.56915,0 -3.5287,2.84782 0,1.13912 3.5287,2.84781 0.56915,0 0,-6.83475 0,0 0,0 z"
+ style="color:#000000;fill:url(#linearGradient29884);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.58802557px;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
+ sodipodi:nodetypes="ccc"
+ id="path29881"
+ d="m 392.51157,247.53778 0,-4.93622 -3.18721,2.46812"
+ style="fill:none;stroke:url(#linearGradient29886);stroke-width:0.58802563px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g24559"
+ transform="translate(259,508.00001)">
+ <rect
+ y="111"
+ x="103"
+ height="16"
+ width="16"
+ id="rect24489"
+ 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
+ transform="matrix(-0.248353,0.02816779,0.02830718,0.248422,140.45214,86.01031)"
+ 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path10768"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:type="arc" />
+ </g>
+ <g
+ style="display:inline"
+ id="g24623"
+ 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"
+ id="rect24479"
+ width="16"
+ height="16"
+ x="243"
+ y="111" />
+ <g
+ transform="translate(0.01612278,6)"
+ id="g10870"
+ style="display:inline">
+ <rect
+ style="fill:url(#linearGradient15719);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect10872"
+ width="11.000006"
+ height="2.9999976"
+ x="245.48387"
+ y="111.49999"
+ rx="0"
+ ry="1.4769578"
+ 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
+ style="fill:none;stroke:url(#linearGradient15721);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 254.47577,112.49191 -7.99189,0.008 0.0242,1"
+ id="path10874"
+ 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="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g24617"
+ transform="translate(-113,487.00001)">
+ <rect
+ y="111"
+ x="223"
+ height="16"
+ width="16"
+ id="rect24477"
+ 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,6)"
+ id="g10876"
+ style="display:inline">
+ <path
+ style="fill:url(#linearGradient15723);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 225.48388,111.49999 4.01612,-0.008 -0.0161,-3.99192 3,0 0.0161,3.99192 3.98388,0.008 0,3 -3.98388,-0.008 -0.0161,4.008 -3,0 0.0161,-4.008 -4.01612,0.008 0,-3 z"
+ id="path10878"
+ sodipodi:nodetypes="ccccccccccccc"
+ 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
+ id="path10880"
+ d="m 232.48388,112.49999 3,0 m -5,2 0,3 m 1,-9 -1,0 0.0161,3.99192 -4.01612,0.008 0.0242,1"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="ccccccccc"
+ 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" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g24629"
+ transform="translate(-128,487.00001)">
+ <rect
+ y="132"
+ x="322"
+ height="16"
+ width="16"
+ id="rect24475"
+ 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="g11344"
+ 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.9261989,0,0,0.928757,209.23303,-98.08036)"
+ style="display:inline">
+ <g
+ style="display:inline"
+ id="g11346"
+ 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">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path11348"
+ style="fill:url(#linearGradient15774);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.06496322;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,130.45005)" />
+ </g>
+ <path
+ d="m 134.19651,255.80467 -6.46038,0 m 3.23019,3.23013 0,-6.46025"
+ style="fill:none;stroke:url(#linearGradient15776);stroke-width:3.2301569;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
+ id="path11350"
+ 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 130.96632,259.0348 0,-6.46025"
+ style="fill:none;stroke:#000000;stroke-width:1.07819378;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path11352"
+ inkscape:connector-curvature="0" />
+ <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.784039,0,0,0.779055,-3.508124,71.29625)"
+ id="g11354"
+ style="fill:none;stroke:url(#linearGradient15780);stroke-width:1.27024341;stroke-opacity:1;display:inline">
+ <path
+ transform="matrix(0.858314,0,0,0.863791,58.21752,134.9089)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient15778);stroke-width:1.60000753;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path11356"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ id="path11358"
+ style="fill:none;stroke:#000000;stroke-width:1.07819378;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 134.19651,255.80467 -6.46038,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"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g24604"
+ transform="translate(305,487.00001)">
+ <rect
+ y="111"
+ x="183"
+ height="16"
+ width="16"
+ id="rect24483"
+ 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(-1,0,0,-1,382.01612,238.00006)"
+ id="g54036"
+ style="display:inline">
+ <path
+ sodipodi:type="arc"
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient16025);stroke-width:1.94115818;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"
+ id="path54038"
+ sodipodi:cx="190.5"
+ sodipodi:cy="119.5"
+ sodipodi:rx="5.5"
+ sodipodi:ry="5.5"
+ d="m 196,119.5 a 5.5,5.5 0 1 1 -11,0 5.5,5.5 0 1 1 11,0 z"
+ transform="matrix(0.61819,0,0,0.618186,73.23488,45.12681)" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g24582"
+ transform="translate(114.02028,508.00993)">
+ <rect
+ y="111"
+ x="143"
+ height="16"
+ width="16"
+ id="rect24487"
+ 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="g24576">
+ <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 1 1 -5.5889,0 2.7944512,2.7944512 0 1 1 5.5889,0 z"
+ sodipodi:ry="2.7944512"
+ sodipodi:rx="2.7944512"
+ sodipodi:cy="35.5"
+ sodipodi:cx="330.5"
+ id="path15084"
+ 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 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="path15086"
+ style="opacity:0.4;fill:none;stroke:url(#linearGradient15122);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(#linearGradient15124);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="path15099"
+ 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(-1.288521,0,0,-1.2885339,576.8463,164.73299)" />
+ </g>
+ </g>
+ <g
+ style="opacity:0.6;display:inline"
+ id="g24923"
+ 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"
+ id="rect24905"
+ width="16"
+ height="16"
+ x="43"
+ y="69" />
+ <g
+ transform="translate(0.01612278,0)"
+ id="g10995"
+ style="display:inline">
+ <g
+ style="fill:none;display:inline"
+ 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(-0.608695,0,0,0.604849,289.36339,-70.36932)"
+ id="g10997">
+ <path
+ id="path10999"
+ d="m 394.08819,237.85988 -6.57143,6.61322 6.57143,6.61322 1.23215,0 -10e-6,-13.22644 -1.23214,0 z"
+ style="fill:none;stroke:#000000;stroke-width:1.64807379;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path11001"
+ d="m 49.233877,73.74999 3.75,3.75 -3.75,3.75 -0.25,0 0,-7.5 0.25,0 z"
+ style="fill:#808080;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:none;stroke:#ffffff;stroke-width:0.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 57.25,606.75 -3.75,3.75 -0.5,0"
+ id="path35403"
+ sodipodi:nodetypes="cc"
+ transform="translate(-4.0161228,-529.00001)"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g24911"
+ 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"
+ id="rect24909"
+ width="16"
+ height="16"
+ x="82"
+ y="69" />
+ <g
+ style="display:inline"
+ transform="matrix(0,-1,1,0,-153.98989,467.9919)"
+ id="g11003"
+ 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
+ id="path11005"
+ d="m 392.49192,239.48989 -5.00001,4.75 0,0.5 5.00001,4.75 1,0 0,-10 -1,0 z"
+ style="color:#000000;fill:url(#linearGradient15742-5);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;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path11007"
+ d="m 392.49191,248.23989 0,-7.5"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g24917"
+ 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"
+ id="rect24907"
+ width="16"
+ height="16"
+ x="62"
+ y="69" />
+ <g
+ style="display:inline"
+ id="g11009"
+ transform="matrix(-1,0,0,1,461.01011,-167)"
+ 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="fill:url(#linearGradient15742);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 392.5,239.5 -4.98989,4.74999 0,0.5 4.98989,4.75001 1.01011,-1e-5 0.0368,-9.96874 L 392.5,239.5 z"
+ id="path11011"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient27860);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 392.51011,248.24999 0,-7.5 -4,3.75"
+ id="path11013"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g25461"
+ transform="translate(444,424.00001)">
+ <rect
+ y="174"
+ x="23"
+ height="16"
+ width="16"
+ id="rect25118"
+ 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="g25451">
+ <g
+ id="use25367"
+ transform="translate(24.016123,6)">
+ <rect
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000036;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.3;marker:none;visibility:visible;display:inline;overflow:visible"
+ id="rect25447"
+ width="1.0000005"
+ height="3.0000005"
+ x="6.5000019"
+ y="178.50003" />
+ <rect
+ y="177.5"
+ x="5.5"
+ height="3"
+ width="1"
+ id="rect25449"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.3;marker:none;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ <g
+ id="use25369"
+ transform="translate(28.016123,6)">
+ <rect
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000036;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.3;marker:none;visibility:visible;display:inline;overflow:visible"
+ id="rect25441"
+ width="1.0000005"
+ height="3.0000005"
+ x="6.5000019"
+ y="178.50003" />
+ <rect
+ y="177.5"
+ x="5.5"
+ height="3"
+ width="1"
+ id="rect25443"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.3;marker:none;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ <rect
+ y="184.50003"
+ x="26.516125"
+ height="3.0000005"
+ width="1.0000005"
+ id="rect25373"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000036;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.3;marker:none;visibility:visible;display:inline;overflow:visible" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.3;marker:none;visibility:visible;display:inline;overflow:visible"
+ id="rect25375"
+ width="1"
+ height="3"
+ x="25.516123"
+ y="183.5" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g25412"
+ transform="translate(443,424.00001)">
+ <rect
+ y="174"
+ x="3"
+ height="16"
+ width="16"
+ id="rect25116"
+ 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="g25401">
+ <g
+ id="use9783"
+ transform="translate(4.0161228,0)">
+ <rect
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000036;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.3;marker:none;visibility:visible;display:inline;overflow:visible"
+ id="rect25397"
+ width="1.0000005"
+ height="3.0000005"
+ x="6.5000019"
+ y="178.50003" />
+ <rect
+ y="177.5"
+ x="5.5"
+ height="3"
+ width="1"
+ id="rect25399"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.3;marker:none;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ <g
+ id="use9785"
+ transform="translate(8.0161228,0)">
+ <rect
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000036;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.3;marker:none;visibility:visible;display:inline;overflow:visible"
+ id="rect25391"
+ width="1.0000005"
+ height="3.0000005"
+ x="6.5000019"
+ y="178.50003" />
+ <rect
+ y="177.5"
+ x="5.5"
+ height="3"
+ width="1"
+ id="rect25393"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.3;marker:none;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ <g
+ id="g9787"
+ transform="translate(0.01612278,0)">
+ <rect
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000036;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.3;marker:none;visibility:visible;display:inline;overflow:visible"
+ id="rect9789"
+ width="1.0000005"
+ height="3.0000005"
+ x="6.5000019"
+ y="178.50003" />
+ <rect
+ y="177.5"
+ x="5.5"
+ height="3"
+ width="1"
+ id="rect9791"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.3;marker:none;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g25528"
+ 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"
+ id="rect25526"
+ width="16"
+ height="16"
+ x="143"
+ y="153" />
+ <g
+ transform="translate(0.01612278,0)"
+ id="g10844"
+ style="display:inline">
+ <path
+ style="fill:url(#linearGradient15699);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 144.5,163.5 13,0 0,-1 c 0,-2.25 -0.5,-3 -4,-3 -0.5,-1.25 -1.5,-3 -4,-3 l -1,0 c -3.75,0 -4,2.25 -4,5 l 0,2 z"
+ id="path10846"
+ sodipodi:nodetypes="ccscsccc"
+ 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:type="arc"
+ style="fill:url(#linearGradient15701);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.46666667;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5"
+ id="path10848"
+ sodipodi:cx="147"
+ sodipodi:cy="165"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 148,165 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 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"
+ 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"
+ sodipodi:nodetypes="csccc"
+ id="path10850"
+ d="m 150,157.5 -1.5,0 c -3,0 -3,1.5 -3,5 m 10.99996,-0.71441 c 0,-1.60712 5e-5,-1.28559 -2.99996,-1.28559"
+ style="fill:none;stroke:url(#linearGradient15703);stroke-width:1;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.5,0,0,1.5,-66.5,-83.5)"
+ d="m 148,165 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="165"
+ sodipodi:cx="147"
+ id="path10852"
+ style="fill:url(#linearGradient15705);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.46666667;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5"
+ sodipodi:type="arc" />
+ </g>
+ </g>
+ <g
+ id="g35472"
+ 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"
+ id="rect25724"
+ width="16"
+ height="16"
+ x="89"
+ y="470" />
+ <g
+ id="g35249">
+ <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="path12027"
+ d="m 94.5,480.5 1.25,-1.25"
+ style="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:transform-center-y="-6.245879"
+ inkscape:transform-center-x="-6.2091889"
+ sodipodi:type="arc"
+ style="fill:none;stroke:#000000;stroke-width:0.62898993;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;display:inline"
+ id="path12029"
+ 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.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"
+ inkscape:export-ydpi="90" />
+ <path
+ style="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 90.863188,484.13807 94.25,480.75"
+ id="path12031"
+ 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:none;stroke:#cccccc;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 94.5,480.5 1.25,-1.25"
+ id="path12033"
+ 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
+ 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.4308622,0,0,1.4308687,469.36987,363.18486)"
+ 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="path35965"
+ style="opacity:0.5;fill:url(#radialGradient35967);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.55910218;marker:none;display:inline"
+ sodipodi:type="arc"
+ inkscape:transform-center-x="-6.2091889"
+ inkscape:transform-center-y="-6.245879" />
+ <g
+ id="g12035"
+ 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.0005769,0,0,0.9999104,-69.113516,270.01809)">
+ <path
+ inkscape:transform-center-y="-4.9844055"
+ inkscape:transform-center-x="-4.9755572"
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient35488);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient35490);stroke-width:0.87477797;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;display:inline"
+ id="path12037"
+ 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.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 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="path35287"
+ style="opacity:0.25;fill:url(#radialGradient35492);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
+ sodipodi:type="arc"
+ style="opacity:0.25;fill:url(#radialGradient35494);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path35289"
+ 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(-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 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="135"
+ sodipodi:cx="64"
+ id="path12041"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.74699998;marker:none;display:inline"
+ sodipodi:type="arc"
+ transform="matrix(0.993526,0,0,1.026234,103.4315,65.484747)" />
+ </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="path12043"
+ d="m 90.75,484.25 3.5,-3.5"
+ style="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.7;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M 90.25,484 94,480.25"
+ id="path12045"
+ 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>
+ </g>
+ <g
+ style="display:inline"
+ id="g21566"
+ 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"
+ id="rect21528"
+ width="16"
+ height="16"
+ x="463"
+ y="236" />
+ <g
+ transform="translate(459.98858,167)"
+ style="display:inline"
+ id="g14449">
+ <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="path14451"
+ d="m 17.51142,84.5 -13.988585,0 -0.011415,-14 14,0 0,14 z"
+ style="fill:url(#linearGradient16063);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"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path14523"
+ style="fill:none;stroke:url(#linearGradient16067);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ d="m 6.0097,77.5 6.00172,0 m 1,0 4,0 m -6,-2 6,0 m -3,-2 3,0 m -11.00172,0 7.00172,0 m -7.00172,2 4.00172,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="cccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:none;stroke:url(#linearGradient16069);stroke-width:0.99999976px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 16.51142,71.5 -12,0 0,12 12.000001,0 -10e-7,-12 0,0 0,0 0,0 z"
+ id="path14459"
+ 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" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g21557"
+ transform="translate(-205,-205)">
+ <rect
+ y="236"
+ x="483"
+ height="16"
+ width="16"
+ id="rect21548"
+ 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="g21749">
+ <g
+ transform="translate(479.98859,167)"
+ style="display:inline"
+ id="g14498">
+ <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="path14500"
+ d="m 17.51141,84.5 -14,0 -1e-7,-14 13.9814141,0 0.01859,14 -4e-6,0 z"
+ style="fill:url(#linearGradient14511);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"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:none;stroke:url(#linearGradient14517);stroke-width:0.99999976px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 16.51141,71.5 -12,0 0,12 12.000001,0 -10e-7,-12 z"
+ id="path14508"
+ 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" />
+ </g>
+ <path
+ sodipodi:nodetypes="cccccccccc"
+ 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 486,246.5 7.03916,0 m -2.03916,2 -5,0 m 0.0392,-6 5,0 m -5,-2 6,0 m -6,4 3,0"
+ style="fill:none;stroke:url(#linearGradient21531);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="path15300"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g21497"
+ 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"
+ id="rect21493"
+ width="16"
+ height="16"
+ x="223"
+ y="26" />
+ <g
+ id="g21465">
+ <g
+ style="display:inline"
+ id="g10969"
+ 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="translate(0.1889228,-16)">
+ <g
+ 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="g10971"
+ transform="matrix(1.083333,0,0,1.083326,-149.75,-207.0817)">
+ <g
+ id="g10973">
+ <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="path10975"
+ d="m 356.53857,243.30784 -11.07692,0 0,-11.07699 11.07692,0 0,11.07699 z"
+ style="fill:url(#linearGradient15734);fill-opacity:1;fill-rule:evenodd;stroke:#333333;stroke-width:0.92307967px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ style="fill:none;stroke:#ffffff;stroke-width:0.92307913px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 346.38485,242.26935 -1.3e-4,-9.11543 9.14632,0"
+ id="path10977"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <path
+ id="path10979"
+ d="m 227,49 0,1 2,0 0,-1 -2,0 z m 2,1 0,1 -2,0 0,1 2,0 0,1 -2,0 0,1 2,0 1,0 0,-4 -1,0 z m -2,3 0,-1 -1,0 0,1 1,0 z"
+ style="fill:#0055d4;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:nodetypes="cccccccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 231,47 0,7 1,0 2,0 0,-1 -2,0 0,-2 2,0 0,-1 -2,0 0,-3 -1,0 z m 3,4 0,2 1,0 0,-2 -1,0 z"
+ id="path10981"
+ sodipodi:nodetypes="ccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g16140"
+ style="display:inline"
+ transform="translate(219.98859,-43)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:url(#linearGradient16150);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 17.51141,84.5 -14,0 -1e-7,-14 13.9814141,0 0.01859,14 -4e-6,0 z"
+ id="path16142"
+ 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
+ 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="path16148"
+ d="m 16.51141,71.5 -12,0 0,12 12.000001,0 -10e-7,-12 z"
+ style="fill:none;stroke:url(#linearGradient16154);stroke-width:0.99999976px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path16156"
+ d="m 227,33 0,1 2,0 0,-1 -2,0 z m 2,1 0,1 -2,0 0,1 2,0 0,1 -2,0 0,1 2,0 1,0 0,-4 -1,0 z m -2,3 0,-1 -1,0 0,1 1,0 z"
+ style="fill:#0055d4;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:nodetypes="cccccccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 231,31 0,7 1,0 2,0 0,-1 -2,0 0,-2 2,0 0,-1 -2,0 0,-3 -1,0 z m 3,4 0,2 1,0 0,-2 -1,0 z"
+ id="path16158"
+ sodipodi:nodetypes="ccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g21514"
+ transform="translate(96.030183,5)">
+ <rect
+ y="26"
+ x="202.96982"
+ height="16"
+ width="16"
+ id="rect21491"
+ 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="g21479">
+ <g
+ transform="translate(-19.811077,-16)"
+ 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="g10983"
+ style="display:inline">
+ <g
+ transform="matrix(1.083333,0,0,1.083326,-149.75,-207.0817)"
+ id="g10985"
+ 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="g10987">
+ <path
+ style="fill:url(#linearGradient15736);fill-opacity:1;fill-rule:evenodd;stroke:#333333;stroke-width:0.92307967px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 356.53857,243.30784 -11.07692,0 0,-11.07699 11.07692,0 0,11.07699 z"
+ id="path10989"
+ 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" />
+ <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="path10991"
+ d="m 346.38485,242.26935 -1.3e-4,-9.11543 9.14632,0"
+ style="fill:none;stroke:#ffffff;stroke-width:0.92307913px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <path
+ style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 231,47 0,7 1,0 2,0 0,-1 -2,0 0,-2 2,0 0,-1 -2,0 0,-3 -1,0 z m 3,4 0,2 1,0 0,-2 -1,0 z m -7,-2 0,1 2,0 0,-1 -2,0 z m 2,1 0,1 -2,0 0,1 2,0 0,1 -2,0 0,1 2,0 1,0 0,-4 -1,0 z m -2,3 0,-1 -1,0 0,1 1,0 z"
+ id="path10993"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(199.98859,-43)"
+ style="display:inline"
+ id="g16160">
+ <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="path16162"
+ d="m 17.51141,84.5 -14,0 -1e-7,-14 13.9814141,0 0.01859,14 -4e-6,0 z"
+ style="fill:url(#linearGradient16170);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"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:none;stroke:url(#linearGradient16174);stroke-width:0.99999976px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 16.51141,71.5 -12,0 -1e-6,12 12.000001,0 0,-12 z"
+ id="path16168"
+ 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" />
+ </g>
+ <path
+ style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 211,31 0,7 1,0 2,0 0,-1 -2,0 0,-2 2,0 0,-1 -2,0 0,-3 -1,0 z m 3,4 0,2 1,0 0,-2 -1,0 z m -7,-2 0,1 2,0 0,-1 -2,0 z m 2,1 0,1 -2,0 0,1 2,0 0,1 -2,0 0,1 2,0 1,0 0,-4 -1,0 z m -2,3 0,-1 -1,0 0,1 1,0 z"
+ id="path16178"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g11969"
+ 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="rect21607"
+ width="16"
+ height="16"
+ x="362"
+ y="29" />
+ <g
+ id="g11961">
+ <g
+ transform="translate(358.98859,-40)"
+ style="display:inline"
+ id="g14938">
+ <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="path14940"
+ d="m 17.51141,84.5 -14,0 -1e-7,-14 13.9814141,0 0.01859,14 -4e-6,0 z"
+ style="fill:url(#linearGradient21902);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"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:none;stroke:url(#linearGradient21904);stroke-width:0.99999976px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 16.51141,71.5 -12,0 0,12 12.000001,0 -10e-7,-12 z"
+ id="path14942"
+ 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" />
+ </g>
+ <path
+ sodipodi:nodetypes="cccccccccccccccccccccccccccc"
+ id="path14947"
+ d="m 366,33.03125 0,1 -1,0 0,1 1,0 0,2 1,0 0,-4 -1,0 z M 365,39 l 0,1 2.3295,0 0,-1 L 365,39 z m 2,1 0,1 1,0 0,-1 -1,0 z m 0.0594,1 -1.05938,0 0,1 -1,0 0,1 3,0 0,-1 -1.44062,0 0.5,-1 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 369,34 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m -4,2 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m -4,3 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m -4,2 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z"
+ id="path14953"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#666666;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 370,34 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m -4,2 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m -4,3 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m -4,2 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z"
+ id="path14955"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g11979"
+ 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="rect21605"
+ width="16"
+ height="16"
+ x="341"
+ y="29" />
+ <g
+ id="g11953">
+ <g
+ id="g14924"
+ style="display:inline"
+ transform="translate(337.98858,-40)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:url(#linearGradient21862);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 17.500005,84.5 -13.988585,0 -1e-7,-14 14.0000001,0 -0.01141,14 -5e-6,0 0,0 0,0 z"
+ id="path14929"
+ 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
+ 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="path14933"
+ d="m 16.51142,71.5 -12,0 0,12 12.000001,0 -10e-7,-12 0,0 0,0 0,0 z"
+ style="fill:none;stroke:url(#linearGradient21864);stroke-width:0.99999976px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g11949">
+ <path
+ id="path14967"
+ d="m 344,34 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m -8,2 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m -8,3 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m -8,2 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z"
+ style="fill:#666666;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path14971"
+ d="m 345,34 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m -8,2 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m -8,3 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m -8,2 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z"
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </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">
+ <g
+ id="g22274"
+ transform="translate(-30,0)">
+ <rect
+ ry="0"
+ rx="0"
+ y="-127"
+ x="200"
+ height="16"
+ width="16"
+ id="rect22276"
+ 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
+ style="fill:none;stroke:#0b1728;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"
+ d="m 204,-114 c 4.5365,0 8.5,-3 8.5,-6 0,-1.75 -1.25,-4 -5.5,-4"
+ id="path22282"
+ sodipodi:nodetypes="csc"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#162d50;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;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="rect22278"
+ width="2.9998772"
+ height="3"
+ x="202.50012"
+ y="-115.5"
+ ry="1.4999387"
+ rx="1.4843137" />
+ <rect
+ rx="1.4999387"
+ ry="1.4999387"
+ y="-125.5"
+ x="205.50012"
+ height="3"
+ width="2.9998772"
+ id="rect22280"
+ style="fill:#162d50;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;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"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="csc"
+ id="path22284"
+ d="m 204,-114 c 4.49647,0 8.5,-3 8.5,-6 0,-1.75 -1.25,-4 -5.5,-4"
+ style="fill:none;stroke:url(#linearGradient24098);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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#afc6e9;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 205,-115 c -0.66667,0 -1.33332,1e-5 -2,1e-5 0,0.66939 0,1.33877 0,2.00817 0.66668,0 1.33333,-10e-6 2,-10e-6 0,-0.66939 0,-1.33878 0,-2.00817 z"
+ id="path22288"
+ 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="path22291"
+ d="m 208,-125 c -0.65334,0 -1.30668,1e-5 -1.96003,1e-5 0,0.66667 0,1.33332 0,1.99999 0.65335,0 1.30669,-1e-5 1.96003,-1e-5 0,-0.66666 0,-1.33332 0,-1.99999 z"
+ style="fill:#87aade;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" />
+ </g>
+ <path
+ style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 176.5,-123.5 0,-1 1,0"
+ id="path22293"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path22295"
+ d="m 173.5,-113.5 0,-1 1,0"
+ style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ 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="path22297"
+ d="m 176,-113.25657 c -0.33333,0 -0.66667,-1e-5 -1,-1e-5 0,-0.55431 0,-1.1086 0,-1.66292 0.33333,0 0.66667,1e-5 1,1e-5 0,0.55431 0,1.10861 0,1.66292 z"
+ style="opacity:0.35;fill:#002255;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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="path22299"
+ d="m 179,-122.48792 c -0.32001,0 -0.64002,-1e-5 -0.96003,-1e-5 0,-0.63982 0,-1.27964 0,-1.91948 0.32001,0 0.64002,1e-5 0.96003,1e-5 0,0.63983 0,1.27966 0,1.91948 z"
+ style="opacity:0.2;fill:#002255;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.5;fill:#00112b;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 176,-113 c -0.33333,0 -0.66667,0 -1,0 0,-0.21055 0,-0.42107 0,-0.63162 0.33333,0 0.66667,0 1,0 0,0.21055 0,0.42107 0,0.63162 z"
+ id="path22302"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline"
+ id="g31233"
+ 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"
+ id="rect31205"
+ width="16"
+ height="16"
+ x="63"
+ y="48" />
+ <g
+ id="g9148"
+ 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"
+ transform="matrix(1.0003553,0,0,0.9995949,18.983834,-41.953346)">
+ <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"
+ style="fill:url(#linearGradient15356);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80001998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect9150"
+ width="12.995382"
+ height="13.003749"
+ x="45.5"
+ y="91.491928" />
+ <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:url(#linearGradient15358);stroke-width:1.0000248px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 46.49945,103.49527 0,-11.002747 10.996287,0 0,11.002747 -10.996287,0 z"
+ id="path9152"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g31226"
+ 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"
+ id="rect31207"
+ width="16"
+ height="16"
+ x="83"
+ y="48" />
+ <g
+ style="display:inline"
+ id="g9154"
+ transform="matrix(1.1658027,0,0,1.1657997,-59.289717,-204.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
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path9156"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.23686159;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.6969446,0,0,0.6900977,36.918531,141.69345)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.8;fill:url(#linearGradient15360);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path9158"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.6391427,-0.07194179,0.07284933,-0.6344823,204.68584,307.47408)" />
+ <path
+ transform="matrix(0.5885088,0,0,0.5897133,51.241774,153.48488)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient15362);stroke-width:1.45605874;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path9160"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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"
+ 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="rect31391"
+ width="16"
+ height="16"
+ x="110"
+ y="29" />
+ <g
+ transform="translate(-73,-123.96875)"
+ id="g9974"
+ style="display:inline">
+ <path
+ style="fill:none;stroke:none"
+ d="M 186.2503,165.73428 C 185.16882,164.6489 184.5,163.15208 184.5,161.5 c 0,-3.312 2.688,-6 6,-6 1.65758,0 3.15886,0.67328 4.24511,1.76111 l -8.49481,8.47317 z"
+ id="path9976"
+ sodipodi:nodetypes="csscc"
+ 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="path23601"
+ d="m 188,154 0,2 6,0 0,-2 -6,0 z m 6,2 0,2 1.96875,0 0,6 -1.96875,0 0,1.96875 -6,0 0,-1.96875 -2,0 0,2 2,0 0,1.96875 6,0 0,-1.96875 2,0 0,-2 1.96875,0 0,-6 -1.96875,0 0,-2 -2,0 z m -8,8 0,-6 -2,0 0,6 2,0 z m 0,-6 2,0 0,-2 -2,0 0,2 z"
+ style="opacity:0.1;fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 188,154 0,2 6,0 0,-2 -6,0 z m 6,2 0,2 1.96875,0 0,6 -1.96875,0 0,1.96875 -6,0 0,-1.96875 -2,0 0,2 2,0 0,1.96875 6,0 0,-1.96875 2,0 0,-2 1.96875,0 0,-6 -1.96875,0 0,-2 -2,0 z m -8,8 0,-6 -2,0 0,6 2,0 z m 0,-6 2,0 0,-2 -2,0 0,2 z"
+ id="path9978"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.8;fill:url(#linearGradient15574);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 186,158 2,0 0,-2 6,0 0,2 2,0 0,6 -2,0 0,2 -6,0 0,-2 -2,0 0,-6 z"
+ id="path9980"
+ sodipodi:nodetypes="ccccccccccccc"
+ 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"
+ sodipodi:nodetypes="ccccccccccccc"
+ id="path23596"
+ d="m 186.5,158.46875 2,0 0,-2 5,0 0,2 2,0 0,5 -2,0 0,2 -5,0 0,-2 -2,0 0,-5 z"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient23599);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0.5"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g31442"
+ 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"
+ id="rect31425"
+ width="16"
+ height="16"
+ x="282"
+ y="6" />
+ <g
+ 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="translate(0.01612278,22)"
+ id="g10456"
+ style="display:inline">
+ <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="path10458"
+ d="m 296.49991,-1.4999999 -13.00008,0 0,-12.9999991 13.00008,0 0,12.9999991 0,0 0,0 0,0 z"
+ style="fill:url(#linearGradient15644);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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient15646);stroke-width:1.00000036px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 284.50009,-2.5000021 0,-11.0000069 11.00001,0"
+ id="path10460"
+ 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
+ id="path10462"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
+ d="m 286.42863,-12.4 -0.84311,0 m 2.83879,3 -0.83163,0 m 2.83056,3 -0.82626,0 m 2.78967,1 -0.80293,0 m 3.77084,1 -1.74082,0"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g31515"
+ transform="translate(18,130)">
+ <rect
+ y="27"
+ x="323"
+ height="16"
+ width="16"
+ id="rect31510"
+ 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="g10854"
+ style="display:inline">
+ <rect
+ style="fill:url(#linearGradient15707);fill-opacity:1;fill-rule:nonzero;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="rect10856"
+ width="12"
+ height="12"
+ x="324.50003"
+ y="41.500015" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient15709);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path10858"
+ 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(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"
+ d="m 335.50002,42.500013 -10,0 0,10 L 335.5,52.5 l 0,-10"
+ id="path10860"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient15713);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="path10862"
+ 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.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" />
+ <g
+ style="display:inline"
+ id="g27528"
+ transform="translate(0.01612278,-12)">
+ <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 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="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 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="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" />
+ </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" />
+ <g
+ transform="translate(0.01612278,0)"
+ id="g10864"
+ style="display:inline">
+ <path
+ transform="matrix(1.142871,0,0,1.142855,-27.218817,-5.0713453)"
+ 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="path10866"
+ style="fill:url(#linearGradient15715);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.87499601;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="fill:none;stroke:url(#linearGradient15717);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="path10868"
+ 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.857099,0,0,0.857147,67.228993,5.071249)" />
+ </g>
+ </g>
+ <g
+ id="g31658"
+ 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"
+ id="rect31549"
+ width="16"
+ height="16"
+ x="26"
+ y="8" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:url(#linearGradient31664);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 40.499999,22.499999 -12.999999,0 0,-12.999999 12.982741,0 0.01726,12.999999 -2e-6,0 z"
+ id="path31555"
+ 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="cccccccccccccccccccccccccccccccccccc"
+ id="path31559"
+ d="M 36.5,11.548223 36.5,19 l 0,-7.451777 z M 37.5,16 l 0,3 0,-3 z m -3,-2 0,5 0,-5 z m 1,0 0,5 0,-5 z m -3,1 0,4 0,-4 z m 6,0 0,4 0,-4 z m -5,1 0,3 0,-3 z m -3,1 0,2 0,-2 z m 9,1.578539 0,0.421461 0,-0.421461 z M 31.5,18 l 0,1 0,-1 z m -3,-0.52573 0,1.52573 0,-1.52573 z m 1,1.087098 0,0.438632 0,-0.438632 z"
+ style="fill:none;stroke:url(#linearGradient31666);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient31672);stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ d="m 28.5,19.5 11,0"
+ id="path31670"
+ sodipodi:nodetypes="cc"
+ 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="path31557"
+ d="m 39.5,10.500004 -11,0 0,11 11.000001,0 -10e-7,-11 z"
+ style="fill:none;stroke:url(#linearGradient31668);stroke-width:0.99999976px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline"
+ id="g31429"
+ transform="translate(-234,4)">
+ <rect
+ y="6"
+ x="302"
+ height="16"
+ width="16"
+ id="rect31427"
+ 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,-16)"
+ id="g13262"
+ style="display:inline">
+ <g
+ 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="translate(20.00009,22)"
+ id="g13264">
+ <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="path13266"
+ d="m 296.49991,14.5 -13.00008,0 0,-12.999999 13.00008,0 0,12.999999 z"
+ style="fill:url(#linearGradient31646);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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient31648);stroke-width:1.00000036px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 284.50009,13.499998 0,-11.000007 11.00001,0"
+ id="path13268"
+ 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" />
+ </g>
+ <path
+ id="path13270"
+ style="fill:none;stroke:#ffffff;stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ d="m 310,34 -3.5,-1.5 0,-5 3.5,-1.5 3.5,1.5 0,5 -3.5,1.5 z"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g13272"
+ transform="translate(0,-10)"
+ style="stroke-width:1.10000002;stroke-miterlimit:4;stroke-dasharray:none">
+ <path
+ id="path13274"
+ style="fill:none;stroke:url(#radialGradient31650);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ d="m 310,44 -3.5,-1.5 0,-5 3.5,-1.5 3.5,1.5 0,5 -3.5,1.5 z"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ d="m 310,44 -3.5,-1.5 0,-5 3.5,-1.5 3.5,1.5 0,5 -3.5,1.5 z"
+ style="fill:none;stroke:url(#radialGradient31652);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="path13276"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path13278"
+ style="fill:none;stroke:url(#radialGradient31654);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ d="m 310,44 -3.5,-1.5 0,-5 3.5,-1.5 3.5,1.5 0,5 -3.5,1.5 z"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ d="m 309.98388,44 -3.5,-1.5 0,-5 3.5,-1.5 3.5,1.5 0,5 -3.5,1.5 z"
+ style="fill:none;stroke:url(#radialGradient31656);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="path13280"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ transform="translate(-21,-418)"
+ id="g31674">
+ <rect
+ y="428"
+ x="47"
+ height="16"
+ width="16"
+ id="rect31676"
+ 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="g31678">
+ <rect
+ ry="0"
+ style="fill:#ececec;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="rect31680"
+ width="13.016124"
+ height="12.953857"
+ x="48.499996"
+ y="429.54614" />
+ <rect
+ y="430"
+ x="50.016117"
+ height="11.046139"
+ width="11.000001"
+ id="rect31682"
+ style="fill:url(#linearGradient31694);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
+ style="fill:url(#linearGradient31696);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 49,430 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,0 0,3 3,0 0,-3 -3,0 z m 0,3 -3,0 0,3 3,0 0,-3 z m 0,3 0,3 3,0 0,-3 -3,0 z m -3,0 -3,0 0,3 3,0 0,-3 z m -3,0 0,-3 -3,0 0,3 3,0 z"
+ id="path31684"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient31698);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 60.517703,430.5 -11.017704,0 0,11 11.017704,0 0,-11"
+ id="path31686"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g11938"
+ transform="translate(0,2)">
+ <rect
+ y="8"
+ x="278"
+ height="16"
+ width="16"
+ id="rect31906"
+ 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(-64.983874,-102.97791)"
+ id="g14768"
+ style="display:inline">
+ <path
+ style="fill:url(#linearGradient31932);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 348.18876,112.47791 8.33334,0 0,13 -11,0 -1e-5,-10 2.66667,-3 0,0 0,0 0,0 z"
+ id="path14575"
+ 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
+ style="fill:#666666;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 349,114 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 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 0,-2 2,0 0,-2 -2,0 0,2 z m 0,-2 0,-2 -2,0 0,2 2,0 z"
+ id="rect14548"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M -48.500031,260.50809 -46.5,260.5 l -3.1e-5,-1.99191"
+ style="opacity:0.7;fill:none;stroke:#000000;stroke-width:0.76923829px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1;display:inline;filter:url(#filter31351)"
+ id="path14579"
+ sodipodi:nodetypes="ccc"
+ transform="matrix(1.2999758,0,0,1.2999988,409.54887,-222.56021)"
+ 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:url(#linearGradient31934);stroke-width:0.99999988px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ d="m 354.58387,114.50843 -7.05183,-0.0551 0.007,9.11382"
+ id="path14581"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 345,116 4,0 0,-4 -4,4 z"
+ id="path14583"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 346.5,117.00001 0,7.5 m 3.5,-11 5.5,0"
+ style="fill:none;stroke:url(#linearGradient31936);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ id="path14585"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path14587"
+ 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 345.5221,114.97791 0,10.5 11,0 0,-13 -8.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"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g10845"
+ 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="rect31964"
+ width="16"
+ height="16"
+ x="26"
+ y="260" />
+ <g
+ transform="translate(-2322.9523,-570.94199)"
+ id="g12799"
+ style="display:inline">
+ <path
+ sodipodi:nodetypes="cczcccc"
+ id="path12801"
+ d="m 2349.9523,841.94199 c 2.0093,-2.0093 3.5347,-3.43269 5.544,-5.44199 3.25,-3.25 9,-2 9,2 -4.5,-2.5 -7.044,3.94199 -0.544,3.94199 l 0,1.5 -14,0 0,-2 z"
+ style="opacity:0.8;fill:url(#linearGradient38692);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:#0b1728;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 2349.5,842.49627 c 1.9988,-1.99875 3.9535,-4.05552 5.9523,-6.05428 3.25,-3.25 9.044,-1.94199 9.044,2.05801 -4.5,-2.5 -6.544,4.94199 0,4"
+ id="path12805"
+ sodipodi:nodetypes="cczc"
+ 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"
+ sodipodi:nodetypes="ccs"
+ id="path12807"
+ d="m 2351,842.51381 c 1.67,-1.67002 3.34,-3.34005 5.0101,-5.01008 2.1922,-2.31174 5.9422,-2.81174 7.4422,-0.0617"
+ style="fill:none;stroke:url(#radialGradient13900);stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g13136"
+ transform="translate(0,2)">
+ <rect
+ y="260"
+ x="131"
+ height="16"
+ width="16"
+ id="rect32039"
+ 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="g13125">
+ <g
+ id="g12811"
+ transform="translate(-70.98388,253.6)"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ style="opacity:0.4">
+ <g
+ 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"
+ transform="matrix(1.090908,0,0,1.083334,-60.5905,-148.5)"
+ id="g12813">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path12815"
+ d="m 253.9851,154.06144 0.0148,-7.98461 -5.97312,2.67692 c 0,2.37037 -0.0149,8.01803 -0.0149,8.53832 l 5.97323,-3.23063 -1e-5,0 z"
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ 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"
+ style="fill:#c9c9c9;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 242.06842,154.06144 0,-8.21538 5.95834,2.90769 0,8.30769 -5.95834,-3 z"
+ id="path12817"
+ 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="path12819"
+ d="m 242.06842,146.21529 5.95834,-2.67692 5.95834,2.67692 -5.95834,2.53846 -5.95834,-2.53846 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ 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
+ sodipodi:nodetypes="ccccccccc"
+ 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="path12821"
+ 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 209.98388,21.9 -6.5,-3.5 0,-8.5 m 6.5,12 6.5,-3.5 0,-8.5 m 0,0 -6.5,-2.75 -6.5,2.75"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline"
+ id="g12823"
+ transform="matrix(0.668332,0,0,0.668394,53.64412,108.1139)"
+ 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\Kopia blender\.blender\icons\blender's iconset.png"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path12825"
+ style="fill:url(#linearGradient13112);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:1.60044813;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.8412876,0,0,0.8414582,16.661932,139.91818)" />
+ <path
+ transform="matrix(0.654253,0,0,0.6543912,41.350498,161.99208)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient13114);stroke-width:2.28663301;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path27909"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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="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"
+ 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"
+ id="rect12049"
+ width="16"
+ height="16"
+ x="47.000004"
+ y="387" />
+ <g
+ transform="translate(-336.01611,233)"
+ id="g22979">
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 391.01611,155 -6.00001,2.125 0,7.65625 6.00001,3.21875 6,-3.21875 0,-7.65625 -6,-2.125 z"
+ id="path12053"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path12063"
+ d="m 397.01609,164.76992 0,-7.6298 -6,-2.14012 c 0,2.58362 8.3e-4,12.47266 8.3e-4,13.03976 l 5.99917,-3.26984 0,0 0,0 0,0 z"
+ style="fill:url(#linearGradient17712);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ 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="path12065"
+ d="m 385.01609,164.75 0,-7.5 6,-2.25 c 0,2.37037 0,12.47971 0,13 l -6,-3.25 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99989706;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="path12067"
+ d="m 385.01658,157.14012 6.00034,-2.17997 5.99917,2.17997 -5.99975,2.72493 -5.99976,-2.72493 z"
+ style="fill:#ffffff;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccc"
+ id="path12835"
+ d="m 385.01612,158 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,-0.5 -2,-0.5 0,1 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,1 2,1 0,-2 -2,0 z m -2,-2 0,-2 -2,0 0,2 2,0 z"
+ style="fill:#c81700;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient17714);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 385.51625,164.52217 0,-7.03525 5.49627,-2.01007 5.49628,2.01007 0,7.03525 -5.49628,3.01511 -5.49627,-3.01511 z"
+ id="path12069"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g23022"
+ 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"
+ id="rect23020"
+ width="16"
+ height="16"
+ x="343"
+ y="237" />
+ <g
+ id="g9430"
+ transform="translate(19.991123,0.02506982)"
+ style="display:inline">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path9432"
+ d="m 330.5,240.5 5,5 -5,5 -5,-5 5,-5 z"
+ style="fill:url(#linearGradient15436);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.85000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5"
+ inkscape:connector-curvature="0" />
+ <path
+ 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.5"
+ d="m 327,245.5 3.5,-3.5"
+ id="path9434"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g23028"
+ transform="translate(18.067322,-17)">
+ <rect
+ y="237"
+ x="322.93268"
+ height="16"
+ width="16"
+ id="rect23018"
+ 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"
+ transform="translate(0.04112278,0.02506982)"
+ id="g12077">
+ <path
+ style="fill:url(#linearGradient52027);fill-opacity:1;fill-rule:nonzero;stroke:#341b00;stroke-width:0.85000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5"
+ d="m 330.5,240.5 5,5 -5,5 -5,-5 5,-5 z"
+ id="path12079"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path12081"
+ d="m 327,245.5 3.5,-3.5"
+ 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.5"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g23056"
+ transform="translate(118,4)">
+ <rect
+ y="216"
+ x="181"
+ height="16"
+ width="16"
+ id="rect23010"
+ 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,1,1,0,-56.06114,-164)"
+ id="g13176"
+ 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">
+ <path
+ id="path13178"
+ d="m 392.53018,240.5312 -1,0 -4,3.9688 4,4.0312 1,0 0,-8 z"
+ style="opacity:0.2;fill:none;stroke:#ff982a;stroke-width:5;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="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ style="opacity:0.7;fill:none;stroke:#ff982a;stroke-width:3.5;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 392.5,240.5312 -1,0 -4,3.9688 4,4.0312 1,0 0,-8 z"
+ id="path13180"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path13182"
+ d="m 392.5,240.5312 -1,0 -4,3.9688 4,4.0312 1,0 0,-8 z"
+ style="fill:url(#linearGradient52023);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient13639);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"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path13184"
+ d="m 389,244.5 2.5,-2.5"
+ style="opacity:0.9;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g23048"
+ 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"
+ id="rect23012"
+ width="16"
+ height="16"
+ x="201"
+ y="215.03018" />
+ <g
+ transform="matrix(0,1,1,0,-35.015077,-166)"
+ id="g13216"
+ 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">
+ <path
+ id="path13218"
+ d="m 395.53018,243.5312 -4,-4 -9,4 9,4 4,-4 z"
+ style="opacity:0.2;fill:none;stroke:#ff982a;stroke-width:5;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="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="opacity:0.75;fill:none;stroke:#ff982a;stroke-width:3.5;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 395.5,243.5312 -4,-4 -9,4 9,4 4,-4 z"
+ id="path13220"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path13222"
+ d="m 391.5,239.5312 -9,4 9,4 4,-4 -4,-4 z"
+ style="fill:url(#linearGradient52025);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient14661);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"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path13224"
+ d="m 385,243.5312 6.25,-2.75"
+ style="opacity:0.85;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g23040"
+ transform="translate(36,4.96982)">
+ <rect
+ y="215.03018"
+ x="221"
+ height="16"
+ width="16"
+ id="rect23014"
+ 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"
+ 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="g13226"
+ transform="matrix(0,1,1,0,-15.015077,-166)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="opacity:0.2;fill:none;stroke:#ff982a;stroke-width:5;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 395.53018,243.5312 -4,-4 -9,4 9,4 4,-4 z"
+ id="path13228"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path13230"
+ d="m 395.53018,243.5312 -4,-4 -9,4 9,4 4,-4 z"
+ style="opacity:0.75;fill:none;stroke:#ff982a;stroke-width:3.5;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="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:url(#linearGradient15993);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient15995);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 391.5,239.5312 -9,4 9,4 4,-4 -4,-4 z"
+ id="path13232"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.85;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 385,243.5312 6.25,-2.75"
+ id="path13234"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g23034"
+ transform="translate(37,5)">
+ <rect
+ y="215"
+ x="241"
+ height="16"
+ width="16"
+ id="rect23016"
+ 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,1,1,0,4.9849228,-166)"
+ id="g13236"
+ 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">
+ <path
+ id="path13238"
+ d="m 391.5,239.5312 -9,4 9,4 4,-4 -4,-4 z"
+ style="fill:url(#linearGradient15997);fill-opacity:1;fill-rule:evenodd;stroke:#000000;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"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path13240"
+ d="m 385,243.5312 6.25,-2.75"
+ style="opacity:0.85;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g23114"
+ transform="translate(-81,46)">
+ <rect
+ y="174"
+ x="401"
+ height="16"
+ width="16"
+ id="rect23112"
+ 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"
+ 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="g11747"
+ transform="matrix(0,1,1,0,163.98492,-206)">
+ <path
+ sodipodi:nodetypes="cccccc"
+ style="fill:url(#linearGradient15854);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 392.5,240.5312 -1,0 -4,3.9688 4,4.0312 1,0 0,-8 z"
+ id="path11749"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 389,244.5 2.5,-2.5"
+ id="path11751"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g23160"
+ 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"
+ id="rect23130"
+ width="16"
+ height="16"
+ x="364"
+ y="195" />
+ <g
+ transform="translate(0.01612278,0)"
+ id="g10790"
+ style="display:inline">
+ <path
+ style="fill:url(#linearGradient15681);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 364.48388,198.5 0,9 1,0 5,-3.75 0,3.75 1,0 5.01612,-3.71875 0,3.71875 2,0 0,-9 -2,0 0,3.71875 -5.01612,-3.71875 -1,0 0,3.75 -5,-3.75 -1,0 z"
+ id="path10792"
+ sodipodi:nodetypes="ccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path10794"
+ d="m 365.48388,206.5 0,-6.75 4.25,3.25"
+ style="fill:none;stroke:url(#linearGradient11764);stroke-width:0.99999952px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient11762);stroke-width:0.99999952px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 371.48388,206.5 0,-6.75 4.5,3.25"
+ id="path10796"
+ sodipodi:nodetypes="ccc"
+ 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:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 377.23388,206.75 0.0161,-7.5"
+ id="path10798"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path11760"
+ d="m 377.98388,200 -1.25,0 0,-1 1.25,0 0,1 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g23168"
+ transform="translate(-315.95126,25)">
+ <rect
+ y="195"
+ x="382.95126"
+ height="16"
+ width="16"
+ id="rect23132"
+ 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.01597308,0.03124949)"
+ 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="g10800"
+ style="display:inline">
+ <g
+ id="g10802"
+ transform="matrix(-1,0,0,1,762.9688,2.086163e-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
+ style="fill:url(#linearGradient15683);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 365.53351,198.46875 -1,0 0,9 1,0 5,-3.75 0,3.75755 1,0 5.00539,-3.71875 0,3.71875 1.99461,0 0,-9 -1.99461,0 0,3.71875 -5.00539,-3.71875 -1,0 0,3.74245 -5,-3.75 z"
+ id="path10804"
+ sodipodi:nodetypes="ccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path10806"
+ d="m 369.28351,202.71875 -3.5,-2.75"
+ style="fill:none;stroke:#ffffff;stroke-width:1.39999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1.39999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 375.28351,202.71875 -3.5,-2.75"
+ id="path10808"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path10986"
+ d="m 377.03351,199.9763 1.25,0 0,-1 -1.25,0 0,1 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="cc"
+ id="path10810"
+ d="m 385.18529,206.7263 0,-7.5"
+ 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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g23154"
+ transform="translate(-317,25)">
+ <rect
+ y="195"
+ x="343"
+ height="16"
+ width="16"
+ id="rect23128"
+ 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="g10812"
+ transform="matrix(-2.196282,0,0,1.316799,1208.5661,-118.9575)"
+ 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="color:#000000;fill:url(#linearGradient37396-1);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.58802557px;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 392.96689,239.5639 -0.56915,0 -4.43932,4.36665 0,1.13912 4.43932,4.36665 0.56915,0 0,-9.87242 0,0 0,0 z"
+ id="path10814"
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient11766);stroke-width:0.58802563px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 392.51157,248.2972 0,-7.97389 -4.09783,3.98695"
+ id="path10816"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g23136"
+ 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"
+ id="rect23134"
+ width="16"
+ height="16"
+ x="283"
+ y="195" />
+ <g
+ transform="translate(0.01612278,0)"
+ id="g10818"
+ style="display:inline">
+ <g
+ id="g10820"
+ transform="translate(0,8)">
+ <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"
+ ry="1.9320945"
+ rx="0"
+ y="286.5"
+ x="189.49994"
+ height="3"
+ width="11.000029"
+ id="rect10822"
+ style="fill:url(#linearGradient15687);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ transform="matrix(0,1,1,0,0,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="path10824"
+ d="m 287.5,199.27782 0,-8.77775 1,-7e-5"
+ style="fill:none;stroke:url(#linearGradient15689);stroke-width:1.00000012px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(6,8)"
+ id="g10826">
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ style="fill:url(#linearGradient15691);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect10828"
+ width="11.000029"
+ height="3"
+ x="189.49994"
+ y="286.5"
+ rx="0"
+ ry="1.9320945"
+ 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
+ sodipodi:nodetypes="ccc"
+ style="fill:none;stroke:url(#linearGradient15693);stroke-width:1.00000012px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 287.5,199.27782 0,-8.77775 1,-7e-5"
+ id="path10830"
+ 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" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g23146"
+ 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"
+ id="rect23126"
+ width="16"
+ height="16"
+ x="323"
+ y="195" />
+ <g
+ style="display:inline"
+ id="g11898"
+ 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.714947,0,0,0.714947,237.35342,27.84315)">
+ <g
+ style="display:inline"
+ id="g11900"
+ 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">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path11903"
+ style="fill:url(#linearGradient13543);fill-opacity:1;fill-rule:nonzero;stroke:#552200;stroke-width:1.77777624;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.847956,0,0,0.858716,59.65221,121.6111)" />
+ </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.784039,0,0,0.779055,-3.508124,71.29625)"
+ id="g11905"
+ style="fill:none;stroke:url(#linearGradient15878);stroke-width:1.65010214;stroke-opacity:1;display:inline">
+ <path
+ transform="matrix(0.780492,0,0,0.786646,68.5413,130.1431)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient13545);stroke-width:2.28401804;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path11907"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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="g24423">
+ <rect
+ y="220"
+ x="131"
+ height="16"
+ width="16"
+ id="rect23008"
+ 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"
+ transform="translate(-71.046377,45.90625)"
+ 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="g11015">
+ <path
+ style="fill:url(#linearGradient15744);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 205.54638,177.59375 -1,0 0,9 1,0 5,-3.75 0,3.75 1,0 5,-3.75 0,-1.5 -5,-3.75 -1,0 0,3.75 -5,-3.75 z"
+ id="path11017"
+ sodipodi:nodetypes="ccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path11019"
+ d="m 205.54638,185.34375 0,-6.5 4.25,3.25"
+ style="fill:none;stroke:url(#linearGradient10982);stroke-width:1.10000002;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\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(#linearGradient10984);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 211.54638,185.34375 0,-6.5 4,3"
+ id="path11021"
+ sodipodi:nodetypes="ccc"
+ 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" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g23235"
+ 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"
+ id="rect23226"
+ width="16"
+ height="16"
+ x="184"
+ y="174" />
+ <g
+ style="display:inline"
+ 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,0,0,1,402.07862,-0.09375)"
+ id="g11023">
+ <path
+ id="path11025"
+ d="m 205.57862,177.59375 -1,0 0,9 1,0 5,-3.75 0,3.75 1,0 5,-3.75 0,-1.5 -5,-3.75 -1,0 0,3.75 -5,-3.75 z"
+ style="fill:url(#linearGradient15746);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"
+ sodipodi:nodetypes="ccccccccccccc"
+ 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:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 209.57862,181.84375 -4,-3"
+ id="path11027"
+ sodipodi:nodetypes="cc"
+ 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"
+ sodipodi:nodetypes="cc"
+ id="path11029"
+ d="m 215.57862,181.84375 -4,-3"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </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">
+ <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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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)" />
+ <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 1 1 -16,0 8,8 0 1 1 16,0 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"
+ sodipodi:type="arc"
+ transform="matrix(0.4812861,0,0,0.4822895,65.395173,166.1609)" />
+ </g>
+ </g>
+ <g
+ id="g16279"
+ transform="translate(318,7.00009)" />
+ <g
+ id="g28089"
+ transform="translate(0,2)">
+ <rect
+ y="260"
+ x="-315"
+ height="16"
+ width="16"
+ id="rect16267"
+ 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
+ id="g28079">
+ <g
+ id="g51539"
+ style="opacity:0.4">
+ <path
+ id="path51537"
+ d="m 300.5,270.5 5,4 0,1 2,0 0,-1 6,-4 1,0 0,-2 -2,0 0,1 -11,0 0,-1 -2,0 0,2 1,0 z"
+ style="fill:#ffffff;fill-opacity:0.70588235;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccccccccccccc"
+ d="m 299.5,268.5 0,2 2,10e-6 0,-2 -2,-10e-6 z m 13,0 0,2 2,10e-6 0,-2 -2,-10e-6 z m -7,4.99999 0,2 2,10e-6 0,-2 -2,-10e-6 z m 7,-3.99999 -11,0 m -0.75,1 4.75,3.878 m 2.08359,0.122 5.66641,-4"
+ style="fill:none;stroke:url(#linearGradient28077);stroke-width:0.99999952;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline"
+ id="path16283"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g28004"
+ transform="translate(501,-139)">
+ <path
+ id="path16269"
+ d="m -200,401 12,0 -6.4,7.99999 L -200,401 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#162d50;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="cccc"
+ 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="path16271"
+ d="m -199.75,401 11.75,0 -6.5,7.99999 L -199.75,401 z"
+ style="fill:url(#linearGradient28057);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ sodipodi:nodetypes="cccc"
+ 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\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ id="path16273"
+ d="m -189.5,401.5 -9.25,0 4.25,6.5"
+ style="opacity:0.87999998;fill:none;stroke:url(#linearGradient22970);stroke-width:1.00000036px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline"
+ id="rect16275"
+ width="2.0172491"
+ height="2.0328345"
+ x="-201.51724"
+ y="399.46716" />
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline"
+ id="rect16285"
+ width="2.0172396"
+ height="2.0000157"
+ x="-195.5"
+ y="408.49997" />
+ <rect
+ y="399.49997"
+ x="-188.51724"
+ height="2.0000157"
+ width="2.0172396"
+ id="rect16287"
+ style="fill:#d7e3f4;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline" />
+ </g>
+ </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"
+ 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"
+ id="rect28314"
+ width="16"
+ height="16"
+ x="-293.99997"
+ y="280.99994"
+ transform="scale(-1,1)" />
+ <g
+ id="g28424">
+ <g
+ id="g28320"
+ transform="translate(318.99999,17.49994)">
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ sodipodi:nodetypes="ccccc"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient24395);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -33,272.25 0,-7 6,2.75 0,7.25 -6,-3 z"
+ id="path28322"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path28324"
+ d="m -33,272.25 0,-7 6,2.75 0,7.25 -6,-3 z"
+ style="fill:url(#linearGradient28532);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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path28326"
+ d="m -27.25,274.75 0,-6.5 -5.5,-2.5 0,6.25"
+ style="fill:none;stroke:url(#linearGradient28530);stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g28414"
+ style="opacity:0.8"
+ transform="translate(0.25,0.25)">
+ <path
+ style="opacity:0.4;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.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"
+ d="m 280,285.25 5.5,-2.5"
+ id="path28410"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path28376"
+ d="m 280,285.25 5.5,-2.5"
+ style="fill:none;stroke:#ffc655;stroke-width:1px;stroke-linecap:round;stroke-linejoin:bevel;stroke-opacity:1;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="opacity:0.6"
+ id="g28418"
+ transform="translate(0,-7.5)">
+ <path
+ sodipodi:nodetypes="cc"
+ style="opacity:0.4;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.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"
+ d="m 286.5,296 5.5,-3"
+ id="path28420"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path28422"
+ d="m 286.5,296 5.5,-3"
+ style="fill:#ff8080;fill-rule:evenodd;stroke:#ffc655;stroke-width:1px;stroke-linecap:round;stroke-linejoin:bevel;stroke-opacity:1;display:inline"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:none;stroke:#0b1728;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 279.99999,292.9999 0,-7 6,2.75004 0,7.25 -6,-3.00004 z"
+ id="path28328"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g28402"
+ style="opacity:0.8">
+ <path
+ id="path28398"
+ d="m 286.5,296 5.5,-3"
+ style="opacity:0.4;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.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"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:#ff8080;fill-rule:evenodd;stroke:#ffc655;stroke-width:1px;stroke-linecap:round;stroke-linejoin:bevel;stroke-opacity:1;display:inline"
+ d="m 286.5,296 5.5,-3"
+ id="path28374"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-161.00001,168.99994)"
+ id="g28338">
+ <g
+ id="g28340">
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ id="path28342"
+ d="m 441,123.99996 0,-7 6,2.75004 0,7.25 -6,-3.00004 z"
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:#162d50;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path28344"
+ d="m 441.00001,124.00006 0,-7 6,2.74994 c 0,2.37037 0,6.72971 0,7.25 l -6,-2.99994 z"
+ style="fill:url(#linearGradient28474);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.09488797;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
+ style="fill:#22467e;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 441,117 0,2.25 2,0 0,-1.25 -2,-1 z m 2,2 0,2 2,0 0,-2 -2,0 z m 2,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,1.25 2,1 0,-2.25 -2,0 z m -2,-2 0,-2 -2,0 0,2 2,0 z"
+ id="path28346"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path28348"
+ d="m 446.75,126.5 0,-6.5 -5.5,-2.5 0,6.25 5.5,2.75 z"
+ style="fill:none;stroke:url(#linearGradient28528);stroke-width:0.75;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>
+ </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"
+ style="display:inline">
+ <rect
+ y="-183"
+ x="563"
+ height="16"
+ width="16"
+ id="rect12620"
+ 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="g12622">
+ <g
+ transform="translate(476.04566,-283.51773)"
+ id="g12624"
+ style="opacity:0.7">
+ <path
+ style="fill:none;stroke:#1a1a1a;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"
+ d="m 89.95451,104.01774 5,9.5 5,-9.5 -10,0 z"
+ id="path12626"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path12628"
+ d="m 89.95451,103.98095 5,9.5 5,-9.5 -10,0 z"
+ style="fill:none;stroke:#cccccc;stroke-width:1.5;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>
+ <rect
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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="rect12630"
+ width="2.9998772"
+ height="3"
+ x="574.50031"
+ y="-181.49998"
+ ry="1.4999386"
+ rx="1.4999386" />
+ <rect
+ rx="1.4999386"
+ ry="1.4999386"
+ y="-181.49998"
+ x="564.50043"
+ height="3"
+ width="2.9998772"
+ id="rect12632"
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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:#000000;stroke-width:1.5;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="rect12634"
+ width="2.9998772"
+ height="3"
+ x="569.5"
+ y="-171.5"
+ ry="1.4999386"
+ rx="1.4999386" />
+ <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="path12636"
+ d="m 577.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:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 572.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="path12638"
+ 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;display:inline"
+ d="m 567.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="path12640"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <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"
+ transform="translate(-21,128)">
+ <rect
+ y="302"
+ x="-231"
+ height="16"
+ width="16"
+ id="rect12012"
+ 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
+ id="g12045">
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="opacity:0.9;fill:#552200;fill-opacity:1;fill-rule:evenodd;stroke:#2b1600;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 218,313.25 c -0.99997,-6.5 5.99997,-2.75 4.99994,-9.25 l 5.00003,2 c 1,7 -6,2 -5,10 L 218,313.25 z"
+ id="path12014"
+ 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"
+ id="path12016"
+ d="m 218,313.25 c -0.99997,-6.5 5.99997,-3.25 4.99994,-9.25 l 5.00003,2 c 1,7 -6,2 -5,10 L 218,313.25 z"
+ style="opacity:0.95;fill:#ff9f37;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:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="opacity:0.75;fill:url(#radialGradient12116);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.88812488px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 218,313.25 c -0.99997,-6.5 5.99997,-3.25 4.99994,-9.25 l 5.00003,2 c 1,7 -6,2 -5,10 L 218,313.25 z"
+ id="path12020"
+ 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"
+ id="path12018"
+ d="m 218,313.25 c -0.99997,-6.5 5.99997,-3.25 4.99994,-9.25 l 5.00003,2 c 1,7 -6,2 -5,10 L 218,313.25 z"
+ style="opacity:0.7;fill:url(#linearGradient12114);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.88812488px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ style="opacity:0.75;fill:none;stroke:url(#linearGradient12118);stroke-width:1;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 223.24994,304.5 4.25003,1.75 c 1,5.75 -5.50003,2 -5.08025,8.84783 l -4.04773,-2.23212"
+ id="path12022"
+ 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"
+ id="path12024"
+ d="m 223.24994,304.5 4.25003,1.75"
+ style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1;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"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g12219"
+ transform="translate(-20.999998,128)">
+ <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="rect12147"
+ width="16.000032"
+ height="16"
+ x="-231.00003"
+ y="281" />
+ <g
+ transform="translate(235.00016,-1)"
+ id="g12149">
+ <g
+ id="g12151"
+ transform="translate(-376,510)"
+ style="opacity:0.8">
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ id="path12153"
+ d="m 358.99997,-216.75 c -0.99997,-6.5 6.00003,-2.75 5,-9.25 L 369,-224 c 1,7 -6,2 -5,10 l -5.00003,-2.75 z"
+ style="fill:none;stroke:#1a1a1a;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:#b3b3b3;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 358.99997,-216.75 C 358,-223.25 365,-220 363.99997,-226 L 369,-224 c 1,7 -6,2 -5,10 l -5.00003,-2.75 z"
+ id="path12155"
+ 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"
+ style="opacity:0.7;fill:url(#linearGradient12213);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.88812488px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M 358.99997,-216.75 C 358,-223.25 365,-220 363.99997,-226 L 369,-224 c 1,7 -6,2 -5,10 l -5.00003,-2.75 z"
+ id="path12157"
+ 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"
+ id="path12159"
+ d="M 358.99997,-216.75 C 358,-223.25 365,-220 363.99997,-226 L 369,-224 c 1,7 -6,2 -5,10 l -5.00003,-2.75 z"
+ style="opacity:0.75;fill:url(#radialGradient12215);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.88812488px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccc"
+ 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="path12161"
+ d="m 364.24984,-225.5 4.25016,1.75 c 1,5.75 -5.50003,2 -5.08381,8.85761 l -4.04561,-2.26888"
+ style="fill:none;stroke:url(#linearGradient12217);stroke-width:1;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"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;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 364.24997,-225.5 4.25003,1.75"
+ id="path12163"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-399.2499,383.75)"
+ id="g12165">
+ <rect
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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="rect12167"
+ width="2.9998772"
+ height="3"
+ x="391.75"
+ y="-99.25"
+ ry="1.4999387"
+ rx="1.4999387" />
+ <path
+ style="fill:#ffffff;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 394.24987,-98.75 c -0.66667,0 -1.33332,1e-5 -2,1e-5 0,0.66939 0,1.33877 0,2.00817 0.66668,0 1.33333,-10e-6 2,-10e-6 0,-0.66939 0,-1.33878 0,-2.00817 z"
+ id="path12169"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g12171"
+ transform="translate(-406.2499,380.75)">
+ <rect
+ rx="1.4999387"
+ ry="1.4999387"
+ y="-98.25"
+ x="392.74988"
+ height="3"
+ width="2.9998772"
+ id="rect12173"
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path12175"
+ d="m 395.24974,-97.75 c -0.66667,0 -1.33332,1e-5 -2,1e-5 0,0.666663 0,1.333317 0,1.99999 0.66668,0 1.33333,-1e-5 2,-1e-5 0,-0.666663 0,-1.333327 0,-1.99999 z"
+ style="fill:#ffffff;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" />
+ </g>
+ <path
+ style="opacity:0.3;fill:#ffffff;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 -11.00003,286 c -0.66668,0 -1.33332,0 -2,0 0,-0.33334 0,-0.66666 0,-1 0.66668,0 1.33332,0 2,0 0,0.33334 0,0.66667 0,1 z"
+ id="path12177"
+ 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="path12179"
+ d="m -7.00003,285.53933 c -0.33334,0 -0.66666,10e-6 -1,10e-6 0,0.82281 0,1.64561 0,2.46844 0.33334,0 0.66666,-1e-5 1,-1e-5 0,-0.82282 0,-1.64562 0,-2.46844 l 0,0 0,0 0,0 z"
+ style="opacity:0.3;fill:#ffffff;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
+ 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="path12187"
+ d="m -9.972188,286 c -0.342621,0 -0.685221,0 -1.027842,0 0,-0.66873 0,-1.33742 0,-2.00616 0.342621,0 0.685221,0 1.027842,0 0,0.66874 0,1.33745 0,2.00616 z"
+ style="opacity:0.3;fill:#ffffff;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.3;fill:#ffffff;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 -6.000162,287 c -0.33334,0 -0.66666,0 -1,0 0,0.33428 0,0.66856 0,1.00284 0.33334,0 0.66666,0 1,0 0,-0.33428 0,-0.66856 0,-1.00284 z"
+ id="path12239"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ 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"
+ transform="translate(0,2)">
+ <rect
+ y="260"
+ x="257"
+ height="16"
+ width="16"
+ id="rect28219"
+ style="opacity:0;fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999875;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g24279">
+ <rect
+ transform="matrix(1,5.257811e-6,0,1,0,0)"
+ y="261.49863"
+ x="258.5"
+ height="7.007431"
+ width="6.9999733"
+ id="rect28121"
+ style="fill:url(#linearGradient24272);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.89999998;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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <g
+ id="g12274"
+ transform="translate(6.2265309e-7,0.00746971)">
+ <g
+ style="opacity:0.4"
+ id="g11480"
+ transform="matrix(1,0,0,-0.985055,81.000076,281.63418)">
+ <rect
+ transform="matrix(1,-5.3375811e-6,0,-1,0,0)"
+ y="-14.357183"
+ x="183.49992"
+ height="7.1213336"
+ width="7.000011"
+ id="rect11482"
+ style="fill:url(#linearGradient12305);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00755596;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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.00755763px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 184.49992,8.2651727 0,5.0306663 5,0.04519"
+ id="path11484"
+ 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="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(1,0,0,-0.985055,78.000075,278.62671)"
+ id="g11472">
+ <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"
+ style="fill:url(#linearGradient12307);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.90680158;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;display:inline"
+ id="rect11474"
+ width="6.9999948"
+ height="7.1137514"
+ x="183.49992"
+ y="-14.349599"
+ transform="matrix(1,-5.3375811e-6,0,-1,0,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="path11476"
+ d="m 184.49993,8.3103653 -1e-5,5.0230827 5,0"
+ style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.00755763px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <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"
+ style="fill:url(#linearGradient24277);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;display:inline"
+ id="rect24275"
+ width="6.8437233"
+ height="6.8198147"
+ x="258.65625"
+ y="261.68613"
+ transform="matrix(1,5.257811e-6,0,1,0,0)" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient24268);stroke-width:1.00000036px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 259.5,267.5 0,-5 5,0 0,5 -5,0 z"
+ id="path28123"
+ 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
+ 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="path12295"
+ d="m 266.5,265.5 0,3.94801 -4,0"
+ style="opacity:0.2;fill:none;stroke:#162d50;stroke-width:1.00000036px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ 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)" />
+ <g
+ id="g17375"
+ 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"
+ inkscape:export-ydpi="90"
+ style="display:inline">
+ <rect
+ style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="rect17377"
+ width="16"
+ height="16"
+ x="162.99997"
+ y="237.5" />
+ <g
+ transform="translate(73,-319.5)"
+ id="g17379"
+ style="fill:#ffcc00;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;display:inline">
+ <path
+ style="fill:none;stroke:#2b1600;stroke-width:1.20000005;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -169,233 0,1 1,0 0,10 -1,0 0,1 4,0 0,-1 -1,0 0,-4 3,0 0,1 1,0 0,-3 -1,0 0,1 -3,0 0,-5 5,0 0,1 1,0 0,-2 -8,0 -1,0 z"
+ transform="translate(262.99997,326)"
+ id="rect17381"
+ sodipodi:nodetypes="cccccccccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="fill:#ffcc00;display:inline"
+ id="g17395"
+ transform="translate(73,-319.5)">
+ <path
+ style="fill:url(#linearGradient13699)"
+ d="m -169,233 0,1 1,0 0,10 -1,0 0,1 4,0 0,-1 -1,0 0,-4 3,0 0,1 1,0 0,-3 -1,0 0,1 -3,0 0,-5 5,0 0,1 1,0 0,-2 -8,0 -1,0 z"
+ id="rect17397"
+ sodipodi:nodetypes="cccccccccccccccccccccccc"
+ transform="translate(262.99997,326)"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="opacity:0.85;fill:#ffffff;display:inline"
+ d="m 198,304 0,1 0.5,0 0,-1 -0.5,0 z m 1,1 0,10 0.65625,0 0,-10 L 199,305 z m 7,0 0,1 0.5,0 0,-1 -0.5,0 z m -2,4 0,1 0.5,0 0,-1 -0.5,0 z m 0,2 0,1 0.5,0 0,-1 -0.5,0 z m -6,4 0,1 0.5,0 0,-1 -0.5,0 z"
+ id="path17411"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccc"
+ transform="translate(-31.000031,-64.5)"
+ 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"
+ transform="translate(289,331.00001)">
+ <rect
+ y="183"
+ x="-158"
+ height="16"
+ width="16"
+ id="rect14146"
+ 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(36,0)"
+ id="g14148">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path14151"
+ d="m -187,192 4,-4"
+ style="fill:none;stroke:#162d50;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ d="m -191,198 0.76562,0.21876 4.73438,-4.71876 0,-3 -3,0 -4,4 -0.75,0.75 0.25,0.75 2,2 z"
+ style="fill:url(#linearGradient14167);fill-opacity:1;fill-rule:evenodd;stroke:#162d50;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path14153"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path14155"
+ d="m -190.5,197.5 -2,-2"
+ style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccccccc"
+ id="path14157"
+ d="m -179.48388,187.51562 c 2.75,-1.75 -1.25,-5.75 -3,-3 L -183,186.5 l -1.48388,0.0156 -0.26612,0.73438 -0.73388,0.26562 0.98388,-0.0156 0,1 1,1 1,0 0.0161,1.01562 0.23388,-0.76562 0.76612,-0.23438 L -181.5,188 l 2.01612,-0.48438 z"
+ style="fill:url(#linearGradient14169);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient14171);stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -186.5,191.5 2,-2"
+ id="path14159"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient14173);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m -180,187.5 c 2.49911,-1.20238 -0.79146,-5.05796 -2.25,-2.75 l -0.75,1.75 -1.25,0.25 -0.75,0.75 2.75,2.75 0.75,-1 0,-1.25 1.5,-0.5 z"
+ id="path14161"
+ sodipodi:nodetypes="ccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path14163"
+ d="M -180.23388,184.53124 C -181.75937,183.83967 -182,185 -182.5,186.75 l -1.98388,0.53124"
+ style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ style="opacity:0.85;fill:none;stroke:#ffffff;stroke-width:0.60000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -192.5,195.5 4.26612,-4.23438 1.75,0 2,-2"
+ id="path14165"
+ inkscape:connector-curvature="0" />
+ </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"
+ 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="rect17322"
+ width="16"
+ height="16"
+ x="47"
+ y="29" />
+ <g
+ transform="translate(116,-325)"
+ id="g17324">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path17326"
+ d="m -55,358.25 -6,-2.25 -6,2.25 0,7.5 6,3.25 6,-3.25 0,-7.5 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path17328"
+ d="m -55,365.75 0,-7.5 -6,2.75 c 0,2.58363 8.34e-4,7.47325 8.34e-4,8.04035 L -55,365.75 z"
+ style="fill:url(#linearGradient17337);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
+ sodipodi:nodetypes="ccccc"
+ style="fill:#c9c9c9;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m -67,365.75 0,-7.5 6,2.75 8.34e-4,8.04035 L -67,365.75 z"
+ id="path17330"
+ 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="path17332"
+ d="m -67,358.25 6,-2.25 6,2.25 -6,2.75 -6,-2.75 z"
+ style="fill:#ffffff;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient17339);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M -66.499841,365.52276 -66.5,358.5 l 5.5,-2 5.5,2 0,7 -5.5,3 -5.499841,-2.97724 z"
+ id="path17334"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g17610"
+ transform="translate(-20.999893,190.97867)"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ y="281.02133"
+ x="193.99989"
+ height="16"
+ width="16"
+ id="rect17612"
+ 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="g17614">
+ <rect
+ y="285.52133"
+ x="198.49976"
+ height="2"
+ width="8"
+ id="rect17616"
+ style="fill:none;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ transform="translate(191.9999,212.02134)"
+ id="g17618"
+ style="display:inline">
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:url(#linearGradient17656);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 16.499049,83.47866 -12.999056,0 -10e-8,-12.97866 13.0114221,0 -0.01237,12.97866 4e-6,0 z"
+ id="path17620"
+ 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" />
+ </g>
+ <rect
+ style="fill:none;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect17622"
+ width="8"
+ height="2"
+ x="198.49976"
+ y="289.52136" />
+ <rect
+ y="283"
+ x="195.99989"
+ height="12"
+ width="12.000107"
+ id="rect17624"
+ style="opacity:0.1;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g17626"
+ transform="translate(-31.00024,484.0498)">
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 237.5,-198.52846 0,1 -8.99987,0"
+ id="path17628"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path17630"
+ d="m 228.55567,-198.51423 8.88878,0"
+ style="fill:none;stroke:#4d4d4d;stroke-width:0.99999994px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g17632"
+ transform="translate(-16.999997,0.9739989)">
+ <rect
+ transform="scale(-1,1)"
+ style="fill:#d7e3f4;fill-opacity:1;fill-rule:evenodd;stroke:#5f8dd3;stroke-width:0.99999982;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="rect17634"
+ width="2"
+ height="3.0120413"
+ x="-253.5"
+ y="-200.474" />
+ <path
+ id="path17636"
+ d="m 251.49999,-197.47154 2,0 0,-3"
+ style="opacity:0.45;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 251.99999,-196.47154 2.5,0 0,-3.5"
+ id="path17638"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g17640"
+ transform="translate(-31.00024,484.0498)">
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path17642"
+ d="m 237.5,-192.60425 0,1 -8.99987,0.026"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#4d4d4d;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 228.50013,-192.60425 8.99987,0.026"
+ id="path17644"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g17646"
+ transform="translate(-19.014593,0.97154)">
+ <rect
+ y="-194.51543"
+ x="-251.5"
+ height="2.9940825"
+ width="2.0000002"
+ id="rect17648"
+ style="fill:#d7e3f4;fill-opacity:1;fill-rule:evenodd;stroke:#5f8dd3;stroke-width:0.99999994;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="scale(-1,1)" />
+ <path
+ id="path17650"
+ d="m 249.49999,-191.52134 2,0 0,-3"
+ style="opacity:0.45;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path17652"
+ d="m 250.01459,-190.52134 2.5,0 0,-3.5"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <path
+ 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="path17654"
+ d="m 196.4999,294.5 0.0303,-11 11.01349,0 -0.0303,11 -11.01349,0 z"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient17658);stroke-width:0.99999976px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g13494"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ transform="translate(0,128.00001)">
+ <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"
+ style="fill:#e6e6e6;fill-opacity:0.23529412;fill-rule:nonzero;stroke:none"
+ id="rect16876"
+ width="8.0127983"
+ height="8.012805"
+ x="260.99997"
+ y="473.98718"
+ ry="0.4193894"
+ rx="0.4193894" />
+ <rect
+ ry="0.82841855"
+ y="473.48724"
+ x="260.50003"
+ height="9.0127392"
+ width="9.0127354"
+ id="rect16878"
+ style="opacity:0.3;fill:none;stroke:url(#linearGradient12658);stroke-width:1.00002468;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"
+ rx="0.82841796" />
+ <rect
+ rx="0.80560946"
+ 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="opacity:0.4;fill:none;stroke:url(#linearGradient12655);stroke-width:1.00002468;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect16880"
+ width="9.0127354"
+ height="9.0127392"
+ x="-269.51276"
+ y="-482.5"
+ ry="0.83038348"
+ transform="scale(-1,-1)" />
+ </g>
+ <g
+ id="g28870"
+ 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"
+ transform="translate(0,128.00001)">
+ <g
+ transform="translate(20.999991,0)"
+ id="g13503">
+ <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"
+ style="fill:#e6e6e6;fill-opacity:0.23529412;fill-rule:nonzero;stroke:none"
+ id="rect13505"
+ width="8.0127983"
+ height="8.012805"
+ x="260.99997"
+ y="473.98718"
+ ry="0.4193894"
+ rx="0.4193894" />
+ <rect
+ ry="0.82841855"
+ y="473.48724"
+ x="260.50003"
+ height="9.0127392"
+ width="9.0127354"
+ id="rect13507"
+ style="opacity:0.3;fill:none;stroke:url(#linearGradient13511);stroke-width:1.00002468;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"
+ rx="0.82841796" />
+ <rect
+ rx="0.80560946"
+ 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="opacity:0.4;fill:none;stroke:url(#linearGradient13513);stroke-width:1.00002468;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect13509"
+ width="9.0127354"
+ height="9.0127392"
+ x="-269.51276"
+ y="-482.5"
+ ry="0.83038348"
+ transform="scale(-1,-1)" />
+ </g>
+ <path
+ d="m 283.5,478.5 1.99999,2 m 3.75,-4.75 c -1.28654,1.14367 -2.78042,2.75628 -3.75,4.75"
+ style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="path16507"
+ 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" />
+ <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 a 2.7944512,2.7944512 0 1 1 -5.5889,0 2.7944512,2.7944512 0 1 1 5.5889,0 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 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 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 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="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" />
+ </g>
+ </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"
+ 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="rect18695"
+ width="16"
+ height="16"
+ x="236"
+ y="260" />
+ <g
+ id="g18697"
+ 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"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path18719"
+ 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(#linearGradient18721);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"
+ transform="translate(179,-179)">
+ <path
+ id="path18707"
+ d="m 146.0019,73.295281 5,-1.894157 5,1.894157 -5,2.073959 -5,-2.073959 z"
+ style="fill:url(#linearGradient18728);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"
+ d="m 335,-105.5 -5,2 0,6.75 5,-2.75 0,-6 z"
+ style="fill:url(#linearGradient18765);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path18709"
+ 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(#linearGradient18712);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path18758"
+ 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"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g14548"
+ transform="translate(0,23)">
+ <rect
+ y="239"
+ x="152"
+ height="16"
+ width="16"
+ id="rect14326"
+ 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="g14538">
+ <path
+ sodipodi:nodetypes="css"
+ id="path14330"
+ d="m 155.51612,249.67445 c 0,3.70073 8,3.70073 8,0 0,-2.71386 -4,-1.727 -4,-5.67444"
+ style="fill:none;stroke:#0b1728;stroke-width:3.0999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(0.8675713,0,0,-1.199958,80.598976,391.9948)"
+ d="m 93.25,125 a 1.75,1.25 0 1 1 -3.5,0 1.75,1.25 0 1 1 3.5,0 z"
+ sodipodi:ry="1.25"
+ sodipodi:rx="1.75"
+ sodipodi:cy="125"
+ sodipodi:cx="91.5"
+ id="path14332"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:#0b1728;stroke-width:2.74424219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ sodipodi:type="arc" />
+ <path
+ style="fill:none;stroke:url(#linearGradient14568);stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ d="m 155.51612,249.75002 c 0,3.75 8,3.75 8,0 0,-2.75 -4,-1.75 -4,-5.75"
+ id="path14334"
+ sodipodi:nodetypes="css"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#000000;fill-opacity:1;stroke:url(#linearGradient14570);stroke-width:1.28417933;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="path14336"
+ sodipodi:cx="91.5"
+ sodipodi:cy="125"
+ sodipodi:rx="1.75"
+ sodipodi:ry="1.25"
+ d="m 93.25,125 a 1.75,1.25 0 1 1 -3.5,0 1.75,1.25 0 1 1 3.5,0 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 a 1.75,1.25 0 1 1 -3.5,0 1.75,1.25 0 1 1 3.5,0 z"
+ sodipodi:ry="1.25"
+ sodipodi:rx="1.75"
+ sodipodi:cy="125"
+ sodipodi:cx="91.5"
+ id="path14338"
+ style="fill:none;stroke:url(#linearGradient14572);stroke-width:1.28417933;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ sodipodi:type="arc" />
+ <rect
+ y="241"
+ x="158.99884"
+ height="2"
+ width="2.0011597"
+ id="rect14340"
+ style="opacity:0.75;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" />
+ <path
+ sodipodi:nodetypes="cs"
+ id="path14342"
+ d="m 155.95084,249.59135 c 0,3.34488 7.13055,3.34488 7.13055,0"
+ style="opacity:0.45;fill:none;stroke:#ffffff;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(349,127.99988)"
+ id="g26256">
+ <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"
+ width="16"
+ height="16"
+ x="-29"
+ y="491.00012" />
+ <g
+ id="g26260">
+ <g
+ id="g26262">
+ <path
+ sodipodi:nodetypes="cc"
+ d="M -15.594023,497.94339 -20.25,493.5"
+ style="fill:none;stroke:#28170b;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.34386529;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path26264"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(3.625,0,0,3.1690202,-67.8125,318.31703)"
+ d="m 14.5,57.5 a 1,1.0000004 0 1 1 -2,0 1,1.0000004 0 1 1 2,0 z"
+ sodipodi:ry="1.0000004"
+ sodipodi:rx="1"
+ sodipodi:cy="57.5"
+ sodipodi:cx="13.5"
+ id="path26266"
+ style="fill:none;stroke:#28170b;stroke-width:1.32768786;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.10397505;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ id="path26268"
+ style="fill:none;stroke:#28170b;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.34386529;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -25.5,496.5 7.5,0 m -9.5,6 6,-6"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ transform="matrix(3.5999897,0,0,3.1249932,-67.499871,320.6879)"
+ d="m 14.5,57.5 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="57.5"
+ sodipodi:cx="13.5"
+ id="path26270"
+ style="fill:none;stroke:url(#linearGradient26282);stroke-width:0.92424375;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.10397505;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ d="m -25.5,496.5 7.984366,-0.0226 M -27.5,502.5 l 6,-6 m 5.996227,1.44466 L -20.25,493.5"
+ style="fill:none;stroke:url(#linearGradient26284);stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.34386529;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path26272"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path26274"
+ sodipodi:cx="13.5"
+ sodipodi:cy="57.5"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 14.5,57.5 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 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 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="57.5"
+ sodipodi:cx="13.5"
+ id="path26276"
+ style="fill:#2c5aa0;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient26286);stroke-width:0.22536004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.10397505;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path26278"
+ sodipodi:cx="13.5"
+ sodipodi:cy="57.5"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 14.5,57.5 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ transform="matrix(4.7519907,0,0,4.1435313,-83.051884,262.12196)" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ d="m -20.515634,493.80534 c -0.07079,-0.45769 0.0843,-0.63855 0.5,-0.5 m -7.704183,9.08552 4.25,-4.25 m -2,-2 6.25,0"
+ style="fill:none;stroke:url(#linearGradient26288);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ id="path26280"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g15201"
+ 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"
+ id="rect15183"
+ width="16"
+ height="16"
+ x="215"
+ y="365" />
+ <g
+ id="g15185"
+ transform="translate(167.99999,-62.999991)">
+ <rect
+ y="429.54614"
+ x="48.499996"
+ height="12.953857"
+ width="13.016124"
+ id="rect15187"
+ style="fill:#ececec;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(#linearGradient15195);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00207269;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect15189"
+ width="11.000001"
+ height="11.046139"
+ x="50.016117"
+ y="430" />
+ <path
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccc"
+ id="path15191"
+ d="m 49,430 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,0 0,3 3,0 0,-3 -3,0 z m 0,3 -3,0 0,3 3,0 0,-3 z m 0,3 0,3 3,0 0,-3 -3,0 z m -3,0 -3,0 0,3 3,0 0,-3 z m -3,0 0,-3 -3,0 0,3 3,0 z"
+ style="fill:url(#linearGradient15209);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" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path15193"
+ d="m 60.517703,430.5 -11.017704,0 0,11 11.017704,0 0,-11"
+ style="fill:none;stroke:url(#linearGradient15211);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(-174.00091,22.99815)"
+ id="g15532" />
+ <g
+ id="g15356"
+ transform="translate(-21,128.00001)">
+ <rect
+ y="344"
+ x="89"
+ height="16"
+ width="16"
+ id="rect15319"
+ 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="g15351">
+ <rect
+ y="345.50153"
+ x="90.5"
+ height="12.998481"
+ width="13"
+ id="rect15323"
+ style="fill:url(#linearGradient15363);fill-opacity:1;fill-rule:nonzero;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: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
+ sodipodi:nodetypes="ccc"
+ id="path15326"
+ d="m 91.499805,357.49999 0,-10.99829 11.000195,0 0,10.99829 -11.000195,0 z"
+ style="fill:none;stroke:url(#linearGradient15365);stroke-width:0.99999982px;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"
+ 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"
+ sodipodi:nodetypes="cszzcc"
+ id="path15332"
+ d="m 103.5,353.27516 c -0.37083,-1.1875 -1.21031,-1.72293 -1.9,-1.72929 -1.39235,-0.0134 -1.47709,3.98814 -2.999997,4 -1.491657,0.0119 -2.001315,-7 -3.5,-7 -1.52993,-10e-4 -1.18608,5.00645 -3.5,4.97929 l -1,0"
+ style="fill:none;stroke:url(#linearGradient15367);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ inkscape:export-ydpi="90"
+ 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">
+ <rect
+ y="237.5"
+ x="162.99997"
+ height="16"
+ width="16"
+ id="rect15371"
+ style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" />
+ <g
+ style="fill:#ffcc00;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;display:inline"
+ id="g15373"
+ transform="translate(73,-319.5)">
+ <path
+ sodipodi:nodetypes="cccccccccccccccccccccccc"
+ id="path15375"
+ transform="translate(262.99997,326)"
+ d="m -169,233 0,1 1,0 0,10 -1,0 0,1 4,0 0,-1 -1,0 0,-4 3,0 0,1 1,0 0,-3 -1,0 0,1 -3,0 0,-5 5,0 0,1 1,0 0,-2 -8,0 -1,0 z"
+ style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(73,-319.5)"
+ id="g15377"
+ style="fill:#ffcc00;display:inline">
+ <path
+ sodipodi:nodetypes="cccccccccccccccccccccccc"
+ id="path15379"
+ transform="translate(262.99997,326)"
+ d="m -169,233 0,1 1,0 0,10 -1,0 0,1 4,0 0,-1 -1,0 0,-4 3,0 0,1 1,0 0,-3 -1,0 0,1 -3,0 0,-5 5,0 0,1 1,0 0,-2 -8,0 -1,0 z"
+ style="fill:url(#linearGradient15383)"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ transform="translate(-31.000031,-64.5)"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccc"
+ id="path15381"
+ d="m 198,304 0,1 0.5,0 0,-1 -0.5,0 z m 1,1 0,10 0.65625,0 0,-10 L 199,305 z m 7,0 0,1 0.5,0 0,-1 -0.5,0 z m -2,4 0,1 0.5,0 0,-1 -0.5,0 z m 0,2 0,1 0.5,0 0,-1 -0.5,0 z m -6,4 0,1 0.5,0 0,-1 -0.5,0 z"
+ style="opacity:0.85;fill:#ffffff;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g14355"
+ transform="translate(0,128.00001)">
+ <rect
+ y="428"
+ x="68"
+ height="16"
+ width="16"
+ id="rect14357"
+ 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="g14359"
+ 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="translate(-15.161301,338)"
+ style="display:inline">
+ <path
+ sodipodi:nodetypes="czszcccc"
+ id="path14368"
+ 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:7.40000034;display:inline"
+ d="m 86.5,100.53983 4.342131,0.008 c 5.188235,0.0101 5.335295,-2.04831 3.335293,-4.04831 -0.964875,-0.964875 -4.5,-4 1.500002,-5 M 88.840543,97.588774 86.5,100.53983 M 88.828993,103.5 86.5,100.53983"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 86.5,100.53983 4.342131,0.008 C 96.03037,100.55844 96.17743,98.5 94.177424,96.5 c -0.964875,-0.964875 -4.5,-4 1.500002,-5 M 88.840543,97.588774 86.5,100.53983 M 88.828993,103.5 86.5,100.53983"
+ style="fill:none;stroke:url(#linearGradient14377);stroke-width:1.50000143;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000034;display:inline"
+ id="path14375"
+ sodipodi:nodetypes="czszcccc"
+ inkscape:connector-curvature="0" />
+ </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"
+ 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"
+ id="rect16520"
+ width="16"
+ height="16"
+ x="110"
+ y="492"
+ rx="0"
+ ry="0" />
+ <g
+ id="g16522">
+ <rect
+ ry="1.7356256"
+ y="494.5"
+ x="110.5"
+ height="12"
+ width="15"
+ id="rect16524"
+ style="fill:url(#linearGradient16638);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
+ sodipodi:nodetypes="ccccccccc"
+ id="path16527"
+ d="M 111,498.48148 111,504 c 0,0.56404 0.36784,1.00001 0.84375,1 l 12.3125,0 C 124.63216,505 125,504.56405 125,504 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(#linearGradient16640);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="rect16530"
+ width="15"
+ height="2"
+ x="110.5"
+ y="494.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="rect16532"
+ width="15"
+ height="12"
+ x="110.5"
+ y="494.5"
+ ry="1.503511"
+ rx="1.503511" />
+ <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="path16535"
+ 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(1.3955004,0,0,1.2452423,11.18333,-121.72474)" />
+ <rect
+ rx="0.5078125"
+ ry="0.4910686"
+ y="495.5"
+ x="111.5"
+ height="10"
+ width="13.000001"
+ id="rect16537"
+ 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 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="path16540"
+ 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="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient16642);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="path16542"
+ 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(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 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="path16544"
+ 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(#linearGradient16644);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="path16546"
+ 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.790122,0,0,0.787736,57.870479,107.05649)" />
+ <g
+ id="g16548"
+ transform="matrix(0.7547901,0,0,1,59.021765,-1)">
+ <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="path16550"
+ 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.7901234,0,0,0.2000006,9.8760061,395.5997)" />
+ <path
+ sodipodi:nodetypes="csccc"
+ id="path16554"
+ 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="rect16556"
+ width="2.6497433"
+ height="1"
+ x="70.189362"
+ y="495" />
+ </g>
+ <rect
+ y="496.5"
+ x="122"
+ height="1.5"
+ width="2"
+ id="rect16558"
+ 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(#radialGradient16646);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect16562"
+ width="2"
+ height="1.5"
+ x="122"
+ y="496.5" />
+ <rect
+ y="497"
+ x="115"
+ height="1"
+ width="1"
+ id="rect16564"
+ 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" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#radialGradient16648);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="path16566"
+ 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(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 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="path16568"
+ style="fill:url(#radialGradient16650);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
+ 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="path16570"
+ 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.1975308,0,0,0.1999991,103.0926,401.10045)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.7;fill:url(#radialGradient32447);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.98985863;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path32441"
+ 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.8867575,0.06148883,-0.06130315,-0.8840797,219.44126,941.51187)" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g21847"
+ transform="translate(24,422.99999)"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ style="opacity:0;fill:#ffaaaa;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect21291"
+ width="16"
+ height="16"
+ x="464"
+ y="7"
+ rx="0"
+ ry="0" />
+ <g
+ id="g21822">
+ <rect
+ ry="1.5909902"
+ y="10.5"
+ x="465.5"
+ height="10"
+ width="12"
+ id="rect21295"
+ style="fill:url(#linearGradient21776);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ rx="1.5909902" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path21297"
+ d="m 465.46685,13.40909 0,4.59375 c 0,0.56244 0.34142,0.99717 0.78315,0.99716 l 10.5,0.01065 c 0.44173,0 0.78315,-0.43471 0.78315,-0.99716 l 0,-4.59375 c -0.29118,0.37073 -0.71398,0.59091 -1.16022,0.59091 L 466.62707,14 c -0.44624,0 -0.86904,-0.22018 -1.16022,-0.59091 l 0,0 0,0 0,0 z"
+ style="fill:url(#linearGradient21773);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.362712"
+ 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="rect21299"
+ width="12"
+ height="2.0056314"
+ x="465.5"
+ y="10.494369"
+ ry="1.0028157" />
+ <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="rect21301"
+ width="12"
+ height="10"
+ x="465.5"
+ y="10.5"
+ ry="1.3782184"
+ rx="1.3782184" />
+ <rect
+ rx="0.39062494"
+ ry="0.44196323"
+ y="11.5"
+ x="466.5"
+ height="7.999999"
+ width="9.9998779"
+ id="rect21303"
+ 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="g21305"
+ transform="matrix(0.7547901,0,0,1,414.01868,-484.99999)">
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:#999999;stroke-width:2.90780973;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="path21307"
+ 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.7834486,0,0,0.2000006,10.413535,395.5997)" />
+ <path
+ sodipodi:nodetypes="csccc"
+ id="path21309"
+ d="m 69.531013,495.51105 0,-0.50001 c 0,-0.276 0.890314,-0.5 1.987308,-0.5 1.096993,0 1.987307,0.224 1.987307,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="rect21311"
+ width="2.6497409"
+ height="1"
+ x="70.193451"
+ y="495.01105" />
+ </g>
+ <g
+ transform="matrix(1,0,0,0.6666667,331,-319.00002)"
+ id="g21313">
+ <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="rect21315"
+ width="2"
+ height="1.5"
+ x="143"
+ y="496.5" />
+ <rect
+ y="496.5"
+ x="143"
+ height="1.5"
+ width="2"
+ id="rect21317"
+ style="fill:url(#radialGradient21741);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <rect
+ y="13"
+ x="468"
+ height="1"
+ width="1"
+ id="rect21319"
+ 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" />
+ <g
+ id="g21804"
+ 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 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="path21323"
+ style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.89240623;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.25;fill:none;stroke:#000000;stroke-width:0.71801031;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="path21325"
+ 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(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 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="path21327"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient21814);stroke-width:1.11641002;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:1.00804472;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="path21329"
+ 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.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 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="path21331"
+ style="fill:none;stroke:url(#linearGradient21816);stroke-width:1.69505489;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(0.9913883,0,0,1.0058976,394.67318,-488.46061)"
+ 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="path21333"
+ style="fill:none;stroke:url(#radialGradient21818);stroke-width:0.80110824;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:url(#radialGradient21820);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path21335"
+ 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.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 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="path21337"
+ style="opacity:0.2;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" />
+ <path
+ transform="matrix(-0.6760501,-0.1575078,0.1570322,-0.6740085,446.07727,367.34791)"
+ 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="path22185"
+ style="opacity:0.7;fill:url(#radialGradient22187);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
+ style="opacity:0.05;fill:none;stroke:#ffffff;stroke-width:0.99999982;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 476.49997,11.941967 0,7.174103"
+ id="rect21642"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(45,422.99999)"
+ id="g22102"
+ style="opacity:0.25;display:inline">
+ <rect
+ ry="0"
+ rx="0"
+ y="7"
+ x="464"
+ height="16"
+ width="16"
+ id="rect22104"
+ style="opacity:0;fill:#ffaaaa;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g22106">
+ <rect
+ style="fill:url(#linearGradient22154);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22108"
+ width="12"
+ height="10"
+ x="465.5"
+ y="10.5"
+ ry="1.5909902"
+ rx="1.5909902" />
+ <path
+ style="fill:url(#linearGradient22156);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 465,13.40909 0,4.59375 c 0,0.56244 0.36784,0.99717 0.84375,0.99716 l 11.3125,0.01065 c 0.47591,0 0.84375,-0.43471 0.84375,-0.99716 l 0,-4.59375 c -0.31371,0.37073 -0.76923,0.59091 -1.25,0.59091 L 466.25,14 c -0.48077,0 -0.93629,-0.22018 -1.25,-0.59091 l 0,0 0,0 0,0 z"
+ id="path22110"
+ sodipodi:nodetypes="ccccccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ ry="1"
+ y="10.494369"
+ x="465"
+ height="2"
+ width="13"
+ id="rect22112"
+ 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.4762714" />
+ <rect
+ ry="1.3782184"
+ y="10.5"
+ x="465.5"
+ height="10"
+ width="12"
+ id="rect22114"
+ style="fill:none;stroke:#000000;stroke-width:1;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"
+ rx="1.3782184" />
+ <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="rect22116"
+ width="9.9998779"
+ height="7.999999"
+ x="466.5"
+ y="11.5"
+ ry="0.44196323"
+ rx="0.39062494" />
+ <g
+ transform="matrix(0.7547901,0,0,1,414.01868,-484.99999)"
+ id="g22118">
+ <path
+ transform="matrix(0.7834486,0,0,0.2000006,10.413535,395.5997)"
+ 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="path22120"
+ style="fill:none;stroke:#999999;stroke-width:2.90780973;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
+ 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.531013,495.51105 0,-0.50001 c 0,-0.276 0.890314,-0.5 1.987308,-0.5 1.096993,0 1.987307,0.224 1.987307,0.5 l 0,0.50001"
+ id="path22122"
+ sodipodi:nodetypes="csccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="495.01105"
+ x="70.193451"
+ height="1"
+ width="2.6497409"
+ id="rect22124"
+ 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
+ id="g22126"
+ transform="matrix(1,0,0,0.6666667,331,-319.00002)">
+ <rect
+ y="496.5"
+ x="143"
+ height="1.5"
+ width="2"
+ id="rect22128"
+ 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(#radialGradient22158);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22130"
+ width="2"
+ height="1.5"
+ x="143"
+ y="496.5" />
+ </g>
+ <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="rect22132"
+ width="1"
+ height="1"
+ x="468"
+ y="13" />
+ <g
+ transform="translate(1.1408497e-7,0.5000446)"
+ id="g22134">
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.89240623;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="path22136"
+ 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(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 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="path22138"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.71801031;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:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient22160);stroke-width:1.11641002;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="path22140"
+ 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.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 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="path22142"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#b3b3b3;stroke-width:1.00804472;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(#linearGradient22162);stroke-width:1.69505489;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="path22144"
+ 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.591154,0,0,0.5887513,425.87219,-279.05319)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#radialGradient22164);stroke-width:0.80110824;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="path22146"
+ 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.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 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="path22148"
+ style="fill:url(#radialGradient22166);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
+ 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="path22150"
+ 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.1975308,0,0,0.1999991,456.07844,-84.89955)" />
+ </g>
+ <path
+ sodipodi:nodetypes="cc"
+ id="path22152"
+ d="m 476.49997,11.941967 0,7.174103"
+ style="opacity:0.05;fill:none;stroke:#ffffff;stroke-width:0.99999982;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(-272,478.06251)"
+ id="g30185"
+ style="opacity:0.98000004;display:inline"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ y="-48"
+ x="403"
+ height="16"
+ width="16"
+ id="rect30187"
+ 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" />
+ <path
+ transform="matrix(1.3340954,0,0,1.3333333,-178.16901,-188.16667)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:#2b1600;stroke-width:0.74978584;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path30189"
+ sodipodi:cx="443.5"
+ sodipodi:cy="108.5"
+ sodipodi:rx="3"
+ sodipodi:ry="3"
+ d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z" />
+ <path
+ d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z"
+ sodipodi:ry="3"
+ sodipodi:rx="3"
+ sodipodi:cy="108.5"
+ sodipodi:cx="443.5"
+ id="path30191"
+ style="fill:none;stroke:#2b1600;stroke-width:0.74978584;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ transform="matrix(1.3340954,0,0,1.3333333,-184.1736,-187.16666)" />
+ <path
+ d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z"
+ sodipodi:ry="3"
+ sodipodi:rx="3"
+ sodipodi:cy="108.5"
+ sodipodi:cx="443.5"
+ id="path30193"
+ style="fill:url(#linearGradient24132);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.85464907;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ transform="matrix(1.1662469,0,0,1.1666676,-103.72925,-170.08344)" />
+ <path
+ sodipodi:nodetypes="cccccccccccccccccc"
+ id="path30195"
+ d="m 409.5,-39.50001 -2,2.000003 -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 -4,-1e-5 0,0 0,0 0,0 z"
+ style="fill:#f89a35;fill-opacity:1;fill-rule:nonzero;stroke:#2b1600;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:open="true"
+ sodipodi:end="8.1340281"
+ sodipodi:start="3.0449434"
+ transform="matrix(1.0812107,0,0,1.082338,-66.018179,-160.93645)"
+ sodipodi:type="arc"
+ style="opacity:0.98000004;fill:none;stroke:url(#linearGradient30231);stroke-width:0.92440742;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path30197"
+ sodipodi:cx="443.5"
+ sodipodi:cy="108.5"
+ sodipodi:rx="3"
+ sodipodi:ry="3"
+ d="m 440.514,108.7895 a 3,3 0 1 1 2.1568,2.59363" />
+ <path
+ transform="matrix(1.1662469,0,0,1.1666676,-109.73384,-169.08343)"
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient30233);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.85464907;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path30199"
+ sodipodi:cx="443.5"
+ sodipodi:cy="108.5"
+ sodipodi:rx="3"
+ sodipodi:ry="3"
+ d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z" />
+ <path
+ sodipodi:open="true"
+ sodipodi:end="5.930273"
+ sodipodi:start="0.96146912"
+ d="m 445.21695,110.9601 a 3,3 0 1 1 1.09816,-3.497"
+ sodipodi:ry="3"
+ sodipodi:rx="3"
+ sodipodi:cy="108.5"
+ sodipodi:cx="443.5"
+ id="path30201"
+ style="opacity:0.98000004;fill:none;stroke:url(#linearGradient30235);stroke-width:0.9380942;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ transform="matrix(1.0655819,0,0,1.0664004,-65.085308,-158.20716)" />
+ <rect
+ y="-41"
+ x="409"
+ height="2.0000005"
+ width="4.0000658"
+ id="rect30203"
+ style="fill:#c8955e;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(0.3352674,0,0,0.3357219,258.80309,-78.928541)"
+ sodipodi:type="arc"
+ style="opacity:0.98000004;fill:none;stroke:url(#linearGradient30237);stroke-width:2.98067403;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path30205"
+ sodipodi:cx="443.5"
+ sodipodi:cy="108.5"
+ sodipodi:rx="3"
+ sodipodi:ry="3"
+ d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z" />
+ <rect
+ y="-43"
+ x="407"
+ height="1.0000002"
+ width="1"
+ 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 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z"
+ sodipodi:ry="3"
+ sodipodi:rx="3"
+ sodipodi:cy="108.5"
+ sodipodi:cx="443.5"
+ id="path30209"
+ style="opacity:0.98000004;fill:none;stroke:url(#linearGradient30239);stroke-width:2.98067403;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ transform="matrix(0.3352674,0,0,0.3357219,264.80311,-79.91866)" />
+ <rect
+ 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"
+ id="rect30211"
+ width="1"
+ height="1.0000002"
+ x="413.00003"
+ y="-43.99012" />
+ <rect
+ y="-37"
+ x="413"
+ height="2"
+ width="3.99542"
+ id="rect30213"
+ style="fill:url(#linearGradient30241);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000024;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path30215"
+ d="m 416.49542,-37 1.5,-1 0,4 -1.5,-1 0,-2 z"
+ style="fill:url(#linearGradient30243);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000024;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path30217"
+ d="m 415.99542,-37 1,-0.5 0,3 -1,-0.5 0,-2 z"
+ style="fill:url(#linearGradient30245);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" />
+ <path
+ style="fill:url(#linearGradient30247);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 413,-37 1,0 0,2 -1,0 0,-2 z"
+ id="path30219"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path30221"
+ d="m 409.75,-38.5 2.75,0 0,4 -4,0 0,-2.75 1.25,-1.25 z"
+ style="fill:#ec8f2c;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient30249);stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <rect
+ ry="1.2544428"
+ y="-37.821297"
+ x="407"
+ height="2.6761446"
+ width="2.8293107"
+ id="rect30223"
+ style="opacity:0.6;fill:none;stroke:url(#linearGradient20217);stroke-width:1.00000024;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"
+ rx="1.2544428" />
+ <rect
+ style="fill:#ffdbb5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000024;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect30225"
+ width="3"
+ height="1"
+ x="406"
+ y="-37.000008" />
+ <rect
+ style="fill:#634321;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect30227"
+ width="4"
+ height="1"
+ x="409"
+ y="-40" />
+ </g>
+ <g
+ style="opacity:0.98000004;display:inline"
+ id="g30282"
+ 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"
+ id="rect30284"
+ width="16"
+ height="16"
+ x="403"
+ y="-48" />
+ <path
+ d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z"
+ sodipodi:ry="3"
+ sodipodi:rx="3"
+ sodipodi:cy="108.5"
+ sodipodi:cx="443.5"
+ id="path30286"
+ style="fill:none;stroke:#000000;stroke-width:0.74978584;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ transform="matrix(1.3340954,0,0,1.3333333,-178.16901,-188.16667)" />
+ <path
+ transform="matrix(1.3340954,0,0,1.3333333,-184.1736,-187.16666)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:#000000;stroke-width:0.74978584;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path30288"
+ sodipodi:cx="443.5"
+ sodipodi:cy="108.5"
+ sodipodi:rx="3"
+ sodipodi:ry="3"
+ d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z" />
+ <path
+ transform="matrix(1.1662469,0,0,1.1666676,-103.72925,-170.08344)"
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient30326);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.85464907;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path30290"
+ sodipodi:cx="443.5"
+ sodipodi:cy="108.5"
+ sodipodi:rx="3"
+ sodipodi:ry="3"
+ d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 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"
+ id="path30292"
+ sodipodi:nodetypes="cccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 440.514,108.7895 a 3,3 0 1 1 2.1568,2.59363"
+ sodipodi:ry="3"
+ sodipodi:rx="3"
+ sodipodi:cy="108.5"
+ sodipodi:cx="443.5"
+ id="path30294"
+ style="opacity:0.98000004;fill:none;stroke:url(#linearGradient30328);stroke-width:0.92440742;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ transform="matrix(1.0812107,0,0,1.082338,-66.018179,-160.93645)"
+ sodipodi:start="3.0449434"
+ sodipodi:end="8.1340281"
+ sodipodi:open="true" />
+ <path
+ d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z"
+ sodipodi:ry="3"
+ sodipodi:rx="3"
+ sodipodi:cy="108.5"
+ sodipodi:cx="443.5"
+ id="path30296"
+ style="fill:url(#linearGradient30330);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.85464907;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ transform="matrix(1.1662469,0,0,1.1666676,-109.73384,-169.08343)" />
+ <path
+ transform="matrix(1.0655819,0,0,1.0664004,-65.085308,-158.20716)"
+ sodipodi:type="arc"
+ style="opacity:0.98000004;fill:none;stroke:url(#linearGradient30332);stroke-width:0.9380942;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path30298"
+ sodipodi:cx="443.5"
+ sodipodi:cy="108.5"
+ sodipodi:rx="3"
+ sodipodi:ry="3"
+ d="m 445.21695,110.9601 a 3,3 0 1 1 1.09816,-3.497"
+ sodipodi:start="0.96146912"
+ sodipodi:end="5.930273"
+ sodipodi:open="true" />
+ <rect
+ style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect30300"
+ width="4.0000658"
+ height="2.0000005"
+ x="409"
+ y="-41" />
+ <path
+ d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z"
+ sodipodi:ry="3"
+ sodipodi:rx="3"
+ sodipodi:cy="108.5"
+ sodipodi:cx="443.5"
+ id="path30302"
+ style="opacity:0.98000004;fill:none;stroke:url(#linearGradient30334);stroke-width:2.98067403;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ transform="matrix(0.3352674,0,0,0.3357219,258.80309,-78.928541)" />
+ <rect
+ style="fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect30304"
+ width="1"
+ height="1.0000002"
+ x="407"
+ y="-43" />
+ <path
+ transform="matrix(0.3352674,0,0,0.3357219,264.80311,-79.91866)"
+ sodipodi:type="arc"
+ style="opacity:0.98000004;fill:none;stroke:url(#linearGradient30336);stroke-width:2.98067403;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path30306"
+ sodipodi:cx="443.5"
+ sodipodi:cy="108.5"
+ sodipodi:rx="3"
+ sodipodi:ry="3"
+ d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z" />
+ <rect
+ y="-43.99012"
+ x="413.00003"
+ height="1.0000002"
+ width="1"
+ id="rect30308"
+ style="fill:#333333;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(#linearGradient30338);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000024;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect30310"
+ width="3.99542"
+ height="2"
+ x="413"
+ y="-37" />
+ <path
+ style="fill:url(#linearGradient30340);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000024;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 416.49542,-37 1.5,-1 0,4 -1.5,-1 0,-2 z"
+ id="path30312"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient30342);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 415.99542,-37 1,-0.5 0,3 -1,-0.5 0,-2 z"
+ id="path30314"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path30316"
+ d="m 413,-37 1,0 0,2 -1,0 0,-2 z"
+ style="fill:url(#linearGradient30344);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" />
+ <path
+ style="fill:none;stroke:url(#linearGradient30346);stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 409.75,-38.5 2.75,0 0,4 -4,0 0,-2.75 1.25,-1.25 z"
+ id="path30318"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.6;fill:none;stroke:url(#linearGradient30348);stroke-width:1.00000024;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"
+ id="rect30320"
+ width="2.8293107"
+ height="2.6761446"
+ x="407"
+ y="-37.821297"
+ ry="1.2544428"
+ rx="1.2544428" />
+ <rect
+ y="-37.000008"
+ x="406"
+ height="1"
+ width="3"
+ id="rect30322"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000024;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="-40"
+ x="409"
+ height="1"
+ width="4"
+ id="rect30324"
+ 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>
+ <g
+ style="opacity:0.98000004;display:inline"
+ id="g30350"
+ 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"
+ id="rect30352"
+ width="16"
+ height="16"
+ x="403"
+ y="-48" />
+ <path
+ d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z"
+ sodipodi:ry="3"
+ sodipodi:rx="3"
+ sodipodi:cy="108.5"
+ sodipodi:cx="443.5"
+ id="path30354"
+ style="fill:none;stroke:#000000;stroke-width:0.74978584;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ transform="matrix(1.3340954,0,0,1.3333333,-178.16901,-188.16667)" />
+ <path
+ transform="matrix(1.3340954,0,0,1.3333333,-184.1736,-187.16666)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:#000000;stroke-width:0.74978584;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path30356"
+ sodipodi:cx="443.5"
+ sodipodi:cy="108.5"
+ sodipodi:rx="3"
+ sodipodi:ry="3"
+ d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z" />
+ <path
+ transform="matrix(1.1662469,0,0,1.1666676,-103.72925,-170.08344)"
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient30394);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.85464907;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path30358"
+ sodipodi:cx="443.5"
+ sodipodi:cy="108.5"
+ sodipodi:rx="3"
+ sodipodi:ry="3"
+ d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 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"
+ id="path30360"
+ sodipodi:nodetypes="cccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 440.514,108.7895 a 3,3 0 1 1 2.1568,2.59363"
+ sodipodi:ry="3"
+ sodipodi:rx="3"
+ sodipodi:cy="108.5"
+ sodipodi:cx="443.5"
+ id="path30362"
+ style="opacity:0.98000004;fill:none;stroke:url(#linearGradient30396);stroke-width:0.92440742;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ transform="matrix(1.0812107,0,0,1.082338,-66.018179,-160.93645)"
+ sodipodi:start="3.0449434"
+ sodipodi:end="8.1340281"
+ sodipodi:open="true" />
+ <path
+ d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z"
+ sodipodi:ry="3"
+ sodipodi:rx="3"
+ sodipodi:cy="108.5"
+ sodipodi:cx="443.5"
+ id="path30364"
+ style="fill:url(#linearGradient30398);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.85464907;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ transform="matrix(1.1662469,0,0,1.1666676,-109.73384,-169.08343)" />
+ <path
+ transform="matrix(1.0655819,0,0,1.0664004,-65.085308,-158.20716)"
+ sodipodi:type="arc"
+ style="opacity:0.98000004;fill:none;stroke:url(#linearGradient30400);stroke-width:0.9380942;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path30366"
+ sodipodi:cx="443.5"
+ sodipodi:cy="108.5"
+ sodipodi:rx="3"
+ sodipodi:ry="3"
+ d="m 445.21695,110.9601 a 3,3 0 1 1 1.09816,-3.497"
+ sodipodi:start="0.96146912"
+ sodipodi:end="5.930273"
+ sodipodi:open="true" />
+ <rect
+ style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect30368"
+ width="4.0000658"
+ height="2.0000005"
+ x="409"
+ y="-41" />
+ <path
+ d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z"
+ sodipodi:ry="3"
+ sodipodi:rx="3"
+ sodipodi:cy="108.5"
+ sodipodi:cx="443.5"
+ id="path30370"
+ style="opacity:0.98000004;fill:none;stroke:url(#linearGradient30402);stroke-width:2.98067403;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ transform="matrix(0.3352674,0,0,0.3357219,258.80309,-78.928541)" />
+ <rect
+ style="fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect30372"
+ width="1"
+ height="1.0000002"
+ x="407"
+ y="-43" />
+ <path
+ transform="matrix(0.3352674,0,0,0.3357219,264.80311,-79.91866)"
+ sodipodi:type="arc"
+ style="opacity:0.98000004;fill:none;stroke:url(#linearGradient30404);stroke-width:2.98067403;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path30374"
+ sodipodi:cx="443.5"
+ sodipodi:cy="108.5"
+ sodipodi:rx="3"
+ sodipodi:ry="3"
+ d="m 446.5,108.5 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z" />
+ <rect
+ y="-43.99012"
+ x="413.00003"
+ height="1.0000002"
+ width="1"
+ id="rect30376"
+ style="fill:#333333;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(#linearGradient30406);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000024;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect30378"
+ width="3.99542"
+ height="2"
+ x="413"
+ y="-37" />
+ <path
+ style="fill:url(#linearGradient30408);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000024;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 416.49542,-37 1.5,-1 0,4 -1.5,-1 0,-2 z"
+ id="path30380"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient30410);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 415.99542,-37 1,-0.5 0,3 -1,-0.5 0,-2 z"
+ id="path30382"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path30384"
+ d="m 413,-37 1,0 0,2 -1,0 0,-2 z"
+ style="fill:url(#linearGradient30412);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" />
+ <path
+ style="fill:none;stroke:url(#linearGradient30414);stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 409.75,-38.5 2.75,0 0,4 -4,0 0,-2.75 1.25,-1.25 z"
+ id="path30386"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.6;fill:none;stroke:url(#linearGradient30416);stroke-width:1.00000024;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"
+ id="rect30388"
+ width="2.8293107"
+ height="2.6761446"
+ x="407"
+ y="-37.821297"
+ ry="1.2544428"
+ rx="1.2544428" />
+ <rect
+ y="-37.000008"
+ x="406"
+ height="1"
+ width="3"
+ id="rect30390"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000024;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="-40"
+ x="409"
+ height="1"
+ width="4"
+ 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)">
+ <g
+ id="g17368"
+ transform="translate(16,-32)">
+ <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(#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" />
+ <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" />
+ </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"
+ transform="translate(9.471,32.00923)">
+ <rect
+ y="-22.009235"
+ x="226.52901"
+ height="16"
+ width="16"
+ id="rect17382"
+ 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="-20.509235"
+ x="228.04515"
+ height="13"
+ width="12.983856"
+ id="rect17384"
+ style="fill:url(#linearGradient32749);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" />
+ <rect
+ transform="translate(271.529,-379.00923)"
+ style="fill:url(#linearGradient32751);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect17387"
+ width="12"
+ height="12"
+ x="-43"
+ y="359"
+ mask="url(#mask17570)" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path17389"
+ d="m 240.029,-19.509225 -10.98386,0 0,11.0000002 10.98384,-10e-6 0,-11.0000002"
+ style="fill:none;stroke:url(#linearGradient32753);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" />
+ </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"
+ 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"
+ id="rect18439"
+ width="16"
+ height="16"
+ x="-124"
+ y="325"
+ rx="0"
+ ry="0" />
+ <g
+ transform="translate(-11,154.99966)"
+ id="g18441"
+ style="opacity:0.7">
+ <g
+ transform="translate(-99,-97.999673)"
+ id="g18443"
+ style="display:inline">
+ <g
+ transform="translate(41.011415,162)"
+ style="display:inline"
+ id="g18445">
+ <g
+ transform="translate(-80,-48)"
+ id="g18447">
+ <path
+ style="fill:#d7d7d7;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;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 36.488585,166.3823 -0.25,1.1177 -9.499995,0 -1.25,-1.25 -5e-6,-10.75 11,0 0,10.8823 z"
+ id="path18449"
+ 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
+ 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="path18451"
+ d="m 34.988585,166.00001 -8,0 0,-1.00001 8,0 0,1.00001 z"
+ style="fill:#4d4d4d;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
+ 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="path18453"
+ d="m 35.47469,156.50008 -8.986105,-8e-5 5e-6,10 8.999995,0 -0.01389,-9.99992 -5e-6,0 0,0 0,0 z"
+ style="fill:none;stroke:url(#linearGradient17177);stroke-width:0.99999923px;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="ccccc"
+ inkscape:connector-curvature="0" />
+ <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"
+ y="165.00002"
+ x="27.988585"
+ height="1.0000023"
+ width="1"
+ id="rect18455"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ transform="matrix(1,0,0,-1,0,320)"
+ id="g18457"
+ style="fill:#ee0000;fill-opacity:1" />
+ </g>
+ </g>
+ </g>
+ <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="path18459"
+ d="m -101,181 -10,0 0,-8 10,0 0,8 z"
+ style="opacity:0.5;fill:url(#radialGradient17179);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-11,154.99966)"
+ id="g18461">
+ <g
+ id="g18463"
+ transform="translate(-347,193.00032)">
+ <path
+ sodipodi:nodetypes="ccccccccccccsccc"
+ style="fill:#e1e1e1;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 246.5,-15.5 c -1.65264,0 -3,1.347359 -3,3 l 0,2 c 0,1.6526411 1.34737,3 3,3 l 0,0 c 1.65264,0 3,-1.3473589 3,-3 l -0.0312,-1.96875 c 0,-1.652641 -1.31612,-3.03125 -2.96875,-3.03125 l 0,0 -5e-5,0 z m 0,2 c 0.554,0 1,0.446 1,1 l 0,2 c 0,0.554 -0.446,1 -1,1 -0.554,0 -1,-0.446 -1,-1 l 0,-2 c 0,-0.554 0.446,-1 1,-1 z"
+ id="path18465"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path18467"
+ d="m 246.5,-19.5 c -1.65264,0 -3,1.347359 -3,3 l 0,2 c 0,1.652641 1.34737,3 3,3 l 0,0 c 1.65264,0 3,-1.347359 3,-3 l 0,-2 c 0,-1.652641 -1.34737,-3 -3,-3 l 0,0 z m 0,2 c 0.554,0 1,0.446 1,1 l 0,2 c 0,0.554 -0.446,1 -1,1 -0.554,0 -1,-0.446 -1,-1 l 0,-2 c 0,-0.554 0.446,-1 1,-1 z"
+ style="fill:url(#radialGradient17181);fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccccccccsccc"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(6,0)"
+ clip-path="url(#clipPath17188)"
+ id="path18473"
+ d="m 240.5,-15.5 c -1.65264,0 -3,1.347359 -3,3 l 0,2 c 0,1.6526411 1.34737,3 3,3 l 0,0 c 1.65264,0 3,-1.3473589 3,-3 l -0.0312,-1.96875 c 0,-1.652641 -1.31612,-3.03125 -2.96875,-3.03125 l 0,0 -5e-5,0 z m 0,2 c 0.554,0 1,0.446 1,1 l 0,2 c 0,0.554 -0.446,1 -1,1 -0.554,0 -1,-0.446 -1,-1 l 0,-2 c 0,-0.554 0.446,-1 1,-1 z"
+ style="fill:#d3d7cf;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccccccccsccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="-14.06875"
+ x="244"
+ height="2.5"
+ width="1"
+ id="rect18475"
+ style="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" />
+ <rect
+ style="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"
+ id="rect18477"
+ width="1"
+ height="1"
+ x="245"
+ y="-15.06875" />
+ </g>
+ <g
+ id="g18479" />
+ </g>
+ </g>
+ <g
+ id="g18489"
+ transform="translate(287,-54.93125)">
+ <g
+ id="g18491"
+ transform="translate(0,-3.2e-4)"
+ style="opacity:0.7">
+ <g
+ style="display:inline"
+ id="g18493"
+ transform="translate(-79,-97.999673)">
+ <g
+ id="g18495"
+ style="display:inline"
+ transform="translate(41.011415,162)">
+ <g
+ id="g18497"
+ transform="translate(-80,-48)">
+ <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"
+ id="path18499"
+ d="m 36.488585,166.3823 -0.25,1.1177 -9.499995,0 -1.25,-1.25 -5e-6,-10.75 11,0 0,10.8823 z"
+ style="fill:#d7d7d7;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;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:#4d4d4d;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 34.988585,165.99999 -8,0 0,-1 8,0 0,1 z"
+ id="path18501"
+ 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"
+ style="fill:none;stroke:url(#linearGradient23914);stroke-width:0.99999923px;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 35.47469,156.50008 -8.986105,-8e-5 5e-6,10 8.999995,0 -0.01389,-9.99992 -5e-6,0 0,0 0,0 z"
+ id="path18503"
+ 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:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect18505"
+ width="1"
+ height="1.000007"
+ x="27.988585"
+ y="165"
+ 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="fill:#ee0000;fill-opacity:1"
+ id="g18507"
+ transform="matrix(1,0,0,-1,0,320)" />
+ </g>
+ </g>
+ </g>
+ <g
+ transform="translate(-157,18.000328)"
+ style="opacity:0.5"
+ id="g18509">
+ <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="path18511"
+ d="m 76,164 -10,0 0,-9 10,0 0,9 z"
+ style="opacity:0.8;fill:url(#radialGradient23916);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#radialGradient23918);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 76,164 -10,0 0,-9 10,0 0,9 z"
+ id="path18513"
+ 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" />
+ </g>
+ </g>
+ <g
+ id="g18515"
+ transform="translate(0,-3.2e-4)">
+ <g
+ id="g18517">
+ <g
+ transform="translate(-360,181.00032)"
+ id="g18519"
+ mask="url(#mask13041)">
+ <path
+ id="path18521"
+ d="m 279.46875,-11.53125 c -1.65264,0 -2.96875,1.316109 -2.96875,2.96875 l 0,1.0625 c 0,1.6526411 1.31612,2.96875 2.96875,2.96875 l 0.0625,0 c 1.65264,0 2.96875,-1.3161089 2.96875,-2.96875 l 0,-1.0625 c 0,-1.652641 -1.31612,-2.96875 -2.96875,-2.96875 l -0.0625,0 z M 279.5,-9.5 c 0.554,0 1,0.446 1,1 l 0,1 c 0,0.554 -0.446,1 -1,1 -0.554,0 -1,-0.446 -1,-1 l 0,-1 c 0,-0.554 0.446,-1 1,-1 z"
+ style="fill:#dcdcdc;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccccccccsccc"
+ mask="none"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="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"
+ id="rect18523"
+ width="1"
+ height="2.5"
+ x="277"
+ y="-10" />
+ <rect
+ y="-11"
+ x="278"
+ height="1"
+ width="1"
+ id="rect18525"
+ style="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" />
+ </g>
+ <g
+ id="g18527"
+ transform="translate(-360,191.06282)"
+ mask="url(#mask13052)">
+ <path
+ sodipodi:nodetypes="ccccccccccccsccc"
+ style="fill:#dcdcdc;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 279.46875,-11.53125 c -1.65264,0 -2.96875,1.316109 -2.96875,2.96875 l 0,1.0625 c 0,1.6526411 1.31612,2.96875 2.96875,2.96875 l 0.0625,0 c 1.65264,0 2.96875,-1.3161089 2.96875,-2.96875 l 0,-1.0625 c 0,-1.652641 -1.31612,-2.96875 -2.96875,-2.96875 l -0.0625,0 z M 279.5,-9.5 c 0.554,0 1,0.446 1,1 l 0,1 c 0,0.554 -0.446,1 -1,1 -0.554,0 -1,-0.446 -1,-1 l 0,-1 c 0,-0.554 0.446,-1 1,-1 z"
+ id="path18529"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="-10"
+ x="277"
+ height="2.5"
+ width="1"
+ id="rect18531"
+ style="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" />
+ <rect
+ style="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"
+ id="rect18533"
+ width="1"
+ height="1"
+ x="278"
+ y="-11" />
+ </g>
+ </g>
+ <g
+ id="g18535" />
+ </g>
+ </g>
+ <g
+ id="g18658"
+ transform="translate(-147.04123,1.9815)">
+ <rect
+ y="71.018501"
+ x="383.04123"
+ height="16"
+ width="16"
+ id="rect18661"
+ 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="g18663">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient18682);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 397.54124,84.25 -1.25,1.25 -10.5,0 -1.24999,-1.25 0,-11.75 12.99999,0 0,11.75 z"
+ id="path18665"
+ 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="path18667"
+ d="m 396.04123,84.0185 -10,0 0,-1.0185 10,0 0,1.0185 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" />
+ <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"
+ y="83.018501"
+ x="387.04123"
+ height="0.99999702"
+ width="0.99998772"
+ id="rect18671"
+ style="fill:#e6e6e6;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(-39.85994,-165.9815)"
+ id="g18674">
+ <path
+ sodipodi:nodetypes="csssccc"
+ d="m 430.24956,241.60271 -0.86957,2.62878 c -1.04667,3.16416 -1.3885,3.86937 -2.40118,2.64949 -0.37662,-0.45369 -1.31958,0.42592 -0.85102,0.66654 2.9195,1.49927 3.83448,-0.99495 4.73215,-3.56602 l 0.75,-2.37879 -1.36038,0 0,0 0,0 0,0 z"
+ id="path18676"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 430.33455,240.97335 c -0.77131,0.0353 -1.46745,0.21844 -2.3658,0.6829 -0.74329,0.3843 -1.31497,1.26096 -1.28125,1.75 0.0247,0.35816 0.29068,0.65625 0.65625,0.65625 0.36558,0 0.6936,-0.30765 0.6781,-0.65797 C 428,242.91083 427.68952,243 427.84375,242.625 c 0.11839,-0.28788 0.47629,-0.71901 0.90625,-0.83455 0.61327,-0.1648 1.873,0.18401 2.5,0.20955 1.75215,0.0714 3.67097,-0.15759 4.5,-1 -0.24423,0.0241 -2.49503,0.0675 -2.75,0.0625 -1.06533,-0.0208 -1.89414,-0.12444 -2.66545,-0.0891 l 0,-5e-5 z"
+ id="path18678"
+ sodipodi:nodetypes="cssssssscss"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccscc"
+ d="m 430.47881,243.98149 c 1.25,0 2.77121,0.0774 3.52119,0.0185 -0.28977,0.34542 -1.08416,0.80085 -1.5,0.89651 -0.84895,0.19531 -2.02119,-0.033 -2.89006,0.0468 l 0.86887,-0.96184 0,3e-5 z"
+ id="path18680"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="cccc"
+ style="fill:none;stroke:url(#linearGradient18690);stroke-width:0.99999923px;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 396.54123,73.51858 -10.98611,-8e-5 -0.0139,11.00008 11,0 0,-11 10e-6,0 z"
+ id="path18688"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(2,529.00001)"
+ id="g18738"
+ 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="rect18740"
+ width="16"
+ height="16"
+ x="3"
+ y="69" />
+ <g
+ style="display:inline"
+ id="g18742"
+ transform="translate(0.01612278,0)">
+ <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"
+ 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"
+ d="M 17.453876,82.25 16.233877,83.5 5.75,83.5 4.5,82.25 l -1e-7,-11.75 12.9652911,0 -0.01141,11.75 -5e-6,0 0,0 0,0 z"
+ style="fill:url(#linearGradient18752);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"
+ sodipodi:nodetypes="ccccccc"
+ 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"
+ d="M 15.983877,81.999998 7.7338772,82 l 0,-0.999998 8.2499998,-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(#linearGradient18756);stroke-width:0.99999976px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="M 5.4838772,82.500001 5.511418,71.499938 16.483877,71.5 l 0,11 -10.9999998,10e-7 z"
+ id="path18748"
+ 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"
+ width="1"
+ height="1"
+ x="5.9838772"
+ y="80.999992"
+ 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>
+ <g
+ transform="translate(256.9902,446.00001)"
+ id="g18759"
+ 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="rect18761"
+ width="16"
+ height="16"
+ x="42.0098"
+ y="173" />
+ <g
+ style="display:inline"
+ id="g18763"
+ 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="translate(-0.00161682,-3.9821186e-5)">
+ <path
+ sodipodi:nodetypes="cccccc"
+ 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="path41276"
+ d="m 56.511417,178.50003 -10,0 0,9 8.75,0 1.25,-1.25 0,-7.75 z"
+ style="opacity:0.15;fill:#000000;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ id="path18765"
+ d="m 55.011418,177.00004 -10.000001,-1e-5 0,9 10.000001,1e-5 0,-9 z"
+ style="opacity:0.85;fill:url(#linearGradient18779);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ 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 55.501617,177.75004 -1.25,-1.25 -8.4902,-1e-5 -1.25,1.25 0,7.5 1.25,1.25 8.4902,1e-5 1.25,-1.25 0,-7.5 z"
+ id="path18767"
+ 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="ccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#4d4d4d;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 54.011419,178.00004 -8.000002,-1e-5 0,0.99996 8.000002,1e-5 0,-0.99996 z"
+ id="path18773"
+ 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" />
+ </g>
+ <path
+ 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="path18860"
+ d="m 54.5098,177.5 0,8 -9,-1e-5 0,-8 9,1e-5 z"
+ style="fill:none;stroke:url(#linearGradient18862);stroke-width:0.99999923px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g18864"
+ transform="translate(210,253.00005)">
+ <rect
+ y="345"
+ x="-184"
+ height="16"
+ width="16"
+ id="rect18694"
+ 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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ id="path18698"
+ d="m -176.47247,352.5 -0.59149,0 -5.43604,0 0.0161,-6.00003 6.01141,0 0,6.00003 2e-5,0 0,0 0,0 z"
+ style="fill:url(#linearGradient18846);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"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient18841);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 -176.5,358.5 -1,1 -3.73388,0 -1.25,-1.25 0,-5.74999 6.01141,0 L -176.5,358.5 z"
+ id="path18702"
+ 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="ccccccc"
+ 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="path18710"
+ d="m -169.5133,358.25 -1.2367,1.25 -4.75,0 -1,-1 0,-12 7.00001,0 -0.0133,11.75 -10e-6,0 z"
+ style="fill:url(#linearGradient18831);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"
+ 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="path18712"
+ d="m -171,358 -4,0 0,-1.00004 4,0 0,1.00004 z"
+ style="color:#000000;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"
+ 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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ id="path18718"
+ d="m -177.5,353.5 0,5 -4,0 0,-5 4,0 z"
+ style="fill:none;stroke:url(#linearGradient18823);stroke-width:0.99999923px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -178,358.00004 -3,0 0,-1.00004 3,0 0,1.00004 z"
+ id="path18850"
+ 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(#linearGradient18854);stroke-width:0.99999923px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m -170.5,347.5 0,11.00001 -5,0 0,-11.00001 5,0 z"
+ id="path18852"
+ 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" />
+ <path
+ style="fill:none;stroke:url(#linearGradient18858);stroke-width:0.99999923px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m -177.5,347.50001 0,4 -4,0 0,-4 4,0 z"
+ id="path18856"
+ 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" />
+ <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="path17395"
+ d="m -178,358.00004 -3,0 0,-1.00004 3,0 0,1.00004 z"
+ style="color:#000000;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g17204"
+ transform="translate(290,-291)">
+ <g
+ transform="translate(-204,295)"
+ id="g18875"
+ 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="rect18877"
+ width="16"
+ height="16"
+ x="3"
+ y="69" />
+ <g
+ style="display:inline"
+ id="g18879"
+ transform="translate(0.01612278,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="path18881"
+ d="M 17.453876,82.25 16.233877,83.5 5.75,83.5 4.5,82.25 l -1e-7,-11.75 12.9652911,0 -0.01141,11.75 -5e-6,0 0,0 0,0 z"
+ style="fill:url(#linearGradient17222);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"
+ 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="path18883"
+ d="M 15.983877,81.999998 5.9838772,82 l 0,-0.999998 9.9999998,-2e-6 0,0.999998 z"
+ style="fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient17224);stroke-width:0.99999976px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="M 5.4838772,82.500001 5.511418,71.499938 16.483877,71.5 l 0,11 -10.9999998,10e-7 z"
+ id="path18885"
+ 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:#ececec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect18887"
+ width="1"
+ height="1"
+ x="6.9838772"
+ y="81"
+ 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
+ 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 -197.50001,368.5 9,0 m -9,2 9,0 m -9,2 9,0"
+ style="fill:none;stroke:url(#linearGradient17226);stroke-width:0.9999994px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1"
+ id="path19108"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g17183"
+ transform="translate(294,-291)">
+ <g
+ style="display:inline"
+ id="g19069"
+ transform="translate(-187,295)">
+ <rect
+ y="69"
+ x="3"
+ height="16"
+ width="16"
+ id="rect19071"
+ 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,0)"
+ id="g19073"
+ style="display:inline">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient17214);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 17.453876,82.25 16.233877,83.5 5.75,83.5 4.5,82.25 l -1e-7,-11.75 12.9652911,0 -0.01141,11.75 -5e-6,0 0,0 0,0 z"
+ id="path19075"
+ 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="ccccc"
+ style="fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="M 15.983877,81.999998 5.9838772,82 l 0,-0.999998 9.9999998,-2e-6 0,0.999998 z"
+ id="path19077"
+ 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="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="path19079"
+ d="M 5.4838772,82.500001 5.511418,71.499938 16.483877,71.5 l 0,11 -10.9999998,10e-7 z"
+ style="fill:none;stroke:url(#linearGradient17216);stroke-width:0.99999976px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <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="81"
+ x="6.9838772"
+ height="1"
+ width="1"
+ id="rect19081"
+ style="fill:#ececec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+ <path
+ id="path19112"
+ style="fill:none;stroke:url(#linearGradient17218);stroke-width:0.99999946px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1"
+ d="m -173.49999,372.5 2,0 m -2,-2 2,0 m -2,-2 2,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"
+ 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"
+ d="m -180.5,372.5 3,0 m -3,-2 3,0 m -3,-2 3,0"
+ style="fill:none;stroke:url(#linearGradient17220);stroke-width:0.99999952px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1"
+ id="path19116"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#999999;fill-opacity:0.75;fill-rule:evenodd;stroke:#808080;stroke-width:0.99999928px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ d="m -175.39386,374.49044 0,-7.03646"
+ id="path19120"
+ 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="cc"
+ 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="path19122"
+ d="m -174.39384,374.5 0,-8.00012 2.89384,0"
+ style="fill:none;stroke:#ffffff;stroke-width:0.9999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g41473">
+ <g
+ id="g20803"
+ transform="translate(-116.99998,424.00001)">
+ <g
+ transform="translate(-340.00002,-121.00001)"
+ id="g20805">
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#e9e9af;stroke-width:0.49999988;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="path32699"
+ sodipodi:cx="464.5"
+ sodipodi:cy="192.5"
+ sodipodi:rx="1.75"
+ sodipodi:ry="1.75"
+ d="m 466.25,192.5 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 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 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 z"
+ sodipodi:ry="1.75"
+ sodipodi:rx="1.75"
+ sodipodi:cy="192.5"
+ sodipodi:cx="464.5"
+ id="path32701"
+ style="opacity:0.4;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#e1e08a;stroke-width:0.69999987;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:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#adac2f;stroke-width:1.16666663;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="path32703"
+ sodipodi:cx="464.5"
+ sodipodi:cy="192.5"
+ sodipodi:rx="1.75"
+ sodipodi:ry="1.75"
+ d="m 466.25,192.5 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 z"
+ transform="matrix(0.8571429,0,0,0.8571429,67.857123,27.999992)" />
+ </g>
+ <rect
+ y="71"
+ x="125"
+ height="2"
+ width="2"
+ id="rect20813"
+ style="fill:#f4f4d7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <g
+ id="g41392">
+ <g
+ transform="translate(-456.00027,338.00001)"
+ id="g20782">
+ <path
+ style="fill:url(#linearGradient23241);fill-opacity:1;fill-rule:nonzero;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 472.50029,156.5 c -1.9309,0 -3,0.66961 -3,1.5 l 0,7 c 0,0.83039 1.0691,1.5 3,1.5 1.9309,0 3,-0.66961 3,-1.5 l 0,-7 c 0,-0.83039 -1.0691,-1.5 -3,-1.5 z"
+ id="path20784"
+ sodipodi:nodetypes="cccsccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient23243);stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 470.50029,158.5 0,6.45352 c 0,0.54648 1.28413,0.46583 2,0.54648 1,0 2,0 2,-0.55753 l 0,-6.45352"
+ id="path20786"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.7;fill:url(#radialGradient23245);fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 472.50029,156.5 c -1.9309,0 -3,0.5 -3,1.5 l 0,7 c 0,0.83039 1.0691,1.5 3,1.5 1.9309,0 3,-0.66961 3,-1.5 l 0,-7 c 0,-1 -1.0691,-1.5 -3,-1.5 z"
+ id="path20788"
+ sodipodi:nodetypes="cccsccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#eff6ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.73959124;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path20790"
+ sodipodi:cx="108"
+ sodipodi:cy="-222"
+ sodipodi:rx="3.3084693"
+ sodipodi:ry="1.2798798"
+ d="m 111.30847,-222 a 3.3084693,1.2798798 0 1 1 -6.61694,0 3.3084693,1.2798798 0 1 1 6.61694,0 z"
+ transform="matrix(0.9067635,0,0,1.3047091,374.56954,447.97555)" />
+ <path
+ sodipodi:nodetypes="cccsccc"
+ id="path20793"
+ d="m 472.50029,156.5 c -1.9309,0 -3,0.5 -3,1.5 l 0,7 c 0,0.83039 1.0691,1.5 3,1.5 1.9309,0 3.00029,-0.75001 3,-1.5 l 0,-7 c 0,-1 -1.0691,-1.5 -3,-1.5 z"
+ style="fill:none;stroke:#162d50;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-116.99998,424.00001)"
+ id="g32690">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path32692"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.05875278;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.4371593,0,0,0.4371565,71.294972,28.418283)" />
+ <path
+ transform="matrix(-0.3851128,-0.04237784,0.04389507,-0.3737467,174.55414,129.70537)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path32694"
+ style="opacity:0.6;fill:url(#linearGradient23247);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:type="arc" />
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path20801"
+ style="fill:none;stroke:url(#linearGradient23250);stroke-width:3.99999762;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.3000001,0,0,0.3000002,89.398992,44.603723)" />
+ </g>
+ <rect
+ y="493"
+ x="5"
+ height="16"
+ width="16"
+ id="rect20815"
+ style="fill:none;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+ <g
+ id="g17123"
+ transform="translate(207.01492,72.000007)">
+ <rect
+ y="442"
+ x="-34"
+ height="16"
+ width="16"
+ id="rect17125"
+ style="opacity:0;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="czsccccccccccccccccccccccccccccs"
+ id="path17128"
+ d="m -21.25,443.25 c -1.25,-1.25 -3.5,0.25 -7.5,4 -4,3.75 -5.25,6.25 -4,7.5 1.013195,1.01319 3.75,2.5 3.75,2.5 l 0.25,0 0,-0.25 -2.75,-3.5 1,-1 3.5,2.75 0.25,0 0,-0.25 -2.75,-3.5 1,-1 3.5,2.75 0.25,0 0,-0.25 -2.75,-3.5 1,-1 3.5,2.75 0.25,0 0,-0.25 -2.75,-3.5 1,-1 3.5,2.75 0.25,0 0,-0.25 -2.75,-3.5 1,-1 3.5,2.75 0.25,0 0,-0.25 c 0,0 -2,-3.25 -2.5,-3.75 z"
+ style="fill:none;stroke:#000000;stroke-width:1.60000002;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:url(#linearGradient17135);fill-rule:evenodd;stroke:none"
+ d="m -21.25,443.25 c -0.5,-0.5 -3.5,0.25 -7.5,4 -4,3.75 -4.5,7 -4,7.5 0.5,0.5 3.5,2.75 3.5,2.75 l 0.75,-0.75 -2.75,-3.25 0.75,-0.75 3.25,2.75 0.75,-0.75 -2.75,-3.25 0.75,-0.75 3.25,2.75 0.75,-0.75 -2.75,-3.25 0.75,-0.75 3.25,2.75 0.75,-0.75 -2.75,-3.25 0.75,-0.75 3.25,2.75 0.75,-0.75 -2.75,-3.25 0.75,-0.75 3.25,2.75 0.75,-0.75 c 0,0 -2.249997,-3 -2.75,-3.5 z"
+ id="path17131"
+ sodipodi:nodetypes="czsccccccccccccccccccccccs"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1.39999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -21.75,443.75 c -1,-1 -3.5,1 -6.5,4 -3,3 -5,5.5 -4,6.5"
+ id="path17133"
+ sodipodi:nodetypes="czs"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g17299"
+ transform="translate(-21,128.00001)">
+ <g
+ transform="translate(464,422)"
+ id="g17228"
+ 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="rect17230"
+ width="16"
+ height="16"
+ x="3"
+ y="69" />
+ <g
+ style="display:inline"
+ id="g17232"
+ transform="translate(0.01612278,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="path17234"
+ d="m 17.453876,82.25 -1.219999,1.25 -10.4999998,0 -1.25,-1.25 -1e-7,-11.75 12.9814139,0 -0.01141,11.75 -5e-6,0 0,0 0,0 z"
+ style="fill:url(#linearGradient17242);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"
+ sodipodi:nodetypes="ccccccc"
+ 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="path17236"
+ d="M 15.983877,81.999998 5.9838772,82 l 0,-0.999998 9.9999998,-2e-6 0,0.999998 z"
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient17244);stroke-width:0.99999976px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 5.4838772,82.5 0,-11 10.9999998,0 0,11 -10.9999998,0 z"
+ id="path17238"
+ 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:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect17240"
+ width="1"
+ height="1"
+ x="6.9838772"
+ y="81"
+ 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>
+ <g
+ transform="translate(20.96875,0)"
+ id="g17279">
+ <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"
+ d="m 450.70226,498 6.81386,0 m -4.98487,-2.5 -1.82899,2.5 m 1.82899,2.5 -1.82899,-2.5"
+ style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path17281"
+ sodipodi:nodetypes="czcccc"
+ 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"
+ sodipodi:nodetypes="cc"
+ id="path17283"
+ style="fill:none;stroke:#ffffff;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ d="m 453.28125,496 -0.75,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\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ d="m 452.78125,499 4.76119,0"
+ style="fill:none;stroke:#ffffff;stroke-width:0.50000006;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path17286"
+ sodipodi:nodetypes="cz"
+ inkscape:connector-curvature="0" />
+ </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"
+ 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"
+ id="rect33081"
+ width="16"
+ height="16"
+ x="162"
+ y="90" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#1a1a1a;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="rect33085"
+ width="2.5"
+ height="1.75"
+ x="165.74995"
+ y="96.749977" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path33087"
+ d="m 164.99996,98.99998 6,-2.5 6,2.5 0,2.75 -5.99999,3.24999 -6.00001,-3.24999 0,-2.75 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="91.999977"
+ x="170.98643"
+ height="7"
+ width="2"
+ id="rect32743"
+ style="opacity:0.96000001;fill:none;stroke:#1a1a1a;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" />
+ <path
+ id="path33091"
+ d="m 164.99996,98.99998 6,-2.5 6,2.5 0,0.5 -6,3 -6,-2.93442 0,-0.56558 z"
+ style="fill:#808080;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"
+ style="fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 164.99997,101.74998 -1e-5,-2.25 6,3 0.01,2.49885 -6.00995,-3.24885 -4e-5,0 0,0 0,0 z"
+ id="path33093"
+ 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="path33095"
+ d="m 176.99996,101.74998 0,-2.25 -6,3 c 0,2.58362 0,1.9329 0,2.5 l 6,-3.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" />
+ <rect
+ style="fill:#aa0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect33097"
+ width="2"
+ height="1"
+ x="165.99995"
+ y="97.999977" />
+ <rect
+ y="96.999977"
+ x="165.99995"
+ height="1"
+ width="2"
+ id="rect32749"
+ style="fill:#ff2a2a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.5;fill:#ffaaaa;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect32751"
+ width="1"
+ height="2"
+ x="165.99995"
+ y="96.999977" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path32753"
+ d="m 165.49996,99.49998 0,0 0,2 5.5,3 5.5,-3 0,-2"
+ style="fill:none;stroke:url(#linearGradient22081);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(-114.00004,-232.99999)"
+ id="g32755">
+ <rect
+ style="opacity:0.3;fill:none;stroke:#1a1a1a;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"
+ id="rect33103"
+ width="2"
+ height="3.9642856"
+ x="285"
+ y="328.03571" />
+ <path
+ transform="matrix(1.6666708,0,0,1.6666633,-190.66784,-215.66559)"
+ d="m 287.5,325 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 z"
+ sodipodi:ry="1.5"
+ sodipodi:rx="1.5"
+ sodipodi:cy="325"
+ sodipodi:cx="286"
+ id="path33105"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#550000;stroke-width:0.59999985;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:type="arc" />
+ <rect
+ style="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="rect32759"
+ width="2"
+ height="3.5000324"
+ x="285"
+ y="328.49997" />
+ <rect
+ y="328.49997"
+ x="285"
+ height="3.5000324"
+ width="1"
+ id="rect32761"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient32335);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.59999985;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path32763"
+ sodipodi:cx="286"
+ sodipodi:cy="325"
+ sodipodi:rx="1.5"
+ sodipodi:ry="1.5"
+ d="m 287.5,325 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 z"
+ transform="matrix(1.333351,0,0,1.333345,-95.338377,-107.33714)" />
+ <rect
+ y="331"
+ x="284"
+ height="1"
+ width="1"
+ id="rect32765"
+ style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.5;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="rect32767"
+ width="2"
+ height="1"
+ x="285"
+ y="332" />
+ <rect
+ style="opacity:0.5;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="rect32769"
+ width="1"
+ height="1"
+ x="287"
+ y="331" />
+ </g>
+ <path
+ sodipodi:nodetypes="cc"
+ id="path48963"
+ d="m 165.49996,98.99998 5.5,2.75"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <g
+ mask="url(#mask20957)"
+ id="g21598">
+ <path
+ mask="none"
+ sodipodi:nodetypes="cccc"
+ id="path21596"
+ d="m 168.25,102.75 -0.75,0.75 c -1,1 -0.75,1 -2,1 l -2.25,0"
+ style="opacity:0.7;fill:none;stroke:#1a1a1a;stroke-width:2.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ececec;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 168.25,102.75 -0.75,0.75 c -1.25,1.17188 -0.75,1 -2,1 l -3,0"
+ id="path21594"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g34058"
+ transform="translate(0,12)">
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path32379"
+ d="m 35.5,65.5 6,0 0,11 -9,0 0,-8 3,-3 z"
+ style="fill:url(#linearGradient31964);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient31966);stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(0,-10)"
+ id="g34026">
+ <path
+ style="fill:url(#linearGradient31968);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient31970);stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;display:inline"
+ d="m 29.5,71.5 6,0 0,11 -9,0 0,-8 3,-3 z"
+ id="path32383"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="73"
+ x="27.984795"
+ height="8"
+ width="6.0303202"
+ id="rect32389"
+ 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
+ style="fill:#fa0000;fill-opacity:1"
+ transform="matrix(-1,0,0,1,217.99997,-167)"
+ id="g32391">
+ <g
+ style="fill:#fa0000;fill-opacity:1"
+ id="g32393">
+ <path
+ style="fill:#b41500;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 187.03125,239 0,2 2,0 0,-2 -2,0 z m 2,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 0,-2 0,-2 -2,0 0,2 2,0 z"
+ transform="matrix(-1,0,0,1,375.01609,1)"
+ id="path32395"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="fill:#fa0000;fill-opacity:1"
+ id="g32397"
+ transform="translate(2,-2)" />
+ <g
+ style="fill:#fa0000;fill-opacity:1"
+ transform="translate(0,-4)"
+ id="g32399" />
+ <g
+ style="fill:#fa0000;fill-opacity:1"
+ id="g32401"
+ transform="translate(2,-6)" />
+ <g
+ style="fill:#fa0000;fill-opacity:1"
+ transform="translate(0,-8)"
+ id="g32403" />
+ </g>
+ <path
+ mask="none"
+ clip-path="none"
+ transform="matrix(1.499975,0,0,1.4959551,100.24881,-314.20841)"
+ sodipodi:nodetypes="ccc"
+ id="path32405"
+ style="fill:none;stroke:#000000;stroke-width:0.66757292px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1;display:inline;filter:url(#filter23214)"
+ d="M -48.500031,260.50809 -46.5,260.5 l -3.1e-5,-1.99191"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path32407"
+ style="opacity:0.98999999;fill:none;stroke:url(#linearGradient31972);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 27.5,76 -3e-5,5.5081 M 31,72.5 l 3.49997,0.0081"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path32409"
+ d="m 25.99997,75.00809 4,0 0,-4 -4,4 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ d="m 26.5,64 0,8.5 6,0 -0.01513,4 9.01513,0 0,-11 -5.98487,0 -0.01513,-4 -6.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"
+ id="path32414"
+ sodipodi:nodetypes="cccccccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(-158,-135)"
+ id="g33249">
+ <path
+ sodipodi:nodetypes="cccccccccccccccccccc"
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 35,78 0,1 5,0 0,-1 -5,0 z m 0,2 0,1 5,0 0,-1 -5,0 z m -1,2 0,1 6,0 0,-1 -6,0 z m 5,2 0,1 1,0 0,-1 -1,0 z"
+ transform="translate(158,125)"
+ id="rect33241"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ d="m 33.5,73.25 0,2.25001 M 36.25,66.5 l 4.25,0"
+ style="fill:none;stroke:url(#linearGradient31974);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ id="path33301"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline"
+ id="g22429"
+ transform="translate(542.99004,484.00118)">
+ <rect
+ y="9"
+ x="-34"
+ height="16"
+ width="16"
+ id="rect22431"
+ 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" />
+ <g
+ id="g22433">
+ <path
+ 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 -32,17 7,-3 6,2.5 0,3.74998 -6.99999,3.74999 L -32,20.74998 -32,17 z"
+ id="path22435"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ 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 -32,17 6,-2.5 6,2.5 0,0.5 -6,3 -6,-2.93442 L -32,17 z"
+ id="path22437"
+ 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:#2c281a;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 -24.99004,20.99883 -25,14.00002 -32,17 l 3.5,1.75 3.50996,2.24883 0,0 0,0 0,0 z"
+ id="path22439"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path22441"
+ d="M -24.99004,20.99883 -25,14 l 6,2.5 -3.5,1.75 -2.49004,2.74883 0,0 0,0 0,0 z"
+ style="fill:#716844;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
+ style="fill:none;stroke:url(#linearGradient22453);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="M -19.5,16.5 -25,14.25 -31.5,17"
+ id="path22443"
+ sodipodi:nodetypes="ccc"
+ 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="path22445"
+ d="M -31.99999,20.74998 -32,17.5 l 6,3 0.01,3.49883 -6.00995,-3.24885 -4e-5,0 0,0 0,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"
+ 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:#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 -19,20.25 0,-3.24998 -7,3.49998 c 0,2.58362 0,2.93288 0,3.49998 L -19,20.25 z"
+ id="path22447"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.96000001;fill:none;stroke:url(#linearGradient22455);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -31.5,17.5 0,2.99998 5.5,3 6.5,-3.49998 0,-2.99998"
+ id="path22449"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path22451"
+ d="m -31.5,17.5 5.5,3 6.5,-3.5"
+ style="fill:none;stroke:url(#linearGradient22457);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ 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"
+ 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"
+ id="rect18472"
+ width="16"
+ height="16"
+ x="164"
+ y="592" />
+ <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="cccccc"
+ d="m 169.51126,596.5 c 3.98874,3.75 3.98874,7.5 3.98874,9 m 1.01472,-11 c 3.48528,5 2.98528,9.5 2.98874,11 M 166.5,600.5 c 2,1 3,3 3.00692,5"
+ style="fill:none;stroke:url(#linearGradient18478);stroke-width:3.29999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path18474"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path18476"
+ style="fill:none;stroke:url(#linearGradient18480);stroke-width:1.70000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 169.51126,596.5 c 3.98874,3.75 3.98874,7 3.98874,9 m 1.01472,-11 c 3.48528,5 2.98528,9.5 2.98874,11 M 166.5,600.5 c 2,1 3,3 3.00692,5"
+ 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" />
+ </g>
+ <g
+ style="display:inline"
+ id="g22771"
+ transform="translate(-186,487.00001)">
+ <g
+ id="g21832"
+ style="opacity:0.85">
+ <rect
+ transform="scale(-1,1)"
+ y="82"
+ x="-433.5"
+ height="3"
+ width="7.8166504"
+ id="rect22717"
+ style="opacity:0.5;fill:url(#linearGradient22880);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ transform="scale(-1,1)"
+ y="83"
+ x="-434"
+ height="1"
+ width="8.9931746"
+ id="rect21783"
+ style="fill:url(#linearGradient22848);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ transform="scale(-1,1)"
+ y="83"
+ x="-430.5"
+ height="1"
+ width="2"
+ id="rect22877"
+ style="fill:#333333;fill-opacity:0.81960784;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <g
+ style="opacity:0.8"
+ id="g22652">
+ <rect
+ y="69"
+ x="422"
+ height="16"
+ width="16"
+ id="rect22589"
+ style="opacity:0.05;fill:url(#radialGradient22838);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g22619">
+ <path
+ sodipodi:nodetypes="csscccc"
+ id="path21775"
+ d="m 422.51387,74.4375 c 2.14278,1.6383 5.29475,5.652 6.25,7.5625 0.5,1 1.05394,1.01957 1.5,0 0.875,-2 3.25,-4.75 4.75,-6 l -3.5,-4 c -1.25,1.83839 -2,3.25 -2.75,4.63304 -1.71617,-1.72583 -4.35859,-3.39262 -6.25,-4.13304"
+ style="fill:url(#linearGradient22840);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient22842);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" />
+ </g>
+ </g>
+ <g
+ id="g22626">
+ <g
+ id="g22622">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path21777"
+ d="m 422.51387,73.5 c 1.93909,0.815624 4.07262,1.664731 6,4 l 0.75,0 c 0.82427,-1.547027 1.51287,-2.596571 2.16161,-3.5"
+ style="fill:none;stroke:url(#linearGradient22844);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient22846);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+ d="m 422.51387,73.5 c 1.93909,0.815624 5.41183,5.25 7,8 1.5,-3 2.75,-4 4.75,-6.25"
+ id="path21779"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient22896);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 428.5,78.5 c 0.95165,-1.519624 1.88025,-3.040081 2.92548,-4.5"
+ id="path22894"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g22592"
+ transform="translate(434.01387,-281)">
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient22850);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.82784271;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="path21781"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.4380641,0,0,0.4372851,-57.820839,302.39978)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient22852);stroke-width:4.11671448;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="path21785"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.2913522,0,0,0.2916372,38.453823,319.58486)" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g35565"
+ transform="translate(147,527.00001)"
+ inkscape:export-filename="/home/wolter/Documenten/Blender/Icons/Fake2.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ y="71"
+ x="215"
+ height="16"
+ width="16"
+ id="rect34912"
+ style="opacity:0;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g35549">
+ <g
+ transform="translate(167,137)"
+ id="g34916">
+ <path
+ transform="translate(58.032932,-27.838387)"
+ d="m 3.5,-32 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="-32"
+ sodipodi:cx="0"
+ id="path34918"
+ style="fill:none;stroke:#1a1a1a;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"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:#000000;stroke-width:0.56022131;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="path34920"
+ sodipodi:cx="0"
+ sodipodi:cy="-32"
+ sodipodi:rx="3.5"
+ sodipodi:ry="3.5"
+ d="m 3.5,-32 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
+ transform="matrix(1.4285714,0,0,1.4274429,55.5,-11.825777)" />
+ </g>
+ <g
+ id="g34922"
+ transform="matrix(1.1068703,0,0,1.0981766,160.5341,122.19554)">
+ <path
+ sodipodi:type="arc"
+ style="fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path34924"
+ sodipodi:cx="0"
+ sodipodi:cy="-32"
+ sodipodi:rx="3.5"
+ sodipodi:ry="3.5"
+ d="m 3.5,-32 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 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 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="-32"
+ sodipodi:cx="0"
+ id="path34926"
+ style="fill:none;stroke:url(#linearGradient35583);stroke-width:1.17982781;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"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient35585);stroke-width:1.16643703;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="path34928"
+ sodipodi:cx="0"
+ sodipodi:cy="-32"
+ sodipodi:rx="3.5"
+ sodipodi:ry="3.5"
+ d="m 3.5,-32 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
+ transform="matrix(0.774689,0,0,0.7805148,56.890573,-14.812697)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient35587);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99581552;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path34930"
+ sodipodi:cx="0"
+ sodipodi:cy="-32"
+ sodipodi:rx="3.5"
+ sodipodi:ry="3.5"
+ d="m 3.5,-32 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 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 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="-32"
+ sodipodi:cx="0"
+ id="path34932"
+ style="fill:url(#linearGradient35589);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99581552;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ </g>
+ <g
+ transform="translate(167,137)"
+ id="g34934">
+ <path
+ transform="matrix(0.8571429,0,0,0.8571429,58.032932,-32.409816)"
+ d="m 3.5,-32 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="-32"
+ sodipodi:cx="0"
+ id="path34936"
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient35591);stroke-width:1.40000081;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="path34938"
+ sodipodi:cx="0"
+ sodipodi:cy="-32"
+ sodipodi:rx="3.5"
+ sodipodi:ry="3.5"
+ d="m 3.5,-32 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 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 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="-32"
+ sodipodi:cx="0"
+ id="path34940"
+ style="fill:none;stroke:url(#linearGradient35593);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"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient35595);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path34942"
+ sodipodi:cx="0"
+ sodipodi:cy="-32"
+ sodipodi:rx="3.5"
+ sodipodi:ry="3.5"
+ d="m 3.5,-32 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z"
+ transform="matrix(0.8571429,0,0,0.8571429,58.032932,-32.409816)" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g35712"
+ transform="translate(307,636)"
+ inkscape:export-filename="/home/wolter/Documenten/Blender/Icons/Fake1.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ y="-38"
+ x="34"
+ height="16"
+ width="16"
+ id="rect35714"
+ 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(231.01612,149)"
+ id="g34102"
+ style="opacity:0.96000001;display:inline">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path35717"
+ d="m -187.24592,-178.75235 -5.0202,5.00235 -3,2 -1,-1 2,-3 5.0202,-5.00235 2,2 z"
+ style="fill:url(#linearGradient35740);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -187.24592,-178.75235 -5.2702,5.25235 -3,2 -1,-1 2,-3 5.2702,-5.25235 2,2 z"
+ id="path34105"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path34107"
+ d="m -195.4858,-172.48532 1.46968,-2.51468 4.26612,-4.25"
+ style="fill:none;stroke:#ffffff;stroke-width:0.85000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path35721"
+ d="m 44.5,-37.5 -2,2 1,1 -2,2 -4,0 -1,1 7,7 1,-1 0,-4 2,-2 1,1 1.5098,-1.5098 0.4902,-0.4902 -5,-5 z"
+ style="fill:url(#linearGradient35742);fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="cccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path35723"
+ d="m 44.5,-29.5 -3,-3"
+ style="fill:none;stroke:url(#linearGradient35744);stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path35725"
+ d="m 46.5,-31.5 -3,-3"
+ style="fill:none;stroke:url(#linearGradient35746);stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path35729"
+ d="m 43.5,-33.5 -1.75,1.75 -4,0 -0.25,0.25"
+ style="fill:none;stroke:#ffffff;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path35731"
+ d="m 43.5,-35.5 1,-1"
+ style="fill:none;stroke:#ffffff;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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path35733"
+ d="m 42,-32 0,0 2,-2 2.5,2.5 -2,2 L 42,-32"
+ style="fill:url(#linearGradient35750);fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient35752);stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 44.55,-36.45 3.95,3.95"
+ id="path34886"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path34890"
+ d="m 43.5,-35.5 3.715625,3.66875"
+ style="fill:none;stroke:url(#linearGradient35754);stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient35756);stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 41.55,-31.45 2.2,2.2"
+ id="path34894"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.3;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 45.5,-31.5 -1.25,1.25"
+ id="path34906"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path34908"
+ d="M 48.65,-32.65 47.4,-31.4"
+ style="opacity:0.3;fill:none;stroke:#ffffff;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient35772);fill-rule:evenodd;stroke:none"
+ d="m 41.5,-32.25 -4.25,0 6.5,6.25 0,-4"
+ id="path35770"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path35727"
+ d="m 38.25,-31.25 5.5,5.5"
+ style="fill:none;stroke:url(#linearGradient35748);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ 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"
+ 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"
+ d="m 433.14375,58.950006 -2.75,2.75"
+ id="path11878"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path11880"
+ d="m 425.39375,56.700006 2.75,-2.75"
+ style="fill:#ff0000;fill-opacity:0.75;fill-rule:evenodd;stroke:url(#linearGradient68939);stroke-width:2.4000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g11883"
+ transform="translate(0,-0.044194)">
+ <path
+ transform="translate(459.95822,-187.9558)"
+ sodipodi:nodetypes="czzc"
+ id="path11885"
+ d="m -32.20822,242.24999 2,-2 c 3.74999,-3.75 8.74999,1.25 5,5 l -2,2"
+ style="fill:none;stroke:url(#linearGradient68941);stroke-width:2.20000005;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:connector-curvature="0" />
+ <rect
+ y="48"
+ x="423"
+ height="16"
+ width="16"
+ id="rect51637"
+ style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" />
+ <g
+ transform="translate(440,-188)"
+ id="g11891">
+ <path
+ transform="translate(-440,188.0442)"
+ id="path11895"
+ d="m 432.125,49.03125 c -1.30818,0.127946 -2.64484,0.727176 -3.75,1.8125 l -4.78125,4.6875 2.8125,2.875 4.78125,-4.71875 c 1.25772,-1.235151 1.98833,-0.85542 2.53125,-0.3125 0.54292,0.542919 0.91397,1.2336 -0.34375,2.46875 l -4.78125,4.6875 2.8125,2.875 4.78125,-4.71875 c 2.52607,-2.480751 2.30083,-6.16792 0.34375,-8.125 -0.97854,-0.978541 -2.36579,-1.53434 -3.84375,-1.53125 -0.18474,3.86e-4 -0.37562,-0.01828 -0.5625,0 z m 0.5625,0.875 c 1.23689,8.8e-4 2.39931,0.461809 3.21875,1.28125 1.63889,1.63889 1.89928,4.676909 -0.34375,6.875 l -4.28125,4.1875 -1.5625,-1.5625 4.3125,-4.21875 c 1.54471,-1.51377 1.17361,-2.857641 0.3125,-3.71875 -0.86111,-0.86111 -2.23654,-1.201271 -3.78125,0.3125 l -4.28125,4.1875 -1.5625,-1.5625 4.3125,-4.21875 c 1.12152,-1.09905 2.41936,-1.563381 3.65625,-1.5625 z"
+ style="opacity:0.9;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="csc"
+ id="path11897"
+ d="m -3.4321903,240.29419 c 0.82637,1.47069 0.7752067,3.63228 -0.8178097,5.23203 l -2.2237373,2.23314"
+ style="opacity:0.3;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="opacity:0.6"
+ id="g11899">
+ <path
+ sodipodi:nodetypes="czs"
+ id="path11901"
+ d="m 425.25,55.75 4.25,-4.25 c 1.59639,-1.596386 4.02931,-1.32637 5.5,-0.5"
+ style="fill:none;stroke:url(#linearGradient68943);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient68945);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ d="m 435,56 -4.75,4.75"
+ id="path11905"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(-313,109)"
+ id="g51645"
+ 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"
+ id="rect11909"
+ width="16"
+ height="16"
+ x="423"
+ y="48" />
+ <g
+ id="g11911"
+ transform="translate(440,-187.9558)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:3.79999995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -15,245 4.79178,-4.70581 c 3.7837908,-3.7159 8.7837908,1.2841 5,5 L -10,250"
+ id="path51649"
+ sodipodi:nodetypes="czzc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czzc"
+ id="path51651"
+ d="m -14.5,244.5 4.29178,-4.20581 c 3.7877432,-3.71186 8.7877432,1.28814 5,5 L -9.5,249.5"
+ style="fill:none;stroke:url(#linearGradient68947);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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ff0000;fill-opacity:0.75;fill-rule:evenodd;stroke:url(#linearGradient68949);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"
+ d="M -6.75,246.75 -9.5,249.5"
+ id="path51653"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path51655"
+ d="m -14.5,244.5 2.75,-2.75"
+ style="fill:#ff0000;fill-opacity:0.75;fill-rule:evenodd;stroke:url(#linearGradient68951);stroke-width:2.4000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#481608;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -10.95822,242.99999 -2,-2"
+ id="path11922"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.85;fill:none;stroke:url(#linearGradient68953);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -14.70822,243.74999 4.25,-4.25 c 1.5,-1.49999 3.5,-1.5 5,-0.75"
+ id="path11924"
+ sodipodi:nodetypes="czs"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path11926"
+ d="m -5.95822,247.99999 -2,-2"
+ style="fill:none;stroke:#481608;stroke-width:1;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:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path11928"
+ d="m -4.95822,243.99999 -4.5,4.5"
+ style="opacity:0.85;fill:none;stroke:url(#linearGradient68955);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cs"
+ id="path11930"
+ d="m -4.0503493,245.73202 c 1.5801026,-1.61251 1.6441797,-3.76134 0.8178097,-5.23203"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g28545"
+ transform="translate(21,-19)">
+ <g
+ style="opacity:0.8;display:inline"
+ mask="url(#mask69005)"
+ transform="matrix(0.646567,0,0,0.644332,-233.54872,129.49706)"
+ id="g36675">
+ <g
+ style="display:inline"
+ id="g36677"
+ transform="matrix(1.8217829,0,0,1.8217829,375.38164,-343.68741)"
+ 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\Kopia blender\.blender\icons\blender's iconset.png"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36680"
+ style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.14285731;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.7428442,0,0,0.7454212,30.426387,135.62554)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.8;fill:url(#linearGradient51774);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path36682"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.6852904,-0.07823249,0.07810925,-0.6899628,209.72326,315.34566)" />
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36684"
+ style="fill:none;stroke:url(#linearGradient51776);stroke-width:1.33333385;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:type="arc"
+ transform="matrix(0.6367237,0,0,0.6389323,44.434295,148.19125)" />
+ </g>
+ </g>
+ <g
+ transform="translate(-61.375,-188.625)"
+ id="g51790"
+ style="display:inline">
+ <rect
+ style="opacity:0;fill-opacity:1;display:inline"
+ id="rect22754"
+ width="16"
+ height="16"
+ x="213.375"
+ y="343.625" />
+ <g
+ id="g51778">
+ <path
+ sodipodi:nodetypes="czscc"
+ id="path22715"
+ d="m 219.36593,351.65 0,-3.5 c 0,-2.025 1.25907,-2.525 2.50907,-2.525 1.25,0 2.5,0.5 2.49092,2.525 l 0,3.5"
+ style="fill:none;stroke:#000000;stroke-width:3.79999995;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient51804);stroke-width:2.5;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 219.36593,351.65 0.009,-3.275 c 0.006,-2.25 1.24773,-2.74375 2.5,-2.75 1.25227,-0.006 2.5,0.5 2.50907,2.725 l -0.0182,3.3"
+ id="path22717"
+ sodipodi:nodetypes="czscc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path22719"
+ d="m 224.35595,351.24375 0,0.53125"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient51806);stroke-width:2.5;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient51808);stroke-width:2.5;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 219.40595,351.72527 0,-0.50027"
+ id="path22721"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path22723"
+ d="m 220.7625,350.275 -2,0"
+ style="fill:none;stroke:#803300;stroke-width:1;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:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#803300;stroke-width:1.00000024;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 225.61593,350.15 -2.25,0"
+ id="path22725"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czs"
+ id="path22727"
+ d="m 218.61592,352.15 0,-4 c 0,-2.025 1.21963,-2.89049 2.75,-3.25"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient51810);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:none;stroke:url(#linearGradient51812);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ d="m 223.61593,352.15 0,-3.75115 c 0,-1.35618 -0.49093,-2.02385 -1.24093,-2.02385"
+ id="path22730"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.05;fill:none;stroke:#000000;stroke-width:0.73376155;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ d="m 225.24243,350.48448 c -0.001,-0.14034 0.0155,-2.61281 0,-2.75 -0.10562,-0.93297 -0.53761,-1.74673 -1.11525,-2.29782"
+ id="path22732"
+ sodipodi:nodetypes="css"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path22738"
+ d="m 220.11593,347.65 0,3.125"
+ style="opacity:0.02000002;fill:none;stroke:#000000;stroke-width:0.84999996;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g20285"
+ transform="translate(0,107.00001)">
+ <rect
+ y="449"
+ x="257"
+ height="16"
+ width="16"
+ id="rect19373"
+ 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="opacity:0.6;stroke:#162d50"
+ id="g19375"
+ transform="translate(14.081669,359)">
+ <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="cc"
+ id="path19377"
+ d="m 253.41833,95.5 c 1.5,1.5 1.5,3.5 0,5"
+ style="opacity:0.9;fill:none;stroke:#162d50;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="cc"
+ id="path19379"
+ d="m 255.41833,93.5 c 2.75,2.75 2.75,6.25 0,9"
+ style="opacity:0.9;fill:none;stroke:#162d50;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <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="cc"
+ id="path19381"
+ d="m 267.5,454.5 c 1.5,1.5 1.5,3.5 0,5"
+ style="opacity:0.9;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path19385"
+ d="m 264.58167,451.5 -1.08167,0 -3,3 c 0,-0.554 -0.446,-1 -1,-1 l -1,0 c -0.554,0 -1,0.446 -1,1 l 0,5 c 0,0.554 0.446,1 1,1 l 1,0 c 0.554,0 1,-0.446 1,-1 l 3,3 1.08167,0 0,-11 z"
+ style="fill:url(#linearGradient20275);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:nodetypes="ccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path19455"
+ d="m 258.5,459.5 1,0 1,-1 3.25,3"
+ style="fill:none;stroke:url(#linearGradient20309);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ 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="opacity:0.5;fill:none;stroke:url(#linearGradient20269);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 260.5,454.5 0,4.9091"
+ id="path19387"
+ 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"
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 258.5,455.5 1,0"
+ id="path19389"
+ 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="path19391"
+ d="m 262.59506,453.5 1,-1"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path19393"
+ d="m 258.5,454.63598 1,0"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="cc"
+ 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="cc"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 262.59506,454.5 1,-1"
+ id="path19395"
+ 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.9;fill:none;stroke:#ffffff;stroke-width:1.29999995;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 269.5,452.5 c 2.75,2.75 2.75,6.25 0,9"
+ id="path19397"
+ sodipodi:nodetypes="cc"
+ 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
+ id="path20281"
+ d="m 263.5,452.5 0,9"
+ style="fill:none;stroke:url(#linearGradient20283);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient20303);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 258.5,454.3 0,5.4"
+ id="path20301"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g38213"
+ transform="translate(0,-1.00005)">
+ <rect
+ y="513.99988"
+ x="26"
+ height="16"
+ width="16"
+ id="rect38641"
+ 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="g36101">
+ <g
+ id="g22740"
+ style="opacity:0.7"
+ transform="translate(-116,424.99975)">
+ <g
+ transform="translate(-179,199.50012)"
+ id="g38620">
+ <path
+ id="path38622"
+ d="m 329.5,-108.25 -5.5,1.75 0,7.74988 6,2.09544 5,-2.84532 0,-6.75 -5.5,-2 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.00000167;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 324,-99.00012 0,-7.49988 6,-1.75 0,11.5 -0.5,0.25 -5.5,-2.50012 z"
+ id="path38624"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(179,-179)"
+ id="g38626">
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ style="fill:#787878;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 156,79.5 0,-7 -5,-1.75 0,11.5 5,-2.75 z"
+ id="path38628"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ sodipodi:nodetypes="ccccc"
+ style="fill:#ffffff;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 145,72.5 5.5,-2 5.5,2 -5.5,2.5 -5.5,-2.5 z"
+ id="path38630"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="fill:none;stroke:url(#linearGradient38718);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.25012 0,-7.24988"
+ id="path38632"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="opacity:0.95999995;fill:none;stroke:url(#linearGradient38721);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 145.5,93.25012 c 0,0 5,2.25 5,2.25 l 5,-2.25"
+ id="path38634"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.19199997;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect38636"
+ width="1"
+ height="7.75"
+ x="150"
+ y="95.000122" />
+ <rect
+ y="95.25"
+ x="151"
+ height="7.75"
+ width="1"
+ id="rect22687"
+ style="opacity:0.09599998;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <rect
+ rx="0"
+ ry="0"
+ y="526.49988"
+ x="33.5"
+ height="3.0001416"
+ width="2.9999485"
+ id="rect38643"
+ style="fill:none;stroke:#783e00;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
+ rx="0"
+ ry="0"
+ y="516.49988"
+ x="27.5"
+ height="3.0001416"
+ width="2.9999485"
+ id="rect38645"
+ style="fill:none;stroke:#783e00;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:none;stroke:#783e00;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="rect38647"
+ width="2.9999485"
+ height="3.0001416"
+ x="27.5"
+ y="524.49969"
+ ry="0"
+ rx="0" />
+ <rect
+ style="fill:none;stroke:#783e00;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="rect38649"
+ width="2.9999485"
+ height="3.0001416"
+ x="33.5"
+ y="518.49969"
+ ry="0"
+ rx="0" />
+ <rect
+ style="opacity:0.06000001;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="rect38754"
+ width="3.9785564"
+ height="4"
+ x="34.021442"
+ y="519.00006" />
+ <rect
+ rx="0"
+ ry="0"
+ y="518.99976"
+ x="34"
+ height="2.0000772"
+ width="1.9999485"
+ id="rect39152"
+ style="fill:#ffd4a5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="rect28386"
+ d="m 28,519.50001 -0.5,0 0,-3.00014 2.99995,0"
+ style="fill:none;stroke:#462500;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#462500;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"
+ d="m 28,524.50001 -0.5,0 0,3.00014 2.99995,0"
+ id="path28390"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path28392"
+ d="m 33.5,527.75001 -9e-5,1.75004 3.00014,0 -5e-5,-1.75004"
+ style="fill:none;stroke:#462500;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="517.00006"
+ x="28.021444"
+ height="4"
+ width="3.9785564"
+ id="rect37868-0-2"
+ 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" />
+ <rect
+ style="fill:#ffd4a5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect28536"
+ width="1.9999485"
+ height="2.0000772"
+ x="28.000046"
+ y="517"
+ ry="0"
+ rx="0" />
+ <rect
+ style="fill:#ffd4a5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect28538"
+ width="1.9999485"
+ height="2.0000772"
+ x="34.000046"
+ y="527"
+ ry="0"
+ rx="0" />
+ <rect
+ y="525.00006"
+ x="28.021444"
+ height="1.9999889"
+ width="3.9785564"
+ id="rect38756"
+ 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" />
+ <rect
+ style="fill:#ffd4a5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect28540"
+ width="1.9999485"
+ height="2.0000772"
+ x="28.000046"
+ y="525"
+ ry="0"
+ rx="0" />
+ </g>
+ </g>
+ <g
+ id="g39255"
+ 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"
+ id="rect39088"
+ width="16"
+ height="16"
+ x="173"
+ y="70.976562" />
+ <g
+ id="g39227">
+ <g
+ transform="translate(1.0000047,-0.02344036)"
+ id="g39109">
+ <g
+ transform="translate(8,8)"
+ id="g39113">
+ <rect
+ ry="0"
+ y="72.5"
+ x="173.5"
+ height="6"
+ width="5"
+ id="rect39115"
+ style="fill:url(#linearGradient39281);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.69999999;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
+ style="fill:#333333"
+ transform="matrix(-1,0,0,-1,352,144)"
+ id="g39117" />
+ <rect
+ ry="0"
+ style="fill:none;stroke:url(#linearGradient39283);stroke-width:0.99999994;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="rect39119"
+ width="2.9999952"
+ height="4.0000029"
+ x="174.52599"
+ y="73.523438" />
+ </g>
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path39123"
+ d="m 183.25,82.5 c 0.25,0 1.5,0 1.5,0 l -1.5,0 z m 0,2 1.5,0 -1.5,0 z"
+ style="fill:none;stroke:#333333;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-6.9999953,-9.0234404)"
+ id="g39125">
+ <g
+ id="g39127"
+ transform="translate(8,8)">
+ <rect
+ style="fill:url(#linearGradient39285);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.69999999;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="rect39129"
+ width="5"
+ height="6"
+ x="173.5"
+ y="72.5"
+ ry="0" />
+ <g
+ id="g39131"
+ transform="matrix(-1,0,0,-1,352,144)"
+ style="fill:#333333" />
+ <path
+ style="fill:#666666;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 177,73.02344 0,1 -1,0 0,-1 1,0 z m -1,1 0,1 -1,0 0,-1 1,0 z m -1,0 -1,0 0,-1 1,0 0,1 z m 0,1 0,1 -1,0 0,-1 1,0 z m 0,1 1,0 0,1 -1,0 0,-1 z m 0,1 0,1 -1,-1 1,0 z m 1,0 1,0 0,1 -1,0 0,-1 z m 1,0 0,-1 1,0 0,1 -1,0 z m 0,-1 -1,0 0,-1 1,0 0,1 z m 0,-1 0,-1 1,0 0,1 -1,0 z"
+ id="rect39177"
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient39287);stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 174.52599,77.52344 0,-4.000002 2.99999,0"
+ id="rect39133"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g39149"
+ transform="translate(1,-9)">
+ <g
+ transform="translate(8,8)"
+ id="g39151">
+ <rect
+ ry="0"
+ y="72.5"
+ x="173.5"
+ height="6"
+ width="5"
+ id="rect39153"
+ style="fill:url(#linearGradient39289);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.69999999;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
+ style="fill:#333333"
+ transform="matrix(-1,0,0,-1,352,144)"
+ id="g39155" />
+ <rect
+ ry="0"
+ style="fill:none;stroke:url(#linearGradient39291);stroke-width:0.99999994;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="rect39157"
+ width="2.9999952"
+ height="4.0000029"
+ x="174.52599"
+ y="73.523438" />
+ </g>
+ </g>
+ <g
+ transform="translate(-7,0)"
+ id="g39163">
+ <g
+ id="g39165"
+ transform="translate(8,8)">
+ <rect
+ style="fill:url(#linearGradient39293);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.69999999;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="rect39167"
+ width="5"
+ height="6"
+ x="173.5"
+ y="72.5"
+ ry="0" />
+ <g
+ id="g39169"
+ transform="matrix(-1,0,0,-1,352,144)"
+ style="fill:#333333" />
+ <rect
+ y="73.523438"
+ x="174.52599"
+ height="4.0000029"
+ width="2.9999952"
+ id="rect39171"
+ style="fill:none;stroke:url(#linearGradient39295);stroke-width:0.99999994;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"
+ ry="0" />
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ transform="translate(168,-37)"
+ id="g39106">
+ <g
+ style="opacity:0.5;display:inline"
+ id="g39108"
+ transform="translate(69,-142)">
+ <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="rect39110"
+ width="16"
+ height="16"
+ x="-64"
+ y="336" />
+ <g
+ transform="translate(1,0)"
+ id="g39112">
+ <g
+ transform="translate(-386,446.5)"
+ id="g39114">
+ <path
+ id="path39116"
+ 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="path39118"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(179,-179)"
+ id="g39120">
+ <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="path39122"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ 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="path39124"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="fill:none;stroke:url(#linearGradient39008);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="path39126"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ style="fill:url(#linearGradient39010);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect39128"
+ width="1"
+ height="7.75"
+ x="-57"
+ y="342" />
+ <path
+ style="fill:none;stroke:url(#linearGradient39012);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="path39130"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <rect
+ y="197"
+ x="7.0214434"
+ height="4"
+ width="3.9785564"
+ id="rect37868-0-11"
+ 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" />
+ <rect
+ y="204"
+ x="7.0214434"
+ height="3"
+ width="3.9785564"
+ id="rect37868-0-7"
+ 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
+ style="display:inline"
+ id="g39132"
+ transform="matrix(0.8303712,0,0,0.8404094,-87.641227,155.05106)">
+ <g
+ id="g39134">
+ <path
+ id="path39136"
+ d="m 115.18474,49.326679 0.0443,0 c 0.98532,0 1.77856,0.793241 1.77856,1.778566 l 0,1.46e-4 c 0,0.985326 -0.79324,1.778566 -1.77856,1.778566 l -0.0443,0 c -0.98533,0 -1.77857,-0.79324 -1.77857,-1.778566 l 0,-1.46e-4 c 0,-0.985325 0.79324,-1.778566 1.77857,-1.778566 z"
+ style="fill:none;stroke:#000000;stroke-width:1.78961492;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"
+ 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="path39138"
+ d="m 116.40772,49.919572 c -0.80364,0 -1.60728,1.2e-5 -2.41092,1.2e-5 0,0.793735 0,1.587459 0,2.381206 0.80364,0 1.60728,-1.2e-5 2.41092,-1.2e-5 0,-0.793735 0,-1.587471 0,-2.381206 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1.78961492;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 115.18474,57.651268 0.0443,0 c 0.98532,0 1.77856,0.793241 1.77856,1.778566 l 0,1.46e-4 c 0,0.985326 -0.79324,1.778566 -1.77856,1.778566 l -0.0443,0 c -0.98533,0 -1.77857,-0.79324 -1.77857,-1.778566 l 0,-1.46e-4 c 0,-0.985325 0.79324,-1.778566 1.77857,-1.778566 z"
+ id="path37768"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 116.40772,58.244161 c -0.80364,0 -1.60728,1.2e-5 -2.41092,1.2e-5 0,0.793735 0,1.587459 0,2.381206 0.80364,0 1.60728,-1.2e-5 2.41092,-1.2e-5 0,-0.793735 0,-1.587471 0,-2.381206 z"
+ id="path37770"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ transform="translate(168,-37)"
+ id="g39140">
+ <g
+ transform="translate(90,-142)"
+ id="g39142"
+ style="opacity:0.5;display:inline">
+ <rect
+ y="336"
+ x="-64"
+ height="16"
+ width="16"
+ id="rect39144"
+ 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="g39146"
+ transform="translate(1,0)">
+ <g
+ id="g39148"
+ 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="path39150"
+ 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="path39152"
+ 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" />
+ <g
+ id="g39154"
+ transform="translate(179,-179)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path39156"
+ 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" />
+ <path
+ id="path39158"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path39160"
+ d="m 334.5,-106.5 0,6.75 -5,2.75 -5,-2.75 0,-6.75"
+ style="fill:none;stroke:url(#linearGradient39014);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ y="342"
+ x="-57"
+ height="7.75"
+ width="1"
+ id="rect39162"
+ style="fill:url(#linearGradient39016);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path39164"
+ d="m -61,340.65468 c 0,0 4.5,2 4.5,2 l 4.5,-2"
+ style="fill:none;stroke:url(#linearGradient39018);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <rect
+ y="198"
+ x="29"
+ height="8"
+ width="2.0000007"
+ id="rect37868-0-14"
+ 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" />
+ <rect
+ y="201"
+ x="32.021442"
+ height="7"
+ width="3.9785564"
+ id="rect37868-0-3"
+ 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
+ transform="translate(-1081.9421,-238.02038)"
+ style="fill:#ffeeaa;display:inline"
+ id="g39166">
+ <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:#d5e5ff;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;display:inline"
+ id="rect39168"
+ width="1.9820247"
+ height="8.0116062"
+ x="1109.4872"
+ y="435.4964"
+ transform="matrix(1,2.1226448e-5,0,1,0,0)" />
+ <rect
+ transform="matrix(1,3.6759233e-5,0,1,0,0)"
+ y="435.97955"
+ x="1109.958"
+ height="7.0000257"
+ width="0.99999994"
+ id="rect39170"
+ style="fill:#ffffff;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" />
+ <rect
+ transform="matrix(1,2.1226448e-5,0,1,0,0)"
+ y="438.49628"
+ x="1114.4713"
+ height="8.0116062"
+ width="1.9820247"
+ id="rect37773"
+ style="fill:#d5e5ff;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;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:#ffffff;fill-opacity:1;fill-rule:nonzero;display:inline"
+ id="rect37775"
+ width="0.99999994"
+ height="7.0000257"
+ x="1114.9421"
+ y="438.97937"
+ transform="matrix(1,3.6759233e-5,0,1,0,0)" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ transform="translate(168,-37)"
+ id="g39172">
+ <g
+ style="opacity:0.5;display:inline"
+ id="g39174"
+ transform="translate(111,-142)">
+ <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="rect39176"
+ width="16"
+ height="16"
+ x="-64"
+ y="336" />
+ <g
+ transform="translate(1,0)"
+ id="g39178">
+ <g
+ transform="translate(-386,446.5)"
+ id="g39180">
+ <path
+ id="path39182"
+ 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="path39184"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(179,-179)"
+ id="g39186">
+ <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="path39188"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ 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="path39190"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="fill:none;stroke:url(#linearGradient39020);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="path39192"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ style="fill:url(#linearGradient39022);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect39194"
+ width="1"
+ height="7.75"
+ x="-57"
+ y="342" />
+ <path
+ style="fill:none;stroke:url(#linearGradient39024);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="path39196"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <rect
+ y="201"
+ x="54"
+ height="7"
+ width="2.9785564"
+ id="rect37868-0-57"
+ 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
+ transform="translate(-1080.9861,-240)"
+ style="fill:#ffeeaa;display:inline"
+ id="g39198">
+ <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="path39200"
+ d="m 1130.4859,445.25 0,-7.5 6,2.75 0,8 -6,-3.25 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient39026);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="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g28811"
+ transform="translate(0,128.00001)">
+ <rect
+ y="365"
+ x="194"
+ height="16"
+ width="16"
+ id="rect28809"
+ style="opacity:0;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ style="display:inline"
+ id="g23255"
+ 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,-69.122722,304.28985)">
+ <path
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path23257"
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.86138636;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"
+ 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.81218,0,0,0.815735,163.7897,-27.2907)" />
+ <path
+ style="fill:#b3b3b3;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 270.98701,62.965769 0.0109,7.256732 c -1.99907,0 -3.99814,-0.250925 -6.00812,-1.234549 0,-3.324245 2.68676,-6.022183 5.99722,-6.022183 l 0,0 0,0 0,0 z m 0.0109,7.256732 c 1.99908,0 3.99815,-0.250925 5.98632,-1.234549 0,3.324245 -2.68675,6.022182 -5.99722,6.022182 l 0.0109,-4.787633 0,0 0,0 0,0 z"
+ id="path23259"
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient23274);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path23261"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.749782,0,0,0.752489,172.03052,-19.77379)" />
+ <path
+ transform="matrix(0.749782,0,0,0.752489,172.03052,-19.77379)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path23263"
+ style="opacity:0.1;fill:url(#linearGradient23276);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(0.624782,0,0,0.627489,188.53052,-5.0185058)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path23265"
+ style="opacity:0.8;fill:url(#linearGradient23278);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1.40226042;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 267.70545,67.406839 c 0.34141,-0.888253 0.96594,-1.399916 1.66978,-1.680902"
+ id="path23267"
+ sodipodi:nodetypes="cs"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path23269"
+ d="m 274.98515,70.995347 c 0,0.953349 -1,1.906699 -2,1.906699"
+ style="opacity:0.6;fill:none;stroke:#ffe680;stroke-width:1.00161445px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;filter:url(#filter13996)"
+ 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"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path23271"
+ style="fill:none;stroke:url(#linearGradient23280);stroke-width:1.45689511;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:type="arc"
+ transform="matrix(0.6875,0,0,0.6875,180.25,-12.125)" />
+ </g>
+ </g>
+ <g
+ id="g40234">
+ <rect
+ y="514.00012"
+ x="5"
+ height="15.99988"
+ width="16"
+ id="rect40163"
+ style="opacity:0;fill:#f6d0a6;fill-opacity:1;fill-rule:evenodd;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g40089"
+ transform="translate(70,178)">
+ <g
+ id="g40091"
+ transform="translate(-386,446.5)">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:#422200;fill-opacity:1;fill-rule:evenodd;stroke:#281500;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="path40093"
+ 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="path40095"
+ d="m 324,-99.5 0,-7 6,-1.75 0,11.5 -0.5,0.25 -5.5,-3 z"
+ style="fill:#efa351;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g40097"
+ transform="translate(179,-179)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path40099"
+ d="m 156,79.5 0,-7 -5,-1.75 0,11.5 5,-2.75 z"
+ style="fill:#915515;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ 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="path40101"
+ d="m 145,72.5 5.5,-2 5.5,2 -5.5,2.5 -5.5,-2.5 z"
+ style="fill:#f5ca9b;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path40103"
+ d="m 334.5,-106.5 0,6.75 -5,2.75 -5,-2.75 0,-6.75"
+ style="fill:none;stroke:url(#linearGradient40171);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ y="342"
+ x="-57"
+ height="7.75"
+ width="1"
+ id="rect40106"
+ style="fill:url(#linearGradient40173);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path40109"
+ d="m -61,340.65468 c 0,0 4.5,2 4.5,2 l 4.5,-2"
+ style="fill:none;stroke:url(#linearGradient40175);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g57337"
+ transform="translate(10,254)" />
+ <g
+ style="display:inline"
+ id="g57399"
+ 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path57401"
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.86138636;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"
+ 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.81218,0,0,0.815735,163.7897,-27.2907)" />
+ <path
+ style="fill:#b3b3b3;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 270.98701,62.965769 0.0109,7.256732 c -1.99907,0 -3.99814,-0.250925 -6.00812,-1.234549 0,-3.324245 2.68676,-6.022183 5.99722,-6.022183 l 0,0 0,0 0,0 z m 0.0109,7.256732 c 1.99908,0 3.99815,-0.250925 5.98632,-1.234549 0,3.324245 -2.68675,6.022182 -5.99722,6.022182 l 0.0109,-4.787633 0,0 0,0 0,0 z"
+ id="path57403"
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient57417);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path57405"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.749782,0,0,0.752489,172.03052,-19.77379)" />
+ <path
+ transform="matrix(0.749782,0,0,0.752489,172.03052,-19.77379)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path57407"
+ style="opacity:0.1;fill:url(#linearGradient57419);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(0.624782,0,0,0.627489,188.53052,-5.0185058)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path57409"
+ style="opacity:0.8;fill:url(#linearGradient57421);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1.40226042;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 267.70545,67.406839 c 0.34141,-0.888253 0.96594,-1.399916 1.66978,-1.680902"
+ id="path57411"
+ sodipodi:nodetypes="cs"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path57413"
+ d="m 274.98515,70.995347 c 0,0.953349 -1,1.906699 -2,1.906699"
+ style="opacity:0.6;fill:none;stroke:#ffe680;stroke-width:1.00161445px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;filter:url(#filter13996)"
+ 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"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path57415"
+ style="fill:none;stroke:url(#linearGradient57423);stroke-width:1.45689511;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:type="arc"
+ transform="matrix(0.6875,0,0,0.6875,180.25,-12.125)" />
+ </g>
+ <g
+ style="display:inline"
+ id="g22832"
+ 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"
+ id="rect22222"
+ width="16"
+ height="16"
+ x="-68"
+ y="256" />
+ <g
+ id="g22818">
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m -66.5,257.5 5,0 c 0,1 3,1 3,0 l 5,0 0,5 -2,0 -2.9e-4,8 -8.99971,-5e-5 0,-7.99995 -2,0 0,-5 z"
+ id="path22864"
+ sodipodi:nodetypes="ccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccc"
+ id="rect22236"
+ d="m -66.5,257.5 4.75,0 c -0.5,3.25 4,3.25 3.5,0 l 4.75,0 0,5 -2,0 -2.9e-4,8 -8.99971,-5e-5 0,-7.99995 -2,0 0,-5 z"
+ style="fill:url(#linearGradient22905);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.69999999;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient22891);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999863;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -66,258 4,0 c 0,2.5 4,2.5 4,0 l 4,0 0,4 -2,0 0,8 -8,0 0,-8 -2,0 0,-4 z"
+ id="path23050"
+ sodipodi:nodetypes="ccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path23055"
+ d="m -66,258 4,0 c 0,0.61505 0.242101,1.07878 0.607179,1.3912 L -61.5,259.5 -64,262 l -2,0 0,-4 z"
+ style="fill:url(#linearGradient22893);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999863;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient22895);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999863;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -54,258 -4,0 c 0,0.61505 -0.242101,1.07878 -0.607179,1.3912 L -58.5,259.5 l 2.5,2.5 2,0 0,-4 z"
+ id="path23059"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient22897);stroke-width:1.00000012px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m -56.5,262.75 0,6.75 -7,0 0,-7.5"
+ id="path22238"
+ 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
+ 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="path22276"
+ d="m -56.5,269.5 -7,0 m -2,-8 0,-3 m 11,0 0,3 m -8,-3 c 0.5,2.75 4.5,2.75 5,0"
+ style="fill:none;stroke:url(#linearGradient22899);stroke-width:1.00000012px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path23065"
+ d="m -63.5,264.5 c 0.75,3.5 4.25,5.5 7,3"
+ style="opacity:0.85;fill:none;stroke:url(#linearGradient22901);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:3.9000001;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.85;fill:none;stroke:url(#linearGradient22903);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:3.9000001;stroke-opacity:1;stroke-dasharray:none"
+ d="m -63.5,263.5 c 1,3.5 4.25,5.5 7,3"
+ id="path23063"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g23071"
+ transform="translate(0,1)"
+ style="opacity:0.9">
+ <path
+ style="opacity:0.4;fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -60.5,262.5 1,0 0,2.75"
+ id="path23069"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path23067"
+ d="m -60.5,262.5 1,0 0,2.75"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ transform="translate(-105,-229)"
+ id="g22900"
+ 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="rect22902"
+ width="16"
+ height="16"
+ x="257"
+ y="449" />
+ <g
+ transform="translate(14.081669,359)"
+ id="g22904"
+ style="opacity:0.6;stroke:#162d50">
+ <path
+ style="opacity:0.9;fill:none;stroke:#162d50;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 253.41833,95.5 c 1.5,1.5 1.5,3.5 0,5"
+ id="path22906"
+ sodipodi:nodetypes="cc"
+ 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.9;fill:none;stroke:#162d50;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 255.41833,93.5 c 2.75,2.75 2.75,6.25 0,9"
+ id="path22908"
+ sodipodi:nodetypes="cc"
+ 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" />
+ </g>
+ <path
+ style="opacity:0.9;fill:none;stroke:#d5e5ff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 267.5,454.5 c 1.5,1.5 1.5,3.5 0,5"
+ id="path22910"
+ sodipodi:nodetypes="cc"
+ 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="ccccccccccccc"
+ style="fill:url(#linearGradient22933);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ d="m 264.58167,451.5 -1.08167,0 -3,3 c 0,-0.554 -0.446,-1 -1,-1 l -1,0 c -0.554,0 -1,0.446 -1,1 l 0,5 c 0,0.554 0.446,1 1,1 l 1,0 c 0.554,0 1,-0.446 1,-1 l 3,3 1.08167,0 0,-11 z"
+ id="path22912"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient22935);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ d="m 258.5,459.5 1,0 1,-1 3.25,3"
+ id="path22914"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path22916"
+ d="m 260.5,454.5 0,4.9091"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient22937);stroke-width:1;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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path22918"
+ d="m 258.5,455.5 1,0"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="cc"
+ 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="cc"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 262.59506,453.5 1,-1"
+ id="path22920"
+ 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
+ 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="cc"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 258.5,454.63598 1,0"
+ id="path22922"
+ 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="path22924"
+ d="m 262.59506,454.5 1,-1"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="cc"
+ 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"
+ sodipodi:nodetypes="cc"
+ id="path22926"
+ d="m 269.5,452.5 c 2.75,2.75 2.75,6.25 0,9"
+ style="opacity:0.9;fill:none;stroke:#d5e5ff;stroke-width:1.29999995;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:none;stroke:url(#linearGradient22939);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 263.5,452.5 0,9"
+ id="path22928"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path22931"
+ d="m 258.5,454.3 0,5.4"
+ style="fill:none;stroke:url(#linearGradient22941);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g23411"
+ transform="translate(-399,-19)">
+ <rect
+ transform="scale(-1,1)"
+ y="260"
+ x="-441"
+ height="16"
+ width="16"
+ id="rect22167"
+ 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="g23378">
+ <g
+ transform="translate(-36.00033,108.00006)"
+ id="g22183">
+ <path
+ style="fill:url(#linearGradient23445);fill-opacity:1;fill-rule:nonzero;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 472.50029,156.5 c -1.9309,0 -3,0.66961 -3,1.5 l 0,8 c 0,0.83039 1.0691,1.5 3,1.5 1.9309,0 3,-0.66961 3,-1.5 l 0,-8 c 0,-0.83039 -1.0691,-1.5 -3,-1.5 z"
+ id="path22187"
+ sodipodi:nodetypes="cccsccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient23447);stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 470.50029,158.5 0,7.51105 c 0,0.54648 1,0.54648 2,0.54648 1,0 2,0 2,-0.55753 l 0,-7.51105"
+ id="path22189"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#eff6ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.73959124;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path22199"
+ sodipodi:cx="108"
+ sodipodi:cy="-222"
+ sodipodi:rx="3.3084693"
+ sodipodi:ry="1.2798798"
+ d="m 111.30847,-222 a 3.3084693,1.2798798 0 1 1 -6.61694,0 3.3084693,1.2798798 0 1 1 6.61694,0 z"
+ transform="matrix(0.9067635,0,0,1.3047091,374.56954,447.97555)" />
+ <path
+ sodipodi:nodetypes="cccsccc"
+ id="path22203"
+ d="m 472.50029,156.5 c -1.9309,0 -3,0.5 -3,1.5 l 0,8 c 0,0.83039 1.0691,1.5 3,1.5 1.9309,0 3.00029,-0.75001 3,-1.5 l 0,-8 c 0,-1 -1.0691,-1.5 -3,-1.5 z"
+ style="fill:none;stroke:#0b1728;stroke-width:0.80000001;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="cssc"
+ id="path23068"
+ d="m 436.5,265.5 0,-0.75 c 0,-4.25 -7,-4.25 -7,0 l 0,2.75"
+ style="opacity:0.55;fill:none;stroke:#0b1728;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"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.1;fill:none;stroke:#e1e08e;stroke-width:4;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="rect22214"
+ width="2.9999998"
+ height="3"
+ x="428"
+ y="266"
+ rx="1.2002208"
+ ry="1.2002208" />
+ <path
+ style="opacity:0.6;fill:none;stroke:#0b1728;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"
+ d="m 436.5,265.5 0,-0.75"
+ id="path23343"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#d7e3f4;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 436.5,265.5 0,-0.75 c 0,-4.25 -7,-4.25 -7,0 l 0,2.75"
+ id="path22210"
+ sodipodi:nodetypes="cssc"
+ inkscape:connector-curvature="0" />
+ <rect
+ rx="1.2002209"
+ y="266"
+ x="428"
+ height="3"
+ width="3"
+ id="rect22216"
+ style="opacity:0.4;fill:#a09f2c;fill-opacity:1;fill-rule:nonzero;stroke:#d6d562;stroke-width:2;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.2002209" />
+ <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="path23005"
+ d="m 427,266 c 0,-0.33336 10e-6,-0.6667 10e-6,-1.00006 0.33335,0 0.6667,0 1.00005,0 0,0.33336 -1e-5,0.6667 -1e-5,1.00006 -0.33335,0 -0.6667,0 -1.00005,0 z"
+ style="opacity:0.7;fill:#8c8b25;fill-opacity:1;fill-rule:nonzero;stroke:#8c8b0a;stroke-width:1.5;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.7;fill:#8c8b25;fill-opacity:1;fill-rule:nonzero;stroke:#8c8b0a;stroke-width:1.5;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"
+ d="m 427,270 c 0,-0.33336 10e-6,-0.6667 10e-6,-1.00006 0.33335,0 0.6667,0 1.00005,0 0,0.33336 -1e-5,0.6667 -1e-5,1.00006 -0.33335,0 -0.6667,0 -1.00005,0 z"
+ id="path23007"
+ 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="path23009"
+ d="m 430.99994,270 c 0,-0.33336 1e-5,-0.6667 1e-5,-1.00006 0.33335,0 0.6667,0 1.00005,0 0,0.33336 -10e-6,0.6667 -10e-6,1.00006 -0.33335,0 -0.6667,0 -1.00005,0 z"
+ style="opacity:0.7;fill:#8c8b25;fill-opacity:1;fill-rule:nonzero;stroke:#8c8b0a;stroke-width:1.5;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.7;fill:#8c8b25;fill-opacity:1;fill-rule:nonzero;stroke:#8c8b0a;stroke-width:1.5;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"
+ d="m 430.99994,266.00006 c 0,-0.33336 1e-5,-0.6667 1e-5,-1.00006 0.33335,0 0.6667,0 1.00005,0 0,0.33336 -10e-6,0.6667 -10e-6,1.00006 -0.33335,0 -0.6667,0 -1.00005,0 z"
+ id="path23012"
+ 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:#545306;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 428.25,266.25 0.75,-0.75 1,0 0.75,0.75 0.75,0.75 0,1 -0.75,0.75 -0.75,0.75 -1,0 -0.75,-0.75 -0.75,-0.75 0,-1 0.75,-0.75 z"
+ id="rect23002"
+ sodipodi:nodetypes="ccccccccccccc"
+ 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="path22218"
+ d="m 428,267 c 1,0 1.99998,10e-6 2.99998,10e-6 0,0.33335 0,0.6667 0,1.00005 -1,0 -1.99998,-1e-5 -2.99998,-1e-5 0,-0.33335 0,-0.6667 0,-1.00005 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 428.99996,269 c 0,-0.99999 1e-5,-1.99995 1e-5,-2.99994 0.33335,0 0.6667,0 1.00005,0 0,0.99999 -1e-5,1.99995 -1e-5,2.99994 -0.33335,0 -0.6667,0 -1.00005,0 z"
+ id="path22220"
+ 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;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 427,266 c 0,-0.33336 10e-6,-0.6667 10e-6,-1.00006 0.33335,0 0.6667,0 1.00005,0 0,0.33336 -1e-5,0.6667 -1e-5,1.00006 -0.33335,0 -0.6667,0 -1.00005,0 z"
+ id="path23312"
+ 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="path23314"
+ d="m 427,270 c 0,-0.33336 10e-6,-0.6667 10e-6,-1.00006 0.33335,0 0.6667,0 1.00005,0 0,0.33336 -1e-5,0.6667 -1e-5,1.00006 -0.33335,0 -0.6667,0 -1.00005,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 430.99994,270 c 0,-0.33336 1e-5,-0.6667 1e-5,-1.00006 0.33335,0 0.6667,0 1.00005,0 0,0.33336 -10e-6,0.6667 -10e-6,1.00006 -0.33335,0 -0.6667,0 -1.00005,0 z"
+ id="path23316"
+ 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="path23318"
+ d="m 430.99994,266.00006 c 0,-0.33336 1e-5,-0.6667 1e-5,-1.00006 0.33335,0 0.6667,0 1.00005,0 0,0.33336 -10e-6,0.6667 -10e-6,1.00006 -0.33335,0 -0.6667,0 -1.00005,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <g
+ style="opacity:0.65"
+ id="g23333"
+ transform="translate(464,-83)">
+ <g
+ id="g23320">
+ <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="path23014"
+ d="m -38,351 c 0,-0.33336 1e-5,-0.6667 1e-5,-1.00006 0.33335,0 0.666699,0 1.000049,0 0,0.33336 -1e-5,0.6667 -1e-5,1.00006 -0.33335,0 -0.666699,0 -1.000049,0 z"
+ style="fill:#8c8b25;fill-opacity:1;fill-rule:nonzero;stroke:#504f14;stroke-width:1.20000005;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#8c8b25;fill-opacity:1;fill-rule:nonzero;stroke:#504f14;stroke-width:1.20000005;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"
+ d="m -32.000059,351 c 0,-0.33336 1e-5,-0.6667 1e-5,-1.00006 0.33335,0 0.666699,0 1.000049,0 0,0.33336 -10e-6,0.6667 -10e-6,1.00006 -0.33335,0 -0.666699,0 -1.000049,0 l 0,0 0,0 0,0 z"
+ id="path23016"
+ 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="path23018"
+ d="m -35,354 c 0,-0.33336 1e-5,-0.6667 1e-5,-1.00006 0.33335,0 0.666699,0 1.000049,0 0,0.33336 -1e-5,0.6667 -1e-5,1.00006 -0.33335,0 -0.666699,0 -1.000049,0 z"
+ style="fill:#8c8b25;fill-opacity:1;fill-rule:nonzero;stroke:#504f14;stroke-width:1.20000005;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g23325"
+ style="fill:#ffffff;stroke:none">
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -38,351 c 0,-0.33336 1e-5,-0.6667 1e-5,-1.00006 0.33335,0 0.666699,0 1.000049,0 0,0.33336 -1e-5,0.6667 -1e-5,1.00006 -0.33335,0 -0.666699,0 -1.000049,0 z"
+ id="path23327"
+ 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="path23329"
+ d="m -32.000059,351 c 0,-0.33336 1e-5,-0.6667 1e-5,-1.00006 0.33335,0 0.666699,0 1.000049,0 0,0.33336 -10e-6,0.6667 -10e-6,1.00006 -0.33335,0 -0.666699,0 -1.000049,0 l 0,0 0,0 0,0 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -35,354 c 0,-0.33336 1e-5,-0.6667 1e-5,-1.00006 0.33335,0 0.666699,0 1.000049,0 0,0.33336 -1e-5,0.6667 -1e-5,1.00006 -0.33335,0 -0.666699,0 -1.000049,0 z"
+ id="path23331"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ id="g22853"
+ transform="translate(4.2e-4,2.056923)">
+ <g
+ style="display:inline"
+ 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="g22355"
+ transform="translate(296.99995,249.99998)">
+ <rect
+ transform="matrix(1,5.248259e-6,0,1,0,0)"
+ y="15.999177"
+ x="155.00008"
+ height="3.9999785"
+ width="4.0000005"
+ id="rect22359"
+ style="fill:url(#linearGradient23531);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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
+ 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:#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="rect22365"
+ width="4.9999776"
+ height="4.9999595"
+ x="154.50008"
+ y="15.499179"
+ transform="matrix(1,5.248259e-6,0,1,0,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="path22367"
+ d="m 155.50007,19.49999 -5.5e-4,-3.000005 2.99988,5e-6 6.8e-4,3 -3.00001,0 0,0 0,0 0,0 z"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient23533);stroke-width:1.00000012px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(187.99958,-21.0368)"
+ id="g23427">
+ <g
+ transform="translate(170.04549,179.51905)"
+ id="g23429"
+ style="opacity:0.7">
+ <path
+ style="fill:none;stroke:#214478;stroke-width:2.5;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 90.45451,103.98095 0,11 11,0 0,-11 -11,0 z"
+ id="path23431"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path23433"
+ d="m 90.45451,103.98095 0,11 11,0 0,-11 -11,0 z"
+ style="fill:none;stroke:#afc6e9;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>
+ <g
+ id="g23435">
+ <rect
+ rx="1.4999386"
+ ry="1.4999386"
+ y="293.5"
+ x="270.49985"
+ height="3"
+ width="2.9998772"
+ id="rect23438"
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:1.5;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:#0b1728;stroke-width:1.5;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="rect23440"
+ width="2.9998772"
+ height="3"
+ x="258.50024"
+ y="281.5368"
+ ry="1.4999386"
+ rx="1.4999386" />
+ <rect
+ rx="1.4999386"
+ ry="1.4999386"
+ y="293.49997"
+ x="258.49969"
+ height="3"
+ width="2.9998772"
+ id="rect23442"
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:1.5;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
+ style="fill:#d7e3f4;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 273,294 c -0.6694,0 -1.3388,10e-6 -2.0082,10e-6 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="path23444"
+ 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="path23446"
+ d="m 261,294 c -0.6694,0 -1.3388,10e-6 -2.0082,10e-6 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:#d7e3f4;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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="path23448"
+ d="m 261.00042,282.0368 c -0.6694,0 -1.3388,10e-6 -2.0082,10e-6 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:#d7e3f4;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:1.5;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="rect23450"
+ width="2.9998772"
+ height="3"
+ x="270.49985"
+ y="281.5"
+ ry="1.4999386"
+ rx="1.4999386" />
+ <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="path23452"
+ d="m 273,282 c -0.6694,0 -1.3388,10e-6 -2.0082,10e-6 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:#d7e3f4;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g40939"
+ 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="rect31966"
+ width="16"
+ height="16"
+ x="47"
+ y="260" />
+ <g
+ transform="translate(0,21)"
+ id="g40631">
+ <rect
+ style="fill:#87aade;fill-opacity:1;fill-rule:nonzero;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;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40597"
+ width="5"
+ height="3"
+ x="56.500004"
+ y="240.5" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path40599"
+ d="m 48.5,244.5 5,0 0,3 8,0 0,6 -13,0 0,-9 z"
+ style="fill:url(#linearGradient40965);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccccccccc"
+ d="m 49,250.5 12,0 m -4.5,-2.5 0,2.5 m -5,-2.5 0,2.5 m 2,2.5 0,-2.5 m 5,2.5 0,-2.5 m -5.5,-3 -4,0"
+ style="fill:none;stroke:url(#linearGradient40967);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ id="path40601"
+ inkscape:connector-curvature="0" />
+ <path
+ 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:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 48.5,244.5 5,0 0,3 8,0 0,6 -13,0 0,-9 z"
+ id="path40603"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40605"
+ d="m 49.5,246.5 0,-1 3,0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 49.5,249.5 0,-1 1,0"
+ id="path40615"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 57.5,242.5 0,-1 3,0"
+ id="use40619"
+ inkscape:connector-curvature="0" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path40605"
+ id="use40963"
+ transform="translate(3,3)"
+ width="600"
+ height="512" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path40605"
+ id="use40969"
+ transform="translate(8,3)"
+ width="600"
+ height="512"
+ style="opacity:0.9" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path40605"
+ id="use40971"
+ transform="translate(0,6)"
+ width="600"
+ height="512" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path40605"
+ id="use40973"
+ transform="translate(5,6)"
+ width="600"
+ height="512" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path40615"
+ id="use40975"
+ transform="translate(10,3)"
+ width="600"
+ height="512"
+ style="opacity:0.9" />
+ </g>
+ </g>
+ <g
+ id="g40825"
+ transform="translate(0,1)">
+ <rect
+ y="260"
+ x="215"
+ height="16"
+ width="16"
+ id="rect40827"
+ 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"
+ 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="g40829"
+ transform="translate(67.999923,253.00001)">
+ <path
+ style="fill:url(#linearGradient40843);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 148.50005,9.5 7.00001,3.68e-5 1e-5,2.9999632 -4,0 0,4 -3.00002,0.0039 0,-7.00391 0,10e-6 z"
+ id="path40831"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ transform="matrix(1,5.248259e-6,0,1,0,0)"
+ y="14.499187"
+ x="153.49606"
+ height="6.9999576"
+ width="7.004014"
+ id="rect40833"
+ style="fill:url(#linearGradient40845);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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
+ sodipodi:nodetypes="ccccccc"
+ id="path40835"
+ d="m 148.50005,9.5 7.00001,3.68e-5 1e-5,2.9999632 -4,0 0,4 -3.00002,0.0039 0,-7.00391 0,10e-6 z"
+ style="fill:none;stroke:#0b1728;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 149.50015,15.500012 7e-5,-5.000011 4.99993,0"
+ id="path40837"
+ 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" />
+ <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"
+ 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:7.40000265;display:inline"
+ id="rect40839"
+ width="7.004014"
+ height="6.9999576"
+ x="153.49606"
+ y="14.499187"
+ transform="matrix(1,5.248259e-6,0,1,0,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="path40841"
+ d="m 154.50063,20.499995 6e-5,-4.999998 4.99933,0 6e-5,4.999993 -4.99945,5e-6 z"
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient40847);stroke-width:1.00000012px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g23613" />
+ <g
+ style="display:inline;enable-background:new"
+ transform="translate(404,214.02012)"
+ id="g13021">
+ <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"
+ width="16"
+ height="16"
+ x="63"
+ y="48" />
+ <g
+ id="g12991"
+ 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"
+ transform="matrix(1.0003553,0,0,0.9995949,19.983834,-40.953347)">
+ <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"
+ style="opacity:0.35;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80001998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="rect13004"
+ width="10.996093"
+ height="11.004457"
+ x="45.5"
+ y="91.49041" />
+ <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="opacity:0.2;fill:none;stroke:url(#linearGradient23510);stroke-width:1.0000248px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ d="m 46.499645,101.49618 0,-9.003652 8.996803,-0.0017 0,9.003642 -8.996803,0.002 0,-2.9e-4 0,0 0,0 z"
+ id="path13009"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient23512);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.80001998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40018745;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 53.247247,91.490409 3.248846,0.0015 0,11.002931 -10.996093,1e-5 0,-3.251316 7.747247,-7.753141 0,1.6e-5 z"
+ id="rect12993"
+ sodipodi:nodetypes="cccccc"
+ 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:url(#linearGradient23514);stroke-width:1.0000248px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 46.499451,101.49446 1.94e-4,-1.750708 7.247425,-7.252938 1.749378,0 10e-7,9.001936 -8.996998,0.002 0,-2.9e-4 0,0 0,0 z"
+ id="path12995"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ </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"
+ transform="translate(-42.01991,-103.9242)">
+ <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"
+ id="rect23589"
+ width="16"
+ height="16"
+ x="-382.01102"
+ y="403.99695" />
+ <g
+ id="g23591">
+ <rect
+ style="fill:none;stroke:#04090f;stroke-width:2.89999986;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23594"
+ width="8.4671335"
+ height="5.6703448"
+ x="-33.946648"
+ y="-559.34406"
+ ry="2.143424"
+ rx="2.1489482"
+ transform="matrix(-0.7071068,0.7071068,-0.7071068,-0.7071068,0,0)" />
+ <rect
+ rx="2.1489475"
+ ry="2.1434233"
+ y="-557.84644"
+ x="-28.308893"
+ height="5.5734196"
+ width="8.5043812"
+ id="rect23596"
+ style="fill:none;stroke:#04090f;stroke-width:2.89999986;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="matrix(-0.7071068,0.7071068,-0.7071068,-0.7071068,0,0)" />
+ <path
+ style="fill:none;stroke:url(#linearGradient24349);stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 411.51991,375.4242 -0.5,-0.5 c -0.69131,-0.69131 -0.87523,-2.06255 1.2e-4,-2.92851 l 3.01169,-2.97968 c 0.87526,-0.86596 2.29698,-0.69523 2.98828,-0.004 l 0.52541,0.52542"
+ id="path23598"
+ sodipodi:nodetypes="cssssc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:0.10736198;fill-rule:nonzero;stroke:#04090f;stroke-width:2.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.50000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 408.98474,371.9281 c 0.84182,-0.84182 2.19551,-0.84356 3.03517,-0.004"
+ id="path23561"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cssssc"
+ id="path24352"
+ d="m 411.51991,375.4242 -0.5,-0.5 c -0.69131,-0.69131 -0.87523,-2.06255 1.2e-4,-2.92851 l 3.01169,-2.97968 c 0.87526,-0.86596 2.29698,-0.69523 2.98828,-0.004 l 0.52541,0.52542"
+ style="opacity:0.68999999;fill:none;stroke:url(#radialGradient24354);stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23600"
+ style="fill:none;stroke:url(#linearGradient24341);stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 407.52985,379.36839 c 0.5623,0.50813 1.81497,0.33519 2.49825,-0.3481 l 2.95063,-3.084 c 0.87062,-0.87061 0.69197,-2.30021 0.004,-2.98827 l -1.02382,-1.02382 c -0.69131,-0.69131 -2.11766,-0.86672 -2.98828,0.004 l -2.95063,3.08399 c -0.87062,0.87063 -0.62293,2.42889 -0.004,2.98829 l 1.51384,1.368 1e-5,-9e-5 0,0 0,0 z"
+ sodipodi:nodetypes="ccccccczz"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccczz"
+ d="m 407.52985,379.36839 c 0.5623,0.50813 1.81497,0.33519 2.49825,-0.3481 l 2.95063,-3.084 c 0.87062,-0.87061 0.69197,-2.30021 0.004,-2.98827 l -1.02382,-1.02382 c -0.69131,-0.69131 -2.11766,-0.86672 -2.98828,0.004 l -2.95063,3.08399 c -0.87062,0.87063 -0.62293,2.42889 -0.004,2.98829 l 1.51384,1.368 1e-5,-9e-5 0,0 0,0 z"
+ style="fill:none;stroke:url(#radialGradient23610);stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5"
+ id="path23602"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-opacity:0.10736198;fill-rule:nonzero;stroke:#04090f;stroke-width:2.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.50000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 415.01991,375.9242 c -0.84182,0.84182 -2.16034,0.83966 -3,0"
+ id="path23563"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="csssssc"
+ id="path23604"
+ d="m 417.52541,369.52542 0.49841,0.4984 c 0.68807,0.68805 0.86671,2.11766 -0.004,2.98828 l -2.99178,2.99178 c -0.68328,0.68328 -1.74799,0.71589 -2.49825,0.34809 -0.18628,-0.0913 -0.37463,-0.2925 -0.51148,-0.42936 l -0.7484,-0.74841"
+ style="fill:none;stroke:url(#radialGradient23612);stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g22800"
+ transform="translate(-21,2)">
+ <rect
+ y="260"
+ x="530"
+ height="16"
+ width="16"
+ id="rect23587"
+ 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
+ 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="opacity:0.35;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="rect23591"
+ width="4.0000005"
+ height="15"
+ x="533.5"
+ y="260.5" />
+ <path
+ style="fill:url(#linearGradient22847);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40018745;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 533.5,275.5 4,0 0,-1 c 0,-2.5 2,-5 5,-5 l 1,0 0,-4 -1,0 c -5.17135,0 -9,3.25 -9,9 l 0,1 z"
+ id="path23595"
+ sodipodi:nodetypes="ccssccssc"
+ 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="opacity:0.2;fill:none;stroke:url(#linearGradient22849);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ d="m 534.50003,274.5 0,-12.99752 1.99998,-0.002 0,12.99752 -1.99998,0.002 z"
+ id="path23593"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path23709"
+ d="m 542.5,266.5 c -4.89085,0.22833 -7.75,2.75 -8,8"
+ style="fill:none;stroke:url(#linearGradient22851);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>
+ <g
+ id="g23347"
+ transform="translate(251.98387,128)"
+ style="display:inline">
+ <rect
+ y="428"
+ x="26.016129"
+ height="16.000002"
+ width="16.000006"
+ id="rect23350"
+ 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" />
+ <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="rect23352"
+ width="16"
+ height="16"
+ x="26"
+ y="428" />
+ <g
+ style="display:inline"
+ id="g23354"
+ 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.11238,367.28985)">
+ <path
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path23356"
+ style="fill:#724c4c;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.10749674;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"
+ 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.81218,0,0,0.815735,163.7897,-27.2907)" />
+ <path
+ transform="matrix(0.7480284,0,0,0.7480284,172.26025,-19.267349)"
+ sodipodi:type="arc"
+ style="fill:#f9f9f9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.16363633;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path23358"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(0.7478104,0,0,0.7510504,172.29077,-19.598754)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path23360"
+ style="opacity:0.6;fill:url(#linearGradient23373);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccc"
+ id="path40668"
+ d="m 269.98748,62.965763 c -1.39411,0.455357 -2.67784,0.634788 -4.24803,3.011091 l 2.24896,0 1.99907,-3.011091 0,0 0,0 0,0 z m 0.99954,0 0,3.011091 2.99861,0 -1.99908,-3.011091 -0.99953,0 z m 2.99861,3.011091 0.99953,3.011091 1.99907,0 c 0.006,-0.929403 -0.1914,-1.917894 -0.74965,-3.011091 l -2.24895,0 0,0 0,0 0,0 z m 0.99953,3.011091 -3.99814,0 0,3.011092 2.49884,0 1.4993,-3.011092 z m -3.99814,3.011092 -2.99861,0 1.99907,3.011091 0.99954,0 0,-3.011091 0,0 0,0 0,0 z m -2.99861,0 -0.99954,-3.011092 -1.99907,0 c -0.006,0.929404 0.1914,1.917895 0.74965,3.011092 l 2.24896,0 0,0 0,0 0,0 z m -0.99954,-3.011092 3.99815,0 0,-3.011091 -2.49884,0 -1.49931,3.011091 0,0 0,0 0,0 z m 7.24312,3.011092 -1.85125,3.011091 c 1.3675,-0.485137 2.19971,-0.728674 3.85384,-3.011091 l -2.00259,0 z"
+ style="fill:url(#linearGradient23375);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" />
+ <path
+ style="fill:#990d18;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 274.00069,72.011668 0.005,0.97479 -0.99045,0.01431 -0.0223,1.019377 -0.481,0.837285 c 0.77072,-0.321774 2.72643,-1.067855 3.69499,-2.816464 l -2.20604,-0.0293 -2e-4,2e-6 0,0 0,0 z"
+ id="path23365"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.4;fill:url(#linearGradient23377);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path40671"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.749782,0,0,0.752489,172.03052,-19.77379)" />
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path23369"
+ style="fill:none;stroke:url(#linearGradient23379);stroke-width:1.14049816;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:type="arc"
+ transform="matrix(0.7010701,0,0,0.7040938,178.4346,-14.083074)" />
+ <path
+ id="path23371"
+ d="m 268.98793,64.973163 0,0.407752 -0.93706,0 0,0.595945 -0.56224,0 0,1.003697 -0.49977,0 0,1.505546 0.99953,0 0,-1.505546 0.4373,0 0,-0.595945 0.56224,0 0,-0.407752 1.53054,0 0,-1.003697 -1.53054,0 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#aaccff;stroke-width:0;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" />
+ </g>
+ </g>
+ <g
+ id="g22826"
+ transform="translate(21,-18.979877)">
+ <rect
+ y="281"
+ x="509"
+ height="16"
+ width="16"
+ id="rect22743"
+ 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="g22808">
+ <g
+ id="g23567">
+ <path
+ style="fill:url(#linearGradient23565);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40018745;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 511.5,282.5 1.25,0 1.5,1 5.5,0 1.5,-1 1.25,0 0,8.25 c 0,6.25 -11,6.25 -11,0 l 0,-8.25 z"
+ id="path22751"
+ sodipodi:nodetypes="ccccccccc"
+ 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:url(#linearGradient23562);stroke-width:0.99999982px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 512.5,291 0,-7.25 c 0.8354,1.24437 8.04784,1.12713 9,0 l 0,7.25 c 0,4.5 -9,4.5 -9,0 z"
+ id="path22753"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g23624"
+ style="opacity:0.5">
+ <g
+ id="g23620">
+ <rect
+ y="286"
+ x="514"
+ height="3"
+ width="3"
+ id="rect23592"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999994;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ rx="1.0220957"
+ ry="1.1453303" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999994;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 518.8317,286 1.3366,0 c 0.46076,0 0.8317,0.49209 0.8317,1.10334 l 0,0.79332 C 521,288.50791 520.62906,289 520.1683,289 l -1.3366,0 C 518.37094,289 518,288.50791 518,287.89666 l 0,-0.79332 C 518,286.49209 518.37094,286 518.8317,286 z"
+ id="rect23595"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g23614">
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999994;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23599"
+ width="2"
+ height="2"
+ x="514"
+ y="290" />
+ <rect
+ y="291"
+ x="515"
+ height="2"
+ width="4.5"
+ id="rect23601"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999994;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:0.99999994;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23607"
+ width="1.25"
+ height="2"
+ x="519.5"
+ y="290" />
+ </g>
+ </g>
+ <path
+ style="fill:#0b1728;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999994;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 514,287.25 1.25,-1.25 0.75,0 0,2 -2,0 0,-0.75 z"
+ id="rect23575"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="290"
+ x="514"
+ height="1"
+ width="1"
+ id="rect23577"
+ style="fill:#162d50;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999994;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#162d50;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999994;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23579"
+ width="4"
+ height="1"
+ x="515"
+ y="291" />
+ <rect
+ style="fill:#162d50;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999994;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23583"
+ width="1"
+ height="1"
+ x="519"
+ y="290" />
+ <path
+ style="fill:#0b1728;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999994;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 520,286 -0.75,0 -1.25,1.25 0,0.75 2,0 0,-2 z"
+ id="rect23597"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24003"
+ transform="translate(210,-37)"
+ style="display:inline">
+ <g
+ style="display:inline"
+ id="g24005"
+ transform="translate(90,-142)">
+ <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="rect24007"
+ width="16"
+ height="16"
+ x="-64"
+ y="336" />
+ <g
+ transform="translate(1,0)"
+ id="g24009">
+ <g
+ transform="translate(-386,446.5)"
+ id="g24011">
+ <path
+ id="path24028"
+ 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:#1a1a1a;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="path24030"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(179,-179)"
+ id="g24032">
+ <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="path24034"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ 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="path24036"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="fill:none;stroke:url(#linearGradient24052);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="path24039"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ style="fill:url(#linearGradient24054);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24041"
+ width="1"
+ height="7.75"
+ x="-57"
+ y="342" />
+ <path
+ style="fill:none;stroke:url(#linearGradient24056);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="path24044"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24062"
+ d="m 202.5,135.71875 -6,2.18085 0,7.36038 6,3.27127 6,-3.27127 0,-7.36038 -6,-2.18085 z"
+ style="opacity:0.65;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;enable-background:new"
+ sodipodi:nodetypes="ccccccc"
+ transform="translate(-259,202)"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:none;stroke:url(#linearGradient24066);stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m -56.5,337.71875 -6,2.18085 0,7.36038 6,3.27127 6,-3.27127 0,-7.36038 -6,-2.18085 z"
+ id="path24058"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24046"
+ style="fill:#ffeeaa;display:inline"
+ transform="translate(-1081.9421,-238.02038)" />
+ </g>
+ <g
+ id="g24311"
+ transform="translate(-16.99965,-228.99997)">
+ <g
+ style="opacity:0.55"
+ transform="translate(21.0003,-3e-5)"
+ id="g24226">
+ <g
+ transform="translate(43.04504,242.48228)"
+ id="g24228">
+ <path
+ style="opacity:0.8;fill:none;stroke:#333333;stroke-width:2.5;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 90.45451,103.98095 0,7 7.00045,0.0368 0,-7 -7.00045,-0.0368 z"
+ id="path24230"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path24232"
+ d="m 90.45451,103.98095 4.5e-4,7.03677 7,0 -4.5e-4,-7.03677 -7,0 z"
+ style="fill:#989898;fill-opacity:1;fill-rule:evenodd;stroke:#e6e6e6;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>
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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="rect24234"
+ width="2.9998772"
+ height="3"
+ x="139.50012"
+ y="352.5"
+ ry="1.4999386"
+ rx="1.4999386" />
+ <rect
+ rx="1.4999386"
+ ry="1.4999386"
+ y="344.50003"
+ x="131.4998"
+ height="3"
+ width="2.9998772"
+ id="rect24236"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.29999995;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:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.29999995;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="rect24238"
+ width="2.9998772"
+ height="3"
+ x="131.50012"
+ y="352.5"
+ ry="1.4999386"
+ rx="1.4999386" />
+ <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="path24240"
+ d="m 142.00027,353 c -0.6694,0 -1.3388,10e-6 -2.0082,10e-6 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:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 134.00042,353.00003 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="path24242"
+ 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;display:inline"
+ d="m 133.99997,345.00003 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="path24244"
+ 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
+ rx="1.4999386"
+ ry="1.4999386"
+ y="344.5"
+ x="139.49985"
+ height="3"
+ width="2.9998772"
+ id="rect24246"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.29999995;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
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 142,345 c -0.6694,0 -1.3388,10e-6 -2.0082,10e-6 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="path24248"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g24250"
+ transform="translate(16.999682,3.99994)">
+ <g
+ id="g24252"
+ transform="translate(43.04504,242.48228)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path24254"
+ d="m 90.45451,103.98095 0,7 7.00045,0.0368 0,-7 -7.00045,-0.0368 z"
+ style="opacity:0.8;fill:none;stroke:#333333;stroke-width:2.5;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:#c3c3c3;fill-opacity:1;fill-rule:evenodd;stroke:#e6e6e6;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 90.45451,103.98095 4.5e-4,7.03677 7,0 -4.5e-4,-7.03677 -7,0 z"
+ id="path24256"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ rx="1.4999386"
+ ry="1.4999386"
+ y="352.5"
+ x="139.50012"
+ height="3"
+ width="2.9998772"
+ id="rect24258"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.29999995;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:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.29999995;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="rect24260"
+ width="2.9998772"
+ height="3"
+ x="131.4998"
+ y="344.50003"
+ ry="1.4999386"
+ rx="1.4999386" />
+ <rect
+ rx="1.4999386"
+ ry="1.4999386"
+ y="352.5"
+ x="131.50012"
+ height="3"
+ width="2.9998772"
+ id="rect24262"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.29999995;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
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 142.00027,353 c -0.6694,0 -1.3388,10e-6 -2.0082,10e-6 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="path24264"
+ 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="path24266"
+ d="m 134.00042,353.00003 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:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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="path24268"
+ d="m 133.99997,345.00003 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:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.29999995;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="rect24270"
+ width="2.9998772"
+ height="3"
+ x="139.49985"
+ y="344.5"
+ ry="1.4999386"
+ rx="1.4999386" />
+ <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="path24272"
+ d="m 142,345 c -0.6694,0 -1.3388,10e-6 -2.0082,10e-6 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:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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"
+ transform="translate(-60,60)">
+ <rect
+ y="-29"
+ x="128"
+ height="16"
+ width="16"
+ id="rect23087"
+ 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" />
+ <g
+ id="g23937">
+ <path
+ sodipodi:nodetypes="cscc"
+ d="m 140,-21 c 1.125,1 3.5,0.25 3.5,-1 0,-1.5 0.47443,-1.637992 -2,-1.5 -0.1033,1.43128 -0.66697,1.819388 -1.5,2.5 z"
+ style="fill:#999999;fill-rule:evenodd;stroke:#000000;stroke-width:0.55000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path23906"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23099"
+ style="fill:#e6e6e6;fill-rule:evenodd;stroke:#000000;stroke-width:0.55000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 132,-21 c -1.125,1 -3.5,0.25 -3.5,-1 0,-1.5 -0.47443,-1.637992 2,-1.5 0.1033,1.43128 0.66697,1.819388 1.5,2.5 z"
+ sodipodi:nodetypes="cscc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23090"
+ style="fill:url(#linearGradient23971);fill-rule:evenodd;stroke:none;display:inline;enable-background:new"
+ d="m 135.75,-25.5 -1.25,-2 -0.75,0 -3.25,2.75 0,1.25 c 0.15379,2.182132 1.3678,1.901463 3,4 l 0,4.5 c 0,1.5 1.5,1.5 2.5,1.5 1,0 2.5,0 2.5,-1.5 l 0,-4.5 c 1.62605,-2.090636 2.83897,-1.844587 3,-4 l 0,-1.25 -3.25,-2.75 -0.75,0 -1.25,2"
+ sodipodi:nodetypes="cccccccsccccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.8;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23876"
+ width="2"
+ height="1"
+ x="135"
+ y="-16" />
+ <rect
+ y="-21"
+ x="135"
+ height="2"
+ width="2.75"
+ id="rect23881"
+ style="fill:url(#linearGradient24099);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ ry="1"
+ rx="1" />
+ <rect
+ 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"
+ id="rect23883"
+ width="2"
+ height="1"
+ x="135"
+ y="-21" />
+ <path
+ sodipodi:type="arc"
+ style="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"
+ id="path23902"
+ sodipodi:cx="133"
+ sodipodi:cy="-23"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 134,-23 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ transform="translate(0.5,-0.46875)" />
+ <path
+ transform="matrix(1.2143583,0,0,1.1512108,-28.054112,2.9290602)"
+ d="m 134,-23 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="-23"
+ sodipodi:cx="133"
+ id="path23125"
+ style="fill:none;stroke:url(#linearGradient23973);stroke-width:0.93034029;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:type="arc" />
+ <path
+ transform="matrix(0.8392157,0,0,0.8382979,21.884318,-4.2140957)"
+ d="m 134,-23 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="-23"
+ sodipodi:cx="133"
+ id="path23900"
+ style="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"
+ sodipodi:type="arc" />
+ <rect
+ y="-15"
+ x="135"
+ height="1"
+ width="2"
+ id="rect23914"
+ 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" />
+ <path
+ sodipodi:nodetypes="ccccccccccccccccs"
+ d="m 131.88556,-21.103144 c 0.4583,0.371362 1.00745,1.072735 1.61444,1.853144 l 0,3.75 c 0,1.5 1.5,2 2.5,2 1,0 2.5,-0.5 2.5,-2 l 0,-3.75 c 0.64842,-0.833678 1.23114,-1.545786 1.70766,-1.936772 M 130.5,-23.5 l 0,-1.25 3,-2.75 1,0 1.25,1.75 0.5,0 1.25,-1.75 1,0 3,2.75 0,1.25"
+ 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="path23924"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient23975);stroke-width:0.94079971;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="path23960"
+ sodipodi:cx="133"
+ sodipodi:cy="-23"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 134,-23 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ transform="matrix(1.2116904,0,0,1.1282344,-22.693138,2.3776257)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path23970"
+ sodipodi:cx="133"
+ sodipodi:cy="-23"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 134,-23 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 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"
+ d="M 136.75,-24.75 138,-26.5"
+ id="path23929"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path23978"
+ d="m 129.25,-22.25 0.5,-0.5"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.35;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 142.75,-22.5 -0.25,-0.25"
+ id="path23980"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g24504"
+ 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"
+ id="rect23149"
+ width="16"
+ height="16"
+ x="-441"
+ y="281"
+ transform="scale(-1,1)" />
+ <g
+ id="g24488">
+ <g
+ id="g24377"
+ 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"
+ transform="matrix(-1.0003553,0,0,0.9995949,486.01617,193.04665)">
+ <path
+ style="fill:url(#linearGradient24539);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.70001745;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40018745;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 55.496449,92.490815 4.998228,0.0015 -1e-6,6.000906 -4.998227,-4e-6 m -5.997869,0 -3.99858,10e-7 10e-7,-6.002432 3.998579,0"
+ id="path24388"
+ sodipodi:nodetypes="cccccccc"
+ 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:url(#linearGradient24541);stroke-width:1.0000248px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 55.496399,97.494124 3.998631,4.3e-4 10e-7,-4.003331 -3.998582,-3e-6 m -5.997771,-8.55e-4 -2.999032,8.54e-4 -1.96e-4,4.001622 2.99913,0"
+ id="path24390"
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="opacity:0.5"
+ id="g23153"
+ transform="translate(-39.00033,129)">
+ <path
+ sodipodi:nodetypes="cccsccc"
+ id="path23156"
+ d="m 472.50033,152.49994 c -1.9309,0 -3,0.66961 -3,1.5 L 469.50029,166 c 0,0.83039 1.0691,1.5 3,1.5 1.9309,0 3,-0.66961 3,-1.5 l 4e-5,-12.00006 c 0,-0.83039 -1.0691,-1.5 -3,-1.5 z"
+ style="fill:url(#linearGradient24543);fill-opacity:1;fill-rule:nonzero;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path23158"
+ d="m 470.50033,153.99994 -4e-5,12.01111 c 0,0.54648 1,0.54648 2,0.54648 1,0 2,0 2,-0.55753 l 4e-5,-12.01111"
+ style="fill:none;stroke:url(#linearGradient24545);stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(0.9067635,0,0,1.2421435,374.56954,430.00586)"
+ d="m 111.30847,-222 a 3.3084693,1.2798798 0 1 1 -6.61694,0 3.3084693,1.2798798 0 1 1 6.61694,0 z"
+ sodipodi:ry="1.2798798"
+ sodipodi:rx="3.3084693"
+ sodipodi:cy="-222"
+ sodipodi:cx="108"
+ id="path23160"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.73959124;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ style="fill:none;stroke:#1a1a1a;stroke-width:0.69999999;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 472.50033,152.49994 c -0.62477,0 -1.15931,0.0523 -1.5966,0.15704 -0.91421,0.21887 -1.4034,0.66652 -1.4034,1.34296 L 469.50029,166 c 0,0.83039 1.0691,1.5 3,1.5 1.9309,0 3.00029,-0.75001 3,-1.5 l 4e-5,-12.00006 c 0,-1 -1.0691,-1.5 -3,-1.5 z"
+ id="path23163"
+ sodipodi:nodetypes="csccsccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient24547);stroke-width:0.80000001;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 469.50033,154 c 0,1.5 1.0691,1.5 3,1.5 1.9309,0 3,-0.25 3,-1.5"
+ id="path24484"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path24404"
+ style="fill:url(#linearGradient24549);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 436.5,292 c -2.9e-4,-0.74999 -2.9e-4,-6.75005 0,-6.00006 2.9e-4,0.74999 -1.0691,1.5 -3,1.5 -1.9309,0 -3,-0.66961 -3,-1.5 0,-0.83039 0,5.16967 0,6.00006 0,0.83039 1.0691,1.5 3,1.5 1.9309,0 3.00029,-0.75001 3,-1.5 z"
+ sodipodi:nodetypes="ccsccsc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.3;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 430.75001,287.5 c 0,0.54447 0.98001,0.98352 2.75,0.98352 1.77,0 2.75027,-0.49177 2.75,-0.98352"
+ id="path24464"
+ sodipodi:nodetypes="csc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24472"
+ style="fill:none;stroke:url(#linearGradient24551);stroke-width:0.80000001;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 430.5,285.75 0,5.5 m 6,-5.5 0,5.5"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="csc"
+ id="path24424"
+ d="m 430.5,285.5 0,0.5 c 0,0.83039 1.0691,1.5 3,1.5 1.9309,0 3.00029,-0.75001 3,-1.5 l 0,-0.5"
+ style="fill:none;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 430.5,291.5 0,0.75 c 0,0.75 1.0691,1.25 3,1.25 1.9309,0 3,-0.5 3,-1.25 l 0,-0.75"
+ id="path24470"
+ sodipodi:nodetypes="csccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24095"
+ transform="translate(126,23)">
+ <g
+ style="opacity:0.45;display:inline"
+ id="g23290"
+ transform="translate(216,191)">
+ <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="rect23292"
+ width="16"
+ height="16"
+ x="83"
+ y="48" />
+ <g
+ style="display:inline"
+ id="g23294"
+ transform="matrix(1.1658027,0,0,1.1657997,-59.289717,-204.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
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path23297"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.98948926;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.6969446,0,0,0.6900977,36.918531,141.69345)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.8;fill:url(#linearGradient24112);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path23299"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.6391427,-0.07194179,0.07284933,-0.6344823,204.68584,307.47408)" />
+ <path
+ transform="matrix(0.5885088,0,0,0.5897133,51.241774,153.48488)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient24114);stroke-width:1.45605874;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path23301"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="translate(0,-1)"
+ id="g23266"
+ style="display:inline;enable-background:new">
+ <g
+ id="g24238">
+ <path
+ style="opacity:0.7;fill:url(#linearGradient24116);fill-opacity:1;fill-rule:nonzero;stroke:#132747;stroke-width:0.69999999;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 313.25,246.5 c -2.13129,3.51035 -4.20028,0.92659 -6.75,0 -2.5,-0.90852 -5.25,-1.69675 -5.75,-0.25 -1,3.5 1.75,8.25 6.25,8.25 4.5,0 7.25,-4.5 6.25,-8 z"
+ id="path24164"
+ sodipodi:nodetypes="csczc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path24220"
+ d="M 301.49346,248.00351 C 300.75,245 304.5,246.75 307.5,247.5"
+ style="fill:none;stroke:url(#linearGradient24118);stroke-width:1.00000083;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ 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.0828313,0,0,1.0828897,167.85295,5.9780113)"
+ id="g24116"
+ style="display:inline;enable-background:new"
+ clip-path="url(#clipPath24168)">
+ <path
+ transform="matrix(0.75,0,0,0.75,29.5,135)"
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient24121);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.98504531;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="path24134"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(0.6352868,0,0,0.6352859,44.642106,148.53594)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient24123);stroke-width:1.45364487;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="path24144"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ sodipodi:nodetypes="cs"
+ id="path24166"
+ d="m 306.9667,246.52825 c -1.63301,1.38546 -3.26623,2.75322 -4.93069,1.49745"
+ style="fill:none;stroke:#132747;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 313.25,246.25 c -1,-3.5 -4.2097,-1.48101 -6.2833,0.27825"
+ id="path24198"
+ sodipodi:nodetypes="cs"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41107"
+ 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="rect41109"
+ width="16"
+ height="16"
+ x="110"
+ y="260" />
+ <g
+ style="display:inline"
+ id="g41111"
+ transform="translate(-92.033883,254)">
+ <g
+ id="g41113"
+ transform="translate(20.05,-0.09375)">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path41115"
+ d="m 195.7,12.34375 -8.21612,8.25"
+ style="fill:none;stroke:#0b1728;stroke-width:2.70000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(0.941788,0.336207,-0.336207,0.941788,16.5539,-62.39971)"
+ id="g41117">
+ <path
+ sodipodi:nodetypes="csccsc"
+ id="path41119"
+ d="m 191.82819,15.661146 c -2.50169,-2.892812 -3.51599,-3.257525 -5.63502,-2.501059 -1.55469,0.555005 -3.0441,1.883066 -4.82641,-0.135198 l 3.04462,-5.5995832 c 1.58362,1.6624741 2.57888,1.2029919 3.73322,0.7909034 1.64813,-0.5883624 2.98174,-0.5189446 6.10591,2.3329558"
+ style="fill:url(#linearGradient41127);fill-opacity:1;fill-rule:evenodd;stroke:#0b1728;stroke-width:0.80000007;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient41129);stroke-width:0.85000008;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
+ d="m 184.59619,8.6865928 -2.20359,4.2375362 c 0.98797,0.735441 2.20267,0.01003 3.54842,-0.470383 2.11902,-0.756466 3.52208,-0.551271 5.62148,1.765004 l 1.625,-3.46875 c -2.19923,-2.2239943 -3.61351,-2.2477085 -5.02619,-1.7433979 -1.08094,0.3858805 -2.30419,0.5856276 -3.56512,-0.3200093 z"
+ id="path41121"
+ sodipodi:nodetypes="ccsccsc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="fill:#6593d4;fill-opacity:1;fill-rule:evenodd;stroke:#87aade;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 195.7,12.34375 -8.21612,8.25"
+ id="path41123"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path41125"
+ d="m 191.6399,15.190092 3.2987,-3.242382"
+ style="opacity:0.5;fill:#6593d4;fill-opacity:1;fill-rule:evenodd;stroke:#2c5aa0;stroke-width:0.60000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41132"
+ transform="translate(237.98389,298.06154)">
+ <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"
+ y="195"
+ x="124.01612"
+ height="16"
+ width="16"
+ id="rect41134"
+ 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="g41136">
+ <path
+ id="path41138"
+ style="fill:none;stroke:#000000;stroke-width:3.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 131.51612,200.41538 0,3.2 3,1.88462 2.75,-1.75 m -5.75,-0.62692 -3,2.37692 0,4 m 3,-9.08462 3,0.0846 2,-3 m -10.75,0.25 2.25,2.66538 3.5,0"
+ sodipodi:nodetypes="ccccccccccccc"
+ 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:#acacac;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect41140"
+ width="2"
+ height="1.9692308"
+ x="130.01611"
+ y="196.96924"
+ 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
+ y="196.96924"
+ x="130.01611"
+ height="1.9692308"
+ width="2"
+ id="rect41142"
+ style="opacity:0.95;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;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" />
+ <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="path41144"
+ style="fill:none;stroke:url(#linearGradient41170);stroke-width:1.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 125.76612,197.75 2.25,2.75 3.5,0 m 0,0 0,3 3,2 2.75,-1.75 m -5.75,-0.62692 -3,2.37692 0,4 m 3,-9 3,0 2,-3"
+ sodipodi:nodetypes="ccccccccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41146"
+ 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"
+ id="rect41148"
+ width="16"
+ height="16"
+ x="263"
+ y="194" />
+ <g
+ id="g41150"
+ transform="translate(0,-1)">
+ <path
+ id="path41152"
+ style="fill:none;stroke:#000000;stroke-width:3.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 270.51612,199.5 -0.0161,2 1.75,4 1.25,3 m -3,-7 -1.75,4 -1.25,3"
+ sodipodi:nodetypes="ccccccc"
+ 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:#000000;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect41154"
+ width="2"
+ height="2"
+ x="270.01611"
+ y="196"
+ 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"
+ sodipodi:nodetypes="ccccccc"
+ d="m 270.51612,199.5 3,0 2.75,0 m -11.5,0 2.75,0 3,0"
+ style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path23087"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccccc"
+ d="m 270.51612,199.5 -0.0161,2 1.75,4 1.25,3 m -3,-7 -1.75,4 -1.25,3 m 3.01612,-9 3,0 2.75,0 m -11.5,0 2.75,0 3,0"
+ style="fill:none;stroke:url(#linearGradient41172);stroke-width:1.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path41157"
+ 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
+ y="196"
+ x="269.76608"
+ height="2.75"
+ width="2.4999998"
+ id="rect41159"
+ style="opacity:0.5;fill:none;stroke:url(#radialGradient41174);stroke-width:2;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\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ y="196"
+ x="270.01611"
+ height="2"
+ width="2"
+ id="rect41161"
+ style="fill:#ececec;fill-opacity:1;fill-rule:nonzero;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" />
+ </g>
+ </g>
+ <g
+ transform="translate(28.983879,319.02657)"
+ id="g41999"
+ 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="rect42001"
+ width="16"
+ height="16"
+ x="124.01612"
+ y="195"
+ 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="translate(6.71875e-6,0.03077095)"
+ style="display:inline;enable-background:new"
+ id="g42059">
+ <path
+ id="path42061"
+ style="fill:none;stroke:#000000;stroke-width:3.0999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 131.51612,200.41538 0,3.2 3,1.88462 2.75,-1.75 m -5.75,-0.62692 -3,2.37692 -0.002,3.68505 m 3.00187,-8.76967 3,0.0846 2,-3 m -10.75,0.25 2.25,2.66538 3.5,0"
+ sodipodi:nodetypes="ccccccccccccc"
+ 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:#acacac;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect42063"
+ width="2"
+ height="1.9692308"
+ x="130.01611"
+ y="196.97343"
+ 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
+ y="196.97343"
+ x="130.01611"
+ height="1.9692308"
+ width="2"
+ id="rect42065"
+ style="opacity:0.95;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;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" />
+ <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="path42067"
+ style="fill:none;stroke:url(#linearGradient42069);stroke-width:1.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 125.76612,197.75 2.25,2.75 3.5,0 m 0,0 0,3 3,2 2.75,-1.75 m -5.75,-0.62692 -3,2.37692 -0.002,3.68505 m 3.00187,-8.68505 3,0 2,-3"
+ sodipodi:nodetypes="ccccccccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-19.00001,-0.03076)"
+ style="display:inline;enable-background:new"
+ id="g42015">
+ <g
+ id="g42017"
+ transform="translate(-1.999999,-8.9958)">
+ <path
+ id="path42019"
+ d="m 145.99053,204.49753 0.0368,0 c 0.81818,0 1.47687,0.66665 1.47687,1.49473 l 0,1.2e-4 c 0,0.82808 -0.65869,1.49472 -1.47687,1.49472 l -0.0368,0 c -0.81819,0 -1.47687,-0.66664 -1.47687,-1.49472 l 0,-1.2e-4 c 0,-0.82808 0.65868,-1.49473 1.47687,-1.49473 z"
+ style="fill:none;stroke:#964e00;stroke-width:1.49505997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ 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="path42021"
+ d="m 147.00606,204.9958 c -0.66732,0 -1.33464,1e-5 -2.00196,1e-5 0,0.66707 0,1.33412 0,2.00119 0.66732,0 1.33464,-1e-5 2.00196,-1e-5 0,-0.66706 0,-1.33412 0,-2.00119 z"
+ style="fill:#ffd4a5;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>
+ <g
+ id="g42023"
+ transform="translate(0,-1)">
+ <path
+ style="fill:none;stroke:#964e00;stroke-width:1.49505997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 156.00059,196.50173 0.0368,0 c 0.81818,0 1.47687,0.66665 1.47687,1.49473 l 0,1.2e-4 c 0,0.82808 -0.65869,1.49472 -1.47687,1.49472 l -0.0368,0 c -0.81819,0 -1.47687,-0.66664 -1.47687,-1.49472 l 0,-1.2e-4 c 0,-0.82808 0.65868,-1.49473 1.47687,-1.49473 z"
+ id="path42025"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffd4a5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 157.01612,197 c -0.66732,0 -1.33464,1e-5 -2.00196,1e-5 0,0.66707 0,1.33412 0,2.00119 0.66732,0 1.33464,-1e-5 2.00196,-1e-5 0,-0.66706 0,-1.33412 0,-2.00119 z"
+ id="path42027"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ transform="translate(120,68)"
+ id="g42071"
+ style="display:inline;enable-background:new">
+ <rect
+ y="194"
+ x="263"
+ height="16"
+ width="16"
+ id="rect42073"
+ 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,-1)"
+ id="g42075">
+ <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="ccccccc"
+ d="m 270.51612,199.5 -0.0161,2 1.75,4 1.25,3 m -3,-7 -1.75,4 -1.25,3"
+ style="fill:#162d50;fill-opacity:1;fill-rule:evenodd;stroke:#0b1728;stroke-width:3.0999999;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="path42077"
+ inkscape:connector-curvature="0" />
+ <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"
+ y="196"
+ x="270.01611"
+ height="2"
+ width="2"
+ id="rect42079"
+ style="fill:none;stroke:#0b1728;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <path
+ id="path42081"
+ style="fill:none;stroke:#0b1728;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"
+ d="m 270.51612,199.5 3,0 2.75,0 m -11.5,0 2.75,0 3,0"
+ sodipodi:nodetypes="ccccccc"
+ 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="path42083"
+ style="fill:none;stroke:url(#linearGradient42093);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 270.51612,199.5 -0.0161,2 1.75,4 1.25,3 m -3,-7 -1.75,4 -1.25,3 m 3.01612,-9 3,0 2.75,0 m -11.5,0 2.75,0 3,0"
+ sodipodi:nodetypes="ccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <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="opacity:0.5;fill:none;stroke:url(#radialGradient42091);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect42085"
+ width="2.4999998"
+ height="2.75"
+ x="269.76608"
+ y="196" />
+ <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:#c8d8f0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect42087"
+ width="2"
+ height="2"
+ x="270.01611"
+ y="196" />
+ </g>
+ </g>
+ <g
+ transform="translate(-111,236)"
+ id="g42095"
+ style="display:inline;enable-background:new">
+ <rect
+ y="194"
+ x="263"
+ height="16"
+ width="16"
+ id="rect42097"
+ 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,-1)"
+ id="g42099">
+ <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="ccccccc"
+ d="m 270.51612,199.5 -0.0161,2 1.75,4 1.25,3 m -3,-7 -1.75,4 -1.25,3"
+ style="fill:none;stroke:#241300;stroke-width:3.0999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path42101"
+ inkscape:connector-curvature="0" />
+ <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"
+ y="196"
+ x="270.01611"
+ height="2"
+ width="2"
+ id="rect42103"
+ style="fill:none;stroke:#2b1600;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <path
+ id="path42105"
+ style="fill:none;stroke:#241300;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 270.51612,199.5 3,0 2.75,0 m -11.5,0 2.75,0 3,0"
+ sodipodi:nodetypes="ccccccc"
+ 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="path42107"
+ style="fill:none;stroke:#ffad55;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 270.51612,199.5 -0.0161,2 1.75,4 1.25,3 m -3,-7 -1.75,4 -1.25,3 m 3.01612,-9 3,0 2.75,0 m -11.5,0 2.75,0 3,0"
+ sodipodi:nodetypes="ccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <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="opacity:0.5;fill:none;stroke:url(#radialGradient42115);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect42109"
+ width="2.4999998"
+ height="2.75"
+ x="269.76608"
+ y="196" />
+ <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:#ffb769;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect42111"
+ width="2"
+ height="2"
+ x="270.01611"
+ y="196" />
+ <path
+ sodipodi:nodetypes="ccccccccccccc"
+ d="m 270.51612,199.5 -0.0161,2 1.75,4 1.25,3 m -3,-7 -1.75,4 -1.25,3 m 3.01612,-9 3,0 2.75,0 m -11.5,0 2.75,0 3,0"
+ style="fill:none;stroke:url(#linearGradient42121);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"
+ id="path42117"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(113.22629,214.3098)"
+ id="g42123"
+ 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="rect42125"
+ width="16"
+ height="16"
+ x="124.01612"
+ y="195"
+ 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="g42127"
+ style="opacity:0.8">
+ <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="ccccccccccccc"
+ d="m 131.51612,200.41538 0,3.2 3,1.88462 2.75,-1.75 m -5.75,-0.62692 -3,2.37692 0,4 m 3,-9.08462 3,0.0846 2,-3 m -10.75,0.25 2.25,2.66538 3.5,0"
+ style="fill:none;stroke:#1a1a1a;stroke-width:3.0999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path42129"
+ inkscape:connector-curvature="0" />
+ <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"
+ y="196.96924"
+ x="130.01611"
+ height="1.9692308"
+ width="2"
+ id="rect42131"
+ style="fill:#acacac;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <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="opacity:0.95;fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect42133"
+ width="2"
+ height="1.9692308"
+ x="130.01611"
+ y="196.96924" />
+ <path
+ sodipodi:nodetypes="ccccccccccccc"
+ d="m 125.76612,197.75 2.25,2.75 3.5,0 m 0,0 0,3 3,2 2.75,-1.75 m -5.75,-0.62692 -3,2.37692 0,4 m 3,-9 3,0 2,-3"
+ style="fill:none;stroke:url(#linearGradient42155);stroke-width:1.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path42135"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g42161"
+ transform="translate(-128.99942,340.96539)"
+ style="display:inline;enable-background:new">
+ <g
+ id="g42163"
+ transform="translate(-1.999997,-8)">
+ <path
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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 256,-137.52519 0.0368,0 c 0.81818,0 1.47687,0.66665 1.47687,1.49473 l 0,1.2e-4 c 0,0.82808 -0.65869,1.49472 -1.47687,1.49472 l -0.0368,0 c -0.81819,0 -1.47687,-0.66664 -1.47687,-1.49472 l 0,-1.2e-4 c 0,-0.82808 0.65868,-1.49473 1.47687,-1.49473 z"
+ id="path42165"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;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 257.01553,-137.02692 c -0.66732,0 -1.33464,1e-5 -2.00196,1e-5 0,0.66707 0,1.33412 0,2.00119 0.66732,0 1.33464,-1e-5 2.00196,-1e-5 0,-0.66706 0,-1.33412 0,-2.00119 z"
+ id="path42167"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g42169">
+ <path
+ id="path42171"
+ d="m 265.98447,-145.52519 0.0368,0 c 0.81818,0 1.47687,0.66665 1.47687,1.49473 l 0,1.2e-4 c 0,0.82808 -0.65869,1.49472 -1.47687,1.49472 l -0.0368,0 c -0.81819,0 -1.47687,-0.66664 -1.47687,-1.49472 l 0,-1.2e-4 c 0,-0.82808 0.65868,-1.49473 1.47687,-1.49473 z"
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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"
+ 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="path42173"
+ d="m 267,-145.02692 c -0.66732,0 -1.33464,1e-5 -2.00196,1e-5 0,0.66707 0,1.33412 0,2.00119 0.66732,0 1.33464,-1e-5 2.00196,-1e-5 0,-0.66706 0,-1.33412 0,-2.00119 z"
+ style="fill:#ffffff;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" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g42258"
+ transform="translate(0,86)">
+ <g
+ transform="translate(-111,129)"
+ id="g42260"
+ style="opacity:0.9;display:inline;enable-background:new">
+ <rect
+ y="194"
+ x="263"
+ height="16"
+ width="16"
+ id="rect42262"
+ 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,-1)"
+ id="g42264"
+ style="opacity:0.8">
+ <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="ccccccc"
+ d="m 270.51612,199.5 -0.0161,2 1.75,4 1.25,3 m -3,-7 -1.75,4 -1.25,3"
+ style="fill:none;stroke:#1a1a1a;stroke-width:3.0999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path42266"
+ inkscape:connector-curvature="0" />
+ <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"
+ y="196"
+ x="270.01611"
+ height="2"
+ width="2"
+ id="rect42268"
+ style="fill:none;stroke:#000000;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <path
+ id="path42270"
+ style="fill:none;stroke:#1a1a1a;stroke-width:3.0999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 270.51612,199.5 3,0 2.75,0 m -11.5,0 2.75,0 3,0"
+ sodipodi:nodetypes="ccccccc"
+ 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="path42272"
+ style="fill:none;stroke:url(#linearGradient42290);stroke-width:1.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 270.51612,199.5 -0.0161,2 1.75,4 1.25,3 m -3,-7 -1.75,4 -1.25,3 m 3.01612,-9 3,0 2.75,0 m -11.5,0 2.75,0 3,0"
+ sodipodi:nodetypes="ccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <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="opacity:0.5;fill:none;stroke:url(#radialGradient42292);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect42274"
+ width="2.4999998"
+ height="2.75"
+ x="269.76608"
+ y="196" />
+ <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:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect42276"
+ width="2"
+ height="2"
+ x="270.01611"
+ y="196" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g42278"
+ transform="translate(-83.0076,464.0087)">
+ <path
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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 236.98447,-138.49827 0.0368,0 c 0.81818,0 1.47687,0.66665 1.47687,1.49473 l 0,1.2e-4 c 0,0.82808 -0.65869,1.49472 -1.47687,1.49472 l -0.0368,0 c -0.81819,0 -1.47687,-0.66664 -1.47687,-1.49472 l 0,-1.2e-4 c 0,-0.82808 0.65868,-1.49473 1.47687,-1.49473 z"
+ id="path42280"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;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 238,-138 c -0.66732,0 -1.33464,1e-5 -2.00196,1e-5 0,0.66707 0,1.33412 0,2.00119 0.66732,0 1.33464,-1e-5 2.00196,-1e-5 0,-0.66706 0,-1.33412 0,-2.00119 z"
+ id="path42282"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g42284"
+ transform="translate(-81,470)">
+ <path
+ id="path42286"
+ d="m 246.98447,-144.49827 0.0368,0 c 0.81818,0 1.47687,0.66665 1.47687,1.49473 l 0,1.2e-4 c 0,0.82808 -0.65869,1.49472 -1.47687,1.49472 l -0.0368,0 c -0.81819,0 -1.47687,-0.66664 -1.47687,-1.49472 l 0,-1.2e-4 c 0,-0.82808 0.65868,-1.49473 1.47687,-1.49473 z"
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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"
+ 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="path42288"
+ d="m 248,-144 c -0.66732,0 -1.33464,1e-5 -2.00196,1e-5 0,0.66707 0,1.33412 0,2.00119 0.66732,0 1.33464,-1e-5 2.00196,-1e-5 0,-0.66706 0,-1.33412 0,-2.00119 z"
+ style="fill:#ffffff;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" />
+ </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"
+ 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"
+ inkscape:export-ydpi="90">
+ <rect
+ ry="1.767767"
+ y="596.5"
+ x="69.5"
+ height="13"
+ width="13"
+ id="rect23677"
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;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"
+ rx="1.767767" />
+ <g
+ style="display:inline"
+ id="g23438"
+ transform="translate(45,357.99031)">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ style="fill:url(#linearGradient23775);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 25,239.50969 0.5,-0.5 11,0 0.5,0.5 0,11 -0.5,0.5 -11,0 -0.5,-0.5 0,-11 z"
+ id="path23673"
+ 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="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="rect23655"
+ width="16"
+ height="16"
+ x="23"
+ y="237.00969" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:0.9999997px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 25.499991,250.49338 0,-11.00155 10.999993,0"
+ id="path23447"
+ 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
+ transform="matrix(0.9,0,0,0.9,7.6,60.3)"
+ d="m 80.166667,603 a 4.1666665,4.1666665 0 1 1 -8.333334,0 4.1666665,4.1666665 0 1 1 8.333334,0 z"
+ sodipodi:ry="4.1666665"
+ sodipodi:rx="4.1666665"
+ sodipodi:cy="603"
+ sodipodi:cx="76"
+ id="path23605"
+ style="fill:#dad9d9;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient23777);stroke-width:0.8888889;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:type="arc" />
+ <rect
+ y="602"
+ x="74"
+ height="2"
+ width="1"
+ id="rect23613"
+ style="fill:#000000;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:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23615"
+ width="1"
+ height="2"
+ 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"
+ transform="translate(0,128.00001)">
+ <rect
+ y="427.99997"
+ x="215"
+ height="16"
+ width="16"
+ id="rect51640"
+ 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="rect18676"
+ 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="g23292">
+ <g
+ id="g23271">
+ <g
+ id="g23265">
+ <path
+ inkscape:transform-center-y="-1.75"
+ sodipodi:nodetypes="ccccccc"
+ id="use22458"
+ 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(#linearGradient23257);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="use22460"
+ 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(#linearGradient23254);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="use22462"
+ 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(#linearGradient23251);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="path22465"
+ 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(#linearGradient23248);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" />
+ </g>
+ <g
+ id="g23259">
+ <path
+ inkscape:transform-center-y="-1.75"
+ id="path22585"
+ 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(#linearGradient23244);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="use22587"
+ 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(#linearGradient23239);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="use22589"
+ 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(#linearGradient23235);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="use22591"
+ 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(#linearGradient23231);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="g19146">
+ <rect
+ y="628.25"
+ x="85"
+ height="2.5"
+ width="1"
+ id="rect19148"
+ 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="rect19150"
+ width="1"
+ height="2.5"
+ x="629"
+ y="-86.75" />
+ </g>
+ </g>
+ <g
+ id="g23162"
+ transform="translate(0,-4)">
+ <g
+ id="g23156">
+ <path
+ inkscape:transform-center-y="-1.75"
+ sodipodi:nodetypes="ccccccc"
+ id="use24185"
+ d="m 224.75,442.5 0,0 -3.5,-0.75 -1.5,0 0,1.5 1.5,0 3.5,-0.75 z"
+ style="fill:none;stroke:url(#linearGradient23177);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="use24187"
+ d="m 220.5,446.75 0,0 0.75,-3.5 0,-1.5 -1.5,0 0.25,1.5 0.5,3.5 z"
+ style="fill:none;stroke:url(#linearGradient23179);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="use24189"
+ d="m 216.25,442.5 0,0 3.5,0.75 1.5,0 0,-1.5 -1.5,0 -3.5,0.75 z"
+ style="fill:none;stroke:url(#linearGradient23181);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="path24197"
+ d="m 220.5,438 0,-0.15625 -0.75,3.90625 0,1.5 1.5,0 0,-1.5 -0.75,-3.75 z"
+ style="fill:none;stroke:url(#linearGradient23183);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>
+ <g
+ id="g23150">
+ <path
+ inkscape:transform-center-y="-1.75"
+ id="path24201"
+ 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(#linearGradient23185);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="use24203"
+ 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(#linearGradient23187);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="use24205"
+ 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(#linearGradient23189);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="use24207"
+ 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(#linearGradient23191);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="g24209">
+ <rect
+ y="628"
+ x="85"
+ height="2.9999599"
+ width="1"
+ id="rect24211"
+ 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="rect24213"
+ width="1"
+ height="3"
+ x="629"
+ y="-87" />
+ </g>
+ </g>
+ <g
+ id="g23052"
+ transform="translate(0,4)">
+ <path
+ inkscape:transform-center-y="-1.25"
+ sodipodi:nodetypes="ccccccc"
+ id="path24226"
+ 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(#linearGradient22715);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(#linearGradient22711);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="use24228"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.25"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient22707);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="use24230"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.25"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient22704);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="use24232"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.25"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:transform-center-y="-1.49998"
+ id="path24236"
+ 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(#linearGradient22701);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(#linearGradient22698);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="use24238"
+ inkscape:transform-center-y="-1.49998"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient22695);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="use24240"
+ inkscape:transform-center-y="-1.49998"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient22692);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="use24242"
+ inkscape:transform-center-y="-1.49998"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(133.00004,-201.99996)"
+ id="g24244">
+ <rect
+ y="628.5"
+ x="85"
+ height="2"
+ width="1"
+ id="rect24249"
+ 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="rect24251"
+ width="1"
+ height="2"
+ x="629"
+ y="-86.5" />
+ </g>
+ </g>
+ <g
+ id="g23116"
+ transform="translate(0,-4)">
+ <g
+ transform="translate(0,-6.4549394)"
+ id="g23090">
+ <path
+ inkscape:transform-center-y="-1.75"
+ sodipodi:nodetypes="ccccccc"
+ id="use24445"
+ 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(#linearGradient23132);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" />
+ <path
+ inkscape:transform-center-y="-1.75"
+ sodipodi:nodetypes="ccccccc"
+ id="use24447"
+ 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(#linearGradient23134);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" />
+ <path
+ inkscape:transform-center-y="-1.75"
+ sodipodi:nodetypes="ccccccc"
+ id="use24449"
+ 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(#linearGradient23136);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" />
+ <path
+ style="fill:none;stroke:url(#linearGradient23138);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="path24452"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g23110">
+ <path
+ inkscape:transform-center-y="-1.75"
+ id="path22819"
+ 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(#linearGradient23140);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="path22821"
+ 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(#linearGradient23142);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="path22823"
+ 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(#linearGradient23144);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="path22825"
+ 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(#linearGradient23147);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="g23105">
+ <g
+ transform="translate(141.99999,-184.99353)"
+ id="g24264">
+ <rect
+ y="628.5"
+ x="85"
+ height="2"
+ width="1"
+ id="rect24266"
+ 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="rect24268"
+ width="1"
+ height="2"
+ x="629"
+ y="-86.5" />
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ id="g23415"
+ 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"
+ id="rect23417"
+ 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="rect23419"
+ 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="g23422">
+ <g
+ id="g23424">
+ <g
+ id="g23426">
+ <path
+ style="fill:none;stroke:url(#linearGradient23563);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="path23430"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient23566);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="path23432"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient23568);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="path23434"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient23570);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,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="path23437"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g23439">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23572);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="path23441"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23574);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="path23443"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23576);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="path23449"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23578);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="path23453"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g23455"
+ 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="rect23457"
+ width="1"
+ height="2.5"
+ x="85"
+ y="628.25" />
+ <rect
+ y="-86.75"
+ x="629"
+ height="2.5"
+ width="1"
+ id="rect23463"
+ 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="g23465">
+ <g
+ id="g23467">
+ <path
+ style="fill:none;stroke:url(#linearGradient23580);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.49999,-0.75 -1.50001,0 0,1.5 1.50001,0 3.49999,-0.75 z"
+ id="path23469"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient23582);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="path23472"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient23587);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="path23474"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient23589);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.5 -1e-5,1.5 1.5,0 1e-5,-1.5 -0.75001,-3.5 z"
+ id="path23476"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g23479">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23591);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="path23481"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23593);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="path23484"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23597);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="path23486"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23600);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="path23488"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g23491"
+ 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="rect23493"
+ width="1"
+ height="2.9999599"
+ x="85"
+ y="628" />
+ <rect
+ y="-87"
+ x="629"
+ height="3"
+ width="1"
+ id="rect23496"
+ 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="g23498">
+ <path
+ style="fill:none;stroke:url(#linearGradient23602);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="path23500"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.25"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:transform-center-y="-1.25"
+ sodipodi:nodetypes="ccccccc"
+ id="path23502"
+ 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(#linearGradient23606);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
+ inkscape:transform-center-y="-1.25"
+ sodipodi:nodetypes="ccccccc"
+ id="path23504"
+ 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(#linearGradient23608);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
+ inkscape:transform-center-y="-1.25"
+ sodipodi:nodetypes="ccccccc"
+ id="path23506"
+ 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(#linearGradient23610);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
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23612);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="path23508"
+ inkscape:transform-center-y="-1.49998"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:transform-center-y="-1.49998"
+ id="path23510"
+ 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(#linearGradient23616);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.49998"
+ id="path23512"
+ 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(#linearGradient23618);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.49998"
+ id="path23514"
+ 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(#linearGradient23620);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
+ id="g23517"
+ transform="translate(133.00004,-201.99996)">
+ <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="rect23520"
+ width="1"
+ height="2"
+ x="85"
+ y="628.5" />
+ <rect
+ y="-86.5"
+ x="629"
+ height="2"
+ width="1"
+ id="rect23522"
+ 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="g23524">
+ <g
+ id="g23526"
+ transform="translate(0,-6.4549394)">
+ <path
+ style="fill:none;stroke:url(#linearGradient23622);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="path23529"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient23624);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="path23531"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient23626);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="path23533"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:transform-center-y="-1.75"
+ sodipodi:nodetypes="ccccccc"
+ id="path23535"
+ 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(#linearGradient23628);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" />
+ </g>
+ <g
+ id="g23538">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23630);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="path23541"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23632);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="path23544"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23635);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="path23549"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient23637);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="path23551"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g23555">
+ <g
+ id="g23557"
+ 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="rect23559"
+ width="1"
+ height="2"
+ x="85"
+ y="628.5" />
+ <rect
+ y="-86.5"
+ x="629"
+ height="2"
+ width="1"
+ id="rect23561"
+ 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
+ transform="translate(-21.000008,-166)"
+ id="g23639">
+ <rect
+ y="427.99997"
+ x="215"
+ height="16"
+ 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" />
+ <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>
+ <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>
+ <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" />
+ </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" />
+ </g>
+ </g>
+ <g
+ id="g23757"
+ transform="translate(0,-4)">
+ <g
+ transform="translate(0,-6.4549394)"
+ id="g23759">
+ <path
+ inkscape:transform-center-y="-1.75"
+ 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" />
+ <path
+ inkscape:transform-center-y="-1.75"
+ 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" />
+ <path
+ inkscape:transform-center-y="-1.75"
+ 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" />
+ <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"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:transform-center-y="-1.75"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g23778">
+ <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"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <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" />
+ <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" />
+ <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">
+ <g
+ transform="translate(141.99999,-184.99353)"
+ id="g23791">
+ <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"
+ width="1"
+ height="2"
+ x="629"
+ y="-86.5" />
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ id="g24300"
+ 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"
+ inkscape:export-ydpi="90">
+ <rect
+ y="529"
+ x="117"
+ height="16"
+ width="16"
+ id="rect24298"
+ 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" />
+ <g
+ transform="translate(28.71596,210.64282)"
+ id="g41346"
+ style="display:inline">
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new"
+ id="rect41308"
+ width="14"
+ height="6.0000124"
+ x="88.784042"
+ y="326.84842"
+ ry="2.0305908"
+ rx="2.0305908"
+ 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="1.029202"
+ ry="1.029202"
+ y="327.84842"
+ x="89.784042"
+ height="4.00875"
+ width="12"
+ id="rect41626"
+ style="fill:none;stroke:url(#linearGradient24317);stroke-width:1.00000048;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new"
+ 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="2.0154257"
+ ry="2.0154257"
+ y="319.85718"
+ x="88.784042"
+ height="4.9999971"
+ width="14"
+ id="rect41313"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;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.97821051"
+ ry="0.97821051"
+ y="320.85718"
+ x="89.784042"
+ height="2.9999971"
+ width="12.000008"
+ id="rect41629"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient24319);stroke-width:1.00000048;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new"
+ 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:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect41631"
+ width="8"
+ height="3.9999919"
+ x="89.284042"
+ y="320.35718"
+ rx="0"
+ ry="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"
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient24321);stroke-width:1.00000048;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new"
+ id="rect41633"
+ width="12.000008"
+ height="2.9999971"
+ x="89.784042"
+ y="320.85718"
+ ry="0.97821051"
+ rx="0.97821051" />
+ <rect
+ style="opacity:0.6;fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect41635"
+ width="0.99999988"
+ height="3.0000272"
+ x="96.284042"
+ y="320.85718"
+ rx="0"
+ ry="0" />
+ <g
+ style="opacity:0.8;display:inline;enable-background:new"
+ transform="matrix(-1,0,0,1,193.28404,-130.61032)"
+ id="g41637">
+ <g
+ id="g41639">
+ <rect
+ transform="matrix(-1,0,0,1,194,-1.1e-6)"
+ ry="0"
+ rx="0"
+ y="459.9675"
+ x="91"
+ height="1"
+ width="1"
+ id="rect41641"
+ style="fill:#000000;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(-1,0,0,1,194,-1.1e-6)"
+ style="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="rect24094"
+ width="1"
+ height="3"
+ x="92"
+ y="458.9675"
+ rx="0"
+ ry="0" />
+ <rect
+ style="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="rect24096"
+ width="1"
+ height="1"
+ x="92"
+ y="459.9675"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="458.9675"
+ x="93"
+ height="3"
+ width="1"
+ id="rect24098"
+ style="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>
+ </g>
+ </g>
+ </g>
+ <g
+ id="g24339"
+ transform="translate(0,128.00001)">
+ <rect
+ y="407"
+ x="194"
+ height="16"
+ width="16"
+ id="rect24195"
+ 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" />
+ <g
+ transform="translate(-230,238.99245)"
+ id="g41674"
+ style="display:inline">
+ <path
+ style="fill:url(#linearGradient24238);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 424.5,170.5 0,10.5 1.5,1.5 9.5,0 0,-11 -7,0 0,-1 -4,0 z"
+ id="path24199"
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ style="display:inline"
+ id="g41677"
+ transform="translate(-26,49.00749)">
+ <rect
+ ry="0"
+ rx="0"
+ y="120.50006"
+ x="456.5"
+ height="7.9999371"
+ width="7.0000038"
+ id="rect41679"
+ style="fill:url(#linearGradient24276);fill-opacity:1;fill-rule:nonzero;stroke:#4d4d4d;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <g
+ id="g41681">
+ <path
+ style="fill:#c80000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 192,239 0,2 2,0 0,-2 -2,0 z m 2,2 0,2 2,0 0,-2 -2,0 z m 0,2 -2,0 0,2 2,0 0,-2 z m -2,0 0,-2 -2,0 0,2 2,0 z"
+ transform="translate(267,-117.99994)"
+ id="path41683"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ ry="0"
+ rx="0"
+ y="121.5"
+ x="457.5"
+ height="5.9999981"
+ width="5.0000038"
+ id="rect41685"
+ style="fill:none;stroke:url(#linearGradient24278);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline" />
+ </g>
+ <path
+ style="fill:#d1c595;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient24244);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 427.5,175.5 12,0.008 0,5.5 -1.5,1.49245 -12,0.008 0,-2 1.5,0 0,-5.00755 0,-9e-4 z"
+ id="path41687"
+ 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 426.5,181.5 -1.01563,-0.98437 0,-9.02344 2,0 0,1 2.17355,0.0154"
+ id="path41689"
+ inkscape:connector-curvature="0" />
+ <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 428,181.50755 9.5,0"
+ id="path41691"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41693"
+ d="m 438.5,176.50755 -10,-0.008 0,4.00755 -1.5,1.5 -1.5,-1.5"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient24246);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-rule:evenodd;stroke:none"
+ d="m 428,171.00755 0,2 -3,0 0,-2 3,0 z"
+ id="path24228"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g24230"
+ transform="translate(270,-408)"
+ style="fill:#d45500;fill-opacity:1;display:inline" />
+ <path
+ sodipodi:nodetypes="ccccccccccccc"
+ id="path24234"
+ d="m 424.5,170.5 0,10.5 1.5,1.5 12,0.008 1.5,-1.49245 0,-5.5 -2,-0.008 0,-6 -7,0 0,2 -2,-0.008 0,-1 -4,0 0,4.5e-4 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" />
+ <path
+ style="opacity:0.3;fill:none;stroke:#d40000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ d="m 189.5,244.14308 0,-5.64308 7,0 0,5.64842"
+ id="path41698"
+ sodipodi:nodetypes="cccc"
+ transform="translate(241,-68.99245)"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="fill:#d45500;fill-opacity:1;display:inline"
+ transform="translate(-65,-169.00755)"
+ id="g24176" />
+ <g
+ id="g24393"
+ 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"
+ transform="translate(0,128.00001)">
+ <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="rect24152"
+ width="16"
+ height="16"
+ x="89"
+ y="407" />
+ <g
+ id="g24378">
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path41754"
+ d="m 89.5,409.49245 0,10.5 1.5,1.5 9.5,0 0,-11 -7,0 0,-1 -4,0 z"
+ style="fill:url(#linearGradient24374);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <g
+ style="display:inline"
+ id="g41756"
+ transform="translate(-361,287.99994)">
+ <rect
+ ry="0"
+ rx="0"
+ y="120.50006"
+ x="456.5"
+ height="7.9999371"
+ width="7.0000038"
+ id="rect24160"
+ style="fill:url(#linearGradient41721);fill-opacity:1;fill-rule:nonzero;stroke:#333333;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="121.5"
+ x="457.5"
+ height="5.9999981"
+ width="5.0000038"
+ id="rect24162"
+ style="fill:none;stroke:url(#linearGradient41723);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline" />
+ <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="cccc"
+ id="path41760"
+ style="opacity:0.65;fill:none;stroke:#333333;stroke-width:0.9999997px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 458.49992,122.50172 3.00006,0 m -3.00006,1.99301 3.00006,0"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path41762"
+ d="m 92.5,414.49245 12,0.008 0,5.5 -1.5,1.49245 -12,0.008 0,-2 1.5,0 0,-5.00755 0,-9e-4 z"
+ style="fill:#d1c595;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient24367);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" />
+ <path
+ id="path41764"
+ d="m 91.5,420.49245 -1.01563,-0.98437 0,-9.02344 2,0 0,1 2.17355,0.0154"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41766"
+ d="m 93,420.5 9.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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient24362);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 103.5,415.5 -10,-0.008 0,4.00755 -1.5,1.5 -1.5,-1.5"
+ id="path41768"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path24174"
+ d="m 93,410 0,2 -3,0 0,-2 3,0 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ 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,409.49245 0,10.5 1.5,1.5 12,0.008 1.5,-1.49245 0,-5.5 -2,-0.008 0,-6 -7,0 0,2 -2,-0.008 0,-1 -4,0 0,4.5e-4 z"
+ id="path24178"
+ sodipodi:nodetypes="ccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path24190"
+ d="m 95.5,410.5 0,-2 7,0 0,5.92967"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g22846"
+ transform="translate(84,86)">
+ <rect
+ ry="0"
+ y="323"
+ x="26"
+ height="16"
+ width="16"
+ id="rect22783"
+ 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" />
+ <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 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="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 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 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" />
+ </g>
+ </g>
+ <g
+ id="g23767"
+ 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"
+ id="rect23769"
+ width="16"
+ height="16"
+ x="26"
+ y="323"
+ ry="0" />
+ <g
+ id="g23771">
+ <path
+ sodipodi:nodetypes="cssssssc"
+ id="path23788"
+ 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:#ff8400;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#2b1600;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="path23802"
+ sodipodi:nodetypes="cssssssc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path23808"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ ry="0.765625"
+ rx="0.765625"
+ y="333.25"
+ x="31"
+ height="4.75"
+ width="6"
+ id="rect23810"
+ style="fill:#2b1600;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:#846544;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23812"
+ width="4"
+ height="3"
+ x="32"
+ y="334" />
+ <path
+ sodipodi:nodetypes="cssssccccsccsssc"
+ id="path23816"
+ 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(#linearGradient23890);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ transform="matrix(1.0666667,0,0,1,-233.7,254.00667)"
+ inkscape:connector-curvature="0" />
+ <path
+ 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="path23819"
+ 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
+ id="path23821"
+ 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"
+ inkscape:connector-curvature="0" />
+ <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="rect23824"
+ width="0.25"
+ height="1"
+ x="37"
+ y="336" />
+ <rect
+ y="334"
+ x="36.96875"
+ height="1.099999"
+ width="0.28125"
+ id="rect23826"
+ 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="rect23828"
+ 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="rect23830"
+ width="0.28125"
+ height="1.099999"
+ x="30.90625"
+ y="333.95001" />
+ <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(#linearGradient23892);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.61155295;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path23838"
+ 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="path23840"
+ style="opacity:0.95;fill:url(#radialGradient23894);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
+ id="path23842"
+ style="fill:none;stroke:url(#linearGradient23896);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" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.25;fill:url(#radialGradient23898);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path23844"
+ 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.9552133,0,0,0.9315985,-40.901258,-140.2522)" />
+ <path
+ transform="matrix(0.99567,0,-0.00787885,1,-30.654936,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="path23846"
+ sodipodi:cx="64"
+ sodipodi:cy="135"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 65,135 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 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
+ 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(#radialGradient23900);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;display:inline"
+ id="path23848"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.85;fill:#503416;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23850"
+ width="5"
+ height="0.75"
+ x="31.5"
+ y="333" />
+ <path
+ style="fill:#552c00;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="path23852"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.2;fill:url(#linearGradient23902);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="path23860"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <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="rect23862"
+ width="1"
+ height="1"
+ x="32"
+ y="328" />
+ <path
+ sodipodi:nodetypes="csscssc"
+ id="path23866"
+ style="fill:none;stroke:url(#radialGradient23904);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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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="path23873"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <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="rect23877"
+ width="2"
+ height="1"
+ x="33"
+ y="329" />
+ <rect
+ y="328"
+ x="35"
+ height="1"
+ width="1"
+ id="rect23888"
+ 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
+ id="g23912"
+ 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"
+ id="rect23915"
+ width="16"
+ height="16"
+ x="26"
+ y="323"
+ ry="0" />
+ <g
+ id="g23917">
+ <path
+ sodipodi:nodetypes="cssssssc"
+ id="path23920"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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: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="path23927"
+ sodipodi:nodetypes="cssssssc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path23931"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ ry="0.765625"
+ rx="0.765625"
+ y="333.25"
+ x="31"
+ height="4.75"
+ width="6"
+ id="rect23933"
+ 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:#a89858;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23935"
+ width="4"
+ height="3"
+ x="32"
+ y="334" />
+ <path
+ sodipodi:nodetypes="cssssccccsccsssc"
+ id="path23948"
+ 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(#linearGradient24090);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ transform="matrix(1.0666667,0,0,1,-233.7,254.00667)"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 32.35,336.4 1.25,0"
+ id="path23950"
+ 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
+ id="path23956"
+ d="m 32.35,334.4 1.25,0"
+ style="fill:none;stroke:#ffffff;stroke-width:1.29999995;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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <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="rect23959"
+ width="0.25"
+ height="1"
+ x="37"
+ y="336" />
+ <rect
+ y="334"
+ x="36.96875"
+ height="1.099999"
+ width="0.28125"
+ id="rect23961"
+ 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="rect23965"
+ 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="rect23967"
+ width="0.28125"
+ height="1.099999"
+ x="30.90625"
+ y="333.95001" />
+ <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(#linearGradient24092);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.61155295;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path23982"
+ 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="path23984"
+ style="opacity:0.6;fill:url(#radialGradient24094);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
+ id="path24054"
+ style="fill:none;stroke:url(#linearGradient24096);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" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.25;fill:url(#radialGradient24098);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path24056"
+ 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.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="path24060"
+ sodipodi:cx="64"
+ sodipodi:cy="135"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 65,135 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 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
+ 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(#radialGradient24100);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;display:inline"
+ id="path24064"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.85;fill:#504416;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24066"
+ width="5"
+ height="0.75"
+ x="31.5"
+ y="333" />
+ <path
+ 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="path24068"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.2;fill:url(#linearGradient24102);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="path24070"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <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="rect24072"
+ width="1"
+ height="1"
+ x="32"
+ y="328" />
+ <path
+ sodipodi:nodetypes="csscssc"
+ id="path24078"
+ style="fill:none;stroke:url(#radialGradient24104);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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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="path24082"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <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="rect24086"
+ width="2"
+ height="1"
+ x="33"
+ y="329" />
+ <rect
+ y="328"
+ x="35"
+ height="1"
+ width="1"
+ id="rect24088"
+ 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
+ id="g25056"
+ transform="translate(-168,2)">
+ <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" />
+ <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" />
+ <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" />
+ <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" />
+ <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" />
+ <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" />
+ </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"
+ transform="translate(-126,2)"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <g
+ id="g41200"
+ style="opacity:0.65;display:inline;enable-background:new">
+ <rect
+ y="71"
+ x="341"
+ height="16"
+ width="16"
+ id="rect41164"
+ 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" />
+ <g
+ id="g41166"
+ transform="translate(252,-337)">
+ <path
+ style="fill:url(#linearGradient42055);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,409.49245 0,10.5 1.5,1.5 10.5,0.008 0,-11 -8,-0.008 0,-1 -4,0 z"
+ id="path41168"
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(-361,287.99994)"
+ id="g41170"
+ style="display:inline" />
+ <path
+ style="fill:#d1c595;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient42057);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.49245 11,0.0151 0,5.5 -1.5,1.49245 -11,0 0,-2 1.5,0 0,-5.00755 0,0 0,0 0,0 z"
+ id="path41172"
+ 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,-9.02344 2,0 0,1 L 100.5,411.5"
+ id="path41174"
+ inkscape:connector-curvature="0" />
+ <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 9.5,0"
+ id="path41176"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41178"
+ d="m 102.5,415.5 -9,-0.008 0,4.00755 -1.5,1.5 -1.5,-1.5"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient42059);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 93,410 0,2 -3,0 0,-2 3,0 z"
+ id="path41180"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccc"
+ id="path41182"
+ d="m 89.5,409.50755 0,10.4849 1.5,1.5 11,0.008 1.5,-1.49245 0,-5.5 -2,-0.008 0,-3.9849 -8,-0.008 0,-1 -4,0 0,4.5e-4 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" />
+ </g>
+ </g>
+ <g
+ transform="translate(-81,-80.992447)"
+ id="g24185"
+ style="display:inline">
+ <path
+ sodipodi:nodetypes="ccccccccccccccccccccccc"
+ id="path41134"
+ d="m 428.75,158.5 3,-0.008 0,6.50755 0,2.50755 0.75,0 0,-1 1,0 0,-1 2,0 0,1 1,0 0,1 0.67818,0 0,-9.50755 -0.67818,0 0,-0.5 -0.25,0 0,-0.75 -1.75,-0.008 -4.75,0.008 0,1 -1,0 0,0.75 0,4.5e-4 z"
+ style="fill:none;stroke:#401406;stroke-width:1.00000012;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
+ id="g41137"
+ transform="translate(-16,37.992447)">
+ <g
+ transform="translate(0,-1)"
+ id="g41139">
+ <rect
+ style="fill:#822b0f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24197"
+ width="3"
+ height="0.99999988"
+ x="445"
+ y="121.00755" />
+ <g
+ id="g24199">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path41143"
+ d="m 446,120 0,1 6,0 0,-1 -6,0 z"
+ style="fill:#ed7e5c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccccc"
+ style="fill:#e7541a;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 448,121 0,9.00755 1,0.008 0,-1 1,0 0,-1 1,-0.008 0,1.00755 1,0 0,1 1,-0.008 0,-9.00755 -5,0 0,4.5e-4 0,0 0,0 z"
+ id="path41145"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.6;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"
+ d="m 448,121 0,9.00755 1,0 0,-9.00755 -1,0 0,0 0,0 0,0 z"
+ id="path41147"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path41149"
+ d="m 452,121 0,9.00755 1,0 0,-9.00755 -1,0 0,0 0,0 0,0 z"
+ style="opacity:0.3;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.5;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"
+ d="m 446,120.00755 0,1 2,-0.008 0,-1 -2,0.008 z"
+ id="path41151"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path41153"
+ d="m 445,121.00755 0,1 1,0 0,-1 -1,0 z"
+ style="opacity:0.45;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"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g24216"
+ style="opacity:0.3">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path41156"
+ d="m 451,128.00755 0,1 1,0 0,-1 -1,0 z"
+ style="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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="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"
+ d="m 450,127.00755 0,1 1,0 0,-1 -1,0 0,0 0,0 0,0 z"
+ id="path41158"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path41160"
+ d="m 449,128.00755 0,1 1,0 0,-1 -1,0 z"
+ style="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"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ id="g62487"
+ transform="translate(0,128)">
+ <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"
+ id="rect23556"
+ width="16"
+ height="16"
+ x="281"
+ y="68" />
+ <g
+ transform="matrix(0,-1,1,0,-254.00001,365.00041)"
+ id="g24740">
+ <g
+ style="opacity:0.7"
+ id="g24922">
+ <path
+ d="m 69.5,325.5 0,10 12,0 0,-10 -12,0 z m 6,0 0,10 m 6,-5 -12,0"
+ style="fill:none;stroke:#1a1a1a;stroke-width:2.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"
+ id="path24671"
+ sodipodi:nodetypes="ccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24673"
+ style="fill:none;stroke:#cccccc;stroke-width:1;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 69.5,325.5 0,10 12,0 0,-10 -12,0 z m 6,0 0,10 m 6,-5 -12,0"
+ sodipodi:nodetypes="ccccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ rx="1.4999386"
+ ry="1.4999386"
+ y="323.5"
+ x="80.500122"
+ height="3"
+ width="2.9998772"
+ id="rect24678"
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path24681"
+ d="m 83.00041,324.00001 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:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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="rect24684"
+ width="2.9998772"
+ height="3"
+ x="80.49971"
+ y="334.5"
+ ry="1.4999386"
+ rx="1.4999386" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ d="m 83,335 c -0.6694,0 -1.3388,10e-6 -2.0082,10e-6 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="path24686"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g62412"
+ transform="translate(1,127)">
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ y="67"
+ x="303"
+ height="16"
+ width="16"
+ id="rect23554"
+ 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" />
+ <g
+ transform="matrix(0,1,1,0,-255,214)"
+ id="g24695">
+ <g
+ transform="translate(-356.00003,55.00003)"
+ id="g24697">
+ <g
+ transform="translate(296.99995,249.99998)"
+ id="g24699"
+ 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="g24701"
+ transform="translate(187.99958,-21.0368)">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ d="m 258.50045,291.53677 0,10 12,0 0,-10 -12,0 z m 6,0 0,10 m 6,-5 -12,0"
+ style="opacity:0.9;fill:none;stroke:#2b1600;stroke-width:2.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"
+ id="path24703"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path24705"
+ style="fill:none;stroke:#ed993f;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"
+ d="m 258.50045,291.53677 0,10 12,0 0,-10 -12,0 z m 6,0 0,10 m 6,-5 -12,0"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g24709" />
+ <path
+ sodipodi:nodetypes="cccccccccc"
+ d="m 258.50045,291.53677 0,3.28125 0,6.71875 12,0 0,-10 -12,0 z m 6,0 0,10 m 6,-5 -12,0"
+ style="fill:none;stroke:url(#linearGradient62436);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"
+ id="path24711"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g24713">
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24715"
+ width="1"
+ height="1"
+ x="90"
+ y="325"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="325"
+ x="96"
+ height="1"
+ width="1"
+ id="rect24717"
+ style="fill:#ffffff;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:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24719"
+ width="1"
+ height="1"
+ x="102"
+ y="325"
+ rx="0"
+ ry="0" />
+ </g>
+ <g
+ transform="translate(0,5)"
+ id="g24721">
+ <rect
+ ry="0"
+ rx="0"
+ y="325"
+ x="90"
+ height="1"
+ width="1"
+ id="rect24723"
+ style="fill:#ffffff;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:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24725"
+ width="1"
+ height="1"
+ x="96"
+ y="325"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="325"
+ x="102"
+ height="1"
+ width="1"
+ id="rect24727"
+ style="fill:#ffffff;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="g24729"
+ transform="translate(0,9.96875)">
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24731"
+ width="1"
+ height="1"
+ x="90"
+ y="325.03125"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="325.03125"
+ x="96"
+ height="1"
+ width="1"
+ id="rect24733"
+ style="fill:#ffffff;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:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24736"
+ width="1"
+ height="1"
+ x="102"
+ y="325.03125"
+ rx="0"
+ ry="0" />
+ <path
+ id="rect24766"
+ d="m 70,304 0,1 1,0 0,-1 -1,0 z m 0,1 -1,0 0,1 1,0 0,-1 z m 6,-1 0,1 1,0 0,-1 -1,0 z m 0,1 -1,0 0,1 1,0 0,-1 z m 5,0 0,1 1,0 0,-1 -1,0 z m -11,4 0,1 1,0 0,-1 -1,0 z m 0,1 -1,0 0,1 1,0 0,-1 z m 6,-1 0,1 1,0 0,-1 -1,0 z m 0,1 -1,0 0,1 1,0 0,-1 z m 5,0 0,1 1,0 0,-1 -1,0 z m -11,4 0,1 1,0 0,-1 -1,0 z m 6,0 0,1 1,0 0,-1 -1,0 z"
+ style="opacity:0.27999998;fill:#2b1600;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="translate(21,11.03125)"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g62543"
+ transform="translate(1,2)">
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ y="340"
+ x="261"
+ height="16"
+ width="16"
+ id="rect23562"
+ 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" />
+ <g
+ id="g24926"
+ transform="matrix(0,1,1,0,18,172)">
+ <g
+ id="g24928"
+ transform="translate(-356.00003,55.00003)">
+ <g
+ style="display:inline"
+ 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="g24930"
+ transform="translate(296.99995,249.99998)" />
+ <g
+ transform="translate(187.99958,-21.0368)"
+ id="g24932">
+ <path
+ id="path24935"
+ style="opacity:0.9;fill:none;stroke:#0b1728;stroke-width:2.29999995;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 258.50045,291.53677 0,10 12,0 0,-10 -12,0 z m 6,0 0,10 m 6,-5 -12,0"
+ sodipodi:nodetypes="ccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 258.50045,291.53677 0,10 12,0 0,-10 -12,0 z m 6,0 0,10 m 6,-5 -12,0"
+ style="fill:none;stroke:url(#linearGradient62558);stroke-width:1;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="path24937"
+ sodipodi:nodetypes="ccccccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g24939" />
+ </g>
+ </g>
+ <g
+ id="g24943">
+ <path
+ id="rect24945"
+ transform="translate(-252,42)"
+ d="m 342,283 0,1 1,0 0,-1 -1,0 z m 6,0 0,1 1,0 0,-1 -1,0 z m 6,0 0,1 1,0 0,-1 -1,0 z m -12,5 0,1 1,0 0,-1 -1,0 z m 6,0 0,1 1,0 0,-1 -1,0 z m 6,0 0,1 1,0 0,-1 -1,0 z m -12,5 0,1 1,0 0,-1 -1,0 z m 6,0 0,1 1,0 0,-1 -1,0 z m 6,0 0,1 1,0 0,-1 -1,0 z"
+ style="opacity:0.7;fill:url(#linearGradient62560);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" />
+ </g>
+ <g
+ id="g24951"
+ transform="translate(0,5)" />
+ <g
+ transform="translate(0,9.96875)"
+ id="g24959">
+ <path
+ style="opacity:0.27999998;fill:#162d50;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 70,304 0,1 1,0 0,-1 -1,0 z m 0,1 -1,0 0,1 1,0 0,-1 z m 6,-1 0,1 1,0 0,-1 -1,0 z m 0,1 -1,0 0,1 1,0 0,-1 z m 5,0 0,1 1,0 0,-1 -1,0 z m -11,4 0,1 1,0 0,-1 -1,0 z m 0,1 -1,0 0,1 1,0 0,-1 z m 6,-1 0,1 1,0 0,-1 -1,0 z m 0,1 -1,0 0,1 1,0 0,-1 z m 5,0 0,1 1,0 0,-1 -1,0 z m -11,4 0,1 1,0 0,-1 -1,0 z m 6,0 0,1 1,0 0,-1 -1,0 z"
+ id="path24967"
+ transform="translate(21,11.03125)"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g24707"
+ transform="translate(-210,128)">
+ <rect
+ y="302"
+ x="299"
+ height="16"
+ width="16"
+ id="rect24543"
+ 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" />
+ <path
+ style="fill:#f0a453;fill-opacity:1;fill-rule:nonzero;stroke:#2b1600;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 304.5,308.5 c 1.52069,0 3,-1.25 3,-2.5 0,-2 1.5,-3.5 3.5,-3.5 2,0 3.5,1.568 3.5,3.5 0,1.84581 -1.5,3.5 -3.5,3.5 -1.25,0 -2.5,1.5 -2.5,3 0,2.25 -1.75,4 -4,4 -2.25,0 -4,-1.75 -4,-4 0,-2.25 1.75,-4 4,-4 z"
+ id="path24546"
+ sodipodi:nodetypes="cssssszzs"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 311,303 c -1.75507,0 -3,1.24493 -3,3 0,0.81824 -0.48216,1.55558 -1.125,2.09375 C 306.23216,308.63192 305.39457,309 304.5,309 c -1.996,0 -3.5,1.504 -3.5,3.5 0,1.996 1.504,3.5 3.5,3.5 1.996,0 3.5,-1.504 3.5,-3.5 0,-0.88607 0.36895,-1.73024 0.90625,-2.375 0.5373,-0.64476 1.27281,-1.125 2.09375,-1.125 1.72989,0 3,-1.41958 3,-3 0,-1.67845 -1.25603,-3 -3,-3 z"
+ id="path24792"
+ style="opacity:0.8;fill:url(#linearGradient24797);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.86598092;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:original="M 311 302.5 C 309 302.5 307.5 304 307.5 306 C 307.5 307.25 306.02069 308.5 304.5 308.5 C 302.25 308.5 300.5 310.25 300.5 312.5 C 300.5 314.75 302.25 316.5 304.5 316.5 C 306.75 316.5 308.5 314.75 308.5 312.5 C 308.5 311 309.75 309.5 311 309.5 C 313 309.5 314.5 307.84581 314.5 306 C 314.5 304.068 313 302.5 311 302.5 z "
+ inkscape:radius="-0.48985747"
+ sodipodi:type="inkscape:offset" />
+ <path
+ d="m 311,303.46875 c -1.5178,0 -2.53125,1.01345 -2.53125,2.53125 0,1.00544 -0.55807,1.86332 -1.28125,2.46875 -0.72318,0.60543 -1.66291,1 -2.6875,1 -1.74994,0 -3.03125,1.28131 -3.03125,3.03125 0,1.74994 1.28131,3.03125 3.03125,3.03125 1.74994,0 3.03125,-1.28131 3.03125,-3.03125 0,-1.01789 0.3963,-1.96306 1,-2.6875 0.6037,-0.72444 1.45799,-1.28125 2.46875,-1.28125 1.46823,0 2.53125,-1.20792 2.53125,-2.53125 0,-1.43282 -1.03531,-2.53125 -2.53125,-2.53125 z"
+ id="path24550"
+ style="fill:none;stroke:url(#radialGradient24599);stroke-width:1;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:original="M 311 302.5 C 309 302.5 307.5 304 307.5 306 C 307.5 307.25 306.02069 308.5 304.5 308.5 C 302.25 308.5 300.5 310.25 300.5 312.5 C 300.5 314.75 302.25 316.5 304.5 316.5 C 306.75 316.5 308.5 314.75 308.5 312.5 C 308.5 311 309.75 309.5 311 309.5 C 313 309.5 314.5 307.84581 314.5 306 C 314.5 304.068 313 302.5 311 302.5 z "
+ inkscape:radius="-0.96440691"
+ sodipodi:type="inkscape:offset" />
+ <path
+ transform="translate(96.999991,232.95)"
+ sodipodi:type="arc"
+ style="opacity:0.75;fill:url(#radialGradient43962);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path43958"
+ sodipodi:cx="207.5"
+ sodipodi:cy="79.5"
+ sodipodi:rx="3.5"
+ sodipodi:ry="3.5"
+ d="m 211,79.5 a 3.5,3.5 0 1 1 -7,0 3.5,3.5 0 1 1 7,0 z" />
+ <path
+ d="m 211,79.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="79.5"
+ sodipodi:cx="207.5"
+ id="path43960"
+ style="opacity:0.75;fill:url(#radialGradient43964);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.14754021;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ transform="matrix(0.8714292,0,0,0.8714292,130.17844,236.77138)" />
+ <path
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="-0.96440691"
+ inkscape:original="M 311 302.5 C 309 302.5 307.5 304 307.5 306 C 307.5 307.25 306.02069 308.5 304.5 308.5 C 302.25 308.5 300.5 310.25 300.5 312.5 C 300.5 314.75 302.25 316.5 304.5 316.5 C 306.75 316.5 308.5 314.75 308.5 312.5 C 308.5 311 309.75 309.5 311 309.5 C 313 309.5 314.5 307.84581 314.5 306 C 314.5 304.068 313 302.5 311 302.5 z "
+ style="fill:none;stroke:url(#radialGradient24632);stroke-width:1;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="path24630"
+ d="m 311,303.46875 c -1.5178,0 -2.53125,1.01345 -2.53125,2.53125 0,1.00544 -0.55807,1.86332 -1.28125,2.46875 -0.72318,0.60543 -1.66291,1 -2.6875,1 -1.74994,0 -3.03125,1.28131 -3.03125,3.03125 0,1.74994 1.28131,3.03125 3.03125,3.03125 1.74994,0 3.03125,-1.28131 3.03125,-3.03125 0,-1.01789 0.3963,-1.96306 1,-2.6875 0.6037,-0.72444 1.45799,-1.28125 2.46875,-1.28125 1.46823,0 2.53125,-1.20792 2.53125,-2.53125 0,-1.43282 -1.03531,-2.53125 -2.53125,-2.53125 z"
+ transform="matrix(0,-1,-1,0,617,617)" />
+ <path
+ transform="matrix(0,-1,-1,0,617,617)"
+ d="m 311,303.46875 c -1.5178,0 -2.53125,1.01345 -2.53125,2.53125 0,1.00544 -0.55807,1.86332 -1.28125,2.46875 -0.72318,0.60543 -1.66291,1 -2.6875,1 -1.74994,0 -3.03125,1.28131 -3.03125,3.03125 0,1.74994 1.28131,3.03125 3.03125,3.03125 1.74994,0 3.03125,-1.28131 3.03125,-3.03125 0,-1.01789 0.3963,-1.96306 1,-2.6875 0.6037,-0.72444 1.45799,-1.28125 2.46875,-1.28125 1.46823,0 2.53125,-1.20792 2.53125,-2.53125 0,-1.43282 -1.03531,-2.53125 -2.53125,-2.53125 z"
+ id="path24809"
+ style="fill:none;stroke:url(#linearGradient24820);stroke-width:1;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:original="M 311 302.5 C 309 302.5 307.5 304 307.5 306 C 307.5 307.25 306.02069 308.5 304.5 308.5 C 302.25 308.5 300.5 310.25 300.5 312.5 C 300.5 314.75 302.25 316.5 304.5 316.5 C 306.75 316.5 308.5 314.75 308.5 312.5 C 308.5 311 309.75 309.5 311 309.5 C 313 309.5 314.5 307.84581 314.5 306 C 314.5 304.068 313 302.5 311 302.5 z "
+ inkscape:radius="-0.96440691"
+ sodipodi:type="inkscape:offset" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g23140"
+ 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"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ y="286"
+ x="-6"
+ height="16"
+ width="16"
+ id="rect39828"
+ style="opacity:0;fill:#ffffff;fill-opacity:0.75;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g23145">
+ <g
+ id="g23149">
+ <path
+ id="path39832"
+ style="fill:none;stroke:#1a1a1a;stroke-width:3;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 -4.5,289.5 1.5,0 c 3.5,0 1.9989834,11 6.5,11 2.6782554,0 2.25,-3 5.25,-3 l 0.25,0"
+ sodipodi:nodetypes="csccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccscc"
+ d="m 9,297.5 -0.25,0 c -3,0 -2.5,3 -5.25,3 -4.5010166,0 -3,-11 -6.5,-11 l -2,0"
+ style="fill:none;stroke:#bde7a2;stroke-width:1.60000002;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="path39834"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path39836"
+ style="opacity:0.35;fill:none;stroke:url(#radialGradient23167);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 3.5,300.5 c -4.5,0 -3,-11 -6.5,-11"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g23161">
+ <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="path39839"
+ d="m -4.5,294.5 6,0 c 4,0 2,-7 6,-7 l 1,0"
+ style="fill:none;stroke:#000000;stroke-width:3;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:nodetypes="cssc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cssc"
+ style="fill:none;stroke:#ffffff;stroke-width:1.60000002;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 -5,294.5 6.5,0 c 4,0 2,-7 6,-7 l 1.5,0"
+ id="path23165"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ transform="translate(54,277.99993)"
+ id="g24129"
+ 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">
+ <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="rect24131"
+ width="16"
+ height="16"
+ x="203"
+ y="257" />
+ <g
+ style="display:inline;enable-background:new"
+ 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="g24133"
+ transform="translate(-39.983882,19.00809)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 244.51612,238.49191 -0.0161,3 7.98388,0 0.0161,-3 -7.98388,0 z"
+ id="path39845"
+ 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
+ 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="path39847"
+ d="m 247.51612,241.49191 -0.0161,3 11,0 0.0161,-3 -11,0 z"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;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="ccccc"
+ 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="path39849"
+ d="m 243.5,247.49191 -0.0161,3 12,0 0.0161,-3 -12,0 z"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 250.48388,250.49191 -0.0161,3 7.01612,0 0.0161,-3 -7.01612,0 z"
+ id="path39851"
+ 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" />
+ </g>
+ <path
+ style="fill:none;stroke:url(#linearGradient24202);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 205.51612,259.5 c 0,-0.25 0,-1 0,-1 l 6,0"
+ id="path39853"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path24145"
+ d="m 208.51612,262.5 c 0,-0.25 0,-1 0,-1 l 9,0"
+ style="fill:none;stroke:url(#linearGradient24204);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient24206);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 204.5,268.5 c 0,-0.25 0,-1 0,-1 l 10,0"
+ id="path24147"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient24208);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 211.5,271.5 c 0,-0.25 0,-1 0,-1 l 5,0"
+ id="path39857"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(2,298)"
+ id="g40315"
+ 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">
+ <g
+ id="g40317"
+ transform="matrix(-1.023377,0,0,1.016727,-99.930251,85.381494)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path40319"
+ d="m -114.25921,159.20547 0,-6.88483 5.85921,2.61269 -0.01,7.96045 -5.84921,-3.68831 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.96069634;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ 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"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.96069634;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -102.53333,159.20547 0,-6.88483 -5.86667,2.61269 -0.0101,7.96045 5.87676,-3.68831 10e-6,0 0,0 0,0 z"
+ id="path40321"
+ 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="path40323"
+ d="m -102.53333,152.32064 -5.8704,-1.47533 -5.85548,1.47533 5.85921,2.85858 5.86667,-2.85858 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.96069634;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ 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" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path40325"
+ d="m -114.25921,159.20548 0,-6.88484 5.86294,-1.47532 c 0,2.52838 -0.004,11.53297 -0.004,12.08795 l -5.85864,-3.72779 -3e-4,0 z"
+ style="fill:url(#linearGradient40722);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ 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"
+ style="fill:#c9c9c9;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m -102.53333,159.20548 0,-6.88484 -5.8704,-1.47533 0.003,12.08796 5.86724,-3.72779 1.6e-4,0 0,0 0,0 z"
+ id="path40327"
+ 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="path40329"
+ d="m -102.53333,152.32064 -5.8704,-1.47533 -5.85548,1.47533 5.85548,1.72121 5.8704,-1.72121 z"
+ style="fill:#ffffff;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path40331"
+ d="m -103.02191,152.32064 1e-5,6.63895 0,0 -5.37437,3.44241 -5.37437,-3.44241 1e-5,-6.63895"
+ style="fill:none;stroke:url(#linearGradient40724);stroke-width:0.98034734px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ y="237"
+ x="3"
+ height="16"
+ width="16"
+ id="rect40333"
+ style="fill:none;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ transform="translate(12.401337,137.46985)"
+ id="g40381"
+ 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">
+ <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="rect40383"
+ width="16"
+ height="16"
+ x="265.59866"
+ y="397.53015" />
+ <g
+ style="display:inline"
+ id="g40385"
+ transform="translate(2.6147745,148.53014)">
+ <path
+ id="path40387"
+ d="m 270,251 0,1.625 c -0.53409,0.12195 -1.02562,0.33162 -1.46875,0.625 l -1.29736,-1.49999 -1.5,1.5 1.51611,1.28124 c -0.29338,0.44313 -0.50305,0.93466 -0.625,1.46875 l -1.625,0 0,2 1.625,0 c 0.12195,0.53409 0.33162,1.02562 0.625,1.46875 l -1.51611,1.28126 1.5,1.5 1.29736,-1.50001 c 0.44313,0.29338 0.93466,0.50305 1.46875,0.625 l 0,1.625 2,0 0,-1.625 c 0.53409,-0.12195 1.02562,-0.33162 1.46875,-0.625 l 1.26514,1.50001 1.5,-1.5 -1.25,-1.25 c 0.29338,-0.44313 0.26916,-0.96592 0.39111,-1.50001 l 1.625,0 0,-2 -1.625,0 c -0.12195,-0.53409 -0.0977,-1.05686 -0.39111,-1.49999 l 1.25,-1.25 -1.5,-1.5 -1.25,1.25 C 273.04076,252.70663 272.53409,252.74695 272,252.625 l 0,-1.625 -2,0 z m -1,4 4,0 0,4 -4,0 0,-4 z"
+ style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccc"
+ 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:url(#linearGradient40734);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 270,251 0,1.625 c -0.53409,0.12195 -1.07298,0.0816 -1.51611,0.37501 l -1.25,-1.25 -1.5,1.5 1.25,1.25 c -0.29338,0.44313 -0.23694,0.9659 -0.35889,1.49999 l -1.625,0 0,2 1.625,0 c 0.12195,0.53409 0.0655,1.05688 0.35889,1.50001 l -1.25,1.25 1.5,1.5 1.25,-1.25 c 0.44313,0.29338 0.98202,0.25304 1.51611,0.37499 l 0,1.625 2,0 0,-1.625 c 0.53409,-0.12195 1.04076,-0.0816 1.48389,-0.37499 l 1.25,1.25 1.5,-1.5 -1.25,-1.25 c 0.29338,-0.44313 0.26916,-0.96592 0.39111,-1.50001 l 1.625,0 0,-2 -1.625,0 c -0.12195,-0.53409 -0.0977,-1.05686 -0.39111,-1.49999 l 1.25,-1.25 -1.5,-1.5 -1.25,1.25 C 273.04076,252.70663 272.53409,252.74695 272,252.625 l 0,-1.625 -2,0 z m -1,4 4,0 0,4 -4,0 0,-4 z"
+ id="path40389"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccc"
+ 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="cccccscccccccc"
+ id="path40391"
+ d="M 274.73389,252.25001 273.5,253.75 m -2,-2.25 -1,0 0,1.5 c -0.35104,0.0802 -1.01806,0.29269 -1.5172,0.50569 m -1.49,1.50752 c -0.20864,0.49552 -0.41426,1.14284 -0.4928,1.48679 l -1.5,0 0,1 m 1.5,-5 -0.5,0.5 m 1.25,6.5 -1.51611,1.25001"
+ 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"
+ 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="ccc"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 273.23389,255.50001 0,3.75 L 269.5,259.25"
+ id="path40393"
+ 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
+ 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 266.43389,253.45001 1,-1"
+ id="path40395"
+ sodipodi:nodetypes="cc"
+ 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" />
+ <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-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" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g40520"
+ 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"
+ inkscape:export-ydpi="90">
+ <rect
+ y="407"
+ x="216"
+ height="16"
+ width="16"
+ id="rect40522"
+ 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="g40524"
+ transform="translate(12,170.00654)">
+ <path
+ sodipodi:nodetypes="cccssssssccccsssssscccccc"
+ id="path40526"
+ d="m 207.5,239.5 0,3 0,5.03125 c -0.31763,0.0283 -0.63892,0.0942 -0.96875,0.21875 -0.61538,0.23235 -1.12455,0.59487 -1.5,1.03125 -0.37546,0.43635 -0.63146,0.99926 -0.46875,1.625 0.1627,0.62575 0.6413,0.93109 1.15625,1.03125 0.51496,0.10016 1.1346,0.0761 1.75,-0.15625 0.61542,-0.23236 1.12456,-0.62615 1.5,-1.0625 0.33776,-0.39252 0.53125,-0.86133 0.53125,-1.46875 l 0,-6.25 6,0 0,5.03125 c -0.31763,0.0283 -0.63892,0.0942 -0.96875,0.21875 -0.61538,0.23235 -1.12455,0.59487 -1.5,1.03125 -0.37546,0.43635 -0.63146,0.99926 -0.46875,1.625 0.1627,0.62575 0.6413,0.93109 1.15625,1.03125 0.51496,0.10016 1.1346,0.0761 1.75,-0.15625 0.61542,-0.23236 1.12456,-0.62615 1.5,-1.0625 C 217.30651,249.82623 217.5,249.3373 217.5,248.75 l 0,-9.25 -1,0 -1,0 -6,0 -2,0 z"
+ style="fill:url(#linearGradient40758);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.58322862;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g40528">
+ <path
+ id="path40530"
+ d="m 207.44628,248.42245 c -0.25577,0.0323 -0.54038,0.11684 -0.81334,0.24698 -0.36394,0.17354 -0.65949,0.40136 -0.86757,0.65378 -0.20806,0.2524 -0.34395,0.56878 -0.21514,0.8647 0.12879,0.29592 0.44506,0.40032 0.76358,0.40164 0.3185,0.001 0.6909,-0.0762 1.05486,-0.24968 0.36397,-0.17355 0.65786,-0.41845 0.86594,-0.67084 0.20807,-0.25239 0.34394,-0.56879 0.21514,-0.86472 -0.12879,-0.29592 -0.44345,-0.38323 -0.76195,-0.38454 -0.0796,-3.4e-4 -0.15625,-0.008 -0.24152,0.003 l 0,-3.2e-4 0,0 0,0 z"
+ style="fill:none;stroke:url(#linearGradient40760);stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#cccccc;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 209.5,241.5 6,0"
+ id="path40532"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient40762);stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ d="m 215.4463,248.42245 c -0.25577,0.0323 -0.54038,0.11684 -0.81334,0.24698 -0.36394,0.17354 -0.65949,0.40136 -0.86757,0.65378 -0.20806,0.2524 -0.34395,0.56878 -0.21514,0.8647 0.12879,0.29592 0.44506,0.40032 0.76358,0.40164 0.3185,0.001 0.6909,-0.0762 1.05486,-0.24968 0.36397,-0.17355 0.65786,-0.41845 0.86594,-0.67084 0.20807,-0.25239 0.34394,-0.56879 0.21514,-0.86472 -0.12879,-0.29592 -0.44345,-0.38323 -0.76195,-0.38454 -0.0796,-3.4e-4 -0.15625,-0.008 -0.24152,0.003 l 0,-3.2e-4 0,0 0,0 z"
+ id="path40534"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="opacity:0.96000001;display:inline;enable-background:new"
+ id="g40602"
+ 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"
+ inkscape:export-ydpi="90">
+ <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="rect40604"
+ width="16"
+ height="16"
+ x="299"
+ y="407" />
+ <g
+ 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(0.927848,0,0,0.916217,147.82022,210.72362)"
+ id="g40606"
+ style="display:inline">
+ <path
+ transform="matrix(0.87787,0,0,0.889264,55.67911,118.0341)"
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient42519);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.22752953;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path40608"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ style="fill:none;stroke:url(#linearGradient42523);stroke-width:1.17973554;stroke-opacity:1;display:inline"
+ id="g40610"
+ transform="matrix(0.784039,0,0,0.779055,172.50801,241.28815)"
+ 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\Kopia blender\.blender\icons\blender's iconset.png"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path40612"
+ style="fill:none;stroke:url(#linearGradient42521);stroke-width:1.44816053;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.87787,0,0,0.889264,55.67911,118.0341)" />
+ </g>
+ <path
+ sodipodi:nodetypes="cccc"
+ d="m 309.5,411.5 -3,3 m 0,1 2,2"
+ style="fill:none;stroke:#ffffff;stroke-width:2.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path40614"
+ 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:transform-center-x="-1.25"
+ inkscape:transform-center-y="1.25"
+ id="path40616"
+ style="fill:none;stroke:#aa0000;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 306.5,415.5 2,2"
+ 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" />
+ <rect
+ style="opacity:0.5;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40618"
+ width="1"
+ height="1.5"
+ x="307"
+ y="419" />
+ <rect
+ style="opacity:0.5;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40620"
+ width="1.5"
+ height="1"
+ x="311"
+ y="414" />
+ <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"
+ d="m 309.5,411.5 -3,3"
+ style="fill:none;stroke:#000000;stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path40622"
+ inkscape:transform-center-y="-0.75"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:transform-center-y="-1.0204512"
+ inkscape:transform-center-x="1.4653436"
+ id="path40624"
+ d="m 306.85514,408.97535 c -3.25557,0.003 -5.8936,2.6597 -5.87155,5.95078 0.0105,1.56055 0.63214,2.99542 1.61111,4.05762 2.7831,-7.37691 5.95805,-1.77373 7.49116,-9.06794 -0.92886,-0.60835 -2.04538,-0.9415 -3.23072,-0.94046 l 0,0 0,0 0,0 z"
+ style="fill:url(#linearGradient42525);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="415"
+ x="301.51614"
+ height="1"
+ width="1.4999696"
+ id="rect40626"
+ style="opacity:0.3;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="409.5"
+ x="306"
+ height="1.4999921"
+ width="1"
+ id="rect40628"
+ style="opacity:0.3;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:transform-center-y="-0.75"
+ id="path40630"
+ style="opacity:0.6;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 309.5,411.5 -3,3"
+ 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>
+ <g
+ transform="translate(9,297.99992)"
+ id="g40632"
+ 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">
+ <g
+ style="opacity:0.96000001;display:inline"
+ id="g40634"
+ transform="translate(-1.5986633,-160.53013)">
+ <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="rect40636"
+ width="16"
+ height="16"
+ x="165.59866"
+ y="397.53015" />
+ <g
+ id="g40638"
+ transform="translate(2.6147745,150.03014)"
+ 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">
+ <rect
+ style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="rect40640"
+ width="15.000031"
+ height="16"
+ x="162.99997"
+ y="247.5" />
+ <rect
+ ry="1.9578006"
+ rx="1.9578006"
+ y="250.00002"
+ x="164.48389"
+ height="13.000053"
+ width="11.999973"
+ id="rect40642"
+ style="fill:url(#linearGradient40788);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ d="m 174.48389,251 1,1 0,9 -1,1 -8,0 -1,-1 0,-9 1,-1 8,0 z"
+ style="fill:none;stroke:url(#linearGradient40790);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ id="path40644"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccccccc"
+ transform="translate(-0.0161112,10.500011)"
+ id="path40646"
+ d="m 165.25,238.25 1,-1 0.5,0 0.75,0.75 0.75,-0.75 0.5,0 0.75,0.75 0.75,-0.75 0.5,0 0.75,0.75 0.75,-0.75 0.5,0 0.75,0.83779 0.75,-0.83779 0.5,0 1,1 0,2.75 -0.75,1 -1,0 -0.5,-1 -0.5,1 -1,0 -0.5,-1 -0.5,1 -1,0 -0.5,-1 -0.5,1 -1,0 -0.5,-1 -0.5,1 -1,0 -0.75,-1 0,-2.75 z"
+ style="fill:url(#linearGradient40792);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 166.48389,249.00001 0,2 m 2,-2 0,2 m 2,-2 0,2 m 2,-2 0,2 m 2,-2 0,2"
+ style="fill:none;stroke:url(#linearGradient40794);stroke-width:0.99999976px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ id="path40648"
+ sodipodi:nodetypes="cccccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <rect
+ y="248"
+ x="168"
+ height="1"
+ width="7"
+ id="rect40650"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40652"
+ width="7"
+ height="1"
+ x="168"
+ y="246" />
+ <rect
+ y="244"
+ x="168"
+ height="1"
+ width="7"
+ id="rect40654"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40656"
+ width="1"
+ height="1"
+ x="174"
+ y="250" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g40518"
+ transform="translate(18.999997,-40.99992)">
+ <g
+ style="display:inline"
+ transform="translate(60.98406,570.00002)"
+ id="g40521">
+ <g
+ 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="translate(0.01612278,22)"
+ id="g40523"
+ style="display:inline">
+ <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="path40525"
+ d="m 296.49991,-1.4999999 -13.00008,0 0,-12.9999991 13.00008,0 0,12.9999991 0,0 0,0 0,0 z"
+ style="fill:#333333;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient40545);stroke-width:1.00000036px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 284.50009,-2.5000021 0,-11.0000069 11.00001,0 -2.7e-4,11.000009 -10.99974,-2.1e-6 z"
+ id="path40527"
+ 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.3;fill:#9dac93;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 345,578 0,1 12,0 0,-1 -12,0 z m 0,2 0,1 12,0 0,-1 -12,0 z m 0,2 0,1 12,0 0,-1 -12,0 z m 0,2 0,1 12,0 0,-1 -12,0 z m 0,2 0,1 12,0 0,-1 -12,0 z m 0,2 0,1 12,0 0,-1 -12,0 z"
+ id="path40529"
+ transform="translate(-61.000183,-592.00002)"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient40547);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 295.99982,-1.9999789 -11.9999,0 0,-12.0000411 11.9999,0 0,12.0000411 0,0 0,0 0,0 z"
+ id="path40531"
+ 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" />
+ </g>
+ </g>
+ <rect
+ y="580"
+ x="347"
+ height="1"
+ width="0.99999863"
+ id="rect40533"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40535"
+ width="0.99999863"
+ height="1"
+ x="348"
+ y="581" />
+ <rect
+ y="582"
+ x="349"
+ height="1"
+ width="0.99999863"
+ id="rect40537"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40539"
+ width="0.99999863"
+ height="1"
+ x="348"
+ y="583" />
+ <rect
+ y="584"
+ x="347"
+ height="1"
+ width="0.99999863"
+ id="rect40541"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40543"
+ width="3"
+ height="1"
+ x="350"
+ y="584" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g24081"
+ 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"
+ inkscape:export-ydpi="90">
+ <rect
+ transform="scale(1,-1)"
+ y="-652.00006"
+ x="104"
+ height="16"
+ width="16"
+ id="rect23916"
+ 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="g24071">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ 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="path23922"
+ d="m 118.5,637.6177 -1.25,-1.1177 -10.5,0 -1.25,1.25 0.0161,12.75006 0.9839,0.99994 11,0 1.01611,-0.99994 L 118.5,637.6177 z"
+ style="fill:url(#linearGradient26077);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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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 117,638 -10,0 0,1 10,0 0,-1 z"
+ id="path23926"
+ 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="ccccccccc"
+ style="fill:none;stroke:url(#linearGradient26079);stroke-width:0.99999923px;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 117.5,650.25006 -0.25,0.25 -10.5,0 -0.25,-0.25 0,-12.5 0.25,-0.25 10.5,0 0.25,0.25 0,12.5 z"
+ id="path23928"
+ 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:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23930"
+ width="1"
+ height="1.0000043"
+ x="115"
+ y="-639"
+ 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="scale(1,-1)" />
+ <path
+ style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35476059;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 108,641 0,4 4,0 0,-4 -4,0 z m 4,4 0,4 4,0 0,-4 -4,0 z"
+ id="rect23964"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24035"
+ d="m 108,649 0,-4 4,0 0,4 -4,0 z m 4,-4 0,-4 4,0 0,4 -4,0 z"
+ style="fill:#ececec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35476059;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="-648.5"
+ x="-115.5"
+ height="7"
+ width="7"
+ id="rect23986"
+ style="opacity:0.55;fill:none;stroke:url(#linearGradient26081);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"
+ transform="scale(-1,-1)" />
+ <rect
+ style="opacity:0.4;fill:none;stroke:url(#linearGradient26083);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="rect23971"
+ width="7"
+ height="7"
+ x="108.5"
+ 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"
+ 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"
+ inkscape:export-ydpi="90">
+ <rect
+ transform="scale(1,-1)"
+ y="-652.00006"
+ x="104"
+ height="16"
+ width="16"
+ id="rect23328"
+ 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="g23330">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ 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="path23333"
+ d="m 118.5,637.6177 -1.25,-1.1177 -10.5,0 -1.25,1.25 0.0161,12.75006 0.9839,0.99994 11,0 1.01611,-0.99994 L 118.5,637.6177 z"
+ style="fill:url(#linearGradient23351);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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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 117,638 -10,0 0,1 10,0 0,-1 z"
+ id="path23335"
+ 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="ccccccccc"
+ style="fill:none;stroke:url(#linearGradient23353);stroke-width:0.99999923px;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 117.5,650.25006 -0.25,0.25 -10.5,0 -0.25,-0.25 0,-12.5 0.25,-0.25 10.5,0 0.25,0.25 0,12.5 z"
+ id="path23337"
+ 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:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23339"
+ width="1"
+ height="1.0000043"
+ x="115"
+ y="-639"
+ 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="scale(1,-1)" />
+ <path
+ style="fill:#b41500;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35476059;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 108,641 0,4 4,0 0,-4 -4,0 z m 4,4 0,4 4,0 0,-4 -4,0 z"
+ id="path23341"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path23345"
+ d="m 108,649 0,-4 4,0 0,4 -4,0 z m 4,-4 0,-4 4,0 0,4 -4,0 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35476059;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="-648.5"
+ x="-115.5"
+ height="7"
+ width="7"
+ id="rect23347"
+ style="opacity:0.45;fill:none;stroke:url(#linearGradient23355);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"
+ transform="scale(-1,-1)" />
+ <rect
+ style="opacity:0.4;fill:none;stroke:url(#linearGradient23357);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="rect23349"
+ width="7"
+ height="7"
+ x="108.5"
+ y="641.5" />
+ </g>
+ </g>
+ <g
+ 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"
+ transform="translate(-198,-247)"
+ style="display:inline;enable-background:new">
+ <rect
+ y="257"
+ x="203"
+ height="16"
+ width="16"
+ id="rect42665"
+ 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(-39.983882,19.00809)"
+ id="g42667"
+ 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;enable-background:new">
+ <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="path42669"
+ d="m 244.51612,238.49191 -0.0161,3 7.98388,0 0.0161,-3 -7.98388,0 z"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;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 247.51612,241.49191 -0.0161,3 11,0 0.0161,-3 -11,0 z"
+ id="path42671"
+ 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="ccccc"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 243.5,247.49191 -0.0161,3 12,0 0.0161,-3 -12,0 z"
+ id="path42673"
+ 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="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="path42675"
+ d="m 250.48388,250.49191 -0.0161,3 7.01612,0 0.0161,-3 -7.01612,0 z"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path42677"
+ d="m 205.51612,259.5 c 0,-0.25 0,-1 0,-1 l 6,0"
+ style="fill:none;stroke:url(#linearGradient42685);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient42687);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 208.51612,262.5 c 0,-0.25 0,-1 0,-1 l 9,0"
+ id="path42679"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path42681"
+ d="m 204.5,268.5 c 0,-0.25 0,-1 0,-1 l 10,0"
+ style="fill:none;stroke:url(#linearGradient42689);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path42683"
+ d="m 211.5,271.5 c 0,-0.25 0,-1 0,-1 l 5,0"
+ style="fill:none;stroke:url(#linearGradient42691);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g25594"
+ transform="translate(-306,-275)">
+ <g
+ style="display:inline"
+ transform="translate(363,59)"
+ id="g25596"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Pulpit\common file transparent SMALL.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ ry="0"
+ rx="0.80014729"
+ y="289"
+ x="389"
+ height="16"
+ width="16"
+ id="rect25598"
+ style="opacity:0;fill:#ffffff;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="g25600"
+ transform="translate(-177,71)">
+ <g
+ 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="g25602"
+ transform="translate(480,287.5)">
+ <g
+ id="g25604"
+ transform="translate(-118.5,-200.5)"
+ 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
+ id="g25606"
+ transform="translate(1,24)"
+ style="fill:#000000" />
+ </g>
+ </g>
+ <rect
+ rx="0"
+ y="348"
+ x="752"
+ height="16"
+ width="16"
+ id="rect25608"
+ style="opacity:0;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6;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="path25610"
+ d="m 756.16666,348.50001 10.33334,0 0,14.99999 -13,0 -10e-6,-11.99999 2.66667,-3 z"
+ style="fill:url(#linearGradient25872);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M -48.500031,260.50809 -46.5,260.5 l -3.1e-5,-1.99191"
+ style="opacity:0.8;fill:none;stroke:#000000;stroke-width:0.76923829px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1;display:inline;filter:url(#filter31351)"
+ id="path25612"
+ sodipodi:nodetypes="ccc"
+ transform="matrix(1.2999758,0,0,1.2999988,817.54887,13.43979)"
+ inkscape:connector-curvature="0" />
+ <g
+ mask="url(#mask23591)"
+ transform="translate(725,-419)"
+ id="g25614"
+ style="display:inline">
+ <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="rect25616"
+ width="9"
+ height="13.999984"
+ x="31"
+ y="768" />
+ <g
+ id="g25618">
+ <rect
+ y="771"
+ x="32"
+ height="1"
+ width="1"
+ id="rect25620"
+ 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="rect25622"
+ width="1"
+ height="1"
+ x="32"
+ y="773" />
+ <rect
+ y="775"
+ x="32"
+ height="1"
+ width="1"
+ id="rect25624"
+ 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="rect25626"
+ width="1"
+ height="1"
+ x="32"
+ y="777" />
+ <rect
+ y="779"
+ x="32"
+ height="1"
+ width="1"
+ id="rect25628"
+ 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="rect25630"
+ width="1"
+ height="1"
+ x="32"
+ y="781" />
+ <rect
+ y="771"
+ x="34"
+ height="3"
+ width="3"
+ id="rect25632"
+ 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="rect25634"
+ width="3"
+ height="3"
+ x="34"
+ y="775" />
+ <rect
+ y="779"
+ x="34"
+ height="3"
+ width="3"
+ id="rect25636"
+ 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="rect25638"
+ width="1"
+ height="1"
+ x="38"
+ y="771" />
+ <rect
+ y="773"
+ x="38"
+ height="1"
+ width="1"
+ id="rect25640"
+ 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="rect25642"
+ width="1"
+ height="1"
+ x="38"
+ y="775" />
+ <rect
+ y="777"
+ x="38"
+ height="1"
+ width="1"
+ id="rect25644"
+ 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="rect25646"
+ width="1"
+ height="1"
+ x="38"
+ y="779" />
+ <rect
+ y="781"
+ x="38"
+ height="1"
+ width="1"
+ id="rect25648"
+ 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="rect25650"
+ width="1"
+ height="1"
+ x="32"
+ y="769.02289" />
+ <rect
+ y="769.02289"
+ x="38"
+ height="1"
+ width="1"
+ id="rect25652"
+ 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="rect25654"
+ width="3"
+ height="2"
+ x="34"
+ y="768" />
+ </g>
+ </g>
+ <path
+ sodipodi:nodetypes="cccc"
+ d="m 754.5,353 0,9.5 m 3.5,-13 7.5,0"
+ style="fill:none;stroke:url(#linearGradient25874);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ id="path25656"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 753,352 4,0 0,-4 -4,4 z"
+ id="path25658"
+ 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,351.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="path25660"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g25988"
+ transform="translate(-152,-151)">
+ <g
+ transform="translate(-272,34)"
+ id="g25437"
+ style="display:inline;enable-background:new">
+ <g
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Pulpit\common file transparent SMALL.png"
+ id="g25439"
+ transform="translate(523,-99)"
+ style="display:inline">
+ <rect
+ style="opacity:0;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25442"
+ width="16"
+ height="16"
+ x="389"
+ y="289"
+ rx="0.80014729"
+ ry="0" />
+ <g
+ transform="translate(-177,71)"
+ id="g25444">
+ <g
+ transform="translate(480,287.5)"
+ id="g25446"
+ 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
+ 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"
+ transform="translate(-118.5,-200.5)"
+ id="g25448" />
+ </g>
+ <g
+ style="fill:#000000"
+ transform="translate(1,24)"
+ id="g25450" />
+ </g>
+ </g>
+ <rect
+ style="opacity:0;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25452"
+ width="16"
+ height="16"
+ x="912"
+ y="190"
+ rx="0" />
+ <g
+ id="g25454">
+ <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="path25456"
+ d="m 916.16666,190.50001 10.33334,0 0,14.99999 -13,0 -10e-6,-11.99999 2.66667,-3 z"
+ style="fill:url(#linearGradient26011);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M -48.500031,260.50809 -46.5,260.5 l -3.1e-5,-1.99191"
+ style="opacity:0.8;fill:none;stroke:#000000;stroke-width:0.76923829px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1;display:inline;filter:url(#filter22979)"
+ id="path25458"
+ sodipodi:nodetypes="ccc"
+ transform="matrix(1.2999758,0,0,1.2999988,977.54887,-144.56021)"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ d="m 914.5,195 0,9.5 m 3.5,-13 7.5,0"
+ style="fill:none;stroke:url(#linearGradient26013);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ id="path25460"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 913,194 4,0 0,-4 -4,4 z"
+ id="path25462"
+ 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 913.5,193.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="path25464"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path25582"
+ d="m 650,228 1,0 -10e-6,6.5 -1,0 L 650,228 z"
+ style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 654,227 0,2 -4,0 10e-6,-2 3.99999,0 z"
+ id="path25584"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(0.8571421,0,0,0.8,601.28577,-208.6)"
+ id="g25586"
+ style="display:inline;enable-background:new">
+ <path
+ sodipodi:type="arc"
+ style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path25588"
+ sodipodi:cx="53"
+ sodipodi:cy="554"
+ sodipodi:rx="4.5"
+ sodipodi:ry="2.25"
+ d="m 57.5,554 a 4.5,2.25 0 1 1 -9,0 4.5,2.25 0 1 1 9,0 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 a 4.5,2.25 0 1 1 -9,0 4.5,2.25 0 1 1 9,0 z"
+ sodipodi:ry="2.25"
+ sodipodi:rx="4.5"
+ sodipodi:cy="554"
+ sodipodi:cx="53"
+ id="path25590"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter20578);enable-background:accumulate"
+ sodipodi:type="arc" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path25592"
+ d="m 654,227 0,1 -4,0 10e-6,-1 3.99999,0 z"
+ style="opacity:0.5;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path25662"
+ d="m 645.5,226.5 0,2 -2,0"
+ style="fill:none;stroke:url(#linearGradient26015);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g25963"
+ transform="translate(-86,-139)">
+ <g
+ transform="translate(-262,-147)"
+ id="g25359"
+ style="display:inline;enable-background:new">
+ <g
+ transform="translate(-34,169)"
+ id="g25361">
+ <g
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Pulpit\common file transparent SMALL.png"
+ id="g25363"
+ transform="translate(523,-99)"
+ style="display:inline">
+ <rect
+ style="opacity:0;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25365"
+ width="16"
+ height="16"
+ x="389"
+ y="289"
+ rx="0.80014729"
+ ry="0" />
+ <g
+ transform="translate(-177,71)"
+ id="g25367">
+ <g
+ transform="translate(480,287.5)"
+ id="g25369"
+ 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
+ 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"
+ transform="translate(-118.5,-200.5)"
+ id="g25372" />
+ </g>
+ <g
+ style="fill:#000000"
+ transform="translate(1,24)"
+ id="g25374" />
+ </g>
+ </g>
+ <rect
+ style="opacity:0;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25376"
+ width="16"
+ height="16"
+ x="912"
+ y="190"
+ rx="0" />
+ <g
+ id="g25378">
+ <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="path25380"
+ d="m 916.16666,190.50001 10.33334,0 0,14.99999 -13,0 -10e-6,-11.99999 2.66667,-3 z"
+ style="fill:url(#linearGradient25982);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M -48.500031,260.50809 -46.5,260.5 l -3.1e-5,-1.99191"
+ style="opacity:0.8;fill:none;stroke:#000000;stroke-width:0.76923829px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1;display:inline;filter:url(#filter22999)"
+ id="path25382"
+ sodipodi:nodetypes="ccc"
+ transform="matrix(1.2999758,0,0,1.2999988,977.54887,-144.56021)"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ d="m 914.5,195 0,9.5 m 3.5,-13 7.5,0"
+ style="fill:none;stroke:url(#linearGradient25984);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ id="path25384"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 913,194 4,0 0,-4 -4,4 z"
+ id="path25387"
+ 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 913.5,193.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="path25389"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <path
+ d="m 889.5,372.5 1,0 m 0,-4 -8,0 m 5,2 -5,0 m 1.25,-8 6.75,0 m 0,4 -8,0 m 8,-2 -8,0"
+ style="opacity:0.7;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ id="path25391"
+ sodipodi:nodetypes="cccccccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="fill:none;stroke:url(#linearGradient25986);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 621.5,214.5 0,2 -2,0"
+ id="path25668"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g25933"
+ transform="translate(-107,-115)">
+ <g
+ id="g25393"
+ transform="translate(-296,-2.000004)"
+ style="display:inline;enable-background:new">
+ <g
+ style="display:inline"
+ transform="translate(523,-99)"
+ id="g25396"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Pulpit\common file transparent SMALL.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ ry="0"
+ rx="0.80014729"
+ y="289"
+ x="389"
+ height="16"
+ width="16"
+ id="rect25398"
+ style="opacity:0;fill:#ffffff;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="g25400"
+ transform="translate(-177,71)">
+ <g
+ 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="g25402"
+ transform="translate(480,287.5)">
+ <g
+ id="g25404"
+ transform="translate(-118.5,-200.5)"
+ 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
+ id="g25406"
+ transform="translate(1,24)"
+ style="fill:#000000" />
+ </g>
+ </g>
+ <rect
+ rx="0"
+ y="190"
+ x="912"
+ height="16"
+ width="16"
+ id="rect25408"
+ style="opacity:0;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g25410">
+ <path
+ style="fill:url(#linearGradient25957);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 916.16666,190.50001 10.33334,0 0,14.99999 -13,0 -10e-6,-11.99999 2.66667,-3 z"
+ id="path25413"
+ 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" />
+ <g
+ transform="translate(15.27209,-110)"
+ style="fill:#0044aa;display:inline"
+ id="g25415">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path25417"
+ d="m 902.72791,305 2,0.90909 0,9.09091 -2,0 0,-10 z"
+ style="fill:#214478"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path25419"
+ d="m 901.72791,305 1,0 0.25,0.5 -1.25,0 0,-0.5 z"
+ style="fill:#214478"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path25421"
+ d="m 902.72791,305 6.75,0 0,1 -5.09127,0 -1.65873,-1 z"
+ style="fill:#214478"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="310"
+ x="904.72791"
+ height="1"
+ width="2.7499952"
+ id="rect25423"
+ style="fill:#214478" />
+ <rect
+ y="309.25"
+ x="907.22791"
+ height="2.5"
+ width="0.5"
+ id="rect25425"
+ style="fill:#214478" />
+ <rect
+ y="305"
+ x="909.22791"
+ height="2"
+ width="0.5"
+ id="rect25427"
+ style="fill:#214478" />
+ </g>
+ <path
+ transform="matrix(1.2999758,0,0,1.2999988,977.54887,-144.56021)"
+ sodipodi:nodetypes="ccc"
+ id="path25429"
+ style="opacity:0.8;fill:none;stroke:#000000;stroke-width:0.76923829px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1;display:inline;filter:url(#filter23007)"
+ d="M -48.500031,260.50809 -46.5,260.5 l -3.1e-5,-1.99191"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path25431"
+ style="fill:none;stroke:url(#linearGradient25959);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 914.5,195 0,9.5 m 3.5,-13 7.5,0"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path25433"
+ d="m 913,194 4,0 0,-4 -4,4 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path25435"
+ 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 913.5,193.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"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <path
+ id="path25670"
+ d="m 621.5,190.5 0,2 -2,0"
+ style="fill:none;stroke:url(#linearGradient25961);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g25672"
+ transform="translate(-348,-155)">
+ <g
+ transform="translate(-126,60.000002)"
+ id="g25674">
+ <g
+ transform="translate(-34,-22.000002)"
+ id="g25676">
+ <g
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Pulpit\common file transparent SMALL.png"
+ id="g25678"
+ transform="translate(523,-99)"
+ style="display:inline">
+ <rect
+ style="opacity:0;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25680"
+ width="16"
+ height="16"
+ x="389"
+ y="289"
+ rx="0.80014729"
+ ry="0" />
+ <g
+ transform="translate(-177,71)"
+ id="g25682">
+ <g
+ transform="translate(480,287.5)"
+ id="g25684"
+ 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
+ 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"
+ transform="translate(-118.5,-200.5)"
+ id="g25686" />
+ </g>
+ <g
+ style="fill:#000000"
+ transform="translate(1,24)"
+ id="g25688" />
+ </g>
+ </g>
+ <rect
+ style="opacity:0;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25690"
+ width="16"
+ height="16"
+ x="912"
+ y="190"
+ rx="0" />
+ <g
+ id="g25692">
+ <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="path25694"
+ d="m 916.16666,190.50001 10.33334,0 0,14.99999 -13,0 -10e-6,-11.99999 2.66667,-3 z"
+ style="fill:url(#linearGradient25886);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M -48.500031,260.50809 -46.5,260.5 l -3.1e-5,-1.99191"
+ style="opacity:0.8;fill:none;stroke:#000000;stroke-width:0.76923829px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1;display:inline;filter:url(#filter23015)"
+ id="path25696"
+ sodipodi:nodetypes="ccc"
+ transform="matrix(1.2999758,0,0,1.2999988,977.54887,-144.56021)"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ d="m 914.5,195 0,9.5 m 3.5,-13 7.5,0"
+ style="fill:none;stroke:url(#linearGradient25888);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ id="path25698"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 913,194 4,0 0,-4 -4,4 z"
+ id="path25700"
+ 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 913.5,193.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="path25702"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g25705"
+ transform="translate(910,-321.00012)"
+ mask="none"
+ clip-path="url(#clipPath22590)">
+ <rect
+ y="491.00012"
+ x="-29"
+ height="16"
+ width="16"
+ id="rect25707"
+ 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="g25709">
+ <g
+ id="g25711">
+ <path
+ id="path25713"
+ 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:0.34386529;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M -15.594023,497.94339 -20.25,493.5"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:#000000;stroke-width:1.32768786;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.10397505;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path25715"
+ sodipodi:cx="13.5"
+ sodipodi:cy="57.5"
+ sodipodi:rx="1"
+ sodipodi:ry="1.0000004"
+ d="m 14.5,57.5 a 1,1.0000004 0 1 1 -2,0 1,1.0000004 0 1 1 2,0 z"
+ transform="matrix(3.625,0,0,3.1690202,-67.8125,318.31703)" />
+ <path
+ sodipodi:nodetypes="cccc"
+ d="m -25.5,496.5 7.5,0 m -8.5,5.00012 3.5,-3.5"
+ 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:0.34386529;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path25717"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient25890);stroke-width:0.92424375;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.10397505;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path25719"
+ sodipodi:cx="13.5"
+ sodipodi:cy="57.5"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 14.5,57.5 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ transform="matrix(3.5999897,0,0,3.1249932,-67.499871,320.6879)" />
+ <path
+ id="path25721"
+ style="fill:none;stroke:url(#linearGradient25892);stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.34386529;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -25.5,496.5 7.984366,-0.0226 M -26.5,501.50012 -21.5,496.5 m 5.996227,1.44466 L -20.25,493.5"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(3.25,0,0,3.25,-62.875,313.125)"
+ d="m 14.5,57.5 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="57.5"
+ sodipodi:cx="13.5"
+ id="path25723"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#2c5aa0;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path25725"
+ sodipodi:cx="13.5"
+ sodipodi:cy="57.5"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 14.5,57.5 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 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 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="57.5"
+ sodipodi:cx="13.5"
+ id="path25727"
+ style="fill:none;stroke:url(#linearGradient25894);stroke-width:0.22536004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.10397505;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ id="path25729"
+ style="fill:none;stroke:url(#linearGradient25897);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -20.515634,493.80534 c -0.07079,-0.45769 0.0843,-0.63855 0.5,-0.5 m -6.734366,7.94478 3.280183,-3.10926 m -2,-2 6.25,0"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <path
+ style="fill:none;stroke:url(#linearGradient25899);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 757.5,230.5 0,2 -2,0"
+ id="path25731"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g25822"
+ transform="translate(273,-334)">
+ <rect
+ y="407"
+ x="89"
+ height="16"
+ width="16"
+ id="rect25824"
+ 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" />
+ <g
+ id="g25826">
+ <path
+ style="fill:url(#linearGradient25927);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,408.5 0,11.49245 1.5,1.5 10.5,0.008 0,-11.99245 -8,-0.008 0,-1 -4,0 z"
+ id="path25828"
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(-361,287.99994)"
+ id="g25830"
+ style="display:inline" />
+ <path
+ style="fill:#d1c595;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient25929);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,413.74245 12,0.008 0,6.25 -1.5,1.49245 -12,0.008 0,-2 1.5,0 0,-5.75755 0,-9e-4 z"
+ id="path25832"
+ 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,-10.02344 2,0 0,1 L 100.5,410.5"
+ id="path25834"
+ inkscape:connector-curvature="0" />
+ <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 9.5,0"
+ id="path25836"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path25838"
+ d="m 103.5,414.75 -10,-0.008 0,4.75755 -1.5,1.5 -1.5,-1.5"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient25931);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 93,409 0,2 -3,0 0,-2 3,0 z"
+ id="path25840"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccc"
+ id="path25842"
+ d="m 89.5,408.5 0,11.49245 1.5,1.5 12,0.008 1.5,-1.49245 0,-6.50755 -3,-0.008 0,-3.9849 -8,-0.008 0,-1 -4,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" />
+ </g>
+ </g>
+ <g
+ transform="translate(371,90.000008)"
+ id="g26093">
+ <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"
+ width="16"
+ height="16"
+ x="117"
+ y="529" />
+ <g
+ style="display:inline"
+ id="g26097"
+ transform="translate(28.71596,210.64282)">
+ <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="2.0305908"
+ ry="2.0305908"
+ y="326.84842"
+ x="88.784042"
+ height="6.0000124"
+ width="14"
+ id="rect26099"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new" />
+ <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"
+ style="fill:none;stroke:url(#linearGradient26126);stroke-width:1.00000048;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new"
+ id="rect26101"
+ width="12"
+ height="4.00875"
+ x="89.784042"
+ y="327.84842"
+ ry="1.029202"
+ rx="1.029202" />
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new"
+ id="rect26103"
+ width="14"
+ height="4.9999971"
+ x="88.784042"
+ y="319.85718"
+ ry="2.0154257"
+ rx="2.0154257"
+ 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"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient26128);stroke-width:1.00000048;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new"
+ id="rect26105"
+ width="12.000008"
+ height="2.9999971"
+ x="89.784042"
+ y="320.85718"
+ ry="0.97821051"
+ rx="0.97821051" />
+ <rect
+ ry="0"
+ rx="0"
+ y="320.35718"
+ x="89.284042"
+ height="3.9999919"
+ width="8"
+ id="rect26107"
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ rx="0.97821051"
+ ry="0.97821051"
+ y="320.85718"
+ x="89.784042"
+ height="2.9999971"
+ width="12.000008"
+ id="rect26109"
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient26130);stroke-width:1.00000048;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new"
+ 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"
+ rx="0"
+ y="320.85718"
+ x="96.284042"
+ height="3.0000272"
+ width="0.99999988"
+ id="rect26111"
+ style="opacity:0.6;fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g26113"
+ transform="matrix(-1,0,0,1,193.28404,-130.61032)"
+ style="opacity:0.8;display:inline;enable-background:new">
+ <g
+ id="g26115">
+ <rect
+ style="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="rect26117"
+ width="1"
+ height="1"
+ x="91"
+ y="459.9675"
+ rx="0"
+ ry="0"
+ transform="matrix(-1,0,0,1,194,-1.1e-6)" />
+ <rect
+ ry="0"
+ rx="0"
+ y="458.9675"
+ x="92"
+ height="3"
+ width="1"
+ id="rect26119"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="matrix(-1,0,0,1,194,-1.1e-6)" />
+ <rect
+ ry="0"
+ rx="0"
+ y="459.9675"
+ x="92"
+ height="1"
+ width="1"
+ id="rect26121"
+ style="fill:#000000;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:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect26123"
+ width="1"
+ height="3"
+ x="93"
+ y="458.9675"
+ rx="0"
+ ry="0" />
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ id="g28119"
+ transform="translate(0,127.99999)">
+ <rect
+ y="302"
+ x="404"
+ height="16"
+ width="16.000004"
+ id="rect27916"
+ style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" />
+ <g
+ id="g28110">
+ <path
+ id="path27918"
+ d="m 412,306.45213 c -3.54545,0 -5.90909,1.5 -6.49999,3.04787 0.5909,1.45213 2.95581,3.77094 6.49999,3.75 3.54709,-0.021 5.9091,-2.29787 6.50001,-3.75 -0.59091,-1.54787 -2.95455,-3.04787 -6.50001,-3.04787 z"
+ style="fill:url(#linearGradient28107);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ sodipodi:nodetypes="ccscz"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 434.99991,14.5 a 3.9999149,2.91429 0 1 1 -7.99982,0 3.9999149,2.91429 0 1 1 7.99982,0 z"
+ sodipodi:ry="2.91429"
+ sodipodi:rx="3.9999149"
+ sodipodi:cy="14.5"
+ sodipodi:cx="431"
+ id="path27920"
+ style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(0.7500463,0,0,1.0294111,88.73017,294.07354)" />
+ <path
+ d="m 65,135 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="135"
+ sodipodi:cx="64"
+ id="path27922"
+ style="fill:url(#linearGradient28099);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.74699998;marker:none;display:inline"
+ sodipodi:type="arc"
+ transform="matrix(2.249956,0,0,2.251405,267.75278,4.81032)" />
+ <path
+ sodipodi:nodetypes="ccscs"
+ style="fill:none;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ 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"
+ id="path27924"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="307.91428"
+ x="411"
+ height="2"
+ width="2"
+ id="rect27926"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <path
+ d="m 65,135 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="135"
+ sodipodi:cx="64"
+ id="path27928"
+ 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="translate(347,172.91429)" />
+ </g>
+ </g>
+ <g
+ id="g27932"
+ transform="translate(4e-6,127.99999)">
+ <g
+ transform="translate(0.4838899,-6.2084382e-8)"
+ id="g27934">
+ <path
+ sodipodi:nodetypes="ccscz"
+ style="opacity:0.25;fill:url(#radialGradient27973);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 432.51611,305.45213 c -3,0 -7,2.04787 -5.5,4.04787 0.5,1.45213 2.49969,3.02073 5.49861,2.99979 3.00139,-0.021 4.82513,-1.62106 5.50139,-2.99995 2,-2.49984 -2.5,-4.04771 -5.5,-4.04771 z"
+ id="path27936"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path27938"
+ d="m 432.51611,305.45213 c -3,0 -7.75,2.04787 -6.25,4.04787 0.5,1.45213 3.25108,3.52094 6.25,3.5 3.00139,-0.021 5.82374,-2.12111 6.5,-3.5 2,-2.49984 -3.5,-4.04787 -6.5,-4.04787 z"
+ style="opacity:0.18000004;fill:url(#radialGradient27975);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ sodipodi:nodetypes="ccscz"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.25;fill:none;stroke:url(#linearGradient27977);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 438.51611,309.5 c -2,4 -10,4 -12,0"
+ id="path27940"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path27942"
+ d="m 426.01611,309.5 c 2,5 11,5 13,0"
+ style="opacity:0.3;fill:none;stroke:#000000;stroke-width:1.00000012px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ style="opacity:0.25;fill:none;stroke:none"
+ id="rect27944"
+ width="15.983887"
+ height="16"
+ x="425.01611"
+ y="302" />
+ </g>
+ <g
+ id="g27416"
+ transform="translate(105,-82)">
+ <rect
+ style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="rect27418"
+ width="16.000004"
+ height="16"
+ x="404"
+ y="302" />
+ <g
+ id="g27420">
+ <path
+ sodipodi:nodetypes="ccscz"
+ style="fill:url(#linearGradient27448);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 412,306.45213 c -3.54545,0 -5.90909,1.5 -6.49999,3.04787 0.5909,1.45213 2.95581,3.77094 6.49999,3.75 3.54709,-0.021 5.9091,-2.29787 6.50001,-3.75 -0.59091,-1.54787 -2.95455,-3.04787 -6.50001,-3.04787 z"
+ id="path27422"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(0.7500463,0,0,1.0294111,88.73017,294.07354)"
+ sodipodi:type="arc"
+ style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path27424"
+ sodipodi:cx="431"
+ sodipodi:cy="14.5"
+ sodipodi:rx="3.9999149"
+ sodipodi:ry="2.91429"
+ d="m 434.99991,14.5 a 3.9999149,2.91429 0 1 1 -7.99982,0 3.9999149,2.91429 0 1 1 7.99982,0 z" />
+ <path
+ transform="matrix(2.249956,0,0,2.251405,267.75278,4.81032)"
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient27450);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.74699998;marker:none;display:inline"
+ id="path27426"
+ sodipodi:cx="64"
+ sodipodi:cy="135"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 65,135 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 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"
+ style="fill:none;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="ccscs"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect27430"
+ width="2"
+ height="2"
+ x="411"
+ y="307.91428" />
+ <path
+ transform="translate(347,172.91429)"
+ sodipodi:type="arc"
+ style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.74699998;marker:none;display:inline"
+ id="path27432"
+ sodipodi:cx="64"
+ sodipodi:cy="135"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 65,135 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z" />
+ </g>
+ </g>
+ <g
+ transform="translate(62.983887,-82)"
+ id="g27434">
+ <g
+ id="g27436"
+ transform="translate(0.4838899,-6.2084382e-8)">
+ <path
+ id="path27438"
+ d="m 432.51611,305.45213 c -3,0 -7,2.04787 -5.5,4.04787 0.5,1.45213 2.49969,3.02073 5.49861,2.99979 3.00139,-0.021 4.82513,-1.62106 5.50139,-2.99995 2,-2.49984 -2.5,-4.04771 -5.5,-4.04771 z"
+ style="opacity:0.25;fill:url(#radialGradient27452);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ sodipodi:nodetypes="ccscz"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccscz"
+ style="opacity:0.18000004;fill:url(#radialGradient27454);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 432.51611,305.45213 c -3,0 -7.75,2.04787 -6.25,4.04787 0.5,1.45213 3.25108,3.52094 6.25,3.5 3.00139,-0.021 5.82374,-2.12111 6.5,-3.5 2,-2.49984 -3.5,-4.04787 -6.5,-4.04787 z"
+ id="path27440"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path27442"
+ d="m 438.51611,309.5 c -2,4 -10,4 -12,0"
+ style="opacity:0.25;fill:none;stroke:url(#linearGradient27456);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.3;fill:none;stroke:#000000;stroke-width:1.00000012px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 426.01611,309.5 c 2,5 11,5 13,0"
+ id="path27444"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ y="302"
+ x="425.01611"
+ height="16"
+ width="15.983887"
+ id="rect27446"
+ style="opacity:0.25;fill:none;stroke:none" />
+ </g>
+ <g
+ transform="translate(147,170.00001)"
+ id="g27500">
+ <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"
+ width="16"
+ height="16"
+ x="26"
+ y="323"
+ ry="0" />
+ <g
+ id="g27516">
+ <path
+ sodipodi:nodetypes="cssssssc"
+ id="path27518"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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="path27520"
+ sodipodi:nodetypes="cssssssc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path27522"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ ry="0.765625"
+ rx="0.765625"
+ y="333.25"
+ x="31"
+ height="4.75"
+ width="6"
+ id="rect27524"
+ 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="rect27527"
+ width="4"
+ height="3"
+ x="32"
+ y="334" />
+ <path
+ sodipodi:nodetypes="cssssccccsccsssc"
+ id="path27529"
+ 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(#linearGradient27598);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ transform="matrix(1.0666667,0,0,1,-233.7,254.00667)"
+ inkscape:connector-curvature="0" />
+ <path
+ 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="path27531"
+ 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
+ id="path27533"
+ 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"
+ inkscape:connector-curvature="0" />
+ <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="rect27535"
+ width="0.25"
+ height="1"
+ x="37"
+ y="336" />
+ <rect
+ y="334"
+ x="37"
+ height="1"
+ width="0.25"
+ id="rect27537"
+ 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="rect27539"
+ 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="rect27541"
+ 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(#linearGradient27600);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.61155295;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path27543"
+ 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="path27545"
+ style="opacity:0.6;fill:url(#radialGradient27602);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
+ id="path27547"
+ style="fill:none;stroke:url(#linearGradient27604);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" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.25;fill:url(#radialGradient27606);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path27549"
+ 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.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="path27551"
+ sodipodi:cx="64"
+ sodipodi:cy="135"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 65,135 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 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
+ 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(#radialGradient27608);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;display:inline"
+ id="path27554"
+ inkscape:connector-curvature="0" />
+ <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="rect27557"
+ width="5"
+ height="0.75"
+ x="31.5"
+ y="333" />
+ <path
+ 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="path27564"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.2;fill:url(#linearGradient27610);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="path27566"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <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="rect27585"
+ width="1"
+ height="1"
+ x="32"
+ y="328" />
+ <path
+ sodipodi:nodetypes="csscssc"
+ id="path27587"
+ style="fill:none;stroke:url(#radialGradient27612);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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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="path27590"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <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="rect27594"
+ width="2"
+ height="1"
+ x="33"
+ y="329" />
+ <rect
+ y="328"
+ x="35"
+ height="1"
+ width="1"
+ id="rect27596"
+ 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
+ style="display:inline;enable-background:new"
+ id="g28080"
+ transform="translate(-823,-175)">
+ <rect
+ y="416"
+ x="870"
+ height="16"
+ width="16"
+ id="rect28083"
+ style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ transform="matrix(1.2930992,0,0,1.3011246,677.85367,159.07065)"
+ style="opacity:0.96000001;display:inline"
+ id="g28085">
+ <path
+ transform="matrix(1.1162596,0,0,1.1065394,67.801614,-350.49863)"
+ 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="path28087"
+ style="opacity:0.25;fill:url(#radialGradient28099);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
+ sodipodi:type="arc"
+ style="opacity:0.5;fill:url(#radialGradient28101);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path28089"
+ 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(-1.3568764,-0.3150232,0.3151738,-1.348049,102.81491,906.57916)" />
+ </g>
+ <path
+ style="fill:url(#linearGradient28103);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.89999998;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 883.5,426.5 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-3.5 2.5,-4.5 5,-10 2.5,5.5 5,6.5 5,10 z"
+ id="path28091"
+ sodipodi:nodetypes="csscc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="csscssc"
+ id="path28093"
+ d="m 878.5,418.40909 c 0.4375,0.96023 0.90625,1.78977 1.36328,2.53255 0.45703,0.74278 0.90234,1.3988 1.29297,2.01196 0.78125,1.22633 1.34375,2.28125 1.34375,3.5161 0,2.22473 -1.792,4.0303 -4,4.0303 -2.208,0 -4,-1.80557 -4,-4.0303 0,-2.41818 2.25,-4.2197 4,-8.06061 z"
+ style="fill:none;stroke:url(#linearGradient28105);stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ 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="path28095"
+ sodipodi:cx="878.5"
+ sodipodi:cy="425"
+ sodipodi:rx="1.5"
+ sodipodi:ry="1"
+ d="m 880,425 a 1.5,1 0 1 1 -3,0 1.5,1 0 1 1 3,0 z"
+ transform="matrix(0.6434675,-0.7329672,0.7942866,0.5945179,-26.858149,815.24158)" />
+ <path
+ inkscape:transform-center-y="-7.1785015"
+ inkscape:transform-center-x="-7.136318"
+ sodipodi:type="arc"
+ style="opacity:0.4;fill:url(#radialGradient28107);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69954133;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path28097"
+ 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.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"
+ inkscape:export-ydpi="90" />
+ </g>
+ <g
+ transform="translate(-94.999994,403.00001)"
+ id="g30296"
+ 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="rect30298"
+ width="16"
+ height="16"
+ x="163"
+ y="195" />
+ <g
+ id="g30300">
+ <g
+ transform="translate(0.01612278,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="g30302"
+ style="display:inline">
+ <g
+ style="fill:#ff943d;fill-opacity:1;stroke:none"
+ id="g30304">
+ <rect
+ transform="matrix(0,-1,1,0,0,0)"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect30306"
+ width="1"
+ height="2"
+ x="-199"
+ y="168.98387" />
+ <rect
+ y="207.98763"
+ x="174.98387"
+ height="2"
+ width="1"
+ id="rect30309"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ y="164.98387"
+ x="-199"
+ height="2"
+ width="1"
+ id="rect30311"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ transform="matrix(0,-1,1,0,0,0)" />
+ <rect
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect30313"
+ width="1"
+ height="2"
+ x="174.98387"
+ y="203.98763" />
+ <rect
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect30315"
+ width="1"
+ height="2"
+ x="162.98387"
+ y="207" />
+ <rect
+ y="203"
+ x="162.98387"
+ height="2"
+ width="1"
+ id="rect30318"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ y="167.97594"
+ x="-211"
+ height="2"
+ width="1"
+ id="rect30326"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ 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"
+ id="rect30328"
+ width="1"
+ height="2"
+ x="-211"
+ y="171.97594" />
+ <rect
+ transform="matrix(0,-1,1,0,0,0)"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect30330"
+ width="1"
+ height="2"
+ x="-211"
+ y="163.98387" />
+ <rect
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect30332"
+ width="1"
+ height="2"
+ x="162.98387"
+ y="199" />
+ </g>
+ <g
+ style="fill:#532500;fill-opacity:1"
+ id="g30334">
+ <rect
+ transform="matrix(0,-1,1,0,0,0)"
+ style="fill:#552c00;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect30336"
+ width="1"
+ height="2"
+ x="-199"
+ y="166.98387" />
+ <rect
+ style="fill:#552c00;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect30338"
+ width="1"
+ height="2"
+ x="174.98387"
+ y="205.98763" />
+ <rect
+ y="205"
+ x="162.98387"
+ height="2"
+ width="1"
+ id="rect30340"
+ style="fill:#552c00;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#552c00;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect30342"
+ width="1"
+ height="2"
+ x="162.98387"
+ y="209" />
+ <rect
+ y="165.97594"
+ x="-211"
+ height="2"
+ width="1"
+ id="rect30344"
+ style="fill:#552c00;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ transform="matrix(0,-1,1,0,0,0)" />
+ <rect
+ transform="matrix(0,-1,1,0,0,0)"
+ style="fill:#552c00;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect30346"
+ width="1"
+ height="2"
+ x="-211"
+ y="169.97594" />
+ <rect
+ y="173.97594"
+ x="-211"
+ height="2"
+ width="1"
+ id="rect30348"
+ style="fill:#552c00;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ transform="matrix(0,-1,1,0,0,0)" />
+ <rect
+ y="202"
+ x="174.98387"
+ height="2"
+ width="1"
+ id="rect30350"
+ style="fill:#554400;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#552c00;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect30353"
+ width="1"
+ height="2"
+ x="162.98387"
+ y="201" />
+ <rect
+ y="162.98387"
+ x="-199"
+ height="2"
+ width="1"
+ id="rect30355"
+ style="fill:#552c00;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ transform="matrix(0,-1,1,0,0,0)" />
+ </g>
+ </g>
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path30357"
+ d="m 163.99999,199 6.51562,0 1.23438,3.25 3.25,1.20312 0,6.54688 -11,0 0,-11 z"
+ style="opacity:0.25;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"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(0.781818,0,0,0.781818,38.760709,42.85549)"
+ 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="g30359"
+ style="display:inline">
+ <path
+ inkscape:transform-center-y="-6.3853012"
+ inkscape:transform-center-x="-6.3473305"
+ sodipodi:type="arc"
+ style="fill:none;stroke:#000000;stroke-width:0.78698397;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;display:inline"
+ id="path30361"
+ 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.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"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;stroke:#28170b;stroke-width:4.47674513;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 164.66657,209.31279 3.51745,-3.51744"
+ id="path30363"
+ 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
+ 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="path30365"
+ d="m 168.5,205.5 0.96309,-0.98372"
+ style="fill:none;stroke:#000000;stroke-width:2.5581398;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#cccccc;stroke-width:1.40697706;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 168.5,205.5 1.28285,-1.30349"
+ id="path30367"
+ 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="g30369"
+ 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.878699,0,0,0.877142,14.70687,20.74499)">
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient30389);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient30391);stroke-width:1.16848361;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="path30371"
+ 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.2468441,0,0,1.246865,503.16273,106.89331)" />
+ </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="path30373"
+ d="m 164.66657,209.31279 3.51745,-3.51744"
+ style="fill:none;stroke:#a05a2c;stroke-width:2.55814004;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
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:1.2790699;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 164.02704,208.99303 3.83721,-3.83721"
+ id="path30375"
+ 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
+ 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.4627004,0,0,1.4628053,551.73128,85.525552)"
+ 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="path30377"
+ style="opacity:0.5;fill:url(#radialGradient30393);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69954133;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ inkscape:transform-center-x="-6.3473305"
+ inkscape:transform-center-y="-6.3853012" />
+ <g
+ id="g30379"
+ style="opacity:0.96000001;display:inline"
+ transform="matrix(0.9729196,0,0,0.9789579,9.7047721,-0.8010785)">
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.25;fill:url(#radialGradient30395);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path30381"
+ 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(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 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="path30383"
+ style="opacity:0.25;fill:url(#radialGradient30397);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
+ d="m 65,135 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="135"
+ sodipodi:cx="64"
+ id="path30385"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.74699998;marker:none;display:inline"
+ sodipodi:type="arc"
+ transform="matrix(1.2790738,0,0,1.2790735,89.840744,25.765779)" />
+ </g>
+ <path
+ id="path30387"
+ d="m 163.99999,199 0,11 1,0 0,-10 6,0 0,-1 -7,0 z"
+ style="opacity:0.12999998;fill:#000000;fill-opacity:1;fill-rule:nonzero;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>
+ <g
+ id="g28857">
+ <rect
+ y="241.00877"
+ x="68.001282"
+ height="16"
+ width="16"
+ id="rect27661"
+ 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
+ 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(0.9168751,0,0,0.9161255,-39.818417,44.251476)"
+ id="g27663"
+ style="display:inline"
+ clip-path="url(#clipPath42711)">
+ <path
+ transform="matrix(0.75,0,0,0.75,29.5,135)"
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient42435);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:1.45480967;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="path27665"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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"
+ clip-path="none"
+ mask="none" />
+ <path
+ transform="matrix(0.6147126,0,0,0.6147118,47.3579,150.96368)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient42437);stroke-width:1.77499008;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="path27667"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="translate(-167.99872,-18.991228)"
+ style="opacity:0.55"
+ id="g27669">
+ <path
+ style="fill:url(#linearGradient42432);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"
+ 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"
+ 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>
+ <g
+ transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,-167.74474,113.52244)"
+ style="display:inline;enable-background:new"
+ id="g27675">
+ <path
+ style="opacity:0.2;fill:none;stroke:#000000;stroke-width:1.49999988;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 73.54505,272.57627 1.06066,-2.47487"
+ id="path33728"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path27679"
+ d="m 73.545051,272.22272 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
+ sodipodi:nodetypes="cc"
+ id="path33730"
+ d="m 78.494797,266.21231 2.651651,-0.88388"
+ style="opacity:0.2;fill:none;stroke:#000000;stroke-width:1.49999988;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"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path42359"
+ 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
+ id="g56105">
+ <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"
+ width="16"
+ height="16"
+ x="530"
+ y="52" />
+ <g
+ id="g56091">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ id="path29110"
+ d="m 531,58 6,-2.5 7.99996,3.49998 0,2.75 -5.99999,3.24999 L 531,60.75 531,58 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.70000005;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\4.png"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:#9e9e9e;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 531,58 6,-2.5 7.99996,3.49998 0,0.5 -6,3 L 531,58.56558 531,58 z"
+ id="path29112" />
+ <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="path29114"
+ d="M 531.00001,60.75 531,58.5 l 7.99996,3.99998 0.01,2.49885 -8.00991,-4.24883 -4e-5,0 z"
+ style="fill:#848484;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ 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"
+ style="fill:#383838;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 544.99996,61.74998 0,-2.25 -6,3 c 0,2.58362 0,1.9329 0,2.5 l 6,-3.25 z"
+ id="path29116"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient56084);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 531.5,58.5 0,2 7.49996,3.99998 5.5,-3 0,-2"
+ id="path29118"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 531.5,58 7.49996,3.74998"
+ id="path29120"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient29129);stroke-width:1.08012342;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="path29122"
+ sodipodi:cx="749"
+ sodipodi:cy="420.25"
+ sodipodi:rx="2.5"
+ sodipodi:ry="1.75"
+ d="m 751.5,420.25 a 2.5,1.75 0 1 1 -5,0 2.5,1.75 0 1 1 5,0 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"
+ id="rect29125"
+ width="1"
+ height="1"
+ x="544"
+ y="61" />
+ </g>
+ </g>
+ <g
+ transform="translate(-0.1658249,128.41502)"
+ id="g27744">
+ <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"
+ width="16"
+ height="16"
+ x="47.165825"
+ y="364.58499" />
+ <g
+ id="g27748"
+ transform="matrix(1.032664,0,0,1.043556,-79.760429,254.38542)"
+ 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">
+ <path
+ sodipodi:type="arc"
+ style="fill:#4169a5;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:1.22966909;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="path27750"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path27752"
+ style="fill:url(#linearGradient27767);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ 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.666432,0,0,0.659342,42.69924,35.46375)" />
+ <path
+ transform="matrix(0.3631382,0,0,0.3593485,81.755824,69.904768)"
+ 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:type="arc"
+ style="opacity:0.7;fill:url(#linearGradient27769);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path27755"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path27757"
+ d="m 274.98515,70.995347 c 0,0.953349 -1,1.906699 -2,1.906699"
+ style="opacity:0.5;fill:none;stroke:#ffe680;stroke-width:1.00161445px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;filter:url(#filter13996)"
+ transform="matrix(0.9688184,0,0,0.9547322,-131.63668,47.640696)"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccccssscsscccscccccccccccccccsccccc"
+ id="path27761"
+ d="m 130.67404,112.3079 c 0.0244,0.78706 -0.15754,1.63085 0.59269,2.02213 0.71197,-0.0434 1.49133,0.64122 1.35667,1.40517 -0.26776,0.77861 0.14071,1.12325 0.95576,1.36401 0.57868,-0.0716 0.79053,-0.93546 0.87357,-1.36401 0.0948,-1.27121 0.51542,-1.09421 0.82108,-1.98991 -0.45733,-0.91502 -0.003,-1.04443 -0.72629,-1.43739 m -1.00945,-3.89288 c -0.4426,0.34378 -0.24372,1.04314 -0.66162,1.39841 -0.45372,0.13628 -0.78226,-0.0605 -1.16771,0.43164 -0.30841,1.10457 0.35004,1.22306 0.90205,1.10457 0.49538,-0.0502 0.61419,-0.94321 0.97928,-0.37853 0.0831,0.10976 0.71917,-0.0403 0.86266,0.18898 0.0669,0.10682 -0.11785,0.0255 -0.14729,0.18955 -0.0428,0.23847 0.27734,0.37341 0.372,0.3824 0.32089,0.0305 0.60005,0.92548 0.83846,1.05499 0,0.46738 0.0924,-0.6774 0.3515,-0.78703 0.22948,-0.0971 0.47929,0.10731 0.5,0 0.29928,-1.55081 -1.26113,-3.00604 -2.82933,-3.58498 z M 128.96474,107.5 c -0.6111,1.01384 0.85343,1.46103 1.73001,1.21329 0.57897,-0.37879 1.00716,-0.92331 0.55665,-1.21329 -0.20614,-0.1415 -2.07706,0.0431 -2.28666,0 l 0,0 0,0 0,0 z m -1.372,1.37253 c -0.49575,-0.14959 0.44952,-0.11945 0.45733,0.45751 0.1696,0.54756 -0.42801,0.23756 0,0.45752 0.70893,0.1644 0.35328,1.70031 -0.28114,1.56208 -0.56042,0.10119 -0.43915,0.95826 -1.64865,0.88279 -0.0836,0.0755 -1.04512,0.61593 -0.81421,1.21521 1.12968,0.30162 -0.36816,1.26478 -0.43867,0.55236 -0.15441,-0.49797 -0.62853,-1.11348 -0.43994,-1.68674 0.11734,-0.63627 0.5689,-1.12263 0.82646,-1.69865 0.36225,-0.61946 0.89084,-1.17688 1.57758,-1.42595 0.21411,-0.16799 0.46159,-0.41691 0.76124,-0.31613 l 0,0 0,0 0,0 z m -0.91467,5.03262 c -0.55163,-0.27585 -0.72934,0.28829 -0.60377,0.7984 0.15577,0.47138 0.52607,0.97695 0.72628,1.43739 0.40435,0.49619 1.512,1.34081 2.17883,1.67696 0.31768,0.16015 0.48418,0 0.24209,-0.23956 -0.31367,-0.6375 -1.14073,-1.94893 -0.48418,-2.15609 0.59647,-0.60342 0.34203,-1.58773 -0.48419,-1.43739 -0.54779,-0.25818 -0.75551,-0.39899 -1.38855,-0.0752 -0.0558,0.0743 -0.12403,0.006 -0.18651,-0.004 l 0,-5.1e-4 0,0 0,0 z"
+ style="fill:url(#linearGradient27771);fill-opacity:1;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\Kopia blender\.blender\icons\blender's iconset.png"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path27763"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient27773);stroke-width:1.45454657;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:type="arc"
+ transform="matrix(0.6657538,0,0,0.6588051,42.794535,35.527157)" />
+ <path
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path27765"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ 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.06052282,0,0,0.05989117,121.21686,103.80334)" />
+ </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"
+ transform="translate(0,2)">
+ <g
+ id="g31771"
+ transform="matrix(0,-1,1,0,249,491)">
+ <g
+ style="opacity:0.7;display:inline"
+ id="g31773"
+ transform="translate(257,86)">
+ <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="rect31775"
+ width="16"
+ height="16"
+ x="63"
+ y="48" />
+ </g>
+ <g
+ id="g31784"
+ transform="matrix(-1,0,0,1,656,0)">
+ <path
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;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 323.5,137.5 0,9 3,0 3,0 3,0 0,-4 0,-5 -3,0 0,6 -3,0 0,-6 -3,0 z"
+ id="path31786"
+ sodipodi:nodetypes="cccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path31788"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 324.5,145.5 0,-7 1,0 m 6,0 -1,0 0,6 -4,0"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ transform="translate(0,21)"
+ style="opacity:0.8"
+ id="g31854">
+ <g
+ id="g31823">
+ <g
+ id="g31807">
+ <path
+ id="path31804"
+ d="m 384.5,138.5 0,-3 3,0"
+ style="fill:none;stroke:#00112b;stroke-width:2.4000001;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:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#b9d5ff;stroke-width:1;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 384.5,138.5 0,-3 3,0"
+ id="path31796"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(-1,0,0,1,782,0)"
+ id="g31811">
+ <path
+ style="fill:none;stroke:#00112b;stroke-width:2.4000001;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:new"
+ d="m 384.5,138.5 0,-3 3,0"
+ id="path31813"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path31819"
+ d="m 384.5,138.5 0,-3 3,0"
+ style="fill:none;stroke:#b9d5ff;stroke-width:1;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g31831"
+ transform="matrix(1,0,0,-1,0,284)">
+ <g
+ id="g31833">
+ <path
+ style="fill:none;stroke:#00112b;stroke-width:2.4000001;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:new"
+ d="m 384.5,138.5 0,-3 3,0"
+ id="path31842"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path31845"
+ d="m 384.5,138.5 0,-3 3,0"
+ style="fill:none;stroke:#b9d5ff;stroke-width:1;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g31847"
+ transform="matrix(-1,0,0,1,782,0)">
+ <path
+ id="path31849"
+ d="m 384.5,138.5 0,-3 3,0"
+ style="fill:none;stroke:#00112b;stroke-width:2.4000001;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:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#b9d5ff;stroke-width:1;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 384.5,138.5 0,-3 3,0"
+ id="path31852"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </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"
+ transform="translate(63,212.00001)">
+ <rect
+ ry="0"
+ rx="0"
+ y="281"
+ x="47"
+ height="16"
+ width="16"
+ id="rect31979"
+ 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="g31981">
+ <g
+ transform="translate(-290.00001,409.99343)"
+ style="opacity:0.75;display:inline"
+ id="g31985">
+ <path
+ style="fill:none;stroke:#1a1a1a;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"
+ d="m 341.00001,-115.99343 c 4.5365,0 8.49999,-2.75 8.49999,-5.75 0,-1.75 -1.25,-4 -5.5,-4"
+ id="path31987"
+ sodipodi:nodetypes="csc"
+ 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"
+ 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\jendrzych's iconset.png"
+ sodipodi:nodetypes="csc"
+ id="path31994"
+ d="m 341.00001,-115.99343 c 4.49647,0 8.49999,-2.75 8.49999,-5.75 0,-1.75 -1.25,-4 -5.5,-4"
+ style="fill:none;stroke:#cccccc;stroke-width:1.5;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>
+ <g
+ transform="translate(-189.02763,408)"
+ id="g31998"
+ style="display:inline">
+ <rect
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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="rect32000"
+ width="2.9998772"
+ height="3"
+ x="238.52776"
+ y="-115.5"
+ ry="1.4999387"
+ rx="1.4999387" />
+ <path
+ style="fill:#ffffff;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 241.02763,-115 c -0.66667,0 -1.33332,1e-5 -2,1e-5 0,0.66939 0,1.33877 0,2.00817 0.66668,0 1.33333,-10e-6 2,-10e-6 0,-0.66939 0,-1.33878 0,-2.00817 z"
+ id="path32009"
+ 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
+ rx="1.4999387"
+ ry="1.4999387"
+ y="-125.5"
+ x="241.52776"
+ height="3"
+ width="2.9998772"
+ id="rect32011"
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path32014"
+ d="m 244.02763,-125 c -0.65334,0 -1.30668,1e-5 -1.96003,1e-5 0,0.66667 0,1.33332 0,1.99999 0.65335,0 1.30669,-1e-5 1.96003,-1e-5 0,-0.66666 0,-1.33332 0,-1.99999 z"
+ style="fill:#ffffff;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" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ id="g32016"
+ 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"
+ id="rect32018"
+ width="16"
+ height="16"
+ x="563"
+ y="-183" />
+ <g
+ id="g32020">
+ <g
+ style="opacity:0.75"
+ id="g32022"
+ transform="translate(476.04566,-283.51773)">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path32025"
+ d="m 89.95451,104.01774 5,9.5 5,-9.5 -10,0 z"
+ style="fill:none;stroke:#1a1a1a;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#cccccc;stroke-width:1.5;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.95451,103.98095 5,9.5 5,-9.5 -10,0 z"
+ id="path32028"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ rx="1.4999386"
+ ry="1.4999386"
+ y="-181.49998"
+ x="574.50031"
+ height="3"
+ width="2.9998772"
+ id="rect32030"
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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:#000000;stroke-width:1.5;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="rect32032"
+ width="2.9998772"
+ height="3"
+ x="564.50043"
+ y="-181.49998"
+ ry="1.4999386"
+ rx="1.4999386" />
+ <rect
+ rx="1.4999386"
+ ry="1.4999386"
+ y="-171.5"
+ x="569.5"
+ height="3"
+ width="2.9998772"
+ id="rect32034"
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 577.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="path32036"
+ 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="path32038"
+ d="m 572.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:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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="path32040"
+ d="m 567.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:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g32042"
+ transform="translate(83,212.00001)">
+ <rect
+ y="68"
+ x="281"
+ height="16"
+ width="16"
+ id="rect32044"
+ 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"
+ transform="matrix(0,1,1,0,0,0)" />
+ <g
+ id="g32046"
+ transform="matrix(0,-1,1,0,-254.00001,365.00041)">
+ <g
+ id="g32048"
+ style="opacity:0.7">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path32051"
+ style="fill:none;stroke:#1a1a1a;stroke-width:2.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 69.5,325.5 0,10 12,0 0,-10 -12,0 z m 6,0 0,10 m 6,-5 -12,0"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ d="m 69.5,325.5 0,10 12,0 0,-10 -12,0 z m 6,0 0,10 m 6,-5 -12,0"
+ style="fill:none;stroke:#cccccc;stroke-width:1;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="path32053"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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="rect32055"
+ width="2.9998772"
+ height="3"
+ x="80.500122"
+ y="323.5"
+ ry="1.4999386"
+ rx="1.4999386" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ d="m 83.00041,324.00001 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="path32061"
+ 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
+ rx="1.4999386"
+ ry="1.4999386"
+ y="334.5"
+ x="80.49971"
+ height="3"
+ width="2.9998772"
+ id="rect32063"
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path32065"
+ d="m 83,335 c -0.6694,0 -1.3388,10e-6 -2.0082,10e-6 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:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g25012"
+ transform="translate(-83.999998,191)">
+ <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="rect25014"
+ width="16.000032"
+ height="16"
+ x="-231.00003"
+ y="281" />
+ <g
+ transform="translate(235.00016,-1)"
+ id="g25016">
+ <g
+ id="g25018"
+ transform="translate(-376,510)"
+ style="opacity:0.8">
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ id="path25020"
+ d="m 358.99997,-216.75 c -0.99997,-6.5 6.00003,-2.75 5,-9.25 L 369,-224 c 1,7 -6,2 -5,10 l -5.00003,-2.75 z"
+ style="fill:none;stroke:#1a1a1a;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:#b3b3b3;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 358.99997,-216.75 C 358,-223.25 365,-220 363.99997,-226 L 369,-224 c 1,7 -6,2 -5,10 l -5.00003,-2.75 z"
+ id="path25022"
+ 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"
+ style="opacity:0.7;fill:url(#linearGradient25056);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.88812488px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M 358.99997,-216.75 C 358,-223.25 365,-220 363.99997,-226 L 369,-224 c 1,7 -6,2 -5,10 l -5.00003,-2.75 z"
+ id="path25024"
+ 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"
+ id="path25026"
+ d="M 358.99997,-216.75 C 358,-223.25 365,-220 363.99997,-226 L 369,-224 c 1,7 -6,2 -5,10 l -5.00003,-2.75 z"
+ style="opacity:0.75;fill:url(#radialGradient25058);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.88812488px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccc"
+ 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="path25028"
+ d="m 364.24984,-225.5 4.25016,1.75 c 1,5.75 -5.50003,2 -5.08381,8.85761 l -4.04561,-2.26888"
+ style="fill:none;stroke:url(#linearGradient25060);stroke-width:1;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"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;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 364.24997,-225.5 4.25003,1.75"
+ id="path25031"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-399.2499,383.75)"
+ id="g25033">
+ <rect
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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="rect25035"
+ width="2.9998772"
+ height="3"
+ x="391.75"
+ y="-99.25"
+ ry="1.4999387"
+ rx="1.4999387" />
+ <path
+ style="fill:#ffffff;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 394.24987,-98.75 c -0.66667,0 -1.33332,1e-5 -2,1e-5 0,0.66939 0,1.33877 0,2.00817 0.66668,0 1.33333,-10e-6 2,-10e-6 0,-0.66939 0,-1.33878 0,-2.00817 z"
+ id="path25039"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g25041"
+ transform="translate(-406.2499,380.75)">
+ <rect
+ rx="1.4999387"
+ ry="1.4999387"
+ y="-98.25"
+ x="392.74988"
+ height="3"
+ width="2.9998772"
+ id="rect25043"
+ style="fill:#dfa535;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;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"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path25046"
+ d="m 395.24974,-97.75 c -0.66667,0 -1.33332,1e-5 -2,1e-5 0,0.666663 0,1.333317 0,1.99999 0.66668,0 1.33333,-1e-5 2,-1e-5 0,-0.666663 0,-1.333327 0,-1.99999 z"
+ style="fill:#ffffff;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" />
+ </g>
+ <path
+ style="opacity:0.3;fill:#ffffff;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 -11.00003,286 c -0.66668,0 -1.33332,0 -2,0 0,-0.33334 0,-0.66666 0,-1 0.66668,0 1.33332,0 2,0 0,0.33334 0,0.66667 0,1 z"
+ id="path25048"
+ 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="path25050"
+ d="m -7.00003,285.53933 c -0.33334,0 -0.66666,10e-6 -1,10e-6 0,0.82281 0,1.64561 0,2.46844 0.33334,0 0.66666,-1e-5 1,-1e-5 0,-0.82282 0,-1.64562 0,-2.46844 l 0,0 0,0 0,0 z"
+ style="opacity:0.3;fill:#ffffff;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
+ 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="path25052"
+ d="m -9.972188,286 c -0.342621,0 -0.685221,0 -1.027842,0 0,-0.66873 0,-1.33742 0,-2.00616 0.342621,0 0.685221,0 1.027842,0 0,0.66874 0,1.33745 0,2.00616 z"
+ style="opacity:0.3;fill:#ffffff;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.3;fill:#ffffff;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 -6.000162,287 c -0.33334,0 -0.66666,0 -1,0 0,0.33428 0,0.66856 0,1.00284 0.33334,0 0.66666,0 1,0 0,-0.33428 0,-0.66856 0,-1.00284 z"
+ id="path25054"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g32145"
+ transform="translate(147,191.00001)">
+ <g
+ transform="translate(-138,212)"
+ style="opacity:0.8;display:inline"
+ id="g32147">
+ <g
+ transform="translate(1.0551033e-6,0)"
+ id="g32149">
+ <g
+ style="display:inline"
+ transform="matrix(0.927273,0,0,1,85.654543,64)"
+ id="g32151"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\Browser icons ver 1\Outliner ICON CODES.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <path
+ sodipodi:nodetypes="cccccc"
+ 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="path32153"
+ style="fill:none;stroke:#1a1a1a;stroke-width:3.63466382;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ d="M 70.499967,14.5 75.5,17.5 m -5.000033,-3 -4.999967,3 m 4.970586,-3 0,-6"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccccccc"
+ 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:#1a1a1a;stroke-width:1.86925566;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 69.392137,7 0,2 2.156862,0 0,-2 -2.156862,0 z M 63.999982,17 64,19 l 2.156862,0 -1.8e-5,-2 -2.156862,0 0,0 0,0 0,0 z m 10.78431,0 0,2 2.156862,0 0,-2 -2.156862,0 z"
+ id="path32155"
+ 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"
+ transform="matrix(1.176776,0,0,1.176776,-12.47787,-2.548088)"
+ d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 z"
+ sodipodi:ry="1.5"
+ sodipodi:rx="1.5"
+ sodipodi:cy="14.5"
+ sodipodi:cx="70.5"
+ id="path32158"
+ style="fill:url(#radialGradient32241);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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"
+ sodipodi:nodetypes="cccc"
+ d="M 70.499967,14.5 75.5,17.5"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ececec;stroke-width:1.97310317;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path32161"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M 70.499967,14.5 75.5,17.5 m -5.000033,-3 -4.999967,3 m 4.970586,-3 0,-6"
+ style="opacity:0.8;fill:none;stroke:url(#radialGradient32243);stroke-width:2.07695079;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path32165"
+ 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="cccccc"
+ transform="translate(-1.6176466e-5,0)"
+ 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"
+ sodipodi:nodetypes="ccccc"
+ id="path32168"
+ d="m 74.784292,17 0,2 2.156862,0 0,-2 -2.156862,0 z"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;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"
+ sodipodi:nodetypes="cccc"
+ id="path32172"
+ style="fill:none;stroke:#999999;stroke-width:1.97310317;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ d="M 70.499967,14.5 65.5,17.5"
+ 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"
+ sodipodi:nodetypes="cc"
+ id="path32174"
+ style="fill:none;stroke:#cccccc;stroke-width:2.07695079;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ d="m 70.470586,14.5 0,-6"
+ 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"
+ sodipodi:nodetypes="ccccc"
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 69.392137,7 0,2 2.156862,0 0,-2 -2.156862,0 z"
+ id="path32177"
+ 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"
+ sodipodi:nodetypes="ccccc"
+ style="fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 64,17 0,2 2.156844,0 0,-2 L 64,17 z"
+ id="path32179"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="13.25"
+ x="68.583321"
+ height="3.5"
+ width="3.774509"
+ id="rect32186"
+ style="opacity:0.05;fill:#554400;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="ccc"
+ id="path32193"
+ d="m 64.539197,18.5 0,-1 1.078431,0"
+ style="opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.03847623px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ 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:1.03847647px;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 69.931347,8.5 0,-0.9673924 1.078413,0"
+ id="path32197"
+ sodipodi:nodetypes="ccc"
+ 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"
+ sodipodi:nodetypes="ccc"
+ id="path32199"
+ d="m 75.323509,18.500001 0,-1 1.078431,0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.03847647px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="5"
+ x="61.843121"
+ height="16"
+ width="17.254898"
+ id="rect32201"
+ style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 155,80.5 -3,-1.870665"
+ id="path32206"
+ transform="matrix(1.0784311,0,0,1,-92.372519,-64)"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.01000001;fill:#d4aa00;fill-opacity:1;fill-rule:evenodd;stroke:#999999;stroke-width:1.03847647px;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 74.245078,17.500001 0,-1 1.078431,0"
+ id="path32208"
+ sodipodi:nodetypes="ccc"
+ 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
+ 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="cc"
+ id="path32215"
+ d="m 69.931352,9.5000005 1.078431,0"
+ style="opacity:0.4;fill:#6a6a6a;fill-opacity:1;fill-rule:evenodd;stroke:#666666;stroke-width:1.03847647px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ 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"
+ sodipodi:nodetypes="ccc"
+ id="path32218"
+ d="m 66.696014,17.499989 0,-1 -1.078431,0"
+ style="opacity:0.4;fill:#6a6a6a;fill-opacity:1;fill-rule:evenodd;stroke:#4c4c4c;stroke-width:1.03847575px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path32230"
+ d="m 147,80.5 3,-1.870665"
+ style="opacity:0.4;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="opacity:0.35;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 150.5,73.5 0,4"
+ id="path32235"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ y="78"
+ x="150.06403"
+ height="2"
+ width="2"
+ id="rect32237"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <rect
+ rx="0"
+ ry="0"
+ y="289.5"
+ x="11.499837"
+ height="3"
+ width="2.9998772"
+ id="rect32239"
+ 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
+ style="display:inline;enable-background:new"
+ id="g52805"
+ 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"
+ id="rect52807"
+ width="16"
+ height="16"
+ x="-75"
+ y="420" />
+ <g
+ transform="translate(-577.98389,452.95862)"
+ style="display:inline;enable-background:new"
+ id="g52809">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path52811"
+ 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(#radialGradient53119);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="path52813"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path52815"
+ 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(#linearGradient53121);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 514.98389,-24.95862 -2.25,2.5 1.38281,1.847656 2.36719,-2.347656 -1.5,-2 z"
+ id="path52817"
+ 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 518.48389,-29.45862 -4,4.75 2,2.25 2,-2"
+ id="path52819"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path52821"
+ d="m 518.98389,-29.70862 -4.75,5.5 1.75,1.75 3,-2.75 0,-4.5 z"
+ style="fill:url(#linearGradient53123);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 5,-6"
+ id="path52823"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.4;fill:none;stroke:url(#linearGradient53125);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="path52825"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-185,34)"
+ id="g52827">
+ <rect
+ ry="0.019097222"
+ style="opacity:0;fill:#736c54;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect52829"
+ width="11"
+ height="11"
+ x="110"
+ y="386"
+ rx="0.019097222" />
+ <g
+ id="g52831">
+ <path
+ id="path52833"
+ d="m 116.53125,386.5 c -0.56312,0 -1.03125,0.46811 -1.03125,1.03125 l 0,0.9375 c 0,0.28156 0.12508,0.53133 0.3125,0.71875 L 113,392 c -0.18742,-0.18742 -0.46844,-0.5 -0.75,-0.5 l -0.75,0 c -0.56312,0 -1.03125,0.46811 -1.03125,1.03125 l 0,0.9375 c 0,0.56312 0.46813,1.03125 1.03125,1.03125 l 0.9375,0 c 0.0103,0 0.021,3e-4 0.0312,0 -3e-4,0.0102 0,0.021 0,0.0312 l 0,0.9375 c 0,0.56312 0.46813,1.03126 1.03125,1.03125 l 0.96875,0 c 0.56312,0 1,-0.46813 1,-1.03125 l 0,-0.9375 c 0,-0.28156 -0.10164,-0.53133 -0.28125,-0.71875 l 2.625,-2.625 c 0.18742,0.18742 0.43719,0.3125 0.71875,0.3125 l 0.96875,0 c 0.56312,0 1,-0.46813 1,-1.03125 l 0,-0.9375 c 0,-0.56312 -0.43688,-1.03125 -1,-1.03125 l -0.96875,0 c -0.0103,0 -0.021,-3e-4 -0.0312,0 3e-4,-0.0102 0,-0.021 0,-0.0312 l 0,-0.9375 c 0,-0.56312 -0.46813,-1.03125 -1.03125,-1.03125 l -0.9375,0 z"
+ style="fill:url(#linearGradient53127);fill-opacity:1;fill-rule:evenodd;stroke:#333333;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="cccccccccccsccccccccccccccscccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path52835"
+ d="m 111.5,393.5 0,-0.75 0.25,-0.25 1.75,0 3,-3 0,-1.75 0.25,-0.25 0.75,0"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 118.75,389.5 0.75,0 m -6,6 0,-0.75"
+ id="path52837"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.2;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"
+ id="rect52839"
+ width="1"
+ height="1"
+ x="114"
+ y="393" />
+ <rect
+ y="390"
+ x="117"
+ height="1"
+ width="1"
+ id="rect52841"
+ style="opacity:0.2;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>
+ </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">
+ <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" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g52873"
+ transform="translate(120,94.000007)">
+ <rect
+ y="420"
+ x="-52"
+ height="16"
+ width="16"
+ id="rect52875"
+ 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
+ transform="translate(-556.98389,452.95862)"
+ style="display:inline;enable-background:new"
+ id="g52877">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path52879"
+ 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(#radialGradient53141);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="path52881"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path52883"
+ 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(#linearGradient53143);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="path52885"
+ 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 520.48389,-31.45862 -6,6.75 2,2.25 4,-4"
+ id="path52887"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path52889"
+ d="m 520.98389,-31.95862 -6.75,7.75 1.75,1.75 5,-4.5 0,-5 z"
+ style="fill:url(#linearGradient53145);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 7,-8.25"
+ id="path52891"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.4;fill:none;stroke:url(#linearGradient53147);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="path52893"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ mask="url(#mask57450)"
+ id="g52895"
+ style="display:inline"
+ transform="translate(-378.00003,264.99999)">
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path52897"
+ d="m 328.50261,168.45815 0.0576,-10.96002 10.94282,-0.0283"
+ style="opacity:0.7;fill:none;stroke:#000000;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#d2d2d2;stroke-width:1.60000002;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 328.50261,168.45815 0.0576,-10.96002 10.94282,-0.0283"
+ id="path52899"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ transform="matrix(1,5.25126e-6,0,1,0,0)"
+ y="155.49829"
+ x="326.50003"
+ height="2.9999838"
+ width="2.9999995"
+ id="rect52901"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265" />
+ </g>
+ </g>
+ <g
+ transform="translate(318,94.000007)"
+ id="g52903"
+ 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"
+ id="rect52905"
+ width="16"
+ height="16"
+ x="-124"
+ y="420" />
+ <g
+ id="g52907"
+ transform="translate(-258,96.99999)"
+ mask="url(#mask32294)">
+ <path
+ style="opacity:0.3;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 142.5,327.5 c 0,1.2526 -0.5,2 -1.5,3 -1,1 0,3 -1.25,3 l -2.5,0 c -1.25,0 -0.25,-2 -1.25,-3 -1,-1 -1.5,-1.75686 -1.5,-3 0,-2.208 1.792,-4 4,-4 2.208,0 4,1.792 4,4 z"
+ id="path52909"
+ sodipodi:nodetypes="cssssssc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cssssssc"
+ id="path52911"
+ d="m 142.5,327.5 c 0,1.2526 -0.5,2 -1.5,3 -1,1 0,3 -1.25,3 l -2.5,0 c -1.25,0 -0.25,-2 -1.25,-3 -1,-1 -1.5,-1.75686 -1.5,-3 0,-2.208 1.792,-4 4,-4 2.208,0 4,1.792 4,4 z"
+ style="fill:none;stroke:#1a1a1a;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 137.5,336.00001 2,0 0,1 -2,-10e-6 0,-0.99999 z"
+ id="path52913"
+ 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="rect52915"
+ width="5"
+ height="4.7498698"
+ x="136"
+ y="331.25"
+ rx="0.765625"
+ ry="0.765625" />
+ <rect
+ y="332.60001"
+ x="137"
+ height="2.55"
+ width="3"
+ id="rect52917"
+ style="fill:#a89858;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,-128.7,252.00668)"
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="-0.021577613"
+ inkscape:original="M 249.25 79.96875 C 248.7604 79.96875 248.46875 80.255136 248.46875 80.5 C 248.46875 80.744863 248.76041 81.031252 249.25 81.03125 C 249.73959 81.031248 251.26039 81.03125 251.75 81.03125 C 252.23961 81.03125 252.53125 80.744873 252.53125 80.5 C 252.53125 80.255131 252.23961 79.968752 251.75 79.96875 L 249.25 79.96875 z M 249.25 81.96875 C 248.7604 81.96875 248.46875 82.255138 248.46875 82.5 C 248.46875 82.744863 248.76041 83.031253 249.25 83.03125 L 251.75 83.03125 C 252.23961 83.03125 252.53125 82.744875 252.53125 82.5 C 252.53125 82.255131 252.23961 81.968753 251.75 81.96875 C 251.26039 81.968747 249.7396 81.96875 249.25 81.96875 z "
+ style="fill:url(#linearGradient53149);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path52919"
+ 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 l 2.5,0 c 0.4812,0 0.75,-0.272259 0.75,-0.5 0,-0.227736 -0.2688,-0.499998 -0.75,-0.5 l -2.5,0 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 2.5,0 c 0.4812,0 0.75,-0.272257 0.75,-0.5 0,-0.227736 -0.2688,-0.499997 -0.75,-0.5 l -2.5,0 c -0.0601,0 -0.10258,-0.0082 -0.15625,0 z" />
+ <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="path52921"
+ d="m 137.25,334.25 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 137.25,332.25 1.25,0"
+ id="path52923"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="334"
+ x="141"
+ height="1"
+ width="0.25"
+ id="rect52925"
+ 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="rect52927"
+ width="0.25"
+ height="1"
+ x="141"
+ y="332" />
+ <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="rect52929"
+ width="0.25"
+ height="1"
+ x="135.75"
+ y="334" />
+ <rect
+ y="332"
+ x="135.75"
+ height="1"
+ width="0.25"
+ id="rect52931"
+ 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="translate(-112,254)"
+ 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="path52933"
+ style="fill:url(#linearGradient53151);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(#radialGradient53153);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.61155295;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path52935"
+ 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="translate(-112,254)" />
+ <path
+ d="m 138.5,324.5 c 1.656,0 3,1.34699 3,3.00667 0,0.89477 -0.39063,1.69865 -1.01019,2.24958 C 139.96017,330.22723 139.5,331 139.5,332.25 m -1,-7.75 c -1.656,0 -3,1.34699 -3,3.00667 0,0.89477 0.39063,1.69865 1.01019,2.24958 C 137.03983,330.22723 137.5,331 137.5,332.25"
+ style="fill:none;stroke:url(#linearGradient53155);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;display:inline"
+ id="path52937"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(0.8490785,0,0,0.8469086,71.921104,-98.093334)"
+ 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="path52939"
+ style="opacity:0.25;fill:url(#radialGradient53157);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 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="135"
+ sodipodi:cx="64"
+ id="path52941"
+ 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,74.34506,191)" />
+ <path
+ id="path52943"
+ style="fill:none;stroke:url(#radialGradient53159);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;display:inline"
+ d="m 138.5,324.5 c 1.656,0 3,1.34699 3,3.00667 0,0.89477 -0.39063,1.69865 -1.01019,2.24958 C 139.96017,330.22723 139.5,331 139.5,332.25 m -1,-7.75 c -1.656,0 -3,1.34699 -3,3.00667 0,0.89477 0.39063,1.69865 1.01019,2.24958 C 137.03983,330.22723 137.5,331 137.5,332.25"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="331"
+ x="136.01562"
+ height="0.75"
+ width="4.96875"
+ id="rect52945"
+ style="opacity:0.85;fill:#504416;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="path52947"
+ d="m 137.5,335.01146 2,0 0,1 -2,-10e-6 0,-0.99999 z"
+ style="fill:#6c6753;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path52949"
+ d="m 138,329 0,3.75 1,0 0,-3.75 -1,0 z"
+ style="opacity:0.2;fill:url(#linearGradient53161);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="137"
+ height="1"
+ width="3"
+ id="rect52951"
+ style="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.3;fill:#d3bc5f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect52953"
+ width="1"
+ height="1"
+ x="138"
+ y="328" />
+ <path
+ d="m 138.5,324.5 c 1.656,0 3,1.34699 3,3.00667 0,0.89477 -0.39063,1.69865 -1.01019,2.24958 C 139.96017,330.22723 139.5,331 139.5,332.25 m -1,-7.75 c -1.656,0 -3,1.34699 -3,3.00667 0,0.89477 0.39063,1.69865 1.01019,2.24958 C 137.03983,330.22723 137.5,331 137.5,332.25"
+ style="fill:none;stroke:url(#radialGradient53163);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;display:inline"
+ id="path52955"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path52957"
+ d="m 137.5,336.00001 0.5,0 0,1 -0.5,-10e-6 0,-0.99999 z"
+ style="opacity:0.3;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-626.98389,452.95862)"
+ style="display:inline;enable-background:new"
+ id="g52959">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path52961"
+ 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(#radialGradient53165);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="path52963"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path52965"
+ 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(#linearGradient53167);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 514.98389,-24.95862 -2.25,2.5 1.38281,1.847656 2.36719,-2.347656 -1.5,-2 z"
+ id="path52967"
+ 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 518.48389,-29.45862 -4,4.75 2,2.25 2,-2"
+ id="path52969"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path52971"
+ d="m 518.98389,-29.70862 -4.75,5.5 1.75,1.75 3,-2.75 0,-4.5 z"
+ style="fill:url(#linearGradient53169);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 5,-6"
+ id="path52973"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.4;fill:none;stroke:url(#linearGradient53171);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="path52975"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g77742"
+ style="fill:#ffeeaa;display:inline"
+ transform="translate(-870.9421,-297.02038)" />
+ <g
+ id="g33404"
+ 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"
+ id="rect33341"
+ width="16"
+ height="16"
+ x="257"
+ y="113" />
+ <g
+ style="opacity:0.8;display:inline"
+ id="g33343"
+ transform="matrix(1.1658027,0,0,1.1657997,112.71027,-140.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
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path33345"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:1.33333421;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.643333,0,0,0.643335,44.424162,146.72855)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.8;fill:url(#linearGradient33427);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path33347"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.5858806,-0.06590218,0.06677852,-0.5812167,198.80048,299.96262)" />
+ <path
+ transform="matrix(0.5361112,0,0,0.5361024,58.577433,159.38208)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient33429);stroke-width:1.60001671;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path33349"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="translate(5,-21)"
+ id="g33351">
+ <g
+ id="g33353"
+ transform="translate(169.04507,38.63228)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path33355"
+ d="m 90.45493,102.86772 -4.5e-4,6.03674 6.00045,-0.0367 4.5e-4,-6.03674 -6.00045,0.0367 z"
+ style="opacity:0.7;fill:none;stroke:#002255;stroke-width:2.5;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:#afc6e9;fill-opacity:0.70588235;fill-rule:evenodd;stroke:#afc6e9;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 90.45493,102.86772 -4.5e-4,6.03674 6,0 4.5e-4,-6.03674 -6,0 z"
+ id="path33357"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ rx="1.4999386"
+ ry="1.4999386"
+ y="146.5"
+ x="264.50012"
+ height="3"
+ width="2.9998772"
+ id="rect33359"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.29999995;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:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.29999995;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="rect33361"
+ width="2.9998772"
+ height="3"
+ x="257.50012"
+ y="139.5"
+ ry="1.4999386"
+ rx="1.4999386" />
+ <rect
+ rx="1.4999386"
+ ry="1.4999386"
+ y="146.49997"
+ x="257.49969"
+ height="3"
+ width="2.9998772"
+ id="rect33363"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.29999995;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
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 267.00027,146.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="path33365"
+ 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="path33367"
+ d="m 260,147 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:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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="path33369"
+ d="m 260.00029,140 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:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.29999995;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="rect33371"
+ width="2.9998772"
+ height="3"
+ x="264.50085"
+ y="139.5"
+ ry="1.4999386"
+ rx="1.4999386" />
+ <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="path33373"
+ d="m 267.00101,139.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:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g50822"
+ 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"
+ id="rect50824"
+ width="16"
+ height="16"
+ x="-27"
+ y="446" />
+ <g
+ transform="translate(-49,229)"
+ id="g50826"
+ style="opacity:0.5">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path50828"
+ style="fill:none;stroke:#1a1a1a;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 25.5,220 0,10.5 4,0 m -4,-5 c 0.125,0 4,0 4,0"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ d="m 25.5,220 0,10.5 4,0 m -4,-5 c 0.125,0 4,0 4,0"
+ style="fill:none;stroke:#bcd0f5;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="path50830"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ style="fill:url(#linearGradient50870);fill-opacity:1;fill-rule:evenodd;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"
+ id="rect50832"
+ width="7.000001"
+ height="3"
+ x="-26.5"
+ y="446.5" />
+ <g
+ transform="translate(-48,228)"
+ style="opacity:0.45"
+ id="g50834">
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect50836"
+ width="1"
+ height="1"
+ x="24"
+ y="226" />
+ <rect
+ y="231"
+ x="24"
+ height="1"
+ width="1"
+ id="rect50838"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <path
+ sodipodi:nodetypes="cccccccccc"
+ id="path50840"
+ d="m -19.5,452.5 0,3 7,0 0,-3 -7,0 z m 0,6 0,3 7,0 0,-3 -7,0 z"
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:#1a1a1a;stroke-width:0.69999999;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
+ sodipodi:nodetypes="ccc"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -25.5,448.5 0,-1 5,0"
+ id="path50842"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path50844"
+ d="m -18.5,454.5 0,-1 5,0"
+ style="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="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -18.5,460.5 0,-1 5,0"
+ id="path50846"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="447.25"
+ x="-25"
+ height="1.75"
+ width="1"
+ id="rect50848"
+ style="opacity:0.4;fill:#000000;fill-opacity:0.70588235;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.3;fill:#000000;fill-opacity:0.70588235;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect50850"
+ width="1"
+ height="2"
+ x="-18"
+ y="453" />
+ <rect
+ y="459"
+ x="-18"
+ height="2"
+ width="1"
+ id="rect50852"
+ style="opacity:0.3;fill:#000000;fill-opacity:0.70588235;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ id="path50854"
+ d="m -23.5,448.5 0,-1 3,0"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -16.5,454.5 0,-1 3,0"
+ id="path50856"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path50858"
+ d="m -16.5,460.5 0,-1 3,0"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <rect
+ transform="translate(-48,228)"
+ y="225"
+ x="24"
+ height="1"
+ width="1"
+ id="rect50860"
+ 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" />
+ <rect
+ 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"
+ id="rect50862"
+ width="1"
+ height="1"
+ x="-23"
+ y="454" />
+ <rect
+ y="455"
+ x="-24"
+ height="1"
+ width="1"
+ id="rect50864"
+ 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" />
+ <rect
+ 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"
+ id="rect50866"
+ width="1"
+ height="1"
+ x="-24"
+ y="458" />
+ <rect
+ y="459"
+ x="-23"
+ height="1"
+ width="1"
+ id="rect50868"
+ 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"
+ 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"
+ id="rect33464"
+ width="16"
+ height="16"
+ x="173"
+ y="134"
+ ry="0" />
+ <g
+ style="opacity:0.8;display:inline"
+ id="g33466"
+ transform="matrix(1.0761252,0,0,1.0761229,40.809522,-96.59025)"
+ 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\Kopia blender\.blender\icons\blender's iconset.png"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path33469"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient33831);stroke-width:1.44444537;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.643333,0,0,0.643335,44.424162,146.72855)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.8;fill:url(#linearGradient33833);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path33471"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.5902213,-0.06639044,0.06727327,-0.5855229,199.31507,300.5352)" />
+ <path
+ transform="matrix(0.5227063,0,0,0.5226977,60.34688,160.96383)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient33835);stroke-width:1.77780378;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path33473"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ style="display:inline;enable-background:new"
+ id="g33475"
+ transform="translate(-62.70896,-1.9304201)">
+ <path
+ style="fill:none;stroke:#003380;stroke-width:2.99999976;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 245.20896,142.43042 5,-5"
+ id="path33477"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.25;fill:none;stroke:#2a7fff;stroke-width:2.99999928;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000233;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 244.54233,144.43041 1.33333,0 1.33332,-1.33332 0,-1.33335 -1.33332,-1.33332 -1.33332,-1e-5 -1.33333,1.33334 0,1.33333 1.33332,1.33333 z"
+ id="path33479"
+ sodipodi:nodetypes="ccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path33483"
+ d="m 244.45896,144.43042 1.5,0 1.25,-1.25 0,-1.5 -1.3333,-1.25 -1.4167,0 -1.25,1.25 0,1.5 1.25,1.25 z"
+ style="fill:none;stroke:#0044aa;stroke-width:1.20000005;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 244.45896,143.93042 1.5,0 0.75,-0.75 0,-1.5 -0.75,-0.75 -1.5,0 -0.75,0.75 0,1.5 0.75,0.75 z"
+ id="path33481"
+ sodipodi:nodetypes="ccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path33485"
+ d="m 245.20896,142.43042 5,-5"
+ style="fill:none;stroke:url(#linearGradient33585);stroke-width:1.29999995;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="cc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="141.93039"
+ x="244.709"
+ height="1"
+ width="1"
+ id="rect33487"
+ style="opacity:0.8;fill:#00112b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.99999976;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ transform="translate(84,-124)"
+ id="g36191"
+ mask="url(#mask25369)">
+ <rect
+ y="281"
+ x="320"
+ height="16"
+ width="16"
+ id="rect36193"
+ style="opacity:0.01000001;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="cccc"
+ d="m 324.5,295.75 0,-13.5 m 7,13.5 0,-13.5"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path36195"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path36197"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M 321.25001,285.50001 334.75,285.5 M 321.25001,292.50001 334.75,292.5"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path36199"
+ style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 324.5,296.5 0,-14.99999 m 7,14.99999 0,-14.99999"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ d="m 320.5,285.50001 15,0 m -15,6.99999 15,0"
+ style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ 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)">
+ <path
+ inkscape:transform-center-y="-4.9844055"
+ inkscape:transform-center-x="-4.9755572"
+ 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"
+ 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.14287,0,0,1.142863,463.9317,115.80133)" />
+ <g
+ id="g36232">
+ <path
+ transform="matrix(1.1162596,0,0,1.1065394,80.948334,-350.49863)"
+ 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="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" />
+ <path
+ 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 a 2.5312502,2.5 0 1 1 -5.0625,0 2.5312502,2.5 0 1 1 5.0625,0 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 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 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)" />
+ </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"
+ 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"
+ id="rect36248"
+ width="16"
+ height="16"
+ x="71"
+ y="518" />
+ <g
+ id="g36250">
+ <g
+ mask="url(#mask18634)"
+ id="g36252"
+ transform="translate(-136,386)">
+ <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="path36254"
+ d="m 210,134.5 7.5,0 0,13 -10,0 0,-10.5 2.5,-2.5 z"
+ style="fill:url(#linearGradient37472);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(1.2999758,0,0,1.2999988,271.54887,-199.56022)"
+ sodipodi:nodetypes="ccc"
+ id="path36256"
+ style="fill:none;stroke:#000000;stroke-width:0.76923829px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1;display:inline;filter:url(#filter31351)"
+ d="m -48.384641,259.86235 2.000031,-0.008 -3.1e-5,-1.99191"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path36258"
+ d="m 207,138 4,0 0,-4 -4,4 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ 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 207.5,137 0,10.5 10,0 0,-13 -7.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="path36260"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path36262"
+ style="fill:none;stroke:url(#linearGradient37475);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 208.5,138.5 0,8 m 3,-11 5,0"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="opacity:0.01000001"
+ clip-path="url(#clipPath18524)"
+ transform="translate(-134,387)"
+ id="g36264">
+ <path
+ style="fill:url(#linearGradient37477);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 210,134.5 7.5,0 0,12 -10,0 0,-9.5 2.5,-2.5 z"
+ id="path36266"
+ 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
+ d="m -48.384641,259.86235 2.000031,-0.008 -3.1e-5,-1.99191"
+ style="opacity:0.7;fill:none;stroke:#000000;stroke-width:0.76923829px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1;display:inline;filter:url(#filter31351)"
+ id="path36268"
+ sodipodi:nodetypes="ccc"
+ transform="matrix(1.2999758,0,0,1.2999988,271.54887,-199.56022)"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 207,138 4,0 0,-4 -4,4 z"
+ id="path36270"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path36272"
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 207.5,137 0,9.5 10,0 0,-12 -7.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"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 208.5,138.5 0,7 m 3,-10 5,0"
+ style="fill:none;stroke:url(#linearGradient37479);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ id="path36274"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline"
+ id="g36276"
+ 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.781818,0,0,0.781818,-53.239298,365.85549)">
+ <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.4627004,0,0,1.4628053,551.73128,85.525552)"
+ 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="path36278"
+ style="fill:#ffffff;fill-opacity:0.1372549;stroke:#000000;stroke-width:0.78698397;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.3473305"
+ inkscape:transform-center-y="-6.3853012" />
+ <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="path36280"
+ d="m 164.66657,209.31279 3.51745,-3.51744"
+ style="fill:none;stroke:#28170b;stroke-width:4.47674513;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2.5581398;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 168.5,205.5 0.96309,-0.98372"
+ id="path36282"
+ 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
+ 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="path36284"
+ d="m 168.5,205.5 1.28285,-1.30349"
+ style="fill:none;stroke:#cccccc;stroke-width:1.40697706;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" />
+ <g
+ transform="matrix(0.878699,0,0,0.877142,14.70687,20.74499)"
+ 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="g36286">
+ <path
+ transform="matrix(-1.2468441,0,0,1.246865,503.16273,106.89331)"
+ 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="path36288"
+ style="fill:url(#linearGradient37481);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient37483);stroke-width:1.16848361;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:type="arc" />
+ </g>
+ <path
+ style="fill:none;stroke:#a05a2c;stroke-width:2.55814004;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 164.66657,209.31279 3.51745,-3.51744"
+ id="path36290"
+ 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
+ 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="path36292"
+ d="m 164.02704,208.99303 3.83721,-3.83721"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:1.2790699;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:transform-center-y="-6.3853012"
+ inkscape:transform-center-x="-6.3473305"
+ sodipodi:type="arc"
+ style="opacity:0.5;fill:url(#radialGradient37485);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69954133;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path36294"
+ 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.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"
+ inkscape:export-ydpi="90" />
+ <g
+ transform="matrix(0.9729196,0,0,0.9789579,9.7047721,-0.8010785)"
+ style="opacity:0.96000001;display:inline"
+ id="g36296">
+ <path
+ transform="matrix(1.1162596,0,0,1.1065394,80.948334,-350.49863)"
+ 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="path36298"
+ style="opacity:0.25;fill:url(#radialGradient37487);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
+ sodipodi:type="arc"
+ style="opacity:0.25;fill:url(#radialGradient37489);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path36300"
+ 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(-1.087144,-0.2518404,0.2525206,-1.0776772,126.97246,766.619)" />
+ </g>
+ <path
+ transform="matrix(1.2790738,0,0,1.2790735,89.840744,25.765779)"
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.74699998;marker:none;display:inline"
+ id="path36302"
+ sodipodi:cx="64"
+ sodipodi:cy="135"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 65,135 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z" />
+ </g>
+ </g>
+ </g>
+ <g
+ transform="translate(42,41)"
+ id="g36304"
+ style="opacity:0.96000001;display:inline;enable-background:new">
+ <path
+ inkscape:transform-center-y="-6.5435007"
+ inkscape:transform-center-x="-6.5092113"
+ sodipodi:type="arc"
+ style="fill:url(#radialGradient37491);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.63636374;marker:none;display:inline"
+ id="path36306"
+ 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.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"
+ inkscape:export-ydpi="90" />
+ <g
+ transform="translate(42,87)"
+ id="g36308">
+ <rect
+ y="449"
+ x="89"
+ height="16"
+ width="16"
+ id="rect36310"
+ 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="path36312"
+ d="M 93.5,460.5 95,459"
+ style="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:transform-center-y="-6.8594309"
+ inkscape:transform-center-x="-6.8191649"
+ sodipodi:type="arc"
+ style="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;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path36314"
+ 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,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"
+ inkscape:export-ydpi="90" />
+ <path
+ style="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 90.863188,463.13807 93.25,460.75"
+ id="path36316"
+ 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:none;stroke:#cccccc;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 93.5,460.5 2,-2"
+ id="path36318"
+ 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="g36320"
+ 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,-86.169279,229.32421)">
+ <path
+ inkscape:transform-center-y="-4.9844055"
+ inkscape:transform-center-x="-4.9755572"
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient37493);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient37495);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="path36322"
+ 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.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 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="path36326"
+ style="opacity:0.25;fill:url(#radialGradient37497);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
+ sodipodi:type="arc"
+ style="opacity:0.25;fill:url(#radialGradient37499);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path36328"
+ 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(-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 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="135"
+ sodipodi:cx="64"
+ id="path36330"
+ 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)" />
+ </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="path36332"
+ d="m 90.75,463.25 2.5,-2.5"
+ style="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.7;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M 90.25,463 93,460.25"
+ id="path36334"
+ 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>
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 142,545 1,3e-5 0,-1 0,-1 3.5,0 0,-2 -3.5,0 0,-1 0,-1 -1,-3e-5 -2,2.5 0,1 z"
+ id="path36337"
+ sodipodi:nodetypes="ccccccccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g36339"
+ 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"
+ id="rect36341"
+ width="16"
+ height="16"
+ x="341"
+ y="238" />
+ <g
+ transform="translate(0,-12)"
+ id="g36343">
+ <g
+ id="g36345"
+ transform="matrix(1.1658027,0,0,1.1657997,198.71028,-2.0560643)">
+ <path
+ inkscape:transform-center-y="-3.2499984"
+ inkscape:transform-center-x="-2.8145849"
+ sodipodi:end="5.7595865"
+ sodipodi:start="4.712389"
+ 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 a 8,8 0 0 1 6.9282,4 L 132,118 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36349"
+ style="fill:#ff6600;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(0.6969448,0,0,0.6969467,36.918512,140.83126)" />
+ <path
+ transform="matrix(0.3484724,0.6035735,-0.603572,0.3484734,154.13836,102.27942)"
+ sodipodi:type="arc"
+ style="fill:#ad2f94;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path36351"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ 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"
+ sodipodi:start="4.712389"
+ sodipodi:end="5.7595865"
+ inkscape:transform-center-x="-3.2630798"
+ inkscape:transform-center-y="1.6729808e-05" />
+ <path
+ inkscape:transform-center-y="3.2500173"
+ inkscape:transform-center-x="-2.8145756"
+ sodipodi:end="5.7595865"
+ sodipodi:start="4.712389"
+ 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 a 8,8 0 0 1 6.9282,4 L 132,118 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36353"
+ style="fill:#0060f0;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(-0.3484724,0.6035735,-0.603572,-0.3484733,246.13507,184.51913)" />
+ <path
+ transform="matrix(-0.6969448,2.2484149e-8,-4.6257528e-8,-0.6969467,220.91956,305.31067)"
+ sodipodi:type="arc"
+ style="fill:#00d4aa;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path36355"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ 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"
+ sodipodi:start="4.712389"
+ sodipodi:end="5.7595865"
+ inkscape:transform-center-x="2.8145978"
+ inkscape:transform-center-y="3.249994" />
+ <path
+ inkscape:transform-center-x="3.2630773"
+ sodipodi:end="5.7595865"
+ sodipodi:start="4.712389"
+ 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 a 8,8 0 0 1 6.9282,4 L 132,118 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36357"
+ style="fill:#ccff00;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(-0.3484724,-0.6035734,0.603572,-0.3484734,103.69972,343.86251)" />
+ <path
+ inkscape:transform-center-y="-3.2500006"
+ transform="matrix(0.3484724,-0.6035734,0.603572,0.3484733,11.703006,261.6228)"
+ sodipodi:type="arc"
+ style="fill:#ffbf0e;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path36359"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ 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"
+ sodipodi:start="4.712389"
+ sodipodi:end="5.7595865"
+ inkscape:transform-center-x="2.8145777" />
+ </g>
+ <path
+ transform="matrix(0.8124999,0,0,0.8045157,241.75,163.13011)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:#000000;stroke-width:0.98948926;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path36361"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(-0.7451143,-0.08386971,0.08492794,-0.7396793,437.33358,356.39712)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36363"
+ style="opacity:0.3;fill:url(#radialGradient37501);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:type="arc" />
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36365"
+ style="fill:none;stroke:url(#linearGradient37503);stroke-width:1.45605874;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.6860851,0,0,0.6874876,258.44808,176.87656)" />
+ </g>
+ </g>
+ <g
+ transform="translate(105,41)"
+ id="g36367"
+ style="opacity:0.96000001;display:inline;enable-background:new">
+ <g
+ id="g36369"
+ transform="translate(0,87)">
+ <rect
+ y="449"
+ x="89"
+ height="16"
+ width="16"
+ id="rect36371"
+ 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="path36373"
+ d="M 93.5,460.5 95,459"
+ style="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:transform-center-y="-6.8594309"
+ inkscape:transform-center-x="-6.8191649"
+ sodipodi:type="arc"
+ style="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="path36375"
+ 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,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"
+ inkscape:export-ydpi="90" />
+ <path
+ style="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 90.863188,463.13807 93.25,460.75"
+ id="path36377"
+ 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:none;stroke:#cccccc;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M 93.5,460.5 95,459"
+ id="path36379"
+ 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="g36381"
+ 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,-86.169279,229.32421)">
+ <path
+ inkscape:transform-center-y="-4.9844055"
+ inkscape:transform-center-x="-4.9755572"
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient37505);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient37507);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="path36383"
+ 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.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 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="path36387"
+ style="opacity:0.25;fill:url(#radialGradient37509);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
+ sodipodi:type="arc"
+ style="opacity:0.25;fill:url(#radialGradient37511);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path36389"
+ 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(-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 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="135"
+ sodipodi:cx="64"
+ id="path36391"
+ 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)" />
+ </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="path36393"
+ d="m 90.75,463.25 2.5,-2.5"
+ style="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.7;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M 90.25,463 93,460.25"
+ id="path36395"
+ 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>
+ <path
+ inkscape:transform-center-y="-6.547647"
+ inkscape:transform-center-x="-6.5102284"
+ sodipodi:type="arc"
+ style="fill:url(#radialGradient37513);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.63636374;marker:none;display:inline"
+ id="path36397"
+ 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,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"
+ inkscape:export-ydpi="90" />
+ <g
+ id="g36399"
+ style="fill:#000000"
+ transform="translate(0,87)">
+ <g
+ id="g36401"
+ style="fill:#000000">
+ <rect
+ style="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="rect36403"
+ width="2"
+ height="6"
+ x="98"
+ y="452"
+ ry="0.453125" />
+ <rect
+ y="-102"
+ x="454"
+ height="6"
+ width="2"
+ id="rect36405"
+ style="fill:#000000;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)"
+ ry="0.65625" />
+ </g>
+ </g>
+ </g>
+ <g
+ transform="translate(105,41)"
+ id="g36407"
+ 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 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="path36409"
+ style="fill:url(#radialGradient37515);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.63636374;marker:none;display:inline"
+ sodipodi:type="arc"
+ inkscape:transform-center-x="-6.5092113"
+ inkscape:transform-center-y="-6.5435007" />
+ <g
+ id="g36411"
+ transform="translate(21,87)">
+ <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="rect36413"
+ width="16"
+ height="16"
+ x="89"
+ y="449" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M 93.5,460.5 95,459"
+ id="path36415"
+ 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
+ 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,505.21462,331.643)"
+ 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="path36417"
+ style="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: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="path36419"
+ d="M 90.863188,463.13807 93.25,460.75"
+ style="fill:none;stroke:#28170b;stroke-width:3.70000005;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"
+ sodipodi:nodetypes="cc"
+ id="path36421"
+ d="M 93.5,460.5 95,459"
+ style="fill:none;stroke:#cccccc;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(1.0988734,0,0,1.0981343,-86.169279,229.32421)"
+ 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="g36423">
+ <path
+ transform="matrix(-1.14287,0,0,1.142863,463.9317,115.7853)"
+ 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="path36425"
+ style="fill:url(#linearGradient37517);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient37519);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="g36427">
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.25;fill:url(#radialGradient37521);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path36429"
+ 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(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 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="path36431"
+ style="opacity:0.25;fill:url(#radialGradient37523);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="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.74699998;marker:none;display:inline"
+ id="path36433"
+ sodipodi:cx="64"
+ sodipodi:cy="135"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 65,135 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ inkscape:transform-center-x="-3.1120555"
+ inkscape:transform-center-y="-5.7593212" />
+ </g>
+ <path
+ style="fill:none;stroke:#a05a2c;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 90.75,463.25 2.5,-2.5"
+ id="path36435"
+ 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
+ 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="path36437"
+ d="M 90.25,463 93,460.25"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ y="-123"
+ x="541"
+ height="6"
+ width="2"
+ id="rect36439"
+ style="fill:#000000;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)"
+ ry="0.609375" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g36441"
+ transform="translate(107,-124)">
+ <g
+ style="opacity:0.85;display:inline;enable-background:new"
+ transform="translate(-273,0)"
+ id="g36443"
+ mask="url(#mask25561)">
+ <rect
+ y="281"
+ x="320"
+ height="16"
+ width="16"
+ id="rect36445"
+ style="opacity:0.01000001;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="cccc"
+ d="m 325.5,295.75 0,-13.5 m 6,13.5 0,-13.5"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path36447"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path36449"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 321.25,286.5 13.49999,-10e-6 M 321.25001,292.50001 334.75,292.5"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path36451"
+ style="fill:none;stroke:#e6e6e6;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 325.5,296.49999 0,-14.99999 m 6,15 0,-14.99999"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ d="m 320.5,286.5 15,0 m -15,6 15,0"
+ style="fill:none;stroke:#e6e6e6;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path36453"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-21,0)"
+ id="g36455">
+ <g
+ transform="translate(-277.98388,250)"
+ id="g36457"
+ style="display:inline">
+ <path
+ transform="matrix(1.142871,0,0,1.142855,-27.218817,-5.0713453)"
+ 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="path36459"
+ style="fill:url(#linearGradient37525);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.69999641;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="fill:none;stroke:url(#linearGradient37527);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="path36461"
+ 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.857099,0,0,0.857147,67.228993,5.071249)" />
+ </g>
+ <g
+ transform="translate(-210,147)"
+ id="g36463">
+ <rect
+ y="137"
+ x="282"
+ height="1"
+ width="1"
+ id="rect36465"
+ style="fill:#0055d4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#0055d4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36467"
+ width="1"
+ height="1"
+ x="283"
+ y="138" />
+ <rect
+ y="139"
+ x="282"
+ height="1"
+ width="1"
+ id="rect36469"
+ style="fill:#0055d4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#0055d4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36472"
+ width="1"
+ height="1"
+ x="281"
+ y="138" />
+ <rect
+ y="138"
+ x="283"
+ height="1"
+ width="1"
+ id="rect36474"
+ style="fill:#0055d4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g36476"
+ style="opacity:0.5">
+ <rect
+ y="137"
+ x="281"
+ height="1"
+ width="1"
+ id="rect36478"
+ style="fill:#0055d4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="137"
+ x="283"
+ height="1"
+ width="1"
+ id="rect36480"
+ style="fill:#0055d4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="139"
+ x="283"
+ height="1"
+ width="1"
+ id="rect36482"
+ style="fill:#0055d4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="139"
+ x="281"
+ height="1"
+ width="1"
+ id="rect36484"
+ style="fill:#0055d4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g36486"
+ transform="translate(-44.309303,267.47333)">
+ <rect
+ y="309.52667"
+ x="49.309303"
+ height="16"
+ width="16"
+ id="rect36488"
+ style="opacity:0;fill:#ececec;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:transform-center-y="-5"
+ inkscape:transform-center-x="5"
+ style="opacity:0.7"
+ id="g36490"
+ transform="translate(-396.6907,133.52667)">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path36492"
+ d="m 447.5,180.5 0,-2.25 0.75,-0.75 2.25,0"
+ style="fill:none;stroke:#241f1c;stroke-width:2.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#e3dedb;stroke-width:1px;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 447.5,180.5 0,-2.25 0.75,-0.75 2.25,0"
+ id="path36494"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(0,1,-1,0,241.3093,-136.47333)"
+ id="g36496"
+ style="opacity:0.7"
+ inkscape:transform-center-x="-5"
+ inkscape:transform-center-y="-5">
+ <path
+ style="fill:none;stroke:#241f1c;stroke-width:2.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 447.5,180.5 0,-2.25 0.75,-0.75 2.25,0"
+ id="path36498"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path36500"
+ d="m 447.5,180.5 0,-2.25 0.75,-0.75 2.25,0"
+ style="fill:none;stroke:#e3dedb;stroke-width:1px;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>
+ <g
+ inkscape:transform-center-y="5"
+ inkscape:transform-center-x="-5"
+ style="opacity:0.7"
+ id="g36502"
+ transform="matrix(-1,0,0,-1,511.3093,501.52667)">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path36504"
+ d="m 447.5,180.5 0,-2.25 0.75,-0.75 2.25,0"
+ style="fill:none;stroke:#241f1c;stroke-width:2.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#e3dedb;stroke-width:1px;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 447.5,180.5 0,-2.25 0.75,-0.75 2.25,0"
+ id="path36506"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(0,-1,1,0,-126.6907,771.52667)"
+ id="g36508"
+ style="opacity:0.7"
+ inkscape:transform-center-x="5"
+ inkscape:transform-center-y="5">
+ <path
+ style="fill:none;stroke:#241f1c;stroke-width:2.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 447.5,180.5 0,-2.25 0.75,-0.75 2.25,0"
+ id="path36510"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path36512"
+ d="m 447.5,180.5 0,-2.25 0.75,-0.75 2.25,0"
+ style="fill:none;stroke:#e3dedb;stroke-width:1px;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>
+ <g
+ transform="matrix(1.1870922,0,0,1.1818357,-168.36213,276.1664)"
+ id="g36514"
+ style="display:inline">
+ <g
+ id="g36516">
+ <g
+ style="display:inline;enable-background:new"
+ id="g36518"
+ transform="matrix(0.8423946,0,0,0.8461413,-192.36364,-120.73212)">
+ <path
+ inkscape:transform-center-y="-3"
+ inkscape:transform-center-x="3"
+ sodipodi:nodetypes="ccccccccccccccccc"
+ id="path36520"
+ d="m 450.5,179 -0.83982,0.68197 L 449,180.5 l 0,0.5 1,0 0,1 1,0 0,1 0.25,0 0.66329,-1.10494 L 453,181.25 l 0,-0.25 -1,0 0,-1 -1,0 0,-1 -0.5,0 z"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M 459,180.5 458.31803,179.66018 457.5,179 l -0.5,0 0,1 -1,0 0,1 -1,0 0,0.25 1.10494,0.66329 L 456.75,183 l 0.25,0 0,-1 1,0 0,-1 1,0 0,-0.5 z"
+ id="path36522"
+ sodipodi:nodetypes="ccccccccccccccccc"
+ inkscape:transform-center-x="-3"
+ inkscape:transform-center-y="-3"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:transform-center-y="3"
+ inkscape:transform-center-x="-3"
+ sodipodi:nodetypes="ccccccccccccccccc"
+ id="path36524"
+ d="m 457.5,189 0.83982,-0.68197 L 459,187.5 l 0,-0.5 -1,0 0,-1 -1,0 0,-1 -0.25,0 -0.66329,1.10494 L 455,186.75 l 0,0.25 1,0 0,1 1,0 0,1 0.5,0 z"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 449,187.5 0.68197,0.83982 L 450.5,189 l 0.5,0 0,-1 1,0 0,-1 1,0 0,-0.25 -1.10494,-0.66329 L 451.25,185 l -0.25,0 0,1 -1,0 0,1 -1,0 0,0.5 z"
+ id="path36526"
+ sodipodi:nodetypes="ccccccccccccccccc"
+ inkscape:transform-center-x="3"
+ inkscape:transform-center-y="3"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="cssscczzzz"
+ 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="path36528"
+ d="m 190.07108,29.454411 c -3.02619,0 -5.48439,2.463313 -5.48438,5.5 0,3.036688 2.45819,5.500001 5.48438,5.5 3.02619,0 5.48437,-2.46331 5.48437,-5.5 0,-3.036689 -2.45818,-5.500001 -5.48437,-5.5 z m 0.0124,3.388115 c 1.26359,0 2.10599,0.846143 2.10599,2.115354 0,1.269211 -0.8424,2.115353 -2.10599,2.115353 -1.26359,0 -2.10598,-0.846141 -2.10598,-2.115353 0,-1.269212 0.84239,-2.115354 2.10598,-2.115354 l 0,0 0,0 0,0 z"
+ style="fill:url(#linearGradient37529);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.75983924;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" />
+ <path
+ transform="matrix(0.5547465,0,0,-0.5552803,116.84153,100.48096)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient37531);stroke-width:2.28174472;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="path36530"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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" />
+ <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"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36532"
+ style="fill:none;stroke:url(#linearGradient37533);stroke-width:3.21050167;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:type="arc"
+ transform="matrix(0.3942416,0,0,-0.3946688,138.04864,81.514802)" />
+ <path
+ sodipodi:nodetypes="cccccccccccccccccccccccccccc"
+ id="path36534"
+ d="m 190.94678,29.919785 -0.8687,-0.147436 -0.81609,0.147436 0,2.538424 0.8347,-0.01215 0.85009,0.01215 0,-2.538424 0,0 0,0 0,0 z m 1.68479,4.230706 0,0.846142 0,0.846141 2.52718,0 0.0755,-0.891284 -0.0755,-0.800999 -2.52718,0 0,0 0,0 0,0 z m -7.58155,0 -0.10953,0.819696 0.10953,0.872587 2.52718,0 0,-0.846141 0,-0.846142 -2.52718,0 z m 5.89676,3.17303 -0.8687,0.152099 -0.81609,-0.152099 0,2.74996 0.8347,0.07585 0.85009,-0.07585 0,-2.74996 z"
+ style="fill:#d40000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ 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"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36536"
+ style="fill:none;stroke:url(#linearGradient37535);stroke-width:2.28174472;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:type="arc"
+ transform="matrix(0.5547465,0,0,-0.5552803,116.84153,100.48096)" />
+ <path
+ transform="matrix(0.3942416,0,0,-0.3946688,138.04864,81.514802)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient37537);stroke-width:3.21050167;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="path36538"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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>
+ <g
+ style="opacity:0.96000001;display:inline;enable-background:new"
+ id="g36540"
+ inkscape:label="Layer 1"
+ transform="translate(-211.14286,264.78067)">
+ <g
+ transform="translate(307.14286,-384.78067)"
+ id="g36542"
+ style="display:inline">
+ <rect
+ y="592"
+ x="182"
+ height="16"
+ width="16"
+ id="rect36544"
+ 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="g36546"
+ transform="translate(117.00001,391)">
+ <g
+ transform="translate(-203,-446)"
+ style="display:inline"
+ id="g36548">
+ <g
+ transform="matrix(0.9993234,0,0,1.0050357,164.07104,603.72198)"
+ style="opacity:0.96000001;display:inline"
+ id="g36550">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path36552"
+ d="m 118.00879,52.264848 10e-6,2.238708 -7.00472,3.482446 -6.00407,-2.984969 -1e-5,-2.238708 7.00473,-2.736203 6.00406,2.238726 0,0 0,0 0,0 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.79609263;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path36554"
+ d="m 105.00001,52.762325 7.00473,-2.736212 6.00406,2.238717 0,2.238716 -7.00473,1.492495 -6.00406,-0.995 0,-2.238716 0,0 0,0 0,0 z"
+ style="fill:#e6e6e6;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"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 105.00998,54.999895 -0.01,-1.988833 6.00407,2.984969 0.01,1.988833 -6.00406,-2.984969 -1e-5,0 z"
+ id="path36556"
+ 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="path36558"
+ d="m 118.0088,54.503556 -0.01,-1.988833 -6.99476,3.481308 c 0,2.570679 0,1.425722 0,1.989979 l 7.00473,-3.482454 3e-5,0 0,0 0,0 z"
+ style="fill:#4d4d4d;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" />
+ </g>
+ <path
+ style="fill:none;stroke:url(#linearGradient37539);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 269.25,657.25 0,1.5 5.75,3 6.75,-3.5 0,-1.5"
+ id="path36560"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="M 70,228.5 65,226"
+ id="path36562"
+ transform="translate(2.0099702,-15.001162)"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline"
+ transform="matrix(-1,0,0,1,433.97059,0)"
+ id="g36564">
+ <path
+ sodipodi:nodetypes="cssccssccssc"
+ id="path36566"
+ d="m 245.5,593.5 c 1.25,2.5 0.97056,4.5 0.97056,6.5 0,0.75 1,0.75 1,0 0,-2.5 0.0294,-4 -1.97056,-6.5 z m -5,0 c 2.75,1.25 2.97056,4.5 2.97056,6.5 0,0.75 1,0.75 1,0 0,-2.5 -0.72056,-5 -3.97056,-6.5 z m -1,4 c 1.97058,0 1.97058,2 1.97058,2.5 0,0.75 0,0.75 0,0 0,-0.5 0,-2.5 -1.97058,-2.5 z"
+ style="fill:none;stroke:url(#linearGradient37541);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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cssccssccssc"
+ id="path36568"
+ d="m 245.5,593.5 c 1.25,2.5 0.97056,4.5 0.97056,6.5 0,0.75 1,0.75 1,0 0,-2.5 0.0294,-4 -1.97056,-6.5 z m -5,0 c 2.75,1.25 2.97056,4.5 2.97056,6.5 0,0.75 1,0.75 1,0 0,-2.5 -0.72056,-5 -3.97056,-6.5 z m -1,4 c 1.97058,0 1.97058,1.5 1.97058,2.5 0,0.5 0,0.5 0,0 0,-1 0,-2.5 -1.97058,-2.5 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient37543);stroke-width:1.29999995;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>
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g36570"
+ transform="translate(21,254)">
+ <rect
+ y="321"
+ x="66"
+ height="20"
+ width="20"
+ id="rect36572"
+ style="opacity:0;fill:#ececec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ transform="translate(-235,231)"
+ id="g36574"
+ style="display:inline;enable-background:new">
+ <g
+ transform="translate(392,-78.06282)"
+ id="g36576"
+ style="display:inline;enable-background:new">
+ <g
+ id="g36578">
+ <g
+ mask="url(#mask13041)"
+ id="g36580"
+ transform="translate(-360,181.06282)">
+ <path
+ mask="none"
+ sodipodi:nodetypes="ccccccccccccsccc"
+ style="fill:#dcdcdc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 279.46875,-12.53125 c -1.65264,0 -2.96875,1.066109 -2.96875,2.71875 l 0,2.5625 c 0,1.6526411 1.31612,2.71875 2.96875,2.71875 l 0.0625,0 c 1.65264,0 2.96875,-1.0661089 2.96875,-2.71875 l 0,-2.5625 c 0,-1.652641 -1.31612,-2.71875 -2.96875,-2.71875 l -0.0625,0 z M 279.5,-10.5 c 0.554,0 1,0.196 1,0.75 l 0,2.5 c 0,0.554 -0.446,0.75 -1,0.75 -0.554,0 -1,-0.196 -1,-0.75 l 0,-2.5 c 0,-0.554 0.446,-0.75 1,-0.75 z"
+ id="path36582"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="-10"
+ x="277"
+ height="2.5"
+ width="1"
+ id="rect36584"
+ style="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"
+ ry="0.5" />
+ <rect
+ style="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"
+ id="rect36586"
+ width="1"
+ height="1"
+ x="277.49176"
+ y="-11.287262"
+ ry="0.5" />
+ </g>
+ <g
+ mask="url(#mask13052)"
+ transform="translate(-360,191.06282)"
+ id="g36588">
+ <path
+ id="path36590"
+ d="m 279.46875,-11.53125 c -1.65264,0 -2.96875,1.003609 -2.96875,2.65625 l 0,2.5625 c 0,1.6526411 1.34737,2.75 3,2.75 l 0.0625,0 c 1.65264,0 2.9375,-1.0973589 2.9375,-2.75 l 0,-2.5625 c 0,-1.652641 -1.31612,-2.65625 -2.96875,-2.65625 l -0.0625,0 z M 279.5,-9.5 c 0.554,0 1,0.1335 1,0.6875 l 0,2.5 c 0,0.554 -0.41475,0.78125 -0.96875,0.78125 -0.554,0 -1.03125,-0.22725 -1.03125,-0.78125 l 0,-2.5 c 0,-0.554 0.446,-0.6875 1,-0.6875 z"
+ style="fill:#dcdcdc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccccccccsccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="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"
+ id="rect36592"
+ width="1"
+ height="2.5"
+ x="277"
+ y="-10"
+ ry="0.390625" />
+ <rect
+ y="-11"
+ x="278"
+ height="1"
+ width="1"
+ id="rect36594"
+ style="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"
+ ry="0.5" />
+ </g>
+ </g>
+ <g
+ id="g36596" />
+ </g>
+ <rect
+ style="opacity:0.15;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36608"
+ width="1"
+ height="3"
+ x="311"
+ y="93" />
+ <rect
+ y="104"
+ x="311"
+ height="3"
+ width="1"
+ id="rect36610"
+ style="opacity:0.15;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g36612"
+ transform="translate(0,275)">
+ <g
+ transform="translate(-226,210)"
+ id="g36614"
+ style="display:inline;enable-background:new">
+ <path
+ id="path36616"
+ d="m 302.5,105.52631 0,-4"
+ style="fill:none;stroke:#2d2d2d;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <g
+ mask="url(#mask24466)"
+ transform="translate(23,116.0625)"
+ id="g36618">
+ <path
+ id="path36620"
+ d="m 279.46875,-12.59375 c -1.65264,0 -2.96875,1.066109 -2.96875,2.71875 l 0,2.5625 c 0,1.6526411 1.31612,2.78125 2.96875,2.78125 l 0.0625,0 c 1.65264,0 2.96875,-1.1286089 2.96875,-2.78125 l 0,-2.5625 c 0,-1.652641 -1.31612,-2.71875 -2.96875,-2.71875 l -0.0625,0 z m 0.0312,2.03125 c 0.554,0 1,0.196 1,0.75 l 0,2.5 c 0,0.554 -0.446,0.8125 -1,0.8125 -0.554,0 -1,-0.2585 -1,-0.8125 l 0,-2.5 c 0,-0.554 0.446,-0.75 1,-0.75 z"
+ style="fill:#dcdcdc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccccccccsccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.7;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"
+ id="rect36622"
+ width="1"
+ height="3.5"
+ x="277"
+ y="-11.0625"
+ ry="0.5" />
+ <rect
+ y="-12.0625"
+ x="278"
+ height="1"
+ width="1"
+ id="rect36624"
+ style="opacity:0.7;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"
+ ry="0.5" />
+ </g>
+ <g
+ id="g36626"
+ mask="url(#mask24456)"
+ transform="translate(2e-6,-21.02385)">
+ <path
+ id="path36628"
+ d="m 302.5,118.49506 0,-3.99506"
+ style="fill:none;stroke:#2d2d2d;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(22.999998,128.02385)"
+ id="g36630"
+ mask="none">
+ <path
+ id="path36632"
+ d="m 279.46875,-11.53125 c -1.65264,0 -2.96875,1.128609 -2.96875,2.78125 l 0,2.5 c 0,1.6526411 1.34737,2.75 3,2.75 l 0.0625,0 c 1.65264,0 2.9375,-1.0973589 2.9375,-2.75 l 0,-2.5 c 0,-1.652641 -1.31612,-2.78125 -2.96875,-2.78125 l -0.0625,0 z M 279.5,-9.5 c 0.554,0 1,0.2585 1,0.8125 l 0,2.4375 c 0,0.554 -0.41475,0.78125 -0.96875,0.78125 -0.554,0 -1.03125,-0.22725 -1.03125,-0.78125 l 0,-2.4375 c 0,-0.554 0.446,-0.8125 1,-0.8125 z"
+ style="fill:#dcdcdc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccccccccsccc"
+ mask="none"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.7;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"
+ id="rect36634"
+ width="1"
+ height="3.5"
+ x="277"
+ y="-10"
+ ry="0.5" />
+ <rect
+ y="-11"
+ x="278"
+ height="1"
+ width="1"
+ id="rect36636"
+ style="opacity:0.7;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" />
+ </g>
+ <g
+ mask="none"
+ id="g36638"
+ transform="translate(22.999998,120)">
+ <path
+ mask="none"
+ sodipodi:nodetypes="ccccccccccccsccc"
+ style="fill:#dcdcdc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 279.46875,-11.53125 c -1.65264,0 -2.96875,1.128609 -2.96875,2.78125 l 0,2.5 c 0,1.6526411 1.34737,2.75 3,2.75 l 0.0625,0 c 1.65264,0 2.9375,-1.0973589 2.9375,-2.75 l 0,-2.5 c 0,-1.652641 -1.31612,-2.78125 -2.96875,-2.78125 l -0.0625,0 z M 279.5,-9.5 c 0.554,0 1,0.2585 1,0.8125 l 0,2.4375 c 0,0.554 -0.41475,0.78125 -0.96875,0.78125 -0.554,0 -1.03125,-0.22725 -1.03125,-0.78125 l 0,-2.4375 c 0,-0.554 0.446,-0.8125 1,-0.8125 z"
+ id="path36640"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="-10"
+ x="277"
+ height="3.5"
+ width="1"
+ id="rect36642"
+ style="opacity:0.7;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" />
+ <rect
+ style="opacity:0.7;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"
+ id="rect36644"
+ width="1"
+ height="1"
+ x="278"
+ y="-11" />
+ </g>
+ <g
+ id="g36646"
+ mask="none"
+ transform="translate(21.999998,-0.00494)">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path36648"
+ d="m 280.5,118.5 0,-4"
+ style="opacity:0.55;fill:none;stroke:#1a1a1a;stroke-width:2.79440284;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path36650"
+ d="m 280.5,118.5 0,-4"
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <path
+ style="opacity:0.55;fill:none;stroke:#1a1a1a;stroke-width:2.79440284;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 302.5,105.52631 0,-4"
+ id="path36652"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 302.5,105.52631 0,-4"
+ id="path36654"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="99"
+ x="302"
+ height="1"
+ width="1"
+ id="rect36664"
+ style="opacity:0.15;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <rect
+ y="297"
+ x="66"
+ height="26"
+ width="20"
+ id="rect36666"
+ style="opacity:0;fill:#ececec;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <g
+ transform="matrix(-1,0,0,1,530,548)"
+ style="opacity:0.9;display:inline;enable-background:new"
+ id="g36668">
+ <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"
+ width="16"
+ height="16"
+ x="488"
+ y="29" />
+ <g
+ id="g36672">
+ <path
+ sodipodi:nodetypes="csccccccccsssc"
+ id="path36674"
+ d="m 500.5,34.5 0,5 c 0,1.666667 0.25,1.75 1,3.25 l -1.25,1.75 -1.75,-1.75 -1.75,1.75 -0.5,0 -1.75,-1.75 -1.75,1.75 -1,0 C 491,43 490.5,42.416667 490.5,40.75 l 0,-6.25 c 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
+ style="fill:url(#linearGradient37545);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" />
+ <path
+ d="m 495.5,30.375 c -2.28774,0 -4.125,1.837258 -4.125,4.125 l 0,6.25 c 0,0.74605 0.0978,1.170828 0.28125,1.625 0.13101,0.324408 0.38353,0.789244 0.625,1.25 l 0.0937,0 1.5,-1.5 a 0.87292083,0.87292083 0 0 1 1.25,0 l 1.375,1.375 1.375,-1.375 a 0.87292083,0.87292083 0 0 1 1.1875,-0.03125 l 1.375,1.21875 0.1875,-0.1875 0,-0.4375 C 500.24057,42.152166 499.91254,41.661109 499.78125,41.125 499.62101,40.470677 499.625,39.833334 499.625,39 l 0,-4.5 c 0,-2.287742 -1.83726,-4.125 -4.125,-4.125 z"
+ id="path36676"
+ style="fill:none;stroke:url(#linearGradient37547);stroke-width:1;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:original="M 495.5 29.5 C 492.74 29.5 490.5 31.74 490.5 34.5 L 490.5 40.75 C 490.5 42.416667 491 43 491.75 44.5 L 492.75 44.5 L 494.5 42.75 L 496.25 44.5 L 496.75 44.5 L 498.5 42.75 L 500.5 44.5 L 501.5 43.5 L 501.5 42.5 C 500.5 41.25 500.5 40.666667 500.5 39 L 500.5 34.5 C 500.5 31.74 498.26 29.5 495.5 29.5 z "
+ inkscape:radius="-0.87283355"
+ sodipodi:type="inkscape:offset" />
+ <g
+ style="opacity:0.25;fill:#000000"
+ id="g36678">
+ <path
+ sodipodi:nodetypes="cccc"
+ style="fill:#000000;fill-rule:evenodd;stroke:none"
+ d="m 493,43.75 c 0,-0.212963 0,-5.75 0,-5.75 l 1.5,4.472222 L 493,43.75 z"
+ id="path36681"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path36683"
+ d="m 497,44 c 0,-0.203703 -1,-6 -1,-6 l 2,3.428571 0,1.714286 L 497,44 z"
+ style="fill:#000000;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(-1,0,0,1,990,0.25)"
+ id="g36685"
+ style="opacity:0.7;fill:#ffffff">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path36687"
+ d="m 493,43.75 c 0,-0.212963 1,-6 1,-6 l 1,5 -1,1 -1,0 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:none"
+ d="m 497,43.75 c 0,-0.203703 0,-6 0,-6 l 2,5 -1,1 -1,0 z"
+ id="path36689"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:none"
+ d="m 490,43.25 c 0,-0.212963 1.5,-6.25 1.5,-6.25 l 0.5,5.5 -2,0.75 z"
+ id="path36691"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ 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"
+ d="m 500.5,34.5 0,4.5 c 0,1.666667 0,2.25 1,3.5 l 0,1 -1,1 -2,-1.75 -1.75,1.75 -0.5,0 -1.75,-1.75 -1.75,1.75 -0.5,0 C 491,43 490.5,43.166667 490.5,41.5 l 0,-7 c 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
+ id="path36693"
+ sodipodi:nodetypes="cscccccccccsssc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path36695"
+ d="m 56,139 0,1 -1,0 0,1 2,0 0,-2 -1,0 z"
+ style="opacity:0.8;fill:url(#linearGradient37549);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;enable-background:new"
+ sodipodi:nodetypes="ccccccc"
+ transform="translate(441,-105)"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.8;fill:url(#linearGradient37551);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;enable-background:new"
+ d="m 51,139 0,2 2,0 0,-1 -1,0 0,-1 -1,0 z"
+ id="path36697"
+ sodipodi:nodetypes="ccccccc"
+ transform="translate(441,-105)"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(47,571)"
+ id="g36699"
+ 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"
+ d="m 67,7.75 0,7.25 -1,0 -1,-2 -1,0 0,1 2,5 2,2 7,0 2,-3.25 0,-4 L 76.5,13 76,13 76,14 75,14 75,12.75 74.25,12 73,12 l 0,2 -1,0 0,-2 -1,-1 -1,0 0,3 -1,0 L 69,7.75 68.37057,7 67.643297,7 67,7.75 z"
+ id="path36701"
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36703"
+ width="16"
+ height="16"
+ x="63"
+ y="6" />
+ <path
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccc"
+ id="path36705"
+ d="m 67,7.75 0,7.25 -1,0 0,-1 -1,-1 -1,0 0,1 2,5 2,2 7,0 2,-3.25 0,-4 L 76.5,13 76,13 76,14 75,14 75,12.75 74.25,12 73,12 l 0,2 -1,0 0,-2 -1,-1 -1,0 0,3 -1,0 L 69,7.75 68.37057,7 67.643297,7 67,7.75 z"
+ style="fill:url(#linearGradient37553);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.40000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient37555);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.40000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 69,17 0,3 1,0 0,-3 -1,0 z m 2,0 0,3 1,0 0,-3 -1,0 z m 2,0 0,3 1,0 0,-3 -1,0 z"
+ id="path36707"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="15"
+ x="66"
+ height="1"
+ width="1"
+ id="rect36709"
+ style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36711"
+ width="1"
+ height="1"
+ x="66"
+ y="16" />
+ <path
+ style="fill:none;stroke:url(#linearGradient37557);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 74.09375,12.25 -0.625,0 0,1.75 c 0.0031,0.12523 -0.04536,0.246239 -0.133933,0.334817 C 73.246239,14.423395 73.12523,14.4718 73,14.46875 L 72.5,14.5 m -1.65625,-3.25 -0.375,0 0,2.75 c 0.0031,0.12523 -0.04536,0.246239 -0.133933,0.334817 C 70.246239,14.423395 70.12523,14.4718 70,14.46875 L 69.5,14.5 M 64.46875,13.46875 64.5,14 l 1.870938,4.629172 1.847812,1.902078 6.53125,0 1.78125,-2.875 0,-4 -0.0625,-0.125 0,0.46875 c 0.0031,0.12523 -0.04536,0.246239 -0.133933,0.334817 C 76.246239,14.423395 76.12523,14.4718 76,14.46875 L 75.5,14.5 m -7.3125,-7.03125 -0.3125,0 L 67.5,8 l 0,7"
+ id="path36713"
+ sodipodi:nodetypes="cccscccccscccccccccccscccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.15;fill:url(#radialGradient37559);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.40000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 66,15 0,-1 -1,-1 -1,0 0,1 2,5 0,-4 z"
+ id="path36715"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g36882"
+ transform="translate(-21,254)">
+ <rect
+ ry="0"
+ rx="0"
+ y="323"
+ x="257"
+ height="16"
+ width="16"
+ id="rect36884"
+ style="opacity:0;fill:#ffaaaa;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g36886"
+ 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"
+ transform="translate(21,69)">
+ <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="rect36888"
+ width="1"
+ height="2"
+ x="236"
+ y="262" />
+ <rect
+ y="-239.00793"
+ x="260"
+ height="2.0079346"
+ width="1"
+ id="rect36890"
+ 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="matrix(0,1,-1,0,0,0)" />
+ <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="rect36892"
+ width="1"
+ height="2"
+ x="236"
+ y="266" />
+ <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="rect36894"
+ width="2"
+ height="1"
+ x="236.99207"
+ y="269" />
+ <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="rect36896"
+ width="1"
+ height="1.9920638"
+ x="269"
+ y="-242.99207" />
+ <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="rect36898"
+ width="1"
+ height="1.9920638"
+ x="269"
+ y="-246.99207" />
+ <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="rect36900"
+ width="1"
+ height="2"
+ x="246.99207"
+ y="266" />
+ </g>
+ <g
+ style="fill:#321900;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="g36902">
+ <rect
+ transform="scale(1,-1)"
+ style="fill:#321900;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36904"
+ width="1"
+ height="2"
+ x="257"
+ y="-331" />
+ <rect
+ transform="scale(1,-1)"
+ style="fill:#321900;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36906"
+ width="1"
+ height="2"
+ x="257"
+ y="-335" />
+ <rect
+ transform="scale(1,-1)"
+ style="fill:#321900;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36908"
+ width="1"
+ height="2"
+ x="257"
+ y="-339" />
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ style="fill:#321900;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36910"
+ width="1"
+ height="2.0079362"
+ x="338"
+ y="259.99207" />
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ style="fill:#321900;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36912"
+ width="1"
+ height="2.0079362"
+ x="338"
+ y="263.99207" />
+ <rect
+ y="-339"
+ x="267.99207"
+ height="2"
+ width="1"
+ id="rect36914"
+ style="fill:#321900;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)" />
+ </g>
+ <rect
+ y="330"
+ x="258"
+ height="8"
+ width="10"
+ id="rect36916"
+ style="opacity:0.2;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
+ id="g36918"
+ transform="translate(-205,313.97063)">
+ <rect
+ style="fill:url(#linearGradient37571);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36920"
+ width="12"
+ height="10"
+ x="465.5"
+ y="10.5"
+ ry="1.5909902"
+ rx="1.5909902" />
+ <path
+ style="fill:url(#linearGradient37573);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 465,13.40909 0,4.59375 c 0,0.56244 0.36784,0.99717 0.84375,0.99716 l 11.3125,0.01065 c 0.47591,0 0.84375,-0.43471 0.84375,-0.99716 l 0,-4.59375 c -0.31371,0.37073 -0.76923,0.59091 -1.25,0.59091 L 466.25,14 c -0.48077,0 -0.93629,-0.22018 -1.25,-0.59091 l 0,0 0,0 0,0 z"
+ id="path36922"
+ sodipodi:nodetypes="ccccccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ ry="0.98531502"
+ y="10.52937"
+ x="465.5"
+ height="1.9999996"
+ width="12"
+ id="rect36924"
+ 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.4762714" />
+ <rect
+ ry="1.3782184"
+ y="10.5"
+ x="465.5"
+ height="10"
+ width="12"
+ id="rect36926"
+ 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"
+ rx="1.3782184" />
+ <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="rect36928"
+ width="9.9998779"
+ height="7.999999"
+ x="466.5"
+ y="11.5"
+ ry="0.44196323"
+ rx="0.39062494" />
+ <g
+ transform="matrix(0.7547901,0,0,1,414.01868,-484.99999)"
+ id="g36930">
+ <path
+ transform="matrix(0.7834486,0,0,0.2000006,10.413535,395.5997)"
+ 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="path36932"
+ style="fill:none;stroke:#999999;stroke-width:2.90780973;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
+ style="fill:none;stroke:#000000;stroke-width:0.92082453;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.531013,495.51105 0,-0.50001 c 0,-0.276 0.890314,-0.5 1.987308,-0.5 1.096993,0 1.987307,0.224 1.987307,0.5 l 0,0.50001"
+ id="path36934"
+ sodipodi:nodetypes="csccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="495.01105"
+ x="70.193451"
+ height="1"
+ width="2.6497409"
+ id="rect36936"
+ 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
+ id="g36938"
+ transform="matrix(1,0,0,0.6666667,331,-319.00002)">
+ <rect
+ y="496.5"
+ x="143"
+ height="1.5"
+ width="2"
+ id="rect36940"
+ 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(#radialGradient37575);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36942"
+ width="2"
+ height="1.5"
+ x="143"
+ y="496.5" />
+ </g>
+ <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="rect36944"
+ width="1"
+ height="1"
+ x="468"
+ y="13" />
+ <g
+ transform="translate(1.1408497e-7,0.5000446)"
+ id="g36946">
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.89240623;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="path36948"
+ 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(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 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="path36950"
+ style="opacity:0.25;fill:none;stroke:#000000;stroke-width:0.71801031;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:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient37578);stroke-width:1.11641002;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="path36952"
+ 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.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 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="path36954"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#b3b3b3;stroke-width:0.80643582;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(#linearGradient37580);stroke-width:1.69505489;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="path36956"
+ 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.591154,0,0,0.5887513,425.87219,-279.05319)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#radialGradient37582);stroke-width:0.80110824;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="path36958"
+ 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.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 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="path36960"
+ style="opacity:0.7;fill:url(#radialGradient37584);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
+ sodipodi:type="arc"
+ style="opacity:0.2;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="path36962"
+ 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.1975308,0,0,0.1999991,456.0926,-84.399595)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.7;fill:url(#radialGradient37586);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.26754272;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path36964"
+ 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.6760501,-0.1575078,0.1570322,-0.6740085,446.07727,367.34791)" />
+ </g>
+ <path
+ sodipodi:nodetypes="cc"
+ id="path36966"
+ d="m 476.49997,11.941967 0,7.174103"
+ style="opacity:0.05;fill:none;stroke:#ffffff;stroke-width:0.99999982;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ 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"
+ d="m 258,330 0,8 1,0 0,-7 1,0 0,-1 -2,0 z"
+ id="path36968"
+ sodipodi:nodetypes="ccccccc"
+ 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" />
+ <g
+ id="g36976"
+ transform="translate(1,84)">
+ <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" />
+ </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:#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"
+ 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"
+ id="rect37070"
+ width="16"
+ height="16"
+ x="173"
+ y="491" />
+ <g
+ id="g37072">
+ <g
+ style="stroke:#1a1a1a;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none"
+ id="g37074"
+ transform="translate(-63.000001,168)">
+ <g
+ style="stroke:#1a1a1a;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none"
+ id="g37076">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 243.5,336.5 0,-12"
+ id="path37078"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 240.5,325.5 3,3 3,-3"
+ id="path37080"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path37082"
+ d="m 240.5,335.5 3,-3 3,3"
+ style="fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="stroke:#1a1a1a;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none"
+ transform="matrix(0,1,-1,0,574,87)"
+ id="g37084">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path37086"
+ d="m 243.5,336.5 0,-12"
+ style="fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path37088"
+ d="m 240.5,325.5 3,3 3,-3"
+ style="fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 240.5,335.5 3,-3 3,3"
+ id="path37090"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g37092"
+ style="stroke:#c8c8c8;stroke-opacity:1">
+ <g
+ id="g37094"
+ style="stroke:#c8c8c8;stroke-opacity:1">
+ <g
+ style="stroke:#c8c8c8;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="g37096"
+ transform="translate(-63.000001,168)">
+ <path
+ style="fill:none;stroke:#c8c8c8;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 243.5,336.5 0,-12"
+ id="path37098"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#c8c8c8;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 240.5,325.5 3,3 3,-3"
+ id="path37100"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path37102"
+ d="m 240.5,335.5 3,-3 3,3"
+ style="fill:none;stroke:#c8c8c8;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="stroke:#c8c8c8;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ transform="matrix(0,1,-1,0,511,255)"
+ id="g37104">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path37106"
+ d="m 243.5,336.5 0,-12"
+ style="fill:none;stroke:#c8c8c8;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path37108"
+ d="m 240.5,325.5 3,3 3,-3"
+ style="fill:none;stroke:#c8c8c8;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#c8c8c8;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 240.5,335.5 3,-3 3,3"
+ id="path37110"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <path
+ transform="matrix(0.625,0,0,0.625,15.1875,291.9375)"
+ sodipodi:type="arc"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#c8c8c8;stroke-width:2.4000001;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="path37112"
+ sodipodi:cx="264.5"
+ sodipodi:cy="330.5"
+ sodipodi:rx="2"
+ sodipodi:ry="2"
+ d="m 266.5,330.5 a 2,2 0 1 1 -4,0 2,2 0 1 1 4,0 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"
+ d="M 175.75,495.75 175.5,495.5"
+ id="path37114"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path37116"
+ d="m 177.5,493.5 0.25,0.25"
+ style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 180.5,492.25 0,2.5"
+ id="path37118"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ 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"
+ d="m 177,500 -1.75,1.75"
+ id="path37120"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path37122"
+ d="m 174.25,498.5 2.5,0"
+ 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
+ sodipodi:nodetypes="cc"
+ id="path37124"
+ d="m 179.75,501.25 -2.5,2.5"
+ style="fill:none;stroke:#ffffff;stroke-width:1;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
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#ffffff;stroke-width:1;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 185.75,495.25 -2.5,2.5"
+ id="path37126"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path37128"
+ d="M 183.75,493.25 182,495"
+ 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 a 2,2 0 1 1 -4,0 2,2 0 1 1 4,0 z"
+ sodipodi:ry="2"
+ sodipodi:rx="2"
+ sodipodi:cy="330.5"
+ sodipodi:cx="264.5"
+ id="path37130"
+ style="fill:none;stroke:url(#linearGradient37588);stroke-width:2.4000001;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"
+ sodipodi:type="arc"
+ transform="matrix(0.625,0,0,0.625,15.1875,291.9375)" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path37132"
+ d="m 182.5,502.5 0,0"
+ style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 184.5,500.5 0,0"
+ id="path37134"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ d="m 185.5,498.5 1.25,0"
+ id="path37136"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g37138"
+ transform="translate(147.01612,401.00818)">
+ <rect
+ transform="scale(1,-1)"
+ y="-87"
+ x="256.98419"
+ height="16"
+ width="16"
+ id="rect37140"
+ 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
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265"
+ d="m 266.48388,77.49182 c -1,0 -2,10e-6 -3,2e-5 0,0.99999 0,1.99999 0,2.99998 1,0 2,-1e-5 3,-2e-5 0,-0.99999 0,-1.99998 0,-2.99998 z"
+ id="path37142"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path37144"
+ d="m 266.48388,83.49182 c -1,0 -2,10e-6 -3,10e-6 0,1 0,2 0,2.99999 1,-1e-5 2,-1e-5 3,-2e-5 0,-0.99999 0,-1.99999 0,-2.99998 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265"
+ d="m 261.48419,74.5 c -1,0 -2,1e-5 -3,1e-5 0,1 0,2 0,2.99999 1,-1e-5 2,-1e-5 3,-2e-5 0,-0.99999 0,-1.99999 0,-2.99998 z"
+ id="path37146"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265"
+ d="m 261.48419,80.5 c -1,0 -2,1e-5 -3,1e-5 0,1 0,2 0,2.99999 1,-1e-5 2,-1e-5 3,-2e-5 0,-0.99999 0,-1.99999 0,-2.99998 z"
+ id="path37148"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(-189.01581,-315)"
+ style="opacity:0.55"
+ id="g37150">
+ <path
+ id="path37152"
+ d="m 460.50726,389.48364 c -1.00252,0 -2.00505,1e-5 -3.00757,1e-5 0,1.00272 0,2.00544 0,3.00817 1.00252,0 2.00505,-1e-5 3.00757,-1e-5 0,-1.00273 0,-2.00545 0,-3.00817 z"
+ style="fill:none;stroke:#000000;stroke-width:1.00000072;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1.00000072;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265"
+ d="m 460.51514,395.48364 c -1.00252,0 -2.00505,1e-5 -3.00757,1e-5 0,1.00272 0,2.00544 0,3.00817 1.00252,0 2.00505,-1e-5 3.00757,-1e-5 0,-1.00273 0,-2.00545 0,-3.00817 z"
+ id="path37154"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1.00000072;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265"
+ d="m 455.5,386.5 c -1.00252,0 -2.00505,10e-6 -3.00757,10e-6 0,1.00272 0,2.00544 0,3.00817 1.00252,0 2.00505,-10e-6 3.00757,-10e-6 0,-1.00273 0,-2.00545 0,-3.00817 z"
+ id="path37156"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-189.01581,-315)"
+ style="opacity:0.55"
+ id="g37158">
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 457.99938,389.98364 c 0.6694,0 1.33879,1e-5 2.00819,1e-5 0,0.66939 0,1.33877 0,2.00817 -0.6694,0 -1.33879,-1e-5 -2.00819,-1e-5 0,-0.66939 0,-1.33878 0,-2.00817 z"
+ id="path37160"
+ 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="path37162"
+ d="m 458.00726,395.98364 c 0.6694,0 1.33879,1e-5 2.00819,1e-5 0,0.66939 0,1.33877 0,2.00817 -0.6694,0 -1.33879,-1e-5 -2.00819,-1e-5 0,-0.66939 0,-1.33878 0,-2.00817 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;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\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path37164"
+ d="m 452.99212,387 c 0.6694,0 1.33879,10e-6 2.00819,10e-6 0,0.66939 0,1.33877 0,2.00817 -0.6694,0 -1.33879,-10e-6 -2.00819,-10e-6 0,-0.66939 0,-1.33878 0,-2.00817 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ transform="translate(420,44)"
+ id="g37166">
+ <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"
+ width="16.000006"
+ height="16.000002"
+ x="26.016129"
+ y="428" />
+ <rect
+ y="428"
+ x="26"
+ height="16"
+ width="16"
+ id="rect37170"
+ 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(1.0004639,0,0,0.9963165,-237.11238,367.28985)"
+ 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="g37172"
+ style="display:inline">
+ <path
+ transform="matrix(0.81218,0,0,0.815735,163.7897,-27.2907)"
+ 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:type="arc"
+ style="fill:#724c4c;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.10749674;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="path37174"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path37176"
+ style="fill:#f9f9f9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.16363633;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ transform="matrix(0.7480284,0,0,0.7480284,172.26025,-19.267349)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.6;fill:url(#linearGradient37590);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path37178"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.7478104,0,0,0.7510504,172.29077,-19.598754)" />
+ <path
+ style="fill:url(#linearGradient37592);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 269.98748,62.965763 c -1.39411,0.455357 -2.67784,0.634788 -4.24803,3.011091 l 2.24896,0 1.99907,-3.011091 0,0 0,0 0,0 z m 0.99954,0 0,3.011091 2.99861,0 -1.99908,-3.011091 -0.99953,0 z m 2.99861,3.011091 0.99953,3.011091 1.99907,0 c 0.006,-0.929403 -0.1914,-1.917894 -0.74965,-3.011091 l -2.24895,0 0,0 0,0 0,0 z m 0.99953,3.011091 -3.99814,0 0,3.011092 2.49884,0 1.4993,-3.011092 z m -3.99814,3.011092 -2.99861,0 1.99907,3.011091 0.99954,0 0,-3.011091 0,0 0,0 0,0 z m -2.99861,0 -0.99954,-3.011092 -1.99907,0 c -0.006,0.929404 0.1914,1.917895 0.74965,3.011092 l 2.24896,0 0,0 0,0 0,0 z m -0.99954,-3.011092 3.99815,0 0,-3.011091 -2.49884,0 -1.49931,3.011091 0,0 0,0 0,0 z m 7.24312,3.011092 -1.85125,3.011091 c 1.3675,-0.485137 2.19971,-0.728674 3.85384,-3.011091 l -2.00259,0 z"
+ id="path37180"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path37182"
+ d="m 274.00069,72.011668 0.005,0.97479 -0.99045,0.01431 -0.0223,1.019377 -0.481,0.837285 c 0.77072,-0.321774 2.72643,-1.067855 3.69499,-2.816464 l -2.20604,-0.0293 -2e-4,2e-6 0,0 0,0 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(0.749782,0,0,0.752489,172.03052,-19.77379)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path37185"
+ style="opacity:0.4;fill:url(#linearGradient37594);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(0.7010701,0,0,0.7040938,178.4346,-14.083074)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient37596);stroke-width:1.14049816;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="path37187"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#aaccff;stroke-width:0;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 268.98793,64.973163 0,0.407752 -0.93706,0 0,0.595945 -0.56224,0 0,1.003697 -0.49977,0 0,1.505546 0.99953,0 0,-1.505546 0.4373,0 0,-0.595945 0.56224,0 0,-0.407752 1.53054,0 0,-1.003697 -1.53054,0 z"
+ id="path37189"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(-499.98389,503.95862)"
+ style="display:inline;enable-background:new"
+ id="g37229">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path37231"
+ 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(#radialGradient37608);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="path37233"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path37235"
+ d="m 515.48389,-25.95862 -2.75,3.25 1.75,2.25 3,-3"
+ style="fill:none;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient37610);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="path37237"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#2b0000;stroke-width:1.29999995;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 520.48389,-31.45862 -6,6.75 2,2.25 4,-4"
+ id="path37239"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path37241"
+ d="m 520.98389,-31.95862 -6.75,7.75 1.75,1.75 5,-4.5 0,-5 z"
+ style="fill:url(#linearGradient37612);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 7,-8.25"
+ id="path37243"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.4;fill:none;stroke:url(#linearGradient37614);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="path37245"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g37307"
+ transform="translate(-42,86)">
+ <g
+ id="g37309"
+ transform="translate(209,0)">
+ <rect
+ rx="0.015625"
+ y="393"
+ x="222"
+ height="9"
+ width="9"
+ id="rect37311"
+ style="opacity:0;fill:#736c54;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ ry="0.015625" />
+ <g
+ id="g37313"
+ transform="matrix(0.4224039,0.424791,0.4224039,-0.424791,74.64489,479.288)"
+ style="display:inline">
+ <path
+ style="fill:url(#linearGradient37636);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.33543694;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 85.554034,278.09107 c 1.182038,0.59351 1.745531,1.60418 1.940766,2.40894 l 0.0052,0.2482 c 0,0.75 -0.75,1.75 -1.5,1.75 -0.75,0 -1.16648,-0.20985 -1.91648,-1.20806 -0.5,0 -0.676716,3.3e-4 -1.176716,3.3e-4 -0.75,0.99821 -1.156804,1.20773 -1.906804,1.20773 -0.75,0 -1.5,-1 -1.5,-1.75 l -0.0052,-0.2482 c 0.217441,-0.78256 0.749208,-1.83372 1.92792,-2.42058 l 0.07208,-4.57942 c -0.335564,-0.0958 -0.633693,-0.23081 -0.890995,-0.39497 -0.637372,-0.40663 -1.024226,-0.99226 -1.109005,-1.60503 l 0.0052,-0.2518 c 0,-0.75 0.68844,-1.71861 1.5,-1.75 0.71584,-0.0277 1.25,0 2,1.00179 l 1,0 c 0.749447,-1.00234 1.174653,-1.09387 2,-1.00179 0.745329,0.0832 1.5,1 1.5,1.75 l -0.0052,0.2518 c -0.122391,0.38782 -0.722942,1.77706 -2,2 l 0.05923,4.59106 4e-6,0 0,0 0,0 z"
+ id="path37315"
+ sodipodi:nodetypes="ccczcczccccsscsccscscc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path37317"
+ d="m 82.886207,273.9157 -0.02165,3.97041"
+ style="fill:none;stroke:#ffffff;stroke-width:1.66929841px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path37319"
+ d="M 82.4948,279.50001 C 80,278.75 79.891731,281.54098 81.141731,281.29098"
+ style="fill:none;stroke:#ffffff;stroke-width:0.83464772;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:0.83464754;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 82.320782,273.05364 c -2.405243,-1.28815 -1.663086,-3.01898 -0.56905,-2.28347"
+ id="path37321"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(315,0)"
+ id="g37323"
+ style="display:inline;enable-background:new">
+ <rect
+ ry="0.019097222"
+ style="opacity:0;fill:#736c54;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37325"
+ width="11"
+ height="11"
+ x="110"
+ y="386"
+ rx="0.019097222" />
+ <g
+ id="g37327">
+ <path
+ id="path37329"
+ d="m 116.53125,386.5 c -0.56312,0 -1.03125,0.46811 -1.03125,1.03125 l 0,0.9375 c 0,0.28156 0.12508,0.53133 0.3125,0.71875 L 113,392 c -0.18742,-0.18742 -0.46844,-0.5 -0.75,-0.5 l -0.75,0 c -0.56312,0 -1.03125,0.46811 -1.03125,1.03125 l 0,0.9375 c 0,0.56312 0.46813,1.03125 1.03125,1.03125 l 0.9375,0 c 0.0103,0 0.021,3e-4 0.0312,0 -3e-4,0.0102 0,0.021 0,0.0312 l 0,0.9375 c 0,0.56312 0.46813,1.03126 1.03125,1.03125 l 0.96875,0 c 0.56312,0 1,-0.46813 1,-1.03125 l 0,-0.9375 c 0,-0.28156 -0.10164,-0.53133 -0.28125,-0.71875 l 2.625,-2.625 c 0.18742,0.18742 0.43719,0.3125 0.71875,0.3125 l 0.96875,0 c 0.56312,0 1,-0.46813 1,-1.03125 l 0,-0.9375 c 0,-0.56312 -0.43688,-1.03125 -1,-1.03125 l -0.96875,0 c -0.0103,0 -0.021,-3e-4 -0.0312,0 3e-4,-0.0102 0,-0.021 0,-0.0312 l 0,-0.9375 c 0,-0.56312 -0.46813,-1.03125 -1.03125,-1.03125 l -0.9375,0 z"
+ style="fill:url(#linearGradient37638);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;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="cccccccccccsccccccccccccccscccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path37331"
+ d="m 111.5,393.5 0,-0.75 0.25,-0.25 1.75,0 3,-3 0,-1.75 0.25,-0.25 0.75,0"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 118.75,389.5 0.75,0 m -6,6 0,-0.75"
+ id="path37333"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.2;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"
+ id="rect37335"
+ width="1"
+ height="1"
+ x="114"
+ y="393" />
+ <rect
+ y="390"
+ x="117"
+ height="1"
+ width="1"
+ id="rect37337"
+ style="opacity:0.2;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>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g37339"
+ transform="translate(-84,65)">
+ <rect
+ transform="scale(-1,-1)"
+ y="-423"
+ x="-525"
+ height="16"
+ width="16"
+ id="rect37341"
+ 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="g37343"
+ transform="translate(205.00003,252.00003)"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\not used yet.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <g
+ transform="matrix(0.767131,0,0,0.788662,393.6565,37.08664)"
+ style="fill:#000000;fill-opacity:1"
+ id="g37345"
+ 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,390.0934,62.34418)"
+ id="g37347"
+ 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="g37350"
+ style="opacity:0.3" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 304.99997,158.99997 c 0.66669,0 1.33337,1e-5 2.00006,1e-5 0,0.66668 0,1.33337 0,2.00005 -0.66669,0 -1.33337,-1e-5 -2.00006,-1e-5 0,-0.66668 0,-1.33337 0,-2.00005 z"
+ id="path37352"
+ 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="g37354"
+ style="fill:none"
+ transform="translate(141,63)"
+ 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="fill:none;stroke:#000000;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265"
+ d="m 163.5,95.5 c 1,5e-6 2,1.1e-5 3,1.6e-5 0,0.999995 0,1.99999 0,2.999984 -1,-5e-6 -2,-1.1e-5 -3,-1.6e-5 0,-0.999994 0,-1.999989 0,-2.999984 z"
+ id="path37356"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path37358"
+ d="m 163.5,101.5 c 1,1e-5 2,1e-5 3,2e-5 0,0.99999 0,1.99999 0,2.99998 -1,-1e-5 -2,-1e-5 -3,-2e-5 0,-0.99999 0,-1.99998 0,-2.99998 z"
+ style="fill:none;stroke:#000000;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265"
+ d="m 168.49997,92.49997 c 1,5e-6 2,1.1e-5 3,1.6e-5 0,0.999995 0,1.999995 0,2.999985 -1,-1e-5 -2,-1e-5 -3,-2e-5 0,-0.99999 0,-1.999986 0,-2.999981 l 0,0 0,0 0,0 z"
+ id="path37360"
+ inkscape:connector-curvature="0" />
+ </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"
+ id="path37362"
+ d="m 304.99997,164.99997 c 0.66669,0 1.33337,1e-5 2.00006,1e-5 0,0.66668 0,1.33337 0,2.00005 -0.66669,0 -1.33337,-1e-5 -2.00006,-1e-5 0,-0.66668 0,-1.33337 0,-2.00005 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 309.99994,155.99994 c 0.66669,0 1.33337,1e-5 2.00006,1e-5 0,0.66668 0,1.33337 0,2.00005 -0.66669,0 -1.33337,-1e-5 -2.00006,-1e-5 0,-0.66668 0,-1.33337 0,-2.00005 z"
+ id="path37364"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g37366"
+ transform="matrix(0.7614057,0,0,0.7675903,253.76942,219.40377)">
+ <g
+ transform="matrix(1.1658027,0,0,1.1657997,198.71028,-2.0560643)"
+ id="g37368">
+ <path
+ transform="matrix(0.6969448,0,0,0.6969467,36.918512,140.83126)"
+ sodipodi:type="arc"
+ style="fill:#ff5a19;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path37370"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ 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"
+ sodipodi:start="4.712389"
+ sodipodi:end="5.7595865"
+ inkscape:transform-center-x="-2.8145849"
+ inkscape:transform-center-y="-3.2499984" />
+ <path
+ inkscape:transform-center-y="1.6729808e-05"
+ inkscape:transform-center-x="-3.2630798"
+ sodipodi:end="5.7595865"
+ sodipodi:start="4.712389"
+ 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 a 8,8 0 0 1 6.9282,4 L 132,118 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path37372"
+ style="fill:#ad2f94;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(0.3484724,0.6035735,-0.603572,0.3484734,154.13836,102.27942)" />
+ <path
+ transform="matrix(-0.3484724,0.6035735,-0.603572,-0.3484733,246.13507,184.51913)"
+ sodipodi:type="arc"
+ style="fill:#0060f0;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path37374"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ 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"
+ sodipodi:start="4.712389"
+ sodipodi:end="5.7595865"
+ inkscape:transform-center-x="-2.8145756"
+ inkscape:transform-center-y="3.2500173" />
+ <path
+ inkscape:transform-center-y="3.249994"
+ inkscape:transform-center-x="2.8145978"
+ sodipodi:end="5.7595865"
+ sodipodi:start="4.712389"
+ 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 a 8,8 0 0 1 6.9282,4 L 132,118 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path37376"
+ style="fill:#00d4aa;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(-0.6969448,2.2484149e-8,-4.6257528e-8,-0.6969467,220.91956,305.31067)" />
+ <path
+ transform="matrix(-0.3484724,-0.6035734,0.603572,-0.3484734,103.69972,343.86251)"
+ sodipodi:type="arc"
+ style="fill:#ccff00;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path37378"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ 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"
+ sodipodi:start="4.712389"
+ sodipodi:end="5.7595865"
+ inkscape:transform-center-x="3.2630773" />
+ <path
+ inkscape:transform-center-x="2.8145777"
+ sodipodi:end="5.7595865"
+ sodipodi:start="4.712389"
+ 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 a 8,8 0 0 1 6.9282,4 L 132,118 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path37380"
+ style="fill:#ffbf0e;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(0.3484724,-0.6035734,0.603572,0.3484733,11.703006,261.6228)"
+ inkscape:transform-center-y="-3.2500006" />
+ </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"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path37382"
+ style="fill:none;stroke:#000000;stroke-width:1.29430985;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.8124999,0,0,0.8045157,241.75,163.13011)" />
+ <path
+ transform="matrix(0.6594197,0,0,0.6608114,261.96791,180.02435)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient37640);stroke-width:1.98156261;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path37384"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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"
+ 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="rect37759"
+ width="16"
+ height="16"
+ x="173"
+ y="617" />
+ <g
+ style="display:inline"
+ id="g37761"
+ transform="translate(-290,397)">
+ <g
+ id="g37779">
+ <g
+ id="g37781"
+ style="opacity:0.85"
+ transform="translate(20.029029,0)">
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path37783"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ 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="path37785"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g37787"
+ transform="translate(20.029029,0)">
+ <path
+ id="path37789"
+ 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"
+ inkscape:connector-curvature="0" />
+ <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:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path37791"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ transform="translate(-58,340)"
+ id="g41151"
+ style="display:inline;enable-background:new">
+ <rect
+ y="48"
+ x="63"
+ height="16"
+ width="16"
+ id="rect41153"
+ 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(1.0003553,0,0,0.9995949,18.983834,-41.953346)"
+ style="display:inline"
+ 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="g41155">
+ <rect
+ y="91.491928"
+ x="45.5"
+ height="13.003749"
+ width="12.995382"
+ id="rect41157"
+ style="fill:url(#linearGradient42322);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80001998;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" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path41159"
+ d="m 46.49945,103.49527 0,-11.002747 10.996287,0 0,11.002747 -10.996287,0 z"
+ style="fill:none;stroke:url(#linearGradient42324);stroke-width:1.0000248px;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(-15,340)"
+ id="g41161"
+ style="display:inline;enable-background:new">
+ <rect
+ y="48"
+ x="83"
+ height="16"
+ width="16"
+ id="rect41163"
+ 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"
+ 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.1658027,0,0,1.1657997,-59.289717,-204.05607)"
+ id="g41165"
+ style="display:inline">
+ <path
+ transform="matrix(0.6969446,0,0,0.6900977,36.918531,141.69345)"
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.23686147;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path41167"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(-0.6391427,-0.07194179,0.07284933,-0.6344823,204.68584,307.47408)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path41169"
+ style="opacity:0.8;fill:url(#linearGradient42326);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:type="arc" />
+ <path
+ id="path41171"
+ style="fill:none;stroke:url(#linearGradient42328);stroke-width:0.51466751;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new"
+ d="m 134.27086,222.67786 c -0.8523,1.03645 -2.40069,1.91195 -5.35869,1.91195 -2.92931,0 -4.50028,-0.8755 -5.35806,-1.88283 m 5.3611,5.72324 c -1.3021,0 -2.35888,-2.40136 -2.35888,-5.36019 0,-2.95882 1.05678,-5.36019 2.35888,-5.36019 1.30211,0 2.35889,2.40137 2.35889,5.36019 0,2.9364 -1.03866,5.32486 -2.33081,5.35981"
+ 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"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path41173"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient42330);stroke-width:1.45605874;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.5885088,0,0,0.5897133,51.241774,153.48488)" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41175"
+ transform="translate(-21,359)">
+ <rect
+ y="29"
+ x="47"
+ height="16"
+ width="16"
+ id="rect41177"
+ 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="g41179"
+ transform="translate(116,-325)">
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -55,358.25 -6,-2.25 -6,2.25 0,7.5 6,3.25 6,-3.25 0,-7.5 z"
+ id="path41181"
+ sodipodi:nodetypes="ccccccc"
+ 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:url(#linearGradient42332);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 -55,365.75 0,-7.5 -6,-2.25 8.34e-4,13.04035 L -55,365.75 z"
+ id="path41183"
+ sodipodi:nodetypes="ccccc"
+ 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="path41185"
+ d="m -67,365.75 0,-7.5 6,-2.25 8.34e-4,13.04035 L -67,365.75 z"
+ style="fill:#c9c9c9;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ sodipodi:nodetypes="ccccc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m -67,358.25 6,-2.25 6,2.25 -6,2.75 -6,-2.75 z"
+ id="path41187"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path41189"
+ d="M -66.499841,365.52276 -66.5,358.5 l 5.5,-2 5.5,2 0,7 -5.5,3 -5.499841,-2.97724 z"
+ style="fill:none;stroke:url(#linearGradient42334);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ transform="translate(3,417)"
+ id="g41191">
+ <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"
+ width="16"
+ height="16"
+ x="128"
+ y="-29" />
+ <g
+ id="g41195">
+ <path
+ id="path41197"
+ style="fill:#999999;fill-rule:evenodd;stroke:#000000;stroke-width:0.55000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 140,-21 c 1.125,1 3.5,0.25 3.5,-1 0,-1.5 0.47443,-1.637992 -2,-1.5 -0.1033,1.43128 -0.66697,1.819388 -1.5,2.5 z"
+ sodipodi:nodetypes="cscc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cscc"
+ d="m 132,-21 c -1.125,1 -3.5,0.25 -3.5,-1 0,-1.5 -0.47443,-1.637992 2,-1.5 0.1033,1.43128 0.66697,1.819388 1.5,2.5 z"
+ style="fill:#e6e6e6;fill-rule:evenodd;stroke:#000000;stroke-width:0.55000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path41199"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccccsccccccc"
+ d="m 135.75,-25.5 -1.25,-2 -0.75,0 -3.25,2.75 0,1.25 c 0.15379,2.182132 1.3678,1.901463 3,4 l 0,4.5 c 0,1.5 1.5,1.5 2.5,1.5 1,0 2.5,0 2.5,-1.5 l 0,-4.5 c 1.62605,-2.090636 2.83897,-1.844587 3,-4 l 0,-1.25 -3.25,-2.75 -0.75,0 -1.25,2"
+ style="fill:url(#linearGradient42336);fill-rule:evenodd;stroke:none;display:inline;enable-background:new"
+ id="path41201"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="-16"
+ x="135"
+ height="1"
+ width="2"
+ id="rect41203"
+ style="opacity:0.8;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ ry="1"
+ style="fill:url(#linearGradient42338);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect41205"
+ width="2.75"
+ height="2"
+ x="135"
+ y="-21"
+ rx="1" />
+ <rect
+ y="-21"
+ x="135"
+ height="1"
+ width="2"
+ id="rect41207"
+ 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 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="-23"
+ sodipodi:cx="133"
+ id="path41209"
+ style="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"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient42340);stroke-width:0.93034029;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="path41211"
+ sodipodi:cx="133"
+ sodipodi:cy="-23"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 134,-23 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ transform="matrix(1.2143583,0,0,1.1512108,-28.054112,2.9290602)" />
+ <path
+ sodipodi:type="arc"
+ style="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"
+ id="path41213"
+ sodipodi:cx="133"
+ sodipodi:cy="-23"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 134,-23 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 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"
+ id="rect41215"
+ width="2"
+ height="1"
+ x="135"
+ y="-15" />
+ <path
+ id="path41217"
+ style="fill:none;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 131.88556,-21.103144 c 0.4583,0.371362 1.00745,1.072735 1.61444,1.853144 l 0,3.75 c 0,1.5 1.5,2 2.5,2 1,0 2.5,-0.5 2.5,-2 l 0,-3.75 c 0.64842,-0.833678 1.23114,-1.545786 1.70766,-1.936772 M 130.5,-23.5 l 0,-1.25 3,-2.75 1,0 1.25,1.75 0.5,0 1.25,-1.75 1,0 3,2.75 0,1.25"
+ sodipodi:nodetypes="ccccccccccccccccs"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(1.2116904,0,0,1.1282344,-22.693138,2.3776257)"
+ d="m 134,-23 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="-23"
+ sodipodi:cx="133"
+ id="path41219"
+ style="fill:none;stroke:url(#linearGradient42342);stroke-width:0.94079971;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:type="arc" />
+ <path
+ transform="matrix(0.8392157,0,0,0.8382979,26.893134,-4.2140957)"
+ d="m 134,-23 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="-23"
+ sodipodi:cx="133"
+ id="path41221"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path41223"
+ d="M 136.75,-24.75 138,-26.5"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 129.25,-22.25 0.5,-0.5"
+ id="path41225"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path41227"
+ d="m 142.75,-22.5 -0.25,-0.25"
+ style="opacity:0.35;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41229"
+ transform="translate(169,365)">
+ <rect
+ y="23"
+ x="-80"
+ height="16"
+ width="16"
+ id="rect41231"
+ style="opacity:0;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path41233"
+ d="m -72,23.5 -1.5,4 8,0 0,-0.25 -6.5,-3.75 z"
+ style="fill:#ececec;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41235"
+ d="m -73.5,27.5 3,7 5,-7 -8,0 z"
+ style="fill:#c3c3c3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41237"
+ d="m -65.5,27.5 -5,7 5,0 0,-7 z"
+ style="fill:#666666;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41239"
+ d="m -70.5,34.5 -1.5,4 6.5,-3.75 0,-0.25 -5,0"
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41241"
+ d="m -78.5,34.5 0,0.25 6.5,3.75 1.5,-4 -8,0 z"
+ style="fill:#b3b3b3;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41243"
+ d="m -78.5,27.5 0,-0.25 6.5,-3.75 -1.5,4 -5,0 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41245"
+ d="m -73.5,27.5 -5,0 0,7 5,-7 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41247"
+ d="m -78.5,34.5 8,0 -3,-7 -5,7 z"
+ style="fill:#f2f2f2;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:0.76889962;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="path41249"
+ sodipodi:sides="6"
+ sodipodi:cx="-72"
+ sodipodi:cy="31"
+ sodipodi:r1="7.2111025"
+ sodipodi:r2="6.244998"
+ sodipodi:arg1="0.52359878"
+ sodipodi:arg2="1.0471976"
+ inkscape:flatsided="true"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M -65.755002,34.605551 -72,38.211102 l -6.244998,-3.605551 0,-7.211102 L -72,23.788898 l 6.244998,3.605551 z"
+ transform="matrix(1.040833,0,0,1.0400629,2.9399768,-1.241949)" />
+ <path
+ sodipodi:nodetypes="cccccccccccc"
+ id="path41251"
+ style="fill:none;stroke:url(#linearGradient42344);stroke-width:0.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -78.5,27.5 13,0 m -7,-3 -1,3 m -5,7 12.75,0 m -12.75,0 5,-6.75 3,6.75 5,-7 m -5,7 -1,3"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(0.8807051,0,0,0.9013876,-8.5892309,3.0569843)"
+ d="M -65.755002,34.605551 -72,38.211102 l -6.244998,-3.605551 0,-7.211102 L -72,23.788898 l 6.244998,3.605551 z"
+ inkscape:randomized="0"
+ inkscape:rounded="0"
+ inkscape:flatsided="true"
+ sodipodi:arg2="1.0471976"
+ sodipodi:arg1="0.52359878"
+ sodipodi:r2="6.244998"
+ sodipodi:r1="7.2111025"
+ sodipodi:cy="31"
+ sodipodi:cx="-72"
+ sodipodi:sides="6"
+ id="path41253"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient42346);stroke-width:1.12235165;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="star" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41255"
+ transform="translate(231,348)">
+ <rect
+ y="40"
+ x="-121"
+ height="16"
+ width="16"
+ id="rect41257"
+ 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(1.0003553,0,0,0.9995949,-165.01617,-49.953346)"
+ style="display:inline"
+ 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="g41259">
+ <rect
+ y="92.490814"
+ x="46.499645"
+ height="12.004883"
+ width="11.995742"
+ id="rect41261"
+ style="fill:url(#linearGradient42348);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80001998;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" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path41263"
+ d="m 47.49929,95.49203 0,-2.000811 1.999291,3e-6 0,2.000811 -1.999291,-3e-6 z"
+ style="fill:none;stroke:url(#linearGradient42350);stroke-width:1.00002491px;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"
+ 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:url(#linearGradient42352);stroke-width:1.00002491px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 47.49929,99.493651 0,-1.999102 1.999291,-4e-6 0,1.999102 -1.999291,4e-6 z"
+ id="path41265"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path41267"
+ d="m 47.49929,103.49527 0,-1.9991 1.999291,0 0,1.9991 -1.999291,0 z"
+ style="fill:none;stroke:url(#linearGradient42354);stroke-width:1.00002491px;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"
+ 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:url(#linearGradient42356);stroke-width:1.00002491px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 51.497871,103.49527 0,-1.9991 1.99929,0 0,1.9991 -1.99929,0 z"
+ id="path41269"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path41271"
+ d="m 51.497869,99.49194 0,-1.9991 1.99929,0 0,1.9991 -1.99929,0 z"
+ style="fill:none;stroke:url(#linearGradient42358);stroke-width:1.00002491px;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"
+ 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:url(#linearGradient42360);stroke-width:1.00002491px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 51.497868,95.49203 1e-6,-2.000811 1.99929,0 -1e-6,2.000811 -1.99929,0 z"
+ id="path41273"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path41275"
+ d="m 55.496451,103.49527 0,-1.9991 1.99929,0 0,1.9991 -1.99929,0 z"
+ style="fill:none;stroke:url(#linearGradient42362);stroke-width:1.00002491px;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"
+ 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:url(#linearGradient42364);stroke-width:1.00002491px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 55.496449,99.49194 0,-1.9991 1.99929,0 0,1.9991 -1.99929,0 z"
+ id="path41277"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path41279"
+ d="m 55.496448,95.49203 0,-2.000811 1.99929,0 0,2.000811 -1.99929,0 z"
+ style="fill:none;stroke:url(#linearGradient42366);stroke-width:1.00002491px;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path41281"
+ style="fill:none;stroke:url(#linearGradient42368);stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -110.5,43 0,11 m -4,-11 0,11 m 7.5,-3.5 -11,0 m 11,-4 -11,0"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41283"
+ transform="translate(275,332)">
+ <rect
+ y="56"
+ x="-228"
+ height="16"
+ width="16"
+ id="rect41285"
+ 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\Kopia blender\.blender\icons\blender's iconset.png"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path41287"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.23034608;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.8124999,0,0,0.813059,-327.25,-31.946343)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.8;fill:url(#linearGradient42370);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path41289"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.7451143,0.08386971,-0.08492794,0.7396793,-308.33359,-34.308811)" />
+ <path
+ transform="matrix(0.6860851,0,0,0.6874876,-310.55192,-17.123443)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient42372);stroke-width:1.45605874;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path41291"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path41293"
+ style="fill:none;stroke:url(#linearGradient42374);stroke-width:1.78040731;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.5610858,0,0,0.5622541,-294.05201,-2.3458915)" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41295"
+ transform="translate(380,233)">
+ <rect
+ y="155"
+ x="-228"
+ height="16"
+ width="16"
+ id="rect41297"
+ 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" />
+ <path
+ sodipodi:nodetypes="cccsccc"
+ id="path41299"
+ d="m -220,156.5 c -3.036,0 -5.49999,1.12 -5.49999,2.5 l -1e-5,9 c 0,1.38 2.46399,2.5 5.49999,2.5 3.036,0 5.5,-1.12 5.5,-2.5 l 1e-5,-9 c 0,-1.38 -2.464,-2.5 -5.5,-2.5 z"
+ style="fill:url(#linearGradient42376);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient42378);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient42380);stroke-width:1;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 -215.49145,159.5 c 0,1 -1.5,2 -4.50855,2 -3.00854,0 -4.49145,-1 -4.49145,-2 0,-1.5 2.25,-2.25 4.5,-2.25 2.25,0 4.5,0.75 4.5,2.25 z"
+ id="path41301"
+ sodipodi:nodetypes="czszs"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czs"
+ id="path41303"
+ d="m -214.99565,159.99149 c 0,1.12926 -1.66739,2.25851 -5.01168,2.25851 -3.34426,0 -4.99267,-1.12925 -4.99267,-2.25851"
+ style="opacity:0.3;fill:none;stroke:url(#linearGradient42382);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
+ 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;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -220,156.5 c -3.49999,0 -5.49999,1.12 -5.49999,2.5 l -1e-5,8.5 c 0,2 2.46399,3 5.49999,3 3.036,0 5.50001,-1 5.50001,-3 l 0,-8.5 c 0,-1.38 -1.99999,-2.5 -5.5,-2.5 z"
+ id="path41305"
+ sodipodi:nodetypes="cccsccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient42384);stroke-width:0.99999994;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 -224.5,160.5 0,6.5 c 0,0.9838 0.64285,2.5 4.5,2.5 3.85714,0 4.5,-1.5162 4.5,-2.5 l 0,-6.5"
+ id="path41307"
+ sodipodi:nodetypes="ccscc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41309"
+ 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"
+ id="rect41311"
+ width="16"
+ height="16"
+ x="-228"
+ y="176" />
+ <path
+ sodipodi:nodetypes="cssscccscc"
+ id="path41313"
+ d="m -220,178.5 c -4.14,0 -7.40235,2.464 -7.40234,5.5 0,3.036 3.26234,5.5 7.40234,5.5 4.14,0 7.40234,-2.464 7.40234,-5.5 0,-3.036 -3.26233,-5.50001 -7.40234,-5.5 z m 0,4 c 1.2993,0 2.42742,0.39879 3.03125,1 -0.60383,0.60121 -1.73196,1 -3.03125,1 -1.29929,0 -2.42742,-0.39879 -3.03125,-1 0.60383,-0.60121 1.73196,-1 3.03125,-1 z"
+ style="fill:url(#linearGradient42386);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;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccsscc"
+ id="path41315"
+ d="m -214.625,180.4375 c 1.5822,4.85564 -3.15377,7.27675 -11.84375,6.21875 l 0,0.0312 c 1.25689,1.67541 3.66207,2.8125 6.46875,2.8125 4.14,0 7.40625,-2.464 7.40625,-5.5 0,-1.34213 -0.64966,-2.57614 -1.71875,-3.53125 -0.10326,-0.0119 -0.20204,-0.024 -0.3125,-0.0312 z"
+ style="opacity:0.6;fill:url(#radialGradient42388);fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.6;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"
+ d="m -223.375,183.45313 c 1.90631,-1.46639 4.08905,-1.44306 6.1875,-0.53125 L -217,182.76563 c -0.60315,-4.39553 -10.23988,-3.57787 -6.375,0.6875 z"
+ id="path41317"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccsccc"
+ id="path41319"
+ d="m -223.375,183.65625 0.5,-0.0312 c -0.0509,-0.0426 -0.11109,-0.08 -0.15625,-0.125 0.60383,-0.60121 1.73196,-1 3.03125,-1 0.99575,0 1.89552,0.24495 2.53125,0.625 L -217,182.96875 c -0.60315,-4.39553 -10.23988,-3.57787 -6.375,0.6875 z"
+ style="opacity:0.6;fill:url(#radialGradient42390);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" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient42392);stroke-width:0.5962854;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="path41321"
+ sodipodi:cx="-220"
+ sodipodi:cy="40.5"
+ sodipodi:rx="6.5"
+ sodipodi:ry="2.5"
+ d="m -213.5,40.5 a 6.5,2.5 0 1 1 -13,0 6.5,2.5 0 1 1 13,0 z"
+ transform="matrix(0.9999986,0,0,1.799999,-2.971883e-4,111.10004)" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41323"
+ transform="translate(422,192)">
+ <rect
+ y="196"
+ x="-228"
+ height="16"
+ width="16"
+ id="rect41325"
+ 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" />
+ <path
+ sodipodi:nodetypes="ccssscc"
+ id="path41327"
+ d="m -220,196.70312 -6.24219,10.18714 c -0.17094,0.32797 -0.25781,0.44407 -0.25781,0.85974 0,2.25 2.96003,3.75 6.5,3.75 3.53998,0 6.5,-1.5 6.5,-3.75 0,-0.41567 -0.0869,-0.53177 -0.2578,-0.85974 L -220,196.70312 z"
+ style="fill:url(#radialGradient42394);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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient42396);stroke-width:1;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,198.75 -5.29067,8.34531 c -0.1388,0.26737 -0.20933,0.56583 -0.20933,0.90469 0,1.3338 2.63213,2.56728 5.50644,2.56728 2.87432,0 5.49356,-1.23348 5.49356,-2.56728 0,-0.33886 -0.0706,-0.63732 -0.20932,-0.90469 L -220,198.75 z"
+ id="path41329"
+ sodipodi:nodetypes="ccssscc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.05;fill:none;stroke:#1a1a1a;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 -226.5,208 c 0,-1.63609 2.96003,-3.5 6.5,-3.5 3.53998,0 6.5,1.75 6.5,3.5"
+ id="path41331"
+ sodipodi:nodetypes="css"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41333"
+ 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"
+ id="rect41335"
+ width="16"
+ height="16"
+ x="-278"
+ y="137" />
+ <g
+ transform="translate(-22,0)"
+ id="g41337">
+ <path
+ style="fill:#aaccff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;display:inline;enable-background:new"
+ d="m -243.5,137.5 c 1.00003,1e-5 2.00005,1e-5 3.00008,2e-5 0,0.99999 0,1.99999 0,2.99998 -1.00003,0 -2.00005,-1e-5 -3.00008,-1e-5 0,-1 0,-1.99999 0,-2.99999 z"
+ id="path41339"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41341"
+ d="m -255.5,137.5 c 1.00003,1e-5 2.00005,1e-5 3.00008,2e-5 0,0.99999 0,1.99998 0,2.99998 -1.00003,-1e-5 -2.00005,-1e-5 -3.00008,-2e-5 0,-0.99999 0,-1.99999 0,-2.99998 z"
+ style="fill:#aaccff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g41343"
+ style="opacity:0.7">
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:#aaccff;fill-opacity:0.75;fill-rule:evenodd;stroke:#003380;stroke-width:2.79999995;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 -252.25,139.5 8.5,0"
+ id="path41345"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41347"
+ d="m -252,139.5 8,0"
+ style="fill:#aaccff;fill-opacity:1;fill-rule:evenodd;stroke:#aaccff;stroke-width:1.5;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="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m -254.5,139.5 0,-1 1,0"
+ id="path41349"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41351"
+ d="m -242.5,139.5 0,-1 1,0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g41353"
+ transform="translate(-327,-164)">
+ <rect
+ rx="1.4999387"
+ ry="1.4999387"
+ y="312.5"
+ x="52.5"
+ height="3"
+ width="2.9998772"
+ id="rect41355"
+ style="fill:#1a1a1a;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:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:3.0999999;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 54,314.25 c 3.75,1.75 8.5,2.36379 8.5,-2 0,-3 -3.5,-6.25 -5.5,-8.25"
+ id="path41357"
+ sodipodi:nodetypes="csc"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#cccccc;stroke-width:1.5;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 54,314.25 c 3.5,1.75 8.5,2.36741 8.5,-2 0,-3 -3.5,-6.25 -5.5,-8.25"
+ id="path41359"
+ sodipodi:nodetypes="csc"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#1a1a1a;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:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect41361"
+ width="2.9998772"
+ height="3"
+ x="55.500122"
+ y="302.5"
+ ry="1.4999387"
+ rx="1.4999387" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="csc"
+ id="path41363"
+ d="m 54,314.25 c 3.5,1.75 8.5,2.33285 8.5,-2 0,-3 -3.5,-6.25 -5.5,-8.25"
+ style="fill:none;stroke:url(#linearGradient42398);stroke-width:1.5;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
+ 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="path41365"
+ d="m 55,313 c -0.67541,0 -1.35081,10e-6 -2.02623,10e-6 0,0.66666 0,1.33332 0,1.99999 0.67542,0 1.35082,-10e-6 2.02623,-10e-6 0,-0.66666 0,-1.33333 0,-1.99999 z"
+ style="fill:#e6e6e6;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="fill:#ececec;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 58,303 c -0.666663,0 -1.333327,10e-6 -2,10e-6 0,0.66667 0,1.33332 0,1.99999 0.666673,0 1.333337,-10e-6 2,-10e-6 0,-0.66666 0,-1.33332 0,-1.99999 z"
+ id="path41367"
+ 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.8;fill:#ececec;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 56.499999,304.5 0,-1 1,0"
+ id="path41369"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41371"
+ d="m 53.5,314.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
+ 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="path41373"
+ d="m 56,315.66293 c -0.32001,0 -0.64002,-1e-5 -0.96003,-1e-5 0,-0.55431 0,-1.1086 0,-1.66292 0.32001,0 0.64002,10e-6 0.96003,10e-6 0,0.55431 0,1.10861 0,1.66292 z"
+ style="opacity:0.15;fill:#4b4b4b;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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="path41375"
+ d="m 59,306 c -0.333333,0 -0.666667,-10e-6 -1,-10e-6 0,-0.66666 0,-1.33331 0,-1.99999 0.333333,0 0.666667,10e-6 1,10e-6 0,0.66667 0,1.33333 0,1.99999 z"
+ style="opacity:0.15;fill:#4b4b4b;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.15;fill:#1d1d1d;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 56,316 c -0.32001,0 -0.64002,0 -0.96003,0 0,-0.21055 0,-0.42107 0,-0.63162 0.32001,0 0.64002,0 0.96003,0 0,0.21055 0,0.42107 0,0.63162 z"
+ id="path41377"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-21.421813,3.140625)"
+ id="g41379"
+ style="display:inline;enable-background:new" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41381"
+ transform="matrix(0,1,1,0,99,651)">
+ <rect
+ y="137"
+ x="-284"
+ height="16"
+ width="16"
+ id="rect41383"
+ style="opacity:0.01000001;fill:#ff0000;fill-opacity:0.75;fill-rule:evenodd;stroke:none;stroke-width:3.0999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ rx="1.4999387"
+ ry="1.4999353"
+ y="149.5"
+ x="-271.5"
+ height="2.9999931"
+ width="2.9998772"
+ id="rect41385"
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:0.99999994;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
+ id="g41387">
+ <path
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ d="m -271.50008,137.5 c 1.00003,1e-5 2.00005,1e-5 3.00008,2e-5 0,0.99999 0,1.99999 0,2.99998 -1.00003,0 -2.00005,-1e-5 -3.00008,-1e-5 0,-1 0,-1.99999 0,-2.99999 z"
+ id="path41389"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41391"
+ d="m -283.50008,137.5 c 1.00003,1e-5 2.00005,1e-5 3.00008,2e-5 0,0.99999 0,1.99998 0,2.99998 -1.00003,-1e-5 -2.00005,-1e-5 -3.00008,-2e-5 0,-0.99999 0,-1.99999 0,-2.99998 z"
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ 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;display:inline;enable-background:new"
+ d="m -282.50008,139.5 0,-1 1,0"
+ id="path41393"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41395"
+ d="m -270.50008,139.5 0,-1 1,0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g41397"
+ style="opacity:0.7">
+ <path
+ id="path41399"
+ d="m -270.5,140.74992 0,8.5"
+ style="fill:#aaccff;fill-opacity:0.75;fill-rule:evenodd;stroke:#003380;stroke-width:2.79999995;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"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:#aaccff;fill-opacity:0.75;fill-rule:evenodd;stroke:#003380;stroke-width:2.79999995;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 -280.25008,139.5 8.5,0"
+ id="path41401"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:#aaccff;fill-opacity:0.75;fill-rule:evenodd;stroke:#003380;stroke-width:2.79999995;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 -281.49999,140.75 0,8.5"
+ id="path41403"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41405"
+ d="m -280.00008,139.5 8,0"
+ style="fill:#aaccff;fill-opacity:1;fill-rule:evenodd;stroke:#aaccff;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"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:#aaccff;fill-opacity:1;fill-rule:evenodd;stroke:#aaccff;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 -270.5,140.99992 0,8"
+ id="path41407"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41409"
+ d="m -281.49999,141 0,8"
+ style="fill:#aaccff;fill-opacity:1;fill-rule:evenodd;stroke:#aaccff;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"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <rect
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:0.99999994;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="rect41411"
+ width="2.9998772"
+ height="2.999995"
+ x="-283.5"
+ y="149.5"
+ ry="1.4999362"
+ rx="1.4999387" />
+ <g
+ id="g41413">
+ <path
+ sodipodi:nodetypes="csc"
+ id="path41415"
+ d="m -270.5,150.5 c 0,-4.0296 -2.4502,-6 -5.5,-6 -3.0498,0 -5.5,1.9704 -5.5,6"
+ 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:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#cccccc;stroke-width:1.5;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 -270.5,150.5 c 0,-4.0296 -2.4502,-6 -5.5,-6 -3.0498,0 -5.5,1.9704 -5.5,6"
+ id="path41417"
+ sodipodi:nodetypes="csc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="csc"
+ id="path41419"
+ d="m 36.445698,40.205481 c 0,3.312 -2.660849,4.931507 -5.972849,4.931507 -3.312,0 -5.97285,-1.619507 -5.97285,-4.931507"
+ style="fill:none;stroke:url(#linearGradient42400);stroke-width:1.41714692;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.9208335,0,0,-1.2166667,-304.06042,199.41667)"
+ inkscape:connector-curvature="0" />
+ </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"
+ id="path41421"
+ d="m -269,150 c -0.66667,0 -1.33333,1e-5 -2,1e-5 0,0.66667 0,1.33332 0,1.99999 0.66667,0 1.33333,-1e-5 2,-1e-5 0,-0.66666 0,-1.33332 0,-1.99999 z"
+ style="fill:#cccccc;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="fill:#ffffff;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 -281,150 c -0.66667,0 -1.33333,1e-5 -2,1e-5 0,0.66667 0,1.33332 0,1.99999 0.66667,0 1.33333,-1e-5 2,-1e-5 0,-0.66666 0,-1.33332 0,-1.99999 z"
+ id="path41423"
+ 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.8;fill:#ececec;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m -270.5,151.5 0,-1 1,0"
+ id="path41425"
+ inkscape:connector-curvature="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="149"
+ x="-283"
+ height="1"
+ width="2.75"
+ id="rect41427"
+ style="opacity:0.2;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" />
+ <rect
+ style="opacity:0.2;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"
+ id="rect41429"
+ width="2.75"
+ height="1"
+ x="-271.75"
+ y="149"
+ rx="0"
+ ry="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41431"
+ transform="translate(565.49991,277.875)">
+ <g
+ transform="translate(-23.5,-18.875)"
+ id="g41433"
+ style="opacity:0.8">
+ <rect
+ style="opacity:0.01000001;fill:#ff0000;fill-opacity:0.75;fill-rule:evenodd;stroke:none;stroke-width:3.0999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect41435"
+ width="16"
+ height="16"
+ x="-284.99991"
+ y="108" />
+ <path
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ d="m -272.5,108.5 c 1.00003,1e-5 2.00005,1e-5 3.00008,2e-5 0,0.99999 0,1.99999 0,2.99998 -1.00003,0 -2.00005,-1e-5 -3.00008,-1e-5 0,-1 0,-1.99999 0,-2.99999 z"
+ id="path41437"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41439"
+ d="m -284.5,108.5 c 1.00003,1e-5 2.00005,1e-5 3.00008,2e-5 0,0.99999 0,1.99998 0,2.99998 -1.00003,-1e-5 -2.00005,-1e-5 -3.00008,-2e-5 0,-0.99999 0,-1.99999 0,-2.99998 z"
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ 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;display:inline;enable-background:new"
+ d="m -283.5,110.5 0,-1 1,0"
+ id="path41441"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41443"
+ d="m -271.5,110.5 0,-1 1,0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41445"
+ d="m -272.49992,123.5 c 1.00003,-1e-5 2.00005,-1e-5 3.00008,-2e-5 0,-0.99999 0,-1.99999 0,-2.99998 -1.00003,0 -2.00005,1e-5 -3.00008,1e-5 0,1 0,1.99999 0,2.99999 z"
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ d="m -284.49992,123.5 c 1.00003,-1e-5 2.00005,-1e-5 3.00008,-2e-5 0,-0.99999 0,-1.99998 0,-2.99998 -1.00003,1e-5 -2.00005,1e-5 -3.00008,2e-5 0,0.99999 0,1.99999 0,2.99998 z"
+ id="path41447"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41449"
+ d="m -283.49992,122.5 0,-1 1,0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ 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;display:inline;enable-background:new"
+ d="m -271.49992,122.5 0,-1 1,0"
+ id="path41451"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(1.0019678,0,0,1,-97.100449,33.125005)"
+ id="g41453">
+ <path
+ transform="matrix(0.6860851,0,0,0.6874876,-293.56324,-17.123443)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:#000000;stroke-width:4.36388111;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path41455"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path41457"
+ style="fill:none;stroke:url(#linearGradient42402);stroke-width:2.18194032;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.6860851,0,0,0.6874876,-293.56324,-17.123443)" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41459"
+ transform="translate(311,278)">
+ <g
+ transform="translate(0,-19)"
+ id="g41461"
+ style="opacity:0.8">
+ <rect
+ y="108"
+ x="-284.99991"
+ height="16"
+ width="16"
+ id="rect41463"
+ style="opacity:0.01000001;fill:#ff0000;fill-opacity:0.75;fill-rule:evenodd;stroke:none;stroke-width:3.0999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ id="path41465"
+ d="m -272.5,108.5 c 1.00003,1e-5 2.00005,1e-5 3.00008,2e-5 0,0.99999 0,1.99999 0,2.99998 -1.00003,0 -2.00005,-1e-5 -3.00008,-1e-5 0,-1 0,-1.99999 0,-2.99999 z"
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ d="m -284.5,108.5 c 1.00003,1e-5 2.00005,1e-5 3.00008,2e-5 0,0.99999 0,1.99998 0,2.99998 -1.00003,-1e-5 -2.00005,-1e-5 -3.00008,-2e-5 0,-0.99999 0,-1.99999 0,-2.99998 z"
+ id="path41467"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41469"
+ d="m -283.5,110.5 0,-1 1,0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ 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;display:inline;enable-background:new"
+ d="m -271.5,110.5 0,-1 1,0"
+ id="path41471"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ d="m -272.49992,123.5 c 1.00003,-1e-5 2.00005,-1e-5 3.00008,-2e-5 0,-0.99999 0,-1.99999 0,-2.99998 -1.00003,0 -2.00005,1e-5 -3.00008,1e-5 0,1 0,1.99999 0,2.99999 z"
+ id="path41473"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41475"
+ d="m -284.49992,123.5 c 1.00003,-1e-5 2.00005,-1e-5 3.00008,-2e-5 0,-0.99999 0,-1.99998 0,-2.99998 -1.00003,1e-5 -2.00005,1e-5 -3.00008,2e-5 0,0.99999 0,1.99999 0,2.99998 z"
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ 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;display:inline;enable-background:new"
+ d="m -283.49992,122.5 0,-1 1,0"
+ id="path41477"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41479"
+ d="m -271.49992,122.5 0,-1 1,0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-57,33)"
+ id="g41481">
+ <rect
+ y="56"
+ x="-228"
+ height="16"
+ width="16"
+ id="rect41483"
+ 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\Kopia blender\.blender\icons\blender's iconset.png"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path41485"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.23039246;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.8124999,0,0,0.8129977,-327.25,-31.938622)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.8;fill:url(#linearGradient42404);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path41487"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.7451143,0.08386971,-0.08492794,0.7396793,-308.33359,-34.308811)" />
+ <path
+ transform="matrix(0.6860851,0,0,0.6874876,-310.55192,-17.123443)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient42406);stroke-width:1.45605874;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path41489"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path41491"
+ style="fill:none;stroke:url(#linearGradient42408);stroke-width:1.78040731;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.5610858,0,0,0.5622541,-294.05201,-2.3458915)" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41493"
+ transform="translate(455,122.97748)">
+ <rect
+ y="244.02252"
+ x="-240.00009"
+ height="16"
+ width="16"
+ id="rect41495"
+ 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" />
+ <g
+ id="g41497"
+ transform="translate(15.99992,107.02252)">
+ <path
+ id="path41499"
+ d="m -243.5,137.5 c 1.00003,1e-5 2.00005,1e-5 3.00008,2e-5 0,0.99999 0,1.99999 0,2.99998 -1.00003,0 -2.00005,-1e-5 -3.00008,-1e-5 0,-1 0,-1.99999 0,-2.99999 z"
+ style="fill:#aaccff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#aaccff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000265;display:inline;enable-background:new"
+ d="m -255.5,137.5 c 1.00003,1e-5 2.00005,1e-5 3.00008,2e-5 0,0.99999 0,1.99998 0,2.99998 -1.00003,-1e-5 -2.00005,-1e-5 -3.00008,-2e-5 0,-0.99999 0,-1.99999 0,-2.99998 z"
+ id="path41501"
+ inkscape:connector-curvature="0" />
+ <g
+ style="opacity:0.5"
+ id="g41503">
+ <path
+ id="path41505"
+ d="m -252.25,138.49219 8.5,0"
+ style="fill:#aaccff;fill-opacity:0.75;fill-rule:evenodd;stroke:#003380;stroke-width:2.79999995;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"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:#aaccff;fill-opacity:1;fill-rule:evenodd;stroke:#aaccff;stroke-width:1.5;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 -252,138.49219 8,0"
+ id="path41507"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path41509"
+ d="m -254.5,139.5 0,-1 1,0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ 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;display:inline;enable-background:new"
+ d="m -242.5,139.5 0,-1 1,0"
+ id="path41511"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ style="fill:#1a1a1a;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:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect41513"
+ width="2.9998772"
+ height="3"
+ x="-233.49988"
+ y="245.52252"
+ ry="1.4999387"
+ rx="1.4999387" />
+ <g
+ id="g41515"
+ transform="translate(68.499908,155.89752)">
+ <g
+ transform="matrix(1.0019678,0,0,1,-97.100449,33.125005)"
+ id="g41517">
+ <path
+ transform="matrix(0.6860851,0,0,0.6874876,-293.56324,-17.123443)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:#000000;stroke-width:4.36388111;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path41519"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path41521"
+ style="fill:none;stroke:url(#linearGradient42410);stroke-width:2.18194032;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.6860851,0,0,0.6874876,-293.56324,-17.123443)" />
+ </g>
+ </g>
+ <rect
+ rx="1.4999387"
+ ry="1.4999387"
+ y="245.52252"
+ x="-233.49988"
+ height="3"
+ width="2.9998772"
+ id="rect41523"
+ style="opacity:0.25;fill:#1a1a1a;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:7.40000265;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"
+ id="path41525"
+ d="m -230.99988,246.02251 c -0.66667,0 -1.33333,10e-6 -2,10e-6 0,0.66667 0,1.33332 0,1.99999 0.66667,0 1.33333,-1e-5 2,-1e-5 0,-0.66666 0,-1.33332 0,-1.99999 z"
+ style="fill:#ffffff;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" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41527"
+ transform="translate(70.968338,302.76882)">
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ style="opacity:0.01000001;fill:#ff0000;fill-opacity:0.75;fill-rule:evenodd;stroke:none;stroke-width:3.0999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect41529"
+ width="16"
+ height="16"
+ x="64.231171"
+ y="-65.968338" />
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.99999994;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="rect41531"
+ width="2.9998772"
+ height="2.9999931"
+ x="76.731178"
+ y="-53.468342"
+ ry="1.4999353"
+ rx="1.4999387" />
+ <g
+ transform="matrix(0,1,1,0,-202.96833,348.23118)"
+ id="g41533"
+ style="display:inline;enable-background:new">
+ <path
+ id="path41535"
+ d="m -271.50008,137.5 c 1.00003,1e-5 2.00005,1e-5 3.00008,2e-5 0,0.99999 0,1.99999 0,2.99998 -1.00003,0 -2.00005,-1e-5 -3.00008,-1e-5 0,-1 0,-1.99999 0,-2.99999 z"
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ d="m -283.50008,137.5 c 1.00003,1e-5 2.00005,1e-5 3.00008,2e-5 0,0.99999 0,1.99998 0,2.99998 -1.00003,-1e-5 -2.00005,-1e-5 -3.00008,-2e-5 0,-0.99999 0,-1.99999 0,-2.99998 z"
+ id="path41537"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41539"
+ d="m -282.50008,139.5 0,-1 1,0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ 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;display:inline;enable-background:new"
+ d="m -270.50008,139.5 0,-1 1,0"
+ id="path41541"
+ inkscape:connector-curvature="0" />
+ <g
+ style="opacity:0.7"
+ id="g41543">
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:#aaccff;fill-opacity:0.75;fill-rule:evenodd;stroke:#003380;stroke-width:2.79999995;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 -270.5,140.74992 0,8.5"
+ id="path41545"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41547"
+ d="m -280.25008,139.5 8.5,0"
+ style="fill:#aaccff;fill-opacity:0.75;fill-rule:evenodd;stroke:#003380;stroke-width:2.79999995;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"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41549"
+ d="m -281.49999,140.75 0,8.5"
+ style="fill:#aaccff;fill-opacity:0.75;fill-rule:evenodd;stroke:#003380;stroke-width:2.79999995;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"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:#aaccff;fill-opacity:1;fill-rule:evenodd;stroke:#aaccff;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 -280.00008,139.5 8,0"
+ id="path41551"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41553"
+ d="m -270.5,140.99992 0,8"
+ style="fill:#aaccff;fill-opacity:1;fill-rule:evenodd;stroke:#aaccff;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"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:#aaccff;fill-opacity:1;fill-rule:evenodd;stroke:#aaccff;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 -281.49999,141 0,8"
+ id="path41555"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ rx="1.4999387"
+ ry="1.4999362"
+ y="-53.468342"
+ x="64.731171"
+ height="2.999995"
+ width="2.9998772"
+ id="rect41557"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.99999994;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
+ transform="matrix(0,1,1,0,-202.96833,348.23118)"
+ id="g41559"
+ style="display:inline;enable-background:new">
+ <path
+ 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:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -270.5,150.5 c 0,-4.0296 -2.4502,-6 -5.5,-6 -3.0498,0 -5.5,1.9704 -5.5,6"
+ id="path41561"
+ sodipodi:nodetypes="csc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="csc"
+ id="path41563"
+ d="m -270.5,150.5 c 0,-4.0296 -2.4502,-6 -5.5,-6 -3.0498,0 -5.5,1.9704 -5.5,6"
+ style="fill:none;stroke:#cccccc;stroke-width:1.5;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
+ transform="matrix(0.9208335,0,0,-1.2166667,-304.06042,199.41667)"
+ style="fill:none;stroke:url(#linearGradient42412);stroke-width:1.41714692;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 36.445698,40.205481 c 0,3.312 -2.660849,4.931507 -5.972849,4.931507 -3.312,0 -5.97285,-1.619507 -5.97285,-4.931507"
+ id="path41565"
+ sodipodi:nodetypes="csc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="opacity:0.6;display:inline;enable-background:new"
+ transform="translate(132.03151,-159.76882)"
+ id="g41567">
+ <path
+ transform="matrix(0.8124999,0,0,0.8131203,-292.24999,136.05677)"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.98423982;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 133.84616,110 0,15.98779 L 132,126 c -4.416,0 -8,-3.584 -8,-8 0,-4.416 3.584,-8 8,-8 l 1.84616,0 z"
+ id="path41569"
+ sodipodi:nodetypes="cccscc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="csscccc"
+ id="path41571"
+ d="M 132.92501,125.94702 C 132.6215,125.98201 132.31284,126 132,126 c -4.416,0 -8,-3.584 -8,-8 0,-4.11109 3.10616,-7.5011 7.09807,-7.94965 l 1.32084,-0.14976 1.81209,15.89838 -1.30599,0.14805 0,0 0,0 0,0 z"
+ style="opacity:0.8;fill:url(#linearGradient42414);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ transform="matrix(0.7451143,0.08449152,-0.08492794,0.7451633,-273.33359,132.91784)"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccscc"
+ id="path41573"
+ d="m 132.71228,109.99971 0,16.00029 L 132,126 c -4.416,0 -8,-3.584 -8,-8 0,-4.416 3.584,-8 8,-8 l 0.71228,-2.9e-4 z"
+ style="fill:none;stroke:url(#linearGradient42416);stroke-width:1.45605874;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0"
+ transform="matrix(0.6860851,0,0,0.6874876,-275.55192,150.87656)"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="css"
+ id="path41575"
+ d="m 132,126 c -4.416,0 -8,-3.584 -8,-8 0,-4.416 3.584,-8 8,-8"
+ style="fill:none;stroke:url(#linearGradient42418);stroke-width:1.78040731;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0"
+ transform="matrix(0.5610858,0,0,0.5622541,-259.05201,165.65411)"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="fill:#cccccc;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 -52.968334,79.231175 c 0,-0.66667 10e-6,-1.33333 10e-6,-2 0.66667,0 1.33332,0 1.99999,0 0,0.66667 -1e-5,1.33333 -1e-5,2 -0.66666,0 -1.33332,0 -1.99999,0 z"
+ id="path41577"
+ 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="path41579"
+ d="m -52.968334,67.231175 c 0,-0.66667 10e-6,-1.33333 10e-6,-2 0.66667,0 1.33332,0 1.99999,0 0,0.66667 -1e-5,1.33333 -1e-5,2 -0.66666,0 -1.33332,0 -1.99999,0 z"
+ style="fill:#ffffff;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
+ id="path41581"
+ d="m -51.468334,77.731175 -1,0 0,1"
+ style="opacity:0.8;fill:#ececec;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ style="opacity:0.2;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"
+ id="rect41583"
+ width="2.75"
+ height="1"
+ x="65.231171"
+ y="-53.968342"
+ rx="0"
+ ry="0" />
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ ry="0"
+ rx="0"
+ y="-53.968342"
+ x="76.481178"
+ height="1"
+ width="2.75"
+ id="rect41585"
+ style="opacity:0.2;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
+ style="display:inline;enable-background:new"
+ id="g41587"
+ 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"
+ id="rect41589"
+ width="16"
+ height="16"
+ x="-307"
+ y="136" />
+ <g
+ id="g41591"
+ transform="translate(-22.000001,28)"
+ style="opacity:0.8;display:inline;enable-background:new">
+ <rect
+ y="108"
+ x="-284.99991"
+ height="16"
+ width="16"
+ id="rect41593"
+ style="opacity:0.01000001;fill:#ff0000;fill-opacity:0.75;fill-rule:evenodd;stroke:none;stroke-width:3.0999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ id="path41595"
+ d="m -272.5,108.5 c 1.00003,1e-5 2.00005,1e-5 3.00008,2e-5 0,0.99999 0,1.99999 0,2.99998 -1.00003,0 -2.00005,-1e-5 -3.00008,-1e-5 0,-1 0,-1.99999 0,-2.99999 z"
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ d="m -284.5,108.5 c 1.00003,1e-5 2.00005,1e-5 3.00008,2e-5 0,0.99999 0,1.99998 0,2.99998 -1.00003,-1e-5 -2.00005,-1e-5 -3.00008,-2e-5 0,-0.99999 0,-1.99999 0,-2.99998 z"
+ id="path41597"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41599"
+ d="m -283.5,110.5 0,-1 1,0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ 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;display:inline;enable-background:new"
+ d="m -271.5,110.5 0,-1 1,0"
+ id="path41601"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ d="m -272.49992,123.5 c 1.00003,-1e-5 2.00005,-1e-5 3.00008,-2e-5 0,-0.99999 0,-1.99999 0,-2.99998 -1.00003,0 -2.00005,1e-5 -3.00008,1e-5 0,1 0,1.99999 0,2.99999 z"
+ id="path41603"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41605"
+ d="m -284.49992,123.5 c 1.00003,-1e-5 2.00005,-1e-5 3.00008,-2e-5 0,-0.99999 0,-1.99998 0,-2.99998 -1.00003,1e-5 -2.00005,1e-5 -3.00008,2e-5 0,0.99999 0,1.99999 0,2.99998 z"
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ 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;display:inline;enable-background:new"
+ d="m -283.49992,122.5 0,-1 1,0"
+ id="path41607"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41609"
+ d="m -271.49992,122.5 0,-1 1,0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g41611">
+ <path
+ sodipodi:nodetypes="cccsccc"
+ id="path41613"
+ d="m -299,137.5 c -3.036,0 -5.49999,1.12 -5.49999,2.5 l -10e-6,8 c 0,1.38 2.46399,2.5 5.49999,2.5 3.036,0 5.5,-1.12 5.5,-2.5 l 10e-6,-8 c 0,-1.38 -2.464,-2.5 -5.5,-2.5 z"
+ style="fill:url(#linearGradient42420);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient42422);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient42424);stroke-width:1;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 -294.49145,140.5 c 0,1 -1.5,2 -4.50855,2 -3.00854,0 -4.49145,-1 -4.49145,-2 0,-1.5 2.25,-2.25 4.5,-2.25 2.25,0 4.5,0.75 4.5,2.25 z"
+ id="path41615"
+ sodipodi:nodetypes="czszs"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czs"
+ id="path41617"
+ d="m -293.99565,140.99149 c 0,1.12926 -1.66739,2.25851 -5.01168,2.25851 -3.34426,0 -4.99267,-1.12925 -4.99267,-2.25851"
+ style="opacity:0.3;fill:none;stroke:url(#linearGradient42426);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
+ 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;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -299,137.5 c -3.49999,0 -5.49999,1.12 -5.49999,2.5 l -10e-6,7.5 c 0,2 2.46399,3 5.49999,3 3.036,0 5.50001,-1 5.50001,-3 l 0,-7.5 c 0,-1.38 -1.99999,-2.5 -5.5,-2.5 z"
+ id="path41619"
+ sodipodi:nodetypes="cccsccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient42428);stroke-width:0.99999994;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 -303.5,141.5 0,5.5 c 0,0.9838 0.64285,2.5 4.5,2.5 3.85714,0 4.5,-1.5162 4.5,-2.5 l 0,-5.5"
+ id="path41621"
+ sodipodi:nodetypes="ccscc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41623"
+ transform="translate(258.99995,102)">
+ <rect
+ transform="scale(-1,1)"
+ style="opacity:0.01000001;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"
+ id="rect41625"
+ width="16.000032"
+ height="16"
+ x="195.99995"
+ y="265" />
+ <g
+ transform="translate(77.000139,146.99992)"
+ id="g41627">
+ <path
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ d="m -287.5,118.5 c 10e-6,1.00003 10e-6,2.00005 2e-5,3.00008 0.99999,0 1.99998,0 2.99998,0 -10e-6,-1.00003 -10e-6,-2.00005 -2e-5,-3.00008 -0.99999,0 -1.99999,0 -2.99998,0 z"
+ id="path41629"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41631"
+ d="m -285.5,119.5 -1,0 0,1"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <g
+ style="opacity:0.5"
+ id="g41633"
+ transform="matrix(0,1,1,0,-425,402.00008)">
+ <path
+ id="path41635"
+ d="m -279.50016,139.5 6.00016,2e-5"
+ style="fill:#aaccff;fill-opacity:0.75;fill-rule:evenodd;stroke:#003380;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"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41637"
+ d="m -281.50008,141.5 0,2"
+ style="fill:#aaccff;fill-opacity:0.75;fill-rule:evenodd;stroke:#003380;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"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:#aaccff;fill-opacity:1;fill-rule:evenodd;stroke:#aaccff;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 -280.00008,139.5 6.50008,2e-5"
+ id="path41639"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:#aaccff;fill-opacity:1;fill-rule:evenodd;stroke:#aaccff;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 -281.49999,141 -9e-5,2.5"
+ id="path41641"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g41643"
+ transform="matrix(-1,0,0,-1,-484.99984,399)">
+ <path
+ id="path41645"
+ d="m -287.5,118.5 c 10e-6,1.00003 10e-6,2.00005 2e-5,3.00008 0.99999,0 1.99998,0 2.99998,0 -10e-6,-1.00003 -10e-6,-2.00005 -2e-5,-3.00008 -0.99999,0 -1.99999,0 -2.99998,0 z"
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ 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;display:inline;enable-background:new"
+ d="m -285.5,119.5 -1,0 0,1"
+ id="path41647"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(0,1,1,0,-425,402.00008)"
+ id="g41649"
+ style="opacity:0.5">
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:#aaccff;fill-opacity:0.75;fill-rule:evenodd;stroke:#003380;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 -279.50016,139.5 7,0"
+ id="path41652"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:#aaccff;fill-opacity:0.75;fill-rule:evenodd;stroke:#003380;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 -281.50008,141.5 0,2"
+ id="path41654"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41656"
+ d="m -280.00008,139.5 7.49992,0"
+ style="fill:#aaccff;fill-opacity:1;fill-rule:evenodd;stroke:#aaccff;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"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41658"
+ d="m -281.49999,141 -9e-5,2.5"
+ style="fill:#aaccff;fill-opacity:1;fill-rule:evenodd;stroke:#aaccff;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"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(-191.99984,-17.000001)"
+ id="g41660"
+ style="display:inline;enable-background:new">
+ <g
+ id="g41662"
+ transform="translate(-376,510)">
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ id="path41664"
+ d="m 358.99997,-216.75 c -0.99997,-6.5 6.00003,-2.75 5,-9.25 L 369,-224 c 1,7 -6,2 -5,10 l -5.00003,-2.75 z"
+ style="fill:none;stroke:#000000;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"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:#cdcdcd;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 358.99997,-216.75 C 358,-223.25 365,-220 363.99997,-226 L 369,-224 c 1,7 -6,2 -5,10 l -5.00003,-2.75 z"
+ id="path41666"
+ 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"
+ style="opacity:0.7;fill:url(#linearGradient42430);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.88812488px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M 358.99997,-216.75 C 358,-223.25 365,-220 363.99997,-226 L 369,-224 c 1,7 -6,2 -5,10 l -5.00003,-2.75 z"
+ id="path41668"
+ 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"
+ id="path41670"
+ d="M 358.99997,-216.75 C 358,-223.25 365,-220 363.99997,-226 L 369,-224 c 1,7 -6,2 -5,10 l -5.00003,-2.75 z"
+ style="opacity:0.85;fill:url(#radialGradient42432);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.88812488px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccc"
+ 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="path41672"
+ d="m 364.24984,-225.5 4.25016,1.75 c 1,5.75 -5.50003,2 -5.08381,8.85761 l -4.04561,-2.26888"
+ style="opacity:0.75;fill:none;stroke:url(#linearGradient42434);stroke-width:1;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"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;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 364.24997,-225.5 4.25003,1.75"
+ id="path41674"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-399.2499,383.75)"
+ id="g41676" />
+ <g
+ id="g41678"
+ transform="translate(-406.2499,380.75)" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41680"
+ transform="translate(338.00016,191)">
+ <g
+ id="g41682"
+ transform="translate(56.999841,68)"
+ style="opacity:0.8;display:inline;enable-background:new">
+ <rect
+ y="108"
+ x="-284.99991"
+ height="16"
+ width="16"
+ id="rect41684"
+ style="opacity:0.01000001;fill:#ff0000;fill-opacity:0.75;fill-rule:evenodd;stroke:none;stroke-width:3.0999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ id="path41686"
+ d="m -272.5,108.5 c 1.00003,1e-5 2.00005,1e-5 3.00008,2e-5 0,0.99999 0,1.99999 0,2.99998 -1.00003,0 -2.00005,-1e-5 -3.00008,-1e-5 0,-1 0,-1.99999 0,-2.99999 z"
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ d="m -284.5,108.5 c 1.00003,1e-5 2.00005,1e-5 3.00008,2e-5 0,0.99999 0,1.99998 0,2.99998 -1.00003,-1e-5 -2.00005,-1e-5 -3.00008,-2e-5 0,-0.99999 0,-1.99999 0,-2.99998 z"
+ id="path41688"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41690"
+ d="m -283.5,110.5 0,-1 1,0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ 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;display:inline;enable-background:new"
+ d="m -271.5,110.5 0,-1 1,0"
+ id="path41692"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ d="m -272.49992,123.5 c 1.00003,-1e-5 2.00005,-1e-5 3.00008,-2e-5 0,-0.99999 0,-1.99999 0,-2.99998 -1.00003,0 -2.00005,1e-5 -3.00008,1e-5 0,1 0,1.99999 0,2.99999 z"
+ id="path41694"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41696"
+ d="m -284.49992,123.5 c 1.00003,-1e-5 2.00005,-1e-5 3.00008,-2e-5 0,-0.99999 0,-1.99998 0,-2.99998 -1.00003,1e-5 -2.00005,1e-5 -3.00008,2e-5 0,0.99999 0,1.99999 0,2.99998 z"
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ 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;display:inline;enable-background:new"
+ d="m -283.49992,122.5 0,-1 1,0"
+ id="path41699"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41701"
+ d="m -271.49992,122.5 0,-1 1,0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ y="176"
+ x="-228"
+ height="16"
+ width="16"
+ id="rect41703"
+ 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" />
+ <path
+ style="fill:url(#linearGradient42436);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;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -220,178.5 c -4.14,0 -7.40235,2.464 -7.40234,5.5 0,3.036 3.26234,5.5 7.40234,5.5 4.14,0 7.40234,-2.464 7.40234,-5.5 0,-3.036 -3.26233,-5.50001 -7.40234,-5.5 z m 0,4 c 1.2993,0 2.42742,0.39879 3.03125,1 -0.60383,0.60121 -1.73196,1 -3.03125,1 -1.29929,0 -2.42742,-0.39879 -3.03125,-1 0.60383,-0.60121 1.73196,-1 3.03125,-1 z"
+ id="path41705"
+ sodipodi:nodetypes="cssscccscc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.6;fill:url(#radialGradient42438);fill-rule:evenodd;stroke:none"
+ d="m -214.625,180.4375 c 1.5822,4.85564 -3.15377,7.27675 -11.84375,6.21875 l 0,0.0312 c 1.25689,1.67541 3.66207,2.8125 6.46875,2.8125 4.14,0 7.40625,-2.464 7.40625,-5.5 0,-1.34213 -0.64966,-2.57614 -1.71875,-3.53125 -0.10326,-0.0119 -0.20204,-0.024 -0.3125,-0.0312 z"
+ id="path41707"
+ sodipodi:nodetypes="cccsscc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path41709"
+ d="m -223.375,183.45313 c 1.90631,-1.46639 4.08905,-1.44306 6.1875,-0.53125 L -217,182.76563 c -0.60315,-4.39553 -10.23988,-3.57787 -6.375,0.6875 z"
+ style="opacity:0.6;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.6;fill:url(#radialGradient42440);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 -223.375,183.65625 0.5,-0.0312 c -0.0509,-0.0426 -0.11109,-0.08 -0.15625,-0.125 0.60383,-0.60121 1.73196,-1 3.03125,-1 0.99575,0 1.89552,0.24495 2.53125,0.625 L -217,182.96875 c -0.60315,-4.39553 -10.23988,-3.57787 -6.375,0.6875 z"
+ id="path41711"
+ sodipodi:nodetypes="cccsccc"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(0.9999986,0,0,1.799999,-2.971883e-4,111.10004)"
+ d="m -213.5,40.5 a 6.5,2.5 0 1 1 -13,0 6.5,2.5 0 1 1 13,0 z"
+ sodipodi:ry="2.5"
+ sodipodi:rx="6.5"
+ sodipodi:cy="40.5"
+ sodipodi:cx="-220"
+ id="path41713"
+ style="fill:none;stroke:url(#linearGradient42442);stroke-width:0.5962854;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"
+ sodipodi:type="arc" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41715"
+ 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"
+ id="rect41717"
+ width="16"
+ height="16"
+ x="-211.99985"
+ y="304" />
+ <g
+ style="opacity:0.8;display:inline;enable-background:new"
+ transform="translate(73.00016,196)"
+ id="g41719">
+ <rect
+ y="108"
+ x="-284.99991"
+ height="16"
+ width="16"
+ id="rect41721"
+ style="opacity:0.01000001;fill:#ff0000;fill-opacity:0.75;fill-rule:evenodd;stroke:none;stroke-width:3.0999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ id="path41723"
+ d="m -272.5,108.5 c 1.00003,1e-5 2.00005,1e-5 3.00008,2e-5 0,0.99999 0,1.99999 0,2.99998 -1.00003,0 -2.00005,-1e-5 -3.00008,-1e-5 0,-1 0,-1.99999 0,-2.99999 z"
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ d="m -284.5,108.5 c 1.00003,1e-5 2.00005,1e-5 3.00008,2e-5 0,0.99999 0,1.99998 0,2.99998 -1.00003,-1e-5 -2.00005,-1e-5 -3.00008,-2e-5 0,-0.99999 0,-1.99999 0,-2.99998 z"
+ id="path41725"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41727"
+ d="m -283.5,110.5 0,-1 1,0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ 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;display:inline;enable-background:new"
+ d="m -271.5,110.5 0,-1 1,0"
+ id="path41729"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ d="m -272.49992,123.5 c 1.00003,-1e-5 2.00005,-1e-5 3.00008,-2e-5 0,-0.99999 0,-1.99999 0,-2.99998 -1.00003,0 -2.00005,1e-5 -3.00008,1e-5 0,1 0,1.99999 0,2.99999 z"
+ id="path41731"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41733"
+ d="m -284.49992,123.5 c 1.00003,-1e-5 2.00005,-1e-5 3.00008,-2e-5 0,-0.99999 0,-1.99998 0,-2.99998 -1.00003,1e-5 -2.00005,1e-5 -3.00008,2e-5 0,0.99999 0,1.99999 0,2.99998 z"
+ style="fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:#003380;stroke-width:0.99999875;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:new"
+ 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;display:inline;enable-background:new"
+ d="m -283.49992,122.5 0,-1 1,0"
+ id="path41735"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41737"
+ d="m -271.49992,122.5 0,-1 1,0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline"
+ id="g41739"
+ transform="matrix(1.1658027,0,0,1.1657997,-354.28956,51.94393)"
+ 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\Kopia blender\.blender\icons\blender's iconset.png"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path41741"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.23686147;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.6969446,0,0,0.6900977,36.918531,141.69345)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.8;fill:url(#linearGradient42444);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path41743"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.6391427,-0.07194179,0.07284933,-0.6344823,204.68584,307.47408)" />
+ <path
+ transform="matrix(0.5885088,0,0,0.5897133,51.241774,153.48488)"
+ sodipodi:type="arc"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient42446);stroke-width:1.45605874;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path41745"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ sodipodi:nodetypes="cscc"
+ id="path41747"
+ style="fill:none;stroke:url(#linearGradient42448);stroke-width:0.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new"
+ d="m -197.75642,311.54171 c -0.99362,1.2083 -2.79874,2.22895 -6.24718,2.22895 -3.415,0 -5.24644,-1.02065 -6.24644,-2.195"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41749"
+ transform="matrix(1,0,0,-1,496,768)">
+ <rect
+ transform="scale(-1,1)"
+ y="385"
+ x="202"
+ height="16"
+ width="16"
+ id="rect41751"
+ 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" />
+ <path
+ sodipodi:nodetypes="ccc"
+ style="fill:none;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -203.5,396.5 0,3 -3,0"
+ id="path41753"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41755"
+ d="m -213.5,386.5 0,3 -3,0"
+ style="fill:none;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41757"
+ d="m -208.5,391.5 0,3 -3,0"
+ style="fill:none;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g41759"
+ 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,0,0,1,-118.8387,295.00001)"
+ style="display:inline">
+ <path
+ sodipodi:nodetypes="cz"
+ id="path41761"
+ 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:7.40000034;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 85.6613,103.49999 9,-9"
+ inkscape:connector-curvature="0" />
+ <path
+ 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"
+ id="path41763"
+ sodipodi:nodetypes="cz"
+ d=""
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 85.6613,103.49999 9,-9"
+ style="fill:none;stroke:#d7e3f4;stroke-width:1.5;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="path41765"
+ sodipodi:nodetypes="cz"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path41767"
+ d="m -203,400 0,-4 -1,0 0,3 -3,0 0,1 4,0 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path41769"
+ d="m -213,390 0,-4 -1,0 0,3 -3,0 0,1 4,0 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -208,395 0,-4 -1,0 0,3 -3,0 0,1 4,0 z"
+ id="path41771"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(-1,0,0,-1,-420,786)"
+ style="opacity:0.2"
+ id="g41773">
+ <path
+ style="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"
+ d="m -208,395 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ id="path41775"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path41777"
+ d="m -216,387 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ style="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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="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"
+ d="m -211,392 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ id="path41779"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path41781"
+ d="m -213,390 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ style="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"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g42152"
+ transform="translate(272.99917,170)">
+ <g
+ transform="translate(83.990361,105)"
+ id="g42154"
+ style="opacity:0.5">
+ <path
+ transform="matrix(0.9361892,0,0,0.9375002,-26.576994,10.374973)"
+ sodipodi:type="arc"
+ style="fill:#ffd5d5;fill-opacity:0.58823529;fill-rule:nonzero;stroke:#800000;stroke-width:1.06741309;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42157"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path42159"
+ style="fill:none;stroke:url(#linearGradient42462);stroke-width:1.22662127;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.814129,0,0,0.816369,-10.451999,24.674751)" />
+ <path
+ transform="matrix(0.6848076,0,0,0.6867124,6.6184411,39.974237)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient42464);stroke-width:1.45823753;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42161"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(0.814129,0,0,0.816369,-10.451999,24.674751)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient42466);stroke-width:1.22662127;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42163"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="translate(81.056581,171.48366)"
+ id="g42165">
+ <path
+ id="path42168"
+ d="m 101.94425,50.518348 -5.000004,1.875 0,6.3125 5.000004,2.71875 5,-2.71875 0,-6.3125 -5,-1.875 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path42170"
+ d="m 106.94413,58.696518 0,-6.29009 -5,-1.89415 c 0,2.16796 0,10.43646 0,10.91232 l 5,-2.72808 z"
+ style="fill:url(#linearGradient42468);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ 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"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 96.944126,58.696518 0,-6.29009 5.000004,-1.89415 0,10.91232 -5.000004,-2.72808 z"
+ id="path42175"
+ 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="path42177"
+ d="m 96.944126,52.406428 5.000004,-1.89415 5,1.89415 -5,2.07396 -5.000004,-2.07396 z"
+ style="fill:#ffffff;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient42470);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 106.44413,52.406428 0,6.04208 -4.5,2.48007 -4.500004,-2.48007 0,-6.04208"
+ id="path42179"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g42181"
+ transform="translate(335.99917,149.00001)">
+ <g
+ style="opacity:0.5"
+ id="g42183"
+ transform="translate(83.990367,126)">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path42185"
+ style="fill:#ffd5d5;fill-opacity:0.58823529;fill-rule:nonzero;stroke:#800000;stroke-width:1.06741309;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.9361892,0,0,0.9375002,-26.576994,10.374973)" />
+ <path
+ transform="matrix(0.814129,0,0,0.816369,-10.451999,24.674751)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient42472);stroke-width:1.22662127;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42187"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path42189"
+ style="fill:none;stroke:url(#linearGradient42474);stroke-width:1.45823753;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.6848076,0,0,0.6867124,6.6184411,39.974237)" />
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path42191"
+ style="fill:none;stroke:url(#linearGradient42477);stroke-width:1.22662127;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.814129,0,0,0.816369,-10.451999,24.674751)" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ transform="translate(321.49473,233.64631)"
+ id="g42193">
+ <g
+ id="g42195"
+ transform="translate(-38.4939,35.353694)">
+ <path
+ sodipodi:nodetypes="cccsccc"
+ id="path42197"
+ d="m -98.999998,-25.5 c -2.485192,0 -4.499992,0.89481 -4.500002,2 l 0,7 c 0,1.10519 2.0148,2 4.500002,2 2.48519,0 4.499998,-1.1448 4.499998,-2.25 l 2e-6,-6.75 c 0,-1.10519 -2.01481,-2 -4.5,-2 z"
+ style="fill:url(#linearGradient42479);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccscc"
+ id="path42199"
+ d="m -102.5,-22 0,5 c 0,1.25 0.5,1.5 3.5,1.5 3,0 3.5,-0.25 3.5,-1.5 l 0,-5"
+ style="fill:none;stroke:url(#linearGradient42481);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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="css"
+ id="path42201"
+ d="M -94.730509,-23.353486 C -94.748454,-21.92288 -95.5,-21.5 -99,-21.5 c -3.5,0 -4.24845,-0.42288 -4.24845,-1.848345"
+ style="fill:none;stroke:url(#linearGradient42483);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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient42485);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"
+ d="m -95.341215,-23.173655 c 0,0.873491 -0.648671,1.587005 -3.656631,1.582419 -3.011664,-0.0046 -3.656634,-0.708928 -3.656634,-1.582419 0,-0.87349 0.64497,-1.582418 3.656634,-1.582418 3.00796,0 3.656631,0.708928 3.656631,1.582418 z"
+ id="path42203"
+ sodipodi:nodetypes="csssc"
+ inkscape:connector-curvature="0" />
+ <path
+ 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;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -99,-25.5 c -4,0 -4.49999,0.89481 -4.5,2 l 0,6 c 0,1.10519 0,3.00433 4.50216,3.002164 C -94.5,-14.5 -94.5,-16.3948 -94.5,-17.5 l 0,-6 c 0,-1.10519 -0.5,-2 -4.5,-2 z"
+ id="path42205"
+ sodipodi:nodetypes="cccsccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g42207"
+ transform="translate(251.99917,191.00001)">
+ <g
+ transform="translate(83.990364,83.999999)"
+ id="g42209"
+ style="opacity:0.5">
+ <path
+ transform="matrix(0.9361892,0,0,0.9375002,-26.576994,10.374973)"
+ sodipodi:type="arc"
+ style="fill:#ffd5d5;fill-opacity:0.58823529;fill-rule:nonzero;stroke:#800000;stroke-width:1.06741309;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42211"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path42213"
+ style="fill:none;stroke:url(#linearGradient42487);stroke-width:1.22662127;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.814129,0,0,0.816369,-10.451999,24.674751)" />
+ <path
+ transform="matrix(0.6848076,0,0,0.6867124,6.6184411,39.974237)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient42489);stroke-width:1.45823753;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42215"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(0.814129,0,0,0.816369,-10.451999,24.674751)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient42491);stroke-width:1.22662127;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42217"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(1.3088013,0,0,1.3078064,114.94487,78.842325)"
+ style="display:inline"
+ 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="g42219">
+ <rect
+ y="94.553505"
+ x="48.560436"
+ height="7.6462827"
+ width="7.6405811"
+ id="rect42221"
+ style="fill:url(#linearGradient42493);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.61147881;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" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path42223"
+ d="m 49.324493,101.43525 0,-6.117109 6.112464,0 9.17e-4,6.117009 -6.113381,1e-4 0,0 0,0 0,0 z"
+ style="fill:none;stroke:url(#linearGradient42495);stroke-width:0.76434839px;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g42225"
+ transform="translate(293.99917,128.01655)">
+ <g
+ id="g42227">
+ <g
+ transform="translate(83.990364,146.98346)"
+ id="g42229"
+ style="opacity:0.5">
+ <path
+ transform="matrix(0.9361892,0,0,0.9375002,-26.576994,10.374973)"
+ sodipodi:type="arc"
+ style="fill:#ffd5d5;fill-opacity:0.58823529;fill-rule:nonzero;stroke:#800000;stroke-width:1.06741309;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42231"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path42233"
+ style="fill:none;stroke:url(#linearGradient42497);stroke-width:1.22662127;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.814129,0,0,0.816369,-10.451999,24.674751)" />
+ <path
+ transform="matrix(0.6848076,0,0,0.6867124,6.6184411,39.974237)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient42499);stroke-width:1.45823753;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42235"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(0.814129,0,0,0.816369,-10.451999,24.674751)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient42501);stroke-width:1.22662127;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42237"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ style="display:inline"
+ id="g42239"
+ transform="matrix(0.9864502,0,0,0.9977342,55.832396,47.37231)"
+ 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\Kopia blender\.blender\icons\blender's iconset.png"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path42241"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.45345163;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.6969446,0,0,0.6900977,36.918531,141.69345)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.8;fill:url(#linearGradient42503);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path42243"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.6289675,-0.07056955,0.07168957,-0.6223801,203.47957,305.88099)" />
+ <path
+ transform="matrix(0.5718707,0,0,0.5622842,53.438009,156.77386)"
+ sodipodi:type="arc"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient42505);stroke-width:1.77757704;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42245"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ style="display:inline;enable-background:new"
+ id="g42247"
+ transform="translate(315,107)">
+ <g
+ transform="translate(83.990364,168)"
+ id="g42249"
+ style="opacity:0.5">
+ <path
+ transform="matrix(0.9361892,0,0,0.9375002,-26.576994,10.374973)"
+ sodipodi:type="arc"
+ style="fill:#ffd5d5;fill-opacity:0.58823529;fill-rule:nonzero;stroke:#800000;stroke-width:1.06741309;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42251"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path42253"
+ style="fill:none;stroke:url(#linearGradient42507);stroke-width:1.22662127;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.814129,0,0,0.816369,-10.451999,24.674751)" />
+ <path
+ transform="matrix(0.6848076,0,0,0.6867124,6.6184411,39.974237)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient42509);stroke-width:1.45823753;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42255"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(0.814129,0,0,0.816369,-10.451999,24.674751)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient42511);stroke-width:1.22662127;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42257"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="translate(67,168)"
+ id="g42259">
+ <rect
+ style="opacity:0;fill:#ffd5d5;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect42261"
+ width="14"
+ height="14"
+ x="109"
+ y="116" />
+ <g
+ transform="matrix(0,-0.7411719,0.7413284,0,26.310335,194.89046)"
+ id="g42263">
+ <rect
+ y="113"
+ x="89.000832"
+ height="16"
+ width="16"
+ id="rect42265"
+ 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"
+ 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.3039373,-0.2835816,-0.2811062,1.3154136,-8.365286,-135.94413)"
+ id="g42268"
+ style="display:inline">
+ <path
+ transform="matrix(0.6969446,0,0,0.6900977,36.918531,141.69345)"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.52109182;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0"
+ d="m 139.87786,116.72728 c 0,4.416 -4.87654,8.89303 -9.18264,9.14567 -4.03231,0.23658 -6.86684,-2.60955 -6.61392,-6.64097 0.26963,-4.29785 4.87655,-8.89304 9.18265,-9.14567 4.03232,-0.23656 6.86685,2.60957 6.61391,6.64097 z"
+ id="path42273"
+ sodipodi:nodetypes="csssc"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(-0.6214741,-0.06030772,0.08065856,-0.6191475,201.43124,304.14414)"
+ style="opacity:0.8;fill:url(#linearGradient42513);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 140.14875,115.73726 c 0,4.416 -4.29905,10.26855 -8.71505,10.26855 -4.416,0 -7.23906,-1.65769 -7.23906,-6.07369 0,-4.416 4.28332,-9.5732 8.27188,-10.31985 3.26409,-0.61103 7.68223,1.70899 7.68223,6.12499 l 0,0 0,0 0,0 z"
+ id="path42275"
+ sodipodi:nodetypes="csssc"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(0.5541229,-0.02016698,-0.02019099,0.5552959,58.152692,160.26124)"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient42515);stroke-width:1.90297282;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0"
+ d="m 139.88903,116.28509 c 0,4.416 -5.24736,9.49944 -9.66336,9.49944 -4.416,0 -6.16482,-1.70296 -6.16482,-6.11896 0,-4.416 5.24736,-9.49945 9.66336,-9.49945 4.416,0 6.16482,1.70297 6.16482,6.11897 l 0,0 0,0 0,0 z"
+ id="path42277"
+ sodipodi:nodetypes="csssc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ inkscape:export-ydpi="90"
+ 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">
+ <rect
+ y="237.5"
+ x="162.99997"
+ height="16"
+ width="16"
+ id="rect42282"
+ style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" />
+ <g
+ id="g42285"
+ style="opacity:0.9">
+ <g
+ transform="translate(75.999999,-319.5)"
+ id="g42287"
+ style="fill:#ffcc00;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;display:inline">
+ <path
+ style="fill:none;stroke:#1a1a1a;stroke-width:1.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m -167,235 0,9 1,0 0,-4 3,0 0,-1 -3,0 0,-4 5,0 0,-1 -6,0 0,1 z"
+ transform="translate(262.99997,326)"
+ id="path42289"
+ sodipodi:nodetypes="cccccccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="fill:#ffcc00;display:inline"
+ id="g42291"
+ transform="translate(75.999999,-319.5)">
+ <path
+ style="fill:url(#linearGradient42517)"
+ d="m -167,235 0,9 1,0 0,-4 3,0 0,-1 -3,0 0,-4 5,0 0,-1 -6,0 0,1 z"
+ transform="translate(262.99997,326)"
+ id="path42294"
+ sodipodi:nodetypes="cccccccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="opacity:0.85;fill:#ffffff;display:inline"
+ d="m 171.99997,240.5 0,10 0.65625,0 0,-10 -0.65625,0 z"
+ id="path42296"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="fill:none;stroke:#162d50;stroke-width:1.60000002;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"
+ id="g42298">
+ <rect
+ style="fill:none;stroke:#162d50;stroke-width:1.60000002;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"
+ id="rect42300"
+ width="1.25"
+ height="1"
+ x="90"
+ y="43"
+ transform="translate(73.999969,208.5)" />
+ <rect
+ y="251.5"
+ x="167.74997"
+ height="1"
+ width="1.2500329"
+ id="rect42302"
+ style="fill:none;stroke:#162d50;stroke-width:1.60000002;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" />
+ <rect
+ y="238.5"
+ x="163.99997"
+ height="1"
+ width="1.2499995"
+ id="rect42304"
+ style="fill:none;stroke:#162d50;stroke-width:1.60000002;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" />
+ <rect
+ style="fill:none;stroke:#162d50;stroke-width:1.60000002;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"
+ id="rect42306"
+ width="1.250011"
+ height="1"
+ x="167.74997"
+ y="238.5" />
+ <rect
+ style="fill:none;stroke:#162d50;stroke-width:1.60000002;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"
+ id="rect42308"
+ width="1.0000029"
+ height="12.5"
+ x="165.99997"
+ y="239.25" />
+ </g>
+ <g
+ id="g42310"
+ style="fill:#e9f0fa;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate">
+ <rect
+ transform="translate(73.999969,208.5)"
+ y="43"
+ x="90"
+ height="1"
+ width="2"
+ id="rect42312"
+ style="fill:#e9f0fa;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:#e9f0fa;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect42314"
+ width="2"
+ height="1"
+ x="166.99997"
+ y="251.5" />
+ <rect
+ style="fill:#e9f0fa;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect42316"
+ width="2"
+ height="1"
+ x="163.99997"
+ y="238.5" />
+ <rect
+ y="238.5"
+ x="166.99997"
+ height="1"
+ width="2"
+ id="rect42318"
+ style="fill:#e9f0fa;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="239.5"
+ x="165.99997"
+ height="12"
+ width="0.99999952"
+ id="rect42320"
+ style="fill:#e9f0fa;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g35366"
+ transform="translate(333.02099,358)">
+ <rect
+ y="135"
+ x="-202"
+ height="16"
+ width="16"
+ id="rect35368"
+ 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" />
+ <g
+ transform="matrix(0.8692812,0,0,0.8692812,-279.33076,38.816971)"
+ id="g35370"
+ style="opacity:0.35">
+ <path
+ transform="matrix(0.9361892,0,0,0.9375002,-26.576994,10.374973)"
+ sodipodi:type="arc"
+ style="fill:#f8dcdc;fill-opacity:0.58823529;fill-rule:nonzero;stroke:#580000;stroke-width:1.22792602;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="path35372"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path35374"
+ style="fill:none;stroke:url(#linearGradient35406);stroke-width:1.4523226;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.7910044,0,0,0.7931859,-7.3995492,27.410355)" />
+ <path
+ transform="matrix(0.644496,0,0,0.6462993,11.939574,44.742981)"
+ sodipodi:type="arc"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient35408);stroke-width:1.78243256;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path35376"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ id="g35378"
+ transform="matrix(0.857703,0,0,0.8577018,-4.235469,19.278753)"
+ style="opacity:0.7">
+ <path
+ sodipodi:nodetypes="cssssszzs"
+ id="path35380"
+ d="m -222.5,141.5 c 1.52069,0 2.97702,-1.62476 3,-2.5 0.0525,-1.99931 1.5,-3.5 3.5,-3.5 2,0 3.5,1.568 3.5,3.5 0,1.84581 -1.5,3.50326 -3.5,3.5 -0.8997,-0.001 -2.5,1.5 -2.5,3 0,2.25 -1.75,4 -4,4 -2.25,0 -4,-1.75 -4,-4 0,-2.25 1.75,-4 4,-4 z"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:0.93272448;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" />
+ <path
+ transform="translate(-527,-167)"
+ d="m 311,303 c -1.75507,0 -3,1.24493 -3,3 0,0.81824 -0.48216,1.55558 -1.125,2.09375 C 306.23216,308.63192 305.39457,309 304.5,309 c -1.996,0 -3.5,1.504 -3.5,3.5 0,1.996 1.504,3.5 3.5,3.5 1.996,0 3.5,-1.504 3.5,-3.5 0,-0.88607 0.36895,-1.73024 0.90625,-2.375 0.5373,-0.64476 1.27281,-1.125 2.09375,-1.125 1.72989,0 3,-1.41958 3,-3 0,-1.67845 -1.25603,-3 -3,-3 z"
+ id="path35382"
+ style="opacity:0.8;fill:url(#linearGradient35410);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.86598092;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:original="M 311 302.5 C 309 302.5 307.5 304 307.5 306 C 307.5 307.25 306.02069 308.5 304.5 308.5 C 302.25 308.5 300.5 310.25 300.5 312.5 C 300.5 314.75 302.25 316.5 304.5 316.5 C 306.75 316.5 308.5 314.75 308.5 312.5 C 308.5 311 309.75 309.5 311 309.5 C 313 309.5 314.5 307.84581 314.5 306 C 314.5 304.068 313 302.5 311 302.5 z "
+ inkscape:radius="-0.48985747"
+ sodipodi:type="inkscape:offset" />
+ <path
+ transform="translate(-527,-167)"
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="-0.96440691"
+ inkscape:original="M 311 302.5 C 309 302.5 307.5 304 307.5 306 C 307.5 307.25 306.02069 308.5 304.5 308.5 C 302.25 308.5 300.5 310.25 300.5 312.5 C 300.5 314.75 302.25 316.5 304.5 316.5 C 306.75 316.5 308.5 314.75 308.5 312.5 C 308.5 311 309.75 309.5 311 309.5 C 313 309.5 314.5 307.84581 314.5 306 C 314.5 304.068 313 302.5 311 302.5 z "
+ style="fill:none;stroke:url(#radialGradient35412);stroke-width:1.16590559;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="path35384"
+ d="m 311,303.46875 c -1.5178,0 -2.53125,1.01345 -2.53125,2.53125 0,1.00544 -0.55807,1.86332 -1.28125,2.46875 -0.72318,0.60543 -1.66291,1 -2.6875,1 -1.74994,0 -3.03125,1.28131 -3.03125,3.03125 0,1.74994 1.28131,3.03125 3.03125,3.03125 1.74994,0 3.03125,-1.28131 3.03125,-3.03125 0,-1.01789 0.3963,-1.96306 1,-2.6875 0.6037,-0.72444 1.45799,-1.28125 2.46875,-1.28125 1.46823,0 2.53125,-1.20792 2.53125,-2.53125 0,-1.43282 -1.03531,-2.53125 -2.53125,-2.53125 z" />
+ <path
+ transform="matrix(0,-1,-1,0,90,450)"
+ d="m 311,303.46875 c -1.5178,0 -2.53125,1.01345 -2.53125,2.53125 0,1.00544 -0.55807,1.86332 -1.28125,2.46875 -0.72318,0.60543 -1.66291,1 -2.6875,1 -1.74994,0 -3.03125,1.28131 -3.03125,3.03125 0,1.74994 1.28131,3.03125 3.03125,3.03125 1.74994,0 3.03125,-1.28131 3.03125,-3.03125 0,-1.01789 0.3963,-1.96306 1,-2.6875 0.6037,-0.72444 1.45799,-1.28125 2.46875,-1.28125 1.46823,0 2.53125,-1.20792 2.53125,-2.53125 0,-1.43282 -1.03531,-2.53125 -2.53125,-2.53125 z"
+ id="path35386"
+ style="fill:none;stroke:url(#radialGradient35414);stroke-width:1.16590559;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:original="M 311 302.5 C 309 302.5 307.5 304 307.5 306 C 307.5 307.25 306.02069 308.5 304.5 308.5 C 302.25 308.5 300.5 310.25 300.5 312.5 C 300.5 314.75 302.25 316.5 304.5 316.5 C 306.75 316.5 308.5 314.75 308.5 312.5 C 308.5 311 309.75 309.5 311 309.5 C 313 309.5 314.5 307.84581 314.5 306 C 314.5 304.068 313 302.5 311 302.5 z "
+ inkscape:radius="-0.96440691"
+ sodipodi:type="inkscape:offset" />
+ </g>
+ <g
+ style="opacity:0.12999998"
+ id="g35388"
+ transform="matrix(0.8692812,0,0,0.8692812,-279.33076,38.816971)">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path35390"
+ style="fill:#ffd5d5;fill-opacity:0.58823529;fill-rule:nonzero;stroke:#530505;stroke-width:1.22792602;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.9361892,0,0,0.9375002,-26.576994,10.374973)" />
+ <path
+ transform="matrix(0.7910044,0,0,0.7931859,-7.3995492,27.410355)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient35416);stroke-width:1.4523226;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path35392"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path35394"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient35418);stroke-width:1.78243256;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.644496,0,0,0.6462993,11.939574,44.742981)" />
+ </g>
+ <g
+ style="opacity:0.9;display:inline;enable-background:new"
+ transform="matrix(0.8749996,0,0,0.8802811,-404.57262,-113.49608)"
+ id="g35396">
+ <path
+ sodipodi:type="arc"
+ style="fill:#ececec;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient35420);stroke-width:1.13942409;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="path35398"
+ sodipodi:cx="219.5"
+ sodipodi:cy="292.5"
+ sodipodi:rx="4"
+ sodipodi:ry="4"
+ d="m 223.5,292.5 a 4,4 0 1 1 -8,0 4,4 0 1 1 8,0 z"
+ transform="translate(20,0)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.8;fill:url(#linearGradient35422);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29032254;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path35400"
+ sodipodi:cx="219.5"
+ sodipodi:cy="292.5"
+ sodipodi:rx="4"
+ sodipodi:ry="4"
+ d="m 223.5,292.5 a 4,4 0 1 1 -8,0 4,4 0 1 1 8,0 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 a 4,4 0 1 1 -8,0 4,4 0 1 1 8,0 z"
+ sodipodi:ry="4"
+ sodipodi:rx="4"
+ sodipodi:cy="292.5"
+ sodipodi:cx="219.5"
+ id="path35402"
+ style="fill:none;stroke:url(#linearGradient35424);stroke-width:1.6138407;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(0.875,0,0,0.875,47.4375,36.5625)"
+ d="m 223.5,292.5 a 4,4 0 1 1 -8,0 4,4 0 1 1 8,0 z"
+ sodipodi:ry="4"
+ sodipodi:rx="4"
+ sodipodi:cy="292.5"
+ sodipodi:cx="219.5"
+ id="path35404"
+ style="opacity:0.8;fill:url(#radialGradient35426);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29032254;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ </g>
+ </g>
+ <g
+ transform="translate(291,273.9804)"
+ id="g35428"
+ 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"
+ id="rect35430"
+ width="16"
+ height="16"
+ x="-202"
+ y="135" />
+ <g
+ style="opacity:0.35"
+ id="g35432"
+ transform="matrix(0.8692812,0,0,0.8692812,-279.33076,38.816971)">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path35434"
+ style="fill:#f8dcdc;fill-opacity:0.58823529;fill-rule:nonzero;stroke:#580000;stroke-width:1.22792602;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"
+ transform="matrix(0.9361892,0,0,0.9375002,-26.576994,10.374973)" />
+ <path
+ transform="matrix(0.7910044,0,0,0.7931859,-7.3995492,27.410355)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient35468);stroke-width:1.4523226;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path35436"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path35438"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient35470);stroke-width:1.78243256;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.644496,0,0,0.6462993,11.939574,44.742981)" />
+ </g>
+ <g
+ style="opacity:0.7"
+ transform="matrix(0.857703,0,0,0.8577018,-4.235469,19.278753)"
+ id="g35440">
+ <path
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.93272448;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 -222.5,141.5 c 1.52069,0 2.97702,-1.62476 3,-2.5 0.0525,-1.99931 1.5,-3.5 3.5,-3.5 2,0 3.5,1.568 3.5,3.5 0,1.84581 -1.5,3.50326 -3.5,3.5 -0.8997,-0.001 -2.5,1.5 -2.5,3 0,2.25 -1.75,4 -4,4 -2.25,0 -4,-1.75 -4,-4 0,-2.25 1.75,-4 4,-4 z"
+ id="path35442"
+ sodipodi:nodetypes="cssssszzs"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="-0.48985747"
+ inkscape:original="M 311 302.5 C 309 302.5 307.5 304 307.5 306 C 307.5 307.25 306.02069 308.5 304.5 308.5 C 302.25 308.5 300.5 310.25 300.5 312.5 C 300.5 314.75 302.25 316.5 304.5 316.5 C 306.75 316.5 308.5 314.75 308.5 312.5 C 308.5 311 309.75 309.5 311 309.5 C 313 309.5 314.5 307.84581 314.5 306 C 314.5 304.068 313 302.5 311 302.5 z "
+ style="opacity:0.8;fill:url(#linearGradient35472);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.86598092;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path35444"
+ d="m 311,303 c -1.75507,0 -3,1.24493 -3,3 0,0.81824 -0.48216,1.55558 -1.125,2.09375 C 306.23216,308.63192 305.39457,309 304.5,309 c -1.996,0 -3.5,1.504 -3.5,3.5 0,1.996 1.504,3.5 3.5,3.5 1.996,0 3.5,-1.504 3.5,-3.5 0,-0.88607 0.36895,-1.73024 0.90625,-2.375 0.5373,-0.64476 1.27281,-1.125 2.09375,-1.125 1.72989,0 3,-1.41958 3,-3 0,-1.67845 -1.25603,-3 -3,-3 z"
+ transform="translate(-527,-167)" />
+ <path
+ d="m 311,303.46875 c -1.5178,0 -2.53125,1.01345 -2.53125,2.53125 0,1.00544 -0.55807,1.86332 -1.28125,2.46875 -0.72318,0.60543 -1.66291,1 -2.6875,1 -1.74994,0 -3.03125,1.28131 -3.03125,3.03125 0,1.74994 1.28131,3.03125 3.03125,3.03125 1.74994,0 3.03125,-1.28131 3.03125,-3.03125 0,-1.01789 0.3963,-1.96306 1,-2.6875 0.6037,-0.72444 1.45799,-1.28125 2.46875,-1.28125 1.46823,0 2.53125,-1.20792 2.53125,-2.53125 0,-1.43282 -1.03531,-2.53125 -2.53125,-2.53125 z"
+ id="path35446"
+ style="fill:none;stroke:url(#radialGradient35474);stroke-width:1.16590559;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:original="M 311 302.5 C 309 302.5 307.5 304 307.5 306 C 307.5 307.25 306.02069 308.5 304.5 308.5 C 302.25 308.5 300.5 310.25 300.5 312.5 C 300.5 314.75 302.25 316.5 304.5 316.5 C 306.75 316.5 308.5 314.75 308.5 312.5 C 308.5 311 309.75 309.5 311 309.5 C 313 309.5 314.5 307.84581 314.5 306 C 314.5 304.068 313 302.5 311 302.5 z "
+ inkscape:radius="-0.96440691"
+ sodipodi:type="inkscape:offset"
+ transform="translate(-527,-167)" />
+ <path
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="-0.96440691"
+ inkscape:original="M 311 302.5 C 309 302.5 307.5 304 307.5 306 C 307.5 307.25 306.02069 308.5 304.5 308.5 C 302.25 308.5 300.5 310.25 300.5 312.5 C 300.5 314.75 302.25 316.5 304.5 316.5 C 306.75 316.5 308.5 314.75 308.5 312.5 C 308.5 311 309.75 309.5 311 309.5 C 313 309.5 314.5 307.84581 314.5 306 C 314.5 304.068 313 302.5 311 302.5 z "
+ style="fill:none;stroke:url(#radialGradient35476);stroke-width:1.16590559;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="path35448"
+ d="m 311,303.46875 c -1.5178,0 -2.53125,1.01345 -2.53125,2.53125 0,1.00544 -0.55807,1.86332 -1.28125,2.46875 -0.72318,0.60543 -1.66291,1 -2.6875,1 -1.74994,0 -3.03125,1.28131 -3.03125,3.03125 0,1.74994 1.28131,3.03125 3.03125,3.03125 1.74994,0 3.03125,-1.28131 3.03125,-3.03125 0,-1.01789 0.3963,-1.96306 1,-2.6875 0.6037,-0.72444 1.45799,-1.28125 2.46875,-1.28125 1.46823,0 2.53125,-1.20792 2.53125,-2.53125 0,-1.43282 -1.03531,-2.53125 -2.53125,-2.53125 z"
+ transform="matrix(0,-1,-1,0,90,450)" />
+ </g>
+ <g
+ transform="matrix(0.8692812,0,0,0.8692812,-279.33076,38.816971)"
+ id="g35450"
+ style="opacity:0.12999998">
+ <path
+ transform="matrix(0.9361892,0,0,0.9375002,-26.576994,10.374973)"
+ sodipodi:type="arc"
+ style="fill:#ffd5d5;fill-opacity:0.58823529;fill-rule:nonzero;stroke:#530505;stroke-width:1.22792602;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path35452"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path35454"
+ style="fill:none;stroke:url(#linearGradient35478);stroke-width:1.4523226;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.7910044,0,0,0.7931859,-7.3995492,27.410355)" />
+ <path
+ transform="matrix(0.644496,0,0,0.6462993,11.939574,44.742981)"
+ sodipodi:type="arc"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient35480);stroke-width:1.78243256;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path35456"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ id="g35458"
+ transform="matrix(0.8749996,0,0,0.8802811,-404.57262,-113.49608)"
+ style="opacity:0.9;display:inline;enable-background:new">
+ <path
+ transform="translate(20,0)"
+ d="m 223.5,292.5 a 4,4 0 1 1 -8,0 4,4 0 1 1 8,0 z"
+ sodipodi:ry="4"
+ sodipodi:rx="4"
+ sodipodi:cy="292.5"
+ sodipodi:cx="219.5"
+ id="path35460"
+ style="fill:#ececec;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient35482);stroke-width:1.13942409;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(0.875,0,0,0.875,47.4375,36.5625)"
+ d="m 223.5,292.5 a 4,4 0 1 1 -8,0 4,4 0 1 1 8,0 z"
+ sodipodi:ry="4"
+ sodipodi:rx="4"
+ sodipodi:cy="292.5"
+ sodipodi:cx="219.5"
+ id="path35462"
+ style="opacity:0.8;fill:url(#linearGradient35484);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29032254;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient35486);stroke-width:1.6138407;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="path35464"
+ sodipodi:cx="219.5"
+ sodipodi:cy="292.5"
+ sodipodi:rx="4"
+ sodipodi:ry="4"
+ d="m 223.5,292.5 a 4,4 0 1 1 -8,0 4,4 0 1 1 8,0 z"
+ transform="matrix(0.7060003,0,0,0.7060647,84.532933,85.976064)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.8;fill:url(#radialGradient35488);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29032254;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path35466"
+ sodipodi:cx="219.5"
+ sodipodi:cy="292.5"
+ sodipodi:rx="4"
+ sodipodi:ry="4"
+ d="m 223.5,292.5 a 4,4 0 1 1 -8,0 4,4 0 1 1 8,0 z"
+ transform="matrix(0.875,0,0,0.875,47.4375,36.5625)" />
+ </g>
+ </g>
+ <g
+ id="g34702"
+ 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">
+ <g
+ id="g35479"
+ transform="translate(30.046349,-38.039825)"
+ style="display:inline;enable-background:new">
+ <g
+ transform="translate(-340.00002,-121.00001)"
+ id="g35481">
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#e9e9af;stroke-width:0.58333313;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="path35483"
+ sodipodi:cx="464.5"
+ sodipodi:cy="192.5"
+ sodipodi:rx="1.75"
+ sodipodi:ry="1.75"
+ d="m 466.25,192.5 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 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 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 z"
+ sodipodi:ry="1.75"
+ sodipodi:rx="1.75"
+ sodipodi:cy="192.5"
+ sodipodi:cx="464.5"
+ id="path35485"
+ style="opacity:0.4;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#e1e08e;stroke-width:0.69999987;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:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#adac2f;stroke-width:1.16666663;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="path35487"
+ sodipodi:cx="464.5"
+ sodipodi:cy="192.5"
+ sodipodi:rx="1.75"
+ sodipodi:ry="1.75"
+ d="m 466.25,192.5 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 z"
+ transform="matrix(0.8571429,0,0,0.8571429,66.810813,28.039828)" />
+ </g>
+ <rect
+ y="71.039841"
+ x="123.95369"
+ height="2"
+ width="2"
+ id="rect35489"
+ style="fill:#f4eed7;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="opacity:0.6"
+ transform="matrix(-1,0,0,1,194,-21)"
+ id="g35439">
+ <path
+ style="fill:url(#linearGradient35446);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new"
+ d="m 31.5,52.5 c -1.656,0 -3,1.343998 -3,3 0,0.02155 -4.53e-4,0.04106 0,0.0625 -1.138867,0.233417 -1.999999,1.229094 -2,2.4375 0,1.381035 1.120001,2.500001 2.5,2.5 l 6.5,0 c 1.656,0 3,-1.344001 3,-3 0,-1.656001 -1.344,-2.999999 -3,-3 -0.40365,0 -0.77337,0.105241 -1.125,0.25 C 34.035268,53.465989 32.89035,52.500001 31.5,52.5 z"
+ id="path34600"
+ 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"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path35419"
+ style="fill:url(#linearGradient35450);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ sodipodi:type="arc"
+ transform="matrix(0,0.3125,-0.3124999,0,68.374988,14.250001)" />
+ <path
+ transform="matrix(0,0.2187504,-0.2187496,0,54.562456,29.374947)"
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient35448);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ id="path34624"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(0.08088095,0.3018518,-0.3018517,0.08088093,60.442218,8.1116116)"
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient35452);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ id="path35435"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path35429"
+ style="fill:url(#linearGradient35454);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ sodipodi:type="arc"
+ transform="matrix(0,0.2812501,-0.2812497,0,64.937461,20.624986)" />
+ <path
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="-0.92788464"
+ inkscape:original="M 31.5 52.5 C 29.844 52.5 28.5 53.843998 28.5 55.5 C 28.5 55.521551 28.499547 55.541057 28.5 55.5625 C 27.361133 55.795917 26.500001 56.791594 26.5 58 C 26.5 59.381035 27.620001 60.500001 29 60.5 L 35.5 60.5 C 37.156 60.5 38.5 59.155999 38.5 57.5 C 38.5 55.843999 37.156 54.500001 35.5 54.5 C 35.09635 54.5 34.72663 54.605241 34.375 54.75 C 34.035268 53.465989 32.89035 52.500001 31.5 52.5 z "
+ style="fill:none;stroke:url(#linearGradient35718);stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new"
+ id="path35703"
+ d="m 31.5,53.4375 c -1.153957,0 -2.0625,0.908541 -2.0625,2.0625 0,0.03455 7.4e-5,0.03475 0,0.03125 a 0.92797743,0.92797743 0 0 1 -0.75,0.9375 c -0.72055,0.147681 -1.249999,0.763662 -1.25,1.53125 0,0.879367 0.684082,1.562501 1.5625,1.5625 l 6.5,0 c 1.153956,0 2.0625,-0.908545 2.0625,-2.0625 0,-1.153957 -0.908543,-2.062499 -2.0625,-2.0625 -0.242369,0 -0.494949,0.03839 -0.78125,0.15625 A 0.92797743,0.92797743 0 0 1 33.46875,55 C 33.231438,54.103084 32.460566,53.437501 31.5,53.4375 z" />
+ </g>
+ <rect
+ y="31"
+ x="152"
+ height="16"
+ width="16"
+ id="rect34608"
+ 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"
+ 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(0.9059893,0,0,0.9161677,40.690483,-162.91268)"
+ id="g34610"
+ style="display:inline">
+ <path
+ transform="matrix(0.6879625,0,0,0.6812035,38.104167,142.74297)"
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.6033566;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path34612"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(-0.6156869,-0.06867104,0.07017585,-0.6056363,201.96224,303.63852)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path34614"
+ style="opacity:0.8;fill:url(#linearGradient34618);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:type="arc" />
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path34616"
+ style="fill:none;stroke:url(#linearGradient34620);stroke-width:2.02934265;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.5436035,0,0,0.5381576,57.159565,159.63177)" />
+ </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"
+ transform="translate(-20.999985,0)">
+ <rect
+ y="157"
+ x="89.000015"
+ height="16"
+ width="16"
+ id="rect36400"
+ style="opacity:0;fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g36402">
+ <g
+ transform="translate(8.000015,151)"
+ style="stroke:#1a1a1a;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ id="g36404">
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#00163c;stroke-width:3.29999995;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 88.999985,8 0,8"
+ id="path36407"
+ 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="path36410"
+ d="m 82.99997,20 6.000015,-4"
+ style="fill:none;stroke:#5d0606;stroke-width:3.29999995;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="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#183c00;stroke-width:3.29999995;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 94.99997,20 88.999985,16"
+ id="path36412"
+ 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
+ style="fill:none;stroke:#5d0606;stroke-width:1.79999995;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="rect36414"
+ width="2.0000153"
+ height="2.0000069"
+ x="89.999985"
+ y="170"
+ rx="0"
+ ry="0" />
+ <rect
+ style="fill:none;stroke:#001e50;stroke-width:1.79999995;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="rect36416"
+ width="2.0000153"
+ height="2.0000069"
+ x="96"
+ y="158"
+ rx="0"
+ ry="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#4c8ff4;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 97,159 0,8"
+ id="path36418"
+ 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="path36420"
+ d="M 90.999985,171 97,167"
+ style="fill:none;stroke:#ef4e29;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"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="170"
+ x="89.999985"
+ height="2.0000069"
+ width="2.0000153"
+ id="rect36422"
+ style="opacity:0.3;fill:none;stroke:#5d0606;stroke-width:1.79999995;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
+ sodipodi:nodetypes="ccc"
+ style="opacity:0.3;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 90.499985,170.75 6,-4 1.5e-5,-7.25"
+ id="path36424"
+ 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
+ ry="0"
+ rx="0"
+ y="170"
+ x="102"
+ height="2.0000069"
+ width="2.0000153"
+ id="rect36426"
+ style="fill:#acc373;fill-opacity:1;fill-rule:nonzero;stroke:#183c00;stroke-width:1.79999995;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
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#93e420;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 102.99998,171 97,167"
+ id="path36428"
+ 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
+ ry="0"
+ rx="0"
+ y="170"
+ x="90"
+ height="2"
+ width="2"
+ id="rect36430"
+ style="fill:#eb512e;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.3499999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ ry="0"
+ rx="0"
+ y="158"
+ x="96"
+ height="2.0000069"
+ width="2.0000153"
+ id="rect36432"
+ style="opacity:0.3;fill:none;stroke:#001e50;stroke-width:1.79999995;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
+ ry="0"
+ rx="0"
+ y="158"
+ x="96.000023"
+ height="2"
+ width="2"
+ id="rect36434"
+ style="fill:#4c8ff4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.3499999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.5;fill:url(#radialGradient36452);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ id="path36436"
+ sodipodi:cx="70.5"
+ sodipodi:cy="14.5"
+ sodipodi:rx="1.5"
+ sodipodi:ry="1.5"
+ d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 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"
+ inkscape:export-ydpi="90" />
+ <path
+ transform="matrix(0.6666679,0,0,0.6666668,49.999915,157.33333)"
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ id="path36438"
+ sodipodi:cx="70.5"
+ sodipodi:cy="14.5"
+ sodipodi:rx="1.5"
+ sodipodi:ry="1.5"
+ d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 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" />
+ <rect
+ style="opacity:0.3;fill:#acc373;fill-opacity:1;fill-rule:nonzero;stroke:#183c00;stroke-width:1.79999995;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="rect36440"
+ width="2.0000153"
+ height="2.0000069"
+ x="102"
+ y="170"
+ rx="0"
+ ry="0" />
+ <rect
+ style="fill:#95e51f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.3499999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36442"
+ width="2"
+ height="2"
+ x="102.00002"
+ y="170"
+ rx="0"
+ ry="0" />
+ <g
+ id="g36444"
+ style="opacity:0.8">
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path36446"
+ d="m 96.5,159.5 0,-1 1,0"
+ style="fill:none;stroke:url(#linearGradient36454);stroke-width:1.00000012;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:none;stroke:url(#linearGradient36456);stroke-width:1.00000012;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 90.499985,171.5 0,-1 1,0"
+ id="path36448"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path36450"
+ d="m 102.49999,171.5 0,-1 1,0"
+ style="opacity:0.9;fill:none;stroke:url(#linearGradient36458);stroke-width:1.00000012;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ transform="translate(105,337.99999)"
+ id="g35291"
+ 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"
+ id="rect35293"
+ width="16"
+ height="16"
+ x="-210"
+ y="-66"
+ transform="scale(-1,-1)" />
+ <g
+ id="g35295"
+ transform="translate(22.999994,19)">
+ <path
+ inkscape:connector-curvature="0"
+ id="path35297"
+ d="m 178.00001,33.5 -1.5,0 L 174,36 c -1.00699,1.006986 -0.0205,3.604505 2.1875,5.8125 2.208,2.207997 4.80551,3.194485 5.8125,2.1875 l 2.50001,-2.5 0,-1.5 -0.75,-1.75 -4,-4 -1.75,-0.75 z"
+ style="fill:url(#linearGradient36648);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ sodipodi:nodetypes="cccscccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path35299"
+ style="fill:url(#linearGradient36650);fill-rule:evenodd;stroke:none"
+ d="m 186.50001,35.5 -2.75,2.75 -1,-1 -1,-1 -1,-1 -1,-1 2.75,-2.75 1.25,0 1.5,1.25 1.25,1.5 0,1.25 z"
+ sodipodi:nodetypes="ccccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path35301"
+ d="m 182.50001,31.5 -2.75,2.75 -1.75,-0.75 -1.5,0 L 174,36 c -1.00699,1.006986 -0.0205,3.604505 2.1875,5.8125 2.208,2.207997 4.80551,3.194485 5.8125,2.1875 l 2.50001,-2.5 0,-1.5 -0.75,-1.75 2.75,-2.75 0,-1 -1.25,-1.75 -1.75,-1.25 -1,0 z"
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="cccccsccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccc"
+ style="fill:none;stroke:url(#linearGradient36652);stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 174.75001,36.5 2.25,-2.25 1.5,0.25 1.5,0.75 1.5,1.25 1.25,1.5 0.75,1.5 0.25,1.5 -1.5,1.5"
+ id="path35303" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#d3c656;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.74147779;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path35305"
+ sodipodi:cx="181"
+ sodipodi:cy="35"
+ sodipodi:rx="1.2111344"
+ sodipodi:ry="4.9951267"
+ d="m 182.21113,35 a 1.2111344,4.9951267 0 1 1 0,-0.01066"
+ 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 a 1.1763829,5.5293522 0 1 1 -2.35276,0 1.1763829,5.5293522 0 1 1 2.35276,0 z"
+ sodipodi:ry="5.5293522"
+ sodipodi:rx="1.1763829"
+ sodipodi:cy="35"
+ sodipodi:cx="181"
+ id="path35307"
+ style="fill:#f3eebb;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.74147779;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="czs"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient36654);stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M 182.25,43.75 C 182.25,42 182,41 179.5,38.5 177,36 175.75,35.75 174.25,35.75"
+ id="path35309" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient36656);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 180.50001,34.5 2,-2 1,0 1,1 1,1 0,1 -2,2"
+ id="path35311"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path35313"
+ d="m 184.50001,41.5 c 0,-1.75 0,-3 -2.5,-5.5 -2.5,-2.5 -4,-2.5 -5.5,-2.5"
+ style="fill:none;stroke:url(#linearGradient36658);stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="czs" />
+ </g>
+ <g
+ id="g35315"
+ style="opacity:0.65">
+ <g
+ id="g35317"
+ transform="translate(21,21)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ style="fill:none;stroke:#2b2600;stroke-width:2.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 174.5,40.5 0,3 3,0"
+ id="path35319" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cz"
+ id="path35321"
+ style="fill:none;stroke:#2b2600;stroke-width:3;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"
+ d="M 175.5,42.5 179,39" />
+ </g>
+ <g
+ transform="matrix(-1,0,0,-1,383,116)"
+ id="g35323">
+ <g
+ style="display:inline"
+ transform="matrix(-1,0,0,-1,272.1613,155.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="g35325">
+ <path
+ inkscape:connector-curvature="0"
+ d=""
+ sodipodi:nodetypes="cz"
+ id="path35327"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cz"
+ id="path35329"
+ style="opacity:0.85;fill:none;stroke:#f4f1d7;stroke-width:1.5;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"
+ d="m 85.6613,103.49999 5,-5" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#fffbd5;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 188,51 0,4 -1,0 0,-3 -3,0 0,-1 4,0 z"
+ id="path35331"
+ sodipodi:nodetypes="ccccccc" />
+ <g
+ id="g35333"
+ style="opacity:0.2"
+ transform="matrix(-1,0,0,1,-29,-335)">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#b5a731;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -216,387 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ id="path35335"
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ </g>
+ </g>
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect35337"
+ width="1.25"
+ height="1.25"
+ x="200.75"
+ y="58" />
+ <rect
+ y="58.75"
+ x="199.75"
+ height="1.5"
+ width="1.5"
+ id="rect35339"
+ style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.5;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect35341"
+ width="1.5"
+ height="1.5"
+ x="198.75"
+ y="59.75" />
+ </g>
+ <g
+ id="g35343"
+ transform="translate(0,-7e-6)">
+ <rect
+ transform="scale(-1,-1)"
+ y="-404"
+ x="-273"
+ height="16"
+ width="16"
+ id="rect35345"
+ 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" />
+ <g
+ mask="url(#mask31861)"
+ id="g35347"
+ transform="translate(63,338)"
+ style="opacity:0.65">
+ <g
+ id="g35349"
+ transform="matrix(0,-1,1,0,104.00001,149.1613)"
+ style="stroke:#9e872a;stroke-opacity:1">
+ <path
+ inkscape:connector-curvature="0"
+ id="path35351"
+ d="m 187.5,53.75 0,-2.25 -2,0"
+ style="fill:none;stroke:#2b2600;stroke-width:2.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ sodipodi:nodetypes="ccc"
+ transform="matrix(0,1,-1,0,149.1613,-83.00001)" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 85.6613,103.49999 5.5,-5.5"
+ style="fill:none;stroke:#2b2600;stroke-width:3;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="path35353"
+ sodipodi:nodetypes="cz"
+ transform="matrix(0,-1,1,0,-6.83869,189.16129)" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ style="fill:none;stroke:#2b2600;stroke-width:2.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 187.5,53.5 0,-2 -2,0"
+ id="path35355"
+ transform="matrix(0,-1,1,0,33.1613,278.99999)" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cz"
+ id="path35357"
+ style="fill:none;stroke:#2b2600;stroke-width:3;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"
+ d="m 85.6613,103.49999 5.5,-5.5"
+ transform="matrix(0,1,-1,0,189.16129,6.83869)" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path35359"
+ d="m 187.5,53.5 0,-2 -2,0"
+ style="fill:none;stroke:#2b2600;stroke-width:2.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ sodipodi:nodetypes="ccc"
+ transform="translate(-89.8387,39.99999)" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 85.6613,103.49999 5.5,-5.5"
+ style="fill:none;stroke:#2b2600;stroke-width:3;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="path35361"
+ sodipodi:nodetypes="cz"
+ transform="matrix(-1,0,0,-1,182.3226,195.99998)" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ style="fill:none;stroke:#2b2600;stroke-width:2.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 187.5,53.5 0,-2 -2,0"
+ id="path35363"
+ transform="matrix(-1,0,0,-1,272.1613,155.99999)" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cz"
+ id="path35365"
+ style="fill:none;stroke:#2b2600;stroke-width:3;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"
+ d="m 85.6613,103.49999 5.5,-5.5" />
+ </g>
+ <g
+ id="g35367"
+ transform="translate(21,0)">
+ <g
+ id="g35369"
+ 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,0,0,-1,272.1613,155.99999)"
+ style="display:inline">
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ id="path35371"
+ sodipodi:nodetypes="cz"
+ d="" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 85.6613,103.49999 5.5,-5.5"
+ style="opacity:0.85;fill:none;stroke:#f4f1d7;stroke-width:1.5;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="path35373"
+ sodipodi:nodetypes="cz" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ id="path35375"
+ d="m 188,51 0,3 -1,0 0,-2 -2,0 0,-1 3,0 z"
+ style="fill:#fffbd5;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ transform="matrix(-1,0,0,1,-29,-335)"
+ style="opacity:0.3"
+ id="g35377">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ id="path35379"
+ d="m -216,387 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ style="fill:#2b2600;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>
+ <g
+ transform="matrix(-1,0,0,-1,383,116)"
+ id="g35381">
+ <g
+ style="display:inline"
+ transform="matrix(-1,0,0,-1,272.1613,155.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="g35383">
+ <path
+ inkscape:connector-curvature="0"
+ d=""
+ sodipodi:nodetypes="cz"
+ id="path35385"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cz"
+ id="path35387"
+ style="opacity:0.85;fill:none;stroke:#f4f1d7;stroke-width:1.5;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"
+ d="m 85.6613,103.49999 5.5,-5.5" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#fffbd5;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 188,51 0,3 -1,0 0,-2 -2,0 0,-1 3,0 z"
+ id="path35391"
+ sodipodi:nodetypes="ccccccc" />
+ <g
+ id="g35393"
+ style="opacity:0.3"
+ transform="matrix(-1,0,0,1,-29,-335)">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#2b2600;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -216,387 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ id="path35395"
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ </g>
+ <g
+ id="g35398"
+ inkscape:transform-center-x="3.125"
+ inkscape:transform-center-y="-3.125"
+ transform="matrix(0,-1,1,0,144,239)">
+ <g
+ id="g35400"
+ 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,0,0,-1,272.1613,155.99999)"
+ style="display:inline">
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ id="path35405"
+ sodipodi:nodetypes="cz"
+ d="" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 85.6613,103.49999 5.5,-5.5"
+ style="opacity:0.85;fill:none;stroke:#f4f1d7;stroke-width:1.5;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="path35407"
+ sodipodi:nodetypes="cz" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ id="path35409"
+ d="m 188,51 0,3 -1,0 0,-2 -2,0 0,-1 3,0 z"
+ style="fill:#fffbd5;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ transform="matrix(-1,0,0,1,-29,-335)"
+ style="opacity:0.3"
+ id="g35411">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ id="path35413"
+ d="m -216,387 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ style="fill:#2b2600;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>
+ <g
+ id="g35415"
+ transform="translate(-16,0)">
+ <path
+ inkscape:connector-curvature="0"
+ d="M 223.5,63.5 218,58"
+ style="opacity:0.85;fill:none;stroke:#f4f1d7;stroke-width:1.5;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="path35417"
+ sodipodi:nodetypes="cz" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#fffbd5;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 225,65 -3,0 0,-1 2,0 0,-2 1,0 0,3 z"
+ id="path35420"
+ sodipodi:nodetypes="ccccccc" />
+ <g
+ id="g35422"
+ style="opacity:0.3"
+ transform="matrix(0,-1,-1,0,611,-152)">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#2b2600;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -216,387 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ id="path35424"
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ transform="translate(139.00002,324)"
+ id="g35426">
+ <g
+ id="g35429"
+ 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 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 z"
+ sodipodi:ry="1.75"
+ sodipodi:rx="1.75"
+ sodipodi:cy="192.5"
+ sodipodi:cx="464.5"
+ id="path35431"
+ style="opacity:0.1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#e9ddaf;stroke-width:0.49999988;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:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.15;fill:#e1d18e;fill-opacity:1;fill-rule:nonzero;stroke:#fffc28;stroke-width:0.38888648;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="path35433"
+ sodipodi:cx="464.5"
+ sodipodi:cy="192.5"
+ sodipodi:rx="1.75"
+ sodipodi:ry="1.75"
+ d="m 466.25,192.5 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 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 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 z"
+ sodipodi:ry="1.75"
+ sodipodi:rx="1.75"
+ sodipodi:cy="192.5"
+ sodipodi:cx="464.5"
+ id="path35437"
+ style="opacity:0.3;fill:#e1d98e;fill-opacity:1;fill-rule:nonzero;stroke:#f0d700;stroke-width:0.50000638;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:type="arc" />
+ <path
+ transform="matrix(1.428566,0,0,1.428566,-197.56891,-81.998957)"
+ d="m 466.25,192.5 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 z"
+ sodipodi:ry="1.75"
+ sodipodi:rx="1.75"
+ sodipodi:cy="192.5"
+ sodipodi:cx="464.5"
+ id="path35439"
+ style="fill:#fbf7e5;fill-opacity:1;fill-rule:nonzero;stroke:#474213;stroke-width:0.63000238;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:type="arc" />
+ </g>
+ </g>
+ <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="rect35441"
+ width="2"
+ height="2"
+ x="264"
+ y="395" />
+ </g>
+ <g
+ transform="translate(147,337.99999)"
+ id="g35443"
+ 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"
+ id="rect35445"
+ width="16"
+ height="16"
+ x="131"
+ y="50" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccc"
+ id="path35447"
+ d="m 144.5,63.5 -1,0 -2.5,-1 -1.5,3 -1,0 -1.5,-3 -2.5,1 -1,10e-7 0,-1.000001 1,-2.5 -3,-1.5 0,-1 3,-1.5 -1,-2.5 0,-1 1,0 2.5,1 1.5,-3 1,0 1.5,3 2.5,-1 1,0 0,1 -1,2.5 3,1.5 0,1 -3,1.5 1,2.5 0,1 z"
+ style="opacity:0.85;fill:#f5efb2;fill-opacity:0.58823529;fill-rule:nonzero;stroke:#38330e;stroke-width:0.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" />
+ <g
+ id="g35449">
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#e9ddaf;stroke-width:0.49999988;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="path35451"
+ sodipodi:cx="464.5"
+ sodipodi:cy="192.5"
+ sodipodi:rx="1.75"
+ sodipodi:ry="1.75"
+ d="m 466.25,192.5 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 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 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 z"
+ sodipodi:ry="1.75"
+ sodipodi:rx="1.75"
+ sodipodi:cy="192.5"
+ sodipodi:cx="464.5"
+ id="path35453"
+ style="opacity:0.3;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#fff6d5;stroke-width:0.38888386;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:type="arc" />
+ <path
+ transform="matrix(2.0000089,0,0,2.0000089,-790.00413,-327.00163)"
+ d="m 466.25,192.5 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 z"
+ sodipodi:ry="1.75"
+ sodipodi:rx="1.75"
+ sodipodi:cy="192.5"
+ sodipodi:cx="464.5"
+ id="path35455"
+ style="fill:#b5a51f;fill-opacity:1;fill-rule:nonzero;stroke:#463f00;stroke-width:0.39999822;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:type="arc" />
+ <rect
+ style="opacity:0.9;fill:#ffed55;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect35457"
+ width="5"
+ height="5"
+ x="136"
+ y="55"
+ rx="2.5"
+ ry="2.5" />
+ <rect
+ ry="1.875"
+ rx="1.875"
+ y="55.25"
+ x="136.25"
+ height="3.75"
+ width="3.75"
+ id="rect35459"
+ style="opacity:0.9;fill:#fbfaef;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="56"
+ x="137"
+ height="2"
+ width="2"
+ id="rect35461"
+ style="opacity:0.9;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+ <g
+ transform="translate(189,295.99999)"
+ id="g35463"
+ style="display:inline;enable-background:new">
+ <rect
+ y="92"
+ x="152"
+ height="16"
+ width="16"
+ id="rect35465"
+ 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="g35467"
+ transform="matrix(1.6519496,0,0,1.6519309,-230.47015,-63.200317)"
+ style="opacity:0.25;display:inline;filter:url(#filter30564);enable-background:new"
+ clip-path="url(#clipPath31849)">
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.1;fill:#e1d18e;fill-opacity:1;fill-rule:nonzero;stroke:#fff6aa;stroke-width:0.26988116;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="path35469"
+ sodipodi:cx="464.5"
+ sodipodi:cy="192.5"
+ sodipodi:rx="1.75"
+ sodipodi:ry="1.75"
+ d="m 466.25,192.5 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 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 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 z"
+ sodipodi:ry="1.75"
+ sodipodi:rx="1.75"
+ sodipodi:cy="192.5"
+ sodipodi:cx="464.5"
+ id="path35471"
+ style="opacity:0.25;fill:#e1d18e;fill-opacity:1;fill-rule:nonzero;stroke:#ffe400;stroke-width:0.31863192;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:type="arc" />
+ <path
+ transform="matrix(1.5591172,0,0,1.559203,-486.06699,-203.16445)"
+ d="m 466.25,192.5 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 z"
+ sodipodi:ry="1.75"
+ sodipodi:rx="1.75"
+ sodipodi:cy="192.5"
+ sodipodi:cx="464.5"
+ id="path35473"
+ style="fill:#ffeeaa;fill-opacity:1;fill-rule:nonzero;stroke:#b4b200;stroke-width:0.38825312;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:type="arc" />
+ </g>
+ <g
+ id="g35477"
+ style="opacity:0.6"
+ transform="translate(-55,-1)">
+ <g
+ id="g35480">
+ <path
+ inkscape:connector-curvature="0"
+ id="path35482"
+ d="m 219.5,102 0,4.5"
+ style="fill:none;stroke:#2b2600;stroke-width:2.5;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"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path35484"
+ d="m 221.75,105.25 -2.25,2.25 -2.25,-2.25"
+ style="fill:none;stroke:#2b2600;stroke-width:2.79999995;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>
+ <g
+ id="g35486">
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.85;fill:none;stroke:#f4f1d7;stroke-width:1;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"
+ d="m 219.5,101.5 0,5.5"
+ id="path35488"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#ffffd5;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 221.75,105.25 -2.25,2.25 -2.25,-2.25"
+ id="path35490"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ </g>
+ <g
+ style="opacity:0.6"
+ id="g35493"
+ transform="matrix(0,1,-1,0,261,-124)">
+ <g
+ id="g35496">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#2b2600;stroke-width:2.5;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"
+ d="m 219.5,102 0,4.5"
+ id="path35498" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#2b2600;stroke-width:2.79999995;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"
+ d="m 221.75,105.25 -2.25,2.25 -2.25,-2.25"
+ id="path35500"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <g
+ id="g35502">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path35504"
+ d="m 219.5,101.5 0,5.5"
+ style="opacity:0.85;fill:none;stroke:#f4f1d7;stroke-width:1;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" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path35506"
+ d="m 221.75,105.25 -2.25,2.25 -2.25,-2.25"
+ style="fill:none;stroke:#ffffd5;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ </g>
+ <g
+ id="g35508"
+ style="opacity:0.65;display:inline;enable-background:new"
+ transform="translate(-41,41)">
+ <g
+ id="g35510"
+ transform="translate(21,21)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ style="fill:none;stroke:#2b2600;stroke-width:2.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 174.5,40.5 0,3 3,0"
+ id="path35512" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cz"
+ id="path35514"
+ style="fill:none;stroke:#2b2600;stroke-width:3;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"
+ d="m 175.5,42.5 5.75,-5.75" />
+ </g>
+ <g
+ transform="matrix(-1,0,0,-1,383,116)"
+ id="g35516">
+ <g
+ style="display:inline"
+ transform="matrix(-1,0,0,-1,272.1613,155.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="g35518">
+ <path
+ inkscape:connector-curvature="0"
+ d=""
+ sodipodi:nodetypes="cz"
+ id="path35520"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cz"
+ id="path35522"
+ style="opacity:0.85;fill:none;stroke:#f4f1d7;stroke-width:1.5;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"
+ d="m 85.6613,103.49999 6.25,-6.25" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#fffbd5;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 188,51 0,4 -1,0 0,-3 -3,0 0,-1 4,0 z"
+ id="path35524"
+ sodipodi:nodetypes="ccccccc" />
+ <g
+ id="g35526"
+ style="opacity:0.2"
+ transform="matrix(-1,0,0,1,-29,-335)">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#b5a731;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -216,387 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ id="path35528"
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ </g>
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path35530"
+ d="m 161.5,95.5 3,3"
+ style="opacity:0.15;fill:#e1d18e;fill-opacity:1;fill-rule:nonzero;stroke:#ffeeaa;stroke-width:5;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;filter:url(#filter30556);enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.25;fill:#ffdd55;fill-opacity:1;fill-rule:nonzero;stroke:#ffed55;stroke-width:4;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;filter:url(#filter30552);enable-background:accumulate"
+ d="m 161.5,94.5 4,4"
+ id="path35532"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path35534"
+ d="m 161.5,93.5 5,5"
+ style="fill:none;stroke:#5a5310;stroke-width:3.29999995;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:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#fbf7e5;stroke-width:1.60000002;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 161.5,93.5 5,5"
+ id="path35536"
+ sodipodi:nodetypes="cc" />
+ </g>
+ <g
+ transform="translate(168,274.99999)"
+ id="g35538"
+ 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"
+ id="rect35540"
+ width="16"
+ height="16"
+ x="152"
+ y="113.00001" />
+ <g
+ id="g35542"
+ transform="translate(-21,21.000005)">
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.12000002;fill:#fff6aa;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter30544);enable-background:accumulate"
+ d="m 177,94.75 c 0,0 -0.47556,3.774441 2.5,6.75 2.97556,2.97556 7,2.5 7,2.5 3.44436,-0.63991 2.99995,-3.42845 0.0937,-4.5 -1.83387,-3.557342 -2.66053,-4.290113 -5.09375,-5.09375 -0.64623,-3.372957 -3.91818,-2.771894 -4.5,0.34375 l 5e-5,0 z"
+ id="path35544"
+ sodipodi:nodetypes="cscccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.17000002;fill:#ffed55;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter30580);enable-background:accumulate"
+ d="m 179.15625,93.71875 c 0,0 -0.3702,1.0264 -0.21875,2.1875 0.15145,1.1611 0.76936,2.613109 2.15625,4 1.38689,1.38689 2.8389,2.0048 4,2.15625 1.1611,0.15145 2.1875,-0.21875 2.1875,-0.21875 1.01828,-0.43147 1.49397,-1.60672 1.0625,-2.625 l -5.65501,-5.846474 c -1.32148,-1.409979 -2.40864,-0.889298 -3.53249,0.346474 z"
+ id="path35546"
+ sodipodi:nodetypes="cssscccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cssscccc"
+ id="path35548"
+ d="m 179.15625,93.71875 c 0,0 -0.3702,1.0264 -0.21875,2.1875 0.15145,1.1611 0.76936,2.613109 2.15625,4 1.38689,1.38689 2.8389,2.0048 4,2.15625 1.1611,0.15145 2.1875,-0.21875 2.1875,-0.21875 1.01828,-0.43147 1.49397,-1.60672 1.0625,-2.625 l -5.65501,-5.846474 c -1.32148,-1.409979 -2.40864,-0.889298 -3.53249,0.346474 z"
+ style="opacity:0.18000004;fill:#fff6aa;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter30580);enable-background:accumulate"
+ transform="matrix(0.5121167,0,0,0.5121167,89.625148,47.477443)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#5a5310;stroke-width:3.0999999;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 176.5,93.5 c 0,0 5.75,-0.25 8.5,2.5 2.75,2.75 2.5,8.5 2.5,8.5"
+ id="path35550"
+ sodipodi:nodetypes="czs" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="czs"
+ id="path35552"
+ d="m 176.5,93.5 c 0,0 5.75,-0.25 8.5,2.5 3,3 2.5,8.5 2.5,8.5"
+ style="fill:none;stroke:#fbf7e5;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" />
+ </g>
+ <g
+ id="g35554"
+ style="opacity:0.65;display:inline;enable-background:new"
+ transform="translate(-42,63.000005)">
+ <g
+ id="g35556"
+ transform="translate(21,21)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ style="fill:none;stroke:#2b2600;stroke-width:2.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 174.5,40.5 0,3 3,0"
+ id="path35558" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cz"
+ id="path35561"
+ style="fill:none;stroke:#2b2600;stroke-width:3;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"
+ d="m 175.5,42.5 6.25,-6.25" />
+ </g>
+ <g
+ transform="matrix(-1,0,0,-1,383,116)"
+ id="g35563">
+ <g
+ style="display:inline"
+ transform="matrix(-1,0,0,-1,272.1613,155.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="g35566">
+ <path
+ inkscape:connector-curvature="0"
+ d=""
+ sodipodi:nodetypes="cz"
+ id="path35568"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cz"
+ id="path35570"
+ style="opacity:0.85;fill:none;stroke:#f4f1d7;stroke-width:1.5;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"
+ d="m 85.6613,103.49999 7,-7" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#fffbd5;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 188,51 0,4 -1,0 0,-3 -3,0 0,-1 4,0 z"
+ id="path35572"
+ sodipodi:nodetypes="ccccccc" />
+ <g
+ id="g35574"
+ style="opacity:0.2"
+ transform="matrix(-1,0,0,1,-29,-335)">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#b5a731;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -216,387 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ id="path35576"
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ id="g36448"
+ transform="translate(41.84997,0.15003049)">
+ <g
+ transform="translate(105,416)"
+ id="g36297">
+ <g
+ id="g36211"
+ transform="translate(194.04507,17.48225)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path36215"
+ d="m 90.45451,103.98095 0,7 7.00045,0.0368 0,-7 -7.00045,-0.0368 z"
+ style="opacity:0.8;fill:none;stroke:#333333;stroke-width:2.5;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:#cccccc;fill-opacity:0.15686275;fill-rule:evenodd;stroke:#e6e6e6;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 90.45451,103.98095 4.5e-4,7.03677 7,0 -4.5e-4,-7.03677 -7,0 z"
+ id="path36228"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ rx="1.4999386"
+ ry="1.4999386"
+ y="127.49997"
+ x="290.50015"
+ height="3"
+ width="2.9998772"
+ id="rect36230"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.29999995;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:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.29999995;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="rect36232"
+ width="2.9998772"
+ height="3"
+ x="282.49982"
+ y="119.5"
+ ry="1.4999386"
+ rx="1.4999386" />
+ <rect
+ rx="1.4999386"
+ ry="1.4999386"
+ y="127.49997"
+ x="282.50015"
+ height="3"
+ width="2.9998772"
+ id="rect36234"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.29999995;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
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 293.0003,127.99997 c -0.6694,0 -1.3388,10e-6 -2.0082,10e-6 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 l 0,0 0,0 0,0 z"
+ id="path36237"
+ 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="path36239"
+ d="m 285.00045,128 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:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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="path36241"
+ d="m 285,120 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:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.29999995;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="rect36243"
+ width="2.9998772"
+ height="3"
+ x="290.49988"
+ y="119.49997"
+ ry="1.4999386"
+ rx="1.4999386" />
+ <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="path36245"
+ d="m 293.00003,119.99997 c -0.6694,0 -1.3388,10e-6 -2.0082,10e-6 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 l 0,0 0,0 0,0 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ </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="rect36312"
+ width="16"
+ height="16"
+ x="383"
+ y="535" />
+ <g
+ id="g36314"
+ transform="translate(334.99992,111)">
+ <rect
+ y="429.54614"
+ x="48.499996"
+ height="9.9538488"
+ width="10.000013"
+ id="rect36316"
+ style="fill:#ececec;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(#linearGradient36468);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00207269;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36318"
+ width="9.0000706"
+ height="9.0003176"
+ x="49.000011"
+ y="430" />
+ <path
+ sodipodi:nodetypes="ccccccccccccccccccccccccc"
+ id="path36320"
+ d="m 49,430 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 m -6,3 0,-3 -3,0 0,3 3,0 z"
+ style="fill:url(#linearGradient36470);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" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path36324"
+ d="m 57.50001,430.49999 -8.000011,10e-6 1.1e-5,7.99999 8,0 -1.1e-5,-7.99999"
+ style="fill:none;stroke:url(#linearGradient36472);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </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" />
+ <g
+ transform="translate(1,0)"
+ id="g35733">
+ <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" />
+ <g
+ transform="translate(179,-179)"
+ id="g35741">
+ <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" />
+ <path
+ 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="path35745"
+ inkscape:connector-curvature="0" />
+ </g>
+ <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" />
+ </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" />
+ <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" />
+ </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" />
+ <g
+ id="g35757"
+ transform="translate(1,0)">
+ <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" />
+ <g
+ id="g35765"
+ transform="translate(179,-179)">
+ <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" />
+ <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:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ <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" />
+ </g>
+ <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" />
+ <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" />
+ </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">
+ <g
+ transform="translate(111,-158)"
+ id="g35778"
+ style="opacity:0.55;display:inline">
+ <rect
+ y="336"
+ x="-64"
+ height="16"
+ width="16"
+ id="rect35780"
+ style="opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g35782"
+ transform="translate(1,0)">
+ <g
+ id="g35785"
+ transform="translate(-386,446.5)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:#552200;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 329.5,-108.25 -5.5,2 0,6.75 5.5,3 5.5,-3 0,-6.75 -5.5,-2 z"
+ id="path35787" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ id="path35789"
+ d="m 324,-99.5 0,-7 6,-1.75 0,11.5 -0.5,0.25 -5.5,-3 z"
+ style="fill:#c9c9c9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06898749px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="cccccc" />
+ <g
+ id="g35791"
+ transform="translate(179,-179)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc"
+ id="path35793"
+ d="m 156,79.5 0,-7 -5,-1.75 0,11.5 5,-2.75 z"
+ style="fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89401144px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path35795"
+ d="m 145,72.5 5.5,-2 5.5,2 -5.5,2.5 -5.5,-2.5 z"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ sodipodi:nodetypes="ccccc"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc"
+ id="path35797"
+ d="m 334.5,-106.5 0,6.75 -5,2.75 -5,-2.75 0,-6.75"
+ style="fill:none;stroke:url(#linearGradient36725);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <rect
+ y="342"
+ x="-57"
+ height="7.75"
+ width="1"
+ id="rect35799"
+ style="fill:url(#linearGradient36727);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path35801"
+ d="m -61,340.65468 c 0,0 4.5,2 4.5,2 l 4.5,-2"
+ style="fill:none;stroke:url(#linearGradient36729);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ </g>
+ <rect
+ style="opacity:0.07999998;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37868-0-4-8"
+ width="3.0000007"
+ height="7.25"
+ x="54"
+ y="185" />
+ <g
+ id="g35818"
+ style="fill:#ffeeaa;display:inline"
+ transform="translate(-1080.9861,-256)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc"
+ style="fill:#ffb769;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"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path35822"
+ d="m 1136.4859,448.5 -6,-3.25 0,-7.5"
+ style="fill:none;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>
+ <g
+ transform="matrix(-1,0,0,1,532,25)"
+ id="g37386"
+ 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="rect37388"
+ width="16"
+ height="16"
+ x="343"
+ y="195" />
+ <g
+ 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(-2.196282,0,0,1.316799,1208.5661,-118.9575)"
+ id="g37390"
+ style="display:inline">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path37392"
+ d="m 392.96689,239.5639 -0.56915,0 -4.43932,4.36665 0,1.13912 4.43932,4.36665 0.56911,-1e-5 0,-9.87242 0,0 4e-5,1e-5 0,0 z"
+ style="fill:url(#linearGradient37396);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.58802557px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path37394"
+ d="m 392.51157,247.91748 0,-7.59417 -4.09783,3.98695 0,0.3797"
+ style="fill:none;stroke:url(#linearGradient37398);stroke-width:0.58802563px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ 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"
+ 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"
+ id="rect38783"
+ width="16"
+ height="16"
+ x="-259"
+ y="72" />
+ <path
+ sodipodi:nodetypes="csasc"
+ id="path38785"
+ d="m -257.5,83.5 2,0 c 2,0 2.50929,2 4,2 1.49071,0 2,-2 4,-2 l 2,0"
+ style="fill:none;stroke:#001c46;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" />
+ <path
+ style="fill:none;stroke:#aaccff;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 -257.5,83.5 2,0 c 2,0 2.50929,2 4,2 1.49071,0 2,-2 4,-2 l 2,0"
+ id="path38787"
+ sodipodi:nodetypes="csasc"
+ inkscape:connector-curvature="0" />
+ <g
+ style="display:inline;enable-background:new"
+ transform="matrix(1,0,0,-1,-235,265)"
+ id="g38789">
+ <path
+ transform="translate(-1,2)"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;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 -16,180 0,6 -1,0 0,-1.75 -1,1.75 0,1.5 2,2.5 6,0 1,-2 0,-3.25 -0.75,-0.75 -0.25,0 0,1 -1,0 0,-1 -0.75,-0.75 -0.25,0 0,1.75 -1,0 0,-1.5 -0.75,-1 -0.25,0 0,2.5 -1,0 0,-5 -1,0 z"
+ id="path38791"
+ sodipodi:nodetypes="cccccccccccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g38794"
+ transform="translate(-1,2)">
+ <path
+ sodipodi:nodetypes="ccccccccccccccccccccccccccc"
+ id="path38796"
+ d="m -16,179.5 0,6.5 -1,0 0,-2 -0.25,0 -0.75,2 0,1.5 2,2.5 6,0 1,-2 0,-3.25 -0.75,-0.75 -0.25,0 0,1 -1,0 0,-1 -0.75,-0.75 -0.25,0 0,1.75 -1,0 0,-1.5 -0.75,-1 -0.25,0 0,2.5 -1,0 0,-5.5 -1,0 z"
+ style="fill:url(#linearGradient39048);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.40000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.40000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -15,187 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z m 2,0 0,1 1,0 0,-1 -1,0 z"
+ id="path38799"
+ sodipodi:nodetypes="ccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path38801"
+ d="m -15,185 0,1 1,0 0,-1 -1,0 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.40000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.40000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -13,185 0,1 1,0 0,-1 -1,0 z"
+ id="path38803"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path38805"
+ d="m -11,185 0,1 1,0 0,-1 -1,0 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.40000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient39050);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.40000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -18,186 0,1 1,0 0,-3 -0.25,0 -0.75,2 z"
+ id="path38807"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path38810"
+ d="m -17.25,187.5 1.5,2 5.25,0 1,-2 0,-0.5"
+ style="fill:none;stroke:url(#linearGradient39052);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" />
+ <path
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.40000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -14.00935,182.77669 0,1 1,0 0,-1 -1,0 z"
+ id="path38819"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path38821"
+ d="m -11.978216,183.55574 0,1 1,0 0,-1 -1,0 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.40000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.40000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -11.978216,183.55574 0,1 1,0 0,-1 -1,0 z"
+ id="path38823"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path38825"
+ d="m -16,180 0,1 1,0 0,-1 -1,0 z"
+ style="opacity:0.2;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.40000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g39803"
+ transform="translate(-66,268)"
+ inkscape:export-filename="C:\Documents and Settings\Pracownia\Pulpit\sss.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ y="-27"
+ x="155"
+ height="16"
+ width="15.999955"
+ id="rect39805"
+ 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" />
+ <g
+ style="opacity:0.6;display:inline;enable-background:new"
+ id="g39807">
+ <path
+ style="fill:url(#linearGradient39835-9);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:1;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:new"
+ d="m 157.5,-26.5 c -1.10457,0 -2,0.895431 -2,2 0,1.104569 0.89543,2 2,2 0.0211,0 0.0415,6.5e-4 0.0625,0 0.005,0.02296 0.0259,0.03977 0.0312,0.0625 -0.63487,0.174633 -1.09375,0.747145 -1.09375,1.4375 0,0.828426 0.67157,1.5 1.5,1.5 0.69036,0 1.26287,-0.45888 1.4375,-1.09375 0.18381,0.04305 0.36556,0.09375 0.5625,0.09375 1.38071,0 2.5,-1.119289 2.5,-2.5 0,-1.380711 -1.11929,-2.5 -2.5,-2.5 -0.25351,0 -0.48817,0.05484 -0.71875,0.125 -0.32553,-0.663426 -0.9924,-1.125 -1.78125,-1.125 l 5e-5,0 z"
+ id="path39809"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(0,0.1250004,0.1250004,0,143.24995,-37.50005)"
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient39837-4);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ id="path39811"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path39813"
+ style="fill:url(#linearGradient39839-3);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ sodipodi:type="arc"
+ transform="matrix(0,0.25,0.2500001,0,130.49998,-56)" />
+ </g>
+ <g
+ transform="translate(45,-100)"
+ id="g39815">
+ <path
+ style="fill:#214478;stroke:none"
+ d="m 110.5,85.5 c 0,2.25 2,3 3.5,3 2.25,0 3.1933,-1.514034 4,-2.5 l 4.5,-5.5 3,0 0,-2 -4,0 -5.5,5.5 -1.25,-1.5 -3.25,0 -1,1 0,2 z"
+ id="path39817"
+ sodipodi:nodetypes="cszccccccccz"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cszccccccccz"
+ id="path39819"
+ d="m 110.5,85.5 c 0,2.25 2,3 3.5,3 2.25,0 3.46788,-1.244422 4.25,-2.25 L 120,84 l -2,-2 -1.5,1.5 -1,0 0,-1 -1,-1 -3,0 -1,1 0,3 z"
+ style="fill:url(#linearGradient39841-3);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cszccccccccccccccccz"
+ id="path39821"
+ d="m 110.5,85 c 0,2.25 1.5,3.5 3.75,3.5 2.25,0 3.50071,-1.469729 4.25,-2.5 l 4,-5.5 0.5,0 0.5,0 1,0 1,0 0,-2 -1,0 -1.11272,0 -0.88728,0 -1,0 -5,5 -1,0 0,-1 -1,-1 -3,0 -1,1 0,2.5 z"
+ style="fill:none;stroke:#0b1728;stroke-width:0.80000001;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path39823"
+ d="m 118,83 1,0 0,1 1,0 0,-1 -1,0 0,-1 -1,0 0,1 z"
+ style="fill:url(#linearGradient39843-3);stroke-width:1px"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path39825"
+ d="m 111.5,82.5 0.75818,0.763059 1.5,0 0.75,-0.75"
+ style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="82"
+ x="112"
+ height="1"
+ width="2"
+ id="rect39827"
+ style="opacity:0.6;fill:#000000;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
+ <rect
+ y="83.5"
+ x="115"
+ height="1.4999981"
+ width="0.99994147"
+ id="rect39829"
+ style="opacity:0.4;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" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path39831"
+ d="m 124.5,79.5 -3,0 -5,5 -0.5,0"
+ style="opacity:0.4;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccsc"
+ id="path39833"
+ d="m 111.5,83.5 0,1.271428 c -0.0915,0.859266 0.18827,2.299909 2.00056,2.733557 3.70517,0.886581 6.00049,-3.943221 6.00049,-3.943221"
+ style="fill:none;stroke:url(#linearGradient39845-2);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(-249,193)"
+ id="g41505"
+ style="display:inline">
+ <g
+ style="opacity:0.85"
+ id="g41507">
+ <rect
+ style="opacity:0.5;fill:url(#linearGradient41540);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect41509"
+ width="7.8166504"
+ height="3"
+ x="-433.5"
+ y="82"
+ transform="scale(-1,1)" />
+ <rect
+ style="fill:url(#linearGradient41542);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect41511"
+ width="8.9931746"
+ height="1"
+ x="-434"
+ y="83"
+ transform="scale(-1,1)" />
+ <rect
+ style="fill:#333333;fill-opacity:0.81960784;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect41514"
+ width="2"
+ height="1"
+ x="-430.5"
+ y="83"
+ transform="scale(-1,1)" />
+ </g>
+ <g
+ id="g41613"
+ style="opacity:0.45">
+ <g
+ style="opacity:0.8"
+ id="g41516">
+ <rect
+ y="69"
+ x="422"
+ height="16"
+ width="16"
+ id="rect41518"
+ style="opacity:0.05;fill:url(#radialGradient41666);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g41520">
+ <path
+ sodipodi:nodetypes="csscccc"
+ id="path41522"
+ d="m 422.51387,74.4375 c 2.14278,1.6383 5.29475,5.652 6.25,7.5625 0.5,1 1.05394,1.01957 1.5,0 0.875,-2 3.25,-4.75 4.75,-6 l -3.5,-4 c -1.25,1.83839 -2,3.25 -2.75,4.63304 -1.71617,-1.72583 -4.35859,-3.39262 -6.25,-4.13304"
+ style="fill:url(#linearGradient41668);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient41670);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" />
+ </g>
+ </g>
+ <g
+ id="g41524">
+ <g
+ id="g41526">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path41528"
+ d="m 422.51387,73.5 c 1.93909,0.815624 4.07262,1.664731 6,4 l 0.75,0 c 0.82427,-1.547027 1.51287,-2.596571 2.16161,-3.5"
+ style="fill:none;stroke:url(#linearGradient41672);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient41674);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+ d="m 422.51387,73.5 c 1.93909,0.815624 5.41183,5.25 7,8 1.5,-3 2.75,-4 4.75,-6.25"
+ id="path41530"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient41676);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 428.5,78.5 c 0.95165,-1.519624 1.88025,-3.040081 2.92548,-4.5"
+ id="path41532"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient41582);fill-opacity:1;fill-rule:evenodd;stroke:#0b1728;stroke-width:2.07584167;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="path32513-1"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.4336871,0,0,0.4334311,376.83381,21.772579)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient32529-7);stroke-width:3.1984036;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="path32517-6"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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">
+ <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" />
+ <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" />
+ </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"
+ transform="translate(41.834175,191.41501)">
+ <rect
+ y="364.58499"
+ x="47.165825"
+ height="16"
+ width="16"
+ id="rect38701"
+ 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"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ transform="matrix(1.032664,0,0,1.043556,-79.760429,254.38542)"
+ id="g38703">
+ <path
+ transform="matrix(0.787566,0,0,0.779223,26.709197,21.3179)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path38705"
+ style="fill:#3771c8;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:1.22966909;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(0.666432,0,0,0.659342,42.69924,35.46375)"
+ 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:type="arc"
+ style="fill:url(#linearGradient38719);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path38707"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z" />
+ <path
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path38709"
+ style="opacity:0.7;fill:url(#linearGradient38722);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ 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.3631382,0,0,0.3593485,81.755824,69.904768)" />
+ <path
+ transform="matrix(0.9688184,0,0,0.9547322,-131.63668,47.640696)"
+ style="opacity:0.5;fill:none;stroke:#ffe680;stroke-width:1.00161445px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;filter:url(#filter13996)"
+ d="m 274.98515,70.995347 c 0,0.953349 -1,1.906699 -2,1.906699"
+ id="path38711"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient38724);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 130.67404,112.3079 c 0.0244,0.78706 -0.15754,1.63085 0.59269,2.02213 0.71197,-0.0434 1.49133,0.64122 1.35667,1.40517 -0.26776,0.77861 0.14071,1.12325 0.95576,1.36401 0.57868,-0.0716 0.79053,-0.93546 0.87357,-1.36401 0.0948,-1.27121 0.51542,-1.09421 0.82108,-1.98991 -0.45733,-0.91502 -0.003,-1.04443 -0.72629,-1.43739 m -1.00945,-3.89288 c -0.4426,0.34378 -0.24372,1.04314 -0.66162,1.39841 -0.45372,0.13628 -0.78226,-0.0605 -1.16771,0.43164 -0.30841,1.10457 0.35004,1.22306 0.90205,1.10457 0.49538,-0.0502 0.61419,-0.94321 0.97928,-0.37853 0.0831,0.10976 0.71917,-0.0403 0.86266,0.18898 0.0669,0.10682 -0.11785,0.0255 -0.14729,0.18955 -0.0428,0.23847 0.27734,0.37341 0.372,0.3824 0.32089,0.0305 0.60005,0.92548 0.83846,1.05499 0,0.46738 0.0924,-0.6774 0.3515,-0.78703 0.22948,-0.0971 0.47929,0.10731 0.5,0 0.29928,-1.55081 -1.26113,-3.00604 -2.82933,-3.58498 z M 128.96474,107.5 c -0.6111,1.01384 0.85343,1.46103 1.73001,1.21329 0.57897,-0.37879 1.00716,-0.92331 0.55665,-1.21329 -0.20614,-0.1415 -2.07706,0.0431 -2.28666,0 l 0,0 0,0 0,0 z m -1.372,1.37253 c -0.49575,-0.14959 0.44952,-0.11945 0.45733,0.45751 0.1696,0.54756 -0.42801,0.23756 0,0.45752 0.70893,0.1644 0.35328,1.70031 -0.28114,1.56208 -0.56042,0.10119 -0.43915,0.95826 -1.64865,0.88279 -0.0836,0.0755 -1.04512,0.61593 -0.81421,1.21521 1.12968,0.30162 -0.36816,1.26478 -0.43867,0.55236 -0.15441,-0.49797 -0.62853,-1.11348 -0.43994,-1.68674 0.11734,-0.63627 0.5689,-1.12263 0.82646,-1.69865 0.36225,-0.61946 0.89084,-1.17688 1.57758,-1.42595 0.21411,-0.16799 0.46159,-0.41691 0.76124,-0.31613 l 0,0 0,0 0,0 z m -0.91467,5.03262 c -0.55163,-0.27585 -0.72934,0.28829 -0.60377,0.7984 0.15577,0.47138 0.52607,0.97695 0.72628,1.43739 0.40435,0.49619 1.512,1.34081 2.17883,1.67696 0.31768,0.16015 0.48418,0 0.24209,-0.23956 -0.31367,-0.6375 -1.14073,-1.94893 -0.48418,-2.15609 0.59647,-0.60342 0.34203,-1.58773 -0.48419,-1.43739 -0.54779,-0.25818 -0.75551,-0.39899 -1.38855,-0.0752 -0.0558,0.0743 -0.12403,0.006 -0.18651,-0.004 l 0,-5.1e-4 0,0 0,0 z"
+ id="path38713"
+ sodipodi:nodetypes="ccccccccccccssscsscccscccccccccccccccsccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(0.6657538,0,0,0.6588051,42.794535,35.527157)"
+ sodipodi:type="arc"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient38726);stroke-width:1.45454657;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="path38715"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(0.06052282,0,0,0.05989117,121.21686,103.80334)"
+ 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:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path38717"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z" />
+ </g>
+ </g>
+ <g
+ transform="translate(179.00003,444.99999)"
+ id="g37955"
+ style="display:inline">
+ <rect
+ y="90"
+ x="162"
+ height="16"
+ width="16"
+ id="rect37957"
+ 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="96.749977"
+ x="165.74995"
+ height="1.75"
+ width="2.5"
+ id="rect37959"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#1a1a1a;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
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 164.99996,98.99998 6,-2.5 6,2.5 0,2.75 -5.99999,3.24999 -6.00001,-3.24999 0,-2.75 z"
+ id="path37961"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.96000001;fill:none;stroke:#1a1a1a;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"
+ id="rect37963"
+ width="2"
+ height="7"
+ x="170.98643"
+ y="91.999977" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:#808080;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 164.99996,98.99998 6,-2.5 6,2.5 0,0.5 -6,3 -6,-2.93442 0,-0.56558 z"
+ id="path37965"
+ 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="path37967"
+ d="m 164.99997,101.74998 -1e-5,-2.25 6,3 0.01,2.49885 -6.00995,-3.24885 -4e-5,0 0,0 0,0 z"
+ style="fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ sodipodi:nodetypes="ccccc"
+ 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:#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 176.99996,101.74998 0,-2.25 -6,3 c 0,2.58362 0,1.9329 0,2.5 l 6,-3.25 z"
+ id="path37969"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="97.999977"
+ x="165.99995"
+ height="1"
+ width="2"
+ id="rect37971"
+ style="fill:#aa0000;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:#ff2a2a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37973"
+ width="2"
+ height="1"
+ x="165.99995"
+ y="96.999977" />
+ <rect
+ y="96.999977"
+ x="165.99995"
+ height="2"
+ width="1"
+ id="rect37975"
+ style="opacity:0.5;fill:#ffaaaa;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ style="fill:none;stroke:url(#linearGradient38005);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 165.49996,99.49998 0,0 0,2 5.5,3 5.5,-3 0,-2"
+ id="path37977"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g37979"
+ transform="translate(-114.00004,-232.99999)">
+ <rect
+ y="328.03571"
+ x="285"
+ height="3.9642856"
+ width="2"
+ id="rect37981"
+ style="opacity:0.3;fill:none;stroke:#1a1a1a;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" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#550000;stroke-width:0.59999985;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="path37983"
+ sodipodi:cx="286"
+ sodipodi:cy="325"
+ sodipodi:rx="1.5"
+ sodipodi:ry="1.5"
+ d="m 287.5,325 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 z"
+ transform="matrix(1.6666708,0,0,1.6666633,-190.66784,-215.66559)" />
+ <rect
+ y="328.49997"
+ x="285"
+ height="3.5000324"
+ width="2"
+ id="rect37985"
+ style="fill:#b3b3b3;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:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37987"
+ width="1"
+ height="3.5000324"
+ x="285"
+ y="328.49997" />
+ <path
+ transform="matrix(1.333351,0,0,1.333345,-95.338377,-107.33714)"
+ d="m 287.5,325 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 z"
+ sodipodi:ry="1.5"
+ sodipodi:rx="1.5"
+ sodipodi:cy="325"
+ sodipodi:cx="286"
+ id="path37989"
+ style="fill:url(#linearGradient38007);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.59999985;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <rect
+ style="opacity:0.5;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="rect37991"
+ width="1"
+ height="1"
+ x="284"
+ y="331" />
+ <rect
+ y="332"
+ x="285"
+ height="1"
+ width="2"
+ id="rect37993"
+ style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="331"
+ x="287"
+ height="1"
+ width="1"
+ id="rect37995"
+ style="opacity:0.5;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>
+ <path
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 165.49996,98.99998 5.5,2.75"
+ id="path37997"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g37999"
+ mask="url(#mask20957)">
+ <path
+ style="opacity:0.7;fill:none;stroke:#1a1a1a;stroke-width:2.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 168.25,102.75 -0.75,0.75 c -1,1 -0.75,1 -2,1 l -2.25,0"
+ id="path38001"
+ sodipodi:nodetypes="cccc"
+ mask="none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path38003"
+ d="m 168.25,102.75 -0.75,0.75 c -1.25,1.17188 -0.75,1 -2,1 l -3,0"
+ style="fill:none;stroke:#ececec;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ 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"
+ transform="translate(588,446)">
+ <rect
+ y="26"
+ x="-79"
+ height="16"
+ width="16"
+ id="rect43390-2"
+ style="opacity:0;fill:#999999;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="g43392-4"
+ clip-path="url(#clipPath43368-1)">
+ <rect
+ style="fill:#ec0606;fill-opacity:1;fill-rule:nonzero;stroke:#910000;stroke-width:0.80000001;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"
+ id="rect43394-5"
+ width="6"
+ height="2"
+ x="-72.5"
+ y="31.5"
+ rx="0.79505396"
+ ry="0.79505396" />
+ <rect
+ ry="0.79505396"
+ rx="0.79505396"
+ y="28.5"
+ x="-75.5"
+ height="2"
+ width="6"
+ id="rect43396-5"
+ style="fill:#6996d7;fill-opacity:1;fill-rule:nonzero;stroke:#143564;stroke-width:0.80000001;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" />
+ <rect
+ style="fill:#6996d7;fill-opacity:1;fill-rule:nonzero;stroke:#143564;stroke-width:0.80000001;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"
+ id="rect43398-1"
+ width="6"
+ height="2"
+ x="-75.5"
+ y="36.5"
+ rx="0.74381745"
+ ry="0.74381745" />
+ <rect
+ ry="0.71819919"
+ rx="0.71819919"
+ y="39.5"
+ x="-72.5"
+ height="2"
+ width="6"
+ id="rect43400-7"
+ style="fill:#ec0606;fill-opacity:1;fill-rule:nonzero;stroke:#910000;stroke-width:0.80000001;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" />
+ <path
+ id="path43402-1"
+ style="fill:none;stroke:#000000;stroke-width:2.9000001;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m -68.50037,45.540088 c 0,-2 -5,-2 -5,-4 0,-2.030484 5.00037,-2 4.99787,-4.040088 0.002,-2 -4.9975,-2 -4.9975,-4 0,-2.030484 5.005,-1.959912 5,-4 0,-2 -5,-2 -5,-4 0,-2.030484 5.00037,-2 4.99537,-4.040088"
+ sodipodi:nodetypes="cscscsc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cscscsc"
+ d="m -68.50037,45.540088 c 0,-2 -5,-2 -5,-4 0,-2.030484 5.00037,-2 4.99787,-4.040088 0.002,-2 -4.9975,-2 -4.9975,-4 0,-2.030484 5.005,-1.959912 5,-4 0,-2 -5,-2 -5,-4 0,-2.030484 5.00037,-2 4.99537,-4.040088"
+ style="fill:none;stroke:#ffffff;stroke-width:1.39999998;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ id="path43404-1"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path43406-5"
+ style="opacity:0.4;fill:none;stroke:url(#radialGradient43410-4);stroke-width:1.39999998;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m -68.50037,45.540088 c 0,-2 -5,-2 -5,-4 0,-2.030484 5.00037,-2 4.99787,-4.040088 0.002,-2 -4.9975,-2 -4.9975,-4 0,-2.030484 5.005,-1.959912 5,-4 0,-2 -5,-2 -5,-4 0,-2.030484 5.00037,-2 4.99537,-4.040088"
+ sodipodi:nodetypes="cscscsc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cscscsc"
+ d="m -68.50037,45.540088 c 0,-2 -5,-2 -5,-4 0,-2.030484 5.00037,-2 4.99787,-4.040088 0.002,-2 -4.9975,-2 -4.9975,-4 0,-2.030484 5.005,-1.959912 5,-4 0,-2 -5,-2 -5,-4 0,-2.030484 5.00037,-2 4.99537,-4.040088"
+ style="opacity:0.4;fill:none;stroke:url(#radialGradient43412-8);stroke-width:1.39999998;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ id="path43408-2"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ transform="translate(273,441)"
+ id="g40240">
+ <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"
+ d="M 52.75,44.25 62.5,34.5 c 0,-1 -0.5,-1.5 -1,-2 -0.498692,-0.498692 -1,-1 -2,-1 l -9.75,9.75 c 1,0 1.501308,0.501308 2,1 0.5,0.5 1,1 1,2 z"
+ sodipodi:nodetypes="ccsccsc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="31"
+ x="47"
+ height="16"
+ width="16"
+ id="rect40244"
+ style="opacity:0.01000001;fill:#d40000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
+ <path
+ sodipodi:nodetypes="ccsccc"
+ d="M 60.75,36.25 62.5,34.5 c 0,-1 -0.5,-1.5 -1,-2 -0.498692,-0.498692 -1,-1 -2,-1 l -1.75,1.75 3,3 z"
+ style="fill:url(#linearGradient40270);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.69999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path40246"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ d="m 57.5,35.5 -1,-1 -6.75,6.75 1.75,0.25 6,-6 z"
+ style="fill:#bcd35f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path40248"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40250"
+ style="fill:#445016;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 59.5,37.25 -1,-0.75 -6,6 0.25,1.5 6.75,-6.75 z"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path40252"
+ d="m 59.75,37.25 -3,-3"
+ style="fill:none;stroke:url(#linearGradient40272);stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient40274);stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 60.75,36.25 -3,-3"
+ id="path40254"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient40276);fill-opacity:1;stroke-width:1px"
+ d="m 57.75,33.25 2.98375,3.003125 -1.0075,1.0075 -3.0225,-2.98375 L 57.75,33.25 z"
+ id="path40256"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#501616;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 61,36 1.5,-1.5 c 0,-1 -0.5,-1.5 -1,-2 -0.498692,-0.498692 -1,-1 -2,-1 L 58,33"
+ id="path40258"
+ sodipodi:nodetypes="ccscc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path40260"
+ d="M 58.25,32.75 50,41 l -2,4 -0.5,0.5 0.25,0.75 0.75,0.25 0.5,-0.5 4,-2 8.25,-8.25"
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccsc"
+ id="path40262"
+ d="M 50.25,41 48.5,44.25 49.75,45.5 53,43.75 C 53,43.25 52.5,42.5 52,42 51.501308,41.501308 50.75,41 50.25,41 z"
+ style="fill:url(#linearGradient40278);fill-opacity:1;stroke-width:1px"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#445016;stroke:#22280b;stroke-width:2.4000001;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 48.25,45.75 0.5,-0.5"
+ id="path40264"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path40266"
+ d="M 48.25,45.75 48.5,45.5"
+ style="fill:none;stroke:#9ab432;stroke-width:1.10000002;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.3;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round"
+ d="M 52.527427,43.527587 61.514313,34.48568"
+ id="path40268"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g40603-2"
+ transform="translate(238,594)">
+ <rect
+ y="-122"
+ x="-44"
+ height="16"
+ width="16"
+ id="rect40445-4"
+ style="opacity:0.01000001;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path40447-5"
+ d="m -43.5,-116.75 12.5,-4.75 0.75,2 -13.25,5 0,-2.25 z"
+ style="fill:#1a1a1a;stroke:#000000;stroke-width:0.89999998;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="-114.5"
+ x="-42.5"
+ height="7.9999971"
+ width="12.999988"
+ id="rect40449-5"
+ style="fill:url(#linearGradient39686-1);fill-opacity:1;fill-rule:nonzero;stroke:#000000;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" />
+ <rect
+ style="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"
+ id="rect40451-1"
+ width="1"
+ height="1.5"
+ x="-32"
+ y="-121" />
+ <rect
+ y="-119.41868"
+ x="-36"
+ height="1.5"
+ width="1"
+ id="rect40453-7"
+ style="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" />
+ <rect
+ style="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"
+ id="rect40455-1"
+ width="1"
+ height="1.5"
+ x="-37"
+ y="-119.16868" />
+ <rect
+ y="-117.62802"
+ x="-41"
+ height="1.5"
+ width="1"
+ id="rect40457-1"
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;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:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40459-5"
+ width="1"
+ height="1.5"
+ x="-40"
+ y="-117.87802" />
+ <rect
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:#000000;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"
+ id="rect40461-2"
+ width="13.999996"
+ height="2.0000052"
+ x="-43.5"
+ y="-114.5" />
+ <rect
+ y="-113"
+ x="-42"
+ height="1.7500292"
+ width="12.154154"
+ id="rect40490-7"
+ style="opacity:0.8;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.55400002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ id="rect40463-6"
+ d="m -40,-114 0,1.25 2,0 0,-1.25 -2,0 z m 4,0 0,1.25 2,0 0,-1.25 -2,0 z m 4,0 0,1.25 2,0 0,-1.25 -2,0 z"
+ style="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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.3;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round"
+ d="m -31.5,-120.5 -9.75,3.75"
+ id="path40474-1"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:none;stroke:url(#linearGradient39688-9);stroke-width:1px;stroke-linejoin:round"
+ d="m -41.5,-107.5 0,-6 11,0 0,6 -11,0 z"
+ id="path40476-4"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#87aade;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 -43,-116.75 1,0 1,1.75 0,2 -2,0 0,-3.75 z"
+ id="path40478-2"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#002255;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 -41,-115 0,2 -2,0 0,0.75 2.75,0 0,-3 -1.25,-2.25 -1.5,0.25 0,0.5 1,0 1,1.75 z"
+ id="path40480-3"
+ sodipodi:nodetypes="ccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40558-2"
+ d="m -41.5,-107.38206 0,-4.66445"
+ style="opacity:0.2;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="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"
+ id="rect40553-2"
+ width="1"
+ height="1.5"
+ x="-33"
+ y="-120.75" />
+ <rect
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40556-1"
+ width="1"
+ height="1.25"
+ x="-40"
+ y="-114" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round"
+ d="m -42.4975,-113.46527 0,-3.0928"
+ id="path40560-6"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(1,0)"
+ style="opacity:0.35"
+ id="g40590-8">
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.55400002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40586-5"
+ width="5"
+ height="0.9617852"
+ x="-38"
+ y="-110" />
+ <rect
+ y="-111"
+ x="-36"
+ height="3"
+ width="1.0280838"
+ id="rect40588-7"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.55400002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+ <g
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ transform="translate(56,-67)"
+ id="g42945"
+ style="display:inline;enable-background:new">
+ <rect
+ y="602"
+ x="327"
+ height="16"
+ width="16"
+ id="rect42947"
+ 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="g42949">
+ <g
+ style="opacity:0.85"
+ id="g42951">
+ <path
+ style="fill:#e6e6e6;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 341.5161,616.38229 340.5,617.5 l -10.73389,-10e-6 -1.25,-1.25 L 328.5,605.5 l 13,0 0.0161,10.88229 z"
+ id="path42953"
+ 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
+ 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="path42955"
+ d="m 340,616 -8.25,0 0,-1 8.25,0 0,1 z"
+ style="fill:#999999;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" />
+ <rect
+ style="opacity:0.2;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="rect38927"
+ width="11.970581"
+ height="8.0306396"
+ x="329.02942"
+ y="605.96936" />
+ <rect
+ y="605.96936"
+ x="329.02942"
+ height="8.0306396"
+ width="11.970581"
+ id="rect45307"
+ style="opacity:0.3;fill:url(#radialGradient45309);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: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="path42957"
+ d="m 340.48389,606.50001 c -3.66204,-3e-5 -7.70403,2e-5 -10.98389,-10e-6 l 0.002,10.00007 10.99778,-7e-5 -0.0161,-9.99999 2.1e-4,0 z"
+ style="fill:none;stroke:url(#linearGradient42965-7);stroke-width:0.99999923px;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="ccccc"
+ inkscape:connector-curvature="0" />
+ <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"
+ y="615"
+ x="330"
+ height="1.0000043"
+ width="1"
+ id="rect42959"
+ 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" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="opacity:0.35;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"
+ d="m 340.5,614 -11,0 0,-1 11,0 0,1 z"
+ id="path38929"
+ 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.25;fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;filter:url(#filter24186-3-2)"
+ d="m 337.7,606.7 0,2.75 2,1.5 0,2.5 -0.25,0.25 -1.75,0 0,-2 -2,0 0,2 -1.75,0 -0.25,-0.25 0,-2.5 2,-1.5 0,-2.75 2,0 z"
+ id="path42961"
+ sodipodi:nodetypes="ccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccccccccccccccccc"
+ id="path42963"
+ d="m 333.75,602.5 1.75,0 c 0,0 0,2 0,2 l 2,0 0,-2 1.75,0 0.25,0.25 0,2.5 -2,1.5 0,2.5 2,1.5 0,2.5 -0.25,0.25 -1.75,0 0,-2 -2,0 0,2 -1.75,0 -0.25,-0.25 0,-2.5 2,-1.5 0,-2.5 -2,-1.5 0,-2.5 0.25,-0.25 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:url(#linearGradient42967-6);stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </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" />
+ <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">
+ <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.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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ 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">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 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)" />
+ </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"
+ height="16"
+ width="16"
+ id="rect41249"
+ 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="g41251"
+ 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)"
+ style="opacity:0.8;display:inline">
+ <g
+ style="display:inline"
+ id="g41253"
+ 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">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 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"
+ 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"
+ id="path41257"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <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.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">
+ <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"
+ id="path41262"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ id="path41264"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g40887">
+ <g
+ id="g40668">
+ <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="rect39989"
+ width="16"
+ height="16"
+ x="215"
+ y="472"
+ rx="0"
+ ry="0" />
+ <g
+ id="g40555">
+ <rect
+ ry="1.7356256"
+ y="475.5"
+ x="215.5"
+ height="11.000039"
+ width="14.000015"
+ id="rect39993"
+ style="fill:url(#linearGradient40918);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
+ sodipodi:nodetypes="ccccccccc"
+ id="path39996"
+ d="m 216.00001,479.40741 0,4.59259 c 0,0.56404 0.36784,1.00001 0.84375,1 l 11.3125,0 c 0.47591,0 0.84375,-0.43595 0.84375,-1 l 0,-4.59259 C 228.6863,479.7792 228.23078,480 227.75001,480 l -10.5,0 c -0.48077,0 -0.93629,-0.2208 -1.25,-0.59259 z"
+ style="fill:url(#linearGradient40920);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="rect39999"
+ width="14.000005"
+ height="2.0000522"
+ x="215.5"
+ y="475.5"
+ ry="0.8750208" />
+ <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="rect40001"
+ width="14.000006"
+ height="10.999848"
+ x="215.5"
+ y="475.5"
+ ry="1.503511"
+ rx="1.503511" />
+ <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="path40005"
+ 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(1.3955004,0,0,1.2452423,115.18334,-141.72474)" />
+ <rect
+ rx="0.5078125"
+ ry="0.4910686"
+ y="476.5"
+ x="216.5"
+ height="9.0000038"
+ width="12.000035"
+ id="rect40008"
+ 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,100.49326,-321.69208)"
+ 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="path40010"
+ style="opacity:0.25;fill:none;stroke:#000000;stroke-width:0.62952662;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:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient40922);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="path40012"
+ 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(1.1794014,0,0,0.8999954,131.50687,28.952303)" />
+ <path
+ transform="matrix(1.1827463,0,0,1.2,131.2458,-119.90002)"
+ 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="path40014"
+ 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(#linearGradient40924);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="path40016"
+ 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.790122,0,0,0.787736,161.87049,87.05649)" />
+ <path
+ transform="matrix(0.5963773,0,0,0.2000006,171.47609,375.5997)"
+ 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="path40020"
+ 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" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1;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 216.48394,475.5 0,-0.50001 c 0,-0.276 0.67629,-0.5 1.50958,-0.5 0.83329,0 1.50958,0.224 1.50958,0.5 l 0,0.50001"
+ id="path40022"
+ sodipodi:nodetypes="csccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="475"
+ x="217"
+ height="1"
+ width="2"
+ id="rect40024"
+ 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="477"
+ x="226"
+ height="1"
+ width="2"
+ id="rect40026"
+ 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(#radialGradient40926);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40028"
+ width="2"
+ height="1"
+ x="226"
+ y="477" />
+ <rect
+ y="478"
+ x="218"
+ height="1"
+ width="1"
+ id="rect40030"
+ 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" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#radialGradient40928);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="path40032"
+ 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(1.1827463,0,0,1.2,131.2458,-119.90002)" />
+ <path
+ transform="matrix(0.8888868,0,0,0.8862026,154.16683,37.626266)"
+ 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="path40034"
+ style="fill:url(#radialGradient40930);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
+ 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="path40036"
+ 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.1975308,0,0,0.1999991,207.09261,381.10045)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.7;fill:url(#radialGradient40932);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.98985863;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path40043"
+ 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.8867575,0.06148883,-0.06130315,-0.8840797,323.44127,921.51187)" />
+ </g>
+ </g>
+ <g
+ transform="matrix(0.9986805,0,0,1,-92.569205,199)"
+ id="g25007-8"
+ style="display:inline;enable-background:new">
+ <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-2"
+ 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-4"
+ 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
+ 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-5"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ 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-5"
+ d="m 318.48945,276 1.25165,-0.25 1.50199,0 1.25162,0.25001 0,1.00005 -1.25162,0.24994 -1.50199,0 -1.25165,-0.24995 0,-1.00005 0,0 0,0 0,0 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 319.99139,278.50006 -0.25029,-1.25006 0,-1.5 0.2503,-1.25 1.00137,0 0.25032,1.25 0,1.5 -0.25033,1.25006 -1.00137,0 0,0 0,0 0,0 z"
+ id="path25015-1"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ 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">
+ <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"
+ width="16"
+ height="16"
+ x="109"
+ y="472" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:url(#linearGradient36549);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;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 110.5,472.5 13.98222,2e-5 0,14.96443 -13.98222,-2e-5 0,-14.96443 z"
+ id="path36516"
+ 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="path36518"
+ d="m 111.49999,485.48369 0,-11.00155 10.99999,0"
+ style="fill:none;stroke:#ffffff;stroke-width:0.9999997px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.25;fill:url(#radialGradient36551);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 112,474 11,0 0,11 -11,0 0,-11 z"
+ id="path36521"
+ 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" />
+ <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="path36523"
+ d="m 112.5,474.5 9.98224,0 0,10 -9.98224,0 0,-10 z"
+ style="fill:url(#linearGradient36553);fill-opacity:1;fill-rule:evenodd;stroke:#808080;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" />
+ <path
+ style="opacity:0.5;fill:none;stroke:#4d4d4d;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 112.5,484.5 0,-10 9.98224,0"
+ id="path36525"
+ 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="ccc"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g39496">
+ <path
+ transform="matrix(0.2498674,0,0,0.249916,83.518554,451.9933)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient36555);stroke-width:4.00173378;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path36527"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ sodipodi:nodetypes="cccsccc"
+ id="path36529"
+ d="m 119,475.50001 c -1.44825,0 -1.50029,0.42731 -1.50029,0.85462 l 2.2e-4,4.27306 c 0,0.85461 0.052,0.85461 1.50029,0.85461 1.44823,0 1.49984,0.0467 1.49984,-0.85461 l 0,-4.27306 c 0,-0.42731 -0.0518,-0.85462 -1.50006,-0.85462 z"
+ style="fill:url(#linearGradient36557);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" />
+ <path
+ style="fill:none;stroke:url(#linearGradient36559);stroke-width:0.80000001;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 118.99995,475.50001 c -1.44821,0 -1.50025,0.42731 -1.50025,0.85461 l 2.2e-4,4.27306 c 0,0.85462 0.052,0.85462 1.50025,0.85462 1.44821,0 1.49982,0.0467 1.49982,-0.85462 l 0,-4.27306 c 0,-0.4273 -0.0518,-0.85461 -1.50004,-0.85461 z"
+ id="path36531"
+ sodipodi:nodetypes="cccsccc"
+ 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"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36533"
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(0.1876323,0,0,0.1876688,91.733582,459.33847)" />
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36535"
+ style="fill:#ffffff;stroke:url(#linearGradient36561);stroke-width:12.91347408;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.1154571,0,0,0.1168626,101.25809,467.69987)" />
+ <g
+ style="opacity:0.7"
+ id="g36537">
+ <path
+ transform="matrix(1.1428645,0,0,1.1428645,-416.36057,256.4986)"
+ d="m 466.25,192.5 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 z"
+ sodipodi:ry="1.75"
+ sodipodi:rx="1.75"
+ sodipodi:cy="192.5"
+ sodipodi:cx="464.5"
+ id="path36539"
+ style="opacity:0.15;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#ffdd55;stroke-width:0.87499446;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:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffd42a;fill-opacity:1;fill-rule:nonzero;stroke:#ffd42a;stroke-width:1.74999654;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="path36541"
+ sodipodi:cx="464.5"
+ sodipodi:cy="192.5"
+ sodipodi:rx="1.75"
+ sodipodi:ry="1.75"
+ d="m 466.25,192.5 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 z"
+ transform="matrix(0.5714297,0,0,0.5714297,-150.92912,366.49979)" />
+ <rect
+ y="476"
+ x="113.99994"
+ height="1"
+ width="1"
+ id="rect36543"
+ 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:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36545"
+ width="2"
+ height="1"
+ x="118"
+ y="476" />
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36547"
+ style="fill:none;stroke:url(#linearGradient36563);stroke-width:4.00173378;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.2498674,0,0,0.249916,83.518554,451.9933)" />
+ </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"
+ transform="translate(-369,-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"
+ 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);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);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"
+ 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);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ id="path39245"
+ 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"
+ 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"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39251"
+ d="m 757.5,206.5 0,2 -2,0"
+ style="fill:none;stroke:url(#linearGradient39260);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-705,268)"
+ id="g36639"
+ 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"
+ d="m 756.16666,204.50001 10.33334,0 0,14.99999 -13,0 -10e-6,-11.99999 2.66667,-3 z"
+ id="path36641"
+ 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
+ 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="path36643"
+ 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(#radialGradient36659);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" />
+ <path
+ id="path36646"
+ style="fill:none;stroke:url(#linearGradient36661);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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path36649"
+ d="m 753,208 4,0 0,-4 -4,4 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path36653"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient36663);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 757.5,206.5 0,2 -2,0"
+ id="path36655"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g37112"
+ transform="translate(-42,0)">
+ <g
+ transform="matrix(-1,0,0,1,887,548.02778)"
+ style="opacity:0.8;display:inline;enable-background:new"
+ id="g36742">
+ <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="rect36744"
+ width="16"
+ height="16"
+ x="488"
+ y="29" />
+ <g
+ id="g36746">
+ <path
+ sodipodi:nodetypes="csccccccccsssc"
+ id="path36748"
+ d="m 500.5,34.5 0,5 c 0,1.666667 0.25,1.75 1,3.25 l -1.25,1.75 -1.75,-1.75 -1.75,1.75 -0.5,0 -1.75,-1.75 -1.75,1.75 -1,0 C 491,43 490.5,42.416667 490.5,40.75 l 0,-6.25 c 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
+ style="fill:url(#linearGradient37132);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" />
+ <path
+ d="m 495.5,30.375 c -2.28774,0 -4.125,1.837258 -4.125,4.125 l 0,6.25 c 0,0.74605 0.0978,1.170828 0.28125,1.625 0.13101,0.324408 0.38353,0.789244 0.625,1.25 l 0.0937,0 1.5,-1.5 a 0.87292083,0.87292083 0 0 1 1.25,0 l 1.375,1.375 1.375,-1.375 a 0.87292083,0.87292083 0 0 1 1.1875,-0.03125 l 1.375,1.21875 0.1875,-0.1875 0,-0.4375 C 500.24057,42.152166 499.91254,41.661109 499.78125,41.125 499.62101,40.470677 499.625,39.833334 499.625,39 l 0,-4.5 c 0,-2.287742 -1.83726,-4.125 -4.125,-4.125 z"
+ id="path36750"
+ style="fill:none;stroke:url(#linearGradient37134);stroke-width:1;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:original="M 495.5 29.5 C 492.74 29.5 490.5 31.74 490.5 34.5 L 490.5 40.75 C 490.5 42.416667 491 43 491.75 44.5 L 492.75 44.5 L 494.5 42.75 L 496.25 44.5 L 496.75 44.5 L 498.5 42.75 L 500.5 44.5 L 501.5 43.5 L 501.5 42.5 C 500.5 41.25 500.5 40.666667 500.5 39 L 500.5 34.5 C 500.5 31.74 498.26 29.5 495.5 29.5 z "
+ inkscape:radius="-0.87283355"
+ sodipodi:type="inkscape:offset" />
+ <g
+ style="opacity:0.25;fill:#000000"
+ id="g36752">
+ <path
+ sodipodi:nodetypes="cccc"
+ style="fill:#000000;fill-rule:evenodd;stroke:none"
+ d="m 493,43.75 c 0,-0.212963 0,-5.75 0,-5.75 l 1.5,4.472222 L 493,43.75 z"
+ id="path36754"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path36756"
+ d="m 497,44 c 0,-0.203703 -1,-6 -1,-6 l 2,3.428571 0,1.714286 L 497,44 z"
+ style="fill:#000000;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(-1,0,0,1,990,0.25)"
+ id="g36758"
+ style="opacity:0.7;fill:#ffffff">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path36760"
+ d="m 493,43.75 c 0,-0.212963 1,-6 1,-6 l 1,5 -1,1 -1,0 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:none"
+ d="m 497,43.75 c 0,-0.203703 0,-6 0,-6 l 2,5 -1,1 -1,0 z"
+ id="path36762"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:none"
+ d="m 490,43.25 c 0,-0.212963 1.5,-6.25 1.5,-6.25 l 0.5,5.5 -2,0.75 z"
+ id="path36764"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ 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"
+ d="m 500.5,34.5 0,4.5 c 0,1.666667 0,2.25 1,3.5 l 0,1 -1,1 -2,-1.75 -1.75,1.75 -0.5,0 -1.75,-1.75 -1.75,1.75 -0.5,0 C 491,43 490.5,43.166667 490.5,41.5 l 0,-7 c 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
+ id="path36766"
+ sodipodi:nodetypes="cscccccccccsssc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path36768"
+ d="m 56,139 0,1 -1,0 0,1 2,0 0,-2 -1,0 z"
+ style="opacity:0.8;fill:url(#linearGradient37136);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;enable-background:new"
+ sodipodi:nodetypes="ccccccc"
+ transform="translate(441,-105)"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.8;fill:url(#linearGradient37138);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;enable-background:new"
+ d="m 51,139 0,2 2,0 0,-1 -1,0 0,-1 -1,0 z"
+ id="path36770"
+ sodipodi:nodetypes="ccccccc"
+ transform="translate(441,-105)"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <path
+ style="opacity:0.65;fill:#000000;fill-rule:evenodd;stroke:#2b0000;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 385.5,578.5 12,12"
+ id="path36738"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path36740"
+ d="m 385.5,578.5 12,12"
+ style="fill:none;stroke:#ff5555;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" />
+ </g>
+ <g
+ transform="translate(87.000001,33.999969)"
+ id="g37053"
+ 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">
+ <rect
+ y="459.00003"
+ x="-61.000011"
+ height="16"
+ width="16"
+ id="rect37055"
+ 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" />
+ <g
+ transform="matrix(0.9778614,0.2092535,-0.2092535,0.9778614,137.19272,32.846168)"
+ style="display:inline;enable-background:new"
+ id="g37057"
+ inkscape:transform-center-x="6.529123"
+ inkscape:transform-center-y="4.2273311">
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;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 -98.435716,459.41623 9.935716,0.0838 0,10.99997 -9.935716,-0.0838 0,-10.99997 z"
+ id="path37059"
+ 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" />
+ <path
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="-0.8656081"
+ inkscape:original="M -98.4375 459.40625 L -98.4375 470.40625 L -88.5 470.5 L -88.5 459.5 L -98.4375 459.40625 z "
+ style="fill:url(#linearGradient37089);fill-opacity:1;fill-rule:evenodd;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="path37061"
+ d="m -97.5625,460.28125 0,9.25 8.1875,0.0937 0,-9.25 -8.1875,-0.0937 z" />
+ </g>
+ <g
+ id="g37063"
+ style="display:inline;enable-background:new"
+ transform="translate(38.999989,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="path37065"
+ d="m -99.499989,459.50003 10.999989,-10e-6 0,10.99997 -10.999989,10e-6 0,-10.99997 z"
+ style="fill:#ffffff;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;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.5;fill:url(#linearGradient37091);fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0;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 -97.999989,461 7.99998,0 0,8 -7.99998,0 0,-8 z"
+ id="path37067"
+ 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
+ transform="matrix(0.5714297,0,0,0.5714297,-362.92909,351.49978)"
+ d="m 466.25,192.5 a 1.75,1.75 0 1 1 -3.5,0 1.75,1.75 0 1 1 3.5,0 z"
+ sodipodi:ry="1.75"
+ sodipodi:rx="1.75"
+ sodipodi:cy="192.5"
+ sodipodi:cx="464.5"
+ id="path37069"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#d4aa00;stroke-width:1.74999654;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: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"
+ id="path37071"
+ d="m -98.49992,460.49999 9.00002,0 0,9.00003 -9.00002,0 0,-9.00003 z"
+ style="fill:none;stroke:url(#linearGradient37093);stroke-width:0.99999952px;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="fill:#ffe680;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37073"
+ width="1"
+ height="1"
+ x="-98"
+ y="461" />
+ <rect
+ y="461.5"
+ x="-94.500008"
+ height="5"
+ width="3"
+ id="rect37075"
+ style="fill:url(#linearGradient37096);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:none;stroke:url(#linearGradient37098);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"
+ id="rect37077"
+ width="3"
+ height="5"
+ x="-94.500008"
+ y="461.5"
+ rx="0.46547449"
+ ry="0.46547449" />
+ <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="rect37079"
+ width="2"
+ height="1"
+ x="-94.000008"
+ y="462" />
+ <path
+ transform="matrix(0.1904433,0,0,0.1904803,-120.13881,444.5233)"
+ sodipodi:type="arc"
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:#4d4d4d;stroke-width:5.25039816;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path37081"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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" />
+ <rect
+ ry="0.46547449"
+ rx="0.46547449"
+ y="461.5"
+ x="-94.500008"
+ height="5"
+ width="3"
+ id="rect37083"
+ style="fill:none;stroke:url(#linearGradient37100);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" />
+ <path
+ transform="matrix(0.07365497,0,0,0.07463961,-104.72475,458.19728)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient37102);stroke-width:20.23044777;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path37085"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path37087"
+ style="fill:none;stroke:url(#linearGradient37104);stroke-width:5.25039816;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.1904433,0,0,0.1904803,-120.13881,444.5233)" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g37514"
+ transform="translate(-327.01257,-130.96121)">
+ <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="path37516"
+ d="m 757.01257,204.46121 9.48743,0.0388 0,14.99999 -13,0 0.0126,-11.53879 3.5,-3.5 -3e-5,0 z"
+ style="fill:#dcdcdc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g37518"
+ style="display:inline;enable-background:new"
+ transform="translate(838.01257,111.96121)">
+ <g
+ id="g37520">
+ <rect
+ style="fill:#e9afaf;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37522"
+ width="9.9999914"
+ height="12"
+ x="-83"
+ y="94" />
+ <rect
+ y="101"
+ x="-83"
+ height="4.9999976"
+ width="9.9999924"
+ id="rect37524"
+ style="opacity:0.5;fill:#4b7fcd;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="94"
+ x="-83"
+ height="6.8499999"
+ width="9.9999914"
+ id="rect37526"
+ style="opacity:0.3;fill:url(#radialGradient37553);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="cccccccccccc"
+ id="path37528"
+ d="m -83,100.00002 1,0 1,0.74999 1,-0.74999 1,0.99999 2,0 1.5,-0.75 1.5,0.75 0.999991,0 L -73,102 l -9.999991,0 -9e-6,-1.99998 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37530"
+ width="2.0000029"
+ height="2.0000038"
+ x="-77"
+ y="96" />
+ <path
+ style="opacity:0.3;fill:#2b0000;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 -83,102 10,0 0,1 -10,0 0,-1 z"
+ id="path37532"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path37534"
+ d="m -77,102 2.000003,0 -0.750003,4 -0.5,0 -0.75,-4 z"
+ style="opacity:0.5;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g37536"
+ style="display:inline;enable-background:new"
+ transform="translate(838.01257,111.96121)">
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path37538"
+ d="m -82.5,105.5 0,-11 9,0"
+ style="opacity:0.25;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.2;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;display:inline;enable-background:new"
+ d="m -82.5,105.5 0,-11 9,0 0,11 -9,0 z"
+ id="path37540"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="opacity:0.5;fill:url(#radialGradient37555);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 757.51257,204.46121 9,1e-5 0,14.99999 -13,0 0,-11 4,-4 z"
+ id="path37542"
+ 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.51257,209.96121 754.5,218.5 M 759.01257,205.46121 765.5,205.5"
+ style="opacity:0.1;fill:none;stroke:url(#linearGradient37558);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ id="path37544"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 753.01257,208.96121 5,0 0,-5 -5,5 z"
+ id="path37546"
+ 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.51257,207.96121 753.5,219.5 l 13,0 0,-14.99999 -9.48743,-0.0388 -3.5,3.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="path37549"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path37551"
+ d="m 758.51257,206.46121 0,3 -3,0"
+ style="fill:none;stroke:url(#linearGradient37561);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g37514-4"
+ transform="translate(-726.01257,268.03879)">
+ <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="path37516-1"
+ d="m 757.01257,204.46121 9.48743,0.0388 0,14.99999 -13,0 0.0126,-11.53879 3.5,-3.5 -3e-5,0 z"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g37518-1"
+ style="display:inline;enable-background:new"
+ transform="translate(838.01257,111.96121)">
+ <g
+ id="g37520-3">
+ <rect
+ style="fill:#ebb5b5;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37522-8"
+ width="9.9999914"
+ height="12"
+ x="-83"
+ y="94" />
+ <rect
+ y="101"
+ x="-83"
+ height="4.9999976"
+ width="9.9999924"
+ id="rect37524-7"
+ style="opacity:0.5;fill:#4b80cd;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="94"
+ x="-83"
+ height="6.8499999"
+ width="9.9999914"
+ id="rect37526-4"
+ style="opacity:0.3;fill:url(#radialGradient37553-2);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="cccccccccccc"
+ id="path37528-2"
+ d="m -83,100.00002 1,0 1,0.74999 1,-0.74999 1,0.99999 2,0 1.5,-0.75 1.5,0.75 0.999991,0 L -73,102 l -9.999991,0 -9e-6,-1.99998 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37530-7"
+ width="2.0000029"
+ height="2.0000038"
+ x="-77"
+ y="96" />
+ <path
+ style="opacity:0.3;fill:#280b0b;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 -83,102 10,0 0,1 -10,0 0,-1 z"
+ id="path37532-7"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path37534-9"
+ d="m -77,102 2.000003,0 -0.750003,4 -0.5,0 -0.75,-4 z"
+ style="opacity:0.5;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g37536-3"
+ style="display:inline;enable-background:new"
+ transform="translate(838.01257,111.96121)">
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path37538-1"
+ d="m -82.5,105.5 0,-11 9,0"
+ style="opacity:0.25;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.2;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;display:inline;enable-background:new"
+ d="m -82.5,105.5 0,-11 9,0 0,11 -9,0 z"
+ id="path37540-9"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="opacity:0.5;fill:url(#radialGradient37555-5);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 757.51257,204.46121 9,1e-5 0,14.99999 -13,0 0,-11 4,-4 z"
+ id="path37542-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:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ d="M 754.51257,209.96121 754.5,218.5 M 759.01257,205.46121 765.5,205.5"
+ style="fill:none;stroke:url(#linearGradient37558-8);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ id="path37544-6"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 753.01257,208.96121 5,0 0,-5 -5,5 z"
+ id="path37546-5"
+ 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.51257,207.96121 753.5,219.5 l 13,0 0,-14.99999 -9.48743,-0.0388 -3.5,3.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="path37549-0"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path37551-2"
+ d="m 758.51257,206.46121 0,3 -3,0"
+ style="fill:none;stroke:url(#linearGradient37610-3);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-167.99999,190.99999)"
+ id="g71820">
+ <rect
+ y="365"
+ x="215"
+ height="16"
+ width="16"
+ id="rect71822"
+ 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(167.99999,-62.999991)"
+ id="g71824">
+ <rect
+ ry="0"
+ style="fill:#ececec;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="rect71826"
+ width="13.016124"
+ height="12.953857"
+ x="48.499996"
+ y="429.54614" />
+ <rect
+ y="430"
+ x="50.016117"
+ height="11.046139"
+ width="11.000001"
+ id="rect71828"
+ style="fill:url(#linearGradient71834);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
+ style="fill:url(#linearGradient71836);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 49,430 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,0 0,3 3,0 0,-3 -3,0 z m 0,3 -3,0 0,3 3,0 0,-3 z m 0,3 0,3 3,0 0,-3 -3,0 z m -3,0 -3,0 0,3 3,0 0,-3 z m -3,0 0,-3 -3,0 0,3 3,0 z"
+ id="path71830"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient71838);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 60.517703,430.5 -11.017704,0 0,11 11.017704,0 0,-11"
+ id="path71832"
+ sodipodi:nodetypes="ccc"
+ 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)">
+ <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-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" />
+ <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:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <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" />
+ <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" />
+ <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,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" />
+ <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" />
+ </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"
+ transform="translate(131,-30)">
+ <g
+ transform="translate(-45.97248,412)"
+ id="g38319">
+ <path
+ style="fill:url(#linearGradient38362);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 40.472488,166.25001 -1.250005,1.25 -12.483893,-1e-5 -1.25,-1.25 -5e-6,-11.75001 14.983898,1e-5 5e-6,11.75001 z"
+ id="path38330"
+ 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
+ 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="path38332"
+ d="m 38.972483,166.00001 -10.250003,0 0,-1 10.250003,0 0,1 z"
+ style="fill:#b3b3b3;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" />
+ <g
+ transform="translate(110.97248,58)"
+ style="display:inline;enable-background:new"
+ id="g38334">
+ <g
+ id="g38336">
+ <rect
+ y="97.000008"
+ x="-85"
+ height="8.9999962"
+ width="14.000007"
+ id="rect38338"
+ style="fill:#d89090;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.5;fill:#3771c8;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect38340"
+ width="13.999992"
+ height="2.9999936"
+ x="-85"
+ y="103.00001" />
+ <rect
+ style="opacity:0.3;fill:url(#radialGradient38364);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect38342"
+ width="14"
+ height="8.8499966"
+ x="-85"
+ y="97.000008" />
+ <path
+ style="fill:#000000;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 -84.999997,101.00001 1.166667,0 1.166666,0.74999 1.166667,-0.74999 1.166666,0.99999 4.666666,1e-5 1.75,-0.75 1.75,0.75 1.166667,0 1e-5,0.99999 -13.999999,-1e-5 -10e-6,-1.99998 0,0 0,0 0,0 z"
+ id="path38344"
+ sodipodi:nodetypes="cccccccccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="99"
+ x="-77"
+ height="2.0000038"
+ width="2.0000029"
+ id="rect38346"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path38350"
+ d="m -85,103.0089 14.061944,0 0,1 -14.061944,0 0,-1 z"
+ style="opacity:0.3;fill:#280b0b;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path38360"
+ d="m -71.75,105.5 -12.5,0"
+ style="opacity:0.7;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.4;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -77,103 2.000003,0 -0.750003,2.75 -0.5,0 L -77,103 z"
+ id="path38352"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </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"
+ id="path38354"
+ d="m 39.472483,155.5 -13,0 0.01611,11 13.01389,-7e-5 -0.03,-10.99993 z"
+ style="fill:none;stroke:url(#linearGradient38367);stroke-width:0.99999923px;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="ccccc"
+ inkscape:connector-curvature="0" />
+ <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"
+ y="165"
+ x="26.972481"
+ height="1.0000043"
+ width="1"
+ id="rect38356"
+ 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
+ transform="translate(63,473)"
+ style="display:inline;enable-background:new"
+ id="g38358" />
+ </g>
+ <g
+ id="g38738"
+ transform="translate(41.000016,-2e-5)">
+ <rect
+ y="472"
+ x="488"
+ height="16"
+ width="16"
+ id="rect43314"
+ style="opacity:0;fill:#999999;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(565,446)"
+ clip-path="url(#clipPath43368-7)"
+ id="g43300">
+ <rect
+ style="fill:#4e83d0;fill-opacity:1;fill-rule:nonzero;stroke:#143564;stroke-width:0.80000001;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"
+ id="rect43243"
+ width="6"
+ height="2"
+ x="-75.5"
+ y="28.5"
+ rx="0.79505396"
+ ry="0.79505396" />
+ <rect
+ ry="0.74381745"
+ rx="0.74381745"
+ y="36.5"
+ x="-75.5"
+ height="2"
+ width="6"
+ id="rect43245"
+ style="fill:#4e83d0;fill-opacity:1;fill-rule:nonzero;stroke:#143564;stroke-width:0.80000001;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" />
+ <rect
+ style="fill:#ec0606;fill-opacity:1;fill-rule:nonzero;stroke:#910000;stroke-width:0.80000001;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"
+ id="rect43262"
+ width="6"
+ height="2"
+ x="-72.5"
+ y="39.5"
+ rx="0.71819919"
+ ry="0.71819919" />
+ <path
+ sodipodi:nodetypes="cscscsc"
+ d="m -68.50037,45.540088 c 0,-2 -5,-2 -5,-4 0,-2.030484 5.00037,-2 4.99787,-4.040088 0.002,-2 -4.9975,-2 -4.9975,-4 0,-2.030484 5.005,-1.959912 5,-4 0,-2 -5,-2 -5,-4 0,-2.030484 5.00037,-2 4.99537,-4.040088"
+ style="fill:none;stroke:#000000;stroke-width:2.9000001;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ id="path43241"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41718"
+ style="fill:none;stroke:#ffffff;stroke-width:1.39999998;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m -68.50037,45.540088 c 0,-2 -5,-2 -5,-4 0,-2.030484 5.00037,-2 4.99787,-4.040088 0.002,-2 -4.9975,-2 -4.9975,-4 0,-2.030484 5.005,-1.959912 5,-4 0,-2 -5,-2 -5,-4 0,-2.030484 5.00037,-2 4.99537,-4.040088"
+ sodipodi:nodetypes="cscscsc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cscscsc"
+ d="m -68.50037,45.540088 c 0,-2 -5,-2 -5,-4 0,-2.030484 5.00037,-2 4.99787,-4.040088 0.002,-2 -4.9975,-2 -4.9975,-4 0,-2.030484 5.005,-1.959912 5,-4 0,-2 -5,-2 -5,-4 0,-2.030484 5.00037,-2 4.99537,-4.040088"
+ style="opacity:0.35;fill:none;stroke:url(#radialGradient38734);stroke-width:1.39999998;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ id="path43266"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path43282"
+ style="opacity:0.35;fill:none;stroke:url(#radialGradient38736);stroke-width:1.39999998;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m -68.50037,45.540088 c 0,-2 -5,-2 -5,-4 0,-2.030484 5.00037,-2 4.99787,-4.040088 0.002,-2 -4.9975,-2 -4.9975,-4 0,-2.030484 5.005,-1.959912 5,-4 0,-2 -5,-2 -5,-4 0,-2.030484 5.00037,-2 4.99537,-4.040088"
+ sodipodi:nodetypes="cscscsc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g39638-8"
+ transform="matrix(0.9986805,0,0,1,179.4308,202.99997)">
+ <rect
+ rx="1.2018067"
+ y="274.00003"
+ x="317.9888"
+ height="4.9999909"
+ width="5.006597"
+ id="rect39640-1"
+ style="opacity:0.25;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.5;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="rect39642-2"
+ width="5.0065966"
+ height="4.9999905"
+ x="317.9888"
+ y="274.00003"
+ rx="1.2018069"
+ ry="1.2018069" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ 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="path43508"
+ d="m 317.98879,278 0,-3 1.00132,-1 3.00396,0 1.00132,1 0,3 -1.00132,1 -3.00396,0 -1.00132,-1 z"
+ style="opacity:0.8;fill:#dcb000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ inkscape:connector-curvature="0" />
+ <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="path39644-1"
+ 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 317.98877,276 c 1.66888,0 3.33774,10e-6 5.00662,10e-6 0,0.33335 0,0.6667 0,1.00005 -1.66888,0 -3.33774,-1e-5 -5.00662,-1e-5 0,-0.33335 0,-0.6667 0,-1.00005 z"
+ id="path39646-4"
+ 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="path39648-9"
+ d="m 319.99139,279.00006 c 0,-1.66671 10e-6,-3.33335 10e-6,-5.00006 0.33379,0 0.66758,0 1.00137,0 0,1.66671 -1e-5,3.33335 -1e-5,5.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="g28606">
+ <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="matrix(0,-1,-1,0,0,0)"
+ 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="rect22257"
+ width="16"
+ height="16"
+ x="-551"
+ y="-168" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path22271"
+ d="m 167.49999,535.50001 0,8 -9,0 0,-6 2,-2 7,0 z"
+ style="fill:url(#linearGradient28603);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:30;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ id="rect22281"
+ d="m 166.99999,538.00001 -2,0 0,3 2,0 0,-3 z m -3,0 -1.75,0 -1.25,1.25 0,1.75 3,0 0,-3 z"
+ style="fill:url(#linearGradient28600);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.75;fill:#f2f2f2;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22285"
+ width="1"
+ height="1"
+ x="542"
+ y="162"
+ transform="matrix(0,1,1,0,0,0)" />
+ <path
+ id="rect22287"
+ d="m 166.99999,542.00001 -1,0 0,1 1,0 0,-1 z m -2,0 -1,0 0,1 1,0 0,-1 z"
+ style="opacity:0.2;fill:#f2f2f2;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" />
+ <path
+ id="rect22291"
+ d="m 166.99999,536.00001 -1,0 0,1 1,0 0,-1 z m -2,0 -1,0 0,1 1,0 0,-1 z m -2,0 -1,0 0,1 1,0 0,-1 z"
+ style="opacity:0.8;fill:#f2f2f2;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" />
+ <path
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:30;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 158.74999,537.25001 4.75,4.75 0,1 -4.75,0 0,-5.75 z"
+ id="path22298"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient28593);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:30;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 152.49999,550.50001 0,-8 9,0 1.75,-1.5 0.25,0.5 0,7.75 -1.25,1.25 -9.75,0 z"
+ id="path22300"
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 152.49999,550.50001 9.5,0 1.5,-1.5 0,-5.5 4,0 0,-8 -7,0 -2,2 0,5 -6,0 0,8 z"
+ id="path22304"
+ sodipodi:nodetypes="ccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.9;fill:url(#linearGradient28589);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 162.99999,544.00001 -1,1 -1,0 0,3 0.75,0 1.25,-1.25 0,-2.75 z m -3,1 -3,0 0,3 3,0 0,-3 z m -4,0 -3,0 0,3 3,0 0,-3 z"
+ id="rect22308"
+ sodipodi:nodetypes="ccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="rect22314"
+ d="m 161.99999,549.00001 -1,0 0,1 1,0 0,-1 z m -2,0 -1,0 0,1 1,0 0,-1 z m -2,0 -1,0 0,1 1,0 0,-1 z m -2,0 -1,0 0,1 1,0 0,-1 z m -2,0 -1,0 0,1 1,0 0,-1 z"
+ style="opacity:0.8;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:connector-curvature="0" />
+ <path
+ id="rect22322"
+ d="m 161.99999,543.00001 -1,0 0,1 1,0 0,-1 z m -2,0 -1,0 0,1 1,0 0,-1 z m -2,0 -1,0 0,1 1,0 0,-1 z m -2,0 -1,0 0,1 1,0 0,-1 z m -2,0 -1,0 0,1 1,0 0,-1 z"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.7;fill:#d7e3f4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.39999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 160.99999,542.00001 0,-0.5 -2,-2 0,2.5 2,0 z"
+ id="path22348"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path22340"
+ style="fill:none;stroke:url(#linearGradient28583);stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 158.99999,542.50001 2.5,0 0,-1 -2.25,-2.25 m 4.25,4.25 0,-2 -3,-3 0.5,-0.5"
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient28580);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 162.49999,542.50001 -1,1 -8,0 0,6 8.25,0 1,-1"
+ id="path22342"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path22345"
+ style="fill:none;stroke:url(#linearGradient28577);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 164.49999,542.50001 2,0 0,-6 -5.5,0 -1.5,1.5 0,0.5 3,3 0,1"
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ d="m 160.74999,536.50001 -1.25,1.25 0,0.75 3,3 0,1"
+ style="fill:none;stroke:url(#linearGradient28574);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path22368"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="542"
+ x="162"
+ height="6.25"
+ width="1"
+ id="rect38915"
+ 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)">
+ <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)">
+ <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" />
+ </g>
+ <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" />
+ </g>
+ </g>
+ </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"
+ transform="translate(-21,0)">
+ <g
+ style="display:inline;enable-background:new"
+ id="g38076"
+ transform="translate(173.70204,-41.325069)">
+ <g
+ transform="translate(1,1.0000001)"
+ id="g38078">
+ <g
+ id="g38080"
+ 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="rect38082"
+ 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="rect38084"
+ width="0.99999899"
+ height="1"
+ x="170.0161"
+ y="177.01379" />
+ <rect
+ y="177.01379"
+ x="168.0161"
+ height="1"
+ width="1"
+ id="rect38086"
+ 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="rect38088"
+ width="1"
+ height="1"
+ x="166.0161"
+ y="177.01379" />
+ <rect
+ y="179.01379"
+ x="166.0161"
+ height="1"
+ width="1"
+ id="rect38090"
+ 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="rect38092"
+ 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="rect38094"
+ 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="rect38096"
+ 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="rect38098"
+ width="1"
+ height="1"
+ x="166.0161"
+ y="183.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="rect38173"
+ width="0.99999899"
+ height="1"
+ x="178.0161"
+ y="177.01379" />
+ <rect
+ y="177.01379"
+ x="176.0161"
+ height="1"
+ width="1"
+ id="rect38175"
+ 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="189.01379"
+ x="166.0161"
+ height="1"
+ width="1"
+ id="rect38181"
+ 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="187.01379"
+ x="166.0161"
+ height="1"
+ width="1"
+ id="rect38183"
+ 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
+ transform="translate(-40.70204,21.325054)"
+ id="g38100"
+ style="fill:#000000">
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect38102"
+ width="1"
+ height="1"
+ x="166.00002"
+ y="178.00002" />
+ <rect
+ y="180.00002"
+ x="166.00002"
+ height="1"
+ width="1"
+ id="rect38104"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect38106"
+ width="1"
+ height="1"
+ x="167.00002"
+ y="177.00002" />
+ <rect
+ y="177.00002"
+ x="169.00002"
+ height="1"
+ width="1"
+ id="rect38108"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect38110"
+ width="1"
+ height="1"
+ x="171.00002"
+ y="177.00002" />
+ <rect
+ y="182.00002"
+ x="166.00002"
+ height="1"
+ width="1"
+ id="rect38112"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect38114"
+ width="1"
+ height="1"
+ x="173"
+ y="177.00002" />
+ <rect
+ y="177.00002"
+ x="175"
+ height="1"
+ width="1"
+ id="rect38116"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect38118"
+ width="1"
+ height="1"
+ x="166"
+ y="184" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect38120"
+ width="1"
+ height="1"
+ x="166"
+ y="186" />
+ <rect
+ y="177.00002"
+ x="177"
+ height="1"
+ width="1"
+ id="rect38169"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ y="188.00002"
+ x="166"
+ height="1"
+ width="1"
+ id="rect38177"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ </g>
+ </g>
+ <g
+ id="g38190"
+ transform="matrix(-1,0,0,-1,264.59592,410.65014)">
+ <g
+ transform="translate(-40.718137,21.311275)"
+ id="g38192"
+ 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="rect38194"
+ width="1"
+ height="1"
+ x="166.0161"
+ y="181.01379" />
+ <rect
+ y="177.01379"
+ x="170.0161"
+ height="1"
+ width="0.99999899"
+ id="rect38196"
+ 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="rect38198"
+ width="1"
+ height="1"
+ x="168.0161"
+ y="177.01379" />
+ <rect
+ y="177.01379"
+ x="166.0161"
+ height="1"
+ width="1"
+ id="rect38200"
+ 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="rect38203"
+ 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="rect38205"
+ width="0.99999899"
+ height="1"
+ x="174.0161"
+ y="177.01379" />
+ <rect
+ y="177.01379"
+ x="172.0161"
+ height="1"
+ width="1"
+ id="rect38207"
+ 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="rect38209"
+ 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="rect38211"
+ 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="rect38215"
+ width="1"
+ height="1"
+ x="176.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="rect38219"
+ width="1"
+ height="1"
+ x="166.0161"
+ y="187.01379" />
+ </g>
+ <g
+ style="fill:#000000"
+ id="g38225"
+ transform="translate(-40.70204,21.325054)">
+ <rect
+ y="178.00002"
+ x="166.00002"
+ height="1"
+ width="1"
+ id="rect38227"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect38229"
+ width="1"
+ height="1"
+ x="166.00002"
+ y="180.00002" />
+ <rect
+ y="177.00002"
+ x="167.00002"
+ height="1"
+ width="1"
+ id="rect38231"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect38233"
+ width="1"
+ height="1"
+ x="169.00002"
+ y="177.00002" />
+ <rect
+ y="177.00002"
+ x="171.00002"
+ height="1"
+ width="1"
+ id="rect38235"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect38237"
+ width="1"
+ height="1"
+ x="166.00002"
+ y="182.00002" />
+ <rect
+ y="177.00002"
+ x="173"
+ height="1"
+ width="1"
+ id="rect38239"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect38241"
+ width="1"
+ height="1"
+ x="175"
+ y="177.00002" />
+ <rect
+ y="184"
+ x="166"
+ height="1"
+ width="1"
+ id="rect38243"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ y="186"
+ x="166"
+ height="1"
+ width="1"
+ id="rect38245"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect38247"
+ width="1"
+ height="1"
+ x="177"
+ y="177.00002" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect38251"
+ width="1"
+ height="1"
+ x="166"
+ y="188.00002" />
+ </g>
+ </g>
+ </g>
+ <path
+ sodipodi:nodetypes="cccccc"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000048px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 301.5,168.92817 5e-5,-9.44187 11.99995,0 0,12.00195 -12,0.0118 0,-2.57183 0,-5e-5 z"
+ id="path37737-4"
+ inkscape:connector-curvature="0" />
+ <rect
+ 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="rect37061-2"
+ width="2.9998772"
+ height="3"
+ x="305.5"
+ y="161.5"
+ ry="0"
+ rx="0" />
+ <rect
+ rx="0"
+ ry="0"
+ y="164.5"
+ x="303.50012"
+ height="3"
+ width="2.9998772"
+ id="rect38072"
+ 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" />
+ <rect
+ 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="rect38074"
+ width="2.9998772"
+ height="3"
+ x="306.50012"
+ y="165.5"
+ ry="0"
+ rx="0" />
+ </g>
+ <g
+ id="g38397"
+ transform="translate(20.999878,0)">
+ <rect
+ rx="0"
+ ry="0"
+ y="158.5"
+ x="283.50012"
+ height="3"
+ width="2.9998772"
+ id="rect38277"
+ 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" />
+ <rect
+ 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="rect38279"
+ width="2.9998772"
+ height="3"
+ x="280.50012"
+ y="167.5"
+ ry="0"
+ rx="0" />
+ <rect
+ rx="0"
+ ry="0"
+ y="164.5"
+ x="288.50024"
+ height="3"
+ width="2.9998772"
+ id="rect38281"
+ 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"
+ transform="translate(436,-380)">
+ <rect
+ y="516"
+ x="-95"
+ height="16"
+ width="16"
+ id="rect36540"
+ 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="g36458"
+ transform="translate(-122,1.3e-4)">
+ <g
+ id="g36460"
+ style="opacity:0.75"
+ transform="translate(-116,424.99975)">
+ <g
+ transform="translate(-179,199.50012)"
+ id="g36462">
+ <path
+ id="path36464"
+ d="m 328.5,-107.25 -4.5,1.75 0,6.5 4.5,2.25 4.25,-2 0,-6.75 -4.25,-1.75 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.00000167;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(179,-179)"
+ id="g36468">
+ <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 154,80 0,-6.5 -4.5,-1.75 0,10.5 L 154,80 z"
+ id="path36470"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 324,-99.00012 0,-6.49988 4.5,-1.75 0.5,0.25 0,10 -0.5,0.25 -4.5,-2.25012 z"
+ id="path36466"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient38049);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 332.5,-105.5 0,6.25 -4,2 -4,-2.00012 0,-6.24988"
+ id="path36474"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ sodipodi:nodetypes="ccccc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 324,-105.5 4.5,-1.75 4.5,1.75 -4.5,2 -4.5,-2 z"
+ id="path36472"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccc"
+ style="opacity:0.95999995;fill:none;stroke:url(#linearGradient38051);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 145.5,94.25012 c 0,0 4,1.75 4,1.75 l 4,-1.75"
+ id="path36476"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.35;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36479"
+ width="1"
+ height="6.7500019"
+ x="149"
+ y="96.000122" />
+ <rect
+ y="96.000122"
+ x="150"
+ height="6.7500019"
+ width="1"
+ id="rect36481"
+ style="opacity:0.09599998;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <rect
+ rx="0"
+ ry="0"
+ y="517.49976"
+ x="27.500006"
+ height="3.0001416"
+ width="2.9999485"
+ id="rect36486"
+ style="fill:none;stroke:#8c4800;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:none;stroke:#8c4800;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="rect36489"
+ width="2.9999485"
+ height="3.0001416"
+ x="27.500006"
+ y="524.49951"
+ ry="0"
+ rx="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path36496"
+ d="m 28.000006,520.49983 -0.5,0 0,-3.00014 2.99995,0"
+ style="fill:none;stroke:#5a2f00;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#5a2f00;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"
+ d="m 28.000006,524.49978 -0.5,0 0,3.00014 2.99995,0"
+ id="path36499"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#ffd4a5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36503"
+ width="1.9999485"
+ height="2.0000772"
+ x="28.000051"
+ y="517.99988"
+ ry="0"
+ rx="0" />
+ <rect
+ style="fill:#ffd4a5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36507"
+ width="1.9999485"
+ height="2.0000772"
+ x="28.000051"
+ y="524.99982"
+ ry="0"
+ rx="0" />
+ </g>
+ <g
+ transform="translate(-309,277)"
+ id="g36761-1"
+ style="display:inline;enable-background:new">
+ <path
+ style="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"
+ d="m 223,243 0,10 1,0 0,-1 1,0 1,0 0,2 1,0 0,1 1,0 0,-1 1,0 0,-2 -1,0 0,-2 1,0 1,0 0,-1 -1,0 0,-1 -1,0 0,-1 -1,0 0,-1 -1,0 0,-1 -1,0 0,-1 -1,0 0,-1 -1,0 z"
+ id="path36763-5"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g36765-2"
+ style="fill:#1a1a1a;display:inline;enable-background:new"
+ transform="translate(5,-6.0000002e-7)">
+ <rect
+ y="243"
+ x="218"
+ height="10"
+ width="1"
+ id="rect36767-7"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="244"
+ x="219"
+ height="1"
+ width="1"
+ id="rect36769-6"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="245"
+ x="220"
+ height="1"
+ width="1"
+ id="rect36771-1"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="246"
+ x="221"
+ height="1"
+ width="1"
+ id="rect36773-4"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="247"
+ x="222"
+ height="1"
+ width="1"
+ id="rect36775-2"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="248"
+ x="223"
+ height="1"
+ width="1"
+ id="rect36777-3"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="249"
+ x="224"
+ height="1"
+ width="1.0000017"
+ id="rect36779-2"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="252"
+ x="219"
+ height="1"
+ width="1"
+ id="rect36781-2"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="251"
+ x="220"
+ height="1"
+ width="1"
+ id="rect36783-1"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="252"
+ x="221"
+ height="2"
+ width="1"
+ id="rect36785-6"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="250"
+ x="222.25"
+ height="2"
+ width="0.75"
+ id="rect36787-8"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="252"
+ x="223"
+ height="1.9999931"
+ width="1"
+ id="rect36789-5"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="254"
+ x="222"
+ height="1.0000006"
+ width="1.5"
+ id="rect36791-7"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36793-6"
+ width="1.5"
+ height="1"
+ x="223.5"
+ y="250" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g37508"
+ transform="translate(525,27.999998)">
+ <g
+ style="opacity:0.7"
+ id="g37302"
+ transform="translate(-244,373.99988)">
+ <g
+ transform="translate(-179,199.50012)"
+ id="g37304">
+ <path
+ id="path37306"
+ d="m 328.5,-107.25 -4.5,1.75 0,6.5 4.5,2.25 4.5,-2.25 0,-6.5 -4.5,-1.75 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;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"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(179,-179)"
+ id="g37308">
+ <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 154,80 0,-6.5 -4.5,-1.75 0,10.5 L 154,80 z"
+ id="path37311"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 324,-99.00012 0,-6.49988 4.5,-1.75 0.5,0.25 0,10 -0.5,0.25 -4.5,-2.25012 z"
+ id="path37313"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient37530);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 332.5,-105.5 0,6.25 -4,2 -4,-2.00012 0,-6.24988"
+ id="path37316"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ sodipodi:nodetypes="ccccc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 324,-105.5 4.5,-1.75 4.5,1.75 -4.5,2 -4.5,-2 z"
+ id="path37318"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccc"
+ style="opacity:0.95999995;fill:none;stroke:url(#linearGradient37534);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 145.5,94.25012 c 0,0 4,1.75 4,1.75 l 4,-1.75"
+ id="path37320"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37322"
+ width="1"
+ height="6.7500019"
+ x="149"
+ y="96.000122" />
+ <rect
+ y="96.000122"
+ x="150"
+ height="6.7500019"
+ width="1"
+ id="rect37324"
+ style="opacity:0.09599998;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <g
+ id="g37284"
+ transform="translate(-524.98389,247.00001)">
+ <rect
+ y="218"
+ x="425"
+ height="16"
+ width="16"
+ id="rect37286"
+ 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(46.000035,99.00001)"
+ id="g37288"
+ style="display:inline">
+ <g
+ style="display:inline"
+ id="g37290"
+ transform="translate(-3.542969e-5,0)">
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path37292"
+ style="fill:none;stroke:#000000;stroke-width:3.0999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ d="m 388.23389,129.74998 4.25,-4.24999 m 0.98389,1.99999 -1.48389,-1.49999 m 0.48389,2.49999 -1.4142,-1.41422"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 387.98389,129.99999 c 0.78065,0.78065 0.78065,2.21936 0,3 -0.78064,0.78065 -2.21935,0.78065 -3,0 -0.78064,-0.78064 -0.78064,-2.21935 0,-3 0.78065,-0.78064 2.21936,-0.78064 3,0 z"
+ style="fill:none;stroke:#000000;stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path37504"
+ sodipodi:nodetypes="csssc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ d="m 388.23389,129.74998 4.25,-4.24999 m 0.98389,1.99999 -0.25,-0.25 m -0.75,1.25 -0.25,-0.25"
+ style="fill:none;stroke:#ffffff;stroke-width:1.50000191;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000034;display:inline"
+ id="path37294"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path37500"
+ style="fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ d="m 387.98389,129.99999 c 0.78064,0.78065 0.78064,2.21935 0,3 -0.78065,0.78065 -2.21936,0.78065 -3,0 -0.78065,-0.78065 -0.78065,-2.21935 0,-3 0.78064,-0.78065 2.21935,-0.78065 3,0 z"
+ sodipodi:nodetypes="czzzz"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ transform="matrix(1.99999,0,0,1.99999,571.48293,-823.49525)"
+ d="m -92,477.5 a 0.5,0.5 0 1 1 -1,0 0.5,0.5 0 1 1 1,0 z"
+ sodipodi:ry="0.5"
+ sodipodi:rx="0.5"
+ sodipodi:cy="477.5"
+ sodipodi:cx="-92.5"
+ id="path37506"
+ style="opacity:0.4;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ sodipodi:type="arc" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g37565">
+ <g
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ transform="matrix(0.7668704,0,0,0.7668711,19.45715,14.604317)"
+ id="g10270-1"
+ style="opacity:0.3;display:inline;enable-background:new">
+ <path
+ transform="matrix(0.75,0,0,0.75,29.5,135)"
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.39093411;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path10272-2"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(-0.683022,-0.07745026,0.0778507,-0.683064,209.4726,314.325)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path10275-3"
+ style="opacity:0.4;fill:url(#linearGradient38254);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:type="arc" />
+ </g>
+ <rect
+ y="178"
+ x="110"
+ height="16"
+ width="16"
+ id="rect37989"
+ 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"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ id="g38006"
+ transform="translate(-255.99996,227.9746)"
+ style="display:inline">
+ <rect
+ transform="matrix(1,5.251142e-6,0,1,0,0)"
+ y="-43.49577"
+ x="372.49994"
+ height="2.9999874"
+ width="3.0000761"
+ id="rect37525"
+ style="opacity:0.15;fill:none;stroke:#d5e5ff;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="0"
+ ry="0" />
+ <rect
+ transform="matrix(1,-5.25127e-6,0,-1,0,0)"
+ y="40.991806"
+ x="372.99994"
+ height="2.0000756"
+ width="2.0000861"
+ id="rect38010"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" />
+ <rect
+ ry="0"
+ rx="0"
+ style="fill:#ebf3ff;fill-opacity:1;fill-rule:nonzero;stroke:#004cbe;stroke-width:0.99999875;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="rect38012"
+ width="3.0000761"
+ height="2.9999874"
+ x="372.49994"
+ y="-43.49577"
+ transform="matrix(1,5.251142e-6,0,1,0,0)" />
+ </g>
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2.4000001;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:new"
+ d="m 114.5,192.5 -3,0 0,-3 m 13,0 0,3 -3,0 m -0.25,-13 3.25,0 0,3 m -13,0 0,-3 3,0"
+ id="path37498"
+ sodipodi:nodetypes="cccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccccccccc"
+ id="rect38140"
+ d="m 114.5,192.5 -3,0 0,-3 m 13,0 0,3 -3,0 m -0.25,-13 3.25,0 0,3 m -13,0 0,-3 3,0"
+ style="fill:none;stroke:url(#linearGradient37509);stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ 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" />
+ <g
+ transform="translate(-290,397)"
+ id="g37579"
+ style="display:inline">
+ <g
+ id="g37582">
+ <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" />
+ </g>
+ <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" />
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ id="g37577"
+ transform="translate(-105,-63)">
+ <g
+ style="opacity:0.8;display:inline;enable-background:new"
+ id="g37580"
+ transform="matrix(0.7668704,0,0,0.7668711,19.45715,14.604317)"
+ 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">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path37582"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.39093411;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.75,0,0,0.75,29.5,135)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient37613);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path37584"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path38120-7"
+ style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:2.28571391;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:new"
+ 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" />
+ </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="rect37586"
+ width="16"
+ height="16"
+ x="110"
+ y="178" />
+ <path
+ sodipodi:nodetypes="cccccccccccc"
+ id="path37608"
+ d="m 114.5,192.5 -3,0 0,-3 m 13,0 0,3 -3,0 m -0.25,-13 3.25,0 0,3 m -13,0 0,-3 3,0"
+ style="fill:none;stroke:#000000;stroke-width:2.4000001;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:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient37615);stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ d="m 114.5,192.5 -3,0 0,-3 m 13,0 0,3 -3,0 m -0.25,-13 3.25,0 0,3 m -13,0 0,-3 3,0"
+ id="path37610"
+ sodipodi:nodetypes="cccccccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g14409"
+ 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"
+ id="rect15296"
+ width="16"
+ height="16"
+ x="47"
+ y="92" />
+ <g
+ style="display:inline"
+ id="g15298"
+ transform="matrix(1.0756796,0,0,1.076923,-83.216744,-140.6923)"
+ 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\Kopia blender\.blender\icons\blender's iconset.png"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path15301"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.11492968;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.75,0,0,0.75,29.5,135)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.6;fill:url(#linearGradient14439-9);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path15303"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.6926913,-0.07795333,0.0789528,-0.6875008,210.6113,314.95068)" />
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path15305"
+ style="fill:none;stroke:url(#linearGradient14441-4);stroke-width:1.454548;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:type="arc"
+ transform="matrix(0.6391304,0,0,0.6383922,44.127271,148.16974)" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g14396"
+ transform="translate(4.7892764e-7,23)">
+ <rect
+ y="92"
+ x="68"
+ height="16"
+ width="16"
+ id="rect15309"
+ 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="g15311"
+ 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.0829765,0,0,1.0830206,-86.990103,-142.06175)"
+ style="display:inline">
+ <g
+ transform="matrix(0.928617,0,0,0.931035,10.2435,15.47372)"
+ id="g15313">
+ <path
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path15315"
+ style="fill:#7c7c7c;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.10805392;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ 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.8076551,0,0,0.8055247,44.427594,128.39229)" />
+ <path
+ transform="matrix(0.745771,0,0,0.7384254,52.598397,136.33161)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path15317"
+ style="opacity:0.7;fill:url(#linearGradient14433-1);fill-opacity:1;fill-rule:nonzero"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient14435-7);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path15319"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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.624995,0,0,0.625,68.0007,149.25)" />
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path15321"
+ style="fill:none;stroke:url(#linearGradient14437-6);stroke-width:1.4544518;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:type="arc"
+ transform="matrix(0.6837125,0,0,0.6818205,60.789416,142.9887)" />
+ </g>
+ <path
+ sodipodi:nodetypes="cc"
+ id="path15323"
+ d="m 147.27014,223.27443 c 0.22029,-2.14702 1.65545,-2.83866 3,-3"
+ style="fill:none;stroke:#ffffff;stroke-width:0.92336226px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.5;fill:none;stroke:#ffe680;stroke-width:0.9233622px;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;filter:url(#filter15421-1);enable-background:accumulate"
+ d="m 153.73381,225.66118 c 0,1 -1,2 -2,2"
+ id="path15325"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g37996"
+ 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"
+ id="rect37994"
+ width="16.000006"
+ height="16.000002"
+ x="-24.00001"
+ y="114" />
+ <path
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path37953"
+ style="fill:#ececec;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.10749674;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"
+ 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.8125568,0,0,0.8127302,-123.25796,26.09414)" />
+ <path
+ id="path37970"
+ d="m -18,116.34375 c -1.706032,0.60248 -3.053766,1.95022 -3.65625,3.65625 l 3.65625,0 0,-3.65625 z m 0,3.65625 0,4 4,0 0,-4 -4,0 z m 4,0 3.65625,0 C -10.94623,118.29397 -12.29397,116.94623 -14,116.34375 L -14,120 z m 0,4 0,3.65625 c 1.70603,-0.60248 3.05377,-1.95022 3.65625,-3.65625 L -14,124 z m -4,0 -3.65625,0 c 0.602484,1.70603 1.950218,3.05377 3.65625,3.65625 L -18,124 z"
+ style="fill:url(#linearGradient38073-8);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(0.749378,0,0,0.7495379,-114.92287,33.554528)"
+ 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:type="arc"
+ style="opacity:0.25;fill:url(#linearGradient38075-5);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.23055196;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path37963"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path37955"
+ style="fill:none;stroke:url(#linearGradient38077-1);stroke-width:1.45488834;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:type="arc"
+ transform="matrix(0.6874075,0,0,0.6872685,-106.73771,40.90046)" />
+ <path
+ style="opacity:0.7;fill:url(#linearGradient38079-2);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 -18,116.34375 c -1.706032,0.60248 -3.053766,1.95022 -3.65625,3.65625 l 3.65625,0 0,-3.65625 z"
+ id="path37972"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(4.7892764e-7,23)"
+ id="g38272"
+ style="display:inline;enable-background:new">
+ <g
+ id="g37676">
+ <rect
+ y="92"
+ x="26"
+ height="16"
+ width="16"
+ id="rect38274"
+ 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
+ transform="matrix(-0.7606373,-0.08449162,0.08669728,-0.7451645,124.04885,199.0823)"
+ 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path38284"
+ style="opacity:0.75;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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="fill:none;stroke:#000000;stroke-width:1.23076892;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path38294"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ transform="matrix(0.8125001,0,0,0.8125002,-73.250026,4.1249738)" />
+ <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.1;fill:none;stroke:url(#radialGradient38306-3);stroke-width:2.44404984;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path38296"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="10.07671"
+ d="m 140,118 a 8,10.07671 0 0 1 -15.99907,0.15349"
+ sodipodi:start="0"
+ sodipodi:end="3.12636"
+ transform="matrix(0.8077059,0,0,-0.2072667,-72.578821,124.6156)"
+ sodipodi:open="true" />
+ <path
+ transform="matrix(-0.7451139,-0.08394973,0.08492792,-0.7403854,122.33348,198.48526)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path15303-4"
+ style="opacity:0.15;fill:url(#linearGradient37646-4);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ sodipodi:type="arc" />
+ <path
+ transform="matrix(0.780896,0,0,0.2786183,-69.081831,66.644097)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:#000000;stroke-width:1.50070953;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="path38300"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 0 1 -15.99907,0.12186"
+ sodipodi:start="0"
+ sodipodi:end="3.12636"
+ 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
+ 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(#linearGradient37677);stroke-width:1.45454454;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:new"
+ id="path38298"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ transform="matrix(0.6875009,0,0,0.687501,-56.75013,18.874887)" />
+ <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:#000000;stroke-width:1.35088885;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="path38302"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -5.7e-4,-0.0952"
+ 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path38304"
+ style="opacity:0.18000004;fill:none;stroke:url(#linearGradient38313-7);stroke-width:1.0666672;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:new"
+ 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" />
+ </g>
+ </g>
+ <g
+ id="g39510"
+ transform="translate(-570,274)">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path44921"
+ d="m 653.5,356.5 -4,4 -7,0 -4,-4 0,-7 4,-4 7,0 4,4 0,7 z"
+ style="fill:url(#linearGradient39518);fill-opacity:1;fill-rule:nonzero;stroke:#550000;stroke-width:1;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" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path44926"
+ d="m 652.5,356 -3.5,3.5 -6,0 -3.5,-3.5 0,-6 3.5,-3.5 6,0 3.5,3.5 0,6 z"
+ style="fill:none;stroke:url(#linearGradient39520);stroke-width:1.20000005;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient39523);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 651.5,355.5 -2.75,3 -5.25,0 -3,-3 0,-5 3,-3 5,0 3,3 0,5 z"
+ id="path44954"
+ sodipodi:nodetypes="ccccccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(0.6567169,0.6567169,-0.6567304,0.6567304,736.47216,94.047762)"
+ style="display:inline;enable-background:new"
+ id="g51749-0-4">
+ <path
+ id="path51751-1-8"
+ style="fill:none;stroke:#aa0000;stroke-width:2.69179726;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 132.08133,266.03337 -7.61363,0 m 3.80681,3.80673 0,-7.61347"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path51753-2-2"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.29206276;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 128.27451,269.8401 0,-7.61347 m 3.80682,3.80674 -7.61363,0"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g40247"
+ 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"
+ id="rect40250"
+ width="16"
+ height="15.99988"
+ x="5"
+ y="514.00012" />
+ <g
+ transform="translate(70,178)"
+ id="g40252">
+ <g
+ transform="translate(-386,446.5)"
+ id="g40254">
+ <path
+ id="path40257"
+ 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:#422200;fill-opacity:1;fill-rule:evenodd;stroke:#281500;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:#efa351;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 324,-99.5 0,-7 6,-1.75 0,11.5 -0.5,0.25 -5.5,-3 z"
+ id="path40259"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(179,-179)"
+ id="g40261">
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ style="fill:#915515;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 156,79.5 0,-7 -5,-1.75 0,11.5 5,-2.75 z"
+ id="path40263"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ sodipodi:nodetypes="ccccc"
+ style="fill:#f5ca9b;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 145,72.5 5.5,-2 5.5,2 -5.5,2.5 -5.5,-2.5 z"
+ id="path40270"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="fill:none;stroke:url(#linearGradient40280);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="path40272"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ style="fill:url(#linearGradient40282);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40275"
+ width="1"
+ height="7.75"
+ x="-57"
+ y="342" />
+ <path
+ style="fill:none;stroke:url(#linearGradient40284);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="path40278"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(508.99432,90)"
+ id="g38556">
+ <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"
+ id="rect38558"
+ width="16"
+ height="16"
+ x="46"
+ y="-209.99432" />
+ <g
+ transform="translate(-113.99432,-362)"
+ id="g38560"
+ style="opacity:0.5">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path38563"
+ style="fill:none;stroke:#000000;stroke-width:2.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 -93.5,422.5 12,0 0,-12 -12,0 0,12 z m 0,-6 12,0 m -6.00001,-5.99959 0,12"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.7;fill:url(#linearGradient38689);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect38570"
+ width="13"
+ height="13"
+ x="-94.000008"
+ y="410"
+ rx="0"
+ ry="0" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ d="m -93.5,422.5 12,0 -1e-5,-11.99959 -12,0 1e-5,11.99959 z m 0,-6 12,0 m -6.00001,-5.99959 1e-5,11.99959"
+ style="fill:none;stroke:#f2f2f2;stroke-width:1;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="path38572"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path38574"
+ d="M -92.46875,415.53125 -92.5,411.5 l 4,0"
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient38693);stroke-width:1px;stroke-linecap:round"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient38695);stroke-width:1px;stroke-linecap:round"
+ d="M -86.46875,415.53125 -86.5,411.5 l 4,0"
+ id="path38577"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient38697);stroke-width:1px;stroke-linecap:round"
+ d="M -92.46875,421.53125 -92.5,417.5 l 4,0"
+ id="path38579"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path38581"
+ d="M -86.46875,421.53125 -86.5,417.5 l 4,0"
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient38701);stroke-width:1px;stroke-linecap:round"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ y="48"
+ x="-207.99432"
+ height="9"
+ width="9.0000038"
+ id="rect37920-7"
+ style="opacity:0.07999998;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g38583"
+ transform="translate(-137.99432,-356)">
+ <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="path38585"
+ d="m -70.5,411.5 0,-8 8,0 0,8 -8,0 z"
+ style="fill:#ffb769;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"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ style="fill:none;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"
+ d="m -70.5,411.5 0,-8 8,0"
+ id="path38588"
+ 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.4;fill:none;stroke:url(#linearGradient38703);stroke-width:1px;stroke-linecap:round;display:inline;enable-background:new"
+ d="M -68.46875,409.53125 -68.5,405.5 l 4,0"
+ id="path38590"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path38592"
+ d="m -64.53125,405.5 0.03125,4.03125 -4,0"
+ style="opacity:0.4;fill:none;stroke:url(#linearGradient38706);stroke-width:1px;stroke-linecap:round;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(505.99432,90)"
+ id="g38644">
+ <rect
+ y="-185.99432"
+ x="46"
+ height="16"
+ width="16"
+ id="rect38650"
+ 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"
+ transform="matrix(0,1,1,0,0,0)" />
+ <g
+ style="opacity:0.5"
+ id="g38652"
+ transform="translate(-98.99432,-362)">
+ <path
+ d="m -85.5,422.5 4,0 0,-12 -4,0 0,12 z m 0,-6 4,0"
+ style="fill:none;stroke:#000000;stroke-width:2.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"
+ id="path38654"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="410"
+ x="-86"
+ height="13"
+ width="4.9999924"
+ id="rect38657"
+ style="opacity:0.7;fill:url(#linearGradient38720);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ id="path38659"
+ style="fill:none;stroke:#f2f2f2;stroke-width:1;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 -85.49999,422.49959 -81.5,422.5 -81.50001,410.50041 -85.5,410.5 l 1e-5,11.99959 z m 0,-6 L -81.5,416.5"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient38723);stroke-width:1px;stroke-linecap:round"
+ d="M -84.46875,415.53125 -84.5,411.5 l 2,0"
+ id="path38661"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path38663"
+ d="M -84.46875,421.53125 -84.5,417.5 l 2,0"
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient38725);stroke-width:1px;stroke-linecap:round"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(1,0,0,1.7057638,-106.49432,-641.33135)"
+ id="g38665">
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:#ffb769;fill-opacity:1;fill-rule:nonzero;stroke:#462400;stroke-width:0.76566803;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 -71,412.03125 0,-8.2055 7,0 0,8.2055 -7,0 z"
+ id="path38668"
+ 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="path38670"
+ d="m -69,407.19668 0,-2.19843 2.75,0"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient38727);stroke-width:0.76566803px;stroke-linecap:round;display:inline;enable-background:new"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient38729);stroke-width:0.76566803px;stroke-linecap:round;display:inline;enable-background:new"
+ d="m -66,405.14481 0,2.19843 -2.75,0"
+ id="path38672"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient38731);stroke-width:0.76566803px;stroke-linecap:round;display:inline;enable-background:new"
+ d="m -69,410.71416 0,-2.19843 2.75,0"
+ id="path38674"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path38676"
+ d="m -66,408.6623 0,2.19843 -2.75,-10e-6"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient38736);stroke-width:0.76566803px;stroke-linecap:round;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g39152"
+ transform="translate(507.99432,90)">
+ <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"
+ id="rect39154"
+ width="16"
+ height="16"
+ x="46"
+ y="-229.99432" />
+ <g
+ transform="translate(-133.99432,-362)"
+ id="g39157"
+ style="opacity:0.55">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path39159"
+ style="fill:none;stroke:#000000;stroke-width:2.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 -93.5,422.5 12,0 0,-12 -12,0 0,12 z m 0,-6 12,0 m -6.00001,-5.99959 0,12"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.7;fill:url(#linearGradient39199);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect39161"
+ width="13"
+ height="13"
+ x="-94.000008"
+ y="410"
+ rx="0"
+ ry="0" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ d="m -93.5,422.5 12,0 -1e-5,-11.99959 -12,0 1e-5,11.99959 z m 0,-6 12,0 m -6.00001,-5.99959 1e-5,11.99959"
+ style="fill:none;stroke:#f2f2f2;stroke-width:1;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="path39163"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39165"
+ d="M -92.46875,415.53125 -92.5,411.5 l 4,0"
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient39201);stroke-width:1px;stroke-linecap:round"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient39203);stroke-width:1px;stroke-linecap:round"
+ d="M -86.46875,415.53125 -86.5,411.5 l 4,0"
+ id="path39167"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient39205);stroke-width:1px;stroke-linecap:round"
+ d="M -92.46875,421.53125 -92.5,417.5 l 4,0"
+ id="path39169"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39171"
+ d="M -86.46875,421.53125 -86.5,417.5 l 4,0"
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient39207);stroke-width:1px;stroke-linecap:round"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ style="opacity:0.07999998;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37922"
+ width="1.9785498"
+ height="10"
+ x="-215.97287"
+ y="48" />
+ <rect
+ style="opacity:0.07999998;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37896-1"
+ width="2.9785526"
+ height="10"
+ x="-227.99432"
+ y="48" />
+ <g
+ id="g39173"
+ transform="translate(-190.01023,-189.50001)">
+ <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="rect39175"
+ width="1.9999995"
+ height="9.999959"
+ x="-38.484093"
+ y="236.00082"
+ transform="matrix(1,2.1226448e-5,0,1,0,0)" />
+ <rect
+ transform="matrix(1,3.6759233e-5,0,1,0,0)"
+ y="236.5014"
+ x="-37.984093"
+ height="8.9999657"
+ width="0.9999997"
+ id="rect39178"
+ style="fill:#ffcb91;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="path39180"
+ d="m -37.484093,246.00001 -0.9549,0.0112 -0.0271,-10.01124 1.982,4e-5 0,1"
+ 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>
+ <rect
+ y="48"
+ x="-221.97287"
+ height="10"
+ width="2.9785526"
+ id="rect37920"
+ style="opacity:0.07999998;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ transform="translate(-184.01023,-189.50001)"
+ id="g39182">
+ <rect
+ transform="matrix(1,2.6522988e-5,0,1,0,0)"
+ y="236.00104"
+ x="-38.484093"
+ height="9.9999399"
+ width="1.9999998"
+ id="rect39184"
+ 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:#ffcb91;fill-opacity:1;fill-rule:nonzero;display:inline"
+ id="rect39186"
+ width="0.99999994"
+ height="9.0000439"
+ x="-37.984093"
+ y="236.50175"
+ transform="matrix(1,4.7261927e-5,0,1,0,0)" />
+ <path
+ 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 -38.484093,237.00001 0.018,-1.00004 1.982,4e-5 0,1"
+ id="path39189"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(-1,0,0,1,-252.97841,-189.50001)"
+ id="g39191">
+ <rect
+ transform="matrix(1,2.1226448e-5,0,1,0,0)"
+ y="236.00082"
+ x="-38.484093"
+ height="9.999959"
+ width="1.9999995"
+ id="rect39193"
+ 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:#ffcb91;fill-opacity:1;fill-rule:nonzero;display:inline"
+ id="rect39195"
+ width="0.9999997"
+ height="8.9999657"
+ x="-37.984093"
+ y="236.5014"
+ transform="matrix(1,3.6759233e-5,0,1,0,0)" />
+ <path
+ 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.484093,246.00001 -0.9549,0.0112 -0.0271,-10.01124 1.982,4e-5 0,1"
+ id="path39197"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g29977">
+ <rect
+ y="257"
+ x="136"
+ height="16"
+ width="16"
+ id="rect39211"
+ 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"
+ transform="matrix(0,1,1,0,0,0)" />
+ <g
+ transform="translate(353,-272)"
+ style="opacity:0.55"
+ id="g39213">
+ <path
+ d="m -93.5,422.5 12,0 0,-12 -12,0 0,12 z m 0,-6 12,0 m -6.00001,-5.99959 0,12"
+ style="fill:none;stroke:#000000;stroke-width:2.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"
+ id="path39215"
+ sodipodi:nodetypes="ccccccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="410"
+ x="-94.000008"
+ height="13"
+ width="13"
+ id="rect39217"
+ style="opacity:0.7;fill:url(#linearGradient39246);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ id="path39219"
+ style="fill:none;stroke:#f2f2f2;stroke-width:1;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 -93.5,422.5 12,0 -1e-5,-11.99959 -12,0 1e-5,11.99959 z m 0,-6 12,0 m -6.00001,-5.99959 1e-5,11.99959"
+ sodipodi:nodetypes="ccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient39248);stroke-width:1px;stroke-linecap:round"
+ d="M -92.46875,415.53125 -92.5,411.5 l 4,0"
+ id="path39221"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39223"
+ d="M -86.46875,415.53125 -86.5,411.5 l 4,0"
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient39252);stroke-width:1px;stroke-linecap:round"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39225"
+ d="M -92.46875,421.53125 -92.5,417.5 l 4,0"
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient39255);stroke-width:1px;stroke-linecap:round"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient39259);stroke-width:1px;stroke-linecap:round"
+ d="M -86.46875,421.53125 -86.5,417.5 l 4,0"
+ id="path39227"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ transform="matrix(0,-1,1,0,0,0)"
+ rx="0"
+ ry="0"
+ y="257.5"
+ x="-139.50027"
+ height="3"
+ width="2.9998772"
+ id="rect39229"
+ style="fill:none;stroke:#402100;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="opacity:0.07999998;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37866"
+ width="3.9785564"
+ height="4"
+ x="258"
+ y="137" />
+ <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="path39231"
+ d="m 258,137 c 0,0.6694 10e-6,1.3388 10e-6,2.0082 0.66939,0 1.33877,0 2.00817,0 0,-0.6694 -10e-6,-1.3388 -10e-6,-2.0082 -0.66939,0 -1.33878,0 -2.00817,0 z"
+ style="fill:#ffc17d;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="137"
+ x="265.02145"
+ height="4"
+ width="3.9785564"
+ id="rect37868"
+ style="opacity:0.07999998;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ transform="matrix(0,-1,1,0,0,0)"
+ style="fill:none;stroke:#402100;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="rect39233"
+ width="2.9998772"
+ height="3"
+ x="-139.50031"
+ y="264.49182"
+ ry="0"
+ rx="0" />
+ <rect
+ y="144"
+ x="258.02145"
+ height="4"
+ width="3.9785564"
+ id="rect37870"
+ style="opacity:0.07999998;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.07999998;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37896"
+ width="3.9785564"
+ height="4"
+ x="265.02145"
+ y="144" />
+ <path
+ style="fill:#ffc17d;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 264.99183,137 c 0,0.6694 1e-5,1.3388 1e-5,2.0082 0.66939,0 1.33877,0 2.00817,0 0,-0.6694 -10e-6,-1.3388 -10e-6,-2.0082 -0.66939,0 -1.33878,0 -2.00817,0 z"
+ id="path39235"
+ 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
+ rx="0"
+ ry="0"
+ y="257.49182"
+ x="-146.4921"
+ height="3"
+ width="2.9998772"
+ id="rect39237"
+ style="fill:none;stroke:#402100;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="matrix(0,-1,1,0,0,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="path39239"
+ d="m 257.99182,143.9918 c 0,0.6694 10e-6,1.3388 10e-6,2.0082 0.66939,0 1.33877,0 2.00817,0 0,-0.6694 -10e-6,-1.3388 -10e-6,-2.0082 -0.66939,0 -1.33878,0 -2.00817,0 z"
+ style="fill:#ffc17d;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <rect
+ transform="matrix(0,-1,1,0,0,0)"
+ style="fill:none;stroke:#402100;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="rect39241"
+ width="2.9998772"
+ height="3"
+ x="-146.4921"
+ y="264.5"
+ ry="0"
+ rx="0" />
+ <path
+ style="fill:#ffc17d;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 265,143.9918 c 0,0.6694 10e-6,1.3388 10e-6,2.0082 0.66939,0 1.33877,0 2.00817,0 0,-0.6694 -10e-6,-1.3388 -10e-6,-2.0082 -0.66939,0 -1.33878,0 -2.00817,0 z"
+ id="path39244"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g39098"
+ transform="translate(42,63)">
+ <rect
+ ry="0"
+ rx="0"
+ y="535"
+ x="488"
+ height="16"
+ width="16"
+ id="rect39095"
+ style="opacity:0;fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g39082">
+ <g
+ mask="url(#mask38956)"
+ id="g38942"
+ transform="translate(0,-21)">
+ <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="path38944"
+ d="m 489.5,570.5 7.5,0 c 7.75,0 6.25,-9 2.5,-9 l -1,0"
+ style="fill:none;stroke:#000000;stroke-width:2.79999995;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:nodetypes="cssc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cssc"
+ style="fill:none;stroke:url(#linearGradient39115);stroke-width:1.39999998;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 489,570.5 8,0 c 7.75,0 6.25,-9 2.5,-9 l -1,0"
+ id="path38946"
+ 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
+ sodipodi:nodetypes="cccsccccccc"
+ id="path38948"
+ d="m 493.5,535.5 c -0.554,0 -1,0.446 -1,1 l 0,8 c 0,0.554 0.446,1 1,1 0.554,0 1,-0.446 1,-1 l 1.5,0 c 1.939,0 3.5,-1.561 3.5,-3.5 l 0,-1 c 0,-1.939 -1.561,-3.5 -3.5,-3.5 l -1.5,0 c 0,-0.554 -0.446,-1 -1,-1 z"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffeeaa;fill-opacity:1;fill-rule:evenodd;stroke:#28220b;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 492.5,539.5 -3,0 c -0.54593,0 -0.98543,-0.4395 -0.98543,-0.98544 0,-0.54593 0.4395,-0.98543 0.98543,-0.98543 l 3,0"
+ id="rect38938"
+ sodipodi:nodetypes="ccscc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient39117);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 494.5,543.59375 1.5,0 c 1.45545,0 2.59375,-1.1383 2.59375,-2.59375 l 0,-1 c 0,-1.45545 -1.1383,-2.59375 -2.59375,-2.59375 l -1.5,0"
+ id="path39045"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ ry="0.5"
+ rx="0.49151421"
+ y="536"
+ x="493"
+ height="9"
+ width="1"
+ id="rect38950"
+ style="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" />
+ <path
+ style="fill:none;stroke:url(#linearGradient39119);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 494.5,542.5 1.5,0 c 0.94305,0 1.5,-0.55695 1.5,-1.5 l 0,-1 c 0,-0.94305 -0.55695,-1.5 -1.5,-1.5 l -1.5,0"
+ id="path39068"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.4;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect39052"
+ width="1"
+ height="7"
+ x="494"
+ y="537"
+ rx="0.49151421"
+ ry="0.5" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path39076"
+ d="m 494.5,542.5 1.5,0 c 0.94305,0 1.5,-0.55695 1.5,-1.5 l 0,-1 c 0,-0.94305 -0.55695,-1.5 -1.5,-1.5 l -1.5,0"
+ style="fill:none;stroke:url(#linearGradient39122);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccscc"
+ id="path39534"
+ d="m 492.5,543.47087 -3,0 c -0.54593,0 -0.98543,-0.4395 -0.98543,-0.98544 0,-0.54593 0.4395,-0.98543 0.98543,-0.98543 l 3,0"
+ style="fill:#ffeeaa;fill-opacity:1;fill-rule:evenodd;stroke:#28220b;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(-105,212.00008)"
+ id="g39237"
+ style="display:inline;enable-background:new">
+ <g
+ 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"
+ id="g39240"
+ transform="translate(5.4013367,9.4697686)"
+ 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="rect39242"
+ width="16"
+ height="16"
+ x="125.59866"
+ y="397.53015" />
+ <g
+ style="display:inline"
+ transform="translate(2.6147745,160.52205)"
+ 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="g39244">
+ <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.927848,0,0,0.916217,-28.19594,40.73172)"
+ id="g39246"
+ style="display:inline">
+ <path
+ transform="matrix(1.0155084,0,0,1.0286863,37.51084,101.58226)"
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient39261);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.8489247;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path39248"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ style="fill:none;stroke:url(#linearGradient39265);stroke-width:1.17973554;stroke-opacity:1;display:inline"
+ id="g39250"
+ 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">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path39252"
+ style="fill:none;stroke:url(#linearGradient39263);stroke-width:1.22986293;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(1.0337319,0,0,1.0470635,35.105336,99.413761)" />
+ </g>
+ </g>
+ </g>
+ <path
+ sodipodi:nodetypes="cccccccccccccccccccccccccc"
+ id="path39309"
+ transform="translate(105,-235.00008)"
+ d="m 32,645 0,1 -1,0 0,2 2,0 0,-1 2,0 0,2 -1,0 0,1.25 -1,0 0,1.75 2,0 0,-1.5 1,0 0,-1 1,0 0,-3.5 -1,0 0,-1 -4,0 z m 1,8 0,2 2,0 0,-2 -2,0 z"
+ style="opacity:0.5;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ d="m 32,645 0,1 -1,0 0,2 2,0 0,-1 2,0 -0.02802,1.97638 -1,0 L 34,650.25 l -1,0 0,1.75 2,0 0,-1.5 1,0 0,-1 1,0 0,-3.5 -1,0 0,-1 -4,0 z m 1,8 0,2 2,0 0,-2 -2,0 z"
+ transform="translate(105,-235.00008)"
+ id="path11803-1"
+ sodipodi:nodetypes="cccccccccccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-3.0078133e-8,128.00008)"
+ id="g39694"
+ style="display:inline;enable-background:new">
+ <g
+ 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"
+ id="g39696"
+ transform="translate(5.4013367,9.4697686)"
+ 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="rect39698"
+ width="16"
+ height="16"
+ x="125.59866"
+ y="397.53015" />
+ <g
+ style="display:inline"
+ transform="translate(2.6147745,160.52205)"
+ 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="g39700">
+ <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.927848,0,0,0.916217,-28.19594,40.73172)"
+ id="g39702"
+ style="display:inline">
+ <path
+ transform="matrix(0.8835182,0,0,0.8949854,54.933548,117.35897)"
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient39261-4-5);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.97574574;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="path39704"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ style="fill:none;stroke:url(#linearGradient39718);stroke-width:1.17973554;stroke-opacity:1;display:inline"
+ id="g39706"
+ 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">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path39708"
+ style="fill:none;stroke:url(#linearGradient39716);stroke-width:1.44816053;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.87787,0,0,0.889264,55.67911,118.0341)" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g39802"
+ style="opacity:0.7;stroke:#000000">
+ <path
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000"
+ d="m 138,413.99992 c 0.25,0 2,0 2,0 l 0,4 0.75,0 0,1 -3.5,0 0,-1 0.75,0 0,-3 c -0.66667,0 4.15703,0 -1.25,0 l 0.5,-1 0.75,0 z"
+ id="path39804"
+ sodipodi:nodetypes="cccccccccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect39806"
+ width="2"
+ height="2"
+ x="138"
+ y="410.99991"
+ rx="0"
+ ry="0" />
+ </g>
+ <g
+ id="g39798">
+ <path
+ sodipodi:nodetypes="cccccccccccc"
+ id="path39710"
+ d="m 138,413.99992 c 0.25,0 2,0 2,0 l 0,4 0.75,0 0,1 -3.5,0 0,-1 0.75,0 0,-3 c -0.66667,0 4.15703,0 -1.25,0 l 0.5,-1 0.75,0 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="410.99991"
+ x="138"
+ height="2"
+ width="2"
+ id="rect39712"
+ style="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" />
+ </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" />
+ <g
+ id="g40270"
+ transform="translate(146.99999,-417.99999)">
+ <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" />
+ <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" />
+ <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" />
+ </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" />
+ </g>
+ <g
+ id="g39333"
+ 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"
+ id="rect38951"
+ width="16"
+ height="16"
+ x="26"
+ y="198" />
+ <g
+ style="display:inline;enable-background:new"
+ id="g39096-7"
+ transform="translate(26.00079,19.1)">
+ <rect
+ rx="1.3125"
+ ry="1.3125001"
+ y="180.53122"
+ x="5.4992032"
+ height="9.9687805"
+ width="10.000007"
+ id="rect39098-7"
+ style="fill:url(#linearGradient40731);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path39100-7"
+ d="m 6.5,181.53121 7.99921,0 0,7.96879 -7.99921,0 0,-7.96879 z"
+ style="fill:none;stroke:url(#linearGradient40733-0);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(-1.00079,-19)"
+ style="fill:#ffffff;display:inline;enable-background:new"
+ id="g39118-3">
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 10.25,199 c -0.1385,0 -0.25,0.1115 -0.25,0.25 l 0,1.75 -0.5,0 c -0.277,0 -0.5,0.223 -0.5,0.5 0,0.277 0.223,0.5 0.5,0.5 l 4,0 c 0.277,0 0.5,-0.223 0.5,-0.5 0,-0.277 -0.223,-0.5 -0.5,-0.5 l -0.5,0 0,-1.75 C 13,199.1115 12.8885,199 12.75,199 l -2.5,0 z"
+ id="path39183-3"
+ inkscape:connector-curvature="0" />
+ <path
+ id="rect39114-5"
+ d="m 10.25,199 c -0.1385,0 -0.25,0.1115 -0.25,0.25 l 0,1.75 -0.5,0 c -0.277,0 -0.5,0.223 -0.5,0.5 0,0.277 0.223,0.5 0.5,0.5 l 4,0 c 0.277,0 0.5,-0.223 0.5,-0.5 0,-0.277 -0.223,-0.5 -0.5,-0.5 l -0.5,0 0,-1.75 C 13,199.1115 12.8885,199 12.75,199 l -2.5,0 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="opacity:0.45;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 9.49921,181.5 2,0"
+ id="path39106-9"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(0,-1,-1,0,212.75,247.25)"
+ id="g38966">
+ <g
+ id="g38968"
+ transform="matrix(-1,0,0,-1,215.25,222.75)">
+ <path
+ sodipodi:nodetypes="ccc"
+ style="fill:none;stroke:#000000;stroke-width:2.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 174.5,38.5 0,5 5,0"
+ id="path38970"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cz"
+ id="path38972"
+ style="fill:none;stroke:#000000;stroke-width:3.20000005;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"
+ d="m 175.5,42.5 5,-5"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-146.75,127.75)"
+ id="g38975">
+ <g
+ style="display:inline"
+ transform="matrix(-1,0,0,-1,272.1613,155.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="g38977">
+ <path
+ d=""
+ sodipodi:nodetypes="cz"
+ id="path38984"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cz"
+ id="path38987"
+ style="opacity:0.85;fill:none;stroke:#ffffff;stroke-width:1.5;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"
+ d=""
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 188,51 0,6 -1,0 0,-5 -5,0 0,-1 6,0 z"
+ id="path38994"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g38996"
+ style="opacity:0.2"
+ transform="matrix(-1,0,0,1,-29,-335)">
+ <path
+ style="fill:#333333;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -216,387 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ id="path38998"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ transform="matrix(-1,0,0,-1,118.4113,290.74999)"
+ 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="g39000">
+ <path
+ d=""
+ sodipodi:nodetypes="cz"
+ id="path39015"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cz"
+ id="path39017"
+ style="fill:none;stroke:#ffffff;stroke-width:1.5;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"
+ d="m 78.1613,110.99999 5.5,-5.5"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(-1,0,0,1,-175.75,-207.25)"
+ style="opacity:0.2"
+ id="g39020">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path39022"
+ d="m -216,387 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ style="opacity:0.7;fill:#333333;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g39306"
+ transform="translate(-1,-62)">
+ <rect
+ y="198"
+ x="6"
+ height="16"
+ width="16"
+ id="rect38948"
+ 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" />
+ <g
+ id="g39096"
+ transform="translate(1.00079,19)">
+ <rect
+ rx="1.3125"
+ ry="1.3125001"
+ y="180.53122"
+ x="5.4992032"
+ height="9.9687805"
+ width="10.000007"
+ id="rect39098"
+ style="fill:url(#linearGradient40731);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path39100"
+ d="m 6.5,181.53121 7.99921,0 0,7.96879 -7.99921,0 0,-7.96879 z"
+ style="fill:none;stroke:url(#linearGradient40733);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(-1.00079,-19)"
+ style="fill:#ffffff;display:inline;enable-background:new"
+ id="g39118">
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 10.25,199 c -0.1385,0 -0.25,0.1115 -0.25,0.25 l 0,1.75 -0.5,0 c -0.277,0 -0.5,0.223 -0.5,0.5 0,0.277 0.223,0.5 0.5,0.5 l 4,0 c 0.277,0 0.5,-0.223 0.5,-0.5 0,-0.277 -0.223,-0.5 -0.5,-0.5 l -0.5,0 0,-1.75 C 13,199.1115 12.8885,199 12.75,199 l -2.5,0 z"
+ id="path39183"
+ inkscape:connector-curvature="0" />
+ <path
+ id="rect39114"
+ d="m 10.25,199 c -0.1385,0 -0.25,0.1115 -0.25,0.25 l 0,1.75 -0.5,0 c -0.277,0 -0.5,0.223 -0.5,0.5 0,0.277 0.223,0.5 0.5,0.5 l 4,0 c 0.277,0 0.5,-0.223 0.5,-0.5 0,-0.277 -0.223,-0.5 -0.5,-0.5 l -0.5,0 0,-1.75 C 13,199.1115 12.8885,199 12.75,199 l -2.5,0 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="opacity:0.45;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 9.49921,181.5 2,0"
+ id="path39106"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g39052"
+ transform="matrix(0,1,-1,0,199.75,171.75)">
+ <g
+ transform="matrix(-1,0,0,-1,215.25,222.75)"
+ id="g39054">
+ <path
+ id="path39056"
+ d="m 174.5,38.5 0,5 5,0"
+ style="fill:none;stroke:#000000;stroke-width:2.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 175.5,42.5 5,-5"
+ style="fill:none;stroke:#000000;stroke-width:3.20000005;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="path39058"
+ sodipodi:nodetypes="cz"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g39060"
+ transform="translate(-146.75,127.75)">
+ <g
+ id="g39062"
+ 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,0,0,-1,272.1613,155.99999)"
+ style="display:inline">
+ <path
+ 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"
+ id="path39064"
+ sodipodi:nodetypes="cz"
+ d=""
+ inkscape:connector-curvature="0" />
+ <path
+ d=""
+ style="opacity:0.85;fill:none;stroke:#ffffff;stroke-width:1.5;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="path39066"
+ sodipodi:nodetypes="cz"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path39069"
+ d="m 188,51 0,6 -1,0 0,-5 -5,0 0,-1 6,0 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(-1,0,0,1,-29,-335)"
+ style="opacity:0.2"
+ id="g39071">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path39073"
+ d="m -216,387 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ style="fill:#333333;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g39076"
+ 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,0,0,-1,118.4113,290.74999)"
+ style="display:inline">
+ <path
+ 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"
+ id="path39078"
+ sodipodi:nodetypes="cz"
+ d=""
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 78.1613,110.99999 5.5,-5.5"
+ style="fill:none;stroke:#ffffff;stroke-width:1.5;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="path39080"
+ sodipodi:nodetypes="cz"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g39083"
+ style="opacity:0.2"
+ transform="matrix(-1,0,0,1,-175.75,-207.25)">
+ <path
+ style="opacity:0.7;fill:#333333;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -216,387 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ id="path39085"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g40848"
+ 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"
+ id="rect40824"
+ width="16"
+ height="16"
+ x="-17"
+ y="94" />
+ <g
+ id="g39622"
+ transform="translate(-3.2236328e-6,0.9999981)">
+ <g
+ transform="translate(-83.999951,1.9073486e-6)"
+ style="opacity:0.6"
+ id="g40663">
+ <rect
+ style="fill:url(#linearGradient40875-3-9-8);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect40665"
+ width="7.9999967"
+ height="9.9999981"
+ x="69.499954"
+ y="94.5"
+ rx="0"
+ ry="0" />
+ <rect
+ style="fill:none;stroke:url(#linearGradient40877-5-5-9);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="rect40667"
+ width="5.9999967"
+ height="7.9999981"
+ x="70.499954"
+ y="95.5"
+ rx="0"
+ ry="0" />
+ </g>
+ <g
+ id="g40669"
+ transform="translate(-85,-1)">
+ <rect
+ 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:0"
+ id="rect40671"
+ width="8.0000029"
+ height="9.0000019"
+ x="73.5"
+ y="98.5"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="99"
+ x="74"
+ height="9"
+ width="7"
+ id="rect40673"
+ style="fill:url(#linearGradient40879-9-8-1);fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <path
+ style="fill:none;stroke:#333333;stroke-width:0.7499997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0"
+ d="m 73.5,103.75 0,-5.25 4,0"
+ id="path40675"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:none;stroke:url(#linearGradient40881-8-0-8);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="rect40677"
+ width="6.0000033"
+ height="7.0000019"
+ x="74.5"
+ y="99.5"
+ rx="0"
+ ry="0" />
+ </g>
+ <rect
+ style="opacity:0.4;fill:url(#radialGradient40883-4-0-3);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ id="rect40679"
+ width="7.0000033"
+ height="8.0000019"
+ x="-11"
+ y="98"
+ rx="0"
+ ry="0" />
+ </g>
+ <g
+ transform="translate(-122.97615,-9.9999881)"
+ id="g40681">
+ <path
+ id="path40683"
+ d="m 116.47121,117.5 -3.99506,0"
+ style="fill:none;stroke:#2d2d2d;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ mask="none"
+ sodipodi:nodetypes="ccccccccccccsccc"
+ style="fill:#dcdcdc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 114.4449,117.46875 c 0,-1.65264 1.12861,-2.96875 2.78125,-2.96875 l 1.5,0 c 1.65264,0 2.71875,1.31617 2.71875,2.9688 l 0,0.0625 c 0,1.65264 -1.06611,2.9687 -2.71875,2.9687 l -1.5,0 c -1.65264,0 -2.78125,-1.31612 -2.78125,-2.96875 l 0,-0.0625 z m 2.03125,0.0312 c 0,0.554 0.2585,0.99995 0.8125,0.99995 l 1.40625,-0.0312 c 0.554,0 0.78125,-0.41475 0.78125,-0.96875 0,-0.554 -0.22725,-1.03125 -0.78125,-1.03125 l -1.40625,0.0312 c -0.554,0 -0.8125,0.44605 -0.8125,1.00005 z"
+ id="path40685"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="116"
+ x="115"
+ height="2.47615"
+ width="1"
+ id="rect40687"
+ style="opacity:0.7;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"
+ transform="matrix(0,1,1,0,0,0)" />
+ <rect
+ style="opacity:0.7;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"
+ id="rect40689"
+ width="1"
+ height="1"
+ x="116"
+ y="115"
+ transform="matrix(0,1,1,0,0,0)" />
+ <path
+ id="path40691"
+ d="m 106.4449,117.4688 c 0,-1.65264 1.12861,-2.96875 2.78125,-2.96875 l 1.5,-5e-5 c 1.65264,0 2.71875,1.31617 2.71875,2.9688 l 0,0.0625 c 0,1.65264 -1.06611,2.9687 -2.71875,2.9687 l -1.5,5e-5 c -1.65264,0 -2.78125,-1.31612 -2.78125,-2.96875 l 0,-0.0625 z m 2.03125,0.0312 c 0,0.554 0.2585,1 0.8125,1 l 1.4375,-5e-5 c 0.554,0 0.75,-0.44595 0.75,-0.99995 0,-0.554 -0.196,-1.00005 -0.75,-1.00005 l -1.4375,5e-5 c -0.554,0 -0.8125,0.446 -0.8125,1 z"
+ style="fill:#dcdcdc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccccccccsccc"
+ mask="none"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.7;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"
+ id="rect40693"
+ width="0.99998814"
+ height="2.5000362"
+ x="115"
+ y="107.97615"
+ transform="matrix(0,1,1,0,0,0)" />
+ <rect
+ y="106.97615"
+ x="116"
+ height="1"
+ width="1"
+ id="rect40695"
+ style="opacity:0.7;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"
+ transform="matrix(0,1,1,0,0,0)" />
+ <path
+ style="opacity:0.55;fill:none;stroke:#1a1a1a;stroke-width:2.79440284;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 116.47121,117.5 -4.99506,-1e-5"
+ id="path40697"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 116.47121,117.5 -4.99506,-1e-5"
+ id="path40699"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="118.97615"
+ x="119"
+ height="1"
+ width="1"
+ id="rect40701"
+ style="fill:#dcdcdc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="matrix(0,1,1,0,0,0)" />
+ <rect
+ style="fill:#dcdcdc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40703"
+ width="1"
+ height="1"
+ x="115"
+ y="118.97615"
+ transform="matrix(0,1,1,0,0,0)" />
+ <rect
+ style="fill:#dcdcdc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40705"
+ width="1"
+ height="1"
+ x="119"
+ y="111"
+ transform="matrix(0,1,1,0,0,0)" />
+ <rect
+ y="111"
+ x="115"
+ height="1"
+ width="1"
+ id="rect40707"
+ style="fill:#dcdcdc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="matrix(0,1,1,0,0,0)" />
+ <rect
+ style="opacity:0.15;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40709"
+ width="1"
+ height="0.97614998"
+ x="117"
+ y="118"
+ transform="matrix(0,1,1,0,0,0)" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g40697"
+ 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"
+ inkscape:export-ydpi="90">
+ <rect
+ y="29"
+ x="-31"
+ height="16"
+ width="16"
+ id="rect40643"
+ 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="g40513"
+ style="opacity:0.8">
+ <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="path40465"
+ d="M -27.80208,29.59375 -19.5,29.5 -19.53126,42.40625 -30.5,42.5 l 0.03125,-9.90625 2.66667,-3 z"
+ style="fill:url(#linearGradient40511-7-9-5);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ d="m -29.5,34 0,7.5 m 3.5,-11 5.5,0"
+ style="fill:none;stroke:url(#linearGradient40507-4-8-1);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ id="path40469"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.5;fill:url(#radialGradient40649-2-6-6);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="M -27.80208,29.59375 -19.5,29.5 -19.53126,42.40625 -30.5,42.5 l 0.03125,-9.90625 2.66667,-3 z"
+ id="path40645"
+ 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
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m -31,33 4,0 0,-4 -4,4 z"
+ id="path40471"
+ 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 -30.5,32.00001 0,10.49999 11,-1e-5 0,-12.99999 -8.5,10e-6 -2.5,2.5 0,0 0,0 0,0 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="path40473"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40475"
+ d="m -26.5,31.5 0,2 -2,0"
+ style="fill:none;stroke:url(#linearGradient40502-7-8-3);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g40263"
+ transform="matrix(0.8738816,0,0,0.8823479,-135.18828,-60.939841)"
+ 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">
+ <path
+ sodipodi:type="arc"
+ style="fill:#3771c8;fill-opacity:1;fill-rule:nonzero;stroke:#040910;stroke-width:1.45371544;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="path40265"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path40267"
+ style="fill:url(#linearGradient40635-7-2-2);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ 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.666432,0,0,0.659342,42.69924,35.46375)" />
+ <path
+ transform="matrix(0.3631382,0,0,0.3593485,81.755824,69.904768)"
+ 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:type="arc"
+ style="opacity:0.7;fill:url(#linearGradient40637-9-5-8);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path40269"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path40271"
+ d="m 274.98515,70.995347 c 0,0.953349 -1,1.906699 -2,1.906699"
+ style="opacity:0.5;fill:none;stroke:#ffe680;stroke-width:1.18410921px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;filter:url(#filter13996-9-7-7)"
+ transform="matrix(0.9688184,0,0,0.9547322,-131.63668,47.640696)"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccccssscsscccscccccccccccccccsccccc"
+ id="path40273"
+ d="m 130.67404,112.3079 c 0.0244,0.78706 -0.15754,1.63085 0.59269,2.02213 0.71197,-0.0434 1.49133,0.64122 1.35667,1.40517 -0.26776,0.77861 0.14071,1.12325 0.95576,1.36401 0.57868,-0.0716 0.79053,-0.93546 0.87357,-1.36401 0.0948,-1.27121 0.51542,-1.09421 0.82108,-1.98991 -0.45733,-0.91502 -0.003,-1.04443 -0.72629,-1.43739 m -1.00945,-3.89288 c -0.4426,0.34378 -0.24372,1.04314 -0.66162,1.39841 -0.45372,0.13628 -0.78226,-0.0605 -1.16771,0.43164 -0.30841,1.10457 0.35004,1.22306 0.90205,1.10457 0.49538,-0.0502 0.61419,-0.94321 0.97928,-0.37853 0.0831,0.10976 0.71917,-0.0403 0.86266,0.18898 0.0669,0.10682 -0.11785,0.0255 -0.14729,0.18955 -0.0428,0.23847 0.27734,0.37341 0.372,0.3824 0.32089,0.0305 0.60005,0.92548 0.83846,1.05499 0,0.46738 0.0924,-0.6774 0.3515,-0.78703 0.22948,-0.0971 0.47929,0.10731 0.5,0 0.29928,-1.55081 -1.26113,-3.00604 -2.82933,-3.58498 z M 128.96474,107.5 c -0.6111,1.01384 0.85343,1.46103 1.73001,1.21329 0.57897,-0.37879 1.00716,-0.92331 0.55665,-1.21329 -0.20614,-0.1415 -2.07706,0.0431 -2.28666,0 l 0,0 0,0 0,0 z m -1.372,1.37253 c -0.49575,-0.14959 0.44952,-0.11945 0.45733,0.45751 0.1696,0.54756 -0.42801,0.23756 0,0.45752 0.70893,0.1644 0.35328,1.70031 -0.28114,1.56208 -0.56042,0.10119 -0.43915,0.95826 -1.64865,0.88279 -0.0836,0.0755 -1.04512,0.61593 -0.81421,1.21521 1.12968,0.30162 -0.36816,1.26478 -0.43867,0.55236 -0.15441,-0.49797 -0.62853,-1.11348 -0.43994,-1.68674 0.11734,-0.63627 0.5689,-1.12263 0.82646,-1.69865 0.36225,-0.61946 0.89084,-1.17688 1.57758,-1.42595 0.21411,-0.16799 0.46159,-0.41691 0.76124,-0.31613 l 0,0 0,0 0,0 z m -0.91467,5.03262 c -0.55163,-0.27585 -0.72934,0.28829 -0.60377,0.7984 0.15577,0.47138 0.52607,0.97695 0.72628,1.43739 0.40435,0.49619 1.512,1.34081 2.17883,1.67696 0.31768,0.16015 0.48418,0 0.24209,-0.23956 -0.31367,-0.6375 -1.14073,-1.94893 -0.48418,-2.15609 0.59647,-0.60342 0.34203,-1.58773 -0.48419,-1.43739 -0.54779,-0.25818 -0.75551,-0.39899 -1.38855,-0.0752 -0.0558,0.0743 -0.12403,0.006 -0.18651,-0.004 l 0,-5.1e-4 0,0 0,0 z"
+ style="fill:url(#linearGradient40639-1-2-1);fill-opacity:1;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\Kopia blender\.blender\icons\blender's iconset.png"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path40275"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient40641-9-2-7);stroke-width:1.78065979;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:type="arc"
+ transform="matrix(0.6429129,0,0,0.6362007,45.809534,38.194473)" />
+ <path
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path40277"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ 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.06052282,0,0,0.05989117,121.21686,103.80334)" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g41840"
+ transform="translate(497,652)">
+ <rect
+ y="-75"
+ x="-135"
+ height="16"
+ width="16"
+ id="rect41622"
+ 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="g41624"
+ style="display:inline;enable-background:new"
+ transform="matrix(1,0,0,0.9999542,-104,-101.99865)">
+ <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="path41626"
+ d="M -27.80208,29.59375 -19.5,29.5 -19.53126,42.40625 -30.5,42.5 l 0.03125,-9.90625 2.66667,-3 z"
+ style="fill:url(#linearGradient41638-8-6);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ d="m -29.5,34 0,7.5 m 3.5,-11 5.5,0"
+ style="fill:none;stroke:url(#linearGradient41640-2-0);stroke-width:1.00002289px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ id="path41628"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.5;fill:url(#radialGradient41642-5-0);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="M -27.80208,29.59375 -19.5,29.5 -19.53126,42.40625 -30.5,42.5 l 0.03125,-9.90625 2.66667,-3 z"
+ id="path41630"
+ 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
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m -31,33 4,0 0,-4 -4,4 z"
+ id="path41632"
+ 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 -30.5,32.00001 0,10.49999 11,-1e-5 0,-12.99999 -8.5,10e-6 -2.5,2.5 0,0 0,0 0,0 z"
+ style="fill:none;stroke:#000000;stroke-width:0.80001831;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path41634"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path41636"
+ d="m -26.5,31.5 0,2 -2,0"
+ style="fill:none;stroke:url(#linearGradient41644-5-4);stroke-width:1.00002289px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g43546-0"
+ transform="matrix(0.9986805,0,0,1,-443.5692,-347.00003)">
+ <rect
+ rx="1.2018067"
+ y="274.00003"
+ x="317.9888"
+ height="4.9999909"
+ width="5.006597"
+ id="rect43548-7"
+ style="opacity:0.2;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.4;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="rect43550-6"
+ width="5.0065966"
+ height="4.9999905"
+ x="317.9888"
+ y="274.00003"
+ rx="1.2018069"
+ ry="1.2018069" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ 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="path43552-3"
+ d="m 317.98879,278 0,-3 1.00132,-1 3.00396,0 1.00132,1 0,3 -1.00132,1 -3.00396,0 -1.00132,-1 z"
+ style="opacity:0.8;fill:#dcb000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#967800;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 318.9901,278.50003 c 0,-1.33336 3e-5,-2.66664 3e-5,-4 1.00132,0 2.00263,0 3.00395,0 0,1.33336 -3e-5,2.66664 -3e-5,4 -1.00132,0 -2.00263,0 -3.00395,0 z"
+ id="path43554-6"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <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="path43583-1"
+ d="m 318.48944,278.00003 c 0,-1.00002 4e-5,-1.99998 4e-5,-3 1.33509,0 2.67017,0 4.00526,0 0,1.00002 -4e-5,1.99998 -4e-5,3 -1.33509,0 -2.67017,0 -4.00526,0 z"
+ style="fill:#967800;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 317.98877,276 c 1.66888,0 3.33774,10e-6 5.00662,10e-6 0,0.33335 0,0.6667 0,1.00005 -1.66888,0 -3.33774,-1e-5 -5.00662,-1e-5 0,-0.33335 0,-0.6667 0,-1.00005 z"
+ id="path43556-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"
+ 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="path43558-4"
+ d="m 319.99139,279.00006 c 0,-1.66671 10e-6,-3.33335 10e-6,-5.00006 0.33379,0 0.66758,0 1.00137,0 0,1.66671 -1e-5,3.33335 -1e-5,5.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
+ transform="translate(378,684)"
+ style="display:inline;enable-background:new"
+ id="g39156">
+ <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"
+ width="16"
+ height="16"
+ x="-205"
+ y="-87" />
+ <g
+ transform="translate(-272,-181)"
+ style="opacity:0.6"
+ id="g40789">
+ <rect
+ style="fill:url(#linearGradient39136-2-0);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="rect40791"
+ width="9.0000124"
+ height="10.000001"
+ x="68.5"
+ y="95.5"
+ rx="0"
+ ry="0" />
+ <rect
+ style="fill:none;stroke:url(#linearGradient39138-8-6);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="rect40793"
+ width="7.0000038"
+ height="8.0000086"
+ x="69.5"
+ y="96.5"
+ rx="0"
+ ry="0" />
+ </g>
+ <g
+ id="g40795"
+ transform="translate(-273.00002,-181)">
+ <rect
+ 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:0"
+ id="rect40797"
+ width="8.9999342"
+ height="10.000006"
+ x="73.500023"
+ y="99.5"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="100"
+ x="74.000023"
+ height="9"
+ width="8.0000086"
+ id="rect40799"
+ style="fill:url(#linearGradient39140-6-8);fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <path
+ style="fill:none;stroke:#333333;stroke-width:0.7499997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0"
+ d="m 73.5,103.75 2e-5,-4.25 4,0"
+ id="path40801"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:none;stroke:url(#linearGradient39143-0-6);stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="rect40803"
+ width="7.0000048"
+ height="8.0000267"
+ x="74.500023"
+ y="100.5"
+ rx="0"
+ ry="0" />
+ </g>
+ <g
+ style="fill:#800000"
+ id="g37993">
+ <rect
+ style="fill:#800000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37978"
+ width="2.00001"
+ height="1.0000038"
+ x="-198"
+ y="-77" />
+ <rect
+ y="-76"
+ x="-197.00002"
+ height="2"
+ width="1.0000153"
+ id="rect37980"
+ style="fill:#800000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#800000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37982"
+ width="1.0000153"
+ height="1"
+ x="-197.00002"
+ y="-79" />
+ <rect
+ y="-75"
+ x="-194.5"
+ height="1.0000088"
+ width="1.4999988"
+ id="rect37984"
+ style="fill:#800000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="-76"
+ x="-195.00002"
+ height="1"
+ width="1.0000153"
+ id="rect37986"
+ style="fill:#800000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#800000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37988"
+ width="1.5000049"
+ height="1.0000198"
+ x="-194.5"
+ y="-77" />
+ <rect
+ style="fill:#800000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.70000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect37990"
+ width="1.0000153"
+ height="5"
+ x="-193.00002"
+ y="-79" />
+ </g>
+ </g>
+ <g
+ id="g39528">
+ <g
+ clip-path="url(#clipPath40902)"
+ id="g40560"
+ transform="matrix(-1,0,0,1,90,-62)">
+ <rect
+ y="198"
+ x="6"
+ height="16"
+ width="16"
+ id="rect40562"
+ 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" />
+ <g
+ style="opacity:0.4"
+ id="g40565"
+ transform="matrix(-1,0,0,1,21.999203,19)">
+ <rect
+ rx="1.3125"
+ ry="1.3125001"
+ y="180.53122"
+ x="5.4992032"
+ height="9.9687805"
+ width="10.000007"
+ id="rect40567"
+ style="fill:url(#linearGradient40731);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path40569"
+ d="m 6.5,181.53121 7.99921,0 0,7.96879 -7.99921,0 0,-7.96879 z"
+ style="fill:none;stroke:url(#linearGradient40679);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(-1.00079,-19)"
+ style="fill:#ffffff;display:inline;enable-background:new"
+ id="g40571">
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 10.25,199 c -0.1385,0 -0.25,0.1115 -0.25,0.25 l 0,1.75 -0.5,0 c -0.277,0 -0.5,0.223 -0.5,0.5 0,0.277 0.223,0.5 0.5,0.5 l 4,0 c 0.277,0 0.5,-0.223 0.5,-0.5 0,-0.277 -0.223,-0.5 -0.5,-0.5 l -0.5,0 0,-1.75 C 13,199.1115 12.8885,199 12.75,199 l -2.5,0 z"
+ id="path40573"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40575"
+ d="m 10.25,199 c -0.1385,0 -0.25,0.1115 -0.25,0.25 l 0,1.75 -0.5,0 c -0.277,0 -0.5,0.223 -0.5,0.5 0,0.277 0.223,0.5 0.5,0.5 l 4,0 c 0.277,0 0.5,-0.223 0.5,-0.5 0,-0.277 -0.223,-0.5 -0.5,-0.5 l -0.5,0 0,-1.75 C 13,199.1115 12.8885,199 12.75,199 l -2.5,0 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="opacity:0.45;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 9.49921,181.5 2,0"
+ id="path40577"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g40581"
+ transform="matrix(0,1,-1,0,199.75,171.75)">
+ <g
+ transform="matrix(-1,0,0,-1,215.25,222.75)"
+ id="g40583">
+ <path
+ id="path40585"
+ d="m 174.5,38.5 0,5 5,0"
+ style="fill:none;stroke:#00112b;stroke-width:2.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 175.5,42.5 5,-5"
+ style="fill:none;stroke:#00112b;stroke-width:3.20000005;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="path40587"
+ sodipodi:nodetypes="cz"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g40589"
+ transform="translate(-146.75,127.75)">
+ <g
+ id="g40591"
+ 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,0,0,-1,272.1613,155.99999)"
+ style="display:inline">
+ <path
+ 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"
+ id="path40593"
+ sodipodi:nodetypes="cz"
+ d=""
+ inkscape:connector-curvature="0" />
+ <path
+ d=""
+ style="opacity:0.85;fill:none;stroke:#ffffff;stroke-width:1.5;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="path40595"
+ sodipodi:nodetypes="cz"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path40597"
+ d="m 188,51 0,6 -1,0 0,-5 -5,0 0,-1 6,0 z"
+ style="fill:#c3dbff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(-1,0,0,1,-29,-335)"
+ style="opacity:0.2"
+ id="g40599">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path40602"
+ d="m -216,387 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ style="fill:#333333;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g40604"
+ 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,0,0,-1,118.4113,290.74999)"
+ style="display:inline">
+ <path
+ 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"
+ id="path40606"
+ sodipodi:nodetypes="cz"
+ d=""
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 78.1613,110.99999 5.5,-5.5"
+ style="fill:#abcdff;fill-opacity:1;stroke:#c3dbff;stroke-width:1.5;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="path40609"
+ sodipodi:nodetypes="cz"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g40611"
+ style="opacity:0.2"
+ transform="matrix(-1,0,0,1,-175.75,-207.25)">
+ <path
+ style="opacity:0.7;fill:#333333;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -216,387 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ id="path40613"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,-160.74474,8.5136728)"
+ style="display:inline;enable-background:new"
+ id="g27675-3">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path27679-1"
+ d="m 73.191498,271.86917 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.95;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-0"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path42359-1"
+ 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
+ id="g39560">
+ <g
+ clip-path="url(#clipPath40897)"
+ id="g40506"
+ transform="matrix(-1,0,0,1,89,-62)">
+ <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"
+ id="rect40508"
+ width="16"
+ height="16"
+ x="26"
+ y="198" />
+ <g
+ transform="matrix(-1,0,0,1,46.99921,19)"
+ id="g39096-2"
+ style="opacity:0.4;display:inline;enable-background:new">
+ <rect
+ style="fill:url(#linearGradient40731);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect39098-5"
+ width="10.000007"
+ height="9.9687805"
+ x="5.4992032"
+ y="180.53122"
+ ry="1.3125001"
+ rx="1.3125" />
+ <path
+ style="fill:none;stroke:url(#linearGradient40733-03);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 6.5,181.53121 7.99921,0 0,7.96879 -7.99921,0 0,-7.96879 z"
+ id="path39100-0"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g39118-9"
+ style="fill:#ffffff;display:inline;enable-background:new"
+ transform="translate(-1.00079,-19)">
+ <path
+ id="path39183-4"
+ d="m 10.25,199 c -0.1385,0 -0.25,0.1115 -0.25,0.25 l 0,1.75 -0.5,0 c -0.277,0 -0.5,0.223 -0.5,0.5 0,0.277 0.223,0.5 0.5,0.5 l 4,0 c 0.277,0 0.5,-0.223 0.5,-0.5 0,-0.277 -0.223,-0.5 -0.5,-0.5 l -0.5,0 0,-1.75 C 13,199.1115 12.8885,199 12.75,199 l -2.5,0 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 10.25,199 c -0.1385,0 -0.25,0.1115 -0.25,0.25 l 0,1.75 -0.5,0 c -0.277,0 -0.5,0.223 -0.5,0.5 0,0.277 0.223,0.5 0.5,0.5 l 4,0 c 0.277,0 0.5,-0.223 0.5,-0.5 0,-0.277 -0.223,-0.5 -0.5,-0.5 l -0.5,0 0,-1.75 C 13,199.1115 12.8885,199 12.75,199 l -2.5,0 z"
+ id="rect39114-7"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path39106-8"
+ d="m 9.49921,181.5 2,0"
+ style="opacity:0.45;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(0,-1,-1,0,212.75,247.25)"
+ id="g40522">
+ <g
+ id="g40526"
+ transform="matrix(-1,0,0,-1,215.25,222.75)">
+ <path
+ sodipodi:nodetypes="ccc"
+ style="fill:none;stroke:#00112b;stroke-width:2.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 174.5,38.5 0,5 5,0"
+ id="path40528"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cz"
+ id="path40533"
+ style="fill:none;stroke:#00112b;stroke-width:3.20000005;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"
+ d="m 175.5,42.5 5,-5"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-146.75,127.75)"
+ id="g40535">
+ <g
+ style="display:inline"
+ transform="matrix(-1,0,0,-1,272.1613,155.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="g40537">
+ <path
+ d=""
+ sodipodi:nodetypes="cz"
+ id="path40539"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cz"
+ id="path40541"
+ style="opacity:0.85;fill:none;stroke:#ffffff;stroke-width:1.5;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"
+ d=""
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="fill:#c3dbff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 188,51 0,6 -1,0 0,-5 -5,0 0,-1 6,0 z"
+ id="path40543"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g40545"
+ style="opacity:0.2"
+ transform="matrix(-1,0,0,1,-29,-335)">
+ <path
+ style="fill:#333333;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -216,387 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ id="path40547"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline"
+ transform="matrix(-1,0,0,-1,118.4113,290.74999)"
+ 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="g40549">
+ <path
+ d=""
+ sodipodi:nodetypes="cz"
+ id="path40551"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cz"
+ id="path40553"
+ style="fill:#abcdff;fill-opacity:1;stroke:#c3dbff;stroke-width:1.5;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"
+ d="m 78.1613,110.99999 5.5,-5.5"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(-1,0,0,1,-175.75,-207.25)"
+ style="opacity:0.2"
+ id="g40556">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path40558"
+ d="m -216,387 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ style="opacity:0.7;fill:#333333;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g40888"
+ style="display:inline;enable-background:new"
+ transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,-194.74474,8.5136728)">
+ <path
+ 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 73.191498,271.86917 7.071067,-7.07107"
+ id="path40890"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40892"
+ style="opacity:0.95;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"
+ 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="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="path40894"
+ inkscape:connector-curvature="0" />
+ </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">
+ <g
+ id="g44266"
+ style="opacity:0.8;display:inline"
+ transform="translate(-138,212)">
+ <g
+ id="g44268"
+ transform="translate(1.0551033e-6,0)">
+ <g
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\Browser icons ver 1\Outliner ICON CODES.png"
+ id="g44270"
+ transform="matrix(0.927273,0,0,1,85.654543,64)"
+ style="display:inline">
+ <path
+ d="M 70.499967,14.5 75.5,17.5 m -5.000033,-3 -4.999967,3 m 4.970586,-3 0,-6"
+ style="fill:none;stroke:#1a1a1a;stroke-width:3.63466382;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path44272"
+ 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="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path44274"
+ d="m 69.392137,7 0,2 2.156862,0 0,-2 -2.156862,0 z M 63.999982,17 64,19 l 2.156862,0 -1.8e-5,-2 -2.156862,0 0,0 0,0 0,0 z m 10.78431,0 0,2 2.156862,0 0,-2 -2.156862,0 z"
+ style="fill:none;stroke:#1a1a1a;stroke-width:1.86925566;stroke-linecap:square;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"
+ sodipodi:nodetypes="ccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#radialGradient44318);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path44276"
+ sodipodi:cx="70.5"
+ sodipodi:cy="14.5"
+ sodipodi:rx="1.5"
+ sodipodi:ry="1.5"
+ d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 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"
+ inkscape:export-ydpi="90" />
+ <path
+ id="path44278"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ececec;stroke-width:1.97310317;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ d="M 70.499967,14.5 75.5,17.5"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(-1.6176466e-5,0)"
+ sodipodi:nodetypes="cccccc"
+ 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="path44280"
+ style="opacity:0.8;fill:none;stroke:url(#radialGradient44320);stroke-width:2.07695079;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ d="M 70.499967,14.5 75.5,17.5 m -5.000033,-3 -4.999967,3 m 4.970586,-3 0,-6"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 74.784292,17 0,2 2.156862,0 0,-2 -2.156862,0 z"
+ id="path44282"
+ sodipodi:nodetypes="ccccc"
+ 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
+ d="M 70.499967,14.5 65.5,17.5"
+ style="fill:none;stroke:#999999;stroke-width:1.97310317;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path44284"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 70.470586,14.5 0,-6"
+ style="fill:none;stroke:#cccccc;stroke-width:2.07695079;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path44286"
+ sodipodi:nodetypes="cc"
+ 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
+ id="path44288"
+ d="m 69.392137,7 0,2 2.156862,0 0,-2 -2.156862,0 z"
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:nodetypes="ccccc"
+ 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
+ id="path44290"
+ d="m 64,17 0,2 2.156844,0 0,-2 L 64,17 z"
+ style="fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:nodetypes="ccccc"
+ 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" />
+ <rect
+ style="opacity:0.05;fill:#554400;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect44292"
+ width="3.774509"
+ height="3.5"
+ x="68.583321"
+ y="13.25" />
+ <path
+ style="opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.03847623px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ d="m 64.539197,18.5 0,-1 1.078431,0"
+ id="path44294"
+ sodipodi:nodetypes="ccc"
+ 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="ccc"
+ id="path44296"
+ d="m 69.931347,8.5 0,-0.9673924 1.078413,0"
+ style="fill:none;stroke:#ffffff;stroke-width:1.03847647px;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\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:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.03847647px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ d="m 75.323509,18.500001 0,-1 1.078431,0"
+ id="path44298"
+ sodipodi:nodetypes="ccc"
+ 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" />
+ <rect
+ style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect44300"
+ width="17.254898"
+ height="16"
+ x="61.843121"
+ y="5" />
+ <path
+ transform="matrix(1.0784311,0,0,1,-92.372519,-64)"
+ id="path44302"
+ d="m 155,80.5 -3,-1.870665"
+ style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ 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"
+ sodipodi:nodetypes="ccc"
+ id="path44304"
+ d="m 74.245078,17.500001 0,-1 1.078431,0"
+ style="opacity:0.01000001;fill:#d4aa00;fill-opacity:1;fill-rule:evenodd;stroke:#999999;stroke-width:1.03847647px;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.4;fill:#6a6a6a;fill-opacity:1;fill-rule:evenodd;stroke:#666666;stroke-width:1.03847647px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ d="m 69.931352,9.5000005 1.078431,0"
+ id="path44306"
+ sodipodi:nodetypes="cc"
+ 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:#6a6a6a;fill-opacity:1;fill-rule:evenodd;stroke:#4c4c4c;stroke-width:1.03847575px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline"
+ d="m 66.696014,17.499989 0,-1 -1.078431,0"
+ id="path44308"
+ sodipodi:nodetypes="ccc"
+ 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" />
+ </g>
+ <path
+ style="opacity:0.4;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 147,80.5 3,-1.870665"
+ id="path44310"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path44312"
+ d="m 150.5,73.5 0,4"
+ style="opacity:0.35;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect44314"
+ width="2"
+ height="2"
+ x="150.06403"
+ y="78" />
+ </g>
+ <rect
+ 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="rect44316"
+ width="2.9998772"
+ height="3"
+ x="11.499837"
+ y="289.5"
+ ry="0"
+ rx="0" />
+ </g>
+ <g
+ id="g43843">
+ <g
+ transform="translate(20,-30.990313)"
+ id="g39499">
+ <g
+ style="opacity:0.5"
+ transform="translate(-20,8)"
+ id="g39466">
+ <rect
+ style="opacity:0;fill:#333333;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect39468"
+ width="16"
+ height="16"
+ x="47"
+ y="642" />
+ </g>
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path39470"
+ d="m 34.8125,650.5 c -0.469932,0.0628 -0.901978,0.36287 -1.125,0.78125 l -6,11 c -0.495227,0.9075 0.278677,2.21576 1.3125,2.21875 l 12,0 c 1.033823,-0.003 1.807727,-1.31125 1.3125,-2.21875 l -6,-11 c -0.282798,-0.52794 -0.905299,-0.85216 -1.5,-0.78125 z"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;fill:#ffdd55;fill-opacity:1;stroke:#2b0000;stroke-width:0.89999998;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="655"
+ x="34"
+ height="5"
+ width="2.0152419"
+ id="rect39472"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect39474"
+ width="2.0152419"
+ height="1"
+ x="33.984756"
+ y="661" />
+ <path
+ id="path39476"
+ d="m 34.936406,651.39468 c -0.144491,0.0192 -0.31295,0.15614 -0.381583,0.28384 l -6.105329,11.1013 c -0.0509,0.0926 -0.05511,0.27404 0.0636,0.47307 0.118705,0.19902 0.275323,0.31508 0.381582,0.31538 l 12.210658,0 c 0.106265,-3e-4 0.262877,-0.11636 0.381583,-0.31538 0.118706,-0.19903 0.114499,-0.38055 0.06359,-0.47307 l -6.105329,-11.1013 c -0.08049,-0.14902 -0.33952,-0.30385 -0.508777,-0.28384 l 5e-6,0 z"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.5;fill:none;stroke:#ff0000;stroke-width:1.39999998;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ inkscape:connector-curvature="0" />
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;fill:none;stroke:url(#linearGradient39508);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ d="m 34.936406,651.39468 c -0.144491,0.0192 -0.31295,0.15614 -0.381583,0.28384 l -6.105329,11.1013 c -0.0509,0.0926 -0.05511,0.27404 0.0636,0.47307 0.118705,0.19902 0.275323,0.31508 0.381582,0.31538 l 12.210658,0 c 0.106265,-3e-4 0.262877,-0.11636 0.381583,-0.31538 0.118706,-0.19903 0.114499,-0.38055 0.06359,-0.47307 l -6.105329,-11.1013 c -0.08049,-0.14902 -0.33952,-0.30385 -0.508777,-0.28384 l 5e-6,0 z"
+ id="path39478"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path43799"
+ d="M 54.75,622.5 50,631.25"
+ style="opacity:0.25;fill:none;stroke:#2b2200;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path43801"
+ d="m 29.5,631.5 9.5,0"
+ style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ transform="translate(21,0)"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g44081"
+ 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"
+ id="rect44079"
+ width="16"
+ height="16"
+ x="320"
+ y="73" />
+ <g
+ transform="translate(0,-22.005631)"
+ id="g43931">
+ <g
+ id="g43459">
+ <g
+ transform="translate(0,21)"
+ id="g43446">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path43448"
+ d="m 333.25,86.005631 -5.25,0 -1,-1 L 327,76"
+ style="fill:none;stroke:#000000;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path43450"
+ d="M 331.25,80.244369 327,76 l -4.25,4.244369"
+ style="fill:none;stroke:#000000;stroke-width:3.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(0,21)"
+ id="g43442">
+ <path
+ style="fill:none;stroke:#dcdcdc;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 333.25,86.005631 -5.25,0 -1,-1 L 327,76"
+ id="path42664"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#dcdcdc;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 331.25,80.25 327,76.005631 322.75,80.25"
+ id="path42666"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <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;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 328.5,106.50563 5,0 m -7,-7.00563 0,6.50563"
+ id="path43773"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient44954);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 322.25,101.00563 4.5,-4.499999 0.5,0 4.5,4.499999"
+ id="path44952"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g44124">
+ <rect
+ y="73"
+ x="341"
+ height="16"
+ width="16"
+ id="rect44077"
+ 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
+ id="g44913"
+ transform="translate(0,1)">
+ <g
+ transform="matrix(-1,0,0,-1,698,183)"
+ id="g43652">
+ <path
+ sodipodi:nodetypes="csc"
+ id="path43654"
+ d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 5.75,2 8,0.5"
+ style="fill:none;stroke:#000000;stroke-width:3.5999999;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
+ sodipodi:nodetypes="ccc"
+ id="path43660"
+ d="m 343,108.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#000000;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(-1,0,0,-1,698,183)"
+ id="g43662">
+ <path
+ style="fill:none;stroke:#dcdcdc;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 343.5,104.5 1.75,1.75 c 2.3454,2.33848 5.75,2.25 8,0.5"
+ id="path43668"
+ sodipodi:nodetypes="csc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#dcdcdc;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 343,108.25 0,-4.25 4.25,0"
+ id="path43666"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path43671"
+ d="m 354,78 0,-1 0,-1.5 -1,0 0,1.5 -1.5,0 0,1 1.5,0 1,0 z"
+ style="opacity:0.15;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path43747"
+ d="M 353.09375,76.40625 C 350.56802,73.88797 346.75,74 344.25,76"
+ style="fill:none;stroke:url(#linearGradient44944);stroke-width:1.10000002;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: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 350.5,78.5 4,0 0,-4"
+ id="path43750"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g44931"
+ transform="translate(0,-1)">
+ <g
+ transform="translate(0,-21)"
+ id="g43636">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:3.5999999;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.5,104.5 1.75,1.75 c 2.3454,2.33848 5.75,2.25 8,0.5"
+ id="path43623"
+ sodipodi:nodetypes="csc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;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,108.25 0,-4.25 4.25,0"
+ id="path43506"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(0,-21)"
+ id="g43632">
+ <path
+ sodipodi:nodetypes="csc"
+ id="path43584"
+ d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 5.75,2.25 8,0.5"
+ style="fill:none;stroke:#dcdcdc;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path43502"
+ d="m 343,108.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#e6e6e6;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="opacity:0.15;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 344,84 0,1 0,1.5 1,0 0,-1.5 1.5,0 0,-1 -1.5,0 -1,0 z"
+ id="rect43547"
+ inkscape:connector-curvature="0" />
+ <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;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 347.5,82.5 -4.5,0 c -0.25,0 -0.5,0.25 -0.5,0.5 l 0,4.5"
+ id="path43761"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient44942);stroke-width:1.10000002;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 345.59375,84.90625 c 2.07803,2.0719 5.36384,2.10325 7.53125,0.1875"
+ id="path43765"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g44097">
+ <rect
+ y="52"
+ x="320"
+ height="16"
+ width="16"
+ id="rect44095"
+ 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(42.999999,-42)"
+ id="g43952">
+ <g
+ transform="matrix(0,-1,1,0,183.99437,429)"
+ id="g43483">
+ <g
+ transform="translate(0,21)"
+ id="g43488">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path43490"
+ d="M 327,86.255631 327,76"
+ style="fill:none;stroke:#000000;stroke-width:3.4000001;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"
+ d="M 331.25,79.25 327,75.005631 322.75,79.25"
+ style="fill:none;stroke:#000000;stroke-width:3.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(0,21)"
+ id="g43494">
+ <path
+ style="fill:none;stroke:#dcdcdc;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 327,86.255631 327,76"
+ id="path43496"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#dcdcdc;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 331.25,79.25 327,75.005631 322.75,79.25"
+ id="path43498"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <path
+ sodipodi:nodetypes="cc"
+ id="path43776"
+ 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"
+ d=""
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient44485);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 284,97.25 -4.5,4.5 0,0.5 4.5,4.5"
+ id="path43780"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path43860"
+ d="m 291.5,101.5 -8.99437,0"
+ 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(-1,0)"
+ id="g44111">
+ <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"
+ width="16"
+ height="16"
+ x="341"
+ y="52" />
+ <g
+ transform="translate(41.97875,-42)"
+ id="g43941">
+ <g
+ id="g43467"
+ transform="matrix(0,-1,-1,0,409.02125,429)">
+ <g
+ id="g43469"
+ transform="translate(0,21)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M 327,86.25 327,76"
+ id="path43471"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:3.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M 331.25,79.25 327,75.005631 322.75,79.25"
+ id="path43473"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g43475"
+ transform="translate(0,21)">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path43478"
+ d="M 327,86.25 327,76"
+ style="fill:none;stroke:#dcdcdc;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path43481"
+ d="M 331.25,79.25 327,75.005631 322.75,79.25"
+ style="fill:none;stroke:#dcdcdc;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <path
+ style="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 308.5,106 2.75,-2.75"
+ id="path43778"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path43785"
+ d="m 308.75,97.25 c -0.25,0 -0.5,0.25 -0.5,0.5 m 2.26562,3.75 -8.99437,0"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient44950);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 309.02125,97.249998 4.5,4.500002 0,0.5 -4.5,4.5"
+ id="path44948"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g32752"
+ inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\v. 2.5.06\prvicons 2.5.06.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ y="180"
+ x="872"
+ height="192"
+ width="192"
+ id="rect30285"
+ style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.39191818;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png"
+ transform="translate(856,-203)"
+ id="g21955"
+ style="opacity:0.3;display:inline;enable-background:new">
+ <rect
+ 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"
+ id="rect21957"
+ width="48"
+ height="48"
+ x="108"
+ y="430"
+ rx="2.4004419"
+ ry="0" />
+ <g
+ id="g21959">
+ <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="path21961"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ style="fill:url(#linearGradient21977);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path21963"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,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" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)"
+ d="m 115,444 12,0 -1,-11 -11,11 z"
+ id="path21965"
+ 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)" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path21967"
+ style="fill:none;stroke:url(#linearGradient21979);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 117.5,443.75 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" />
+ <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 115.5,442.75 0,31.75 33,0 0,-41 -23.75,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="path21969"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)"
+ d="m 116,443 11,1 -2,-10 -9,9 z"
+ id="path21971"
+ 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)" />
+ <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="path21973"
+ d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z"
+ style="fill:#ffffff;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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ d="m 147.5,435 0,38.5 -30.5,0"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path21975"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ </g>
+ <g
+ id="g30335">
+ <g
+ id="g21367"
+ transform="translate(760,-202)">
+ <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="path21369"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ style="fill:url(#linearGradient30321);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path21371"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,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" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)"
+ d="m 115,444 12,0 -1,-11 -11,11 z"
+ id="path21373"
+ 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)" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path21375"
+ style="fill:none;stroke:url(#linearGradient30323);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 117.5,443.75 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" />
+ <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 115.5,442.75 0,31.75 33,0 0,-41 -23.75,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="path21377"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)"
+ d="m 116,443 11,1 -2,-10 -9,9 z"
+ id="path21569"
+ 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)" />
+ <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="path21379"
+ d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z"
+ style="fill:#ffffff;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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ d="m 147.5,435 0,38.5 -30.5,0"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path21381"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="font-size:33.49144363px;font-style:normal;font-weight:normal;fill:#214478;fill-opacity:1;stroke:none;display:inline;font-family:Bitstream Vera Sans"
+ d="m 891.07148,245 -0.0715,9 2.39012,0 C 896,254 896,253 896.5,251 l 0.5,0 0,7 -0.5,0 c -0.5,-2 -0.5,-3 -3.10988,-3 L 891,255 l 0,7 c 0,2.5 1,3.25 3.14146,3.39973 l -0.004,0.60029 L 885,266 l 0.004,-0.60029 C 887,265.25 888,264.5 888.00001,262 L 888,248 c 0,-2.5 -1,-3.25 -3,-3.5 l 0,-0.5 16,0 0,5 -0.5,0 c -0.50001,-1.99999 -1.5,-4 -4.5,-4 l -4.92852,0 z"
+ id="text13209"
+ sodipodi:nodetypes="ccccccccccccccccccccccc" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g21625"
+ transform="translate(904,-154)"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ ry="0"
+ rx="2.4004419"
+ y="430"
+ x="108"
+ height="48"
+ width="48"
+ id="rect21627"
+ 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" />
+ <g
+ id="g21629">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient21647);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ id="path21631"
+ 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" />
+ <g
+ style="opacity:0.5;fill:#000000;display:inline"
+ id="g16261"
+ transform="matrix(1.2499985,0,0,1,-87.6203,-147.85351)">
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
+ id="rect35099"
+ width="17.600004"
+ height="1"
+ x="167.69646"
+ y="598.85352"
+ rx="0.12125195"
+ ry="0.065390877" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
+ id="rect35101"
+ width="17.600004"
+ height="1"
+ x="167.69646"
+ y="600.85352"
+ rx="0.12125195"
+ ry="0.065390877" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
+ id="rect15690"
+ width="17.600004"
+ height="1"
+ x="167.69646"
+ y="602.85352"
+ rx="0.12125195"
+ ry="0.065390877" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
+ id="rect15692"
+ width="17.600004"
+ height="1"
+ x="167.69646"
+ y="604.85352"
+ rx="0.12125195"
+ ry="0.065390877" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
+ id="rect15694"
+ width="17.600004"
+ height="1"
+ x="167.69646"
+ y="606.85352"
+ rx="0.12125195"
+ ry="0.065390877" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
+ id="rect15696"
+ width="17.600004"
+ height="1"
+ x="167.69646"
+ y="608.85352"
+ rx="0.12125195"
+ ry="0.065390877" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
+ id="rect15698"
+ width="17.600004"
+ height="1"
+ x="167.69646"
+ y="610.85352"
+ rx="0.12125195"
+ ry="0.065390877" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
+ id="rect15700"
+ width="17.600004"
+ height="1"
+ x="167.69646"
+ y="612.85352"
+ rx="0.12125195"
+ ry="0.065390877" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
+ id="rect15732"
+ width="14.400002"
+ height="1"
+ x="167.69646"
+ y="614.85352"
+ rx="0.09920612"
+ ry="0.065390877" />
+ <g
+ transform="translate(150.89645,557.85352)"
+ id="g4849"
+ style="fill:#000000;display:inline">
+ <rect
+ ry="0.065390877"
+ rx="0.12125195"
+ y="29"
+ x="16.799992"
+ height="1"
+ width="17.600004"
+ id="rect15736"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" />
+ <rect
+ ry="0.065390877"
+ rx="0.12125195"
+ y="31"
+ x="16.799992"
+ height="1"
+ width="17.600004"
+ id="rect15738"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" />
+ <rect
+ ry="0.065390877"
+ rx="0.12125195"
+ y="33"
+ x="16.799992"
+ height="1"
+ width="17.600004"
+ id="rect15740"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" />
+ <rect
+ ry="0.065390877"
+ rx="0.12125195"
+ y="35"
+ x="16.799992"
+ height="1"
+ width="17.600004"
+ id="rect15742"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" />
+ <rect
+ ry="0.065390877"
+ rx="0.055114571"
+ y="37"
+ x="16.799992"
+ height="1"
+ width="8.0000095"
+ id="rect15744"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" />
+ </g>
+ <rect
+ ry="0.065390304"
+ rx="0.0057410933"
+ y="617.85352"
+ x="184.49646"
+ height="0.99999124"
+ width="0.83333319"
+ id="rect16334"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" />
+ </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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path21633"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="url(#clipPath13106)"
+ 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="cccc"
+ id="path21635"
+ d="m 115,444 12,0 -1,-11 -11,11 z"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="none"
+ 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 117.5,443.75 9,-2.5 0,-6"
+ style="fill:none;stroke:url(#linearGradient21649);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path21637"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path21639"
+ style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 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"
+ clip-path="url(#clipPath13106)"
+ 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="cccc"
+ id="path21641"
+ d="m 116,443 11,1 -2,-10 -9,9 z"
+ style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z"
+ id="path21643"
+ 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" />
+ <g
+ id="g35119"
+ transform="translate(2,-160.99999)"
+ style="display:inline">
+ <g
+ style="display:inline"
+ transform="translate(105.39645,589.71201)"
+ id="g16097">
+ <g
+ id="g16099"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4"
+ transform="matrix(0.229703,0,0,0.229703,4.967081,4.244972)">
+ <radialGradient
+ id="radialGradient16101"
+ cx="20.892099"
+ cy="114.5684"
+ r="5.256"
+ fx="20.892099"
+ fy="114.5684"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ offset="0"
+ style="stop-color:#F0F0F0"
+ id="stop16103" />
+ <stop
+ offset="1"
+ style="stop-color:#474747"
+ id="stop16105" />
+ </radialGradient>
+ <radialGradient
+ id="radialGradient16109"
+ cx="20.892099"
+ cy="64.567902"
+ r="5.257"
+ fx="20.892099"
+ fy="64.567902"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ offset="0"
+ style="stop-color:#F0F0F0"
+ id="stop16111" />
+ <stop
+ offset="1"
+ style="stop-color:#474747"
+ id="stop16113" />
+ </radialGradient>
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 12.85355,31.53813 c 0,0.552274 -0.447803,0.99986 -1,0.99986 -0.552477,0 -1,-0.447865 -1,-0.99986 0,-0.552554 0.447803,-1.00014 1,-1.00014 0.552197,0 1,0.447866 1,1.00014 l 0,0 0,0 0,0 z"
+ id="path16107" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient21565);fill-rule:nonzero;stroke:none"
+ d="m 12.60355,31.288131 c 0,0.552274 -0.447803,0.999859 -1,0.999859 -0.552477,0 -1,-0.447865 -1,-0.999859 0,-0.552556 0.447803,-1.000141 1,-1.000141 0.552197,0 1,0.447866 1,1.000141 z"
+ id="path16117" />
+ </g>
+ <g
+ id="g16131"
+ transform="translate(105.39645,579.71201)"
+ style="display:inline">
+ <g
+ transform="matrix(0.229703,0,0,0.229703,4.967081,4.244972)"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4"
+ id="g16133">
+ <radialGradient
+ gradientUnits="userSpaceOnUse"
+ fy="114.5684"
+ fx="20.892099"
+ r="5.256"
+ cy="114.5684"
+ cx="20.892099"
+ id="radialGradient16135">
+ <stop
+ id="stop16137"
+ style="stop-color:#F0F0F0"
+ offset="0" />
+ <stop
+ id="stop16140"
+ style="stop-color:#474747"
+ offset="1" />
+ </radialGradient>
+ <radialGradient
+ gradientUnits="userSpaceOnUse"
+ fy="64.567902"
+ fx="20.892099"
+ r="5.257"
+ cy="64.567902"
+ cx="20.892099"
+ id="radialGradient16142">
+ <stop
+ id="stop16144"
+ style="stop-color:#F0F0F0"
+ offset="0" />
+ <stop
+ id="stop16146"
+ style="stop-color:#474747"
+ offset="1" />
+ </radialGradient>
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ id="path35139"
+ d="m 12.85355,31.53813 c 0,0.552274 -0.447803,0.99986 -1,0.99986 -0.552477,0 -1,-0.447865 -1,-0.99986 0,-0.552554 0.447803,-1.00014 1,-1.00014 0.552197,0 1,0.447866 1,1.00014 l 0,0 0,0 0,0 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path35141"
+ d="m 12.60355,31.288131 c 0,0.552274 -0.447803,0.999859 -1,0.999859 -0.552477,0 -1,-0.447865 -1,-0.999859 0,-0.552556 0.447803,-1.000141 1,-1.000141 0.552197,0 1,0.447866 1,1.000141 z"
+ style="fill:url(#radialGradient21567);fill-rule:nonzero;stroke:none" />
+ </g>
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path21645"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 147.5,435 0,38.5 -30.5,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" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g21572"
+ transform="translate(808,-203)"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ ry="0"
+ rx="2.4004419"
+ y="430"
+ x="108"
+ height="48"
+ width="48"
+ id="rect21574"
+ 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" />
+ <g
+ id="g21576">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient21594);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ id="path21578"
+ 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"
+ d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path21580"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="url(#clipPath13106)"
+ 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="cccc"
+ id="path21582"
+ d="m 115,444 12,0 -1,-11 -11,11 z"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="none"
+ 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 117.5,443.75 9,-2.5 0,-6"
+ style="fill:none;stroke:url(#linearGradient21596);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path21584"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path21586"
+ style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 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"
+ clip-path="url(#clipPath13106)"
+ 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="cccc"
+ id="path21588"
+ d="m 116,443 11,1 -2,-10 -9,9 z"
+ style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z"
+ id="path21590"
+ 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"
+ sodipodi:nodetypes="ccc"
+ id="path21592"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 147.5,435 0,38.5 -30.5,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" />
+ </g>
+ </g>
+ <g
+ id="g30382">
+ <g
+ id="g23655"
+ transform="translate(760,-154)">
+ <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="path23657"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ style="fill:url(#linearGradient30368);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path23659"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,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" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)"
+ d="m 115,444 12,0 -1,-11 -11,11 z"
+ id="path23661"
+ 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)" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path23663"
+ style="fill:none;stroke:url(#linearGradient30370);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 117.5,443.75 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" />
+ <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 115.5,442.75 0,31.75 33,0 0,-41 -23.75,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="path23665"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)"
+ d="m 116,443 11,1 -2,-10 -9,9 z"
+ id="path23667"
+ 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)" />
+ <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="path23669"
+ d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z"
+ style="fill:#ffffff;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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ d="m 147.5,435 0,38.5 -30.5,0"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path23671"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 888,295 1,0 0,14 -1,0 0,-14 z"
+ id="path23675"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path23677"
+ d="m 900,294 1.00002,-1 0,14 -1.00002,0 0,-13 z"
+ style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc"
+ id="path23679"
+ d="m 901.00003,292 0,2.25 -13.00002,2 0,-2.25 13.00002,-2 z"
+ style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g23681"
+ 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 a 4.5,2.25 0 1 1 -9,0 4.5,2.25 0 1 1 9,0 z"
+ sodipodi:ry="2.25"
+ sodipodi:rx="4.5"
+ sodipodi:cy="554"
+ sodipodi:cx="53"
+ id="path23683"
+ style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter20578);enable-background:accumulate"
+ id="path23685"
+ sodipodi:cx="53"
+ sodipodi:cy="554"
+ sodipodi:rx="4.5"
+ sodipodi:ry="2.25"
+ d="m 57.5,554 a 4.5,2.25 0 1 1 -9,0 4.5,2.25 0 1 1 9,0 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)" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.38999999;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 901.00003,292 -1e-5,1 -13.00002,2 10e-6,-1 13.00002,-2 z"
+ id="path23694"
+ sodipodi:nodetypes="ccccc" />
+ <g
+ transform="matrix(1.1428564,0,0,1.2000001,834.71436,-357.40005)"
+ id="g23717">
+ <path
+ sodipodi:type="arc"
+ style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path23724"
+ sodipodi:cx="53"
+ sodipodi:cy="554"
+ sodipodi:rx="4.5"
+ sodipodi:ry="2.25"
+ d="m 57.5,554 a 4.5,2.25 0 1 1 -9,0 4.5,2.25 0 1 1 9,0 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 a 4.5,2.25 0 1 1 -9,0 4.5,2.25 0 1 1 9,0 z"
+ sodipodi:ry="2.25"
+ sodipodi:rx="4.5"
+ sodipodi:cy="554"
+ sodipodi:cx="53"
+ id="path23726"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter20578);enable-background:accumulate"
+ sodipodi:type="arc" />
+ </g>
+ </g>
+ <g
+ id="g23922"
+ transform="translate(-16,-220)"
+ style="display:inline;enable-background:new">
+ <g
+ style="display:inline"
+ id="g23924"
+ transform="translate(824,66)"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ ry="0"
+ rx="2.4004419"
+ y="430"
+ x="108"
+ height="48"
+ width="48"
+ id="rect23926"
+ 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" />
+ <g
+ id="g23928">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient23978);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ id="path23930"
+ 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"
+ d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path23932"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="url(#clipPath13106)"
+ 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="cccc"
+ id="path23934"
+ d="m 115,444 12,0 -1,-11 -11,11 z"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="none"
+ 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 117.5,443.75 9,-2.5 0,-6"
+ style="fill:none;stroke:url(#linearGradient23980);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path23936"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path23938"
+ style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 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"
+ clip-path="url(#clipPath13106)"
+ 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="cccc"
+ id="path23940"
+ d="m 116,443 11,1 -2,-10 -9,9 z"
+ style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z"
+ id="path23942"
+ 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"
+ sodipodi:nodetypes="ccc"
+ id="path23944"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 147.5,435 0,38.5 -30.5,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" />
+ </g>
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccc"
+ id="path23946"
+ d="m 952,530 0,10 1,0 1,0 11,0 1,0 1,0 0,-10 -15,0 z m 1,2 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ transform="scale(1,-1)"
+ style="fill:url(#linearGradient23982);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect23948"
+ width="13"
+ height="5.5"
+ x="953"
+ y="-524" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path23952"
+ transform="translate(76,0)"
+ d="m 876,514 0,17 15,0 0,-17 -1,0 0,1 -1,0 0,-1 -11,0 0,1 -1,0 0,-1 -1,0 z m 1,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccc"
+ style="fill:url(#linearGradient23986);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 952,507 3,0 0,3 9,0 0,-3 3,0 0,7 -15,0 0,-7 z m 1,0 1,0 -1,0 z m 0,1 0,1 1,0 0,-1 -1,0 z m 0,3 0,1 1,0 0,-1 -1,0 z m 12,-4 1,0 -1,0 z m 0,1 0,1 1,0 0,-1 -1,0 z m 0,3 0,1 1,0 0,-1 -1,0 z"
+ id="path23954" />
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ ry="0"
+ y="955"
+ x="507"
+ height="9"
+ width="3"
+ id="rect23956"
+ style="fill:url(#linearGradient23988);fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect23958"
+ width="9"
+ height="9"
+ x="512"
+ y="955"
+ ry="0"
+ transform="matrix(0,1,1,0,0,0)" />
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ ry="0"
+ y="955"
+ x="523"
+ height="9"
+ width="9"
+ id="rect23960"
+ style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <path
+ transform="matrix(0,-0.5624971,0.5624971,0,893.12531,590.74965)"
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path23962"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path23964"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(0,-0.5624964,0.5624964,0,893.12545,601.74956)" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccc"
+ id="path23966"
+ d="m 961.00001,519.00005 -3,0 0,-0.99992 0.99994,0 6e-5,-2.00008 -1,0 0,-1 1,0 0,-1 1.00006,0 0,4.00008 0.99994,0 0,0.99992 z" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 958,525 0,1 2,0 0,-1 -2,0 z m 2,1 0,1 1,0 0,-1 -1,0 z m 0,1 -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"
+ id="path23968" />
+ <rect
+ style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect23970"
+ width="6"
+ height="9"
+ x="534"
+ y="955"
+ ry="0"
+ transform="matrix(0,1,1,0,0,0)" />
+ <g
+ clip-path="url(#clipPath23877)"
+ id="g23972">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path23974"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(0,-0.5624964,0.5624964,0,893.12545,612.74956)" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 958,536 0,1 2,0 0,-1 -2,0 z m 2,1 0,1 1,0 0,-1 -1,0 z m 0,1 -1,0 0,1 1,0 0,-1 z m 0,1 0,1 1,0 0,-1 -1,0 z m 0,1 -2,0 0,1 2,0 0,-1 z"
+ id="path23976" />
+ </g>
+ </g>
+ <g
+ transform="translate(208,88)"
+ id="g45475"
+ style="display:inline;enable-background:new">
+ <g
+ style="display:inline"
+ id="g22242"
+ transform="translate(696,-194)"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ ry="0"
+ rx="2.4004419"
+ y="430"
+ x="108"
+ height="48"
+ width="48"
+ id="rect22244"
+ 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" />
+ <g
+ id="g22246">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient22274);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ id="path22249"
+ 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"
+ d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path22251"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="url(#clipPath13106)"
+ 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="cccc"
+ id="path22253"
+ d="m 115,444 12,0 -1,-11 -11,11 z"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="none"
+ 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 117.5,443.75 9,-2.5 0,-6"
+ style="fill:none;stroke:url(#linearGradient22276);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path22264"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path22266"
+ style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 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"
+ clip-path="url(#clipPath13106)"
+ 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="cccc"
+ id="path22268"
+ d="m 116,443 11,1 -2,-10 -9,9 z"
+ style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z"
+ id="path22270"
+ 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"
+ sodipodi:nodetypes="ccc"
+ id="path22272"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 147.5,435 0,38.5 -30.5,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" />
+ </g>
+ </g>
+ <g
+ id="g21517"
+ inkscape:label="Layer 1"
+ 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 a 15.467961,5.3033009 0 1 1 -30.935922,0 15.467961,5.3033009 0 1 1 30.935922,0 z"
+ sodipodi:ry="5.3033009"
+ sodipodi:rx="15.467961"
+ sodipodi:cy="38.98439"
+ sodipodi:cx="28.019106"
+ id="path35486"
+ style="opacity:0.54857142;fill:url(#radialGradient21442);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csssssssssscccsscccscccssccc"
+ 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"
+ id="path2482"
+ 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 a 11.5625,10.125 0 1 1 -23.125,0 11.5625,10.125 0 1 1 23.125,0 z"
+ sodipodi:ry="10.125"
+ sodipodi:rx="11.5625"
+ sodipodi:cy="25.75"
+ sodipodi:cx="31.1875"
+ id="path39153"
+ style="fill:url(#linearGradient21444);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.4857143;fill:none;stroke:url(#linearGradient21446);stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
+ 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"
+ id="path21414"
+ sodipodi:nodetypes="csssssscssscsssccssscscccsccssssccscsscccssssc" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ id="path2478"
+ style="fill:#3465a4;fill-rule:evenodd;stroke:none" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csssscsccsscsccssssscsscccsssc"
+ id="path39166"
+ 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"
+ style="opacity:0.51999996;fill:url(#radialGradient21448);fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ </g>
+ </g>
+ <g
+ style="opacity:0.5"
+ id="g24847"
+ transform="translate(162,248)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccssssccc"
+ style="fill:url(#linearGradient24867);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path24849"
+ d="m 806.5,114.5 c 0,2.25 2,4 4,4 l 30,0 c 0.4163,0 1,-0.5 1,-1 l 0,-29 c 0,-0.5 -0.5,-1 -1,-1 l -21.02773,0.04419 C 818.98721,87.545209 818.5,87 818.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -10,0 c -0.5,0 -1,0.5 -1,1 l 0,31 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path24851"
+ style="opacity:0.07999998;fill:url(#linearGradient24869);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+ d="m 807.5,89.5 33,0 m -33,12 33,0 m -33,-4 33,0 m -33,-6 33,0 m -33,20 33,0 m -33,2 33,0 m -33,-18 33,0 m -33,-2 33,0 m -20,-6 -13,0 m 0,20 33,0 m -33,-2 33,0 m -33,-2 33,0 m -33,-4 33,0 m -33,10 33,0 m -33,6 33,0"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="74.800003"
+ inkscape:export-xdpi="74.800003"
+ inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png"
+ sodipodi:nodetypes="csccsczc"
+ id="path24853"
+ d="m 844,118.5 c 3.5,0 5.5,-2 5.5,-5.5 l 0,-18.5 c -11.75604,-1.11e-4 -23.91623,0 -35.5,0 l 0,19.5 c 0,4.5 -7,4 -7,0.25 0,2 2.00002,3.73529 3,3.75 l 34,0.5 z"
+ style="fill:url(#linearGradient24871);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:connector-curvature="0"
+ d="m 807,87 12,0 0.0385,-3.33333 C 819.04423,83.166705 818.97512,83 818.5,83 l -10.92308,0 c -0.47512,0 -0.53846,0.16667 -0.53846,0.66667 L 807,87 z"
+ id="path24855"
+ style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:nodetypes="ccssccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ d="m 840.5,89 0,4.5"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+ id="path24857" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path24859"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+ d="m 848.5,95.5 0,18 c 0,1.25 0.25,3 -1.25,4"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccsc"
+ d="m 818.5,83.5 -11,0 0,30 c 0,5 7,5 7,0 l 0,-18 34,0 m -29,-8 c 0,0.5 0.5286,1 1,1 l 20,0"
+ style="opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="path24861" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 806.5,113.5 c 0,2.75 2,5 5,5 l 33,0 c 3,0 5,-2 5,-5 l 0,-18 c 0,-0.471405 -0.5286,-1 -1,-1 l -7,0 0,-6 c 0,-0.5 -0.5,-1 -1,-1 l -20.02773,0.04419 C 819.98721,87.54526 819.5,87 819.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -11,0 c -0.5,0 -1,0.5 -1,1 l 0,30 z"
+ id="path24863"
+ style="fill:none;stroke:#000000;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"
+ sodipodi:nodetypes="ccccsscccssssccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient24873);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 841.5,94.5 -27,0 c -0.4714,0 -1,0.528595 -1,1 l 0,18 c 0,2.25 -1.25,3 -2.5,3"
+ id="path24865"
+ sodipodi:nodetypes="csscc" />
+ </g>
+ <g
+ style="opacity:0.5"
+ transform="translate(114,248)"
+ id="g24784">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 806.5,114.5 c 0,2.25 2,4 4,4 l 30,0 c 0.4163,0 1,-0.5 1,-1 l 0,-29 c 0,-0.5 -0.5,-1 -1,-1 l -21.02773,0.04419 C 818.98721,87.545209 818.5,87 818.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -10,0 c -0.5,0 -1,0.5 -1,1 l 0,31 z"
+ id="path24789"
+ style="fill:url(#linearGradient24809);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccssssccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccc"
+ d="m 807.5,89.5 33,0 m -33,12 33,0 m -33,-4 33,0 m -33,-6 33,0 m -33,20 33,0 m -33,2 33,0 m -33,-18 33,0 m -33,-2 33,0 m -20,-6 -13,0 m 0,20 33,0 m -33,-2 33,0 m -33,-2 33,0 m -33,-4 33,0 m -33,10 33,0 m -33,6 33,0"
+ style="opacity:0.07999998;fill:url(#linearGradient24811);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+ id="path24791" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient24813);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 844,118.5 c 3.5,0 5.5,-2 5.5,-5.5 l 0,-18.5 c -11.75604,-1.11e-4 -23.91623,0 -35.5,0 l 0,19.5 c 0,4.5 -7,4 -7,0.25 0,2 2.00002,3.73529 3,3.75 l 34,0.5 z"
+ id="path24793"
+ sodipodi:nodetypes="csccsczc"
+ inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png"
+ inkscape:export-xdpi="74.800003"
+ inkscape:export-ydpi="74.800003" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccssccc"
+ style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path24796"
+ d="m 807,87 12,0 0.0385,-3.33333 C 819.04423,83.166705 818.97512,83 818.5,83 l -10.92308,0 c -0.47512,0 -0.53846,0.16667 -0.53846,0.66667 L 807,87 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path24799"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+ d="m 840.5,89 0,4.5"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ d="m 848.5,95.5 0,18 c 0,1.25 0.25,3 -1.25,4"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+ id="path24801" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path24803"
+ style="opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ d="m 818.5,83.5 -11,0 0,30 c 0,5 7,5 7,0 l 0,-18 34,0 m -29,-8 c 0,0.5 0.5286,1 1,1 l 20,0"
+ sodipodi:nodetypes="cccccccsc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccsscccssssccc"
+ style="fill:none;stroke:#000000;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="path24805"
+ d="m 806.5,113.5 c 0,2.75 2,5 5,5 l 33,0 c 3,0 5,-2 5,-5 l 0,-18 c 0,-0.471405 -0.5286,-1 -1,-1 l -7,0 0,-6 c 0,-0.5 -0.5,-1 -1,-1 l -20.02773,0.04419 C 819.98721,87.54526 819.5,87 819.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -11,0 c -0.5,0 -1,0.5 -1,1 l 0,30 z" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csscc"
+ id="path24807"
+ d="m 841.5,94.5 -27,0 c -0.4714,0 -1,0.528595 -1,1 l 0,18 c 0,2.25 -1.25,3 -2.5,3"
+ style="fill:none;stroke:url(#linearGradient24815);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ </g>
+ <g
+ transform="translate(0,-2)"
+ style="opacity:0.4;stroke:#3d361a;filter:url(#filter44473)"
+ id="g44424">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path44406"
+ d="m 950.25,362 -5.25,0 -1,-1 0,-10"
+ style="fill:none;stroke:#3d361a;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path44408"
+ d="M 948.25,354.25 944,350.00563 939.75,354.25"
+ style="fill:none;stroke:#3d361a;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new" />
+ </g>
+ <g
+ transform="translate(617,273)"
+ id="g44334"
+ style="display:inline;enable-background:new">
+ <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="rect44336"
+ width="16"
+ height="16"
+ x="320"
+ y="73" />
+ <g
+ transform="translate(0,-21)"
+ id="g44338">
+ <g
+ id="g44340">
+ <g
+ transform="translate(0,21)"
+ id="g44342">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path44344"
+ d="m 333.25,87 -5.25,0 -1,-1 0,-10"
+ style="fill:none;stroke:#000000;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path44346"
+ d="M 331.25,79.25 327,75.005631 322.75,79.25"
+ style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ <g
+ transform="translate(0,21)"
+ id="g44348">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 333.25,87 -5.25,0 -1,-1 0,-10"
+ id="path44350"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M 331.25,79.25 327,75.005631 322.75,79.25"
+ id="path44352"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 328.5,107.5 5,0 m -7,-9 0,8.5 m -4.25,-7 4.5,-4.5"
+ id="path44354"
+ sodipodi:nodetypes="cccccc" />
+ </g>
+ </g>
+ <g
+ transform="translate(66,248)"
+ id="g24818"
+ style="display:inline;enable-background:new">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccssssccc"
+ style="fill:url(#linearGradient24839);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path24821"
+ d="m 806.5,114.5 c 0,2.25 2,4 4,4 l 30,0 c 0.4163,0 1,-0.5 1,-1 l 0,-29 c 0,-0.5 -0.5,-1 -1,-1 l -21.02773,0.04419 C 818.98721,87.545209 818.5,87 818.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -10,0 c -0.5,0 -1,0.5 -1,1 l 0,31 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path24823"
+ style="opacity:0.07999998;fill:url(#linearGradient24841);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+ d="m 807.5,89.5 33,0 m -33,12 33,0 m -33,-4 33,0 m -33,-6 33,0 m -33,20 33,0 m -33,2 33,0 m -33,-18 33,0 m -33,-2 33,0 m -20,-6 -13,0 m 0,20 33,0 m -33,-2 33,0 m -33,-2 33,0 m -33,-4 33,0 m -33,10 33,0 m -33,6 33,0"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="74.800003"
+ inkscape:export-xdpi="74.800003"
+ inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png"
+ sodipodi:nodetypes="csccsczc"
+ id="path24825"
+ d="m 844,118.5 c 3.5,0 5.5,-2 5.5,-5.5 l 0,-16 c -11.75604,-1.11e-4 -23.91623,0 -35.5,0 l 0,17 c 0,4.5 -7,4 -7,0.25 0,2 2.00002,3.73529 3,3.75 l 34,0.5 z"
+ style="fill:url(#linearGradient24843);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:connector-curvature="0"
+ d="m 807,87 12,0 0.0385,-3.33333 C 819.04423,83.166705 818.97512,83 818.5,83 l -10.92308,0 c -0.47512,0 -0.53846,0.16667 -0.53846,0.66667 L 807,87 z"
+ id="path24827"
+ style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:nodetypes="ccssccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ d="m 840.5,89 0,7.5"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+ id="path24829" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path24831"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+ d="m 848.5,98.75 0,14.75 c 0,1.25 0.25,3 -1.25,4"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccsc"
+ d="m 818.5,83.5 -11,0 0,30 c 0,5 7,5 7,0 l 0,-16 34,0 m -29,-10 c 0,0.5 0.5286,1 1,1 l 20,0"
+ style="opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="path24833" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 806.5,113.5 c 0,2.75 2,5 5,5 l 33,0 c 3,0 5,-2 5,-5 l 0,-16 c 0,-0.471405 -0.5286,-1 -1,-1 l -7,0 0,-8 c 0,-0.5 -0.5,-1 -1,-1 l -20.02773,0.04419 C 819.98721,87.54526 819.5,87 819.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -11,0 c -0.5,0 -1,0.5 -1,1 l 0,30 z"
+ id="path24835"
+ style="fill:none;stroke:#000000;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"
+ sodipodi:nodetypes="ccccsscccssssccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient24845);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 841.5,96.500004 -27,0 c -0.4714,0 -1,0.528595 -1,1 l 0,15.999996 c 0,2.25 -1.25,3 -2.5,3"
+ id="path24837"
+ sodipodi:nodetypes="csscc" />
+ </g>
+ <g
+ style="opacity:0.4;filter:url(#filter44477)"
+ id="g44455">
+ <path
+ inkscape:connector-curvature="0"
+ transform="translate(645,252.05)"
+ style="fill:none;stroke:#3d361a;stroke-width:5;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.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5"
+ id="path44446"
+ sodipodi:nodetypes="cs" />
+ <path
+ inkscape:connector-curvature="0"
+ transform="translate(645,252.05)"
+ style="fill:none;stroke:#3d361a;stroke-width:5;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,108.25 0,-4.25 4.25,0"
+ id="path44449"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ transform="matrix(-1,0,0,-1,1343,456.05)"
+ sodipodi:nodetypes="cs"
+ id="path44451"
+ d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5"
+ style="fill:none;stroke:#3d361a;stroke-width:5;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"
+ transform="matrix(-1,0,0,-1,1343,456.05)"
+ sodipodi:nodetypes="ccc"
+ id="path44453"
+ d="m 343,108.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#3d361a;stroke-width:5;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
+ transform="translate(645,273.05)"
+ id="g44356"
+ style="display:inline;enable-background:new">
+ <rect
+ y="73"
+ x="341"
+ height="16"
+ width="16"
+ id="rect44358"
+ 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(0,-21)"
+ id="g44360">
+ <g
+ id="g44362">
+ <g
+ id="g44364">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cs"
+ id="path44366"
+ d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5"
+ style="fill:none;stroke:#000000;stroke-width:3.5;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="path44368"
+ d="m 343,108.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#000000;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" />
+ </g>
+ <g
+ id="g44370">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#e6e6e6;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 343,108.25 0,-4.25 4.25,0"
+ id="path44372"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#e6e6e6;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 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5"
+ id="path44374"
+ sodipodi:nodetypes="cs" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ id="path44376"
+ d="m 344,105 0,1 0,1.5 1,0 0,-1.5 1.5,0 0,-1 -1.5,0 -1,0 z"
+ style="opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <g
+ id="g44378"
+ transform="matrix(-1,0,0,-1,698,204)">
+ <g
+ id="g44380">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000;stroke-width:3.5;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.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5"
+ id="path44382"
+ sodipodi:nodetypes="cs" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000;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,108.25 0,-4.25 4.25,0"
+ id="path44384"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <g
+ id="g44386">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path44388"
+ d="m 343,108.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#e6e6e6;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" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cs"
+ id="path44390"
+ d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5"
+ style="fill:none;stroke:#e6e6e6;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" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 344,105 0,1 0,1.5 1,0 0,-1.5 1.5,0 0,-1 -1.5,0 -1,0 z"
+ id="path44392" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient44402);stroke-width:1.10000002;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 344.90625,106.59375 c 2.52573,2.51828 6.66805,2.52691 9.1875,0 l 0.5,-0.5"
+ id="path44394"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 350.5,99.5 4,0 0,-4"
+ id="path44396"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 347.5,103.5 -4.5,0 c -0.25,0 -0.5,0.25 -0.5,0.5 l 0,4.5"
+ id="path44398"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient44404);stroke-width:1.10000002;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 345.59375,105.90625 c 2.07803,2.0719 5.36384,2.10325 7.53125,0.1875 L 354,105.25"
+ id="path44400"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ </g>
+ <g
+ id="g34977"
+ style="display:inline;enable-background:new">
+ <g
+ style="display:inline"
+ id="g21853-3"
+ transform="translate(856,-154)"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ ry="0"
+ rx="2.4004419"
+ y="430"
+ x="108"
+ height="48"
+ width="48"
+ id="rect21855-8"
+ 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" />
+ <g
+ id="g21857-6">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient21875-7-1-0-1);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ id="path21859-9"
+ 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"
+ d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path21861-8"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="url(#clipPath13106-9-2-9-9)"
+ 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="cccc"
+ id="path21863-6"
+ d="m 115,444 12,0 -1,-11 -11,11 z"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011-6-7-0-8)" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="none"
+ 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 117.5,443.75 9,-2.5 0,-6"
+ style="fill:none;stroke:url(#linearGradient21877-3-2-7-2);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path21865-6"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path21867-2"
+ style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 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"
+ clip-path="url(#clipPath13106-9-2-9-9)"
+ 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="cccc"
+ id="path21869-3"
+ d="m 116,443 11,1 -2,-10 -9,9 z"
+ style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011-6-7-0-8)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z"
+ id="path21871-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:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path21873-2"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 147.5,435 0,38.5 -30.5,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" />
+ </g>
+ </g>
+ <g
+ id="g34938"
+ transform="translate(63,-47)">
+ <path
+ id="path61236"
+ style="color:#000000;fill:url(#linearGradient34959-9-2-1);fill-opacity:1;fill-rule:nonzero;stroke:#ff0000;stroke-width:0.17893334;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 919.5,356.5067 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.0064 2.5,0.006 c 2,0 3.5,2.5 3.5,6 0,3.5 -1.25,6 -3.5,6 -4.98134,0 -12.77318,0 -2.5,0 l 0,2.75 c 0,2.5 -2,3.24997 -5.5,3.24998 l 0,2e-5 c -3.5,0.0104 -5.5,-0.75 -5.5,-3.25 l 0,-2.7628"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cssssccsscsccsc" />
+ <path
+ sodipodi:nodetypes="cssssccsscsccsc"
+ inkscape:connector-curvature="0"
+ 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.0064 -2.5,-0.006 c -2,0 -3.5,-2.5 -3.5,-6 0,-3.5 1.25,-6 3.5,-6 4.98134,0 12.77318,0 2.5,0 l 0,-2.75 c 0,-2.5 2,-3.24997 5.5,-3.24998 l 0,-2e-5 c 3.5,-0.0104 5.5,0.75 5.5,3.25 l 0,2.7628"
+ style="color:#000000;fill:url(#linearGradient34961-3-6-5);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.17893334;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path61233" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccscccsccccsccccc"
+ id="path61167"
+ d="m 925,338.50002 c -3.5,10e-6 -5.5,0.74998 -5.5,3.24998 l 0,2.75 5.5,0 -8,0 c -2.25,0 -3.5,2.5 -3.5,6 0,3.5 1.5,6 3.5,6 l 2.5,0.0128 0,2.9872 c 0,2 2,3.01281 5.5,3.0128 3.5,-1e-5 5.5,-1.0128 5.5,-3.0128 l 0,-3 -5.5,0 8,0 c 2,0 3.5,-2.5 3.5,-6 0,-3.5 -1.5,-6 -3.5,-6 l -2.5,0.0128 0,-2.7628 c 0,-2.5 -2,-3.26045 -5.5,-3.25 z"
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-miterlimit:4;stroke-opacity:0.8627451;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path61169"
+ 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 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="342"
+ sodipodi:cx="922"
+ id="path61220"
+ 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 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="359"
+ sodipodi:cx="928"
+ id="path61222"
+ 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" />
+ <g
+ style="opacity:0.4"
+ id="g61345">
+ <path
+ style="fill:none;stroke:url(#linearGradient34963-5-9-1);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 920.5,343.25 0,-1.5 c 0,-1.75 1.5,-2.25 4.5,-2.25 3,0 4.5,0.5 4.5,2.25 l 0,4.75"
+ id="path61333"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cszsc" />
+ <path
+ style="fill:none;stroke:url(#linearGradient34965-1-5-2);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 925.5,345 0,0.25 -0.25,0.25 -8.25,0 c -1.5,0 -2.5,2 -2.5,5 0,3 1.28917,5 2.5,5 l 1.5,0"
+ id="path61335"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccszsc" />
+ <path
+ style="fill:none;stroke:none"
+ d="m 920.75,343.5 4.5,0 0.25,0.25 0,0.5"
+ id="path61337"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:none"
+ d="m 918.5,355.25 0,-1.75 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"
+ id="path61339"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cssssc" />
+ <path
+ transform="matrix(1.5161021,0,0,1.5161021,-475.84616,-176.50693)"
+ sodipodi:type="arc"
+ style="color:#000000;fill:none;stroke:url(#linearGradient34967-4-1-8);stroke-width:0.52766895;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path61355"
+ sodipodi:cx="922"
+ sodipodi:cy="342"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 923,342 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z" />
+ </g>
+ <g
+ style="opacity:0.8;stroke:#ff0000"
+ transform="matrix(-1,0,0,-1,1850,701)"
+ id="g34104">
+ <path
+ sodipodi:nodetypes="cszsc"
+ inkscape:connector-curvature="0"
+ id="path34106"
+ d="m 920.5,343.25 0,-1.5 c 0,-1.75 1.5,-2.25 4.5,-2.25 3,0 4.5,0.5 4.5,2.25 l 0,4.75"
+ style="fill:none;stroke:none" />
+ <path
+ sodipodi:nodetypes="csc"
+ inkscape:connector-curvature="0"
+ id="path34108"
+ d="m 914.5,350.5 c 0,3 1.28917,5 2.5,5 l 1.5,0"
+ style="fill:none;stroke:url(#linearGradient34969-4-4-1);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path34110"
+ d="m 920.75,343.5 4.5,0 0.25,0.25 0,0.5"
+ style="fill:none;stroke:url(#linearGradient34971-5-0-9);stroke-linecap:round;stroke-linejoin:round" />
+ <path
+ sodipodi:nodetypes="cssssc"
+ inkscape:connector-curvature="0"
+ id="path34113"
+ 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 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="342"
+ sodipodi:cx="922"
+ id="path34115"
+ style="color:#000000;fill:none;stroke:url(#linearGradient34975-9-4-9);stroke-width:0.52766895;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ transform="matrix(1.5161021,0,0,1.5161021,-475.84616,-176.50693)" />
+ <path
+ style="fill:none;stroke:none"
+ d="m 925.5,345 0,0.25 -0.25,0.25 -8.25,0 c -1.5,0 -2.5,2 -2.5,5"
+ id="path34901"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccsc" />
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ id="g44575"
+ 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"
+ transform="translate(168,-42)">
+ <g
+ id="g43593"
+ transform="matrix(-1,0,0,1,677,525)">
+ <path
+ style="fill:none;stroke:#000000;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="path43595"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;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="path43597"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(1,0,0,-1,-21,729)"
+ id="g44539">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path44541"
+ d="m 347.25,100.25 -4,-4"
+ style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path44543"
+ d="m 343,100.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#000000;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g43599"
+ transform="matrix(-1,0,0,1,677,517)">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path43601"
+ d="M 347.25,108.25 343,104"
+ style="fill:none;stroke:#dcdcdc;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path43603"
+ d="m 343,108.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#dcdcdc;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="opacity:0.93999993;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 333.5,622.5 0,3 m -4,-5 4.5,0"
+ id="path44489"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.93999993;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 329.25,625 2,-2"
+ id="path44491"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 333,622 0,1 0,1.5 -1,0 0,-1.5 -1.5,0 0,-1 1.5,0 1,0 z"
+ id="path43605"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(1,0,0,-1,-21,737)"
+ id="g44545">
+ <path
+ style="fill:none;stroke:#dcdcdc;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 347.25,108.25 343,104"
+ id="path44547"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#dcdcdc;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 343,108.25 0,-4.25 4.25,0"
+ id="path44549"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path44551"
+ d="m 323.5,632.5 3,0 m -5,-4 0,4.5"
+ style="opacity:0.93999993;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path44553"
+ d="m 326,628.25 -2,2"
+ style="opacity:0.93999993;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path44555"
+ d="m 323,632 0,-1 0,-1.5 1,0 0,1.5 1.5,0 0,1 -1.5,0 -1,0 z"
+ style="opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g44633"
+ 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"
+ inkscape:export-ydpi="90">
+ <g
+ id="g44671"
+ transform="matrix(-1,0,0,-1,662.9375,1247)">
+ <g
+ id="g44635"
+ transform="matrix(-1,0,0,1,677,525)">
+ <path
+ style="fill:none;stroke:#000000;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"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;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"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g44647"
+ transform="matrix(-1,0,0,1,677,517)">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path44649"
+ d="M 347.25,108.25 343,104"
+ style="fill:none;stroke:#dcdcdc;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path44651"
+ d="m 343,108.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#dcdcdc;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="opacity:0.93999993;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 332.5,621.5 -3,0 m 5,4 0,-4.5"
+ id="path44653"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.93999993;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 330,625.75 2,-2"
+ id="path44655"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 333,622 0,1 0,1.5 -1,0 0,-1.5 -1.5,0 0,-1 1.5,0 1,0 z"
+ id="path44657"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g44682"
+ transform="matrix(-1,0,0,-1,648.9375,1261)">
+ <g
+ transform="matrix(1,0,0,-1,-21,729)"
+ id="g44641">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path44643"
+ d="m 347.25,100.25 -4,-4"
+ style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path44645"
+ d="m 343,100.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#000000;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(1,0,0,-1,-21,737)"
+ id="g44659">
+ <path
+ style="fill:none;stroke:#dcdcdc;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 347.25,108.25 343,104"
+ id="path44661"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#dcdcdc;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 343,108.25 0,-4.25 4.25,0"
+ id="path44663"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path44665"
+ d="m 322.5,631.5 0,-3 m 4,5 -4.5,0"
+ style="opacity:0.93999993;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path44667"
+ d="m 326.75,629 -2,2"
+ style="opacity:0.93999993;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path44669"
+ d="m 323,632 0,-1 0,-1.5 1,0 0,1.5 1.5,0 0,1 -1.5,0 -1,0 z"
+ style="opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ clip-path="url(#clipPath45147)"
+ id="g45199">
+ <g
+ id="g45201"
+ clip-path="none"
+ transform="translate(1,1)">
+ <rect
+ y="261"
+ x="4"
+ height="16"
+ width="16"
+ id="rect45203"
+ 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(-96.98388,244)"
+ 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="g45205"
+ style="display:inline">
+ <path
+ id="path45207"
+ style="fill:url(#linearGradient45220);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 105.48388,31.25 6.25,-6 c 0.49692,0.284098 0.2225,0.232267 0.76612,0.25 2.20206,0.07183 4,-1.792 4,-4 l -1,-1 -2.5,2.5 -0.5,-0.5 -1,-1 -0.5,-0.5 2.5,-2.5 -1,-1 c -2.208,0 -4,1.792 -4,4 0,0.58349 0.009,0.250006 0.23388,0.75 l -6.25,6 0,2 1,1 2,0 z"
+ sodipodi:nodetypes="ccsccccccccsccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ d="m 115.5,21.5 -2.25,2.25 m -1,-5.5 c -1.75,0 -4,2.25 -2.5,5 l -1.26612,0.25 -5,5 0,1.75"
+ 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"
+ id="path45209"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccsccccccccsccccccc"
+ d="m 105.48388,31.5 5.5,-5.5 0.25,-0.5 1.26612,0 c 2.73388,0 4,-1.792 4,-4 l -1,-1 -2.5,2.5 -0.5,-0.5 -1,-1 -0.5,-0.5 2.5,-2.5 -1,-1 c -2.208,0 -3.96454,1.25 -4,4 l -0.0161,1.25 -0.5,0.25 -5.5,5.5 0,2 1,1 2,0 -2e-5,0 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;stroke-dashoffset:0"
+ id="path45211"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ d="m 109.98388,25 -5,5"
+ style="fill:none;stroke:#afc6e9;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path45214"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path45216"
+ style="fill:none;stroke:#336abd;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 109.48388,24.5 -4,4"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#162d50;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.0999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect45218"
+ width="1"
+ height="1"
+ x="103.98388"
+ y="29" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g45262">
+ <rect
+ style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="rect45264"
+ width="16"
+ height="16"
+ x="-420"
+ y="577"
+ transform="scale(-1,1)" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:3.29999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 412,585 0,-6"
+ id="path45266"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path45268"
+ d="m 412,585 0,-6"
+ style="fill:none;stroke:#b3b3b3;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <g
+ style="fill:none;stroke:#ffffff;stroke-width:2.56570244;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="g45270"
+ transform="matrix(0.5478212,-0.56064,0.5419177,0.5545983,197.19518,557.21673)"
+ 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
+ sodipodi:open="true"
+ transform="matrix(0.9615911,0.00541935,0.00537191,0.9740527,43.776178,107.51876)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:#000000;stroke-width:4.37432003;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="path45272"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 139.98403,118.50525 a 8,8 0 1 1 -8.39706,-8.49458"
+ 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"
+ sodipodi:start="0.063198177"
+ sodipodi:end="4.6607369" />
+ <path
+ sodipodi:end="4.6607369"
+ sodipodi:start="0.063198177"
+ 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 a 8,8 0 1 1 -8.39706,-8.49458"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path45274"
+ style="fill:none;stroke:#b3b3b3;stroke-width:2.65110302;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:type="arc"
+ transform="matrix(0.9615911,0.00541935,0.00537191,0.9740527,43.776178,107.51876)"
+ sodipodi:open="true" />
+ <path
+ sodipodi:open="true"
+ transform="matrix(1.0558925,0.00528428,0.00523802,1.0695762,31.432317,96.175729)"
+ sodipodi:type="arc"
+ style="opacity:0.75;fill:none;stroke:url(#linearGradient45283);stroke-width:1.20716298;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="path45276"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 139.98403,118.50525 a 8,8 0 1 1 -8.39706,-8.49458"
+ 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"
+ sodipodi:start="0.063198177"
+ sodipodi:end="4.6607369" />
+ <path
+ sodipodi:open="true"
+ sodipodi:end="4.6607369"
+ sodipodi:start="0.063198177"
+ 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 a 8,8 0 1 1 -8.39706,-8.49458"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path45278"
+ style="opacity:0.75;fill:none;stroke:url(#linearGradient45285);stroke-width:1.44679213;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:type="arc"
+ transform="matrix(0.8810135,0.00553476,0.00548631,0.8924309,54.323627,117.21103)" />
+ </g>
+ <path
+ style="opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 411.5,585 0,-6"
+ id="path45280"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ transform="translate(517.99163,649)"
+ id="g45287">
+ <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"
+ style="opacity:0.25;fill:none;stroke:#000000;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"
+ id="path45290"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ d="m -120.5,-68.5 c -3.15098,1.124146 -6.99163,5 -8.99163,9 l -3.5,-3.5 -0.5,0.5 4,4 c 1.42501,-3.330356 5.5,-8.75 8.99163,-10"
+ style="fill:none;stroke:#0b1e00;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"
+ id="path45302"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path45294"
+ style="fill:none;stroke:#9af23d;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -120.5,-68.5 c -3.15098,1.124146 -6.99163,5 -8.99163,9 l -3.5,-3.5 -0.5,0.5 4,4 c 1.42501,-3.330356 5.5,-8.75 8.99163,-10"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g42952"
+ style="display:inline;enable-background:new"
+ transform="translate(433,-61)">
+ <rect
+ y="554"
+ x="-113"
+ height="16"
+ width="16"
+ id="rect42954"
+ 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(-252,462.99988)"
+ id="g42956">
+ <g
+ id="g42958"
+ transform="translate(-179,199.50012)">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;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"
+ d="m 328.5,-107.25 -4.5,1.75 0,6.5 4.5,2.25 4.5,-2.25 0,-6.5 -4.5,-1.75 z"
+ id="path42960"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g42962"
+ transform="translate(179,-179)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path42964"
+ d="m 154,80 0,-6.5 -4.5,-1.75 0,10.5 L 154,80 z"
+ style="fill:#808080;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" />
+ </g>
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ id="path42966"
+ d="m 324,-99.00012 0,-6.49988 4.5,-1.75 0.5,0.25 0,10 -0.5,0.25 -4.5,-2.25012 z"
+ style="fill:#cccccc;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="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path42968"
+ d="m 332.5,-105.5 0,6.25 -4,2 -4,-2.00012 0,-6.24988"
+ style="fill:none;stroke:url(#linearGradient42988);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path42970"
+ d="m 324,-105.5 4.5,-1.75 4.5,1.75 -4.5,2 -4.5,-2 z"
+ style="fill:#f2f2f2;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="path42972"
+ d="m 145.5,94.25012 c 0,0 4,1.75 4,1.75 l 4,-1.75"
+ style="opacity:0.95999995;fill:none;stroke:url(#linearGradient42990);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="96.000122"
+ x="149"
+ height="6.7500019"
+ width="1"
+ id="rect42974"
+ style="opacity:0.18000004;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.09599998;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect42976"
+ width="1"
+ height="6.7500019"
+ x="150"
+ y="96.000122" />
+ </g>
+ <g
+ 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(0.7882544,0,0,0.7883038,-210.45268,388.9974)"
+ id="g42978"
+ style="display:inline;enable-background:new">
+ <path
+ transform="matrix(0.6425292,0,0,0.642531,44.523834,146.81699)"
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.97436094;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42980"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(-0.5858806,-0.06590218,0.06677852,-0.5812167,198.80048,299.96262)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path42982"
+ style="opacity:0.8;fill:url(#linearGradient42992);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:type="arc" />
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path42984"
+ style="fill:none;stroke:url(#linearGradient42994);stroke-width:2.54167628;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.4991181,0,0,0.4991107,63.460522,163.7471)" />
+ </g>
+ <path
+ id="path42986"
+ d="m -102.5625,554.75 c -0.0429,0.005 -0.0849,0.0154 -0.125,0.0312 l -4.5,1.75 c -0.1919,0.0756 -0.31653,0.26258 -0.3125,0.4688 l 0,6.5 c 0.003,0.18741 0.11203,0.35691 0.28125,0.4375 l 4.5,2.25 c 0.13787,0.0682 0.29963,0.0682 0.4375,0 l 4.499997,-2.25 c 0.169224,-0.0806 0.278188,-0.25009 0.28125,-0.4375 l 0,-6.5 c 0.004,-0.2062 -0.120622,-0.39315 -0.3125,-0.46875 l -4.499997,-1.75 c -0.0792,-0.0318 -0.16537,-0.0426 -0.25,-0.0312 l 0,-5e-5 z"
+ style="opacity:0.3;fill:none;stroke:url(#linearGradient42996);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" />
+ </g>
+ <g
+ id="g43828">
+ <g
+ transform="translate(0,128)"
+ id="g24024">
+ <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="rect22150"
+ width="16"
+ height="16"
+ x="299"
+ y="365" />
+ <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="path12337"
+ d="m 304.20488,366.47791 8.33334,0 0,13 -11,0 -1e-5,-10 2.66667,-3 0,0 0,0 0,0 z"
+ style="fill:url(#linearGradient14204);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(1.2999758,0,0,1.2999988,365.56499,31.43979)"
+ sodipodi:nodetypes="ccc"
+ id="path12339"
+ style="opacity:0.7;fill:none;stroke:#000000;stroke-width:0.76923829px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1;display:inline;filter:url(#filter31351)"
+ d="M -48.500031,260.50809 -46.5,260.5 l -3.1e-5,-1.99191"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path12341"
+ d="m 301.01612,370 4,0 0,-4 -4,4 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path12343"
+ style="fill:none;stroke:url(#linearGradient14198);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 302.51612,371.00001 0,7.5 m 3.5,-11 5.5,0"
+ 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 301.53822,368.97791 0,10.5 11,0 0,-13 -8.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="path12345"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ transform="translate(-454.0088,290)"
+ mask="url(#mask43822)"
+ sodipodi:nodetypes="cccccccc"
+ id="path43815"
+ d="m 765.0088,212.5 -3.9824,3.5 -0.0176,-2 -6.9736,0 -0.0132,-3 6.9868,0 0.004,-2 z"
+ style="opacity:0.93999993;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ inkscape:transform-center-x="-2"
+ inkscape:transform-center-y="1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g43838"
+ transform="translate(0,-21)"
+ style="opacity:0.4">
+ <g
+ id="g43840"
+ transform="translate(0,128)">
+ <rect
+ y="365"
+ x="299"
+ height="16"
+ width="16"
+ id="rect43842"
+ 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
+ style="fill:url(#linearGradient43856);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 304.20488,366.47791 8.33334,0 0,13 -11,0 -1e-5,-10 2.66667,-3 0,0 0,0 0,0 z"
+ id="path43844"
+ 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
+ d="M -48.500031,260.50809 -46.5,260.5 l -3.1e-5,-1.99191"
+ style="opacity:0.7;fill:none;stroke:#000000;stroke-width:0.76923829px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1;display:inline;filter:url(#filter31351)"
+ id="path43846"
+ sodipodi:nodetypes="ccc"
+ transform="matrix(1.2999758,0,0,1.2999988,365.56499,31.43979)"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 301.01612,370 4,0 0,-4 -4,4 z"
+ id="path43848"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 302.51612,371.00001 0,7.5 m 3.5,-11 5.5,0"
+ style="fill:none;stroke:url(#linearGradient43858);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ id="path43850"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path43852"
+ 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 301.53822,368.97791 0,10.5 11,0 0,-13 -8.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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ inkscape:transform-center-y="1"
+ inkscape:transform-center-x="-2"
+ style="opacity:0.93999993;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ d="m 765.0088,212.5 -3.9824,3.5 -0.0176,-2 -6.9736,0 -0.0132,-3 6.9868,0 0.004,-2 z"
+ id="path43854"
+ sodipodi:nodetypes="cccccccc"
+ mask="url(#mask43822)"
+ transform="translate(-454.0088,290)"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g46790"
+ transform="translate(0,12)" />
+ <g
+ id="g46890" />
+ <g
+ id="g46912"
+ 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"
+ inkscape:export-ydpi="90">
+ <rect
+ y="107"
+ x="23"
+ height="16"
+ width="16"
+ id="rect46788"
+ style="opacity:0.01000001;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"
+ transform="matrix(-1,0,0,1,0,12)" />
+ <g
+ style="opacity:0.55;display:inline;enable-background:new"
+ transform="translate(-22,30)"
+ id="g46766">
+ <g
+ id="g46768"
+ transform="translate(23.01472,-88)">
+ <path
+ id="path46770"
+ style="fill:none;stroke:url(#linearGradient46780);stroke-width:3.29999995;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 -34.51472,179.5 C -38,184.5 -37.5,189 -37.50346,190.5"
+ 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
+ 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"
+ d="M -34.51472,179.5 C -38,184.5 -37.5,189 -37.50346,190.5"
+ style="fill:none;stroke:url(#linearGradient46782);stroke-width:1.70000005;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="path46772"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(24.03125,-88)"
+ id="g46774">
+ <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"
+ d="m -28.53125,182.5 c -4.5,2 -4.96875,6.5 -4.96875,8"
+ style="fill:none;stroke:url(#linearGradient46784);stroke-width:3.29999995;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="path46776"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path46778"
+ style="fill:none;stroke:url(#linearGradient46786);stroke-width:1.70000005;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 -28.53125,182.5 c -4.5,2 -4.96875,6 -4.96875,8"
+ 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>
+ </g>
+ <g
+ id="g46860"
+ transform="translate(18.998123,-58.00355)"
+ style="display:inline;enable-background:new">
+ <path
+ id="path46862"
+ d="m -52.01365,177.50527 0.03679,0 c 0.818181,0 1.476865,0.66665 1.476865,1.49473 l 0,1.2e-4 c 0,0.82808 -0.658684,1.49472 -1.476865,1.49472 l -0.03679,0 c -0.81819,0 -1.476874,-0.66664 -1.476874,-1.49472 l 0,-1.2e-4 c 0,-0.82808 0.658684,-1.49473 1.476874,-1.49473 l 0,0 0,0 z"
+ style="fill:none;stroke:#462300;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"
+ 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="path46864"
+ d="m -50.998123,178.00355 c -0.66732,0 -1.334639,1e-5 -2.001959,1e-5 0,0.66706 0,1.33411 0,2.00119 0.66732,0 1.334639,-1e-5 2.001959,-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;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ transform="translate(26.01365,-55.00527)"
+ id="g46866">
+ <path
+ style="fill:none;stroke:#462300;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 -52.01365,177.50527 0.03679,0 c 0.818181,0 1.476865,0.66665 1.476865,1.49473 l 0,1.2e-4 c 0,0.82808 -0.658684,1.49472 -1.476865,1.49472 l -0.03679,0 c -0.81819,0 -1.476874,-0.66664 -1.476874,-1.49472 l 0,-1.2e-4 c 0,-0.82808 0.658684,-1.49473 1.476874,-1.49473 l 0,0 0,0 z"
+ id="path46868"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffc17d;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ d="m -50.998123,178.00355 c -0.66732,0 -1.334639,1e-5 -2.001959,1e-5 0,0.66706 0,1.33411 0,2.00119 0.66732,0 1.334639,-1e-5 2.001959,-1e-5 0,-0.66707 0,-1.33413 0,-2.00119 z"
+ id="path46870"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g46928"
+ 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"
+ inkscape:export-ydpi="90">
+ <g
+ transform="translate(-20,0)"
+ id="g46800">
+ <rect
+ transform="scale(-1,1)"
+ style="opacity:0.01000001;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"
+ id="rect46802"
+ width="16"
+ height="16"
+ x="24"
+ y="119" />
+ <g
+ id="g46804"
+ transform="translate(-22,18)"
+ style="opacity:0.55;display:inline;enable-background:new">
+ <g
+ transform="translate(23.01472,-76)"
+ id="g46806">
+ <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"
+ d="M -34.51472,179.5 C -38,184.5 -37.5,189 -37.50346,190.5"
+ style="fill:none;stroke:url(#linearGradient46818);stroke-width:3.29999995;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="path46808"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path46810"
+ style="fill:none;stroke:url(#linearGradient46820);stroke-width:1.70000005;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 -34.51472,179.5 C -38,184.5 -37.5,189 -37.50346,190.5"
+ 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>
+ <g
+ id="g46812"
+ transform="translate(24,-76)">
+ <path
+ id="path46814"
+ style="fill:none;stroke:url(#linearGradient46822);stroke-width:3.29999995;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 -28.53125,182.5 c -4.5,2 -4.96875,6.5 -4.96875,8"
+ 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
+ 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"
+ d="m -28.53125,182.5 c -4.5,2 -4.96875,6 -4.96875,8"
+ style="fill:none;stroke:url(#linearGradient46824);stroke-width:1.70000005;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="path46816"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ transform="translate(-4.98635,-46.00527)"
+ id="g46872">
+ <path
+ style="fill:none;stroke:#462300;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 -52.01365,177.50527 0.03679,0 c 0.818181,0 1.476865,0.66665 1.476865,1.49473 l 0,1.2e-4 c 0,0.82808 -0.658684,1.49472 -1.476865,1.49472 l -0.03679,0 c -0.81819,0 -1.476874,-0.66664 -1.476874,-1.49472 l 0,-1.2e-4 c 0,-0.82808 0.658684,-1.49473 1.476874,-1.49473 l 0,0 0,0 z"
+ id="path46874"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffc17d;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ d="m -50.998123,178.00355 c -0.66732,0 -1.334639,1e-5 -2.001959,1e-5 0,0.66706 0,1.33411 0,2.00119 0.66732,0 1.334639,-1e-5 2.001959,-1e-5 0,-0.66707 0,-1.33413 0,-2.00119 z"
+ id="path46876"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g46878"
+ transform="translate(-0.98635,-58.00527)"
+ style="display:inline;enable-background:new">
+ <path
+ id="path46880"
+ d="m -52.01365,177.50527 0.03679,0 c 0.818181,0 1.476865,0.66665 1.476865,1.49473 l 0,1.2e-4 c 0,0.82808 -0.658684,1.49472 -1.476865,1.49472 l -0.03679,0 c -0.81819,0 -1.476874,-0.66664 -1.476874,-1.49472 l 0,-1.2e-4 c 0,-0.82808 0.658684,-1.49473 1.476874,-1.49473 l 0,0 0,0 z"
+ style="fill:none;stroke:#462300;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"
+ 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="path46882"
+ d="m -50.998123,178.00355 c -0.66732,0 -1.334639,1e-5 -2.001959,1e-5 0,0.66706 0,1.33411 0,2.00119 0.66732,0 1.334639,-1e-5 2.001959,-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;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ transform="translate(-4.023135,-51.99484)"
+ id="g46884">
+ <path
+ style="fill:none;stroke:#462300;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 -52.01365,177.50527 0.03679,0 c 0.818181,0 1.476865,0.66665 1.476865,1.49473 l 0,1.2e-4 c 0,0.82808 -0.658684,1.49472 -1.476865,1.49472 l -0.03679,0 c -0.81819,0 -1.476874,-0.66664 -1.476874,-1.49472 l 0,-1.2e-4 c 0,-0.82808 0.658684,-1.49473 1.476874,-1.49473 l 0,0 0,0 z"
+ id="path46886"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffc17d;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ d="m -50.998123,178.00355 c -0.66732,0 -1.334639,1e-5 -2.001959,1e-5 0,0.66706 0,1.33411 0,2.00119 0.66732,0 1.334639,-1e-5 2.001959,-1e-5 0,-0.66707 0,-1.33413 0,-2.00119 z"
+ id="path46888"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g46958"
+ 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"
+ inkscape:export-ydpi="90">
+ <g
+ id="g46960"
+ transform="translate(22,12)">
+ <rect
+ y="107"
+ x="24"
+ height="16"
+ width="16"
+ id="rect46962"
+ style="opacity:0.01000001;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"
+ transform="scale(-1,1)" />
+ <g
+ style="opacity:0.55;display:inline;enable-background:new"
+ transform="translate(-22,18)"
+ id="g46964">
+ <g
+ id="g46966"
+ transform="translate(23.01472,-88)">
+ <path
+ id="path46968"
+ style="fill:none;stroke:url(#linearGradient46990);stroke-width:3.29999995;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 -34.51472,179.5 C -38,184.5 -37.5,189 -37.50346,190.5"
+ 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
+ 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"
+ d="M -34.51472,179.5 C -38,184.5 -37.5,189 -37.50346,190.5"
+ style="fill:none;stroke:url(#linearGradient46992);stroke-width:1.70000005;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="path46970"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(24.140625,-88)"
+ id="g46972">
+ <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"
+ d="m -28.53125,182.5 c -4.5,2 -4.96875,6.5 -4.96875,8"
+ style="fill:none;stroke:url(#linearGradient46994);stroke-width:3.29999995;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="path46974"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path46976"
+ style="fill:none;stroke:url(#linearGradient46996);stroke-width:1.70000005;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 -28.53125,182.5 c -4.5,2 -4.96875,6 -4.96875,8"
+ 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>
+ <g
+ transform="translate(23.01472,-88)"
+ id="g46978">
+ <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"
+ d="M -34.51472,179.5 C -38,184.5 -37.5,189 -37.50346,190.5"
+ style="fill:none;stroke:url(#linearGradient46998);stroke-width:3.29999995;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="path46980"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path46982"
+ style="fill:none;stroke:url(#linearGradient47000);stroke-width:1.70000005;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 -34.51472,179.5 C -38,184.5 -37.5,189 -37.50346,190.5"
+ 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>
+ </g>
+ </g>
+ <g
+ transform="translate(24,-58)"
+ id="g46984"
+ style="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"
+ sodipodi:nodetypes="cc"
+ d="m -28.53125,182.5 c -4.5,2 -4.96875,6.5 -4.96875,8"
+ style="fill:none;stroke:#462300;stroke-width:3.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"
+ id="path46986"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path46988"
+ style="fill:none;stroke:#ffc17d;stroke-width:1.70000005;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 -28.53125,182.5 c -4.5,2 -4.96875,6 -4.96875,8"
+ 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>
+ </g>
+ <g
+ transform="translate(-1,0)"
+ id="g24914">
+ <g
+ id="g25430"
+ transform="translate(0,-21)">
+ <rect
+ ry="0"
+ rx="0"
+ transform="translate(1,0)"
+ y="514"
+ x="446"
+ height="16"
+ width="16"
+ id="rect25424"
+ style="opacity:0;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" />
+ <g
+ style="opacity:0.8;display:inline;enable-background:new"
+ id="g24916"
+ transform="translate(337,128)">
+ <rect
+ rx="0.019097222"
+ y="386"
+ x="110"
+ height="11"
+ width="11"
+ id="rect24918"
+ style="opacity:0;fill:#736c54;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ ry="0.019097222" />
+ <g
+ id="g24920">
+ <path
+ sodipodi:nodetypes="cccccccccccsccccccccccccccscccc"
+ style="fill:url(#linearGradient25449);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;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 116.53125,386.5 c -0.56312,0 -1.03125,0.46811 -1.03125,1.03125 l 0,0.9375 c 0,0.28156 0.12508,0.53133 0.3125,0.71875 L 113,392 c -0.18742,-0.18742 -0.46844,-0.5 -0.75,-0.5 l -0.75,0 c -0.56312,0 -1.03125,0.46811 -1.03125,1.03125 l 0,0.9375 c 0,0.56312 0.46813,1.03125 1.03125,1.03125 l 0.9375,0 c 0.0103,0 0.021,3e-4 0.0312,0 -3e-4,0.0102 0,0.021 0,0.0312 l 0,0.9375 c 0,0.56312 0.46813,1.03126 1.03125,1.03125 l 0.96875,0 c 0.56312,0 1,-0.46813 1,-1.03125 l 0,-0.9375 c 0,-0.28156 -0.10164,-0.53133 -0.28125,-0.71875 l 2.625,-2.625 c 0.18742,0.18742 0.43719,0.3125 0.71875,0.3125 l 0.96875,0 c 0.56312,0 1,-0.46813 1,-1.03125 l 0,-0.9375 c 0,-0.56312 -0.43688,-1.03125 -1,-1.03125 l -0.96875,0 c -0.0103,0 -0.021,-3e-4 -0.0312,0 3e-4,-0.0102 0,-0.021 0,-0.0312 l 0,-0.9375 c 0,-0.56312 -0.46813,-1.03125 -1.03125,-1.03125 l -0.9375,0 z"
+ id="path24923"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 111.5,393.5 0,-0.75 0.25,-0.25 1.75,0 3,-3 0,-1.75 0.25,-0.25 0.75,0"
+ id="path24925"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path24927"
+ d="m 118.75,389.5 0.75,0 m -6,6 0,-0.75"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="393"
+ x="114"
+ height="1"
+ width="1"
+ id="rect24929"
+ style="opacity:0.2;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" />
+ <rect
+ style="opacity:0.2;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"
+ id="rect24931"
+ width="1"
+ height="1"
+ x="117"
+ y="390" />
+ </g>
+ </g>
+ <g
+ transform="translate(22.915112,0.02875225)"
+ id="g24933">
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ style="fill:none;stroke:#000000;stroke-width:2.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 430.5,525.5329 0,2 1,1 2,0 2,-2.0329 0,-2 -1,-1 -2,0 -2,2.0329 z"
+ id="path24939"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path24941"
+ d="m 433.5,522.4671 0,1.75 1,1.25 2,0 2,-1.9671 0,-2 -1,-1 -2,0 -2,1.9671 z"
+ style="fill:none;stroke:#000000;stroke-width:2.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ style="fill:none;stroke:url(#linearGradient25451);stroke-width:1.29999995;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 433.5,522.4671 0,2.0329 1,0.9671 2,0 2,-1.9671 0,-2 -1,-1 -2,0 -2,1.9671 z"
+ id="path24945"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24954"
+ d="m 434.5,523.5 -2,0"
+ style="fill:none;stroke:#000000;stroke-width:2.70000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path24956"
+ d="m 430.5,525.5 0,2 1,1 2,0 2,-2 0,-2 -1,-1 -2,0 -2,2 z"
+ style="fill:none;stroke:url(#linearGradient25453);stroke-width:1.29999995;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:none;stroke:#000000;stroke-width:2.70000005;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 434.08489,525.47125 2.25,0"
+ id="path24958"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24960"
+ d="M 434.33489,525.47125 436.5,525.4671"
+ style="fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <rect
+ style="fill:url(#linearGradient40731);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect25426"
+ width="0"
+ height="0.25"
+ x="462.25"
+ y="515"
+ transform="translate(1,0)"
+ rx="1.3125"
+ ry="0.25" />
+ </g>
+ <g
+ transform="translate(0.00572791,126.98898)"
+ id="g25026">
+ <rect
+ y="403.99695"
+ x="-382.01102"
+ height="16"
+ width="16"
+ id="rect25028"
+ 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="matrix(0,-1,1,0,0,0)" />
+ <g
+ id="g25030">
+ <rect
+ transform="matrix(-0.7071068,0.7071068,-0.7071068,-0.7071068,0,0)"
+ rx="2.1489482"
+ ry="2.143424"
+ y="-559.32709"
+ x="-33.931175"
+ height="5.651536"
+ width="8.4518671"
+ id="rect25032"
+ 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:0.5" />
+ <rect
+ transform="matrix(-0.7071068,0.7071068,-0.7071068,-0.7071068,0,0)"
+ 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:0.5"
+ id="rect25034"
+ width="8.5198517"
+ height="5.5904222"
+ x="-28.308893"
+ y="-557.84644"
+ ry="2.1434233"
+ rx="2.1489475" />
+ <path
+ sodipodi:nodetypes="cssssc"
+ id="path25036"
+ d="m 411.49427,375.51102 -0.5,-0.5 c -0.69131,-0.69131 -0.84611,-2.14587 0.0258,-3.01533 l 2.98873,-2.98076 c 0.87178,-0.86946 2.29697,-0.69523 2.98828,-0.004 l 0.52541,0.52542"
+ style="fill:none;stroke:url(#linearGradient25117);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(-0.7071068,0.7071068,-0.7071068,-0.7071068,0,0)"
+ style="fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5"
+ d="m -26.159946,-552.25601 c -1.190517,0 -2.148947,-0.95597 -2.148947,-2.14343"
+ id="rect25114"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.7;fill:none;stroke:url(#radialGradient25457);stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 411.49427,375.51102 -0.5,-0.5 c -0.69131,-0.69131 -0.84611,-2.14587 0.0258,-3.01533 l 2.98873,-2.98076 c 0.87178,-0.86946 2.29697,-0.69523 2.98828,-0.004 l 0.52541,0.52542"
+ id="path25455"
+ sodipodi:nodetypes="cssssc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccczz"
+ d="m 407.51079,379.37902 c 0.56229,0.50812 1.81497,0.33519 2.49825,-0.3481 l 2.96969,-3.09463 c 0.87062,-0.87061 0.69197,-2.30021 0.004,-2.98827 l -1.02382,-1.02382 c -0.69131,-0.69131 -2.11766,-0.86672 -2.98828,0.004 l -2.96969,3.09462 c -0.87062,0.87063 -0.62293,2.42889 -0.004,2.98829 l 1.51384,1.368 10e-6,-9e-5 0,0 0,0 z"
+ style="fill:none;stroke:url(#linearGradient25106);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path25038"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path25040"
+ style="opacity:0.7;fill:none;stroke:url(#radialGradient25048);stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5"
+ d="m 407.4987,379.35912 c 0.56229,0.50812 1.81497,0.33519 2.49825,-0.3481 l 2.98178,-3.07473 c 0.87062,-0.87061 0.69197,-2.30021 0.004,-2.98827 l -1.02382,-1.02382 c -0.69131,-0.69131 -2.11766,-0.86672 -2.98828,0.004 l -2.98178,3.07472 c -0.87062,0.87063 -0.62293,2.42889 -0.004,2.98829 l 1.51384,1.368 10e-6,-9e-5 0,0 0,0 z"
+ sodipodi:nodetypes="ccccccczz"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(-0.7071068,0.7071068,-0.7071068,-0.7071068,0,0)"
+ style="fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5"
+ d="m -27.628256,-559.32709 c 1.190517,0 2.148948,0.95597 2.148948,2.14343"
+ id="rect25127"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient25117);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 417.50245,369.52434 0.49841,0.4984 c 0.68807,0.68805 0.86319,2.11415 -0.004,2.98828 l -2.96882,2.99286 c -0.68052,0.68603 -1.74799,0.71589 -2.49825,0.34809 -0.18628,-0.0913 -0.39866,-0.20409 -0.53552,-0.34095 l -1,-1"
+ id="path25042"
+ sodipodi:nodetypes="csssssc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g23496"
+ transform="matrix(-1,0,0,1,614,0)">
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ y="299"
+ x="52"
+ height="16"
+ width="16"
+ id="rect23456"
+ 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
+ id="g23458"
+ transform="matrix(0,1,1,0,203.99437,-269)">
+ <g
+ id="g23460">
+ <g
+ id="g23462"
+ transform="translate(0,21)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 327,76 0,10.00563 2,2 3,0 2,-2 0,-3.25"
+ id="path23464"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:3.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M 330.25,79.25563 327,76 l -3.25,3.25563"
+ id="path23466"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g23468"
+ transform="translate(0,21)">
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path23470"
+ d="m 327,76 0,10.00563 2,2 3,0 2,-2 0,-3"
+ style="fill:none;stroke:#dcdcdc;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path23473"
+ d="M 330.25,79.25563 327,76.005631 323.75,79.25563"
+ style="fill:none;stroke:#dcdcdc;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <path
+ sodipodi:nodetypes="cc"
+ id="path23475"
+ d="m 333.5,106.50563 0,-2.75"
+ 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"
+ inkscape:connector-curvature="0" />
+ <rect
+ transform="matrix(0,1,1,0,269,-203.99437)"
+ y="56"
+ x="303"
+ height="1"
+ width="1.5"
+ id="rect23492"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path23547"
+ d="m 330,100.50563 -1.25,-1.25"
+ style="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"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23494"
+ width="1.5"
+ height="1"
+ x="99.00563"
+ y="328"
+ transform="matrix(0,1,1,0,0,0)" />
+ <path
+ style="fill:none;stroke:url(#linearGradient23559);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 323.25,100.25563 c 0,0.25 0.25,0.5 0.5,0.5 m 2.75,-1.24437 0,7.74437 2.25,2.25 3.5,0 2,-2"
+ id="path23550"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path23552"
+ d="m 323.25,100.00563 3.5,-3.5 0.5,0 3.5,3.5"
+ style="fill:none;stroke:url(#linearGradient23557);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>
+ </g>
+ <g
+ id="g23511"
+ 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"
+ id="rect23513"
+ width="16"
+ height="16"
+ x="52"
+ y="299"
+ transform="matrix(0,1,1,0,0,0)" />
+ <g
+ transform="matrix(0,1,1,0,203.99437,-269)"
+ id="g23515">
+ <g
+ id="g23518">
+ <g
+ transform="translate(0,21)"
+ id="g23520">
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path23523"
+ d="m 327,76 0,10.00563 2,2 3,0 2,-2 0,-3.25"
+ style="fill:none;stroke:#000000;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path23525"
+ d="M 330.25,79.25563 327,76 l -3.25,3.25563"
+ style="fill:none;stroke:#000000;stroke-width:3.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(0,21)"
+ id="g23527">
+ <path
+ style="fill:none;stroke:#dcdcdc;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 327,76 0,10.00563 2,2 3,0 2,-2 0,-3"
+ id="path23530"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#dcdcdc;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 330.25,79.25563 327,76.005631 323.75,79.25563"
+ id="path23532"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <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;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 326.5,99.5 0,6.50563 m 3,2.5 2,0 2,-2 0,-2.75"
+ id="path23534"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient23543);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 323.25,100.00563 3.5,-3.499999 0.5,0 3.5,3.499999"
+ id="path23536"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23539"
+ width="1.5"
+ height="1"
+ x="303"
+ y="56"
+ transform="matrix(0,1,1,0,269,-203.99437)" />
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ y="328"
+ x="99.00563"
+ height="1"
+ width="1.5"
+ id="rect23541"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </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"
+ style="display:inline">
+ <rect
+ y="69"
+ x="62"
+ height="16"
+ width="16"
+ id="rect27864"
+ 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"
+ 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,0,0,1,461.01011,-167)"
+ id="g27866"
+ style="display:inline">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path27868"
+ d="m 392.5,239.5 -4.98989,4.75 0,0.5 4.98989,4.75 1.01011,-1e-5 0.0368,-9.96874 L 392.5,239.5 z"
+ style="fill:url(#linearGradient27872);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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path27870"
+ d="m 392.51011,248.24999 0,-7.49999 -4,3.75"
+ style="fill:none;stroke:url(#linearGradient27874);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="matrix(1,0,0,-1,70,704.00001)"
+ id="g27876"
+ style="display:inline">
+ <rect
+ y="69"
+ x="82"
+ height="16"
+ width="16"
+ id="rect27878"
+ 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"
+ 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="g27880"
+ transform="matrix(0,-1,1,0,-153.98989,467.9919)"
+ style="display:inline">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="color:#000000;fill:url(#linearGradient27886);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;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 392.49192,239.48989 -5.00001,4.75 0,0.5 5.00001,4.75 1,0 0,-10 -1,0 z"
+ id="path27882"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient27902);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 392.49191,248.23989 -4.00002,-3.75 4.00002,-3.75"
+ id="path27884"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(-231,-21)"
+ id="g29960"
+ 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">
+ <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="rect29962"
+ width="16"
+ height="16"
+ x="-336"
+ y="283"
+ transform="scale(-1,1)" />
+ <g
+ transform="translate(362,20.75)"
+ id="g29964"
+ mask="none"
+ clip-path="none">
+ <path
+ id="path29966"
+ d="m -35,273.5 0,-10.5 8,3.75 0,10.75 -8,-4 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#0b1728;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ 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" />
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ sodipodi:nodetypes="ccccc"
+ style="fill:url(#linearGradient29988);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m -35,273.5 0,-10.5 8,3.75 0,10.75 -8,-4 z"
+ id="path29968"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path29970"
+ d="m 334.5,287.75 -7,-3.25 0,9"
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient29990);stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <g
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ transform="matrix(0.6827482,0,0,0.68258425,246.77037,137.93793)"
+ id="g29972"
+ style="opacity:0.75;display:inline;enable-background:new"
+ mask="url(#mask29419)"
+ clip-path="url(#clipPath28964)">
+ <path
+ transform="matrix(0.75,0,0,0.75,28.052144,135)"
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#162d50;stroke-width:1.75781369;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path29974"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(-0.683022,-0.07745026,0.0778507,-0.683064,208.02475,314.325)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path29976"
+ style="color:#000000;fill:url(#linearGradient29773-5);fill-opacity:1;fill-rule:nonzero;stroke:none;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\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:type="arc"
+ style="opacity:0.65;fill:none;stroke:#ffffff;stroke-width:2.56764865;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:new"
+ id="path29978"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ transform="matrix(0.5705005,0,0,0.5705012,51.746079,156.18087)" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g29980"
+ transform="matrix(0.6827482,0,0,0.68258425,236.77037,141.93793)"
+ 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">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path29982"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.56250119;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.75,0,0,0.75,29.5,135)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient29994);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path29984"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path29986"
+ style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:2.56764865;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:new"
+ 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" />
+ </g>
+ </g>
+ <g
+ id="g29313"
+ transform="translate(-21,2)"
+ style="opacity:0.5">
+ <rect
+ y="176"
+ x="425"
+ height="16"
+ width="16"
+ id="rect29315"
+ 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="g29317"
+ transform="translate(263,148.99995)">
+ <g
+ transform="matrix(0.786268,0,0,0.7877987,82.392071,-41.848894)"
+ 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="g29320">
+ <path
+ transform="matrix(0.874026,0,0,0.873701,-3.948211,-5.552958)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path29323"
+ style="fill:url(#linearGradient29334);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.16319752;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(0.398744,0,0,-0.395524,58.82401,144.1804)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient29336);stroke-width:3.20095801;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path29326"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(0.186538,0,0,-0.189699,145.3693,57.36304)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient29338);stroke-width:5.31599474;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ id="path29328"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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" />
+ <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"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path29330"
+ style="fill:none;stroke:url(#linearGradient29340);stroke-width:1.77120221;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:type="arc"
+ transform="matrix(0.566689,0,0,-0.562497,95.23056,101.3747)" />
+ <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"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path29332"
+ style="fill:none;stroke:url(#linearGradient29342);stroke-width:2.35577321;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:type="arc"
+ 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">
+ <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>
+ </g>
+ <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>
+ </g>
+ <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 a 4.5,4.5 0 0 1 -4.509724,4.499989"
+ 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 a 4.5,4.5 0 0 1 -4.509724,4.499989"
+ 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 a 4.5,4.5 0 0 1 -4.509724,4.499989"
+ 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 a 4.5,4.5 0 0 1 -4.509724,4.499989"
+ 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>
+ </g>
+ </g>
+ <g
+ transform="translate(315,-441)"
+ id="g31816">
+ <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"
+ width="16"
+ height="16"
+ x="-247"
+ y="514" />
+ <g
+ transform="translate(0,-21)"
+ id="g31820">
+ <path
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:3.5999999;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 -245.25,538 12.5,0"
+ id="path31822"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path31824"
+ d="m -245.25,538 12.5,0"
+ style="color:#000000;fill:none;stroke:#d2d2d2;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m -245.5,538.5 -0.25,-0.5 0.25,-0.5 13,0"
+ id="path31826"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path31828"
+ d="m -242.5,543.5 0,-1 7,0"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m -239.5,548.5 0,-1 1,0"
+ id="path31830"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path31832"
+ d="m -242.25,543 6.5,0"
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:3.5999999;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="color:#000000;fill:none;stroke:#d2d2d2;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 -242.25,543 6.5,0"
+ id="path31834"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path31836"
+ d="m -242.5,543.5 -0.25,-0.5 0.25,-0.5 7,0"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:3.5999999;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 -239.25,548 0.5,0"
+ id="path31838"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path31840"
+ d="m -239.25,548 0.5,0"
+ style="color:#000000;fill:none;stroke:#d2d2d2;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m -239.5,548.5 -0.25,-0.5 0.25,-0.5 1,0"
+ id="path31844"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g31846"
+ 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"
+ inkscape:export-ydpi="90">
+ <rect
+ style="opacity:0;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect31848"
+ width="16"
+ height="16"
+ x="-186"
+ y="493" />
+ <path
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:3.5999999;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 -177.25,499 5.25,0 0,0.5 -5.03256,7.02015 0,0.5 L -171.75,507"
+ id="path31857"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path31859"
+ d="m -177.25,499 5.25,0 0,0.5 -5.03256,7.02015 0,0.5 L -171.75,507"
+ style="color:#000000;fill:none;stroke:url(#linearGradient31946);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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -175.25,506.5 3.75,0 m -6.5,-8 6.25,0 m -1.75,2 -4,5.75 0,1"
+ id="path31861"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter50168-9);enable-background:accumulate;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ d="m -183.4375,493.25 a 1.7525094,1.7525094 0 0 0 0.1875,3.5 l 1.875,0 0.125,0 c 0.30188,0 0.5,0.19814 0.5,0.5 l -2.25,0 a 1.750175,1.750175 0 0 0 -1.25,0.5 l -1,1 a 1.750175,1.750175 0 0 0 -0.5,1.25 l 0,2 a 1.750175,1.750175 0 0 0 0.5,1.25 l 1,1 a 1.750175,1.750175 0 0 0 1.25,0.5 l 2.5,0 a 1.750175,1.750175 0 0 0 1.25,-0.5 l 0.25,0.25 a 1.767767,1.767767 0 1 0 2.5,-2.5 l -0.75,-0.75 0,-1.9375 a 1.750175,1.750175 0 0 0 0,-0.5 1.750175,1.750175 0 0 0 0,-0.1875 l 0,-1.09375 a 1.750175,1.750175 0 0 0 0,-0.28125 1.750175,1.750175 0 0 0 -0.125,-0.6875 c -0.004,-0.0221 -0.0268,-0.0405 -0.0312,-0.0625 a 1.750175,1.750175 0 0 0 -0.0312,-0.0937 c -0.35614,-1.57819 -1.57955,-2.76466 -3.1875,-3.03125 a 1.750175,1.750175 0 0 0 -0.625,-0.125 l -0.1875,0 -1.8125,0 a 1.750175,1.750175 0 0 0 -0.1875,0 z m 1.1875,7.5 1.5,0 0,0.5 -1.5,0 0,-0.5 z"
+ id="path31869"
+ clip-path="url(#clipPath50172-0)"
+ mask="none"
+ transform="translate(-0.05279266,-2.0457936e-6)"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path31871"
+ transform="translate(-0.25906372,0.25457764)"
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:3.5999999;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 -180.99094,494.73636 c 1.24765,0 2.25907,1.01142 2.25907,2.25906 m -0.009,0 0,4.75 1.25,1.25 m -2.75,-0.25 -2.5,0 -1,-1 0,-2 1,-1 4,0 m -4.25,-4 2,0"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m -180.99094,494.73636 c 1.24765,0 2.25907,1.01142 2.25907,2.25906 m -0.009,0 0,4.75 1.25,1.25 m -2.75,-0.25 -2.5,0 -1,-1 0,-2 1,-1 4,0 m -4.25,-4 2,0"
+ style="color:#000000;fill:none;stroke:url(#linearGradient31948);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"
+ transform="translate(-0.25906372,0.25457764)"
+ id="path31873"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path31875"
+ d="m -179.5,495.25 -1.25,-0.75 -2.75,0 -0.25,0.5 0.24997,0.5"
+ style="fill:none;stroke:#ffffff;stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path31879"
+ d="m -184.5,502 0,-2.25 1.25,-1.25 3.25,0"
+ style="fill:none;stroke:#ffffff;stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path31881"
+ d="m -182.25,502.5 2,0 0.75,-0.75 0,-1"
+ style="fill:none;stroke:#ffffff;stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g31883"
+ transform="translate(189,-315)">
+ <g
+ style="opacity:0.96000001;display:inline;enable-background:new"
+ id="g31885"
+ transform="translate(-307.59866,-9.53021)">
+ <g
+ id="g31887"
+ transform="translate(2.6147747,150.03012)"
+ 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="g31889">
+ <rect
+ transform="translate(-2.6147747,-150.03012)"
+ y="397.53015"
+ x="165.59866"
+ height="16"
+ width="16"
+ id="rect31891"
+ 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="247.5"
+ x="162.99997"
+ height="16"
+ width="15.000031"
+ id="rect31893"
+ style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" />
+ <path
+ d="m 167.48389,249.00007 0,2 m 6,-2 0,2"
+ style="fill:none;stroke:#162d50;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path31896"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:url(#linearGradient31950);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect31898"
+ width="11.999973"
+ height="13.000053"
+ x="164.48389"
+ y="250.00002"
+ rx="1.0000547"
+ ry="1.0000547" />
+ <path
+ sodipodi:nodetypes="cc"
+ d="m 165.48389,262.00007 0,-11"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ id="path31900"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path31902"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient31952);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 175.48389,251.00007 0,11 -10,0 0,-11 10,0 z"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(346.98389,-98.49991)"
+ style="color:#000000;fill:url(#linearGradient31954);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 -181.5,348.96875 c -0.0977,0 -0.2593,0.0405 -0.375,0.15625 -0.1157,0.1157 -0.15625,0.27731 -0.15625,0.375 l 0,7 2.53125,2.53125 10.53125,0 0,-1.15625 c -1.11643,-0.22954 -2,-1.19538 -2,-2.375 l 0,-6 c 0,-0.0977 -0.0405,-0.2593 -0.15625,-0.375 -0.1157,-0.1157 -0.27731,-0.15625 -0.375,-0.15625 l -10,0 z"
+ id="path31905"
+ sodipodi:nodetypes="cscccccccscc"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(346.98389,-98.49991)"
+ style="color:#000000;fill:none;stroke:url(#linearGradient31956);stroke-width:1px;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 -181.5,349.5 0,6.75 2.25,2.25 9.7813,0.0312 -0.0313,-0.2812 c -1.11143,-0.43566 -2,-1.49177 -2,-2.75 l 0.0313,-6.00005 -10.0313,5e-5 z"
+ id="path31907"
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="color:#000000;fill:url(#linearGradient31958);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.4000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect31909"
+ width="11.000002"
+ height="4.0000105"
+ x="164.98389"
+ y="250.50008"
+ rx="0"
+ ry="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ d="m 165.48389,254.50007 0,-3.5 10,0 0,3.5"
+ style="opacity:0.45;fill:none;stroke:url(#linearGradient31960);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ id="path31912"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path31914"
+ style="opacity:0.8;fill:none;stroke:#162d50;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 167.48389,249.00007 0,2 m 6,-2 0,2"
+ inkscape:connector-curvature="0" />
+ <path
+ style="color:#000000;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;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -181.5,348.5 c -0.13851,0 -0.25527,0.0433 -0.375,0.0937 -0.23945,0.10094 -0.43031,0.2918 -0.53125,0.53125 -0.0505,0.11973 -0.0937,0.23649 -0.0937,0.375 l 0,7 0,4 c 0,0.55403 0.44597,1 1,1 l 10,0 c 0.55403,0 1,-0.44597 1,-1 l 0,-1 2,0 0,-2 c -1.09489,0 -2,-0.90511 -2,-2 l 0,-6 c 0,-0.125 -0.0391,-0.25781 -0.0937,-0.375 -0.10094,-0.23945 -0.2918,-0.43031 -0.53125,-0.53125 -0.11973,-0.0505 -0.23649,-0.0937 -0.375,-0.0937 l -10,0 z"
+ transform="translate(346.98389,-98.49991)"
+ id="path31917"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path31919"
+ style="fill:none;stroke:url(#linearGradient31962);stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 167.48389,249.00007 0,2 m 6,-2 0,2"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.3;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m -200.5,372.5 0.75,0 1.25,-1.25 0,-0.75"
+ id="path31921"
+ transform="translate(367.98389,-119.49993)"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path31923"
+ d="m 173.48389,253.00007 0.75,0 1.25,-1.25 0,-0.75"
+ style="opacity:0.3;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path31925"
+ d="m 167.48389,252.00007 0.5,0 0.5,-0.5 0,-0.5"
+ style="opacity:0.7;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.7;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 173.48389,252.00007 0.5,0 0.5,-0.5 0,-0.5"
+ id="path31927"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.25;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 165.48389,254.00007 10,0"
+ id="path31929"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path31931"
+ d="m -170.5,359.5 c -3.30603,0.005 -5.7501,0 -9,0 l -1.75,-1.75"
+ style="opacity:0.5;color:#000000;fill:none;stroke:#000000;stroke-width:0.89999998;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="translate(346.98389,-98.49991)"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="csc"
+ style="color:#000000;fill:none;stroke:#000000;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 170.48389,259.00009 c -0.25,0 -0.64081,-0.31307 -0.82432,-0.78241 -0.17644,-0.45125 -0.17568,-0.96756 -0.17568,-2.21759"
+ id="path31933"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path31935"
+ d="m 173.48389,259.00009 c -0.25,0 -0.64081,-0.31307 -0.82432,-0.78241 -0.17644,-0.45125 -0.17568,-0.96756 -0.17568,-2.21759"
+ style="color:#000000;fill:none;stroke:#000000;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"
+ sodipodi:nodetypes="csc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <rect
+ ry="0"
+ rx="0"
+ y="396"
+ x="-136"
+ height="1"
+ width="1"
+ id="rect31937"
+ style="color:#000000;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" />
+ <rect
+ style="color:#000000;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"
+ id="rect31939"
+ width="1"
+ height="1"
+ x="-133"
+ y="396"
+ rx="0"
+ ry="0" />
+ <rect
+ y="398.25"
+ x="-136"
+ height="0.7500025"
+ width="0.50001091"
+ id="rect31941"
+ style="opacity:0.7;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.7;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect31943"
+ width="0.50001091"
+ height="0.7500025"
+ x="-133.00002"
+ y="398.25" />
+ </g>
+ <g
+ 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\screw modifier.png"
+ transform="translate(-105,-42)"
+ id="g31976">
+ <rect
+ y="283"
+ x="236"
+ height="16"
+ width="16"
+ id="rect31978"
+ 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" />
+ <path
+ sodipodi:nodetypes="cccccccccccc"
+ id="path31980"
+ d="m 244,283.5 c -3.49999,0 -5.5,1 -5.49999,2.5 l -1e-5,1.75 3,3 0,6.5 1.25,1.25 2.5,0 1.25,-1.25 0,-6.5 3,-3 0,-1.75 c 0,-1.5 -1.99999,-2.5 -5.5,-2.5 z"
+ style="color:#000000;fill:url(#linearGradient32236);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="color:#000000;fill:url(#linearGradient32238);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 244,287.5 c -3.49999,0 -5.5,-1 -5.49999,-2.5 l -1e-5,2.75 3,3 5,0 3,-3 0,-2.75 c 0,1.5 -1.99999,2.5 -5.5,2.5 z"
+ id="path31982"
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czs"
+ id="path31985"
+ d="m 248.99999,286.24149 c 0,1.12925 -1.66739,2.25851 -5.01168,2.25851 -3.34426,0 -4.99267,-1.12926 -4.99267,-2.25851"
+ style="fill:none;stroke:url(#linearGradient32240);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
+ 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:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 246.5,290.75 3,-3 0,-1.75 c 0,-1.5 -1.99999,-2.5 -5.5,-2.5 -3.49999,0 -5.5,1 -5.49999,2.5 l -1e-5,1.75 3,3"
+ id="path31989"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#89a9d9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.29137695;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 249,285.86765 c 0,0.99654 -1.81092,1.88235 -5,1.88235 -3.18906,0 -5,-0.88581 -5,-1.88235 0,-1.36765 2.61499,-2.11765 5,-2.11765 2.38501,0 5,0.75 5,2.11765 z"
+ id="path31991"
+ sodipodi:nodetypes="czszs"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path31993"
+ d="m 239.5,287.5 3,3"
+ style="opacity:0.7;color:#000000;fill:none;stroke:url(#linearGradient32242);stroke-width:0.99999994;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path31996"
+ d="m 241.5,290.75 0,6.5 1.25,1.25 2.5,0 1.25,-1.25 0,-6.5"
+ 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;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ style="color:#000000;fill:none;stroke:url(#linearGradient32244);stroke-width:0.99999994;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 242.5,291 0,5.75 0.75,0.75 1.5,0 0.75,-0.75 0,-6.25 3,-3"
+ id="path31998"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="color:#000000;fill:url(#linearGradient32246);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 242.5,291 c -0.277,0 -0.5,0.223 -0.5,0.5 0,0.277 0.223,0.5 0.5,0.5 l 3,0 c 0.277,0 0.5,-0.223 0.5,-0.5 0,-0.277 -0.223,-0.5 -0.5,-0.5 l -3,0 z m 0,2 c -0.277,0 -0.5,0.223 -0.5,0.5 0,0.277 0.223,0.5 0.5,0.5 l 3,0 c 0.277,0 0.5,-0.223 0.5,-0.5 0,-0.277 -0.223,-0.5 -0.5,-0.5 l -3,0 z m 0,2 c -0.277,0 -0.5,0.223 -0.5,0.5 0,0.277 0.223,0.5 0.5,0.5 l 3,0 c 0.277,0 0.5,-0.223 0.5,-0.5 0,-0.277 -0.223,-0.5 -0.5,-0.5 l -3,0 z m 0.75,2 c -0.277,0 -0.5,0.223 -0.5,0.5 0,0.277 0.223,0.5 0.5,0.5 l 1.5,0 c 0.277,0 0.5,-0.223 0.5,-0.5 0,-0.277 -0.223,-0.5 -0.5,-0.5 l -1.5,0 z"
+ id="path32000"
+ inkscape:connector-curvature="0" />
+ <path
+ style="color:#000000;fill:url(#linearGradient32248);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 242.5,292 c -0.277,0 -0.5,0.223 -0.5,0.5 0,0.277 0.223,0.5 0.5,0.5 l 2.75,0 c 0.277,0 0.5,-0.223 0.5,-0.5 0,-0.277 -0.223,-0.5 -0.5,-0.5 l -2.75,0 z m 0,2 c -0.277,0 -0.5,0.223 -0.5,0.5 0,0.277 0.223,0.5 0.5,0.5 l 2.75,0 c 0.277,0 0.5,-0.223 0.5,-0.5 0,-0.277 -0.223,-0.5 -0.5,-0.5 l -2.75,0 z m 0,2 c -0.277,0 -0.5,0.223 -0.5,0.5 0,0.277 0.223,0.5 0.5,0.5 l 2.75,0 c 0.277,0 0.5,-0.223 0.5,-0.5 0,-0.277 -0.223,-0.5 -0.5,-0.5 l -2.75,0 z"
+ id="path32002"
+ sodipodi:nodetypes="csccscccsccscccsccscc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M 242.47368,287.53915 246,284"
+ id="path32004"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path32006"
+ d="m 243.5,287.5 3,-3"
+ style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ 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"
+ transform="translate(147,0)">
+ <g
+ style="display:inline;enable-background:new"
+ transform="translate(-240,-247)"
+ id="g32262"
+ 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"
+ mask="url(#mask29801)">
+ <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="rect32264"
+ width="16"
+ height="16"
+ x="203"
+ y="257" />
+ <g
+ style="display:inline;enable-background:new"
+ 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="g32266"
+ transform="translate(-39.983882,19.00809)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 244.51612,238.49191 -0.0161,3 7.98388,0 0.0161,-3 -7.98388,0 z"
+ id="path32269"
+ 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
+ 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="path32276"
+ d="m 247.51612,241.49191 -0.0161,3 11,0 0.0161,-3 -11,0 z"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;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="ccccc"
+ 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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ id="path32278"
+ d="m 249.48388,247.49191 -0.0161,3 7.01612,0 0.0161,-3 -7.01612,0 z"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.69999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="fill:none;stroke:url(#linearGradient32296);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 205.51612,259.5 c 0,-0.25 0,-1 0,-1 l 6,0"
+ id="path32280"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path32282"
+ d="m 208.51612,262.5 c 0,-0.25 0,-1 0,-1 l 9,0"
+ style="fill:none;stroke:url(#linearGradient32299);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path32284"
+ d="m 210.5,268.5 c 0,-0.25 0,-1 0,-1 l 5,0"
+ style="fill:none;stroke:url(#linearGradient32301);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g32286"
+ transform="translate(-85,-411)">
+ <rect
+ y="427.5"
+ x="48.5"
+ height="9"
+ width="9"
+ id="rect32288"
+ style="fill:#ececec;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(#linearGradient32303);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00207269;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect32290"
+ width="5.9999886"
+ height="6"
+ x="50.000011"
+ y="429" />
+ <path
+ sodipodi:nodetypes="ccccccccccccccccccccccccc"
+ id="path32292"
+ d="m 50,429 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,2 -2,0 0,2 2,0 0,-2 z m -4,2 0,-2 -2,0 0,2 2,0 z"
+ style="fill:url(#linearGradient32305);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" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path32294"
+ d="m 56.50001,428.49999 -7.000011,10e-6 1.1e-5,6.99999 7,0 -1.1e-5,-6.99999"
+ style="fill:none;stroke:url(#linearGradient32307);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ 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\mysterious PR.png"
+ transform="translate(-118,-465)"
+ id="g32309">
+ <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"
+ width="16"
+ height="16"
+ x="312"
+ y="685" />
+ <g
+ id="g32313">
+ <g
+ style="opacity:0.96000001;display:inline"
+ id="g32315"
+ transform="matrix(0.927848,0,0,0.916217,160.82022,488.72362)"
+ 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\Kopia blender\.blender\icons\blender's iconset.png"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path32317"
+ style="fill:url(#linearGradient32353);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.22752953;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.87787,0,0,0.889264,55.67911,118.0341)" />
+ </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"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path32319"
+ style="opacity:0.96000001;fill:none;stroke:url(#linearGradient32355);stroke-width:1.44816053;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.68828432,0,0,0.69278557,229.1626,611.24321)" />
+ <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="path32321"
+ style="opacity:0.96000001;fill:none;stroke:#ffffff;stroke-width:2.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 322.5,689.5 -3,3 m 0,1 2,2"
+ 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"
+ sodipodi:nodetypes="cc"
+ d="m 319.5,693.5 2,2"
+ style="opacity:0.96000001;fill:none;stroke:#aa0000;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path32323"
+ inkscape:transform-center-y="1.25"
+ inkscape:transform-center-x="-1.25"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="697"
+ x="320"
+ height="1.5"
+ width="1"
+ id="rect32325"
+ style="opacity:0.48000004;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="692"
+ x="324"
+ height="1"
+ width="1.5"
+ id="rect32327"
+ style="opacity:0.48000004;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ style="opacity:0.96000001;fill:url(#linearGradient32357);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 319.85514,686.97535 c -3.25557,0.003 -5.8936,2.6597 -5.87155,5.95078 0.0105,1.56055 0.63214,2.99542 1.61111,4.05762 2.7831,-7.37691 5.95805,-1.77373 7.49116,-9.06794 -0.92886,-0.60835 -2.04538,-0.9415 -3.23072,-0.94046 l 0,0 0,0 0,0 z"
+ id="path32329"
+ inkscape:transform-center-x="1.4653436"
+ inkscape:transform-center-y="-1.0204512"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:transform-center-y="-2.5000099"
+ inkscape:transform-center-x="-3.00001"
+ id="path32331"
+ d="m 319.93245,687.49998 c -0.13655,0 -0.28922,0.0368 -0.43244,0.0521 l 0,4.94792 6,0 c -0.22415,-2.79556 -2.6077,-5 -5.56756,-5 z"
+ style="color:#000000;fill:#ff9e05;fill-opacity:1;fill-rule:evenodd;stroke:#d68c1a;stroke-width:1;stroke-linejoin:round;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.28800001;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect32333"
+ width="1.4999696"
+ height="1"
+ x="314.51614"
+ y="693" />
+ <rect
+ style="opacity:0.15;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect32335"
+ width="1"
+ height="1.4999921"
+ x="319"
+ y="687.5" />
+ <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"
+ d="m 324.5,692.5 -5,0"
+ style="opacity:0.8;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path32349"
+ inkscape:transform-center-y="-0.75"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(0.68828432,0,0,0.69278557,229.1626,611.24321)"
+ sodipodi:type="arc"
+ style="opacity:0.6;fill:none;stroke:url(#linearGradient32359);stroke-width:1.44816053;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path32351"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ 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\recently used.png"
+ transform="translate(32,-86.95)"
+ id="g32361">
+ <rect
+ y="664"
+ x="414"
+ height="16"
+ width="16"
+ id="rect32363"
+ 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="g32365">
+ <g
+ style="opacity:0.8"
+ id="g32367"
+ transform="translate(23,1)">
+ <g
+ style="opacity:0.96000001;display:inline"
+ id="g32369"
+ transform="matrix(0.927848,0,0,0.916217,240.82022,467.72362)"
+ 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\Kopia blender\.blender\icons\blender's iconset.png"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path32371"
+ style="fill:url(#linearGradient32426);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.19779229;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.80941061,0,0,0.82049866,65.263425,126.69853)" />
+ </g>
+ <g
+ 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(0.784039,0,0,0.779055,265.50801,498.28815)"
+ id="g32373"
+ style="opacity:0.96000001;fill:none;stroke:url(#linearGradient32430);stroke-width:1.17973554;stroke-opacity:1;display:inline">
+ <path
+ transform="matrix(0.79894049,0,0,0.80499668,66.729242,128.65178)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient32428);stroke-width:1.59548569;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path32375"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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: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="path32377"
+ style="opacity:0.96000001;fill:none;stroke:#ffffff;stroke-width:2.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 400.5,668.5 0,4 m 0,0 2,2"
+ 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"
+ sodipodi:nodetypes="cc"
+ d="m 400.5,672.5 2,2"
+ style="opacity:0.96000001;fill:none;stroke:#aa0000;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path32380"
+ inkscape:transform-center-y="1.25"
+ inkscape:transform-center-x="-1.25"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="676"
+ x="400"
+ height="2.5"
+ width="1"
+ id="rect32382"
+ style="opacity:0.48000004;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="672"
+ x="404"
+ height="1"
+ width="2.5"
+ id="rect32384"
+ style="opacity:0.15;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:transform-center-y="-0.75"
+ id="path32387"
+ style="opacity:0.96000001;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 400.5,668.5 0,4"
+ 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:url(#linearGradient32432);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 400.30467,667.25 c -2.80257,0.003 -5.07354,2.32096 -5.05455,5.19291 0.009,1.36179 0.54419,2.61392 1.38693,3.54084 2.39585,-6.4374 5.12903,-1.54783 6.44881,-7.91306 -0.79962,-0.53087 -1.76077,-0.82159 -2.78119,-0.82069 l 0,0 0,0 0,0 z"
+ id="path32389"
+ inkscape:transform-center-x="1.2614492"
+ inkscape:transform-center-y="-0.89049022"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.28800001;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect32391"
+ width="2.4838562"
+ height="1"
+ x="394.51614"
+ y="672" />
+ <rect
+ style="opacity:0.28800001;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect32393"
+ width="1"
+ height="1.4999921"
+ x="400"
+ y="666.5" />
+ <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"
+ d="m 400.5,668.5 0,4"
+ style="opacity:0.57600002;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path32396"
+ inkscape:transform-center-y="-0.75"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g32398">
+ <g
+ transform="matrix(1,0,0,-1,73,774)"
+ id="g32400">
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path32403"
+ d="m 343,108.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#0b1e00;stroke-width:3.5999999;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>
+ <path
+ style="color:#000000;fill:none;stroke:#0b1e00;stroke-width:3.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 428,671.25 c -0.0541,-1.25729 -0.54273,-2.44429 -1.37516,-3.38809 -2.00926,-2.27808 -5.59675,-2.62117 -7.87484,-0.61191 L 417,669"
+ id="path32411"
+ sodipodi:nodetypes="csc"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(1,0,0,-1,73,774)"
+ id="g32413">
+ <path
+ style="fill:none;stroke:#8af01e;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 343,108.25 0,-4.25 4.25,0"
+ id="path32416"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path32418"
+ d="m 417,669 0,-1 0,-1.5 1,0 0,1.5 1.5,0 0,1 -1.5,0 -1,0 z"
+ style="opacity:0.15;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="csc"
+ id="path32420"
+ d="m 428,671.25 c -0.0541,-1.25729 -0.54273,-2.44429 -1.37516,-3.38809 -2.00926,-2.27808 -5.59675,-2.62117 -7.87484,-0.61191 L 417,669"
+ style="color:#000000;fill:none;stroke:#8af01e;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.4;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 415.5,670 0,-4.5 m 5,4 -2,0"
+ id="path32422"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cscccc"
+ id="path32424"
+ d="m 428.5,671.21875 c -0.0591,-1.37274 -0.59591,-2.66246 -1.5,-3.6875 -1.09228,-1.23842 -2.62571,-1.96363 -4.1875,-2.09375 -1.55879,-0.12987 -3.16135,0.33951 -4.40625,1.4375 -3.3e-4,0.0104 -3.3e-4,0.0208 0,0.0312 L 417.5,667.75"
+ style="opacity:0.4;color:#000000;fill:none;stroke:url(#linearGradient32434);stroke-width:1.10000002;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>
+ </g>
+ </g>
+ <g
+ transform="translate(0,2)"
+ id="g31005">
+ <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"
+ width="16"
+ height="16"
+ x="425"
+ y="218" />
+ <g
+ style="display:inline"
+ id="g31009"
+ transform="translate(43.016148,98.00001)">
+ <g
+ transform="translate(-3.542969e-5,0)"
+ id="g31011"
+ style="display:inline">
+ <path
+ d="M 388.23389,129.74999 394.5,123.5 m 0.98389,1.99999 L 394,124 m 0.48389,2.49999 -1.4142,-1.41422"
+ style="fill:none;stroke:#000000;stroke-width:3.00000095;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path31013"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="csssc"
+ id="path31021"
+ style="fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ d="m 388.04706,129.93681 c 0.81353,0.81353 0.81353,2.31284 0,3.12634 -0.81352,0.81354 -2.31283,0.81354 -3.12635,0 -0.81353,-0.8135 -0.81353,-2.31281 0,-3.12634 0.81352,-0.81352 2.31283,-0.81352 3.12635,0 z"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path31015"
+ style="fill:none;stroke:url(#linearGradient31019);stroke-width:1.50000191;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000034;display:inline"
+ d="M 388.73389,129.24999 394.5,123.5 m 0.98389,1.99999 -0.25,-0.25 m -0.75,1.25 -0.25,-0.25"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czzzz"
+ d="m 388.01764,129.96629 c 0.79818,0.79819 0.79818,2.26923 0,3.06743 -0.7982,0.79819 -2.26925,0.79819 -3.06743,0 -0.79821,-0.7982 -0.79821,-2.26924 0,-3.06743 0.79818,-0.7982 2.26923,-0.7982 3.06743,0 z"
+ style="fill:none;stroke:url(#linearGradient31025);stroke-width:1.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path31023"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ transform="matrix(1.4399775,0,0,1.4399775,-171.50748,-44.947546)"
+ d="m 388.20316,122.5078 a 0.70312506,0.71093756 0 1 1 -1.40625,0 0.70312506,0.71093756 0 1 1 1.40625,0 z"
+ sodipodi:ry="0.71093756"
+ sodipodi:rx="0.70312506"
+ sodipodi:cy="122.5078"
+ sodipodi:cx="387.50003"
+ id="path31017"
+ style="opacity:0.3;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc" />
+ </g>
+ </g>
+ <g
+ id="g31159">
+ <g
+ style="opacity:0.8"
+ transform="translate(-21,2)"
+ id="g31037">
+ <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="rect31039"
+ width="16"
+ height="16"
+ x="425"
+ y="218" />
+ <g
+ style="display:inline"
+ id="g31041"
+ transform="translate(43.016148,98.00001)">
+ <g
+ transform="translate(-3.542969e-5,0)"
+ id="g31043"
+ style="display:inline">
+ <path
+ d="M 388.23389,129.74999 394.5,123.5 m 0.98389,1.99999 L 394,124 m 0.48389,2.49999 -1.4142,-1.41422"
+ style="fill:none;stroke:#000000;stroke-width:3.00000095;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path31045"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="csssc"
+ id="path31047"
+ style="fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ d="m 388.04706,129.93681 c 0.81353,0.81353 0.81353,2.31284 0,3.12634 -0.81352,0.81354 -2.31283,0.81354 -3.12635,0 -0.81353,-0.8135 -0.81353,-2.31281 0,-3.12634 0.81352,-0.81352 2.31283,-0.81352 3.12635,0 z"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path31049"
+ style="fill:none;stroke:url(#linearGradient31055);stroke-width:1.50000191;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000034;display:inline"
+ d="M 388.73389,129.24999 394.5,123.5 m 0.98389,1.99999 -0.25,-0.25 m -0.75,1.25 -0.25,-0.25"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="czzzz"
+ d="m 388.01764,129.96629 c 0.79818,0.79819 0.79818,2.26923 0,3.06743 -0.7982,0.79819 -2.26925,0.79819 -3.06743,0 -0.79821,-0.7982 -0.79821,-2.26924 0,-3.06743 0.79818,-0.7982 2.26923,-0.7982 3.06743,0 z"
+ style="fill:none;stroke:url(#linearGradient31057);stroke-width:1.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path31051"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ transform="matrix(1.4399775,0,0,1.4399775,-171.50748,-44.947546)"
+ d="m 388.20316,122.5078 a 0.70312506,0.71093756 0 1 1 -1.40625,0 0.70312506,0.71093756 0 1 1 1.40625,0 z"
+ sodipodi:ry="0.71093756"
+ sodipodi:rx="0.70312506"
+ sodipodi:cy="122.5078"
+ sodipodi:cx="387.50003"
+ id="path31053"
+ style="opacity:0.3;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc" />
+ </g>
+ </g>
+ <g
+ id="g31031"
+ transform="matrix(0,1,-1,0,636.39781,-199.65488)">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path31033"
+ d="m 422.15488,229.89781 11,-11"
+ style="opacity:0.5;fill:#000000;fill-rule:evenodd;stroke:#2b0000;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ff5555;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 422.15488,229.89781 11,-11"
+ id="path31035"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g31133"
+ transform="translate(0,-21)">
+ <rect
+ y="241"
+ x="383"
+ height="16"
+ width="16"
+ id="rect31089"
+ 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(3.016145,122.00001)"
+ id="g31091"
+ style="display:inline">
+ <g
+ style="display:inline"
+ id="g31093"
+ transform="translate(-3.542969e-5,0)">
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path31095"
+ style="fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ d="m 388.23389,129.74999 5.25,-5.25 m 0.98389,1.99999 -1.48389,-1.49999 m 0.48389,2.49999 -1.4142,-1.41422"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 388.04706,129.93681 c 0.81353,0.81353 0.81353,2.31284 0,3.12634 -0.81352,0.81354 -2.31283,0.81354 -3.12635,0 -0.81353,-0.8135 -0.81353,-2.31281 0,-3.12634 0.81352,-0.81352 2.31283,-0.81352 3.12635,0 z"
+ style="fill:none;stroke:#000000;stroke-width:2.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path31097"
+ sodipodi:nodetypes="csssc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ d="m 388.73389,129.24999 4.75,-4.75 m 0.98389,1.99999 -0.25,-0.25 m -0.75,1.25 -0.25,-0.25"
+ style="fill:none;stroke:url(#linearGradient31151);stroke-width:1.50000191;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000034;display:inline"
+ id="path31099"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path31101"
+ style="fill:none;stroke:url(#linearGradient31153);stroke-width:1.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ d="m 388.01764,129.96629 c 0.79818,0.79819 0.79818,2.26923 0,3.06743 -0.7982,0.79819 -2.26925,0.79819 -3.06743,0 -0.79821,-0.7982 -0.79821,-2.26924 0,-3.06743 0.79818,-0.7982 2.26923,-0.7982 3.06743,0 z"
+ sodipodi:nodetypes="czzzz"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.05;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path31103"
+ sodipodi:cx="387.50003"
+ sodipodi:cy="122.5078"
+ sodipodi:rx="0.70312506"
+ sodipodi:ry="0.71093756"
+ d="m 388.20316,122.5078 a 0.70312506,0.71093756 0 1 1 -1.40625,0 0.70312506,0.71093756 0 1 1 1.40625,0 z"
+ transform="matrix(1.4399775,0,0,1.4399775,-171.50748,-44.947546)" />
+ </g>
+ <path
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;opacity:0.3;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.4000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ d="m 389.5,229.65625 c -0.73878,0 -1.48012,0.26136 -2.03125,0.8125 -1.10229,1.10226 -1.10228,2.96023 0,4.0625 0.41335,0.41335 0.92256,0.67791 1.46875,0.78125 0.008,-0.004 0.0231,0.004 0.0312,0 0.76739,-0.40457 1.35785,-1.08414 1.65625,-1.90625 -0.0307,0.0416 -0.0579,0.0891 -0.0937,0.125 -0.49413,0.49412 -1.5684,0.49411 -2.0625,0 -0.49414,-0.49413 -0.49413,-1.56838 0,-2.0625 0.24705,-0.24706 0.63541,-0.375 1.03125,-0.375 0.39584,0 0.78419,0.12794 1.03125,0.375 0.12353,0.12353 0.21949,0.29083 0.28125,0.46875 -0.0858,-0.9079 -0.52654,-1.71591 -1.1875,-2.28125 -0.0405,-0.002 -0.0845,0 -0.125,0 z m -2.125,1.9375 c 0.37998,0 0.65625,0.27629 0.65625,0.65625 0,0.37998 -0.27627,0.6875 -0.65625,0.6875 -0.37092,0 -0.64331,-0.29002 -0.65625,-0.65625 0,-0.009 -3.2e-4,-0.0223 0,-0.0312 0.0129,-0.3662 0.28534,-0.65625 0.65625,-0.65625 z"
+ transform="translate(0,21)"
+ id="path31190"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g31059"
+ transform="translate(-42,23)">
+ <g
+ style="display:inline"
+ id="g31073"
+ transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,60.12783,410.54412)">
+ <g
+ id="g31075"
+ transform="translate(2.016112,1.00001)">
+ <path
+ d="m 388.60119,129.3396 4.94975,-4.94974 m 1.41421,1.41421 -1.23743,-1.23743 m 0.53033,1.94454 -1.23742,-1.23744"
+ style="fill:none;stroke:#100d04;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path31077"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="csssc"
+ id="path31113"
+ style="fill:none;stroke:#100d04;stroke-width:2.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ d="m 387.93695,130.00385 c 0.8043,0.80431 0.8043,2.10984 0,2.91414 -0.8043,0.80431 -2.10984,0.80431 -2.91414,0 -0.8043,-0.8043 -0.8043,-2.10983 0,-2.91414 0.8043,-0.80428 2.10984,-0.80428 2.91414,0 z"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path31079"
+ style="fill:none;stroke:url(#linearGradient31155);stroke-width:1.50000191;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000034;display:inline"
+ d="m 388.60119,129.3396 4.94975,-4.94974 m 1.41421,1.41421 -0.25,-0.25 m -0.4571,0.95711 -0.25,-0.25"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.05;fill:#181406;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path31081"
+ sodipodi:cx="387.50003"
+ sodipodi:cy="122.5078"
+ sodipodi:rx="0.70312506"
+ sodipodi:ry="0.71093756"
+ d="m 388.20316,122.5078 a 0.70312506,0.71093756 0 1 1 -1.40625,0 0.70312506,0.71093756 0 1 1 1.40625,0 z"
+ transform="matrix(1.7719122,0,0,1.7719122,-300.13217,-85.612134)" />
+ <path
+ sodipodi:nodetypes="czzzz"
+ d="m 387.96588,129.97488 c 0.82029,0.8203 0.82029,2.15177 0,2.97206 -0.8203,0.82029 -2.15179,0.82029 -2.97206,0 -0.8203,-0.82029 -0.8203,-2.15176 0,-2.97206 0.82027,-0.82029 2.15176,-0.82029 2.97206,0 z"
+ style="fill:none;stroke:url(#linearGradient31157);stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.40000034;display:inline"
+ id="path31109"
+ inkscape:connector-curvature="0" />
+ </g>
+ </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"
+ transform="translate(448,657)">
+ <rect
+ y="-122"
+ x="-44"
+ height="16"
+ width="16"
+ id="rect40445-4-2"
+ style="opacity:0.01000001;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path40447-5-3"
+ d="m -43.5,-116.75 12.5,-4.75 0.75,2 -13.25,5 0,-2.25 z"
+ style="fill:#1a1a1a;stroke:#000000;stroke-width:0.89999998;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="-114.5"
+ x="-42.5"
+ height="7.9999971"
+ width="12.999988"
+ id="rect40449-5-9"
+ style="fill:url(#linearGradient16887);fill-opacity:1;fill-rule:nonzero;stroke:#000000;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" />
+ <rect
+ style="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"
+ id="rect40451-1-1"
+ width="1"
+ height="1.5"
+ x="-32"
+ y="-121" />
+ <rect
+ y="-119.41868"
+ x="-36"
+ height="1.5"
+ width="1"
+ id="rect40453-7-7"
+ style="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" />
+ <rect
+ style="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"
+ id="rect40455-1-9"
+ width="1"
+ height="1.5"
+ x="-37"
+ y="-119.16868" />
+ <rect
+ y="-117.62802"
+ x="-41"
+ height="1.5"
+ width="1"
+ id="rect40457-1-4"
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;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:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40459-5-8"
+ width="1"
+ height="1.5"
+ x="-40"
+ y="-117.87802" />
+ <rect
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:#000000;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"
+ id="rect40461-2-3"
+ width="13.999996"
+ height="2.0000052"
+ x="-43.5"
+ y="-114.5" />
+ <rect
+ y="-113"
+ x="-42"
+ height="1.7500292"
+ width="12.154154"
+ id="rect40490-7-9"
+ style="opacity:0.8;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.55400002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ id="rect40463-6-4"
+ d="m -40,-114 0,1.25 2,0 0,-1.25 -2,0 z m 4,0 0,1.25 2,0 0,-1.25 -2,0 z m 4,0 0,1.25 2,0 0,-1.25 -2,0 z"
+ style="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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.3;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round"
+ d="m -31.5,-120.5 -9.75,3.75"
+ id="path40474-1-2"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:none;stroke:url(#linearGradient16889);stroke-width:1px;stroke-linejoin:round"
+ d="m -41.5,-107.5 0,-6 11,0 0,6 -11,0 z"
+ id="path40476-4-2"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#87aade;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 -43,-116.75 1,0 1,1.75 0,2 -2,0 0,-3.75 z"
+ id="path40478-2-5"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#002255;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 -41,-115 0,2 -2,0 0,0.75 2.75,0 0,-3 -1.25,-2.25 -1.5,0.25 0,0.5 1,0 1,1.75 z"
+ id="path40480-3-8"
+ sodipodi:nodetypes="ccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path40558-2-3"
+ d="m -41.5,-107.38206 0,-4.66445"
+ style="opacity:0.2;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="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"
+ id="rect40553-2-9"
+ width="1"
+ height="1.5"
+ x="-33"
+ y="-120.75" />
+ <rect
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40556-1-3"
+ width="1"
+ height="1.25"
+ x="-40"
+ y="-114" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round"
+ d="m -42.4975,-113.46527 0,-3.0928"
+ id="path40560-6-1"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(1,0)"
+ style="opacity:0.35"
+ id="g40590-8-8">
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.55400002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40586-5-0"
+ width="5"
+ height="0.9617852"
+ x="-38"
+ y="-110" />
+ <rect
+ y="-111"
+ x="-36"
+ height="3"
+ width="1.0280838"
+ id="rect40588-7-3"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.55400002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g55801">
+ <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"
+ width="16"
+ height="16"
+ x="47"
+ y="52" />
+ <g
+ transform="translate(74.95064,-440.02091)"
+ id="g26260-3">
+ <g
+ id="g26262-9">
+ <path
+ sodipodi:nodetypes="cc"
+ d="M -15.594023,497.94339 -20.25,493.5"
+ style="fill:none;stroke:#28170b;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.34386529;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path26264-6"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(3.625,0,0,3.1690202,-67.8125,318.31703)"
+ d="m 14.5,57.5 a 1,1.0000004 0 1 1 -2,0 1,1.0000004 0 1 1 2,0 z"
+ sodipodi:ry="1.0000004"
+ sodipodi:rx="1"
+ sodipodi:cy="57.5"
+ sodipodi:cx="13.5"
+ id="path26266-7"
+ style="fill:none;stroke:#28170b;stroke-width:1.32768786;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.10397505;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ id="path26268-5"
+ style="fill:none;stroke:#28170b;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.34386529;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -25.5,496.5 7.5,0 m -9.5,6 6,-6"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ transform="matrix(3.5999897,0,0,3.1249932,-67.499871,320.6879)"
+ d="m 14.5,57.5 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="57.5"
+ sodipodi:cx="13.5"
+ id="path26270-5"
+ style="fill:none;stroke:url(#linearGradient26282-0);stroke-width:0.92424375;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.10397505;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ d="m -25.5,496.5 7.984366,-0.0226 M -27.5,502.5 l 6,-6 m 5.996227,1.44466 L -20.25,493.5"
+ style="fill:none;stroke:url(#linearGradient26284-9);stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.34386529;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path26272-4"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path26274-0"
+ sodipodi:cx="13.5"
+ sodipodi:cy="57.5"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 14.5,57.5 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 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 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="57.5"
+ sodipodi:cx="13.5"
+ id="path26276-1"
+ style="fill:#2c5aa0;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient26286-4);stroke-width:0.22536004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.10397505;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path26278-1"
+ sodipodi:cx="13.5"
+ sodipodi:cy="57.5"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 14.5,57.5 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ transform="matrix(4.7519907,0,0,4.1435313,-83.051884,262.12196)" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ d="m -20.515634,493.80534 c -0.07079,-0.45769 0.0843,-0.63855 0.5,-0.5 m -7.704183,9.08552 4.25,-4.25 m -2,-2 6.25,0"
+ style="fill:none;stroke:url(#linearGradient26288-9);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ id="path26280-5"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g24933-4"
+ transform="translate(-375.85,-461.8829)">
+ <path
+ inkscape:connector-curvature="0"
+ id="path24939-9"
+ d="m 430.5,525.5329 0,2 1,1 2,0 2,-2.0329 0,-2 -1,-1 -2,0 -2,2.0329 z"
+ style="fill:none;stroke:#000000;stroke-width:2.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000;stroke-width:2.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 433.5,522.4671 0,1.75 1,1.25 2,0 2,-1.9671 0,-2 -1,-1 -2,0 -2,1.9671 z"
+ id="path24941-0"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path24945-6"
+ d="m 433.5,522.4671 0,2.0329 1,0.9671 2,0 2,-1.9671 0,-2 -1,-1 -2,0 -2,1.9671 z"
+ style="fill:none;stroke:url(#linearGradient55785);stroke-width:1.29999995;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="ccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#000000;stroke-width:2.70000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 434.5,523.5 -2,0"
+ id="path24954-1" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient55787);stroke-width:1.29999995;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 430.5,525.5 0,2 1,1 2,0 2,-2 0,-2 -1,-1 -2,0 -2,2 z"
+ id="path24956-1"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path24958-1"
+ d="m 434.08489,525.47125 2.25,0"
+ style="fill:none;stroke:#000000;stroke-width:2.70000005;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M 434.33489,525.47125 436.5,525.4671"
+ id="path24960-1" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g55835">
+ <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"
+ width="16"
+ height="16"
+ x="68"
+ y="52" />
+ <g
+ transform="translate(95.95064,-440.02091)"
+ id="g26260-3-6">
+ <g
+ id="g26262-9-1">
+ <path
+ sodipodi:nodetypes="cc"
+ d="M -15.594023,497.94339 -20.25,493.5"
+ style="fill:none;stroke:#28170b;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.34386529;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path26264-6-7"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(3.625,0,0,3.1690202,-67.8125,318.31703)"
+ d="m 14.5,57.5 a 1,1.0000004 0 1 1 -2,0 1,1.0000004 0 1 1 2,0 z"
+ sodipodi:ry="1.0000004"
+ sodipodi:rx="1"
+ sodipodi:cy="57.5"
+ sodipodi:cx="13.5"
+ id="path26266-7-7"
+ style="fill:none;stroke:#28170b;stroke-width:1.32768786;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.10397505;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ id="path26268-5-3"
+ style="fill:none;stroke:#28170b;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.34386529;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -25.5,496.5 7.5,0 m -9.5,6 6,-6"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ transform="matrix(3.5999897,0,0,3.1249932,-67.499871,320.6879)"
+ d="m 14.5,57.5 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="57.5"
+ sodipodi:cx="13.5"
+ id="path26270-5-9"
+ style="fill:none;stroke:url(#linearGradient26282-0-8);stroke-width:0.92424375;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.10397505;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ d="m -25.5,496.5 7.984366,-0.0226 M -27.5,502.5 l 6,-6 m 5.996227,1.44466 L -20.25,493.5"
+ style="fill:none;stroke:url(#linearGradient26284-9-6);stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.34386529;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path26272-4-9"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path26274-0-6"
+ sodipodi:cx="13.5"
+ sodipodi:cy="57.5"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 14.5,57.5 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 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 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="57.5"
+ sodipodi:cx="13.5"
+ id="path26276-1-7"
+ style="fill:#2c5aa0;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient26286-4-5);stroke-width:0.22536004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.10397505;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path26278-1-5"
+ sodipodi:cx="13.5"
+ sodipodi:cy="57.5"
+ sodipodi:rx="1"
+ sodipodi:ry="1"
+ d="m 14.5,57.5 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
+ transform="matrix(4.7519907,0,0,4.1435313,-83.051884,262.12196)" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ d="m -20.515634,493.80534 c -0.07079,-0.45769 0.0843,-0.63855 0.5,-0.5 m -7.704183,9.08552 4.25,-4.25 m -2,-2 6.25,0"
+ style="fill:none;stroke:url(#linearGradient26288-9-5);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ id="path26280-5-4"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(-1,0,0,-1,110.9,273.1)"
+ id="g39333-1"
+ style="display:inline;enable-background:new">
+ <g
+ transform="translate(26.00079,19.1)"
+ id="g39096-7-1"
+ style="display:inline;enable-background:new">
+ <g
+ id="g39118-3-3"
+ style="fill:#ffffff;display:inline;enable-background:new"
+ transform="translate(-1.00079,-19)" />
+ </g>
+ <g
+ id="g38966-7"
+ transform="matrix(0,-1,-1,0,212.75,247.25)">
+ <g
+ transform="matrix(-1,0,0,-1,215.25,222.75)"
+ id="g38968-4">
+ <path
+ inkscape:connector-curvature="0"
+ id="path38970-5"
+ d="m 174.5,38.5 0,5 5,0"
+ style="fill:none;stroke:#000000;stroke-width:2.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 175.5,42.5 5,-5"
+ style="fill:none;stroke:#000000;stroke-width:3.20000005;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="path38972-1"
+ sodipodi:nodetypes="cz" />
+ </g>
+ <g
+ id="g38975-0"
+ transform="translate(-146.75,127.75)">
+ <g
+ id="g38977-1"
+ 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,0,0,-1,272.1613,155.99999)"
+ style="display:inline">
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ id="path38984-8"
+ sodipodi:nodetypes="cz"
+ d="" />
+ <path
+ inkscape:connector-curvature="0"
+ d=""
+ style="opacity:0.85;fill:none;stroke:#ffffff;stroke-width:1.5;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="path38987-2"
+ sodipodi:nodetypes="cz" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ id="path38994-9"
+ d="m 188,51 0,6 -1,0 0,-5 -5,0 0,-1 6,0 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ transform="matrix(-1,0,0,1,-29,-335)"
+ style="opacity:0.2"
+ id="g38996-7">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ id="path38998-6"
+ d="m -216,387 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ style="fill:#333333;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>
+ <g
+ id="g39000-4"
+ 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,0,0,-1,118.4113,290.74999)"
+ style="display:inline">
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ id="path39015-9"
+ sodipodi:nodetypes="cz"
+ d="" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 78.1613,110.99999 5.5,-5.5"
+ style="fill:none;stroke:#ffffff;stroke-width:1.5;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="path39017-0"
+ sodipodi:nodetypes="cz" />
+ </g>
+ <g
+ id="g39020-8"
+ style="opacity:0.2"
+ transform="matrix(-1,0,0,1,-175.75,-207.25)">
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.7;fill:#333333;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -216,387 0,2 1,0 0,-1 1,0 0,-1 -2,0 z"
+ id="path39022-9"
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g55731">
+ <rect
+ y="51.97921"
+ x="25.950649"
+ height="16"
+ width="16"
+ id="rect42947-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
+ transform="translate(-301.04935,-550.02079)"
+ id="g42949-4">
+ <g
+ style="opacity:0.85"
+ id="g42951-6">
+ <path
+ style="fill:#e6e6e6;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 341.5161,616.38229 340.5,617.5 l -10.73389,-10e-6 -1.25,-1.25 L 328.5,605.5 l 13,0 0.0161,10.88229 z"
+ id="path42953-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"
+ sodipodi:nodetypes="ccccccc"
+ 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="path42955-8"
+ d="m 340,616 -8.25,0 0,-1 8.25,0 0,1 z"
+ style="fill:#999999;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" />
+ <rect
+ style="opacity:0.2;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="rect38927-6"
+ width="11.970581"
+ height="8.0306396"
+ x="329.02942"
+ y="605.96936" />
+ <rect
+ y="605.96936"
+ x="329.02942"
+ height="8.0306396"
+ width="11.970581"
+ id="rect45307-5"
+ style="opacity:0.3;fill:url(#radialGradient45309-0);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: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="path42957-3"
+ d="m 340.48389,606.50001 c -3.66204,-3e-5 -7.70403,2e-5 -10.98389,-10e-6 l 0.002,10.00007 10.99778,-7e-5 -0.0161,-9.99999 2.1e-4,0 z"
+ style="fill:none;stroke:url(#linearGradient42965-7-9);stroke-width:0.99999923px;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="ccccc"
+ inkscape:connector-curvature="0" />
+ <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"
+ y="615"
+ x="330"
+ height="1.0000043"
+ width="1"
+ id="rect42959-9"
+ 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" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="opacity:0.35;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"
+ d="m 340.5,614 -11,0 0,-1 11,0 0,1 z"
+ id="path38929-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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="opacity:0.25;fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;filter:url(#filter24186-3-2-5)"
+ d="m 337.7,606.7 0,2.75 2,1.5 0,2.5 -0.25,0.25 -1.75,0 0,-2 -2,0 0,2 -1.75,0 -0.25,-0.25 0,-2.5 2,-1.5 0,-2.75 2,0 z"
+ id="path42961-6"
+ sodipodi:nodetypes="ccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccccccccccccccccc"
+ id="path42963-7"
+ d="m 333.75,602.5 1.75,0 c 0,0 0,2 0,2 l 2,0 0,-2 1.75,0 0.25,0.25 0,2.5 -2,1.5 0,2.5 2,1.5 0,2.5 -0.25,0.25 -1.75,0 0,-2 -2,0 0,2 -1.75,0 -0.25,-0.25 0,-2.5 2,-1.5 0,-2.5 -2,-1.5 0,-2.5 0.25,-0.25 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:url(#linearGradient42967-6-4);stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g45287-4"
+ transform="translate(160.94228,123.97921)"
+ style="display:inline;enable-background:new">
+ <path
+ inkscape:connector-curvature="0"
+ id="path45290-5"
+ style="opacity:0.25;fill:none;stroke:#000000;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"
+ 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"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path45302-1"
+ style="fill:none;stroke:#0b1e00;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"
+ d="m -120.5,-68.5 c -3.15098,1.124146 -6.99163,5 -8.99163,9 l -3.5,-3.5 -0.5,0.5 4,4 c 1.42501,-3.330356 5.5,-8.75 8.99163,-10"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ d="m -120.5,-68.5 c -3.15098,1.124146 -6.99163,5 -8.99163,9 l -3.5,-3.5 -0.5,0.5 4,4 c 1.42501,-3.330356 5.5,-8.75 8.99163,-10"
+ style="fill:none;stroke:#9af23d;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path45294-9" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g55696">
+ <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="rect45203-3"
+ width="16"
+ height="16"
+ x="-20.95064"
+ y="-67.97921" />
+ <g
+ style="display:inline"
+ id="g45205-1"
+ 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,0,0,-1,123.0839,85.1)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccsccccccccsccccc"
+ d="m 105.48388,31.25 6.25,-6 c 0.49692,0.284098 0.2225,0.232267 0.76612,0.25 2.20206,0.07183 4,-1.792 4,-4 l -1,-1 -2.5,2.5 -0.5,-0.5 -1,-1 -0.5,-0.5 2.5,-2.5 -1,-1 c -2.208,0 -4,1.792 -4,4 0,0.58349 0.009,0.250006 0.23388,0.75 l -6.25,6 0,2 1,1 2,0 z"
+ style="fill:url(#linearGradient55656);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path45207-7" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path45209-9"
+ 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 115.5,21.5 -2.25,2.25 m -1,-5.5 c -1.75,0 -4,2.25 -2.5,5 l -1.26612,0.25 -5,5 0,1.75"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path45211-9"
+ 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:0"
+ d="m 105.48388,31.5 5.5,-5.5 0.25,-0.5 1.26612,0 c 2.73388,0 4,-1.792 4,-4 l -1,-1 -2.5,2.5 -0.5,-0.5 -1,-1 -0.5,-0.5 2.5,-2.5 -1,-1 c -2.208,0 -3.96454,1.25 -4,4 l -0.0161,1.25 -0.5,0.25 -5.5,5.5 0,2 1,1 2,0 -2e-5,0 z"
+ sodipodi:nodetypes="cccsccccccccsccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path45214-0"
+ style="fill:none;stroke:#d7d7d7;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 109.98388,25 -5,5"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ d="m 109.48388,24.5 -4,4"
+ style="fill:none;stroke:#646464;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path45216-1" />
+ <rect
+ y="29"
+ x="103.98388"
+ height="1"
+ width="1"
+ id="rect45218-5"
+ style="fill:#162d50;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.0999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <g
+ transform="translate(-409.04935,-611.97079)"
+ id="g32398-1">
+ <g
+ id="g32400-8"
+ transform="matrix(1,0,0,-1,73,774)">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#0b1e00;stroke-width:3.5999999;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,108.25 0,-4.25 4.25,0"
+ id="path32403-1"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csc"
+ id="path32411-7"
+ d="m 428,671.25 c -0.0541,-1.25729 -0.54273,-2.44429 -1.37516,-3.38809 -2.00926,-2.27808 -5.59675,-2.62117 -7.87484,-0.61191 L 417,669"
+ style="color:#000000;fill:none;stroke:#0b1e00;stroke-width:3.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" />
+ <g
+ id="g32413-8"
+ transform="matrix(1,0,0,-1,73,774)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path32416-5"
+ d="m 343,108.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#8af01e;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" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.15;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 417,669 0,-1 0,-1.5 1,0 0,1.5 1.5,0 0,1 -1.5,0 -1,0 z"
+ id="path32418-2" />
+ <path
+ inkscape:connector-curvature="0"
+ style="color:#000000;fill:none;stroke:#8af01e;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 428,671.25 c -0.0541,-1.25729 -0.54273,-2.44429 -1.37516,-3.38809 -2.00926,-2.27808 -5.59675,-2.62117 -7.87484,-0.61191 L 417,669"
+ id="path32420-2"
+ sodipodi:nodetypes="csc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path32422-4"
+ d="m 415.5,670 0,-4.5 m 5,4 -2,0"
+ style="opacity:0.4;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" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.4;color:#000000;fill:none;stroke:url(#linearGradient55624);stroke-width:1.10000002;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 428.5,671.21875 c -0.0591,-1.37274 -0.59591,-2.66246 -1.5,-3.6875 -1.09228,-1.23842 -2.62571,-1.96363 -4.1875,-2.09375 -1.55879,-0.12987 -3.16135,0.33951 -4.40625,1.4375 -3.3e-4,0.0104 -3.3e-4,0.0208 0,0.0312 L 417.5,667.75"
+ id="path32424-5"
+ sodipodi:nodetypes="cscccc" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g17770">
+ <rect
+ y="51.979202"
+ x="88.95063"
+ height="16"
+ width="16"
+ id="rect42954-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
+ transform="translate(-49.94936,-39.370919)"
+ id="g42956-6">
+ <g
+ id="g42958-1"
+ transform="translate(-179,199.50012)">
+ <path
+ inkscape:connector-curvature="0"
+ id="path14490"
+ d="m 328.5,-107.25 -4.5,1.75 0,6.5 4.5,2.25 4.5,-2.25 0,-6.5 -4.5,-1.75 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#281500;stroke-width:1.79999995;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"
+ sodipodi:nodetypes="ccccccc" />
+ <g
+ id="g42962-0"
+ transform="translate(179,-179)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path42964-9"
+ d="m 154,80 0,-6.5 -4.5,-1.75 0,10.5 L 154,80 z"
+ style="fill:#915515;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ 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
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ id="path42966-1"
+ d="m 324,-99.00012 0,-6.49988 4.5,-1.75 0.5,0.25 0,10 -0.5,0.25 -4.5,-2.25012 z"
+ style="fill:#efa351;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path42968-5"
+ d="m 332.5,-105.5 0,6.25 -4,2 -4,-2.00012 0,-6.24988"
+ style="fill:none;stroke:url(#linearGradient55950);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path42970-1"
+ d="m 324,-105.5 4.5,-1.75 4.5,1.75 -4.5,2 -4.5,-2 z"
+ style="fill:#f5ca9b;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ 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="path42972-5"
+ d="m 145.5,94.25012 c 0,0 4,1.75 4,1.75 l 4,-1.75"
+ style="opacity:0.95999995;fill:none;stroke:url(#linearGradient55952);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="96.000122"
+ x="149"
+ height="6.7500019"
+ width="1"
+ id="rect42974-8"
+ style="fill:url(#linearGradient55954);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.09599998;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect42976-8"
+ width="1"
+ height="6.7500019"
+ x="150"
+ y="96.000122" />
+ </g>
+ <g
+ 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(0.7882544,0,0,0.7883038,-8.4020402,-113.3734)"
+ id="g42978-1"
+ style="display:inline;enable-background:new">
+ <path
+ transform="matrix(0.6425292,0,0,0.642531,44.523834,146.81699)"
+ sodipodi:type="arc"
+ style="fill:#f2b676;fill-opacity:1;fill-rule:nonzero;stroke:#281500;stroke-width:1.97436094;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42980-5"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path42984-5"
+ style="fill:none;stroke:url(#linearGradient55956);stroke-width:2.54167628;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.4991181,0,0,0.4991107,63.460522,163.7471)" />
+ <path
+ transform="matrix(-0.5858806,-0.06590218,0.06677852,-0.5812167,198.80048,299.96262)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path42982-9"
+ style="opacity:0.8;fill:url(#linearGradient55958);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:type="arc" />
+ </g>
+ <g
+ transform="matrix(0.875,0,0,0.875,-151.54375,-26.76875)"
+ id="g43952-8">
+ <g
+ transform="matrix(0,-1,1,0,183.99437,429)"
+ id="g43483-9">
+ <g
+ transform="translate(0,21)"
+ id="g43488-2">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path43490-2"
+ d="M 327,86.255631 327,76"
+ style="fill:none;stroke:#000000;stroke-width:3.88571429;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"
+ d="M 331.25,79.25 327,75.005631 322.75,79.25"
+ style="fill:none;stroke:#000000;stroke-width:4.11428547;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(0,21)"
+ id="g43494-2">
+ <path
+ style="fill:none;stroke:#dcdcdc;stroke-width:2.28571439;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,86.255631 327,76"
+ id="path43496-7"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#dcdcdc;stroke-width:2.28571439;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 331.25,79.25 327,75.005631 322.75,79.25"
+ id="path43498-9"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <path
+ sodipodi:nodetypes="cc"
+ id="path43776-0"
+ style="fill:none;stroke:#ffffff;stroke-width:1.14285719;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=""
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient55988);stroke-width:1.14285719;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 284,97.25 -4.5,4.5 0,0.5 4.5,4.5"
+ id="path43780-4"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path43860-6"
+ d="m 291.5,101.5 -8.99437,0"
+ style="fill:none;stroke:#ffffff;stroke-width:1.14285719;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>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g56020">
+ <g
+ transform="translate(-28.94936,-39.370919)"
+ id="g42956-6-7">
+ <g
+ id="g42958-1-8"
+ transform="translate(-179,199.50012)">
+ <path
+ inkscape:connector-curvature="0"
+ id="path14490-2"
+ d="m 328.5,-107.25 -4.5,1.75 0,6.5 4.5,2.25 4.5,-2.25 0,-6.5 -4.5,-1.75 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#281500;stroke-width:1.79999995;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"
+ sodipodi:nodetypes="ccccccc" />
+ <g
+ id="g42962-0-2"
+ transform="translate(179,-179)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path42964-9-7"
+ d="m 154,80 0,-6.5 -4.5,-1.75 0,10.5 L 154,80 z"
+ style="fill:#915515;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ 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
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ id="path42966-1-0"
+ d="m 324,-99.00012 0,-6.49988 4.5,-1.75 0.5,0.25 0,10 -0.5,0.25 -4.5,-2.25012 z"
+ style="fill:#efa351;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path42968-5-4"
+ d="m 332.5,-105.5 0,6.25 -4,2 -4,-2.00012 0,-6.24988"
+ style="fill:none;stroke:url(#linearGradient14559-8);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path42970-1-3"
+ d="m 324,-105.5 4.5,-1.75 4.5,1.75 -4.5,2 -4.5,-2 z"
+ style="fill:#f5ca9b;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ 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="path42972-5-8"
+ d="m 145.5,94.25012 c 0,0 4,1.75 4,1.75 l 4,-1.75"
+ style="opacity:0.95999995;fill:none;stroke:url(#linearGradient14561-9);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="96.000122"
+ x="149"
+ height="6.7500019"
+ width="1"
+ id="rect42974-8-0"
+ style="fill:url(#linearGradient14563-3);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.09599998;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect42976-8-4"
+ width="1"
+ height="6.7500019"
+ x="150"
+ y="96.000122" />
+ </g>
+ <g
+ 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(0.7882544,0,0,0.7883038,12.59796,-113.3734)"
+ id="g42978-1-6"
+ style="display:inline;enable-background:new">
+ <path
+ transform="matrix(0.6425292,0,0,0.642531,44.523834,146.81699)"
+ sodipodi:type="arc"
+ style="fill:#f2b676;fill-opacity:1;fill-rule:nonzero;stroke:#281500;stroke-width:1.97436094;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42980-5-8"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path42984-5-2"
+ style="fill:none;stroke:url(#linearGradient14565-5);stroke-width:2.54167628;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.4991181,0,0,0.4991107,63.460522,163.7471)" />
+ <path
+ transform="matrix(-0.5858806,-0.06590218,0.06677852,-0.5812167,198.80048,299.96262)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path42982-9-0"
+ style="opacity:0.8;fill:url(#linearGradient14567-8);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:type="arc" />
+ </g>
+ <g
+ transform="matrix(0.875,0,0,0.875,-149.68867,-26.76875)"
+ id="g43941-0">
+ <g
+ id="g43467-5"
+ transform="matrix(0,-1,-1,0,409.02125,429)">
+ <g
+ id="g43469-6"
+ transform="translate(0,21)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:3.88571429;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M 327,86.25 327,76"
+ id="path43471-7"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:4.11428547;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M 331.25,79.25 327,75.005631 322.75,79.25"
+ id="path43473-1"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g43475-6"
+ transform="translate(0,21)">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path43478-9"
+ d="M 327,86.25 327,76"
+ style="fill:none;stroke:#dcdcdc;stroke-width:2.28571439;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
+ sodipodi:nodetypes="ccc"
+ id="path43481-3"
+ d="M 331.25,79.25 327,75.005631 322.75,79.25"
+ style="fill:none;stroke:#dcdcdc;stroke-width:2.28571439;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>
+ </g>
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1.37142861;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 308.5,106 2.75,-2.75"
+ id="path43778-6"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path43785-2"
+ d="m 308.75,97.25 c -0.25,0 -0.5,0.25 -0.5,0.5 m 2.26562,3.75 -8.99437,0"
+ style="fill:none;stroke:#ffffff;stroke-width:1.14285719;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:none;stroke:url(#linearGradient55990);stroke-width:1.14285719;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.02125,97.249998 4.5,4.500002 0,0.5 -4.5,4.5"
+ id="path44948-4"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g56270">
+ <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"
+ width="16"
+ height="16"
+ x="131"
+ y="52" />
+ <g
+ transform="translate(-399,2)"
+ id="g56091-7">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ id="path29110-17"
+ d="m 531,58 6,-2.5 7.99996,3.49998 0,2.75 -5.99999,3.24999 L 531,60.75 531,58 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.70000005;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\4.png"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:#9e9e9e;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 531,58 6,-2.5 7.99996,3.49998 0,0.5 -6,3 L 531,58.56558 531,58 z"
+ id="path29112-53" />
+ <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="path29114-1"
+ d="M 531.00001,60.75 531,58.5 l 7.99996,3.99998 0.01,2.49885 -8.00991,-4.24883 -4e-5,0 z"
+ style="fill:#848484;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ 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"
+ style="fill:#383838;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 544.99996,61.74998 0,-2.25 -6,3 c 0,2.58362 0,1.9329 0,2.5 l 6,-3.25 z"
+ id="path29116-3"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient56084-9);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 531.5,58.5 0,2 7.49996,3.99998 5.5,-3 0,-2"
+ id="path29118-7"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 531.5,58 7.49996,3.74998"
+ id="path29120-1"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient29129-4);stroke-width:1.08012342;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="path29122-40"
+ sodipodi:cx="749"
+ sodipodi:cy="420.25"
+ sodipodi:rx="2.5"
+ sodipodi:ry="1.75"
+ d="m 751.5,420.25 a 2.5,1.75 0 1 1 -5,0 2.5,1.75 0 1 1 5,0 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"
+ id="rect29125-3"
+ width="1"
+ height="1"
+ x="544"
+ y="61" />
+ </g>
+ <g
+ transform="matrix(0.53305487,0,0,0.53305487,-263.95264,-56.614058)"
+ id="g15021"
+ style="display:inline;enable-background:new">
+ <path
+ style="fill:url(#linearGradient15123);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="path15023"
+ 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
+ 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="path15025"
+ 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(#radialGradient15125);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" />
+ <path
+ id="path15027"
+ style="fill:none;stroke:url(#linearGradient15127);stroke-width:1.03178871;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ d="m 754.5,209 0,9.5 m 3.5,-13 7.5,0"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path15029"
+ d="m 753,208 4,0 0,-4 -4,4 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ id="path15031"
+ style="fill:none;stroke:#000000;stroke-width:1.50078368;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient15129);stroke-width:0.93798971;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 757.5,206.5 0,2 -2,0"
+ id="path15033"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g15009"
+ transform="matrix(0.53305487,0,0,0.53305487,86.97987,-126.1707)">
+ <rect
+ y="344"
+ x="89"
+ height="16"
+ width="16"
+ id="rect15011"
+ 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="g15013">
+ <rect
+ y="344.7504"
+ x="91.249611"
+ height="12.998481"
+ width="13"
+ id="rect15015"
+ style="fill:url(#linearGradient15131);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.50078368;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" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path15017"
+ d="m 92.28796,356.69549 0,-10.90453 10.90641,0 0,10.90453 -10.90641,0 z"
+ style="fill:none;stroke:url(#linearGradient15133);stroke-width:0.56279385;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\Kopia 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"
+ sodipodi:nodetypes="cszzcc"
+ id="path15019"
+ d="m 103.5,353.27516 c -0.37083,-1.1875 -1.21031,-1.72293 -1.9,-1.72929 -1.39235,-0.0134 -1.47709,3.98814 -2.999997,4 -1.491657,0.0119 -2.001315,-7 -3.5,-7 -1.52993,-10e-4 -1.18608,5.00645 -3.5,4.97929 l -1,0"
+ style="fill:none;stroke:url(#linearGradient15135);stroke-width:1.1255877;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g15035"
+ transform="matrix(0.53305487,0,0,0.53305487,-270.25684,-53.589044)">
+ <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="path15037"
+ d="m 757.01257,204.46121 9.48743,0.0388 0,14.99999 -13,0 0.0126,-11.53879 3.5,-3.5 -3e-5,0 z"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g15039"
+ style="display:inline;enable-background:new"
+ transform="translate(838.01257,111.96121)">
+ <g
+ id="g15041">
+ <rect
+ style="fill:#ebb5b5;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect15043"
+ width="9.9999914"
+ height="12"
+ x="-83"
+ y="94" />
+ <rect
+ y="101"
+ x="-83"
+ height="4.9999976"
+ width="9.9999924"
+ id="rect15045"
+ style="opacity:0.5;fill:#4b80cd;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="94"
+ x="-83"
+ height="6.8499999"
+ width="9.9999914"
+ id="rect15047"
+ style="opacity:0.3;fill:url(#radialGradient15137-5);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="cccccccccccc"
+ id="path15050"
+ d="m -83,100.00002 1,0 1,0.74999 1,-0.74999 1,0.99999 2,0 1.5,-0.75 1.5,0.75 0.999991,0 L -73,102 l -9.999991,0 -9e-6,-1.99998 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect15052"
+ width="2.0000029"
+ height="2.0000038"
+ x="-77"
+ y="96" />
+ <path
+ style="opacity:0.3;fill:#280b0b;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 -83,102 10,0 0,1 -10,0 0,-1 z"
+ id="path15054"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path15056"
+ d="m -77,102 2.000003,0 -0.750003,4 -0.5,0 -0.75,-4 z"
+ style="opacity:0.5;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g15058"
+ style="display:inline;enable-background:new"
+ transform="translate(838.01257,111.96121)">
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path15060"
+ d="m -82.5,105.5 0,-11 9,0"
+ style="opacity:0.25;fill:none;stroke:#000000;stroke-width:1.87597954px;stroke-linecap:round;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.2;fill:none;stroke:#000000;stroke-width:1.87597954px;stroke-linecap:round;display:inline;enable-background:new"
+ d="m -82.5,105.5 0,-11 9,0 0,11 -9,0 z"
+ id="path15062"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="opacity:0.5;fill:url(#radialGradient15139-5);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 757.51257,204.46121 9,1e-5 0,14.99999 -13,0 0,-11 4,-4 z"
+ id="path15064"
+ 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.51257,209.96121 754.5,218.5 M 759.01257,205.46121 765.5,205.5"
+ style="fill:none;stroke:url(#linearGradient15141-6);stroke-width:1.03178871;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="path15066"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 753.01257,208.96121 5,0 0,-5 -5,5 z"
+ id="path15068"
+ 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.51257,207.96121 753.5,219.5 l 13,0 0,-14.99999 -9.48743,-0.0388 -3.5,3.5 z"
+ style="fill:none;stroke:#000000;stroke-width:1.50078368;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path15070"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path15072"
+ d="m 758.51257,206.46121 0,3 -3,0"
+ style="fill:none;stroke:url(#linearGradient15143-1);stroke-width:0.93798971;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g56314">
+ <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"
+ width="16"
+ height="16"
+ x="152"
+ y="52" />
+ <g
+ transform="translate(-378,2)"
+ id="g56091-71">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ id="path29110-7"
+ d="m 531,58 6,-2.5 7.99996,3.49998 0,2.75 -5.99999,3.24999 L 531,60.75 531,58 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.70000005;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\4.png"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:#9e9e9e;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 531,58 6,-2.5 7.99996,3.49998 0,0.5 -6,3 L 531,58.56558 531,58 z"
+ id="path29112-1" />
+ <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="path29114-0"
+ d="M 531.00001,60.75 531,58.5 l 7.99996,3.99998 0.01,2.49885 -8.00991,-4.24883 -4e-5,0 z"
+ style="fill:#848484;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ 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"
+ style="fill:#383838;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 544.99996,61.74998 0,-2.25 -6,3 c 0,2.58362 0,1.9329 0,2.5 l 6,-3.25 z"
+ id="path29116-7"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient56084-0);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 531.5,58.5 0,2 7.49996,3.99998 5.5,-3 0,-2"
+ id="path29118-8"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 531.5,58 7.49996,3.74998"
+ id="path29120-7"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient29129-1);stroke-width:1.08012342;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="path29122-0"
+ sodipodi:cx="749"
+ sodipodi:cy="420.25"
+ sodipodi:rx="2.5"
+ sodipodi:ry="1.75"
+ d="m 751.5,420.25 a 2.5,1.75 0 1 1 -5,0 2.5,1.75 0 1 1 5,0 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"
+ id="rect29125-72"
+ width="1"
+ height="1"
+ x="544"
+ y="61" />
+ </g>
+ <g
+ transform="translate(-262.04935,-611.97079)"
+ id="g32365-0-5">
+ <g
+ style="opacity:0.8"
+ id="g32367-2-1"
+ transform="translate(23,1)">
+ <g
+ style="opacity:0.96000001;display:inline"
+ id="g32369-7-1"
+ transform="matrix(0.927848,0,0,0.916217,240.82022,467.72362)"
+ 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
+ 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(0.784039,0,0,0.779055,265.50801,498.28815)"
+ id="g32373-2-0"
+ style="opacity:0.96000001;fill:none;stroke:url(#linearGradient32430-7-9-7);stroke-width:1.17973554;stroke-opacity:1;display:inline" />
+ </g>
+ <g
+ id="g32398-1-7">
+ <g
+ transform="matrix(1,0,0,-1,73,774)"
+ id="g32400-8-4">
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path32403-1-2"
+ d="m 343,108.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#0b1e00;stroke-width:3.5999999;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>
+ <path
+ style="color:#000000;fill:none;stroke:#0b1e00;stroke-width:3.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 428,671.25 c -0.0541,-1.25729 -0.54273,-2.44429 -1.37516,-3.38809 -2.00926,-2.27808 -5.59675,-2.62117 -7.87484,-0.61191 L 417,669"
+ id="path32411-7-3"
+ sodipodi:nodetypes="csc"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(1,0,0,-1,73,774)"
+ id="g32413-8-5">
+ <path
+ style="fill:none;stroke:#8af01e;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 343,108.25 0,-4.25 4.25,0"
+ id="path32416-5-1"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path32418-2-3"
+ d="m 417,669 0,-1 0,-1.5 1,0 0,1.5 1.5,0 0,1 -1.5,0 -1,0 z"
+ style="opacity:0.15;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="csc"
+ id="path32420-2-7"
+ d="m 428,671.25 c -0.0541,-1.25729 -0.54273,-2.44429 -1.37516,-3.38809 -2.00926,-2.27808 -5.59675,-2.62117 -7.87484,-0.61191 L 417,669"
+ style="color:#000000;fill:none;stroke:#8af01e;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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.4;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 415.5,670 0,-4.5 m 5,4 -2,0"
+ id="path32422-4-0"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cscccc"
+ id="path32424-5-0"
+ d="m 428.5,671.21875 c -0.0591,-1.37274 -0.59591,-2.66246 -1.5,-3.6875 -1.09228,-1.23842 -2.62571,-1.96363 -4.1875,-2.09375 -1.55879,-0.12987 -3.16135,0.33951 -4.40625,1.4375 -3.3e-4,0.0104 -3.3e-4,0.0208 0,0.0312 L 417.5,667.75"
+ style="opacity:0.4;color:#000000;fill:none;stroke:url(#linearGradient32434-5-8-9);stroke-width:1.10000002;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>
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g56410">
+ <g
+ transform="translate(190.95065,3.97921)"
+ id="g18875-2"
+ 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="rect18877-3"
+ width="16"
+ height="16"
+ x="3"
+ y="69" />
+ <g
+ style="display:inline"
+ id="g18879-4"
+ transform="translate(0.01612278,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="path18881-0"
+ d="M 17.453876,82.25 16.233877,83.5 5.75,83.5 4.5,82.25 l -1e-7,-11.75 12.9652911,0 -0.01141,11.75 -5e-6,0 0,0 0,0 z"
+ style="fill:url(#linearGradient17222-4-4);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"
+ 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="path18883-5"
+ d="M 15.983877,81.999998 5.9838772,82 l 0,-0.999998 9.9999998,-2e-6 0,0.999998 z"
+ style="fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient17224-0-9);stroke-width:0.99999976px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="M 5.4838772,82.500001 5.511418,71.499938 16.483877,71.5 l 0,11 -10.9999998,10e-7 z"
+ id="path18885-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"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#ececec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect18887-7"
+ width="1"
+ height="1"
+ x="6.9838772"
+ y="81"
+ 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
+ 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 197.45064,77.47921 9,0 m -9,2 9,0 m -9,2 9,0"
+ style="fill:none;stroke:url(#linearGradient56401);stroke-width:0.9999994px;stroke-linecap:square;stroke-linejoin:round;stroke-opacity:1"
+ id="path19108-4"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g45287-4-9"
+ transform="translate(328.94228,144.9792)"
+ style="display:inline;enable-background:new">
+ <path
+ inkscape:connector-curvature="0"
+ id="path45290-5-8"
+ style="opacity:0.25;fill:none;stroke:#000000;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"
+ 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"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path45302-1-2"
+ style="fill:none;stroke:#0b1e00;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"
+ d="m -120.5,-68.5 c -3.15098,1.124146 -6.99163,5 -8.99163,9 l -3.5,-3.5 -0.5,0.5 4,4 c 1.42501,-3.330356 5.5,-8.75 8.99163,-10"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ d="m -120.5,-68.5 c -3.15098,1.124146 -6.99163,5 -8.99163,9 l -3.5,-3.5 -0.5,0.5 4,4 c 1.42501,-3.330356 5.5,-8.75 8.99163,-10"
+ style="fill:none;stroke:#9af23d;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path45294-9-3" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g56383">
+ <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"
+ width="16"
+ height="16"
+ x="173"
+ y="73" />
+ <g
+ id="g45287-4-6"
+ transform="translate(307.94228,144.9792)"
+ style="display:inline;enable-background:new">
+ <path
+ inkscape:connector-curvature="0"
+ id="path45290-5-0"
+ style="opacity:0.25;fill:none;stroke:#000000;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"
+ 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"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path45302-1-7"
+ style="fill:none;stroke:#0b1e00;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"
+ d="m -120.5,-68.5 c -3.15098,1.124146 -6.99163,5 -8.99163,9 l -3.5,-3.5 -0.5,0.5 4,4 c 1.42501,-3.330356 5.5,-8.75 8.99163,-10"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ d="m -120.5,-68.5 c -3.15098,1.124146 -6.99163,5 -8.99163,9 l -3.5,-3.5 -0.5,0.5 4,4 c 1.42501,-3.330356 5.5,-8.75 8.99163,-10"
+ style="fill:none;stroke:#9af23d;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path45294-9-7" />
+ </g>
+ <g
+ transform="translate(421.95065,-463.02079)"
+ id="g31820-9">
+ <path
+ sodipodi:nodetypes="ccc"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m -239.5,548.5 0,-1 1,0"
+ id="path31830-7"
+ inkscape:connector-curvature="0" />
+ <path
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:3.5999999;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 -239.25,548 0.5,0"
+ id="path31838-1"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path31840-4"
+ d="m -239.25,548 0.5,0"
+ style="color:#000000;fill:none;stroke:#d2d2d2;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m -239.5,548.5 -0.25,-0.5 0.25,-0.5 1,0"
+ id="path31844-1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(425.95065,-463.02079)"
+ id="g31820-9-7">
+ <path
+ sodipodi:nodetypes="ccc"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m -239.5,548.5 0,-1 1,0"
+ id="path31830-7-9"
+ inkscape:connector-curvature="0" />
+ <path
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:3.5999999;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 -239.25,548 0.5,0"
+ id="path31838-1-6"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path31840-4-3"
+ d="m -239.25,548 0.5,0"
+ style="color:#000000;fill:none;stroke:#d2d2d2;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m -239.5,548.5 -0.25,-0.5 0.25,-0.5 1,0"
+ id="path31844-1-3"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g56477">
+ <rect
+ y="73"
+ x="299"
+ height="16"
+ width="16"
+ id="rect25824-7"
+ 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" />
+ <g
+ transform="translate(209.95065,-333.02079)"
+ id="g25826-2">
+ <path
+ style="fill:url(#linearGradient25927-1-2);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,408.5 0,11.49245 1.5,1.5 10.5,0.008 0,-11.99245 -8,-0.008 0,-1 -4,0 z"
+ id="path25828-2"
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(-361,287.99994)"
+ id="g25830-3"
+ style="display:inline" />
+ <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,-10.02344 2,0 0,1 L 100.5,410.5"
+ id="path25834-2"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 93,409 0,2 -3,0 0,-2 3,0 z"
+ id="path25840-3"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccccc"
+ id="path25842-4"
+ d="m 89.5,408.5 0,11.49245 1.5,1.5 12,0.008 1.5,-1.49245 0,-6.50755 -3,-0.008 0,-3.9849 -8,-0.008 0,-1 -4,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" />
+ </g>
+ <g
+ id="g56440">
+ <g
+ style="opacity:0.96000001;display:inline"
+ id="g40606-5"
+ transform="matrix(0.927848,0,0,0.916217,148.77086,-125.29717)"
+ 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\Kopia blender\.blender\icons\blender's iconset.png"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path40608-1"
+ style="fill:url(#linearGradient42519-8-7);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.22752953;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.87787,0,0,0.889264,55.67911,118.0341)" />
+ </g>
+ <g
+ 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(0.784039,0,0,0.779055,173.45865,-94.73264)"
+ id="g40610-3"
+ style="opacity:0.96000001;fill:none;stroke:url(#linearGradient42523-5-8);stroke-width:1.17973554;stroke-opacity:1;display:inline">
+ <path
+ transform="matrix(0.87787,0,0,0.889264,55.67911,118.0341)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient42521-3-0);stroke-width:1.44816053;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path40612-7"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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"
+ 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="path40614-9"
+ style="opacity:0.96000001;fill:none;stroke:#ffffff;stroke-width:2.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 310.45064,75.47921 -3,3 m 0,1 2,2"
+ 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"
+ d="m 307.45064,79.47921 2,2"
+ style="opacity:0.96000001;fill:none;stroke:#aa0000;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path40616-6"
+ inkscape:transform-center-y="1.25"
+ inkscape:transform-center-x="-1.25" />
+ <rect
+ y="82.97921"
+ x="307.95065"
+ height="1.5"
+ width="1"
+ id="rect40618-1"
+ style="opacity:0.48000004;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="77.97921"
+ x="311.95065"
+ height="1"
+ width="1.5"
+ id="rect40620-6"
+ style="opacity:0.48000004;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:transform-center-y="-0.75"
+ id="path40622-6"
+ style="opacity:0.96000001;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 310.45064,75.47921 -3,3"
+ 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"
+ style="opacity:0.96000001;fill:url(#linearGradient56428);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 307.80578,72.95456 c -3.25557,0.003 -5.8936,2.6597 -5.87155,5.95078 0.0105,1.56055 0.63214,2.99542 1.61111,4.05762 2.7831,-7.37691 5.95805,-1.77373 7.49116,-9.06794 -0.92886,-0.60835 -2.04538,-0.9415 -3.23072,-0.94046 l 0,0 0,0 0,0 z"
+ id="path40624-9"
+ inkscape:transform-center-x="1.4653436"
+ inkscape:transform-center-y="-1.0204512" />
+ <rect
+ style="opacity:0.28800001;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40626-3"
+ width="1.4999696"
+ height="1"
+ x="302.4668"
+ y="78.97921" />
+ <rect
+ style="opacity:0.28800001;fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect40628-5"
+ width="1"
+ height="1.4999921"
+ x="306.95065"
+ y="73.47921" />
+ <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"
+ d="m 310.45064,75.47921 -3,3"
+ style="opacity:0.57600002;fill:none;stroke:#000000;stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path40630-7"
+ inkscape:transform-center-y="-0.75" />
+ </g>
+ <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="rect15838"
+ width="16"
+ height="16"
+ x="298.95065"
+ y="73.97921" />
+ <g
+ transform="translate(209.95065,-333.02079)"
+ id="g15840">
+ <g
+ style="display:inline"
+ id="g15844"
+ transform="translate(-361,287.99994)" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc"
+ id="path15846"
+ d="m 92.5,413.74245 12,0.008 0,6.25 -1.5,1.49245 -12,0.008 0,-2 1.5,0 0,-5.75755 0,-9e-4 z"
+ style="fill:#d1c595;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient25929-7-8);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="path15850"
+ d="m 93,420.5 9.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(#linearGradient15963-3);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="m 103.5,414.75 -10,-0.008 0,4.75755 -1.5,1.5 -1.5,-1.5"
+ id="path15852" />
+ <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,419.99245 1.5,1.5 12,0.008 1.5,-1.49245 0,-6.50755 -3,-0.008"
+ id="path15856"
+ sodipodi:nodetypes="cccccc" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g36339-2"
+ 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"
+ id="rect36341-7"
+ width="16"
+ height="16"
+ x="341"
+ y="238" />
+ <g
+ transform="translate(0,-12)"
+ id="g36343-6">
+ <path
+ transform="matrix(-0.7451143,-0.08386971,0.08492794,-0.7396793,437.33358,356.39712)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36363-9"
+ style="opacity:0.3;fill:url(#radialGradient37501-4-64);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:type="arc" />
+ <g
+ id="g36345-6"
+ transform="matrix(1.1658027,0,0,1.1657997,198.71028,-2.0560643)">
+ <path
+ inkscape:transform-center-y="-3.2499984"
+ inkscape:transform-center-x="-2.8145849"
+ sodipodi:end="5.7595865"
+ sodipodi:start="4.712389"
+ 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 a 8,8 0 0 1 6.9282,4 L 132,118 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36349-3"
+ style="fill:#fa2929;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(0.6969448,0,0,0.6969467,36.918512,140.83126)" />
+ <path
+ transform="matrix(0.3484724,0.6035735,-0.603572,0.3484734,154.13836,102.27942)"
+ sodipodi:type="arc"
+ style="fill:#ba0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path36351-4"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ 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"
+ sodipodi:start="4.712389"
+ sodipodi:end="5.7595865"
+ inkscape:transform-center-x="-3.2630798"
+ inkscape:transform-center-y="1.6729808e-05" />
+ <path
+ inkscape:transform-center-y="3.2500173"
+ inkscape:transform-center-x="-2.8145756"
+ sodipodi:end="5.7595865"
+ sodipodi:start="4.712389"
+ 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 a 8,8 0 0 1 6.9282,4 L 132,118 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36353-6"
+ style="fill:#8c0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(-0.3484724,0.6035735,-0.603572,-0.3484733,246.13507,184.51913)" />
+ <path
+ transform="matrix(-0.6969448,2.2484149e-8,-4.6257528e-8,-0.6969467,220.91956,305.31067)"
+ sodipodi:type="arc"
+ style="fill:#bb1010;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path36355-4"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ 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"
+ sodipodi:start="4.712389"
+ sodipodi:end="5.7595865"
+ inkscape:transform-center-x="2.8145978"
+ inkscape:transform-center-y="3.249994" />
+ <path
+ inkscape:transform-center-x="3.2630773"
+ sodipodi:end="5.7595865"
+ sodipodi:start="4.712389"
+ 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 a 8,8 0 0 1 6.9282,4 L 132,118 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36357-2"
+ style="fill:#fa2929;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(-0.3484724,-0.6035734,0.603572,-0.3484734,103.69972,343.86251)" />
+ <path
+ inkscape:transform-center-y="-3.2500006"
+ transform="matrix(0.3484724,-0.6035734,0.603572,0.3484733,11.703006,261.6228)"
+ sodipodi:type="arc"
+ style="fill:#ff7777;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path36359-5"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ 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"
+ sodipodi:start="4.712389"
+ sodipodi:end="5.7595865"
+ inkscape:transform-center-x="2.8145777" />
+ </g>
+ <path
+ transform="matrix(0.8124999,0,0,0.8045157,241.75,163.13011)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:#000000;stroke-width:0.98948926;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path36361-7"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36365-0"
+ style="fill:none;stroke:url(#linearGradient37503-1-7);stroke-width:1.45605874;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.6860851,0,0,0.6874876,258.44808,176.87656)" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g36339-2-8"
+ 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"
+ id="rect36341-7-6"
+ width="16"
+ height="16"
+ x="341"
+ y="238" />
+ <g
+ transform="translate(0,-12)"
+ id="g36343-6-8">
+ <path
+ transform="matrix(-0.7451143,-0.08386971,0.08492794,-0.7396793,437.33358,356.39712)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36363-9-4"
+ style="opacity:0.3;fill:url(#radialGradient37501-4-9-0);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:type="arc" />
+ <g
+ id="g36345-6-9"
+ transform="matrix(1.1658027,0,0,1.1657997,198.71028,-2.0560643)">
+ <path
+ inkscape:transform-center-y="-3.2499984"
+ inkscape:transform-center-x="-2.8145849"
+ sodipodi:end="5.7595865"
+ sodipodi:start="4.712389"
+ 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 a 8,8 0 0 1 6.9282,4 L 132,118 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36349-3-1"
+ style="fill:#1fdf05;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(0.6969448,0,0,0.6969467,36.918512,140.83126)" />
+ <path
+ transform="matrix(0.3484724,0.6035735,-0.603572,0.3484734,154.13836,102.27942)"
+ sodipodi:type="arc"
+ style="fill:#16ba00;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path36351-4-7"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ 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"
+ sodipodi:start="4.712389"
+ sodipodi:end="5.7595865"
+ inkscape:transform-center-x="-3.2630798"
+ inkscape:transform-center-y="1.6729808e-05" />
+ <path
+ inkscape:transform-center-y="3.2500173"
+ inkscape:transform-center-x="-2.8145756"
+ sodipodi:end="5.7595865"
+ sodipodi:start="4.712389"
+ 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 a 8,8 0 0 1 6.9282,4 L 132,118 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36353-6-7"
+ style="fill:#109400;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(-0.3484724,0.6035735,-0.603572,-0.3484733,246.13507,184.51913)" />
+ <path
+ transform="matrix(-0.6969448,2.2484149e-8,-4.6257528e-8,-0.6969467,220.91956,305.31067)"
+ sodipodi:type="arc"
+ style="fill:#24bb10;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path36355-4-6"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ 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"
+ sodipodi:start="4.712389"
+ sodipodi:end="5.7595865"
+ inkscape:transform-center-x="2.8145978"
+ inkscape:transform-center-y="3.249994" />
+ <path
+ inkscape:transform-center-x="3.2630773"
+ sodipodi:end="5.7595865"
+ sodipodi:start="4.712389"
+ 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 a 8,8 0 0 1 6.9282,4 L 132,118 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36357-2-5"
+ style="fill:#60f44c;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(-0.3484724,-0.6035734,0.603572,-0.3484734,103.69972,343.86251)" />
+ <path
+ inkscape:transform-center-y="-3.2500006"
+ transform="matrix(0.3484724,-0.6035734,0.603572,0.3484733,11.703006,261.6228)"
+ sodipodi:type="arc"
+ style="fill:#87ff77;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path36359-5-2"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ 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"
+ sodipodi:start="4.712389"
+ sodipodi:end="5.7595865"
+ inkscape:transform-center-x="2.8145777" />
+ </g>
+ <path
+ transform="matrix(0.8124999,0,0,0.8045157,241.75,163.13011)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:#000000;stroke-width:0.98948926;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path36361-7-9"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36365-0-7"
+ style="fill:none;stroke:url(#linearGradient37503-1-9-9);stroke-width:1.45605874;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.6860851,0,0,0.6874876,258.44808,176.87656)" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g36339-2-9"
+ 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"
+ id="rect36341-7-4"
+ width="16"
+ height="16"
+ x="341"
+ y="238" />
+ <g
+ transform="translate(0,-12)"
+ id="g36343-6-2">
+ <path
+ transform="matrix(-0.7451143,-0.08386971,0.08492794,-0.7396793,437.33358,356.39712)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36363-9-0"
+ style="opacity:0.3;fill:url(#radialGradient37501-4-6-8);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ sodipodi:type="arc" />
+ <g
+ id="g36345-6-4"
+ transform="matrix(1.1658027,0,0,1.1657997,198.71028,-2.0560643)">
+ <path
+ inkscape:transform-center-y="-3.2499984"
+ inkscape:transform-center-x="-2.8145849"
+ sodipodi:end="5.7595865"
+ sodipodi:start="4.712389"
+ 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 a 8,8 0 0 1 6.9282,4 L 132,118 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36349-3-5"
+ style="fill:#5050fb;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(0.6969448,0,0,0.6969467,36.918512,140.83126)" />
+ <path
+ transform="matrix(0.3484724,0.6035735,-0.603572,0.3484734,154.13836,102.27942)"
+ sodipodi:type="arc"
+ style="fill:#0000ba;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path36351-4-3"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ 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"
+ sodipodi:start="4.712389"
+ sodipodi:end="5.7595865"
+ inkscape:transform-center-x="-3.2630798"
+ inkscape:transform-center-y="1.6729808e-05" />
+ <path
+ inkscape:transform-center-y="3.2500173"
+ inkscape:transform-center-x="-2.8145756"
+ sodipodi:end="5.7595865"
+ sodipodi:start="4.712389"
+ 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 a 8,8 0 0 1 6.9282,4 L 132,118 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36353-6-4"
+ style="fill:#00008c;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(-0.3484724,0.6035735,-0.603572,-0.3484733,246.13507,184.51913)" />
+ <path
+ transform="matrix(-0.6969448,2.2484149e-8,-4.6257528e-8,-0.6969467,220.91956,305.31067)"
+ sodipodi:type="arc"
+ style="fill:#1010bb;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path36355-4-4"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ 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"
+ sodipodi:start="4.712389"
+ sodipodi:end="5.7595865"
+ inkscape:transform-center-x="2.8145978"
+ inkscape:transform-center-y="3.249994" />
+ <path
+ inkscape:transform-center-x="3.2630773"
+ sodipodi:end="5.7595865"
+ sodipodi:start="4.712389"
+ 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 a 8,8 0 0 1 6.9282,4 L 132,118 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36357-2-9"
+ style="fill:#5050fb;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(-0.3484724,-0.6035734,0.603572,-0.3484734,103.69972,343.86251)" />
+ <path
+ inkscape:transform-center-y="-3.2500006"
+ transform="matrix(0.3484724,-0.6035734,0.603572,0.3484733,11.703006,261.6228)"
+ sodipodi:type="arc"
+ style="fill:#9a9afd;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path36359-5-4"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ 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"
+ sodipodi:start="4.712389"
+ sodipodi:end="5.7595865"
+ inkscape:transform-center-x="2.8145777" />
+ </g>
+ <path
+ transform="matrix(0.8124999,0,0,0.8045157,241.75,163.13011)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:#000000;stroke-width:0.98948926;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path36361-7-0"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path36365-0-0"
+ style="fill:none;stroke:url(#linearGradient37503-1-1-1);stroke-width:1.45605874;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.6860851,0,0,0.6874876,258.44808,176.87656)" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g42207-2"
+ transform="translate(230.94982,190.97922)">
+ <g
+ transform="translate(83.990364,83.999999)"
+ id="g42209-9"
+ style="opacity:0.5">
+ <path
+ transform="matrix(0.9361892,0,0,0.9375002,-26.576994,10.374973)"
+ sodipodi:type="arc"
+ style="fill:#ffd5d5;fill-opacity:0.58823529;fill-rule:nonzero;stroke:#800000;stroke-width:1.06741309;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42211-6"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path42213-0"
+ style="fill:none;stroke:url(#linearGradient42487-4-5);stroke-width:1.22662127;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.814129,0,0,0.816369,-10.451999,24.674751)" />
+ <path
+ transform="matrix(0.6848076,0,0,0.6867124,6.6184411,39.974237)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient42489-5-9);stroke-width:1.45823753;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42215-8"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(0.814129,0,0,0.816369,-10.451999,24.674751)"
+ sodipodi:type="arc"
+ style="fill:none;stroke:url(#linearGradient42491-0-9);stroke-width:1.22662127;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path42217-3"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path17230"
+ style="fill:none;stroke:url(#linearGradient17232-8);stroke-width:3.2130022;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.31076006,0,0,0.31171146,55.992715,84.224347)" />
+ </g>
+ <g
+ transform="matrix(1.3088013,0,0,1.3078064,114.94487,78.842325)"
+ style="display:inline"
+ 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="g42219-5" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g16164">
+ <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"
+ width="16"
+ height="16"
+ x="173"
+ y="241" />
+ <g
+ id="g16145">
+ <g
+ transform="translate(-150.04936,350.7292)"
+ id="g18697-4">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ id="path18699-1"
+ 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"
+ style="fill:none;stroke:url(#linearGradient28405-0);stroke-width:1.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient18721-1-6);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 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"
+ id="path18719-9" />
+ <g
+ transform="translate(179,-179)"
+ id="g18703-1">
+ <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:url(#linearGradient18728-6-0);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 146.0019,73.295281 5,-1.894157 5,1.894157 -5,2.073959 -5,-2.073959 z"
+ id="path18707-3" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc"
+ style="fill:url(#linearGradient18765-0-9);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 334.98437,-105.6875 -5,2.04687 0.0156,6.89063 5,-2.75 z"
+ id="path18763-6" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient18712-0-7);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ 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"
+ id="path18709-9"
+ sodipodi:nodetypes="ccccccc" />
+ <g
+ style="opacity:0.7"
+ id="g18737-7" />
+ </g>
+ <g
+ id="g52877-0"
+ style="display:inline;enable-background:new"
+ transform="translate(-332.03324,273.93783)">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#2968c3;fill-opacity:1;fill-rule:evenodd;stroke:#0b1728;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="path52879-3"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path52881-6"
+ 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(#radialGradient53141-5-8);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="path52883-5"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc"
+ id="path52885-6"
+ 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(#linearGradient53143-6-3);fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path52887-1"
+ d="m 520.48389,-31.45862 -6,6.75 2,2.25 4,-4"
+ style="fill:none;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" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient53145-1-0);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 520.98389,-31.95862 -6.75,7.75 1.75,1.75 5,-4.5 0,-5 z"
+ id="path52889-3"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path52891-3"
+ d="m 513.48389,-22.45862 7,-8.25"
+ 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="path52893-4"
+ 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(#linearGradient53147-9-4);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g16082">
+ <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"
+ width="16"
+ height="16"
+ x="152"
+ y="241" />
+ <g
+ id="g16049">
+ <g
+ id="g16027">
+ <g
+ transform="translate(-20.81186,-5.9082992)"
+ id="g27791"
+ style="display:inline;enable-background:new">
+ <path
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:3.5999999;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 173.5625,249.6875 0.5,0"
+ id="path31838-1-6-1-4"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path31840-4-3-0-6"
+ d="m 173.5625,249.6875 0.5,0"
+ style="color:#000000;fill:none;stroke:#181dff;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ style="fill:none;stroke:#2f4cff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 173.3125,250.1875 -0.25,-0.5 0.25,-0.5 1,0"
+ id="path31844-1-3-6-4"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-13.91186,-7.9082992)"
+ id="g27791-5"
+ style="fill:none;display:inline;enable-background:new">
+ <path
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:3.5999999;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 173.5625,249.6875 0.5,0"
+ id="path31838-1-6-1-4-5"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path31840-4-3-0-6-0"
+ d="m 173.5625,249.6875 0.5,0"
+ style="color:#000000;fill:none;stroke:#00cc19;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ style="fill:none;stroke:#34ff24;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 173.3125,250.1875 -0.25,-0.5 0.25,-0.5 1,0"
+ id="path31844-1-3-6-4-7"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-10.27839,-7.4632172)"
+ id="g27791-9"
+ style="display:inline;enable-background:new">
+ <path
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:3.5999999;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 173.5625,249.6875 0.5,0"
+ id="path31838-1-6-1-4-7"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path31840-4-3-0-6-5"
+ d="m 173.5625,249.6875 0.5,0"
+ style="color:#000000;fill:none;stroke:#ffff0a;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ style="fill:none;stroke:#fcff7b;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 173.3125,250.1875 -0.25,-0.5 0.25,-0.5 1,0"
+ id="path31844-1-3-6-4-9"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-6.9118602,-5.9082992)"
+ id="g27791-0"
+ style="display:inline;enable-background:new">
+ <path
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:3.5999999;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 173.5625,249.6875 0.5,0"
+ id="path31838-1-6-1-4-54"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path31840-4-3-0-6-1"
+ d="m 173.5625,249.6875 0.5,0"
+ style="color:#000000;fill:none;stroke:#ff0606;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ style="fill:none;stroke:#ff3131;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 173.3125,250.1875 -0.25,-0.5 0.25,-0.5 1,0"
+ id="path31844-1-3-6-4-4"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-17.39403,-7.3654702)"
+ id="g27791-5-2"
+ style="fill:none;display:inline;enable-background:new">
+ <path
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:3.5999999;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 173.5625,249.6875 0.5,0"
+ id="path31838-1-6-1-4-5-4"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path31840-4-3-0-6-0-6"
+ d="m 173.5625,249.6875 0.5,0"
+ style="color:#000000;fill:none;stroke:#00bc86;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ style="fill:none;stroke:#24ffea;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 173.3125,250.1875 -0.25,-0.5 0.25,-0.5 1,0"
+ id="path31844-1-3-6-4-7-2"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g16016">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ id="path18699-7"
+ d="m 159.95712,247.8542 -3.25648,1.32353 -1.7128,5.25087 5,2.71875 4.99999,-2.71875 -1.77423,-5.25087 z"
+ style="fill:none;stroke:#0b1728;stroke-width:1.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient16010);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 159.98133,247.9448 -3.25648,1.2408 -1.73704,5.243 5,2.71875 4.99999,-2.71875 -1.75,-5.243 z"
+ id="path18719-4" />
+ <g
+ transform="translate(8.95064,173.9792)"
+ id="g18703-0">
+ <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:url(#linearGradient15994);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 147.75124,75.228495 3.25648,-1.253486 3.25648,1.253486 -3.25648,1.372473 z"
+ id="path18707-0" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc"
+ style="fill:url(#linearGradient16005);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 163.2136,249.34317 -3.25648,1.32353 -0.006,6.4375 5,-2.75 z"
+ id="path18763-7" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient16002);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 162.79956,249.6191 1.65308,4.57246 -4.5,2.48007 -4.5,-2.48007 1.75043,-4.61666 2.79824,-1.11389 z"
+ id="path18709-5"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ sodipodi:nodetypes="csssc"
+ inkscape:connector-curvature="0"
+ id="path14332-7-5"
+ d="m 161.04227,247.90828 c 0.24495,-0.26634 0.39423,-0.62011 0.39423,-1.00834 0,-0.8284 -0.67974,-1.49994 -1.51825,-1.49994 -0.83851,0 -1.51825,0.67154 -1.51825,1.49994 0,0.43979 0.0353,0.57241 0.34052,0.84677"
+ style="fill:#e6e6e6;fill-opacity:1;stroke:#0b1728;stroke-width:2.80000019;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new" />
+ <path
+ transform="matrix(0.8540253,0,0,-1.199954,81.751209,396.89409)"
+ d="m 93.25,125 a 1.75,1.25 0 1 1 -3.5,0 1.75,1.25 0 1 1 3.5,0 z"
+ sodipodi:ry="1.25"
+ sodipodi:rx="1.75"
+ sodipodi:cy="125"
+ sodipodi:cx="91.5"
+ id="path14336-5-6"
+ style="fill:#000000;fill-opacity:1;stroke:url(#linearGradient15989);stroke-width:1.28417933;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ sodipodi:type="arc" />
+ <rect
+ style="opacity:0.75;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="rect14340-2-4"
+ width="2.0011597"
+ height="2"
+ x="158.93533"
+ y="245.8999" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g16224">
+ <rect
+ y="241"
+ x="194"
+ height="16"
+ width="16"
+ id="rect18695-5-8"
+ 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="g16203">
+ <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-6"
+ width="16"
+ height="16"
+ x="193.95064"
+ y="240.9792" />
+ <g
+ clip-path="url(#clipPath42711-8-1)"
+ style="display:inline;enable-background:new"
+ id="g27663-9"
+ transform="matrix(0.9168751,0,0,0.9161255,86.13094,44.221905)"
+ 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="ccccccccc"
+ inkscape:connector-curvature="0"
+ id="path27665-7"
+ d="m 140.02478,121.67739 -4.38034,-0.0133 0.0328,4.36819 -6.18368,-0.0323 -0.0643,-16 6.1827,-0.0158 -0.0143,4.42449 4.42553,-0.0164 z"
+ clip-path="none"
+ mask="none"
+ style="fill:url(#linearGradient15368-7);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:1.45480967;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="matrix(0.75,0,0,0.75,29.5,135)" />
+ <path
+ transform="matrix(0.75,0,0,0.75,29.5,135)"
+ style="fill:url(#linearGradient15326-8);fill-opacity:1;stroke:#183e75;stroke-width:1.45480967;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ mask="none"
+ clip-path="none"
+ d="m 135.64444,121.66409 -6.15088,-0.006 -0.0643,-7.28458 6.1684,0.0349 z"
+ id="path15284"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ transform="matrix(0.75,0,0,0.75,29.5,135)"
+ style="fill:none;stroke:#0b1728;stroke-width:1.45480967;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ mask="none"
+ clip-path="none"
+ d="m 140.02478,121.67739 -4.38034,-0.0133 0.0328,4.36819 -6.18368,-0.0323 -0.0643,-16 6.1827,-0.0158 -0.0143,4.42449 4.42553,-0.0164 z"
+ id="path15318"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccc" />
+ </g>
+ <g
+ id="g27669-3"
+ style="opacity:0.55;display:inline;enable-background:new"
+ transform="translate(-42.04936,-19.020799)">
+ <path
+ inkscape:connector-curvature="0"
+ transform="matrix(0.9285719,0,0,0.9072647,16.387388,24.853058)"
+ sodipodi:nodetypes="cccc"
+ id="path27671-9"
+ d="M 243.50439,274.05251 237.04285,268 l 0.43058,-0.40461 6.03096,-5.66723"
+ style="fill:url(#linearGradient42432-3-3);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
+ style="fill:url(#linearGradient15281-5);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.87159598;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M 243.55198,273.44361 237.66157,268 l 5.84282,0.0171"
+ id="path15273"
+ sodipodi:nodetypes="ccc"
+ transform="matrix(0.9285719,0,0,0.9072647,16.387388,24.853058)"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path27673-0-1"
+ d="m 200.70018,253.41671 -4.93656,-4.42903 4.93656,-4.57097"
+ style="fill:none;stroke:url(#linearGradient15620-8);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
+ id="g27675-38"
+ style="display:inline;enable-background:new"
+ transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,-41.79538,113.49288)">
+ <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 73.545051,272.22272 7.071067,-7.07107"
+ id="path27679-2"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path42388-6"
+ 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-8" />
+ </g>
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:0.6507937;display:inline;enable-background:new"
+ d="m 207.43504,247.49483 1.06248,0"
+ id="path15333"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:0.6507937;display:inline;enable-background:new"
+ d="m 203.9116,244.49483 1.51561,0"
+ id="path15333-4"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:0.6507937;display:inline;enable-background:new"
+ d="m 203.9116,247.51045 1.54686,0"
+ id="path15333-3"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#1b4685;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 207.38817,249.47921 0.0703,0.004"
+ id="path15333-2"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#185e98;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 203.38817,249.47921 1.07811,0.0118"
+ id="path15333-2-7"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#143564;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 204.37254,253.47921 1.07811,0.0118"
+ id="path15333-2-7-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g16281">
+ <rect
+ y="241"
+ x="236"
+ height="16"
+ width="16"
+ id="rect18695-5-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" />
+ <g
+ id="g38510"
+ style="display:inline;enable-background:new"
+ transform="translate(-0.04936017,-0.02079917)">
+ <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="rect41297-5"
+ width="10"
+ height="16"
+ x="239"
+ y="241" />
+ <path
+ style="fill:url(#linearGradient15474-9);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 244,242.5 c -1.8975,0 -3.4375,1.12 -3.4375,2.5 l 0,2.6875 c -0.79985,0.58688 -1.28125,1.40301 -1.28125,2.4375 0,1.01219 0.48237,1.85277 1.28125,2.4375 l 0,1.4375 c 0,1.38 1.54,2.5 3.4375,2.5 1.8975,0 3.4375,-1.12 3.4375,-2.5 l 0,-1.375 c 0.82151,-0.58809 1.3125,-1.44988 1.3125,-2.5 0,-1.02039 -0.50216,-1.82067 -1.3125,-2.40625 l 0,-2.71875 c 0,-1.38 -1.54,-2.5 -3.4375,-2.5 z"
+ id="path41299-1"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.44561403;fill:none;stroke:url(#linearGradient15467-9);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 246.78175,244.56297 c -0.49244,0.67079 -1.66895,1.05852 -2.78633,1.05852 -1.11738,0 -2.54413,-0.3096 -2.81106,-1.12463"
+ id="path41303-1"
+ sodipodi:nodetypes="czs" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csc"
+ id="path41307-7"
+ d="m 241.4192,253.61696 c 0.11987,0.88868 0.64962,2.00518 2.61584,2.01183 1.81407,0.006 2.49621,-1.01999 2.49621,-2.00379"
+ style="fill:none;stroke:#1b4685;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.64285715;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="czcsssc"
+ id="path15557"
+ d="m 247.22147,247.96875 c -0.5625,0.53865 -1.82275,0.90274 -3.1948,0.90274 -1.37205,0 -2.25345,-0.3128 -3.15167,-0.80899 -0.625,0.59375 -1.17803,1.9131 -0.72606,2.94175 0.61274,1.39456 1.58368,2.00791 3.99437,2.02034 2.38609,0.0123 3.13442,-0.85323 3.75195,-2.02459 0.57357,-1.08798 0.16996,-2.1875 -0.67379,-3.03125 z"
+ style="fill:none;stroke:url(#linearGradient15601-9);stroke-width:1;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
+ inkscape:connector-curvature="0"
+ id="path41305-9"
+ d="m 244,242.5 c -2.18749,0 -3.4375,1.12 -3.4375,2.5 l 0,2.3125 c -0.8822,0.72794 -1.4375,1.73295 -1.4375,2.84375 0,1.1108 0.5553,2.11581 1.4375,2.84375 l 0,0.5 c 0,2 1.54,3 3.4375,3 1.8975,0 3.4375,-1 3.4375,-3 l 0,-0.5 c 0.8822,-0.72794 1.4375,-1.73295 1.4375,-2.84375 0,-1.1108 -0.5553,-2.11581 -1.4375,-2.84375 l 0,-2.3125 c 0,-1.38 -1.24999,-2.5 -3.4375,-2.5 z"
+ style="fill:none;stroke:#0b1728;stroke-width:0.80000007;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
+ style="display:inline;enable-background:new"
+ id="g41715-3"
+ transform="matrix(0.75,0,0,0.625,396.9999,55.104854)">
+ <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="rect41717-2"
+ width="16"
+ height="16"
+ x="-211.99985"
+ y="304" />
+ <g
+ style="opacity:0.8;display:inline;enable-background:new"
+ transform="translate(73.00016,196)"
+ id="g41719-6" />
+ <g
+ style="display:inline"
+ id="g41739-4"
+ transform="matrix(1.1658027,0,0,1.1657997,-354.28956,51.94393)"
+ 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
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient15576-5);stroke-width:1;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 247.03531,249.33728 c -0.5,0.22615 -1.69837,0.52774 -2.8823,0.52774 -1.18393,0 -1.75974,-0.0315 -3.02667,-0.49649"
+ id="path41303-1-0"
+ sodipodi:nodetypes="czs" />
+ <path
+ style="fill:none;stroke:#0b1728;stroke-width:0.80000007;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 250.25295,253 c 0.73683,-0.72794 1.01313,-1.73295 1.01313,-2.84375 0,-1.1108 -0.2763,-2.11581 -1.01313,-2.84375"
+ id="path15603"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csc" />
+ <path
+ sodipodi:nodetypes="csc"
+ inkscape:connector-curvature="0"
+ id="path15609"
+ d="m 249.80713,252.38128 c 0.53336,-0.70678 0.65533,-1.36527 0.65533,-2.22503 0,-0.80144 -0.27822,-1.5779 -0.65533,-2.18084"
+ style="fill:none;stroke:#aacee7;stroke-width:0.80000007;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.80392157;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ style="fill:none;stroke:#0b1728;stroke-width:0.80000007;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 237.81491,253 c -0.73683,-0.72794 -1.01313,-1.73295 -1.01313,-2.84375 0,-1.1108 0.2763,-2.11581 1.01313,-2.84375"
+ id="path15603-0"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csc" />
+ <path
+ sodipodi:nodetypes="csc"
+ inkscape:connector-curvature="0"
+ id="path15609-7"
+ d="m 238.26073,252.38128 c -0.53336,-0.70678 -0.65533,-1.36527 -0.65533,-2.22503 0,-0.80144 0.27822,-1.5779 0.65533,-2.18084"
+ style="fill:none;stroke:#aacee7;stroke-width:0.80000007;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.80392157;stroke-dasharray:none;stroke-dashoffset:7.40000265;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+ <g
+ id="g81264">
+ <rect
+ y="241"
+ x="278"
+ height="16"
+ width="16"
+ id="rect41153-9"
+ 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.96226475,0.05341077)"
+ id="g16521">
+ <rect
+ y="242.48071"
+ x="280.45062"
+ height="12.983693"
+ width="12.031255"
+ id="rect41157-7"
+ style="fill:url(#linearGradient81258);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.90000004;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" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path41159-4"
+ d="m 281.45064,253.1653 0.0312,-9.6861 3.81301,0.0312"
+ style="fill:none;stroke:url(#linearGradient81260);stroke-width:0.99999994;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\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:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:0.53174594;display:inline;enable-background:new"
+ d="m 291.50046,246.74298 -3.08218,7.80871"
+ id="path15817-5"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:0.48809521"
+ d="m 285.63278,246.41513 -3.2942,8.11179"
+ id="path15817"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#555555;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 286.48189,242.32295 0.0625,12.09375"
+ id="path15730"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline;enable-background:new"
+ id="rect16285-9-59"
+ width="2.0172396"
+ height="2.0000157"
+ x="279.45065"
+ y="241.47917" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path41159-4-9"
+ d="m 287.42759,252.9156 -0.0313,-9.49861 3.85989,0.0312"
+ style="fill:none;stroke:url(#linearGradient81262);stroke-width:0.99999982px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ 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:#1b4685;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 292.04439,242.6042 -5.18214,13.04504"
+ id="path15722"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#1b4685;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 286.07564,242.5417 -5.19822,12.90441"
+ id="path15726"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline;enable-background:new"
+ id="rect16285-9-1"
+ width="2.0172396"
+ height="2.0000157"
+ x="285.47092"
+ y="241.53545" />
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline;enable-background:new"
+ id="rect16285-9-50"
+ width="2.0172396"
+ height="2.0000157"
+ x="285.47092"
+ y="254.48941" />
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline;enable-background:new"
+ id="rect16285-9-6"
+ width="2.0172396"
+ height="2.0000157"
+ x="291.48386"
+ y="254.48941" />
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline;enable-background:new"
+ id="rect16285-9-16"
+ width="2.0172396"
+ height="2.0000157"
+ x="291.45065"
+ y="241.47917" />
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline;enable-background:new"
+ id="rect16285-9-15"
+ width="2.0172396"
+ height="2.0000157"
+ x="279.48859"
+ y="254.48941" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g16263">
+ <rect
+ y="241"
+ x="215"
+ height="16"
+ width="16"
+ id="rect18695-5-85"
+ 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="g16254">
+ <path
+ sodipodi:nodetypes="ccccccccccccccccscsscccscscccsccc"
+ inkscape:connector-curvature="0"
+ id="path15496"
+ d="m 220.26315,246.13546 c -0.0862,0.1378 -0.24068,0.22975 -0.40625,0.28125 -1.65981,0.47731 -3.15715,1.19818 -4.5,2.59375 -0.0159,0.0174 -0.0268,0.0393 -0.0312,0.0625 -0.001,0.0103 -0.001,0.0208 0,0.0312 -0.001,0.0103 -0.001,0.0208 0,0.0312 -0.001,0.0104 -0.001,0.0208 0,0.0312 0.0905,0.15733 0.21244,0.52956 0.25,0.8125 0.0551,0.41528 -0.0701,0.57924 -0.21875,0.8125 -0.0121,0.008 -0.0227,0.0191 -0.0312,0.0312 -0.001,0.0104 -0.001,0.0208 0,0.0312 -0.001,0.0103 -0.001,0.0208 0,0.0312 -0.001,0.0104 -0.001,0.0208 0,0.0312 0.008,0.0121 0.0191,0.0227 0.0312,0.0312 1.14704,1.20048 2.82583,2.11181 4.34375,2.15625 0.23229,0.01 0.47603,0.12502 0.59375,0.3125 0.16075,0.25148 0.43475,0.47431 0.75,0.65625 0.36481,0.21054 0.91885,0.30403 1.0936,0.3126 -0.22349,-0.50587 -0.17899,-0.77088 -0.0469,-0.99985 0.0995,-0.17241 0.27563,-0.29702 0.54688,-0.34375 1.23062,-0.212 2.86055,-0.63055 4.03125,-1.34375 0.29545,-0.18247 0.80307,-0.0462 1,0.25 0.55094,0.7385 1.45946,1.2674 2.03896,1.31646 -0.36853,-0.9196 -0.50376,-2.31287 -0.46489,-3.25371 0.0492,-1.1901 0.4842,-2.52395 1.04302,-3.51538 -0.16982,0.006 -0.65061,0.17808 -0.71074,0.20318 -0.7366,0.30737 -1.4716,0.94031 -1.90625,1.5625 -0.21933,0.29875 -0.71618,0.4032 -1,0.1875 -1.35724,-1.03154 -2.55364,-1.6969 -4.09375,-2.1875 -0.26943,-0.0858 -0.50165,-0.42209 -0.5,-0.71875 0.002,-0.30009 0.0702,-0.84684 0.12109,-1.07402 -0.58853,0.18102 -1.36128,0.81203 -1.93359,1.66737 z"
+ style="fill:none;stroke:url(#linearGradient38716-8);stroke-width:0.60000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1;display:inline;enable-background:new" />
+ <path
+ style="fill:url(#radialGradient15517-8);fill-opacity:1;stroke:#0b1728;stroke-width:0.89999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 219.6786,253.82631 c -1.96642,-0.0576 -4.05614,-1.31113 -5.29929,-2.86623 0.0654,-0.19861 0.53326,-0.60538 0.48122,-0.99782 -0.0595,-0.44857 -0.37333,-0.70398 -0.47362,-0.96241 1.5443,-1.81083 3.32964,-2.734 5.24944,-3.28607 0.78991,-1.17883 1.845,-2.02236 3.60073,-2.29898 -0.23142,0.67492 -0.40517,1.48328 -0.41544,2.14499 1.60855,0.52209 2.84544,1.19775 4.24601,2.26976 1.05365,-1.50823 3.37131,-2.56597 4.4316,-1.95202 -0.84375,1.27451 -1.45665,2.90118 -1.50672,4.17975 -0.0491,1.25211 0.0947,2.42706 0.75517,3.90477 -1.30024,0.35961 -2.91498,-0.40691 -3.71178,-1.61649 -1.31489,0.80105 -3.03198,1.22409 -4.31307,1.42108 0.13331,0.35326 0.31382,0.79794 0.42375,1.41797 -1.5092,0.0506 -2.82758,-0.35645 -3.468,-1.3583 z"
+ id="path26202"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccsccccccsccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path38361"
+ d="m 218.00011,250.69439 c -0.39287,0 -0.71132,-0.31189 -0.71132,-0.69657 0,-0.38468 0.31845,-0.69659 0.71132,-0.69659 0.39025,0 0.70763,0.30797 0.71128,0.69334 0,0.38793 -0.31844,0.69982 -0.71128,0.69982 z"
+ style="fill:none;stroke:url(#linearGradient15553-4);stroke-width:1.10000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.72222218;stroke-dasharray:none;display:inline;enable-background:new" />
+ <path
+ style="fill:none;stroke:#183e75;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 217.62649,250.02159 c -0.17675,0 -0.32002,-0.1385 -0.32002,-0.30932 0,-0.17083 0.14327,-0.30933 0.32002,-0.30933 0.17557,0 0.31836,0.13676 0.32,0.30789 0,0.17226 -0.14327,0.31076 -0.32,0.31076 z"
+ id="path26221"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient15545-5);stroke-width:0.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.58823529;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 219.95124,248.20112 c 0.63267,0.99518 0.82685,2.28773 0.0962,3.39254"
+ id="path26223-2"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ transform="translate(-0.04936017,-0.02079917)"
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="-0.21185222"
+ inkscape:original="M 222.25 244.5 C 221.66147 244.68102 220.88481 245.30091 220.3125 246.15625 C 220.2263 246.29405 220.07182 246.386 219.90625 246.4375 C 218.24644 246.91481 216.7491 247.63568 215.40625 249.03125 C 215.39035 249.04865 215.3794 249.07055 215.375 249.09375 C 215.374 249.10405 215.374 249.1146 215.375 249.125 C 215.374 249.1353 215.374 249.14585 215.375 249.15625 C 215.374 249.16665 215.374 249.1771 215.375 249.1875 C 215.4655 249.34483 215.58744 249.71706 215.625 250 C 215.6801 250.41528 215.5549 250.57924 215.40625 250.8125 C 215.39415 250.8205 215.3835 250.83165 215.375 250.84375 C 215.374 250.85415 215.374 250.8646 215.375 250.875 C 215.374 250.8853 215.374 250.89585 215.375 250.90625 C 215.374 250.91665 215.374 250.9271 215.375 250.9375 C 215.383 250.9496 215.39415 250.96025 215.40625 250.96875 C 216.55329 252.16923 218.23208 253.08056 219.75 253.125 C 219.98229 253.135 220.22603 253.25002 220.34375 253.4375 C 220.5045 253.68898 220.7785 253.91181 221.09375 254.09375 C 221.45856 254.30429 222.01275 254.39768 222.1875 254.40625 C 221.96401 253.90038 221.99291 253.63522 222.125 253.40625 C 222.2245 253.23384 222.41625 253.10923 222.6875 253.0625 C 223.91812 252.8505 225.54805 252.43195 226.71875 251.71875 C 227.0142 251.53628 227.52182 251.67255 227.71875 251.96875 C 228.26969 252.70725 229.1705 253.23219 229.75 253.28125 C 229.38147 252.36165 229.24238 250.97209 229.28125 250.03125 C 229.33045 248.84115 229.78493 247.52268 230.34375 246.53125 C 230.17393 246.53725 229.68513 246.69365 229.625 246.71875 C 228.8884 247.02612 228.1534 247.65906 227.71875 248.28125 C 227.49942 248.58 227.00257 248.68445 226.71875 248.46875 C 225.36151 247.43721 224.16511 246.77185 222.625 246.28125 C 222.35557 246.19545 222.12335 245.85916 222.125 245.5625 C 222.127 245.26241 222.19911 244.72718 222.25 244.5 z "
+ style="fill:none;stroke:url(#linearGradient15502-8);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ id="path15500"
+ d="m 221.96875,244.90625 c -0.47698,0.2556 -1.02431,0.71077 -1.46875,1.375 -0.12408,0.19836 -0.33308,0.28211 -0.53125,0.34375 a 0.21187341,0.21187341 0 0 1 0,0.0312 c -1.62449,0.46715 -3.06989,1.15677 -4.375,2.5 -0.005,0.005 0.005,0.026 0,0.0312 0.1061,0.21524 0.2123,0.49726 0.25,0.78125 0.0568,0.42776 -0.0841,0.69165 -0.21875,0.90625 1.11129,1.13328 2.71326,1.98992 4.125,2.03125 0.29567,0.0127 0.61425,0.14029 0.78125,0.40625 0.1325,0.20728 0.35983,0.42268 0.65625,0.59375 0.20197,0.11656 0.49212,0.2047 0.71875,0.25 -0.0302,-0.11277 -0.0911,-0.24526 -0.0937,-0.34375 -0.005,-0.19698 0.0446,-0.36065 0.125,-0.5 0.13631,-0.23619 0.40186,-0.41416 0.71875,-0.46875 1.21549,-0.20939 2.80996,-0.62559 3.9375,-1.3125 0.21394,-0.13213 0.48738,-0.12178 0.71875,-0.0625 0.22418,0.0574 0.42522,0.18054 0.5625,0.375 0.41333,0.55404 1.07488,0.98799 1.5625,1.15625 -0.29258,-0.93531 -0.41043,-2.11125 -0.375,-2.96875 0.0456,-1.10343 0.44992,-2.25295 0.9375,-3.21875 -0.14571,0.0415 -0.29515,0.0995 -0.28125,0.0937 -0.68743,0.28685 -1.40343,0.91443 -1.8125,1.5 a 0.21187341,0.21187341 0 0 1 -0.0312,0 c -0.14786,0.2014 -0.35962,0.32934 -0.59375,0.375 -0.23413,0.0457 -0.48506,-0.002 -0.6875,-0.15625 -1.34443,-1.0218 -2.51369,-1.67283 -4.03125,-2.15625 -0.1942,-0.0618 -0.35572,-0.18089 -0.46875,-0.34375 -0.11303,-0.16286 -0.18863,-0.35845 -0.1875,-0.5625 0.001,-0.19898 0.0297,-0.41985 0.0625,-0.65625 z" />
+ <path
+ style="fill:none;stroke:url(#linearGradient15537-5);stroke-width:0.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 220.40065,247.42921 c 1.3319,1.37892 1.29257,3.57882 0.34306,4.70903"
+ id="path26223-2-7"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g16592">
+ <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"
+ width="16"
+ height="16"
+ x="488"
+ y="262" />
+ <g
+ id="g16579">
+ <rect
+ y="268.95908"
+ x="495.95065"
+ height="1"
+ width="2"
+ id="rect23532-1-0"
+ style="opacity:0.8;fill:#1e56ab;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;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 501.95064,269.22921 0,0.75008 0,2.99996 -3,1.5 c -3,1.5 -6.25,1.5 -10,1.49996 l -0.0183,-2.52715 c 0,0 3.366,-6.98108 4.33827,-8.04174 0.97227,-1.06066 4.00392,-2.08028 4.61579,-2.33915 3.72167,-0.006 4.09599,4.72641 4.06425,6.15804 z m -8,0.25 4.90625,-1.875 c 0.0715,-1.36645 -0.67378,-2.97927 -2.03429,-3.23624"
+ id="path23522-5"
+ sodipodi:nodetypes="scccccsccsccc" />
+ <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 493.95064,269.47921 4,-1.5 0.9375,-0.40625 3.0625,1.65625 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-5" />
+ <path
+ 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"
+ 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"
+ 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"
+ 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"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.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\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"
+ 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" />
+ <path
+ 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"
+ 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"
+ d="m 497.15108,270.57068 c -0.87852,0.21783 -1.75,-0.0997 -1.75,-0.67783 0,-0.57817 0.44856,-1.11322 1.32701,-1.33132 0.77415,-0.19217 1.49604,0.10015 1.66916,0.65891 0.16722,0.53968 -0.3266,1.12224 -1.24617,1.35024 z"
+ id="path27309-9"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="sssss" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:0.37383178"
+ d="m 492.06936,275.51839 0.98651,-0.0593"
+ id="path27317-2"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g14953">
+ <rect
+ y="198.9792"
+ x="4.9506397"
+ height="16"
+ width="16"
+ id="rect23018-5-4"
+ 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.94058502,0,0,0.94058502,0.9128606,12.74924)"
+ id="g56716">
+ <path
+ sodipodi:type="star"
+ style="fill:url(#linearGradient14951);fill-opacity:1;stroke:#000000;stroke-width:0.96882826;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path15855"
+ sodipodi:sides="5"
+ sodipodi:cx="13.700194"
+ sodipodi:cy="207.20645"
+ sodipodi:r1="7.1873641"
+ sodipodi:r2="3.3158474"
+ sodipodi:arg1="0.94697287"
+ sodipodi:arg2="1.5618338"
+ inkscape:flatsided="false"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="m 17.898641,213.04008 -4.168729,-2.51791 -4.280439,2.47993 1.106473,-4.74277 -3.6812884,-3.3046 4.8525664,-0.41328 2.005278,-4.52229 1.892578,4.48735 4.920618,0.50967 -3.682889,3.18662 z"
+ inkscape:transform-center-x="-0.010954063"
+ inkscape:transform-center-y="-0.74285516"
+ transform="matrix(1.0972098,0,0,1.0975406,-2.0923019,-19.740595)" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1.06316817;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0"
+ d="m 12.931855,202.51514 -1.201334,2.70994 c -0.137665,0.32193 -0.454082,0.55986 -0.800889,0.60222 l -2.9032248,0.26765 2.2358168,1.97391 c 0.261321,0.2395 0.380487,0.62447 0.300333,0.97022 l -0.667408,2.81032"
+ id="path15869"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ </g>
+ <g
+ transform="translate(-0.04936017,-0.02079917)"
+ style="display:inline;enable-background:new"
+ id="g16432">
+ <rect
+ y="199"
+ x="68"
+ height="16"
+ width="16"
+ id="rect23008-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" />
+ <g
+ style="display:inline"
+ transform="translate(-129.04638,24.90625)"
+ 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="g11015-1">
+ <path
+ style="fill:url(#linearGradient15744-9-8);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 205.54638,177.59375 -1,0 0,9 1,0 5,-3.75 0,-1.5 z"
+ id="path11017-5"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path11019-7"
+ d="m 205.54638,185.34375 0,-6.5 4.03125,3.01562"
+ style="fill:none;stroke:url(#linearGradient10982-8-5);stroke-width:1.10000002;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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ style="fill:url(#linearGradient16268-9);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new"
+ id="rect10822-0-7"
+ width="9.2000065"
+ height="2.1999984"
+ x="202.39999"
+ y="71.400002"
+ rx="0"
+ ry="1.4168683"
+ 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="cc"
+ style="fill:none;stroke:url(#linearGradient16302-5);stroke-width:1.00000012px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 72.27078,203.33478 0.475194,-7e-5"
+ id="path10824-4-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" />
+ </g>
+ <g
+ transform="translate(-0.04936017,-0.02079917)"
+ style="display:inline;enable-background:new"
+ id="g16424">
+ <rect
+ transform="scale(-1,1)"
+ y="198.89999"
+ x="-62.900002"
+ height="16"
+ width="16"
+ id="rect23008-0-8"
+ 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;enable-background:new"
+ transform="matrix(-1,0,0,1,259.94638,24.80625)"
+ 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="g11015-1-2">
+ <path
+ style="fill:url(#linearGradient15744-9-0-9);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 205.54638,177.59375 -1,0 0,9 1,0 5,-3.75 0,-1.5 z"
+ id="path11017-5-5"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path11019-7-9"
+ d="m 205.54638,178.84375 4.03125,3.01562"
+ style="fill:none;stroke:url(#linearGradient10982-8-9-5);stroke-width:1.10000002;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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ transform="matrix(0,1,-1,0,0,0)"
+ style="fill:url(#linearGradient16268-5-0);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline;enable-background:new"
+ id="rect10822-0-7-7"
+ width="9.2000065"
+ height="2.1999984"
+ x="202.29999"
+ y="-59.5"
+ rx="0"
+ ry="1.4168683"
+ 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="cc"
+ style="fill:none;stroke:url(#linearGradient16302-3-4);stroke-width:1.00000012px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 58.62922,203.23478 -0.475194,-7e-5"
+ id="path10824-4-2-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" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g56653">
+ <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"
+ style="opacity:0.3;color:#000000;fill:#0027b4;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path18242" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path38437-9"
+ 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"
+ style="color:#000000;fill:#000000;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="path18240"
+ d="m 289.95065,120.97921 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"
+ style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g27975"
+ style="display:inline;enable-background:new"
+ transform="translate(-0.04936017,-0.02079917)">
+ <rect
+ style="opacity:0;fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36400-0-73"
+ width="16"
+ height="16"
+ x="278"
+ y="115" />
+ <g
+ id="g36402-8-9"
+ transform="translate(186.99836,-42.1)">
+ <rect
+ style="fill:#acc373;fill-opacity:1;fill-rule:nonzero;stroke:#5d0606;stroke-width:1.79999995;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="rect36426-6-8"
+ width="2.0000153"
+ height="2.0000069"
+ x="102"
+ y="170"
+ rx="0"
+ ry="0" />
+ <g
+ id="g36404-0-04"
+ style="stroke:#1a1a1a;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new"
+ transform="translate(8.000015,151)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:url(#linearGradient27963-5);stroke-width:3.29999995;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 85.65162,18.243282 88.999985,16"
+ id="path36410-3-3"
+ 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="path36407-9-8"
+ d="m 88.999985,8 0,8"
+ style="fill:none;stroke:#00163c;stroke-width:3.29999995;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="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"
+ id="path36412-3-7"
+ d="M 94.99997,20 88.999985,16"
+ style="fill:none;stroke:#5d0606;stroke-width:3.29999995;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="cc" />
+ </g>
+ <rect
+ ry="0"
+ rx="0"
+ y="158"
+ x="96"
+ height="2.0000069"
+ width="2.0000153"
+ id="rect36416-1-8"
+ style="fill:none;stroke:#001e50;stroke-width:1.79999995;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"
+ 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="path36418-7-2"
+ d="m 97,159 0,8"
+ style="fill:none;stroke:#4c8ff4;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"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:url(#linearGradient27965-1);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 93.15039,169.65379 3.794367,-2.66484"
+ id="path36420-1-8"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path36424-2-5"
+ d="M 92.728285,169.42532 96.499985,166.75 96.5,159.5"
+ style="opacity:0.3;fill:none;stroke:url(#linearGradient27967-9);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"
+ 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"
+ id="path36428-6-8"
+ d="M 102.99998,171 97,167"
+ style="fill:none;stroke:#ef4e29;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"
+ sodipodi:nodetypes="cc" />
+ <rect
+ style="opacity:0.3;fill:none;stroke:#001e50;stroke-width:1.79999995;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="rect36432-1-2"
+ width="2.0000153"
+ height="2.0000069"
+ x="96"
+ y="158"
+ rx="0"
+ ry="0" />
+ <rect
+ style="fill:#4c8ff4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.3499999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36434-5-5"
+ width="2"
+ height="2"
+ x="96.000023"
+ y="158"
+ rx="0"
+ ry="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"
+ transform="matrix(1.3333333,0,0,1.3333343,3,147.66665)"
+ d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 z"
+ sodipodi:ry="1.5"
+ sodipodi:rx="1.5"
+ sodipodi:cy="14.5"
+ sodipodi:cx="70.5"
+ id="path36436-4-6"
+ style="opacity:0.5;fill:url(#radialGradient27969-8);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ 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 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 z"
+ sodipodi:ry="1.5"
+ sodipodi:rx="1.5"
+ sodipodi:cy="14.5"
+ sodipodi:cx="70.5"
+ id="path36438-7-62"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ sodipodi:type="arc"
+ transform="matrix(0.6666679,0,0,0.6666668,49.999915,157.33333)" />
+ <rect
+ ry="0"
+ rx="0"
+ y="170"
+ x="102"
+ height="2.0000069"
+ width="2.0000153"
+ id="rect36440-7-5"
+ style="opacity:0.3;fill:#acc373;fill-opacity:1;fill-rule:nonzero;stroke:#5d0606;stroke-width:1.79999995;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
+ ry="0"
+ rx="0"
+ y="170"
+ x="102.00002"
+ height="2"
+ width="2"
+ id="rect36442-2-0"
+ style="fill:#eb512e;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.3499999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ style="opacity:0.8"
+ id="g36444-2-2">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient27971-9);stroke-width:1.00000012;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 96.5,159.5 0,-1 1,0"
+ id="path36446-6-0"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.9;fill:none;stroke:url(#linearGradient27973-6);stroke-width:1.00000012;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 102.49999,171.5 0,-1 1,0"
+ id="path36450-1-8"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g56628">
+ <g
+ transform="translate(-0.04936017,-1.0207992)"
+ id="g18315"
+ style="display:inline;enable-background:new">
+ <path
+ inkscape:connector-curvature="0"
+ id="path18244-7"
+ style="opacity:0.3;color:#000000;fill:#45eb0a;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 269,122 0,2.25 1,0 0,2.75 1,0 0,-2.75 1,0 0,-2.25 -1,0 0,2 -1,0 0,-2 -1,0 z m 0,-6 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" />
+ <path
+ style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 269,116 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"
+ id="path38437-9-2"
+ inkscape:connector-curvature="0" />
+ <path
+ style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 269,122 0,2.25 1,0 0,2.75 1,0 0,-2.75 1,0 0,-2.25 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ id="path38435-3-8-1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ y="114.97919"
+ x="256.95062"
+ height="16"
+ width="16"
+ id="rect36400-0"
+ style="opacity:0;fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ transform="translate(-2.0730802,-0.12079917)"
+ id="g17954"
+ style="display:inline;enable-background:new">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:url(#linearGradient17973-0);stroke-width:3.29999995;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 261.67372,127.26538 3.34836,-2.24328"
+ id="path36410-3-3-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" />
+ <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="path36407-9"
+ d="m 264.99997,117 0,8"
+ style="fill:none;stroke:#00163c;stroke-width:3.29999995;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="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"
+ id="path36412-3"
+ d="m 270.99996,129 -5.99999,-4"
+ style="fill:none;stroke:#183c00;stroke-width:3.29999995;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="cc" />
+ <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="path36420-1-8-8"
+ d="m 261.17248,127.67589 3.79437,-2.66484"
+ style="fill:none;stroke:url(#linearGradient17975-1);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"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:none;stroke:#001e50;stroke-width:1.79999995;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="rect36416-1"
+ width="2.0000153"
+ height="2.0000069"
+ x="263.99997"
+ y="116"
+ rx="0"
+ ry="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#4c8ff4;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 264.99998,117 0,8"
+ id="path36418-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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ style="opacity:0.3;fill:none;stroke:url(#linearGradient17977-8);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 260.75037,127.44742 3.7717,-2.67532 2e-5,-7.25"
+ id="path36424-2-5-6"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="128"
+ x="269.99997"
+ height="2.0000069"
+ width="2.0000153"
+ id="rect36426-6"
+ style="fill:#acc373;fill-opacity:1;fill-rule:nonzero;stroke:#183c00;stroke-width:1.79999995;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
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#4ee420;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 270.99996,129 -5.99998,-4"
+ id="path36428-6"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="116"
+ x="263.99997"
+ height="2.0000069"
+ width="2.0000153"
+ id="rect36432-1"
+ style="opacity:0.3;fill:none;stroke:#001e50;stroke-width:1.79999995;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
+ ry="0"
+ rx="0"
+ y="116"
+ x="264"
+ height="2"
+ width="2"
+ id="rect36434-5"
+ style="fill:#4c8ff4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.3499999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.5;fill:url(#radialGradient17979-7);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ id="path36436-4"
+ sodipodi:cx="70.5"
+ sodipodi:cy="14.5"
+ sodipodi:rx="1.5"
+ sodipodi:ry="1.5"
+ d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 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"
+ inkscape:export-ydpi="90" />
+ <path
+ transform="matrix(0.6666679,0,0,0.6666668,217.99989,115.33333)"
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ id="path36438-7"
+ sodipodi:cx="70.5"
+ sodipodi:cy="14.5"
+ sodipodi:rx="1.5"
+ sodipodi:ry="1.5"
+ d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 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" />
+ <rect
+ style="opacity:0.3;fill:#acc373;fill-opacity:1;fill-rule:nonzero;stroke:#183c00;stroke-width:1.79999995;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="rect36440-7"
+ width="2.0000153"
+ height="2.0000069"
+ x="269.99997"
+ y="128"
+ rx="0"
+ ry="0" />
+ <rect
+ style="fill:#4ee51f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.3499999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36442-2"
+ width="2"
+ height="2"
+ x="270"
+ y="128"
+ rx="0"
+ ry="0" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient17981-0);stroke-width:1.00000012;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 264.49998,117.5 0,-1 1,0"
+ id="path36446-6"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.72000002;fill:none;stroke:url(#linearGradient17983-9);stroke-width:1.00000012;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 270.49997,129.5 0,-1 1,0"
+ id="path36450-1"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g56680">
+ <g
+ transform="translate(-0.04936017,-1.0207992)"
+ id="g18312"
+ style="display:inline;enable-background:new">
+ <path
+ inkscape:connector-curvature="0"
+ id="path11174-1-9"
+ style="opacity:0.3;color:#000000;fill:#f82516;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 311,122 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 m -1,-9 0,2.25 1,0 0,2.75 1,0 0,-2.75 1,0 0,-2.25 -1,0 0,2 -1,0 0,-2 -1,0 z" />
+ </g>
+ <rect
+ y="114.97919"
+ x="298.95062"
+ height="16"
+ width="16"
+ id="rect36400-0-73-7"
+ style="opacity:0;fill:#666666;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path38435-3-8"
+ d="m 310.95065,114.97921 0,2.25 1,0 0,2.75 1,0 0,-2.75 1,0 0,-2.25 -1,0 0,2 -1,0 0,-2 -1,0 z"
+ style="color:#000000;fill:#000000;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="path18240-3"
+ d="m 310.95065,120.97921 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"
+ style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ transform="translate(0.95063983,-0.12079917)"
+ id="g27760"
+ style="display:inline;enable-background:new">
+ <rect
+ style="fill:none;stroke:#183c00;stroke-width:1.79999995;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="rect36416-1-8-5"
+ width="2.0000153"
+ height="2.0000069"
+ x="302.98999"
+ y="116"
+ rx="0"
+ ry="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="128"
+ x="308.98999"
+ height="2.0000069"
+ width="2.0000153"
+ id="rect36426-6-8-0"
+ style="fill:#acc373;fill-opacity:1;fill-rule:nonzero;stroke:#5d0606;stroke-width:1.79999995;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: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="path36410-3-3-7-4"
+ d="m 300.65,127.2387 3.34836,-2.24328"
+ style="fill:none;stroke:url(#linearGradient27998-5);stroke-width:3.29999995;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="cc"
+ inkscape:connector-curvature="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\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path36407-9-8-3"
+ d="m 303.98998,117 0,8"
+ style="fill:none;stroke:#183c00;stroke-width:3.29999995;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="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:url(#linearGradient28000-5);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 300.14876,127.64921 3.79437,-2.66484"
+ id="path36420-1-8-8-6"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <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="path36412-3-7-3"
+ d="m 309.98997,129 -5.99999,-4"
+ style="fill:none;stroke:#5d0606;stroke-width:3.29999995;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="cc" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#4ee420;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 303.98999,117 0,8"
+ id="path36418-7-2-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"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="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\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path36424-2-5-6-9"
+ d="m 299.72665,127.42074 3.7717,-2.67532 2e-5,-7.25"
+ style="opacity:0.3;fill:none;stroke:url(#linearGradient28002-1);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"
+ sodipodi:nodetypes="ccc" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#ef4e29;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 309.98997,129 -5.99998,-4"
+ id="path36428-6-8-8"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <rect
+ ry="0"
+ rx="0"
+ y="116"
+ x="302.98999"
+ height="2.0000069"
+ width="2.0000153"
+ id="rect36432-1-2-2"
+ style="opacity:0.3;fill:none;stroke:#183c00;stroke-width:1.79999995;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
+ ry="0"
+ rx="0"
+ y="116"
+ x="302.99002"
+ height="2"
+ width="2"
+ id="rect36434-5-5-9"
+ style="fill:#4ee51f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.3499999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.5;fill:url(#radialGradient28004-7);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ id="path36436-4-6-0"
+ sodipodi:cx="70.5"
+ sodipodi:cy="14.5"
+ sodipodi:rx="1.5"
+ sodipodi:ry="1.5"
+ d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 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"
+ inkscape:export-ydpi="90" />
+ <path
+ transform="matrix(0.6666679,0,0,0.6666668,256.9899,115.33333)"
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;enable-background:new"
+ id="path36438-7-62-3"
+ sodipodi:cx="70.5"
+ sodipodi:cy="14.5"
+ sodipodi:rx="1.5"
+ sodipodi:ry="1.5"
+ d="m 72,14.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 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" />
+ <rect
+ style="opacity:0.3;fill:#acc373;fill-opacity:1;fill-rule:nonzero;stroke:#5d0606;stroke-width:1.79999995;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="rect36440-7-5-9"
+ width="2.0000153"
+ height="2.0000069"
+ x="308.98999"
+ y="128"
+ rx="0"
+ ry="0" />
+ <rect
+ style="fill:#eb512e;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.3499999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36442-2-0-6"
+ width="2"
+ height="2"
+ x="308.99002"
+ y="128"
+ rx="0"
+ ry="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path36446-6-0-8"
+ d="m 303.5,117.51562 0,-1 1,0"
+ style="opacity:0.8;fill:none;stroke:url(#linearGradient28006-8);stroke-width:1.00000012;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path36450-1-8-0"
+ d="m 309.47793,129.48277 0,-1 1,0"
+ style="opacity:0.9;fill:none;stroke:url(#linearGradient28008-2);stroke-width:1.00000012;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ 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">
+ <rect
+ y="198.9792"
+ x="4.9506397"
+ height="16"
+ width="16"
+ id="rect23018-5-4-4"
+ 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.94058502,0,0,0.94058502,0.9128606,12.74924)"
+ id="g56716-9">
+ <path
+ sodipodi:type="star"
+ style="fill:url(#linearGradient14951-4);fill-opacity:1;stroke:#341b00;stroke-width:0.96882826;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path15855-2"
+ sodipodi:sides="5"
+ sodipodi:cx="13.700194"
+ sodipodi:cy="207.20645"
+ sodipodi:r1="7.1873641"
+ sodipodi:r2="3.3158474"
+ sodipodi:arg1="0.94697287"
+ sodipodi:arg2="1.5618338"
+ inkscape:flatsided="false"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="m 17.898641,213.04008 -4.168729,-2.51791 -4.280439,2.47993 1.106473,-4.74277 -3.6812884,-3.3046 4.8525664,-0.41328 2.005278,-4.52229 1.892578,4.48735 4.920618,0.50967 -3.682889,3.18662 z"
+ inkscape:transform-center-x="-0.010954063"
+ inkscape:transform-center-y="-0.74285516"
+ transform="matrix(1.0972098,0,0,1.0975406,-2.0923019,-19.740595)" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1.06316817;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0"
+ d="m 12.931855,202.51514 -1.201334,2.70994 c -0.137665,0.32193 -0.454082,0.55986 -0.800889,0.60222 l -2.9032248,0.26765 2.2358168,1.97391 c 0.261321,0.2395 0.380487,0.62447 0.300333,0.97022 l -0.667408,2.81032"
+ id="path15869-5"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ </g>
+ <g
+ transform="translate(189,-229)"
+ id="g22900-8"
+ 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="rect22902-0"
+ width="16"
+ height="16"
+ x="257"
+ y="449" />
+ <g
+ transform="translate(14.081669,359)"
+ id="g22904-5"
+ style="opacity:0.6;stroke:#162d50">
+ <path
+ style="opacity:0.9;fill:none;stroke:#2d3239;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 253.41833,95.5 c 1.5,1.5 1.5,3.5 0,5"
+ id="path22906-2"
+ sodipodi:nodetypes="cc"
+ 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.9;fill:none;stroke:#2d3239;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 255.41833,93.5 c 2.75,2.75 2.75,6.25 0,9"
+ id="path22908-5"
+ sodipodi:nodetypes="cc"
+ 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" />
+ </g>
+ <path
+ style="opacity:0.9;fill:none;stroke:#e4e9f0;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 267.5,454.5 c 1.5,1.5 1.5,3.5 0,5"
+ id="path22910-1"
+ sodipodi:nodetypes="cc"
+ 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="ccccccccccccc"
+ style="fill:url(#linearGradient22933-6);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ d="m 264.58167,451.5 -1.08167,0 -3,3 c 0,-0.554 -0.446,-1 -1,-1 l -1,0 c -0.554,0 -1,0.446 -1,1 l 0,5 c 0,0.554 0.446,1 1,1 l 1,0 c 0.554,0 1,-0.446 1,-1 l 3,3 1.08167,0 0,-11 z"
+ id="path22912-6"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient22935-6);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ d="m 258.5,459.5 1,0 1,-1 3.25,3"
+ id="path22914-3"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path22916-2"
+ d="m 260.5,454.5 0,4.9091"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient22937-4);stroke-width:1;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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path22918-7"
+ d="m 258.5,455.5 1,0"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="cc"
+ 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="cc"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 262.59506,453.5 1,-1"
+ id="path22920-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
+ 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="cc"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 258.5,454.63598 1,0"
+ id="path22922-0"
+ 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="path22924-2"
+ d="m 262.59506,454.5 1,-1"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="cc"
+ 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"
+ sodipodi:nodetypes="cc"
+ id="path22926-3"
+ d="m 269.5,452.5 c 2.75,2.75 2.75,6.25 0,9"
+ style="opacity:0.9;fill:none;stroke:#e4e9f0;stroke-width:1.29999995;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:none;stroke:url(#linearGradient22939-8);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 263.5,452.5 0,9"
+ id="path22928-8"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path22931-5"
+ d="m 258.5,454.3 0,5.4"
+ style="fill:none;stroke:url(#linearGradient17039);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(210,-229)"
+ id="g22900-8-5"
+ 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="rect22902-0-6"
+ width="16"
+ height="16"
+ x="257"
+ y="449" />
+ <g
+ transform="translate(14.081669,359)"
+ id="g22904-5-2"
+ style="opacity:0.6;stroke:#162d50" />
+ <path
+ sodipodi:nodetypes="ccccccccccccc"
+ style="fill:url(#linearGradient22933-6-8);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ d="m 264.58167,451.5 -1.08167,0 -3,3 c 0,-0.554 -0.446,-1 -1,-1 l -1,0 c -0.554,0 -1,0.446 -1,1 l 0,5 c 0,0.554 0.446,1 1,1 l 1,0 c 0.554,0 1,-0.446 1,-1 l 3,3 1.08167,0 0,-11 z"
+ id="path22912-6-4"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient22935-6-2);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ d="m 258.5,459.5 1,0 1,-1 3.25,3"
+ id="path22914-3-7"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path22916-2-2"
+ d="m 260.5,454.5 0,4.9091"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient22937-4-1);stroke-width:1;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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path22918-7-7"
+ d="m 258.5,455.5 1,0"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="cc"
+ 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="cc"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 262.59506,453.5 1,-1"
+ id="path22920-0-4"
+ 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
+ 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="cc"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 258.5,454.63598 1,0"
+ id="path22922-0-2"
+ 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="path22924-2-7"
+ d="m 262.59506,454.5 1,-1"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient22939-8-6);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 263.5,452.5 0,9"
+ id="path22928-8-6"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path22931-5-7"
+ d="m 258.5,454.3 0,5.4"
+ style="fill:none;stroke:url(#linearGradient17172);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-42,-40)"
+ id="g22900-8-3"
+ 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="rect22902-0-4"
+ width="16"
+ height="16"
+ x="257"
+ y="449" />
+ <g
+ transform="translate(14.081669,359)"
+ id="g22904-5-8"
+ style="opacity:0.6;stroke:#162d50">
+ <path
+ style="opacity:0.9;fill:none;stroke:#333333;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 253.41833,95.5 c 1.5,1.5 1.5,3.5 0,5"
+ id="path22906-2-2"
+ sodipodi:nodetypes="cc"
+ 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.9;fill:none;stroke:#333333;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 255.41833,93.5 c 2.75,2.75 2.75,6.25 0,9"
+ id="path22908-5-8"
+ sodipodi:nodetypes="cc"
+ 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" />
+ </g>
+ <path
+ style="opacity:0.9;fill:none;stroke:#eaeaea;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 267.5,454.5 c 1.5,1.5 1.5,3.5 0,5"
+ id="path22910-1-6"
+ sodipodi:nodetypes="cc"
+ 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="ccccccccccccc"
+ style="opacity:0.8;fill:url(#linearGradient22933-6-87);fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ d="m 264.58167,451.5 -1.08167,0 -3,3 c 0,-0.554 -0.446,-1 -1,-1 l -1,0 c -0.554,0 -1,0.446 -1,1 l 0,5 c 0,0.554 0.446,1 1,1 l 1,0 c 0.554,0 1,-0.446 1,-1 l 3,3 1.08167,0 0,-11 z"
+ id="path22912-6-9"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient22935-6-22);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ d="m 258.5,459.5 1,0 1,-1 3.25,3"
+ id="path22914-3-3"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path22916-2-6"
+ d="m 260.5,454.5 0,4.9091"
+ style="opacity:0.5;fill:none;stroke:url(#linearGradient22937-4-8);stroke-width:1;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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path22918-7-5"
+ d="m 258.5,455.5 1,0"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="cc"
+ 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="cc"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 262.59506,453.5 1,-1"
+ id="path22920-0-8"
+ 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
+ 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="cc"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 258.5,454.63598 1,0"
+ id="path22922-0-0"
+ 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="path22924-2-2"
+ d="m 262.59506,454.5 1,-1"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="cc"
+ 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"
+ sodipodi:nodetypes="cc"
+ id="path22926-3-1"
+ d="m 269.5,452.5 c 2.75,2.75 2.75,6.25 0,9"
+ style="opacity:0.9;fill:none;stroke:#eaeaea;stroke-width:1.29999995;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:none;stroke:url(#linearGradient22939-8-3);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 263.5,452.5 0,9"
+ id="path22928-8-5"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path22931-5-2"
+ d="m 258.5,454.3 0,5.4"
+ style="fill:none;stroke:url(#linearGradient17172-9);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g17563">
+ <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"
+ width="16"
+ height="16"
+ x="215"
+ y="430" />
+ <g
+ id="g17546">
+ <path
+ style="opacity:0.6;fill:none;stroke:#643200;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 227.5,433.5 c 2.75,2.75 2.75,6.25 0,9"
+ id="path22908-5-0-4"
+ sodipodi:nodetypes="cc"
+ 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.6;fill:none;stroke:#633300;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 225.5,435.5 c 1.5,1.5 1.5,3.5 0,5"
+ id="path22906-2-9-6"
+ sodipodi:nodetypes="cc"
+ 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
+ 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="cc"
+ id="path22910-1-4"
+ d="m 225.5,435.5 c 1.5,1.5 1.5,3.5 0,5"
+ style="opacity:0.9;fill:none;stroke:url(#linearGradient17582);stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path22912-6-7"
+ d="m 222.58167,432.5 -1.08167,0 -3,3 c 0,-0.554 -0.446,-1 -1,-1 l -1,0 c -0.554,0 -1,0.446 -1,1 l 0,5 c 0,0.554 0.446,1 1,1 l 1,0 c 0.554,0 1,-0.446 1,-1 l 3,3 1.08167,0 0,-11 z"
+ style="fill:url(#linearGradient17584);fill-opacity:1;fill-rule:nonzero;stroke:#2b1600;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.84313725;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
+ sodipodi:nodetypes="ccccccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path22914-3-6"
+ d="m 216.5,440.5 1,0 1,-1 3.25,3"
+ style="fill:none;stroke:url(#linearGradient17586);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray: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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ style="opacity:0.65263157;fill:none;stroke:url(#linearGradient17588);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 218.5,435.5 0,4.9091"
+ id="path22916-2-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"
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 216.5,436.5 1,0"
+ id="path22918-7-2" />
+ <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="path22920-0-2"
+ d="m 220.59506,434.5 1,-1"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path22922-0-22"
+ d="m 216.5,435.63598 1,0"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="cc"
+ 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="cc"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 220.59506,435.5 1,-1"
+ id="path22924-2-9"
+ 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="opacity:0.9;fill:none;stroke:url(#linearGradient17590);stroke-width:1.29999995;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 227.5,433.5 c 2.75,2.75 2.75,6.25 0,9"
+ id="path22926-3-9"
+ sodipodi:nodetypes="cc"
+ 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="path22928-8-7"
+ d="m 221.5,433.5 0,9"
+ style="fill:none;stroke:url(#linearGradient17592);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient17594);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 216.5,435.3 0,5.4"
+ id="path22931-5-72" />
+ <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="cc"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 225.37642,435.40307 0.60225,0.61872"
+ id="path22922-0-22-4"
+ 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"
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 227.40936,433.37013 0.51386,0.59663"
+ id="path22922-0-22-2"
+ 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" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g17941">
+ <rect
+ transform="scale(-1,1)"
+ y="220.00047"
+ x="-546"
+ height="16"
+ width="16"
+ id="rect14357-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="g17935">
+ <rect
+ style="fill:#ec0606;fill-opacity:1;fill-rule:nonzero;stroke:#910000;stroke-width:0.80000001;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"
+ id="rect43394-5-7"
+ width="6"
+ height="2"
+ x="540.12811"
+ y="231.61429"
+ rx="0.79505396"
+ ry="0.79505396" />
+ <path
+ sodipodi:nodetypes="czszcccc"
+ id="path14368-1"
+ 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:7.40000034;display:inline"
+ d="m 542.6613,230.54031 -4.34213,0.008 c -5.18824,0.0101 -5.3353,-2.04831 -3.33529,-4.04831 0.96487,-0.96488 3.61611,-2.89515 -1.50001,-5 m 6.83689,6.08925 2.34054,2.95106 m -2.32899,2.96017 2.32899,-2.96017"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 542.6613,230.54031 -4.34213,0.008 c -5.18824,0.0106 -5.3353,-2.04783 -3.33529,-4.04783 0.96487,-0.96488 3.83708,-2.76256 -1.50001,-5 m 6.83689,6.08877 2.34054,2.95106 m -2.32899,2.96017 2.32899,-2.96017"
+ style="fill:none;stroke:url(#linearGradient17932);stroke-width:1.50000143;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:7.40000034;display:inline"
+ id="path14375-4"
+ sodipodi:nodetypes="czszcccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ ry="0.79505396"
+ rx="0.79505396"
+ y="220.375"
+ x="530.3125"
+ height="2"
+ width="6"
+ id="rect43396-5-4"
+ style="fill:#6996d7;fill-opacity:1;fill-rule:nonzero;stroke:#143564;stroke-width:0.80000001;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" />
+ </g>
+ </g>
+ <g
+ id="g20086">
+ <rect
+ y="598"
+ x="299"
+ height="16"
+ width="16"
+ id="rect25569-8"
+ 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(1.1,-0.09992002)"
+ id="g20068">
+ <rect
+ y="605.5"
+ x="-312.5"
+ height="7.0000267"
+ width="10"
+ id="rect15044-4"
+ style="fill:url(#linearGradient20080);fill-opacity:1;fill-rule:nonzero;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: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="scale(-1,1)" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path15046-4"
+ style="fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 304.49848,605.5625 0,-2 c 0,-2 -0.62933,-3 -2.51731,-3.00008 -1.2779,5e-5 -2.17039,0.23501 -2.53494,1.78073"
+ 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="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient20199);stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 304.49848,605.5625 0,-2.25 c 0,-1.75 -0.62933,-2.75 -2.51734,-2.75008 -1.27677,5e-5 -2.05659,0.20629 -2.29807,1.20103"
+ id="path15049-9"
+ sodipodi:nodetypes="cscc"
+ 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
+ ry="0"
+ rx="0"
+ y="606.5"
+ x="303.5"
+ height="5"
+ width="8"
+ id="rect15051-2"
+ style="fill:none;stroke:url(#linearGradient20084);stroke-width:1.00000024;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="path19016-6"
+ d="m 304,607.5 7.5,0"
+ style="opacity:0.5;fill:none;stroke:#939dac;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.5;fill:none;stroke:#939dac;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 304,609.5 7.5,0"
+ id="path19018-0" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path19020-2"
+ d="m 304,611.5 7.5,0"
+ style="opacity:0.5;fill:none;stroke:#939dac;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
+ <rect
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36041-6"
+ width="1"
+ height="2.0000124"
+ x="307"
+ y="608" />
+ <rect
+ y="608"
+ x="307"
+ height="0.99994379"
+ width="0.99998754"
+ id="rect36043-2"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 308,608 0,2 -1,0 0,1 1,0 1,0 0,-1 0,-2 -1,0 z"
+ id="path36045-7"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(21,0)"
+ style="display:inline;enable-background:new"
+ id="g20086-7">
+ <rect
+ y="598"
+ x="299"
+ height="16"
+ width="16"
+ id="rect25569-8-3"
+ 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(1.1,-0.09992002)"
+ id="g20068-2">
+ <rect
+ y="605.5"
+ x="-312.5"
+ height="7.0000267"
+ width="10"
+ id="rect15044-4-1"
+ style="fill:url(#linearGradient20080-5);fill-opacity:1;fill-rule:nonzero;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: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="scale(-1,1)" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path15046-4-9"
+ style="fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 310.5,605.5 0,-2 c 0,-2 -0.75,-3 -3,-3.00008 -2.25,8e-5 -3,1.00008 -3,3.00008 l 0,2"
+ 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"
+ style="fill:none;stroke:url(#linearGradient20082-4);stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 310.5,605.5 c 0,0 0,-2.25 0,-2.25 0,-1.75 -0.75,-2.75 -3.00003,-2.75008 C 305.25,600.5 304.5,601.5 304.5,603.25 l 0,2.25005"
+ id="path15049-9-8"
+ sodipodi:nodetypes="csccc"
+ 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
+ ry="0"
+ rx="0"
+ y="606.5"
+ x="303.5"
+ height="5"
+ width="8"
+ id="rect15051-2-5"
+ style="fill:none;stroke:url(#linearGradient20084-9);stroke-width:1.00000024;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="path19016-6-0"
+ d="m 304,607.5 7.5,0"
+ style="opacity:0.5;fill:none;stroke:#939dac;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.5;fill:none;stroke:#939dac;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 304,609.5 7.5,0"
+ id="path19018-0-2" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path19020-2-9"
+ d="m 304,611.5 7.5,0"
+ style="opacity:0.5;fill:none;stroke:#939dac;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
+ <rect
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect36041-6-4"
+ width="1"
+ height="2.0000124"
+ x="307"
+ y="608" />
+ <rect
+ y="608"
+ x="307"
+ height="0.99994379"
+ width="0.99998754"
+ id="rect36043-2-8"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 308,608 0,2 -1,0 0,1 1,0 1,0 0,-1 0,-2 -1,0 z"
+ id="path36045-7-1"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(-105.02687,272.93951)"
+ style="display:inline;enable-background:new"
+ id="g17107">
+ <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"
+ width="16"
+ height="16"
+ x="299"
+ y="325" />
+ <g
+ id="g17099">
+ <path
+ style="fill:url(#linearGradient16783-1-6-0-2);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;enable-background:new"
+ d="M 309.7702,332.24765 304.5,337.5 l -1,0 -1,1 -1,0 0,-1 1,-1 0,-1 5.2702,-5.25235 z"
+ id="path18700-1-3-9"
+ sodipodi:nodetypes="cccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc"
+ id="path17007-7"
+ d="M 309.7702,332.24765 304.5,337.5 l -1,0 -1,1 -1,0 0,-1 1,-1 0,-1 5.2702,-5.25235 z"
+ style="fill:none;stroke:#000000;stroke-width:0.69999999;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new" />
+ <path
+ sodipodi:nodetypes="ccszsccc"
+ id="path18711-5-8-1"
+ d="m 310.5,333.5 0,-2.75 c 1.1224,0 1.75,0 2.5,-0.75 0.75,-0.75 0.75,-2.25 0,-3 -0.75,-0.75 -2.25,-0.75 -3,0 -0.75,0.75 -0.75,1.49506 -0.75,2.5 l -2.75,0 4,4 z"
+ style="fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:#1a1a1a;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:transform-center-x="-1.4435745"
+ inkscape:transform-center-y="-1.4192649"
+ style="fill:url(#linearGradient16778-3-5-3-2);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;enable-background:new"
+ d="m 309.22323,329.79745 c -0.11594,-0.12547 0.0486,-1.2642 0.81343,-2.11918 1.04731,-1.1688 1.89745,-0.8692 1.99021,-0.61778 1.02063,2.76644 -1.73024,3.89859 -2.80364,2.73696 z"
+ id="path18713-4-2-0"
+ sodipodi:nodetypes="csss"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path18715-9-8-1"
+ d="m 308.26612,330.5 c 0,0 0.25,0 0.25,0 l 0,-1"
+ style="opacity:0.98000004;fill:none;stroke:url(#linearGradient16775-4-9-5-6);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ 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;display:inline;enable-background:new"
+ d="m 303.25,335.75 4.17237,-4.0625"
+ id="path18705-8-4-0"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ transform="translate(-42,231)"
+ style="display:inline;enable-background:new"
+ id="g17942-1">
+ <rect
+ y="304"
+ x="278"
+ height="16"
+ width="16"
+ id="rect22048-0-1-2"
+ style="opacity:0.01000001;fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.89999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g17930-6">
+ <rect
+ y="305.5"
+ x="281.5"
+ height="6.0211244"
+ width="9.0000076"
+ id="rect22050-0-1-6"
+ style="opacity:0.6;fill:#ffd6aa;fill-opacity:1;fill-rule:evenodd;stroke:#2b1600;stroke-width:0.40000001;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
+ sodipodi:nodetypes="ccccc"
+ id="path22056-3-7-1"
+ d="m 282.5,316.5 3,3 3,-3 -3,-3 -3,3 z"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="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"
+ d="m 282.75,316.5 2.75,2.75 2.75,-2.75 -2.75,-2.75 -2.75,2.75 z"
+ id="path22058-8-8-7"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path22060-3-9-9"
+ d="m 283.5,316.5 2,-2 2,2 -2,2 -2,-2 z"
+ style="fill:none;stroke:url(#linearGradient18148);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path22157-2-9-1"
+ d="m 287.75,308.25 0,0.5 2.5,2.5 0.5,0 2.5,-2.5 0,-0.5 -2.5,-2.5 -0.5,0 -2.5,2.5 z"
+ style="fill:none;stroke:#552c00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#e98316;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 288,308.5 2.5,2.5 2.5,-2.5 -2.5,-2.5 -2.5,2.5 z"
+ id="path22159-1-9-5"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path22161-4-8-9"
+ d="M 288.64504,308.5 290.5,306.66161 292.35496,308.5 290.5,310.36049 z"
+ style="fill:none;stroke:url(#linearGradient17904-1);stroke-width:0.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 278.75,308.25 0,0.5 2.5,2.5 0.5,0 2.5,-2.5 0,-0.5 -2.5,-2.5 -0.5,0 -2.5,2.5 z"
+ id="path22208-0-8-1"
+ sodipodi:nodetypes="ccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path22212-5-4-4"
+ d="m 279,308.5 2.5,2.5 2.5,-2.5 -2.5,-2.5 z"
+ style="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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="fill:none;stroke:url(#linearGradient17893-5);stroke-width:0.89999998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M 279.64062,308.5 281.5,306.66406 283.35547,308.5 281.5,310.375 z"
+ id="path22214-3-8-8"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g16806">
+ <rect
+ y="472"
+ x="257"
+ height="16"
+ width="16"
+ id="rect35680"
+ 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:transform-center-y="2.2787562"
+ inkscape:transform-center-x="-0.78726"
+ id="g35844"
+ transform="translate(-186,256.02369)"
+ style="opacity:0.9;display:inline;enable-background:new">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path35846"
+ d="m 454.5,218.5 c -1.25,-1.5 -2.5,-1.5 -4,1 -1.5,-2.5 -2.75,-2.5 -4,-1"
+ style="opacity:0.85;fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#f2f2f2;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 454.5,218.5 c -1.25,-1.5 -2.5,-1.5 -4,1 -1.5,-2.5 -2.75,-2.5 -4,-1"
+ id="path35848"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path35862"
+ d="m 264.5,485.5 -1,-1 -2,2 -2,-2 -1,1.02369"
+ style="opacity:0.76499999;fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:0.89999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 264.5,485.5 -1,-1 -2,2 -2,-2 -1,1.02369"
+ id="path35864"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="translate(-21,21)"
+ id="g38276">
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.85;fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 292.5,459.5 c -1.25,-1.5 -3.5,-1.5 -5,1 -1.5,-2.5 -3.75,-2.5 -5,-1"
+ id="path35702"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path35704"
+ d="m 292.5,459.5 c -1.25,-1.5 -3.5,-1.5 -5,1 -1.5,-2.5 -3.75,-2.5 -5,-1"
+ style="fill:none;stroke:#ececec;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ <path
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0"
+ d="m 266.53125,480.65625 -0.0312,0.9375 m -0.85937,-1.07813 c 0.49634,0.0684 0.8328,0.24341 1.79687,0"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ id="path16745" />
+ <path
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0"
+ d="m 264.46875,474.79687 -0.0312,0.9375 m -0.85937,-1.07813 c 0.49634,0.0684 0.8328,0.24341 1.79687,0"
+ style="fill:none;stroke:#f0f0f0;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ 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">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc"
+ id="path45378-1-5-0"
+ d="m 367.75,440.75 1.75,-1.5 2.5,5.25 1.75,-1 -2.25,-5 2.5,0 -6.25,-6.25 z"
+ style="fill:url(#linearGradient17833-9);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="430"
+ x="362"
+ height="16"
+ width="16"
+ id="rect45374-0-5-0"
+ 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" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0"
+ id="path17835-6"
+ d="m 367.5,431.5 7,7.25 -3,0 2.5,4.75 -1.75,1 -2.5,-5 -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" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path17845-4"
+ d="m 368.34375,433.75 0,5.75"
+ style="fill:none;stroke:#ffffff;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ <g
+ transform="translate(84,0)"
+ style="display:inline;enable-background:new"
+ id="g17847-9">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc"
+ id="path45378-1-5-6"
+ d="m 367.75,440.75 1.75,-1.5 2.5,5.25 1.75,-1 -2.25,-5 2.5,0 -6.25,-6.25 z"
+ style="fill:url(#linearGradient17833-8);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="430"
+ x="362"
+ height="16"
+ width="16"
+ id="rect45374-0-5-6"
+ 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" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0"
+ id="path17835-7"
+ d="m 367.5,431.5 7,7.25 -3,0 2.5,4.75 -1.75,1 -2.5,-5 -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" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path17845-9"
+ d="m 368.34375,433.75 0,5.75"
+ style="fill:none;stroke:#ffffff;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g10534-1"
+ transform="translate(189.0161,-397)">
+ <rect
+ y="428"
+ x="193.9839"
+ height="16"
+ width="16"
+ id="rect20642-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
+ transform="translate(-29.016109,339.00751)"
+ id="g20606-2">
+ <g
+ transform="translate(-199.98388,-106)"
+ id="g10953-7">
+ <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="cccccccccccccccccccccccccccccccccccccc"
+ style="fill:none;stroke:#000000;stroke-width:1.70000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 429.9998,196.99249 0,1.625 c -0.53409,0.12195 -1.02562,0.33162 -1.46875,0.625 l -1.53125,-1.25 -1,1 1.25,1.53125 c -0.29338,0.44313 -0.50305,0.93466 -0.625,1.46875 l -1.625,0 0,2 1.625,0 c 0.12195,0.53409 0.33162,1.02562 0.625,1.46875 l -1.25,1.53125 1,1 1.53125,-1.25 c 0.44313,0.29338 0.93466,0.50305 1.46875,0.625 l 0,1.625 2,0 0,-1.625 c 0.53409,-0.12195 1.02562,-0.33162 1.46875,-0.625 l 1.53125,1.25 1,-1 -1.25,-1.53125 c 0.29338,-0.44313 0.50305,-0.93466 0.625,-1.46875 l 1.625,0 0,-2 -1.625,0 c -0.12195,-0.53409 -0.33162,-1.02562 -0.625,-1.46875 l 1.25,-1.53125 -1,-1 -1.53125,1.25 c -0.44313,-0.29338 -0.93466,-0.50305 -1.46875,-0.625 l 0,-1.625 -2,0 z m -1,4 4,0 0,4 -4,0 0,-4 z"
+ id="path10955-5"
+ 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"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccc"
+ id="path10957-4"
+ d="m 429.9998,196.99249 0,1.625 c -0.53409,0.12195 -1.02562,0.33162 -1.46875,0.625 l -1.53125,-1.25 -1,1 1.25,1.53125 c -0.29338,0.44313 -0.50305,0.93466 -0.625,1.46875 l -1.625,0 0,2 1.625,0 c 0.12195,0.53409 0.33162,1.02562 0.625,1.46875 l -1.25,1.53125 1,1 1.53125,-1.25 c 0.44313,0.29338 0.93466,0.50305 1.46875,0.625 l 0,1.625 2,0 0,-1.625 c 0.53409,-0.12195 1.02562,-0.33162 1.46875,-0.625 l 1.53125,1.25 1,-1 -1.25,-1.53125 c 0.29338,-0.44313 0.50305,-0.93466 0.625,-1.46875 l 1.625,0 0,-2 -1.625,0 c -0.12195,-0.53409 -0.33162,-1.02562 -0.625,-1.46875 l 1.5,-1.78125 -1,-1 -1.78125,1.5 c -0.44313,-0.29338 -0.93466,-0.50305 -1.46875,-0.625 l 0,-1.625 -2,0 z m -1,4 4,0 0,4 -4,0 0,-4 z"
+ style="fill:url(#linearGradient20796-9);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 434.9998,198.49249 -1.5,1.25 m -2,-2.25 -1,0 0,1.5 c -0.35104,0.0802 -1.01806,0.29269 -1.5172,0.50569 m -1.49,1.50752 c -0.20864,0.49552 -0.41426,1.14284 -0.4928,1.48679 l -1.5,0 0,1 m 1.5,-5 -0.5,0.5 m 1.25,6.5 -1.25,1.5 m 6.5,-5.5 0,3.5 -3.5,0 m -3,-6 0.5,-0.5 1.5,1.25"
+ style="fill:none;stroke:#f9f9f9;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0"
+ id="path10959-0"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="translate(-199.98388,-106)"
+ id="g10961-1">
+ <rect
+ ry="0"
+ rx="0"
+ y="202.46629"
+ x="430.49979"
+ height="8.1236582"
+ width="7.0000763"
+ id="rect10963-2"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;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" />
+ <path
+ d="m 432.53795,204.5065 2.96201,0 m -2.96201,1.993 2.96201,0 m -2.96201,1.993 2.96201,0"
+ style="fill:none;stroke:#000000;stroke-width:0.99999988px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ id="path10965-7"
+ 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" />
+ <rect
+ ry="0"
+ rx="0"
+ y="202.48912"
+ x="430.49661"
+ height="8.0067444"
+ width="7.0067482"
+ id="rect10967-1"
+ style="fill:none;stroke:url(#linearGradient20798-1);stroke-width:0.99325603;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\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ </g>
+ </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">
+ <rect
+ y="325"
+ x="299"
+ height="16"
+ width="16.000002"
+ id="rect44300-0-5-3-4"
+ style="opacity:0;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g81149-2">
+ <path
+ sodipodi:nodetypes="cssssssssssssssscssc"
+ inkscape:connector-curvature="0"
+ id="path41299-1-2-7-4-0"
+ d="m 306.46211,325.45009 c -1.82601,0 -3.30699,1.48105 -3.30699,3.30711 0,0.25952 0.0379,0.51035 0.087,0.75425 0.18833,0.93505 0.24637,1.73179 -0.11603,2.43677 -0.32404,0.63034 -0.67881,0.97731 -1.45039,1.27638 -1.27734,0.49511 -2.17564,1.6304 -2.17564,3.04602 0,0.7411 0.24647,1.42826 0.6672,1.97265 0.21236,0.27479 0.1962,0.24789 0.29008,0.34806 0.60044,0.64074 1.56724,0.98341 2.29168,0.95729 0.74932,-0.027 1.28404,-0.28854 1.8855,-0.60911 0.58287,-0.31066 0.97831,-0.70633 1.82755,-0.69624 0.70498,0.008 1.33214,0.39548 1.88546,0.75426 0.55206,0.35795 1.29426,0.55886 1.8275,0.55114 1.8258,-0.0264 3.30697,-1.48104 3.30697,-3.30711 0,-1.23932 -0.68675,-2.33495 -1.71151,-2.87196 -0.78932,-0.41364 -1.71989,-0.83441 -2.11757,-1.47945 -0.44817,-0.72695 0.029,-2.46582 0.029,-2.46582 0.0441,-0.21523 0.087,-0.43896 0.087,-0.66722 0,-1.82606 -1.48098,-3.30711 -3.30698,-3.30711 z"
+ style="fill:url(#linearGradient80406-8);fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.89999998;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="cscsscc"
+ inkscape:connector-curvature="0"
+ id="path15475-1-1-9"
+ d="m 306.46211,326.3494 c -1.34707,0 -2.40772,1.06069 -2.40772,2.4078 0,0.17324 0.0147,0.36498 0.058,0.5802 0.2006,0.99599 0.30102,2.03645 -0.20306,3.017 -0.3838,0.74661 -1.01301,1.33313 -1.91455,1.68257 -0.98238,0.38077 -1.59548,1.19286 -1.59548,2.23374 0.0793,1.22982 0.59501,1.65939 1.12899,2.05552"
+ style="fill:none;stroke:url(#linearGradient80403-6);stroke-width:0.99999988;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ d="m 306.5,333.5 -4,3 m 4,-3 4,3 m -4,-8 0,5"
+ style="fill:none;stroke:#acc1f5;stroke-width:2.29999995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ id="path16558"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path15730-0-3-9-7"
+ style="fill:none;stroke:#474747;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 306.5,333.5 -4,3 m 4,-3 4,3 m -4,-8 0,5" />
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline;enable-background:new"
+ id="rect16285-9-59-6-8-3"
+ width="2.0172396"
+ height="2.0000157"
+ x="305.48901"
+ y="327.52499" />
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline;enable-background:new"
+ id="rect16285-9-59-6-82-7"
+ width="2.0172396"
+ height="2.0000157"
+ x="301.52026"
+ y="335.49374" />
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline;enable-background:new"
+ id="rect16285-9-59-6-9-2"
+ width="2.0172396"
+ height="2.0000157"
+ x="309.49374"
+ y="335.49374" />
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;fill-rule:nonzero;stroke:#0b1728;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0.5;display:inline;enable-background:new"
+ id="rect16285-9-59-6-1-6"
+ width="2.0172396"
+ height="2.0000157"
+ x="305.52499"
+ 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
+ style="display:inline;enable-background:new"
+ id="g16724-8-3">
+ <rect
+ y="598"
+ x="152"
+ height="16"
+ width="16"
+ id="rect38813-3-2"
+ 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" />
+ <g
+ transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,76.587007,362.72598)"
+ id="g10876-8-5-8-64-4"
+ style="display:inline;enable-background:new">
+ <path
+ style="fill:url(#linearGradient16663-3-0-8);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.89999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 226.05286,111.6246 3.53553,0 1e-5,-3.53553 2.82843,0 0,3.53553 3.53553,0 -1e-5,2.82843 -3.53553,0 0,3.53553 -2.82843,0 0,-3.53553 -3.53553,0 z"
+ id="path10878-4-0-1-4-6"
+ sodipodi:nodetypes="ccccccccccccc"
+ 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="cc"
+ inkscape:connector-curvature="0"
+ id="path16661-5-1-6"
+ d="m 235.06847,113.56915 0,-1.06066"
+ style="fill:none;stroke:#d4d4d4;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path16659-5-9-6"
+ d="m 230.47227,114.62981 0,2.47487"
+ style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path16657-8-5-2"
+ d="m 230.47227,108.97295 0,2.47488"
+ style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path10880-7-5-7-5-9"
+ d="m 226.93674,112.50849 0,1.06066"
+ style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ </g>
+ <g
+ transform="translate(252,21)"
+ style="display:inline;enable-background:new"
+ id="g16724-8-1">
+ <rect
+ y="598"
+ x="152"
+ height="16"
+ width="16"
+ id="rect38813-3-1"
+ 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" />
+ <g
+ transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,76.587007,362.72598)"
+ id="g10876-8-5-8-64-9"
+ style="display:inline;enable-background:new">
+ <path
+ style="fill:url(#linearGradient16663-3-0-0);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.89999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 224.63864,111.6246 4.94975,0 0,-4.94974 2.82843,0 1e-5,4.94974 4.94973,0 -1e-5,2.82843 -4.94973,0 0,4.94975 -2.82843,0 0,-4.94975 -4.94975,0 z"
+ id="path10878-4-0-1-4-9"
+ sodipodi:nodetypes="ccccccccccccc"
+ 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="cc"
+ inkscape:connector-curvature="0"
+ id="path16661-5-1-5"
+ d="m 236.48268,113.56915 0,-1.06066"
+ style="fill:none;stroke:#d4d4d4;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path16659-5-9-5"
+ d="m 230.47227,114.62981 0,3.88908"
+ style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path16657-8-5-5"
+ d="m 230.47227,107.55874 0,3.88909"
+ style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path10880-7-5-7-5-6"
+ d="m 225.52253,112.50849 0,1.06066"
+ style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ </g>
+ <g
+ id="g27438">
+ <g
+ transform="translate(0,-21)"
+ id="g23604">
+ <g
+ style="fill:#321900"
+ id="g23590">
+ <rect
+ transform="scale(-1,-1)"
+ y="-602"
+ x="-258"
+ height="2"
+ width="1"
+ id="rect23464"
+ style="fill:#321900;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ transform="scale(-1,-1)"
+ style="fill:#321900;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23466"
+ width="1"
+ height="2"
+ x="-258"
+ y="-606" />
+ <rect
+ style="fill:#321900;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23548"
+ width="1"
+ height="2"
+ x="-273"
+ y="-602"
+ transform="scale(-1,-1)" />
+ <rect
+ y="-606"
+ x="-273"
+ height="2"
+ width="1"
+ id="rect23550"
+ style="fill:#321900;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="scale(-1,-1)" />
+ <rect
+ y="-268"
+ x="598"
+ height="2"
+ width="1"
+ id="rect23472"
+ style="fill:#321900;fill-opacity:1;fill-rule:nonzero;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
+ transform="matrix(0,1,-1,0,0,0)"
+ style="fill:#321900;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23474"
+ width="1"
+ height="2"
+ x="598"
+ y="-264" />
+ <rect
+ transform="matrix(0,1,-1,0,0,0)"
+ style="fill:#321900;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23476"
+ width="1"
+ height="2"
+ x="598"
+ y="-271.99207" />
+ <rect
+ y="-259.99207"
+ x="598"
+ height="2"
+ width="1"
+ id="rect23480"
+ style="fill:#321900;fill-opacity:1;fill-rule:nonzero;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
+ transform="matrix(0,1,-1,0,0,0)"
+ style="fill:#321900;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23540"
+ width="1"
+ height="2"
+ x="607"
+ y="-268" />
+ <rect
+ y="-264"
+ x="607"
+ height="2"
+ width="1"
+ id="rect23542"
+ style="fill:#321900;fill-opacity:1;fill-rule:nonzero;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="-271.99207"
+ x="607"
+ height="2"
+ width="1"
+ id="rect23544"
+ style="fill:#321900;fill-opacity:1;fill-rule:nonzero;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
+ transform="matrix(0,1,-1,0,0,0)"
+ style="fill:#321900;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23546"
+ width="1"
+ height="2"
+ x="607"
+ y="-259.99207" />
+ </g>
+ <g
+ id="g23572">
+ <rect
+ transform="matrix(0,-1,-1,0,0,0)"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect23461"
+ width="1"
+ height="2"
+ x="-608"
+ y="-270" />
+ <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="rect23468"
+ width="1"
+ height="2"
+ x="-273"
+ y="-600" />
+ <rect
+ transform="scale(-1,-1)"
+ y="-604"
+ x="-273"
+ height="2"
+ width="1"
+ id="rect23470"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ y="-266"
+ x="-608"
+ height="2"
+ width="1"
+ id="rect23478"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ 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"
+ id="rect23482"
+ width="1"
+ height="2"
+ x="-608"
+ y="-262" />
+ <rect
+ y="-262"
+ x="598"
+ height="2"
+ width="1"
+ id="rect23529"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ 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"
+ id="rect23531"
+ width="1"
+ height="2"
+ x="598"
+ y="-266" />
+ <rect
+ y="-270"
+ x="598"
+ height="2"
+ width="1"
+ id="rect23533"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ transform="matrix(0,1,-1,0,0,0)" />
+ <rect
+ y="-273"
+ x="-608"
+ height="1"
+ width="2"
+ id="rect23535"
+ style="fill:#ff982a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ transform="matrix(0,-1,-1,0,0,0)" />
+ <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="rect23525"
+ width="1"
+ height="2"
+ x="-258"
+ y="-600"
+ transform="scale(-1,-1)" />
+ <rect
+ y="-604"
+ x="-258"
+ height="2"
+ width="1"
+ id="rect23527"
+ 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
+ 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="rect23537"
+ width="1"
+ height="2"
+ x="-258"
+ y="-608" />
+ </g>
+ <rect
+ y="599"
+ x="258"
+ height="8"
+ width="14"
+ id="rect23637"
+ 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" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc"
+ style="opacity:0.12999998;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 259,600 13,0 0,-1 -14,0 0,8 1,0 0,-7 z"
+ id="path23639" />
+ <g
+ transform="translate(40,359)"
+ id="g23641"
+ style="display:inline;enable-background:new">
+ <g
+ id="g23646"
+ style="fill:#1a1a1a;display:inline;enable-background:new"
+ transform="translate(5,-6.0000002e-7)" />
+ </g>
+ </g>
+ <g
+ transform="translate(0.1767767,0.13258252)"
+ id="g106636">
+ <path
+ style="fill:url(#linearGradient106641);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 263.5625,590.375 1.75,-1.5 1.99177,3.7253 1.75,-1 -1.74177,-3.4753 2.5,0 -6.25,-6.25 z"
+ id="path45378-1-5-6-2-9"
+ 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 263.3125,581.125 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-5"
+ 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 264.15625,583.375 0,5.75"
+ id="path17845-9-1-1"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ </g>
+ </g>
+ <g
+ transform="translate(0.02855492,0)"
+ style="display:inline;enable-background:new"
+ id="g15868-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"
+ id="rect18695-6-9-6"
+ width="15.971445"
+ height="16.000002"
+ x="110"
+ y="241" />
+ <g
+ id="g15853-0">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path15095-5"
+ d="m 117.9106,247.99675 0.007,7.98875 -5.98631,-3.26708 -0.0121,-7.34356 z"
+ style="opacity:0.63859648;fill:url(#radialGradient15836-5);fill-opacity:1;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="path18719-6-9-0"
+ d="m 117.94049,242.95683 -5.85545,2.34692 6.10637,2.4934 -0.17358,8.22275 6.00064,-3.2989 0.0442,-7.36753 z"
+ style="fill:url(#linearGradient15851-6);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-4-7-7"
+ transform="matrix(1.2133883,0,0,1.2133883,-65.271004,156.45833)">
+ <path
+ id="path18707-3-8-5"
+ d="m 146.0019,73.295281 5,-2.007976 5,2.007976 -5,2.073959 z"
+ style="fill:url(#linearGradient15818-5);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-2-5-8"
+ d="m 124.01757,245.38766 -6.11113,2.33515 0.39771,8.10095 5.71891,-3.11585 z"
+ style="fill:url(#linearGradient15846-4);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path18709-1-1-0"
+ d="m 114.36329,244.98044 3.58667,-1.46751 5.56035,2.22692 0.0356,6.65202 -4.34973,2.45342"
+ style="fill:none;stroke:url(#linearGradient15843-2);stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g18737-4-8-8"
+ style="opacity:0.7"
+ transform="matrix(1.2133883,0,0,1.2133883,-282.46751,373.65484)" />
+ <path
+ sodipodi:nodetypes="ccccccccccc"
+ inkscape:connector-curvature="0"
+ id="path15957-6"
+ d="m 118.29703,256.35166 5.94799,-3.23942 c 0.0419,-0.0185 0.0806,-0.0443 0.11369,-0.0758 0.0689,-0.0703 0.11042,-0.16699 0.1137,-0.26543 l -0.0379,-7.432 c 10e-4,-0.16462 -0.1103,-0.32426 -0.26543,-0.37919 l -6.06694,-2.42677 c -0.0474,-0.0224 -0.0992,-0.0354 -0.15167,-0.0379 l 1.2e-4,0 c -0.0524,0.002 -0.10423,0.0154 -0.15167,0.0379 l -5.53168,2.30782"
+ style="fill:none;stroke:#0b1728;stroke-width:0.89999998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="0.4429636"
+ inkscape:original="M 111.90625 245.375 L 111.9375 252.71875 L 117.90625 256 L 117.90625 248 L 111.90625 245.375 z "
+ style="fill:none;stroke:url(#linearGradient16730);stroke-width:0.89999998;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path16571-2"
+ d="m 111.78125,244.9375 a 0.4430079,0.4430079 0 0 0 -0.3125,0.4375 l 0.0312,7.34375 a 0.4430079,0.4430079 0 0 0 0.21875,0.375 l 5.96875,3.28125 A 0.4430079,0.4430079 0 0 0 118.34375,256 l 0,-8 a 0.4430079,0.4430079 0 0 0 -0.25,-0.40625 l -6,-2.625 a 0.4430079,0.4430079 0 0 0 -0.3125,-0.0312 z" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient16562-7);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 117.31869,255.08504 -4.89325,-2.67466 -0.0154,-6.1798"
+ id="path16560-5"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="opacity:0.75333408;fill:none;stroke:url(#linearGradient15773-7);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:0.38888891"
+ d="m 112.44393,252.43208 3.76322,-1.57568"
+ id="path15671-3"
+ inkscape:connector-curvature="0"
+ 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">
+ <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"
+ width="16"
+ height="16"
+ x="131"
+ y="556" />
+ <g
+ transform="translate(104,40.00013)"
+ id="g39545">
+ <g
+ transform="translate(-116,424.99975)"
+ style="opacity:0.75"
+ id="g39547">
+ <g
+ id="g39549"
+ transform="translate(-179,199.50012)">
+ <path
+ sodipodi:nodetypes="ccccccc"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.00000167;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 328.5,-107.25 -4.5,1.75 0,6.5 4.5,2.25 4.25,-2 0,-6.75 -4.25,-1.75 z"
+ id="path39551"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g39553"
+ transform="translate(179,-179)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path39556"
+ d="m 154,80 0,-6.5 -4.5,-1.75 0,10.5 L 154,80 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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ id="path39558"
+ d="m 324,-99.00012 0,-6.49988 4.5,-1.75 0.5,0.25 0,10 -0.5,0.25 -4.5,-2.25012 z"
+ style="fill:#cccccc;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="ccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path39560"
+ d="m 332.5,-105.5 0,6.25 -4,2 -4,-2.00012 0,-6.24988"
+ style="fill:none;stroke:url(#linearGradient27496);stroke-width:0.99999982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path39562"
+ d="m 324,-105.5 4.5,-1.75 4.5,1.75 -4.5,2 -4.5,-2 z"
+ style="fill:#ffffff;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="path39564"
+ d="m 145.5,94.25012 c 0,0 4,1.75 4,1.75 l 4,-1.75"
+ style="opacity:0.95999995;fill:none;stroke:url(#linearGradient27498);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="96.000122"
+ x="149"
+ height="6.7500019"
+ width="1"
+ id="rect39567"
+ style="opacity:0.35;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="opacity:0.09599998;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.06666696px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect39569"
+ width="1"
+ height="6.7500019"
+ x="150"
+ y="96.000122" />
+ </g>
+ <rect
+ style="fill:none;stroke:#8c4800;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="rect39571"
+ width="2.9999485"
+ height="3.0001416"
+ x="27.500006"
+ y="517.49976"
+ ry="0"
+ rx="0" />
+ <rect
+ rx="0"
+ ry="0"
+ y="524.49951"
+ x="27.500006"
+ height="3.0001416"
+ width="2.9999485"
+ id="rect39574"
+ style="fill:none;stroke:#8c4800;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
+ y="517.99988"
+ x="28.021444"
+ height="4"
+ width="3.9785564"
+ id="rect37868-0-5"
+ 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" />
+ <path
+ style="fill:none;stroke:#5a2f00;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"
+ d="m 28.000006,520.49983 -0.5,0 0,-3.00014 2.99995,0"
+ id="path39576"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path39583"
+ d="m 28.000006,524.49978 -0.5,0 0,3.00014 2.99995,0"
+ style="fill:none;stroke:#5a2f00;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"
+ inkscape:connector-curvature="0" />
+ <rect
+ rx="0"
+ ry="0"
+ y="517.99988"
+ x="28.000051"
+ height="2.0000772"
+ width="1.9999485"
+ id="rect39585"
+ style="fill:#ffd4a5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ y="524.99988"
+ x="28"
+ height="1.999992"
+ width="3.9785564"
+ id="rect37868-0-1"
+ 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" />
+ <rect
+ rx="0"
+ ry="0"
+ y="524.99982"
+ x="28.000051"
+ height="2.0000772"
+ width="1.9999485"
+ id="rect39587"
+ style="fill:#ffd4a5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <g
+ transform="translate(-122.79197,-20.867417)"
+ id="g106636-9"
+ style="display:inline;enable-background:new">
+ <path
+ style="fill:url(#linearGradient106641-3);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 263.5625,590.375 1.75,-1.5 1.99177,3.7253 1.75,-1 -1.74177,-3.4753 2.5,0 -6.25,-6.25 z"
+ id="path45378-1-5-6-2-9-3"
+ 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 263.3125,581.125 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-5-1"
+ 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 264.15625,583.375 0,5.75"
+ id="path17845-9-1-1-8"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g52905"
+ transform="translate(398.95001,-42)">
+ <rect
+ y="367"
+ x="-372.95001"
+ height="16"
+ width="16"
+ id="rect52907"
+ 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" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path52910"
+ d="m -368.95,374 5,-5"
+ style="fill:none;stroke:#000000;stroke-width:3.70000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <g
+ mask="url(#mask52637-8-8)"
+ id="g52912"
+ transform="translate(-18.95,-84)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ d="m -352.5,465.5 2,0 c 1.10456,0 2,-0.89543 2,-1.99999 l 0,-1.00001 -2.5,-2.5"
+ style="color:#000000;fill:none;stroke:#3c0800;stroke-width:2.70000005;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="path52914"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path52916"
+ style="color:#000000;fill:none;stroke:#ed7432;stroke-width:1.5;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 -353.25,465.5 2.75,0 c 1.10456,0 2,-0.89543 2,-1.99999 l 0,-1.00001 -2.5,-2.5"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ mask="none"
+ sodipodi:nodetypes="ccccc"
+ d="m -353.25,465.5 2.75,0 c 1.10456,0 2,-0.89543 2,-1.99999 l 0,-1.00001 -2.5,-2.5"
+ style="color:#000000;fill:none;stroke:url(#linearGradient52998-5-5);stroke-width:1.5;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="path52918"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ ry="1.5"
+ rx="1.5"
+ style="fill:none;stroke:#000000;stroke-width:2.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.26976086;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect52920"
+ width="3"
+ height="3"
+ x="-371.45001"
+ y="-376.5"
+ transform="scale(1,-1)" />
+ <g
+ transform="matrix(-1,0,0,1,-711.95,-84)"
+ id="g52922"
+ mask="url(#mask52879-0-5)">
+ <path
+ id="path52924"
+ style="color:#000000;fill:none;stroke:#0b1728;stroke-width:2.70000005;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 -353.5,465.5 3,0 c 1.10456,0 2,-0.89543 2,-1.99999 l 0,-1.00001 -2.5,-2.5"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ d="m -354.2,465.5 3.7,0 c 1.10456,0 2,-0.89543 2,-1.99999 l 0,-1.00001 -2.5,-2.5"
+ style="color:#000000;fill:none;stroke:#7be10f;stroke-width:1.5;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="path52926"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path52928"
+ style="color:#000000;fill:none;stroke:url(#linearGradient53000-3-9);stroke-width:1.5;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 -354.2,465.5 3.75,0 c 1.10456,0 2,-0.89543 2,-1.99999 l 0,-1.00001 -2.5,-2.5"
+ sodipodi:nodetypes="ccccc"
+ mask="none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ transform="scale(1,-1)"
+ y="-376.5"
+ x="-361.45001"
+ height="3"
+ width="3"
+ id="rect52930"
+ style="fill:none;stroke:#000000;stroke-width:2.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.26976086;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ rx="1.5"
+ ry="1.5" />
+ <path
+ style="fill:none;stroke:#b3b3b3;stroke-width:2.20000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -367.7,372.75 3.75,-3.75"
+ id="path52932"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <rect
+ transform="scale(1,-1)"
+ y="-376.5"
+ x="-371.45001"
+ height="3"
+ width="3"
+ id="rect52934"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#cccccc;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.26976086;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ rx="1.5"
+ ry="1.5" />
+ <rect
+ ry="1.5"
+ rx="1.5"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#cccccc;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.26976086;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect52936"
+ width="3"
+ height="3"
+ x="-361.45001"
+ y="-376.5"
+ transform="scale(1,-1)" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path52938"
+ d="m -368.45,372.5 4,-4 1,0"
+ style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <rect
+ ry="1.5"
+ rx="1.5"
+ style="fill:none;stroke:url(#linearGradient53002-6-2);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.26976086;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect52940"
+ width="3"
+ height="3"
+ x="-371.45001"
+ y="-376.5"
+ transform="scale(1,-1)" />
+ <rect
+ transform="scale(1,-1)"
+ y="-376.5"
+ x="-361.45001"
+ height="3"
+ width="3"
+ id="rect52942"
+ style="fill:none;stroke:url(#linearGradient58927);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:7.26976086;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ rx="1.5"
+ ry="1.5" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ transform="translate(252,-210)"
+ id="g52978">
+ <path
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1.29999995;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 -198,536 -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 -204,542 l 0,1 0,1 1.90625,0.15625 c 0.14227,0.6231 0.25145,1.07677 0.59375,1.59375 l -1.75,1.75 1.75,1.75 1.75,-1.75 c 0.51699,0.34229 0.97065,0.45148 1.59375,0.59375 L -198,550 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 -190,544 l 0,-1 0,-1 -1.90625,-0.15625 c -0.14227,-0.6231 -0.25145,-1.07677 -0.59375,-1.59375 l 1.75,-1.75 -1.75,-1.75 -1.75,1.75 c -0.51699,-0.34229 -0.97065,-0.45148 -1.59375,-0.59375 L -196,536 l -1,0 -1,0 z m 1,4.125 c 1.58782,0 2.875,1.28718 2.875,2.875 0,1.58782 -1.28718,2.875 -2.875,2.875 -1.58782,0 -2.875,-1.28718 -2.875,-2.875 0,-1.58782 1.28718,-2.875 2.875,-2.875 z"
+ id="path52980"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path52982"
+ d="m -196,550 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 -190,544 l 0,-1 0,-1 -1.90625,-0.15625 c -0.14227,-0.6231 -0.25145,-1.07677 -0.59375,-1.59375 l 1.5,-1.75 -1.5,-1.5 -1.75,1.5 c -0.51699,-0.34229 -0.97065,-0.45148 -1.59375,-0.59375 L -196,536 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.5 -1.5,1.5 1.5,1.75 c -0.34229,0.51699 -0.45148,0.97065 -0.59375,1.59375 L -204,542 l 0,1 0,1 1.90625,0.15625 c 0.14227,0.6231 0.25145,1.07677 0.59375,1.59375 l -1.5,1.75 1.5,1.5 1.75,-1.5 c 0.51699,0.34229 0.97065,0.45148 1.59375,0.59375 L -198,550 l 1,0 1,0 z m -1,-4 c -1.65685,0 -3,-1.34315 -3,-3 0,-1.65685 1.34315,-3 3,-3 1.65685,0 3,1.34315 3,3 0,1.65685 -1.34315,3 -3,3 z"
+ style="color:#000000;fill:url(#linearGradient32854-6-2);fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="535"
+ x="-205"
+ height="16"
+ width="16"
+ id="rect52984"
+ 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
+ ry="6.4999995"
+ rx="6.4999995"
+ y="539.5"
+ x="-200.5"
+ height="6.981843"
+ width="6.981843"
+ id="rect52986"
+ style="fill:none;stroke:url(#linearGradient32856-3-2);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"
+ 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 -192.5,537.5 -1.25,1.25 m -2.75,-2.25 -1,0 0,1.5 c -0.35104,0.0802 -1.50086,0.537 -2,0.75 m -1.75,1.75 c -0.20864,0.49552 -0.67146,1.65605 -0.75,2 l -1.5,0 0,1 m 1.75,-5.75 -0.5,0.5 m 1,8 -1.25,1.25"
+ id="path52988"
+ sodipodi:nodetypes="cccccscccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path52990"
+ d="m -202.5,538.75 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" />
+ <rect
+ style="opacity:0.4;fill:none;stroke:url(#linearGradient32858-7-2);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"
+ id="rect52992"
+ width="6.981843"
+ height="6.981843"
+ x="193.51816"
+ y="-546.48187"
+ rx="6.4999995"
+ ry="6.4999995"
+ transform="scale(-1,-1)" />
+ <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="opacity:0.35;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 -197.5,548.25 0,1.25 m 7,-7 -1.25,0"
+ id="path52994"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path52996"
+ d="m -191.75,547.25 -1,1"
+ style="opacity:0.3;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" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g32860"
+ transform="translate(231,-294)">
+ <rect
+ style="opacity:0;color:#000000;fill:#ffff00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect32862"
+ width="16"
+ height="16"
+ x="-226"
+ y="619" />
+ <path
+ sodipodi:nodetypes="cccsssscccc"
+ style="opacity:0.5;fill:url(#linearGradient32896-0-4);fill-opacity:1;stroke:none"
+ d="m -212.5,619.5 -2,0 -6.0625,6.0625 C -220.70928,625.548 -220.84942,625.5 -221,625.5 c -2.48528,0 -4.5,2.01473 -4.5,4.5 0,2.48527 2.01472,4.5 4.5,4.5 2.48528,0 4.5,-2.01473 4.5,-4.5 0,-0.14948 -0.017,-0.29176 -0.0312,-0.4375 l 6.0312,-6.0625 0,-2 -2,-2 z"
+ id="path32864"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m -177.09897,651.49231 a 2.4505157,2.4923096 0 1 1 -4.90103,0 2.4505157,2.4923096 0 1 1 4.90103,0 z"
+ sodipodi:ry="2.4923096"
+ sodipodi:rx="2.4505157"
+ sodipodi:cy="651.49231"
+ sodipodi:cx="-179.54948"
+ id="path32866"
+ style="color:#000000;fill:url(#linearGradient32899-8-3);fill-opacity:1;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ transform="matrix(1.224232,0,0,1.2036922,-1.189782,-154.19619)" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path32868"
+ d="m -219.5,626.5 5.5,-5.5 0.5,-0.5 0.5,0.5 0.5,0.5"
+ style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(-21,0)"
+ d="M -193.09375,620.46875 -198.875,626.25 a 0.95626367,0.95626367 0 0 1 -0.78125,0.25 c -0.29297,-0.0289 -0.39637,-0.0312 -0.34375,-0.0312 -1.96853,0 -3.53125,1.56273 -3.53125,3.53125 0,1.96852 1.56272,3.53125 3.53125,3.53125 1.96853,0 3.53125,-1.56273 3.53125,-3.53125 0,-0.0768 0.0155,-0.18427 0,-0.34375 a 0.95626367,0.95626367 0 0 1 0.25,-0.78125 l 5.75,-5.78125 0,-1.1875 -1.4375,-1.4375 -1.1875,0 z"
+ id="path32870"
+ style="fill:none;stroke:url(#radialGradient32901-4-9);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:original="M -193.5 619.5 L -199.5625 625.5625 C -199.70928 625.548 -199.84942 625.5 -200 625.5 C -202.48528 625.5 -204.5 627.51473 -204.5 630 C -204.5 632.48527 -202.48528 634.5 -200 634.5 C -197.51472 634.5 -195.5 632.48527 -195.5 630 C -195.5 629.85052 -195.51705 629.70824 -195.53125 629.5625 L -189.5 623.5 L -189.5 621.5 L -191.5 619.5 L -193.5 619.5 z "
+ inkscape:radius="-0.95616806"
+ sodipodi:type="inkscape:offset" />
+ <path
+ id="path32872"
+ d="m -217,624 0,1 -1,0 0,0.0312 -0.0312,0 0,0.96875 -0.96875,0 0,0.0312 -0.0312,0 0,1 -1,0 0,1 0,1 1,0 1,0 0,-1 1,0 0,-0.0312 0.0312,0 0,-0.96875 0.96875,0 0,-0.0312 0.0312,0 0,-1 1,0 0,-1 -1,0 0,-1 -1,0 z"
+ style="color:#000000;fill:url(#linearGradient32903-6-4);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.97113496;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(1.2638889,0,0,1.2222222,32.853009,-140.1836)"
+ d="m -201.22313,628.93835 a 0.80938911,0.80938911 0 1 1 -1.61878,0 0.80938911,0.80938911 0 1 1 1.61878,0 z"
+ sodipodi:ry="0.80938911"
+ sodipodi:rx="0.80938911"
+ sodipodi:cy="628.93835"
+ sodipodi:cx="-202.03252"
+ id="path32874"
+ style="opacity:0.7;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.97113496;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.7;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.97113496;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path32877"
+ sodipodi:cx="-202.03252"
+ sodipodi:cy="628.93835"
+ sodipodi:rx="0.80938911"
+ sodipodi:ry="0.80938911"
+ d="m -201.22313,628.93835 a 0.80938911,0.80938911 0 1 1 -1.61878,0 0.80938911,0.80938911 0 1 1 1.61878,0 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 a 0.80938911,0.80938911 0 1 1 -1.61878,0 0.80938911,0.80938911 0 1 1 1.61878,0 z"
+ sodipodi:ry="0.80938911"
+ sodipodi:rx="0.80938911"
+ sodipodi:cy="628.93835"
+ sodipodi:cx="-202.03252"
+ id="path32879"
+ style="opacity:0.7;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.97113496;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ style="opacity:0.35;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m -213.5,621.5 -6,6"
+ id="path32881"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path32883"
+ d="m -212.5,619.5 -2,0 -6.0625,6.0625 C -220.70928,625.548 -220.84942,625.5 -221,625.5 c -2.48528,0 -4.5,2.01473 -4.5,4.5 0,2.48527 2.01472,4.5 4.5,4.5 2.48528,0 4.5,-2.01473 4.5,-4.5 0,-0.14948 -0.017,-0.29176 -0.0312,-0.4375 l 6.0312,-6.0625 0,-2 -2,-2 z"
+ style="fill:none;stroke:#000000;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="cccsssscccc"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(-21,0)"
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="-0.95616806"
+ inkscape:original="M -193.5 619.5 L -199.5625 625.5625 C -199.70928 625.548 -199.84942 625.5 -200 625.5 C -202.48528 625.5 -204.5 627.51473 -204.5 630 C -204.5 632.48527 -202.48528 634.5 -200 634.5 C -197.51472 634.5 -195.5 632.48527 -195.5 630 C -195.5 629.85052 -195.51705 629.70824 -195.53125 629.5625 L -189.5 623.5 L -189.5 621.5 L -191.5 619.5 L -193.5 619.5 z "
+ style="fill:none;stroke:url(#radialGradient32905-9-5);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path32886"
+ d="M -193.09375,620.46875 -198.875,626.25 a 0.95626367,0.95626367 0 0 1 -0.78125,0.25 c -0.29297,-0.0289 -0.39637,-0.0312 -0.34375,-0.0312 -1.96853,0 -3.53125,1.56273 -3.53125,3.53125 0,1.96852 1.56272,3.53125 3.53125,3.53125 1.96853,0 3.53125,-1.56273 3.53125,-3.53125 0,-0.0768 0.0155,-0.18427 0,-0.34375 a 0.95626367,0.95626367 0 0 1 0.25,-0.78125 l 5.75,-5.78125 0,-1.1875 -1.4375,-1.4375 -1.1875,0 z" />
+ <g
+ style="opacity:0.3;fill:#ffffff"
+ id="g32888">
+ <rect
+ style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect32890"
+ width="1"
+ height="0.98873287"
+ x="-217"
+ y="622.98871" />
+ <rect
+ y="624"
+ x="-216"
+ height="0.98873287"
+ width="1"
+ id="rect32892"
+ style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect32894"
+ width="1"
+ height="0.98873287"
+ x="-215"
+ 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"
+ transform="translate(72,509.96991)">
+ <rect
+ y="148"
+ x="-46"
+ height="16"
+ width="16"
+ id="rect45977-0"
+ style="opacity:0;fill:#666666;stroke:none;stroke-width:2.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="scale(1,-1)" />
+ <path
+ sodipodi:nodetypes="cscccc"
+ id="path43354-7"
+ d="m -42,-162.5 c -1.383118,0 -2.5,2.0178 -2.5,4.5 0,2.4822 1.116881,4.5 2.5,4.5 l 9.5,-2 c 1.25,-0.25 1.25,-4.75 0,-5 -3.164485,-0.63789 -6.364604,-1.31719 -9.5,-2 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path43211-1"
+ d="m -42.46462,-153.21991 0,4"
+ style="fill:none;stroke:#000000;stroke-width:2.0999999;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m -42,-163.5 c -1.175382,0 -2.068672,0.84122 -2.625,1.84375 -0.556328,1.00253 -0.875,2.26593 -0.875,3.65625 0,1.39032 0.318672,2.65372 0.875,3.65625 0.556328,1.00253 1.449618,1.84375 2.625,1.84375 a 0.9950207,0.9950207 0 0 0 0.21875,-0.0312 l 9.46875,-2 c 0.01655,-0.003 0.01506,-0.0275 0.03125,-0.0312 0.840076,-0.19179 1.234143,-0.86885 1.4375,-1.46875 0.207276,-0.61147 0.28125,-1.28773 0.28125,-1.96875 0,-0.68102 -0.07397,-1.35728 -0.28125,-1.96875 -0.207276,-0.61147 -0.593404,-1.32493 -1.46875,-1.5 -3.157727,-0.63653 -6.336828,-1.31795 -9.46875,-2 A 0.9950207,0.9950207 0 0 0 -42,-163.5 z"
+ id="path43480-7"
+ style="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"
+ inkscape:original="M -42 -162.5 C -43.383118 -162.5 -44.5 -160.4822 -44.5 -158 C -44.5 -155.5178 -43.383119 -153.5 -42 -153.5 L -32.5 -155.5 C -31.25 -155.75 -31.25 -160.25 -32.5 -160.5 C -35.664485 -161.13789 -38.864604 -161.81719 -42 -162.5 z "
+ inkscape:radius="0.99492121"
+ sodipodi:type="inkscape:offset" />
+ <g
+ id="g43531-7"
+ style="fill:#bc2b00;stroke:none">
+ <g
+ id="g43521-7"
+ style="fill:#bc2b00;stroke:none">
+ <path
+ style="fill:#bc2b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.57082754;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -94.9375,-169.09375 c -0.02445,0.0114 -0.07282,0.0179 -0.09375,0.0312 -0.07655,0.0171 -0.129072,0.0618 -0.1875,0.0937 -0.06733,0.0426 -0.102853,0.0701 -0.125,0.125 -0.04225,0.0882 -0.02336,0.20307 0.0625,0.28125 0.425481,0.37342 0.870923,1.31835 1.09375,2.46875 0.222825,1.15041 0.26055,2.52729 0.0625,3.8125 -0.229814,1.49133 -0.739166,2.50981 -1.21875,2.875 -0.06733,0.0426 -0.134102,0.10133 -0.15625,0.15625 -0.02264,0.0932 0.04665,0.17736 0.15625,0.25 0.116379,0.0913 0.296118,0.15625 0.5,0.15625 0.203886,0 0.383626,-0.065 0.5,-0.15625 0.05375,-0.0409 0.10617,-0.08 0.15625,-0.125 0.100788,-0.012 0.199646,-0.0299 0.28125,-0.0625 0.05623,-0.0197 0.114869,-0.067 0.15625,-0.0937 0.879891,-0.58512 1.33731,-1.57799 1.59375,-3.03125 0.221887,-1.25745 0.188175,-2.58853 -0.0625,-3.71875 -0.250672,-1.13023 -0.67717,-2.06619 -1.40625,-2.625 -0.07644,-0.0471 -0.164946,-0.10325 -0.28125,-0.125 -0.08767,-0.0266 -0.180589,-0.0253 -0.28125,-0.0312 -0.03116,-0.0302 -0.0613,-0.0653 -0.09375,-0.0937 -0.05975,-0.064 -0.132554,-0.12368 -0.25,-0.15625 -0.124538,-0.0375 -0.266141,-0.0447 -0.40625,-0.0312 l 0,-1e-4 0,0 z"
+ transform="translate(56,6)"
+ id="path43515-7"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g43525-3"
+ transform="matrix(1,0,0,0.8248704,3.9999996,-27.664792)"
+ style="fill:#bc2b00;stroke:none">
+ <path
+ id="path43527-3"
+ style="fill:#bc2b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.62850982;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -38.766635,-163.1299 c -0.1926,0.0198 -0.359499,0.088 -0.454803,0.18574 -0.141826,0.12415 -0.141826,0.2845 0,0.40865 0.393723,0.36252 0.827594,1.30384 1.03955,2.45188 0.211957,1.14804 0.253401,2.50645 0.06497,3.78928 -0.218694,1.48887 -0.72826,2.54519 -1.169495,2.89767 -0.09595,0.0836 -0.129342,0.18561 -0.09271,0.28335 0.03663,0.0977 0.140225,0.18301 0.287629,0.23675 0.146132,0.0549 0.324618,0.074 0.495554,0.053 0.170936,-0.0209 0.320068,-0.0802 0.414052,-0.16446 0.787677,-0.62926 1.137868,-1.68972 1.364411,-3.23203 0.196047,-1.33468 0.156543,-2.73807 -0.06497,-3.93787 -0.221514,-1.1998 -0.582737,-2.18614 -1.234468,-2.78623 -0.130885,-0.13138 -0.387364,-0.2047 -0.649719,-0.18574 l 0,0 -10e-7,1e-5 0,0 z m 0.338475,0.29257 c -0.244486,0.0286 -0.443513,0.11281 -0.531926,0.22492 -0.08841,0.11212 -0.05483,0.23776 0.08976,0.33579 0.442252,0.33867 0.938861,1.23068 1.179113,2.31292 0.24025,1.08225 0.287292,2.36512 0.07369,3.57452 -0.247925,1.40376 -0.831847,2.40481 -1.326503,2.73346 -0.229933,0.15651 -0.165504,0.37098 0.14739,0.49062 0.163456,0.0637 0.375184,0.0924 0.584711,0.0791 0.209527,-0.0133 0.398079,-0.0673 0.520708,-0.14918 0.899238,-0.59746 1.290496,-1.62825 1.547585,-3.0839 0.222494,-1.25976 0.177718,-2.58217 -0.0737,-3.71469 -0.251412,-1.13252 -0.582944,-2.05893 -1.326502,-2.62833 -0.04216,-0.0265 -0.09175,-0.05 -0.147388,-0.0701 -0.187804,-0.0957 -0.469403,-0.13585 -0.736946,-0.10513 l 8e-6,0 0,0 z"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <path
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="0.99492121"
+ inkscape:original="M -42 -162.5 C -43.383118 -162.5 -44.5 -160.4822 -44.5 -158 C -44.5 -155.5178 -43.383119 -153.5 -42 -153.5 L -32.5 -155.5 C -31.25 -155.75 -31.25 -160.25 -32.5 -160.5 C -35.664485 -161.13789 -38.864604 -161.81719 -42 -162.5 z "
+ style="fill:url(#linearGradient24022-6);fill-opacity:1;fill-rule:evenodd;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"
+ id="path43484-5"
+ d="m -42,-163.5 c -1.175382,0 -2.068672,0.84122 -2.625,1.84375 -0.556328,1.00253 -0.875,2.26593 -0.875,3.65625 0,1.39032 0.318672,2.65372 0.875,3.65625 0.556328,1.00253 1.449618,1.84375 2.625,1.84375 a 0.9950207,0.9950207 0 0 0 0.21875,-0.0312 l 9.46875,-2 c 0.01655,-0.003 0.01506,-0.0275 0.03125,-0.0312 0.840076,-0.19179 1.234143,-0.86885 1.4375,-1.46875 0.207276,-0.61147 0.28125,-1.28773 0.28125,-1.96875 0,-0.68102 -0.07397,-1.35728 -0.28125,-1.96875 -0.207276,-0.61147 -0.593404,-1.32493 -1.46875,-1.5 -3.157727,-0.63653 -6.336828,-1.31795 -9.46875,-2 A 0.9950207,0.9950207 0 0 0 -42,-163.5 z" />
+ <path
+ style="fill:none;stroke:#999999;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m -42.46462,-152.96991 0,4.5"
+ id="path43213-9"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(2.5815738,0,0,1.0580577,65.140965,9.1698698)"
+ d="m -40.52941,-158 a 0.9705897,4.25 0 1 1 -1.94118,0 0.9705897,4.25 0 1 1 1.94118,0 z"
+ sodipodi:ry="4.25"
+ sodipodi:rx="0.9705897"
+ sodipodi:cy="-158"
+ sodipodi:cx="-41.5"
+ id="path43356-9"
+ style="fill:url(#linearGradient24024-4);fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.48405313;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"
+ sodipodi:type="arc" />
+ <rect
+ style="opacity:0.3;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect43215-8"
+ width="1"
+ height="1"
+ x="-42.964619"
+ y="-152.96989" />
+ <path
+ d="m -42,-162.59375 c -0.74028,0 -1.381145,0.54136 -1.84375,1.375 -0.462605,0.83364 -0.75,1.96262 -0.75,3.21875 0,1.25613 0.287395,2.38511 0.75,3.21875 0.462605,0.83364 1.10347,1.375 1.84375,1.375 a 0.10019871,0.10019871 0 0 0 0.03125,0 l 9.5,-2 c 0.369179,-0.0738 0.619862,-0.43015 0.78125,-0.90625 0.161388,-0.4761 0.21875,-1.08496 0.21875,-1.6875 0,-0.60254 -0.05736,-1.2114 -0.21875,-1.6875 -0.161388,-0.4761 -0.412071,-0.83241 -0.78125,-0.90625 -3.163804,-0.63775 -6.364954,-1.31727 -9.5,-2 a 0.10019871,0.10019871 0 0 0 -0.03125,0 z"
+ id="path43218-1"
+ style="fill:none;stroke:url(#linearGradient14482-7);stroke-width:1;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:original="M -42 -162.5 C -43.383118 -162.5 -44.5 -160.4822 -44.5 -158 C -44.5 -155.5178 -43.383119 -153.5 -42 -153.5 L -32.5 -155.5 C -31.25 -155.75 -31.25 -160.25 -32.5 -160.5 C -35.664485 -161.13789 -38.864604 -161.81719 -42 -162.5 z "
+ inkscape:radius="0.10018869"
+ sodipodi:type="inkscape:offset" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g24573-8"
+ transform="translate(189,104.96991)">
+ <g
+ id="g24558-2">
+ <rect
+ y="241"
+ x="47"
+ height="16"
+ width="16"
+ id="rect24365-6"
+ style="opacity:0;fill:#ffff00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.10000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="cccccccccccsss"
+ id="path24370-6"
+ d="m 60.5,253 -1,0.5 -0.998035,-1 -7e-6,-2 -0.999999,-1 -2.251959,0 -0.75,-0.75 0.002,-2.25 -1.000001,-1 -1.999993,0 -1.001965,-0.75 0.498035,-1 c 1.618614,-3.25 6.964866,-2.7871 9.501965,-0.25 2.5371,2.53709 3,8 0,9.5 L 60.5,253 z"
+ style="fill:url(#linearGradient24044-1);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;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccccsccsccccc"
+ id="path24406-0"
+ d="m 55.40625,241.84375 c -1.752306,-0.0251 -3.360906,0.59103 -4.09375,2.0625 l -0.15625,0.3125 c -0.122559,0.2366 -0.05653,0.52711 0.15625,0.6875 l 0.15625,0.125 c 0.100886,0.0688 0.221909,0.1018 0.34375,0.0937 l 1.6875,0 c 0.01042,3e-4 0.02083,3e-4 0.03125,0 0.09863,-0.003 0.17826,0.0573 0.25,0.125 l 1,0.96875 c 0.06775,0.0718 0.09659,0.15137 0.09375,0.25 -2.98e-4,0.0104 -2.98e-4,0.0208 0,0.0312 l 0,2.09375 0.375,0.15625 4.96875,-4.96875 c -1.186918,-1.18692 -3.03835,-1.91206 -4.8125,-1.9375 l 0,1e-4 0,0 z"
+ style="fill:url(#linearGradient24046-9);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <g
+ style="opacity:0.82999998"
+ id="g24372-3"
+ transform="translate(21,0)"
+ mask="url(#mask25021-4)">
+ <path
+ id="path24374-8"
+ style="fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ d="m 30,246.5 -2,7 1.5,1.5 7,-2 m -3.5,-3 -4.5,4.5"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path24380-0"
+ style="fill:none;stroke:url(#radialGradient24048-2);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:new"
+ d="M 34.25,248.75 28.5,254.5"
+ mask="none"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ mask="none"
+ d="m 30.5,244.75 -2.5,8.75 1.5,1.5 8.75,-2.5"
+ style="fill:none;stroke:url(#radialGradient24050-4);stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new"
+ id="path24448-1"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:nodetypes="cccccccccccccccccssc"
+ id="path24408-2"
+ d="m 55.40625,242.375 c -1.622878,-0.0233 -2.972755,0.53436 -3.59375,1.78125 l -0.15625,0.3125 0.15625,0.125 1.6875,0 c 0.243249,-0.007 0.479315,0.0829 0.65625,0.25 l 1,1 c 0.167073,0.17694 0.257003,0.413 0.25,0.65625 L 55.5,248 l 0.5,0.5 1.5,0.0937 c 0.243249,-0.007 0.479315,0.0829 0.65625,0.25 l 1,1 c 0.167073,0.17694 0.257003,0.413 0.25,0.65625 l 0,1.59375 0.28125,0.28125 0.40625,-0.1875 c 1.084704,-0.54235 1.613412,-1.88556 1.5625,-3.53125 -0.05091,-1.64569 -0.757004,-3.44451 -1.8125,-4.5 -1.05838,-1.05838 -2.814635,-1.75798 -4.4375,-1.78125 l 0,5e-5 z"
+ style="fill:none;stroke:url(#linearGradient24053-5);stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24450-5"
+ width="2"
+ height="1"
+ x="50"
+ y="245" />
+ <rect
+ style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24452-0"
+ width="1"
+ height="1"
+ x="54"
+ y="248" />
+ <rect
+ style="opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24454-9"
+ width="1"
+ height="1"
+ x="55"
+ y="249" />
+ <rect
+ style="opacity:0.3;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24456-4"
+ width="1"
+ height="2"
+ x="58"
+ y="252" />
+ <rect
+ y="249"
+ x="54"
+ height="1"
+ width="1"
+ id="rect24659-7"
+ style="opacity:0.3;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g24384-8"
+ transform="matrix(0.3350147,0,0,0.3350147,6.410699,179.66413)"
+ 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">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path24396-3"
+ style="fill:#ff541f;fill-opacity:1;fill-rule:nonzero;stroke:#320b00;stroke-width:3.58193231;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"
+ transform="matrix(0.75,0,0,0.75,29.5,135)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.6;fill:url(#linearGradient24055-1);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path24398-5"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path24400-1"
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient24057-7);stroke-width:6.6867547;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:new"
+ 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" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g43234-2"
+ transform="matrix(-1,0,0,1,185,310)">
+ <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"
+ id="rect44017-0"
+ width="16"
+ height="16"
+ x="-46"
+ y="-52" />
+ <g
+ style="opacity:0.8"
+ id="g43226-1">
+ <g
+ id="g43115-6"
+ clip-path="url(#clipPath43135-6)"
+ mask="url(#mask43188-4)">
+ <path
+ d="m -45.5,42.5 1,1 3,-1 0.75,1 1.25,0 1,1 0,2 2,2 -2,2 0,1"
+ 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:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path43103-4"
+ sodipodi:nodetypes="cccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccccccc"
+ id="path43099-0"
+ style="fill:none;stroke:#ffffff;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 -45.5,42.5 1,1 3,-1 0.75,1 1.25,0 1,1 0,2 2,2 -2,2 0,1"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ mask="url(#mask43182-5)"
+ clip-path="url(#clipPath43178-6)"
+ id="g43206-6">
+ <path
+ d="m -45.5,42.5 1,1 3,-1 0.75,1 1.25,0 1,1 0,3 2,2 -1,1 -1,1"
+ 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:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path43208-1"
+ sodipodi:nodetypes="cccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccccccc"
+ id="path43210-8"
+ style="fill:none;stroke:#ffffff;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 -45.5,42.5 1,1 3,-1 0.75,1 1.25,0 1,1 0,3 2,2 -1,1 -1,1"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ id="g43218-9">
+ <g
+ id="g43129-8"
+ clip-path="url(#clipPath43178-6)"
+ mask="url(#mask43182-5)">
+ <path
+ sodipodi:nodetypes="cccccccccccccccc"
+ id="path43131-4"
+ 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:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -45.5,37.5 3,0 0,1 3,0 1,-1 2,2 0,1 1,1 2,0 1,1 0,1 -1,1 0,2 2,2 0,2 -1,1"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m -45.5,37.5 3,0 0,1 3,0 1,-1 2,2 0,1 1,1 2,0 1,1 0,1 -1,1 0,2 2,2 0,2 -1,1"
+ style="fill:none;stroke:#ffffff;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"
+ id="path43133-1"
+ sodipodi:nodetypes="cccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ mask="url(#mask43188-4)"
+ clip-path="url(#clipPath43135-6)"
+ id="g43212-4">
+ <path
+ sodipodi:nodetypes="ccccccccccccccc"
+ id="path43214-3"
+ 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:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -45.5,37.5 3,0 0,1 3,0 1,-1 2,2 0,1 1,1 2,0 1,1 -1,1 0,3 2,2 0,2 -1,1"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m -45.5,37.5 3,0 0,1 3,0 1,-1 2,2 0,1 1,1 2,0 1,1 -1,1 0,3 2,2 0,2 -1,1"
+ style="fill:none;stroke:#ffffff;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"
+ id="path43216-9"
+ sodipodi:nodetypes="ccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g29725-8"
+ transform="matrix(-0.3350147,0,0,0.3350147,-0.450611,-25.365697)"
+ 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">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path29727-8"
+ style="fill:#ff541f;fill-opacity:1;fill-rule:nonzero;stroke:#320b00;stroke-width:3.58193231;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"
+ transform="matrix(0.75,0,0,0.75,29.5,135)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.6;fill:url(#linearGradient24210-1);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path29729-0"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path29731-8"
+ style="opacity:0.7;fill:none;stroke:url(#linearGradient24212-8);stroke-width:6.6867547;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:new"
+ 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" />
+ </g>
+ </g>
+ <g
+ transform="translate(0,336)"
+ style="display:inline;enable-background:new"
+ id="g21835-7">
+ <g
+ transform="translate(51,10)"
+ style="opacity:0.8"
+ id="g44612-7">
+ <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"
+ id="rect44610-8"
+ width="16"
+ height="16"
+ x="-46"
+ y="-16" />
+ <g
+ id="g44566-3"
+ transform="translate(0,22)">
+ <g
+ transform="translate(0,0.02014865)"
+ inkscape:transform-center-x="6.4341195"
+ id="g44395-8">
+ <g
+ id="g44383-3"
+ inkscape:transform-center-x="6.4130439"
+ style="fill:none;stroke:#000000;stroke-width:2.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" />
+ <g
+ inkscape:transform-center-x="6.4130439"
+ id="g44315-7" />
+ </g>
+ <g
+ id="g44401-1"
+ inkscape:transform-center-x="-6.4341194"
+ transform="matrix(-1,0,0,-1,-76,-27.947857)">
+ <g
+ style="fill:none;stroke:#000000;stroke-width:2.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:transform-center-x="6.4130439"
+ id="g44403-0" />
+ <g
+ id="g44407-7"
+ inkscape:transform-center-x="6.4130439" />
+ </g>
+ <g
+ inkscape:transform-center-y="-6.3979735"
+ id="g44425-3"
+ transform="matrix(0,1,-1,0,-51.984003,24.036146)">
+ <g
+ style="fill:none;stroke:#000000;stroke-width:2.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:transform-center-x="6.4130439"
+ id="g44427-4" />
+ <g
+ id="g44431-9"
+ inkscape:transform-center-x="6.4130439" />
+ </g>
+ <g
+ inkscape:transform-center-y="6.4702655"
+ transform="matrix(0,-1,1,0,-24.015997,-51.963854)"
+ id="g44435-6">
+ <g
+ id="g44437-5"
+ inkscape:transform-center-x="6.4130439"
+ style="fill:none;stroke:#000000;stroke-width:2.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" />
+ <g
+ inkscape:transform-center-x="6.4130439"
+ id="g44441-1" />
+ </g>
+ <g
+ inkscape:transform-center-y="-4.4797485"
+ id="g44532-0">
+ <g
+ inkscape:transform-center-y="-4.4797485"
+ id="g44511-9"
+ transform="matrix(-0.7071068,0.7071068,-0.7071068,-0.7071068,-74.7838,3.0074334)"
+ inkscape:transform-center-x="-4.4797485">
+ <g
+ style="fill:none;stroke:#000000;stroke-width:2.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:transform-center-x="6.4130439"
+ id="g44514-9" />
+ <g
+ id="g44518-6"
+ inkscape:transform-center-x="6.4130439" />
+ </g>
+ <g
+ inkscape:transform-center-x="4.4797488"
+ transform="matrix(0.7071068,0.7071068,-0.7071068,0.7071068,-20.992567,22.7838)"
+ id="g44522-8"
+ inkscape:transform-center-y="-4.4797486">
+ <g
+ id="g44524-3"
+ inkscape:transform-center-x="6.4130439"
+ style="fill:none;stroke:#000000;stroke-width:2.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" />
+ <g
+ inkscape:transform-center-x="6.4130439"
+ id="g44528-4" />
+ </g>
+ </g>
+ <g
+ transform="matrix(-1,0,0,-1,-75.995432,-28)"
+ id="g44544-8"
+ inkscape:transform-center-y="4.4797485">
+ <g
+ inkscape:transform-center-x="-4.4797485"
+ transform="matrix(-0.7071068,0.7071068,-0.7071068,-0.7071068,-74.7838,3.0074334)"
+ id="g44546-4"
+ inkscape:transform-center-y="-4.4797485">
+ <g
+ id="g44548-9"
+ inkscape:transform-center-x="6.4130439"
+ style="fill:none;stroke:#000000;stroke-width:2.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" />
+ <g
+ inkscape:transform-center-x="6.4130439"
+ id="g44552-9" />
+ </g>
+ <g
+ inkscape:transform-center-y="-4.4797486"
+ id="g44556-2"
+ transform="matrix(0.7071068,0.7071068,-0.7071068,0.7071068,-20.992567,22.7838)"
+ inkscape:transform-center-x="4.4797488">
+ <g
+ style="fill:none;stroke:#000000;stroke-width:2.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:transform-center-x="6.4130439"
+ id="g44558-5">
+ <path
+ d="m 139.82809,116.3993 c 0.21326,1.04297 0.21596,2.11803 0.008,3.16206 m -6.21068,6.20286 c -1.04294,0.21326 -2.11797,0.21596 -3.16197,0.008 m -6.20664,-6.20689 c -0.21326,-1.04297 -0.21596,-2.11803 -0.008,-3.16206 m 6.21068,-6.20286 c 1.04294,-0.21326 2.11797,-0.21596 3.16196,-0.008 m 5.10366,12.24081 c -0.58667,0.88829 -1.34493,1.65039 -2.23019,2.24157 m -11.07625,-11.07658 c 0.58667,-0.88829 1.34492,-1.65038 2.23019,-2.24157 m 8.8404,0.006 c 0.88827,0.58669 1.65034,1.34497 2.24151,2.23026 m -11.07626,11.07657 c -0.88826,-0.58669 -1.65033,-1.34496 -2.2415,-2.23025"
+ style="stroke:#000000;stroke-width:3.44192362;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="matrix(-0.8135104,0,0,-0.8134867,69.383376,81.991427)"
+ id="path44560-5"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g44562-3"
+ inkscape:transform-center-x="6.4130439">
+ <path
+ d="m 139.86607,116.59777 c 0.16588,0.93061 0.16532,1.88326 -0.002,2.81367 m -6.43712,6.39076 c -0.93059,0.16588 -1.88321,0.16532 -2.81359,-0.002 m -6.39454,-6.43334 c -0.16588,-0.93061 -0.16532,-1.88326 0.002,-2.81367 m 6.43712,-6.39076 c 0.93058,-0.16588 1.88321,-0.16532 2.81359,0.002 m 5.25357,12.26879 c -0.58667,0.88829 -1.34493,1.65039 -2.23019,2.24157 m -11.07625,-11.07658 c 0.58667,-0.88829 1.34492,-1.65038 2.23019,-2.24157 m 8.8404,0.006 c 0.88827,0.58669 1.65034,1.34497 2.24151,2.23026 m -11.07626,11.07657 c -0.88826,-0.58669 -1.65033,-1.34496 -2.2415,-2.23025"
+ style="fill:none;stroke:#ffffff;stroke-width:1.72096181;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.8135104,0,0,-0.8134867,69.383376,81.991427)"
+ id="path44564-3"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ transform="matrix(0.4200287,0,0,0.4200289,-40.97369,-75.87647)"
+ id="g45379-3"
+ style="display:inline;enable-background:new">
+ <path
+ transform="matrix(0.75,0,0,0.75,29.5,135)"
+ sodipodi:type="arc"
+ style="fill:#ff541f;fill-opacity:1;fill-rule:nonzero;stroke:#2b0000;stroke-width:2.5395081;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path45381-7"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(-0.6011908,-0.06817113,0.06852359,-0.6012277,199.77148,303.44348)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path45383-4"
+ style="fill:url(#linearGradient24214-1);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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.6;fill:none;stroke:url(#linearGradient24216-4);stroke-width:5.33335066;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:new"
+ id="path45385-3"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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"
+ transform="translate(198,390)">
+ <g
+ mask="url(#mask45447-7)"
+ transform="translate(-261,-409)"
+ id="g15201-1-0"
+ style="opacity:0.8;display:inline;enable-background:new">
+ <rect
+ y="365"
+ x="215"
+ height="16"
+ width="16"
+ id="rect15183-3-8"
+ 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(167.99999,-62.999991)"
+ id="g15185-8-8">
+ <rect
+ ry="0"
+ style="fill:#ececec;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="rect15187-7-0"
+ width="13.016124"
+ height="12.953857"
+ x="48.499996"
+ y="429.54614" />
+ <rect
+ y="430"
+ x="50.016117"
+ height="11.046139"
+ width="11.000001"
+ id="rect15189-4-6"
+ style="fill:url(#linearGradient24218-1);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
+ style="fill:url(#linearGradient24220-5);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 49,430 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,0 0,3 3,0 0,-3 -3,0 z m 0,3 -3,0 0,3 3,0 0,-3 z m 0,3 0,3 3,0 0,-3 -3,0 z m -3,0 -3,0 0,3 3,0 0,-3 z m -3,0 0,-3 -3,0 0,3 3,0 z"
+ id="path15191-2-8"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient24222-6);stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 60.517703,430.5 -11.017704,0 0,11 11.017704,0 0,-11"
+ id="path15193-7-1"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="429.54614"
+ x="48.499996"
+ height="12.953857"
+ width="13.016124"
+ id="rect45403-9"
+ style="fill:url(#radialGradient24224-0);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ ry="0" />
+ </g>
+ </g>
+ <g
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ transform="matrix(0.4200287,0,0,0.4200289,-86.973687,-124.87647)"
+ id="g45391-8"
+ style="display:inline;enable-background:new">
+ <path
+ transform="matrix(0.75,0,0,0.75,29.5,135)"
+ sodipodi:type="arc"
+ style="fill:#ff541f;fill-opacity:1;fill-rule:nonzero;stroke:#2b0000;stroke-width:2.5395081;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="path45393-9"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(-0.6011908,-0.06817113,0.06852359,-0.6012277,199.77148,303.44348)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path45395-7"
+ style="fill:url(#linearGradient24226-2);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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.75;fill:none;stroke:url(#linearGradient24228-5);stroke-width:5.33335066;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:new"
+ id="path45397-2"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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"
+ transform="matrix(-1,0,0,1,16.999998,490)">
+ <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"
+ id="rect45977-5-8"
+ width="16"
+ height="16"
+ x="-46"
+ y="128" />
+ <g
+ mask="url(#mask45865-7)"
+ style="opacity:0.95"
+ id="g45749-2">
+ <path
+ sodipodi:nodetypes="cssssssc"
+ id="path45716-8"
+ d="m -37.991001,-135.06482 c -0.756259,0.48145 -1.648418,-0.21174 -1.880274,-0.94014 -0.414735,-1.30293 0.637877,-2.55676 1.880274,-2.82041 1.823267,-0.38691 3.481311,1.06592 3.760547,2.82041 0.372178,2.33846 -1.494127,4.41212 -3.760547,4.70069 -2.852058,0.36313 -5.346025,-1.9223 -5.640821,-4.70069 -0.357038,-3.365 2.346435,-6.33509 5.640821,-6.58096 3.825581,-0.28552 7.055689,2.67913 7.813138,6.13556"
+ style="fill:none;stroke:#000000;stroke-width:2.77754736;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ transform="matrix(0.6590823,0.8571222,-0.8500307,0.6645808,-129.57187,-12.997286)"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="matrix(0.6590823,0.8571222,-0.8500307,0.6645808,-129.57187,-12.997286)"
+ style="fill:none;stroke:#ffffff;stroke-width:1.1110189;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -37.991001,-135.06482 c -0.756259,0.48145 -1.648418,-0.21174 -1.880274,-0.94014 -0.414735,-1.30293 0.637877,-2.55676 1.880274,-2.82041 1.823267,-0.38691 3.481311,1.06592 3.760547,2.82041 0.372178,2.33846 -1.494127,4.41212 -3.760547,4.70069 -2.852058,0.36313 -5.346025,-1.9223 -5.640821,-4.70069 -0.357038,-3.365 2.346435,-6.33509 5.640821,-6.58096 3.825581,-0.28552 7.055689,2.67913 7.813138,6.13556"
+ id="path45712-9"
+ sodipodi:nodetypes="cssssssc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g29693-0"
+ transform="matrix(-1,0,0,1,-78.286205,4.2655334)">
+ <rect
+ rx="1.4999387"
+ ry="1.4999387"
+ y="-141.76553"
+ x="-39.799313"
+ height="3"
+ width="2.9998772"
+ id="rect29695-7"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#5a0d00;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"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ id="path29697-8"
+ d="m -37.299433,-141.26553 -1.999997,1e-5 0,1.99999 1.999997,-10e-6 0,-1.99999 z"
+ style="fill:#ff541f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000072;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path29699-1"
+ d="m -38.799427,-139.76553 0,-1 0.999994,0"
+ style="opacity:0.45;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ style="opacity:0.4;fill:#ffffff;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 -38.29943,-141.26553 -1,1e-5 0,0.99999 1,0 0,-1 z"
+ id="path29701-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"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g45137-8"
+ transform="translate(156,308)">
+ <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"
+ id="rect46015-6"
+ width="16"
+ height="16"
+ x="-46"
+ y="-54" />
+ <g
+ id="g45118-1">
+ <g
+ id="g45099-2"
+ transform="translate(0,6.9866005)">
+ <g
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ transform="matrix(0.6645615,0,0,0.6645596,-126.90026,-106.03317)"
+ id="g37580-2-4"
+ style="display:inline;enable-background:new">
+ <path
+ transform="matrix(0.75,0,0,0.75,29.5,135)"
+ sodipodi:type="arc"
+ style="fill:#ff541f;fill-opacity:1;fill-rule:nonzero;stroke:#2b0000;stroke-width:1.60507059;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="path37582-3-2"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(-0.683022,-0.07745026,0.0778507,-0.683064,209.4726,314.325)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path37584-3-5"
+ style="opacity:0.6;fill:url(#linearGradient24230-5);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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.7;fill:none;stroke:url(#linearGradient24232-9);stroke-width:2.66303396;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:new"
+ id="path38120-7-4-8"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ transform="matrix(0.5650525,0,0,0.5650532,53.91307,156.82373)" />
+ </g>
+ <g
+ style="opacity:0.5;fill:#ffd5d5"
+ id="g45083-6">
+ <rect
+ ry="0.88169974"
+ rx="0.88169974"
+ y="42.25"
+ x="-44"
+ height="1.7633995"
+ width="5.5"
+ id="rect45079-2"
+ style="fill:#ffd5d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000083;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
+ <rect
+ ry="0.875"
+ rx="0.97123623"
+ style="fill:#ffd5d5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000083;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ id="rect45081-6"
+ width="5.5"
+ height="1.75"
+ x="40"
+ y="40"
+ transform="matrix(0,1,-1,0,0,0)" />
+ </g>
+ <rect
+ y="41.986599"
+ x="-44.006248"
+ height="1.0133995"
+ width="5.0062485"
+ id="rect45067-5"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000083;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
+ <rect
+ transform="matrix(0,-1,1,0,0,0)"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000083;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ id="rect45069-3"
+ width="4.9865952"
+ height="1.0133995"
+ x="-44.986595"
+ y="-42.009823" />
+ </g>
+ <g
+ id="g45110-9"
+ transform="translate(0,-6.986599)">
+ <g
+ style="display:inline;enable-background:new"
+ id="g44887-2"
+ transform="matrix(0.6610822,0,0,0.6610806,-119.47405,-98.276513)"
+ 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">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path44889-4"
+ style="fill:#f2f2f2;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.61351788;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.75,0,0,0.75,29.5,135)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient24234-7);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path44891-6"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path44893-1"
+ style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:2.64463997;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:new"
+ 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" />
+ </g>
+ <rect
+ ry="1.0066998"
+ rx="1.0066998"
+ y="49"
+ x="-37"
+ height="2.0133996"
+ width="5.5"
+ id="rect45087-8"
+ style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000083;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000083;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ id="rect45077-2"
+ width="5.0062485"
+ height="1.0133995"
+ x="-37.006248"
+ y="48.986599" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g24618-1"
+ transform="translate(168,176)">
+ <rect
+ ry="0"
+ rx="0"
+ y="170"
+ x="5"
+ height="16"
+ width="16"
+ id="rect42080-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
+ mask="url(#mask43040-7)"
+ transform="translate(51.040182,194)"
+ id="g42934-9">
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ sodipodi:nodetypes="csc"
+ id="path42084-7"
+ d="m -43,-12 c 4.5365,0 10.5,-1.75 10.5,-6 0,-1.75 -1.25,-4 -5.5,-4"
+ style="fill:none;stroke:#3c0800;stroke-width:3.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"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#3c0800;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="rect42088-6"
+ width="2.9998772"
+ height="3"
+ x="-39.499878"
+ y="-23.5"
+ ry="1.4999387"
+ rx="1.4999387" />
+ <rect
+ rx="1.4999387"
+ ry="1.4999387"
+ y="-13.5"
+ x="-44.499878"
+ height="3"
+ width="2.9998772"
+ id="rect42092-2"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#5a0d00;stroke-width:0.5;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
+ style="fill:none;stroke:#ed5e32;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 -43,-12 c 4.5365,0 10.5,-1.75 10.5,-6 0,-1.75 -1.25,-4 -5.5,-4"
+ id="path42142-9"
+ sodipodi:nodetypes="csc"
+ 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"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient24236-2);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 -43,-12 c 4.5365,0 10.5,-1.75 10.5,-6 0,-1.75 -1.25,-4 -5.5,-4"
+ id="path42140-5"
+ sodipodi:nodetypes="csc"
+ 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"
+ 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="path42094-2"
+ d="m -42,-13 c -0.67541,0 -1.35081,10e-6 -2.02623,10e-6 0,0.66939 0,1.33877 0,2.00817 0.67542,0 1.35082,-10e-6 2.02623,-10e-6 0,-0.66939 0,-1.33878 0,-2.00817 z"
+ style="fill:#ff541f;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="fill:#ff8d69;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 -37,-23 c -0.65334,0 -1.30668,10e-6 -1.96003,10e-6 0,0.66667 0,1.33332 0,1.99999 0.65335,0 1.30669,-10e-6 1.96003,-10e-6 0,-0.66666 0,-1.33332 0,-1.99999 z"
+ id="path42096-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"
+ 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;display:inline"
+ d="m -38.5,-21.5 0,-1 1,0"
+ id="path42098-0"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path42100-3"
+ d="m -43.52623,-11.5 0,-1 1,0"
+ style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ 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="path42102-9"
+ d="m -36,-20.48792 c -0.32001,0 -0.64002,-10e-6 -0.96003,-10e-6 0,-0.63982 0,-1.27964 0,-1.91948 0.32001,0 0.64002,10e-6 0.96003,10e-6 0,0.63983 0,1.27966 0,1.91948 z"
+ style="opacity:0.15;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.5;fill:#ff541f;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 -40.999878,-11 c -0.32001,0 -0.64002,0 -0.96003,0 0,-0.21055 0,-0.42107 0,-0.63162 0.32001,0 0.64002,0 0.96003,0 0,0.21055 0,0.42107 0,0.63162 z"
+ id="path42104-1"
+ 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="path42106-8"
+ d="m -40.999878,-11.33707 c -0.32001,0 -0.64002,-10e-6 -0.96003,-10e-6 0,-0.55431 0,-1.1086 0,-1.66292 0.32001,0 0.64002,10e-6 0.96003,10e-6 0,0.55431 0,1.10861 0,1.66292 z"
+ style="opacity:0.25;fill:#ff541f;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" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g44965-1"
+ transform="matrix(0.5000262,0,0,0.5000067,-54.73874,70.74849)"
+ 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">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path44967-9"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.13326335;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.75,0,0,0.75,29.5,135)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient24239-1);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path44969-5"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path44971-3"
+ style="opacity:0.5;fill:none;stroke:#ffffff;stroke-width:4.0295496;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:new"
+ 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" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g43314-2"
+ transform="translate(177,410)">
+ <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"
+ id="rect43157-5"
+ width="16"
+ height="16"
+ x="-46"
+ y="48" />
+ <g
+ id="g43221-2"
+ transform="matrix(1.1891377,0,0,1.189137,-45.334548,102.47504)"
+ style="display:inline;enable-background:new">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path43224-5"
+ style="fill:#dcdcdc;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.86864018;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.3150215,0,0,0.3150217,-36.662669,-174.25239)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.79000005;fill:url(#linearGradient24241-6);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path43226-8"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path43228-6"
+ style="opacity:0.6;fill:none;stroke:url(#linearGradient24243-1);stroke-width:4.00001144;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:new"
+ 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" />
+ </g>
+ <g
+ transform="matrix(0.9963903,0,0,1,-2.1155075,0)"
+ id="g43169-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"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path43170-7"
+ style="fill:#ff5b29;fill-opacity:1;fill-rule:nonzero;stroke:#2b0000;stroke-width:1.6028651;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.5625217,0,0,0.5624997,-110.25304,-122.37496)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient24245-3);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path43172-2"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path43174-2"
+ style="opacity:0.65;fill:none;stroke:url(#linearGradient24247-8);stroke-width:2.29000854;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:new"
+ 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" />
+ </g>
+ <g
+ transform="matrix(0,-1,-1,0,-93.999999,-92)"
+ id="g42385-9">
+ <path
+ sodipodi:nodetypes="csscc"
+ id="path42387-4"
+ d="m -36.5,-51.499999 c -0.5,1 -1.34258,1.996832 -2.996831,1.996832 -1.654251,0 -3,-1.345743 -3,-2.999994 0,-1.308742 0.996831,-2.496838 1.996831,-2.996838 l 4,4 z"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient24249-9);stroke-width:0.89999998;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient24251-6);fill-opacity:1;fill-rule:nonzero"
+ d="m -36.5,-51.499999 c -0.5,1 -1.34258,1.996832 -2.996831,1.996832 -1.654251,0 -2.996872,-1.345746 -3,-2.999994 C -42.5,-54.175184 -41.5,-54.999999 -40.5,-55.499999 l 4,4 z"
+ id="path43279-1"
+ sodipodi:nodetypes="csscc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccsss"
+ id="path42392-9"
+ d="m -40.75,-54.249999 3,3 c -0.25,0.25 -0.659057,0.708509 -1.758414,0.708509 -1.099355,0 -1.991586,-0.877412 -1.991586,-1.958509 0,-1.081096 0.5,-1.5 0.75,-1.75 z"
+ style="opacity:0.6;fill:none;stroke:url(#linearGradient24253-0);stroke-width:1.00000048;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(1.1891377,0,0,1.189137,-39.353927,107.5067)"
+ id="g43258-6"
+ style="display:inline;enable-background:new">
+ <path
+ transform="matrix(0.3150215,0,0,0.3150217,-36.662669,-174.25239)"
+ sodipodi:type="arc"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient24255-6);stroke-width:2.40253735;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path43260-9"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(-0.2610878,-0.02960567,0.02975872,-0.2611039,35.872259,-102.36161)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path43262-8"
+ style="fill:url(#linearGradient24257-6);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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.7;fill:none;stroke:url(#linearGradient24259-1);stroke-width:4.00001144;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:new"
+ id="path43264-2"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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">
+ <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"
+ id="rect49020-5"
+ width="16"
+ height="16"
+ x="-46"
+ y="69" />
+ <g
+ id="g49022-4"
+ style="opacity:0.5">
+ <g
+ id="g49024-9"
+ mask="url(#mask48816-8)"
+ style="opacity:0.4;display:inline;enable-background:new">
+ <path
+ id="path49027-1"
+ d="M -42.5,-79.5 -32,-83"
+ style="fill:none;stroke:#2b0800;stroke-width:2.70000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ff8d73;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M -42.5,-79.5 -32,-83"
+ id="path49031-2"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g49034-5">
+ <g
+ style="display:inline;enable-background:new"
+ id="g49036-0"
+ transform="matrix(1.1891377,0,0,1.189137,-48.353927,83.503529)">
+ <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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path49039-8"
+ style="fill:#ececec;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.13558888;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ sodipodi:type="arc"
+ transform="matrix(0.3150215,0,0,0.3150217,-36.662669,-174.25239)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient24279-6);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ id="path49043-3"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path49045-9"
+ style="fill:none;stroke:url(#linearGradient24281-3);stroke-width:4.00001144;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:new"
+ 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" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g49048-3"
+ style="opacity:0.8">
+ <g
+ style="opacity:0.5"
+ mask="url(#mask48816-8)"
+ id="g49050-9">
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#2b0800;stroke-width:2.70000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M -39.5,-75.5 -32,-83"
+ id="path49055-6"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path49057-7"
+ d="M -39.5,-75.5 -32,-83"
+ style="fill:none;stroke:#ff8d73;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g49059-9">
+ <g
+ transform="matrix(1.1891377,0,0,1.189137,-45.367039,87.538326)"
+ id="g49061-9"
+ style="display:inline;enable-background:new">
+ <path
+ transform="matrix(0.3150215,0,0,0.3150217,-36.662669,-174.25239)"
+ sodipodi:type="arc"
+ style="fill:#ececec;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.13558888;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path49065-7"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(-0.2610878,-0.02960567,0.02975872,-0.2611039,35.872259,-102.36161)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path49067-6"
+ style="fill:url(#linearGradient24283-7);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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="fill:none;stroke:url(#linearGradient24285-8);stroke-width:4.00001144;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:new"
+ id="path49069-9"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ transform="matrix(0.2102357,0,0,0.2102362,-22.830954,-161.8877)" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g49071-3">
+ <g
+ id="g49073-5"
+ mask="url(#mask28585-8)">
+ <path
+ id="path49075-7"
+ d="M -34.5,-72.5 -32,-83"
+ style="fill:none;stroke:#2b0800;stroke-width:2.70000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ff8d73;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M -34.5,-72.5 -32,-83"
+ id="path49077-6"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ transform="matrix(1.1891377,0,0,1.189137,-40.353927,90.509865)"
+ id="g49079-6"
+ style="display:inline;enable-background:new">
+ <path
+ transform="matrix(0.3150215,0,0,0.3150217,-36.662669,-174.25239)"
+ sodipodi:type="arc"
+ style="fill:#ececec;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.13558888;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ id="path49082-5"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(-0.2610878,-0.02960567,0.02975872,-0.2611039,35.872259,-102.36161)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path49084-8"
+ style="fill:url(#linearGradient24287-1);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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="fill:none;stroke:url(#linearGradient24289-3);stroke-width:4.00001144;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:new"
+ id="path49086-2"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 z"
+ transform="matrix(0.2102357,0,0,0.2102362,-22.830954,-161.8877)" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ transform="translate(6.299313,57.265533)"
+ id="g49088-5">
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#5a0d00;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="rect49090-4"
+ width="2.9998772"
+ height="3"
+ x="-39.799313"
+ y="-141.76553"
+ ry="1.4999387"
+ rx="1.4999387" />
+ <path
+ style="fill:#ff541f;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 -37.299433,-141.26553 c -0.65334,0 -1.30668,1e-5 -1.96003,1e-5 0,0.66667 0,1.33332 0,1.99999 0.65335,0 1.30669,-10e-6 1.96003,-10e-6 0,-0.66666 0,-1.33332 0,-1.99999 z"
+ id="path49092-4"
+ 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.45;fill:none;stroke:#ffffff;stroke-width:1px;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 -38.799433,-139.76553 0,-1 1,0"
+ id="path49094-1"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g33096-6"
+ transform="translate(189,147)">
+ <g
+ transform="translate(51,203)"
+ id="g45912-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="rect35680-9-6"
+ width="16"
+ height="16"
+ x="-46"
+ y="-4" />
+ <g
+ style="opacity:0.95;display:inline;enable-background:new"
+ transform="translate(-491,-214.9763)"
+ id="g35844-1-3"
+ inkscape:transform-center-x="-0.78726"
+ inkscape:transform-center-y="2.2787562">
+ <path
+ style="opacity:0.95;fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 454.5,218.5 c -1.25,-1.5 -2.5,-1.5 -4,1 -1.5,-2.5 -2.75,-2.5 -4,-1"
+ id="path35846-9-3"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path35848-8-5"
+ d="m 454.5,218.5 c -1.25,-1.5 -2.5,-1.5 -4,1 -1.5,-2.5 -2.75,-2.5 -4,-1"
+ style="fill:none;stroke:#f2f2f2;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect35914-6-5"
+ width="1"
+ height="2"
+ x="450"
+ y="217.9763" />
+ <rect
+ y="217.9763"
+ x="449.25"
+ height="1"
+ width="0.75"
+ id="rect35916-5-3"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.60000002;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:0.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect35919-0-2"
+ width="0.75"
+ height="1"
+ x="451"
+ y="217.9763" />
+ </g>
+ <g
+ id="g38276-9-8"
+ transform="translate(-324,-461)">
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path35702-0-2"
+ d="m 292.5,459.5 c -1.25,-1.5 -3.5,-1.5 -5,1 -1.5,-2.5 -3.75,-2.5 -5,-1"
+ style="opacity:0.95;fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ececec;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 292.5,459.5 c -1.25,-1.5 -3.5,-1.5 -5,1 -1.5,-2.5 -3.75,-2.5 -5,-1"
+ id="path35704-0-5"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ <rect
+ y="459"
+ x="287"
+ height="2"
+ width="1"
+ id="rect35908-6-3"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.60000002;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:0.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect35910-1-6"
+ width="0.75"
+ height="1"
+ x="286.25"
+ y="459" />
+ <rect
+ y="459"
+ x="288"
+ height="1"
+ width="0.75"
+ id="rect35912-3-1"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <g
+ style="opacity:0.9;display:inline;enable-background:new"
+ transform="translate(-484,-209.97631)"
+ id="g45582-8"
+ inkscape:transform-center-x="-0.78726"
+ inkscape:transform-center-y="2.2787562">
+ <path
+ style="opacity:0.95;fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 452.5,218.47631 -1,-1 -2,2 -2,-2 -1,1.02369"
+ id="path45584-6"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path45586-2"
+ d="m 452.5,218.47631 -1,-1 -2,2 -2,-2 -1,1.02369"
+ style="fill:none;stroke:#ffffff;stroke-width:0.80000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect45588-1"
+ width="1"
+ height="1.4999862"
+ x="449"
+ y="218.4763" />
+ <rect
+ y="217.9763"
+ x="448"
+ height="0.99998617"
+ width="1"
+ id="rect45590-4"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.60000002;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:0.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect45592-6"
+ width="1"
+ height="0.99998617"
+ x="447"
+ y="216.9763" />
+ <rect
+ y="217.9763"
+ x="446"
+ height="0.99998617"
+ width="1"
+ id="rect45594-2"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.60000002;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:0.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect45596-9"
+ width="1"
+ height="0.99998617"
+ x="452"
+ y="217.9763" />
+ <rect
+ y="216.9763"
+ x="451"
+ height="0.99998617"
+ width="1"
+ id="rect45598-1"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.60000002;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:0.60000002;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect45600-5"
+ width="1"
+ height="0.99998617"
+ x="450"
+ y="217.9763" />
+ </g>
+ </g>
+ <g
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ transform="matrix(0.3350147,0,0,0.3350147,-35.55948,137.66413)"
+ id="g29713-0"
+ style="display:inline;enable-background:new">
+ <path
+ transform="matrix(0.75,0,0,0.75,29.5,135)"
+ sodipodi:type="arc"
+ style="fill:#ff541f;fill-opacity:1;fill-rule:nonzero;stroke:#320b00;stroke-width:3.58193231;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="path29715-3"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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
+ transform="matrix(-0.6011908,-0.06817113,0.06852359,-0.6012277,199.77148,303.44348)"
+ 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 1 1 -16,0 8,8 0 1 1 16,0 z"
+ sodipodi:ry="8"
+ sodipodi:rx="8"
+ sodipodi:cy="118"
+ sodipodi:cx="132"
+ id="path29717-6"
+ style="opacity:0.6;fill:url(#linearGradient33126-9);fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ 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.7;fill:none;stroke:url(#linearGradient33128-2);stroke-width:6.6867547;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:new"
+ id="path29719-4"
+ sodipodi:cx="132"
+ sodipodi:cy="118"
+ sodipodi:rx="8"
+ sodipodi:ry="8"
+ d="m 140,118 a 8,8 0 1 1 -16,0 8,8 0 1 1 16,0 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"
+ transform="translate(21,273)">
+ <rect
+ y="73"
+ x="47"
+ height="16"
+ width="16"
+ id="rect24980-2"
+ style="opacity:0;fill:#808080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ clip-path="none"
+ mask="none"
+ id="g24568-9"
+ transform="translate(93,198.04787)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2.79999995;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 -44.5,-117.48534 c 0,1 1,3 5.5,3 5.25,0 7.5,-3.26466 7.5,-6.01466 0,-1.5 -0.5,-2.25 -1,-3"
+ id="path24570-3"
+ sodipodi:nodetypes="cssc"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g24572-4"
+ mask="url(#mask43050-6)"
+ transform="translate(-22,0)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2.79999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -11.5,-110.54787 c 2.25,-1.5 2,-3.45213 2,-4.20213 0,-1.6875 -2.25,-5.75 -7.5,-5.75 -4.5,0 -5.5,2 -5.5,3"
+ id="path24574-4"
+ sodipodi:nodetypes="cssz"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cssz"
+ id="path24576-0"
+ d="m -11.5,-110.54787 c 2.25,-1.5 2,-3.45213 2,-4.20213 0,-1.6875 -2.25,-5.75 -7.5,-5.75 -4.5,0 -5.5,2 -5.5,3"
+ style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.65;fill:none;stroke:url(#radialGradient24295-1);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m -11.5,-110.54787 c 2.25,-1.5 2,-3.45213 2,-4.20213 0,-1.6875 -2.25,-5.75 -7.5,-5.75 -4.5,0 -5.5,2 -5.5,3"
+ id="path24578-5"
+ sodipodi:nodetypes="cssz"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cssz"
+ id="path24580-9"
+ d="m -11.5,-110.54787 c 2.5,-1.5 2,-3.45213 2,-4.20213 0,-1.6875 -2.25,-5.75 -7.5,-5.75 -4.5,0 -5.5,2 -5.5,3"
+ style="opacity:0.65;fill:none;stroke:url(#radialGradient24297-0);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ sodipodi:type="arc"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path24582-6"
+ sodipodi:cx="-10.5"
+ sodipodi:cy="-117.5"
+ sodipodi:rx="1.5"
+ sodipodi:ry="1.5"
+ d="m -9,-117.5 a 1.5,1.5 0 1 1 -3,0 1.5,1.5 0 1 1 3,0 z"
+ transform="matrix(1,0,0,1.4166681,-22,49.0835)" />
+ <g
+ id="g24584-3">
+ <rect
+ y="-124.50001"
+ x="-39.75"
+ height="14.999989"
+ width="2.5"
+ id="rect24586-4"
+ style="fill:#821b00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#ff9d7d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24588-2"
+ width="1"
+ height="14.999989"
+ x="-39"
+ y="-124.50001" />
+ <rect
+ style="fill:url(#radialGradient24299-9);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24590-8"
+ width="2"
+ height="14.999989"
+ x="-39.5"
+ y="-124.50001" />
+ </g>
+ <path
+ sodipodi:nodetypes="cssc"
+ id="path24592-8"
+ d="m -44.5,-117.48534 c 0,1 1,3 5.5,3 5.25,0 7.5,-3.26466 7.5,-6.01466 0,-1.5 -0.5,-2.25 -1,-3"
+ style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ 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"
+ transform="translate(0.03262657,-0.06636782)">
+ <g
+ 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\fullscreen.png"
+ transform="translate(-125.61657,-482.86685)"
+ id="g44633-8"
+ style="display:inline;enable-background:new">
+ <g
+ transform="matrix(-1,0,0,-1,662.9375,1247)"
+ id="g44671-4">
+ <g
+ transform="matrix(-1,0,0,1,677,525)"
+ id="g44635-3">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path44637-0"
+ d="m 347.25,100.25 -4,-4"
+ style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path44639-9"
+ d="m 343,100.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#000000;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" />
+ </g>
+ <g
+ transform="matrix(-1,0,0,1,677,517)"
+ id="g44647-2">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#dcdcdc;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 347.25,108.25 343,104"
+ id="path44649-6"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#dcdcdc;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 343,108.25 0,-4.25 4.25,0"
+ id="path44651-7"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path44653-5"
+ d="m 332.5,621.5 -3,0 m 5,4 0,-4.5"
+ style="opacity:0.93999993;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path44655-9"
+ d="m 330,625.75 2,-2"
+ style="opacity:0.93999993;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path44657-2"
+ d="m 333,622 0,1 0,1.5 -1,0 0,-1.5 -1.5,0 0,-1 1.5,0 1,0 z"
+ style="opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <g
+ transform="matrix(-1,0,0,-1,648.9375,1261)"
+ id="g44682-2">
+ <g
+ id="g44641-6"
+ transform="matrix(1,0,0,-1,-21,729)">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000;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"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000;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"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <g
+ id="g44659-9"
+ transform="matrix(1,0,0,-1,-21,737)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path44661-9"
+ d="M 347.25,108.25 343,104"
+ style="fill:none;stroke:#dcdcdc;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" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path44663-9"
+ d="m 343,108.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#dcdcdc;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" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.93999993;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 322.5,631.5 0,-3 m 4,5 -4.5,0"
+ id="path44665-0"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.93999993;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 326.75,629 -2,2"
+ id="path44667-6"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 323,632 0,-1 0,-1.5 1,0 0,1.5 1.5,0 0,1 -1.5,0 -1,0 z"
+ id="path44669-4" />
+ </g>
+ </g>
+ <g
+ transform="translate(-10.783378,-1.2374369)"
+ id="g29973">
+ <rect
+ style="fill:none;stroke:#402100;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="rect39229-9"
+ width="2.9998772"
+ height="3"
+ x="-153.41948"
+ y="204.7984"
+ ry="0"
+ rx="0"
+ transform="matrix(0,-1,1,0,0,0)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ffc17d;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 205.2984,150.91921 c 0,0.6694 1e-5,1.3388 1e-5,2.0082 0.66939,0 1.33877,0 2.00817,0 0,-0.6694 -1e-5,-1.3388 -1e-5,-2.0082 -0.66939,0 -1.33878,0 -2.00817,0 z"
+ id="path39231-8"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\BLENDER ICONSET\blender-cvs-windows\.blender\.blender\icons\jendrzych's iconset.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ </g>
+ <g
+ transform="translate(2.1213231,-14.318909)"
+ id="g29973-5"
+ style="display:inline;enable-background:new">
+ <rect
+ style="fill:none;stroke:#402100;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="rect39229-9-8"
+ width="2.9998772"
+ height="3"
+ x="-153.41948"
+ y="204.7984"
+ ry="0"
+ rx="0"
+ transform="matrix(0,-1,1,0,0,0)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ffc17d;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 205.2984,150.91921 c 0,0.6694 1e-5,1.3388 1e-5,2.0082 0.66939,0 1.33877,0 2.00817,0 0,-0.6694 -1e-5,-1.3388 -1e-5,-2.0082 -0.66939,0 -1.33878,0 -2.00817,0 z"
+ id="path39231-8-9"
+ 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="g30336">
+ <g
+ style="opacity:1;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"
+ 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"
+ d="m 343,100.25 0,-4.25 4.25,0"
+ id="path44645-3-3"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <g
+ id="g44659-9-4"
+ transform="matrix(-1,0,0,1,565.35356,41.06678)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path44661-9-9"
+ d="M 347.25,108.25 343,104"
+ style="fill:none;stroke:#dcdcdc;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" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path44663-9-4"
+ d="m 343,108.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#dcdcdc;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" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.93999993;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 221.85356,146.56678 0,3 m -4,-5 4.5,0"
+ id="path44665-0-4"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.93999993;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 217.60356,149.06678 2,-2"
+ id="path44667-6-6"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 221.35356,146.06678 0,1 0,1.5 -1,0 0,-1.5 -1.5,0 0,-1 1.5,0 1,0 z"
+ id="path44669-4-5" />
+ <rect
+ transform="matrix(0,-1,1,0,0,0)"
+ rx="0"
+ ry="0"
+ y="215.04765"
+ x="-152.11568"
+ 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" />
+ <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="path39231-8-6"
+ d="m 215.54765,149.61541 c 0,0.6694 1e-5,1.3388 1e-5,2.0082 0.66939,0 1.33877,0 2.00817,0 0,-0.6694 -10e-6,-1.3388 -10e-6,-2.0082 -0.66939,0 -1.33878,0 -2.00817,0 z"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g30322">
+ <g
+ id="g44635-3-6"
+ 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"
+ 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"
+ d="m 343,100.25 0,-4.25 4.25,0"
+ id="path44639-9-5"
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g44647-2-0"
+ transform="matrix(1,0,0,-1,-118.64644,247.06678)">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path44649-6-7"
+ d="M 347.25,108.25 343,104"
+ style="fill:none;stroke:#dcdcdc;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"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path44651-7-3"
+ d="m 343,108.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#dcdcdc;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"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="opacity:0.93999993;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 225.85356,142.56678 3,0 m -5,-4 0,4.5"
+ id="path44653-5-3"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.93999993;fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new"
+ d="m 228.35356,138.31678 -2,2"
+ id="path44655-9-8"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 225.35356,142.06678 0,-1 0,-1.5 1,0 0,1.5 1.5,0 0,1 -1.5,0 -1,0 z"
+ id="path44657-2-3"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 228.45235,136.53393 c 0,0.6694 1e-5,1.3388 1e-5,2.0082 0.66939,0 1.33877,0 2.00817,0 0,-0.6694 -1e-5,-1.3388 -1e-5,-2.0082 -0.66939,0 -1.33878,0 -2.00817,0 z"
+ id="path39231-8-9-4"
+ 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>
+ <rect
+ transform="matrix(0,-1,1,0,0,0)"
+ rx="0"
+ ry="0"
+ y="227.95235"
+ x="-139.03419"
+ 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" />
+ </g>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer6"
+ inkscape:label="Python icons"
+ style="display:none">
+ <g
+ style="display:inline;enable-background:new"
+ id="g30250-6"
+ transform="matrix(-1,0,0,1,788.49395,-2.4863553)" />
+ <g
+ id="g59188"
+ transform="translate(441,-963.36218)"
+ style="display:inline;enable-background:new">
+ <rect
+ style="opacity:0;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect59190"
+ width="16"
+ height="16"
+ x="26"
+ y="1036.3622" />
+ <g
+ transform="translate(-727,832.3622)"
+ id="g59192"
+ style="display:inline;enable-background:new">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient106804);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 756.16666,204.50001 8.33334,-1e-5 0,13.99999 -11,1e-5 -10e-6,-10.99999 2.66667,-3 z"
+ id="path59194"
+ 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="path59196"
+ d="m 756.16666,204.50001 8.33334,-1e-5 0,13.99999 -11,1e-5 -10e-6,-10.99999 2.66667,-3 z"
+ style="opacity:0.3;fill:url(#radialGradient106806);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="path59198"
+ style="fill:none;stroke:url(#linearGradient106808);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 5.5,0"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path59200"
+ 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="path59202"
+ 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,11.49999 11,-1e-5 0,-13.99999 -8.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(#linearGradient106810);stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 757.5,206.5 0,2 -2,0"
+ id="path59204" />
+ </g>
+ <g
+ id="g59206"
+ transform="translate(26,2.12e-5)">
+ <g
+ transform="translate(42,3.0002)"
+ id="g59208">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#4381b3;fill-opacity:1;stroke:none"
+ d="m -32.5,1036.8622 c -3,0 -3,1.5128 -3,2.0128 l 0,0.9872 -0.5,0 c -0.25,0 -2.5,10e-4 -2.5,3 0,2.9988 2.25,3 2.5,3 l 0.5,0 0,-1 c 0,-1.1046 0.89543,-2 2,-2 l 2,-0.013 c 1.10457,0 2,-0.8954 2,-2 l 0,-1.9872 c 0,-0.5 0,-2 -3,-2 l 0,0 0,2e-4 z"
+ id="path59210"
+ sodipodi:nodetypes="ccccsccccccccc" />
+ <rect
+ style="opacity:0.01000001;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="rect59212"
+ width="0.99999928"
+ height="1.0468764"
+ x="-34"
+ y="1038.3153" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccsccccccccc"
+ id="path59214"
+ d="m -32.5,1048.8622 c 3,0 3,-1.5128 3,-2.0128 l 0,-0.9872 0.5,0 c 0.25,0 2.5,-10e-4 2.5,-3 0,-2.9988 -2.25,-3 -2.5,-3 l -0.5,0 0,1 c 0,1.1046 -0.89543,2 -2,2 l -2,0.013 c -1.10457,0 -2,0.8954 -2,2 l 0,1.9872 c 0,0.5 0,2 3,2 l 0,0 0,-2e-4 z"
+ style="fill:#ffd43b;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="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m -32.5,1036.8622 c -3,0 -3,1 -3,2.0128 l 0,0.9872 3.5,0 -4,0.013 c -0.25,0 -2.5,10e-4 -2.5,3 0,2.9988 2.25,3 2.5,3 l 0.5,0 0,1 c 0,0.9872 0,1.9872 3,1.9872 3,0 3,-1.0128 3,-2 l 0,-1 -2.5,0 3,0 c 0.25,0 2.5,-10e-4 2.5,-3 0,-2.9988 -2.25,-3 -2.5,-3 l -0.5,0 0,-1 c 0,-1.0128 0,-2 -3,-2 l 0,-2e-4 z"
+ id="path59216"
+ sodipodi:nodetypes="cccccscccsccccscccz" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;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 -29.5,1039.8622 0,1 c 0,1.1046 -0.89543,2 -2,2 l -2,0 c -1.10457,0 -2,0.8954 -2,2 l 0,1"
+ id="path59218"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cszs"
+ id="path59220"
+ d="m -30.5,1041.3622 0,-2.5 c 0,-0.5128 0.25,-1 -2,-1 -2.15993,0 -1.99997,0.4872 -2,1"
+ style="fill:none;stroke:url(#linearGradient106812);stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient106814);stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m -32.5,1040.8494 -3.49995,0.013 c -1.00005,0 -1.50005,0.7372 -1.5,2 5e-5,1.285 0.49995,2 1.5,2"
+ id="path59222"
+ sodipodi:nodetypes="cszs" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ d="m -34.5,1044.8494 c 0,-0.5 0.5,-1 1,-1 l 2,0.013 c 1.64438,0 3,-1.3428 3,-2.9872 m -6,3.9744 0,3.5"
+ style="fill:none;stroke:url(#linearGradient106816);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path59224" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ id="path59226"
+ style="fill:none;stroke:url(#linearGradient106818);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m -31.5,1046.8494 1,0.013" />
+ </g>
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ transform="translate(172,-563.36218)"
+ id="g3978-5">
+ <rect
+ style="opacity:0;fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible"
+ id="rect3980-2"
+ width="16"
+ height="15.999996"
+ x="211"
+ y="594.36218"
+ rx="0" />
+ <path
+ style="fill:#5590bf;fill-opacity:1;stroke:none"
+ d="m 219,594.875 c -3.5,10e-6 -3.5,1.5 -3.5,2 l 0,2 -0.5,0 c -0.25,0 -2.5,10e-4 -2.5,3 0,2.99883 2.25,2.99999 2.5,3 l 0.5,0 0,-1 c 0,-1.10457 0.89543,-2 2,-2 l 3,0 c 1.10457,0 2,-0.89543 2,-2 l 0,-3 c 0,-0.5 0,-2.00001 -3.5,-2 z"
+ id="path3982-7"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="opacity:0.01000001;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="rect3984-6"
+ width="0.99999928"
+ height="1.0468764"
+ x="217"
+ y="596.31531" />
+ <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="rect3986-1"
+ width="0.99999928"
+ height="1.0000014"
+ x="217"
+ y="596.36218" />
+ <path
+ id="path3988-4"
+ d="m 219,608.86218 c 3.5,-10e-6 3.5,-1.5 3.5,-2 l 0,-2 0.5,0 c 0.25,0 2.5,-10e-4 2.5,-3 0,-2.99883 -2.25,-2.99999 -2.5,-3 l -0.5,0 0,1 c 0,1.10457 -0.89543,2 -2,2 l -3,0 c -1.10457,0 -2,0.89543 -2,2 l 0,3 c 0,0.5 0,2.00001 3.5,2 z"
+ style="fill:#ffd43b;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
+ y="606.36218"
+ x="220"
+ height="1.0000014"
+ width="0.99999928"
+ id="rect3990-2"
+ 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" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 219,594.875 c -3.5,10e-6 -3.5,0.98718 -3.5,2 l 0,1.98718 3.5,0 -4,0.0128 c -0.25,0 -2.5,10e-4 -2.5,3 0,2.99883 2.25,2.99999 2.5,3 l 0.5,0 0,2 c 0,0.9872 0,2.00001 3.5,2 3.5,-1e-5 3.5,-1.0128 3.5,-2 l 0,-2.0128 -3.5,0 4,0.0128 c 0.25,0 2.5,-0.001 2.5,-3 0,-2.99883 -2.25,-2.99999 -2.5,-3 l -0.5,0 0,-2 c 0,-1.0128 0,-2.00001 -3.5,-2 l 0,2e-5 0,0 z"
+ id="path3992-3"
+ sodipodi:nodetypes="cccccscccsccccsccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;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 222.5,598.86218 0,1 c 0,1.10457 -0.89543,2 -2,2 l -3,0 c -1.10457,0 -2,0.89543 -2,2 l 0,1"
+ id="path3994-2"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cszsc"
+ id="path3996-2"
+ d="m 221.5,600.86218 -5e-5,-3.98718 c -1e-5,-0.51282 0.23494,-0.98725 -2.49995,-1 -2.75,-0.0128 -2.49992,0.48718 -2.49995,1 l -5e-5,0.98718"
+ style="fill:none;stroke:url(#linearGradient106820);stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:url(#linearGradient106822);stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 218.5,599.86218 -3.49995,0.0128 c -1.00005,0.004 -1.50005,0.73718 -1.5,2 5e-5,1.285 0.49995,2 1.5,2"
+ id="path3998-16"
+ sodipodi:nodetypes="cszs"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccc"
+ d="m 216.5,603.86218 c 0,-0.5 0.5,-1 1,-1 l 3,0 c 1.64438,0 3,-1.3428 3,-2.98718 m -7,3.98718 0,3.5"
+ style="fill:none;stroke:url(#linearGradient106824);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path4000-8"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path4002-5"
+ style="fill:none;stroke:url(#linearGradient106826);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 219.5,605.86218 2.00005,0.0128"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+</svg>
diff --git a/release/datafiles/blender_icons16.png b/release/datafiles/blender_icons16.png
new file mode 100644
index 00000000000..ffdc30e0915
--- /dev/null
+++ b/release/datafiles/blender_icons16.png
Binary files differ
diff --git a/release/datafiles/blender_icons32.png b/release/datafiles/blender_icons32.png
new file mode 100644
index 00000000000..9d91902d49d
--- /dev/null
+++ b/release/datafiles/blender_icons32.png
Binary files differ
diff --git a/release/datafiles/fonts/bmonofont-i18n.ttf.gz b/release/datafiles/fonts/bmonofont-i18n.ttf.gz
new file mode 100644
index 00000000000..1453ad48c6c
--- /dev/null
+++ b/release/datafiles/fonts/bmonofont-i18n.ttf.gz
Binary files differ
diff --git a/release/datafiles/fonts/droidsans.ttf.gz b/release/datafiles/fonts/droidsans.ttf.gz
index 439515e5bb4..a0e7502cc1f 100644
--- a/release/datafiles/fonts/droidsans.ttf.gz
+++ b/release/datafiles/fonts/droidsans.ttf.gz
Binary files differ
diff --git a/release/datafiles/matcaps/license.txt b/release/datafiles/matcaps/license.txt
new file mode 100644
index 00000000000..358c8dcd832
--- /dev/null
+++ b/release/datafiles/matcaps/license.txt
@@ -0,0 +1,3 @@
+These matcap images are licensed as GNU GPL 2 or later, like the rest of Blender's code.
+
+Thanks to Kent Trammell, Aidy Burrows, John Herreno , Terry Wallwork and David Silverman for making the pictures.
diff --git a/release/datafiles/matcaps/mc01.jpg b/release/datafiles/matcaps/mc01.jpg
new file mode 100644
index 00000000000..8c7aef287ee
--- /dev/null
+++ b/release/datafiles/matcaps/mc01.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc02.jpg b/release/datafiles/matcaps/mc02.jpg
new file mode 100644
index 00000000000..11deddfeaed
--- /dev/null
+++ b/release/datafiles/matcaps/mc02.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc03.jpg b/release/datafiles/matcaps/mc03.jpg
new file mode 100644
index 00000000000..64d992fb61a
--- /dev/null
+++ b/release/datafiles/matcaps/mc03.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc04.jpg b/release/datafiles/matcaps/mc04.jpg
new file mode 100644
index 00000000000..42be580ee93
--- /dev/null
+++ b/release/datafiles/matcaps/mc04.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc05.jpg b/release/datafiles/matcaps/mc05.jpg
new file mode 100644
index 00000000000..586d233ef31
--- /dev/null
+++ b/release/datafiles/matcaps/mc05.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc06.jpg b/release/datafiles/matcaps/mc06.jpg
new file mode 100644
index 00000000000..657883d0866
--- /dev/null
+++ b/release/datafiles/matcaps/mc06.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc07.jpg b/release/datafiles/matcaps/mc07.jpg
new file mode 100644
index 00000000000..372caf7e87c
--- /dev/null
+++ b/release/datafiles/matcaps/mc07.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc08.jpg b/release/datafiles/matcaps/mc08.jpg
new file mode 100644
index 00000000000..50eec402812
--- /dev/null
+++ b/release/datafiles/matcaps/mc08.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc09.jpg b/release/datafiles/matcaps/mc09.jpg
new file mode 100644
index 00000000000..e05d441aaf9
--- /dev/null
+++ b/release/datafiles/matcaps/mc09.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc10.jpg b/release/datafiles/matcaps/mc10.jpg
new file mode 100644
index 00000000000..ab82f17bb93
--- /dev/null
+++ b/release/datafiles/matcaps/mc10.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc11.jpg b/release/datafiles/matcaps/mc11.jpg
new file mode 100644
index 00000000000..053550f082c
--- /dev/null
+++ b/release/datafiles/matcaps/mc11.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc12.jpg b/release/datafiles/matcaps/mc12.jpg
new file mode 100644
index 00000000000..beb16f3742e
--- /dev/null
+++ b/release/datafiles/matcaps/mc12.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc13.jpg b/release/datafiles/matcaps/mc13.jpg
new file mode 100644
index 00000000000..7fb8fa58e8f
--- /dev/null
+++ b/release/datafiles/matcaps/mc13.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc14.jpg b/release/datafiles/matcaps/mc14.jpg
new file mode 100644
index 00000000000..ba868d2f95a
--- /dev/null
+++ b/release/datafiles/matcaps/mc14.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc15.jpg b/release/datafiles/matcaps/mc15.jpg
new file mode 100644
index 00000000000..b10ea326a42
--- /dev/null
+++ b/release/datafiles/matcaps/mc15.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc16.jpg b/release/datafiles/matcaps/mc16.jpg
new file mode 100644
index 00000000000..c6ce02d59df
--- /dev/null
+++ b/release/datafiles/matcaps/mc16.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc17.jpg b/release/datafiles/matcaps/mc17.jpg
new file mode 100644
index 00000000000..14f15f70460
--- /dev/null
+++ b/release/datafiles/matcaps/mc17.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc18.jpg b/release/datafiles/matcaps/mc18.jpg
new file mode 100644
index 00000000000..db572856b07
--- /dev/null
+++ b/release/datafiles/matcaps/mc18.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc19.jpg b/release/datafiles/matcaps/mc19.jpg
new file mode 100644
index 00000000000..56d2efb1734
--- /dev/null
+++ b/release/datafiles/matcaps/mc19.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc20.jpg b/release/datafiles/matcaps/mc20.jpg
new file mode 100644
index 00000000000..002a0910dd9
--- /dev/null
+++ b/release/datafiles/matcaps/mc20.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc21.jpg b/release/datafiles/matcaps/mc21.jpg
new file mode 100644
index 00000000000..cb2fea573b8
--- /dev/null
+++ b/release/datafiles/matcaps/mc21.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc22.jpg b/release/datafiles/matcaps/mc22.jpg
new file mode 100644
index 00000000000..2fc71b98c5a
--- /dev/null
+++ b/release/datafiles/matcaps/mc22.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc23.jpg b/release/datafiles/matcaps/mc23.jpg
new file mode 100644
index 00000000000..3793c0fcaa5
--- /dev/null
+++ b/release/datafiles/matcaps/mc23.jpg
Binary files differ
diff --git a/release/datafiles/matcaps/mc24.jpg b/release/datafiles/matcaps/mc24.jpg
new file mode 100644
index 00000000000..2a9618d8fe1
--- /dev/null
+++ b/release/datafiles/matcaps/mc24.jpg
Binary files differ
diff --git a/release/datafiles/preview_cycles.blend b/release/datafiles/preview_cycles.blend
new file mode 100644
index 00000000000..11bf8bbb7b8
--- /dev/null
+++ b/release/datafiles/preview_cycles.blend
Binary files differ
diff --git a/release/datafiles/prvicons.sh b/release/datafiles/prvicons.sh
new file mode 100755
index 00000000000..144dd9da362
--- /dev/null
+++ b/release/datafiles/prvicons.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+# This script updates icons from the SVG file
+
+inkscape prvicons.svg --without-gui --export-png=prvicons.png
diff --git a/release/datafiles/prvicons.svg b/release/datafiles/prvicons.svg
new file mode 100644
index 00000000000..d373410db73
--- /dev/null
+++ b/release/datafiles/prvicons.svg
@@ -0,0 +1,19741 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="192"
+ height="192"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.48.3.1 r9886"
+ version="1.0"
+ sodipodi:docname="prvicons.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ style="display:inline;enable-background:new"
+ inkscape:export-filename="blender_icons.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <title
+ id="title49470">Blender icons v. 2.5.06</title>
+ <defs
+ id="defs4">
+ <linearGradient
+ id="linearGradient30958">
+ <stop
+ id="stop30960"
+ offset="0"
+ style="stop-color:#fff9cf;stop-opacity:1;" />
+ <stop
+ id="stop30962"
+ offset="1"
+ style="stop-color:#c7bc52;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient29312">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop29314" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop29316" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient29304">
+ <stop
+ style="stop-color:#11233f;stop-opacity:1;"
+ offset="0"
+ id="stop29306" />
+ <stop
+ style="stop-color:#162d50;stop-opacity:0;"
+ offset="1"
+ id="stop29308" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient27896">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop27898" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop27900" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient27854">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop27856" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop27858" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24343">
+ <stop
+ id="stop24345"
+ offset="0"
+ style="stop-color:#184990;stop-opacity:1;" />
+ <stop
+ id="stop24347"
+ offset="1"
+ style="stop-color:#c1d5f3;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient25417">
+ <stop
+ id="stop25419"
+ offset="0"
+ style="stop-color:#60553b;stop-opacity:1;" />
+ <stop
+ id="stop25421"
+ offset="1"
+ style="stop-color:#b0a17f;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient25108">
+ <stop
+ id="stop25110"
+ offset="0"
+ style="stop-color:white;stop-opacity:1;" />
+ <stop
+ id="stop25112"
+ offset="1"
+ style="stop-color:#c6c6c6;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient43807">
+ <stop
+ style="stop-color:#e31b1b;stop-opacity:1;"
+ offset="0"
+ id="stop43809" />
+ <stop
+ style="stop-color:#930000;stop-opacity:1;"
+ offset="1"
+ id="stop43811" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient38845">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop38847" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop38849" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient38831">
+ <stop
+ style="stop-color:#182b42;stop-opacity:1;"
+ offset="0"
+ id="stop38833" />
+ <stop
+ id="stop38836"
+ offset="0.38971797"
+ style="stop-color:#598ac7;stop-opacity:1;" />
+ <stop
+ style="stop-color:#f1f1f1;stop-opacity:1;"
+ offset="1"
+ id="stop38838" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient38256">
+ <stop
+ id="stop38258"
+ offset="0"
+ style="stop-color:#e7e0c7;stop-opacity:1;" />
+ <stop
+ id="stop38260"
+ offset="1"
+ style="stop-color:#f1eddf;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient71814">
+ <stop
+ style="stop-color:#6e0d00;stop-opacity:1;"
+ offset="0"
+ id="stop71816" />
+ <stop
+ style="stop-color:#6f2913;stop-opacity:0;"
+ offset="1"
+ id="stop71818" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37667">
+ <stop
+ id="stop37669"
+ offset="0"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ id="stop37671"
+ offset="1"
+ style="stop-color:black;stop-opacity:0" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient39080">
+ <stop
+ style="stop-color:#1a2a3d;stop-opacity:1;"
+ offset="0"
+ id="stop39082" />
+ <stop
+ id="stop39084"
+ offset="0.5"
+ style="stop-color:#95b0d1;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop39086" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient40809">
+ <stop
+ style="stop-color:#0059d7;stop-opacity:1;"
+ offset="0"
+ id="stop40811" />
+ <stop
+ style="stop-color:#b7d4ff;stop-opacity:1;"
+ offset="1"
+ id="stop40813" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient40703">
+ <stop
+ style="stop-color:#143564;stop-opacity:1;"
+ offset="0"
+ id="stop40705" />
+ <stop
+ style="stop-color:#c1d7f8;stop-opacity:1;"
+ offset="1"
+ id="stop40707" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37925">
+ <stop
+ id="stop37927"
+ offset="0"
+ style="stop-color:#e7cbab;stop-opacity:1;" />
+ <stop
+ id="stop37929"
+ offset="1"
+ style="stop-color:#af7333;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient36273">
+ <stop
+ id="stop36275"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop36277"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient35411">
+ <stop
+ id="stop35414"
+ offset="0"
+ style="stop-color:#2b5385;stop-opacity:1;" />
+ <stop
+ id="stop35416"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient31356">
+ <stop
+ id="stop31358"
+ offset="0"
+ style="stop-color:#1a1a1a;stop-opacity:1" />
+ <stop
+ id="stop31360"
+ offset="1"
+ style="stop-color:#1a1a1a;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient28107"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7228842,8.5733105e-8,-9.4831885e-8,0.7995973,71.917045,14.582004)"
+ cx="256.49512"
+ cy="81.396774"
+ fx="256.49512"
+ fy="81.396774"
+ r="3.779551" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient28105"
+ gradientUnits="userSpaceOnUse"
+ x1="875.73486"
+ y1="422.77902"
+ x2="885.04938"
+ y2="427.01648" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient28887"
+ id="linearGradient28103"
+ gradientUnits="userSpaceOnUse"
+ x1="873.09998"
+ y1="422.09964"
+ x2="881.01172"
+ y2="429.23453" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient28101"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.6572588,1.2500456,-1.6473175,2.2058465,774.83033,-697.31982)"
+ cx="76.180473"
+ cy="500.20651"
+ fx="76.180473"
+ fy="500.20651"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient28099"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <linearGradient
+ id="linearGradient28887">
+ <stop
+ style="stop-color:#2158a7;stop-opacity:1;"
+ offset="0"
+ id="stop28889" />
+ <stop
+ style="stop-color:#2f73d5;stop-opacity:0.19607843;"
+ offset="1"
+ id="stop28891" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient44421"
+ gradientUnits="userSpaceOnUse"
+ x1="209"
+ y1="238"
+ x2="226.625"
+ y2="251.71078" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient44557"
+ gradientUnits="userSpaceOnUse"
+ x1="209"
+ y1="238"
+ x2="226.625"
+ y2="251.71078" />
+ <linearGradient
+ id="linearGradient24168">
+ <stop
+ id="stop24170"
+ offset="0"
+ style="stop-color:#182437;stop-opacity:1;" />
+ <stop
+ id="stop24172"
+ offset="1"
+ style="stop-color:#2b4163;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24144">
+ <stop
+ id="stop24146"
+ offset="0"
+ style="stop-color:#3d361a;stop-opacity:1;" />
+ <stop
+ style="stop-color:#d1c595;stop-opacity:1;"
+ offset="0.17958513"
+ id="stop24148" />
+ <stop
+ id="stop24150"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24101">
+ <stop
+ style="stop-color:#643400;stop-opacity:1;"
+ offset="0"
+ id="stop24103" />
+ <stop
+ id="stop24105"
+ offset="0.22606115"
+ style="stop-color:#ed983d;stop-opacity:1;" />
+ <stop
+ style="stop-color:#fff0d5;stop-opacity:1;"
+ offset="1"
+ id="stop24107" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24081">
+ <stop
+ id="stop24083"
+ offset="0"
+ style="stop-color:#b45d00;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ff982a;stop-opacity:1;"
+ offset="0.3167825"
+ id="stop24085" />
+ <stop
+ id="stop24087"
+ offset="1"
+ style="stop-color:#ffedd5;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient23302">
+ <stop
+ id="stop23304"
+ offset="0"
+ style="stop-color:#b45d00;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ff982a;stop-opacity:1;"
+ offset="0.39332664"
+ id="stop23306" />
+ <stop
+ id="stop23308"
+ offset="1"
+ style="stop-color:#ffedd5;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient24735">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop24737" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop24739" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24727">
+ <stop
+ style="stop-color:#3d361a;stop-opacity:1;"
+ offset="0"
+ id="stop24729" />
+ <stop
+ id="stop24731"
+ offset="0.77520341"
+ style="stop-color:#d1c595;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop24733" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24711">
+ <stop
+ style="stop-color:#3d361a;stop-opacity:1;"
+ offset="0"
+ id="stop24713" />
+ <stop
+ id="stop24715"
+ offset="0.21609697"
+ style="stop-color:#d1c595;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop24717" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24695">
+ <stop
+ style="stop-color:#3d361a;stop-opacity:1;"
+ offset="0"
+ id="stop24697" />
+ <stop
+ id="stop24699"
+ offset="0.60401857"
+ style="stop-color:#d1c595;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop24701" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24687">
+ <stop
+ style="stop-color:#3d361a;stop-opacity:1;"
+ offset="0"
+ id="stop24689" />
+ <stop
+ id="stop24691"
+ offset="0.59630167"
+ style="stop-color:#d1c595;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop24693" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24679">
+ <stop
+ style="stop-color:#3d361a;stop-opacity:1;"
+ offset="0"
+ id="stop24681" />
+ <stop
+ id="stop24683"
+ offset="0.45537567"
+ style="stop-color:#d1c595;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop24685" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24671">
+ <stop
+ style="stop-color:#3d361a;stop-opacity:1;"
+ offset="0"
+ id="stop24673" />
+ <stop
+ id="stop24675"
+ offset="0.29527253"
+ style="stop-color:#d1c595;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop24677" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient23705">
+ <stop
+ id="stop23707"
+ offset="0"
+ style="stop-color:#d4d2bf;stop-opacity:1;" />
+ <stop
+ id="stop23709"
+ offset="1"
+ style="stop-color:#857f5d;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient23906">
+ <stop
+ id="stop23908"
+ offset="0"
+ style="stop-color:#ff921d;stop-opacity:1;" />
+ <stop
+ id="stop23910"
+ offset="1"
+ style="stop-color:#ffa751;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient42459">
+ <stop
+ style="stop-color:#e7dfab;stop-opacity:1;"
+ offset="0"
+ id="stop42461" />
+ <stop
+ style="stop-color:#af9d33;stop-opacity:1;"
+ offset="1"
+ id="stop42463" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient41723"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(744,397)"
+ x1="-287"
+ y1="-276.1875"
+ x2="-281.4375"
+ y2="-271.9375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient41721"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.695652,0,0,0.869703,342.06514,-90.66358)"
+ x1="171.42436"
+ y1="259.71194"
+ x2="170.20523"
+ y2="244.96393" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24246"
+ gradientUnits="userSpaceOnUse"
+ x1="426.12415"
+ y1="179.12074"
+ x2="425"
+ y2="179.12285" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24143"
+ id="linearGradient24244"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(186,-105)"
+ x1="246.12868"
+ y1="283.63254"
+ x2="237.75459"
+ y2="266.34406" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24278"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(744,397)"
+ x1="-287.56247"
+ y1="-276.71042"
+ x2="-282.59851"
+ y2="-271.35284" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient24276"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.695652,0,0,0.869703,342.06514,-90.66358)"
+ x1="190.33647"
+ y1="266.7905"
+ x2="170.9689"
+ y2="247.58694" />
+ <linearGradient
+ id="linearGradient24143">
+ <stop
+ id="stop24145"
+ offset="0"
+ style="stop-color:#3d361a;stop-opacity:1;" />
+ <stop
+ style="stop-color:#d1c595;stop-opacity:1;"
+ offset="0.5"
+ id="stop24669" />
+ <stop
+ id="stop24147"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24687"
+ id="linearGradient24238"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,304.84783,-86.57833)"
+ x1="120.2969"
+ y1="281.26645"
+ x2="116.37123"
+ y2="260.21841" />
+ <linearGradient
+ id="linearGradient24642">
+ <stop
+ style="stop-color:#d0dbe8;stop-opacity:1;"
+ offset="0"
+ id="stop24644" />
+ <stop
+ style="stop-color:#6ca3e9;stop-opacity:0;"
+ offset="1"
+ id="stop24646" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24632">
+ <stop
+ style="stop-color:#28394f;stop-opacity:1;"
+ offset="0"
+ id="stop24634" />
+ <stop
+ id="stop24636"
+ offset="0.17637014"
+ style="stop-color:#0d386a;stop-opacity:0.78431374;" />
+ <stop
+ id="stop24638"
+ offset="0.35274029"
+ style="stop-color:#18437d;stop-opacity:0.47058824;" />
+ <stop
+ style="stop-color:#154e94;stop-opacity:0;"
+ offset="1"
+ id="stop24640" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22562"
+ id="radialGradient23167"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9934369,-0.1143813,0.1033636,0.8977446,-30.451879,30.134649)"
+ cx="-0.10810681"
+ cy="294.60239"
+ fx="-0.10810681"
+ fy="294.60239"
+ r="6.6750002" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient23201"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-61,0)"
+ x1="22.75"
+ y1="245"
+ x2="24.25"
+ y2="245" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient23199"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1,0)"
+ x1="22.75"
+ y1="245"
+ x2="24.5"
+ y2="245" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask23189">
+ <g
+ transform="translate(-28,49)"
+ id="g23193">
+ <rect
+ y="237"
+ x="22"
+ height="16"
+ width="9"
+ id="rect23195"
+ style="fill:url(#linearGradient23199);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ transform="scale(-1,1)"
+ style="fill:url(#linearGradient23201);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23197"
+ width="9"
+ height="16"
+ x="-38"
+ y="237" />
+ </g>
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24208"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-46.000005,-117)"
+ x1="257.75"
+ y1="388"
+ x2="272"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24206"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-54.000005,-120)"
+ x1="258.52756"
+ y1="388"
+ x2="279"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24204"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-48.983883,-126)"
+ x1="259.75"
+ y1="388"
+ x2="273"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24202"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-52.983883,-129)"
+ x1="258"
+ y1="388"
+ x2="273"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23379"
+ gradientUnits="userSpaceOnUse"
+ x1="126.37032"
+ y1="110.87843"
+ x2="139.86742"
+ y2="126.57021" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15437"
+ id="linearGradient23377"
+ gradientUnits="userSpaceOnUse"
+ x1="137.88235"
+ y1="124.67203"
+ x2="131.3092"
+ y2="117.24104" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13938"
+ id="linearGradient23375"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9995363,0,0,-1.0036971,220.01067,167.35026)"
+ x1="52.06274"
+ y1="96.767769"
+ x2="44.999863"
+ y2="103.57072" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14232"
+ id="linearGradient23373"
+ gradientUnits="userSpaceOnUse"
+ x1="122.38876"
+ y1="108.82882"
+ x2="133.88583"
+ y2="121.20407" />
+ <linearGradient
+ id="linearGradient23974">
+ <stop
+ id="stop23976"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop23978"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient40983">
+ <stop
+ style="stop-color:#6a9ae0;stop-opacity:1;"
+ offset="0"
+ id="stop40985" />
+ <stop
+ style="stop-color:#5189db;stop-opacity:0;"
+ offset="1"
+ id="stop40987" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23280"
+ gradientUnits="userSpaceOnUse"
+ x1="127.60629"
+ y1="112.12571"
+ x2="140.72693"
+ y2="126.72997" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23278"
+ gradientUnits="userSpaceOnUse"
+ x1="125.01582"
+ y1="110.86718"
+ x2="132.46898"
+ y2="119.54019" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient23276"
+ gradientUnits="userSpaceOnUse"
+ x1="139.37782"
+ y1="126.3454"
+ x2="131.71249"
+ y2="118.34238" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14418"
+ id="linearGradient23274"
+ gradientUnits="userSpaceOnUse"
+ x1="144.8255"
+ y1="132.15414"
+ x2="130.10634"
+ y2="117.10313" />
+ <linearGradient
+ id="linearGradient30777"
+ inkscape:collect="always">
+ <stop
+ id="stop30779"
+ offset="0"
+ style="stop-color:#acacac;stop-opacity:1" />
+ <stop
+ id="stop30781"
+ offset="1"
+ style="stop-color:black;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient29485">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop29487" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop29489" />
+ </linearGradient>
+ <filter
+ inkscape:collect="always"
+ x="-0.55821538"
+ width="2.1164308"
+ y="-1.0219563"
+ height="3.0439126"
+ id="filter20578"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="2.0410255"
+ id="feGaussianBlur20580" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath20586">
+ <path
+ sodipodi:type="arc"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path34889"
+ sodipodi:cx="53"
+ sodipodi:cy="554"
+ sodipodi:rx="4.5"
+ sodipodi:ry="2.25"
+ d="m 57.5,554 a 4.5,2.25 0 1 1 -9,0 4.5,2.25 0 1 1 9,0 z"
+ transform="matrix(1.870472,0.1894819,-0.6587894,2.4281336,319.59052,-798.11661)" />
+ </clipPath>
+ <radialGradient
+ id="aigrd2"
+ cx="20.892099"
+ cy="114.5684"
+ r="5.256"
+ fx="20.892099"
+ fy="114.5684"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ offset="0"
+ style="stop-color:#F0F0F0"
+ id="stop15566" />
+ <stop
+ offset="1.0000000"
+ style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
+ id="stop15568" />
+ </radialGradient>
+ <filter
+ inkscape:collect="always"
+ x="-0.45600089"
+ width="1.9120018"
+ y="-0.50666559"
+ height="2.0133312"
+ id="filter63011"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.899998"
+ id="feGaussianBlur63013" />
+ </filter>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath13106">
+ <path
+ style="fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ id="path34850"
+ 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" />
+ </clipPath>
+ <linearGradient
+ id="linearGradient58334">
+ <stop
+ id="stop58336"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.87628865;" />
+ <stop
+ id="stop58338"
+ offset="1.0000000"
+ style="stop-color:#fffffe;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient8864">
+ <stop
+ id="stop8866"
+ offset="0"
+ style="stop-color:#b43214;stop-opacity:1;" />
+ <stop
+ id="stop8868"
+ offset="1"
+ style="stop-color:#e86830;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient20324">
+ <stop
+ id="stop20326"
+ offset="0"
+ style="stop-color:#35241b;stop-opacity:1;" />
+ <stop
+ style="stop-color:#69390e;stop-opacity:0.8392157;"
+ offset="0.17637014"
+ id="stop20328" />
+ <stop
+ style="stop-color:#6c5b15;stop-opacity:0.67843139;"
+ offset="0.35274029"
+ id="stop20330" />
+ <stop
+ id="stop20332"
+ offset="1"
+ style="stop-color:#947b15;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37623">
+ <stop
+ id="stop37625"
+ offset="0"
+ style="stop-color:#e5e1ca;stop-opacity:1;" />
+ <stop
+ id="stop37627"
+ offset="1"
+ style="stop-color:#d6ca22;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient36116">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop36118" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop36120" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22852"
+ gradientUnits="userSpaceOnUse"
+ x1="133.94305"
+ y1="116.00471"
+ x2="117.29694"
+ y2="133.14267" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient22850"
+ gradientUnits="userSpaceOnUse"
+ x1="136.55727"
+ y1="125.87247"
+ x2="129.70895"
+ y2="118.00132" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22896"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.01387,0)"
+ x1="441.98615"
+ y1="77.44017"
+ x2="424.75217"
+ y2="75.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22846"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.01387,0)"
+ x1="438.61115"
+ y1="78"
+ x2="424.75217"
+ y2="75.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22844"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.01387,0)"
+ x1="437.98615"
+ y1="77"
+ x2="424.75217"
+ y2="75.5" />
+ <linearGradient
+ id="linearGradient22562">
+ <stop
+ style="stop-color:#001e50;stop-opacity:1;"
+ offset="0"
+ id="stop22564" />
+ <stop
+ style="stop-color:#1e3e70;stop-opacity:0;"
+ offset="1"
+ id="stop22566" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22562"
+ id="linearGradient22842"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(399.01387,-202)"
+ x1="28.4375"
+ y1="277"
+ x2="23.25"
+ y2="276.92188" />
+ <linearGradient
+ id="linearGradient22556">
+ <stop
+ id="stop22558"
+ offset="0"
+ style="stop-color:#6a9bef;stop-opacity:1" />
+ <stop
+ style="stop-color:#bccee8;stop-opacity:0.58450705;"
+ offset="0.77941167"
+ id="stop22568" />
+ <stop
+ id="stop22560"
+ offset="1"
+ style="stop-color:#ccdaed;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22556"
+ id="linearGradient22840"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.785748,0,0,0.78488,265.93616,46.1048)"
+ x1="210.08989"
+ y1="38.088879"
+ x2="199.27217"
+ y2="38.088879" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="radialGradient22838"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8128508,0,0,0.8128508,80.474142,14.46897)"
+ cx="430.00003"
+ cy="77.3125"
+ fx="430.00003"
+ fy="77.3125"
+ r="8" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22882"
+ id="linearGradient22848"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1929722,0,0,0.5,-462.63135,-59)"
+ x1="24"
+ y1="285"
+ x2="31.538462"
+ y2="285" />
+ <linearGradient
+ id="linearGradient22882">
+ <stop
+ style="stop-color:#323232;stop-opacity:0;"
+ offset="0"
+ id="stop22884" />
+ <stop
+ id="stop22886"
+ offset="0.21233012"
+ style="stop-color:#323232;stop-opacity:0.49803922;" />
+ <stop
+ id="stop22888"
+ offset="0.54086536"
+ style="stop-color:#323232;stop-opacity:1;" />
+ <stop
+ style="stop-color:#323232;stop-opacity:0.49803922;"
+ offset="0.83381736"
+ id="stop22890" />
+ <stop
+ style="stop-color:#323232;stop-opacity:0;"
+ offset="1"
+ id="stop22892" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22882"
+ id="linearGradient22880"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0369025,0,0,1.5,-458.38567,-344)"
+ x1="23.959812"
+ y1="285"
+ x2="31.498274"
+ y2="285" />
+ <linearGradient
+ id="linearGradient35407">
+ <stop
+ id="stop35409"
+ offset="0"
+ style="stop-color:#a17306;stop-opacity:1;" />
+ <stop
+ style="stop-color:#cca649;stop-opacity:1;"
+ offset="0.43277758"
+ id="stop35411" />
+ <stop
+ id="stop35413"
+ offset="1"
+ style="stop-color:#f9f5e9;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient35391">
+ <stop
+ id="stop35393"
+ offset="0"
+ style="stop-color:#322800;stop-opacity:1;" />
+ <stop
+ id="stop35395"
+ offset="1"
+ style="stop-color:#6e4800;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient34157">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop34159" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop34161" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38256"
+ id="linearGradient22457"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-18)"
+ x1="-25.5"
+ y1="36.828632"
+ x2="-25.5"
+ y2="26.027344" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22455"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-354,-314.00002)"
+ x1="308"
+ y1="323"
+ x2="343.26239"
+ y2="340" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22453"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-18)"
+ x1="-27.299919"
+ y1="37"
+ x2="-25.5"
+ y2="23.414351" />
+ <linearGradient
+ id="linearGradient21609">
+ <stop
+ id="stop21611"
+ offset="0"
+ style="stop-color:black;stop-opacity:1" />
+ <stop
+ id="stop21613"
+ offset="1"
+ style="stop-color:white;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient21609"
+ id="linearGradient20961"
+ gradientUnits="userSpaceOnUse"
+ x1="162"
+ y1="103.71875"
+ x2="165"
+ y2="103.75" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask20957">
+ <rect
+ y="101"
+ x="162"
+ height="5"
+ width="8"
+ id="rect20959"
+ style="fill:url(#linearGradient20961);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32335"
+ gradientUnits="userSpaceOnUse"
+ x1="285.39999"
+ y1="323.80002"
+ x2="286.60001"
+ y2="325" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22081"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-157.00004,-233.00002)"
+ x1="308"
+ y1="323"
+ x2="337.80573"
+ y2="337.517" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient19900">
+ <stop
+ style="stop-color:#1a1a1a;stop-opacity:1;"
+ offset="0"
+ id="stop19902" />
+ <stop
+ style="stop-color:#1a1a1a;stop-opacity:0;"
+ offset="1"
+ id="stop19904" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18105">
+ <stop
+ id="stop18107"
+ offset="0"
+ style="stop-color:#162d50;stop-opacity:1" />
+ <stop
+ id="stop18109"
+ offset="1"
+ style="stop-color:#1e3e70;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18056">
+ <stop
+ id="stop18058"
+ offset="0"
+ style="stop-color:#162d50;stop-opacity:1" />
+ <stop
+ id="stop18060"
+ offset="1"
+ style="stop-color:#295498;stop-opacity:0.34057972;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient21327">
+ <stop
+ style="stop-color:#1e3e70;stop-opacity:1;"
+ offset="0"
+ id="stop21329" />
+ <stop
+ style="stop-color:#1e3e70;stop-opacity:0;"
+ offset="1"
+ id="stop21331" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient19625">
+ <stop
+ id="stop19627"
+ offset="0"
+ style="stop-color:#2258a6;stop-opacity:1;" />
+ <stop
+ id="stop19629"
+ offset="1"
+ style="stop-color:#c1d7f8;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35391"
+ id="linearGradient20217"
+ x1="408.75"
+ y1="-35.483223"
+ x2="408.75"
+ y2="-40.000008"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient18821">
+ <stop
+ style="stop-color:#fc6b58;stop-opacity:1;"
+ offset="0"
+ id="stop18823" />
+ <stop
+ style="stop-color:#fc6b58;stop-opacity:0;"
+ offset="1"
+ id="stop18825" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient22187"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <linearGradient
+ id="linearGradient29149">
+ <stop
+ id="stop29151"
+ offset="0"
+ style="stop-color:#76adff;stop-opacity:1;" />
+ <stop
+ id="stop29153"
+ offset="1"
+ style="stop-color:#a5c9ff;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient21820"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient21818"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.4624192,0,0,1.4467089,-36.975824,-224.99718)"
+ cx="79.959885"
+ cy="503.81497"
+ fx="79.959885"
+ fy="503.81497"
+ r="2.9089756" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient21816"
+ gradientUnits="userSpaceOnUse"
+ x1="89.526657"
+ y1="511.42972"
+ x2="78.000008"
+ y2="501.04794" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient21814"
+ gradientUnits="userSpaceOnUse"
+ x1="80.768944"
+ y1="504.67188"
+ x2="76.885078"
+ y2="501.58331" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262"
+ id="radialGradient21741"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3949409,0.3949425,-0.4243709,0.4254619,321.60762,256.85923)"
+ cx="75.95578"
+ cy="492.15359"
+ fx="75.95578"
+ fy="492.15359"
+ r="3.1650217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15809"
+ id="linearGradient21773"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9281768,0,0,0.9971589,401.42265,-484.56523)"
+ x1="88.874489"
+ y1="502.71924"
+ x2="41.311054"
+ y2="501.10059" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient21776"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8666667,0,0,0.9166667,406.13333,-443.79167)"
+ x1="108"
+ y1="500"
+ x2="54.8125"
+ y2="500" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262"
+ id="radialGradient22166"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8886193,0.8021825,-0.8051059,0.8972684,411.80247,-8.668512)"
+ cx="74.518959"
+ cy="499.99969"
+ fx="74.518959"
+ fy="499.99969"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient22164"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.4624192,0,0,1.4467089,-36.975824,-224.99718)"
+ cx="79.959885"
+ cy="503.81497"
+ fx="79.959885"
+ fy="503.81497"
+ r="2.9089756" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22162"
+ gradientUnits="userSpaceOnUse"
+ x1="89.526657"
+ y1="511.42972"
+ x2="78.000008"
+ y2="501.04794" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient22160"
+ gradientUnits="userSpaceOnUse"
+ x1="80.768944"
+ y1="504.67188"
+ x2="76.885078"
+ y2="501.58331" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262"
+ id="radialGradient22158"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3949409,0.3949425,-0.4243709,0.4254619,321.60762,256.85923)"
+ cx="75.95578"
+ cy="492.15359"
+ fx="75.95578"
+ fy="492.15359"
+ r="3.1650217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15809"
+ id="linearGradient22156"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.9971589,396,-484.56523)"
+ x1="88.874489"
+ y1="502.71924"
+ x2="41.311054"
+ y2="501.10059" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient22154"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8666667,0,0,0.9166667,406.13333,-443.79167)"
+ x1="108"
+ y1="500"
+ x2="54.8125"
+ y2="500" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient15809">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop15811" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop15813" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15437">
+ <stop
+ id="stop15439"
+ offset="0"
+ style="stop-color:#20529e;stop-opacity:1;" />
+ <stop
+ id="stop15441"
+ offset="1"
+ style="stop-color:#1d3f71;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15425">
+ <stop
+ style="stop-color:#8c0000;stop-opacity:1;"
+ offset="0"
+ id="stop15427" />
+ <stop
+ style="stop-color:#c80000;stop-opacity:0;"
+ offset="1"
+ id="stop15429" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient14262">
+ <stop
+ id="stop14264"
+ offset="0"
+ style="stop-color:#2661b6;stop-opacity:1;" />
+ <stop
+ id="stop14266"
+ offset="1"
+ style="stop-color:#c1d7f8;stop-opacity:0;" />
+ </linearGradient>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath17188">
+ <path
+ style="fill:#d3d7cf;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 240.5,-19.90625 c -1.87005,0 -3.40625,1.536202 -3.40625,3.40625 l 0,2 c 0,1.87005 1.53621,3.40625 3.40625,3.40625 l 0,-2.8125 c -0.33932,0 -0.59375,-0.254431 -0.59375,-0.59375 l 0,-2 c 0,-0.339319 0.25443,-0.59375 0.59375,-0.59375 l 0,-2.8125 z"
+ id="path17190"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <linearGradient
+ id="linearGradient18344">
+ <stop
+ style="stop-color:#6c6c6c;stop-opacity:1;"
+ offset="0"
+ id="stop18346" />
+ <stop
+ style="stop-color:#f0f0f0;stop-opacity:1;"
+ offset="1"
+ id="stop18348" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient5060">
+ <stop
+ id="stop5062"
+ offset="0"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ id="stop5064"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient27957">
+ <stop
+ id="stop27959"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:0;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0.59290552"
+ id="stop27963" />
+ <stop
+ id="stop27961"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient23647">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop23649" />
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="1"
+ id="stop23651" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient23390">
+ <stop
+ style="stop-color:#000000;stop-opacity:1.0000000"
+ offset="0.0000000"
+ id="stop23392" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1.0000000"
+ offset="1.0000000"
+ id="stop23400" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16359">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop16361" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop16363" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15746"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.207032,0,0,0.903901,679.26,-38.98429)"
+ x1="386.09836"
+ y1="230.09529"
+ x2="388.35962"
+ y2="248.10277" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15744"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.207032,0,0,0.903901,679.30638,-38.92179)"
+ x1="390.61163"
+ y1="229.34804"
+ x2="390.55936"
+ y2="248.24983" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15683"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.203777,0,0,0.903901,837.9645,-18.01568)"
+ x1="383.67041"
+ y1="225.94354"
+ x2="385.60632"
+ y2="248.55901" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15681"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.207032,0,0,0.903901,839.2424,-18.01568)"
+ x1="391.80222"
+ y1="230.5647"
+ x2="387.94211"
+ y2="247.83209" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient13545"
+ gradientUnits="userSpaceOnUse"
+ x1="126.37006"
+ y1="112.31642"
+ x2="137.11284"
+ y2="126.19643" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient15878"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ id="linearGradient20756">
+ <stop
+ style="stop-color:#932200;stop-opacity:1;"
+ offset="0"
+ id="stop20758" />
+ <stop
+ style="stop-color:#f8420a;stop-opacity:1;"
+ offset="1"
+ id="stop20760" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20756"
+ id="linearGradient13543"
+ gradientUnits="userSpaceOnUse"
+ x1="126.45676"
+ y1="110.59049"
+ x2="134.94949"
+ y2="122.08995" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15693"
+ 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"
+ id="linearGradient15691"
+ 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"
+ id="linearGradient15689"
+ 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"
+ id="linearGradient15687"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.222225,0,0,1,-87.33412,169)"
+ x1="217.22589"
+ y1="107.25085"
+ x2="235.90916"
+ y2="121" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15854"
+ gradientUnits="userSpaceOnUse"
+ x1="381.56296"
+ y1="234.59885"
+ x2="393"
+ y2="247.99632" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31456"
+ id="linearGradient13639"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8329616,0,0,0.8433415,58.576199,29.193917)"
+ x1="399.987"
+ y1="259.26602"
+ x2="385.88068"
+ y2="241.70195" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23178"
+ id="linearGradient52023"
+ gradientUnits="userSpaceOnUse"
+ x1="390.75"
+ y1="244.5312"
+ x2="395.9375"
+ y2="250.9062" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31456"
+ id="linearGradient14661"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8329616,0,0,0.8433415,58.576199,29.193917)"
+ x1="400.88739"
+ y1="257.4874"
+ x2="385.88068"
+ y2="241.70195" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23178"
+ id="linearGradient52025"
+ gradientUnits="userSpaceOnUse"
+ x1="391.01859"
+ y1="241.86644"
+ x2="396.79285"
+ y2="247.83134" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31456"
+ id="linearGradient15995"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8329616,0,0,0.8433415,58.576199,29.193917)"
+ x1="399.08661"
+ y1="257.41327"
+ x2="385.88068"
+ y2="241.70195" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15993"
+ gradientUnits="userSpaceOnUse"
+ x1="381.5"
+ y1="231.7812"
+ x2="393.4375"
+ y2="247.1562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15997"
+ gradientUnits="userSpaceOnUse"
+ x1="381.5"
+ y1="231.7812"
+ x2="393.4375"
+ y2="247.1562" />
+ <linearGradient
+ id="linearGradient47130">
+ <stop
+ style="stop-color:#ed7b00;stop-opacity:1;"
+ offset="0"
+ id="stop47132" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop47134" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23178"
+ id="linearGradient52027"
+ gradientUnits="userSpaceOnUse"
+ x1="329.28757"
+ y1="244.97151"
+ x2="339.84518"
+ y2="254.18553" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15436"
+ gradientUnits="userSpaceOnUse"
+ x1="319.75095"
+ y1="234.63918"
+ x2="333.94208"
+ y2="248.68198" />
+ <linearGradient
+ id="linearGradient32842">
+ <stop
+ style="stop-color:#183e75;stop-opacity:1;"
+ offset="0"
+ id="stop32844" />
+ <stop
+ style="stop-color:#1d3f71;stop-opacity:0;"
+ offset="1"
+ id="stop32846" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient13900"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.2541045,-1.3755453,0.900369,1.4754358,-3699.4512,2858.7)"
+ cx="2357.1072"
+ cy="826.77924"
+ fx="2357.1072"
+ fy="826.77924"
+ r="6.1896501" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40983"
+ id="linearGradient38692"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(2226.9963,823)"
+ x1="130.70599"
+ y1="18.44199"
+ x2="130.70599"
+ y2="21.94199" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15717"
+ gradientUnits="userSpaceOnUse"
+ x1="328.38852"
+ y1="33.505165"
+ x2="331.44778"
+ y2="36.739578" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15715"
+ gradientUnits="userSpaceOnUse"
+ x1="320.2735"
+ y1="25.109356"
+ x2="332.41409"
+ y2="37.468754" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15713"
+ gradientUnits="userSpaceOnUse"
+ x1="329.18762"
+ y1="34.005215"
+ x2="331.44778"
+ y2="36.739578" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15711"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(2.011921e-5,12.000013)"
+ x1="326.483"
+ y1="31.446384"
+ x2="337.3125"
+ y2="41.875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15709"
+ gradientUnits="userSpaceOnUse"
+ x1="332.49747"
+ y1="38.166924"
+ x2="326.41843"
+ y2="31.22842" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15707"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(2.011921e-5,12.000013)"
+ x1="323.37836"
+ y1="30.3883"
+ x2="343.5636"
+ y2="53.758793" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15646"
+ gradientUnits="userSpaceOnUse"
+ x1="279.00009"
+ y1="-16.62501"
+ x2="291.93054"
+ y2="-6.3206272" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15644"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.000006,0,0,1,258.9997,-253)"
+ x1="25.437477"
+ y1="238.54002"
+ x2="51.01355"
+ y2="263.79816" />
+ <linearGradient
+ id="linearGradient20973">
+ <stop
+ id="stop20975"
+ offset="0"
+ style="stop-color:#15ff00;stop-opacity:1;" />
+ <stop
+ id="stop20977"
+ offset="1"
+ style="stop-color:#15ff00;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient20962">
+ <stop
+ style="stop-color:#00a8ff;stop-opacity:1;"
+ offset="0"
+ id="stop20965" />
+ <stop
+ style="stop-color:#00a8ff;stop-opacity:0;"
+ offset="1"
+ id="stop20967" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient20036">
+ <stop
+ style="stop-color:#ffb55e;stop-opacity:1;"
+ offset="0"
+ id="stop20038" />
+ <stop
+ style="stop-color:#ff8400;stop-opacity:0;"
+ offset="1"
+ id="stop20040" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15574"
+ gradientUnits="userSpaceOnUse"
+ x1="197.63152"
+ y1="169.14206"
+ x2="190.41687"
+ y2="160.02296" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15358"
+ gradientUnits="userSpaceOnUse"
+ x1="47.655102"
+ y1="93.805557"
+ x2="59.057678"
+ y2="105.27895"
+ gradientTransform="matrix(1.1000194,0,0,1.0998287,-4.6508478,-9.2334126)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15356"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9995967,0,0,1.0002103,-78.949724,-0.02739749)"
+ x1="109.04134"
+ y1="75.666725"
+ x2="135.45256"
+ y2="103.11092" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15362"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient15360"
+ gradientUnits="userSpaceOnUse"
+ x1="124.40742"
+ y1="111.98244"
+ x2="135.36497"
+ y2="120.87388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient21531"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2859754,0,0,1,39.669142,20)"
+ x1="348.06064"
+ y1="220.55545"
+ x2="363.71661"
+ y2="239.94608" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient14517"
+ gradientUnits="userSpaceOnUse"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="18.01141"
+ y2="84.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient14511"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="3.3959732"
+ y1="216.62332"
+ x2="35.029804"
+ y2="248.37102" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient16069"
+ gradientUnits="userSpaceOnUse"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="17.011419"
+ y2="82.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient16067"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2859754,0,0,1,-440.36032,-147)"
+ x1="348.06064"
+ y1="220.55545"
+ x2="363.71661"
+ y2="239.94608" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient16063"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="6.9917974"
+ y1="219.61856"
+ x2="35.029804"
+ y2="248.37102" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient16154"
+ gradientUnits="userSpaceOnUse"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="18.51141"
+ y2="85.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient16150"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="3.8504581"
+ y1="217.4549"
+ x2="33.15686"
+ y2="247.71701" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15734"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8520698,0,0,0.7746114,324.58589,47.486124)"
+ x1="9.5404434"
+ y1="223.47467"
+ x2="35.029804"
+ y2="248.37102" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient16174"
+ gradientUnits="userSpaceOnUse"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="18.51141"
+ y2="85.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient16170"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="2.911078"
+ y1="217.3624"
+ x2="33.15686"
+ y2="247.71701" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15736"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8520698,0,0,0.7746114,324.58589,47.486124)"
+ x1="9.5404434"
+ y1="223.47467"
+ x2="35.029804"
+ y2="248.37102" />
+ <linearGradient
+ id="linearGradient13998">
+ <stop
+ id="stop14000"
+ offset="0"
+ style="stop-color:#f57d07;stop-opacity:1;" />
+ <stop
+ id="stop14002"
+ offset="1"
+ style="stop-color:white;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4343">
+ <stop
+ id="stop4345"
+ offset="0"
+ style="stop-color:white;stop-opacity:1;" />
+ <stop
+ id="stop4347"
+ offset="1"
+ style="stop-color:#fff9f9;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15057"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.3333334,0,0,0.8333334,747.50001,337.33345)"
+ x1="-285.65732"
+ y1="-274.23453"
+ x2="-279.44821"
+ y2="-268.04858" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15053"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.166667,-441,-81.66662)"
+ x1="43.647511"
+ y1="164.125"
+ x2="75.731438"
+ y2="164.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15705"
+ gradientUnits="userSpaceOnUse"
+ x1="148.71947"
+ y1="166.53206"
+ x2="147"
+ y2="165" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15703"
+ gradientUnits="userSpaceOnUse"
+ x1="146.80022"
+ y1="158.34668"
+ x2="150.08357"
+ y2="162.03282" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15701"
+ gradientUnits="userSpaceOnUse"
+ x1="148.71947"
+ y1="166.53206"
+ x2="147"
+ y2="165" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15699"
+ gradientUnits="userSpaceOnUse"
+ x1="122.84515"
+ y1="126.83902"
+ x2="149.88129"
+ y2="164.94562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15742"
+ gradientUnits="userSpaceOnUse"
+ x1="392.0101"
+ y1="224.99998"
+ x2="392.0101"
+ y2="249.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15721"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(19.97577,-6.0080883)"
+ x1="227.57907"
+ y1="118.47696"
+ x2="235"
+ y2="118.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15719"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(19.97577,-6.0080883)"
+ x1="222.4996"
+ y1="110.37873"
+ x2="233.08319"
+ y2="121" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15723"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-6.0080883)"
+ x1="230.95012"
+ y1="100.89436"
+ x2="230.74091"
+ y2="124.09359" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15778"
+ gradientUnits="userSpaceOnUse"
+ x1="126.37006"
+ y1="112.31642"
+ x2="135.54141"
+ y2="122.0597" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient15780"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15776"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,10.767079)"
+ x1="132.35471"
+ y1="246.32236"
+ x2="129.81586"
+ y2="243.70523" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15774"
+ gradientUnits="userSpaceOnUse"
+ x1="103.53399"
+ y1="88.301094"
+ x2="136.3542"
+ y2="123.17216" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15450"
+ gradientUnits="userSpaceOnUse"
+ x1="126.37006"
+ y1="112.31642"
+ x2="144.22272"
+ y2="129.82761" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient15452"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient15448"
+ gradientUnits="userSpaceOnUse"
+ x1="132.12782"
+ y1="246.32236"
+ x2="129.24866"
+ y2="243.31177" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15446"
+ gradientUnits="userSpaceOnUse"
+ x1="87.969383"
+ y1="69.87941"
+ x2="135.40274"
+ y2="121.19196" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15582"
+ gradientUnits="userSpaceOnUse"
+ x1="9.062501"
+ y1="117.46875"
+ x2="24.625006"
+ y2="131.65625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15584"
+ gradientUnits="userSpaceOnUse"
+ x1="28.607456"
+ y1="116.80592"
+ x2="43.766914"
+ y2="131.5226" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15124"
+ gradientUnits="userSpaceOnUse"
+ x1="328.38852"
+ y1="33.505165"
+ x2="331.44778"
+ y2="36.739578" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30208"
+ id="linearGradient15122"
+ gradientUnits="userSpaceOnUse"
+ x1="328.95557"
+ y1="33.94022"
+ x2="331.74063"
+ y2="37.044456" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient16025"
+ gradientUnits="userSpaceOnUse"
+ x1="192.11751"
+ y1="122.12527"
+ x2="184.43379"
+ y2="112.34031" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15580"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.395521,0,0,-0.3955,275.223,171.0515)"
+ x1="213.51967"
+ y1="121.417"
+ x2="204.05295"
+ y2="111.7235" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15578"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.607961,0,0,0.607967,64.49194,51.63899)"
+ x1="213.53587"
+ y1="122.66508"
+ x2="203.33264"
+ y2="112.67535" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15748"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,-241.7085,428.4841)"
+ x1="349.04059"
+ y1="143.70836"
+ x2="336.72485"
+ y2="117.00745" />
+ <linearGradient
+ id="linearGradient10585">
+ <stop
+ id="stop10587"
+ offset="0.0000000"
+ style="stop-color:#d7d7d7;stop-opacity:1.0000000;" />
+ <stop
+ id="stop10595"
+ offset="1.0000000"
+ style="stop-color:#000000;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4138">
+ <stop
+ style="stop-color:#6c432f;stop-opacity:1;"
+ offset="0"
+ id="stop4140" />
+ <stop
+ style="stop-color:#c0966d;stop-opacity:1;"
+ offset="1"
+ id="stop4142" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient31320">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop31322" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop31324" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient12678">
+ <stop
+ id="stop12680"
+ offset="0"
+ style="stop-color:#d40000;stop-opacity:1" />
+ <stop
+ id="stop12682"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient13991"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(1.691866,0.00341)"
+ x1="86.452194"
+ y1="101.22832"
+ x2="110.48556"
+ y2="81.14637" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient13520"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(1.401389,-3.2412)"
+ x1="130.59862"
+ y1="121.2412"
+ x2="142.29109"
+ y2="133.53448" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23215"
+ x1="147.07098"
+ y1="134.18185"
+ x2="129.67148"
+ y2="115.54105"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient23178">
+ <stop
+ style="stop-color:#ff992b;stop-opacity:1;"
+ offset="0"
+ id="stop23180" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop23182" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient13973">
+ <stop
+ style="stop-color:#3c4c18;stop-opacity:1;"
+ offset="0"
+ id="stop13975" />
+ <stop
+ style="stop-color:#9aff31;stop-opacity:0;"
+ offset="1"
+ id="stop13977" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient13938">
+ <stop
+ id="stop13940"
+ offset="0"
+ style="stop-color:#6e0c00;stop-opacity:1;" />
+ <stop
+ id="stop13942"
+ offset="1"
+ style="stop-color:#ee3800;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient14232">
+ <stop
+ style="stop-color:#fff32a;stop-opacity:1;"
+ offset="0"
+ id="stop14234" />
+ <stop
+ style="stop-color:#fff551;stop-opacity:0;"
+ offset="1"
+ id="stop14236" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient14418">
+ <stop
+ id="stop14420"
+ offset="0"
+ style="stop-color:#fa2509;stop-opacity:1;" />
+ <stop
+ id="stop14422"
+ offset="1"
+ style="stop-color:#fa2509;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient14935"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-26,2.9206276e-6)"
+ x1="474"
+ y1="73.999992"
+ x2="477.25"
+ y2="77.499992" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient14841"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-6,1.4603138e-6)"
+ x1="474.84375"
+ y1="75"
+ x2="477.5"
+ y2="77.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient18852"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-22)"
+ x1="148.15451"
+ y1="-216.25"
+ x2="157.91019"
+ y2="-216.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient18850"
+ gradientUnits="userSpaceOnUse"
+ x1="107.15463"
+ y1="-227.83138"
+ x2="105.81714"
+ y2="-219.8996" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient18848"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(20.000285,-20.002166)"
+ x1="123.36729"
+ y1="-219.24783"
+ x2="136.51436"
+ y2="-217.99782" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient18845"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(20.000285,-20.002166)"
+ x1="135.30351"
+ y1="-219.54408"
+ x2="123.63815"
+ y2="-219.49783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient18843"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-22)"
+ x1="157.97339"
+ y1="-215.99998"
+ x2="146.36111"
+ y2="-215.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient18901"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(279.04534,461.00001)"
+ x1="151"
+ y1="-234"
+ x2="149.95467"
+ y2="-239.14549" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient18904"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(280.04419,461)"
+ x1="151"
+ y1="-234"
+ x2="150.25"
+ y2="-236.85815" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient18898"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(280.99885,461)"
+ x1="150.11926"
+ y1="-235.21587"
+ x2="145.20955"
+ y2="-241.85452" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient18896"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(280,461)"
+ x1="150.95467"
+ y1="-234.00002"
+ x2="147.41411"
+ y2="-239.28557" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient17819"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(280,459)"
+ x1="150.95467"
+ y1="-234.00002"
+ x2="147.41411"
+ y2="-239.28557" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient17817"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(280,461)"
+ x1="150.95467"
+ y1="-234.00002"
+ x2="147.41411"
+ y2="-239.28557" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient17535"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-22)"
+ x1="148.15451"
+ y1="-216.25"
+ x2="157.91019"
+ y2="-216.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient17533"
+ gradientUnits="userSpaceOnUse"
+ x1="107.15463"
+ y1="-227.83138"
+ x2="105.81714"
+ y2="-219.8996" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient17531"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(20.000285,-20.002166)"
+ x1="123.36729"
+ y1="-219.24783"
+ x2="136.51436"
+ y2="-217.99782" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient17529"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(20.000285,-20.002166)"
+ x1="135.30351"
+ y1="-219.54408"
+ x2="123.63815"
+ y2="-219.49783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient17527"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-22)"
+ x1="157.97339"
+ y1="-215.99998"
+ x2="146.36111"
+ y2="-215.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient18207">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop18209" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1"
+ id="stop18211" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18207"
+ id="linearGradient18213"
+ x1="481.46063"
+ y1="219"
+ x2="519.44189"
+ y2="218.48816"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient17506"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-22)"
+ x1="148.15451"
+ y1="-216.25"
+ x2="157.91019"
+ y2="-216.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient17504"
+ gradientUnits="userSpaceOnUse"
+ x1="107.15463"
+ y1="-227.83138"
+ x2="105.81714"
+ y2="-219.8996" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient17502"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(20.000285,-20.002166)"
+ x1="123.36729"
+ y1="-219.24783"
+ x2="136.51436"
+ y2="-217.99782" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient17500"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(20.000285,-20.002166)"
+ x1="135.30351"
+ y1="-219.54408"
+ x2="123.63815"
+ y2="-219.49783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient17498"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-22)"
+ x1="157.97339"
+ y1="-215.99998"
+ x2="146.36111"
+ y2="-215.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient18670"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2078427,0,0,1.0516432,-357.40769,69.427229)"
+ x1="362.28571"
+ y1="-45.098213"
+ x2="352.46426"
+ y2="-54.124699" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask18666">
+ <rect
+ y="6"
+ x="62.921577"
+ height="14.000001"
+ width="15.098035"
+ id="rect18668"
+ style="fill:url(#linearGradient18670);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient15592"
+ gradientUnits="userSpaceOnUse"
+ x1="127.50285"
+ y1="114.74636"
+ x2="132.35237"
+ y2="118.69846" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient15590"
+ gradientUnits="userSpaceOnUse"
+ x1="127.50285"
+ y1="114.74636"
+ x2="135.54628"
+ y2="120.58403" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient15596"
+ gradientUnits="userSpaceOnUse"
+ x1="124.52369"
+ y1="112.22441"
+ x2="131.10667"
+ y2="118.10129" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient15594"
+ gradientUnits="userSpaceOnUse"
+ x1="127.50285"
+ y1="114.74636"
+ x2="134.62978"
+ y2="120.14633" />
+ <linearGradient
+ id="linearGradient14219">
+ <stop
+ id="stop14221"
+ offset="0"
+ style="stop-color:#ff8605;stop-opacity:1;" />
+ <stop
+ id="stop14223"
+ offset="1"
+ style="stop-color:#9c6700;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient31456">
+ <stop
+ style="stop-color:#2b1600;stop-opacity:1;"
+ offset="0"
+ id="stop31458" />
+ <stop
+ style="stop-color:#6e3900;stop-opacity:0;"
+ offset="1"
+ id="stop31460" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient19425">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop19427" />
+ <stop
+ id="stop19431"
+ offset="0.63109845"
+ style="stop-color:#fffffe;stop-opacity:0.65789473;" />
+ <stop
+ style="stop-color:#fffffe;stop-opacity:0.0000000;"
+ offset="1.0000000"
+ id="stop19429" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient30208">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop30210" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop30212" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15782"
+ gradientUnits="userSpaceOnUse"
+ x1="125.19086"
+ y1="125.66204"
+ x2="132.98256"
+ y2="118" />
+ <linearGradient
+ id="linearGradient9030">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop9032" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop9034" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37542">
+ <stop
+ id="stop37544"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient30124">
+ <stop
+ style="stop-color:#1d4a8c;stop-opacity:1;"
+ offset="0"
+ id="stop30126" />
+ <stop
+ style="stop-color:#c1d4f2;stop-opacity:1;"
+ offset="1"
+ id="stop30128" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15893">
+ <stop
+ style="stop-color:#2968c3;stop-opacity:1;"
+ offset="0"
+ id="stop15895" />
+ <stop
+ id="stop15897"
+ offset="0.37679368"
+ style="stop-color:#b5ccf0;stop-opacity:1;" />
+ <stop
+ style="stop-color:#b5ccf0;stop-opacity:1;"
+ offset="0.59786767"
+ id="stop15899" />
+ <stop
+ style="stop-color:#2968c3;stop-opacity:1;"
+ offset="1"
+ id="stop15901" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient24000">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop24002" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop24004" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient32998">
+ <stop
+ style="stop-color:#2968c3;stop-opacity:1;"
+ offset="0"
+ id="stop33000" />
+ <stop
+ style="stop-color:#c1d7f8;stop-opacity:1;"
+ offset="1"
+ id="stop33002" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient21364"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,-32.5,115.5045)"
+ x1="261.83936"
+ y1="11.593864"
+ x2="277.86761"
+ y2="29.392145" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient21366"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,-32.9445,114.0045)"
+ x1="272.05627"
+ y1="24.537012"
+ x2="283.42514"
+ y2="37.115723" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient21368"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(124,-102.00001)"
+ x1="85.1875"
+ y1="239.125"
+ x2="92.8125"
+ y2="245.625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient21370"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,-32.5,115.5045)"
+ x1="261.83936"
+ y1="11.593864"
+ x2="277.86761"
+ y2="29.392145" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient21372"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,-32.9445,114.0045)"
+ x1="272.05627"
+ y1="24.537012"
+ x2="283.42514"
+ y2="37.115723" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient21374"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(124,-102.00001)"
+ x1="85.1875"
+ y1="239.125"
+ x2="92.8125"
+ y2="245.625" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="radialGradient21517"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.891843,0,0,0.909224,-173.99085,171.21624)"
+ cx="350.5"
+ cy="14.5"
+ fx="350.5"
+ fy="14.5"
+ r="6.9000001" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient21641"
+ gradientUnits="userSpaceOnUse"
+ x1="127.50285"
+ y1="114.74636"
+ x2="133.62564"
+ y2="120.24665" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient21643"
+ gradientUnits="userSpaceOnUse"
+ x1="126.15096"
+ y1="113.21745"
+ x2="132"
+ y2="118" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient20796"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(159.9998,-41.00751)"
+ x1="261.44702"
+ y1="234.6606"
+ x2="274.30609"
+ y2="247.73561" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient20798"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(199.9999,105.99249)"
+ x1="235.46884"
+ y1="103"
+ x2="228.71886"
+ y2="94.53125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient21862"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="3.2344713"
+ y1="215.76874"
+ x2="33.15686"
+ y2="247.71701" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient21864"
+ gradientUnits="userSpaceOnUse"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="19.011419"
+ y2="86" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient21902"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="3.3268692"
+ y1="215.35608"
+ x2="33.15686"
+ y2="247.71701" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient21904"
+ gradientUnits="userSpaceOnUse"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="18.51141"
+ y2="85.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient31646"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.000006,0,0,1,258.9997,-237)"
+ x1="24.374985"
+ y1="238.33629"
+ x2="55.384842"
+ y2="269.1373" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31648"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,16)"
+ x1="278.55817"
+ y1="-16.978563"
+ x2="291.577"
+ y2="-5.8786855" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20036"
+ id="radialGradient31650"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.816279,0,-3.646264e-6,0.779872,56.32029,28.34496)"
+ cx="306.55292"
+ cy="11.818644"
+ fx="306.55292"
+ fy="11.818644"
+ r="4.25" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14418"
+ id="radialGradient31652"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.580596,1.138426,-0.692447,0.961382,-175.3891,-329.6844)"
+ cx="312.80765"
+ cy="10.620173"
+ fx="312.80765"
+ fy="10.620173"
+ r="4.25" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20962"
+ id="radialGradient31654"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.48445,-0.00657397,0.00734631,1.660903,-154.1629,19.305572)"
+ cx="313.74268"
+ cy="15.619254"
+ fx="313.74268"
+ fy="15.619254"
+ r="4.25" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20973"
+ id="radialGradient31656"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.756245,0,-3.378096e-6,0.722516,72.63115,31.07857)"
+ cx="309.0571"
+ cy="15.518281"
+ fx="309.0571"
+ fy="15.518281"
+ r="4.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient31664"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8579582,0,0,0.9285714,7.397998,-211.96428)"
+ x1="-6.3249049"
+ y1="205.0083"
+ x2="32.351238"
+ y2="248.75177" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient31666"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.9569715,-1,0,259,351.18743)"
+ x1="347.6467"
+ y1="216.75188"
+ x2="345.98633"
+ y2="243.92201" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31668"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166667,0,0,0.9166667,24.364541,-55.041665)"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="18.01141"
+ y2="84.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient31672"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.9297203,-1.2117965,0,305.73028,342.22894)"
+ x1="346.15555"
+ y1="218.2382"
+ x2="346.58698"
+ y2="238.44429" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31694"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166695,0,0,0.9203753,-10.025729,345.78566)"
+ x1="80.60067"
+ y1="108.47212"
+ x2="68.0271"
+ y2="94.239906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13938"
+ id="linearGradient31696"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-15.983875,338)"
+ x1="70.55275"
+ y1="97.5"
+ x2="79.355118"
+ y2="107.18619" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31698"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9998599,0,0,0.9960071,-15.972985,338.41149)"
+ x1="64.998215"
+ y1="90.951675"
+ x2="86.00116"
+ y2="112.03586" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient31932"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,105.5221,92.482413)"
+ x1="257.0376"
+ y1="10.838325"
+ x2="277.61203"
+ y2="31.019331" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient31934"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7827973,0,0,0.9989462,77.082208,42.08484)"
+ x1="332.03717"
+ y1="68.624634"
+ x2="346.08932"
+ y2="83.002625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31936"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(262,-125)"
+ x1="79.329903"
+ y1="236"
+ x2="92.8125"
+ y2="245.625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24000"
+ id="linearGradient33666"
+ gradientUnits="userSpaceOnUse"
+ x1="124.14184"
+ y1="126.23546"
+ x2="132"
+ y2="118" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient33668"
+ gradientUnits="userSpaceOnUse"
+ x1="125.45158"
+ y1="125.94608"
+ x2="133.53401"
+ y2="116.55647" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient33670"
+ gradientUnits="userSpaceOnUse"
+ x1="142.97318"
+ y1="107.64013"
+ x2="130.82327"
+ y2="119.554" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient33681"
+ gradientUnits="userSpaceOnUse"
+ x1="139.93341"
+ y1="110.56118"
+ x2="132"
+ y2="118.66972" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient32842"
+ id="linearGradient33700"
+ gradientUnits="userSpaceOnUse"
+ x1="149.55772"
+ y1="98.630066"
+ x2="123.9021"
+ y2="127.60542" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient10540"
+ gradientUnits="userSpaceOnUse"
+ x1="130.95198"
+ y1="117.09563"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient11333"
+ gradientUnits="userSpaceOnUse"
+ x1="119.1647"
+ y1="106.08605"
+ x2="133.01006"
+ y2="119.79803" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient28057"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-425,393.99999)"
+ x1="225.6198"
+ y1="5.7625732"
+ x2="236.47855"
+ y2="14.103563" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30208"
+ id="linearGradient28077"
+ x1="306.26187"
+ y1="272"
+ x2="307"
+ y2="263.55374"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient28474"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,10)"
+ x1="431.05026"
+ y1="121.42467"
+ x2="446.26407"
+ y2="110.49417" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient28528"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,10)"
+ x1="442.69827"
+ y1="107.56771"
+ x2="450.27414"
+ y2="122.95798" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient28530"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-474,158.25)"
+ x1="437.57828"
+ y1="104.34499"
+ x2="447.96875"
+ y2="117.90625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient28532"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,10)"
+ x1="-38.103703"
+ y1="266.11719"
+ x2="-20.826464"
+ y2="253.23859" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient10982"
+ x1="207.04637"
+ y1="182.09375"
+ x2="213.7883"
+ y2="182.52524"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient10984"
+ x1="212.04637"
+ y1="182.09375"
+ x2="222.35799"
+ y2="182.77524"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient11762"
+ x1="371.98389"
+ y1="203"
+ x2="376.48389"
+ y2="203"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient11764"
+ x1="366.98389"
+ y1="203"
+ x2="370.98389"
+ y2="202.75"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient11766"
+ x1="391.62881"
+ y1="243.48854"
+ x2="386.13718"
+ y2="244.68996"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient12427"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.050372,0,0,1.050372,-3.551238,-0.730396)"
+ cx="70.5"
+ cy="14.5"
+ fx="70.5"
+ fy="14.5"
+ r="1.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14219"
+ id="radialGradient12429"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5007214,0.3131662,-0.3623683,0.5793905,300.02235,-93.056748)"
+ cx="70.470596"
+ cy="14.649424"
+ fx="70.470596"
+ fy="14.649424"
+ r="5.5192375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16359"
+ id="linearGradient12602"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,456.04574,-116.51416)"
+ x1="88.079262"
+ y1="66.110847"
+ x2="95.954262"
+ y2="58.272621" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31456"
+ id="linearGradient12114"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1438.0001,-418)"
+ x1="1663.8125"
+ y1="722"
+ x2="1661.8125"
+ y2="726.37006" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19425"
+ id="radialGradient12116"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.1378252,-0.2988982,2.5269117,1.1651875,-1830.2675,-33.64056)"
+ cx="1662.2664"
+ cy="722.19189"
+ fx="1662.2664"
+ fy="722.19189"
+ r="5.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient12118"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,-1397.7474,-388.72044)"
+ x1="1984.5453"
+ y1="828.21777"
+ x2="1978.11"
+ y2="829.35315" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30208"
+ id="linearGradient12213"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1297,-948)"
+ x1="1663.8125"
+ y1="722"
+ x2="1661.8125"
+ y2="726.37006" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19425"
+ id="radialGradient12215"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.1378252,-0.2988982,2.5269117,1.1651875,-1689.2674,-563.64056)"
+ cx="1662.2664"
+ cy="722.19189"
+ fx="1662.2664"
+ fy="722.19189"
+ r="5.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient12217"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,-1256.7473,-918.72044)"
+ x1="1984.3658"
+ y1="827.77124"
+ x2="1979.2772"
+ y2="827.32849" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient12305"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2000005,0,0,1.1997014,-125.70008,-191.68873)"
+ x1="257.24991"
+ y1="147.38998"
+ x2="262.24991"
+ y2="152.46707" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient12307"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2000005,0,0,1.1997014,-125.70008,-191.68873)"
+ x1="258.08322"
+ y1="147.87068"
+ x2="264.16571"
+ y2="153.8233" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient13046"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(360,-161.99999)"
+ x1="-80"
+ y1="151"
+ x2="-80"
+ y2="152.24998" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask13041">
+ <rect
+ style="fill:url(#linearGradient13046);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect13043"
+ width="7"
+ height="8"
+ x="276"
+ y="-12" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient13056"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(360,-145.93749)"
+ x1="-80"
+ y1="151"
+ x2="-80"
+ y2="152.24998" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask13052">
+ <rect
+ y="4.0625"
+ x="276"
+ height="8"
+ width="7"
+ id="rect13054"
+ style="fill:url(#linearGradient13056);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="scale(1,-1)" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient14167"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-636.98388,52.01562)"
+ x1="443.86667"
+ y1="133.98936"
+ x2="451.98389"
+ y2="143.58749" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4138"
+ id="linearGradient14169"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-635.98388,53.01562)"
+ x1="456.03769"
+ y1="135.76678"
+ x2="453.61005"
+ y2="133.00301" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient14171"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-636.98388,52.01562)"
+ x1="449.14645"
+ y1="136.18045"
+ x2="453.24457"
+ y2="138.7879" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4138"
+ id="linearGradient14173"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-635.98388,53.01562)"
+ x1="456.03769"
+ y1="135.76678"
+ x2="454.31345"
+ y2="133.62801" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient13112"
+ gradientUnits="userSpaceOnUse"
+ x1="133.42287"
+ y1="120.62622"
+ x2="126.67323"
+ y2="113.20281" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient13114"
+ gradientUnits="userSpaceOnUse"
+ x1="120.77391"
+ y1="106.19939"
+ x2="144.64095"
+ y2="129.62753" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient16027"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8289081,0,0,2.1560411,236.27148,-864.45588)"
+ x1="212"
+ y1="435.59741"
+ x2="211.99998"
+ y2="435.32159" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23647"
+ id="linearGradient16031"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1035181,0,0,1,158.18497,-359.77344)"
+ x1="229.6875"
+ y1="440.51562"
+ x2="238.53125"
+ y2="440.57812" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23390"
+ id="radialGradient16034"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.8126517,-0.04317018,0.04642643,1.9485655,-18.817545,-774.28453)"
+ cx="224.32494"
+ cy="441.84744"
+ fx="224.32494"
+ fy="441.84744"
+ r="6.7191267" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30208"
+ id="linearGradient16036"
+ gradientUnits="userSpaceOnUse"
+ x1="211.99998"
+ y1="435.7319"
+ x2="211.99998"
+ y2="436.07974"
+ gradientTransform="matrix(0.9803611,0,0,2.1560411,204.16345,-864.45588)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23647"
+ id="linearGradient16039"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(182,-359.75)"
+ x1="221.96414"
+ y1="439.75"
+ x2="238.87605"
+ y2="448.88205" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient17337"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.0041772,0,0,0.9688607,-81.584854,117.13687)"
+ x1="-4.9152389"
+ y1="252.69086"
+ x2="-45.689278"
+ y2="252.63284" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient17339"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9993234,0,0,1.0050357,-171.92846,305.72314)"
+ x1="107.96875"
+ y1="53.875"
+ x2="117"
+ y2="60.125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient17656"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0008786,0,0,1.081555,-21.021535,-187.45087)"
+ x1="-12.839478"
+ y1="201"
+ x2="44.522621"
+ y2="256.70349" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient17658"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.099576,0,0,1.0999923,190.46996,204.85062)"
+ x1="9.6310225"
+ y1="76"
+ x2="15"
+ y2="81" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient17712"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.0041772,0,0,0.9688607,370.43125,-83.863716)"
+ x1="-5.6700387"
+ y1="250.87607"
+ x2="-46.452946"
+ y2="251.42462" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient17714"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9993234,0,0,1.0050357,280.08766,104.72255)"
+ x1="102.61966"
+ y1="50.742527"
+ x2="117"
+ y2="60.125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient12655"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8193413,0,0,0.8193419,-388.72692,-564.02452)"
+ x1="150.4086"
+ y1="104.61366"
+ x2="151.40744"
+ y2="105.64391" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30208"
+ id="linearGradient12658"
+ gradientUnits="userSpaceOnUse"
+ x1="150.4086"
+ y1="104.61366"
+ x2="151.40744"
+ y2="105.64391"
+ gradientTransform="matrix(0.8193413,0,0,0.8193419,141.28585,391.96271)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30208"
+ id="linearGradient13511"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8193413,0,0,0.8193419,141.28585,391.96271)"
+ x1="150.4086"
+ y1="104.61366"
+ x2="151.40744"
+ y2="105.64391" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient13513"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8193413,0,0,0.8193419,-388.72692,-564.02452)"
+ x1="150.4086"
+ y1="104.61366"
+ x2="151.40744"
+ y2="105.64391" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30208"
+ id="linearGradient13527"
+ gradientUnits="userSpaceOnUse"
+ x1="328.95557"
+ y1="33.94022"
+ x2="331.74063"
+ y2="37.044456" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient13529"
+ gradientUnits="userSpaceOnUse"
+ x1="328.38852"
+ y1="33.505165"
+ x2="331.44778"
+ y2="36.739578" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient14568"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(68.016116,127.00002)"
+ x1="97.983887"
+ y1="127.99998"
+ x2="88.983887"
+ y2="115.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient14570"
+ gradientUnits="userSpaceOnUse"
+ x1="94.485573"
+ y1="122.13319"
+ x2="89.207298"
+ y2="125.83332" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient14572"
+ gradientUnits="userSpaceOnUse"
+ x1="88.560204"
+ y1="127.88263"
+ x2="94.011101"
+ y2="123.83599" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient47130"
+ id="linearGradient13699"
+ x1="-162.89217"
+ y1="245"
+ x2="-174.18907"
+ y2="224.99274"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13998"
+ id="linearGradient26282"
+ gradientUnits="userSpaceOnUse"
+ x1="13.5"
+ y1="57.827747"
+ x2="11.472005"
+ y2="53.875874" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13998"
+ id="linearGradient26284"
+ gradientUnits="userSpaceOnUse"
+ x1="-18.600719"
+ y1="501.96539"
+ x2="-26.642899"
+ y2="487.60382" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient26286"
+ gradientUnits="userSpaceOnUse"
+ x1="15.027407"
+ y1="60.637787"
+ x2="13.5"
+ y2="57.750687" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient26288"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.03018343,0.1408617)"
+ x1="-32.067383"
+ y1="490.70178"
+ x2="-22.25"
+ y2="500" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient14198"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(218.01612,129)"
+ x1="87.03125"
+ y1="241"
+ x2="92.8125"
+ y2="245.625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient14204"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,61.53822,346.48241)"
+ x1="246.89435"
+ y1="-4.4418921"
+ x2="277.68143"
+ y2="30.743095" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15195"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166695,0,0,0.9203753,-10.025729,345.78566)"
+ x1="80.60067"
+ y1="108.47212"
+ x2="68.0271"
+ y2="94.239906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient71814"
+ id="linearGradient15209"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-15.983875,338)"
+ x1="70.55275"
+ y1="97.5"
+ x2="79.355118"
+ y2="107.18619" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15211"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9998599,0,0,0.9960071,-15.972985,338.41149)"
+ x1="61.465469"
+ y1="88.058716"
+ x2="86.00116"
+ y2="112.03586" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient15363"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9999519,0,0,0.9998051,-33.993941,254.01926)"
+ x1="101.21339"
+ y1="68.783279"
+ x2="135.45256"
+ y2="103.11092" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient15365"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1004102,0,0,1.0993832,40.331334,244.81698)"
+ x1="47.655102"
+ y1="93.805557"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10585"
+ id="linearGradient15367"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.032977,0,0,1,128.82015,107.77516)"
+ x1="12.330792"
+ y1="246.97107"
+ x2="41.654194"
+ y2="247.3784" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18207"
+ id="linearGradient15383"
+ gradientUnits="userSpaceOnUse"
+ x1="-132.24858"
+ y1="313.87549"
+ x2="-171.01999"
+ y2="223.69542" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient14377"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(1.691866,0.00341)"
+ x1="86.452194"
+ y1="101.22832"
+ x2="110.48556"
+ y2="81.14637" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient16638"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(42,0)"
+ x1="108"
+ y1="500"
+ x2="54.8125"
+ y2="500" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15809"
+ id="linearGradient16640"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(42,0)"
+ x1="85.874489"
+ y1="501.74075"
+ x2="26.561054"
+ y2="498.48148" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient16642"
+ gradientUnits="userSpaceOnUse"
+ x1="80.768944"
+ y1="504.67188"
+ x2="76.885078"
+ y2="501.58331" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient16644"
+ gradientUnits="userSpaceOnUse"
+ x1="89.526657"
+ y1="511.42972"
+ x2="78.000008"
+ y2="501.04794" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262"
+ id="radialGradient16646"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3949409,0.3949425,-0.4243709,0.4254619,300.60762,256.85923)"
+ cx="75.95578"
+ cy="492.15359"
+ fx="75.95578"
+ fy="492.15359"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient16648"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.4624192,0,0,1.4467089,-36.975824,-224.99718)"
+ cx="79.959885"
+ cy="503.81497"
+ fx="79.959885"
+ fy="503.81497"
+ r="2.9089756" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262"
+ id="radialGradient16650"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8886193,0.8021825,-0.8051059,0.8972684,411.80247,-8.668512)"
+ cx="74.518959"
+ cy="499.99969"
+ fx="74.518959"
+ fy="499.99969"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient32447"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.054749"
+ cy="499.87418"
+ fx="75.054749"
+ fy="499.87418"
+ r="3.1650217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30231"
+ gradientUnits="userSpaceOnUse"
+ x1="441.48248"
+ y1="105.03784"
+ x2="446.73828"
+ y2="111.74544" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24101"
+ id="linearGradient30233"
+ gradientUnits="userSpaceOnUse"
+ x1="445.37457"
+ y1="112.86145"
+ x2="425.92511"
+ y2="84.928581" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30235"
+ gradientUnits="userSpaceOnUse"
+ x1="440.68439"
+ y1="106.0996"
+ x2="446.00906"
+ y2="110.93529" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30237"
+ gradientUnits="userSpaceOnUse"
+ x1="440.34833"
+ y1="105.74502"
+ x2="445.36435"
+ y2="110.27587" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30239"
+ gradientUnits="userSpaceOnUse"
+ x1="440.7211"
+ y1="104.97093"
+ x2="445.36435"
+ y2="110.27587" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23302"
+ id="linearGradient30241"
+ gradientUnits="userSpaceOnUse"
+ x1="414.99771"
+ y1="-35"
+ x2="414.99771"
+ y2="-36.625011" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24081"
+ id="linearGradient30243"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.004608,0)"
+ x1="416.00461"
+ y1="-34"
+ x2="415.94211"
+ y2="-37.718761" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient30245"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.004608,0)"
+ x1="416.5"
+ y1="-29.933779"
+ x2="416.5"
+ y2="-37.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient30247"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1,0)"
+ x1="416.41162"
+ y1="-34.342831"
+ x2="416.46497"
+ y2="-39.140816" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30249"
+ gradientUnits="userSpaceOnUse"
+ x1="409.00003"
+ y1="-40.99012"
+ x2="413.49658"
+ y2="-34.707108" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30326"
+ gradientUnits="userSpaceOnUse"
+ x1="446.05634"
+ y1="112.72269"
+ x2="436.76331"
+ y2="100.6615" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30328"
+ gradientUnits="userSpaceOnUse"
+ x1="440.03735"
+ y1="103.53646"
+ x2="446.73828"
+ y2="111.74544" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30330"
+ gradientUnits="userSpaceOnUse"
+ x1="447.06949"
+ y1="114.61743"
+ x2="432.36887"
+ y2="94.07222" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30332"
+ gradientUnits="userSpaceOnUse"
+ x1="438.92477"
+ y1="103.46223"
+ x2="446.00906"
+ y2="110.93529" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30334"
+ gradientUnits="userSpaceOnUse"
+ x1="439.0434"
+ y1="104.06953"
+ x2="445.36435"
+ y2="110.27587" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30336"
+ gradientUnits="userSpaceOnUse"
+ x1="439.04333"
+ y1="104.0401"
+ x2="445.36435"
+ y2="110.27587" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30338"
+ gradientUnits="userSpaceOnUse"
+ x1="415.00003"
+ y1="-33.99012"
+ x2="415"
+ y2="-36.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30340"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.004608,0)"
+ x1="415.41223"
+ y1="-31.506163"
+ x2="415.45193"
+ y2="-37.520515" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient30342"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.004608,0)"
+ x1="416.5"
+ y1="-29.933779"
+ x2="416.5"
+ y2="-37.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient30344"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1,0)"
+ x1="416.5"
+ y1="-33.8125"
+ x2="416.46497"
+ y2="-39.140816" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30346"
+ gradientUnits="userSpaceOnUse"
+ x1="409.00003"
+ y1="-40.99012"
+ x2="413.49658"
+ y2="-34.707108" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient30348"
+ gradientUnits="userSpaceOnUse"
+ x1="408.75"
+ y1="-35.483223"
+ x2="408.75"
+ y2="-40.000008" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30394"
+ gradientUnits="userSpaceOnUse"
+ x1="446.05634"
+ y1="112.72269"
+ x2="436.76331"
+ y2="100.6615" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30396"
+ gradientUnits="userSpaceOnUse"
+ x1="440.03735"
+ y1="103.53646"
+ x2="446.73828"
+ y2="111.74544" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30398"
+ gradientUnits="userSpaceOnUse"
+ x1="447.06949"
+ y1="114.61743"
+ x2="432.36887"
+ y2="94.07222" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30400"
+ gradientUnits="userSpaceOnUse"
+ x1="438.92477"
+ y1="103.46223"
+ x2="446.00906"
+ y2="110.93529" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30402"
+ gradientUnits="userSpaceOnUse"
+ x1="439.0434"
+ y1="104.06953"
+ x2="445.36435"
+ y2="110.27587" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30404"
+ gradientUnits="userSpaceOnUse"
+ x1="439.04333"
+ y1="104.0401"
+ x2="445.36435"
+ y2="110.27587" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30406"
+ gradientUnits="userSpaceOnUse"
+ x1="415.00003"
+ y1="-33.99012"
+ x2="415"
+ y2="-36.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30408"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.004608,0)"
+ x1="415.41223"
+ y1="-31.506163"
+ x2="415.45193"
+ y2="-37.520515" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient30410"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.004608,0)"
+ x1="416.5"
+ y1="-29.933779"
+ x2="416.5"
+ y2="-37.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient30412"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1,0)"
+ x1="416.5"
+ y1="-33.8125"
+ x2="416.46497"
+ y2="-39.140816" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30414"
+ gradientUnits="userSpaceOnUse"
+ x1="409.00003"
+ y1="-40.99012"
+ x2="413.49658"
+ y2="-34.707108" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient30416"
+ gradientUnits="userSpaceOnUse"
+ x1="408.75"
+ 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">
+ <path
+ sodipodi:nodetypes="cccc"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:none"
+ d="m -44,358 0,14 14,-14 -14,0 z"
+ id="path17572"
+ inkscape:connector-curvature="0" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient18682"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8461524,0,0,0.9230835,365.8517,-147.63686)"
+ x1="27.405855"
+ y1="189.20862"
+ x2="35.029804"
+ y2="248.37102" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient18690"
+ gradientUnits="userSpaceOnUse"
+ x1="29.972469"
+ y1="164"
+ x2="29.972469"
+ y2="168"
+ gradientTransform="translate(359.05264,-81.98142)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient18752"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="30.435225"
+ y1="202.99998"
+ x2="30.435225"
+ y2="251.99998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient18756"
+ gradientUnits="userSpaceOnUse"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="16.733877"
+ y2="88"
+ gradientTransform="matrix(1,0,0,1.2222204,0,-15.888744)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient18779"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6923077,0,0,-0.6923079,29.049874,351.11545)"
+ x1="7.9951181"
+ y1="264.90152"
+ x2="32.267426"
+ y2="237.9342" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient18823"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-122.98388,276)"
+ x1="-55.936718"
+ y1="77.808868"
+ x2="-55.844753"
+ y2="84.217026" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient18831"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5384613,0,0,0.538461,-189.69233,224.07704)"
+ x1="29.142912"
+ y1="161.42842"
+ x2="29.142912"
+ y2="252.42851" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient18841"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.462416,0,0,0.538461,-193.81309,224.07705)"
+ x1="29.871567"
+ y1="153.99983"
+ x2="29.871567"
+ y2="252.4285" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient18846"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.462416,0,0,0.461541,-193.81309,236.42243)"
+ x1="29.871567"
+ y1="174.58366"
+ x2="29.871567"
+ y2="259.08319" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient18854"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2500001,0,0,2.2000001,-102.35484,177)"
+ x1="-55.936718"
+ y1="77.808868"
+ x2="-55.844753"
+ y2="84.217026" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient18858"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.8000001,-122.98388,285.5)"
+ x1="-55.936718"
+ y1="77.808868"
+ x2="-55.844753"
+ y2="84.217026" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient18862"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.0000001,0,0,1.6000003,163.54205,53.499972)"
+ x1="-60.266121"
+ y1="74.0625"
+ x2="-54.766121"
+ y2="84.6875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient32725"
+ gradientUnits="userSpaceOnUse"
+ x1="-88.0625"
+ y1="364"
+ x2="-44.983891"
+ y2="411.9375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32727"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166695,0,0,0.9203753,-117.02574,313.78567)"
+ x1="80.60067"
+ y1="108.47212"
+ x2="68.0271"
+ y2="94.239906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient32729"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6666675,0,0,0.6666633,-101.32265,336.66698)"
+ x1="61.983898"
+ y1="88.999977"
+ x2="89.770271"
+ y2="121.709" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32731"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9998599,0,0,0.9960071,-122.97299,306.4115)"
+ x1="61.465469"
+ y1="88.058716"
+ x2="86.00116"
+ y2="112.03586" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient32749"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.081988,0,0,1.0833333,-123.05997,-52.467545)"
+ x1="326.72092"
+ y1="33.927608"
+ x2="352.03485"
+ y2="60.463093" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient32751"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-15.983875,338)"
+ x1="-46.417774"
+ y1="1.9796312"
+ x2="-21.988398"
+ y2="27" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32753"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0983862,0,0,1.0999999,-128.47957,-53.059225)"
+ x1="324.13901"
+ y1="28.882492"
+ x2="333.96365"
+ y2="39.250004" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient17135"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(18,0)"
+ x1="-51.6875"
+ y1="442.6875"
+ x2="-42.377892"
+ y2="452.20007" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient17177"
+ gradientUnits="userSpaceOnUse"
+ x1="28.322077"
+ y1="160.10768"
+ x2="32.679554"
+ y2="164.34546" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient17179"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-6.8461644e-7,-1.8,1.1087755,0.00352366,-193.46828,187.54551)"
+ cx="4.351675"
+ cy="81.592964"
+ fx="4.351675"
+ fy="81.592964"
+ r="5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18344"
+ id="radialGradient17181"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.5123107,0.9569981,-0.5028837,0.7946898,-131.57281,-236.33663)"
+ cx="244.14325"
+ cy="-14.13948"
+ fx="244.14325"
+ fy="-14.13948"
+ r="3.4000001" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient17214"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="29.352921"
+ y1="199"
+ x2="29.352921"
+ y2="250" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient17216"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2222204,0,-15.888744)"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="16.733877"
+ y2="88" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient17218"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2859748,0,0,1,-272.87621,148)"
+ x1="348.06064"
+ y1="220.55545"
+ x2="363.71661"
+ y2="239.94608" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient17220"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4289612,0,0,1,-326.93899,144.5)"
+ x1="348.06064"
+ y1="220.55545"
+ x2="363.71661"
+ y2="239.94608" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient17222"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="29.352921"
+ y1="199"
+ x2="29.352921"
+ y2="250" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient17224"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2222204,0,-15.888744)"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="16.733877"
+ y2="88" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient17226"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2868892,0,0,1,-644.69395,148)"
+ x1="348.06064"
+ y1="220.55545"
+ x2="363.71661"
+ y2="239.94608" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient17242"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,-18.1369,-168)"
+ x1="9.5404434"
+ y1="223.47467"
+ x2="36.247395"
+ y2="249.62102" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient17244"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2222204,0,-15.888744)"
+ x1="5.9836898"
+ y1="71.51989"
+ x2="16.733877"
+ y2="88" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient18712"
+ 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
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient18721"
+ 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"
+ id="linearGradient18728"
+ 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"
+ id="linearGradient18765"
+ 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="#linearGradient34157"
+ id="linearGradient35488"
+ gradientUnits="userSpaceOnUse"
+ x1="270.66064"
+ y1="68.113258"
+ x2="257.38638"
+ y2="81.382545" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35490"
+ gradientUnits="userSpaceOnUse"
+ x1="256.38586"
+ y1="80.515495"
+ x2="262.43726"
+ y2="74.562462" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient35492"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient35494"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient35967"
+ cx="257.35309"
+ cy="79.598709"
+ fx="257.35309"
+ fy="79.598709"
+ r="3.779551"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.656002,0,0,0.656002,88.923481,27.003843)" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath18524">
+ <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.1435655,0,0,1.1436475,512.11415,45.72091)"
+ 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="path18526"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.69954133;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.3473305"
+ inkscape:transform-center-y="-6.3853012" />
+ </clipPath>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask18634">
+ <path
+ sodipodi:nodetypes="ccccscc"
+ style="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"
+ d="m 207,134 0,14 11,0 0,-7.5625 c -1.97252,-0.24738 -3.5,-1.89814 -3.5,-3.9375 0,-0.94675 0.35614,-1.81444 0.90625,-2.5 L 207,134 z"
+ id="path18636"
+ inkscape:connector-curvature="0" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient18478"
+ gradientUnits="userSpaceOnUse"
+ x1="172.5625"
+ y1="601.5"
+ x2="159.13864"
+ y2="585.28772" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient18480"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-97.983877,565.25)"
+ x1="249.64528"
+ y1="1.5973248"
+ x2="271.98389"
+ y2="35.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient18739"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707654,0,0,0.707942,43.55464,-148.13985)"
+ x1="35.597904"
+ y1="158.14117"
+ x2="16.173666"
+ y2="173.23431" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4343"
+ id="linearGradient18741"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5990464,-0.03583042,0.03242597,0.6546824,59.652868,-253.61658)"
+ x1="-12.264804"
+ y1="333.22653"
+ x2="-10.869003"
+ y2="334.86029" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient18743"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(250.01612,148)"
+ x1="-190.37566"
+ y1="-180.13821"
+ x2="-189.34792"
+ y2="-182" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient19045"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.172144,-461,-82.584001)"
+ x1="42.033173"
+ y1="164.51399"
+ x2="75.32457"
+ y2="164.51399" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient19047"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(298,-53.749881)"
+ x1="118.1319"
+ y1="157.11609"
+ x2="85.577972"
+ y2="157.54283" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient19049"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.3333334,0,0,0.8333334,767.51613,327.08335)"
+ x1="-285.65732"
+ y1="-274.23453"
+ x2="-279.44821"
+ y2="-268.04858" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35583"
+ gradientUnits="userSpaceOnUse"
+ x1="-0.78523314"
+ y1="-33.408295"
+ x2="4.952816"
+ y2="-27.882322" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35585"
+ gradientUnits="userSpaceOnUse"
+ x1="-0.78523314"
+ y1="-33.408295"
+ x2="3.1666665"
+ y2="-29.550003" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35587"
+ gradientUnits="userSpaceOnUse"
+ x1="-3.5"
+ y1="-35.5"
+ x2="2.6932251"
+ y2="-29.488832" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35589"
+ gradientUnits="userSpaceOnUse"
+ x1="4.9341426"
+ y1="-29.678047"
+ x2="4.8398785e-16"
+ y2="-32.351803" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35591"
+ gradientUnits="userSpaceOnUse"
+ x1="0.5079475"
+ y1="-32.317398"
+ x2="4.2000003"
+ y2="-28.597046" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient35593"
+ gradientUnits="userSpaceOnUse"
+ x1="2.8144052"
+ y1="-28.1"
+ x2="-4.375"
+ y2="-36.441402" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35595"
+ gradientUnits="userSpaceOnUse"
+ x1="-2.7708333"
+ y1="-35.5"
+ x2="1.1666667"
+ y2="-32" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient35740"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707654,0,0,0.707942,-206.46148,-296.13985)"
+ x1="35.597904"
+ y1="158.14117"
+ x2="10.490564"
+ y2="176.41806" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient35742"
+ gradientUnits="userSpaceOnUse"
+ x1="58.060974"
+ y1="-23.721956"
+ x2="40"
+ y2="-35" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35744"
+ gradientUnits="userSpaceOnUse"
+ x1="46.1875"
+ y1="-28.59375"
+ x2="41.099998"
+ y2="-33.59375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient36116"
+ id="linearGradient35746"
+ gradientUnits="userSpaceOnUse"
+ x1="46"
+ y1="-32"
+ x2="43.883884"
+ y2="-33.939339" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35748"
+ gradientUnits="userSpaceOnUse"
+ x1="41"
+ y1="-29"
+ x2="43"
+ y2="-27" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35750"
+ gradientUnits="userSpaceOnUse"
+ x1="48.662914"
+ y1="-27.071922"
+ x2="43.47097"
+ y2="-32.337086" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35752"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(6.3,-4.7)"
+ x1="39.200001"
+ y1="-30.799999"
+ x2="41.200001"
+ y2="-28.640625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35754"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(5.315625,-3.75)"
+ x1="39.200001"
+ y1="-30.799999"
+ x2="41.325001"
+ y2="-28.765625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35756"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(3.3,0.3)"
+ x1="38.700001"
+ y1="-31.299999"
+ x2="40.012501"
+ y2="-29.799999" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35772"
+ gradientUnits="userSpaceOnUse"
+ x1="51.912914"
+ y1="-24.696922"
+ x2="40.75"
+ y2="-35.75"
+ gradientTransform="translate(-0.75,4.75)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient51774"
+ gradientUnits="userSpaceOnUse"
+ x1="135.32962"
+ y1="120.04005"
+ x2="130.7244"
+ y2="116.31882" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient51776"
+ gradientUnits="userSpaceOnUse"
+ x1="130.9015"
+ y1="115.23484"
+ x2="143.88347"
+ y2="129.27184" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient8864"
+ id="linearGradient51804"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9993234,0,0,1.0050357,111.43697,300.37199)"
+ x1="107.78085"
+ y1="50.778313"
+ x2="111.53449"
+ y2="46.679707" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient51806"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9993234,0,0,1.0050357,111.55698,300.497)"
+ x1="115.37703"
+ y1="51.021076"
+ x2="112.87534"
+ y2="51.021076" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient51808"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9993234,0,0,1.0050357,111.35699,300.55457)"
+ x1="110.57378"
+ y1="50.963791"
+ x2="108.07208"
+ y2="50.963791" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient51810"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5192341,-0.5192341,0.5184617,0.5184617,100.36783,218.31526)"
+ x1="-13.691219"
+ y1="241.78653"
+ x2="0.92051411"
+ y2="237.27565" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient51812"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5192341,-0.5192341,0.5184617,0.5184617,100.13133,218.33837)"
+ x1="-9.0782614"
+ y1="249.96617"
+ x2="-2.9318311"
+ y2="240.68927" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient68937"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(439.89375,-187.79999)"
+ x1="-5.3499999"
+ y1="251.51265"
+ x2="-8.5254431"
+ y2="248.125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient68939"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(439.89375,-187.79999)"
+ x1="-10.35"
+ y1="245.89999"
+ x2="-13.091064"
+ y2="242.8" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient68941"
+ gradientUnits="userSpaceOnUse"
+ x1="-41.065678"
+ y1="240.10526"
+ x2="-15.758821"
+ y2="244.11874" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient68943"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(440.2082,-188.0039)"
+ x1="-10.991813"
+ y1="237.9574"
+ x2="-7.0786314"
+ y2="246.7774" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient68945"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(439.9582,-188.0039)"
+ x1="-5.1338587"
+ y1="244.08765"
+ x2="-14.193665"
+ y2="251.35759" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient8864"
+ id="linearGradient68947"
+ gradientUnits="userSpaceOnUse"
+ x1="-15.6"
+ y1="247.38559"
+ x2="-3.321322"
+ y2="245.68124" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient68949"
+ gradientUnits="userSpaceOnUse"
+ x1="-5.3499999"
+ y1="251.51265"
+ x2="-8.7065439"
+ y2="248.125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient68951"
+ gradientUnits="userSpaceOnUse"
+ x1="-10.35"
+ y1="245.89999"
+ x2="-13.125"
+ y2="242.81946" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient68953"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.25,0.2058042)"
+ x1="-12.538609"
+ y1="240.79787"
+ x2="0.92051411"
+ y2="237.27565" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient68955"
+ gradientUnits="userSpaceOnUse"
+ x1="-7.20822"
+ y1="247.4906"
+ x2="-1.7751017"
+ y2="239.86711" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient69009"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.5466301,0,0,1.6489946,-293.01107,-16.485383)"
+ x1="582"
+ y1="49.294117"
+ x2="582"
+ y2="47.176472" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask69005">
+ <rect
+ style="fill:url(#linearGradient69009);fill-opacity:1;display:inline"
+ id="rect69007"
+ width="24.746082"
+ height="26.383913"
+ x="596.30127"
+ y="39.580433" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient20269"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(12.999999,359)"
+ x1="247"
+ y1="99"
+ x2="247"
+ y2="94" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient20275"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(15.081669,359)"
+ x1="245.63066"
+ y1="106.28436"
+ x2="245.80791"
+ y2="94.440376" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient20283"
+ x1="263.5"
+ y1="455.25"
+ x2="263.5"
+ y2="460.5"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient20303"
+ gradientUnits="userSpaceOnUse"
+ x1="264"
+ y1="452"
+ x2="264"
+ y2="460.6622"
+ gradientTransform="matrix(1,0,0,0.6,-5,182.8)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient20309"
+ x1="268"
+ y1="462"
+ x2="256"
+ y2="459"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#aigrd2"
+ id="radialGradient21565"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2798768,0,0,0.279916,6.0465962,-0.3619733)"
+ cx="20.892099"
+ cy="114.5684"
+ fx="20.892099"
+ fy="114.5684"
+ r="5.256" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#aigrd2"
+ id="radialGradient21567"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2798768,0,0,0.279916,6.0465962,-0.3619733)"
+ cx="20.892099"
+ cy="114.5684"
+ fx="20.892099"
+ fy="114.5684"
+ r="5.256" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient21594"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)"
+ x1="236.94902"
+ y1="-14.103641"
+ x2="276.89801"
+ y2="32.076183" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient21596"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-47.00001,58.00194)"
+ x1="160.14388"
+ y1="376.27383"
+ x2="174.29811"
+ y2="383.69843" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient21647"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)"
+ x1="236.94902"
+ y1="-14.103641"
+ x2="276.89801"
+ y2="31.515814" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient21649"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-47.00001,58.00194)"
+ x1="160.14388"
+ y1="376.27383"
+ x2="174.29811"
+ y2="383.69843" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient21977"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)"
+ x1="236.94902"
+ y1="-14.103641"
+ x2="276.89801"
+ y2="31.515814" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient21979"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-47.00001,58.00194)"
+ x1="160.14388"
+ y1="376.27383"
+ x2="174.29811"
+ y2="383.69843" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath22590">
+ <rect
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect22592"
+ width="12"
+ height="14"
+ x="-30"
+ y="490.00012" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient23595"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.1666667,-737,357.33333)"
+ x1="771.0965"
+ y1="354.28479"
+ x2="772"
+ y2="358.85715" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask23591">
+ <rect
+ mask="none"
+ style="fill:url(#linearGradient23595);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect23593"
+ width="11"
+ height="14"
+ x="30"
+ y="768" />
+ </mask>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath23877">
+ <rect
+ transform="scale(1,-1)"
+ y="-540"
+ x="952"
+ height="6"
+ width="15"
+ id="rect23879"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient23978"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)"
+ x1="236.94902"
+ y1="-14.103641"
+ x2="276.89801"
+ y2="31.515814" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient23980"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-47.00001,58.00194)"
+ x1="160.14388"
+ y1="376.27383"
+ x2="174.29811"
+ y2="383.69843" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31320"
+ id="linearGradient23982"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.733333,808.99997,-697.8)"
+ x1="150.5"
+ y1="239.9987"
+ x2="150.5"
+ y2="237" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29485"
+ id="linearGradient23986"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,1,0,715,364)"
+ x1="147.0625"
+ y1="243.76387"
+ x2="142.9375"
+ y2="243.69914" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30777"
+ id="linearGradient23988"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2857143,364,645.14283)"
+ x1="148"
+ y1="244.11113"
+ x2="144"
+ y2="244.11113" />
+ <linearGradient
+ id="linearGradient3564"
+ inkscape:collect="always">
+ <stop
+ id="stop3566"
+ offset="0"
+ style="stop-color:white;stop-opacity:1;" />
+ <stop
+ id="stop3568"
+ offset="1"
+ style="stop-color:white;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient39155">
+ <stop
+ id="stop39157"
+ offset="0"
+ style="stop-color:white;stop-opacity:1;" />
+ <stop
+ id="stop39159"
+ offset="1"
+ style="stop-color:#dadada;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient39171"
+ inkscape:collect="always">
+ <stop
+ id="stop39173"
+ offset="0"
+ style="stop-color:white;stop-opacity:1;" />
+ <stop
+ id="stop39175"
+ offset="1"
+ style="stop-color:white;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient21442"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient39155"
+ id="linearGradient21444"
+ gradientUnits="userSpaceOnUse"
+ x1="31.1875"
+ y1="18.875"
+ x2="29.875"
+ y2="34.375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3564"
+ id="linearGradient21446"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.06818845,0,0,0.06818845,22.51112,27.02885)"
+ x1="185.9903"
+ y1="193.33229"
+ x2="190.46461"
+ y2="-458.05771" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient39171"
+ id="radialGradient21448"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.647222,0,0,1.26792,-15.47413,-5.79794)"
+ cx="26.109201"
+ cy="19.668886"
+ fx="26.109201"
+ fy="19.668886"
+ r="20.278975" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient22274"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)"
+ x1="236.94902"
+ y1="-14.103641"
+ x2="276.89801"
+ y2="32.076183" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient22276"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-47.00001,58.00194)"
+ x1="160.14388"
+ y1="376.27383"
+ x2="174.29811"
+ y2="383.69843" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38718"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="121.22078"
+ y2="56.357628" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38721"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(207,-246.99988)"
+ x1="-56.5"
+ y1="342.0625"
+ x2="-49"
+ y2="341" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient39281"
+ gradientUnits="userSpaceOnUse"
+ x1="171"
+ y1="71"
+ x2="177"
+ y2="77" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39283"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1944456,0,0,1.2000039,-34.222431,-14.950295)"
+ x1="175.17659"
+ y1="74.972061"
+ x2="176.40117"
+ y2="76.182281" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient39285"
+ gradientUnits="userSpaceOnUse"
+ x1="165.19363"
+ y1="64.53186"
+ x2="176.15442"
+ y2="76.210785" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39287"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1718933,0,0,1.127086,-30.219387,-9.3173845)"
+ x1="172.30418"
+ y1="69.838829"
+ x2="176.84593"
+ y2="75.947906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient39289"
+ gradientUnits="userSpaceOnUse"
+ x1="171"
+ y1="70"
+ x2="177"
+ y2="77" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39291"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1718933,0,0,1.127086,-30.219387,-9.3173845)"
+ x1="175.1628"
+ y1="74.125008"
+ x2="176.84593"
+ y2="75.947906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient39293"
+ gradientUnits="userSpaceOnUse"
+ x1="171"
+ y1="70"
+ x2="177"
+ y2="77" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39295"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1718933,0,0,1.127086,-30.219387,-9.3173845)"
+ x1="175.1628"
+ y1="74.125008"
+ x2="176.84593"
+ y2="75.947906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39008"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="117.12428"
+ y2="61.720783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39010"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39012"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,13)"
+ x1="-56.8125"
+ y1="329.06256"
+ x2="-47.214466"
+ y2="329.26965" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39014"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="117.12428"
+ y2="61.720783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39016"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39018"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,13)"
+ x1="-56.8125"
+ y1="329.06256"
+ x2="-47.214466"
+ y2="329.26965" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39020"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="117.12428"
+ y2="61.720783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39022"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39024"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.7972867,61.99991,2.2419)"
+ x1="260.67468"
+ y1="108.02418"
+ x2="273.9993"
+ y2="126.37626" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39026"
+ x1="1127.7983"
+ y1="448.375"
+ x2="1153.0486"
+ y2="430.25"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14418"
+ id="linearGradient57417"
+ gradientUnits="userSpaceOnUse"
+ x1="146.82516"
+ y1="134.65511"
+ x2="130.10634"
+ y2="117.10313" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient57419"
+ gradientUnits="userSpaceOnUse"
+ x1="139.37782"
+ y1="126.3454"
+ x2="131.71249"
+ y2="118.34238" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient57421"
+ gradientUnits="userSpaceOnUse"
+ x1="125.01582"
+ y1="110.86718"
+ x2="132.46898"
+ y2="119.54019" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient57423"
+ gradientUnits="userSpaceOnUse"
+ x1="127.60629"
+ y1="112.12571"
+ x2="140.72693"
+ y2="126.72997" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient57454"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(258.00306,-231.00101)"
+ x1="75.25"
+ y1="393.25"
+ x2="73.5"
+ y2="391.5" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask57450">
+ <rect
+ y="154.99899"
+ x="326.00305"
+ height="15"
+ width="15"
+ id="rect57452"
+ style="fill:url(#linearGradient57454);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient22891"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.728189,0,0,1.727271,-357.88848,243.63713)"
+ x1="174.99828"
+ y1="12.918247"
+ x2="167.59578"
+ y2="12.551482" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30124"
+ id="linearGradient22893"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.728189,0,0,1.727271,-357.88848,243.63713)"
+ x1="169.47711"
+ y1="10.424105"
+ x2="169.47711"
+ y2="8.1183796" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30124"
+ id="linearGradient22895"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.728189,0,0,1.727271,237.88848,243.63713)"
+ x1="169.41847"
+ y1="10.306772"
+ x2="169.4877"
+ y2="7.9604731" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22897"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-215.00008,249.00001)"
+ x1="145.00008"
+ y1="11.99999"
+ x2="160.31258"
+ y2="19.34374" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22899"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-215.00008,249.00001)"
+ x1="149.00008"
+ y1="10.924165"
+ x2="171.37508"
+ y2="19.12499" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient32842"
+ id="linearGradient22901"
+ gradientUnits="userSpaceOnUse"
+ x1="-68.25"
+ y1="263"
+ x2="-56"
+ y2="265.53439" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22903"
+ gradientUnits="userSpaceOnUse"
+ x1="-66"
+ y1="264"
+ x2="-57"
+ y2="264.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient32998"
+ id="linearGradient22905"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.728189,0,0,1.727271,-357.88848,243.63713)"
+ x1="176.42079"
+ y1="12.946938"
+ x2="169.47711"
+ y2="12.36799" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient22933"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(15.081669,359)"
+ x1="245.63066"
+ y1="106.28436"
+ x2="245.80791"
+ y2="94.440376" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22935"
+ gradientUnits="userSpaceOnUse"
+ x1="268"
+ y1="462"
+ x2="256"
+ y2="459" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient22937"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(12.999999,359)"
+ x1="247"
+ y1="99"
+ x2="247"
+ y2="94" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22939"
+ gradientUnits="userSpaceOnUse"
+ x1="263.5"
+ y1="455.25"
+ x2="263.5"
+ y2="460.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22941"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.6,-5,182.8)"
+ x1="264"
+ y1="452"
+ x2="264"
+ y2="460.6622" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22970"
+ x1="-197.84375"
+ y1="399.90625"
+ x2="-191"
+ y2="409"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19625"
+ id="linearGradient23241"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-6,0)"
+ x1="480.09564"
+ y1="163.08553"
+ x2="476.76578"
+ y2="162.94037" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient23243"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(342.00029,383.00889)"
+ x1="123.36729"
+ y1="-219.24783"
+ x2="134.30893"
+ y2="-218.00888" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient12678"
+ id="radialGradient23245"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0982561,0,0,1.2662999,-45.858153,-42.45126)"
+ cx="470.15939"
+ cy="164.46814"
+ fx="470.15939"
+ fy="164.46814"
+ r="3.500145" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient23247"
+ gradientUnits="userSpaceOnUse"
+ x1="128.7561"
+ y1="115.77483"
+ x2="132.35237"
+ y2="118.69846" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient23250"
+ gradientUnits="userSpaceOnUse"
+ x1="127.30917"
+ y1="111.48133"
+ x2="138.30522"
+ y2="124.69373" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient23445"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-6,0)"
+ x1="480.09564"
+ y1="163.08553"
+ x2="475.50031"
+ y2="162.92206" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient23447"
+ 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="#linearGradient23974"
+ id="linearGradient23531"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.728189,0,0,1.727271,-142.8884,-5.3628832)"
+ x1="172.37032"
+ y1="12.147777"
+ x2="175.38158"
+ y2="15.699567" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23533"
+ gradientUnits="userSpaceOnUse"
+ x1="155.82454"
+ y1="16.845156"
+ x2="158.41653"
+ y2="19.99999" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient40843"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.727201,9.075096e-6,0,1.728246,-147.7149,-10.37485)"
+ x1="171.03941"
+ y1="11.121979"
+ x2="175.33569"
+ y2="16.202652" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient40845"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.728189,0,0,1.727271,-142.8884,-5.3628832)"
+ x1="172.18394"
+ y1="11.912162"
+ x2="176.46956"
+ y2="16.427906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40847"
+ gradientUnits="userSpaceOnUse"
+ x1="156.00008"
+ y1="16.99999"
+ x2="159.00008"
+ y2="19.99999" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient40965"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-20,14)"
+ x1="62.107086"
+ y1="223.54628"
+ x2="96.812675"
+ y2="258.38593" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient32842"
+ id="linearGradient40967"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-21,0)"
+ x1="79.04213"
+ y1="253.5"
+ x2="60.155113"
+ y2="234.7775" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient24098"
+ x1="208.25"
+ y1="-133.89581"
+ x2="204.01923"
+ y2="-111.15749"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23510"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1000194,0,0,1.0998287,-4.3008215,-8.6726798)"
+ x1="47.655102"
+ y1="93.805557"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient23512"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.728189,0,0,1.727271,-142.53857,-4.802156)"
+ x1="110.16959"
+ y1="57.061836"
+ x2="117.55341"
+ y2="64.995972" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23514"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1000194,0,0,1.0998287,-4.3010161,-8.6726854)"
+ x1="47.612946"
+ y1="93.555946"
+ x2="54.252415"
+ y2="100.44998" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23550"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(1,0.01738631)"
+ x1="468.07968"
+ y1="275.27036"
+ x2="510"
+ y2="266.99997" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18105"
+ id="linearGradient23555"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(1,3.959006e-5)"
+ x1="492.95264"
+ y1="267.42996"
+ x2="496.73859"
+ y2="270.36874" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient23581"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9993234,0,0,1.0050357,404.07104,216.722)"
+ x1="116.75796"
+ y1="52.264809"
+ x2="103.18628"
+ y2="55.747272" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient21327"
+ id="linearGradient23585"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(1,-1.0000037)"
+ x1="500.71924"
+ y1="270.24997"
+ x2="477"
+ y2="274" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient32842"
+ id="radialGradient23610"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5274943,0,0,0.7696585,194.81546,86.715119)"
+ cx="412.10059"
+ cy="375.96332"
+ fx="412.10059"
+ fy="375.96332"
+ r="4.4262571" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24343"
+ id="radialGradient23612"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0009003,-1.5278593,1.1592123,0.7594114,-59.938837,957.7287)"
+ cx="409.55594"
+ cy="52.367992"
+ fx="409.55594"
+ fy="52.367992"
+ r="3.8798895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23562"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1004102,0,0,1.0993832,461.68129,182.37748)"
+ x1="47.612946"
+ y1="93.555946"
+ x2="56.524509"
+ y2="101.25028" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient23565"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.728803,0,0,1.7265713,323.39462,186.24644)"
+ x1="115.45872"
+ y1="58.869785"
+ x2="106.20376"
+ y2="58.354706" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient22847"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.728803,0,0,1.7265713,347.39462,166.24644)"
+ x1="110.54202"
+ y1="56.645538"
+ x2="115.53827"
+ y2="63.567348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22849"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2445337,0,0,1.5876961,523.20711,115.4619)"
+ x1="47.655102"
+ y1="93.805557"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22851"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1004102,0,0,1.0993832,503.28129,157.47747)"
+ x1="29.506693"
+ y1="100.66651"
+ x2="34.276955"
+ y2="105.98901" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24052"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="117.12428"
+ y2="61.720783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24054"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24056"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,13)"
+ x1="-56.8125"
+ y1="329.06256"
+ x2="-47.214466"
+ y2="329.26965" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient24066"
+ x1="202.5"
+ y1="143.84116"
+ x2="202.5"
+ y2="132.60213"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-259,202)" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient23738"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.050372,0,0,1.050372,-3.551238,-0.730396)"
+ cx="70.5"
+ cy="14.5"
+ fx="70.5"
+ fy="14.5"
+ r="1.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient23750"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.172144,59.49999,53.45766)"
+ x1="445.5"
+ y1="148.90862"
+ x2="433.5"
+ y2="148.69533" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient23752"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6499984,0,0,0.5439483,434.02514,137.87435)"
+ x1="113.71248"
+ y1="158.24995"
+ x2="91.499992"
+ y2="158.24994" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23754"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0052083,0,0,0.5057472,778.49218,365.83334)"
+ x1="-285.65732"
+ y1="-274.23453"
+ x2="-279.44821"
+ y2="-268.04858" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23914"
+ gradientUnits="userSpaceOnUse"
+ x1="29.200638"
+ y1="160.18758"
+ x2="32.928555"
+ y2="164.13913" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient23916"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.02887268,-1.2550276,0.795821,0.01830762,8.763469,168.20647)"
+ cx="11.708446"
+ cy="81.275032"
+ fx="11.708446"
+ fy="81.275032"
+ r="5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient23918"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.01269957,-0.9297674,1.1086869,0.01514236,-16.51473,165.70609)"
+ cx="4.7455525"
+ cy="82.433929"
+ fx="4.7455525"
+ fy="82.433929"
+ r="5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient24460"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(383,-37.999994)"
+ x1="-80"
+ y1="151"
+ x2="-80"
+ y2="152.24998" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask24456">
+ <rect
+ y="108"
+ x="299"
+ height="17"
+ width="7"
+ id="rect24458"
+ style="fill:url(#linearGradient24460);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ mask="none" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient24470"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(360,-142.95536)"
+ x1="-80"
+ y1="151"
+ x2="-80"
+ y2="152.24998" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask24466">
+ <rect
+ transform="scale(1,-1)"
+ style="fill:url(#linearGradient24470);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.80000001;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect24468"
+ width="7"
+ height="9"
+ x="276"
+ y="4.0625" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient23971"
+ gradientUnits="userSpaceOnUse"
+ x1="154.24324"
+ y1="-11.628862"
+ x2="134.08138"
+ y2="-22.846634" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient23973"
+ gradientUnits="userSpaceOnUse"
+ x1="134.12642"
+ y1="-21.522242"
+ x2="132.29695"
+ y2="-23.945318" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient23975"
+ gradientUnits="userSpaceOnUse"
+ x1="134.6615"
+ y1="-21.3074"
+ x2="131.69801"
+ y2="-24.343456" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient24099"
+ x1="137.5"
+ y1="-18"
+ x2="135.25"
+ y2="-21"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient24539"
+ 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"
+ id="linearGradient24541"
+ 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"
+ id="linearGradient24543"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-6,0)"
+ x1="483.00034"
+ y1="163"
+ x2="476.68781"
+ y2="162.85956" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient24545"
+ 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"
+ id="linearGradient24547"
+ gradientUnits="userSpaceOnUse"
+ x1="475.00034"
+ y1="155"
+ x2="469.75034"
+ y2="155" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient24549"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-6,-6e-5)"
+ x1="442.81525"
+ y1="290.49384"
+ x2="436.5"
+ y2="290.5249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18105"
+ id="linearGradient24551"
+ gradientUnits="userSpaceOnUse"
+ x1="445.99902"
+ y1="288.5"
+ x2="407.3793"
+ y2="288.5" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath24168">
+ <path
+ style="fill:#808080;fill-rule:evenodd;stroke:none"
+ d="m 134.27489,222.11125 c -3.9249,-6.46418 -7.61892,6.46419 -11.54381,0 l 0,0 -1.61614,0 0,8.77283 14.77608,0 0,-8.77283 -1.61613,0 z"
+ id="path24170"
+ sodipodi:nodetypes="cccccccc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient24112"
+ gradientUnits="userSpaceOnUse"
+ x1="124.40742"
+ y1="111.98244"
+ x2="135.36497"
+ y2="120.87388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24114"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient24116"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,1)"
+ x1="302.84085"
+ y1="243.23151"
+ x2="308.82889"
+ y2="244.70323" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24118"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6879084,0,0,0.6879446,216.19282,166.82605)"
+ x1="121.7408"
+ y1="115.90587"
+ x2="130.01318"
+ y2="116.60553" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient24121"
+ gradientUnits="userSpaceOnUse"
+ x1="135.698"
+ y1="122.92034"
+ x2="129.70906"
+ y2="117.15551" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24123"
+ gradientUnits="userSpaceOnUse"
+ x1="125.81818"
+ y1="111.81818"
+ x2="143.88347"
+ y2="129.27184" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient24189"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-93.937441,254)"
+ x1="162.61801"
+ y1="4.5569806"
+ x2="180.11391"
+ y2="23.410421" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24192"
+ gradientUnits="userSpaceOnUse"
+ x1="167.43744"
+ y1="23.749996"
+ x2="175.06059"
+ y2="32.144764"
+ gradientTransform="translate(-94.937441,240)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient24209"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-93.937441,254)"
+ x1="166.86487"
+ y1="12.306217"
+ x2="173.93744"
+ y2="19" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24268"
+ gradientUnits="userSpaceOnUse"
+ x1="186.74992"
+ y1="10.795519"
+ x2="189.24992"
+ y2="9.0189686"
+ gradientTransform="matrix(1,0,0,-0.985055,75.000075,275.63418)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient24272"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2000005,0,0,1.1817719,-50.700005,86.809844)"
+ x1="258.08322"
+ y1="148.24248"
+ x2="264.99994"
+ y2="154.24899" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient24277"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2000005,0,0,1.1817719,-50.700005,86.809844)"
+ x1="258.08322"
+ y1="148.24248"
+ x2="264.99994"
+ y2="154.24899" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient21327"
+ id="linearGradient24395"
+ x1="-27.5"
+ y1="268.76776"
+ x2="-39.875"
+ y2="277.4375"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15893"
+ id="linearGradient41127"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,594,-42.40625)"
+ x1="409.45645"
+ y1="52.77837"
+ x2="402.30673"
+ y2="55.86327" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27957"
+ id="linearGradient41129"
+ gradientUnits="userSpaceOnUse"
+ x1="180.20316"
+ y1="8.0551176"
+ x2="192.75177"
+ y2="12.942369" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient41170"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.9846154,-138.98388,3.9846124)"
+ x1="266.93381"
+ y1="199.60616"
+ x2="291.45029"
+ y2="230.76723" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient41172"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.01612278,0)"
+ x1="268.21783"
+ y1="200.66605"
+ x2="284.9375"
+ y2="224.1875" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient41174"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.25,0,0,1.375,-66.483877,-73.5)"
+ cx="269.99997"
+ cy="197"
+ fx="269.99997"
+ fy="197"
+ r="2" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient41963"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(274,-63.999901)"
+ x1="113.71248"
+ y1="158.24995"
+ x2="87.522514"
+ y2="157.99994" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42069"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.9846154,-138.98388,3.9846124)"
+ x1="266.93381"
+ y1="199.60616"
+ x2="291.45029"
+ y2="230.76723" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient42091"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.25,0,0,1.375,-66.483877,-73.5)"
+ cx="269.99997"
+ cy="197"
+ fx="269.99997"
+ fy="197"
+ r="2" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient42093"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.01612278,0)"
+ x1="276.39999"
+ y1="215.3125"
+ x2="265.70886"
+ y2="196.576" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient42115"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.25,0,0,1.375,-66.483877,-73.5)"
+ cx="269.99997"
+ cy="197"
+ fx="269.99997"
+ fy="197"
+ r="2" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42121"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(60,-342)"
+ x1="206"
+ y1="535"
+ x2="212"
+ y2="549" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42155"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.9846154,-138.98388,3.9846124)"
+ x1="263"
+ y1="193.93752"
+ x2="296.25"
+ y2="239.89455" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42290"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.01612278,0)"
+ x1="265.98389"
+ y1="195"
+ x2="290.98389"
+ y2="232" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient42292"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.25,0,0,1.375,-66.483877,-73.5)"
+ cx="269.99997"
+ cy="197"
+ fx="269.99997"
+ fy="197"
+ r="2" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient40722"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9819031,0,0,0.9481466,-88.271503,-83.584533)"
+ x1="1.6577729"
+ y1="253.01927"
+ x2="-57.772419"
+ y2="253.62515" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40724"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.977157,0,0,0.9835482,0.06815071,100.43848)"
+ x1="107.84375"
+ y1="57.374996"
+ x2="116.99999"
+ y2="60.125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient40734"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,13)"
+ x1="241.17908"
+ y1="214.40446"
+ x2="279.89563"
+ y2="254.94975" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient40736"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6025789,0,0,0.668336,263.48819,85.675422)"
+ x1="49.543404"
+ y1="230.81766"
+ x2="73.932747"
+ y2="247.27646" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40738"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9120445,0,0,1,25.749745,8.9261515)"
+ x1="305.12527"
+ y1="239.03134"
+ x2="308.97327"
+ y2="242" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient40740"
+ 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
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40742"
+ 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
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient40758"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(15.997359,-17.993456)"
+ x1="199.4335"
+ y1="294.81082"
+ x2="196.00264"
+ y2="259.99347" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40760"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7501745,0,0,1.0021005,51.339144,-0.5240716)"
+ x1="207.19595"
+ y1="249.22464"
+ x2="207.81319"
+ y2="250.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40762"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7501745,0,0,1.0021005,59.339161,-0.5240716)"
+ x1="207.19595"
+ y1="249.22464"
+ x2="207.81319"
+ y2="250.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient40788"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,-7.152175,20.92167)"
+ x1="146.51619"
+ y1="217.52046"
+ x2="174.56255"
+ y2="252.52081" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient40790"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(81.000002,13.499998)"
+ x1="87.765625"
+ y1="242.39062"
+ x2="96"
+ y2="251.40294" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18056"
+ id="linearGradient40792"
+ gradientUnits="userSpaceOnUse"
+ x1="170.42908"
+ y1="237.25"
+ x2="170.71698"
+ y2="249.15927" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient40794"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,10)"
+ x1="168.5625"
+ y1="249.55817"
+ x2="168.5"
+ y2="240.10249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40545"
+ gradientUnits="userSpaceOnUse"
+ x1="279.38629"
+ y1="-16.946415"
+ x2="293.80472"
+ y2="-2.5475447" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40547"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9230687,0,0,0.9230801,261.38476,-234.15464)"
+ x1="43.921535"
+ y1="261.52924"
+ x2="29.429007"
+ y2="243.98439" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22249"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1,0)"
+ x1="387"
+ y1="410"
+ x2="388.78125"
+ y2="411.78125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22251"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1,0)"
+ x1="386.88852"
+ y1="409.84152"
+ x2="389.14081"
+ y2="412.45016" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22253"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1,0)"
+ x1="387"
+ y1="409.86362"
+ x2="388.86676"
+ y2="411.88974" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient23775"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.9230769,0,0,-0.9258123,59.615385,471.81593)"
+ x1="-0.71355486"
+ y1="209.97131"
+ x2="37.5"
+ y2="252.16492" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient23777"
+ gradientUnits="userSpaceOnUse"
+ x1="72.698921"
+ y1="599.20789"
+ x2="77.111115"
+ y2="604.11108" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient23351"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,82.8792,399.00004)"
+ x1="-7.445384"
+ y1="204.24995"
+ x2="33.682159"
+ y2="250.99995" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23353"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(80.02752,483.00004)"
+ x1="29.972469"
+ y1="164"
+ x2="36.972481"
+ y2="168.00002" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient23355"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-224,-1290)"
+ x1="113"
+ y1="646"
+ x2="111"
+ y2="644" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23357"
+ gradientUnits="userSpaceOnUse"
+ x1="113"
+ y1="646"
+ x2="111.5"
+ y2="644.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23599"
+ x1="191"
+ y1="158.72728"
+ x2="196.59441"
+ y2="167.67831"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.89375,0,0,0.89375,20.29375,17.10625)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient22692"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6363637,0.6315788,0,-191.68403,523.2955)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient22695"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6363637,0,0,-0.6315788,314.2955,837.68414)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient22698"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6363637,-0.6315788,0,628.68411,331.70458)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient22701"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6363637,0,0,0.6315788,122.70458,17.31597)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient22704"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6363637,0,0,-0.6315788,311.11368,825.05254)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient22707"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6363637,0.6315788,0,-179.05245,520.11368)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient22711"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6363637,-0.6315788,0,616.05253,334.8864)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient22715"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6363637,0,0,0.6315788,125.8864,29.94755)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23132"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6357342,-0.636363,0,628.0905,358.45254)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23134"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.636363,0,0,-0.6357342,320.09081,851.14655)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23136"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6357342,0.636363,0,-173.09051,543.4512)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23138"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.636363,0,0,0.6357342,134.90918,50.757191)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23140"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.636363,0,0,0.6357342,131.72737,31.593709)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23142"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6357342,-0.636363,0,640.81777,348.82507)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23144"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.636363,0,0,-0.6357342,131.72737,857.41243)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23147"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6357342,0.636363,0,-185.81777,540.18107)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23177"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,850,297)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23179"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,-1,366,1072)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23181"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,-409,588)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23183"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(75,-187)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23185"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(70,-207)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23187"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,870,292)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23189"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,70,1092)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23191"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,-429,593)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23231"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.8181822,0.8181823,0,-304.90941,555.63645)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23235"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8181823,0,0,-0.8181822,103.36356,963.90937)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23239"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.8181822,-0.8181823,0,757.9094,309.36361)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23244"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8181823,0,0,0.8181822,103.36356,-98.909308)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23248"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8181823,0,0,0.8181822,107.45448,-82.54566)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23251"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.8181822,0.8181823,0,-288.54575,551.54554)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23254"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.8181823,0,0,-0.8181822,345.54553,947.54573)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23257"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.8181822,-0.8181823,0,741.54576,313.45452)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23563"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.8181822,-0.8181823,0,741.54576,313.45452)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23566"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.8181823,0,0,-0.8181822,345.54553,947.54573)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23568"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.8181822,0.8181823,0,-288.54575,551.54554)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23570"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8181823,0,0,0.8181822,107.45448,-82.54566)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23572"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8181823,0,0,0.8181822,103.36356,-98.909308)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23574"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.8181822,-0.8181823,0,757.9094,309.36361)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23576"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8181823,0,0,-0.8181822,103.36356,963.90937)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23578"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.8181822,0.8181823,0,-304.90941,555.63645)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23580"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,850,297)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23582"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,-1,366,1072)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23587"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,-409,588)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23589"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(75,-187)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23591"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(70,-207)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23593"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,870,292)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23597"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,70,1092)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23600"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,-429,593)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23602"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6363637,0,0,0.6315788,125.8864,29.94755)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23606"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6363637,-0.6315788,0,616.05253,334.8864)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23608"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6363637,0.6315788,0,-179.05245,520.11368)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23610"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6363637,0,0,-0.6315788,311.11368,825.05254)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23612"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6363637,0,0,0.6315788,122.70458,17.31597)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23616"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6363637,-0.6315788,0,628.68411,331.70458)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23618"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6363637,0,0,-0.6315788,314.2955,837.68414)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23620"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6363637,0.6315788,0,-191.68403,523.2955)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23622"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6357342,-0.636363,0,628.0905,358.45254)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23624"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.636363,0,0,-0.6357342,320.09081,851.14655)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23626"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6357342,0.636363,0,-173.09051,543.4512)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20324"
+ id="linearGradient23628"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.636363,0,0,0.6357342,134.90918,50.757191)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23630"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.636363,0,0,0.6357342,131.72737,31.593709)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23632"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6357342,-0.636363,0,640.81777,348.82507)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23635"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.636363,0,0,-0.6357342,131.72737,857.41243)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37623"
+ id="linearGradient23637"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6357342,0.636363,0,-185.81777,540.18107)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23797"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.8181822,-0.8181823,0,741.54576,313.45452)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23799"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.8181823,0,0,-0.8181822,345.54553,947.54573)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23801"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.8181822,0.8181823,0,-288.54575,551.54554)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23803"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8181823,0,0,0.8181822,107.45448,-82.54566)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23805"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8181823,0,0,0.8181822,103.36356,-98.909308)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23807"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.8181822,-0.8181823,0,757.9094,309.36361)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23809"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8181823,0,0,-0.8181822,103.36356,963.90937)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23811"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.8181822,0.8181823,0,-304.90941,555.63645)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23813"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,850,297)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23815"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,-1,366,1072)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23817"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,-409,588)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23819"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(75,-187)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23821"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(70,-207)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23823"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,870,292)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23825"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,70,1092)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23827"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,-429,593)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23829"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6363637,0,0,0.6315788,125.8864,29.94755)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23831"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6363637,-0.6315788,0,616.05253,334.8864)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23833"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6363637,0.6315788,0,-179.05245,520.11368)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23835"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6363637,0,0,-0.6315788,311.11368,825.05254)"
+ x1="145.53571"
+ y1="627.08325"
+ x2="145.53571"
+ y2="623.12494" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23837"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6363637,0,0,0.6315788,122.70458,17.31597)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23839"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6363637,-0.6315788,0,628.68411,331.70458)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23841"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6363637,0,0,-0.6315788,314.2955,837.68414)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23843"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6363637,0.6315788,0,-191.68403,523.2955)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.53571"
+ y2="641.54156" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23845"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6357342,-0.636363,0,628.0905,358.45254)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23847"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.636363,0,0,-0.6357342,320.09081,851.14655)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23849"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6357342,0.636363,0,-173.09051,543.4512)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24632"
+ id="linearGradient23851"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.636363,0,0,0.6357342,134.90918,50.757191)"
+ x1="145.5"
+ y1="627.5"
+ x2="145.5"
+ y2="623.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23853"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.636363,0,0,0.6357342,131.72737,31.593709)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23856"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,0.6357342,-0.636363,0,640.81777,348.82507)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23858"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.636363,0,0,-0.6357342,131.72737,857.41243)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24642"
+ id="linearGradient23860"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.6357342,0.636363,0,-185.81777,540.18107)"
+ x1="150.5"
+ y1="647.75"
+ x2="150.5"
+ y2="642" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42685"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-52.983883,-129)"
+ x1="258"
+ y1="388"
+ x2="273"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42687"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-48.983883,-126)"
+ x1="259.75"
+ y1="388"
+ x2="273"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42689"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-54.000005,-120)"
+ x1="258.52756"
+ y1="388"
+ x2="279"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42691"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-46.000005,-117)"
+ x1="257.75"
+ y1="388"
+ x2="272"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23705"
+ id="linearGradient22892"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(220,-20.00667)"
+ x1="29.4034"
+ y1="100.99999"
+ x2="34.095703"
+ y2="101.15624" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient22917"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2,0,0,0.7333333,-467,262.53823)"
+ x1="250.5"
+ y1="90.253998"
+ x2="250.5"
+ y2="95.252274" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient22922"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4564959,0.09949388,-0.06177986,1.3917691,-283.96093,-143.81911)"
+ cx="135.14931"
+ cy="332.10181"
+ fx="135.14931"
+ fy="332.10181"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient22928"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8750002,0,0,0.83767,7.3124969,247.00379)"
+ x1="27.166666"
+ y1="90.504448"
+ x2="35.166668"
+ y2="101.14744" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient22950"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.53241"
+ cy="500.20956"
+ fx="75.53241"
+ fy="500.20956"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient22952"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6595012,0.7907318,-0.8990144,0.7498135,144.69896,-187.59854)"
+ cx="262.67139"
+ cy="74.072273"
+ fx="262.67139"
+ fy="74.072273"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24168"
+ id="linearGradient22954"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.75,0,0,0.7516675,227.625,0.9640803)"
+ x1="20.125"
+ y1="88.642494"
+ x2="34.125"
+ y2="104.89799" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient23727"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.3687636,0.09935874,-0.05957343,1.3898788,-272.60513,-143.17133)"
+ cx="140.33667"
+ cy="333.05716"
+ fx="140.33667"
+ fy="333.05716"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37925"
+ id="linearGradient23890"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(220,-20.00667)"
+ x1="29.4034"
+ y1="100.99999"
+ x2="34.095703"
+ y2="101.15624" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22562"
+ id="linearGradient23892"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.75,0,0,0.7516675,227.625,0.9640803)"
+ x1="20.125"
+ y1="88.642494"
+ x2="34.125"
+ y2="104.89799" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23906"
+ id="radialGradient23894"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0553103,1.0606182,-1.2516598,1.280294,67.321819,-297.60493)"
+ cx="262.07156"
+ cy="74.306007"
+ fx="262.07156"
+ fy="74.306007"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient23896"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8750002,0,0,0.83767,7.3124969,247.00379)"
+ x1="27.166666"
+ y1="90.504448"
+ x2="35.166668"
+ y2="101.14744" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14232"
+ id="radialGradient23898"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.53241"
+ cy="500.20956"
+ fx="75.53241"
+ fy="500.20956"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient23900"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4564959,0.09949388,-0.06177986,1.3917691,-283.96093,-143.81911)"
+ cx="135.14931"
+ cy="332.10181"
+ fx="135.14931"
+ fy="332.10181"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient23902"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2,0,0,0.7333333,-467,262.53823)"
+ x1="250.5"
+ y1="90.253998"
+ x2="250.5"
+ y2="95.252274" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient23904"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.3687636,0.09935874,-0.05957343,1.3898788,-272.60513,-143.17133)"
+ cx="140.33667"
+ cy="333.05716"
+ fx="140.33667"
+ fy="333.05716"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient42459"
+ id="linearGradient24090"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(220,-20.00667)"
+ x1="29.4034"
+ y1="100.99999"
+ x2="34.095703"
+ y2="101.15624" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22562"
+ id="linearGradient24092"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.75,0,0,0.7516675,227.625,0.9640803)"
+ x1="20.125"
+ y1="88.642494"
+ x2="34.125"
+ y2="104.89799" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient24094"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6595012,0.7907318,-0.8990144,0.7498135,144.69896,-187.59854)"
+ cx="263.21707"
+ cy="74.441246"
+ fx="263.21707"
+ fy="74.441246"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24096"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8750002,0,0,0.83767,7.3124969,247.00379)"
+ x1="27.166666"
+ y1="90.504448"
+ x2="35.166668"
+ y2="101.14744" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient24098"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.53241"
+ cy="500.20956"
+ fx="75.53241"
+ fy="500.20956"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient24100"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4564959,0.09949388,-0.06177986,1.3917691,-283.96093,-143.81911)"
+ cx="135.14931"
+ cy="332.10181"
+ fx="135.14931"
+ fy="332.10181"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient24102"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2,0,0,0.7333333,-467,262.53823)"
+ x1="250.5"
+ y1="90.253998"
+ x2="250.5"
+ y2="95.252274" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient24104"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.3687636,0.09935874,-0.05957343,1.3898788,-272.60513,-143.17133)"
+ cx="140.33667"
+ cy="333.05716"
+ fx="140.33667"
+ fy="333.05716"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24317"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.831045,0,0,0.776773,36.146465,141.05131)"
+ x1="71.762154"
+ y1="239.83469"
+ x2="76.956871"
+ y2="252.05081" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24319"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.831045,0,0,0.776773,36.165705,133.02478)"
+ x1="72.340698"
+ y1="243.03008"
+ x2="73.234337"
+ y2="246.81651" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24321"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.831045,0,0,0.776773,36.165705,133.02478)"
+ x1="66.954422"
+ y1="240.03282"
+ x2="68.458534"
+ y2="246.96069" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24362"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-335,238.99245)"
+ x1="426.12415"
+ y1="179.12074"
+ x2="425"
+ y2="179.12285" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24143"
+ id="linearGradient24367"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-149,133.99245)"
+ x1="244.37868"
+ y1="285.00754"
+ x2="237.75459"
+ y2="266.34406" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24695"
+ id="linearGradient24374"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,-30.15217,152.41412)"
+ x1="120.97597"
+ y1="281.26645"
+ x2="116.37123"
+ y2="260.21841" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient24436"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,-150.99992,596.00357)"
+ x1="199.87271"
+ y1="272.29477"
+ x2="212.22493"
+ y2="287.50357" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24727"
+ id="linearGradient24809"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,765.84783,-274.57833)"
+ x1="59.158501"
+ y1="437.02835"
+ x2="45.021851"
+ y2="349.81818" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24735"
+ id="linearGradient24811"
+ gradientUnits="userSpaceOnUse"
+ x1="807"
+ y1="101.5"
+ x2="841"
+ y2="101.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24711"
+ id="linearGradient24813"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,767.34783,-275.07833)"
+ x1="63.539974"
+ y1="421.80756"
+ x2="63.407566"
+ y2="347.78201" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient24815"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-127,4e-6)"
+ x1="954"
+ y1="102"
+ x2="936"
+ y2="114.99999" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24727"
+ id="linearGradient24839"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,765.84783,-274.57833)"
+ x1="59.158501"
+ y1="437.02835"
+ x2="45.021851"
+ y2="349.81818" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24735"
+ id="linearGradient24841"
+ gradientUnits="userSpaceOnUse"
+ x1="807"
+ y1="101.5"
+ x2="841"
+ y2="101.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24144"
+ id="linearGradient24843"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,767.34783,-275.07833)"
+ x1="64.019142"
+ y1="419.06366"
+ x2="63.407566"
+ y2="347.78201" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient24845"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-127,4e-6)"
+ x1="954"
+ y1="102"
+ x2="936"
+ y2="114.99999" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24727"
+ id="linearGradient24867"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,765.84783,-274.57833)"
+ x1="59.158501"
+ y1="437.02835"
+ x2="45.021851"
+ y2="349.81818" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24735"
+ id="linearGradient24869"
+ gradientUnits="userSpaceOnUse"
+ x1="807"
+ y1="101.5"
+ x2="841"
+ y2="101.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24711"
+ id="linearGradient24871"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,767.34783,-275.07833)"
+ x1="63.659767"
+ y1="422.46088"
+ x2="63.407566"
+ y2="347.78201" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient24873"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-127,4e-6)"
+ x1="954"
+ y1="102"
+ x2="936"
+ y2="114.99999" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24679"
+ id="linearGradient25073"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,-30.15217,152.41412)"
+ x1="121.79003"
+ y1="283.00519"
+ x2="114.66669"
+ y2="250.69945" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24671"
+ id="linearGradient25075"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-149,133.99245)"
+ x1="243.25"
+ y1="283.94504"
+ x2="235"
+ y2="253.00755" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient25077"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-335,238.99245)"
+ x1="426.12415"
+ y1="179.12074"
+ x2="425"
+ y2="179.12285" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24679"
+ id="linearGradient42055"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,-30.15217,152.41412)"
+ x1="120.94298"
+ y1="281.27435"
+ x2="114.66669"
+ y2="250.69945" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24671"
+ id="linearGradient42057"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-149,133.99245)"
+ x1="243.25"
+ y1="283.94504"
+ x2="235"
+ y2="253.00755" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42059"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-335,238.99245)"
+ x1="426.12415"
+ y1="179.12074"
+ x2="425"
+ y2="179.12285" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24101"
+ id="linearGradient24132"
+ gradientUnits="userSpaceOnUse"
+ x1="445.77841"
+ y1="113.24564"
+ x2="426.11459"
+ y2="84.777061" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient24599"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1489145,-0.69297,0.4772363,0.7912359,-113.08929,303.20064)"
+ cx="269.71231"
+ cy="237.2262"
+ fx="269.71231"
+ fy="237.2262"
+ r="7.03125" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient24632"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7236207,-0.7167103,1.004637,1.0143218,-131.254,253.93955)"
+ cx="262.83905"
+ cy="245.91792"
+ fx="262.83905"
+ fy="245.91792"
+ r="7.03125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31456"
+ id="linearGradient24797"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9897912,0,0,0.9897912,2.2765631,2.9503441)"
+ x1="311.3967"
+ y1="310.77368"
+ x2="309.02371"
+ y2="308.51169" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24820"
+ x1="311.37668"
+ y1="311.88205"
+ x2="307.5"
+ y2="308.21875"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20036"
+ id="radialGradient43962"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4011721,0.3766097,-0.7099042,0.7562044,179.21454,-58.566632)"
+ cx="207.04807"
+ cy="78.473343"
+ fx="207.04807"
+ fy="78.473343"
+ r="3.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20036"
+ id="radialGradient43964"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4543499,0.4687811,-0.6244606,0.6052369,161.562,-65.729731)"
+ cx="206.39249"
+ cy="78.443413"
+ fx="206.39249"
+ fy="78.443413"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient62436"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1,0)"
+ x1="248.69196"
+ y1="279.72827"
+ x2="269.3085"
+ y2="303.10999" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient62558"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,1,0,-33.03632,32.03632)"
+ x1="289.61554"
+ y1="320.55179"
+ x2="250.22783"
+ y2="282.28745" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient62560"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,59,638)"
+ x1="354.50601"
+ y1="283.61511"
+ x2="327.92044"
+ y2="300.96124" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25381"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1,21)"
+ x1="342"
+ y1="288.5"
+ x2="344.5"
+ y2="288.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25383"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,638,-40)"
+ x1="342"
+ y1="288.5"
+ x2="344.5"
+ y2="288.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25385"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,-1,699,599)"
+ x1="342"
+ y1="288.5"
+ x2="344.5"
+ y2="288.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25387"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,60,660)"
+ x1="342"
+ y1="288.5"
+ x2="344.5"
+ y2="288.5" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask25369">
+ <g
+ id="g25371"
+ transform="translate(-21,-21)">
+ <path
+ style="fill:url(#linearGradient25381);fill-rule:evenodd;stroke:none"
+ d="m 341,302 8,8 -8,8 0,-16 z"
+ id="path25373"
+ sodipodi:nodetypes="cccc"
+ inkscape:transform-center-x="4"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:transform-center-y="-4"
+ sodipodi:nodetypes="cccc"
+ id="path25375"
+ d="m 357,302 -8,8 -8,-8 16,0 z"
+ style="fill:url(#linearGradient25383);fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:transform-center-x="-4"
+ sodipodi:nodetypes="cccc"
+ id="path25377"
+ d="m 357,318 -8,-8 8,-8 0,16 z"
+ style="fill:url(#linearGradient25385);fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:transform-center-y="4"
+ sodipodi:nodetypes="cccc"
+ id="path25379"
+ d="m 341,318 8,-8 8,8 -16,0 z"
+ style="fill:url(#linearGradient25387);fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ </g>
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25573"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1,21)"
+ x1="342"
+ y1="288.5"
+ x2="344.01321"
+ y2="288.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25575"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,638,-40)"
+ x1="342"
+ y1="288.5"
+ x2="344.5"
+ y2="288.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25577"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,-1,699,599)"
+ x1="342"
+ y1="288.5"
+ x2="344.5"
+ y2="288.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25579"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,60,660)"
+ x1="342"
+ y1="288.5"
+ x2="344.5"
+ y2="288.5" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask25561">
+ <g
+ transform="translate(-21,-21)"
+ id="g25563">
+ <path
+ inkscape:transform-center-x="4"
+ sodipodi:nodetypes="cccc"
+ id="path25565"
+ d="m 341,302 8,8 -8,8 0,-16 z"
+ style="fill:url(#linearGradient25573);fill-rule:evenodd;stroke:none"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient25575);fill-rule:evenodd;stroke:none"
+ d="m 357,302 -8,8 -8,-8 16,0 z"
+ id="path25567"
+ sodipodi:nodetypes="cccc"
+ inkscape:transform-center-y="-4"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient25577);fill-rule:evenodd;stroke:none"
+ d="m 357,318 -8,-8 8,-8 0,16 z"
+ id="path25569"
+ sodipodi:nodetypes="cccc"
+ inkscape:transform-center-x="-4"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient25579);fill-rule:evenodd;stroke:none"
+ d="m 341,318 8,-8 8,8 -16,0 z"
+ id="path25571"
+ sodipodi:nodetypes="cccc"
+ inkscape:transform-center-y="4"
+ inkscape:connector-curvature="0" />
+ </g>
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25872"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,513.5,328.50451)"
+ x1="253.78497"
+ y1="3.6831069"
+ x2="278.25537"
+ y2="30.023426" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334"
+ id="linearGradient25874"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(670,111)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25886"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,673.5,170.50451)"
+ x1="243.92192"
+ y1="-2.6686089"
+ x2="275.10107"
+ y2="26.600887" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334"
+ id="linearGradient25888"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(830,-47)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13998"
+ id="linearGradient25890"
+ gradientUnits="userSpaceOnUse"
+ x1="13.5"
+ y1="57.827747"
+ x2="11.472005"
+ y2="53.875874" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13998"
+ id="linearGradient25892"
+ gradientUnits="userSpaceOnUse"
+ x1="-18.600719"
+ y1="501.96539"
+ x2="-26.642899"
+ y2="487.60382" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient25894"
+ gradientUnits="userSpaceOnUse"
+ x1="15.027407"
+ y1="60.637787"
+ x2="13.5"
+ y2="57.750687" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient25897"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.03018343,0.1408617)"
+ x1="-32.067383"
+ y1="490.70178"
+ x2="-22.25"
+ y2="500" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient25899"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-72.000001)"
+ x1="753.39417"
+ y1="299.83005"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24679"
+ id="linearGradient25927"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,-30.15217,152.41412)"
+ x1="121.79003"
+ y1="283.00519"
+ x2="114.66669"
+ y2="250.69945" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24671"
+ id="linearGradient25929"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-149,133.99245)"
+ x1="243.25"
+ y1="283.94504"
+ x2="235"
+ y2="253.00755" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient25931"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-335,238.99245)"
+ x1="426.12415"
+ y1="179.12074"
+ x2="425"
+ y2="179.12285" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25957"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,673.5,170.50451)"
+ x1="253.78497"
+ y1="3.6831069"
+ x2="278.25537"
+ y2="30.023426" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334"
+ id="linearGradient25959"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(830,-47)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient25961"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-136,-112)"
+ x1="753.39417"
+ y1="299.83005"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient25982"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,673.5,170.50451)"
+ x1="253.78497"
+ y1="3.6831069"
+ x2="278.25537"
+ y2="30.023426" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334"
+ id="linearGradient25984"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(830,-47)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient25986"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-136,-88.000005)"
+ x1="753.39417"
+ y1="299.83005"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient26011"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,673.5,170.50451)"
+ x1="253.78497"
+ y1="3.6831069"
+ x2="278.25537"
+ y2="30.023426" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334"
+ id="linearGradient26013"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(830,-47)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient26015"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-112,-76.000004)"
+ x1="753.39417"
+ y1="299.83005"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient26077"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,82.8792,399.00004)"
+ x1="-7.445384"
+ y1="204.24995"
+ x2="33.682159"
+ y2="250.99995" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient26079"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(80.02752,483.00004)"
+ x1="29.972469"
+ y1="164"
+ x2="36.972481"
+ y2="168.00002" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient26081"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-224,-1290)"
+ x1="113"
+ y1="646"
+ x2="111"
+ y2="644" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient26083"
+ gradientUnits="userSpaceOnUse"
+ x1="113"
+ y1="646"
+ x2="111.5"
+ y2="644.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient26126"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.831045,0,0,0.776773,36.146465,141.05131)"
+ x1="71.762154"
+ y1="239.83469"
+ x2="76.956871"
+ y2="252.05081" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient26128"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.831045,0,0,0.776773,36.165705,133.02478)"
+ x1="72.340698"
+ y1="243.03008"
+ x2="73.234337"
+ y2="246.81651" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient26130"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.831045,0,0,0.776773,36.165705,133.02478)"
+ x1="68.383354"
+ y1="239.95235"
+ x2="69.285805"
+ y2="247.29691" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient27973"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.39459,-0.991726,0.917787,0.36517,234.80511,750.0215)"
+ cx="450.06522"
+ cy="25.190212"
+ fx="450.06522"
+ fy="25.190212"
+ r="5.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient27975"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.121304,-0.696283,0.871429,0.151818,359.51331,621.7)"
+ cx="450.72842"
+ cy="19.250505"
+ fx="450.72842"
+ fy="19.250505"
+ r="5.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27977"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,883.51417,295)"
+ x1="456.81198"
+ y1="15.545153"
+ x2="441.9628"
+ y2="13.21724" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient28099"
+ gradientUnits="userSpaceOnUse"
+ x1="62.793919"
+ y1="133.73566"
+ x2="64.109718"
+ y2="135.18265" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient28107"
+ gradientUnits="userSpaceOnUse"
+ x1="461.66425"
+ y1="16.23234"
+ x2="432.875"
+ y2="14.936845"
+ gradientTransform="translate(-19,294.91429)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient27448"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-19,294.91429)"
+ x1="461.66425"
+ y1="16.23234"
+ x2="432.875"
+ y2="14.936845" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27450"
+ gradientUnits="userSpaceOnUse"
+ x1="62.793919"
+ y1="133.73566"
+ x2="64.109718"
+ y2="135.18265" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient27452"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.39459,-0.991726,0.917787,0.36517,234.80511,750.0215)"
+ cx="450.06522"
+ cy="25.190212"
+ fx="450.06522"
+ fy="25.190212"
+ r="5.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient27454"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.121304,-0.696283,0.871429,0.151818,359.51331,621.7)"
+ cx="450.72842"
+ cy="19.250505"
+ fx="450.72842"
+ fy="19.250505"
+ r="5.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27456"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,883.51417,295)"
+ x1="456.81198"
+ y1="15.545153"
+ x2="441.9628"
+ y2="13.21724" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27540"
+ gradientUnits="userSpaceOnUse"
+ x1="332.49747"
+ y1="38.166924"
+ x2="326.41843"
+ y2="31.22842" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27542"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(2.011921e-5,12.000013)"
+ x1="326.483"
+ y1="31.446384"
+ x2="337.3125"
+ y2="41.875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27544"
+ gradientUnits="userSpaceOnUse"
+ x1="329.18762"
+ y1="34.005215"
+ x2="331.44778"
+ y2="36.739578" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23705"
+ id="linearGradient27598"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(220,-20.00667)"
+ x1="29.4034"
+ y1="100.99999"
+ x2="34.095703"
+ y2="101.15624" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24168"
+ id="linearGradient27600"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.75,0,0,0.7516675,227.625,0.9640803)"
+ x1="20.125"
+ y1="88.642494"
+ x2="34.125"
+ y2="104.89799" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient27602"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6595012,0.7907318,-0.8990144,0.7498135,144.69896,-187.59854)"
+ cx="261.98364"
+ cy="74.083908"
+ fx="261.98364"
+ fy="74.083908"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27604"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8750002,0,0,0.83767,7.3124969,247.00379)"
+ x1="27.166666"
+ y1="90.504448"
+ x2="35.166668"
+ y2="101.14744" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient27606"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.53241"
+ cy="500.20956"
+ fx="75.53241"
+ fy="500.20956"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient27608"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4564959,0.09949388,-0.06177986,1.3917691,-283.96093,-143.81911)"
+ cx="135.14931"
+ cy="332.10181"
+ fx="135.14931"
+ fy="332.10181"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient27610"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2,0,0,0.7333333,-467,262.53823)"
+ x1="250.5"
+ y1="90.253998"
+ x2="250.5"
+ y2="95.252274" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient27612"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.3687636,0.09935874,-0.05957343,1.3898788,-272.60513,-143.17133)"
+ cx="140.33667"
+ cy="333.05716"
+ fx="140.33667"
+ fy="333.05716"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient34157"
+ id="linearGradient30389"
+ gradientUnits="userSpaceOnUse"
+ x1="270.60007"
+ y1="68.519989"
+ x2="258.00165"
+ y2="81.245804" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient30391"
+ gradientUnits="userSpaceOnUse"
+ x1="256.67459"
+ y1="80.395966"
+ x2="262.88068"
+ y2="74.415245" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient30393"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4829018,0,0,0.4829018,133.47136,40.782399)"
+ cx="257.35309"
+ cy="79.598709"
+ fx="257.35309"
+ fy="79.598709"
+ r="3.779551" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient30395"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient30397"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient29127"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(422.99996,88.99998)"
+ x1="308"
+ y1="323"
+ x2="343.26239"
+ y2="340" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient29129"
+ gradientUnits="userSpaceOnUse"
+ x1="732.9375"
+ y1="412.8125"
+ x2="753.40625"
+ y2="418.33594" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27767"
+ gradientUnits="userSpaceOnUse"
+ x1="125.99933"
+ y1="111.2683"
+ x2="134.91479"
+ y2="122.36016" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27769"
+ gradientUnits="userSpaceOnUse"
+ x1="126.72586"
+ y1="112.53999"
+ x2="134.91479"
+ y2="122.36016" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13973"
+ id="linearGradient27771"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(19.367382,0)"
+ x1="112.18942"
+ y1="114.71685"
+ x2="99.628899"
+ y2="99.029617" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient27773"
+ gradientUnits="userSpaceOnUse"
+ x1="127.63637"
+ y1="114.2303"
+ x2="143.69765"
+ y2="131.03783" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="radialGradient31865"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.986122,0,0,0.986122,2.8033684,0.804927)"
+ cx="202"
+ cy="58"
+ fx="202"
+ fy="58"
+ r="7" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask31861">
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#radialGradient31865);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path31863"
+ sodipodi:cx="202"
+ sodipodi:cy="58"
+ sodipodi:rx="11"
+ sodipodi:ry="11"
+ d="m 213,58 a 11,11 0 1 1 -22,0 11,11 0 1 1 22,0 z" />
+ </mask>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath31849">
+ <path
+ style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 232.13187,93.950853 4.84276,0 4.23742,4.237465 0,4.842822 -9.08018,0 0,-9.080287 0,0 z"
+ id="path31851"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient32298"
+ gradientUnits="userSpaceOnUse"
+ x1="-117.5"
+ y1="431.5"
+ x2="-119.5"
+ y2="429.5"
+ gradientTransform="translate(258,-96.99999)" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask32294">
+ <rect
+ y="323"
+ x="134"
+ height="16"
+ width="9"
+ id="rect32296"
+ style="fill:url(#linearGradient32298);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </mask>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient32241"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.050372,0,0,1.050372,-3.551238,-0.730396)"
+ cx="70.5"
+ cy="14.5"
+ fx="70.5"
+ fy="14.5"
+ r="1.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient32243"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5399935,0.3131662,-0.3907892,0.5793905,38.141764,-16.056748)"
+ cx="70.470596"
+ cy="14.649424"
+ fx="70.470596"
+ fy="14.649424"
+ r="5.5192375" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient53119"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.684011,0.3442329,-1.2972142,1.1562236,739.67527,-1155.7895)"
+ cx="975.50568"
+ cy="690.68732"
+ fx="975.50568"
+ fy="690.68732"
+ r="2.333364" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient53121"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.821004,429.95027,-161.55482)"
+ x1="108.71671"
+ y1="171.25618"
+ x2="105.85706"
+ y2="168.04703" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20756"
+ id="linearGradient53123"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.8956408,540.31118,-183.20693)"
+ x1="-26.313976"
+ y1="178.07901"
+ x2="-28.432825"
+ y2="175.87964" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient53125"
+ gradientUnits="userSpaceOnUse"
+ x1="510.29913"
+ y1="-20.435461"
+ x2="505.9494"
+ y2="-17.546936" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient53127"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,-346.7085,428.4841)"
+ x1="352.98236"
+ y1="314.11398"
+ x2="353.72073"
+ y2="297.92099" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13938"
+ id="linearGradient53129"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-15.983875,338)"
+ x1="362.79037"
+ y1="-159.88834"
+ x2="373.83752"
+ y2="-150.41035" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient53131"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9900316,0,0,1,2.450297,0.00704954)"
+ x1="343.51892"
+ y1="175.19124"
+ x2="350.97491"
+ y2="183.3365" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient53133"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.684011,0.3442329,-1.2972142,1.1562236,739.67527,-1155.7895)"
+ cx="975.50568"
+ cy="690.68732"
+ fx="975.50568"
+ fy="690.68732"
+ r="2.333364" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient53135"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.821004,429.95027,-161.55482)"
+ x1="108.71671"
+ y1="171.25618"
+ x2="105.85706"
+ y2="168.04703" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20756"
+ id="linearGradient53137"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.8956408,540.31118,-183.20693)"
+ x1="-26.313976"
+ y1="178.07901"
+ x2="-28.432825"
+ y2="175.87964" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient53139"
+ gradientUnits="userSpaceOnUse"
+ x1="510.29913"
+ y1="-20.435461"
+ x2="505.9494"
+ y2="-17.546936" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient53141"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.684011,0.3442329,-1.2972142,1.1562236,739.67527,-1155.7895)"
+ cx="975.50568"
+ cy="690.68732"
+ fx="975.50568"
+ fy="690.68732"
+ r="2.333364" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient53143"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.821004,429.95027,-161.55482)"
+ x1="108.71671"
+ y1="171.25618"
+ x2="105.85706"
+ y2="168.04703" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20756"
+ id="linearGradient53145"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.8956408,540.31118,-183.20693)"
+ x1="-26.313976"
+ y1="178.07901"
+ x2="-28.432825"
+ y2="175.87964" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient53147"
+ gradientUnits="userSpaceOnUse"
+ x1="510.29913"
+ y1="-20.435461"
+ x2="505.9494"
+ y2="-17.546936" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient42459"
+ id="linearGradient53149"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(220,-20.00667)"
+ x1="29.4034"
+ y1="100.99999"
+ x2="34.095703"
+ y2="101.15624" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22562"
+ id="linearGradient53151"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.75,0,0,0.7516675,227.625,0.9640803)"
+ x1="20.125"
+ y1="88.642494"
+ x2="34.125"
+ y2="104.89799" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient53153"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6595012,0.7907318,-0.8990144,0.7498135,144.69896,-187.59854)"
+ cx="261.98364"
+ cy="74.083908"
+ fx="261.98364"
+ fy="74.083908"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient53155"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.75,0,0,0.7516675,115.625,254.97076)"
+ x1="27.166666"
+ y1="90.504448"
+ x2="35.166668"
+ y2="101.14744" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient53157"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.53241"
+ cy="500.20956"
+ fx="75.53241"
+ fy="500.20956"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient53159"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.1055676,0.08927896,-0.05295416,1.2488779,-134.03789,-95.726825)"
+ cx="135.14931"
+ cy="332.10181"
+ fx="135.14931"
+ fy="332.10181"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient53161"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-112,237.00668)"
+ x1="250.5"
+ y1="90.253998"
+ x2="250.5"
+ y2="95.252274" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient53163"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.1055676,0.08927896,-0.05295416,1.2488779,-134.03789,-95.726825)"
+ cx="140.33667"
+ cy="333.05716"
+ fx="140.33667"
+ fy="333.05716"
+ r="3.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient53165"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.684011,0.3442329,-1.2972142,1.1562236,739.67527,-1155.7895)"
+ cx="975.50568"
+ cy="690.68732"
+ fx="975.50568"
+ fy="690.68732"
+ r="2.333364" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient53167"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.821004,429.95027,-161.55482)"
+ x1="108.71671"
+ y1="171.25618"
+ x2="105.85706"
+ y2="168.04703" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20756"
+ id="linearGradient53169"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.8956408,540.31118,-183.20693)"
+ x1="-26.313976"
+ y1="178.07901"
+ x2="-28.432825"
+ y2="175.87964" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient53171"
+ gradientUnits="userSpaceOnUse"
+ x1="510.29913"
+ y1="-20.435461"
+ x2="505.9494"
+ y2="-17.546936" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23178"
+ id="linearGradient50870"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(2e-6,0)"
+ x1="-22.902081"
+ y1="448"
+ x2="-14.000002"
+ y2="448" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient33427"
+ gradientUnits="userSpaceOnUse"
+ x1="124.40742"
+ y1="111.98244"
+ x2="136.04924"
+ y2="121.25749" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient33429"
+ gradientUnits="userSpaceOnUse"
+ x1="132"
+ y1="117.26753"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient33585"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7071068,-0.7071068,0.7071067,0.7071067,-140.04288,401.30258)"
+ x1="458.99997"
+ y1="89.363937"
+ x2="452.63602"
+ y2="90.071045" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient31356"
+ id="linearGradient33831"
+ gradientUnits="userSpaceOnUse"
+ x1="134.00002"
+ y1="116"
+ x2="142.00002"
+ y2="108" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient33833"
+ gradientUnits="userSpaceOnUse"
+ x1="124.75568"
+ y1="112.24533"
+ x2="132.97911"
+ y2="120.16792" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient33835"
+ gradientUnits="userSpaceOnUse"
+ x1="132"
+ y1="117.26753"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient37472"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,-32.5,115.5045)"
+ x1="254.19829"
+ y1="2.1803131"
+ x2="277.86761"
+ y2="29.392145" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37475"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(124,-102.00001)"
+ x1="85.1875"
+ y1="239.125"
+ x2="92.8125"
+ y2="245.625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient37477"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,-32.5,115.5045)"
+ x1="261.83936"
+ y1="11.593864"
+ x2="275.62497"
+ y2="26.679274" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37479"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(124,-102.00001)"
+ x1="85.1875"
+ y1="239.125"
+ x2="92.8125"
+ y2="245.625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient34157"
+ id="linearGradient37481"
+ gradientUnits="userSpaceOnUse"
+ x1="270.60007"
+ y1="68.519989"
+ x2="258.00165"
+ y2="81.245804" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37483"
+ gradientUnits="userSpaceOnUse"
+ x1="256.67459"
+ y1="80.395966"
+ x2="262.88068"
+ y2="74.415245" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient37485"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4829018,0,0,0.4829018,133.47136,40.782399)"
+ cx="257.35309"
+ cy="79.598709"
+ fx="257.35309"
+ fy="79.598709"
+ r="3.779551" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient37487"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient37489"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient37491"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.5793179,0,-1.0159927e-7,-1.6412688,666.67947,207.37331)"
+ cx="258.47122"
+ cy="78.512764"
+ fx="258.47122"
+ fy="78.512764"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient34157"
+ id="linearGradient37493"
+ gradientUnits="userSpaceOnUse"
+ x1="270.66064"
+ y1="68.113258"
+ x2="257.38638"
+ y2="81.382545" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37495"
+ gradientUnits="userSpaceOnUse"
+ x1="256.38586"
+ y1="80.515495"
+ x2="262.43726"
+ y2="74.562462" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient37497"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient37499"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient37501"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.08933014,-0.7764284,0.7350832,-0.08334857,57.410559,233.30156)"
+ cx="135.83771"
+ cy="117.97826"
+ fx="135.83771"
+ fy="117.97826"
+ r="8" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37503"
+ gradientUnits="userSpaceOnUse"
+ x1="121.19734"
+ y1="105.94044"
+ x2="148.06364"
+ y2="137.6748" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient34157"
+ id="linearGradient37505"
+ gradientUnits="userSpaceOnUse"
+ x1="270.66064"
+ y1="68.113258"
+ x2="257.38638"
+ y2="81.382545" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37507"
+ gradientUnits="userSpaceOnUse"
+ x1="256.38586"
+ y1="80.515495"
+ x2="262.43726"
+ y2="74.562462" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient37509"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient37511"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient37513"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.3336259,0,-8.5793649e-8,-1.3859393,603.17514,187.32668)"
+ cx="258.47122"
+ cy="78.512764"
+ fx="258.47122"
+ fy="78.512764"
+ r="3.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient37515"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.3648614,0,-8.7803051e-8,-1.4184,611.24862,189.87526)"
+ cx="258.47122"
+ cy="78.512764"
+ fx="258.47122"
+ fy="78.512764"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient34157"
+ id="linearGradient37517"
+ gradientUnits="userSpaceOnUse"
+ x1="270.66064"
+ y1="68.113258"
+ x2="257.38638"
+ y2="81.382545" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37519"
+ gradientUnits="userSpaceOnUse"
+ x1="256.38586"
+ y1="80.515495"
+ x2="262.43726"
+ y2="74.562462" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient37521"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient37523"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30124"
+ id="linearGradient37525"
+ gradientUnits="userSpaceOnUse"
+ x1="337.34329"
+ y1="43.328976"
+ x2="330.27045"
+ y2="35.276588" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37527"
+ gradientUnits="userSpaceOnUse"
+ x1="329.9158"
+ y1="35.5"
+ x2="335.27429"
+ y2="41.570362" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37529"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0028571,0,0,0.9943503,-0.4404318,0.129119)"
+ x1="166.89752"
+ y1="9.0567484"
+ x2="193.26451"
+ y2="38.642647" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37531"
+ gradientUnits="userSpaceOnUse"
+ x1="127.93343"
+ y1="122.8346"
+ x2="133.77768"
+ y2="116.99384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37533"
+ gradientUnits="userSpaceOnUse"
+ x1="141.60255"
+ y1="108.39205"
+ x2="132"
+ y2="118.66972" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37535"
+ gradientUnits="userSpaceOnUse"
+ x1="122.86111"
+ y1="127.14286"
+ x2="133.77768"
+ y2="116.99384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37537"
+ gradientUnits="userSpaceOnUse"
+ x1="141.60255"
+ y1="108.39205"
+ x2="132"
+ y2="118.66972" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37539"
+ gradientUnits="userSpaceOnUse"
+ x1="266"
+ y1="659"
+ x2="285"
+ y2="659" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35391"
+ id="linearGradient37541"
+ gradientUnits="userSpaceOnUse"
+ x1="244.21062"
+ y1="600.74884"
+ x2="244.21062"
+ y2="602.96759" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35407"
+ id="linearGradient37543"
+ gradientUnits="userSpaceOnUse"
+ x1="235.29379"
+ y1="588.43396"
+ x2="245.93307"
+ y2="604.52502" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37545"
+ gradientUnits="userSpaceOnUse"
+ x1="510.25"
+ y1="36"
+ x2="494"
+ y2="36"
+ gradientTransform="matrix(-1,0,0,1,992,0)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37547"
+ gradientUnits="userSpaceOnUse"
+ x1="492"
+ y1="33"
+ x2="503"
+ y2="43"
+ gradientTransform="matrix(-1,0,0,1,992,0)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37549"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,551,105)"
+ x1="497.3125"
+ y1="35"
+ x2="483"
+ y2="35" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37551"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,551,105)"
+ x1="497.3125"
+ y1="35"
+ x2="483"
+ y2="35" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37553"
+ gradientUnits="userSpaceOnUse"
+ x1="86.248604"
+ y1="32"
+ x2="68"
+ y2="12" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37555"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,1)"
+ x1="81"
+ y1="27"
+ x2="64.5"
+ y2="9.0000019" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient37557"
+ gradientUnits="userSpaceOnUse"
+ x1="70.78582"
+ y1="15.659542"
+ x2="79.465332"
+ y2="24.480759" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="radialGradient37559"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5997527,0.4726093,-0.6665451,0.8458611,35.480681,-28.765852)"
+ cx="63.013588"
+ cy="14.60904"
+ fx="63.013588"
+ fy="14.60904"
+ r="6.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37571"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8666667,0,0,0.9166667,406.13333,-443.79167)"
+ x1="108"
+ y1="500"
+ x2="54.8125"
+ y2="500" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15809"
+ id="linearGradient37573"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.9971589,396,-484.56523)"
+ x1="83.261826"
+ y1="502.54196"
+ x2="41.311054"
+ y2="501.10059" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262"
+ id="radialGradient37575"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3949409,0.3949425,-0.4243709,0.4254619,321.60762,256.85923)"
+ cx="75.95578"
+ cy="492.15359"
+ fx="75.95578"
+ fy="492.15359"
+ r="3.1650217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37578"
+ gradientUnits="userSpaceOnUse"
+ x1="80.768944"
+ y1="504.67188"
+ x2="76.885078"
+ y2="501.58331" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37580"
+ gradientUnits="userSpaceOnUse"
+ x1="89.526657"
+ y1="511.42972"
+ x2="78.000008"
+ y2="501.04794" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient37582"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.2665671,0.04035316,-0.03648524,1.99062,-82.893589,-502.25433)"
+ cx="79.959885"
+ cy="503.81497"
+ fx="79.959885"
+ fy="503.81497"
+ r="2.9089756" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient37584"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient37586"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37588"
+ gradientUnits="userSpaceOnUse"
+ x1="264.10001"
+ y1="330.10001"
+ x2="264.89999"
+ y2="330.89999" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14232"
+ id="linearGradient37590"
+ gradientUnits="userSpaceOnUse"
+ x1="122.38876"
+ y1="108.82882"
+ x2="133.88583"
+ y2="121.20407" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient37592"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9995363,0,0,-1.0036971,220.01067,167.35026)"
+ x1="51.37524"
+ y1="96.955269"
+ x2="44.999863"
+ y2="103.57072" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15437"
+ id="linearGradient37594"
+ gradientUnits="userSpaceOnUse"
+ x1="137.88235"
+ y1="124.67203"
+ x2="131.3092"
+ y2="117.24104" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37596"
+ gradientUnits="userSpaceOnUse"
+ x1="126.37032"
+ y1="110.87843"
+ x2="139.86742"
+ y2="126.57021" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient37608"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.684011,0.3442329,-1.2972142,1.1562236,739.67527,-1155.7895)"
+ cx="975.50568"
+ cy="690.68732"
+ fx="975.50568"
+ fy="690.68732"
+ r="2.333364" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient37610"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.821004,429.95027,-161.55482)"
+ x1="108.71671"
+ y1="171.25618"
+ x2="105.85706"
+ y2="168.04703" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20756"
+ id="linearGradient37612"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8008385,0,0,0.8956408,540.31118,-183.20693)"
+ x1="-26.313976"
+ y1="178.07901"
+ x2="-28.432825"
+ y2="175.87964" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37614"
+ gradientUnits="userSpaceOnUse"
+ x1="510.29913"
+ y1="-20.435461"
+ x2="505.9494"
+ y2="-17.546936" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient37636"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,-241.7085,428.4841)"
+ x1="387.30396"
+ y1="126.23978"
+ x2="332.88193"
+ y2="123.61623" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient37638"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,-346.7085,428.4841)"
+ x1="352.98236"
+ y1="314.11398"
+ x2="353.72073"
+ y2="297.92099" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37640"
+ gradientUnits="userSpaceOnUse"
+ x1="121.19734"
+ y1="105.94044"
+ x2="148.06364"
+ y2="137.6748" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient42322"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9995967,0,0,1.0002103,-78.949724,-0.02739749)"
+ x1="109.04134"
+ y1="75.666725"
+ x2="135.45256"
+ y2="103.11092" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42324"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1000194,0,0,1.0998287,-4.6508478,-9.2334126)"
+ x1="47.655102"
+ y1="93.805557"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient42326"
+ gradientUnits="userSpaceOnUse"
+ x1="124.8772"
+ y1="110.75571"
+ x2="133.97179"
+ y2="117.77643" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient42328"
+ gradientUnits="userSpaceOnUse"
+ x1="129.32576"
+ y1="223.61363"
+ x2="123.33967"
+ y2="217.06438" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42330"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="142.64723"
+ y2="129.05313" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient42332"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.0041772,0,0,0.9688607,-81.584854,117.13687)"
+ x1="-4.9152389"
+ y1="252.69086"
+ x2="-45.689278"
+ y2="252.63284" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42334"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9993234,0,0,1.0050357,-171.92846,305.72314)"
+ x1="107.96875"
+ y1="53.875"
+ x2="117"
+ y2="60.125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42336"
+ gradientUnits="userSpaceOnUse"
+ x1="154.24324"
+ y1="-11.628862"
+ x2="134.08138"
+ y2="-22.846634" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42338"
+ gradientUnits="userSpaceOnUse"
+ x1="137.5"
+ y1="-18"
+ x2="135.25"
+ y2="-21" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42340"
+ gradientUnits="userSpaceOnUse"
+ x1="134.12642"
+ y1="-21.522242"
+ x2="132.29695"
+ y2="-23.945318" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42342"
+ gradientUnits="userSpaceOnUse"
+ x1="134.6615"
+ y1="-21.3074"
+ x2="131.69801"
+ y2="-24.343456" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient42344"
+ gradientUnits="userSpaceOnUse"
+ x1="-69.457596"
+ y1="31.914484"
+ x2="-76.564636"
+ y2="28.695114" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42346"
+ gradientUnits="userSpaceOnUse"
+ x1="-57.780041"
+ y1="48.005856"
+ x2="-78.812721"
+ y2="31" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient42348"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9995967,0,0,1.0002103,-78.949724,-0.02739749)"
+ x1="109.04134"
+ y1="75.666725"
+ x2="135.45256"
+ y2="103.11092" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42350"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3000195,0,0,0.2998291,32.548709,64.760571)"
+ x1="51.497997"
+ y1="97.491707"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42352"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3000195,0,0,0.1998289,32.548709,79.011866)"
+ x1="51.497997"
+ y1="94.987144"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42354"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3000195,0,0,0.1998289,32.548709,83.013491)"
+ x1="51.497997"
+ y1="94.987129"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42356"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2,0,0,0.1998289,42.197983,83.013493)"
+ x1="48.998543"
+ y1="94.987114"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42358"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2,0,0,0.1998289,42.197981,79.010163)"
+ x1="48.99855"
+ y1="94.995667"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42360"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2,0,0,0.2999998,42.19798,64.743076)"
+ x1="48.998554"
+ y1="97.494553"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42362"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2,0,0,0.1998289,46.196563,83.013493)"
+ x1="48.998539"
+ y1="94.987114"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42364"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2,0,0,0.1998289,46.196561,79.010163)"
+ x1="48.998547"
+ y1="94.995667"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42366"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2,0,0,0.2999998,46.19656,64.743076)"
+ x1="48.998554"
+ y1="97.494553"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient42368"
+ gradientUnits="userSpaceOnUse"
+ x1="-109.125"
+ y1="52.625"
+ x2="-121.73741"
+ y2="38.387074" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient42370"
+ gradientUnits="userSpaceOnUse"
+ x1="112.48699"
+ y1="99.873772"
+ x2="136.44698"
+ y2="123.20583" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42372"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient42374"
+ gradientUnits="userSpaceOnUse"
+ x1="102.83286"
+ y1="85.825607"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42376"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-41,98)"
+ x1="-170.25"
+ y1="65.5"
+ x2="-181.375"
+ y2="65.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42378"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6962506,0,0,0.8034158,-66.833415,127.95312)"
+ x1="-223.42456"
+ y1="43.134327"
+ x2="-202.33263"
+ y2="39.110355" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42380"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6962506,0,0,0.8034158,-66.833415,127.95312)"
+ x1="-219.98772"
+ y1="40.355042"
+ x2="-220.82353"
+ y2="27.996962" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42382"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9098462,0,0,0.9414558,-57.134785,102.33514)"
+ x1="-177.6924"
+ y1="63.26775"
+ x2="-170.82031"
+ y2="62.441177" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42384"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2857143,0,0,0.787037,-92.714287,177.80092)"
+ x1="-101"
+ y1="-16"
+ x2="-93.75"
+ y2="-16.264704" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42386"
+ gradientUnits="userSpaceOnUse"
+ x1="-211.04486"
+ y1="193.68091"
+ x2="-219.5"
+ y2="185.8125" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="radialGradient42388"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.6261963,-1.575549,0.4790575,0.7985147,261.90894,-304.15053)"
+ cx="-216.5222"
+ cy="188.13423"
+ fx="-216.5222"
+ fy="188.13423"
+ r="6.9375" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="radialGradient42390"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4767928,-0.2294888,0.06653313,0.7180687,315.70283,0.01290384)"
+ cx="-221.88463"
+ cy="182.64247"
+ fx="-221.88463"
+ fy="182.64247"
+ r="3.4576657" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42392"
+ gradientUnits="userSpaceOnUse"
+ x1="-225.00002"
+ y1="38.277779"
+ x2="-213"
+ y2="44.732624" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="radialGradient42394"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1226244,0.04761823,-0.1611956,3.8002759,59.188894,-553.59611)"
+ cx="-215.0979"
+ cy="201.01204"
+ fx="-215.0979"
+ fy="201.01204"
+ r="5.8999949" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42396"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,4)"
+ x1="-224"
+ y1="201"
+ x2="-214.39445"
+ y2="195.27762" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient42398"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1142111,0,0,-1,-174.01401,596.00357)"
+ x1="209.05762"
+ y1="290.00357"
+ x2="215.34009"
+ y2="277.00357" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient42400"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1142111,0,0,-1,-174.01401,596.00357)"
+ x1="178.77469"
+ y1="550.50702"
+ x2="198.57239"
+ y2="559.03442" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42402"
+ gradientUnits="userSpaceOnUse"
+ x1="132"
+ y1="120.4313"
+ x2="93.029579"
+ y2="78.9655" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient42404"
+ gradientUnits="userSpaceOnUse"
+ x1="112.48699"
+ y1="99.873772"
+ x2="136.44698"
+ y2="123.20583" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42406"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient42408"
+ gradientUnits="userSpaceOnUse"
+ x1="102.83286"
+ y1="85.825607"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42410"
+ gradientUnits="userSpaceOnUse"
+ x1="132"
+ y1="120.4313"
+ x2="93.029579"
+ y2="78.9655" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient42412"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1142111,0,0,-1,-174.01401,596.00357)"
+ x1="178.77469"
+ y1="550.50702"
+ x2="198.57239"
+ y2="559.03442" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient42414"
+ gradientUnits="userSpaceOnUse"
+ x1="112.48699"
+ y1="99.873772"
+ x2="133.62697"
+ y2="120.49951" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42416"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient42418"
+ gradientUnits="userSpaceOnUse"
+ x1="102.83286"
+ y1="85.825607"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42420"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-120,79)"
+ x1="-170.25"
+ y1="65.5"
+ x2="-181.375"
+ y2="65.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42422"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6962506,0,0,0.8034158,-145.83341,108.95312)"
+ x1="-223.42456"
+ y1="43.134327"
+ x2="-202.33263"
+ y2="39.110355" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42424"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6962506,0,0,0.8034158,-145.83341,108.95312)"
+ x1="-219.98772"
+ y1="40.355042"
+ x2="-220.82353"
+ y2="27.996962" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42426"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9098462,0,0,0.9414558,-136.13478,83.33514)"
+ x1="-177.6924"
+ y1="63.26775"
+ x2="-170.82031"
+ y2="62.441177" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42428"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2857143,0,0,0.787037,-171.71429,158.80092)"
+ x1="-101"
+ y1="-16"
+ x2="-93.75"
+ y2="-16.264704" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30208"
+ id="linearGradient42430"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1297,-948)"
+ x1="1664.4413"
+ y1="720.01788"
+ x2="1661.8125"
+ y2="726.37006" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19425"
+ id="radialGradient42432"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.1378252,-0.2988982,2.5269117,1.1651875,-1689.2674,-563.64056)"
+ cx="1662.2664"
+ cy="722.19189"
+ fx="1662.2664"
+ fy="722.19189"
+ r="5.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42434"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,-1256.7473,-918.72044)"
+ x1="1984.3658"
+ y1="827.77124"
+ x2="1977.4047"
+ y2="829.72656" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42436"
+ gradientUnits="userSpaceOnUse"
+ x1="-211.04486"
+ y1="193.68091"
+ x2="-219.5"
+ y2="185.8125" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="radialGradient42438"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.6261963,-1.575549,0.4790575,0.7985147,261.90894,-304.15053)"
+ cx="-216.5222"
+ cy="188.13423"
+ fx="-216.5222"
+ fy="188.13423"
+ r="6.9375" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="radialGradient42440"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4767928,-0.2294888,0.06653313,0.7180687,315.70283,0.01290384)"
+ cx="-221.88463"
+ cy="182.64247"
+ fx="-221.88463"
+ fy="182.64247"
+ r="3.4576657" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42442"
+ gradientUnits="userSpaceOnUse"
+ x1="-225.00002"
+ y1="38.277779"
+ x2="-213"
+ y2="44.732624" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient42444"
+ gradientUnits="userSpaceOnUse"
+ x1="124.8772"
+ y1="110.75571"
+ x2="133.97179"
+ y2="117.77643" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42446"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="142.64723"
+ y2="129.05313" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient42448"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1658027,0,0,1.1657997,-354.28972,51.94393)"
+ x1="129.32576"
+ y1="223.61363"
+ x2="123.33967"
+ y2="217.06438" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42462"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425"
+ id="linearGradient42464"
+ gradientUnits="userSpaceOnUse"
+ x1="123.26987"
+ y1="108.56933"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42466"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient42468"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.8370074,0,0,0.8129865,84.784966,-149.92038)"
+ x1="-4.9152389"
+ y1="252.69086"
+ x2="-45.689278"
+ y2="252.63284" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42470"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,11.285548,8.325368)"
+ x1="111.03847"
+ y1="57.034107"
+ x2="117.16058"
+ y2="60.591385" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42472"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425"
+ id="linearGradient42474"
+ gradientUnits="userSpaceOnUse"
+ x1="123.26987"
+ y1="108.56933"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42477"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42479"
+ gradientUnits="userSpaceOnUse"
+ x1="-92.587807"
+ y1="-18.005362"
+ x2="-100.62162"
+ y2="-17.998919" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42481"
+ gradientUnits="userSpaceOnUse"
+ x1="-101"
+ y1="-16"
+ x2="-93"
+ y2="-17" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient42483"
+ gradientUnits="userSpaceOnUse"
+ x1="-87.491188"
+ y1="-22.830606"
+ x2="-102.96513"
+ y2="-22.166544" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42485"
+ gradientUnits="userSpaceOnUse"
+ x1="-98.997849"
+ y1="-23.173643"
+ x2="-98.997849"
+ y2="-25.872688" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42487"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425"
+ id="linearGradient42489"
+ gradientUnits="userSpaceOnUse"
+ x1="123.26987"
+ y1="108.56933"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42491"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient42493"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5290924,0,0,0.5294132,-17.313533,46.110999)"
+ x1="109.04134"
+ y1="75.666725"
+ x2="135.45256"
+ y2="103.11092" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42495"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5350034,0,0,0.5349052,24.446207,45.843517)"
+ x1="47.655102"
+ y1="93.805557"
+ x2="59.057678"
+ y2="105.27895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42497"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425"
+ id="linearGradient42499"
+ gradientUnits="userSpaceOnUse"
+ x1="123.26987"
+ y1="108.56933"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42501"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient42503"
+ gradientUnits="userSpaceOnUse"
+ x1="124.8772"
+ y1="110.75571"
+ x2="133.97179"
+ y2="117.77643" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42505"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="142.64723"
+ y2="129.05313" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42507"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425"
+ id="linearGradient42509"
+ gradientUnits="userSpaceOnUse"
+ x1="123.26987"
+ y1="108.56933"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42511"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient42513"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4749148,1.0023386,-1.2226848,-0.4749148,213.62384,41.735193)"
+ x1="118.95689"
+ y1="106.42961"
+ x2="135.14919"
+ y2="119.05286" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42515"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5333554,1.1220467,-1.1447545,-0.5333554,196.63818,32.816067)"
+ x1="130.39502"
+ y1="116.31751"
+ x2="147.95374"
+ y2="134.687" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18207"
+ id="linearGradient42517"
+ gradientUnits="userSpaceOnUse"
+ x1="-132.24858"
+ y1="313.87549"
+ x2="-171.01999"
+ y2="223.69542" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42519"
+ gradientUnits="userSpaceOnUse"
+ x1="114.15679"
+ y1="100.93772"
+ x2="137.5759"
+ y2="124.47867" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42521"
+ gradientUnits="userSpaceOnUse"
+ x1="131.12576"
+ y1="118"
+ x2="140.19273"
+ y2="125.82862" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient42523"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42525"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9050931,-7.9558708e-4,0.00612764,0.9147058,26.488451,35.562258)"
+ x1="299.70026"
+ y1="408.49368"
+ x2="322.08145"
+ y2="429.53806" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35406"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425"
+ id="linearGradient35408"
+ gradientUnits="userSpaceOnUse"
+ x1="119.94563"
+ y1="100.51657"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35410"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9897912,0,0,0.9897912,2.2765631,2.9503441)"
+ x1="311.90765"
+ y1="311.2269"
+ x2="308.84512"
+ y2="308.51169" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient35412"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1377775,-0.7111077,0.4395239,0.7032404,-101.13916,328.96745)"
+ cx="269.71231"
+ cy="237.2262"
+ fx="269.71231"
+ fy="237.2262"
+ r="7.03125" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient35414"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.706663,-1.1377794,0.5688915,0.8533318,-282.47828,404.20327)"
+ cx="262.83905"
+ cy="245.91792"
+ fx="262.83905"
+ fy="245.91792"
+ r="7.03125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35416"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425"
+ id="linearGradient35418"
+ gradientUnits="userSpaceOnUse"
+ x1="119.94563"
+ y1="100.51657"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35420"
+ gradientUnits="userSpaceOnUse"
+ x1="220.14905"
+ y1="291.80676"
+ x2="226.09999"
+ y2="286.2493" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35422"
+ gradientUnits="userSpaceOnUse"
+ x1="223.12212"
+ y1="296.15784"
+ x2="219.06912"
+ y2="291.99768" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35424"
+ gradientUnits="userSpaceOnUse"
+ x1="217.56451"
+ y1="290.56451"
+ x2="224.01613"
+ y2="297.01614" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient35426"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3677588,0.3783715,-0.5696226,0.5536455,304.13863,47.532824)"
+ cx="219.00334"
+ cy="291.33972"
+ fx="219.00334"
+ fy="291.33972"
+ r="4" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35468"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425"
+ id="linearGradient35470"
+ gradientUnits="userSpaceOnUse"
+ x1="119.94563"
+ y1="100.51657"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35472"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9897912,0,0,0.9897912,2.2765631,2.9503441)"
+ x1="311.90765"
+ y1="311.2269"
+ x2="308.84512"
+ y2="308.51169" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient35474"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1377775,-0.7111077,0.4395239,0.7032404,-101.13916,328.96745)"
+ cx="269.71231"
+ cy="237.2262"
+ fx="269.71231"
+ fy="237.2262"
+ r="7.03125" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient35476"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.706663,-1.1377794,0.5688915,0.8533318,-282.47828,404.20327)"
+ cx="262.83905"
+ cy="245.91792"
+ fx="262.83905"
+ fy="245.91792"
+ r="7.03125" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35478"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="140.66667"
+ y2="125.94853" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425"
+ id="linearGradient35480"
+ gradientUnits="userSpaceOnUse"
+ x1="119.94563"
+ y1="100.51657"
+ x2="138.25778"
+ y2="124.59384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35482"
+ gradientUnits="userSpaceOnUse"
+ x1="220.14905"
+ y1="291.80676"
+ x2="226.09999"
+ y2="286.2493" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient35484"
+ gradientUnits="userSpaceOnUse"
+ x1="223.12212"
+ y1="296.15784"
+ x2="219.06912"
+ y2="291.99768" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35486"
+ gradientUnits="userSpaceOnUse"
+ x1="217.56451"
+ y1="290.56451"
+ x2="224.01613"
+ y2="297.01614" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient35488"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3677588,0.3783715,-0.5696226,0.5536455,304.13863,47.532824)"
+ cx="219.00334"
+ cy="291.33972"
+ fx="219.00334"
+ fy="291.33972"
+ r="4" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient34618"
+ gradientUnits="userSpaceOnUse"
+ x1="125.59209"
+ y1="112.6446"
+ x2="133.11621"
+ y2="119.21729" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient34620"
+ gradientUnits="userSpaceOnUse"
+ x1="130.39502"
+ y1="116.31751"
+ x2="141.83322"
+ y2="132.30261" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35411"
+ id="linearGradient35446"
+ gradientUnits="userSpaceOnUse"
+ x1="31"
+ y1="60.000004"
+ x2="34"
+ y2="54.000004" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35411"
+ id="linearGradient35448"
+ gradientUnits="userSpaceOnUse"
+ x1="135.46967"
+ y1="118"
+ x2="121.4286"
+ y2="101.14284" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35411"
+ id="linearGradient35450"
+ gradientUnits="userSpaceOnUse"
+ x1="133.60002"
+ y1="118"
+ x2="128.8"
+ y2="114.8" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35411"
+ id="linearGradient35452"
+ gradientUnits="userSpaceOnUse"
+ x1="132.30316"
+ y1="123.05057"
+ x2="128.8"
+ y2="114.8" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35411"
+ id="linearGradient35454"
+ gradientUnits="userSpaceOnUse"
+ x1="136.35806"
+ y1="124.27161"
+ x2="130.48389"
+ y2="118" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient35718"
+ x1="28.130203"
+ y1="65.791054"
+ x2="32.5"
+ y2="55.066181"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient36452"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.050372,0,0,1.050372,-3.551238,-0.730396)"
+ cx="70.5"
+ cy="14.5"
+ fx="70.5"
+ fy="14.5"
+ r="1.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient36273"
+ id="linearGradient36454"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4000084,0,0,0.4000084,137.60085,-8.4035259)"
+ x1="-103.37495"
+ y1="417.87503"
+ x2="-101.49999"
+ y2="419.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient36273"
+ id="linearGradient36456"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4000084,0,0,0.4000084,131.60084,3.5964741)"
+ x1="-103.37495"
+ y1="417.87503"
+ x2="-101.49999"
+ y2="419.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient36273"
+ id="linearGradient36458"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4000084,0,0,0.4000084,143.60084,3.5964739)"
+ x1="-103.37495"
+ y1="417.87503"
+ x2="-101.49999"
+ y2="419.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient37095"
+ gradientUnits="userSpaceOnUse"
+ x1="125.75312"
+ y1="111.40558"
+ x2="143.16118"
+ y2="129.27902" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient37097"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0028571,0,0,0.9943503,-0.4404318,0.129119)"
+ x1="185.89514"
+ y1="30.343155"
+ x2="197.03207"
+ y2="42.717522" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient36648"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-3,3)"
+ x1="188"
+ y1="40.25"
+ x2="180.8125"
+ y2="32.46875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient36650"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-3,3)"
+ x1="187.8125"
+ y1="33.9375"
+ x2="184.25"
+ y2="30.15625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36652"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-3.0999952,2.9000005)"
+ x1="177.85001"
+ y1="33.537502"
+ x2="186.00626"
+ y2="43.381248" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19900"
+ id="linearGradient36654"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9643891,0,0,0.9772371,6.188671,1.0072576)"
+ x1="182.20605"
+ y1="39.645184"
+ x2="172.36885"
+ y2="31.368597" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36656"
+ gradientUnits="userSpaceOnUse"
+ x1="181.14906"
+ y1="32.701904"
+ x2="186.00002"
+ y2="37.415516" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19900"
+ id="linearGradient36658"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9643891,0,0,0.9772371,9.438677,-2.4927424)"
+ x1="181.9404"
+ y1="40.924297"
+ x2="175.82253"
+ y2="34.272892" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36468"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166695,0,0,0.9203753,-10.025729,345.78566)"
+ x1="80.60067"
+ y1="108.47212"
+ x2="68.0271"
+ y2="94.239906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13938"
+ id="linearGradient36470"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-15.983875,338)"
+ x1="68.361542"
+ y1="95.337166"
+ x2="88.785263"
+ y2="116.62141" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36472"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9998599,0,0,0.9960071,-15.972985,338.41149)"
+ x1="58.761654"
+ y1="84.330009"
+ x2="81.383331"
+ y2="108.06429" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36713"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="117.12428"
+ y2="61.720783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36715"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36717"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,13)"
+ x1="-56.8125"
+ y1="329.06256"
+ x2="-47.214466"
+ y2="329.26965" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36719"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="117.12428"
+ y2="61.720783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36721"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36723"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,13)"
+ x1="-56.8125"
+ y1="329.06256"
+ x2="-47.214466"
+ y2="329.26965" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36725"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="117.12428"
+ y2="61.720783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36727"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient36729"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.7972867,61.99991,2.2419)"
+ x1="260.67468"
+ y1="108.02418"
+ x2="273.9993"
+ y2="126.37626" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient37396"
+ gradientUnits="userSpaceOnUse"
+ x1="389.73953"
+ y1="220.84622"
+ x2="389.59052"
+ y2="248.09296"
+ gradientTransform="matrix(-1,0,0,1,780.92531,0)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37398"
+ gradientUnits="userSpaceOnUse"
+ x1="389.51059"
+ y1="241.72565"
+ x2="388.20074"
+ y2="242.55887"
+ gradientTransform="matrix(-1,0,0,1,780.92531,0)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient38570"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-2,0)"
+ x1="-20"
+ y1="283"
+ x2="-20"
+ y2="284.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient38572"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-2,-582)"
+ x1="-20"
+ y1="283"
+ x2="-20"
+ y2="284.5" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask38561">
+ <g
+ id="g38563">
+ <rect
+ y="278"
+ x="-23"
+ height="13"
+ width="16"
+ id="rect38565"
+ style="fill:url(#linearGradient38570);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:url(#linearGradient38572);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect38567"
+ width="16"
+ height="13"
+ x="-23"
+ y="-304" />
+ </g>
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-7">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-1" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-2" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610-7-6">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-4-1" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-0-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069-4-2">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-8-3" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-8-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient11871-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop11873-5" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop11875-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-7-6"
+ id="linearGradient39048"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,-83,199)"
+ x1="96"
+ y1="42"
+ x2="68"
+ y2="12" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-4-2"
+ id="linearGradient39050"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,-83,199)"
+ x1="65"
+ y1="20"
+ x2="66"
+ y2="12" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient11871-4"
+ id="linearGradient39052"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,-83,199)"
+ x1="67.25"
+ y1="18"
+ x2="68"
+ y2="16" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35411-4-27"
+ id="linearGradient39835-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8422958,0,0,0.8364537,82.535678,2.9394266)"
+ x1="89.975014"
+ y1="-32.339718"
+ x2="88.492455"
+ y2="-33.303608" />
+ <linearGradient
+ id="linearGradient35411-4-27">
+ <stop
+ id="stop35414-0-9"
+ offset="0"
+ style="stop-color:#2b5385;stop-opacity:1;" />
+ <stop
+ id="stop35416-9-5"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35411-8-1-3"
+ id="linearGradient39837-4"
+ gradientUnits="userSpaceOnUse"
+ x1="131.02808"
+ y1="123.49161"
+ x2="128.7139"
+ y2="115.97001" />
+ <linearGradient
+ id="linearGradient35411-8-1-3">
+ <stop
+ id="stop35414-2-7-1"
+ offset="0"
+ style="stop-color:#2b5385;stop-opacity:1;" />
+ <stop
+ id="stop35416-4-1-2"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35411-8-1-3"
+ id="linearGradient39839-3"
+ gradientUnits="userSpaceOnUse"
+ x1="136.35806"
+ y1="124.27161"
+ x2="130.48389"
+ y2="118" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974-5-4"
+ id="linearGradient39841-3"
+ gradientUnits="userSpaceOnUse"
+ x1="115.15884"
+ y1="88.476723"
+ x2="109.18613"
+ y2="82.308861" />
+ <linearGradient
+ id="linearGradient23974-5-4">
+ <stop
+ id="stop23976-27-1"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop23978-6-1"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-8"
+ id="linearGradient39843-3"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21,0)"
+ x1="101"
+ y1="84.25"
+ x2="97.75"
+ y2="81.5" />
+ <linearGradient
+ id="linearGradient1610-8">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-7" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-4" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-77"
+ id="linearGradient39845-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21,0)"
+ x1="87.44548"
+ y1="81.439644"
+ x2="96.592278"
+ y2="89.708977" />
+ <linearGradient
+ id="linearGradient319-77">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-31" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22882"
+ id="linearGradient41540"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0369025,0,0,1.5,-458.38567,-344)"
+ x1="23.959812"
+ y1="285"
+ x2="31.498274"
+ y2="285" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22882"
+ id="linearGradient41542"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1929722,0,0,0.5,-462.63135,-59)"
+ x1="24"
+ y1="285"
+ x2="31.538462"
+ y2="285" />
+ <linearGradient
+ id="linearGradient23974-4">
+ <stop
+ id="stop23976-20"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop23978-9"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-37"
+ id="linearGradient32529-7"
+ gradientUnits="userSpaceOnUse"
+ x1="139.2112"
+ y1="111.35809"
+ x2="125.18381"
+ y2="128" />
+ <linearGradient
+ id="linearGradient319-37">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-2" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-60" />
+ </linearGradient>
+ <linearGradient
+ y2="125.77761"
+ x2="139.07738"
+ y1="115.76797"
+ x1="129.62384"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient41582"
+ xlink:href="#linearGradient23974-4"
+ inkscape:collect="always" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="radialGradient41666"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8128508,0,0,0.8128508,80.474142,14.46897)"
+ cx="430.00003"
+ cy="77.3125"
+ fx="430.00003"
+ fy="77.3125"
+ r="8" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient41668"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.785748,0,0,0.78488,265.93616,46.1048)"
+ x1="210.08989"
+ y1="38.088879"
+ x2="199.27217"
+ y2="38.088879" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient41670"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(399.01387,-202)"
+ x1="28.4375"
+ y1="277"
+ x2="23.25"
+ y2="276.92188" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient41672"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.01387,0)"
+ x1="437.98615"
+ y1="77"
+ x2="424.75217"
+ y2="75.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient41674"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.01387,0)"
+ x1="438.61115"
+ y1="78"
+ x2="424.75217"
+ y2="75.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient41676"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.01387,0)"
+ x1="441.98615"
+ y1="77.44017"
+ x2="424.75217"
+ y2="75.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient42432"
+ gradientUnits="userSpaceOnUse"
+ x1="258.94861"
+ y1="285.63672"
+ x2="237.92474"
+ y2="261.44183" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient42435"
+ gradientUnits="userSpaceOnUse"
+ x1="135.45557"
+ y1="122.90726"
+ x2="130.54761"
+ y2="116.54932" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient42437"
+ gradientUnits="userSpaceOnUse"
+ x1="125.81818"
+ y1="111.81818"
+ x2="143.88347"
+ y2="129.27184" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath42711">
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect42713"
+ width="8.7252884"
+ height="17.464855"
+ x="127.4093"
+ y="214.76154" />
+ </clipPath>
+ <linearGradient
+ id="linearGradient38796-7-9">
+ <stop
+ style="stop-color:#fc9694;stop-opacity:1;"
+ offset="0"
+ id="stop38798-6-8" />
+ <stop
+ style="stop-color:#e71609;stop-opacity:1;"
+ offset="1"
+ id="stop38800-1-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610-87">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-78" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-3" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient24679-1">
+ <stop
+ style="stop-color:#3d361a;stop-opacity:1;"
+ offset="0"
+ id="stop24681-0" />
+ <stop
+ id="stop24683-7"
+ offset="0.45537567"
+ style="stop-color:#d1c595;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop24685-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38719"
+ gradientUnits="userSpaceOnUse"
+ x1="125.99933"
+ y1="111.2683"
+ x2="134.91479"
+ y2="122.36016" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38722"
+ gradientUnits="userSpaceOnUse"
+ x1="126.72586"
+ y1="112.53999"
+ x2="134.91479"
+ y2="122.36016" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13973"
+ id="linearGradient38724"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(19.367382,0)"
+ x1="111.46314"
+ y1="113.45913"
+ x2="99.628899"
+ y2="99.029617" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38726"
+ gradientUnits="userSpaceOnUse"
+ x1="127.63637"
+ y1="114.2303"
+ x2="143.69765"
+ y2="131.03783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient39142"
+ gradientUnits="userSpaceOnUse"
+ x1="400.90442"
+ y1="68.853401"
+ x2="410.47467"
+ y2="77.877228" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38005"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-157.00004,-233.00002)"
+ x1="308"
+ y1="323"
+ x2="337.80573"
+ y2="337.517" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38007"
+ gradientUnits="userSpaceOnUse"
+ x1="285.39999"
+ y1="323.80002"
+ x2="286.60001"
+ y2="325" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath43368-1">
+ <rect
+ style="fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect43370-7"
+ width="16"
+ height="16"
+ x="-79"
+ y="26" />
+ </clipPath>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43276-0"
+ id="radialGradient43410-4"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4098275,-0.6406034,2.5104141,1.6060416,-127.46107,-65.792415)"
+ cx="-67.890839"
+ cy="33.548397"
+ fx="-67.890839"
+ fy="33.548397"
+ r="3.1501868" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient43276-0">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop43278-9" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop43280-4" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43276-0"
+ id="radialGradient43412-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4098275,-0.7183766,2.5885772,1.4767588,-130.41049,-65.518114)"
+ cx="-74.960228"
+ cy="34.896461"
+ fx="-74.960228"
+ fy="34.896461"
+ r="3.1501868" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38796-7-9"
+ id="linearGradient40270"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-21)"
+ x1="59.622501"
+ y1="54.1525"
+ x2="60.981617"
+ y2="55.566177" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-87"
+ id="linearGradient40272"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.5,-21)"
+ x1="60.25"
+ y1="56.5"
+ x2="57.789688"
+ y2="54.130001" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-87"
+ id="linearGradient40274"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-0.5,-21)"
+ x1="60.25"
+ y1="56.5"
+ x2="56"
+ y2="52.25" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-87"
+ id="linearGradient40276"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1.54625,-1)"
+ x1="63.666252"
+ y1="37.960625"
+ x2="60.676094"
+ y2="34.685287" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24679-1"
+ id="linearGradient40278"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-21)"
+ x1="52.17437"
+ y1="65.644958"
+ x2="50.371208"
+ y2="62.960247" />
+ <linearGradient
+ id="linearGradient24143-0">
+ <stop
+ id="stop24145-0"
+ offset="0"
+ style="stop-color:#2c2c2c;stop-opacity:1;" />
+ <stop
+ style="stop-color:#b3b3b3;stop-opacity:1;"
+ offset="0.5"
+ id="stop24669-1" />
+ <stop
+ id="stop24147-4"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-3-7"
+ id="linearGradient39686-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(22,0)"
+ x1="-70.605209"
+ y1="-121.58411"
+ x2="-28.177105"
+ y2="-89.026711" />
+ <linearGradient
+ id="linearGradient1610-3-7">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-1-4" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-6-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-5-9-4"
+ id="linearGradient39688-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(22,0)"
+ x1="-74"
+ y1="-124"
+ x2="-55.5975"
+ y2="-103.2075" />
+ <linearGradient
+ id="linearGradient319-5-9-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-761-8-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-89-24-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37542-6">
+ <stop
+ id="stop37544-18"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-92"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16500-3">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-3" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-41" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient9030-1">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop9032-9" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop9034-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient59371">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop59373" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop59375" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-9-1"
+ id="linearGradient42965-7"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(301.02752,449.99999)"
+ x1="25.963812"
+ y1="155.66899"
+ x2="29.972469"
+ y2="168" />
+ <linearGradient
+ id="linearGradient319-9-1">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-92-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-55-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-06-1"
+ id="linearGradient42967-6"
+ gradientUnits="userSpaceOnUse"
+ x1="335.96875"
+ y1="607.09375"
+ x2="337.04251"
+ y2="628.20752" />
+ <linearGradient
+ id="linearGradient1610-06-1">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-8-4" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-1-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient41266"
+ gradientUnits="userSpaceOnUse"
+ x1="98.858559"
+ y1="80.045052"
+ x2="135.00615"
+ y2="122.92735" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient41268"
+ gradientUnits="userSpaceOnUse"
+ x1="130.75166"
+ y1="245.03757"
+ x2="129.24866"
+ y2="243.31177" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient41270"
+ gradientUnits="userSpaceOnUse"
+ x1="126.37006"
+ y1="112.31642"
+ x2="144.22272"
+ y2="129.82761" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient41272"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient40918"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(146.00001,-20)"
+ x1="108"
+ y1="500"
+ x2="54.8125"
+ y2="500" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15809"
+ id="linearGradient40920"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(146.00001,-20)"
+ x1="88.874489"
+ y1="502.71924"
+ x2="41.311054"
+ y2="501.10059" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient40922"
+ gradientUnits="userSpaceOnUse"
+ x1="80.768944"
+ y1="504.67188"
+ x2="76.885078"
+ y2="501.58331" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40924"
+ gradientUnits="userSpaceOnUse"
+ x1="89.526657"
+ y1="511.42972"
+ x2="78.000008"
+ y2="501.04794" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262"
+ id="radialGradient40926"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3949409,0.3949425,-0.4243709,0.4254619,404.60763,237.35923)"
+ cx="75.95578"
+ cy="492.15359"
+ fx="75.95578"
+ fy="492.15359"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient40928"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.9435203,-2.1990242,1.1704696,1.0049395,-665.14472,173.40654)"
+ cx="79.959885"
+ cy="503.81497"
+ fx="79.959885"
+ fy="503.81497"
+ r="2.9089756" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14262"
+ id="radialGradient40930"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8886193,0.8021825,-0.8051059,0.8972684,411.80247,-8.668512)"
+ cx="74.518959"
+ cy="499.99969"
+ fx="74.518959"
+ fy="499.99969"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient40932"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.054749"
+ cy="499.87418"
+ fx="75.054749"
+ fy="499.87418"
+ r="3.1650217" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-6"
+ id="linearGradient36549"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.1511102,0,0,-1.1511102,152.68442,762.00423)"
+ x1="-16.608393"
+ y1="199.5118"
+ x2="30.713354"
+ y2="245.13458" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-3"
+ id="radialGradient36551"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6959954,0.116912,-0.04402498,0.2620878,107.60035,414.99606)"
+ cx="32.193073"
+ cy="243.37001"
+ fx="32.193073"
+ fy="243.37001"
+ r="6.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24143-0"
+ id="linearGradient36553"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.9999993,0,0,-0.9821923,147.99998,720.60935)"
+ x1="32.204613"
+ y1="233.6039"
+ x2="35.615856"
+ y2="251.99768" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-3"
+ id="linearGradient36555"
+ gradientUnits="userSpaceOnUse"
+ x1="148.76726"
+ y1="134.53409"
+ x2="114.11786"
+ y2="101.28939" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40809"
+ id="linearGradient36557"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7500336,0,0,0.8546123,-239.89087,340.17205)"
+ x1="481.60803"
+ y1="163.09677"
+ x2="477.10818"
+ y2="163.00024" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient59371"
+ id="linearGradient36559"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7500181,0,0,0.8546123,-235.38338,339.18935)"
+ x1="473.79471"
+ y1="164.64572"
+ x2="463.90472"
+ y2="160.80888" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030-1"
+ id="linearGradient36561"
+ gradientUnits="userSpaceOnUse"
+ x1="129.74713"
+ y1="118"
+ x2="144.33401"
+ y2="132.61403" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-3"
+ id="linearGradient36563"
+ gradientUnits="userSpaceOnUse"
+ x1="138.46678"
+ y1="124.90586"
+ x2="126.18426"
+ y2="116.14438" />
+ <linearGradient
+ id="linearGradient9030-7-8-6">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop9032-4-9-2" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop9034-0-2-3" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient40809-2-2">
+ <stop
+ style="stop-color:#0059d7;stop-opacity:1;"
+ offset="0"
+ id="stop40811-1-6" />
+ <stop
+ style="stop-color:#b7d4ff;stop-opacity:1;"
+ offset="1"
+ id="stop40813-4-2" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient20055-7-5-5">
+ <stop
+ id="stop20057-1-7-7"
+ offset="0"
+ style="stop-color:#0a2a5a;stop-opacity:1;" />
+ <stop
+ id="stop20059-1-6-8"
+ offset="1"
+ style="stop-color:#3771c8;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient16500-4-9-7">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-8-5-8" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-8-4-0" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37829">
+ <stop
+ id="stop37831"
+ offset="0"
+ style="stop-color:#3d361a;stop-opacity:1;" />
+ <stop
+ style="stop-color:#d1c595;stop-opacity:1;"
+ offset="0.5"
+ id="stop37833" />
+ <stop
+ id="stop37835"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient40578-4-8">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop40580-8-9" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop40582-6-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient39254"
+ 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="#linearGradient40578-4-8"
+ id="radialGradient39256"
+ 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="#linearGradient58334"
+ id="linearGradient39258"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(670,-33)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39260"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-95.999998)"
+ x1="754.28558"
+ y1="300.83292"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ id="linearGradient40455-7">
+ <stop
+ id="stop40457-6"
+ offset="0"
+ style="stop-color:#fff991;stop-opacity:1;" />
+ <stop
+ id="stop40459-1"
+ offset="1"
+ style="stop-color:#fffbb9;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient36657"
+ 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="#linearGradient40578-4-8"
+ id="radialGradient36659"
+ 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="#linearGradient58334"
+ id="linearGradient36661"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(670,-33)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient36663"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-95.999998)"
+ x1="754.28558"
+ y1="300.83292"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37829"
+ id="linearGradient37089"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.9999993,0,0,-0.9821923,165.4,716.20935)"
+ x1="261.17639"
+ y1="247.85646"
+ x2="253.86414"
+ y2="288.70752" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient39080"
+ id="linearGradient37091"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.888884,0,0,-0.8730569,136.66557,688.20759)"
+ x1="261.60016"
+ y1="247.008"
+ x2="263.60016"
+ y2="262.27994" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030-7-8-6"
+ id="linearGradient37093"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-124.99991,219.9903)"
+ x1="19.923029"
+ y1="232.59058"
+ x2="50.485012"
+ y2="265.9697" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40809-2-2"
+ id="linearGradient37096"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7500336,0,0,0.8546123,-239.89087,340.17205)"
+ x1="199.26254"
+ y1="144.5041"
+ x2="193.7029"
+ y2="144.5041" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20055-7-5-5"
+ id="linearGradient37098"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-670.99999,411.99999)"
+ x1="579.625"
+ y1="54.299286"
+ x2="576.4375"
+ y2="49.84375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-4-9-7"
+ id="linearGradient37100"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-670.99999,411.99999)"
+ x1="582.79974"
+ y1="56.363762"
+ x2="575.70361"
+ y2="49.87711" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030-7-8-6"
+ id="linearGradient37102"
+ gradientUnits="userSpaceOnUse"
+ x1="129.74713"
+ y1="118"
+ x2="144.33401"
+ y2="132.61403" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-4-9-7"
+ id="linearGradient37104"
+ gradientUnits="userSpaceOnUse"
+ x1="140.78264"
+ y1="123.96156"
+ x2="132.25548"
+ y2="116.40535" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40455-7"
+ id="radialGradient37553"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7881042,0.01544832,-0.01690407,0.7184169,-16.705439,29.204304)"
+ cx="-73.135666"
+ cy="95.970413"
+ fx="-73.135666"
+ fy="95.970413"
+ r="4.9999957" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37667"
+ id="radialGradient37555"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4604901,-0.4901463,0.6187826,0.5813434,279.52277,457.42224)"
+ cx="756.98285"
+ cy="206.8443"
+ fx="756.98285"
+ fy="206.8443"
+ r="6.9000001" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334"
+ id="linearGradient37558"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(670,-33)"
+ x1="89.012573"
+ y1="243.96121"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient37561"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(1,-94.999998)"
+ x1="754.28558"
+ y1="300.83292"
+ x2="758.62622"
+ y2="305.53677" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40455-7-1"
+ id="radialGradient37553-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.7881042,0.01544832,-0.01690407,0.7184169,-16.705439,29.204304)"
+ cx="-73.227486"
+ cy="95.949913"
+ fx="-73.227486"
+ fy="95.949913"
+ r="4.9999957" />
+ <linearGradient
+ id="linearGradient40455-7-1">
+ <stop
+ id="stop40457-6-6"
+ offset="0"
+ style="stop-color:#fff991;stop-opacity:1;" />
+ <stop
+ id="stop40459-1-8"
+ offset="1"
+ style="stop-color:#fffbb9;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40578-4-8-7"
+ id="radialGradient37555-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4769848,-0.5257394,0.6056598,0.5494938,269.68012,490.96577)"
+ cx="756.83508"
+ cy="206.40076"
+ fx="756.83508"
+ fy="206.40076"
+ r="6.9000001" />
+ <linearGradient
+ id="linearGradient40578-4-8-7">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop40580-8-9-6" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop40582-6-8-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334-9"
+ id="linearGradient37558-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(670,-33)"
+ x1="89.012573"
+ y1="243.96121"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ id="linearGradient58334-9">
+ <stop
+ id="stop58336-27"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.87628865;" />
+ <stop
+ id="stop58338-9"
+ offset="1.0000000"
+ style="stop-color:#fffffe;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-4">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-31" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-23" />
+ </linearGradient>
+ <linearGradient
+ y2="305"
+ x2="758"
+ y1="300.83292"
+ x1="754.28558"
+ gradientTransform="translate(1,-94.999998)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient37610-3"
+ xlink:href="#linearGradient16500-4"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient71834"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166695,0,0,0.9203753,-10.025729,345.78566)"
+ x1="80.60067"
+ y1="108.47212"
+ x2="68.0271"
+ y2="94.239906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient71814"
+ id="linearGradient71836"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-15.983875,338)"
+ x1="70.55275"
+ y1="97.5"
+ x2="79.355118"
+ y2="107.18619" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient71838"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9998599,0,0,0.9960071,-15.972985,338.41149)"
+ x1="61.465469"
+ y1="88.058716"
+ x2="86.00116"
+ y2="112.03586" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38256"
+ id="linearGradient37188"
+ gradientUnits="userSpaceOnUse"
+ x1="-22"
+ y1="36.47311"
+ x2="-18.85"
+ y2="22.485678"
+ gradientTransform="translate(522.00015,466)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37191"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(168.00015,169.99998)"
+ x1="308"
+ y1="323"
+ x2="343.26239"
+ y2="340" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37201"
+ gradientUnits="userSpaceOnUse"
+ x1="-26"
+ y1="38"
+ x2="-27"
+ y2="30.200407"
+ gradientTransform="translate(522.00015,466)" />
+ <linearGradient
+ id="linearGradient1610-7409">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-488" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-2" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient40578-4-8-5">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop40580-8-9-5" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop40582-6-8-17" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient58334-1">
+ <stop
+ id="stop58336-5"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.87628865;" />
+ <stop
+ id="stop58338-27"
+ offset="1.0000000"
+ style="stop-color:#fffffe;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-14">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-23" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-22" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-7409"
+ id="linearGradient37317"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,513.5,184.50451)"
+ x1="253.78497"
+ y1="3.6831069"
+ x2="272.92456"
+ y2="26.239208" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40578-4-8-5"
+ id="radialGradient37319"
+ 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="#linearGradient58334-1"
+ id="linearGradient37321"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(670,-33)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-14"
+ id="linearGradient37323"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-95.999998)"
+ x1="754.1275"
+ y1="301.01553"
+ x2="758.77625"
+ y2="305.51749" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient37338"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(461.00015,453)"
+ x1="37"
+ y1="53"
+ x2="36.74033"
+ y2="44.322407" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37132"
+ gradientUnits="userSpaceOnUse"
+ x1="510.25"
+ y1="36"
+ x2="494"
+ y2="36"
+ gradientTransform="matrix(-1,0,0,1,992,0)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37134"
+ gradientUnits="userSpaceOnUse"
+ x1="492"
+ y1="33"
+ x2="503"
+ y2="43"
+ gradientTransform="matrix(-1,0,0,1,992,0)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37136"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,551,105)"
+ x1="497.3125"
+ y1="35"
+ x2="483"
+ y2="35" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient37138"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,551,105)"
+ x1="497.3125"
+ y1="35"
+ x2="483"
+ y2="35" />
+ <linearGradient
+ id="linearGradient40455-7-1-7">
+ <stop
+ id="stop40457-6-6-4"
+ offset="0"
+ style="stop-color:#fff991;stop-opacity:1;" />
+ <stop
+ id="stop40459-1-8-0"
+ offset="1"
+ style="stop-color:#fffbb9;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient38362"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.923955,0,0,1,2.85168,-84)"
+ x1="-9.3937483"
+ y1="203.3882"
+ x2="28.275171"
+ y2="249.73875" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40455-7-1-7"
+ id="radialGradient38364"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1033468,0.01995877,-0.02366572,0.9281732,7.8124646,13.285893)"
+ cx="-73.972397"
+ cy="94.935921"
+ fx="-73.972397"
+ fy="94.935921"
+ r="4.9999957" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38367"
+ gradientUnits="userSpaceOnUse"
+ x1="19.210167"
+ y1="143.17894"
+ x2="38.580528"
+ y2="167.11429"
+ gradientTransform="matrix(1,0,0,0.8461542,0,25.615323)" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath43368-7">
+ <rect
+ style="fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect43370-1"
+ width="16"
+ height="16"
+ x="-79"
+ y="26" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient43276-6">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop43278-0" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop43280-49" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43276-6"
+ id="radialGradient38734"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4098275,-0.6406034,2.5104141,1.6060416,-127.46107,-65.792415)"
+ cx="-67.890839"
+ cy="33.548397"
+ fx="-67.890839"
+ fy="33.548397"
+ r="3.1501868" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43276-6"
+ id="radialGradient38736"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4098275,-0.7183766,2.5885772,1.4767588,-130.41049,-65.518114)"
+ cx="-74.960228"
+ cy="34.896461"
+ fx="-74.960228"
+ fy="34.896461"
+ r="3.1501868" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient36718"
+ gradientUnits="userSpaceOnUse"
+ x1="400.90442"
+ y1="68.853401"
+ x2="410.47467"
+ y2="77.877228" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38049"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="121.22078"
+ y2="56.357628" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38051"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(207,-246.99988)"
+ x1="-56.5"
+ y1="342.0625"
+ x2="-49"
+ y2="341" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37530"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="121.22078"
+ y2="56.357628" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient37534"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(207,-246.99988)"
+ x1="-56.5"
+ y1="342.0625"
+ x2="-49"
+ y2="341" />
+ <linearGradient
+ id="linearGradient1610-6">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-18" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-92" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069-9">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-5" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-43" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9"
+ id="linearGradient38254"
+ gradientUnits="userSpaceOnUse"
+ x1="124.19057"
+ y1="111.30384"
+ x2="134.62978"
+ y2="120.14633" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-6"
+ id="linearGradient37509"
+ gradientUnits="userSpaceOnUse"
+ x1="189.76083"
+ y1="248.13905"
+ x2="116.05637"
+ y2="183.6826" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9"
+ id="linearGradient37613"
+ gradientUnits="userSpaceOnUse"
+ x1="123.80045"
+ y1="111.03492"
+ x2="132.99687"
+ y2="118.98331" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-6"
+ id="linearGradient37615"
+ gradientUnits="userSpaceOnUse"
+ x1="189.76083"
+ y1="248.13905"
+ x2="116.05637"
+ y2="183.6826" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425-4-9-8"
+ id="linearGradient38073-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,22)"
+ x1="-14.752135"
+ y1="101.82622"
+ x2="-45.074585"
+ y2="68.279541" />
+ <linearGradient
+ id="linearGradient15425-4-9-8">
+ <stop
+ style="stop-color:#960000;stop-opacity:1;"
+ offset="0"
+ id="stop15427-5-8-24" />
+ <stop
+ style="stop-color:#c80000;stop-opacity:0;"
+ offset="1"
+ id="stop15429-8-2-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060-1"
+ id="linearGradient38075-5"
+ gradientUnits="userSpaceOnUse"
+ x1="137.33838"
+ y1="124.67571"
+ x2="131.35606"
+ y2="118.00494" />
+ <linearGradient
+ id="linearGradient5060-1">
+ <stop
+ id="stop5062-7"
+ offset="0"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ id="stop5064-1"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-52"
+ id="linearGradient38077-1"
+ gradientUnits="userSpaceOnUse"
+ x1="127.15736"
+ y1="111.48302"
+ x2="146.01884"
+ y2="136.15825" />
+ <linearGradient
+ id="linearGradient319-52">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-7614" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-232" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15425-4-9-8"
+ id="linearGradient38079-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,22)"
+ x1="-15"
+ y1="101"
+ x2="-22"
+ y2="94" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient14418-6"
+ id="linearGradient14433-1"
+ gradientUnits="userSpaceOnUse"
+ x1="139.29807"
+ y1="127.35454"
+ x2="130.33557"
+ y2="115.81818" />
+ <linearGradient
+ id="linearGradient14418-6">
+ <stop
+ id="stop14420-8"
+ offset="0"
+ style="stop-color:#fa2509;stop-opacity:1;" />
+ <stop
+ id="stop14422-5"
+ offset="1"
+ style="stop-color:#fa2509;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-52"
+ id="linearGradient14435-7"
+ gradientUnits="userSpaceOnUse"
+ x1="125.36379"
+ y1="110.81054"
+ x2="135.22182"
+ y2="120.76331" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-52"
+ id="linearGradient14437-6"
+ gradientUnits="userSpaceOnUse"
+ x1="125.81818"
+ y1="111.81818"
+ x2="141.43347"
+ y2="127.52184" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-2"
+ id="linearGradient14439-9"
+ gradientUnits="userSpaceOnUse"
+ x1="125.20553"
+ y1="111.38132"
+ x2="132.35237"
+ y2="118.69846" />
+ <linearGradient
+ id="linearGradient10069-2">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-79" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-52"
+ id="linearGradient14441-4"
+ gradientUnits="userSpaceOnUse"
+ x1="125.81818"
+ y1="111.81818"
+ x2="143.88347"
+ y2="129.27184" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient48327-1"
+ id="radialGradient38306-3"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4461753,0.01083717,0.0036163,6.752143,-191.34795,-740.3814)"
+ cx="131.99811"
+ cy="126.63337"
+ fx="131.99811"
+ fy="126.63337"
+ r="9.1978254" />
+ <linearGradient
+ id="linearGradient48327-1">
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="0"
+ id="stop48329-23" />
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="1"
+ id="stop48331-3" />
+ </linearGradient>
+ <linearGradient
+ y2="118.69846"
+ x2="132.35237"
+ y1="111.38132"
+ x1="125.20553"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient37646-4"
+ xlink:href="#linearGradient10069-74-1"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient10069-74-1">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-0-1" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-9-3" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-7409-3-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-48-8-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-82-6-27" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-7409-3-7"
+ id="linearGradient38313-7"
+ gradientUnits="userSpaceOnUse"
+ x1="125.81818"
+ y1="111.81818"
+ x2="143.88347"
+ y2="129.27184" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-7409-3-7"
+ id="linearGradient37677"
+ gradientUnits="userSpaceOnUse"
+ x1="130.60338"
+ y1="115.87343"
+ x2="143.88347"
+ y2="129.27184" />
+ <linearGradient
+ id="linearGradient319-19">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-865" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-02" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069-8-3-3">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-9-8-7" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-2-7-1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-95-2-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-43-7-3" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-12-7-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient21327-6">
+ <stop
+ style="stop-color:#1e3e70;stop-opacity:1;"
+ offset="0"
+ id="stop21329-3" />
+ <stop
+ style="stop-color:#1e3e70;stop-opacity:0;"
+ offset="1"
+ id="stop21331-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient20055-8-4">
+ <stop
+ id="stop20057-8-0"
+ offset="0"
+ style="stop-color:#0a2a5a;stop-opacity:1;" />
+ <stop
+ id="stop20059-2-0"
+ offset="1"
+ style="stop-color:#3771c8;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient39088">
+ <stop
+ id="stop39090"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop39092"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610-83">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-24" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-11" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069-95">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-10" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-64" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient11871-3">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop11873-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop11875-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069-3">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-87" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-42" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39630"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="121.22078"
+ y2="56.357628" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39632"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(207,-246.99988)"
+ x1="-56.5"
+ y1="342.0625"
+ x2="-49"
+ y2="341" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40171"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="120.06789"
+ y2="54.6674" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40173"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40175"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,13)"
+ x1="-56.8125"
+ y1="329.06256"
+ x2="-47.214466"
+ y2="329.26965" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40280"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="120.06789"
+ y2="54.6674" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40282"
+ gradientUnits="userSpaceOnUse"
+ x1="-56.5"
+ y1="340.32199"
+ x2="-56.5"
+ y2="348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40284"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,13)"
+ x1="-56.8125"
+ y1="329.06256"
+ x2="-47.214466"
+ y2="329.26965" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient38689"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-420,490.00041)"
+ x1="301.5"
+ y1="-105.87541"
+ x2="340"
+ y2="-65.250412" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient38693"
+ gradientUnits="userSpaceOnUse"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient38695"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(6,0)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient38697"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,6)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient38701"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(6,6)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-7"
+ id="linearGradient38703"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(24,-6)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38706"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,-1,-157,821.03125)"
+ x1="-90.5"
+ y1="413.51562"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient38720"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.3846148,0,0,1,-211.38442,490.00041)"
+ x1="301.5"
+ y1="-105.87541"
+ x2="340"
+ y2="-65.250412" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient38723"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(8,0)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient38725"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(8,6)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-7"
+ id="linearGradient38727"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(24,-6)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38729"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,-1,-156,821.03125)"
+ x1="-89.75"
+ y1="413.98114"
+ x2="-86.75"
+ y2="416.32614" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-7"
+ id="linearGradient38731"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(24,-2.4825165)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient38736"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,-1,-156,824.54874)"
+ x1="-89.75"
+ y1="413.98114"
+ x2="-86.75"
+ y2="416.32614" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient39199"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-420,490.00041)"
+ x1="301.5"
+ y1="-105.87541"
+ x2="340"
+ y2="-65.250412" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39201"
+ gradientUnits="userSpaceOnUse"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39203"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(6,0)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39205"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,6)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39207"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(6,6)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient39246"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-420,490.00041)"
+ x1="301.5"
+ y1="-105.87541"
+ x2="340"
+ y2="-65.250412" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39248"
+ gradientUnits="userSpaceOnUse"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39252"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(6,0)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39255"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,6)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient39259"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(6,6)"
+ x1="-97"
+ y1="408"
+ x2="-88"
+ y2="413.51562" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-83"
+ id="linearGradient38961"
+ gradientUnits="userSpaceOnUse"
+ x1="488.5"
+ y1="568"
+ x2="495"
+ y2="568" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask38956">
+ <rect
+ style="fill:url(#linearGradient38961);stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect38958"
+ width="16"
+ height="12"
+ x="488"
+ y="560"
+ rx="0"
+ ry="0" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-83"
+ id="linearGradient39115"
+ gradientUnits="userSpaceOnUse"
+ x1="487.2518"
+ y1="531.95105"
+ x2="490.65796"
+ y2="580.63715" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient11871-3"
+ id="linearGradient39117"
+ gradientUnits="userSpaceOnUse"
+ x1="496.49335"
+ y1="537.78113"
+ x2="498.40021"
+ y2="540.13623" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient11871-3"
+ id="linearGradient39119"
+ gradientUnits="userSpaceOnUse"
+ x1="495.85294"
+ y1="541.69116"
+ x2="495.25"
+ y2="539.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-3"
+ id="linearGradient39122"
+ gradientUnits="userSpaceOnUse"
+ x1="494.38467"
+ y1="532.42651"
+ x2="496.21078"
+ y2="541.02698" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40703"
+ id="linearGradient39261"
+ gradientUnits="userSpaceOnUse"
+ x1="122.25188"
+ y1="106.08706"
+ x2="147.08464"
+ y2="134.12131" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39263"
+ gradientUnits="userSpaceOnUse"
+ x1="116.75861"
+ y1="97.375854"
+ x2="145.729"
+ y2="137.52937" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient39265"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ id="linearGradient319-46">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-03" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-62" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-46"
+ id="linearGradient39508"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-20,0)"
+ x1="39.102718"
+ y1="641.73358"
+ x2="58.680996"
+ y2="661.93829" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient43807"
+ id="linearGradient39518"
+ gradientUnits="userSpaceOnUse"
+ x1="648.09674"
+ y1="355.85541"
+ x2="634.09503"
+ y2="341.23715" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient39088"
+ id="linearGradient39520"
+ gradientUnits="userSpaceOnUse"
+ x1="696.63055"
+ y1="403.93069"
+ x2="643.71313"
+ y2="349.93216" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-95"
+ id="linearGradient39523"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8461524,0,0,0.8461523,99.385524,54.308237)"
+ x1="633.10468"
+ y1="338.95337"
+ x2="649.69073"
+ y2="354.92981" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient39716"
+ gradientUnits="userSpaceOnUse"
+ x1="121.80637"
+ y1="106.4641"
+ x2="142.1468"
+ y2="132.44617" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient39718"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40189"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9998599,0,0,0.9960071,131.027,-79.5885)"
+ x1="57.347244"
+ y1="82.75322"
+ x2="86.00116"
+ y2="112.03586" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40202"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166695,0,0,0.9203753,136.97426,-72.21433)"
+ x1="80.60067"
+ y1="108.47212"
+ x2="68.0271"
+ y2="94.239906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40295"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166695,0,0,0.9203753,136.97426,-72.21433)"
+ x1="80.60067"
+ y1="108.47212"
+ x2="68.0271"
+ y2="94.239906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient40297"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9998599,0,0,0.9960071,131.027,-79.5885)"
+ x1="57.347244"
+ y1="82.75322"
+ x2="86.00116"
+ y2="112.03586" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask40306">
+ <path
+ id="path40308"
+ d="m 195,11.00001 0,14 0.5,0 13.5,-13.5 0,-0.5 -14,0 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:none"
+ sodipodi:nodetypes="cccccc"
+ inkscape:connector-curvature="0" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40703-5-5"
+ id="linearGradient39261-4-5"
+ gradientUnits="userSpaceOnUse"
+ x1="128.09367"
+ y1="112.43961"
+ x2="145.20987"
+ y2="133.4879" />
+ <linearGradient
+ id="linearGradient40703-5-5">
+ <stop
+ style="stop-color:#143564;stop-opacity:1;"
+ offset="0"
+ id="stop40705-8-2" />
+ <stop
+ style="stop-color:#c1d7f8;stop-opacity:1;"
+ offset="1"
+ id="stop40707-8-7" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient38252-9">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop38254-3" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop38256-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-74-9-1"
+ id="linearGradient40511-7-9-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,-270.46874,9.59825)"
+ x1="256.14325"
+ y1="5.6181068"
+ x2="278.79254"
+ y2="29.688427" />
+ <linearGradient
+ id="linearGradient1610-74-9-1">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-0-8-7" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-9-3-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334-8-6-5"
+ id="linearGradient40507-4-8-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-114,-208)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ id="linearGradient58334-8-6-5">
+ <stop
+ id="stop58336-8-9-2"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.87628865;" />
+ <stop
+ id="stop58338-24-8-7"
+ offset="1.0000000"
+ style="stop-color:#fffffe;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-5-6-1"
+ id="radialGradient40649-2-6-6"
+ cx="-27.749987"
+ cy="32.615383"
+ fx="-27.749987"
+ fy="32.615383"
+ r="5.5"
+ gradientTransform="matrix(0.4545454,0.3636364,-0.3862167,0.4827711,-2.5397644,26.345139)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-5-6-1">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-17-2-4" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-11-3-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-5-6-1"
+ id="linearGradient40502-7-8-3"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-784,-271)"
+ x1="754"
+ y1="300.5"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-5-6-2"
+ id="linearGradient40635-7-2-2"
+ gradientUnits="userSpaceOnUse"
+ x1="125.99933"
+ y1="111.2683"
+ x2="134.91479"
+ y2="122.36016" />
+ <linearGradient
+ id="linearGradient319-5-6-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-761-2-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-89-7-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-5-6-2"
+ id="linearGradient40637-9-5-8"
+ gradientUnits="userSpaceOnUse"
+ x1="126.72586"
+ y1="112.53999"
+ x2="134.91479"
+ y2="122.36016" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13973-3-7-8"
+ id="linearGradient40639-1-2-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(19.367382,0)"
+ x1="111.2239"
+ y1="112.62726"
+ x2="99.628899"
+ y2="99.029617" />
+ <linearGradient
+ id="linearGradient13973-3-7-8">
+ <stop
+ style="stop-color:#3c4c18;stop-opacity:1;"
+ offset="0"
+ id="stop13975-1-8-9" />
+ <stop
+ style="stop-color:#9aff31;stop-opacity:0;"
+ offset="1"
+ id="stop13977-2-0-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-5-6-2"
+ id="linearGradient40641-9-2-7"
+ gradientUnits="userSpaceOnUse"
+ x1="127.63637"
+ y1="114.2303"
+ x2="143.69765"
+ y2="131.03783" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-74-9-1"
+ id="linearGradient41638-8-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,-270.46874,9.59825)"
+ x1="256.14325"
+ y1="5.6181068"
+ x2="278.79254"
+ y2="29.688427" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334-8-6-5"
+ id="linearGradient41640-2-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-114,-208)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-5-6-1"
+ id="radialGradient41642-5-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4545454,0.3636364,-0.3862167,0.4827711,-2.5397644,26.345139)"
+ cx="-27.749987"
+ cy="32.615383"
+ fx="-27.749987"
+ fy="32.615383"
+ r="5.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-5-6-1"
+ id="linearGradient41644-5-4"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-784,-271)"
+ x1="754"
+ y1="300.5"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-3-0-7-6"
+ id="linearGradient40875-3-9-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.695652,0,0,0.869703,-44.93485,-114.66358)"
+ x1="188.77448"
+ y1="259.745"
+ x2="164.0939"
+ y2="242.22473" />
+ <linearGradient
+ id="linearGradient37542-3-0-7-6">
+ <stop
+ id="stop37544-1-6-6-5"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-2-1-7-0"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-34-8-7-0"
+ id="linearGradient40877-5-5-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(357.00001,373)"
+ x1="-287.75"
+ y1="-276.75"
+ x2="-276"
+ y2="-264.875" />
+ <linearGradient
+ id="linearGradient319-34-8-7-0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-11-9-8-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-38-3-1-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-3-0-7-6"
+ id="linearGradient40879-9-8-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.608695,0,0,0.760996,-26.1305,-84.76968)"
+ x1="130.70929"
+ y1="210.78392"
+ x2="171.50414"
+ y2="248.54021" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-34-8-7-0"
+ id="linearGradient40881-8-0-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(361.00001,376)"
+ x1="-283"
+ y1="-272"
+ x2="-277.01501"
+ y2="-267.26749" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-7-6-7-4"
+ id="radialGradient40883-4-0-3"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.06118084,-0.8594818,2.4629674,-0.1753088,-259.40057,190.15309)"
+ cx="77.721619"
+ cy="104.09358"
+ fx="77.721619"
+ fy="104.09358"
+ r="3.9999998" />
+ <linearGradient
+ id="linearGradient10069-7-6-7-4">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-81-3-2-4" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-6-7-5-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-3-0-7-6"
+ id="linearGradient39136-2-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.695652,0,0,0.869703,-44.93485,-114.66358)"
+ x1="188.77448"
+ y1="259.745"
+ x2="164.0939"
+ y2="242.22473" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-34-8-7-0"
+ id="linearGradient39138-8-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(357.00001,373)"
+ x1="-287.75"
+ y1="-276.75"
+ x2="-276"
+ y2="-264.875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-3-0-7-6"
+ id="linearGradient39140-6-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.608695,0,0,0.760996,-26.1305,-84.76968)"
+ x1="130.70929"
+ y1="210.78392"
+ x2="174.35753"
+ y2="250.6842" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-34-8-7-0"
+ id="linearGradient39143-0-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(361.00001,376)"
+ x1="-283"
+ y1="-272"
+ x2="-277.01501"
+ y2="-267.26749" />
+ <linearGradient
+ id="linearGradient319-17-1-6">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-115-1-5" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-27-3-7" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-17-1-6"
+ id="linearGradient40679"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.7972867,-259.00009,90.24189)"
+ x1="255.63673"
+ y1="99.513062"
+ x2="275.1503"
+ y2="129.36641" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient25417"
+ id="linearGradient40731"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.997161,-259.00079,67.35344)"
+ x1="280.0918"
+ y1="129.28557"
+ x2="267.20212"
+ y2="116.41341" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-17-1-6"
+ id="linearGradient40733"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.7972867,-259.00009,90.24189)"
+ x1="255.63673"
+ y1="99.513062"
+ x2="275.1503"
+ y2="129.36641" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-17-1-6-7"
+ id="linearGradient40733-0"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.7972867,-259.00009,90.24189)"
+ x1="255.63673"
+ y1="99.513062"
+ x2="275.1503"
+ y2="129.36641" />
+ <linearGradient
+ id="linearGradient319-17-1-6-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-115-1-5-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-27-3-7-7" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-17-1-6-8"
+ id="linearGradient40733-03"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.7972867,-259.00009,90.24189)"
+ x1="255.63673"
+ y1="99.513062"
+ x2="275.1503"
+ y2="129.36641" />
+ <linearGradient
+ id="linearGradient319-17-1-6-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-115-1-5-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-27-3-7-1" />
+ </linearGradient>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath40897">
+ <rect
+ y="198"
+ x="-41"
+ height="16"
+ width="15"
+ id="rect40899"
+ style="opacity:0.45;fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="scale(-1,1)" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath40902">
+ <rect
+ y="197"
+ x="-22"
+ height="17"
+ width="15"
+ id="rect40904"
+ style="opacity:0.45;fill:#80b3ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.29999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ transform="scale(-1,1)" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient38478"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(254.01612,-211.00101)"
+ x1="96.824379"
+ y1="393.90298"
+ x2="94.246101"
+ y2="391.21976" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask38474">
+ <rect
+ style="fill:url(#linearGradient38478);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect38476"
+ width="15"
+ height="15"
+ x="343.01611"
+ y="174.99901" />
+ </mask>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient44318"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.050372,0,0,1.050372,-3.551238,-0.730396)"
+ cx="70.5"
+ cy="14.5"
+ fx="70.5"
+ fy="14.5"
+ r="1.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient44320"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5399935,0.3131662,-0.3907892,0.5793905,38.141764,-16.056748)"
+ cx="70.470596"
+ cy="14.649424"
+ fx="70.470596"
+ fy="14.649424"
+ r="5.5192375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-19"
+ id="linearGradient42988"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,239.34332,-149.78578)"
+ x1="104.90227"
+ y1="53.227627"
+ x2="121.22078"
+ y2="56.357628" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-19"
+ id="linearGradient42990"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(207,-246.99988)"
+ x1="-56.5"
+ y1="342.0625"
+ x2="-49"
+ y2="341" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-8-3-3"
+ id="linearGradient42992"
+ gradientUnits="userSpaceOnUse"
+ x1="126.55782"
+ y1="113.57294"
+ x2="132.41052"
+ y2="118.81034" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-95-2-7"
+ id="linearGradient42994"
+ gradientUnits="userSpaceOnUse"
+ x1="132"
+ y1="117.26753"
+ x2="142.72656"
+ y2="127.72736" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-8-3-3"
+ id="linearGradient42996"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(4.9999967,20)"
+ x1="-114.75"
+ y1="546.5"
+ x2="-110.5"
+ y2="542.5" />
+ <linearGradient
+ id="linearGradient44627">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop44629" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop44631" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10069-9-7-4-74">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-5-4-5-0" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-43-0-5-9" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient44939-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop44941-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop44943-2" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient44402"
+ gradientUnits="userSpaceOnUse"
+ x1="351.15625"
+ y1="108.35222"
+ x2="345.40625"
+ y2="108.00847" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient44404"
+ gradientUnits="userSpaceOnUse"
+ x1="351.71875"
+ y1="106.93575"
+ x2="347.1875"
+ y2="106.7795" />
+ <filter
+ inkscape:collect="always"
+ id="filter44473"
+ x="-0.12578467"
+ width="1.2515693"
+ y="-0.11472401"
+ height="1.229448"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.81235925"
+ id="feGaussianBlur44475" />
+ </filter>
+ <filter
+ inkscape:collect="always"
+ id="filter44477"
+ x="-0.12176471"
+ width="1.2435294"
+ y="-0.11828571"
+ height="1.2365714"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.8625"
+ id="feGaussianBlur44479" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient44485"
+ gradientUnits="userSpaceOnUse"
+ x1="279.75"
+ y1="101.5"
+ x2="284.5"
+ y2="106.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient44942"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-21)"
+ x1="351.71875"
+ y1="106.93575"
+ x2="339.125"
+ y2="105.092" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient44944"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,-1,698,183)"
+ x1="351.15625"
+ y1="108.35222"
+ x2="336.40625"
+ y2="106.19597" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient44950"
+ gradientUnits="userSpaceOnUse"
+ x1="279"
+ y1="102"
+ x2="281.75"
+ y2="102"
+ gradientTransform="matrix(-1,0,0,1,593.02125,-1.8e-6)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient44954"
+ gradientUnits="userSpaceOnUse"
+ x1="279.75"
+ y1="101.5"
+ x2="283"
+ y2="105.5"
+ gradientTransform="matrix(0,1,1,0,225,-182.99437)" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath45147">
+ <path
+ sodipodi:nodetypes="ccccccccccccccccccccccc"
+ id="path45149"
+ d="m 5,261 13,0 0,1 -1,0 0,1 1,0 0,1 -1,0 0,1 -1,0 0,2 2,0 0,-1 1,0 0,-1 1,0 0,1 1,0 0,-1 1,0 0,13 -17,0 0,-17 z"
+ style="opacity:0.2;fill:#3771c8;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.0999999;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient45220"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,221,10)"
+ x1="115.84575"
+ y1="10.8125"
+ x2="106.125"
+ y2="19.9375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38252-9"
+ id="linearGradient45283"
+ gradientUnits="userSpaceOnUse"
+ x1="125.86876"
+ y1="111.85698"
+ x2="130.88379"
+ y2="121.70699" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38252-9"
+ id="linearGradient45285"
+ gradientUnits="userSpaceOnUse"
+ x1="134.78751"
+ y1="122.29202"
+ x2="132.60205"
+ y2="117.96092" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-4-74"
+ id="radialGradient45309"
+ cx="336.42892"
+ cy="611.10455"
+ fx="336.42892"
+ fy="611.10455"
+ r="5.9852905"
+ gradientTransform="matrix(1.0070601,0.03386866,-0.03770425,1.1211085,20.665977,-85.772965)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44627"
+ id="linearGradient43826"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,1444.9824,-215)"
+ x1="689.47357"
+ y1="427"
+ x2="685.47357"
+ y2="427" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask43822">
+ <rect
+ y="208"
+ x="754"
+ height="9"
+ width="12"
+ id="rect43824"
+ style="opacity:0.93999993;fill:url(#linearGradient43826);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient43856"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,61.53822,346.48241)"
+ x1="246.89435"
+ y1="-4.4418921"
+ x2="277.68143"
+ y2="30.743095" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient43858"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(218.01612,129)"
+ x1="87.03125"
+ y1="241"
+ x2="92.8125"
+ y2="245.625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient46780"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,140,-415)"
+ x1="172.5625"
+ y1="601.5"
+ x2="159.13864"
+ y2="585.28772" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient46782"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,237.98388,150.25)"
+ x1="249.64528"
+ y1="1.5973248"
+ x2="271.98389"
+ y2="35.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient46784"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,140,-415)"
+ x1="172.5625"
+ y1="601.5"
+ x2="159.13864"
+ y2="585.28772" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient46786"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,237.98388,150.25)"
+ x1="249.64528"
+ y1="1.5973248"
+ x2="271.98389"
+ y2="35.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient46818"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,140,-415)"
+ x1="172.5625"
+ y1="601.5"
+ x2="159.13864"
+ y2="585.28772" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient46820"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,237.98388,150.25)"
+ x1="249.64528"
+ y1="1.5973248"
+ x2="271.98389"
+ y2="35.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient46822"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,140,-415)"
+ x1="172.5625"
+ y1="601.5"
+ x2="159.13864"
+ y2="585.28772" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient46824"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,237.98388,150.25)"
+ x1="249.64528"
+ y1="1.5973248"
+ x2="271.98389"
+ y2="35.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient46990"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,140,-415)"
+ x1="172.5625"
+ y1="601.5"
+ x2="159.13864"
+ y2="585.28772" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient46992"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,237.98388,150.25)"
+ x1="249.64528"
+ y1="1.5973248"
+ x2="271.98389"
+ y2="35.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient46994"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,140,-415)"
+ x1="172.5625"
+ y1="601.5"
+ x2="159.13864"
+ y2="585.28772" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient46996"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,237.98388,150.25)"
+ x1="249.64528"
+ y1="1.5973248"
+ x2="271.98389"
+ y2="35.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient46998"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,140,-415)"
+ x1="172.5625"
+ y1="601.5"
+ x2="159.13864"
+ y2="585.28772" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient47000"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,237.98388,150.25)"
+ x1="249.64528"
+ y1="1.5973248"
+ x2="271.98389"
+ y2="35.75" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient25048"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5274943,0,0,0.7696585,194.81546,86.715119)"
+ cx="412.10059"
+ cy="375.96332"
+ fx="412.10059"
+ fy="375.96332"
+ r="4.4262571" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient25108"
+ id="linearGradient25106"
+ gradientUnits="userSpaceOnUse"
+ x1="408.91928"
+ y1="373.01221"
+ x2="410.55432"
+ y2="375.5058" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient25108"
+ id="linearGradient25117"
+ gradientUnits="userSpaceOnUse"
+ x1="411.05389"
+ y1="375.39175"
+ x2="407.62576"
+ y2="370.21317" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient25449"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,-346.7085,428.4841)"
+ x1="352.98236"
+ y1="314.11398"
+ x2="353.72073"
+ y2="297.92099" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient25108"
+ id="linearGradient25451"
+ gradientUnits="userSpaceOnUse"
+ x1="436.54755"
+ y1="524.30481"
+ x2="434.49387"
+ y2="519.46057" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient25108"
+ id="linearGradient25453"
+ gradientUnits="userSpaceOnUse"
+ x1="432.0849"
+ y1="524.97125"
+ x2="433"
+ y2="526" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="radialGradient25457"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5274943,0,0,0.7696585,194.81546,86.715119)"
+ cx="410.73904"
+ cy="370.11554"
+ fx="410.73904"
+ fy="370.11554"
+ r="4.4262571" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient23543"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,1,0,225,-182.99437)"
+ x1="279.75"
+ y1="101.5"
+ x2="283"
+ y2="105.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient23557"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,1,0,225,-182.99437)"
+ x1="279"
+ y1="102"
+ x2="281.75"
+ y2="102" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8"
+ id="linearGradient23559"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,1,0,225,-182.99437)"
+ x1="292.25"
+ y1="106.5"
+ x2="289.5"
+ y2="109.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24343"
+ id="linearGradient24341"
+ x1="413.9498"
+ y1="386.45807"
+ x2="406.7699"
+ y2="374.42419"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24343"
+ id="linearGradient24349"
+ gradientUnits="userSpaceOnUse"
+ x1="403.9577"
+ y1="367.62839"
+ x2="413.98795"
+ y2="374.07153" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient21327-6"
+ id="radialGradient24354"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6402148,-1.1088846,0.8413297,0.4857498,104.42892,800.46622)"
+ cx="409.55594"
+ cy="52.367992"
+ fx="409.55594"
+ fy="52.367992"
+ r="3.8798895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient34157"
+ id="linearGradient24511"
+ gradientUnits="userSpaceOnUse"
+ x1="270.66064"
+ y1="68.113258"
+ x2="257.38638"
+ y2="81.382545" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient24513"
+ gradientUnits="userSpaceOnUse"
+ x1="256.90005"
+ y1="80.100891"
+ x2="262.43726"
+ y2="74.562462" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29149"
+ id="radialGradient24515"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.217888"
+ cy="500.66806"
+ fx="75.217888"
+ fy="500.66806"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient18821"
+ id="radialGradient24517"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8728692,0.8400852,-1.1671853,1.2200916,594.18579,-173.07738)"
+ cx="75.554794"
+ cy="500.26215"
+ fx="75.554794"
+ fy="500.26215"
+ r="3.1650217" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient24519"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6691529,0,4.3047361e-8,0.6954014,84.50351,24.951375)"
+ cx="259.02887"
+ cy="77.962585"
+ fx="259.02887"
+ fy="77.962585"
+ r="3.5" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="radialGradient24523"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.3879142,0,8.9286134e-8,1.4423572,-101.87942,-32.970267)"
+ cx="259.55096"
+ cy="77.188034"
+ fx="259.55096"
+ fy="77.188034"
+ r="3.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30321"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)"
+ x1="240.70209"
+ y1="-9.4293213"
+ x2="276.89801"
+ y2="31.515814" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient30323"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-47.00001,58.00194)"
+ x1="160.14388"
+ y1="376.27383"
+ x2="174.29811"
+ y2="383.69843" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient30368"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)"
+ x1="236.94902"
+ y1="-14.103641"
+ x2="276.89801"
+ y2="31.515814" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="linearGradient30370"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-47.00001,58.00194)"
+ x1="160.14388"
+ y1="376.27383"
+ x2="174.29811"
+ y2="383.69843" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30208"
+ id="linearGradient25056"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-1297,-948)"
+ x1="1663.8125"
+ y1="722"
+ x2="1661.8125"
+ y2="726.37006" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19425"
+ id="radialGradient25058"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.1378252,-0.2988982,2.5269117,1.1651875,-1689.2674,-563.64056)"
+ cx="1662.2664"
+ cy="722.19189"
+ fx="1662.2664"
+ fy="722.19189"
+ r="5.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient25060"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8167109,0,0,0.8433415,-1256.7473,-918.72044)"
+ x1="1984.3658"
+ y1="827.77124"
+ x2="1979.2772"
+ y2="827.32849" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient29407"
+ gradientUnits="userSpaceOnUse"
+ x1="98.858559"
+ y1="80.045052"
+ x2="135.00615"
+ y2="122.92735" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient29409"
+ gradientUnits="userSpaceOnUse"
+ x1="130.75166"
+ y1="245.03757"
+ x2="129.24866"
+ y2="243.31177" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient29411"
+ gradientUnits="userSpaceOnUse"
+ x1="126.37006"
+ y1="112.31642"
+ x2="144.22272"
+ y2="129.82761" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient29413"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ id="linearGradient44939-8-7-1-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop44941-8-4-5-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop44943-2-0-2-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-7"
+ id="linearGradient37396-1"
+ gradientUnits="userSpaceOnUse"
+ x1="389.73953"
+ y1="220.84622"
+ x2="389.59052"
+ y2="248.09296"
+ gradientTransform="matrix(-1,0,0,1,780.92531,0)" />
+ <linearGradient
+ id="linearGradient37542-7">
+ <stop
+ id="stop37544-40"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-94"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-5"
+ id="linearGradient15742-5"
+ 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="linearGradient37542-5">
+ <stop
+ id="stop37544-1"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-71"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27854"
+ id="linearGradient27860"
+ x1="392.02036"
+ y1="241.13428"
+ x2="386.30408"
+ y2="241.31801"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient27872"
+ gradientUnits="userSpaceOnUse"
+ x1="392.0101"
+ y1="224.99998"
+ x2="392.0101"
+ y2="249.99998"
+ gradientTransform="matrix(-1,0,0,1,782.02022,0)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient27854"
+ id="linearGradient27874"
+ 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"
+ xlink:href="#linearGradient37542-5"
+ id="linearGradient27886"
+ 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
+ inkscape:collect="always"
+ xlink:href="#linearGradient27896"
+ id="linearGradient27902"
+ x1="388.70071"
+ y1="244.85669"
+ x2="391.17557"
+ y2="249.54126"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient10069-9-71">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-5-1" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-43-5" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient23974-2">
+ <stop
+ id="stop23976-2"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop23978-1"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath28964">
+ <path
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Tata\Pulpit\4.png"
+ sodipodi:nodetypes="ccccc"
+ style="fill:url(#linearGradient28968);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;enable-background:new"
+ d="m 117.50984,228.63415 0,-15.01646 11.71735,5.49383 0,15.38271 -11.71735,-5.86008 z"
+ id="path28966"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974-2"
+ id="linearGradient28968"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.4646688,0,0,1.4650206,168.77325,-157.03253)"
+ x1="-38.103703"
+ y1="266.11719"
+ x2="-20.826464"
+ y2="253.23859" />
+ <linearGradient
+ id="linearGradient319-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-761" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-7"
+ id="linearGradient29424"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.4646688,0,0,1.4650206,168.77325,-157.03253)"
+ x1="-26.511335"
+ y1="257.99881"
+ x2="-30.075666"
+ y2="259.87677" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask29419">
+ <path
+ id="path29422"
+ d="m 117.50984,229.00041 0,-15.38272 11.71735,5.49383 0,15.74897 -11.71735,-5.86008 z"
+ style="opacity:0.5;fill:url(#linearGradient29424);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;enable-background:new"
+ 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" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient23974"
+ id="linearGradient29988"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,10)"
+ x1="-35.153767"
+ y1="271.58572"
+ x2="-23.636715"
+ y2="252.03563" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-5"
+ id="linearGradient29990"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-113.93222,176.71918)"
+ x1="446.93222"
+ y1="105.28082"
+ x2="441.93222"
+ y2="120.28082" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-71"
+ id="linearGradient29994"
+ gradientUnits="userSpaceOnUse"
+ x1="123.80045"
+ y1="111.03492"
+ x2="131.72171"
+ y2="118.18078" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient21327-6-8"
+ id="linearGradient29773-5"
+ gradientUnits="userSpaceOnUse"
+ x1="124.78239"
+ y1="111.13178"
+ x2="132.99687"
+ y2="118.98331" />
+ <linearGradient
+ id="linearGradient21327-6-8">
+ <stop
+ style="stop-color:#1e3e70;stop-opacity:1;"
+ offset="0"
+ id="stop21329-3-4" />
+ <stop
+ style="stop-color:#1e3e70;stop-opacity:0;"
+ offset="1"
+ id="stop21331-4-0" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient28526">
+ <stop
+ id="stop28528"
+ offset="0"
+ style="stop-color:#2561b7;stop-opacity:1;" />
+ <stop
+ id="stop28530"
+ offset="1"
+ style="stop-color:#f9fbff;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-62">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-90" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-4" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1610-52-2">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-32-8" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-46-8" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient319-62-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-90-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-4-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient29334"
+ gradientUnits="userSpaceOnUse"
+ x1="121.74819"
+ y1="104.14172"
+ x2="140.18503"
+ y2="126.89457" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069"
+ id="linearGradient29336"
+ gradientUnits="userSpaceOnUse"
+ x1="155.10138"
+ y1="91.071259"
+ x2="122.40444"
+ y2="127.60542" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient24000"
+ id="linearGradient29338"
+ gradientUnits="userSpaceOnUse"
+ x1="124.66362"
+ y1="126.19594"
+ x2="132"
+ y2="118" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient29340"
+ gradientUnits="userSpaceOnUse"
+ x1="124.28249"
+ y1="126.88889"
+ x2="133.53401"
+ y2="116.55647" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient29342"
+ gradientUnits="userSpaceOnUse"
+ x1="147.25899"
+ y1="101.45953"
+ x2="130.82327"
+ y2="119.554" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient28574"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,-1,0,449.99999,1678)"
+ x1="1138.1963"
+ y1="287.70486"
+ x2="1146.6705"
+ y2="288.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient28577"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,-1,0,558.99999,1286)"
+ x1="757.2467"
+ y1="367.52411"
+ x2="740.30865"
+ y2="405.3895" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient28580"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,-1,0,558.99999,1288)"
+ x1="745.48267"
+ y1="396.45972"
+ x2="737.62225"
+ y2="401.90442" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500"
+ id="linearGradient28583"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,1,0,-239.00001,1286)"
+ x1="743"
+ y1="402"
+ x2="752"
+ y2="400" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38845"
+ id="linearGradient28589"
+ gradientUnits="userSpaceOnUse"
+ x1="162.41054"
+ y1="413.87982"
+ x2="161.83331"
+ y2="406.47784"
+ gradientTransform="matrix(0,1,-1,0,574.99991,384.00001)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38831"
+ id="linearGradient28593"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,-1,0,558.99999,1288)"
+ x1="743.87036"
+ y1="396.04428"
+ x2="744.1059"
+ y2="423.54419" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient28600"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,1,-1,0,719.99999,383.00001)"
+ x1="148.56801"
+ y1="544.21143"
+ x2="163.11441"
+ y2="569.18829" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient38831"
+ id="linearGradient28603"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-1,-1,0,449.99999,1678)"
+ x1="1141.2856"
+ y1="288.19919"
+ x2="1146.2682"
+ y2="291.35333" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-52-2"
+ id="radialGradient29805"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.94105289,0.01178942,-0.01073736,0.8570756,238.4669,249.70522)"
+ cx="-30.028414"
+ cy="19.425121"
+ fx="-30.028414"
+ fy="19.425121"
+ r="7" />
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask29801">
+ <rect
+ style="opacity:0.35;color:#000000;fill:url(#radialGradient29805);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.71217775;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
+ id="rect29803"
+ width="15"
+ height="16"
+ x="204"
+ y="257" />
+ </mask>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-7"
+ id="linearGradient29884"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1,0,0,1,780.92531,0)"
+ x1="389.73953"
+ y1="220.84622"
+ x2="389.59052"
+ y2="248.09296" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient29886"
+ gradientUnits="userSpaceOnUse"
+ x1="391.62881"
+ y1="243.48854"
+ x2="386.13718"
+ y2="244.68996" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath50172-0">
+ <path
+ id="path50174-8"
+ d="m -177.34375,498 a 1.001098,1.001098 0 1 0 0.0937,2 l 3.65625,0 -4.25,5.9375 a 1.0001,1.0001 0 0 0 -0.1875,0.59375 l 0,0.5 a 1.0001,1.0001 0 0 0 1,1 L -171.75,508 a 1.0001,1.0001 0 1 0 0,-2 l -3.6875,0.0312 4.25,-5.9375 A 1.0001,1.0001 0 0 0 -171,499.5 l 0,-0.5 a 1.0001,1.0001 0 0 0 -1,-1 l -5.25,0 a 1.0001,1.0001 0 0 0 -0.0937,0 z"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <radialGradient
+ id="radialGradient16142-7"
+ cx="20.892099"
+ cy="64.567902"
+ r="5.257"
+ fx="20.892099"
+ fy="64.567902"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ offset="0"
+ style="stop-color:#F0F0F0"
+ id="stop16144-4" />
+ <stop
+ offset="1"
+ style="stop-color:#474747"
+ id="stop16146-0" />
+ </radialGradient>
+ <linearGradient
+ id="linearGradient37542-78">
+ <stop
+ id="stop37544-2"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-78"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient9030-2">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop9032-0" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop9034-89" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient37542-04-82">
+ <stop
+ id="stop37544-9-0"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-4-5"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient9030-38-2">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop9032-6-7" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop9034-9-6" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient30766-8"
+ inkscape:collect="always">
+ <stop
+ id="stop30768-7"
+ offset="0"
+ style="stop-color:#be0000;stop-opacity:1" />
+ <stop
+ id="stop30770-8"
+ offset="1"
+ style="stop-color:#ff5108;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient30752-0">
+ <stop
+ style="stop-color:#0c1b63;stop-opacity:1;"
+ offset="0"
+ id="stop30754-9" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1"
+ id="stop30756-5" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32140"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-64,-10)"
+ x1="18.773417"
+ y1="6.2494373"
+ x2="6.9718256"
+ y2="17.82831" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32142"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.701513,0.712657,0.712657,0.701513,50.5916,-449.6745)"
+ x1="385.62408"
+ y1="244.3396"
+ x2="401.63013"
+ y2="244.38875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32144"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-65.00001,-10.749995)"
+ x1="61.032951"
+ y1="5.9830923"
+ x2="46.491322"
+ y2="20.147326" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32146"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.199998,0,0,1.199999,-74.19988,-12.499988)"
+ x1="59.02124"
+ y1="6.0129876"
+ x2="44.509518"
+ y2="20.110929" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32148"
+ gradientUnits="userSpaceOnUse"
+ x1="47.348152"
+ y1="-25.553123"
+ x2="53.567928"
+ y2="-31.095215" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#radialGradient16142-7"
+ id="linearGradient31946"
+ gradientUnits="userSpaceOnUse"
+ x1="-176.1799"
+ y1="508.33572"
+ x2="-193.07495"
+ y2="482.27924" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#radialGradient16142"
+ id="linearGradient31948"
+ gradientUnits="userSpaceOnUse"
+ x1="-178.00789"
+ y1="505.36523"
+ x2="-194.90294"
+ y2="479.30875" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-78"
+ id="linearGradient31950"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,-7.152175,20.92167)"
+ x1="155.37498"
+ y1="230.51552"
+ x2="181.25543"
+ y2="269.24564" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030-2"
+ id="linearGradient31952"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(81.000002,13.499998)"
+ x1="87.765625"
+ y1="242.39062"
+ x2="96"
+ y2="251.40294" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-04-82"
+ id="linearGradient31954"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.043478,0,0,0.956667,-354.13606,119.42158)"
+ x1="148.47061"
+ y1="217.28368"
+ x2="171.77303"
+ y2="250.87756" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030-38-2"
+ id="linearGradient31956"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(81.000002,13.499998)"
+ x1="-259.99872"
+ y1="340.81195"
+ x2="-253.90541"
+ y2="345.10736" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30766-8"
+ id="linearGradient31958"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0017964,0,0,0.99629977,-0.31613165,0.94171311)"
+ x1="167.51979"
+ y1="252.44223"
+ x2="170.78137"
+ y2="261.69635" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030-2"
+ id="linearGradient31960"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(81.000002,13.499998)"
+ x1="87.473038"
+ y1="238.21507"
+ x2="89.889603"
+ y2="243.80345" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30752-0"
+ id="linearGradient31962"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,10)"
+ x1="168.53265"
+ y1="244.52007"
+ x2="168.53265"
+ y2="239.5473" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient31964"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-237.5,45.5045)"
+ x1="263.35254"
+ y1="19.495501"
+ x2="275.43362"
+ y2="28.583914" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient31966"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-238,44.0045)"
+ x1="271.69839"
+ y1="22.713789"
+ x2="283.37738"
+ y2="36.874088" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient31968"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-243.5,51.5045)"
+ x1="260.25369"
+ y1="11.017987"
+ x2="275.43362"
+ y2="28.583914" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542"
+ id="linearGradient31970"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-244,50.0045)"
+ x1="271.69839"
+ y1="22.713789"
+ x2="283.37738"
+ y2="36.874088" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31972"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-57.00003,-165.99191)"
+ x1="85.853188"
+ y1="239.5473"
+ x2="90.563423"
+ y2="242.99191" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31974"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-51,-172)"
+ x1="88"
+ y1="240.90625"
+ x2="92.8125"
+ y2="245.625" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient28526"
+ id="linearGradient32236"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(423,225)"
+ x1="-175.72238"
+ y1="66.323799"
+ x2="-183.03308"
+ y2="66.235535" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20055-8-4"
+ id="linearGradient32238"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(423,225)"
+ x1="-174.51762"
+ y1="66.654762"
+ x2="-183.58472"
+ y2="65.917358" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-62"
+ id="linearGradient32240"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9098462,0,0,0.9414558,406.86085,228.58514)"
+ x1="-180.7581"
+ y1="63.445515"
+ x2="-169.07387"
+ y2="62.182106" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-62-8"
+ id="linearGradient32242"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2857143,0,0,0.787037,371.28571,304.80092)"
+ x1="-101"
+ y1="-16"
+ x2="-96.861107"
+ y2="-15.138513" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-62-8"
+ id="linearGradient32244"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.2857143,0,0,0.787037,371.28571,304.80092)"
+ x1="-101"
+ y1="-16"
+ x2="-96.705353"
+ y2="-15.562586" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29312"
+ id="linearGradient32246"
+ gradientUnits="userSpaceOnUse"
+ x1="242.99834"
+ y1="291.5047"
+ x2="244.75"
+ y2="291.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient29304"
+ id="linearGradient32248"
+ gradientUnits="userSpaceOnUse"
+ x1="245.20622"
+ y1="294.49902"
+ x2="243.5"
+ y2="294.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32296"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-52.983883,-129)"
+ x1="258"
+ y1="388"
+ x2="273"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32299"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-48.983883,-126)"
+ x1="259.75"
+ y1="388"
+ x2="273"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32301"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-47.000005,-120)"
+ x1="257.75"
+ y1="388"
+ x2="272"
+ y2="388" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32303"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9166695,0,0,0.9203753,-9.025729,344.78566)"
+ x1="80.60067"
+ y1="108.47212"
+ x2="68.0271"
+ y2="94.239906" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient13938"
+ id="linearGradient32305"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-14.983875,337)"
+ x1="68.361542"
+ y1="95.337166"
+ x2="88.785263"
+ y2="116.62141" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32307"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9998599,0,0,0.9960071,-15.972985,338.41149)"
+ x1="58.761654"
+ y1="84.330009"
+ x2="81.383331"
+ y2="108.06429" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient32353"
+ gradientUnits="userSpaceOnUse"
+ x1="114.15679"
+ y1="100.93772"
+ x2="137.5759"
+ y2="124.47867" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32355"
+ gradientUnits="userSpaceOnUse"
+ x1="131.12576"
+ y1="118"
+ x2="140.19273"
+ y2="125.82862" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32357"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9050931,-7.9558708e-4,0.00612764,0.9147058,39.488451,313.56226)"
+ x1="299.70026"
+ y1="408.49368"
+ x2="322.08145"
+ y2="429.53806" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32359"
+ gradientUnits="userSpaceOnUse"
+ x1="131.12576"
+ y1="118"
+ x2="140.19273"
+ y2="125.82862" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610"
+ id="linearGradient32426"
+ gradientUnits="userSpaceOnUse"
+ x1="114.15679"
+ y1="100.93772"
+ x2="137.5759"
+ y2="124.47867" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32428"
+ gradientUnits="userSpaceOnUse"
+ x1="131.12576"
+ y1="118"
+ x2="140.19273"
+ y2="125.82862" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9030"
+ id="linearGradient32430"
+ gradientUnits="userSpaceOnUse"
+ x1="190.68166"
+ y1="244.14676"
+ x2="174.75458"
+ y2="226.33672" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient32432"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.77915445,-6.9426235e-4,0.00527501,0.79821029,158.94945,341.39422)"
+ x1="299.70026"
+ y1="408.49368"
+ x2="322.08145"
+ y2="429.53806" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8-7-1-7"
+ id="linearGradient32434"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-1,73,792.5)"
+ x1="346"
+ y1="128.5"
+ x2="368"
+ y2="123.5" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31019"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,257.1483,118.6716)"
+ x1="85.548706"
+ y1="100.22395"
+ x2="85.347076"
+ y2="113.09817" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31025"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.72300056,-0.72300056,0.72300056,0.72300056,254.24127,118.38327)"
+ x1="85.548706"
+ y1="100.22395"
+ x2="85.347076"
+ y2="113.09817" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31055"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,257.1483,118.6716)"
+ x1="85.548706"
+ y1="100.22395"
+ x2="85.347076"
+ y2="113.09817" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31057"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.72300056,-0.72300056,0.72300056,0.72300056,254.24127,118.38327)"
+ x1="85.548706"
+ y1="100.22395"
+ x2="85.347076"
+ y2="113.09817" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31151"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,257.1483,118.6716)"
+ x1="85.548706"
+ y1="100.22395"
+ x2="85.347076"
+ y2="113.09817" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319"
+ id="linearGradient31153"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.72300056,-0.72300056,0.72300056,0.72300056,254.24127,118.38327)"
+ x1="85.548706"
+ y1="100.22395"
+ x2="84.95932"
+ y2="122.23821" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30958"
+ id="linearGradient31155"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,257.14826,118.6716)"
+ x1="85.861206"
+ y1="99.348953"
+ x2="85.60022"
+ y2="105.88815" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient30958"
+ id="linearGradient31157"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.74301467,-0.74301467,0.74301467,0.74301467,250.58064,118.02214)"
+ x1="85.861206"
+ y1="99.348953"
+ x2="85.60022"
+ y2="105.88815" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-7409-7-7-19-1"
+ id="linearGradient32854-6-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-1.1666676,0,0,-1.1666676,119.15081,827.66691)"
+ x1="262.04343"
+ y1="233.0448"
+ x2="273.85818"
+ y2="247.32738" />
+ <linearGradient
+ id="linearGradient37542-7409-7-7-19-1">
+ <stop
+ id="stop37544-48-6-1-8-9"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-82-1-0-6-8"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8-4-7-8-3-0-3"
+ id="linearGradient32856-3-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.53706486,0,0,0.53706486,-249.10439,522.04547)"
+ x1="97.616623"
+ y1="39.47208"
+ x2="94.157646"
+ y2="35.759052" />
+ <linearGradient
+ id="linearGradient44939-8-4-7-8-3-0-3">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop44941-8-5-40-2-4-2-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop44943-2-5-9-4-9-8-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient10069-9-7-5-4-6-5-0-3"
+ id="linearGradient32858-7-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.53706486,0,0,0.53706486,144.9138,-563.9364)"
+ x1="97.616623"
+ y1="39.47208"
+ x2="94.157646"
+ y2="35.759052" />
+ <linearGradient
+ id="linearGradient10069-9-7-5-4-6-5-0-3">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop10071-5-4-58-5-9-1-2-1" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop10073-43-0-4-0-8-0-4-9" />
+ </linearGradient>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask52637-8-8">
+ <rect
+ mask="none"
+ style="fill:url(#radialGradient52641-2-8);fill-opacity:1;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect52639-8-9"
+ width="7.9918551"
+ height="8.9366941"
+ x="-354"
+ y="458"
+ rx="0"
+ ry="0" />
+ </mask>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-7409-7-7-0-9-9"
+ id="radialGradient52641-2-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.39420438,-0.08239205,0.27256031,1.3040635,-361.27885,-161.73915)"
+ cx="-302.79681"
+ cy="462.0358"
+ fx="-302.79681"
+ fy="462.0358"
+ r="8" />
+ <linearGradient
+ id="linearGradient37542-7409-7-7-0-9-9">
+ <stop
+ id="stop37544-48-6-1-4-1-1"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop37546-82-1-0-9-3-3"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-31-8-9-1"
+ id="linearGradient52998-5-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-42,0)"
+ x1="-307"
+ y1="475"
+ x2="-303.00003"
+ y2="463.92236" />
+ <linearGradient
+ id="linearGradient319-31-8-9-1">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop320-23-2-8-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop321-34-4-4-2" />
+ </linearGradient>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask52879-0-5">
+ <rect
+ mask="none"
+ style="fill:url(#radialGradient52883-6-8);fill-opacity:1;stroke:none;stroke-width:2.79999995;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect52881-7-3"
+ width="7.9918551"
+ height="8.9366941"
+ x="-354.95001"
+ y="458"
+ rx="0"
+ ry="0" />
+ </mask>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient37542-7409-7-7-0-9-9"
+ id="radialGradient52883-6-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.39420438,-0.08239205,0.27256031,1.3040635,-362.22886,-161.73912)"
+ cx="-302.79681"
+ cy="462.0358"
+ fx="-302.79681"
+ fy="462.0358"
+ r="8" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient319-31-8-9-1"
+ id="linearGradient53000-3-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-42,0)"
+ x1="-308.7684"
+ y1="476.0105"
+ x2="-304.76843"
+ y2="464.93286" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient34488-1-8"
+ id="linearGradient53002-6-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-839.95,-273.25)"
+ x1="469.49295"
+ y1="-101.22778"
+ x2="470.7515"
+ y2="-102.52942" />
+ <linearGradient
+ id="linearGradient34488-1-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop34490-0-5-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop34492-4-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient32877-9-6-8"
+ id="linearGradient32896-0-4"
+ gradientUnits="userSpaceOnUse"
+ x1="-217.1391"
+ y1="626.39844"
+ x2="-213.69197"
+ y2="623.21643" />
+ <linearGradient
+ id="linearGradient32877-9-6-8">
+ <stop
+ style="stop-color:#b3b3b3;stop-opacity:1;"
+ offset="0"
+ id="stop32879-8-1-1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop32881-4-3-9" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient33058-4-9-5"
+ id="linearGradient32899-8-3"
+ gradientUnits="userSpaceOnUse"
+ x1="-180.37465"
+ y1="650.94128"
+ x2="-177.70576"
+ y2="653.27765" />
+ <linearGradient
+ id="linearGradient33058-4-9-5">
+ <stop
+ style="stop-color:#e5250b;stop-opacity:1;"
+ offset="0"
+ id="stop33060-3-3-9" />
+ <stop
+ style="stop-color:#460000;stop-opacity:1;"
+ offset="1"
+ id="stop33062-9-4-7" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8-4-8-6-8"
+ id="radialGradient32901-4-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1748275,-1.7208853,0.51495275,0.35155123,-289.20197,69.961171)"
+ cx="-197.66467"
+ cy="630.61389"
+ fx="-197.66467"
+ fy="630.61389"
+ r="7.03125" />
+ <linearGradient
+ id="linearGradient44939-8-4-8-6-8">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop44941-8-5-0-0-0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop44943-2-5-8-6-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient33058-2-7-1-7"
+ id="linearGradient32903-6-4"
+ gradientUnits="userSpaceOnUse"
+ x1="-218.31921"
+ y1="624.84143"
+ x2="-215.31401"
+ y2="628.46533" />
+ <linearGradient
+ id="linearGradient33058-2-7-1-7">
+ <stop
+ style="stop-color:#e5250b;stop-opacity:1;"
+ offset="0"
+ id="stop33060-1-8-8-5" />
+ <stop
+ style="stop-color:#460000;stop-opacity:1;"
+ offset="1"
+ id="stop33062-4-3-4-5" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient44939-8-4-8-6-8"
+ id="radialGradient32905-9-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.62164476,0.39733376,-0.55111069,0.86222272,269.0477,166.72227)"
+ cx="-202.18748"
+ cy="627"
+ fx="-202.18748"
+ fy="627"
+ r="7.03125" />
+ <linearGradient
+ y2="-102.52942"
+ x2="470.73633"
+ y1="-101.3037"
+ x1="469.52335"
+ gradientTransform="translate(-829.95,-273.25)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient58927"
+ xlink:href="#linearGradient34488-1-8"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-71-6-9-7"
+ id="linearGradient21875-7-1-0-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4126967,0,0,2.7035619,-536.07088,379.29465)"
+ x1="236.94902"
+ y1="-14.103641"
+ x2="278.34866"
+ y2="32.902874" />
+ <linearGradient
+ id="linearGradient1610-71-6-9-7">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-26-8-5-4" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-04-8-8-0" />
+ </linearGradient>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath13106-9-2-9-9">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ id="path34850-4-7-0-4"
+ 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" />
+ </clipPath>
+ <filter
+ inkscape:collect="always"
+ x="-0.45600089"
+ width="1.9120018"
+ y="-0.50666559"
+ height="2.0133312"
+ id="filter63011-6-7-0-8"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.899998"
+ id="feGaussianBlur63013-0-1-0-8" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060-6-6-2-4"
+ id="linearGradient21877-3-2-7-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-47.00001,58.00194)"
+ x1="160.14388"
+ y1="376.27383"
+ x2="174.29811"
+ y2="383.69843" />
+ <linearGradient
+ id="linearGradient5060-6-6-2-4">
+ <stop
+ id="stop5062-2-0-5-5"
+ offset="0"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ id="stop5064-4-4-5-5"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4671-6-4-1-7"
+ id="linearGradient34959-9-2-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.562541,0,0,0.567972,-9.399749,-5.305317)"
+ x1="1666.1765"
+ y1="639.65356"
+ x2="1659.0875"
+ y2="629.23273" />
+ <linearGradient
+ id="linearGradient4671-6-4-1-7">
+ <stop
+ id="stop4673-7-6-4-1"
+ offset="0"
+ style="stop-color:#ffd43b;stop-opacity:1;" />
+ <stop
+ id="stop4675-8-0-8-1"
+ offset="1"
+ style="stop-color:#ffe873;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4689-1-6-4-2"
+ id="linearGradient34961-3-6-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.562541,0,0,0.567972,-9.399749,-5.305317)"
+ x1="1641.4773"
+ y1="607.50525"
+ x2="1663.2872"
+ y2="626.40344" />
+ <linearGradient
+ id="linearGradient4689-1-6-4-2">
+ <stop
+ id="stop4691-6-2-6-7"
+ offset="0"
+ style="stop-color:#5a9fd4;stop-opacity:1;" />
+ <stop
+ id="stop4693-0-4-8-6"
+ offset="1"
+ style="stop-color:#306998;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-5-1-4-8-9-88-8-4"
+ id="linearGradient34963-5-9-1"
+ gradientUnits="userSpaceOnUse"
+ x1="922.89703"
+ y1="339.66599"
+ x2="924.10608"
+ y2="344.10001" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3966-5-1-4-8-9-88-8-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3968-7-9-0-8-2-1-3-2" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3970-6-6-6-2-8-2-5-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-5-1-4-8-9-88-8-4"
+ id="linearGradient34965-1-5-2"
+ gradientUnits="userSpaceOnUse"
+ x1="919.09998"
+ y1="345.42163"
+ x2="922.104"
+ y2="355.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-5-1-4-8-9-8-9-5-5"
+ id="linearGradient34967-4-1-8"
+ gradientUnits="userSpaceOnUse"
+ x1="922.64624"
+ y1="342.71866"
+ x2="921.82654"
+ y2="341.98108" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3966-5-1-4-8-9-8-9-5-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3968-7-9-0-8-2-9-8-5-7" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3970-6-6-6-2-8-0-2-8-6" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-5-1-4-8-9-88-8-4"
+ id="linearGradient34969-4-4-1"
+ gradientUnits="userSpaceOnUse"
+ x1="917.75"
+ y1="355.5"
+ x2="917.25"
+ y2="353" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-5-1-4-8-9-88-8-4"
+ id="linearGradient34971-5-0-9"
+ gradientUnits="userSpaceOnUse"
+ x1="923"
+ y1="343.75"
+ x2="923"
+ y2="344.75" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-5-1-4-8-9-88-8-4"
+ id="radialGradient34973-2-5-7"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.4166677,-7.678944e-6,1.853542e-6,0.58333478,-1309.0016,145.80659)"
+ cx="924"
+ cy="349.20001"
+ fx="924"
+ fy="349.20001"
+ r="6" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-5-1-4-8-9-88-8-4"
+ id="linearGradient34975-9-4-9"
+ gradientUnits="userSpaceOnUse"
+ x1="921.34045"
+ y1="341.34042"
+ x2="922.16492"
+ y2="342.16492" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3944-4-6-7-7"
+ id="linearGradient47921-1-7-1-1"
+ gradientUnits="userSpaceOnUse"
+ x1="215.99414"
+ y1="592.95746"
+ x2="218.99957"
+ y2="601.36218" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3944-4-6-7-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3946-2-4-4-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3948-3-5-0-0" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3952-2-6-4-4"
+ id="linearGradient47923-2-8-9-9"
+ gradientUnits="userSpaceOnUse"
+ x1="213.00005"
+ y1="597.41553"
+ x2="216.00003"
+ y2="604.375" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3952-2-6-4-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3954-1-1-8-8" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3956-6-5-8-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-5-1-45-4"
+ id="linearGradient47925-8-5-2-2"
+ gradientUnits="userSpaceOnUse"
+ x1="218.06126"
+ y1="601.83856"
+ x2="219.5"
+ y2="606.11218" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3966-5-1-45-4">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3968-7-9-5-5" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3970-6-6-1-5" />
+ </linearGradient>
+ <linearGradient
+ y2="609.36218"
+ x2="221"
+ y1="604.31494"
+ x1="219"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient49198-1-1"
+ xlink:href="#linearGradient3966-5-1-45-4"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-1-1-9-4-7-1"
+ id="linearGradient59244-7"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.888889,0,0,1,513.5,184.50451)"
+ x1="253.78497"
+ y1="3.6831069"
+ x2="278.40161"
+ y2="29.679312" />
+ <linearGradient
+ id="linearGradient1610-1-1-9-4-7-1">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop1611-74-7-2-2-2-1" />
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="1"
+ id="stop1612-09-4-7-5-1-5" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient40578-4-8-4-0-5-2-4-7"
+ id="radialGradient59246-2"
+ 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
+ id="linearGradient40578-4-8-4-0-5-2-4-7">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop40580-8-9-8-9-4-6-9-6" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop40582-6-8-8-4-3-8-9-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient58334-24-8-2-6-0-2"
+ id="linearGradient59248-4"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(670,-33)"
+ x1="87"
+ y1="241.125"
+ x2="93.0625"
+ y2="249" />
+ <linearGradient
+ id="linearGradient58334-24-8-2-6-0-2">
+ <stop
+ id="stop58336-55-8-3-6-3-3"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.87628865;" />
+ <stop
+ id="stop58338-17-2-3-3-0-2"
+ offset="1.0000000"
+ style="stop-color:#fffffe;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient16500-11-1-4-3-1"
+ id="linearGradient59250-2"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-95.999998)"
+ x1="754.28558"
+ y1="300.83292"
+ x2="758"
+ y2="305" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient16500-11-1-4-3-1">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop16502-5-1-5-5-6" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop16504-27-3-6-0-8" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3944-1-7-5-7-7"
+ id="linearGradient59252-5"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-251,440.9872)"
+ x1="215.99414"
+ y1="592.95746"
+ x2="218.99957"
+ y2="601.36218" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3944-1-7-5-7-7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3946-7-4-3-6-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3948-1-2-5-7-1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3952-5-7-6-8-9"
+ id="linearGradient59254-8"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-251,440.9872)"
+ x1="213.00005"
+ y1="597.41553"
+ x2="216.00003"
+ y2="604.375" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3952-5-7-6-8-9">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3954-2-9-1-3-2" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3956-7-3-4-6-7" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-8-9-6-4-5"
+ id="linearGradient59256-9"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-251,440.9872)"
+ x1="218.06126"
+ y1="601.83856"
+ x2="219.5"
+ y2="606.11218" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3966-8-9-6-4-5">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3968-2-8-2-4-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3970-4-6-6-1-3" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3966-8-9-6-4-5"
+ id="linearGradient59258-1"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-251,440.9872)"
+ x1="219"
+ y1="604.31494"
+ x2="221"
+ y2="609.36218" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10000"
+ objecttolerance="10000"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1"
+ inkscape:cx="147.30844"
+ inkscape:cy="114.24342"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1912"
+ inkscape:window-height="1031"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:snap-nodes="true"
+ inkscape:snap-bbox="false"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:object-nodes="false"
+ inkscape:object-paths="false"
+ inkscape:snap-intersection-line-segments="true"
+ inkscape:snap-intersection-grid-guide="false"
+ inkscape:window-maximized="1"
+ inkscape:bbox-paths="false"
+ inkscape:snap-global="true"
+ inkscape:snap-bbox-midpoints="false"
+ inkscape:snap-grids="true"
+ inkscape:snap-to-guides="false"
+ inkscape:snap-page="false"
+ units="px"
+ inkscape:snap-center="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid17394"
+ visible="true"
+ enabled="true"
+ spacingx="0.25px"
+ spacingy="0.25px"
+ empspacing="4"
+ color="#808080"
+ opacity="0.09803922"
+ dotted="false"
+ empcolor="#7f7f7f"
+ empopacity="0.25098039"
+ snapvisiblegridlinesonly="true"
+ originx="0px"
+ originy="0px" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Blender icons v. 2.5.06</dc:title>
+ <dc:date>21.05.2012</dc:date>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Andrzej Ambroż</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:rights>
+ <cc:Agent>
+ <dc:title>Andrzej Ambroż</dc:title>
+ </cc:Agent>
+ </dc:rights>
+ <dc:publisher>
+ <cc:Agent>
+ <dc:title>Andrzej Ambroż</dc:title>
+ </cc:Agent>
+ </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>
+ </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
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="bckgrnd"
+ style="display:none"
+ sodipodi:insensitive="true"
+ transform="translate(-872,-180)">
+ <rect
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.20000005;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect20607"
+ width="1083.874"
+ height="650"
+ x="-4"
+ y="-4" />
+ </g>
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#1a1a1a;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"
+ id="path23417"
+ sodipodi:nodetypes="cc"
+ d=""
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:1.79999995;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path23347"
+ sodipodi:nodetypes="cc"
+ d=""
+ inkscape:connector-curvature="0" />
+ <g
+ inkscape:label="ICONS"
+ inkscape:groupmode="layer"
+ id="layer1"
+ style="display:inline"
+ transform="translate(-872,-180)">
+ <g
+ id="g10203"
+ transform="translate(-211.20006,170)" />
+ <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
+ id="g14009"
+ transform="translate(1,-0.01245054)" />
+ <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">
+ <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>
+ <g
+ id="g16279"
+ transform="translate(318,7.00009)" />
+ <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="g12156"
+ transform="translate(-130.97687,-108)" />
+ <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="g11534"
+ transform="translate(21,-1)" />
+ <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
+ 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
+ transform="translate(-174.00091,22.99815)"
+ id="g15532" />
+ <g
+ transform="translate(-111.96756,-108)"
+ id="g15923">
+ <g
+ id="g15925" />
+ </g>
+ <g
+ transform="translate(189.19394,55.494451)"
+ id="g15616" />
+ <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)" />
+ <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="fill:#d45500;fill-opacity:1;display:inline"
+ transform="translate(47,-247.0151)"
+ id="g51988" />
+ <g
+ style="display:inline"
+ id="g57337"
+ transform="translate(10,254)" />
+ <g
+ id="g23613" />
+ <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="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
+ style="fill:#d45500;fill-opacity:1;display:inline"
+ transform="translate(-65,-169.00755)"
+ id="g24176" />
+ <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
+ 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="g77742"
+ style="fill:#ffeeaa;display:inline"
+ transform="translate(-870.9421,-297.02038)" />
+ <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="fill:#d45500;fill-opacity:1;display:inline"
+ transform="translate(250,-41.00755)"
+ id="g36511" />
+ <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
+ transform="translate(259,168)"
+ mask="url(#mask38561)"
+ id="g40090" />
+ <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
+ 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
+ id="g32752"
+ inkscape:export-filename="C:\Documents and Settings\Pracownia\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\RELEASES\v. 2.5.06\prvicons v.2.5.06.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ y="180"
+ x="872"
+ height="192"
+ width="192"
+ id="rect30285"
+ style="opacity:0;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.39191818;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png"
+ transform="translate(856,-203)"
+ id="g21955"
+ style="opacity:0.3;display:inline;enable-background:new">
+ <rect
+ 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"
+ id="rect21957"
+ width="48"
+ height="48"
+ x="108"
+ y="430"
+ rx="2.4004419"
+ ry="0" />
+ <g
+ id="g21959">
+ <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="path21961"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ style="fill:url(#linearGradient21977);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path21963"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,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" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)"
+ d="m 115,444 12,0 -1,-11 -11,11 z"
+ id="path21965"
+ 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)" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path21967"
+ style="fill:none;stroke:url(#linearGradient21979);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 117.5,443.75 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" />
+ <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 115.5,442.75 0,31.75 33,0 0,-41 -23.75,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="path21969"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)"
+ d="m 116,443 11,1 -2,-10 -9,9 z"
+ id="path21971"
+ 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)" />
+ <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="path21973"
+ d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z"
+ style="fill:#ffffff;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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ d="m 147.5,435 0,38.5 -30.5,0"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path21975"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ </g>
+ <g
+ id="g30335">
+ <g
+ id="g21367"
+ transform="translate(760,-202)">
+ <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="path21369"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ style="fill:url(#linearGradient30321);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path21371"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,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" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)"
+ d="m 115,444 12,0 -1,-11 -11,11 z"
+ id="path21373"
+ 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)" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path21375"
+ style="fill:none;stroke:url(#linearGradient30323);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 117.5,443.75 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" />
+ <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 115.5,442.75 0,31.75 33,0 0,-41 -23.75,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="path21377"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)"
+ d="m 116,443 11,1 -2,-10 -9,9 z"
+ id="path21569"
+ 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)" />
+ <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="path21379"
+ d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z"
+ style="fill:#ffffff;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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ d="m 147.5,435 0,38.5 -30.5,0"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path21381"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="font-size:33.49144363px;font-style:normal;font-weight:normal;fill:#214478;fill-opacity:1;stroke:none;display:inline;font-family:Bitstream Vera Sans"
+ d="m 891.07148,245 -0.0715,9 2.39012,0 C 896,254 896,253 896.5,251 l 0.5,0 0,7 -0.5,0 c -0.5,-2 -0.5,-3 -3.10988,-3 L 891,255 l 0,7 c 0,2.5 1,3.25 3.14146,3.39973 l -0.004,0.60029 L 885,266 l 0.004,-0.60029 C 887,265.25 888,264.5 888.00001,262 L 888,248 c 0,-2.5 -1,-3.25 -3,-3.5 l 0,-0.5 16,0 0,5 -0.5,0 c -0.50001,-1.99999 -1.5,-4 -4.5,-4 l -4.92852,0 z"
+ id="text13209"
+ sodipodi:nodetypes="ccccccccccccccccccccccc" />
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g21625"
+ transform="translate(904,-154)"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ ry="0"
+ rx="2.4004419"
+ y="430"
+ x="108"
+ height="48"
+ width="48"
+ id="rect21627"
+ 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" />
+ <g
+ id="g21629">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient21647);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ id="path21631"
+ 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" />
+ <g
+ style="opacity:0.5;fill:#000000;display:inline"
+ id="g16261"
+ transform="matrix(1.2499985,0,0,1,-87.6203,-147.85351)">
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
+ id="rect35099"
+ width="17.600004"
+ height="1"
+ x="167.69646"
+ y="598.85352"
+ rx="0.12125195"
+ ry="0.065390877" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
+ id="rect35101"
+ width="17.600004"
+ height="1"
+ x="167.69646"
+ y="600.85352"
+ rx="0.12125195"
+ ry="0.065390877" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
+ id="rect15690"
+ width="17.600004"
+ height="1"
+ x="167.69646"
+ y="602.85352"
+ rx="0.12125195"
+ ry="0.065390877" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
+ id="rect15692"
+ width="17.600004"
+ height="1"
+ x="167.69646"
+ y="604.85352"
+ rx="0.12125195"
+ ry="0.065390877" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
+ id="rect15694"
+ width="17.600004"
+ height="1"
+ x="167.69646"
+ y="606.85352"
+ rx="0.12125195"
+ ry="0.065390877" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
+ id="rect15696"
+ width="17.600004"
+ height="1"
+ x="167.69646"
+ y="608.85352"
+ rx="0.12125195"
+ ry="0.065390877" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
+ id="rect15698"
+ width="17.600004"
+ height="1"
+ x="167.69646"
+ y="610.85352"
+ rx="0.12125195"
+ ry="0.065390877" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
+ id="rect15700"
+ width="17.600004"
+ height="1"
+ x="167.69646"
+ y="612.85352"
+ rx="0.12125195"
+ ry="0.065390877" />
+ <rect
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
+ id="rect15732"
+ width="14.400002"
+ height="1"
+ x="167.69646"
+ y="614.85352"
+ rx="0.09920612"
+ ry="0.065390877" />
+ <g
+ transform="translate(150.89645,557.85352)"
+ id="g4849"
+ style="fill:#000000;display:inline">
+ <rect
+ ry="0.065390877"
+ rx="0.12125195"
+ y="29"
+ x="16.799992"
+ height="1"
+ width="17.600004"
+ id="rect15736"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" />
+ <rect
+ ry="0.065390877"
+ rx="0.12125195"
+ y="31"
+ x="16.799992"
+ height="1"
+ width="17.600004"
+ id="rect15738"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" />
+ <rect
+ ry="0.065390877"
+ rx="0.12125195"
+ y="33"
+ x="16.799992"
+ height="1"
+ width="17.600004"
+ id="rect15740"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" />
+ <rect
+ ry="0.065390877"
+ rx="0.12125195"
+ y="35"
+ x="16.799992"
+ height="1"
+ width="17.600004"
+ id="rect15742"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" />
+ <rect
+ ry="0.065390877"
+ rx="0.055114571"
+ y="37"
+ x="16.799992"
+ height="1"
+ width="8.0000095"
+ id="rect15744"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" />
+ </g>
+ <rect
+ ry="0.065390304"
+ rx="0.0057410933"
+ y="617.85352"
+ x="184.49646"
+ height="0.99999124"
+ width="0.83333319"
+ id="rect16334"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:block;overflow:visible;enable-background:accumulate" />
+ </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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path21633"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="url(#clipPath13106)"
+ 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="cccc"
+ id="path21635"
+ d="m 115,444 12,0 -1,-11 -11,11 z"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="none"
+ 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 117.5,443.75 9,-2.5 0,-6"
+ style="fill:none;stroke:url(#linearGradient21649);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path21637"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path21639"
+ style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 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"
+ clip-path="url(#clipPath13106)"
+ 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="cccc"
+ id="path21641"
+ d="m 116,443 11,1 -2,-10 -9,9 z"
+ style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z"
+ id="path21643"
+ 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" />
+ <g
+ id="g35119"
+ transform="translate(2,-160.99999)"
+ style="display:inline">
+ <g
+ style="display:inline"
+ transform="translate(105.39645,589.71201)"
+ id="g16097">
+ <g
+ id="g16099"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4"
+ transform="matrix(0.229703,0,0,0.229703,4.967081,4.244972)">
+ <radialGradient
+ id="radialGradient16101"
+ cx="20.892099"
+ cy="114.5684"
+ r="5.256"
+ fx="20.892099"
+ fy="114.5684"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ offset="0"
+ style="stop-color:#F0F0F0"
+ id="stop16103" />
+ <stop
+ offset="1"
+ style="stop-color:#474747"
+ id="stop16105" />
+ </radialGradient>
+ <radialGradient
+ id="radialGradient16109"
+ cx="20.892099"
+ cy="64.567902"
+ r="5.257"
+ fx="20.892099"
+ fy="64.567902"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ offset="0"
+ style="stop-color:#F0F0F0"
+ id="stop16111" />
+ <stop
+ offset="1"
+ style="stop-color:#474747"
+ id="stop16113" />
+ </radialGradient>
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+ d="m 12.85355,31.53813 c 0,0.552274 -0.447803,0.99986 -1,0.99986 -0.552477,0 -1,-0.447865 -1,-0.99986 0,-0.552554 0.447803,-1.00014 1,-1.00014 0.552197,0 1,0.447866 1,1.00014 l 0,0 0,0 0,0 z"
+ id="path16107" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient21565);fill-rule:nonzero;stroke:none"
+ d="m 12.60355,31.288131 c 0,0.552274 -0.447803,0.999859 -1,0.999859 -0.552477,0 -1,-0.447865 -1,-0.999859 0,-0.552556 0.447803,-1.000141 1,-1.000141 0.552197,0 1,0.447866 1,1.000141 z"
+ id="path16117" />
+ </g>
+ <g
+ id="g16131"
+ transform="translate(105.39645,579.71201)"
+ style="display:inline">
+ <g
+ transform="matrix(0.229703,0,0,0.229703,4.967081,4.244972)"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4"
+ id="g16133">
+ <radialGradient
+ gradientUnits="userSpaceOnUse"
+ fy="114.5684"
+ fx="20.892099"
+ r="5.256"
+ cy="114.5684"
+ cx="20.892099"
+ id="radialGradient16135">
+ <stop
+ id="stop16137"
+ style="stop-color:#F0F0F0"
+ offset="0" />
+ <stop
+ id="stop16140"
+ style="stop-color:#474747"
+ offset="1" />
+ </radialGradient>
+ <radialGradient
+ gradientUnits="userSpaceOnUse"
+ fy="64.567902"
+ fx="20.892099"
+ r="5.257"
+ cy="64.567902"
+ cx="20.892099"
+ id="radialGradient16142">
+ <stop
+ id="stop16144"
+ style="stop-color:#F0F0F0"
+ offset="0" />
+ <stop
+ id="stop16146"
+ style="stop-color:#474747"
+ offset="1" />
+ </radialGradient>
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ id="path35139"
+ d="m 12.85355,31.53813 c 0,0.552274 -0.447803,0.99986 -1,0.99986 -0.552477,0 -1,-0.447865 -1,-0.99986 0,-0.552554 0.447803,-1.00014 1,-1.00014 0.552197,0 1,0.447866 1,1.00014 l 0,0 0,0 0,0 z"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path35141"
+ d="m 12.60355,31.288131 c 0,0.552274 -0.447803,0.999859 -1,0.999859 -0.552477,0 -1,-0.447865 -1,-0.999859 0,-0.552556 0.447803,-1.000141 1,-1.000141 0.552197,0 1,0.447866 1,1.000141 z"
+ style="fill:url(#radialGradient21567);fill-rule:nonzero;stroke:none" />
+ </g>
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path21645"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 147.5,435 0,38.5 -30.5,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" />
+ </g>
+ </g>
+ <g
+ style="display:inline;enable-background:new"
+ id="g21572"
+ transform="translate(808,-203)"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ ry="0"
+ rx="2.4004419"
+ y="430"
+ x="108"
+ height="48"
+ width="48"
+ id="rect21574"
+ 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" />
+ <g
+ id="g21576">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient21594);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ id="path21578"
+ 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"
+ d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path21580"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="url(#clipPath13106)"
+ 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="cccc"
+ id="path21582"
+ d="m 115,444 12,0 -1,-11 -11,11 z"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="none"
+ 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 117.5,443.75 9,-2.5 0,-6"
+ style="fill:none;stroke:url(#linearGradient21596);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path21584"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path21586"
+ style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 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"
+ clip-path="url(#clipPath13106)"
+ 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="cccc"
+ id="path21588"
+ d="m 116,443 11,1 -2,-10 -9,9 z"
+ style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z"
+ id="path21590"
+ 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"
+ sodipodi:nodetypes="ccc"
+ id="path21592"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 147.5,435 0,38.5 -30.5,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" />
+ </g>
+ </g>
+ <g
+ id="g30382">
+ <g
+ id="g23655"
+ transform="translate(760,-154)">
+ <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="path23657"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ style="fill:url(#linearGradient30368);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path23659"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,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" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)"
+ d="m 115,444 12,0 -1,-11 -11,11 z"
+ id="path23661"
+ 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)" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path23663"
+ style="fill:none;stroke:url(#linearGradient30370);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 117.5,443.75 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" />
+ <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 115.5,442.75 0,31.75 33,0 0,-41 -23.75,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="path23665"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)"
+ d="m 116,443 11,1 -2,-10 -9,9 z"
+ id="path23667"
+ 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)" />
+ <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="path23669"
+ d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z"
+ style="fill:#ffffff;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\Kopia blender\.blender\icons\jendrzych's iconset.png"
+ d="m 147.5,435 0,38.5 -30.5,0"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path23671"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 888,295 1,0 0,14 -1,0 0,-14 z"
+ id="path23675"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path23677"
+ d="m 900,294 1.00002,-1 0,14 -1.00002,0 0,-13 z"
+ style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc"
+ id="path23679"
+ d="m 901.00003,292 0,2.25 -13.00002,2 0,-2.25 13.00002,-2 z"
+ style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <g
+ id="g23681"
+ 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"
+ sodipodi:ry="2.25"
+ sodipodi:rx="4.5"
+ sodipodi:cy="554"
+ sodipodi:cx="53"
+ id="path23683"
+ style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter20578);enable-background:accumulate"
+ id="path23685"
+ sodipodi:cx="53"
+ 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"
+ transform="matrix(0.3848865,-0.1700959,0.2278131,0.3626733,-93.107467,361.59408)"
+ inkscape:transform-center-y="0.3813435"
+ clip-path="url(#clipPath20586)" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.38999999;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 901.00003,292 -1e-5,1 -13.00002,2 10e-6,-1 13.00002,-2 z"
+ id="path23694"
+ sodipodi:nodetypes="ccccc" />
+ <g
+ transform="matrix(1.1428564,0,0,1.2000001,834.71436,-357.40005)"
+ id="g23717">
+ <path
+ sodipodi:type="arc"
+ style="fill:#112b00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path23724"
+ sodipodi:cx="53"
+ 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"
+ 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"
+ sodipodi:ry="2.25"
+ sodipodi:rx="4.5"
+ sodipodi:cy="554"
+ sodipodi:cx="53"
+ id="path23726"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter20578);enable-background:accumulate"
+ sodipodi:type="arc" />
+ </g>
+ </g>
+ <g
+ id="g23922"
+ transform="translate(-16,-220)"
+ style="display:inline;enable-background:new">
+ <g
+ style="display:inline"
+ id="g23924"
+ transform="translate(824,66)"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ ry="0"
+ rx="2.4004419"
+ y="430"
+ x="108"
+ height="48"
+ width="48"
+ id="rect23926"
+ 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" />
+ <g
+ id="g23928">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient23978);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ id="path23930"
+ 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"
+ d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path23932"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="url(#clipPath13106)"
+ 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="cccc"
+ id="path23934"
+ d="m 115,444 12,0 -1,-11 -11,11 z"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="none"
+ 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 117.5,443.75 9,-2.5 0,-6"
+ style="fill:none;stroke:url(#linearGradient23980);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path23936"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path23938"
+ style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 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"
+ clip-path="url(#clipPath13106)"
+ 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="cccc"
+ id="path23940"
+ d="m 116,443 11,1 -2,-10 -9,9 z"
+ style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z"
+ id="path23942"
+ 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"
+ sodipodi:nodetypes="ccc"
+ id="path23944"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 147.5,435 0,38.5 -30.5,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" />
+ </g>
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccc"
+ id="path23946"
+ d="m 952,530 0,10 1,0 1,0 11,0 1,0 1,0 0,-10 -15,0 z m 1,2 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ transform="scale(1,-1)"
+ style="fill:url(#linearGradient23982);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect23948"
+ width="13"
+ height="5.5"
+ x="953"
+ y="-524" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path23952"
+ transform="translate(76,0)"
+ d="m 876,514 0,17 15,0 0,-17 -1,0 0,1 -1,0 0,-1 -11,0 0,1 -1,0 0,-1 -1,0 z m 1,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z m -12,3 1,0 0,1 -1,0 0,-1 z m 12,0 1,0 0,1 -1,0 0,-1 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccc"
+ style="fill:url(#linearGradient23986);fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 952,507 3,0 0,3 9,0 0,-3 3,0 0,7 -15,0 0,-7 z m 1,0 1,0 -1,0 z m 0,1 0,1 1,0 0,-1 -1,0 z m 0,3 0,1 1,0 0,-1 -1,0 z m 12,-4 1,0 -1,0 z m 0,1 0,1 1,0 0,-1 -1,0 z m 0,3 0,1 1,0 0,-1 -1,0 z"
+ id="path23954" />
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ ry="0"
+ y="955"
+ x="507"
+ height="9"
+ width="3"
+ id="rect23956"
+ style="fill:url(#linearGradient23988);fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <rect
+ style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect23958"
+ width="9"
+ height="9"
+ x="512"
+ y="955"
+ ry="0"
+ transform="matrix(0,1,1,0,0,0)" />
+ <rect
+ transform="matrix(0,1,1,0,0,0)"
+ ry="0"
+ y="955"
+ x="523"
+ height="9"
+ width="9"
+ id="rect23960"
+ style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <path
+ transform="matrix(0,-0.5624971,0.5624971,0,893.12531,590.74965)"
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path23962"
+ 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="path23964"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(0,-0.5624964,0.5624964,0,893.12545,601.74956)" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccc"
+ id="path23966"
+ d="m 961.00001,519.00005 -3,0 0,-0.99992 0.99994,0 6e-5,-2.00008 -1,0 0,-1 1,0 0,-1 1.00006,0 0,4.00008 0.99994,0 0,0.99992 z" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 958,525 0,1 2,0 0,-1 -2,0 z m 2,1 0,1 1,0 0,-1 -1,0 z m 0,1 -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"
+ id="path23968" />
+ <rect
+ style="fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="rect23970"
+ width="6"
+ height="9"
+ x="534"
+ y="955"
+ ry="0"
+ transform="matrix(0,1,1,0,0,0)" />
+ <g
+ clip-path="url(#clipPath23877)"
+ id="g23972">
+ <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="path23974"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:type="arc"
+ transform="matrix(0,-0.5624964,0.5624964,0,893.12545,612.74956)" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 958,536 0,1 2,0 0,-1 -2,0 z m 2,1 0,1 1,0 0,-1 -1,0 z m 0,1 -1,0 0,1 1,0 0,-1 z m 0,1 0,1 1,0 0,-1 -1,0 z m 0,1 -2,0 0,1 2,0 0,-1 z"
+ id="path23976" />
+ </g>
+ </g>
+ <g
+ transform="translate(208,88)"
+ id="g45475"
+ style="display:inline;enable-background:new">
+ <g
+ style="display:inline"
+ id="g22242"
+ transform="translate(696,-194)"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ ry="0"
+ rx="2.4004419"
+ y="430"
+ x="108"
+ height="48"
+ width="48"
+ id="rect22244"
+ 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" />
+ <g
+ id="g22246">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient22274);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ id="path22249"
+ 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"
+ d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path22251"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="url(#clipPath13106)"
+ 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="cccc"
+ id="path22253"
+ d="m 115,444 12,0 -1,-11 -11,11 z"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011)" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="none"
+ 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 117.5,443.75 9,-2.5 0,-6"
+ style="fill:none;stroke:url(#linearGradient22276);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path22264"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path22266"
+ style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 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"
+ clip-path="url(#clipPath13106)"
+ 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="cccc"
+ id="path22268"
+ d="m 116,443 11,1 -2,-10 -9,9 z"
+ style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z"
+ id="path22270"
+ 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"
+ sodipodi:nodetypes="ccc"
+ id="path22272"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 147.5,435 0,38.5 -30.5,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" />
+ </g>
+ </g>
+ <g
+ id="g21517"
+ inkscape:label="Layer 1"
+ 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"
+ sodipodi:ry="5.3033009"
+ sodipodi:rx="15.467961"
+ sodipodi:cy="38.98439"
+ sodipodi:cx="28.019106"
+ id="path35486"
+ style="opacity:0.54857142;fill:url(#radialGradient21442);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csssssssssscccsscccscccssccc"
+ 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"
+ id="path2482"
+ 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"
+ sodipodi:ry="10.125"
+ sodipodi:rx="11.5625"
+ sodipodi:cy="25.75"
+ sodipodi:cx="31.1875"
+ id="path39153"
+ style="fill:url(#linearGradient21444);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.4857143;fill:none;stroke:url(#linearGradient21446);stroke-width:1.7812928;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
+ 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"
+ id="path21414"
+ sodipodi:nodetypes="csssssscssscsssccssscscccsccssssccscsscccssssc" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ id="path2478"
+ style="fill:#3465a4;fill-rule:evenodd;stroke:none" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csssscsccsscsccssssscsscccsssc"
+ id="path39166"
+ 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"
+ style="opacity:0.51999996;fill:url(#radialGradient21448);fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ </g>
+ </g>
+ <g
+ style="opacity:0.5"
+ id="g24847"
+ transform="translate(162,248)">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccssssccc"
+ style="fill:url(#linearGradient24867);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path24849"
+ d="m 806.5,114.5 c 0,2.25 2,4 4,4 l 30,0 c 0.4163,0 1,-0.5 1,-1 l 0,-29 c 0,-0.5 -0.5,-1 -1,-1 l -21.02773,0.04419 C 818.98721,87.545209 818.5,87 818.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -10,0 c -0.5,0 -1,0.5 -1,1 l 0,31 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path24851"
+ style="opacity:0.07999998;fill:url(#linearGradient24869);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+ d="m 807.5,89.5 33,0 m -33,12 33,0 m -33,-4 33,0 m -33,-6 33,0 m -33,20 33,0 m -33,2 33,0 m -33,-18 33,0 m -33,-2 33,0 m -20,-6 -13,0 m 0,20 33,0 m -33,-2 33,0 m -33,-2 33,0 m -33,-4 33,0 m -33,10 33,0 m -33,6 33,0"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="74.800003"
+ inkscape:export-xdpi="74.800003"
+ inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png"
+ sodipodi:nodetypes="csccsczc"
+ id="path24853"
+ d="m 844,118.5 c 3.5,0 5.5,-2 5.5,-5.5 l 0,-18.5 c -11.75604,-1.11e-4 -23.91623,0 -35.5,0 l 0,19.5 c 0,4.5 -7,4 -7,0.25 0,2 2.00002,3.73529 3,3.75 l 34,0.5 z"
+ style="fill:url(#linearGradient24871);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:connector-curvature="0"
+ d="m 807,87 12,0 0.0385,-3.33333 C 819.04423,83.166705 818.97512,83 818.5,83 l -10.92308,0 c -0.47512,0 -0.53846,0.16667 -0.53846,0.66667 L 807,87 z"
+ id="path24855"
+ style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:nodetypes="ccssccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ d="m 840.5,89 0,4.5"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+ id="path24857" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path24859"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+ d="m 848.5,95.5 0,18 c 0,1.25 0.25,3 -1.25,4"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccsc"
+ d="m 818.5,83.5 -11,0 0,30 c 0,5 7,5 7,0 l 0,-18 34,0 m -29,-8 c 0,0.5 0.5286,1 1,1 l 20,0"
+ style="opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="path24861" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 806.5,113.5 c 0,2.75 2,5 5,5 l 33,0 c 3,0 5,-2 5,-5 l 0,-18 c 0,-0.471405 -0.5286,-1 -1,-1 l -7,0 0,-6 c 0,-0.5 -0.5,-1 -1,-1 l -20.02773,0.04419 C 819.98721,87.54526 819.5,87 819.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -11,0 c -0.5,0 -1,0.5 -1,1 l 0,30 z"
+ id="path24863"
+ style="fill:none;stroke:#000000;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"
+ sodipodi:nodetypes="ccccsscccssssccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient24873);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 841.5,94.5 -27,0 c -0.4714,0 -1,0.528595 -1,1 l 0,18 c 0,2.25 -1.25,3 -2.5,3"
+ id="path24865"
+ sodipodi:nodetypes="csscc" />
+ </g>
+ <g
+ style="opacity:0.5"
+ transform="translate(114,248)"
+ id="g24784">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 806.5,114.5 c 0,2.25 2,4 4,4 l 30,0 c 0.4163,0 1,-0.5 1,-1 l 0,-29 c 0,-0.5 -0.5,-1 -1,-1 l -21.02773,0.04419 C 818.98721,87.545209 818.5,87 818.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -10,0 c -0.5,0 -1,0.5 -1,1 l 0,31 z"
+ id="path24789"
+ style="fill:url(#linearGradient24809);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:nodetypes="ccccccssssccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccc"
+ d="m 807.5,89.5 33,0 m -33,12 33,0 m -33,-4 33,0 m -33,-6 33,0 m -33,20 33,0 m -33,2 33,0 m -33,-18 33,0 m -33,-2 33,0 m -20,-6 -13,0 m 0,20 33,0 m -33,-2 33,0 m -33,-2 33,0 m -33,-4 33,0 m -33,10 33,0 m -33,6 33,0"
+ style="opacity:0.07999998;fill:url(#linearGradient24811);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+ id="path24791" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient24813);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 844,118.5 c 3.5,0 5.5,-2 5.5,-5.5 l 0,-18.5 c -11.75604,-1.11e-4 -23.91623,0 -35.5,0 l 0,19.5 c 0,4.5 -7,4 -7,0.25 0,2 2.00002,3.73529 3,3.75 l 34,0.5 z"
+ id="path24793"
+ sodipodi:nodetypes="csccsczc"
+ inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png"
+ inkscape:export-xdpi="74.800003"
+ inkscape:export-ydpi="74.800003" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccssccc"
+ style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path24796"
+ d="m 807,87 12,0 0.0385,-3.33333 C 819.04423,83.166705 818.97512,83 818.5,83 l -10.92308,0 c -0.47512,0 -0.53846,0.16667 -0.53846,0.66667 L 807,87 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path24799"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+ d="m 840.5,89 0,4.5"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ d="m 848.5,95.5 0,18 c 0,1.25 0.25,3 -1.25,4"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+ id="path24801" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path24803"
+ style="opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ d="m 818.5,83.5 -11,0 0,30 c 0,5 7,5 7,0 l 0,-18 34,0 m -29,-8 c 0,0.5 0.5286,1 1,1 l 20,0"
+ sodipodi:nodetypes="cccccccsc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccsscccssssccc"
+ style="fill:none;stroke:#000000;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="path24805"
+ d="m 806.5,113.5 c 0,2.75 2,5 5,5 l 33,0 c 3,0 5,-2 5,-5 l 0,-18 c 0,-0.471405 -0.5286,-1 -1,-1 l -7,0 0,-6 c 0,-0.5 -0.5,-1 -1,-1 l -20.02773,0.04419 C 819.98721,87.54526 819.5,87 819.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -11,0 c -0.5,0 -1,0.5 -1,1 l 0,30 z" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csscc"
+ id="path24807"
+ d="m 841.5,94.5 -27,0 c -0.4714,0 -1,0.528595 -1,1 l 0,18 c 0,2.25 -1.25,3 -2.5,3"
+ style="fill:none;stroke:url(#linearGradient24815);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ </g>
+ <g
+ transform="translate(0,-2)"
+ style="opacity:0.4;stroke:#3d361a;filter:url(#filter44473)"
+ id="g44424">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path44406"
+ d="m 950.25,362 -5.25,0 -1,-1 0,-10"
+ style="fill:none;stroke:#3d361a;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path44408"
+ d="M 948.25,354.25 944,350.00563 939.75,354.25"
+ style="fill:none;stroke:#3d361a;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new" />
+ </g>
+ <g
+ transform="translate(617,273)"
+ id="g44334"
+ style="display:inline;enable-background:new">
+ <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="rect44336"
+ width="16"
+ height="16"
+ x="320"
+ y="73" />
+ <g
+ transform="translate(0,-21)"
+ id="g44338">
+ <g
+ id="g44340">
+ <g
+ transform="translate(0,21)"
+ id="g44342">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ id="path44344"
+ d="m 333.25,87 -5.25,0 -1,-1 0,-10"
+ style="fill:none;stroke:#000000;stroke-width:3.4000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path44346"
+ d="M 331.25,79.25 327,75.005631 322.75,79.25"
+ style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ </g>
+ <g
+ transform="translate(0,21)"
+ id="g44348">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 333.25,87 -5.25,0 -1,-1 0,-10"
+ id="path44350"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#e6e6e6;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M 331.25,79.25 327,75.005631 322.75,79.25"
+ id="path44352"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 328.5,107.5 5,0 m -7,-9 0,8.5 m -4.25,-7 4.5,-4.5"
+ id="path44354"
+ sodipodi:nodetypes="cccccc" />
+ </g>
+ </g>
+ <g
+ transform="translate(66,248)"
+ id="g24818"
+ style="display:inline;enable-background:new">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccssssccc"
+ style="fill:url(#linearGradient24839);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path24821"
+ d="m 806.5,114.5 c 0,2.25 2,4 4,4 l 30,0 c 0.4163,0 1,-0.5 1,-1 l 0,-29 c 0,-0.5 -0.5,-1 -1,-1 l -21.02773,0.04419 C 818.98721,87.545209 818.5,87 818.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -10,0 c -0.5,0 -1,0.5 -1,1 l 0,31 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path24823"
+ style="opacity:0.07999998;fill:url(#linearGradient24841);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+ d="m 807.5,89.5 33,0 m -33,12 33,0 m -33,-4 33,0 m -33,-6 33,0 m -33,20 33,0 m -33,2 33,0 m -33,-18 33,0 m -33,-2 33,0 m -20,-6 -13,0 m 0,20 33,0 m -33,-2 33,0 m -33,-2 33,0 m -33,-4 33,0 m -33,10 33,0 m -33,6 33,0"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="74.800003"
+ inkscape:export-xdpi="74.800003"
+ inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png"
+ sodipodi:nodetypes="csccsczc"
+ id="path24825"
+ d="m 844,118.5 c 3.5,0 5.5,-2 5.5,-5.5 l 0,-16 c -11.75604,-1.11e-4 -23.91623,0 -35.5,0 l 0,17 c 0,4.5 -7,4 -7,0.25 0,2 2.00002,3.73529 3,3.75 l 34,0.5 z"
+ style="fill:url(#linearGradient24843);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:connector-curvature="0"
+ d="m 807,87 12,0 0.0385,-3.33333 C 819.04423,83.166705 818.97512,83 818.5,83 l -10.92308,0 c -0.47512,0 -0.53846,0.16667 -0.53846,0.66667 L 807,87 z"
+ id="path24827"
+ style="opacity:0.7;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ sodipodi:nodetypes="ccssccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ d="m 840.5,89 0,7.5"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+ id="path24829" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path24831"
+ style="opacity:0.1;fill:none;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
+ d="m 848.5,98.75 0,14.75 c 0,1.25 0.25,3 -1.25,4"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccsc"
+ d="m 818.5,83.5 -11,0 0,30 c 0,5 7,5 7,0 l 0,-16 34,0 m -29,-10 c 0,0.5 0.5286,1 1,1 l 20,0"
+ style="opacity:0.75;fill:none;stroke:#ffffff;stroke-width:1.29999995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="path24833" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 806.5,113.5 c 0,2.75 2,5 5,5 l 33,0 c 3,0 5,-2 5,-5 l 0,-16 c 0,-0.471405 -0.5286,-1 -1,-1 l -7,0 0,-8 c 0,-0.5 -0.5,-1 -1,-1 l -20.02773,0.04419 C 819.98721,87.54526 819.5,87 819.5,86.5 l 0,-3 c 0,-0.5 -0.5,-1 -1,-1 l -11,0 c -0.5,0 -1,0.5 -1,1 l 0,30 z"
+ id="path24835"
+ style="fill:none;stroke:#000000;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"
+ sodipodi:nodetypes="ccccsscccssssccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient24845);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 841.5,96.500004 -27,0 c -0.4714,0 -1,0.528595 -1,1 l 0,15.999996 c 0,2.25 -1.25,3 -2.5,3"
+ id="path24837"
+ sodipodi:nodetypes="csscc" />
+ </g>
+ <g
+ style="opacity:0.4;filter:url(#filter44477)"
+ id="g44455">
+ <path
+ inkscape:connector-curvature="0"
+ transform="translate(645,252.05)"
+ style="fill:none;stroke:#3d361a;stroke-width:5;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.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5"
+ id="path44446"
+ sodipodi:nodetypes="cs" />
+ <path
+ inkscape:connector-curvature="0"
+ transform="translate(645,252.05)"
+ style="fill:none;stroke:#3d361a;stroke-width:5;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,108.25 0,-4.25 4.25,0"
+ id="path44449"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ transform="matrix(-1,0,0,-1,1343,456.05)"
+ sodipodi:nodetypes="cs"
+ id="path44451"
+ d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5"
+ style="fill:none;stroke:#3d361a;stroke-width:5;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"
+ transform="matrix(-1,0,0,-1,1343,456.05)"
+ sodipodi:nodetypes="ccc"
+ id="path44453"
+ d="m 343,108.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#3d361a;stroke-width:5;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
+ transform="translate(645,273.05)"
+ id="g44356"
+ style="display:inline;enable-background:new">
+ <rect
+ y="73"
+ x="341"
+ height="16"
+ width="16"
+ id="rect44358"
+ 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(0,-21)"
+ id="g44360">
+ <g
+ id="g44362">
+ <g
+ id="g44364">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cs"
+ id="path44366"
+ d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5"
+ style="fill:none;stroke:#000000;stroke-width:3.5;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="path44368"
+ d="m 343,108.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#000000;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" />
+ </g>
+ <g
+ id="g44370">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#e6e6e6;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 343,108.25 0,-4.25 4.25,0"
+ id="path44372"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#e6e6e6;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 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5"
+ id="path44374"
+ sodipodi:nodetypes="cs" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ id="path44376"
+ d="m 344,105 0,1 0,1.5 1,0 0,-1.5 1.5,0 0,-1 -1.5,0 -1,0 z"
+ style="opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ <g
+ id="g44378"
+ transform="matrix(-1,0,0,-1,698,204)">
+ <g
+ id="g44380">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000;stroke-width:3.5;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.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5"
+ id="path44382"
+ sodipodi:nodetypes="cs" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000;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,108.25 0,-4.25 4.25,0"
+ id="path44384"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <g
+ id="g44386">
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path44388"
+ d="m 343,108.25 0,-4.25 4.25,0"
+ style="fill:none;stroke:#e6e6e6;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" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cs"
+ id="path44390"
+ d="m 343.5,104.5 1.75,1.75 c 2.3454,2.33848 6.16153,2.34539 8.5,0 l 0.5,-0.5"
+ style="fill:none;stroke:#e6e6e6;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" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:0.1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 344,105 0,1 0,1.5 1,0 0,-1.5 1.5,0 0,-1 -1.5,0 -1,0 z"
+ id="path44392" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient44402);stroke-width:1.10000002;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 344.90625,106.59375 c 2.52573,2.51828 6.66805,2.52691 9.1875,0 l 0.5,-0.5"
+ id="path44394"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 350.5,99.5 4,0 0,-4"
+ id="path44396"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ 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"
+ d="m 347.5,103.5 -4.5,0 c -0.25,0 -0.5,0.25 -0.5,0.5 l 0,4.5"
+ id="path44398"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:url(#linearGradient44404);stroke-width:1.10000002;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 345.59375,105.90625 c 2.07803,2.0719 5.36384,2.10325 7.53125,0.1875 L 354,105.25"
+ id="path44400"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ </g>
+ <g
+ id="g34977"
+ style="display:inline;enable-background:new">
+ <g
+ style="display:inline"
+ id="g21853-3"
+ transform="translate(856,-154)"
+ inkscape:export-filename="C:\Documents and Settings\Pracowniaa\Moje dokumenty\Moje obrazy\BLENDER ICONS redesign\ver 2\IMAGE BROWSER ICONS.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <rect
+ ry="0"
+ rx="2.4004419"
+ y="430"
+ x="108"
+ height="48"
+ width="48"
+ id="rect21855-8"
+ 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" />
+ <g
+ id="g21857-6">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient21875-7-1-0-1);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;display:inline"
+ d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
+ id="path21859-9"
+ 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"
+ d="m 147.25,434.5 c -4.875,0 -21.75,0 -21.75,0 m -8.9447,8.5 -0.0553,30"
+ style="opacity:0.7;fill:none;stroke:#ffffff;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ id="path21861-8"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="url(#clipPath13106-9-2-9-9)"
+ 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="cccc"
+ id="path21863-6"
+ d="m 115,444 12,0 -1,-11 -11,11 z"
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter63011-6-7-0-8)" />
+ <path
+ inkscape:connector-curvature="0"
+ clip-path="none"
+ 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 117.5,443.75 9,-2.5 0,-6"
+ style="fill:none;stroke:url(#linearGradient21877-3-2-7-2);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path21865-6"
+ sodipodi:nodetypes="ccc" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path21867-2"
+ style="fill:none;stroke:#333333;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 115.5,442.75 0,31.75 33,0 0,-41 -23.75,0 -9.25,9.25 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"
+ clip-path="url(#clipPath13106-9-2-9-9)"
+ 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="cccc"
+ id="path21869-3"
+ d="m 116,443 11,1 -2,-10 -9,9 z"
+ style="opacity:0.16000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline;filter:url(#filter63011-6-7-0-8)" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 116,443 0.0108,0.72434 L 126,441 l 0,-7 -1,0 -9,9 z"
+ id="path21871-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:export-ydpi="90" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc"
+ id="path21873-2"
+ style="opacity:0.15;fill:none;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 147.5,435 0,38.5 -30.5,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" />
+ </g>
+ </g>
+ <g
+ id="g34938"
+ transform="translate(63,-47)">
+ <path
+ id="path61236"
+ style="color:#000000;fill:url(#linearGradient34959-9-2-1);fill-opacity:1;fill-rule:nonzero;stroke:#ff0000;stroke-width:0.17893334;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 919.5,356.5067 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.0064 2.5,0.006 c 2,0 3.5,2.5 3.5,6 0,3.5 -1.25,6 -3.5,6 -4.98134,0 -12.77318,0 -2.5,0 l 0,2.75 c 0,2.5 -2,3.24997 -5.5,3.24998 l 0,2e-5 c -3.5,0.0104 -5.5,-0.75 -5.5,-3.25 l 0,-2.7628"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cssssccsscsccsc" />
+ <path
+ sodipodi:nodetypes="cssssccsscsccsc"
+ inkscape:connector-curvature="0"
+ 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.0064 -2.5,-0.006 c -2,0 -3.5,-2.5 -3.5,-6 0,-3.5 1.25,-6 3.5,-6 4.98134,0 12.77318,0 2.5,0 l 0,-2.75 c 0,-2.5 2,-3.24997 5.5,-3.24998 l 0,-2e-5 c 3.5,-0.0104 5.5,0.75 5.5,3.25 l 0,2.7628"
+ style="color:#000000;fill:url(#linearGradient34961-3-6-5);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.17893334;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path61233" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccscccsccccsccccc"
+ id="path61167"
+ d="m 925,338.50002 c -3.5,10e-6 -5.5,0.74998 -5.5,3.24998 l 0,2.75 5.5,0 -8,0 c -2.25,0 -3.5,2.5 -3.5,6 0,3.5 1.5,6 3.5,6 l 2.5,0.0128 0,2.9872 c 0,2 2,3.01281 5.5,3.0128 3.5,-1e-5 5.5,-1.0128 5.5,-3.0128 l 0,-3 -5.5,0 8,0 c 2,0 3.5,-2.5 3.5,-6 0,-3.5 -1.5,-6 -3.5,-6 l -2.5,0.0128 0,-2.7628 c 0,-2.5 -2,-3.26045 -5.5,-3.25 z"
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-miterlimit:4;stroke-opacity:0.8627451;stroke-dasharray:none" />
+ <path
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc"
+ id="path61169"
+ 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"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="342"
+ sodipodi:cx="922"
+ id="path61220"
+ 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"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="359"
+ sodipodi:cx="928"
+ id="path61222"
+ 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" />
+ <g
+ style="opacity:0.4"
+ id="g61345">
+ <path
+ style="fill:none;stroke:url(#linearGradient34963-5-9-1);stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 920.5,343.25 0,-1.5 c 0,-1.75 1.5,-2.25 4.5,-2.25 3,0 4.5,0.5 4.5,2.25 l 0,4.75"
+ id="path61333"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cszsc" />
+ <path
+ style="fill:none;stroke:url(#linearGradient34965-1-5-2);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+ d="m 925.5,345 0,0.25 -0.25,0.25 -8.25,0 c -1.5,0 -2.5,2 -2.5,5 0,3 1.28917,5 2.5,5 l 1.5,0"
+ id="path61335"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccszsc" />
+ <path
+ style="fill:none;stroke:none"
+ d="m 920.75,343.5 4.5,0 0.25,0.25 0,0.5"
+ id="path61337"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:none"
+ d="m 918.5,355.25 0,-1.75 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"
+ id="path61339"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cssssc" />
+ <path
+ transform="matrix(1.5161021,0,0,1.5161021,-475.84616,-176.50693)"
+ sodipodi:type="arc"
+ style="color:#000000;fill:none;stroke:url(#linearGradient34967-4-1-8);stroke-width:0.52766895;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path61355"
+ sodipodi:cx="922"
+ 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" />
+ </g>
+ <g
+ style="opacity:0.8;stroke:#ff0000"
+ transform="matrix(-1,0,0,-1,1850,701)"
+ id="g34104">
+ <path
+ sodipodi:nodetypes="cszsc"
+ inkscape:connector-curvature="0"
+ id="path34106"
+ d="m 920.5,343.25 0,-1.5 c 0,-1.75 1.5,-2.25 4.5,-2.25 3,0 4.5,0.5 4.5,2.25 l 0,4.75"
+ style="fill:none;stroke:none" />
+ <path
+ sodipodi:nodetypes="csc"
+ inkscape:connector-curvature="0"
+ id="path34108"
+ d="m 914.5,350.5 c 0,3 1.28917,5 2.5,5 l 1.5,0"
+ style="fill:none;stroke:url(#linearGradient34969-4-4-1);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path34110"
+ d="m 920.75,343.5 4.5,0 0.25,0.25 0,0.5"
+ style="fill:none;stroke:url(#linearGradient34971-5-0-9);stroke-linecap:round;stroke-linejoin:round" />
+ <path
+ sodipodi:nodetypes="cssssc"
+ inkscape:connector-curvature="0"
+ id="path34113"
+ 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"
+ sodipodi:ry="1"
+ sodipodi:rx="1"
+ sodipodi:cy="342"
+ sodipodi:cx="922"
+ id="path34115"
+ style="color:#000000;fill:none;stroke:url(#linearGradient34975-9-4-9);stroke-width:0.52766895;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ transform="matrix(1.5161021,0,0,1.5161021,-475.84616,-176.50693)" />
+ <path
+ style="fill:none;stroke:none"
+ d="m 925.5,345 0,0.25 -0.25,0.25 -8.25,0 c -1.5,0 -2.5,2 -2.5,5"
+ id="path34901"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccsc" />
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ id="g46790"
+ transform="translate(0,12)" />
+ <g
+ id="g46890" />
+ <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>
+</svg>
diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png
index 41284eff9c1..7affcab8a82 100644
--- a/release/datafiles/splash.png
+++ b/release/datafiles/splash.png
Binary files differ
diff --git a/release/datafiles/startup.blend b/release/datafiles/startup.blend
index cdd43c74f3b..40e1363797a 100644
--- a/release/datafiles/startup.blend
+++ b/release/datafiles/startup.blend
Binary files differ
diff --git a/release/scripts/freestyle/data/env_map/brown00.png b/release/scripts/freestyle/data/env_map/brown00.png
new file mode 100644
index 00000000000..855f06f4fb9
--- /dev/null
+++ b/release/scripts/freestyle/data/env_map/brown00.png
Binary files differ
diff --git a/release/scripts/freestyle/data/env_map/gray00.png b/release/scripts/freestyle/data/env_map/gray00.png
new file mode 100644
index 00000000000..7c9b1a8149e
--- /dev/null
+++ b/release/scripts/freestyle/data/env_map/gray00.png
Binary files differ
diff --git a/release/scripts/freestyle/data/env_map/gray01.png b/release/scripts/freestyle/data/env_map/gray01.png
new file mode 100644
index 00000000000..06542908e6b
--- /dev/null
+++ b/release/scripts/freestyle/data/env_map/gray01.png
Binary files differ
diff --git a/release/scripts/freestyle/data/env_map/gray02.png b/release/scripts/freestyle/data/env_map/gray02.png
new file mode 100644
index 00000000000..0208f4920d9
--- /dev/null
+++ b/release/scripts/freestyle/data/env_map/gray02.png
Binary files differ
diff --git a/release/scripts/freestyle/data/env_map/gray03.png b/release/scripts/freestyle/data/env_map/gray03.png
new file mode 100644
index 00000000000..aab9b957c21
--- /dev/null
+++ b/release/scripts/freestyle/data/env_map/gray03.png
Binary files differ
diff --git a/release/scripts/freestyle/style_modules/ChainingIterators.py b/release/scripts/freestyle/style_modules/ChainingIterators.py
new file mode 100644
index 00000000000..f0dfc468adb
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/ChainingIterators.py
@@ -0,0 +1,703 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public 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 : ChainingIterators.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Chaining Iterators to be used with chaining operators
+
+from Freestyle import AdjacencyIterator, ChainingIterator, ExternalContourUP1D, Nature, TVertex
+from Freestyle import ContextFunctions as CF
+
+## the natural chaining iterator
+## It follows the edges of same nature following the topology of
+## objects with preseance on silhouettes, then borders,
+## then suggestive contours, then everything else. It doesn't chain the same ViewEdge twice
+## You can specify whether to stay in the selection or not.
+class pyChainSilhouetteIterator(ChainingIterator):
+ def __init__(self, stayInSelection=True):
+ ChainingIterator.__init__(self, stayInSelection, True, None, True)
+ def init(self):
+ pass
+ def traverse(self, iter):
+ winner = None
+ it = AdjacencyIterator(iter)
+ tvertex = self.next_vertex
+ if type(tvertex) is TVertex:
+ mateVE = tvertex.get_mate(self.current_edge)
+ while not it.is_end:
+ ve = it.object
+ if ve.id == mateVE.id:
+ winner = ve
+ break
+ it.increment()
+ else:
+ ## case of NonTVertex
+ natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
+ for i in range(len(natures)):
+ currentNature = self.current_edge.nature
+ if (natures[i] & currentNature) != 0:
+ count=0
+ while not it.is_end:
+ visitNext = 0
+ oNature = it.object.nature
+ if (oNature & natures[i]) != 0:
+ if natures[i] != oNature:
+ for j in range(i):
+ if (natures[j] & oNature) != 0:
+ visitNext = 1
+ break
+ if visitNext != 0:
+ break
+ count = count+1
+ winner = it.object
+ it.increment()
+ if count != 1:
+ winner = None
+ break
+ return winner
+
+## the natural chaining iterator
+## It follows the edges of same nature on the same
+## objects with preseance on silhouettes, then borders,
+## then suggestive contours, then everything else. It doesn't chain the same ViewEdge twice
+## You can specify whether to stay in the selection or not.
+## You can specify whether to chain iterate over edges that were
+## already visited or not.
+class pyChainSilhouetteGenericIterator(ChainingIterator):
+ def __init__(self, stayInSelection=True, stayInUnvisited=True):
+ ChainingIterator.__init__(self, stayInSelection, stayInUnvisited, None, True)
+ def init(self):
+ pass
+ def traverse(self, iter):
+ winner = None
+ it = AdjacencyIterator(iter)
+ tvertex = self.next_vertex
+ if type(tvertex) is TVertex:
+ mateVE = tvertex.get_mate(self.current_edge)
+ while not it.is_end:
+ ve = it.object
+ if ve.id == mateVE.id:
+ winner = ve
+ break
+ it.increment()
+ else:
+ ## case of NonTVertex
+ natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
+ for i in range(len(natures)):
+ currentNature = self.current_edge.nature
+ if (natures[i] & currentNature) != 0:
+ count=0
+ while not it.is_end:
+ visitNext = 0
+ oNature = it.object.nature
+ ve = it.object
+ if ve.id == self.current_edge.id:
+ it.increment()
+ continue
+ if (oNature & natures[i]) != 0:
+ if natures[i] != oNature:
+ for j in range(i):
+ if (natures[j] & oNature) != 0:
+ visitNext = 1
+ break
+ if visitNext != 0:
+ break
+ count = count+1
+ winner = ve
+ it.increment()
+ if count != 1:
+ winner = None
+ break
+ return winner
+
+class pyExternalContourChainingIterator(ChainingIterator):
+ def __init__(self):
+ ChainingIterator.__init__(self, False, True, None, True)
+ self._isExternalContour = ExternalContourUP1D()
+ def init(self):
+ self._nEdges = 0
+ self._isInSelection = 1
+ def checkViewEdge(self, ve, orientation):
+ if orientation != 0:
+ vertex = ve.second_svertex()
+ else:
+ vertex = ve.first_svertex()
+ it = AdjacencyIterator(vertex,1,1)
+ while not it.is_end:
+ ave = it.object
+ if self._isExternalContour(ave):
+ return 1
+ it.increment()
+ print("pyExternlContourChainingIterator : didn't find next edge")
+ return 0
+ def traverse(self, iter):
+ winner = None
+ it = AdjacencyIterator(iter)
+ while not it.is_end:
+ ve = it.object
+ if self._isExternalContour(ve):
+ if ve.time_stamp == CF.get_time_stamp():
+ winner = ve
+ it.increment()
+
+ self._nEdges = self._nEdges+1
+ if winner is None:
+ orient = 1
+ it = AdjacencyIterator(iter)
+ while not it.is_end:
+ ve = it.object
+ if it.is_incoming:
+ orient = 0
+ good = self.checkViewEdge(ve,orient)
+ if good != 0:
+ winner = ve
+ it.increment()
+ return winner
+
+## the natural chaining iterator
+## with a sketchy multiple touch
+class pySketchyChainSilhouetteIterator(ChainingIterator):
+ def __init__(self, nRounds=3,stayInSelection=True):
+ ChainingIterator.__init__(self, stayInSelection, False, None, True)
+ self._timeStamp = CF.get_time_stamp()+nRounds
+ self._nRounds = nRounds
+ def init(self):
+ self._timeStamp = CF.get_time_stamp()+self._nRounds
+ def traverse(self, iter):
+ winner = None
+ it = AdjacencyIterator(iter)
+ tvertex = self.next_vertex
+ if type(tvertex) is TVertex:
+ mateVE = tvertex.get_mate(self.current_edge)
+ while not it.is_end:
+ ve = it.object
+ if ve.id == mateVE.id:
+ winner = ve
+ break
+ it.increment()
+ else:
+ ## case of NonTVertex
+ natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
+ for i in range(len(natures)):
+ currentNature = self.current_edge.nature
+ if (natures[i] & currentNature) != 0:
+ count=0
+ while not it.is_end:
+ visitNext = 0
+ oNature = it.object.nature
+ ve = it.object
+ if ve.id == self.current_edge.id:
+ it.increment()
+ continue
+ if (oNature & natures[i]) != 0:
+ if (natures[i] != oNature) != 0:
+ for j in range(i):
+ if (natures[j] & oNature) != 0:
+ visitNext = 1
+ break
+ if visitNext != 0:
+ break
+ count = count+1
+ winner = ve
+ it.increment()
+ if count != 1:
+ winner = None
+ break
+ if winner is None:
+ winner = self.current_edge
+ if winner.chaining_time_stamp == self._timeStamp:
+ winner = None
+ return winner
+
+
+# Chaining iterator designed for sketchy style.
+# can chain several times the same ViewEdge
+# in order to produce multiple strokes per ViewEdge.
+class pySketchyChainingIterator(ChainingIterator):
+ def __init__(self, nRounds=3, stayInSelection=True):
+ ChainingIterator.__init__(self, stayInSelection, False, None, True)
+ self._timeStamp = CF.get_time_stamp()+nRounds
+ self._nRounds = nRounds
+ def init(self):
+ self._timeStamp = CF.get_time_stamp()+self._nRounds
+ def traverse(self, iter):
+ winner = None
+ it = AdjacencyIterator(iter)
+ while not it.is_end:
+ ve = it.object
+ if ve.id == self.current_edge.id:
+ it.increment()
+ continue
+ winner = ve
+ it.increment()
+ if winner is None:
+ winner = self.current_edge
+ if winner.chaining_time_stamp == self._timeStamp:
+ return None
+ return winner
+
+
+## Chaining iterator that fills small occlusions
+## percent
+## The max length of the occluded part
+## expressed in % of the total chain length
+class pyFillOcclusionsRelativeChainingIterator(ChainingIterator):
+ def __init__(self, percent):
+ ChainingIterator.__init__(self, False, True, None, True)
+ self._length = 0
+ self._percent = float(percent)
+ def init(self):
+ # each time we're evaluating a chain length
+ # we try to do it once. Thus we reinit
+ # the chain length here:
+ self._length = 0
+ def traverse(self, iter):
+ winner = None
+ winnerOrientation = 0
+ print(self.current_edge.id.first, self.current_edge.id.second)
+ it = AdjacencyIterator(iter)
+ tvertex = self.next_vertex
+ if type(tvertex) is TVertex:
+ mateVE = tvertex.get_mate(self.current_edge)
+ while not it.is_end:
+ ve = it.object
+ if ve.id == mateVE.id:
+ winner = ve
+ if not it.is_incoming:
+ winnerOrientation = 1
+ else:
+ winnerOrientation = 0
+ break
+ it.increment()
+ else:
+ ## case of NonTVertex
+ natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
+ for nat in natures:
+ if (self.current_edge.nature & nat) != 0:
+ count=0
+ while not it.is_end:
+ ve = it.object
+ if (ve.nature & nat) != 0:
+ count = count+1
+ winner = ve
+ if not it.is_incoming:
+ winnerOrientation = 1
+ else:
+ winnerOrientation = 0
+ it.increment()
+ if count != 1:
+ winner = None
+ break
+ if winner is not None:
+ # check whether this edge was part of the selection
+ if winner.time_stamp != CF.get_time_stamp():
+ #print("---", winner.id.first, winner.id.second)
+ # if not, let's check whether it's short enough with
+ # respect to the chain made without staying in the selection
+ #------------------------------------------------------------
+ # Did we compute the prospective chain length already ?
+ if self._length == 0:
+ #if not, let's do it
+ _it = pyChainSilhouetteGenericIterator(0,0)
+ _it.begin = winner
+ _it.current_edge = winner
+ _it.orientation = winnerOrientation
+ _it.init()
+ while not _it.is_end:
+ ve = _it.object
+ #print("--------", ve.id.first, ve.id.second)
+ self._length = self._length + ve.length_2d
+ _it.increment()
+ if _it.is_begin:
+ break;
+ _it.begin = winner
+ _it.current_edge = winner
+ _it.orientation = winnerOrientation
+ if not _it.is_begin:
+ _it.decrement()
+ while (not _it.is_end) and (not _it.is_begin):
+ ve = _it.object
+ #print("--------", ve.id.first, ve.id.second)
+ self._length = self._length + ve.length_2d
+ _it.decrement()
+
+ # let's do the comparison:
+ # nw let's compute the length of this connex non selected part:
+ connexl = 0
+ _cit = pyChainSilhouetteGenericIterator(0,0)
+ _cit.begin = winner
+ _cit.current_edge = winner
+ _cit.orientation = winnerOrientation
+ _cit.init()
+ while _cit.is_end == 0 and _cit.object.time_stamp != CF.get_time_stamp():
+ ve = _cit.object
+ #print("-------- --------", ve.id.first, ve.id.second)
+ connexl = connexl + ve.length_2d
+ _cit.increment()
+ if connexl > self._percent * self._length:
+ winner = None
+ return winner
+
+## Chaining iterator that fills small occlusions
+## size
+## The max length of the occluded part
+## expressed in pixels
+class pyFillOcclusionsAbsoluteChainingIterator(ChainingIterator):
+ def __init__(self, length):
+ ChainingIterator.__init__(self, False, True, None, True)
+ self._length = float(length)
+ def init(self):
+ pass
+ def traverse(self, iter):
+ winner = None
+ winnerOrientation = 0
+ #print(self.current_edge.id.first, self.current_edge.id.second)
+ it = AdjacencyIterator(iter)
+ tvertex = self.next_vertex
+ if type(tvertex) is TVertex:
+ mateVE = tvertex.get_mate(self.current_edge)
+ while not it.is_end:
+ ve = it.object
+ if ve.id == mateVE.id:
+ winner = ve
+ if not it.is_incoming:
+ winnerOrientation = 1
+ else:
+ winnerOrientation = 0
+ break
+ it.increment()
+ else:
+ ## case of NonTVertex
+ natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
+ for nat in natures:
+ if (self.current_edge.nature & nat) != 0:
+ count=0
+ while not it.is_end:
+ ve = it.object
+ if (ve.nature & nat) != 0:
+ count = count+1
+ winner = ve
+ if not it.is_incoming:
+ winnerOrientation = 1
+ else:
+ winnerOrientation = 0
+ it.increment()
+ if count != 1:
+ winner = None
+ break
+ if winner is not None:
+ # check whether this edge was part of the selection
+ if winner.time_stamp != CF.get_time_stamp():
+ #print("---", winner.id.first, winner.id.second)
+ # nw let's compute the length of this connex non selected part:
+ connexl = 0
+ _cit = pyChainSilhouetteGenericIterator(0,0)
+ _cit.begin = winner
+ _cit.current_edge = winner
+ _cit.orientation = winnerOrientation
+ _cit.init()
+ while _cit.is_end == 0 and _cit.object.time_stamp != CF.get_time_stamp():
+ ve = _cit.object
+ #print("-------- --------", ve.id.first, ve.id.second)
+ connexl = connexl + ve.length_2d
+ _cit.increment()
+ if connexl > self._length:
+ winner = None
+ return winner
+
+
+## Chaining iterator that fills small occlusions
+## percent
+## The max length of the occluded part
+## expressed in % of the total chain length
+class pyFillOcclusionsAbsoluteAndRelativeChainingIterator(ChainingIterator):
+ def __init__(self, percent, l):
+ ChainingIterator.__init__(self, False, True, None, True)
+ self._length = 0
+ self._absLength = l
+ self._percent = float(percent)
+ def init(self):
+ # each time we're evaluating a chain length
+ # we try to do it once. Thus we reinit
+ # the chain length here:
+ self._length = 0
+ def traverse(self, iter):
+ winner = None
+ winnerOrientation = 0
+ print(self.current_edge.id.first, self.current_edge.id.second)
+ it = AdjacencyIterator(iter)
+ tvertex = self.next_vertex
+ if type(tvertex) is TVertex:
+ mateVE = tvertex.get_mate(self.current_edge)
+ while not it.is_end:
+ ve = it.object
+ if ve.id == mateVE.id:
+ winner = ve
+ if not it.is_incoming:
+ winnerOrientation = 1
+ else:
+ winnerOrientation = 0
+ break
+ it.increment()
+ else:
+ ## case of NonTVertex
+ natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
+ for nat in natures:
+ if (self.current_edge.nature & nat) != 0:
+ count=0
+ while not it.is_end:
+ ve = it.object
+ if (ve.nature & nat) != 0:
+ count = count+1
+ winner = ve
+ if not it.is_incoming:
+ winnerOrientation = 1
+ else:
+ winnerOrientation = 0
+ it.increment()
+ if count != 1:
+ winner = None
+ break
+ if winner is not None:
+ # check whether this edge was part of the selection
+ if winner.time_stamp != CF.get_time_stamp():
+ #print("---", winner.id.first, winner.id.second)
+ # if not, let's check whether it's short enough with
+ # respect to the chain made without staying in the selection
+ #------------------------------------------------------------
+ # Did we compute the prospective chain length already ?
+ if self._length == 0:
+ #if not, let's do it
+ _it = pyChainSilhouetteGenericIterator(0,0)
+ _it.begin = winner
+ _it.current_edge = winner
+ _it.orientation = winnerOrientation
+ _it.init()
+ while not _it.is_end:
+ ve = _it.object
+ #print("--------", ve.id.first, ve.id.second)
+ self._length = self._length + ve.length_2d
+ _it.increment()
+ if _it.is_begin:
+ break;
+ _it.begin = winner
+ _it.current_edge = winner
+ _it.orientation = winnerOrientation
+ if not _it.is_begin:
+ _it.decrement()
+ while (not _it.is_end) and (not _it.is_begin):
+ ve = _it.object
+ #print("--------", ve.id.first, ve.id.second)
+ self._length = self._length + ve.length_2d
+ _it.decrement()
+
+ # let's do the comparison:
+ # nw let's compute the length of this connex non selected part:
+ connexl = 0
+ _cit = pyChainSilhouetteGenericIterator(0,0)
+ _cit.begin = winner
+ _cit.current_edge = winner
+ _cit.orientation = winnerOrientation
+ _cit.init()
+ while _cit.is_end == 0 and _cit.object.time_stamp != CF.get_time_stamp():
+ ve = _cit.object
+ #print("-------- --------", ve.id.first, ve.id.second)
+ connexl = connexl + ve.length_2d
+ _cit.increment()
+ if (connexl > self._percent * self._length) or (connexl > self._absLength):
+ winner = None
+ return winner
+
+## Chaining iterator that fills small occlusions without caring about the
+## actual selection
+## percent
+## The max length of the occluded part
+## expressed in % of the total chain length
+class pyFillQi0AbsoluteAndRelativeChainingIterator(ChainingIterator):
+ def __init__(self, percent, l):
+ ChainingIterator.__init__(self, False, True, None, True)
+ self._length = 0
+ self._absLength = l
+ self._percent = float(percent)
+ def init(self):
+ # each time we're evaluating a chain length
+ # we try to do it once. Thus we reinit
+ # the chain length here:
+ self._length = 0
+ def traverse(self, iter):
+ winner = None
+ winnerOrientation = 0
+ print(self.current_edge.id.first, self.current_edge.id.second)
+ it = AdjacencyIterator(iter)
+ tvertex = self.next_vertex
+ if type(tvertex) is TVertex:
+ mateVE = tvertex.get_mate(self.current_edge)
+ while not it.is_end:
+ ve = it.object
+ if ve.id == mateVE.id:
+ winner = ve
+ if not it.is_incoming:
+ winnerOrientation = 1
+ else:
+ winnerOrientation = 0
+ break
+ it.increment()
+ else:
+ ## case of NonTVertex
+ natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
+ for nat in natures:
+ if (self.current_edge.nature & nat) != 0:
+ count=0
+ while not it.is_end:
+ ve = it.object
+ if (ve.nature & nat) != 0:
+ count = count+1
+ winner = ve
+ if not it.is_incoming:
+ winnerOrientation = 1
+ else:
+ winnerOrientation = 0
+ it.increment()
+ if count != 1:
+ winner = None
+ break
+ if winner is not None:
+ # check whether this edge was part of the selection
+ if winner.qi != 0:
+ #print("---", winner.id.first, winner.id.second)
+ # if not, let's check whether it's short enough with
+ # respect to the chain made without staying in the selection
+ #------------------------------------------------------------
+ # Did we compute the prospective chain length already ?
+ if self._length == 0:
+ #if not, let's do it
+ _it = pyChainSilhouetteGenericIterator(0,0)
+ _it.begin = winner
+ _it.current_edge = winner
+ _it.orientation = winnerOrientation
+ _it.init()
+ while not _it.is_end:
+ ve = _it.object
+ #print("--------", ve.id.first, ve.id.second)
+ self._length = self._length + ve.length_2d
+ _it.increment()
+ if _it.is_begin:
+ break;
+ _it.begin = winner
+ _it.current_edge = winner
+ _it.orientation = winnerOrientation
+ if not _it.is_begin:
+ _it.decrement()
+ while (not _it.is_end) and (not _it.is_begin):
+ ve = _it.object
+ #print("--------", ve.id.first, ve.id.second)
+ self._length = self._length + ve.length_2d
+ _it.decrement()
+
+ # let's do the comparison:
+ # nw let's compute the length of this connex non selected part:
+ connexl = 0
+ _cit = pyChainSilhouetteGenericIterator(0,0)
+ _cit.begin = winner
+ _cit.current_edge = winner
+ _cit.orientation = winnerOrientation
+ _cit.init()
+ while not _cit.is_end and _cit.object.qi != 0:
+ ve = _cit.object
+ #print("-------- --------", ve.id.first, ve.id.second)
+ connexl = connexl + ve.length_2d
+ _cit.increment()
+ if (connexl > self._percent * self._length) or (connexl > self._absLength):
+ winner = None
+ return winner
+
+
+## the natural chaining iterator
+## It follows the edges of same nature on the same
+## objects with preseance on silhouettes, then borders,
+## then suggestive contours, then everything else. It doesn't chain the same ViewEdge twice
+## You can specify whether to stay in the selection or not.
+class pyNoIdChainSilhouetteIterator(ChainingIterator):
+ def __init__(self, stayInSelection=True):
+ ChainingIterator.__init__(self, stayInSelection, True, None, True)
+ def init(self):
+ pass
+ def traverse(self, iter):
+ winner = None
+ it = AdjacencyIterator(iter)
+ tvertex = self.next_vertex
+ if type(tvertex) is TVertex:
+ mateVE = tvertex.get_mate(self.current_edge)
+ while not it.is_end:
+ ve = it.object
+ feB = self.current_edge.last_fedge
+ feA = ve.first_fedge
+ vB = feB.second_svertex
+ vA = feA.first_svertex
+ if vA.id.first == vB.id.first:
+ winner = ve
+ break
+ feA = self.current_edge.first_fedge
+ feB = ve.last_fedge
+ vB = feB.second_svertex
+ vA = feA.first_svertex
+ if vA.id.first == vB.id.first:
+ winner = ve
+ break
+ feA = self.current_edge.last_fedge
+ feB = ve.last_fedge
+ vB = feB.second_svertex
+ vA = feA.second_svertex
+ if vA.id.first == vB.id.first:
+ winner = ve
+ break
+ feA = self.current_edge.first_fedge
+ feB = ve.first_fedge
+ vB = feB.first_svertex
+ vA = feA.first_svertex
+ if vA.id.first == vB.id.first:
+ winner = ve
+ break
+ it.increment()
+ else:
+ ## case of NonTVertex
+ natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE]
+ for i in range(len(natures)):
+ currentNature = self.current_edge.nature
+ if (natures[i] & currentNature) != 0:
+ count=0
+ while not it.is_end:
+ visitNext = 0
+ oNature = it.object.nature
+ if (oNature & natures[i]) != 0:
+ if natures[i] != oNature:
+ for j in range(i):
+ if (natures[j] & oNature) != 0:
+ visitNext = 1
+ break
+ if visitNext != 0:
+ break
+ count = count+1
+ winner = it.object
+ it.increment()
+ if count != 1:
+ winner = None
+ break
+ return winner
+
diff --git a/release/scripts/freestyle/style_modules/Functions0D.py b/release/scripts/freestyle/style_modules/Functions0D.py
new file mode 100644
index 00000000000..b36961f3f91
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/Functions0D.py
@@ -0,0 +1,105 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public 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 : Functions0D.py
+# Authors : Fredo Durand, Stephane Grabli, Francois Sillion, Emmanuel Turquin
+# Date : 30/06/2005
+# Purpose : Functions (functors) to be used for 0D elements
+
+from Freestyle import Curvature2DAngleF0D, CurvePoint, ReadCompleteViewMapPixelF0D, \
+ ReadSteerableViewMapPixelF0D, UnaryFunction0DDouble, UnaryFunction0DMaterial, \
+ UnaryFunction0DVec2f
+from Freestyle import ContextFunctions as CF
+
+import math
+import mathutils
+
+class CurveMaterialF0D(UnaryFunction0DMaterial):
+ # A replacement of the built-in MaterialF0D for stroke creation.
+ # MaterialF0D does not work with Curves and Strokes.
+ def __call__(self, inter):
+ cp = inter.object
+ assert(isinstance(cp, CurvePoint))
+ fe = cp.first_svertex.get_fedge(cp.second_svertex)
+ assert(fe is not None)
+ return fe.material if fe.is_smooth else fe.material_left
+
+class pyInverseCurvature2DAngleF0D(UnaryFunction0DDouble):
+ def __call__(self, inter):
+ func = Curvature2DAngleF0D()
+ c = func(inter)
+ return (3.1415 - c)
+
+class pyCurvilinearLengthF0D(UnaryFunction0DDouble):
+ def __call__(self, inter):
+ cp = inter.object
+ assert(isinstance(cp, CurvePoint))
+ return cp.t2d
+
+## estimate anisotropy of density
+class pyDensityAnisotropyF0D(UnaryFunction0DDouble):
+ def __init__(self,level):
+ UnaryFunction0DDouble.__init__(self)
+ self.IsoDensity = ReadCompleteViewMapPixelF0D(level)
+ self.d0Density = ReadSteerableViewMapPixelF0D(0, level)
+ self.d1Density = ReadSteerableViewMapPixelF0D(1, level)
+ self.d2Density = ReadSteerableViewMapPixelF0D(2, level)
+ self.d3Density = ReadSteerableViewMapPixelF0D(3, level)
+ def __call__(self, inter):
+ c_iso = self.IsoDensity(inter)
+ c_0 = self.d0Density(inter)
+ c_1 = self.d1Density(inter)
+ c_2 = self.d2Density(inter)
+ c_3 = self.d3Density(inter)
+ cMax = max(max(c_0,c_1), max(c_2,c_3))
+ cMin = min(min(c_0,c_1), min(c_2,c_3))
+ if c_iso == 0:
+ v = 0
+ else:
+ v = (cMax-cMin)/c_iso
+ return v
+
+## Returns the gradient vector for a pixel
+## l
+## the level at which one wants to compute the gradient
+class pyViewMapGradientVectorF0D(UnaryFunction0DVec2f):
+ def __init__(self, l):
+ UnaryFunction0DVec2f.__init__(self)
+ self._l = l
+ self._step = math.pow(2,self._l)
+ def __call__(self, iter):
+ p = iter.object.point_2d
+ gx = CF.read_complete_view_map_pixel(self._l, int(p.x+self._step), int(p.y)) - \
+ CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y))
+ gy = CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y+self._step)) - \
+ CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y))
+ return mathutils.Vector([gx, gy])
+
+class pyViewMapGradientNormF0D(UnaryFunction0DDouble):
+ def __init__(self, l):
+ UnaryFunction0DDouble.__init__(self)
+ self._l = l
+ self._step = math.pow(2,self._l)
+ def __call__(self, iter):
+ p = iter.object.point_2d
+ gx = CF.read_complete_view_map_pixel(self._l, int(p.x+self._step), int(p.y)) - \
+ CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y))
+ gy = CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y+self._step)) - \
+ CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y))
+ grad = mathutils.Vector([gx, gy])
+ return grad.length
diff --git a/release/scripts/freestyle/style_modules/Functions1D.py b/release/scripts/freestyle/style_modules/Functions1D.py
new file mode 100644
index 00000000000..17b4f1922a6
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/Functions1D.py
@@ -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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : Functions1D.py
+# Authors : Fredo Durand, Stephane Grabli, Francois Sillion, Emmanuel Turquin
+# Date : 08/04/2005
+# Purpose : Functions (functors) to be used for 1D elements
+
+from Freestyle import GetProjectedZF1D, IntegrationType, UnaryFunction1DDouble, integrate
+from Functions0D import pyDensityAnisotropyF0D, pyViewMapGradientNormF0D
+import string
+
+class pyGetInverseProjectedZF1D(UnaryFunction1DDouble):
+ def __call__(self, inter):
+ func = GetProjectedZF1D()
+ z = func(inter)
+ return (1.0 - z)
+
+class pyGetSquareInverseProjectedZF1D(UnaryFunction1DDouble):
+ def __call__(self, inter):
+ func = GetProjectedZF1D()
+ z = func(inter)
+ return (1.0 - z*z)
+
+class pyDensityAnisotropyF1D(UnaryFunction1DDouble):
+ def __init__(self,level, integrationType=IntegrationType.MEAN, sampling=2.0):
+ UnaryFunction1DDouble.__init__(self, integrationType)
+ self._func = pyDensityAnisotropyF0D(level)
+ self._integration = integrationType
+ self._sampling = sampling
+ def __call__(self, inter):
+ v = integrate(self._func, inter.pointsBegin(self._sampling), inter.pointsEnd(self._sampling), self._integration)
+ return v
+
+class pyViewMapGradientNormF1D(UnaryFunction1DDouble):
+ def __init__(self,l, integrationType, sampling=2.0):
+ UnaryFunction1DDouble.__init__(self, integrationType)
+ self._func = pyViewMapGradientNormF0D(l)
+ self._integration = integrationType
+ self._sampling = sampling
+ def __call__(self, inter):
+ v = integrate(self._func, inter.pointsBegin(self._sampling), inter.pointsEnd(self._sampling), self._integration)
+ return v
diff --git a/release/scripts/freestyle/style_modules/PredicatesB1D.py b/release/scripts/freestyle/style_modules/PredicatesB1D.py
new file mode 100644
index 00000000000..642ff5f9845
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/PredicatesB1D.py
@@ -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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : PredicatesB1D.py
+# Authors : Fredo Durand, Stephane Grabli, Francois Sillion, Emmanuel Turquin
+# Date : 08/04/2005
+# Purpose : Binary predicates (functors) to be used for 1D elements
+
+from Freestyle import BinaryPredicate1D, GetZF1D, IntegrationType, Nature, SameShapeIdBP1D, ZDiscontinuityF1D
+from Functions1D import pyViewMapGradientNormF1D
+
+import random
+
+class pyZBP1D(BinaryPredicate1D):
+ def __call__(self, i1, i2):
+ func = GetZF1D()
+ return (func(i1) > func(i2))
+
+class pyZDiscontinuityBP1D(BinaryPredicate1D):
+ def __init__(self, iType = IntegrationType.MEAN):
+ BinaryPredicate1D.__init__(self)
+ self._GetZDiscontinuity = ZDiscontinuityF1D(iType)
+ def __call__(self, i1, i2):
+ return (self._GetZDiscontinuity(i1) > self._GetZDiscontinuity(i2))
+
+class pyLengthBP1D(BinaryPredicate1D):
+ def __call__(self, i1, i2):
+ return (i1.length_2d > i2.length_2d)
+
+class pySilhouetteFirstBP1D(BinaryPredicate1D):
+ def __call__(self, inter1, inter2):
+ bpred = SameShapeIdBP1D()
+ if (bpred(inter1, inter2) != 1):
+ return 0
+ if (inter1.nature & Nature.SILHOUETTE):
+ return (inter2.nature & Nature.SILHOUETTE) != 0
+ return (inter1.nature == inter2.nature)
+
+class pyNatureBP1D(BinaryPredicate1D):
+ def __call__(self, inter1, inter2):
+ return (inter1.nature & inter2.nature)
+
+class pyViewMapGradientNormBP1D(BinaryPredicate1D):
+ def __init__(self,l, sampling=2.0):
+ BinaryPredicate1D.__init__(self)
+ self._GetGradient = pyViewMapGradientNormF1D(l, IntegrationType.MEAN)
+ def __call__(self, i1,i2):
+ print("compare gradient")
+ return (self._GetGradient(i1) > self._GetGradient(i2))
+
+class pyShuffleBP1D(BinaryPredicate1D):
+ def __init__(self):
+ BinaryPredicate1D.__init__(self)
+ random.seed(1)
+ def __call__(self, inter1, inter2):
+ r1 = random.uniform(0,1)
+ r2 = random.uniform(0,1)
+ return (r1<r2)
diff --git a/release/scripts/freestyle/style_modules/PredicatesU0D.py b/release/scripts/freestyle/style_modules/PredicatesU0D.py
new file mode 100644
index 00000000000..49675eb3c6a
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/PredicatesU0D.py
@@ -0,0 +1,96 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public 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 : PredicatesU0D.py
+# Authors : Fredo Durand, Stephane Grabli, Francois Sillion, Emmanuel Turquin
+# Date : 08/04/2005
+# Purpose : Unary predicates (functors) to be used for 0D elements
+
+from Freestyle import Curvature2DAngleF0D, Nature, QuantitativeInvisibilityF0D, UnaryPredicate0D
+from Functions0D import pyCurvilinearLengthF0D
+
+class pyHigherCurvature2DAngleUP0D(UnaryPredicate0D):
+ def __init__(self,a):
+ UnaryPredicate0D.__init__(self)
+ self._a = a
+ def __call__(self, inter):
+ func = Curvature2DAngleF0D()
+ a = func(inter)
+ return (a > self._a)
+
+class pyUEqualsUP0D(UnaryPredicate0D):
+ def __init__(self,u, w):
+ UnaryPredicate0D.__init__(self)
+ self._u = u
+ self._w = w
+ def __call__(self, inter):
+ func = pyCurvilinearLengthF0D()
+ u = func(inter)
+ return (u > (self._u-self._w)) and (u < (self._u+self._w))
+
+class pyVertexNatureUP0D(UnaryPredicate0D):
+ def __init__(self,nature):
+ UnaryPredicate0D.__init__(self)
+ self._nature = nature
+ def __call__(self, inter):
+ v = inter.object
+ return (v.nature & self._nature) != 0
+
+## check whether an Interface0DIterator
+## is a TVertex and is the one that is
+## hidden (inferred from the context)
+class pyBackTVertexUP0D(UnaryPredicate0D):
+ def __init__(self):
+ UnaryPredicate0D.__init__(self)
+ self._getQI = QuantitativeInvisibilityF0D()
+ def __call__(self, iter):
+ if (iter.object.nature & Nature.T_VERTEX) == 0:
+ return 0
+ if iter.is_end:
+ return 0
+ if self._getQI(iter) != 0:
+ return 1
+ return 0
+
+class pyParameterUP0DGoodOne(UnaryPredicate0D):
+ def __init__(self,pmin,pmax):
+ UnaryPredicate0D.__init__(self)
+ self._m = pmin
+ self._M = pmax
+ #self.getCurvilinearAbscissa = GetCurvilinearAbscissaF0D()
+ def __call__(self, inter):
+ #s = self.getCurvilinearAbscissa(inter)
+ u = inter.u
+ #print(u)
+ return ((u>=self._m) and (u<=self._M))
+
+class pyParameterUP0D(UnaryPredicate0D):
+ def __init__(self,pmin,pmax):
+ UnaryPredicate0D.__init__(self)
+ self._m = pmin
+ self._M = pmax
+ #self.getCurvilinearAbscissa = GetCurvilinearAbscissaF0D()
+ def __call__(self, inter):
+ func = Curvature2DAngleF0D()
+ c = func(inter)
+ b1 = (c>0.1)
+ #s = self.getCurvilinearAbscissa(inter)
+ u = inter.u
+ #print(u)
+ b = ((u>=self._m) and (u<=self._M))
+ return b and b1
diff --git a/release/scripts/freestyle/style_modules/PredicatesU1D.py b/release/scripts/freestyle/style_modules/PredicatesU1D.py
new file mode 100644
index 00000000000..5c48219e9f4
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/PredicatesU1D.py
@@ -0,0 +1,342 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public 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 : PredicatesU1D.py
+# Authors : Fredo Durand, Stephane Grabli, Francois Sillion, Emmanuel Turquin
+# Date : 08/04/2005
+# Purpose : Unary predicates (functors) to be used for 1D elements
+
+from Freestyle import Curvature2DAngleF0D, CurveNatureF1D, DensityF1D, GetCompleteViewMapDensityF1D, \
+ GetDirectionalViewMapDensityF1D, GetOccludersF1D, GetProjectedZF1D, GetShapeF1D, GetSteerableViewMapDensityF1D, \
+ IntegrationType, ShapeUP1D, TVertex, UnaryPredicate1D
+from Functions1D import pyDensityAnisotropyF1D, pyViewMapGradientNormF1D
+
+class pyNFirstUP1D(UnaryPredicate1D):
+ def __init__(self, n):
+ UnaryPredicate1D.__init__(self)
+ self.__n = n
+ self.__count = 0
+ def __call__(self, inter):
+ self.__count = self.__count + 1
+ if self.__count <= self.__n:
+ return 1
+ return 0
+
+class pyHigherLengthUP1D(UnaryPredicate1D):
+ def __init__(self,l):
+ UnaryPredicate1D.__init__(self)
+ self._l = l
+ def __call__(self, inter):
+ return (inter.length_2d > self._l)
+
+class pyNatureUP1D(UnaryPredicate1D):
+ def __init__(self,nature):
+ UnaryPredicate1D.__init__(self)
+ self._nature = nature
+ self._getNature = CurveNatureF1D()
+ def __call__(self, inter):
+ if(self._getNature(inter) & self._nature):
+ return 1
+ return 0
+
+class pyHigherNumberOfTurnsUP1D(UnaryPredicate1D):
+ def __init__(self,n,a):
+ UnaryPredicate1D.__init__(self)
+ self._n = n
+ self._a = a
+ def __call__(self, inter):
+ count = 0
+ func = Curvature2DAngleF0D()
+ it = inter.vertices_begin()
+ while not it.is_end:
+ if func(it) > self._a:
+ count = count+1
+ if count > self._n:
+ return 1
+ it.increment()
+ return 0
+
+class pyDensityUP1D(UnaryPredicate1D):
+ def __init__(self,wsize,threshold, integration = IntegrationType.MEAN, sampling=2.0):
+ UnaryPredicate1D.__init__(self)
+ self._wsize = wsize
+ self._threshold = threshold
+ self._integration = integration
+ self._func = DensityF1D(self._wsize, self._integration, sampling)
+ def __call__(self, inter):
+ if self._func(inter) < self._threshold:
+ return 1
+ return 0
+
+class pyLowSteerableViewMapDensityUP1D(UnaryPredicate1D):
+ def __init__(self,threshold, level,integration = IntegrationType.MEAN):
+ UnaryPredicate1D.__init__(self)
+ self._threshold = threshold
+ self._level = level
+ self._integration = integration
+ def __call__(self, inter):
+ func = GetSteerableViewMapDensityF1D(self._level, self._integration)
+ v = func(inter)
+ print(v)
+ if v < self._threshold:
+ return 1
+ return 0
+
+class pyLowDirectionalViewMapDensityUP1D(UnaryPredicate1D):
+ def __init__(self,threshold, orientation, level,integration = IntegrationType.MEAN):
+ UnaryPredicate1D.__init__(self)
+ self._threshold = threshold
+ self._orientation = orientation
+ self._level = level
+ self._integration = integration
+ def __call__(self, inter):
+ func = GetDirectionalViewMapDensityF1D(self._orientation, self._level, self._integration)
+ v = func(inter)
+ #print(v)
+ if v < self._threshold:
+ return 1
+ return 0
+
+class pyHighSteerableViewMapDensityUP1D(UnaryPredicate1D):
+ def __init__(self,threshold, level,integration = IntegrationType.MEAN):
+ UnaryPredicate1D.__init__(self)
+ self._threshold = threshold
+ self._level = level
+ self._integration = integration
+ self._func = GetSteerableViewMapDensityF1D(self._level, self._integration)
+ def __call__(self, inter):
+ v = self._func(inter)
+ if v > self._threshold:
+ return 1
+ return 0
+
+class pyHighDirectionalViewMapDensityUP1D(UnaryPredicate1D):
+ def __init__(self,threshold, orientation, level,integration = IntegrationType.MEAN, sampling=2.0):
+ UnaryPredicate1D.__init__(self)
+ self._threshold = threshold
+ self._orientation = orientation
+ self._level = level
+ self._integration = integration
+ self._sampling = sampling
+ def __call__(self, inter):
+ func = GetDirectionalViewMapDensityF1D(self._orientation, self._level, self._integration, self._sampling)
+ v = func(inter)
+ if v > self._threshold:
+ return 1
+ return 0
+
+class pyHighViewMapDensityUP1D(UnaryPredicate1D):
+ def __init__(self,threshold, level,integration = IntegrationType.MEAN, sampling=2.0):
+ UnaryPredicate1D.__init__(self)
+ self._threshold = threshold
+ self._level = level
+ self._integration = integration
+ self._sampling = sampling
+ self._func = GetCompleteViewMapDensityF1D(self._level, self._integration, self._sampling) # 2.0 is the smpling
+ def __call__(self, inter):
+ #print("toto")
+ #print(func.name)
+ #print(inter.name)
+ v= self._func(inter)
+ if v > self._threshold:
+ return 1
+ return 0
+
+class pyDensityFunctorUP1D(UnaryPredicate1D):
+ def __init__(self,wsize,threshold, functor, funcmin=0.0, funcmax=1.0, integration = IntegrationType.MEAN):
+ UnaryPredicate1D.__init__(self)
+ self._wsize = wsize
+ self._threshold = float(threshold)
+ self._functor = functor
+ self._funcmin = float(funcmin)
+ self._funcmax = float(funcmax)
+ self._integration = integration
+ def __call__(self, inter):
+ func = DensityF1D(self._wsize, self._integration)
+ res = self._functor(inter)
+ k = (res-self._funcmin)/(self._funcmax-self._funcmin)
+ if func(inter) < self._threshold*k:
+ return 1
+ return 0
+
+class pyZSmallerUP1D(UnaryPredicate1D):
+ def __init__(self,z, integration=IntegrationType.MEAN):
+ UnaryPredicate1D.__init__(self)
+ self._z = z
+ self._integration = integration
+ def __call__(self, inter):
+ func = GetProjectedZF1D(self._integration)
+ if func(inter) < self._z:
+ return 1
+ return 0
+
+class pyIsOccludedByUP1D(UnaryPredicate1D):
+ def __init__(self,id):
+ UnaryPredicate1D.__init__(self)
+ self._id = id
+ def __call__(self, inter):
+ func = GetShapeF1D()
+ shapes = func(inter)
+ for s in shapes:
+ if(s.id == self._id):
+ return 0
+ it = inter.vertices_begin()
+ itlast = inter.vertices_end()
+ itlast.decrement()
+ v = it.object
+ vlast = itlast.object
+ tvertex = v.viewvertex
+ if type(tvertex) is TVertex:
+ print("TVertex: [ ", tvertex.id.first, ",", tvertex.id.second," ]")
+ eit = tvertex.edges_begin()
+ while not eit.is_end:
+ ve, incoming = eit.object
+ if ve.id == self._id:
+ return 1
+ print("-------", ve.id.first, "-", ve.id.second)
+ eit.increment()
+ tvertex = vlast.viewvertex
+ if type(tvertex) is TVertex:
+ print("TVertex: [ ", tvertex.id.first, ",", tvertex.id.second," ]")
+ eit = tvertex.edges_begin()
+ while not eit.is_end:
+ ve, incoming = eit.object
+ if ve.id == self._id:
+ return 1
+ print("-------", ve.id.first, "-", ve.id.second)
+ eit.increment()
+ return 0
+
+class pyIsInOccludersListUP1D(UnaryPredicate1D):
+ def __init__(self,id):
+ UnaryPredicate1D.__init__(self)
+ self._id = id
+ def __call__(self, inter):
+ func = GetOccludersF1D()
+ occluders = func(inter)
+ for a in occluders:
+ if a.id == self._id:
+ return 1
+ return 0
+
+class pyIsOccludedByItselfUP1D(UnaryPredicate1D):
+ def __init__(self):
+ UnaryPredicate1D.__init__(self)
+ self.__func1 = GetOccludersF1D()
+ self.__func2 = GetShapeF1D()
+ def __call__(self, inter):
+ lst1 = self.__func1(inter)
+ lst2 = self.__func2(inter)
+ for vs1 in lst1:
+ for vs2 in lst2:
+ if vs1.id == vs2.id:
+ return 1
+ return 0
+
+class pyIsOccludedByIdListUP1D(UnaryPredicate1D):
+ def __init__(self, idlist):
+ UnaryPredicate1D.__init__(self)
+ self._idlist = idlist
+ self.__func1 = GetOccludersF1D()
+ def __call__(self, inter):
+ lst1 = self.__func1(inter)
+ for vs1 in lst1:
+ for _id in self._idlist:
+ if vs1.id == _id:
+ return 1
+ return 0
+
+class pyShapeIdListUP1D(UnaryPredicate1D):
+ def __init__(self,idlist):
+ UnaryPredicate1D.__init__(self)
+ self._idlist = idlist
+ self._funcs = []
+ for _id in idlist :
+ self._funcs.append(ShapeUP1D(_id.first, _id.second))
+ def __call__(self, inter):
+ for func in self._funcs :
+ if func(inter) == 1:
+ return 1
+ return 0
+
+## deprecated
+class pyShapeIdUP1D(UnaryPredicate1D):
+ def __init__(self, _id):
+ UnaryPredicate1D.__init__(self)
+ self._id = _id
+ def __call__(self, inter):
+ func = GetShapeF1D()
+ shapes = func(inter)
+ for a in shapes:
+ if a.id == self._id:
+ return 1
+ return 0
+
+class pyHighDensityAnisotropyUP1D(UnaryPredicate1D):
+ def __init__(self,threshold, level, sampling=2.0):
+ UnaryPredicate1D.__init__(self)
+ self._l = threshold
+ self.func = pyDensityAnisotropyF1D(level, IntegrationType.MEAN, sampling)
+ def __call__(self, inter):
+ return (self.func(inter) > self._l)
+
+class pyHighViewMapGradientNormUP1D(UnaryPredicate1D):
+ def __init__(self,threshold, l, sampling=2.0):
+ UnaryPredicate1D.__init__(self)
+ self._threshold = threshold
+ self._GetGradient = pyViewMapGradientNormF1D(l, IntegrationType.MEAN)
+ def __call__(self, inter):
+ gn = self._GetGradient(inter)
+ #print(gn)
+ return (gn > self._threshold)
+
+class pyDensityVariableSigmaUP1D(UnaryPredicate1D):
+ def __init__(self,functor, sigmaMin,sigmaMax, lmin, lmax, tmin, tmax, integration = IntegrationType.MEAN, sampling=2.0):
+ UnaryPredicate1D.__init__(self)
+ self._functor = functor
+ self._sigmaMin = float(sigmaMin)
+ self._sigmaMax = float(sigmaMax)
+ self._lmin = float(lmin)
+ self._lmax = float(lmax)
+ self._tmin = tmin
+ self._tmax = tmax
+ self._integration = integration
+ self._sampling = sampling
+ def __call__(self, inter):
+ sigma = (self._sigmaMax-self._sigmaMin)/(self._lmax-self._lmin)*(self._functor(inter)-self._lmin) + self._sigmaMin
+ t = (self._tmax-self._tmin)/(self._lmax-self._lmin)*(self._functor(inter)-self._lmin) + self._tmin
+ if sigma < self._sigmaMin:
+ sigma = self._sigmaMin
+ self._func = DensityF1D(sigma, self._integration, self._sampling)
+ d = self._func(inter)
+ if d < t:
+ return 1
+ return 0
+
+class pyClosedCurveUP1D(UnaryPredicate1D):
+ def __call__(self, inter):
+ it = inter.vertices_begin()
+ itlast = inter.vertices_end()
+ itlast.decrement()
+ vlast = itlast.object
+ v = it.object
+ print(v.id.first, v.id.second)
+ print(vlast.id.first, vlast.id.second)
+ if v.id == vlast.id:
+ return 1
+ return 0
diff --git a/release/scripts/freestyle/style_modules/anisotropic_diffusion.py b/release/scripts/freestyle/style_modules/anisotropic_diffusion.py
new file mode 100644
index 00000000000..bc1654475ac
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/anisotropic_diffusion.py
@@ -0,0 +1,44 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : anisotropic_diffusion.py
+# Author : Fredo Durand
+# Date : 12/08/2004
+# Purpose : Smoothes lines using an anisotropic diffusion scheme
+
+from Freestyle import ChainPredicateIterator, ConstantThicknessShader, ExternalContourUP1D, IncreasingColorShader, \
+ Operators, QuantitativeInvisibilityUP1D, SamplingShader, Stroke, StrokeTextureShader, TrueBP1D, TrueUP1D
+from logical_operators import AndUP1D, NotUP1D
+from shaders import pyDiffusion2Shader
+
+# pyDiffusion2Shader parameters
+offset = 0.25
+nbIter = 30
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D())
+Operators.select(upred)
+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),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/apriori_and_causal_density.py b/release/scripts/freestyle/style_modules/apriori_and_causal_density.py
new file mode 100644
index 00000000000..8284f7308f8
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/apriori_and_causal_density.py
@@ -0,0 +1,39 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : apriori_and_causal_density.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Selects the lines with high a priori density and
+# subjects them to the causal density so as to avoid
+# cluttering
+
+from Freestyle import ChainPredicateIterator, ConstantColorShader, ConstantThicknessShader, IntegrationType, \
+ Operators, QuantitativeInvisibilityUP1D, TrueBP1D
+from PredicatesU1D import pyDensityUP1D, pyHighViewMapDensityUP1D
+from logical_operators import AndUP1D, NotUP1D
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyHighViewMapDensityUP1D(0.3, IntegrationType.LAST))
+Operators.select(upred)
+bpred = TrueBP1D()
+Operators.bidirectional_chain(ChainPredicateIterator(upred, bpred), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ ConstantThicknessShader(2),
+ ConstantColorShader(0, 0, 0, 1),
+ ]
+Operators.create(pyDensityUP1D(1, 0.1, IntegrationType.MEAN), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/apriori_density.py b/release/scripts/freestyle/style_modules/apriori_density.py
new file mode 100644
index 00000000000..575f2b92a25
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/apriori_density.py
@@ -0,0 +1,37 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : apriori_density.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws lines having a high a priori density
+
+from Freestyle import ChainPredicateIterator, ConstantColorShader, ConstantThicknessShader, Operators, \
+ QuantitativeInvisibilityUP1D, TrueBP1D, TrueUP1D
+from PredicatesU1D import pyHighViewMapDensityUP1D
+from logical_operators import AndUP1D, NotUP1D
+
+Operators.select(AndUP1D(QuantitativeInvisibilityUP1D(0), pyHighViewMapDensityUP1D(0.1,5)))
+bpred = TrueBP1D()
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyHighViewMapDensityUP1D(0.0007,5))
+Operators.bidirectional_chain(ChainPredicateIterator(upred, bpred), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ ConstantThicknessShader(2),
+ ConstantColorShader(0.0, 0.0, 0.0,1)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/backbone_stretcher.py b/release/scripts/freestyle/style_modules/backbone_stretcher.py
new file mode 100644
index 00000000000..1e113bec368
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/backbone_stretcher.py
@@ -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 #####
+
+# Filename : backbone_stretcher.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Stretches the geometry of visible lines
+
+from Freestyle import BackboneStretcherShader, ChainSilhouetteIterator, ConstantColorShader, \
+ Operators, QuantitativeInvisibilityUP1D, TextureAssignerShader, TrueUP1D
+from logical_operators import NotUP1D
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ TextureAssignerShader(4),
+ ConstantColorShader(0.5, 0.5, 0.5),
+ BackboneStretcherShader(20),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/blueprint_circles.py b/release/scripts/freestyle/style_modules/blueprint_circles.py
new file mode 100644
index 00000000000..769615e791f
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/blueprint_circles.py
@@ -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 #####
+
+# Filename : blueprint_circles.py
+# Author : Emmanuel Turquin
+# Date : 04/08/2005
+# Purpose : Produces a blueprint using circular contour strokes
+
+from Freestyle import ChainPredicateIterator, ConstantThicknessShader, ContourUP1D, IncreasingColorShader, \
+ Operators, QuantitativeInvisibilityUP1D, SameShapeIdBP1D, TextureAssignerShader, TrueUP1D
+from PredicatesU1D import pyHigherLengthUP1D
+from logical_operators import AndUP1D, NotUP1D
+from shaders import pyBluePrintCirclesShader, pyPerlinNoise1DShader
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D())
+bpred = SameShapeIdBP1D()
+Operators.select(upred)
+Operators.bidirectional_chain(ChainPredicateIterator(upred,bpred), NotUP1D(upred))
+Operators.select(pyHigherLengthUP1D(200))
+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/style_modules/blueprint_ellipses.py b/release/scripts/freestyle/style_modules/blueprint_ellipses.py
new file mode 100644
index 00000000000..70c999fa2c7
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/blueprint_ellipses.py
@@ -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 #####
+
+# Filename : blueprint_ellipses.py
+# Author : Emmanuel Turquin
+# Date : 04/08/2005
+# Purpose : Produces a blueprint using elliptic contour strokes
+
+from Freestyle import ChainPredicateIterator, ConstantThicknessShader, ContourUP1D, IncreasingColorShader, \
+ Operators, QuantitativeInvisibilityUP1D, SameShapeIdBP1D, TextureAssignerShader, TrueUP1D
+from PredicatesU1D import pyHigherLengthUP1D
+from logical_operators import AndUP1D, NotUP1D
+from shaders import pyBluePrintEllipsesShader, pyPerlinNoise1DShader
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D())
+bpred = SameShapeIdBP1D()
+Operators.select(upred)
+Operators.bidirectional_chain(ChainPredicateIterator(upred, bpred), NotUP1D(upred))
+Operators.select(pyHigherLengthUP1D(200))
+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/style_modules/blueprint_squares.py b/release/scripts/freestyle/style_modules/blueprint_squares.py
new file mode 100644
index 00000000000..7193beb8de5
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/blueprint_squares.py
@@ -0,0 +1,43 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : blueprint_squares.py
+# Author : Emmanuel Turquin
+# Date : 04/08/2005
+# Purpose : Produces a blueprint using square contour strokes
+
+from Freestyle import ChainPredicateIterator, ConstantThicknessShader, ContourUP1D, IncreasingColorShader, \
+ Operators, QuantitativeInvisibilityUP1D, SameShapeIdBP1D, TextureAssignerShader, TrueUP1D
+from PredicatesU1D import pyHigherLengthUP1D
+from logical_operators import AndUP1D, NotUP1D
+from shaders import pyBluePrintSquaresShader, pyPerlinNoise1DShader
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D())
+bpred = SameShapeIdBP1D()
+Operators.select(upred)
+Operators.bidirectional_chain(ChainPredicateIterator(upred, bpred), NotUP1D(upred))
+Operators.select(pyHigherLengthUP1D(200))
+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),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/cartoon.py b/release/scripts/freestyle/style_modules/cartoon.py
new file mode 100644
index 00000000000..61bc11520a1
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/cartoon.py
@@ -0,0 +1,38 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : cartoon.py
+# 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
+# fashion.
+
+from Freestyle import BezierCurveShader, ChainSilhouetteIterator, ConstantThicknessShader, Operators, \
+ QuantitativeInvisibilityUP1D, TrueUP1D
+from logical_operators import NotUP1D
+from shaders import pyMaterialColorShader
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ BezierCurveShader(3),
+ ConstantThicknessShader(4),
+ pyMaterialColorShader(0.8),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/contour.py b/release/scripts/freestyle/style_modules/contour.py
new file mode 100644
index 00000000000..e4eb8c2c3ae
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/contour.py
@@ -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 #####
+
+# Filename : contour.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws each object's visible contour
+
+from Freestyle import ChainPredicateIterator, ConstantThicknessShader, ContourUP1D, IncreasingColorShader, \
+ Operators, QuantitativeInvisibilityUP1D, SameShapeIdBP1D, TrueUP1D
+from logical_operators import AndUP1D, NotUP1D
+
+Operators.select(AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D()))
+bpred = SameShapeIdBP1D()
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D())
+Operators.bidirectional_chain(ChainPredicateIterator(upred, bpred), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ ConstantThicknessShader(5.0),
+ IncreasingColorShader(0.8,0,0,1,0.1,0,0,1),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/curvature2d.py b/release/scripts/freestyle/style_modules/curvature2d.py
new file mode 100644
index 00000000000..57bc8382220
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/curvature2d.py
@@ -0,0 +1,37 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : curvature2d.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : The stroke points are colored in gray levels and depending
+# on the 2d curvature value
+
+from Freestyle import ChainSilhouetteIterator, ConstantThicknessShader, Operators, \
+ QuantitativeInvisibilityUP1D, Stroke, StrokeTextureShader, TrueUP1D
+from logical_operators import NotUP1D
+from shaders import py2DCurvatureColorShader
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ StrokeTextureShader("smoothAlpha.bmp", Stroke.OPAQUE_MEDIUM, False),
+ ConstantThicknessShader(5),
+ py2DCurvatureColorShader()
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/external_contour.py b/release/scripts/freestyle/style_modules/external_contour.py
new file mode 100644
index 00000000000..28bd28f2a7a
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/external_contour.py
@@ -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 #####
+
+# Filename : external_contour.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws the external contour of the scene
+
+from Freestyle import ChainPredicateIterator, ConstantColorShader, ConstantThicknessShader, \
+ ExternalContourUP1D, Operators, QuantitativeInvisibilityUP1D, TrueBP1D, TrueUP1D
+from logical_operators import AndUP1D, NotUP1D
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D())
+Operators.select(upred)
+bpred = TrueBP1D()
+Operators.bidirectional_chain(ChainPredicateIterator(upred, bpred), NotUP1D(upred))
+shaders_list = [
+ ConstantThicknessShader(3),
+ ConstantColorShader(0.0, 0.0, 0.0, 1),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/external_contour_sketchy.py b/release/scripts/freestyle/style_modules/external_contour_sketchy.py
new file mode 100644
index 00000000000..d85e9674e90
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/external_contour_sketchy.py
@@ -0,0 +1,43 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : external_contour_sketchy.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws the external contour of the scene using a sketchy
+# chaining iterator (in particular each ViewEdge can be drawn
+# several times
+
+from ChainingIterators import pySketchyChainingIterator
+from Freestyle import ExternalContourUP1D, IncreasingColorShader, IncreasingThicknessShader, \
+ Operators, QuantitativeInvisibilityUP1D, SamplingShader, SmoothingShader, SpatialNoiseShader, \
+ TextureAssignerShader, TrueUP1D
+from logical_operators import AndUP1D, NotUP1D
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D())
+Operators.select(upred)
+Operators.bidirectional_chain(pySketchyChainingIterator(), NotUP1D(upred))
+shaders_list = [
+ SamplingShader(4),
+ SpatialNoiseShader(10, 150, 2, 1, 1),
+ 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/style_modules/external_contour_smooth.py b/release/scripts/freestyle/style_modules/external_contour_smooth.py
new file mode 100644
index 00000000000..f42f3bf3338
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/external_contour_smooth.py
@@ -0,0 +1,39 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : external_contour_smooth.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws a smooth external contour
+
+from Freestyle import ChainPredicateIterator, ExternalContourUP1D, IncreasingColorShader, \
+ IncreasingThicknessShader, Operators, QuantitativeInvisibilityUP1D, SamplingShader, \
+ SmoothingShader, TrueBP1D, TrueUP1D
+from logical_operators import AndUP1D, NotUP1D
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D())
+Operators.select(upred)
+bpred = TrueBP1D()
+Operators.bidirectional_chain(ChainPredicateIterator(upred, bpred), NotUP1D(upred))
+shaders_list = [
+ SamplingShader(2),
+ IncreasingThicknessShader(4,20),
+ IncreasingColorShader(1.0, 0.0, 0.5,1, 0.5,1, 0.3, 1),
+ SmoothingShader(100, 0.05, 0, 0.2, 0, 0, 0, 1),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/haloing.py b/release/scripts/freestyle/style_modules/haloing.py
new file mode 100644
index 00000000000..ee907ec967f
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/haloing.py
@@ -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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : haloing.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : This style module selects the lines that
+# are connected (in the image) to a specific
+# object and trims them in order to produce
+# a haloing effect around the target shape
+
+from Freestyle import ChainSilhouetteIterator, Id, IncreasingColorShader, IncreasingThicknessShader, \
+ Operators, QuantitativeInvisibilityUP1D, SamplingShader, TipRemoverShader, TrueUP1D
+from PredicatesU1D import pyIsOccludedByUP1D
+from logical_operators import AndUP1D, NotUP1D
+from shaders import pyTVertexRemoverShader
+
+# id corresponds to the id of the target object
+# (accessed by SHIFT+click)
+id = Id(3,0)
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyIsOccludedByUP1D(id))
+Operators.select(upred)
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(upred))
+shaders_list = [
+ IncreasingThicknessShader(3, 5),
+ IncreasingColorShader(1,0,0, 1,0,1,0,1),
+ SamplingShader(1.0),
+ pyTVertexRemoverShader(),
+ TipRemoverShader(3.0),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/ignore_small_occlusions.py b/release/scripts/freestyle/style_modules/ignore_small_occlusions.py
new file mode 100644
index 00000000000..aeab1b2e731
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/ignore_small_occlusions.py
@@ -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 #####
+
+# Filename : ignore_small_oclusions.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : The strokes are drawn through small occlusions
+
+from ChainingIterators import pyFillOcclusionsAbsoluteChainingIterator
+from Freestyle import ConstantColorShader, ConstantThicknessShader, Operators, \
+ QuantitativeInvisibilityUP1D, SamplingShader, TrueUP1D
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+#Operators.bidirectional_chain(pyFillOcclusionsChainingIterator(0.1))
+Operators.bidirectional_chain(pyFillOcclusionsAbsoluteChainingIterator(12))
+shaders_list = [
+ SamplingShader(5.0),
+ ConstantThicknessShader(3),
+ ConstantColorShader(0.0, 0.0, 0.0),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/invisible_lines.py b/release/scripts/freestyle/style_modules/invisible_lines.py
new file mode 100644
index 00000000000..6a72534d0ac
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/invisible_lines.py
@@ -0,0 +1,37 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : invisible_lines.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws all lines whose Quantitative Invisibility
+# is different from 0
+
+from Freestyle import ChainSilhouetteIterator, ConstantColorShader, ConstantThicknessShader, \
+ Operators, QuantitativeInvisibilityUP1D, SamplingShader, TrueUP1D
+from logical_operators import NotUP1D
+
+upred = NotUP1D(QuantitativeInvisibilityUP1D(0))
+Operators.select(upred)
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(upred))
+shaders_list = [
+ SamplingShader(5.0),
+ ConstantThicknessShader(3.0),
+ ConstantColorShader(0.7, 0.7, 0.7),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/japanese_bigbrush.py b/release/scripts/freestyle/style_modules/japanese_bigbrush.py
new file mode 100644
index 00000000000..ca421536c42
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/japanese_bigbrush.py
@@ -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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : japanese_bigbrush.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Simulates a big brush fr oriental painting
+
+from Freestyle import BezierCurveShader, ChainSilhouetteIterator, ConstantColorShader, \
+ ConstantThicknessShader, IntegrationType, Operators, QuantitativeInvisibilityUP1D, \
+ SamplingShader, TextureAssignerShader, TipRemoverShader
+from Functions0D import pyInverseCurvature2DAngleF0D
+from PredicatesB1D import pyLengthBP1D
+from PredicatesU0D import pyParameterUP0D
+from PredicatesU1D import pyDensityUP1D, pyHigherLengthUP1D, pyHigherNumberOfTurnsUP1D
+from logical_operators import NotUP1D
+from shaders import pyNonLinearVaryingThicknessShader, pySamplingShader
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+## Splits strokes at points of highest 2D curavture
+## 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)
+## Keeps only long enough strokes
+Operators.select(pyHigherLengthUP1D(100))
+## Sorts so as to draw the longest strokes first
+## (this will be done using the causal density)
+Operators.sort(pyLengthBP1D())
+shaders_list = [
+ pySamplingShader(10),
+ BezierCurveShader(30),
+ SamplingShader(50),
+ ConstantThicknessShader(10),
+ pyNonLinearVaryingThicknessShader(4, 25, 0.6),
+ TextureAssignerShader(6),
+ ConstantColorShader(0.2, 0.2, 0.2,1.0),
+ TipRemoverShader(10),
+ ]
+## Use the causal density to avoid cluttering
+Operators.create(pyDensityUP1D(8, 0.4, IntegrationType.MEAN), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/logical_operators.py b/release/scripts/freestyle/style_modules/logical_operators.py
new file mode 100644
index 00000000000..cffb9e1cc58
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/logical_operators.py
@@ -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 #####
+
+# Filename : logical_operators.py
+# Authors : Fredo Durand, Stephane Grabli, Francois Sillion, Emmanuel Turquin
+# Date : 08/04/2005
+# Purpose : Logical unary predicates (functors) for 1D elements
+
+from Freestyle import UnaryPredicate1D
+
+class AndUP1D(UnaryPredicate1D):
+ def __init__(self, pred1, pred2):
+ UnaryPredicate1D.__init__(self)
+ self.__pred1 = pred1
+ self.__pred2 = pred2
+ def __call__(self, inter):
+ return self.__pred1(inter) and self.__pred2(inter)
+
+class OrUP1D(UnaryPredicate1D):
+ def __init__(self, pred1, pred2):
+ UnaryPredicate1D.__init__(self)
+ self.__pred1 = pred1
+ self.__pred2 = pred2
+ def __call__(self, inter):
+ return self.__pred1(inter) or self.__pred2(inter)
+
+class NotUP1D(UnaryPredicate1D):
+ def __init__(self, pred):
+ UnaryPredicate1D.__init__(self)
+ self.__pred = pred
+ def __call__(self, inter):
+ return not self.__pred(inter)
diff --git a/release/scripts/freestyle/style_modules/long_anisotropically_dense.py b/release/scripts/freestyle/style_modules/long_anisotropically_dense.py
new file mode 100644
index 00000000000..90fc84c5dae
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/long_anisotropically_dense.py
@@ -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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : long_anisotropically_dense.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Selects the lines that are long and have a high anisotropic
+# a priori density and uses causal density
+# to draw without cluttering. Ideally, half of the
+# selected lines are culled using the causal density.
+#
+# ********************* WARNING *************************************
+# ******** The Directional a priori density maps must ******
+# ******** have been computed prior to using this style module ******
+
+from Freestyle import ChainSilhouetteIterator, ConstantColorShader, ConstantThicknessShader, DensityF1D, \
+ IntegrationType, Operators, QuantitativeInvisibilityUP1D, SamplingShader, UnaryPredicate1D
+from PredicatesB1D import pyLengthBP1D
+from PredicatesU1D import pyHighDensityAnisotropyUP1D, pyHigherLengthUP1D
+from logical_operators import NotUP1D
+
+## custom density predicate
+class pyDensityUP1D(UnaryPredicate1D):
+ def __init__(self, wsize, threshold, integration=IntegrationType.MEAN, sampling=2.0):
+ UnaryPredicate1D.__init__(self)
+ self._wsize = wsize
+ self._threshold = threshold
+ self._integration = integration
+ self._func = DensityF1D(self._wsize, self._integration, sampling)
+ self._func2 = DensityF1D(self._wsize, IntegrationType.MAX, sampling)
+ def __call__(self, inter):
+ c = self._func(inter)
+ m = self._func2(inter)
+ if c < self._threshold:
+ return 1
+ if m > 4*c:
+ if c < 1.5*self._threshold:
+ return 1
+ return 0
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectional_chain(ChainSilhouetteIterator(),NotUP1D(QuantitativeInvisibilityUP1D(0)))
+Operators.select(pyHigherLengthUP1D(40))
+## selects lines having a high anisotropic a priori density
+Operators.select(pyHighDensityAnisotropyUP1D(0.3,4))
+Operators.sort(pyLengthBP1D())
+shaders_list = [
+ SamplingShader(2.0),
+ ConstantThicknessShader(2),
+ ConstantColorShader(0.2,0.2,0.25,1),
+ ]
+## uniform culling
+Operators.create(pyDensityUP1D(3.0,2.0e-2, IntegrationType.MEAN, 0.1), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/multiple_parameterization.py b/release/scripts/freestyle/style_modules/multiple_parameterization.py
new file mode 100644
index 00000000000..2296a9735ce
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/multiple_parameterization.py
@@ -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 #####
+
+# Filename : multiple_parameterization.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : The thickness and the color of the strokes vary continuously
+# independently from occlusions although only
+# visible lines are actually drawn. This is equivalent
+# to assigning the thickness using a parameterization covering
+# the complete silhouette (visible+invisible) and drawing
+# the strokes using a second parameterization that only
+# covers the visible portions.
+
+from Freestyle import ChainSilhouetteIterator, ConstantColorShader, IncreasingColorShader, \
+ IncreasingThicknessShader, Operators, QuantitativeInvisibilityUP1D, SamplingShader, \
+ TextureAssignerShader, TrueUP1D
+from shaders import pyHLRShader
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+## Chain following the same nature, but without the restriction
+## of staying inside the selection (0).
+Operators.bidirectional_chain(ChainSilhouetteIterator(0))
+shaders_list = [
+ SamplingShader(20),
+ 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/style_modules/nature.py b/release/scripts/freestyle/style_modules/nature.py
new file mode 100644
index 00000000000..dd520c5c85f
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/nature.py
@@ -0,0 +1,39 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : nature.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Uses the NatureUP1D predicate to select the lines
+# of a given type (among Nature.SILHOUETTE, Nature.CREASE, Nature.SUGGESTIVE_CONTOURS,
+# Nature.BORDERS).
+# The suggestive contours must have been enabled in the
+# options dialog to appear in the View Map.
+
+from Freestyle import ChainSilhouetteIterator, IncreasingColorShader, \
+ IncreasingThicknessShader, Nature, Operators, TrueUP1D
+from PredicatesU1D import pyNatureUP1D
+from logical_operators import NotUP1D
+
+Operators.select(pyNatureUP1D(Nature.SILHOUETTE))
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(pyNatureUP1D(Nature.SILHOUETTE)))
+shaders_list = [
+ IncreasingThicknessShader(3, 10),
+ IncreasingColorShader(0.0, 0.0, 0.0, 1, 0.8, 0, 0, 1),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/near_lines.py b/release/scripts/freestyle/style_modules/near_lines.py
new file mode 100644
index 00000000000..d2dab89d478
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/near_lines.py
@@ -0,0 +1,38 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : near_lines.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws the lines that are "closer" than a threshold
+# (between 0 and 1)
+
+from Freestyle import ChainSilhouetteIterator, ConstantColorShader, ConstantThicknessShader, \
+ IntegrationType, Operators, QuantitativeInvisibilityUP1D, TextureAssignerShader, TrueUP1D
+from PredicatesU1D import pyZSmallerUP1D
+from logical_operators import AndUP1D, NotUP1D
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyZSmallerUP1D(0.5, IntegrationType.MEAN))
+Operators.select(upred)
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(upred))
+shaders_list = [
+ TextureAssignerShader(-1),
+ ConstantThicknessShader(5),
+ ConstantColorShader(0.0, 0.0, 0.0),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/occluded_by_specific_object.py b/release/scripts/freestyle/style_modules/occluded_by_specific_object.py
new file mode 100644
index 00000000000..4f8c0e859ed
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/occluded_by_specific_object.py
@@ -0,0 +1,40 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : occluded_by_specific_object.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws only the lines that are occluded by a given object
+
+from Freestyle import ChainSilhouetteIterator, ConstantColorShader, ConstantThicknessShader, \
+ Id, Operators, QuantitativeInvisibilityUP1D, SamplingShader, TrueUP1D
+from PredicatesU1D import pyIsInOccludersListUP1D
+from logical_operators import AndUP1D, NotUP1D
+
+## the id of the occluder (use SHIFT+click on the ViewMap to
+## retrieve ids)
+id = Id(3,0)
+upred = AndUP1D(NotUP1D(QuantitativeInvisibilityUP1D(0)), pyIsInOccludersListUP1D(id))
+Operators.select(upred)
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(upred))
+shaders_list = [
+ SamplingShader(5),
+ ConstantThicknessShader(3),
+ ConstantColorShader(0.3, 0.3, 0.3, 1),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/parameter_editor.py b/release/scripts/freestyle/style_modules/parameter_editor.py
new file mode 100644
index 00000000000..ffb01f06c7b
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/parameter_editor.py
@@ -0,0 +1,1259 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public 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 : parameter_editor.py
+# Authors : Tamito Kajiyama
+# Date : 26/07/2010
+# Purpose : Interactive manipulation of stylization parameters
+
+import Freestyle
+import math
+import mathutils
+import time
+
+from ChainingIterators import pySketchyChainSilhouetteIterator, pySketchyChainingIterator
+from Freestyle import BackboneStretcherShader, BezierCurveShader, BinaryPredicate1D, ChainPredicateIterator, \
+ ChainSilhouetteIterator, ConstantColorShader, ContourUP1D, Curvature2DAngleF0D, ExternalContourUP1D, \
+ FalseBP1D, FalseUP1D, GuidingLinesShader, Interface0DIterator, Nature, Noise, Normal2DF0D, Operators, \
+ PolygonalizationShader, QuantitativeInvisibilityF1D, QuantitativeInvisibilityUP1D, SamplingShader, \
+ SpatialNoiseShader, StrokeAttribute, StrokeShader, TipRemoverShader, TrueBP1D, TrueUP1D, UnaryPredicate0D, \
+ UnaryPredicate1D, VertexOrientation2DF0D, WithinImageBoundaryUP1D
+from Functions0D import CurveMaterialF0D
+from PredicatesU1D import pyNatureUP1D
+from logical_operators import AndUP1D, NotUP1D, OrUP1D
+from shaders import pyBluePrintCirclesShader, pyBluePrintEllipsesShader, pyBluePrintSquaresShader
+
+class ColorRampModifier(StrokeShader):
+ def __init__(self, blend, influence, ramp):
+ StrokeShader.__init__(self)
+ self.__blend = blend
+ self.__influence = influence
+ self.__ramp = ramp
+ def evaluate(self, t):
+ col = Freestyle.evaluateColorRamp(self.__ramp, t)
+ col = col.xyz # omit alpha
+ return col
+ def blend_ramp(self, a, b):
+ return Freestyle.blendRamp(self.__blend, a, self.__influence, b)
+
+class ScalarBlendModifier(StrokeShader):
+ def __init__(self, blend, influence):
+ StrokeShader.__init__(self)
+ self.__blend = blend
+ self.__influence = influence
+ def blend(self, v1, v2):
+ fac = self.__influence
+ facm = 1.0 - fac
+ if self.__blend == "MIX":
+ v1 = facm * v1 + fac * v2
+ elif self.__blend == "ADD":
+ v1 += fac * v2
+ elif self.__blend == "MULTIPLY":
+ v1 *= facm + fac * v2;
+ elif self.__blend == "SUBTRACT":
+ v1 -= fac * v2
+ elif self.__blend == "DIVIDE":
+ if v2 != 0.0:
+ v1 = facm * v1 + fac * v1 / v2
+ elif self.__blend == "DIFFERENCE":
+ v1 = facm * v1 + fac * abs(v1 - v2)
+ elif self.__blend == "MININUM":
+ tmp = fac * v1
+ if v1 > tmp:
+ v1 = tmp
+ elif self.__blend == "MAXIMUM":
+ tmp = fac * v1
+ if v1 < tmp:
+ v1 = tmp
+ else:
+ raise ValueError("unknown curve blend type: " + self.__blend)
+ return v1
+
+class CurveMappingModifier(ScalarBlendModifier):
+ def __init__(self, blend, influence, mapping, invert, curve):
+ ScalarBlendModifier.__init__(self, blend, influence)
+ assert mapping in ("LINEAR", "CURVE")
+ self.__mapping = getattr(self, mapping)
+ self.__invert = invert
+ self.__curve = curve
+ def LINEAR(self, t):
+ if self.__invert:
+ return 1.0 - t
+ return t
+ def CURVE(self, t):
+ return Freestyle.evaluateCurveMappingF(self.__curve, 0, t)
+ def evaluate(self, t):
+ return self.__mapping(t)
+
+class ThicknessModifierMixIn:
+ def __init__(self):
+ scene = Freestyle.getCurrentScene()
+ self.__persp_camera = (scene.camera.data.type == "PERSP")
+ def set_thickness(self, sv, outer, inner):
+ fe = sv.first_svertex.get_fedge(sv.second_svertex)
+ nature = fe.nature
+ if (nature & Nature.BORDER):
+ if self.__persp_camera:
+ point = -sv.point_3d.copy()
+ point.normalize()
+ 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 (nature & Nature.SILHOUETTE):
+ if fe.is_smooth: # TODO more tests needed
+ outer, inner = inner, outer
+ else:
+ outer = inner = (outer + inner) / 2
+ sv.attribute.thickness = (outer, inner)
+
+class ThicknessBlenderMixIn(ThicknessModifierMixIn):
+ def __init__(self, position, ratio):
+ ThicknessModifierMixIn.__init__(self)
+ self.__position = position
+ self.__ratio = ratio
+ def blend_thickness(self, outer, inner, v):
+ if self.__position == "CENTER":
+ outer = self.blend(outer, v / 2)
+ inner = self.blend(inner, v / 2)
+ elif self.__position == "INSIDE":
+ outer = self.blend(outer, 0)
+ inner = self.blend(inner, v)
+ elif self.__position == "OUTSIDE":
+ outer = self.blend(outer, v)
+ inner = self.blend(inner, 0)
+ elif self.__position == "RELATIVE":
+ outer = self.blend(outer, v * self.__ratio)
+ inner = self.blend(inner, v * (1 - self.__ratio))
+ else:
+ raise ValueError("unknown thickness position: " + self.__position)
+ return outer, inner
+
+class BaseColorShader(ConstantColorShader):
+ pass
+
+class BaseThicknessShader(StrokeShader, ThicknessModifierMixIn):
+ def __init__(self, thickness, position, ratio):
+ StrokeShader.__init__(self)
+ ThicknessModifierMixIn.__init__(self)
+ if position == "CENTER":
+ self.__outer = thickness / 2
+ self.__inner = thickness / 2
+ elif position == "INSIDE":
+ self.__outer = 0
+ self.__inner = thickness
+ elif position == "OUTSIDE":
+ self.__outer = thickness
+ self.__inner = 0
+ elif position == "RELATIVE":
+ self.__outer = thickness * ratio
+ self.__inner = thickness * (1 - ratio)
+ else:
+ raise ValueError("unknown thickness position: " + self.position)
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ sv = it.object
+ self.set_thickness(sv, self.__outer, self.__inner)
+ it.increment()
+
+# Along Stroke modifiers
+
+def iter_t2d_along_stroke(stroke):
+ total = stroke.length_2d
+ distance = 0.0
+ it = stroke.stroke_vertices_begin()
+ prev = it.object.point
+ while not it.is_end:
+ p = it.object.point
+ distance += (prev - p).length
+ prev = p.copy() # need a copy because the point can be altered
+ t = min(distance / total, 1.0)
+ yield it, t
+ it.increment()
+
+class ColorAlongStrokeShader(ColorRampModifier):
+ def shade(self, stroke):
+ for it, t in iter_t2d_along_stroke(stroke):
+ sv = it.object
+ a = sv.attribute.color
+ b = self.evaluate(t)
+ sv.attribute.color = self.blend_ramp(a, b)
+
+class AlphaAlongStrokeShader(CurveMappingModifier):
+ def shade(self, stroke):
+ for it, t in iter_t2d_along_stroke(stroke):
+ sv = it.object
+ a = sv.attribute.alpha
+ b = self.evaluate(t)
+ sv.attribute.alpha = self.blend(a, b)
+
+class ThicknessAlongStrokeShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ def __init__(self, thickness_position, thickness_ratio,
+ blend, influence, mapping, invert, curve, value_min, value_max):
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ self.__value_min = value_min
+ self.__value_max = value_max
+ def shade(self, stroke):
+ for it, t in iter_t2d_along_stroke(stroke):
+ sv = it.object
+ a = sv.attribute.thickness
+ b = self.__value_min + self.evaluate(t) * (self.__value_max - self.__value_min)
+ c = self.blend_thickness(a[0], a[1], b)
+ self.set_thickness(sv, c[0], c[1])
+
+# Distance from Camera modifiers
+
+def iter_distance_from_camera(stroke, range_min, range_max):
+ normfac = range_max - range_min # normalization factor
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ p = it.object.point_3d # in the camera coordinate
+ distance = p.length
+ if distance < range_min:
+ t = 0.0
+ elif distance > range_max:
+ t = 1.0
+ else:
+ t = (distance - range_min) / normfac
+ yield it, t
+ it.increment()
+
+class ColorDistanceFromCameraShader(ColorRampModifier):
+ def __init__(self, blend, influence, ramp, range_min, range_max):
+ ColorRampModifier.__init__(self, blend, influence, ramp)
+ self.__range_min = range_min
+ self.__range_max = range_max
+ def shade(self, stroke):
+ for it, t in iter_distance_from_camera(stroke, self.__range_min, self.__range_max):
+ sv = it.object
+ a = sv.attribute.color
+ b = self.evaluate(t)
+ sv.attribute.color = self.blend_ramp(a, b)
+
+class AlphaDistanceFromCameraShader(CurveMappingModifier):
+ def __init__(self, blend, influence, mapping, invert, curve, range_min, range_max):
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ self.__range_min = range_min
+ self.__range_max = range_max
+ def shade(self, stroke):
+ for it, t in iter_distance_from_camera(stroke, self.__range_min, self.__range_max):
+ sv = it.object
+ a = sv.attribute.alpha
+ b = self.evaluate(t)
+ sv.attribute.alpha = self.blend(a, b)
+
+class ThicknessDistanceFromCameraShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ def __init__(self, thickness_position, thickness_ratio,
+ blend, influence, mapping, invert, curve, range_min, range_max, value_min, value_max):
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ self.__range_min = range_min
+ self.__range_max = range_max
+ self.__value_min = value_min
+ self.__value_max = value_max
+ def shade(self, stroke):
+ for it, t in iter_distance_from_camera(stroke, self.__range_min, self.__range_max):
+ sv = it.object
+ a = sv.attribute.thickness
+ b = self.__value_min + self.evaluate(t) * (self.__value_max - self.__value_min)
+ c = self.blend_thickness(a[0], a[1], b)
+ self.set_thickness(sv, c[0], c[1])
+
+# Distance from Object modifiers
+
+def iter_distance_from_object(stroke, object, range_min, range_max):
+ scene = Freestyle.getCurrentScene()
+ mv = scene.camera.matrix_world.copy() # model-view matrix
+ mv.invert()
+ loc = mv * object.location # loc in the camera coordinate
+ normfac = range_max - range_min # normalization factor
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ p = it.object.point_3d # in the camera coordinate
+ distance = (p - loc).length
+ if distance < range_min:
+ t = 0.0
+ elif distance > range_max:
+ t = 1.0
+ else:
+ t = (distance - range_min) / normfac
+ yield it, t
+ it.increment()
+
+class ColorDistanceFromObjectShader(ColorRampModifier):
+ def __init__(self, blend, influence, ramp, target, range_min, range_max):
+ ColorRampModifier.__init__(self, blend, influence, ramp)
+ self.__target = target
+ self.__range_min = range_min
+ self.__range_max = range_max
+ def shade(self, stroke):
+ if self.__target is None:
+ return
+ for it, t in iter_distance_from_object(stroke, self.__target, self.__range_min, self.__range_max):
+ sv = it.object
+ a = sv.attribute.color
+ b = self.evaluate(t)
+ sv.attribute.color = self.blend_ramp(a, b)
+
+class AlphaDistanceFromObjectShader(CurveMappingModifier):
+ def __init__(self, blend, influence, mapping, invert, curve, target, range_min, range_max):
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ self.__target = target
+ self.__range_min = range_min
+ self.__range_max = range_max
+ def shade(self, stroke):
+ if self.__target is None:
+ return
+ for it, t in iter_distance_from_object(stroke, self.__target, self.__range_min, self.__range_max):
+ sv = it.object
+ a = sv.attribute.alpha
+ b = self.evaluate(t)
+ sv.attribute.alpha = self.blend(a, b)
+
+class ThicknessDistanceFromObjectShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ def __init__(self, thickness_position, thickness_ratio,
+ blend, influence, mapping, invert, curve, target, range_min, range_max, value_min, value_max):
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ self.__target = target
+ self.__range_min = range_min
+ self.__range_max = range_max
+ self.__value_min = value_min
+ self.__value_max = value_max
+ def shade(self, stroke):
+ if self.__target is None:
+ return
+ for it, t in iter_distance_from_object(stroke, self.__target, self.__range_min, self.__range_max):
+ sv = it.object
+ a = sv.attribute.thickness
+ b = self.__value_min + self.evaluate(t) * (self.__value_max - self.__value_min)
+ c = self.blend_thickness(a[0], a[1], b)
+ self.set_thickness(sv, c[0], c[1])
+
+# Material modifiers
+
+def iter_material_color(stroke, material_attr):
+ func = CurveMaterialF0D()
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ material = func(Interface0DIterator(it))
+ if material_attr == "DIFF":
+ color = (material.diffuse[0],
+ material.diffuse[1],
+ material.diffuse[2])
+ elif material_attr == "SPEC":
+ color = (material.specular[0],
+ material.specular[1],
+ material.specular[2])
+ else:
+ raise ValueError("unexpected material attribute: " + material_attr)
+ yield it, color
+ it.increment()
+
+def iter_material_value(stroke, material_attr):
+ func = CurveMaterialF0D()
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ material = func(Interface0DIterator(it))
+ if material_attr == "DIFF":
+ r = material.diffuse[0]
+ g = material.diffuse[1]
+ b = material.diffuse[2]
+ t = 0.35 * r + 0.45 * r + 0.2 * b
+ elif material_attr == "DIFF_R":
+ t = material.diffuse[0]
+ elif material_attr == "DIFF_G":
+ t = material.diffuse[1]
+ elif material_attr == "DIFF_B":
+ t = material.diffuse[2]
+ elif material_attr == "SPEC":
+ r = material.specular[0]
+ g = material.specular[1]
+ b = material.specular[2]
+ t = 0.35 * r + 0.45 * r + 0.2 * b
+ elif material_attr == "SPEC_R":
+ t = material.specular[0]
+ elif material_attr == "SPEC_G":
+ t = material.specular[1]
+ elif material_attr == "SPEC_B":
+ t = material.specular[2]
+ elif material_attr == "SPEC_HARDNESS":
+ t = material.shininess
+ elif material_attr == "ALPHA":
+ t = material.diffuse[3]
+ else:
+ raise ValueError("unexpected material attribute: " + material_attr)
+ yield it, t
+ it.increment()
+
+class ColorMaterialShader(ColorRampModifier):
+ def __init__(self, blend, influence, ramp, material_attr, use_ramp):
+ ColorRampModifier.__init__(self, blend, influence, ramp)
+ self.__material_attr = material_attr
+ self.__use_ramp = use_ramp
+ def shade(self, stroke):
+ if self.__material_attr in ["DIFF", "SPEC"] and not self.__use_ramp:
+ for it, b in iter_material_color(stroke, self.__material_attr):
+ sv = it.object
+ a = sv.attribute.color
+ sv.attribute.color = self.blend_ramp(a, b)
+ else:
+ for it, t in iter_material_value(stroke, self.__material_attr):
+ sv = it.object
+ a = sv.attribute.color
+ b = self.evaluate(t)
+ sv.attribute.color = self.blend_ramp(a, b)
+
+class AlphaMaterialShader(CurveMappingModifier):
+ def __init__(self, blend, influence, mapping, invert, curve, material_attr):
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ self.__material_attr = material_attr
+ def shade(self, stroke):
+ for it, t in iter_material_value(stroke, self.__material_attr):
+ sv = it.object
+ a = sv.attribute.alpha
+ b = self.evaluate(t)
+ sv.attribute.alpha = self.blend(a, b)
+
+class ThicknessMaterialShader(ThicknessBlenderMixIn, CurveMappingModifier):
+ def __init__(self, thickness_position, thickness_ratio,
+ blend, influence, mapping, invert, curve, material_attr, value_min, value_max):
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
+ CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve)
+ self.__material_attr = material_attr
+ self.__value_min = value_min
+ self.__value_max = value_max
+ def shade(self, stroke):
+ for it, t in iter_material_value(stroke, self.__material_attr):
+ sv = it.object
+ a = sv.attribute.thickness
+ b = self.__value_min + self.evaluate(t) * (self.__value_max - self.__value_min)
+ c = self.blend_thickness(a[0], a[1], b)
+ self.set_thickness(sv, c[0], c[1])
+
+# Calligraphic thickness modifier
+
+class CalligraphicThicknessShader(ThicknessBlenderMixIn, ScalarBlendModifier):
+ def __init__(self, thickness_position, thickness_ratio,
+ blend, influence, orientation, min_thickness, max_thickness):
+ ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio)
+ ScalarBlendModifier.__init__(self, blend, influence)
+ self.__orientation = mathutils.Vector((math.cos(orientation), math.sin(orientation)))
+ self.__min_thickness = min_thickness
+ self.__max_thickness = max_thickness
+ def shade(self, stroke):
+ func = VertexOrientation2DF0D()
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ dir = func(Interface0DIterator(it))
+ orthDir = mathutils.Vector((-dir.y, dir.x))
+ orthDir.normalize()
+ fac = abs(orthDir * self.__orientation)
+ sv = it.object
+ a = sv.attribute.thickness
+ b = self.__min_thickness + fac * (self.__max_thickness - self.__min_thickness)
+ b = max(b, 0.0)
+ c = self.blend_thickness(a[0], a[1], b)
+ self.set_thickness(sv, c[0], c[1])
+ it.increment()
+
+# Geometry modifiers
+
+def iter_distance_along_stroke(stroke):
+ distance = 0.0
+ it = stroke.stroke_vertices_begin()
+ prev = it.object.point
+ while not it.is_end:
+ p = it.object.point
+ distance += (prev - p).length
+ prev = p.copy() # need a copy because the point can be altered
+ yield it, distance
+ it.increment()
+
+class SinusDisplacementShader(StrokeShader):
+ def __init__(self, wavelength, amplitude, phase):
+ StrokeShader.__init__(self)
+ self._wavelength = wavelength
+ self._amplitude = amplitude
+ self._phase = phase / wavelength * 2 * math.pi
+ self._getNormal = Normal2DF0D()
+ def shade(self, stroke):
+ for it, distance in iter_distance_along_stroke(stroke):
+ v = it.object
+ n = self._getNormal(Interface0DIterator(it))
+ n = n * self._amplitude * math.cos(distance / self._wavelength * 2 * math.pi + self._phase)
+ v.point = v.point + n
+ stroke.update_length()
+
+class PerlinNoise1DShader(StrokeShader):
+ def __init__(self, freq = 10, amp = 10, oct = 4, angle = math.radians(45), seed = -1):
+ StrokeShader.__init__(self)
+ self.__noise = Noise(seed)
+ self.__freq = freq
+ self.__amp = amp
+ self.__oct = oct
+ self.__dir = mathutils.Vector([math.cos(angle), math.sin(angle)])
+ def shade(self, stroke):
+ length = stroke.length_2d
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ v = it.object
+ nres = self.__noise.turbulence1(length * v.u, self.__freq, self.__amp, self.__oct)
+ v.point = v.point + nres * self.__dir
+ it.increment()
+ stroke.update_length()
+
+class PerlinNoise2DShader(StrokeShader):
+ def __init__(self, freq = 10, amp = 10, oct = 4, angle = math.radians(45), seed = -1):
+ StrokeShader.__init__(self)
+ self.__noise = Noise(seed)
+ self.__freq = freq
+ self.__amp = amp
+ self.__oct = oct
+ self.__dir = mathutils.Vector([math.cos(angle), math.sin(angle)])
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ v = it.object
+ vec = mathutils.Vector([v.projected_x, v.projected_y])
+ nres = self.__noise.turbulence2(vec, self.__freq, self.__amp, self.__oct)
+ v.point = v.point + nres * self.__dir
+ it.increment()
+ stroke.update_length()
+
+class Offset2DShader(StrokeShader):
+ def __init__(self, start, end, x, y):
+ StrokeShader.__init__(self)
+ self.__start = start
+ self.__end = end
+ self.__xy = mathutils.Vector([x, y])
+ self.__getNormal = Normal2DF0D()
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ v = it.object
+ u = v.u
+ a = self.__start + u * (self.__end - self.__start)
+ n = self.__getNormal(Interface0DIterator(it))
+ n = n * a
+ v.point = v.point + n + self.__xy
+ it.increment()
+ stroke.update_length()
+
+class Transform2DShader(StrokeShader):
+ def __init__(self, pivot, scale_x, scale_y, angle, pivot_u, pivot_x, pivot_y):
+ StrokeShader.__init__(self)
+ self.__pivot = pivot
+ self.__scale_x = scale_x
+ self.__scale_y = scale_y
+ self.__angle = angle
+ self.__pivot_u = pivot_u
+ self.__pivot_x = pivot_x
+ self.__pivot_y = pivot_y
+ def shade(self, stroke):
+ # determine the pivot of scaling and rotation operations
+ if self.__pivot == "START":
+ it = stroke.stroke_vertices_begin()
+ pivot = it.object.point
+ elif self.__pivot == "END":
+ it = stroke.stroke_vertices_end()
+ it.decrement()
+ pivot = it.object.point
+ elif self.__pivot == "PARAM":
+ p = None
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ prev = p
+ v = it.object
+ p = v.point
+ u = v.u
+ if self.__pivot_u < u:
+ break
+ it.increment()
+ if prev is None:
+ pivot = p
+ else:
+ delta = u - self.__pivot_u
+ pivot = p + delta * (prev - p)
+ elif self.__pivot == "CENTER":
+ pivot = mathutils.Vector([0.0, 0.0])
+ n = 0
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ p = it.object.point
+ pivot = pivot + p
+ n = n + 1
+ it.increment()
+ pivot.x = pivot.x / n
+ pivot.y = pivot.y / n
+ elif self.__pivot == "ABSOLUTE":
+ pivot = mathutils.Vector([self.__pivot_x, self.__pivot_y])
+ # apply scaling and rotation operations
+ cos_theta = math.cos(self.__angle)
+ sin_theta = math.sin(self.__angle)
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ v = it.object
+ p = v.point
+ p = p - pivot
+ x = p.x * self.__scale_x
+ y = p.y * self.__scale_y
+ p.x = x * cos_theta - y * sin_theta
+ p.y = x * sin_theta + y * cos_theta
+ v.point = p + pivot
+ it.increment()
+ stroke.update_length()
+
+# Predicates and helper functions
+
+class QuantitativeInvisibilityRangeUP1D(UnaryPredicate1D):
+ def __init__(self, qi_start, qi_end):
+ UnaryPredicate1D.__init__(self)
+ self.__getQI = QuantitativeInvisibilityF1D()
+ self.__qi_start = qi_start
+ self.__qi_end = qi_end
+ def __call__(self, inter):
+ qi = self.__getQI(inter)
+ return self.__qi_start <= qi <= self.__qi_end
+
+def join_unary_predicates(upred_list, bpred):
+ if not upred_list:
+ return None
+ upred = upred_list[0]
+ for p in upred_list[1:]:
+ upred = bpred(upred, p)
+ return upred
+
+class ObjectNamesUP1D(UnaryPredicate1D):
+ def __init__(self, names, negative):
+ UnaryPredicate1D.__init__(self)
+ self._names = names
+ self._negative = negative
+ def __call__(self, viewEdge):
+ found = viewEdge.viewshape.name in self._names
+ if self._negative:
+ return not found
+ return found
+
+# Stroke caps
+
+def iter_stroke_vertices(stroke):
+ it = stroke.stroke_vertices_begin()
+ prev_p = None
+ while not it.is_end:
+ sv = it.object
+ p = sv.point
+ if prev_p is None or (prev_p - p).length > 1e-6:
+ yield sv
+ prev_p = p.copy()
+ it.increment()
+
+class RoundCapShader(StrokeShader):
+ def round_cap_thickness(self, x):
+ x = max(0.0, min(x, 1.0))
+ return math.sqrt(1.0 - (x ** 2))
+ def shade(self, stroke):
+ # save the location and attribute of stroke vertices
+ buffer = []
+ for sv in iter_stroke_vertices(stroke):
+ buffer.append((mathutils.Vector(sv.point), StrokeAttribute(sv.attribute)))
+ nverts = len(buffer)
+ if nverts < 2:
+ return
+ # calculate the number of additional vertices to form caps
+ R, L = stroke[0].attribute.thickness
+ caplen_beg = (R + L) / 2.0
+ nverts_beg = max(5, int(R + L))
+ R, L = stroke[-1].attribute.thickness
+ caplen_end = (R + L) / 2.0
+ nverts_end = max(5, int(R + L))
+ # adjust the total number of stroke vertices
+ stroke.resample(nverts + nverts_beg + nverts_end)
+ # restore the location and attribute of the original vertices
+ for i in range(nverts):
+ p, attr = buffer[i]
+ stroke[nverts_beg + i].point = p
+ stroke[nverts_beg + i].attribute = attr
+ # reshape the cap at the beginning of the stroke
+ q, attr = buffer[1]
+ p, attr = buffer[0]
+ d = p - q
+ d = d / d.length * caplen_beg
+ n = 1.0 / nverts_beg
+ R, L = attr.thickness
+ for i in range(nverts_beg):
+ t = (nverts_beg - i) * n
+ stroke[i].point = p + d * t
+ r = self.round_cap_thickness((nverts_beg - i + 1) * n)
+ stroke[i].attribute = attr
+ stroke[i].attribute.thickness = (R * r, L * r)
+ # reshape the cap at the end of the stroke
+ q, attr = buffer[-2]
+ p, attr = buffer[-1]
+ d = p - q
+ d = d / d.length * caplen_end
+ n = 1.0 / nverts_end
+ R, L = attr.thickness
+ for i in range(nverts_end):
+ t = (nverts_end - i) * n
+ stroke[-i-1].point = p + d * t
+ r = self.round_cap_thickness((nverts_end - i + 1) * n)
+ stroke[-i-1].attribute = attr
+ stroke[-i-1].attribute.thickness = (R * r, L * r)
+ # update the curvilinear 2D length of each vertex
+ stroke.update_length()
+
+class SquareCapShader(StrokeShader):
+ def shade(self, stroke):
+ # save the location and attribute of stroke vertices
+ buffer = []
+ for sv in iter_stroke_vertices(stroke):
+ buffer.append((mathutils.Vector(sv.point), StrokeAttribute(sv.attribute)))
+ nverts = len(buffer)
+ if nverts < 2:
+ return
+ # calculate the number of additional vertices to form caps
+ R, L = stroke[0].attribute.thickness
+ caplen_beg = (R + L) / 2.0
+ nverts_beg = 1
+ R, L = stroke[-1].attribute.thickness
+ caplen_end = (R + L) / 2.0
+ nverts_end = 1
+ # adjust the total number of stroke vertices
+ stroke.resample(nverts + nverts_beg + nverts_end)
+ # restore the location and attribute of the original vertices
+ for i in range(nverts):
+ p, attr = buffer[i]
+ stroke[nverts_beg + i].point = p
+ stroke[nverts_beg + i].attribute = attr
+ # reshape the cap at the beginning of the stroke
+ q, attr = buffer[1]
+ p, attr = buffer[0]
+ d = p - q
+ stroke[0].point = p + d / d.length * caplen_beg
+ stroke[0].attribute = attr
+ # reshape the cap at the end of the stroke
+ q, attr = buffer[-2]
+ p, attr = buffer[-1]
+ d = p - q
+ stroke[-1].point = p + d / d.length * caplen_beg
+ stroke[-1].attribute = attr
+ # update the curvilinear 2D length of each vertex
+ stroke.update_length()
+
+# Split by dashed line pattern
+
+class SplitPatternStartingUP0D(UnaryPredicate0D):
+ def __init__(self, controller):
+ UnaryPredicate0D.__init__(self)
+ self._controller = controller
+ def __call__(self, inter):
+ return self._controller.start()
+
+class SplitPatternStoppingUP0D(UnaryPredicate0D):
+ def __init__(self, controller):
+ UnaryPredicate0D.__init__(self)
+ self._controller = controller
+ def __call__(self, inter):
+ return self._controller.stop()
+
+class SplitPatternController:
+ def __init__(self, pattern, sampling):
+ self.sampling = float(sampling)
+ k = len(pattern) // 2
+ n = k * 2
+ self.start_pos = [pattern[i] + pattern[i+1] for i in range(0, n, 2)]
+ self.stop_pos = [pattern[i] for i in range(0, n, 2)]
+ self.init()
+ def init(self):
+ self.start_len = 0.0
+ self.start_idx = 0
+ self.stop_len = self.sampling
+ self.stop_idx = 0
+ def start(self):
+ self.start_len += self.sampling
+ if abs(self.start_len - self.start_pos[self.start_idx]) < self.sampling / 2.0:
+ self.start_len = 0.0
+ self.start_idx = (self.start_idx + 1) % len(self.start_pos)
+ return True
+ return False
+ def stop(self):
+ if self.start_len > 0.0:
+ self.init()
+ self.stop_len += self.sampling
+ if abs(self.stop_len - self.stop_pos[self.stop_idx]) < self.sampling / 2.0:
+ self.stop_len = self.sampling
+ self.stop_idx = (self.stop_idx + 1) % len(self.stop_pos)
+ return True
+ return False
+
+# Dashed line
+
+class DashedLineShader(StrokeShader):
+ def __init__(self, pattern):
+ StrokeShader.__init__(self)
+ self._pattern = pattern
+ def shade(self, stroke):
+ index = 0 # pattern index
+ start = 0.0 # 2D curvilinear length
+ visible = True
+ sampling = 1.0
+ it = stroke.stroke_vertices_begin(sampling)
+ while not it.is_end:
+ pos = it.t # curvilinear abscissa
+ # The extra 'sampling' term is added below, because the
+ # visibility attribute of the i-th vertex refers to the
+ # visibility of the stroke segment between the i-th and
+ # (i+1)-th vertices.
+ if pos - start + sampling > self._pattern[index]:
+ start = pos
+ index += 1
+ if index == len(self._pattern):
+ index = 0
+ visible = not visible
+ it.object.attribute.visible = visible
+ it.increment()
+
+# predicates for chaining
+
+class AngleLargerThanBP1D(BinaryPredicate1D):
+ def __init__(self, angle):
+ BinaryPredicate1D.__init__(self)
+ self._angle = angle
+ def __call__(self, i1, i2):
+ sv1a = i1.first_fedge.first_svertex.point_2d
+ sv1b = i1.last_fedge.second_svertex.point_2d
+ sv2a = i2.first_fedge.first_svertex.point_2d
+ sv2b = i2.last_fedge.second_svertex.point_2d
+ if (sv1a - sv2a).length < 1e-6:
+ dir1 = sv1a - sv1b
+ dir2 = sv2b - sv2a
+ elif (sv1b - sv2b).length < 1e-6:
+ dir1 = sv1b - sv1a
+ dir2 = sv2a - sv2b
+ elif (sv1a - sv2b).length < 1e-6:
+ dir1 = sv1a - sv1b
+ dir2 = sv2a - sv2b
+ elif (sv1b - sv2a).length < 1e-6:
+ dir1 = sv1b - sv1a
+ dir2 = sv2b - sv2a
+ else:
+ return False
+ denom = dir1.length * dir2.length
+ if denom < 1e-6:
+ return False
+ x = (dir1 * dir2) / denom
+ return math.acos(min(max(x, -1.0), 1.0)) > self._angle
+
+class AndBP1D(BinaryPredicate1D):
+ def __init__(self, pred1, pred2):
+ BinaryPredicate1D.__init__(self)
+ self.__pred1 = pred1
+ self.__pred2 = pred2
+ def __call__(self, i1, i2):
+ return self.__pred1(i1, i2) and self.__pred2(i1, i2)
+
+# predicates for selection
+
+class LengthThresholdUP1D(UnaryPredicate1D):
+ def __init__(self, min_length=None, max_length=None):
+ UnaryPredicate1D.__init__(self)
+ self._min_length = min_length
+ self._max_length = max_length
+ def __call__(self, inter):
+ length = inter.length_2d
+ if self._min_length is not None and length < self._min_length:
+ return False
+ if self._max_length is not None and length > self._max_length:
+ return False
+ return True
+
+class FaceMarkBothUP1D(UnaryPredicate1D):
+ def __call__(self, inter): # ViewEdge
+ fe = inter.first_fedge
+ while fe is not None:
+ if fe.is_smooth:
+ if fe.face_mark:
+ return True
+ else:
+ if fe.face_mark_right and fe.face_mark_left:
+ return True
+ fe = fe.next_fedge
+ return False
+
+class FaceMarkOneUP1D(UnaryPredicate1D):
+ def __call__(self, inter): # ViewEdge
+ fe = inter.first_fedge
+ while fe is not None:
+ if fe.is_smooth:
+ if fe.face_mark:
+ return True
+ else:
+ if fe.face_mark_right or fe.face_mark_left:
+ return True
+ fe = fe.next_fedge
+ return False
+
+# predicates for splitting
+
+class MaterialBoundaryUP0D(UnaryPredicate0D):
+ def __call__(self, it):
+ if it.is_begin:
+ return False
+ it_prev = Interface0DIterator(it)
+ it_prev.decrement()
+ v = it.object
+ it.increment()
+ if it.is_end:
+ return False
+ fe = v.get_fedge(it_prev.object)
+ idx1 = fe.material_index if fe.is_smooth else fe.material_index_left
+ fe = v.get_fedge(it.object)
+ idx2 = fe.material_index if fe.is_smooth else fe.material_index_left
+ return idx1 != idx2
+
+class Curvature2DAngleThresholdUP0D(UnaryPredicate0D):
+ def __init__(self, min_angle=None, max_angle=None):
+ UnaryPredicate0D.__init__(self)
+ self._min_angle = min_angle
+ self._max_angle = max_angle
+ self._func = Curvature2DAngleF0D()
+ def __call__(self, inter):
+ angle = math.pi - self._func(inter)
+ if self._min_angle is not None and angle < self._min_angle:
+ return True
+ if self._max_angle is not None and angle > self._max_angle:
+ return True
+ return False
+
+class Length2DThresholdUP0D(UnaryPredicate0D):
+ def __init__(self, length_limit):
+ UnaryPredicate0D.__init__(self)
+ self._length_limit = length_limit
+ self._t = 0.0
+ def __call__(self, inter):
+ t = inter.t # curvilinear abscissa
+ if t < self._t:
+ self._t = 0.0
+ return False
+ if t - self._t < self._length_limit:
+ return False
+ self._t = t
+ return True
+
+# Seed for random number generation
+
+class Seed:
+ def __init__(self):
+ self.t_max = 2 ** 15
+ self.t = int(time.time()) % self.t_max
+ def get(self, seed):
+ if seed < 0:
+ self.t = (self.t + 1) % self.t_max
+ return self.t
+ return seed
+
+_seed = Seed()
+
+# main function for parameter processing
+
+def process(layer_name, lineset_name):
+ scene = Freestyle.getCurrentScene()
+ layer = scene.render.layers[layer_name]
+ lineset = layer.freestyle_settings.linesets[lineset_name]
+ linestyle = lineset.linestyle
+
+ selection_criteria = []
+ # prepare selection criteria by visibility
+ if lineset.select_by_visibility:
+ if lineset.visibility == "VISIBLE":
+ selection_criteria.append(
+ QuantitativeInvisibilityUP1D(0))
+ elif lineset.visibility == "HIDDEN":
+ selection_criteria.append(
+ NotUP1D(QuantitativeInvisibilityUP1D(0)))
+ elif lineset.visibility == "RANGE":
+ selection_criteria.append(
+ QuantitativeInvisibilityRangeUP1D(lineset.qi_start, lineset.qi_end))
+ # prepare selection criteria by edge types
+ if lineset.select_by_edge_types:
+ edge_type_criteria = []
+ if lineset.select_silhouette:
+ upred = pyNatureUP1D(Nature.SILHOUETTE)
+ edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_silhouette else upred)
+ if lineset.select_border:
+ upred = pyNatureUP1D(Nature.BORDER)
+ edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_border else upred)
+ if lineset.select_crease:
+ upred = pyNatureUP1D(Nature.CREASE)
+ edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_crease else upred)
+ if lineset.select_ridge_valley:
+ upred = pyNatureUP1D(Nature.RIDGE)
+ edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_ridge_valley else upred)
+ if lineset.select_suggestive_contour:
+ upred = pyNatureUP1D(Nature.SUGGESTIVE_CONTOUR)
+ edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_suggestive_contour else upred)
+ if lineset.select_material_boundary:
+ upred = pyNatureUP1D(Nature.MATERIAL_BOUNDARY)
+ edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_material_boundary else upred)
+ if lineset.select_edge_mark:
+ upred = pyNatureUP1D(Nature.EDGE_MARK)
+ edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_edge_mark else upred)
+ if lineset.select_contour:
+ upred = ContourUP1D()
+ edge_type_criteria.append(NotUP1D(upred) if lineset.exclude_contour else upred)
+ 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 = join_unary_predicates(edge_type_criteria, OrUP1D)
+ else:
+ upred = join_unary_predicates(edge_type_criteria, AndUP1D)
+ if upred is not None:
+ if lineset.edge_type_negation == "EXCLUSIVE":
+ upred = NotUP1D(upred)
+ selection_criteria.append(upred)
+ # prepare selection criteria by face marks
+ if lineset.select_by_face_marks:
+ if lineset.face_mark_condition == "BOTH":
+ upred = FaceMarkBothUP1D()
+ else:
+ upred = FaceMarkOneUP1D()
+ if lineset.face_mark_negation == "EXCLUSIVE":
+ upred = NotUP1D(upred)
+ selection_criteria.append(upred)
+ # prepare selection criteria by group of objects
+ if lineset.select_by_group:
+ if lineset.group is not None:
+ names = dict((ob.name, True) for ob in lineset.group.objects)
+ upred = ObjectNamesUP1D(names, lineset.group_negation == 'EXCLUSIVE')
+ selection_criteria.append(upred)
+ # prepare selection criteria by image border
+ if lineset.select_by_image_border:
+ fac = scene.render.resolution_percentage / 100.0
+ w = scene.render.resolution_x * fac
+ h = scene.render.resolution_y * fac
+ if scene.render.use_border:
+ xmin = scene.render.border_min_x * w
+ xmax = scene.render.border_max_x * w
+ ymin = scene.render.border_min_y * h
+ ymax = scene.render.border_max_y * h
+ else:
+ xmin, xmax = 0.0, float(w)
+ ymin, ymax = 0.0, float(h)
+ upred = WithinImageBoundaryUP1D(xmin, ymin, xmax, ymax)
+ selection_criteria.append(upred)
+ # select feature edges
+ upred = join_unary_predicates(selection_criteria, AndUP1D)
+ if upred is None:
+ upred = TrueUP1D()
+ Operators.select(upred)
+ # join feature edges to form chains
+ if linestyle.use_chaining:
+ if linestyle.chaining == "PLAIN":
+ if linestyle.same_object:
+ Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(upred))
+ else:
+ Operators.bidirectional_chain(ChainPredicateIterator(upred, TrueBP1D()), NotUP1D(upred))
+ elif linestyle.chaining == "SKETCHY":
+ if linestyle.same_object:
+ Operators.bidirectional_chain(pySketchyChainSilhouetteIterator(linestyle.rounds))
+ else:
+ Operators.bidirectional_chain(pySketchyChainingIterator(linestyle.rounds))
+ else:
+ Operators.chain(ChainPredicateIterator(FalseUP1D(), FalseBP1D()), NotUP1D(upred))
+ # split chains
+ if linestyle.material_boundary:
+ Operators.sequential_split(MaterialBoundaryUP0D())
+ if linestyle.use_min_angle or linestyle.use_max_angle:
+ min_angle = linestyle.min_angle if linestyle.use_min_angle else None
+ max_angle = linestyle.max_angle if linestyle.use_max_angle else None
+ Operators.sequential_split(Curvature2DAngleThresholdUP0D(min_angle, max_angle))
+ if linestyle.use_split_length:
+ Operators.sequential_split(Length2DThresholdUP0D(linestyle.split_length), 1.0)
+ if linestyle.use_split_pattern:
+ pattern = []
+ if linestyle.split_dash1 > 0 and linestyle.split_gap1 > 0:
+ pattern.append(linestyle.split_dash1)
+ pattern.append(linestyle.split_gap1)
+ if linestyle.split_dash2 > 0 and linestyle.split_gap2 > 0:
+ pattern.append(linestyle.split_dash2)
+ pattern.append(linestyle.split_gap2)
+ if linestyle.split_dash3 > 0 and linestyle.split_gap3 > 0:
+ pattern.append(linestyle.split_dash3)
+ pattern.append(linestyle.split_gap3)
+ if len(pattern) > 0:
+ sampling = 1.0
+ controller = SplitPatternController(pattern, sampling)
+ Operators.sequential_split(SplitPatternStartingUP0D(controller),
+ SplitPatternStoppingUP0D(controller),
+ sampling)
+ # select chains
+ if linestyle.use_min_length or linestyle.use_max_length:
+ min_length = linestyle.min_length if linestyle.use_min_length else None
+ max_length = linestyle.max_length if linestyle.use_max_length else None
+ Operators.select(LengthThresholdUP1D(min_length, max_length))
+ # prepare a list of stroke shaders
+ shaders_list = []
+ for m in linestyle.geometry_modifiers:
+ if not m.use:
+ continue
+ if m.type == "SAMPLING":
+ shaders_list.append(SamplingShader(
+ m.sampling))
+ elif m.type == "BEZIER_CURVE":
+ shaders_list.append(BezierCurveShader(
+ m.error))
+ elif m.type == "SINUS_DISPLACEMENT":
+ shaders_list.append(SinusDisplacementShader(
+ m.wavelength, m.amplitude, m.phase))
+ elif m.type == "SPATIAL_NOISE":
+ shaders_list.append(SpatialNoiseShader(
+ m.amplitude, m.scale, m.octaves, m.smooth, m.pure_random))
+ elif m.type == "PERLIN_NOISE_1D":
+ shaders_list.append(PerlinNoise1DShader(
+ m.frequency, m.amplitude, m.octaves, m.angle, _seed.get(m.seed)))
+ elif m.type == "PERLIN_NOISE_2D":
+ shaders_list.append(PerlinNoise2DShader(
+ m.frequency, m.amplitude, m.octaves, m.angle, _seed.get(m.seed)))
+ elif m.type == "BACKBONE_STRETCHER":
+ shaders_list.append(BackboneStretcherShader(
+ m.backbone_length))
+ elif m.type == "TIP_REMOVER":
+ shaders_list.append(TipRemoverShader(
+ m.tip_length))
+ elif m.type == "POLYGONIZATION":
+ shaders_list.append(PolygonalizationShader(
+ m.error))
+ elif m.type == "GUIDING_LINES":
+ shaders_list.append(GuidingLinesShader(
+ m.offset))
+ elif m.type == "BLUEPRINT":
+ if m.shape == "CIRCLES":
+ shaders_list.append(pyBluePrintCirclesShader(
+ m.rounds, m.random_radius, m.random_center))
+ elif m.shape == "ELLIPSES":
+ shaders_list.append(pyBluePrintEllipsesShader(
+ m.rounds, m.random_radius, m.random_center))
+ elif m.shape == "SQUARES":
+ shaders_list.append(pyBluePrintSquaresShader(
+ m.rounds, m.backbone_length, m.random_backbone))
+ elif m.type == "2D_OFFSET":
+ shaders_list.append(Offset2DShader(
+ m.start, m.end, m.x, m.y))
+ elif m.type == "2D_TRANSFORM":
+ shaders_list.append(Transform2DShader(
+ m.pivot, m.scale_x, m.scale_y, m.angle, m.pivot_u, m.pivot_x, m.pivot_y))
+ color = linestyle.color
+ if (not linestyle.use_chaining) or (linestyle.chaining == "PLAIN" and linestyle.same_object):
+ thickness_position = linestyle.thickness_position
+ else:
+ thickness_position = "CENTER"
+ import bpy
+ if bpy.app.debug_freestyle:
+ print("Warning: Thickness position options are applied when chaining is disabled")
+ print(" or the Plain chaining is used with the Same Object option enabled.")
+ shaders_list.append(BaseColorShader(color.r, color.g, color.b, linestyle.alpha))
+ shaders_list.append(BaseThicknessShader(linestyle.thickness, thickness_position,
+ linestyle.thickness_ratio))
+ for m in linestyle.color_modifiers:
+ if not m.use:
+ continue
+ if m.type == "ALONG_STROKE":
+ shaders_list.append(ColorAlongStrokeShader(
+ m.blend, m.influence, m.color_ramp))
+ elif m.type == "DISTANCE_FROM_CAMERA":
+ shaders_list.append(ColorDistanceFromCameraShader(
+ m.blend, m.influence, m.color_ramp,
+ m.range_min, m.range_max))
+ elif m.type == "DISTANCE_FROM_OBJECT":
+ shaders_list.append(ColorDistanceFromObjectShader(
+ m.blend, m.influence, m.color_ramp, m.target,
+ m.range_min, m.range_max))
+ elif m.type == "MATERIAL":
+ shaders_list.append(ColorMaterialShader(
+ m.blend, m.influence, m.color_ramp, m.material_attr,
+ m.use_ramp))
+ for m in linestyle.alpha_modifiers:
+ if not m.use:
+ continue
+ if m.type == "ALONG_STROKE":
+ shaders_list.append(AlphaAlongStrokeShader(
+ m.blend, m.influence, m.mapping, m.invert, m.curve))
+ elif m.type == "DISTANCE_FROM_CAMERA":
+ shaders_list.append(AlphaDistanceFromCameraShader(
+ m.blend, m.influence, m.mapping, m.invert, m.curve,
+ m.range_min, m.range_max))
+ elif m.type == "DISTANCE_FROM_OBJECT":
+ shaders_list.append(AlphaDistanceFromObjectShader(
+ m.blend, m.influence, m.mapping, m.invert, m.curve, m.target,
+ m.range_min, m.range_max))
+ elif m.type == "MATERIAL":
+ shaders_list.append(AlphaMaterialShader(
+ m.blend, m.influence, m.mapping, m.invert, m.curve,
+ m.material_attr))
+ for m in linestyle.thickness_modifiers:
+ if not m.use:
+ continue
+ if m.type == "ALONG_STROKE":
+ shaders_list.append(ThicknessAlongStrokeShader(
+ thickness_position, linestyle.thickness_ratio,
+ m.blend, m.influence, m.mapping, m.invert, m.curve,
+ m.value_min, m.value_max))
+ elif m.type == "DISTANCE_FROM_CAMERA":
+ shaders_list.append(ThicknessDistanceFromCameraShader(
+ thickness_position, linestyle.thickness_ratio,
+ m.blend, m.influence, m.mapping, m.invert, m.curve,
+ m.range_min, m.range_max, m.value_min, m.value_max))
+ elif m.type == "DISTANCE_FROM_OBJECT":
+ shaders_list.append(ThicknessDistanceFromObjectShader(
+ thickness_position, linestyle.thickness_ratio,
+ m.blend, m.influence, m.mapping, m.invert, m.curve, m.target,
+ m.range_min, m.range_max, m.value_min, m.value_max))
+ elif m.type == "MATERIAL":
+ shaders_list.append(ThicknessMaterialShader(
+ thickness_position, linestyle.thickness_ratio,
+ m.blend, m.influence, m.mapping, m.invert, m.curve,
+ m.material_attr, m.value_min, m.value_max))
+ elif m.type == "CALLIGRAPHY":
+ shaders_list.append(CalligraphicThicknessShader(
+ thickness_position, linestyle.thickness_ratio,
+ m.blend, m.influence,
+ m.orientation, m.min_thickness, m.max_thickness))
+ if linestyle.caps == "ROUND":
+ shaders_list.append(RoundCapShader())
+ elif linestyle.caps == "SQUARE":
+ shaders_list.append(SquareCapShader())
+ 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)
+ if len(pattern) > 0:
+ shaders_list.append(DashedLineShader(pattern))
+ # create strokes using the shaders list
+ Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/polygonalize.py b/release/scripts/freestyle/style_modules/polygonalize.py
new file mode 100644
index 00000000000..092efbb2df1
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/polygonalize.py
@@ -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 #####
+
+# Filename : polygonalize.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Make the strokes more "polygonal"
+
+from Freestyle import ChainSilhouetteIterator, ConstantColorShader, ConstantThicknessShader, \
+ Operators, PolygonalizationShader, QuantitativeInvisibilityUP1D, SamplingShader, TrueUP1D
+from logical_operators import NotUP1D
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ SamplingShader(2.0),
+ ConstantThicknessShader(3),
+ ConstantColorShader(0.0, 0.0, 0.0),
+ PolygonalizationShader(8),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/qi0.py b/release/scripts/freestyle/style_modules/qi0.py
new file mode 100644
index 00000000000..3badf818566
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/qi0.py
@@ -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 #####
+
+# Filename : qi0.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws the visible lines (chaining follows same nature lines)
+# (most basic style module)
+
+from Freestyle import ChainSilhouetteIterator, ConstantColorShader, ConstantThicknessShader, \
+ Operators, QuantitativeInvisibilityUP1D, SamplingShader, TrueUP1D
+from logical_operators import NotUP1D
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ SamplingShader(5.0),
+ ConstantThicknessShader(4.0),
+ ConstantColorShader(0.0, 0.0, 0.0)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/qi0_not_external_contour.py b/release/scripts/freestyle/style_modules/qi0_not_external_contour.py
new file mode 100644
index 00000000000..20860b36aa3
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/qi0_not_external_contour.py
@@ -0,0 +1,41 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : qi0_not_external_contour.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws the visible lines (chaining follows same nature lines)
+# that do not belong to the external contour of the scene
+
+from Freestyle import BackboneStretcherShader, ChainSilhouetteIterator, ExternalContourUP1D, \
+ IncreasingColorShader, IncreasingThicknessShader, Operators, QuantitativeInvisibilityUP1D, \
+ SamplingShader, SpatialNoiseShader, TextureAssignerShader, TrueUP1D
+from logical_operators import AndUP1D, NotUP1D
+
+upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D())
+Operators.select(upred)
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(upred))
+shaders_list = [
+ SamplingShader(4),
+ SpatialNoiseShader(4, 150, 2, True, True),
+ 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/style_modules/qi1.py b/release/scripts/freestyle/style_modules/qi1.py
new file mode 100644
index 00000000000..7ab86b67c86
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/qi1.py
@@ -0,0 +1,37 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : qi1.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws lines hidden by one surface.
+# *** Quantitative Invisibility must have been
+# enabled in the options dialog to use this style module ****
+
+from Freestyle import ChainSilhouetteIterator, ConstantColorShader, ConstantThicknessShader, \
+ Operators, QuantitativeInvisibilityUP1D, SamplingShader, TrueUP1D
+from logical_operators import NotUP1D
+
+Operators.select(QuantitativeInvisibilityUP1D(1))
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(1)))
+shaders_list = [
+ SamplingShader(5.0),
+ ConstantThicknessShader(3),
+ ConstantColorShader(0.5, 0.5, 0.5, 1)
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/qi2.py b/release/scripts/freestyle/style_modules/qi2.py
new file mode 100644
index 00000000000..510a22e3e07
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/qi2.py
@@ -0,0 +1,37 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : qi2.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws lines hidden by two surfaces.
+# *** Quantitative Invisibility must have been
+# enabled in the options dialog to use this style module ****
+
+from Freestyle import ChainSilhouetteIterator, ConstantColorShader, ConstantThicknessShader, \
+ Operators, QuantitativeInvisibilityUP1D, SamplingShader, TrueUP1D
+from logical_operators import NotUP1D
+
+Operators.select(QuantitativeInvisibilityUP1D(2))
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(2)))
+shaders_list = [
+ SamplingShader(10),
+ ConstantThicknessShader(1.5),
+ ConstantColorShader(0.7, 0.7, 0.7, 1),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/sequentialsplit_sketchy.py b/release/scripts/freestyle/style_modules/sequentialsplit_sketchy.py
new file mode 100644
index 00000000000..966e5ddf129
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/sequentialsplit_sketchy.py
@@ -0,0 +1,44 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : sequentialsplit_sketchy.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Use the sequential split with two different
+# predicates to specify respectively the starting and
+# the stopping extremities for strokes
+
+from Freestyle import ChainSilhouetteIterator, ConstantColorShader, IncreasingThicknessShader, Nature, \
+ Operators, QuantitativeInvisibilityUP1D, SpatialNoiseShader, TextureAssignerShader, TrueUP1D
+from PredicatesU0D import pyBackTVertexUP0D, pyVertexNatureUP0D
+from logical_operators import NotUP1D
+
+upred = QuantitativeInvisibilityUP1D(0)
+Operators.select(upred)
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(upred))
+## starting and stopping predicates:
+start = pyVertexNatureUP0D(Nature.NON_T_VERTEX)
+stop = pyBackTVertexUP0D()
+Operators.sequential_split(start, stop, 10)
+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/style_modules/shaders.py b/release/scripts/freestyle/style_modules/shaders.py
new file mode 100644
index 00000000000..b955b9d4d08
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/shaders.py
@@ -0,0 +1,1238 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public 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 : shaders.py
+# Authors : Fredo Durand, Stephane Grabli, Francois Sillion, Emmanuel Turquin
+# Date : 11/08/2005
+# Purpose : Stroke shaders to be used for creation of stylized strokes
+
+from Freestyle import AdjacencyIterator, Curvature2DAngleF0D, DensityF0D, GetProjectedZF0D, \
+ Interface0DIterator, MaterialF0D, Nature, Noise, Normal2DF0D, Orientation2DF1D, \
+ StrokeAttribute, StrokeShader, StrokeVertexIterator, ZDiscontinuityF0D
+from Freestyle import ContextFunctions as CF
+from PredicatesU0D import pyVertexNatureUP0D
+
+import math
+import mathutils
+import random
+
+## thickness modifiers
+######################
+
+class pyDepthDiscontinuityThicknessShader(StrokeShader):
+ def __init__(self, min, max):
+ StrokeShader.__init__(self)
+ self.__min = float(min)
+ self.__max = float(max)
+ self.__func = ZDiscontinuityF0D()
+ def shade(self, stroke):
+ z_min=0.0
+ z_max=1.0
+ a = (self.__max - self.__min)/(z_max-z_min)
+ b = (self.__min*z_max-self.__max*z_min)/(z_max-z_min)
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ z = self.__func(Interface0DIterator(it))
+ thickness = a*z+b
+ it.object.attribute.thickness = (thickness, thickness)
+ it.increment()
+
+class pyConstantThicknessShader(StrokeShader):
+ def __init__(self, thickness):
+ StrokeShader.__init__(self)
+ self._thickness = thickness
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ t = self._thickness/2.0
+ it.object.attribute.thickness = (t, t)
+ it.increment()
+
+class pyFXSThicknessShader(StrokeShader):
+ def __init__(self, thickness):
+ StrokeShader.__init__(self)
+ self._thickness = thickness
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ t = self._thickness/2.0
+ it.object.attribute.thickness = (t, t)
+ it.increment()
+
+class pyFXSVaryingThicknessWithDensityShader(StrokeShader):
+ def __init__(self, wsize, threshold_min, threshold_max, thicknessMin, thicknessMax):
+ StrokeShader.__init__(self)
+ self.wsize= wsize
+ self.threshold_min= threshold_min
+ self.threshold_max= threshold_max
+ self._thicknessMin = thicknessMin
+ self._thicknessMax = thicknessMax
+ def shade(self, stroke):
+ n = stroke.stroke_vertices_size()
+ i = 0
+ it = stroke.stroke_vertices_begin()
+ func = DensityF0D(self.wsize)
+ while not it.is_end:
+ c = func(Interface0DIterator(it))
+ if c < self.threshold_min:
+ c = self.threshold_min
+ if c > self.threshold_max:
+ c = self.threshold_max
+## t = (c - self.threshold_min)/(self.threshold_max - self.threshold_min)*(self._thicknessMax-self._thicknessMin) + self._thicknessMin
+ t = (self.threshold_max - c )/(self.threshold_max - self.threshold_min)*(self._thicknessMax-self._thicknessMin) + self._thicknessMin
+ it.object.attribute.thickness = (t/2.0, t/2.0)
+ i = i+1
+ it.increment()
+
+class pyIncreasingThicknessShader(StrokeShader):
+ def __init__(self, thicknessMin, thicknessMax):
+ StrokeShader.__init__(self)
+ self._thicknessMin = thicknessMin
+ self._thicknessMax = thicknessMax
+ def shade(self, stroke):
+ n = stroke.stroke_vertices_size()
+ i = 0
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ c = float(i)/float(n)
+ if i < float(n)/2.0:
+ t = (1.0 - c)*self._thicknessMin + c * self._thicknessMax
+ else:
+ t = (1.0 - c)*self._thicknessMax + c * self._thicknessMin
+ it.object.attribute.thickness = (t/2.0, t/2.0)
+ i = i+1
+ it.increment()
+
+class pyConstrainedIncreasingThicknessShader(StrokeShader):
+ def __init__(self, thicknessMin, thicknessMax, ratio):
+ StrokeShader.__init__(self)
+ self._thicknessMin = thicknessMin
+ self._thicknessMax = thicknessMax
+ self._ratio = ratio
+ def shade(self, stroke):
+ slength = stroke.length_2d
+ tmp = self._ratio*slength
+ maxT = 0.0
+ if tmp < self._thicknessMax:
+ maxT = tmp
+ else:
+ maxT = self._thicknessMax
+ n = stroke.stroke_vertices_size()
+ i = 0
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ att = it.object.attribute
+ c = float(i)/float(n)
+ if i < float(n)/2.0:
+ t = (1.0 - c)*self._thicknessMin + c * maxT
+ else:
+ t = (1.0 - c)*maxT + c * self._thicknessMin
+ att.thickness = (t/2.0, t/2.0)
+ if i == n-1:
+ att.thickness = (self._thicknessMin/2.0, self._thicknessMin/2.0)
+ i = i+1
+ it.increment()
+
+class pyDecreasingThicknessShader(StrokeShader):
+ def __init__(self, thicknessMax, thicknessMin):
+ StrokeShader.__init__(self)
+ self._thicknessMin = thicknessMin
+ self._thicknessMax = thicknessMax
+ def shade(self, stroke):
+ l = stroke.length_2d
+ tMax = self._thicknessMax
+ if self._thicknessMax > 0.33*l:
+ tMax = 0.33*l
+ tMin = self._thicknessMin
+ if self._thicknessMin > 0.1*l:
+ tMin = 0.1*l
+ n = stroke.stroke_vertices_size()
+ i = 0
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ c = float(i)/float(n)
+ t = (1.0 - c)*tMax +c*tMin
+ it.object.attribute.thickness = (t/2.0, t/2.0)
+ i = i+1
+ it.increment()
+
+def smoothC(a, exp):
+ return math.pow(float(a), exp) * math.pow(2.0, exp)
+
+class pyNonLinearVaryingThicknessShader(StrokeShader):
+ def __init__(self, thicknessExtremity, thicknessMiddle, exponent):
+ StrokeShader.__init__(self)
+ self._thicknessMin = thicknessMiddle
+ self._thicknessMax = thicknessExtremity
+ self._exponent = exponent
+ def shade(self, stroke):
+ n = stroke.stroke_vertices_size()
+ i = 0
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ if i < float(n)/2.0:
+ c = float(i)/float(n)
+ else:
+ c = float(n-i)/float(n)
+ c = smoothC(c, self._exponent)
+ t = (1.0 - c)*self._thicknessMax + c * self._thicknessMin
+ it.object.attribute.thickness = (t/2.0, t/2.0)
+ i = i+1
+ it.increment()
+
+## Spherical linear interpolation (cos)
+class pySLERPThicknessShader(StrokeShader):
+ def __init__(self, thicknessMin, thicknessMax, omega=1.2):
+ StrokeShader.__init__(self)
+ self._thicknessMin = thicknessMin
+ self._thicknessMax = thicknessMax
+ self._omega = omega
+ def shade(self, stroke):
+ slength = stroke.length_2d
+ tmp = 0.33*slength
+ maxT = self._thicknessMax
+ if tmp < self._thicknessMax:
+ maxT = tmp
+ n = stroke.stroke_vertices_size()
+ i = 0
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ c = float(i)/float(n)
+ if i < float(n)/2.0:
+ t = math.sin((1-c)*self._omega)/math.sinh(self._omega)*self._thicknessMin + math.sin(c*self._omega)/math.sinh(self._omega) * maxT
+ else:
+ t = math.sin((1-c)*self._omega)/math.sinh(self._omega)*maxT + math.sin(c*self._omega)/math.sinh(self._omega) * self._thicknessMin
+ it.object.attribute.thickness = (t/2.0, t/2.0)
+ i = i+1
+ it.increment()
+
+class pyTVertexThickenerShader(StrokeShader): ## FIXME
+ def __init__(self, a=1.5, n=3):
+ StrokeShader.__init__(self)
+ self._a = a
+ self._n = n
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ predTVertex = pyVertexNatureUP0D(Nature.T_VERTEX)
+ while not it.is_end:
+ if predTVertex(it) == 1:
+ it2 = StrokeVertexIterator(it)
+ it2.increment()
+ if not (it.is_begin or it2.is_end):
+ it.increment()
+ continue
+ n = self._n
+ a = self._a
+ if it.is_begin:
+ it3 = StrokeVertexIterator(it)
+ count = 0
+ while (not it3.is_end) and count < n:
+ att = it3.object.attribute
+ (tr, tl) = att.thickness
+ r = (a-1.0)/float(n-1)*(float(n)/float(count+1) - 1) + 1
+ #r = (1.0-a)/float(n-1)*count + a
+ att.thickness = (r*tr, r*tl)
+ it3.increment()
+ count = count + 1
+ if it2.is_end:
+ it4 = StrokeVertexIterator(it)
+ count = 0
+ while (not it4.is_begin) and count < n:
+ att = it4.object.attribute
+ (tr, tl) = att.thickness
+ r = (a-1.0)/float(n-1)*(float(n)/float(count+1) - 1) + 1
+ #r = (1.0-a)/float(n-1)*count + a
+ att.thickness = (r*tr, r*tl)
+ it4.decrement()
+ count = count + 1
+ if it4.is_begin:
+ att = it4.object.attribute
+ (tr, tl) = att.thickness
+ r = (a-1.0)/float(n-1)*(float(n)/float(count+1) - 1) + 1
+ #r = (1.0-a)/float(n-1)*count + a
+ att.thickness = (r*tr, r*tl)
+ it.increment()
+
+class pyImportance2DThicknessShader(StrokeShader):
+ def __init__(self, x, y, w, kmin, kmax):
+ StrokeShader.__init__(self)
+ self._x = x
+ self._y = y
+ self._w = float(w)
+ self._kmin = float(kmin)
+ self._kmax = float(kmax)
+ def shade(self, stroke):
+ origin = mathutils.Vector([self._x, self._y])
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ v = it.object
+ p = mathutils.Vector([v.projected_x, v.projected_y])
+ d = (p-origin).length
+ if d > self._w:
+ k = self._kmin
+ else:
+ k = (self._kmax*(self._w-d) + self._kmin*d)/self._w
+ att = v.attribute
+ (tr, tl) = att.thickness
+ att.thickness = (k*tr/2.0, k*tl/2.0)
+ it.increment()
+
+class pyImportance3DThicknessShader(StrokeShader):
+ def __init__(self, x, y, z, w, kmin, kmax):
+ StrokeShader.__init__(self)
+ self._x = x
+ self._y = y
+ self._z = z
+ self._w = float(w)
+ self._kmin = float(kmin)
+ self._kmax = float(kmax)
+ def shade(self, stroke):
+ origin = mathutils.Vector([self._x, self._y, self._z])
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ v = it.object
+ p = v.point_3d
+ d = (p-origin).length
+ if d > self._w:
+ k = self._kmin
+ else:
+ k = (self._kmax*(self._w-d) + self._kmin*d)/self._w
+ att = v.attribute
+ (tr, tl) = att.thickness
+ att.thickness = (k*tr/2.0, k*tl/2.0)
+ it.increment()
+
+class pyZDependingThicknessShader(StrokeShader):
+ def __init__(self, min, max):
+ StrokeShader.__init__(self)
+ self.__min = min
+ self.__max = max
+ self.__func = GetProjectedZF0D()
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ z_min = 1
+ z_max = 0
+ while not it.is_end:
+ z = self.__func(Interface0DIterator(it))
+ if z < z_min:
+ z_min = z
+ if z > z_max:
+ z_max = z
+ it.increment()
+ z_diff = 1 / (z_max - z_min)
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ z = (self.__func(Interface0DIterator(it)) - z_min) * z_diff
+ thickness = (1 - z) * self.__max + z * self.__min
+ it.object.attribute.thickness = (thickness, thickness)
+ it.increment()
+
+
+## color modifiers
+##################
+
+class pyConstantColorShader(StrokeShader):
+ def __init__(self,r,g,b, a = 1):
+ StrokeShader.__init__(self)
+ self._r = r
+ self._g = g
+ self._b = b
+ self._a = a
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ att = it.object.attribute
+ att.color = (self._r, self._g, self._b)
+ att.alpha = self._a
+ it.increment()
+
+#c1->c2
+class pyIncreasingColorShader(StrokeShader):
+ def __init__(self,r1,g1,b1,a1, r2,g2,b2,a2):
+ StrokeShader.__init__(self)
+ self._c1 = [r1,g1,b1,a1]
+ self._c2 = [r2,g2,b2,a2]
+ def shade(self, stroke):
+ n = stroke.stroke_vertices_size() - 1
+ inc = 0
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ att = it.object.attribute
+ c = float(inc)/float(n)
+
+ att.color = ((1-c)*self._c1[0] + c*self._c2[0],
+ (1-c)*self._c1[1] + c*self._c2[1],
+ (1-c)*self._c1[2] + c*self._c2[2])
+ att.alpha = (1-c)*self._c1[3] + c*self._c2[3]
+ inc = inc+1
+ it.increment()
+
+# c1->c2->c1
+class pyInterpolateColorShader(StrokeShader):
+ def __init__(self,r1,g1,b1,a1, r2,g2,b2,a2):
+ StrokeShader.__init__(self)
+ self._c1 = [r1,g1,b1,a1]
+ self._c2 = [r2,g2,b2,a2]
+ def shade(self, stroke):
+ n = stroke.stroke_vertices_size() - 1
+ inc = 0
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ att = it.object.attribute
+ u = float(inc)/float(n)
+ c = 1-2*(math.fabs(u-0.5))
+ att.color = ((1-c)*self._c1[0] + c*self._c2[0],
+ (1-c)*self._c1[1] + c*self._c2[1],
+ (1-c)*self._c1[2] + c*self._c2[2])
+ att.alpha = (1-c)*self._c1[3] + c*self._c2[3]
+ inc = inc+1
+ it.increment()
+
+class pyMaterialColorShader(StrokeShader):
+ def __init__(self, threshold=50):
+ StrokeShader.__init__(self)
+ self._threshold = threshold
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ func = MaterialF0D()
+ xn = 0.312713
+ yn = 0.329016
+ Yn = 1.0
+ un = 4.* xn/ ( -2.*xn + 12.*yn + 3. )
+ vn= 9.* yn/ ( -2.*xn + 12.*yn +3. )
+ while not it.is_end:
+ mat = func(Interface0DIterator(it))
+
+ r = mat.diffuse[0]
+ g = mat.diffuse[1]
+ b = mat.diffuse[2]
+
+ X = 0.412453*r + 0.35758 *g + 0.180423*b
+ Y = 0.212671*r + 0.71516 *g + 0.072169*b
+ Z = 0.019334*r + 0.119193*g + 0.950227*b
+
+ if X == 0 and Y == 0 and Z == 0:
+ X = 0.01
+ Y = 0.01
+ Z = 0.01
+ u = 4.*X / (X + 15.*Y + 3.*Z)
+ v = 9.*Y / (X + 15.*Y + 3.*Z)
+
+ L= 116. * math.pow((Y/Yn),(1./3.)) -16
+ U = 13. * L * (u - un)
+ V = 13. * L * (v - vn)
+
+ if L > self._threshold:
+ L = L/1.3
+ U = U+10
+ else:
+ L = L +2.5*(100-L)/5.
+ U = U/3.0
+ V = V/3.0
+ u = U / (13. * L) + un
+ v = V / (13. * L) + vn
+
+ Y = Yn * math.pow( ((L+16.)/116.), 3.)
+ X = -9. * Y * u / ((u - 4.)* v - u * v)
+ Z = (9. * Y - 15*v*Y - v*X) /( 3. * v)
+
+ r = 3.240479 * X - 1.53715 * Y - 0.498535 * Z
+ g = -0.969256 * X + 1.875991 * Y + 0.041556 * Z
+ b = 0.055648 * X - 0.204043 * Y + 1.057311 * Z
+
+ r = max(0,r)
+ g = max(0,g)
+ b = max(0,b)
+
+ it.object.attribute.color = (r, g, b)
+ it.increment()
+
+class pyRandomColorShader(StrokeShader):
+ def __init__(self, s=1):
+ StrokeShader.__init__(self)
+ random.seed(s)
+ def shade(self, stroke):
+ ## pick a random color
+ c0 = float(random.uniform(15,75))/100.0
+ c1 = float(random.uniform(15,75))/100.0
+ c2 = float(random.uniform(15,75))/100.0
+ print(c0, c1, c2)
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ it.object.attribute.color = (c0,c1,c2)
+ it.increment()
+
+class py2DCurvatureColorShader(StrokeShader):
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ func = Curvature2DAngleF0D()
+ while not it.is_end:
+ c = func(Interface0DIterator(it))
+ if c < 0:
+ print("negative 2D curvature")
+ color = 10.0 * c/3.1415
+ it.object.attribute.color = (color, color, color)
+ it.increment()
+
+class pyTimeColorShader(StrokeShader):
+ def __init__(self, step=0.01):
+ StrokeShader.__init__(self)
+ self._t = 0
+ self._step = step
+ def shade(self, stroke):
+ c = self._t*1.0
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ it.object.attribute.color = (c,c,c)
+ it.increment()
+ self._t = self._t+self._step
+
+## geometry modifiers
+
+class pySamplingShader(StrokeShader):
+ def __init__(self, sampling):
+ StrokeShader.__init__(self)
+ self._sampling = sampling
+ def shade(self, stroke):
+ stroke.resample(float(self._sampling))
+ stroke.update_length()
+
+class pyBackboneStretcherShader(StrokeShader):
+ def __init__(self, l):
+ StrokeShader.__init__(self)
+ self._l = l
+ def shade(self, stroke):
+ it0 = stroke.stroke_vertices_begin()
+ it1 = StrokeVertexIterator(it0)
+ it1.increment()
+ itn = stroke.stroke_vertices_end()
+ itn.decrement()
+ itn_1 = StrokeVertexIterator(itn)
+ itn_1.decrement()
+ v0 = it0.object
+ v1 = it1.object
+ vn_1 = itn_1.object
+ vn = itn.object
+ p0 = mathutils.Vector([v0.projected_x, v0.projected_y])
+ pn = mathutils.Vector([vn.projected_x, vn.projected_y])
+ p1 = mathutils.Vector([v1.projected_x, v1.projected_y])
+ pn_1 = mathutils.Vector([vn_1.projected_x, vn_1.projected_y])
+ d1 = p0-p1
+ d1.normalize()
+ dn = pn-pn_1
+ dn.normalize()
+ newFirst = p0+d1*float(self._l)
+ newLast = pn+dn*float(self._l)
+ v0.point = newFirst
+ vn.point = newLast
+ stroke.update_length()
+
+class pyLengthDependingBackboneStretcherShader(StrokeShader):
+ def __init__(self, l):
+ StrokeShader.__init__(self)
+ self._l = l
+ def shade(self, stroke):
+ l = stroke.length_2d
+ stretch = self._l*l
+ it0 = stroke.stroke_vertices_begin()
+ it1 = StrokeVertexIterator(it0)
+ it1.increment()
+ itn = stroke.stroke_vertices_end()
+ itn.decrement()
+ itn_1 = StrokeVertexIterator(itn)
+ itn_1.decrement()
+ v0 = it0.object
+ v1 = it1.object
+ vn_1 = itn_1.object
+ vn = itn.object
+ p0 = mathutils.Vector([v0.projected_x, v0.projected_y])
+ pn = mathutils.Vector([vn.projected_x, vn.projected_y])
+ p1 = mathutils.Vector([v1.projected_x, v1.projected_y])
+ pn_1 = mathutils.Vector([vn_1.projected_x, vn_1.projected_y])
+ d1 = p0-p1
+ d1.normalize()
+ dn = pn-pn_1
+ dn.normalize()
+ newFirst = p0+d1*float(stretch)
+ newLast = pn+dn*float(stretch)
+ v0.point = newFirst
+ vn.point = newLast
+ stroke.update_length()
+
+
+## Shader to replace a stroke by its corresponding tangent
+class pyGuidingLineShader(StrokeShader):
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin() ## get the first vertex
+ itlast = stroke.stroke_vertices_end() ##
+ itlast.decrement() ## get the last one
+ t = itlast.object.point - it.object.point ## tangent direction
+ itmiddle = StrokeVertexIterator(it) ##
+ while itmiddle.object.u < 0.5: ## look for the stroke middle vertex
+ itmiddle.increment() ##
+ it = StrokeVertexIterator(itmiddle)
+ it.increment()
+ while not it.is_end: ## position all the vertices along the tangent for the right part
+ it.object.point = itmiddle.object.point \
+ +t*(it.object.u-itmiddle.object.u)
+ it.increment()
+ it = StrokeVertexIterator(itmiddle)
+ it.decrement()
+ while not it.is_begin: ## position all the vertices along the tangent for the left part
+ it.object.point = itmiddle.object.point \
+ -t*(itmiddle.object.u-it.object.u)
+ it.decrement()
+ it.object.point = itmiddle.object.point-t*itmiddle.object.u ## first vertex
+ stroke.update_length()
+
+
+class pyBackboneStretcherNoCuspShader(StrokeShader):
+ def __init__(self, l):
+ StrokeShader.__init__(self)
+ self._l = l
+ def shade(self, stroke):
+ it0 = stroke.stroke_vertices_begin()
+ it1 = StrokeVertexIterator(it0)
+ it1.increment()
+ itn = stroke.stroke_vertices_end()
+ itn.decrement()
+ itn_1 = StrokeVertexIterator(itn)
+ itn_1.decrement()
+ v0 = it0.object
+ v1 = it1.object
+ if (v0.nature & Nature.CUSP) == 0 and (v1.nature & Nature.CUSP) == 0:
+ p0 = v0.point
+ p1 = v1.point
+ d1 = p0-p1
+ d1.normalize()
+ newFirst = p0+d1*float(self._l)
+ v0.point = newFirst
+ vn_1 = itn_1.object
+ vn = itn.object
+ if (vn.nature & Nature.CUSP) == 0 and (vn_1.nature & Nature.CUSP) == 0:
+ pn = vn.point
+ pn_1 = vn_1.point
+ dn = pn-pn_1
+ dn.normalize()
+ newLast = pn+dn*float(self._l)
+ vn.point = newLast
+ stroke.update_length()
+
+class pyDiffusion2Shader(StrokeShader):
+ """This shader iteratively adds an offset to the position of each
+ stroke vertex in the direction perpendicular to the stroke direction
+ at the point. The offset is scaled by the 2D curvature (i.e., how
+ quickly the stroke curve is) at the point."""
+ def __init__(self, lambda1, nbIter):
+ StrokeShader.__init__(self)
+ self._lambda = lambda1
+ self._nbIter = nbIter
+ self._normalInfo = Normal2DF0D()
+ self._curvatureInfo = Curvature2DAngleF0D()
+ def shade(self, stroke):
+ for i in range (1, self._nbIter):
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ v = it.object
+ p1 = v.point
+ p2 = self._normalInfo(Interface0DIterator(it))*self._lambda*self._curvatureInfo(Interface0DIterator(it))
+ v.point = p1+p2
+ it.increment()
+ stroke.update_length()
+
+class pyTipRemoverShader(StrokeShader):
+ def __init__(self, l):
+ StrokeShader.__init__(self)
+ self._l = l
+ def shade(self, stroke):
+ originalSize = stroke.stroke_vertices_size()
+ if originalSize < 4:
+ return
+ verticesToRemove = []
+ oldAttributes = []
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ v = it.object
+ if v.curvilinear_abscissa < self._l or v.stroke_length-v.curvilinear_abscissa < self._l:
+ verticesToRemove.append(v)
+ oldAttributes.append(StrokeAttribute(v.attribute))
+ it.increment()
+ if originalSize-len(verticesToRemove) < 2:
+ return
+ for sv in verticesToRemove:
+ stroke.remove_vertex(sv)
+ stroke.update_length()
+ stroke.resample(originalSize)
+ if stroke.stroke_vertices_size() != originalSize:
+ print("pyTipRemover: Warning: resampling problem")
+ it = stroke.stroke_vertices_begin()
+ for a in oldAttributes:
+ if it.is_end:
+ break
+ it.object.attribute = a
+ it.increment()
+ stroke.update_length()
+
+class pyTVertexRemoverShader(StrokeShader):
+ def shade(self, stroke):
+ if stroke.stroke_vertices_size() <= 3:
+ return
+ predTVertex = pyVertexNatureUP0D(Nature.T_VERTEX)
+ it = stroke.stroke_vertices_begin()
+ itlast = stroke.stroke_vertices_end()
+ itlast.decrement()
+ if predTVertex(it):
+ stroke.remove_vertex(it.object)
+ if predTVertex(itlast):
+ stroke.remove_vertex(itlast.object)
+ stroke.update_length()
+
+class pyExtremitiesOrientationShader(StrokeShader):
+ def __init__(self, x1,y1,x2=0,y2=0):
+ StrokeShader.__init__(self)
+ self._v1 = mathutils.Vector([x1,y1])
+ self._v2 = mathutils.Vector([x2,y2])
+ def shade(self, stroke):
+ #print(self._v1.x,self._v1.y)
+ stroke.setBeginningOrientation(self._v1.x,self._v1.y)
+ stroke.setEndingOrientation(self._v2.x,self._v2.y)
+
+def get_fedge(it1, it2):
+ return it1.get_fedge(it2)
+
+class pyHLRShader(StrokeShader):
+ def shade(self, stroke):
+ originalSize = stroke.stroke_vertices_size()
+ if originalSize < 4:
+ return
+ it = stroke.stroke_vertices_begin()
+ invisible = 0
+ it2 = StrokeVertexIterator(it)
+ it2.increment()
+ fe = get_fedge(it.object, it2.object)
+ if fe.viewedge.qi != 0:
+ invisible = 1
+ while not it2.is_end:
+ v = it.object
+ vnext = it2.object
+ if (v.nature & Nature.VIEW_VERTEX) != 0:
+ #if (v.nature & Nature.T_VERTEX) != 0:
+ fe = get_fedge(v, vnext)
+ qi = fe.viewedge.qi
+ if qi != 0:
+ invisible = 1
+ else:
+ invisible = 0
+ if invisible:
+ v.attribute.visible = False
+ it.increment()
+ it2.increment()
+
+class pyTVertexOrientationShader(StrokeShader):
+ def __init__(self):
+ StrokeShader.__init__(self)
+ self._Get2dDirection = Orientation2DF1D()
+ ## finds the TVertex orientation from the TVertex and
+ ## the previous or next edge
+ def findOrientation(self, tv, ve):
+ mateVE = tv.get_mate(ve)
+ if ve.qi != 0 or mateVE.qi != 0:
+ ait = AdjacencyIterator(tv,1,0)
+ winner = None
+ incoming = True
+ while not ait.is_end:
+ ave = ait.object
+ if ave.id != ve.id and ave.id != mateVE.id:
+ winner = ait.object
+ if not ait.isIncoming(): # FIXME
+ incoming = False
+ break
+ ait.increment()
+ if winner is not None:
+ if not incoming:
+ direction = self._Get2dDirection(winner.last_fedge)
+ else:
+ direction = self._Get2dDirection(winner.first_fedge)
+ return direction
+ return None
+ def castToTVertex(self, cp):
+ if cp.t2d() == 0.0:
+ return cp.first_svertex.viewvertex
+ elif cp.t2d() == 1.0:
+ return cp.second_svertex.viewvertex
+ return None
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ it2 = StrokeVertexIterator(it)
+ it2.increment()
+ ## case where the first vertex is a TVertex
+ v = it.object
+ if (v.nature & Nature.T_VERTEX) != 0:
+ tv = self.castToTVertex(v)
+ if tv is not None:
+ ve = get_fedge(v, it2.object).viewedge
+ dir = self.findOrientation(tv, ve)
+ if dir is not None:
+ #print(dir.x, dir.y)
+ v.attribute.set_attribute_vec2("orientation", dir)
+ while not it2.is_end:
+ vprevious = it.object
+ v = it2.object
+ if (v.nature & Nature.T_VERTEX) != 0:
+ tv = self.castToTVertex(v)
+ if tv is not None:
+ ve = get_fedge(vprevious, v).viewedge
+ dir = self.findOrientation(tv, ve)
+ if dir is not None:
+ #print(dir.x, dir.y)
+ v.attribute.set_attribute_vec2("orientation", dir)
+ it.increment()
+ it2.increment()
+ ## case where the last vertex is a TVertex
+ v = it.object
+ if (v.nature & Nature.T_VERTEX) != 0:
+ itPrevious = StrokeVertexIterator(it)
+ itPrevious.decrement()
+ tv = self.castToTVertex(v)
+ if tv is not None:
+ ve = get_fedge(itPrevious.object, v).viewedge
+ dir = self.findOrientation(tv, ve)
+ if dir is not None:
+ #print(dir.x, dir.y)
+ v.attribute.set_attribute_vec2("orientation", dir)
+
+class pySinusDisplacementShader(StrokeShader):
+ def __init__(self, f, a):
+ StrokeShader.__init__(self)
+ self._f = f
+ self._a = a
+ self._getNormal = Normal2DF0D()
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ v = it.object
+ #print(self._getNormal.name)
+ n = self._getNormal(Interface0DIterator(it))
+ p = v.point
+ u = v.u
+ a = self._a*(1-2*(math.fabs(u-0.5)))
+ n = n*a*math.cos(self._f*u*6.28)
+ #print(n.x, n.y)
+ v.point = p+n
+ #v.point = v.point+n*a*math.cos(f*v.u)
+ it.increment()
+ stroke.update_length()
+
+class pyPerlinNoise1DShader(StrokeShader):
+ def __init__(self, freq = 10, amp = 10, oct = 4, seed = -1):
+ StrokeShader.__init__(self)
+ self.__noise = Noise(seed)
+ self.__freq = freq
+ self.__amp = amp
+ self.__oct = oct
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ v = it.object
+ i = v.projected_x + v.projected_y
+ nres = self.__noise.turbulence1(i, self.__freq, self.__amp, self.__oct)
+ v.point = (v.projected_x + nres, v.projected_y + nres)
+ it.increment()
+ stroke.update_length()
+
+class pyPerlinNoise2DShader(StrokeShader):
+ def __init__(self, freq = 10, amp = 10, oct = 4, seed = -1):
+ StrokeShader.__init__(self)
+ self.__noise = Noise(seed)
+ self.__freq = freq
+ self.__amp = amp
+ self.__oct = oct
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ v = it.object
+ vec = mathutils.Vector([v.projected_x, v.projected_y])
+ nres = self.__noise.turbulence2(vec, self.__freq, self.__amp, self.__oct)
+ v.point = (v.projected_x + nres, v.projected_y + nres)
+ it.increment()
+ stroke.update_length()
+
+class pyBluePrintCirclesShader(StrokeShader):
+ def __init__(self, turns = 1, random_radius = 3, random_center = 5):
+ StrokeShader.__init__(self)
+ self.__turns = turns
+ self.__random_center = random_center
+ self.__random_radius = random_radius
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ if it.is_end:
+ return
+ p_min = it.object.point.copy()
+ p_max = it.object.point.copy()
+ while not it.is_end:
+ p = it.object.point
+ if p.x < p_min.x:
+ p_min.x = p.x
+ if p.x > p_max.x:
+ p_max.x = p.x
+ if p.y < p_min.y:
+ p_min.y = p.y
+ if p.y > p_max.y:
+ p_max.y = p.y
+ it.increment()
+ stroke.resample(32 * self.__turns)
+ sv_nb = stroke.stroke_vertices_size()
+# print("min :", p_min.x, p_min.y) # DEBUG
+# print("mean :", p_sum.x, p_sum.y) # DEBUG
+# print("max :", p_max.x, p_max.y) # DEBUG
+# print("----------------------") # DEBUG
+#######################################################
+ sv_nb = sv_nb // self.__turns
+ center = (p_min + p_max) / 2
+ radius = (center.x - p_min.x + center.y - p_min.y) / 2
+ p_new = mathutils.Vector([0, 0])
+#######################################################
+ R = self.__random_radius
+ C = self.__random_center
+ i = 0
+ it = stroke.stroke_vertices_begin()
+ for j in range(self.__turns):
+ prev_radius = radius
+ prev_center = center
+ radius = radius + random.randint(-R, R)
+ center = center + mathutils.Vector([random.randint(-C, C), random.randint(-C, C)])
+ while i < sv_nb and not it.is_end:
+ t = float(i) / float(sv_nb - 1)
+ r = prev_radius + (radius - prev_radius) * t
+ c = prev_center + (center - prev_center) * t
+ p_new.x = c.x + r * math.cos(2 * math.pi * t)
+ p_new.y = c.y + r * math.sin(2 * math.pi * t)
+ it.object.point = p_new
+ i = i + 1
+ it.increment()
+ i = 1
+ verticesToRemove = []
+ while not it.is_end:
+ verticesToRemove.append(it.object)
+ it.increment()
+ for sv in verticesToRemove:
+ stroke.remove_vertex(sv)
+ stroke.update_length()
+
+class pyBluePrintEllipsesShader(StrokeShader):
+ def __init__(self, turns = 1, random_radius = 3, random_center = 5):
+ StrokeShader.__init__(self)
+ self.__turns = turns
+ self.__random_center = random_center
+ self.__random_radius = random_radius
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ if it.is_end:
+ return
+ p_min = it.object.point.copy()
+ p_max = it.object.point.copy()
+ while not it.is_end:
+ p = it.object.point
+ if p.x < p_min.x:
+ p_min.x = p.x
+ if p.x > p_max.x:
+ p_max.x = p.x
+ if p.y < p_min.y:
+ p_min.y = p.y
+ if p.y > p_max.y:
+ p_max.y = p.y
+ it.increment()
+ stroke.resample(32 * self.__turns)
+ sv_nb = stroke.stroke_vertices_size()
+ sv_nb = sv_nb // self.__turns
+ center = (p_min + p_max) / 2
+ radius = center - p_min
+ p_new = mathutils.Vector([0, 0])
+#######################################################
+ R = self.__random_radius
+ C = self.__random_center
+ i = 0
+ it = stroke.stroke_vertices_begin()
+ for j in range(self.__turns):
+ prev_radius = radius
+ prev_center = center
+ radius = radius + mathutils.Vector([random.randint(-R, R), random.randint(-R, R)])
+ center = center + mathutils.Vector([random.randint(-C, C), random.randint(-C, C)])
+ while i < sv_nb and not it.is_end:
+ t = float(i) / float(sv_nb - 1)
+ r = prev_radius + (radius - prev_radius) * t
+ c = prev_center + (center - prev_center) * t
+ p_new.x = c.x + r.x * math.cos(2 * math.pi * t)
+ p_new.y = c.y + r.y * math.sin(2 * math.pi * t)
+ it.object.point = p_new
+ i = i + 1
+ it.increment()
+ i = 1
+ verticesToRemove = []
+ while not it.is_end:
+ verticesToRemove.append(it.object)
+ it.increment()
+ for sv in verticesToRemove:
+ stroke.remove_vertex(sv)
+ stroke.update_length()
+
+
+class pyBluePrintSquaresShader(StrokeShader):
+ def __init__(self, turns = 1, bb_len = 10, bb_rand = 0):
+ StrokeShader.__init__(self)
+ self.__turns = turns
+ self.__bb_len = bb_len
+ self.__bb_rand = bb_rand
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ if it.is_end:
+ return
+ p_min = it.object.point.copy()
+ p_max = it.object.point.copy()
+ while not it.is_end:
+ p = it.object.point
+ if p.x < p_min.x:
+ p_min.x = p.x
+ if p.x > p_max.x:
+ p_max.x = p.x
+ if p.y < p_min.y:
+ p_min.y = p.y
+ if p.y > p_max.y:
+ p_max.y = p.y
+ it.increment()
+ stroke.resample(32 * self.__turns)
+ sv_nb = stroke.stroke_vertices_size()
+#######################################################
+ sv_nb = sv_nb // self.__turns
+ first = sv_nb // 4
+ second = 2 * first
+ third = 3 * first
+ fourth = sv_nb
+ p_first = mathutils.Vector([p_min.x - self.__bb_len, p_min.y])
+ p_first_end = mathutils.Vector([p_max.x + self.__bb_len, p_min.y])
+ p_second = mathutils.Vector([p_max.x, p_min.y - self.__bb_len])
+ p_second_end = mathutils.Vector([p_max.x, p_max.y + self.__bb_len])
+ p_third = mathutils.Vector([p_max.x + self.__bb_len, p_max.y])
+ p_third_end = mathutils.Vector([p_min.x - self.__bb_len, p_max.y])
+ p_fourth = mathutils.Vector([p_min.x, p_max.y + self.__bb_len])
+ p_fourth_end = mathutils.Vector([p_min.x, p_min.y - self.__bb_len])
+#######################################################
+ R = self.__bb_rand
+ r = self.__bb_rand // 2
+ it = stroke.stroke_vertices_begin()
+ visible = True
+ for j in range(self.__turns):
+ p_first = p_first + mathutils.Vector([random.randint(-R, R), random.randint(-r, r)])
+ p_first_end = p_first_end + mathutils.Vector([random.randint(-R, R), random.randint(-r, r)])
+ p_second = p_second + mathutils.Vector([random.randint(-r, r), random.randint(-R, R)])
+ p_second_end = p_second_end + mathutils.Vector([random.randint(-r, r), random.randint(-R, R)])
+ p_third = p_third + mathutils.Vector([random.randint(-R, R), random.randint(-r, r)])
+ p_third_end = p_third_end + mathutils.Vector([random.randint(-R, R), random.randint(-r, r)])
+ p_fourth = p_fourth + mathutils.Vector([random.randint(-r, r), random.randint(-R, R)])
+ p_fourth_end = p_fourth_end + mathutils.Vector([random.randint(-r, r), random.randint(-R, R)])
+ vec_first = p_first_end - p_first
+ vec_second = p_second_end - p_second
+ vec_third = p_third_end - p_third
+ vec_fourth = p_fourth_end - p_fourth
+ i = 0
+ while i < sv_nb and not it.is_end:
+ if i < first:
+ p_new = p_first + vec_first * float(i)/float(first - 1)
+ if i == first - 1:
+ visible = False
+ elif i < second:
+ p_new = p_second + vec_second * float(i - first)/float(second - first - 1)
+ if i == second - 1:
+ visible = False
+ elif i < third:
+ p_new = p_third + vec_third * float(i - second)/float(third - second - 1)
+ if i == third - 1:
+ visible = False
+ else:
+ p_new = p_fourth + vec_fourth * float(i - third)/float(fourth - third - 1)
+ if i == fourth - 1:
+ visible = False
+ if it.object == None:
+ i = i + 1
+ it.increment()
+ if not visible:
+ visible = True
+ continue
+ it.object.point = p_new
+ it.object.attribute.visible = visible
+ if not visible:
+ visible = True
+ i = i + 1
+ it.increment()
+ verticesToRemove = []
+ while not it.is_end:
+ verticesToRemove.append(it.object)
+ it.increment()
+ for sv in verticesToRemove:
+ stroke.remove_vertex(sv)
+ stroke.update_length()
+
+
+class pyBluePrintDirectedSquaresShader(StrokeShader):
+ def __init__(self, turns = 1, bb_len = 10, mult = 1):
+ StrokeShader.__init__(self)
+ self.__mult = mult
+ self.__turns = turns
+ self.__bb_len = 1 + float(bb_len) / 100
+ def shade(self, stroke):
+ stroke.resample(32 * self.__turns)
+ p_mean = mathutils.Vector([0, 0])
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ p = it.object.point
+ p_mean = p_mean + p
+ it.increment()
+ sv_nb = stroke.stroke_vertices_size()
+ p_mean = p_mean / sv_nb
+ p_var_xx = 0
+ p_var_yy = 0
+ p_var_xy = 0
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ p = it.object.point
+ p_var_xx = p_var_xx + math.pow(p.x - p_mean.x, 2)
+ p_var_yy = p_var_yy + math.pow(p.y - p_mean.y, 2)
+ p_var_xy = p_var_xy + (p.x - p_mean.x) * (p.y - p_mean.y)
+ it.increment()
+ p_var_xx = p_var_xx / sv_nb
+ p_var_yy = p_var_yy / sv_nb
+ p_var_xy = p_var_xy / sv_nb
+## print(p_var_xx, p_var_yy, p_var_xy)
+ trace = p_var_xx + p_var_yy
+ det = p_var_xx * p_var_yy - p_var_xy * p_var_xy
+ sqrt_coeff = math.sqrt(trace * trace - 4 * det)
+ lambda1 = (trace + sqrt_coeff) / 2
+ lambda2 = (trace - sqrt_coeff) / 2
+## print(lambda1, lambda2)
+ theta = math.atan(2 * p_var_xy / (p_var_xx - p_var_yy)) / 2
+## print(theta)
+ if p_var_yy > p_var_xx:
+ e1 = mathutils.Vector([math.cos(theta + math.pi / 2), math.sin(theta + math.pi / 2)]) * math.sqrt(lambda1) * self.__mult
+ e2 = mathutils.Vector([math.cos(theta + math.pi), math.sin(theta + math.pi)]) * math.sqrt(lambda2) * self.__mult
+ else:
+ e1 = mathutils.Vector([math.cos(theta), math.sin(theta)]) * math.sqrt(lambda1) * self.__mult
+ e2 = mathutils.Vector([math.cos(theta + math.pi / 2), math.sin(theta + math.pi / 2)]) * math.sqrt(lambda2) * self.__mult
+#######################################################
+ sv_nb = sv_nb // self.__turns
+ first = sv_nb // 4
+ second = 2 * first
+ third = 3 * first
+ fourth = sv_nb
+ bb_len1 = self.__bb_len
+ bb_len2 = 1 + (bb_len1 - 1) * math.sqrt(lambda1 / lambda2)
+ p_first = p_mean - e1 - e2 * bb_len2
+ p_second = p_mean - e1 * bb_len1 + e2
+ p_third = p_mean + e1 + e2 * bb_len2
+ p_fourth = p_mean + e1 * bb_len1 - e2
+ vec_first = e2 * bb_len2 * 2
+ vec_second = e1 * bb_len1 * 2
+ vec_third = vec_first * -1
+ vec_fourth = vec_second * -1
+#######################################################
+ it = stroke.stroke_vertices_begin()
+ visible = True
+ for j in range(self.__turns):
+ i = 0
+ while i < sv_nb:
+ if i < first:
+ p_new = p_first + vec_first * float(i)/float(first - 1)
+ if i == first - 1:
+ visible = False
+ elif i < second:
+ p_new = p_second + vec_second * float(i - first)/float(second - first - 1)
+ if i == second - 1:
+ visible = False
+ elif i < third:
+ p_new = p_third + vec_third * float(i - second)/float(third - second - 1)
+ if i == third - 1:
+ visible = False
+ else:
+ p_new = p_fourth + vec_fourth * float(i - third)/float(fourth - third - 1)
+ if i == fourth - 1:
+ visible = False
+ it.object.point = p_new
+ it.object.attribute.visible = visible
+ if not visible:
+ visible = True
+ i = i + 1
+ it.increment()
+ verticesToRemove = []
+ while not it.is_end:
+ verticesToRemove.append(it.object)
+ it.increment()
+ for sv in verticesToRemove:
+ stroke.remove_vertex(sv)
+ stroke.update_length()
+
+class pyModulateAlphaShader(StrokeShader):
+ def __init__(self, min = 0, max = 1):
+ StrokeShader.__init__(self)
+ self.__min = min
+ self.__max = max
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ alpha = it.object.attribute.alpha
+ p = it.object.point
+ alpha = alpha * p.y / 400
+ if alpha < self.__min:
+ alpha = self.__min
+ elif alpha > self.__max:
+ alpha = self.__max
+ it.object.attribute.alpha = alpha
+ it.increment()
+
+## various
+class pyDummyShader(StrokeShader):
+ def shade(self, stroke):
+ it = stroke.stroke_vertices_begin()
+ while not it.is_end:
+ toto = Interface0DIterator(it)
+ att = it.object.attribute
+ att.color = (0.3, 0.4, 0.4)
+ att.thickness = (0, 5)
+ it.increment()
+
+class pyDebugShader(StrokeShader):
+ def shade(self, stroke):
+ fe = CF.get_selected_fedge()
+ id1 = fe.first_svertex.id
+ id2 = fe.second_svertex.id
+ #print(id1.first, id1.second)
+ #print(id2.first, id2.second)
+ it = stroke.stroke_vertices_begin()
+ found = True
+ foundfirst = True
+ foundsecond = False
+ while not it.is_end:
+ cp = it.object
+ if cp.first_svertex.id == id1 or cp.second_svertex.id == id1:
+ foundfirst = True
+ if cp.first_svertex.id == id2 or cp.second_svertex.id == id2:
+ foundsecond = True
+ if foundfirst and foundsecond:
+ found = True
+ break
+ it.increment()
+ if found:
+ print("The selected Stroke id is: ", stroke.id.first, stroke.id.second)
diff --git a/release/scripts/freestyle/style_modules/sketchy_multiple_parameterization.py b/release/scripts/freestyle/style_modules/sketchy_multiple_parameterization.py
new file mode 100644
index 00000000000..e10b0c32b55
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/sketchy_multiple_parameterization.py
@@ -0,0 +1,43 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : sketchy_multiple_parameterization.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Builds sketchy strokes whose topology relies on a
+# parameterization that covers the complete lines (visible+invisible)
+# whereas only the visible portions are actually drawn
+
+from ChainingIterators import pySketchyChainSilhouetteIterator
+from Freestyle import IncreasingColorShader, IncreasingThicknessShader, Operators, \
+ QuantitativeInvisibilityUP1D, SamplingShader, SmoothingShader, SpatialNoiseShader, \
+ TextureAssignerShader, TrueUP1D
+from shaders import pyHLRShader
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectional_chain(pySketchyChainSilhouetteIterator(3, False))
+shaders_list = [
+ SamplingShader(2),
+ SpatialNoiseShader(15, 120, 2, True, True),
+ 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/style_modules/sketchy_topology_broken.py b/release/scripts/freestyle/style_modules/sketchy_topology_broken.py
new file mode 100644
index 00000000000..7c99946c813
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/sketchy_topology_broken.py
@@ -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 #####
+
+# Filename : sketchy_topology_broken.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : The topology of the strokes is, first, built
+# independantly from the 3D topology of objects,
+# and, second, so as to chain several times the same ViewEdge.
+
+from ChainingIterators import pySketchyChainingIterator
+from Freestyle import IncreasingColorShader, IncreasingThicknessShader, Operators, \
+ QuantitativeInvisibilityUP1D, SamplingShader, SmoothingShader, SpatialNoiseShader, \
+ TextureAssignerShader, TrueUP1D
+from shaders import pyBackboneStretcherNoCuspShader
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+## Chain 3 times each ViewEdge indpendantly from the
+## initial objects topology
+Operators.bidirectional_chain(pySketchyChainingIterator(3))
+shaders_list = [
+ SamplingShader(4),
+ SpatialNoiseShader(6, 120, 2, True, True),
+ 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/style_modules/sketchy_topology_preserved.py b/release/scripts/freestyle/style_modules/sketchy_topology_preserved.py
new file mode 100644
index 00000000000..4b525b97f04
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/sketchy_topology_preserved.py
@@ -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 #####
+
+# Filename : sketchy_topology_preserved.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : The topology of the strokes is built
+# so as to chain several times the same ViewEdge.
+# The topology of the objects is preserved
+
+from ChainingIterators import pySketchyChainSilhouetteIterator
+from Freestyle import ConstantColorShader, IncreasingThicknessShader, Operators, \
+ QuantitativeInvisibilityUP1D, SamplingShader, SmoothingShader, SpatialNoiseShader, \
+ TextureAssignerShader, TrueUP1D
+
+upred = QuantitativeInvisibilityUP1D(0)
+Operators.select(upred)
+Operators.bidirectional_chain(pySketchyChainSilhouetteIterator(3, True))
+shaders_list = [
+ SamplingShader(4),
+ SpatialNoiseShader(20, 220, 2, True, True),
+ 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/style_modules/split_at_highest_2d_curvatures.py b/release/scripts/freestyle/style_modules/split_at_highest_2d_curvatures.py
new file mode 100644
index 00000000000..4e635bc4eee
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/split_at_highest_2d_curvatures.py
@@ -0,0 +1,41 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : split_at_highest_2d_curvature.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws the visible lines (chaining follows same nature lines)
+# (most basic style module)
+
+from Freestyle import ChainSilhouetteIterator, ConstantThicknessShader, IncreasingColorShader, \
+ Operators, QuantitativeInvisibilityUP1D, TextureAssignerShader, TrueUP1D
+from Functions0D import pyInverseCurvature2DAngleF0D
+from PredicatesU0D import pyParameterUP0D
+from PredicatesU1D import pyHigherLengthUP1D
+from logical_operators import NotUP1D
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+func = pyInverseCurvature2DAngleF0D()
+Operators.recursive_split(func, pyParameterUP0D(0.4, 0.6), NotUP1D(pyHigherLengthUP1D(100)), 2)
+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/style_modules/split_at_tvertices.py b/release/scripts/freestyle/style_modules/split_at_tvertices.py
new file mode 100644
index 00000000000..122b79450c6
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/split_at_tvertices.py
@@ -0,0 +1,40 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : split_at_tvertices.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws strokes that starts and stops at Tvertices (visible or not)
+
+from Freestyle import ChainSilhouetteIterator, ConstantThicknessShader, IncreasingColorShader, \
+ Nature, Operators, QuantitativeInvisibilityUP1D, TextureAssignerShader, TrueUP1D
+from PredicatesU0D import pyVertexNatureUP0D
+from logical_operators import NotUP1D
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+start = pyVertexNatureUP0D(Nature.T_VERTEX)
+## use the same predicate to decide where to start and where to stop
+## the strokes:
+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/style_modules/stroke_texture.py b/release/scripts/freestyle/style_modules/stroke_texture.py
new file mode 100644
index 00000000000..07fce377866
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/stroke_texture.py
@@ -0,0 +1,38 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : stroke_texture.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws textured strokes (illustrate the StrokeTextureShader shader)
+
+from Freestyle import BezierCurveShader, ChainSilhouetteIterator, ConstantColorShader, \
+ ConstantThicknessShader, Operators, QuantitativeInvisibilityUP1D, SamplingShader, \
+ Stroke, StrokeTextureShader, TrueUP1D
+from logical_operators import NotUP1D
+
+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/style_modules/suggestive.py b/release/scripts/freestyle/style_modules/suggestive.py
new file mode 100644
index 00000000000..3d0e031acc9
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/suggestive.py
@@ -0,0 +1,38 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : suggestive.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Draws the suggestive contours.
+# ***** The suggestive contours must be enabled
+# in the options dialog *****
+
+from Freestyle import ChainSilhouetteIterator, ConstantColorShader, IncreasingThicknessShader, \
+ Nature, Operators, QuantitativeInvisibilityUP1D, TrueUP1D
+from PredicatesU1D import pyNatureUP1D
+from logical_operators import AndUP1D, NotUP1D
+
+upred = AndUP1D(pyNatureUP1D(Nature.SUGGESTIVE_CONTOUR), QuantitativeInvisibilityUP1D(0))
+Operators.select(upred)
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(upred))
+shaders_list = [
+ IncreasingThicknessShader(1, 3),
+ ConstantColorShader(0.2, 0.2, 0.2, 1),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/thickness_fof_depth_discontinuity.py b/release/scripts/freestyle/style_modules/thickness_fof_depth_discontinuity.py
new file mode 100644
index 00000000000..9dff325bb00
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/thickness_fof_depth_discontinuity.py
@@ -0,0 +1,37 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : thickness_fof_depth_discontinuity.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Assigns to strokes a thickness that depends on the depth discontinuity
+
+from Freestyle import ChainSilhouetteIterator, ConstantColorShader, ConstantThicknessShader, \
+ Operators, QuantitativeInvisibilityUP1D, SamplingShader, TrueUP1D
+from logical_operators import NotUP1D
+from shaders import pyDepthDiscontinuityThicknessShader
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ SamplingShader(1),
+ ConstantThicknessShader(3),
+ ConstantColorShader(0.0, 0.0, 0.0),
+ pyDepthDiscontinuityThicknessShader(0.8, 6),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/tipremover.py b/release/scripts/freestyle/style_modules/tipremover.py
new file mode 100644
index 00000000000..92918840bec
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/tipremover.py
@@ -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 #####
+
+# Filename : tipremover.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Removes strokes extremities
+
+from Freestyle import ChainSilhouetteIterator, ConstantColorShader, ConstantThicknessShader, \
+ Operators, QuantitativeInvisibilityUP1D, SamplingShader, TipRemoverShader, TrueUP1D
+from logical_operators import NotUP1D
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ SamplingShader(5),
+ ConstantThicknessShader(3),
+ ConstantColorShader(0, 0, 0),
+ TipRemoverShader(20),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/tvertex_remover.py b/release/scripts/freestyle/style_modules/tvertex_remover.py
new file mode 100644
index 00000000000..962425fa009
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/tvertex_remover.py
@@ -0,0 +1,37 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : tvertex_remover.py
+# Author : Stephane Grabli
+# Date : 04/08/2005
+# Purpose : Removes TVertices
+
+from Freestyle import ChainSilhouetteIterator, ConstantColorShader, IncreasingThicknessShader, \
+ Operators, QuantitativeInvisibilityUP1D, SamplingShader, TrueUP1D
+from logical_operators import NotUP1D
+from shaders import pyTVertexRemoverShader
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+Operators.bidirectional_chain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0)))
+shaders_list = [
+ IncreasingThicknessShader(3, 5),
+ ConstantColorShader(0.2, 0.2, 0.2, 1),
+ SamplingShader(10.0),
+ pyTVertexRemoverShader(),
+ ]
+Operators.create(TrueUP1D(), shaders_list)
diff --git a/release/scripts/freestyle/style_modules/uniformpruning_zsort.py b/release/scripts/freestyle/style_modules/uniformpruning_zsort.py
new file mode 100644
index 00000000000..b9fcb33e895
--- /dev/null
+++ b/release/scripts/freestyle/style_modules/uniformpruning_zsort.py
@@ -0,0 +1,39 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Filename : uniformpruning_zsort.py
+# Authors : Fredo Durand, Stephane Grabli, Francois Sillion, Emmanuel Turquin
+# Date : 08/04/2005
+
+from Freestyle import ChainSilhouetteIterator, ConstantColorShader, ConstantThicknessShader, IntegrationType, \
+ Operators, QuantitativeInvisibilityUP1D, SamplingShader, Stroke, StrokeTextureShader
+from PredicatesB1D import pyZBP1D
+from PredicatesU1D import pyDensityUP1D
+
+Operators.select(QuantitativeInvisibilityUP1D(0))
+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 6bf81d73f8b..02115054396 100644
--- a/release/scripts/modules/addon_utils.py
+++ b/release/scripts/modules/addon_utils.py
@@ -29,7 +29,7 @@ __all__ = (
)
import bpy as _bpy
-
+_user_preferences = _bpy.context.user_preferences
error_duplicates = False
error_encoding = False
@@ -201,16 +201,16 @@ def check(module_name):
:rtype: tuple of booleans
"""
import sys
- loaded_default = module_name in _bpy.context.user_preferences.addons
+ loaded_default = module_name in _user_preferences.addons
mod = sys.modules.get(module_name)
loaded_state = mod and getattr(mod, "__addon_enabled__", Ellipsis)
if loaded_state is Ellipsis:
print("Warning: addon-module %r found module "
- "but without __addon_enabled__ field, "
- "possible name collision from file: %r" %
- (module_name, getattr(mod, "__file__", "<unknown>")))
+ "but without __addon_enabled__ field, "
+ "possible name collision from file: %r" %
+ (module_name, getattr(mod, "__file__", "<unknown>")))
loaded_state = False
@@ -232,6 +232,7 @@ def enable(module_name, default_set=True, persistent=False):
import os
import sys
+ from bpy_restrict_state import RestrictBlend
def handle_error():
import traceback
@@ -259,34 +260,38 @@ def enable(module_name, default_set=True, persistent=False):
# Split registering up into 3 steps so we can undo
# if it fails par way through.
- # 1) try import
- try:
- mod = __import__(module_name)
- mod.__time__ = os.path.getmtime(mod.__file__)
- mod.__addon_enabled__ = False
- except:
- handle_error()
- return None
-
- # 2) try register collected modules
- # removed, addons need to handle own registration now.
-
- # 3) try run the modules register function
- try:
- mod.register()
- except:
- print("Exception in module register(): %r" %
- getattr(mod, "__file__", module_name))
- handle_error()
- del sys.modules[module_name]
- return None
+ # disable the context, using the context at all is
+ # really bad while loading an addon, don't do it!
+ with RestrictBlend():
+
+ # 1) try import
+ try:
+ mod = __import__(module_name)
+ mod.__time__ = os.path.getmtime(mod.__file__)
+ mod.__addon_enabled__ = False
+ except:
+ handle_error()
+ return None
+
+ # 2) try register collected modules
+ # removed, addons need to handle own registration now.
+
+ # 3) try run the modules register function
+ try:
+ mod.register()
+ except:
+ print("Exception in module register(): %r" %
+ getattr(mod, "__file__", module_name))
+ handle_error()
+ del sys.modules[module_name]
+ return None
# * OK loaded successfully! *
if default_set:
# just in case its enabled already
- ext = _bpy.context.user_preferences.addons.get(module_name)
+ ext = _user_preferences.addons.get(module_name)
if not ext:
- ext = _bpy.context.user_preferences.addons.new()
+ ext = _user_preferences.addons.new()
ext.module = module_name
mod.__addon_enabled__ = True
@@ -327,7 +332,7 @@ def disable(module_name, default_set=True):
(module_name, "disabled" if mod is None else "loaded"))
# could be in more then once, unlikely but better do this just in case.
- addons = _bpy.context.user_preferences.addons
+ addons = _user_preferences.addons
if default_set:
while module_name in addons:
diff --git a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
new file mode 100644
index 00000000000..9be786f14c1
--- /dev/null
+++ b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
@@ -0,0 +1,917 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public 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.
+# XXX: This script is meant to be used from inside Blender!
+# You should not directly use this script, rather use update_msg.py!
+
+import collections
+import copy
+import datetime
+import os
+import re
+import sys
+
+# XXX Relative import does not work here when used from Blender...
+from bl_i18n_utils import settings as settings_i18n, utils
+
+import bpy
+
+##### Utils #####
+
+# check for strings like "+%f°"
+ignore_reg = re.compile(r"^(?:[-*.()/\\+%°0-9]|%d|%f|%s|%r|\s)*$")
+filter_message = ignore_reg.match
+
+
+def init_spell_check(settings, lang="en_US"):
+ try:
+ from bl_i18n_utils import utils_spell_check
+ return utils_spell_check.SpellChecker(settings, lang)
+ except Exception as e:
+ print("Failed to import utils_spell_check ({})".format(str(e)))
+ return None
+
+
+def _gen_check_ctxt(settings):
+ return {
+ "multi_rnatip": set(),
+ "multi_lines": set(),
+ "py_in_rna": set(),
+ "not_capitalized": set(),
+ "end_point": set(),
+ "undoc_ops": set(),
+ "spell_checker": init_spell_check(settings),
+ "spell_errors": {},
+ }
+
+
+def _gen_reports(check_ctxt):
+ return {
+ "check_ctxt": check_ctxt,
+ "rna_structs": [],
+ "rna_structs_skipped": [],
+ "rna_props": [],
+ "rna_props_skipped": [],
+ "py_messages": [],
+ "py_messages_skipped": [],
+ "src_messages": [],
+ "src_messages_skipped": [],
+ "messages_skipped": set(),
+ }
+
+
+def check(check_ctxt, msgs, key, msgsrc, settings):
+ """
+ Performs a set of checks over the given key (context, message)...
+ """
+ if check_ctxt is None:
+ return
+ multi_rnatip = check_ctxt.get("multi_rnatip")
+ multi_lines = check_ctxt.get("multi_lines")
+ py_in_rna = check_ctxt.get("py_in_rna")
+ not_capitalized = check_ctxt.get("not_capitalized")
+ end_point = check_ctxt.get("end_point")
+ undoc_ops = check_ctxt.get("undoc_ops")
+ spell_checker = check_ctxt.get("spell_checker")
+ spell_errors = check_ctxt.get("spell_errors")
+
+ if multi_rnatip is not None:
+ if key in msgs and key not in multi_rnatip:
+ multi_rnatip.add(key)
+ if multi_lines is not None:
+ if '\n' in key[1]:
+ multi_lines.add(key)
+ if py_in_rna is not None:
+ if key in py_in_rna[1]:
+ py_in_rna[0].add(key)
+ if not_capitalized is not None:
+ if(key[1] not in settings.WARN_MSGID_NOT_CAPITALIZED_ALLOWED and
+ key[1][0].isalpha() and not key[1][0].isupper()):
+ not_capitalized.add(key)
+ if end_point is not None:
+ if (key[1].strip().endswith('.') and not key[1].strip().endswith('...') and
+ key[1] not in settings.WARN_MSGID_END_POINT_ALLOWED):
+ end_point.add(key)
+ if undoc_ops is not None:
+ if key[1] == settings.UNDOC_OPS_STR:
+ undoc_ops.add(key)
+ if spell_checker is not None and spell_errors is not None:
+ err = spell_checker.check(key[1])
+ if err:
+ spell_errors[key] = err
+
+
+def print_info(reports, pot):
+ def _print(*args, **kwargs):
+ kwargs["file"] = sys.stderr
+ print(*args, **kwargs)
+
+ pot.update_info()
+
+ _print("{} RNA structs were processed (among which {} were skipped), containing {} RNA properties "
+ "(among which {} were skipped).".format(len(reports["rna_structs"]), len(reports["rna_structs_skipped"]),
+ len(reports["rna_props"]), len(reports["rna_props_skipped"])))
+ _print("{} messages were extracted from Python UI code (among which {} were skipped), and {} from C source code "
+ "(among which {} were skipped).".format(len(reports["py_messages"]), len(reports["py_messages_skipped"]),
+ len(reports["src_messages"]), len(reports["src_messages_skipped"])))
+ _print("{} messages were rejected.".format(len(reports["messages_skipped"])))
+ _print("\n")
+ _print("Current POT stats:")
+ pot.print_stats(prefix="\t", output=_print)
+ _print("\n")
+
+ check_ctxt = reports["check_ctxt"]
+ if check_ctxt is None:
+ return
+ multi_rnatip = check_ctxt.get("multi_rnatip")
+ multi_lines = check_ctxt.get("multi_lines")
+ py_in_rna = check_ctxt.get("py_in_rna")
+ not_capitalized = check_ctxt.get("not_capitalized")
+ end_point = check_ctxt.get("end_point")
+ undoc_ops = check_ctxt.get("undoc_ops")
+ spell_errors = check_ctxt.get("spell_errors")
+
+ # XXX Temp, no multi_rnatip nor py_in_rna, see below.
+ keys = multi_lines | not_capitalized | end_point | undoc_ops | spell_errors.keys()
+ if keys:
+ _print("WARNINGS:")
+ for key in keys:
+ if undoc_ops and key in undoc_ops:
+ _print("\tThe following operators are undocumented!")
+ else:
+ _print("\t“{}â€|“{}â€:".format(*key))
+ if multi_lines and key in multi_lines:
+ _print("\t\t-> newline in this message!")
+ if not_capitalized and key in not_capitalized:
+ _print("\t\t-> message not capitalized!")
+ if end_point and key in end_point:
+ _print("\t\t-> message with endpoint!")
+ # XXX Hide this one for now, too much false positives.
+# if multi_rnatip and key in multi_rnatip:
+# _print("\t\t-> tip used in several RNA items")
+# if py_in_rna and key in py_in_rna:
+# _print("\t\t-> RNA message also used in py UI code!")
+ if spell_errors and spell_errors.get(key):
+ lines = ["\t\t-> {}: misspelled, suggestions are ({})".format(w, "'" + "', '".join(errs) + "'")
+ for w, errs in spell_errors[key]]
+ _print("\n".join(lines))
+ _print("\t\t{}".format("\n\t\t".join(pot.msgs[key].sources)))
+
+
+def enable_addons(addons={}, support={}, disable=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)!
+ """
+ import addon_utils
+
+ userpref = bpy.context.user_preferences
+ used_ext = {ext.module for ext in userpref.addons}
+
+ ret = [mod for mod in addon_utils.modules(addon_utils.addons_fake_modules)
+ if ((addons and mod.__name__ in addons) or
+ (not addons and addon_utils.module_bl_info(mod)["support"] in support))]
+
+ for mod in ret:
+ module_name = mod.__name__
+ if disable:
+ if module_name not in used_ext:
+ continue
+ print(" Disabling module ", module_name)
+ bpy.ops.wm.addon_disable(module=module_name)
+ else:
+ if module_name in used_ext:
+ continue
+ print(" Enabling module ", module_name)
+ bpy.ops.wm.addon_enable(module=module_name)
+
+ # XXX There are currently some problems with bpy/rna...
+ # *Very* tricky to solve!
+ # So this is a hack to make all newly added operator visible by
+ # bpy.types.OperatorProperties.__subclasses__()
+ for cat in dir(bpy.ops):
+ cat = getattr(bpy.ops, cat)
+ for op in dir(cat):
+ getattr(cat, op).get_rna()
+
+ return ret
+
+
+def process_msg(msgs, msgctxt, msgid, msgsrc, reports, check_ctxt, settings):
+ if filter_message(msgid):
+ reports["messages_skipped"].add((msgid, msgsrc))
+ return
+ if not msgctxt:
+ # We do *not* want any "" context!
+ msgctxt = settings.DEFAULT_CONTEXT
+ # Always unescape keys!
+ msgctxt = utils.I18nMessage.do_unescape(msgctxt)
+ msgid = utils.I18nMessage.do_unescape(msgid)
+ key = (msgctxt, msgid)
+ check(check_ctxt, msgs, key, msgsrc, settings)
+ msgsrc = settings.PO_COMMENT_PREFIX_SOURCE_CUSTOM + msgsrc
+ if key not in msgs:
+ msgs[key] = utils.I18nMessage([msgctxt], [msgid], [], [msgsrc], settings=settings)
+ else:
+ msgs[key].comment_lines.append(msgsrc)
+
+
+##### RNA #####
+def dump_messages_rna(msgs, reports, settings):
+ """
+ Dump into messages dict all RNA-defined UI messages (labels en tooltips).
+ """
+ def class_blacklist():
+ blacklist_rna_class = [
+ # core classes
+ "Context", "Event", "Function", "UILayout", "UnknownType",
+ # registerable classes
+ "Panel", "Menu", "Header", "RenderEngine", "Operator", "OperatorMacro", "Macro", "KeyingSetInfo",
+ # window classes
+ "Window",
+ ]
+
+ # Collect internal operators
+ # extend with all internal operators
+ # note that this uses internal api introspection functions
+ # 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__())
+
+ get_instance = __import__("_bpy").ops.get_instance
+# path_resolve = type(bpy.context).__base__.path_resolve
+ for idname in op_ids:
+ op = get_instance(idname)
+ # XXX Do not skip INTERNAL's anymore, some of those ops show up in UI now!
+# if 'INTERNAL' in path_resolve(op, "bl_options"):
+# blacklist_rna_class.append(idname)
+
+ # Collect builtin classes we don't need to doc
+ blacklist_rna_class.append("Property")
+ blacklist_rna_class.extend([cls.__name__ for cls in bpy.types.Property.__subclasses__()])
+
+ # Collect classes which are attached to collections, these are api access only.
+ collection_props = set()
+ for cls_id in dir(bpy.types):
+ cls = getattr(bpy.types, cls_id)
+ for prop in cls.bl_rna.properties:
+ if prop.type == 'COLLECTION':
+ prop_cls = prop.srna
+ if prop_cls is not None:
+ collection_props.add(prop_cls.identifier)
+ blacklist_rna_class.extend(sorted(collection_props))
+
+ return blacklist_rna_class
+
+ check_ctxt_rna = check_ctxt_rna_tip = None
+ check_ctxt = reports["check_ctxt"]
+ if check_ctxt:
+ check_ctxt_rna = {
+ "multi_lines": check_ctxt.get("multi_lines"),
+ "not_capitalized": check_ctxt.get("not_capitalized"),
+ "end_point": check_ctxt.get("end_point"),
+ "undoc_ops": check_ctxt.get("undoc_ops"),
+ "spell_checker": check_ctxt.get("spell_checker"),
+ "spell_errors": check_ctxt.get("spell_errors"),
+ }
+ check_ctxt_rna_tip = check_ctxt_rna
+ check_ctxt_rna_tip["multi_rnatip"] = check_ctxt.get("multi_rnatip")
+
+ default_context = settings.DEFAULT_CONTEXT
+
+ # Function definitions
+ def walk_properties(cls):
+ bl_rna = cls.bl_rna
+ # Get our parents' properties, to not export them multiple times.
+ bl_rna_base = bl_rna.base
+ if bl_rna_base:
+ bl_rna_base_props = set(bl_rna_base.properties.values())
+ else:
+ bl_rna_base_props = set()
+
+ for prop in bl_rna.properties:
+ # Only write this property if our parent hasn't got it.
+ if prop in bl_rna_base_props:
+ continue
+ if prop.identifier == "rna_type":
+ continue
+ reports["rna_props"].append((cls, prop))
+
+ msgsrc = "bpy.types.{}.{}".format(bl_rna.identifier, prop.identifier)
+ msgctxt = prop.translation_context or default_context
+
+ if prop.name and (prop.name != prop.identifier or msgctxt != default_context):
+ process_msg(msgs, msgctxt, prop.name, msgsrc, reports, check_ctxt_rna, settings)
+ if prop.description:
+ process_msg(msgs, default_context, prop.description, msgsrc, reports, check_ctxt_rna_tip, settings)
+
+ if isinstance(prop, bpy.types.EnumProperty):
+ for item in prop.enum_items:
+ msgsrc = "bpy.types.{}.{}:'{}'".format(bl_rna.identifier, prop.identifier, item.identifier)
+ if item.name and item.name != item.identifier:
+ process_msg(msgs, msgctxt, item.name, msgsrc, reports, check_ctxt_rna, settings)
+ if item.description:
+ process_msg(msgs, default_context, item.description, msgsrc, reports, check_ctxt_rna_tip,
+ settings)
+
+ blacklist_rna_class = class_blacklist()
+
+ def walk_class(cls):
+ bl_rna = cls.bl_rna
+ reports["rna_structs"].append(cls)
+ if bl_rna.identifier in blacklist_rna_class:
+ reports["rna_structs_skipped"].append(cls)
+ return
+
+ # XXX translation_context of Operator sub-classes are not "good"!
+ # So ignore those Operator sub-classes (anyway, will get the same from OperatorProperties sub-classes!)...
+ if issubclass(cls, bpy.types.Operator):
+ reports["rna_structs_skipped"].append(cls)
+ return
+
+ msgsrc = "bpy.types." + bl_rna.identifier
+ msgctxt = bl_rna.translation_context or default_context
+
+ if bl_rna.name and (bl_rna.name != bl_rna.identifier or msgctxt != default_context):
+ process_msg(msgs, msgctxt, bl_rna.name, msgsrc, reports, check_ctxt_rna, settings)
+
+ if bl_rna.description:
+ process_msg(msgs, default_context, bl_rna.description, msgsrc, reports, check_ctxt_rna_tip, settings)
+ elif cls.__doc__: # XXX Some classes (like KeyingSetInfo subclasses) have void description... :(
+ process_msg(msgs, default_context, cls.__doc__, msgsrc, reports, check_ctxt_rna_tip, settings)
+
+ if hasattr(bl_rna, 'bl_label') and bl_rna.bl_label:
+ process_msg(msgs, msgctxt, bl_rna.bl_label, msgsrc, reports, check_ctxt_rna, settings)
+
+ walk_properties(cls)
+
+ def walk_keymap_hierarchy(hier, msgsrc_prev):
+ for lvl in hier:
+ msgsrc = msgsrc_prev + "." + lvl[1]
+ process_msg(msgs, default_context, lvl[0], msgsrc, reports, None, settings)
+ if lvl[3]:
+ walk_keymap_hierarchy(lvl[3], msgsrc)
+
+ # Dump Messages
+ def process_cls_list(cls_list):
+ if not cls_list:
+ return
+
+ def full_class_id(cls):
+ """ gives us 'ID.Lamp.AreaLamp' which is best for sorting."""
+ cls_id = ""
+ bl_rna = cls.bl_rna
+ while bl_rna:
+ cls_id = bl_rna.identifier + "." + cls_id
+ bl_rna = bl_rna.base
+ return cls_id
+
+ cls_list.sort(key=full_class_id)
+ for cls in cls_list:
+ walk_class(cls)
+ # Recursively process subclasses.
+ process_cls_list(cls.__subclasses__())
+
+ # Parse everything (recursively parsing from bpy_struct "class"...).
+ process_cls_list(bpy.types.ID.__base__.__subclasses__())
+
+ # And parse keymaps!
+ from bpy_extras.keyconfig_utils import KM_HIERARCHY
+
+ walk_keymap_hierarchy(KM_HIERARCHY, "KM_HIERARCHY")
+
+
+##### Python source code #####
+def dump_py_messages_from_files(msgs, reports, files, settings):
+ """
+ Dump text inlined in the python files given, e.g. 'My Name' in:
+ layout.prop("someprop", text="My Name")
+ """
+ import ast
+
+ bpy_struct = bpy.types.ID.__base__
+
+ root_paths = tuple(bpy.utils.resource_path(t) for t in ('USER', 'LOCAL', 'SYSTEM'))
+ def make_rel(path):
+ for rp in root_paths:
+ if path.startswith(rp):
+ return os.path.relpath(path, rp)
+ # Use binary's dir as fallback...
+ return os.path.relpath(path, os.path.dirname(bpy.app.binary_path))
+
+ # Helper function
+ def extract_strings_ex(node, is_split=False):
+ """
+ Recursively get strings, needed in case we have "Blah" + "Blah", passed as an argument in that case it won't
+ evaluate to a string. However, break on some kind of stopper nodes, like e.g. Subscript.
+ """
+ if type(node) == ast.Str:
+ eval_str = ast.literal_eval(node)
+ if eval_str:
+ yield (is_split, eval_str, (node,))
+ else:
+ is_split = (type(node) in separate_nodes)
+ for nd in ast.iter_child_nodes(node):
+ if type(nd) not in stopper_nodes:
+ yield from extract_strings_ex(nd, is_split=is_split)
+
+ def _extract_string_merge(estr_ls, nds_ls):
+ return "".join(s for s in estr_ls if s is not None), tuple(n for n in nds_ls if n is not None)
+
+ def extract_strings(node):
+ estr_ls = []
+ nds_ls = []
+ for is_split, estr, nds in extract_strings_ex(node):
+ estr_ls.append(estr)
+ nds_ls.extend(nds)
+ ret = _extract_string_merge(estr_ls, nds_ls)
+ return ret
+
+ def extract_strings_split(node):
+ """
+ Returns a list args as returned by 'extract_strings()', But split into groups based on separate_nodes, this way
+ expressions like ("A" if test else "B") wont be merged but "A" + "B" will.
+ """
+ estr_ls = []
+ nds_ls = []
+ bag = []
+ for is_split, estr, nds in extract_strings_ex(node):
+ if is_split:
+ bag.append((estr_ls, nds_ls))
+ estr_ls = []
+ nds_ls = []
+
+ estr_ls.append(estr)
+ nds_ls.extend(nds)
+
+ bag.append((estr_ls, nds_ls))
+
+ return [_extract_string_merge(estr_ls, nds_ls) for estr_ls, nds_ls in bag]
+
+
+ def _ctxt_to_ctxt(node):
+ return extract_strings(node)[0]
+
+ def _op_to_ctxt(node):
+ opname, _ = extract_strings(node)
+ if not opname:
+ return settings.DEFAULT_CONTEXT
+ op = bpy.ops
+ for n in opname.split('.'):
+ op = getattr(op, n)
+ try:
+ return op.get_rna().bl_rna.translation_context
+ except Exception as e:
+ default_op_context = bpy.app.translations.contexts.operator_default
+ print("ERROR: ", str(e))
+ print(" Assuming default operator context '{}'".format(default_op_context))
+ return default_op_context
+
+ # Gather function names.
+ # In addition of UI func, also parse pgettext ones...
+ # Tuples of (module name, (short names, ...)).
+ pgettext_variants = (
+ ("pgettext", ("_",)),
+ ("pgettext_iface", ("iface_",)),
+ ("pgettext_tip", ("tip_",))
+ )
+ pgettext_variants_args = {"msgid": (0, {"msgctxt": 1})}
+
+ # key: msgid keywords.
+ # val: tuples of ((keywords,), context_getter_func) to get a context for that msgid.
+ # Note: order is important, first one wins!
+ translate_kw = {
+ "text": ((("text_ctxt",), _ctxt_to_ctxt),
+ (("operator",), _op_to_ctxt),
+ ),
+ "msgid": ((("msgctxt",), _ctxt_to_ctxt),
+ ),
+ "message": (),
+ }
+
+ context_kw_set = {}
+ for k, ctxts in translate_kw.items():
+ s = set()
+ for c, _ in ctxts:
+ s |= set(c)
+ context_kw_set[k] = s
+
+ # {func_id: {msgid: (arg_pos,
+ # {msgctxt: arg_pos,
+ # ...
+ # }
+ # ),
+ # ...
+ # },
+ # ...
+ # }
+ func_translate_args = {}
+
+ # First, functions from UILayout
+ # First loop is for msgid args, second one is for msgctxt args.
+ for func_id, func in bpy.types.UILayout.bl_rna.functions.items():
+ # check it has one or more arguments as defined in translate_kw
+ for arg_pos, (arg_kw, arg) in enumerate(func.parameters.items()):
+ if ((arg_kw in translate_kw) and (not arg.is_output) and (arg.type == 'STRING')):
+ func_translate_args.setdefault(func_id, {})[arg_kw] = (arg_pos, {})
+ for func_id, func in bpy.types.UILayout.bl_rna.functions.items():
+ if func_id not in func_translate_args:
+ continue
+ for arg_pos, (arg_kw, arg) in enumerate(func.parameters.items()):
+ if (not arg.is_output) and (arg.type == 'STRING'):
+ for msgid, msgctxts in context_kw_set.items():
+ if arg_kw in msgctxts:
+ func_translate_args[func_id][msgid][1][arg_kw] = arg_pos
+ # The report() func of operators.
+ for func_id, func in bpy.types.Operator.bl_rna.functions.items():
+ # check it has one or more arguments as defined in translate_kw
+ for arg_pos, (arg_kw, arg) in enumerate(func.parameters.items()):
+ if ((arg_kw in translate_kw) and (not arg.is_output) and (arg.type == 'STRING')):
+ func_translate_args.setdefault(func_id, {})[arg_kw] = (arg_pos, {})
+ # We manually add funcs from bpy.app.translations
+ for func_id, func_ids in pgettext_variants:
+ func_translate_args[func_id] = pgettext_variants_args
+ for func_id in func_ids:
+ func_translate_args[func_id] = pgettext_variants_args
+ #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}
+ # Consider strings separate: ("a" if test else "b")
+ separate_nodes = {ast.IfExp}
+
+ check_ctxt_py = None
+ if reports["check_ctxt"]:
+ check_ctxt = reports["check_ctxt"]
+ check_ctxt_py = {
+ "py_in_rna": (check_ctxt.get("py_in_rna"), set(msgs.keys())),
+ "multi_lines": check_ctxt.get("multi_lines"),
+ "not_capitalized": check_ctxt.get("not_capitalized"),
+ "end_point": check_ctxt.get("end_point"),
+ "spell_checker": check_ctxt.get("spell_checker"),
+ "spell_errors": check_ctxt.get("spell_errors"),
+ }
+
+ for fp in files:
+ with open(fp, 'r', encoding="utf8") as filedata:
+ root_node = ast.parse(filedata.read(), fp, 'exec')
+
+ fp_rel = make_rel(fp)
+
+ for node in ast.walk(root_node):
+ if type(node) == ast.Call:
+ # print("found function at")
+ # print("%s:%d" % (fp, node.lineno))
+
+ # We can't skip such situations! from blah import foo\nfoo("bar") would also be an ast.Name func!
+ if type(node.func) == ast.Name:
+ func_id = node.func.id
+ elif hasattr(node.func, "attr"):
+ func_id = node.func.attr
+ # Ugly things like getattr(self, con.type)(context, box, con)
+ else:
+ continue
+
+ func_args = func_translate_args.get(func_id, {})
+
+ # First try to get i18n contexts, for every possible msgid id.
+ msgctxts = dict.fromkeys(func_args.keys(), "")
+ for msgid, (_, context_args) in func_args.items():
+ context_elements = {}
+ for arg_kw, arg_pos in context_args.items():
+ if arg_pos < len(node.args):
+ context_elements[arg_kw] = node.args[arg_pos]
+ else:
+ for kw in node.keywords:
+ if kw.arg == arg_kw:
+ context_elements[arg_kw] = kw.value
+ break
+ #print(context_elements)
+ for kws, proc in translate_kw[msgid]:
+ if set(kws) <= context_elements.keys():
+ args = tuple(context_elements[k] for k in kws)
+ #print("running ", proc, " with ", args)
+ ctxt = proc(*args)
+ if ctxt:
+ msgctxts[msgid] = ctxt
+ break
+
+ #print(translate_args)
+ # do nothing if not found
+ for arg_kw, (arg_pos, _) in func_args.items():
+ msgctxt = msgctxts[arg_kw]
+ estr_lst = [(None, ())]
+ if arg_pos < len(node.args):
+ estr_lst = extract_strings_split(node.args[arg_pos])
+ #print(estr, nds)
+ else:
+ for kw in node.keywords:
+ if kw.arg == arg_kw:
+ estr_lst = extract_strings_split(kw.value)
+ break
+ #print(estr, nds)
+ for estr, nds in estr_lst:
+ if estr:
+ if nds:
+ msgsrc = "{}:{}".format(fp_rel, sorted({nd.lineno for nd in nds})[0])
+ else:
+ msgsrc = "{}:???".format(fp_rel)
+ process_msg(msgs, msgctxt, estr, msgsrc, reports, check_ctxt_py, settings)
+ reports["py_messages"].append((msgctxt, estr, msgsrc))
+
+
+def dump_py_messages(msgs, reports, addons, settings, addons_only=False):
+ def _get_files(path):
+ if not os.path.exists(path):
+ return []
+ if os.path.isdir(path):
+ return [os.path.join(dpath, fn) for dpath, _, fnames in os.walk(path) for fn in fnames
+ if not fn.startswith("_") and fn.endswith(".py")]
+ return [path]
+
+ files = []
+ if not addons_only:
+ for path in settings.CUSTOM_PY_UI_FILES:
+ for root in (bpy.utils.resource_path(t) for t in ('USER', 'LOCAL', 'SYSTEM')):
+ files += _get_files(os.path.join(root, path))
+
+ # Add all given addons.
+ for mod in addons:
+ fn = mod.__file__
+ if os.path.basename(fn) == "__init__.py":
+ files += _get_files(os.path.dirname(fn))
+ else:
+ files.append(fn)
+
+ dump_py_messages_from_files(msgs, reports, sorted(files), settings)
+
+
+##### C source code #####
+def dump_src_messages(msgs, reports, settings):
+ def get_contexts():
+ """Return a mapping {C_CTXT_NAME: ctxt_value}."""
+ return {k: getattr(bpy.app.translations.contexts, n) for k, n in bpy.app.translations.contexts_C_to_py.items()}
+
+ contexts = get_contexts()
+
+ # Build regexes to extract messages (with optional contexts) from C source.
+ pygettexts = tuple(re.compile(r).search for r in settings.PYGETTEXT_KEYWORDS)
+
+ _clean_str = re.compile(settings.str_clean_re).finditer
+ clean_str = lambda s: "".join(m.group("clean") for m in _clean_str(s))
+
+ def dump_src_file(path, rel_path, msgs, reports, settings):
+ def process_entry(_msgctxt, _msgid):
+ # Context.
+ msgctxt = settings.DEFAULT_CONTEXT
+ if _msgctxt:
+ if _msgctxt in contexts:
+ msgctxt = contexts[_msgctxt]
+ elif '"' in _msgctxt or "'" in _msgctxt:
+ msgctxt = clean_str(_msgctxt)
+ else:
+ print("WARNING: raw context “{}†couldn’t be resolved!".format(_msgctxt))
+ # Message.
+ msgid = ""
+ if _msgid:
+ if '"' in _msgid or "'" in _msgid:
+ msgid = clean_str(_msgid)
+ else:
+ print("WARNING: raw message “{}†couldn’t be resolved!".format(_msgid))
+ return msgctxt, msgid
+
+ check_ctxt_src = None
+ if reports["check_ctxt"]:
+ check_ctxt = reports["check_ctxt"]
+ check_ctxt_src = {
+ "multi_lines": check_ctxt.get("multi_lines"),
+ "not_capitalized": check_ctxt.get("not_capitalized"),
+ "end_point": check_ctxt.get("end_point"),
+ "spell_checker": check_ctxt.get("spell_checker"),
+ "spell_errors": check_ctxt.get("spell_errors"),
+ }
+
+ data = ""
+ with open(path) as f:
+ data = f.read()
+ for srch in pygettexts:
+ m = srch(data)
+ line = pos = 0
+ while m:
+ d = m.groupdict()
+ # Line.
+ line += data[pos:m.start()].count('\n')
+ msgsrc = rel_path + ":" + str(line)
+ _msgid = d.get("msg_raw")
+ # First, try the "multi-contexts" stuff!
+ _msgctxts = tuple(d.get("ctxt_raw{}".format(i)) for i in range(settings.PYGETTEXT_MAX_MULTI_CTXT))
+ if _msgctxts[0]:
+ for _msgctxt in _msgctxts:
+ if not _msgctxt:
+ break
+ msgctxt, msgid = process_entry(_msgctxt, _msgid)
+ process_msg(msgs, msgctxt, msgid, msgsrc, reports, check_ctxt_src, settings)
+ reports["src_messages"].append((msgctxt, msgid, msgsrc))
+ else:
+ _msgctxt = d.get("ctxt_raw")
+ msgctxt, msgid = process_entry(_msgctxt, _msgid)
+ process_msg(msgs, msgctxt, msgid, msgsrc, reports, check_ctxt_src, settings)
+ reports["src_messages"].append((msgctxt, msgid, msgsrc))
+
+ pos = m.end()
+ line += data[m.start():pos].count('\n')
+ m = srch(data, pos)
+
+ forbidden = set()
+ forced = set()
+ if os.path.isfile(settings.SRC_POTFILES):
+ with open(settings.SRC_POTFILES) as src:
+ for l in src:
+ if l[0] == '-':
+ forbidden.add(l[1:].rstrip('\n'))
+ elif l[0] != '#':
+ forced.add(l.rstrip('\n'))
+ for root, dirs, files in os.walk(settings.POTFILES_SOURCE_DIR):
+ if "/.svn" in root:
+ continue
+ for fname in files:
+ if os.path.splitext(fname)[1] not in settings.PYGETTEXT_ALLOWED_EXTS:
+ continue
+ path = os.path.join(root, fname)
+ rel_path = os.path.relpath(path, settings.SOURCE_DIR)
+ if rel_path in forbidden:
+ continue
+ elif rel_path not in forced:
+ forced.add(rel_path)
+ for rel_path in sorted(forced):
+ path = os.path.join(settings.SOURCE_DIR, rel_path)
+ if os.path.exists(path):
+ dump_src_file(path, rel_path, msgs, reports, settings)
+
+
+##### Main functions! #####
+def dump_messages(do_messages, do_checks, settings):
+ bl_ver = "Blender " + bpy.app.version_string
+ bl_rev = bpy.app.build_revision
+ bl_date = datetime.datetime.strptime(bpy.app.build_date.decode() + "T" + bpy.app.build_time.decode(),
+ "%Y-%m-%dT%H:%M:%S")
+ pot = utils.I18nMessages.gen_empty_messages(settings.PARSER_TEMPLATE_ID, bl_ver, bl_rev, bl_date, bl_date.year,
+ settings=settings)
+ msgs = pot.msgs
+
+ # Enable all wanted addons.
+ # For now, enable all official addons, before extracting msgids.
+ addons = enable_addons(support={"OFFICIAL"})
+ # Note this is not needed if we have been started with factory settings, but just in case...
+ enable_addons(support={"COMMUNITY", "TESTING"}, disable=True)
+
+ reports = _gen_reports(_gen_check_ctxt(settings) if do_checks else None)
+
+ # Get strings from RNA.
+ dump_messages_rna(msgs, reports, settings)
+
+ # Get strings from UI layout definitions text="..." args.
+ dump_py_messages(msgs, reports, addons, settings)
+
+ # Get strings from C source code.
+ dump_src_messages(msgs, reports, 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)
+ if tip:
+ process_msg(msgs, settings.DEFAULT_CONTEXT, tip, "Addons' categories", reports, None, settings)
+
+ # Get strings specific to translations' menu.
+ for lng in settings.LANGUAGES:
+ process_msg(msgs, settings.DEFAULT_CONTEXT, lng[1], "Languages’ labels from bl_i18n_utils/settings.py",
+ reports, None, settings)
+ for cat in settings.LANGUAGES_CATEGORIES:
+ process_msg(msgs, settings.DEFAULT_CONTEXT, cat[1],
+ "Language categories’ labels from bl_i18n_utils/settings.py", reports, None, settings)
+
+ #pot.check()
+ pot.unescape() # Strings gathered in py/C source code may contain escaped chars...
+ print_info(reports, pot)
+ #pot.check()
+
+ if do_messages:
+ print("Writing messages…")
+ pot.write('PO', settings.FILE_NAME_POT)
+
+ print("Finished extracting UI messages!")
+
+
+def dump_addon_messages(module_name, messages_formats, do_checks, settings):
+ # Enable our addon and get strings from RNA.
+ addon = enable_addons(addons={module_name})[0]
+
+ addon_info = addon_utils.module_bl_info(addon)
+ ver = addon_info.name + " " + ".".join(addon_info.version)
+ rev = "???"
+ date = datetime.datetime()
+ pot = utils.I18nMessages.gen_empty_messages(settings.PARSER_TEMPLATE_ID, ver, rev, date, date.year,
+ settings=settings)
+ msgs = pot.msgs
+
+ minus_msgs = copy.deepcopy(msgs)
+
+ check_ctxt = _gen_check_ctxt(settings) if do_checks else None
+ minus_check_ctxt = _gen_check_ctxt(settings) if do_checks else None
+
+ # Get current addon state (loaded or not):
+ was_loaded = addon_utils.check(module_name)[1]
+
+ # Enable our addon and get strings from RNA.
+ addons = enable_addons(addons={module_name})
+ reports = _gen_reports(check_ctxt)
+ dump_messages_rna(msgs, reports, settings)
+
+ # Now disable our addon, and rescan RNA.
+ enable_addons(addons={module_name}, disable=True)
+ reports["check_ctxt"] = minus_check_ctxt
+ dump_messages_rna(minus_msgs, reports, settings)
+
+ # Restore previous state if needed!
+ if was_loaded:
+ enable_addons(addons={module_name})
+
+ # and make the diff!
+ for key in minus_msgs:
+ if key == settings.PO_HEADER_KEY:
+ continue
+ del msgs[key]
+
+ if check_ctxt:
+ for key in check_ctxt:
+ for warning in minus_check_ctxt[key]:
+ check_ctxt[key].remove(warning)
+
+ # and we are done with those!
+ del minus_msgs
+ del minus_check_ctxt
+
+ # get strings from UI layout definitions text="..." args
+ reports["check_ctxt"] = check_ctxt
+ dump_messages_pytext(msgs, reports, addons, settings, addons_only=True)
+
+ print_info(reports, pot)
+
+ return pot
+
+
+def main():
+ try:
+ import bpy
+ except ImportError:
+ print("This script must run from inside blender")
+ return
+
+ import sys
+ back_argv = sys.argv
+ # Get rid of Blender args!
+ sys.argv = sys.argv[sys.argv.index("--") + 1:]
+
+ 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()
+
+ settings = settings_i18n.I18nSettings()
+ settings.from_json(args.settings)
+
+ if args.output:
+ settings.FILE_NAME_POT = args.output
+
+ 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__))
+ main()
diff --git a/release/scripts/modules/bl_i18n_utils/bl_process_msg.py b/release/scripts/modules/bl_i18n_utils/bl_process_msg.py
deleted file mode 100644
index 7e9266d0530..00000000000
--- a/release/scripts/modules/bl_i18n_utils/bl_process_msg.py
+++ /dev/null
@@ -1,524 +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 *****
-
-# <pep8 compliant>
-
-# Write out messages.txt from Blender.
-# XXX: This script is meant to be used from inside Blender!
-# You should not directly use this script, rather use update_msg.py!
-
-import os
-
-# XXX Relative import does not work here when used from Blender...
-from bl_i18n_utils import settings
-
-
-#classes = set()
-
-
-SOURCE_DIR = settings.SOURCE_DIR
-
-CUSTOM_PY_UI_FILES = [os.path.abspath(os.path.join(SOURCE_DIR, p)) for p in settings.CUSTOM_PY_UI_FILES]
-FILE_NAME_MESSAGES = settings.FILE_NAME_MESSAGES
-COMMENT_PREFIX = settings.COMMENT_PREFIX
-CONTEXT_PREFIX = settings.CONTEXT_PREFIX
-CONTEXT_DEFAULT = settings.CONTEXT_DEFAULT
-UNDOC_OPS_STR = settings.UNDOC_OPS_STR
-
-NC_ALLOWED = settings.WARN_MSGID_NOT_CAPITALIZED_ALLOWED
-
-
-def check(check_ctxt, messages, key, msgsrc):
- if check_ctxt is None:
- return
- multi_rnatip = check_ctxt.get("multi_rnatip")
- multi_lines = check_ctxt.get("multi_lines")
- py_in_rna = check_ctxt.get("py_in_rna")
- not_capitalized = check_ctxt.get("not_capitalized")
- end_point = check_ctxt.get("end_point")
- undoc_ops = check_ctxt.get("undoc_ops")
-
- if multi_rnatip is not None:
- if key in messages and key not in multi_rnatip:
- multi_rnatip.add(key)
- if multi_lines is not None:
- if '\n' in key[1]:
- multi_lines.add(key)
- if py_in_rna is not None:
- if key in py_in_rna[1]:
- py_in_rna[0].add(key)
- if not_capitalized is not None:
- if(key[1] not in NC_ALLOWED and key[1][0].isalpha() and not key[1][0].isupper()):
- not_capitalized.add(key)
- if end_point is not None:
- if key[1].strip().endswith('.'):
- end_point.add(key)
- if undoc_ops is not None:
- if key[1] == UNDOC_OPS_STR:
- undoc_ops.add(key)
-
-
-def dump_messages_rna(messages, check_ctxt):
- import bpy
-
- def classBlackList():
- blacklist_rna_class = [
- # core classes
- "Context", "Event", "Function", "UILayout", "BlendData",
- # registerable classes
- "Panel", "Menu", "Header", "RenderEngine", "Operator", "OperatorMacro", "Macro",
- "KeyingSetInfo", "UnknownType",
- # window classes
- "Window",
- ]
-
- # ---------------------------------------------------------------------
- # Collect internal operators
-
- # extend with all internal operators
- # note that this uses internal api introspection functions
- # 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__())
-
- get_instance = __import__("_bpy").ops.get_instance
- path_resolve = type(bpy.context).__base__.path_resolve
- for idname in op_ids:
- op = get_instance(idname)
- # XXX Do not skip INTERNAL's anymore, some of those ops show up in UI now!
-# if 'INTERNAL' in path_resolve(op, "bl_options"):
-# blacklist_rna_class.append(idname)
-
- # ---------------------------------------------------------------------
- # Collect builtin classes we don't need to doc
- blacklist_rna_class.append("Property")
- blacklist_rna_class.extend([cls.__name__ for cls in bpy.types.Property.__subclasses__()])
-
- # ---------------------------------------------------------------------
- # Collect classes which are attached to collections, these are api
- # access only.
- collection_props = set()
- for cls_id in dir(bpy.types):
- cls = getattr(bpy.types, cls_id)
- for prop in cls.bl_rna.properties:
- if prop.type == 'COLLECTION':
- prop_cls = prop.srna
- if prop_cls is not None:
- collection_props.add(prop_cls.identifier)
- blacklist_rna_class.extend(sorted(collection_props))
-
- return blacklist_rna_class
-
- blacklist_rna_class = classBlackList()
-
- def filterRNA(bl_rna):
- rid = bl_rna.identifier
- if rid in blacklist_rna_class:
- print(" skipping", rid)
- return True
- return False
-
- check_ctxt_rna = check_ctxt_rna_tip = None
- if check_ctxt:
- check_ctxt_rna = {"multi_lines": check_ctxt.get("multi_lines"),
- "not_capitalized": check_ctxt.get("not_capitalized"),
- "end_point": check_ctxt.get("end_point"),
- "undoc_ops": check_ctxt.get("undoc_ops")}
- check_ctxt_rna_tip = check_ctxt_rna
- check_ctxt_rna_tip["multi_rnatip"] = check_ctxt.get("multi_rnatip")
-
- # -------------------------------------------------------------------------
- # Function definitions
-
- def walkProperties(bl_rna):
- import bpy
-
- # Get our parents' properties, to not export them multiple times.
- bl_rna_base = bl_rna.base
- if bl_rna_base:
- bl_rna_base_props = bl_rna_base.properties.values()
- else:
- bl_rna_base_props = ()
-
- for prop in bl_rna.properties:
- # Only write this property if our parent hasn't got it.
- if prop in bl_rna_base_props:
- continue
- if prop.identifier == "rna_type":
- continue
-
- msgsrc = "bpy.types.{}.{}".format(bl_rna.identifier, prop.identifier)
- context = getattr(prop, "translation_context", CONTEXT_DEFAULT)
- if prop.name and (prop.name != prop.identifier or context):
- key = (context, prop.name)
- check(check_ctxt_rna, messages, key, msgsrc)
- messages.setdefault(key, []).append(msgsrc)
- if prop.description:
- key = (CONTEXT_DEFAULT, prop.description)
- check(check_ctxt_rna_tip, messages, key, msgsrc)
- messages.setdefault(key, []).append(msgsrc)
- if isinstance(prop, bpy.types.EnumProperty):
- for item in prop.enum_items:
- msgsrc = "bpy.types.{}.{}:'{}'".format(bl_rna.identifier,
- prop.identifier,
- item.identifier)
- if item.name and item.name != item.identifier:
- key = (CONTEXT_DEFAULT, item.name)
- check(check_ctxt_rna, messages, key, msgsrc)
- messages.setdefault(key, []).append(msgsrc)
- if item.description:
- key = (CONTEXT_DEFAULT, item.description)
- check(check_ctxt_rna_tip, messages, key, msgsrc)
- messages.setdefault(key, []).append(msgsrc)
-
- def walkRNA(bl_rna):
- if filterRNA(bl_rna):
- return
-
- msgsrc = ".".join(("bpy.types", bl_rna.identifier))
- context = getattr(bl_rna, "translation_context", CONTEXT_DEFAULT)
-
- if bl_rna.name and (bl_rna.name != bl_rna.identifier or context):
- key = (context, bl_rna.name)
- check(check_ctxt_rna, messages, key, msgsrc)
- messages.setdefault(key, []).append(msgsrc)
-
- if bl_rna.description:
- key = (CONTEXT_DEFAULT, bl_rna.description)
- check(check_ctxt_rna_tip, messages, key, msgsrc)
- messages.setdefault(key, []).append(msgsrc)
-
- if hasattr(bl_rna, 'bl_label') and bl_rna.bl_label:
- key = (context, bl_rna.bl_label)
- check(check_ctxt_rna, messages, key, msgsrc)
- messages.setdefault(key, []).append(msgsrc)
-
- walkProperties(bl_rna)
-
- def walkClass(cls):
- walkRNA(cls.bl_rna)
-
- def walk_keymap_hierarchy(hier, msgsrc_prev):
- for lvl in hier:
- msgsrc = "{}.{}".format(msgsrc_prev, lvl[1])
- messages.setdefault((CONTEXT_DEFAULT, lvl[0]), []).append(msgsrc)
-
- if lvl[3]:
- walk_keymap_hierarchy(lvl[3], msgsrc)
-
- # -------------------------------------------------------------------------
- # Dump Messages
-
- def process_cls_list(cls_list):
- if not cls_list:
- return 0
-
- def full_class_id(cls):
- """ gives us 'ID.Lamp.AreaLamp' which is best for sorting.
- """
- cls_id = ""
- bl_rna = cls.bl_rna
- while bl_rna:
- cls_id = "{}.{}".format(bl_rna.identifier, cls_id)
- bl_rna = bl_rna.base
- return cls_id
-
- cls_list.sort(key=full_class_id)
- processed = 0
- for cls in cls_list:
- # XXX translation_context of Operator sub-classes are not "good"!
- # So ignore those Operator sub-classes (anyway, will get the same from OperatorProperties
- # sub-classes!)...
- if issubclass(cls, bpy.types.Operator):
- continue
-
- walkClass(cls)
-# classes.add(cls)
- # Recursively process subclasses.
- processed += process_cls_list(cls.__subclasses__()) + 1
- return processed
-
- # Parse everything (recursively parsing from bpy_struct "class"...).
- processed = process_cls_list(type(bpy.context).__base__.__subclasses__())
- print("{} classes processed!".format(processed))
-# import pickle
-# global classes
-# classes = {str(c) for c in classes}
-# with open("/home/i7deb64/Bureau/tpck_2", "wb") as f:
-# pickle.dump(classes, f, protocol=0)
-
- from bpy_extras.keyconfig_utils import KM_HIERARCHY
-
- walk_keymap_hierarchy(KM_HIERARCHY, "KM_HIERARCHY")
-
-
-def dump_messages_pytext(messages, check_ctxt):
- """ dumps text inlined in the python user interface: eg.
-
- layout.prop("someprop", text="My Name")
- """
- import ast
-
- # -------------------------------------------------------------------------
- # Gather function names
-
- import bpy
- # key: func_id
- # val: [(arg_kw, arg_pos), (arg_kw, arg_pos), ...]
- func_translate_args = {}
-
- # so far only 'text' keywords, but we may want others translated later
- translate_kw = ("text", )
-
- # 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, }
-
- for func_id, func in bpy.types.UILayout.bl_rna.functions.items():
- # check it has a 'text' argument
- for (arg_pos, (arg_kw, arg)) in enumerate(func.parameters.items()):
- if ((arg_kw in translate_kw) and
- (arg.is_output is False) and
- (arg.type == 'STRING')):
-
- func_translate_args.setdefault(func_id, []).append((arg_kw,
- arg_pos))
- # print(func_translate_args)
-
- check_ctxt_py = None
- if check_ctxt:
- check_ctxt_py = {"py_in_rna": (check_ctxt["py_in_rna"], messages.copy()),
- "multi_lines": check_ctxt["multi_lines"],
- "not_capitalized": check_ctxt["not_capitalized"],
- "end_point": check_ctxt["end_point"]}
-
- # -------------------------------------------------------------------------
- # Function definitions
-
- def extract_strings(fp_rel, node):
- """ Recursively get strings, needed in case we have "Blah" + "Blah",
- passed as an argument in that case it wont evaluate to a string.
- However, break on some kind of stopper nodes, like e.g. Subscript.
- """
-
- if type(node) == ast.Str:
- eval_str = ast.literal_eval(node)
- if eval_str:
- key = (CONTEXT_DEFAULT, eval_str)
- msgsrc = "{}:{}".format(fp_rel, node.lineno)
- check(check_ctxt_py, messages, key, msgsrc)
- messages.setdefault(key, []).append(msgsrc)
- return
-
- for nd in ast.iter_child_nodes(node):
- if type(nd) not in stopper_nodes:
- extract_strings(fp_rel, nd)
-
- def extract_strings_from_file(fp):
- filedata = open(fp, 'r', encoding="utf8")
- root_node = ast.parse(filedata.read(), fp, 'exec')
- filedata.close()
-
- fp_rel = os.path.relpath(fp, SOURCE_DIR)
-
- for node in ast.walk(root_node):
- if type(node) == ast.Call:
- # print("found function at")
- # print("%s:%d" % (fp, node.lineno))
-
- # lambda's
- if type(node.func) == ast.Name:
- continue
-
- # getattr(self, con.type)(context, box, con)
- if not hasattr(node.func, "attr"):
- continue
-
- translate_args = func_translate_args.get(node.func.attr, ())
-
- # do nothing if not found
- for arg_kw, arg_pos in translate_args:
- if arg_pos < len(node.args):
- extract_strings(fp_rel, node.args[arg_pos])
- else:
- for kw in node.keywords:
- if kw.arg == arg_kw:
- extract_strings(fp_rel, kw.value)
-
- # -------------------------------------------------------------------------
- # Dump Messages
-
- mod_dir = os.path.join(SOURCE_DIR,
- "release",
- "scripts",
- "startup",
- "bl_ui")
-
- files = [os.path.join(mod_dir, fn)
- for fn in sorted(os.listdir(mod_dir))
- if not fn.startswith("_")
- if fn.endswith("py")
- ]
-
- # Dummy Cycles has its py addon in its own dir!
- files += CUSTOM_PY_UI_FILES
-
- for fp in files:
- extract_strings_from_file(fp)
-
-
-def dump_messages(do_messages, do_checks):
- import collections
- import re
-
- def enable_addons():
- """For now, enable all official addons, before extracting msgids."""
- import addon_utils
- import bpy
-
- userpref = bpy.context.user_preferences
- used_ext = {ext.module for ext in userpref.addons}
- support = {"OFFICIAL"}
- # collect the categories that can be filtered on
- addons = [(mod, addon_utils.module_bl_info(mod)) for mod in
- addon_utils.modules(addon_utils.addons_fake_modules)]
-
- for mod, info in addons:
- module_name = mod.__name__
- if module_name in used_ext or info["support"] not in support:
- continue
- print(" Enabling module ", module_name)
- bpy.ops.wm.addon_enable(module=module_name)
-
- # XXX There are currently some problems with bpy/rna...
- # *Very* tricky to solve!
- # So this is a hack to make all newly added operator visible by
- # bpy.types.OperatorProperties.__subclasses__()
- for cat in dir(bpy.ops):
- cat = getattr(bpy.ops, cat)
- for op in dir(cat):
- getattr(cat, op).get_rna()
-
- # check for strings like ": %d"
- ignore_reg = re.compile(r"^(?:[-*.()/\\+:%xWXYZ0-9]|%d|%f|%s|%r|\s)*$")
- filter_message = ignore_reg.match
-
- messages = getattr(collections, 'OrderedDict', dict)()
-
- messages[(CONTEXT_DEFAULT, "")] = []
-
- # Enable all wanted addons.
- enable_addons()
-
- check_ctxt = None
- if do_checks:
- check_ctxt = {"multi_rnatip": set(),
- "multi_lines": set(),
- "py_in_rna": set(),
- "not_capitalized": set(),
- "end_point": set(),
- "undoc_ops": set()}
-
- # get strings from RNA
- dump_messages_rna(messages, check_ctxt)
-
- # get strings from UI layout definitions text="..." args
- dump_messages_pytext(messages, check_ctxt)
-
- del messages[(CONTEXT_DEFAULT, "")]
-
- if do_checks:
- print("WARNINGS:")
- keys = set()
- for c in check_ctxt.values():
- keys |= c
- # XXX Temp, see below
- keys -= check_ctxt["multi_rnatip"]
- for key in keys:
- if key in check_ctxt["undoc_ops"]:
- print("\tThe following operators are undocumented:")
- else:
- print("\t“{}â€|“{}â€:".format(*key))
- if key in check_ctxt["multi_lines"]:
- print("\t\t-> newline in this message!")
- if key in check_ctxt["not_capitalized"]:
- print("\t\t-> message not capitalized!")
- if key in check_ctxt["end_point"]:
- print("\t\t-> message with endpoint!")
- # XXX Hide this one for now, too much false positives.
-# if key in check_ctxt["multi_rnatip"]:
-# print("\t\t-> tip used in several RNA items")
- if key in check_ctxt["py_in_rna"]:
- print("\t\t-> RNA message also used in py UI code:")
- print("\t\t{}".format("\n\t\t".join(messages[key])))
-
- if do_messages:
- print("Writing messages…")
- num_written = 0
- num_filtered = 0
- with open(FILE_NAME_MESSAGES, 'w', encoding="utf8") as message_file:
- for (ctx, key), value in messages.items():
- # filter out junk values
- if filter_message(key):
- num_filtered += 1
- continue
-
- # Remove newlines in key and values!
- message_file.write("\n".join(COMMENT_PREFIX + msgsrc.replace("\n", "") for msgsrc in value))
- message_file.write("\n")
- if ctx:
- message_file.write(CONTEXT_PREFIX + ctx.replace("\n", "") + "\n")
- message_file.write(key.replace("\n", "") + "\n")
- num_written += 1
-
- print("Written {} messages to: {} ({} were filtered out)."
- "".format(num_written, FILE_NAME_MESSAGES, num_filtered))
-
-
-def main():
- try:
- import bpy
- except ImportError:
- print("This script must run from inside blender")
- return
-
- import sys
- back_argv = sys.argv
- # Get rid of Blender args!
- sys.argv = sys.argv[sys.argv.index("--") + 1:]
-
- 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', help="Output messages file path.")
- args = parser.parse_args()
-
- if args.output:
- global FILE_NAME_MESSAGES
- FILE_NAME_MESSAGES = args.output
-
- dump_messages(do_messages=args.no_messages, do_checks=args.no_checks)
-
- sys.argv = back_argv
-
-
-if __name__ == "__main__":
- print("\n\n *** Running {} *** \n".format(__file__))
- main()
diff --git a/release/scripts/modules/bl_i18n_utils/check_po.py b/release/scripts/modules/bl_i18n_utils/check_po.py
deleted file mode 100755
index 2e82047bb95..00000000000
--- a/release/scripts/modules/bl_i18n_utils/check_po.py
+++ /dev/null
@@ -1,177 +0,0 @@
-#!/usr/bin/python3
-
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public 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>
-
-# Check po’s in branches (or in trunk) for missing/unneeded messages.
-
-import os
-import sys
-from codecs import open
-
-try:
- import settings
- import utils
-except:
- from . import (settings, utils)
-
-TRUNK_PO_DIR = settings.TRUNK_PO_DIR
-BRANCHES_DIR = settings.BRANCHES_DIR
-
-FILE_NAME_POT = settings.FILE_NAME_POT
-
-
-def print_diff(ref_messages, messages, states):
- # Remove comments from messages list!
- messages = set(messages.keys()) - states["comm_msg"]
- unneeded = (messages - ref_messages)
- for msgid in unneeded:
- print('\tUnneeded message id "{}"'.format(msgid))
-
- missing = (ref_messages - messages)
- for msgid in missing:
- print('\tMissing message id "{}"'.format(msgid))
-
- for msgid in states["comm_msg"]:
- print('\tCommented message id "{}"'.format(msgid))
-
- print("\t{} unneeded messages, {} missing messages, {} commented messages." \
- "".format(len(unneeded), len(missing), len(states["comm_msg"])))
- return 0
-
-
-def process_po(ref_messages, po, glob_stats, do_stats, do_messages):
- print("Checking {}...".format(po))
- ret = 0
-
- messages, states, stats = utils.parse_messages(po)
- if do_messages:
- t = print_diff(ref_messages, messages, states)
- if t:
- ret = t
- if do_stats:
- print("\tStats:")
- t = utils.print_stats(stats, glob_stats, prefix=" ")
- if t:
- ret = t
- if states["is_broken"]:
- print("\tERROR! This .po is broken!")
- ret = 1
- return ret
-
-
-def main():
- import argparse
- parser = argparse.ArgumentParser(description="Check po’s in branches " \
- "(or in trunk) for missing" \
- "/unneeded messages.")
- parser.add_argument('-s', '--stats', action="store_true",
- help="Print po’s stats.")
- parser.add_argument('-m', '--messages', action="store_true",
- help="Print po’s missing/unneeded/commented messages.")
- parser.add_argument('-t', '--trunk', action="store_true",
- help="Check po’s in /trunk/po rather than /branches.")
- parser.add_argument('-p', '--pot',
- help="Specify the .pot file used as reference.")
- parser.add_argument('langs', metavar='ISO_code', nargs='*',
- help="Restrict processed languages to those.")
- args = parser.parse_args()
-
- if args.pot:
- global FILE_NAME_POT
- FILE_NAME_POT = args.pot
- glob_stats = {"nbr" : 0.0,
- "lvl" : 0.0,
- "lvl_ttips" : 0.0,
- "lvl_trans_ttips" : 0.0,
- "lvl_ttips_in_trans": 0.0,
- "lvl_comm" : 0.0,
- "nbr_signs" : 0,
- "nbr_trans_signs" : 0,
- "contexts" : set()}
- ret = 0
-
- pot_messages = None
- if args.messages:
- pot_messages, u1, pot_stats = utils.parse_messages(FILE_NAME_POT)
- pot_messages = set(pot_messages.keys())
- glob_stats["nbr_signs"] = pot_stats["nbr_signs"]
-
- if args.langs:
- for lang in args.langs:
- if args.trunk:
- po = os.path.join(TRUNK_PO_DIR, ".".join((lang, "po")))
- else:
- po = os.path.join(BRANCHES_DIR, lang, ".".join((lang, "po")))
- if os.path.exists(po):
- t = process_po(pot_messages, po, glob_stats,
- args.stats, args.messages)
- if t:
- ret = t
- elif args.trunk:
- for po in os.listdir(TRUNK_PO_DIR):
- if po.endswith(".po"):
- po = os.path.join(TRUNK_PO_DIR, po)
- t = process_po(pot_messages, po, glob_stats,
- args.stats, args.messages)
- if t:
- ret = t
- else:
- for lang in os.listdir(BRANCHES_DIR):
- for po in os.listdir(os.path.join(BRANCHES_DIR, lang)):
- if po.endswith(".po"):
- po = os.path.join(BRANCHES_DIR, lang, po)
- t = process_po(pot_messages, po, glob_stats,
- args.stats, args.messages)
- if t:
- ret = t
-
- if args.stats and glob_stats["nbr"] != 0.0:
- nbr_contexts = len(glob_stats["contexts"] - {""})
- if nbr_contexts != 1:
- if nbr_contexts == 0:
- nbr_contexts = "No"
- _ctx_txt = "s are"
- else:
- _ctx_txt = " is"
- print("\nAverage stats for all {:.0f} processed files:\n"
- " {:>6.1%} done!\n"
- " {:>6.1%} of messages are tooltips.\n"
- " {:>6.1%} of tooltips are translated.\n"
- " {:>6.1%} of translated messages are tooltips.\n"
- " {:>6.1%} of messages are commented.\n"
- " The org msgids are currently made of {} signs.\n"
- " All processed translations are currently made of {} signs.\n"
- " {} specific context{} present:\n {}\n"
- "".format(glob_stats["nbr"], glob_stats["lvl"] / glob_stats["nbr"],
- glob_stats["lvl_ttips"] / glob_stats["nbr"],
- glob_stats["lvl_trans_ttips"] / glob_stats["nbr"],
- glob_stats["lvl_ttips_in_trans"] / glob_stats["nbr"],
- glob_stats["lvl_comm"] / glob_stats["nbr"], glob_stats["nbr_signs"],
- glob_stats["nbr_trans_signs"], nbr_contexts, _ctx_txt,
- "\n ".join(glob_stats["contexts"]-{""})))
-
- return ret
-
-
-if __name__ == "__main__":
- print("\n\n *** Running {} *** \n".format(__file__))
- print(" *** WARNING! Number of tooltips is only an estimation! ***\n")
- sys.exit(main())
diff --git a/release/scripts/modules/bl_i18n_utils/clean_po.py b/release/scripts/modules/bl_i18n_utils/clean_po.py
deleted file mode 100755
index 2924ad9fb74..00000000000
--- a/release/scripts/modules/bl_i18n_utils/clean_po.py
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/python3
-
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public 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>
-
-# Clean (i.e. remove commented messages) po’s in branches or trunk.
-
-import os
-import sys
-import collections
-
-try:
- import settings
- import utils
-except:
- from . import (settings, utils)
-
-
-TRUNK_PO_DIR = settings.TRUNK_PO_DIR
-BRANCHES_DIR = settings.BRANCHES_DIR
-
-
-def do_clean(po, strict):
- print("Cleaning {}...".format(po))
- messages, states, u1 = utils.parse_messages(po)
-
- if strict and states["is_broken"]:
- print("ERROR! This .po file is broken!")
- return 1
-
- for msgkey in states["comm_msg"]:
- del messages[msgkey]
- utils.write_messages(po, messages, states["comm_msg"], states["fuzzy_msg"])
- print("Removed {} commented messages.".format(len(states["comm_msg"])))
- return 0
-
-
-def main():
- import argparse
- parser = argparse.ArgumentParser(description="Clean po’s in branches " \
- "or trunk (i.e. remove " \
- "all commented messages).")
- parser.add_argument('-t', '--trunk', action="store_true",
- help="Clean po’s in trunk rather than branches.")
- parser.add_argument('-s', '--strict', action="store_true",
- help="Raise an error if a po is broken.")
- parser.add_argument('langs', metavar='ISO_code', nargs='*',
- help="Restrict processed languages to those.")
- args = parser.parse_args()
-
- ret = 0
-
- if args.langs:
- for lang in args.langs:
- if args.trunk:
- po = os.path.join(TRUNK_PO_DIR, ".".join((lang, "po")))
- else:
- po = os.path.join(BRANCHES_DIR, lang, ".".join((lang, "po")))
- if os.path.exists(po):
- t = do_clean(po, args.strict)
- if t:
- ret = t
- elif args.trunk:
- for po in os.listdir(TRUNK_PO_DIR):
- if po.endswith(".po"):
- po = os.path.join(TRUNK_PO_DIR, po)
- t = do_clean(po, args.strict)
- if t:
- ret = t
- else:
- for lang in os.listdir(BRANCHES_DIR):
- for po in os.listdir(os.path.join(BRANCHES_DIR, lang)):
- if po.endswith(".po"):
- po = os.path.join(BRANCHES_DIR, lang, po)
- t = do_clean(po, args.strict)
- if t:
- ret = t
-
-
-if __name__ == "__main__":
- print("\n\n *** Running {} *** \n".format(__file__))
- sys.exit(main())
diff --git a/release/scripts/modules/bl_i18n_utils/import_po_from_branches.py b/release/scripts/modules/bl_i18n_utils/import_po_from_branches.py
deleted file mode 100755
index 533dded3c57..00000000000
--- a/release/scripts/modules/bl_i18n_utils/import_po_from_branches.py
+++ /dev/null
@@ -1,123 +0,0 @@
-#!/usr/bin/python3
-
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public 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 in trunk/po all po from branches translated above the given threshold.
-
-import os
-import shutil
-import sys
-import subprocess
-from codecs import open
-
-try:
- import settings
- import utils
- import rtl_preprocess
-except:
- from . import (settings, utils, rtl_preprocess)
-
-
-TRUNK_PO_DIR = settings.TRUNK_PO_DIR
-BRANCHES_DIR = settings.BRANCHES_DIR
-
-IMPORT_LANGUAGES_SKIP = settings.IMPORT_LANGUAGES_SKIP
-
-RTL_PREPROCESS_FILE = settings.RTL_PREPROCESS_FILE
-
-PY3 = settings.PYTHON3_EXEC
-
-
-def main():
- import argparse
- parser = argparse.ArgumentParser(description="Import advanced enough po’s " \
- "from branches to trunk.")
- parser.add_argument('-t', '--threshold', type=int,
- help="Import threshold, as a percentage.")
- parser.add_argument('-s', '--strict', action="store_true",
- help="Raise an error if a po is broken.")
- parser.add_argument('langs', metavar='ISO_code', nargs='*',
- help="Restrict processed languages to those.")
- args = parser.parse_args()
-
- ret = 0
-
- threshold = float(settings.IMPORT_MIN_LEVEL) / 100.0
- if args.threshold is not None:
- threshold = float(args.threshold) / 100.0
-
- for lang in os.listdir(BRANCHES_DIR):
- if (args.langs and lang not in args.langs) or lang in IMPORT_LANGUAGES_SKIP:
- continue
- po = os.path.join(BRANCHES_DIR, lang, ".".join((lang, "po")))
- if os.path.exists(po):
- po_is_rtl = os.path.join(BRANCHES_DIR, lang, RTL_PREPROCESS_FILE)
- msgs, state, stats = utils.parse_messages(po)
- tot_msgs = stats["tot_msg"]
- trans_msgs = stats["trans_msg"]
- lvl = 0.0
- if tot_msgs:
- lvl = float(trans_msgs) / float(tot_msgs)
- if lvl > threshold:
- if state["is_broken"] and args.strict:
- print("{:<10}: {:>6.1%} done, but BROKEN, skipped." \
- "".format(lang, lvl))
- ret = 1
- else:
- if os.path.exists(po_is_rtl):
- out_po = os.path.join(TRUNK_PO_DIR,
- ".".join((lang, "po")))
- out_raw_po = os.path.join(TRUNK_PO_DIR,
- "_".join((lang, "raw.po")))
- keys = []
- trans = []
- for k, m in msgs.items():
- keys.append(k)
- trans.append("".join(m["msgstr_lines"]))
- trans = rtl_preprocess.log2vis(trans)
- for k, t in zip(keys, trans):
- # Mono-line for now...
- msgs[k]["msgstr_lines"] = [t]
- utils.write_messages(out_po, msgs, state["comm_msg"],
- state["fuzzy_msg"])
- # Also copies org po!
- shutil.copy(po, out_raw_po)
- print("{:<10}: {:>6.1%} done, enough translated " \
- "messages, processed and copied to trunk." \
- "".format(lang, lvl))
- else:
- shutil.copy(po, TRUNK_PO_DIR)
- print("{:<10}: {:>6.1%} done, enough translated " \
- "messages, copied to trunk.".format(lang, lvl))
- else:
- if state["is_broken"] and args.strict:
- print("{:<10}: {:>6.1%} done, BROKEN and not enough " \
- "translated messages, skipped".format(lang, lvl))
- ret = 1
- else:
- print("{:<10}: {:>6.1%} done, not enough translated " \
- "messages, skipped.".format(lang, lvl))
- return ret
-
-
-if __name__ == "__main__":
- print("\n\n *** Running {} *** \n".format(__file__))
- sys.exit(main())
diff --git a/release/scripts/modules/bl_i18n_utils/merge_po.py b/release/scripts/modules/bl_i18n_utils/merge_po.py
index baf67de2e81..610be0f15bd 100755
--- a/release/scripts/modules/bl_i18n_utils/merge_po.py
+++ b/release/scripts/modules/bl_i18n_utils/merge_po.py
@@ -37,26 +37,22 @@ except:
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="" \
- "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" \
- "The fuzzy flag is removed if necessary.\n" \
- "All other comments are never modified.\n" \
- "Commented messages in dst will always remain " \
- "commented, and commented messages are never merged " \
+ 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"
+ "The fuzzy flag is removed if necessary.\n"
+ "All other comments are never modified.\n"
+ "Commented messages in dst will always remain commented, and commented messages are never merged "
"from sources.")
- parser.add_argument('-s', '--stats', action="store_true",
- help="Show statistics info.")
+ parser.add_argument('-s', '--stats', action="store_true", help="Show statistics info.")
parser.add_argument('-r', '--replace', action="store_true",
help="Replace existing messages of same \"level\" already in dest po.")
- parser.add_argument('dst', metavar='dst.po',
- help="The dest po into which merge the others.")
- parser.add_argument('src', metavar='src.po', nargs='+',
- help="The po's to merge into the dst.po one.")
+ parser.add_argument('dst', metavar='dst.po', help="The dest po into which merge the others.")
+ parser.add_argument('src', metavar='src.po', nargs='+', help="The po's to merge into the dst.po one.")
args = parser.parse_args()
ret = 0
@@ -67,89 +63,78 @@ def main():
nbr_added = 0
nbr_unfuzzied = 0
- dst_messages, dst_states, dst_stats = utils.parse_messages(args.dst)
- if dst_states["is_broken"]:
+ dst_msgs = utils.I18nMessages(kind='PO', src=args.dst)
+ if dst_msgs.parsing_errors:
print("Dest po is BROKEN, aborting.")
return 1
if args.stats:
print("Dest po, before merging:")
- utils.print_stats(dst_stats, prefix="\t")
- # If we don’t want to replace existing valid translations, pre-populate
- # done_msgkeys and done_fuzzy_msgkeys.
+ dst_msgs.print_stats(prefix="\t")
+ # If we don’t want to replace existing valid translations, pre-populate done_msgkeys and done_fuzzy_msgkeys.
if not args.replace:
- done_msgkeys = dst_states["trans_msg"].copy()
- done_fuzzy_msgkeys = dst_states["fuzzy_msg"].copy()
+ done_msgkeys = dst_msgs.trans_msgs.copy()
+ done_fuzzy_msgkeys = dst_msgs.fuzzy_msgs.copy()
for po in args.src:
- messages, states, stats = utils.parse_messages(po)
- if states["is_broken"]:
+ msgs = utils.I18nMessages(kind='PO', src=po)
+ if msgs.parsing_errors:
print("\tSrc po {} is BROKEN, skipping.".format(po))
ret = 1
continue
print("\tMerging {}...".format(po))
if args.stats:
print("\t\tMerged po stats:")
- utils.print_stats(stats, prefix="\t\t\t")
- for msgkey, val in messages.items():
+ msgs.print_stats(prefix="\t\t\t")
+ for msgkey, msg in msgs.msgs.items():
msgctxt, msgid = msgkey
# This msgkey has already been completely merged, or is a commented one,
# or the new message is commented, skip it.
- if msgkey in (done_msgkeys | dst_states["comm_msg"] | states["comm_msg"]):
+ if msgkey in (done_msgkeys | dst_msgs.comm_msgs | msgs.comm_msgs):
continue
- is_ttip = utils.is_tooltip(msgid)
+ is_ttip = msg.is_tooltip
# New messages does not yet exists in dest.
- if msgkey not in dst_messages:
- dst_messages[msgkey] = messages[msgkey]
- if msgkey in states["fuzzy_msg"]:
+ if msgkey not in dst_msgs.msgs:
+ dst_msgs[msgkey] = msgs.msgs[msgkey]
+ if msgkey in msgs.fuzzy_msgs:
done_fuzzy_msgkeys.add(msgkey)
- dst_states["fuzzy_msg"].add(msgkey)
- elif msgkey in states["trans_msg"]:
+ dst_msgs.fuzzy_msgs.add(msgkey)
+ elif msgkey in msgs.trans_msgs:
done_msgkeys.add(msgkey)
- dst_states["trans_msg"].add(msgkey)
- dst_stats["trans_msg"] += 1
- if is_ttip:
- dst_stats["trans_ttips"] += 1
+ dst_msgs.trans_msgs.add(msgkey)
nbr_added += 1
- dst_stats["tot_msg"] += 1
- if is_ttip:
- dst_stats["tot_ttips"] += 1
# From now on, the new messages is already in dst.
# New message is neither translated nor fuzzy, skip it.
- elif msgkey not in (states["trans_msg"] | states["fuzzy_msg"]):
+ elif msgkey not in (msgs.trans_msgs | msgs.fuzzy_msgs):
continue
# From now on, the new message is either translated or fuzzy!
# The new message is translated.
- elif msgkey in states["trans_msg"]:
- dst_messages[msgkey]["msgstr_lines"] = messages[msgkey]["msgstr_lines"]
+ elif msgkey in msgs.trans_msgs:
+ dst_msgs.msgs[msgkey].msgstr = msg.msgstr
done_msgkeys.add(msgkey)
done_fuzzy_msgkeys.discard(msgkey)
- if msgkey in dst_states["fuzzy_msg"]:
- dst_states["fuzzy_msg"].remove(msgkey)
+ if msgkey in dst_msgs.fuzzy_msgs:
+ dst_msgs.fuzzy_msgs.remove(msgkey)
nbr_unfuzzied += 1
- if msgkey not in dst_states["trans_msg"]:
- dst_states["trans_msg"].add(msgkey)
- dst_stats["trans_msg"] += 1
- if is_ttip:
- dst_stats["trans_ttips"] += 1
+ if msgkey not in dst_msgs.trans_msgs:
+ dst_msgs.trans_msgs.add(msgkey)
else:
nbr_replaced += 1
nbr_merged += 1
- # The new message is fuzzy, org one is fuzzy too,
- # and this msgkey has not yet been merged.
- elif msgkey not in (dst_states["trans_msg"] | done_fuzzy_msgkeys):
- dst_messages[msgkey]["msgstr_lines"] = messages[msgkey]["msgstr_lines"]
+ # The new message is fuzzy, org one is fuzzy too, and this msgkey has not yet been merged.
+ elif msgkey not in (dst_msgs.trans_msgs | done_fuzzy_msgkeys):
+ dst_msgs[msgkey].msgstr = msg.msgstr
done_fuzzy_msgkeys.add(msgkey)
- dst_states["fuzzy_msg"].add(msgkey)
+ dst_msgs.fuzzy_msgs.add(msgkey)
nbr_merged += 1
nbr_replaced += 1
- utils.write_messages(args.dst, dst_messages, dst_states["comm_msg"], dst_states["fuzzy_msg"])
+ dst_msgs.write(kind='PO', dest=args.dst)
- print("Merged completed. {} messages were merged (among which {} were replaced), " \
- "{} were added, {} were \"un-fuzzied\"." \
- "".format(nbr_merged, nbr_replaced, nbr_added, nbr_unfuzzied))
+ print("Merged completed. {} messages were merged (among which {} were replaced), {} were added, "
+ "{} were \"un-fuzzied\".".format(nbr_merged, nbr_replaced, nbr_added, nbr_unfuzzied))
if args.stats:
+ dst_msgs.update_info()
print("Final merged po stats:")
- utils.print_stats(dst_stats, prefix="\t")
+ dst_msgs.print_stats(prefix="\t")
return ret
diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py
index c7414e84046..fbfca8f639d 100644
--- a/release/scripts/modules/bl_i18n_utils/settings.py
+++ b/release/scripts/modules/bl_i18n_utils/settings.py
@@ -24,8 +24,12 @@
# XXX This is a template, most values should be OK, but some you’ll have to
# edit (most probably, BLENDER_EXEC and SOURCE_DIR).
-import os.path
+import json
+import os
+import sys
+
+import bpy
###############################################################################
# MISC
@@ -80,29 +84,94 @@ LANGUAGES = (
(34, "Estonian (Eestlane)", "et_EE"),
(35, "Esperanto (Esperanto)", "eo"),
(36, "Spanish from Spain (Español de España)", "es_ES"),
+ (37, "Amharic (አማርኛ)", "am_ET"),
+ (38, "Uzbek (Oʻzbek)", "uz_UZ"),
+ (39, "Uzbek Cyrillic (Ўзбек)", "uz_UZ@cyrillic"),
+ (40, "Hindi (मानक हिनà¥à¤¦à¥€)", "hi_IN"),
)
+# Default context, in py!
+DEFAULT_CONTEXT = bpy.app.translations.contexts.default
+
# Name of language file used by Blender to generate translations' menu.
LANGUAGES_FILE = "languages"
-# The min level of completeness for a po file to be imported from /branches
-# into /trunk, as a percentage. -1 means "import everything".
-IMPORT_MIN_LEVEL = -1
+# The min level of completeness for a po file to be imported from /branches into /trunk, as a percentage.
+IMPORT_MIN_LEVEL = 0.0
# Languages in /branches we do not want to import in /trunk currently...
-IMPORT_LANGUAGES_SKIP = {'bg', 'ca', 'fi', 'el', 'ko', 'ne', 'pl', 'ro'}
+IMPORT_LANGUAGES_SKIP = {
+ 'am_ET', 'bg_BG', 'fi_FI', 'el_GR', 'et_EE', 'ne_NP', 'nl_NL', 'pl_PL', 'ro_RO', 'uz_UZ', 'uz_UZ@cyrillic',
+}
+
+# Languages that need RTL pre-processing.
+IMPORT_LANGUAGES_RTL = {
+ 'ar_EG', 'fa_IR', 'he_IL',
+}
# The comment prefix used in generated messages.txt file.
-COMMENT_PREFIX = "#~ "
+MSG_COMMENT_PREFIX = "#~ "
+
+# The comment prefix used in generated messages.txt file.
+MSG_CONTEXT_PREFIX = "MSGCTXT:"
+
+# The default comment prefix used in po's.
+PO_COMMENT_PREFIX= "# "
# The comment prefix used to mark sources of msgids, in po's.
-COMMENT_PREFIX_SOURCE = "#: "
+PO_COMMENT_PREFIX_SOURCE = "#: "
-# The comment prefix used in generated messages.txt file.
-CONTEXT_PREFIX = "MSGCTXT:"
+# The comment prefix used to mark sources of msgids, in po's.
+PO_COMMENT_PREFIX_SOURCE_CUSTOM = "#. :src: "
+
+# The general "generated" comment prefix, in po's.
+PO_COMMENT_PREFIX_GENERATED = "#. "
+
+# The comment prefix used to comment entries in po's.
+PO_COMMENT_PREFIX_MSG= "#~ "
+
+# The comment prefix used to mark fuzzy msgids, in po's.
+PO_COMMENT_FUZZY = "#, fuzzy"
+
+# The prefix used to define context, in po's.
+PO_MSGCTXT = "msgctxt "
+
+# The prefix used to define msgid, in po's.
+PO_MSGID = "msgid "
+
+# The prefix used to define msgstr, in po's.
+PO_MSGSTR = "msgstr "
+
+# The 'header' key of po files.
+PO_HEADER_KEY = (DEFAULT_CONTEXT, "")
+
+PO_HEADER_MSGSTR = (
+ "Project-Id-Version: {blender_ver} (r{blender_rev})\\n\n"
+ "Report-Msgid-Bugs-To: \\n\n"
+ "POT-Creation-Date: {time}\\n\n"
+ "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\n"
+ "Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n\n"
+ "Language-Team: LANGUAGE <LL@li.org>\\n\n"
+ "Language: {uid}\\n\n"
+ "MIME-Version: 1.0\\n\n"
+ "Content-Type: text/plain; charset=UTF-8\\n\n"
+ "Content-Transfer-Encoding: 8bit\n"
+)
+PO_HEADER_COMMENT_COPYRIGHT = (
+ "# Blender's translation file (po format).\n"
+ "# Copyright (C) {year} The Blender Foundation.\n"
+ "# This file is distributed under the same license as the Blender package.\n"
+ "#\n"
+)
+PO_HEADER_COMMENT = (
+ "# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.\n"
+ "#"
+)
+
+TEMPLATE_ISO_ID = "__TEMPLATE__"
-# Default context.
-CONTEXT_DEFAULT = ""
+# Num buttons report their label with a trailing ': '...
+NUM_BUTTON_SUFFIX = ": "
# Undocumented operator placeholder string.
UNDOC_OPS_STR = "(undocumented operator)"
@@ -118,8 +187,7 @@ PYGETTEXT_ALLOWED_EXTS = {".c", ".cpp", ".cxx", ".hpp", ".hxx", ".h"}
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", "blenfont", "BLF_translation.h")
# Regex to extract contexts defined in BLF_translation.h
# XXX Not full-proof, but should be enough here!
@@ -143,11 +211,21 @@ _str_base = (
"(?P={_}2)" # And closing quote.
)
str_clean_re = _str_base.format(_="g", capt="P<clean>")
+_inbetween_str_re = (
+ # XXX Strings may have comments between their pieces too, not only spaces!
+ r"(?:\s*(?:"
+ # A C comment
+ r"/\*.*(?!\*/).\*/|"
+ # Or a C++ one!
+ r"//[^\n]*\n"
+ # And we are done!
+ r")?)*"
+)
# Here we have to consider two different cases (empty string and other).
_str_whole_re = (
_str_base.format(_="{_}1_", capt=":") +
# Optional loop start, this handles "split" strings...
- "(?:(?<=[\"'])\\s*(?=[\"'])(?:"
+ "(?:(?<=[\"'])" + _inbetween_str_re + "(?=[\"'])(?:"
+ _str_base.format(_="{_}2_", capt=":") +
# End of loop.
"))*"
@@ -165,9 +243,10 @@ PYGETTEXT_KEYWORDS = (() +
for it in ("CTX_IFACE_", "CTX_TIP_", "CTX_N_")) +
tuple(("{}\\((?:[^\"',]+,){{1,2}}\\s*" + _msg_re + r"\s*(?:\)|,)").format(it)
- for it in ("BKE_report", "BKE_reportf", "BKE_reports_prepend", "BKE_reports_prependf")) +
+ for it in ("BKE_report", "BKE_reportf", "BKE_reports_prepend", "BKE_reports_prependf",
+ "CTX_wm_operator_poll_msg_set")) +
- tuple(("{}\\((?:[^\"',]+,){{3}}\\s*" + _msg_re + r"\s*,").format(it)
+ tuple(("{}\\((?:[^\"',]+,){{3}}\\s*" + _msg_re + r"\s*\)").format(it)
for it in ("BMO_error_raise",)) +
tuple(("{}\\((?:[^\"',]+,)\\s*" + _msg_re + r"\s*(?:\)|,)").format(it)
@@ -178,84 +257,123 @@ PYGETTEXT_KEYWORDS = (() +
for it in ("BLF_I18N_MSGID_MULTI_CTXT",))
)
-ESCAPE_RE = (
- (r'((?<!\\)"|(?<!\\)\\(?!\\|"))', r"\\\1"),
- ('\t', r"\\t"),
-)
-
# Should po parser warn when finding a first letter not capitalized?
WARN_MSGID_NOT_CAPITALIZED = True
# Strings that should not raise above warning!
WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
- "", # Simplifies things... :p
- "sin(x) / x",
- "fBM",
- "sqrt(x*x+y*y+z*z)",
- "iTaSC",
+ "", # Simplifies things... :p
+ "ac3",
+ "along X",
+ "along Y",
+ "along Z",
+ "along %s X",
+ "along %s Y",
+ "along %s Z",
+ "along local Z",
+ "ascii",
+ "author", # Addons' field. :/
"bItasc",
- "px",
- "mm",
+ "description", # Addons' field. :/
+ "dx",
+ "fBM",
+ "flac",
+ "fps: %.2f",
+ "fps: %i",
"fStop",
- "sRGB",
+ "gimbal",
+ "global",
+ "iScale",
"iso-8859-15",
- "utf-8",
- "ascii",
- "re",
- "y",
- "ac3",
- "flac",
+ "iTaSC",
+ "iTaSC parameters",
+ "kb",
+ "local",
+ "location", # Addons' field. :/
+ "locking %s X",
+ "locking %s Y",
+ "locking %s Z",
"mkv",
+ "mm",
"mp2",
"mp3",
+ "normal",
"ogg",
- "wav",
- "iTaSC parameters",
- "vBVH",
- "rv",
- "et_EE",
- "eo",
- "available with", # Is part of multi-line msg.
- "virtual parents", # Is part of multi-line msg.
- "description", # Addons' field. :/
- "location", # Addons' field. :/
- "author", # Addons' field. :/
- "in memory to enable editing!", # Is part of multi-line msg.
- "iScale",
- "dx",
"p0",
+ "px",
+ "re",
"res",
+ "rv",
+ "sin(x) / x",
+ "sqrt(x*x+y*y+z*z)",
+ "sRGB",
+ "utf-8",
+ "vBVH",
+ "view",
+ "wav",
+ "y",
+ # Sub-strings.
+ "available with",
+ "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 path can't be written to",
+ "in memory to enable editing!",
+ "unable to load movie clip",
+ "unable to load text",
+ "unable to open the file",
+ "unknown error reading file",
+ "unknown error stating file",
+ "unknown error writing file",
+ "unsupported font format",
+ "unsupported format",
+ "unsupported image format",
+ "unsupported movie clip format",
+ "verts only",
+ "virtual parents",
}
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.",
+}
+
+PARSER_CACHE_HASH = 'sha1'
+
+PARSER_TEMPLATE_ID = "__POT__"
+PARSER_PY_ID = "__PY__"
+
+PARSER_PY_MARKER_BEGIN = "\n# ##### BEGIN AUTOGENERATED I18N SECTION #####\n"
+PARSER_PY_MARKER_END = "\n# ##### END AUTOGENERATED I18N SECTION #####\n"
+
+PARSER_MAX_FILE_SIZE = 2**24 # in bytes, i.e. 16 Mb.
###############################################################################
# PATHS
###############################################################################
-# The tools path, should be OK.
-TOOLS_DIR = os.path.join(os.path.dirname(__file__))
-
# The Python3 executable.You’ll likely have to edit it in your user_settings.py
# if you’re under Windows.
PYTHON3_EXEC = "python3"
# The Blender executable!
-# This is just an example, you’ll most likely have to edit it in your user_settings.py!
-BLENDER_EXEC = os.path.abspath(os.path.join(TOOLS_DIR, "..", "..", "..", "..", "blender"))
-
-# The xgettext tool. You’ll likely have to edit it in your user_settings.py if you’re under Windows.
-GETTEXT_XGETTEXT_EXECUTABLE = "xgettext"
-
-# The gettext msgmerge tool. You’ll likely have to edit it in your user_settings.py if you’re under Windows.
-GETTEXT_MSGMERGE_EXECUTABLE = "msgmerge"
+# This is just an example, you’ll have to edit it in your user_settings.py!
+BLENDER_EXEC = os.path.abspath(os.path.join("foo", "bar", "blender"))
+# check for blender.bin
+if not os.path.exists(BLENDER_EXEC):
+ if os.path.exists(BLENDER_EXEC + ".bin"):
+ BLENDER_EXEC = BLENDER_EXEC + ".bin"
# The gettext msgfmt "compiler". You’ll likely have to edit it in your user_settings.py if you’re under Windows.
GETTEXT_MSGFMT_EXECUTABLE = "msgfmt"
-# The svn binary... You’ll likely have to edit it in your user_settings.py if you’re under Windows.
-SVN_EXECUTABLE = "svn"
-
# The FriBidi C compiled library (.so under Linux, .dll under windows...).
# You’ll likely have to edit it in your user_settings.py if you’re under Windows., e.g. using the included one:
# FRIBIDI_LIB = os.path.join(TOOLS_DIR, "libfribidi.dll")
@@ -265,58 +383,171 @@ FRIBIDI_LIB = "libfribidi.so.0"
RTL_PREPROCESS_FILE = "is_rtl"
# The Blender source root path.
-# This is just an example, you’ll most likely have to override it in your user_settings.py!
-SOURCE_DIR = os.path.abspath(os.path.join(TOOLS_DIR, "..", "..", "..", "..", "..", "..", "blender_msgs"))
+# This is just an example, you’ll have to override it in your user_settings.py!
+SOURCE_DIR = os.path.abspath(os.path.join("blender"))
-# The bf-translation repository (you'll likely have to override this in your user_settings.py).
-I18N_DIR = os.path.abspath(os.path.join(TOOLS_DIR, "..", "..", "..", "..", "..", "..", "i18n"))
+# The bf-translation repository (you'll have to override this in your user_settings.py).
+I18N_DIR = os.path.abspath(os.path.join("i18n"))
-# The /branches path (overriden in bf-translation's i18n_override_settings.py).
-BRANCHES_DIR = os.path.join(I18N_DIR, "branches")
+# The /branches path (relative to I18N_DIR).
+REL_BRANCHES_DIR = os.path.join("branches")
-# The /trunk path (overriden in bf-translation's i18n_override_settings.py).
-TRUNK_DIR = os.path.join(I18N_DIR, "trunk")
+# The /trunk path (relative to I18N_DIR).
+REL_TRUNK_DIR = os.path.join("trunk")
-# The /trunk/po path (overriden in bf-translation's i18n_override_settings.py).
-TRUNK_PO_DIR = os.path.join(TRUNK_DIR, "po")
+# The /trunk/po path (relative to I18N_DIR).
+REL_TRUNK_PO_DIR = os.path.join(REL_TRUNK_DIR, "po")
-# The /trunk/mo path (overriden in bf-translation's i18n_override_settings.py).
-TRUNK_MO_DIR = os.path.join(TRUNK_DIR, "locale")
+# The /trunk/mo path (relative to I18N_DIR).
+REL_TRUNK_MO_DIR = os.path.join(REL_TRUNK_DIR, "locale")
-# The file storing Blender-generated messages.
-FILE_NAME_MESSAGES = os.path.join(TRUNK_PO_DIR, "messages.txt")
+# The Blender source path to check for i18n macros (relative to SOURCE_DIR).
+REL_POTFILES_SOURCE_DIR = os.path.join("source")
-# The Blender source path to check for i18n macros.
-POTFILES_SOURCE_DIR = os.path.join(SOURCE_DIR, "source")
+# The template messages file (relative to I18N_DIR).
+REL_FILE_NAME_POT = os.path.join(REL_BRANCHES_DIR, DOMAIN + ".pot")
-# The "source" file storing which files should be processed by xgettext, used to create FILE_NAME_POTFILES
-FILE_NAME_SRC_POTFILES = os.path.join(TRUNK_PO_DIR, "_POTFILES.in")
+# Mo root datapath.
+REL_MO_PATH_ROOT = os.path.join(REL_TRUNK_DIR, "locale")
-# The final (generated) file storing which files should be processed by xgettext.
-FILE_NAME_POTFILES = os.path.join(TRUNK_PO_DIR, "POTFILES.in")
+# Mo path generator for a given language.
+REL_MO_PATH_TEMPLATE = os.path.join(REL_MO_PATH_ROOT, "{}", "LC_MESSAGES")
-# The template messages file.
-FILE_NAME_POT = os.path.join(TRUNK_PO_DIR, ".".join((DOMAIN, "pot")))
+# Mo path generator for a given language (relative to any "locale" dir).
+MO_PATH_ROOT_RELATIVE = os.path.join("locale")
+MO_PATH_TEMPLATE_RELATIVE = os.path.join(MO_PATH_ROOT_RELATIVE, "{}", "LC_MESSAGES")
-# Other py files that should be searched for ui strings, relative to SOURCE_DIR.
-# Needed for Cycles, currently...
-CUSTOM_PY_UI_FILES = [os.path.join("intern", "cycles", "blender", "addon", "ui.py"),]
+# Mo file name.
+MO_FILE_NAME = DOMAIN + ".mo"
+# Where to search for py files that may contain ui strings (relative to one of the 'resource_path' of Blender).
+CUSTOM_PY_UI_FILES = [
+ os.path.join("scripts", "startup", "bl_ui"),
+ os.path.join("scripts", "modules", "rna_prop_ui.py"),
+]
+
+# An optional text file listing files to force include/exclude from py_xgettext process.
+SRC_POTFILES = ""
# A cache storing validated msgids, to avoid re-spellchecking them.
SPELL_CACHE = os.path.join("/tmp", ".spell_cache")
+# Threshold defining whether a new msgid is similar enough with an old one to reuse its translation...
+SIMILAR_MSGID_THRESHOLD = 0.75
+
+# Additional import paths to add to sys.path (';' separated)...
+INTERN_PY_SYS_PATHS = ""
# Custom override settings must be one dir above i18n tools itself!
-import sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
try:
- from bl_i18n_override_settings import *
+ from bl_i18n_settings_override import *
except ImportError: # If no i18n_override_settings available, it’s no error!
pass
# Override with custom user settings, if available.
try:
- from user_settings import *
+ from settings_user import *
except ImportError: # If no user_settings available, it’s no error!
pass
+
+
+for p in set(INTERN_PY_SYS_PATHS.split(";")):
+ if p:
+ sys.path.append(p)
+
+
+# The settings class itself!
+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!)
+ if os.path.isabs(path):
+ return os.path.relpath(path, ref)
+ else:
+ return path
+
+def _gen_get_set_path(ref, name):
+ def _get(self):
+ return _do_get(getattr(self, ref), getattr(self, name))
+ def _set(self, value):
+ 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:
+ """
+ Class allowing persistence of our settings!
+ Saved in JSon format, so settings should be JSon'able objects!
+ """
+ _settings = None
+
+ def __new__(cls, *args, **kwargs):
+ # Addon preferences are singleton by definition, so is this class!
+ if not I18nSettings._settings:
+ cls._settings = super(I18nSettings, cls).__new__(cls)
+ cls._settings.__dict__ = {uid: data for uid, data in globals().items() if not uid.startswith("_")}
+ return I18nSettings._settings
+
+ def from_json(self, string):
+ data = dict(json.loads(string))
+ # Special case... :/
+ if "INTERN_PY_SYS_PATHS" in data:
+ self.PY_SYS_PATHS = data["INTERN_PY_SYS_PATHS"]
+ self.__dict__.update(data)
+
+ def to_json(self):
+ # Only save the diff from default i18n_settings!
+ glob = globals()
+ export_dict = {uid: val for uid, val in self.__dict__.items() if glob.get(uid) != val}
+ return json.dumps(export_dict)
+
+ def load(self, fname, reset=False):
+ if reset:
+ self.__dict__ = {uid: data for uid, data in globals().items() if not uid.startswith("_")}
+ if isinstance(fname, str):
+ if not os.path.isfile(fname):
+ return
+ with open(fname) as f:
+ self.from_json(f.read())
+ # Else assume fname is already a file(like) object!
+ else:
+ self.from_json(fname.read())
+
+ def save(self, fname):
+ if isinstance(fname, str):
+ with open(fname, 'w') as f:
+ f.write(self.to_json())
+ # Else assume fname is already a file(like) object!
+ else:
+ fname.write(self.to_json())
+
+ BRANCHES_DIR = property(*(_gen_get_set_path("I18N_DIR", "REL_BRANCHES_DIR")))
+ 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")))
+ 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")))
+ MO_PATH_TEMPLATE = property(*(_gen_get_set_path("I18N_DIR", "REL_MO_PATH_TEMPLATE")))
+
+ def _get_py_sys_paths(self):
+ return self.INTERN_PY_SYS_PATHS
+ def _set_py_sys_paths(self, val):
+ old_paths = set(self.INTERN_PY_SYS_PATHS.split(";")) - {""}
+ new_paths = set(val.split(";")) - {""}
+ for p in old_paths - new_paths:
+ if p in sys.path:
+ sys.path.remove(p)
+ for p in new_paths - old_paths:
+ sys.path.append(p)
+ self.INTERN_PY_SYS_PATHS = val
+ PY_SYS_PATHS = property(_get_py_sys_paths, _set_py_sys_paths)
diff --git a/release/scripts/modules/bl_i18n_utils/user_settings.py b/release/scripts/modules/bl_i18n_utils/settings_user.py
index 23d9783cd0f..23d9783cd0f 100644
--- a/release/scripts/modules/bl_i18n_utils/user_settings.py
+++ b/release/scripts/modules/bl_i18n_utils/settings_user.py
diff --git a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py b/release/scripts/modules/bl_i18n_utils/spell_check_utils.py
deleted file mode 100644
index fbe405a61c6..00000000000
--- a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py
+++ /dev/null
@@ -1,528 +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 #####
-
-# <pep8 compliant>
-
-import re
-
-
-_valid_before = "(?<=[\\s*'\"`])|(?<=[a-zA-Z][/-])|(?<=^)"
-_valid_after = "(?=[\\s'\"`.!?,;:])|(?=[/-]\\s*[a-zA-Z])|(?=$)"
-_valid_words = "(?:{})(?:(?:[A-Z]+[a-z]*)|[A-Z]*|[a-z]*)(?:{})".format(_valid_before, _valid_after)
-_reg = re.compile(_valid_words)
-
-
-def split_words(text):
- return [w for w in _reg.findall(text) if w]
-
-
-# These must be all lower case for comparisons
-dict_uimsgs = {
- # OK words
- "aren", # aren't
- "betweens", # yuck! in-betweens!
- "boolean", "booleans",
- "couldn", #couldn't
- "decrement",
- "derivate",
- "doesn", # doesn't
- "fader",
- "hasn", # hasn't
- "hoc", # ad-hoc
- "indices",
- "iridas",
- "isn", # isn't
- "iterable",
- "kyrgyz",
- "latin",
- "merchantability",
- "mplayer",
- "vertices",
-
- # Merged words
- "addon", "addons",
- "antialiasing",
- "arcsine", "arccosine", "arctangent",
- "autoclip",
- "autocomplete",
- "autoname",
- "autosave",
- "autoscale",
- "autosmooth",
- "autosplit",
- "backface", "backfacing",
- "backimage",
- "backscattered",
- "bandnoise",
- "bindcode",
- "bitrate",
- "blendin",
- "bonesize",
- "boundbox",
- "boxpack",
- "buffersize",
- "builtin", "builtins",
- "bytecode",
- "chunksize",
- "de",
- "defocus",
- "denoise",
- "despill", "despilling",
- "filebrowser",
- "filelist",
- "filename", "filenames",
- "filepath", "filepaths",
- "forcefield", "forcefields",
- "fulldome", "fulldomes",
- "fullscreen",
- "gridline",
- "hemi",
- "inbetween",
- "inscatter", "inscattering",
- "libdata",
- "lightless",
- "lookup", "lookups",
- "mathutils",
- "midlevel",
- "midground",
- "mixdown",
- "multi",
- "multifractal",
- "multires", "multiresolution",
- "multisampling",
- "multitexture",
- "multiuser",
- "namespace",
- "keyconfig",
- "playhead",
- "polyline",
- "popup", "popups",
- "pre",
- "precalculate",
- "prefetch",
- "premultiply", "premultiplied",
- "prepass",
- "prepend",
- "preprocess", "preprocessing",
- "preseek",
- "readonly",
- "realtime",
- "rekey",
- "remesh",
- "reprojection",
- "resize",
- "restpose",
- "retarget", "retargets", "retargeting", "retargeted",
- "ringnoise",
- "rolloff",
- "screencast", "screenshot", "screenshots",
- "selfcollision",
- "singletexture",
- "startup",
- "stateful",
- "starfield",
- "subflare", "subflares",
- "subframe", "subframes",
- "subclass", "subclasses", "subclassing",
- "subdirectory", "subdirectories", "subdir", "subdirs",
- "submodule", "submodules",
- "subpath",
- "subsize",
- "substep", "substeps",
- "targetless",
- "textbox", "textboxes",
- "tilemode",
- "timestamp", "timestamps",
- "timestep", "timesteps",
- "todo",
- "un",
- "unbake",
- "uncomment",
- "undeformed",
- "undistort", "undistortion",
- "ungroup",
- "unhide",
- "unindent",
- "unkeyed",
- "unpremultiply",
- "unprojected",
- "unreacted",
- "unregister",
- "unselected",
- "unsubdivided", "unsubdivide",
- "unshadowed",
- "unspill",
- "unstitchable",
- "vectorscope",
- "whitespace", "whitespaces",
- "worldspace",
- "workflow",
-
- # Neologisms, slangs
- "affectable",
- "automagic", "automagically",
- "blobby",
- "blockiness", "blocky",
- "collider", "colliders",
- "deformer", "deformers",
- "determinator",
- "editability",
- "keyer",
- "lacunarity",
- "numerics",
- "occluder",
- "passepartout",
- "perspectively",
- "polygonization",
- "selectability",
- "slurph",
- "stitchable",
- "symmetrize",
- "trackability",
- "transmissivity",
- "rasterized", "rasterization",
- "renderer", "renderable", "renderability",
-
- # Abbreviations
- "aero",
- "amb",
- "anim",
- "bool",
- "calc",
- "config", "configs",
- "const",
- "coord", "coords",
- "degr",
- "dof",
- "dupli", "duplis",
- "eg",
- "esc",
- "expr",
- "fac",
- "fra",
- "frs",
- "grless",
- "http",
- "init",
- "kbit",
- "lensdist",
- "loc", "rot", "pos",
- "lorem",
- "luma",
- "multicam",
- "num",
- "ok",
- "orco",
- "ortho",
- "persp",
- "pref", "prefs",
- "prev",
- "param",
- "premul",
- "quad", "quads",
- "quat", "quats",
- "recalc", "recalcs",
- "refl",
- "sel",
- "spec",
- "struct", "structs",
- "tex",
- "tri", "tris",
- "uv", "uvs", "uvw", "uw", "uvmap",
- "vec",
- "vert", "verts",
- "vis",
- "xyz", "xzy", "yxz", "yzx", "zxy", "zyx",
- "xy", "xz", "yx", "yz", "zx", "zy",
-
- # General computer/science terms
- "boid", "boids",
- "equisolid",
- "euler", "eulers",
- "hashable",
- "intrinsics",
- "isosurface",
- "jitter", "jittering", "jittered",
- "keymap", "keymaps",
- "lambertian",
- "laplacian",
- "metadata",
- "nand", "xnor",
- "normals",
- "numpad",
- "octree",
- "opengl",
- "pulldown", "pulldowns",
- "quantized",
- "samplerate",
- "scrollback",
- "scrollbar",
- "scroller",
- "searchable",
- "spacebar",
- "tooltip", "tooltips",
- "trackpad",
- "unicode",
- "viewport", "viewports",
- "viscoelastic",
- "wildcard", "wildcards",
-
- # General computer graphics terms
- "anaglyph",
- "bezier", "beziers",
- "bicubic",
- "bilinear",
- "blackpoint", "whitepoint",
- "blinn",
- "bokeh",
- "catadioptric",
- "centroid",
- "chrominance",
- "codec", "codecs",
- "collada",
- "compositing",
- "crossfade",
- "deinterlace",
- "dropoff",
- "dv",
- "eigenvectors",
- "equirectangular",
- "fisheye",
- "framerate",
- "gimbal",
- "grayscale",
- "icosphere",
- "inpaint",
- "lightmap",
- "lossless", "lossy",
- "midtones",
- "mipmap", "mipmaps", "mip",
- "ngon", "ngons",
- "ntsc",
- "nurb", "nurbs",
- "perlin",
- "phong",
- "radiosity",
- "raytrace", "raytracing", "raytraced",
- "renderfarm",
- "shader", "shaders",
- "specular", "specularity",
- "spillmap",
- "sobel",
- "tonemap",
- "toon",
- "timecode",
- "voronoi",
- "voxel", "voxels",
- "wireframe",
- "zmask",
- "ztransp",
-
- # Blender terms
- "audaspace",
- "bbone",
- "breakdowner",
- "bspline",
- "bweight",
- "colorband",
- "datablock", "datablocks",
- "despeckle",
- "dopesheet",
- "dupliface", "duplifaces",
- "dupliframe", "dupliframes",
- "dupliobject", "dupliob",
- "dupligroup",
- "duplivert",
- "editbone",
- "editmode",
- "fcurve", "fcurves",
- "fluidsim",
- "frameserver",
- "enum",
- "keyframe", "keyframes", "keyframing", "keyframed",
- "metaball", "metaballs",
- "metaelement", "metaelements",
- "metastrip", "metastrips",
- "movieclip",
- "mpoly",
- "mtex",
- "nabla",
- "navmesh",
- "outliner",
- "paintmap", "paintmaps",
- "polygroup", "polygroups",
- "poselib",
- "pushpull",
- "pyconstraint", "pyconstraints",
- "shapekey", "shapekeys",
- "shrinkfatten",
- "shrinkwrap",
- "softbody",
- "stucci",
- "sunsky",
- "subsurf",
- "tessface", "tessfaces",
- "texface",
- "timeline", "timelines",
- "tosphere",
- "vcol", "vcols",
- "vgroup", "vgroups",
- "vinterlace",
- "wetmap", "wetmaps",
- "wpaint",
-
- # Algorithm names
- "beckmann",
- "catmull",
- "catrom",
- "chebychev",
- "courant",
- "kutta",
- "lennard",
- "minkowski",
- "minnaert",
- "musgrave",
- "nayar",
- "netravali",
- "oren",
- "prewitt",
- "runge",
- "verlet",
- "worley",
-
- # Acronyms
- "aa", "msaa",
- "api",
- "asc", "cdl",
- "ascii",
- "atrac",
- "bw",
- "ccd",
- "cmd",
- "cpus",
- "ctrl",
- "cw", "ccw",
- "dev",
- "djv",
- "dpi",
- "dvar",
- "dx",
- "eo",
- "fh",
- "fov",
- "fft",
- "futura",
- "gfx",
- "gl",
- "glsl",
- "gpl",
- "gpu", "gpus",
- "hc",
- "hdc",
- "hdr",
- "hh", "mm", "ss", "ff", # hh:mm:ss:ff timecode
- "hsv", "hsva",
- "id",
- "itu",
- "lhs",
- "lmb", "mmb", "rmb",
- "mux",
- "ndof",
- "ppc",
- "precisa",
- "px",
- "qmc",
- "rgb", "rgba",
- "rhs",
- "rv",
- "sdl",
- "sl",
- "smpte",
- "svn",
- "ui",
- "unix",
- "vbo", "vbos",
- "ycc", "ycca",
- "yuv", "yuva",
-
- # Blender acronyms
- "bge",
- "bli",
- "bvh",
- "dbvt",
- "dop", # BLI K-Dop BVH
- "ik",
- "nla",
- "py",
- "qbvh",
- "rna",
- "rvo",
- "simd",
- "sph",
- "svbvh",
-
- # CG acronyms
- "ao",
- "bsdf",
- "ior",
- "mocap",
-
- # Files types/formats
- "avi",
- "attrac",
- "autodesk",
- "bmp",
- "btx",
- "cineon",
- "dpx",
- "dxf",
- "eps",
- "exr",
- "fbx",
- "ffmpeg",
- "flac",
- "gzip",
- "ico",
- "jpg", "jpeg",
- "matroska",
- "mdd",
- "mkv",
- "mpeg", "mjpeg",
- "mtl",
- "ogg",
- "openjpeg",
- "osl",
- "oso",
- "piz",
- "png",
- "po",
- "quicktime",
- "rle",
- "sgi",
- "stl",
- "svg",
- "targa", "tga",
- "tiff",
- "theora",
- "vorbis",
- "wav",
- "xiph",
- "xml",
- "xna",
- "xvid",
-}
diff --git a/release/scripts/modules/bl_i18n_utils/update_branches.py b/release/scripts/modules/bl_i18n_utils/update_branches.py
deleted file mode 100755
index 4c38a2f71fb..00000000000
--- a/release/scripts/modules/bl_i18n_utils/update_branches.py
+++ /dev/null
@@ -1,107 +0,0 @@
-#!/usr/bin/python3
-
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public 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>
-
-# Update all branches:
-# * Generate a temp messages.txt file.
-# * Use it to generate a temp .pot file.
-# * Use it to update all .po’s in /branches.
-
-import subprocess
-import os
-import sys
-import tempfile
-
-try:
- import settings
-except:
- from . import settings
-
-
-PY3 = settings.PYTHON3_EXEC
-
-FILE_NAME_POT = settings.FILE_NAME_POT
-
-
-def main():
- import argparse
- parser = argparse.ArgumentParser(description="" \
- "Update all branches:\n" \
- "* Generate a temp messages.txt file.\n" \
- "* Use it to generate a temp .pot file.\n" \
- "* Use it to update all .po’s in /branches.")
- parser.add_argument('--pproc-contexts', action="store_true",
- help="Pre-process po’s to avoid having plenty of "
- "fuzzy msgids just because a context was "
- "added/changed!")
- parser.add_argument('-c', '--no_checks', default=True,
- action="store_false",
- help="No checks over UI messages.")
- parser.add_argument('-a', '--add', action="store_true",
- help="Add missing po’s (useful only when one or " \
- "more languages are given!).")
- parser.add_argument('langs', metavar='ISO_code', nargs='*',
- help="Restrict processed languages to those.")
- args = parser.parse_args()
-
- ret = 0
-
- # Generate a temp messages file.
- dummy, msgfile = tempfile.mkstemp(suffix=".txt",
- prefix="blender_messages_")
- os.close(dummy)
- cmd = (PY3, "./update_msg.py", "-o", msgfile)
- t = subprocess.call(cmd)
- if t:
- ret = t
-
- # Generate a temp pot file.
- # Back to having a pot file in trunk/po. It's quite useful for translators that want to start
- # a new translation and not not want to bother generating their own po from scratch!
-# dummy, potfile = tempfile.mkstemp(suffix=".pot",
-# prefix="blender_pot_")
-# os.close(dummy)
- potfile = FILE_NAME_POT
- cmd = [PY3, "./update_pot.py", "-i", msgfile, "-o", potfile]
- if not args.no_checks:
- cmd.append("-c")
- t = subprocess.call(cmd)
- if t:
- ret = t
-
- # Update branches’ po files.
- cmd = [PY3, "./update_po.py", "-i", potfile]
- if args.langs:
- if args.add:
- cmd.append("-a")
- cmd += args.langs
- if args.pproc_contexts:
- cmd.append("--pproc-contexts")
- t = subprocess.call(cmd)
- if t:
- ret = t
-
- return ret
-
-
-if __name__ == "__main__":
- print("\n\n *** Running {} *** \n".format(__file__))
- sys.exit(main())
diff --git a/release/scripts/modules/bl_i18n_utils/update_languages_menu.py b/release/scripts/modules/bl_i18n_utils/update_languages_menu.py
deleted file mode 100755
index 9b4cb20fadf..00000000000
--- a/release/scripts/modules/bl_i18n_utils/update_languages_menu.py
+++ /dev/null
@@ -1,148 +0,0 @@
-#!/usr/bin/python3
-
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public 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>
-
-# Update "languages" text file used by Blender at runtime to build translations menu.
-
-import os
-import sys
-import shutil
-
-try:
- import settings
- import utils
-except:
- from . import (settings, utils)
-
-TRUNK_PO_DIR = settings.TRUNK_PO_DIR
-TRUNK_MO_DIR = settings.TRUNK_MO_DIR
-
-LANGUAGES_CATEGORIES = settings.LANGUAGES_CATEGORIES
-LANGUAGES = settings.LANGUAGES
-LANGUAGES_FILE = settings.LANGUAGES_FILE
-
-OK = 0
-MISSING = 1
-TOOLOW = 2
-FORBIDDEN = 3
-FLAG_MESSAGES = {
- OK: "",
- MISSING: "No translation yet!",
- TOOLOW: "Not enough advanced to be included...",
- FORBIDDEN: "Explicitly forbidden!",
-}
-
-def find_matching_po(languages, stats, forbidden):
- """Match languages defined in LANGUAGES setting to relevant po, if possible!"""
- ret = []
- for uid, label, org_key, in languages:
- key = org_key
- if key not in stats:
- # Try to simplify the key (eg from es_ES to es).
- if '_' in org_key:
- key = org_key[0:org_key.index('_')]
- # For stuff like sr_SR@latin -> sr@latin...
- if '@' in org_key:
- key = key + org_key[org_key.index('@'):]
- if key in stats:
- if key in forbidden:
- ret.append((stats[key], uid, label, org_key, FORBIDDEN))
- else:
- ret.append((stats[key], uid, label, org_key, OK))
- else:
- ret.append((0.0, uid, label, org_key, MISSING))
- return ret
-
-def main():
- import argparse
- parser = argparse.ArgumentParser(description=""
- "Update 'languages' text file used by Blender at runtime to build translations menu.")
- parser.add_argument('-m', '--min_translation', type=int, default=-100,
- help="Minimum level of translation, as a percentage "
- "(translations below this are commented out in menu).")
- parser.add_argument('langs', metavar='ISO_code', nargs='*',
- help="Unconditionally exclude those languages from the menu.")
- args = parser.parse_args()
-
- ret = 0
- min_trans = args.min_translation / 100.0
- forbidden = set(args.langs)
- # 'DEFAULT' and en_US are always valid, fully-translated "languages"!
- stats = {"DEFAULT": 1.0, "en_US": 1.0}
-
- # Get the "done level" of each po in trunk...
- for po in os.listdir(TRUNK_PO_DIR):
- if po.endswith(".po") and not po.endswith("_raw.po"):
- lang = os.path.basename(po)[:-3]
- u1, u2, _stats = utils.parse_messages(os.path.join(TRUNK_PO_DIR, po))
- stats[lang] = _stats["trans_msg"] / _stats["tot_msg"]
-
- # Generate languages file used by Blender's i18n system.
- # First, match all entries in LANGUAGES to a lang in stats, if possible!
- stats = find_matching_po(LANGUAGES, stats, forbidden)
- limits = sorted(LANGUAGES_CATEGORIES, key=lambda it: it[0], reverse=True)
- idx = 0
- stats = sorted(stats, key=lambda it: it[0], reverse=True)
- langs_cats = [[] for i in range(len(limits))]
- highest_uid = 0
- for prop, uid, label, key, flag in stats:
- if prop < limits[idx][0]:
- # Sub-sort languages by iso-codes.
- langs_cats[idx].sort(key=lambda it: it[2])
- idx += 1
- if prop < min_trans and flag == OK:
- flag = TOOLOW
- langs_cats[idx].append((uid, label, key, flag))
- if abs(uid) > highest_uid:
- highest_uid = abs(uid)
- # Sub-sort last group of languages by iso-codes!
- langs_cats[idx].sort(key=lambda it: it[2])
- with open(os.path.join(TRUNK_MO_DIR, LANGUAGES_FILE), 'w', encoding="utf-8") as f:
- f.write("# File used by Blender to know which languages (translations) are available, \n")
- f.write("# and to generate translation menu.\n")
- f.write("#\n")
- f.write("# File format:\n")
- f.write("# ID:MENULABEL:ISOCODE\n")
- f.write("# ID must be unique, except for 0 value (marks categories for menu).\n")
- f.write("# Line starting with a # are comments!\n")
- f.write("#\n")
- f.write("# Automatically generated by bl_i18n_utils/update_languages_menu.py script.\n")
- f.write("# Highest ID currently in use: {}\n".format(highest_uid))
- for cat, langs_cat in zip(limits, langs_cats):
- f.write("#\n")
- # Write "category menu label"...
- if langs_cat:
- f.write("0:{}::\n".format(cat[1]))
- else:
- # Do not write the category if it has no language!
- f.write("# Void category! #0:{}:\n".format(cat[1]))
- # ...and all matching language entries!
- for uid, label, key, flag in langs_cat:
- if flag == OK:
- f.write("{}:{}:{}\n".format(uid, label, key))
- else:
- # Non-existing, commented entry!
- f.write("# {} #{}:{}:{}\n".format(FLAG_MESSAGES[flag], uid, label, key))
-
-
-if __name__ == "__main__":
- print("\n\n *** Running {} *** \n".format(__file__))
- sys.exit(main())
diff --git a/release/scripts/modules/bl_i18n_utils/update_mo.py b/release/scripts/modules/bl_i18n_utils/update_mo.py
deleted file mode 100755
index 7f68736593c..00000000000
--- a/release/scripts/modules/bl_i18n_utils/update_mo.py
+++ /dev/null
@@ -1,106 +0,0 @@
-#!/usr/bin/python3
-
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public 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>
-
-# Create or update mo’s under /trunk/locale/…
-
-import subprocess
-import os
-import sys
-
-try:
- import settings
- import utils
-except:
- from . import (settings, utils)
-
-
-GETTEXT_MSGFMT_EXECUTABLE = settings.GETTEXT_MSGFMT_EXECUTABLE
-
-SOURCE_DIR = settings.SOURCE_DIR
-TRUNK_MO_DIR = settings.TRUNK_MO_DIR
-TRUNK_PO_DIR = settings.TRUNK_PO_DIR
-
-DOMAIN = settings.DOMAIN
-
-
-def process_po(po, lang, mo=None):
- if not mo:
- mo_dir = os.path.join(TRUNK_MO_DIR, lang, "LC_MESSAGES")
- # Create dirs if not existing!
- if not os.path.isdir(mo_dir):
- os.makedirs(mo_dir, exist_ok=True)
-
- # show stats
- cmd = (GETTEXT_MSGFMT_EXECUTABLE,
- "--statistics",
- po,
- "-o",
- mo or os.path.join(mo_dir, ".".join((DOMAIN, "mo"))),
- )
-
- print("Running ", " ".join(cmd))
- ret = subprocess.call(cmd)
- print("Finished.")
- return ret
-
-
-def main():
- import argparse
- parser = argparse.ArgumentParser(description="Create or update mo’s " \
- "under {}.".format(TRUNK_MO_DIR))
- parser.add_argument('langs', metavar='ISO_code', nargs='*',
- help="Restrict processed languages to those.")
- parser.add_argument('--po', help="Only process that po file (implies --mo).",
- nargs='?')
- parser.add_argument('--mo', help="Mo file to generate (implies --po).",
- nargs='?')
- args = parser.parse_args()
-
- ret = 0
-
- if args.po and args.mo:
- if os.path.exists(args.po):
- t = process_po(args.po, None, args.mo)
- if t:
- ret = t
- elif args.langs:
- for lang in args.langs:
- po = os.path.join(TRUNK_PO_DIR, ".".join((lang, "po")))
- if os.path.exists(po):
- t = process_po(po, lang)
- if t:
- ret = t
- else:
- for po in os.listdir(TRUNK_PO_DIR):
- if po.endswith(".po") and not po.endswith("_raw.po"):
- lang = os.path.basename(po)[:-3]
- po = os.path.join(TRUNK_PO_DIR, po)
- t = process_po(po, lang)
- if t:
- ret = t
-
- return ret
-
-
-if __name__ == "__main__":
- print("\n\n *** Running {} *** \n".format(__file__))
- sys.exit(main())
diff --git a/release/scripts/modules/bl_i18n_utils/update_msg.py b/release/scripts/modules/bl_i18n_utils/update_msg.py
deleted file mode 100755
index c1b0d636655..00000000000
--- a/release/scripts/modules/bl_i18n_utils/update_msg.py
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/usr/bin/python3
-
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public 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-80 compliant>
-
-# Write out messages.txt from Blender.
-
-import os
-import sys
-import subprocess
-
-try:
- import settings
-except:
- from . import settings
-
-
-BLENDER_ARGS = [
- settings.BLENDER_EXEC,
- "--background",
- "--factory-startup",
- "--python",
- os.path.join(settings.TOOLS_DIR, "bl_process_msg.py"),
- "--",
- "-m",
-]
-
-
-def main():
- import argparse
- parser = argparse.ArgumentParser(description="Write out messages.txt " \
- "from Blender.")
- parser.add_argument('-c', '--no_checks', default=True,
- action="store_false",
- help="No checks over UI messages.")
- parser.add_argument('-b', '--blender', help="Blender executable path.")
- parser.add_argument('-o', '--output', help="Output messages file path.")
- args = parser.parse_args()
- if args.blender:
- BLENDER_ARGS[0] = args.blender
- if not args.no_checks:
- BLENDER_ARGS.append("-c")
- if args.output:
- BLENDER_ARGS.append("-o")
- BLENDER_ARGS.append(args.output)
- ret = subprocess.call(BLENDER_ARGS)
-
- return ret
-
-
-if __name__ == "__main__":
- print("\n\n *** Running {} *** \n".format(__file__))
- ret = main()
- if ret:
- raise(Exception(ret))
diff --git a/release/scripts/modules/bl_i18n_utils/update_po.py b/release/scripts/modules/bl_i18n_utils/update_po.py
deleted file mode 100755
index 4c6495c5cfe..00000000000
--- a/release/scripts/modules/bl_i18n_utils/update_po.py
+++ /dev/null
@@ -1,172 +0,0 @@
-#!/usr/bin/python3
-
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public 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>
-
-# Update po’s in the branches from blender.pot in /trunk/po dir.
-
-import subprocess
-import os
-import sys
-from codecs import open
-import shutil
-
-try:
- import settings
- import utils
-except:
- from . import (settings, utils)
-
-
-GETTEXT_MSGMERGE_EXECUTABLE = settings.GETTEXT_MSGMERGE_EXECUTABLE
-BRANCHES_DIR = settings.BRANCHES_DIR
-TRUNK_PO_DIR = settings.TRUNK_PO_DIR
-FILE_NAME_POT = settings.FILE_NAME_POT
-
-
-def pproc_newcontext_po(po, pot_messages, pot_stats):
- print("Adding new contexts to {}...".format(po))
- messages, state, stats = utils.parse_messages(po)
- known_ctxt = stats["contexts"]
- print("Already known (present) context(s): {}".format(str(known_ctxt)))
-
- new_ctxt = set()
- added = 0
- # Only use valid already translated messages!
- allowed_keys = state["trans_msg"] - state["fuzzy_msg"] - state["comm_msg"]
- for key in pot_messages.keys():
- ctxt, msgid = key
- if ctxt in known_ctxt:
- continue
- new_ctxt.add(ctxt)
- for t_ctxt in known_ctxt:
- # XXX The first match will win, this might not be optimal...
- t_key = (t_ctxt, msgid)
- if t_key in allowed_keys:
- # Wrong comments (sources) will be removed by msgmerge...
- messages[key] = messages[t_key]
- messages[key]["msgctxt_lines"] = [ctxt]
- added += 1
-
- utils.write_messages(po, messages, state["comm_msg"], state["fuzzy_msg"])
- print("Finished!\n {} new context(s) was/were added {}, adding {} new "
- "messages.\n".format(len(new_ctxt), str(new_ctxt), added))
- return 0
-
-
-def process_po(po, lang):
- # update po file
- cmd = (GETTEXT_MSGMERGE_EXECUTABLE,
- "--update",
- "-w", "1", # XXX Ugly hack to prevent msgmerge merging
- # short source comments together!
- "--no-wrap",
- "--backup=none",
- "--lang={}".format(lang),
- po,
- FILE_NAME_POT,
- )
-
- print("Updating {}...".format(po))
- print("Running ", " ".join(cmd))
- ret = subprocess.call(cmd)
- print("Finished!\n")
- return ret
-
-
-def main():
- import argparse
- parser = argparse.ArgumentParser(description="Write out messages.txt "
- "from Blender.")
- parser.add_argument('-t', '--trunk', action="store_true",
- help="Update po’s in /trunk/po rather than /branches.")
- parser.add_argument('-i', '--input', metavar="File",
- help="Input pot file path.")
- parser.add_argument('--pproc-contexts', action="store_true",
- help="Pre-process po’s to avoid having plenty of "
- "fuzzy msgids just because a context was "
- "added/changed!")
- parser.add_argument('-a', '--add', action="store_true",
- help="Add missing po’s (useful only when one or "
- "more languages are given!).")
- parser.add_argument('langs', metavar='ISO_code', nargs='*',
- help="Restrict processed languages to those.")
- args = parser.parse_args()
-
- if args.input:
- global FILE_NAME_POT
- FILE_NAME_POT = args.input
- ret = 0
-
- if args.pproc_contexts:
- _ctxt_proc = pproc_newcontext_po
- pot_messages, _a, pot_stats = utils.parse_messages(FILE_NAME_POT)
- else:
- _ctxt_proc = lambda a, b, c: 0
- pot_messages, pot_stats = None, None
-
- if args.langs:
- for lang in args.langs:
- if args.trunk:
- dr = TRUNK_PO_DIR
- po = os.path.join(dr, ".".join((lang, "po")))
- else:
- dr = os.path.join(BRANCHES_DIR, lang)
- po = os.path.join(dr, ".".join((lang, "po")))
- if args.add:
- if not os.path.exists(dr):
- os.makedirs(dr)
- if not os.path.exists(po):
- shutil.copy(FILE_NAME_POT, po)
- if args.add or os.path.exists(po):
- t = _ctxt_proc(po, pot_messages, pot_stats)
- if t:
- ret = t
- t = process_po(po, lang)
- if t:
- ret = t
- elif args.trunk:
- for po in os.listdir(TRUNK_PO_DIR):
- if po.endswith(".po"):
- lang = os.path.basename(po)[:-3]
- po = os.path.join(TRUNK_PO_DIR, po)
- t = _ctxt_proc(po, pot_messages, pot_stats)
- if t:
- ret = t
- t = process_po(po, lang)
- if t:
- ret = t
- else:
- for lang in os.listdir(BRANCHES_DIR):
- po = os.path.join(BRANCHES_DIR, lang, ".".join((lang, "po")))
- if os.path.exists(po):
- t = _ctxt_proc(po, pot_messages, pot_stats)
- if t:
- ret = t
- t = process_po(po, lang)
- if t:
- ret = t
-
- return ret
-
-
-if __name__ == "__main__":
- print("\n\n *** Running {} *** \n".format(__file__))
- sys.exit(main())
diff --git a/release/scripts/modules/bl_i18n_utils/update_pot.py b/release/scripts/modules/bl_i18n_utils/update_pot.py
deleted file mode 100755
index ecb5d837a09..00000000000
--- a/release/scripts/modules/bl_i18n_utils/update_pot.py
+++ /dev/null
@@ -1,339 +0,0 @@
-#!/usr/bin/python3
-
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public 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>
-
-# Update blender.pot file from messages.txt
-
-import subprocess
-import os
-import sys
-import re
-import tempfile
-import argparse
-import time
-import pickle
-
-try:
- import settings
- import utils
-except:
- from . import (settings, utils)
-
-
-LANGUAGES_CATEGORIES = settings.LANGUAGES_CATEGORIES
-LANGUAGES = settings.LANGUAGES
-
-COMMENT_PREFIX = settings.COMMENT_PREFIX
-COMMENT_PREFIX_SOURCE = settings.COMMENT_PREFIX_SOURCE
-CONTEXT_PREFIX = settings.CONTEXT_PREFIX
-FILE_NAME_MESSAGES = settings.FILE_NAME_MESSAGES
-FILE_NAME_POT = settings.FILE_NAME_POT
-SOURCE_DIR = settings.SOURCE_DIR
-POTFILES_DIR = settings.POTFILES_SOURCE_DIR
-SRC_POTFILES = settings.FILE_NAME_SRC_POTFILES
-
-CONTEXT_DEFAULT = settings.CONTEXT_DEFAULT
-PYGETTEXT_ALLOWED_EXTS = settings.PYGETTEXT_ALLOWED_EXTS
-PYGETTEXT_MAX_MULTI_CTXT = settings.PYGETTEXT_MAX_MULTI_CTXT
-
-SVN_EXECUTABLE = settings.SVN_EXECUTABLE
-
-WARN_NC = settings.WARN_MSGID_NOT_CAPITALIZED
-NC_ALLOWED = settings.WARN_MSGID_NOT_CAPITALIZED_ALLOWED
-
-SPELL_CACHE = settings.SPELL_CACHE
-
-
-# Do this only once!
-# Get contexts defined in blf.
-CONTEXTS = {}
-with open(os.path.join(SOURCE_DIR, settings.PYGETTEXT_CONTEXTS_DEFSRC)) as f:
- reg = re.compile(settings.PYGETTEXT_CONTEXTS)
- f = f.read()
- # This regex is supposed to yield tuples
- # (key=C_macro_name, value=C_string).
- CONTEXTS = dict(m.groups() for m in reg.finditer(f))
-
-# Build regexes to extract messages (with optional contexts) from C source.
-pygettexts = tuple(re.compile(r).search
- for r in settings.PYGETTEXT_KEYWORDS)
-_clean_str = re.compile(settings.str_clean_re).finditer
-clean_str = lambda s: "".join(m.group("clean") for m in _clean_str(s))
-
-
-def check_file(path, rel_path, messages):
- def process_entry(ctxt, msg):
- # Context.
- if ctxt:
- if ctxt in CONTEXTS:
- ctxt = CONTEXTS[ctxt]
- elif '"' in ctxt or "'" in ctxt:
- ctxt = clean_str(ctxt)
- else:
- print("WARNING: raw context “{}†couldn’t be resolved!"
- "".format(ctxt))
- ctxt = CONTEXT_DEFAULT
- else:
- ctxt = CONTEXT_DEFAULT
- # Message.
- if msg:
- if '"' in msg or "'" in msg:
- msg = clean_str(msg)
- else:
- print("WARNING: raw message “{}†couldn’t be resolved!"
- "".format(msg))
- msg = ""
- else:
- msg = ""
- return (ctxt, msg)
-
- with open(path, encoding="utf-8") as f:
- f = f.read()
- for srch in pygettexts:
- m = srch(f)
- line = pos = 0
- while m:
- d = m.groupdict()
- # Line.
- line += f[pos:m.start()].count('\n')
- msg = d.get("msg_raw")
- # First, try the "multi-contexts" stuff!
- ctxts = tuple(d.get("ctxt_raw{}".format(i)) for i in range(PYGETTEXT_MAX_MULTI_CTXT))
- if ctxts[0]:
- for ctxt in ctxts:
- if not ctxt:
- break
- ctxt, _msg = process_entry(ctxt, msg)
- # And we are done for this item!
- messages.setdefault((ctxt, _msg), []).append(":".join((rel_path, str(line))))
- else:
- ctxt = d.get("ctxt_raw")
- ctxt, msg = process_entry(ctxt, msg)
- # And we are done for this item!
- messages.setdefault((ctxt, msg), []).append(":".join((rel_path, str(line))))
- pos = m.end()
- line += f[m.start():pos].count('\n')
- m = srch(f, pos)
-
-
-def py_xgettext(messages):
- forbidden = set()
- forced = set()
- with open(SRC_POTFILES) as src:
- for l in src:
- if l[0] == '-':
- forbidden.add(l[1:].rstrip('\n'))
- elif l[0] != '#':
- forced.add(l.rstrip('\n'))
- for root, dirs, files in os.walk(POTFILES_DIR):
- if "/.svn" in root:
- continue
- for fname in files:
- if os.path.splitext(fname)[1] not in PYGETTEXT_ALLOWED_EXTS:
- continue
- path = os.path.join(root, fname)
- rel_path = os.path.relpath(path, SOURCE_DIR)
- if rel_path in forbidden:
- continue
- elif rel_path not in forced:
- forced.add(rel_path)
- for rel_path in sorted(forced):
- path = os.path.join(SOURCE_DIR, rel_path)
- if os.path.exists(path):
- check_file(path, rel_path, messages)
-
-
-# Spell checking!
-import enchant
-dict_spelling = enchant.Dict("en_US")
-
-from spell_check_utils import (dict_uimsgs,
- split_words,
- )
-
-_spell_checked = set()
-
-
-def spell_check(txt, cache):
- ret = []
-
- if cache is not None and txt in cache:
- return ret
-
- for w in split_words(txt):
- w_lower = w.lower()
- if w_lower in dict_uimsgs | _spell_checked:
- continue
- if not dict_spelling.check(w):
- ret.append("{}: suggestions are ({})"
- .format(w, "'" + "', '".join(dict_spelling.suggest(w))
- + "'"))
- else:
- _spell_checked.add(w_lower)
-
- if not ret:
- if cache is not None:
- cache.add(txt)
-
- return ret
-
-
-def get_svnrev():
- cmd = [SVN_EXECUTABLE,
- "info",
- "--xml",
- SOURCE_DIR,
- ]
- xml = subprocess.check_output(cmd)
- return re.search(b'revision="(\d+)"', xml).group(1)
-
-
-def gen_empty_pot():
- blender_rev = get_svnrev().decode()
- utctime = time.gmtime()
- time_str = time.strftime("%Y-%m-%d %H:%M+0000", utctime)
- year_str = time.strftime("%Y", utctime)
-
- return utils.gen_empty_messages(blender_rev, time_str, year_str)
-
-
-escape_re = tuple(re.compile(r[0]) for r in settings.ESCAPE_RE)
-escape = lambda s, n: escape_re[n].sub(settings.ESCAPE_RE[n][1], s)
-
-
-def merge_messages(msgs, states, messages, do_checks, spell_cache):
- num_added = num_present = 0
- for (context, msgid), srcs in messages.items():
- if do_checks:
- err = spell_check(msgid, spell_cache)
- if err:
- print("WARNING: spell check failed on “" + msgid + "â€:")
- print("\t\t" + "\n\t\t".join(err))
- print("\tFrom:\n\t\t" + "\n\t\t".join(srcs))
-
- # Escape some chars in msgid!
- for n in range(len(escape_re)):
- msgid = escape(msgid, n)
-
- srcs = [COMMENT_PREFIX_SOURCE + s for s in srcs]
-
- key = (context, msgid)
- if key not in msgs:
- msgs[key] = {"msgid_lines": [msgid],
- "msgstr_lines": [""],
- "comment_lines": srcs,
- "msgctxt_lines": [context]}
- num_added += 1
- else:
- # We need to merge comments!
- msgs[key]["comment_lines"].extend(srcs)
- num_present += 1
-
- return num_added, num_present
-
-
-def main():
- parser = argparse.ArgumentParser(description="Update blender.pot file from messages.txt and source code parsing, "
- "and performs some checks over msgids.")
- parser.add_argument('-w', '--warning', action="store_true",
- help="Show warnings.")
- parser.add_argument('-i', '--input', metavar="File",
- help="Input messages file path.")
- parser.add_argument('-o', '--output', metavar="File",
- help="Output pot file path.")
-
- args = parser.parse_args()
- if args.input:
- global FILE_NAME_MESSAGES
- FILE_NAME_MESSAGES = args.input
- if args.output:
- global FILE_NAME_POT
- FILE_NAME_POT = args.output
-
- print("Running fake py gettext…")
- # Not using any more xgettext, simpler to do it ourself!
- messages = utils.new_messages()
- py_xgettext(messages)
- print("Finished, found {} messages.".format(len(messages)))
-
- if SPELL_CACHE and os.path.exists(SPELL_CACHE):
- with open(SPELL_CACHE, 'rb') as f:
- spell_cache = pickle.load(f)
- else:
- spell_cache = set()
-
- print("Generating POT file {}…".format(FILE_NAME_POT))
- msgs, states = gen_empty_pot()
- tot_messages, _a = merge_messages(msgs, states, messages,
- True, spell_cache)
-
- # add messages collected automatically from RNA
- print("\tMerging RNA messages from {}…".format(FILE_NAME_MESSAGES))
- messages = utils.new_messages()
- with open(FILE_NAME_MESSAGES, encoding="utf-8") as f:
- srcs = []
- context = ""
- for line in f:
- line = utils.stripeol(line)
-
- if line.startswith(COMMENT_PREFIX):
- srcs.append(line[len(COMMENT_PREFIX):].strip())
- elif line.startswith(CONTEXT_PREFIX):
- context = line[len(CONTEXT_PREFIX):].strip()
- else:
- key = (context, line)
- messages[key] = srcs
- srcs = []
- context = ""
- num_added, num_present = merge_messages(msgs, states, messages,
- True, spell_cache)
- tot_messages += num_added
- print("\tMerged {} messages ({} were already present)."
- "".format(num_added, num_present))
-
- print("\tAdding languages labels...")
- messages = {(CONTEXT_DEFAULT, lng[1]):
- ("Languages’ labels from bl_i18n_utils/settings.py",)
- for lng in LANGUAGES}
- messages.update({(CONTEXT_DEFAULT, cat[1]):
- ("Language categories’ labels from bl_i18n_utils/settings.py",)
- for cat in LANGUAGES_CATEGORIES})
- num_added, num_present = merge_messages(msgs, states, messages,
- True, spell_cache)
- tot_messages += num_added
- print("\tAdded {} language messages.".format(num_added))
-
- # Write back all messages into blender.pot.
- utils.write_messages(FILE_NAME_POT, msgs, states["comm_msg"],
- states["fuzzy_msg"])
-
- if SPELL_CACHE and spell_cache:
- with open(SPELL_CACHE, 'wb') as f:
- pickle.dump(spell_cache, f)
-
- print("Finished, total: {} messages!".format(tot_messages - 1))
-
- return 0
-
-
-if __name__ == "__main__":
- print("\n\n *** Running {} *** \n".format(__file__))
- sys.exit(main())
diff --git a/release/scripts/modules/bl_i18n_utils/update_trunk.py b/release/scripts/modules/bl_i18n_utils/update_trunk.py
deleted file mode 100755
index b84a227ae0a..00000000000
--- a/release/scripts/modules/bl_i18n_utils/update_trunk.py
+++ /dev/null
@@ -1,162 +0,0 @@
-#!/usr/bin/python3
-
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public 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>
-
-# Update trunk from branches:
-# * Remove po’s in trunk.
-# * Copy po’s from branches advanced enough.
-# * Clean po’s in trunk.
-# * Compile po’s in trunk in mo’s, keeping track of those failing.
-# * Remove po’s, mo’s (and their dir’s) that failed to compile or
-# are no more present in trunk.
-
-import subprocess
-import os
-import sys
-import shutil
-
-try:
- import settings
- import utils
-except:
- from . import (settings, utils)
-
-BRANCHES_DIR = settings.BRANCHES_DIR
-TRUNK_PO_DIR = settings.TRUNK_PO_DIR
-TRUNK_MO_DIR = settings.TRUNK_MO_DIR
-
-LANGUAGES_CATEGORIES = settings.LANGUAGES_CATEGORIES
-LANGUAGES = settings.LANGUAGES
-LANGUAGES_FILE = settings.LANGUAGES_FILE
-
-PY3 = settings.PYTHON3_EXEC
-
-
-def find_matching_po(languages, stats):
- """Match languages defined in LANGUAGES setting to relevant po, if possible!"""
- ret = []
- for uid, label, org_key in languages:
- key = org_key
- if key not in stats:
- # Try to simplify the key (eg from es_ES to es).
- if '_' in org_key:
- key = org_key[0:org_key.index('_')]
- if '@' in org_key:
- key = key + org_key[org_key.index('@'):]
- if key in stats:
- ret.append((stats[key], uid, label, org_key))
- else:
- # Mark invalid entries, so that we can put them in the languages file,
- # but commented!
- ret.append((0.0, -uid, label, org_key))
- return ret
-
-def main():
- import argparse
- parser = argparse.ArgumentParser(description=""
- "Update trunk from branches:\n"
- "* Remove po’s in trunk.\n"
- "* Copy po’s from branches advanced enough.\n"
- "* Clean po’s in trunk.\n"
- "* Compile po’s in trunk in mo’s, keeping track of those failing.\n"
- "* Remove po’s and mo’s (and their dir’s) that "
- "failed to compile or are no more present in trunk."
- "* Generate languages file used by Blender's i18n.")
- parser.add_argument('-t', '--threshold', type=int, help="Import threshold, as a percentage.")
- parser.add_argument('-p', '--po', action="store_true", help="Remove failing po’s.")
- parser.add_argument('-m', '--mo', action="store_true", help="Remove failing mo’s.")
- parser.add_argument('langs', metavar='ISO_code', nargs='*', help="Restrict processed languages to those.")
- args = parser.parse_args()
-
- ret = 0
- failed = set()
-
- # Remove po’s in trunk.
- for po in os.listdir(TRUNK_PO_DIR):
- if po.endswith(".po"):
- lang = os.path.basename(po)[:-3]
- if args.langs and lang not in args.langs:
- continue
- po = os.path.join(TRUNK_PO_DIR, po)
- os.remove(po)
-
- # Copy po’s from branches.
- cmd = [PY3, "./import_po_from_branches.py", "-s"]
- if args.threshold is not None:
- cmd += ["-t", str(args.threshold)]
- if args.langs:
- cmd += args.langs
- t = subprocess.call(cmd)
- if t:
- ret = t
-
- # Add in failed all mo’s no more having relevant po’s in trunk.
- for lang in os.listdir(TRUNK_MO_DIR):
- if lang in {".svn", LANGUAGES_FILE}:
- continue # !!!
- if not os.path.exists(os.path.join(TRUNK_PO_DIR, ".".join((lang, "po")))):
- failed.add(lang)
-
- # Check and compile each po separately, to keep track of those failing.
- # XXX There should not be any failing at this stage, import step is
- # supposed to have already filtered them out!
- for po in os.listdir(TRUNK_PO_DIR):
- if po.endswith(".po") and not po.endswith("_raw.po"):
- lang = os.path.basename(po)[:-3]
- if args.langs and lang not in args.langs:
- continue
-
- cmd = [PY3, "./clean_po.py", "-t", "-s", lang]
- t = subprocess.call(cmd)
- if t:
- ret = t
- failed.add(lang)
- continue
-
- cmd = [PY3, "./update_mo.py", lang]
- t = subprocess.call(cmd)
- if t:
- ret = t
- failed.add(lang)
- continue
-
- # Generate languages file used by Blender's i18n system.
- cmd = [PY3, "./update_languages_menu.py"]
- t = subprocess.call(cmd)
- if t:
- ret = t
-
- # Remove failing po’s, mo’s and related dir’s.
- for lang in failed:
- print("Lang “{}†failed, removing it...".format(lang))
- if args.po:
- po = os.path.join(TRUNK_PO_DIR, ".".join((lang, "po")))
- if os.path.exists(po):
- os.remove(po)
- if args.mo:
- mo = os.path.join(TRUNK_MO_DIR, lang)
- if os.path.exists(mo):
- shutil.rmtree(mo)
-
-
-if __name__ == "__main__":
- print("\n\n *** Running {} *** \n".format(__file__))
- sys.exit(main())
diff --git a/release/scripts/modules/bl_i18n_utils/utils.py b/release/scripts/modules/bl_i18n_utils/utils.py
index 9481f750092..4ab92880bde 100644
--- a/release/scripts/modules/bl_i18n_utils/utils.py
+++ b/release/scripts/modules/bl_i18n_utils/utils.py
@@ -20,357 +20,1398 @@
# Some misc utilities...
+import collections
+import concurrent.futures
+import copy
+import hashlib
import os
+import re
+import struct
import sys
-import collections
+import tempfile
+#import time
-from bl_i18n_utils import settings
+from bl_i18n_utils import (settings,
+ utils_rtl,
+ )
+import bpy
-COMMENT_PREFIX = settings.COMMENT_PREFIX
-WARN_NC = settings.WARN_MSGID_NOT_CAPITALIZED
-NC_ALLOWED = settings.WARN_MSGID_NOT_CAPITALIZED_ALLOWED
+##### Misc Utils #####
+from bpy.app.translations import locale_explode
-def stripeol(s):
- return s.rstrip("\n\r")
+_valid_po_path_re = re.compile(r"^\S+:[0-9]+$")
+def is_valid_po_path(path):
+ return bool(_valid_po_path_re.match(path))
-# XXX For now, we assume that all messages > 30 chars are tooltips!
-def is_tooltip(msgid):
- return len(msgid) > 30
+def get_best_similar(data):
+ import difflib
+ key, use_similar, similar_pool = data
-def new_messages():
- return getattr(collections, 'OrderedDict', dict)()
+ # try to find some close key in existing messages...
+ # Optimized code inspired by difflib.get_close_matches (as we only need the best match).
+ # We also consider to never make a match when len differs more than -len_key / 2, +len_key * 2 (which is valid
+ # as long as use_similar is not below ~0.7).
+ # Gives an overall ~20% of improvement!
+ #tmp = difflib.get_close_matches(key[1], similar_pool, n=1, cutoff=use_similar)
+ #if tmp:
+ #tmp = tmp[0]
+ tmp = None
+ s = difflib.SequenceMatcher()
+ s.set_seq2(key[1])
+ len_key = len(key[1])
+ min_len = len_key // 2
+ max_len = len_key * 2
+ for x in similar_pool:
+ if min_len < len(x) < max_len:
+ s.set_seq1(x)
+ if s.real_quick_ratio() >= use_similar and s.quick_ratio() >= use_similar:
+ sratio = s.ratio()
+ if sratio >= use_similar:
+ tmp = x
+ use_similar = sratio
+ return key, tmp
-def parse_messages(fname):
+def locale_match(loc1, loc2):
"""
- Returns a tupple (messages, states, stats).
- messages is an odereddict of dicts
- {(ctxt, msgid): {msgid_lines:, msgstr_lines:,
- comment_lines:, msgctxt_lines:}}.
- states is a dict of three sets of (msgid, ctxt), and a boolean flag
- indicating the .po is somewhat broken
- {trans_msg:, fuzzy_msg:, comm_msg:, is_broken:}.
- stats is a dict of values
- {tot_msg:, trans_msg:, tot_ttips:, trans_ttips:, comm_msg:,
- nbr_signs:, nbr_trans_signs:, contexts: set()}.
- Note: This function will silently "arrange" mis-formated entries, thus
- using afterward write_messages() should always produce a po-valid file,
- though not correct!
+ Return:
+ -n if loc1 is a subtype of loc2 (e.g. 'fr_FR' is a subtype of 'fr').
+ +n if loc2 is a subtype of loc1.
+ n becomes smaller when both locales are more similar (e.g. (sr, sr_SR) are more similar than (sr, sr_SR@latin)).
+ 0 if they are exactly the same.
+ ... (Ellipsis) if they cannot match!
+ Note: We consider that 'sr_SR@latin' is a subtype of 'sr@latin', 'sr_SR' and 'sr', but 'sr_SR' and 'sr@latin' won't
+ match (will return ...)!
+ Note: About similarity, diff in variants are more important than diff in countries, currently here are the cases:
+ (sr, sr_SR) -> 1
+ (sr@latin, sr_SR@latin) -> 1
+ (sr, sr@latin) -> 2
+ (sr_SR, sr_SR@latin) -> 2
+ (sr, sr_SR@latin) -> 3
"""
- tot_messages = 0
- tot_tooltips = 0
- trans_messages = 0
- trans_tooltips = 0
- comm_messages = 0
- nbr_signs = 0
- nbr_trans_signs = 0
- contexts = set()
- reading_msgid = False
- reading_msgstr = False
- reading_msgctxt = False
- reading_comment = False
- is_translated = False
- is_fuzzy = False
- is_commented = False
- is_broken = False
- msgid_lines = []
- msgstr_lines = []
- msgctxt_lines = []
- comment_lines = []
-
- messages = new_messages()
- translated_messages = set()
- fuzzy_messages = set()
- commented_messages = set()
-
- def clean_vars():
- nonlocal reading_msgid, reading_msgstr, reading_msgctxt, \
- reading_comment, is_fuzzy, is_translated, is_commented, \
- msgid_lines, msgstr_lines, msgctxt_lines, comment_lines
- reading_msgid = reading_msgstr = reading_msgctxt = \
- reading_comment = False
- is_tooltip = is_fuzzy = is_translated = is_commented = False
+ if loc1 == loc2:
+ return 0
+ l1, c1, v1, *_1 = locale_explode(loc1)
+ l2, c2, v2, *_2 = locale_explode(loc2)
+
+ if l1 == l2:
+ if c1 == c2:
+ if v1 == v2:
+ return 0
+ elif v2 is None:
+ return -2
+ elif v1 is None:
+ return 2
+ return ...
+ elif c2 is None:
+ if v1 == v2:
+ return -1
+ elif v2 is None:
+ return -3
+ return ...
+ elif c1 is None:
+ if v1 == v2:
+ return 1
+ elif v1 is None:
+ return 3
+ return ...
+ return ...
+
+
+##### Main Classes #####
+
+class I18nMessage:
+ """
+ Internal representation of a message.
+ """
+ __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=[],
+ 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.is_fuzzy = is_fuzzy
+ self.is_commented = is_commented
+
+ def _get_msgctxt(self):
+ return "".join(self.msgctxt_lines)
+ def _set_msgctxt(self, ctxt):
+ self.msgctxt_lines = [ctxt]
+ msgctxt = property(_get_msgctxt, _set_msgctxt)
+
+ def _get_msgid(self):
+ return "".join(self.msgid_lines)
+ def _set_msgid(self, msgid):
+ self.msgid_lines = [msgid]
+ msgid = property(_get_msgid, _set_msgid)
+
+ def _get_msgstr(self):
+ return "".join(self.msgstr_lines)
+ def _set_msgstr(self, msgstr):
+ self.msgstr_lines = [msgstr]
+ msgstr = property(_get_msgstr, _set_msgstr)
+
+ def _get_sources(self):
+ lstrip1 = len(self.settings.PO_COMMENT_PREFIX_SOURCE)
+ lstrip2 = len(self.settings.PO_COMMENT_PREFIX_SOURCE_CUSTOM)
+ return ([l[lstrip1:] for l in self.comment_lines if l.startswith(self.settings.PO_COMMENT_PREFIX_SOURCE)] +
+ [l[lstrip2:] for l in self.comment_lines
+ if l.startswith(self.settings.PO_COMMENT_PREFIX_SOURCE_CUSTOM)])
+ def _set_sources(self, sources):
+ cmmlines = self.comment_lines.copy()
+ for l in cmmlines:
+ if (l.startswith(self.settings.PO_COMMENT_PREFIX_SOURCE) or
+ l.startswith(self.settings.PO_COMMENT_PREFIX_SOURCE_CUSTOM)):
+ self.comment_lines.remove(l)
+ lines_src = []
+ lines_src_custom = []
+ for src in sources:
+ if is_valid_po_path(src):
+ lines_src.append(self.settings.PO_COMMENT_PREFIX_SOURCE + src)
+ else:
+ lines_src_custom.append(self.settings.PO_COMMENT_PREFIX_SOURCE_CUSTOM + src)
+ self.comment_lines += lines_src_custom + lines_src
+ sources = property(_get_sources, _set_sources)
+
+ def _get_is_tooltip(self):
+ # XXX For now, we assume that all messages > 30 chars are tooltips!
+ return len(self.msgid) > 30
+ is_tooltip = property(_get_is_tooltip)
+
+ def copy(self):
+ # Deepcopy everything but the settings!
+ return self.__class__(msgctxt_lines=self.msgctxt_lines[:], msgid_lines=self.msgid_lines[:],
+ msgstr_lines=self.msgstr_lines[:], comment_lines=self.comment_lines[:],
+ is_commented=self.is_commented, is_fuzzy=self.is_fuzzy, settings=self.settings)
+
+ def normalize(self, max_len=80):
+ """
+ Normalize this message, call this before exporting it...
+ Currently normalize msgctxt, msgid and msgstr lines to given max_len (if below 1, make them single line).
+ """
+ max_len -= 2 # The two quotes!
+
+ def _splitlines(text):
+ lns = text.splitlines()
+ return [l + "\n" for l in lns[:-1]] + lns[-1:]
+
+ # We do not need the full power of textwrap... We just split first at escaped new lines, then into each line
+ # if needed... No word splitting, nor fancy spaces handling!
+ def _wrap(text, max_len, init_len):
+ if len(text) + init_len < max_len:
+ return [text]
+ lines = _splitlines(text)
+ ret = []
+ for l in lines:
+ tmp = []
+ cur_len = 0
+ words = l.split(' ')
+ for w in words:
+ cur_len += len(w) + 1
+ if cur_len > (max_len - 1) and tmp:
+ ret.append(" ".join(tmp) + " ")
+ del tmp[:]
+ cur_len = len(w) + 1
+ tmp.append(w)
+ if tmp:
+ ret.append(" ".join(tmp))
+ return ret
+
+ if max_len < 1:
+ self.msgctxt_lines = _splitlines(self.msgctxt)
+ self.msgid_lines = _splitlines(self.msgid)
+ self.msgstr_lines = _splitlines(self.msgstr)
+ else:
+ init_len = len(self.settings.PO_MSGCTXT) + 1
+ if self.is_commented:
+ init_len += len(self.settings.PO_COMMENT_PREFIX_MSG)
+ self.msgctxt_lines = _wrap(self.msgctxt, max_len, init_len)
+
+ init_len = len(self.settings.PO_MSGID) + 1
+ if self.is_commented:
+ init_len += len(self.settings.PO_COMMENT_PREFIX_MSG)
+ self.msgid_lines = _wrap(self.msgid, max_len, init_len)
+
+ init_len = len(self.settings.PO_MSGSTR) + 1
+ if self.is_commented:
+ init_len += len(self.settings.PO_COMMENT_PREFIX_MSG)
+ self.msgstr_lines = _wrap(self.msgstr, max_len, init_len)
+
+ # Be sure comment lines are not duplicated (can happen with sources...).
+ tmp = []
+ for l in self.comment_lines:
+ if l not in tmp:
+ tmp.append(l)
+ self.comment_lines = tmp
+
+ _esc_quotes = re.compile(r'(?!<\\)((?:\\\\)*)"')
+ _unesc_quotes = re.compile(r'(?!<\\)((?:\\\\)*)\\"')
+ _esc_names = ("msgctxt_lines", "msgid_lines", "msgstr_lines")
+ _esc_names_all = _esc_names + ("comment_lines",)
+
+ @classmethod
+ def do_escape(cls, txt):
+ """Replace some chars by their escaped versions!"""
+ if "\n" in txt:
+ txt = txt.replace("\n", r"\n")
+ if "\t" in txt:
+ txt.replace("\t", r"\t")
+ if '"' in txt:
+ txt = cls._esc_quotes.sub(r'\1\"', txt)
+ return txt
+
+ @classmethod
+ def do_unescape(cls, txt):
+ """Replace escaped chars by real ones!"""
+ if r"\n" in txt:
+ txt = txt.replace(r"\n", "\n")
+ if r"\t" in txt:
+ txt = txt.replace(r"\t", "\t")
+ if r'\"' in txt:
+ txt = cls._unesc_quotes.sub(r'\1"', txt)
+ return txt
+
+ def escape(self, do_all=False):
+ names = self._esc_names_all if do_all else self._esc_names
+ for name in names:
+ setattr(self, name, [self.do_escape(l) for l in getattr(self, name)])
+
+ def unescape(self, do_all=True):
+ names = self._esc_names_all if do_all else self._esc_names
+ for name in names:
+ setattr(self, name, [self.do_unescape(l) for l in getattr(self, name)])
+
+
+class I18nMessages:
+ """
+ Internal representation of messages for one language (iso code), with additional stats info.
+ """
+
+ # Avoid parsing again!
+ # Keys should be (pseudo) file-names, values are tuples (hash, I18nMessages)
+ # Note: only used by po parser currently!
+ #_parser_cache = {}
+
+ def __init__(self, uid=None, kind=None, key=None, src=None, settings=settings):
+ self.settings = settings
+ self.uid = uid if uid is not None else settings.PARSER_TEMPLATE_ID
+ self.msgs = self._new_messages()
+ self.trans_msgs = set()
+ self.fuzzy_msgs = set()
+ self.comm_msgs = set()
+ self.ttip_msgs = set()
+ self.contexts = set()
+ self.nbr_msgs = 0
+ self.nbr_trans_msgs = 0
+ self.nbr_ttips = 0
+ self.nbr_trans_ttips = 0
+ self.nbr_comm_msgs = 0
+ self.nbr_signs = 0
+ self.nbr_trans_signs = 0
+ self.parsing_errors = []
+ if kind and src:
+ self.parse(kind, key, src)
+ self.update_info()
+
+ self._reverse_cache = None
+
+ @staticmethod
+ def _new_messages():
+ return getattr(collections, 'OrderedDict', dict)()
+
+ @classmethod
+ def gen_empty_messages(cls, uid, blender_ver, blender_rev, time, year, default_copyright=True, settings=settings):
+ """Generate an empty I18nMessages object (only header is present!)."""
+ fmt = settings.PO_HEADER_MSGSTR
+ msgstr = fmt.format(blender_ver=str(blender_ver), blender_rev=int(blender_rev), time=str(time), uid=str(uid))
+ comment = ""
+ if default_copyright:
+ comment = settings.PO_HEADER_COMMENT_COPYRIGHT.format(year=str(year))
+ comment = comment + settings.PO_HEADER_COMMENT
+
+ msgs = cls(uid=uid, settings=settings)
+ key = settings.PO_HEADER_KEY
+ msgs.msgs[key] = I18nMessage([key[0]], [key[1]], msgstr.split("\n"), comment.split("\n"),
+ False, False, settings=settings)
+ msgs.update_info()
+
+ return msgs
+
+ def normalize(self, max_len=80):
+ for msg in self.msgs.values():
+ msg.normalize(max_len)
+
+ def escape(self, do_all=False):
+ for msg in self.msgs.values():
+ msg.escape(do_all)
+
+ def unescape(self, do_all=True):
+ for msg in self.msgs.values():
+ msg.unescape(do_all)
+
+ def check(self, fix=False):
+ """
+ Check consistency between messages and their keys!
+ Check messages using format stuff are consistant between msgid and msgstr!
+ If fix is True, tries to fix the issues.
+ Return a list of found errors (empty if everything went OK!).
+ """
+ ret = []
+ default_context = self.settings.DEFAULT_CONTEXT
+ _format = re.compile("%[.0-9]*[tslfd]").findall
+ done_keys = set()
+ tmp = {}
+ rem = set()
+ for key, msg in self.msgs.items():
+ msgctxt, msgid, msgstr = msg.msgctxt, msg.msgid, msg.msgstr
+ real_key = (msgctxt or default_context, msgid)
+ if key != real_key:
+ ret.append("Error! msg's context/message do not match its key ({} / {})".format(real_key, key))
+ if real_key in self.msgs:
+ ret.append("Error! msg's real_key already used!")
+ if fix:
+ rem.add(real_key)
+ elif fix:
+ tmp[real_key] = msg
+ done_keys.add(key)
+ if '%' in msgid and msgstr and len(_format(msgid)) != len(_format(msgstr)):
+ ret.append("Error! msg's format entities are not matched in msgid and msgstr ({})".format(real_key))
+ if fix:
+ msg.msgstr = ""
+ for k in rem:
+ del self.msgs[k]
+ self.msgs.update(tmp)
+ return ret
+
+ def clean_commented(self):
+ self.update_info()
+ nbr = len(self.comm_msgs)
+ for k in self.comm_msgs:
+ del self.msgs[k]
+ return nbr
+
+ def rtl_process(self):
+ keys = []
+ trans = []
+ for k, m in self.msgs.items():
+ keys.append(k)
+ trans.append(m.msgstr)
+ trans = utils_rtl.log2vis(trans, self.settings)
+ for k, t in zip(keys, trans):
+ self.msgs[k].msgstr = t
+
+ def merge(self, replace=False, *args):
+ # TODO
+ pass
+
+ def update(self, ref, use_similar=None, keep_old_commented=True):
+ """
+ Update this I18nMessage with the ref one. Translations from ref are never used. Source comments from ref
+ completely replace current ones. If use_similar is not 0.0, it will try to match new messages in ref with an
+ existing one. Messages no more found in ref will be marked as commented if keep_old_commented is True,
+ or removed.
+ """
+ if use_similar is None:
+ use_similar = self.settings.SIMILAR_MSGID_THRESHOLD
+
+ similar_pool = {}
+ if use_similar > 0.0:
+ for key, msg in self.msgs.items():
+ if msg.msgstr: # No need to waste time with void translations!
+ similar_pool.setdefault(key[1], set()).add(key)
+
+ msgs = self._new_messages().fromkeys(ref.msgs.keys())
+ ref_keys = set(ref.msgs.keys())
+ org_keys = set(self.msgs.keys())
+ new_keys = ref_keys - org_keys
+ removed_keys = org_keys - ref_keys
+
+ # First process keys present in both org and ref messages.
+ for key in ref_keys - new_keys:
+ msg, refmsg = self.msgs[key], ref.msgs[key]
+ msg.sources = refmsg.sources
+ msg.is_commented = refmsg.is_commented
+ msgs[key] = msg
+
+ # Next process new keys.
+ if use_similar > 0.0:
+ with concurrent.futures.ProcessPoolExecutor() as exctr:
+ for key, msgid in exctr.map(get_best_similar,
+ tuple((nk, use_similar, tuple(similar_pool.keys())) for nk in new_keys)):
+ if msgid:
+ # Try to get the same context, else just get one...
+ skey = (key[0], msgid)
+ if skey not in similar_pool[msgid]:
+ skey = tuple(similar_pool[msgid])[0]
+ # We keep org translation and comments, and mark message as fuzzy.
+ msg, refmsg = self.msgs[skey].copy(), ref.msgs[key]
+ msg.msgctxt = refmsg.msgctxt
+ msg.msgid = refmsg.msgid
+ msg.sources = refmsg.sources
+ msg.is_fuzzy = True
+ msg.is_commented = refmsg.is_commented
+ msgs[key] = msg
+ else:
+ msgs[key] = ref.msgs[key]
+ else:
+ for key in new_keys:
+ msgs[key] = ref.msgs[key]
+
+ # Add back all "old" and already commented messages as commented ones, if required
+ # (and translation was not void!).
+ if keep_old_commented:
+ for key in removed_keys:
+ msgs[key] = self.msgs[key]
+ msgs[key].is_commented = True
+ msgs[key].sources = []
+
+ # Special 'meta' message, change project ID version and pot creation date...
+ key = self.settings.PO_HEADER_KEY
+ rep = []
+ markers = ("Project-Id-Version:", "POT-Creation-Date:")
+ for mrk in markers:
+ for rl in ref.msgs[key].msgstr_lines:
+ if rl.startswith(mrk):
+ for idx, ml in enumerate(msgs[key].msgstr_lines):
+ if ml.startswith(mrk):
+ rep.append((idx, rl))
+ for idx, txt in rep:
+ msgs[key].msgstr_lines[idx] = txt
+
+ # And finalize the update!
+ self.msgs = msgs
+
+ def update_info(self):
+ self.trans_msgs.clear()
+ self.fuzzy_msgs.clear()
+ self.comm_msgs.clear()
+ self.ttip_msgs.clear()
+ self.contexts.clear()
+ self.nbr_signs = 0
+ self.nbr_trans_signs = 0
+ for key, msg in self.msgs.items():
+ if key == self.settings.PO_HEADER_KEY:
+ continue
+ if msg.is_commented:
+ self.comm_msgs.add(key)
+ else:
+ if msg.msgstr:
+ self.trans_msgs.add(key)
+ if msg.is_fuzzy:
+ self.fuzzy_msgs.add(key)
+ if msg.is_tooltip:
+ self.ttip_msgs.add(key)
+ self.contexts.add(key[0])
+ self.nbr_signs += len(msg.msgid)
+ self.nbr_trans_signs += len(msg.msgstr)
+ self.nbr_msgs = len(self.msgs)
+ self.nbr_trans_msgs = len(self.trans_msgs - self.fuzzy_msgs)
+ self.nbr_ttips = len(self.ttip_msgs)
+ self.nbr_trans_ttips = len(self.ttip_msgs & (self.trans_msgs - self.fuzzy_msgs))
+ self.nbr_comm_msgs = len(self.comm_msgs)
+
+ def print_info(self, prefix="", output=print, print_stats=True, print_errors=True):
+ """
+ Print out some info about an I18nMessages object.
+ """
+ lvl = 0.0
+ lvl_ttips = 0.0
+ lvl_comm = 0.0
+ lvl_trans_ttips = 0.0
+ lvl_ttips_in_trans = 0.0
+ if self.nbr_msgs > 0:
+ lvl = float(self.nbr_trans_msgs) / float(self.nbr_msgs)
+ lvl_ttips = float(self.nbr_ttips) / float(self.nbr_msgs)
+ lvl_comm = float(self.nbr_comm_msgs) / float(self.nbr_msgs + self.nbr_comm_msgs)
+ if self.nbr_ttips > 0:
+ lvl_trans_ttips = float(self.nbr_trans_ttips) / float(self.nbr_ttips)
+ if self.nbr_trans_msgs > 0:
+ lvl_ttips_in_trans = float(self.nbr_trans_ttips) / float(self.nbr_trans_msgs)
+
+ lines = []
+ if print_stats:
+ lines += [
+ "",
+ "{:>6.1%} done! ({} translated messages over {}).\n"
+ "".format(lvl, self.nbr_trans_msgs, self.nbr_msgs),
+ "{:>6.1%} of messages are tooltips ({} over {}).\n"
+ "".format(lvl_ttips, self.nbr_ttips, self.nbr_msgs),
+ "{:>6.1%} of tooltips are translated ({} over {}).\n"
+ "".format(lvl_trans_ttips, self.nbr_trans_ttips, self.nbr_ttips),
+ "{:>6.1%} of translated messages are tooltips ({} over {}).\n"
+ "".format(lvl_ttips_in_trans, self.nbr_trans_ttips, self.nbr_trans_msgs),
+ "{:>6.1%} of messages are commented ({} over {}).\n"
+ "".format(lvl_comm, self.nbr_comm_msgs, self.nbr_comm_msgs + self.nbr_msgs),
+ "This translation is currently made of {} signs.\n".format(self.nbr_trans_signs)
+ ]
+ if print_errors and self.parsing_errors:
+ lines += ["WARNING! Errors during parsing:\n"]
+ lines += [" Around line {}: {}\n".format(line, error) for line, error in self.parsing_errors]
+ output(prefix.join(lines))
+
+ def invalidate_reverse_cache(self, rebuild_now=False):
+ """
+ Invalidate the reverse cache used by find_best_messages_matches.
+ """
+ self._reverse_cache = None
+ if rebuild_now:
+ src_to_msg, ctxt_to_msg, msgid_to_msg, msgstr_to_msg = {}, {}, {}, {}
+ for key, msg in self.msgs.items():
+ if msg.is_commented:
+ continue
+ ctxt, msgid = key
+ ctxt_to_msg.setdefault(ctxt, set()).add(key)
+ msgid_to_msg.setdefault(msgid, set()).add(key)
+ msgstr_to_msg.setdefault(msg.msgstr, set()).add(key)
+ for src in msg.sources:
+ src_to_msg.setdefault(src, set()).add(key)
+ self._reverse_cache = (src_to_msg, ctxt_to_msg, msgid_to_msg, msgstr_to_msg)
+
+ def find_best_messages_matches(self, msgs, msgmap, rna_ctxt, rna_struct_name, rna_prop_name, rna_enum_name):
+ """
+ Try to find the best I18nMessages (i.e. context/msgid pairs) for the given UI messages:
+ msgs: an object containing properties listed in msgmap's values.
+ msgmap: a dict of various messages to use for search:
+ {"but_label": subdict, "rna_label": subdict, "enum_label": subdict,
+ "but_tip": subdict, "rna_tip": subdict, "enum_tip": subdict}
+ each subdict being like that:
+ {"msgstr": id, "msgid": id, "msg_flags": id, "key": set()}
+ where msgstr and msgid are identifiers of string props in msgs (resp. translated and org message),
+ msg_flags is not used here, and key is a set of matching (msgctxt, msgid) keys for the item.
+ The other parameters are about the RNA element from which the strings come from, if it could be determined:
+ rna_ctxt: the labels' i18n context.
+ rna_struct_name, rna_prop_name, rna_enum_name: should be self-explanatory!
+ """
+ # Build helper mappings.
+ # Note it's user responsibility to know when to invalidate (and hence force rebuild) this cache!
+ if self._reverse_cache is None:
+ self.invalidate_reverse_cache(True)
+ src_to_msg, ctxt_to_msg, msgid_to_msg, msgstr_to_msg = self._reverse_cache
+
+ # print(len(src_to_msg), len(ctxt_to_msg), len(msgid_to_msg), len(msgstr_to_msg))
+
+ # Build RNA key.
+ src, src_rna, src_enum = bpy.utils.make_rna_paths(rna_struct_name, rna_prop_name, rna_enum_name)
+ print("src: ", src_rna, src_enum)
+
+ # Labels.
+ elbl = getattr(msgs, msgmap["enum_label"]["msgstr"])
+ if elbl:
+ # Enum items' labels have no i18n context...
+ k = ctxt_to_msg[self.settings.DEFAULT_CONTEXT].copy()
+ if elbl in msgid_to_msg:
+ k &= msgid_to_msg[elbl]
+ elif elbl in msgstr_to_msg:
+ k &= msgstr_to_msg[elbl]
+ else:
+ k = set()
+ # We assume if we already have only one key, it's the good one!
+ if len(k) > 1 and src_enum in src_to_msg:
+ k &= src_to_msg[src_enum]
+ msgmap["enum_label"]["key"] = k
+ rlbl = getattr(msgs, msgmap["rna_label"]["msgstr"])
+ #print("rna label: " + rlbl, rlbl in msgid_to_msg, rlbl in msgstr_to_msg)
+ if rlbl:
+ k = ctxt_to_msg[rna_ctxt].copy()
+ if k and rlbl in msgid_to_msg:
+ k &= msgid_to_msg[rlbl]
+ elif k and rlbl in msgstr_to_msg:
+ k &= msgstr_to_msg[rlbl]
+ else:
+ k = set()
+ # We assume if we already have only one key, it's the good one!
+ if len(k) > 1 and src_rna in src_to_msg:
+ k &= src_to_msg[src_rna]
+ msgmap["rna_label"]["key"] = k
+ blbl = getattr(msgs, msgmap["but_label"]["msgstr"])
+ blbls = [blbl]
+ if blbl.endswith(self.settings.NUM_BUTTON_SUFFIX):
+ # Num buttons report their label with a trailing ': '...
+ blbls.append(blbl[:-len(self.settings.NUM_BUTTON_SUFFIX)])
+ print("button label: " + blbl)
+ if blbl and elbl not in blbls and (rlbl not in blbls or rna_ctxt != self.settings.DEFAULT_CONTEXT):
+ # Always Default context for button label :/
+ k = ctxt_to_msg[self.settings.DEFAULT_CONTEXT].copy()
+ found = False
+ for bl in blbls:
+ if bl in msgid_to_msg:
+ k &= msgid_to_msg[bl]
+ found = True
+ break
+ elif bl in msgstr_to_msg:
+ k &= msgstr_to_msg[bl]
+ found = True
+ break
+ if not found:
+ k = set()
+ # XXX No need to check against RNA path here, if blabel is different
+ # from rlabel, should not match anyway!
+ msgmap["but_label"]["key"] = k
+
+ # Tips (they never have a specific context).
+ etip = getattr(msgs, msgmap["enum_tip"]["msgstr"])
+ #print("enum tip: " + etip)
+ if etip:
+ k = ctxt_to_msg[self.settings.DEFAULT_CONTEXT].copy()
+ if etip in msgid_to_msg:
+ k &= msgid_to_msg[etip]
+ elif etip in msgstr_to_msg:
+ k &= msgstr_to_msg[etip]
+ else:
+ k = set()
+ # We assume if we already have only one key, it's the good one!
+ if len(k) > 1 and src_enum in src_to_msg:
+ k &= src_to_msg[src_enum]
+ msgmap["enum_tip"]["key"] = k
+ rtip = getattr(msgs, msgmap["rna_tip"]["msgstr"])
+ #print("rna tip: " + rtip)
+ if rtip:
+ k = ctxt_to_msg[self.settings.DEFAULT_CONTEXT].copy()
+ if k and rtip in msgid_to_msg:
+ k &= msgid_to_msg[rtip]
+ elif k and rtip in msgstr_to_msg:
+ k &= msgstr_to_msg[rtip]
+ else:
+ k = set()
+ # We assume if we already have only one key, it's the good one!
+ if len(k) > 1 and src_rna in src_to_msg:
+ k &= src_to_msg[src_rna]
+ msgmap["rna_tip"]["key"] = k
+ #print(k)
+ btip = getattr(msgs, msgmap["but_tip"]["msgstr"])
+ #print("button tip: " + btip)
+ if btip and btip not in {rtip, etip}:
+ k = ctxt_to_msg[self.settings.DEFAULT_CONTEXT].copy()
+ if btip in msgid_to_msg:
+ k &= msgid_to_msg[btip]
+ elif btip in msgstr_to_msg:
+ k &= msgstr_to_msg[btip]
+ else:
+ k = set()
+ # XXX No need to check against RNA path here, if btip is different from rtip, should not match anyway!
+ msgmap["but_tip"]["key"] = k
+
+ def parse(self, kind, key, src):
+ del self.parsing_errors[:]
+ self.parsers[kind](self, src, key)
+ if self.parsing_errors:
+ print("{} ({}):".format(key, src))
+ self.print_info(print_stats=False)
+ print("The parser solved them as well as it could...")
+ self.update_info()
+
+ def parse_messages_from_po(self, src, key=None):
+ """
+ Parse a po file.
+ Note: This function will silently "arrange" mis-formated entries, thus using afterward write_messages() should
+ always produce a po-valid file, though not correct!
+ """
+ reading_msgid = False
+ reading_msgstr = False
+ reading_msgctxt = False
+ reading_comment = False
+ is_commented = False
+ is_fuzzy = False
+ msgctxt_lines = []
msgid_lines = []
msgstr_lines = []
- msgctxt_lines = []
comment_lines = []
- def finalize_message():
- nonlocal reading_msgid, reading_msgstr, reading_msgctxt, \
- reading_comment, is_fuzzy, is_translated, is_commented, \
- msgid_lines, msgstr_lines, msgctxt_lines, comment_lines, \
- messages, translated_messages, fuzzy_messages, \
- commented_messages, \
- tot_messages, tot_tooltips, trans_messages, trans_tooltips, \
- comm_messages, nbr_signs, nbr_trans_signs, contexts
-
- msgid = "".join(msgid_lines)
- msgctxt = "".join(msgctxt_lines)
- msgkey = (msgctxt, msgid)
- is_ttip = is_tooltip(msgid)
-
- # Never allow overriding existing msgid/msgctxt pairs!
- if msgkey in messages:
- clean_vars()
- return
+ default_context = self.settings.DEFAULT_CONTEXT
- nbr_signs += len(msgid)
- if is_commented:
- commented_messages.add(msgkey)
- elif is_fuzzy:
- fuzzy_messages.add(msgkey)
- elif is_translated:
- translated_messages.add(msgkey)
- nbr_trans_signs += len("".join(msgstr_lines))
- messages[msgkey] = {"msgid_lines" : msgid_lines,
- "msgstr_lines" : msgstr_lines,
- "comment_lines": comment_lines,
- "msgctxt_lines": msgctxt_lines}
-
- if is_commented:
- comm_messages += 1
- else:
- tot_messages += 1
- if is_ttip:
- tot_tooltips += 1
- if not is_fuzzy and is_translated:
- trans_messages += 1
- if is_ttip:
- trans_tooltips += 1
- if msgctxt not in contexts:
- contexts.add(msgctxt)
-
- clean_vars()
-
- with open(fname, 'r', encoding="utf-8") as f:
- for line_nr, line in enumerate(f):
- line = stripeol(line)
+ # Helper function
+ def finalize_message(self, line_nr):
+ nonlocal reading_msgid, reading_msgstr, reading_msgctxt, reading_comment
+ nonlocal is_commented, is_fuzzy, msgid_lines, msgstr_lines, msgctxt_lines, comment_lines
+
+ msgid = I18nMessage.do_unescape("".join(msgid_lines))
+ msgctxt = I18nMessage.do_unescape("".join(msgctxt_lines))
+ msgkey = (msgctxt or default_context, msgid)
+
+ # Never allow overriding existing msgid/msgctxt pairs!
+ if msgkey in self.msgs:
+ self.parsing_errors.append((line_nr, "{} context/msgid is already in current messages!".format(msgkey)))
+ return
+
+ self.msgs[msgkey] = I18nMessage(msgctxt_lines, msgid_lines, msgstr_lines, comment_lines,
+ is_commented, is_fuzzy, settings=self.settings)
+
+ # Let's clean up and get ready for next message!
+ reading_msgid = reading_msgstr = reading_msgctxt = reading_comment = False
+ is_commented = is_fuzzy = False
+ msgctxt_lines = []
+ msgid_lines = []
+ msgstr_lines = []
+ comment_lines = []
+
+ # try to use src as file name...
+ if os.path.isfile(src):
+ if os.stat(src).st_size > self.settings.PARSER_MAX_FILE_SIZE:
+ # Security, else we could read arbitrary huge files!
+ print("WARNING: skipping file {}, too huge!".format(src))
+ return
+ if not key:
+ key = src
+ with open(src, 'r', encoding="utf-8") as f:
+ src = f.read()
+
+ _msgctxt = self.settings.PO_MSGCTXT
+ _comm_msgctxt = self.settings.PO_COMMENT_PREFIX_MSG + _msgctxt
+ _len_msgctxt = len(_msgctxt + '"')
+ _len_comm_msgctxt = len(_comm_msgctxt + '"')
+ _msgid = self.settings.PO_MSGID
+ _comm_msgid = self.settings.PO_COMMENT_PREFIX_MSG + _msgid
+ _len_msgid = len(_msgid + '"')
+ _len_comm_msgid = len(_comm_msgid + '"')
+ _msgstr = self.settings.PO_MSGSTR
+ _comm_msgstr = self.settings.PO_COMMENT_PREFIX_MSG + _msgstr
+ _len_msgstr = len(_msgstr + '"')
+ _len_comm_msgstr = len(_comm_msgstr + '"')
+ _comm_str = self.settings.PO_COMMENT_PREFIX_MSG
+ _comm_fuzzy = self.settings.PO_COMMENT_FUZZY
+ _len_comm_str = len(_comm_str + '"')
+
+ # Main loop over all lines in src...
+ for line_nr, line in enumerate(src.splitlines()):
if line == "":
- finalize_message()
+ if reading_msgstr:
+ finalize_message(self, line_nr)
+ continue
- elif line.startswith("msgctxt") or \
- line.startswith("".join((COMMENT_PREFIX, "msgctxt"))):
+ elif line.startswith(_msgctxt) or line.startswith(_comm_msgctxt):
reading_comment = False
reading_ctxt = True
- if line.startswith(COMMENT_PREFIX):
+ if line.startswith(_comm_str):
is_commented = True
- line = line[9 + len(COMMENT_PREFIX):-1]
+ line = line[_len_comm_msgctxt:-1]
else:
- line = line[9:-1]
+ line = line[_len_msgctxt:-1]
msgctxt_lines.append(line)
- elif line.startswith("msgid") or \
- line.startswith("".join((COMMENT_PREFIX, "msgid"))):
+ elif line.startswith(_msgid) or line.startswith(_comm_msgid):
reading_comment = False
reading_msgid = True
- if line.startswith(COMMENT_PREFIX):
+ if line.startswith(_comm_str):
+ if not is_commented and reading_ctxt:
+ self.parsing_errors.append((line_nr, "commented msgid following regular msgctxt"))
is_commented = True
- line = line[7 + len(COMMENT_PREFIX):-1]
+ line = line[_len_comm_msgid:-1]
else:
- line = line[7:-1]
+ line = line[_len_msgid:-1]
+ reading_ctxt = False
msgid_lines.append(line)
- elif line.startswith("msgstr") or \
- line.startswith("".join((COMMENT_PREFIX, "msgstr"))):
+ elif line.startswith(_msgstr) or line.startswith(_comm_msgstr):
if not reading_msgid:
- is_broken = True
+ self.parsing_errors.append((line_nr, "msgstr without a prior msgid"))
else:
reading_msgid = False
reading_msgstr = True
- if line.startswith(COMMENT_PREFIX):
- line = line[8 + len(COMMENT_PREFIX):-1]
+ if line.startswith(_comm_str):
+ line = line[_len_comm_msgstr:-1]
if not is_commented:
- is_broken = True
+ self.parsing_errors.append((line_nr, "commented msgstr following regular msgid"))
else:
- line = line[8:-1]
+ line = line[_len_msgstr:-1]
if is_commented:
- is_broken = True
+ self.parsing_errors.append((line_nr, "regular msgstr following commented msgid"))
msgstr_lines.append(line)
- if line:
- is_translated = True
- elif line.startswith("#"):
- if reading_msgid:
- if is_commented:
- msgid_lines.append(line[1 + len(COMMENT_PREFIX):-1])
- else:
- msgid_lines.append(line)
- is_broken = True
- elif reading_msgstr:
- if is_commented:
- msgstr_lines.append(line[1 + len(COMMENT_PREFIX):-1])
- else:
- msgstr_lines.append(line)
- is_broken = True
+ elif line.startswith(_comm_str[0]):
+ if line.startswith(_comm_str):
+ if reading_msgctxt:
+ if is_commented:
+ msgctxt_lines.append(line[_len_comm_str:-1])
+ else:
+ msgctxt_lines.append(line)
+ self.parsing_errors.append((line_nr, "commented string while reading regular msgctxt"))
+ elif reading_msgid:
+ if is_commented:
+ msgid_lines.append(line[_len_comm_str:-1])
+ else:
+ msgid_lines.append(line)
+ self.parsing_errors.append((line_nr, "commented string while reading regular msgid"))
+ elif reading_msgstr:
+ if is_commented:
+ msgstr_lines.append(line[_len_comm_str:-1])
+ else:
+ msgstr_lines.append(line)
+ self.parsing_errors.append((line_nr, "commented string while reading regular msgstr"))
else:
- if line.startswith("#, fuzzy"):
+ if reading_msgctxt or reading_msgid or reading_msgstr:
+ self.parsing_errors.append((line_nr,
+ "commented string within msgctxt, msgid or msgstr scope, ignored"))
+ elif line.startswith(_comm_fuzzy):
is_fuzzy = True
else:
comment_lines.append(line)
reading_comment = True
else:
- if reading_msgid:
+ if reading_msgctxt:
+ msgctxt_lines.append(line[1:-1])
+ elif reading_msgid:
msgid_lines.append(line[1:-1])
elif reading_msgstr:
line = line[1:-1]
msgstr_lines.append(line)
- if not is_translated and line:
- is_translated = True
else:
- is_broken = True
+ self.parsing_errors.append((line_nr, "regular string outside msgctxt, msgid or msgstr scope"))
+ #self.parsing_errors += (str(comment_lines), str(msgctxt_lines), str(msgid_lines), str(msgstr_lines))
# If no final empty line, last message is not finalized!
if reading_msgstr:
- finalize_message()
-
- return (messages,
- {"trans_msg": translated_messages,
- "fuzzy_msg": fuzzy_messages,
- "comm_msg" : commented_messages,
- "is_broken": is_broken},
- {"tot_msg" : tot_messages,
- "trans_msg" : trans_messages,
- "tot_ttips" : tot_tooltips,
- "trans_ttips" : trans_tooltips,
- "comm_msg" : comm_messages,
- "nbr_signs" : nbr_signs,
- "nbr_trans_signs": nbr_trans_signs,
- "contexts" : contexts})
-
-
-def write_messages(fname, messages, commented, fuzzy):
- "Write in fname file the content of messages (similar to parse_messages " \
- "returned values). commented and fuzzy are two sets containing msgid. " \
- "Returns the number of written messages."
- num = 0
- with open(fname, 'w', encoding="utf-8") as f:
- for msgkey, val in messages.items():
- msgctxt, msgid = msgkey
- f.write("\n".join(val["comment_lines"]))
- # Only mark as fuzzy if msgstr is not empty!
- if msgkey in fuzzy and "".join(val["msgstr_lines"]):
- f.write("\n#, fuzzy")
- if msgkey in commented:
- if msgctxt:
- f.write("\n{}msgctxt \"".format(COMMENT_PREFIX))
- f.write("\"\n{}\"".format(COMMENT_PREFIX).join(
- val["msgctxt_lines"]))
- f.write("\"")
- f.write("\n{}msgid \"".format(COMMENT_PREFIX))
- f.write("\"\n{}\"".format(COMMENT_PREFIX).join(
- val["msgid_lines"]))
- f.write("\"\n{}msgstr \"".format(COMMENT_PREFIX))
- f.write("\"\n{}\"".format(COMMENT_PREFIX).join(
- val["msgstr_lines"]))
- f.write("\"\n\n")
- else:
- if msgctxt:
- f.write("\nmsgctxt \"")
- f.write("\"\n\"".join(val["msgctxt_lines"]))
- f.write("\"")
- f.write("\nmsgid \"")
- f.write("\"\n\"".join(val["msgid_lines"]))
- f.write("\"\nmsgstr \"")
- f.write("\"\n\"".join(val["msgstr_lines"]))
- f.write("\"\n\n")
- num += 1
- return num
-
-
-def gen_empty_messages(blender_rev, time_str, year_str):
- """Generate an empty messages & state data (only header if present!)."""
- header_key = ("", "")
-
- messages = new_messages()
- messages[header_key] = {
- "msgid_lines": [""],
- "msgctxt_lines": [],
- "msgstr_lines": [
- "Project-Id-Version: Blender r{}\\n"
- "".format(blender_rev),
- "Report-Msgid-Bugs-To: \\n",
- "POT-Creation-Date: {}\\n"
- "".format(time_str),
- "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n",
- "Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n",
- "Language-Team: LANGUAGE <LL@li.org>\\n",
- "Language: \\n",
- "MIME-Version: 1.0\\n",
- "Content-Type: text/plain; charset=UTF-8\\n",
- "Content-Transfer-Encoding: 8bit\\n"
- ],
- "comment_lines": [
- "# Blender's translation file (po format).",
- "# Copyright (C) {} The Blender Foundation."
- "".format(year_str),
- "# This file is distributed under the same "
- "# license as the Blender package.",
- "# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.",
- "#",
- ],
- }
+ finalize_message(self, line_nr)
+ self.unescape()
+
+ def write(self, kind, dest):
+ self.writers[kind](self, dest)
- states = {"trans_msg": set(),
- "fuzzy_msg": {header_key},
- "comm_msg": set(),
- "is_broken": False}
+ def write_messages_to_po(self, fname):
+ """
+ Write messages in fname po file.
+ """
+ default_context = self.settings.DEFAULT_CONTEXT
- return messages, states
+ def _write(self, f):
+ _msgctxt = self.settings.PO_MSGCTXT
+ _msgid = self.settings.PO_MSGID
+ _msgstr = self.settings.PO_MSGSTR
+ _comm = self.settings.PO_COMMENT_PREFIX_MSG
+ self.escape()
+
+ for num, msg in enumerate(self.msgs.values()):
+ f.write("\n".join(msg.comment_lines))
+ # Only mark as fuzzy if msgstr is not empty!
+ if msg.is_fuzzy and msg.msgstr:
+ f.write("\n" + self.settings.PO_COMMENT_FUZZY)
+ _p = _comm if msg.is_commented else ""
+ chunks = []
+ if msg.msgctxt and msg.msgctxt != default_context:
+ if len(msg.msgctxt_lines) > 1:
+ chunks += [
+ "\n" + _p + _msgctxt + "\"\"\n" + _p + "\"",
+ ("\"\n" + _p + "\"").join(msg.msgctxt_lines),
+ "\"",
+ ]
+ else:
+ chunks += ["\n" + _p + _msgctxt + "\"" + msg.msgctxt + "\""]
+ if len(msg.msgid_lines) > 1:
+ chunks += [
+ "\n" + _p + _msgid + "\"\"\n" + _p + "\"",
+ ("\"\n" + _p + "\"").join(msg.msgid_lines),
+ "\"",
+ ]
+ else:
+ chunks += ["\n" + _p + _msgid + "\"" + msg.msgid + "\""]
+ if len(msg.msgstr_lines) > 1:
+ chunks += [
+ "\n" + _p + _msgstr + "\"\"\n" + _p + "\"",
+ ("\"\n" + _p + "\"").join(msg.msgstr_lines),
+ "\"",
+ ]
+ else:
+ chunks += ["\n" + _p + _msgstr + "\"" + msg.msgstr + "\""]
+ chunks += ["\n\n"]
+ f.write("".join(chunks))
+
+ self.unescape()
+
+ 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)
+ # Else assume fname is already a file(like) object!
+ else:
+ _write(self, fname)
+
+ def write_messages_to_mo(self, fname):
+ """
+ Write messages in fname mo file.
+ """
+ # XXX Temp solution, until I can make own mo generator working...
+ import subprocess
+ with tempfile.NamedTemporaryFile(mode='w+', encoding="utf-8") as tmp_po_f:
+ self.write_messages_to_po(tmp_po_f)
+ cmd = (self.settings.GETTEXT_MSGFMT_EXECUTABLE,
+ "--statistics", # show stats
+ tmp_po_f.name,
+ "-o",
+ fname,
+ )
+ print("Running ", " ".join(cmd))
+ ret = subprocess.call(cmd)
+ print("Finished.")
+ return
+ # XXX Code below is currently broken (generates corrupted mo files it seems :( )!
+ # Using http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html notation.
+ # Not generating hash table!
+ # Only translated, unfuzzy messages are taken into account!
+ default_context = self.settings.DEFAULT_CONTEXT
+ msgs = tuple(v for v in self.msgs.values() if not (v.is_fuzzy or v.is_commented) and v.msgstr and v.msgid)
+ msgs = sorted(msgs[:2],
+ key=lambda e: (e.msgctxt + e.msgid) if (e.msgctxt and e.msgctxt != default_context) else e.msgid)
+ magic_nbr = 0x950412de
+ format_rev = 0
+ N = len(msgs)
+ O = 32
+ T = O + N * 8
+ S = 0
+ H = T + N * 8
+ # Prepare our data! we need key (optional context and msgid), translation, and offset and length of both.
+ # Offset are relative to start of their own list.
+ EOT = b"0x04" # Used to concatenate context and msgid
+ _msgid_offset = 0
+ _msgstr_offset = 0
+ def _gen(v):
+ nonlocal _msgid_offset, _msgstr_offset
+ msgid = v.msgid.encode("utf-8")
+ msgstr = v.msgstr.encode("utf-8")
+ if v.msgctxt and v.msgctxt != default_context:
+ msgctxt = v.msgctxt.encode("utf-8")
+ msgid = msgctxt + EOT + msgid
+ # Don't forget the final NULL char!
+ _msgid_len = len(msgid) + 1
+ _msgstr_len = len(msgstr) + 1
+ ret = ((msgid, _msgid_len, _msgid_offset), (msgstr, _msgstr_len, _msgstr_offset))
+ _msgid_offset += _msgid_len
+ _msgstr_offset += _msgstr_len
+ return ret
+ msgs = tuple(_gen(v) for v in msgs)
+ msgid_start = H
+ msgstr_start = msgid_start + _msgid_offset
+ print(N, msgstr_start + _msgstr_offset)
+ print(msgs)
+
+ with open(fname, 'wb') as f:
+ # Header...
+ f.write(struct.pack("=8I", magic_nbr, format_rev, N, O, T, S, H, 0))
+ # Msgid's length and offset.
+ f.write(b"".join(struct.pack("=2I", length, msgid_start + offset) for (_1, length, offset), _2 in msgs))
+ # Msgstr's length and offset.
+ f.write(b"".join(struct.pack("=2I", length, msgstr_start + offset) for _1, (_2, length, offset) in msgs))
+ # No hash table!
+ # Msgid's.
+ f.write(b"\0".join(msgid for (msgid, _1, _2), _3 in msgs) + b"\0")
+ # Msgstr's.
+ f.write(b"\0".join(msgstr for _1, (msgstr, _2, _3) in msgs) + b"\0")
+
+ parsers = {
+ "PO": parse_messages_from_po,
+ }
-def print_stats(stats, glob_stats=None, prefix=""):
+ writers = {
+ "PO": write_messages_to_po,
+ "MO": write_messages_to_mo,
+ }
+
+
+class I18n:
"""
- Print out some stats about a po file.
- glob_stats is for making global stats over several po's.
+ Internal representation of a whole translation set.
"""
- tot_msgs = stats["tot_msg"]
- trans_msgs = stats["trans_msg"]
- tot_ttips = stats["tot_ttips"]
- trans_ttips = stats["trans_ttips"]
- comm_msgs = stats["comm_msg"]
- nbr_signs = stats["nbr_signs"]
- nbr_trans_signs = stats["nbr_trans_signs"]
- contexts = stats["contexts"]
- lvl = lvl_ttips = lvl_trans_ttips = lvl_ttips_in_trans = lvl_comm = 0.0
-
- if tot_msgs > 0:
- lvl = float(trans_msgs) / float(tot_msgs)
- lvl_ttips = float(tot_ttips) / float(tot_msgs)
- lvl_comm = float(comm_msgs) / float(tot_msgs+comm_msgs)
- if tot_ttips > 0:
- lvl_trans_ttips = float(trans_ttips) / float(tot_ttips)
- if trans_msgs > 0:
- lvl_ttips_in_trans = float(trans_ttips) / float(trans_msgs)
-
- if glob_stats:
- glob_stats["nbr"] += 1.0
- glob_stats["lvl"] += lvl
- glob_stats["lvl_ttips"] += lvl_ttips
- glob_stats["lvl_trans_ttips"] += lvl_trans_ttips
- glob_stats["lvl_ttips_in_trans"] += lvl_ttips_in_trans
- glob_stats["lvl_comm"] += lvl_comm
- glob_stats["nbr_trans_signs"] += nbr_trans_signs
- if glob_stats["nbr_signs"] == 0:
- glob_stats["nbr_signs"] = nbr_signs
- glob_stats["contexts"] |= contexts
-
- lines = ("",
- "{:>6.1%} done! ({} translated messages over {}).\n"
- "".format(lvl, trans_msgs, tot_msgs),
- "{:>6.1%} of messages are tooltips ({} over {}).\n"
- "".format(lvl_ttips, tot_ttips, tot_msgs),
- "{:>6.1%} of tooltips are translated ({} over {}).\n"
- "".format(lvl_trans_ttips, trans_ttips, tot_ttips),
- "{:>6.1%} of translated messages are tooltips ({} over {}).\n"
- "".format(lvl_ttips_in_trans, trans_ttips, trans_msgs),
- "{:>6.1%} of messages are commented ({} over {}).\n"
- "".format(lvl_comm, comm_msgs, comm_msgs + tot_msgs),
- "This translation is currently made of {} signs.\n"
- "".format(nbr_trans_signs))
- print(prefix.join(lines))
- return 0
+
+ @staticmethod
+ def _parser_check_file(path, maxsize=settings.PARSER_MAX_FILE_SIZE, _begin_marker=None, _end_marker=None):
+ if os.stat(path).st_size > maxsize:
+ # Security, else we could read arbitrary huge files!
+ print("WARNING: skipping file {}, too huge!".format(path))
+ return None, None, None
+ txt = ""
+ with open(path) as f:
+ txt = f.read()
+ _in = 0
+ _out = len(txt)
+ if _begin_marker:
+ _in = None
+ if _begin_marker in txt:
+ _in = txt.index(_begin_marker) + len(_begin_marker)
+ if _end_marker:
+ _out = None
+ if _end_marker in txt:
+ _out = txt.index(_end_marker)
+ if _in is not None and _out is not None:
+ return txt[:_in], txt[_in:_out], txt[_out:]
+ return txt, None, None
+
+ @staticmethod
+ def _dst(self, path, uid, kind):
+ if kind == 'PO':
+ if uid == self.settings.PARSER_TEMPLATE_ID:
+ if not path.endswith(".pot"):
+ return os.path.join(os.path.dirname(path), "blender.pot")
+ if not path.endswith(".po"):
+ return os.path.join(os.path.dirname(path), uid + ".po")
+ elif kind == 'PY':
+ if not path.endswith(".py"):
+ if self.src.get(self.settings.PARSER_PY_ID):
+ return self.src[self.settings.PARSER_PY_ID]
+ return os.path.join(os.path.dirname(path), "translations.py")
+ return path
+
+ def __init__(self, kind=None, src=None, langs=set(), settings=settings):
+ self.settings = settings
+ self.trans = {}
+ self.src = {} # Should have the same keys as self.trans (plus PARSER_PY_ID for py file)!
+ self.dst = self._dst # A callable that transforms src_path into dst_path!
+ if kind and src:
+ self.parse(kind, src, langs)
+ self.update_info()
+
+ def _py_file_get(self):
+ return self.src.get(self.settings.PARSER_PY_ID)
+ def _py_file_set(self, value):
+ self.src[self.settings.PARSER_PY_ID] = value
+ py_file = property(_py_file_get, _py_file_set)
+
+ def escape(self, do_all=False):
+ for trans in self.trans.values():
+ trans.escape(do_all)
+
+ def unescape(self, do_all=True):
+ for trans in self.trans.values():
+ trans.unescape(do_all)
+
+ def update_info(self):
+ self.nbr_trans = 0
+ self.lvl = 0.0
+ self.lvl_ttips = 0.0
+ self.lvl_trans_ttips = 0.0
+ self.lvl_ttips_in_trans = 0.0
+ self.lvl_comm = 0.0
+ self.nbr_signs = 0
+ self.nbr_trans_signs = 0
+ self.contexts = set()
+
+ if self.settings.PARSER_TEMPLATE_ID in self.trans:
+ self.nbr_trans = len(self.trans) - 1
+ self.nbr_signs = self.trans[self.settings.PARSER_TEMPLATE_ID].nbr_signs
+ else:
+ self.nbr_trans = len(self.trans)
+ for msgs in self.trans.values():
+ msgs.update_info()
+ if msgs.nbr_msgs > 0:
+ self.lvl += float(msgs.nbr_trans_msgs) / float(msgs.nbr_msgs)
+ self.lvl_ttips += float(msgs.nbr_ttips) / float(msgs.nbr_msgs)
+ self.lvl_comm += float(msgs.nbr_comm_msgs) / float(msgs.nbr_msgs + msgs.nbr_comm_msgs)
+ if msgs.nbr_ttips > 0:
+ self.lvl_trans_ttips = float(msgs.nbr_trans_ttips) / float(msgs.nbr_ttips)
+ if msgs.nbr_trans_msgs > 0:
+ self.lvl_ttips_in_trans = float(msgs.nbr_trans_ttips) / float(msgs.nbr_trans_msgs)
+ if self.nbr_signs == 0:
+ self.nbr_signs = msgs.nbr_signs
+ self.nbr_trans_signs += msgs.nbr_trans_signs
+ self.contexts |= msgs.contexts
+
+ def print_stats(self, prefix="", print_msgs=True):
+ """
+ Print out some stats about an I18n object.
+ If print_msgs is True, it will also print all its translations' stats.
+ """
+ if print_msgs:
+ msgs_prefix = prefix + " "
+ for key, msgs in self.trans.items():
+ if key == self.settings.PARSER_TEMPLATE_ID:
+ continue
+ print(prefix + key + ":")
+ msgs.print_stats(prefix=msgs_prefix)
+ print(prefix)
+
+ nbr_contexts = len(self.contexts - {bpy.app.translations.contexts.default})
+ if nbr_contexts != 1:
+ if nbr_contexts == 0:
+ nbr_contexts = "No"
+ _ctx_txt = "s are"
+ else:
+ _ctx_txt = " is"
+ lines = (("",
+ "Average stats for all {} translations:\n".format(self.nbr_trans),
+ " {:>6.1%} done!\n".format(self.lvl / self.nbr_trans),
+ " {:>6.1%} of messages are tooltips.\n".format(self.lvl_ttips / self.nbr_trans),
+ " {:>6.1%} of tooltips are translated.\n".format(self.lvl_trans_ttips / self.nbr_trans),
+ " {:>6.1%} of translated messages are tooltips.\n".format(self.lvl_ttips_in_trans / self.nbr_trans),
+ " {:>6.1%} of messages are commented.\n".format(self.lvl_comm / self.nbr_trans),
+ " The org msgids are currently made of {} signs.\n".format(self.nbr_signs),
+ " All processed translations are currently made of {} signs.\n".format(self.nbr_trans_signs),
+ " {} specific context{} present:\n".format(self.nbr_contexts, _ctx_txt)) +
+ tuple(" " + c + "\n" for c in self.contexts - {bpy.app.translations.contexts.default}) +
+ ("\n",)
+ )
+ print(prefix.join(lines))
+
+ def parse(self, kind, src, langs=set()):
+ self.parsers[kind](self, src, langs)
+
+ def parse_from_po(self, src, langs=set()):
+ """
+ src must be a tuple (dir_of_pos, pot_file), where:
+ * dir_of_pos may either contains iso_CODE.po files, and/or iso_CODE/iso_CODE.po files.
+ * pot_file may be None (in which case there will be no ref messages).
+ if langs set is void, all languages found are loaded.
+ """
+ root_dir, pot_file = src
+ if pot_file and os.path.isfile(pot_file):
+ self.trans[self.settings.PARSER_TEMPLATE_ID] = I18nMessages(self.settings.PARSER_TEMPLATE_ID, 'PO',
+ pot_file, pot_file, settings=self.settings)
+ self.src_po[self.settings.PARSER_TEMPLATE_ID] = pot_file
+
+ for p in os.listdir(root_dir):
+ uid = po_file = None
+ if p.endswith(".po") and os.path.isfile(p):
+ uid = p[:-3]
+ if langs and uid not in langs:
+ continue
+ po_file = os.path.join(root_dir, p)
+ elif os.path.isdir(p):
+ uid = p
+ if langs and uid not in langs:
+ continue
+ po_file = os.path.join(root_dir, p, p + ".po")
+ if not os.path.isfile(po_file):
+ continue
+ else:
+ continue
+ if uid in self.trans:
+ printf("WARNING! {} id has been found more than once! only first one has been loaded!".format(uid))
+ continue
+ self.trans[uid] = I18nMessages(uid, 'PO', po_file, po_file, settings=self.settings)
+ self.src_po[uid] = po_file
+
+ def parse_from_py(self, src, langs=set()):
+ """
+ src must be a valid path, either a py file or a module directory (in which case all py files inside it
+ will be checked, first file macthing will win!).
+ if langs set is void, all languages found are loaded.
+ """
+ default_context = self.settings.DEFAULT_CONTEXT
+ txt = None
+ if os.path.isdir(src):
+ for root, dnames, fnames in os.walk(src):
+ for fname in fnames:
+ path = os.path.join(root, fname)
+ _1, txt, _2 = self._parser_check_file(path)
+ if txt is not None:
+ self.src[self.settings.PARSER_PY_ID] = path
+ break
+ if txt is not None:
+ break
+ elif src.endswith(".py") and os.path.isfile(src):
+ _1, txt, _2 = _check_file(src, self.settings.PARSER_PY_MARKER_BEGIN, self.settings.PARSER_PY_MARKER_END)
+ if txt is not None:
+ self.src[self.settings.PARSER_PY_ID] = src
+ if txt is None:
+ return
+ env = globals()
+ exec(txt, env)
+ if "translations_tuple" not in env:
+ return # No data...
+ msgs = env["translations_tuple"]
+ for key, (sources, gen_comments), *translations in msgs:
+ if self.settings.PARSER_TEMPLATE_ID not in self.trans:
+ self.trans[self.settings.PARSER_TEMPLATE_ID] = I18nMessages(self.settings.PARSER_TEMPLATE_ID,
+ settings=self.settings)
+ self.src[self.settings.PARSER_TEMPLATE_ID] = self.src[self.settings.PARSER_PY_ID]
+ if key in self.trans[self.settings.PARSER_TEMPLATE_ID].msgs:
+ print("ERROR! key {} is defined more than once! Skipping re-definitions!")
+ continue
+ custom_src = [c for c in sources if c.startswith("bpy.")]
+ src = [c for c in sources if not c.startswith("bpy.")]
+ common_comment_lines = [self.settings.PO_COMMENT_PREFIX_GENERATED + c for c in gen_comments] + \
+ [self.settings.PO_COMMENT_PREFIX_SOURCE_CUSTOM + c for c in custom_src] + \
+ [self.settings.PO_COMMENT_PREFIX_SOURCE + c for c in src]
+ ctxt = [key[0]] if key[0] else [default_context]
+ self.trans[self.settings.PARSER_TEMPLATE_ID].msgs[key] = I18nMessage(ctxt, [key[1]], [""],
+ common_comment_lines, False, False,
+ settings=self.settings)
+ for uid, msgstr, (is_fuzzy, user_comments) in translations:
+ if uid not in self.trans:
+ self.trans[uid] = I18nMessages(uid, settings=self.settings)
+ self.src[uid] = self.src[self.settings.PARSER_PY_ID]
+ comment_lines = [self.settings.PO_COMMENT_PREFIX + c for c in user_comments] + common_comment_lines
+ self.trans[uid].msgs[key] = I18nMessage(ctxt, [key[1]], [msgstr], comment_lines, False, is_fuzzy,
+ settings=self.settings)
+ self.unescape()
+
+ def write(self, kind, langs=set()):
+ self.writers[kind](self, langs)
+
+ def write_to_po(self, langs=set()):
+ """
+ Write all translations into po files. By default, write in the same files (or dir) as the source, specify
+ a custom self.dst function to write somewhere else!
+ Note: If langs is set and you want to export the pot template as well, langs must contain PARSER_TEMPLATE_ID
+ ({} currently).
+ """.format(self.settings.PARSER_TEMPLATE_ID)
+ keys = self.trans.keys()
+ if langs:
+ keys &= langs
+ for uid in keys:
+ dst = self.dst(self, self.src.get(uid, ""), uid, 'PO')
+ self.trans[uid].write('PO', dst)
+
+ def write_to_py(self, langs=set()):
+ """
+ Write all translations as python code, either in a "translations.py" file under same dir as source(s), or in
+ specified file is self.py_file is set (default, as usual can be customized with self.dst callable!).
+ Note: If langs is set and you want to export the pot template as well, langs must contain PARSER_TEMPLATE_ID
+ ({} currently).
+ """.format(self.settings.PARSER_TEMPLATE_ID)
+ default_context = self.settings.DEFAULT_CONTEXT
+ def _gen_py(self, langs, tab=" "):
+ _lencomm = len(self.settings.PO_COMMENT_PREFIX)
+ _lengen = len(self.settings.PO_COMMENT_PREFIX_GENERATED)
+ _lensrc = len(self.settings.PO_COMMENT_PREFIX_SOURCE)
+ _lencsrc = len(self.settings.PO_COMMENT_PREFIX_SOURCE_CUSTOM)
+ ret = [
+ "# NOTE: You can safely move around this auto-generated block (with the begin/end markers!), and "
+ "edit the translations by hand.",
+ "# Just carefully respect the format of the tuple!",
+ "",
+ "# Tuple of tuples "
+ "((msgctxt, msgid), (sources, gen_comments), (lang, translation, (is_fuzzy, comments)), ...)",
+ "translations_tuple = (",
+ ]
+ # First gather all keys (msgctxt, msgid) - theoretically, all translations should share the same, but...
+ keys = set()
+ for trans in self.trans.items:
+ keys |= trans.msgs.keys()
+ # Get the ref translation (ideally, PARSER_TEMPLATE_ID one, else the first one that pops up!
+ # Ref translation will be used to generate sources "comments"
+ ref = self.trans.get(self.settings.PARSER_TEMPLATE_ID) or self.trans[list(self.trans.keys())[0]]
+ # Get all languages (uids) and sort them (PARSER_TEMPLATE_ID excluded!)
+ translations = self.trans.keys() - {self.settings.PARSER_TEMPLATE_ID}
+ if langs:
+ translations &= langs
+ translations = [('"' + lng + '"', " " * len(lng) + 4, self.trans[lng]) for lng in sorted(translations)]
+ for key in keys:
+ if ref.msgs[key].is_commented:
+ continue
+ # Key (context + msgid).
+ msgctxt, msgid = key
+ if not msgctxt:
+ msgctxt = default_context
+ ret.append(tab + "(({}, \"{}\"),".format('"' + msgctxt + '"' if msgctxt else "None", msgid))
+ # Common comments (mostly sources!).
+ sources = []
+ gen_comments = []
+ for comment in ref.msgs[key].comment_lines:
+ if comment.startswith(self.settings.PO_COMMENT_PREFIX_SOURCE_CUSTOM):
+ sources.append(comment[_lencsrc:])
+ elif comment.startswith(self.settings.PO_COMMENT_PREFIX_SOURCE):
+ sources.append(comment[_lensrc:])
+ elif comment.startswith(self.settings.PO_COMMENT_PREFIX_GENERATED):
+ gen_comments.append(comment[_lengen:])
+ if not (sources or gen_comments):
+ ret.append(tab + " ((), ()),")
+ else:
+ if len(sources) > 1:
+ ret.append(tab + " ((\"" + sources[0] + "\",")
+ ret += [tab + " \"" + s + "\"," for s in sources[1:-1]]
+ ret.append(tab + " \"" + sources[-1] + "\"),")
+ else:
+ ret.append(tab + " ((" + ('"' + sources[0] + '",' if sources else "") + "),")
+ if len(gen_comments) > 1:
+ ret.append(tab + " (\"" + gen_comments[0] + "\",")
+ ret += [tab + " \"" + s + "\"," for s in gen_comments[1:-1]]
+ ret.append(tab + " \"" + gen_comments[-1] + "\")),")
+ else:
+ ret.append(tab + " (" + ('"' + gen_comments[0] + '",' if gen_comments else "") + ")),")
+ # All languages
+ for lngstr, lngsp, trans in translations:
+ if trans.msgs[key].is_commented:
+ continue
+ # Language code and translation.
+ ret.append(tab + " (" + lngstr + ", \"" + trans.msgs[key].msgstr + "\",")
+ # User comments and fuzzy.
+ comments = []
+ for comment in trans.msgs[key].comment_lines:
+ if comment.startswith(self.settings.PO_COMMENT_PREFIX):
+ comments.append(comment[_lencomm:])
+ ret.append(tab + lngsp + "(" + ("True" if trans.msgs[key].is_fuzzy else "False") + ",")
+ if len(comments) > 1:
+ ret.append(tab + lngsp + " (\"" + comments[0] + "\",")
+ ret += [tab + lngsp + " \"" + s + "\"," for s in comments[1:-1]]
+ ret.append(tab + lngsp + " \"" + comments[-1] + "\"))),")
+ else:
+ ret[-1] = ret[-1] + " " + ('"' + comments[0] + '",' if comments else "") + "))),"
+ ret.append(tab + "),")
+ ret += [
+ ")",
+ "",
+ "translations_dict = {}",
+ "for msg in translations_tuple:",
+ tab + "key = msg[0]",
+ tab + "for lang, trans, (is_fuzzy, comments) in msg[2:]:",
+ tab * 2 + "if trans and not is_fuzzy:",
+ tab * 3 + "translations_dict.setdefault(lang, {})[key] = trans",
+ "",
+ ]
+ return ret
+
+ self.escape(True)
+ dst = self.dst(self, self.src.get(self.settings.PARSER_PY_ID, ""), self.settings.PARSER_PY_ID, 'PY')
+ prev = txt = next = ""
+ if os.path.exists(dst):
+ if not os.path.isfile(dst):
+ print("WARNING: trying to write as python code into {}, which is not a file! Aborting.".format(dst))
+ return
+ prev, txt, next = self._parser_check_file(dst, self.settings.PARSER_MAX_FILE_SIZE,
+ self.settings.PARSER_PY_MARKER_BEGIN,
+ self.settings.PARSER_PY_MARKER_END)
+ if prev is None:
+ return
+ if txt is None:
+ print("WARNING: given python file {} has no auto-generated translations yet, will be added at "
+ "the end of the file, you can move that section later if needed...".format(dst))
+ txt = _gen_py(self, langs)
+ else:
+ printf("Creating python file {} containing translations.".format(dst))
+ txt = [
+ "# ***** BEGIN GPL LICENSE BLOCK *****",
+ "#",
+ "# This program is free software; you can redistribute it and/or",
+ "# modify it under the terms of the GNU General Public License",
+ "# as published by the Free Software Foundation; either version 2",
+ "# of the License, or (at your option) any later version.",
+ "#",
+ "# This program is distributed in the hope that it will be useful,",
+ "# but WITHOUT ANY WARRANTY; without even the implied warranty of",
+ "# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
+ "# GNU General Public License for more details.",
+ "#",
+ "# You should have received a copy of the GNU General Public 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 *****",
+ "",
+ self.settings.PARSER_PY_MARKER_BEGIN,
+ "",
+ ]
+ txt += _gen_py(self, langs)
+ txt += [
+ "",
+ self.settings.PARSER_PY_MARKER_END,
+ ]
+ with open(dst, 'w') as f:
+ f.write(prev + "\n".join(txt) + (next or ""))
+ self.unescape()
+
+ parsers = {
+ "PO": parse_from_po,
+ "PY": parse_from_py,
+ }
+
+ writers = {
+ "PO": write_to_po,
+ "PY": write_to_py,
+ }
diff --git a/release/scripts/modules/bl_i18n_utils/utils_languages_menu.py b/release/scripts/modules/bl_i18n_utils/utils_languages_menu.py
new file mode 100755
index 00000000000..789b1315659
--- /dev/null
+++ b/release/scripts/modules/bl_i18n_utils/utils_languages_menu.py
@@ -0,0 +1,96 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public 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>
+
+# Update "languages" text file used by Blender at runtime to build translations menu.
+
+
+import os
+
+
+OK = 0
+MISSING = 1
+TOOLOW = 2
+FORBIDDEN = 3
+FLAG_MESSAGES = {
+ OK: "",
+ MISSING: "No translation yet!",
+ TOOLOW: "Not enough advanced to be included...",
+ FORBIDDEN: "Explicitly forbidden!",
+}
+
+def gen_menu_file(stats, settings):
+ # Generate languages file used by Blender's i18n system.
+ # First, match all entries in LANGUAGES to a lang in stats, if possible!
+ tmp = []
+ for uid_num, label, uid, in settings.LANGUAGES:
+ if uid in stats:
+ if uid in settings.IMPORT_LANGUAGES_SKIP:
+ tmp.append((stats[uid], uid_num, label, uid, FORBIDDEN))
+ else:
+ tmp.append((stats[uid], uid_num, label, uid, OK))
+ else:
+ tmp.append((0.0, uid_num, label, uid, MISSING))
+ stats = tmp
+ limits = sorted(settings.LANGUAGES_CATEGORIES, key=lambda it: it[0], reverse=True)
+ idx = 0
+ stats = sorted(stats, key=lambda it: it[0], reverse=True)
+ langs_cats = [[] for i in range(len(limits))]
+ highest_uid = 0
+ for lvl, uid_num, label, uid, flag in stats:
+ if lvl < limits[idx][0]:
+ # Sub-sort languages by iso-codes.
+ langs_cats[idx].sort(key=lambda it: it[2])
+ idx += 1
+ if lvl < settings.IMPORT_MIN_LEVEL and flag == OK:
+ flag = TOOLOW
+ langs_cats[idx].append((uid_num, label, uid, flag))
+ if abs(uid_num) > highest_uid:
+ highest_uid = abs(uid_num)
+ # Sub-sort last group of languages by iso-codes!
+ langs_cats[idx].sort(key=lambda it: it[2])
+ data_lines = [
+ "# File used by Blender to know which languages (translations) are available, ",
+ "# and to generate translation menu.",
+ "#",
+ "# File format:",
+ "# ID:MENULABEL:ISOCODE",
+ "# ID must be unique, except for 0 value (marks categories for menu).",
+ "# Line starting with a # are comments!",
+ "#",
+ "# Automatically generated by bl_i18n_utils/update_languages_menu.py script.",
+ "# Highest ID currently in use: {}".format(highest_uid),
+ ]
+ for cat, langs_cat in zip(limits, langs_cats):
+ data_lines.append("#")
+ # Write "category menu label"...
+ if langs_cat:
+ data_lines.append("0:{}:".format(cat[1]))
+ else:
+ # Do not write the category if it has no language!
+ data_lines.append("# Void category! #0:{}:".format(cat[1]))
+ # ...and all matching language entries!
+ for uid_num, label, uid, flag in langs_cat:
+ if flag == OK:
+ data_lines.append("{}:{}:{}".format(uid_num, label, uid))
+ else:
+ # Non-existing, commented entry!
+ 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))
diff --git a/release/scripts/modules/bl_i18n_utils/rtl_preprocess.py b/release/scripts/modules/bl_i18n_utils/utils_rtl.py
index d28f87cf042..0544f93a262 100755
--- a/release/scripts/modules/bl_i18n_utils/rtl_preprocess.py
+++ b/release/scripts/modules/bl_i18n_utils/utils_rtl.py
@@ -36,18 +36,6 @@ import sys
import ctypes
import re
-try:
- import settings
- import utils
-except:
- from . import (settings, utils)
-
-
-FRIBIDI_LIB = settings.FRIBIDI_LIB
-
-###### Import C library and recreate "defines". #####
-fbd = ctypes.CDLL(FRIBIDI_LIB)
-
#define FRIBIDI_MASK_NEUTRAL 0x00000040L /* Is neutral */
FRIBIDI_PAR_ON = 0x00000040
@@ -80,12 +68,9 @@ FRIBIDI_FLAG_REMOVE_SPECIALS = 0x00040000
FRIBIDI_FLAG_SHAPE_ARAB_PRES = 0x00000100
FRIBIDI_FLAG_SHAPE_ARAB_LIGA = 0x00000200
-FRIBIDI_FLAGS_DEFAULT = FRIBIDI_FLAG_SHAPE_MIRRORING | \
- FRIBIDI_FLAG_REORDER_NSM | \
- FRIBIDI_FLAG_REMOVE_SPECIALS
+FRIBIDI_FLAGS_DEFAULT = FRIBIDI_FLAG_SHAPE_MIRRORING | FRIBIDI_FLAG_REORDER_NSM | FRIBIDI_FLAG_REMOVE_SPECIALS
-FRIBIDI_FLAGS_ARABIC = FRIBIDI_FLAG_SHAPE_ARAB_PRES | \
- FRIBIDI_FLAG_SHAPE_ARAB_LIGA
+FRIBIDI_FLAGS_ARABIC = FRIBIDI_FLAG_SHAPE_ARAB_PRES | FRIBIDI_FLAG_SHAPE_ARAB_LIGA
MENU_DETECT_REGEX = re.compile("%x\\d+\\|")
@@ -158,11 +143,13 @@ def protect_format_seq(msg):
return "".join(ret)
-def log2vis(msgs):
+def log2vis(msgs, settings):
"""
Globally mimics deprecated fribidi_log2vis.
msgs should be an iterable of messages to rtl-process.
"""
+ fbd = ctypes.CDLL(settings.FRIBIDI_LIB)
+
for msg in msgs:
msg = protect_format_seq(msg)
@@ -206,52 +193,3 @@ def log2vis(msgs):
# print(*(ord(c) for c in fbc_str))
yield fbc_str.value
-
-
-##### Command line stuff. #####
-def main():
- import argparse
- parser = argparse.ArgumentParser(description="" \
- "Preprocesses right-to-left languages.\n" \
- "You can use it either standalone, or through " \
- "import_po_from_branches or update_trunk.\n\n" \
- "Note: This has been tested on Linux, not 100% it will " \
- "work nicely on Windows or OsX.\n" \
- "Note: This uses ctypes, as there is no py3 binding for " \
- "fribidi currently. This implies you only need the " \
- "compiled C library to run it.\n" \
- "Note: It handles some formating/escape codes (like " \
- "\\\", %s, %x12, %.4f, etc.), protecting them from ugly " \
- "(evil) fribidi, which seems completely unaware of such " \
- "things (as unicode is...).")
- parser.add_argument('dst', metavar='dst.po',
- help="The dest po into which write the " \
- "pre-processed messages.")
- parser.add_argument('src', metavar='src.po',
- help="The po's to pre-process messages.")
- args = parser.parse_args()
-
- msgs, state, u1 = utils.parse_messages(args.src)
- if state["is_broken"]:
- print("Source po is BROKEN, aborting.")
- return 1
-
- keys = []
- trans = []
- for key, val in msgs.items():
- keys.append(key)
- trans.append("".join(val["msgstr_lines"]))
- trans = log2vis(trans)
- for key, trn in zip(keys, trans):
- # Mono-line for now...
- msgs[key]["msgstr_lines"] = [trn]
-
- utils.write_messages(args.dst, msgs, state["comm_msg"], state["fuzzy_msg"])
-
- print("RTL pre-process completed.")
- return 0
-
-
-if __name__ == "__main__":
- print("\n\n *** Running {} *** \n".format(__file__))
- sys.exit(main())
diff --git a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
new file mode 100644
index 00000000000..925166a3d8b
--- /dev/null
+++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py
@@ -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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+import enchant
+import os
+import pickle
+import re
+
+
+class SpellChecker():
+ """
+ A basic spell checker.
+ """
+
+ # These must be all lower case for comparisons
+ uimsgs = {
+ # OK words
+ "aren", # aren't
+ "betweens", # yuck! in-betweens!
+ "boolean", "booleans",
+ "couldn", # couldn't
+ "decrement",
+ "derivate",
+ "doesn", # doesn't
+ "fader",
+ "hasn", # hasn't
+ "hoc", # ad-hoc
+ "indices",
+ "iridas",
+ "isn", # isn't
+ "iterable",
+ "kyrgyz",
+ "latin",
+ "merchantability",
+ "mplayer",
+ "vertices",
+
+ # Merged words
+ "addon", "addons",
+ "antialiasing",
+ "arcsine", "arccosine", "arctangent",
+ "autoclip",
+ "autocomplete",
+ "autoname",
+ "autosave",
+ "autoscale",
+ "autosmooth",
+ "autosplit",
+ "backface", "backfacing",
+ "backimage",
+ "backscattered",
+ "bandnoise",
+ "bindcode",
+ "bitrate",
+ "blendfile",
+ "blendin",
+ "bonesize",
+ "boundbox",
+ "boxpack",
+ "buffersize",
+ "builtin", "builtins",
+ "bytecode",
+ "chunksize",
+ "customdata",
+ "dataset", "datasets",
+ "de",
+ "defocus",
+ "denoise",
+ "despill", "despilling",
+ "editcurve",
+ "editmesh",
+ "filebrowser",
+ "filelist",
+ "filename", "filenames",
+ "filepath", "filepaths",
+ "forcefield", "forcefields",
+ "fulldome", "fulldomes",
+ "fullscreen",
+ "gridline",
+ "hemi",
+ "inbetween",
+ "inscatter", "inscattering",
+ "libdata",
+ "lightless",
+ "localview",
+ "lookup", "lookups",
+ "mathutils",
+ "midlevel",
+ "midground",
+ "mixdown",
+ "multi",
+ "multifractal",
+ "multires", "multiresolution",
+ "multisampling",
+ "multitexture",
+ "multiuser",
+ "namespace",
+ "keyconfig",
+ "playhead",
+ "polyline",
+ "popup", "popups",
+ "pre",
+ "precache", "precaching",
+ "precalculate",
+ "prefetch",
+ "premultiply", "premultiplied",
+ "prepass",
+ "prepend",
+ "preprocess", "preprocessing",
+ "preseek",
+ "raytree",
+ "readonly",
+ "realtime",
+ "rekey",
+ "remesh",
+ "reprojection",
+ "resize",
+ "restpose",
+ "retarget", "retargets", "retargeting", "retargeted",
+ "ringnoise",
+ "rolloff",
+ "screencast", "screenshot", "screenshots",
+ "selfcollision",
+ "shadowbuffer", "shadowbuffers",
+ "singletexture",
+ "spellcheck", "spellchecking",
+ "startup",
+ "stateful",
+ "starfield",
+ "subflare", "subflares",
+ "subframe", "subframes",
+ "subclass", "subclasses", "subclassing",
+ "subdirectory", "subdirectories", "subdir", "subdirs",
+ "submodule", "submodules",
+ "subpath",
+ "subsize",
+ "substep", "substeps",
+ "targetless",
+ "textbox", "textboxes",
+ "tilemode",
+ "timestamp", "timestamps",
+ "timestep", "timesteps",
+ "todo",
+ "un",
+ "unbake",
+ "uncomment",
+ "undeformed",
+ "undistort", "undistortion",
+ "ungroup", "ungrouped",
+ "unhide",
+ "unindent",
+ "unkeyed",
+ "unpremultiply",
+ "unprojected",
+ "unreacted",
+ "unregister",
+ "unselected",
+ "unsubdivided", "unsubdivide",
+ "unshadowed",
+ "unspill",
+ "unstitchable",
+ "vectorscope",
+ "whitespace", "whitespaces",
+ "worldspace",
+ "workflow",
+
+ # Neologisms, slangs
+ "affectable",
+ "automagic", "automagically",
+ "blobby",
+ "blockiness", "blocky",
+ "collider", "colliders",
+ "deformer", "deformers",
+ "determinator",
+ "editability",
+ "keyer",
+ "lacunarity",
+ "numerics",
+ "occluder",
+ "passepartout",
+ "perspectively",
+ "pixelate",
+ "polygonization",
+ "selectability",
+ "slurph",
+ "stitchable",
+ "symmetrize",
+ "trackability",
+ "transmissivity",
+ "rasterized", "rasterization", "rasterizer",
+ "renderer", "renderable", "renderability",
+
+ # Abbreviations
+ "aero",
+ "amb",
+ "anim",
+ "bool",
+ "calc",
+ "config", "configs",
+ "const",
+ "coord", "coords",
+ "degr",
+ "dof",
+ "dupli", "duplis",
+ "eg",
+ "esc",
+ "expr",
+ "fac",
+ "fra",
+ "frs",
+ "grless",
+ "http",
+ "init",
+ "kbit", "kb",
+ "lang", "langs",
+ "lclick", "rclick",
+ "lensdist",
+ "loc", "rot", "pos",
+ "lorem",
+ "luma",
+ "mem",
+ "multicam",
+ "num",
+ "ok",
+ "orco",
+ "ortho",
+ "persp",
+ "pref", "prefs",
+ "prev",
+ "param",
+ "premul",
+ "quad", "quads",
+ "quat", "quats",
+ "recalc", "recalcs",
+ "refl",
+ "sce",
+ "sel",
+ "spec",
+ "struct", "structs",
+ "sys",
+ "tex",
+ "tri", "tris",
+ "uv", "uvs", "uvw", "uw", "uvmap",
+ "ve",
+ "vec",
+ "vel", # velocity!
+ "vert", "verts",
+ "vis",
+ "xyz", "xzy", "yxz", "yzx", "zxy", "zyx",
+ "xy", "xz", "yx", "yz", "zx", "zy",
+
+ # General computer/science terms
+ "boid", "boids",
+ "equisolid",
+ "euler", "eulers",
+ "fribidi",
+ "gettext",
+ "hashable",
+ "intrinsics",
+ "isosurface",
+ "jitter", "jittering", "jittered",
+ "keymap", "keymaps",
+ "lambertian",
+ "laplacian",
+ "metadata",
+ "msgfmt",
+ "nand", "xnor",
+ "normals",
+ "numpad",
+ "octree",
+ "opengl",
+ "pulldown", "pulldowns",
+ "quantized",
+ "samplerate",
+ "scrollback",
+ "scrollbar",
+ "scroller",
+ "searchable",
+ "spacebar",
+ "tooltip", "tooltips",
+ "trackpad",
+ "unicode",
+ "viewport", "viewports",
+ "viscoelastic",
+ "wildcard", "wildcards",
+
+ # General computer graphics terms
+ "anaglyph",
+ "bezier", "beziers",
+ "bicubic",
+ "bilinear",
+ "blackpoint", "whitepoint",
+ "blinn",
+ "bokeh",
+ "catadioptric",
+ "centroid",
+ "chrominance",
+ "codec", "codecs",
+ "collada",
+ "compositing",
+ "crossfade",
+ "deinterlace",
+ "dropoff",
+ "dv",
+ "eigenvectors",
+ "equirectangular",
+ "fisheye",
+ "framerate",
+ "gimbal",
+ "grayscale",
+ "icosphere",
+ "inpaint",
+ "lightmap",
+ "lossless", "lossy",
+ "matcap",
+ "midtones",
+ "mipmap", "mipmaps", "mip",
+ "ngon", "ngons",
+ "ntsc",
+ "nurb", "nurbs",
+ "perlin",
+ "phong",
+ "radiosity",
+ "raytrace", "raytracing", "raytraced",
+ "renderfarm",
+ "shader", "shaders",
+ "specular", "specularity",
+ "spillmap",
+ "sobel",
+ "tonemap",
+ "toon",
+ "timecode",
+ "voronoi",
+ "voxel", "voxels",
+ "wireframe",
+ "zmask",
+ "ztransp",
+
+ # Blender terms
+ "audaspace",
+ "bbone",
+ "breakdowner",
+ "bspline",
+ "bweight",
+ "colorband",
+ "datablock", "datablocks",
+ "despeckle",
+ "dopesheet",
+ "dupliface", "duplifaces",
+ "dupliframe", "dupliframes",
+ "dupliobject", "dupliob",
+ "dupligroup",
+ "duplivert",
+ "editbone",
+ "editmode",
+ "fcurve", "fcurves",
+ "fluidsim",
+ "frameserver",
+ "enum",
+ "keyframe", "keyframes", "keyframing", "keyframed",
+ "metaball", "metaballs",
+ "metaelement", "metaelements",
+ "metastrip", "metastrips",
+ "movieclip",
+ "mpoly",
+ "mtex",
+ "nabla",
+ "navmesh",
+ "outliner",
+ "paintmap", "paintmaps",
+ "polygroup", "polygroups",
+ "poselib",
+ "pushpull",
+ "pyconstraint", "pyconstraints",
+ "shapekey", "shapekeys",
+ "shrinkfatten",
+ "shrinkwrap",
+ "softbody",
+ "stucci",
+ "sunsky",
+ "subsurf",
+ "tessface", "tessfaces",
+ "texface",
+ "timeline", "timelines",
+ "tosphere",
+ "uilist",
+ "vcol", "vcols",
+ "vgroup", "vgroups",
+ "vinterlace",
+ "wetmap", "wetmaps",
+ "wpaint",
+ "uvwarp",
+
+ # Algorithm names
+ "beckmann",
+ "catmull",
+ "catrom",
+ "chebychev",
+ "courant",
+ "kutta",
+ "lennard",
+ "minkowski",
+ "minnaert",
+ "musgrave",
+ "nayar",
+ "netravali",
+ "oren",
+ "prewitt",
+ "runge",
+ "verlet",
+ "worley",
+
+ # Acronyms
+ "aa", "msaa",
+ "ao",
+ "api",
+ "asc", "cdl",
+ "ascii",
+ "atrac",
+ "bsdf",
+ "bw",
+ "ccd",
+ "cmd",
+ "cpus",
+ "ctrl",
+ "cw", "ccw",
+ "dev",
+ "djv",
+ "dpi",
+ "dvar",
+ "dx",
+ "eo",
+ "fh",
+ "fov",
+ "fft",
+ "futura",
+ "gfx",
+ "gl",
+ "glsl",
+ "gpl",
+ "gpu", "gpus",
+ "hc",
+ "hdc",
+ "hdr",
+ "hh", "mm", "ss", "ff", # hh:mm:ss:ff timecode
+ "hsv", "hsva",
+ "id",
+ "ior",
+ "itu",
+ "lhs",
+ "lmb", "mmb", "rmb",
+ "kb",
+ "mocap",
+ "msgid", "msgids",
+ "mux",
+ "ndof",
+ "ppc",
+ "precisa",
+ "px",
+ "qmc",
+ "rgb", "rgba",
+ "rhs",
+ "rv",
+ "sdl",
+ "sl",
+ "smpte",
+ "svn",
+ "ui",
+ "unix",
+ "vbo", "vbos",
+ "ycc", "ycca",
+ "yuv", "yuva",
+
+ # Blender acronyms
+ "bge",
+ "bli",
+ "bpy",
+ "bvh",
+ "dbvt",
+ "dop", # BLI K-Dop BVH
+ "ik",
+ "nla",
+ "py",
+ "qbvh",
+ "rna",
+ "rvo",
+ "simd",
+ "sph",
+ "svbvh",
+
+ # Files types/formats
+ "avi",
+ "attrac",
+ "autocad",
+ "autodesk",
+ "bmp",
+ "btx",
+ "cineon",
+ "dpx",
+ "dxf",
+ "eps",
+ "exr",
+ "fbx",
+ "ffmpeg",
+ "flac",
+ "gzip",
+ "ico",
+ "jpg", "jpeg",
+ "json",
+ "matroska",
+ "mdd",
+ "mkv",
+ "mpeg", "mjpeg",
+ "mtl",
+ "ogg",
+ "openjpeg",
+ "osl",
+ "oso",
+ "piz",
+ "png",
+ "po",
+ "quicktime",
+ "rle",
+ "sgi",
+ "stl",
+ "svg",
+ "targa", "tga",
+ "tiff",
+ "theora",
+ "vorbis",
+ "wav",
+ "xiph",
+ "xml",
+ "xna",
+ "xvid",
+ }
+
+ _valid_before = "(?<=[\\s*'\"`])|(?<=[a-zA-Z][/-])|(?<=^)"
+ _valid_after = "(?=[\\s'\"`.!?,;:])|(?=[/-]\\s*[a-zA-Z])|(?=$)"
+ _valid_words = "(?:{})(?:(?:[A-Z]+[a-z]*)|[A-Z]*|[a-z]*)(?:{})".format(_valid_before, _valid_after)
+ _split_words = re.compile(_valid_words).findall
+
+ @classmethod
+ def split_words(cls, text):
+ return [w for w in cls._split_words(text) if w]
+
+ def __init__(self, settings, lang="en_US"):
+ self.settings = settings
+ self.dict_spelling = enchant.Dict(lang)
+ self.cache = set(self.uimsgs)
+
+ cache = self.settings.SPELL_CACHE
+ if cache and os.path.exists(cache):
+ with open(cache, 'rb') as f:
+ self.cache |= set(pickle.load(f))
+
+ def __del__(self):
+ cache = self.settings.SPELL_CACHE
+ if cache and os.path.exists(cache):
+ with open(cache, 'wb') as f:
+ pickle.dump(self.cache, f)
+
+ def check(self, txt):
+ ret = []
+
+ if txt in self.cache:
+ return ret
+
+ for w in self.split_words(txt):
+ w_lower = w.lower()
+ if w_lower in self.cache:
+ continue
+ if not self.dict_spelling.check(w):
+ ret.append((w, self.dict_spelling.suggest(w)))
+ else:
+ self.cache.add(w_lower)
+
+ if not ret:
+ self.cache.add(txt)
+
+ return ret
diff --git a/release/scripts/modules/bpy/__init__.py b/release/scripts/modules/bpy/__init__.py
index 34b7a9ea7b6..3a2f9bde2c7 100644
--- a/release/scripts/modules/bpy/__init__.py
+++ b/release/scripts/modules/bpy/__init__.py
@@ -58,6 +58,7 @@ def main():
# from bpy.types import Panel
sys.modules["bpy.app"] = app
sys.modules["bpy.app.handlers"] = app.handlers
+ sys.modules["bpy.app.translations"] = app.translations
sys.modules["bpy.types"] = types
#~ if "-d" in sys.argv: # Enable this to measure start up speed
diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py
index d32b69b501c..6c91568cbc1 100644
--- a/release/scripts/modules/bpy/path.py
+++ b/release/scripts/modules/bpy/path.py
@@ -30,6 +30,9 @@ __all__ = (
"display_name",
"display_name_from_filepath",
"ensure_ext",
+ "extensions_image",
+ "extensions_movie",
+ "extensions_audio",
"is_subdir",
"module_names",
"relpath",
@@ -39,6 +42,11 @@ __all__ = (
import bpy as _bpy
import os as _os
+from _bpy_path import (extensions_audio,
+ extensions_movie,
+ extensions_image,
+ )
+
def abspath(path, start=None, library=None):
"""
diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py
index 4ad00eb267e..9c4117f0953 100644
--- a/release/scripts/modules/bpy/utils.py
+++ b/release/scripts/modules/bpy/utils.py
@@ -35,6 +35,7 @@ __all__ = (
"register_module",
"register_manual_map",
"unregister_manual_map",
+ "make_rna_paths",
"manual_map",
"resource_path",
"script_path_user",
@@ -57,6 +58,7 @@ import sys as _sys
import addon_utils as _addon_utils
+_user_preferences = _bpy.context.user_preferences
_script_module_dirs = "startup", "modules"
@@ -132,8 +134,6 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
"""
use_time = _bpy.app.debug_python
- prefs = _bpy.context.user_preferences
-
if use_time:
import time
t_main = time.time()
@@ -150,7 +150,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
# to reload. note that they will only actually reload of the
# modification time changes. This `won't` work for packages so...
# its not perfect.
- for module_name in [ext.module for ext in prefs.addons]:
+ for module_name in [ext.module for ext in _user_preferences.addons]:
_addon_utils.disable(module_name, default_set=False)
def register_module_call(mod):
@@ -218,24 +218,28 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
del _global_loaded_modules[:]
- for base_path in script_paths():
- for path_subdir in _script_module_dirs:
- path = _os.path.join(base_path, path_subdir)
- if _os.path.isdir(path):
- _sys_path_ensure(path)
+ from bpy_restrict_state import RestrictBlend
- # only add this to sys.modules, don't run
- if path_subdir == "modules":
- continue
+ with RestrictBlend():
+ for base_path in script_paths():
+ for path_subdir in _script_module_dirs:
+ path = _os.path.join(base_path, path_subdir)
+ if _os.path.isdir(path):
+ _sys_path_ensure(path)
- for mod in modules_from_path(path, loaded_modules):
- test_register(mod)
+ # only add this to sys.modules, don't run
+ if path_subdir == "modules":
+ continue
+
+ for mod in modules_from_path(path, loaded_modules):
+ test_register(mod)
# deal with addons separately
_addon_utils.reset_all(reload_scripts)
# run the active integration preset
- filepath = preset_find(prefs.inputs.active_keyconfig, "keyconfig")
+ filepath = preset_find(_user_preferences.inputs.active_keyconfig,
+ "keyconfig")
if filepath:
keyconfig_set(filepath)
@@ -264,7 +268,7 @@ def script_path_user():
def script_path_pref():
"""returns the user preference or None"""
- path = _bpy.context.user_preferences.filepaths.script_directory
+ path = _user_preferences.filepaths.script_directory
return _os.path.normpath(path) if path else None
@@ -637,3 +641,29 @@ def manual_map():
continue
yield prefix, url_manual_mapping
+
+
+# Build an RNA path from struct/property/enum names.
+def make_rna_paths(struct_name, prop_name, enum_name):
+ """
+ Create RNA "paths" from given names.
+
+ :arg struct_name: Name of a RNA struct (like e.g. "Scene").
+ :type struct_name: string
+ :arg prop_name: Name of a RNA struct's property.
+ :type prop_name: string
+ :arg enum_name: Name of a RNA enum identifier.
+ :type enum_name: string
+ :return: A triple of three "RNA paths" (most_complete_path, "struct.prop", "struct.prop:'enum'").
+ If no enum_name is given, the third element will always be void.
+ :rtype: tuple of strings
+ """
+ src = src_rna = src_enum = ""
+ if struct_name:
+ if prop_name:
+ src = src_rna = ".".join((struct_name, prop_name))
+ if enum_name:
+ src = src_enum = "{}:'{}'".format(src_rna, enum_name)
+ else:
+ src = src_rna = struct_name
+ return src, src_rna, src_enum
diff --git a/release/scripts/modules/bpy_extras/anim_utils.py b/release/scripts/modules/bpy_extras/anim_utils.py
index b8d08628de4..20a9a412f26 100644
--- a/release/scripts/modules/bpy_extras/anim_utils.py
+++ b/release/scripts/modules/bpy_extras/anim_utils.py
@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8-80 compliant>
+# <pep8 compliant>
__all__ = (
"bake_action",
@@ -52,7 +52,7 @@ def bake_action(frame_start,
:type do_pose: bool
:arg do_object: Bake objects.
:type do_object: bool
- :arg do_constraint_clear: Remove constraints.
+ :arg do_constraint_clear: Remove constraints (and do 'visual keying').
:type do_constraint_clear: bool
:arg do_clean: Remove redundant keyframes after baking.
:type do_clean: bool
@@ -65,61 +65,20 @@ def bake_action(frame_start,
"""
# -------------------------------------------------------------------------
- # Helper Functions
+ # Helper Functions and vars
- def pose_frame_info(obj):
- from mathutils import Matrix
+ def pose_frame_info(obj, do_visual_keying):
+ matrix = {}
+ for name, pbone in obj.pose.bones.items():
+ if do_visual_keying:
+ # Get the final transform of the bone in its own local space...
+ matrix[name] = obj.convert_space(pbone, pbone.matrix, 'POSE', 'LOCAL')
+ else:
+ matrix[name] = pbone.matrix_basis.copy()
+ return matrix
- info = {}
-
- pose = obj.pose
-
- pose_items = pose.bones.items()
-
- for name, pbone in pose_items:
- binfo = {}
- bone = pbone.bone
-
- binfo["parent"] = getattr(bone.parent, "name", None)
- binfo["bone"] = bone
- binfo["pbone"] = pbone
- binfo["matrix_local"] = bone.matrix_local.copy()
- try:
- binfo["matrix_local_inv"] = binfo["matrix_local"].inverted()
- except:
- binfo["matrix_local_inv"] = Matrix()
-
- binfo["matrix"] = bone.matrix.copy()
- binfo["matrix_pose"] = pbone.matrix.copy()
- try:
- binfo["matrix_pose_inv"] = binfo["matrix_pose"].inverted()
- except:
- binfo["matrix_pose_inv"] = Matrix()
-
- info[name] = binfo
-
- for name, pbone in pose_items:
- binfo = info[name]
- binfo_parent = binfo.get("parent", None)
- if binfo_parent:
- binfo_parent = info[binfo_parent]
-
- matrix = binfo["matrix_pose"]
- rest_matrix = binfo["matrix_local"]
-
- if binfo_parent:
- matrix = binfo_parent["matrix_pose_inv"] * matrix
- rest_matrix = binfo_parent["matrix_local_inv"] * rest_matrix
-
- binfo["matrix_key"] = rest_matrix.inverted() * matrix
-
- return info
-
- def obj_frame_info(obj):
- info = {}
- # parent = obj.parent
- info["matrix_key"] = obj.matrix_local.copy()
- return info
+ def obj_frame_info(obj, do_visual_keying):
+ return obj.matrix_local.copy() if do_visual_keying else obj.matrix_basis.copy()
# -------------------------------------------------------------------------
# Setup the Context
@@ -127,33 +86,30 @@ def bake_action(frame_start,
# TODO, pass data rather then grabbing from the context!
scene = bpy.context.scene
obj = bpy.context.object
- pose = obj.pose
frame_back = scene.frame_current
- if pose is None:
+ if obj.pose is None:
do_pose = False
- if do_pose is None and do_object is None:
+ if not (do_pose or do_object):
return None
pose_info = []
obj_info = []
+ options = {'INSERTKEY_NEEDED'}
+
frame_range = range(frame_start, frame_end + 1, frame_step)
# -------------------------------------------------------------------------
# Collect transformations
- # could speed this up by applying steps here too...
for f in frame_range:
scene.frame_set(f)
-
if do_pose:
- pose_info.append(pose_frame_info(obj))
+ pose_info.append(pose_frame_info(obj, do_constraint_clear))
if do_object:
- obj_info.append(obj_frame_info(obj))
-
- f += 1
+ obj_info.append(obj_frame_info(obj, do_constraint_clear))
# -------------------------------------------------------------------------
# Create action
@@ -164,57 +120,44 @@ def bake_action(frame_start,
action = bpy.data.actions.new("Action")
atd.action = action
- if do_pose:
- pose_items = pose.bones.items()
- else:
- pose_items = [] # skip
-
# -------------------------------------------------------------------------
# Apply transformations to action
# pose
- for name, pbone in (pose_items if do_pose else ()):
- if only_selected and not pbone.bone.select:
- continue
-
- if do_constraint_clear:
- while pbone.constraints:
- pbone.constraints.remove(pbone.constraints[0])
-
- # create compatible eulers
- euler_prev = None
-
- for f in frame_range:
- f_step = (f - frame_start) // frame_step
- matrix = pose_info[f_step][name]["matrix_key"]
-
- # pbone.location = matrix.to_translation()
- # pbone.rotation_quaternion = matrix.to_quaternion()
- pbone.matrix_basis = matrix
-
- pbone.keyframe_insert("location", -1, f, name)
-
- rotation_mode = pbone.rotation_mode
-
- if rotation_mode == 'QUATERNION':
- pbone.keyframe_insert("rotation_quaternion", -1, f, name)
- elif rotation_mode == 'AXIS_ANGLE':
- pbone.keyframe_insert("rotation_axis_angle", -1, f, name)
- else: # euler, XYZ, ZXY etc
-
- if euler_prev is not None:
- euler = pbone.rotation_euler.copy()
- euler.make_compatible(euler_prev)
- pbone.rotation_euler = euler
- euler_prev = euler
- del euler
-
- pbone.keyframe_insert("rotation_euler", -1, f, name)
-
- if euler_prev is None:
- euler_prev = pbone.rotation_euler.copy()
-
- pbone.keyframe_insert("scale", -1, f, name)
+ if do_pose:
+ for name, pbone in obj.pose.bones.items():
+ if only_selected and not pbone.bone.select:
+ continue
+
+ if do_constraint_clear:
+ while pbone.constraints:
+ pbone.constraints.remove(pbone.constraints[0])
+
+ # create compatible eulers
+ euler_prev = None
+
+ for (f, matrix) in zip(frame_range, pose_info):
+ pbone.matrix_basis = matrix[name].copy()
+
+ pbone.keyframe_insert("location", -1, f, name, options)
+
+ rotation_mode = pbone.rotation_mode
+ if rotation_mode == 'QUATERNION':
+ pbone.keyframe_insert("rotation_quaternion", -1, f, name, options)
+ elif rotation_mode == 'AXIS_ANGLE':
+ pbone.keyframe_insert("rotation_axis_angle", -1, f, name, options)
+ else: # euler, XYZ, ZXY etc
+ if euler_prev is not None:
+ euler = pbone.rotation_euler.copy()
+ euler.make_compatible(euler_prev)
+ pbone.rotation_euler = euler
+ euler_prev = euler
+ del euler
+ else:
+ euler_prev = pbone.rotation_euler.copy()
+ pbone.keyframe_insert("rotation_euler", -1, f, name, options)
+
+ pbone.keyframe_insert("scale", -1, f, name, options)
# object. TODO. multiple objects
if do_object:
@@ -225,18 +168,17 @@ def bake_action(frame_start,
# create compatible eulers
euler_prev = None
- for f in frame_range:
- matrix = obj_info[(f - frame_start) // frame_step]["matrix_key"]
- obj.matrix_local = matrix
+ for (f, matrix) in zip(frame_range, obj_info):
+ name = "Action Bake" # XXX: placeholder
+ obj.matrix_basis = matrix
- obj.keyframe_insert("location", -1, f)
+ obj.keyframe_insert("location", -1, f, name, options)
rotation_mode = obj.rotation_mode
-
if rotation_mode == 'QUATERNION':
- obj.keyframe_insert("rotation_quaternion", -1, f)
+ obj.keyframe_insert("rotation_quaternion", -1, f, name, options)
elif rotation_mode == 'AXIS_ANGLE':
- obj.keyframe_insert("rotation_axis_angle", -1, f)
+ obj.keyframe_insert("rotation_axis_angle", -1, f, name, options)
else: # euler, XYZ, ZXY etc
if euler_prev is not None:
euler = obj.rotation_euler.copy()
@@ -244,15 +186,11 @@ def bake_action(frame_start,
obj.rotation_euler = euler
euler_prev = euler
del euler
-
- obj.keyframe_insert("rotation_euler", -1, f)
-
- if euler_prev is None:
+ else:
euler_prev = obj.rotation_euler.copy()
+ obj.keyframe_insert("rotation_euler", -1, f, name, options)
- obj.keyframe_insert("scale", -1, f)
-
- scene.frame_set(frame_back)
+ obj.keyframe_insert("scale", -1, f, name, options)
# -------------------------------------------------------------------------
# Clean
@@ -271,4 +209,6 @@ def bake_action(frame_start,
else:
i += 1
+ scene.frame_set(frame_back)
+
return action
diff --git a/release/scripts/modules/bpy_extras/io_utils.py b/release/scripts/modules/bpy_extras/io_utils.py
index 4457ecb43e6..dfb6c46ef87 100644
--- a/release/scripts/modules/bpy_extras/io_utils.py
+++ b/release/scripts/modules/bpy_extras/io_utils.py
@@ -79,20 +79,23 @@ class ExportHelper:
return {'RUNNING_MODAL'}
def check(self, context):
+ import os
change_ext = False
change_axis = _check_axis_conversion(self)
check_extension = self.check_extension
if check_extension is not None:
- filepath = bpy.path.ensure_ext(self.filepath,
- self.filename_ext
- if check_extension
- else "")
+ filepath = self.filepath
+ if os.path.basename(filepath):
+ filepath = bpy.path.ensure_ext(filepath,
+ self.filename_ext
+ if check_extension
+ else "")
- if filepath != self.filepath:
- self.filepath = filepath
- change_ext = True
+ if filepath != self.filepath:
+ self.filepath = filepath
+ change_ext = True
return (change_ext or change_axis)
@@ -338,7 +341,7 @@ path_reference_mode = EnumProperty(
('COPY', "Copy", "Copy the file to the destination path "
"(or subdirectory)"),
),
- default='AUTO'
+ default='AUTO',
)
@@ -433,10 +436,7 @@ def path_reference_copy(copy_set, report=print):
pass
else:
dir_to = os.path.dirname(file_dst)
-
- if not os.path.isdir(dir_to):
- os.makedirs(dir_to)
-
+ os.makedirs(dir_to, exist_ok=True)
shutil.copy(file_src, file_dst)
@@ -477,10 +477,10 @@ def unique_name(key, name, name_dict, name_max=-1, clean_func=None, sep="."):
while name_new in name_dict_values:
count_str = "%03d" % count
name_new = "%.*s%s%s" % (name_max - (len(count_str) + 1),
- name_new_orig,
- sep,
- count_str,
- )
+ name_new_orig,
+ sep,
+ count_str,
+ )
count += 1
name_dict[key] = name_new
diff --git a/release/scripts/modules/bpy_extras/keyconfig_utils.py b/release/scripts/modules/bpy_extras/keyconfig_utils.py
index dbff90c2447..29a65965c3f 100644
--- a/release/scripts/modules/bpy_extras/keyconfig_utils.py
+++ b/release/scripts/modules/bpy_extras/keyconfig_utils.py
@@ -18,6 +18,11 @@
# <pep8 compliant>
+# bpy.type.KeyMap: (km.name, km.space_type, km.region_type, [...])
+
+# ('Script', 'EMPTY', 'WINDOW', []),
+
+
KM_HIERARCHY = [
('Window', 'EMPTY', 'WINDOW', []), # file save, window change, exit
('Screen', 'EMPTY', 'WINDOW', [ # full screen, undo, screenshot
@@ -42,6 +47,7 @@ KM_HIERARCHY = [
('Vertex Paint', 'EMPTY', 'WINDOW', []),
('Weight Paint', 'EMPTY', 'WINDOW', []),
+ ('Weight Paint Vertex Selection', 'EMPTY', 'WINDOW', []),
('Face Mask', 'EMPTY', 'WINDOW', []),
('Image Paint', 'EMPTY', 'WINDOW', []), # image and view3d
('Sculpt', 'EMPTY', 'WINDOW', []),
@@ -49,9 +55,12 @@ KM_HIERARCHY = [
('Armature Sketch', 'EMPTY', 'WINDOW', []),
('Particle', 'EMPTY', 'WINDOW', []),
+ ('Knife Tool Modal Map', 'EMPTY', 'WINDOW', []),
+ ('Paint Stroke Modal', 'EMPTY', 'WINDOW', []),
+
('Object Non-modal', 'EMPTY', 'WINDOW', []), # mode change
- ('3D View Generic', 'VIEW_3D', 'WINDOW', []) # toolbar and properties
+ ('3D View Generic', 'VIEW_3D', 'WINDOW', []), # toolbar and properties
]),
('Frames', 'EMPTY', 'WINDOW', []), # frame navigation (per region)
@@ -59,53 +68,65 @@ KM_HIERARCHY = [
('Animation', 'EMPTY', 'WINDOW', []), # frame change on click, preview range (per region)
('Animation Channels', 'EMPTY', 'WINDOW', []),
('Graph Editor', 'GRAPH_EDITOR', 'WINDOW', [
- ('Graph Editor Generic', 'GRAPH_EDITOR', 'WINDOW', [])
+ ('Graph Editor Generic', 'GRAPH_EDITOR', 'WINDOW', []),
]),
('Dopesheet', 'DOPESHEET_EDITOR', 'WINDOW', []),
('NLA Editor', 'NLA_EDITOR', 'WINDOW', [
('NLA Channels', 'NLA_EDITOR', 'WINDOW', []),
- ('NLA Generic', 'NLA_EDITOR', 'WINDOW', [])
+ ('NLA Generic', 'NLA_EDITOR', 'WINDOW', []),
]),
('Image', 'IMAGE_EDITOR', 'WINDOW', [
('UV Editor', 'EMPTY', 'WINDOW', []), # image (reverse order, UVEdit before Image
('Image Paint', 'EMPTY', 'WINDOW', []), # image and view3d
('UV Sculpt', 'EMPTY', 'WINDOW', []),
- ('Image Generic', 'IMAGE_EDITOR', 'WINDOW', [])
+ ('Image Generic', 'IMAGE_EDITOR', 'WINDOW', []),
]),
('Timeline', 'TIMELINE', 'WINDOW', []),
('Outliner', 'OUTLINER', 'WINDOW', []),
('Node Editor', 'NODE_EDITOR', 'WINDOW', [
- ('Node Generic', 'NODE_EDITOR', 'WINDOW', [])
+ ('Node Generic', 'NODE_EDITOR', 'WINDOW', []),
+ ]),
+ ('Sequencer', 'SEQUENCE_EDITOR', 'WINDOW', [
+ ('SequencerCommon', 'SEQUENCE_EDITOR', 'WINDOW', []),
+ ('SequencerPreview', 'SEQUENCE_EDITOR', 'WINDOW', []),
]),
- ('Sequencer', 'SEQUENCE_EDITOR', 'WINDOW', []),
('Logic Editor', 'LOGIC_EDITOR', 'WINDOW', []),
('File Browser', 'FILE_BROWSER', 'WINDOW', [
('File Browser Main', 'FILE_BROWSER', 'WINDOW', []),
- ('File Browser Buttons', 'FILE_BROWSER', 'WINDOW', [])
+ ('File Browser Buttons', 'FILE_BROWSER', 'WINDOW', []),
]),
+ ('Info', 'INFO', 'WINDOW', []),
+
('Property Editor', 'PROPERTIES', 'WINDOW', []), # align context menu
- ('Text', 'TEXT_EDITOR', 'WINDOW', []),
+ ('Text', 'TEXT_EDITOR', 'WINDOW', [
+ ('Text Generic', 'TEXT_EDITOR', 'WINDOW', []),
+ ]),
('Console', 'CONSOLE', 'WINDOW', []),
('Clip', 'CLIP_EDITOR', 'WINDOW', [
('Clip Editor', 'CLIP_EDITOR', 'WINDOW', []),
('Clip Graph Editor', 'CLIP_EDITOR', 'WINDOW', []),
+ ('Clip Dopesheet Editor', 'CLIP_EDITOR', 'WINDOW', []),
('Mask Editing', 'EMPTY', 'WINDOW', []), # image (reverse order, UVEdit before Image
]),
('View3D Gesture Circle', 'EMPTY', 'WINDOW', []),
+ ('Gesture Straight Line', 'EMPTY', 'WINDOW', []),
+ ('Gesture Zoom Border', 'EMPTY', 'WINDOW', []),
('Gesture Border', 'EMPTY', 'WINDOW', []),
+
('Standard Modal Map', 'EMPTY', 'WINDOW', []),
('Transform Modal Map', 'EMPTY', 'WINDOW', []),
('View3D Fly Modal', 'EMPTY', 'WINDOW', []),
('View3D Rotate Modal', 'EMPTY', 'WINDOW', []),
('View3D Move Modal', 'EMPTY', 'WINDOW', []),
('View3D Zoom Modal', 'EMPTY', 'WINDOW', []),
+ ('View3D Dolly Modal', 'EMPTY', 'WINDOW', []),
]
diff --git a/release/scripts/modules/bpy_extras/mesh_utils.py b/release/scripts/modules/bpy_extras/mesh_utils.py
index 0166f954dc9..f4fdfece947 100644
--- a/release/scripts/modules/bpy_extras/mesh_utils.py
+++ b/release/scripts/modules/bpy_extras/mesh_utils.py
@@ -152,10 +152,13 @@ def edge_face_count_dict(mesh):
faces using each edge.
:rtype: dict
"""
- face_edge_keys = [face.edge_keys for face in mesh.tessfaces]
+
face_edge_count = {}
- for face_keys in face_edge_keys:
- for key in face_keys:
+ loops = mesh.loops
+ edges = mesh.edges
+ for poly in mesh.polygons:
+ for i in poly.loop_indices:
+ key = edges[loops[i].edge_index].key
try:
face_edge_count[key] += 1
except:
@@ -247,7 +250,7 @@ def edge_loops_from_tessfaces(mesh, tessfaces=None, seams=()):
break
i = ed_adj.index(context_loop[-2])
- context_loop.append(ed_adj[not i])
+ context_loop.append(ed_adj[not i])
# Dont look at this again
del ed_adj[:]
@@ -530,12 +533,12 @@ def face_random_points(num_points, tessfaces):
tris.append((verts[fv[0]].co,
verts[fv[1]].co,
verts[fv[2]].co,
- ))
+ ))
if len(fv) == 4:
tris.append((verts[fv[0]].co,
verts[fv[3]].co,
verts[fv[2]].co,
- ))
+ ))
tri_faces.append(tris)
# For each face, generate the required number of random points
diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py
index 46731b807f7..ab5dc3e6aee 100644
--- a/release/scripts/modules/bpy_extras/object_utils.py
+++ b/release/scripts/modules/bpy_extras/object_utils.py
@@ -26,7 +26,6 @@ __all__ = (
import bpy
-import mathutils
from bpy.props import BoolProperty, FloatVectorProperty
@@ -80,7 +79,7 @@ def add_object_align_init(context, operator):
rotation = space_data.region_3d.view_matrix.to_3x3().inverted()
rotation.resize_4x4()
else:
- rotation = mathutils.Matrix()
+ rotation = Matrix()
# set the operator properties
if operator:
@@ -124,9 +123,10 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True):
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 v3d:
- base.layers_from_view(context.space_data)
+ else False for i in range(len(scene.layers))]
+ else:
+ if v3d:
+ base.layers_from_view(context.space_data)
obj_new.matrix_world = add_object_align_init(context, operator)
diff --git a/release/scripts/modules/bpy_extras/view3d_utils.py b/release/scripts/modules/bpy_extras/view3d_utils.py
index b2f366d5d1e..7a075e93e1a 100644
--- a/release/scripts/modules/bpy_extras/view3d_utils.py
+++ b/release/scripts/modules/bpy_extras/view3d_utils.py
@@ -50,7 +50,7 @@ def region_2d_to_vector_3d(region, rv3d, coord):
out = Vector(((2.0 * coord[0] / region.width) - 1.0,
(2.0 * coord[1] / region.height) - 1.0,
-0.5
- ))
+ ))
w = out.dot(persinv[3].xyz) + persinv[3][3]
@@ -89,7 +89,7 @@ def region_2d_to_origin_3d(region, rv3d, coord):
persinv = persmat.inverted()
origin_start = ((persinv.col[0].xyz * dx) +
(persinv.col[1].xyz * dy) +
- viewinv.translation)
+ viewinv.translation)
return origin_start
diff --git a/release/scripts/modules/bpy_restrict_state.py b/release/scripts/modules/bpy_restrict_state.py
new file mode 100644
index 00000000000..4aa3c5de573
--- /dev/null
+++ b/release/scripts/modules/bpy_restrict_state.py
@@ -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.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8-80 compliant>
+
+"""
+This module contains RestrictBlend context manager.
+"""
+
+__all__ = (
+ "RestrictBlend",
+ )
+
+import bpy as _bpy
+
+
+class _RestrictContext():
+ __slots__ = ()
+ _real_data = _bpy.data
+ # safe, the pointer never changes
+ _real_pref = _bpy.context.user_preferences
+
+ @property
+ def window_manager(self):
+ return self._real_data.window_managers[0]
+
+ @property
+ def user_preferences(self):
+ return self._real_pref
+
+
+class _RestrictData():
+ __slots__ = ()
+
+
+_context_restrict = _RestrictContext()
+_data_restrict = _RestrictData()
+
+
+class RestrictBlend():
+ __slots__ = ("context", "data")
+
+ def __enter__(self):
+ self.data = _bpy.data
+ self.context = _bpy.context
+ _bpy.data = _data_restrict
+ _bpy.context = _context_restrict
+
+ def __exit__(self, type, value, traceback):
+ _bpy.data = self.data
+ _bpy.context = self.context
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index e42ae43aed6..f42fd8e3107 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -484,6 +484,7 @@ class Text(bpy_types.ID):
if cont.type == 'PYTHON']
)
+
# values are module: [(cls, path, line), ...]
TypeMap = {}
@@ -603,6 +604,10 @@ class KeyingSetInfo(StructRNA, metaclass=RNAMeta):
__slots__ = ()
+class AddonPreferences(StructRNA, metaclass=RNAMeta):
+ __slots__ = ()
+
+
class _GenericUI:
__slots__ = ()
@@ -664,6 +669,10 @@ class Panel(StructRNA, _GenericUI, metaclass=RNAMeta):
__slots__ = ()
+class UIList(StructRNA, _GenericUI, metaclass=RNAMeta):
+ __slots__ = ()
+
+
class Header(StructRNA, _GenericUI, metaclass=RNAMeta):
__slots__ = ()
@@ -698,7 +707,9 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
files.sort()
for f, filepath in files:
- props = layout.operator(operator, text=bpy.path.display_name(f))
+ props = layout.operator(operator,
+ text=bpy.path.display_name(f),
+ translate=False)
for attr, value in props_default.items():
setattr(props, attr, value)
@@ -717,3 +728,165 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
self.path_menu(bpy.utils.preset_paths(self.preset_subdir),
self.preset_operator,
filter_ext=lambda ext: ext.lower() in {".py", ".xml"})
+
+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__ = ()
+
+
+class NodeSocketTemplate():
+ type = 'UNDEFINED'
+
+ # Default implementation:
+ # Create a single property using the socket template's 'value_property' attribute
+ # value_property should be created in the __init__ function
+ #
+ # If necessary this function can be overloaded in subclasses, e.g. to create multiple value properties
+ def define_node_properties(self, node_type, prefix):
+ if hasattr(self, "value_property"):
+ setattr(node_type, prefix+"value", self.value_property)
+
+ def init_socket(self, socket):
+ socket.type = self.type
+ if hasattr(self, "value_property"):
+ socket.value_property = self.value_property[1]['attr']
+
+
+def gen_valid_identifier(seq):
+ # get an iterator
+ itr = iter(seq)
+ # pull characters until we get a legal one for first in identifer
+ for ch in itr:
+ if ch == '_' or ch.isalpha():
+ yield ch
+ break
+ # pull remaining characters and yield legal ones for identifier
+ for ch in itr:
+ if ch == '_' or ch.isalpha() or ch.isdigit():
+ yield ch
+
+def sanitize_identifier(name):
+ return ''.join(gen_valid_identifier(name))
+
+def unique_identifier(name, identifier_list):
+ # First some basic sanitation, to make a usable identifier string from the name
+ base = sanitize_identifier(name)
+ # Now make a unique identifier by appending an unused index
+ identifier = base
+ index = 0
+ while identifier in identifier_list:
+ index += 1
+ identifier = base + str(index)
+ return identifier
+
+class RNAMetaNode(RNAMetaPropGroup):
+ def __new__(cls, name, bases, classdict, **args):
+ # Wrapper for node.init, to add sockets from templates
+
+ def create_sockets(self):
+ inputs = getattr(self, 'input_templates', None)
+ if inputs:
+ for temp in inputs:
+ socket = self.inputs.new(type=temp.bl_socket_idname, name=temp.name, identifier=temp.identifier)
+ temp.init_socket(socket)
+ outputs = getattr(self, 'output_templates', None)
+ if outputs:
+ for temp in outputs:
+ socket = self.outputs.new(type=temp.bl_socket_idname, name=temp.name, identifier=temp.identifier)
+ temp.init_socket(socket)
+
+ init_base = classdict.get('init', None)
+ if init_base:
+ def init_node(self, context):
+ create_sockets(self)
+ init_base(self, context)
+ else:
+ def init_node(self, context):
+ create_sockets(self)
+
+ classdict['init'] = init_node
+
+ # Create the regular class
+ result = RNAMetaPropGroup.__new__(cls, name, bases, classdict)
+
+ # Add properties from socket templates
+ inputs = classdict.get('input_templates', None)
+ if inputs:
+ for i, temp in enumerate(inputs):
+ temp.identifier = unique_identifier(temp.name, [t.identifier for t in inputs[0:i]])
+ temp.define_node_properties(result, "input_"+temp.identifier+"_")
+ outputs = classdict.get('output_templates', None)
+ if outputs:
+ for i, temp in enumerate(outputs):
+ temp.identifier = unique_identifier(temp.name, [t.identifier for t in outputs[0:i]])
+ temp.define_node_properties(result, "output_"+temp.identifier+"_")
+
+ return result
+
+
+class Node(StructRNA, metaclass=RNAMetaNode):
+ __slots__ = ()
+
+ @classmethod
+ def poll(cls, ntree):
+ return True
+
+
+class NodeSocket(StructRNA, metaclass=RNAMetaPropGroup):
+ __slots__ = ()
+
+ @property
+ def links(self):
+ """List of node links from or to this socket"""
+ return tuple(link for link in self.id_data.links
+ if (link.from_socket == self or
+ link.to_socket == self))
+
+
+class NodeSocketInterface(StructRNA, metaclass=RNAMetaPropGroup):
+ __slots__ = ()
+
+
+# These are intermediate subclasses, need a bpy type too
+class CompositorNode(Node):
+ __slots__ = ()
+
+ @classmethod
+ def poll(cls, ntree):
+ return ntree.bl_idname == 'CompositorNodeTree'
+
+ def update(self):
+ self.tag_need_exec()
+
+class ShaderNode(Node):
+ __slots__ = ()
+
+ @classmethod
+ def poll(cls, ntree):
+ return ntree.bl_idname == 'ShaderNodeTree'
+
+
+class TextureNode(Node):
+ __slots__ = ()
+
+ @classmethod
+ def poll(cls, ntree):
+ return ntree.bl_idname == 'TextureNodeTree'
+
diff --git a/release/scripts/modules/console/complete_import.py b/release/scripts/modules/console/complete_import.py
index 8f2b5324cdc..9277e04af76 100644
--- a/release/scripts/modules/console/complete_import.py
+++ b/release/scripts/modules/console/complete_import.py
@@ -111,10 +111,10 @@ def module_list(path):
else:
folder_list = []
#folder_list = glob.glob(os.path.join(path,'*'))
- folder_list = [p for p in folder_list \
- if os.path.exists(os.path.join(path, p, '__init__.py'))\
- or p[-3:] in ('.py', '.so')\
- or p[-4:] in ('.pyc', '.pyo', '.pyd')]
+ folder_list = [p for p in folder_list \
+ if os.path.exists(os.path.join(path, p, '__init__.py')) \
+ or p[-3:] in {'.py', '.so'} \
+ or p[-4:] in {'.pyc', '.pyo', '.pyd'}]
folder_list = [os.path.basename(p).split('.')[0] for p in folder_list]
return folder_list
diff --git a/release/scripts/modules/console/intellisense.py b/release/scripts/modules/console/intellisense.py
index a177b305fda..b694cceafea 100644
--- a/release/scripts/modules/console/intellisense.py
+++ b/release/scripts/modules/console/intellisense.py
@@ -148,7 +148,7 @@ def expand(line, cursor, namespace, private=True):
if prefix:
line = line[:cursor] + prefix + line[cursor:]
- cursor += len(prefix)
+ cursor += len(prefix.encode('utf-8'))
if no_calltip and prefix.endswith('('):
return expand(line, cursor, namespace, private)
return line, cursor, scrollback
diff --git a/release/scripts/modules/console_python.py b/release/scripts/modules/console_python.py
index 60dfa2b6344..55ff84fea96 100644
--- a/release/scripts/modules/console_python.py
+++ b/release/scripts/modules/console_python.py
@@ -334,8 +334,8 @@ def banner(context):
add_scrollback("Cursor: Left/Right Home/End", 'OUTPUT')
add_scrollback("Remove: Backspace/Delete", 'OUTPUT')
add_scrollback("Execute: Enter", 'OUTPUT')
- add_scrollback("Autocomplete: Ctrl+Space", 'OUTPUT')
- add_scrollback("Ctrl +/- Wheel: Zoom", 'OUTPUT')
+ add_scrollback("Autocomplete: Ctrl-Space", 'OUTPUT')
+ add_scrollback("Zoom: Ctrl +/-, Ctrl-Wheel", 'OUTPUT')
add_scrollback("Builtin Modules: bpy, bpy.data, bpy.ops, "
"bpy.props, bpy.types, bpy.context, bpy.utils, "
"bgl, blf, mathutils",
diff --git a/release/scripts/modules/rna_prop_ui.py b/release/scripts/modules/rna_prop_ui.py
index 32c8ed11bc5..dd0cd632413 100644
--- a/release/scripts/modules/rna_prop_ui.py
+++ b/release/scripts/modules/rna_prop_ui.py
@@ -92,6 +92,9 @@ def draw(layout, context, context_member, property_type, use_edit=True):
if not rna_item:
return
+ if rna_item.id_data.library is not None:
+ use_edit = False
+
assert(isinstance(rna_item, property_type))
items = rna_item.items()
@@ -132,11 +135,11 @@ def draw(layout, context, context_member, property_type, use_edit=True):
else:
row = box.row()
- row.label(text=key)
+ row.label(text=key, translate=False)
# explicit exception for arrays
if to_dict or to_list:
- row.label(text=val_draw)
+ row.label(text=val_draw, translate=False)
else:
if key in rna_properties:
row.prop(rna_item, key, text="")
@@ -145,7 +148,7 @@ def draw(layout, context, context_member, property_type, use_edit=True):
if use_edit:
row = split.row(align=True)
- props = row.operator("wm.properties_edit", text="edit")
+ props = row.operator("wm.properties_edit", text="Edit")
assign_props(props, val_draw, key)
props = row.operator("wm.properties_remove", text="", icon='ZOOMOUT')
diff --git a/release/scripts/modules/rna_xml.py b/release/scripts/modules/rna_xml.py
index e21ccd08a35..08b60ebc6f8 100644
--- a/release/scripts/modules/rna_xml.py
+++ b/release/scripts/modules/rna_xml.py
@@ -265,7 +265,15 @@ def xml2rna(root_xml,
tp_name = 'ARRAY'
# print(" %s.%s (%s) --- %s" % (type(value).__name__, attr, tp_name, subvalue_type))
- setattr(value, attr, value_xml_coerce)
+ try:
+ setattr(value, attr, value_xml_coerce)
+ except ValueError:
+ # size mismatch
+ val = getattr(value, attr)
+ if len(val) < len(value_xml_coerce):
+ setattr(value, attr, value_xml_coerce[:len(val)])
+ else:
+ setattr(value, attr, list(value_xml_coerce) + list(val)[len(value_xml_coerce):])
# ---------------------------------------------------------------------
# Complex attributes
diff --git a/release/scripts/presets/interaction/3dsmax.py b/release/scripts/presets/interaction/3dsmax.py
new file mode 100644
index 00000000000..681aa4ab4b7
--- /dev/null
+++ b/release/scripts/presets/interaction/3dsmax.py
@@ -0,0 +1,12 @@
+# Configuration 3dsmax
+import bpy
+
+bpy.context.user_preferences.edit.use_drag_immediately = False
+bpy.context.user_preferences.edit.use_insertkey_xyz_to_rgb = False
+bpy.context.user_preferences.view.use_auto_perspective = True
+bpy.context.user_preferences.view.use_quit_dialog = True
+bpy.context.user_preferences.inputs.select_mouse = 'LEFT'
+bpy.context.user_preferences.inputs.view_zoom_method = 'DOLLY'
+bpy.context.user_preferences.inputs.view_zoom_axis = 'VERTICAL'
+bpy.context.user_preferences.inputs.view_rotate_method = 'TURNTABLE'
+bpy.context.user_preferences.inputs.invert_mouse_zoom = False
diff --git a/release/scripts/presets/interface_theme/back_to_black.xml b/release/scripts/presets/interface_theme/back_to_black.xml
index 0a77aa132a8..05216841cbd 100644
--- a/release/scripts/presets/interface_theme/back_to_black.xml
+++ b/release/scripts/presets/interface_theme/back_to_black.xml
@@ -1,7 +1,9 @@
<bpy>
<Theme>
<user_interface>
- <ThemeUserInterface icon_file=""
+ <ThemeUserInterface menu_shadow_fac="0.5"
+ menu_shadow_width="12"
+ icon_file=""
icon_alpha="1"
axis_x="#dc0000"
axis_y="#00dc00"
@@ -220,16 +222,10 @@
blend="0.1">
</ThemeWidgetStateColors>
</wcol_state>
- <panel>
- <ThemePanelColors header="#000000ff"
- show_header="FALSE">
- </ThemePanelColors>
- </panel>
</ThemeUserInterface>
</user_interface>
<view_3d>
<ThemeView3D grid="#222222"
- panel="#a5a5a57f"
wire="#888888"
lamp="#c1d40028"
speaker="#535353"
@@ -281,24 +277,35 @@
camera_path="#5a5a5a"
skin_root="#000000">
<space>
- <ThemeSpaceGeneric back="#0f0f0f"
- title="#5d5d5d"
- text="#7d7d7d"
- text_hi="#ffffff"
- header="#000000"
- header_text="#979797"
- header_text_hi="#ffffff"
- button="#000000"
- button_title="#c5c5c5"
- button_text="#c3c3c3"
- button_text_hi="#ffffff">
- </ThemeSpaceGeneric>
+ <ThemeSpaceGradient title="#5d5d5d"
+ text="#7d7d7d"
+ text_hi="#ffffff"
+ header="#000000"
+ header_text="#979797"
+ header_text_hi="#ffffff"
+ button="#00000057"
+ button_title="#c5c5c5"
+ button_text="#c3c3c3"
+ button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ <gradients>
+ <ThemeGradientColors show_grad="FALSE"
+ gradient="#393939"
+ high_gradient="#000000">
+ </ThemeGradientColors>
+ </gradients>
+ </ThemeSpaceGradient>
</space>
</ThemeView3D>
</view_3d>
<graph_editor>
<ThemeGraphEditor grid="#262626"
- panel="#ffffff"
window_sliders="#969696"
channels_region="#6d6d6d"
vertex="#ffffff"
@@ -331,10 +338,17 @@
header="#000000"
header_text="#979797"
header_text_hi="#ffffff"
- button="#000000"
+ button="#000000ff"
button_title="#c5c5c5"
button_text="#c3c3c3"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -348,7 +362,6 @@
</graph_editor>
<file_browser>
<ThemeFileBrowser selected_file="#354d66"
- tiles="#343434"
scrollbar="#a0a0a0"
scroll_handle="#7f7070"
active_file="#b1b1b1"
@@ -361,10 +374,17 @@
header="#000000"
header_text="#979797"
header_text_hi="#ffffff"
- button="#000000"
+ button="#000000ff"
button_title="#c5c5c5"
button_text="#c3c3c3"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -400,10 +420,17 @@
header="#000000"
header_text="#979797"
header_text_hi="#ffffff"
- button="#000000"
+ button="#000000ff"
button_title="#c3c3c3"
button_text="#c3c3c3"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -437,10 +464,17 @@
header="#000000"
header_text="#979797"
header_text_hi="#ffffff"
- button="#000000"
+ button="#000000ff"
button_title="#c5c5c5"
button_text="#c3c3c3"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -476,10 +510,17 @@
header="#000000"
header_text="#979797"
header_text_hi="#ffffff"
- button="#000000"
+ button="#000000ff"
button_title="#c5c5c5"
button_text="#c3c3c3"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeImageEditor>
@@ -507,16 +548,23 @@
header="#000000"
header_text="#f3f3f3"
header_text_hi="#ffffff"
- button="#020202"
+ button="#02020242"
button_title="#bdbdbd"
button_text="#dddddd"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeSequenceEditor>
</sequence_editor>
<properties>
- <ThemeProperties panel="#828282">
+ <ThemeProperties>
<space>
<ThemeSpaceGeneric back="#000000"
title="#5d5d5d"
@@ -525,10 +573,17 @@
header="#000000"
header_text="#979797"
header_text_hi="#ffffff"
- button="#000000"
+ button="#000000ff"
button_title="#c5c5c5"
button_text="#c3c3c3"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeProperties>
@@ -538,7 +593,10 @@
selected_text="#202020"
cursor="#ff0000"
syntax_builtin="#cf3d99"
+ syntax_symbols="#4c4c4c"
syntax_special="#969629"
+ syntax_preprocessor="#32008c"
+ syntax_reserved="#8c3c00"
syntax_comment="#249d60"
syntax_string="#cc3535"
syntax_numbers="#3c68ff">
@@ -550,10 +608,17 @@
header="#000000"
header_text="#b9b9b9"
header_text_hi="#ffffff"
- button="#000000"
+ button="#000000ff"
button_title="#d8d8d8"
button_text="#cccccc"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeTextEditor>
@@ -569,10 +634,17 @@
header="#000000"
header_text="#979797"
header_text_hi="#ffffff"
- button="#000000"
+ button="#000000ff"
button_title="#c5c5c5"
button_text="#c3c3c3"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeTimeline>
@@ -589,6 +661,8 @@
operator_node="#0e3157"
group_node="#091a07"
frame_node="#9a9b9ba0"
+ matte_node="#977474"
+ distor_node="#749797"
noodle_curving="5">
<space>
<ThemeSpaceGeneric back="#000000"
@@ -598,10 +672,17 @@
header="#000000"
header_text="#c7c7c7"
header_text_hi="#ffffff"
- button="#000000"
+ button="#0000002f"
button_title="#c5c5c5"
button_text="#c3c3c3"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -614,7 +695,7 @@
</ThemeNodeEditor>
</node_editor>
<logic_editor>
- <ThemeLogicEditor panel="#a5a5a5">
+ <ThemeLogicEditor>
<space>
<ThemeSpaceGeneric back="#070707"
title="#5d5d5d"
@@ -623,10 +704,17 @@
header="#000000"
header_text="#979797"
header_text_hi="#ffffff"
- button="#000000"
+ button="#000000ff"
button_title="#c5c5c5"
button_text="#c3c3c3"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeLogicEditor>
@@ -642,10 +730,17 @@
header="#000000"
header_text="#979797"
header_text_hi="#ffffff"
- button="#000000"
+ button="#000000ff"
button_title="#c5c5c5"
button_text="#c3c3c3"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeOutliner>
@@ -660,10 +755,17 @@
header="#000000"
header_text="#adadad"
header_text_hi="#ffffff"
- button="#000000"
+ button="#000000ff"
button_title="#c5c5c5"
button_text="#c3c3c3"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeInfo>
@@ -678,10 +780,17 @@
header="#000000"
header_text="#979797"
header_text_hi="#ffffff"
- button="#000000"
+ button="#000000ff"
button_title="#c5c5c5"
button_text="#c3c3c3"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeUserPreferences>
@@ -691,7 +800,8 @@
line_input="#cecece"
line_info="#00aa00"
line_error="#dc6060"
- cursor="#dc6060">
+ cursor="#dc6060"
+ select="#ffffff30">
<space>
<ThemeSpaceGeneric back="#0f0f0f"
title="#5d5d5d"
@@ -700,10 +810,17 @@
header="#000000"
header_text="#979797"
header_text_hi="#ffffff"
- button="#000000"
+ button="#000000ff"
button_title="#c5c5c5"
button_text="#c3c3c3"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeConsole>
@@ -732,10 +849,17 @@
header="#000000"
header_text="#979797"
header_text_hi="#ffffff"
- button="#070707"
+ button="#070707ff"
button_title="#c5c5c5"
button_text="#c3c3c3"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
diff --git a/release/scripts/presets/interface_theme/blender_24x.xml b/release/scripts/presets/interface_theme/blender_24x.xml
index 18ae3072208..48a3ee951aa 100644
--- a/release/scripts/presets/interface_theme/blender_24x.xml
+++ b/release/scripts/presets/interface_theme/blender_24x.xml
@@ -1,7 +1,9 @@
<bpy>
<Theme>
<user_interface>
- <ThemeUserInterface icon_file=""
+ <ThemeUserInterface menu_shadow_fac="0.5"
+ menu_shadow_width="12"
+ icon_file=""
icon_alpha="1"
axis_x="#dc0000"
axis_y="#00dc00"
@@ -220,16 +222,10 @@
blend="0.5">
</ThemeWidgetStateColors>
</wcol_state>
- <panel>
- <ThemePanelColors header="#00000019"
- show_header="FALSE">
- </ThemePanelColors>
- </panel>
</ThemeUserInterface>
</user_interface>
<view_3d>
<ThemeView3D grid="#5c5c5c"
- panel="#a5a5a5ff"
wire="#000000"
lamp="#00000028"
speaker="#000000"
@@ -281,24 +277,35 @@
camera_path="#000000"
skin_root="#000000">
<space>
- <ThemeSpaceGeneric back="#757575"
- title="#000000"
- text="#000000"
- text_hi="#ffffff"
- header="#b4b4b4"
- header_text="#000000"
- header_text_hi="#ffffff"
- button="#b4b4b4"
- button_title="#5a5a5a"
- button_text="#5a5a5a"
- button_text_hi="#ffffff">
- </ThemeSpaceGeneric>
+ <ThemeSpaceGradient title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#b4b4b4"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#b4b4b457"
+ button_title="#5a5a5a"
+ button_text="#5a5a5a"
+ button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ <gradients>
+ <ThemeGradientColors show_grad="FALSE"
+ gradient="#000000"
+ high_gradient="#757575">
+ </ThemeGradientColors>
+ </gradients>
+ </ThemeSpaceGradient>
</space>
</ThemeView3D>
</view_3d>
<graph_editor>
<ThemeGraphEditor grid="#818181"
- panel="#ffffff"
window_sliders="#969696"
channels_region="#707070"
vertex="#000000"
@@ -331,10 +338,17 @@
header="#b4b4b4"
header_text="#000000"
header_text_hi="#ffffff"
- button="#727272"
+ button="#727272ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -348,7 +362,6 @@
</graph_editor>
<file_browser>
<ThemeFileBrowser selected_file="#a0a0d0"
- tiles="#b4b4b4"
scrollbar="#a0a0a0"
scroll_handle="#7f7070"
active_file="#828282"
@@ -361,10 +374,17 @@
header="#b4b4b4"
header_text="#000000"
header_text_hi="#ffffff"
- button="#b4b4b4"
+ button="#b4b4b4ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -400,10 +420,17 @@
header="#b4b4b4"
header_text="#000000"
header_text_hi="#ffffff"
- button="#b4b4b4"
+ button="#b4b4b4ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -437,10 +464,17 @@
header="#b4b4b4"
header_text="#000000"
header_text_hi="#ffffff"
- button="#b4b4b4"
+ button="#b4b4b4ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -476,10 +510,17 @@
header="#b4b4b4"
header_text="#000000"
header_text_hi="#ffffff"
- button="#b4b4b4"
+ button="#b4b4b4ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeImageEditor>
@@ -507,16 +548,23 @@
header="#b4b4b4"
header_text="#000000"
header_text_hi="#ffffff"
- button="#b4b4b4"
+ button="#b4b4b442"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeSequenceEditor>
</sequence_editor>
<properties>
- <ThemeProperties panel="#828282">
+ <ThemeProperties>
<space>
<ThemeSpaceGeneric back="#b4b4b4"
title="#000000"
@@ -525,10 +573,17 @@
header="#b4b4b4"
header_text="#000000"
header_text_hi="#ffffff"
- button="#b4b4b4"
+ button="#b4b4b4ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeProperties>
@@ -538,7 +593,10 @@
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">
@@ -550,10 +608,17 @@
header="#b4b4b4"
header_text="#000000"
header_text_hi="#ffffff"
- button="#b4b4b4"
+ button="#b4b4b4ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeTextEditor>
@@ -569,10 +634,17 @@
header="#b4b4b4"
header_text="#000000"
header_text_hi="#ffffff"
- button="#b4b4b4"
+ button="#b4b4b4ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeTimeline>
@@ -589,6 +661,8 @@
operator_node="#6c696f"
group_node="#69756e"
frame_node="#9a9b9ba0"
+ matte_node="#977474"
+ distor_node="#749797"
noodle_curving="5">
<space>
<ThemeSpaceGeneric back="#757575"
@@ -598,10 +672,17 @@
header="#b4b4b4"
header_text="#000000"
header_text_hi="#ffffff"
- button="#b4b4b4"
+ button="#b4b4b42f"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -614,7 +695,7 @@
</ThemeNodeEditor>
</node_editor>
<logic_editor>
- <ThemeLogicEditor panel="#a5a5a5">
+ <ThemeLogicEditor>
<space>
<ThemeSpaceGeneric back="#b4b4b4"
title="#000000"
@@ -623,10 +704,17 @@
header="#b4b4b4"
header_text="#000000"
header_text_hi="#ffffff"
- button="#b4b4b4"
+ button="#b4b4b4ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeLogicEditor>
@@ -642,10 +730,17 @@
header="#b4b4b4"
header_text="#000000"
header_text_hi="#ffffff"
- button="#b4b4b4"
+ button="#b4b4b4ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeOutliner>
@@ -660,10 +755,17 @@
header="#b4b4b4"
header_text="#000000"
header_text_hi="#ffffff"
- button="#b4b4b4"
+ button="#b4b4b4ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeInfo>
@@ -678,10 +780,17 @@
header="#b4b4b4"
header_text="#000000"
header_text_hi="#ffffff"
- button="#b4b4b4"
+ button="#b4b4b4ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeUserPreferences>
@@ -691,7 +800,8 @@
line_input="#ffffff"
line_info="#00aa00"
line_error="#dc6060"
- cursor="#dc6060">
+ cursor="#dc6060"
+ select="#c6777799">
<space>
<ThemeSpaceGeneric back="#b4b4b4"
title="#000000"
@@ -700,10 +810,17 @@
header="#b4b4b4"
header_text="#000000"
header_text_hi="#ffffff"
- button="#b4b4b4"
+ button="#b4b4b4ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeConsole>
@@ -732,10 +849,17 @@
header="#b4b4b4"
header_text="#000000"
header_text_hi="#ffffff"
- button="#b4b4b4"
+ button="#b4b4b4ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
diff --git a/release/scripts/presets/interface_theme/elsyiun.xml b/release/scripts/presets/interface_theme/elsyiun.xml
index c10eb108000..3ea49edc7f5 100644
--- a/release/scripts/presets/interface_theme/elsyiun.xml
+++ b/release/scripts/presets/interface_theme/elsyiun.xml
@@ -1,7 +1,9 @@
<bpy>
<Theme>
<user_interface>
- <ThemeUserInterface icon_file=""
+ <ThemeUserInterface menu_shadow_fac="0.5"
+ menu_shadow_width="12"
+ icon_file=""
icon_alpha="1"
axis_x="#dc0000"
axis_y="#00dc00"
@@ -220,16 +222,10 @@
blend="0.5">
</ThemeWidgetStateColors>
</wcol_state>
- <panel>
- <ThemePanelColors header="#00000019"
- show_header="FALSE">
- </ThemePanelColors>
- </panel>
</ThemeUserInterface>
</user_interface>
<view_3d>
<ThemeView3D grid="#585858"
- panel="#a5a5a57f"
wire="#000000"
lamp="#00000028"
speaker="#000000"
@@ -281,24 +277,35 @@
camera_path="#000000"
skin_root="#000000">
<space>
- <ThemeSpaceGeneric back="#4b4b4b"
- title="#000000"
- text="#b8b8b8"
- text_hi="#e9e9e9"
- header="#3b3b3b"
- header_text="#b9b9b9"
- header_text_hi="#ffffff"
- button="#3b3b3b"
- button_title="#979797"
- button_text="#979797"
- button_text_hi="#ffffff">
- </ThemeSpaceGeneric>
+ <ThemeSpaceGradient title="#000000"
+ text="#b8b8b8"
+ text_hi="#e9e9e9"
+ header="#3b3b3b"
+ header_text="#b9b9b9"
+ header_text_hi="#ffffff"
+ button="#3b3b3b57"
+ button_title="#979797"
+ button_text="#979797"
+ button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ <gradients>
+ <ThemeGradientColors show_grad="FALSE"
+ gradient="#000000"
+ high_gradient="#4b4b4b">
+ </ThemeGradientColors>
+ </gradients>
+ </ThemeSpaceGradient>
</space>
</ThemeView3D>
</view_3d>
<graph_editor>
<ThemeGraphEditor grid="#585858"
- panel="#ffffff"
window_sliders="#969696"
channels_region="#707070"
vertex="#000000"
@@ -331,10 +338,17 @@
header="#3b3b3b"
header_text="#000000"
header_text_hi="#ffffff"
- button="#3b3b3b"
+ button="#3b3b3bff"
button_title="#8b8b8b"
button_text="#8b8b8b"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -348,7 +362,6 @@
</graph_editor>
<file_browser>
<ThemeFileBrowser selected_file="#755129"
- tiles="#3b3b3b"
scrollbar="#a0a0a0"
scroll_handle="#7f7070"
active_file="#828282"
@@ -361,10 +374,17 @@
header="#3b3b3b"
header_text="#8b8b8b"
header_text_hi="#ffffff"
- button="#303030"
+ button="#303030ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -400,10 +420,17 @@
header="#3b3b3b"
header_text="#000000"
header_text_hi="#ffffff"
- button="#3b3b3b"
+ button="#3b3b3bff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -437,10 +464,17 @@
header="#3b3b3b"
header_text="#000000"
header_text_hi="#ffffff"
- button="#aaaaaa"
+ button="#aaaaaaff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -476,10 +510,17 @@
header="#303030"
header_text="#000000"
header_text_hi="#ffffff"
- button="#303030"
+ button="#303030ff"
button_title="#8b8b8b"
button_text="#8b8b8b"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeImageEditor>
@@ -507,16 +548,23 @@
header="#3b3b3b"
header_text="#000000"
header_text_hi="#ffffff"
- button="#3b3b3b"
+ button="#3b3b3b42"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeSequenceEditor>
</sequence_editor>
<properties>
- <ThemeProperties panel="#828282">
+ <ThemeProperties>
<space>
<ThemeSpaceGeneric back="#3b3b3b"
title="#979797"
@@ -525,10 +573,17 @@
header="#3b3b3b"
header_text="#000000"
header_text_hi="#ffffff"
- button="#727272"
+ button="#727272ff"
button_title="#b8b8b8"
button_text="#b8b8b8"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeProperties>
@@ -538,7 +593,10 @@
selected_text="#4e4e8f"
cursor="#8b8bff"
syntax_builtin="#808bed"
+ syntax_symbols="#4c4c4c"
syntax_special="#c080d0"
+ syntax_preprocessor="#409090"
+ syntax_reserved="#8c3c00"
syntax_comment="#cd8b00"
syntax_string="#ffcd8b"
syntax_numbers="#f0ad6d">
@@ -550,10 +608,17 @@
header="#3b3b3b"
header_text="#000000"
header_text_hi="#ffffff"
- button="#3b3b3b"
+ button="#3b3b3bff"
button_title="#8b8b8b"
button_text="#8b8b8b"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeTextEditor>
@@ -569,10 +634,17 @@
header="#3b3b3b"
header_text="#000000"
header_text_hi="#ffffff"
- button="#727272"
+ button="#727272ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeTimeline>
@@ -589,6 +661,8 @@
operator_node="#2c6f6f"
group_node="#1e7524"
frame_node="#9a9b9ba0"
+ matte_node="#977474"
+ distor_node="#749797"
noodle_curving="5">
<space>
<ThemeSpaceGeneric back="#3b3b3b"
@@ -598,10 +672,17 @@
header="#3b3b3b"
header_text="#000000"
header_text_hi="#ffffff"
- button="#3b3b3b"
+ button="#3b3b3b2f"
button_title="#8b8b8b"
button_text="#8b8b8b"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -614,7 +695,7 @@
</ThemeNodeEditor>
</node_editor>
<logic_editor>
- <ThemeLogicEditor panel="#3b3b3b">
+ <ThemeLogicEditor>
<space>
<ThemeSpaceGeneric back="#3b3b3b"
title="#000000"
@@ -623,10 +704,17 @@
header="#3b3b3b"
header_text="#000000"
header_text_hi="#ffffff"
- button="#3b3b3b"
+ button="#3b3b3bff"
button_title="#8b8b8b"
button_text="#8b8b8b"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeLogicEditor>
@@ -642,10 +730,17 @@
header="#3b3b3b"
header_text="#000000"
header_text_hi="#ffffff"
- button="#727272"
+ button="#727272ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeOutliner>
@@ -660,10 +755,17 @@
header="#3b3b3b"
header_text="#000000"
header_text_hi="#000000"
- button="#3b3b3b"
+ button="#3b3b3bff"
button_title="#000000"
button_text="#000000"
button_text_hi="#000000">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeInfo>
@@ -678,10 +780,17 @@
header="#3b3b3b"
header_text="#000000"
header_text_hi="#ffffff"
- button="#727272"
+ button="#727272ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeUserPreferences>
@@ -691,7 +800,8 @@
line_input="#ffffff"
line_info="#00aa00"
line_error="#dc6060"
- cursor="#dc6060">
+ cursor="#dc6060"
+ select="#4e4e8f80">
<space>
<ThemeSpaceGeneric back="#202020"
title="#000000"
@@ -700,10 +810,17 @@
header="#303030"
header_text="#000000"
header_text_hi="#ffffff"
- button="#3b3b3b"
+ button="#3b3b3bff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeConsole>
@@ -732,10 +849,17 @@
header="#313131"
header_text="#000000"
header_text_hi="#ffffff"
- button="#3b3b3b"
+ button="#3b3b3bff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="FALSE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
diff --git a/release/scripts/presets/interface_theme/hexagon.xml b/release/scripts/presets/interface_theme/hexagon.xml
index ad514bbbafa..299df3860f5 100644
--- a/release/scripts/presets/interface_theme/hexagon.xml
+++ b/release/scripts/presets/interface_theme/hexagon.xml
@@ -1,7 +1,9 @@
<bpy>
<Theme>
<user_interface>
- <ThemeUserInterface icon_file=""
+ <ThemeUserInterface menu_shadow_fac="0.5"
+ menu_shadow_width="12"
+ icon_file=""
icon_alpha="1"
axis_x="#dc0000"
axis_y="#00dc00"
@@ -220,16 +222,10 @@
blend="0.5">
</ThemeWidgetStateColors>
</wcol_state>
- <panel>
- <ThemePanelColors header="#00000019"
- show_header="TRUE">
- </ThemePanelColors>
- </panel>
</ThemeUserInterface>
</user_interface>
<view_3d>
<ThemeView3D grid="#5e5e83"
- panel="#a5a5a5ff"
wire="#000000"
lamp="#00000028"
speaker="#000000"
@@ -281,24 +277,35 @@
camera_path="#000000"
skin_root="#000000">
<space>
- <ThemeSpaceGeneric back="#7f818d"
- title="#000000"
- text="#000000"
- text_hi="#ffffff"
- header="#646875"
- header_text="#000000"
- header_text_hi="#ffffff"
- button="#6c717f"
- button_title="#eaeaea"
- button_text="#d7d7d7"
- button_text_hi="#ffffff">
- </ThemeSpaceGeneric>
+ <ThemeSpaceGradient title="#000000"
+ text="#000000"
+ text_hi="#ffffff"
+ header="#646875"
+ header_text="#000000"
+ header_text_hi="#ffffff"
+ button="#6c717f57"
+ button_title="#eaeaea"
+ button_text="#d7d7d7"
+ button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ <gradients>
+ <ThemeGradientColors show_grad="FALSE"
+ gradient="#000000"
+ high_gradient="#7f818d">
+ </ThemeGradientColors>
+ </gradients>
+ </ThemeSpaceGradient>
</space>
</ThemeView3D>
</view_3d>
<graph_editor>
<ThemeGraphEditor grid="#58587c"
- panel="#ffffff"
window_sliders="#969696"
channels_region="#707070"
vertex="#000000"
@@ -331,10 +338,17 @@
header="#5c606c"
header_text="#000000"
header_text_hi="#ffffff"
- button="#646875"
+ button="#646875ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -348,7 +362,6 @@
</graph_editor>
<file_browser>
<ThemeFileBrowser selected_file="#69a5be"
- tiles="#5c606c"
scrollbar="#a0a0a0"
scroll_handle="#7f7070"
active_file="#859cb9"
@@ -361,10 +374,17 @@
header="#5c606c"
header_text="#dddddd"
header_text_hi="#ffffff"
- button="#6c717f"
+ button="#6c717fff"
button_title="#d7d7d7"
button_text="#d7d7d7"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -400,10 +420,17 @@
header="#5c606c"
header_text="#000000"
header_text_hi="#ffffff"
- button="#646875"
+ button="#646875ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -437,10 +464,17 @@
header="#5c606c"
header_text="#000000"
header_text_hi="#ffffff"
- button="#6c717f"
+ button="#6c717fff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -476,10 +510,17 @@
header="#5c606c"
header_text="#000000"
header_text_hi="#ffffff"
- button="#646875"
+ button="#646875ff"
button_title="#eeeeee"
button_text="#eeeeee"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeImageEditor>
@@ -507,16 +548,23 @@
header="#5c606c"
header_text="#000000"
header_text_hi="#ffffff"
- button="#646875"
+ button="#64687542"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeSequenceEditor>
</sequence_editor>
<properties>
- <ThemeProperties panel="#828282">
+ <ThemeProperties>
<space>
<ThemeSpaceGeneric back="#646875"
title="#ffffff"
@@ -525,10 +573,17 @@
header="#646875"
header_text="#000000"
header_text_hi="#ffffff"
- button="#727272"
+ button="#727272ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeProperties>
@@ -538,7 +593,10 @@
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">
@@ -550,10 +608,17 @@
header="#5c606c"
header_text="#000000"
header_text_hi="#ffffff"
- button="#646875"
+ button="#646875ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeTextEditor>
@@ -569,10 +634,17 @@
header="#565863"
header_text="#000000"
header_text_hi="#ffffff"
- button="#5a5e6a"
+ button="#5a5e6aff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeTimeline>
@@ -589,6 +661,8 @@
operator_node="#6c697e"
group_node="#69756e"
frame_node="#9a9b9ba0"
+ matte_node="#977474"
+ distor_node="#749797"
noodle_curving="5">
<space>
<ThemeSpaceGeneric back="#7c7e88"
@@ -598,10 +672,17 @@
header="#5c606c"
header_text="#000000"
header_text_hi="#ffffff"
- button="#646875"
+ button="#6468752f"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -614,7 +695,7 @@
</ThemeNodeEditor>
</node_editor>
<logic_editor>
- <ThemeLogicEditor panel="#a5a5a5">
+ <ThemeLogicEditor>
<space>
<ThemeSpaceGeneric back="#7c7e88"
title="#000000"
@@ -623,10 +704,17 @@
header="#5c606c"
header_text="#000000"
header_text_hi="#ffffff"
- button="#6c717f"
+ button="#6c717fff"
button_title="#d7d7d7"
button_text="#d7d7d7"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeLogicEditor>
@@ -642,10 +730,17 @@
header="#6c717f"
header_text="#000000"
header_text_hi="#ffffff"
- button="#727272"
+ button="#727272ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeOutliner>
@@ -660,10 +755,17 @@
header="#646875"
header_text="#dddddd"
header_text_hi="#ffffff"
- button="#b4b4b4"
+ button="#b4b4b4ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeInfo>
@@ -678,10 +780,17 @@
header="#5c606c"
header_text="#000000"
header_text_hi="#ffffff"
- button="#6c717f"
+ button="#6c717fff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeUserPreferences>
@@ -691,7 +800,8 @@
line_input="#ffffff"
line_info="#00aa00"
line_error="#dc0606"
- cursor="#dc6060">
+ cursor="#dc6060"
+ select="#ffffff30">
<space>
<ThemeSpaceGeneric back="#7c7e88"
title="#000000"
@@ -700,10 +810,17 @@
header="#5c606c"
header_text="#000000"
header_text_hi="#ffffff"
- button="#6c717f"
+ button="#6c717fff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeConsole>
@@ -732,10 +849,17 @@
header="#5c606c"
header_text="#000000"
header_text_hi="#ffffff"
- button="#646875"
+ button="#646875ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000019"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
diff --git a/release/scripts/presets/interface_theme/ubuntu_ambiance.xml b/release/scripts/presets/interface_theme/ubuntu_ambiance.xml
index 8f4a42b6ab7..38ab35d4b7b 100644
--- a/release/scripts/presets/interface_theme/ubuntu_ambiance.xml
+++ b/release/scripts/presets/interface_theme/ubuntu_ambiance.xml
@@ -1,7 +1,9 @@
<bpy>
<Theme>
<user_interface>
- <ThemeUserInterface icon_file=""
+ <ThemeUserInterface menu_shadow_fac="0.5"
+ menu_shadow_width="12"
+ icon_file=""
icon_alpha="1"
axis_x="#dc0000"
axis_y="#00dc00"
@@ -220,16 +222,10 @@
blend="0.1">
</ThemeWidgetStateColors>
</wcol_state>
- <panel>
- <ThemePanelColors header="#00000000"
- show_header="TRUE">
- </ThemePanelColors>
- </panel>
</ThemeUserInterface>
</user_interface>
<view_3d>
<ThemeView3D grid="#3c3b37"
- panel="#a5a5a57f"
wire="#93237f"
lamp="#ffffff34"
speaker="#93237f"
@@ -281,24 +277,35 @@
camera_path="#7dbd00"
skin_root="#000000">
<space>
- <ThemeSpaceGeneric back="#131311"
- title="#9c9c9c"
- text="#9c9c9c"
- text_hi="#ffffff"
- header="#464541"
- header_text="#acacac"
- header_text_hi="#ffffff"
- button="#3c3b37"
- button_title="#9c9c9c"
- button_text="#9c9c9c"
- button_text_hi="#ffffff">
- </ThemeSpaceGeneric>
+ <ThemeSpaceGradient title="#9c9c9c"
+ text="#9c9c9c"
+ text_hi="#ffffff"
+ header="#464541"
+ header_text="#acacac"
+ header_text_hi="#ffffff"
+ button="#3c3b3757"
+ button_title="#9c9c9c"
+ button_text="#9c9c9c"
+ button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000000"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
+ <gradients>
+ <ThemeGradientColors show_grad="FALSE"
+ gradient="#000000"
+ high_gradient="#131311">
+ </ThemeGradientColors>
+ </gradients>
+ </ThemeSpaceGradient>
</space>
</ThemeView3D>
</view_3d>
<graph_editor>
<ThemeGraphEditor grid="#3c3b37"
- panel="#ffffff"
window_sliders="#95948f"
channels_region="#707070"
vertex="#ffffff"
@@ -331,10 +338,17 @@
header="#464541"
header_text="#acacac"
header_text_hi="#ffffff"
- button="#3c3b37"
+ button="#3c3b37ff"
button_title="#9c9c9c"
button_text="#9c9c9c"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000000"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -348,7 +362,6 @@
</graph_editor>
<file_browser>
<ThemeFileBrowser selected_file="#6b395a"
- tiles="#3c3b37"
scrollbar="#a0a0a0"
scroll_handle="#7f7070"
active_file="#eeedeb"
@@ -361,10 +374,17 @@
header="#464541"
header_text="#acacac"
header_text_hi="#ffffff"
- button="#727272"
+ button="#727272ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000000"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -400,10 +420,17 @@
header="#464541"
header_text="#acacac"
header_text_hi="#ffffff"
- button="#3c3b37"
+ button="#3c3b37ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000000"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -437,10 +464,17 @@
header="#464541"
header_text="#cacaca"
header_text_hi="#ffffff"
- button="#3c3b37"
+ button="#3c3b37ff"
button_title="#9c9c9c"
button_text="#9c9c9c"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000000"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -476,10 +510,17 @@
header="#464541"
header_text="#acacac"
header_text_hi="#ffffff"
- button="#3c3b37"
+ button="#3c3b37ff"
button_title="#b1b1b1"
button_text="#b9b9b9"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000000"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeImageEditor>
@@ -507,16 +548,23 @@
header="#464541"
header_text="#acacac"
header_text_hi="#ffffff"
- button="#3c3b37"
+ button="#3c3b3742"
button_title="#acacac"
button_text="#acacac"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000000"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeSequenceEditor>
</sequence_editor>
<properties>
- <ThemeProperties panel="#3c3b37">
+ <ThemeProperties>
<space>
<ThemeSpaceGeneric back="#3c3b37"
title="#acacac"
@@ -525,10 +573,17 @@
header="#464541"
header_text="#acacac"
header_text_hi="#ffffff"
- button="#3c3b37"
+ button="#3c3b37ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000000"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeProperties>
@@ -538,7 +593,10 @@
selected_text="#641f44"
cursor="#f47421"
syntax_builtin="#d6ff01"
+ syntax_symbols="#4c4c4c"
syntax_special="#33a500"
+ syntax_preprocessor="#be00ff"
+ syntax_reserved="#8c3c00"
syntax_comment="#249d60"
syntax_string="#6e00ff"
syntax_numbers="#972144">
@@ -550,10 +608,17 @@
header="#464541"
header_text="#acacac"
header_text_hi="#ffffff"
- button="#191919"
+ button="#191919ff"
button_title="#64645e"
button_text="#95948f"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000000"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeTextEditor>
@@ -569,10 +634,17 @@
header="#464541"
header_text="#acacac"
header_text_hi="#ffffff"
- button="#3c3b37"
+ button="#3c3b37ff"
button_title="#9c9c9c"
button_text="#9c9c9c"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000000"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeTimeline>
@@ -589,6 +661,8 @@
operator_node="#000000"
group_node="#19b6ee"
frame_node="#9a9b9ba0"
+ matte_node="#977474"
+ distor_node="#749797"
noodle_curving="5">
<space>
<ThemeSpaceGeneric back="#29001b"
@@ -598,10 +672,17 @@
header="#464541"
header_text="#acacac"
header_text_hi="#ffffff"
- button="#353430"
+ button="#3534302f"
button_title="#acacac"
button_text="#acacac"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000000"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
@@ -614,7 +695,7 @@
</ThemeNodeEditor>
</node_editor>
<logic_editor>
- <ThemeLogicEditor panel="#acacac">
+ <ThemeLogicEditor>
<space>
<ThemeSpaceGeneric back="#29001b"
title="#000000"
@@ -623,10 +704,17 @@
header="#464541"
header_text="#acacac"
header_text_hi="#ffffff"
- button="#353430"
+ button="#353430ff"
button_title="#7d7d7d"
button_text="#acacac"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000000"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeLogicEditor>
@@ -642,10 +730,17 @@
header="#464541"
header_text="#acacac"
header_text_hi="#ffffff"
- button="#3c3b37"
+ button="#3c3b37ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#f47421">
+ <panelcolors>
+ <ThemePanelColors header="#00000000"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeOutliner>
@@ -660,10 +755,17 @@
header="#464541"
header_text="#ffffff"
header_text_hi="#ffffff"
- button="#3c3b37"
+ button="#3c3b37ff"
button_title="#eeedeb"
button_text="#eeedeb"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000000"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeInfo>
@@ -678,10 +780,17 @@
header="#3c3b37"
header_text="#d3d2cd"
header_text_hi="#ffffff"
- button="#696965"
+ button="#696965ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000000"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeUserPreferences>
@@ -691,7 +800,8 @@
line_input="#19b6ee"
line_info="#f47421"
line_error="#ff0000"
- cursor="#f47421">
+ cursor="#f47421"
+ select="#641f4480">
<space>
<ThemeSpaceGeneric back="#131311"
title="#000000"
@@ -700,10 +810,17 @@
header="#464541"
header_text="#acacac"
header_text_hi="#ffffff"
- button="#3c3b37"
+ button="#3c3b37ff"
button_title="#000000"
button_text="#000000"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000000"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
</ThemeConsole>
@@ -732,10 +849,17 @@
header="#464541"
header_text="#9c9c9c"
header_text_hi="#ffffff"
- button="#3c3b37"
+ button="#3c3b37ff"
button_title="#9c9c9c"
button_text="#ffffff"
button_text_hi="#ffffff">
+ <panelcolors>
+ <ThemePanelColors header="#00000000"
+ back="#72727280"
+ show_header="TRUE"
+ show_back="FALSE">
+ </ThemePanelColors>
+ </panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
diff --git a/release/scripts/presets/keyconfig/3dsmax.py b/release/scripts/presets/keyconfig/3dsmax.py
new file mode 100644
index 00000000000..6a719c2619c
--- /dev/null
+++ b/release/scripts/presets/keyconfig/3dsmax.py
@@ -0,0 +1,1359 @@
+# Configuration 3dsmax
+import bpy
+
+wm = bpy.context.window_manager
+kc = wm.keyconfigs.new('3dsmax')
+
+# Map 3D View
+km = kc.keymaps.new('3D View', space_type='VIEW_3D', region_type='WINDOW', modal=False)
+
+kmi = km.keymap_items.new('view3d.manipulator', 'LEFTMOUSE', 'PRESS', any=True)
+kmi.properties.release_confirm = True
+kmi = km.keymap_items.new('view3d.cursor3d', 'ACTIONMOUSE', 'PRESS')
+kmi = km.keymap_items.new('view3d.rotate', 'MIDDLEMOUSE', 'PRESS', alt=True)
+kmi = km.keymap_items.new('view3d.move', 'MIDDLEMOUSE', 'PRESS')
+kmi = km.keymap_items.new('view3d.zoom', 'MIDDLEMOUSE', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('view3d.dolly', 'MIDDLEMOUSE', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('view3d.view_selected', 'NUMPAD_PERIOD', 'PRESS', ctrl=True)
+kmi.properties.use_all_regions = True
+kmi = km.keymap_items.new('view3d.view_selected', 'NUMPAD_PERIOD', 'PRESS')
+kmi.properties.use_all_regions = False
+kmi = km.keymap_items.new('view3d.view_lock_to_active', 'NUMPAD_PERIOD', 'PRESS', shift=True)
+kmi = km.keymap_items.new('view3d.view_lock_clear', 'NUMPAD_PERIOD', 'PRESS', alt=True)
+kmi = km.keymap_items.new('view3d.fly', 'F', 'PRESS', shift=True)
+kmi = km.keymap_items.new('view3d.smoothview', 'TIMER1', 'ANY', any=True)
+kmi = km.keymap_items.new('view3d.rotate', 'TRACKPADPAN', 'ANY')
+kmi = km.keymap_items.new('view3d.rotate', 'MOUSEROTATE', 'ANY')
+kmi = km.keymap_items.new('view3d.move', 'TRACKPADPAN', 'ANY', shift=True)
+kmi = km.keymap_items.new('view3d.zoom', 'TRACKPADZOOM', 'ANY')
+kmi = km.keymap_items.new('view3d.zoom', 'TRACKPADPAN', 'ANY', ctrl=True)
+kmi = km.keymap_items.new('view3d.zoom', 'NUMPAD_PLUS', 'PRESS')
+kmi.properties.delta = 1
+kmi = km.keymap_items.new('view3d.zoom', 'NUMPAD_MINUS', 'PRESS')
+kmi.properties.delta = -1
+kmi = km.keymap_items.new('view3d.zoom', 'EQUAL', 'PRESS', ctrl=True)
+kmi.properties.delta = 1
+kmi = km.keymap_items.new('view3d.zoom', 'MINUS', 'PRESS', ctrl=True)
+kmi.properties.delta = -1
+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_camera_1_to_1', 'NUMPAD_ENTER', 'PRESS', shift=True)
+kmi = km.keymap_items.new('view3d.view_center_camera', 'HOME', 'PRESS')
+kmi = km.keymap_items.new('view3d.view_center_cursor', 'HOME', 'PRESS', alt=True)
+kmi = km.keymap_items.new('view3d.view_all', 'HOME', 'PRESS')
+kmi.properties.center = False
+kmi = km.keymap_items.new('view3d.view_all', 'HOME', 'PRESS', ctrl=True)
+kmi.properties.use_all_regions = True
+kmi.properties.center = False
+kmi = km.keymap_items.new('view3d.view_all', 'C', 'PRESS', shift=True)
+kmi.properties.center = True
+kmi = km.keymap_items.new('view3d.viewnumpad', 'C', 'PRESS')
+kmi.properties.type = 'CAMERA'
+kmi = km.keymap_items.new('view3d.viewnumpad', 'F', 'PRESS')
+kmi.properties.type = 'FRONT'
+kmi = km.keymap_items.new('view3d.view_orbit', 'NUMPAD_2', 'PRESS')
+kmi.properties.type = 'ORBITDOWN'
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_3', 'PRESS')
+kmi.properties.type = 'RIGHT'
+kmi = km.keymap_items.new('view3d.view_orbit', 'NUMPAD_4', 'PRESS')
+kmi.properties.type = 'ORBITLEFT'
+kmi = km.keymap_items.new('view3d.view_persportho', 'NUMPAD_5', 'PRESS')
+kmi = km.keymap_items.new('view3d.view_orbit', 'NUMPAD_6', 'PRESS')
+kmi.properties.type = 'ORBITRIGHT'
+kmi = km.keymap_items.new('view3d.viewnumpad', 'T', 'PRESS')
+kmi.properties.type = 'TOP'
+kmi = km.keymap_items.new('view3d.view_orbit', 'NUMPAD_8', 'PRESS')
+kmi.properties.type = 'ORBITUP'
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_1', 'PRESS', ctrl=True)
+kmi.properties.type = 'BACK'
+kmi = km.keymap_items.new('view3d.viewnumpad', 'L', 'PRESS')
+kmi.properties.type = 'LEFT'
+kmi = km.keymap_items.new('view3d.viewnumpad', 'B', 'PRESS')
+kmi.properties.type = 'BOTTOM'
+kmi = km.keymap_items.new('view3d.view_pan', 'NUMPAD_2', 'PRESS', ctrl=True)
+kmi.properties.type = 'PANDOWN'
+kmi = km.keymap_items.new('view3d.view_pan', 'NUMPAD_4', 'PRESS', ctrl=True)
+kmi.properties.type = 'PANLEFT'
+kmi = km.keymap_items.new('view3d.view_pan', 'NUMPAD_6', 'PRESS', ctrl=True)
+kmi.properties.type = 'PANRIGHT'
+kmi = km.keymap_items.new('view3d.view_pan', 'NUMPAD_8', 'PRESS', ctrl=True)
+kmi.properties.type = 'PANUP'
+kmi = km.keymap_items.new('view3d.view_pan', 'WHEELUPMOUSE', 'PRESS', ctrl=True)
+kmi.properties.type = 'PANRIGHT'
+kmi = km.keymap_items.new('view3d.view_pan', 'WHEELDOWNMOUSE', 'PRESS', ctrl=True)
+kmi.properties.type = 'PANLEFT'
+kmi = km.keymap_items.new('view3d.view_pan', 'WHEELUPMOUSE', 'PRESS', shift=True)
+kmi.properties.type = 'PANUP'
+kmi = km.keymap_items.new('view3d.view_pan', 'WHEELDOWNMOUSE', 'PRESS', shift=True)
+kmi.properties.type = 'PANDOWN'
+kmi = km.keymap_items.new('view3d.view_orbit', 'WHEELUPMOUSE', 'PRESS', ctrl=True, alt=True)
+kmi.properties.type = 'ORBITLEFT'
+kmi = km.keymap_items.new('view3d.view_orbit', 'WHEELDOWNMOUSE', 'PRESS', ctrl=True, alt=True)
+kmi.properties.type = 'ORBITRIGHT'
+kmi = km.keymap_items.new('view3d.view_orbit', 'WHEELUPMOUSE', 'PRESS', shift=True, alt=True)
+kmi.properties.type = 'ORBITUP'
+kmi = km.keymap_items.new('view3d.view_orbit', 'WHEELDOWNMOUSE', 'PRESS', shift=True, alt=True)
+kmi.properties.type = 'ORBITDOWN'
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_1', 'PRESS', shift=True)
+kmi.properties.type = 'FRONT'
+kmi.properties.align_active = True
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_3', 'PRESS', shift=True)
+kmi.properties.type = 'RIGHT'
+kmi.properties.align_active = True
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_7', 'PRESS', shift=True)
+kmi.properties.type = 'TOP'
+kmi.properties.align_active = True
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_1', 'PRESS', shift=True, ctrl=True)
+kmi.properties.type = 'BACK'
+kmi.properties.align_active = True
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_3', 'PRESS', shift=True, ctrl=True)
+kmi.properties.type = 'LEFT'
+kmi.properties.align_active = True
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_7', 'PRESS', shift=True, ctrl=True)
+kmi.properties.type = 'BOTTOM'
+kmi.properties.align_active = True
+kmi = km.keymap_items.new('view3d.localview', 'NUMPAD_SLASH', 'PRESS')
+kmi = km.keymap_items.new('view3d.ndof_orbit_zoom', 'NDOF_MOTION', 'ANY')
+kmi = km.keymap_items.new('view3d.ndof_orbit', 'NDOF_MOTION', 'ANY', ctrl=True)
+kmi = km.keymap_items.new('view3d.ndof_pan', 'NDOF_MOTION', 'ANY', shift=True)
+kmi = km.keymap_items.new('view3d.ndof_all', 'NDOF_MOTION', 'ANY', shift=True, ctrl=True)
+kmi = km.keymap_items.new('view3d.view_selected', 'NDOF_BUTTON_FIT', 'PRESS')
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NDOF_BUTTON_FRONT', 'PRESS')
+kmi.properties.type = 'FRONT'
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NDOF_BUTTON_BACK', 'PRESS')
+kmi.properties.type = 'BACK'
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NDOF_BUTTON_LEFT', 'PRESS')
+kmi.properties.type = 'LEFT'
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NDOF_BUTTON_RIGHT', 'PRESS')
+kmi.properties.type = 'RIGHT'
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NDOF_BUTTON_TOP', 'PRESS')
+kmi.properties.type = 'TOP'
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NDOF_BUTTON_BOTTOM', 'PRESS')
+kmi.properties.type = 'BOTTOM'
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NDOF_BUTTON_FRONT', 'PRESS', shift=True)
+kmi.properties.type = 'FRONT'
+kmi.properties.align_active = True
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NDOF_BUTTON_RIGHT', 'PRESS', shift=True)
+kmi.properties.type = 'RIGHT'
+kmi.properties.align_active = True
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NDOF_BUTTON_TOP', 'PRESS', shift=True)
+kmi.properties.type = 'TOP'
+kmi.properties.align_active = True
+kmi = km.keymap_items.new('view3d.layers', 'ACCENT_GRAVE', 'PRESS')
+kmi.properties.nr = 0
+kmi = km.keymap_items.new('view3d.layers', 'ONE', 'PRESS', any=True)
+kmi.properties.nr = 1
+kmi = km.keymap_items.new('view3d.layers', 'TWO', 'PRESS', any=True)
+kmi.properties.nr = 2
+kmi = km.keymap_items.new('view3d.layers', 'THREE', 'PRESS', any=True)
+kmi.properties.nr = 3
+kmi = km.keymap_items.new('view3d.layers', 'FOUR', 'PRESS', any=True)
+kmi.properties.nr = 4
+kmi = km.keymap_items.new('view3d.layers', 'FIVE', 'PRESS', any=True)
+kmi.properties.nr = 5
+kmi = km.keymap_items.new('view3d.layers', 'SIX', 'PRESS', any=True)
+kmi.properties.nr = 6
+kmi = km.keymap_items.new('view3d.layers', 'SEVEN', 'PRESS', any=True)
+kmi.properties.nr = 7
+kmi = km.keymap_items.new('view3d.layers', 'EIGHT', 'PRESS', any=True)
+kmi.properties.nr = 8
+kmi = km.keymap_items.new('view3d.layers', 'NINE', 'PRESS', any=True)
+kmi.properties.nr = 9
+kmi = km.keymap_items.new('view3d.layers', 'ZERO', 'PRESS', any=True)
+kmi.properties.nr = 10
+kmi = km.keymap_items.new('wm.context_toggle_enum', 'Z', 'PRESS')
+kmi.properties.data_path = 'space_data.viewport_shade'
+kmi.properties.value_1 = 'SOLID'
+kmi.properties.value_2 = 'WIREFRAME'
+kmi = km.keymap_items.new('wm.context_toggle_enum', 'Z', 'PRESS', alt=True)
+kmi.properties.data_path = 'space_data.viewport_shade'
+kmi.properties.value_1 = 'SOLID'
+kmi.properties.value_2 = 'TEXTURED'
+kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE')
+kmi.properties.extend = False
+kmi.properties.deselect = False
+kmi.properties.toggle = False
+kmi.properties.center = False
+kmi.properties.enumerate = False
+kmi.properties.object = False
+kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', ctrl=True)
+kmi.properties.extend = False
+kmi.properties.deselect = False
+kmi.properties.toggle = True
+kmi.properties.center = False
+kmi.properties.enumerate = False
+kmi.properties.object = False
+kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True)
+kmi.properties.extend = False
+kmi.properties.deselect = False
+kmi.properties.toggle = False
+kmi.properties.center = True
+kmi.properties.enumerate = False
+kmi.properties.object = True
+kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', alt=True)
+kmi.properties.extend = False
+kmi.properties.deselect = False
+kmi.properties.toggle = False
+kmi.properties.center = False
+kmi.properties.enumerate = True
+kmi.properties.object = False
+kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', shift=True, ctrl=True)
+kmi.properties.extend = True
+kmi.properties.deselect = False
+kmi.properties.toggle = True
+kmi.properties.center = True
+kmi.properties.enumerate = False
+kmi.properties.object = False
+kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', ctrl=True, alt=True)
+kmi.properties.extend = False
+kmi.properties.deselect = False
+kmi.properties.toggle = False
+kmi.properties.center = True
+kmi.properties.enumerate = True
+kmi.properties.object = False
+kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', shift=True, alt=True)
+kmi.properties.extend = False
+kmi.properties.deselect = False
+kmi.properties.toggle = True
+kmi.properties.center = False
+kmi.properties.enumerate = True
+kmi.properties.object = False
+kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', shift=True, ctrl=True, alt=True)
+kmi.properties.extend = False
+kmi.properties.deselect = False
+kmi.properties.toggle = True
+kmi.properties.center = True
+kmi.properties.enumerate = True
+kmi.properties.object = False
+kmi = km.keymap_items.new('view3d.select_border', 'EVT_TWEAK_L', 'ANY')
+kmi.properties.extend = False
+kmi = km.keymap_items.new('view3d.select_lasso', 'EVT_TWEAK_A', 'ANY', ctrl=True)
+kmi.properties.deselect = False
+kmi = km.keymap_items.new('view3d.select_lasso', 'EVT_TWEAK_A', 'ANY', shift=True, ctrl=True)
+kmi.properties.deselect = True
+kmi = km.keymap_items.new('view3d.select_circle', 'C', 'PRESS', alt=True)
+kmi = km.keymap_items.new('view3d.clip_border', 'B', 'PRESS', alt=True)
+kmi = km.keymap_items.new('view3d.zoom_border', 'B', 'PRESS', shift=True)
+kmi = km.keymap_items.new('view3d.render_border', 'B', 'PRESS', shift=True)
+kmi.properties.camera_only = True
+kmi = km.keymap_items.new('view3d.render_border', 'B', 'PRESS', ctrl=True)
+kmi.properties.camera_only = False
+kmi = km.keymap_items.new('view3d.clear_render_border', 'B', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('view3d.camera_to_view', 'NUMPAD_0', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('view3d.object_as_camera', 'NUMPAD_0', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.call_menu', 'S', 'PRESS', shift=True)
+kmi.properties.name = 'VIEW3D_MT_snap'
+kmi = km.keymap_items.new('view3d.copybuffer', 'C', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('view3d.pastebuffer', 'V', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.context_set_enum', 'COMMA', 'PRESS')
+kmi.properties.data_path = 'space_data.pivot_point'
+kmi.properties.value = 'BOUNDING_BOX_CENTER'
+kmi = km.keymap_items.new('wm.context_set_enum', 'COMMA', 'PRESS', ctrl=True)
+kmi.properties.data_path = 'space_data.pivot_point'
+kmi.properties.value = 'MEDIAN_POINT'
+kmi = km.keymap_items.new('wm.context_toggle', 'COMMA', 'PRESS', alt=True)
+kmi.properties.data_path = 'space_data.use_pivot_point_align'
+kmi = km.keymap_items.new('wm.context_toggle', 'SPACE', 'PRESS', ctrl=True)
+kmi.properties.data_path = 'space_data.show_manipulator'
+kmi = km.keymap_items.new('wm.context_set_enum', 'PERIOD', 'PRESS')
+kmi.properties.data_path = 'space_data.pivot_point'
+kmi.properties.value = 'CURSOR'
+kmi = km.keymap_items.new('wm.context_set_enum', 'PERIOD', 'PRESS', ctrl=True)
+kmi.properties.data_path = 'space_data.pivot_point'
+kmi.properties.value = 'INDIVIDUAL_ORIGINS'
+kmi = km.keymap_items.new('wm.context_set_enum', 'PERIOD', 'PRESS', alt=True)
+kmi.properties.data_path = 'space_data.pivot_point'
+kmi.properties.value = 'ACTIVE_ELEMENT'
+kmi = km.keymap_items.new('transform.translate', 'W', 'PRESS', shift=True)
+kmi = km.keymap_items.new('transform.translate', 'EVT_TWEAK_S', 'ANY')
+kmi = km.keymap_items.new('transform.rotate', 'E', 'PRESS', shift=True)
+kmi = km.keymap_items.new('transform.resize', 'R', 'PRESS', shift=True)
+kmi = km.keymap_items.new('transform.warp', 'Q', 'PRESS', shift=True)
+kmi = km.keymap_items.new('transform.tosphere', 'S', 'PRESS', shift=True, alt=True)
+kmi = km.keymap_items.new('transform.shear', 'S', 'PRESS', shift=True, ctrl=True, alt=True)
+kmi = km.keymap_items.new('transform.select_orientation', 'SPACE', 'PRESS', alt=True)
+kmi = km.keymap_items.new('transform.create_orientation', 'SPACE', 'PRESS', ctrl=True, alt=True)
+kmi.properties.use = True
+kmi = km.keymap_items.new('transform.mirror', 'M', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.context_toggle', 'TAB', 'PRESS', shift=True)
+kmi.properties.data_path = 'tool_settings.use_snap'
+kmi = km.keymap_items.new('wm.context_menu_enum', 'TAB', 'PRESS', shift=True, ctrl=True)
+kmi.properties.data_path = 'tool_settings.snap_element'
+kmi = km.keymap_items.new('transform.translate', 'T', 'PRESS', shift=True)
+kmi.properties.texture_space = True
+kmi = km.keymap_items.new('transform.resize', 'T', 'PRESS', shift=True, alt=True)
+kmi.properties.texture_space = True
+kmi = km.keymap_items.new('transform.skin_resize', 'A', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('view3d.enable_manipulator', 'W', 'PRESS')
+kmi.properties.translate = True
+kmi = km.keymap_items.new('view3d.enable_manipulator', 'E', 'PRESS')
+kmi.properties.rotate = True
+kmi = km.keymap_items.new('view3d.enable_manipulator', 'R', 'PRESS')
+kmi.properties.scale = True
+kmi = km.keymap_items.new('wm.context_toggle', 'S', 'PRESS')
+kmi.properties.data_path = 'tool_settings.use_snap'
+kmi = km.keymap_items.new('wm.context_toggle_enum', 'A', 'PRESS')
+kmi.properties.data_path = 'tool_settings.snap_element'
+kmi.properties.value_1 = 'VERTEX'
+kmi.properties.value_2 = 'INCREMENT'
+kmi = km.keymap_items.new('view3d.select_border', 'EVT_TWEAK_L', 'ANY', ctrl=True)
+kmi = km.keymap_items.new('wm.context_toggle', 'G', 'PRESS')
+kmi.properties.data_path = 'space_data.show_floor'
+
+# Map 3D View Generic
+km = kc.keymaps.new('3D View Generic', space_type='VIEW_3D', region_type='WINDOW', modal=False)
+
+kmi = km.keymap_items.new('view3d.properties', 'N', 'PRESS')
+kmi = km.keymap_items.new('view3d.toolshelf', 'D', 'PRESS')
+
+# Map Weight Paint Vertex Selection
+km = kc.keymaps.new('Weight Paint Vertex Selection', space_type='EMPTY', region_type='WINDOW', modal=False)
+
+kmi = km.keymap_items.new('paint.vert_select_all', 'A', 'PRESS')
+kmi = km.keymap_items.new('paint.vert_select_inverse', 'I', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('view3d.select_border', 'B', 'PRESS')
+kmi = km.keymap_items.new('view3d.select_lasso', 'EVT_TWEAK_A', 'ANY', ctrl=True)
+kmi.properties.deselect = False
+kmi = km.keymap_items.new('view3d.select_lasso', 'EVT_TWEAK_A', 'ANY', shift=True, ctrl=True)
+kmi.properties.deselect = True
+kmi = km.keymap_items.new('view3d.select_circle', 'C', 'PRESS', alt=True)
+
+# Map Pose
+km = kc.keymaps.new('Pose', space_type='EMPTY', region_type='WINDOW', modal=False)
+
+kmi = km.keymap_items.new('object.parent_set', 'P', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', shift=True)
+kmi.properties.name = 'INFO_MT_add'
+kmi = km.keymap_items.new('pose.hide', 'H', 'PRESS')
+kmi.properties.unselected = False
+kmi = km.keymap_items.new('pose.hide', 'H', 'PRESS', shift=True)
+kmi.properties.unselected = True
+kmi = km.keymap_items.new('pose.reveal', 'H', 'PRESS', alt=True)
+kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', ctrl=True)
+kmi.properties.name = 'VIEW3D_MT_pose_apply'
+kmi = km.keymap_items.new('pose.rot_clear', 'R', 'PRESS', alt=True)
+kmi = km.keymap_items.new('pose.loc_clear', 'G', 'PRESS', alt=True)
+kmi = km.keymap_items.new('pose.scale_clear', 'S', 'PRESS', alt=True)
+kmi = km.keymap_items.new('pose.quaternions_flip', 'F', 'PRESS', alt=True)
+kmi = km.keymap_items.new('pose.rotation_mode_set', 'R', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('pose.copy', 'C', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('pose.paste', 'V', 'PRESS', ctrl=True)
+kmi.properties.flipped = False
+kmi = km.keymap_items.new('pose.paste', 'V', 'PRESS', shift=True, ctrl=True)
+kmi.properties.flipped = True
+kmi = km.keymap_items.new('pose.select_all', 'LEFTMOUSE', 'CLICK')
+kmi.properties.action = 'TOGGLE'
+kmi = km.keymap_items.new('pose.select_all', 'I', 'PRESS', ctrl=True)
+kmi.properties.action = 'INVERT'
+kmi = km.keymap_items.new('pose.select_parent', 'P', 'PRESS', shift=True)
+kmi = km.keymap_items.new('pose.select_hierarchy', 'LEFT_BRACKET', 'PRESS')
+kmi.properties.direction = 'PARENT'
+kmi.properties.extend = False
+kmi = km.keymap_items.new('pose.select_hierarchy', 'LEFT_BRACKET', 'PRESS', shift=True)
+kmi.properties.direction = 'PARENT'
+kmi.properties.extend = True
+kmi = km.keymap_items.new('pose.select_hierarchy', 'RIGHT_BRACKET', 'PRESS')
+kmi.properties.direction = 'CHILD'
+kmi.properties.extend = False
+kmi = km.keymap_items.new('pose.select_hierarchy', 'RIGHT_BRACKET', 'PRESS', shift=True)
+kmi.properties.direction = 'CHILD'
+kmi.properties.extend = True
+kmi = km.keymap_items.new('pose.select_linked', 'L', 'PRESS', alt=True)
+kmi = km.keymap_items.new('pose.select_grouped', 'G', 'PRESS', shift=True)
+kmi = km.keymap_items.new('pose.select_flip_active', 'F', 'PRESS', shift=True)
+kmi = km.keymap_items.new('pose.constraint_add_with_targets', 'C', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('pose.constraints_clear', 'C', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('pose.ik_add', 'I', 'PRESS', shift=True)
+kmi = km.keymap_items.new('pose.ik_clear', 'I', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('wm.call_menu', 'G', 'PRESS', ctrl=True)
+kmi.properties.name = 'VIEW3D_MT_pose_group'
+kmi = km.keymap_items.new('wm.call_menu', 'W', 'PRESS', shift=True)
+kmi.properties.name = 'VIEW3D_MT_bone_options_toggle'
+kmi = km.keymap_items.new('wm.call_menu', 'W', 'PRESS', shift=True, ctrl=True)
+kmi.properties.name = 'VIEW3D_MT_bone_options_enable'
+kmi = km.keymap_items.new('wm.call_menu', 'W', 'PRESS', alt=True)
+kmi.properties.name = 'VIEW3D_MT_bone_options_disable'
+kmi = km.keymap_items.new('armature.layers_show_all', 'ACCENT_GRAVE', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('pose.armature_layers', 'M', 'PRESS', shift=True)
+kmi = km.keymap_items.new('pose.bone_layers', 'M', 'PRESS')
+kmi = km.keymap_items.new('transform.transform', 'S', 'PRESS', ctrl=True, alt=True)
+kmi.properties.mode = 'BONE_SIZE'
+kmi = km.keymap_items.new('anim.keyframe_insert_menu', 'I', 'PRESS')
+kmi = km.keymap_items.new('anim.keyframe_delete_v3d', 'I', 'PRESS', alt=True)
+kmi = km.keymap_items.new('anim.keying_set_active_set', 'I', 'PRESS', shift=True, ctrl=True, alt=True)
+kmi = km.keymap_items.new('poselib.browse_interactive', 'L', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('poselib.pose_add', 'L', 'PRESS', shift=True)
+kmi = km.keymap_items.new('poselib.pose_remove', 'L', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('poselib.pose_rename', 'L', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('pose.push', 'E', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('pose.relax', 'E', 'PRESS', alt=True)
+kmi = km.keymap_items.new('pose.breakdown', 'E', 'PRESS', shift=True)
+kmi = km.keymap_items.new('wm.call_menu', 'Q', 'PRESS')
+kmi.properties.name = 'VIEW3D_MT_pose_specials'
+
+# Map Object Mode
+km = kc.keymaps.new('Object Mode', space_type='EMPTY', region_type='WINDOW', modal=False)
+
+kmi = km.keymap_items.new('wm.context_cycle_enum', 'O', 'PRESS', shift=True)
+kmi.properties.data_path = 'tool_settings.proportional_edit_falloff'
+kmi = km.keymap_items.new('wm.context_toggle', 'O', 'PRESS')
+kmi.properties.data_path = 'tool_settings.use_proportional_edit_objects'
+kmi = km.keymap_items.new('view3d.game_start', 'P', 'PRESS')
+kmi = km.keymap_items.new('object.select_all', 'LEFTMOUSE', 'CLICK')
+kmi.properties.action = 'DESELECT'
+kmi = km.keymap_items.new('object.select_all', 'I', 'PRESS', ctrl=True)
+kmi.properties.action = 'INVERT'
+kmi = km.keymap_items.new('object.select_linked', 'L', 'PRESS', shift=True)
+kmi = km.keymap_items.new('object.select_grouped', 'G', 'PRESS', shift=True)
+kmi = km.keymap_items.new('object.select_mirror', 'M', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('object.select_hierarchy', 'LEFT_BRACKET', 'PRESS')
+kmi.properties.direction = 'PARENT'
+kmi.properties.extend = False
+kmi = km.keymap_items.new('object.select_hierarchy', 'LEFT_BRACKET', 'PRESS', shift=True)
+kmi.properties.direction = 'PARENT'
+kmi.properties.extend = True
+kmi = km.keymap_items.new('object.select_hierarchy', 'RIGHT_BRACKET', 'PRESS')
+kmi.properties.direction = 'CHILD'
+kmi.properties.extend = False
+kmi = km.keymap_items.new('object.select_hierarchy', 'RIGHT_BRACKET', 'PRESS', shift=True)
+kmi.properties.direction = 'CHILD'
+kmi.properties.extend = True
+kmi = km.keymap_items.new('object.parent_set', 'P', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('object.parent_no_inverse_set', 'P', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('object.parent_clear', 'P', 'PRESS', alt=True)
+kmi = km.keymap_items.new('object.track_set', 'T', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('object.track_clear', 'T', 'PRESS', alt=True)
+kmi = km.keymap_items.new('object.constraint_add_with_targets', 'C', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('object.constraints_clear', 'C', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('object.location_clear', 'G', 'PRESS', alt=True)
+kmi = km.keymap_items.new('object.rotation_clear', 'R', 'PRESS', alt=True)
+kmi = km.keymap_items.new('object.scale_clear', 'S', 'PRESS', alt=True)
+kmi = km.keymap_items.new('object.origin_clear', 'O', 'PRESS', alt=True)
+kmi = km.keymap_items.new('object.hide_view_clear', 'H', 'PRESS', alt=True)
+kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS')
+kmi.properties.unselected = False
+kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS', shift=True)
+kmi.properties.unselected = True
+kmi = km.keymap_items.new('object.hide_render_clear', 'H', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('object.hide_render_set', 'H', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('object.move_to_layer', 'M', 'PRESS')
+kmi = km.keymap_items.new('object.delete', 'X', 'PRESS')
+kmi.properties.use_global = False
+kmi = km.keymap_items.new('object.delete', 'X', 'PRESS', shift=True)
+kmi.properties.use_global = False
+kmi = km.keymap_items.new('object.delete', 'DEL', 'PRESS')
+kmi = km.keymap_items.new('object.delete', 'DEL', 'PRESS', shift=True)
+kmi.properties.use_global = True
+kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', shift=True)
+kmi.properties.name = 'INFO_MT_add'
+kmi = km.keymap_items.new('object.duplicates_make_real', 'A', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', ctrl=True)
+kmi.properties.name = 'VIEW3D_MT_object_apply'
+kmi = km.keymap_items.new('wm.call_menu', 'U', 'PRESS')
+kmi.properties.name = 'VIEW3D_MT_make_single_user'
+kmi = km.keymap_items.new('wm.call_menu', 'L', 'PRESS', ctrl=True)
+kmi.properties.name = 'VIEW3D_MT_make_links'
+kmi = km.keymap_items.new('object.duplicate_move', 'D', 'PRESS', shift=True)
+kmi = km.keymap_items.new('object.duplicate_move_linked', 'D', 'PRESS', alt=True)
+kmi = km.keymap_items.new('object.join', 'J', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('object.convert', 'C', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('object.proxy_make', 'P', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('object.make_local', 'L', 'PRESS', alt=True)
+kmi = km.keymap_items.new('anim.keyframe_insert_menu', 'I', 'PRESS')
+kmi = km.keymap_items.new('anim.keyframe_delete_v3d', 'I', 'PRESS', alt=True)
+kmi = km.keymap_items.new('anim.keying_set_active_set', 'I', 'PRESS', shift=True, ctrl=True, alt=True)
+kmi = km.keymap_items.new('group.create', 'G', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('group.objects_remove', 'G', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('group.objects_remove_all', 'G', 'PRESS', shift=True, ctrl=True, alt=True)
+kmi = km.keymap_items.new('group.objects_add_active', 'G', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('group.objects_remove_active', 'G', 'PRESS', shift=True, alt=True)
+kmi = km.keymap_items.new('rigidbody.objects_add', 'R', 'PRESS', ctrl=True)
+kmi.properties.type = 'ACTIVE'
+kmi = km.keymap_items.new('rigidbody.objects_add', 'R', 'PRESS', shift=True, ctrl=True)
+kmi.properties.type = 'PASSIVE'
+kmi = km.keymap_items.new('rigidbody.objects_remove', 'R', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('wm.call_menu', 'Q', 'PRESS')
+kmi.properties.name = 'VIEW3D_MT_object_specials'
+kmi = km.keymap_items.new('object.subdivision_set', 'ZERO', 'PRESS', ctrl=True)
+kmi.properties.level = 0
+kmi = km.keymap_items.new('object.subdivision_set', 'ONE', 'PRESS', ctrl=True)
+kmi.properties.level = 1
+kmi = km.keymap_items.new('object.subdivision_set', 'TWO', 'PRESS', ctrl=True)
+kmi.properties.level = 2
+kmi = km.keymap_items.new('object.subdivision_set', 'THREE', 'PRESS', ctrl=True)
+kmi.properties.level = 3
+kmi = km.keymap_items.new('object.subdivision_set', 'FOUR', 'PRESS', ctrl=True)
+kmi.properties.level = 4
+kmi = km.keymap_items.new('object.subdivision_set', 'FIVE', 'PRESS', ctrl=True)
+kmi.properties.level = 5
+
+# Map Image Paint
+km = kc.keymaps.new('Image Paint', space_type='EMPTY', region_type='WINDOW', modal=False)
+
+kmi = km.keymap_items.new('paint.image_paint', 'LEFTMOUSE', 'PRESS')
+kmi = km.keymap_items.new('paint.grab_clone', 'RIGHTMOUSE', 'PRESS')
+kmi = km.keymap_items.new('paint.sample_color', 'RIGHTMOUSE', 'PRESS')
+kmi = km.keymap_items.new('paint.clone_cursor_set', 'LEFTMOUSE', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('brush.active_index_set', 'ONE', 'PRESS')
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 0
+kmi = km.keymap_items.new('brush.active_index_set', 'TWO', 'PRESS')
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 1
+kmi = km.keymap_items.new('brush.active_index_set', 'THREE', 'PRESS')
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 2
+kmi = km.keymap_items.new('brush.active_index_set', 'FOUR', 'PRESS')
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 3
+kmi = km.keymap_items.new('brush.active_index_set', 'FIVE', 'PRESS')
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 4
+kmi = km.keymap_items.new('brush.active_index_set', 'SIX', 'PRESS')
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 5
+kmi = km.keymap_items.new('brush.active_index_set', 'SEVEN', 'PRESS')
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 6
+kmi = km.keymap_items.new('brush.active_index_set', 'EIGHT', 'PRESS')
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 7
+kmi = km.keymap_items.new('brush.active_index_set', 'NINE', 'PRESS')
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 8
+kmi = km.keymap_items.new('brush.active_index_set', 'ZERO', 'PRESS')
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 9
+kmi = km.keymap_items.new('brush.active_index_set', 'ONE', 'PRESS', shift=True)
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 10
+kmi = km.keymap_items.new('brush.active_index_set', 'TWO', 'PRESS', shift=True)
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 11
+kmi = km.keymap_items.new('brush.active_index_set', 'THREE', 'PRESS', shift=True)
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 12
+kmi = km.keymap_items.new('brush.active_index_set', 'FOUR', 'PRESS', shift=True)
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 13
+kmi = km.keymap_items.new('brush.active_index_set', 'FIVE', 'PRESS', shift=True)
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 14
+kmi = km.keymap_items.new('brush.active_index_set', 'SIX', 'PRESS', shift=True)
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 15
+kmi = km.keymap_items.new('brush.active_index_set', 'SEVEN', 'PRESS', shift=True)
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 16
+kmi = km.keymap_items.new('brush.active_index_set', 'EIGHT', 'PRESS', shift=True)
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 17
+kmi = km.keymap_items.new('brush.active_index_set', 'NINE', 'PRESS', shift=True)
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 18
+kmi = km.keymap_items.new('brush.active_index_set', 'ZERO', 'PRESS', shift=True)
+kmi.properties.mode = 'image_paint'
+kmi.properties.index = 19
+kmi = km.keymap_items.new('brush.scale_size', 'LEFT_BRACKET', 'PRESS')
+kmi.properties.scalar = 0.8999999761581421
+kmi = km.keymap_items.new('brush.scale_size', 'RIGHT_BRACKET', 'PRESS')
+kmi.properties.scalar = 1.1111111640930176
+kmi = km.keymap_items.new('wm.radial_control', 'F', 'PRESS', ctrl=True)
+kmi.properties.data_path_primary = 'tool_settings.image_paint.brush.size'
+kmi.properties.data_path_secondary = 'tool_settings.unified_paint_settings.size'
+kmi.properties.use_secondary = 'tool_settings.unified_paint_settings.use_unified_size'
+kmi.properties.rotation_path = 'tool_settings.image_paint.brush.texture_slot.angle'
+kmi.properties.color_path = 'tool_settings.image_paint.brush.cursor_color_add'
+kmi.properties.fill_color_path = 'tool_settings.image_paint.brush.color'
+kmi.properties.zoom_path = 'space_data.zoom'
+kmi.properties.image_id = 'tool_settings.image_paint.brush'
+kmi = km.keymap_items.new('wm.radial_control', 'F', 'PRESS', shift=True)
+kmi.properties.data_path_primary = 'tool_settings.image_paint.brush.strength'
+kmi.properties.data_path_secondary = 'tool_settings.unified_paint_settings.strength'
+kmi.properties.use_secondary = 'tool_settings.unified_paint_settings.use_unified_strength'
+kmi.properties.rotation_path = 'tool_settings.image_paint.brush.texture_slot.angle'
+kmi.properties.color_path = 'tool_settings.image_paint.brush.cursor_color_add'
+kmi.properties.fill_color_path = 'tool_settings.image_paint.brush.color'
+kmi.properties.zoom_path = ''
+kmi.properties.image_id = 'tool_settings.image_paint.brush'
+kmi = km.keymap_items.new('wm.radial_control', 'W', 'PRESS')
+kmi.properties.data_path_primary = 'tool_settings.image_paint.brush.weight'
+kmi.properties.data_path_secondary = 'tool_settings.unified_paint_settings.weight'
+kmi.properties.use_secondary = 'tool_settings.unified_paint_settings.use_unified_weight'
+kmi.properties.rotation_path = 'tool_settings.image_paint.brush.texture_slot.angle'
+kmi.properties.color_path = 'tool_settings.image_paint.brush.cursor_color_add'
+kmi.properties.fill_color_path = 'tool_settings.image_paint.brush.color'
+kmi.properties.zoom_path = ''
+kmi.properties.image_id = 'tool_settings.image_paint.brush'
+kmi = km.keymap_items.new('wm.context_toggle', 'M', 'PRESS')
+kmi.properties.data_path = 'image_paint_object.data.use_paint_mask'
+
+# Map Vertex Paint
+km = kc.keymaps.new('Vertex Paint', space_type='EMPTY', region_type='WINDOW', modal=False)
+
+kmi = km.keymap_items.new('paint.vertex_paint', 'LEFTMOUSE', 'PRESS')
+kmi = km.keymap_items.new('paint.sample_color', 'RIGHTMOUSE', 'PRESS')
+kmi = km.keymap_items.new('paint.vertex_color_set', 'K', 'PRESS', shift=True)
+kmi = km.keymap_items.new('brush.active_index_set', 'ONE', 'PRESS')
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 0
+kmi = km.keymap_items.new('brush.active_index_set', 'TWO', 'PRESS')
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 1
+kmi = km.keymap_items.new('brush.active_index_set', 'THREE', 'PRESS')
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 2
+kmi = km.keymap_items.new('brush.active_index_set', 'FOUR', 'PRESS')
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 3
+kmi = km.keymap_items.new('brush.active_index_set', 'FIVE', 'PRESS')
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 4
+kmi = km.keymap_items.new('brush.active_index_set', 'SIX', 'PRESS')
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 5
+kmi = km.keymap_items.new('brush.active_index_set', 'SEVEN', 'PRESS')
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 6
+kmi = km.keymap_items.new('brush.active_index_set', 'EIGHT', 'PRESS')
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 7
+kmi = km.keymap_items.new('brush.active_index_set', 'NINE', 'PRESS')
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 8
+kmi = km.keymap_items.new('brush.active_index_set', 'ZERO', 'PRESS')
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 9
+kmi = km.keymap_items.new('brush.active_index_set', 'ONE', 'PRESS', shift=True)
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 10
+kmi = km.keymap_items.new('brush.active_index_set', 'TWO', 'PRESS', shift=True)
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 11
+kmi = km.keymap_items.new('brush.active_index_set', 'THREE', 'PRESS', shift=True)
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 12
+kmi = km.keymap_items.new('brush.active_index_set', 'FOUR', 'PRESS', shift=True)
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 13
+kmi = km.keymap_items.new('brush.active_index_set', 'FIVE', 'PRESS', shift=True)
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 14
+kmi = km.keymap_items.new('brush.active_index_set', 'SIX', 'PRESS', shift=True)
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 15
+kmi = km.keymap_items.new('brush.active_index_set', 'SEVEN', 'PRESS', shift=True)
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 16
+kmi = km.keymap_items.new('brush.active_index_set', 'EIGHT', 'PRESS', shift=True)
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 17
+kmi = km.keymap_items.new('brush.active_index_set', 'NINE', 'PRESS', shift=True)
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 18
+kmi = km.keymap_items.new('brush.active_index_set', 'ZERO', 'PRESS', shift=True)
+kmi.properties.mode = 'vertex_paint'
+kmi.properties.index = 19
+kmi = km.keymap_items.new('brush.scale_size', 'LEFT_BRACKET', 'PRESS')
+kmi.properties.scalar = 0.8999999761581421
+kmi = km.keymap_items.new('brush.scale_size', 'RIGHT_BRACKET', 'PRESS')
+kmi.properties.scalar = 1.1111111640930176
+kmi = km.keymap_items.new('wm.radial_control', 'F', 'PRESS', ctrl=True)
+kmi.properties.data_path_primary = 'tool_settings.vertex_paint.brush.size'
+kmi.properties.data_path_secondary = 'tool_settings.unified_paint_settings.size'
+kmi.properties.use_secondary = 'tool_settings.unified_paint_settings.use_unified_size'
+kmi.properties.rotation_path = 'tool_settings.vertex_paint.brush.texture_slot.angle'
+kmi.properties.color_path = 'tool_settings.vertex_paint.brush.cursor_color_add'
+kmi.properties.fill_color_path = 'tool_settings.vertex_paint.brush.color'
+kmi.properties.zoom_path = ''
+kmi.properties.image_id = 'tool_settings.vertex_paint.brush'
+kmi = km.keymap_items.new('wm.radial_control', 'F', 'PRESS', shift=True)
+kmi.properties.data_path_primary = 'tool_settings.vertex_paint.brush.strength'
+kmi.properties.data_path_secondary = 'tool_settings.unified_paint_settings.strength'
+kmi.properties.use_secondary = 'tool_settings.unified_paint_settings.use_unified_strength'
+kmi.properties.rotation_path = 'tool_settings.vertex_paint.brush.texture_slot.angle'
+kmi.properties.color_path = 'tool_settings.vertex_paint.brush.cursor_color_add'
+kmi.properties.fill_color_path = 'tool_settings.vertex_paint.brush.color'
+kmi.properties.zoom_path = ''
+kmi.properties.image_id = 'tool_settings.vertex_paint.brush'
+kmi = km.keymap_items.new('wm.radial_control', 'Q', 'PRESS')
+kmi.properties.data_path_primary = 'tool_settings.vertex_paint.brush.weight'
+kmi.properties.data_path_secondary = 'tool_settings.unified_paint_settings.weight'
+kmi.properties.use_secondary = 'tool_settings.unified_paint_settings.use_unified_weight'
+kmi.properties.rotation_path = 'tool_settings.vertex_paint.brush.texture_slot.angle'
+kmi.properties.color_path = 'tool_settings.vertex_paint.brush.cursor_color_add'
+kmi.properties.fill_color_path = 'tool_settings.vertex_paint.brush.color'
+kmi.properties.zoom_path = ''
+kmi.properties.image_id = 'tool_settings.vertex_paint.brush'
+kmi = km.keymap_items.new('wm.context_toggle', 'M', 'PRESS')
+kmi.properties.data_path = 'vertex_paint_object.data.use_paint_mask'
+
+# Map Weight Paint
+km = kc.keymaps.new('Weight Paint', space_type='EMPTY', region_type='WINDOW', modal=False)
+
+kmi = km.keymap_items.new('paint.weight_paint', 'LEFTMOUSE', 'PRESS')
+kmi = km.keymap_items.new('paint.weight_sample', 'ACTIONMOUSE', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('paint.weight_sample_group', 'ACTIONMOUSE', 'PRESS', shift=True)
+kmi = km.keymap_items.new('paint.weight_gradient', 'LEFTMOUSE', 'PRESS', alt=True)
+kmi.properties.type = 'LINEAR'
+kmi = km.keymap_items.new('paint.weight_gradient', 'LEFTMOUSE', 'PRESS', ctrl=True, alt=True)
+kmi.properties.type = 'RADIAL'
+kmi = km.keymap_items.new('paint.weight_set', 'K', 'PRESS', shift=True)
+kmi = km.keymap_items.new('brush.active_index_set', 'ONE', 'PRESS')
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 0
+kmi = km.keymap_items.new('brush.active_index_set', 'TWO', 'PRESS')
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 1
+kmi = km.keymap_items.new('brush.active_index_set', 'THREE', 'PRESS')
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 2
+kmi = km.keymap_items.new('brush.active_index_set', 'FOUR', 'PRESS')
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 3
+kmi = km.keymap_items.new('brush.active_index_set', 'FIVE', 'PRESS')
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 4
+kmi = km.keymap_items.new('brush.active_index_set', 'SIX', 'PRESS')
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 5
+kmi = km.keymap_items.new('brush.active_index_set', 'SEVEN', 'PRESS')
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 6
+kmi = km.keymap_items.new('brush.active_index_set', 'EIGHT', 'PRESS')
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 7
+kmi = km.keymap_items.new('brush.active_index_set', 'NINE', 'PRESS')
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 8
+kmi = km.keymap_items.new('brush.active_index_set', 'ZERO', 'PRESS')
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 9
+kmi = km.keymap_items.new('brush.active_index_set', 'ONE', 'PRESS', shift=True)
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 10
+kmi = km.keymap_items.new('brush.active_index_set', 'TWO', 'PRESS', shift=True)
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 11
+kmi = km.keymap_items.new('brush.active_index_set', 'THREE', 'PRESS', shift=True)
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 12
+kmi = km.keymap_items.new('brush.active_index_set', 'FOUR', 'PRESS', shift=True)
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 13
+kmi = km.keymap_items.new('brush.active_index_set', 'FIVE', 'PRESS', shift=True)
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 14
+kmi = km.keymap_items.new('brush.active_index_set', 'SIX', 'PRESS', shift=True)
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 15
+kmi = km.keymap_items.new('brush.active_index_set', 'SEVEN', 'PRESS', shift=True)
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 16
+kmi = km.keymap_items.new('brush.active_index_set', 'EIGHT', 'PRESS', shift=True)
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 17
+kmi = km.keymap_items.new('brush.active_index_set', 'NINE', 'PRESS', shift=True)
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 18
+kmi = km.keymap_items.new('brush.active_index_set', 'ZERO', 'PRESS', shift=True)
+kmi.properties.mode = 'weight_paint'
+kmi.properties.index = 19
+kmi = km.keymap_items.new('brush.scale_size', 'LEFT_BRACKET', 'PRESS')
+kmi.properties.scalar = 0.8999999761581421
+kmi = km.keymap_items.new('brush.scale_size', 'RIGHT_BRACKET', 'PRESS')
+kmi.properties.scalar = 1.1111111640930176
+kmi = km.keymap_items.new('wm.radial_control', 'F', 'PRESS', ctrl=True)
+kmi.properties.data_path_primary = 'tool_settings.weight_paint.brush.size'
+kmi.properties.data_path_secondary = 'tool_settings.unified_paint_settings.size'
+kmi.properties.use_secondary = 'tool_settings.unified_paint_settings.use_unified_size'
+kmi.properties.rotation_path = 'tool_settings.weight_paint.brush.texture_slot.angle'
+kmi.properties.color_path = 'tool_settings.weight_paint.brush.cursor_color_add'
+kmi.properties.fill_color_path = ''
+kmi.properties.zoom_path = ''
+kmi.properties.image_id = 'tool_settings.weight_paint.brush'
+kmi = km.keymap_items.new('wm.radial_control', 'F', 'PRESS', shift=True)
+kmi.properties.data_path_primary = 'tool_settings.weight_paint.brush.strength'
+kmi.properties.data_path_secondary = 'tool_settings.unified_paint_settings.strength'
+kmi.properties.use_secondary = 'tool_settings.unified_paint_settings.use_unified_strength'
+kmi.properties.rotation_path = 'tool_settings.weight_paint.brush.texture_slot.angle'
+kmi.properties.color_path = 'tool_settings.weight_paint.brush.cursor_color_add'
+kmi.properties.fill_color_path = ''
+kmi.properties.zoom_path = ''
+kmi.properties.image_id = 'tool_settings.weight_paint.brush'
+kmi = km.keymap_items.new('wm.radial_control', 'Q', 'PRESS')
+kmi.properties.data_path_primary = 'tool_settings.weight_paint.brush.weight'
+kmi.properties.data_path_secondary = 'tool_settings.unified_paint_settings.weight'
+kmi.properties.use_secondary = 'tool_settings.unified_paint_settings.use_unified_weight'
+kmi.properties.rotation_path = 'tool_settings.weight_paint.brush.texture_slot.angle'
+kmi.properties.color_path = 'tool_settings.weight_paint.brush.cursor_color_add'
+kmi.properties.fill_color_path = ''
+kmi.properties.zoom_path = ''
+kmi.properties.image_id = 'tool_settings.weight_paint.brush'
+kmi = km.keymap_items.new('wm.context_toggle', 'M', 'PRESS')
+kmi.properties.data_path = 'weight_paint_object.data.use_paint_mask'
+kmi = km.keymap_items.new('wm.context_toggle', 'V', 'PRESS')
+kmi.properties.data_path = 'weight_paint_object.data.use_paint_mask_vertex'
+kmi = km.keymap_items.new('paint.weight_from_bones', 'Q', 'PRESS')
+
+# Map Sculpt
+km = kc.keymaps.new('Sculpt', space_type='EMPTY', region_type='WINDOW', modal=False)
+
+kmi = km.keymap_items.new('sculpt.brush_stroke', 'LEFTMOUSE', 'PRESS')
+kmi.properties.mode = 'NORMAL'
+kmi = km.keymap_items.new('sculpt.brush_stroke', 'LEFTMOUSE', 'PRESS', ctrl=True)
+kmi.properties.mode = 'INVERT'
+kmi = km.keymap_items.new('sculpt.brush_stroke', 'LEFTMOUSE', 'PRESS', shift=True)
+kmi.properties.mode = 'SMOOTH'
+kmi = km.keymap_items.new('paint.hide_show', 'H', 'PRESS', shift=True)
+kmi.properties.action = 'SHOW'
+kmi.properties.area = 'INSIDE'
+kmi = km.keymap_items.new('paint.hide_show', 'H', 'PRESS')
+kmi.properties.action = 'HIDE'
+kmi.properties.area = 'INSIDE'
+kmi = km.keymap_items.new('paint.hide_show', 'H', 'PRESS', alt=True)
+kmi.properties.action = 'SHOW'
+kmi.properties.area = 'ALL'
+kmi = km.keymap_items.new('object.subdivision_set', 'ZERO', 'PRESS', ctrl=True)
+kmi.properties.level = 0
+kmi = km.keymap_items.new('object.subdivision_set', 'ONE', 'PRESS', ctrl=True)
+kmi.properties.level = 1
+kmi = km.keymap_items.new('object.subdivision_set', 'TWO', 'PRESS', ctrl=True)
+kmi.properties.level = 2
+kmi = km.keymap_items.new('object.subdivision_set', 'THREE', 'PRESS', ctrl=True)
+kmi.properties.level = 3
+kmi = km.keymap_items.new('object.subdivision_set', 'FOUR', 'PRESS', ctrl=True)
+kmi.properties.level = 4
+kmi = km.keymap_items.new('object.subdivision_set', 'FIVE', 'PRESS', ctrl=True)
+kmi.properties.level = 5
+kmi = km.keymap_items.new('paint.mask_flood_fill', 'M', 'PRESS', alt=True)
+kmi.properties.mode = 'VALUE'
+kmi.properties.value = 0.0
+kmi = km.keymap_items.new('paint.mask_flood_fill', 'I', 'PRESS', ctrl=True)
+kmi.properties.mode = 'INVERT'
+kmi = km.keymap_items.new('sculpt.dynamic_topology_toggle', 'D', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.radial_control', 'D', 'PRESS', shift=True)
+kmi.properties.data_path_primary = 'tool_settings.sculpt.detail_size'
+kmi.properties.data_path_secondary = ''
+kmi.properties.use_secondary = ''
+kmi.properties.rotation_path = 'tool_settings.sculpt.brush.texture_slot.angle'
+kmi.properties.color_path = 'tool_settings.sculpt.brush.cursor_color_add'
+kmi.properties.fill_color_path = ''
+kmi.properties.zoom_path = ''
+kmi.properties.image_id = 'tool_settings.sculpt.brush'
+kmi = km.keymap_items.new('object.subdivision_set', 'PAGE_UP', 'PRESS')
+kmi.properties.level = 1
+kmi.properties.relative = True
+kmi = km.keymap_items.new('object.subdivision_set', 'PAGE_DOWN', 'PRESS')
+kmi.properties.level = -1
+kmi.properties.relative = True
+kmi = km.keymap_items.new('brush.active_index_set', 'ONE', 'PRESS')
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 0
+kmi = km.keymap_items.new('brush.active_index_set', 'TWO', 'PRESS')
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 1
+kmi = km.keymap_items.new('brush.active_index_set', 'THREE', 'PRESS')
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 2
+kmi = km.keymap_items.new('brush.active_index_set', 'FOUR', 'PRESS')
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 3
+kmi = km.keymap_items.new('brush.active_index_set', 'FIVE', 'PRESS')
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 4
+kmi = km.keymap_items.new('brush.active_index_set', 'SIX', 'PRESS')
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 5
+kmi = km.keymap_items.new('brush.active_index_set', 'SEVEN', 'PRESS')
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 6
+kmi = km.keymap_items.new('brush.active_index_set', 'EIGHT', 'PRESS')
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 7
+kmi = km.keymap_items.new('brush.active_index_set', 'NINE', 'PRESS')
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 8
+kmi = km.keymap_items.new('brush.active_index_set', 'ZERO', 'PRESS')
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 9
+kmi = km.keymap_items.new('brush.active_index_set', 'ONE', 'PRESS', shift=True)
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 10
+kmi = km.keymap_items.new('brush.active_index_set', 'TWO', 'PRESS', shift=True)
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 11
+kmi = km.keymap_items.new('brush.active_index_set', 'THREE', 'PRESS', shift=True)
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 12
+kmi = km.keymap_items.new('brush.active_index_set', 'FOUR', 'PRESS', shift=True)
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 13
+kmi = km.keymap_items.new('brush.active_index_set', 'FIVE', 'PRESS', shift=True)
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 14
+kmi = km.keymap_items.new('brush.active_index_set', 'SIX', 'PRESS', shift=True)
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 15
+kmi = km.keymap_items.new('brush.active_index_set', 'SEVEN', 'PRESS', shift=True)
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 16
+kmi = km.keymap_items.new('brush.active_index_set', 'EIGHT', 'PRESS', shift=True)
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 17
+kmi = km.keymap_items.new('brush.active_index_set', 'NINE', 'PRESS', shift=True)
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 18
+kmi = km.keymap_items.new('brush.active_index_set', 'ZERO', 'PRESS', shift=True)
+kmi.properties.mode = 'sculpt'
+kmi.properties.index = 19
+kmi = km.keymap_items.new('brush.scale_size', 'LEFT_BRACKET', 'PRESS')
+kmi.properties.scalar = 0.8999999761581421
+kmi = km.keymap_items.new('brush.scale_size', 'RIGHT_BRACKET', 'PRESS')
+kmi.properties.scalar = 1.1111111640930176
+kmi = km.keymap_items.new('wm.radial_control', 'F', 'PRESS', ctrl=True)
+kmi.properties.data_path_primary = 'tool_settings.sculpt.brush.size'
+kmi.properties.data_path_secondary = 'tool_settings.unified_paint_settings.size'
+kmi.properties.use_secondary = 'tool_settings.unified_paint_settings.use_unified_size'
+kmi.properties.rotation_path = 'tool_settings.sculpt.brush.texture_slot.angle'
+kmi.properties.color_path = 'tool_settings.sculpt.brush.cursor_color_add'
+kmi.properties.fill_color_path = ''
+kmi.properties.zoom_path = ''
+kmi.properties.image_id = 'tool_settings.sculpt.brush'
+kmi = km.keymap_items.new('wm.radial_control', 'F', 'PRESS', shift=True)
+kmi.properties.data_path_primary = 'tool_settings.sculpt.brush.strength'
+kmi.properties.data_path_secondary = 'tool_settings.unified_paint_settings.strength'
+kmi.properties.use_secondary = 'tool_settings.unified_paint_settings.use_unified_strength'
+kmi.properties.rotation_path = 'tool_settings.sculpt.brush.texture_slot.angle'
+kmi.properties.color_path = 'tool_settings.sculpt.brush.cursor_color_add'
+kmi.properties.fill_color_path = ''
+kmi.properties.zoom_path = ''
+kmi.properties.image_id = 'tool_settings.sculpt.brush'
+kmi = km.keymap_items.new('wm.radial_control', 'W', 'PRESS')
+kmi.properties.data_path_primary = 'tool_settings.sculpt.brush.weight'
+kmi.properties.data_path_secondary = 'tool_settings.unified_paint_settings.weight'
+kmi.properties.use_secondary = 'tool_settings.unified_paint_settings.use_unified_weight'
+kmi.properties.rotation_path = 'tool_settings.sculpt.brush.texture_slot.angle'
+kmi.properties.color_path = 'tool_settings.sculpt.brush.cursor_color_add'
+kmi.properties.fill_color_path = ''
+kmi.properties.zoom_path = ''
+kmi.properties.image_id = 'tool_settings.sculpt.brush'
+kmi = km.keymap_items.new('wm.radial_control', 'F', 'PRESS', ctrl=True)
+kmi.properties.data_path_primary = 'tool_settings.sculpt.brush.texture_slot.angle'
+kmi.properties.data_path_secondary = ''
+kmi.properties.use_secondary = ''
+kmi.properties.rotation_path = 'tool_settings.sculpt.brush.texture_slot.angle'
+kmi.properties.color_path = 'tool_settings.sculpt.brush.cursor_color_add'
+kmi.properties.fill_color_path = ''
+kmi.properties.zoom_path = ''
+kmi.properties.image_id = 'tool_settings.sculpt.brush'
+kmi = km.keymap_items.new('paint.brush_select', 'D', 'PRESS')
+kmi.properties.paint_mode = 'SCULPT'
+kmi.properties.sculpt_tool = 'DRAW'
+kmi = km.keymap_items.new('paint.brush_select', 'S', 'PRESS')
+kmi.properties.paint_mode = 'SCULPT'
+kmi.properties.sculpt_tool = 'SMOOTH'
+kmi = km.keymap_items.new('paint.brush_select', 'P', 'PRESS')
+kmi.properties.paint_mode = 'SCULPT'
+kmi.properties.sculpt_tool = 'PINCH'
+kmi = km.keymap_items.new('paint.brush_select', 'I', 'PRESS')
+kmi.properties.paint_mode = 'SCULPT'
+kmi.properties.sculpt_tool = 'INFLATE'
+kmi = km.keymap_items.new('paint.brush_select', 'G', 'PRESS')
+kmi.properties.paint_mode = 'SCULPT'
+kmi.properties.sculpt_tool = 'GRAB'
+kmi = km.keymap_items.new('paint.brush_select', 'L', 'PRESS')
+kmi.properties.paint_mode = 'SCULPT'
+kmi.properties.sculpt_tool = 'LAYER'
+kmi = km.keymap_items.new('paint.brush_select', 'T', 'PRESS', shift=True)
+kmi.properties.paint_mode = 'SCULPT'
+kmi.properties.sculpt_tool = 'FLATTEN'
+kmi = km.keymap_items.new('paint.brush_select', 'C', 'PRESS')
+kmi.properties.paint_mode = 'SCULPT'
+kmi.properties.sculpt_tool = 'CLAY'
+kmi = km.keymap_items.new('paint.brush_select', 'C', 'PRESS', shift=True)
+kmi.properties.paint_mode = 'SCULPT'
+kmi.properties.sculpt_tool = 'CREASE'
+kmi = km.keymap_items.new('paint.brush_select', 'K', 'PRESS')
+kmi.properties.paint_mode = 'SCULPT'
+kmi.properties.sculpt_tool = 'SNAKE_HOOK'
+kmi = km.keymap_items.new('paint.brush_select', 'M', 'PRESS')
+kmi.properties.paint_mode = 'SCULPT'
+kmi.properties.sculpt_tool = 'MASK'
+kmi.properties.toggle = True
+kmi.properties.create_missing = True
+kmi = km.keymap_items.new('wm.context_menu_enum', 'A', 'PRESS')
+kmi.properties.data_path = 'tool_settings.sculpt.brush.stroke_method'
+kmi = km.keymap_items.new('wm.context_toggle', 'S', 'PRESS', shift=True)
+kmi.properties.data_path = 'tool_settings.sculpt.brush.use_smooth_stroke'
+kmi = km.keymap_items.new('wm.context_menu_enum', 'R', 'PRESS')
+kmi.properties.data_path = 'tool_settings.sculpt.brush.texture_angle_source_random'
+
+# Map Mesh
+km = kc.keymaps.new('Mesh', space_type='EMPTY', region_type='WINDOW', modal=False)
+
+kmi = km.keymap_items.new('mesh.loopcut_slide', 'R', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('mesh.inset', 'I', 'PRESS')
+kmi = km.keymap_items.new('mesh.bevel', 'B', 'PRESS', ctrl=True)
+kmi.properties.vertex_only = False
+kmi = km.keymap_items.new('mesh.bevel', 'B', 'PRESS', shift=True, ctrl=True)
+kmi.properties.vertex_only = True
+kmi = km.keymap_items.new('mesh.loop_select', 'SELECTMOUSE', 'PRESS', alt=True)
+kmi.properties.extend = False
+kmi.properties.deselect = False
+kmi.properties.toggle = False
+kmi = km.keymap_items.new('mesh.loop_select', 'SELECTMOUSE', 'PRESS', shift=True, alt=True)
+kmi.properties.extend = False
+kmi.properties.deselect = False
+kmi.properties.toggle = True
+kmi = km.keymap_items.new('mesh.edgering_select', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True)
+kmi.properties.extend = False
+kmi.properties.deselect = False
+kmi.properties.toggle = False
+kmi = km.keymap_items.new('mesh.edgering_select', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True)
+kmi.properties.extend = False
+kmi.properties.deselect = False
+kmi.properties.toggle = True
+kmi = km.keymap_items.new('mesh.select_shortest_path', 'SELECTMOUSE', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('mesh.select_all', 'LEFTMOUSE', 'CLICK')
+kmi.properties.action = 'DESELECT'
+kmi = km.keymap_items.new('mesh.select_all', 'I', 'PRESS', ctrl=True)
+kmi.properties.action = 'INVERT'
+kmi = km.keymap_items.new('mesh.select_more', 'NUMPAD_PLUS', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('mesh.select_less', 'NUMPAD_MINUS', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('mesh.select_non_manifold', 'M', 'PRESS', shift=True, ctrl=True, alt=True)
+kmi = km.keymap_items.new('mesh.select_linked', 'L', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('mesh.select_linked_pick', 'L', 'PRESS', alt=True)
+kmi.properties.deselect = False
+kmi = km.keymap_items.new('mesh.select_linked_pick', 'L', 'PRESS', shift=True)
+kmi.properties.deselect = True
+kmi = km.keymap_items.new('mesh.faces_select_linked_flat', 'F', 'PRESS', shift=True, ctrl=True, alt=True)
+kmi = km.keymap_items.new('mesh.select_similar', 'G', 'PRESS', shift=True)
+kmi = km.keymap_items.new('wm.call_menu', 'TAB', 'PRESS', ctrl=True)
+kmi.properties.name = 'VIEW3D_MT_edit_mesh_select_mode'
+kmi = km.keymap_items.new('mesh.hide', 'H', 'PRESS')
+kmi.properties.unselected = False
+kmi = km.keymap_items.new('mesh.hide', 'H', 'PRESS', shift=True)
+kmi.properties.unselected = True
+kmi = km.keymap_items.new('mesh.reveal', 'H', 'PRESS', alt=True)
+kmi = km.keymap_items.new('mesh.normals_make_consistent', 'N', 'PRESS', ctrl=True)
+kmi.properties.inside = False
+kmi = km.keymap_items.new('mesh.normals_make_consistent', 'N', 'PRESS', shift=True, ctrl=True)
+kmi.properties.inside = True
+kmi = km.keymap_items.new('view3d.edit_mesh_extrude_move_normal', 'E', 'PRESS')
+kmi = km.keymap_items.new('wm.call_menu', 'E', 'PRESS', alt=True)
+kmi.properties.name = 'VIEW3D_MT_edit_mesh_extrude'
+kmi = km.keymap_items.new('transform.edge_crease', 'E', 'PRESS', shift=True)
+kmi = km.keymap_items.new('mesh.spin', 'R', 'PRESS', alt=True)
+kmi = km.keymap_items.new('mesh.fill', 'F', 'PRESS', alt=True)
+kmi = km.keymap_items.new('mesh.beautify_fill', 'F', 'PRESS', shift=True, alt=True)
+kmi = km.keymap_items.new('mesh.quads_convert_to_tris', 'T', 'PRESS', ctrl=True)
+kmi.properties.use_beauty = True
+kmi = km.keymap_items.new('mesh.quads_convert_to_tris', 'T', 'PRESS', shift=True, ctrl=True)
+kmi.properties.use_beauty = False
+kmi = km.keymap_items.new('mesh.tris_convert_to_quads', 'J', 'PRESS', alt=True)
+kmi = km.keymap_items.new('mesh.rip_move', 'V', 'PRESS')
+kmi = km.keymap_items.new('mesh.rip_move_fill', 'V', 'PRESS', alt=True)
+kmi = km.keymap_items.new('mesh.merge', 'M', 'PRESS', alt=True)
+kmi = km.keymap_items.new('transform.shrink_fatten', 'S', 'PRESS', alt=True)
+kmi = km.keymap_items.new('mesh.edge_face_add', 'F', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('mesh.duplicate_move', 'D', 'PRESS', shift=True)
+kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', shift=True)
+kmi.properties.name = 'INFO_MT_mesh_add'
+kmi = km.keymap_items.new('mesh.separate', 'P', 'PRESS')
+kmi = km.keymap_items.new('mesh.split', 'Y', 'PRESS')
+kmi = km.keymap_items.new('mesh.vert_connect', 'J', 'PRESS')
+kmi = km.keymap_items.new('transform.vert_slide', 'V', 'PRESS', shift=True)
+kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'CLICK', ctrl=True)
+kmi.properties.rotate_source = True
+kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'CLICK', shift=True, ctrl=True)
+kmi.properties.rotate_source = False
+kmi = km.keymap_items.new('wm.call_menu', 'X', 'PRESS')
+kmi.properties.name = 'VIEW3D_MT_edit_mesh_delete'
+kmi = km.keymap_items.new('wm.call_menu', 'DEL', 'PRESS')
+kmi.properties.name = 'VIEW3D_MT_edit_mesh_delete'
+kmi = km.keymap_items.new('mesh.knife_tool', 'K', 'PRESS')
+kmi.properties.use_occlude_geometry = True
+kmi.properties.only_selected = False
+kmi = km.keymap_items.new('mesh.knife_tool', 'K', 'PRESS', shift=True)
+kmi.properties.use_occlude_geometry = False
+kmi.properties.only_selected = True
+kmi = km.keymap_items.new('object.vertex_parent_set', 'P', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.call_menu', 'Q', 'PRESS')
+kmi.properties.name = 'VIEW3D_MT_edit_mesh_specials'
+kmi = km.keymap_items.new('wm.call_menu', 'F', 'PRESS', ctrl=True)
+kmi.properties.name = 'VIEW3D_MT_edit_mesh_faces'
+kmi = km.keymap_items.new('wm.call_menu', 'E', 'PRESS', ctrl=True)
+kmi.properties.name = 'VIEW3D_MT_edit_mesh_edges'
+kmi = km.keymap_items.new('wm.call_menu', 'V', 'PRESS', ctrl=True)
+kmi.properties.name = 'VIEW3D_MT_edit_mesh_vertices'
+kmi = km.keymap_items.new('wm.call_menu', 'H', 'PRESS', ctrl=True)
+kmi.properties.name = 'VIEW3D_MT_hook'
+kmi = km.keymap_items.new('wm.call_menu', 'U', 'PRESS')
+kmi.properties.name = 'VIEW3D_MT_uv_map'
+kmi = km.keymap_items.new('wm.call_menu', 'G', 'PRESS', ctrl=True)
+kmi.properties.name = 'VIEW3D_MT_vertex_group'
+kmi = km.keymap_items.new('object.subdivision_set', 'ZERO', 'PRESS', ctrl=True)
+kmi.properties.level = 0
+kmi = km.keymap_items.new('object.subdivision_set', 'ONE', 'PRESS', ctrl=True)
+kmi.properties.level = 1
+kmi = km.keymap_items.new('object.subdivision_set', 'TWO', 'PRESS', ctrl=True)
+kmi.properties.level = 2
+kmi = km.keymap_items.new('object.subdivision_set', 'THREE', 'PRESS', ctrl=True)
+kmi.properties.level = 3
+kmi = km.keymap_items.new('object.subdivision_set', 'FOUR', 'PRESS', ctrl=True)
+kmi.properties.level = 4
+kmi = km.keymap_items.new('object.subdivision_set', 'FIVE', 'PRESS', ctrl=True)
+kmi.properties.level = 5
+kmi = km.keymap_items.new('wm.context_cycle_enum', 'O', 'PRESS', shift=True)
+kmi.properties.data_path = 'tool_settings.proportional_edit_falloff'
+kmi = km.keymap_items.new('wm.context_toggle_enum', 'O', 'PRESS')
+kmi.properties.data_path = 'tool_settings.proportional_edit'
+kmi.properties.value_1 = 'DISABLED'
+kmi.properties.value_2 = 'ENABLED'
+kmi = km.keymap_items.new('wm.context_toggle_enum', 'O', 'PRESS', alt=True)
+kmi.properties.data_path = 'tool_settings.proportional_edit'
+kmi.properties.value_1 = 'DISABLED'
+kmi.properties.value_2 = 'CONNECTED'
+kmi = km.keymap_items.new('wm.context_set_value', 'ONE', 'PRESS')
+kmi.properties.data_path = 'tool_settings.mesh_select_mode'
+kmi.properties.value = '(True,False,False)'
+kmi = km.keymap_items.new('wm.context_set_value', 'TWO', 'PRESS')
+kmi.properties.data_path = 'tool_settings.mesh_select_mode'
+kmi.properties.value = '(False,True,False)'
+kmi = km.keymap_items.new('wm.context_set_value', 'THREE', 'PRESS')
+kmi.properties.data_path = 'tool_settings.mesh_select_mode'
+kmi.properties.value = '(False,False,True)'
+
+# Map Curve
+km = kc.keymaps.new('Curve', space_type='EMPTY', region_type='WINDOW', modal=False)
+
+kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', shift=True)
+kmi.properties.name = 'INFO_MT_edit_curve_add'
+kmi = km.keymap_items.new('curve.handle_type_set', 'V', 'PRESS')
+kmi = km.keymap_items.new('curve.vertex_add', 'LEFTMOUSE', 'CLICK', ctrl=True)
+kmi = km.keymap_items.new('curve.select_all', 'LEFTMOUSE', 'CLICK')
+kmi.properties.action = 'TOGGLE'
+kmi = km.keymap_items.new('curve.select_all', 'I', 'PRESS', ctrl=True)
+kmi.properties.action = 'INVERT'
+kmi = km.keymap_items.new('curve.select_row', 'R', 'PRESS', shift=True)
+kmi = km.keymap_items.new('curve.select_more', 'NUMPAD_PLUS', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('curve.select_less', 'NUMPAD_MINUS', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('curve.select_linked', 'L', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('curve.select_linked_pick', 'L', 'PRESS')
+kmi.properties.deselect = False
+kmi = km.keymap_items.new('curve.select_linked_pick', 'L', 'PRESS', shift=True)
+kmi.properties.deselect = True
+kmi = km.keymap_items.new('curve.separate', 'P', 'PRESS')
+kmi = km.keymap_items.new('curve.extrude_move', 'E', 'PRESS')
+kmi = km.keymap_items.new('curve.duplicate_move', 'D', 'PRESS', shift=True)
+kmi = km.keymap_items.new('curve.make_segment', 'F', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('curve.cyclic_toggle', 'C', 'PRESS', alt=True)
+kmi = km.keymap_items.new('curve.delete', 'X', 'PRESS')
+kmi = km.keymap_items.new('curve.delete', 'DEL', 'PRESS')
+kmi = km.keymap_items.new('curve.tilt_clear', 'T', 'PRESS', alt=True)
+kmi = km.keymap_items.new('transform.tilt', 'T', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('transform.transform', 'S', 'PRESS', alt=True)
+kmi.properties.mode = 'CURVE_SHRINKFATTEN'
+kmi = km.keymap_items.new('curve.reveal', 'H', 'PRESS', alt=True)
+kmi = km.keymap_items.new('curve.hide', 'H', 'PRESS')
+kmi.properties.unselected = False
+kmi = km.keymap_items.new('curve.hide', 'H', 'PRESS', shift=True)
+kmi.properties.unselected = True
+kmi = km.keymap_items.new('object.vertex_parent_set', 'P', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.call_menu', 'Q', 'PRESS')
+kmi.properties.name = 'VIEW3D_MT_edit_curve_specials'
+kmi = km.keymap_items.new('wm.call_menu', 'H', 'PRESS', ctrl=True)
+kmi.properties.name = 'VIEW3D_MT_hook'
+kmi = km.keymap_items.new('wm.context_cycle_enum', 'O', 'PRESS', shift=True)
+kmi.properties.data_path = 'tool_settings.proportional_edit_falloff'
+kmi = km.keymap_items.new('wm.context_toggle_enum', 'O', 'PRESS')
+kmi.properties.data_path = 'tool_settings.proportional_edit'
+kmi.properties.value_1 = 'DISABLED'
+kmi.properties.value_2 = 'ENABLED'
+kmi = km.keymap_items.new('wm.context_toggle_enum', 'O', 'PRESS', alt=True)
+kmi.properties.data_path = 'tool_settings.proportional_edit'
+kmi.properties.value_1 = 'DISABLED'
+kmi.properties.value_2 = 'CONNECTED'
+
+# Map Armature
+km = kc.keymaps.new('Armature', space_type='EMPTY', region_type='WINDOW', modal=False)
+
+kmi = km.keymap_items.new('sketch.delete', 'X', 'PRESS')
+kmi = km.keymap_items.new('sketch.delete', 'DEL', 'PRESS')
+kmi = km.keymap_items.new('sketch.finish_stroke', 'RIGHTMOUSE', 'PRESS')
+kmi = km.keymap_items.new('sketch.cancel_stroke', 'ESC', 'PRESS')
+kmi = km.keymap_items.new('sketch.gesture', 'LEFTMOUSE', 'PRESS', shift=True)
+kmi = km.keymap_items.new('sketch.draw_stroke', 'LEFTMOUSE', 'PRESS')
+kmi = km.keymap_items.new('sketch.draw_stroke', 'LEFTMOUSE', 'PRESS', ctrl=True)
+kmi.properties.snap = True
+kmi = km.keymap_items.new('sketch.draw_preview', 'MOUSEMOVE', 'ANY')
+kmi = km.keymap_items.new('sketch.draw_preview', 'MOUSEMOVE', 'ANY', ctrl=True)
+kmi.properties.snap = True
+kmi = km.keymap_items.new('armature.hide', 'H', 'PRESS')
+kmi.properties.unselected = False
+kmi = km.keymap_items.new('armature.hide', 'H', 'PRESS', shift=True)
+kmi.properties.unselected = True
+kmi = km.keymap_items.new('armature.reveal', 'H', 'PRESS', alt=True)
+kmi = km.keymap_items.new('armature.align', 'A', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('armature.calculate_roll', 'N', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('armature.switch_direction', 'F', 'PRESS', alt=True)
+kmi = km.keymap_items.new('armature.bone_primitive_add', 'A', 'PRESS', shift=True)
+kmi = km.keymap_items.new('armature.parent_set', 'P', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('armature.parent_clear', 'P', 'PRESS', alt=True)
+kmi = km.keymap_items.new('armature.select_all', 'LEFTMOUSE', 'CLICK')
+kmi.properties.action = 'TOGGLE'
+kmi = km.keymap_items.new('armature.select_all', 'I', 'PRESS', ctrl=True)
+kmi.properties.action = 'INVERT'
+kmi = km.keymap_items.new('armature.select_hierarchy', 'LEFT_BRACKET', 'PRESS')
+kmi.properties.direction = 'PARENT'
+kmi.properties.extend = False
+kmi = km.keymap_items.new('armature.select_hierarchy', 'LEFT_BRACKET', 'PRESS', shift=True)
+kmi.properties.direction = 'PARENT'
+kmi.properties.extend = True
+kmi = km.keymap_items.new('armature.select_hierarchy', 'RIGHT_BRACKET', 'PRESS')
+kmi.properties.direction = 'CHILD'
+kmi.properties.extend = False
+kmi = km.keymap_items.new('armature.select_hierarchy', 'RIGHT_BRACKET', 'PRESS', shift=True)
+kmi.properties.direction = 'CHILD'
+kmi.properties.extend = True
+kmi = km.keymap_items.new('armature.select_similar', 'G', 'PRESS', shift=True)
+kmi = km.keymap_items.new('armature.select_linked', 'L', 'PRESS')
+kmi = km.keymap_items.new('armature.delete', 'X', 'PRESS')
+kmi = km.keymap_items.new('armature.delete', 'DEL', 'PRESS')
+kmi = km.keymap_items.new('armature.duplicate_move', 'D', 'PRESS', shift=True)
+kmi = km.keymap_items.new('armature.extrude_move', 'E', 'PRESS')
+kmi = km.keymap_items.new('armature.extrude_forked', 'E', 'PRESS', shift=True)
+kmi = km.keymap_items.new('armature.click_extrude', 'LEFTMOUSE', 'CLICK', ctrl=True)
+kmi = km.keymap_items.new('armature.fill', 'F', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('armature.merge', 'M', 'PRESS', alt=True)
+kmi = km.keymap_items.new('armature.separate', 'P', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('wm.call_menu', 'W', 'PRESS', shift=True)
+kmi.properties.name = 'VIEW3D_MT_bone_options_toggle'
+kmi = km.keymap_items.new('wm.call_menu', 'W', 'PRESS', shift=True, ctrl=True)
+kmi.properties.name = 'VIEW3D_MT_bone_options_enable'
+kmi = km.keymap_items.new('wm.call_menu', 'W', 'PRESS', alt=True)
+kmi.properties.name = 'VIEW3D_MT_bone_options_disable'
+kmi = km.keymap_items.new('armature.layers_show_all', 'ACCENT_GRAVE', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('armature.armature_layers', 'M', 'PRESS', shift=True)
+kmi = km.keymap_items.new('armature.bone_layers', 'M', 'PRESS')
+kmi = km.keymap_items.new('transform.transform', 'S', 'PRESS', ctrl=True, alt=True)
+kmi.properties.mode = 'BONE_SIZE'
+kmi = km.keymap_items.new('transform.transform', 'R', 'PRESS', ctrl=True)
+kmi.properties.mode = 'BONE_ROLL'
+kmi = km.keymap_items.new('wm.call_menu', 'Q', 'PRESS')
+kmi.properties.name = 'VIEW3D_MT_armature_specials'
+
+# Map Metaball
+km = kc.keymaps.new('Metaball', space_type='EMPTY', region_type='WINDOW', modal=False)
+
+kmi = km.keymap_items.new('object.metaball_add', 'A', 'PRESS', shift=True)
+kmi = km.keymap_items.new('mball.reveal_metaelems', 'H', 'PRESS', alt=True)
+kmi = km.keymap_items.new('mball.hide_metaelems', 'H', 'PRESS')
+kmi.properties.unselected = False
+kmi = km.keymap_items.new('mball.hide_metaelems', 'H', 'PRESS', shift=True)
+kmi.properties.unselected = True
+kmi = km.keymap_items.new('mball.delete_metaelems', 'X', 'PRESS')
+kmi = km.keymap_items.new('mball.delete_metaelems', 'DEL', 'PRESS')
+kmi = km.keymap_items.new('mball.duplicate_metaelems', 'D', 'PRESS', shift=True)
+kmi = km.keymap_items.new('mball.select_all', 'LEFTMOUSE', 'CLICK')
+kmi.properties.action = 'TOGGLE'
+kmi = km.keymap_items.new('mball.select_all', 'I', 'PRESS', ctrl=True)
+kmi.properties.action = 'INVERT'
+kmi = km.keymap_items.new('wm.context_cycle_enum', 'O', 'PRESS', shift=True)
+kmi.properties.data_path = 'tool_settings.proportional_edit_falloff'
+kmi = km.keymap_items.new('wm.context_toggle_enum', 'O', 'PRESS')
+kmi.properties.data_path = 'tool_settings.proportional_edit'
+kmi.properties.value_1 = 'DISABLED'
+kmi.properties.value_2 = 'ENABLED'
+kmi = km.keymap_items.new('wm.context_toggle_enum', 'O', 'PRESS', alt=True)
+kmi.properties.data_path = 'tool_settings.proportional_edit'
+kmi.properties.value_1 = 'DISABLED'
+kmi.properties.value_2 = 'CONNECTED'
+
+# Map Lattice
+km = kc.keymaps.new('Lattice', space_type='EMPTY', region_type='WINDOW', modal=False)
+
+kmi = km.keymap_items.new('lattice.select_all', 'LEFTMOUSE', 'CLICK')
+kmi.properties.action = 'TOGGLE'
+kmi = km.keymap_items.new('lattice.select_all', 'I', 'PRESS', ctrl=True)
+kmi.properties.action = 'INVERT'
+kmi = km.keymap_items.new('object.vertex_parent_set', 'P', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('lattice.flip', 'F', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.call_menu', 'H', 'PRESS', ctrl=True)
+kmi.properties.name = 'VIEW3D_MT_hook'
+kmi = km.keymap_items.new('wm.context_cycle_enum', 'O', 'PRESS', shift=True)
+kmi.properties.data_path = 'tool_settings.proportional_edit_falloff'
+kmi = km.keymap_items.new('wm.context_toggle_enum', 'O', 'PRESS')
+kmi.properties.data_path = 'tool_settings.proportional_edit'
+kmi.properties.value_1 = 'DISABLED'
+kmi.properties.value_2 = 'ENABLED'
+
+# Map Particle
+km = kc.keymaps.new('Particle', space_type='EMPTY', region_type='WINDOW', modal=False)
+
+kmi = km.keymap_items.new('particle.select_all', 'A', 'PRESS')
+kmi.properties.action = 'TOGGLE'
+kmi = km.keymap_items.new('particle.select_all', 'I', 'PRESS', ctrl=True)
+kmi.properties.action = 'INVERT'
+kmi = km.keymap_items.new('particle.select_more', 'NUMPAD_PLUS', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('particle.select_less', 'NUMPAD_MINUS', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('particle.select_linked', 'L', 'PRESS')
+kmi.properties.deselect = False
+kmi = km.keymap_items.new('particle.select_linked', 'L', 'PRESS', shift=True)
+kmi.properties.deselect = True
+kmi = km.keymap_items.new('particle.delete', 'X', 'PRESS')
+kmi = km.keymap_items.new('particle.delete', 'DEL', 'PRESS')
+kmi = km.keymap_items.new('particle.reveal', 'H', 'PRESS', alt=True)
+kmi = km.keymap_items.new('particle.hide', 'H', 'PRESS')
+kmi.properties.unselected = False
+kmi = km.keymap_items.new('particle.hide', 'H', 'PRESS', shift=True)
+kmi.properties.unselected = True
+kmi = km.keymap_items.new('view3d.manipulator', 'LEFTMOUSE', 'PRESS', any=True)
+kmi.properties.release_confirm = True
+kmi = km.keymap_items.new('particle.brush_edit', 'LEFTMOUSE', 'PRESS')
+kmi = km.keymap_items.new('particle.brush_edit', 'LEFTMOUSE', 'PRESS', shift=True)
+kmi = km.keymap_items.new('wm.radial_control', 'F', 'PRESS', ctrl=True)
+kmi.properties.data_path_primary = 'tool_settings.particle_edit.brush.size'
+kmi = km.keymap_items.new('wm.radial_control', 'F', 'PRESS', shift=True)
+kmi.properties.data_path_primary = 'tool_settings.particle_edit.brush.strength'
+kmi = km.keymap_items.new('wm.call_menu', 'W', 'PRESS')
+kmi.properties.name = 'VIEW3D_MT_particle_specials'
+kmi = km.keymap_items.new('particle.weight_set', 'K', 'PRESS', shift=True)
+kmi = km.keymap_items.new('wm.context_cycle_enum', 'O', 'PRESS', shift=True)
+kmi.properties.data_path = 'tool_settings.proportional_edit_falloff'
+kmi = km.keymap_items.new('wm.context_toggle_enum', 'O', 'PRESS')
+kmi.properties.data_path = 'tool_settings.proportional_edit'
+kmi.properties.value_1 = 'DISABLED'
+kmi.properties.value_2 = 'ENABLED'
+
+# Map Transform Modal Map
+km = kc.keymaps.new('Transform Modal Map', space_type='EMPTY', region_type='WINDOW', modal=True)
+
+kmi = km.keymap_items.new_modal('CANCEL', 'ESC', 'PRESS', any=True)
+kmi = km.keymap_items.new_modal('CONFIRM', 'LEFTMOUSE', 'RELEASE', any=True)
+kmi = km.keymap_items.new_modal('CONFIRM', 'RET', 'PRESS', any=True)
+kmi = km.keymap_items.new_modal('CONFIRM', 'NUMPAD_ENTER', 'PRESS', any=True)
+kmi = km.keymap_items.new_modal('TRANSLATE', 'W', 'PRESS')
+kmi = km.keymap_items.new_modal('ROTATE', 'E', 'PRESS')
+kmi = km.keymap_items.new_modal('RESIZE', 'R', 'PRESS')
+kmi = km.keymap_items.new_modal('SNAP_TOGGLE', 'TAB', 'PRESS', shift=True)
+kmi = km.keymap_items.new_modal('SNAP_INV_ON', 'LEFT_CTRL', 'PRESS', any=True)
+kmi = km.keymap_items.new_modal('SNAP_INV_OFF', 'LEFT_CTRL', 'RELEASE', any=True)
+kmi = km.keymap_items.new_modal('SNAP_INV_ON', 'RIGHT_CTRL', 'PRESS', any=True)
+kmi = km.keymap_items.new_modal('SNAP_INV_OFF', 'RIGHT_CTRL', 'RELEASE', any=True)
+kmi = km.keymap_items.new_modal('ADD_SNAP', 'A', 'PRESS')
+kmi = km.keymap_items.new_modal('REMOVE_SNAP', 'A', 'PRESS', alt=True)
+kmi = km.keymap_items.new_modal('PROPORTIONAL_SIZE_UP', 'PAGE_UP', 'PRESS')
+kmi = km.keymap_items.new_modal('PROPORTIONAL_SIZE_DOWN', 'PAGE_DOWN', 'PRESS')
+kmi = km.keymap_items.new_modal('PROPORTIONAL_SIZE_UP', 'WHEELDOWNMOUSE', 'PRESS')
+kmi = km.keymap_items.new_modal('PROPORTIONAL_SIZE_DOWN', 'WHEELUPMOUSE', 'PRESS')
+kmi = km.keymap_items.new_modal('PROPORTIONAL_SIZE', 'TRACKPADPAN', 'ANY')
+kmi = km.keymap_items.new_modal('EDGESLIDE_EDGE_NEXT', 'WHEELDOWNMOUSE', 'PRESS', alt=True)
+kmi = km.keymap_items.new_modal('EDGESLIDE_PREV_NEXT', 'WHEELUPMOUSE', 'PRESS', alt=True)
+kmi = km.keymap_items.new_modal('AUTOIK_CHAIN_LEN_UP', 'PAGE_UP', 'PRESS', shift=True)
+kmi = km.keymap_items.new_modal('AUTOIK_CHAIN_LEN_DOWN', 'PAGE_DOWN', 'PRESS', shift=True)
+kmi = km.keymap_items.new_modal('AUTOIK_CHAIN_LEN_UP', 'WHEELDOWNMOUSE', 'PRESS', shift=True)
+kmi = km.keymap_items.new_modal('AUTOIK_CHAIN_LEN_DOWN', 'WHEELUPMOUSE', 'PRESS', shift=True)
diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py
index ec8efc8d371..d6805fb3484 100644
--- a/release/scripts/presets/keyconfig/maya.py
+++ b/release/scripts/presets/keyconfig/maya.py
@@ -138,41 +138,49 @@ kmi.properties.extend = False
kmi.properties.center = False
kmi.properties.object = False
kmi.properties.enumerate = False
+kmi.properties.toggle = False
kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', shift=True)
-kmi.properties.extend = True
+kmi.properties.extend = False
kmi.properties.center = False
kmi.properties.object = False
kmi.properties.enumerate = False
+kmi.properties.toggle = True
kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', ctrl=True)
kmi.properties.extend = False
kmi.properties.center = True
kmi.properties.object = False
kmi.properties.enumerate = False
+kmi.properties.toggle = False
kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', alt=True)
kmi.properties.extend = False
kmi.properties.center = False
kmi.properties.object = False
kmi.properties.enumerate = True
+kmi.properties.toggle = False
kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', shift=True, ctrl=True)
kmi.properties.extend = True
kmi.properties.center = True
kmi.properties.object = False
kmi.properties.enumerate = False
+kmi.properties.toggle = True
kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', ctrl=True, alt=True)
kmi.properties.extend = False
kmi.properties.center = True
kmi.properties.object = False
kmi.properties.enumerate = True
+kmi.properties.toggle = False
kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', shift=True, alt=True)
kmi.properties.extend = True
kmi.properties.center = False
kmi.properties.object = False
kmi.properties.enumerate = True
+kmi.properties.toggle = True
kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', shift=True, ctrl=True, alt=True)
kmi.properties.extend = True
kmi.properties.center = True
kmi.properties.object = False
kmi.properties.enumerate = True
+kmi.properties.toggle = True
kmi = km.keymap_items.new('view3d.select_border', 'EVT_TWEAK_S', 'ANY')
kmi.properties.extend = False
kmi = km.keymap_items.new('view3d.select_lasso', 'EVT_TWEAK_A', 'ANY', ctrl=True)
@@ -218,7 +226,9 @@ kmi.properties.use = True
kmi = km.keymap_items.new('transform.mirror', 'M', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('wm.context_toggle', 'TAB', 'PRESS', shift=True)
kmi.properties.data_path = 'tool_settings.use_snap'
-kmi = km.keymap_items.new('transform.snap_type', 'TAB', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('WM_OT_context_menu_enum', 'TAB', 'PRESS', shift=True, ctrl=True)
+kmi.properties.data_path = 'tool_settings.snap_element'
+
kmi = km.keymap_items.new('view3d.enable_manipulator', 'W', 'PRESS')
kmi.properties.translate = True
kmi = km.keymap_items.new('view3d.enable_manipulator', 'E', 'PRESS')
diff --git a/release/scripts/presets/operator/wm.collada_export/second_life_rigged.py b/release/scripts/presets/operator/wm.collada_export/second_life_rigged.py
index 2c695a22ff9..717e044ccd6 100644
--- a/release/scripts/presets/operator/wm.collada_export/second_life_rigged.py
+++ b/release/scripts/presets/operator/wm.collada_export/second_life_rigged.py
@@ -7,10 +7,12 @@ op.export_mesh_type_selection = 'view'
op.selected = True
op.include_children = False
op.include_armatures = True
+op.include_shapekeys = False
op.deform_bones_only = True
op.active_uv_only = True
op.include_uv_textures = True
op.use_texture_copies = True
+op.triangulate = True
op.use_object_instantiation = False
op.sort_by_name = True
op.second_life = True
diff --git a/release/scripts/presets/operator/wm.collada_export/second_life_static.py b/release/scripts/presets/operator/wm.collada_export/second_life_static.py
index 081788b7e9d..9518fe5fb35 100644
--- a/release/scripts/presets/operator/wm.collada_export/second_life_static.py
+++ b/release/scripts/presets/operator/wm.collada_export/second_life_static.py
@@ -7,10 +7,12 @@ op.export_mesh_type_selection = 'view'
op.selected = True
op.include_children = False
op.include_armatures = False
+op.include_shapekeys = False
op.deform_bones_only = False
op.active_uv_only = True
op.include_uv_textures = True
op.use_texture_copies = True
+op.triangulate = True
op.use_object_instantiation = False
op.sort_by_name = True
op.second_life = False
diff --git a/release/scripts/startup/bl_operators/__init__.py b/release/scripts/startup/bl_operators/__init__.py
index ecbbe34dbb4..64851a3a4c1 100644
--- a/release/scripts/startup/bl_operators/__init__.py
+++ b/release/scripts/startup/bl_operators/__init__.py
@@ -22,7 +22,7 @@ if "bpy" in locals():
from imp import reload as _reload
for val in _modules_loaded.values():
_reload(val)
-_modules = (
+_modules = [
"add_mesh_torus",
"anim",
"clip",
@@ -35,6 +35,7 @@ _modules = (
"object_randomize_transform",
"object_quick_effects",
"presets",
+ "rigidbody",
"screen_play_rendered_anim",
"sequencer",
"uvcalc_follow_active",
@@ -43,16 +44,18 @@ _modules = (
"vertexpaint_dirt",
"view3d",
"wm",
-)
+]
+
+import bpy
+
+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}
+_modules_loaded = {name: _namespace[name] for name in _modules if name != 'bpy'}
del _namespace
-import bpy
-
-
def register():
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_operators/add_mesh_torus.py b/release/scripts/startup/bl_operators/add_mesh_torus.py
index 552247f0940..63e796e2b5d 100644
--- a/release/scripts/startup/bl_operators/add_mesh_torus.py
+++ b/release/scripts/startup/bl_operators/add_mesh_torus.py
@@ -19,7 +19,6 @@
# <pep8-80 compliant>
import bpy
from bpy.types import Operator
-import mathutils
from bpy.props import (FloatProperty,
IntProperty,
@@ -31,9 +30,7 @@ from bpy_extras import object_utils
def add_torus(major_rad, minor_rad, major_seg, minor_seg):
from math import cos, sin, pi
-
- Vector = mathutils.Vector
- Quaternion = mathutils.Quaternion
+ from mathutils import Vector, Quaternion
PI_2 = pi * 2.0
z_axis = 0.0, 0.0, 1.0
diff --git a/release/scripts/startup/bl_operators/anim.py b/release/scripts/startup/bl_operators/anim.py
index 902c7007fb9..e34e9a981a6 100644
--- a/release/scripts/startup/bl_operators/anim.py
+++ b/release/scripts/startup/bl_operators/anim.py
@@ -187,17 +187,20 @@ class BakeAction(Operator):
)
only_selected = BoolProperty(
name="Only Selected",
+ description="Only key selected object/bones",
default=True,
)
clear_constraints = BoolProperty(
name="Clear Constraints",
+ description="Remove all constraints from keyed object/bones, and do 'visual' keying",
default=False,
)
bake_types = EnumProperty(
name="Bake Data",
+ description="Which data's transformations to bake",
options={'ENUM_FLAG'},
- items=(('POSE', "Pose", ""),
- ('OBJECT', "Object", ""),
+ items=(('POSE', "Pose", "Bake bones transformations"),
+ ('OBJECT', "Object", "Bake object transformations"),
),
default={'POSE'},
)
@@ -208,12 +211,12 @@ class BakeAction(Operator):
action = anim_utils.bake_action(self.frame_start,
self.frame_end,
- self.step,
- self.only_selected,
- 'POSE' in self.bake_types,
- 'OBJECT' in self.bake_types,
- self.clear_constraints,
- True,
+ frame_step=self.step,
+ only_selected=self.only_selected,
+ do_pose='POSE' in self.bake_types,
+ do_object='OBJECT' in self.bake_types,
+ do_constraint_clear=self.clear_constraints,
+ do_clean=True,
)
if action is None:
diff --git a/release/scripts/startup/bl_operators/freestyle.py b/release/scripts/startup/bl_operators/freestyle.py
new file mode 100644
index 00000000000..19e6f67ba77
--- /dev/null
+++ b/release/scripts/startup/bl_operators/freestyle.py
@@ -0,0 +1,135 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public 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 bpy
+
+from bpy.props import (EnumProperty, StringProperty)
+
+
+class SCENE_OT_freestyle_fill_range_by_selection(bpy.types.Operator):
+ '''Fill the Range Min/Max entries by the min/max distance between selected mesh objects and the source object
+ (either a user-specified object or the active camera)'''
+ bl_idname = "scene.freestyle_fill_range_by_selection"
+ bl_label = "Fill Range by Selection"
+
+ 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")
+
+ def execute(self, context):
+ rl = context.scene.render.layers.active
+ lineset = rl.freestyle_settings.linesets.active
+ linestyle = lineset.linestyle
+ # Find the modifier to work on
+ if self.type == 'COLOR':
+ m = linestyle.color_modifiers[self.name]
+ elif self.type == 'ALPHA':
+ m = linestyle.alpha_modifiers[self.name]
+ else:
+ m = linestyle.thickness_modifiers[self.name]
+ # Find the source object
+ if m.type == 'DISTANCE_FROM_CAMERA':
+ source = context.scene.camera
+ elif m.type == 'DISTANCE_FROM_OBJECT':
+ if m.target is None:
+ self.report({'ERROR'}, "Target object not specified")
+ return {'CANCELLED'}
+ source = m.target
+ else:
+ self.report({'ERROR'}, "Unexpected modifier type: " + m.type)
+ return {'CANCELLED'}
+ # Find selected mesh objects
+ selection = [ob for ob in context.scene.objects if ob.select and ob.type == 'MESH' and ob.name != source.name]
+ if len(selection) > 0:
+ # Compute the min/max distance between selected mesh objects and the source
+ min_dist = sys.float_info.max
+ max_dist = -min_dist
+ for ob in selection:
+ for vert in ob.data.vertices:
+ dist = (ob.matrix_world * vert.co - source.location).length
+ min_dist = min(dist, min_dist)
+ max_dist = max(dist, max_dist)
+ # Fill the Range Min/Max entries with the computed distances
+ m.range_min = min_dist
+ m.range_max = max_dist
+ return {'FINISHED'}
+
+
+class SCENE_OT_freestyle_add_edge_marks_to_keying_set(bpy.types.Operator):
+ '''Add the data paths to the Freestyle Edge Mark property of selected edges to the active keying set'''
+ bl_idname = "scene.freestyle_add_edge_marks_to_keying_set"
+ bl_label = "Add Edge Marks to Keying Set"
+ bl_options = {'UNDO'}
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.active_object
+ return (ob and ob.type == 'MESH')
+
+ def execute(self, context):
+ # active keying set
+ scene = context.scene
+ ks = scene.keying_sets.active
+ if ks is None:
+ ks = scene.keying_sets.new(idname="FreestyleEdgeMarkKeyingSet", name="Freestyle Edge Mark Keying Set")
+ ks.bl_description = ""
+ # add data paths to the keying set
+ ob = context.active_object
+ ob_mode = ob.mode
+ mesh = ob.data
+ bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+ for i, edge in enumerate(mesh.edges):
+ if not edge.hide and edge.select:
+ path = 'edges[%d].use_freestyle_edge_mark' % i
+ ks.paths.add(mesh, path, index=0)
+ bpy.ops.object.mode_set(mode=ob_mode, toggle=False)
+ return {'FINISHED'}
+
+
+class SCENE_OT_freestyle_add_face_marks_to_keying_set(bpy.types.Operator):
+ '''Add the data paths to the Freestyle Face Mark property of selected polygons to the active keying set'''
+ bl_idname = "scene.freestyle_add_face_marks_to_keying_set"
+ bl_label = "Add Face Marks to Keying Set"
+ bl_options = {'UNDO'}
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.active_object
+ return (ob and ob.type == 'MESH')
+
+ def execute(self, context):
+ # active keying set
+ scene = context.scene
+ ks = scene.keying_sets.active
+ if ks is None:
+ ks = scene.keying_sets.new(idname="FreestyleFaceMarkKeyingSet", name="Freestyle Face Mark Keying Set")
+ ks.bl_description = ""
+ # add data paths to the keying set
+ ob = context.active_object
+ ob_mode = ob.mode
+ mesh = ob.data
+ bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+ for i, polygon in enumerate(mesh.polygons):
+ if not polygon.hide and polygon.select:
+ path = 'polygons[%d].use_freestyle_face_mark' % i
+ ks.paths.add(mesh, path, index=0)
+ bpy.ops.object.mode_set(mode=ob_mode, toggle=False)
+ return {'FINISHED'}
diff --git a/release/scripts/startup/bl_operators/node.py b/release/scripts/startup/bl_operators/node.py
index fb264cb3429..5c7f3c3f4b2 100644
--- a/release/scripts/startup/bl_operators/node.py
+++ b/release/scripts/startup/bl_operators/node.py
@@ -20,77 +20,138 @@
import bpy
from bpy.types import Operator
-from bpy.props import EnumProperty
-
-# XXX These node item lists should actually be generated by a callback at
-# operator execution time (see node_type_items below),
-# using the active node tree from the context.
-# Due to a difficult bug in bpy this is not possible
-# (item list memory gets freed too early),
-# so for now just copy the static item lists to these global variables.
-#
-# In the custom_nodes branch, the static per-tree-type node items are replaced
-# by a single independent type list anyway (with a poll function to limit node
-# types to the respective trees). So this workaround is only temporary.
+from bpy.props import BoolProperty, EnumProperty, StringProperty
-# lazy init
-node_type_items_dict = {}
-# Prefixes used to distinguish base node types and node groups
-node_type_prefix = 'NODE_'
-node_group_prefix = 'GROUP_'
+# Base class for node 'Add' operators
+class NodeAddOperator():
+ @staticmethod
+ def store_mouse_cursor(context, event):
+ space = context.space_data
+ v2d = context.region.view2d
+ # convert mouse position to the View2D for later node placement
+ space.cursor_location = v2d.region_to_view(event.mouse_region_x,
+ event.mouse_region_y)
-# Generate a list of enum items for a given node class
-# Copy existing type enum, adding a prefix to distinguish from node groups
-# Skip the base node group type,
-# node groups will be added below for all existing group trees
-def node_type_items(node_class):
- return [(node_type_prefix + item.identifier, item.name, item.description)
- for item in node_class.bl_rna.properties['type'].enum_items
- if item.identifier != 'GROUP']
+ def create_node(self, context, node_type):
+ space = context.space_data
+ tree = space.edit_tree
+ # select only the new node
+ for n in tree.nodes:
+ n.select = False
-# Generate items for node group types
-# Filter by the given tree_type
-# Node group trees don't have a description property yet
-# (could add this as a custom property though)
-def node_group_items(tree_type):
- return [(node_group_prefix + group.name, group.name, '')
- for group in bpy.data.node_groups if group.type == tree_type]
+ node = tree.nodes.new(type=node_type)
+ if space.use_hidden_preview:
+ node.show_preview = False
-# Returns the enum item list for the edited tree in the context
-def node_type_items_cb(self, context):
+ node.select = True
+ tree.nodes.active = node
+ node.location = space.cursor_location
+ return node
+
+ @classmethod
+ def poll(cls, context):
+ space = context.space_data
+ # needs active node editor and a tree to add nodes to
+ return (space.type == 'NODE_EDITOR' and space.edit_tree)
+
+ # Default invoke stores the mouse position to place the node correctly
+ def invoke(self, context, event):
+ self.store_mouse_cursor(context, event)
+ return self.execute(context)
+
+
+# Simple basic operator for adding a node
+class NODE_OT_add_node(NodeAddOperator, Operator):
+ '''Add a node to the active tree'''
+ bl_idname = "node.add_node"
+ bl_label = "Add Node"
+
+ type = StringProperty(
+ name="Node Type",
+ description="Node type",
+ )
+ # optional group tree parameter for group nodes
+ group_tree = StringProperty(
+ name="Group tree",
+ description="Group node tree name",
+ )
+ use_transform = BoolProperty(
+ name="Use Transform",
+ description="Start transform operator after inserting the node",
+ default=False,
+ )
+
+ def execute(self, context):
+ node = self.create_node(context, self.type)
+
+ # set the node group tree of a group node
+ if self.properties.is_property_set('group_tree'):
+ node.node_tree = bpy.data.node_groups[self.group_tree]
+
+ return {'FINISHED'}
+
+ def invoke(self, context, event):
+ self.store_mouse_cursor(context, event)
+ result = self.execute(context)
+ if self.use_transform and ('FINISHED' in result):
+ return bpy.ops.transform.translate('INVOKE_DEFAULT')
+ else:
+ return result
+
+
+def node_classes_iter(base=bpy.types.Node):
+ """
+ Yields all true node classes by checking for the is_registered_node_type classmethod.
+ Node types can use specialized subtypes of bpy.types.Node, which are not usable
+ nodes themselves (e.g. CompositorNode).
+ """
+ if base.is_registered_node_type():
+ yield base
+ for subclass in base.__subclasses__():
+ for node_class in node_classes_iter(subclass):
+ yield node_class
+
+
+def node_class_items_iter(node_class, context):
+ identifier = node_class.bl_rna.identifier
+ # XXX Checking for explicit group node types is stupid.
+ # This should be replaced by a generic system of generating
+ # node items via callback.
+ # Group node_tree pointer should also use a poll function to filter the library list,
+ # but cannot do that without a node instance here. A node callback could just use the internal poll function.
+ if identifier in {'ShaderNodeGroup', 'CompositorNodeGroup', 'TextureNodeGroup'}:
+ tree_idname = context.space_data.edit_tree.bl_idname
+ for group in bpy.data.node_groups:
+ if group.bl_idname == tree_idname:
+ yield (group.name, "", {"node_tree":group}) # XXX empty string should be replaced by description from tree
+ else:
+ yield (node_class.bl_rna.name, node_class.bl_rna.description, {})
+
+
+def node_items_iter(context):
snode = context.space_data
if not snode:
- return ()
+ return
tree = snode.edit_tree
if not tree:
- return ()
-
- # Lists of basic node types for each
- if not node_type_items_dict:
- node_type_items_dict.update({
- 'SHADER': node_type_items(bpy.types.ShaderNode),
- 'COMPOSITING': node_type_items(bpy.types.CompositorNode),
- 'TEXTURE': node_type_items(bpy.types.TextureNode),
- })
-
- # XXX Does not work correctly, see comment above
- '''
- return [(item.identifier, item.name, item.description, item.value)
- for item in
- tree.nodes.bl_rna.functions['new'].parameters['type'].enum_items]
- '''
-
- if tree.type in node_type_items_dict:
- return node_type_items_dict[tree.type] + node_group_items(tree.type)
- else:
- return ()
+ return
+
+ for node_class in node_classes_iter():
+ if node_class.poll(tree):
+ for item in node_class_items_iter(node_class, context):
+ yield (node_class,) + item
+
+
+# Create an enum list from node class items
+def node_type_items_cb(self, context):
+ return [(str(index), item[1], item[2]) for index, item in enumerate(node_items_iter(context))]
-class NODE_OT_add_search(Operator):
+class NODE_OT_add_search(NodeAddOperator, Operator):
'''Add a node to the active tree'''
bl_idname = "node.add_search"
bl_label = "Search and Add Node"
@@ -104,55 +165,48 @@ class NODE_OT_add_search(Operator):
items=node_type_items_cb,
)
- _node_type_items_dict = None
+ def execute(self, context):
+ for index, item in enumerate(node_items_iter(context)):
+ if str(index) == self.type:
+ node = self.create_node(context, item[0].bl_rna.identifier)
+ for prop,value in item[3].items():
+ setattr(node, prop, value)
+ break
+ return {'FINISHED'}
- def create_node(self, context):
- space = context.space_data
- tree = space.edit_tree
+ def invoke(self, context, event):
+ self.store_mouse_cursor(context, event)
+ # Delayed execution in the search popup
+ context.window_manager.invoke_search_popup(self)
+ return {'CANCELLED'}
- # Enum item identifier has an additional prefix to
- # distinguish base node types from node groups
- item = self.type
- if item.startswith(node_type_prefix):
- # item means base node type
- node = tree.nodes.new(type=item[len(node_type_prefix):])
- elif item.startswith(node_group_prefix):
- # item means node group type
- node = tree.nodes.new(
- type='GROUP',
- group=bpy.data.node_groups[item[len(node_group_prefix):]])
- else:
- return None
- for n in tree.nodes:
- if n == node:
- node.select = True
- tree.nodes.active = node
- else:
- node.select = False
- node.location = space.cursor_location
- return node
+# Simple basic operator for adding a node without further initialization
+class NODE_OT_add_node(NodeAddOperator, bpy.types.Operator):
+ '''Add a node to the active tree'''
+ bl_idname = "node.add_node"
+ bl_label = "Add Node"
- @classmethod
- def poll(cls, context):
- space = context.space_data
- # needs active node editor and a tree to add nodes to
- return (space.type == 'NODE_EDITOR' and space.edit_tree)
+ type = StringProperty(name="Node Type", description="Node type")
def execute(self, context):
- self.create_node(context)
+ node = self.create_node(context, self.type)
return {'FINISHED'}
- def invoke(self, context, event):
- space = context.space_data
- v2d = context.region.view2d
- # convert mouse position to the View2D for later node placement
- space.cursor_location = v2d.region_to_view(event.mouse_region_x,
- event.mouse_region_y)
+class NODE_OT_add_group_node(NodeAddOperator, bpy.types.Operator):
+ '''Add a group node to the active tree'''
+ bl_idname = "node.add_group_node"
+ bl_label = "Add Group Node"
- context.window_manager.invoke_search_popup(self)
- return {'CANCELLED'}
+ type = StringProperty(name="Node Type", description="Node type")
+ grouptree = StringProperty(name="Group tree", description="Group node tree name")
+
+ def execute(self, context):
+ node = self.create_node(context, self.type)
+ node.node_tree = bpy.data.node_groups[self.grouptree]
+
+ return {'FINISHED'}
class NODE_OT_collapse_hide_unused_toggle(Operator):
@@ -183,3 +237,24 @@ class NODE_OT_collapse_hide_unused_toggle(Operator):
socket.hide = hide
return {'FINISHED'}
+
+
+class NODE_OT_tree_path_parent(Operator):
+ '''Go to parent node tree'''
+ bl_idname = "node.tree_path_parent"
+ bl_label = "Parent Node Tree"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ @classmethod
+ def poll(cls, context):
+ space = context.space_data
+ # needs active node editor and a tree
+ return (space.type == 'NODE_EDITOR' and len(space.path) > 1)
+
+ def execute(self, context):
+ space = context.space_data
+
+ space.path.pop()
+
+ return {'FINISHED'}
+
diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py
index 9e449f325d6..ae6b80865dd 100644
--- a/release/scripts/startup/bl_operators/object.py
+++ b/release/scripts/startup/bl_operators/object.py
@@ -110,6 +110,12 @@ class SelectCamera(Operator):
bl_label = "Select Camera"
bl_options = {'REGISTER', 'UNDO'}
+ extend = BoolProperty(
+ name="Extend",
+ description="Extend the selection",
+ default=False
+ )
+
def execute(self, context):
scene = context.scene
view = context.space_data
@@ -123,6 +129,8 @@ class SelectCamera(Operator):
elif camera.name not in scene.objects:
self.report({'WARNING'}, "Active camera is not in this scene")
else:
+ if not self.extend:
+ bpy.ops.object.select_all(action='DESELECT')
context.scene.objects.active = camera
camera.select = True
return {'FINISHED'}
@@ -297,7 +305,7 @@ class ShapeTransfer(Operator):
('RELATIVE_EDGE',
"Relative Edge",
"Calculate relative position (using edges)",
- ),
+ ),
),
name="Transformation Mode",
description="Relative shape positions to the new shape method",
@@ -373,11 +381,8 @@ class ShapeTransfer(Operator):
(orig_shape_coords[i] - orig_coords[i]))
elif mode == 'RELATIVE_FACE':
- loops_vidxs = me.loops.foreach_get("vert_index")
for poly in me.polygons:
- l_start = l_stop = poly.loop_start
- l_stop += poly.loop_total
- idxs = loops_vidxs[l_start:l_stop]
+ idxs = poly.vertices[:]
v_before = idxs[-2]
v = idxs[-1]
for v_after in idxs:
@@ -468,9 +473,9 @@ class ShapeTransfer(Operator):
class JoinUVs(Operator):
- """Copy UV Layout to objects with matching geometry"""
+ """Transfer UV Layouts from active to selected objects (needs matching geometry)"""
bl_idname = "object.join_uvs"
- bl_label = "Join as UVs"
+ bl_label = "Transfer UV Layouts"
@classmethod
def poll(cls, context):
@@ -674,7 +679,7 @@ class TransformsToDeltasAnim(Operator):
"scale" : "delta_scale"
}
DELTA_PATHS = STANDARD_TO_DELTA_PATHS.values()
-
+
# try to apply on each selected object
success = False
for obj in context.selected_editable_objects:
@@ -684,7 +689,7 @@ class TransformsToDeltasAnim(Operator):
"No animation data to convert on object: %r" %
obj.name)
continue
-
+
# first pass over F-Curves: ensure that we don't have conflicting
# transforms already (e.g. if this was applied already) [#29110]
existingFCurves = {}
@@ -700,7 +705,7 @@ class TransformsToDeltasAnim(Operator):
else:
# non-transform - ignore
continue
-
+
# a delta path like this for the same index shouldn't
# exist already, otherwise we've got a conflict
if dpath in existingFCurves:
@@ -708,8 +713,9 @@ class TransformsToDeltasAnim(Operator):
if fcu.array_index in existingFCurves[dpath]:
# conflict
self.report({'ERROR'},
- "Object '%r' already has '%r' F-Curve(s). Remove these before trying again" %
- (obj.name, dpath))
+ "Object '%r' already has '%r' F-Curve(s). "
+ "Remove these before trying again" %
+ (obj.name, dpath))
return {'CANCELLED'}
else:
# no conflict here
@@ -717,8 +723,7 @@ class TransformsToDeltasAnim(Operator):
else:
# no conflict yet
existingFCurves[dpath] = [fcu.array_index]
-
-
+
# if F-Curve uses standard transform path
# just append "delta_" to this path
for fcu in adt.action.fcurves:
@@ -758,7 +763,7 @@ class DupliOffsetFromCursor(Operator):
@classmethod
def poll(cls, context):
- return context.active_object is not None
+ return (context.active_object is not None)
def execute(self, context):
scene = context.scene
diff --git a/release/scripts/startup/bl_operators/object_align.py b/release/scripts/startup/bl_operators/object_align.py
index a32bb8c5353..e843209da3c 100644
--- a/release/scripts/startup/bl_operators/object_align.py
+++ b/release/scripts/startup/bl_operators/object_align.py
@@ -114,31 +114,32 @@ def GlobalBB_HQ(obj):
return Vector((left, front, up)), Vector((right, back, down))
-def align_objects(align_x,
+def align_objects(context,
+ align_x,
align_y,
align_z,
align_mode,
relative_to,
bb_quality):
- cursor = bpy.context.scene.cursor_location
+ cursor = context.scene.cursor_location
Left_Front_Up_SEL = [0.0, 0.0, 0.0]
Right_Back_Down_SEL = [0.0, 0.0, 0.0]
flag_first = True
- objs = []
+ objects = []
- for obj in bpy.context.selected_objects:
+ for obj in context.selected_objects:
matrix_world = obj.matrix_world.copy()
bb_world = [matrix_world * Vector(v[:]) for v in obj.bound_box]
- objs.append((obj, bb_world))
+ objects.append((obj, bb_world))
- if not objs:
+ if not objects:
return False
- for obj, bb_world in objs:
+ for obj, bb_world in objects:
if bb_quality and obj.type == 'MESH':
GBB = GlobalBB_HQ(obj)
@@ -150,7 +151,7 @@ def align_objects(align_x,
# Active Center
- if obj == bpy.context.active_object:
+ if obj == context.active_object:
center_active_x = (Left_Front_Up[0] + Right_Back_Down[0]) / 2.0
center_active_y = (Left_Front_Up[1] + Right_Back_Down[1]) / 2.0
@@ -200,7 +201,7 @@ def align_objects(align_x,
# Main Loop
- for obj, bb_world in objs:
+ for obj, bb_world in objects:
matrix_world = obj.matrix_world.copy()
bb_world = [matrix_world * Vector(v[:]) for v in obj.bound_box]
@@ -386,7 +387,8 @@ class AlignObjects(Operator):
def execute(self, context):
align_axis = self.align_axis
- ret = align_objects('X' in align_axis,
+ ret = align_objects(context,
+ 'X' in align_axis,
'Y' in align_axis,
'Z' in align_axis,
self.align_mode,
diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py
index cd0b63a6b78..47012f0c459 100644
--- a/release/scripts/startup/bl_operators/object_quick_effects.py
+++ b/release/scripts/startup/bl_operators/object_quick_effects.py
@@ -72,7 +72,7 @@ class QuickFur(Operator):
)
def execute(self, context):
- fake_context = bpy.context.copy()
+ fake_context = context.copy()
mesh_objects = [obj for obj in context.selected_objects
if obj.type == 'MESH']
@@ -161,7 +161,7 @@ class QuickExplode(Operator):
)
def execute(self, context):
- fake_context = bpy.context.copy()
+ fake_context = context.copy()
obj_act = context.active_object
if obj_act is None or obj_act.type != 'MESH':
@@ -311,7 +311,7 @@ class QuickSmoke(Operator):
)
def execute(self, context):
- fake_context = bpy.context.copy()
+ fake_context = context.copy()
mesh_objects = [obj for obj in context.selected_objects
if obj.type == 'MESH']
min_co = Vector((100000.0, 100000.0, 100000.0))
@@ -432,7 +432,7 @@ class QuickFluid(Operator):
)
def execute(self, context):
- fake_context = bpy.context.copy()
+ fake_context = context.copy()
mesh_objects = [obj for obj in context.selected_objects
if (obj.type == 'MESH' and not 0.0 in obj.dimensions)]
min_co = Vector((100000, 100000, 100000))
diff --git a/release/scripts/startup/bl_operators/object_randomize_transform.py b/release/scripts/startup/bl_operators/object_randomize_transform.py
index a6efc9dfd85..38110328603 100644
--- a/release/scripts/startup/bl_operators/object_randomize_transform.py
+++ b/release/scripts/startup/bl_operators/object_randomize_transform.py
@@ -23,7 +23,8 @@ from bpy.types import Operator
from mathutils import Vector
-def randomize_selected(seed, delta, loc, rot, scale, scale_even, scale_min):
+def randomize_selected(context, seed, delta,
+ loc, rot, scale, scale_even, scale_min):
import random
from random import uniform
@@ -33,7 +34,7 @@ def randomize_selected(seed, delta, loc, rot, scale, scale_even, scale_min):
def rand_vec(vec_range):
return Vector(uniform(-val, val) for val in vec_range)
- for obj in bpy.context.selected_objects:
+ for obj in context.selected_objects:
if loc:
if delta:
@@ -180,6 +181,7 @@ class RandomizeLocRotSize(Operator):
#scale_min = self.scale_min
scale_min = 0
- randomize_selected(seed, delta, loc, rot, scale, scale_even, scale_min)
+ randomize_selected(context, seed, delta,
+ loc, rot, scale, scale_even, scale_min)
return {'FINISHED'}
diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py
index ee9769d8b43..dac7adecaff 100644
--- a/release/scripts/startup/bl_operators/presets.py
+++ b/release/scripts/startup/bl_operators/presets.py
@@ -320,13 +320,13 @@ class AddPresetFluid(AddPresetBase, Operator):
preset_menu = "FLUID_MT_presets"
preset_defines = [
- "fluid = bpy.context.fluid"
- ]
+ "fluid = bpy.context.fluid"
+ ]
preset_values = [
- "fluid.settings.viscosity_base",
- "fluid.settings.viscosity_exponent",
- ]
+ "fluid.settings.viscosity_base",
+ "fluid.settings.viscosity_exponent",
+ ]
preset_subdir = "fluid"
@@ -477,7 +477,7 @@ class AddPresetNodeColor(AddPresetBase, Operator):
class AddPresetInterfaceTheme(AddPresetBase, Operator):
"""Add a theme preset"""
bl_idname = "wm.interface_theme_preset_add"
- bl_label = "Add Tracking Settings Preset"
+ bl_label = "Add Theme Preset"
preset_menu = "USERPREF_MT_interface_theme_presets"
preset_subdir = "interface_theme"
diff --git a/release/scripts/startup/bl_operators/rigidbody.py b/release/scripts/startup/bl_operators/rigidbody.py
new file mode 100644
index 00000000000..f327c602fb6
--- /dev/null
+++ b/release/scripts/startup/bl_operators/rigidbody.py
@@ -0,0 +1,292 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8-80 compliant>
+
+import bpy
+from bpy.types import Operator
+from bpy.props import IntProperty
+from bpy.props import EnumProperty
+
+
+class CopyRigidbodySettings(Operator):
+ '''Copy Rigid Body settings from active object to selected'''
+ bl_idname = "rigidbody.object_settings_copy"
+ bl_label = "Copy Rigid Body Settings"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.object
+ return (obj and obj.rigid_body)
+
+ def execute(self, context):
+ obj = context.object
+ scene = context.scene
+
+ # deselect all but mesh objects
+ for o in context.selected_objects:
+ if o.type != 'MESH':
+ o.select = False
+
+ 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)
+
+ # copy settings
+ for o in objects:
+ if o.rigid_body is None:
+ continue
+
+ o.rigid_body.type = obj.rigid_body.type
+ o.rigid_body.kinematic = obj.rigid_body.kinematic
+ o.rigid_body.mass = obj.rigid_body.mass
+ o.rigid_body.collision_shape = obj.rigid_body.collision_shape
+ o.rigid_body.use_margin = obj.rigid_body.use_margin
+ o.rigid_body.collision_margin = obj.rigid_body.collision_margin
+ o.rigid_body.friction = obj.rigid_body.friction
+ o.rigid_body.restitution = obj.rigid_body.restitution
+ o.rigid_body.use_deactivation = obj.rigid_body.use_deactivation
+ o.rigid_body.start_deactivated = obj.rigid_body.start_deactivated
+ o.rigid_body.deactivate_linear_velocity = obj.rigid_body.deactivate_linear_velocity
+ o.rigid_body.deactivate_angular_velocity = obj.rigid_body.deactivate_angular_velocity
+ o.rigid_body.linear_damping = obj.rigid_body.linear_damping
+ o.rigid_body.angular_damping = obj.rigid_body.angular_damping
+ o.rigid_body.collision_groups = obj.rigid_body.collision_groups
+
+ return {'FINISHED'}
+
+
+class BakeToKeyframes(Operator):
+ '''Bake rigid body transformations of selected objects to keyframes'''
+ bl_idname = "rigidbody.bake_to_keyframes"
+ bl_label = "Bake To Keyframes"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ frame_start = IntProperty(
+ name="Start Frame",
+ description="Start frame for baking",
+ min=0, max=300000,
+ default=1,
+ )
+ frame_end = IntProperty(
+ name="End Frame",
+ description="End frame for baking",
+ min=1, max=300000,
+ default=250,
+ )
+ step = IntProperty(
+ name="Frame Step",
+ description="Frame Step",
+ min=1, max=120,
+ default=1,
+ )
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.object
+ return (obj and obj.rigid_body)
+
+ def execute(self, context):
+ bake = []
+ objects = []
+ scene = context.scene
+ frame_orig = scene.frame_current
+ frames_step = range(self.frame_start, self.frame_end + 1, self.step)
+ frames_full = range(self.frame_start, self.frame_end + 1)
+
+ # filter objects selection
+ for obj in context.selected_objects:
+ if not obj.rigid_body or obj.rigid_body.type != 'ACTIVE':
+ obj.select = False
+
+ objects = context.selected_objects
+
+ if objects:
+ # store transformation data
+ # need to start at scene start frame so simulation is run from the beginning
+ for f in frames_full:
+ scene.frame_set(f)
+ if f in frames_step:
+ mat = {}
+ for i, obj in enumerate(objects):
+ mat[i] = obj.matrix_world.copy()
+ bake.append(mat)
+
+ # apply transformations as keyframes
+ for i, f in enumerate(frames_step):
+ scene.frame_set(f)
+ obj_prev = objects[0]
+ for j, obj in enumerate(objects):
+ mat = bake[i][j]
+
+ obj.location = mat.to_translation()
+
+ rot_mode = obj.rotation_mode
+ if rot_mode == 'QUATERNION':
+ obj.rotation_quaternion = mat.to_quaternion()
+ elif rot_mode == 'AXIS_ANGLE':
+ # this is a little roundabout but there's no better way right now
+ aa = mat.to_quaternion().to_axis_angle()
+ obj.rotation_axis_angle = (aa[1], ) + aa[0][:]
+ else: # euler
+ # make sure euler rotation is compatible to previous frame
+ obj.rotation_euler = mat.to_euler(rot_mode, obj_prev.rotation_euler)
+
+ obj_prev = obj
+
+ bpy.ops.anim.keyframe_insert(type='BUILTIN_KSI_LocRot', confirm_success=False)
+
+ # remove baked objects from simulation
+ bpy.ops.rigidbody.objects_remove()
+
+ # clean up keyframes
+ for obj in objects:
+ action = obj.animation_data.action
+ for fcu in action.fcurves:
+ keyframe_points = fcu.keyframe_points
+ i = 1
+ # remove unneeded keyframes
+ while i < len(keyframe_points) - 1:
+ 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])
+ else:
+ i += 1
+ # use linear interpolation for better visual results
+ for keyframe in keyframe_points:
+ keyframe.interpolation = 'LINEAR'
+
+ # return to the frame we started on
+ scene.frame_set(frame_orig)
+
+ return {'FINISHED'}
+
+ def invoke(self, context, event):
+ scene = context.scene
+ self.frame_start = scene.frame_start
+ self.frame_end = scene.frame_end
+
+ wm = context.window_manager
+ return wm.invoke_props_dialog(self)
+
+
+class ConnectRigidBodies(Operator):
+ '''Create rigid body constraints between selected rigid bodies'''
+ bl_idname = "rigidbody.connect"
+ bl_label = "Connect Rigid Bodies"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ con_type = EnumProperty(
+ name="Type",
+ description="Type of generated constraint",
+ # XXX Would be nice to get icons too, but currently not possible ;)
+ items=tuple((e.identifier, e.name, e.description, e. value)
+ for e in bpy.types.RigidBodyConstraint.bl_rna.properties["type"].enum_items),
+ default='FIXED',)
+
+ pivot_type = EnumProperty(
+ name="Location",
+ description="Constraint pivot location",
+ items=(('CENTER', "Center", "Pivot location is between the constrained rigid bodies"),
+ ('ACTIVE', "Active", "Pivot location is at the active object position"),
+ ('SELECTED', "Selected", "Pivot location is at the selected object position")),
+ default='CENTER',)
+
+ connection_pattern = EnumProperty(
+ name="Connection Pattern",
+ description="Pattern used to connect objects",
+ items=(('SELECTED_TO_ACTIVE', "Selected to Active", "Connect selected objects to the active object"),
+ ('CHAIN_DISTANCE', "Chain by Distance", "Connect objects as a chain based on distance, starting at the active object")),
+ default='SELECTED_TO_ACTIVE',)
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.object
+ return (obj and obj.rigid_body)
+
+ def _add_constraint(self, context, object1, object2):
+ if object1 == object2:
+ return
+
+ if self.pivot_type == 'ACTIVE':
+ loc = object1.location
+ elif self.pivot_type == 'SELECTED':
+ loc = object2.location
+ else:
+ loc = (object1.location + object2.location) / 2.0
+
+ ob = bpy.data.objects.new("Constraint", object_data=None)
+ ob.location = loc
+ context.scene.objects.link(ob)
+ context.scene.objects.active = ob
+ ob.select = True
+
+ bpy.ops.rigidbody.constraint_add()
+ con_obj = context.active_object
+ con_obj.empty_draw_type = 'ARROWS'
+ con = con_obj.rigid_body_constraint
+ con.type = self.con_type
+
+ con.object1 = object1
+ con.object2 = object2
+
+ def execute(self, context):
+ scene = context.scene
+ objects = context.selected_objects
+ obj_act = context.active_object
+ change = False
+
+ if self.connection_pattern == 'CHAIN_DISTANCE':
+ objs_sorted = [obj_act]
+ objects_tmp = context.selected_objects
+ if obj_act.select:
+ objects_tmp.remove(obj_act)
+ objects_tmp.sort(key=lambda o: (obj_act.location - o.location).length)
+ last_obj = obj_act
+
+ while (len(objects_tmp)):
+ objects_tmp.sort(key=lambda o: (last_obj.location - o.location).length)
+ objs_sorted.append(objects_tmp[0])
+ last_obj = objects_tmp[0]
+ objects_tmp.remove(objects_tmp[0])
+
+ for i in range(1, len(objs_sorted)):
+ self._add_constraint(context, objs_sorted[i-1], objs_sorted[i])
+ change = True
+
+ else: # SELECTED_TO_ACTIVE
+ for obj in objects:
+ self._add_constraint(context, obj_act, obj)
+ change = True;
+
+ if change:
+ # restore selection
+ bpy.ops.object.select_all(action='DESELECT')
+ for obj in objects:
+ obj.select = True
+ scene.objects.active = obj_act
+ return {'FINISHED'}
+ else:
+ self.report({'WARNING'}, "No other objects selected")
+ return {'CANCELLED'}
diff --git a/release/scripts/startup/bl_operators/uvcalc_follow_active.py b/release/scripts/startup/bl_operators/uvcalc_follow_active.py
index 727c4ad739f..ee3ae2878dc 100644
--- a/release/scripts/startup/bl_operators/uvcalc_follow_active.py
+++ b/release/scripts/startup/bl_operators/uvcalc_follow_active.py
@@ -26,17 +26,18 @@ from bpy.types import Operator
def extend(obj, operator, EXTEND_MODE):
+
import bmesh
me = obj.data
# script will fail without UVs
if not me.uv_textures:
me.uv_textures.new()
-
+
bm = bmesh.from_edit_mesh(me)
-
+
f_act = bm.faces.active
uv_act = bm.loops.layers.uv.active
-
+
if f_act is None:
operator.report({'ERROR'}, "No active face")
return
@@ -46,12 +47,17 @@ def extend(obj, operator, EXTEND_MODE):
faces = [f for f in bm.faces if f.select and len(f.verts) == 4]
- for f in faces:
- f.tag = False
- f_act.tag = True
-
-
# our own local walker
+ def walk_face_init(faces, f_act):
+ # first tag all faces True (so we dont uvmap them)
+ for f in bm.faces:
+ f.tag = True
+ # then tag faces arg False
+ for f in faces:
+ f.tag = False
+ # tag the active face True since we begin there
+ f_act.tag = True
+
def walk_face(f):
# all faces in this list must be tagged
f.tag = True
@@ -73,6 +79,29 @@ def extend(obj, operator, EXTEND_MODE):
faces_a, faces_b = faces_b, faces_a
faces_b.clear()
+ def walk_edgeloop(l):
+ """
+ Could make this a generic function
+ """
+ e_first = l.edge
+ e = None
+ while True:
+ e = l.edge
+ yield e
+
+ # don't step past non-manifold edges
+ if e.is_manifold:
+ # welk around the quad and then onto the next face
+ l = l.link_loop_radial_next
+ if len(l.face.verts) == 4:
+ l = l.link_loop_next.link_loop_next
+ if l.edge is e_first:
+ break
+ else:
+ break
+ else:
+ break
+
def extrapolate_uv(fac,
l_a_outer, l_a_inner,
l_b_outer, l_b_inner):
@@ -82,7 +111,7 @@ def extend(obj, operator, EXTEND_MODE):
def apply_uv(f_prev, l_prev, f_next):
l_a = [None, None, None, None]
l_b = [None, None, None, None]
-
+
l_a[0] = l_prev
l_a[1] = l_a[0].link_loop_next
l_a[2] = l_a[1].link_loop_next
@@ -103,7 +132,7 @@ def extend(obj, operator, EXTEND_MODE):
# +-----------+
# copy from this face to the one above.
- # get the other loops
+ # get the other loops
l_next = l_prev.link_loop_radial_next
if l_next.vert != l_prev.vert:
l_b[1] = l_next
@@ -119,7 +148,9 @@ def extend(obj, operator, EXTEND_MODE):
l_a_uv = [l[uv_act].uv for l in l_a]
l_b_uv = [l[uv_act].uv for l in l_b]
- if EXTEND_MODE == 'LENGTH':
+ if EXTEND_MODE == 'LENGTH_AVERAGE':
+ fac = edge_lengths[l_b[2].edge.index][0] / edge_lengths[l_a[1].edge.index][0]
+ elif EXTEND_MODE == 'LENGTH':
a0, b0, c0 = l_a[3].vert.co, l_a[0].vert.co, l_b[3].vert.co
a1, b1, c1 = l_a[2].vert.co, l_a[1].vert.co, l_b[2].vert.co
@@ -140,6 +171,40 @@ def extend(obj, operator, EXTEND_MODE):
l_a_uv[2], l_a_uv[1],
l_b_uv[2], l_b_uv[1])
+ # -------------------------------------------
+ # Calculate average length per loop if needed
+
+ if EXTEND_MODE == 'LENGTH_AVERAGE':
+ bm.edges.index_update()
+ edge_lengths = [None] * len(bm.edges)
+
+ for f in faces:
+ # we know its a quad
+ l_quad = f.loops[:]
+ l_pair_a = (l_quad[0], l_quad[2])
+ l_pair_b = (l_quad[1], l_quad[3])
+
+ for l_pair in (l_pair_a, l_pair_b):
+ if edge_lengths[l_pair[0].edge.index] is None:
+
+ edge_length_store = [-1.0]
+ edge_length_accum = 0.0
+ edge_length_total = 0
+
+ for l in l_pair:
+ if edge_lengths[l.edge.index] is None:
+ for e in walk_edgeloop(l):
+ if edge_lengths[e.index] is None:
+ edge_lengths[e.index] = edge_length_store
+ edge_length_accum += e.calc_length()
+ edge_length_total += 1
+
+ edge_length_store[0] = edge_length_accum / edge_length_total
+
+ # done with average length
+ # ------------------------
+
+ walk_face_init(faces, f_act)
for f_triple in walk_face(f_act):
apply_uv(*f_triple)
@@ -162,8 +227,10 @@ class FollowActiveQuads(Operator):
name="Edge Length Mode",
description="Method to space UV edge loops",
items=(('EVEN', "Even", "Space all UVs evenly"),
- ('LENGTH', "Length", "Average space UVs edge length of each loop")),
- default='LENGTH',
+ ('LENGTH', "Length", "Average space UVs edge length of each loop"),
+ ('LENGTH_AVERAGE', "Length Average", "Average space UVs edge length of each loop"),
+ ),
+ default='LENGTH_AVERAGE',
)
@classmethod
diff --git a/release/scripts/startup/bl_operators/uvcalc_lightmap.py b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
index 198b3660ff8..b24a71365b4 100644
--- a/release/scripts/startup/bl_operators/uvcalc_lightmap.py
+++ b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
@@ -189,14 +189,14 @@ class prettyface(object):
def lightmap_uvpack(meshes,
- PREF_SEL_ONLY=True,
- PREF_NEW_UVLAYER=False,
- PREF_PACK_IN_ONE=False,
- PREF_APPLY_IMAGE=False,
- PREF_IMG_PX_SIZE=512,
- PREF_BOX_DIV=8,
- PREF_MARGIN_DIV=512
- ):
+ PREF_SEL_ONLY=True,
+ PREF_NEW_UVLAYER=False,
+ PREF_PACK_IN_ONE=False,
+ PREF_APPLY_IMAGE=False,
+ PREF_IMG_PX_SIZE=512,
+ PREF_BOX_DIV=8,
+ PREF_MARGIN_DIV=512
+ ):
"""
BOX_DIV if the maximum division of the UV map that
a box may be consolidated into.
@@ -516,7 +516,7 @@ def lightmap_uvpack(meshes,
def unwrap(operator, context, **kwargs):
- is_editmode = (bpy.context.object.mode == 'EDIT')
+ is_editmode = (context.object.mode == 'EDIT')
if is_editmode:
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
diff --git a/release/scripts/startup/bl_operators/vertexpaint_dirt.py b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
index bfbde2f4b07..e2a820b761a 100644
--- a/release/scripts/startup/bl_operators/vertexpaint_dirt.py
+++ b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
@@ -127,13 +127,14 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean,
col[0] = tone * col[0]
col[1] = tone * col[1]
col[2] = tone * col[2]
-
+ me.update()
return {'FINISHED'}
import bpy
from bpy.types import Operator
from bpy.props import FloatProperty, IntProperty, BoolProperty
+from math import pi
class VertexPaintDirt(Operator):
@@ -156,14 +157,16 @@ class VertexPaintDirt(Operator):
clean_angle = FloatProperty(
name="Highlight Angle",
description="Less than 90 limits the angle used in the tonal range",
- min=0.0, max=180.0,
- default=180.0,
+ min=0.0, max=pi,
+ default=pi,
+ unit="ROTATION",
)
dirt_angle = FloatProperty(
name="Dirt Angle",
description="Less than 90 limits the angle used in the tonal range",
- min=0.0, max=180.0,
+ min=0.0, max=pi,
default=0.0,
+ unit="ROTATION",
)
dirt_only = BoolProperty(
name="Dirt Only",
@@ -171,20 +174,21 @@ class VertexPaintDirt(Operator):
default=False,
)
+ @classmethod
+ def poll(cls, context):
+ obj = context.object
+ return (obj and obj.type == 'MESH')
+
def execute(self, context):
import time
from math import radians
- obj = context.object
-
- if not obj or obj.type != 'MESH':
- self.report({'ERROR'}, "Error, no active mesh object, aborting")
- return {'CANCELLED'}
+ obj = context.object
mesh = obj.data
t = time.time()
- ret = applyVertexDirt(mesh, self.blur_iterations, self.blur_strength, radians(self.dirt_angle), radians(self.clean_angle), self.dirt_only)
+ 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))
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index 105b532ac38..a7085e51bd3 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -29,12 +29,15 @@ from bpy.props import (StringProperty,
from rna_prop_ui import rna_idprop_ui_prop_get, rna_idprop_ui_prop_clear
+from bpy.app.translations import pgettext_tip as tip_
+
class MESH_OT_delete_edgeloop(Operator):
"""Delete an edge loop by merging the faces on each side """ \
"""to a single face loop"""
bl_idname = "mesh.delete_edgeloop"
bl_label = "Delete Edge Loop"
+ bl_options = {'UNDO', 'REGISTER'}
@classmethod
def poll(cls, context):
@@ -44,7 +47,7 @@ class MESH_OT_delete_edgeloop(Operator):
mesh = context.object.data
use_mirror_x = mesh.use_mirror_x
mesh.use_mirror_x = False
- if 'FINISHED' in bpy.ops.transform.edge_slide(value=1.0):
+ if 'FINISHED' in bpy.ops.transform.edge_slide(value=1.0, correct_uv=True):
bpy.ops.mesh.select_more()
bpy.ops.mesh.remove_doubles()
ret = {'FINISHED'}
@@ -500,18 +503,16 @@ class WM_MT_context_menu_enum(Menu):
def draw(self, context):
data_path = self.data_path
- value = context_path_validate(bpy.context, data_path)
+ value = context_path_validate(context, data_path)
if value is Ellipsis:
return {'PASS_THROUGH'}
base_path, prop_string = data_path.rsplit(".", 1)
value_base = context_path_validate(context, base_path)
+ prop = value_base.bl_rna.properties[prop_string]
- values = [(i.name, i.identifier) for i in value_base.bl_rna.properties[prop_string].enum_items]
-
- for name, identifier in values:
- props = self.layout.operator("wm.context_set_enum", text=name)
- props.data_path = data_path
- props.value = identifier
+ layout = self.layout
+ layout.label(prop.name, icon=prop.icon)
+ layout.prop(value_base, prop_string, expand=True)
class WM_OT_context_menu_enum(Operator):
@@ -821,25 +822,42 @@ def _wm_doc_get_id(doc_id, do_url=True, url_prefix=""):
elif len(id_split) == 2: # rna, class.prop
class_name, class_prop = id_split
+ # an operator (common case - just button referencing an op)
if hasattr(bpy.types, class_name.upper() + "_OT_" + class_prop):
if do_url:
url = ("%s/bpy.ops.%s.html#bpy.ops.%s.%s" % (url_prefix, class_name, class_name, class_prop))
else:
rna = "bpy.ops.%s.%s" % (class_name, class_prop)
else:
+ rna_class = getattr(bpy.types, class_name)
+
+ # an operator setting (selected from a running operator), rare case
+ # note: Py defined operators are subclass of Operator,
+ # C defined operators are subclass of OperatorProperties.
+ # we may need to check on this at some point.
+ if issubclass(rna_class, (bpy.types.Operator, bpy.types.OperatorProperties)):
+ # note: ignore the prop name since we don't have a way to link into it
+ class_name, class_prop = class_name.split("_OT_", 1)
+ class_name = class_name.lower()
+ if do_url:
+ url = ("%s/bpy.ops.%s.html#bpy.ops.%s.%s" % (url_prefix, class_name, class_name, class_prop))
+ else:
+ rna = "bpy.ops.%s.%s" % (class_name, class_prop)
+ else:
+ # an RNA setting, common case
- # detect if this is a inherited member and use that name instead
- rna_parent = getattr(bpy.types, class_name).bl_rna
- rna_prop = rna_parent.properties[class_prop]
- rna_parent = rna_parent.base
- while rna_parent and rna_prop == rna_parent.properties.get(class_prop):
- class_name = rna_parent.identifier
+ # detect if this is a inherited member and use that name instead
+ rna_parent = rna_class.bl_rna
+ rna_prop = rna_parent.properties[class_prop]
rna_parent = rna_parent.base
+ while rna_parent and rna_prop == rna_parent.properties.get(class_prop):
+ class_name = rna_parent.identifier
+ rna_parent = rna_parent.base
- if do_url:
- url = ("%s/bpy.types.%s.html#bpy.types.%s.%s" % (url_prefix, class_name, class_name, class_prop))
- else:
- rna = ("bpy.types.%s.%s" % (class_name, class_prop))
+ if do_url:
+ url = ("%s/bpy.types.%s.html#bpy.types.%s.%s" % (url_prefix, class_name, class_name, class_prop))
+ else:
+ rna = ("bpy.types.%s.%s" % (class_name, class_prop))
return url if do_url else rna
@@ -1255,13 +1273,6 @@ class WM_OT_copy_prev_settings(Operator):
else:
shutil.copytree(path_src, path_dst, symlinks=True)
- # in 2.57 and earlier windows installers, system scripts were copied
- # into the configuration directory, don't want to copy those
- system_script = os.path.join(path_dst, "scripts/modules/bpy_types.py")
- if os.path.isfile(system_script):
- shutil.rmtree(os.path.join(path_dst, "scripts"))
- shutil.rmtree(os.path.join(path_dst, "plugins"))
-
# don't loose users work if they open the splash later.
if bpy.data.is_saved is bpy.data.is_dirty is False:
bpy.ops.wm.read_homefile()
@@ -1596,7 +1607,7 @@ class WM_OT_addon_enable(Operator):
"version %d.%d.%d and might not "
"function (correctly), "
"though it is enabled") %
- info_ver)
+ info_ver)
return {'FINISHED'}
else:
return {'CANCELLED'}
@@ -1620,7 +1631,7 @@ class WM_OT_addon_disable(Operator):
class WM_OT_theme_install(Operator):
- "Install a theme"
+ "Load and apply a Blender XML theme file"
bl_idname = "wm.theme_install"
bl_label = "Install Theme..."
@@ -1739,7 +1750,7 @@ class WM_OT_addon_install(Operator):
# don't use bpy.utils.script_paths("addons") because we may not be able to write to it.
path_addons = bpy.utils.user_resource('SCRIPTS', "addons", create=True)
else:
- path_addons = bpy.context.user_preferences.filepaths.script_directory
+ path_addons = context.user_preferences.filepaths.script_directory
if path_addons:
path_addons = os.path.join(path_addons, "addons")
@@ -1748,8 +1759,7 @@ class WM_OT_addon_install(Operator):
return {'CANCELLED'}
# create dir is if missing.
- if not os.path.exists(path_addons):
- os.makedirs(path_addons)
+ os.makedirs(path_addons, exist_ok=True)
# Check if we are installing from a target path,
# doing so causes 2+ addons of same name or when the same from/to
@@ -1830,7 +1840,7 @@ class WM_OT_addon_install(Operator):
bpy.utils.refresh_script_paths()
# print message
- msg = "Modules Installed from %r into %r (%s)" % (pyfile, path_addons, ", ".join(sorted(addons_new)))
+ msg = tip_("Modules Installed from %r into %r (%s)") % (pyfile, path_addons, ", ".join(sorted(addons_new)))
print(msg)
self.report({'INFO'}, msg)
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index e4be84d5396..868fa2a311c 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -24,8 +24,9 @@ if "bpy" in locals():
from imp import reload as _reload
for val in _modules_loaded.values():
_reload(val)
-_modules = (
+_modules = [
"properties_animviz",
+ "properties_constraint",
"properties_data_armature",
"properties_data_bone",
"properties_data_camera",
@@ -40,7 +41,6 @@ _modules = (
"properties_game",
"properties_mask_common",
"properties_material",
- "properties_object_constraint",
"properties_object",
"properties_particle",
"properties_physics_cloth",
@@ -48,9 +48,12 @@ _modules = (
"properties_physics_dynamicpaint",
"properties_physics_field",
"properties_physics_fluid",
+ "properties_physics_rigidbody",
+ "properties_physics_rigidbody_constraint",
"properties_physics_smoke",
"properties_physics_softbody",
"properties_render",
+ "properties_render_layer",
"properties_scene",
"properties_texture",
"properties_world",
@@ -72,16 +75,18 @@ _modules = (
"space_userpref",
"space_view3d",
"space_view3d_toolbar",
-)
+]
+
+import bpy
+
+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}
+_modules_loaded = {name: _namespace[name] for name in _modules if name != 'bpy'}
del _namespace
-import bpy
-
-
def register():
bpy.utils.register_module(__name__)
@@ -132,3 +137,11 @@ def register():
def unregister():
bpy.utils.unregister_module(__name__)
+
+
+# Define a default UIList, when a list does not need any custom drawing...
+# Keep in sync with its #defined name in UI_interface.h
+class UI_UL_list(bpy.types.UIList):
+ pass
+
+bpy.utils.register_class(UI_UL_list)
diff --git a/release/scripts/startup/bl_ui/properties_object_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py
index eb0929895f8..07390525132 100644
--- a/release/scripts/startup/bl_ui/properties_object_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_constraint.py
@@ -172,7 +172,6 @@ class ConstraintButtonsPanel():
sub.active = con.use_rotation
sub.prop(con, "orient_weight", text="Rotation", slider=True)
-
def IK_COPY_POSE(self, context, layout, con):
self.target_template(layout, con)
self.ik_template(layout, con)
@@ -837,7 +836,7 @@ class ConstraintButtonsPanel():
layout.operator("clip.constraint_to_fcurve")
def SCRIPT(self, context, layout, con):
- layout.label("Blender 2.6 doesn't support python constraints yet.")
+ layout.label("Blender 2.6 doesn't support python constraints yet")
class OBJECT_PT_constraints(ConstraintButtonsPanel, Panel):
@@ -852,16 +851,16 @@ class OBJECT_PT_constraints(ConstraintButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
- ob = context.object
+ obj = context.object
- if ob.mode == 'POSE':
+ if obj.type == 'ARMATURE' and obj.mode in {'EDIT', 'POSE'}:
box = layout.box()
box.alert = True
box.label(icon='INFO', text="See Bone Constraints tab to Add Constraints to active bone")
else:
- layout.operator_menu_enum("object.constraint_add", "type")
+ layout.operator_menu_enum("object.constraint_add", "type", text="Add Object Constraint")
- for con in ob.constraints:
+ for con in obj.constraints:
self.draw_constraint(context, con)
@@ -877,7 +876,7 @@ class BONE_PT_constraints(ConstraintButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
- layout.operator_menu_enum("pose.constraint_add", "type")
+ layout.operator_menu_enum("pose.constraint_add", "type", text="Add Bone Constraint")
for con in context.pose_bone.constraints:
self.draw_constraint(context, con)
diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py
index 845beb0f862..74f33170384 100644
--- a/release/scripts/startup/bl_ui/properties_data_armature.py
+++ b/release/scripts/startup/bl_ui/properties_data_armature.py
@@ -124,7 +124,7 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
rows = 2
if group:
rows = 5
- row.template_list(pose, "bone_groups", pose.bone_groups, "active_index", rows=rows)
+ row.template_list("UI_UL_list", "bone_groups", pose, "bone_groups", pose.bone_groups, "active_index", rows=rows)
col = row.column(align=True)
col.active = (ob.proxy is None)
@@ -184,7 +184,8 @@ class DATA_PT_pose_library(ArmatureButtonsPanel, Panel):
if poselib:
# list of poses in pose library
row = layout.row()
- row.template_list(poselib, "pose_markers", poselib.pose_markers, "active_index", rows=5)
+ row.template_list("UI_UL_list", "pose_markers", poselib, "pose_markers",
+ poselib.pose_markers, "active_index", rows=5)
# column of operators for active pose
# - goes beside list
diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py
index fdaee6b7cde..a8954a1c33e 100644
--- a/release/scripts/startup/bl_ui/properties_data_bone.py
+++ b/release/scripts/startup/bl_ui/properties_data_bone.py
@@ -170,6 +170,8 @@ class BONE_PT_relations(BoneButtonsPanel, Panel):
if ob and pchan:
col.label(text="Bone Group:")
col.prop_search(pchan, "bone_group", ob.pose, "bone_groups", text="")
+ col.label(text="Object Children:")
+ col.prop(bone, "use_relative_parent")
col = split.column()
col.label(text="Parent:")
@@ -181,11 +183,11 @@ class BONE_PT_relations(BoneButtonsPanel, Panel):
sub = col.column()
sub.active = (bone.parent is not None)
sub.prop(bone, "use_connect")
- sub.prop(bone, "use_inherit_rotation", text="Inherit Rotation")
- sub.prop(bone, "use_inherit_scale", text="Inherit Scale")
+ sub.prop(bone, "use_inherit_rotation")
+ sub.prop(bone, "use_inherit_scale")
sub = col.column()
sub.active = (not bone.parent or not bone.use_connect)
- sub.prop(bone, "use_local_location", text="Local Location")
+ sub.prop(bone, "use_local_location")
class BONE_PT_display(BoneButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py
index 25cecc90c70..c74560e14ac 100644
--- a/release/scripts/startup/bl_ui/properties_data_camera.py
+++ b/release/scripts/startup/bl_ui/properties_data_camera.py
@@ -80,7 +80,7 @@ class DATA_PT_lens(CameraButtonsPanel, Panel):
row = col.row()
if cam.lens_unit == 'MILLIMETERS':
row.prop(cam, "lens")
- elif cam.lens_unit == 'DEGREES':
+ elif cam.lens_unit == 'FOV':
row.prop(cam, "angle")
row.prop(cam, "lens_unit", text="")
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 6125540d491..86a48999663 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -18,7 +18,7 @@
# <pep8 compliant>
import bpy
-from bpy.types import Menu, Panel
+from bpy.types import Menu, Panel, UIList
from rna_prop_ui import PropertyPanel
@@ -34,10 +34,11 @@ class MESH_MT_vertex_group_specials(Menu):
layout.operator("object.vertex_group_copy_to_linked", icon='LINK_AREA')
layout.operator("object.vertex_group_copy_to_selected", icon='LINK_AREA')
layout.operator("object.vertex_group_mirror", icon='ARROW_LEFTRIGHT')
- layout.operator("object.vertex_group_remove", icon='X', text="Delete All").all = True
+ layout.operator("object.vertex_group_remove", icon='X', text="Delete All Vertex Groups").all = True
+ layout.operator("object.vertex_group_remove_from", icon='X', text="Remove Selected from All Vertex Groups").all = True
layout.separator()
- layout.operator("object.vertex_group_lock", icon='LOCKED', text="Lock All").action = 'SELECT'
- layout.operator("object.vertex_group_lock", icon='UNLOCKED', text="UnLock All").action = 'DESELECT'
+ layout.operator("object.vertex_group_lock", icon='LOCKED', text="Lock All").action = 'LOCK'
+ layout.operator("object.vertex_group_lock", icon='UNLOCKED', text="UnLock All").action = 'UNLOCK'
layout.operator("object.vertex_group_lock", icon='LOCKED', text="Lock Invert All").action = 'INVERT'
@@ -54,6 +55,53 @@ class MESH_MT_shape_key_specials(Menu):
layout.operator("object.shape_key_add", icon='ZOOMIN', text="New Shape From Mix").from_mix = True
+class MESH_UL_vgroups(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ # assert(isinstance(item, bpy.types.VertexGroup)
+ vgroup = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.label(text=vgroup.name, translate=False, icon_value=icon)
+ icon = 'LOCKED' if vgroup.lock_weight else 'UNLOCKED'
+ layout.prop(vgroup, "lock_weight", text="", icon=icon, emboss=False)
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
+class MESH_UL_shape_keys(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ # assert(isinstance(item, bpy.types.ShapeKey)
+ obj = active_data
+ key = data
+ key_block = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ split = layout.split(0.66, False)
+ split.label(text=item.name, translate=False, icon_value=icon)
+ row = split.row(True)
+ if key_block.mute or (obj.mode == 'EDIT' and not (obj.use_shape_key_edit_mode and obj.type == 'MESH')):
+ row.active = False
+ if not item.relative_key or index > 0:
+ row.prop(key_block, "value", text="", emboss=False)
+ else:
+ row.label(text="")
+ row.prop(key_block, "mute", text="", emboss=False)
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
+class MESH_UL_uvmaps_vcols(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ # assert(isinstance(item, (bpy.types.MeshTexturePolyLayer, bpy.types.MeshLoopColorLayer))
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.label(text=item.name, translate=False, icon_value=icon)
+ 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'}:
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
class MeshButtonsPanel():
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
@@ -144,7 +192,7 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
rows = 5
row = layout.row()
- row.template_list(ob, "vertex_groups", ob.vertex_groups, "active_index", rows=rows)
+ row.template_list("MESH_UL_vgroups", "", ob, "vertex_groups", ob.vertex_groups, "active_index", rows=rows)
col = row.column(align=True)
col.operator("object.vertex_group_add", icon='ZOOMIN', text="")
@@ -202,7 +250,7 @@ class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
rows = 2
if kb:
rows = 5
- row.template_list(key, "key_blocks", ob, "active_shape_key_index", rows=rows)
+ row.template_list("MESH_UL_shape_keys", "", key, "key_blocks", ob, "active_shape_key_index", rows=rows)
col = row.column()
@@ -282,7 +330,7 @@ class DATA_PT_uv_texture(MeshButtonsPanel, Panel):
row = layout.row()
col = row.column()
- col.template_list(me, "uv_textures", me.uv_textures, "active_index", rows=2)
+ col.template_list("MESH_UL_uvmaps_vcols", "uvmaps", me, "uv_textures", me.uv_textures, "active_index", rows=2)
col = row.column(align=True)
col.operator("mesh.uv_texture_add", icon='ZOOMIN', text="")
@@ -305,7 +353,7 @@ class DATA_PT_vertex_colors(MeshButtonsPanel, Panel):
row = layout.row()
col = row.column()
- col.template_list(me, "vertex_colors", me.vertex_colors, "active_index", rows=2)
+ col.template_list("MESH_UL_uvmaps_vcols", "vcols", me, "vertex_colors", me.vertex_colors, "active_index", rows=2)
col = row.column(align=True)
col.operator("mesh.vertex_color_add", icon='ZOOMIN', text="")
@@ -324,17 +372,20 @@ class DATA_PT_customdata(MeshButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
- # me = context.mesh
+ obj = context.object
+ me = context.mesh
col = layout.column()
- # sticky has no UI access since 2.49 - we may remove
- '''
- row = col.row(align=True)
- row.operator("mesh.customdata_create_sticky")
- row.operator("mesh.customdata_clear_sticky", icon='X')
- '''
+
col.operator("mesh.customdata_clear_mask", icon='X')
col.operator("mesh.customdata_clear_skin", icon='X')
+ col = layout.column()
+
+ col.enabled = (obj.mode != 'EDIT')
+ col.prop(me, "use_customdata_vertex_bevel")
+ col.prop(me, "use_customdata_edge_bevel")
+ col.prop(me, "use_customdata_edge_crease")
+
class DATA_PT_custom_props_mesh(MeshButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 62461d800f6..71178e6afac 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -19,6 +19,7 @@
# <pep8 compliant>
import bpy
from bpy.types import Panel
+from bpy.app.translations import pgettext_iface as iface_
class ModifierButtonsPanel():
@@ -123,20 +124,17 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
split.prop(md, "width")
split.prop(md, "use_only_vertices")
- # -- new modifier only, this may be reverted in favor of 2.62 mod.
- '''
- split = layout.split()
- split.prop(md, "use_even_offset")
- split.prop(md, "use_distance_offset")
- '''
- # -- end
+ layout.prop(md, "segments")
layout.label(text="Limit Method:")
layout.row().prop(md, "limit_method", expand=True)
if md.limit_method == 'ANGLE':
layout.prop(md, "angle_limit")
- elif md.limit_method == 'WEIGHT':
- layout.row().prop(md, "edge_weight_method", expand=True)
+ elif md.limit_method == 'VGROUP':
+ layout.label(text="Vertex Group:")
+ layout.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ # elif md.limit_method == 'WEIGHT':
+ # layout.row().prop(md, "edge_weight_method", expand=True)
def BOOLEAN(self, layout, ob, md):
split = layout.split()
@@ -162,6 +160,44 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
sub.active = md.use_random_order
sub.prop(md, "seed")
+ def MESH_CACHE(self, layout, ob, md):
+ layout.prop(md, "cache_format")
+ layout.prop(md, "filepath")
+
+ layout.label(text="Evaluation:")
+ layout.prop(md, "factor", slider=True)
+ layout.prop(md, "deform_mode")
+ layout.prop(md, "interpolation")
+
+ layout.label(text="Time Mapping:")
+
+ row = layout.row()
+ row.prop(md, "time_mode", expand=True)
+ row = layout.row()
+ row.prop(md, "play_mode", expand=True)
+ if md.play_mode == 'SCENE':
+ layout.prop(md, "frame_start")
+ layout.prop(md, "frame_scale")
+ else:
+ time_mode = md.time_mode
+ if time_mode == 'FRAME':
+ layout.prop(md, "eval_frame")
+ elif time_mode == 'TIME':
+ layout.prop(md, "eval_time")
+ elif time_mode == 'FACTOR':
+ layout.prop(md, "eval_factor")
+
+ layout.label(text="Axis Mapping:")
+ split = layout.split(percentage=0.5, align=True)
+ split.alert = (md.forward_axis[-1] == md.up_axis[-1])
+ split.label("Forward/Up Axis:")
+ split.prop(md, "forward_axis", text="")
+ split.prop(md, "up_axis", text="")
+ split = layout.split(percentage=0.5)
+ split.label(text="Flip Axis:")
+ row = split.row()
+ row.prop(md, "flip_axis")
+
def CAST(self, layout, ob, md):
split = layout.split(percentage=0.25)
@@ -227,7 +263,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
layout.prop(md, "angle_limit")
layout.prop(md, "use_dissolve_boundaries")
- layout.label(text="Face Count" + ": %d" % md.face_count)
+ layout.label(text=iface_("Face Count: %d") % md.face_count, translate=False)
def DISPLACE(self, layout, ob, md):
has_texture = (md.texture is not None)
@@ -333,23 +369,24 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
def LAPLACIANSMOOTH(self, layout, ob, md):
layout.prop(md, "iterations")
-
+
split = layout.split(percentage=0.25)
-
+
col = split.column()
col.label(text="Axis:")
col.prop(md, "use_x")
col.prop(md, "use_y")
col.prop(md, "use_z")
-
+
col = split.column()
col.label(text="Lambda:")
col.prop(md, "lambda_factor", text="Factor")
col.prop(md, "lambda_border", text="Border")
-
+
col.separator()
col.prop(md, "use_volume_preserve")
-
+ col.prop(md, "use_normalized")
+
layout.label(text="Vertex Group:")
layout.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
@@ -472,7 +509,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
row.label()
def OCEAN(self, layout, ob, md):
- if not md.is_build_enabled:
+ if not bpy.app.build_options.mod_oceansim:
layout.label("Built without OceanSim modifier")
return
@@ -489,11 +526,13 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col = split.column()
col.prop(md, "time")
- col.prop(md, "resolution")
+ col.prop(md, "depth")
+ col.prop(md, "random_seed")
col = split.column()
+ col.prop(md, "resolution")
+ col.prop(md, "size")
col.prop(md, "spatial_size")
- col.prop(md, "depth")
layout.label("Waves:")
@@ -534,7 +573,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
if md.is_cached:
layout.operator("object.ocean_bake", text="Free Bake").free = True
else:
- layout.operator("object.ocean_bake")
+ layout.operator("object.ocean_bake").free = False
split = layout.split()
split.enabled = not md.is_cached
@@ -547,7 +586,14 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.label(text="Cache path:")
col.prop(md, "filepath", text="")
- #col.prop(md, "bake_foam_fade")
+ split = layout.split()
+ split.enabled = not md.is_cached
+
+ col = split.column()
+ col.active = md.use_foam
+ col.prop(md, "bake_foam_fade")
+
+ col = split.column()
def PARTICLE_INSTANCE(self, layout, ob, md):
layout.prop(md, "object")
@@ -669,7 +715,10 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col = split.column()
col.label(text="Deform:")
- col.prop(md, "factor")
+ if md.deform_method in {'TAPER', 'STRETCH'}:
+ col.prop(md, "factor")
+ else:
+ col.prop(md, "angle")
col.prop(md, "limits", slider=True)
if md.deform_method in {'TAPER', 'STRETCH', 'TWIST'}:
col.prop(md, "lock_x")
@@ -701,6 +750,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col = split.column()
col.prop(md, "thickness")
+ col.prop(md, "thickness_clamp")
col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
col.label(text="Crease:")
@@ -712,6 +762,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col = split.column()
col.prop(md, "offset")
+ col.prop(md, "use_flip_normals")
sub = col.column()
sub.active = bool(md.vertex_group)
sub.prop(md, "invert_vertex_group", text="Invert")
@@ -727,7 +778,6 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
row = row.row()
row.active = md.use_rim
row.prop(md, "material_offset_rim", text="Rim")
- sub.prop(md, "use_flip_normals")
def SUBSURF(self, layout, ob, md):
layout.row().prop(md, "subdivision_type", expand=True)
@@ -1032,5 +1082,47 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
def TRIANGULATE(self, layout, ob, md):
layout.prop(md, "use_beauty")
+ def UV_WARP(self, layout, ob, md):
+ split = layout.split()
+ col = split.column()
+ col.prop(md, "center")
+
+ col = split.column()
+ col.label(text="UV Axis:")
+ col.prop(md, "axis_u", text="")
+ col.prop(md, "axis_v", text="")
+
+ split = layout.split()
+ col = split.column()
+ col.label(text="From:")
+ col.prop(md, "object_from", text="")
+
+ col = split.column()
+ col.label(text="To:")
+ col.prop(md, "object_to", text="")
+
+ split = layout.split()
+ col = split.column()
+ obj = md.object_from
+ if obj and obj.type == 'ARMATURE':
+ col.label(text="Bone:")
+ col.prop_search(md, "bone_from", obj.data, "bones", text="")
+
+ col = split.column()
+ obj = md.object_to
+ if obj and obj.type == 'ARMATURE':
+ col.label(text="Bone:")
+ col.prop_search(md, "bone_to", obj.data, "bones", text="")
+
+ split = layout.split()
+
+ col = split.column()
+ col.label(text="Vertex Group:")
+ col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+
+ col = split.column()
+ col.label(text="UV Map:")
+ col.prop_search(md, "uv_layer", ob.data, "uv_textures", text="")
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/properties_freestyle.py b/release/scripts/startup/bl_ui/properties_freestyle.py
new file mode 100644
index 00000000000..0665c0aba4a
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_freestyle.py
@@ -0,0 +1,668 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public 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 Menu, Panel, UIList
+from bl_ui.properties_render import RenderButtonsPanel
+from bl_ui.properties_render_layer import RenderLayerButtonsPanel
+
+
+# Render properties
+
+class RenderFreestyleButtonsPanel(RenderButtonsPanel):
+ # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
+
+ @classmethod
+ def poll(cls, context):
+ if not super().poll(context):
+ return False
+ return bpy.app.build_options.freestyle
+
+
+class RENDER_PT_freestyle(RenderFreestyleButtonsPanel, Panel):
+ bl_label = "Freestyle"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ def draw_header(self, context):
+ rd = context.scene.render
+ self.layout.prop(rd, "use_freestyle", text="")
+
+ def draw(self, context):
+ rd = context.scene.render
+
+ layout = self.layout
+ layout.active = rd.use_freestyle
+
+ row = layout.row()
+ row.label(text="Line Thickness:")
+ row.prop(rd, "line_thickness_mode", expand=True)
+ row = layout.row()
+ row.active = (rd.line_thickness_mode == 'ABSOLUTE')
+ row.prop(rd, "unit_line_thickness")
+
+
+# Render layer properties
+
+class RenderLayerFreestyleButtonsPanel(RenderLayerButtonsPanel):
+ # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
+
+ @classmethod
+ def poll(cls, context):
+ if not super().poll(context):
+ return False
+ rd = context.scene.render
+ return bpy.app.build_options.freestyle and rd.use_freestyle and rd.layers.active
+
+
+class RenderLayerFreestyleEditorButtonsPanel(RenderLayerFreestyleButtonsPanel):
+ # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
+
+ @classmethod
+ def poll(cls, context):
+ if not super().poll(context):
+ return False
+ rl = context.scene.render.layers.active
+ return rl and rl.freestyle_settings.mode == 'EDITOR'
+
+
+class RENDERLAYER_UL_linesets(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ lineset = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.label(lineset.name, icon_value=icon)
+ layout.prop(lineset, "show_render", text="", index=index)
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label("", icon_value=icon)
+
+##ifdef WITH_FREESTYLE
+# else if (RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer) ||
+# RNA_struct_is_a(itemptr->type, &RNA_FreestyleLineSet)) {
+##else
+# else if (RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer)) {
+##endif
+# uiItemL(sub, name, icon);
+# uiBlockSetEmboss(block, UI_EMBOSS);
+# uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "use", 0, 0, 0, 0, 0, NULL);
+# }
+
+
+class RENDER_MT_lineset_specials(Menu):
+ bl_label = "Lineset Specials"
+
+ def draw(self, context):
+ layout = self.layout
+ layout.operator("scene.freestyle_lineset_copy", icon='COPYDOWN')
+ layout.operator("scene.freestyle_lineset_paste", icon='PASTEDOWN')
+
+
+class RENDERLAYER_PT_freestyle(RenderLayerFreestyleButtonsPanel, Panel):
+ bl_label = "Freestyle"
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ def draw(self, context):
+ rd = context.scene.render
+ rl = rd.layers.active
+ freestyle = rl.freestyle_settings
+
+ layout = self.layout
+ layout.active = rl.use_freestyle
+ layout.prop(freestyle, "mode", text="Control mode")
+
+ col = layout.column()
+ col.label(text="Edge Detection Options:")
+ split = col.split()
+ sub = split.column()
+ sub.prop(freestyle, "crease_angle")
+ sub.prop(freestyle, "use_culling")
+ sub = split.column()
+ sub.prop(freestyle, "use_smoothness")
+ sub.prop(freestyle, "use_material_boundaries")
+ col.prop(freestyle, "use_advanced_options")
+ # Advanced options are hidden by default to warn new users
+ if freestyle.use_advanced_options:
+ split = col.split()
+ sub = split.column()
+ sub.active = freestyle.use_advanced_options
+ if freestyle.mode == 'SCRIPT':
+ sub.prop(freestyle, "use_ridges_and_valleys")
+ sub.prop(freestyle, "sphere_radius")
+ sub = split.column()
+ sub.active = freestyle.use_advanced_options
+ if freestyle.mode == 'SCRIPT':
+ sub.prop(freestyle, "use_suggestive_contours")
+ sub.prop(freestyle, "kr_derivative_epsilon")
+
+ if freestyle.mode == 'SCRIPT':
+ split = layout.split()
+ split.label("Style modules:")
+ split.operator("scene.freestyle_module_add", text="Add")
+ for i, module in enumerate(freestyle.modules):
+ box = layout.box()
+ box.context_pointer_set("freestyle_module", module)
+ row = box.row(align=True)
+ row.prop(module, "use", text="")
+ row.prop(module, "module_path", text="")
+ row.operator("scene.freestyle_module_remove", icon='X', text="")
+ row.operator("scene.freestyle_module_move", icon='TRIA_UP', text="").direction = 'UP'
+ row.operator("scene.freestyle_module_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
+
+
+class RENDERLAYER_PT_freestyle_lineset(RenderLayerFreestyleEditorButtonsPanel, Panel):
+ bl_label = "Freestyle Line Set"
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ def draw_edge_type_buttons(self, box, lineset, edge_type):
+ # property names
+ select_edge_type = "select_" + edge_type
+ exclude_edge_type = "exclude_" + edge_type
+ # draw edge type buttons
+ row = box.row(align=True)
+ row.prop(lineset, select_edge_type)
+ sub = row.column()
+ sub.prop(lineset, exclude_edge_type, text="")
+ sub.active = getattr(lineset, select_edge_type)
+
+ def draw(self, context):
+ rd = context.scene.render
+ rl = rd.layers.active
+ freestyle = rl.freestyle_settings
+ lineset = freestyle.linesets.active
+
+ layout = self.layout
+ layout.active = rl.use_freestyle
+
+ col = layout.column()
+ row = col.row()
+ rows = 5 if lineset else 2
+ row.template_list("RENDERLAYER_UL_linesets", "", freestyle, "linesets", freestyle.linesets, "active_index", rows=rows)
+
+ sub = row.column()
+ subsub = sub.column(align=True)
+ subsub.operator("scene.freestyle_lineset_add", icon='ZOOMIN', text="")
+ subsub.operator("scene.freestyle_lineset_remove", icon='ZOOMOUT', text="")
+ subsub.menu("RENDER_MT_lineset_specials", icon='DOWNARROW_HLT', text="")
+ if lineset:
+ sub.separator()
+ subsub = sub.column(align=True)
+ subsub.operator("scene.freestyle_lineset_move", icon='TRIA_UP', text="").direction = 'UP'
+ subsub.operator("scene.freestyle_lineset_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
+
+ col.prop(lineset, "name")
+
+ col = layout.column()
+ col.label(text="Selection By:")
+ row = col.row(align=True)
+ row.prop(lineset, "select_by_visibility", text="Visibility", toggle=True)
+ row.prop(lineset, "select_by_edge_types", text="Edge Types", toggle=True)
+ row.prop(lineset, "select_by_face_marks", text="Face Marks", toggle=True)
+ row.prop(lineset, "select_by_group", text="Group", toggle=True)
+ row.prop(lineset, "select_by_image_border", text="Image Border", toggle=True)
+
+ if lineset.select_by_visibility:
+ col.label(text="Visibility:")
+ row = col.row(align=True)
+ row.prop(lineset, "visibility", expand=True)
+ if lineset.visibility == 'RANGE':
+ row = col.row(align=True)
+ row.prop(lineset, "qi_start")
+ row.prop(lineset, "qi_end")
+
+ if lineset.select_by_edge_types:
+ col.label(text="Edge Types:")
+ row = col.row()
+ row.prop(lineset, "edge_type_negation", expand=True)
+ row.prop(lineset, "edge_type_combination", expand=True)
+
+ split = col.split()
+ sub = split.column()
+ self.draw_edge_type_buttons(sub, lineset, "silhouette")
+ self.draw_edge_type_buttons(sub, lineset, "border")
+ self.draw_edge_type_buttons(sub, lineset, "contour")
+ self.draw_edge_type_buttons(sub, lineset, "suggestive_contour")
+ self.draw_edge_type_buttons(sub, lineset, "ridge_valley")
+ sub = split.column()
+ self.draw_edge_type_buttons(sub, lineset, "crease")
+ self.draw_edge_type_buttons(sub, lineset, "edge_mark")
+ self.draw_edge_type_buttons(sub, lineset, "external_contour")
+ self.draw_edge_type_buttons(sub, lineset, "material_boundary")
+
+ if lineset.select_by_face_marks:
+ col.label(text="Face Marks:")
+ row = col.row()
+ row.prop(lineset, "face_mark_negation", expand=True)
+ row.prop(lineset, "face_mark_condition", expand=True)
+
+ if lineset.select_by_group:
+ col.label(text="Group:")
+ row = col.row()
+ row.prop(lineset, "group", text="")
+ row.prop(lineset, "group_negation", expand=True)
+
+
+class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel, Panel):
+ bl_label = "Freestyle Line Style"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ def draw_modifier_box_header(self, box, modifier):
+ row = box.row()
+ row.context_pointer_set("modifier", modifier)
+ if modifier.expanded:
+ icon = 'TRIA_DOWN'
+ else:
+ icon = 'TRIA_RIGHT'
+ row.prop(modifier, "expanded", text="", icon=icon, emboss=False)
+ # TODO: Use icons rather than text label, would save some room!
+ row.label(text=modifier.rna_type.name)
+ row.prop(modifier, "name", text="")
+ if modifier.use:
+ icon = 'RESTRICT_RENDER_OFF'
+ else:
+ icon = 'RESTRICT_RENDER_ON'
+ row.prop(modifier, "use", text="", icon=icon)
+ sub = row.row(align=True)
+ sub.operator("scene.freestyle_modifier_copy", icon='NONE', text="Copy")
+ sub.operator("scene.freestyle_modifier_move", icon='TRIA_UP', text="").direction = 'UP'
+ sub.operator("scene.freestyle_modifier_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
+ sub.operator("scene.freestyle_modifier_remove", icon='X', text="")
+
+ def draw_modifier_common(self, box, modifier):
+ row = box.row()
+ row.prop(modifier, "blend", text="")
+ row.prop(modifier, "influence")
+
+ def draw_modifier_color_ramp_common(self, box, modifier, has_range):
+ box.template_color_ramp(modifier, "color_ramp", expand=True)
+ if has_range:
+ row = box.row(align=True)
+ row.prop(modifier, "range_min")
+ row.prop(modifier, "range_max")
+
+ def draw_modifier_curve_common(self, box, modifier, has_range, has_value):
+ row = box.row()
+ row.prop(modifier, "mapping", text="")
+ sub = row.column()
+ sub.prop(modifier, "invert")
+ if modifier.mapping == 'CURVE':
+ sub.active = False
+ box.template_curve_mapping(modifier, "curve")
+ if has_range:
+ row = box.row(align=True)
+ row.prop(modifier, "range_min")
+ row.prop(modifier, "range_max")
+ if has_value:
+ row = box.row(align=True)
+ row.prop(modifier, "value_min")
+ row.prop(modifier, "value_max")
+
+ def draw_color_modifier(self, context, modifier):
+ layout = self.layout
+
+ col = layout.column(align=True)
+ self.draw_modifier_box_header(col.box(), modifier)
+ if modifier.expanded:
+ box = col.box()
+ self.draw_modifier_common(box, modifier)
+
+ if modifier.type == 'ALONG_STROKE':
+ self.draw_modifier_color_ramp_common(box, modifier, False)
+
+ elif modifier.type == 'DISTANCE_FROM_OBJECT':
+ box.prop(modifier, "target")
+ self.draw_modifier_color_ramp_common(box, modifier, True)
+ prop = box.operator("scene.freestyle_fill_range_by_selection")
+ prop.type = 'COLOR'
+ prop.name = modifier.name
+
+ elif modifier.type == 'DISTANCE_FROM_CAMERA':
+ self.draw_modifier_color_ramp_common(box, modifier, True)
+ prop = box.operator("scene.freestyle_fill_range_by_selection")
+ prop.type = 'COLOR'
+ prop.name = modifier.name
+
+ elif modifier.type == 'MATERIAL':
+ row = box.row()
+ row.prop(modifier, "material_attr", text="")
+ sub = row.column()
+ sub.prop(modifier, "use_ramp")
+ if modifier.material_attr in {'DIFF', 'SPEC'}:
+ sub.active = True
+ show_ramp = modifier.use_ramp
+ else:
+ sub.active = False
+ show_ramp = True
+ if show_ramp:
+ self.draw_modifier_color_ramp_common(box, modifier, False)
+
+ def draw_alpha_modifier(self, context, modifier):
+ layout = self.layout
+
+ col = layout.column(align=True)
+ self.draw_modifier_box_header(col.box(), modifier)
+ if modifier.expanded:
+ box = col.box()
+ self.draw_modifier_common(box, modifier)
+
+ if modifier.type == 'ALONG_STROKE':
+ self.draw_modifier_curve_common(box, modifier, False, False)
+
+ elif modifier.type == 'DISTANCE_FROM_OBJECT':
+ box.prop(modifier, "target")
+ self.draw_modifier_curve_common(box, modifier, True, False)
+ prop = box.operator("scene.freestyle_fill_range_by_selection")
+ prop.type = 'ALPHA'
+ prop.name = modifier.name
+
+ elif modifier.type == 'DISTANCE_FROM_CAMERA':
+ self.draw_modifier_curve_common(box, modifier, True, False)
+ prop = box.operator("scene.freestyle_fill_range_by_selection")
+ prop.type = 'ALPHA'
+ prop.name = modifier.name
+
+ elif modifier.type == 'MATERIAL':
+ box.prop(modifier, "material_attr", text="")
+ self.draw_modifier_curve_common(box, modifier, False, False)
+
+ def draw_thickness_modifier(self, context, modifier):
+ layout = self.layout
+
+ col = layout.column(align=True)
+ self.draw_modifier_box_header(col.box(), modifier)
+ if modifier.expanded:
+ box = col.box()
+ self.draw_modifier_common(box, modifier)
+
+ if modifier.type == 'ALONG_STROKE':
+ self.draw_modifier_curve_common(box, modifier, False, True)
+
+ elif modifier.type == 'DISTANCE_FROM_OBJECT':
+ box.prop(modifier, "target")
+ self.draw_modifier_curve_common(box, modifier, True, True)
+ prop = box.operator("scene.freestyle_fill_range_by_selection")
+ prop.type = 'THICKNESS'
+ prop.name = modifier.name
+
+ elif modifier.type == 'DISTANCE_FROM_CAMERA':
+ self.draw_modifier_curve_common(box, modifier, True, True)
+ prop = box.operator("scene.freestyle_fill_range_by_selection")
+ prop.type = 'THICKNESS'
+ prop.name = modifier.name
+
+ elif modifier.type == 'MATERIAL':
+ box.prop(modifier, "material_attr", text="")
+ self.draw_modifier_curve_common(box, modifier, False, True)
+
+ elif modifier.type == 'CALLIGRAPHY':
+ box.prop(modifier, "orientation")
+ row = box.row(align=True)
+ row.prop(modifier, "min_thickness")
+ row.prop(modifier, "max_thickness")
+
+ def draw_geometry_modifier(self, context, modifier):
+ layout = self.layout
+
+ col = layout.column(align=True)
+ self.draw_modifier_box_header(col.box(), modifier)
+ if modifier.expanded:
+ box = col.box()
+
+ if modifier.type == 'SAMPLING':
+ box.prop(modifier, "sampling")
+
+ elif modifier.type == 'BEZIER_CURVE':
+ box.prop(modifier, "error")
+
+ elif modifier.type == 'SINUS_DISPLACEMENT':
+ split = box.split()
+ col = split.column()
+ col.prop(modifier, "wavelength")
+ col.prop(modifier, "amplitude")
+ col = split.column()
+ col.prop(modifier, "phase")
+
+ elif modifier.type == 'SPATIAL_NOISE':
+ split = box.split()
+ col = split.column()
+ col.prop(modifier, "amplitude")
+ col.prop(modifier, "scale")
+ col.prop(modifier, "octaves")
+ col = split.column()
+ col.prop(modifier, "smooth")
+ col.prop(modifier, "pure_random")
+
+ elif modifier.type == 'PERLIN_NOISE_1D':
+ split = box.split()
+ col = split.column()
+ col.prop(modifier, "frequency")
+ col.prop(modifier, "amplitude")
+ col.prop(modifier, "seed")
+ col = split.column()
+ col.prop(modifier, "octaves")
+ col.prop(modifier, "angle")
+
+ elif modifier.type == 'PERLIN_NOISE_2D':
+ split = box.split()
+ col = split.column()
+ col.prop(modifier, "frequency")
+ col.prop(modifier, "amplitude")
+ col.prop(modifier, "seed")
+ col = split.column()
+ col.prop(modifier, "octaves")
+ col.prop(modifier, "angle")
+
+ elif modifier.type == 'BACKBONE_STRETCHER':
+ box.prop(modifier, "backbone_length")
+
+ elif modifier.type == 'TIP_REMOVER':
+ box.prop(modifier, "tip_length")
+
+ elif modifier.type == 'POLYGONIZATION':
+ box.prop(modifier, "error")
+
+ elif modifier.type == 'GUIDING_LINES':
+ box.prop(modifier, "offset")
+
+ elif modifier.type == 'BLUEPRINT':
+ row = box.row()
+ row.prop(modifier, "shape", expand=True)
+ box.prop(modifier, "rounds")
+ row = box.row()
+ if modifier.shape in {'CIRCLES', 'ELLIPSES'}:
+ row.prop(modifier, "random_radius")
+ row.prop(modifier, "random_center")
+ elif modifier.shape == 'SQUARES':
+ row.prop(modifier, "backbone_length")
+ row.prop(modifier, "random_backbone")
+
+ elif modifier.type == '2D_OFFSET':
+ row = box.row(align=True)
+ row.prop(modifier, "start")
+ row.prop(modifier, "end")
+ row = box.row(align=True)
+ row.prop(modifier, "x")
+ row.prop(modifier, "y")
+
+ elif modifier.type == '2D_TRANSFORM':
+ box.prop(modifier, "pivot")
+ if modifier.pivot == 'PARAM':
+ box.prop(modifier, "pivot_u")
+ elif modifier.pivot == 'ABSOLUTE':
+ row = box.row(align=True)
+ row.prop(modifier, "pivot_x")
+ row.prop(modifier, "pivot_y")
+ row = box.row(align=True)
+ row.prop(modifier, "scale_x")
+ row.prop(modifier, "scale_y")
+ box.prop(modifier, "angle")
+
+ def draw(self, context):
+ rd = context.scene.render
+ rl = rd.layers.active
+ lineset = rl.freestyle_settings.linesets.active
+
+ layout = self.layout
+ layout.active = rl.use_freestyle
+
+ if lineset is None:
+ return
+ linestyle = lineset.linestyle
+
+ layout.template_ID(lineset, "linestyle", new="scene.freestyle_linestyle_new")
+ row = layout.row(align=True)
+ row.prop(linestyle, "panel", expand=True)
+ if linestyle.panel == 'STROKES':
+ ## Chaining
+ layout.label(text="Chaining:")
+ split = layout.split(align=True)
+ # First column
+ col = split.column()
+ col.prop(linestyle, "use_chaining", text="Enable Chaining")
+ sub = col.row()
+ sub.active = linestyle.use_chaining
+ sub.prop(linestyle, "same_object")
+ # Second column
+ col = split.column()
+ col.active = linestyle.use_chaining
+ col.prop(linestyle, "chaining", text="")
+ if linestyle.chaining == 'SKETCHY':
+ col.prop(linestyle, "rounds")
+
+ ## Splitting
+ layout.label(text="Splitting:")
+ split = layout.split(align=True)
+ # First column
+ col = split.column()
+ row = col.row(align=True)
+ row.prop(linestyle, "use_min_angle", text="")
+ sub = row.row()
+ sub.active = linestyle.use_min_angle
+ sub.prop(linestyle, "min_angle")
+ row = col.row(align=True)
+ row.prop(linestyle, "use_max_angle", text="")
+ sub = row.row()
+ sub.active = linestyle.use_max_angle
+ sub.prop(linestyle, "max_angle")
+ # Second column
+ col = split.column()
+ row = col.row(align=True)
+ row.prop(linestyle, "use_split_length", text="")
+ sub = row.row()
+ sub.active = linestyle.use_split_length
+ sub.prop(linestyle, "split_length", text="2D Length")
+ row = col.row(align=True)
+ row.prop(linestyle, "material_boundary")
+ # End of columns
+ row = layout.row(align=True)
+ row.prop(linestyle, "use_split_pattern", text="")
+ sub = row.row()
+ sub.active = linestyle.use_split_pattern
+ sub.prop(linestyle, "split_dash1", text="D1")
+ sub.prop(linestyle, "split_gap1", text="G1")
+ sub.prop(linestyle, "split_dash2", text="D2")
+ sub.prop(linestyle, "split_gap2", text="G2")
+ sub.prop(linestyle, "split_dash3", text="D3")
+ sub.prop(linestyle, "split_gap3", text="G3")
+
+ ## Selection
+ layout.label(text="Selection:")
+ split = layout.split(align=True)
+ # First column
+ col = split.column()
+ row = col.row(align=True)
+ row.prop(linestyle, "use_min_length", text="")
+ sub = row.row()
+ sub.active = linestyle.use_min_length
+ sub.prop(linestyle, "min_length")
+ # Second column
+ col = split.column()
+ row = col.row(align=True)
+ row.prop(linestyle, "use_max_length", text="")
+ sub = row.row()
+ sub.active = linestyle.use_max_length
+ sub.prop(linestyle, "max_length")
+
+ ## Caps
+ layout.label(text="Caps:")
+ row = layout.row(align=True)
+ row.prop(linestyle, "caps", expand=True)
+
+ ## Dashed lines
+ layout.label(text="Dashed Line:")
+ row = layout.row(align=True)
+ row.prop(linestyle, "use_dashed_line", text="")
+ sub = row.row()
+ sub.active = linestyle.use_dashed_line
+ sub.prop(linestyle, "dash1", text="D1")
+ sub.prop(linestyle, "gap1", text="G1")
+ sub.prop(linestyle, "dash2", text="D2")
+ sub.prop(linestyle, "gap2", text="G2")
+ sub.prop(linestyle, "dash3", text="D3")
+ sub.prop(linestyle, "gap3", text="G3")
+
+ elif linestyle.panel == 'COLOR':
+ col = layout.column()
+ row = col.row()
+ row.label(text="Base Color:")
+ row.prop(linestyle, "color", text="")
+ col.label(text="Modifiers:")
+ col.operator_menu_enum("scene.freestyle_color_modifier_add", "type", text="Add Modifier")
+ for modifier in linestyle.color_modifiers:
+ self.draw_color_modifier(context, modifier)
+
+ elif linestyle.panel == 'ALPHA':
+ col = layout.column()
+ row = col.row()
+ row.label(text="Base Transparency:")
+ row.prop(linestyle, "alpha")
+ col.label(text="Modifiers:")
+ col.operator_menu_enum("scene.freestyle_alpha_modifier_add", "type", text="Add Modifier")
+ for modifier in linestyle.alpha_modifiers:
+ self.draw_alpha_modifier(context, modifier)
+
+ elif linestyle.panel == 'THICKNESS':
+ col = layout.column()
+ row = col.row()
+ row.label(text="Base Thickness:")
+ row.prop(linestyle, "thickness")
+ row = col.row()
+ row.prop(linestyle, "thickness_position", expand=True)
+ row = col.row()
+ row.prop(linestyle, "thickness_ratio")
+ row.active = (linestyle.thickness_position == 'RELATIVE')
+ col = layout.column()
+ col.label(text="Modifiers:")
+ col.operator_menu_enum("scene.freestyle_thickness_modifier_add", "type", text="Add Modifier")
+ for modifier in linestyle.thickness_modifiers:
+ self.draw_thickness_modifier(context, modifier)
+
+ elif linestyle.panel == 'GEOMETRY':
+ col = layout.column()
+ col.label(text="Modifiers:")
+ col.operator_menu_enum("scene.freestyle_geometry_modifier_add", "type", text="Add Modifier")
+ for modifier in linestyle.geometry_modifiers:
+ self.draw_geometry_modifier(context, modifier)
+
+ elif linestyle.panel == 'MISC':
+ pass
+
+
+if __name__ == "__main__": # only for live edit.
+ bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py
index bf0c9eb762a..1f05c8eea5a 100644
--- a/release/scripts/startup/bl_ui/properties_game.py
+++ b/release/scripts/startup/bl_ui/properties_game.py
@@ -199,6 +199,7 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel):
col = split.column()
col.prop(game, "collision_mask")
+
class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel, Panel):
bl_label = "Collision Bounds"
COMPAT_ENGINES = {'BLENDER_GAME'}
@@ -402,13 +403,18 @@ class RENDER_PT_game_system(RenderButtonsPanel, Panel):
layout = self.layout
gs = context.scene.game_settings
+ col = layout.column()
+ row = col.row()
+ col = row.column()
+ col.prop(gs, "use_frame_rate")
+ col.prop(gs, "restrict_animation_updates")
+ col.prop(gs, "use_material_caching")
+ col = row.column()
+ col.prop(gs, "use_display_lists")
+ col.active = gs.raster_storage != 'VERTEX_BUFFER_OBJECT'
row = layout.row()
- row.prop(gs, "use_frame_rate")
- row.prop(gs, "restrict_animation_updates")
-
- row = layout.row()
- row.prop(gs, "use_display_lists")
+ row.prop(gs, "raster_storage")
row = layout.row()
row.label("Exit Key")
@@ -615,7 +621,9 @@ class WORLD_PT_game_physics(WorldButtonsPanel, Panel):
layout.prop(gs, "physics_engine")
if gs.physics_engine != 'NONE':
- layout.prop(gs, "physics_gravity", text="Gravity")
+ col = layout.column()
+ col.prop(gs, "physics_gravity", text="Gravity")
+ col.prop(gs, "occlusion_culling_resolution", text="Culling Resolution")
split = layout.split()
@@ -638,12 +646,6 @@ class WORLD_PT_game_physics(WorldButtonsPanel, Panel):
sub = col.row()
sub.prop(gs, "deactivation_time", text="Time")
- col = layout.column()
- col.prop(gs, "use_occlusion_culling", text="Occlusion Culling")
- sub = col.column()
- sub.active = gs.use_occlusion_culling
- sub.prop(gs, "occlusion_culling_resolution", text="Resolution")
-
else:
split = layout.split()
diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py
index 208b0a63075..4ceaffbaf8d 100644
--- a/release/scripts/startup/bl_ui/properties_mask_common.py
+++ b/release/scripts/startup/bl_ui/properties_mask_common.py
@@ -22,7 +22,25 @@
# menus are referenced `as is`
import bpy
-from bpy.types import Menu
+from bpy.types import Menu, UIList
+
+
+class MASK_UL_layers(UIList):
+ def draw_item(self, context, layout, data, item, icon,
+ active_data, active_propname, index):
+ # assert(isinstance(item, bpy.types.MaskLayer)
+ mask = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ split = layout.split()
+ split.label(text=mask.name, translate=False, icon_value=icon)
+ row = split.row(align=True)
+ row.prop(mask, "alpha", text="", emboss=False)
+ 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'}:
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
class MASK_PT_mask:
@@ -69,7 +87,7 @@ class MASK_PT_layers:
rows = 5 if active_layer else 2
row = layout.row()
- row.template_list(mask, "layers",
+ row.template_list("MASK_UL_layers", "", mask, "layers",
mask, "active_layer_index", rows=rows)
sub = row.column(align=True)
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index 951644db752..9a3957fe353 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -18,8 +18,9 @@
# <pep8 compliant>
import bpy
-from bpy.types import Menu, Panel
+from bpy.types import Menu, Panel, UIList
from rna_prop_ui import PropertyPanel
+from bpy.app.translations import pgettext_iface as iface_
def active_node_mat(mat):
@@ -69,6 +70,25 @@ class MATERIAL_MT_specials(Menu):
layout.operator("material.paste", icon='PASTEDOWN')
+class MATERIAL_UL_matslots(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ # assert(isinstance(item, bpy.types.MaterialSlot)
+ ob = data
+ slot = item
+ ma = slot.material
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.label(text=ma.name if ma else "", translate=False, icon_value=icon)
+ if ma and not context.scene.render.use_shading_nodes:
+ manode = ma.active_node_material
+ if manode:
+ 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'}:
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
class MaterialButtonsPanel():
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
@@ -104,7 +124,7 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
if ob:
row = layout.row()
- row.template_list(ob, "material_slots", ob, "active_material_index", rows=2)
+ row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=2)
col = row.column(align=True)
col.operator("object.material_slot_add", icon='ZOOMIN', text="")
@@ -544,7 +564,7 @@ class MATERIAL_PT_halo(MaterialButtonsPanel, Panel):
row.prop(halo, toggle, text="")
sub = row.column()
sub.active = getattr(halo, toggle)
- sub.prop(halo, number, text=name)
+ sub.prop(halo, number, text=name, translate=False)
if not color == "":
sub.prop(mat, color, text="")
@@ -571,9 +591,9 @@ class MATERIAL_PT_halo(MaterialButtonsPanel, Panel):
col.prop(halo, "use_soft")
col = split.column()
- number_but(col, "use_ring", "ring_count", "Rings", "mirror_color")
- number_but(col, "use_lines", "line_count", "Lines", "specular_color")
- number_but(col, "use_star", "star_tip_count", "Star tips", "")
+ number_but(col, "use_ring", "ring_count", iface_("Rings"), "mirror_color")
+ number_but(col, "use_lines", "line_count", iface_("Lines"), "specular_color")
+ number_but(col, "use_star", "star_tip_count", iface_("Star Tips"), "")
class MATERIAL_PT_flare(MaterialButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index 8a668b5d95b..c5dbe946012 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -162,7 +162,10 @@ class OBJECT_PT_groups(ObjectButtonsPanel, Panel):
obj = context.object
row = layout.row(align=True)
- row.operator("object.group_link", text="Add to Group")
+ if bpy.data.groups:
+ row.operator("object.group_link", text="Add to Group")
+ else:
+ row.operator("object.group_add", text="Add to Group")
row.operator("object.group_add", text="", icon='ZOOMIN')
# XXX, this is bad practice, yes, I wrote it :( - campbell
@@ -230,6 +233,7 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel):
col.prop(ob, "show_x_ray", text="X-Ray")
if ob.type == 'MESH':
col.prop(ob, "show_transparent", text="Transparency")
+ col.prop(ob, "show_all_edges")
class OBJECT_PT_duplication(ObjectButtonsPanel, Panel):
@@ -289,6 +293,9 @@ class OBJECT_PT_relations_extras(ObjectButtonsPanel, Panel):
row.active = ((ob.parent is not None) and (ob.use_slow_parent))
row.prop(ob, "slow_parent_offset", text="Offset")
+ layout.prop(ob, "extra_recalc_object")
+ layout.prop(ob, "extra_recalc_data")
+
from bl_ui.properties_animviz import (MotionPathButtonsPanel,
OnionSkinButtonsPanel)
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index 53cf640beb9..a3275bea4ee 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -70,26 +70,36 @@ class UnifiedPaintPanel():
# Used in both the View3D toolbar and texture properties
-def sculpt_brush_texture_settings(layout, brush):
+def brush_texture_settings(layout, brush, sculpt):
tex_slot = brush.texture_slot
layout.label(text="Brush Mapping:")
# map_mode
- layout.row().prop(tex_slot, "map_mode", text="")
- layout.separator()
+ if sculpt:
+ layout.row().prop(tex_slot, "map_mode", text="")
+ layout.separator()
+ else:
+ layout.row().prop(tex_slot, "tex_paint_map_mode", text="")
+ layout.separator()
# angle and texture_angle_source
col = layout.column()
- col.active = brush.sculpt_capabilities.has_texture_angle_source
+ col.active = brush.brush_capabilities.has_texture_angle_source
col.label(text="Angle:")
- if brush.sculpt_capabilities.has_random_texture_angle:
- col.prop(brush, "texture_angle_source_random", text="")
+ if brush.brush_capabilities.has_random_texture_angle:
+ if sculpt:
+ if brush.sculpt_capabilities.has_random_texture_angle:
+ col.prop(brush, "texture_angle_source_random", text="")
+ else:
+ col.prop(brush, "texture_angle_source_no_random", text="")
+
+ else:
+ col.prop(brush, "texture_angle_source_random", text="")
else:
col.prop(brush, "texture_angle_source_no_random", text="")
-
col = layout.column()
- col.active = brush.sculpt_capabilities.has_texture_angle
+ col.active = brush.brush_capabilities.has_texture_angle
col.prop(tex_slot, "angle", text="")
# scale and offset
@@ -97,7 +107,8 @@ def sculpt_brush_texture_settings(layout, brush):
split.prop(tex_slot, "offset")
split.prop(tex_slot, "scale")
- # texture_sample_bias
- col = layout.column(align=True)
- col.label(text="Sample Bias:")
- col.prop(brush, "texture_sample_bias", slider=True, text="")
+ if sculpt:
+ # texture_sample_bias
+ col = layout.column(align=True)
+ col.label(text="Sample Bias:")
+ col.prop(brush, "texture_sample_bias", slider=True, text="")
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
index 3f672d2a977..d4a16b56b43 100644
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -20,6 +20,7 @@
import bpy
from bpy.types import Panel
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,
@@ -96,7 +97,8 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
if ob:
row = layout.row()
- row.template_list(ob, "particle_systems", ob.particle_systems, "active_index", rows=2)
+ row.template_list("UI_UL_list", "particle_systems", ob, "particle_systems",
+ ob.particle_systems, "active_index", rows=2)
col = row.column(align=True)
col.operator("object.particle_system_add", icon='ZOOMIN', text="")
@@ -148,7 +150,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
#row.label(text="Render")
if part.is_fluid:
- layout.label(text="%d fluid particles for this frame" % part.count)
+ layout.label(text=iface_("%d fluid particles for this frame") % part.count, translate=False)
return
row = col.row()
@@ -490,11 +492,13 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
col.prop(part, "integrator", text="")
col.prop(part, "timestep")
sub = col.row()
- if part.adaptive_subframes:
- sub.prop(part, "courant_target", text="Threshold")
- else:
- sub.prop(part, "subframes")
- sub.prop(part, "adaptive_subframes", text="")
+ sub.prop(part, "subframes")
+ supports_courant = part.physics_type == 'FLUID'
+ subsub = sub.row()
+ subsub.enabled = supports_courant
+ subsub.prop(part, "adaptive_subframes", text="")
+ if supports_courant and part.adaptive_subframes:
+ col.prop(part, "courant_target", text="Threshold")
row = layout.row()
row.prop(part, "use_size_deflect")
@@ -504,6 +508,10 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
fluid = part.fluid
split = layout.split()
+ sub = split.row()
+ sub.prop(fluid, "solver", expand=True)
+
+ split = layout.split()
col = split.column()
col.label(text="Fluid properties:")
@@ -514,13 +522,14 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
col = split.column()
col.label(text="Advanced:")
- sub = col.row()
- sub.prop(fluid, "repulsion", slider=fluid.factor_repulsion)
- sub.prop(fluid, "factor_repulsion", text="")
+ if fluid.solver == 'DDR':
+ sub = col.row()
+ sub.prop(fluid, "repulsion", slider=fluid.factor_repulsion)
+ sub.prop(fluid, "factor_repulsion", text="")
- sub = col.row()
- sub.prop(fluid, "stiff_viscosity", slider=fluid.factor_stiff_viscosity)
- sub.prop(fluid, "factor_stiff_viscosity", text="")
+ sub = col.row()
+ sub.prop(fluid, "stiff_viscosity", slider=fluid.factor_stiff_viscosity)
+ sub.prop(fluid, "factor_stiff_viscosity", text="")
sub = col.row()
sub.prop(fluid, "fluid_radius", slider=fluid.factor_radius)
@@ -530,27 +539,37 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
sub.prop(fluid, "rest_density", slider=fluid.factor_density)
sub.prop(fluid, "factor_density", text="")
- split = layout.split()
-
- col = split.column()
- col.label(text="Springs:")
- col.prop(fluid, "spring_force", text="Force")
- col.prop(fluid, "use_viscoelastic_springs")
- sub = col.column(align=True)
- sub.active = fluid.use_viscoelastic_springs
- sub.prop(fluid, "yield_ratio", slider=True)
- sub.prop(fluid, "plasticity", slider=True)
-
- col = split.column()
- col.label(text="Advanced:")
- sub = col.row()
- sub.prop(fluid, "rest_length", slider=fluid.factor_rest_length)
- sub.prop(fluid, "factor_rest_length", text="")
- col.label(text="")
- sub = col.column()
- sub.active = fluid.use_viscoelastic_springs
- sub.prop(fluid, "use_initial_rest_length")
- sub.prop(fluid, "spring_frames", text="Frames")
+ if fluid.solver == 'CLASSICAL':
+ # With the classical solver, it is possible to calculate the
+ # spacing between particles when the fluid is at rest. This
+ # makes it easier to set stable initial conditions.
+ particle_volume = part.mass / fluid.rest_density
+ spacing = pow(particle_volume, 1.0 / 3.0)
+ sub = col.row()
+ sub.label(text="Spacing: %g" % spacing)
+
+ elif fluid.solver == 'DDR':
+ split = layout.split()
+
+ col = split.column()
+ col.label(text="Springs:")
+ col.prop(fluid, "spring_force", text="Force")
+ col.prop(fluid, "use_viscoelastic_springs")
+ sub = col.column(align=True)
+ sub.active = fluid.use_viscoelastic_springs
+ sub.prop(fluid, "yield_ratio", slider=True)
+ sub.prop(fluid, "plasticity", slider=True)
+
+ col = split.column()
+ col.label(text="Advanced:")
+ sub = col.row()
+ sub.prop(fluid, "rest_length", slider=fluid.factor_rest_length)
+ sub.prop(fluid, "factor_rest_length", text="")
+ col.label(text="")
+ sub = col.column()
+ sub.active = fluid.use_viscoelastic_springs
+ sub.prop(fluid, "use_initial_rest_length")
+ sub.prop(fluid, "spring_frames", text="Frames")
elif part.physics_type == 'KEYED':
split = layout.split()
@@ -619,7 +638,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
layout.label(text="Fluid interaction:")
row = layout.row()
- row.template_list(psys, "targets", psys, "active_particle_target_index")
+ row.template_list("UI_UL_list", "particle_targets", psys, "targets", psys, "active_particle_target_index")
col = row.column()
sub = col.row()
@@ -685,7 +704,8 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel):
# Currently boids can only use the first state so these are commented out for now.
#row = layout.row()
- #row.template_list(boids, "states", boids, "active_boid_state_index", compact="True")
+ #row.template_list("UI_UL_list", "particle_boids", boids, "states",
+ # boids, "active_boid_state_index", compact="True")
#col = row.row()
#sub = col.row(align=True)
#sub.operator("boid.state_add", icon='ZOOMIN', text="")
@@ -706,7 +726,7 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel):
row.label(text="")
row = layout.row()
- row.template_list(state, "rules", state, "active_boid_rule_index")
+ row.template_list("UI_UL_list", "particle_boids_rules", state, "rules", state, "active_boid_rule_index")
col = row.column()
sub = col.row()
@@ -823,7 +843,12 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel):
col = split.column()
col.label(text="Timing:")
col.prop(part, "use_absolute_path_time")
- col.prop(part, "path_start", text="Start", slider=not part.use_absolute_path_time)
+
+ if part.type == 'HAIR' or psys.point_cache.is_baked:
+ col.prop(part, "path_start", text="Start", slider=not part.use_absolute_path_time)
+ else:
+ col.prop(part, "trail_count")
+
col.prop(part, "path_end", text="End", slider=not part.use_absolute_path_time)
col.prop(part, "length_random", text="Random", slider=True)
@@ -869,7 +894,8 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel):
if part.use_group_count and not part.use_whole_group:
row = layout.row()
- row.template_list(part, "dupli_weights", part, "active_dupliweight_index")
+ row.template_list("UI_UL_list", "particle_dupli_weights", part, "dupli_weights",
+ part, "active_dupliweight_index")
col = row.column()
sub = col.row()
diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py
index 5a44294f0e0..91b4cc0ae49 100644
--- a/release/scripts/startup/bl_ui/properties_physics_cloth.py
+++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py
@@ -91,7 +91,7 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
sub.prop(cloth, "pin_stiffness", text="Stiffness")
col.label(text="Pre roll:")
- col.prop(cloth, "pre_roll", text="Frame")
+ col.prop(cloth, "pre_roll", text="Frames")
# Disabled for now
"""
diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py
index 405e877d1e2..2d9d4649e28 100644
--- a/release/scripts/startup/bl_ui/properties_physics_common.py
+++ b/release/scripts/startup/bl_ui/properties_physics_common.py
@@ -21,6 +21,8 @@
import bpy
from bpy.types import Panel
+i18n_default_ctxt = bpy.app.translations.contexts.default
+
class PhysicButtonsPanel():
bl_space_type = 'PROPERTIES'
@@ -37,12 +39,20 @@ def physics_add(self, layout, md, name, type, typeicon, toggles):
sub = layout.row(align=True)
if md:
sub.context_pointer_set("modifier", md)
- sub.operator("object.modifier_remove", text=name, icon='X')
+ sub.operator("object.modifier_remove", text=name, text_ctxt=i18n_default_ctxt, icon='X')
if(toggles):
sub.prop(md, "show_render", text="")
sub.prop(md, "show_viewport", text="")
else:
- sub.operator("object.modifier_add", text=name, icon=typeicon).type = type
+ sub.operator("object.modifier_add", text=name, text_ctxt=i18n_default_ctxt, icon=typeicon).type = type
+
+
+def physics_add_special(self, layout, data, name, addop, removeop, typeicon):
+ sub = layout.row(align=True)
+ if data:
+ sub.operator(removeop, text=name, text_ctxt=i18n_default_ctxt, icon='X')
+ else:
+ sub.operator(addop, text=name, text_ctxt=i18n_default_ctxt, icon=typeicon)
class PHYSICS_PT_add(PhysicButtonsPanel, Panel):
@@ -76,6 +86,18 @@ class PHYSICS_PT_add(PhysicButtonsPanel, Panel):
physics_add(self, col, context.fluid, "Fluid", 'FLUID_SIMULATION', 'MOD_FLUIDSIM', True)
physics_add(self, col, context.smoke, "Smoke", 'SMOKE', 'MOD_SMOKE', True)
+ if(ob.type == 'MESH'):
+ physics_add_special(self, col, ob.rigid_body, "Rigid Body",
+ "rigidbody.object_add",
+ "rigidbody.object_remove",
+ 'MESH_ICOSPHERE') # XXX: need dedicated icon
+
+ # all types of objects can have rigid body constraint
+ physics_add_special(self, col, ob.rigid_body_constraint, "Rigid Body Constraint",
+ "rigidbody.constraint_add",
+ "rigidbody.constraint_remove",
+ 'CONSTRAINT') # RB_TODO needs better icon
+
# cache-type can be 'PSYS' 'HAIR' 'SMOKE' etc
@@ -84,11 +106,13 @@ def point_cache_ui(self, context, cache, enabled, cachetype):
layout.context_pointer_set("point_cache", cache)
- row = layout.row()
- row.template_list(cache, "point_caches", cache.point_caches, "active_index", rows=2)
- col = row.column(align=True)
- col.operator("ptcache.add", icon='ZOOMIN', text="")
- col.operator("ptcache.remove", icon='ZOOMOUT', text="")
+ if not cachetype == 'RIGID_BODY':
+ row = layout.row()
+ row.template_list("UI_UL_list", "point_caches", cache, "point_caches",
+ cache.point_caches, "active_index", rows=2)
+ col = row.column(align=True)
+ col.operator("ptcache.add", icon='ZOOMIN', text="")
+ col.operator("ptcache.remove", icon='ZOOMOUT', text="")
row = layout.row()
if cachetype in {'PSYS', 'HAIR', 'SMOKE'}:
@@ -131,13 +155,13 @@ def point_cache_ui(self, context, cache, enabled, cachetype):
row.enabled = enabled
row.prop(cache, "frame_start")
row.prop(cache, "frame_end")
- if cachetype not in {'SMOKE', 'CLOTH', 'DYNAMIC_PAINT'}:
+ if cachetype not in {'SMOKE', 'CLOTH', 'DYNAMIC_PAINT', 'RIGID_BODY'}:
row.prop(cache, "frame_step")
-
+
if cachetype != 'SMOKE':
layout.label(text=cache.info)
- if cachetype not in {'SMOKE', 'DYNAMIC_PAINT'}:
+ if cachetype not in {'SMOKE', 'DYNAMIC_PAINT', 'RIGID_BODY'}:
split = layout.split()
split.enabled = enabled and bpy.data.is_saved
diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
index 1df2936b2d4..7ee63ee7a2f 100644
--- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
+++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
@@ -18,13 +18,34 @@
# <pep8 compliant>
import bpy
-from bpy.types import Panel
+from bpy.types import Panel, UIList
from bl_ui.properties_physics_common import (point_cache_ui,
effector_weights_ui,
)
+class PHYSICS_UL_dynapaint_surfaces(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ # assert(isinstance(item, bpy.types.DynamicPaintSurface)
+ surf = item
+ sticon = layout.enum_item_icon(surf, "surface_type", surf.surface_type)
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ row = layout.row(align=True)
+ row.label(text="", icon_value=icon)
+ row.label(text=surf.name, translate=False, icon_value=sticon)
+ row = layout.row(align=True)
+ if surf.use_color_preview:
+ 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'}:
+ layout.alignment = 'CENTER'
+ row = layout.row(align=True)
+ row.label(text="", icon_value=icon)
+ row.label(text="", icon_value=sticon)
+
+
class PhysicButtonsPanel():
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
@@ -58,7 +79,8 @@ class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel):
surface = canvas.canvas_surfaces.active
row = layout.row()
- row.template_list(canvas, "canvas_surfaces", canvas.canvas_surfaces, "active_index", rows=2)
+ row.template_list("PHYSICS_UL_dynapaint_surfaces", "", canvas, "canvas_surfaces",
+ canvas.canvas_surfaces, "active_index", rows=2)
col = row.column(align=True)
col.operator("dpaint.surface_slot_add", icon='ZOOMIN', text="")
diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py
index 08278c02693..b3cd5dc5464 100644
--- a/release/scripts/startup/bl_ui/properties_physics_fluid.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py
@@ -19,6 +19,7 @@
# <pep8 compliant>
import bpy
from bpy.types import Panel, Menu
+from bpy.app.translations import pgettext_iface as iface_
class FLUID_MT_presets(Menu):
@@ -50,7 +51,7 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel, Panel):
fluid = md.settings
col = layout.column()
- if fluid is None:
+ if not bpy.app.build_options.mod_fluid:
col.label("Built without fluids")
return
@@ -64,7 +65,8 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel, Panel):
if fluid.type == 'DOMAIN':
# odd formatting here so translation script can extract string
- layout.operator("fluid.bake", text="Bake (Req. Memory:" + " %s)" % fluid.memory_estimate, icon='MOD_FLUIDSIM')
+ layout.operator("fluid.bake", text=iface_("Bake (Req. Memory: %s)") % fluid.memory_estimate,
+ translate=False, icon='MOD_FLUIDSIM')
split = layout.split()
col = split.column()
@@ -90,8 +92,9 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel, Panel):
col = split.column()
col.label()
- col.prop(fluid, "use_speed_vectors")
- col.prop(fluid, "use_reverse_frames")
+ sub = col.column(align=True)
+ sub.prop(fluid, "use_speed_vectors")
+ sub.prop(fluid, "use_reverse_frames")
col.prop(fluid, "frame_offset", text="Offset")
layout.prop(fluid, "filepath", text="")
@@ -293,9 +296,9 @@ class PHYSICS_PT_domain_particles(PhysicButtonsPanel, Panel):
fluid = context.fluid.settings
- col = layout.column(align=True)
- col.prop(fluid, "tracer_particles")
- col.prop(fluid, "generate_particles")
+ row = layout.row()
+ row.prop(fluid, "tracer_particles", text="Tracer")
+ row.prop(fluid, "generate_particles", text="Generate")
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/properties_physics_rigidbody.py b/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
new file mode 100644
index 00000000000..77ea5a90344
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
@@ -0,0 +1,132 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public 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 Panel
+
+
+class PHYSICS_PT_rigidbody_panel():
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "physics"
+
+
+class PHYSICS_PT_rigid_body(PHYSICS_PT_rigidbody_panel, Panel):
+ bl_label = "Rigid Body"
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.object
+ return (obj and obj.rigid_body and
+ (not context.scene.render.use_game_engine))
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ rbo = ob.rigid_body
+
+ if rbo is not None:
+ layout.prop(rbo, "type", text="Type")
+ row = layout.row()
+ if rbo.type == 'ACTIVE':
+ row.prop(rbo, "enabled", text="Dynamic")
+ row.prop(rbo, "kinematic", text="Animated")
+
+ if rbo.type == 'ACTIVE':
+ layout.prop(rbo, "mass")
+
+
+class PHYSICS_PT_rigid_body_collisions(PHYSICS_PT_rigidbody_panel, Panel):
+ bl_label = "Rigid Body Collisions"
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.object
+ return (obj and obj.rigid_body and
+ (not context.scene.render.use_game_engine))
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ rbo = ob.rigid_body
+
+ layout.prop(rbo, "collision_shape", text="Shape")
+
+ split = layout.split()
+
+ col = split.column()
+ col.label(text="Surface Response:")
+ col.prop(rbo, "friction")
+ col.prop(rbo, "restitution", text="Bounciness")
+
+ col = split.column()
+ col.label(text="Sensitivity:")
+ if rbo.collision_shape in {'MESH', 'CONE'}:
+ col.prop(rbo, "collision_margin", text="Margin")
+ else:
+ col.prop(rbo, "use_margin")
+ sub = col.column()
+ sub.active = rbo.use_margin
+ sub.prop(rbo, "collision_margin", text="Margin")
+
+ layout.prop(rbo, "collision_groups")
+
+
+class PHYSICS_PT_rigid_body_dynamics(PHYSICS_PT_rigidbody_panel, Panel):
+ bl_label = "Rigid Body Dynamics"
+ bl_default_closed = True
+
+ @classmethod
+ def poll(cls, context):
+ obj = context.object
+ return (obj and obj.rigid_body and
+ obj.rigid_body.type == 'ACTIVE' and
+ (not context.scene.render.use_game_engine))
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ rbo = ob.rigid_body
+
+ #col = layout.column(align=1)
+ #col.label(text="Activation:")
+ # XXX: settings such as activate on collison/etc.
+
+ split = layout.split()
+
+ col = split.column()
+ col.label(text="Deactivation:")
+ col.prop(rbo, "use_deactivation")
+ sub = col.column()
+ sub.active = rbo.use_deactivation
+ sub.prop(rbo, "start_deactivated")
+ sub.prop(rbo, "deactivate_linear_velocity", text="Linear Vel")
+ sub.prop(rbo, "deactivate_angular_velocity", text="Angular Vel")
+ # TODO: other params such as time?
+
+ col = split.column()
+ col.label(text="Damping:")
+ col.prop(rbo, "linear_damping", text="Translation")
+ col.prop(rbo, "angular_damping", text="Rotation")
+
+if __name__ == "__main__": # only for live edit.
+ bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py b/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py
new file mode 100644
index 00000000000..a49c6d623ca
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py
@@ -0,0 +1,233 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public 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 Panel
+
+
+class PHYSICS_PT_rigidbody_constraint_panel():
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "physics"
+
+
+class PHYSICS_PT_rigid_body_constraint(PHYSICS_PT_rigidbody_constraint_panel, Panel):
+ bl_label = "Rigid Body Constraint"
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ rd = context.scene.render
+ return (ob and ob.rigid_body_constraint and (not rd.use_game_engine))
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ rbc = ob.rigid_body_constraint
+
+ layout.prop(rbc, "type")
+
+ row = layout.row()
+ row.prop(rbc, "enabled")
+ row.prop(rbc, "disable_collisions")
+
+ layout.prop(rbc, "object1")
+ layout.prop(rbc, "object2")
+
+ if rbc.type != 'MOTOR':
+ row = layout.row()
+ row.prop(rbc, "use_breaking")
+ sub = row.row()
+ sub.active = rbc.use_breaking
+ sub.prop(rbc, "breaking_threshold", text="Threshold")
+
+ row = layout.row()
+ row.prop(rbc, "override_solver_iterations", text="Override Iterations")
+ sub = row.row()
+ sub.active = rbc.override_solver_iterations
+ sub.prop(rbc, "num_solver_iterations", text="Iterations")
+
+ if rbc.type == 'HINGE':
+ col = layout.column(align=True)
+ col.label("Limits:")
+
+ row = col.row()
+ sub = row.row()
+ sub.scale_x = 0.5
+ sub.prop(rbc, "use_limit_ang_z", toggle=True)
+ sub = row.row()
+ sub.active = rbc.use_limit_ang_z
+ sub.prop(rbc, "limit_ang_z_lower", text="Lower")
+ sub.prop(rbc, "limit_ang_z_upper", text="Upper")
+
+ elif rbc.type == 'SLIDER':
+ col = layout.column(align=True)
+ col.label("Limits:")
+
+ row = col.row()
+ sub = row.row()
+ sub.scale_x = 0.5
+ sub.prop(rbc, "use_limit_lin_x", toggle=True)
+ sub = row.row()
+ sub.active = rbc.use_limit_lin_x
+ sub.prop(rbc, "limit_lin_x_lower", text="Lower")
+ sub.prop(rbc, "limit_lin_x_upper", text="Upper")
+
+ elif rbc.type == 'PISTON':
+ col = layout.column(align=True)
+ col.label("Limits:")
+
+ row = col.row()
+ sub = row.row()
+ sub.scale_x = 0.5
+ sub.prop(rbc, "use_limit_lin_x", toggle=True)
+ sub = row.row()
+ sub.active = rbc.use_limit_lin_x
+ sub.prop(rbc, "limit_lin_x_lower", text="Lower")
+ sub.prop(rbc, "limit_lin_x_upper", text="Upper")
+
+ col = layout.column(align=True)
+
+ row = col.row()
+ sub = row.row()
+ sub.scale_x = 0.5
+ sub.prop(rbc, "use_limit_ang_x", toggle=True)
+ sub = row.row()
+ sub.active = rbc.use_limit_ang_x
+ sub.prop(rbc, "limit_ang_x_lower", text="Lower")
+ sub.prop(rbc, "limit_ang_x_upper", text="Upper")
+
+ elif rbc.type == 'MOTOR':
+ col = layout.column(align=True)
+ col.label("Linear motor:")
+
+ row = col.row()
+ sub = row.row()
+ sub.scale_x = 0.5
+ sub.prop(rbc, "use_motor_lin", toggle=True, text="Enable")
+ sub = row.row()
+ sub.active = rbc.use_motor_lin
+ sub.prop(rbc, "motor_lin_target_velocity", text="Target Velocity")
+ sub.prop(rbc, "motor_lin_max_impulse", text="Max Impulse")
+
+ col.label("Angular motor:")
+
+ row = col.row()
+ sub = row.row()
+ sub.scale_x = 0.5
+ sub.prop(rbc, "use_motor_ang", toggle=True, text="Enable")
+ sub = row.row()
+ sub.active = rbc.use_motor_ang
+ sub.prop(rbc, "motor_ang_target_velocity", text="Target Velocity")
+ sub.prop(rbc, "motor_ang_max_impulse", text="Max Impulse")
+
+ elif rbc.type in {'GENERIC', 'GENERIC_SPRING'}:
+ col = layout.column(align=True)
+ col.label("Limits:")
+
+ row = col.row()
+ sub = row.row()
+ sub.scale_x = 0.5
+ sub.prop(rbc, "use_limit_lin_x", toggle=True)
+ sub = row.row()
+ sub.active = rbc.use_limit_lin_x
+ sub.prop(rbc, "limit_lin_x_lower", text="Lower")
+ sub.prop(rbc, "limit_lin_x_upper", text="Upper")
+
+ row = col.row()
+ sub = row.row()
+ sub.scale_x = 0.5
+ sub.prop(rbc, "use_limit_lin_y", toggle=True)
+ sub = row.row()
+ sub.active = rbc.use_limit_lin_y
+ sub.prop(rbc, "limit_lin_y_lower", text="Lower")
+ sub.prop(rbc, "limit_lin_y_upper", text="Upper")
+
+ row = col.row()
+ sub = row.row()
+ sub.scale_x = 0.5
+ sub.prop(rbc, "use_limit_lin_z", toggle=True)
+ sub = row.row()
+ sub.active = rbc.use_limit_lin_z
+ sub.prop(rbc, "limit_lin_z_lower", text="Lower")
+ sub.prop(rbc, "limit_lin_z_upper", text="Upper")
+
+ col = layout.column(align=True)
+
+ row = col.row()
+ sub = row.row()
+ sub.scale_x = 0.5
+ sub.prop(rbc, "use_limit_ang_x", toggle=True)
+ sub = row.row()
+ sub.active = rbc.use_limit_ang_x
+ sub.prop(rbc, "limit_ang_x_lower", text="Lower")
+ sub.prop(rbc, "limit_ang_x_upper", text="Upper")
+
+ row = col.row()
+ sub = row.row()
+ sub.scale_x = 0.5
+ sub.prop(rbc, "use_limit_ang_y", toggle=True)
+ sub = row.row()
+ sub.active = rbc.use_limit_ang_y
+ sub.prop(rbc, "limit_ang_y_lower", text="Lower")
+ sub.prop(rbc, "limit_ang_y_upper", text="Upper")
+
+ row = col.row()
+ sub = row.row()
+ sub.scale_x = 0.5
+ sub.prop(rbc, "use_limit_ang_z", toggle=True)
+ sub = row.row()
+ sub.active = rbc.use_limit_ang_z
+ sub.prop(rbc, "limit_ang_z_lower", text="Lower")
+ sub.prop(rbc, "limit_ang_z_upper", text="Upper")
+
+ if rbc.type == 'GENERIC_SPRING':
+ col = layout.column(align=True)
+ col.label("Springs:")
+
+ row = col.row()
+ sub = row.row()
+ sub.scale_x = 0.1
+ sub.prop(rbc, "use_spring_x", toggle=True, text="X")
+ sub = row.row()
+ sub.active = rbc.use_spring_x
+ sub.prop(rbc, "spring_stiffness_x", text="Stiffness")
+ sub.prop(rbc, "spring_damping_x")
+
+ row = col.row()
+ sub = row.row()
+ sub.scale_x = 0.1
+ sub.prop(rbc, "use_spring_y", toggle=True, text="Y")
+ sub = row.row()
+ sub.active = rbc.use_spring_y
+ sub.prop(rbc, "spring_stiffness_y", text="Stiffness")
+ sub.prop(rbc, "spring_damping_y")
+
+ row = col.row()
+ sub = row.row()
+ sub.scale_x = 0.1
+ sub.prop(rbc, "use_spring_z", toggle=True, text="Z")
+ sub = row.row()
+ sub.active = rbc.use_spring_z
+ sub.prop(rbc, "spring_stiffness_z", text="Stiffness")
+ sub.prop(rbc, "spring_damping_z")
+
+if __name__ == "__main__": # only for live edit.
+ bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/properties_physics_smoke.py b/release/scripts/startup/bl_ui/properties_physics_smoke.py
index ce5053f0ecf..487f43aa973 100644
--- a/release/scripts/startup/bl_ui/properties_physics_smoke.py
+++ b/release/scripts/startup/bl_ui/properties_physics_smoke.py
@@ -76,7 +76,7 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
elif md.smoke_type == 'FLOW':
flow = md.flow_settings
-
+
layout.prop(flow, "smoke_flow_type", expand=False)
if flow.smoke_flow_type != "OUTFLOW":
@@ -118,7 +118,8 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
col = split.column()
col.prop(coll, "collision_type")
-
+
+
class PHYSICS_PT_smoke_flow_advanced(PhysicButtonsPanel, Panel):
bl_label = "Smoke Flow Advanced"
bl_options = {'DEFAULT_CLOSED'}
@@ -132,7 +133,7 @@ class PHYSICS_PT_smoke_flow_advanced(PhysicButtonsPanel, Panel):
layout = self.layout
ob = context.object
flow = context.smoke.flow_settings
-
+
split = layout.split()
col = split.column()
@@ -147,11 +148,12 @@ class PHYSICS_PT_smoke_flow_advanced(PhysicButtonsPanel, Panel):
if flow.texture_map_type == "AUTO":
sub.prop(flow, "texture_size")
sub.prop(flow, "texture_offset")
-
+
col = split.column()
col.label(text="Vertex Group:")
col.prop_search(flow, "density_vertex_group", ob, "vertex_groups", text="")
+
class PHYSICS_PT_smoke_fire(PhysicButtonsPanel, Panel):
bl_label = "Smoke Flames"
bl_options = {'DEFAULT_CLOSED'}
@@ -179,7 +181,8 @@ class PHYSICS_PT_smoke_fire(PhysicButtonsPanel, Panel):
col.prop(domain, "flame_ignition")
col.prop(domain, "flame_max_temp")
col.prop(domain, "flame_smoke_color")
-
+
+
class PHYSICS_PT_smoke_adaptive_domain(PhysicButtonsPanel, Panel):
bl_label = "Smoke Adaptive Domain"
bl_options = {'DEFAULT_CLOSED'}
@@ -199,10 +202,10 @@ class PHYSICS_PT_smoke_adaptive_domain(PhysicButtonsPanel, Panel):
domain = context.smoke.domain_settings
layout.active = domain.use_adaptive_domain
-
+
split = layout.split()
- split.enabled = not domain.point_cache.is_baked
-
+ split.enabled = (not domain.point_cache.is_baked)
+
col = split.column(align=True)
col.label(text="Resolution:")
col.prop(domain, "additional_res")
@@ -212,6 +215,7 @@ class PHYSICS_PT_smoke_adaptive_domain(PhysicButtonsPanel, Panel):
col.label(text="Advanced:")
col.prop(domain, "adapt_threshold")
+
class PHYSICS_PT_smoke_highres(PhysicButtonsPanel, Panel):
bl_label = "Smoke High Resolution"
bl_options = {'DEFAULT_CLOSED'}
@@ -249,6 +253,7 @@ class PHYSICS_PT_smoke_highres(PhysicButtonsPanel, Panel):
layout.prop(md, "show_high_resolution")
+
class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, Panel):
bl_label = "Smoke Groups"
bl_options = {'DEFAULT_CLOSED'}
@@ -262,7 +267,7 @@ class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
domain = context.smoke.domain_settings
-
+
split = layout.split()
col = split.column()
@@ -276,6 +281,7 @@ class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, Panel):
col.label(text="Collision Group:")
col.prop(domain, "collision_group", text="")
+
class PHYSICS_PT_smoke_cache(PhysicButtonsPanel, Panel):
bl_label = "Smoke Cache"
bl_options = {'DEFAULT_CLOSED'}
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 9814dd7e902..5cf86b8d4b0 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -1,4 +1,5 @@
# ##### BEGIN GPL LICENSE BLOCK #####
+
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -50,8 +51,8 @@ class RenderButtonsPanel():
@classmethod
def poll(cls, context):
- rd = context.scene.render
- return context.scene and (rd.engine in cls.COMPAT_ENGINES)
+ scene = context.scene
+ return scene and (scene.render.engine in cls.COMPAT_ENGINES)
class RENDER_PT_render(RenderButtonsPanel, Panel):
@@ -71,110 +72,6 @@ class RENDER_PT_render(RenderButtonsPanel, Panel):
layout.prop(rd, "display_mode", text="Display")
-class RENDER_PT_layers(RenderButtonsPanel, Panel):
- bl_label = "Layers"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- rd = scene.render
-
- row = layout.row()
- row.template_list(rd, "layers", rd.layers, "active_index", rows=2)
-
- col = row.column(align=True)
- col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
- col.operator("scene.render_layer_remove", icon='ZOOMOUT', text="")
-
- row = layout.row()
- rl = rd.layers.active
- if rl:
- row.prop(rl, "name")
- row.prop(rd, "use_single_layer", text="", icon_only=True)
-
- split = layout.split()
-
- col = split.column()
- col.prop(scene, "layers", text="Scene")
- col.label(text="")
- col.prop(rl, "light_override", text="Light")
- col.prop(rl, "material_override", text="Material")
-
- col = split.column()
- col.prop(rl, "layers", text="Layer")
- col.label(text="Mask Layers:")
- col.prop(rl, "layers_zmask", text="")
-
- layout.separator()
- layout.label(text="Include:")
-
- split = layout.split()
-
- col = split.column()
- col.prop(rl, "use_zmask")
- row = col.row()
- row.prop(rl, "invert_zmask", text="Negate")
- row.active = rl.use_zmask
- col.prop(rl, "use_all_z")
-
- col = split.column()
- col.prop(rl, "use_solid")
- col.prop(rl, "use_halo")
- col.prop(rl, "use_ztransp")
-
- col = split.column()
- col.prop(rl, "use_sky")
- col.prop(rl, "use_edge_enhance")
- col.prop(rl, "use_strand")
-
- layout.separator()
-
- split = layout.split()
-
- col = split.column()
- col.label(text="Passes:")
- col.prop(rl, "use_pass_combined")
- col.prop(rl, "use_pass_z")
- col.prop(rl, "use_pass_vector")
- col.prop(rl, "use_pass_normal")
- col.prop(rl, "use_pass_uv")
- col.prop(rl, "use_pass_mist")
- col.prop(rl, "use_pass_object_index")
- col.prop(rl, "use_pass_material_index")
- col.prop(rl, "use_pass_color")
-
- col = split.column()
- col.label()
- col.prop(rl, "use_pass_diffuse")
- row = col.row()
- row.prop(rl, "use_pass_specular")
- row.prop(rl, "exclude_specular", text="")
- row = col.row()
- row.prop(rl, "use_pass_shadow")
- row.prop(rl, "exclude_shadow", text="")
- row = col.row()
- row.prop(rl, "use_pass_emit")
- row.prop(rl, "exclude_emit", text="")
- row = col.row()
- row.prop(rl, "use_pass_ambient_occlusion")
- row.prop(rl, "exclude_ambient_occlusion", text="")
- row = col.row()
- row.prop(rl, "use_pass_environment")
- row.prop(rl, "exclude_environment", text="")
- row = col.row()
- row.prop(rl, "use_pass_indirect")
- row.prop(rl, "exclude_indirect", text="")
- row = col.row()
- row.prop(rl, "use_pass_reflection")
- row.prop(rl, "exclude_reflection", text="")
- row = col.row()
- row.prop(rl, "use_pass_refraction")
- row.prop(rl, "exclude_refraction", text="")
-
-
class RENDER_PT_dimensions(RenderButtonsPanel, Panel):
bl_label = "Dimensions"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -338,7 +235,7 @@ class RENDER_PT_performance(RenderButtonsPanel, Panel):
subsub = sub.column()
subsub.enabled = rd.threads_mode == 'FIXED'
subsub.prop(rd, "threads")
-
+
sub = col.column(align=True)
sub.label(text="Tile Size:")
sub.prop(rd, "tile_x", text="X")
@@ -460,10 +357,14 @@ class RENDER_PT_output(RenderButtonsPanel, Panel):
layout.prop(rd, "filepath", text="")
- flow = layout.column_flow()
- flow.prop(rd, "use_overwrite")
- flow.prop(rd, "use_placeholder")
- flow.prop(rd, "use_file_extension")
+ split = layout.split()
+
+ col = split.column()
+ col.active = not rd.is_movie_format
+ col.prop(rd, "use_overwrite")
+ col.prop(rd, "use_placeholder")
+
+ split.prop(rd, "use_file_extension")
layout.template_image_settings(image_settings, color_management=False)
@@ -573,7 +474,7 @@ class RENDER_PT_bake(RenderButtonsPanel, Panel):
layout.prop(rd, "bake_type")
multires_bake = False
- if rd.bake_type in ['NORMALS', 'DISPLACEMENT']:
+ if rd.bake_type in ['NORMALS', 'DISPLACEMENT', 'AO']:
layout.prop(rd, "use_bake_multires")
multires_bake = rd.use_bake_multires
@@ -591,9 +492,12 @@ class RENDER_PT_bake(RenderButtonsPanel, Panel):
split = layout.split()
col = split.column()
- col.prop(rd, "use_bake_clear")
- col.prop(rd, "bake_margin")
- col.prop(rd, "bake_quad_split", text="Split")
+ col.prop(rd, "use_bake_to_vertex_color")
+ sub = col.column()
+ sub.active = not rd.use_bake_to_vertex_color
+ sub.prop(rd, "use_bake_clear")
+ sub.prop(rd, "bake_margin")
+ sub.prop(rd, "bake_quad_split", text="Split")
col = split.column()
col.prop(rd, "use_bake_selected_to_active")
@@ -602,11 +506,19 @@ class RENDER_PT_bake(RenderButtonsPanel, Panel):
sub.prop(rd, "bake_distance")
sub.prop(rd, "bake_bias")
else:
- if rd.bake_type == 'DISPLACEMENT':
- layout.prop(rd, "use_bake_lores_mesh")
+ split = layout.split()
+
+ col = split.column()
+ col.prop(rd, "use_bake_clear")
+ col.prop(rd, "bake_margin")
- layout.prop(rd, "use_bake_clear")
- layout.prop(rd, "bake_margin")
+ if rd.bake_type == 'DISPLACEMENT':
+ col = split.column()
+ col.prop(rd, "use_bake_lores_mesh")
+ if rd.bake_type == 'AO':
+ col = split.column()
+ col.prop(rd, "bake_bias")
+ col.prop(rd, "bake_samples")
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/properties_render_layer.py b/release/scripts/startup/bl_ui/properties_render_layer.py
new file mode 100644
index 00000000000..af11fa505ff
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_render_layer.py
@@ -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 #####
+
+# <pep8 compliant>
+import bpy
+from bpy.types import Menu, Panel, UIList
+
+
+class RenderLayerButtonsPanel():
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "render_layer"
+ # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
+
+ @classmethod
+ def poll(cls, context):
+ scene = context.scene
+ return scene and (scene.render.engine in cls.COMPAT_ENGINES)
+
+
+class RENDERLAYER_UL_renderlayers(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ # assert(isinstance(item, bpy.types.SceneRenderLayer)
+ layer = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.label(layer.name, icon_value=icon)
+ layout.prop(layer, "use", text="", index=index)
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label("", icon_value=icon)
+
+# else if (RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer)) {
+# uiItemL(sub, name, icon);
+# uiBlockSetEmboss(block, UI_EMBOSS);
+# uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "use", 0, 0, 0, 0, 0, NULL);
+# }
+
+
+class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel):
+ bl_label = "Layers"
+ bl_options = {'HIDE_HEADER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+ rd = scene.render
+
+ row = layout.row()
+ row.template_list("RENDERLAYER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=2)
+
+ col = row.column(align=True)
+ col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
+ col.operator("scene.render_layer_remove", icon='ZOOMOUT', text="")
+
+ row = layout.row()
+ rl = rd.layers.active
+ if rl:
+ row.prop(rl, "name")
+ row.prop(rd, "use_single_layer", text="", icon_only=True)
+
+
+class RENDERLAYER_PT_layer_options(RenderLayerButtonsPanel, Panel):
+ bl_label = "Layer"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+ rd = scene.render
+ rl = rd.layers.active
+
+ split = layout.split()
+
+ col = split.column()
+ col.prop(scene, "layers", text="Scene")
+ col.label(text="")
+ col.prop(rl, "light_override", text="Light")
+ col.prop(rl, "material_override", text="Material")
+
+ col = split.column()
+ col.prop(rl, "layers", text="Layer")
+ col.label(text="Mask Layers:")
+ col.prop(rl, "layers_zmask", text="")
+
+ layout.separator()
+ layout.label(text="Include:")
+
+ split = layout.split()
+
+ col = split.column()
+ col.prop(rl, "use_zmask")
+ row = col.row()
+ row.prop(rl, "invert_zmask", text="Negate")
+ row.active = rl.use_zmask
+ col.prop(rl, "use_all_z")
+
+ col = split.column()
+ col.prop(rl, "use_solid")
+ col.prop(rl, "use_halo")
+ col.prop(rl, "use_ztransp")
+
+ col = split.column()
+ col.prop(rl, "use_sky")
+ col.prop(rl, "use_edge_enhance")
+ col.prop(rl, "use_strand")
+ if bpy.app.build_options.freestyle:
+ row = col.row()
+ row.prop(rl, "use_freestyle")
+ row.active = rd.use_freestyle
+
+
+class RENDERLAYER_PT_layer_passes(RenderLayerButtonsPanel, Panel):
+ bl_label = "Render Passes"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ def draw_pass_type_buttons(self, box, rl, pass_type):
+ # property names
+ use_pass_type = "use_pass_" + pass_type
+ exclude_pass_type = "exclude_" + pass_type
+ # draw pass type buttons
+ row = box.row()
+ row.prop(rl, use_pass_type)
+ row.prop(rl, exclude_pass_type, text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+ rd = scene.render
+ rl = rd.layers.active
+
+ split = layout.split()
+
+ col = split.column()
+ col.prop(rl, "use_pass_combined")
+ col.prop(rl, "use_pass_z")
+ col.prop(rl, "use_pass_vector")
+ col.prop(rl, "use_pass_normal")
+ col.prop(rl, "use_pass_uv")
+ col.prop(rl, "use_pass_mist")
+ col.prop(rl, "use_pass_object_index")
+ col.prop(rl, "use_pass_material_index")
+ col.prop(rl, "use_pass_color")
+
+ col = split.column()
+ col.prop(rl, "use_pass_diffuse")
+ self.draw_pass_type_buttons(col, rl, "specular")
+ self.draw_pass_type_buttons(col, rl, "shadow")
+ self.draw_pass_type_buttons(col, rl, "emit")
+ self.draw_pass_type_buttons(col, rl, "ambient_occlusion")
+ self.draw_pass_type_buttons(col, rl, "environment")
+ self.draw_pass_type_buttons(col, rl, "indirect")
+ self.draw_pass_type_buttons(col, rl, "reflection")
+ self.draw_pass_type_buttons(col, rl, "refraction")
+
+
+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 518b253d0b0..eed8c84a389 100644
--- a/release/scripts/startup/bl_ui/properties_scene.py
+++ b/release/scripts/startup/bl_ui/properties_scene.py
@@ -18,9 +18,26 @@
# <pep8 compliant>
import bpy
-from bpy.types import Panel
+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,
+ )
+
+
+class SCENE_UL_keying_set_paths(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ # assert(isinstance(item, bpy.types.KeyingSetPath)
+ kspath = item
+ icon = layout.enum_item_icon(kspath, "id_type", kspath.id_type)
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.label(text=kspath.data_path, translate=False, icon_value=icon)
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
class SceneButtonsPanel():
bl_space_type = 'PROPERTIES'
@@ -47,36 +64,6 @@ class SCENE_PT_scene(SceneButtonsPanel, Panel):
layout.prop(scene, "active_clip", text="Active Clip")
-class SCENE_PT_audio(SceneButtonsPanel, Panel):
- bl_label = "Audio"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- rd = context.scene.render
- ffmpeg = rd.ffmpeg
-
- layout.prop(scene, "audio_volume")
- layout.operator("sound.bake_animation")
-
- split = layout.split()
-
- col = split.column()
- col.label("Listener:")
- col.prop(scene, "audio_distance_model", text="")
- col.prop(scene, "audio_doppler_speed", text="Speed")
- col.prop(scene, "audio_doppler_factor", text="Doppler")
-
- col = split.column()
- col.label("Format:")
- col.prop(ffmpeg, "audio_channels", text="")
- col.prop(ffmpeg, "audio_mixrate", text="Rate")
-
- layout.operator("sound.mixdown")
-
-
class SCENE_PT_unit(SceneButtonsPanel, Panel):
bl_label = "Units"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -90,10 +77,10 @@ class SCENE_PT_unit(SceneButtonsPanel, Panel):
col.row().prop(unit, "system", expand=True)
col.row().prop(unit, "system_rotation", expand=True)
- row = layout.row()
- row.active = (unit.system != 'NONE')
- row.prop(unit, "scale_length", text="Scale")
- row.prop(unit, "use_separate")
+ if unit.system != 'NONE':
+ row = layout.row()
+ row.prop(unit, "scale_length", text="Scale")
+ row.prop(unit, "use_separate")
class SCENE_PT_keying_sets(SceneButtonsPanel, Panel):
@@ -107,7 +94,7 @@ class SCENE_PT_keying_sets(SceneButtonsPanel, Panel):
row = layout.row()
col = row.column()
- col.template_list(scene, "keying_sets", scene.keying_sets, "active_index", rows=2)
+ col.template_list("UI_UL_list", "keying_sets", scene, "keying_sets", scene.keying_sets, "active_index", rows=2)
col = row.column(align=True)
col.operator("anim.keying_set_add", icon='ZOOMIN', text="")
@@ -151,7 +138,7 @@ class SCENE_PT_keying_set_paths(SceneButtonsPanel, Panel):
row = layout.row()
col = row.column()
- col.template_list(ks, "paths", ks.paths, "active_index", rows=2)
+ col.template_list("SCENE_UL_keying_set_paths", "", ks, "paths", ks.paths, "active_index", rows=2)
col = row.column(align=True)
col.operator("anim.keying_set_path_add", icon='ZOOMIN', text="")
@@ -186,6 +173,63 @@ class SCENE_PT_keying_set_paths(SceneButtonsPanel, Panel):
col.prop(ksp, "bl_options")
+class SCENE_PT_color_management(SceneButtonsPanel, Panel):
+ bl_label = "Color Management"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+ rd = scene.render
+
+ col = layout.column()
+ col.label(text="Display:")
+ col.prop(scene.display_settings, "display_device")
+
+ col = layout.column()
+ col.separator()
+ col.label(text="Render:")
+ col.template_colormanaged_view_settings(scene, "view_settings")
+
+ col = layout.column()
+ col.separator()
+ col.label(text="Sequencer:")
+ col.prop(scene.sequencer_colorspace_settings, "name")
+
+
+class SCENE_PT_audio(SceneButtonsPanel, Panel):
+ bl_label = "Audio"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+ rd = context.scene.render
+ ffmpeg = rd.ffmpeg
+
+ layout.prop(scene, "audio_volume")
+ layout.operator("sound.bake_animation")
+
+ split = layout.split()
+
+ col = split.column()
+ col.label("Listener:")
+ col.prop(scene, "audio_distance_model", text="")
+ col.prop(scene, "audio_doppler_speed", text="Speed")
+ col.prop(scene, "audio_doppler_factor", text="Doppler")
+
+ col = split.column()
+ col.label("Format:")
+ col.prop(ffmpeg, "audio_channels", text="")
+ col.prop(ffmpeg, "audio_mixrate", text="Rate")
+
+ layout.operator("sound.mixdown")
+
+
class SCENE_PT_physics(SceneButtonsPanel, Panel):
bl_label = "Gravity"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -203,6 +247,88 @@ class SCENE_PT_physics(SceneButtonsPanel, Panel):
layout.prop(scene, "gravity", text="")
+class SCENE_PT_rigid_body_world(SceneButtonsPanel, Panel):
+ bl_label = "Rigid Body World"
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ @classmethod
+ def poll(cls, context):
+ scene = context.scene
+ rd = scene.render
+ return scene and (rd.engine in cls.COMPAT_ENGINES)
+
+ def draw_header(self, context):
+ scene = context.scene
+ rbw = scene.rigidbody_world
+ if rbw is not None:
+ self.layout.prop(rbw, "enabled", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+
+ rbw = scene.rigidbody_world
+
+ if rbw is None:
+ layout.operator("rigidbody.world_add")
+ else:
+ layout.operator("rigidbody.world_remove")
+
+ col = layout.column()
+ col.active = rbw.enabled
+
+ col = col.column()
+ col.prop(rbw, "group")
+ col.prop(rbw, "constraints")
+
+ split = col.split()
+
+ col = split.column()
+ col.prop(rbw, "time_scale", text="Speed")
+ col.prop(rbw, "use_split_impulse")
+
+ col = split.column()
+ col.prop(rbw, "steps_per_second", text="Steps Per Second")
+ col.prop(rbw, "num_solver_iterations", text="Solver Iterations")
+
+
+class SCENE_PT_rigid_body_cache(SceneButtonsPanel, Panel):
+ bl_label = "Rigid Body Cache"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ @classmethod
+ def poll(cls, context):
+ rd = context.scene.render
+ scene = context.scene
+ return scene and scene.rigidbody_world and (rd.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ scene = context.scene
+ rbw = scene.rigidbody_world
+
+ point_cache_ui(self, context, rbw.point_cache, rbw.point_cache.is_baked is False and rbw.enabled, 'RIGID_BODY')
+
+
+class SCENE_PT_rigid_body_field_weights(SceneButtonsPanel, Panel):
+ bl_label = "Rigid Body Field Weights"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ @classmethod
+ def poll(cls, context):
+ rd = context.scene.render
+ scene = context.scene
+ return scene and scene.rigidbody_world and (rd.engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ scene = context.scene
+ rbw = scene.rigidbody_world
+
+ effector_weights_ui(self, context, rbw.effector_weights, 'RIGID_BODY')
+
+
class SCENE_PT_simplify(SceneButtonsPanel, Panel):
bl_label = "Simplify"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -231,34 +357,6 @@ class SCENE_PT_simplify(SceneButtonsPanel, Panel):
col.prop(rd, "simplify_ao_sss", text="AO and SSS")
-class SCENE_PT_color_management(Panel):
- bl_label = "Color Management"
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "scene"
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- rd = scene.render
-
- col = layout.column()
- col.label(text="Display:")
- col.prop(scene.display_settings, "display_device")
-
- col = layout.column()
- col.separator()
- col.label(text="Render:")
- col.template_colormanaged_view_settings(scene, "view_settings")
- col.prop(rd, "use_color_unpremultiply")
-
- col = layout.column()
- col.separator()
- col.label(text="Sequencer:")
- col.prop(scene.sequencer_colorspace_settings, "name")
-
-
class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
_context_path = "scene"
diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py
index e623d034b48..2d064404828 100644
--- a/release/scripts/startup/bl_ui/properties_texture.py
+++ b/release/scripts/startup/bl_ui/properties_texture.py
@@ -18,7 +18,7 @@
# <pep8 compliant>
import bpy
-from bpy.types import Menu, Panel
+from bpy.types import Menu, Panel, UIList
from bpy.types import (Brush,
Lamp,
@@ -30,7 +30,7 @@ from bpy.types import (Brush,
from rna_prop_ui import PropertyPanel
-from bl_ui.properties_paint_common import sculpt_brush_texture_settings
+from bl_ui.properties_paint_common import brush_texture_settings
class TEXTURE_MT_specials(Menu):
@@ -55,6 +55,22 @@ class TEXTURE_MT_envmap_specials(Menu):
layout.operator("texture.envmap_clear", icon='FILE_REFRESH')
layout.operator("texture.envmap_clear_all", icon='FILE_REFRESH')
+
+class TEXTURE_UL_texslots(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ # assert(isinstance(item, bpy.types.MaterialTextureSlot)
+ ma = data
+ slot = item
+ tex = slot.texture if slot else None
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.label(text=tex.name if tex else "", translate=False, icon_value=icon)
+ if tex and isinstance(item, bpy.types.MaterialTextureSlot):
+ layout.prop(ma, "use_textures", text="", index=index)
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
from bl_ui.properties_material import active_node_mat
@@ -142,7 +158,7 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel, Panel):
if tex_collection:
row = layout.row()
- row.template_list(idblock, "texture_slots", idblock, "active_texture_index", rows=2)
+ row.template_list("TEXTURE_UL_texslots", "", idblock, "texture_slots", idblock, "active_texture_index", rows=2)
col = row.column(align=True)
col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
@@ -416,6 +432,12 @@ class TEXTURE_PT_image_sampling(TextureTypePanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
def draw(self, context):
+ if context.scene.render.engine == 'BLENDER_GAME':
+ self.draw_bge(context)
+ else:
+ self.draw_bi(context)
+
+ def draw_bi(self, context):
layout = self.layout
idblock = context_tex_datablock(context)
@@ -426,7 +448,9 @@ class TEXTURE_PT_image_sampling(TextureTypePanel, Panel):
col = split.column()
col.label(text="Alpha:")
- col.prop(tex, "use_alpha", text="Use")
+ row = col.row()
+ row.active = tex.image and tex.image.use_alpha
+ row.prop(tex, "use_alpha", text="Use")
col.prop(tex, "use_calculate_alpha", text="Calculate")
col.prop(tex, "invert_alpha", text="Invert")
col.separator()
@@ -453,6 +477,33 @@ class TEXTURE_PT_image_sampling(TextureTypePanel, Panel):
texture_filter_common(tex, col)
+ def draw_bge(self, context):
+ layout = self.layout
+
+ idblock = context_tex_datablock(context)
+ tex = context.texture
+ slot = getattr(context, "texture_slot", None)
+
+ split = layout.split()
+
+ col = split.column()
+ col.label(text="Alpha:")
+ col.prop(tex, "use_calculate_alpha", text="Calculate")
+ col.prop(tex, "invert_alpha", text="Invert")
+
+ col = split.column()
+
+ #Only for Material based textures, not for Lamp/World...
+ if slot and isinstance(idblock, Material):
+ col.prop(tex, "use_normal_map")
+ row = col.row()
+ row.active = tex.use_normal_map
+ row.prop(slot, "normal_map_space", text="")
+
+ row = col.row()
+ row.active = not tex.use_normal_map
+ row.prop(tex, "use_derivative_map")
+
class TEXTURE_PT_image_mapping(TextureTypePanel, Panel):
bl_label = "Image Mapping"
@@ -869,8 +920,8 @@ class TEXTURE_PT_mapping(TextureSlotPanel, Panel):
split.prop(tex, "object", text="")
if isinstance(idblock, Brush):
- if context.sculpt_object:
- sculpt_brush_texture_settings(layout, idblock)
+ if context.sculpt_object or context.image_paint_object:
+ brush_texture_settings(layout, idblock, context.sculpt_object)
else:
if isinstance(idblock, Material):
split = layout.split(percentage=0.3)
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index cb88226b55a..43761dd439e 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -19,7 +19,24 @@
# <pep8-80 compliant>
import bpy
-from bpy.types import Panel, Header, Menu
+from bpy.types import Panel, Header, Menu, UIList
+from bpy.app.translations import pgettext_iface as iface_
+
+
+class CLIP_UL_tracking_objects(UIList):
+ def draw_item(self, context, layout, data, item, icon,
+ active_data, active_propname, index):
+ # assert(isinstance(item, bpy.types.MovieTrackingObject)
+ tobj = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.label(text=tobj.name, translate=False,
+ icon='CAMERA_DATA' if tobj.is_camera
+ else 'OBJECT_DATA')
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label(text="",
+ icon='CAMERA_DATA' if tobj.is_camera
+ else 'OBJECT_DATA')
class CLIP_HT_header(Header):
@@ -315,14 +332,14 @@ class CLIP_PT_tools_solve(CLIP_PT_tracking_panel, Panel):
col.prop(tracking_object, "keyframe_b")
col = layout.column(align=True)
- col.active = (tracking_object.is_camera and
- not settings.use_tripod_solver)
+ col.active = tracking_object.is_camera
col.label(text="Refine:")
col.prop(settings, "refine_intrinsics", text="")
col = layout.column(align=True)
col.active = not settings.use_tripod_solver
- col.prop(settings, "use_fallback_reconstruction", text="Allow Fallback")
+ col.prop(settings, "use_fallback_reconstruction",
+ text="Allow Fallback")
sub = col.column()
sub.active = settings.use_fallback_reconstruction
sub.prop(settings, "reconstruction_success_threshold")
@@ -471,7 +488,7 @@ class CLIP_PT_objects(CLIP_PT_clip_view_panel, Panel):
tracking = sc.clip.tracking
row = layout.row()
- row.template_list(tracking, "objects",
+ row.template_list("CLIP_UL_tracking_objects", "", tracking, "objects",
tracking, "active_object_index", rows=3)
sub = row.column(align=True)
@@ -728,7 +745,8 @@ class CLIP_PT_stabilization(CLIP_PT_reconstruction_panel, Panel):
layout.active = stab.use_2d_stabilization
row = layout.row()
- row.template_list(stab, "tracks", stab, "active_track_index", rows=3)
+ row.template_list("UI_UL_list", "stabilization_tracks", stab, "tracks",
+ stab, "active_track_index", rows=3)
sub = row.column(align=True)
@@ -861,6 +879,7 @@ class CLIP_PT_tools_clip(CLIP_PT_clip_view_panel, Panel):
bl_space_type = 'CLIP_EDITOR'
bl_region_type = 'TOOLS'
bl_label = "Clip"
+ bl_translation_context = bpy.app.translations.contexts.id_movieclip
def draw(self, context):
layout = self.layout
@@ -893,10 +912,11 @@ class CLIP_MT_view(Menu):
ratios = ((1, 8), (1, 4), (1, 2), (1, 1), (2, 1), (4, 1), (8, 1))
+ text = iface_("Zoom %d:%d")
for a, b in ratios:
- text = "Zoom %d:%d" % (a, b)
layout.operator("clip.view_zoom_ratio",
- text=text).ratio = a / b
+ text=text % (a, b),
+ translate=False).ratio = a / b
else:
if sc.view == 'GRAPH':
layout.operator_context = 'INVOKE_REGION_PREVIEW'
@@ -914,6 +934,7 @@ class CLIP_MT_view(Menu):
class CLIP_MT_clip(Menu):
bl_label = "Clip"
+ bl_translation_context = bpy.app.translations.contexts.id_movieclip
def draw(self, context):
layout = self.layout
diff --git a/release/scripts/startup/bl_ui/space_console.py b/release/scripts/startup/bl_ui/space_console.py
index 23d16c14f2d..70e0fb4fcf2 100644
--- a/release/scripts/startup/bl_ui/space_console.py
+++ b/release/scripts/startup/bl_ui/space_console.py
@@ -80,7 +80,9 @@ class CONSOLE_MT_language(Menu):
languages.sort()
for language in languages:
- layout.operator("console.language", text=language[0].upper() + language[1:]).language = language
+ layout.operator("console.language",
+ text=language.title(),
+ translate=False).language = language
def add_scrollback(text, text_type):
diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py
index 5535070c1c4..8a4529863a9 100644
--- a/release/scripts/startup/bl_ui/space_dopesheet.py
+++ b/release/scripts/startup/bl_ui/space_dopesheet.py
@@ -29,7 +29,6 @@ from bpy.types import Header, Menu
def dopesheet_filter(layout, context, genericFiltersOnly=False):
dopesheet = context.space_data.dopesheet
is_nla = context.area.type == 'NLA_EDITOR'
- is_drivers = (context.area.type == 'GRAPH_EDITOR' and context.space_data.mode == 'DRIVERS')
row = layout.row(align=True)
row.prop(dopesheet, "show_only_selected", text="")
@@ -37,8 +36,7 @@ def dopesheet_filter(layout, context, genericFiltersOnly=False):
if is_nla:
row.prop(dopesheet, "show_missing_nla", text="")
-
- if is_drivers:
+ else: # graph and dopesheet editors - F-Curves and drivers only
row.prop(dopesheet, "show_only_errors", text="")
if not genericFiltersOnly:
@@ -241,6 +239,10 @@ class DOPESHEET_MT_channel(Menu):
layout.operator("anim.channels_delete")
layout.separator()
+ layout.operator("anim.channels_group")
+ layout.operator("anim.channels_ungroup")
+
+ layout.separator()
layout.operator_menu_enum("anim.channels_setting_toggle", "type")
layout.operator_menu_enum("anim.channels_setting_enable", "type")
layout.operator_menu_enum("anim.channels_setting_disable", "type")
@@ -275,8 +277,8 @@ class DOPESHEET_MT_key(Menu):
layout.operator("action.keyframe_insert")
layout.separator()
- layout.operator("action.frame_jump")
-
+ layout.operator("action.frame_jump")
+
layout.separator()
layout.operator("action.duplicate_move")
layout.operator("action.delete")
diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py
index 4cb6538458f..2d0b1c93d13 100644
--- a/release/scripts/startup/bl_ui/space_graph.py
+++ b/release/scripts/startup/bl_ui/space_graph.py
@@ -161,6 +161,10 @@ class GRAPH_MT_channel(Menu):
layout.operator("anim.channels_delete")
layout.separator()
+ layout.operator("anim.channels_group")
+ layout.operator("anim.channels_ungroup")
+
+ layout.separator()
layout.operator_menu_enum("anim.channels_setting_toggle", "type")
layout.operator_menu_enum("anim.channels_setting_enable", "type")
layout.operator_menu_enum("anim.channels_setting_disable", "type")
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 1ea20d96386..b48e7660a6b 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -19,7 +19,8 @@
# <pep8 compliant>
import bpy
from bpy.types import Header, Menu, Panel
-from bl_ui.properties_paint_common import UnifiedPaintPanel
+from bl_ui.properties_paint_common import UnifiedPaintPanel, brush_texture_settings
+from bpy.app.translations import pgettext_iface as iface_
class ImagePaintPanel(UnifiedPaintPanel):
@@ -71,7 +72,7 @@ class IMAGE_MT_view(Menu):
ratios = ((1, 8), (1, 4), (1, 2), (1, 1), (2, 1), (4, 1), (8, 1))
for a, b in ratios:
- layout.operator("image.view_zoom_ratio", text="Zoom" + " %d:%d" % (a, b)).ratio = a / b
+ layout.operator("image.view_zoom_ratio", text=iface_("Zoom %d:%d") % (a, b), translate=False).ratio = a / b
layout.separator()
@@ -146,9 +147,7 @@ class IMAGE_MT_image(Menu):
if not show_render:
layout.separator()
- if ima.packed_file:
- layout.operator("image.unpack")
- else:
+ if not ima.packed_file:
layout.operator("image.pack")
# only for dirty && specific image types, perhaps
@@ -699,7 +698,12 @@ class IMAGE_PT_paint(Panel, ImagePaintPanel):
self.prop_unified_strength(row, context, brush, "use_pressure_strength")
row = col.row(align=True)
- row.prop(brush, "jitter", slider=True)
+ if(brush.use_relative_jitter):
+ row.prop(brush, "use_relative_jitter", text="", icon='LOCKED')
+ row.prop(brush, "jitter", slider=True)
+ else:
+ row.prop(brush, "use_relative_jitter", text="", icon='UNLOCKED')
+ row.prop(brush, "jitter_absolute")
row.prop(brush, "use_pressure_jitter", toggle=True, text="")
col.prop(brush, "blend", text="Blend")
@@ -722,7 +726,8 @@ class IMAGE_PT_tools_brush_texture(BrushButtonsPanel, Panel):
col = layout.column()
col.template_ID_preview(brush, "texture", new="texture.new", rows=3, cols=8)
- col.prop(brush, "use_fixed_texture")
+
+ brush_texture_settings(col, brush, 0)
class IMAGE_PT_tools_brush_tool(BrushButtonsPanel, Panel):
@@ -752,19 +757,34 @@ class IMAGE_PT_paint_stroke(BrushButtonsPanel, Panel):
toolsettings = context.tool_settings.image_paint
brush = toolsettings.brush
+
+ col = layout.column()
+ col.prop(toolsettings, "input_samples")
- layout.prop(brush, "use_airbrush")
- row = layout.row()
+ col.prop(brush, "use_airbrush")
+ row = col.row()
row.active = brush.use_airbrush
row.prop(brush, "rate", slider=True)
- layout.prop(brush, "use_space")
- row = layout.row(align=True)
+ col.separator()
+
+ col.prop(brush, "use_smooth_stroke")
+
+ col = layout.column()
+ col.active = brush.use_smooth_stroke
+ col.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
+ col.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
+
+ col.separator()
+
+ col = layout.column()
+ col.prop(brush, "use_space")
+ row = col.row(align=True)
row.active = brush.use_space
row.prop(brush, "spacing", text="Distance", slider=True)
row.prop(brush, "use_pressure_spacing", toggle=True, text="")
- layout.prop(brush, "use_wrap")
+ col.prop(brush, "use_wrap")
class IMAGE_PT_paint_curve(BrushButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py
index 8df117e27a0..d782bb1b3b9 100644
--- a/release/scripts/startup/bl_ui/space_info.py
+++ b/release/scripts/startup/bl_ui/space_info.py
@@ -65,7 +65,7 @@ class INFO_HT_header(Header):
row = layout.row(align=True)
row.operator("wm.splash", text="", icon='BLENDER', emboss=False)
- row.label(text=scene.statistics())
+ row.label(text=scene.statistics(), translate=False)
# XXX: BEFORE RELEASE, MOVE FILE MENU OUT OF INFO!!!
"""
@@ -112,7 +112,7 @@ class INFO_MT_file(Menu):
layout.separator()
- layout.operator_context = 'EXEC_AREA' if context.blend_data.is_saved else 'INVOKE_AREA'
+ layout.operator_context = 'EXEC_AREA' if context.blend_data.is_saved else 'INVOKE_AREA'
layout.operator("wm.save_mainfile", text="Save", icon='FILE_TICK')
layout.operator_context = 'INVOKE_AREA'
@@ -124,8 +124,9 @@ class INFO_MT_file(Menu):
layout.operator("screen.userpref_show", text="User Preferences...", icon='PREFERENCES')
- layout.operator_context = 'EXEC_AREA'
+ layout.operator_context = 'INVOKE_AREA'
layout.operator("wm.save_homefile", icon='SAVE_PREFS')
+ layout.operator_context = 'EXEC_AREA'
layout.operator("wm.read_factory_settings", icon='LOAD_FACTORY')
layout.separator()
@@ -156,7 +157,7 @@ class INFO_MT_file_import(Menu):
bl_label = "Import"
def draw(self, context):
- if hasattr(bpy.types, "WM_OT_collada_import"):
+ if bpy.app.build_options.collada:
self.layout.operator("wm.collada_import", text="Collada (Default) (.dae)")
@@ -165,7 +166,7 @@ class INFO_MT_file_export(Menu):
bl_label = "Export"
def draw(self, context):
- if hasattr(bpy.types, "WM_OT_collada_export"):
+ if bpy.app.build_options.collada:
self.layout.operator("wm.collada_export", text="Collada (Default) (.dae)")
@@ -361,6 +362,12 @@ class INFO_MT_window(Menu):
layout.operator("wm.window_duplicate")
layout.operator("wm.window_fullscreen_toggle", icon='FULLSCREEN_ENTER')
+
+ layout.separator()
+
+ layout.operator("screen.screenshot").full = True
+ layout.operator("screen.screencast").full = True
+
if sys.platform[:3] == "win":
layout.separator()
layout.operator("wm.console_toggle", icon='CONSOLE')
@@ -373,7 +380,7 @@ class INFO_MT_help(Menu):
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="Release Log", icon='URL').url = "http://www.blender.org/development/release-logs/blender-265"
+ layout.operator("wm.url_open", text="Release Log", icon='URL').url = "http://www.blender.org/development/release-logs/blender-266"
layout.separator()
layout.operator("wm.url_open", text="Blender Website", icon='URL').url = "http://www.blender.org"
diff --git a/release/scripts/startup/bl_ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py
index b15dcb3d07c..49dedaa83c5 100644
--- a/release/scripts/startup/bl_ui/space_nla.py
+++ b/release/scripts/startup/bl_ui/space_nla.py
@@ -167,6 +167,9 @@ class NLA_MT_add(Menu):
layout.separator()
layout.operator("nla.tracks_add").above_selected = False
layout.operator("nla.tracks_add", text="Add Tracks Above Selected").above_selected = True
+
+ layout.separator()
+ layout.operator("nla.selected_objects_add")
class NLA_MT_edit_transform(Menu):
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index c46b1c20738..e739c5ea5d4 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -44,8 +44,8 @@ class NODE_HT_header(Header):
row.menu("NODE_MT_node")
layout.prop(snode, "tree_type", text="", expand=True)
-
- if snode.tree_type == 'SHADER':
+
+ if snode.tree_type == 'ShaderNodeTree':
if scene.render.use_shading_nodes:
layout.prop(snode, "shader_type", text="", expand=True)
@@ -65,7 +65,7 @@ class NODE_HT_header(Header):
if snode_id:
layout.prop(snode_id, "use_nodes")
- elif snode.tree_type == 'TEXTURE':
+ elif snode.tree_type == 'TextureNodeTree':
layout.prop(snode, "texture_type", text="", expand=True)
if id_from:
@@ -76,7 +76,7 @@ class NODE_HT_header(Header):
if snode_id:
layout.prop(snode_id, "use_nodes")
- elif snode.tree_type == 'COMPOSITING':
+ elif snode.tree_type == 'CompositorNodeTree':
layout.prop(snode_id, "use_nodes")
layout.prop(snode_id.render, "use_free_unused_nodes", text="Free Unused")
layout.prop(snode, "show_backdrop")
@@ -84,6 +84,13 @@ class NODE_HT_header(Header):
row = layout.row(align=True)
row.prop(snode, "backdrop_channels", text="", expand=True)
layout.prop(snode, "use_auto_render")
+
+ else:
+ # Custom node tree is edited as independent ID block
+ layout.template_ID(snode, "node_tree", new="node.new_node_tree")
+
+ layout.prop(snode, "pin", text="")
+ layout.operator("node.tree_path_parent", text="", icon='FILE_PARENT')
layout.separator()
@@ -182,6 +189,7 @@ class NODE_MT_node(Menu):
layout.operator("node.group_edit")
layout.operator("node.group_ungroup")
layout.operator("node.group_make")
+ layout.operator("node.group_insert")
layout.separator()
@@ -208,7 +216,7 @@ class NODE_PT_properties(Panel):
@classmethod
def poll(cls, context):
snode = context.space_data
- return snode.tree_type == 'COMPOSITING'
+ return snode.tree_type == 'CompositorNodeTree'
def draw_header(self, context):
snode = context.space_data
@@ -237,7 +245,7 @@ class NODE_PT_quality(bpy.types.Panel):
@classmethod
def poll(cls, context):
snode = context.space_data
- return snode.tree_type == 'COMPOSITING' and snode.node_tree is not None
+ return snode.tree_type == 'CompositorNodeTree' and snode.node_tree is not None
def draw(self, context):
layout = self.layout
@@ -252,7 +260,9 @@ class NODE_PT_quality(bpy.types.Panel):
col = layout.column()
col.prop(tree, "use_opencl")
+ col.prop(tree, "use_groupnode_buffer")
col.prop(tree, "two_pass")
+ col.prop(tree, "use_viewer_border")
col.prop(snode, "show_highlight")
col.prop(snode, "use_hidden_preview")
@@ -274,5 +284,28 @@ class NODE_MT_node_color_specials(Menu):
layout.operator("node.node_copy_color", icon='COPY_ID')
+class NODE_UL_interface_sockets(bpy.types.UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ socket = item
+ color = socket.draw_color(context)
+
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ row = layout.row(align=True)
+
+ # inputs get icon on the left
+ if socket.in_out == 'IN':
+ row.template_node_socket(color)
+
+ row.label(text=socket.name, icon_value=icon)
+
+ # outputs get icon on the right
+ if socket.in_out == 'OUT':
+ row.template_node_socket(color)
+
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.template_node_socket(color)
+
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index fdfd43157c7..aa445b9500d 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -19,6 +19,7 @@
# <pep8 compliant>
import bpy
from bpy.types import Header, Menu, Panel
+from bpy.app.translations import pgettext_iface as iface_
def act_strip(context):
@@ -88,6 +89,7 @@ class SEQUENCER_HT_header(Header):
layout.separator()
layout.operator("sequencer.refresh_all")
+ layout.prop(st, "preview_channels", expand=True, text="")
layout.prop(st, "display_channel", text="Channel")
ed = context.scene.sequence_editor
@@ -422,23 +424,25 @@ class SEQUENCER_PT_edit(SequencerButtonsPanel, Panel):
col = layout.column(align=True)
row = col.row()
- row.label(text="Final Length" + ": %s" % bpy.utils.smpte_from_frame(strip.frame_final_duration))
+ row.label(text=iface_("Final Length: %s") % bpy.utils.smpte_from_frame(strip.frame_final_duration),
+ translate=False)
row = col.row()
row.active = (frame_current >= strip.frame_start and frame_current <= strip.frame_start + strip.frame_duration)
- row.label(text="Playhead" + ": %d" % (frame_current - strip.frame_start))
+ row.label(text=iface_("Playhead: %d") % (frame_current - strip.frame_start), translate=False)
- col.label(text="Frame Offset" + " %d:%d" % (strip.frame_offset_start, strip.frame_offset_end))
- col.label(text="Frame Still" + " %d:%d" % (strip.frame_still_start, strip.frame_still_end))
+ col.label(text=iface_("Frame Offset %d:%d") % (strip.frame_offset_start, strip.frame_offset_end),
+ translate=False)
+ col.label(text=iface_("Frame Still %d:%d") % (strip.frame_still_start, strip.frame_still_end), translate=False)
elem = False
if strip.type == 'IMAGE':
- elem = strip.getStripElem(frame_current)
+ elem = strip.strip_elem_from_frame(frame_current)
elif strip.type == 'MOVIE':
elem = strip.elements[0]
if elem and elem.orig_width > 0 and elem.orig_height > 0:
- col.label(text="Original Dimension" + ": %dx%d" % (elem.orig_width, elem.orig_height))
+ col.label(text=iface_("Original Dimension: %dx%d") % (elem.orig_width, elem.orig_height), translate=False)
else:
col.label(text="Original Dimension: None")
@@ -595,13 +599,14 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
# Current element for the filename
- elem = strip.getStripElem(context.scene.frame_current)
+ elem = strip.strip_elem_from_frame(context.scene.frame_current)
if elem:
split = layout.split(percentage=0.2)
split.label(text="File:")
split.prop(elem, "filename", text="") # strip.elements[0] could be a fallback
layout.prop(strip.colorspace_settings, "name")
+ layout.prop(strip, "alpha_mode")
layout.operator("sequencer.change_path")
@@ -714,7 +719,7 @@ class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel):
if scene:
sta = scene.frame_start
end = scene.frame_end
- layout.label(text="Original frame range" + ": %d-%d (%d)" % (sta, end, end - sta + 1))
+ layout.label(text=iface_("Original frame range: %d-%d (%d)") % (sta, end, end - sta + 1), translate=False)
class SEQUENCER_PT_mask(SequencerButtonsPanel, Panel):
@@ -743,7 +748,7 @@ class SEQUENCER_PT_mask(SequencerButtonsPanel, Panel):
if mask:
sta = mask.frame_start
end = mask.frame_end
- layout.label(text="Original frame range" + ": %d-%d (%d)" % (sta, end, end - sta + 1))
+ layout.label(text=iface_("Original frame range: %d-%d (%d)") % (sta, end, end - sta + 1), translate=False)
class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel):
@@ -797,7 +802,6 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel):
col.label(text="Colors:")
col.prop(strip, "color_saturation", text="Saturation")
col.prop(strip, "color_multiply", text="Multiply")
- col.prop(strip, "use_premultiply")
col.prop(strip, "use_float")
@@ -867,6 +871,10 @@ class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, Panel):
#col.active = render.use_sequencer_gl_preview
col.prop(render, "sequencer_gl_preview", text="")
+ row = col.row()
+ row.active = render.sequencer_gl_preview == 'SOLID'
+ row.prop(render, "use_sequencer_gl_textured_solid")
+
class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel):
bl_label = "View Settings"
diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py
index fa8752c21be..4264fc95cea 100644
--- a/release/scripts/startup/bl_ui/space_text.py
+++ b/release/scripts/startup/bl_ui/space_text.py
@@ -19,6 +19,7 @@
# <pep8-80 compliant>
import bpy
from bpy.types import Header, Menu, Panel
+from bpy.app.translations import pgettext_iface as iface_
class TEXT_HT_header(Header):
@@ -66,16 +67,17 @@ class TEXT_HT_header(Header):
row.operator("text.run_script")
row = layout.row()
+ row.active = text.name.endswith(".py")
row.prop(text, "use_module")
row = layout.row()
if text.filepath:
if text.is_dirty:
- row.label(text="File" + ": *%r " %
- text.filepath + "(unsaved)")
+ row.label(text=iface_("File: *%r (unsaved)") %
+ text.filepath, translate=False)
else:
- row.label(text="File" + ": %r" %
- text.filepath)
+ row.label(text=iface_("File: %r") %
+ text.filepath, translate=False)
else:
row.label(text="Text: External"
if text.library
@@ -151,7 +153,7 @@ class TEXT_MT_view(Menu):
layout = self.layout
layout.operator("text.properties", icon='MENU_PANEL')
-
+
layout.separator()
layout.operator("text.move",
@@ -193,16 +195,35 @@ class TEXT_MT_text(Menu):
layout.operator("text.run_script")
-class TEXT_MT_templates(Menu):
- bl_label = "Templates"
+class TEXT_MT_templates_py(Menu):
+ bl_label = "Python"
def draw(self, context):
- self.path_menu(bpy.utils.script_paths("templates"),
+ self.path_menu(bpy.utils.script_paths("templates_py"),
"text.open",
{"internal": True},
)
+class TEXT_MT_templates_osl(Menu):
+ bl_label = "Open Shading Language"
+
+ def draw(self, context):
+ self.path_menu(bpy.utils.script_paths("templates_osl"),
+ "text.open",
+ {"internal": True},
+ )
+
+
+class TEXT_MT_templates(Menu):
+ bl_label = "Templates"
+
+ def draw(self, context):
+ layout = self.layout
+ layout.menu("TEXT_MT_templates_py")
+ layout.menu("TEXT_MT_templates_osl")
+
+
class TEXT_MT_edit_select(Menu):
bl_label = "Select"
@@ -281,6 +302,7 @@ class TEXT_MT_edit(Menu):
layout.operator("text.jump")
layout.operator("text.properties", text="Find...")
+ layout.operator("text.autocomplete")
layout.separator()
diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py
index cb9e2444793..6af9f377237 100644
--- a/release/scripts/startup/bl_ui/space_time.py
+++ b/release/scripts/startup/bl_ui/space_time.py
@@ -152,6 +152,7 @@ class TIME_MT_cache(Menu):
col.prop(st, "cache_cloth")
col.prop(st, "cache_smoke")
col.prop(st, "cache_dynamicpaint")
+ col.prop(st, "cache_rigidbody")
class TIME_MT_frame(Menu):
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 0bb25e98456..2742e6d8155 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -19,7 +19,28 @@
# <pep8 compliant>
import bpy
from bpy.types import Header, Menu, Panel
-import os
+from bpy.app.translations import pgettext_iface as iface_
+
+
+def ui_style_items(col, context):
+ """ UI Style settings """
+
+ split = col.split()
+
+ col = split.column()
+ col.label(text="Kerning Style:")
+ col.row().prop(context, "font_kerning_style", expand=True)
+ col.prop(context, "points")
+
+ col = split.column()
+ col.label(text="Shadow Offset:")
+ col.prop(context, "shadow_offset_x", text="X")
+ col.prop(context, "shadow_offset_y", text="Y")
+
+ col = split.column()
+ col.prop(context, "shadow")
+ col.prop(context, "shadowalpha")
+ col.prop(context, "shadowcolor")
def ui_items_general(col, context):
@@ -84,7 +105,7 @@ class USERPREF_HT_header(Header):
userpref = context.user_preferences
layout.operator_context = 'EXEC_AREA'
- layout.operator("wm.save_homefile", text="Save As Default")
+ layout.operator("wm.save_userpref")
layout.operator_context = 'INVOKE_DEFAULT'
@@ -162,6 +183,7 @@ class USERPREF_PT_interface(Panel):
return (userpref.active_section == 'INTERFACE')
def draw(self, context):
+ import sys
layout = self.layout
userpref = context.user_preferences
@@ -247,7 +269,7 @@ class USERPREF_PT_interface(Panel):
col.prop(view, "show_splash")
- if os.name == "nt":
+ if sys.platform[:3] == "win":
col.prop(view, "use_quit_dialog")
@@ -382,6 +404,7 @@ class USERPREF_PT_system(Panel):
return (userpref.active_section == 'SYSTEM')
def draw(self, context):
+ import sys
layout = self.layout
userpref = context.user_preferences
@@ -445,6 +468,10 @@ class USERPREF_PT_system(Panel):
col.label(text="Window Draw Method:")
col.prop(system, "window_draw_method", text="")
col.prop(system, "multi_sample", text="")
+ if sys.platform == "linux" and system.multi_sample != 'NONE':
+ col.label(text="Might fail for Mesh editing selection!")
+ col.separator()
+ col.prop(system, "use_region_overlap")
col.label(text="Text Draw Options:")
col.prop(system, "use_text_antialiasing")
col.label(text="Textures:")
@@ -453,6 +480,10 @@ class USERPREF_PT_system(Panel):
col.prop(system, "texture_collection_rate", text="Collection Rate")
col.separator()
+
+ col.label(text="Images:")
+ col.prop(system, "image_gpubuffer_limit")
+
col.separator()
col.separator()
@@ -491,15 +522,17 @@ class USERPREF_PT_system(Panel):
sub.active = system.use_weight_color_range
sub.template_color_ramp(system, "weight_color_range", expand=True)
- column.separator()
-
- column.prop(system, "use_international_fonts")
- if system.use_international_fonts:
- column.prop(system, "language")
- row = column.row()
- row.label(text="Translate:")
- row.prop(system, "use_translate_interface", text="Interface")
- row.prop(system, "use_translate_tooltips", text="Tooltips")
+ if bpy.app.build_options.international:
+ column.separator()
+ column.prop(system, "use_international_fonts")
+ if system.use_international_fonts:
+ column.prop(system, "language")
+ row = column.row()
+ row.label(text="Translate:", text_ctxt=bpy.app.translations.contexts.id_windowmanager)
+ row = column.row(True)
+ row.prop(system, "use_translate_interface", text="Interface", toggle=True)
+ row.prop(system, "use_translate_tooltips", text="Tooltips", toggle=True)
+ row.prop(system, "use_translate_new_dataname", text="New Data", toggle=True)
class USERPREF_MT_interface_theme_presets(Menu):
@@ -685,7 +718,8 @@ class USERPREF_PT_theme(Panel):
col.separator()
ui = theme.user_interface
- col.label("Icons:")
+
+ col.label("Menu Shadow:")
row = col.row()
@@ -694,20 +728,19 @@ class USERPREF_PT_theme(Panel):
padding = subsplit.split(percentage=0.15)
colsub = padding.column()
colsub = padding.column()
- colsub.row().prop(ui, "icon_file")
+ colsub.row().prop(ui, "menu_shadow_fac")
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, "menu_shadow_width")
col.separator()
col.separator()
- ui = theme.user_interface.panel
- col.label("Panels:")
+ col.label("Icons:")
row = col.row()
@@ -716,16 +749,15 @@ class USERPREF_PT_theme(Panel):
padding = subsplit.split(percentage=0.15)
colsub = padding.column()
colsub = padding.column()
- rowsub = colsub.row()
- rowsub.prop(ui, "show_header")
- rowsub.label()
+ colsub.active = False
+ colsub.row().prop(ui, "icon_file")
subsplit = row.split(percentage=0.85)
padding = subsplit.split(percentage=0.15)
colsub = padding.column()
colsub = padding.column()
- colsub.row().prop(ui, "header")
+ colsub.row().prop(ui, "icon_alpha")
col.separator()
col.separator()
@@ -743,20 +775,20 @@ class USERPREF_PT_theme(Panel):
colsub.row().prop(ui, "axis_x")
colsub.row().prop(ui, "axis_y")
colsub.row().prop(ui, "axis_z")
-
+
subsplit = row.split(percentage=0.85)
padding = subsplit.split(percentage=0.15)
colsub = padding.column()
colsub = padding.column()
-
+
layout.separator()
layout.separator()
elif theme.theme_area == 'BONE_COLOR_SETS':
col = split.column()
for i, ui in enumerate(theme.bone_color_sets):
- col.label(text="Color Set" + " %d:" % (i + 1)) # i starts from 0
+ col.label(text=iface_("Color Set %d:") % (i + 1), translate=False) # i starts from 0
row = col.row()
@@ -775,6 +807,28 @@ class USERPREF_PT_theme(Panel):
colsub = padding.column()
colsub = padding.column()
colsub.row().prop(ui, "show_colored_constraints")
+ elif theme.theme_area == 'STYLE':
+ col = split.column()
+
+ style = context.user_preferences.ui_styles[0]
+
+ ui = style.panel_title
+ col.label(text="Panel Title:")
+ ui_style_items(col, ui)
+
+ col.separator()
+ col.separator()
+
+ ui = style.widget
+ col.label(text="Widget:")
+ ui_style_items(col, ui)
+
+ col.separator()
+ col.separator()
+
+ ui = style.widget_label
+ col.label(text="Widget Label:")
+ ui_style_items(col, ui)
else:
self._theme_generic(split, getattr(theme, theme.theme_area.lower()))
@@ -855,6 +909,7 @@ class USERPREF_PT_file(Panel):
col.prop(paths, "recent_files")
col.prop(paths, "use_save_preview_images")
col.label(text="Auto Save:")
+ col.prop(paths, "use_keep_session")
col.prop(paths, "use_auto_save_temporary_files")
sub = col.column()
sub.active = paths.use_auto_save_temporary_files
@@ -920,6 +975,8 @@ class USERPREF_PT_input(Panel, InputKeyMapPanel):
return (userpref.active_section == 'INPUT')
def draw_input_prefs(self, inputs, layout):
+ import sys
+
# General settings
row = layout.row()
col = row.column()
@@ -972,6 +1029,11 @@ class USERPREF_PT_input(Panel, InputKeyMapPanel):
sub.prop(inputs, "invert_zoom_wheel", text="Invert Wheel Zoom Direction")
#sub.prop(view, "wheel_scroll_lines", text="Scroll Lines")
+ if sys.platform == "darwin":
+ sub = col.column()
+ sub.label(text="Trackpad:")
+ sub.prop(inputs, "use_trackpad_natural")
+
col.separator()
sub = col.column()
sub.label(text="NDOF Device:")
@@ -1034,6 +1096,8 @@ class USERPREF_PT_addons(Panel):
@staticmethod
def is_user_addon(mod, user_addon_paths):
+ import os
+
if not user_addon_paths:
for path in (bpy.utils.script_path_user(),
bpy.utils.script_path_pref()):
@@ -1056,6 +1120,7 @@ class USERPREF_PT_addons(Panel):
box.label(l)
def draw(self, context):
+ import os
import addon_utils
layout = self.layout
@@ -1064,8 +1129,8 @@ class USERPREF_PT_addons(Panel):
used_ext = {ext.module for ext in userpref.addons}
userpref_addons_folder = os.path.join(userpref.filepaths.script_directory, "addons")
- scripts_addons_folder = bpy.utils.user_resource('SCRIPTS', "addons")
-
+ scripts_addons_folder = bpy.utils.user_resource('SCRIPTS', "addons")
+
# collect the categories that can be filtered on
addons = [(mod, addon_utils.module_bl_info(mod)) for mod in addon_utils.modules(addon_utils.addons_fake_modules)]
@@ -1116,7 +1181,7 @@ class USERPREF_PT_addons(Panel):
(filter == "Enabled" and is_enabled) or
(filter == "Disabled" and not is_enabled) or
(filter == "User" and (mod.__file__.startswith((scripts_addons_folder, userpref_addons_folder))))
- ):
+ ):
if search and search not in info["name"].lower():
if info["author"]:
@@ -1126,7 +1191,8 @@ class USERPREF_PT_addons(Panel):
continue
# Addon UI Code
- box = col.column().box()
+ col_box = col.column()
+ box = col_box.box()
colsub = box.column()
row = colsub.row()
@@ -1159,15 +1225,15 @@ class USERPREF_PT_addons(Panel):
if mod:
split = colsub.row().split(percentage=0.15)
split.label(text="File:")
- split.label(text=mod.__file__)
+ split.label(text=mod.__file__, translate=False)
if info["author"]:
split = colsub.row().split(percentage=0.15)
split.label(text="Author:")
- split.label(text=info["author"])
+ split.label(text=info["author"], translate=False)
if info["version"]:
split = colsub.row().split(percentage=0.15)
split.label(text="Version:")
- split.label(text='.'.join(str(x) for x in info["version"]))
+ split.label(text='.'.join(str(x) for x in info["version"]), translate=False)
if info["warning"]:
split = colsub.row().split(percentage=0.15)
split.label(text="Warning:")
@@ -1180,7 +1246,7 @@ class USERPREF_PT_addons(Panel):
split = colsub.row().split(percentage=0.15)
split.label(text="Internet:")
if info["wiki_url"]:
- split.operator("wm.url_open", text="Link to the Wiki", icon='HELP').url = info["wiki_url"]
+ split.operator("wm.url_open", text="Documentation", icon='HELP').url = info["wiki_url"]
if info["tracker_url"]:
split.operator("wm.url_open", text="Report a Bug", icon='URL').url = info["tracker_url"]
if user_addon:
@@ -1189,6 +1255,24 @@ class USERPREF_PT_addons(Panel):
for i in range(4 - tot_row):
split.separator()
+ # Show addon user preferences
+ if is_enabled:
+ addon_preferences = userpref.addons[module_name].preferences
+ if addon_preferences is not None:
+ draw = getattr(addon_preferences, "draw", None)
+ if draw is not None:
+ addon_preferences_class = type(addon_preferences)
+ box_prefs = col_box.box()
+ box_prefs.label("Preferences:")
+ addon_preferences_class.layout = box_prefs
+ try:
+ draw(context)
+ except:
+ import traceback
+ traceback.print_exc()
+ box_prefs.label(text="Error (see console)", icon='ERROR')
+ del addon_preferences_class.layout
+
# Append missing scripts
# First collect scripts that are used but have no script file.
module_names = {mod.__name__ for mod, info in addons}
@@ -1206,7 +1290,7 @@ class USERPREF_PT_addons(Panel):
colsub = box.column()
row = colsub.row()
- row.label(text=module_name, icon='ERROR')
+ row.label(text=module_name, translate=False, icon='ERROR')
if is_enabled:
row.operator("wm.addon_disable", icon='CHECKBOX_HLT', text="", emboss=False).module = module_name
diff --git a/release/scripts/startup/bl_ui/space_userpref_keymap.py b/release/scripts/startup/bl_ui/space_userpref_keymap.py
index 81d67aa662c..4c634378ed2 100644
--- a/release/scripts/startup/bl_ui/space_userpref_keymap.py
+++ b/release/scripts/startup/bl_ui/space_userpref_keymap.py
@@ -19,6 +19,7 @@
# <pep8 compliant>
import bpy
from bpy.types import Menu
+from bpy.app.translations import pgettext_iface as iface_
class USERPREF_MT_keyconfigs(Menu):
@@ -97,7 +98,7 @@ class InputKeyMapPanel:
subcol = self.indented_layout(col, level + 1)
subrow = subcol.row()
subrow.prop(km, "show_expanded_items", text="", emboss=False)
- subrow.label(text="%s " % km.name + "(Global)")
+ subrow.label(text=iface_("%s (Global)") % km.name, translate=False)
else:
km.show_expanded_items = True
@@ -172,17 +173,17 @@ class InputKeyMapPanel:
if kmi.show_expanded:
box = col.box()
- if map_type not in {'TEXTINPUT', 'TIMER'}:
- split = box.split(percentage=0.4)
- sub = split.row()
+ split = box.split(percentage=0.4)
+ sub = split.row()
- if km.is_modal:
- sub.prop(kmi, "propvalue", text="")
- else:
- # One day...
- #~ sub.prop_search(kmi, "idname", bpy.context.window_manager, "operators_all", text="")
- sub.prop(kmi, "idname", text="")
+ if km.is_modal:
+ sub.prop(kmi, "propvalue", text="")
+ else:
+ # One day...
+ #~ sub.prop_search(kmi, "idname", bpy.context.window_manager, "operators_all", text="")
+ sub.prop(kmi, "idname", text="")
+ if map_type not in {'TEXTINPUT', 'TIMER'}:
sub = split.column()
subrow = sub.row(align=True)
@@ -212,14 +213,101 @@ class InputKeyMapPanel:
self.draw_km(display_keymaps, kc, kmm, None, layout, level + 1)
layout.context_pointer_set("keymap", km)
- def draw_filtered(self, display_keymaps, filter_text, layout):
+ _EVENT_TYPES = set()
+ _EVENT_TYPE_MAP = {}
+
+ def draw_filtered(self, display_keymaps, filter_type, filter_text, layout):
+
+ if filter_type == 'NAME':
+ def filter_func(kmi):
+ return (filter_text in kmi.idname.lower() or
+ filter_text in kmi.name.lower())
+ else:
+ if not self._EVENT_TYPES:
+ enum = bpy.types.Event.bl_rna.properties["type"].enum_items
+ self._EVENT_TYPES.update(enum.keys())
+ self._EVENT_TYPE_MAP.update({item.name.replace(" ", "_").upper(): key for key, item in enum.items()})
+
+ del enum
+ self._EVENT_TYPE_MAP.update({
+ "`": 'ACCENT_GRAVE',
+ "*": 'NUMPAD_ASTERIX',
+ "/": 'NUMPAD_SLASH',
+ "RMB": 'RIGHTMOUSE',
+ "LMB": 'LEFTMOUSE',
+ "MMB": 'MIDDLEMOUSE',
+ })
+ self._EVENT_TYPE_MAP.update({
+ "%d" % i: "NUMPAD_%d" % i for i in range(9)
+ })
+ # done with once off init
+
+ filter_text_split = filter_text.strip()
+ filter_text_split = filter_text.split()
+
+ # Modifier {kmi.attribute: name} mapping
+ key_mod = {
+ "ctrl": "ctrl",
+ "alt": "alt",
+ "shift": "shift",
+ "cmd": "oskey",
+ "oskey": "oskey",
+ "any": "any",
+ }
+ # KeyMapItem like dict, use for comparing against
+ # attr: state
+ kmi_test_dict = {}
+
+ # initialize? - so if a if a kmi has a MOD assigned it wont show up.
+ #~ for kv in key_mod.values():
+ #~ kmi_test_dict[kv] = False
+
+ # altname: attr
+ for kk, kv in key_mod.items():
+ if kk in filter_text_split:
+ filter_text_split.remove(kk)
+ kmi_test_dict[kv] = True
+ # whats left should be the event type
+ if len(filter_text_split) > 1:
+ return False
+ elif filter_text_split:
+ kmi_type = filter_text_split[0].upper()
+
+ if kmi_type not in self._EVENT_TYPES:
+ # replacement table
+ kmi_type_test = self._EVENT_TYPE_MAP.get(kmi_type)
+ if kmi_type_test is None:
+ # print("Unknown Type:", kmi_type)
+
+ # Partial match
+ for k, v in self._EVENT_TYPE_MAP.items():
+ if kmi_type in k:
+ kmi_type_test = v
+ break
+ if kmi_type in v:
+ kmi_type_test = v
+ break
+
+ if kmi_type_test is None:
+ return False
+
+ kmi_type = kmi_type_test
+ del kmi_type_test
+
+ kmi_test_dict["type"] = kmi_type
+
+ # main filter func, runs many times
+ def filter_func(kmi):
+ for kk, ki in kmi_test_dict.items():
+ if getattr(kmi, kk) != ki:
+ return False
+ return True
+
for km, kc in display_keymaps:
km = km.active()
layout.context_pointer_set("keymap", km)
- filtered_items = [kmi for kmi in km.keymap_items
- if (filter_text in kmi.idname.lower() or
- filter_text in kmi.name.lower())]
+ filtered_items = [kmi for kmi in km.keymap_items if filter_func(kmi)]
if filtered_items:
col = layout.column()
@@ -242,6 +330,7 @@ class InputKeyMapPanel:
col = self.indented_layout(layout, 1)
subcol = col.split(percentage=0.2).column()
subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN')
+ return True
def draw_hierarchy(self, display_keymaps, layout):
from bpy_extras import keyconfig_utils
@@ -253,6 +342,7 @@ class InputKeyMapPanel:
wm = context.window_manager
kc = wm.keyconfigs.user
+ spref = context.space_data
col = layout.column()
sub = col.column()
@@ -263,7 +353,7 @@ class InputKeyMapPanel:
row = subcol.row(align=True)
#~ row.prop_search(wm.keyconfigs, "active", wm, "keyconfigs", text="Key Config:")
- text = bpy.path.display_name(context.window_manager.keyconfigs.active.name)
+ text = bpy.path.display_name(wm.keyconfigs.active.name)
if not text:
text = "Blender (default)"
row.menu("USERPREF_MT_keyconfigs", text=text)
@@ -272,17 +362,27 @@ class InputKeyMapPanel:
#~ layout.context_pointer_set("keyconfig", wm.keyconfigs.active)
#~ row.operator("wm.keyconfig_remove", text="", icon='X')
-
- row.prop(context.space_data, "filter_text", icon='VIEWZOOM')
+ row.separator()
+ rowsub = row.split(align=True, percentage=0.33)
+ # postpone drawing into rowsub, so we can set alert!
col.separator()
-
display_keymaps = keyconfig_utils.keyconfig_merge(kc, kc)
- if context.space_data.filter_text != "":
- filter_text = context.space_data.filter_text.lower()
- self.draw_filtered(display_keymaps, filter_text, col)
+ filter_type = spref.filter_type
+ filter_text = spref.filter_text.strip()
+ if filter_text:
+ filter_text = filter_text.lower()
+ ok = self.draw_filtered(display_keymaps, filter_type, filter_text, col)
else:
self.draw_hierarchy(display_keymaps, col)
+ ok = True
+
+ # go back and fill in rowsub
+ rowsub.prop(spref, "filter_type", text="")
+ rowsubsub = rowsub.row(align=True)
+ if not ok:
+ rowsubsub.alert = True
+ rowsubsub.prop(spref, "filter_text", text="", icon='VIEWZOOM')
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index b1dfc397ce0..08c161f65d8 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -44,7 +44,13 @@ class VIEW3D_HT_header(Header):
sub.menu("VIEW3D_MT_view")
# Select Menu
- if mode_string not in {'EDIT_TEXT', 'SCULPT', 'PAINT_WEIGHT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}:
+ if mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}:
+ mesh = obj.data
+ if mesh.use_paint_mask:
+ sub.menu("VIEW3D_MT_select_paint_mask")
+ elif mesh.use_paint_mask_vertex and mode_string == 'PAINT_WEIGHT':
+ sub.menu("VIEW3D_MT_select_paint_mask_vertex")
+ elif mode_string not in {'EDIT_TEXT', 'SCULPT'}:
sub.menu("VIEW3D_MT_select_%s" % mode_string.lower())
if edit_object:
@@ -70,7 +76,8 @@ class VIEW3D_HT_header(Header):
row.prop(toolsettings.particle_edit, "select_mode", text="", expand=True)
# Occlude geometry
- if view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'} and (mode == 'PARTICLE_EDIT' or (mode == 'EDIT' and obj.type == 'MESH')):
+ if ((view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'} and (mode == 'PARTICLE_EDIT' or (mode == 'EDIT' and obj.type == 'MESH'))) or
+ (mode == 'WEIGHT_PAINT')):
row.prop(view, "use_occlude_geometry", text="")
# Proportional editing
@@ -104,6 +111,11 @@ class VIEW3D_HT_header(Header):
elif snap_element == 'FACE':
row.prop(toolsettings, "use_snap_project", text="")
+ # AutoMerge editing
+ if obj:
+ if (mode == 'EDIT' and obj.type == 'MESH'):
+ layout.prop(toolsettings, "use_mesh_automerge", text="", icon='AUTOMERGE_ON')
+
# OpenGL render
row = layout.row(align=True)
row.operator("render.opengl", text="", icon='RENDER_STILL')
@@ -202,7 +214,7 @@ class VIEW3D_MT_transform_object(VIEW3D_MT_transform_base):
layout.operator("object.origin_set", text="Geometry to Origin").type = 'GEOMETRY_ORIGIN'
layout.operator("object.origin_set", text="Origin to Geometry").type = 'ORIGIN_GEOMETRY'
layout.operator("object.origin_set", text="Origin to 3D Cursor").type = 'ORIGIN_CURSOR'
-
+ layout.operator("object.origin_set", text="Origin to Center of Mass").type = 'ORIGIN_CENTER_OF_MASS'
layout.separator()
layout.operator("object.randomize_transform")
@@ -573,6 +585,7 @@ class VIEW3D_MT_select_edit_mesh(Menu):
layout.separator()
+ layout.operator("mesh.select_ungrouped", text="Ungrouped Verts")
layout.operator("mesh.select_random", text="Random")
layout.operator("mesh.select_nth")
layout.operator("mesh.edges_select_sharp", text="Sharp Edges")
@@ -622,7 +635,7 @@ class VIEW3D_MT_select_edit_curve(Menu):
layout.operator("curve.select_all").action = 'TOGGLE'
layout.operator("curve.select_all", text="Inverse").action = 'INVERT'
layout.operator("curve.select_random")
- layout.operator("curve.select_nth", text="Every Nth Number of Points")
+ layout.operator("curve.select_nth")
layout.operator("curve.select_linked", text="Select Linked")
layout.separator()
@@ -652,7 +665,7 @@ class VIEW3D_MT_select_edit_surface(Menu):
layout.operator("curve.select_all").action = 'TOGGLE'
layout.operator("curve.select_all", text="Inverse").action = 'INVERT'
layout.operator("curve.select_random")
- layout.operator("curve.select_nth", text="Every Nth Number of Points")
+ layout.operator("curve.select_nth")
layout.operator("curve.select_linked", text="Select Linked")
layout.separator()
@@ -672,6 +685,7 @@ class VIEW3D_MT_select_edit_metaball(Menu):
layout = self.layout
layout.operator("view3d.select_border")
+ layout.operator("view3d.select_circle")
layout.separator()
@@ -696,6 +710,10 @@ class VIEW3D_MT_select_edit_lattice(Menu):
layout.operator("lattice.select_all").action = 'TOGGLE'
layout.operator("lattice.select_all", text="Inverse").action = 'INVERT'
+ layout.separator()
+
+ layout.operator("lattice.select_ungrouped", text="Ungrouped Verts")
+
class VIEW3D_MT_select_edit_armature(Menu):
bl_label = "Select"
@@ -729,15 +747,43 @@ class VIEW3D_MT_select_edit_armature(Menu):
layout.operator("object.select_pattern", text="Select Pattern...")
-class VIEW3D_MT_select_face(Menu): # XXX no matching enum
+class VIEW3D_MT_select_paint_mask(Menu):
bl_label = "Select"
def draw(self, context):
- # layout = self.layout
+ layout = self.layout
+
+ layout.operator("view3d.select_border")
+ layout.operator("view3d.select_circle")
+
+ layout.separator()
+
+ layout.operator("paint.face_select_all").action = 'TOGGLE'
+ layout.operator("paint.face_select_all", text="Inverse").action = 'INVERT'
+
+ layout.separator()
+
+ layout.operator("paint.face_select_linked", text="Linked")
+
+
+class VIEW3D_MT_select_paint_mask_vertex(Menu):
+ bl_label = "Select"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("view3d.select_border")
+ layout.operator("view3d.select_circle")
+
+ layout.separator()
+
+ layout.operator("paint.vert_select_all").action = 'TOGGLE'
+ layout.operator("paint.vert_select_all", text="Inverse").action = 'INVERT'
+
+ layout.separator()
+
+ layout.operator("paint.vert_select_ungrouped", text="Ungrouped Verts")
- # TODO
- # see view3d_select_faceselmenu
- pass
# ********** Object menu **********
@@ -1065,12 +1111,14 @@ class VIEW3D_MT_make_links(Menu):
def draw(self, context):
layout = self.layout
-
+ operator_context_default = layout.operator_context
if(len(bpy.data.scenes) > 10):
- layout.operator_context = 'INVOKE_DEFAULT'
+ layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("object.make_links_scene", text="Objects to Scene...", icon='OUTLINER_OB_EMPTY')
else:
+ layout.operator_context = 'EXEC_REGION_WIN'
layout.operator_menu_enum("object.make_links_scene", "scene", text="Objects to Scene...")
+ layout.operator_context = operator_context_default
layout.operator_enum("object.make_links_data", "type") # inline
@@ -1536,7 +1584,7 @@ class VIEW3D_MT_pose_group(Menu):
def draw(self, context):
layout = self.layout
-
+
pose = context.active_object.pose
layout.operator_context = 'EXEC_AREA'
@@ -1609,6 +1657,8 @@ class BoneOptions:
def draw(self, context):
layout = self.layout
+ default_context = bpy.app.translations.contexts.default
+
options = [
"show_wire",
"use_deform",
@@ -1628,7 +1678,8 @@ class BoneOptions:
opt_suffix = "bone."
for opt in options:
- props = layout.operator("wm.context_collection_boolean_set", text=bone_props[opt].name)
+ props = layout.operator("wm.context_collection_boolean_set", text=bone_props[opt].name,
+ text_ctxt=default_context)
props.data_path_iter = data_path_iter
props.data_path_item = opt_suffix + opt
props.type = self.type
@@ -1679,7 +1730,6 @@ class VIEW3D_MT_edit_mesh(Menu):
layout.operator("view3d.edit_mesh_extrude_individual_move", text="Extrude Individual")
layout.operator("mesh.duplicate_move")
layout.menu("VIEW3D_MT_edit_mesh_delete")
- layout.menu("VIEW3D_MT_edit_mesh_dissolve")
layout.separator()
@@ -1709,19 +1759,37 @@ class VIEW3D_MT_edit_mesh_specials(Menu):
layout.operator("mesh.subdivide", text="Subdivide").smoothness = 0.0
layout.operator("mesh.subdivide", text="Subdivide Smooth").smoothness = 1.0
+
+ layout.separator()
+
layout.operator("mesh.merge", text="Merge...")
layout.operator("mesh.remove_doubles")
+
+ layout.separator()
+
layout.operator("mesh.hide", text="Hide").unselected = False
layout.operator("mesh.reveal", text="Reveal")
layout.operator("mesh.select_all", text="Select Inverse").action = 'INVERT'
+
+ layout.separator()
+
layout.operator("mesh.flip_normals")
layout.operator("mesh.vertices_smooth", text="Smooth")
layout.operator("mesh.vertices_smooth_laplacian", text="Laplacian Smooth")
+
+ layout.separator()
+
layout.operator("mesh.inset")
layout.operator("mesh.bevel", text="Bevel")
layout.operator("mesh.bridge_edge_loops")
+
+ layout.separator()
+
layout.operator("mesh.faces_shade_smooth")
layout.operator("mesh.faces_shade_flat")
+
+ layout.separator()
+
layout.operator("mesh.blend_from_shape")
layout.operator("mesh.shape_propagate_to_all")
layout.operator("mesh.select_vertex_path")
@@ -1788,10 +1856,11 @@ class VIEW3D_MT_edit_mesh_vertices(Menu):
layout.operator("mesh.split")
layout.operator_menu_enum("mesh.separate", "type")
layout.operator("mesh.vert_connect")
- layout.operator("mesh.vert_slide")
+ layout.operator("transform.vert_slide")
layout.separator()
+ layout.operator("mesh.bevel").vertex_only = True
layout.operator("mesh.vertices_smooth")
layout.operator("mesh.remove_doubles")
layout.operator("mesh.sort_elements", text="Sort Vertices").elements = {'VERT'}
@@ -1838,6 +1907,12 @@ class VIEW3D_MT_edit_mesh_edges(Menu):
layout.separator()
+ if context.scene and bpy.app.build_options.freestyle:
+ layout.operator("mesh.mark_freestyle_edge").clear = False
+ layout.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True
+
+ layout.separator()
+
layout.operator("mesh.edge_rotate", text="Rotate Edge CW").use_ccw = False
layout.operator("mesh.edge_rotate", text="Rotate Edge CCW").use_ccw = True
@@ -1878,6 +1953,12 @@ class VIEW3D_MT_edit_mesh_faces(Menu):
layout.separator()
+ if context.scene and bpy.app.build_options.freestyle:
+ layout.operator("mesh.mark_freestyle_face").clear = False
+ layout.operator("mesh.mark_freestyle_face", text="Clear Freestyle Face").clear = True
+
+ layout.separator()
+
layout.operator("mesh.quads_convert_to_tris")
layout.operator("mesh.tris_convert_to_quads")
@@ -1923,21 +2004,12 @@ class VIEW3D_MT_edit_mesh_delete(Menu):
layout.separator()
layout.operator("mesh.dissolve")
- layout.operator("mesh.edge_collapse")
- layout.operator("mesh.delete_edgeloop", text="Edge Loop")
-
-
-class VIEW3D_MT_edit_mesh_dissolve(Menu):
- bl_label = "Dissolve"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("mesh.dissolve")
+ layout.operator("mesh.dissolve_limited")
layout.separator()
- layout.operator("mesh.dissolve_limited")
+ layout.operator("mesh.edge_collapse")
+ layout.operator("mesh.delete_edgeloop", text="Edge Loop")
class VIEW3D_MT_edit_mesh_showhide(ShowHideMenu, Menu):
@@ -2381,9 +2453,6 @@ class VIEW3D_PT_view3d_display(Panel):
col.prop(view, "show_outline_selected")
col.prop(view, "show_all_objects_origin")
col.prop(view, "show_relationship_lines")
- if ob and ob.type == 'MESH':
- mesh = ob.data
- col.prop(mesh, "show_all_edges")
col = layout.column()
col.active = display_all
@@ -2408,7 +2477,10 @@ class VIEW3D_PT_view3d_display(Panel):
col.label(text="Shading:")
col.prop(gs, "material_mode", text="")
col.prop(view, "show_textured_solid")
-
+ if view.viewport_shade == 'SOLID':
+ col.prop(view, "use_matcap")
+ if view.use_matcap:
+ col.template_icon_view(view, "matcap_icon")
col.prop(view, "show_backface_culling")
layout.separator()
@@ -2473,22 +2545,37 @@ class VIEW3D_PT_view3d_meshdisplay(Panel):
mesh = context.active_object.data
- col = layout.column()
+ split = layout.split()
+
+ col = split.column()
col.label(text="Overlays:")
- col.prop(mesh, "show_edges", text="Edges")
col.prop(mesh, "show_faces", text="Faces")
+ col.prop(mesh, "show_edges", text="Edges")
col.prop(mesh, "show_edge_crease", text="Creases")
- col.prop(mesh, "show_edge_bevel_weight", text="Bevel Weights")
+
+ col = split.column()
+ col.label()
col.prop(mesh, "show_edge_seams", text="Seams")
col.prop(mesh, "show_edge_sharp", text="Sharp")
+ col.prop(mesh, "show_edge_bevel_weight", text="Weights")
+
+ if context.scene and bpy.app.build_options.freestyle:
+ col.prop(mesh, "show_freestyle_edge_marks", text="Freestyle Edge Marks")
+ col.prop(mesh, "show_freestyle_face_marks", text="Freestyle Face Marks")
+
+ col = layout.column()
col.separator()
col.label(text="Normals:")
row = col.row()
+
sub = row.row(align=True)
sub.prop(mesh, "show_normal_vertex", text="", icon='VERTEXSEL')
sub.prop(mesh, "show_normal_face", text="", icon='FACESEL')
- row.prop(context.scene.tool_settings, "normal_size", text="Size")
+
+ sub = row.row(align=True)
+ sub.active = mesh.show_normal_vertex or mesh.show_normal_face
+ sub.prop(context.scene.tool_settings, "normal_size", text="Size")
col.separator()
col.label(text="Numerics:")
@@ -2665,6 +2752,8 @@ class VIEW3D_PT_etch_a_ton(Panel):
col.prop(toolsettings, "use_etch_quick")
col.prop(toolsettings, "use_etch_overdraw")
+ col.separator()
+
col.prop(toolsettings, "etch_convert_mode")
if toolsettings.etch_convert_mode == 'LENGTH':
@@ -2676,11 +2765,20 @@ class VIEW3D_PT_etch_a_ton(Panel):
elif toolsettings.etch_convert_mode == 'RETARGET':
col.prop(toolsettings, "etch_template")
col.prop(toolsettings, "etch_roll_mode")
- col.prop(toolsettings, "use_etch_autoname")
- col.prop(toolsettings, "etch_number")
- col.prop(toolsettings, "etch_side")
- col.operator("sketch.convert", text="Convert")
+ col.separator()
+
+ colsub = col.column(align=True)
+ colsub.prop(toolsettings, "use_etch_autoname")
+ sub = colsub.column()
+ sub.enabled = not toolsettings.use_etch_autoname
+ sub.prop(toolsettings, "etch_number")
+ sub.prop(toolsettings, "etch_side")
+
+ col.separator()
+
+ col.operator("sketch.convert", text="Convert to Bones")
+ col.operator("sketch.delete", text="Delete Strokes")
class VIEW3D_PT_context_properties(Panel):
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 91132a72b07..24e4dac4ded 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -20,7 +20,7 @@
import bpy
from bpy.types import Menu, Panel
from bl_ui.properties_paint_common import UnifiedPaintPanel
-from bl_ui.properties_paint_common import sculpt_brush_texture_settings
+from bl_ui.properties_paint_common import brush_texture_settings
class View3DPanel():
@@ -64,6 +64,8 @@ def draw_gpencil_tools(context, layout):
row = col.row()
row.prop(context.tool_settings, "use_grease_pencil_sessions")
+ col.operator("view3d.ruler")
+
# ********** default tools for object-mode ****************
@@ -102,12 +104,40 @@ class VIEW3D_PT_tools_objectmode(View3DPanel, Panel):
col = layout.column(align=True)
col.label(text="Motion Paths:")
- col.operator("object.paths_calculate", text="Calculate Paths")
- col.operator("object.paths_clear", text="Clear Paths")
+ row = col.row(align=True)
+ row.operator("object.paths_calculate", text="Calculate")
+ row.operator("object.paths_clear", text="Clear")
draw_repeat_tools(context, layout)
draw_gpencil_tools(context, layout)
+ col = layout.column(align=True)
+
+
+class VIEW3D_PT_tools_rigidbody(View3DPanel, Panel):
+ bl_context = "objectmode"
+ bl_label = "Rigid Body Tools"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ col = layout.column(align=True)
+ col.label(text="Add/Remove:")
+ row = col.row()
+ row.operator("rigidbody.objects_add", text="Add Active").type = 'ACTIVE'
+ row.operator("rigidbody.objects_add", text="Add Passive").type = 'PASSIVE'
+ row = col.row()
+ row.operator("rigidbody.objects_remove", text="Remove")
+
+ col = layout.column(align=True)
+ col.label(text="Object Tools:")
+ col.operator("rigidbody.shape_change", text="Change Shape")
+ col.operator("rigidbody.mass_calculate", text="Calculate Mass")
+ col.operator("rigidbody.object_settings_copy", text="Copy from Active")
+ col.operator("rigidbody.bake_to_keyframes", text="Bake To Keyframes")
+ col.label(text="Constraints:")
+ col.operator("rigidbody.connect", text="Connect")
# ********** default tools for editmode_mesh ****************
@@ -150,6 +180,7 @@ class VIEW3D_PT_tools_meshedit(View3DPanel, Panel):
props = row.operator("mesh.knife_tool", text="Select")
props.use_occlude_geometry = False
props.only_selected = True
+ col.operator("mesh.knife_project")
col = layout.column(align=True)
col.label(text="Remove:")
@@ -237,6 +268,8 @@ class VIEW3D_PT_tools_curveedit(View3DPanel, Panel):
col.operator("curve.cyclic_toggle")
col.operator("curve.switch_direction")
col.operator("curve.spline_type_set")
+ col.operator("curve.radius_set")
+ col.operator("curve.smooth_radius")
col = layout.column(align=True)
col.label(text="Handles:")
@@ -251,6 +284,7 @@ class VIEW3D_PT_tools_curveedit(View3DPanel, Panel):
col.label(text="Modeling:")
col.operator("curve.extrude_move", text="Extrude")
col.operator("curve.subdivide")
+ col.operator("curve.smooth")
draw_repeat_tools(context, layout)
@@ -439,8 +473,9 @@ class VIEW3D_PT_tools_posemode(View3DPanel, Panel):
col = layout.column(align=True)
col.label(text="Motion Paths:")
- col.operator("pose.paths_calculate", text="Calculate Paths")
- col.operator("pose.paths_clear", text="Clear Paths")
+ row = col.row(align=True)
+ row.operator("pose.paths_calculate", text="Calculate")
+ row.operator("pose.paths_clear", text="Clear")
draw_repeat_tools(context, layout)
@@ -645,7 +680,12 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
self.prop_unified_strength(row, context, brush, "use_pressure_strength")
row = col.row(align=True)
- row.prop(brush, "jitter", slider=True)
+ if(brush.use_relative_jitter):
+ row.prop(brush, "use_relative_jitter", text="", icon='LOCKED')
+ row.prop(brush, "jitter", slider=True)
+ else:
+ row.prop(brush, "use_relative_jitter", text="", icon='UNLOCKED')
+ row.prop(brush, "jitter_absolute")
row.prop(brush, "use_pressure_jitter", toggle=True, text="")
col.prop(brush, "blend", text="Blend")
@@ -673,7 +713,12 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
self.prop_unified_strength(row, context, brush, "use_pressure_strength")
row = col.row(align=True)
- row.prop(brush, "jitter", slider=True)
+ if(brush.use_relative_jitter):
+ row.prop(brush, "use_relative_jitter", text="", icon='LOCKED')
+ row.prop(brush, "jitter", slider=True)
+ else:
+ row.prop(brush, "use_relative_jitter", text="", icon='UNLOCKED')
+ row.prop(brush, "jitter_absolute")
row.prop(brush, "use_pressure_jitter", toggle=True, text="")
col.prop(brush, "vertex_tool", text="Blend")
@@ -708,7 +753,7 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
def poll(cls, context):
settings = cls.paint_settings(context)
return (settings and settings.brush and
- (context.sculpt_object or context.image_paint_object))
+ (context.sculpt_object or context.image_paint_object or context.vertex_paint_object))
def draw(self, context):
layout = self.layout
@@ -720,24 +765,21 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
col = layout.column()
col.template_ID_preview(brush, "texture", new="texture.new", rows=3, cols=8)
- if brush.use_paint_image:
- col.prop(brush, "use_fixed_texture")
- if context.sculpt_object:
- sculpt_brush_texture_settings(col, brush)
+ brush_texture_settings(col, brush, context.sculpt_object)
- # use_texture_overlay and texture_overlay_alpha
- col = layout.column(align=True)
- col.active = brush.sculpt_capabilities.has_overlay
- col.label(text="Overlay:")
+ # use_texture_overlay and texture_overlay_alpha
+ col = layout.column(align=True)
+ col.active = brush.brush_capabilities.has_overlay
+ col.label(text="Overlay:")
- row = col.row()
- if brush.use_texture_overlay:
- row.prop(brush, "use_texture_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
- else:
- row.prop(brush, "use_texture_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
- sub = row.row()
- sub.prop(brush, "texture_overlay_alpha", text="Alpha")
+ row = col.row()
+ if brush.use_texture_overlay:
+ row.prop(brush, "use_texture_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
+ else:
+ row.prop(brush, "use_texture_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
+ sub = row.row()
+ sub.prop(brush, "texture_overlay_alpha", text="Alpha")
class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
@@ -777,9 +819,10 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
if brush.use_space:
col.separator()
- row = col.row()
+ row = col.row(align=True)
row.active = brush.use_space
row.prop(brush, "spacing", text="Spacing")
+ row.prop(brush, "use_pressure_spacing", toggle=True, text="")
if brush.sculpt_capabilities.has_smooth_stroke:
col = layout.column()
@@ -796,7 +839,12 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
col.separator()
row = col.row(align=True)
- row.prop(brush, "jitter", slider=True)
+ if(brush.use_relative_jitter):
+ row.prop(brush, "use_relative_jitter", text="", icon='LOCKED')
+ row.prop(brush, "jitter", slider=True)
+ else:
+ row.prop(brush, "use_relative_jitter", text="", icon='UNLOCKED')
+ row.prop(brush, "jitter_absolute")
row.prop(brush, "use_pressure_jitter", toggle=True, text="")
else:
@@ -808,23 +856,23 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
col.separator()
- if not image_paint:
- col.prop(brush, "use_smooth_stroke")
+ col.prop(brush, "use_smooth_stroke")
- col = layout.column()
- col.active = brush.use_smooth_stroke
- col.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
- col.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
+ col = layout.column()
+ col.active = brush.use_smooth_stroke
+ col.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
+ col.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
col.separator()
col = layout.column()
- col.active = brush.sculpt_capabilities.has_spacing
+ col.active = brush.brush_capabilities.has_spacing
col.prop(brush, "use_space")
- row = col.row()
+ row = col.row(align=True)
row.active = brush.use_space
row.prop(brush, "spacing", text="Spacing")
+ row.prop(brush, "use_pressure_spacing", toggle=True, text="")
class VIEW3D_PT_tools_brush_curve(Panel, View3DPaintPanel):
@@ -854,6 +902,36 @@ class VIEW3D_PT_tools_brush_curve(Panel, View3DPaintPanel):
row.operator("brush.curve_preset", icon='NOCURVE', text="").shape = 'MAX'
+class VIEW3D_PT_sculpt_topology(Panel, View3DPaintPanel):
+ bl_label = "Topology"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.sculpt_object and context.tool_settings.sculpt)
+
+ def draw(self, context):
+ layout = self.layout
+
+ toolsettings = context.tool_settings
+ sculpt = toolsettings.sculpt
+
+ if context.sculpt_object.use_dynamic_topology_sculpting:
+ layout.operator("sculpt.dynamic_topology_toggle", icon='X', text="Disable Dynamic")
+ else:
+ layout.operator("sculpt.dynamic_topology_toggle", icon='SCULPT_DYNTOPO', text="Enable Dynamic")
+
+ col = layout.column()
+ col.active = context.sculpt_object.use_dynamic_topology_sculpting
+ col.prop(sculpt, "detail_size")
+ col.prop(sculpt, "use_smooth_shading")
+ col.prop(sculpt, "use_edge_collapse")
+ col.operator("sculpt.optimize")
+ col.separator()
+ col.prop(sculpt, "symmetrize_direction")
+ col.operator("sculpt.symmetrize")
+
+
class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
bl_label = "Options"
bl_options = {'DEFAULT_CLOSED'}
@@ -971,6 +1049,7 @@ class VIEW3D_PT_tools_weightpaint(View3DPanel, Panel):
col.operator("object.vertex_group_transfer_weight", text="Transfer Weights")
col.operator("object.vertex_group_limit_total", text="Limit Total")
col.operator("object.vertex_group_fix", text="Fix Deforms")
+ col.operator("paint.weight_gradient")
class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
@@ -998,6 +1077,11 @@ class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
col.prop(wpaint, "input_samples")
+ col.label("Show Zero Weights:")
+ rowsub = col.row()
+ rowsub.active = (not tool_settings.use_multipaint)
+ rowsub.prop(tool_settings, "vertex_group_user", expand=True)
+
self.unified_paint_settings(col, context)
# Commented out because the Apply button isn't an operator yet, making these settings useless
@@ -1050,11 +1134,6 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel, Panel):
brush = context.tool_settings.image_paint.brush
return (brush is not None)
- def draw_header(self, context):
- ipaint = context.tool_settings.image_paint
-
- self.layout.prop(ipaint, "use_projection", text="")
-
def draw(self, context):
layout = self.layout
@@ -1063,37 +1142,35 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel, Panel):
toolsettings = context.tool_settings
ipaint = toolsettings.image_paint
settings = toolsettings.image_paint
- use_projection = ipaint.use_projection
+
+ layout.prop(ipaint, "input_samples")
col = layout.column()
- col.active = use_projection
col.prop(ipaint, "use_occlude")
col.prop(ipaint, "use_backface_culling")
row = layout.row()
- row.active = (use_projection)
row.prop(ipaint, "use_normal_falloff")
-
+
sub = row.row()
sub.active = (ipaint.use_normal_falloff)
sub.prop(ipaint, "normal_angle", text="")
split = layout.split()
- split.active = (use_projection)
split.prop(ipaint, "use_stencil_layer", text="Stencil")
row = split.row()
row.active = (ipaint.use_stencil_layer)
stencil_text = mesh.uv_texture_stencil.name if mesh.uv_texture_stencil else ""
- row.menu("VIEW3D_MT_tools_projectpaint_stencil", text=stencil_text)
+ row.menu("VIEW3D_MT_tools_projectpaint_stencil", text=stencil_text, translate=False)
row.prop(ipaint, "invert_stencil", text="", icon='IMAGE_ALPHA')
- row = layout.row()
- row.active = (settings.brush.image_tool == 'CLONE')
- row.prop(ipaint, "use_clone_layer", text="Clone")
+ col = layout.column()
+ col.active = (settings.brush.image_tool == 'CLONE')
+ col.prop(ipaint, "use_clone_layer", text="Clone from UV map")
clone_text = mesh.uv_texture_clone.name if mesh.uv_texture_clone else ""
- row.menu("VIEW3D_MT_tools_projectpaint_clone", text=clone_text)
+ col.menu("VIEW3D_MT_tools_projectpaint_clone", text=clone_text, translate=False)
layout.prop(ipaint, "seam_bleed")
@@ -1108,7 +1185,7 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel, Panel):
col.operator("paint.project_image", text="Apply Camera Image")
col.operator("image.save_dirty", text="Save All Edited")
-
+
class VIEW3D_PT_imagepaint_options(View3DPaintPanel):
bl_label = "Options"
@@ -1132,7 +1209,7 @@ class VIEW3D_MT_tools_projectpaint_clone(Menu):
layout = self.layout
for i, tex in enumerate(context.active_object.data.uv_textures):
- props = layout.operator("wm.context_set_int", text=tex.name)
+ props = layout.operator("wm.context_set_int", text=tex.name, translate=False)
props.data_path = "active_object.data.uv_texture_clone_index"
props.value = i
@@ -1143,13 +1220,13 @@ class VIEW3D_MT_tools_projectpaint_stencil(Menu):
def draw(self, context):
layout = self.layout
for i, tex in enumerate(context.active_object.data.uv_textures):
- props = layout.operator("wm.context_set_int", text=tex.name)
+ props = layout.operator("wm.context_set_int", text=tex.name, translate=False)
props.data_path = "active_object.data.uv_texture_stencil_index"
props.value = i
class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
- """default tools for particle mode"""
+ """Default tools for particle mode"""
bl_context = "particlemode"
bl_label = "Options"
@@ -1166,7 +1243,8 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
if pe.type == 'PARTICLES':
if ob.particle_systems:
if len(ob.particle_systems) > 1:
- layout.template_list(ob, "particle_systems", ob.particle_systems, "active_index", rows=2, maxrows=3)
+ layout.template_list("UI_UL_list", "particle_systems", ob, "particle_systems",
+ ob.particle_systems, "active_index", rows=2, maxrows=3)
ptcache = ob.particle_systems.active.point_cache
else:
@@ -1175,7 +1253,8 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
ptcache = md.point_cache
if ptcache and len(ptcache.point_caches) > 1:
- layout.template_list(ptcache, "point_caches", ptcache.point_caches, "active_index", rows=2, maxrows=3)
+ layout.template_list("UI_UL_list", "particles_point_caches", ptcache, "point_caches",
+ ptcache.point_caches, "active_index", rows=2, maxrows=3)
if not pe.is_editable:
layout.label(text="Point cache must be baked")
diff --git a/release/scripts/startup/keyingsets_builtins.py b/release/scripts/startup/keyingsets_builtins.py
index 6ad87375738..6d52a81456b 100644
--- a/release/scripts/startup/keyingsets_builtins.py
+++ b/release/scripts/startup/keyingsets_builtins.py
@@ -20,14 +20,11 @@
"""
Built-In Keying Sets
-None of these Keying Sets should be removed, as these
-are needed by various parts of Blender in order for them
+None of these Keying Sets should be removed, as these are needed by various parts of Blender in order for them
to work correctly.
-Beware also about changing the order that these are defined
-here, since this can result in old files referring to the
-wrong Keying Set as the active one, potentially resulting
-in lost (i.e. unkeyed) animation.
+Beware also about changing the order that these are defined here, since this can result in old files referring to the
+wrong Keying Set as the active one, potentially resulting in lost (i.e. unkeyed) animation.
"""
import bpy
@@ -138,9 +135,7 @@ class BUILTIN_KSI_LocScale(KeyingSetInfo):
# LocRotScale
class BUILTIN_KSI_LocRotScale(KeyingSetInfo):
- """
- Insert a keyframe on each of the location, rotation, and scale channels
- """
+ """Insert a keyframe on each of the location, rotation, and scale channels"""
bl_idname = ANIM_KS_LOC_ROT_SCALE_ID
bl_label = "LocRotScale"
@@ -181,12 +176,10 @@ class BUILTIN_KSI_RotScale(KeyingSetInfo):
# ------------
-# Location
+# VisualLocation
class BUILTIN_KSI_VisualLoc(KeyingSetInfo):
- """
- Insert a keyframe on each of the location channels, taking into account
- effects of constraints and relationships
- """
+ """Insert a keyframe on each of the location channels, taking into account effects of constraints """
+ """and relationships"""
bl_label = "Visual Location"
bl_options = {'INSERTKEY_VISUAL'}
@@ -201,12 +194,10 @@ class BUILTIN_KSI_VisualLoc(KeyingSetInfo):
generate = keyingsets_utils.RKS_GEN_location
-# Rotation
+# VisualRotation
class BUILTIN_KSI_VisualRot(KeyingSetInfo):
- """
- Insert a keyframe on each of the rotation channels, taking into account
- effects of constraints and relationships
- """
+ """Insert a keyframe on each of the rotation channels, taking into account effects of constraints """
+ """and relationships"""
bl_label = "Visual Rotation"
bl_options = {'INSERTKEY_VISUAL'}
@@ -221,12 +212,28 @@ class BUILTIN_KSI_VisualRot(KeyingSetInfo):
generate = keyingsets_utils.RKS_GEN_rotation
+# VisualScaling
+class BUILTIN_KSI_VisualScaling(KeyingSetInfo):
+ """Insert a keyframe on each of the scale channels, taking into account effects of constraints """
+ """and relationships"""
+ bl_label = "Visual Scaling"
+
+ bl_options = {'INSERTKEY_VISUAL'}
+
+ # poll - use predefined callback for selected bones/objects
+ poll = keyingsets_utils.RKS_POLL_selected_items
+
+ # iterator - use callback for selected bones/objects
+ iterator = keyingsets_utils.RKS_ITER_selected_item
+
+ # generator - use callback for location
+ generate = keyingsets_utils.RKS_GEN_scaling
+
+
# VisualLocRot
class BUILTIN_KSI_VisualLocRot(KeyingSetInfo):
- """
- Insert a keyframe on each of the location and rotation channels,
- taking into account effects of constraints and relationships
- """
+ """Insert a keyframe on each of the location and rotation channels, taking into account effects of constraints """
+ """and relationships"""
bl_label = "Visual LocRot"
bl_options = {'INSERTKEY_VISUAL'}
@@ -244,6 +251,74 @@ class BUILTIN_KSI_VisualLocRot(KeyingSetInfo):
# rotation
keyingsets_utils.RKS_GEN_rotation(self, context, ks, data)
+
+# VisualLocScale
+class BUILTIN_KSI_VisualLocScale(KeyingSetInfo):
+ """Insert a keyframe on each of the location and scaling channels, taking into account effects of constraints """
+ """and relationships"""
+ bl_label = "Visual LocScale"
+
+ bl_options = {'INSERTKEY_VISUAL'}
+
+ # poll - use predefined callback for selected bones/objects
+ poll = keyingsets_utils.RKS_POLL_selected_items
+
+ # iterator - use callback for selected bones/objects
+ iterator = keyingsets_utils.RKS_ITER_selected_item
+
+ # generator
+ def generate(self, context, ks, data):
+ # location
+ keyingsets_utils.RKS_GEN_location(self, context, ks, data)
+ # scaling
+ keyingsets_utils.RKS_GEN_scaling(self, context, ks, data)
+
+
+# VisualLocRotScale
+class BUILTIN_KSI_VisualLocRotScale(KeyingSetInfo):
+ """Insert a keyframe on each of the location, rotation and scaling channels, taking into account effects """
+ """of constraints and relationships"""
+ bl_label = "Visual LocRotScale"
+
+ bl_options = {'INSERTKEY_VISUAL'}
+
+ # poll - use predefined callback for selected bones/objects
+ poll = keyingsets_utils.RKS_POLL_selected_items
+
+ # iterator - use callback for selected bones/objects
+ iterator = keyingsets_utils.RKS_ITER_selected_item
+
+ # generator
+ def generate(self, context, ks, data):
+ # location
+ keyingsets_utils.RKS_GEN_location(self, context, ks, data)
+ # rotation
+ keyingsets_utils.RKS_GEN_rotation(self, context, ks, data)
+ # scaling
+ keyingsets_utils.RKS_GEN_scaling(self, context, ks, data)
+
+
+# VisualRotScale
+class BUILTIN_KSI_VisualRotScale(KeyingSetInfo):
+ """Insert a keyframe on each of the rotation and scaling channels, taking into account effects of constraints """
+ """and relationships"""
+ bl_label = "Visual RotScale"
+
+ bl_options = {'INSERTKEY_VISUAL'}
+
+ # poll - use predefined callback for selected bones/objects
+ poll = keyingsets_utils.RKS_POLL_selected_items
+
+ # iterator - use callback for selected bones/objects
+ iterator = keyingsets_utils.RKS_ITER_selected_item
+
+ # generator
+ def generate(self, context, ks, data):
+ # rotation
+ keyingsets_utils.RKS_GEN_rotation(self, context, ks, data)
+ # scaling
+ keyingsets_utils.RKS_GEN_scaling(self, context, ks, data)
+
# ------------
@@ -273,10 +348,8 @@ class BUILTIN_KSI_Available(KeyingSetInfo):
# All properties that are likely to get animated in a character rig
class BUILTIN_KSI_WholeCharacter(KeyingSetInfo):
- """
- Insert a keyframe for all properties that are likely to get animated in a
- character rig (useful when blocking out a shot)
- """
+ """Insert a keyframe for all properties that are likely to get animated in a character rig """
+ """(useful when blocking out a shot)"""
bl_idname = ANIM_KS_WHOLE_CHARACTER_ID
bl_label = "Whole Character"
diff --git a/release/scripts/templates_osl/empty_shader.osl b/release/scripts/templates_osl/empty_shader.osl
new file mode 100644
index 00000000000..e2c9a4a257e
--- /dev/null
+++ b/release/scripts/templates_osl/empty_shader.osl
@@ -0,0 +1,6 @@
+
+shader name()
+{
+
+}
+
diff --git a/release/scripts/templates_osl/noise.osl b/release/scripts/templates_osl/noise.osl
new file mode 100644
index 00000000000..05cc31687c0
--- /dev/null
+++ b/release/scripts/templates_osl/noise.osl
@@ -0,0 +1,18 @@
+
+shader noise(
+ float Time = 1.0,
+ point Point = P,
+ output float Cell = 0.0,
+ output color Perlin = 0.8,
+ output color UPerlin = 0.8)
+{
+ /* Cell Noise */
+ Cell = noise("cell", Point);
+
+ /* Perlin 4D Noise*/
+ Perlin = noise("perlin", Point, Time);
+
+ /* UPerlin 4D Noise*/
+ UPerlin = noise("uperlin", Point, Time);
+}
+
diff --git a/release/scripts/templates_osl/wireframe.osl b/release/scripts/templates_osl/wireframe.osl
new file mode 100644
index 00000000000..00e4506e73c
--- /dev/null
+++ b/release/scripts/templates_osl/wireframe.osl
@@ -0,0 +1,11 @@
+
+#include "oslutil.h"
+
+shader wireframe(
+ float Line_Width = 2.0,
+ int Raster = 1,
+ output float Wire = 0.0)
+{
+ Wire = wireframe("triangles", Line_Width, Raster);
+}
+
diff --git a/release/scripts/templates/addon_add_object.py b/release/scripts/templates_py/addon_add_object.py
index a4df5fb7436..66da6a969c7 100644
--- a/release/scripts/templates/addon_add_object.py
+++ b/release/scripts/templates_py/addon_add_object.py
@@ -2,7 +2,7 @@ bl_info = {
"name": "New Object",
"author": "Your Name Here",
"version": (1, 0),
- "blender": (2, 5, 5),
+ "blender": (2, 65, 0),
"location": "View3D > Add > Mesh > New Object",
"description": "Adds a new Mesh Object",
"warning": "",
diff --git a/release/scripts/templates/background_job.py b/release/scripts/templates_py/background_job.py
index 11b51e5a9b5..11b51e5a9b5 100644
--- a/release/scripts/templates/background_job.py
+++ b/release/scripts/templates_py/background_job.py
diff --git a/release/scripts/templates/batch_export.py b/release/scripts/templates_py/batch_export.py
index 45d26f4b525..45d26f4b525 100644
--- a/release/scripts/templates/batch_export.py
+++ b/release/scripts/templates_py/batch_export.py
diff --git a/release/scripts/templates/bmesh_simple.py b/release/scripts/templates_py/bmesh_simple.py
index 45e6b52d578..45e6b52d578 100644
--- a/release/scripts/templates/bmesh_simple.py
+++ b/release/scripts/templates_py/bmesh_simple.py
diff --git a/release/scripts/templates/bmesh_simple_editmode.py b/release/scripts/templates_py/bmesh_simple_editmode.py
index d79ba02c2cb..d79ba02c2cb 100644
--- a/release/scripts/templates/bmesh_simple_editmode.py
+++ b/release/scripts/templates_py/bmesh_simple_editmode.py
diff --git a/release/scripts/templates/builtin_keyingset.py b/release/scripts/templates_py/builtin_keyingset.py
index 19f92dc75e7..19f92dc75e7 100644
--- a/release/scripts/templates/builtin_keyingset.py
+++ b/release/scripts/templates_py/builtin_keyingset.py
diff --git a/release/scripts/templates_py/custom_nodes.py b/release/scripts/templates_py/custom_nodes.py
new file mode 100644
index 00000000000..3bcc7f979b3
--- /dev/null
+++ b/release/scripts/templates_py/custom_nodes.py
@@ -0,0 +1,160 @@
+import bpy
+# XXX these don't work yet ...
+#from bpy_types import NodeTree, Node, NodeSocket
+
+# Implementation of custom nodes from Python
+
+
+# Shortcut for node type menu
+def add_nodetype(layout, type):
+ layout.operator("node.add_node", text=type.bl_label).type = type.bl_rna.identifier
+
+# Derived from the NodeTree base type, similar to Menu, Operator, Panel, etc.
+class MyCustomTree(bpy.types.NodeTree):
+ # Description string
+ '''A custom node tree type that will show up in the node editor header'''
+ # Optional identifier string. If not explicitly defined, the python class name is used.
+ bl_idname = 'CustomTreeType'
+ # Label for nice name display
+ bl_label = 'Custom Node Tree'
+ # 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'
+
+ def draw_add_menu(self, context, layout):
+ layout.label("Hello World!")
+ add_nodetype(layout, bpy.types.CustomNodeType)
+ add_nodetype(layout, bpy.types.MyCustomGroup)
+
+
+# Custom socket type
+class MyCustomSocket(bpy.types.NodeSocket):
+ # Description string
+ '''Custom node socket type'''
+ # Optional identifier string. If not explicitly defined, the python class name is used.
+ bl_idname = 'CustomSocketType'
+ # Label for nice name display
+ bl_label = 'Custom Node Socket'
+
+ # Enum items list
+ my_items = [
+ ("DOWN", "Down", "Where your feet are"),
+ ("UP", "Up", "Where your head should be"),
+ ("LEFT", "Left", "Not right"),
+ ("RIGHT", "Right", "Not left")
+ ]
+
+ myEnumProperty = bpy.props.EnumProperty(name="Direction", description="Just an example", items=my_items, default='UP')
+
+ # Optional function for drawing the socket input value
+ def draw(self, context, layout, node):
+ layout.prop(self, "myEnumProperty", text=self.name)
+
+ # Socket color
+ def draw_color(self, context, node):
+ return (1.0, 0.4, 0.216, 0.5)
+
+# Base class for all custom nodes in this tree type.
+# Defines a poll function to enable instantiation.
+class MyCustomTreeNode :
+ @classmethod
+ def poll(cls, ntree):
+ return ntree.bl_idname == 'CustomTreeType'
+
+# Derived from the Node base type.
+class MyCustomNode(bpy.types.Node, MyCustomTreeNode):
+ # === Basics ===
+ # Description string
+ '''A custom node'''
+ # Optional identifier string. If not explicitly defined, the python class name is used.
+ bl_idname = 'CustomNodeType'
+ # Label for nice name display
+ bl_label = 'Custom Node'
+ # Icon identifier
+ bl_icon = 'SOUND'
+
+ # === Custom Properties ===
+ # These work just like custom properties in ID data blocks
+ # Extensive information can be found under
+ # http://wiki.blender.org/index.php/Doc:2.6/Manual/Extensions/Python/Properties
+ myStringProperty = bpy.props.StringProperty()
+ myFloatProperty = bpy.props.FloatProperty(default=3.1415926)
+
+ # === Optional Functions ===
+ # Initialization function, called when a new node is created.
+ # This is the most common place to create the sockets for a node, as shown below.
+ # NOTE: this is not the same as the standard __init__ function in Python, which is
+ # a purely internal Python method and unknown to the node system!
+ def init(self, context):
+ self.inputs.new('CustomSocketType', "Hello")
+ self.inputs.new('NodeSocketFloat', "World")
+ self.inputs.new('NodeSocketVector', "!")
+
+ self.outputs.new('NodeSocketColor', "How")
+ self.outputs.new('NodeSocketColor', "are")
+ self.outputs.new('NodeSocketFloat', "you")
+
+ # Copy function to initialize a copied node from an existing one.
+ def copy(self, node):
+ print("Copying from node ", node)
+
+ # Free function to clean up on removal.
+ def free(self):
+ print("Removing node ", self, ", Goodbye!")
+
+ # Additional buttons displayed on the node.
+ def draw_buttons(self, context, layout):
+ layout.label("Node settings")
+ layout.prop(self, "myFloatProperty")
+
+ # Detail buttons in the sidebar.
+ # If this function is not defined, the draw_buttons function is used instead
+ def draw_buttons_ext(self, context, layout):
+ layout.prop(self, "myFloatProperty")
+ # myStringProperty button will only be visible in the sidebar
+ layout.prop(self, "myStringProperty")
+
+
+# A customized group-like node.
+class MyCustomGroup(bpy.types.NodeGroup, MyCustomTreeNode):
+ # === Basics ===
+ # Description string
+ '''A custom group node'''
+ # Label for nice name display
+ bl_label = 'Custom Group Node'
+ bl_group_tree_idname = 'CustomTreeType'
+
+ orks = bpy.props.IntProperty(default=3)
+ dwarfs = bpy.props.IntProperty(default=12)
+ wizards = bpy.props.IntProperty(default=1)
+
+ # Additional buttons displayed on the node.
+ def draw_buttons(self, context, layout):
+ col = layout.column(align=True)
+ col.prop(self, "orks")
+ col.prop(self, "dwarfs")
+ col.prop(self, "wizards")
+
+ layout.label("The Node Tree:")
+ layout.prop(self, "node_tree", text="")
+
+
+def register():
+ bpy.utils.register_class(MyCustomTree)
+ bpy.utils.register_class(MyCustomSocket)
+ bpy.utils.register_class(MyCustomNode)
+ bpy.utils.register_class(MyCustomGroup)
+
+
+def unregister():
+ bpy.utils.unregister_class(MyCustomTree)
+ bpy.utils.unregister_class(MyCustomSocket)
+ bpy.utils.unregister_class(MyCustomNode)
+ bpy.utils.unregister_class(MyCustomGroup)
+
+
+if __name__ == "__main__":
+ register()
+
diff --git a/release/scripts/templates/driver_functions.py b/release/scripts/templates_py/driver_functions.py
index 1c6af0e574f..1c6af0e574f 100644
--- a/release/scripts/templates/driver_functions.py
+++ b/release/scripts/templates_py/driver_functions.py
diff --git a/release/scripts/templates/gamelogic.py b/release/scripts/templates_py/gamelogic.py
index 01ac27c56cd..01ac27c56cd 100644
--- a/release/scripts/templates/gamelogic.py
+++ b/release/scripts/templates_py/gamelogic.py
diff --git a/release/scripts/templates/gamelogic_module.py b/release/scripts/templates_py/gamelogic_module.py
index 88c8cf0d75b..88c8cf0d75b 100644
--- a/release/scripts/templates/gamelogic_module.py
+++ b/release/scripts/templates_py/gamelogic_module.py
diff --git a/release/scripts/templates/gamelogic_simple.py b/release/scripts/templates_py/gamelogic_simple.py
index dbfcf948b18..dbfcf948b18 100644
--- a/release/scripts/templates/gamelogic_simple.py
+++ b/release/scripts/templates_py/gamelogic_simple.py
diff --git a/release/scripts/templates/operator_file_export.py b/release/scripts/templates_py/operator_file_export.py
index 9511cb163bc..9511cb163bc 100644
--- a/release/scripts/templates/operator_file_export.py
+++ b/release/scripts/templates_py/operator_file_export.py
diff --git a/release/scripts/templates/operator_file_import.py b/release/scripts/templates_py/operator_file_import.py
index 9940a1b98eb..9940a1b98eb 100644
--- a/release/scripts/templates/operator_file_import.py
+++ b/release/scripts/templates_py/operator_file_import.py
diff --git a/release/scripts/templates/operator_mesh_add.py b/release/scripts/templates_py/operator_mesh_add.py
index fa248cb9005..fa248cb9005 100644
--- a/release/scripts/templates/operator_mesh_add.py
+++ b/release/scripts/templates_py/operator_mesh_add.py
diff --git a/release/scripts/templates/operator_modal.py b/release/scripts/templates_py/operator_modal.py
index 88e5ee80590..88e5ee80590 100644
--- a/release/scripts/templates/operator_modal.py
+++ b/release/scripts/templates_py/operator_modal.py
diff --git a/release/scripts/templates/operator_modal_draw.py b/release/scripts/templates_py/operator_modal_draw.py
index f1c4e113b0a..d11ddf0b467 100644
--- a/release/scripts/templates/operator_modal_draw.py
+++ b/release/scripts/templates_py/operator_modal_draw.py
@@ -42,20 +42,22 @@ class ModalDrawOperator(bpy.types.Operator):
self.mouse_path.append((event.mouse_region_x, event.mouse_region_y))
elif event.type == 'LEFTMOUSE':
- context.region.callback_remove(self._handle)
+ bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
return {'FINISHED'}
elif event.type in {'RIGHTMOUSE', 'ESC'}:
- context.region.callback_remove(self._handle)
+ bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
return {'CANCELLED'}
return {'RUNNING_MODAL'}
def invoke(self, context, event):
if context.area.type == 'VIEW_3D':
+ # the arguments we pass the the callback
+ args = (self, context)
# Add the region OpenGL drawing callback
# draw in view space with 'POST_VIEW' and 'PRE_VIEW'
- self._handle = context.region.callback_add(draw_callback_px, (self, context), 'POST_PIXEL')
+ self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, args, 'WINDOW', 'POST_PIXEL')
self.mouse_path = []
diff --git a/release/scripts/templates/operator_modal_timer.py b/release/scripts/templates_py/operator_modal_timer.py
index 72c153df9d2..3088d59fbcf 100644
--- a/release/scripts/templates/operator_modal_timer.py
+++ b/release/scripts/templates_py/operator_modal_timer.py
@@ -14,7 +14,7 @@ class ModalTimerOperator(bpy.types.Operator):
if event.type == 'TIMER':
# change theme color, silly!
- color = context.user_preferences.themes[0].view_3d.space.back
+ color = context.user_preferences.themes[0].view_3d.space.gradients.high_gradient
color.s = 1.0
color.h += 0.01
diff --git a/release/scripts/templates/operator_modal_view3d.py b/release/scripts/templates_py/operator_modal_view3d.py
index c870bbffdcf..c870bbffdcf 100644
--- a/release/scripts/templates/operator_modal_view3d.py
+++ b/release/scripts/templates_py/operator_modal_view3d.py
diff --git a/release/scripts/templates/operator_modal_view3d_raycast.py b/release/scripts/templates_py/operator_modal_view3d_raycast.py
index 3236c08cc8c..eac76922187 100644
--- a/release/scripts/templates/operator_modal_view3d_raycast.py
+++ b/release/scripts/templates_py/operator_modal_view3d_raycast.py
@@ -16,7 +16,6 @@ def main(context, event, ray_max=10000.0):
ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
ray_target = ray_origin + (view_vector * ray_max)
- scene.cursor_location = ray_target
def visible_objects_and_duplis():
"""Loop over (object, matrix) pairs (mesh only)"""
@@ -58,7 +57,9 @@ def main(context, event, ray_max=10000.0):
if obj.type == 'MESH':
hit, normal, face_index = obj_ray_cast(obj, matrix)
if hit is not None:
- length_squared = (hit - ray_origin).length_squared
+ hit_world = matrix * hit
+ scene.cursor_location = hit_world
+ length_squared = (hit_world - ray_origin).length_squared
if length_squared < best_length_squared:
best_length_squared = length_squared
best_obj = obj
@@ -67,6 +68,7 @@ def main(context, event, ray_max=10000.0):
# we could do lots of stuff but for the example just select.
if best_obj is not None:
best_obj.select = True
+ context.scene.objects.active = best_obj
class ViewOperatorRayCast(bpy.types.Operator):
@@ -105,3 +107,4 @@ def unregister():
if __name__ == "__main__":
register()
+
diff --git a/release/scripts/templates/operator_node.py b/release/scripts/templates_py/operator_node.py
index b689ce7634e..b689ce7634e 100644
--- a/release/scripts/templates/operator_node.py
+++ b/release/scripts/templates_py/operator_node.py
diff --git a/release/scripts/templates/operator_simple.py b/release/scripts/templates_py/operator_simple.py
index 715daa3a8b4..715daa3a8b4 100644
--- a/release/scripts/templates/operator_simple.py
+++ b/release/scripts/templates_py/operator_simple.py
diff --git a/release/scripts/templates/operator_uv.py b/release/scripts/templates_py/operator_uv.py
index fdd0b993f8b..fdd0b993f8b 100644
--- a/release/scripts/templates/operator_uv.py
+++ b/release/scripts/templates_py/operator_uv.py
diff --git a/release/scripts/templates/script_stub.py b/release/scripts/templates_py/script_stub.py
index 44c7b802e2c..44c7b802e2c 100644
--- a/release/scripts/templates/script_stub.py
+++ b/release/scripts/templates_py/script_stub.py
diff --git a/release/scripts/templates_py/ui_list.py b/release/scripts/templates_py/ui_list.py
new file mode 100644
index 00000000000..f71b342c854
--- /dev/null
+++ b/release/scripts/templates_py/ui_list.py
@@ -0,0 +1,79 @@
+import bpy
+
+
+class MATERIAL_UL_matslots_example(bpy.types.UIList):
+ # The draw_item function is called for each item of the collection that is visible in the list.
+ # data is the RNA object containing the collection,
+ # item is the current drawn item of the collection,
+ # icon is the "computed" icon for the item (as an integer, because some objects like materials or textures
+ # have custom icons ID, which are not available as enum items).
+ # active_data is the RNA object containing the active property for the collection (i.e. integer pointing to the
+ # active item of the collection).
+ # active_propname is the name of the active property (use 'getattr(active_data, active_propname)').
+ # index is index of the current item in the collection.
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ ob = data
+ slot = item
+ ma = slot.material
+ # draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code.
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ # You should always start your row layout by a label (icon + text), this will also make the row easily
+ # selectable in the list!
+ # We use icon_value of label, as our given icon is an integer value, not an enum ID.
+ # Note "data" names should never be translated!
+ layout.label(text=ma.name if ma else "", translate=False, icon_value=icon)
+ # And now we can add other UI stuff...
+ # Here, we add nodes info if this material uses (old!) shading nodes.
+ if ma and not context.scene.render.use_shading_nodes:
+ manode = ma.active_node_material
+ if manode:
+ # The static method UILayout.icon returns the integer value of the icon ID "computed" for the given
+ # RNA object.
+ layout.label(text="Node %s" % manode.name, translate=False, icon_value=layout.icon(manode))
+ elif ma.use_nodes:
+ layout.label(text="Node <none>", translate=False)
+ else:
+ layout.label(text="")
+ # 'GRID' layout type should be as compact as possible (typically a single icon!).
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
+# And now we can use this list everywhere in Blender. Here is a small example panel.
+class UIListPanelExample(bpy.types.Panel):
+ """Creates a Panel in the Object properties window"""
+ bl_label = "UIList Panel"
+ bl_idname = "OBJECT_PT_ui_list_example"
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "object"
+
+ def draw(self, context):
+ layout = self.layout
+
+ obj = context.object
+
+ # template_list now takes two new args.
+ # The first one is the identifier of the registered UIList to use (if you want only the default list,
+ # with no custom draw code, use "UI_UL_list").
+ layout.template_list("MATERIAL_UL_matslots_example", "", obj, "material_slots", obj, "active_material_index")
+
+ # The second one can usually be left as an empty string. It's an additional ID used to distinguish lists in case you
+ # use the same list several times in a given area.
+ layout.template_list("MATERIAL_UL_matslots_example", "compact", obj, "material_slots",
+ obj, "active_material_index", type='COMPACT')
+
+
+def register():
+ bpy.utils.register_class(MATERIAL_UL_matslots_example)
+ bpy.utils.register_class(UIListPanelExample)
+
+
+def unregister():
+ bpy.utils.unregister_class(MATERIAL_UL_matslots_example)
+ bpy.utils.unregister_class(UIListPanelExample)
+
+
+if __name__ == "__main__":
+ register() \ No newline at end of file
diff --git a/release/scripts/templates/ui_menu.py b/release/scripts/templates_py/ui_menu.py
index a21e5ed86c8..a21e5ed86c8 100644
--- a/release/scripts/templates/ui_menu.py
+++ b/release/scripts/templates_py/ui_menu.py
diff --git a/release/scripts/templates/ui_menu_simple.py b/release/scripts/templates_py/ui_menu_simple.py
index 2129dfd81a4..2129dfd81a4 100644
--- a/release/scripts/templates/ui_menu_simple.py
+++ b/release/scripts/templates_py/ui_menu_simple.py
diff --git a/release/scripts/templates/ui_panel.py b/release/scripts/templates_py/ui_panel.py
index cacdb83e815..cacdb83e815 100644
--- a/release/scripts/templates/ui_panel.py
+++ b/release/scripts/templates_py/ui_panel.py
diff --git a/release/scripts/templates/ui_panel_simple.py b/release/scripts/templates_py/ui_panel_simple.py
index 9bcc750560f..9bcc750560f 100644
--- a/release/scripts/templates/ui_panel_simple.py
+++ b/release/scripts/templates_py/ui_panel_simple.py
diff --git a/release/text/readme.html b/release/text/readme.html
index 414a7d8e744..54d112c5e2b 100644
--- a/release/text/readme.html
+++ b/release/text/readme.html
@@ -12,18 +12,18 @@
</style>
</head>
<body>
-<p class="title"><b>Blender 2.65</b></p>
+<p class="title"><b>Blender 2.66</b></p>
<p><br></p>
<p class="header"><b>About</b></p>
<p class="body">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, Windows and FreeBSD and has a large world-wide community.</p>
<p class="body">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="body">For more information, visit <a href="http://www.blender.org">blender.org</a>.</p>
<p><br></p>
-<p class="header"><b>2.65</b></p>
-<p class="body">The Blender Foundation and online developer community is proud to present Blender 2.65. This release is the sixth official stable release of the Blender 2.6 series, in which we will refine the 2.5 series and add exciting new features. <a href="http://www.blender.org/development/release-logs/blender-265/">More information about this release</a>.</p>
+<p class="header"><b>2.66</b></p>
+<p class="body">The Blender Foundation and online developer community is proud to present Blender 2.66. This release is the seventh official stable release of the Blender 2.6 series, in which we will refine the 2.5 series and add exciting new features. <a href="http://www.blender.org/development/release-logs/blender-266/">More information about this release</a>.</p>
<p><br></p>
<p class="header"><b>Bugs</b></p>
-<p class="body">Although Blender 2.65 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 → 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="body">Although Blender 2.66 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 → 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><br></p>
<p class="header"><b>Package Contents</b></p>
<p class="body">The downloaded Blender package includes:</p>
@@ -47,7 +47,7 @@
<p class="header"><b>Links</b></p>
<p class="body">Users:</p>
<p class="body"> General information <a href="http://www.blender.org">www.blender.org</a> <br>
- Full release log <a href="http://www.blender.org/development/release-logs/blender-265/">www.blender.org/development/release-logs/blender-265/</a><br>
+ Full release log <a href="http://www.blender.org/development/release-logs/blender-266/">www.blender.org/development/release-logs/blender-266/</a><br>
Tutorials <a href="http://www.blender.org/education-help/">www.blender.org/education-help/</a> <br>
Manual <a href="http://wiki.blender.org/index.php/Doc:2.6/Manual">wiki.blender.org/index.php/Doc:2.6/Manual</a><br>
User Forum <a href="http://www.blenderartists.org">www.blenderartists.org</a><br>
diff --git a/release/windows/contrib/vfapi/vfapi-plugin.c b/release/windows/contrib/vfapi/vfapi-plugin.c
index 99ca6c64e80..96a5ada8f14 100644
--- a/release/windows/contrib/vfapi/vfapi-plugin.c
+++ b/release/windows/contrib/vfapi/vfapi-plugin.c
@@ -127,12 +127,12 @@ static unsigned long getipaddress(const char * ipaddr)
return (ip);
}
-static void my_send(SOCKET sock, char * str)
+static void my_send(SOCKET sock, char *str)
{
send(sock, str, strlen(str), 0);
}
-static int my_recv(SOCKET sock, char * line, int maxlen)
+static int my_recv(SOCKET sock, char *line, int maxlen)
{
int got = 0;
int toget = maxlen;
@@ -148,7 +148,7 @@ static int my_recv(SOCKET sock, char * line, int maxlen)
return maxlen;
}
-static int my_gets(SOCKET sock, char * line, int maxlen)
+static int my_gets(SOCKET sock, char *line, int maxlen)
{
int last_rval = 0;
diff --git a/source/SConscript b/source/SConscript
index fdd126b28c6..432cfb31c7d 100644
--- a/source/SConscript
+++ b/source/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
SConscript(['blender/SConscript'])
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index ae3f3dce396..7e327028a01 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -43,6 +43,7 @@ set(SRC_DNA_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_dynamicpaint_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_effect_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_fileglobal_types.h
+ ${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_group_types.h
@@ -51,6 +52,7 @@ set(SRC_DNA_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_key_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_lamp_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_lattice_types.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_linestyle_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_listBase.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_material_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_mesh_types.h
@@ -66,6 +68,7 @@ set(SRC_DNA_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_packedFile_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_particle_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_property_types.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_rigidbody_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_scene_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_screen_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_sdna_types.h
@@ -107,7 +110,6 @@ add_subdirectory(makesdna)
add_subdirectory(makesrna)
if(WITH_COMPOSITOR)
- add_subdirectory(opencl) # later on this may be used more generally
add_subdirectory(compositor)
endif()
@@ -138,3 +140,8 @@ endif()
if(WITH_OPENCOLLADA)
add_subdirectory(collada)
endif()
+
+if(WITH_FREESTYLE)
+ add_subdirectory(freestyle)
+endif()
+
diff --git a/source/blender/SConscript b/source/blender/SConscript
index e1f81f9aaba..66d54961131 100644
--- a/source/blender/SConscript
+++ b/source/blender/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
import sys
@@ -39,5 +65,7 @@ if env['WITH_BF_COLLADA']:
SConscript (['collada/SConscript'])
if env['WITH_BF_COMPOSITOR']:
- SConscript (['compositor/SConscript',
- 'opencl/SConscript'])
+ SConscript (['compositor/SConscript'])
+
+if env['WITH_BF_FREESTYLE']:
+ SConscript (['freestyle/SConscript'])
diff --git a/source/blender/avi/SConscript b/source/blender/avi/SConscript
index 4d2ce8fd845..0e46781b768 100644
--- a/source/blender/avi/SConscript
+++ b/source/blender/avi/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('intern/*.c')
diff --git a/source/blender/avi/intern/avi.c b/source/blender/avi/intern/avi.c
index d6301b723a7..1b1ec1c08af 100644
--- a/source/blender/avi/intern/avi.c
+++ b/source/blender/avi/intern/avi.c
@@ -38,12 +38,15 @@
#include <stdio.h>
#include <ctype.h>
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
#include "MEM_guardedalloc.h"
#include "MEM_sys_types.h"
-#ifdef WIN32
-# include "BLI_winstuff.h"
-#endif
+#include "BLI_utildefines.h"
+#include "BLI_fileops.h"
#include "AVI_avi.h"
#include "avi_intern.h"
@@ -208,7 +211,7 @@ int AVI_is_avi(char *name)
FILE *fp;
int ret;
- fp = fopen(name, "rb");
+ fp = BLI_fopen(name, "rb");
if (fp == NULL)
return 0;
@@ -238,7 +241,7 @@ int AVI_is_avi(const char *name)
DEBUG_PRINT("opening movie\n");
movie.type = AVI_MOVIE_READ;
- movie.fp = fopen(name, "rb");
+ movie.fp = BLI_fopen(name, "rb");
movie.offset_table = NULL;
if (movie.fp == NULL)
@@ -404,7 +407,9 @@ int AVI_is_avi(const char *name)
}
if (j > 0) fseek(movie.fp, j, SEEK_CUR);
}
- else fseek(movie.fp, movie.streams[temp].sf_size, SEEK_CUR);
+ else {
+ fseek(movie.fp, movie.streams[temp].sf_size, SEEK_CUR);
+ }
/* Walk to the next LIST */
while (GET_FCC(movie.fp) != FCC("LIST")) {
@@ -439,7 +444,7 @@ AviError AVI_open_movie(const char *name, AviMovie *movie)
memset(movie, 0, sizeof(AviMovie));
movie->type = AVI_MOVIE_READ;
- movie->fp = fopen(name, "rb");
+ movie->fp = BLI_fopen(name, "rb");
movie->offset_table = NULL;
if (movie->fp == NULL)
@@ -595,8 +600,10 @@ AviError AVI_open_movie(const char *name, AviMovie *movie)
}
if (j > 0) fseek(movie->fp, j, SEEK_CUR);
}
- else fseek(movie->fp, movie->streams[temp].sf_size, SEEK_CUR);
-
+ else {
+ fseek(movie->fp, movie->streams[temp].sf_size, SEEK_CUR);
+ }
+
/* Walk to the next LIST */
while (GET_FCC(movie->fp) != FCC("LIST")) {
temp = GET_FCC(movie->fp);
@@ -761,7 +768,7 @@ AviError AVI_open_compress(char *name, AviMovie *movie, int streams, ...)
int64_t junk_pos;
movie->type = AVI_MOVIE_WRITE;
- movie->fp = fopen(name, "wb");
+ movie->fp = BLI_fopen(name, "wb");
movie->index_entries = 0;
@@ -950,7 +957,6 @@ AviError AVI_write_frame(AviMovie *movie, int frame_num, ...)
{
AviList list;
AviChunk chunk;
- AviIndexEntry *temp;
va_list ap;
int stream;
int64_t rec_off;
@@ -965,15 +971,7 @@ AviError AVI_write_frame(AviMovie *movie, int frame_num, ...)
if (frame_num + 1 > movie->index_entries) {
const size_t entry_size = (movie->header->Streams + 1) * sizeof(AviIndexEntry);
-
- if (movie->entries != NULL) {
- temp = (AviIndexEntry *)MEM_recallocN(movie->entries, (frame_num + 1) * entry_size);
- }
- else {
- temp = (AviIndexEntry *) MEM_callocN((frame_num + 1) * entry_size, "newidxentry");
- }
-
- movie->entries = temp;
+ movie->entries = (AviIndexEntry *)MEM_recallocN(movie->entries, (frame_num + 1) * entry_size);
movie->index_entries = frame_num + 1;
}
diff --git a/source/blender/avi/intern/avi_endian.c b/source/blender/avi/intern/avi_endian.c
index 70add8bd90f..9720d83f2c8 100644
--- a/source/blender/avi/intern/avi_endian.c
+++ b/source/blender/avi/intern/avi_endian.c
@@ -49,7 +49,7 @@
#ifdef __BIG_ENDIAN__
/* copied from BLI_endian_switch_inline.h */
-static void invert(int *num)
+static void invert(int *val)
{
int tval = *val;
*val = ((tval >> 24)) |
diff --git a/source/blender/avi/intern/avi_intern.h b/source/blender/avi/intern/avi_intern.h
index c8d54fe99e9..5dc48657831 100644
--- a/source/blender/avi/intern/avi_intern.h
+++ b/source/blender/avi/intern/avi_intern.h
@@ -37,9 +37,27 @@
unsigned int GET_FCC (FILE *fp);
unsigned int GET_TCC (FILE *fp);
-#define PUT_FCC(ch4, fp) putc(ch4[0],fp); putc(ch4[1],fp); putc(ch4[2],fp); putc(ch4[3],fp)
-#define PUT_FCCN(num, fp) putc((num>>0)&0377,fp); putc((num>>8)&0377,fp); putc((num>>16)&0377,fp); putc((num>>24)&0377,fp)
-#define PUT_TCC(ch2, fp) putc(ch2[0],fp); putc(ch2[1],fp)
+#define PUT_FCC(ch4, fp) \
+{ \
+ putc(ch4[0], fp); \
+ putc(ch4[1], fp); \
+ putc(ch4[2], fp); \
+ putc(ch4[3], fp); \
+} (void)0
+
+#define PUT_FCCN(num, fp) \
+{ \
+ putc((num >> 0) & 0377, fp); \
+ putc((num >> 8) & 0377, fp); \
+ putc((num >> 16) & 0377, fp); \
+ putc((num >> 24) & 0377, fp); \
+} (void)0
+
+#define PUT_TCC(ch2, fp) \
+{ \
+ putc(ch2[0], fp); \
+ putc(ch2[1], fp); \
+} (void)0
void *avi_format_convert (AviMovie *movie, int stream, void *buffer, AviFormat from, AviFormat to, int *size);
diff --git a/source/blender/avi/intern/avi_mjpeg.c b/source/blender/avi/intern/avi_mjpeg.c
index 396f1199cd9..91b8fa5a060 100644
--- a/source/blender/avi/intern/avi_mjpeg.c
+++ b/source/blender/avi/intern/avi_mjpeg.c
@@ -206,7 +206,7 @@ static int Decode_JPEG(unsigned char *inBuffer, unsigned char *outBuffer, unsign
return 1;
}
-static void Compress_JPEG(int quality, unsigned char *outbuffer, unsigned char *inBuffer, int width, int height, int bufsize)
+static void Compress_JPEG(int quality, unsigned char *outbuffer, const unsigned char *inBuffer, int width, int height, int bufsize)
{
int i, rowstride;
unsigned int y;
@@ -316,7 +316,8 @@ static int check_and_decode_jpeg(unsigned char *inbuf, unsigned char *outbuf, in
}
}
-static void check_and_compress_jpeg(int quality, unsigned char *outbuf, unsigned char *inbuf, int width, int height, int bufsize)
+static void check_and_compress_jpeg(int quality, unsigned char *outbuf, const unsigned char *inbuf,
+ int width, int height, int bufsize)
{
/* JPEG's are always multiples of 16, extra is ignored in AVI's */
if ((width & 0xF) || (height & 0xF)) {
@@ -379,7 +380,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);
+ check_and_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);
@@ -388,10 +393,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);
+ check_and_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);
+ 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);
}
*size += numbytes;
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index 6f348ccc267..fd8bd196717 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -37,6 +37,7 @@ struct ColorManagedDisplay;
int BLF_init(int points, int dpi);
void BLF_exit(void);
+void BLF_default_dpi(int dpi);
void BLF_cache_clear(void);
@@ -76,6 +77,7 @@ void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t l
/* 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);
/* This function return the bounding box of the string
* and are not multiplied by the aspect.
@@ -182,6 +184,7 @@ void BLF_dir_free(char **dirs, int count);
#define BLF_KERNING_DEFAULT (1 << 3)
#define BLF_MATRIX (1 << 4)
#define BLF_ASPECT (1 << 5)
+#define BLF_HINTING (1 << 6)
#define BLF_DRAW_STR_DUMMY_MAX 1024
diff --git a/source/blender/blenfont/BLF_translation.h b/source/blender/blenfont/BLF_translation.h
index 159d4b067b6..dc72c77b3bf 100644
--- a/source/blender/blenfont/BLF_translation.h
+++ b/source/blender/blenfont/BLF_translation.h
@@ -33,6 +33,8 @@
#ifndef __BLF_TRANSLATION_H__
#define __BLF_TRANSLATION_H__
+#include "BLI_utildefines.h" /* for bool type */
+
#define TEXT_DOMAIN_NAME "blender"
/* blf_lang.c */
@@ -48,26 +50,37 @@ void BLF_lang_free(void);
/* Set the current locale. */
void BLF_lang_set(const char *);
-/* Get the current locale (short code, e.g. es_ES). */
+/* 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 */
-#ifdef WITH_INTERNATIONAL
unsigned char *BLF_get_unifont(int *unifont_size);
void BLF_free_unifont(void);
-#endif
+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 */
-int BLF_translate_iface(void);
-int BLF_translate_tooltips(void);
+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. */
@@ -76,22 +89,26 @@ const char *BLF_translate_do_tooltip(const char *msgctxt, const char *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 CTX_IFACE_(context, msgid) BLF_translate_do_iface(context, msgid)
- #define CTX_TIP_(context, msgid) BLF_translate_do_tooltip(context, msgid)
+/*# 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 CTX_IFACE_(context, msgid) ((void)context, msgid)
- #define CTX_TIP_(context, msgid) ((void)context, msgid)
+/*# 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 most
+ * 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, ...)
@@ -100,10 +117,19 @@ const char *BLF_translate_do_tooltip(const char *msgctxt, const char *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. Just in case... */
-#define BLF_I18NCONTEXT_DEFAULT ""
+/* 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"
@@ -115,6 +141,7 @@ const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid);
#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"
@@ -143,4 +170,53 @@ const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid);
#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_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_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} \
+}
+
#endif /* __BLF_TRANSLATION_H__ */
diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt
index 90baef14a74..7bb80c34323 100644
--- a/source/blender/blenfont/CMakeLists.txt
+++ b/source/blender/blenfont/CMakeLists.txt
@@ -29,6 +29,7 @@ set(INC
../editors/include
../makesdna
../makesrna
+ ../python
../imbuf
../../../intern/guardedalloc
../../../intern/locale
diff --git a/source/blender/blenfont/SConscript b/source/blender/blenfont/SConscript
index c0591c877ef..3529330a308 100644
--- a/source/blender/blenfont/SConscript
+++ b/source/blender/blenfont/SConscript
@@ -1,11 +1,37 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
import sys
Import ('env')
sources = env.Glob('intern/*.c')
incs = '. intern #/intern/guardedalloc #/intern/locale ../blenkernel ../blenlib ../blenloader'
-incs += ' ../makesdna ../makesrna ../imbuf ../editors/include'
+incs += ' ../makesdna ../makesrna ../python ../imbuf ../editors/include'
incs += ' #/extern/glew/include'
incs += ' ' + env['BF_FREETYPE_INC']
@@ -17,4 +43,4 @@ if sys.platform == 'win32' or env['OURPLATFORM'] == 'linuxcross':
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
-env.BlenderLib ( 'bf_blenfont', sources, Split(incs), Split(defs), libtype=['core','player'], priority=[210,210] )
+env.BlenderLib ( 'bf_blenfont', sources, Split(incs), defines=defs, libtype=['core','player'], priority=[210,210] )
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index 778b6c11e5a..6523aa87473 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -43,6 +43,8 @@
#include "DNA_listBase.h"
#include "DNA_vec_types.h"
+#include "BLI_math.h"
+
#include "BIF_gl.h"
#include "BLF_api.h"
@@ -87,6 +89,11 @@ int BLF_init(int points, int dpi)
return blf_font_init();
}
+void BLF_default_dpi(int dpi)
+{
+ global_font_dpi = dpi;
+}
+
void BLF_exit(void)
{
FontBLF *font;
@@ -511,8 +518,8 @@ static void blf_draw__start(FontBLF *font, GLint *mode, GLint *param)
if (font->flags & BLF_ASPECT)
glScalef(font->aspect[0], font->aspect[1], font->aspect[2]);
- if (font->flags & BLF_ROTATION)
- glRotatef(font->angle, 0.0f, 0.0f, 1.0f);
+ if (font->flags & BLF_ROTATION) /* radians -> degrees */
+ glRotatef(font->angle * (float)(180.0 / M_PI), 0.0f, 0.0f, 1.0f);
if (font->shadow || font->blur)
glGetFloatv(GL_CURRENT_COLOR, font->orig_col);
@@ -569,6 +576,21 @@ 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)
+{
+ FontBLF *font = blf_get(fontid);
+ GLint mode, param;
+ int columns = 0;
+
+ if (font && font->glyph_cache) {
+ blf_draw__start(font, &mode, &param);
+ columns = blf_font_draw_mono(font, str, len, cwidth);
+ blf_draw__end(mode, param);
+ }
+
+ return columns;
+}
+
void BLF_boundbox(int fontid, const char *str, rctf *box)
{
FontBLF *font = blf_get(fontid);
@@ -597,6 +619,7 @@ void BLF_width_and_height_default(const char *str, float *width, float *height)
return;
}
+ BLF_size(global_font_default, global_font_points, global_font_dpi);
BLF_width_and_height(global_font_default, str, width, height);
}
diff --git a/source/blender/blenfont/intern/blf_dir.c b/source/blender/blenfont/intern/blf_dir.c
index b6a98faa48c..116a55c0579 100644
--- a/source/blender/blenfont/intern/blf_dir.c
+++ b/source/blender/blenfont/intern/blf_dir.c
@@ -41,6 +41,7 @@
#include "DNA_vec_types.h"
+#include "BLI_utildefines.h"
#include "BLI_fileops.h"
#include "BLI_listbase.h"
#include "BLI_path_util.h"
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 1900efa2dbc..f2c36475870 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -219,6 +219,40 @@ void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len)
}
}
+/* use fixed column width, but an utf8 character may occupy multiple columns */
+int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
+{
+ unsigned int c;
+ GlyphBLF *g;
+ int col, columns = 0;
+ int pen_x = 0, pen_y = 0;
+ size_t i = 0;
+ GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
+
+ blf_font_ensure_ascii_table(font);
+
+ while ((i < len) && str[i]) {
+ BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
+
+ if (c == BLI_UTF8_ERR)
+ break;
+ if (g == NULL)
+ continue;
+
+ /* do not return this loop if clipped, we want every character tested */
+ blf_glyph_render(font, g, (float)pen_x, (float)pen_y);
+
+ col = BLI_wcwidth((wchar_t)c);
+ if (col < 0)
+ col = 1;
+
+ columns += col;
+ pen_x += cwidth * col;
+ }
+
+ return columns;
+}
+
/* Sanity checks are done by BLF_draw_buffer() */
void blf_font_buffer(FontBLF *font, const char *str)
{
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 91ecded88be..a6b04b24399 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -83,7 +83,7 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
memset(gc->glyph_ascii_table, 0, sizeof(gc->glyph_ascii_table));
memset(gc->bucket, 0, sizeof(gc->bucket));
- gc->textures = (GLuint *)malloc(sizeof(GLuint) * 256);
+ gc->textures = (GLuint *)MEM_mallocN(sizeof(GLuint) * 256, __func__);
gc->ntex = 256;
gc->cur_tex = -1;
gc->x_offs = 0;
@@ -150,7 +150,7 @@ void blf_glyph_cache_free(GlyphCacheBLF *gc)
if (gc->cur_tex + 1 > 0)
glDeleteTextures(gc->cur_tex + 1, gc->textures);
- free((void *)gc->textures);
+ MEM_freeN((void *)gc->textures);
MEM_freeN(gc);
}
@@ -178,8 +178,7 @@ static void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc)
gc->p2_height = font->max_tex_size;
tot_mem = gc->p2_width * gc->p2_height;
- buf = (unsigned char *)malloc(tot_mem);
- memset((void *)buf, 0, tot_mem);
+ buf = (unsigned char *)MEM_callocN(tot_mem, __func__);
glGenTextures(1, &gc->textures[gc->cur_tex]);
glBindTexture(GL_TEXTURE_2D, (font->tex_bind_state = gc->textures[gc->cur_tex]));
@@ -189,7 +188,7 @@ static void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, gc->p2_width, gc->p2_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buf);
- free((void *)buf);
+ MEM_freeN((void *)buf);
}
GlyphBLF *blf_glyph_search(GlyphCacheBLF *gc, unsigned int c)
@@ -214,6 +213,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
FT_Error err;
FT_Bitmap bitmap, tempbitmap;
int sharp = (U.text_render & USER_TEXT_DISABLE_AA);
+ int flags = FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP;
FT_BBox bbox;
unsigned int key;
@@ -221,10 +221,13 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
if (g)
return g;
+ if (font->flags & BLF_HINTING)
+ flags &= ~FT_LOAD_NO_HINTING;
+
if (sharp)
err = FT_Load_Glyph(font->face, (FT_UInt)index, FT_LOAD_TARGET_MONO);
else
- err = FT_Load_Glyph(font->face, (FT_UInt)index, FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP); /* Sure about NO_* flags? */
+ err = FT_Load_Glyph(font->face, (FT_UInt)index, flags);
if (err)
return NULL;
@@ -383,7 +386,7 @@ int blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
if (gc->cur_tex == -1) {
blf_glyph_cache_texture(font, gc);
gc->x_offs = gc->pad;
- gc->y_offs = gc->pad;
+ gc->y_offs = 0;
}
if (gc->x_offs > (gc->p2_width - gc->max_glyph_width)) {
@@ -391,7 +394,7 @@ int blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
gc->y_offs += gc->max_glyph_height;
if (gc->y_offs > (gc->p2_height - gc->max_glyph_height)) {
- gc->y_offs = gc->pad;
+ gc->y_offs = 0;
blf_glyph_cache_texture(font, gc);
}
}
@@ -400,6 +403,19 @@ int blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
g->xoff = gc->x_offs;
g->yoff = gc->y_offs;
+ /* prevent glTexSubImage2D from failing if the character
+ * asks for pixels out of bounds, this tends only to happen
+ * with very small sizes (5px high or less) */
+ if (UNLIKELY((g->xoff + g->width) > gc->p2_width)) {
+ g->width -= (g->xoff + g->width) - gc->p2_width;
+ BLI_assert(g->width > 0);
+ }
+ if (UNLIKELY((g->yoff + g->height) > gc->p2_height)) {
+ g->height -= (g->yoff + g->height) - gc->p2_height;
+ BLI_assert(g->height > 0);
+ }
+
+
glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index 65a54783978..b1301be46fd 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -53,6 +53,7 @@ void blf_font_attach_from_mem(struct FontBLF *font, const unsigned char *mem, in
void blf_font_size(struct FontBLF *font, int size, 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);
+int blf_font_draw_mono(struct FontBLF *font, const char *str, size_t len, int cwidth);
void blf_font_buffer(struct FontBLF *font, const char *str);
void blf_font_boundbox(struct FontBLF *font, const char *str, struct rctf *box);
void blf_font_width_and_height(struct FontBLF *font, const char *str, float *width, float *height);
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index 1acc3dad4cf..de6e70e4461 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -166,7 +166,7 @@ typedef struct FontBLF {
/* initial position for draw the text. */
float pos[3];
- /* angle in degrees. */
+ /* angle in radians. */
float angle;
/* blur: 3 or 5 large kernel */
diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c
index 0ed48623dd5..65abfc52ee5 100644
--- a/source/blender/blenfont/intern/blf_lang.c
+++ b/source/blender/blenfont/intern/blf_lang.c
@@ -27,30 +27,28 @@
* \ingroup blf
*/
-
-#include "BLF_translation.h" /* own include */
-
-#ifdef WITH_INTERNATIONAL
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "boost_locale_wrapper.h"
-
-#include "BKE_global.h"
-
-#include "DNA_userdef_types.h"
-
#include "RNA_types.h"
-#include "MEM_guardedalloc.h"
+#include "BLF_translation.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_global.h"
+
+#include "DNA_userdef_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#ifdef WITH_INTERNATIONAL
+
+#include "boost_locale_wrapper.h"
/* Locale options. */
static const char **locales = NULL;
@@ -58,9 +56,6 @@ static int num_locales = 0;
static EnumPropertyItem *locales_menu = NULL;
static int num_locales_menu = 0;
-#define ULANGUAGE ((U.language >= 0 && U.language < num_locales) ? U.language : 0)
-#define LOCALE(_id) (locales ? locales[_id] : "")
-
static void free_locales(void)
{
if (locales) {
@@ -83,15 +78,16 @@ static void free_locales(void)
static void fill_locales(void)
{
- char *languages_path = BLI_get_folder(BLENDER_DATAFILES, "locale");
+ const char * const languages_path = BLI_get_folder(BLENDER_DATAFILES, "locale");
+ char languages[FILE_MAX];
LinkNode *lines = NULL, *line;
char *str;
int idx = 0;
free_locales();
- BLI_join_dirfile(languages_path, FILE_MAX, languages_path, "languages");
- line = lines = BLI_file_read_as_lines(languages_path);
+ 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...
* Should not be a problem, though, as this file is script-generated! */
@@ -99,7 +95,7 @@ static void fill_locales(void)
/* First loop to find highest locale ID */
while (line) {
int t;
- str = (char*) line->link;
+ str = (char *)line->link;
if (str[0] == '#' || str[0] == '\0') {
line = line->next;
continue; /* Comment or void... */
@@ -112,17 +108,17 @@ static void fill_locales(void)
}
num_locales_menu++; /* The "closing" void item... */
- /* And now, buil locales and locale_menu! */
+ /* And now, build locales and locale_menu! */
locales_menu = MEM_callocN(num_locales_menu * sizeof(EnumPropertyItem), __func__);
line = lines;
/* Do not allocate locales with zero-sized mem, as LOCALE macro uses NULL locales as invalid marker! */
if (num_locales > 0) {
- locales = MEM_callocN(num_locales * sizeof(char*), __func__);
+ locales = MEM_callocN(num_locales * sizeof(char *), __func__);
while (line) {
int id;
char *loc, *sep1, *sep2, *sep3;
- str = (char*) line->link;
+ str = (char *)line->link;
if (str[0] == '#' || str[0] == '\0') {
line = line->next;
continue;
@@ -176,15 +172,21 @@ static void fill_locales(void)
BLI_file_free_lines(lines);
}
+#endif /* WITH_INTERNATIONAL */
EnumPropertyItem *BLF_RNA_lang_enum_properties(void)
{
+#ifdef WITH_INTERNATIONAL
return locales_menu;
+#else
+ return NULL;
+#endif
}
void BLF_lang_init(void)
{
- char *messagepath = BLI_get_folder(BLENDER_DATAFILES, "locale");
+#ifdef WITH_INTERNATIONAL
+ const char * const messagepath = BLI_get_folder(BLENDER_DATAFILES, "locale");
if (messagepath) {
bl_locale_init(messagepath, TEXT_DOMAIN_NAME);
@@ -193,15 +195,26 @@ void BLF_lang_init(void)
else {
printf("%s: 'locale' data path for translations not found, continuing\n", __func__);
}
+#else
+#endif
}
void BLF_lang_free(void)
{
+#ifdef WITH_INTERNATIONAL
free_locales();
+#else
+#endif
}
+#ifdef WITH_INTERNATIONAL
+# define ULANGUAGE ((U.language >= 0 && U.language < num_locales) ? U.language : 0)
+# define LOCALE(_id) (locales ? locales[(_id)] : "")
+#endif
+
void BLF_lang_set(const char *str)
{
+#ifdef WITH_INTERNATIONAL
int ulang = ULANGUAGE;
const char *short_locale = str ? str : LOCALE(ulang);
const char *short_locale_utf8 = NULL;
@@ -229,40 +242,79 @@ void BLF_lang_set(const char *str)
bl_locale_set(short_locale_utf8);
if (short_locale[0]) {
- MEM_freeN((void*)short_locale_utf8);
+ MEM_freeN((void *)short_locale_utf8);
}
+#else
+ (void)str;
+#endif
}
+/* Get the current locale (short code, e.g. es_ES). */
const char *BLF_lang_get(void)
{
- int uilang = ULANGUAGE;
- return LOCALE(uilang);
+#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();
+ }
+ return locale;
+#else
+ return "";
+#endif
}
#undef LOCALE
#undef ULANGUAGE
-#else /* ! WITH_INTERNATIONAL */
-
-void BLF_lang_init(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: 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)
{
- return;
-}
+ char *m1, *m2, *_t = NULL;
-void BLF_lang_free(void)
-{
- return;
-}
+ m1 = strchr(locale, '_');
+ m2 = strchr(locale, '@');
-void BLF_lang_set(const char *str)
-{
- (void)str;
- return;
-}
-
-const char *BLF_lang_get(void)
-{
- return "";
+ if (language || language_variant) {
+ if (m1 || m2) {
+ _t = m1 ? BLI_strdupn(locale, m1 - locale) : BLI_strdupn(locale, m2 - locale);
+ if (language)
+ *language = _t;
+ }
+ else if (language) {
+ *language = BLI_strdup(locale);
+ }
+ }
+ if (country) {
+ if (m1)
+ *country = m2 ? BLI_strdupn(m1 + 1, m2 - (m1 + 1)) : BLI_strdup(m1 + 1);
+ else
+ *country = NULL;
+ }
+ if (variant) {
+ if (m2)
+ *variant = BLI_strdup(m2 + 1);
+ else
+ *variant = NULL;
+ }
+ if (language_country) {
+ if (m1)
+ *language_country = m2 ? BLI_strdupn(locale, m2 - locale) : BLI_strdup(locale);
+ else
+ *language_country = NULL;
+ }
+ if (language_variant) {
+ if (m2)
+ *language_variant = m1 ? BLI_strdupcat(_t, m2) : BLI_strdup(locale);
+ else
+ *language_variant = NULL;
+ }
+ if (_t && !language) {
+ MEM_freeN(_t);
+ }
}
-
-#endif /* WITH_INTERNATIONAL */
diff --git a/source/blender/blenfont/intern/blf_translation.c b/source/blender/blenfont/intern/blf_translation.c
index 5d4b631688a..57f442f8bfc 100644
--- a/source/blender/blenfont/intern/blf_translation.c
+++ b/source/blender/blenfont/intern/blf_translation.c
@@ -33,28 +33,33 @@
#include "BLF_translation.h"
-#ifdef WITH_INTERNATIONAL
-
-#include "boost_locale_wrapper.h"
-
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
+#include "BLI_fileops.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
-#include "BLI_path_util.h"
-#include "BLI_fileops.h"
#include "DNA_userdef_types.h" /* For user settings. */
+#include "BPY_extern.h"
+
+#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 *unifont_size_r)
{
+#ifdef WITH_INTERNATIONAL
if (unifont_ttf == NULL) {
- char *fontpath = BLI_get_folder(BLENDER_DATAFILES, "fonts");
+ const char * const fontpath = BLI_get_folder(BLENDER_DATAFILES, "fonts");
if (fontpath) {
char unifont_path[1024];
@@ -70,44 +75,114 @@ unsigned char *BLF_get_unifont(int *unifont_size_r)
*unifont_size_r = unifont_size;
return unifont_ttf;
+#else
+ (void)unifont_size_r;
+ 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 *unifont_size_r)
+{
+#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__);
+ }
+ }
+
+ *unifont_size_r = unifont_mono_size;
+
+ return unifont_mono_ttf;
+#else
+ (void)unifont_size_r;
+ 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)
+{
+ /* We use the "short" test, a more complete one could be:
+ * return (!msgctxt || !msgctxt[0] || !strcmp(msgctxt == BLF_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]);
+}
const char *BLF_pgettext(const char *msgctxt, const char *msgid)
{
#ifdef WITH_INTERNATIONAL
+ const char *ret = msgid;
+
if (msgid && msgid[0]) {
- return bl_locale_pgettext(msgctxt, msgid);
+ if (BLF_is_default_context(msgctxt)) {
+ msgctxt = BLF_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!
+ */
+ if (ret == msgid) {
+ ret = BPY_app_translations_py_pgettext(msgctxt, msgid);
+ }
}
- return "";
+
+ return ret;
#else
(void)msgctxt;
return msgid;
#endif
}
-int BLF_translate_iface(void)
+bool BLF_translate_iface(void)
{
#ifdef WITH_INTERNATIONAL
return (U.transopts & USER_DOTRANSLATE) && (U.transopts & USER_TR_IFACE);
#else
- return 0;
+ return false;
#endif
}
-int BLF_translate_tooltips(void)
+bool BLF_translate_tooltips(void)
{
#ifdef WITH_INTERNATIONAL
return (U.transopts & USER_DOTRANSLATE) && (U.transopts & USER_TR_TOOLTIPS);
#else
- return 0;
+ return false;
+#endif
+}
+
+bool BLF_translate_new_dataname(void)
+{
+#ifdef WITH_INTERNATIONAL
+ return (U.transopts & USER_DOTRANSLATE) && (U.transopts & USER_TR_NEWDATANAME);
+#else
+ return false;
#endif
}
@@ -140,3 +215,18 @@ const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid)
return msgid;
#endif
}
+
+const char *BLF_translate_do_new_dataname(const char *msgctxt, const char *msgid)
+{
+#ifdef WITH_INTERNATIONAL
+ if (BLF_translate_new_dataname()) {
+ return BLF_pgettext(msgctxt, msgid);
+ }
+ else {
+ return msgid;
+ }
+#else
+ (void)msgctxt;
+ return msgid;
+#endif
+}
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 617c4cd2bc8..51c46bcc235 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -95,6 +95,8 @@ struct BMEditMesh;
struct ListBase;
struct PBVH;
+#define DM_OMP_LIMIT 10000 /* setting zero so we can catch bugs in OpenMP/BMesh */
+
/* number of sub-elements each mesh element has (for interpolation) */
#define SUB_ELEMS_VERT 0
#define SUB_ELEMS_EDGE 2
@@ -105,6 +107,11 @@ struct PBVH;
* Also, the mface origindex layer indexes mpolys, not mfaces.
*/
+typedef struct DMCoNo {
+ float co[3];
+ float no[3];
+} DMCoNo;
+
typedef struct DMGridAdjacency {
int index[4];
int rotation[4];
@@ -168,6 +175,9 @@ struct DerivedMesh {
float auto_bump_scale;
DMDirtyFlag dirty;
+ /* use for converting to BMesh which doesn't store bevel weight and edge crease by default */
+ char cd_flag;
+
/** Calculate vert and face normals */
void (*calcNormals)(DerivedMesh *dm);
@@ -598,12 +608,12 @@ void DM_interp_poly_data(struct DerivedMesh *source, struct DerivedMesh *dest,
float *weights, int count, int dest_index);
/* Temporary? A function to give a colorband to derivedmesh for vertexcolor ranges */
-void vDM_ColorBand_store(struct ColorBand *coba);
+void vDM_ColorBand_store(const struct ColorBand *coba, const char alert_color[4]);
/** Simple function to get me->totvert amount of vertices/normals,
* correctly deformed and subsurfered. Needed especially when vertexgroups are involved.
* In use now by vertex/weight paint and particles */
-float *mesh_get_mapped_verts_nors(struct Scene *scene, struct Object *ob);
+DMCoNo *mesh_get_mapped_verts_nors(struct Scene *scene, struct Object *ob);
/* */
DerivedMesh *mesh_get_derived_final(struct Scene *scene, struct Object *ob,
@@ -721,4 +731,4 @@ BLI_INLINE int DM_origindex_mface_mpoly(const int *index_mf_to_mpoly, const int
return (j != ORIGINDEX_NONE) ? (index_mp_to_orig ? index_mp_to_orig[j] : j) : ORIGINDEX_NONE;
}
-#endif
+#endif /* __BKE_DERIVEDMESH_H__ */
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 2d7030b2d42..12c9f6b449f 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -44,6 +44,7 @@ struct FCurve;
struct bPose;
struct bItasc;
struct bPoseChannel;
+struct Main;
struct Object;
struct Scene;
struct ID;
@@ -56,7 +57,7 @@ extern "C" {
/* Action Lib Stuff ----------------- */
/* Allocate a new bAction with the given name */
-struct bAction *add_empty_action(const char name[]);
+struct bAction *add_empty_action(struct Main *bmain, const char name[]);
/* Allocate a copy of the given Action and all its data */
struct bAction *BKE_action_copy(struct bAction *src);
@@ -220,7 +221,7 @@ void BKE_pose_remove_group(struct Object *ob);
void what_does_obaction(struct Object *ob, struct Object *workob, struct bPose *pose, struct bAction *act, char groupname[], float cframe);
/* for proxy */
-void BKE_pose_copy_result(struct bPose *to, struct bPose *from);
+bool BKE_pose_copy_result(struct bPose *to, struct bPose *from);
/* clear all transforms */
void BKE_pose_rest(struct bPose *pose);
diff --git a/source/blender/blenkernel/BKE_addon.h b/source/blender/blenkernel/BKE_addon.h
new file mode 100644
index 00000000000..eafaec3e605
--- /dev/null
+++ b/source/blender/blenkernel/BKE_addon.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.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __BKE_ADDON_H__
+#define __BKE_ADDON_H__
+
+#include "RNA_types.h"
+
+typedef struct bAddonPrefType {
+ /* type info */
+ char idname[64]; // best keep the same size as BKE_ST_MAXNAME
+
+ /* RNA integration */
+ ExtensionRNA ext;
+} bAddonPrefType;
+
+bAddonPrefType *BKE_addon_pref_type_find(const char *idname, int quiet);
+void BKE_addon_pref_type_add(bAddonPrefType *apt);
+void BKE_addon_pref_type_remove(bAddonPrefType *apt);
+
+void BKE_addon_pref_type_init(void);
+void BKE_addon_pref_type_free(void);
+
+#endif /* __BKE_ADDON_H__ */
diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h
index 11537964e32..539c5780cd5 100644
--- a/source/blender/blenkernel/BKE_anim.h
+++ b/source/blender/blenkernel/BKE_anim.h
@@ -65,8 +65,8 @@ int where_on_path(struct Object *ob, float ctime, float vec[4], float dir[3], fl
/* ---------------------------------------------------- */
/* Dupli-Geometry */
-struct ListBase *object_duplilist_ex(struct Scene *sce, struct Object *ob, int update, int for_render);
-struct ListBase *object_duplilist(struct Scene *sce, struct Object *ob, int for_render);
+struct ListBase *object_duplilist_ex(struct Scene *sce, struct Object *ob, bool update, bool for_render);
+struct ListBase *object_duplilist(struct Scene *sce, struct Object *ob, bool for_render);
void free_object_duplilist(struct ListBase *lb);
int count_duplilist(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index e648523aec3..dd150ba6a63 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -63,10 +63,10 @@ short BKE_animdata_set_action(struct ReportList *reports, struct ID *id, struct
void BKE_free_animdata(struct ID *id);
/* Copy AnimData */
-struct AnimData *BKE_copy_animdata(struct AnimData *adt, const short do_action);
+struct AnimData *BKE_copy_animdata(struct AnimData *adt, const bool do_action);
/* Copy AnimData */
-int BKE_copy_animdata_id(struct ID *id_to, struct ID *id_from, const short do_action);
+int BKE_copy_animdata_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);
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 765a00b8d4b..fb9e9f4e691 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -73,7 +73,7 @@ typedef struct PoseTree {
extern "C" {
#endif
-struct bArmature *BKE_armature_add(const char *name);
+struct bArmature *BKE_armature_add(struct Main *bmain, const char *name);
struct bArmature *BKE_armature_from_object(struct Object *ob);
void BKE_armature_bonelist_free(struct ListBase *lb);
void BKE_armature_free(struct bArmature *arm);
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index cd75749fa3c..c6b02bc8361 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -41,8 +41,8 @@ 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 265
-#define BLENDER_SUBVERSION 0
+#define BLENDER_VERSION 266
+#define BLENDER_SUBVERSION 3
/* 262 was the last editmesh release but it has compatibility code for bmesh data */
#define BLENDER_MINVERSION 262
@@ -50,7 +50,7 @@ extern "C" {
/* used by packaging tools */
/* can be left blank, otherwise a,b,c... etc with no quotes */
-#define BLENDER_VERSION_CHAR
+#define BLENDER_VERSION_CHAR a
/* alpha/beta/rc/release, docs use this */
#define BLENDER_VERSION_CYCLE alpha
@@ -62,6 +62,7 @@ struct bContext;
struct ReportList;
struct Scene;
struct Main;
+struct ID;
int BKE_read_file(struct bContext *C, const char *filepath, struct ReportList *reports);
@@ -69,15 +70,20 @@ int BKE_read_file(struct bContext *C, const char *filepath, struct ReportList *r
#define BKE_READ_FILE_OK 1 /* OK */
#define BKE_READ_FILE_OK_USERPREFS 2 /* OK, and with new user settings */
-int BKE_read_file_from_memory(struct bContext *C, char *filebuf, int filelength, struct ReportList *reports);
+int BKE_read_file_from_memory(struct bContext *C, const void *filebuf, int filelength, struct ReportList *reports);
int BKE_read_file_from_memfile(struct bContext *C, struct MemFile *memfile, struct ReportList *reports);
+int BKE_read_file_userdef(const char *filepath, struct ReportList *reports);
+int BKE_write_file_userdef(const char *filepath, struct ReportList *reports);
+
void free_blender(void);
void initglobals(void);
/* load new userdef from file, exit blender */
void BKE_userdef_free(void);
-
+/* handle changes in userdef */
+void BKE_userdef_state(void);
+
/* set this callback when a UI is running */
void set_blender_test_break_cb(void (*func)(void) );
int blender_test_break(void);
@@ -93,9 +99,15 @@ extern void BKE_reset_undo(void);
extern char *BKE_undo_menu_string(void);
extern void BKE_undo_number(struct bContext *C, int nr);
extern const char *BKE_undo_get_name(int nr, int *active);
-extern void BKE_undo_save_quit(void);
+extern int BKE_undo_save_file(const char *filename);
extern struct Main *BKE_undo_get_main(struct Scene **scene);
+ /* copybuffer */
+void BKE_copybuffer_begin(void);
+void BKE_copybuffer_tag_ID(struct ID *id);
+int BKE_copybuffer_save(const char *filename, struct ReportList *reports);
+ int BKE_copybuffer_paste(struct bContext *C, const char *libname, struct ReportList *reports);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_bmesh.h b/source/blender/blenkernel/BKE_bmesh.h
index 8bfee836c0d..4bc21625cf3 100644
--- a/source/blender/blenkernel/BKE_bmesh.h
+++ b/source/blender/blenkernel/BKE_bmesh.h
@@ -38,7 +38,7 @@
/*NOTE: this is the bmesh 1.0 code. it's completely outdated.*/
/* uncomment to use the new bevel operator as a modifier */
-// #define USE_BM_BEVEL_OP_AS_MOD
+#define USE_BM_BEVEL_OP_AS_MOD
/* bevel tool defines */
/* element flags */
@@ -53,6 +53,7 @@
#define BME_BEVEL_RADIUS (1 << 2)
#define BME_BEVEL_ANGLE (1 << 3)
#define BME_BEVEL_WEIGHT (1 << 4)
+#define BME_BEVEL_VGROUP (1 << 5)
//~ #define BME_BEVEL_EWEIGHT (1<<4)
//~ #define BME_BEVEL_VWEIGHT (1<<5)
#define BME_BEVEL_PERCENT (1 << 6)
diff --git a/source/blender/blenlib/BLI_bpath.h b/source/blender/blenkernel/BKE_bpath.h
index 438bffb2fc5..16a8b1be85b 100644
--- a/source/blender/blenlib/BLI_bpath.h
+++ b/source/blender/blenkernel/BKE_bpath.h
@@ -25,14 +25,14 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file BLI_bpath.h
- * \ingroup bli
+/** \file BKE_bpath.h
+ * \ingroup bke
* \attention Based on ghash, difference is ghash is not a fixed size,
* so for BPath we don't need to malloc
*/
-#ifndef __BLI_BPATH_H__
-#define __BLI_BPATH_H__
+#ifndef __BKE_BPATH_H__
+#define __BKE_BPATH_H__
struct ID;
struct ListBase;
@@ -43,20 +43,20 @@ struct ReportList;
* path has changed, and in that case, should write the result to pathOut. */
typedef int (*BPathVisitor)(void *userdata, char *path_dst, const char *path_src);
/* Executes 'visit' for each path associated with 'id'. */
-void BLI_bpath_traverse_id(struct Main *bmain, struct ID *id, BPathVisitor visit_cb, const int flag, void *userdata);
-void BLI_bpath_traverse_id_list(struct Main *bmain, struct ListBase *lb, BPathVisitor visit_cb, const int flag, void *userdata);
-void BLI_bpath_traverse_main(struct Main *bmain, BPathVisitor visit_cb, const int flag, void *userdata);
-int BLI_bpath_relocate_visitor(void *oldbasepath, char *path_dst, const char *path_src);
+void BKE_bpath_traverse_id(struct Main *bmain, struct ID *id, BPathVisitor visit_cb, const int flag, void *userdata);
+void BKE_bpath_traverse_id_list(struct Main *bmain, struct ListBase *lb, BPathVisitor visit_cb, const int flag, void *userdata);
+void BKE_bpath_traverse_main(struct Main *bmain, BPathVisitor visit_cb, const int flag, void *userdata);
+int BKE_bpath_relocate_visitor(void *oldbasepath, char *path_dst, const char *path_src);
/* Functions for temp backup/restore of paths, path count must NOT change */
-void *BLI_bpath_list_backup(struct Main *bmain, const int flag);
-void BLI_bpath_list_restore(struct Main *bmain, const int flag, void *ls_handle);
-void BLI_bpath_list_free(void *ls_handle);
+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 BLI_BPATH_TRAVERSE_ABS (1 << 0) /* convert paths to absolute */
-#define BLI_BPATH_TRAVERSE_SKIP_LIBRARY (1 << 2) /* skip library paths */
-#define BLI_BPATH_TRAVERSE_SKIP_PACKED (1 << 3) /* skip packed data */
-#define BLI_BPATH_TRAVERSE_SKIP_MULTIFILE (1 << 4) /* skip paths where a single dir is used with an array of files, eg.
+#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 */
@@ -64,9 +64,9 @@ void BLI_bpath_list_free(void *ls_handle);
/* high level funcs */
/* creates a text file with missing files if there are any */
-void BLI_bpath_missing_files_check(struct Main *bmain, struct ReportList *reports);
-void BLI_bpath_missing_files_find(struct Main *bmain, const char *searchpath, struct ReportList *reports);
-void BLI_bpath_relative_convert(struct Main *bmain, const char *basedir, struct ReportList *reports);
-void BLI_bpath_absolute_convert(struct Main *bmain, const char *basedir, struct ReportList *reports);
+void BKE_bpath_missing_files_check(struct Main *bmain, struct ReportList *reports);
+void BKE_bpath_missing_files_find(struct Main *bmain, const char *searchpath, struct ReportList *reports);
+void BKE_bpath_relative_convert(struct Main *bmain, const char *basedir, struct ReportList *reports);
+void BKE_bpath_absolute_convert(struct Main *bmain, const char *basedir, struct ReportList *reports);
-#endif /* __BLI_BPATH_H__ */
+#endif /* __BKE_BPATH_H__ */
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index cbffb6c0cea..e0afb1929a5 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -36,12 +36,19 @@
struct ID;
struct Brush;
struct ImBuf;
+struct ImagePool;
+struct Main;
struct Scene;
struct wmOperator;
// enum CurveMappingPreset;
+
+/* globals for brush execution */
+void BKE_brush_system_init(void);
+void BKE_brush_system_exit(void);
+
/* datablock functions */
-struct Brush *BKE_brush_add(const char *name);
+struct Brush *BKE_brush_add(struct Main *bmain, const char *name);
struct Brush *BKE_brush_copy(struct Brush *brush);
void BKE_brush_make_local(struct Brush *brush);
void BKE_brush_free(struct Brush *brush);
@@ -67,23 +74,13 @@ 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 */
/* sampling */
-void BKE_brush_sample_tex(const struct Scene *scene, struct Brush *brush, const float xy[2], float rgba[4], const int thread);
+float BKE_brush_sample_tex_3D(const Scene *scene, struct Brush *br, const float point[3],
+ float rgba[4], const int thread, struct ImagePool *pool);
+float BKE_brush_sample_tex_2D(const struct Scene *scene, struct Brush *brush, const float xy[2],
+ float rgba[4]);
void BKE_brush_imbuf_new(const struct Scene *scene, struct Brush *brush, short flt, short texfalloff, int size,
struct ImBuf **imbuf, int use_color_correction);
-/* painting */
-struct BrushPainter;
-typedef struct BrushPainter BrushPainter;
-typedef int (*BrushFunc)(void *user, struct ImBuf *ibuf, const float lastpos[2], const float pos[2]);
-
-BrushPainter *BKE_brush_painter_new(struct Scene *scene, struct Brush *brush);
-void BKE_brush_painter_require_imbuf(BrushPainter *painter, short flt,
- short texonly, int size);
-int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float pos[2],
- double time, float pressure, void *user, int use_color_correction);
-void BKE_brush_painter_break_stroke(BrushPainter *painter);
-void BKE_brush_painter_free(BrushPainter *painter);
-
/* texture */
unsigned int *BKE_brush_gen_texture_cache(struct Brush *br, int half_side);
@@ -99,6 +96,7 @@ float BKE_brush_unprojected_radius_get(const struct Scene *scene, struct 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);
+void BKE_brush_alpha_set(Scene *scene, struct Brush *brush, float alpha);
float BKE_brush_weight_get(const Scene *scene, struct Brush *brush);
void BKE_brush_weight_set(const Scene *scene, struct Brush *brush, float value);
diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h
index 2a27934c038..a07558cc8af 100644
--- a/source/blender/blenkernel/BKE_camera.h
+++ b/source/blender/blenkernel/BKE_camera.h
@@ -39,6 +39,7 @@ extern "C" {
#include "DNA_vec_types.h"
struct Camera;
+struct Main;
struct Object;
struct RegionView3D;
struct RenderData;
@@ -48,7 +49,7 @@ struct View3D;
/* Camera Datablock */
-void *BKE_camera_add(const char *name);
+void *BKE_camera_add(struct Main *bmain, const char *name);
struct Camera *BKE_camera_copy(struct Camera *cam);
void BKE_camera_make_local(struct Camera *cam);
void BKE_camera_free(struct Camera *ca);
@@ -111,7 +112,7 @@ 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 short do_clip, const float scale[3],
+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]);
diff --git a/source/blender/blenkernel/BKE_ccg.h b/source/blender/blenkernel/BKE_ccg.h
index 6d39d42bde5..fb6211504ae 100644
--- a/source/blender/blenkernel/BKE_ccg.h
+++ b/source/blender/blenkernel/BKE_ccg.h
@@ -126,7 +126,7 @@ BLI_INLINE CCGElem *CCG_elem_offset(const CCGKey *key, CCGElem *elem, int offset
BLI_INLINE CCGElem *CCG_grid_elem(const CCGKey *key, CCGElem *elem, int x, int y)
{
- BLI_assert(x < key->grid_size && y < key->grid_size);
+// BLI_assert(x < key->grid_size && y < key->grid_size);
return CCG_elem_offset(key, elem, (y * key->grid_size + x));
}
diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h
index 2b2497f3f50..af5e925987d 100644
--- a/source/blender/blenkernel/BKE_cdderivedmesh.h
+++ b/source/blender/blenkernel/BKE_cdderivedmesh.h
@@ -63,14 +63,12 @@ DerivedMesh *CDDM_from_editbmesh(struct BMEditMesh *em, int use_mdisps, int use_
/* merge verts */
DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap);
-DerivedMesh *CDDM_from_curve_orco(struct Scene *scene, struct Object *ob);
-
/* creates a CDDerivedMesh from the given curve object */
struct DerivedMesh *CDDM_from_curve(struct Object *ob);
/* creates a CDDerivedMesh from the given curve object and specified dispbase */
/* useful for OrcoDM creation for curves with constructive modifiers */
-DerivedMesh *CDDM_from_curve_displist(struct Object *ob, struct ListBase *dispbase, int **orco_index_ptr);
+DerivedMesh *CDDM_from_curve_displist(struct Object *ob, struct ListBase *dispbase);
/* Copies the given DerivedMesh with verts, faces & edges stored as
* custom element data.
diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h
index 96e05aa87b9..e0b7e68bafc 100644
--- a/source/blender/blenkernel/BKE_colortools.h
+++ b/source/blender/blenkernel/BKE_colortools.h
@@ -42,14 +42,6 @@ struct Histogram;
struct ImBuf;
struct rctf;
-#if defined _MSC_VER
-# define DO_INLINE __inline
-#elif defined(__sun) || defined(__sun__)
-# define DO_INLINE
-#else
-# define DO_INLINE static inline
-#endif
-
void curvemapping_set_defaults(struct CurveMapping *cumap, int tot, float minx, float miny, float maxx, float maxy);
struct CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy);
void curvemapping_free_data(struct CurveMapping *cumap);
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index 79e75127763..c79dc62bb61 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 *constraint_get_typeinfo(struct bConstraint *con);
-bConstraintTypeInfo *get_constraint_typeinfo(int type);
+bConstraintTypeInfo *BKE_constraint_get_typeinfo(struct bConstraint *con);
+bConstraintTypeInfo *BKE_get_constraint_typeinfo(int type);
/* ---------------------------------------------------------------------------- */
/* Useful macros for testing various common flag combinations */
@@ -120,38 +120,38 @@ bConstraintTypeInfo *get_constraint_typeinfo(int type);
/* ---------------------------------------------------------------------------- */
/* Constraint function prototypes */
-void unique_constraint_name(struct bConstraint *con, struct ListBase *list);
+void BKE_unique_constraint_name(struct bConstraint *con, struct ListBase *list);
-void free_constraints(struct ListBase *list);
-void copy_constraints(struct ListBase *dst, const struct ListBase *src, int do_extern);
-void relink_constraints(struct ListBase *list);
-void id_loop_constraints(struct ListBase *list, ConstraintIDFunc func, void *userdata);
-void free_constraint_data(struct bConstraint *con);
+void BKE_free_constraints(struct ListBase *list);
+void BKE_copy_constraints(struct ListBase *dst, const struct ListBase *src, int do_extern);
+void BKE_relink_constraints(struct ListBase *list);
+void BKE_id_loop_constraints(struct ListBase *list, ConstraintIDFunc func, void *userdata);
+void BKE_free_constraint_data(struct bConstraint *con);
/* Constraint API function prototypes */
-struct bConstraint *constraints_get_active(struct ListBase *list);
-void constraints_set_active(ListBase *list, struct bConstraint *con);
-struct bConstraint *constraints_findByName(struct ListBase *list, const char *name);
-
-struct bConstraint *add_ob_constraint(struct Object *ob, const char *name, short type);
-struct bConstraint *add_pose_constraint(struct Object *ob, struct bPoseChannel *pchan, const char *name, short type);
+struct bConstraint *BKE_constraints_get_active(struct ListBase *list);
+void BKE_constraints_set_active(ListBase *list, struct bConstraint *con);
+struct bConstraint *BKE_constraints_findByName(struct ListBase *list, const char *name);
+
+struct bConstraint *BKE_add_ob_constraint(struct Object *ob, const char *name, short type);
+struct bConstraint *BKE_add_pose_constraint(struct Object *ob, struct bPoseChannel *pchan, const char *name, short type);
-int remove_constraint(ListBase *list, struct bConstraint *con);
-void remove_constraints_type(ListBase *list, short type, short last_only);
+int BKE_remove_constraint(ListBase *list, struct bConstraint *con);
+void BKE_remove_constraints_type(ListBase *list, short type, short last_only);
/* Constraints + Proxies function prototypes */
-void extract_proxylocal_constraints(struct ListBase *dst, struct ListBase *src);
-short proxylocked_constraints_owner(struct Object *ob, struct bPoseChannel *pchan);
+void BKE_extract_proxylocal_constraints(struct ListBase *dst, struct ListBase *src);
+short BKE_proxylocked_constraints_owner(struct Object *ob, struct bPoseChannel *pchan);
/* Constraint Evaluation function prototypes */
-struct bConstraintOb *constraints_make_evalob(struct Scene *scene, struct Object *ob, void *subdata, short datatype);
-void constraints_clear_evalob(struct bConstraintOb *cob);
+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 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);
-void get_constraint_target_matrix(struct Scene *scene, struct bConstraint *con, int n, short ownertype, void *ownerdata, float mat[4][4], float ctime);
-void get_constraint_targets_for_solving(struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime);
-void solve_constraints(struct ListBase *conlist, struct bConstraintOb *cob, float ctime);
+void BKE_get_constraint_target_matrix(struct Scene *scene, struct bConstraint *con, int n, short ownertype, void *ownerdata, float mat[4][4], float ctime);
+void BKE_get_constraint_targets_for_solving(struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime);
+void BKE_solve_constraints(struct ListBase *conlist, struct bConstraintOb *cob, float ctime);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 22b8f474cca..285077f258c 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -185,6 +185,7 @@ enum {
PointerRNA CTX_data_pointer_get(const bContext *C, const char *member);
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type);
ListBase CTX_data_collection_get(const bContext *C, const char *member);
+ListBase CTX_data_dir_get_ex(const bContext *C, const short use_store, const short use_rna, const short use_all);
ListBase CTX_data_dir_get(const bContext *C);
int CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb, short *r_type);
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 536bbecb79b..6e298a6d4f6 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -38,7 +38,7 @@ struct BezTriple;
struct Curve;
struct EditNurb;
struct ListBase;
-struct ListBase;
+struct Main;
struct Nurb;
struct Object;
struct Scene;
@@ -57,7 +57,7 @@ struct Scene;
void BKE_curve_unlink(struct Curve *cu);
void BKE_curve_free(struct Curve *cu);
void BKE_curve_editfont_free(struct Curve *cu);
-struct Curve *BKE_curve_add(const char *name, int type);
+struct Curve *BKE_curve_add(struct Main *bmain, const char *name, int type);
struct Curve *BKE_curve_copy(struct Curve *cu);
void BKE_curve_make_local(struct Curve *cu);
short BKE_curve_type_get(struct Curve *cu);
@@ -65,9 +65,9 @@ void BKE_curve_type_test(struct Object *ob);
void BKE_curve_curve_dimension_update(struct Curve *cu);
void BKE_curve_texspace_calc(struct Curve *cu);
-int BKE_curve_minmax(struct Curve *cu, float min[3], float max[3]);
-int BKE_curve_center_median(struct Curve *cu, float cent[3]);
-int BKE_curve_center_bounds(struct Curve *cu, float cent[3]);
+bool BKE_curve_minmax(struct Curve *cu, float min[3], float max[3]);
+bool BKE_curve_center_median(struct Curve *cu, float cent[3]);
+bool BKE_curve_center_bounds(struct Curve *cu, float cent[3]);
void BKE_curve_translate(struct Curve *cu, float offset[3], int do_keys);
void BKE_curve_delete_material_index(struct Curve *cu, int index);
@@ -117,13 +117,14 @@ void BKE_nurb_knot_calc_u(struct Nurb *nu);
void BKE_nurb_knot_calc_v(struct Nurb *nu);
/* nurb checks if they can be drawn, also clamp order func */
-int BKE_nurb_check_valid_u(struct Nurb *nu);
-int BKE_nurb_check_valid_v(struct Nurb *nu);
+bool BKE_nurb_check_valid_u(struct Nurb *nu);
+bool BKE_nurb_check_valid_v(struct Nurb *nu);
-int BKE_nurb_order_clamp_u(struct Nurb *nu);
-int BKE_nurb_order_clamp_v(struct Nurb *nu);
+bool BKE_nurb_order_clamp_u(struct Nurb *nu);
+bool BKE_nurb_order_clamp_v(struct Nurb *nu);
void BKE_nurb_direction_switch(struct Nurb *nu);
+bool BKE_nurb_type_convert(struct Nurb *nu, const short type, const bool use_handles);
void BKE_nurb_points_add(struct Nurb *nu, int number);
void BKE_nurb_bezierPoints_add(struct Nurb *nu, int number);
@@ -134,4 +135,4 @@ void BKE_nurb_handles_calc(struct Nurb *nu);
void BKE_nurb_handles_autocalc(struct Nurb *nu, int flag);
void BKE_nurb_handles_test(struct Nurb *nu);
-#endif
+#endif /* __BKE_CURVE_H__ */
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 4736e7b7312..a51de2d4ae1 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -39,6 +39,7 @@ extern "C" {
#endif
#include "../blenloader/BLO_sys_types.h" /* XXX, should have a more generic include for this */
+#include "BLI_utildefines.h"
struct BMesh;
struct ID;
@@ -215,6 +216,8 @@ void CustomData_free_elem(struct CustomData *data, int index, int count);
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);
@@ -246,6 +249,8 @@ 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);
+int CustomData_get_offset(const struct CustomData *data, int type);
+int CustomData_get_n_offset(const struct CustomData *data, int type, int n);
int CustomData_get_layer_index(const struct CustomData *data, int type);
int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n);
@@ -254,6 +259,7 @@ int CustomData_get_active_layer_index(const struct CustomData *data, int type);
int CustomData_get_render_layer_index(const struct CustomData *data, int type);
int CustomData_get_clone_layer_index(const struct CustomData *data, int type);
int CustomData_get_stencil_layer_index(const struct CustomData *data, int type);
+int CustomData_get_named_layer(const struct CustomData *data, int type, const char *name);
int CustomData_get_active_layer(const struct CustomData *data, int type);
int CustomData_get_render_layer(const struct CustomData *data, int type);
int CustomData_get_clone_layer(const struct CustomData *data, int type);
@@ -304,7 +310,7 @@ void CustomData_bmesh_free_block(struct CustomData *data, void **block);
/* copy custom data to/from layers as in mesh/derivedmesh, to editmesh
* blocks of data. the CustomData's must not be compatible */
void CustomData_to_bmesh_block(const struct CustomData *source,
- struct CustomData *dest, int src_index, void **dest_block);
+ struct CustomData *dest, int src_index, void **dest_block, bool use_default_init);
void CustomData_from_bmesh_block(const struct CustomData *source,
struct CustomData *dest, void *src_block, int dest_index);
diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h
index 8306da71432..b18bb5a87b6 100644
--- a/source/blender/blenkernel/BKE_deform.h
+++ b/source/blender/blenkernel/BKE_deform.h
@@ -43,9 +43,9 @@ struct MDeformVert;
void defgroup_copy_list(struct ListBase *lb1, struct ListBase *lb2);
struct bDeformGroup *defgroup_duplicate(struct bDeformGroup *ingroup);
struct bDeformGroup *defgroup_find_name(struct Object *ob, const char *name);
-int *defgroup_flip_map(struct Object *ob, int *flip_map_len, int use_default);
-int *defgroup_flip_map_single(struct Object *ob, int *flip_map_len, int use_default, int defgroup);
-int defgroup_flip_index(struct Object *ob, int index, int use_default);
+int *defgroup_flip_map(struct Object *ob, int *flip_map_len, const bool use_default);
+int *defgroup_flip_map_single(struct Object *ob, int *flip_map_len, const bool use_default, int defgroup);
+int defgroup_flip_index(struct Object *ob, int index, const bool use_default);
int defgroup_name_index(struct Object *ob, const char *name);
void defgroup_unique_name(struct bDeformGroup *dg, struct Object *ob);
@@ -55,15 +55,20 @@ void defvert_add_index_notest(struct MDeformVert *dv, int de
void defvert_remove_group(struct MDeformVert *dvert, struct MDeformWeight *dw);
void defvert_clear(struct MDeformVert *dvert);
int defvert_find_shared(const struct MDeformVert *dvert_a, const struct MDeformVert *dvert_b);
+bool defvert_is_weight_zero(const struct MDeformVert *dvert, const int defgroup_tot);
+
+void BKE_defvert_array_free_elems(struct MDeformVert *dvert, int totvert);
+void BKE_defvert_array_free(struct MDeformVert *dvert, int totvert);
+void BKE_defvert_array_copy(struct MDeformVert *dst, const struct MDeformVert *src, int totvert);
float defvert_find_weight(const struct MDeformVert *dvert, const int defgroup);
float defvert_array_find_weight_safe(const struct MDeformVert *dvert, const int index, const int defgroup);
void defvert_copy(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src);
void defvert_copy_index(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src, const int defgroup);
-void defvert_sync(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src, int use_verify);
+void defvert_sync(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src, const bool use_verify);
void defvert_sync_mapped(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src,
- const int *flip_map, const int flip_map_len, const int use_verify);
+ const int *flip_map, const int flip_map_len, const bool use_verify);
void defvert_remap(struct MDeformVert *dvert, int *map, const int map_len);
void defvert_flip(struct MDeformVert *dvert, const int *flip_map, const int flip_map_len);
void defvert_flip_merged(struct MDeformVert *dvert, const int *flip_map, const int flip_map_len);
@@ -79,5 +84,4 @@ void BKE_deform_split_prefix(const char string[MAX_VGROUP_NAME], char base[MAX_V
void flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_NAME], int strip_number);
-#endif
-
+#endif /* __BKE_DEFORM_H__ */
diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h
index cf7e4b24288..6baf20aeb2c 100644
--- a/source/blender/blenkernel/BKE_depsgraph.h
+++ b/source/blender/blenkernel/BKE_depsgraph.h
@@ -30,107 +30,94 @@
* \ingroup bke
*/
+/* Dependency Graph
+ *
+ * The dependency graph tracks relations between datablocks, and is used to
+ * determine which datablocks need to be update based on dependencies and
+ * visibility.
+ *
+ * It does not itself execute changes in objects, but rather sorts the objects
+ * in the appropriate order and sets flags indicating they should be updated.
+ */
+
#ifdef __cplusplus
extern "C" {
#endif
-// #define DEPS_DEBUG
-
struct ID;
struct Main;
+struct Object;
struct Scene;
-struct DagNodeQueue;
-struct DagForest;
-struct DagNode;
-struct GHash;
-
-/* **** DAG relation types *** */
-
-/* scene link to object */
-#define DAG_RL_SCENE (1 << 0)
-/* object link to data */
-#define DAG_RL_DATA (1 << 1)
-
-/* object changes object (parent, track, constraints) */
-#define DAG_RL_OB_OB (1 << 2)
-/* object changes obdata (hooks, constraints) */
-#define DAG_RL_OB_DATA (1 << 3)
-/* data changes object (vertex parent) */
-#define DAG_RL_DATA_OB (1 << 4)
-/* data changes data (deformers) */
-#define DAG_RL_DATA_DATA (1 << 5)
-
-#define DAG_NO_RELATION (1 << 6)
-
-#define DAG_RL_ALL_BUT_DATA (DAG_RL_SCENE | DAG_RL_OB_OB | DAG_RL_OB_DATA | DAG_RL_DATA_OB | DAG_RL_DATA_DATA)
-#define DAG_RL_ALL (DAG_RL_ALL_BUT_DATA | DAG_RL_DATA)
-
-
-typedef void (*graph_action_func)(void *ob, void **data);
-
-// queues are returned by all BFS & DFS queries
-// opaque type
-void *pop_ob_queue(struct DagNodeQueue *queue);
-int queue_count(struct DagNodeQueue *queue);
-void queue_delete(struct DagNodeQueue *queue);
-
-// queries
-struct DagForest *build_dag(struct Main *bmain, struct Scene *sce, short mask);
-void free_forest(struct DagForest *Dag);
-
-// note :
-// the meanings of the 2 returning values is a bit different :
-// BFS return 1 for cross-edges and back-edges. the latter are considered harmfull, not the former
-// DFS return 1 only for back-edges
-int pre_and_post_BFS(struct DagForest *dag, short mask, graph_action_func pre_func, graph_action_func post_func, void **data);
-int pre_and_post_DFS(struct DagForest *dag, short mask, graph_action_func pre_func, graph_action_func post_func, void **data);
-
-int pre_and_post_source_BFS(struct DagForest *dag, short mask, struct DagNode *source, graph_action_func pre_func, graph_action_func post_func, void **data);
-int pre_and_post_source_DFS(struct DagForest *dag, short mask, struct DagNode *source, graph_action_func pre_func, graph_action_func post_func, void **data);
-
-struct DagNodeQueue *get_obparents(struct DagForest *dag, void *ob);
-struct DagNodeQueue *get_first_ancestors(struct DagForest *dag, void *ob);
-struct DagNodeQueue *get_all_childs(struct DagForest *dag, void *ob);
-short are_obs_related(struct DagForest *dag, void *ob1, void *ob2);
-int is_acyclic(struct DagForest *dag);
-//int get_cycles(struct DagForest *dag, struct DagNodeQueue **queues, int *count); //
-
-/* ********** API *************** */
-/* Note that the DAG never executes changes in Objects, only sets flags in Objects */
-
-/* (re)-create dependency graph for scene */
-void DAG_scene_sort(struct Main *bmain, struct Scene *sce);
-
-/* flag all objects that need recalc because they're animated */
-void DAG_scene_update_flags(struct Main *bmain, struct Scene *sce, unsigned int lay, const short do_time);
-/* flushes all recalc flags in objects down the dependency tree */
-void DAG_scene_flush_update(struct Main *bmain, struct Scene *sce, unsigned int lay, const short do_time);
-/* tag objects for update on file load */
-void DAG_on_visible_update(struct Main *bmain, const short do_time);
-
-/* when setting manual RECALC flags, call this afterwards */
-void DAG_ids_flush_update(struct Main *bmain, int time);
-
-/* tag datablock to get updated for the next redraw */
-void DAG_id_tag_update(struct ID *id, short flag);
-/* flush all tagged updates */
-void DAG_ids_flush_tagged(struct Main *bmain);
-/* check and clear ID recalc flags */
-void DAG_ids_check_recalc(struct Main *bmain, struct Scene *scene, int time);
-void DAG_ids_clear_recalc(struct Main *bmain);
-/* test if any of this id type is tagged for update */
-void DAG_id_type_tag(struct Main *bmain, short idtype);
-int DAG_id_type_tagged(struct Main *bmain, short idtype);
-
-/* (re)-create dependency graph for armature pose */
-void DAG_pose_sort(struct Object *ob);
-
-/* callback for editors module to do updates */
-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));
-
-/* debugging */
-void DAG_print_dependencies(struct Main *bmain, struct Scene *scene, struct Object *ob);
+
+/* Build and Update
+ *
+ * DAG_scene_relations_update will rebuild the dependency graph for a given
+ * scene if needed, and sort objects in the scene.
+ *
+ * DAG_relations_tag_update will clear all dependency graphs and mark them to
+ * be rebuilt later. The graph is not rebuilt immediately to avoid slowdowns
+ * when this function is call multiple times from different operators.
+ *
+ * DAG_scene_relations_rebuild forces an immediaterebuild of the dependency
+ * graph, this is only needed in rare cases
+ */
+
+void DAG_scene_relations_update(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);
+
+/* Update Tagging
+ *
+ * DAG_scene_update_flags will mark all objects that depend on time (animation,
+ * physics, ..) to be recalculated, used when changing the current frame.
+ *
+ * DAG_on_visible_update will mark all objects that are visible for the first
+ * time to be updated, for example on file load or changing layer visibility.
+ *
+ * DAG_id_tag_update will mark a given datablock to be updated. The flag indicates
+ * a specific subset to be update (only object transform and data for now).
+ *
+ * DAG_id_type_tag marks a particular datablock type as having changing. This does
+ * not cause any updates but is used by external render engines to detect if for
+ * example a datablock was removed. */
+
+void DAG_scene_update_flags(struct Main *bmain, struct Scene *sce, unsigned int lay, const short do_time);
+void DAG_on_visible_update(struct Main *bmain, const short do_time);
+
+void DAG_id_tag_update(struct ID *id, short flag);
+void DAG_id_tag_update_ex(struct Main *bmain, struct ID *id, short flag);
+void DAG_id_type_tag(struct Main *bmain, short idtype);
+int DAG_id_type_tagged(struct Main *bmain, short idtype);
+
+/* Flushing Tags
+ *
+ * DAG_scene_flush_update flushes object recalculation flags immediately to other
+ * dependencies. Do not use outside of depsgraph.c, this will be removed.
+ *
+ * DAG_ids_flush_tagged will flush datablock update flags flags to dependencies,
+ * use this right before updating to mark all the needed datablocks for update.
+ *
+ * DAG_ids_check_recalc and DAG_ids_clear_recalc are used for external render
+ * engines to detect changes. */
+
+void DAG_scene_flush_update(struct Main *bmain, struct Scene *sce, unsigned int lay, const short do_time);
+void DAG_ids_flush_tagged(struct Main *bmain);
+void DAG_ids_check_recalc(struct Main *bmain, struct Scene *scene, int time);
+void DAG_ids_clear_recalc(struct Main *bmain);
+
+/* Armature: sorts the bones according to dependencies between them */
+
+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));
+
+/* Debugging: print dependency graph for scene or armature object to console */
+
+void DAG_print_dependencies(struct Main *bmain, struct Scene *scene, struct Object *ob);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
index 758a2a8a2e8..10c31189d02 100644
--- a/source/blender/blenkernel/BKE_displist.h
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -83,9 +83,9 @@ void BKE_displist_elem_free(DispList *dl);
DispList *BKE_displist_find_or_create(struct ListBase *lb, int type);
DispList *BKE_displist_find(struct ListBase *lb, int type);
void BKE_displist_normals_add(struct ListBase *lb);
-void BKE_displist_count(struct ListBase *lb, int *totvert, int *totface);
+void BKE_displist_count(struct ListBase *lb, int *totvert, int *totface, int *tottri);
void BKE_displist_free(struct ListBase *lb);
-int BKE_displist_has_faces(struct ListBase *lb);
+bool BKE_displist_has_faces(struct ListBase *lb);
void BKE_displist_make_surf(struct Scene *scene, struct Object *ob, struct ListBase *dispbase, struct DerivedMesh **derivedFinal, int forRender, int forOrco);
void BKE_displist_make_curveTypes(struct Scene *scene, struct Object *ob, int forOrco);
@@ -94,7 +94,7 @@ void BKE_displist_make_curveTypes_forOrco(struct Scene *scene, struct Object *ob
void BKE_displist_make_mball(struct Scene *scene, struct Object *ob);
void BKE_displist_make_mball_forRender(struct Scene *scene, struct Object *ob, struct ListBase *dispbase);
-int BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4);
+bool BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4);
void BKE_displist_fill(struct ListBase *dispbase, struct ListBase *to, int flipnormal);
float BKE_displist_calc_taper(struct Scene *scene, struct Object *taperobj, int cur, int tot);
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index bf2f1262eee..d7ef04195d5 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -41,6 +41,7 @@ struct FModifier;
struct ChannelDriver;
struct DriverVar;
struct DriverTarget;
+struct FCM_EnvelopeData;
struct bAction;
struct BezTriple;
@@ -181,6 +182,8 @@ void evaluate_value_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float *c
void fcurve_bake_modifiers(struct FCurve *fcu, int start, int end);
+int BKE_fcm_envelope_find_index(struct FCM_EnvelopeData *array, float frame, int arraylen, bool *r_exists);
+
/* ************** F-Curves API ******************** */
/* -------- Data Managemnt -------- */
@@ -197,7 +200,7 @@ struct FCurve *list_find_fcurve(ListBase *list, const char rna_path[], const int
struct FCurve *iter_step_fcurve(struct FCurve *fcu_iter, const char rna_path[]);
/* high level function to get an fcurve from C without having the rna */
-struct FCurve *id_data_find_fcurve(ID *id, void *data, struct StructRNA *type, const char *prop_name, int index, char *driven);
+struct FCurve *id_data_find_fcurve(ID *id, void *data, struct StructRNA *type, const char *prop_name, int index, bool *r_driven);
/* Get list of LinkData's containing pointers to the F-Curves which control the types of data indicated
* e.g. numMatches = list_find_data_fcurves(matches, &act->curves, "pose.bones[", "MyFancyBone");
@@ -205,12 +208,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, int *driven);
+struct FCurve *rna_get_fcurve(struct PointerRNA *ptr, struct PropertyRNA *prop, int rnaindex, struct bAction **action, bool *r_driven);
/* 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)
*/
-int binarysearch_bezt_index(struct BezTriple array[], float frame, int arraylen, short *replace);
+int binarysearch_bezt_index(struct BezTriple array[], float frame, int arraylen, bool *r_replace);
/* get the time extents for F-Curve */
void calc_fcurve_range(struct FCurve *fcu, float *min, float *max,
diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h
index cd52dd75f26..028ff0f93d6 100644
--- a/source/blender/blenkernel/BKE_font.h
+++ b/source/blender/blenkernel/BKE_font.h
@@ -71,7 +71,7 @@ typedef struct EditFont {
} EditFont;
-int BKE_vfont_is_builtin(struct VFont *vfont);
+bool BKE_vfont_is_builtin(struct VFont *vfont);
void BKE_vfont_builtin_register(void *mem, int size);
void BKE_vfont_free_data(struct VFont *vfont);
diff --git a/source/blender/blenkernel/BKE_freestyle.h b/source/blender/blenkernel/BKE_freestyle.h
new file mode 100644
index 00000000000..84a4bc255af
--- /dev/null
+++ b/source/blender/blenkernel/BKE_freestyle.h
@@ -0,0 +1,64 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_FREESTYLE_H__
+#define __BKE_FREESTYLE_H__
+
+/** \file BKE_freestyle.h
+ * \ingroup bke
+ */
+
+#include "DNA_scene_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* FreestyleConfig */
+void BKE_freestyle_config_init(FreestyleConfig *config);
+void BKE_freestyle_config_free(FreestyleConfig *config);
+void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *config);
+
+/* FreestyleConfig.modules */
+void BKE_freestyle_module_add(FreestyleConfig *config);
+void BKE_freestyle_module_delete(FreestyleConfig *config, FreestyleModuleConfig *module_conf);
+void BKE_freestyle_module_move_up(FreestyleConfig *config, FreestyleModuleConfig *module_conf);
+void BKE_freestyle_module_move_down(FreestyleConfig *config, FreestyleModuleConfig *module_conf);
+
+/* FreestyleConfig.linesets */
+FreestyleLineSet *BKE_freestyle_lineset_add(FreestyleConfig *config);
+FreestyleLineSet *BKE_freestyle_lineset_get_active(FreestyleConfig *config);
+short BKE_freestyle_lineset_get_active_index(FreestyleConfig *config);
+void BKE_freestyle_lineset_set_active_index(FreestyleConfig *config, short index);
+void BKE_freestyle_lineset_unique_name(FreestyleConfig *config, FreestyleLineSet *lineset);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index f6276a69d57..5d8b6983aad 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -114,7 +114,7 @@ typedef struct Global {
#define G_BACKBUFSEL (1 << 4)
#define G_PICKSEL (1 << 5)
-/* #define G_FACESELECT (1 << 8) use (mesh->editflag & ME_EDIT_PAINT_MASK) */
+/* #define G_FACESELECT (1 << 8) use (mesh->editflag & ME_EDIT_PAINT_FACE_SEL) */
#define G_SCRIPT_AUTOEXEC (1 << 13)
#define G_SCRIPT_OVERRIDE_PREF (1 << 14) /* when this flag is set ignore the userprefs */
@@ -132,10 +132,12 @@ enum {
G_DEBUG_EVENTS = (1 << 3), /* input/window/screen events */
G_DEBUG_HANDLERS = (1 << 4), /* events handling */
G_DEBUG_WM = (1 << 5), /* operator, undo */
- G_DEBUG_JOBS = (1 << 6) /* jobs time profiling */
+ G_DEBUG_JOBS = (1 << 6), /* jobs time profiling */
+ G_DEBUG_FREESTYLE = (1 << 7), /* freestyle messages */
};
-#define G_DEBUG_ALL (G_DEBUG | G_DEBUG_FFMPEG | G_DEBUG_PYTHON | G_DEBUG_EVENTS | G_DEBUG_WM | G_DEBUG_JOBS)
+#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.fileflags */
@@ -149,7 +151,7 @@ enum {
/* #define G_FILE_SHOW_PROFILE (1 << 6) */ /* deprecated */
#define G_FILE_LOCK (1 << 7)
#define G_FILE_SIGN (1 << 8)
-/* #define G_FILE_PUBLISH (1 << 9) */ /* deprecated */
+#define G_FILE_USERPREFS (1 << 9)
#define G_FILE_NO_UI (1 << 10)
/* #define G_FILE_GAME_TO_IPO (1 << 11) */ /* deprecated */
#define G_FILE_GAME_MAT (1 << 12) /* deprecated */
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
index 3e9803a908b..8c36a73a088 100644
--- a/source/blender/blenkernel/BKE_group.h
+++ b/source/blender/blenkernel/BKE_group.h
@@ -36,13 +36,14 @@
struct Base;
struct Group;
struct GroupObject;
+struct Main;
struct Object;
struct bAction;
struct Scene;
void BKE_group_free(struct Group *group);
void BKE_group_unlink(struct Group *group);
-struct Group *add_group(const char *name);
+struct Group *add_group(struct Main *bmain, const char *name);
struct Group *BKE_group_copy(struct Group *group);
int add_to_group(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
int rem_from_group(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
diff --git a/source/blender/blenkernel/BKE_idcode.h b/source/blender/blenkernel/BKE_idcode.h
index 2a01ef3afdb..10a34838662 100644
--- a/source/blender/blenkernel/BKE_idcode.h
+++ b/source/blender/blenkernel/BKE_idcode.h
@@ -32,47 +32,11 @@
* \ingroup bke
*/
-/**
- * Convert an idcode into a name.
- *
- * \param code The code to convert.
- * \return A static string representing the name of
- * the code.
- */
const char *BKE_idcode_to_name(int code);
-
-/**
- * Convert an idcode into a name (plural).
- *
- * \param code The code to convert.
- * \return A static string representing the name of
- * the code.
- */
const char *BKE_idcode_to_name_plural(int code);
-
-/**
- * Convert a name into an idcode (ie. ID_SCE)
- *
- * \param name The name to convert.
- * \return The code for the name, or 0 if invalid.
- */
-int BKE_idcode_from_name(const char *name);
-
-/**
- * Return non-zero when an ID type is linkable.
- *
- * \param code The code to check.
- * \return Boolean, 0 when non linkable.
- */
-int BKE_idcode_is_linkable(int code);
-
-/**
- * Return if the ID code is a valid ID code.
- *
- * \param code The code to check.
- * \return Boolean, 0 when invalid.
- */
-int BKE_idcode_is_valid(int code);
+int BKE_idcode_from_name(const char *name);
+bool BKE_idcode_is_linkable(int code);
+bool BKE_idcode_is_valid(int code);
/**
* 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 a9f6a61a655..d8ad3b2e892 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -58,8 +58,6 @@ typedef union IDPropertyTemplate {
/* ----------- Property Array Type ---------- */
-/* note: as a start to move away from the stupid IDP_New function, this type
- * has it's own allocation function.*/
IDProperty *IDP_NewIDPArray(const char *name)
#ifdef __GNUC__
__attribute__((warn_unused_result))
@@ -136,18 +134,11 @@ __attribute__((nonnull))
#endif
;
-/**
- * replaces all properties with the same name in a destination group from a source group.
- */
void IDP_ReplaceGroupInGroup(struct IDProperty *dest, struct IDProperty *src)
#ifdef __GNUC__
__attribute__((nonnull))
#endif
;
-
-/**
- * Checks if a property with the same name as prop exists, and if so replaces it.
- * Use this to preserve order!*/
void IDP_ReplaceInGroup(struct IDProperty *group, struct IDProperty *prop)
#ifdef __GNUC__
__attribute__((nonnull))
@@ -160,42 +151,17 @@ __attribute__((nonnull))
#endif
;
-/**
- * This function has a sanity check to make sure ID properties with the same name don't
- * get added to the group.
- *
- * 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.
- *
- * 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
- * to free an ID property, you first call IDP_FreeProperty then MEM_freeN the
- * struct. In the future this will just be IDP_FreeProperty and the code will
- * be reorganized to work properly.
- */
int IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop)
#ifdef __GNUC__
__attribute__((nonnull))
#endif
;
-
-/** this is the same as IDP_AddToGroup, only you pass an item
- * in the group list to be inserted after. */
int IDP_InsertToGroup(struct IDProperty *group, struct IDProperty *previous,
struct IDProperty *pnew)
#ifdef __GNUC__
__attribute__((nonnull (1, 3))) /* 'group', 'pnew' */
#endif
;
-
-/** \note this does not free the property!!
- *
- * To free the property, you have to do:
- * IDP_FreeProperty(prop); //free all subdata
- * MEM_freeN(prop); //free property struct itself
- */
void IDP_RemFromGroup(struct IDProperty *group, struct IDProperty *prop)
#ifdef __GNUC__
__attribute__((nonnull))
@@ -208,41 +174,23 @@ __attribute__((warn_unused_result))
__attribute__((nonnull))
#endif
;
-/** same as above but ensure type match */
IDProperty *IDP_GetPropertyTypeFromGroup(struct IDProperty *prop, const char *name, const char type)
#ifdef __GNUC__
__attribute__((warn_unused_result))
__attribute__((nonnull))
#endif
;
-
-/**
- * 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(struct IDProperty *prop)
#ifdef __GNUC__
__attribute__((warn_unused_result))
#endif
;
-
-/**
- * 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)
#ifdef __GNUC__
__attribute__((warn_unused_result))
__attribute__((nonnull))
#endif
;
-
-/**
- * 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)
#ifdef __GNUC__
__attribute__((nonnull))
@@ -250,9 +198,6 @@ __attribute__((nonnull))
;
/*-------- Main Functions --------*/
-/** Get the Group property that contains the id properties for ID id. Set create_if_needed
- * to create the Group property and attach it to id if it doesn't exist; otherwise
- * the function will return NULL if there's no Group property attached to the ID.*/
struct IDProperty *IDP_GetProperties(struct ID *id, int create_if_needed)
#ifdef __GNUC__
__attribute__((warn_unused_result))
@@ -278,31 +223,6 @@ __attribute__((warn_unused_result))
#endif
;
-/**
- * Allocate a new ID.
- *
- * This function takes three arguments: the ID property type, a union which defines
- * it's initial value, and a name.
- *
- * The union is simple to use; see the top of this header file for its definition.
- * An example of using this function:
- *
- * IDPropertyTemplate val;
- * IDProperty *group, *idgroup, *color;
- * group = IDP_New(IDP_GROUP, val, "group1"); //groups don't need a template.
- *
- * val.array.len = 4
- * val.array.type = IDP_FLOAT;
- * color = IDP_New(IDP_ARRAY, val, "color1");
- *
- * idgroup = IDP_GetProperties(some_id, 1);
- * IDP_AddToGroup(idgroup, color);
- * IDP_AddToGroup(idgroup, group);
- *
- * Note that you MUST either attach the id property to an id property group with
- * IDP_AddToGroup or MEM_freeN the property, doing anything else might result in
- * a memory leak.
- */
struct IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *name)
#ifdef __GNUC__
__attribute__((warn_unused_result))
@@ -310,12 +230,10 @@ __attribute__((nonnull))
#endif
;
-/** \note this will free all child properties of list arrays and groups!
- * Also, note that this does NOT unlink anything! Plus it doesn't free
- * the actual struct IDProperty struct either.*/
void IDP_FreeProperty(struct IDProperty *prop);
-/** Unlinks any struct IDProperty<->ID linkage that might be going on.*/
+void IDP_ClearProperty(IDProperty *prop);
+
void IDP_UnlinkProperty(struct IDProperty *prop);
#define IDP_Int(prop) ((prop)->data.val)
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 1f9630d9fce..26ac2cc8bb4 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -44,6 +44,7 @@ struct anim;
struct Scene;
struct Object;
struct ImageFormatData;
+struct ImagePool;
struct Main;
#define IMA_MAX_SPACE 64
@@ -60,12 +61,14 @@ int 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(struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf);
int BKE_imbuf_write_as(struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf, const short is_copy);
-void BKE_makepicstring(char *string, const char *base, const char *relbase, int frame, const char imtype, const short use_ext, const short use_frames);
-int BKE_add_image_extension(char *string, const char imtype);
+void BKE_makepicstring(char *string, const char *base, const char *relbase, int frame, const struct ImageFormatData *im_format, const short use_ext, const short use_frames);
+void BKE_makepicstring_from_type(char *string, const char *base, const char *relbase, int frame, const char imtype, const short use_ext, const short 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);
-int BKE_imtype_is_movie(const char imtype);
+bool BKE_imtype_is_movie(const char imtype);
int BKE_imtype_supports_zbuf(const char imtype);
int BKE_imtype_supports_compress(const char imtype);
int BKE_imtype_supports_quality(const char imtype);
@@ -144,13 +147,21 @@ int BKE_image_has_ibuf(struct Image *ima, struct ImageUser *iuser);
struct ImBuf *BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **lock_r);
void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock);
+struct ImagePool *BKE_image_pool_new(void);
+void BKE_image_pool_free(struct ImagePool *pool);
+struct ImBuf *BKE_image_pool_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, struct ImagePool *pool);
+void BKE_image_pool_release_ibuf(struct Image *ima, struct ImBuf *ibuf, struct ImagePool *pool);
+
+/* set an alpha mode based on file extension */
+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(const char *filepath);
+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(const char *filepath);
/* adds image, adds ibuf, generates color or pattern */
-struct Image *BKE_image_add_generated(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short uvtestgrid, float color[4]);
+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, float color[4]);
/* adds image from imbuf, owns imbuf */
struct Image *BKE_image_add_from_imbuf(struct ImBuf *ibuf);
@@ -197,7 +208,7 @@ void BKE_image_memorypack(struct Image *ima);
void BKE_image_print_memlist(void);
/* empty image block, of similar type and filename */
-struct Image *BKE_image_copy(struct Image *ima);
+struct Image *BKE_image_copy(struct Main *bmain, struct Image *ima);
/* merge source into dest, and free source */
void BKE_image_merge(struct Image *dest, struct Image *source);
@@ -217,6 +228,10 @@ void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width,
void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int height, int width);
void BKE_image_buf_fill_checker_color(unsigned char *rect, float *rect_float, int height, int width);
+/* Cycles hookup */
+unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame);
+float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
index d7d75b4c4c9..a159cbb13d4 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -59,7 +59,7 @@ 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 *do_ob_key(struct Scene *scene, struct Object *ob);
+float *BKE_key_evaluate_object(struct Scene *scene, struct Object *ob, int *r_totelem);
struct Key *BKE_key_from_object(struct Object *ob);
struct KeyBlock *BKE_keyblock_from_object(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h
index 244decf9d52..205c7c7d1e6 100644
--- a/source/blender/blenkernel/BKE_lamp.h
+++ b/source/blender/blenkernel/BKE_lamp.h
@@ -37,9 +37,10 @@ extern "C" {
#endif
struct Lamp;
+struct Main;
struct Scene;
-struct Lamp *BKE_lamp_add(const char *name) WARN_UNUSED;
+struct Lamp *BKE_lamp_add(struct Main *bmain, const char *name) WARN_UNUSED;
struct Lamp *BKE_lamp_copy(struct Lamp *la) WARN_UNUSED;
struct Lamp *localize_lamp(struct Lamp *la) WARN_UNUSED;
void BKE_lamp_make_local(struct Lamp *la);
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index a0bebd752b5..b195af18a8e 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -35,6 +35,7 @@
*/
struct Lattice;
+struct Main;
struct Object;
struct Scene;
struct DerivedMesh;
@@ -42,7 +43,7 @@ struct BPoint;
struct MDeformVert;
void BKE_lattice_resize(struct Lattice *lt, int u, int v, int w, struct Object *ltOb);
-struct Lattice *BKE_lattice_add(const char *name);
+struct Lattice *BKE_lattice_add(struct Main *bmain, const char *name);
struct Lattice *BKE_lattice_copy(struct Lattice *lt);
void BKE_lattice_free(struct Lattice *lt);
void BKE_lattice_make_local(struct Lattice *lt);
@@ -75,5 +76,10 @@ void BKE_lattice_modifiers_calc(struct Scene *scene, struct Object *ob);
struct MDeformVert *BKE_lattice_deform_verts_get(struct Object *lattice);
+void BKE_lattice_minmax(struct Lattice *lt, float min[3], float max[3]);
+void BKE_lattice_center_median(struct Lattice *lt, float cent[3]);
+void BKE_lattice_center_bounds(struct Lattice *lt, float cent[3]);
+void BKE_lattice_translate(struct Lattice *lt, float offset[3], int do_keys);
+
#endif
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index bc081b7f308..816fb2d1b35 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -51,27 +51,34 @@ __attribute__((warn_unused_result))
__attribute__((nonnull))
#endif
;
+void *BKE_libblock_copy_ex(struct Main *bmain, struct ID *id)
+#ifdef __GNUC__
+__attribute__((warn_unused_result))
+__attribute__((nonnull))
+#endif
+;
void *BKE_libblock_copy(struct ID *id)
#ifdef __GNUC__
__attribute__((warn_unused_result))
__attribute__((nonnull))
#endif
;
-void BKE_libblock_copy_data(struct ID *id, const struct ID *id_from, const short do_action);
+void BKE_libblock_copy_data(struct ID *id, const struct ID *id_from, const bool do_action);
void BKE_id_lib_local_paths(struct Main *bmain, struct Library *lib, struct ID *id);
void id_lib_extern(struct ID *id);
void BKE_library_filepath_set(struct Library *lib, const char *filepath);
+void id_us_ensure_real(struct ID *id);
void id_us_plus(struct ID *id);
void id_us_min(struct ID *id);
-int id_make_local(struct ID *id, int test);
-int id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop);
-int id_copy(struct ID *id, struct ID **newid, int test);
-int id_unlink(struct ID *id, int test);
+bool id_make_local(struct ID *id, bool test);
+bool id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop);
+bool id_copy(struct ID *id, struct ID **newid, bool test);
+bool id_unlink(struct ID *id, int test);
void id_sort_by_name(struct ListBase *lb, struct ID *id);
-int new_id(struct ListBase *lb, struct ID *id, const char *name);
+bool new_id(struct ListBase *lb, struct ID *id, const char *name);
void id_clear_lib_data(struct Main *bmain, struct ID *id);
struct ListBase *which_libbase(struct Main *mainlib, short type);
@@ -89,10 +96,9 @@ void tag_main_lb(struct ListBase *lb, const short tag);
void tag_main(struct Main *mainvar, const short tag);
void rename_id(struct ID *id, const char *name);
-void name_uiprefix_id(char *name, struct ID *id);
+void name_uiprefix_id(char *name, const struct ID *id);
void test_idbutton(char *name);
-void text_idbutton(struct ID *id, char *text);
-void BKE_library_make_local(struct Main *bmain, struct Library *lib, int untagged_only);
+void BKE_library_make_local(struct Main *bmain, struct Library *lib, bool untagged_only);
struct ID *BKE_libblock_find_name(const short type, const char *name)
#ifdef __GNUC__
__attribute__((warn_unused_result))
@@ -121,4 +127,4 @@ void set_free_windowmanager_cb(void (*func)(struct bContext *, struct wmWindowMa
}
#endif
-#endif
+#endif /* __BKE_LIBRARY_H__ */
diff --git a/source/blender/blenkernel/BKE_linestyle.h b/source/blender/blenkernel/BKE_linestyle.h
new file mode 100644
index 00000000000..13d111cb93b
--- /dev/null
+++ b/source/blender/blenkernel/BKE_linestyle.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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_LINESTYLE_H__
+#define __BKE_LINESTYLE_H__
+
+/** \file BKE_linestyle.h
+ * \ingroup bke
+ * \brief Blender kernel freestyle line style functionality.
+ */
+
+#include "DNA_linestyle_types.h"
+
+#define LS_MODIFIER_TYPE_COLOR 1
+#define LS_MODIFIER_TYPE_ALPHA 2
+#define LS_MODIFIER_TYPE_THICKNESS 3
+#define LS_MODIFIER_TYPE_GEOMETRY 4
+
+struct Main;
+struct Object;
+struct ColorBand;
+
+FreestyleLineStyle *BKE_new_linestyle(const char *name, struct Main *main);
+void BKE_free_linestyle(FreestyleLineStyle *linestyle);
+FreestyleLineStyle *BKE_copy_linestyle(FreestyleLineStyle *linestyle);
+
+LineStyleModifier *BKE_add_linestyle_color_modifier(FreestyleLineStyle *linestyle, int type);
+LineStyleModifier *BKE_add_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, int type);
+LineStyleModifier *BKE_add_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, int type);
+LineStyleModifier *BKE_add_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, int type);
+
+LineStyleModifier *BKE_copy_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m);
+LineStyleModifier *BKE_copy_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m);
+LineStyleModifier *BKE_copy_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m);
+LineStyleModifier *BKE_copy_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m);
+
+void BKE_remove_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
+void BKE_remove_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
+void BKE_remove_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
+void BKE_remove_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier);
+
+void BKE_move_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction);
+void BKE_move_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction);
+void BKE_move_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction);
+void BKE_move_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction);
+
+void BKE_list_modifier_color_ramps(FreestyleLineStyle *linestyle, ListBase *listbase);
+char *BKE_path_from_ID_to_color_ramp(FreestyleLineStyle *linestyle, struct ColorBand *color_ramp);
+
+void BKE_unlink_linestyle_target_object(FreestyleLineStyle *linestyle, struct Object *ob);
+
+#endif /* __BKE_LINESTYLE_H__ */
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index cfdcf1436bf..264a7421e91 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -51,9 +51,10 @@ struct Library;
typedef struct Main {
struct Main *next, *prev;
char name[1024]; /* 1024 = FILE_MAX */
- short versionfile, subversionfile;
+ short versionfile, subversionfile; /* see BLENDER_VERSION, BLENDER_SUBVERSION */
short minversionfile, minsubversionfile;
- int revision; /* svn revision of binary that saved file */
+ int revision; /* svn revision of binary that saved file */
+ short recovered; /* indicate the main->name (file) is the recovered one */
struct Library *curlib;
ListBase scene;
@@ -87,14 +88,20 @@ typedef struct Main {
ListBase gpencil;
ListBase movieclip;
ListBase mask;
+ ListBase linestyle;
char id_tag_update[256];
} Main;
+#define MAIN_VERSION_ATLEAST(main, ver, subver) \
+ ((main)->versionfile > (ver) || (main->versionfile == (ver) && (main)->subversionfile >= (subver)))
+#define MAIN_VERSION_OLDER(main, ver, subver) \
+ ((main)->versionfile < (ver) || (main->versionfile == (ver) && (main)->subversionfile < (subver)))
+
+
#ifdef __cplusplus
}
#endif
-#endif
-
+#endif /* __BKE_MAIN_H__ */
diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h
index cc15ceecbac..b40ad4814f0 100644
--- a/source/blender/blenkernel/BKE_mask.h
+++ b/source/blender/blenkernel/BKE_mask.h
@@ -98,7 +98,7 @@ void BKE_mask_point_select_set(struct MaskSplinePoint *point, const short do_sel
void BKE_mask_point_select_set_handle(struct MaskSplinePoint *point, const short do_select);
/* general */
-struct Mask *BKE_mask_new(const char *name);
+struct Mask *BKE_mask_new(struct Main *bmain, const char *name);
struct Mask *BKE_mask_copy_nolib(struct Mask *mask);
struct Mask *BKE_mask_copy(struct Mask *mask);
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index dd1b1a7752b..350eaf23f6f 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -52,7 +52,7 @@ void BKE_material_free_ex(struct Material *ma, int do_id_user);
void test_object_materials(struct ID *id);
void resize_object_material(struct Object *ob, const short totcol);
void init_material(struct Material *ma);
-struct Material *BKE_material_add(const char *name);
+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);
struct Material *give_node_material(struct Material *ma); /* returns node material or self */
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
index 7a0eea1b009..9bbff515983 100644
--- a/source/blender/blenkernel/BKE_mball.h
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -32,6 +32,7 @@
* \since March 2001
* \author nzc
*/
+struct Main;
struct MetaBall;
struct Object;
struct Scene;
@@ -39,7 +40,7 @@ struct MetaElem;
void BKE_mball_unlink(struct MetaBall *mb);
void BKE_mball_free(struct MetaBall *mb);
-struct MetaBall *BKE_mball_add(const char *name);
+struct MetaBall *BKE_mball_add(struct Main *bmain, const char *name);
struct MetaBall *BKE_mball_copy(struct MetaBall *mb);
void BKE_mball_make_local(struct MetaBall *mb);
@@ -47,8 +48,8 @@ void BKE_mball_make_local(struct MetaBall *mb);
void BKE_mball_cubeTable_free(void);
void BKE_mball_polygonize(struct Scene *scene, struct Object *ob, struct ListBase *dispbase);
-int BKE_mball_is_basis_for(struct Object *ob1, struct Object *ob2);
-int BKE_mball_is_basis(struct Object *ob);
+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);
void BKE_mball_texspace_calc(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index e53d0efffbd..71024a4ead2 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -39,6 +39,7 @@ struct DispList;
struct ListBase;
struct BMEditMesh;
struct BMesh;
+struct Main;
struct Mesh;
struct MPoly;
struct MLoop;
@@ -80,7 +81,7 @@ struct BMesh *BKE_mesh_to_bmesh(struct Mesh *me, struct Object *ob);
int BKE_mesh_recalc_tessellation(struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata,
struct MVert *mvert,
int totface, int totloop, int totpoly,
- const int do_face_normals);
+ const bool do_face_normals);
/* for forwards compat only quad->tri polys to mface, skip ngons.
*/
@@ -100,6 +101,16 @@ void BKE_mesh_calc_poly_center(struct MPoly *mpoly, struct MLoop *loopstart,
float BKE_mesh_calc_poly_area(struct MPoly *mpoly, struct MLoop *loopstart,
struct MVert *mvarray, const float polynormal[3]);
+void BKE_mesh_calc_relative_deform(
+ const struct MPoly *mpoly, const int totpoly,
+ const struct MLoop *mloop, const int totvert,
+
+ const float (*vert_cos_src)[3],
+ const float (*vert_cos_dst)[3],
+
+ const float (*vert_cos_org)[3],
+ float (*vert_cos_new)[3]);
+
/* Find the index of the loop in 'poly' which references vertex,
* returns -1 if not found */
int poly_find_loop_from_vert(const struct MPoly *poly,
@@ -123,36 +134,43 @@ void BKE_mesh_flush_hidden_from_verts(const struct MVert *mvert,
struct MEdge *medge, int totedge,
struct MPoly *mpoly, int totpoly);
+void BKE_mesh_flush_select_from_polys_ex(struct MVert *mvert, const int totvert,
+ struct MLoop *mloop,
+ struct MEdge *medge, const int totedge,
+ const struct MPoly *mpoly, const int totpoly);
+void BKE_mesh_flush_select_from_polys(struct Mesh *me);
+void BKE_mesh_flush_select_from_verts_ex(const struct MVert *mvert, const int totvert,
+ struct MLoop *mloop,
+ struct MEdge *medge, const int totedge,
+ struct MPoly *mpoly, const int totpoly);
+void BKE_mesh_flush_select_from_verts(struct Mesh *me);
+
void BKE_mesh_unlink(struct Mesh *me);
void BKE_mesh_free(struct Mesh *me, int unlink);
-struct Mesh *BKE_mesh_add(const char *name);
+struct Mesh *BKE_mesh_add(struct Main *bmain, const char *name);
+struct Mesh *BKE_mesh_copy_ex(struct Main *bmain, struct Mesh *me);
struct Mesh *BKE_mesh_copy(struct Mesh *me);
-void mesh_update_customdata_pointers(struct Mesh *me, const short do_ensure_tess_cd);
+void BKE_mesh_update_customdata_pointers(struct Mesh *me, const bool do_ensure_tess_cd);
void BKE_mesh_make_local(struct Mesh *me);
void BKE_mesh_boundbox_calc(struct Mesh *me, float r_loc[3], float r_size[3]);
void BKE_mesh_texspace_calc(struct Mesh *me);
-float *BKE_mesh_orco_verts_get(struct Object *ob);
+float (*BKE_mesh_orco_verts_get(struct Object *ob))[3];
void BKE_mesh_orco_verts_transform(struct Mesh *me, float (*orco)[3], int totvert, int invert);
int test_index_face(struct MFace *mface, struct CustomData *mfdata, int mfindex, int nr);
struct Mesh *BKE_mesh_from_object(struct Object *ob);
-void set_mesh(struct Object *ob, struct Mesh *me);
+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,
- int *_totloop, int *_totpoly, int **orco_index_ptr);
-void BKE_mesh_nurbs_to_mdata_orco(struct MPoly *mpoly, int totpoly,
- struct MLoop *mloops, struct MLoopUV *mloopuvs,
- float (*orco)[3], int (*orco_index)[4]);
+ struct MLoopUV **alluv, int *_totloop, int *_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_from_nurbs_displist(struct Object *ob, struct ListBase *dispbase,
- int **orco_index_ptr);
-void BKE_mesh_from_curve(struct Scene *scene, struct Object *ob);
-void free_dverts(struct MDeformVert *dvert, int totvert);
-void copy_dverts(struct MDeformVert *dst, struct MDeformVert *src, int totvert); /* __NLA */
+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_delete_material_index(struct Mesh *me, short index);
void BKE_mesh_smooth_flag_set(struct Object *meshOb, int enableSmooth);
void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh);
@@ -194,7 +212,7 @@ void BKE_mesh_calc_normals_mapping_ex(
struct MVert *mverts, int numVerts,
struct MLoop *mloop, struct MPoly *mpolys, int numLoops, int numPolys, float (*polyNors_r)[3],
struct MFace *mfaces, int numFaces, int *origIndexFace, float (*faceNors_r)[3],
- const short only_face_normals);
+ const bool only_face_normals);
void BKE_mesh_calc_normals(
struct MVert *mverts, int numVerts,
@@ -203,7 +221,7 @@ void BKE_mesh_calc_normals(
/* Return a newly MEM_malloc'd array of all the mesh vertex locations
* (_numVerts_r_ may be NULL) */
-float (*mesh_getVertexCos(struct Mesh *me, int *numVerts_r))[3];
+float (*mesh_getVertexCos(struct Mesh *me, int *r_numVerts))[3];
/* map from uv vertex to face (for select linked, stitch, uv suburf) */
@@ -229,8 +247,6 @@ typedef struct UvElement {
/* Next UvElement corresponding to same vertex */
struct UvElement *next;
/* Face the element belongs to */
- struct BMFace *face;
- /* Index in the editFace of the uv */
struct BMLoop *l;
/* index in loop. */
unsigned short tfindex;
@@ -264,7 +280,7 @@ typedef struct UvElementMap {
* to make that many islands, he can bite me :p */
#define INVALID_ISLAND 0xFFFF
-UvVertMap *BKE_mesh_uv_vert_map_make(struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv,
+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);
UvMapVert *BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v);
void BKE_mesh_uv_vert_map_free(UvVertMap *vmap);
@@ -280,12 +296,12 @@ typedef struct IndexNode {
int index;
} IndexNode;
-void create_vert_poly_map(MeshElemMap **map, int **mem,
- const struct MPoly *mface, const struct MLoop *mloop,
- int totvert, int totface, int totloop);
+void BKE_mesh_vert_poly_map_create(MeshElemMap **map, int **mem,
+ const struct MPoly *mface, const struct MLoop *mloop,
+ int totvert, int totface, int totloop);
-void create_vert_edge_map(MeshElemMap **map, int **mem,
- const struct MEdge *medge, int totvert, int totedge);
+void BKE_mesh_vert_edge_map_create(MeshElemMap **map, int **mem,
+ const struct MEdge *medge, int totvert, int totedge);
/* vertex level transformations & checks (no derived mesh) */
@@ -293,7 +309,7 @@ int BKE_mesh_minmax(struct Mesh *me, float r_min[3], float r_max[3]);
int BKE_mesh_center_median(struct Mesh *me, float cent[3]);
int BKE_mesh_center_bounds(struct Mesh *me, float cent[3]);
int BKE_mesh_center_centroid(struct Mesh *me, float cent[3]);
-void BKE_mesh_translate(struct Mesh *me, float offset[3], int do_keys);
+void BKE_mesh_translate(struct Mesh *me, const float offset[3], const bool do_keys);
/* mesh_validate.c */
/* XXX Loop v/e are unsigned, so using max uint_32 value as invalid marker... */
@@ -306,11 +322,11 @@ int BKE_mesh_validate_arrays(
struct MLoop *mloops, unsigned int totloop,
struct MPoly *mpolys, unsigned int totpoly,
struct MDeformVert *dverts, /* assume totvert length */
- const short do_verbose, const short do_fixes);
-int BKE_mesh_validate(struct Mesh *me, int do_verbose);
+ const bool do_verbose, const bool do_fixes);
+int BKE_mesh_validate(struct Mesh *me, const int do_verbose);
int BKE_mesh_validate_dm(struct DerivedMesh *dm);
-void BKE_mesh_calc_edges(struct Mesh *mesh, int update);
+void BKE_mesh_calc_edges(struct Mesh *mesh, bool update, const bool select);
void BKE_mesh_ensure_navmesh(struct Mesh *me);
@@ -327,6 +343,8 @@ void BKE_mesh_loops_to_mface_corners(struct CustomData *fdata, struct CustomData
void BKE_mesh_poly_calc_angles(struct MVert *mvert, struct MLoop *mloop,
struct MPoly *mp, float angles[]);
+void BKE_mesh_do_versions_cd_flag_init(struct Mesh *mesh);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 2fa78b30835..cc260b8f60c 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -358,8 +358,6 @@ int modifiers_isCorrectableDeformed(struct Object *ob);
void modifier_freeTemporaryData(struct ModifierData *md);
int modifiers_isPreview(struct Object *ob);
-int modifiers_indexInObject(struct Object *ob, struct ModifierData *md);
-
typedef struct CDMaskLink {
struct CDMaskLink *next;
CustomDataMask mask;
diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h
index 25d2678ea47..f97b5b1f3a1 100644
--- a/source/blender/blenkernel/BKE_movieclip.h
+++ b/source/blender/blenkernel/BKE_movieclip.h
@@ -43,7 +43,7 @@ struct MovieDistortion;
void BKE_movieclip_free(struct MovieClip *clip);
void BKE_movieclip_unlink(struct Main *bmain, struct MovieClip *clip);
-struct MovieClip *BKE_movieclip_file_add(const char *name);
+struct MovieClip *BKE_movieclip_file_add(struct Main *bmain, const char *name);
void BKE_movieclip_reload(struct MovieClip *clip);
struct ImBuf *BKE_movieclip_get_ibuf(struct MovieClip *clip, struct MovieClipUser *user);
@@ -64,9 +64,18 @@ void BKE_movieclip_get_cache_segments(struct MovieClip *clip, struct MovieClipUs
void BKE_movieclip_build_proxy_frame(struct MovieClip *clip, int clip_flag, struct MovieDistortion *distortion,
int cfra, int *build_sizes, int build_count, int undistorted);
+void BKE_movieclip_build_proxy_frame_for_ibuf(struct MovieClip *clip, struct ImBuf *ibuf, struct MovieDistortion *distortion,
+ int cfra, int *build_sizes, int build_count, int undistorted);
+
float BKE_movieclip_remap_scene_to_clip_frame(struct MovieClip *clip, float framenr);
float BKE_movieclip_remap_clip_to_scene_frame(struct MovieClip *clip, float framenr);
+void BKE_movieclip_filename_for_frame(struct MovieClip *clip, struct MovieClipUser *user, char *name);
+struct ImBuf *BKE_movieclip_anim_ibuf_for_frame(struct MovieClip *clip, struct MovieClipUser *user);
+
+int BKE_movieclip_has_cached_frame(struct MovieClip *clip, struct MovieClipUser *user);
+int BKE_movieclip_put_frame_if_possible(struct MovieClip *clip, struct MovieClipUser *user, struct ImBuf *ibuf);
+
/* cacheing flags */
#define MOVIECLIP_CACHE_SKIP (1 << 0)
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index bee2c374f27..aa09fe1ce8d 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -75,7 +75,7 @@ struct DerivedMesh *multires_make_derived_from_derived(struct DerivedMesh *dm,
struct MultiresModifierData *find_multires_modifier_before(struct Scene *scene,
struct ModifierData *lastmd);
-struct MultiresModifierData *get_multires_modifier(struct Scene *scene, struct Object *ob, int use_first);
+struct MultiresModifierData *get_multires_modifier(struct Scene *scene, struct Object *ob, bool use_first);
struct DerivedMesh *get_multires_dm(struct Scene *scene, struct MultiresModifierData *mmd,
struct Object *ob);
void multiresModifier_del_levels(struct MultiresModifierData *, struct Object *, int direction);
diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h
index 9e08f3a8c83..5b41dc481c9 100644
--- a/source/blender/blenkernel/BKE_nla.h
+++ b/source/blender/blenkernel/BKE_nla.h
@@ -114,7 +114,7 @@ void BKE_nla_tweakmode_exit(struct AnimData *adt);
/* Time Mapping */
/* time mapping conversion modes */
-enum {
+enum eNlaTime_ConvertModes {
/* convert from global time to strip time - for evaluation */
NLATIME_CONVERT_EVAL = 0,
/* convert from global time to strip time - for editing corrections */
@@ -123,7 +123,7 @@ enum {
/* convert from strip time to global time */
// xxx old 1 invert
NLATIME_CONVERT_MAP,
-} eNlaTime_ConvertModes;
+};
float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short mode);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index b8f168cbdea..e62994576a3 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -32,8 +32,21 @@
* \ingroup bke
*/
+#include "BLI_ghash.h"
+#include "BLI_utildefines.h"
+
#include "DNA_listBase.h"
+/* for FOREACH_NODETREE */
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_node_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_world_types.h"
+
+#include "RNA_types.h"
+
/* not very important, but the stack solver likes to know a maximum */
#define MAX_SOCKET 64
@@ -43,11 +56,15 @@ struct bNodeLink;
struct bNodeSocket;
struct bNodeStack;
struct bNodeTree;
+struct bNodeTreeType;
struct bNodeTreeExec;
+struct bNodeExecContext;
+struct bNodeExecData;
struct GPUMaterial;
struct GPUNode;
struct GPUNodeStack;
struct ID;
+struct ImBuf;
struct ImageFormatData;
struct ListBase;
struct Main;
@@ -64,6 +81,8 @@ struct ARegion;
struct Object;
struct ColorManagedViewSettings;
struct ColorManagedDisplaySettings;
+struct bNodeInstanceHash;
+
/* ************** NODE TYPE DEFINITIONS ***** */
@@ -71,9 +90,9 @@ struct ColorManagedDisplaySettings;
* Can be used to quickly define a list of static sockets for a node,
* which are added to each new node of that type.
*
- * \deprecated New nodes should add default sockets in the initialization
- * function instead. This struct is mostly kept for old nodes and should
- * be removed some time.
+ * \deprecated This struct is used by C nodes to define templates as simple
+ * static struct lists. These are converted to the new template collections
+ * in RNA types automatically.
*/
typedef struct bNodeSocketTemplate {
int type, limit;
@@ -85,38 +104,38 @@ typedef struct bNodeSocketTemplate {
/* after this line is used internal only */
struct bNodeSocket *sock; /* used to hold verified socket */
+ char identifier[64]; /* generated from name */
} bNodeSocketTemplate;
-typedef void (*NodeSocketButtonFunction)(const struct bContext *C, struct uiBlock *block,
- struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock,
- const char *name, int x, int y, int width);
-
/** Defines a socket type.
* Defines the appearance and behavior of a socket in the UI.
*/
typedef struct bNodeSocketType {
- int type;
- char ui_name[64]; /* MAX_NAME */
- char ui_description[128];
- int ui_icon;
- char ui_color[4];
+ char idname[64]; /* identifier name */
+
+ void (*draw)(struct bContext *C, struct uiLayout *layout, struct PointerRNA *ptr, struct PointerRNA *node_ptr);
+ void (*draw_color)(struct bContext *C, struct PointerRNA *ptr, struct PointerRNA *node_ptr, float *r_color);
- const char *value_structname;
- int value_structsize;
+ void (*interface_draw)(struct bContext *C, struct uiLayout *layout, struct PointerRNA *ptr);
+ void (*interface_draw_color)(struct bContext *C, struct PointerRNA *ptr, float *r_color);
+ void (*interface_register_properties)(struct bNodeTree *ntree, struct bNodeSocket *stemp, struct StructRNA *data_srna);
+ void (*interface_init_socket)(struct bNodeTree *ntree, struct bNodeSocket *stemp, struct bNode *node, struct bNodeSocket *sock, const char *data_path);
+ void (*interface_from_socket)(struct bNodeTree *ntree, struct bNodeSocket *stemp, struct bNode *node, struct bNodeSocket *sock);
- NodeSocketButtonFunction buttonfunc;
+ /* RNA integration */
+ ExtensionRNA ext_socket;
+ ExtensionRNA ext_interface;
+
+ /* for standard socket types in C */
+ int type, subtype;
} bNodeSocketType;
-/** Template for creating a node.
- * Stored required parameters to make a new node of a specific type.
- */
-typedef struct bNodeTemplate {
- int type;
-
- struct Main *main;
- struct Scene *scene;
- struct bNodeTree *ngroup; /* group tree */
-} bNodeTemplate;
+typedef void (*NodeSocketDrawFunction)(struct bContext *C, struct uiLayout *layout, struct PointerRNA *ptr, struct PointerRNA *node_ptr, int linked);
+
+typedef void *(*NodeInitExecFunction)(struct bNodeExecContext *context, struct bNode *node, bNodeInstanceKey key);
+typedef void (*NodeFreeExecFunction)(struct bNode *node, void *nodedata);
+typedef void (*NodeExecFunction)(void *data, int thread, struct bNode *, struct bNodeExecData *execdata, struct bNodeStack **in, struct bNodeStack **out);
+typedef int (*NodeGPUExecFunction)(struct GPUMaterial *mat, struct bNode *node, struct bNodeExecData *execdata, struct GPUNodeStack *in, struct GPUNodeStack *out);
/** Defines a node type.
* Initial attributes and constants for a node as well as callback functions
@@ -126,8 +145,13 @@ typedef struct bNodeType {
void *next, *prev;
short needs_free; /* set for allocated types that need to be freed */
+ char idname[64]; /* identifier name */
int type;
- char name[64]; /* MAX_NAME */
+
+ char ui_name[64]; /* MAX_NAME */
+ char ui_description[256];
+ int ui_icon;
+
float width, minwidth, maxwidth;
float height, minheight, maxheight;
short nclass, flag, compatibility;
@@ -138,7 +162,8 @@ typedef struct bNodeType {
char storagename[64]; /* struct name for DNA */
/// Main draw function for the node.
- void (*drawfunc)(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node);
+ void (*drawfunc)(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode,
+ struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key);
/// Updates the node geometry attributes according to internal state before actual drawing.
void (*drawupdatefunc)(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node);
/// Draw the option buttons on the node.
@@ -149,8 +174,11 @@ typedef struct bNodeType {
void (*uibackdropfunc)(struct SpaceNode *snode, struct ImBuf *backdrop, struct bNode *node, int x, int y);
/// Draw a node socket. Default draws the input value button.
- NodeSocketButtonFunction drawinputfunc;
- NodeSocketButtonFunction drawoutputfunc;
+ /* XXX deprecated, only used for the OutputFile node,
+ * should be removed at some point.
+ */
+ NodeSocketDrawFunction drawinputfunc;
+ NodeSocketDrawFunction drawoutputfunc;
/// Optional custom label function for the node header.
const char *(*labelfunc)(struct bNode *);
@@ -167,45 +195,42 @@ typedef struct bNodeType {
void (*verifyfunc)(struct bNodeTree *ntree, struct bNode *node, struct ID *id);
/// Initialize a new node instance of this type after creation.
- void (*initfunc)(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp);
- /// Free the custom storage data.
- void (*freestoragefunc)(struct bNode *node);
- /// Make a copy of the custom storage data.
- void (*copystoragefunc)(struct bNode *node, struct bNode *target);
-
- /// Create a template from an existing node.
- struct bNodeTemplate (*templatefunc)(struct bNode *);
- /** If a node can be made from the template in the given node tree.
- * \note Node groups can not be created inside their own node tree.
- */
- int (*validfunc)(struct bNodeTree *ntree, struct bNodeTemplate *ntemp);
+ void (*initfunc)(struct bNodeTree *ntree, struct bNode *node);
+ /// Free the node instance.
+ void (*freefunc)(struct bNode *node);
+ /// Make a copy of the node instance.
+ void (*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node);
- /// Initialize a node tree associated to this node type.
- void (*inittreefunc)(struct bNodeTree *ntree);
- /// Update a node tree associated to this node type.
- void (*updatetreefunc)(struct bNodeTree *ntree);
+ /* Registerable API callback versions, called in addition to C callbacks */
+ void (*initfunc_api)(const struct bContext *C, struct PointerRNA *ptr);
+ void (*freefunc_api)(struct PointerRNA *ptr);
+ void (*copyfunc_api)(struct PointerRNA *ptr, struct bNode *src_node);
- /* group edit callbacks for operators */
- /* XXX this is going to be changed as required by the UI */
- struct bNodeTree *(*group_edit_get)(struct bNode *node);
- struct bNodeTree *(*group_edit_set)(struct bNode *node, int edit);
- void (*group_edit_clear)(struct bNode *node);
+ /* can this node type be added to a node tree */
+ int (*poll)(struct bNodeType *ntype, struct bNodeTree *nodetree);
+ /* can this node be added to a node tree */
+ int (*poll_instance)(struct bNode *node, struct bNodeTree *nodetree);
/* Update the internal links list, for muting and disconnect operators. */
void (*update_internal_links)(struct bNodeTree *, struct bNode *node);
/* **** execution callbacks **** */
- void *(*initexecfunc)(struct bNode *node);
- void (*freeexecfunc)(struct bNode *node, void *nodedata);
- void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, struct bNodeStack **);
- /* XXX this alternative exec function has been added to avoid changing all node types.
- * when a final generic version of execution code is defined, this will be changed anyway
- */
- void (*newexecfunc)(void *data, int thread, struct bNode *, void *nodedata, struct bNodeStack **, struct bNodeStack **);
+ NodeInitExecFunction initexecfunc;
+ NodeFreeExecFunction freeexecfunc;
+ NodeExecFunction execfunc;
/* gpu */
- int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out);
- /* extended gpu function */
- int (*gpuextfunc)(struct GPUMaterial *mat, struct bNode *node, void *nodedata, struct GPUNodeStack *in, struct GPUNodeStack *out);
+ NodeGPUExecFunction gpufunc;
+
+ /* Group type static info
+ *
+ * XXX This data is needed by group operators. If these operators could be implemented completely in Python,
+ * the static data could instead be stored in Python classes and would need no special treatment.
+ * Due to the way group operators move nodes between data blocks this is currently not possible.
+ */
+ char group_tree_idname[64]; /* tree type associated to the group node type */
+
+ /* RNA integration */
+ ExtensionRNA ext;
} bNodeType;
/* node->exec, now in use for composites (#define for break is same as ready yes) */
@@ -244,6 +269,7 @@ typedef struct bNodeType {
#define NODE_CLASS_TRANSFORM 30
#define NODE_CLASS_COMBINE 31
#define NODE_CLASS_SCRIPT 32
+#define NODE_CLASS_INTERFACE 33
#define NODE_CLASS_SHADER 40
#define NODE_CLASS_LAYOUT 100
@@ -257,25 +283,34 @@ typedef struct bNodeType {
#define NODE_RESIZE_RIGHT 4
#define NODE_RESIZE_LEFT 8
-/* enum values for input/output */
-#define SOCK_IN 1
-#define SOCK_OUT 2
+typedef enum eNodeSizePreset {
+ NODE_SIZE_DEFAULT,
+ NODE_SIZE_SMALL,
+ NODE_SIZE_LARGE
+} eNodeSizePreset;
struct bNodeTreeExec;
-typedef void (*bNodeTreeCallback)(void *calldata, struct ID *owner_id, struct bNodeTree *ntree);
typedef void (*bNodeClassCallback)(void *calldata, int nclass, const char *name);
typedef struct bNodeTreeType {
int type; /* type identifier */
- char idname[64]; /* id name for RNA identification */
-
- ListBase node_types; /* type definitions */
+ char idname[64]; /* identifier name */
+
+ char ui_name[64];
+ char ui_description[256];
+ int ui_icon;
/* callbacks */
void (*free_cache)(struct bNodeTree *ntree);
void (*free_node_cache)(struct bNodeTree *ntree, struct bNode *node);
- void (*foreach_nodetree)(struct Main *main, void *calldata, bNodeTreeCallback func); /* iteration over all node trees */
void (*foreach_nodeclass)(struct Scene *scene, void *calldata, bNodeClassCallback func); /* iteration over all node classes */
+ /* Add menu for this node tree. */
+ void (*draw_add_menu)(const struct bContext *C, struct uiLayout *layout, struct bNodeTree *ntree);
+ /* Check visibility in the node editor */
+ int (*poll)(const struct bContext *C, struct bNodeTreeType *ntreetype);
+ /* Select a node tree from the context */
+ void (*get_from_context)(const struct bContext *C, struct bNodeTreeType *ntreetype,
+ struct bNodeTree **r_ntree, struct ID **r_id, struct ID **r_from);
/* calls allowing threaded composite */
void (*localize)(struct bNodeTree *localtree, struct bNodeTree *ntree);
@@ -284,23 +319,37 @@ typedef struct bNodeTreeType {
/* Tree update. Overrides nodetype->updatetreefunc! */
void (*update)(struct bNodeTree *ntree);
- /* Node update. Overrides nodetype->updatefunc! */
- void (*update_node)(struct bNodeTree *ntree, struct bNode *node);
int (*validate_link)(struct bNodeTree *ntree, struct bNodeLink *link);
-
- /* Default internal linking. */
- void (*update_internal_links)(struct bNodeTree *, struct bNode *node);
+
+ /* RNA integration */
+ ExtensionRNA ext;
} bNodeTreeType;
+
/* ************** GENERIC API, TREES *************** */
-struct bNodeTreeType *ntreeGetType(int type);
-struct bNodeType *ntreeGetNodeType(struct bNodeTree *ntree);
-struct bNodeSocketType *ntreeGetSocketType(int type);
+struct bNodeTreeType *ntreeTypeFind(const char *idname);
+void ntreeTypeAdd(struct bNodeTreeType *nt);
+void ntreeTypeFreeLink(struct bNodeTreeType *nt);
+bool ntreeIsRegistered(struct bNodeTree *ntree);
+struct GHashIterator *ntreeTypeGetIterator(void);
+
+/* helper macros for iterating over tree types */
+#define NODE_TREE_TYPES_BEGIN(ntype) \
+{ \
+ GHashIterator *__node_tree_type_iter__ = ntreeTypeGetIterator(); \
+ for (; BLI_ghashIterator_notDone(__node_tree_type_iter__); BLI_ghashIterator_step(__node_tree_type_iter__)) { \
+ bNodeTreeType *ntype = BLI_ghashIterator_getValue(__node_tree_type_iter__);
-struct bNodeTree *ntreeAddTree(const char *name, int type, int nodetype);
-void ntreeInitTypes(struct bNodeTree *ntree);
+#define NODE_TREE_TYPES_END \
+ } \
+ BLI_ghashIterator_free(__node_tree_type_iter__); \
+}
+
+void ntreeSetTypes(const struct bContext *C, struct bNodeTree *ntree);
+
+struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char *idname);
/* copy/free funcs, need to manage ID users */
void ntreeFreeTree_ex(struct bNodeTree *ntree, const short do_id_user);
@@ -330,8 +379,6 @@ void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode *
* new tree types have a per-output socket flag to indicate the final output to use explicitly.
*/
void ntreeSetOutput(struct bNodeTree *ntree);
-void ntreeInitPreview(struct bNodeTree *, int xsize, int ysize);
-void ntreeClearPreview(struct bNodeTree *ntree);
void ntreeFreeCache(struct bNodeTree *ntree);
@@ -341,29 +388,88 @@ 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 *************** */
+
+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,
+ struct bNodeSocket *next_sock, const char *name);
+struct bNodeSocket *ntreeAddSocketInterfaceFromSocket(struct bNodeTree *ntree, struct bNode *from_node, struct bNodeSocket *from_sock);
+struct bNodeSocket *ntreeInsertSocketInterfaceFromSocket(struct bNodeTree *ntree, struct bNodeSocket *next_sock,
+ struct bNode *from_node, struct bNodeSocket *from_sock);
+void ntreeRemoveSocketInterface(struct bNodeTree *ntree, struct bNodeSocket *sock);
+
+struct StructRNA *ntreeInterfaceTypeGet(struct bNodeTree *ntree, int create);
+void ntreeInterfaceTypeFree(struct bNodeTree *ntree);
+void ntreeInterfaceTypeUpdate(struct bNodeTree *ntree);
+
/* ************** GENERIC API, NODES *************** */
-struct bNodeSocket *nodeAddSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, const char *name, int type);
-struct bNodeSocket *nodeInsertSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, struct bNodeSocket *next_sock, const char *name, int type);
+struct bNodeType *nodeTypeFind(const char *idname);
+void nodeRegisterType(struct bNodeType *ntype);
+void nodeUnregisterType(struct bNodeType *ntype);
+bool nodeIsRegistered(struct bNode *node);
+struct GHashIterator *nodeTypeGetIterator(void);
+
+/* helper macros for iterating over node types */
+#define NODE_TYPES_BEGIN(ntype) \
+{ \
+ GHashIterator *__node_type_iter__ = nodeTypeGetIterator(); \
+ for (; BLI_ghashIterator_notDone(__node_type_iter__); BLI_ghashIterator_step(__node_type_iter__)) { \
+ bNodeType *ntype = BLI_ghashIterator_getValue(__node_type_iter__);
+
+#define NODE_TYPES_END \
+ } \
+ BLI_ghashIterator_free(__node_type_iter__); \
+}
+
+struct bNodeSocketType *nodeSocketTypeFind(const char *idname);
+void nodeRegisterSocketType(struct bNodeSocketType *stype);
+void nodeUnregisterSocketType(struct bNodeSocketType *stype);
+bool nodeSocketIsRegistered(struct bNodeSocket *sock);
+struct GHashIterator *nodeSocketTypeGetIterator(void);
+const char * nodeStaticSocketType(int type, int subtype);
+const char * nodeStaticSocketInterfaceType(int type, int subtype);
+
+/* helper macros for iterating over node types */
+#define NODE_SOCKET_TYPES_BEGIN(stype) \
+{ \
+ GHashIterator *__node_socket_type_iter__ = nodeSocketTypeGetIterator(); \
+ for (; BLI_ghashIterator_notDone(__node_socket_type_iter__); BLI_ghashIterator_step(__node_socket_type_iter__)) { \
+ bNodeSocketType *stype = BLI_ghashIterator_getValue(__node_socket_type_iter__);
+
+#define NODE_SOCKET_TYPES_END \
+ } \
+ BLI_ghashIterator_free(__node_socket_type_iter__); \
+}
+
+void nodeMakeDynamicType(struct bNode *node);
+int nodeDynamicUnlinkText(struct ID *txtid);
+
+struct bNodeSocket *nodeFindSocket(struct bNode *node, int in_out, const char *identifier);
+struct bNodeSocket *nodeAddSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, const char *idname,
+ const char *identifier, const char *name);
+struct bNodeSocket *nodeInsertSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, const char *idname,
+ struct bNodeSocket *next_sock, const char *identifier, const char *name);
+struct bNodeSocket *nodeAddStaticSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, int type, int subtype,
+ const char *identifier, const char *name);
+struct bNodeSocket *nodeInsertStaticSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, int type, int subtype,
+ struct bNodeSocket *next_sock, const char *identifier, const char *name);
void nodeRemoveSocket(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock);
void nodeRemoveAllSockets(struct bNodeTree *ntree, struct bNode *node);
-void nodeAddToPreview(struct bNode *node, const float col[4], int x, int y, int do_manage);
-
-struct bNode *nodeAddNode(struct bNodeTree *ntree, struct bNodeTemplate *ntemp);
+struct bNode *nodeAddNode(const struct bContext *C, struct bNodeTree *ntree, const char *idname);
+struct bNode *nodeAddStaticNode(const struct bContext *C, struct bNodeTree *ntree, int type);
void nodeUnlinkNode(struct bNodeTree *ntree, struct bNode *node);
void nodeUniqueName(struct bNodeTree *ntree, struct bNode *node);
-void nodeRegisterType(struct bNodeTreeType *ttype, struct bNodeType *ntype);
-void nodeMakeDynamicType(struct bNode *node);
-int nodeDynamicUnlinkText(struct ID *txtid);
-
void nodeFreeNode(struct bNodeTree *ntree, struct bNode *node);
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);
void nodeInternalRelink(struct bNodeTree *ntree, struct bNode *node);
void nodeToView(struct bNode *node, float x, float y, float *rx, float *ry);
@@ -373,15 +479,16 @@ void nodeAttachNode(struct bNode *node, struct bNode *parent);
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, int *in_out);
+int nodeFindNode(struct bNodeTree *ntree, struct bNodeSocket *sock, struct bNode **nodep, int *sockindex);
struct bNodeLink *nodeFindLink(struct bNodeTree *ntree, struct bNodeSocket *from, struct bNodeSocket *to);
int nodeCountSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock);
+void nodeSetSelected(struct bNode *node, int select);
void nodeSetActive(struct bNodeTree *ntree, struct bNode *node);
struct bNode *nodeGetActive(struct bNodeTree *ntree);
struct bNode *nodeGetActiveID(struct bNodeTree *ntree, short idtype);
-int nodeSetActiveID(struct bNodeTree *ntree, short idtype, struct ID *id);
+bool nodeSetActiveID(struct bNodeTree *ntree, short idtype, struct ID *id);
void nodeClearActive(struct bNodeTree *ntree);
void nodeClearActiveID(struct bNodeTree *ntree, short idtype);
struct bNode *nodeGetActiveTexture(struct bNodeTree *ntree);
@@ -389,11 +496,9 @@ struct bNode *nodeGetActiveTexture(struct bNodeTree *ntree);
void nodeUpdate(struct bNodeTree *ntree, struct bNode *node);
int nodeUpdateID(struct bNodeTree *ntree, struct ID *id);
void nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *node);
-
-void nodeFreePreview(struct bNode *node);
+void nodeSynchronizeID(struct bNode *node, bool copy_to_id);
int nodeSocketIsHidden(struct bNodeSocket *sock);
-void nodeSocketSetType(struct bNodeSocket *sock, int type);
/* Node Clipboard */
void BKE_node_clipboard_init(struct bNodeTree *ntree);
@@ -405,77 +510,189 @@ const struct ListBase *BKE_node_clipboard_get_nodes(void);
const struct ListBase *BKE_node_clipboard_get_links(void);
int BKE_node_clipboard_get_type(void);
+/* Node Instance Hash */
+typedef struct bNodeInstanceHash
+{
+ GHash *ghash; /* XXX should be made a direct member, GHash allocation needs to support it */
+} bNodeInstanceHash;
+
+typedef void (*bNodeInstanceValueFP)(void *value);
+
+extern const bNodeInstanceKey NODE_INSTANCE_KEY_BASE;
+
+bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key, struct bNodeTree *ntree, struct bNode *node);
+
+bNodeInstanceHash *BKE_node_instance_hash_new(const char *info);
+void BKE_node_instance_hash_free(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp);
+void BKE_node_instance_hash_insert(bNodeInstanceHash *hash, bNodeInstanceKey key, void *value);
+void *BKE_node_instance_hash_lookup(bNodeInstanceHash *hash, bNodeInstanceKey key);
+int BKE_node_instance_hash_remove(bNodeInstanceHash *hash, bNodeInstanceKey key, bNodeInstanceValueFP valfreefp);
+void BKE_node_instance_hash_clear(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp);
+void *BKE_node_instance_hash_pop(bNodeInstanceHash *hash, bNodeInstanceKey key);
+int BKE_node_instance_hash_haskey(bNodeInstanceHash *hash, bNodeInstanceKey key);
+int BKE_node_instance_hash_size(bNodeInstanceHash *hash);
+
+void BKE_node_instance_hash_clear_tags(bNodeInstanceHash *hash);
+void BKE_node_instance_hash_tag(bNodeInstanceHash *hash, void *value);
+int BKE_node_instance_hash_tag_key(bNodeInstanceHash *hash, bNodeInstanceKey key);
+void BKE_node_instance_hash_remove_untagged(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp);
+
+typedef GHashIterator bNodeInstanceHashIterator;
+
+BLI_INLINE bNodeInstanceHashIterator *BKE_node_instance_hash_iterator_new(bNodeInstanceHash *hash) { return BLI_ghashIterator_new(hash->ghash); }
+BLI_INLINE void BKE_node_instance_hash_iterator_init(bNodeInstanceHashIterator *iter, bNodeInstanceHash *hash) { BLI_ghashIterator_init(iter, hash->ghash); }
+BLI_INLINE void BKE_node_instance_hash_iterator_free(bNodeInstanceHashIterator *iter) { BLI_ghashIterator_free(iter); }
+BLI_INLINE bNodeInstanceKey BKE_node_instance_hash_iterator_get_key(bNodeInstanceHashIterator *iter) { return *(bNodeInstanceKey *)BLI_ghashIterator_getKey(iter); }
+BLI_INLINE void *BKE_node_instance_hash_iterator_get_value(bNodeInstanceHashIterator *iter) { return BLI_ghashIterator_getValue(iter); }
+BLI_INLINE void BKE_node_instance_hash_iterator_step(bNodeInstanceHashIterator *iter) { BLI_ghashIterator_step(iter); }
+BLI_INLINE bool BKE_node_instance_hash_iterator_not_done(bNodeInstanceHashIterator *iter) { return BLI_ghashIterator_notDone(iter); }
+
+#define NODE_INSTANCE_HASH_ITER(iter_, hash_) \
+ for (BKE_node_instance_hash_iterator_init(&iter_, hash_); \
+ BKE_node_instance_hash_iterator_not_done(&iter_); \
+ BKE_node_instance_hash_iterator_step(&iter_))
+
+
+/* Node Previews */
+
+int BKE_node_preview_used(struct bNode *node);
+bNodePreview *BKE_node_preview_verify(struct bNodeInstanceHash *previews, bNodeInstanceKey key, int xsize, int ysize, int create);
+bNodePreview *BKE_node_preview_copy(struct bNodePreview *preview);
+void BKE_node_preview_free(struct bNodePreview *preview);
+void BKE_node_preview_init_tree(struct bNodeTree *ntree, int xsize, int ysize, int create_previews);
+void BKE_node_preview_free_tree(struct bNodeTree *ntree);
+void BKE_node_preview_remove_unused(struct bNodeTree *ntree);
+void BKE_node_preview_clear(struct bNodePreview *preview);
+void BKE_node_preview_clear_tree(struct bNodeTree *ntree);
+
+void BKE_node_preview_sync_tree(struct bNodeTree *to_ntree, struct bNodeTree *from_ntree);
+void BKE_node_preview_merge_tree(struct bNodeTree *to_ntree, struct bNodeTree *from_ntree, bool remove_old);
+
+void BKE_node_preview_set_pixel(struct bNodePreview *preview, const float col[4], int x, int y, int do_manage);
+
+
/* ************** NODE TYPE ACCESS *************** */
-struct bNodeTemplate nodeMakeTemplate(struct bNode *node);
-int nodeValid(struct bNodeTree *ntree, struct bNodeTemplate *ntemp);
const char *nodeLabel(struct bNode *node);
struct bNodeTree *nodeGroupEditGet(struct bNode *node);
struct bNodeTree *nodeGroupEditSet(struct bNode *node, int edit);
void nodeGroupEditClear(struct bNode *node);
+int nodeGroupPoll(struct bNodeTree *nodetree, struct bNodeTree *grouptree);
+
/* Init a new node type struct with default values and callbacks */
-void node_type_base(struct bNodeTreeType *ttype, struct bNodeType *ntype, int type,
- const char *name, short nclass, short flag);
+void node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag);
+void node_type_base_custom(struct bNodeType *ntype, const char *idname, const char *name, short nclass, short flag);
void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs);
void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth);
-void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp));
-void node_type_valid(struct bNodeType *ntype, int (*validfunc)(struct bNodeTree *ntree, struct bNodeTemplate *ntemp));
+void node_type_size_preset(struct bNodeType *ntype, eNodeSizePreset size);
+void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNodeTree *ntree, struct bNode *node));
void node_type_storage(struct bNodeType *ntype,
const char *storagename,
- void (*freestoragefunc)(struct bNode *),
- void (*copystoragefunc)(struct bNode *, struct bNode *));
+ void (*freefunc)(struct bNode *node),
+ void (*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node));
void node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bNode *));
-void node_type_template(struct bNodeType *ntype, struct bNodeTemplate (*templatefunc)(struct bNode *));
void node_type_update(struct bNodeType *ntype,
void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node),
void (*verifyfunc)(struct bNodeTree *ntree, struct bNode *node, struct ID *id));
-void node_type_tree(struct bNodeType *ntype,
- void (*inittreefunc)(struct bNodeTree *),
- void (*updatetreefunc)(struct bNodeTree *));
-void node_type_group_edit(struct bNodeType *ntype,
- struct bNodeTree *(*group_edit_get)(struct bNode *node),
- struct bNodeTree *(*group_edit_set)(struct bNode *node, int edit),
- void (*group_edit_clear)(struct bNode *node));
-
-void node_type_exec(struct bNodeType *ntype, void (*execfunc)(void *data, struct bNode *, struct bNodeStack **,
- struct bNodeStack **));
-void node_type_exec_new(struct bNodeType *ntype,
- void *(*initexecfunc)(struct bNode *node),
- void (*freeexecfunc)(struct bNode *node, void *nodedata),
- void (*newexecfunc)(void *data, int thread, struct bNode *, void *nodedata,
- struct bNodeStack **, struct bNodeStack **));
+
+void node_type_exec(struct bNodeType *ntype, NodeInitExecFunction initexecfunc, NodeFreeExecFunction freeexecfunc, NodeExecFunction execfunc);
+void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpufunc);
void node_type_internal_links(struct bNodeType *ntype, void (*update_internal_links)(struct bNodeTree *, struct bNode *));
-void node_type_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node,
- struct GPUNodeStack *in, struct GPUNodeStack *out));
-void node_type_gpu_ext(struct bNodeType *ntype, int (*gpuextfunc)(struct GPUMaterial *mat, struct bNode *node,
- void *nodedata, struct GPUNodeStack *in,
- struct GPUNodeStack *out));
void node_type_compatibility(struct bNodeType *ntype, short compatibility);
/* ************** COMMON NODES *************** */
+#define NODE_UNDEFINED -2 /* node type is not registered */
+#define NODE_CUSTOM -1 /* for dynamically registered custom types */
#define NODE_GROUP 2
-#define __NODE_FORLOOP 3 /* deprecated */
+#define __NODE_FORLOOP 3 /* deprecated */
#define __NODE_WHILELOOP 4 /* deprecated */
#define NODE_FRAME 5
#define NODE_REROUTE 6
+#define NODE_GROUP_INPUT 7
+#define NODE_GROUP_OUTPUT 8
-/* look up a socket on a group node by the internal group socket */
-struct bNodeSocket *node_group_find_input(struct bNode *gnode, struct bNodeSocket *gsock);
-struct bNodeSocket *node_group_find_output(struct bNode *gnode, struct bNodeSocket *gsock);
+void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree);
-struct bNodeSocket *node_group_add_socket(struct bNodeTree *ngroup, const char *name, int type, int in_out);
-struct bNodeSocket *node_group_expose_socket(struct bNodeTree *ngroup, struct bNodeSocket *sock, int in_out);
-void node_group_expose_all_sockets(struct bNodeTree *ngroup);
-void node_group_remove_socket(struct bNodeTree *ngroup, struct bNodeSocket *gsock, int in_out);
-struct bNodeSocket *node_group_add_extern_socket(struct bNodeTree *ntree, ListBase *lb, int in_out, struct bNodeSocket *gsock);
-
-/* in node_common.c */
-void register_node_type_frame(struct bNodeTreeType *ttype);
-void register_node_type_reroute(struct bNodeTreeType *ttype);
+/* 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:
+ *
+ * nodetree: The actual bNodeTree data block.
+ * Check nodetree->idname or nodetree->typeinfo to use only specific types.
+ *
+ * id: The owner of the bNodeTree data block.
+ * Same as nodetree if it's a linkable node tree from the library.
+ *
+ * Examples:
+ *
+ * FOREACH_NODETREE(bmain, nodetree)
+ * if (id == nodetree)
+ * printf("This is a linkable node tree");
+ * FOREACH_NODETREE_END
+ *
+ * FOREACH_NODETREE(bmain, nodetree)
+ * if (nodetree->idname == "ShaderNodeTree")
+ * printf("This is a shader node tree);
+ * if (GS(id) == ID_MA)
+ * printf(" and it's owned by a material");
+ * FOREACH_NODETREE_END
+ */
-void BKE_node_tree_unlink_id_cb(void *calldata, struct ID *owner_id, struct bNodeTree *ntree);
+#define FOREACH_NODETREE(bmain, _nodetree, _id) \
+{ \
+ bNodeTree *_nodetree; \
+ ID *_id; \
+ bNodeTree *_ngroup = bmain->nodetree.first; \
+ Scene *_scene = bmain->scene.first; \
+ Material *_mat = bmain->mat.first; \
+ Tex *_tex = bmain->tex.first; \
+ Lamp *_lamp = bmain->lamp.first; \
+ World *_world = bmain->world.first; \
+ /* avoid compiler warning about unused variables */ \
+ (void)_id; \
+ (void)_nodetree; \
+ do { \
+ if (_ngroup) { \
+ _nodetree = _ngroup; \
+ _id = (ID *)_ngroup; \
+ _ngroup = _ngroup->id.next; \
+ } \
+ else if (_scene) { \
+ _nodetree = _scene->nodetree; \
+ _id = (ID *)_scene; \
+ _scene = _scene->id.next; \
+ } \
+ else if (_mat) { \
+ _nodetree = _mat->nodetree; \
+ _id = (ID *)_mat; \
+ _mat = _mat->id.next; \
+ } \
+ else if (_tex) { \
+ _nodetree = _tex->nodetree; \
+ _id = (ID *)_tex; \
+ _tex = _tex->id.next; \
+ } \
+ else if (_lamp) { \
+ _nodetree = _lamp->nodetree; \
+ _id = (ID *)_lamp; \
+ _lamp = _lamp->id.next; \
+ } \
+ else if (_world) { \
+ _nodetree = _world->nodetree; \
+ _id = (ID *)_world; \
+ _world = _world->id.next; \
+ } \
+ else \
+ break; \
+ if (_nodetree) {
+
+#define FOREACH_NODETREE_END \
+ } \
+ } while (TRUE); \
+}
/* ************** SHADER NODES *************** */
@@ -557,6 +774,7 @@ struct ShadeResult;
#define SH_NODE_BSDF_REFRACTION 173
#define SH_NODE_TANGENT 174
#define SH_NODE_NORMAL_MAP 175
+#define SH_NODE_HAIR_INFO 176
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1
@@ -574,11 +792,10 @@ struct ShadeResult;
/* API */
-struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree, int use_tree_data);
-void ntreeShaderEndExecTree(struct bNodeTreeExec *exec, int use_tree_data);
-void ntreeShaderExecTree(struct bNodeTree *ntree, struct ShadeInput *shi, struct ShadeResult *shr);
+struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree);
+void ntreeShaderEndExecTree(struct bNodeTreeExec *exec);
+bool ntreeShaderExecTree(struct bNodeTree *ntree, struct ShadeInput *shi, struct ShadeResult *shr);
void ntreeShaderGetTexcoMode(struct bNodeTree *ntree, int osa, short *texco, int *mode);
-void nodeShaderSynchronizeID(struct bNode *node, int copyto);
/* switch material render loop */
extern void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *);
@@ -736,8 +953,6 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria
/* API */
struct CompBuf;
-struct bNodeTreeExec *ntreeCompositBeginExecTree(struct bNodeTree *ntree, int use_tree_data);
-void ntreeCompositEndExecTree(struct bNodeTreeExec *exec, int use_tree_data);
void ntreeCompositExecTree(struct bNodeTree *ntree, struct RenderData *rd, int rendering, int do_previews,
const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings);
void ntreeCompositTagRender(struct Scene *sce);
@@ -791,8 +1006,8 @@ struct TexResult;
int ntreeTexTagAnimated(struct bNodeTree *ntree);
void ntreeTexCheckCyclics(struct bNodeTree *ntree);
-struct bNodeTreeExec *ntreeTexBeginExecTree(struct bNodeTree *ntree, int use_tree_data);
-void ntreeTexEndExecTree(struct bNodeTreeExec *exec, int use_tree_data);
+struct bNodeTreeExec *ntreeTexBeginExecTree(struct bNodeTree *ntree);
+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);
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 65b3b194553..da5fa3e8195 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -49,6 +49,8 @@ struct bAction;
struct RenderData;
struct rctf;
struct MovieClip;
+struct Main;
+struct RigidBodyWorld;
void BKE_object_workob_clear(struct Object *workob);
void BKE_object_workob_calc_parent(struct Scene *scene, struct Object *ob, struct Object *workob);
@@ -66,7 +68,7 @@ void BKE_object_update_base_layer(struct Scene *scene, struct Object *ob);
void BKE_object_free(struct Object *ob);
void BKE_object_free_display(struct Object *ob);
-int BKE_object_support_modifier_type_check(struct Object *ob, int modifier_type);
+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_free_modifiers(struct Object *ob);
@@ -75,30 +77,34 @@ void BKE_object_make_proxy(struct Object *ob, struct Object *target, struct Obje
void BKE_object_copy_proxy_drivers(struct Object *ob, struct Object *target);
void BKE_object_unlink(struct Object *ob);
-int BKE_object_exists_check(struct Object *obtest);
-
-struct Object *BKE_object_add_only_object(int type, const char *name);
+bool BKE_object_exists_check(struct Object *obtest);
+bool BKE_object_is_in_editmode(struct Object *ob);
+
+struct Object *BKE_object_add_only_object(struct Main *bmain, int type, const char *name);
struct Object *BKE_object_add(struct Scene *scene, int type);
void *BKE_object_obdata_add_from_type(int type);
+struct Object *BKE_object_copy_ex(struct Main *bmain, struct Object *ob, int copy_caches);
struct Object *BKE_object_copy(struct Object *ob);
-struct Object *BKE_object_copy_with_caches(struct Object *ob);
void BKE_object_make_local(struct Object *ob);
-int BKE_object_is_libdata(struct Object *ob);
-int BKE_object_obdata_is_libdata(struct Object *ob);
+bool BKE_object_is_libdata(struct Object *ob);
+bool BKE_object_obdata_is_libdata(struct Object *ob);
void BKE_object_scale_to_mat3(struct Object *ob, float mat[3][3]);
-void BKE_object_rot_to_mat3(struct Object *ob, float mat[3][3]);
-void BKE_object_mat3_to_rot(struct Object *ob, float mat[3][3], short use_compat);
+void BKE_object_rot_to_mat3(struct Object *ob, float mat[3][3], bool use_drot);
+void BKE_object_mat3_to_rot(struct Object *ob, float mat[3][3], bool use_compat);
void BKE_object_to_mat3(struct Object *ob, float mat[3][3]);
void BKE_object_to_mat4(struct Object *ob, float mat[4][4]);
-void BKE_object_apply_mat4(struct Object *ob, float mat[4][4], const short use_compat, const short use_parent);
+void BKE_object_apply_mat4(struct Object *ob, float mat[4][4], const bool use_compat, const bool use_parent);
int BKE_object_pose_context_check(struct Object *ob);
struct Object *BKE_object_pose_armature_get(struct Object *ob);
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);
void BKE_object_where_is_calc_time(struct Scene *scene, struct Object *ob, float ctime);
+void BKE_object_where_is_calc_time_ex(struct Scene *scene, struct Object *ob, float ctime,
+ struct RigidBodyWorld *rbw);
void BKE_object_where_is_calc_simul(struct Scene *scene, struct Object *ob);
void BKE_object_where_is_calc_mat4(struct Scene *scene, struct Object *ob, float obmat[4][4]);
@@ -111,8 +117,8 @@ struct BoundBox *BKE_object_boundbox_get(struct Object *ob);
void BKE_object_dimensions_get(struct Object *ob, float vec[3]);
void BKE_object_dimensions_set(struct Object *ob, const float *value);
void BKE_object_boundbox_flag(struct Object *ob, int flag, int set);
-void BKE_object_minmax(struct Object *ob, float r_min[3], float r_max[3], const short use_hidden);
-int BKE_object_minmax_dupli(struct Scene *scene, struct Object *ob, float r_min[3], float r_max[3], const short use_hidden);
+void BKE_object_minmax(struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden);
+int BKE_object_minmax_dupli(struct Scene *scene, struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden);
/* sometimes min-max isn't enough, we need to loop over each point */
void BKE_object_foreach_display_point(struct Object *ob, float obmat[4][4],
@@ -122,7 +128,7 @@ void BKE_scene_foreach_display_point(struct Scene *scene,
const short flag,
void (*func_cb)(const float[3], void *), void *user_data);
-int BKE_object_parent_loop_check(const struct Object *parent, const struct Object *ob);
+bool BKE_object_parent_loop_check(const struct Object *parent, const struct Object *ob);
void *BKE_object_tfm_backup(struct Object *ob);
void BKE_object_tfm_restore(struct Object *ob, void *obtfm_pt);
@@ -144,6 +150,8 @@ void BKE_object_tfm_protected_restore(struct Object *ob,
const short protectflag);
void BKE_object_handle_update(struct Scene *scene, struct Object *ob);
+void BKE_object_handle_update_ex(struct Scene *scene, struct Object *ob,
+ struct RigidBodyWorld *rbw);
void BKE_object_sculpt_modifiers_changed(struct Object *ob);
int BKE_object_obdata_texspace_get(struct Object *ob, short **r_texflag, float **r_loc, float **r_size, float **r_rot);
@@ -152,9 +160,12 @@ int BKE_object_insert_ptcache(struct Object *ob);
// void object_delete_ptcache(struct Object *ob, int index);
struct KeyBlock *BKE_object_insert_shape_key(struct Scene *scene, struct Object *ob, const char *name, int from_mix);
+bool BKE_object_is_child_recursive(struct Object *ob_parent, struct Object *ob_child);
+bool BKE_object_is_animated(struct Scene *scene, struct Object *ob);
+
+/* return ModifierMode flag */
int BKE_object_is_modified(struct Scene *scene, struct Object *ob);
int BKE_object_is_deform_modified(struct Scene *scene, struct Object *ob);
-int BKE_object_is_animated(struct Scene *scene, struct Object *ob);
void BKE_object_relink(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h
index 603cb1f22a6..8fab44121de 100644
--- a/source/blender/blenkernel/BKE_packedFile.h
+++ b/source/blender/blenkernel/BKE_packedFile.h
@@ -35,6 +35,7 @@
#define RET_OK 0
#define RET_ERROR 1
+struct ID;
struct bSound;
struct Image;
struct Main;
@@ -48,6 +49,7 @@ struct PackedFile *newPackedFile(struct ReportList *reports, const char *filenam
struct PackedFile *newPackedFileMemory(void *mem, int memlen);
void packAll(struct Main *bmain, struct ReportList *reports);
+void packLibraries(struct Main *bmain, struct ReportList *reports);
/* unpack */
char *unpackFile(struct ReportList *reports, const char *abs_name, const char *local_name, struct PackedFile *pf, int how);
@@ -55,6 +57,7 @@ int unpackVFont(struct ReportList *reports, struct VFont *vfont, int how);
int unpackSound(struct Main *bmain, struct ReportList *reports, struct bSound *sound, int how);
int unpackImage(struct ReportList *reports, struct Image *ima, int how);
void unpackAll(struct Main *bmain, struct ReportList *reports, int how);
+int unpackLibraries(struct Main *bmain, struct ReportList *reports);
int writePackedFile(struct ReportList *reports, const char *filename, struct PackedFile *pf, int guimode);
@@ -70,5 +73,10 @@ int seekPackedFile(struct PackedFile *pf, int offset, int whence);
void rewindPackedFile(struct PackedFile *pf);
int readPackedFile(struct PackedFile *pf, void *data, int size);
+/* ID should be not NULL, return 1 if there's a packed file */
+bool BKE_pack_check(struct ID *id);
+/* ID should be not NULL, throws error when ID is Library */
+void BKE_unpack_id(struct Main *bmain, struct ID *id, struct ReportList *reports, int how);
+
#endif
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index c452c177143..35941d0a05a 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -33,6 +33,8 @@
*/
struct bContext;
+struct BMesh;
+struct BMFace;
struct Brush;
struct MDisps;
struct MeshElemMap;
@@ -45,12 +47,24 @@ struct Paint;
struct PBVH;
struct Scene;
struct StrokeCache;
+struct ImagePool;
+struct UnifiedPaintSettings;
extern const char PAINT_CURSOR_SCULPT[3];
extern const char PAINT_CURSOR_VERTEX_PAINT[3];
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
+} PaintMode;
+
void BKE_paint_init(struct Paint *p, const char col[3]);
void BKE_paint_free(struct Paint *p);
void BKE_paint_copy(struct Paint *src, struct Paint *tar);
@@ -58,6 +72,7 @@ void BKE_paint_copy(struct Paint *src, struct Paint *tar);
/* TODO, give these BKE_ prefix too */
struct Paint *paint_get_active(struct Scene *sce);
struct Paint *paint_get_active_from_context(const struct bContext *C);
+PaintMode paintmode_get_active_from_context(const struct bContext *C);
struct Brush *paint_brush(struct Paint *paint);
void paint_brush_set(struct Paint *paint, struct Brush *br);
@@ -71,11 +86,12 @@ int paint_vertsel_test(struct Object *ob);
int paint_is_face_hidden(const struct MFace *f, const struct MVert *mvert);
int paint_is_grid_face_hidden(const unsigned int *grid_hidden,
int gridsize, int x, int y);
+int paint_is_bmesh_face_hidden(struct BMFace *f);
/* paint masks */
float paint_grid_paint_mask(const struct GridPaintMask *gpm, unsigned level,
unsigned x, unsigned y);
-
+void paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups, const float mouse_pos[2]);
/* Session data (mode-specific) */
typedef struct SculptSession {
@@ -92,6 +108,12 @@ typedef struct SculptSession {
/* Mesh connectivity */
const struct MeshElemMap *pmap;
+ /* BMesh for dynamic topology sculpting */
+ struct BMesh *bm;
+ int bm_smooth_shading;
+ /* Undo/redo log for dynamic topology sculpting */
+ struct BMLog *bm_log;
+
/* PBVH acceleration structure */
struct PBVH *pbvh;
int show_diffuse_color;
@@ -107,6 +129,7 @@ typedef struct SculptSession {
/* Used to cache the render of the active texture */
unsigned int texcache_side, *texcache, texcache_actual;
+ struct ImagePool *tex_pool;
/* Layer brush persistence between strokes */
float (*layer_co)[3]; /* Copy of the mesh vertices' locations */
@@ -121,5 +144,6 @@ typedef struct SculptSession {
void free_sculptsession(struct Object *ob);
void free_sculptsession_deformMats(struct SculptSession *ss);
+void sculptsession_bm_to_me(struct Object *ob, int reorder);
#endif
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index bdaffef6818..6c207675cb1 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -20,7 +20,9 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Adaptive time step
+ * Classical SPH
+ * Copyright 2011-2012 AutoCRC
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -58,6 +60,7 @@ struct RNG;
struct SurfaceModifierData;
struct BVHTreeRay;
struct BVHTreeRayHit;
+struct EdgeHash;
#define PARTICLE_P ParticleData * pa; int p
#define LOOP_PARTICLES for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++)
@@ -85,6 +88,24 @@ typedef struct ParticleSimulationData {
float courant_num;
} ParticleSimulationData;
+typedef struct SPHData {
+ ParticleSystem *psys[10];
+ ParticleData *pa;
+ float mass;
+ struct EdgeHash *eh;
+ float *gravity;
+ float hfac;
+ /* Average distance to neighbours (other particles in the support domain),
+ * for calculating the Courant number (adaptive time step). */
+ int pass;
+ float element_size;
+ float flow[3];
+
+ /* Integrator callbacks. This allows different SPH implementations. */
+ void (*force_cb) (void *sphdata_v, ParticleKey *state, float *force, float *impulse);
+ void (*density_cb) (void *rangedata_v, int index, float squared_dist);
+} SPHData;
+
typedef struct ParticleTexture {
float ivel; /* used in reset */
float time, life, exist, size; /* used in init */
@@ -199,7 +220,10 @@ typedef struct ParticleCollision {
ParticleCollisionElement pce;
- float total_time, inv_timestep;
+ /* total_time is the amount of time in this subframe
+ * inv_total_time is the opposite
+ * inv_timestep is the inverse of the amount of time in this frame */
+ float total_time, inv_total_time, inv_timestep;
float radius;
float co1[3], co2[3];
@@ -283,6 +307,10 @@ 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, int vel);
int psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, int always);
+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]);
+
/* for anim.c */
void psys_get_dupli_texture(struct ParticleSystem *psys, struct ParticleSettings *part,
struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa,
diff --git a/source/blender/blenlib/BLI_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 59ecdb359c9..cdc8ef0bdf4 100644
--- a/source/blender/blenlib/BLI_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -18,22 +18,27 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __BLI_PBVH_H__
-#define __BLI_PBVH_H__
+#ifndef __BKE_PBVH_H__
+#define __BKE_PBVH_H__
-/** \file BLI_pbvh.h
- * \ingroup bli
+/** \file BKE_pbvh.h
+ * \ingroup bke
* \brief A BVH for high poly meshes.
*/
#include "BLI_bitmap.h"
+#include "BLI_ghash.h"
+#include "BLI_utildefines.h"
+
+/* Needed for BMesh functions used in the PBVH iterator macro */
+#include "bmesh.h"
struct CCGElem;
struct CCGKey;
struct CustomData;
struct DMFlagMat;
struct DMGridAdjacency;
-struct ListBase;
+struct GHash;
struct MFace;
struct MVert;
struct PBVH;
@@ -49,32 +54,35 @@ typedef struct {
/* Callbacks */
/* returns 1 if the search should continue from this node, 0 otherwise */
-typedef int (*BLI_pbvh_SearchCallback)(PBVHNode *node, void *data);
+typedef int (*BKE_pbvh_SearchCallback)(PBVHNode *node, void *data);
-typedef void (*BLI_pbvh_HitCallback)(PBVHNode *node, void *data);
-typedef void (*BLI_pbvh_HitOccludedCallback)(PBVHNode *node, void *data, float *tmin);
+typedef void (*BKE_pbvh_HitCallback)(PBVHNode *node, void *data);
+typedef void (*BKE_pbvh_HitOccludedCallback)(PBVHNode *node, void *data, float *tmin);
/* Building */
-PBVH *BLI_pbvh_new(void);
-void BLI_pbvh_build_mesh(PBVH *bvh, struct MFace *faces, struct MVert *verts,
+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 BLI_pbvh_build_grids(PBVH *bvh, struct CCGElem **grid_elems,
+void BKE_pbvh_build_grids(PBVH *bvh, struct CCGElem **grid_elems,
struct DMGridAdjacency *gridadj, int totgrid,
struct CCGKey *key, void **gridfaces, struct DMFlagMat *flagmats,
unsigned int **grid_hidden);
-void BLI_pbvh_free(PBVH *bvh);
+void BKE_pbvh_build_bmesh(PBVH *bvh, struct BMesh *bm, int smooth_shading,
+ struct BMLog *log);
+
+void BKE_pbvh_free(PBVH *bvh);
/* Hierarchical Search in the BVH, two methods:
* - for each hit calling a callback
* - gather nodes in an array (easy to multithread) */
-void BLI_pbvh_search_callback(PBVH *bvh,
- BLI_pbvh_SearchCallback scb, void *search_data,
- BLI_pbvh_HitCallback hcb, void *hit_data);
+void BKE_pbvh_search_callback(PBVH *bvh,
+ BKE_pbvh_SearchCallback scb, void *search_data,
+ BKE_pbvh_HitCallback hcb, void *hit_data);
-void BLI_pbvh_search_gather(PBVH *bvh,
- BLI_pbvh_SearchCallback scb, void *search_data,
+void BKE_pbvh_search_gather(PBVH *bvh,
+ BKE_pbvh_SearchCallback scb, void *search_data,
PBVHNode ***array, int *tot);
/* Raycast
@@ -82,33 +90,48 @@ void BLI_pbvh_search_gather(PBVH *bvh,
* it's up to the callback to find the primitive within the leaves that is
* hit first */
-void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data,
+void BKE_pbvh_raycast(PBVH *bvh, BKE_pbvh_HitOccludedCallback cb, void *data,
const float ray_start[3], const float ray_normal[3],
int original);
-int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3],
+int 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);
/* Drawing */
-void BLI_pbvh_node_draw(PBVHNode *node, void *data);
-void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
- int (*setMaterial)(int, void *attribs));
+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, void *attribs), int wireframe);
/* PBVH Access */
typedef enum {
PBVH_FACES,
PBVH_GRIDS,
+ PBVH_BMESH
} PBVHType;
-PBVHType BLI_pbvh_type(const PBVH *bvh);
+PBVHType BKE_pbvh_type(const PBVH *bvh);
+
+/* Get the PBVH root's bounding box */
+void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3]);
/* multires hidden data, only valid for type == PBVH_GRIDS */
-unsigned int **BLI_pbvh_grid_hidden(const PBVH *bvh);
+unsigned int **BKE_pbvh_grid_hidden(const PBVH *bvh);
/* multires level, only valid for type == PBVH_GRIDS */
-void BLI_pbvh_get_grid_key(const PBVH *pbvh, struct CCGKey *key);
+void BKE_pbvh_get_grid_key(const PBVH *pbvh, struct CCGKey *key);
+
+/* Only valid for type == PBVH_BMESH */
+BMesh *BKE_pbvh_get_bmesh(PBVH *pbvh);
+void BKE_pbvh_bmesh_detail_size_set(PBVH *pbvh, float detail_size);
+
+typedef enum {
+ PBVH_Subdivide = 1,
+ PBVH_Collapse = 2,
+} PBVHTopologyUpdateMode;
+int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
+ const float center[3], float radius);
/* Node Access */
@@ -122,45 +145,60 @@ typedef enum {
PBVH_UpdateRedraw = 32,
PBVH_RebuildDrawBuffers = 64,
- PBVH_FullyHidden = 128
+ PBVH_FullyHidden = 128,
+
+ PBVH_UpdateTopology = 256,
} PBVHNodeFlags;
-void BLI_pbvh_node_mark_update(PBVHNode *node);
-void BLI_pbvh_node_mark_rebuild_draw(PBVHNode *node);
-void BLI_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden);
+void BKE_pbvh_node_mark_update(PBVHNode *node);
+void BKE_pbvh_node_mark_rebuild_draw(PBVHNode *node);
+void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden);
+void BKE_pbvh_node_mark_topology_update(PBVHNode *node);
-void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node,
+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 BLI_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node,
+void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node,
int *uniquevert, int *totvert);
-void BLI_pbvh_node_get_verts(PBVH *bvh, PBVHNode *node,
+void BKE_pbvh_node_get_verts(PBVH *bvh, PBVHNode *node,
int **vert_indices, struct MVert **verts);
-void BLI_pbvh_node_get_BB(PBVHNode * node, float bb_min[3], float bb_max[3]);
-void BLI_pbvh_node_get_original_BB(PBVHNode * node, float bb_min[3], float bb_max[3]);
+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]);
-float BLI_pbvh_node_get_tmin(PBVHNode *node);
+float BKE_pbvh_node_get_tmin(PBVHNode *node);
/* test if AABB is at least partially inside the planes' volume */
-int BLI_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data);
+int BKE_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data);
/* test if AABB is at least partially outside the planes' volume */
-int BLI_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data);
+int BKE_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data);
+
+struct GHash *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node);
+struct GHash *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node);
+void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node);
+void BKE_pbvh_bmesh_after_stroke(PBVH *bvh);
/* Update Normals/Bounding Box/Draw Buffers/Redraw and clear flags */
-void BLI_pbvh_update(PBVH *bvh, int flags, float (*face_nors)[3]);
-void BLI_pbvh_redraw_BB(PBVH * bvh, float bb_min[3], float bb_max[3]);
-void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface);
-void BLI_pbvh_grids_update(PBVH *bvh, struct CCGElem **grid_elems,
+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 ***gridfaces, int *totface);
+void BKE_pbvh_grids_update(PBVH *bvh, struct CCGElem **grid_elems,
struct DMGridAdjacency *gridadj, void **gridfaces,
struct DMFlagMat *flagmats, unsigned int **grid_hidden);
-/* vertex deformer */
-float (*BLI_pbvh_get_vertCos(struct PBVH *pbvh))[3];
-void BLI_pbvh_apply_vertCos(struct PBVH *pbvh, float (*vertCos)[3]);
-int BLI_pbvh_isDeformed(struct PBVH *pbvh);
+/* Layer displacement */
+
+/* Get the node's displacement layer, creating it if necessary */
+float *BKE_pbvh_node_layer_disp_get(PBVH *pbvh, PBVHNode *node);
+/* If the node has a displacement layer, free it and set to null */
+void BKE_pbvh_node_layer_disp_free(PBVHNode *node);
+
+/* vertex deformer */
+float (*BKE_pbvh_get_vertCos(struct PBVH *pbvh))[3];
+void BKE_pbvh_apply_vertCos(struct PBVH *pbvh, float (*vertCos)[3]);
+int BKE_pbvh_isDeformed(struct PBVH *pbvh);
/* Vertex Iterator */
@@ -197,9 +235,15 @@ typedef struct PBVHVertexIter {
int *vert_indices;
float *vmask;
+ /* bmesh */
+ struct GHashIterator bm_unique_verts;
+ struct GHashIterator bm_other_verts;
+ struct CustomData *bm_vdata;
+
/* result: these are all computed in the macro, but we assume
* that compiler optimization's will skip the ones we don't use */
struct MVert *mvert;
+ struct BMVert *bm_vert;
float *co;
short *no;
float *fno;
@@ -213,7 +257,7 @@ typedef struct PBVHVertexIter {
void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
PBVHVertexIter *vi, int mode);
-#define BLI_pbvh_vertex_iter_begin(bvh, node, vi, mode) \
+#define BKE_pbvh_vertex_iter_begin(bvh, node, vi, mode) \
pbvh_vertex_iter_init(bvh, node, &vi, mode); \
\
for (vi.i = 0, vi.g = 0; vi.g < vi.totgrid; vi.g++) { \
@@ -241,7 +285,7 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
continue; \
} \
} \
- else { \
+ else if (vi.mverts) { \
vi.mvert = &vi.mverts[vi.vert_indices[vi.gx]]; \
if (mode == PBVH_ITER_UNIQUE && vi.mvert->flag & ME_HIDE) \
continue; \
@@ -250,21 +294,39 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
if (vi.vmask) \
vi.mask = &vi.vmask[vi.vert_indices[vi.gx]]; \
} \
-
-#define BLI_pbvh_vertex_iter_end \
+ else { \
+ if (BLI_ghashIterator_notDone(&vi.bm_unique_verts)) {\
+ vi.bm_vert = BLI_ghashIterator_getKey(&vi.bm_unique_verts); \
+ BLI_ghashIterator_step(&vi.bm_unique_verts); \
+ } \
+ else { \
+ vi.bm_vert = BLI_ghashIterator_getKey(&vi.bm_other_verts); \
+ BLI_ghashIterator_step(&vi.bm_other_verts); \
+ } \
+ if (mode == PBVH_ITER_UNIQUE && \
+ BM_elem_flag_test(vi.bm_vert, BM_ELEM_HIDDEN)) \
+ continue; \
+ vi.co = vi.bm_vert->co; \
+ vi.fno = vi.bm_vert->no; \
+ vi.mask = CustomData_bmesh_get(vi.bm_vdata, \
+ vi.bm_vert->head.data, \
+ CD_PAINT_MASK); \
+ }
+
+#define BKE_pbvh_vertex_iter_end \
} \
} \
}
-void BLI_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count);
-void BLI_pbvh_node_free_proxies(PBVHNode *node);
-PBVHProxyNode *BLI_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node);
-void BLI_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***nodes, int *totnode);
+void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count);
+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 BLI_pbvh_node_BB_reset(PBVHNode *node);
-//void BLI_pbvh_node_BB_expand(PBVHNode *node, float co[3]);
+//void BKE_pbvh_node_BB_reset(PBVHNode *node);
+//void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]);
void pbvh_show_diffuse_color_set(PBVH *bvh, int show_diffuse_color);
-#endif /* __BLI_PBVH_H__ */
+#endif /* __BKE_PBVH_H__ */
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index 77b35e1a25c..1cb50425c40 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -67,6 +67,7 @@
#define PTCACHE_TYPE_SMOKE_DOMAIN 3
#define PTCACHE_TYPE_SMOKE_HIGHRES 4
#define PTCACHE_TYPE_DYNAMICPAINT 5
+#define PTCACHE_TYPE_RIGIDBODY 6
/* high bits reserved for flags that need to be stored in file */
#define PTCACHE_TYPEFLAG_COMPRESS (1 << 16)
@@ -91,6 +92,7 @@ struct PointCache;
struct Scene;
struct SmokeModifierData;
struct SoftBody;
+struct RigidBodyWorld;
/* temp structure for read/write */
typedef struct PTCacheData {
@@ -260,6 +262,7 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct Par
void BKE_ptcache_id_from_cloth(PTCacheID *pid, struct Object *ob, struct ClothModifierData *clmd);
void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd);
void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, struct Object *ob, struct DynamicPaintSurface *surface);
+void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, struct Object *ob, struct RigidBodyWorld *rbw);
void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob, struct Scene *scene, int duplis);
@@ -294,10 +297,6 @@ int BKE_ptcache_read(PTCacheID *pid, float cfra);
/* Main cache writing call. */
int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra);
-/****************** Continue physics ***************/
-void BKE_ptcache_set_continue_physics(struct Main *bmain, struct Scene *scene, int enable);
-int BKE_ptcache_get_continue_physics(void);
-
/******************* Allocate & free ***************/
struct PointCache *BKE_ptcache_add(struct ListBase *ptcaches);
void BKE_ptcache_free_mem(struct ListBase *mem_cache);
diff --git a/source/blender/blenkernel/BKE_property.h b/source/blender/blenkernel/BKE_property.h
index e0eb8c04b60..99e60757f15 100644
--- a/source/blender/blenkernel/BKE_property.h
+++ b/source/blender/blenkernel/BKE_property.h
@@ -47,6 +47,7 @@ void BKE_bproperty_object_set(struct Object *ob, struct bProperty *
// int BKE_bproperty_cmp(struct bProperty *prop, const char *str);
void BKE_bproperty_set(struct bProperty *prop, const char *str);
void BKE_bproperty_add(struct bProperty *prop, const char *str);
-void BKE_bproperty_set_valstr(struct bProperty *prop, char *str);
+/* should really be called '_get_valstr()' or '_as_string()' */
+void BKE_bproperty_set_valstr(struct bProperty *prop, char str[MAX_PROPSTRING]);
#endif
diff --git a/source/blender/blenkernel/BKE_report.h b/source/blender/blenkernel/BKE_report.h
index 4d69a013101..4dc16f6266f 100644
--- a/source/blender/blenkernel/BKE_report.h
+++ b/source/blender/blenkernel/BKE_report.h
@@ -34,7 +34,10 @@
extern "C" {
#endif
+#include <stdio.h>
+
#include "DNA_windowmanager_types.h"
+#include "BLI_utildefines.h"
/* Reporting Information and Errors
*
@@ -72,7 +75,10 @@ void BKE_reports_print(ReportList *reports, ReportType level);
Report *BKE_reports_last_displayable(ReportList *reports);
int BKE_reports_contain(ReportList *reports, ReportType level);
-
+
+bool BKE_report_write_file_fp(FILE *fp, ReportList *reports, const char *header);
+bool BKE_report_write_file(const char *filepath, ReportList *reports, const char *header);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h
new file mode 100644
index 00000000000..bab961bcbd2
--- /dev/null
+++ b/source/blender/blenkernel/BKE_rigidbody.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): Joshua Leung, Sergej Reich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file BKE_rigidbody.h
+ * \ingroup blenkernel
+ * \brief API for Blender-side Rigid Body stuff
+ */
+
+
+#ifndef __BKE_RIGIDBODY_H__
+#define __BKE_RIGIDBODY_H__
+
+struct RigidBodyWorld;
+struct RigidBodyOb;
+
+struct Scene;
+struct Object;
+struct Group;
+
+/* -------------- */
+/* Memory Management */
+
+void BKE_rigidbody_free_world(struct RigidBodyWorld *rbw);
+void BKE_rigidbody_free_object(struct Object *ob);
+void BKE_rigidbody_free_constraint(struct Object *ob);
+
+/* ...... */
+
+struct RigidBodyOb *BKE_rigidbody_copy_object(struct Object *ob);
+struct RigidBodyCon *BKE_rigidbody_copy_constraint(struct Object *ob);
+void BKE_rigidbody_relink_constraint(struct RigidBodyCon *rbc);
+
+/* -------------- */
+/* Setup */
+
+/* create Blender-side settings data - physics objects not initialised yet */
+struct RigidBodyWorld *BKE_rigidbody_create_world(struct Scene *scene);
+struct RigidBodyOb *BKE_rigidbody_create_object(struct Scene *scene, struct Object *ob, short type);
+struct RigidBodyCon *BKE_rigidbody_create_constraint(struct Scene *scene, struct Object *ob, short type);
+
+/* 'validate' (i.e. make new or replace old) Physics-Engine objects */
+void BKE_rigidbody_validate_sim_world(struct Scene *scene, struct RigidBodyWorld *rbw, short rebuild);
+void BKE_rigidbody_validate_sim_object(struct RigidBodyWorld *rbw, struct Object *ob, short rebuild);
+void BKE_rigidbody_validate_sim_shape(struct Object *ob, short rebuild);
+void BKE_rigidbody_validate_sim_constraint(struct RigidBodyWorld *rbw, struct Object *ob, short rebuild);
+
+/* -------------- */
+/* Utilities */
+
+struct RigidBodyWorld *BKE_rigidbody_get_world(struct Scene *scene);
+void BKE_rigidbody_remove_object(struct Scene *scene, struct Object *ob);
+void BKE_rigidbody_remove_constraint(struct Scene *scene, struct Object *ob);
+
+/* -------------- */
+/* Utility Macros */
+
+/* get mass of Rigid Body Object to supply to RigidBody simulators */
+#define RBO_GET_MASS(rbo) \
+ ((rbo && ((rbo->type == RBO_TYPE_PASSIVE) || (rbo->flag & RBO_FLAG_KINEMATIC) || (rbo->flag & RBO_FLAG_DISABLED))) ? (0.0f) : (rbo->mass))
+/* get collision margin for Rigid Body Object, triangle mesh and cone shapes cannot embed margin, convex hull always uses custom margin */
+#define RBO_GET_MARGIN(rbo) \
+ ((rbo->flag & RBO_FLAG_USE_MARGIN || rbo->shape == RB_SHAPE_CONVEXH || rbo->shape == RB_SHAPE_TRIMESH || rbo->shape == RB_SHAPE_CONE) ? (rbo->margin) : (0.04f))
+
+/* -------------- */
+/* Simulation */
+
+void BKE_rigidbody_aftertrans_update(struct Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle);
+void BKE_rigidbody_sync_transforms(struct RigidBodyWorld *rbw, struct Object *ob, float ctime);
+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);
+
+#endif /* __BKE_RIGIDBODY_H__ */
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 9927c7a42ed..9bf0991272a 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -47,7 +47,7 @@ struct RenderData;
struct SceneRenderLayer;
struct Scene;
struct Text;
-struct Text;
+struct Main;
#define SCE_COPY_NEW 0
#define SCE_COPY_EMPTY 1
@@ -67,11 +67,12 @@ void free_avicodecdata(struct AviCodecData *acd);
void free_qtcodecdata(struct QuicktimeCodecData *acd);
void BKE_scene_free(struct Scene *sce);
-struct Scene *BKE_scene_add(const char *name);
+struct Scene *BKE_scene_add(struct Main *bmain, const char *name);
/* base functions */
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);
void BKE_scene_base_deselect_all(struct Scene *sce);
void BKE_scene_base_select(struct Scene *sce, struct Base *selbase);
int BKE_scene_base_iter_next(struct Scene **scene, int val, struct Base **base, struct Object **ob);
@@ -115,6 +116,7 @@ int BKE_scene_use_new_shading_nodes(struct Scene *scene);
void BKE_scene_disable_color_management(struct Scene *scene);
int BKE_scene_check_color_management_enabled(const struct Scene *scene);
+int BKE_scene_check_rigidbody_active(const struct Scene *scene);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 8aa08beec57..5407e22e49e 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -46,6 +46,7 @@ struct bContext;
struct bContextDataResult;
struct bScreen;
struct uiLayout;
+struct uiList;
struct uiMenuItem;
struct wmKeyConfig;
struct wmNotifier;
@@ -74,6 +75,8 @@ typedef struct SpaceType {
/* init is to cope with file load, screen (size) changes, check handlers */
void (*init)(struct wmWindowManager *, struct ScrArea *);
+ /* exit is called when the area is hidden or removed */
+ void (*exit)(struct wmWindowManager *, struct ScrArea *);
/* Listeners can react to bContext changes */
void (*listener)(struct ScrArea *, struct wmNotifier *);
@@ -115,6 +118,8 @@ typedef struct ARegionType {
/* add handlers, stuff you only do once or on area/region type/size changes */
void (*init)(struct wmWindowManager *, struct ARegion *);
+ /* exit is called when the region is hidden or removed */
+ void (*exit)(struct wmWindowManager *, struct ARegion *);
/* draw entirely, view changes should be handled here */
void (*draw)(const struct bContext *, struct ARegion *);
/* contextual changes should be handled here */
@@ -162,9 +167,10 @@ typedef struct ARegionType {
typedef struct PanelType {
struct PanelType *next, *prev;
- char idname[BKE_ST_MAXNAME]; /* unique name */
- char label[BKE_ST_MAXNAME]; /* for panel header */
- char context[BKE_ST_MAXNAME]; /* for buttons window */
+ char idname[BKE_ST_MAXNAME]; /* unique name */
+ char label[BKE_ST_MAXNAME]; /* for panel header */
+ char translation_context[BKE_ST_MAXNAME];
+ char context[BKE_ST_MAXNAME]; /* for buttons window */
int space_type;
int region_type;
@@ -181,6 +187,23 @@ typedef struct PanelType {
ExtensionRNA ext;
} PanelType;
+/* uilist types */
+
+/* draw an item in the uiList */
+typedef void (*uiListDrawItemFunc)(struct uiList *, struct bContext *, struct uiLayout *, struct PointerRNA *,
+ struct PointerRNA *, int, struct PointerRNA *, const char *, int);
+
+typedef struct uiListType {
+ struct uiListType *next, *prev;
+
+ char idname[BKE_ST_MAXNAME]; /* unique name */
+
+ uiListDrawItemFunc draw_item;
+
+ /* RNA integration */
+ ExtensionRNA ext;
+} uiListType;
+
/* header types */
typedef struct HeaderType {
@@ -209,7 +232,8 @@ typedef struct MenuType {
char idname[BKE_ST_MAXNAME]; /* unique name */
char label[BKE_ST_MAXNAME]; /* for button text */
- char *description;
+ char translation_context[BKE_ST_MAXNAME];
+ char *description;
/* verify if the menu should draw or not */
int (*poll)(const struct bContext *, struct MenuType *);
@@ -243,6 +267,7 @@ void BKE_area_region_free(struct SpaceType *st, struct ARegion *ar);
void BKE_screen_area_free(struct ScrArea *sa);
struct ARegion *BKE_area_find_region_type(struct ScrArea *sa, int type);
+struct ARegion *BKE_area_find_region_active_win(struct ScrArea *sa);
struct ScrArea *BKE_screen_find_big_area(struct bScreen *sc, const int spacetype, const short min);
void BKE_screen_view3d_sync(struct View3D *v3d, struct Scene *scene);
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 88294cb30b6..9586df6d119 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -36,6 +36,7 @@ struct Editing;
struct ImBuf;
struct Main;
struct Mask;
+struct MovieClip;
struct Scene;
struct Sequence;
struct SequenceModifierData;
@@ -191,7 +192,7 @@ void BKE_sequencer_pixel_from_sequencer_space_v4(struct Scene *scene, float pixe
/* **********************************************************************
* sequencer scene functions
* ********************************************************************** */
-struct Editing *BKE_sequencer_editing_get(struct Scene *scene, int alloc);
+struct Editing *BKE_sequencer_editing_get(struct Scene *scene, bool alloc);
struct Editing *BKE_sequencer_editing_ensure(struct Scene *scene);
void BKE_sequencer_editing_free(struct Scene *scene);
@@ -288,10 +289,10 @@ int BKE_sequence_tx_get_final_right(struct Sequence *seq, int metaclip);
void BKE_sequence_tx_set_final_left(struct Sequence *seq, int val);
void BKE_sequence_tx_set_final_right(struct Sequence *seq, int val);
void BKE_sequence_tx_handle_xlimits(struct Sequence *seq, int leftflag, int rightflag);
-int BKE_sequence_tx_test(struct Sequence *seq);
-int BKE_sequence_single_check(struct Sequence *seq);
+bool BKE_sequence_tx_test(struct Sequence *seq);
+bool BKE_sequence_single_check(struct Sequence *seq);
void BKE_sequence_single_fix(struct Sequence *seq);
-int BKE_sequence_test_overlap(struct ListBase *seqbasep, struct Sequence *test);
+bool BKE_sequence_test_overlap(struct ListBase *seqbasep, struct Sequence *test);
void BKE_sequence_translate(struct Scene *scene, struct Sequence *seq, int delta);
void BKE_sequence_sound_init(struct Scene *scene, struct Sequence *seq);
struct Sequence *BKE_sequencer_foreground_frame_get(struct Scene *scene, int frame);
@@ -300,14 +301,14 @@ 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);
-int BKE_sequence_base_shuffle(struct ListBase *seqbasep, struct Sequence *test, struct Scene *evil_scene);
-int BKE_sequence_base_shuffle_time(ListBase *seqbasep, struct Scene *evil_scene);
-int BKE_sequence_base_isolated_sel_check(struct ListBase *seqbase);
+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);
void BKE_sequencer_free_imbuf(struct Scene *scene, struct ListBase *seqbasep, int 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);
-int BKE_sequence_check_depend(struct Sequence *seq, struct Sequence *cur);
+bool BKE_sequence_check_depend(struct Sequence *seq, struct Sequence *cur);
void BKE_sequence_invalidate_cache(struct Scene *scene, struct Sequence *seq);
void BKE_sequence_invalidate_dependent(struct Scene *scene, struct Sequence *seq);
void BKE_sequence_invalidate_cache_for_modifier(struct Scene *scene, struct Sequence *seq);
@@ -319,9 +320,11 @@ void BKE_sequencer_update_sound(struct Scene *scene, struct bSound *sound);
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);
-int BKE_sequence_is_valid_check(struct Sequence *seq);
+bool BKE_sequence_is_valid_check(struct Sequence *seq);
void BKE_sequencer_clear_scene_in_allseqs(struct Main *bmain, struct Scene *sce);
+void BKE_sequencer_clear_movieclip_in_clipboard(struct MovieClip *clip);
+void BKE_sequencer_clear_mask_in_clipboard(struct Mask *mask);
struct Sequence *BKE_sequence_get_by_name(struct ListBase *seqbase, const char *name, int recursive);
@@ -356,6 +359,8 @@ typedef struct SeqLoadInfo {
typedef struct Sequence *(*SeqLoadFunc)(struct bContext *, ListBase *, struct SeqLoadInfo *);
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);
struct Sequence *BKE_sequencer_add_image_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);
@@ -363,7 +368,7 @@ struct Sequence *BKE_sequencer_add_sound_strip(struct bContext *C, ListBase *seq
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, int, int, char[256]);
+typedef struct ImBuf *(*SequencerDrawView)(struct Scene *, struct Object *, int, int, unsigned int, int, bool, bool, int, char[256]);
extern SequencerDrawView sequencer_view3d_cb;
/* copy/paste */
@@ -414,4 +419,4 @@ int BKE_sequence_supports_modifiers(struct Sequence *seq);
struct ImBuf *BKE_sequencer_render_mask_input(SeqRenderData context, int mask_input_type, struct Sequence *mask_sequence, struct Mask *mask_id, int cfra, int make_float);
void BKE_sequencer_color_balance_apply(struct StripColorBalance *cb, struct ImBuf *ibuf, float mul, short make_float, struct ImBuf *mask_input);
-#endif /* __BKE_SEQUENCER_H__ */
+#endif /* __BKE_SEQUENCER_H__ */
diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h
index d1332ba937e..61d82e6c604 100644
--- a/source/blender/blenkernel/BKE_shrinkwrap.h
+++ b/source/blender/blenkernel/BKE_shrinkwrap.h
@@ -121,7 +121,8 @@ typedef struct ShrinkwrapCalcData {
} ShrinkwrapCalcData;
-void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts);
+void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object *ob, struct DerivedMesh *dm,
+ float (*vertexCos)[3], int numVerts);
/*
* This function casts a ray in the given BVHTree.. but it takes into consideration the space_transform, that is:
@@ -130,9 +131,12 @@ void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object
* then the input (vert, dir, BVHTreeRayHit) must be defined in ob1 coordinates space
* and the BVHTree must be built in ob2 coordinate space.
*
- * Thus it provides an easy way to cast the same ray across several trees (where each tree was built on its own coords space)
+ * Thus it provides an easy way to cast the same ray across several trees
+ * (where each tree was built on its own coords space)
*/
-int normal_projection_project_vertex(char options, const float *vert, const float *dir, const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata);
+int normal_projection_project_vertex(char options, const float vert[3], const float dir[3],
+ const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit,
+ BVHTree_RayCastCallback callback, void *userdata);
/*
* NULL initializers to local data
@@ -142,6 +146,4 @@ int normal_projection_project_vertex(char options, const float *vert, const floa
#define NULL_BVHTreeRayHit {NULL, }
#define NULL_BVHTreeNearest {0, }
-
-#endif
-
+#endif /* __BKE_SHRINKWRAP_H__ */
diff --git a/source/blender/blenkernel/BKE_speaker.h b/source/blender/blenkernel/BKE_speaker.h
index 52c177fce57..e2f0fa50a86 100644
--- a/source/blender/blenkernel/BKE_speaker.h
+++ b/source/blender/blenkernel/BKE_speaker.h
@@ -33,7 +33,9 @@
* \brief General operations for speakers.
*/
-void *BKE_speaker_add(const char *name);
+struct Main;
+
+void *BKE_speaker_add(struct Main *bmain, const char *name);
struct Speaker *BKE_speaker_copy(struct Speaker *spk);
void BKE_speaker_make_local(struct Speaker *spk);
void BKE_speaker_free(struct Speaker *spk);
diff --git a/source/blender/blenkernel/BKE_suggestions.h b/source/blender/blenkernel/BKE_suggestions.h
index 9b61d9141fb..c36a2d61968 100644
--- a/source/blender/blenkernel/BKE_suggestions.h
+++ b/source/blender/blenkernel/BKE_suggestions.h
@@ -75,7 +75,7 @@ short texttool_text_is_active(Text *text);
/* Suggestions */
void texttool_suggest_add(const char *name, char type);
-void texttool_suggest_prefix(const char *prefix);
+void texttool_suggest_prefix(const char *prefix, const int prefix_len);
void texttool_suggest_clear(void);
SuggItem *texttool_suggest_first(void);
SuggItem *texttool_suggest_last(void);
diff --git a/source/blender/blenkernel/BKE_tessmesh.h b/source/blender/blenkernel/BKE_tessmesh.h
index dea5e726671..b3e6ab37273 100644
--- a/source/blender/blenkernel/BKE_tessmesh.h
+++ b/source/blender/blenkernel/BKE_tessmesh.h
@@ -80,12 +80,11 @@ typedef struct BMEditMesh {
/*temp variables for x-mirror editing*/
int mirror_cdlayer; /* -1 is invalid */
- int mirr_free_arrays;
} BMEditMesh;
-void BMEdit_RecalcTessellation(BMEditMesh *tm);
-BMEditMesh *BMEdit_Create(BMesh *bm, int do_tessellate);
-BMEditMesh *BMEdit_Copy(BMEditMesh *tm);
+void BMEdit_RecalcTessellation(BMEditMesh *em);
+BMEditMesh *BMEdit_Create(BMesh *bm, const bool do_tessellate);
+BMEditMesh *BMEdit_Copy(BMEditMesh *em);
BMEditMesh *BMEdit_FromObject(struct Object *ob);
void BMEdit_Free(BMEditMesh *em);
void BMEdit_UpdateLinkedCustomData(BMEditMesh *em);
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index accac8694a9..5e81fb85d76 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -45,16 +45,16 @@ 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 (const char *name);
+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);
-struct Text* BKE_text_load (const char *file, const char *relpath);
-struct Text* BKE_text_copy (struct Text *ta);
+struct Text *BKE_text_load (struct Main *bmain, const char *file, const char *relpath);
+struct Text *BKE_text_copy (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);
-char* txt_to_buf (struct Text *text);
+char *txt_to_buf (struct Text *text);
void txt_clean_text (struct Text *text);
void txt_order_cursors (struct Text *text);
int txt_find_string (struct Text *text, const char *findstr, int wrap, int match_case);
@@ -62,12 +62,14 @@ int txt_has_sel (struct Text *text);
int txt_get_span (struct TextLine *from, struct TextLine *to);
int txt_utf8_offset_to_index(const char *str, int offset);
int txt_utf8_index_to_offset(const char *str, int index);
+int txt_utf8_offset_to_column(const char *str, int offset);
+int txt_utf8_column_to_offset(const char *str, int column);
void txt_move_up (struct Text *text, short sel);
void txt_move_down (struct Text *text, short sel);
void txt_move_left (struct Text *text, short sel);
void txt_move_right (struct Text *text, short sel);
-void txt_jump_left (struct Text *text, short sel);
-void txt_jump_right (struct Text *text, short sel);
+void txt_jump_left (struct Text *text, bool sel, bool use_init_step);
+void txt_jump_right (struct Text *text, bool sel, bool use_init_step);
void txt_move_bof (struct Text *text, short sel);
void txt_move_eof (struct Text *text, short sel);
void txt_move_bol (struct Text *text, short sel);
@@ -80,7 +82,7 @@ void txt_delete_word (struct Text *text);
void txt_delete_selected (struct Text *text);
void txt_sel_all (struct Text *text);
void txt_sel_line (struct Text *text);
-char* txt_sel_to_buf (struct Text *text);
+char *txt_sel_to_buf (struct Text *text);
void txt_insert_buf (struct Text *text, const char *in_buffer);
void txt_print_undo (struct Text *text);
void txt_undo_add_op (struct Text *text, int op);
@@ -98,14 +100,20 @@ void txt_indent (struct Text *text);
void txt_uncomment (struct Text *text);
void txt_move_lines (struct Text *text, const int direction);
void txt_duplicate_line (struct Text *text);
-int setcurr_tab_spaces (struct Text *text, int space);
+int txt_setcurr_tab_spaces(struct Text *text, int space);
/* utility functions, could be moved somewhere more generic but are python/text related */
int text_check_bracket(const char ch);
int text_check_delim(const char ch);
int text_check_digit(const char ch);
int text_check_identifier(const char ch);
+int text_check_identifier_nodigit(const char ch);
int text_check_whitespace(const char ch);
+int text_find_identifier_start(const char *str, int i);
+
+/* defined in bpy_interface.c */
+extern int text_check_identifier_unicode(const unsigned int ch);
+extern int text_check_identifier_nodigit_unicode(const unsigned int ch);
enum {
TXT_MOVE_LINE_UP = -1,
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
index 78fdd26c9e0..621fc13af67 100644
--- a/source/blender/blenkernel/BKE_texture.h
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -44,6 +44,7 @@ struct EnvMap;
struct HaloRen;
struct Lamp;
struct LampRen;
+struct Main;
struct Material;
struct MTex;
struct OceanTex;
@@ -60,8 +61,8 @@ struct World;
void BKE_texture_free(struct Tex *t);
-void init_colorband(struct ColorBand *coba, int rangetype);
-struct ColorBand *add_colorband(int rangetype);
+void init_colorband(struct ColorBand *coba, bool rangetype);
+struct ColorBand *add_colorband(bool rangetype);
int do_colorband(const struct ColorBand *coba, float in, float out[4]);
void colorband_table_RGBA(struct ColorBand *coba, float **array, int *size);
struct CBData *colorband_element_add(struct ColorBand *coba, float position);
@@ -69,7 +70,7 @@ 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(const char *name);
+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);
diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h
index eb7004b1ced..c8ad708f832 100644
--- a/source/blender/blenkernel/BKE_tracking.h
+++ b/source/blender/blenkernel/BKE_tracking.h
@@ -46,6 +46,7 @@ struct MovieDistortion;
struct Camera;
struct Object;
struct Scene;
+struct rcti;
/* **** Common functions **** */
@@ -143,6 +144,7 @@ void BKE_tracking_camera_get_reconstructed_interpolate(struct MovieTracking *tra
struct MovieDistortion *BKE_tracking_distortion_new(void);
void BKE_tracking_distortion_update(struct MovieDistortion *distortion, struct MovieTracking *tracking,
int calibration_width, int calibration_height);
+void BKE_tracking_distortion_set_threads(struct MovieDistortion *distortion, int threads);
struct MovieDistortion *BKE_tracking_distortion_copy(struct MovieDistortion *distortion);
struct ImBuf *BKE_tracking_distortion_exec(struct MovieDistortion *distortion, struct MovieTracking *tracking,
struct ImBuf *ibuf, int width, int height, float overscan, int undistort);
@@ -156,10 +158,12 @@ struct ImBuf *BKE_tracking_undistort_frame(struct MovieTracking *tracking, struc
struct ImBuf *BKE_tracking_distort_frame(struct MovieTracking *tracking, struct ImBuf *ibuf,
int calibration_width, int calibration_height, float overscan);
+void BKE_tracking_max_undistortion_delta_across_bound(struct MovieTracking *tracking, struct rcti *rect, float delta[2]);
+
/* **** Image sampling **** */
struct ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height,
struct ImBuf *struct_ibuf, struct MovieTrackingTrack *track,
- struct MovieTrackingMarker *marker, int use_mask,
+ struct MovieTrackingMarker *marker, int from_anchor, int use_mask,
int num_samples_x, int num_samples_y, float pos[2]);
struct ImBuf *BKE_tracking_get_pattern_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track,
struct MovieTrackingMarker *marker, int anchored, int disable_channels);
diff --git a/source/blender/blenkernel/BKE_unit.h b/source/blender/blenkernel/BKE_unit.h
index 86f46820c97..6b5ce5e1d21 100644
--- a/source/blender/blenkernel/BKE_unit.h
+++ b/source/blender/blenkernel/BKE_unit.h
@@ -70,7 +70,8 @@ double bUnit_GetScaler(void *usys_pt, int index);
#define B_UNIT_TIME 6
#define B_UNIT_VELOCITY 7
#define B_UNIT_ACCELERATION 8
-#define B_UNIT_TYPE_TOT 9
+#define B_UNIT_CAMERA 9
+#define B_UNIT_TYPE_TOT 10
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_world.h b/source/blender/blenkernel/BKE_world.h
index 7a23bff0184..6bb35e46539 100644
--- a/source/blender/blenkernel/BKE_world.h
+++ b/source/blender/blenkernel/BKE_world.h
@@ -33,11 +33,12 @@
* \author nzc
*/
+struct Main;
struct World;
void BKE_world_free(struct World *sc);
void BKE_world_free_ex(struct World *sc, int do_id_user);
-struct World *add_world(const char *name);
+struct World *add_world(struct Main *bmian, const char *name);
struct World *BKE_world_copy(struct World *wrld);
struct World *localize_world(struct World *wrld);
void BKE_world_make_local(struct World *wrld);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 2da9b402d59..57e99481604 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -58,6 +58,7 @@ set(SRC
intern/CCGSubSurf.c
intern/DerivedMesh.c
intern/action.c
+ intern/addon.c
intern/anim.c
intern/anim_sys.c
intern/armature.c
@@ -65,6 +66,7 @@ set(SRC
intern/bmfont.c
intern/boids.c
intern/booleanops_mesh.c
+ intern/bpath.c
intern/brush.c
intern/bullet.c
intern/bvhutils.c
@@ -88,6 +90,7 @@ set(SRC
intern/fluidsim.c
intern/fmodifier.c
intern/font.c
+ intern/freestyle.c
intern/gpencil.c
intern/group.c
intern/icons.c
@@ -101,9 +104,10 @@ set(SRC
intern/lamp.c
intern/lattice.c
intern/library.c
+ intern/linestyle.c
+ intern/mask.c
intern/mask_evaluate.c
intern/mask_rasterize.c
- intern/mask.c
intern/material.c
intern/mball.c
intern/mesh.c
@@ -121,9 +125,12 @@ set(SRC
intern/paint.c
intern/particle.c
intern/particle_system.c
+ intern/pbvh.c
+ intern/pbvh_bmesh.c
intern/pointcache.c
intern/property.c
intern/report.c
+ intern/rigidbody.c
intern/sca.c
intern/scene.c
intern/screen.c
@@ -150,6 +157,7 @@ set(SRC
BKE_DerivedMesh.h
BKE_action.h
+ BKE_addon.h
BKE_anim.h
BKE_animsys.h
BKE_armature.h
@@ -159,6 +167,7 @@ set(SRC
BKE_bmfont_types.h
BKE_boids.h
BKE_booleanops_mesh.h
+ BKE_bpath.h
BKE_brush.h
BKE_bullet.h
BKE_bvhutils.h
@@ -181,6 +190,7 @@ set(SRC
BKE_fcurve.h
BKE_fluidsim.h
BKE_font.h
+ BKE_freestyle.h
BKE_global.h
BKE_gpencil.h
BKE_group.h
@@ -193,6 +203,7 @@ set(SRC
BKE_lamp.h
BKE_lattice.h
BKE_library.h
+ BKE_linestyle.h
BKE_main.h
BKE_mask.h
BKE_material.h
@@ -209,9 +220,11 @@ set(SRC
BKE_packedFile.h
BKE_paint.h
BKE_particle.h
+ BKE_pbvh.h
BKE_pointcache.h
BKE_property.h
BKE_report.h
+ BKE_rigidbody.h
BKE_sca.h
BKE_scene.h
BKE_screen.h
@@ -234,9 +247,11 @@ set(SRC
BKE_world.h
BKE_writeavi.h
BKE_writeframeserver.h
+
depsgraph_private.h
nla_private.h
intern/CCGSubSurf.h
+ intern/pbvh_intern.h
)
add_definitions(-DGLEW_STATIC)
@@ -250,9 +265,12 @@ endif()
if(WITH_BULLET)
list(APPEND INC_SYS
- ../../../extern/bullet2/src
+ ${BULLET_INCLUDE_DIRS}
)
- add_definitions(-DUSE_BULLET)
+ list(APPEND INC
+ ../../../intern/rigidbody
+ )
+ add_definitions(-DWITH_BULLET)
endif()
#if(WITH_MOD_CLOTH_ELTOPO)
@@ -410,6 +428,10 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_FREESTYLE)
+ add_definitions(-DWITH_FREESTYLE)
+endif()
+
## Warnings as errors, this is too strict!
#if(MSVC)
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index 22be2f78ea7..c21cd168874 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
import os
@@ -15,6 +41,7 @@ incs += ' ../render/extern/include ../makesrna'
incs += ' ../imbuf ../ikplugin ../avi #/intern/elbeem/extern ../nodes ../modifiers'
incs += ' #/intern/iksolver/extern ../blenloader'
incs += ' #/extern/bullet2/src'
+incs += ' #/intern/rigidbody'
incs += ' #/intern/opennl/extern #/intern/bsp/extern'
incs += ' ../gpu #/extern/glew/include'
incs += ' ../bmesh'
@@ -84,7 +111,7 @@ if env['WITH_BF_QUICKTIME']:
incs += ' ' + env['BF_QUICKTIME_INC']
if env['WITH_BF_BULLET']:
- defs.append('USE_BULLET')
+ defs.append('WITH_BULLET')
if env['OURPLATFORM'] == 'darwin':
if env['WITH_BF_OPENMP']:
@@ -121,6 +148,9 @@ if env['WITH_BF_FFTW3']:
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
+if env['WITH_BF_FREESTYLE']:
+ defs.append('WITH_FREESTYLE')
+
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
diff --git a/source/blender/blenkernel/depsgraph_private.h b/source/blender/blenkernel/depsgraph_private.h
index 12c111f5f16..14e7d220449 100644
--- a/source/blender/blenkernel/depsgraph_private.h
+++ b/source/blender/blenkernel/depsgraph_private.h
@@ -34,9 +34,27 @@
#include "DNA_constraint_types.h"
#include "BKE_constraint.h"
+/* **** DAG relation types *** */
+
+/* scene link to object */
+#define DAG_RL_SCENE (1 << 0)
+/* object link to data */
+#define DAG_RL_DATA (1 << 1)
+
+/* object changes object (parent, track, constraints) */
+#define DAG_RL_OB_OB (1 << 2)
+/* object changes obdata (hooks, constraints) */
+#define DAG_RL_OB_DATA (1 << 3)
+/* data changes object (vertex parent) */
+#define DAG_RL_DATA_OB (1 << 4)
+/* data changes data (deformers) */
+#define DAG_RL_DATA_DATA (1 << 5)
+
+#define DAG_NO_RELATION (1 << 6)
+
+#define DAG_RL_ALL_BUT_DATA (DAG_RL_SCENE | DAG_RL_OB_OB | DAG_RL_OB_DATA | DAG_RL_DATA_OB | DAG_RL_DATA_DATA)
+#define DAG_RL_ALL (DAG_RL_ALL_BUT_DATA | DAG_RL_DATA)
-#define DEPSX 5.0f
-#define DEPSY 1.8f
#define DAGQUEUEALLOC 50
@@ -46,8 +64,6 @@ enum {
DAG_BLACK = 2
};
-
-
typedef struct DagAdjList {
struct DagNode *node;
short type;
@@ -108,24 +124,24 @@ void push_queue(DagNodeQueue *queue, DagNode *node);
void push_stack(DagNodeQueue *queue, DagNode *node);
DagNode *pop_queue(DagNodeQueue *queue);
DagNode *get_top_node_queue(DagNodeQueue *queue);
+int queue_count(DagNodeQueue *queue);
+void queue_delete(DagNodeQueue *queue);
// Dag management
-DagForest *getMainDag(void);
-void setMainDag(DagForest *dag);
DagForest *dag_init(void);
+DagForest *build_dag(struct Main *bmain, struct Scene *sce, short mask);
+void free_forest(struct DagForest *Dag);
DagNode *dag_find_node(DagForest *forest, void *fob);
DagNode *dag_add_node(DagForest *forest, void *fob);
DagNode *dag_get_node(DagForest *forest, void *fob);
DagNode *dag_get_sub_node(DagForest *forest, void *fob);
void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name);
-void graph_bfs(void);
-
DagNodeQueue *graph_dfs(void);
void set_node_xy(DagNode *node, float x, float y);
void graph_print_queue(DagNodeQueue *nqueue);
void graph_print_queue_dist(DagNodeQueue *nqueue);
-void graph_print_adj_list(void);
+void graph_print_adj_list(DagForest *dag);
#endif /* __DEPSGRAPH_PRIVATE_H__ */
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index cc20470b4d5..e58d484b0c0 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -16,12 +16,6 @@
#include "BLI_utildefines.h" /* for BLI_assert */
-#ifdef _MSC_VER
-# define CCG_INLINE __inline
-#else
-# define CCG_INLINE inline
-#endif
-
/* used for normalize_v3 in BLI_math_vector
* float.h's FLT_EPSILON causes trouble with subsurf normals - campbell */
#define EPSILON (1.0e-35f)
@@ -236,7 +230,7 @@ int ccg_gridsize(int level)
{
BLI_assert(level > 0);
BLI_assert(level <= 31);
-
+
return (1 << (level - 1)) + 1;
}
@@ -305,7 +299,7 @@ struct CCGVert {
// byte *userData;
};
-static CCG_INLINE byte *VERT_getLevelData(CCGVert *v)
+BLI_INLINE byte *VERT_getLevelData(CCGVert *v)
{
return (byte *)(&(v)[1]);
}
@@ -324,7 +318,7 @@ struct CCGEdge {
// byte *userData;
};
-static CCG_INLINE byte *EDGE_getLevelData(CCGEdge *e)
+BLI_INLINE byte *EDGE_getLevelData(CCGEdge *e)
{
return (byte *)(&(e)[1]);
}
@@ -342,17 +336,17 @@ struct CCGFace {
// byte *userData;
};
-static CCG_INLINE CCGVert **FACE_getVerts(CCGFace *f)
+BLI_INLINE CCGVert **FACE_getVerts(CCGFace *f)
{
return (CCGVert **)(&f[1]);
}
-static CCG_INLINE CCGEdge **FACE_getEdges(CCGFace *f)
+BLI_INLINE CCGEdge **FACE_getEdges(CCGFace *f)
{
return (CCGEdge **)(&(FACE_getVerts(f)[f->numVerts]));
}
-static CCG_INLINE byte *FACE_getCenterData(CCGFace *f)
+BLI_INLINE byte *FACE_getCenterData(CCGFace *f)
{
return (byte *)(&(FACE_getEdges(f)[(f)->numVerts]));
}
@@ -698,28 +692,28 @@ static CCGFace *_face_new(CCGFaceHDL fHDL, CCGVert **verts, CCGEdge **edges, int
return f;
}
-static CCG_INLINE void *_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize)
+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];
}
-static CCG_INLINE void *_face_getIENo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize, int normalDataOffset)
+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];
}
-static CCG_INLINE void *_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize)
+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)];
}
-static CCG_INLINE float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset)
+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);
@@ -742,7 +736,7 @@ static int _face_getEdgeIndex(CCGFace *f, CCGEdge *e)
return i;
return -1;
}
-static CCG_INLINE void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int f_ed_idx, int lvl, int eX, int eY, int levels, int dataSize)
+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);
@@ -1422,18 +1416,25 @@ static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss,
float no[3];
for (S = 0; S < f->numVerts; S++) {
- for (y = 0; y < gridSize - 1; y++)
- for (x = 0; x < gridSize - 1; x++)
+ 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++)
+ 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++)
+ }
+ }
+ 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)
+ }
+ }
+ 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++) {
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index d09bea0f662..b2a5a3a5593 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -47,10 +47,10 @@
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_array.h"
-#include "BLI_pbvh.h"
#include "BLI_utildefines.h"
#include "BLI_linklist.h"
+#include "BKE_pbvh.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_displist.h"
#include "BKE_key.h"
@@ -169,7 +169,7 @@ static MPoly *dm_getPolyArray(DerivedMesh *dm)
static MVert *dm_dupVertArray(DerivedMesh *dm)
{
- MVert *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumVerts(dm),
+ MVert *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumVerts(dm),
"dm_dupVertArray tmp");
if (tmp) dm->copyVertArray(dm, tmp);
@@ -179,7 +179,7 @@ static MVert *dm_dupVertArray(DerivedMesh *dm)
static MEdge *dm_dupEdgeArray(DerivedMesh *dm)
{
- MEdge *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumEdges(dm),
+ MEdge *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumEdges(dm),
"dm_dupEdgeArray tmp");
if (tmp) dm->copyEdgeArray(dm, tmp);
@@ -189,7 +189,7 @@ static MEdge *dm_dupEdgeArray(DerivedMesh *dm)
static MFace *dm_dupFaceArray(DerivedMesh *dm)
{
- MFace *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumTessFaces(dm),
+ MFace *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumTessFaces(dm),
"dm_dupFaceArray tmp");
if (tmp) dm->copyTessFaceArray(dm, tmp);
@@ -199,7 +199,7 @@ static MFace *dm_dupFaceArray(DerivedMesh *dm)
static MLoop *dm_dupLoopArray(DerivedMesh *dm)
{
- MLoop *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumLoops(dm),
+ MLoop *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumLoops(dm),
"dm_dupLoopArray tmp");
if (tmp) dm->copyLoopArray(dm, tmp);
@@ -209,7 +209,7 @@ static MLoop *dm_dupLoopArray(DerivedMesh *dm)
static MPoly *dm_dupPolyArray(DerivedMesh *dm)
{
- MPoly *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumPolys(dm),
+ MPoly *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumPolys(dm),
"dm_dupPolyArray tmp");
if (tmp) dm->copyPolyArray(dm, tmp);
@@ -313,6 +313,8 @@ void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type
CustomData_copy(&source->polyData, &dm->polyData, CD_MASK_DERIVEDMESH,
CD_CALLOC, numPolys);
+ dm->cd_flag = source->cd_flag;
+
dm->type = type;
dm->numVertData = numVerts;
dm->numEdgeData = numEdges;
@@ -483,11 +485,13 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob)
totedge = tmp.totedge = dm->getNumEdges(dm);
totloop = tmp.totloop = dm->getNumLoops(dm);
totpoly = tmp.totpoly = dm->getNumPolys(dm);
+ tmp.totface = 0;
CustomData_copy(&dm->vertData, &tmp.vdata, CD_MASK_MESH, CD_DUPLICATE, totvert);
CustomData_copy(&dm->edgeData, &tmp.edata, CD_MASK_MESH, CD_DUPLICATE, totedge);
CustomData_copy(&dm->loopData, &tmp.ldata, CD_MASK_MESH, CD_DUPLICATE, totloop);
CustomData_copy(&dm->polyData, &tmp.pdata, CD_MASK_MESH, CD_DUPLICATE, totpoly);
+ tmp.cd_flag = dm->cd_flag;
if (CustomData_has_layer(&dm->vertData, CD_SHAPEKEY)) {
KeyBlock *kb;
@@ -538,9 +542,10 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob)
}
/* yes, must be before _and_ after tessellate */
- mesh_update_customdata_pointers(&tmp, TRUE);
+ BKE_mesh_update_customdata_pointers(&tmp, false);
- BKE_mesh_tessface_calc(&tmp);
+ /* since 2.65 caller must do! */
+ // BKE_mesh_tessface_calc(&tmp);
CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge);
@@ -557,6 +562,13 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob)
tmp.key = NULL;
}
+ /* Clear selection history */
+ tmp.mselect = NULL;
+ tmp.totselect = 0;
+ if (me->mselect) {
+ MEM_freeN(me->mselect);
+ }
+
*me = tmp;
}
@@ -569,7 +581,7 @@ void DM_to_meshkey(DerivedMesh *dm, Mesh *me, KeyBlock *kb)
if (totvert == 0 || me->totvert == 0 || me->totvert != totvert) return;
if (kb->data) MEM_freeN(kb->data);
- kb->data = MEM_callocN(me->key->elemsize * me->totvert, "kb->data");
+ kb->data = MEM_mallocN(me->key->elemsize * me->totvert, "kb->data");
kb->totelem = totvert;
fp = kb->data;
@@ -857,30 +869,27 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob,
return dm;
}
-static float *get_editbmesh_orco_verts(BMEditMesh *em)
+static float (*get_editbmesh_orco_verts(BMEditMesh *em))[3]
{
BMIter iter;
BMVert *eve;
- float *orco;
- int a, totvert;
+ float (*orco)[3];
+ int i;
/* these may not really be the orco's, but it's only for preview.
* could be solver better once, but isn't simple */
-
- totvert = em->bm->totvert;
- orco = MEM_mallocN(sizeof(float) * 3 * totvert, "BMEditMesh Orco");
+ orco = MEM_mallocN(sizeof(float) * 3 * em->bm->totvert, "BMEditMesh Orco");
- eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
- for (a = 0; eve; eve = BM_iter_step(&iter), a += 3) {
- copy_v3_v3(orco + a, eve->co);
+ BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ copy_v3_v3(orco[i], eve->co);
}
return orco;
}
/* orco custom data layer */
-static void *get_orco_coords_dm(Object *ob, BMEditMesh *em, int layer, int *free)
+static float (*get_orco_coords_dm(Object *ob, BMEditMesh *em, int layer, int *free))[3]
{
*free = 0;
@@ -889,9 +898,9 @@ static void *get_orco_coords_dm(Object *ob, BMEditMesh *em, int layer, int *free
*free = 1;
if (em)
- return (float(*)[3])get_editbmesh_orco_verts(em);
+ return get_editbmesh_orco_verts(em);
else
- return (float(*)[3])BKE_mesh_orco_verts_get(ob);
+ return BKE_mesh_orco_verts_get(ob);
}
else if (layer == CD_CLOTH_ORCO) {
/* apply shape key for cloth, this should really be solved
@@ -1008,16 +1017,26 @@ void weight_to_rgb(float r_rgb[3], const float weight)
/* draw_flag's for calc_weightpaint_vert_color */
enum {
- CALC_WP_MULTIPAINT = (1 << 0),
- CALC_WP_AUTO_NORMALIZE = (1 << 1)
+ /* only one of these should be set, keep first (for easy bit-shifting) */
+ CALC_WP_GROUP_USER_ACTIVE = (1 << 1),
+ CALC_WP_GROUP_USER_ALL = (1 << 2),
+
+ CALC_WP_MULTIPAINT = (1 << 3),
+ CALC_WP_AUTO_NORMALIZE = (1 << 4)
};
-static void weightpaint_color(unsigned char r_col[4], ColorBand *coba, const float input)
+typedef struct DMWeightColorInfo {
+ const ColorBand *coba;
+ const char *alert_color;
+} DMWeightColorInfo;
+
+
+static void weightpaint_color(unsigned char r_col[4], DMWeightColorInfo *dm_wcinfo, const float input)
{
float colf[4];
- if (coba) {
- do_colorband(coba, input, colf);
+ if (dm_wcinfo && dm_wcinfo->coba) {
+ do_colorband(dm_wcinfo->coba, input, colf);
}
else {
weight_to_rgb(colf, input);
@@ -1034,17 +1053,19 @@ static void weightpaint_color(unsigned char r_col[4], ColorBand *coba, const flo
static void calc_weightpaint_vert_color(
unsigned char r_col[4],
- MDeformVert *dv, ColorBand *coba,
+ MDeformVert *dv,
+ DMWeightColorInfo *dm_wcinfo,
const int defbase_tot, const int defbase_act,
const char *defbase_sel, const int defbase_sel_tot,
const int draw_flag)
{
float input = 0.0f;
- int make_black = FALSE;
+ bool show_alert_color = false;
if ((defbase_sel_tot > 1) && (draw_flag & CALC_WP_MULTIPAINT)) {
- int was_a_nonzero = FALSE;
+ /* Multi-Paint feature */
+ bool was_a_nonzero = false;
unsigned int i;
MDeformWeight *dw = dv->dw;
@@ -1055,15 +1076,15 @@ static void calc_weightpaint_vert_color(
if (defbase_sel[dw->def_nr]) {
if (dw->weight) {
input += dw->weight;
- was_a_nonzero = TRUE;
+ was_a_nonzero = true;
}
}
}
}
/* make it black if the selected groups have no weight on a vertex */
- if (was_a_nonzero == FALSE) {
- make_black = TRUE;
+ if (was_a_nonzero == false) {
+ show_alert_color = true;
}
else if ((draw_flag & CALC_WP_AUTO_NORMALIZE) == FALSE) {
input /= defbase_sel_tot; /* get the average */
@@ -1072,25 +1093,35 @@ static void calc_weightpaint_vert_color(
else {
/* default, non tricky behavior */
input = defvert_find_weight(dv, defbase_act);
+
+ if (draw_flag & CALC_WP_GROUP_USER_ACTIVE) {
+ if (input == 0.0f) {
+ show_alert_color = true;
+ }
+ }
+ else if (draw_flag & CALC_WP_GROUP_USER_ALL) {
+ if (input == 0.0f) {
+ show_alert_color = defvert_is_weight_zero(dv, defbase_tot);
+ }
+ }
}
- if (make_black) { /* TODO, theme color */
- r_col[3] = 255;
- r_col[2] = 0;
- r_col[1] = 0;
- r_col[0] = 0;
+ if (show_alert_color == false) {
+ CLAMP(input, 0.0f, 1.0f);
+ weightpaint_color(r_col, dm_wcinfo, input);
}
else {
- CLAMP(input, 0.0f, 1.0f);
- weightpaint_color(r_col, coba, input);
+ copy_v3_v3_char((char *)r_col, dm_wcinfo->alert_color);
+ r_col[3] = 255;
}
}
-static ColorBand *stored_cb = NULL;
+static DMWeightColorInfo G_dm_wcinfo;
-void vDM_ColorBand_store(ColorBand *coba)
+void vDM_ColorBand_store(const ColorBand *coba, const char alert_color[4])
{
- stored_cb = coba;
+ G_dm_wcinfo.coba = coba;
+ G_dm_wcinfo.alert_color = alert_color;
}
/* return an array of vertex weight colors, caller must free.
@@ -1098,7 +1129,7 @@ void vDM_ColorBand_store(ColorBand *coba)
* 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 unsigned char *calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, int const draw_flag, ColorBand *coba)
+static unsigned char *calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, int const draw_flag, DMWeightColorInfo *dm_wcinfo)
{
MDeformVert *dv = DM_get_vert_data_layer(dm, CD_MDEFORMVERT);
int numVerts = dm->getNumVerts(dm);
@@ -1120,7 +1151,7 @@ static unsigned char *calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, i
}
for (i = numVerts; i != 0; i--, wc += 4, dv++) {
- calc_weightpaint_vert_color(wc, dv, coba, defbase_tot, defbase_act, defbase_sel, defbase_sel_tot, draw_flag);
+ calc_weightpaint_vert_color(wc, dv, dm_wcinfo, defbase_tot, defbase_act, defbase_sel, defbase_sel_tot, draw_flag);
}
if (defbase_sel) {
@@ -1129,7 +1160,12 @@ static unsigned char *calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, i
}
else {
int col_i;
- weightpaint_color((unsigned char *)&col_i, coba, 0.0f);
+ if (draw_flag & (CALC_WP_GROUP_USER_ACTIVE | CALC_WP_GROUP_USER_ALL)) {
+ col_i = 0;
+ }
+ else {
+ weightpaint_color((unsigned char *)&col_i, dm_wcinfo, 0.0f);
+ }
fill_vn_i((int *)wtcol_v, numVerts, col_i);
}
@@ -1156,7 +1192,6 @@ static unsigned char *calc_colors_from_weights_array(const int num, float *weigh
void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag,
float *weights, int num, const int *indices)
{
- ColorBand *coba = stored_cb; /* warning, not a local var */
unsigned char *wtcol_v;
unsigned char(*wtcol_l)[4] = CustomData_get_layer(dm->getLoopDataLayout(dm), CD_PREVIEW_MLOOPCOL);
@@ -1184,10 +1219,10 @@ void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag,
if (indices)
MEM_freeN(w);
}
-
- /* No weights given, take them from active vgroup(s). */
- else
- wtcol_v = calc_weightpaint_vert_array(ob, dm, draw_flag, coba);
+ else {
+ /* No weights given, take them from active vgroup(s). */
+ wtcol_v = calc_weightpaint_vert_array(ob, dm, draw_flag, &G_dm_wcinfo);
+ }
/* now add to loops, so the data can be passed through the modifier stack */
/* If no CD_PREVIEW_MLOOPCOL existed yet, we have to add a new one! */
@@ -1343,9 +1378,13 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
int has_multires = mmd != NULL, multires_applied = 0;
int sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt;
+ int sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm);
- const int draw_flag = ((scene->toolsettings->multipaint ? CALC_WP_MULTIPAINT : 0) |
+ const int draw_flag = ((scene->toolsettings->multipaint ? CALC_WP_MULTIPAINT :
+ /* CALC_WP_GROUP_USER_ACTIVE or CALC_WP_GROUP_USER_ALL*/
+ (1 << scene->toolsettings->weightuser)) |
(scene->toolsettings->auto_normalize ? CALC_WP_AUTO_NORMALIZE : 0));
+
/* Generic preview only in object mode! */
const int do_mod_mcol = (ob->mode == OB_MODE_OBJECT);
#if 0 /* XXX Will re-enable this when we have global mod stack options. */
@@ -1410,7 +1449,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
if (!modifier_isEnabled(scene, md, required_mode)) continue;
if (useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue;
- if (mti->type == eModifierTypeType_OnlyDeform) {
+ if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) {
if (!deformedVerts)
deformedVerts = mesh_getVertexCos(me, &numVerts);
@@ -1421,7 +1460,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
}
/* grab modifiers until index i */
- if ((index >= 0) && (modifiers_indexInObject(ob, md) >= index))
+ if ((index >= 0) && (BLI_findindex(&ob->modifiers, md) >= index))
break;
}
@@ -1468,9 +1507,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
modifier_setError(md, "Modifier requires original data, bad stack position");
continue;
}
- if (sculpt_mode && (!has_multires || multires_applied)) {
+ if (sculpt_mode &&
+ (!has_multires || multires_applied || ob->sculpt->bm))
+ {
int unsupported = 0;
+ if (sculpt_dyntopo)
+ unsupported = TRUE;
+
if (scene->toolsettings->sculpt->flags & SCULPT_ONLY_DEFORM)
unsupported |= mti->type != eModifierTypeType_OnlyDeform;
@@ -1576,9 +1620,15 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
DM_add_poly_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
- range_vn_i(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0);
- range_vn_i(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0);
- range_vn_i(DM_get_poly_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0);
+#pragma omp parallel sections if (dm->numVertData + dm->numEdgeData + dm->numPolyData >= DM_OMP_LIMIT)
+ {
+#pragma omp section
+ { range_vn_i(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0); }
+#pragma omp section
+ { range_vn_i(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0); }
+#pragma omp section
+ { range_vn_i(DM_get_poly_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0); }
+ }
}
}
@@ -1666,7 +1716,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) && (modifiers_indexInObject(ob, md) >= index))
+ if ((index >= 0) && (BLI_findindex(&ob->modifiers, md) >= index))
break;
if (sculpt_mode && md->type == eModifierType_Multires)
@@ -1815,17 +1865,18 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
BLI_linklist_free((LinkNode *)datamasks, NULL);
}
-float (*editbmesh_get_vertex_cos(BMEditMesh * em, int *numVerts_r))[3]
+float (*editbmesh_get_vertex_cos(BMEditMesh *em, int *numVerts_r))[3]
{
- int i, numVerts = *numVerts_r = em->bm->totvert;
- float (*cos)[3];
BMIter iter;
BMVert *eve;
+ float (*cos)[3];
+ int i;
- cos = MEM_mallocN(sizeof(float) * 3 * numVerts, "vertexcos");
+ *numVerts_r = em->bm->totvert;
- eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
- for (i = 0; eve; eve = BM_iter_step(&iter), i++) {
+ cos = MEM_mallocN(sizeof(float) * 3 * em->bm->totvert, "vertexcos");
+
+ BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
copy_v3_v3(cos[i], eve->co);
}
@@ -2312,20 +2363,19 @@ DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em)
static void make_vertexcosnos__mapFunc(void *userData, int index, const float co[3],
const float no_f[3], const short no_s[3])
{
- float *vec = userData;
-
- vec += 6 * index;
+ DMCoNo *co_no = &((DMCoNo *)userData)[index];
/* check if we've been here before (normal should not be 0) */
- if (vec[3] || vec[4] || vec[5]) return;
+ if (!is_zero_v3(co_no->no)) {
+ return;
+ }
- copy_v3_v3(vec, co);
- vec += 3;
+ copy_v3_v3(co_no->co, co);
if (no_f) {
- copy_v3_v3(vec, no_f);
+ copy_v3_v3(co_no->no, no_f);
}
else {
- normal_short_to_float_v3(vec, no_s);
+ normal_short_to_float_v3(co_no->no, no_s);
}
}
@@ -2334,29 +2384,28 @@ static void make_vertexcosnos__mapFunc(void *userData, int index, const float co
/* it stores the normals as floats, but they can still be scaled as shorts (32767 = unit) */
/* in use now by vertex/weight paint and particle generating */
-float *mesh_get_mapped_verts_nors(Scene *scene, Object *ob)
+DMCoNo *mesh_get_mapped_verts_nors(Scene *scene, Object *ob)
{
Mesh *me = ob->data;
DerivedMesh *dm;
- float *vertexcosnos;
+ DMCoNo *vertexcosnos;
/* lets prevent crashing... */
if (ob->type != OB_MESH || me->totvert == 0)
return NULL;
dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
- vertexcosnos = MEM_callocN(6 * sizeof(float) * me->totvert, "vertexcosnos map");
if (dm->foreachMappedVert) {
+ vertexcosnos = MEM_callocN(sizeof(DMCoNo) * me->totvert, "vertexcosnos map");
dm->foreachMappedVert(dm, make_vertexcosnos__mapFunc, vertexcosnos);
}
else {
- float *fp = vertexcosnos;
+ DMCoNo *v_co_no = vertexcosnos = MEM_mallocN(sizeof(DMCoNo) * me->totvert, "vertexcosnos map");
int a;
-
- for (a = 0; a < me->totvert; a++, fp += 6) {
- dm->getVertCo(dm, a, fp);
- dm->getVertNo(dm, a, fp + 3);
+ for (a = 0; a < me->totvert; a++, v_co_no++) {
+ dm->getVertCo(dm, a, v_co_no->co);
+ dm->getVertNo(dm, a, v_co_no->no);
}
}
@@ -2700,7 +2749,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
a = attribs->tottface++;
attribs->tface[a].array = tfdata->layers[layer].data;
- attribs->tface[a].em_offset = tfdata->layers[layer].offset;
+ attribs->tface[a].em_offset = ldata->layers[layer].offset;
attribs->tface[a].gl_index = gattribs->layer[b].glindex;
attribs->tface[a].gl_texco = gattribs->layer[b].gltexco;
}
@@ -2737,7 +2786,8 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
a = attribs->totmcol++;
attribs->mcol[a].array = tfdata->layers[layer].data;
- attribs->mcol[a].em_offset = tfdata->layers[layer].offset;
+ /* 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;
attribs->mcol[a].gl_index = gattribs->layer[b].glindex;
}
}
@@ -2753,6 +2803,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
a = attribs->totmcol++;
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;
attribs->mcol[a].gl_index = gattribs->layer[b].glindex;
}
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index dd27cc70ba3..509442b1d4e 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -43,7 +43,6 @@
#include "DNA_object_types.h"
#include "BLI_blenlib.h"
-#include "BLI_bpath.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
@@ -79,11 +78,11 @@
/* ***************** Library data level operations on action ************** */
-bAction *add_empty_action(const char name[])
+bAction *add_empty_action(Main *bmain, const char name[])
{
bAction *act;
- act = BKE_libblock_alloc(&G.main->action, ID_AC, name);
+ act = BKE_libblock_alloc(&bmain->action, ID_AC, name);
return act;
}
@@ -544,7 +543,7 @@ void BKE_pose_copy_data(bPose **dst, bPose *src, int copycon)
for (pchan = outPose->chanbase.first; pchan; pchan = pchan->next) {
/* TODO: rename this argument... */
if (copycon) {
- copy_constraints(&listb, &pchan->constraints, TRUE); // copy_constraints NULLs listb
+ BKE_copy_constraints(&listb, &pchan->constraints, TRUE); // BKE_copy_constraints NULLs listb
pchan->constraints = listb;
pchan->mpath = NULL; /* motion paths should not get copied yet... */
}
@@ -622,7 +621,7 @@ void BKE_pose_channel_free(bPoseChannel *pchan)
pchan->mpath = NULL;
}
- free_constraints(&pchan->constraints);
+ BKE_free_constraints(&pchan->constraints);
if (pchan->prop) {
IDP_FreeProperty(pchan->prop);
@@ -712,7 +711,7 @@ void BKE_pose_channel_copy_data(bPoseChannel *pchan, const bPoseChannel *pchan_f
pchan->iklinweight = pchan_from->iklinweight;
/* constraints */
- copy_constraints(&pchan->constraints, &pchan_from->constraints, TRUE);
+ BKE_copy_constraints(&pchan->constraints, &pchan_from->constraints, TRUE);
/* id-properties */
if (pchan->prop) {
@@ -1119,18 +1118,18 @@ void BKE_pose_rest(bPose *pose)
}
/* both poses should be in sync */
-void BKE_pose_copy_result(bPose *to, bPose *from)
+bool BKE_pose_copy_result(bPose *to, bPose *from)
{
bPoseChannel *pchanto, *pchanfrom;
if (to == NULL || from == NULL) {
- printf("pose result copy error to:%p from:%p\n", (void *)to, (void *)from); /* debug temp */
- return;
+ printf("Pose copy error, pose to:%p from:%p\n", (void *)to, (void *)from); /* debug temp */
+ return false;
}
if (to == from) {
printf("BKE_pose_copy_result source and target are the same\n");
- return;
+ return false;
}
@@ -1154,6 +1153,7 @@ void BKE_pose_copy_result(bPose *to, bPose *from)
pchanto->protectflag = pchanfrom->protectflag;
}
}
+ return true;
}
/* For the calculation of the effects of an Action at the given frame on an object
diff --git a/source/blender/blenkernel/intern/addon.c b/source/blender/blenkernel/intern/addon.c
new file mode 100644
index 00000000000..7f475cd4732
--- /dev/null
+++ b/source/blender/blenkernel/intern/addon.c
@@ -0,0 +1,85 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#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;
+
+
+bAddonPrefType *BKE_addon_pref_type_find(const char *idname, int quiet)
+{
+ if (idname[0]) {
+ bAddonPrefType *apt;
+
+ apt = BLI_ghash_lookup(global_addonpreftype_hash, idname);
+ if (apt) {
+ return apt;
+ }
+
+ if (!quiet) {
+ printf("search for unknown addon-pref '%s'\n", idname);
+ }
+ }
+ else {
+ if (!quiet) {
+ printf("search for empty addon-pref");
+ }
+ }
+
+ return NULL;
+}
+
+void BKE_addon_pref_type_add(bAddonPrefType *apt)
+{
+ BLI_ghash_insert(global_addonpreftype_hash, (void *)apt->idname, apt);
+}
+
+void BKE_addon_pref_type_remove(bAddonPrefType *apt)
+{
+ BLI_ghash_remove(global_addonpreftype_hash, (void *)apt->idname, NULL, (GHashValFreeFP)MEM_freeN);
+}
+
+void BKE_addon_pref_type_init(void)
+{
+ BLI_assert(global_addonpreftype_hash == NULL);
+ global_addonpreftype_hash = BLI_ghash_str_new(__func__);
+}
+
+void BKE_addon_pref_type_free(void)
+{
+ BLI_ghash_free(global_addonpreftype_hash, NULL, (GHashValFreeFP)MEM_freeN);
+ global_addonpreftype_hash = NULL;
+}
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 89f2291059f..ad791852253 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -311,7 +311,7 @@ static void motionpaths_calc_optimise_depsgraph(Scene *scene, ListBase *targets)
BLI_addhead(&scene->base, base);
mpt->ob->flag |= BA_TEMP_TAG;
-
+
/* we really don't need to continue anymore once this happens, but this line might really 'break' */
break;
}
@@ -319,37 +319,45 @@ static void motionpaths_calc_optimise_depsgraph(Scene *scene, ListBase *targets)
}
/* "brew me a list that's sorted a bit faster now depsy" */
- DAG_scene_sort(G.main, scene);
+ DAG_scene_relations_rebuild(G.main, scene);
}
/* update scene for current frame */
static void motionpaths_calc_update_scene(Scene *scene)
{
#if 1 // 'production' optimizations always on
- Base *base, *last = NULL;
-
- /* only stuff that moves or needs display still */
- DAG_scene_update_flags(G.main, scene, scene->lay, TRUE);
-
- /* find the last object with the tag
- * - all those afterwards are assumed to not be relevant for our calculations
- */
- /* optimize further by moving out... */
- for (base = scene->base.first; base; base = base->next) {
- if (base->object->flag & BA_TEMP_TAG)
- last = base;
+
+ /* rigid body simulation needs complete update to work correctly for now */
+ /* RB_TODO investigate if we could avoid updating everything */
+ if (BKE_scene_check_rigidbody_active(scene)) {
+ BKE_scene_update_for_newframe(G.main, scene, scene->lay);
}
-
- /* perform updates for tagged objects */
- /* XXX: this will break if rigs depend on scene or other data that
- * is animated but not attached to/updatable from objects */
- for (base = scene->base.first; base; base = base->next) {
- /* update this object */
- BKE_object_handle_update(scene, base->object);
+ else { /* otherwise we can optimize by restricting updates */
+ Base *base, *last = NULL;
- /* if this is the last one we need to update, let's stop to save some time */
- if (base == last)
- break;
+ /* only stuff that moves or needs display still */
+ DAG_scene_update_flags(G.main, scene, scene->lay, TRUE);
+
+ /* find the last object with the tag
+ * - all those afterwards are assumed to not be relevant for our calculations
+ */
+ /* optimize further by moving out... */
+ for (base = scene->base.first; base; base = base->next) {
+ if (base->object->flag & BA_TEMP_TAG)
+ last = base;
+ }
+
+ /* perform updates for tagged objects */
+ /* XXX: this will break if rigs depend on scene or other data that
+ * is animated but not attached to/updatable from objects */
+ for (base = scene->base.first; base; base = base->next) {
+ /* update this object */
+ BKE_object_handle_update(scene, base->object);
+
+ /* if this is the last one we need to update, let's stop to save some time */
+ if (base == last)
+ break;
+ }
}
#else // original, 'always correct' version
/* do all updates
@@ -957,7 +965,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
dm = editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH);
}
else
- dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH);
+ dm = mesh_get_derived_final(scene, par, CD_MASK_BAREMESH);
if (flag & DUPLILIST_FOR_RENDER) {
vdd.orco = (float(*)[3])BKE_mesh_orco_verts_get(par);
@@ -1084,7 +1092,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
dm = editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH);
}
else {
- dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH);
+ dm = mesh_get_derived_final(scene, par, CD_MASK_BAREMESH);
}
totface = dm->getNumPolys(dm);
@@ -1146,10 +1154,6 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
if (ob->type != OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */
for (a = 0, mp = mpoly; a < totface; a++, mp++) {
- int mv1;
- int mv2;
- int mv3;
- /* int mv4; */ /* UNUSED */
float *v1;
float *v2;
float *v3;
@@ -1163,9 +1167,9 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
}
else {
BKE_mesh_calc_poly_normal(mp, mloop + mp->loopstart, mvert, f_no);
- v1 = mvert[(mv1 = loopstart[0].v)].co;
- v2 = mvert[(mv2 = loopstart[1].v)].co;
- v3 = mvert[(mv3 = loopstart[2].v)].co;
+ v1 = mvert[loopstart[0].v].co;
+ v2 = mvert[loopstart[1].v].co;
+ v3 = mvert[loopstart[2].v].co;
}
/* translation */
@@ -1480,7 +1484,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
/* blender internal needs this to be set to dupligroup to render
* groups correctly, but we don't want this hack for cycles */
- if(dupli_type_hack && GS(id->name) == ID_GR)
+ if (dupli_type_hack && GS(id->name) == ID_GR)
dupli_type = OB_DUPLIGROUP;
/* to give ipos in object correct offset */
@@ -1708,7 +1712,7 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas
/* Returns a list of DupliObject
* note; group dupli's already set transform matrix. see note in group_duplilist() */
-ListBase *object_duplilist_ex(Scene *sce, Object *ob, int update, int for_render)
+ListBase *object_duplilist_ex(Scene *sce, Object *ob, bool update, bool for_render)
{
ListBase *duplilist = MEM_mallocN(sizeof(ListBase), "duplilist");
int persistent_id[MAX_DUPLI_RECUR] = {0};
@@ -1724,9 +1728,9 @@ ListBase *object_duplilist_ex(Scene *sce, Object *ob, int update, int for_render
/* note: previously updating was always done, this is why it defaults to be on
* but there are likely places it can be called without updating */
-ListBase *object_duplilist(Scene *sce, Object *ob, int for_render)
+ListBase *object_duplilist(Scene *sce, Object *ob, bool for_render)
{
- return object_duplilist_ex(sce, ob, TRUE, for_render);
+ return object_duplilist_ex(sce, ob, true, for_render);
}
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 40b883e3f4e..d4563c936d0 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -86,6 +86,7 @@ short id_type_can_have_animdata(ID *id)
case ID_PA:
case ID_MA: case ID_TE: case ID_NT:
case ID_LA: case ID_CA: case ID_WO:
+ case ID_LS:
case ID_SPK:
case ID_SCE:
case ID_MC:
@@ -242,7 +243,7 @@ void BKE_free_animdata(ID *id)
/* Freeing -------------------------------------------- */
/* Make a copy of the given AnimData - to be used when copying datablocks */
-AnimData *BKE_copy_animdata(AnimData *adt, const short do_action)
+AnimData *BKE_copy_animdata(AnimData *adt, const bool do_action)
{
AnimData *dadt;
@@ -274,7 +275,7 @@ AnimData *BKE_copy_animdata(AnimData *adt, const short do_action)
return dadt;
}
-int BKE_copy_animdata_id(ID *id_to, ID *id_from, const short do_action)
+int BKE_copy_animdata_id(ID *id_to, ID *id_from, const bool do_action)
{
AnimData *adt;
@@ -499,15 +500,15 @@ void BKE_animdata_separate_by_basepath(ID *srcID, ID *dstID, ListBase *basepaths
if (srcAdt->action) {
/* set up an action if necessary, and name it in a similar way so that it can be easily found again */
if (dstAdt->action == NULL) {
- dstAdt->action = add_empty_action(srcAdt->action->id.name + 2);
+ dstAdt->action = add_empty_action(G.main, srcAdt->action->id.name + 2);
}
else if (dstAdt->action == srcAdt->action) {
printf("Argh! Source and Destination share animation! ('%s' and '%s' both use '%s') Making new empty action\n",
srcID->name, dstID->name, srcAdt->action->id.name);
-
+
/* TODO: review this... */
id_us_min(&dstAdt->action->id);
- dstAdt->action = add_empty_action(dstAdt->action->id.name + 2);
+ dstAdt->action = add_empty_action(G.main, dstAdt->action->id.name + 2);
}
/* loop over base paths, trying to fix for each one... */
@@ -533,9 +534,9 @@ void BKE_animdata_separate_by_basepath(ID *srcID, ID *dstID, ListBase *basepaths
/* just need to change lists */
BLI_remlink(&srcAdt->drivers, fcu);
BLI_addtail(&dstAdt->drivers, fcu);
-
+
/* TODO: add depsgraph flushing calls? */
-
+
/* can stop now, as moved already */
break;
}
@@ -827,7 +828,10 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u
/* scenes */
ANIMDATA_NODETREE_IDS_CB(mainptr->scene.first, Scene);
-}
+
+ /* line styles */
+ ANIMDATA_IDS_CB(mainptr->linestyle.first);
+ }
/* Fix all RNA-Paths throughout the database (directly access the Global.main version)
* NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]>
@@ -912,6 +916,9 @@ void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const cha
/* worlds */
RENAMEFIX_ANIM_NODETREE_IDS(mainptr->world.first, World);
+ /* linestyles */
+ RENAMEFIX_ANIM_IDS(mainptr->linestyle.first);
+
/* scenes */
RENAMEFIX_ANIM_NODETREE_IDS(mainptr->scene.first, Scene);
}
@@ -2397,6 +2404,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime)
/* movie clips */
EVAL_ANIM_IDS(main->movieclip.first, ADT_RECALC_ANIM);
+ /* linestyles */
+ EVAL_ANIM_IDS(main->linestyle.first, ADT_RECALC_ANIM);
+
/* objects */
/* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets
* this tagged by Depsgraph on framechange. This optimization means that objects
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index a93d728ad04..ffe6a312ef8 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -37,7 +37,6 @@
#include "MEM_guardedalloc.h"
-#include "BLI_bpath.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -75,11 +74,11 @@
/* **************** Generic Functions, data level *************** */
-bArmature *BKE_armature_add(const char *name)
+bArmature *BKE_armature_add(Main *bmain, const char *name)
{
bArmature *arm;
- arm = BKE_libblock_alloc(&G.main->armature, ID_AR, name);
+ arm = BKE_libblock_alloc(&bmain->armature, ID_AR, name);
arm->deformflag = ARM_DEF_VGROUP | ARM_DEF_ENVELOPE;
arm->flag = ARM_COL_CUSTOM; /* custom bone-group colors */
arm->layer = 1;
@@ -1597,7 +1596,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
}
else if (pchan->bone->layer & layer_protected) {
ListBase proxylocal_constraints = {NULL, NULL};
- bPoseChannel pchanw = {NULL};
+ bPoseChannel pchanw;
/* copy posechannel to temp, but restore important pointers */
pchanw = *pchanp;
@@ -1621,15 +1620,16 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
* 2. copy proxy-pchan's constraints on-to new
* 3. add extracted local constraints back on top
*
- * Note for copy_constraints: when copying constraints, disable 'do_extern' otherwise
- * we get the libs direct linked in this blend. */
- extract_proxylocal_constraints(&proxylocal_constraints, &pchan->constraints);
- copy_constraints(&pchanw.constraints, &pchanp->constraints, FALSE);
+ * Note for BKE_copy_constraints: when copying constraints, disable 'do_extern' otherwise
+ * we get the libs direct linked in this blend.
+ */
+ BKE_extract_proxylocal_constraints(&proxylocal_constraints, &pchan->constraints);
+ BKE_copy_constraints(&pchanw.constraints, &pchanp->constraints, FALSE);
BLI_movelisttolist(&pchanw.constraints, &proxylocal_constraints);
/* constraints - set target ob pointer to own object */
for (con = pchanw.constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -1655,7 +1655,8 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
else {
/* always copy custom shape */
pchan->custom = pchanp->custom;
- pchan->custom_tx = pchanp->custom_tx;
+ if (pchanp->custom_tx)
+ pchan->custom_tx = BKE_pose_channel_find_name(pose, pchanp->custom_tx->name);
/* ID-Property Syncing */
{
@@ -2258,7 +2259,7 @@ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseCha
{
bActionModifier *amod;
bActionStrip *strip, *strip2;
- float scene_cfra = (float)scene->r.cfra;
+ float scene_cfra = BKE_scene_frame_get(scene);
int do_modif;
for (strip = armob->nlastrips.first; strip; strip = strip->next) {
@@ -2427,15 +2428,15 @@ void BKE_pose_where_is_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float
/* prepare PoseChannel for Constraint solving
* - makes a copy of matrix, and creates temporary struct to use
*/
- cob = constraints_make_evalob(scene, ob, pchan, CONSTRAINT_OBTYPE_BONE);
+ cob = BKE_constraints_make_evalob(scene, ob, pchan, CONSTRAINT_OBTYPE_BONE);
/* Solve PoseChannel's Constraints */
- solve_constraints(&pchan->constraints, cob, ctime); /* ctime doesnt alter objects */
+ BKE_solve_constraints(&pchan->constraints, cob, ctime); /* ctime doesnt alter objects */
/* cleanup after Constraint Solving
* - applies matrix back to pchan, and frees temporary struct used
*/
- constraints_clear_evalob(cob);
+ BKE_constraints_clear_evalob(cob);
/* prevent constraints breaking a chain */
if (pchan->bone->flag & BONE_CONNECTED) {
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index f0d201ea3f7..b3c94beba93 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -54,9 +54,9 @@
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_sound_types.h"
+#include "DNA_windowmanager_types.h"
#include "BLI_blenlib.h"
-#include "BLI_bpath.h"
#include "BLI_dynstr.h"
#include "BLI_utildefines.h"
#include "BLI_callbacks.h"
@@ -65,6 +65,8 @@
#include "IMB_moviecache.h"
#include "BKE_blender.h"
+#include "BKE_bpath.h"
+#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_displist.h"
@@ -80,8 +82,11 @@
#include "BKE_screen.h"
#include "BKE_sequencer.h"
#include "BKE_sound.h"
+
#include "RE_pipeline.h"
+#include "BLF_api.h"
+
#include "BLO_undofile.h"
#include "BLO_readfile.h"
#include "BLO_writefile.h"
@@ -116,6 +121,8 @@ void free_blender(void)
IMB_exit();
BKE_images_exit();
+ BKE_brush_system_exit();
+
BLI_callback_global_finalize();
BKE_sequencer_cache_destruct();
@@ -179,7 +186,7 @@ static void clean_paths(Main *main)
{
Scene *scene;
- BLI_bpath_traverse_main(main, clean_paths_visit_cb, BLI_BPATH_TRAVERSE_SKIP_MULTIFILE, NULL);
+ BKE_bpath_traverse_main(main, clean_paths_visit_cb, BKE_BPATH_TRAVERSE_SKIP_MULTIFILE, NULL);
for (scene = main->scene.first; scene; scene = scene->id.next) {
BLI_clean(scene->r.pic);
@@ -230,6 +237,9 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
/* but use new Scene pointer */
curscene = bfd->curscene;
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 */
@@ -270,7 +280,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
G.fileflags = bfd->fileflags;
CTX_wm_manager_set(C, G.main->wm.first);
CTX_wm_screen_set(C, bfd->curscreen);
- CTX_data_scene_set(C, bfd->curscreen->scene);
+ CTX_data_scene_set(C, bfd->curscene);
CTX_wm_area_set(C, NULL);
CTX_wm_region_set(C, NULL);
CTX_wm_menu_set(C, NULL);
@@ -280,7 +290,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
if (CTX_data_scene(C) == NULL) {
/* in case we don't even have a local scene, add one */
if (!G.main->scene.first)
- BKE_scene_add("Scene");
+ BKE_scene_add(G.main, "Scene");
CTX_data_scene_set(C, G.main->scene.first);
CTX_wm_screen(C)->scene = CTX_data_scene(C);
@@ -310,23 +320,38 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
if (G.main->versionfile < 250)
do_versions_ipos_to_animato(G.main);
- if (recover && bfd->filename[0] && G.relbase_valid) {
+ G.main->recovered = 0;
+
+ /* startup.blend or recovered startup */
+ if (bfd->filename[0] == 0) {
+ G.main->name[0] = 0;
+ }
+ else if (recover && G.relbase_valid) {
/* in case of autosave or quit.blend, use original filename instead
* use relbase_valid to make sure the file is saved, else we get <memory2> in the filename */
filepath = bfd->filename;
+ G.main->recovered = 1;
+
+ /* these are the same at times, should never copy to the same location */
+ if (G.main->name != filepath)
+ BLI_strncpy(G.main->name, filepath, FILE_MAX);
}
-#if 0
- else if (!G.relbase_valid) {
- /* otherwise, use an empty string as filename, rather than <memory2> */
- filepath = "";
- }
-#endif
- /* these are the same at times, should never copy to the same location */
- if (G.main->name != filepath)
- BLI_strncpy(G.main->name, filepath, FILE_MAX);
-
/* baseflags, groups, make depsgraph, etc */
+ /* first handle case if other windows have different scenes visible */
+ if (mode == 0) {
+ wmWindowManager *wm = G.main->wm.first;
+
+ if (wm) {
+ wmWindow *win;
+
+ for (win = wm->windows.first; win; win = win->next) {
+ if (win->screen && win->screen->scene) /* zealous check... */
+ if (win->screen->scene != CTX_data_scene(C))
+ BKE_scene_set_background(G.main, win->screen->scene);
+ }
+ }
+ }
BKE_scene_set_background(G.main, CTX_data_scene(C));
if (mode != 'u') {
@@ -335,7 +360,6 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
MEM_freeN(bfd);
- (void)curscene; /* quiet warning */
}
static int handle_subversion_warning(Main *main, ReportList *reports)
@@ -366,6 +390,7 @@ void BKE_userdef_free(void)
wmKeyMap *km;
wmKeyMapItem *kmi;
wmKeyMapDiffItem *kmdi;
+ bAddon *addon, *addon_next;
for (km = U.user_keymaps.first; km; km = km->next) {
for (kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) {
@@ -386,11 +411,30 @@ void BKE_userdef_free(void)
BLI_freelistN(&km->items);
}
+ for (addon = U.addons.first; addon; addon = addon_next) {
+ addon_next = addon->next;
+ if (addon->prop) {
+ IDP_FreeProperty(addon->prop);
+ MEM_freeN(addon->prop);
+ }
+ MEM_freeN(addon);
+ }
+
BLI_freelistN(&U.uistyles);
BLI_freelistN(&U.uifonts);
BLI_freelistN(&U.themes);
BLI_freelistN(&U.user_keymaps);
- BLI_freelistN(&U.addons);
+}
+
+/* handle changes in settings that need recalc */
+void BKE_userdef_state(void)
+{
+ /* prevent accidents */
+ if (U.pixelsize == 0) U.pixelsize = 1;
+
+ BLF_default_dpi(U.pixelsize * U.dpi);
+ U.widget_unit = (U.pixelsize * U.dpi * 20 + 36) / 72;
+
}
int BKE_read_file(bContext *C, const char *filepath, ReportList *reports)
@@ -420,7 +464,7 @@ int BKE_read_file(bContext *C, const char *filepath, ReportList *reports)
return (bfd ? retval : BKE_READ_FILE_FAIL);
}
-int BKE_read_file_from_memory(bContext *C, char *filebuf, int filelength, ReportList *reports)
+int BKE_read_file_from_memory(bContext *C, const void *filebuf, int filelength, ReportList *reports)
{
BlendFileData *bfd;
@@ -439,14 +483,57 @@ int BKE_read_file_from_memfile(bContext *C, MemFile *memfile, ReportList *report
BlendFileData *bfd;
bfd = BLO_read_from_memfile(CTX_data_main(C), G.main->name, memfile, reports);
- if (bfd)
+ if (bfd) {
+ /* remove the unused screens and wm */
+ while (bfd->main->wm.first)
+ BKE_libblock_free(&bfd->main->wm, bfd->main->wm.first);
+ while (bfd->main->screen.first)
+ BKE_libblock_free(&bfd->main->screen, bfd->main->screen.first);
+
setup_app_data(C, bfd, "<memory1>");
+ }
else
BKE_reports_prepend(reports, "Loading failed: ");
return (bfd ? 1 : 0);
}
+/* only read the userdef from a .blend */
+int BKE_read_file_userdef(const char *filepath, ReportList *reports)
+{
+ BlendFileData *bfd;
+ int retval = 0;
+
+ bfd = BLO_read_from_file(filepath, reports);
+ if (bfd->user) {
+ retval = BKE_READ_FILE_OK_USERPREFS;
+
+ /* only here free userdef themes... */
+ BKE_userdef_free();
+
+ U = *bfd->user;
+ MEM_freeN(bfd->user);
+ }
+ free_main(bfd->main);
+ MEM_freeN(bfd);
+
+ return retval;
+}
+
+/* only write the userdef in a .blend */
+int BKE_write_file_userdef(const char *filepath, ReportList *reports)
+{
+ Main *mainb = MEM_callocN(sizeof(Main), "empty main");
+ int retval = 0;
+
+ if (BLO_write_file(mainb, filepath, G_FILE_USERPREFS, reports, NULL)) {
+ retval = 1;
+ }
+
+ MEM_freeN(mainb);
+
+ return retval;
+}
/* ***************** testing for break ************* */
@@ -728,48 +815,39 @@ char *BKE_undo_menu_string(void)
return menu;
}
-/* saves quit.blend */
-void BKE_undo_save_quit(void)
+/* saves .blend using undo buffer, returns 1 == success */
+int BKE_undo_save_file(const char *filename)
{
UndoElem *uel;
MemFileChunk *chunk;
- char str[FILE_MAX];
const int flag = O_BINARY + O_WRONLY + O_CREAT + O_TRUNC + O_EXCL;
int file;
if ((U.uiflag & USER_GLOBALUNDO) == 0) {
- return;
+ return 0;
}
uel = curundo;
if (uel == NULL) {
fprintf(stderr, "No undo buffer to save recovery file\n");
- return;
- }
-
- /* no undo state to save */
- if (undobase.first == undobase.last) {
- return;
+ return 0;
}
- /* save the undo state as quit.blend */
- BLI_make_file_string("/", str, BLI_temporary_dir(), "quit.blend");
-
/* first try create the file, if it exists call without 'O_CREAT',
* to avoid writing to a symlink - use 'O_EXCL' (CVE-2008-1103) */
errno = 0;
- file = BLI_open(str, flag, 0666);
+ file = BLI_open(filename, flag, 0666);
if (file == -1) {
if (errno == EEXIST) {
errno = 0;
- file = BLI_open(str, flag & ~O_CREAT, 0666);
+ file = BLI_open(filename, flag & ~O_CREAT, 0666);
}
}
if (file == -1) {
fprintf(stderr, "Unable to save '%s': %s\n",
- str, errno ? strerror(errno) : "Unknown error opening file");
- return;
+ filename, errno ? strerror(errno) : "Unknown error opening file");
+ return 0;
}
for (chunk = uel->memfile.chunks.first; chunk; chunk = chunk->next) {
@@ -777,16 +855,15 @@ void BKE_undo_save_quit(void)
break;
}
}
-
+
close(file);
if (chunk) {
fprintf(stderr, "Unable to save '%s': %s\n",
- str, errno ? strerror(errno) : "Unknown error writing file");
- }
- else {
- printf("Saved session recovery to '%s'\n", str);
+ filename, errno ? strerror(errno) : "Unknown error writing file");
+ return 0;
}
+ return 1;
}
/* sets curscene */
@@ -806,3 +883,132 @@ Main *BKE_undo_get_main(Scene **scene)
return mainp;
}
+/* ************** copy paste .blend, partial saves ********** */
+
+/* assumes data is in G.main */
+
+void BKE_copybuffer_begin(void)
+{
+ /* set all id flags to zero; */
+ flag_all_listbases_ids(LIB_NEED_EXPAND | LIB_DOIT, 0);
+}
+
+void BKE_copybuffer_tag_ID(ID *id)
+{
+ id->flag |= LIB_NEED_EXPAND | LIB_DOIT;
+}
+
+static void copybuffer_doit(void *UNUSED(handle), Main *UNUSED(bmain), void *vid)
+{
+ if (vid) {
+ ID *id = vid;
+ /* only tag for need-expand if not done, prevents eternal loops */
+ if ((id->flag & LIB_DOIT) == 0)
+ id->flag |= LIB_NEED_EXPAND | LIB_DOIT;
+ }
+}
+
+/* frees main in end */
+int BKE_copybuffer_save(const char *filename, ReportList *reports)
+{
+ Main *mainb = MEM_callocN(sizeof(Main), "copybuffer");
+ ListBase *lbarray[MAX_LIBARRAY], *fromarray[MAX_LIBARRAY];
+ int a, retval;
+
+ BLO_main_expander(copybuffer_doit);
+ BLO_expand_main(NULL, G.main);
+
+ /* move over all tagged blocks */
+ set_listbasepointers(G.main, fromarray);
+ a = set_listbasepointers(mainb, lbarray);
+ while (a--) {
+ ID *id, *nextid;
+ ListBase *lb1 = lbarray[a], *lb2 = fromarray[a];
+
+ for (id = lb2->first; id; id = nextid) {
+ nextid = id->next;
+ if (id->flag & LIB_DOIT) {
+ BLI_remlink(lb2, id);
+ BLI_addtail(lb1, id);
+ }
+ }
+ }
+
+
+ /* save the buffer */
+ retval = BLO_write_file(mainb, filename, 0, reports, NULL);
+
+ /* move back the main, now sorted again */
+ set_listbasepointers(G.main, lbarray);
+ a = set_listbasepointers(mainb, fromarray);
+ while (a--) {
+ ID *id;
+ ListBase *lb1 = lbarray[a], *lb2 = fromarray[a];
+
+ while (lb2->first) {
+ id = lb2->first;
+ BLI_remlink(lb2, id);
+ BLI_addtail(lb1, id);
+ id_sort_by_name(lb1, id);
+ }
+ }
+
+ MEM_freeN(mainb);
+
+ /* set id flag to zero; */
+ flag_all_listbases_ids(LIB_NEED_EXPAND | LIB_DOIT, 0);
+
+ return retval;
+}
+
+/* return success (1) */
+int BKE_copybuffer_paste(bContext *C, const char *libname, ReportList *reports)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Main *mainl = NULL;
+ Library *lib;
+ BlendHandle *bh;
+
+ bh = BLO_blendhandle_from_file(libname, reports);
+
+ if (bh == NULL) {
+ /* error reports will have been made by BLO_blendhandle_from_file() */
+ return 0;
+ }
+
+ 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 flag_all_listbases_ids(LIB_LINK_TAG, 0) is called after! */
+ flag_all_listbases_ids(LIB_PRE_EXISTING, 1);
+
+ /* here appending/linking starts */
+ mainl = BLO_library_append_begin(bmain, &bh, libname);
+
+ BLO_library_append_all(mainl, bh);
+
+ BLO_library_append_end(C, mainl, &bh, 0, 0);
+
+ /* mark all library linked objects to be updated */
+ recalc_all_library_objects(bmain);
+ IMB_colormanagement_check_file_config(bmain);
+
+ /* append, rather than linking */
+ lib = BLI_findstring(&bmain->library, libname, offsetof(Library, filepath));
+ BKE_library_make_local(bmain, lib, true);
+
+ /* important we unset, otherwise these object wont
+ * link into other scenes from this blend file */
+ flag_all_listbases_ids(LIB_PRE_EXISTING, 0);
+
+ /* recreate dependency graph to include new objects */
+ DAG_relations_tag_update(bmain);
+
+ BLO_blendhandle_close(bh);
+ /* remove library... */
+
+ return 1;
+}
diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c
index 0495e729937..78da4f5b1c2 100644
--- a/source/blender/blenkernel/intern/bmfont.c
+++ b/source/blender/blenkernel/intern/bmfont.c
@@ -56,7 +56,7 @@
#include "BKE_bmfont.h"
#include "BKE_bmfont_types.h"
-void printfGlyph(bmGlyph * glyph)
+void printfGlyph(bmGlyph *glyph)
{
printf("unicode: %d '%c'\n", glyph->unicode, glyph->unicode);
printf(" locx: %4d locy: %4d\n", glyph->locx, glyph->locy);
@@ -65,10 +65,10 @@ void printfGlyph(bmGlyph * glyph)
printf(" advan: %3d reser: %3d\n", glyph->advance, glyph->reserved);
}
-#define MAX2(x,y) ((x) > (y) ? (x) : (y))
-#define MAX3(x,y,z) MAX2(MAX2((x), (y)), (z))
+#define MAX2(x, y) ((x) > (y) ? (x) : (y))
+#define MAX3(x, y, z) (MAX2(MAX2((x), (y)), (z)))
-void calcAlpha(ImBuf * ibuf)
+void calcAlpha(ImBuf *ibuf)
{
int i;
char * rect;
@@ -82,7 +82,7 @@ void calcAlpha(ImBuf * ibuf)
}
}
-void readBitmapFontVersion0(ImBuf * ibuf, unsigned char * rect, int step)
+void readBitmapFontVersion0(ImBuf *ibuf, unsigned char *rect, int step)
{
int glyphcount, bytes, i, index, linelength, ysize;
unsigned char * buffer;
@@ -198,7 +198,7 @@ void detectBitmapFont(ImBuf *ibuf)
readBitmapFontVersion0(ibuf, rect, 4);
}
else {
- printf("detectBitmapFont :Unsupported version %d\n", version);
+ printf("detectBitmapFont :Unsupported version %d\n", (int)version);
}
/* on succes ibuf->userdata points to the bitmapfont */
diff --git a/source/blender/blenkernel/intern/booleanops_mesh.c b/source/blender/blenkernel/intern/booleanops_mesh.c
index 461b945282f..f53a89fccfd 100644
--- a/source/blender/blenkernel/intern/booleanops_mesh.c
+++ b/source/blender/blenkernel/intern/booleanops_mesh.c
@@ -56,7 +56,7 @@ CSG_DestroyBlenderMeshInternals(
CSG_MeshDescriptor *mesh
) {
/* Free face and vertex iterators. */
- FreeMeshDescriptors(&(mesh->m_face_iterator),&(mesh->m_vertex_iterator));
+ FreeMeshDescriptors(&(mesh->m_face_iterator), &(mesh->m_vertex_iterator));
}
@@ -138,7 +138,7 @@ CSG_AddMeshToBlender(
if (mesh == NULL) return 0;
if (mesh->base == NULL) return 0;
- invert_m4_m4(inv_mat,mesh->base->object->obmat);
+ invert_m4_m4(inv_mat, mesh->base->object->obmat);
/* Create a new blender mesh object - using 'base' as
* a template for the new object. */
@@ -191,7 +191,7 @@ CSG_PerformOp(
default : op_type = e_csg_intersection;
}
- output->m_descriptor = CSG_DescibeOperands(bool_op,mesh1->m_descriptor,mesh2->m_descriptor);
+ output->m_descriptor = CSG_DescibeOperands(bool_op, mesh1->m_descriptor, mesh2->m_descriptor);
output->base = mesh1->base;
if (output->m_descriptor.user_face_vertex_data_size) {
@@ -228,8 +228,8 @@ CSG_PerformOp(
/* get the ouput mesh descriptors. */
- CSG_OutputFaceDescriptor(bool_op,&(output->m_face_iterator));
- CSG_OutputVertexDescriptor(bool_op,&(output->m_vertex_iterator));
+ CSG_OutputFaceDescriptor(bool_op, &(output->m_face_iterator));
+ CSG_OutputVertexDescriptor(bool_op, &(output->m_vertex_iterator));
output->m_destroy_func = CSG_DestroyCSGMeshInternals;
return 1;
@@ -242,20 +242,20 @@ NewBooleanMeshTest(
int op_type
) {
- CSG_MeshDescriptor m1,m2,output;
- CSG_MeshDescriptor output2,output3;
+ CSG_MeshDescriptor m1, m2, output;
+ CSG_MeshDescriptor output2, output3;
- if (!MakeCSGMeshFromBlenderBase(base,&m1)) {
+ if (!MakeCSGMeshFromBlenderBase(base, &m1)) {
return 0;
}
- if (!MakeCSGMeshFromBlenderBase(base_select,&m2)) {
+ if (!MakeCSGMeshFromBlenderBase(base_select, &m2)) {
return 0;
}
- CSG_PerformOp(&m1,&m2,1,&output);
- CSG_PerformOp(&m1,&m2,2,&output2);
- CSG_PerformOp(&m1,&m2,3,&output3);
+ CSG_PerformOp(&m1, &m2, 1, &output);
+ CSG_PerformOp(&m1, &m2, 2, &output2);
+ CSG_PerformOp(&m1, &m2, 3, &output3);
if (!CSG_AddMeshToBlender(&output)) {
return 0;
diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index c650438a31e..852dcc6216c 100644
--- a/source/blender/blenlib/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -25,7 +25,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/blenlib/intern/bpath.c
+/** \file blender/blenkernel/intern/bpath.c
* \ingroup bli
*/
@@ -70,9 +70,9 @@
#include "DNA_vfont_types.h"
#include "DNA_scene_types.h"
#include "DNA_smoke_types.h"
+#include "DNA_freestyle_types.h"
#include "BLI_blenlib.h"
-#include "BLI_bpath.h"
#include "BLI_utildefines.h"
#include "BKE_font.h"
@@ -83,6 +83,8 @@
#include "BKE_sequencer.h"
#include "BKE_image.h" /* so we can check the image's type */
+#include "BKE_bpath.h" /* own include */
+
static int checkMissingFiles_visit_cb(void *userdata, char *UNUSED(path_dst), const char *path_src)
{
ReportList *reports = (ReportList *)userdata;
@@ -95,9 +97,9 @@ static int checkMissingFiles_visit_cb(void *userdata, char *UNUSED(path_dst), co
}
/* high level function */
-void BLI_bpath_missing_files_check(Main *bmain, ReportList *reports)
+void BKE_bpath_missing_files_check(Main *bmain, ReportList *reports)
{
- BLI_bpath_traverse_main(bmain, checkMissingFiles_visit_cb, BLI_BPATH_TRAVERSE_ABS, reports);
+ BKE_bpath_traverse_main(bmain, checkMissingFiles_visit_cb, BKE_BPATH_TRAVERSE_ABS, reports);
}
typedef struct BPathRemap_Data {
@@ -132,7 +134,7 @@ static int makeFilesRelative_visit_cb(void *userdata, char *path_dst, const char
}
}
-void BLI_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *reports)
+void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *reports)
{
BPathRemap_Data data = {NULL};
@@ -144,7 +146,7 @@ void BLI_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *re
data.basedir = basedir;
data.reports = reports;
- BLI_bpath_traverse_main(bmain, makeFilesRelative_visit_cb, 0, (void *)&data);
+ BKE_bpath_traverse_main(bmain, makeFilesRelative_visit_cb, 0, (void *)&data);
BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO,
"Total files %d | Changed %d | Failed %d",
@@ -174,8 +176,8 @@ static int makeFilesAbsolute_visit_cb(void *userdata, char *path_dst, const char
}
}
-/* similar to BLI_bpath_relative_convert - keep in sync! */
-void BLI_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports)
+/* similar to BKE_bpath_relative_convert - keep in sync! */
+void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports)
{
BPathRemap_Data data = {NULL};
@@ -187,7 +189,7 @@ void BLI_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *re
data.basedir = basedir;
data.reports = reports;
- BLI_bpath_traverse_main(bmain, makeFilesAbsolute_visit_cb, 0, (void *)&data);
+ BKE_bpath_traverse_main(bmain, makeFilesAbsolute_visit_cb, 0, (void *)&data);
BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO,
"Total files %d | Changed %d | Failed %d",
@@ -298,14 +300,14 @@ static int findMissingFiles_visit_cb(void *userdata, char *path_dst, const char
}
}
-void BLI_bpath_missing_files_find(Main *bmain, const char *searchpath, ReportList *reports)
+void BKE_bpath_missing_files_find(Main *bmain, const char *searchpath, ReportList *reports)
{
struct BPathFind_Data data = {NULL};
data.reports = reports;
BLI_split_dir_part(searchpath, data.searchdir, sizeof(data.searchdir));
- BLI_bpath_traverse_main(bmain, findMissingFiles_visit_cb, 0, (void *)&data);
+ BKE_bpath_traverse_main(bmain, findMissingFiles_visit_cb, 0, (void *)&data);
}
/* Run a visitor on a string, replacing the contents of the string as needed. */
@@ -383,11 +385,11 @@ static int rewrite_path_alloc(char **path, BPathVisitor visit_cb, const char *ab
}
/* Run visitor function 'visit' on all paths contained in 'id'. */
-void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
+void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
{
- const char *absbase = (flag & BLI_BPATH_TRAVERSE_ABS) ? ID_BLEND_PATH(bmain, id) : NULL;
+ const char *absbase = (flag & BKE_BPATH_TRAVERSE_ABS) ? ID_BLEND_PATH(bmain, id) : NULL;
- if ((flag & BLI_BPATH_TRAVERSE_SKIP_LIBRARY) && id->lib) {
+ if ((flag & BKE_BPATH_TRAVERSE_SKIP_LIBRARY) && id->lib) {
return;
}
@@ -396,7 +398,7 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
{
Image *ima;
ima = (Image *)id;
- if (ima->packedfile == NULL || (flag & BLI_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
+ if (ima->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
if (ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
rewrite_path_fixed(ima->name, visit_cb, absbase, bpath_user_data);
}
@@ -458,6 +460,10 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
OceanModifierData *omd = (OceanModifierData *) md;
rewrite_path_fixed(omd->cachepath, visit_cb, absbase, bpath_user_data);
}
+ else if (md->type == eModifierType_MeshCache) {
+ MeshCacheModifierData *mcmd = (MeshCacheModifierData *) md;
+ rewrite_path_fixed(mcmd->filepath, visit_cb, absbase, bpath_user_data);
+ }
}
if (ob->soft) {
@@ -475,7 +481,7 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
case ID_SO:
{
bSound *sound = (bSound *)id;
- if (sound->packedfile == NULL || (flag & BLI_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
+ if (sound->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
rewrite_path_fixed(sound->name, visit_cb, absbase, bpath_user_data);
}
break;
@@ -488,7 +494,7 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
case ID_VF:
{
VFont *vfont = (VFont *)id;
- if (vfont->packedfile == NULL || (flag & BLI_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
+ if (vfont->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
if (BKE_vfont_is_builtin(vfont) == FALSE) {
rewrite_path_fixed(((VFont *)id)->name, visit_cb, absbase, bpath_user_data);
}
@@ -555,7 +561,7 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
int len = MEM_allocN_len(se) / sizeof(*se);
int i;
- if (flag & BLI_BPATH_TRAVERSE_SKIP_MULTIFILE) {
+ if (flag & BKE_BPATH_TRAVERSE_SKIP_MULTIFILE) {
/* only operate on one path */
len = MIN2(1, len);
}
@@ -574,6 +580,16 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
}
SEQ_END
}
+ {
+ SceneRenderLayer *srl = scene->r.layers.first;
+
+ for(; srl; srl = srl->next) {
+ FreestyleModuleConfig* module = srl->freestyleConfig.modules.first;
+ for (; module; module = module->next) {
+ rewrite_path_fixed(module->module_path, visit_cb, absbase, bpath_user_data);
+ }
+ }
+ }
break;
}
case ID_ME:
@@ -587,8 +603,11 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
case ID_LI:
{
Library *lib = (Library *)id;
- if (rewrite_path_fixed(lib->name, visit_cb, absbase, bpath_user_data)) {
- BKE_library_filepath_set(lib, lib->name);
+ /* keep packedfile paths always relative to the blend */
+ if (lib->packedfile == NULL) {
+ if (rewrite_path_fixed(lib->name, visit_cb, absbase, bpath_user_data)) {
+ BKE_library_filepath_set(lib, lib->name);
+ }
}
break;
}
@@ -604,26 +623,26 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
}
}
-void BLI_bpath_traverse_id_list(Main *bmain, ListBase *lb, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
+void BKE_bpath_traverse_id_list(Main *bmain, ListBase *lb, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
{
ID *id;
for (id = lb->first; id; id = id->next) {
- BLI_bpath_traverse_id(bmain, id, visit_cb, flag, bpath_user_data);
+ BKE_bpath_traverse_id(bmain, id, visit_cb, flag, bpath_user_data);
}
}
-void BLI_bpath_traverse_main(Main *bmain, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
+void BKE_bpath_traverse_main(Main *bmain, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
{
ListBase *lbarray[MAX_LIBARRAY];
int a = set_listbasepointers(bmain, lbarray);
while (a--) {
- BLI_bpath_traverse_id_list(bmain, lbarray[a], visit_cb, flag, bpath_user_data);
+ BKE_bpath_traverse_id_list(bmain, lbarray[a], visit_cb, flag, bpath_user_data);
}
}
/* Rewrites a relative path to be relative to the main file - unless the path is
* absolute, in which case it is not altered. */
-int BLI_bpath_relocate_visitor(void *pathbase_v, char *path_dst, const char *path_src)
+int BKE_bpath_relocate_visitor(void *pathbase_v, char *path_dst, const char *path_src)
{
/* be sure there is low chance of the path being too short */
char filepath[(FILE_MAXDIR * 2) + FILE_MAXFILE];
@@ -663,14 +682,14 @@ int BLI_bpath_relocate_visitor(void *pathbase_v, char *path_dst, const char *pat
struct PathStore {
struct PathStore *next, *prev;
-} PathStore;
+};
static int bpath_list_append(void *userdata, char *UNUSED(path_dst), const char *path_src)
{
/* store the path and string in a single alloc */
ListBase *ls = userdata;
size_t path_size = strlen(path_src) + 1;
- struct PathStore *path_store = MEM_mallocN(sizeof(PathStore) + path_size, __func__);
+ struct PathStore *path_store = MEM_mallocN(sizeof(struct PathStore) + path_size, __func__);
char *filepath = (char *)(path_store + 1);
memcpy(filepath, path_src, path_size);
@@ -700,23 +719,23 @@ static int bpath_list_restore(void *userdata, char *path_dst, const char *path_s
}
/* return ls_handle */
-void *BLI_bpath_list_backup(Main *bmain, const int flag)
+void *BKE_bpath_list_backup(Main *bmain, const int flag)
{
ListBase *ls = MEM_callocN(sizeof(ListBase), __func__);
- BLI_bpath_traverse_main(bmain, bpath_list_append, flag, ls);
+ BKE_bpath_traverse_main(bmain, bpath_list_append, flag, ls);
return ls;
}
-void BLI_bpath_list_restore(Main *bmain, const int flag, void *ls_handle)
+void BKE_bpath_list_restore(Main *bmain, const int flag, void *ls_handle)
{
ListBase *ls = ls_handle;
- BLI_bpath_traverse_main(bmain, bpath_list_restore, flag, ls);
+ BKE_bpath_traverse_main(bmain, bpath_list_restore, flag, ls);
}
-void BLI_bpath_list_free(void *ls_handle)
+void BKE_bpath_list_free(void *ls_handle)
{
ListBase *ls = ls_handle;
BLI_assert(ls->first == NULL); /* assumes we were used */
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index f310895f590..d6cd7290038 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -29,27 +29,15 @@
* \ingroup bke
*/
-
-#include <math.h>
-#include <string.h>
-
#include "MEM_guardedalloc.h"
#include "DNA_brush_types.h"
-#include "DNA_color_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
-#include "DNA_windowmanager_types.h"
-
-#include "WM_types.h"
-#include "RNA_access.h"
-
-#include "BLI_bpath.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_rand.h"
-#include "BLI_utildefines.h"
#include "BKE_brush.h"
#include "BKE_colortools.h"
@@ -67,6 +55,20 @@
#include "RE_render_ext.h" /* externtex */
#include "RE_shader_ext.h"
+static RNG *brush_rng;
+
+void BKE_brush_system_init(void)
+{
+ brush_rng = BLI_rng_new(0);
+ BLI_rng_srandom(brush_rng, 31415682);
+}
+
+void BKE_brush_system_exit(void)
+{
+ BLI_rng_free(brush_rng);
+}
+
+
static void brush_defaults(Brush *brush)
{
brush->blend = 0;
@@ -122,11 +124,11 @@ static void brush_defaults(Brush *brush)
/* Datablock add/copy/free/make_local */
-Brush *BKE_brush_add(const char *name)
+Brush *BKE_brush_add(Main *bmain, const char *name)
{
Brush *brush;
- brush = BKE_libblock_alloc(&G.main->brush, ID_BR, name);
+ brush = BKE_libblock_alloc(&bmain->brush, ID_BR, name);
/* enable fake user by default */
brush->id.flag |= LIB_FAKEUSER;
@@ -272,7 +274,6 @@ void BKE_brush_debug_print_state(Brush *br)
BR_TEST_FLAG(BRUSH_SIZE_PRESSURE);
BR_TEST_FLAG(BRUSH_JITTER_PRESSURE);
BR_TEST_FLAG(BRUSH_SPACING_PRESSURE);
- BR_TEST_FLAG(BRUSH_FIXED_TEX);
BR_TEST_FLAG(BRUSH_RAKE);
BR_TEST_FLAG(BRUSH_ANCHORED);
BR_TEST_FLAG(BRUSH_DIR_IN);
@@ -433,7 +434,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("Tex");
+ else idtest = (ID *)add_texture(G.main, "Tex");
idtest->us--;
}
if (idtest != id) {
@@ -485,21 +486,133 @@ int BKE_brush_clone_image_delete(Brush *brush)
return 0;
}
-/* Brush Sampling */
-void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float xy[2], float rgba[4], const int thread)
+/* Generic texture sampler for 3D painting systems. point has to be either in
+ * region space mouse coordinates, or 3d world coordinates for 3D mapping */
+float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br,
+ const float point[3],
+ float rgba[4], const int thread,
+ struct ImagePool *pool)
+{
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+ MTex *mtex = &br->mtex;
+ float intensity = 1.0;
+ bool hasrgb = false;
+
+ if (!mtex->tex) {
+ intensity = 1;
+ }
+ else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
+ /* 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);
+ }
+ else {
+ float rotation = -mtex->rot;
+ float point_2d[2] = {point[0], point[1]};
+ float x = 0.0f, y = 0.0f; /* Quite warnings */
+ float radius = 1.0f; /* Quite warnings */
+ float co[3];
+
+ if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
+ /* keep coordinates relative to mouse */
+
+ rotation += ups->brush_rotation;
+
+ point_2d[0] -= ups->tex_mouse[0];
+ point_2d[1] -= ups->tex_mouse[1];
+
+ /* use pressure adjusted size for fixed mode */
+ radius = ups->pixel_radius;
+
+ x = point_2d[0];
+ y = point_2d[1];
+ }
+ else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) {
+ /* leave the coordinates relative to the screen */
+
+ /* use unadjusted size for tiled mode */
+ radius = BKE_brush_size_get(scene, br);
+
+ x = point_2d[0];
+ y = point_2d[1];
+ }
+
+ x /= radius;
+ y /= radius;
+
+ /* it is probably worth optimizing for those cases where
+ * the texture is not rotated by skipping the calls to
+ * atan2, sqrtf, sin, and cos. */
+ if (rotation > 0.001f || rotation < -0.001f) {
+ const float angle = atan2f(y, x) + rotation;
+ const float flen = sqrtf(x * x + y * y);
+
+ x = flen * cosf(angle);
+ y = flen * sinf(angle);
+ }
+
+ x *= br->mtex.size[0];
+ y *= br->mtex.size[1];
+
+ co[0] = x + br->mtex.ofs[0];
+ co[1] = y + br->mtex.ofs[1];
+ co[2] = 0.0f;
+
+ hasrgb = externtex(mtex, co, &intensity,
+ rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
+ }
+
+ intensity += br->texture_sample_bias;
+
+ if (!hasrgb) {
+ rgba[0] = intensity;
+ rgba[1] = intensity;
+ rgba[2] = intensity;
+ rgba[3] = 1.0f;
+ }
+
+ return intensity;
+}
+
+
+/* Brush Sampling for 2D brushes. when we unify the brush systems this will be necessarily a separate function */
+float BKE_brush_sample_tex_2D(const Scene *scene, Brush *brush, const float xy[2], float rgba[4])
{
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
MTex *mtex = &brush->mtex;
if (mtex && mtex->tex) {
float co[3], tin, tr, tg, tb, ta;
+ float x = xy[0], y = xy[1];
int hasrgb;
- const int radius = BKE_brush_size_get(scene, brush);
+ int radius = BKE_brush_size_get(scene, brush);
+ float rotation = -mtex->rot;
+
+ if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
+ rotation += ups->brush_rotation;
+ radius = ups->pixel_radius;
+ }
+
+ x /= radius;
+ y /= radius;
+
+ if (rotation > 0.001f || rotation < -0.001f) {
+ const float angle = atan2f(y, x) + rotation;
+ const float flen = sqrtf(x * x + y * y);
+
+ x = flen * cosf(angle);
+ y = flen * sinf(angle);
+ }
+
+ x *= brush->mtex.size[0];
+ y *= brush->mtex.size[1];
- co[0] = xy[0] / radius;
- co[1] = xy[1] / radius;
+ co[0] = x + brush->mtex.ofs[0];
+ co[1] = y + brush->mtex.ofs[1];
co[2] = 0.0f;
- hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread);
+ hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, 0, NULL);
if (hasrgb) {
rgba[0] = tr;
@@ -513,13 +626,16 @@ void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float xy[2], f
rgba[2] = tin;
rgba[3] = 1.0f;
}
+ return tin;
}
else {
rgba[0] = rgba[1] = rgba[2] = rgba[3] = 1.0f;
+ return 1.0;
}
}
-/* TODO, use define for 'texfall' arg */
+/* TODO, use define for 'texfall' arg
+ * NOTE: only used for 2d brushes currently! */
void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf, int use_color_correction)
{
ImBuf *ibuf;
@@ -558,13 +674,18 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf
dstf[3] = alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);
}
else if (texfall == 1) {
- BKE_brush_sample_tex(scene, brush, xy, dstf, 0);
+ BKE_brush_sample_tex_2D(scene, brush, xy, dstf);
}
- else {
- BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
+ else if (texfall == 2) {
+ BKE_brush_sample_tex_2D(scene, brush, xy, rgba);
mul_v3_v3v3(dstf, rgba, brush_rgb);
dstf[3] = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);
}
+ else {
+ BKE_brush_sample_tex_2D(scene, brush, xy, rgba);
+ copy_v3_v3(dstf, brush_rgb);
+ dstf[3] = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);
+ }
}
}
}
@@ -588,11 +709,11 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf
dst[3] = FTOCHAR(alpha_f);
}
else if (texfall == 1) {
- BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
+ BKE_brush_sample_tex_2D(scene, brush, xy, rgba);
rgba_float_to_uchar(dst, rgba);
}
else if (texfall == 2) {
- BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
+ BKE_brush_sample_tex_2D(scene, brush, xy, rgba);
mul_v3_v3(rgba, brush->rgb);
alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);
@@ -601,7 +722,7 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf
dst[3] = FTOCHAR(alpha_f);
}
else {
- BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
+ BKE_brush_sample_tex_2D(scene, brush, xy, rgba);
alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius);
dst[0] = crgb[0];
@@ -628,13 +749,15 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf
* available. my ussual solution to this is to use the
* ratio of change of the size to change the unprojected
* radius. Not completely convinced that is correct.
- * In anycase, a better solution is needed to prevent
+ * In any case, a better solution is needed to prevent
* inconsistency. */
void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
-
+
+ size = (int)((float)size / U.pixelsize);
+
if (ups->flag & UNIFIED_PAINT_SIZE)
ups->size = size;
else
@@ -644,8 +767,9 @@ void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
int BKE_brush_size_get(const Scene *scene, Brush *brush)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
-
- return (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size;
+ int size = (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size;
+
+ return (int)((float)size * U.pixelsize);
}
int BKE_brush_use_locked_size(const Scene *scene, Brush *brush)
@@ -694,7 +818,7 @@ float BKE_brush_unprojected_radius_get(const Scene *scene, Brush *brush)
brush->unprojected_radius;
}
-static void brush_alpha_set(Scene *scene, Brush *brush, float alpha)
+void BKE_brush_alpha_set(Scene *scene, Brush *brush, float alpha)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
@@ -752,318 +876,10 @@ void BKE_brush_scale_size(int *r_brush_size,
(*r_brush_size) = (int)((float)(*r_brush_size) * scale);
}
-/* Brush Painting */
-
-typedef struct BrushPainterCache {
- short enabled;
-
- int size; /* size override, if 0 uses 2*BKE_brush_size_get(brush) */
- short flt; /* need float imbuf? */
- short texonly; /* no alpha, color or fallof, only texture in imbuf */
-
- int lastsize;
- float lastalpha;
- float lastjitter;
-
- ImBuf *ibuf;
- ImBuf *texibuf;
- ImBuf *maskibuf;
-} BrushPainterCache;
-
-struct BrushPainter {
- Scene *scene;
- Brush *brush;
-
- float lastmousepos[2]; /* mouse position of last paint call */
-
- float accumdistance; /* accumulated distance of brush since last paint op */
- float lastpaintpos[2]; /* position of last paint op */
- float startpaintpos[2]; /* position of first paint */
-
- double accumtime; /* accumulated time since last paint op (airbrush) */
- double lasttime; /* time of last update */
-
- float lastpressure;
-
- short firsttouch; /* first paint op */
-
- float startsize;
- float startalpha;
- float startjitter;
- float startspacing;
-
- BrushPainterCache cache;
-};
-
-BrushPainter *BKE_brush_painter_new(Scene *scene, Brush *brush)
-{
- BrushPainter *painter = MEM_callocN(sizeof(BrushPainter), "BrushPainter");
-
- painter->brush = brush;
- painter->scene = scene;
- painter->firsttouch = 1;
- painter->cache.lastsize = -1; /* force ibuf create in refresh */
-
- painter->startsize = BKE_brush_size_get(scene, brush);
- painter->startalpha = BKE_brush_alpha_get(scene, brush);
- painter->startjitter = brush->jitter;
- painter->startspacing = brush->spacing;
-
- return painter;
-}
-
-void BKE_brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly, int size)
-{
- if ((painter->cache.flt != flt) || (painter->cache.size != size) ||
- ((painter->cache.texonly != texonly) && texonly))
- {
- if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
- if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
- painter->cache.ibuf = painter->cache.maskibuf = NULL;
- painter->cache.lastsize = -1; /* force ibuf create in refresh */
- }
-
- if (painter->cache.flt != flt) {
- if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
- painter->cache.texibuf = NULL;
- painter->cache.lastsize = -1; /* force ibuf create in refresh */
- }
-
- painter->cache.size = size;
- painter->cache.flt = flt;
- painter->cache.texonly = texonly;
- painter->cache.enabled = 1;
-}
-
-void BKE_brush_painter_free(BrushPainter *painter)
-{
- Brush *brush = painter->brush;
-
- BKE_brush_size_set(painter->scene, brush, painter->startsize);
- brush_alpha_set(painter->scene, brush, painter->startalpha);
- brush->jitter = painter->startjitter;
- brush->spacing = painter->startspacing;
-
- if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
- if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
- if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
- MEM_freeN(painter);
-}
-
-static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf,
- int x, int y, int w, int h, int xt, int yt,
- const float pos[2])
-{
- Scene *scene = painter->scene;
- Brush *brush = painter->brush;
- ImBuf *ibuf, *maskibuf, *texibuf;
- float *bf, *mf, *tf, *otf = NULL, xoff, yoff, xy[2], rgba[4];
- unsigned char *b, *m, *t, *ot = NULL;
- int dotexold, origx = x, origy = y;
- const int radius = BKE_brush_size_get(painter->scene, brush);
-
- xoff = -radius + 0.5f;
- yoff = -radius + 0.5f;
- xoff += (int)pos[0] - (int)painter->startpaintpos[0];
- yoff += (int)pos[1] - (int)painter->startpaintpos[1];
-
- ibuf = painter->cache.ibuf;
- texibuf = painter->cache.texibuf;
- maskibuf = painter->cache.maskibuf;
-
- dotexold = (oldtexibuf != NULL);
-
- /* not sure if it's actually needed or it's a mistake in coords/sizes
- * calculation in brush_painter_fixed_tex_partial_update(), but without this
- * limitation memory gets corrupted at fast strokes with quite big spacing (sergey) */
- w = min_ii(w, ibuf->x);
- h = min_ii(h, ibuf->y);
-
- if (painter->cache.flt) {
- for (; y < h; y++) {
- bf = ibuf->rect_float + (y * ibuf->x + origx) * 4;
- tf = texibuf->rect_float + (y * texibuf->x + origx) * 4;
- mf = maskibuf->rect_float + (y * maskibuf->x + origx) * 4;
-
- if (dotexold)
- otf = oldtexibuf->rect_float + ((y - origy + yt) * oldtexibuf->x + xt) * 4;
-
- for (x = origx; x < w; x++, bf += 4, mf += 4, tf += 4) {
- if (dotexold) {
- copy_v3_v3(tf, otf);
- tf[3] = otf[3];
- otf += 4;
- }
- else {
- xy[0] = x + xoff;
- xy[1] = y + yoff;
-
- BKE_brush_sample_tex(scene, brush, xy, tf, 0);
- }
-
- bf[0] = tf[0] * mf[0];
- bf[1] = tf[1] * mf[1];
- bf[2] = tf[2] * mf[2];
- bf[3] = tf[3] * mf[3];
- }
- }
- }
- else {
- for (; y < h; y++) {
- b = (unsigned char *)ibuf->rect + (y * ibuf->x + origx) * 4;
- t = (unsigned char *)texibuf->rect + (y * texibuf->x + origx) * 4;
- m = (unsigned char *)maskibuf->rect + (y * maskibuf->x + origx) * 4;
-
- if (dotexold)
- ot = (unsigned char *)oldtexibuf->rect + ((y - origy + yt) * oldtexibuf->x + xt) * 4;
-
- for (x = origx; x < w; x++, b += 4, m += 4, t += 4) {
- if (dotexold) {
- t[0] = ot[0];
- t[1] = ot[1];
- t[2] = ot[2];
- t[3] = ot[3];
- ot += 4;
- }
- else {
- xy[0] = x + xoff;
- xy[1] = y + yoff;
-
- BKE_brush_sample_tex(scene, brush, xy, rgba, 0);
- rgba_float_to_uchar(t, rgba);
- }
-
- b[0] = t[0] * m[0] / 255;
- b[1] = t[1] * m[1] / 255;
- b[2] = t[2] * m[2] / 255;
- b[3] = t[3] * m[3] / 255;
- }
- }
- }
-}
-
-static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, const float pos[2])
-{
- const Scene *scene = painter->scene;
- Brush *brush = painter->brush;
- BrushPainterCache *cache = &painter->cache;
- ImBuf *oldtexibuf, *ibuf;
- int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
- const int diameter = 2 * BKE_brush_size_get(scene, brush);
-
- imbflag = (cache->flt) ? IB_rectfloat : IB_rect;
- if (!cache->ibuf)
- cache->ibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
- ibuf = cache->ibuf;
-
- oldtexibuf = cache->texibuf;
- cache->texibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
-
- if (oldtexibuf) {
- srcx = srcy = 0;
- destx = (int)painter->lastpaintpos[0] - (int)pos[0];
- desty = (int)painter->lastpaintpos[1] - (int)pos[1];
- w = oldtexibuf->x;
- h = oldtexibuf->y;
-
- IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h);
- }
- else {
- srcx = srcy = 0;
- destx = desty = 0;
- w = h = 0;
- }
-
- x1 = destx;
- y1 = desty;
- x2 = destx + w;
- y2 = desty + h;
-
- /* blend existing texture in new position */
- if ((x1 < x2) && (y1 < y2))
- brush_painter_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos);
-
- if (oldtexibuf)
- IMB_freeImBuf(oldtexibuf);
-
- /* sample texture in new areas */
- if ((0 < x1) && (0 < ibuf->y))
- brush_painter_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos);
- if ((x2 < ibuf->x) && (0 < ibuf->y))
- brush_painter_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos);
- if ((x1 < x2) && (0 < y1))
- brush_painter_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos);
- if ((x1 < x2) && (y2 < ibuf->y))
- brush_painter_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos);
-}
-
-static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2], int use_color_correction)
-{
- const Scene *scene = painter->scene;
- Brush *brush = painter->brush;
- BrushPainterCache *cache = &painter->cache;
- MTex *mtex = &brush->mtex;
- int size;
- short flt;
- const int diameter = 2 * BKE_brush_size_get(scene, brush);
- const float alpha = BKE_brush_alpha_get(scene, brush);
-
- if (diameter != cache->lastsize ||
- alpha != cache->lastalpha ||
- brush->jitter != cache->lastjitter)
- {
- if (cache->ibuf) {
- IMB_freeImBuf(cache->ibuf);
- cache->ibuf = NULL;
- }
- if (cache->maskibuf) {
- IMB_freeImBuf(cache->maskibuf);
- cache->maskibuf = NULL;
- }
-
- flt = cache->flt;
- size = (cache->size) ? cache->size : diameter;
-
- if (brush->flag & BRUSH_FIXED_TEX) {
- BKE_brush_imbuf_new(scene, brush, flt, 3, size, &cache->maskibuf, use_color_correction);
- brush_painter_fixed_tex_partial_update(painter, pos);
- }
- else
- BKE_brush_imbuf_new(scene, brush, flt, 2, size, &cache->ibuf, use_color_correction);
-
- cache->lastsize = diameter;
- cache->lastalpha = alpha;
- cache->lastjitter = brush->jitter;
- }
- else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) {
- int dx = (int)painter->lastpaintpos[0] - (int)pos[0];
- int dy = (int)painter->lastpaintpos[1] - (int)pos[1];
-
- if ((dx != 0) || (dy != 0))
- brush_painter_fixed_tex_partial_update(painter, pos);
- }
-}
-
-void BKE_brush_painter_break_stroke(BrushPainter *painter)
-{
- painter->firsttouch = 1;
-}
-
-static void brush_pressure_apply(BrushPainter *painter, Brush *brush, float pressure)
-{
- if (BKE_brush_use_alpha_pressure(painter->scene, brush))
- brush_alpha_set(painter->scene, brush, max_ff(0.0f, painter->startalpha * pressure));
- if (BKE_brush_use_size_pressure(painter->scene, brush))
- BKE_brush_size_set(painter->scene, brush, max_ff(1.0f, painter->startsize * pressure));
- if (brush->flag & BRUSH_JITTER_PRESSURE)
- brush->jitter = max_ff(0.0f, painter->startjitter * pressure);
- if (brush->flag & BRUSH_SPACING_PRESSURE)
- brush->spacing = max_ff(1.0f, painter->startspacing * (1.5f - pressure));
-}
-
void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2], float jitterpos[2])
{
- int use_jitter = brush->jitter != 0;
+ int use_jitter = (brush->flag & BRUSH_ABSOLUTE_JITTER) ?
+ (brush->jitter_absolute != 0) : (brush->jitter != 0);
/* jitter-ed brush gives weird and unpredictable result for this
* kinds of stroke, so manually disable jitter usage (sergey) */
@@ -1071,180 +887,30 @@ void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2],
if (use_jitter) {
float rand_pos[2];
- const int radius = BKE_brush_size_get(scene, brush);
- const int diameter = 2 * radius;
+ float spread;
+ int diameter;
- /* find random position within a circle of diameter 1 */
do {
- rand_pos[0] = BLI_frand() - 0.5f;
- rand_pos[1] = BLI_frand() - 0.5f;
+ rand_pos[0] = BLI_rng_get_float(brush_rng) - 0.5f;
+ rand_pos[1] = BLI_rng_get_float(brush_rng) - 0.5f;
} while (len_v2(rand_pos) > 0.5f);
- jitterpos[0] = pos[0] + 2 * rand_pos[0] * diameter * brush->jitter;
- jitterpos[1] = pos[1] + 2 * rand_pos[1] * diameter * brush->jitter;
- }
- else {
- copy_v2_v2(jitterpos, pos);
- }
-}
-int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float pos[2], double time, float pressure,
- void *user, int use_color_correction)
-{
- Scene *scene = painter->scene;
- Brush *brush = painter->brush;
- int totpaintops = 0;
-
- if (pressure == 0.0f) {
- if (painter->lastpressure) // XXX - hack, operator misses
- pressure = painter->lastpressure;
- else
- pressure = 1.0f; /* zero pressure == not using tablet */
- }
- if (painter->firsttouch) {
- /* paint exactly once on first touch */
- painter->startpaintpos[0] = pos[0];
- painter->startpaintpos[1] = pos[1];
-
- brush_pressure_apply(painter, brush, pressure);
- if (painter->cache.enabled)
- brush_painter_refresh_cache(painter, pos, use_color_correction);
- totpaintops += func(user, painter->cache.ibuf, pos, pos);
-
- painter->lasttime = time;
- painter->firsttouch = 0;
- painter->lastpaintpos[0] = pos[0];
- painter->lastpaintpos[1] = pos[1];
- }
-#if 0
- else if (painter->brush->flag & BRUSH_AIRBRUSH) {
- float spacing, step, paintpos[2], dmousepos[2], len;
- double starttime, curtime = time;
-
- /* compute brush spacing adapted to brush size */
- spacing = brush->rate; //radius*brush->spacing*0.01f;
-
- /* setup starting time, direction vector and accumulated time */
- starttime = painter->accumtime;
- sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
- len = normalize_v2(dmousepos);
- painter->accumtime += curtime - painter->lasttime;
-
- /* do paint op over unpainted time distance */
- while (painter->accumtime >= spacing) {
- step = (spacing - starttime) * len;
- paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step;
- paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step;
-
- if (painter->cache.enabled)
- brush_painter_refresh_cache(painter);
- totpaintops += func(user, painter->cache.ibuf,
- painter->lastpaintpos, paintpos);
-
- painter->lastpaintpos[0] = paintpos[0];
- painter->lastpaintpos[1] = paintpos[1];
- painter->accumtime -= spacing;
- starttime -= spacing;
- }
-
- painter->lasttime = curtime;
- }
-#endif
- else {
- float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2];
- float t, len, press;
- const int radius = BKE_brush_size_get(scene, brush);
-
- /* compute brush spacing adapted to brush radius, spacing may depend
- * on pressure, so update it */
- brush_pressure_apply(painter, brush, painter->lastpressure);
- spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f;
-
- /* setup starting distance, direction vector and accumulated distance */
- startdistance = painter->accumdistance;
- sub_v2_v2v2(dmousepos, pos, painter->lastmousepos);
- len = normalize_v2(dmousepos);
- painter->accumdistance += len;
-
- if (brush->flag & BRUSH_SPACE) {
- /* do paint op over unpainted distance */
- while ((len > 0.0f) && (painter->accumdistance >= spacing)) {
- step = spacing - startdistance;
- paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step;
- paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step;
-
- t = step / len;
- press = (1.0f - t) * painter->lastpressure + t * pressure;
- brush_pressure_apply(painter, brush, press);
- spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f;
-
- BKE_brush_jitter_pos(scene, brush, paintpos, finalpos);
-
- if (painter->cache.enabled)
- brush_painter_refresh_cache(painter, finalpos, use_color_correction);
-
- totpaintops +=
- func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos);
-
- painter->lastpaintpos[0] = paintpos[0];
- painter->lastpaintpos[1] = paintpos[1];
- painter->accumdistance -= spacing;
- startdistance -= spacing;
- }
+ if (brush->flag & BRUSH_ABSOLUTE_JITTER) {
+ diameter = 2 * brush->jitter_absolute;
+ spread = 1.0;
}
else {
- BKE_brush_jitter_pos(scene, brush, pos, finalpos);
-
- if (painter->cache.enabled)
- brush_painter_refresh_cache(painter, finalpos, use_color_correction);
-
- totpaintops += func(user, painter->cache.ibuf, pos, finalpos);
-
- painter->lastpaintpos[0] = pos[0];
- painter->lastpaintpos[1] = pos[1];
- painter->accumdistance = 0;
- }
-
- /* do airbrush paint ops, based on the number of paint ops left over
- * from regular painting. this is a temporary solution until we have
- * accurate time stamps for mouse move events */
- if (brush->flag & BRUSH_AIRBRUSH) {
- double curtime = time;
- double painttime = brush->rate * totpaintops;
-
- painter->accumtime += curtime - painter->lasttime;
- if (painter->accumtime <= painttime)
- painter->accumtime = 0.0;
- else
- painter->accumtime -= painttime;
-
- while (painter->accumtime >= (double)brush->rate) {
- brush_pressure_apply(painter, brush, pressure);
-
- BKE_brush_jitter_pos(scene, brush, pos, finalpos);
-
- if (painter->cache.enabled)
- brush_painter_refresh_cache(painter, finalpos, use_color_correction);
-
- totpaintops +=
- func(user, painter->cache.ibuf, painter->lastmousepos, finalpos);
- painter->accumtime -= (double)brush->rate;
- }
-
- painter->lasttime = curtime;
+ diameter = 2 * BKE_brush_size_get(scene, brush);
+ spread = brush->jitter;
}
+ /* find random position within a circle of diameter 1 */
+ jitterpos[0] = pos[0] + 2 * rand_pos[0] * diameter * spread;
+ jitterpos[1] = pos[1] + 2 * rand_pos[1] * diameter * spread;
+ }
+ else {
+ copy_v2_v2(jitterpos, pos);
}
-
- painter->lastmousepos[0] = pos[0];
- painter->lastmousepos[1] = pos[1];
- painter->lastpressure = pressure;
-
- brush_alpha_set(scene, brush, painter->startalpha);
- BKE_brush_size_set(scene, brush, painter->startsize);
- brush->jitter = painter->startjitter;
- brush->spacing = painter->startspacing;
-
- return totpaintops;
}
/* Uses the brush curve control to find a strength value between 0 and 1 */
@@ -1281,7 +947,7 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side)
TexResult texres = {0};
int hasrgb, ix, iy;
int side = half_side * 2;
-
+
if (mtex->tex) {
float x, y, step = 2.0 / side, co[3];
@@ -1293,10 +959,10 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side)
co[0] = x;
co[1] = y;
co[2] = 0.0f;
-
+
/* This is copied from displace modifier code */
- hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres);
-
+ hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres, NULL);
+
/* if the texture gave an RGB value, we assume it didn't give a valid
* intensity, so calculate one (formula from do_material_tex).
* if the texture didn't give an RGB value, copy the intensity across
@@ -1315,6 +981,7 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side)
return texcache;
}
+
/**** Radial Control ****/
struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br)
{
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index ad828a70dd8..5028d978351 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -38,11 +38,11 @@
#include "BLI_utildefines.h"
#include "BLI_linklist.h"
+#include "BLI_math.h"
#include "BKE_DerivedMesh.h"
#include "BKE_tessmesh.h"
-#include "BLI_math.h"
#include "MEM_guardedalloc.h"
/* Math stuff for ray casting on mesh faces and for nearest surface */
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 57c88919021..ae1fa3025b9 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -50,11 +50,11 @@
/****************************** Camera Datablock *****************************/
-void *BKE_camera_add(const char *name)
+void *BKE_camera_add(Main *bmain, const char *name)
{
Camera *cam;
- cam = BKE_libblock_alloc(&G.main->camera, ID_CA, name);
+ cam = BKE_libblock_alloc(&bmain->camera, ID_CA, name);
cam->lens = 35.0f;
cam->sensor_x = DEFAULT_SENSOR_WIDTH;
@@ -237,6 +237,9 @@ void BKE_camera_params_from_object(CameraParams *params, Object *ob)
params->clipsta = la->clipsta;
params->clipend = la->clipend;
}
+ else {
+ params->lens = 35.0f;
+ }
}
void BKE_camera_params_from_view3d(CameraParams *params, View3D *v3d, RegionView3D *rv3d)
@@ -368,7 +371,7 @@ void BKE_camera_params_compute_matrix(CameraParams *params)
/***************************** Camera View Frame *****************************/
-void BKE_camera_view_frame_ex(Scene *scene, Camera *camera, float drawsize, const short do_clip, const float scale[3],
+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])
{
float facx, facy;
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 54bbe4bf495..0469e6ea787 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -40,12 +40,12 @@
#include "BLI_blenlib.h"
#include "BLI_edgehash.h"
#include "BLI_math.h"
-#include "BLI_pbvh.h"
#include "BLI_array.h"
#include "BLI_smallhash.h"
#include "BLI_utildefines.h"
#include "BLI_scanfill.h"
+#include "BKE_pbvh.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
@@ -215,7 +215,7 @@ static const MeshElemMap *cdDM_getPolyMap(Object *ob, DerivedMesh *dm)
if (!cddm->pmap && ob->type == OB_MESH) {
Mesh *me = ob->data;
- create_vert_poly_map(&cddm->pmap, &cddm->pmap_mem,
+ BKE_mesh_vert_poly_map_create(&cddm->pmap, &cddm->pmap_mem,
me->mpoly, me->mloop,
me->totvert, me->totpoly, me->totloop);
}
@@ -262,6 +262,17 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
cddm->pbvh_draw = can_pbvh_draw(ob, dm);
}
+ /* Sculpting on a BMesh (dynamic-topology) gets a special PBVH */
+ if (!cddm->pbvh && ob->sculpt->bm) {
+ cddm->pbvh = BKE_pbvh_new();
+ cddm->pbvh_draw = TRUE;
+
+ BKE_pbvh_build_bmesh(cddm->pbvh, ob->sculpt->bm,
+ ob->sculpt->bm_smooth_shading,
+ ob->sculpt->bm_log);
+ }
+
+
/* always build pbvh from original mesh, and only use it for drawing if
* this derivedmesh is just original mesh. it's the multires subsurf dm
* that this is actually for, to support a pbvh on a modified mesh */
@@ -270,14 +281,14 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
Mesh *me = ob->data;
int deformed = 0;
- cddm->pbvh = BLI_pbvh_new();
+ cddm->pbvh = BKE_pbvh_new();
cddm->pbvh_draw = can_pbvh_draw(ob, dm);
pbvh_show_diffuse_color_set(cddm->pbvh, ob->sculpt->show_diffuse_color);
BKE_mesh_tessface_ensure(me);
- BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
+ BKE_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
me->totface, me->totvert, &me->vdata);
deformed = ss->modifiers_active || me->key;
@@ -290,7 +301,7 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
totvert = deformdm->getNumVerts(deformdm);
vertCos = MEM_callocN(3 * totvert * sizeof(float), "cdDM_getPBVH vertCos");
deformdm->getVertCos(deformdm, vertCos);
- BLI_pbvh_apply_vertCos(cddm->pbvh, vertCos);
+ BKE_pbvh_apply_vertCos(cddm->pbvh, vertCos);
MEM_freeN(vertCos);
}
}
@@ -310,7 +321,7 @@ static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
- BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors);
+ BKE_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors);
}
static void cdDM_drawVerts(DerivedMesh *dm)
@@ -414,6 +425,14 @@ static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int drawAllEdges
MVert *mvert = cddm->mvert;
MEdge *medge = cddm->medge;
int i;
+
+ if (cddm->pbvh && cddm->pbvh_draw &&
+ BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH)
+ {
+ BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, TRUE);
+
+ return;
+ }
if (GPU_buffer_legacy(dm)) {
DEBUG_VBO("Using legacy code. cdDM_drawEdges\n");
@@ -530,7 +549,8 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm,
if (dm->numTessFaceData) {
float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
- BLI_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors, setMaterial);
+ BKE_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors,
+ setMaterial, FALSE);
glShadeModel(GL_FLAT);
}
@@ -627,6 +647,23 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
index_mp_to_orig = NULL;
}
+ /* TODO: not entirely correct, but currently dynamic topology will
+ * destroy UVs anyway, so textured display wouldn't work anyway
+ *
+ * this will do more like solid view with lights set up for
+ * textured view, but object itself will be displayed gray
+ * (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) {
+ glDisable(GL_TEXTURE_2D);
+ BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, FALSE);
+ glEnable(GL_TEXTURE_2D);
+ }
+
+ return;
+ }
+
colType = CD_TEXTURE_MCOL;
mcol = dm->getTessFaceDataArray(dm, colType);
if (!mcol) {
@@ -664,8 +701,9 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
}
else {
if (nors) {
- nors += 3; continue;
+ nors += 3;
}
+ continue;
}
}
else if (drawParamsMapped) {
@@ -673,8 +711,9 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
}
else {
if (nors) {
- nors += 3; continue;
+ nors += 3;
}
+ continue;
}
}
@@ -1072,6 +1111,19 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm,
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) {
+ setMaterial(1, &gattribs);
+ BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, FALSE);
+ }
+
+ return;
+ }
+
cdDM_update_normals_from_pbvh(dm);
matnr = -1;
@@ -1373,6 +1425,19 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm,
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) {
+ setMaterial(userData, 1, &gattribs);
+ BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, FALSE);
+ }
+
+ return;
+ }
+
cdDM_update_normals_from_pbvh(dm);
matnr = -1;
@@ -1704,6 +1769,7 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
mesh->totloop, mesh->totpoly);
dm->deformedOnly = 1;
+ dm->cd_flag = mesh->cd_flag;
alloctype = CD_REFERENCE;
@@ -1735,49 +1801,10 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
DerivedMesh *CDDM_from_curve(Object *ob)
{
- return CDDM_from_curve_displist(ob, &ob->disp, NULL);
+ return CDDM_from_curve_displist(ob, &ob->disp);
}
-DerivedMesh *CDDM_from_curve_orco(struct Scene *scene, Object *ob)
-{
- int *orco_index_ptr = NULL;
- int (*orco_index)[4] = NULL;
- float (*orco)[3] = NULL;
- DerivedMesh *dm = CDDM_from_curve_displist(ob, &ob->disp, &orco_index_ptr);
-
- if (orco_index_ptr) {
- orco = (float (*)[3])BKE_curve_make_orco(scene, ob);
- }
-
- if (orco && orco_index_ptr) {
- const char *uvname = "Orco";
-
- int totpoly = dm->getNumPolys(dm);
-
- MPoly *mpolys = dm->getPolyArray(dm);
- MLoop *mloops = dm->getLoopArray(dm);
-
- MLoopUV *mloopuvs;
-
- CustomData_add_layer_named(&dm->polyData, CD_MTEXPOLY, CD_DEFAULT, NULL, dm->numPolyData, uvname);
- mloopuvs = CustomData_add_layer_named(&dm->loopData, CD_MLOOPUV, CD_DEFAULT, NULL, dm->numLoopData, uvname);
-
- BKE_mesh_nurbs_to_mdata_orco(mpolys, totpoly,
- mloops, mloopuvs,
- orco, orco_index);
- }
-
- if (orco_index) {
- MEM_freeN(orco_index);
- }
- if (orco) {
- MEM_freeN(orco);
- }
-
- return dm;
-}
-
-DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase, int **orco_index_ptr)
+DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase)
{
DerivedMesh *dm;
CDDerivedMesh *cddm;
@@ -1788,7 +1815,8 @@ DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase, int **orco
int totvert, totedge, totloop, totpoly;
if (BKE_mesh_nurbs_displist_to_mdata(ob, dispbase, &allvert, &totvert, &alledge,
- &totedge, &allloop, &allpoly, &totloop, &totpoly, orco_index_ptr) != 0)
+ &totedge, &allloop, &allpoly, NULL,
+ &totloop, &totpoly) != 0)
{
/* Error initializing mdata. This often happens when curve is empty */
return CDDM_new(0, 0, 0, 0, 0);
@@ -1875,7 +1903,7 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, int use_mdisps,
bm->totface);
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
- BMIter iter, liter;
+ BMIter iter;
BMVert *eve;
BMEdge *eed;
BMFace *efa;
@@ -1887,13 +1915,12 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, int use_mdisps,
int numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
int numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
int *index, add_orig;
- int has_crease, has_edge_bweight, has_vert_bweight;
CustomDataMask mask;
unsigned int i, j;
- has_edge_bweight = CustomData_has_layer(&bm->edata, CD_BWEIGHT);
- has_vert_bweight = CustomData_has_layer(&bm->vdata, CD_BWEIGHT);
- has_crease = CustomData_has_layer(&bm->edata, CD_CREASE);
+ const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
+ const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
+ const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
dm->deformedOnly = 1;
@@ -1913,7 +1940,7 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, int use_mdisps,
CD_CALLOC, dm->numLoopData);
CustomData_merge(&bm->pdata, &dm->polyData, mask,
CD_CALLOC, dm->numPolyData);
-
+
/* add tessellation mface layers */
if (use_tessface) {
CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, em_tottri);
@@ -1933,8 +1960,7 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, int use_mdisps,
mv->flag = BM_vert_flag_to_mflag(eve);
- if (has_vert_bweight)
- mv->bweight = (unsigned char)(BM_elem_float_data_get(&bm->vdata, eve, CD_BWEIGHT) * 255.0f);
+ if (cd_vert_bweight_offset != -1) mv->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset);
if (add_orig) *index = i;
@@ -1952,11 +1978,6 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, int use_mdisps,
med->v1 = BM_elem_index_get(eed->v1);
med->v2 = BM_elem_index_get(eed->v2);
- if (has_crease)
- med->crease = (unsigned char)(BM_elem_float_data_get(&bm->edata, eed, CD_CREASE) * 255.0f);
- if (has_edge_bweight)
- med->bweight = (unsigned char)(BM_elem_float_data_get(&bm->edata, eed, CD_BWEIGHT) * 255.0f);
-
med->flag = BM_edge_flag_to_mflag(eed);
/* handle this differently to editmode switching,
@@ -1967,6 +1988,9 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, int use_mdisps,
}
}
+ if (cd_edge_crease_offset != -1) med->crease = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset);
+ if (cd_edge_bweight_offset != -1) med->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset);
+
CustomData_from_bmesh_block(&bm->edata, &dm->edgeData, eed->head.data, i);
if (add_orig) *index = i;
}
@@ -2002,7 +2026,8 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, int use_mdisps,
j = 0;
efa = BM_iter_new(&iter, bm, BM_FACES_OF_MESH, NULL);
for (i = 0; efa; i++, efa = BM_iter_step(&iter), index++) {
- BMLoop *l;
+ BMLoop *l_iter;
+ BMLoop *l_first;
MPoly *mp = &mpoly[i];
BM_elem_index_set(efa, i); /* set_inline */
@@ -2011,15 +2036,16 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, int use_mdisps,
mp->flag = BM_face_flag_to_mflag(efa);
mp->loopstart = j;
mp->mat_nr = efa->mat_nr;
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- mloop->v = BM_elem_index_get(l->v);
- mloop->e = BM_elem_index_get(l->e);
- CustomData_from_bmesh_block(&bm->ldata, &dm->loopData, l->head.data, j);
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ mloop->v = BM_elem_index_get(l_iter->v);
+ mloop->e = BM_elem_index_get(l_iter->e);
+ CustomData_from_bmesh_block(&bm->ldata, &dm->loopData, l_iter->head.data, j);
j++;
mloop++;
- }
+ } while ((l_iter = l_iter->next) != l_first);
CustomData_from_bmesh_block(&bm->pdata, &dm->polyData, efa->head.data, i);
@@ -2027,6 +2053,8 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, int use_mdisps,
}
bm->elem_index_dirty &= ~BM_FACE;
+ dm->cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
+
return dm;
}
@@ -2064,6 +2092,7 @@ static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces)
DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces,
numLoops, numPolys);
dm->deformedOnly = source->deformedOnly;
+ dm->cd_flag = source->cd_flag;
dm->dirty = source->dirty;
CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
@@ -2282,6 +2311,7 @@ void CDDM_calc_normals_tessface(DerivedMesh *dm)
*/
DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap)
{
+// #define USE_LOOPS
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
CDDerivedMesh *cddm2 = NULL;
MVert *mv, *mvert = NULL;
@@ -2293,18 +2323,27 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap)
MLoop *ml, *mloop = NULL;
BLI_array_declare(mloop);
EdgeHash *ehash = BLI_edgehash_new();
- int *newv = NULL, *newe = NULL, *newl = NULL;
+ int *newv = NULL, *newe = NULL;
+#ifdef USE_LOOPS
+ int *newl = NULL;
+#endif
int *oldv = NULL, *olde = NULL, *oldl = NULL, *oldp = NULL;
BLI_array_declare(oldv); BLI_array_declare(olde); BLI_array_declare(oldl); BLI_array_declare(oldp);
- int i, j, c, totloop, totpoly;
-
+ int i, j, c, totpoly;
+#ifdef USE_LOOPS
+ int totloop;
+#endif
+
+#ifdef USE_LOOPS
totloop = dm->numLoopData;
+#endif
totpoly = dm->numPolyData;
- newv = MEM_callocN(sizeof(int) * dm->numVertData, "newv vtable CDDM_merge_verts");
- newe = MEM_callocN(sizeof(int) * dm->numEdgeData, "newv etable CDDM_merge_verts");
- newl = MEM_callocN(sizeof(int) * totloop, "newv ltable CDDM_merge_verts");
-
+ newv = MEM_mallocN(sizeof(int) * dm->numVertData, "newv vtable CDDM_merge_verts");
+ newe = MEM_mallocN(sizeof(int) * dm->numEdgeData, "newv etable CDDM_merge_verts");
+#ifdef USE_LOOPS
+ newl = MEM_mallocN(sizeof(int) * totloop, "newv ltable CDDM_merge_verts");
+#endif
/* fill newl with destination vertex indices */
mv = cddm->mvert;
c = 0;
@@ -2314,6 +2353,10 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap)
newv[i] = c++;
BLI_array_append(mvert, *mv);
}
+ else {
+ /* dummy value */
+ newv[i] = 0;
+ }
}
/* now link target vertices to destination indices */
@@ -2382,7 +2425,9 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap)
for (j = 0; j < mp->totloop; j++, ml++) {
med = cddm->medge + ml->e;
if (LIKELY(med->v1 != med->v2)) {
+#ifdef USE_LOOPS
newl[j + mp->loopstart] = BLI_array_count(mloop);
+#endif
BLI_array_append(oldl, j + mp->loopstart);
BLI_array_append(mloop, *ml);
c++;
@@ -2448,8 +2493,10 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap)
MEM_freeN(newv);
if (newe)
MEM_freeN(newe);
+#ifdef USE_LOOPS
if (newl)
MEM_freeN(newl);
+#endif
if (oldv)
MEM_freeN(oldv);
if (olde)
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index f1d73c7777a..a7311d5efc7 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -483,7 +483,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived
clmd->sim_parms->dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame;
/* handle continuous simulation with the play button */
- if (BKE_ptcache_get_continue_physics() || ((clmd->sim_parms->preroll > 0) && (framenr > startframe - clmd->sim_parms->preroll) && (framenr < startframe))) {
+ if ((clmd->sim_parms->preroll > 0) && (framenr > startframe - clmd->sim_parms->preroll) && (framenr < startframe)) {
BKE_ptcache_invalidate(cache);
/* do simulation */
@@ -783,14 +783,12 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm )
/* goalfac= 1.0f; */ /* UNUSED */
- /*
// 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);
if ( verts->goal >= SOFTGOALSNAP )
- verts->flags |= CLOTH_VERT_FLAG_PINNED;
+ verts->flags |= CLOTH_VERT_FLAG_PINNED;
}
if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING ) {
@@ -1153,7 +1151,7 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
if ( !mface[i].v4 )
continue;
- spring = ( ClothSpring *) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
+ spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring");
if (!spring) {
cloth_free_errorsprings(cloth, edgehash, edgelist);
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index f0043d9fa77..ed72a0fb37b 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -59,7 +59,7 @@
#include "BKE_modifier.h"
#include "BKE_DerivedMesh.h"
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
#include "Bullet-C-Api.h"
#endif
#include "BLI_kdopbvh.h"
@@ -116,7 +116,7 @@ BVHTree *bvhtree_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert
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, MFace *faces, int numfaces, MVert *x, MVert *xnew, int UNUSED(numverts), int moving )
{
int i;
MFace *mfaces = faces;
@@ -385,7 +385,7 @@ static CollPair* cloth_collision(ModifierData *md1, ModifierData *md2,
CollisionModifierData *collmd = (CollisionModifierData *) md2;
/* Cloth *cloth = clmd->clothObject; */ /* UNUSED */
MFace *face1=NULL, *face2 = NULL;
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
ClothVertex *verts1 = clmd->clothObject->verts;
#endif
double distance = 0;
@@ -458,7 +458,7 @@ static CollPair* cloth_collision(ModifierData *md1, ModifierData *md2,
}
}
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
// calc distance + normal
distance = plNearestPoints (
verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa, collpair->pb, collpair->vector );
@@ -528,7 +528,7 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned
/* extend array */
if (*numobj >= *maxobj) {
*maxobj *= 2;
- *objs= MEM_reallocN(*objs, sizeof(Object*)*(*maxobj));
+ *objs= MEM_reallocN(*objs, sizeof(Object *)*(*maxobj));
}
(*objs)[*numobj] = ob;
@@ -654,7 +654,7 @@ 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 * 64, "collision array" ); // * 4 since cloth_collision_static can return more than 1 collision
*collisions_index = *collisions;
for ( i = 0; i < numresult; i++ ) {
@@ -706,7 +706,7 @@ static int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, Collision
}
// cloth - object collisions
-int cloth_bvh_objcollision(Object *ob, ClothModifierData * clmd, float step, float dt )
+int cloth_bvh_objcollision(Object *ob, ClothModifierData *clmd, float step, float dt )
{
Cloth *cloth= clmd->clothObject;
BVHTree *cloth_bvh= cloth->bvhtree;
@@ -740,7 +740,7 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData * clmd, float step, flo
/* 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);
+ CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(collob, eModifierType_Collision);
if (!collmd->bvhtree)
continue;
@@ -760,7 +760,7 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData * clmd, float step, flo
// check all collision objects
for (i = 0; i < numcollobj; i++) {
Object *collob= collobjs[i];
- CollisionModifierData *collmd = (CollisionModifierData*)modifiers_findByType(collob, eModifierType_Collision);
+ CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(collob, eModifierType_Collision);
BVHTreeOverlap *overlap = NULL;
unsigned int result = 0;
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index 529fe07cab3..5176f93f4f3 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -199,7 +199,9 @@ int curvemap_remove_point(CurveMap *cuma, CurveMapPoint *point)
cmp[b] = cuma->curve[a];
b++;
}
- else removed++;
+ else {
+ removed++;
+ }
}
MEM_freeN(cuma->curve);
@@ -221,7 +223,9 @@ void curvemap_remove(CurveMap *cuma, const short flag)
cmp[b] = cuma->curve[a];
b++;
}
- else removed++;
+ else {
+ removed++;
+ }
}
cmp[b] = cuma->curve[a];
@@ -895,7 +899,7 @@ void curvemapping_table_RGBA(const CurveMapping *cumap, float **array, int *size
#define INV_255 (1.f / 255.f)
-DO_INLINE int get_bin_float(float f)
+BLI_INLINE int get_bin_float(float f)
{
int bin = (int)((f * 255.0f) + 0.5f); /* 0.5 to prevent quantisation differences */
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index c3aab22fe5a..dc47ff40863 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -43,6 +43,8 @@
#include "BLI_kdopbvh.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "DNA_armature_types.h"
#include "DNA_camera_types.h"
#include "DNA_constraint_types.h"
@@ -96,7 +98,7 @@
/* -------------- Naming -------------- */
/* Find the first available, non-duplicate name for a given constraint */
-void unique_constraint_name(bConstraint *con, ListBase *list)
+void BKE_unique_constraint_name(bConstraint *con, ListBase *list)
{
BLI_uniquename(list, con, "Const", '.', offsetof(bConstraint, name), sizeof(con->name));
}
@@ -105,7 +107,7 @@ void unique_constraint_name(bConstraint *con, ListBase *list)
/* package an object/bone for use in constraint evaluation */
/* This function MEM_calloc's a bConstraintOb struct, that will need to be freed after evaluation */
-bConstraintOb *constraints_make_evalob(Scene *scene, Object *ob, void *subdata, short datatype)
+bConstraintOb *BKE_constraints_make_evalob(Scene *scene, Object *ob, void *subdata, short datatype)
{
bConstraintOb *cob;
@@ -169,7 +171,7 @@ bConstraintOb *constraints_make_evalob(Scene *scene, Object *ob, void *subdata,
}
/* cleanup after constraint evaluation */
-void constraints_clear_evalob(bConstraintOb *cob)
+void BKE_constraints_clear_evalob(bConstraintOb *cob)
{
float delta[4][4], imat[4][4];
@@ -219,7 +221,7 @@ void 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 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)
{
float diff_mat[4][4];
float imat[4][4];
@@ -242,7 +244,7 @@ void constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[4][4
/* use pose-space as stepping stone for other spaces... */
if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) {
/* call self with slightly different values */
- constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
+ BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
}
}
break;
@@ -278,7 +280,7 @@ void constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[4][4
/* use pose-space as stepping stone for other spaces */
if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL)) {
/* call self with slightly different values */
- constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
+ BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
}
}
break;
@@ -293,7 +295,7 @@ void constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[4][4
/* use pose-space as stepping stone for other spaces */
if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) {
/* call self with slightly different values */
- constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
+ BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
}
}
break;
@@ -499,7 +501,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);
- constraint_mat_convertspace(ob, NULL, mat, from, to);
+ BKE_constraint_mat_convertspace(ob, NULL, mat, from, to);
}
/* Case VERTEXGROUP */
/* Current method just takes the average location of all the points in the
@@ -512,11 +514,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);
- constraint_mat_convertspace(ob, NULL, mat, from, to);
+ BKE_constraint_mat_convertspace(ob, NULL, mat, from, to);
}
else if (ob->type == OB_LATTICE) {
contarget_get_lattice_mat(ob, substring, mat);
- constraint_mat_convertspace(ob, NULL, mat, from, to);
+ BKE_constraint_mat_convertspace(ob, NULL, mat, from, to);
}
/* Case BONE */
else {
@@ -549,7 +551,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 */
- constraint_mat_convertspace(ob, pchan, mat, from, to);
+ BKE_constraint_mat_convertspace(ob, pchan, mat, from, to);
}
}
@@ -817,7 +819,7 @@ static void childof_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
static bConstraintTypeInfo CTI_CHILDOF = {
CONSTRAINT_TYPE_CHILDOF, /* type */
sizeof(bChildOfConstraint), /* size */
- "ChildOf", /* name */
+ "Child Of", /* name */
"bChildOfConstraint", /* struct name */
NULL, /* free data */
childof_id_looper, /* id looper */
@@ -992,7 +994,7 @@ static void trackto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
static bConstraintTypeInfo CTI_TRACKTO = {
CONSTRAINT_TYPE_TRACKTO, /* type */
sizeof(bTrackToConstraint), /* size */
- "TrackTo", /* name */
+ "Track To", /* name */
"bTrackToConstraint", /* struct name */
NULL, /* free data */
trackto_id_looper, /* id looper */
@@ -4211,7 +4213,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 *get_constraint_typeinfo(int type)
+bConstraintTypeInfo *BKE_get_constraint_typeinfo(int type)
{
/* initialize the type-info list? */
if (CTI_INIT) {
@@ -4236,11 +4238,11 @@ bConstraintTypeInfo *get_constraint_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.
*/
-bConstraintTypeInfo *constraint_get_typeinfo(bConstraint *con)
+bConstraintTypeInfo *BKE_constraint_get_typeinfo(bConstraint *con)
{
/* only return typeinfo for valid constraints */
if (con)
- return get_constraint_typeinfo(con->type);
+ return BKE_get_constraint_typeinfo(con->type);
else
return NULL;
}
@@ -4252,7 +4254,7 @@ bConstraintTypeInfo *constraint_get_typeinfo(bConstraint *con)
/* ---------- Data Management ------- */
-/* helper function for free_constraint_data() - unlinks references */
+/* helper function for BKE_free_constraint_data() - unlinks references */
static void con_unlink_refs_cb(bConstraint *UNUSED(con), ID **idpoin, short isReference, void *UNUSED(userData))
{
if (*idpoin && isReference)
@@ -4261,12 +4263,12 @@ static void con_unlink_refs_cb(bConstraint *UNUSED(con), ID **idpoin, short isRe
/* Free data of a specific constraint if it has any info.
* be sure to run BIK_clear_data() when freeing an IK constraint,
- * unless DAG_scene_sort is called.
+ * unless DAG_relations_tag_update is called.
*/
-void free_constraint_data(bConstraint *con)
+void BKE_free_constraint_data(bConstraint *con)
{
if (con->data) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
if (cti) {
/* perform any special freeing constraint may have */
@@ -4284,13 +4286,13 @@ void free_constraint_data(bConstraint *con)
}
/* Free all constraints from a constraint-stack */
-void free_constraints(ListBase *list)
+void BKE_free_constraints(ListBase *list)
{
bConstraint *con;
/* Free constraint data and also any extra data */
for (con = list->first; con; con = con->next)
- free_constraint_data(con);
+ BKE_free_constraint_data(con);
/* Free the whole list */
BLI_freelistN(list);
@@ -4298,10 +4300,10 @@ void free_constraints(ListBase *list)
/* Remove the specified constraint from the given constraint stack */
-int remove_constraint(ListBase *list, bConstraint *con)
+int BKE_remove_constraint(ListBase *list, bConstraint *con)
{
if (con) {
- free_constraint_data(con);
+ BKE_free_constraint_data(con);
BLI_freelinkN(list, con);
return 1;
}
@@ -4310,7 +4312,7 @@ int remove_constraint(ListBase *list, bConstraint *con)
}
/* Remove all the constraints of the specified type from the given constraint stack */
-void remove_constraints_type(ListBase *list, short type, short last_only)
+void BKE_remove_constraints_type(ListBase *list, short type, short last_only)
{
bConstraint *con, *conp;
@@ -4322,7 +4324,7 @@ void remove_constraints_type(ListBase *list, short type, short last_only)
conp = con->prev;
if (con->type == type) {
- remove_constraint(list, con);
+ BKE_remove_constraint(list, con);
if (last_only)
return;
}
@@ -4335,7 +4337,7 @@ void remove_constraints_type(ListBase *list, short type, short last_only)
static bConstraint *add_new_constraint_internal(const char *name, short type)
{
bConstraint *con = MEM_callocN(sizeof(bConstraint), "Constraint");
- bConstraintTypeInfo *cti = get_constraint_typeinfo(type);
+ bConstraintTypeInfo *cti = BKE_get_constraint_typeinfo(type);
const char *newName;
/* Set up a generic constraint datablock */
@@ -4353,12 +4355,12 @@ static bConstraint *add_new_constraint_internal(const char *name, short type)
cti->new_data(con->data);
/* if no name is provided, use the type of the constraint as the name */
- newName = (name && name[0]) ? name : cti->name;
+ newName = (name && name[0]) ? name : DATA_(cti->name);
}
else {
/* if no name is provided, use the generic "Const" name */
/* NOTE: any constraint type that gets here really shouldn't get added... */
- newName = (name && name[0]) ? name : "Const";
+ newName = (name && name[0]) ? name : DATA_("Const");
}
/* copy the name */
@@ -4385,17 +4387,17 @@ static bConstraint *add_new_constraint(Object *ob, bPoseChannel *pchan, const ch
* (otherwise unique-naming code will fail, since it assumes element exists in list)
*/
BLI_addtail(list, con);
- unique_constraint_name(con, list);
+ BKE_unique_constraint_name(con, list);
/* if the target list is a list on some PoseChannel belonging to a proxy-protected
* Armature layer, we must tag newly added constraints with a flag which allows them
* to persist after proxy syncing has been done
*/
- if (proxylocked_constraints_owner(ob, pchan))
+ if (BKE_proxylocked_constraints_owner(ob, pchan))
con->flag |= CONSTRAINT_PROXY_LOCAL;
/* make this constraint the active one */
- constraints_set_active(list, con);
+ BKE_constraints_set_active(list, con);
}
/* set type+owner specific immutable settings */
@@ -4419,7 +4421,7 @@ static bConstraint *add_new_constraint(Object *ob, bPoseChannel *pchan, const ch
/* ......... */
/* Add new constraint for the given bone */
-bConstraint *add_pose_constraint(Object *ob, bPoseChannel *pchan, const char *name, short type)
+bConstraint *BKE_add_pose_constraint(Object *ob, bPoseChannel *pchan, const char *name, short type)
{
if (pchan == NULL)
return NULL;
@@ -4428,14 +4430,14 @@ bConstraint *add_pose_constraint(Object *ob, bPoseChannel *pchan, const char *na
}
/* Add new constraint for the given object */
-bConstraint *add_ob_constraint(Object *ob, const char *name, short type)
+bConstraint *BKE_add_ob_constraint(Object *ob, const char *name, short type)
{
return add_new_constraint(ob, NULL, name, type);
}
/* ......... */
-/* helper for relink_constraints() - call ID_NEW() on every ID reference the constraint has */
+/* helper for BKE_relink_constraints() - call ID_NEW() on every ID reference the constraint has */
static void con_relink_id_cb(bConstraint *UNUSED(con), ID **idpoin, short UNUSED(isReference), void *UNUSED(userdata))
{
/* ID_NEW() expects a struct with inline "id" member as first
@@ -4449,20 +4451,20 @@ static void con_relink_id_cb(bConstraint *UNUSED(con), ID **idpoin, short UNUSED
}
/* Reassign links that constraints have to other data (called during file loading?) */
-void relink_constraints(ListBase *conlist)
+void BKE_relink_constraints(ListBase *conlist)
{
/* just a wrapper around ID-loop for just calling ID_NEW() on all ID refs */
- id_loop_constraints(conlist, con_relink_id_cb, NULL);
+ BKE_id_loop_constraints(conlist, con_relink_id_cb, NULL);
}
/* Run the given callback on all ID-blocks in list of constraints */
-void id_loop_constraints(ListBase *conlist, ConstraintIDFunc func, void *userdata)
+void BKE_id_loop_constraints(ListBase *conlist, ConstraintIDFunc func, void *userdata)
{
bConstraint *con;
for (con = conlist->first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
if (cti) {
if (cti->id_looper)
@@ -4473,14 +4475,14 @@ void id_loop_constraints(ListBase *conlist, ConstraintIDFunc func, void *userdat
/* ......... */
-/* helper for copy_constraints(), to be used for making sure that ID's are valid */
+/* helper for BKE_copy_constraints(), to be used for making sure that ID's are valid */
static void con_extern_cb(bConstraint *UNUSED(con), ID **idpoin, short UNUSED(isReference), void *UNUSED(userData))
{
if (*idpoin && (*idpoin)->lib)
id_lib_extern(*idpoin);
}
-/* helper for copy_constraints(), to be used for making sure that usercounts of copied ID's are fixed up */
+/* helper for BKE_copy_constraints(), to be used for making sure that usercounts of copied ID's are fixed up */
static void con_fix_copied_refs_cb(bConstraint *UNUSED(con), ID **idpoin, short isReference, void *UNUSED(userData))
{
/* increment usercount if this is a reference type */
@@ -4489,7 +4491,7 @@ static void con_fix_copied_refs_cb(bConstraint *UNUSED(con), ID **idpoin, short
}
/* duplicate all of the constraints in a constraint stack */
-void copy_constraints(ListBase *dst, const ListBase *src, int do_extern)
+void BKE_copy_constraints(ListBase *dst, const ListBase *src, int do_extern)
{
bConstraint *con, *srccon;
@@ -4497,7 +4499,7 @@ void copy_constraints(ListBase *dst, const ListBase *src, int do_extern)
BLI_duplicatelist(dst, src);
for (con = dst->first, srccon = src->first; con && srccon; srccon = srccon->next, con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
/* make a new copy of the constraint's data */
con->data = MEM_dupallocN(con->data);
@@ -4524,13 +4526,13 @@ void copy_constraints(ListBase *dst, const ListBase *src, int do_extern)
/* ......... */
-bConstraint *constraints_findByName(ListBase *list, const char *name)
+bConstraint *BKE_constraints_findByName(ListBase *list, const char *name)
{
return BLI_findstring(list, name, offsetof(bConstraint, name));
}
/* finds the 'active' constraint in a constraint stack */
-bConstraint *constraints_get_active(ListBase *list)
+bConstraint *BKE_constraints_get_active(ListBase *list)
{
bConstraint *con;
@@ -4547,7 +4549,7 @@ bConstraint *constraints_get_active(ListBase *list)
}
/* Set the given constraint as the active one (clearing all the others) */
-void constraints_set_active(ListBase *list, bConstraint *con)
+void BKE_constraints_set_active(ListBase *list, bConstraint *con)
{
bConstraint *c;
@@ -4564,7 +4566,7 @@ void constraints_set_active(ListBase *list, bConstraint *con)
/* -------- Constraints and Proxies ------- */
/* Rescue all constraints tagged as being CONSTRAINT_PROXY_LOCAL (i.e. added to bone that's proxy-synced in this file) */
-void extract_proxylocal_constraints(ListBase *dst, ListBase *src)
+void BKE_extract_proxylocal_constraints(ListBase *dst, ListBase *src)
{
bConstraint *con, *next;
@@ -4581,7 +4583,7 @@ void extract_proxylocal_constraints(ListBase *dst, ListBase *src)
}
/* Returns if the owner of the constraint is proxy-protected */
-short proxylocked_constraints_owner(Object *ob, bPoseChannel *pchan)
+short BKE_proxylocked_constraints_owner(Object *ob, bPoseChannel *pchan)
{
/* Currently, constraints can only be on object or bone level */
if (ob && ob->proxy) {
@@ -4610,9 +4612,9 @@ short proxylocked_constraints_owner(Object *ob, bPoseChannel *pchan)
* None of the actual calculations of the matrices should be done here! Also, this function is
* not to be used by any new constraints, particularly any that have multiple targets.
*/
-void get_constraint_target_matrix(struct Scene *scene, bConstraint *con, int n, short ownertype, void *ownerdata, float mat[4][4], float ctime)
+void BKE_get_constraint_target_matrix(Scene *scene, bConstraint *con, int index, short ownertype, void *ownerdata, float mat[4][4], float ctime)
{
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintOb *cob;
bConstraintTarget *ct;
@@ -4657,10 +4659,8 @@ void get_constraint_target_matrix(struct Scene *scene, bConstraint *con, int n,
cti->get_constraint_targets(con, &targets);
/* only calculate the target matrix on the first target */
- ct = (bConstraintTarget *)targets.first;
- while (ct && n-- > 0)
- ct = ct->next;
-
+ ct = (bConstraintTarget *)BLI_findlink(&targets, index);
+
if (ct) {
if (cti->get_target_matrix)
cti->get_target_matrix(con, cob, ct, ctime);
@@ -4679,9 +4679,9 @@ void get_constraint_target_matrix(struct Scene *scene, bConstraint *con, int n,
}
/* Get the list of targets required for solving a constraint */
-void get_constraint_targets_for_solving(bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime)
+void BKE_get_constraint_targets_for_solving(bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime)
{
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
if (cti && cti->get_constraint_targets) {
bConstraintTarget *ct;
@@ -4711,10 +4711,10 @@ void get_constraint_targets_for_solving(bConstraint *con, bConstraintOb *cob, Li
/* This function is called whenever constraints need to be evaluated. Currently, all
* constraints that can be evaluated are everytime this gets run.
*
- * constraints_make_evalob and constraints_clear_evalob should be called before and
+ * BKE_constraints_make_evalob and BKE_constraints_clear_evalob should be called before and
* after running this function, to sort out cob
*/
-void solve_constraints(ListBase *conlist, bConstraintOb *cob, float ctime)
+void BKE_solve_constraints(ListBase *conlist, bConstraintOb *cob, float ctime)
{
bConstraint *con;
float oldmat[4][4];
@@ -4726,7 +4726,7 @@ void solve_constraints(ListBase *conlist, bConstraintOb *cob, float ctime)
/* loop over available constraints, solving and blending them */
for (con = conlist->first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
/* these we can skip completely (invalid constraints...) */
@@ -4746,10 +4746,10 @@ void solve_constraints(ListBase *conlist, bConstraintOb *cob, float ctime)
copy_m4_m4(oldmat, cob->matrix);
/* move owner matrix into right space */
- 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);
/* prepare targets for constraint solving */
- get_constraint_targets_for_solving(con, cob, &targets, ctime);
+ BKE_get_constraint_targets_for_solving(con, cob, &targets, ctime);
/* Solve the constraint and put result in cob->matrix */
cti->evaluate_constraint(con, cob, &targets);
@@ -4764,7 +4764,7 @@ void solve_constraints(ListBase *conlist, bConstraintOb *cob, float ctime)
/* move owner back into worldspace for next constraint/other business */
if ((con->flag & CONSTRAINT_SPACEONCE) == 0)
- 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);
/* 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 ffb93139358..d899990a66a 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -27,8 +27,8 @@
* \ingroup bke
*/
-
#include <string.h>
+#include <stdlib.h>
#include <stddef.h>
#include "MEM_guardedalloc.h"
@@ -40,19 +40,21 @@
#include "DNA_windowmanager_types.h"
#include "DNA_object_types.h"
-#include "RNA_access.h"
-
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_screen.h"
+#include "RNA_access.h"
+
#ifdef WITH_PYTHON
-#include "BPY_extern.h"
+# include "BPY_extern.h"
#endif
/* struct */
@@ -327,10 +329,13 @@ static void *ctx_data_pointer_get(const bContext *C, const char *member)
{
bContextDataResult result;
- if (C && ctx_data_get((bContext *)C, member, &result) == 1)
+ if (C && ctx_data_get((bContext *)C, member, &result) == 1) {
+ BLI_assert(result.type == CTX_DATA_TYPE_POINTER);
return result.ptr.data;
-
- return NULL;
+ }
+ else {
+ return NULL;
+ }
}
static int ctx_data_pointer_verify(const bContext *C, const char *member, void **pointer)
@@ -343,6 +348,7 @@ static int ctx_data_pointer_verify(const bContext *C, const char *member, void *
return 1;
}
else if (ctx_data_get((bContext *)C, member, &result) == 1) {
+ BLI_assert(result.type == CTX_DATA_TYPE_POINTER);
*pointer = result.ptr.data;
return 1;
}
@@ -357,6 +363,7 @@ static int ctx_data_collection_get(const bContext *C, const char *member, ListBa
bContextDataResult result;
if (ctx_data_get((bContext *)C, member, &result) == 1) {
+ BLI_assert(result.type == CTX_DATA_TYPE_COLLECTION);
*list = result.list;
return 1;
}
@@ -371,10 +378,13 @@ PointerRNA CTX_data_pointer_get(const bContext *C, const char *member)
{
bContextDataResult result;
- if (ctx_data_get((bContext *)C, member, &result) == 1)
+ if (ctx_data_get((bContext *)C, member, &result) == 1) {
+ BLI_assert(result.type == CTX_DATA_TYPE_POINTER);
return result.ptr;
- else
+ }
+ else {
return PointerRNA_NULL;
+ }
}
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
@@ -399,6 +409,7 @@ ListBase CTX_data_collection_get(const bContext *C, const char *member)
bContextDataResult result;
if (ctx_data_get((bContext *)C, member, &result) == 1) {
+ BLI_assert(result.type == CTX_DATA_TYPE_COLLECTION);
return result.list;
}
else {
@@ -427,11 +438,11 @@ int CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListB
return ret;
}
-static void data_dir_add(ListBase *lb, const char *member)
+static void data_dir_add(ListBase *lb, const char *member, const short use_all)
{
LinkData *link;
- if (strcmp(member, "scene") == 0) /* exception */
+ if ((use_all == FALSE) && strcmp(member, "scene") == 0) /* exception */
return;
if (BLI_findstring(lb, member, offsetof(LinkData, data)))
@@ -442,7 +453,13 @@ static void data_dir_add(ListBase *lb, const char *member)
BLI_addtail(lb, link);
}
-ListBase CTX_data_dir_get(const bContext *C)
+/**
+ * \param C Context
+ * \param use_store Use 'C->wm.store'
+ * \param use_rna Use Include the properties from 'RNA_Context'
+ * \param use_all Don't skip values (currently only "scene")
+ */
+ListBase CTX_data_dir_get_ex(const bContext *C, const short use_store, const short use_rna, const short use_all)
{
bContextDataResult result;
ListBase lb;
@@ -453,11 +470,33 @@ ListBase CTX_data_dir_get(const bContext *C)
memset(&lb, 0, sizeof(lb));
- if (C->wm.store) {
+ if (use_rna) {
+ char name[256], *nameptr;
+ int namelen;
+
+ PropertyRNA *iterprop;
+ PointerRNA ctx_ptr;
+ RNA_pointer_create(NULL, &RNA_Context, (void *)C, &ctx_ptr);
+
+ iterprop = RNA_struct_iterator_property(ctx_ptr.type);
+
+ RNA_PROP_BEGIN (&ctx_ptr, itemptr, iterprop)
+ {
+ nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen);
+ data_dir_add(&lb, name, use_all);
+ if (nameptr) {
+ if (name != nameptr) {
+ MEM_freeN(nameptr);
+ }
+ }
+ }
+ RNA_PROP_END;
+ }
+ if (use_store && C->wm.store) {
bContextStoreEntry *entry;
for (entry = C->wm.store->entries.first; entry; entry = entry->next)
- data_dir_add(&lb, entry->name);
+ data_dir_add(&lb, entry->name, use_all);
}
if ((ar = CTX_wm_region(C)) && ar->type && ar->type->context) {
memset(&result, 0, sizeof(result));
@@ -465,7 +504,7 @@ ListBase CTX_data_dir_get(const bContext *C)
if (result.dir)
for (a = 0; result.dir[a]; a++)
- data_dir_add(&lb, result.dir[a]);
+ data_dir_add(&lb, result.dir[a], use_all);
}
if ((sa = CTX_wm_area(C)) && sa->type && sa->type->context) {
memset(&result, 0, sizeof(result));
@@ -473,7 +512,7 @@ ListBase CTX_data_dir_get(const bContext *C)
if (result.dir)
for (a = 0; result.dir[a]; a++)
- data_dir_add(&lb, result.dir[a]);
+ data_dir_add(&lb, result.dir[a], use_all);
}
if ((sc = CTX_wm_screen(C)) && sc->context) {
bContextDataCallback cb = sc->context;
@@ -482,12 +521,17 @@ ListBase CTX_data_dir_get(const bContext *C)
if (result.dir)
for (a = 0; result.dir[a]; a++)
- data_dir_add(&lb, result.dir[a]);
+ data_dir_add(&lb, result.dir[a], use_all);
}
return lb;
}
+ListBase CTX_data_dir_get(const bContext *C)
+{
+ return CTX_data_dir_get_ex(C, TRUE, FALSE, FALSE);
+}
+
int CTX_data_equals(const char *member, const char *str)
{
return (strcmp(member, str) == 0);
@@ -808,7 +852,7 @@ void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
const char *CTX_wm_operator_poll_msg_get(bContext *C)
{
- return C->wm.operator_poll_msg;
+ return IFACE_(C->wm.operator_poll_msg);
}
/* data context */
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 4b4ca1cb32b..5fba308e3df 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -36,7 +36,6 @@
#include "MEM_guardedalloc.h"
-#include "BLI_bpath.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -168,11 +167,11 @@ void BKE_curve_free(Curve *cu)
MEM_freeN(cu->tb);
}
-Curve *BKE_curve_add(const char *name, int type)
+Curve *BKE_curve_add(Main *bmain, const char *name, int type)
{
Curve *cu;
- cu = BKE_libblock_alloc(&G.main->curve, ID_CU, name);
+ cu = BKE_libblock_alloc(&bmain->curve, ID_CU, name);
copy_v3_fl(cu->size, 1.0f);
cu->flag = CU_FRONT | CU_BACK | CU_DEFORM_BOUNDS_OFF | CU_PATH_RADIUS;
cu->pathlen = 100;
@@ -794,7 +793,9 @@ static void makeknots(Nurb *nu, short uv)
calcknots(nu->knotsv, nu->pntsv, nu->orderv, nu->flagv);
}
}
- else nu->knotsv = NULL;
+ else {
+ nu->knotsv = NULL;
+ }
}
}
}
@@ -876,7 +877,7 @@ static void basisNurb(float t, short order, short pnts, float *knots, float *bas
void BKE_nurb_makeFaces(Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv)
-/* coord_array has to be 3*4*resolu*resolv in size, and zero-ed */
+/* coord_array has to be (3 * 4 * resolu * resolv) in size, and zero-ed */
{
BPoint *bp;
float *basisu, *basis, *basisv, *sum, *fp, *in;
@@ -1747,7 +1748,7 @@ static void calc_bevel_sin_cos(float x1, float y1, float x2, float y2, float *si
else
t02 = (saacos(t02)) / 2.0f;
- t02 = (float)sin(t02);
+ t02 = sinf(t02);
if (t02 == 0.0f)
t02 = 1.0f;
@@ -2203,6 +2204,70 @@ static void make_bevel_list_segment_3D(BevList *bl)
copy_qt_qt(bevp2->quat, bevp1->quat);
}
+/* only for 2 points */
+static void make_bevel_list_segment_2D(BevList *bl)
+{
+ BevPoint *bevp2 = (BevPoint *)(bl + 1);
+ BevPoint *bevp1 = bevp2 + 1;
+
+ const float x1 = bevp1->vec[0] - bevp2->vec[0];
+ const float y1 = bevp1->vec[1] - bevp2->vec[1];
+
+ calc_bevel_sin_cos(x1, y1, -x1, -y1, &(bevp1->sina), &(bevp1->cosa));
+ bevp2->sina = bevp1->sina;
+ bevp2->cosa = bevp1->cosa;
+
+ /* fill in dir & quat */
+ make_bevel_list_segment_3D(bl);
+}
+
+static void make_bevel_list_2D(BevList *bl)
+{
+ /* note: bevp->dir and bevp->quat are not needed for beveling but are
+ * used when making a path from a 2D curve, therefor they need to be set - Campbell */
+
+ BevPoint *bevp2 = (BevPoint *)(bl + 1);
+ BevPoint *bevp1 = bevp2 + (bl->nr - 1);
+ BevPoint *bevp0 = bevp1 - 1;
+ int nr;
+
+ nr = bl->nr;
+ while (nr--) {
+ const float x1 = bevp1->vec[0] - bevp0->vec[0];
+ const float x2 = bevp1->vec[0] - bevp2->vec[0];
+ const float y1 = bevp1->vec[1] - bevp0->vec[1];
+ const float y2 = bevp1->vec[1] - bevp2->vec[1];
+
+ calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa));
+
+ /* from: make_bevel_list_3D_zup, could call but avoid a second loop.
+ * no need for tricky tilt calculation as with 3D curves */
+ bisect_v3_v3v3v3(bevp1->dir, bevp0->vec, bevp1->vec, bevp2->vec);
+ vec_to_quat(bevp1->quat, bevp1->dir, 5, 1);
+ /* done with inline make_bevel_list_3D_zup */
+
+ bevp0 = bevp1;
+ bevp1 = bevp2;
+ bevp2++;
+ }
+
+ /* correct non-cyclic cases */
+ if (bl->poly == -1) {
+ BevPoint *bevp = (BevPoint *)(bl + 1);
+ bevp1 = bevp + 1;
+ bevp->sina = bevp1->sina;
+ bevp->cosa = bevp1->cosa;
+ bevp = (BevPoint *)(bl + 1);
+ bevp += (bl->nr - 1);
+ bevp1 = bevp - 1;
+ bevp->sina = bevp1->sina;
+ bevp->cosa = bevp1->cosa;
+
+ /* correct for the dir/quat, see above why its needed */
+ bevel_list_cyclic_fix_3D(bl);
+ }
+}
+
void BKE_curve_bevelList_make(Object *ob)
{
/*
@@ -2217,10 +2282,11 @@ void BKE_curve_bevelList_make(Object *ob)
BPoint *bp;
BevList *bl, *blnew, *blnext;
BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0;
- float min, inp, x1, x2, y1, y2;
+ float min, inp;
struct bevelsort *sortdata, *sd, *sd1;
int a, b, nr, poly, resolu = 0, len = 0;
int do_tilt, do_radius, do_weight;
+ int is_editmode = 0;
/* this function needs an object, because of tflag and upflag */
cu = ob->data;
@@ -2234,12 +2300,17 @@ void BKE_curve_bevelList_make(Object *ob)
if (cu->editnurb && ob->type != OB_FONT) {
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
nu = nurbs->first;
+ is_editmode = 1;
}
else {
nu = cu->nurb.first;
}
- while (nu) {
+ for (; nu; nu = nu->next) {
+
+ if (nu->hide && is_editmode)
+ continue;
+
/* check if we will calculate tilt data */
do_tilt = CU_DO_TILT(cu, nu);
do_radius = CU_DO_RADIUS(cu, nu); /* normal display uses the radius, better just to calculate them */
@@ -2385,7 +2456,6 @@ void BKE_curve_bevelList_make(Object *ob)
}
}
}
- nu = nu->next;
}
/* STEP 2: DOUBLE POINTS AND AUTOMATIC RESOLUTION, REDUCE DATABLOCKS */
@@ -2530,76 +2600,22 @@ void BKE_curve_bevelList_make(Object *ob)
/* STEP 4: 2D-COSINES or 3D ORIENTATION */
if ((cu->flag & CU_3D) == 0) {
- /* note: bevp->dir and bevp->quat are not needed for beveling but are
- * used when making a path from a 2D curve, therefor they need to be set - Campbell */
- bl = cu->bev.first;
- while (bl) {
-
+ /* 2D Curves */
+ for (bl = cu->bev.first; bl; bl = bl->next) {
if (bl->nr < 2) {
/* do nothing */
}
else if (bl->nr == 2) { /* 2 pnt, treat separate */
- bevp2 = (BevPoint *)(bl + 1);
- bevp1 = bevp2 + 1;
-
- x1 = bevp1->vec[0] - bevp2->vec[0];
- y1 = bevp1->vec[1] - bevp2->vec[1];
-
- calc_bevel_sin_cos(x1, y1, -x1, -y1, &(bevp1->sina), &(bevp1->cosa));
- bevp2->sina = bevp1->sina;
- bevp2->cosa = bevp1->cosa;
-
- /* fill in dir & quat */
- make_bevel_list_segment_3D(bl);
+ make_bevel_list_segment_2D(bl);
}
else {
- bevp2 = (BevPoint *)(bl + 1);
- bevp1 = bevp2 + (bl->nr - 1);
- bevp0 = bevp1 - 1;
-
- nr = bl->nr;
- while (nr--) {
- x1 = bevp1->vec[0] - bevp0->vec[0];
- x2 = bevp1->vec[0] - bevp2->vec[0];
- y1 = bevp1->vec[1] - bevp0->vec[1];
- y2 = bevp1->vec[1] - bevp2->vec[1];
-
- calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa));
-
- /* from: make_bevel_list_3D_zup, could call but avoid a second loop.
- * no need for tricky tilt calculation as with 3D curves */
- bisect_v3_v3v3v3(bevp1->dir, bevp0->vec, bevp1->vec, bevp2->vec);
- vec_to_quat(bevp1->quat, bevp1->dir, 5, 1);
- /* done with inline make_bevel_list_3D_zup */
-
- bevp0 = bevp1;
- bevp1 = bevp2;
- bevp2++;
- }
-
- /* correct non-cyclic cases */
- if (bl->poly == -1) {
- bevp = (BevPoint *)(bl + 1);
- bevp1 = bevp + 1;
- bevp->sina = bevp1->sina;
- bevp->cosa = bevp1->cosa;
- bevp = (BevPoint *)(bl + 1);
- bevp += (bl->nr - 1);
- bevp1 = bevp - 1;
- bevp->sina = bevp1->sina;
- bevp->cosa = bevp1->cosa;
-
- /* correct for the dir/quat, see above why its needed */
- bevel_list_cyclic_fix_3D(bl);
- }
+ make_bevel_list_2D(bl);
}
- bl = bl->next;
}
}
- else { /* 3D Curves */
- bl = cu->bev.first;
- while (bl) {
-
+ else {
+ /* 3D Curves */
+ for (bl = cu->bev.first; bl; bl = bl->next) {
if (bl->nr < 2) {
/* do nothing */
}
@@ -2609,7 +2625,6 @@ void BKE_curve_bevelList_make(Object *ob)
else {
make_bevel_list_3D(bl, (int)(resolu * cu->twist_smooth), cu->twist_mode);
}
- bl = bl->next;
}
}
}
@@ -3304,80 +3319,218 @@ void BKE_curve_keyVertexTilts_apply(Curve *UNUSED(cu), ListBase *lb, float *key)
}
}
-int BKE_nurb_check_valid_u(struct Nurb *nu)
+bool BKE_nurb_check_valid_u(struct Nurb *nu)
{
if (nu == NULL)
- return 0;
+ return false;
if (nu->pntsu <= 1)
- return 0;
+ return false;
if (nu->type != CU_NURBS)
- return 1; /* not a nurb, lets assume its valid */
+ return true; /* not a nurb, lets assume its valid */
- if (nu->pntsu < nu->orderu) return 0;
+ if (nu->pntsu < nu->orderu) return false;
if (((nu->flag & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) { /* Bezier U Endpoints */
if (nu->orderu == 4) {
if (nu->pntsu < 5)
- return 0; /* bezier with 4 orderu needs 5 points */
+ return false; /* bezier with 4 orderu needs 5 points */
}
else {
if (nu->orderu != 3)
- return 0; /* order must be 3 or 4 */
+ return false; /* order must be 3 or 4 */
}
}
- return 1;
+ return true;
}
-int BKE_nurb_check_valid_v(struct Nurb *nu)
+bool BKE_nurb_check_valid_v(struct Nurb *nu)
{
if (nu == NULL)
- return 0;
+ return false;
if (nu->pntsv <= 1)
- return 0;
+ return false;
if (nu->type != CU_NURBS)
- return 1; /* not a nurb, lets assume its valid */
+ return true; /* not a nurb, lets assume its valid */
if (nu->pntsv < nu->orderv)
- return 0;
+ return false;
if (((nu->flag & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) { /* Bezier V Endpoints */
if (nu->orderv == 4) {
if (nu->pntsv < 5)
- return 0; /* bezier with 4 orderu needs 5 points */
+ return false; /* bezier with 4 orderu needs 5 points */
}
else {
if (nu->orderv != 3)
- return 0; /* order must be 3 or 4 */
+ return false; /* order must be 3 or 4 */
}
}
- return 1;
+ return true;
}
-int BKE_nurb_order_clamp_u(struct Nurb *nu)
+bool BKE_nurb_order_clamp_u(struct Nurb *nu)
{
- int change = 0;
+ bool change = false;
if (nu->pntsu < nu->orderu) {
nu->orderu = nu->pntsu;
- change = 1;
+ change = true;
}
if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) {
CLAMP(nu->orderu, 3, 4);
- change = 1;
+ change = true;
}
return change;
}
-int BKE_nurb_order_clamp_v(struct Nurb *nu)
+bool BKE_nurb_order_clamp_v(struct Nurb *nu)
{
- int change = 0;
+ bool change = false;
if (nu->pntsv < nu->orderv) {
nu->orderv = nu->pntsv;
- change = 1;
+ change = true;
}
if (((nu->flagv & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) {
CLAMP(nu->orderv, 3, 4);
- change = 1;
+ change = true;
}
return change;
}
+bool BKE_nurb_type_convert(Nurb *nu, const short type, const bool use_handles)
+{
+ BezTriple *bezt;
+ BPoint *bp;
+ int a, c, nr;
+
+ if (nu->type == CU_POLY) {
+ if (type == CU_BEZIER) { /* to Bezier with vecthandles */
+ nr = nu->pntsu;
+ bezt = (BezTriple *)MEM_callocN(nr * sizeof(BezTriple), "setsplinetype2");
+ nu->bezt = bezt;
+ a = nr;
+ bp = nu->bp;
+ while (a--) {
+ copy_v3_v3(bezt->vec[1], bp->vec);
+ bezt->f1 = bezt->f2 = bezt->f3 = bp->f1;
+ bezt->h1 = bezt->h2 = HD_VECT;
+ bezt->weight = bp->weight;
+ bezt->radius = bp->radius;
+ bp++;
+ bezt++;
+ }
+ MEM_freeN(nu->bp);
+ nu->bp = NULL;
+ nu->pntsu = nr;
+ nu->type = CU_BEZIER;
+ BKE_nurb_handles_calc(nu);
+ }
+ else if (type == CU_NURBS) {
+ nu->type = CU_NURBS;
+ nu->orderu = 4;
+ nu->flagu &= CU_NURB_CYCLIC; /* disable all flags except for cyclic */
+ BKE_nurb_knot_calc_u(nu);
+ a = nu->pntsu * nu->pntsv;
+ bp = nu->bp;
+ while (a--) {
+ bp->vec[3] = 1.0;
+ bp++;
+ }
+ }
+ }
+ else if (nu->type == CU_BEZIER) { /* Bezier */
+ if (type == CU_POLY || type == CU_NURBS) {
+ nr = use_handles ? (3 * nu->pntsu) : nu->pntsu;
+ nu->bp = MEM_callocN(nr * sizeof(BPoint), "setsplinetype");
+ a = nu->pntsu;
+ bezt = nu->bezt;
+ bp = nu->bp;
+ while (a--) {
+ if ((type == CU_POLY && bezt->h1 == HD_VECT && bezt->h2 == HD_VECT) || (use_handles == false)) {
+ /* vector handle becomes 1 poly vertice */
+ copy_v3_v3(bp->vec, bezt->vec[1]);
+ bp->vec[3] = 1.0;
+ bp->f1 = bezt->f2;
+ if (use_handles) nr -= 2;
+ bp->radius = bezt->radius;
+ bp->weight = bezt->weight;
+ bp++;
+ }
+ else {
+ char *f = &bezt->f1;
+ for (c = 0; c < 3; c++, f++) {
+ copy_v3_v3(bp->vec, bezt->vec[c]);
+ bp->vec[3] = 1.0;
+ bp->f1 = *f;
+ bp->radius = bezt->radius;
+ bp->weight = bezt->weight;
+ bp++;
+ }
+ }
+ bezt++;
+ }
+ MEM_freeN(nu->bezt);
+ nu->bezt = NULL;
+ nu->pntsu = nr;
+ nu->pntsv = 1;
+ nu->orderu = 4;
+ nu->orderv = 1;
+ nu->type = type;
+
+#if 0 /* UNUSED */
+ if (nu->flagu & CU_NURB_CYCLIC) c = nu->orderu - 1;
+ else c = 0;
+#endif
+
+ if (type == CU_NURBS) {
+ nu->flagu &= CU_NURB_CYCLIC; /* disable all flags except for cyclic */
+ nu->flagu |= CU_NURB_BEZIER;
+ BKE_nurb_knot_calc_u(nu);
+ }
+ }
+ }
+ else if (nu->type == CU_NURBS) {
+ if (type == CU_POLY) {
+ nu->type = CU_POLY;
+ if (nu->knotsu) MEM_freeN(nu->knotsu); /* python created nurbs have a knotsu of zero */
+ nu->knotsu = NULL;
+ if (nu->knotsv) MEM_freeN(nu->knotsv);
+ nu->knotsv = NULL;
+ }
+ else if (type == CU_BEZIER) { /* to Bezier */
+ nr = nu->pntsu / 3;
+
+ if (nr < 2) {
+ return false; /* conversion impossible */
+ }
+ else {
+ bezt = MEM_callocN(nr * sizeof(BezTriple), "setsplinetype2");
+ nu->bezt = bezt;
+ a = nr;
+ bp = nu->bp;
+ while (a--) {
+ copy_v3_v3(bezt->vec[0], bp->vec);
+ bezt->f1 = bp->f1;
+ bp++;
+ copy_v3_v3(bezt->vec[1], bp->vec);
+ bezt->f2 = bp->f1;
+ bp++;
+ copy_v3_v3(bezt->vec[2], bp->vec);
+ bezt->f3 = bp->f1;
+ bezt->radius = bp->radius;
+ bezt->weight = bp->weight;
+ bp++;
+ bezt++;
+ }
+ MEM_freeN(nu->bp);
+ nu->bp = NULL;
+ MEM_freeN(nu->knotsu);
+ nu->knotsu = NULL;
+ nu->pntsu = nr;
+ nu->type = CU_BEZIER;
+ }
+ }
+ }
+
+ return true;
+}
+
/* Get edit nurbs or normal nurbs list */
ListBase *BKE_curve_nurbs_get(Curve *cu)
{
@@ -3390,7 +3543,7 @@ ListBase *BKE_curve_nurbs_get(Curve *cu)
/* basic vertex data functions */
-int BKE_curve_minmax(Curve *cu, float min[3], float max[3])
+bool BKE_curve_minmax(Curve *cu, float min[3], float max[3])
{
ListBase *nurb_lb = BKE_curve_nurbs_get(cu);
Nurb *nu;
@@ -3401,7 +3554,7 @@ int BKE_curve_minmax(Curve *cu, float min[3], float max[3])
return (nurb_lb->first != NULL);
}
-int BKE_curve_center_median(Curve *cu, float cent[3])
+bool BKE_curve_center_median(Curve *cu, float cent[3])
{
ListBase *nurb_lb = BKE_curve_nurbs_get(cu);
Nurb *nu;
@@ -3432,21 +3585,23 @@ int BKE_curve_center_median(Curve *cu, float cent[3])
}
}
- mul_v3_fl(cent, 1.0f / (float)total);
+ if (total) {
+ mul_v3_fl(cent, 1.0f / (float)total);
+ }
return (total != 0);
}
-int BKE_curve_center_bounds(Curve *cu, float cent[3])
+bool BKE_curve_center_bounds(Curve *cu, float cent[3])
{
float min[3], max[3];
INIT_MINMAX(min, max);
if (BKE_curve_minmax(cu, min, max)) {
mid_v3_v3v3(cent, min, max);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
void BKE_curve_translate(Curve *cu, float offset[3], int do_keys)
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index b2f8db0dcce..bb14dbd3ad0 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -195,7 +195,7 @@ static void layerCopy_bmesh_elem_py_ptr(const void *UNUSED(source), void *dest,
}
#ifndef WITH_PYTHON
-void bpy_bm_generic_invalidate(void *UNUSED(self))
+void bpy_bm_generic_invalidate(struct BPy_BMGeneric *UNUSED(self))
{
/* dummy */
}
@@ -203,8 +203,6 @@ void bpy_bm_generic_invalidate(void *UNUSED(self))
static void layerFree_bmesh_elem_py_ptr(void *data, int count, int size)
{
- extern void bpy_bm_generic_invalidate(void *self);
-
int i;
for (i = 0; i < count; ++i) {
@@ -1143,7 +1141,11 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
layerFree_grid_paint_mask, NULL, NULL, NULL},
/* 36: CD_SKIN_NODE */
{sizeof(MVertSkin), "MVertSkin", 1, NULL, NULL, NULL,
- layerInterp_mvert_skin, NULL, layerDefault_mvert_skin}
+ layerInterp_mvert_skin, NULL, layerDefault_mvert_skin},
+ /* 37: CD_FREESTYLE_EDGE */
+ {sizeof(FreestyleEdge), "FreestyleEdge", 1, NULL, NULL, NULL, NULL, NULL, NULL},
+ /* 38: CD_FREESTYLE_FACE */
+ {sizeof(FreestyleFace), "FreestyleFace", 1, NULL, NULL, NULL, NULL, NULL, NULL}
};
/* note, numbers are from trunk and need updating for bmesh */
@@ -1158,7 +1160,8 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
/* BMESH ONLY */
/* 25-29 */ "CDMPoly", "CDMLoop", "CDShapeKeyIndex", "CDShapeKey", "CDBevelWeight",
/* 30-34 */ "CDSubSurfCrease", "CDOrigSpaceLoop", "CDPreviewLoopCol", "CDBMElemPyPtr", "CDPaintMask",
- /* 35-36 */ "CDGridPaintMask", "CDMVertSkin"
+ /* 35-36 */ "CDGridPaintMask", "CDMVertSkin",
+ /* 37-38 */ "CDFreestyleEdge", "CDFreestyleFace"
};
@@ -1169,8 +1172,8 @@ const CustomDataMask CD_MASK_MESH =
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL |
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_NORMAL | CD_MASK_RECAST | CD_MASK_PAINT_MASK |
- CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN;
+ 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;
const CustomDataMask CD_MASK_EDITMESH =
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MLOOPUV |
CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_SHAPE_KEYINDEX |
@@ -1183,13 +1186,13 @@ const CustomDataMask CD_MASK_DERIVEDMESH =
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_NORMAL | CD_MASK_SHAPEKEY | CD_MASK_RECAST |
- CD_MASK_ORIGINDEX | CD_MASK_MVERT_SKIN;
+ CD_MASK_ORIGINDEX | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE;
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_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_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE;
const CustomDataMask CD_MASK_FACECORNERS =
CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
CD_MASK_MLOOPCOL;
@@ -1242,12 +1245,15 @@ void CustomData_update_typemap(CustomData *data)
}
}
+/* currently only used in BLI_assert */
+#ifndef NDEBUG
static int customdata_typemap_is_valid(const CustomData *data)
{
CustomData data_copy = *data;
CustomData_update_typemap(&data_copy);
return (memcmp(data->typemap, data_copy.typemap, sizeof(data->typemap)) == 0);
}
+#endif
void CustomData_merge(const struct CustomData *source, struct CustomData *dest,
CustomDataMask mask, int alloctype, int totelem)
@@ -1457,6 +1463,14 @@ int CustomData_get_stencil_layer_index(const CustomData *data, int type)
/* -------------------------------------------------------------------- */
/* index values per layer type */
+int CustomData_get_named_layer(const struct CustomData *data, int type, const char *name)
+{
+ const int named_index = CustomData_get_named_layer_index(data, type, name);
+ const int layer_index = data->typemap[type];
+ BLI_assert(customdata_typemap_is_valid(data));
+ return (named_index != -1) ? named_index - layer_index : -1;
+}
+
int CustomData_get_active_layer(const CustomData *data, int type)
{
const int layer_index = data->typemap[type];
@@ -2095,6 +2109,23 @@ void *CustomData_get_layer_named(const struct CustomData *data, int type,
return data->layers[layer_index].data;
}
+int CustomData_get_offset(const CustomData *data, int type)
+{
+ /* get the layer index of the active layer of type */
+ int layer_index = CustomData_get_active_layer_index(data, type);
+ if (layer_index < 0) return -1;
+
+ return data->layers[layer_index].offset;
+}
+
+int CustomData_get_n_offset(const CustomData *data, int type, int n)
+{
+ /* get the layer index of the active layer of type */
+ int layer_index = CustomData_get_layer_index_n(data, type, n);
+ if (layer_index < 0) return -1;
+
+ return data->layers[layer_index].offset;
+}
int CustomData_set_layer_name(const CustomData *data, int type, int n, const char *name)
{
@@ -2104,7 +2135,7 @@ int CustomData_set_layer_name(const CustomData *data, int type, int n, const cha
if (layer_index < 0) return 0;
if (!name) return 0;
- strcpy(data->layers[layer_index].name, name);
+ BLI_strncpy(data->layers[layer_index].name, name, sizeof(data->layers[layer_index].name));
return 1;
}
@@ -2298,34 +2329,46 @@ void CustomData_bmesh_merge(CustomData *source, CustomData *dest,
BMIter iter;
CustomData destold;
void *tmp;
- int t;
+ int iter_type;
+ int totelem;
/* copy old layer description so that old data can be copied into
* the new allocation */
destold = *dest;
- if (destold.layers) destold.layers = MEM_dupallocN(destold.layers);
-
- CustomData_merge(source, dest, mask, alloctype, 0);
- dest->pool = NULL;
- CustomData_bmesh_init_pool(dest, 512, htype);
+ if (destold.layers) {
+ destold.layers = MEM_dupallocN(destold.layers);
+ }
switch (htype) {
case BM_VERT:
- t = BM_VERTS_OF_MESH; break;
+ iter_type = BM_VERTS_OF_MESH;
+ totelem = bm->totvert;
+ break;
case BM_EDGE:
- t = BM_EDGES_OF_MESH; break;
+ iter_type = BM_EDGES_OF_MESH;
+ totelem = bm->totedge;
+ break;
case BM_LOOP:
- t = BM_LOOPS_OF_FACE; break;
+ iter_type = BM_LOOPS_OF_FACE;
+ totelem = bm->totloop;
+ break;
case BM_FACE:
- t = BM_FACES_OF_MESH; break;
+ iter_type = BM_FACES_OF_MESH;
+ totelem = bm->totface;
+ break;
default: /* should never happen */
BLI_assert(!"invalid type given");
- t = BM_VERTS_OF_MESH;
+ iter_type = BM_VERTS_OF_MESH;
+ totelem = bm->totvert;
}
- if (t != BM_LOOPS_OF_FACE) {
+ CustomData_merge(source, dest, mask, alloctype, 0);
+ dest->pool = NULL;
+ CustomData_bmesh_init_pool(dest, totelem, htype);
+
+ if (iter_type != BM_LOOPS_OF_FACE) {
/*ensure all current elements follow new customdata layout*/
- BM_ITER_MESH (h, &iter, bm, t) {
+ BM_ITER_MESH (h, &iter, bm, iter_type) {
tmp = NULL;
CustomData_bmesh_copy_data(&destold, dest, h->data, &tmp);
CustomData_bmesh_free_block(&destold, &h->data);
@@ -2618,6 +2661,19 @@ void CustomData_bmesh_set_layer_n(CustomData *data, void *block, int n, void *so
memcpy(dest, source, typeInfo->size);
}
+/**
+ * \param src_blocks 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)
+{
+ 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);
+}
+
void CustomData_bmesh_interp(CustomData *data, void **src_blocks, const float *weights,
const float *sub_weights, int count, void *dest_block)
{
@@ -2640,36 +2696,47 @@ void CustomData_bmesh_interp(CustomData *data, void **src_blocks, const float *w
for (j = 0; j < count; ++j) {
sources[j] = (char *)src_blocks[j] + layer->offset;
}
-
- typeInfo->interp(sources, weights, sub_weights, count,
- (char *)dest_block + layer->offset);
+ CustomData_bmesh_interp_n(data, sources, weights, sub_weights, count, dest_block, i);
}
}
if (count > SOURCE_BUF_SIZE) MEM_freeN(sources);
}
-void CustomData_bmesh_set_default(CustomData *data, void **block)
+static void CustomData_bmesh_set_default_n(CustomData *data, void **block, int n)
{
const LayerTypeInfo *typeInfo;
+ int offset = data->layers[n].offset;
+
+ typeInfo = layerType_getInfo(data->layers[n].type);
+
+ if (typeInfo->set_default) {
+ typeInfo->set_default((char *)*block + offset, 1);
+ }
+ else {
+ memset((char *)*block + offset, 0, typeInfo->size);
+ }
+}
+
+void CustomData_bmesh_set_default(CustomData *data, void **block)
+{
int i;
if (*block == NULL)
CustomData_bmesh_alloc_block(data, block);
for (i = 0; i < data->totlayer; ++i) {
- int offset = data->layers[i].offset;
-
- typeInfo = layerType_getInfo(data->layers[i].type);
-
- if (typeInfo->set_default)
- typeInfo->set_default((char *)*block + offset, 1);
- else memset((char *)*block + offset, 0, typeInfo->size);
+ CustomData_bmesh_set_default_n(data, block, i);
}
}
+/**
+ * \param use_default_init initializes data which can't be copied,
+ * typically you'll want to use this if the BM_xxx create function
+ * is called with BM_CREATE_SKIP_CD flag
+ */
void CustomData_to_bmesh_block(const CustomData *source, CustomData *dest,
- int src_index, void **dest_block)
+ int src_index, void **dest_block, bool use_default_init)
{
const LayerTypeInfo *typeInfo;
int dest_i, src_i, src_offset;
@@ -2685,11 +2752,14 @@ void CustomData_to_bmesh_block(const CustomData *source, CustomData *dest,
* (this should work because layers are ordered by type)
*/
while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) {
+ if (use_default_init) {
+ CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
+ }
dest_i++;
}
/* if there are no more dest layers, we're done */
- if (dest_i >= dest->totlayer) return;
+ if (dest_i >= dest->totlayer) break;
/* if we found a matching layer, copy the data */
if (dest->layers[dest_i].type == source->layers[src_i].type) {
@@ -2712,6 +2782,13 @@ void CustomData_to_bmesh_block(const CustomData *source, CustomData *dest,
dest_i++;
}
}
+
+ if (use_default_init) {
+ while (dest_i < dest->totlayer) {
+ CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
+ dest_i++;
+ }
+ }
}
void CustomData_from_bmesh_block(const CustomData *source, CustomData *dest,
@@ -2795,7 +2872,7 @@ static int CustomData_is_property_layer(int type)
return 0;
}
-static int cd_layer_find_dupe(CustomData *data, const char *name, int type, int index)
+static bool cd_layer_find_dupe(CustomData *data, const char *name, int type, int index)
{
int i;
/* see if there is a duplicate */
@@ -2805,21 +2882,21 @@ static int cd_layer_find_dupe(CustomData *data, const char *name, int type, int
if (CustomData_is_property_layer(type)) {
if (CustomData_is_property_layer(layer->type) && strcmp(layer->name, name) == 0) {
- return 1;
+ return true;
}
}
else {
if (i != index && layer->type == type && strcmp(layer->name, name) == 0) {
- return 1;
+ return true;
}
}
}
}
- return 0;
+ return false;
}
-static int customdata_unique_check(void *arg, const char *name)
+static bool customdata_unique_check(void *arg, const char *name)
{
struct {CustomData *data; int type; int index; } *data_arg = arg;
return cd_layer_find_dupe(data_arg->data, name, data_arg->type, data_arg->index);
@@ -2854,10 +2931,11 @@ void CustomData_validate_layer_name(const CustomData *data, int type, const char
* deleted, so assign the active layer to name
*/
index = CustomData_get_active_layer_index(data, type);
- strcpy(outname, data->layers[index].name);
+ BLI_strncpy(outname, data->layers[index].name, MAX_CUSTOMDATA_LAYER_NAME);
+ }
+ else {
+ BLI_strncpy(outname, name, MAX_CUSTOMDATA_LAYER_NAME);
}
- else
- strcpy(outname, name);
}
int CustomData_verify_versions(struct CustomData *data, int index)
diff --git a/source/blender/blenkernel/intern/customdata_file.c b/source/blender/blenkernel/intern/customdata_file.c
index 78449879f72..c72eea50e40 100644
--- a/source/blender/blenkernel/intern/customdata_file.c
+++ b/source/blender/blenkernel/intern/customdata_file.c
@@ -29,9 +29,9 @@
#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
#include "BLI_fileops.h"
#include "BLI_string.h"
-#include "BLI_utildefines.h"
#include "BLI_endian_switch.h"
#include "BKE_customdata_file.h"
@@ -404,7 +404,7 @@ void cdf_write_close(CDataFile *cdf)
void cdf_remove(const char *filename)
{
- BLI_delete(filename, 0, 0);
+ BLI_delete(filename, false, false);
}
/********************************** Layers ***********************************/
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index 7c13ca388e0..7543892f2e3 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -34,20 +34,20 @@
#include <math.h>
#include <ctype.h>
#include <stdlib.h>
+#include <stddef.h>
#include "MEM_guardedalloc.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "BKE_deform.h"
-
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "BKE_deform.h" /* own include */
void defgroup_copy_list(ListBase *outbase, ListBase *inbase)
{
@@ -126,7 +126,7 @@ void defvert_copy_index(MDeformVert *dvert_dst, const MDeformVert *dvert_src, co
/* only sync over matching weights, don't add or remove groups
* warning, loop within loop.
*/
-void defvert_sync(MDeformVert *dvert_dst, const MDeformVert *dvert_src, int use_verify)
+void defvert_sync(MDeformVert *dvert_dst, const MDeformVert *dvert_src, const bool use_verify)
{
if (dvert_src->totweight && dvert_dst->totweight) {
int i;
@@ -145,7 +145,7 @@ void defvert_sync(MDeformVert *dvert_dst, const MDeformVert *dvert_src, int use_
/* be sure all flip_map values are valid */
void defvert_sync_mapped(MDeformVert *dvert_dst, const MDeformVert *dvert_src,
- const int *flip_map, const int flip_map_len, const int use_verify)
+ const int *flip_map, const int flip_map_len, const bool use_verify)
{
if (dvert_src->totweight && dvert_dst->totweight) {
int i;
@@ -337,41 +337,16 @@ void defvert_flip_merged(MDeformVert *dvert, const int *flip_map, const int flip
bDeformGroup *defgroup_find_name(Object *ob, const char *name)
{
- /* return a pointer to the deform group with this name
- * or return NULL otherwise.
- */
- bDeformGroup *curdef;
-
- for (curdef = ob->defbase.first; curdef; curdef = curdef->next) {
- if (!strcmp(curdef->name, name)) {
- return curdef;
- }
- }
- return NULL;
+ return BLI_findstring(&ob->defbase, name, offsetof(bDeformGroup, name));
}
int defgroup_name_index(Object *ob, const char *name)
{
- /* Return the location of the named deform group within the list of
- * deform groups. This function is a combination of BLI_findlink and
- * defgroup_find_name. The other two could be called instead, but that
- * require looping over the vertexgroups twice.
- */
- bDeformGroup *curdef;
- int def_nr;
-
- if (name && name[0] != '\0') {
- for (curdef = ob->defbase.first, def_nr = 0; curdef; curdef = curdef->next, def_nr++) {
- if (!strcmp(curdef->name, name))
- return def_nr;
- }
- }
-
- return -1;
+ return (name) ? BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name)) : -1;
}
/* note, must be freed */
-int *defgroup_flip_map(Object *ob, int *flip_map_len, int use_default)
+int *defgroup_flip_map(Object *ob, int *flip_map_len, const bool use_default)
{
int defbase_tot = *flip_map_len = BLI_countlist(&ob->defbase);
@@ -409,7 +384,7 @@ int *defgroup_flip_map(Object *ob, int *flip_map_len, int use_default)
}
/* note, must be freed */
-int *defgroup_flip_map_single(Object *ob, int *flip_map_len, int use_default, int defgroup)
+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);
@@ -441,7 +416,7 @@ int *defgroup_flip_map_single(Object *ob, int *flip_map_len, int use_default, in
}
}
-int defgroup_flip_index(Object *ob, int index, int use_default)
+int defgroup_flip_index(Object *ob, int index, const bool use_default)
{
bDeformGroup *dg = BLI_findlink(&ob->defbase, index);
int flip_index = -1;
@@ -457,22 +432,22 @@ int defgroup_flip_index(Object *ob, int index, int use_default)
return (flip_index == -1 && use_default) ? index : flip_index;
}
-static int defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *ob)
+static bool defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *ob)
{
bDeformGroup *curdef;
for (curdef = ob->defbase.first; curdef; curdef = curdef->next) {
if (dg != curdef) {
if (!strcmp(curdef->name, name)) {
- return 1;
+ return true;
}
}
}
- return 0;
+ return false;
}
-static int defgroup_unique_check(void *arg, const char *name)
+static bool defgroup_unique_check(void *arg, const char *name)
{
struct {Object *ob; void *dg; } *data = arg;
return defgroup_find_name_dupe(name, data->dg, data->ob);
@@ -810,3 +785,73 @@ int defvert_find_shared(const MDeformVert *dvert_a, const MDeformVert *dvert_b)
return -1;
}
+
+/**
+ * return true if has no weights
+ */
+bool defvert_is_weight_zero(const struct MDeformVert *dvert, const int defgroup_tot)
+{
+ MDeformWeight *dw = dvert->dw;
+ unsigned int i;
+ for (i = dvert->totweight; i != 0; i--, dw++) {
+ if (dw->weight != 0.0f) {
+ /* check the group is in-range, happens on rare situations */
+ if (LIKELY(dw->def_nr < defgroup_tot)) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+/* -------------------------------------------------------------------- */
+/* Defvert Array functions */
+
+void BKE_defvert_array_copy(MDeformVert *dst, const MDeformVert *src, int copycount)
+{
+ /* Assumes dst is already set up */
+ int i;
+
+ if (!src || !dst)
+ return;
+
+ memcpy(dst, src, copycount * sizeof(MDeformVert));
+
+ for (i = 0; i < copycount; i++) {
+ if (src[i].dw) {
+ dst[i].dw = MEM_mallocN(sizeof(MDeformWeight) * src[i].totweight, "copy_deformWeight");
+ memcpy(dst[i].dw, src[i].dw, sizeof(MDeformWeight) * src[i].totweight);
+ }
+ }
+
+}
+
+void BKE_defvert_array_free_elems(MDeformVert *dvert, int totvert)
+{
+ /* Instead of freeing the verts directly,
+ * call this function to delete any special
+ * vert data */
+ int i;
+
+ if (!dvert)
+ return;
+
+ /* Free any special data from the verts */
+ for (i = 0; i < totvert; i++) {
+ if (dvert[i].dw) MEM_freeN(dvert[i].dw);
+ }
+}
+
+void BKE_defvert_array_free(MDeformVert *dvert, int totvert)
+{
+ /* Instead of freeing the verts directly,
+ * call this function to delete any special
+ * vert data */
+ if (!dvert)
+ return;
+
+ /* Free any special data from the verts */
+ BKE_defvert_array_free_elems(dvert, totvert);
+
+ MEM_freeN(dvert);
+}
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 3ed759392b6..3a531cf32ae 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -278,22 +278,11 @@ DagNode *pop_queue(DagNodeQueue *queue)
}
}
-void *pop_ob_queue(struct DagNodeQueue *queue)
-{
- return(pop_queue(queue)->ob);
-}
-
DagNode *get_top_node_queue(DagNodeQueue *queue)
{
return queue->first->node;
}
-int queue_count(struct DagNodeQueue *queue)
-{
- return queue->count;
-}
-
-
DagForest *dag_init(void)
{
DagForest *forest;
@@ -424,7 +413,7 @@ static void dag_add_lamp_driver_relations(DagForest *dag, DagNode *node, Lamp *l
dag_add_shader_nodetree_driver_relations(dag, node, la->nodetree);
}
-static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node, int skip_forcefield)
+static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node, int skip_forcefield, bool no_collision)
{
Base *base;
DagNode *node2;
@@ -435,7 +424,7 @@ static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Objec
if ((base->lay & ob->lay) && base->object->pd) {
Object *ob1 = base->object;
if ((ob1->pd->deflect || ob1->pd->forcefield) && (ob1 != ob)) {
- if (skip_forcefield && ob1->pd->forcefield == skip_forcefield)
+ if ((skip_forcefield && ob1->pd->forcefield == skip_forcefield) || (no_collision && ob1->pd->forcefield == 0))
continue;
node2 = dag_get_node(dag, ob1);
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Field Collision");
@@ -472,7 +461,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 = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -599,10 +588,13 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
modifiers_isModifierEnabled(ob, eModifierType_Cloth) ||
modifiers_isModifierEnabled(ob, eModifierType_DynamicPaint))
{
- dag_add_collision_field_relation(dag, scene, ob, node, 0); /* TODO: use effectorweight->group */
+ dag_add_collision_field_relation(dag, scene, ob, node, 0, false); /* TODO: use effectorweight->group */
}
else if (modifiers_isModifierEnabled(ob, eModifierType_Smoke)) {
- dag_add_collision_field_relation(dag, scene, ob, node, PFIELD_SMOKEFLOW);
+ dag_add_collision_field_relation(dag, scene, ob, node, PFIELD_SMOKEFLOW, false);
+ }
+ else if (ob->rigidbody_object) {
+ dag_add_collision_field_relation(dag, scene, ob, node, 0, true);
}
}
@@ -754,7 +746,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 = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -834,7 +826,6 @@ DagForest *build_dag(Main *bmain, Scene *sce, short mask)
DagAdjList *itA;
dag = sce->theDag;
- sce->dagisvalid = 1;
if (dag)
free_forest(dag);
else {
@@ -1188,539 +1179,6 @@ static void dag_check_cycle(DagForest *dag)
}
}
-/*
- * MainDAG is the DAG of all objects in current scene
- * used only for drawing there is one also in each scene
- */
-static DagForest *MainDag = NULL;
-
-DagForest *getMainDag(void)
-{
- return MainDag;
-}
-
-
-void setMainDag(DagForest *dag)
-{
- MainDag = dag;
-}
-
-
-/*
- * note for BFS/DFS
- * in theory we should sweep the whole array
- * but in our case the first node is the scene
- * and is linked to every other object
- *
- * for general case we will need to add outer loop
- */
-
-/*
- * ToDo : change pos kludge
- */
-
-/* adjust levels for drawing in oops space */
-void graph_bfs(void)
-{
- DagNode *node;
- DagNodeQueue *nqueue;
- int pos[50];
- int i;
- DagAdjList *itA;
- int minheight;
-
- /* fprintf(stderr, "starting BFS\n ------------\n"); */
- nqueue = queue_create(DAGQUEUEALLOC);
- for (i = 0; i < 50; i++)
- pos[i] = 0;
-
- /* Init
- * dagnode.first is always the root (scene)
- */
- node = MainDag->DagNode.first;
- while (node) {
- node->color = DAG_WHITE;
- node->BFS_dist = 9999;
- node->k = 0;
- node = node->next;
- }
-
- node = MainDag->DagNode.first;
- if (node->color == DAG_WHITE) {
- node->color = DAG_GRAY;
- node->BFS_dist = 1;
- push_queue(nqueue, node);
- while (nqueue->count) {
- node = pop_queue(nqueue);
-
- minheight = pos[node->BFS_dist];
- itA = node->child;
- while (itA != NULL) {
- if (itA->node->color == DAG_WHITE) {
- itA->node->color = DAG_GRAY;
- itA->node->BFS_dist = node->BFS_dist + 1;
- itA->node->k = (float) minheight;
- push_queue(nqueue, itA->node);
- }
-
- else {
- fprintf(stderr, "bfs not dag tree edge color :%i\n", itA->node->color);
- }
-
-
- itA = itA->next;
- }
- if (pos[node->BFS_dist] > node->k) {
- pos[node->BFS_dist] += 1;
- node->k = (float) pos[node->BFS_dist];
- }
- else {
- pos[node->BFS_dist] = (int) node->k + 1;
- }
- set_node_xy(node, node->BFS_dist * DEPSX * 2, pos[node->BFS_dist] * DEPSY * 2);
- node->color = DAG_BLACK;
-
- // fprintf(stderr, "BFS node : %20s %i %5.0f %5.0f\n", ((ID *) node->ob)->name, node->BFS_dist, node->x, node->y);
- }
- }
- queue_delete(nqueue);
-}
-
-int pre_and_post_BFS(DagForest *dag, short mask, graph_action_func pre_func, graph_action_func post_func, void **data)
-{
- DagNode *node;
-
- node = dag->DagNode.first;
- return pre_and_post_source_BFS(dag, mask, node, pre_func, post_func, data);
-}
-
-
-int pre_and_post_source_BFS(DagForest *dag, short mask, DagNode *source, graph_action_func pre_func, graph_action_func post_func, void **data)
-{
- DagNode *node;
- DagNodeQueue *nqueue;
- DagAdjList *itA;
- int retval = 0;
- /* fprintf(stderr, "starting BFS\n ------------\n"); */
-
- /* Init
- * dagnode.first is always the root (scene)
- */
- node = dag->DagNode.first;
- nqueue = queue_create(DAGQUEUEALLOC);
- while (node) {
- node->color = DAG_WHITE;
- node->BFS_dist = 9999;
- node = node->next;
- }
-
- node = source;
- if (node->color == DAG_WHITE) {
- node->color = DAG_GRAY;
- node->BFS_dist = 1;
- pre_func(node->ob, data);
-
- while (nqueue->count) {
- node = pop_queue(nqueue);
-
- itA = node->child;
- while (itA != NULL) {
- if ((itA->node->color == DAG_WHITE) && (itA->type & mask)) {
- itA->node->color = DAG_GRAY;
- itA->node->BFS_dist = node->BFS_dist + 1;
- push_queue(nqueue, itA->node);
- pre_func(node->ob, data);
- }
-
- else { /* back or cross edge */
- retval = 1;
- }
- itA = itA->next;
- }
- post_func(node->ob, data);
- node->color = DAG_BLACK;
-
- // fprintf(stderr, "BFS node : %20s %i %5.0f %5.0f\n", ((ID *) node->ob)->name, node->BFS_dist, node->x, node->y);
- }
- }
- queue_delete(nqueue);
- return retval;
-}
-
-/* non recursive version of DFS, return queue -- outer loop present to catch odd cases (first level cycles)*/
-DagNodeQueue *graph_dfs(void)
-{
- DagNode *node;
- DagNodeQueue *nqueue;
- DagNodeQueue *retqueue;
- int pos[50];
- int i;
- DagAdjList *itA;
- int time;
- int skip = 0;
- int minheight;
- int maxpos = 0;
- /* int is_cycle = 0; */ /* UNUSED */
- /*
- *fprintf(stderr, "starting DFS\n ------------\n");
- */
- nqueue = queue_create(DAGQUEUEALLOC);
- retqueue = queue_create(MainDag->numNodes);
- for (i = 0; i < 50; i++)
- pos[i] = 0;
-
- /* Init
- * dagnode.first is always the root (scene)
- */
- node = MainDag->DagNode.first;
- while (node) {
- node->color = DAG_WHITE;
- node->DFS_dist = 9999;
- node->DFS_dvtm = node->DFS_fntm = 9999;
- node->k = 0;
- node = node->next;
- }
-
- time = 1;
-
- node = MainDag->DagNode.first;
-
- do {
- if (node->color == DAG_WHITE) {
- node->color = DAG_GRAY;
- node->DFS_dist = 1;
- node->DFS_dvtm = time;
- time++;
- push_stack(nqueue, node);
-
- while (nqueue->count) {
- //graph_print_queue(nqueue);
-
- skip = 0;
- node = get_top_node_queue(nqueue);
-
- minheight = pos[node->DFS_dist];
-
- itA = node->child;
- while (itA != NULL) {
- if (itA->node->color == DAG_WHITE) {
- itA->node->DFS_dvtm = time;
- itA->node->color = DAG_GRAY;
-
- time++;
- itA->node->DFS_dist = node->DFS_dist + 1;
- itA->node->k = (float) minheight;
- push_stack(nqueue, itA->node);
- skip = 1;
- break;
- }
- else {
- if (itA->node->color == DAG_GRAY) { /* back edge */
- fprintf(stderr, "dfs back edge :%15s %15s\n", ((ID *) node->ob)->name, ((ID *) itA->node->ob)->name);
- /* is_cycle = 1; */ /* UNUSED */
- }
- else if (itA->node->color == DAG_BLACK) {
- /* already processed node but we may want later to change distance either to shorter to longer.
- * DFS_dist is the first encounter
- */
-#if 0
- if (node->DFS_dist >= itA->node->DFS_dist)
- itA->node->DFS_dist = node->DFS_dist + 1;
-
- fprintf(stderr, "dfs forward or cross edge :%15s %i-%i %15s %i-%i\n",
- ((ID *) node->ob)->name,
- node->DFS_dvtm,
- node->DFS_fntm,
- ((ID *) itA->node->ob)->name,
- itA->node->DFS_dvtm,
- itA->node->DFS_fntm);
-#endif
- }
- else
- fprintf(stderr, "dfs unknown edge\n");
- }
- itA = itA->next;
- }
-
- if (!skip) {
- node = pop_queue(nqueue);
- node->color = DAG_BLACK;
-
- node->DFS_fntm = time;
- time++;
- if (node->DFS_dist > maxpos)
- maxpos = node->DFS_dist;
- if (pos[node->DFS_dist] > node->k) {
- pos[node->DFS_dist] += 1;
- node->k = (float) pos[node->DFS_dist];
- }
- else {
- pos[node->DFS_dist] = (int) node->k + 1;
- }
- set_node_xy(node, node->DFS_dist * DEPSX * 2, pos[node->DFS_dist] * DEPSY * 2);
-
- // fprintf(stderr, "DFS node : %20s %i %i %i %i\n", ((ID *) node->ob)->name, node->BFS_dist, node->DFS_dist, node->DFS_dvtm, node->DFS_fntm );
-
- push_stack(retqueue, node);
-
- }
- }
- }
- node = node->next;
- } while (node);
-// fprintf(stderr, "i size : %i\n", maxpos);
-
- queue_delete(nqueue);
- return(retqueue);
-}
-
-/* unused */
-int pre_and_post_DFS(DagForest *dag, short mask, graph_action_func pre_func, graph_action_func post_func, void **data)
-{
- DagNode *node;
-
- node = dag->DagNode.first;
- return pre_and_post_source_DFS(dag, mask, node, pre_func, post_func, data);
-}
-
-int pre_and_post_source_DFS(DagForest *dag, short mask, DagNode *source, graph_action_func pre_func, graph_action_func post_func, void **data)
-{
- DagNode *node;
- DagNodeQueue *nqueue;
- DagAdjList *itA;
- int time;
- int skip = 0;
- int retval = 0;
- /*
- * fprintf(stderr, "starting DFS\n ------------\n");
- */
- nqueue = queue_create(DAGQUEUEALLOC);
-
- /* Init
- * dagnode.first is always the root (scene)
- */
- node = dag->DagNode.first;
- while (node) {
- node->color = DAG_WHITE;
- node->DFS_dist = 9999;
- node->DFS_dvtm = node->DFS_fntm = 9999;
- node->k = 0;
- node = node->next;
- }
-
- time = 1;
-
- node = source;
- do {
- if (node->color == DAG_WHITE) {
- node->color = DAG_GRAY;
- node->DFS_dist = 1;
- node->DFS_dvtm = time;
- time++;
- push_stack(nqueue, node);
- pre_func(node->ob, data);
-
- while (nqueue->count) {
- skip = 0;
- node = get_top_node_queue(nqueue);
-
- itA = node->child;
- while (itA != NULL) {
- if ((itA->node->color == DAG_WHITE) && (itA->type & mask) ) {
- itA->node->DFS_dvtm = time;
- itA->node->color = DAG_GRAY;
-
- time++;
- itA->node->DFS_dist = node->DFS_dist + 1;
- push_stack(nqueue, itA->node);
- pre_func(node->ob, data);
-
- skip = 1;
- break;
- }
- else {
- if (itA->node->color == DAG_GRAY) { // back edge
- retval = 1;
- }
-// else if (itA->node->color == DAG_BLACK) { // cross or forward
-//
-// }
- }
- itA = itA->next;
- }
-
- if (!skip) {
- node = pop_queue(nqueue);
- node->color = DAG_BLACK;
-
- node->DFS_fntm = time;
- time++;
- post_func(node->ob, data);
- }
- }
- }
- node = node->next;
- } while (node);
- queue_delete(nqueue);
- return(retval);
-}
-
-
-/* used to get the obs owning a datablock */
-DagNodeQueue *get_obparents(struct DagForest *dag, void *ob)
-{
- DagNode *node, *node1;
- DagNodeQueue *nqueue;
- DagAdjList *itA;
-
- node = dag_find_node(dag, ob);
- if (node == NULL) {
- return NULL;
- }
- else if (node->ancestor_count == 1) { /* simple case */
- nqueue = queue_create(1);
- push_queue(nqueue, node);
- }
- else { /* need to go over the whole dag for adj list */
- nqueue = queue_create(node->ancestor_count);
-
- node1 = dag->DagNode.first;
- do {
- if (node1->DFS_fntm > node->DFS_fntm) { /* a parent is finished after child. must check adj list */
- itA = node->child;
- while (itA != NULL) {
- if ((itA->node == node) && (itA->type == DAG_RL_DATA)) {
- push_queue(nqueue, node);
- }
- itA = itA->next;
- }
- }
- node1 = node1->next;
- } while (node1);
- }
- return nqueue;
-}
-
-DagNodeQueue *get_first_ancestors(struct DagForest *dag, void *ob)
-{
- DagNode *node, *node1;
- DagNodeQueue *nqueue;
- DagAdjList *itA;
-
- node = dag_find_node(dag, ob);
-
- /* need to go over the whole dag for adj list */
- nqueue = queue_create(node->ancestor_count);
-
- node1 = dag->DagNode.first;
- do {
- if (node1->DFS_fntm > node->DFS_fntm) {
- itA = node->child;
- while (itA != NULL) {
- if (itA->node == node) {
- push_queue(nqueue, node);
- }
- itA = itA->next;
- }
- }
- node1 = node1->next;
- } while (node1);
-
- return nqueue;
-}
-
-/* standard DFS list */
-DagNodeQueue *get_all_childs(struct DagForest *dag, void *ob)
-{
- DagNode *node;
- DagNodeQueue *nqueue;
- DagNodeQueue *retqueue;
- DagAdjList *itA;
- int time;
- int skip = 0;
-
- nqueue = queue_create(DAGQUEUEALLOC);
- retqueue = queue_create(dag->numNodes); /* was MainDag... why? (ton) */
-
- node = dag->DagNode.first;
- while (node) {
- node->color = DAG_WHITE;
- node = node->next;
- }
-
- time = 1;
-
- node = dag_find_node(dag, ob); /* could be done in loop above (ton) */
- if (node) { /* can be null for newly added objects */
-
- node->color = DAG_GRAY;
- time++;
- push_stack(nqueue, node);
-
- while (nqueue->count) {
-
- skip = 0;
- node = get_top_node_queue(nqueue);
-
- itA = node->child;
- while (itA != NULL) {
- if (itA->node->color == DAG_WHITE) {
- itA->node->DFS_dvtm = time;
- itA->node->color = DAG_GRAY;
-
- time++;
- push_stack(nqueue, itA->node);
- skip = 1;
- break;
- }
- itA = itA->next;
- }
-
- if (!skip) {
- node = pop_queue(nqueue);
- node->color = DAG_BLACK;
-
- time++;
- push_stack(retqueue, node);
- }
- }
- }
- queue_delete(nqueue);
- return(retqueue);
-}
-
-/* unused */
-#if 0
-short are_obs_related(struct DagForest *dag, void *ob1, void *ob2)
-{
- DagNode *node;
- DagAdjList *itA;
-
- node = dag_find_node(dag, ob1);
-
- itA = node->child;
- while (itA != NULL) {
- if (itA->node->ob == ob2) {
- return itA->node->type;
- }
- itA = itA->next;
- }
- return DAG_NO_RELATION;
-}
-#endif
-
-int is_acyclic(DagForest *dag)
-{
- return dag->is_acyclic;
-}
-
-void set_node_xy(DagNode *node, float x, float y)
-{
- node->x = x;
- node->y = y;
-}
-
-
/* debug test functions */
void graph_print_queue(DagNodeQueue *nqueue)
@@ -1755,12 +1213,12 @@ void graph_print_queue_dist(DagNodeQueue *nqueue)
fprintf(stderr, "\n");
}
-void graph_print_adj_list(void)
+void graph_print_adj_list(DagForest *dag)
{
DagNode *node;
DagAdjList *itA;
- node = (getMainDag())->DagNode.first;
+ node = dag->DagNode.first;
while (node) {
fprintf(stderr, "node : %s col: %i", ((ID *) node->ob)->name, node->color);
itA = node->child;
@@ -1843,8 +1301,18 @@ static void scene_sort_groups(Main *bmain, Scene *sce)
}
}
+/* free the depency graph */
+static void dag_scene_free(Scene *sce)
+{
+ if (sce->theDag) {
+ free_forest(sce->theDag);
+ MEM_freeN(sce->theDag);
+ sce->theDag = NULL;
+ }
+}
+
/* sort the base list on dependency order */
-void DAG_scene_sort(Main *bmain, Scene *sce)
+static void dag_scene_build(Main *bmain, Scene *sce)
{
DagNode *node, *rootnode;
DagNodeQueue *nqueue;
@@ -1853,7 +1321,7 @@ void DAG_scene_sort(Main *bmain, Scene *sce)
int skip = 0;
ListBase tempbase;
Base *base;
-
+
tempbase.first = tempbase.last = NULL;
build_dag(bmain, sce, DAG_RL_ALL_BUT_DATA);
@@ -1933,10 +1401,43 @@ void DAG_scene_sort(Main *bmain, Scene *sce)
printf(" %s\n", base->object->id.name);
}
}
+
/* temporal...? */
sce->recalc |= SCE_PRV_CHANGED; /* test for 3d preview */
}
+/* 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);
+}
+
+/* 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);
+}
+
+/* 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);
+}
+
+void DAG_scene_free(Scene *sce)
+{
+ if (sce->theDag) {
+ free_forest(sce->theDag);
+ MEM_freeN(sce->theDag);
+ sce->theDag = NULL;
+ }
+}
+
static void lib_id_recalc_tag(Main *bmain, ID *id)
{
id->flag |= LIB_ID_RECALC;
@@ -2054,7 +1555,9 @@ static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime)
if (itA->node->lasttime != curtime) {
itA->lay = flush_layer_node(sce, itA->node, curtime); /* lay is only set once for each relation */
}
- else itA->lay = itA->node->lay;
+ else {
+ itA->lay = itA->node->lay;
+ }
node->lay |= itA->lay;
}
@@ -2174,7 +1677,7 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const sho
if (sce->theDag == NULL) {
printf("DAG zero... not allowed to happen!\n");
- DAG_scene_sort(bmain, sce);
+ DAG_scene_relations_update(bmain, sce);
}
firstnode = sce->theDag->DagNode.first; /* always scene node */
@@ -2290,12 +1793,12 @@ static short animdata_use_time(AnimData *adt)
return 0;
}
-static void dag_object_time_update_flags(Object *ob)
+static void dag_object_time_update_flags(Scene *scene, Object *ob)
{
if (ob->constraints.first) {
bConstraint *con;
for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -2350,6 +1853,10 @@ static void dag_object_time_update_flags(Object *ob)
if (object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA;
if ((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA;
+ // XXX: scene here may not be the scene that contains the rigidbody world affecting this!
+ if (ob->rigidbody_object && BKE_scene_check_rigidbody_active(scene))
+ ob->recalc |= OB_RECALC_OB;
+
{
AnimData *adt = BKE_animdata_from_id((ID *)ob->data);
Mesh *me;
@@ -2434,7 +1941,11 @@ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const s
if (do_time) {
/* now if DagNode were part of base, the node->lay could be checked... */
/* we do all now, since the scene_flush checks layers and clears recalc flags even */
- dag_object_time_update_flags(ob);
+
+ /* NOTE: "sce_iter" not "scene" so that rigidbodies in background scenes work
+ * (i.e. muting + rbw availability can be checked and tagged properly) [#33970]
+ */
+ dag_object_time_update_flags(sce_iter, ob);
}
/* handled in next loop */
@@ -2447,7 +1958,7 @@ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const s
for (group = bmain->group.first; group; group = group->id.next) {
if (group->id.flag & LIB_DOIT) {
for (go = group->gobject.first; go; go = go->next) {
- dag_object_time_update_flags(go->ob);
+ dag_object_time_update_flags(scene, go->ob);
}
}
}
@@ -2466,7 +1977,7 @@ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const s
/* hrmf... an exception to look at once, for invisible camera object we do it over */
if (scene->camera)
- dag_object_time_update_flags(scene->camera);
+ dag_object_time_update_flags(scene, scene->camera);
}
/* and store the info in groupobject */
@@ -2482,30 +1993,51 @@ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const s
}
-static void dag_current_scene_layers(Main *bmain, Scene **sce, unsigned int *lay)
+/* struct returned by DagSceneLayer */
+typedef struct DagSceneLayer {
+ struct DagSceneLayer *next, *prev;
+ Scene *scene;
+ unsigned int layer;
+} DagSceneLayer;
+
+/* returns visible scenes with valid DAG */
+static void dag_current_scene_layers(Main *bmain, ListBase *lb)
{
wmWindowManager *wm;
wmWindow *win;
+
+ lb->first = lb->last = NULL;
- /* only one scene supported currently, making more scenes work
- * correctly requires changes beyond just the dependency graph */
-
- *sce = NULL;
- *lay = 0;
-
+ /* if we have a windowmanager, look into windows */
if ((wm = bmain->wm.first)) {
- /* if we have a windowmanager, look into windows */
+
+ flag_listbase_ids(&bmain->scene, LIB_DOIT, 1);
+
for (win = wm->windows.first; win; win = win->next) {
- if (win->screen) {
- if (*sce == NULL) *sce = win->screen->scene;
- *lay |= BKE_screen_visible_layers(win->screen, win->screen->scene);
+ if (win->screen && win->screen->scene->theDag) {
+ Scene *scene = win->screen->scene;
+
+ if (scene->id.flag & LIB_DOIT) {
+ DagSceneLayer *dsl = MEM_mallocN(sizeof(DagSceneLayer), "dag scene layer");
+
+ BLI_addtail(lb, dsl);
+
+ dsl->scene = scene;
+ dsl->layer = BKE_screen_visible_layers(win->screen, scene);
+
+ scene->id.flag &= ~LIB_DOIT;
+ }
}
}
}
else {
/* if not, use the first sce */
- *sce = bmain->scene.first;
- if (*sce) *lay = (*sce)->lay;
+ DagSceneLayer *dsl = MEM_mallocN(sizeof(DagSceneLayer), "dag scene layer");
+
+ BLI_addtail(lb, dsl);
+
+ dsl->scene = bmain->scene.first;
+ dsl->layer = dsl->scene->lay;
/* XXX for background mode, we should get the scene
* from somewhere, for the -S option, but it's in
@@ -2513,31 +2045,24 @@ static void dag_current_scene_layers(Main *bmain, Scene **sce, unsigned int *lay
}
}
-void DAG_ids_flush_update(Main *bmain, int time)
-{
- Scene *sce;
- unsigned int lay;
-
- dag_current_scene_layers(bmain, &sce, &lay);
-
- if (sce)
- DAG_scene_flush_update(bmain, sce, lay, time);
-}
-
void DAG_on_visible_update(Main *bmain, const short do_time)
{
- Scene *scene;
- Base *base;
- Object *ob;
- Group *group;
- GroupObject *go;
- DagNode *node;
- unsigned int lay, oblay;
-
- dag_current_scene_layers(bmain, &scene, &lay);
-
- if (scene && scene->theDag) {
+ ListBase listbase;
+ DagSceneLayer *dsl;
+
+ /* get list of visible scenes and layers */
+ dag_current_scene_layers(bmain, &listbase);
+
+ for (dsl = listbase.first; dsl; dsl = dsl->next) {
+ Scene *scene = dsl->scene;
Scene *sce_iter;
+ Base *base;
+ Object *ob;
+ Group *group;
+ GroupObject *go;
+ DagNode *node;
+ unsigned int lay = dsl->layer, oblay;
+
/* derivedmeshes and displists are not saved to file so need to be
* remade, tag them so they get remade in the scene update loop,
* note armature poses or object matrices are preserved and do not
@@ -2574,6 +2099,8 @@ void DAG_on_visible_update(Main *bmain, const short do_time)
DAG_scene_update_flags(bmain, scene, lay, do_time);
scene->lay_updated |= lay;
}
+
+ BLI_freelistN(&listbase);
/* hack to get objects updating on layer changes */
DAG_id_type_tag(bmain, ID_OB);
@@ -2708,7 +2235,7 @@ static void dag_id_flush_update(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 = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
if (ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER,
CONSTRAINT_TYPE_OBJECTSOLVER))
{
@@ -2758,14 +2285,15 @@ static void dag_id_flush_update(Scene *sce, ID *id)
void DAG_ids_flush_tagged(Main *bmain)
{
+ ListBase listbase;
+ DagSceneLayer *dsl;
ListBase *lbarray[MAX_LIBARRAY];
- Scene *sce;
- unsigned int lay;
int a, do_flush = FALSE;
+
+ /* get list of visible scenes and layers */
+ dag_current_scene_layers(bmain, &listbase);
- dag_current_scene_layers(bmain, &sce, &lay);
-
- if (!sce || !sce->theDag)
+ if (listbase.first == NULL)
return;
/* loop over all ID types */
@@ -2780,7 +2308,10 @@ void DAG_ids_flush_tagged(Main *bmain)
if (id && bmain->id_tag_update[id->name[0]]) {
for (; id; id = id->next) {
if (id->flag & (LIB_ID_RECALC | LIB_ID_RECALC_DATA)) {
- dag_id_flush_update(sce, id);
+
+ for (dsl = listbase.first; dsl; dsl = dsl->next)
+ dag_id_flush_update(dsl->scene, id);
+
do_flush = TRUE;
}
}
@@ -2788,8 +2319,12 @@ void DAG_ids_flush_tagged(Main *bmain)
}
/* flush changes to other objects */
- if (do_flush)
- DAG_scene_flush_update(bmain, sce, lay, 0);
+ if (do_flush) {
+ for (dsl = listbase.first; dsl; dsl = dsl->next)
+ DAG_scene_flush_update(bmain, dsl->scene, dsl->layer, 0);
+ }
+
+ BLI_freelistN(&listbase);
}
void DAG_ids_check_recalc(Main *bmain, Scene *scene, int time)
@@ -2846,12 +2381,10 @@ void DAG_ids_clear_recalc(Main *bmain)
memset(bmain->id_tag_update, 0, sizeof(bmain->id_tag_update));
}
-void DAG_id_tag_update(ID *id, short flag)
+void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag)
{
- Main *bmain = G.main;
-
if (id == NULL) return;
-
+
/* tag ID for update */
if (flag) {
if (flag & OB_RECALC_OB)
@@ -2906,6 +2439,11 @@ void DAG_id_tag_update(ID *id, short flag)
}
}
+void DAG_id_tag_update(ID *id, short flag)
+{
+ DAG_id_tag_update_ex(G.main, id, flag);
+}
+
void DAG_id_type_tag(Main *bmain, short idtype)
{
if (idtype == ID_NT) {
@@ -2992,7 +2530,7 @@ void DAG_pose_sort(Object *ob)
addtoroot = 0;
}
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -3120,7 +2658,7 @@ void DAG_print_dependencies(Main *bmain, Scene *scene, Object *ob)
}
else {
printf("\nDEPENDENCY RELATIONS for %s\n\n", scene->id.name + 2);
- DAG_scene_sort(bmain, scene);
+ DAG_scene_relations_rebuild(bmain, scene);
}
dag_print_dependencies = 0;
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 083cb02fd3d..e4d7814c4e1 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -63,6 +63,7 @@
#include "BLO_sys_types.h" // for intptr_t support
static void boundbox_displist(Object *ob);
+static void boundbox_dispbase(BoundBox *bb, ListBase *dispbase);
void BKE_displist_elem_free(DispList *dl)
{
@@ -121,17 +122,17 @@ DispList *BKE_displist_find(ListBase *lb, int type)
return NULL;
}
-int BKE_displist_has_faces(ListBase *lb)
+bool BKE_displist_has_faces(ListBase *lb)
{
DispList *dl;
for (dl = lb->first; dl; dl = dl->next) {
if (ELEM3(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
void BKE_displist_copy(ListBase *lbn, ListBase *lb)
@@ -225,36 +226,55 @@ void BKE_displist_normals_add(ListBase *lb)
}
}
-void BKE_displist_count(ListBase *lb, int *totvert, int *totface)
+void BKE_displist_count(ListBase *lb, int *totvert, int *totface, int *tottri)
{
DispList *dl;
- dl = lb->first;
- while (dl) {
+ for (dl = lb->first; dl; dl = dl->next) {
+ int vert_tot = 0;
+ int face_tot = 0;
+ int tri_tot = 0;
+
switch (dl->type) {
case DL_SURF:
- *totvert += dl->nr * dl->parts;
- *totface += (dl->nr - 1) * (dl->parts - 1);
+ {
+ vert_tot = dl->nr * dl->parts;
+ face_tot = (dl->nr - 1) * (dl->parts - 1);
+ tri_tot = face_tot * 2;
break;
+ }
case DL_INDEX3:
+ {
+ vert_tot = dl->nr;
+ face_tot = dl->parts;
+ tri_tot = face_tot;
+ break;
+ }
case DL_INDEX4:
- *totvert += dl->nr;
- *totface += dl->parts;
+ {
+ vert_tot = dl->nr;
+ face_tot = dl->parts;
+ tri_tot = face_tot * 2;
break;
+ }
case DL_POLY:
case DL_SEGM:
- *totvert += dl->nr * dl->parts;
+ {
+ vert_tot = dl->nr * dl->parts;
break;
+ }
}
- dl = dl->next;
+ *totvert += vert_tot;
+ *totface += face_tot;
+ *tottri += tri_tot;
}
}
-int BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4)
+bool BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4)
{
if ((dl->flag & DL_CYCL_V) == 0 && a == (dl->parts) - 1) {
- return 0;
+ return false;
}
if (dl->flag & DL_CYCL_U) {
@@ -277,7 +297,7 @@ int BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, in
(*p4) -= dl->nr * dl->parts;
}
- return 1;
+ return true;
}
/* ****************** make displists ********************* */
@@ -290,10 +310,11 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase, i
BPoint *bp;
float *data;
int a, len, resolu;
+ const int editmode = (!forRender && (cu->editnurb || cu->editfont));
nu = nubase->first;
while (nu) {
- if (nu->hide == 0) {
+ if (nu->hide == 0 || editmode == 0) {
if (forRender && cu->resolu_ren != 0)
resolu = cu->resolu_ren;
else
@@ -486,8 +507,8 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, int flipnormal)
dl = dl->next;
}
- /* XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) { */
- if (totvert && (tot = BLI_scanfill_calc(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES))) {
+ /* XXX (obedit && obedit->actcol) ? (obedit->actcol-1) : 0)) { */
+ if (totvert && (tot = BLI_scanfill_calc(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES | BLI_SCANFILL_CALC_HOLES))) {
if (tot) {
dlnew = MEM_callocN(sizeof(DispList), "filldisplist");
dlnew->type = DL_INDEX3;
@@ -738,7 +759,7 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob, int fo
/* this modifiers are moving point of tessellation automatically
* (some of them even can't be applied on tessellated curve), set flag
- * for incformation button in modifier's header
+ * for information button in modifier's header
*/
md->mode |= eModifierMode_ApplyOnSpline;
}
@@ -780,7 +801,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl
required_mode |= eModifierMode_Editmode;
if (cu->editnurb == NULL) {
- keyVerts = do_ob_key(scene, ob);
+ keyVerts = BKE_key_evaluate_object(scene, ob, &numVerts);
if (keyVerts) {
/* split coords from key data, the latter also includes
@@ -789,7 +810,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl
* shape key modifier yet. */
deformedVerts = BKE_curve_keyVertexCos_get(cu, nurb, keyVerts);
originalVerts = MEM_dupallocN(deformedVerts);
- numVerts = BKE_nurbList_verts_count(nurb);
+ BLI_assert(BKE_nurbList_verts_count(nurb) == numVerts);
}
}
@@ -956,7 +977,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba
curve_to_filledpoly(cu, nurb, dispbase);
}
- dm = CDDM_from_curve_displist(ob, dispbase, NULL);
+ dm = CDDM_from_curve_displist(ob, dispbase);
CDDM_calc_normals_mapping(dm);
}
@@ -1046,7 +1067,7 @@ static DerivedMesh *create_orco_dm(Scene *scene, Object *ob)
/* OrcoDM should be created from underformed disp lists */
BKE_displist_make_curveTypes_forOrco(scene, ob, &disp);
- dm = CDDM_from_curve_displist(ob, &disp, NULL);
+ dm = CDDM_from_curve_displist(ob, &disp);
BKE_displist_free(&disp);
@@ -1466,8 +1487,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
float *cur_data = data;
if (cu->taperobj == NULL) {
- if ( (cu->bevobj != NULL) || !((cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) )
- fac = bevp->radius;
+ fac = bevp->radius;
}
else {
float len, taper_fac;
@@ -1579,15 +1599,15 @@ void BKE_displist_make_curveTypes(Scene *scene, Object *ob, int forOrco)
if (ob->derivedFinal) {
DM_set_object_boundbox(ob, ob->derivedFinal);
+
+ /* always keep curve's BB in sync with non-deformed displist */
+ if (cu->bb == NULL)
+ cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
+
+ boundbox_dispbase(cu->bb, &cu->disp);
}
else {
boundbox_displist(ob);
-
- /* if there is no derivedMesh, object's boundbox is unneeded */
- if (ob->bb) {
- MEM_freeN(ob->bb);
- ob->bb = NULL;
- }
}
}
@@ -1623,42 +1643,50 @@ float *BKE_displist_make_orco(Scene *scene, Object *ob, DerivedMesh *derivedFina
return orco;
}
-/* this is confusing, there's also min_max_object, appplying the obmat... */
-static void boundbox_displist(Object *ob)
+static void boundbox_dispbase(BoundBox *bb, ListBase *dispbase)
{
- BoundBox *bb = NULL;
float min[3], max[3];
DispList *dl;
float *vert;
int a, tot = 0;
+ int doit = 0;
INIT_MINMAX(min, max);
+ for (dl = dispbase->first; dl; dl = dl->next) {
+ tot = (dl->type == DL_INDEX3) ? dl->nr : dl->nr * dl->parts;
+ vert = dl->verts;
+ for (a = 0; a < tot; a++, vert += 3) {
+ minmax_v3v3_v3(min, max, vert);
+ }
+ doit |= (tot != 0);
+ }
+
+ if (!doit) {
+ /* there's no geometry in displist, use zero-sized boundbox */
+ zero_v3(min);
+ zero_v3(max);
+ }
+
+ BKE_boundbox_init_from_minmax(bb, min, max);
+}
+
+/* this is confusing, there's also min_max_object, appplying the obmat... */
+static void boundbox_displist(Object *ob)
+{
if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
Curve *cu = ob->data;
- int doit = 0;
-
- if (cu->bb == NULL) cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
- bb = cu->bb;
- for (dl = ob->disp.first; dl; dl = dl->next) {
- tot = (dl->type == DL_INDEX3) ? dl->nr : dl->nr * dl->parts;
- vert = dl->verts;
- for (a = 0; a < tot; a++, vert += 3) {
- minmax_v3v3_v3(min, max, vert);
- }
- doit = (tot != 0);
- }
+ /* calculate curve's BB based on non-deformed displist */
+ if (cu->bb == NULL)
+ cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
- if (!doit) {
- /* there's no geometry in displist, use zero-sized boundbox */
- zero_v3(min);
- zero_v3(max);
- }
+ boundbox_dispbase(cu->bb, &cu->disp);
- }
+ /* object's BB is calculated from final displist */
+ if (ob->bb == NULL)
+ ob->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
- if (bb) {
- BKE_boundbox_init_from_minmax(bb, min, max);
+ boundbox_dispbase(ob->bb, &ob->disp);
}
}
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index ed85e5b627b..4e05595b93a 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -107,9 +107,9 @@ static int neighX[8] = {1, 1, 0, -1, -1, -1, 0, 1};
static int neighY[8] = {0, 1, 1, 1, 0, -1, -1, -1};
/* subframe_updateObject() flags */
-#define UPDATE_PARENTS (1 << 0)
+#define SUBFRAME_RECURSION 5
#define UPDATE_MESH (1 << 1)
-#define UPDATE_EVERYTHING (UPDATE_PARENTS | UPDATE_MESH)
+#define UPDATE_EVERYTHING (UPDATE_MESH) // | UPDATE_PARENTS
/* surface_getBrushFlags() return vals */
#define BRUSH_USES_VELOCITY (1 << 0)
/* brush mesh raycast status */
@@ -340,7 +340,7 @@ int dynamicPaint_outputLayerExists(struct DynamicPaintSurface *surface, Object *
return 0;
}
-static int surface_duplicateOutputExists(void *arg, const char *name)
+static bool surface_duplicateOutputExists(void *arg, const char *name)
{
DynamicPaintSurface *t_surface = (DynamicPaintSurface *)arg;
DynamicPaintSurface *surface = t_surface->canvas->surfaces.first;
@@ -349,11 +349,11 @@ static int surface_duplicateOutputExists(void *arg, const char *name)
if (surface != t_surface && surface->type == t_surface->type &&
surface->format == t_surface->format)
{
- if (surface->output_name[0] != '\0' && !BLI_path_cmp(name, surface->output_name)) return 1;
- if (surface->output_name2[0] != '\0' && !BLI_path_cmp(name, surface->output_name2)) return 1;
+ if (surface->output_name[0] != '\0' && !BLI_path_cmp(name, surface->output_name)) return true;
+ if (surface->output_name2[0] != '\0' && !BLI_path_cmp(name, surface->output_name2)) return true;
}
}
- return 0;
+ return false;
}
static void surface_setUniqueOutputName(DynamicPaintSurface *surface, char *basename, int output)
@@ -367,15 +367,15 @@ static void surface_setUniqueOutputName(DynamicPaintSurface *surface, char *base
}
-static int surface_duplicateNameExists(void *arg, const char *name)
+static bool surface_duplicateNameExists(void *arg, const char *name)
{
DynamicPaintSurface *t_surface = (DynamicPaintSurface *)arg;
DynamicPaintSurface *surface = t_surface->canvas->surfaces.first;
for (; surface; surface = surface->next) {
- if (surface != t_surface && !strcmp(name, surface->name)) return 1;
+ if (surface != t_surface && !strcmp(name, surface->name)) return true;
}
- return 0;
+ return false;
}
void dynamicPaintSurface_setUniqueName(DynamicPaintSurface *surface, const char *basename)
@@ -397,7 +397,7 @@ void dynamicPaintSurface_updateType(struct DynamicPaintSurface *surface)
}
else {
strcpy(surface->output_name, "dp_");
- strcpy(surface->output_name2, surface->output_name);
+ BLI_strncpy(surface->output_name2, surface->output_name, sizeof(surface->output_name2));
surface->flags &= ~MOD_DPAINT_ANTIALIAS;
surface->depth_clamp = 0.0f;
}
@@ -473,7 +473,9 @@ static float mixColors(float a_color[3], float a_weight, float b_color[3], float
}
weight_ratio = b_weight / (a_weight + b_weight);
}
- else return a_weight * (1.0f - ratio);
+ else {
+ return a_weight * (1.0f - ratio);
+ }
/* calculate final interpolation factor */
if (ratio <= 0.5f) {
@@ -507,7 +509,7 @@ static void object_cacheIgnoreClear(Object *ob, int state)
BLI_freelistN(&pidlist);
}
-static int subframe_updateObject(Scene *scene, Object *ob, int flags, float frame)
+static int subframe_updateObject(Scene *scene, Object *ob, int flags, int parent_recursion, float frame)
{
DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
bConstraint *con;
@@ -517,10 +519,11 @@ static int subframe_updateObject(Scene *scene, Object *ob, int flags, float fram
return 1;
/* if object has parents, update them too */
- if (flags & UPDATE_PARENTS) {
+ if (parent_recursion) {
+ int recursion = parent_recursion-1;
int is_canvas = 0;
- if (ob->parent) is_canvas += subframe_updateObject(scene, ob->parent, 0, frame);
- if (ob->track) is_canvas += subframe_updateObject(scene, ob->track, 0, frame);
+ if (ob->parent) is_canvas += subframe_updateObject(scene, ob->parent, 0, recursion, frame);
+ if (ob->track) is_canvas += subframe_updateObject(scene, ob->track, 0, recursion, frame);
/* skip subframe if object is parented
* to vertex of a dynamic paint canvas */
@@ -529,7 +532,7 @@ static int subframe_updateObject(Scene *scene, Object *ob, int flags, float fram
/* also update constraint targets */
for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
if (cti && cti->get_constraint_targets) {
@@ -537,7 +540,7 @@ static int subframe_updateObject(Scene *scene, Object *ob, int flags, float fram
cti->get_constraint_targets(con, &targets);
for (ct = targets.first; ct; ct = ct->next) {
if (ct->tar)
- subframe_updateObject(scene, ct->tar, 0, frame);
+ subframe_updateObject(scene, ct->tar, 0, recursion, frame);
}
/* free temp targets */
if (cti->flush_constraint_targets)
@@ -687,7 +690,7 @@ static void boundInsert(Bounds3D *b, float point[3])
static float getSurfaceDimension(PaintSurfaceData *sData)
{
Bounds3D *mb = &sData->bData->mesh_bounds;
- return MAX3((mb->max[0] - mb->min[0]), (mb->max[1] - mb->min[1]), (mb->max[2] - mb->min[2]));
+ return max_fff((mb->max[0] - mb->min[0]), (mb->max[1] - mb->min[1]), (mb->max[2] - mb->min[2]));
}
static void freeGrid(PaintSurfaceData *data)
@@ -754,14 +757,14 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
/* get dimensions */
sub_v3_v3v3(dim, grid->grid_bounds.max, grid->grid_bounds.min);
copy_v3_v3(td, dim);
- min_dim = MAX3(td[0], td[1], td[2]) / 1000.f;
+ min_dim = max_fff(td[0], td[1], td[2]) / 1000.f;
/* deactivate zero axises */
for (i = 0; i < 3; i++) {
if (td[i] < min_dim) { td[i] = 1.0f; axis -= 1; }
}
- if (axis == 0 || MAX3(td[0], td[1], td[2]) < 0.0001f) {
+ if (axis == 0 || max_fff(td[0], td[1], td[2]) < 0.0001f) {
MEM_freeN(grid_bounds);
MEM_freeN(bData->grid);
bData->grid = NULL;
@@ -1150,7 +1153,7 @@ int dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, stru
{
CBData *ramp;
- brush->paint_ramp = add_colorband(0);
+ brush->paint_ramp = add_colorband(false);
if (!brush->paint_ramp)
return 0;
ramp = brush->paint_ramp->data;
@@ -1166,7 +1169,7 @@ int dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, stru
{
CBData *ramp;
- brush->vel_ramp = add_colorband(0);
+ brush->vel_ramp = add_colorband(false);
if (!brush->vel_ramp)
return 0;
ramp = brush->vel_ramp->data;
@@ -1193,7 +1196,68 @@ void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct Dyn
/* Copy data */
if (tpmd->canvas) {
+ DynamicPaintSurface *surface;
tpmd->canvas->pmd = tpmd;
+ /* free default surface */
+ if (tpmd->canvas->surfaces.first)
+ dynamicPaint_freeSurface(tpmd->canvas->surfaces.first);
+
+ /* copy existing surfaces */
+ for (surface = pmd->canvas->surfaces.first; surface; surface = surface->next) {
+ DynamicPaintSurface *t_surface = dynamicPaint_createNewSurface(tpmd->canvas, NULL);
+
+ /* surface settings */
+ t_surface->brush_group = surface->brush_group;
+ MEM_freeN(t_surface->effector_weights);
+ t_surface->effector_weights = MEM_dupallocN(surface->effector_weights);
+
+ BLI_strncpy(t_surface->name, surface->name, sizeof(t_surface->name));
+ t_surface->format = surface->format;
+ t_surface->type = surface->type;
+ t_surface->disp_type = surface->disp_type;
+ t_surface->image_fileformat = surface->image_fileformat;
+ t_surface->effect_ui = surface->effect_ui;
+ t_surface->preview_id = surface->preview_id;
+ t_surface->init_color_type = surface->init_color_type;
+ t_surface->flags = surface->flags;
+ t_surface->effect = surface->effect;
+
+ t_surface->image_resolution = surface->image_resolution;
+ t_surface->substeps = surface->substeps;
+ t_surface->start_frame = surface->start_frame;
+ t_surface->end_frame = surface->end_frame;
+
+ copy_v4_v4(t_surface->init_color, surface->init_color);
+ t_surface->init_texture = surface->init_texture;
+ BLI_strncpy(t_surface->init_layername, surface->init_layername, sizeof(t_surface->init_layername));
+
+ t_surface->dry_speed = surface->dry_speed;
+ t_surface->diss_speed = surface->diss_speed;
+ t_surface->color_dry_threshold = surface->color_dry_threshold;
+ t_surface->depth_clamp = surface->depth_clamp;
+ t_surface->disp_factor = surface->disp_factor;
+
+
+ t_surface->spread_speed = surface->spread_speed;
+ t_surface->color_spread_speed = surface->color_spread_speed;
+ t_surface->shrink_speed = surface->shrink_speed;
+ t_surface->drip_vel = surface->drip_vel;
+ t_surface->drip_acc = surface->drip_acc;
+
+ t_surface->influence_scale = surface->influence_scale;
+ t_surface->radius_scale = surface->radius_scale;
+
+ t_surface->wave_damping = surface->wave_damping;
+ t_surface->wave_speed = surface->wave_speed;
+ t_surface->wave_timescale = surface->wave_timescale;
+ t_surface->wave_spring = surface->wave_spring;
+
+ BLI_strncpy(t_surface->uvlayer_name, surface->uvlayer_name, sizeof(t_surface->uvlayer_name));
+ BLI_strncpy(t_surface->image_output_path, surface->image_output_path, sizeof(t_surface->image_output_path));
+ BLI_strncpy(t_surface->output_name, surface->output_name, sizeof(t_surface->output_name));
+ BLI_strncpy(t_surface->output_name2, surface->output_name2, sizeof(t_surface->output_name2));
+ }
+ dynamicPaint_resetPreview(tpmd->canvas);
}
else if (tpmd->brush) {
DynamicPaintBrushSettings *brush = pmd->brush, *t_brush = tpmd->brush;
@@ -1422,7 +1486,9 @@ static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface)
/* for vertex surface loop through tfaces and find uv color
* that provides highest alpha */
if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
- #pragma omp parallel for schedule(static)
+ 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;
float uv[3] = {0.0f};
@@ -1435,7 +1501,7 @@ static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface)
uv[0] = tface[i].uv[j][0] * 2.0f - 1.0f;
uv[1] = tface[i].uv[j][1] * 2.0f - 1.0f;
- multitex_ext_safe(tex, uv, &texres);
+ multitex_ext_safe(tex, uv, &texres, pool);
if (texres.tin > pPoint[*vert].alpha) {
copy_v3_v3(pPoint[*vert].color, &texres.tr);
@@ -1443,6 +1509,7 @@ static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface)
}
}
}
+ BKE_image_pool_free(pool);
}
else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data;
@@ -1468,7 +1535,7 @@ static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface)
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);
+ multitex_ext_safe(tex, uv_final, &texres, NULL);
/* apply color */
copy_v3_v3(pPoint[i].color, &texres.tr);
@@ -2315,7 +2382,8 @@ int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
dot11 = d2[0] * d2[0] + d2[1] * d2[1];
dot12 = d2[0] * d3[0] + d2[1] * d3[1];
- invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
+ invDenom = (dot00 * dot11 - dot01 * dot01);
+ invDenom = invDenom ? 1.0f / invDenom : 1.0f;
u = (dot11 * dot02 - dot01 * dot12) * invDenom;
v = (dot00 * dot12 - dot01 * dot02) * invDenom;
@@ -2335,7 +2403,8 @@ int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
dot11 = d2[0] * d2[0] + d2[1] * d2[1];
dot12 = d2[0] * d3[0] + d2[1] * d3[1];
- invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
+ invDenom = (dot00 * dot11 - dot01 * dot01);
+ invDenom = invDenom ? 1.0f / invDenom : 1.0f;
u = (dot11 * dot02 - dot01 * dot12) * invDenom;
v = (dot00 * dot12 - dot01 * dot02) * invDenom;
@@ -2540,7 +2609,9 @@ int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
if (!f_data->uv_p || !f_data->barycentricWeights) error = 1;
}
- else error = 1;
+ else {
+ error = 1;
+ }
sData->total_points = active_points;
@@ -2628,7 +2699,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(output_file, format);
+ BKE_add_image_extension_from_type(output_file, format);
/* Validate output file path */
BLI_path_abs(output_file, G.main->name);
@@ -2778,7 +2849,9 @@ 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 faceIndex, short isQuad, DerivedMesh *orcoDm)
{
Material *mat = bMats->mat;
MFace *mface = orcoDm->getTessFaceArray(orcoDm);
@@ -2791,7 +2864,9 @@ static void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], fl
mat = bMats->ob_mats[mat_nr];
if (mat == NULL) return; /* No material assigned */
}
- else return;
+ else {
+ return;
+ }
}
RE_sample_material_color(mat, color, alpha, volume_co, surface_co, faceIndex, isQuad, orcoDm, brushOb);
@@ -3109,7 +3184,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(Scene *scene, Object *ob, Dy
scene->r.cfra = prev_fra;
scene->r.subframe = prev_sfra;
- subframe_updateObject(scene, ob, UPDATE_EVERYTHING, BKE_scene_frame_get(scene));
+ subframe_updateObject(scene, ob, UPDATE_EVERYTHING, SUBFRAME_RECURSION, BKE_scene_frame_get(scene));
dm_p = CDDM_copy(brush->dm);
numOfVerts_p = dm_p->getNumVerts(dm_p);
mvert_p = dm_p->getVertArray(dm_p);
@@ -3119,7 +3194,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(Scene *scene, Object *ob, Dy
scene->r.cfra = cur_fra;
scene->r.subframe = cur_sfra;
- subframe_updateObject(scene, ob, UPDATE_EVERYTHING, BKE_scene_frame_get(scene));
+ subframe_updateObject(scene, ob, UPDATE_EVERYTHING, SUBFRAME_RECURSION, BKE_scene_frame_get(scene));
dm_c = brush->dm;
numOfVerts_c = dm_c->getNumVerts(dm_c);
mvert_c = dm_p->getVertArray(dm_c);
@@ -3169,13 +3244,13 @@ static void dynamicPaint_brushObjectCalculateVelocity(Scene *scene, Object *ob,
/* previous frame dm */
scene->r.cfra = prev_fra;
scene->r.subframe = prev_sfra;
- subframe_updateObject(scene, ob, UPDATE_PARENTS, BKE_scene_frame_get(scene));
+ subframe_updateObject(scene, ob, 0, SUBFRAME_RECURSION, BKE_scene_frame_get(scene));
copy_m4_m4(prev_obmat, ob->obmat);
/* current frame dm */
scene->r.cfra = cur_fra;
scene->r.subframe = cur_sfra;
- subframe_updateObject(scene, ob, UPDATE_PARENTS, BKE_scene_frame_get(scene));
+ subframe_updateObject(scene, ob, 0, SUBFRAME_RECURSION, BKE_scene_frame_get(scene));
/* calculate speed */
mul_m4_v3(prev_obmat, prev_loc);
@@ -3856,7 +3931,9 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po
strength = 1.0f - distance / brush_radius;
CLAMP(strength, 0.0f, 1.0f);
}
- else strength = 1.0f;
+ else {
+ strength = 1.0f;
+ }
if (strength >= 0.001f) {
float paintColor[3] = {0.0f};
@@ -4199,7 +4276,7 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s
if (surface->effect & MOD_DPAINT_EFFECT_DO_SHRINK)
shrink_speed = surface->shrink_speed;
- fastest_effect = MAX3(spread_speed, shrink_speed, average_force);
+ fastest_effect = max_fff(spread_speed, shrink_speed, average_force);
avg_dist = bData->average_dist * CANVAS_REL_SIZE / getSurfaceDimension(sData);
steps = (int)ceil(1.5f * EFF_MOVEMENT_PER_FRAME * fastest_effect / avg_dist * timescale);
@@ -4383,8 +4460,7 @@ static void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescal
float dt, min_dist, damp_factor;
float wave_speed = surface->wave_speed;
double average_dist = 0.0f;
- Bounds3D *mb = &sData->bData->mesh_bounds;
- float canvas_size = MAX3((mb->max[0] - mb->min[0]), (mb->max[1] - mb->min[1]), (mb->max[2] - mb->min[2]));
+ const float canvas_size = getSurfaceDimension(sData);
float wave_scale = CANVAS_REL_SIZE / canvas_size;
/* allocate memory */
@@ -4898,7 +4974,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
/* update object data on this subframe */
if (subframe) {
scene_setSubframe(scene, subframe);
- subframe_updateObject(scene, brushObj, UPDATE_EVERYTHING, BKE_scene_frame_get(scene));
+ subframe_updateObject(scene, brushObj, UPDATE_EVERYTHING, SUBFRAME_RECURSION, BKE_scene_frame_get(scene));
}
/* Prepare materials if required */
if (brush_usesMaterial(brush, scene))
@@ -4932,7 +5008,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
if (subframe) {
scene->r.cfra = scene_frame;
scene->r.subframe = scene_subframe;
- subframe_updateObject(scene, brushObj, UPDATE_EVERYTHING, BKE_scene_frame_get(scene));
+ subframe_updateObject(scene, brushObj, UPDATE_EVERYTHING, SUBFRAME_RECURSION, BKE_scene_frame_get(scene));
}
/* process special brush effects, like smudge */
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index 321a61ce238..11c05772962 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -39,8 +39,8 @@
#include "BLI_blenlib.h"
#include "BLI_edgehash.h"
#include "BLI_math.h"
-#include "BLI_pbvh.h"
+#include "BKE_pbvh.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
@@ -69,26 +69,26 @@
extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
-BMEditMesh *BMEdit_Create(BMesh *bm, int do_tessellate)
+BMEditMesh *BMEdit_Create(BMesh *bm, const bool do_tessellate)
{
- BMEditMesh *tm = MEM_callocN(sizeof(BMEditMesh), __func__);
+ BMEditMesh *em = MEM_callocN(sizeof(BMEditMesh), __func__);
- tm->bm = bm;
+ em->bm = bm;
if (do_tessellate) {
- BMEdit_RecalcTessellation(tm);
+ BMEdit_RecalcTessellation(em);
}
- return tm;
+ return em;
}
-BMEditMesh *BMEdit_Copy(BMEditMesh *tm)
+BMEditMesh *BMEdit_Copy(BMEditMesh *em)
{
- BMEditMesh *tm2 = MEM_callocN(sizeof(BMEditMesh), __func__);
- *tm2 = *tm;
+ BMEditMesh *em_copy = MEM_callocN(sizeof(BMEditMesh), __func__);
+ *em_copy = *em;
- tm2->derivedCage = tm2->derivedFinal = NULL;
+ em_copy->derivedCage = em_copy->derivedFinal = NULL;
- tm2->bm = BM_mesh_copy(tm->bm);
+ em_copy->bm = BM_mesh_copy(em->bm);
/* The tessellation is NOT calculated on the copy here,
* because currently all the callers of this function use
@@ -97,55 +97,59 @@ BMEditMesh *BMEdit_Copy(BMEditMesh *tm)
* reasons, in that case it makes more sense to do the
* tessellation only when/if that copy ends up getting
* used.*/
- tm2->looptris = NULL;
+ em_copy->looptris = NULL;
- tm2->vert_index = NULL;
- tm2->edge_index = NULL;
- tm2->face_index = NULL;
+ em_copy->vert_index = NULL;
+ em_copy->edge_index = NULL;
+ em_copy->face_index = NULL;
- return tm2;
+ return em_copy;
}
-static void BMEdit_RecalcTessellation_intern(BMEditMesh *tm)
+static void BMEdit_RecalcTessellation_intern(BMEditMesh *em)
{
/* use this to avoid locking pthread for _every_ polygon
* and calling the fill function */
#define USE_TESSFACE_SPEEDUP
- BMesh *bm = tm->bm;
- BMLoop *(*looptris)[3] = NULL;
- BLI_array_declare(looptris);
- BMIter iter, liter;
+ BMesh *bm = em->bm;
+
+ /* this assumes all faces can be scan-filled, which isn't always true,
+ * worst case we over alloc a little which is acceptable */
+ const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
+ const int looptris_tot_prev_alloc = em->looptris ? (MEM_allocN_len(em->looptris) / sizeof(*em->looptris)) : 0;
+
+ BMLoop *(*looptris)[3];
+ BMIter iter;
BMFace *efa;
BMLoop *l;
- int i = 0, j;
+ int i = 0;
ScanFillContext sf_ctx;
#if 0
/* note, we could be clever and re-use this array but would need to ensure
* its realloced at some point, for now just free it */
- if (tm->looptris) MEM_freeN(tm->looptris);
+ if (em->looptris) MEM_freeN(em->looptris);
- /* Use tm->tottri when set, this means no reallocs while transforming,
+ /* Use em->tottri when set, this means no reallocs while transforming,
* (unless scanfill fails), otherwise... */
/* allocate the length of totfaces, avoid many small reallocs,
* if all faces are tri's it will be correct, quads == 2x allocs */
- BLI_array_reserve(looptris, (tm->tottri && tm->tottri < bm->totface * 3) ? tm->tottri : bm->totface);
+ BLI_array_reserve(looptris, (em->tottri && em->tottri < bm->totface * 3) ? em->tottri : bm->totface);
#else
/* this means no reallocs for quad dominant models, for */
- if ( (tm->looptris != NULL) &&
- (tm->tottri != 0) &&
- /* (totrti <= bm->totface * 2) would be fine for all quads,
- * but in case there are some ngons, still re-use the array */
- (tm->tottri <= bm->totface * 3))
+ if ((em->looptris != NULL) &&
+ /* (em->tottri >= looptris_tot)) */
+ /* check against alloc'd size incase we over alloc'd a little */
+ ((looptris_tot_prev_alloc >= looptris_tot) && (looptris_tot_prev_alloc <= looptris_tot * 2)))
{
- looptris = tm->looptris;
+ looptris = em->looptris;
}
else {
- if (tm->looptris) MEM_freeN(tm->looptris);
- BLI_array_reserve(looptris, bm->totface);
+ if (em->looptris) MEM_freeN(em->looptris);
+ looptris = MEM_mallocN(sizeof(*looptris) * looptris_tot, __func__);
}
#endif
@@ -161,16 +165,25 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *tm)
/* no need to ensure the loop order, we know its ok */
else if (efa->len == 3) {
- BLI_array_grow_one(looptris);
+#if 0
+ int j;
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) {
looptris[i][j] = l;
}
i += 1;
+#else
+ /* more cryptic but faster */
+ BMLoop **l_ptr = looptris[i++];
+ l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa);
+ l_ptr[1] = l = l->next;
+ l_ptr[2] = l->next;
+#endif
}
else if (efa->len == 4) {
+#if 0
BMLoop *ltmp[4];
+ int j;
BLI_array_grow_items(looptris, 2);
-
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) {
ltmp[j] = l;
}
@@ -184,11 +197,24 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *tm)
looptris[i][1] = ltmp[2];
looptris[i][2] = ltmp[3];
i += 1;
+#else
+ /* more cryptic but faster */
+ BMLoop **l_ptr_a = looptris[i++];
+ BMLoop **l_ptr_b = looptris[i++];
+ (l_ptr_a[0] = l_ptr_b[0] = l = BM_FACE_FIRST_LOOP(efa));
+ (l_ptr_a[1] = l = l->next);
+ (l_ptr_a[2] = l_ptr_b[1] = l = l->next);
+ ( l_ptr_b[2] = l->next);
+#endif
}
#endif /* USE_TESSFACE_SPEEDUP */
else {
+ int j;
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
ScanFillVert *sf_vert, *sf_vert_last = NULL, *sf_vert_first = NULL;
/* ScanFillEdge *e; */ /* UNUSED */
ScanFillFace *sf_tri;
@@ -197,28 +223,35 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *tm)
BLI_scanfill_begin(&sf_ctx);
/* scanfill time */
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) {
- /*mark order */
- BM_elem_index_set(l, j); /* set_loop */
-
- sf_vert = BLI_scanfill_vert_add(&sf_ctx, l->v->co);
- sf_vert->tmp.p = l;
+ j = 0;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ sf_vert = BLI_scanfill_vert_add(&sf_ctx, l_iter->v->co);
+ sf_vert->tmp.p = l_iter;
if (sf_vert_last) {
/* e = */ BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
}
sf_vert_last = sf_vert;
- if (sf_vert_first == NULL) sf_vert_first = sf_vert;
- }
+ if (sf_vert_first == NULL) {
+ sf_vert_first = sf_vert;
+ }
+
+ /*mark order */
+ BM_elem_index_set(l_iter, j++); /* set_loop */
+
+ } while ((l_iter = l_iter->next) != l_first);
/* complete the loop */
BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
totfilltri = BLI_scanfill_calc_ex(&sf_ctx, 0, efa->no);
- BLI_array_grow_items(looptris, totfilltri);
+ BLI_assert(totfilltri <= efa->len - 2);
+ (void)totfilltri;
for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
+ BMLoop **l_ptr = looptris[i++];
BMLoop *l1 = sf_tri->v1->tmp.p;
BMLoop *l2 = sf_tri->v2->tmp.p;
BMLoop *l3 = sf_tri->v3->tmp.p;
@@ -227,18 +260,19 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *tm)
if (BM_elem_index_get(l2) > BM_elem_index_get(l3)) { SWAP(BMLoop *, l2, l3); }
if (BM_elem_index_get(l1) > BM_elem_index_get(l2)) { SWAP(BMLoop *, l1, l2); }
- looptris[i][0] = l1;
- looptris[i][1] = l2;
- looptris[i][2] = l3;
- i += 1;
+ l_ptr[0] = l1;
+ l_ptr[1] = l2;
+ l_ptr[2] = l3;
}
BLI_scanfill_end(&sf_ctx);
}
}
- tm->tottri = i;
- tm->looptris = looptris;
+ em->tottri = i;
+ em->looptris = looptris;
+
+ BLI_assert(em->tottri <= looptris_tot);
#undef USE_TESSFACE_SPEEDUP
@@ -749,22 +783,18 @@ static void emDM_drawMappedFaces(DerivedMesh *dm,
if (poly_prev != GL_ZERO) glEnd();
}
-static void bmdm_get_tri_tex(BMesh *bm, BMLoop **ls, MLoopUV *luv[3], MLoopCol *lcol[3],
- int has_uv, int has_col)
+static void bmdm_get_tri_uv(BMLoop *ls[3], MLoopUV *luv[3], const int cd_loop_uv_offset)
{
- if (has_uv) {
- luv[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPUV);
- luv[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPUV);
- luv[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPUV);
- }
-
- if (has_col) {
- lcol[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPCOL);
- lcol[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPCOL);
- lcol[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPCOL);
- }
-
+ luv[0] = BM_ELEM_CD_GET_VOID_P(ls[0], cd_loop_uv_offset);
+ luv[1] = BM_ELEM_CD_GET_VOID_P(ls[1], cd_loop_uv_offset);
+ luv[2] = BM_ELEM_CD_GET_VOID_P(ls[2], cd_loop_uv_offset);
+}
+static void bmdm_get_tri_col(BMLoop *ls[3], MLoopCol *lcol[3], const int cd_loop_color_offset)
+{
+ lcol[0] = BM_ELEM_CD_GET_VOID_P(ls[0], cd_loop_color_offset);
+ lcol[1] = BM_ELEM_CD_GET_VOID_P(ls[1], cd_loop_color_offset);
+ lcol[2] = BM_ELEM_CD_GET_VOID_P(ls[2], cd_loop_color_offset);
}
static void emDM_drawFacesTex_common(DerivedMesh *dm,
@@ -780,15 +810,19 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm,
float (*vertexNos)[3] = bmdm->vertexNos;
BMFace *efa;
MLoopUV *luv[3], dummyluv = {{0}};
- MLoopCol *lcol[3] = {NULL}, dummylcol = {0};
- int i, has_vcol = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL);
- int has_uv = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY);
+ MLoopCol *lcol[3] = {NULL} /* , dummylcol = {0} */;
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const int cd_loop_color_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
+ const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
+ bool has_uv = (cd_loop_uv_offset != -1);
+ bool has_vcol = (cd_loop_color_offset != -1);
+ int i;
(void) compareDrawOptions;
luv[0] = luv[1] = luv[2] = &dummyluv;
- dummylcol.r = dummylcol.g = dummylcol.b = dummylcol.a = 255;
+ // dummylcol.r = dummylcol.g = dummylcol.b = dummylcol.a = 255; /* UNUSED */
/* always use smooth shading even for flat faces, else vertex colors wont interpolate */
glShadeModel(GL_SMOOTH);
@@ -800,7 +834,7 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm,
for (i = 0; i < em->tottri; i++) {
BMLoop **ls = em->looptris[i];
- MTexPoly *tp = has_uv ? CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY) : NULL;
+ MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ls[0]->f, cd_poly_tex_offset) : NULL;
MTFace mtf = {{{0}}};
/*unsigned char *cp = NULL;*/ /*UNUSED*/
int drawSmooth = BM_elem_flag_test(ls[0]->f, BM_ELEM_SMOOTH);
@@ -808,7 +842,7 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm,
efa = ls[0]->f;
- if (has_uv) {
+ if (cd_poly_tex_offset != -1) {
ME_MTEXFACE_CPY(&mtf, tp);
}
@@ -825,25 +859,27 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm,
if (!drawSmooth) {
glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]);
- bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
+ if (has_uv) bmdm_get_tri_uv(ls, luv, cd_loop_uv_offset);
+ if (has_vcol) bmdm_get_tri_col(ls, lcol, cd_loop_color_offset);
glTexCoord2fv(luv[0]->uv);
- if (lcol[0])
+ if (has_vcol)
glColor3ubv((const GLubyte *)&(lcol[0]->r));
glVertex3fv(vertexCos[BM_elem_index_get(ls[0]->v)]);
glTexCoord2fv(luv[1]->uv);
- if (lcol[1])
+ if (has_vcol)
glColor3ubv((const GLubyte *)&(lcol[1]->r));
glVertex3fv(vertexCos[BM_elem_index_get(ls[1]->v)]);
glTexCoord2fv(luv[2]->uv);
- if (lcol[2])
+ if (has_vcol)
glColor3ubv((const GLubyte *)&(lcol[2]->r));
glVertex3fv(vertexCos[BM_elem_index_get(ls[2]->v)]);
}
else {
- bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
+ if (has_uv) bmdm_get_tri_uv(ls, luv, cd_loop_uv_offset);
+ if (has_vcol) bmdm_get_tri_col(ls, lcol, cd_loop_color_offset);
glTexCoord2fv(luv[0]->uv);
if (lcol[0])
@@ -872,7 +908,7 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm,
for (i = 0; i < em->tottri; i++) {
BMLoop **ls = em->looptris[i];
- MTexPoly *tp = has_uv ? CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY) : NULL;
+ MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ls[0]->f, cd_poly_tex_offset) : NULL;
MTFace mtf = {{{0}}};
/*unsigned char *cp = NULL;*/ /*UNUSED*/
int drawSmooth = BM_elem_flag_test(ls[0]->f, BM_ELEM_SMOOTH);
@@ -880,12 +916,12 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm,
efa = ls[0]->f;
- if (has_uv) {
+ 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(&mtf, (has_vcol), efa->mat_nr);
else if (drawParamsMapped)
draw_option = drawParamsMapped(userData, BM_elem_index_get(efa));
else
@@ -897,46 +933,42 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm,
if (!drawSmooth) {
glNormal3fv(efa->no);
- bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
+ if (has_uv) bmdm_get_tri_uv(ls, luv, cd_loop_uv_offset);
+ if (has_vcol) bmdm_get_tri_col(ls, lcol, cd_loop_color_offset);
- if (luv[0])
- glTexCoord2fv(luv[0]->uv);
- if (lcol[0])
+ glTexCoord2fv(luv[0]->uv);
+ if (has_vcol)
glColor3ubv((const GLubyte *)&(lcol[0]->r));
glVertex3fv(ls[0]->v->co);
- if (luv[1])
- glTexCoord2fv(luv[1]->uv);
- if (lcol[1])
+ glTexCoord2fv(luv[1]->uv);
+ if (has_vcol)
glColor3ubv((const GLubyte *)&(lcol[1]->r));
glVertex3fv(ls[1]->v->co);
- if (luv[2])
- glTexCoord2fv(luv[2]->uv);
- if (lcol[2])
+ glTexCoord2fv(luv[2]->uv);
+ if (has_vcol)
glColor3ubv((const GLubyte *)&(lcol[2]->r));
glVertex3fv(ls[2]->v->co);
}
else {
- bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
+ if (has_uv) bmdm_get_tri_uv(ls, luv, cd_loop_uv_offset);
+ if (has_vcol) bmdm_get_tri_col(ls, lcol, cd_loop_color_offset);
- if (luv[0])
- glTexCoord2fv(luv[0]->uv);
- if (lcol[0])
+ glTexCoord2fv(luv[0]->uv);
+ if (has_vcol)
glColor3ubv((const GLubyte *)&(lcol[0]->r));
glNormal3fv(ls[0]->v->no);
glVertex3fv(ls[0]->v->co);
- if (luv[1])
- glTexCoord2fv(luv[1]->uv);
- if (lcol[1])
+ glTexCoord2fv(luv[1]->uv);
+ if (has_vcol)
glColor3ubv((const GLubyte *)&(lcol[1]->r));
glNormal3fv(ls[1]->v->no);
glVertex3fv(ls[1]->v->co);
- if (luv[2])
- glTexCoord2fv(luv[2]->uv);
- if (lcol[2])
+ glTexCoord2fv(luv[2]->uv);
+ if (has_vcol)
glColor3ubv((const GLubyte *)&(lcol[2]->r));
glNormal3fv(ls[2]->v->no);
glVertex3fv(ls[2]->v->co);
@@ -965,6 +997,43 @@ static void emDM_drawMappedFacesTex(DerivedMesh *dm,
emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
}
+/**
+ * \note
+ *
+ * For UV's:
+ * const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset);
+ *
+ * This is intentionally different to calling:
+ * CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, i);
+ *
+ * ... because the material may use layer names to select different UV's
+ * see: [#34378]
+ */
+static void emdm_pass_attrib_vertex_glsl(DMVertexAttribs *attribs, BMLoop *loop, int index_in_face)
+{
+ BMVert *eve = loop->v;
+ int i;
+
+ if (attribs->totorco) {
+ const float *orco = attribs->orco.array[BM_elem_index_get(eve)];
+ glVertexAttrib3fvARB(attribs->orco.gl_index, orco);
+ }
+ for (i = 0; i < attribs->tottface; i++) {
+ const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset);
+ glVertexAttrib2fvARB(attribs->tface[i].gl_index, luv->uv);
+ }
+ for (i = 0; i < attribs->totmcol; i++) {
+ const MLoopCol *cp = BM_ELEM_CD_GET_VOID_P(loop, attribs->mcol[i].em_offset);
+ GLubyte col[4];
+ col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
+ glVertexAttrib4ubvARB(attribs->mcol[i].gl_index, col);
+ }
+ if (attribs->tottang) {
+ const float *tang = attribs->tang.array[i * 4 + index_in_face];
+ glVertexAttrib3fvARB(attribs->tang.gl_index, tang);
+ }
+}
+
static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
DMSetMaterial setMaterial,
DMSetDrawOptions setDrawOptions,
@@ -980,7 +1049,7 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
DMVertexAttribs attribs;
GPUVertexAttribs gattribs;
- int i, b, matnr, new_matnr, do_draw;
+ int i, matnr, new_matnr, do_draw;
do_draw = FALSE;
matnr = -1;
@@ -991,30 +1060,6 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
glShadeModel(GL_SMOOTH);
BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
-#define PASSATTRIB(loop, eve, vert) { \
- if (attribs.totorco) { \
- float *orco = attribs.orco.array[BM_elem_index_get(eve)]; \
- glVertexAttrib3fvARB(attribs.orco.gl_index, orco); \
- } \
- for (b = 0; b < attribs.tottface; b++) { \
- MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, \
- CD_MLOOPUV, b); \
- glVertexAttrib2fvARB(attribs.tface[b].gl_index, _luv->uv); \
- } \
- for (b = 0; b < attribs.totmcol; b++) { \
- MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, \
- CD_MLOOPCOL, b); \
- GLubyte _col[4]; \
- _col[0] = _cp->b; _col[1] = _cp->g; _col[2] = _cp->r; _col[3] = _cp->a; \
- glVertexAttrib4ubvARB(attribs.mcol[b].gl_index, _col); \
- } \
- if (attribs.tottang) { \
- float *tang = attribs.tang.array[i * 4 + vert]; \
- glVertexAttrib3fvARB(attribs.tang.gl_index, tang); \
- } \
- } (void)0
-
-
for (i = 0, ltri = em->looptris[0]; i < em->tottri; i++, ltri += 3) {
int drawSmooth;
@@ -1037,20 +1082,20 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
if (vertexCos) glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]);
else glNormal3fv(efa->no);
- PASSATTRIB(ltri[0], ltri[0]->v, 0);
+ emdm_pass_attrib_vertex_glsl(&attribs, ltri[0], 0);
if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
else glVertex3fv(ltri[0]->v->co);
- PASSATTRIB(ltri[1], ltri[1]->v, 1);
+ emdm_pass_attrib_vertex_glsl(&attribs, ltri[1], 1);
if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
else glVertex3fv(ltri[1]->v->co);
- PASSATTRIB(ltri[2], ltri[2]->v, 2);
+ emdm_pass_attrib_vertex_glsl(&attribs, ltri[2], 2);
if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
else glVertex3fv(ltri[2]->v->co);
}
else {
- PASSATTRIB(ltri[0], ltri[0]->v, 0);
+ emdm_pass_attrib_vertex_glsl(&attribs, ltri[0], 0);
if (vertexCos) {
glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
@@ -1060,7 +1105,7 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
glVertex3fv(ltri[0]->v->co);
}
- PASSATTRIB(ltri[1], ltri[1]->v, 1);
+ emdm_pass_attrib_vertex_glsl(&attribs, ltri[1], 1);
if (vertexCos) {
glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
@@ -1070,7 +1115,7 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
glVertex3fv(ltri[1]->v->co);
}
- PASSATTRIB(ltri[2], ltri[2]->v, 2);
+ emdm_pass_attrib_vertex_glsl(&attribs, ltri[2], 2);
if (vertexCos) {
glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
@@ -1083,7 +1128,6 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
glEnd();
}
}
-#undef PASSATTRIB
}
static void emDM_drawFacesGLSL(DerivedMesh *dm,
@@ -1092,6 +1136,38 @@ static void emDM_drawFacesGLSL(DerivedMesh *dm,
dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
}
+/* emdm_pass_attrib_vertex_glsl's note about em_offset use applies here */
+static void emdm_pass_attrib_vertex_mat(DMVertexAttribs *attribs, BMLoop *loop, int index_in_face)
+{
+ BMVert *eve = loop->v;
+ int i;
+
+ if (attribs->totorco) {
+ float *orco = attribs->orco.array[BM_elem_index_get(eve)];
+ if (attribs->orco.gl_texco)
+ glTexCoord3fv(orco);
+ else
+ glVertexAttrib3fvARB(attribs->orco.gl_index, orco);
+ }
+ for (i = 0; i < attribs->tottface; i++) {
+ const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset);
+ if (attribs->tface[i].gl_texco)
+ glTexCoord2fv(luv->uv);
+ else
+ glVertexAttrib2fvARB(attribs->tface[i].gl_index, luv->uv);
+ }
+ for (i = 0; i < attribs->totmcol; i++) {
+ const MLoopCol *cp = BM_ELEM_CD_GET_VOID_P(loop, attribs->mcol[i].em_offset);
+ GLubyte col[4];
+ col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
+ glVertexAttrib4ubvARB(attribs->mcol[i].gl_index, col);
+ }
+ if (attribs->tottang) {
+ float *tang = attribs->tang.array[i * 4 + index_in_face];
+ glVertexAttrib4fvARB(attribs->tang.gl_index, tang);
+ }
+}
+
static void emDM_drawMappedFacesMat(DerivedMesh *dm,
void (*setMaterial)(void *userData, int, void *attribs),
int (*setFace)(void *userData, int index), void *userData)
@@ -1105,7 +1181,7 @@ static void emDM_drawMappedFacesMat(DerivedMesh *dm,
BMLoop **ltri;
DMVertexAttribs attribs = {{{0}}};
GPUVertexAttribs gattribs;
- int i, b, matnr, new_matnr;
+ int i, matnr, new_matnr;
matnr = -1;
@@ -1114,35 +1190,6 @@ static void emDM_drawMappedFacesMat(DerivedMesh *dm,
BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
-#define PASSATTRIB(loop, eve, vert) { \
- if (attribs.totorco) { \
- float *orco = attribs.orco.array[BM_elem_index_get(eve)]; \
- if (attribs.orco.gl_texco) \
- glTexCoord3fv(orco); \
- else \
- glVertexAttrib3fvARB(attribs.orco.gl_index, orco); \
- } \
- for (b = 0; b < attribs.tottface; b++) { \
- MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, \
- CD_MLOOPUV, b); \
- if (attribs.tface[b].gl_texco) \
- glTexCoord2fv(_luv->uv); \
- else \
- glVertexAttrib2fvARB(attribs.tface[b].gl_index, _luv->uv); \
- } \
- for (b = 0; b < attribs.totmcol; b++) { \
- MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, \
- CD_MLOOPCOL, b); \
- GLubyte _col[4]; \
- _col[0] = _cp->b; _col[1] = _cp->g; _col[2] = _cp->r; _col[3] = _cp->a; \
- glVertexAttrib4ubvARB(attribs.mcol[b].gl_index, _col); \
- } \
- if (attribs.tottang) { \
- float *tang = attribs.tang.array[i * 4 + vert]; \
- glVertexAttrib4fvARB(attribs.tang.gl_index, tang); \
- } \
- } (void)0
-
for (i = 0, ltri = em->looptris[0]; i < em->tottri; i++, ltri += 3) {
int drawSmooth;
@@ -1166,21 +1213,21 @@ static void emDM_drawMappedFacesMat(DerivedMesh *dm,
if (vertexCos) glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]);
else glNormal3fv(efa->no);
- PASSATTRIB(ltri[0], ltri[0]->v, 0);
+ emdm_pass_attrib_vertex_mat(&attribs, ltri[0], 0);
if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
else glVertex3fv(ltri[0]->v->co);
- PASSATTRIB(ltri[1], ltri[1]->v, 1);
+ emdm_pass_attrib_vertex_mat(&attribs, ltri[1], 1);
if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
else glVertex3fv(ltri[1]->v->co);
- PASSATTRIB(ltri[2], ltri[2]->v, 2);
+ emdm_pass_attrib_vertex_mat(&attribs, ltri[2], 2);
if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
else glVertex3fv(ltri[2]->v->co);
}
else {
- PASSATTRIB(ltri[0], ltri[0]->v, 0);
+ emdm_pass_attrib_vertex_mat(&attribs, ltri[0], 0);
if (vertexCos) {
glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
@@ -1190,7 +1237,7 @@ static void emDM_drawMappedFacesMat(DerivedMesh *dm,
glVertex3fv(ltri[0]->v->co);
}
- PASSATTRIB(ltri[1], ltri[1]->v, 1);
+ emdm_pass_attrib_vertex_mat(&attribs, ltri[1], 1);
if (vertexCos) {
glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
@@ -1200,7 +1247,7 @@ static void emDM_drawMappedFacesMat(DerivedMesh *dm,
glVertex3fv(ltri[1]->v->co);
}
- PASSATTRIB(ltri[2], ltri[2]->v, 2);
+ emdm_pass_attrib_vertex_mat(&attribs, ltri[2], 2);
if (vertexCos) {
glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
@@ -1212,7 +1259,6 @@ static void emDM_drawMappedFacesMat(DerivedMesh *dm,
}
glEnd();
}
-#undef PASSATTRIB
}
static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
@@ -1276,14 +1322,16 @@ static int emDM_getNumPolys(DerivedMesh *dm)
static int bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *vert_r)
{
+ float *f;
+
copy_v3_v3(vert_r->co, ev->co);
normal_float_to_short_v3(vert_r->no, ev->no);
vert_r->flag = BM_vert_flag_to_mflag(ev);
- if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
- vert_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->vdata, ev, CD_BWEIGHT) * 255.0f);
+ if ((f = CustomData_bmesh_get(&bm->vdata, ev->head.data, CD_BWEIGHT))) {
+ vert_r->bweight = (unsigned char)((*f) * 255.0f);
}
return 1;
@@ -1299,8 +1347,8 @@ static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
return;
}
- // ev = EDBM_vert_at_index(bmdm->tc, index);
- ev = BM_vert_at_index(bmdm->tc->bm, index); /* warning, does list loop, _not_ ideal */
+ ev = bmdm->tc->vert_index[index]; /* should be EDBM_vert_at_index() */
+ // ev = BM_vert_at_index(bmdm->tc->bm, index); /* warning, does list loop, _not_ ideal */
bmvert_to_mvert(bmdm->tc->bm, ev, vert_r);
if (bmdm->vertexCos)
@@ -1312,27 +1360,27 @@ static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
BMesh *bm = bmdm->tc->bm;
BMEdge *e;
+ float *f;
if (index < 0 || index >= bmdm->te) {
printf("error in emDM_getEdge.\n");
return;
}
- // e = EDBM_edge_at_index(bmdm->tc, index);
- e = BM_edge_at_index(bmdm->tc->bm, index); /* warning, does list loop, _not_ ideal */
-
- if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
- edge_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->edata, e, CD_BWEIGHT) * 255.0f);
- }
-
- if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
- edge_r->crease = (unsigned char) (BM_elem_float_data_get(&bm->edata, e, CD_CREASE) * 255.0f);
- }
+ e = bmdm->tc->edge_index[index]; /* should be EDBM_edge_at_index() */
+ // e = BM_edge_at_index(bmdm->tc->bm, index); /* warning, does list loop, _not_ ideal */
edge_r->flag = BM_edge_flag_to_mflag(e);
edge_r->v1 = BM_elem_index_get(e->v1);
edge_r->v2 = BM_elem_index_get(e->v2);
+
+ if ((f = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BWEIGHT))) {
+ edge_r->bweight = (unsigned char)((*f) * 255.0f);
+ }
+ if ((f = CustomData_bmesh_get(&bm->edata, e->head.data, CD_CREASE))) {
+ edge_r->crease = (unsigned char)((*f) * 255.0f);
+ }
}
static void emDM_getTessFace(DerivedMesh *dm, int index, MFace *face_r)
@@ -1367,7 +1415,7 @@ static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
BMesh *bm = bmdm->tc->bm;
BMVert *eve;
BMIter iter;
- const int has_bweight = CustomData_has_layer(&bm->vdata, CD_BWEIGHT);
+ const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
if (bmdm->vertexCos) {
int i;
@@ -1377,9 +1425,8 @@ static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
normal_float_to_short_v3(vert_r->no, eve->no);
vert_r->flag = BM_vert_flag_to_mflag(eve);
- if (has_bweight) {
- vert_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->vdata, eve, CD_BWEIGHT) * 255.0f);
- }
+ vert_r->bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset) : 0;
+
vert_r++;
}
}
@@ -1389,9 +1436,8 @@ static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
normal_float_to_short_v3(vert_r->no, eve->no);
vert_r->flag = BM_vert_flag_to_mflag(eve);
- if (has_bweight) {
- vert_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->vdata, eve, CD_BWEIGHT) * 255.0f);
- }
+ vert_r->bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset) : 0;
+
vert_r++;
}
}
@@ -1402,24 +1448,20 @@ static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
BMEdge *eed;
BMIter iter;
- const int has_bweight = CustomData_has_layer(&bm->edata, CD_BWEIGHT);
- const int has_crease = CustomData_has_layer(&bm->edata, CD_CREASE);
+
+ 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);
BM_mesh_elem_index_ensure(bm, BM_VERT);
BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (has_bweight) {
- edge_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->edata, eed, CD_BWEIGHT) * 255.0f);
- }
-
- if (has_crease) {
- edge_r->crease = (unsigned char) (BM_elem_float_data_get(&bm->edata, eed, CD_CREASE) * 255.0f);
- }
+ edge_r->v1 = BM_elem_index_get(eed->v1);
+ edge_r->v2 = BM_elem_index_get(eed->v2);
edge_r->flag = BM_edge_flag_to_mflag(eed);
- edge_r->v1 = BM_elem_index_get(eed->v1);
- edge_r->v2 = BM_elem_index_get(eed->v2);
+ edge_r->crease = (cd_edge_crease_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset) : 0;
+ edge_r->bweight = (cd_edge_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset) : 0;
edge_r++;
}
@@ -1442,6 +1484,7 @@ static void emDM_copyTessFaceArray(DerivedMesh *dm, MFace *face_r)
face_r->mat_nr = (unsigned char) ef->mat_nr;
face_r->flag = BM_face_flag_to_mflag(ef);
+ face_r->edcode = 0;
face_r->v1 = BM_elem_index_get(l[0]->v);
face_r->v2 = BM_elem_index_get(l[1]->v);
@@ -1627,6 +1670,9 @@ DerivedMesh *getEditDerivedBMesh(BMEditMesh *em,
DM_init((DerivedMesh *)bmdm, DM_TYPE_EDITBMESH, em->bm->totvert,
em->bm->totedge, em->tottri, em->bm->totloop, em->bm->totface);
+ /* could also get from the objects mesh directly */
+ bmdm->dm.cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
+
bmdm->dm.getVertCos = emDM_getVertCos;
bmdm->dm.getMinMax = emDM_getMinMax;
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 1f6db19ac27..9e8693e957e 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -562,7 +562,7 @@ int closest_point_on_surface(SurfaceModifierData *surmd, const float co[3], floa
if (mface->v4)
add_v3_v3(surface_vel, surmd->v[mface->v4].co);
- mul_v3_fl(surface_vel, mface->v4 ? 0.25f : 0.333f);
+ mul_v3_fl(surface_vel, mface->v4 ? 0.25f : (1.0f / 3.0f));
}
return 1;
}
@@ -769,7 +769,7 @@ static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedP
mul_m4_v3(eff->ob->imat, tex_co);
}
- hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result);
+ hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result, NULL);
if (hasrgb && mode==PFIELD_TEX_RGB) {
force[0] = (0.5f - result->tr) * strength;
@@ -780,15 +780,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);
+ multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+1, NULL);
tex_co[0] -= nabla;
tex_co[1] += nabla;
- multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+2);
+ multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+2, NULL);
tex_co[1] -= nabla;
tex_co[2] += nabla;
- multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+3);
+ multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+3, NULL);
if (mode == PFIELD_TEX_GRAD || !hasrgb) { /* if we don't have rgb fall back to grad */
/* generate intensity if texture only has rgb value */
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index ec61311d89e..f63eb9f87e3 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -169,7 +169,7 @@ void copy_fcurves(ListBase *dst, ListBase *src)
/* ----------------- Finding F-Curves -------------------------- */
/* high level function to get an fcurve from C without having the rna */
-FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *prop_name, int index, char *driven)
+FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *prop_name, int index, bool *r_driven)
{
/* anim vars */
AnimData *adt = BKE_animdata_from_id(id);
@@ -180,8 +180,8 @@ FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *pro
PropertyRNA *prop;
char *path;
- if (driven)
- *driven = FALSE;
+ if (r_driven)
+ *r_driven = false;
/* only use the current action ??? */
if (ELEM(NULL, adt, adt->action))
@@ -201,8 +201,8 @@ FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, const char *pro
/* if not animated, check if driven */
if ((fcu == NULL) && (adt->drivers.first)) {
fcu = list_find_fcurve(&adt->drivers, path, index);
- if (fcu && driven)
- *driven = TRUE;
+ if (fcu && r_driven)
+ *r_driven = true;
fcu = NULL;
}
@@ -305,11 +305,11 @@ 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, int *driven)
+FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction **action, bool *r_driven)
{
FCurve *fcu = NULL;
- *driven = 0;
+ *r_driven = false;
/* there must be some RNA-pointer + property combon */
if (prop && ptr->id.data && RNA_property_animateable(ptr, prop)) {
@@ -331,7 +331,7 @@ FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction
fcu = list_find_fcurve(&adt->drivers, path, rnaindex);
if (fcu)
- *driven = 1;
+ *r_driven = true;
}
if (fcu && action)
@@ -354,13 +354,13 @@ FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction
/* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_fcurve)
* Returns the index to insert at (data already at that index will be offset if replace is 0)
*/
-int binarysearch_bezt_index(BezTriple array[], float frame, int arraylen, short *replace)
+int binarysearch_bezt_index(BezTriple array[], float frame, int arraylen, bool *r_replace)
{
int start = 0, end = arraylen;
int loopbreaker = 0, maxloop = arraylen * 2;
/* initialize replace-flag first */
- *replace = 0;
+ *r_replace = false;
/* sneaky optimizations (don't go through searching process if...):
* - keyframe to be added is to be added out of current bounds
@@ -377,7 +377,7 @@ int binarysearch_bezt_index(BezTriple array[], float frame, int arraylen, short
/* 'First' Keyframe (when only one keyframe, this case is used) */
framenum = array[0].vec[1][0];
if (IS_EQT(frame, framenum, BEZT_BINARYSEARCH_THRESH)) {
- *replace = 1;
+ *r_replace = true;
return 0;
}
else if (frame < framenum)
@@ -386,7 +386,7 @@ int binarysearch_bezt_index(BezTriple array[], float frame, int arraylen, short
/* 'Last' Keyframe */
framenum = array[(arraylen - 1)].vec[1][0];
if (IS_EQT(frame, framenum, BEZT_BINARYSEARCH_THRESH)) {
- *replace = 1;
+ *r_replace = true;
return (arraylen - 1);
}
else if (frame > framenum)
@@ -404,7 +404,7 @@ int binarysearch_bezt_index(BezTriple array[], float frame, int arraylen, short
/* check if exactly equal to midpoint */
if (IS_EQT(frame, midfra, BEZT_BINARYSEARCH_THRESH)) {
- *replace = 1;
+ *r_replace = true;
return mid;
}
@@ -500,8 +500,8 @@ short calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, flo
BLI_assert(bezt_last != NULL);
if (include_handles) {
- xminv = MIN3(xminv, bezt_first->vec[0][0], bezt_first->vec[1][0]);
- xmaxv = MAX3(xmaxv, bezt_last->vec[1][0], bezt_last->vec[2][0]);
+ xminv = min_fff(xminv, bezt_first->vec[0][0], bezt_first->vec[1][0]);
+ xmaxv = max_fff(xmaxv, bezt_last->vec[1][0], bezt_last->vec[2][0]);
}
else {
xminv = min_ff(xminv, bezt_first->vec[1][0]);
@@ -517,8 +517,8 @@ short calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, flo
for (bezt = fcu->bezt, i = 0; i < fcu->totvert; bezt++, i++) {
if ((do_sel_only == FALSE) || BEZSELECTED(bezt)) {
if (include_handles) {
- yminv = MIN4(yminv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]);
- ymaxv = MAX4(ymaxv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]);
+ yminv = min_ffff(yminv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]);
+ ymaxv = max_ffff(ymaxv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]);
}
else {
yminv = min_ff(yminv, bezt->vec[1][1]);
@@ -859,7 +859,7 @@ void testhandles_fcurve(FCurve *fcu, const short use_handle)
short flag = 0;
/* flag is initialized as selection status
- * of beztriple control-points (labelled 0,1,2)
+ * of beztriple control-points (labelled 0, 1, 2)
*/
if (bezt->f2 & SELECT) flag |= (1 << 1); // == 2
if (use_handle == FALSE) {
@@ -986,9 +986,9 @@ typedef struct DriverVarTypeInfo {
float (*get_value)(ChannelDriver *driver, DriverVar *dvar);
/* allocation of target slots */
- int num_targets; /* number of target slots required */
+ int num_targets; /* number of target slots required */
const char *target_names[MAX_DRIVER_TARGETS]; /* UI names that should be given to the slots */
- int target_flags[MAX_DRIVER_TARGETS]; /* flags defining the requirements for each slot */
+ short target_flags[MAX_DRIVER_TARGETS]; /* flags defining the requirements for each slot */
} DriverVarTypeInfo;
/* Macro to begin definitions */
@@ -1014,7 +1014,7 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
PointerRNA id_ptr, ptr;
PropertyRNA *prop;
ID *id;
- int index;
+ int index = -1;
float value = 0.0f;
/* sanity check */
@@ -1024,11 +1024,13 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
id = dtar_id_ensure_proxy_from(dtar->id);
/* error check for missing pointer... */
- /* TODO: tag the specific target too as having issues */
if (id == NULL) {
- printf("Error: driver has an invalid target to use\n");
- if (G.debug & G_DEBUG) printf("\tpath = %s\n", dtar->rna_path);
+ if (G.debug & G_DEBUG) {
+ printf("Error: driver has an invalid target to use (path = %s)\n", dtar->rna_path);
+ }
+
driver->flag |= DRIVER_FLAG_INVALID;
+ dtar->flag |= DTAR_FLAG_INVALID;
return 0.0f;
}
@@ -1039,7 +1041,7 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
if (RNA_path_resolve_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) {
if (RNA_property_array_check(prop)) {
/* array */
- if (index < RNA_property_array_length(&ptr, prop)) {
+ if ((index >= 0) && (index < RNA_property_array_length(&ptr, prop))) {
switch (RNA_property_type(prop)) {
case PROP_BOOLEAN:
value = (float)RNA_property_boolean_get_index(&ptr, prop, index);
@@ -1054,6 +1056,17 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
break;
}
}
+ else {
+ /* out of bounds */
+ if (G.debug & G_DEBUG) {
+ printf("Driver Evaluation Error: array index is out of bounds for %s -> %s (%d)",
+ id->name, dtar->rna_path, index);
+ }
+
+ driver->flag |= DRIVER_FLAG_INVALID;
+ dtar->flag |= DTAR_FLAG_INVALID;
+ return 0.0f;
+ }
}
else {
/* not an array */
@@ -1074,16 +1087,20 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
break;
}
}
-
}
else {
- if (G.debug & G_DEBUG)
+ /* path couldn't be resolved */
+ if (G.debug & G_DEBUG) {
printf("Driver Evaluation Error: cannot resolve target for %s -> %s\n", id->name, dtar->rna_path);
+ }
driver->flag |= DRIVER_FLAG_INVALID;
+ dtar->flag |= DTAR_FLAG_INVALID;
return 0.0f;
}
+ /* if we're still here, we should be ok... */
+ dtar->flag &= ~DTAR_FLAG_INVALID;
return value;
}
@@ -1122,25 +1139,45 @@ static float dvar_eval_singleProp(ChannelDriver *driver, DriverVar *dvar)
/* evaluate 'rotation difference' driver variable */
static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar)
{
+ DriverTarget *dtar1 = &dvar->targets[0];
+ DriverTarget *dtar2 = &dvar->targets[1];
bPoseChannel *pchan, *pchan2;
float q1[4], q2[4], quat[4], angle;
/* get pose channels, and check if we've got two */
- pchan = dtar_get_pchan_ptr(driver, &dvar->targets[0]);
- pchan2 = dtar_get_pchan_ptr(driver, &dvar->targets[1]);
+ pchan = dtar_get_pchan_ptr(driver, dtar1);
+ pchan2 = dtar_get_pchan_ptr(driver, dtar2);
if (ELEM(NULL, pchan, pchan2)) {
/* disable this driver, since it doesn't work correctly... */
driver->flag |= DRIVER_FLAG_INVALID;
/* check what the error was */
- if ((pchan == NULL) && (pchan2 == NULL))
- printf("Driver Evaluation Error: Rotational difference failed - first 2 targets invalid\n");
- else if (pchan == NULL)
- printf("Driver Evaluation Error: Rotational difference failed - first target not valid PoseChannel\n");
- else if (pchan2 == NULL)
- printf("Driver Evaluation Error: Rotational difference failed - second target not valid PoseChannel\n");
+ if ((pchan == NULL) && (pchan2 == NULL)) {
+ if (G.debug & G_DEBUG) {
+ printf("Driver Evaluation Error: Rotational difference failed - first 2 targets invalid\n");
+ }
+
+ dtar1->flag |= DTAR_FLAG_INVALID;
+ dtar2->flag |= DTAR_FLAG_INVALID;
+ }
+ else if (pchan == NULL) {
+ if (G.debug & G_DEBUG) {
+ printf("Driver Evaluation Error: Rotational difference failed - first target not valid PoseChannel\n");
+ }
+
+ dtar1->flag |= DTAR_FLAG_INVALID;
+ dtar2->flag &= ~DTAR_FLAG_INVALID;
+ }
+ else if (pchan2 == NULL) {
+ if (G.debug & G_DEBUG) {
+ printf("Driver Evaluation Error: Rotational difference failed - second target not valid PoseChannel\n");
+ }
+ dtar1->flag &= ~DTAR_FLAG_INVALID;
+ dtar2->flag |= DTAR_FLAG_INVALID;
+ }
+
/* stop here... */
return 0.0f;
}
@@ -1163,22 +1200,53 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
{
float loc1[3] = {0.0f, 0.0f, 0.0f};
float loc2[3] = {0.0f, 0.0f, 0.0f};
+ short valid_targets = 0;
- /* get two location values */
- /* NOTE: for now, these are all just worldspace */
+ /* Perform two passes
+ *
+ * FIRST PASS - to just check that everything works...
+ * NOTE: we use loops here to reduce code duplication, though in practice,
+ * there can only be 2 items or else we run into some problems later
+ */
DRIVER_TARGETS_USED_LOOPER(dvar)
{
- /* get pointer to loc values to store in */
Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
- bPoseChannel *pchan;
- float tmp_loc[3];
/* check if this target has valid data */
if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) {
/* invalid target, so will not have enough targets */
driver->flag |= DRIVER_FLAG_INVALID;
- return 0.0f;
+ dtar->flag |= DTAR_FLAG_INVALID;
+ }
+ else {
+ /* target seems to be OK now... */
+ dtar->flag &= ~DTAR_FLAG_INVALID;
+ valid_targets++;
}
+ }
+ DRIVER_TARGETS_LOOPER_END
+
+ /* make sure we have enough valid targets to use - all or nothing for now... */
+ if (valid_targets < dvar->num_targets) {
+ if (G.debug & G_DEBUG) {
+ printf("LocDiff DVar: not enough valid targets (n = %d) (a = %p, b = %p)\n",
+ valid_targets, dvar->targets[0].id, dvar->targets[1].id);
+ }
+ return 0.0f;
+ }
+
+
+ /* SECOND PASS: get two location values */
+ /* NOTE: for now, these are all just worldspace */
+ DRIVER_TARGETS_USED_LOOPER(dvar)
+ {
+ /* get pointer to loc values to store in */
+ Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
+ bPoseChannel *pchan;
+ float tmp_loc[3];
+
+ /* after the checks above, the targets should be valid here... */
+ BLI_assert((ob != NULL) && (GS(ob->id.name) != ID_OB));
/* try to get posechannel */
pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name);
@@ -1192,7 +1260,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);
- 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);
/* ... and from that, we get our transform */
copy_v3_v3(tmp_loc, mat[3]);
@@ -1217,7 +1285,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);
- 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);
/* ... and from that, we get our transform */
copy_v3_v3(tmp_loc, mat[3]);
@@ -1264,8 +1332,13 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) {
/* invalid target, so will not have enough targets */
driver->flag |= DRIVER_FLAG_INVALID;
+ dtar->flag |= DTAR_FLAG_INVALID;
return 0.0f;
}
+ else {
+ /* target should be valid now */
+ dtar->flag &= ~DTAR_FLAG_INVALID;
+ }
/* try to get posechannel */
pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name);
@@ -1288,7 +1361,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);
- 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);
}
else {
/* specially calculate local matrix, since chan_mat is not valid
@@ -1315,7 +1388,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);
- 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);
}
else {
/* transforms to matrix */
@@ -1458,12 +1531,12 @@ void driver_change_variable_type(DriverVar *dvar, int type)
*/
DRIVER_TARGETS_USED_LOOPER(dvar)
{
- int flags = dvti->target_flags[tarIndex];
+ short flags = dvti->target_flags[tarIndex];
/* store the flags */
dtar->flag = flags;
- /* object ID types only, or idtype not yet initialized*/
+ /* object ID types only, or idtype not yet initialized */
if ((flags & DTAR_FLAG_ID_OB_ONLY) || (dtar->idtype == 0))
dtar->idtype = ID_OB;
}
@@ -2022,12 +2095,12 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime
}
else {
/* bezier interpolation */
- /* v1,v2 are the first keyframe and its 2nd handle */
+ /* (v1, v2) are the first keyframe and its 2nd handle */
v1[0] = prevbezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
v2[0] = prevbezt->vec[2][0];
v2[1] = prevbezt->vec[2][1];
- /* v3,v4 are the last keyframe's 1st handle + the last keyframe */
+ /* (v3, v4) are the last keyframe's 1st handle + the last keyframe */
v3[0] = bezt->vec[0][0];
v3[1] = bezt->vec[0][1];
v4[0] = bezt->vec[1][0];
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index 2b393b4d90b..19912a19d94 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -141,55 +141,34 @@ static void fcm_generator_verify(FModifier *fcm)
switch (data->mode) {
case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */
{
+ const int arraysize_new = data->poly_order + 1;
/* arraysize needs to be order+1, so resize if not */
- if (data->arraysize != (data->poly_order + 1)) {
- float *nc;
-
- /* make new coefficients array, and copy over as much data as can fit */
- nc = MEM_callocN(sizeof(float) * (data->poly_order + 1), "FMod_Generator_Coefs");
-
+ if (data->arraysize != arraysize_new) {
if (data->coefficients) {
- if ((int)data->arraysize > (data->poly_order + 1))
- memcpy(nc, data->coefficients, sizeof(float) * (data->poly_order + 1));
- else
- memcpy(nc, data->coefficients, sizeof(float) * data->arraysize);
-
- /* free the old data */
- MEM_freeN(data->coefficients);
+ data->coefficients = MEM_recallocN(data->coefficients, sizeof(float) * arraysize_new);
}
-
- /* set the new data */
- data->coefficients = nc;
- data->arraysize = data->poly_order + 1;
+ else {
+ data->coefficients = MEM_callocN(sizeof(float) * arraysize_new, "FMod_Generator_Coefs");
+ }
+ data->arraysize = arraysize_new;
}
+ break;
}
- break;
-
case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* expanded polynomial expression */
{
- /* arraysize needs to be 2*order, so resize if not */
- if (data->arraysize != (data->poly_order * 2)) {
- float *nc;
-
- /* make new coefficients array, and copy over as much data as can fit */
- nc = MEM_callocN(sizeof(float) * (data->poly_order * 2), "FMod_Generator_Coefs");
-
+ const int arraysize_new = data->poly_order * 2;
+ /* arraysize needs to be (2 * order), so resize if not */
+ if (data->arraysize != arraysize_new) {
if (data->coefficients) {
- if (data->arraysize > (unsigned int)(data->poly_order * 2))
- memcpy(nc, data->coefficients, sizeof(float) * (data->poly_order * 2));
- else
- memcpy(nc, data->coefficients, sizeof(float) * data->arraysize);
-
- /* free the old data */
- MEM_freeN(data->coefficients);
+ data->coefficients = MEM_recallocN(data->coefficients, sizeof(float) * arraysize_new);
}
-
- /* set the new data */
- data->coefficients = nc;
- data->arraysize = data->poly_order * 2;
+ else {
+ data->coefficients = MEM_callocN(sizeof(float) * arraysize_new, "FMod_Generator_Coefs");
+ }
+ data->arraysize = arraysize_new;
}
+ break;
}
- break;
}
}
@@ -501,6 +480,92 @@ static FModifierTypeInfo FMI_ENVELOPE = {
fcm_envelope_evaluate /* evaluate */
};
+/* exported function for finding points */
+
+/* Binary search algorithm for finding where to insert Envelope Data Point.
+ * Returns the index to insert at (data already at that index will be offset if replace is 0)
+ */
+#define BINARYSEARCH_FRAMEEQ_THRESH 0.0001f
+
+int BKE_fcm_envelope_find_index(FCM_EnvelopeData array[], float frame, int arraylen, bool *r_exists)
+{
+ int start = 0, end = arraylen;
+ int loopbreaker = 0, maxloop = arraylen * 2;
+
+ /* initialize exists-flag first */
+ *r_exists = false;
+
+ /* sneaky optimizations (don't go through searching process if...):
+ * - keyframe to be added is to be added out of current bounds
+ * - keyframe to be added would replace one of the existing ones on bounds
+ */
+ if ((arraylen <= 0) || (array == NULL)) {
+ printf("Warning: binarysearch_fcm_envelopedata_index() encountered invalid array\n");
+ return 0;
+ }
+ else {
+ /* check whether to add before/after/on */
+ float framenum;
+
+ /* 'First' Point (when only one point, this case is used) */
+ framenum = array[0].time;
+ if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
+ *r_exists = true;
+ return 0;
+ }
+ else if (frame < framenum) {
+ return 0;
+ }
+
+ /* 'Last' Point */
+ framenum = array[(arraylen - 1)].time;
+ if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
+ *r_exists = true;
+ return (arraylen - 1);
+ }
+ else if (frame > framenum) {
+ return arraylen;
+ }
+ }
+
+
+ /* most of the time, this loop is just to find where to put it
+ * - 'loopbreaker' is just here to prevent infinite loops
+ */
+ for (loopbreaker = 0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) {
+ /* compute and get midpoint */
+ int mid = start + ((end - start) / 2); /* we calculate the midpoint this way to avoid int overflows... */
+ float midfra = array[mid].time;
+
+ /* check if exactly equal to midpoint */
+ if (IS_EQT(frame, midfra, BINARYSEARCH_FRAMEEQ_THRESH)) {
+ *r_exists = true;
+ return mid;
+ }
+
+ /* repeat in upper/lower half */
+ if (frame > midfra) {
+ start = mid + 1;
+ }
+ else if (frame < midfra) {
+ end = mid - 1;
+ }
+ }
+
+ /* print error if loop-limit exceeded */
+ if (loopbreaker == (maxloop - 1)) {
+ printf("Error: binarysearch_fcm_envelopedata_index() was taking too long\n");
+
+ // include debug info
+ printf("\tround = %d: start = %d, end = %d, arraylen = %d\n", loopbreaker, start, end, arraylen);
+ }
+
+ /* not found, so return where to place it */
+ return start;
+}
+#undef BINARYSEARCH_FRAMEEQ_THRESH
+
+
/* Cycles F-Curve Modifier --------------------------- */
/* This modifier changes evaltime to something that exists within the curve's frame-range,
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index d4634748c71..b3edeb67928 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -101,9 +101,9 @@ void BKE_vfont_free(struct VFont *vf)
static void *builtin_font_data = NULL;
static int builtin_font_size = 0;
-int BKE_vfont_is_builtin(struct VFont *vfont)
+bool BKE_vfont_is_builtin(struct VFont *vfont)
{
- return (strcmp(vfont->name, FO_BUILTIN_NAME) == 0);
+ return STREQ(vfont->name, FO_BUILTIN_NAME);
}
void BKE_vfont_builtin_register(void *mem, int size)
@@ -188,18 +188,14 @@ VFont *BKE_vfont_load(Main *bmain, const char *name)
PackedFile *temp_pf = NULL;
int is_builtin;
- if (strcmp(name, FO_BUILTIN_NAME) == 0) {
+ if (STREQ(name, FO_BUILTIN_NAME)) {
BLI_strncpy(filename, name, sizeof(filename));
pf = get_builtin_packedfile();
is_builtin = TRUE;
}
else {
- char dir[FILE_MAXDIR];
-
- BLI_strncpy(dir, name, sizeof(dir));
- BLI_splitdirstring(dir, filename);
-
+ BLI_split_file_part(name, filename, sizeof(filename));
pf = newPackedFile(NULL, name, bmain->name);
temp_pf = newPackedFile(NULL, name, bmain->name);
@@ -947,10 +943,13 @@ makebreak:
ct = chartransdata;
for (i = 0; i < slen; i++) {
if (ct->linenr == lnr) {
- if (ct->charnr == cnr) break;
- if ( (ct + 1)->charnr == 0) break;
+ if ((ct->charnr == cnr) || ((ct + 1)->charnr == 0)) {
+ break;
+ }
+ }
+ else if (ct->linenr > lnr) {
+ break;
}
- else if (ct->linenr > lnr) break;
cu->pos++;
ct++;
}
@@ -962,9 +961,9 @@ makebreak:
float si, co;
ct = chartransdata + cu->pos;
- si = (float)sin(ct->rot);
- co = (float)cos(ct->rot);
-
+ si = sinf(ct->rot);
+ co = cosf(ct->rot);
+
f = cu->editfont->textcurs[0];
f[0] = cu->fsize * (-0.1f * co + ct->xof);
diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c
new file mode 100644
index 00000000000..bcbc3dd99c6
--- /dev/null
+++ b/source/blender/blenkernel/intern/freestyle.c
@@ -0,0 +1,234 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/freestyle.c
+ * \ingroup bke
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_freestyle_types.h"
+#include "DNA_group_types.h"
+
+#include "BKE_freestyle.h"
+#include "BKE_linestyle.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+
+// function declarations
+static FreestyleLineSet *alloc_lineset();
+static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset);
+static FreestyleModuleConfig *alloc_module();
+static void copy_module(FreestyleModuleConfig *new_module, FreestyleModuleConfig *module);
+
+void BKE_freestyle_config_init(FreestyleConfig *config)
+{
+ config->mode = FREESTYLE_CONTROL_EDITOR_MODE;
+
+ config->modules.first = config->modules.last = NULL;
+ config->flags = 0;
+ config->sphere_radius = 1.0f;
+ config->dkr_epsilon = 0.0f;
+ config->crease_angle = DEG2RADF(134.43f);
+
+ config->linesets.first = config->linesets.last = NULL;
+}
+
+void BKE_freestyle_config_free(FreestyleConfig *config)
+{
+ FreestyleLineSet *lineset;
+
+ for (lineset = (FreestyleLineSet *)config->linesets.first; lineset; lineset = lineset->next) {
+ if (lineset->group) {
+ lineset->group->id.us--;
+ lineset->group = NULL;
+ }
+ lineset->linestyle->id.us--;
+ lineset->linestyle = NULL;
+ }
+ BLI_freelistN(&config->linesets);
+ BLI_freelistN(&config->modules);
+}
+
+void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *config)
+{
+ FreestyleLineSet *lineset, *new_lineset;
+ FreestyleModuleConfig *module, *new_module;
+
+ new_config->mode = config->mode;
+ new_config->raycasting_algorithm = config->raycasting_algorithm; /* deprecated */
+ new_config->flags = config->flags;
+ new_config->sphere_radius = config->sphere_radius;
+ new_config->dkr_epsilon = config->dkr_epsilon;
+ new_config->crease_angle = config->crease_angle;
+
+ new_config->linesets.first = new_config->linesets.last = NULL;
+ for (lineset = (FreestyleLineSet *)config->linesets.first; lineset; lineset = lineset->next) {
+ new_lineset = alloc_lineset();
+ copy_lineset(new_lineset, lineset);
+ BLI_addtail(&new_config->linesets, (void *)new_lineset);
+ }
+
+ new_config->modules.first = new_config->modules.last = NULL;
+ for (module = (FreestyleModuleConfig *)config->modules.first; module; module = module->next) {
+ new_module = alloc_module();
+ copy_module(new_module, module);
+ BLI_addtail(&new_config->modules, (void *)new_module);
+ }
+}
+
+static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset)
+{
+ new_lineset->linestyle = lineset->linestyle;
+ new_lineset->linestyle->id.us++;
+ new_lineset->flags = lineset->flags;
+ new_lineset->selection = lineset->selection;
+ new_lineset->qi = lineset->qi;
+ new_lineset->qi_start = lineset->qi_start;
+ new_lineset->qi_end = lineset->qi_end;
+ new_lineset->edge_types = lineset->edge_types;
+ new_lineset->exclude_edge_types = lineset->exclude_edge_types;
+ new_lineset->group = lineset->group;
+ if (new_lineset->group) {
+ new_lineset->group->id.us++;
+ }
+ strcpy(new_lineset->name, lineset->name);
+}
+
+static FreestyleModuleConfig *alloc_module()
+{
+ return (FreestyleModuleConfig *)MEM_callocN(sizeof(FreestyleModuleConfig), "style module configuration");
+}
+
+void BKE_freestyle_module_add(FreestyleConfig *config)
+{
+ FreestyleModuleConfig *module_conf = alloc_module();
+ const size_t maxlen = sizeof(module_conf->module_path);
+ BLI_addtail(&config->modules, (void *)module_conf);
+
+ BLI_strncpy(module_conf->module_path, BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, "freestyle"), maxlen);
+ BLI_join_dirfile(module_conf->module_path, maxlen, module_conf->module_path, "style_modules");
+ BLI_join_dirfile(module_conf->module_path, maxlen, module_conf->module_path, "contour.py");
+ module_conf->is_displayed = 1;
+}
+
+static void copy_module(FreestyleModuleConfig *new_module, FreestyleModuleConfig *module)
+{
+ strcpy(new_module->module_path, module->module_path);
+ new_module->is_displayed = module->is_displayed;
+}
+
+void BKE_freestyle_module_delete(FreestyleConfig *config, FreestyleModuleConfig *module_conf)
+{
+ BLI_freelinkN(&config->modules, module_conf);
+}
+
+void BKE_freestyle_module_move_up(FreestyleConfig *config, FreestyleModuleConfig *module_conf)
+{
+ BLI_remlink(&config->modules, module_conf);
+ BLI_insertlinkbefore(&config->modules, module_conf->prev, module_conf);
+}
+
+void BKE_freestyle_module_move_down(FreestyleConfig *config, FreestyleModuleConfig *module_conf)
+{
+ BLI_remlink(&config->modules, module_conf);
+ BLI_insertlinkafter(&config->modules, module_conf->next, module_conf);
+}
+
+void BKE_freestyle_lineset_unique_name(FreestyleConfig *config, FreestyleLineSet *lineset)
+{
+ BLI_uniquename(&config->linesets, lineset, "FreestyleLineSet", '.', offsetof(FreestyleLineSet, name),
+ sizeof(lineset->name));
+}
+
+static FreestyleLineSet *alloc_lineset()
+{
+ return (FreestyleLineSet *)MEM_callocN(sizeof(FreestyleLineSet), "Freestyle line set");
+}
+
+FreestyleLineSet *BKE_freestyle_lineset_add(FreestyleConfig *config)
+{
+ int lineset_index = BLI_countlist(&config->linesets);
+
+ FreestyleLineSet *lineset = alloc_lineset();
+ BLI_addtail(&config->linesets, (void *)lineset);
+ BKE_freestyle_lineset_set_active_index(config, lineset_index);
+
+ lineset->linestyle = BKE_new_linestyle("LineStyle", NULL);
+ lineset->flags |= FREESTYLE_LINESET_ENABLED;
+ lineset->selection = FREESTYLE_SEL_VISIBILITY | FREESTYLE_SEL_EDGE_TYPES | FREESTYLE_SEL_IMAGE_BORDER;
+ lineset->qi = FREESTYLE_QI_VISIBLE;
+ lineset->qi_start = 0;
+ lineset->qi_end = 100;
+ lineset->edge_types = FREESTYLE_FE_SILHOUETTE | FREESTYLE_FE_BORDER | FREESTYLE_FE_CREASE;
+ lineset->exclude_edge_types = 0;
+ lineset->group = NULL;
+ if (lineset_index > 0)
+ sprintf(lineset->name, "LineSet %i", lineset_index + 1);
+ else
+ strcpy(lineset->name, "LineSet");
+ BKE_freestyle_lineset_unique_name(config, lineset);
+
+ return lineset;
+}
+
+FreestyleLineSet *BKE_freestyle_lineset_get_active(FreestyleConfig *config)
+{
+ FreestyleLineSet *lineset;
+
+ for (lineset = (FreestyleLineSet *)config->linesets.first; lineset; lineset = lineset->next) {
+ if (lineset->flags & FREESTYLE_LINESET_CURRENT)
+ return lineset;
+ }
+ return NULL;
+}
+
+short BKE_freestyle_lineset_get_active_index(FreestyleConfig *config)
+{
+ FreestyleLineSet *lineset;
+ short i;
+
+ for (lineset = (FreestyleLineSet *)config->linesets.first, i = 0; lineset; lineset = lineset->next, i++) {
+ if (lineset->flags & FREESTYLE_LINESET_CURRENT)
+ return i;
+ }
+ return 0;
+}
+
+void BKE_freestyle_lineset_set_active_index(FreestyleConfig *config, short index)
+{
+ FreestyleLineSet *lineset;
+ short i;
+
+ for (lineset = (FreestyleLineSet *)config->linesets.first, i = 0; lineset; lineset = lineset->next, i++) {
+ if (i == index)
+ lineset->flags |= FREESTYLE_LINESET_CURRENT;
+ else
+ lineset->flags &= ~FREESTYLE_LINESET_CURRENT;
+ }
+}
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index a7d0152a799..755030bd208 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -183,12 +183,12 @@ bGPDlayer *gpencil_layer_addnew(bGPdata *gpd, const char *name, int setactive)
gpl->thickness = 3;
/* auto-name */
- strcpy(gpl->info, name);
+ BLI_strncpy(gpl->info, name, sizeof(gpl->info));
BLI_uniquename(&gpd->layers, gpl, "GP_Layer", '.', offsetof(bGPDlayer, info), sizeof(gpl->info));
/* make this one the active one */
if (setactive)
- gpencil_layer_setactive(gpd, gpl);
+ gpencil_layer_setactive(gpd, gpl);
/* return layer */
return gpl;
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index 20d874e7243..98d1d301f65 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -79,6 +79,7 @@ void BKE_group_unlink(Group *group)
Object *ob;
Scene *sce;
SceneRenderLayer *srl;
+ FreestyleLineSet *lineset;
ParticleSystem *psys;
for (ma = bmain->mat.first; ma; ma = ma->id.next) {
@@ -103,6 +104,10 @@ void BKE_group_unlink(Group *group)
for (srl = sce->r.layers.first; srl; srl = srl->next) {
if (srl->light_override == group)
srl->light_override = NULL;
+ for(lineset = srl->freestyleConfig.linesets.first; lineset; lineset= lineset->next) {
+ if (lineset->group == group)
+ lineset->group = NULL;
+ }
}
}
@@ -127,11 +132,11 @@ void BKE_group_unlink(Group *group)
group->id.us = 0;
}
-Group *add_group(const char *name)
+Group *add_group(Main *bmain, const char *name)
{
Group *group;
- group = BKE_libblock_alloc(&G.main->group, ID_GR, name);
+ group = BKE_libblock_alloc(&bmain->group, ID_GR, name);
group->layer = (1 << 20) - 1;
return group;
}
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index d8c3e260399..9c265814b8f 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -51,6 +51,8 @@
#include "BLO_sys_types.h" // for intptr_t support
+#include "GPU_extensions.h"
+
/* GLOBALS */
static GHash *gIcons = NULL;
@@ -138,7 +140,10 @@ void BKE_previewimg_freefunc(void *link)
MEM_freeN(prv->rect[i]);
prv->rect[i] = NULL;
}
+ if (prv->gputexture[i])
+ GPU_texture_free(prv->gputexture[i]);
}
+
MEM_freeN(prv);
}
}
@@ -165,6 +170,7 @@ PreviewImage *BKE_previewimg_copy(PreviewImage *prv)
else {
prv_img->rect[i] = NULL;
}
+ prv_img->gputexture[i] = NULL;
}
}
return prv_img;
diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c
index c3008d17bd1..c64c261b9b0 100644
--- a/source/blender/blenkernel/intern/idcode.c
+++ b/source/blender/blenkernel/intern/idcode.c
@@ -30,12 +30,13 @@
* \ingroup bke
*/
-
#include <stdlib.h>
#include <string.h>
#include "DNA_ID.h"
+#include "BLI_utildefines.h"
+
#include "BKE_idcode.h"
typedef struct {
@@ -62,6 +63,7 @@ static IDType idtypes[] = {
{ 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 },
@@ -88,9 +90,11 @@ static IDType *idtype_from_name(const char *str)
{
int i = nidtypes;
- while (i--)
- if (strcmp(str, idtypes[i].name) == 0)
+ while (i--) {
+ if (STREQ(str, idtypes[i].name)) {
return &idtypes[i];
+ }
+ }
return NULL;
}
@@ -105,17 +109,36 @@ static IDType *idtype_from_code(int code)
return NULL;
}
-int BKE_idcode_is_valid(int code)
+/**
+ * Return if the ID code is a valid ID code.
+ *
+ * \param code The code to check.
+ * \return Boolean, 0 when invalid.
+ */
+bool BKE_idcode_is_valid(int code)
{
- return idtype_from_code(code) ? 1 : 0;
+ return idtype_from_code(code) ? true : false;
}
-int BKE_idcode_is_linkable(int code)
+/**
+ * Return non-zero when an ID type is linkable.
+ *
+ * \param code The code to check.
+ * \return Boolean, 0 when non linkable.
+ */
+bool BKE_idcode_is_linkable(int code)
{
IDType *idt = idtype_from_code(code);
- return idt ? (idt->flags & IDTYPE_FLAGS_ISLINKABLE) : 0;
+ return idt ? ((idt->flags & IDTYPE_FLAGS_ISLINKABLE) != 0) : false;
}
+/**
+ * Convert an idcode into a name.
+ *
+ * \param code The code to convert.
+ * \return A static string representing the name of
+ * the code.
+ */
const char *BKE_idcode_to_name(int code)
{
IDType *idt = idtype_from_code(code);
@@ -123,6 +146,12 @@ const char *BKE_idcode_to_name(int code)
return idt ? idt->name : NULL;
}
+/**
+ * Convert a name into an idcode (ie. ID_SCE)
+ *
+ * \param name The name to convert.
+ * \return The code for the name, or 0 if invalid.
+ */
int BKE_idcode_from_name(const char *name)
{
IDType *idt = idtype_from_name(name);
@@ -130,6 +159,13 @@ int BKE_idcode_from_name(const char *name)
return idt ? idt->code : 0;
}
+/**
+ * Convert an idcode into a name (plural).
+ *
+ * \param code The code to convert.
+ * \return A static string representing the name of
+ * the code.
+ */
const char *BKE_idcode_to_name_plural(int code)
{
IDType *idt = idtype_from_code(code);
@@ -137,6 +173,12 @@ const char *BKE_idcode_to_name_plural(int code)
return idt ? idt->plural : NULL;
}
+/**
+ * Return an ID code and steps the index forward 1.
+ *
+ * \param index start as 0.
+ * \return the code, 0 when all codes have been returned.
+ */
int BKE_idcode_iter_step(int *index)
{
return (*index < nidtypes) ? idtypes[(*index)++].code : 0;
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 5dd0f08dc71..ca1ae23c364 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -27,7 +27,6 @@
* \ingroup bke
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
@@ -62,8 +61,10 @@ static char idp_size_table[] = {
/* --------- property array type -------------*/
-/* note: as a start to move away from the stupid IDP_New function, this type
- * has it's own allocation function.*/
+/**
+ * \note as a start to move away from the stupid IDP_New function, this type
+ * has it's own allocation function.
+ */
IDProperty *IDP_NewIDPArray(const char *name)
{
IDProperty *prop = MEM_callocN(sizeof(IDProperty), "IDProperty prop array");
@@ -444,18 +445,18 @@ void IDP_SyncGroupValues(IDProperty *dest, IDProperty *src)
}
}
-/*
- * replaces all properties with the same name in a destination group from a source group.
+/**
+ * Replaces all properties with the same name in a destination group from a source group.
*/
void IDP_ReplaceGroupInGroup(IDProperty *dest, IDProperty *src)
{
IDProperty *loop, *prop;
for (prop = src->data.group.first; prop; prop = prop->next) {
for (loop = dest->data.group.first; loop; loop = loop->next) {
- if (strcmp(loop->name, prop->name) == 0) {
+ if (STREQ(loop->name, prop->name)) {
IDProperty *copy = IDP_CopyProperty(prop);
- BLI_insertlink(&dest->data.group, loop, copy);
+ BLI_insertlinkafter(&dest->data.group, loop, copy);
BLI_remlink(&dest->data.group, loop);
IDP_FreeProperty(loop);
@@ -472,15 +473,16 @@ void IDP_ReplaceGroupInGroup(IDProperty *dest, IDProperty *src)
}
}
}
-/*
- * replaces a property with the same name in a group, or adds
- * it if the properly doesn't exist.
+
+/**
+ * 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)
{
IDProperty *loop;
if ((loop = IDP_GetPropertyFromGroup(group, prop->name))) {
- BLI_insertlink(&group->data.group, loop, prop);
+ BLI_insertlinkafter(&group->data.group, loop, prop);
BLI_remlink(&group->data.group, loop);
IDP_FreeProperty(loop);
@@ -516,8 +518,21 @@ void IDP_MergeGroup(IDProperty *dest, IDProperty *src, const int do_overwrite)
}
}
-/* returns 0 if an id property with the same name exists and it failed,
- * or 1 if it succeeded in adding to the group.*/
+/**
+ * This function has a sanity check to make sure ID properties with the same name don't
+ * get added to the group.
+ *
+ * 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.
+ *
+ * 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
+ * to free an ID property, you first call IDP_FreeProperty then MEM_freeN the
+ * struct. In the future this will just be IDP_FreeProperty and the code will
+ * be reorganized to work properly.
+ */
int IDP_AddToGroup(IDProperty *group, IDProperty *prop)
{
if (IDP_GetPropertyFromGroup(group, prop->name) == NULL) {
@@ -529,17 +544,28 @@ int IDP_AddToGroup(IDProperty *group, IDProperty *prop)
return 0;
}
+/**
+ * This is the same as IDP_AddToGroup, only you pass an item
+ * in the group list to be inserted after.
+ */
int IDP_InsertToGroup(IDProperty *group, IDProperty *previous, IDProperty *pnew)
{
if (IDP_GetPropertyFromGroup(group, pnew->name) == NULL) {
group->len++;
- BLI_insertlink(&group->data.group, previous, pnew);
+ BLI_insertlinkafter(&group->data.group, previous, pnew);
return 1;
}
return 0;
}
+/**
+ * \note this does not free the property!!
+ *
+ * To free the property, you have to do:
+ * IDP_FreeProperty(prop); //free all subdata
+ * MEM_freeN(prop); //free property struct itself
+ */
void IDP_RemFromGroup(IDProperty *group, IDProperty *prop)
{
group->len--;
@@ -550,7 +576,7 @@ IDProperty *IDP_GetPropertyFromGroup(IDProperty *prop, const char *name)
{
return (IDProperty *)BLI_findstring(&prop->data.group, name, offsetof(IDProperty, name));
}
-
+/** same as above but ensure type match */
IDProperty *IDP_GetPropertyTypeFromGroup(IDProperty *prop, const char *name, const char type)
{
IDProperty *idprop = IDP_GetPropertyFromGroup(prop, name);
@@ -562,6 +588,12 @@ typedef struct IDPIter {
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 = MEM_callocN(sizeof(IDPIter), "IDPIter");
@@ -570,6 +602,12 @@ void *IDP_GetGroupIterator(IDProperty *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;
@@ -583,6 +621,10 @@ IDProperty *IDP_GroupIterNext(void *vself)
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);
@@ -614,6 +656,11 @@ IDProperty *IDP_CopyProperty(IDProperty *prop)
}
}
+/**
+ * Get the Group property that contains the id properties for ID id. Set create_if_needed
+ * to create the Group property and attach it to id if it doesn't exist; otherwise
+ * the function will return NULL if there's no Group property attached to the ID.
+ */
IDProperty *IDP_GetProperties(ID *id, int create_if_needed)
{
if (id->properties) {
@@ -663,7 +710,7 @@ int IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const int is_s
{
IDProperty *link1, *link2;
- if (is_strict && BLI_countlist(&prop1->data.group) != BLI_countlist(&prop2->data.group))
+ if (is_strict && prop1->len != prop2->len)
return 0;
for (link1 = prop1->data.group.first; link1; link1 = link1->next) {
@@ -703,7 +750,31 @@ int IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2)
return IDP_EqualsProperties_ex(prop1, prop2, TRUE);
}
-/* 'val' is never NULL, don't check */
+/**
+ * Allocate a new ID.
+ *
+ * This function takes three arguments: the ID property type, a union which defines
+ * it's initial value, and a name.
+ *
+ * The union is simple to use; see the top of this header file for its definition.
+ * An example of using this function:
+ *
+ * IDPropertyTemplate val;
+ * IDProperty *group, *idgroup, *color;
+ * group = IDP_New(IDP_GROUP, val, "group1"); //groups don't need a template.
+ *
+ * val.array.len = 4
+ * val.array.type = IDP_FLOAT;
+ * color = IDP_New(IDP_ARRAY, val, "color1");
+ *
+ * idgroup = IDP_GetProperties(some_id, 1);
+ * IDP_AddToGroup(idgroup, color);
+ * IDP_AddToGroup(idgroup, group);
+ *
+ * Note that you MUST either attach the id property to an id property group with
+ * 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 *prop = NULL;
@@ -794,9 +865,11 @@ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *n
return prop;
}
-/* NOTE: this will free all child properties including list arrays and groups!
+/**
+ * \note this will free all child properties of list arrays and groups!
* Also, note that this does NOT unlink anything! Plus it doesn't free
- * the actual IDProperty struct either.*/
+ * the actual struct IDProperty struct either.
+ */
void IDP_FreeProperty(IDProperty *prop)
{
switch (prop->type) {
@@ -815,8 +888,18 @@ void IDP_FreeProperty(IDProperty *prop)
}
}
-/* Unlinks any IDProperty<->ID linkage that might be going on.
- * note: currently unused.*/
+void IDP_ClearProperty(IDProperty *prop)
+{
+ IDP_FreeProperty(prop);
+ prop->data.pointer = NULL;
+ prop->len = prop->totallen = 0;
+}
+
+/**
+ * Unlinks any struct IDProperty<->ID linkage that might be going on.
+ *
+ * \note currently unused
+ */
void IDP_UnlinkProperty(IDProperty *prop)
{
switch (prop->type) {
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index c4ce17c394a..26651d76f68 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -68,7 +68,6 @@
#include "BLI_blenlib.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
-#include "BLI_bpath.h"
#include "BKE_bmfont.h"
#include "BKE_colortools.h"
@@ -243,11 +242,11 @@ void BKE_image_free(Image *ima)
}
/* only image block itself */
-static Image *image_alloc(const char *name, short source, short type)
+static Image *image_alloc(Main *bmain, const char *name, short source, short type)
{
Image *ima;
- ima = BKE_libblock_alloc(&G.main->image, ID_IM, name);
+ ima = BKE_libblock_alloc(&bmain->image, ID_IM, name);
if (ima) {
ima->ok = IMA_OK;
@@ -313,10 +312,6 @@ static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int frame)
break;
ibuf->index = index;
- if (ima->flag & IMA_CM_PREDIVIDE)
- ibuf->flags |= IB_cm_predivide;
- else
- ibuf->flags &= ~IB_cm_predivide;
/* this function accepts (link == NULL) */
BLI_insertlinkbefore(&ima->ibufs, link, ibuf);
@@ -328,9 +323,9 @@ static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int frame)
}
/* empty image block, of similar type and filename */
-Image *BKE_image_copy(Image *ima)
+Image *BKE_image_copy(Main *bmain, Image *ima)
{
- Image *nima = image_alloc(ima->id.name + 2, ima->source, ima->type);
+ Image *nima = image_alloc(bmain, ima->id.name + 2, ima->source, ima->type);
BLI_strncpy(nima->name, ima->name, sizeof(ima->name));
@@ -348,6 +343,9 @@ Image *BKE_image_copy(Image *ima)
BKE_color_managed_colorspace_settings_copy(&nima->colorspace_settings, &ima->colorspace_settings);
+ if (ima->packedfile)
+ nima->packedfile = dupPackedFile(ima->packedfile);
+
return nima;
}
@@ -438,7 +436,7 @@ void BKE_image_make_local(struct Image *ima)
extern_local_image(ima);
}
else if (is_local && is_lib) {
- Image *ima_new = BKE_image_copy(ima);
+ Image *ima_new = BKE_image_copy(bmain, ima);
ima_new->id.us = 0;
@@ -553,7 +551,41 @@ int BKE_image_scale(Image *image, int width, int height)
return (ibuf != NULL);
}
-Image *BKE_image_load(const char *filepath)
+static void image_init_color_management(Image *ima)
+{
+ ImBuf *ibuf;
+ char name[FILE_MAX];
+
+ BKE_image_user_file_path(NULL, ima, name);
+
+ /* will set input color space to image format default's */
+ ibuf = IMB_loadiffname(name, IB_test | IB_alphamode_detect, ima->colorspace_settings.name);
+
+ if (ibuf) {
+ if (ibuf->flags & IB_alphamode_premul)
+ ima->alpha_mode = IMA_ALPHA_PREMUL;
+ else
+ ima->alpha_mode = IMA_ALPHA_STRAIGHT;
+
+ IMB_freeImBuf(ibuf);
+ }
+}
+
+void BKE_image_alpha_mode_from_extension(Image *image)
+{
+ if (BLI_testextensie(image->name, ".exr") ||
+ BLI_testextensie(image->name, ".cin") ||
+ BLI_testextensie(image->name, ".dpx") ||
+ BLI_testextensie(image->name, ".hdr"))
+ {
+ image->alpha_mode = IMA_ALPHA_PREMUL;
+ }
+ else {
+ image->alpha_mode = IMA_ALPHA_STRAIGHT;
+ }
+}
+
+Image *BKE_image_load(Main *bmain, const char *filepath)
{
Image *ima;
int file, len;
@@ -561,7 +593,7 @@ Image *BKE_image_load(const char *filepath)
char str[FILE_MAX];
BLI_strncpy(str, filepath, sizeof(str));
- BLI_path_abs(str, G.main->name);
+ BLI_path_abs(str, bmain->name);
/* exists? */
file = BLI_open(str, O_BINARY | O_RDONLY, 0);
@@ -574,12 +606,14 @@ Image *BKE_image_load(const char *filepath)
while (len > 0 && filepath[len - 1] != '/' && filepath[len - 1] != '\\') len--;
libname = filepath + len;
- ima = image_alloc(libname, IMA_SRC_FILE, IMA_TYPE_IMAGE);
+ ima = image_alloc(bmain, libname, IMA_SRC_FILE, IMA_TYPE_IMAGE);
BLI_strncpy(ima->name, filepath, sizeof(ima->name));
if (BLI_testextensie_array(filepath, imb_ext_movie))
ima->source = IMA_SRC_MOVIE;
+ image_init_color_management(ima);
+
return ima;
}
@@ -614,7 +648,7 @@ Image *BKE_image_load_exists(const char *filepath)
}
}
- return BKE_image_load(filepath);
+ return BKE_image_load(G.main, filepath);
}
static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type,
@@ -667,17 +701,17 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char
/* both byte and float buffers are filling in sRGB space, need to linearize float buffer after BKE_image_buf_fill* functions */
IMB_buffer_float_from_float(rect_float, rect_float, ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB,
- ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+ TRUE, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
}
return ibuf;
}
/* adds new image block, creates ImBuf and initializes color */
-Image *BKE_image_add_generated(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, 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, float color[4])
{
/* on save, type is changed to FILE in editsima.c */
- Image *ima = image_alloc(name, IMA_SRC_GENERATED, IMA_TYPE_UV_TEST);
+ Image *ima = image_alloc(bmain, name, IMA_SRC_GENERATED, IMA_TYPE_UV_TEST);
if (ima) {
ImBuf *ibuf;
@@ -703,7 +737,7 @@ Image *BKE_image_add_from_imbuf(ImBuf *ibuf)
/* on save, type is changed to FILE in editsima.c */
Image *ima;
- ima = image_alloc(BLI_path_basename(ibuf->name), IMA_SRC_FILE, IMA_TYPE_IMAGE);
+ ima = image_alloc(G.main, BLI_path_basename(ibuf->name), IMA_SRC_FILE, IMA_TYPE_IMAGE);
if (ima) {
BLI_strncpy(ima->name, ibuf->name, FILE_MAX);
@@ -887,7 +921,7 @@ void BKE_image_free_all_textures(void)
image_free_buffers(ima);
}
}
- /* printf("freed total %d MB\n", totsize/(1024*1024)); */
+ /* printf("freed total %d MB\n", totsize / (1024 * 1024)); */
}
/* except_frame is weak, only works for seqs without offset... */
@@ -938,7 +972,7 @@ int BKE_imtype_to_ftype(const char imtype)
return RADHDR;
#endif
else if (imtype == R_IMF_IMTYPE_PNG)
- return PNG;
+ return PNG | 90;
#ifdef WITH_DDS
else if (imtype == R_IMF_IMTYPE_DDS)
return DDS;
@@ -1008,7 +1042,7 @@ char BKE_ftype_to_imtype(const int ftype)
}
-int BKE_imtype_is_movie(const char imtype)
+bool BKE_imtype_is_movie(const char imtype)
{
switch (imtype) {
case R_IMF_IMTYPE_AVIRAW:
@@ -1019,9 +1053,9 @@ int BKE_imtype_is_movie(const char imtype)
case R_IMF_IMTYPE_THEORA:
case R_IMF_IMTYPE_XVID:
case R_IMF_IMTYPE_FRAMESERVER:
- return 1;
+ return true;
}
- return 0;
+ return false;
}
int BKE_imtype_supports_zbuf(const char imtype)
@@ -1120,6 +1154,8 @@ char BKE_imtype_valid_depths(const char imtype)
return R_IMF_CHAN_DEPTH_10;
case R_IMF_IMTYPE_JP2:
return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16;
+ case R_IMF_IMTYPE_PNG:
+ return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_16;
/* most formats are 8bit only */
default:
return R_IMF_CHAN_DEPTH_8;
@@ -1166,9 +1202,10 @@ char BKE_imtype_from_arg(const char *imtype_arg)
else return R_IMF_IMTYPE_INVALID;
}
-int BKE_add_image_extension(char *string, const char imtype)
+static int do_add_image_extension(char *string, const char imtype, const ImageFormatData *im_format)
{
const char *extension = NULL;
+ (void)im_format; /* may be unused, depends on build options */
if (imtype == R_IMF_IMTYPE_IRIS) {
if (!BLI_testextensie(string, ".rgb"))
@@ -1233,8 +1270,22 @@ int BKE_add_image_extension(char *string, const char imtype)
}
#ifdef WITH_OPENJPEG
else if (imtype == R_IMF_IMTYPE_JP2) {
- if (!BLI_testextensie(string, ".jp2"))
- extension = ".jp2";
+ if (im_format) {
+ if (im_format->jp2_codec == R_IMF_JP2_CODEC_JP2) {
+ if (!BLI_testextensie(string, ".jp2"))
+ extension = ".jp2";
+ }
+ else if (im_format->jp2_codec == R_IMF_JP2_CODEC_J2K) {
+ if (!BLI_testextensie(string, ".j2c"))
+ extension = ".j2c";
+ }
+ else
+ BLI_assert(!"Unsupported jp2 codec was specified in im_format->jp2_codec");
+ }
+ else {
+ if (!BLI_testextensie(string, ".jp2"))
+ extension = ".jp2";
+ }
}
#endif
else { // R_IMF_IMTYPE_AVIRAW, R_IMF_IMTYPE_AVIJPEG, R_IMF_IMTYPE_JPEG90, R_IMF_IMTYPE_QUICKTIME etc
@@ -1260,11 +1311,22 @@ int BKE_add_image_extension(char *string, const char imtype)
}
}
+int BKE_add_image_extension(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)
+{
+ return do_add_image_extension(string, imtype, NULL);
+}
+
void BKE_imformat_defaults(ImageFormatData *im_format)
{
memset(im_format, 0, sizeof(*im_format));
im_format->planes = R_IMF_PLANES_RGB;
im_format->imtype = R_IMF_IMTYPE_PNG;
+ im_format->depth = R_IMF_CHAN_DEPTH_8;
im_format->quality = 90;
im_format->compress = 90;
@@ -1289,9 +1351,13 @@ void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *i
im_format->imtype = R_IMF_IMTYPE_RADHDR;
#endif
- else if (ftype == PNG)
+ else if (ftype == PNG) {
im_format->imtype = R_IMF_IMTYPE_PNG;
+ if (custom_flags & PNG_16BIT)
+ im_format->depth = R_IMF_CHAN_DEPTH_16;
+ }
+
#ifdef WITH_DDS
else if (ftype == DDS)
im_format->imtype = R_IMF_IMTYPE_DDS;
@@ -1352,6 +1418,13 @@ void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *i
if (ftype & JP2_CINE_48FPS)
im_format->jp2_flag |= R_IMF_JP2_FLAG_CINE_48;
}
+
+ if (ftype & JP2_JP2)
+ im_format->jp2_codec = R_IMF_JP2_CODEC_JP2;
+ else if (ftype & JP2_J2K)
+ im_format->jp2_codec = R_IMF_JP2_CODEC_J2K;
+ else
+ BLI_assert(!"Unsupported jp2 codec was specified in file type");
}
#endif
@@ -1494,7 +1567,9 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d
if (camera && camera->type == OB_CAMERA) {
BLI_snprintf(text, sizeof(text), "%.2f", ((Camera *)camera->data)->lens);
}
- else BLI_strncpy(text, "<none>", sizeof(text));
+ else {
+ BLI_strncpy(text, "<none>", sizeof(text));
+ }
BLI_snprintf(stamp_data->cameralens, sizeof(stamp_data->cameralens), do_prefix ? "Lens %s" : "%s", text);
}
@@ -1744,7 +1819,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
}
/* cleanup the buffer. */
- BLF_buffer(mono, NULL, NULL, 0, 0, 0, FALSE);
+ BLF_buffer(mono, NULL, NULL, 0, 0, 0, NULL);
#undef BUFF_MARGIN_X
#undef BUFF_MARGIN_Y
@@ -1816,8 +1891,12 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf)
else if (ELEM5(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) {
ibuf->ftype = PNG;
- if (imtype == R_IMF_IMTYPE_PNG)
+ if (imtype == R_IMF_IMTYPE_PNG) {
+ if (imf->depth == R_IMF_CHAN_DEPTH_16)
+ ibuf->ftype |= PNG_16BIT;
+
ibuf->ftype |= compress;
+ }
}
#ifdef WITH_DDS
@@ -1867,7 +1946,7 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf)
else if (imtype == R_IMF_IMTYPE_DPX) {
ibuf->ftype = DPX;
if (imf->cineon_flag & R_IMF_CINEON_FLAG_LOG) {
- ibuf->ftype |= CINEON_LOG;
+ ibuf->ftype |= CINEON_LOG;
}
if (imf->depth == R_IMF_CHAN_DEPTH_16) {
ibuf->ftype |= CINEON_16BIT;
@@ -1907,6 +1986,13 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf)
if (imf->jp2_flag & R_IMF_JP2_FLAG_CINE_48)
ibuf->ftype |= JP2_CINE_48FPS;
}
+
+ if (imf->jp2_codec == R_IMF_JP2_CODEC_JP2)
+ ibuf->ftype |= JP2_JP2;
+ else if (imf->jp2_codec == R_IMF_JP2_CODEC_J2K)
+ ibuf->ftype |= JP2_J2K;
+ else
+ BLI_assert(!"Unsupported jp2 codec was specified in im_format->jp2_codec");
}
#endif
else {
@@ -1957,7 +2043,8 @@ int BKE_imbuf_write_stamp(Scene *scene, struct Object *camera, ImBuf *ibuf, cons
}
-void BKE_makepicstring(char *string, const char *base, const char *relbase, int frame, const char imtype, 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)
{
if (string == NULL) return;
BLI_strncpy(string, base, FILE_MAX - 10); /* weak assumption */
@@ -1967,8 +2054,17 @@ void BKE_makepicstring(char *string, const char *base, const char *relbase, int
BLI_path_frame(string, frame, 4);
if (use_ext)
- BKE_add_image_extension(string, imtype);
+ 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 short use_ext, const short use_frames)
+{
+ do_makepicstring(string, base, relbase, frame, im_format->imtype, im_format, use_ext, use_frames);
+}
+
+void BKE_makepicstring_from_type(char *string, const char *base, const char *relbase, int frame, const char imtype, const short use_ext, const short use_frames)
+{
+ do_makepicstring(string, base, relbase, frame, imtype, NULL, use_ext, use_frames);
}
/* used by sequencer too */
@@ -2027,7 +2123,7 @@ Image *BKE_image_verify_viewer(int type, const char *name)
break;
if (ima == NULL)
- ima = image_alloc(name, IMA_SRC_VIEWER, type);
+ ima = image_alloc(G.main, name, IMA_SRC_VIEWER, type);
/* happens on reload, imagewindow cannot be image user when hidden*/
if (ima->id.us == 0)
@@ -2075,7 +2171,7 @@ void BKE_image_walk_all_users(const Main *mainp, void *customdata,
}
else if (sa->spacetype == SPACE_NODE) {
SpaceNode *snode = sa->spacedata.first;
- if ((snode->treetype == NTREE_COMPOSIT) && (snode->nodetree)) {
+ if (snode->nodetree && snode->nodetree->type == NTREE_COMPOSIT) {
bNode *node;
for (node = snode->nodetree->nodes.first; node; node = node->next) {
if (node->id && node->type == CMP_NODE_IMAGE) {
@@ -2128,9 +2224,20 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal)
}
}
+#if 0
/* force reload on first use, but not for multilayer, that makes nodes and buttons in ui drawing fail */
if (ima->type != IMA_TYPE_MULTILAYER)
image_free_buffers(ima);
+#else
+ /* image buffers for non-sequence multilayer will share buffers with RenderResult,
+ * however sequence multilayer will own buffers. Such logic makes switching from
+ * single multilayer file to sequence completely instable
+ * since changes in nodes seems this workaround isn't needed anymore, all sockets
+ * are nicely detecting anyway, but freeing buffers always here makes multilayer
+ * sequences behave stable
+ */
+ image_free_buffers(ima);
+#endif
ima->ok = 1;
if (iuser)
@@ -2285,7 +2392,7 @@ void BKE_image_backup_render(Scene *scene, Image *ima)
static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr)
{
const char *colorspace = ima->colorspace_settings.name;
- int predivide = ima->flag & IMA_CM_PREDIVIDE;
+ int predivide = ima->alpha_mode == IMA_ALPHA_PREMUL;
ima->rr = RE_MultilayerConvert(ibuf->userdata, colorspace, predivide, ibuf->x, ibuf->y);
@@ -2317,6 +2424,18 @@ static void image_initialize_after_load(Image *ima, ImBuf *ibuf)
}
+static int imbuf_alpha_flags_for_image(Image *ima)
+{
+ int flag = 0;
+
+ if (ima->flag & IMA_IGNORE_ALPHA)
+ flag |= IB_ignore_alpha;
+ else if (ima->alpha_mode == IMA_ALPHA_PREMUL)
+ flag |= IB_alphamode_premul;
+
+ return flag;
+}
+
static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
{
struct ImBuf *ibuf;
@@ -2331,8 +2450,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
BKE_image_user_file_path(iuser, ima, name);
flag = IB_rect | IB_multilayer;
- if (ima->flag & IMA_DO_PREMUL)
- flag |= IB_premul;
+ flag |= imbuf_alpha_flags_for_image(ima);
/* read ibuf */
ibuf = IMB_loadiffname(name, flag, ima->colorspace_settings.name);
@@ -2491,15 +2609,14 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
/* is there a PackedFile with this image ? */
if (ima->packedfile) {
flag = IB_rect | IB_multilayer;
- if (ima->flag & IMA_DO_PREMUL) flag |= IB_premul;
+ 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>");
}
else {
flag = IB_rect | IB_multilayer | IB_metadata;
- if (ima->flag & IMA_DO_PREMUL)
- flag |= IB_premul;
+ flag |= imbuf_alpha_flags_for_image(ima);
/* get the right string */
BKE_image_user_frame_calc(iuser, cfra, 0);
@@ -2636,6 +2753,14 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
if (rres.have_combined && layer == 0) {
/* pass */
}
+ else if (rect && layer == 0) {
+ /* rect32 is set when there's a Sequence pass, this pass seems
+ * to have layer=0 (this is from image_buttons.c)
+ * in this case we ignore float buffer, because it could have
+ * hung from previous pass which was float
+ */
+ rectf = NULL;
+ }
else if (rres.layers.first) {
RenderLayer *rl = BLI_findlink(&rres.layers, layer - (rres.have_combined ? 1 : 0));
if (rl) {
@@ -2719,20 +2844,33 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
ibuf->dither = dither;
- if (iuser->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE) {
- ibuf->flags |= IB_cm_predivide;
- ima->flag |= IMA_CM_PREDIVIDE;
- }
- else {
- ibuf->flags &= ~IB_cm_predivide;
- ima->flag &= ~IMA_CM_PREDIVIDE;
- }
-
ima->ok = IMA_OK_LOADED;
return ibuf;
}
+static void image_get_fame_and_index(Image *ima, ImageUser *iuser, int *frame_r, int *index_r)
+{
+ int frame = 0, index = 0;
+
+ /* 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;
+ }
+ else if (ima->source == IMA_SRC_SEQUENCE) {
+ if (ima->type == IMA_TYPE_IMAGE) {
+ frame = iuser ? iuser->framenr : ima->lastframe;
+ }
+ else if (ima->type == IMA_TYPE_MULTILAYER) {
+ frame = iuser ? iuser->framenr : ima->lastframe;
+ index = iuser ? iuser->multi_index : IMA_NO_INDEX;
+ }
+ }
+
+ *frame_r = frame;
+ *index_r = index;
+}
+
static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame_r, int *index_r)
{
ImBuf *ibuf = NULL;
@@ -2788,6 +2926,21 @@ static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame
return ibuf;
}
+BLI_INLINE int image_quick_test(Image *ima, ImageUser *iuser)
+{
+ if (ima == NULL)
+ return FALSE;
+
+ if (iuser) {
+ if (iuser->ok == 0)
+ return FALSE;
+ }
+ else if (ima->ok == 0)
+ return FALSE;
+
+ return TRUE;
+}
+
/* Checks optional ImageUser and verifies/creates ImBuf.
*
* not thread-safe, so callee should worry about thread locks
@@ -2802,14 +2955,7 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r)
*lock_r = NULL;
/* quick reject tests */
- if (ima == NULL)
- return NULL;
-
- if (iuser) {
- if (iuser->ok == 0)
- return NULL;
- }
- else if (ima->ok == 0)
+ if (!image_quick_test(ima, iuser))
return NULL;
ibuf = image_get_ibuf_threadsafe(ima, iuser, &frame, &index);
@@ -2933,14 +3079,7 @@ int BKE_image_has_ibuf(Image *ima, ImageUser *iuser)
ImBuf *ibuf;
/* quick reject tests */
- if (ima == NULL)
- return FALSE;
-
- if (iuser) {
- if (iuser->ok == 0)
- return FALSE;
- }
- else if (ima->ok == 0)
+ if (!image_quick_test(ima, iuser))
return FALSE;
ibuf = image_get_ibuf_threadsafe(ima, iuser, NULL, NULL);
@@ -2959,6 +3098,122 @@ int BKE_image_has_ibuf(Image *ima, ImageUser *iuser)
return ibuf != NULL;
}
+/* ******** Pool for image buffers ******** */
+
+typedef struct ImagePoolEntry {
+ struct ImagePoolEntry *next, *prev;
+ Image *image;
+ ImBuf *ibuf;
+ int index;
+ int frame;
+} ImagePoolEntry;
+
+typedef struct ImagePool {
+ ListBase image_buffers;
+} ImagePool;
+
+ImagePool *BKE_image_pool_new(void)
+{
+ ImagePool *pool = MEM_callocN(sizeof(ImagePool), "Image Pool");
+
+ return pool;
+}
+
+void BKE_image_pool_free(ImagePool *pool)
+{
+ ImagePoolEntry *entry, *next_entry;
+
+ /* use single lock to dereference all the image buffers */
+ BLI_spin_lock(&image_spin);
+
+ for (entry = pool->image_buffers.first; entry; entry = next_entry) {
+ next_entry = entry->next;
+
+ if (entry->ibuf)
+ IMB_freeImBuf(entry->ibuf);
+
+ MEM_freeN(entry);
+ }
+
+ BLI_spin_unlock(&image_spin);
+
+ MEM_freeN(pool);
+}
+
+BLI_INLINE ImBuf *image_pool_find_entry(ImagePool *pool, Image *image, int frame, int index, int *found)
+{
+ ImagePoolEntry *entry;
+
+ *found = FALSE;
+
+ for (entry = pool->image_buffers.first; entry; entry = entry->next) {
+ if (entry->image == image && entry->frame == frame && entry->index == index) {
+ *found = TRUE;
+ return entry->ibuf;
+ }
+ }
+
+ return NULL;
+}
+
+ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool)
+{
+ ImBuf *ibuf;
+ int index, frame, found;
+
+ if (!image_quick_test(ima, iuser))
+ return NULL;
+
+ if (pool == NULL) {
+ /* pool could be NULL, in this case use general acquire function */
+ return BKE_image_acquire_ibuf(ima, iuser, NULL);
+ }
+
+ image_get_fame_and_index(ima, iuser, &frame, &index);
+
+ ibuf = image_pool_find_entry(pool, ima, frame, index, &found);
+ if (found)
+ return ibuf;
+
+ BLI_spin_lock(&image_spin);
+
+ ibuf = image_pool_find_entry(pool, ima, frame, index, &found);
+
+ /* will also create entry even in cases image buffer failed to load,
+ * prevents trying to load the same buggy file multiple times
+ */
+ if (!found) {
+ ImagePoolEntry *entry;
+
+ ibuf = image_acquire_ibuf(ima, iuser, NULL);
+
+ if (ibuf)
+ IMB_refImBuf(ibuf);
+
+ entry = MEM_callocN(sizeof(ImagePoolEntry), "Image Pool Entry");
+ entry->image = ima;
+ entry->frame = frame;
+ entry->index = index;
+ entry->ibuf = ibuf;
+
+ BLI_addtail(&pool->image_buffers, entry);
+ }
+
+ BLI_spin_unlock(&image_spin);
+
+ return ibuf;
+}
+
+void BKE_image_pool_release_ibuf(Image *ima, ImBuf *ibuf, ImagePool *pool)
+{
+ /* if pool wasn't actually used, use general release stuff,
+ * for pools image buffers will be dereferenced on pool free
+ */
+ if (pool == NULL) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+}
+
int BKE_image_user_frame_get(const ImageUser *iuser, int cfra, int fieldnr, short *r_is_in_range)
{
const int len = (iuser->fie_ima * iuser->frames) / 2;
@@ -3121,3 +3376,57 @@ void BKE_image_get_aspect(Image *image, float *aspx, float *aspy)
else
*aspy = 1.0f;
}
+
+unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame)
+{
+ ImageUser iuser = {NULL};
+ void *lock;
+ ImBuf *ibuf;
+ unsigned char *pixels = NULL;
+
+ iuser.framenr = frame;
+ iuser.ok = TRUE;
+
+ ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
+
+ if (ibuf) {
+ pixels = (unsigned char *) ibuf->rect;
+
+ if (pixels)
+ pixels = MEM_dupallocN(pixels);
+
+ BKE_image_release_ibuf(image, ibuf, lock);
+ }
+
+ if (!pixels)
+ return NULL;
+
+ return pixels;
+}
+
+float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame)
+{
+ ImageUser iuser = {NULL};
+ void *lock;
+ ImBuf *ibuf;
+ float *pixels = NULL;
+
+ iuser.framenr = frame;
+ iuser.ok = TRUE;
+
+ ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
+
+ if (ibuf) {
+ pixels = ibuf->rect_float;
+
+ if (pixels)
+ pixels = MEM_dupallocN(pixels);
+
+ BKE_image_release_ibuf(image, ibuf, lock);
+ }
+
+ if (!pixels)
+ return NULL;
+
+ return pixels;
+}
diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c
index 468a88775c6..415f0a87431 100644
--- a/source/blender/blenkernel/intern/image_gen.c
+++ b/source/blender/blenkernel/intern/image_gen.c
@@ -24,13 +24,14 @@
* \ingroup bke
*/
-
#include <math.h>
#include <stdlib.h>
-#include "BKE_image.h"
#include "BLI_math_color.h"
#include "BLI_math_base.h"
+
+#include "BKE_image.h"
+
#include "BLF_api.h"
void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, int height, const float color[4])
diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c
index 90cd7bc2df5..b9064fe8ba3 100644
--- a/source/blender/blenkernel/intern/implicit.c
+++ b/source/blender/blenkernel/intern/implicit.c
@@ -1716,7 +1716,7 @@ static void simulate_implicit_euler(lfVector *Vnew, lfVector *UNUSED(lX), lfVect
* (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)
+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");
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 59dd02849dd..c5364744b2d 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -1548,7 +1548,7 @@ static void ipo_to_animdata(ID *id, Ipo *ipo, char actname[], char constname[],
BLI_snprintf(nameBuf, sizeof(nameBuf), "CDA:%s", ipo->id.name + 2);
- adt->action = add_empty_action(nameBuf);
+ adt->action = add_empty_action(G.main, nameBuf);
if (G.debug & G_DEBUG) printf("\t\tadded new action - '%s'\n", nameBuf);
}
@@ -2093,7 +2093,7 @@ void do_versions_ipos_to_animato(Main *main)
bAction *new_act;
/* add a new action for this, and convert all data into that action */
- new_act = add_empty_action(id->name + 2);
+ new_act = add_empty_action(main, id->name + 2);
ipo_to_animato(NULL, ipo, NULL, NULL, NULL, NULL, &new_act->curves, &drivers);
new_act->idroot = ipo->blocktype;
}
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 782d796b8a7..d123de224e9 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -108,19 +108,6 @@ void BKE_key_free_nolib(Key *key)
}
-/* GS reads the memory pointed at in a specific ordering. There are,
- * however two definitions for it. I have jotted them down here, both,
- * but I think the first one is actually used. The thing is that
- * big-endian systems might read this the wrong way round. OTOH, we
- * constructed the IDs that are read out with this macro explicitly as
- * well. I expect we'll sort it out soon... */
-
-/* from blendef: */
-#define GS(a) (*((short *)(a)))
-
-/* from misc_util: flip the bytes from x */
-/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
-
Key *BKE_key_add(ID *id) /* common function */
{
Key *key;
@@ -259,7 +246,7 @@ void BKE_key_sort(Key *key)
/* find the right location and insert before */
for (kb2 = key->block.first; kb2; kb2 = kb2->next) {
if (kb2->pos > kb->pos) {
- BLI_insertlink(&key->block, kb2->prev, kb);
+ BLI_insertlinkafter(&key->block, kb2->prev, kb);
break;
}
}
@@ -418,9 +405,13 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float t[4], int cycl)
k1 = firstkey;
ofs += dpos;
}
- else if (t[2] == t[3]) break;
+ else if (t[2] == t[3]) {
+ break;
+ }
+ }
+ else {
+ k1 = k1->next;
}
- else k1 = k1->next;
t[0] = t[1];
k[0] = k[1];
@@ -608,7 +599,9 @@ static void cp_key(const int start, int end, const int tot, char *poin, Key *key
k1 += a * key->elemsize;
}
}
- else k1 += start * key->elemsize;
+ else {
+ k1 += start * key->elemsize;
+ }
}
if (mode == KEY_MODE_BEZTRIPLE) {
@@ -841,7 +834,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key
if (k[0]->totelem) {
k1d = k[0]->totelem / (float)tot;
}
- else flagdo -= 1;
+ else {
+ flagdo -= 1;
+ }
}
if (tot != k[1]->totelem) {
k2tot = 0.0;
@@ -849,7 +844,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key
if (k[0]->totelem) {
k2d = k[1]->totelem / (float)tot;
}
- else flagdo -= 2;
+ else {
+ flagdo -= 2;
+ }
}
if (tot != k[2]->totelem) {
k3tot = 0.0;
@@ -857,7 +854,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key
if (k[0]->totelem) {
k3d = k[2]->totelem / (float)tot;
}
- else flagdo -= 4;
+ else {
+ flagdo -= 4;
+ }
}
if (tot != k[3]->totelem) {
k4tot = 0.0;
@@ -865,7 +864,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key
if (k[0]->totelem) {
k4d = k[3]->totelem / (float)tot;
}
- else flagdo -= 8;
+ else {
+ flagdo -= 8;
+ }
}
/* this exception needed for slurphing */
@@ -882,7 +883,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key
k1 += a * key->elemsize;
}
}
- else k1 += start * key->elemsize;
+ else {
+ k1 += start * key->elemsize;
+ }
}
if (flagdo & 2) {
if (flagflo & 2) {
@@ -893,7 +896,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key
k2 += a * key->elemsize;
}
}
- else k2 += start * key->elemsize;
+ else {
+ k2 += start * key->elemsize;
+ }
}
if (flagdo & 4) {
if (flagflo & 4) {
@@ -904,7 +909,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key
k3 += a * key->elemsize;
}
}
- else k3 += start * key->elemsize;
+ else {
+ k3 += start * key->elemsize;
+ }
}
if (flagdo & 8) {
if (flagflo & 8) {
@@ -915,7 +922,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key
k4 += a * key->elemsize;
}
}
- else k4 += start * key->elemsize;
+ else {
+ k4 += start * key->elemsize;
+ }
}
}
@@ -981,7 +990,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key
k2 += elemsize;
}
}
- else k2 += elemsize;
+ else {
+ k2 += elemsize;
+ }
}
if (flagdo & 4) {
if (flagflo & 4) {
@@ -991,7 +1002,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key
k3 += elemsize;
}
}
- else k3 += elemsize;
+ else {
+ k3 += elemsize;
+ }
}
if (flagdo & 8) {
if (flagflo & 8) {
@@ -1001,7 +1014,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key
k4 += elemsize;
}
}
- else k4 += elemsize;
+ else {
+ k4 += elemsize;
+ }
}
if (mode == KEY_MODE_BEZTRIPLE) a += 2;
@@ -1078,7 +1093,7 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int
if (key->slurph && key->type != KEY_RELATIVE) {
const float ctime_scaled = key->ctime / 100.0f;
float delta = (float)key->slurph / tot;
- float cfra = (float)scene->r.cfra;
+ float cfra = BKE_scene_frame_get(scene);
int step, a;
if (tot > 100 && slurph_opt) {
@@ -1176,7 +1191,7 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, const in
if (key->slurph && key->type != KEY_RELATIVE) {
const float ctime_scaled = key->ctime / 100.0f;
float delta = (float)key->slurph / tot;
- float cfra = (float)scene->r.cfra;
+ float cfra = BKE_scene_frame_get(scene);
Nurb *nu;
int i = 0, remain = 0;
int step, a;
@@ -1258,7 +1273,7 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int
if (key->slurph && key->type != KEY_RELATIVE) {
const float ctime_scaled = key->ctime / 100.0f;
float delta = (float)key->slurph / tot;
- float cfra = (float)scene->r.cfra;
+ float cfra = BKE_scene_frame_get(scene);
int a;
for (a = 0; a < tot; a++, cfra += delta) {
@@ -1300,13 +1315,13 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int
}
/* returns key coordinates (+ tilt) when key applied, NULL otherwise */
-float *do_ob_key(Scene *scene, Object *ob)
+float *BKE_key_evaluate_object(Scene *scene, Object *ob, int *r_totelem)
{
Key *key = BKE_key_from_object(ob);
KeyBlock *actkb = BKE_keyblock_from_object(ob);
char *out;
int tot = 0, size = 0;
-
+
if (key == NULL || key->block.first == NULL)
return NULL;
@@ -1344,7 +1359,7 @@ float *do_ob_key(Scene *scene, Object *ob)
return NULL;
/* allocate array */
- out = MEM_callocN(size, "do_ob_key out");
+ out = MEM_callocN(size, "BKE_key_evaluate_object out");
/* prevent python from screwing this up? anyhoo, the from pointer could be dropped */
key->from = (ID *)ob->data;
@@ -1373,7 +1388,7 @@ float *do_ob_key(Scene *scene, Object *ob)
}
else {
/* do shapekey local drivers */
- float ctime = (float)scene->r.cfra; // XXX this needs to be checked
+ float ctime = BKE_scene_frame_get(scene);
BKE_animsys_evaluate_animdata(scene, &key->id, key->adt, ctime, ADT_RECALC_DRIVERS);
@@ -1383,6 +1398,9 @@ float *do_ob_key(Scene *scene, Object *ob)
else if (ob->type == OB_SURF) do_curve_key(scene, ob, key, out, tot);
}
+ if (r_totelem) {
+ *r_totelem = tot;
+ }
return (float *)out;
}
@@ -1732,7 +1750,7 @@ void BKE_key_convert_to_mesh(KeyBlock *kb, Mesh *me)
}
/************************* vert coords ************************/
-float (*BKE_key_convert_to_vertcos(Object * ob, KeyBlock * kb))[3]
+float (*BKE_key_convert_to_vertcos(Object *ob, KeyBlock *kb))[3]
{
float (*vertCos)[3], *co;
float *fp = kb->data;
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index 2f37db846f3..32cc5c6c22e 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -54,11 +54,11 @@
#include "BKE_main.h"
#include "BKE_node.h"
-Lamp *BKE_lamp_add(const char *name)
+Lamp *BKE_lamp_add(Main *bmain, const char *name)
{
Lamp *la;
- la = BKE_libblock_alloc(&G.main->lamp, ID_LA, name);
+ la = BKE_libblock_alloc(&bmain->lamp, ID_LA, name);
la->r = la->g = la->b = la->k = 1.0f;
la->haint = la->energy = 1.0f;
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 86b82c3cf43..c881209b109 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -37,7 +37,6 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_bpath.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -89,7 +88,7 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
/* vertex weight groups are just freed all for now */
if (lt->dvert) {
- free_dverts(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
+ BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
lt->dvert = NULL;
}
@@ -181,11 +180,11 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
MEM_freeN(vertexCos);
}
-Lattice *BKE_lattice_add(const char *name)
+Lattice *BKE_lattice_add(Main *bmain, const char *name)
{
Lattice *lt;
- lt = BKE_libblock_alloc(&G.main->latt, ID_LT, name);
+ lt = BKE_libblock_alloc(&bmain->latt, ID_LT, name);
lt->flag = LT_GRID;
@@ -210,7 +209,7 @@ Lattice *BKE_lattice_copy(Lattice *lt)
if (lt->dvert) {
int tot = lt->pntsu * lt->pntsv * lt->pntsw;
ltn->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
- copy_dverts(ltn->dvert, lt->dvert, tot);
+ BKE_defvert_array_copy(ltn->dvert, lt->dvert, tot);
}
ltn->editlatt = NULL;
@@ -221,12 +220,12 @@ Lattice *BKE_lattice_copy(Lattice *lt)
void BKE_lattice_free(Lattice *lt)
{
if (lt->def) MEM_freeN(lt->def);
- if (lt->dvert) free_dverts(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
+ if (lt->dvert) BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
if (lt->editlatt) {
Lattice *editlt = lt->editlatt->latt;
if (editlt->def) MEM_freeN(editlt->def);
- if (editlt->dvert) free_dverts(editlt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
+ if (editlt->dvert) BKE_defvert_array_free(editlt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
MEM_freeN(editlt);
MEM_freeN(lt->editlatt);
@@ -405,9 +404,11 @@ void calc_latt_deform(Object *ob, float co[3], float weight)
if (w != 0.0f) {
if (ww > 0) {
if (ww < lt->pntsw) idx_w = ww * lt->pntsu * lt->pntsv;
- else idx_w = (lt->pntsw - 1) * lt->pntsu * lt->pntsv;
+ else idx_w = (lt->pntsw - 1) * lt->pntsu * lt->pntsv;
+ }
+ else {
+ idx_w = 0;
}
- else idx_w = 0;
for (vv = vi - 1; vv <= vi + 2; vv++) {
v = w * tv[vv - vi + 1];
@@ -415,9 +416,11 @@ void calc_latt_deform(Object *ob, float co[3], float weight)
if (v != 0.0f) {
if (vv > 0) {
if (vv < lt->pntsv) idx_v = idx_w + vv * lt->pntsu;
- else idx_v = idx_w + (lt->pntsv - 1) * lt->pntsu;
+ else idx_v = idx_w + (lt->pntsv - 1) * lt->pntsu;
+ }
+ else {
+ idx_v = idx_w;
}
- else idx_v = idx_w;
for (uu = ui - 1; uu <= ui + 2; uu++) {
u = weight * v * tu[uu - ui + 1];
@@ -425,9 +428,11 @@ void calc_latt_deform(Object *ob, float co[3], float weight)
if (u != 0.0f) {
if (uu > 0) {
if (uu < lt->pntsu) idx_u = idx_v + uu;
- else idx_u = idx_v + (lt->pntsu - 1);
+ else idx_u = idx_v + (lt->pntsu - 1);
+ }
+ else {
+ idx_u = idx_v;
}
- else idx_u = idx_v;
madd_v3_v3fl(co, &lt->latticedata[idx_u * 3], u);
@@ -493,7 +498,9 @@ static int where_on_path_deform(Object *ob, float ctime, float vec[4], float dir
if (cycl == 0) {
ctime1 = CLAMPIS(ctime, 0.0f, 1.0f);
}
- else ctime1 = ctime;
+ else {
+ ctime1 = ctime;
+ }
/* vec needs 4 items */
if (where_on_path(ob, ctime1, vec, dir, quat, radius, NULL)) {
@@ -913,7 +920,7 @@ void outside_lattice(Lattice *lt)
bp->vec[1] += (1.0f - fac1) * bp1->vec[1] + fac1 * bp2->vec[1];
bp->vec[2] += (1.0f - fac1) * bp1->vec[2] + fac1 * bp2->vec[2];
- mul_v3_fl(bp->vec, 0.3333333f);
+ mul_v3_fl(bp->vec, 1.0f / 3.0f);
}
}
@@ -1004,3 +1011,66 @@ struct MDeformVert *BKE_lattice_deform_verts_get(struct Object *oblatt)
if (lt->editlatt) lt = lt->editlatt->latt;
return lt->dvert;
}
+
+void BKE_lattice_center_median(struct Lattice *lt, float cent[3])
+{
+ int i, numVerts;
+
+ if (lt->editlatt) lt = lt->editlatt->latt;
+ numVerts = lt->pntsu * lt->pntsv * lt->pntsw;
+
+ zero_v3(cent);
+
+ for (i = 0; i < numVerts; i++)
+ add_v3_v3(cent, lt->def[i].vec);
+
+ mul_v3_fl(cent, 1.0f / (float)numVerts);
+}
+
+void BKE_lattice_minmax(struct Lattice *lt, float min[3], float max[3])
+{
+ 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, lt->def[i].vec);
+}
+
+void BKE_lattice_center_bounds(struct Lattice *lt, float cent[3])
+{
+ float min[3], max[3];
+
+ INIT_MINMAX(min, max);
+
+ BKE_lattice_minmax(lt, min, max);
+ mid_v3_v3v3(cent, min, max);
+}
+
+void BKE_lattice_translate(Lattice *lt, float offset[3], int do_keys)
+{
+ int i, numVerts;
+
+ numVerts = lt->pntsu * lt->pntsv * lt->pntsw;
+
+ if (lt->def)
+ for (i = 0; i < numVerts; i++)
+ add_v3_v3(lt->def[i].vec, offset);
+
+ if (lt->editlatt)
+ for (i = 0; i < numVerts; i++)
+ add_v3_v3(lt->editlatt->latt->def[i].vec, offset);
+
+ if (do_keys && lt->key) {
+ KeyBlock *kb;
+
+ for (kb = lt->key->block.first; kb; kb = kb->next) {
+ float *fp = kb->data;
+ for (i = kb->totelem; i--; fp += 3) {
+ add_v3_v3(fp, offset);
+ }
+ }
+ }
+}
+
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index eb0612a75bd..594905bf7c5 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -47,6 +47,7 @@
#include "DNA_brush_types.h"
#include "DNA_camera_types.h"
#include "DNA_group_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_ipo_types.h"
#include "DNA_key_types.h"
#include "DNA_lamp_types.h"
@@ -54,6 +55,8 @@
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
+#include "DNA_movieclip_types.h"
+#include "DNA_mask_types.h"
#include "DNA_nla_types.h"
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
@@ -64,51 +67,50 @@
#include "DNA_vfont_types.h"
#include "DNA_windowmanager_types.h"
#include "DNA_world_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_movieclip_types.h"
-#include "DNA_mask_types.h"
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
#include "BLI_utildefines.h"
-#include "BLI_bpath.h"
+#include "BKE_bpath.h"
+#include "BKE_action.h"
#include "BKE_animsys.h"
+#include "BKE_armature.h"
+#include "BKE_brush.h"
#include "BKE_camera.h"
#include "BKE_context.h"
-#include "BKE_lamp.h"
-#include "BKE_library.h"
-#include "BKE_main.h"
-#include "BKE_global.h"
-#include "BKE_sound.h"
-#include "BKE_object.h"
-#include "BKE_screen.h"
-#include "BKE_mesh.h"
-#include "BKE_material.h"
#include "BKE_curve.h"
-#include "BKE_mball.h"
-#include "BKE_text.h"
-#include "BKE_texture.h"
-#include "BKE_scene.h"
+#include "BKE_fcurve.h"
+#include "BKE_font.h"
+#include "BKE_global.h"
+#include "BKE_group.h"
+#include "BKE_gpencil.h"
+#include "BKE_idprop.h"
#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_ipo.h"
#include "BKE_key.h"
-#include "BKE_world.h"
-#include "BKE_font.h"
-#include "BKE_group.h"
+#include "BKE_lamp.h"
#include "BKE_lattice.h"
-#include "BKE_armature.h"
-#include "BKE_action.h"
+#include "BKE_library.h"
+#include "BKE_linestyle.h"
+#include "BKE_mesh.h"
+#include "BKE_material.h"
+#include "BKE_main.h"
+#include "BKE_mball.h"
+#include "BKE_movieclip.h"
+#include "BKE_mask.h"
#include "BKE_node.h"
-#include "BKE_brush.h"
-#include "BKE_idprop.h"
+#include "BKE_object.h"
#include "BKE_particle.h"
-#include "BKE_gpencil.h"
-#include "BKE_fcurve.h"
+#include "BKE_packedFile.h"
#include "BKE_speaker.h"
-#include "BKE_movieclip.h"
-#include "BKE_mask.h"
+#include "BKE_sound.h"
+#include "BKE_screen.h"
+#include "BKE_scene.h"
+#include "BKE_text.h"
+#include "BKE_texture.h"
+#include "BKE_world.h"
#include "RNA_access.h"
@@ -122,9 +124,6 @@
* only use this definition, makes little and big endian systems
* work fine, in conjunction with MAKE_ID */
-/* from blendef: */
-#define GS(a) (*((short *)(a)))
-
/* ************* general ************************ */
@@ -136,9 +135,9 @@ void BKE_id_lib_local_paths(Main *bmain, Library *lib, ID *id)
{
char *bpath_user_data[2] = {bmain->name, lib->filepath};
- BLI_bpath_traverse_id(bmain, id,
- BLI_bpath_relocate_visitor,
- BLI_BPATH_TRAVERSE_SKIP_MULTIFILE,
+ BKE_bpath_traverse_id(bmain, id,
+ BKE_bpath_relocate_visitor,
+ BKE_BPATH_TRAVERSE_SKIP_MULTIFILE,
bpath_user_data);
}
@@ -152,6 +151,16 @@ void id_lib_extern(ID *id)
}
}
+/* ensure we have a real user */
+void id_us_ensure_real(ID *id)
+{
+ if (id) {
+ if (ID_REAL_USERS(id) <= 0) {
+ id->us = MAX2(id->us, 0) + 1;
+ }
+ }
+}
+
void id_us_plus(ID *id)
{
if (id) {
@@ -163,6 +172,7 @@ void id_us_plus(ID *id)
}
}
+/* decrements the user count for *id. */
void id_us_min(ID *id)
{
if (id) {
@@ -178,102 +188,110 @@ void id_us_min(ID *id)
}
}
-int id_make_local(ID *id, int test)
+/* calls the appropriate make_local method for the block, unless test. Returns true
+ * if the block can be made local. */
+bool id_make_local(ID *id, bool test)
{
if (id->flag & LIB_INDIRECT)
- return 0;
+ return false;
switch (GS(id->name)) {
case ID_SCE:
- return 0; /* not implemented */
+ return false; /* not implemented */
case ID_LI:
- return 0; /* can't be linked */
+ return false; /* can't be linked */
case ID_OB:
if (!test) BKE_object_make_local((Object *)id);
- return 1;
+ return true;
case ID_ME:
if (!test) {
BKE_mesh_make_local((Mesh *)id);
BKE_key_make_local(((Mesh *)id)->key);
}
- return 1;
+ return true;
case ID_CU:
if (!test) {
BKE_curve_make_local((Curve *)id);
BKE_key_make_local(((Curve *)id)->key);
}
- return 1;
+ return true;
case ID_MB:
if (!test) BKE_mball_make_local((MetaBall *)id);
- return 1;
+ return true;
case ID_MA:
if (!test) BKE_material_make_local((Material *)id);
- return 1;
+ return true;
case ID_TE:
if (!test) BKE_texture_make_local((Tex *)id);
- return 1;
+ return true;
case ID_IM:
if (!test) BKE_image_make_local((Image *)id);
- return 1;
+ return true;
case ID_LT:
if (!test) {
BKE_lattice_make_local((Lattice *)id);
BKE_key_make_local(((Lattice *)id)->key);
}
- return 1;
+ return true;
case ID_LA:
if (!test) BKE_lamp_make_local((Lamp *)id);
- return 1;
+ return true;
case ID_CA:
if (!test) BKE_camera_make_local((Camera *)id);
- return 1;
+ return true;
case ID_SPK:
if (!test) BKE_speaker_make_local((Speaker *)id);
- return 1;
+ return true;
case ID_IP:
- return 0; /* deprecated */
+ return false; /* deprecated */
case ID_KE:
if (!test) BKE_key_make_local((Key *)id);
- return 1;
+ return true;
case ID_WO:
if (!test) BKE_world_make_local((World *)id);
- return 1;
+ return true;
case ID_SCR:
- return 0; /* can't be linked */
+ return false; /* can't be linked */
case ID_VF:
- return 0; /* not implemented */
+ return false; /* not implemented */
case ID_TXT:
- return 0; /* not implemented */
+ return false; /* not implemented */
case ID_SCRIPT:
- return 0; /* deprecated */
+ return false; /* deprecated */
case ID_SO:
- return 0; /* not implemented */
+ return false; /* not implemented */
case ID_GR:
- return 0; /* not implemented */
+ return false; /* not implemented */
case ID_AR:
if (!test) BKE_armature_make_local((bArmature *)id);
- return 1;
+ return true;
case ID_AC:
if (!test) BKE_action_make_local((bAction *)id);
- return 1;
+ return true;
case ID_NT:
- return 0; /* not implemented */
+ return false; /* not implemented */
case ID_BR:
if (!test) BKE_brush_make_local((Brush *)id);
- return 1;
+ return true;
case ID_PA:
if (!test) BKE_particlesettings_make_local((ParticleSettings *)id);
- return 1;
+ return true;
case ID_WM:
- return 0; /* can't be linked */
+ return false; /* can't be linked */
case ID_GD:
+ return false; /* not implemented */
+ case ID_LS:
return 0; /* not implemented */
}
- return 0;
+ return false;
}
-int id_copy(ID *id, ID **newid, int 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.
+ */
+bool id_copy(ID *id, ID **newid, bool test)
{
if (!test) *newid = NULL;
@@ -282,124 +300,127 @@ int id_copy(ID *id, ID **newid, int test)
* - id.us of the new ID is set to 1 */
switch (GS(id->name)) {
case ID_SCE:
- return 0; /* can't be copied from here */
+ return false; /* can't be copied from here */
case ID_LI:
- return 0; /* can't be copied from here */
+ return false; /* can't be copied from here */
case ID_OB:
if (!test) *newid = (ID *)BKE_object_copy((Object *)id);
- return 1;
+ return true;
case ID_ME:
if (!test) *newid = (ID *)BKE_mesh_copy((Mesh *)id);
- return 1;
+ return true;
case ID_CU:
if (!test) *newid = (ID *)BKE_curve_copy((Curve *)id);
- return 1;
+ return true;
case ID_MB:
if (!test) *newid = (ID *)BKE_mball_copy((MetaBall *)id);
- return 1;
+ return true;
case ID_MA:
if (!test) *newid = (ID *)BKE_material_copy((Material *)id);
- return 1;
+ return true;
case ID_TE:
if (!test) *newid = (ID *)BKE_texture_copy((Tex *)id);
- return 1;
+ return true;
case ID_IM:
- if (!test) *newid = (ID *)BKE_image_copy((Image *)id);
- return 1;
+ if (!test) *newid = (ID *)BKE_image_copy(G.main, (Image *)id);
+ return true;
case ID_LT:
if (!test) *newid = (ID *)BKE_lattice_copy((Lattice *)id);
- return 1;
+ return true;
case ID_LA:
if (!test) *newid = (ID *)BKE_lamp_copy((Lamp *)id);
- return 1;
+ return true;
case ID_SPK:
if (!test) *newid = (ID *)BKE_speaker_copy((Speaker *)id);
- return 1;
+ return true;
case ID_CA:
if (!test) *newid = (ID *)BKE_camera_copy((Camera *)id);
- return 1;
+ return true;
case ID_IP:
- return 0; /* deprecated */
+ return false; /* deprecated */
case ID_KE:
if (!test) *newid = (ID *)BKE_key_copy((Key *)id);
- return 1;
+ return true;
case ID_WO:
if (!test) *newid = (ID *)BKE_world_copy((World *)id);
- return 1;
+ return true;
case ID_SCR:
- return 0; /* can't be copied from here */
+ return false; /* can't be copied from here */
case ID_VF:
- return 0; /* not implemented */
+ return false; /* not implemented */
case ID_TXT:
if (!test) *newid = (ID *)BKE_text_copy((Text *)id);
- return 1;
+ return true;
case ID_SCRIPT:
- return 0; /* deprecated */
+ return false; /* deprecated */
case ID_SO:
- return 0; /* not implemented */
+ return false; /* not implemented */
case ID_GR:
if (!test) *newid = (ID *)BKE_group_copy((Group *)id);
- return 1;
+ return true;
case ID_AR:
if (!test) *newid = (ID *)BKE_armature_copy((bArmature *)id);
- return 1;
+ return true;
case ID_AC:
if (!test) *newid = (ID *)BKE_action_copy((bAction *)id);
- return 1;
+ return true;
case ID_NT:
if (!test) *newid = (ID *)ntreeCopyTree((bNodeTree *)id);
- return 1;
+ return true;
case ID_BR:
if (!test) *newid = (ID *)BKE_brush_copy((Brush *)id);
- return 1;
+ return true;
case ID_PA:
if (!test) *newid = (ID *)BKE_particlesettings_copy((ParticleSettings *)id);
- return 1;
+ return true;
case ID_WM:
- return 0; /* can't be copied from here */
+ return false; /* can't be copied from here */
case ID_GD:
- return 0; /* not implemented */
+ return false; /* not implemented */
case ID_MSK:
if (!test) *newid = (ID *)BKE_mask_copy((Mask *)id);
+ return true;
+ case ID_LS:
+ if (!test) *newid = (ID *)BKE_copy_linestyle((FreestyleLineStyle *)id);
return 1;
}
- return 0;
+ return false;
}
-int id_unlink(ID *id, int test)
+bool id_unlink(ID *id, int test)
{
Main *mainlib = G.main;
ListBase *lb;
switch (GS(id->name)) {
case ID_TXT:
- if (test) return 1;
+ if (test) return true;
BKE_text_unlink(mainlib, (Text *)id);
break;
case ID_GR:
- if (test) return 1;
+ if (test) return true;
BKE_group_unlink((Group *)id);
break;
case ID_OB:
- if (test) return 1;
+ if (test) return true;
BKE_object_unlink((Object *)id);
break;
}
if (id->us == 0) {
- if (test) return 1;
+ if (test) return true;
lb = which_libbase(mainlib, GS(id->name));
BKE_libblock_free(lb, id);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-int id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
+bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
{
ID *newid = NULL;
PointerRNA idptr;
@@ -407,7 +428,7 @@ int id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
if (id) {
/* if property isn't editable, we're going to have an extra block hanging around until we save */
if (RNA_property_editable(ptr, prop)) {
- if (id_copy(id, &newid, 0) && newid) {
+ if (id_copy(id, &newid, false) && newid) {
/* copy animation actions too */
BKE_copy_animdata_id_action(id);
/* us is 1 by convention, but RNA_property_pointer_set
@@ -419,12 +440,12 @@ int id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
RNA_property_pointer_set(ptr, prop, idptr);
RNA_property_update(C, ptr, prop);
- return 1;
+ return true;
}
}
}
- return 0;
+ return false;
}
ListBase *which_libbase(Main *mainlib, short type)
@@ -492,6 +513,8 @@ ListBase *which_libbase(Main *mainlib, short type)
return &(mainlib->movieclip);
case ID_MSK:
return &(mainlib->mask);
+ case ID_LS:
+ return &(mainlib->linestyle);
}
return NULL;
}
@@ -528,7 +551,13 @@ void recalc_all_library_objects(Main *main)
ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
}
-/* note: MAX_LIBARRAY define should match this code */
+/**
+ * puts into array *lb pointers to all the ListBase structs in main,
+ * and returns the number of them as the function result. This is useful for
+ * generic traversal of all the blocks in a Main (by traversing all the
+ * lists in turn), without worrying about block types.
+ *
+ * \note MAX_LIBARRAY define should match this code */
int set_listbasepointers(Main *main, ListBase **lb)
{
int a = 0;
@@ -576,6 +605,7 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[a++] = &(main->wm);
lb[a++] = &(main->movieclip);
lb[a++] = &(main->mask);
+ lb[a++] = &(main->linestyle);
lb[a] = NULL;
@@ -592,6 +622,10 @@ int set_listbasepointers(Main *main, ListBase **lb)
*
* **************************** */
+/**
+ * Allocates and returns memory of the right size for the specified block type,
+ * initialized to zero.
+ */
static ID *alloc_libblock_notest(short type)
{
ID *id = NULL;
@@ -690,11 +724,19 @@ static ID *alloc_libblock_notest(short type)
case ID_MSK:
id = MEM_callocN(sizeof(Mask), "Mask");
break;
+ case ID_LS:
+ id = MEM_callocN(sizeof(FreestyleLineStyle), "Freestyle Line Style");
+ break;
}
return id;
}
-/* used everywhere in blenkernel and text.c */
+/**
+ * Allocates and returns a block of the specified type, with the specified name
+ * (adjusted as necessary to ensure uniqueness), and appended to the specified list.
+ * The user count is set to 1, all other content (apart from name and links) being
+ * initialized to zero.
+ */
void *BKE_libblock_alloc(ListBase *lb, short type, const char *name)
{
ID *id = NULL;
@@ -706,25 +748,25 @@ void *BKE_libblock_alloc(ListBase *lb, short type, const char *name)
id->icon_id = 0;
*( (short *)id->name) = type;
new_id(lb, id, name);
- /* alphabetic insterion: is in new_id */
+ /* alphabetic insertion: is in new_id */
}
return id;
}
/* by spec, animdata is first item after ID */
/* and, trust that BKE_animdata_from_id() will only find AnimData for valid ID-types */
-static void id_copy_animdata(ID *id, const short do_action)
+static void id_copy_animdata(ID *id, const bool do_action)
{
AnimData *adt = BKE_animdata_from_id(id);
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_copy_animdata(iat->adt, do_action); /* could be set to false, need to investigate */
}
}
/* material nodes use this since they are not treated as libdata */
-void BKE_libblock_copy_data(ID *id, const ID *id_from, const short do_action)
+void BKE_libblock_copy_data(ID *id, const ID *id_from, const bool do_action)
{
if (id_from->properties)
id->properties = IDP_CopyProperty(id_from->properties);
@@ -734,13 +776,13 @@ void BKE_libblock_copy_data(ID *id, const ID *id_from, const short do_action)
}
/* used everywhere in blenkernel */
-void *BKE_libblock_copy(ID *id)
+void *BKE_libblock_copy_ex(Main *bmain, ID *id)
{
ID *idn;
ListBase *lb;
size_t idn_len;
- lb = which_libbase(G.main, GS(id->name));
+ lb = which_libbase(bmain, GS(id->name));
idn = BKE_libblock_alloc(lb, GS(id->name), id->name + 2);
assert(idn != NULL);
@@ -756,14 +798,20 @@ void *BKE_libblock_copy(ID *id)
id->newid = idn;
idn->flag |= LIB_NEW;
- BKE_libblock_copy_data(idn, id, FALSE);
+ BKE_libblock_copy_data(idn, id, false);
return idn;
}
-static void BKE_library_free(Library *UNUSED(lib))
+void *BKE_libblock_copy(ID *id)
+{
+ return BKE_libblock_copy_ex(G.main, id);
+}
+
+static void BKE_library_free(Library *lib)
{
- /* no freeing needed for libraries yet */
+ if (lib->packedfile)
+ freePackedFile(lib->packedfile);
}
static void (*free_windowmanager_cb)(bContext *, wmWindowManager *) = NULL;
@@ -914,6 +962,9 @@ void BKE_libblock_free(ListBase *lb, void *idv)
case ID_MSK:
BKE_mask_free(bmain, (Mask *)id);
break;
+ case ID_LS:
+ BKE_free_linestyle((FreestyleLineStyle *)id);
+ break;
}
BLI_remlink(lb, id);
@@ -1164,7 +1215,7 @@ void id_sort_by_name(ListBase *lb, ID *id)
}
-/*
+/**
* Check to see if there is an ID with the same name as 'name'.
* Returns the ID if so, if not, returns NULL
*/
@@ -1186,9 +1237,9 @@ static ID *is_dupid(ListBase *lb, ID *id, const char *name)
return idtest;
}
-/*
+/**
* Check to see if an ID name is already used, and find a new one if so.
- * Return 1 if created a new name (returned in name).
+ * Return true if created a new name (returned in name).
*
* Normally the ID that's being check is already in the ListBase, so ID *id
* points at the new entry. The Python Library module needs to know what
@@ -1196,11 +1247,13 @@ static ID *is_dupid(ListBase *lb, ID *id, const char *name)
* id is NULL
*/
-static int check_for_dupid(ListBase *lb, ID *id, char *name)
+static bool check_for_dupid(ListBase *lb, ID *id, char *name)
{
ID *idtest;
int nr = 0, nrtest, a, left_len;
- char in_use[64]; /* use as a boolean array, unrelated to name length */
+#define MAX_IN_USE 64
+ bool in_use[MAX_IN_USE];
+ /* to speed up finding unused numbers within [1 .. MAX_IN_USE - 1] */
char left[MAX_ID_NAME + 8], leftest[MAX_ID_NAME + 8];
@@ -1208,23 +1261,23 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name)
/* if ( strlen(name) > MAX_ID_NAME-3 ) name[MAX_ID_NAME-3] = 0; */
/* removed since this is only ever called from one place - campbell */
- while (1) {
+ while (true) {
/* phase 1: id already exists? */
idtest = is_dupid(lb, id, name);
/* if there is no double, done */
- if (idtest == NULL) return 0;
+ if (idtest == NULL) return false;
/* we have a dup; need to make a new name */
- /* quick check so we can reuse one of first 64 ids if vacant */
- memset(in_use, 0, sizeof(in_use));
+ /* quick check so we can reuse one of first MAX_IN_USE - 1 ids if vacant */
+ memset(in_use, false, sizeof(in_use));
/* get name portion, number portion ("name.number") */
left_len = BLI_split_name_num(left, &nr, name, '.');
/* if new name will be too long, truncate it */
- if (nr > 999 && left_len > (MAX_ID_NAME - 8)) {
+ if (nr > 999 && left_len > (MAX_ID_NAME - 8)) { /* assumption: won't go beyond 9999 */
left[MAX_ID_NAME - 8] = 0;
left_len = MAX_ID_NAME - 8;
}
@@ -1241,35 +1294,50 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name)
(BLI_split_name_num(leftest, &nrtest, idtest->name + 2, '.') == left_len)
)
{
- if (nrtest < sizeof(in_use))
- in_use[nrtest] = 1; /* mark as used */
+ /* will get here at least once, otherwise is_dupid call above would have returned NULL */
+ if (nrtest < MAX_IN_USE)
+ in_use[nrtest] = true; /* mark as used */
if (nr <= nrtest)
nr = nrtest + 1; /* track largest unused */
}
}
+ /* At this point, nr will be at least 1. */
+ BLI_assert(nr >= 1);
/* decide which value of nr to use */
- for (a = 0; a < sizeof(in_use); a++) {
- if (a >= nr) break; /* stop when we've check up to biggest */
- if (in_use[a] == 0) { /* found an unused value */
+ for (a = 0; a < MAX_IN_USE; a++) {
+ if (a >= nr) break; /* stop when we've checked up to biggest */ /* redundant check */
+ if (!in_use[a]) { /* found an unused value */
nr = a;
+ /* can only be zero if all potential duplicate names had
+ * nonzero numeric suffixes, which means name itself has
+ * nonzero numeric suffix (else no name conflict and wouldn't
+ * have got here), which means name[left_len] is not a null */
break;
}
}
+ /* At this point, nr is either the lowest unused number within [0 .. MAX_IN_USE - 1],
+ * or 1 greater than the largest used number if all those low ones are taken.
+ * We can't be bothered to look for the lowest unused number beyond (MAX_IN_USE - 1). */
/* If the original name has no numeric suffix,
* rather than just chopping and adding numbers,
* shave off the end chars until we have a unique name.
* Check the null terminators match as well so we don't get Cube.000 -> Cube.00 */
if (nr == 0 && name[left_len] == '\0') {
- int len = left_len - 1;
+ int len;
+ /* FIXME: this code will never be executed, because either nr will be
+ * at least 1, or name will not end at left_len! */
+ BLI_assert(0);
+
+ len = left_len - 1;
idtest = is_dupid(lb, id, name);
while (idtest && len > 1) {
name[len--] = '\0';
idtest = is_dupid(lb, id, name);
}
- if (idtest == NULL) return 1;
+ if (idtest == NULL) return true;
/* otherwise just continue and use a number suffix */
}
@@ -1283,24 +1351,26 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name)
/* this format specifier is from hell... */
BLI_snprintf(name, sizeof(id->name) - 2, "%s.%.3d", left, nr);
- return 1;
+ return true;
}
+
+#undef MAX_IN_USE
}
/*
* Only for local blocks: external en indirect blocks already have a
* unique ID.
*
- * return 1: created a new name
+ * return true: created a new name
*/
-int new_id(ListBase *lb, ID *id, const char *tname)
+bool new_id(ListBase *lb, ID *id, const char *tname)
{
- int result;
+ bool result;
char name[MAX_ID_NAME - 2];
/* if library, don't rename */
- if (id->lib) return 0;
+ if (id->lib) return false;
/* if no libdata given, look up based on ID */
if (lb == NULL) lb = which_libbase(G.main, GS(id->name));
@@ -1372,10 +1442,9 @@ void clear_id_newpoins(void)
}
}
-#define LIBTAG(a) if (a && a->id.lib) { a->id.flag &= ~LIB_INDIRECT; a->id.flag |= LIB_EXTERN; } (void)0
-
static void lib_indirect_test_id(ID *id, Library *lib)
{
+#define LIBTAG(a) if (a && a->id.lib) { a->id.flag &= ~LIB_INDIRECT; a->id.flag |= LIB_EXTERN; } (void)0
if (id->lib) {
/* datablocks that were indirectly related are now direct links
@@ -1415,6 +1484,8 @@ static void lib_indirect_test_id(ID *id, Library *lib)
me = ob->data;
LIBTAG(me);
}
+
+#undef LIBTAG
}
void tag_main_lb(ListBase *lb, const short tag)
@@ -1452,9 +1523,9 @@ void tag_main(struct Main *mainvar, const short tag)
/* if lib!=NULL, only all from lib local
* bmain is almost certainly G.main */
-void BKE_library_make_local(Main *bmain, Library *lib, int untagged_only)
+void BKE_library_make_local(Main *bmain, Library *lib, bool untagged_only)
{
- ListBase *lbarray[MAX_LIBARRAY], tempbase = {NULL, NULL};
+ ListBase *lbarray[MAX_LIBARRAY];
ID *id, *idn;
int a;
@@ -1472,7 +1543,7 @@ void BKE_library_make_local(Main *bmain, Library *lib, int untagged_only)
* (very nasty to discover all your links are lost after appending)
* */
if (id->flag & (LIB_EXTERN | LIB_INDIRECT | LIB_NEW) &&
- (untagged_only == 0 || !(id->flag & LIB_PRE_EXISTING)))
+ ((untagged_only == false) || !(id->flag & LIB_PRE_EXISTING)))
{
if (lib == NULL || id->lib == lib) {
if (id->lib) {
@@ -1489,16 +1560,8 @@ void BKE_library_make_local(Main *bmain, Library *lib, int untagged_only)
}
id = idn;
}
-
- /* patch2: make it aphabetically */
- while ( (id = tempbase.first) ) {
- BLI_remlink(&tempbase, id);
- BLI_addtail(lbarray[a], id);
- new_id(lbarray[a], id, NULL);
- }
}
- /* patch 3: make sure library data isn't indirect falsely... */
a = set_listbasepointers(bmain, lbarray);
while (a--) {
for (id = lbarray[a]->first; id; id = id->next)
@@ -1514,39 +1577,20 @@ void test_idbutton(char *name)
ID *idtest;
- lb = which_libbase(G.main, GS(name - 2) );
+ lb = which_libbase(G.main, GS(name) );
if (lb == NULL) return;
/* search for id */
- idtest = BLI_findstring(lb, name, offsetof(ID, name) + 2);
+ idtest = BLI_findstring(lb, name + 2, offsetof(ID, name) + 2);
- if (idtest && (new_id(lb, idtest, name) == 0)) {
+ if (idtest && !new_id(lb, idtest, name + 2)) {
id_sort_by_name(lb, idtest);
}
}
-void text_idbutton(struct ID *id, char *text)
-{
- if (id) {
- if (GS(id->name) == ID_SCE)
- strcpy(text, "SCE: ");
- else if (GS(id->name) == ID_SCR)
- strcpy(text, "SCR: ");
- else if (GS(id->name) == ID_MA && ((Material *)id)->use_nodes)
- strcpy(text, "NT: ");
- else {
- text[0] = id->name[0];
- text[1] = id->name[1];
- text[2] = ':';
- text[3] = ' ';
- text[4] = 0;
- }
- }
- else {
- text[0] = '\0';
- }
-}
-
+/**
+ * Sets the name of a block to name, suitably adjusted for uniqueness.
+ */
void rename_id(ID *id, const char *name)
{
ListBase *lb;
@@ -1557,7 +1601,11 @@ void rename_id(ID *id, const char *name)
new_id(lb, id, name);
}
-void name_uiprefix_id(char *name, ID *id)
+/**
+ * Returns in name the name of the block, with a 3-character prefix prepended
+ * indicating whether it comes from a library, has a fake user, or no users.
+ */
+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' : ' ';
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
new file mode 100644
index 00000000000..fe27ddcfafe
--- /dev/null
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -0,0 +1,1070 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 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/linestyle.c
+ * \ingroup bke
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+#include "DNA_material_types.h" /* for ramp blend */
+#include "DNA_texture_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_linestyle.h"
+#include "BKE_main.h"
+#include "BKE_texture.h"
+#include "BKE_colortools.h"
+#include "BKE_animsys.h"
+
+static const char *modifier_name[LS_MODIFIER_NUM] = {
+ NULL,
+ "Along Stroke",
+ "Distance from Camera",
+ "Distance from Object",
+ "Material",
+ "Sampling",
+ "Bezier Curve",
+ "Sinus Displacement",
+ "Spatial Noise",
+ "Perlin Noise 1D",
+ "Perlin Noise 2D",
+ "Backbone Stretcher",
+ "Tip Remover",
+ "Calligraphy",
+ "Polygonalization",
+ "Guiding Lines",
+ "Blueprint",
+ "2D Offset",
+ "2D Transform",
+};
+
+static void default_linestyle_settings(FreestyleLineStyle *linestyle)
+{
+ linestyle->panel = LS_PANEL_STROKES;
+ linestyle->r = linestyle->g = linestyle->b = 1.0f;
+ linestyle->alpha = 1.0f;
+ linestyle->thickness = 1.0f;
+ linestyle->thickness_position = LS_THICKNESS_CENTER;
+ linestyle->thickness_ratio = 0.5f;
+ linestyle->chaining = LS_CHAINING_PLAIN;
+ linestyle->rounds = 3;
+ linestyle->min_angle = DEG2RADF(0.0f);
+ linestyle->max_angle = DEG2RADF(0.0f);
+ linestyle->min_length = 0.0f;
+ linestyle->max_length = 10000.0f;
+ linestyle->split_length = 100;
+
+ linestyle->color_modifiers.first = linestyle->color_modifiers.last = NULL;
+ linestyle->alpha_modifiers.first = linestyle->alpha_modifiers.last = NULL;
+ linestyle->thickness_modifiers.first = linestyle->thickness_modifiers.last = NULL;
+ linestyle->geometry_modifiers.first = linestyle->geometry_modifiers.last = NULL;
+
+ BKE_add_linestyle_geometry_modifier(linestyle, LS_MODIFIER_SAMPLING);
+
+ linestyle->caps = LS_CAPS_BUTT;
+}
+
+FreestyleLineStyle *BKE_new_linestyle(const char *name, struct Main *main)
+{
+ FreestyleLineStyle *linestyle;
+
+ if (!main)
+ main = G.main;
+
+ linestyle = (FreestyleLineStyle *)BKE_libblock_alloc(&main->linestyle, ID_LS, name);
+
+ default_linestyle_settings(linestyle);
+
+ return linestyle;
+}
+
+void BKE_free_linestyle(FreestyleLineStyle *linestyle)
+{
+ LineStyleModifier *m;
+
+ BKE_free_animdata(&linestyle->id);
+ while ((m = (LineStyleModifier *)linestyle->color_modifiers.first))
+ BKE_remove_linestyle_color_modifier(linestyle, m);
+ while ((m = (LineStyleModifier *)linestyle->alpha_modifiers.first))
+ BKE_remove_linestyle_alpha_modifier(linestyle, m);
+ while ((m = (LineStyleModifier *)linestyle->thickness_modifiers.first))
+ BKE_remove_linestyle_thickness_modifier(linestyle, m);
+ while ((m = (LineStyleModifier *)linestyle->geometry_modifiers.first))
+ BKE_remove_linestyle_geometry_modifier(linestyle, m);
+}
+
+FreestyleLineStyle *BKE_copy_linestyle(FreestyleLineStyle *linestyle)
+{
+ FreestyleLineStyle *new_linestyle;
+ LineStyleModifier *m;
+
+ new_linestyle = BKE_new_linestyle(linestyle->id.name + 2, NULL);
+ BKE_free_linestyle(new_linestyle);
+
+ new_linestyle->r = linestyle->r;
+ new_linestyle->g = linestyle->g;
+ new_linestyle->b = linestyle->b;
+ new_linestyle->alpha = linestyle->alpha;
+ new_linestyle->thickness = linestyle->thickness;
+ new_linestyle->thickness_position = linestyle->thickness_position;
+ new_linestyle->thickness_ratio = linestyle->thickness_ratio;
+ new_linestyle->flag = linestyle->flag;
+ new_linestyle->caps = linestyle->caps;
+ new_linestyle->chaining = linestyle->chaining;
+ new_linestyle->rounds = linestyle->rounds;
+ new_linestyle->min_angle = linestyle->min_angle;
+ new_linestyle->max_angle = linestyle->max_angle;
+ new_linestyle->min_length = linestyle->min_length;
+ new_linestyle->max_length = linestyle->max_length;
+ new_linestyle->split_length = linestyle->split_length;
+ new_linestyle->dash1 = linestyle->dash1;
+ new_linestyle->gap1 = linestyle->gap1;
+ new_linestyle->dash2 = linestyle->dash2;
+ new_linestyle->gap2 = linestyle->gap2;
+ new_linestyle->dash3 = linestyle->dash3;
+ new_linestyle->gap3 = linestyle->gap3;
+ new_linestyle->panel = linestyle->panel;
+ for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next)
+ BKE_copy_linestyle_color_modifier(new_linestyle, m);
+ for (m = (LineStyleModifier *)linestyle->alpha_modifiers.first; m; m = m->next)
+ BKE_copy_linestyle_alpha_modifier(new_linestyle, m);
+ for (m = (LineStyleModifier *)linestyle->thickness_modifiers.first; m; m = m->next)
+ BKE_copy_linestyle_thickness_modifier(new_linestyle, m);
+ for (m = (LineStyleModifier *)linestyle->geometry_modifiers.first; m; m = m->next)
+ BKE_copy_linestyle_geometry_modifier(new_linestyle, m);
+
+ return new_linestyle;
+}
+
+static LineStyleModifier *new_modifier(int type, size_t size)
+{
+ LineStyleModifier *m;
+
+ m = (LineStyleModifier *)MEM_callocN(size, "line style modifier");
+ m->type = type;
+ strcpy(m->name, modifier_name[type]);
+ m->influence = 1.0f;
+ m->flags = LS_MODIFIER_ENABLED | LS_MODIFIER_EXPANDED;
+
+ return m;
+}
+
+static void add_to_modifier_list(ListBase *lb, LineStyleModifier *m)
+{
+ BLI_addtail(lb, (void *)m);
+ BLI_uniquename(lb, m, modifier_name[m->type], '.', offsetof(LineStyleModifier, name), sizeof(m->name));
+}
+
+static LineStyleModifier *alloc_color_modifier(int type)
+{
+ size_t size;
+
+ switch (type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ size = sizeof(LineStyleColorModifier_AlongStroke);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ size = sizeof(LineStyleColorModifier_DistanceFromCamera);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ size = sizeof(LineStyleColorModifier_DistanceFromObject);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ size = sizeof(LineStyleColorModifier_Material);
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+
+ return new_modifier(type, size);
+}
+
+LineStyleModifier *BKE_add_linestyle_color_modifier(FreestyleLineStyle *linestyle, int type)
+{
+ LineStyleModifier *m;
+
+ m = alloc_color_modifier(type);
+ m->blend = MA_RAMP_BLEND;
+
+ switch (type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ ((LineStyleColorModifier_AlongStroke *)m)->color_ramp = add_colorband(1);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ ((LineStyleColorModifier_DistanceFromCamera *)m)->color_ramp = add_colorband(1);
+ ((LineStyleColorModifier_DistanceFromCamera *)m)->range_min = 0.0f;
+ ((LineStyleColorModifier_DistanceFromCamera *)m)->range_max = 10000.0f;
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ ((LineStyleColorModifier_DistanceFromObject *)m)->target = NULL;
+ ((LineStyleColorModifier_DistanceFromObject *)m)->color_ramp = add_colorband(1);
+ ((LineStyleColorModifier_DistanceFromObject *)m)->range_min = 0.0f;
+ ((LineStyleColorModifier_DistanceFromObject *)m)->range_max = 10000.0f;
+ break;
+ case LS_MODIFIER_MATERIAL:
+ ((LineStyleColorModifier_Material *)m)->color_ramp = add_colorband(1);
+ ((LineStyleColorModifier_Material *)m)->mat_attr = LS_MODIFIER_MATERIAL_DIFF;
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ add_to_modifier_list(&linestyle->color_modifiers, m);
+
+ return m;
+}
+
+LineStyleModifier *BKE_copy_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+{
+ LineStyleModifier *new_m;
+
+ new_m = alloc_color_modifier(m->type);
+ new_m->influence = m->influence;
+ new_m->flags = m->flags;
+ new_m->blend = m->blend;
+
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ {
+ LineStyleColorModifier_AlongStroke *p = (LineStyleColorModifier_AlongStroke *)m;
+ LineStyleColorModifier_AlongStroke *q = (LineStyleColorModifier_AlongStroke *)new_m;
+ q->color_ramp = MEM_dupallocN(p->color_ramp);
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ {
+ LineStyleColorModifier_DistanceFromCamera *p = (LineStyleColorModifier_DistanceFromCamera *)m;
+ LineStyleColorModifier_DistanceFromCamera *q = (LineStyleColorModifier_DistanceFromCamera *)new_m;
+ q->color_ramp = MEM_dupallocN(p->color_ramp);
+ q->range_min = p->range_min;
+ q->range_max = p->range_max;
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleColorModifier_DistanceFromObject *p = (LineStyleColorModifier_DistanceFromObject *)m;
+ LineStyleColorModifier_DistanceFromObject *q = (LineStyleColorModifier_DistanceFromObject *)new_m;
+ if (p->target)
+ p->target->id.us++;
+ q->target = p->target;
+ q->color_ramp = MEM_dupallocN(p->color_ramp);
+ q->range_min = p->range_min;
+ q->range_max = p->range_max;
+ }
+ break;
+ case LS_MODIFIER_MATERIAL:
+ {
+ LineStyleColorModifier_Material *p = (LineStyleColorModifier_Material *)m;
+ LineStyleColorModifier_Material *q = (LineStyleColorModifier_Material *)new_m;
+ q->color_ramp = MEM_dupallocN(p->color_ramp);
+ q->mat_attr = p->mat_attr;
+ }
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ add_to_modifier_list(&linestyle->color_modifiers, new_m);
+
+ return new_m;
+}
+
+void BKE_remove_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+{
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ MEM_freeN(((LineStyleColorModifier_AlongStroke *)m)->color_ramp);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ MEM_freeN(((LineStyleColorModifier_DistanceFromCamera *)m)->color_ramp);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ MEM_freeN(((LineStyleColorModifier_DistanceFromObject *)m)->color_ramp);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ MEM_freeN(((LineStyleColorModifier_Material *)m)->color_ramp);
+ break;
+ }
+ BLI_freelinkN(&linestyle->color_modifiers, m);
+}
+
+static LineStyleModifier *alloc_alpha_modifier(int type)
+{
+ size_t size;
+
+ switch (type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ size = sizeof(LineStyleAlphaModifier_AlongStroke);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ size = sizeof(LineStyleAlphaModifier_DistanceFromCamera);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ size = sizeof(LineStyleAlphaModifier_DistanceFromObject);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ size = sizeof(LineStyleAlphaModifier_Material);
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ return new_modifier(type, size);
+}
+
+LineStyleModifier *BKE_add_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, int type)
+{
+ LineStyleModifier *m;
+
+ m = alloc_alpha_modifier(type);
+ m->blend = LS_VALUE_BLEND;
+
+ switch (type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ {
+ LineStyleAlphaModifier_AlongStroke *p = (LineStyleAlphaModifier_AlongStroke *)m;
+ p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ {
+ LineStyleAlphaModifier_DistanceFromCamera *p = (LineStyleAlphaModifier_DistanceFromCamera *)m;
+ p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ p->range_min = 0.0f;
+ p->range_max = 10000.0f;
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleAlphaModifier_DistanceFromObject *p = (LineStyleAlphaModifier_DistanceFromObject *)m;
+ p->target = NULL;
+ p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ p->range_min = 0.0f;
+ p->range_max = 10000.0f;
+ }
+ break;
+ case LS_MODIFIER_MATERIAL:
+ {
+ 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_DIFF;
+ }
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ add_to_modifier_list(&linestyle->alpha_modifiers, m);
+
+ return m;
+}
+
+LineStyleModifier *BKE_copy_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+{
+ LineStyleModifier *new_m;
+
+ new_m = alloc_alpha_modifier(m->type);
+ new_m->influence = m->influence;
+ new_m->flags = m->flags;
+ new_m->blend = m->blend;
+
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ {
+ LineStyleAlphaModifier_AlongStroke *p = (LineStyleAlphaModifier_AlongStroke *)m;
+ LineStyleAlphaModifier_AlongStroke *q = (LineStyleAlphaModifier_AlongStroke *)new_m;
+ q->curve = curvemapping_copy(p->curve);
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ {
+ LineStyleAlphaModifier_DistanceFromCamera *p = (LineStyleAlphaModifier_DistanceFromCamera *)m;
+ LineStyleAlphaModifier_DistanceFromCamera *q = (LineStyleAlphaModifier_DistanceFromCamera *)new_m;
+ q->curve = curvemapping_copy(p->curve);
+ q->range_min = p->range_min;
+ q->range_max = p->range_max;
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleAlphaModifier_DistanceFromObject *p = (LineStyleAlphaModifier_DistanceFromObject *)m;
+ LineStyleAlphaModifier_DistanceFromObject *q = (LineStyleAlphaModifier_DistanceFromObject *)new_m;
+ if (p->target)
+ p->target->id.us++;
+ q->target = p->target;
+ q->curve = curvemapping_copy(p->curve);
+ q->range_min = p->range_min;
+ q->range_max = p->range_max;
+ }
+ break;
+ case LS_MODIFIER_MATERIAL:
+ {
+ LineStyleAlphaModifier_Material *p = (LineStyleAlphaModifier_Material *)m;
+ LineStyleAlphaModifier_Material *q = (LineStyleAlphaModifier_Material *)new_m;
+ q->curve = curvemapping_copy(p->curve);
+ q->mat_attr = p->mat_attr;
+ }
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ add_to_modifier_list(&linestyle->alpha_modifiers, new_m);
+
+ return new_m;
+}
+
+void BKE_remove_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+{
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ curvemapping_free(((LineStyleAlphaModifier_AlongStroke *)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ curvemapping_free(((LineStyleAlphaModifier_DistanceFromCamera *)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ curvemapping_free(((LineStyleAlphaModifier_DistanceFromObject *)m)->curve);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ curvemapping_free(((LineStyleAlphaModifier_Material *)m)->curve);
+ break;
+ }
+ BLI_freelinkN(&linestyle->alpha_modifiers, m);
+}
+
+static LineStyleModifier *alloc_thickness_modifier(int type)
+{
+ size_t size;
+
+ switch (type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ size = sizeof(LineStyleThicknessModifier_AlongStroke);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ size = sizeof(LineStyleThicknessModifier_DistanceFromCamera);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ size = sizeof(LineStyleThicknessModifier_DistanceFromObject);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ size = sizeof(LineStyleThicknessModifier_Material);
+ break;
+ case LS_MODIFIER_CALLIGRAPHY:
+ size = sizeof(LineStyleThicknessModifier_Calligraphy);
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+
+ return new_modifier(type, size);
+}
+
+LineStyleModifier *BKE_add_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, int type)
+{
+ LineStyleModifier *m;
+
+ m = alloc_thickness_modifier(type);
+ m->blend = LS_VALUE_BLEND;
+
+ switch (type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ {
+ LineStyleThicknessModifier_AlongStroke *p = (LineStyleThicknessModifier_AlongStroke *)m;
+ p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ p->value_min = 0.0f;
+ p->value_max = 1.0f;
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ {
+ LineStyleThicknessModifier_DistanceFromCamera *p = (LineStyleThicknessModifier_DistanceFromCamera *)m;
+ p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ p->range_min = 0.0f;
+ p->range_max = 1000.0f;
+ p->value_min = 0.0f;
+ p->value_max = 1.0f;
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleThicknessModifier_DistanceFromObject *p = (LineStyleThicknessModifier_DistanceFromObject *)m;
+ p->target = NULL;
+ p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ p->range_min = 0.0f;
+ p->range_max = 1000.0f;
+ p->value_min = 0.0f;
+ p->value_max = 1.0f;
+ }
+ break;
+ case LS_MODIFIER_MATERIAL:
+ {
+ LineStyleThicknessModifier_Material *p = (LineStyleThicknessModifier_Material *)m;
+ p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ p->mat_attr = LS_MODIFIER_MATERIAL_DIFF;
+ p->value_min = 0.0f;
+ p->value_max = 1.0f;
+ }
+ break;
+ case LS_MODIFIER_CALLIGRAPHY:
+ {
+ LineStyleThicknessModifier_Calligraphy *p = (LineStyleThicknessModifier_Calligraphy *)m;
+ p->min_thickness = 1.0f;
+ p->max_thickness = 10.0f;
+ p->orientation = DEG2RADF(60.0f);
+ }
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ add_to_modifier_list(&linestyle->thickness_modifiers, m);
+
+ return m;
+}
+
+LineStyleModifier *BKE_copy_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+{
+ LineStyleModifier *new_m;
+
+ new_m = alloc_thickness_modifier(m->type);
+ if (!new_m)
+ return NULL;
+ new_m->influence = m->influence;
+ new_m->flags = m->flags;
+ new_m->blend = m->blend;
+
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ {
+ LineStyleThicknessModifier_AlongStroke *p = (LineStyleThicknessModifier_AlongStroke *)m;
+ LineStyleThicknessModifier_AlongStroke *q = (LineStyleThicknessModifier_AlongStroke *)new_m;
+ q->curve = curvemapping_copy(p->curve);
+ q->value_min = p->value_min;
+ q->value_max = p->value_max;
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ {
+ LineStyleThicknessModifier_DistanceFromCamera *p = (LineStyleThicknessModifier_DistanceFromCamera *)m;
+ LineStyleThicknessModifier_DistanceFromCamera *q = (LineStyleThicknessModifier_DistanceFromCamera *)new_m;
+ q->curve = curvemapping_copy(p->curve);
+ q->range_min = p->range_min;
+ q->range_max = p->range_max;
+ q->value_min = p->value_min;
+ q->value_max = p->value_max;
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleThicknessModifier_DistanceFromObject *p = (LineStyleThicknessModifier_DistanceFromObject *)m;
+ LineStyleThicknessModifier_DistanceFromObject *q = (LineStyleThicknessModifier_DistanceFromObject *)new_m;
+ if (p->target)
+ p->target->id.us++;
+ q->target = p->target;
+ q->curve = curvemapping_copy(p->curve);
+ q->range_min = p->range_min;
+ q->range_max = p->range_max;
+ q->value_min = p->value_min;
+ q->value_max = p->value_max;
+ }
+ break;
+ case LS_MODIFIER_MATERIAL:
+ {
+ LineStyleThicknessModifier_Material *p = (LineStyleThicknessModifier_Material *)m;
+ LineStyleThicknessModifier_Material *q = (LineStyleThicknessModifier_Material *)new_m;
+ q->curve = curvemapping_copy(p->curve);
+ q->mat_attr = p->mat_attr;
+ q->value_min = p->value_min;
+ q->value_max = p->value_max;
+ }
+ break;
+ case LS_MODIFIER_CALLIGRAPHY:
+ {
+ LineStyleThicknessModifier_Calligraphy *p = (LineStyleThicknessModifier_Calligraphy *)m;
+ LineStyleThicknessModifier_Calligraphy *q = (LineStyleThicknessModifier_Calligraphy *)new_m;
+ q->min_thickness = p->min_thickness;
+ q->max_thickness = p->max_thickness;
+ q->orientation = p->orientation;
+ }
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ add_to_modifier_list(&linestyle->thickness_modifiers, new_m);
+
+ return new_m;
+}
+
+void BKE_remove_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+{
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ curvemapping_free(((LineStyleThicknessModifier_AlongStroke *)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ curvemapping_free(((LineStyleThicknessModifier_DistanceFromCamera *)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ curvemapping_free(((LineStyleThicknessModifier_DistanceFromObject *)m)->curve);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ curvemapping_free(((LineStyleThicknessModifier_Material *)m)->curve);
+ break;
+ case LS_MODIFIER_CALLIGRAPHY:
+ break;
+ }
+ BLI_freelinkN(&linestyle->thickness_modifiers, m);
+}
+
+static LineStyleModifier *alloc_geometry_modifier(int type)
+{
+ size_t size;
+
+ switch (type) {
+ case LS_MODIFIER_SAMPLING:
+ size = sizeof(LineStyleGeometryModifier_Sampling);
+ break;
+ case LS_MODIFIER_BEZIER_CURVE:
+ size = sizeof(LineStyleGeometryModifier_BezierCurve);
+ break;
+ case LS_MODIFIER_SINUS_DISPLACEMENT:
+ size = sizeof(LineStyleGeometryModifier_SinusDisplacement);
+ break;
+ case LS_MODIFIER_SPATIAL_NOISE:
+ size = sizeof(LineStyleGeometryModifier_SpatialNoise);
+ break;
+ case LS_MODIFIER_PERLIN_NOISE_1D:
+ size = sizeof(LineStyleGeometryModifier_PerlinNoise1D);
+ break;
+ case LS_MODIFIER_PERLIN_NOISE_2D:
+ size = sizeof(LineStyleGeometryModifier_PerlinNoise2D);
+ break;
+ case LS_MODIFIER_BACKBONE_STRETCHER:
+ size = sizeof(LineStyleGeometryModifier_BackboneStretcher);
+ break;
+ case LS_MODIFIER_TIP_REMOVER:
+ size = sizeof(LineStyleGeometryModifier_TipRemover);
+ break;
+ case LS_MODIFIER_POLYGONIZATION:
+ size = sizeof(LineStyleGeometryModifier_Polygonalization);
+ break;
+ case LS_MODIFIER_GUIDING_LINES:
+ size = sizeof(LineStyleGeometryModifier_GuidingLines);
+ break;
+ case LS_MODIFIER_BLUEPRINT:
+ size = sizeof(LineStyleGeometryModifier_Blueprint);
+ break;
+ case LS_MODIFIER_2D_OFFSET:
+ size = sizeof(LineStyleGeometryModifier_2DOffset);
+ break;
+ case LS_MODIFIER_2D_TRANSFORM:
+ size = sizeof(LineStyleGeometryModifier_2DTransform);
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+
+ return new_modifier(type, size);
+}
+
+LineStyleModifier *BKE_add_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, int type)
+{
+ LineStyleModifier *m;
+
+ m = alloc_geometry_modifier(type);
+
+ switch (type) {
+ case LS_MODIFIER_SAMPLING:
+ {
+ LineStyleGeometryModifier_Sampling *p = (LineStyleGeometryModifier_Sampling *)m;
+ p->sampling = 10.0f;
+ }
+ break;
+ case LS_MODIFIER_BEZIER_CURVE:
+ {
+ LineStyleGeometryModifier_BezierCurve *p = (LineStyleGeometryModifier_BezierCurve *)m;
+ p->error = 10.0f;
+ }
+ break;
+ case LS_MODIFIER_SINUS_DISPLACEMENT:
+ {
+ LineStyleGeometryModifier_SinusDisplacement *p = (LineStyleGeometryModifier_SinusDisplacement *)m;
+ p->wavelength = 20.0f;
+ p->amplitude = 5.0f;
+ p->phase = 0.0f;
+ }
+ break;
+ case LS_MODIFIER_SPATIAL_NOISE:
+ {
+ LineStyleGeometryModifier_SpatialNoise *p = (LineStyleGeometryModifier_SpatialNoise *)m;
+ p->amplitude = 5.0f;
+ p->scale = 20.0f;
+ p->octaves = 4;
+ p->flags = LS_MODIFIER_SPATIAL_NOISE_SMOOTH | LS_MODIFIER_SPATIAL_NOISE_PURERANDOM;
+ }
+ break;
+ case LS_MODIFIER_PERLIN_NOISE_1D:
+ {
+ LineStyleGeometryModifier_PerlinNoise1D *p = (LineStyleGeometryModifier_PerlinNoise1D *)m;
+ p->frequency = 10.0f;
+ p->amplitude = 10.0f;
+ p->octaves = 4;
+ p->angle = DEG2RADF(45.0f);
+ }
+ break;
+ case LS_MODIFIER_PERLIN_NOISE_2D:
+ {
+ LineStyleGeometryModifier_PerlinNoise2D *p = (LineStyleGeometryModifier_PerlinNoise2D *)m;
+ p->frequency = 10.0f;
+ p->amplitude = 10.0f;
+ p->octaves = 4;
+ p->angle = DEG2RADF(45.0f);
+ }
+ break;
+ case LS_MODIFIER_BACKBONE_STRETCHER:
+ {
+ LineStyleGeometryModifier_BackboneStretcher *p = (LineStyleGeometryModifier_BackboneStretcher *)m;
+ p->backbone_length = 10.0f;
+ }
+ break;
+ case LS_MODIFIER_TIP_REMOVER:
+ {
+ LineStyleGeometryModifier_TipRemover *p = (LineStyleGeometryModifier_TipRemover *)m;
+ p->tip_length = 10.0f;
+ }
+ break;
+ case LS_MODIFIER_POLYGONIZATION:
+ {
+ LineStyleGeometryModifier_Polygonalization *p = (LineStyleGeometryModifier_Polygonalization *)m;
+ p->error = 10.0f;
+ }
+ break;
+ case LS_MODIFIER_GUIDING_LINES:
+ {
+ LineStyleGeometryModifier_GuidingLines *p = (LineStyleGeometryModifier_GuidingLines *)m;
+ p->offset = 0.0f;
+ }
+ break;
+ case LS_MODIFIER_BLUEPRINT:
+ {
+ LineStyleGeometryModifier_Blueprint *p = (LineStyleGeometryModifier_Blueprint *)m;
+ p->flags = LS_MODIFIER_BLUEPRINT_CIRCLES;
+ p->rounds = 1;
+ p->backbone_length = 10.0f;
+ p->random_radius = 3;
+ p->random_center = 5;
+ p->random_backbone = 5;
+ }
+ break;
+ case LS_MODIFIER_2D_OFFSET:
+ {
+ LineStyleGeometryModifier_2DOffset *p = (LineStyleGeometryModifier_2DOffset *)m;
+ p->start = 0.0f;
+ p->end = 0.0f;
+ p->x = 0.0f;
+ p->y = 0.0f;
+ }
+ break;
+ case LS_MODIFIER_2D_TRANSFORM:
+ {
+ LineStyleGeometryModifier_2DTransform *p = (LineStyleGeometryModifier_2DTransform *)m;
+ p->pivot = LS_MODIFIER_2D_TRANSFORM_PIVOT_CENTER;
+ p->scale_x = 1.0f;
+ p->scale_y = 1.0f;
+ p->angle = DEG2RADF(0.0f);
+ p->pivot_u = 0.5f;
+ p->pivot_x = 0.0f;
+ p->pivot_y = 0.0f;
+ }
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ add_to_modifier_list(&linestyle->geometry_modifiers, m);
+
+ return m;
+}
+
+LineStyleModifier *BKE_copy_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+{
+ LineStyleModifier *new_m;
+
+ new_m = alloc_geometry_modifier(m->type);
+ new_m->flags = m->flags;
+
+ switch (m->type) {
+ case LS_MODIFIER_SAMPLING:
+ {
+ LineStyleGeometryModifier_Sampling *p = (LineStyleGeometryModifier_Sampling *)m;
+ LineStyleGeometryModifier_Sampling *q = (LineStyleGeometryModifier_Sampling *)new_m;
+ q->sampling = p->sampling;
+ }
+ break;
+ case LS_MODIFIER_BEZIER_CURVE:
+ {
+ LineStyleGeometryModifier_BezierCurve *p = (LineStyleGeometryModifier_BezierCurve *)m;
+ LineStyleGeometryModifier_BezierCurve *q = (LineStyleGeometryModifier_BezierCurve *)new_m;
+ q->error = p->error;
+ }
+ break;
+ case LS_MODIFIER_SINUS_DISPLACEMENT:
+ {
+ LineStyleGeometryModifier_SinusDisplacement *p = (LineStyleGeometryModifier_SinusDisplacement *)m;
+ LineStyleGeometryModifier_SinusDisplacement *q = (LineStyleGeometryModifier_SinusDisplacement *)new_m;
+ q->wavelength = p->wavelength;
+ q->amplitude = p->amplitude;
+ q->phase = p->phase;
+ }
+ break;
+ case LS_MODIFIER_SPATIAL_NOISE:
+ {
+ LineStyleGeometryModifier_SpatialNoise *p = (LineStyleGeometryModifier_SpatialNoise *)m;
+ LineStyleGeometryModifier_SpatialNoise *q = (LineStyleGeometryModifier_SpatialNoise *)new_m;
+ q->amplitude = p->amplitude;
+ q->scale = p->scale;
+ q->octaves = p->octaves;
+ q->flags = p->flags;
+ }
+ break;
+ case LS_MODIFIER_PERLIN_NOISE_1D:
+ {
+ LineStyleGeometryModifier_PerlinNoise1D *p = (LineStyleGeometryModifier_PerlinNoise1D *)m;
+ LineStyleGeometryModifier_PerlinNoise1D *q = (LineStyleGeometryModifier_PerlinNoise1D *)new_m;
+ q->frequency = p->frequency;
+ q->amplitude = p->amplitude;
+ q->octaves = p->octaves;
+ q->angle = p->angle;
+ }
+ break;
+ case LS_MODIFIER_PERLIN_NOISE_2D:
+ {
+ LineStyleGeometryModifier_PerlinNoise2D *p = (LineStyleGeometryModifier_PerlinNoise2D *)m;
+ LineStyleGeometryModifier_PerlinNoise2D *q = (LineStyleGeometryModifier_PerlinNoise2D *)new_m;
+ q->frequency = p->frequency;
+ q->amplitude = p->amplitude;
+ q->octaves = p->octaves;
+ q->angle = p->angle;
+ }
+ break;
+ case LS_MODIFIER_BACKBONE_STRETCHER:
+ {
+ LineStyleGeometryModifier_BackboneStretcher *p = (LineStyleGeometryModifier_BackboneStretcher *)m;
+ LineStyleGeometryModifier_BackboneStretcher *q = (LineStyleGeometryModifier_BackboneStretcher *)new_m;
+ q->backbone_length = p->backbone_length;
+ }
+ break;
+ case LS_MODIFIER_TIP_REMOVER:
+ {
+ LineStyleGeometryModifier_TipRemover *p = (LineStyleGeometryModifier_TipRemover *)m;
+ LineStyleGeometryModifier_TipRemover *q = (LineStyleGeometryModifier_TipRemover *)new_m;
+ q->tip_length = p->tip_length;
+ }
+ break;
+ case LS_MODIFIER_POLYGONIZATION:
+ {
+ LineStyleGeometryModifier_Polygonalization *p = (LineStyleGeometryModifier_Polygonalization *)m;
+ LineStyleGeometryModifier_Polygonalization *q = (LineStyleGeometryModifier_Polygonalization *)new_m;
+ q->error = p->error;
+ }
+ break;
+ case LS_MODIFIER_GUIDING_LINES:
+ {
+ LineStyleGeometryModifier_GuidingLines *p = (LineStyleGeometryModifier_GuidingLines *)m;
+ LineStyleGeometryModifier_GuidingLines *q = (LineStyleGeometryModifier_GuidingLines *)new_m;
+ q->offset = p->offset;
+ }
+ break;
+ case LS_MODIFIER_BLUEPRINT:
+ {
+ LineStyleGeometryModifier_Blueprint *p = (LineStyleGeometryModifier_Blueprint *)m;
+ LineStyleGeometryModifier_Blueprint *q = (LineStyleGeometryModifier_Blueprint *)new_m;
+ q->flags = p->flags;
+ q->rounds = p->rounds;
+ q->backbone_length = p->backbone_length;
+ q->random_radius = p->random_radius;
+ q->random_center = p->random_center;
+ q->random_backbone = p->random_backbone;
+ }
+ break;
+ case LS_MODIFIER_2D_OFFSET:
+ {
+ LineStyleGeometryModifier_2DOffset *p = (LineStyleGeometryModifier_2DOffset *)m;
+ LineStyleGeometryModifier_2DOffset *q = (LineStyleGeometryModifier_2DOffset *)new_m;
+ q->start = p->start;
+ q->end = p->end;
+ q->x = p->x;
+ q->y = p->y;
+ }
+ break;
+ case LS_MODIFIER_2D_TRANSFORM:
+ {
+ LineStyleGeometryModifier_2DTransform *p = (LineStyleGeometryModifier_2DTransform *)m;
+ LineStyleGeometryModifier_2DTransform *q = (LineStyleGeometryModifier_2DTransform *)new_m;
+ q->pivot = p->pivot;
+ q->scale_x = p->scale_x;
+ q->scale_y = p->scale_y;
+ q->angle = p->angle;
+ q->pivot_u = p->pivot_u;
+ q->pivot_x = p->pivot_x;
+ q->pivot_y = p->pivot_y;
+ }
+ break;
+ default:
+ return NULL; /* unknown modifier type */
+ }
+ add_to_modifier_list(&linestyle->geometry_modifiers, new_m);
+
+ return new_m;
+}
+
+void BKE_remove_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *m)
+{
+ BLI_freelinkN(&linestyle->geometry_modifiers, m);
+}
+
+static void move_modifier(ListBase *lb, LineStyleModifier *modifier, int direction)
+{
+ BLI_remlink(lb, modifier);
+ if (direction > 0)
+ BLI_insertlinkbefore(lb, modifier->prev, modifier);
+ else
+ BLI_insertlinkafter(lb, modifier->next, modifier);
+}
+
+void BKE_move_linestyle_color_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
+{
+ move_modifier(&linestyle->color_modifiers, modifier, direction);
+}
+
+void BKE_move_linestyle_alpha_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
+{
+ move_modifier(&linestyle->alpha_modifiers, modifier, direction);
+}
+
+void BKE_move_linestyle_thickness_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
+{
+ move_modifier(&linestyle->thickness_modifiers, modifier, direction);
+}
+
+void BKE_move_linestyle_geometry_modifier(FreestyleLineStyle *linestyle, LineStyleModifier *modifier, int direction)
+{
+ move_modifier(&linestyle->geometry_modifiers, modifier, direction);
+}
+
+void BKE_list_modifier_color_ramps(FreestyleLineStyle *linestyle, ListBase *listbase)
+{
+ LineStyleModifier *m;
+ ColorBand *color_ramp;
+ LinkData *link;
+
+ listbase->first = listbase->last = NULL;
+ for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ color_ramp = ((LineStyleColorModifier_AlongStroke *)m)->color_ramp;
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ color_ramp = ((LineStyleColorModifier_DistanceFromCamera *)m)->color_ramp;
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ color_ramp = ((LineStyleColorModifier_DistanceFromObject *)m)->color_ramp;
+ break;
+ case LS_MODIFIER_MATERIAL:
+ color_ramp = ((LineStyleColorModifier_Material *)m)->color_ramp;
+ break;
+ default:
+ continue;
+ }
+ link = (LinkData *) MEM_callocN( sizeof(LinkData), "link to color ramp");
+ link->data = color_ramp;
+ BLI_addtail(listbase, link);
+ }
+}
+
+char *BKE_path_from_ID_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand *color_ramp)
+{
+ LineStyleModifier *m;
+ bool found = false;
+
+ for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ if (color_ramp == ((LineStyleColorModifier_AlongStroke *)m)->color_ramp)
+ found = true;
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ if (color_ramp == ((LineStyleColorModifier_DistanceFromCamera *)m)->color_ramp)
+ found = true;
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ if (color_ramp == ((LineStyleColorModifier_DistanceFromObject *)m)->color_ramp)
+ found = true;
+ break;
+ case LS_MODIFIER_MATERIAL:
+ if (color_ramp == ((LineStyleColorModifier_Material *)m)->color_ramp)
+ found = true;
+ break;
+ }
+ if (found)
+ return BLI_sprintfN("color_modifiers[\"%s\"].color_ramp", m->name);
+ }
+ printf("BKE_path_from_ID_to_color_ramp: No color ramps correspond to the given pointer.\n");
+ return NULL;
+}
+
+void BKE_unlink_linestyle_target_object(FreestyleLineStyle *linestyle, struct Object *ob)
+{
+ LineStyleModifier *m;
+
+ for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next) {
+ if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
+ if (((LineStyleColorModifier_DistanceFromObject *)m)->target == ob) {
+ ((LineStyleColorModifier_DistanceFromObject *)m)->target = NULL;
+ }
+ }
+ }
+ for (m = (LineStyleModifier *)linestyle->alpha_modifiers.first; m; m = m->next) {
+ if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
+ if (((LineStyleAlphaModifier_DistanceFromObject *)m)->target == ob) {
+ ((LineStyleAlphaModifier_DistanceFromObject *)m)->target = NULL;
+ }
+ }
+ }
+ for (m = (LineStyleModifier *)linestyle->thickness_modifiers.first; m; m = m->next) {
+ if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
+ if (((LineStyleThicknessModifier_DistanceFromObject *)m)->target == ob) {
+ ((LineStyleThicknessModifier_DistanceFromObject *)m)->target = NULL;
+ }
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index bda924060d5..a5241684e3a 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -57,6 +57,8 @@
#include "BKE_movieclip.h"
#include "BKE_image.h"
+#include "NOD_composite.h"
+
static MaskSplinePoint *mask_spline_point_next(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point)
{
if (point == &points_array[spline->tot_point - 1]) {
@@ -698,18 +700,18 @@ void BKE_mask_point_select_set_handle(MaskSplinePoint *point, const short do_sel
}
/* only mask block itself */
-static Mask *mask_alloc(const char *name)
+static Mask *mask_alloc(Main *bmain, const char *name)
{
Mask *mask;
- mask = BKE_libblock_alloc(&G.main->mask, ID_MSK, name);
+ mask = BKE_libblock_alloc(&bmain->mask, ID_MSK, name);
mask->id.flag |= LIB_FAKEUSER;
return mask;
}
-Mask *BKE_mask_new(const char *name)
+Mask *BKE_mask_new(Main *bmain, const char *name)
{
Mask *mask;
char mask_name[MAX_ID_NAME - 2];
@@ -719,7 +721,7 @@ Mask *BKE_mask_new(const char *name)
else
strcpy(mask_name, "Mask");
- mask = mask_alloc(mask_name);
+ mask = mask_alloc(bmain, mask_name);
/* arbitrary defaults */
mask->sfra = 1;
@@ -923,6 +925,8 @@ void BKE_mask_free(Main *bmain, Mask *mask)
SpaceLink *sl;
Scene *scene;
+ BKE_sequencer_clear_mask_in_clipboard(mask);
+
for (scr = bmain->screen.first; scr; scr = scr->id.next) {
for (area = scr->areabase.first; area; area = area->next) {
for (sl = area->spacedata.first; sl; sl = sl->next) {
@@ -964,10 +968,9 @@ void BKE_mask_free(Main *bmain, Mask *mask)
}
}
- {
- bNodeTreeType *treetype = ntreeGetType(NTREE_COMPOSIT);
- treetype->foreach_nodetree(bmain, (void *)mask, &BKE_node_tree_unlink_id_cb);
- }
+ FOREACH_NODETREE(bmain, ntree, id) {
+ BKE_node_tree_unlink_id((ID *)mask, ntree);
+ } FOREACH_NODETREE_END
/* free mask data */
BKE_mask_layer_free_list(&mask->masklayers);
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index 2fa928e7c07..e3423c93f3c 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -213,7 +213,7 @@ MaskRasterHandle *BKE_maskrasterize_handle_new(void)
{
MaskRasterHandle *mr_handle;
- mr_handle = MEM_callocN(sizeof(MaskRasterHandle), STRINGIFY(MaskRasterHandle));
+ mr_handle = MEM_callocN(sizeof(MaskRasterHandle), "MaskRasterHandle");
return mr_handle;
}
@@ -569,7 +569,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
unsigned int masklay_index;
mr_handle->layers_tot = BLI_countlist(&mask->masklayers);
- mr_handle->layers = MEM_mallocN(sizeof(MaskRasterLayer) * mr_handle->layers_tot, STRINGIFY(MaskRasterLayer));
+ mr_handle->layers = MEM_mallocN(sizeof(MaskRasterLayer) * mr_handle->layers_tot, "MaskRasterLayer");
BLI_rctf_init_minmax(&mr_handle->bounds);
for (masklay = mask->masklayers.first, masklay_index = 0; masklay; masklay = masklay->next, masklay_index++) {
@@ -933,7 +933,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
}
/* main scan-fill */
- sf_tri_tot = BLI_scanfill_calc_ex(&sf_ctx, 0, zvec);
+ sf_tri_tot = BLI_scanfill_calc_ex(&sf_ctx, BLI_SCANFILL_CALC_HOLES, zvec);
face_array = MEM_mallocN(sizeof(*face_array) * (sf_tri_tot + tot_feather_quads), "maskrast_face_index");
face_index = 0;
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index ea317956255..a4f147a4fac 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -52,7 +52,6 @@
#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
-#include "BLI_bpath.h"
#include "BLI_string.h"
#include "BKE_animsys.h"
@@ -154,6 +153,7 @@ void init_material(Material *ma)
ma->tx_limit = 0.0;
ma->tx_falloff = 1.0;
ma->shad_alpha = 1.0f;
+ ma->vcol_alpha = 0;
ma->gloss_mir = ma->gloss_tra = 1.0;
ma->samp_gloss_mir = ma->samp_gloss_tra = 18;
@@ -207,11 +207,11 @@ void init_material(Material *ma)
ma->preview = NULL;
}
-Material *BKE_material_add(const char *name)
+Material *BKE_material_add(Main *bmain, const char *name)
{
Material *ma;
- ma = BKE_libblock_alloc(&G.main->mat, ID_MA, name);
+ ma = BKE_libblock_alloc(&bmain->mat, ID_MA, name);
init_material(ma);
@@ -629,11 +629,14 @@ Material *give_current_material(Object *ob, short act)
if (totcolp == NULL || ob->totcol == 0) return NULL;
if (act < 0) {
- printf("no!\n");
+ printf("Negative material index!\n");
}
- if (act > ob->totcol) act = ob->totcol;
- else if (act <= 0) act = 1;
+ /* return NULL for invalid 'act', can happen for mesh face indices */
+ if (act > ob->totcol)
+ return NULL;
+ else if (act <= 0)
+ return NULL;
if (ob->matbits && ob->matbits[act - 1]) { /* in object */
ma = ob->mat[act - 1];
@@ -679,19 +682,6 @@ Material *give_node_material(Material *ma)
return NULL;
}
-/* GS reads the memory pointed at in a specific ordering. There are,
- * however two definitions for it. I have jotted them down here, both,
- * but I think the first one is actually used. The thing is that
- * big-endian systems might read this the wrong way round. OTOH, we
- * constructed the IDs that are read out with this macro explicitly as
- * well. I expect we'll sort it out soon... */
-
-/* from blendef: */
-#define GS(a) (*((short *)(a)))
-
-/* from misc_util: flip the bytes from x */
-/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
-
void resize_object_material(Object *ob, const short totcol)
{
Material **newmatar;
@@ -1023,7 +1013,7 @@ void init_render_material(Material *mat, int r_mode, float *amb)
init_render_nodetree(mat->nodetree, mat, r_mode, amb);
if (!mat->nodetree->execdata)
- mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree, 1);
+ mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree);
}
}
@@ -1057,7 +1047,7 @@ void end_render_material(Material *mat)
{
if (mat && mat->nodetree && mat->use_nodes) {
if (mat->nodetree->execdata)
- ntreeShaderEndExecTree(mat->nodetree->execdata, 1);
+ ntreeShaderEndExecTree(mat->nodetree->execdata);
}
}
@@ -1235,6 +1225,11 @@ int object_remove_material_slot(Object *ob)
if (*matarar == NULL) return FALSE;
+ /* can happen on face selection in editmode */
+ if (ob->actcol > ob->totcol) {
+ ob->actcol = ob->totcol;
+ }
+
/* we delete the actcol */
mao = (*matarar)[ob->actcol - 1];
if (mao) mao->id.us--;
@@ -1784,7 +1779,7 @@ static short convert_tfacenomaterial(Main *main, Mesh *me, MTFace *tf, int flag)
}
/* create a new material */
else {
- ma = BKE_material_add(idname + 2);
+ ma = BKE_material_add(main, idname + 2);
if (ma) {
printf("TexFace Convert: Material \"%s\" created.\n", idname + 2);
@@ -1800,7 +1795,9 @@ static short convert_tfacenomaterial(Main *main, Mesh *me, MTFace *tf, int flag)
ma->game.flag = -flag;
id_us_min((ID *)ma);
}
- else printf("Error: Unable to create Material \"%s\" for Mesh \"%s\".", idname + 2, me->id.name + 2);
+ else {
+ printf("Error: Unable to create Material \"%s\" for Mesh \"%s\".", idname + 2, me->id.name + 2);
+ }
}
/* set as converted, no need to go bad to this face */
@@ -1856,7 +1853,7 @@ static void convert_tfacematerial(Main *main, Material *ma)
mat_new = BKE_material_copy(ma);
if (mat_new) {
/* rename the material*/
- strcpy(mat_new->id.name, idname);
+ BLI_strncpy(mat_new->id.name, idname, sizeof(mat_new->id.name));
id_us_min((ID *)mat_new);
mat_nr = mesh_addmaterial(me, mat_new);
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 805e77cf84f..72284130869 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -50,8 +50,6 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLI_bpath.h"
-
#include "BKE_global.h"
#include "BKE_main.h"
@@ -198,11 +196,11 @@ void BKE_mball_free(MetaBall *mb)
if (mb->disp.first) BKE_displist_free(&mb->disp);
}
-MetaBall *BKE_mball_add(const char *name)
+MetaBall *BKE_mball_add(Main *bmain, const char *name)
{
MetaBall *mb;
- mb = BKE_libblock_alloc(&G.main->mball, ID_MB, name);
+ mb = BKE_libblock_alloc(&bmain->mball, ID_MB, name);
mb->size[0] = mb->size[1] = mb->size[2] = 1.0;
mb->texflag = MB_AUTOSPACE;
@@ -441,18 +439,15 @@ float *BKE_mball_make_orco(Object *ob, ListBase *dispbase)
* It test last character of Object ID name. If last character
* is digit it return 0, else it return 1.
*/
-int BKE_mball_is_basis(Object *ob)
+bool BKE_mball_is_basis(Object *ob)
{
- int len;
-
/* just a quick test */
- len = strlen(ob->id.name);
- if (isdigit(ob->id.name[len - 1]) ) return 0;
- return 1;
+ const int len = strlen(ob->id.name);
+ return (!isdigit(ob->id.name[len - 1]));
}
/* return nonzero if ob1 is a basis mball for ob */
-int BKE_mball_is_basis_for(Object *ob1, Object *ob2)
+bool BKE_mball_is_basis_for(Object *ob1, Object *ob2)
{
int basis1nr, basis2nr;
char basis1name[MAX_ID_NAME], basis2name[MAX_ID_NAME];
@@ -460,8 +455,12 @@ int 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)) return BKE_mball_is_basis(ob1);
- else return 0;
+ if (!strcmp(basis1name, basis2name)) {
+ return BKE_mball_is_basis(ob1);
+ }
+ else {
+ return false;
+ }
}
/* \brief copy some properties from object to other metaball object with same base name
@@ -1502,7 +1501,7 @@ static void add_cube(PROCESS *mbproc, int i, int j, int k, int count)
static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a)
{
MetaElem *ml;
- float f = 0.0f;
+ float f;
ml = G_mb.mainb[a];
f = 1.0f - (mb->thresh / ml->s);
@@ -1516,7 +1515,7 @@ static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a)
float in_v /*, out_v*/;
float workp[3];
float dvec[3];
- float tmp_v, workp_v, max_len, len, nx, ny, nz, MAXN;
+ float tmp_v, workp_v, max_len, nx, ny, nz, max_dim;
calc_mballco(ml, in);
in_v = mbproc->function(in[0], in[1], in[2]);
@@ -1575,17 +1574,17 @@ static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a)
ny = abs((out[1] - in[1]) / mbproc->size);
nz = abs((out[2] - in[2]) / mbproc->size);
- MAXN = MAX3(nx, ny, nz);
- if (MAXN != 0.0f) {
- dvec[0] = (out[0] - in[0]) / MAXN;
- dvec[1] = (out[1] - in[1]) / MAXN;
- dvec[2] = (out[2] - in[2]) / MAXN;
+ max_dim = max_fff(nx, ny, nz);
+ if (max_dim != 0.0f) {
+ float len = 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;
- len = 0.0;
while (len <= max_len) {
- workp[0] += dvec[0];
- workp[1] += dvec[1];
- workp[2] += dvec[2];
+ add_v3_v3(workp, dvec);
+
/* compute value of implicite function */
tmp_v = mbproc->function(workp[0], workp[1], workp[2]);
/* add cube to the stack, when value of implicite function crosses zero value */
@@ -1656,6 +1655,14 @@ static void polygonize(PROCESS *mbproc, MetaBall *mb)
}
}
+/* could move to math api */
+BLI_INLINE void copy_v3_fl3(float v[3], float x, float y, float z)
+{
+ v[0] = x;
+ v[1] = y;
+ v[2] = z;
+}
+
static float init_meta(Scene *scene, Object *ob) /* return totsize */
{
Scene *sce_iter = scene;
@@ -1732,6 +1739,7 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */
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;
@@ -1772,39 +1780,27 @@ static float init_meta(Scene *scene, Object *ob) /* return totsize */
G_mb.mainb[a]->mat = (float *) mat;
G_mb.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 */
- /* 0 */
- G_mb.mainb[a]->bb->vec[0][0] = -ml->expx;
- G_mb.mainb[a]->bb->vec[0][1] = -ml->expy;
- G_mb.mainb[a]->bb->vec[0][2] = -ml->expz;
- /* 1 */
- G_mb.mainb[a]->bb->vec[1][0] = ml->expx;
- G_mb.mainb[a]->bb->vec[1][1] = -ml->expy;
- G_mb.mainb[a]->bb->vec[1][2] = -ml->expz;
- /* 2 */
- G_mb.mainb[a]->bb->vec[2][0] = ml->expx;
- G_mb.mainb[a]->bb->vec[2][1] = ml->expy;
- G_mb.mainb[a]->bb->vec[2][2] = -ml->expz;
- /* 3 */
- G_mb.mainb[a]->bb->vec[3][0] = -ml->expx;
- G_mb.mainb[a]->bb->vec[3][1] = ml->expy;
- G_mb.mainb[a]->bb->vec[3][2] = -ml->expz;
- /* 4 */
- G_mb.mainb[a]->bb->vec[4][0] = -ml->expx;
- G_mb.mainb[a]->bb->vec[4][1] = -ml->expy;
- G_mb.mainb[a]->bb->vec[4][2] = ml->expz;
- /* 5 */
- G_mb.mainb[a]->bb->vec[5][0] = ml->expx;
- G_mb.mainb[a]->bb->vec[5][1] = -ml->expy;
- G_mb.mainb[a]->bb->vec[5][2] = ml->expz;
- /* 6 */
- G_mb.mainb[a]->bb->vec[6][0] = ml->expx;
- G_mb.mainb[a]->bb->vec[6][1] = ml->expy;
- G_mb.mainb[a]->bb->vec[6][2] = ml->expz;
- /* 7 */
- G_mb.mainb[a]->bb->vec[7][0] = -ml->expx;
- G_mb.mainb[a]->bb->vec[7][1] = ml->expy;
- G_mb.mainb[a]->bb->vec[7][2] = ml->expz;
+ /* TODO, its possible the elem type has been changed and the exp* values can use a fallback */
+ copy_v3_fl3(G_mb.mainb[a]->bb->vec[0], -expx, -expy, -expz); /* 0 */
+ copy_v3_fl3(G_mb.mainb[a]->bb->vec[1], +expx, -expy, -expz); /* 1 */
+ copy_v3_fl3(G_mb.mainb[a]->bb->vec[2], +expx, +expy, -expz); /* 2 */
+ copy_v3_fl3(G_mb.mainb[a]->bb->vec[3], -expx, +expy, -expz); /* 3 */
+ copy_v3_fl3(G_mb.mainb[a]->bb->vec[4], -expx, -expy, +expz); /* 4 */
+ copy_v3_fl3(G_mb.mainb[a]->bb->vec[5], +expx, -expy, +expz); /* 5 */
+ copy_v3_fl3(G_mb.mainb[a]->bb->vec[6], +expx, +expy, +expz); /* 6 */
+ copy_v3_fl3(G_mb.mainb[a]->bb->vec[7], -expx, +expy, +expz); /* 7 */
/* transformation of Metalem bb */
for (i = 0; i < 8; i++)
@@ -2298,7 +2294,9 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
}
/* width is size per polygonize cube */
- if (G.is_rendering) width = mb->rendersize;
+ if (G.is_rendering) {
+ width = mb->rendersize;
+ }
else {
width = mb->wiresize;
if (G.moving && mb->flag == MB_UPDATE_HALFRES) width *= 2;
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 75504416067..b36f484f4ee 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -46,7 +46,6 @@
#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
-#include "BLI_bpath.h"
#include "BLI_math.h"
#include "BLI_edgehash.h"
#include "BLI_scanfill.h"
@@ -349,7 +348,7 @@ static void mesh_ensure_tessellation_customdata(Mesh *me)
* note that for undo mesh data we want to skip 'ensure_tess_cd' call since
* we don't want to store memory for tessface when its only used for older
* versions of the mesh. - campbell*/
-static void mesh_update_linked_customdata(Mesh *me, const short do_ensure_tess_cd)
+static void mesh_update_linked_customdata(Mesh *me, const bool do_ensure_tess_cd)
{
if (me->edit_btmesh)
BMEdit_UpdateLinkedCustomData(me->edit_btmesh);
@@ -361,7 +360,7 @@ static void mesh_update_linked_customdata(Mesh *me, const short do_ensure_tess_c
CustomData_bmesh_update_active_layers(&me->fdata, &me->pdata, &me->ldata);
}
-void mesh_update_customdata_pointers(Mesh *me, const short do_ensure_tess_cd)
+void BKE_mesh_update_customdata_pointers(Mesh *me, const bool do_ensure_tess_cd)
{
mesh_update_linked_customdata(me, do_ensure_tess_cd);
@@ -431,42 +430,6 @@ void BKE_mesh_free(Mesh *me, int unlink)
if (me->edit_btmesh) MEM_freeN(me->edit_btmesh);
}
-void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount)
-{
- /* Assumes dst is already set up */
- int i;
-
- if (!src || !dst)
- return;
-
- memcpy(dst, src, copycount * sizeof(MDeformVert));
-
- for (i = 0; i < copycount; i++) {
- if (src[i].dw) {
- dst[i].dw = MEM_callocN(sizeof(MDeformWeight) * src[i].totweight, "copy_deformWeight");
- memcpy(dst[i].dw, src[i].dw, sizeof(MDeformWeight) * src[i].totweight);
- }
- }
-
-}
-
-void free_dverts(MDeformVert *dvert, int totvert)
-{
- /* Instead of freeing the verts directly,
- * call this function to delete any special
- * vert data */
- int i;
-
- if (!dvert)
- return;
-
- /* Free any special data from the verts */
- for (i = 0; i < totvert; i++) {
- if (dvert[i].dw) MEM_freeN(dvert[i].dw);
- }
- MEM_freeN(dvert);
-}
-
static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata)
{
if (free_customdata) {
@@ -482,11 +445,11 @@ static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata)
mesh->totface = 0;
}
-Mesh *BKE_mesh_add(const char *name)
+Mesh *BKE_mesh_add(Main *bmain, const char *name)
{
Mesh *me;
- me = BKE_libblock_alloc(&G.main->mesh, ID_ME, name);
+ me = BKE_libblock_alloc(&bmain->mesh, ID_ME, name);
me->size[0] = me->size[1] = me->size[2] = 1.0;
me->smoothresh = 30;
@@ -503,7 +466,7 @@ Mesh *BKE_mesh_add(const char *name)
return me;
}
-Mesh *BKE_mesh_copy(Mesh *me)
+Mesh *BKE_mesh_copy_ex(Main *bmain, Mesh *me)
{
Mesh *men;
MTFace *tface;
@@ -511,7 +474,7 @@ Mesh *BKE_mesh_copy(Mesh *me)
int a, i;
const int do_tessface = ((me->totface != 0) && (me->totpoly == 0)); /* only do tessface if we have no polys */
- men = BKE_libblock_copy(&me->id);
+ men = BKE_libblock_copy_ex(bmain, &me->id);
men->mat = MEM_dupallocN(me->mat);
for (a = 0; a < men->totcol; a++) {
@@ -530,7 +493,7 @@ Mesh *BKE_mesh_copy(Mesh *me)
mesh_tessface_clear_intern(men, FALSE);
}
- mesh_update_customdata_pointers(men, do_tessface);
+ BKE_mesh_update_customdata_pointers(men, do_tessface);
/* ensure indirect linked data becomes lib-extern */
for (i = 0; i < me->fdata.totlayer; i++) {
@@ -564,13 +527,18 @@ Mesh *BKE_mesh_copy(Mesh *me)
return men;
}
+Mesh *BKE_mesh_copy(Mesh *me)
+{
+ return BKE_mesh_copy_ex(G.main, me);
+}
+
BMesh *BKE_mesh_to_bmesh(Mesh *me, Object *ob)
{
BMesh *bm;
bm = BM_mesh_create(&bm_mesh_allocsize_default);
- BM_mesh_bm_from_me(bm, me, TRUE, ob->shapenr);
+ BM_mesh_bm_from_me(bm, me, true, ob->shapenr);
return bm;
}
@@ -654,7 +622,7 @@ void BKE_mesh_make_local(Mesh *me)
for (ob = bmain->object.first; ob; ob = ob->id.next) {
if (me == ob->data) {
if (ob->id.lib == NULL) {
- set_mesh(ob, me_new);
+ BKE_mesh_assign_object(ob, me_new);
}
}
}
@@ -732,7 +700,7 @@ void BKE_mesh_texspace_get(Mesh *me, float r_loc[3], float r_rot[3], float r_siz
if (r_size) copy_v3_v3(r_size, me->size);
}
-float *BKE_mesh_orco_verts_get(Object *ob)
+float (*BKE_mesh_orco_verts_get(Object *ob))[3]
{
Mesh *me = ob->data;
MVert *mvert = NULL;
@@ -749,7 +717,7 @@ float *BKE_mesh_orco_verts_get(Object *ob)
copy_v3_v3(vcos[a], mvert->co);
}
- return (float *)vcos;
+ return vcos;
}
void BKE_mesh_orco_verts_transform(Mesh *me, float (*orco)[3], int totvert, int invert)
@@ -857,7 +825,7 @@ Mesh *BKE_mesh_from_object(Object *ob)
else return NULL;
}
-void set_mesh(Object *ob, Mesh *me)
+void BKE_mesh_assign_object(Object *ob, Mesh *me)
{
Mesh *old = NULL;
@@ -919,12 +887,11 @@ static void make_edges_mdata(MVert *UNUSED(allvert), MFace *allface, MLoop *alll
int old, MEdge **alledge, int *_totedge)
{
MPoly *mpoly;
- MLoop *mloop;
MFace *mface;
MEdge *medge;
EdgeHash *hash = BLI_edgehash_new();
struct edgesort *edsort, *ed;
- int a, b, totedge = 0, final = 0;
+ int a, totedge = 0, final = 0;
/* we put all edges in array, sort them, and detect doubles that way */
@@ -1005,13 +972,16 @@ static void make_edges_mdata(MVert *UNUSED(allvert), MFace *allface, MLoop *alll
mpoly = allpoly;
for (a = 0; a < totpoly; a++, mpoly++) {
- mloop = allloop + mpoly->loopstart;
- for (b = 0; b < mpoly->totloop; b++) {
- int v1, v2;
-
- v1 = mloop[b].v;
- v2 = ME_POLY_LOOP_NEXT(mloop, mpoly, b)->v;
- mloop[b].e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(hash, v1, v2));
+ MLoop *ml, *ml_next;
+ int i = mpoly->totloop;
+
+ ml_next = allloop + mpoly->loopstart; /* first loop */
+ ml = &ml_next[i - 1]; /* last loop */
+
+ while (i-- != 0) {
+ ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(hash, ml->v, ml_next->v));
+ ml = ml_next;
+ ml_next++;
}
}
@@ -1224,11 +1194,11 @@ void BKE_mesh_from_metaball(ListBase *lb, Mesh *me)
index += 4;
}
- mesh_update_customdata_pointers(me, TRUE);
+ BKE_mesh_update_customdata_pointers(me, true);
BKE_mesh_calc_normals(me->mvert, me->totvert, me->mloop, me->mpoly, me->totloop, me->totpoly, NULL);
- BKE_mesh_calc_edges(me, TRUE);
+ BKE_mesh_calc_edges(me, true, false);
}
}
@@ -1241,8 +1211,8 @@ int BKE_mesh_nurbs_to_mdata(Object *ob, MVert **allvert, int *totvert,
return BKE_mesh_nurbs_displist_to_mdata(ob, &ob->disp,
allvert, totvert,
alledge, totedge,
- allloop, allpoly,
- totloop, totpoly, NULL);
+ allloop, allpoly, NULL,
+ totloop, totpoly);
}
/* BMESH: this doesn't calculate all edges from polygons,
@@ -1250,25 +1220,24 @@ 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 */
-/* TODO: orco values for non DL_SURF types */
int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
MVert **allvert, int *_totvert,
MEdge **alledge, int *_totedge,
MLoop **allloop, MPoly **allpoly,
- int *_totloop, int *_totpoly,
- int **orco_index_ptr)
+ MLoopUV **alluv,
+ int *_totloop, int *_totpoly)
{
DispList *dl;
Curve *cu;
MVert *mvert;
MPoly *mpoly;
MLoop *mloop;
+ MLoopUV *mloopuv = NULL;
MEdge *medge;
float *data;
int a, b, ofs, vertcount, startvert, totvert = 0, totedge = 0, totloop = 0, totvlak = 0;
int p1, p2, p3, p4, *index;
int conv_polys = 0;
- int (*orco_index)[4] = NULL;
cu = ob->data;
@@ -1315,15 +1284,13 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
*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");
+
+ if (alluv)
+ *alluv = mloopuv = MEM_callocN(sizeof(MLoopUV) * totvlak * 4, "nurbs_init mloopuv");
/* verts and faces */
vertcount = 0;
- if (orco_index_ptr) {
- *orco_index_ptr = MEM_callocN(sizeof(int) * totvlak * 4, "nurbs_init orco");
- orco_index = (int (*)[4]) *orco_index_ptr;
- }
-
dl = dispbase->first;
while (dl) {
int smooth = dl->rt & CU_SMOOTH ? 1 : 0;
@@ -1396,6 +1363,15 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
mpoly->totloop = 3;
mpoly->mat_nr = dl->col;
+ if (mloopuv) {
+ int i;
+
+ for (i = 0; i < 3; i++, mloopuv++) {
+ mloopuv->uv[0] = (mloop[i].v - startvert) / (float)(dl->nr - 1);
+ mloopuv->uv[1] = 0.0f;
+ }
+ }
+
if (smooth) mpoly->flag |= ME_SMOOTH;
mpoly++;
mloop += 3;
@@ -1445,13 +1421,29 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
mpoly->totloop = 4;
mpoly->mat_nr = dl->col;
- if (orco_index) {
- const int poly_index = mpoly - *allpoly;
- const int p_orco_base = startvert + ((dl->nr + 1) * a) + b;
- orco_index[poly_index][0] = p_orco_base + 1;
- orco_index[poly_index][1] = p_orco_base + dl->nr + 2;
- orco_index[poly_index][2] = p_orco_base + dl->nr + 1;
- orco_index[poly_index][3] = p_orco_base;
+ if (mloopuv) {
+ int orco_sizeu = dl->nr - 1;
+ int orco_sizev = dl->parts - 1;
+ int i;
+
+ /* exception as handled in convertblender.c too */
+ if (dl->flag & DL_CYCL_U) {
+ orco_sizeu++;
+ if (dl->flag & DL_CYCL_V)
+ orco_sizev++;
+ }
+
+ for (i = 0; i < 4; i++, mloopuv++) {
+ /* find uv based on vertex index into grid array */
+ int v = mloop[i].v - startvert;
+
+ mloopuv->uv[0] = (v / dl->nr) / (float)orco_sizev;
+ mloopuv->uv[1] = (v % dl->nr) / (float)orco_sizeu;
+
+ /* cyclic correction */
+ if ((i == 0 || i == 1) && mloopuv->uv[1] == 0.0f)
+ mloopuv->uv[1] = 1.0f;
+ }
}
if (smooth) mpoly->flag |= ME_SMOOTH;
@@ -1464,7 +1456,6 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
p1++;
}
}
-
}
dl = dl->next;
@@ -1485,33 +1476,8 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
}
-MINLINE void copy_uv_orco_v2_v2(float r[2], const float a[2])
-{
- r[0] = 0.5f + a[0] * 0.5f;
- r[1] = 0.5f + a[1] * 0.5f;
-}
-
-/**
- * orco is normally from #BKE_curve_make_orco
- */
-void BKE_mesh_nurbs_to_mdata_orco(MPoly *mpoly, int totpoly,
- MLoop *mloops, MLoopUV *mloopuvs,
- float (*orco)[3], int (*orco_index)[4])
-{
- MPoly *mp;
-
- int i, j;
- for (i = 0, mp = mpoly; i < totpoly; i++, mp++) {
- MLoop *ml = mloops + mp->loopstart;
- MLoopUV *mluv = mloopuvs + mp->loopstart;
- for (j = 0; j < mp->totloop; j++, ml++, mluv++) {
- copy_uv_orco_v2_v2(mluv->uv, orco[orco_index[i][j]]);
- }
- }
-}
-
/* this may fail replacing ob->data, be sure to check ob->type */
-void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, int **orco_index_ptr)
+void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use_orco_uv)
{
Main *bmain = G.main;
Object *ob1;
@@ -1521,6 +1487,7 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, int **orco_ind
MVert *allvert = NULL;
MEdge *alledge = NULL;
MLoop *allloop = NULL;
+ MLoopUV *alluv = NULL;
MPoly *allpoly = NULL;
int totvert, totedge, totloop, totpoly;
@@ -1529,14 +1496,15 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, int **orco_ind
if (dm == NULL) {
if (BKE_mesh_nurbs_displist_to_mdata(ob, dispbase, &allvert, &totvert,
&alledge, &totedge, &allloop,
- &allpoly, &totloop, &totpoly, orco_index_ptr) != 0)
+ &allpoly, (use_orco_uv) ? &alluv : NULL,
+ &totloop, &totpoly) != 0)
{
/* Error initializing */
return;
}
/* make mesh */
- me = BKE_mesh_add("Mesh");
+ me = BKE_mesh_add(G.main, "Mesh");
me->totvert = totvert;
me->totedge = totedge;
me->totloop = totloop;
@@ -1547,12 +1515,18 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, int **orco_ind
me->mloop = CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, allloop, me->totloop);
me->mpoly = CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, allpoly, me->totpoly);
+ if (alluv) {
+ const char *uvname = "Orco";
+ me->mtpoly = CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, uvname);
+ me->mloopuv = CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_ASSIGN, alluv, me->totloop, uvname);
+ }
+
BKE_mesh_calc_normals(me->mvert, me->totvert, me->mloop, me->mpoly, me->totloop, me->totpoly, NULL);
- BKE_mesh_calc_edges(me, TRUE);
+ BKE_mesh_calc_edges(me, true, false);
}
else {
- me = BKE_mesh_add("Mesh");
+ me = BKE_mesh_add(G.main, "Mesh");
DM_to_mesh(dm, me, ob);
}
@@ -1585,7 +1559,7 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, int **orco_ind
void BKE_mesh_from_nurbs(Object *ob)
{
- BKE_mesh_from_nurbs_displist(ob, &ob->disp, NULL);
+ BKE_mesh_from_nurbs_displist(ob, &ob->disp, false);
}
typedef struct EdgeLink {
@@ -1612,65 +1586,46 @@ static void appendPolyLineVert(ListBase *lb, unsigned int index)
BLI_addtail(lb, vl);
}
-void BKE_mesh_from_curve(Scene *scene, Object *ob)
+void BKE_mesh_to_curve_nurblist(DerivedMesh *dm, ListBase *nurblist, const int edge_users_test)
{
- /* make new mesh data from the original copy */
- DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_MESH);
-
- MVert *mverts = dm->getVertArray(dm);
+ MVert *mvert = dm->getVertArray(dm);
MEdge *med, *medge = dm->getEdgeArray(dm);
- MFace *mf, *mface = dm->getTessFaceArray(dm);
+ MPoly *mp, *mpoly = dm->getPolyArray(dm);
+ MLoop *mloop = dm->getLoopArray(dm);
- int totedge = dm->getNumEdges(dm);
- int totface = dm->getNumTessFaces(dm);
+ int dm_totedge = dm->getNumEdges(dm);
+ int dm_totpoly = dm->getNumPolys(dm);
int totedges = 0;
- int i, needsFree = 0;
+ int i;
/* only to detect edge polylines */
- EdgeHash *eh = BLI_edgehash_new();
- EdgeHash *eh_edge = BLI_edgehash_new();
-
+ int *edge_users;
ListBase edges = {NULL, NULL};
- /* create edges from all faces (so as to find edges not in any faces) */
- mf = mface;
- for (i = 0; i < totface; i++, mf++) {
- if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
- BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
- if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
- BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
-
- if (mf->v4) {
- if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
- BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
- if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
- BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
- }
- else {
- if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
- BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
+ /* get boundary edges */
+ edge_users = MEM_callocN(sizeof(int) * dm_totedge, __func__);
+ for (i = 0, mp = mpoly; i < dm_totpoly; i++, mp++) {
+ MLoop *ml = &mloop[mp->loopstart];
+ int j;
+ for (j = 0; j < mp->totloop; j++, ml++) {
+ edge_users[ml->e]++;
}
}
+ /* create edges from all faces (so as to find edges not in any faces) */
med = medge;
- for (i = 0; i < totedge; i++, med++) {
- if (!BLI_edgehash_haskey(eh, med->v1, med->v2)) {
+ for (i = 0; i < dm_totedge; i++, med++) {
+ if (edge_users[i] == edge_users_test) {
EdgeLink *edl = MEM_callocN(sizeof(EdgeLink), "EdgeLink");
-
- BLI_edgehash_insert(eh_edge, med->v1, med->v2, NULL);
edl->edge = med;
BLI_addtail(&edges, edl); totedges++;
}
}
- BLI_edgehash_free(eh_edge, NULL);
- BLI_edgehash_free(eh, NULL);
+ MEM_freeN(edge_users);
if (edges.first) {
- Curve *cu = BKE_curve_add(ob->id.name + 2, OB_CURVE);
- cu->flag |= CU_3D;
-
while (edges.first) {
/* each iteration find a polyline and add this as a nurbs poly spline */
@@ -1750,24 +1705,41 @@ void BKE_mesh_from_curve(Scene *scene, Object *ob)
/* add points */
vl = polyline.first;
for (i = 0, bp = nu->bp; i < totpoly; i++, bp++, vl = (VertLink *)vl->next) {
- copy_v3_v3(bp->vec, mverts[vl->index].co);
+ copy_v3_v3(bp->vec, mvert[vl->index].co);
bp->f1 = SELECT;
bp->radius = bp->weight = 1.0;
}
BLI_freelistN(&polyline);
/* add nurb to curve */
- BLI_addtail(&cu->nurb, nu);
+ BLI_addtail(nurblist, nu);
}
/* --- done with nurbs --- */
}
+ }
+}
+
+void BKE_mesh_to_curve(Scene *scene, Object *ob)
+{
+ /* make new mesh data from the original copy */
+ DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_MESH);
+ ListBase nurblist = {NULL, NULL};
+ bool needsFree = false;
+
+ BKE_mesh_to_curve_nurblist(dm, &nurblist, 0);
+
+ if (nurblist.first) {
+ Curve *cu = BKE_curve_add(G.main, ob->id.name + 2, OB_CURVE);
+ cu->flag |= CU_3D;
+
+ cu->nurb = nurblist;
((Mesh *)ob->data)->id.us--;
ob->data = cu;
ob->type = OB_CURVE;
/* curve objects can't contain DM in usual cases, we could free memory */
- needsFree = 1;
+ needsFree = true;
}
dm->needsFree = needsFree;
@@ -1842,7 +1814,7 @@ void BKE_mesh_calc_normals_mapping_ex(MVert *mverts, int numVerts,
MLoop *mloop, MPoly *mpolys,
int numLoops, int numPolys, float (*polyNors_r)[3],
MFace *mfaces, int numFaces, int *origIndexFace, float (*faceNors_r)[3],
- const short only_face_normals)
+ const bool only_face_normals)
{
float (*pnors)[3] = polyNors_r, (*fnors)[3] = faceNors_r;
int i;
@@ -2091,7 +2063,7 @@ void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh)
mesh->medge, mesh->mface,
&mesh->totloop, &mesh->totpoly, &mesh->mloop, &mesh->mpoly);
- mesh_update_customdata_pointers(mesh, TRUE);
+ BKE_mesh_update_customdata_pointers(mesh, true);
}
/* the same as BKE_mesh_convert_mfaces_to_mpolys but oriented to be used in do_versions from readfile.c
@@ -2113,7 +2085,7 @@ void BKE_mesh_do_versions_convert_mfaces_to_mpolys(Mesh *mesh)
CustomData_bmesh_do_versions_update_active_layers(&mesh->fdata, &mesh->pdata, &mesh->ldata);
- mesh_update_customdata_pointers(mesh, TRUE);
+ BKE_mesh_update_customdata_pointers(mesh, true);
}
void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, CustomData *fdata, CustomData *ldata, CustomData *pdata,
@@ -2218,12 +2190,12 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, CustomData *fdata, CustomData
*mloop_r = mloop;
}
-float (*mesh_getVertexCos(Mesh * me, int *numVerts_r))[3]
+float (*mesh_getVertexCos(Mesh * me, int *r_numVerts))[3]
{
int i, numVerts = me->totvert;
float (*cos)[3] = MEM_mallocN(sizeof(*cos) * numVerts, "vertexcos1");
- if (numVerts_r) *numVerts_r = numVerts;
+ if (r_numVerts) *r_numVerts = numVerts;
for (i = 0; i < numVerts; i++)
copy_v3_v3(cos[i], me->mvert[i].co);
@@ -2235,7 +2207,8 @@ float (*mesh_getVertexCos(Mesh * me, int *numVerts_r))[3]
/* 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_make(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, int selected, float *limit)
{
UvVertMap *vmap;
UvMapVert *buf;
@@ -2343,9 +2316,9 @@ 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 create_vert_poly_map(MeshElemMap **map, int **mem,
- const MPoly *mpoly, const MLoop *mloop,
- int totvert, int totpoly, int totloop)
+void BKE_mesh_vert_poly_map_create(MeshElemMap **map, int **mem,
+ const MPoly *mpoly, const MLoop *mloop,
+ int totvert, int totpoly, int totloop)
{
int i, j;
int *indices;
@@ -2387,8 +2360,8 @@ void create_vert_poly_map(MeshElemMap **map, int **mem,
/* 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 create_vert_edge_map(MeshElemMap **map, int **mem,
- const MEdge *medge, int totvert, int totedge)
+void BKE_mesh_vert_edge_map_create(MeshElemMap **map, int **mem,
+ const MEdge *medge, int totvert, int totedge)
{
int i, *indices;
@@ -2489,11 +2462,11 @@ void BKE_mesh_loops_to_mface_corners(CustomData *fdata, CustomData *ldata,
*/
int BKE_mesh_recalc_tessellation(CustomData *fdata,
CustomData *ldata, CustomData *pdata,
- MVert *mvert, int totface, int UNUSED(totloop),
+ MVert *mvert, int totface, int totloop,
int totpoly,
/* when tessellating to recalculate normals after
* we can skip copying here */
- const int do_face_nor_cpy)
+ const bool do_face_nor_cpy)
{
/* use this to avoid locking pthread for _every_ polygon
* and calling the fill function */
@@ -2504,15 +2477,15 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
#define TESSFACE_SCANFILL (1 << 0)
#define TESSFACE_IS_QUAD (1 << 1)
+ const int looptris_tot = poly_to_tri_count(totpoly, totloop);
+
MPoly *mp, *mpoly;
MLoop *ml, *mloop;
- MFace *mface = NULL, *mf;
- BLI_array_declare(mface);
+ MFace *mface, *mf;
ScanFillContext sf_ctx;
ScanFillVert *sf_vert, *sf_vert_last, *sf_vert_first;
ScanFillFace *sf_tri;
- int *mface_to_poly_map = NULL;
- BLI_array_declare(mface_to_poly_map);
+ int *mface_to_poly_map;
int lindex[4]; /* only ever use 3 in this case */
int poly_index, j, mface_index;
@@ -2526,8 +2499,9 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
/* allocate the length of totfaces, avoid many small reallocs,
* if all faces are tri's it will be correct, quads == 2x allocs */
- BLI_array_reserve(mface_to_poly_map, totpoly);
- BLI_array_reserve(mface, totpoly);
+ /* 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) * looptris_tot, __func__);
+ mface = MEM_mallocN(sizeof(*mface) * looptris_tot, __func__);
mface_index = 0;
mp = mpoly;
@@ -2539,8 +2513,6 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
#ifdef USE_TESSFACE_SPEEDUP
#define ML_TO_MF(i1, i2, i3) \
- BLI_array_grow_one(mface_to_poly_map); \
- BLI_array_grow_one(mface); \
mface_to_poly_map[mface_index] = poly_index; \
mf = &mface[mface_index]; \
/* set loop indices, transformed to vert indices later */ \
@@ -2550,12 +2522,11 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
mf->v4 = 0; \
mf->mat_nr = mp->mat_nr; \
mf->flag = mp->flag; \
+ mf->edcode = 0; \
(void)0
/* ALMOST IDENTICAL TO DEFINE ABOVE (see EXCEPTION) */
#define ML_TO_MF_QUAD() \
- BLI_array_grow_one(mface_to_poly_map); \
- BLI_array_grow_one(mface); \
mface_to_poly_map[mface_index] = poly_index; \
mf = &mface[mface_index]; \
/* set loop indices, transformed to vert indices later */ \
@@ -2565,7 +2536,7 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
mf->v4 = mp->loopstart + 3; /* EXCEPTION */ \
mf->mat_nr = mp->mat_nr; \
mf->flag = mp->flag; \
- mf->edcode |= TESSFACE_IS_QUAD; /* EXCEPTION */ \
+ mf->edcode = TESSFACE_IS_QUAD; /* EXCEPTION */ \
(void)0
@@ -2608,29 +2579,27 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert_first);
totfilltri = BLI_scanfill_calc(&sf_ctx, 0);
- if (totfilltri) {
- BLI_array_grow_items(mface_to_poly_map, totfilltri);
- BLI_array_grow_items(mface, totfilltri);
+ BLI_assert(totfilltri <= mp->totloop - 2);
+ (void)totfilltri;
- for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next, mf++) {
- mface_to_poly_map[mface_index] = poly_index;
- mf = &mface[mface_index];
+ for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next, mf++) {
+ mface_to_poly_map[mface_index] = poly_index;
+ mf = &mface[mface_index];
- /* set loop indices, transformed to vert indices later */
- mf->v1 = sf_tri->v1->keyindex;
- mf->v2 = sf_tri->v2->keyindex;
- mf->v3 = sf_tri->v3->keyindex;
- mf->v4 = 0;
+ /* set loop indices, transformed to vert indices later */
+ mf->v1 = sf_tri->v1->keyindex;
+ mf->v2 = sf_tri->v2->keyindex;
+ mf->v3 = sf_tri->v3->keyindex;
+ mf->v4 = 0;
- mf->mat_nr = mp->mat_nr;
- mf->flag = mp->flag;
+ mf->mat_nr = mp->mat_nr;
+ mf->flag = mp->flag;
#ifdef USE_TESSFACE_SPEEDUP
- mf->edcode |= TESSFACE_SCANFILL; /* tag for sorting loop indices */
+ mf->edcode = TESSFACE_SCANFILL; /* tag for sorting loop indices */
#endif
- mface_index++;
- }
+ mface_index++;
}
BLI_scanfill_end(&sf_ctx);
@@ -2640,9 +2609,10 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
CustomData_free(fdata, totface);
totface = mface_index;
+ BLI_assert(totface <= looptris_tot);
/* not essential but without this we store over-alloc'd memory in the CustomData layers */
- if (LIKELY((MEM_allocN_len(mface) / sizeof(*mface)) != totface)) {
+ if (LIKELY(looptris_tot != totface)) {
mface = MEM_reallocN(mface, sizeof(*mface) * totface);
mface_to_poly_map = MEM_reallocN(mface_to_poly_map, sizeof(*mface_to_poly_map) * totface);
}
@@ -3030,6 +3000,98 @@ 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])
+{
+ int i;
+ float tri_area;
+ float total_area = 0.0f;
+ float v1[3], v2[3], v3[3], normal[3], tri_cent[3];
+
+ BKE_mesh_calc_poly_normal(mpoly, loopstart, mvarray, normal);
+ copy_v3_v3(v1, mvarray[loopstart[0].v].co);
+ copy_v3_v3(v2, mvarray[loopstart[1].v].co);
+ zero_v3(cent);
+
+ for (i = 2; i < mpoly->totloop; i++) {
+ copy_v3_v3(v3, mvarray[loopstart[i].v].co);
+
+ tri_area = area_tri_signed_v3(v1, v2, v3, normal);
+ total_area += tri_area;
+
+ cent_tri_v3(tri_cent, v1, v2, v3);
+ madd_v3_v3fl(cent, tri_cent, tri_area);
+
+ copy_v3_v3(v2, v3);
+ }
+
+ mul_v3_fl(cent, 1.0f / total_area);
+
+ return total_area;
+}
+
+/**
+ * This function takes the difference between 2 vertex-coord-arrays
+ * (\a vert_cos_src, \a vert_cos_dst),
+ * and applies the difference to \a vert_cos_new relative to \a vert_cos_org.
+ *
+ * \param vert_cos_src reference deform source.
+ * \param vert_cos_dst reference deform destination.
+ *
+ * \param vert_cos_org reference for the output location.
+ * \param vert_cos_new resulting coords.
+ */
+void BKE_mesh_calc_relative_deform(
+ const MPoly *mpoly, const int totpoly,
+ const MLoop *mloop, const int totvert,
+
+ const float (*vert_cos_src)[3],
+ const float (*vert_cos_dst)[3],
+
+ const float (*vert_cos_org)[3],
+ float (*vert_cos_new)[3])
+{
+ const MPoly *mp;
+ int i;
+
+ int *vert_accum = MEM_callocN(sizeof(*vert_accum) * totvert, __func__);
+
+ memset(vert_cos_new, '\0', sizeof(*vert_cos_new) * totvert);
+
+ for (i = 0, mp = mpoly; i < totpoly; i++, mp++) {
+ const MLoop *loopstart = mloop + mp->loopstart;
+ int j;
+
+ for (j = 0; j < mp->totloop; j++) {
+ int v_prev = (loopstart + ((mp->totloop + (j - 1)) % mp->totloop))->v;
+ int v_curr = (loopstart + j)->v;
+ int v_next = (loopstart + ((j + 1) % mp->totloop))->v;
+
+ float tvec[3];
+
+ barycentric_transform(
+ tvec, vert_cos_dst[v_curr],
+ vert_cos_org[v_prev], vert_cos_org[v_curr], vert_cos_org[v_next],
+ vert_cos_src[v_prev], vert_cos_src[v_curr], vert_cos_src[v_next]
+ );
+
+ add_v3_v3(vert_cos_new[v_curr], tvec);
+ vert_accum[v_curr] += 1;
+ }
+ }
+
+ for (i = 0; i < totvert; i++) {
+ if (vert_accum[i]) {
+ mul_v3_fl(vert_cos_new[i], 1.0f / (float)vert_accum[i]);
+ }
+ else {
+ copy_v3_v3(vert_cos_new[i], vert_cos_org[i]);
+ }
+ }
+
+ MEM_freeN(vert_accum);
+}
+
/* 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,
@@ -3108,6 +3170,107 @@ void BKE_mesh_flush_hidden_from_verts(const MVert *mvert,
}
}
+/**
+ * simple poly -> vert/edge selection.
+ */
+void BKE_mesh_flush_select_from_polys_ex(MVert *mvert, const int totvert,
+ MLoop *mloop,
+ MEdge *medge, const int totedge,
+ const MPoly *mpoly, const int totpoly)
+{
+ MVert *mv;
+ MEdge *med;
+ const MPoly *mp;
+ int i;
+
+ i = totvert;
+ for (mv = mvert; i--; mv++) {
+ mv->flag &= ~SELECT;
+ }
+
+ i = totedge;
+ for (med = medge; i--; med++) {
+ med->flag &= ~SELECT;
+ }
+
+ i = totpoly;
+ for (mp = mpoly; i--; mp++) {
+ /* assume if its selected its not hidden and none of its verts/edges are hidden
+ * (a common assumption)*/
+ if (mp->flag & ME_FACE_SEL) {
+ MLoop *ml;
+ int j;
+ j = mp->totloop;
+ for (ml = &mloop[mp->loopstart]; j--; ml++) {
+ mvert[ml->v].flag |= SELECT;
+ medge[ml->e].flag |= SELECT;
+ }
+ }
+ }
+}
+void BKE_mesh_flush_select_from_polys(Mesh *me)
+{
+ BKE_mesh_flush_select_from_polys_ex(me->mvert, me->totvert,
+ me->mloop,
+ me->medge, me->totedge,
+ me->mpoly, me->totpoly);
+}
+
+void BKE_mesh_flush_select_from_verts_ex(const MVert *mvert, const int UNUSED(totvert),
+ MLoop *mloop,
+ MEdge *medge, const int totedge,
+ MPoly *mpoly, const int totpoly)
+{
+ MEdge *med;
+ MPoly *mp;
+ int i;
+
+ /* edges */
+ i = totedge;
+ for (med = medge; i--; med++) {
+ if ((med->flag & ME_HIDE) == 0) {
+ if ((mvert[med->v1].flag & SELECT) && (mvert[med->v2].flag & SELECT)) {
+ med->flag |= SELECT;
+ }
+ else {
+ med->flag &= ~SELECT;
+ }
+ }
+ }
+
+ /* polys */
+ i = totpoly;
+ for (mp = mpoly; i--; mp++) {
+ if ((mp->flag & ME_HIDE) == 0) {
+ int ok = TRUE;
+ MLoop *ml;
+ int j;
+ j = mp->totloop;
+ for (ml = &mloop[mp->loopstart]; j--; ml++) {
+ if ((mvert[ml->v].flag & SELECT) == 0) {
+ ok = FALSE;
+ break;
+ }
+ }
+
+ if (ok) {
+ mp->flag |= ME_FACE_SEL;
+ }
+ else {
+ mp->flag &= ~ME_FACE_SEL;
+ }
+ }
+ }
+}
+void BKE_mesh_flush_select_from_verts(Mesh *me)
+{
+ BKE_mesh_flush_select_from_verts_ex(me->mvert, me->totvert,
+ me->mloop,
+ me->medge, me->totedge,
+ me->mpoly, me->totpoly);
+}
+
+
/* basic vertex data functions */
int BKE_mesh_minmax(Mesh *me, float r_min[3], float r_max[3])
{
@@ -3160,9 +3323,8 @@ int BKE_mesh_center_centroid(Mesh *me, float cent[3])
/* calculate a weighted average of polygon centroids */
for (mpoly = me->mpoly; i--; mpoly++) {
- BKE_mesh_calc_poly_center(mpoly, me->mloop + mpoly->loopstart, me->mvert, poly_cent);
- poly_area = BKE_mesh_calc_poly_area(mpoly, me->mloop + mpoly->loopstart, me->mvert, NULL);
-
+ 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);
total_area += poly_area;
}
@@ -3174,7 +3336,7 @@ int BKE_mesh_center_centroid(Mesh *me, float cent[3])
return (me->totpoly != 0);
}
-void BKE_mesh_translate(Mesh *me, float offset[3], int do_keys)
+void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys)
{
int i = me->totvert;
MVert *mvert;
@@ -3213,9 +3375,9 @@ void BKE_mesh_tessface_calc(Mesh *mesh)
mesh->mvert,
mesh->totface, mesh->totloop, mesh->totpoly,
/* calc normals right after, don't copy from polys here */
- FALSE);
+ false);
- mesh_update_customdata_pointers(mesh, TRUE);
+ BKE_mesh_update_customdata_pointers(mesh, true);
}
void BKE_mesh_tessface_ensure(Mesh *mesh)
@@ -3277,3 +3439,39 @@ void BKE_mesh_poly_calc_angles(MVert *mvert, MLoop *mloop,
}
}
#endif
+
+
+void BKE_mesh_do_versions_cd_flag_init(Mesh *mesh)
+{
+ if (UNLIKELY(mesh->cd_flag)) {
+ return;
+ }
+ else {
+ MVert *mv;
+ MEdge *med;
+ int i;
+
+ for (mv = mesh->mvert, i = 0; i < mesh->totvert; mv++, i++) {
+ if (mv->bweight != 0) {
+ mesh->cd_flag |= ME_CDFLAG_VERT_BWEIGHT;
+ break;
+ }
+ }
+
+ for (med = mesh->medge, i = 0; i < mesh->totedge; med++, i++) {
+ if (med->bweight != 0) {
+ mesh->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT;
+ if (mesh->cd_flag & ME_CDFLAG_EDGE_CREASE) {
+ break;
+ }
+ }
+ if (med->crease != 0) {
+ mesh->cd_flag |= ME_CDFLAG_EDGE_CREASE;
+ if (mesh->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) {
+ break;
+ }
+ }
+ }
+
+ }
+}
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index 128b9ae242e..90704cb8b7e 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -190,13 +190,13 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
MLoop *mloops, unsigned int totloop,
MPoly *mpolys, unsigned int totpoly,
MDeformVert *dverts, /* assume totvert length */
- const short do_verbose, const short do_fixes)
+ const bool do_verbose, const bool do_fixes)
{
-# define REMOVE_EDGE_TAG(_me) { _me->v2 = _me->v1; do_edge_free = TRUE; } (void)0
+# define REMOVE_EDGE_TAG(_me) { _me->v2 = _me->v1; do_edge_free = true; } (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; do_polyloop_free = true; } (void)0
+# define REMOVE_POLY_TAG(_mp) { _mp->totloop *= -1; do_polyloop_free = true; } (void)0
MVert *mv = mverts;
MEdge *me;
@@ -205,15 +205,15 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
unsigned int i, j;
int *v;
- short do_edge_free = FALSE;
- short do_face_free = FALSE;
- short do_polyloop_free = FALSE; /* This regroups loops and polys! */
+ bool do_edge_free = false;
+ bool do_face_free = false;
+ bool do_polyloop_free = false; /* This regroups loops and polys! */
- short verts_fixed = FALSE;
- short vert_weights_fixed = FALSE;
- int msel_fixed = FALSE;
+ bool verts_fixed = false;
+ bool vert_weights_fixed = false;
+ bool msel_fixed = false;
- int do_edge_recalc = FALSE;
+ bool do_edge_recalc = false;
EdgeHash *edge_hash = BLI_edgehash_new();
@@ -774,7 +774,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
}
if (do_edge_recalc) {
- BKE_mesh_calc_edges(mesh, TRUE);
+ BKE_mesh_calc_edges(mesh, true, false);
}
}
@@ -825,7 +825,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh,
return (verts_fixed || vert_weights_fixed || do_polyloop_free || do_edge_free || do_edge_recalc || msel_fixed);
}
-static int mesh_validate_customdata(CustomData *data, short do_verbose, const short do_fixes)
+static int mesh_validate_customdata(CustomData *data, const bool do_verbose, const bool do_fixes)
{
int i = 0, has_fixes = 0;
@@ -859,7 +859,7 @@ static int mesh_validate_customdata(CustomData *data, short do_verbose, const sh
static int BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata,
CustomData *ldata, CustomData *pdata,
- short do_verbose, const short do_fixes)
+ const bool do_verbose, const short do_fixes)
{
int vfixed = 0, efixed = 0, lfixed = 0, pfixed = 0;
@@ -871,7 +871,7 @@ static int BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata
return vfixed || efixed || lfixed || pfixed;
}
-int BKE_mesh_validate(Mesh *me, int do_verbose)
+int BKE_mesh_validate(Mesh *me, const int do_verbose)
{
int layers_fixed = 0, arrays_fixed = 0;
@@ -887,13 +887,13 @@ int BKE_mesh_validate(Mesh *me, int do_verbose)
me->mloop, me->totloop,
me->mpoly, me->totpoly,
me->dvert,
- do_verbose, TRUE);
+ do_verbose, true);
if (layers_fixed || arrays_fixed) {
DAG_id_tag_update(&me->id, OB_RECALC_DATA);
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
int BKE_mesh_validate_dm(DerivedMesh *dm)
@@ -908,7 +908,13 @@ int BKE_mesh_validate_dm(DerivedMesh *dm)
TRUE, FALSE);
}
-void BKE_mesh_calc_edges(Mesh *mesh, int update)
+/**
+ * Calculate edges from polygons
+ *
+ * \param mesh The mesh to add edges into
+ * \param update When true create new edges co-exist
+ */
+void BKE_mesh_calc_edges(Mesh *mesh, bool update, const bool select)
{
CustomData edata;
EdgeHashIterator *ehi;
@@ -917,9 +923,11 @@ void BKE_mesh_calc_edges(Mesh *mesh, int update)
EdgeHash *eh = BLI_edgehash_new();
int i, totedge, totpoly = mesh->totpoly;
int med_index;
+ /* select for newly created meshes which are selected [#25595] */
+ const short ed_flag = (ME_EDGEDRAW | ME_EDGERENDER) | (select ? SELECT : 0);
if (mesh->totedge == 0)
- update = FALSE;
+ update = false;
if (update) {
/* assume existing edges are valid
@@ -957,7 +965,7 @@ void BKE_mesh_calc_edges(Mesh *mesh, int update)
}
else {
BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2);
- med->flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT; /* select for newly created meshes which are selected [#25595] */
+ med->flag = ed_flag;
}
/* store the new edge index in the hash value */
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 25b70ce1793..9b8101cdad4 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -95,7 +95,7 @@ ModifierData *modifier_new(int type)
ModifierData *md = MEM_callocN(mti->structSize, mti->structName);
/* note, this name must be made unique later */
- BLI_strncpy(md->name, mti->name, sizeof(md->name));
+ BLI_strncpy(md->name, DATA_(mti->name), sizeof(md->name));
md->type = type;
md->mode = eModifierMode_Realtime | eModifierMode_Render | eModifierMode_Expanded;
@@ -424,7 +424,9 @@ ModifierData *modifiers_getLastPreview(struct Scene *scene, ModifierData *md, in
return tmp_md;
}
-/* NOTE: these aren't used anymore */
+/* NOTE: This is to support old files from before Blender supported modifiers,
+ * in some cases versioning code updates these so for new files this will
+ * return an empty list. */
ModifierData *modifiers_getVirtualModifierList(Object *ob)
{
/* Kinda hacky, but should be fine since we are never
@@ -621,16 +623,6 @@ int modifiers_isPreview(Object *ob)
return FALSE;
}
-int modifiers_indexInObject(Object *ob, ModifierData *md_seek)
-{
- int i = 0;
- ModifierData *md;
-
- for (md = ob->modifiers.first; (md && md_seek != md); md = md->next, i++) ;
- if (!md) return -1; /* modifier isn't in the object */
- return i;
-}
-
void modifier_freeTemporaryData(ModifierData *md)
{
if (md->type == eModifierType_Armature) {
diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c
index 381e4350391..a6c2325c740 100644
--- a/source/blender/blenkernel/intern/modifiers_bmesh.c
+++ b/source/blender/blenkernel/intern/modifiers_bmesh.c
@@ -40,7 +40,11 @@
#include "BKE_bmesh.h"
#include "BKE_tessmesh.h"
-/* main function for copying DerivedMesh data into BMesh */
+/**
+ * The main function for copying DerivedMesh data into BMesh.
+ *
+ * \note The mesh may already have geometry. see 'is_init'
+ */
void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm)
{
MVert *mv, *mvert;
@@ -55,7 +59,20 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm)
BLI_array_declare(verts);
BLI_array_declare(edges);
int i, j, k, totvert, totedge /* , totface */ /* UNUSED */ ;
- int is_init = (bm->totvert == 0) && (bm->totedge == 0) && (bm->totface == 0);
+ bool is_init = (bm->totvert == 0) && (bm->totedge == 0) && (bm->totface == 0);
+ bool is_cddm = (dm->type == DM_TYPE_CDDM); /* duplicate the arrays for non cddm */
+ char has_orig_hflag = 0;
+
+ int cd_vert_bweight_offset;
+ int cd_edge_bweight_offset;
+ int cd_edge_crease_offset;
+
+ if (is_init == FALSE) {
+ /* check if we have an origflag */
+ has_orig_hflag |= CustomData_has_layer(&bm->vdata, CD_ORIGINDEX) ? BM_VERT : 0;
+ has_orig_hflag |= CustomData_has_layer(&bm->edata, CD_ORIGINDEX) ? BM_EDGE : 0;
+ has_orig_hflag |= CustomData_has_layer(&bm->pdata, CD_ORIGINDEX) ? BM_FACE : 0;
+ }
/*merge custom data layout*/
CustomData_bmesh_merge(&dm->vertData, &bm->vdata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_VERT);
@@ -63,38 +80,45 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm)
CustomData_bmesh_merge(&dm->loopData, &bm->ldata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_LOOP);
CustomData_bmesh_merge(&dm->polyData, &bm->pdata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_FACE);
+ if (is_init) {
+ BM_mesh_cd_flag_apply(bm, dm->cd_flag);
+ }
+
+ cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
+ cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
+ cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
+
totvert = dm->getNumVerts(dm);
totedge = dm->getNumEdges(dm);
/* totface = dm->getNumPolys(dm); */ /* UNUSED */
- /* add crease layer */
- BM_data_layer_add(bm, &bm->edata, CD_CREASE);
- /* add bevel weight layers */
- BM_data_layer_add(bm, &bm->edata, CD_BWEIGHT);
- BM_data_layer_add(bm, &bm->vdata, CD_BWEIGHT);
-
vtable = MEM_callocN(sizeof(void **) * totvert, __func__);
etable = MEM_callocN(sizeof(void **) * totedge, __func__);
/*do verts*/
- mv = mvert = dm->dupVertArray(dm);
+ mv = mvert = is_cddm ? dm->getVertArray(dm) : dm->dupVertArray(dm);
for (i = 0; i < totvert; i++, mv++) {
v = BM_vert_create(bm, mv->co, NULL, BM_CREATE_SKIP_CD);
normal_short_to_float_v3(v->no, mv->no);
v->head.hflag = BM_vert_flag_from_mflag(mv->flag);
BM_elem_index_set(v, i); /* set_inline */
- CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v->head.data);
+ CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v->head.data, true);
+ vtable[i] = v;
/* add bevel weight */
- BM_elem_float_data_set(&bm->vdata, v, CD_BWEIGHT, (float)mv->bweight / 255.0f);
- vtable[i] = v;
+ if (cd_vert_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(v, cd_vert_bweight_offset, (float)mv->bweight / 255.0f);
+
+ if (UNLIKELY(has_orig_hflag & BM_VERT)) {
+ int *orig_index = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_ORIGINDEX);
+ *orig_index = ORIGINDEX_NONE;
+ }
}
- MEM_freeN(mvert);
+ if (!is_cddm) MEM_freeN(mvert);
if (is_init) bm->elem_index_dirty &= ~BM_VERT;
/*do edges*/
- me = medge = dm->dupEdgeArray(dm);
+ me = medge = is_cddm ? dm->getEdgeArray(dm) : dm->dupEdgeArray(dm);
for (i = 0; i < totedge; i++, me++) {
//BLI_assert(BM_edge_exists(vtable[me->v1], vtable[me->v2]) == NULL);
e = BM_edge_create(bm, vtable[me->v1], vtable[me->v2], NULL, BM_CREATE_SKIP_CD);
@@ -102,15 +126,18 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm)
e->head.hflag = BM_edge_flag_from_mflag(me->flag);
BM_elem_index_set(e, i); /* set_inline */
- CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->head.data);
+ CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->head.data, true);
etable[i] = e;
- /* add crease */
- BM_elem_float_data_set(&bm->edata, e, CD_CREASE, (float)me->crease / 255.0f);
- /* add bevel weight */
- BM_elem_float_data_set(&bm->edata, e, CD_BWEIGHT, (float)me->bweight / 255.0f);
+ if (cd_edge_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_bweight_offset, (float)me->bweight / 255.0f);
+ if (cd_edge_crease_offset != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_crease_offset, (float)me->crease / 255.0f);
+
+ if (UNLIKELY(has_orig_hflag & BM_EDGE)) {
+ int *orig_index = CustomData_bmesh_get(&bm->edata, e->head.data, CD_ORIGINDEX);
+ *orig_index = ORIGINDEX_NONE;
+ }
}
- MEM_freeN(medge);
+ if (!is_cddm) MEM_freeN(medge);
if (is_init) bm->elem_index_dirty &= ~BM_EDGE;
/* do faces */
@@ -134,7 +161,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm)
edges[j] = etable[ml->e];
}
- f = BM_face_create_ngon(bm, verts[0], verts[1], edges, mp->totloop, BM_CREATE_SKIP_CD);
+ f = BM_face_create(bm, verts, edges, mp->totloop, BM_CREATE_SKIP_CD);
if (UNLIKELY(f == NULL)) {
continue;
@@ -147,10 +174,10 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm)
l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f);
for (k = mp->loopstart; l; l = BM_iter_step(&liter), k++) {
- CustomData_to_bmesh_block(&dm->loopData, &bm->ldata, k, &l->head.data);
+ CustomData_to_bmesh_block(&dm->loopData, &bm->ldata, k, &l->head.data, true);
}
- CustomData_to_bmesh_block(&dm->polyData, &bm->pdata, i, &f->head.data);
+ CustomData_to_bmesh_block(&dm->polyData, &bm->pdata, i, &f->head.data, true);
if (face_normals) {
copy_v3_v3(f->no, face_normals[i]);
@@ -158,6 +185,11 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm)
else {
BM_face_normal_update(f);
}
+
+ if (UNLIKELY(has_orig_hflag & BM_FACE)) {
+ int *orig_index = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_ORIGINDEX);
+ *orig_index = ORIGINDEX_NONE;
+ }
}
if (is_init) bm->elem_index_dirty &= ~BM_FACE;
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index 4156b5b4367..49a64d8e478 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -75,12 +75,19 @@
#include "BKE_node.h"
#include "BKE_image.h" /* openanim */
#include "BKE_tracking.h"
+#include "BKE_sequencer.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "IMB_moviecache.h"
+#ifdef WITH_OPENEXR
+#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)
@@ -216,11 +223,20 @@ static ImBuf *movieclip_load_sequence_file(MovieClip *clip, MovieClipUser *user,
colorspace = clip->colorspace_settings.name;
}
- loadflag = IB_rect | IB_multilayer;
+ loadflag = IB_rect | IB_multilayer | IB_alphamode_detect;
/* read ibuf */
ibuf = IMB_loadiffname(name, loadflag, colorspace);
+#ifdef WITH_OPENEXR
+ if (ibuf) {
+ if (ibuf->ftype == OPENEXR && ibuf->userdata) {
+ IMB_exr_close(ibuf->userdata);
+ ibuf->userdata = NULL;
+ }
+ }
+#endif
+
return ibuf;
}
@@ -441,7 +457,29 @@ static ImBuf *get_imbuf_cache(MovieClip *clip, MovieClipUser *user, int flag)
return NULL;
}
-static void put_imbuf_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int flag)
+static int has_imbuf_cache(MovieClip *clip, MovieClipUser *user, int flag)
+{
+ if (clip->cache) {
+ MovieClipImBufCacheKey key;
+
+ key.framenr = user->framenr;
+
+ if (flag & MCLIP_USE_PROXY) {
+ key.proxy = rendersize_to_proxy(user, flag);
+ key.render_flag = user->render_flag;
+ }
+ else {
+ key.proxy = IMB_PROXY_NONE;
+ key.render_flag = 0;
+ }
+
+ return IMB_moviecache_has_frame(clip->cache->moviecache, &key);
+ }
+
+ return FALSE;
+}
+
+static bool put_imbuf_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int flag, bool destructive)
{
MovieClipImBufCacheKey key;
@@ -473,17 +511,23 @@ static void put_imbuf_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, i
key.render_flag = 0;
}
- IMB_moviecache_put(clip->cache->moviecache, &key, ibuf);
+ if (destructive) {
+ IMB_moviecache_put(clip->cache->moviecache, &key, ibuf);
+ return true;
+ }
+ else {
+ return IMB_moviecache_put_if_possible(clip->cache->moviecache, &key, ibuf);
+ }
}
/*********************** common functions *************************/
/* only image block itself */
-static MovieClip *movieclip_alloc(const char *name)
+static MovieClip *movieclip_alloc(Main *bmain, const char *name)
{
MovieClip *clip;
- clip = BKE_libblock_alloc(&G.main->movieclip, ID_MC, name);
+ clip = BKE_libblock_alloc(&bmain->movieclip, ID_MC, name);
clip->aspx = clip->aspy = 1.0f;
@@ -542,7 +586,7 @@ static void detect_clip_source(MovieClip *clip)
* otherwise creates new.
* does not load ibuf itself
* pass on optional frame for #name images */
-MovieClip *BKE_movieclip_file_add(const char *name)
+MovieClip *BKE_movieclip_file_add(Main *bmain, const char *name)
{
MovieClip *clip;
int file, len;
@@ -550,7 +594,7 @@ MovieClip *BKE_movieclip_file_add(const char *name)
char str[FILE_MAX], strtest[FILE_MAX];
BLI_strncpy(str, name, sizeof(str));
- BLI_path_abs(str, G.main->name);
+ BLI_path_abs(str, bmain->name);
/* exists? */
file = BLI_open(str, O_BINARY | O_RDONLY, 0);
@@ -559,7 +603,7 @@ MovieClip *BKE_movieclip_file_add(const char *name)
close(file);
/* ** first search an identical clip ** */
- for (clip = G.main->movieclip.first; clip; clip = clip->id.next) {
+ for (clip = bmain->movieclip.first; clip; clip = clip->id.next) {
BLI_strncpy(strtest, clip->name, sizeof(clip->name));
BLI_path_abs(strtest, G.main->name);
@@ -580,7 +624,7 @@ MovieClip *BKE_movieclip_file_add(const char *name)
len--;
libname = name + len;
- clip = movieclip_alloc(libname);
+ clip = movieclip_alloc(bmain, libname);
BLI_strncpy(clip->name, name, sizeof(clip->name));
detect_clip_source(clip);
@@ -798,7 +842,7 @@ static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *u
}
if (ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0)
- put_imbuf_cache(clip, user, ibuf, flag);
+ put_imbuf_cache(clip, user, ibuf, flag, true);
}
if (ibuf) {
@@ -1095,6 +1139,7 @@ void BKE_movieclip_reload(MovieClip *clip)
free_buffers(clip);
clip->tracking.stabilization.ok = FALSE;
+ clip->prefetch_ok = FALSE;
/* update clip source */
detect_clip_source(clip);
@@ -1216,7 +1261,7 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip
scopes->ok = TRUE;
}
-static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, int undistorted)
+static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, int undistorted, bool threaded)
{
char name[FILE_MAX];
int quality, rectx, recty;
@@ -1230,7 +1275,10 @@ static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, i
scaleibuf = IMB_dupImBuf(ibuf);
- IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty);
+ if (threaded)
+ IMB_scaleImBuf_threaded(scaleibuf, (short)rectx, (short)recty);
+ else
+ IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty);
quality = clip->proxy.quality;
scaleibuf->ftype = JPG | quality;
@@ -1239,6 +1287,10 @@ static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, i
if (scaleibuf->planes == 32)
scaleibuf->planes = 24;
+ /* TODO: currently the most weak part of multithreaded proxies,
+ * could be solved in a way that thread only prepares memory
+ * buffer and write to disk happens separately
+ */
BLI_lock_thread(LOCK_MOVIECLIP);
BLI_make_existing_file(name);
@@ -1250,12 +1302,18 @@ static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, i
IMB_freeImBuf(scaleibuf);
}
+/* note: currently used by proxy job for movies, threading happens within single frame
+ * (meaning scaling shall be threaded)
+ */
void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct MovieDistortion *distortion,
int cfra, int *build_sizes, int build_count, int undistorted)
{
ImBuf *ibuf;
MovieClipUser user;
+ if (!build_count)
+ return;
+
user.framenr = cfra;
user.render_flag = 0;
user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL;
@@ -1270,7 +1328,7 @@ void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct Movi
tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf);
for (i = 0; i < build_count; i++)
- movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted);
+ movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, true);
IMB_freeImBuf(ibuf);
@@ -1279,8 +1337,34 @@ void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct Movi
}
}
+/* note: currently used by proxy job for sequences, threading happens within sequence
+ * (different threads handles different frames, no threading within frame is needed)
+ */
+void BKE_movieclip_build_proxy_frame_for_ibuf(MovieClip *clip, ImBuf *ibuf, struct MovieDistortion *distortion,
+ int cfra, int *build_sizes, int build_count, int undistorted)
+{
+ if (!build_count)
+ return;
+
+ if (ibuf) {
+ ImBuf *tmpibuf = ibuf;
+ int i;
+
+ if (undistorted)
+ tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf);
+
+ for (i = 0; i < build_count; i++)
+ movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, false);
+
+ if (tmpibuf != ibuf)
+ IMB_freeImBuf(tmpibuf);
+ }
+}
+
void BKE_movieclip_free(MovieClip *clip)
{
+ BKE_sequencer_clear_movieclip_in_clipboard(clip);
+
free_buffers(clip);
BKE_tracking_free(&clip->tracking);
@@ -1325,7 +1409,7 @@ void BKE_movieclip_unlink(Main *bmain, MovieClip *clip)
bConstraint *con;
for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
bFollowTrackConstraint *data = (bFollowTrackConstraint *) con->data;
@@ -1348,10 +1432,9 @@ void BKE_movieclip_unlink(Main *bmain, MovieClip *clip)
}
}
- {
- bNodeTreeType *treetype = ntreeGetType(NTREE_COMPOSIT);
- treetype->foreach_nodetree(bmain, (void *)clip, &BKE_node_tree_unlink_id_cb);
- }
+ FOREACH_NODETREE(bmain, ntree, id) {
+ BKE_node_tree_unlink_id((ID *)clip, ntree);
+ } FOREACH_NODETREE_END
clip->id.us = 0;
}
@@ -1365,3 +1448,59 @@ float BKE_movieclip_remap_clip_to_scene_frame(MovieClip *clip, float framenr)
{
return framenr + (float) clip->start_frame - 1.0f;
}
+
+void BKE_movieclip_filename_for_frame(MovieClip *clip, MovieClipUser *user, char *name)
+{
+ if (clip->source == MCLIP_SRC_SEQUENCE) {
+ int use_proxy;
+
+ use_proxy = (clip->flag & MCLIP_USE_PROXY) && user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL;
+
+ if (use_proxy) {
+ int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
+ get_proxy_fname(clip, user->render_size, undistort, user->framenr, name);
+ }
+ else {
+ get_sequence_fname(clip, user->framenr, name);
+ }
+ }
+ else {
+ BLI_strncpy(name, clip->name, FILE_MAX);
+ BLI_path_abs(name, ID_BLEND_PATH(G.main, &clip->id));
+ }
+}
+
+ImBuf *BKE_movieclip_anim_ibuf_for_frame(MovieClip *clip, MovieClipUser *user)
+{
+ ImBuf *ibuf = NULL;
+
+ if (clip->source == MCLIP_SRC_MOVIE) {
+ BLI_lock_thread(LOCK_MOVIECLIP);
+ ibuf = movieclip_load_movie_file(clip, user, user->framenr, clip->flag);
+ BLI_unlock_thread(LOCK_MOVIECLIP);
+ }
+
+ return ibuf;
+}
+
+int BKE_movieclip_has_cached_frame(MovieClip *clip, MovieClipUser *user)
+{
+ int has_frame = FALSE;
+
+ BLI_lock_thread(LOCK_MOVIECLIP);
+ has_frame = has_imbuf_cache(clip, user, clip->flag);
+ BLI_unlock_thread(LOCK_MOVIECLIP);
+
+ return has_frame;
+}
+
+int BKE_movieclip_put_frame_if_possible(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf)
+{
+ bool result;
+
+ BLI_lock_thread(LOCK_MOVIECLIP);
+ result = put_imbuf_cache(clip, user, ibuf, clip->flag, false);
+ BLI_unlock_thread(LOCK_MOVIECLIP);
+
+ return result;
+}
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index c737dccc5d2..88f534c581c 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -43,9 +43,9 @@
#include "BLI_bitmap.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLI_pbvh.h"
#include "BLI_utildefines.h"
+#include "BKE_pbvh.h"
#include "BKE_ccg.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_mesh.h"
@@ -310,7 +310,7 @@ MultiresModifierData *find_multires_modifier_before(Scene *scene, ModifierData *
/* used for applying scale on mdisps layer and syncing subdivide levels when joining objects
* use_first - return first multires modifier if all multires'es are disabled
*/
-MultiresModifierData *get_multires_modifier(Scene *scene, Object *ob, int use_first)
+MultiresModifierData *get_multires_modifier(Scene *scene, Object *ob, bool use_first)
{
ModifierData *md;
MultiresModifierData *mmd = NULL, *firstmmd = NULL;
@@ -379,7 +379,7 @@ void multires_force_update(Object *ob)
ob->derivedFinal = NULL;
}
if (ob->sculpt && ob->sculpt->pbvh) {
- BLI_pbvh_free(ob->sculpt->pbvh);
+ BKE_pbvh_free(ob->sculpt->pbvh);
ob->sculpt->pbvh = NULL;
}
}
@@ -1407,7 +1407,7 @@ void multires_stitch_grids(Object *ob)
int totface;
if (ccgdm->pbvh) {
- BLI_pbvh_get_grid_updates(ccgdm->pbvh, 0, (void ***)&faces, &totface);
+ BKE_pbvh_get_grid_updates(ccgdm->pbvh, 0, (void ***)&faces, &totface);
if (totface) {
ccgSubSurf_stitchFaces(ccgdm->ss, 0, faces, totface);
@@ -1559,7 +1559,7 @@ static void old_mdisps_convert(MFace *mface, MDisps *mdisp)
if (S == 1) { (*out)[1] = -(*out)[1]; }
else if (S == 2) { SWAP(float, (*out)[0], (*out)[1]); }
else if (S == 3) { (*out)[0] = -(*out)[0]; }
- else if (S == 0) { SWAP(float, (*out)[0], (*out)[1]); (*out)[0] = -(*out)[0]; (*out)[1] = -(*out)[1]; };
+ else if (S == 0) { SWAP(float, (*out)[0], (*out)[1]); (*out)[0] = -(*out)[0]; (*out)[1] = -(*out)[1]; }
}
}
}
diff --git a/source/blender/blenkernel/intern/navmesh_conversion.c b/source/blender/blenkernel/intern/navmesh_conversion.c
index 3bf5f863557..1d662ae3116 100644
--- a/source/blender/blenkernel/intern/navmesh_conversion.c
+++ b/source/blender/blenkernel/intern/navmesh_conversion.c
@@ -436,7 +436,7 @@ int buildNavMeshDataByDerivedMesh(DerivedMesh *dm, int *vertsPerPoly,
unsigned short **polys, int **dtrisToPolysMap,
int **dtrisToTrisMap, int **trisToFacesMap)
{
- int res = 1;
+ int res;
int ntris = 0, *recastData = NULL;
unsigned short *tris = NULL;
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index 6f585198524..ccae1f606fc 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -1262,7 +1262,7 @@ void BKE_nlastrip_validate_fcurves(NlaStrip *strip)
/* Sanity Validation ------------------------------------ */
-static int nla_editbone_name_check(void *arg, const char *name)
+static bool nla_editbone_name_check(void *arg, const char *name)
{
return BLI_ghash_haskey((GHash *)arg, (void *)name);
}
@@ -1447,9 +1447,9 @@ void BKE_nla_validate_state(AnimData *adt)
if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) {
/* 1) First strip must be set to extend hold, otherwise, stuff before acts dodgy
* 2) Only overwrite extend mode if *not* changing it will most probably result in
- * occlusion problems, which will occur iff
- * - blendmode = REPLACE
- * - all channels the same (this is fiddly to test, so is currently assumed)
+ * occlusion problems, which will occur if...
+ * - blendmode = REPLACE
+ * - all channels the same (this is fiddly to test, so is currently assumed)
*
* Should fix problems such as [#29869]
*/
@@ -1660,7 +1660,7 @@ void BKE_nla_tweakmode_exit(AnimData *adt)
/* Baking Tools ------------------------------------------- */
-static void UNUSED_FUNCTION(BKE_nla_bake) (Scene * scene, ID *UNUSED(id), AnimData * adt, int UNUSED(flag))
+static void UNUSED_FUNCTION(BKE_nla_bake) (Scene *scene, ID *UNUSED(id), AnimData *adt, int UNUSED(flag))
{
/* verify that data is valid
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 17dcf34b71f..788b185c6eb 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -58,133 +58,654 @@
#include "BKE_action.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
+#include "BKE_idprop.h"
#include "BKE_image.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BLI_ghash.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "NOD_socket.h"
+#include "NOD_common.h"
#include "NOD_composite.h"
#include "NOD_shader.h"
#include "NOD_texture.h"
+/* Fallback types for undefined tree, nodes, sockets */
+bNodeTreeType NodeTreeTypeUndefined;
+bNodeType NodeTypeUndefined;
+bNodeSocketType NodeSocketTypeUndefined;
-bNodeTreeType *ntreeGetType(int type)
+
+static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype)
+{
+ bNodeSocketTemplate *sockdef;
+ /* bNodeSocket *sock; */ /* UNUSED */
+
+ if (ntype->inputs) {
+ sockdef = ntype->inputs;
+ while (sockdef->type != -1) {
+ /* sock = */ node_add_socket_from_template(ntree, node, sockdef, SOCK_IN);
+
+ sockdef++;
+ }
+ }
+ if (ntype->outputs) {
+ sockdef = ntype->outputs;
+ while (sockdef->type != -1) {
+ /* sock = */ node_add_socket_from_template(ntree, node, sockdef, SOCK_OUT);
+
+ sockdef++;
+ }
+ }
+}
+
+/* Note: This function is called to initialize node data based on the type.
+ * The bNodeType may not be registered at creation time of the node,
+ * so this can be delayed until the node type gets registered.
+ */
+static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
{
- static bNodeTreeType *types[NUM_NTREE_TYPES];
- static int types_init = 1;
- if (types_init) {
- types[NTREE_SHADER] = &ntreeType_Shader;
- types[NTREE_COMPOSIT] = &ntreeType_Composite;
- types[NTREE_TEXTURE] = &ntreeType_Texture;
- types_init = 0;
+ bNodeType *ntype = node->typeinfo;
+ if (ntype == &NodeTypeUndefined)
+ return;
+
+ /* only do this once */
+ if (node->flag & NODE_INIT)
+ return;
+
+ node->flag = NODE_SELECT | ntype->flag;
+ node->width = ntype->width;
+ node->miniwidth = 42.0f;
+ node->height = ntype->height;
+ node->color[0] = node->color[1] = node->color[2] = 0.608; /* default theme color */
+
+ /* initialize the node name with the node label.
+ * note: do this after the initfunc so nodes get their data set which may be used in naming
+ * (node groups for example) */
+ /* XXX Do not use nodeLabel() here, it returns translated content, which should *only* be used
+ * in UI, *never* in data...
+ * This solution may be a bit rougher than nodeLabel()'s returned string, but it's simpler
+ * than adding a "no translate" flag to this func (and labelfunc() as well). */
+ BLI_strncpy(node->name, ntype->ui_name, NODE_MAXSTR);
+ nodeUniqueName(ntree, node);
+
+ node_add_sockets_from_type(ntree, node, ntype);
+
+ if (ntype->initfunc != NULL)
+ ntype->initfunc(ntree, node);
+
+ /* extra init callback */
+ if (ntype->initfunc_api) {
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
+
+ /* XXX Warning: context can be NULL in case nodes are added in do_versions.
+ * Delayed init is not supported for nodes with context-based initfunc_api atm.
+ */
+ BLI_assert(C != NULL);
+ ntype->initfunc_api(C, &ptr);
}
- if (type >= 0 && type < NUM_NTREE_TYPES) {
- return types[type];
+ node->flag |= NODE_INIT;
+}
+
+static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo)
+{
+ if (typeinfo) {
+ ntree->typeinfo = typeinfo;
+
+ /* deprecated integer type */
+ ntree->type = typeinfo->type;
}
else {
- return NULL;
+ ntree->typeinfo = &NodeTreeTypeUndefined;
+
+ ntree->init &= ~NTREE_TYPE_INIT;
+ }
+}
+
+static void node_set_typeinfo(const struct bContext *C, bNodeTree *ntree, bNode *node, bNodeType *typeinfo)
+{
+ if (typeinfo) {
+ node->typeinfo = typeinfo;
+
+ /* deprecated integer type */
+ node->type = typeinfo->type;
+
+ /* initialize the node if necessary */
+ node_init(C, ntree, node);
}
+ else {
+ node->typeinfo = &NodeTypeUndefined;
+
+ ntree->init &= ~NTREE_TYPE_INIT;
+ }
+}
+
+static void node_socket_set_typeinfo(bNodeTree *ntree, bNodeSocket *sock, bNodeSocketType *typeinfo)
+{
+ if (typeinfo) {
+ sock->typeinfo = typeinfo;
+
+ if (sock->default_value == NULL) {
+ /* initialize the default_value pointer used by standard socket types */
+ node_socket_init_default_value(sock);
+ }
+ }
+ else {
+ sock->typeinfo = &NodeSocketTypeUndefined;
+
+ ntree->init &= ~NTREE_TYPE_INIT;
+ }
+}
+
+/* Set specific typeinfo pointers in all node trees on register/unregister */
+static void update_typeinfo(Main *bmain, const struct bContext *C, bNodeTreeType *treetype, bNodeType *nodetype, bNodeSocketType *socktype, bool unregister)
+{
+ if (!bmain)
+ return;
+
+ FOREACH_NODETREE(bmain, ntree, id) {
+ bNode *node;
+ bNodeSocket *sock;
+
+ ntree->init |= NTREE_TYPE_INIT;
+
+ if (treetype && STREQ(ntree->idname, treetype->idname))
+ ntree_set_typeinfo(ntree, unregister ? NULL : treetype);
+
+ /* initialize nodes */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (nodetype && STREQ(node->idname, nodetype->idname))
+ node_set_typeinfo(C, ntree, node, unregister ? NULL : nodetype);
+
+ /* initialize node sockets */
+ for (sock = node->inputs.first; sock; sock = sock->next)
+ if (socktype && STREQ(sock->idname, socktype->idname))
+ node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype);
+ for (sock = node->outputs.first; sock; sock = sock->next)
+ if (socktype && STREQ(sock->idname, socktype->idname))
+ node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype);
+ }
+
+ /* initialize tree sockets */
+ for (sock = ntree->inputs.first; sock; sock = sock->next)
+ if (socktype && STREQ(sock->idname, socktype->idname))
+ node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype);
+ for (sock = ntree->outputs.first; sock; sock = sock->next)
+ if (socktype && STREQ(sock->idname, socktype->idname))
+ node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype);
+ }
+ FOREACH_NODETREE_END
}
-static bNodeType *node_get_type(bNodeTree *ntree, int type)
+/* Try to initialize all typeinfo in a node tree.
+ * NB: In general undefined typeinfo is a perfectly valid case, the type may just be registered later.
+ * In that case the update_typeinfo function will set typeinfo on registration
+ * and do necessary updates.
+ */
+void ntreeSetTypes(const struct bContext *C, bNodeTree *ntree)
{
- bNodeType *ntype = ntreeGetType(ntree->type)->node_types.first;
- for (; ntype; ntype = ntype->next)
- if (ntype->type == type)
- return ntype;
+ bNode *node;
+ bNodeSocket *sock;
+ ntree->init |= NTREE_TYPE_INIT;
+
+ ntree_set_typeinfo(ntree, ntreeTypeFind(ntree->idname));
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ node_set_typeinfo(C, ntree, node, nodeTypeFind(node->idname));
+
+ for (sock = node->inputs.first; sock; sock = sock->next)
+ node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(sock->idname));
+ for (sock = node->outputs.first; sock; sock = sock->next)
+ node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(sock->idname));
+ }
+
+ for (sock = ntree->inputs.first; sock; sock = sock->next)
+ node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(sock->idname));
+ for (sock = ntree->outputs.first; sock; sock = sock->next)
+ node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(sock->idname));
+}
+
+
+static GHash *nodetreetypes_hash = NULL;
+static GHash *nodetypes_hash = NULL;
+static GHash *nodesockettypes_hash = NULL;
+
+bNodeTreeType *ntreeTypeFind(const char *idname)
+{
+ bNodeTreeType *nt;
+
+ if (idname[0]) {
+ nt = BLI_ghash_lookup(nodetreetypes_hash, idname);
+ if (nt)
+ return nt;
+ }
+
return NULL;
}
-bNodeType *ntreeGetNodeType(bNodeTree *ntree)
+void ntreeTypeAdd(bNodeTreeType *nt)
+{
+ BLI_ghash_insert(nodetreetypes_hash, (void *)nt->idname, nt);
+ /* XXX pass Main to register function? */
+ update_typeinfo(G.main, NULL, nt, NULL, NULL, false);
+}
+
+/* callback for hash value free function */
+static void ntree_free_type(void *treetype_v)
{
- return node_get_type(ntree, ntree->nodetype);
+ bNodeTreeType *treetype = treetype_v;
+ /* XXX pass Main to unregister function? */
+ update_typeinfo(G.main, NULL, treetype, NULL, NULL, true);
+ MEM_freeN(treetype);
}
-bNodeSocketType *ntreeGetSocketType(int type)
+void ntreeTypeFreeLink(bNodeTreeType *nt)
{
- static bNodeSocketType *types[NUM_SOCKET_TYPES] = {NULL};
- static int types_init = 1;
+ BLI_ghash_remove(nodetreetypes_hash, nt->idname, NULL, ntree_free_type);
+}
- if (types_init) {
- node_socket_type_init(types);
- types_init = 0;
+bool ntreeIsRegistered(bNodeTree *ntree)
+{
+ return (ntree->typeinfo != &NodeTreeTypeUndefined);
+}
+
+GHashIterator *ntreeTypeGetIterator(void)
+{
+ return BLI_ghashIterator_new(nodetreetypes_hash);
+}
+
+bNodeType *nodeTypeFind(const char *idname)
+{
+ bNodeType *nt;
+
+ if (idname[0]) {
+ nt = BLI_ghash_lookup(nodetypes_hash, idname);
+ if (nt)
+ return nt;
}
- if (type < NUM_SOCKET_TYPES) {
- return types[type];
+ return NULL;
+}
+
+static void free_dynamic_typeinfo(bNodeType *ntype)
+{
+ if (ntype->type == NODE_DYNAMIC) {
+ if (ntype->inputs) {
+ MEM_freeN(ntype->inputs);
+ }
+ if (ntype->outputs) {
+ MEM_freeN(ntype->outputs);
+ }
+ if (ntype->ui_name) {
+ MEM_freeN((void *)ntype->ui_name);
+ }
}
- else {
- return NULL;
+}
+
+/* callback for hash value free function */
+static void node_free_type(void *nodetype_v)
+{
+ bNodeType *nodetype = nodetype_v;
+ /* XXX pass Main to unregister function? */
+ update_typeinfo(G.main, NULL, NULL, nodetype, NULL, true);
+
+ /* XXX deprecated */
+ if (nodetype->type == NODE_DYNAMIC)
+ free_dynamic_typeinfo(nodetype);
+
+ if (nodetype->needs_free)
+ MEM_freeN(nodetype);
+}
+
+void nodeRegisterType(bNodeType *nt)
+{
+ /* debug only: basic verification of registered types */
+ BLI_assert(nt->idname[0] != '\0');
+ BLI_assert(nt->poll != NULL);
+
+ BLI_ghash_insert(nodetypes_hash, (void *)nt->idname, nt);
+ /* XXX pass Main to register function? */
+ update_typeinfo(G.main, NULL, NULL, nt, NULL, false);
+}
+
+void nodeUnregisterType(bNodeType *nt)
+{
+ BLI_ghash_remove(nodetypes_hash, nt->idname, NULL, node_free_type);
+}
+
+bool nodeIsRegistered(bNode *node)
+{
+ return (node->typeinfo != &NodeTypeUndefined);
+}
+
+GHashIterator *nodeTypeGetIterator(void)
+{
+ return BLI_ghashIterator_new(nodetypes_hash);
+}
+
+bNodeSocketType *nodeSocketTypeFind(const char *idname)
+{
+ bNodeSocketType *st;
+
+ if (idname[0]) {
+ st = BLI_ghash_lookup(nodesockettypes_hash, idname);
+ if (st)
+ return st;
}
+
+ return NULL;
}
-void ntreeInitTypes(bNodeTree *ntree)
+/* callback for hash value free function */
+static void node_free_socket_type(void *socktype_v)
{
- bNode *node, *next;
+ bNodeSocketType *socktype = socktype_v;
+ /* XXX pass Main to unregister function? */
+ update_typeinfo(G.main, NULL, NULL, NULL, socktype, true);
- for (node = ntree->nodes.first; node; node = next) {
- next = node->next;
-
- node->typeinfo = node_get_type(ntree, node->type);
+ MEM_freeN(socktype);
+}
- if (node->typeinfo == NULL) {
- printf("Error: Node type %s doesn't exist anymore, removed\n", node->name);
- nodeFreeNode(ntree, node);
- }
+void nodeRegisterSocketType(bNodeSocketType *st)
+{
+ BLI_ghash_insert(nodesockettypes_hash, (void *)st->idname, st);
+ /* XXX pass Main to register function? */
+ update_typeinfo(G.main, NULL, NULL, NULL, st, false);
+}
+
+void nodeUnregisterSocketType(bNodeSocketType *st)
+{
+ BLI_ghash_remove(nodesockettypes_hash, st->idname, NULL, node_free_socket_type);
+}
+
+bool nodeSocketIsRegistered(bNodeSocket *sock)
+{
+ return (sock->typeinfo != &NodeSocketTypeUndefined);
+}
+
+GHashIterator *nodeSocketTypeGetIterator(void)
+{
+ return BLI_ghashIterator_new(nodesockettypes_hash);
+}
+
+void nodeMakeDynamicType(bNode *UNUSED(node))
+{
+ #if 0 /* XXX deprecated */
+ /* find SH_DYNAMIC_NODE ntype */
+ bNodeType *ntype = ntreeType_Shader->node_types.first;
+ while (ntype) {
+ if (ntype->type == NODE_DYNAMIC)
+ break;
+ ntype = ntype->next;
}
-
- ntree->init |= NTREE_TYPE_INIT;
+
+ /* make own type struct to fill */
+ if (ntype) {
+ /*node->typeinfo= MEM_dupallocN(ntype);*/
+ bNodeType *newtype = MEM_callocN(sizeof(bNodeType), "dynamic bNodeType");
+ *newtype = *ntype;
+ BLI_strncpy(newtype->name, ntype->name, sizeof(newtype->name));
+ node->typeinfo = newtype;
+ }
+ #endif
}
-static bNodeSocket *make_socket(bNodeTree *UNUSED(ntree), int in_out, const char *name, int type)
+struct bNodeSocket *nodeFindSocket(bNode *node, int in_out, const char *identifier)
+{
+ bNodeSocket *sock = (in_out == SOCK_IN ? node->inputs.first : node->outputs.first);
+ for (; sock; sock = sock->next) {
+ if (STREQ(sock->identifier, identifier))
+ return sock;
+ }
+ return NULL;
+}
+
+/* find unique socket identifier */
+static bool unique_identifier_check(void *arg, const char *identifier)
+{
+ struct ListBase *lb = arg;
+ bNodeSocket *sock;
+ for (sock = lb->first; sock; sock = sock->next) {
+ if (STREQ(sock->identifier, identifier))
+ return true;
+ }
+ return false;
+}
+
+static bNodeSocket *make_socket(bNodeTree *ntree, bNode *UNUSED(node), int in_out, ListBase *lb,
+ const char *idname, const char *identifier, const char *name)
{
bNodeSocket *sock;
+ char auto_identifier[MAX_NAME];
+
+ if (identifier && identifier[0] != '\0') {
+ /* use explicit identifier */
+ BLI_strncpy(auto_identifier, identifier, sizeof(auto_identifier));
+ }
+ else {
+ /* if no explicit identifier is given, assign a unique identifier based on the name */
+ BLI_strncpy(auto_identifier, name, sizeof(auto_identifier));
+ }
+ /* make the identifier unique */
+ BLI_uniquename_cb(unique_identifier_check, lb, NULL, '.', auto_identifier, sizeof(auto_identifier));
sock = MEM_callocN(sizeof(bNodeSocket), "sock");
+ sock->in_out = in_out;
- BLI_strncpy(sock->name, name, NODE_MAXSTR);
+ BLI_strncpy(sock->identifier, auto_identifier, NODE_MAXSTR);
sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF);
- sock->type = type;
+
+ BLI_strncpy(sock->name, name, NODE_MAXSTR);
sock->storage = NULL;
sock->flag |= SOCK_COLLAPSED;
+ sock->type = SOCK_CUSTOM; /* int type undefined by default */
- sock->default_value = node_socket_make_default_value(type);
- node_socket_init_default_value(type, sock->default_value);
+ BLI_strncpy(sock->idname, idname, sizeof(sock->idname));
+ node_socket_set_typeinfo(ntree, sock, nodeSocketTypeFind(idname));
return sock;
}
-bNodeSocket *nodeAddSocket(bNodeTree *ntree, bNode *node, int in_out, const char *name, int type)
+bNodeSocket *nodeAddSocket(bNodeTree *ntree, bNode *node, int in_out, const char *idname,
+ const char *identifier, const char *name)
{
- bNodeSocket *sock = make_socket(ntree, in_out, name, type);
- if (in_out == SOCK_IN)
- BLI_addtail(&node->inputs, sock);
- else if (in_out == SOCK_OUT)
- BLI_addtail(&node->outputs, sock);
+ ListBase *lb = (in_out == SOCK_IN ? &node->inputs : &node->outputs);
+ bNodeSocket *sock = make_socket(ntree, node, in_out, lb, idname, identifier, name);
+
+ BLI_remlink(lb, sock); /* does nothing for new socket */
+ BLI_addtail(lb, sock);
node->update |= NODE_UPDATE;
return sock;
}
-bNodeSocket *nodeInsertSocket(bNodeTree *ntree, bNode *node, int in_out, bNodeSocket *next_sock, const char *name, int type)
+bNodeSocket *nodeInsertSocket(bNodeTree *ntree, bNode *node, int in_out, const char *idname,
+ bNodeSocket *next_sock, const char *identifier, const char *name)
{
- bNodeSocket *sock = make_socket(ntree, in_out, name, type);
- if (in_out == SOCK_IN)
- BLI_insertlinkbefore(&node->inputs, next_sock, sock);
- else if (in_out == SOCK_OUT)
- BLI_insertlinkbefore(&node->outputs, next_sock, sock);
+ ListBase *lb = (in_out == SOCK_IN ? &node->inputs : &node->outputs);
+ bNodeSocket *sock = make_socket(ntree, node, in_out, lb, idname, identifier, name);
+
+ BLI_remlink(lb, sock); /* does nothing for new socket */
+ BLI_insertlinkbefore(lb, next_sock, sock);
node->update |= NODE_UPDATE;
return sock;
}
+const char *nodeStaticSocketType(int type, int subtype)
+{
+ switch (type) {
+ case SOCK_FLOAT:
+ switch (subtype) {
+ case PROP_UNSIGNED:
+ return "NodeSocketFloatUnsigned";
+ case PROP_PERCENTAGE:
+ return "NodeSocketFloatPercentage";
+ case PROP_FACTOR:
+ return "NodeSocketFloatFactor";
+ case PROP_ANGLE:
+ return "NodeSocketFloatAngle";
+ case PROP_TIME:
+ return "NodeSocketFloatTime";
+ case PROP_NONE:
+ default:
+ return "NodeSocketFloat";
+ }
+ case SOCK_INT:
+ switch (subtype) {
+ case PROP_UNSIGNED:
+ return "NodeSocketIntUnsigned";
+ case PROP_PERCENTAGE:
+ return "NodeSocketIntPercentage";
+ case PROP_FACTOR:
+ return "NodeSocketIntFactor";
+ case PROP_NONE:
+ default:
+ return "NodeSocketInt";
+ }
+ case SOCK_BOOLEAN:
+ return "NodeSocketBool";
+ case SOCK_VECTOR:
+ switch (subtype) {
+ case PROP_TRANSLATION:
+ return "NodeSocketVectorTranslation";
+ case PROP_DIRECTION:
+ return "NodeSocketVectorDirection";
+ case PROP_VELOCITY:
+ return "NodeSocketVectorVelocity";
+ case PROP_ACCELERATION:
+ return "NodeSocketVectorAcceleration";
+ case PROP_EULER:
+ return "NodeSocketVectorEuler";
+ case PROP_XYZ:
+ return "NodeSocketVectorXYZ";
+ case PROP_NONE:
+ default:
+ return "NodeSocketVector";
+ }
+ case SOCK_RGBA:
+ return "NodeSocketColor";
+ case SOCK_STRING:
+ return "NodeSocketString";
+ case SOCK_SHADER:
+ return "NodeSocketShader";
+ }
+ return NULL;
+}
+
+const char *nodeStaticSocketInterfaceType(int type, int subtype)
+{
+ switch (type) {
+ case SOCK_FLOAT:
+ switch (subtype) {
+ case PROP_UNSIGNED:
+ return "NodeSocketInterfaceFloatUnsigned";
+ case PROP_PERCENTAGE:
+ return "NodeSocketInterfaceFloatPercentage";
+ case PROP_FACTOR:
+ return "NodeSocketInterfaceFloatFactor";
+ case PROP_ANGLE:
+ return "NodeSocketInterfaceFloatAngle";
+ case PROP_TIME:
+ return "NodeSocketInterfaceFloatTime";
+ case PROP_NONE:
+ default:
+ return "NodeSocketInterfaceFloat";
+ }
+ case SOCK_INT:
+ switch (subtype) {
+ case PROP_UNSIGNED:
+ return "NodeSocketInterfaceIntUnsigned";
+ case PROP_PERCENTAGE:
+ return "NodeSocketInterfaceIntPercentage";
+ case PROP_FACTOR:
+ return "NodeSocketInterfaceIntFactor";
+ case PROP_NONE:
+ default:
+ return "NodeSocketInterfaceInt";
+ }
+ case SOCK_BOOLEAN:
+ return "NodeSocketInterfaceBool";
+ case SOCK_VECTOR:
+ switch (subtype) {
+ case PROP_TRANSLATION:
+ return "NodeSocketInterfaceVectorTranslation";
+ case PROP_DIRECTION:
+ return "NodeSocketInterfaceVectorDirection";
+ case PROP_VELOCITY:
+ return "NodeSocketInterfaceVectorVelocity";
+ case PROP_ACCELERATION:
+ return "NodeSocketInterfaceVectorAcceleration";
+ case PROP_EULER:
+ return "NodeSocketInterfaceVectorEuler";
+ case PROP_XYZ:
+ return "NodeSocketInterfaceVectorXYZ";
+ case PROP_NONE:
+ default:
+ return "NodeSocketInterfaceVector";
+ }
+ case SOCK_RGBA:
+ return "NodeSocketInterfaceColor";
+ case SOCK_STRING:
+ return "NodeSocketInterfaceString";
+ case SOCK_SHADER:
+ return "NodeSocketInterfaceShader";
+ }
+ return NULL;
+}
+
+bNodeSocket *nodeAddStaticSocket(bNodeTree *ntree, bNode *node, int in_out, int type, int subtype,
+ const char *identifier, const char *name)
+{
+ const char *idname = nodeStaticSocketType(type, subtype);
+ bNodeSocket *sock;
+
+ if (!idname) {
+ printf("Error: static node socket type %d undefined\n", type);
+ return NULL;
+ }
+
+ sock = nodeAddSocket(ntree, node, in_out, idname, identifier, name);
+ sock->type = type;
+ return sock;
+}
+
+bNodeSocket *nodeInsertStaticSocket(bNodeTree *ntree, bNode *node, int in_out, int type, int subtype,
+ bNodeSocket *next_sock, const char *identifier, const char *name)
+{
+ const char *idname = nodeStaticSocketType(type, subtype);
+ bNodeSocket *sock;
+
+ if (!idname) {
+ printf("Error: static node socket type %d undefined\n", type);
+ return NULL;
+ }
+
+ sock = nodeInsertSocket(ntree, node, in_out, idname, next_sock, identifier, name);
+ sock->type = type;
+ return sock;
+}
+
+static void node_socket_free(bNodeTree *UNUSED(ntree), bNodeSocket *sock, bNode *UNUSED(node))
+{
+ if (sock->prop) {
+ IDP_FreeProperty(sock->prop);
+ MEM_freeN(sock->prop);
+ }
+
+ if (sock->default_value)
+ MEM_freeN(sock->default_value);
+}
+
void nodeRemoveSocket(bNodeTree *ntree, bNode *node, bNodeSocket *sock)
{
bNodeLink *link, *next;
@@ -200,7 +721,7 @@ void nodeRemoveSocket(bNodeTree *ntree, bNode *node, bNodeSocket *sock)
BLI_remlink(&node->inputs, sock);
BLI_remlink(&node->outputs, sock);
- node_socket_free_default_value(sock->type, sock->default_value);
+ node_socket_free(ntree, sock, node);
MEM_freeN(sock);
node->update |= NODE_UPDATE;
@@ -208,7 +729,7 @@ void nodeRemoveSocket(bNodeTree *ntree, bNode *node, bNodeSocket *sock)
void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node)
{
- bNodeSocket *sock;
+ bNodeSocket *sock, *sock_next;
bNodeLink *link, *next;
for (link = ntree->links.first; link; link = next) {
@@ -218,12 +739,16 @@ void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node)
}
}
- for (sock = node->inputs.first; sock; sock = sock->next)
- node_socket_free_default_value(sock->type, sock->default_value);
- BLI_freelistN(&node->inputs);
- for (sock = node->outputs.first; sock; sock = sock->next)
- node_socket_free_default_value(sock->type, sock->default_value);
- BLI_freelistN(&node->outputs);
+ for (sock = node->inputs.first; sock; sock = sock_next) {
+ sock_next = sock->next;
+ node_socket_free(ntree, sock, node);
+ MEM_freeN(sock);
+ }
+ for (sock = node->outputs.first; sock; sock = sock_next) {
+ sock_next = sock->next;
+ node_socket_free(ntree, sock, node);
+ MEM_freeN(sock);
+ }
node->update |= NODE_UPDATE;
}
@@ -235,26 +760,18 @@ bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name)
}
/* finds a node based on given socket */
-int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex, int *in_out)
+int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex)
{
+ int in_out = sock->in_out;
bNode *node;
bNodeSocket *tsock;
int index = 0;
for (node = ntree->nodes.first; node; node = node->next) {
- for (index = 0, tsock = node->inputs.first; tsock; tsock = tsock->next, index++) {
- if (tsock == sock) {
- if (in_out) *in_out = SOCK_IN;
+ tsock = (in_out == SOCK_IN ? node->inputs.first : node->outputs.first);
+ for (index = 0; tsock; tsock = tsock->next, index++) {
+ if (tsock == sock)
break;
- }
- }
- if (tsock)
- break;
- for (index = 0, tsock = node->outputs.first; tsock; tsock = tsock->next, index++) {
- if (tsock == sock) {
- if (in_out) *in_out = SOCK_OUT;
- break;
- }
}
if (tsock)
break;
@@ -271,28 +788,6 @@ int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockin
}
/* ************** Add stuff ********** */
-static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype)
-{
- bNodeSocketTemplate *sockdef;
- /* bNodeSocket *sock; */ /* UNUSED */
-
- if (ntype->inputs) {
- sockdef = ntype->inputs;
- while (sockdef->type != -1) {
- /* sock = */ node_add_input_from_template(ntree, node, sockdef);
-
- sockdef++;
- }
- }
- if (ntype->outputs) {
- sockdef = ntype->outputs;
- while (sockdef->type != -1) {
- /* sock = */ node_add_output_from_template(ntree, node, sockdef);
-
- sockdef++;
- }
- }
-}
/* Find the first available, non-duplicate name for a given node */
void nodeUniqueName(bNodeTree *ntree, bNode *node)
@@ -300,51 +795,55 @@ void nodeUniqueName(bNodeTree *ntree, bNode *node)
BLI_uniquename(&ntree->nodes, node, "Node", '.', offsetof(bNode, name), sizeof(node->name));
}
-bNode *nodeAddNode(bNodeTree *ntree, struct bNodeTemplate *ntemp)
+bNode *nodeAddNode(const struct bContext *C, bNodeTree *ntree, const char *idname)
{
bNode *node;
- bNodeType *ntype;
-
- ntype = node_get_type(ntree, ntemp->type);
- if (ntype == NULL) {
- printf("nodeAddNodeType() error: '%d' type invalid\n", ntemp->type);
- return NULL;
- }
- /* validity check */
- if (!nodeValid(ntree, ntemp))
- return NULL;
node = MEM_callocN(sizeof(bNode), "new node");
- node->type = ntype->type;
- node->typeinfo = ntype;
- node->flag = NODE_SELECT | ntype->flag;
- node->width = ntype->width;
- node->miniwidth = 42.0f;
- node->height = ntype->height;
- node->color[0] = node->color[1] = node->color[2] = 0.608; /* default theme color */
-
- node_add_sockets_from_type(ntree, node, ntype);
-
BLI_addtail(&ntree->nodes, node);
- if (ntype->initfunc != NULL)
- ntype->initfunc(ntree, node, ntemp);
-
- /* initialize the node name with the node label.
- * note: do this after the initfunc so nodes get their data set which may be used in naming
- * (node groups for example) */
- /* XXX Do not use nodeLabel() here, it returns translated content, which should *only* be used
- * in UI, *never* in data...
- * This solution may be a bit rougher than nodeLabel()'s returned string, but it's simpler
- * than adding a "no translate" flag to this func (and labelfunc() as well). */
- BLI_strncpy(node->name, node->typeinfo->name, NODE_MAXSTR);
- nodeUniqueName(ntree, node);
+ BLI_strncpy(node->idname, idname, sizeof(node->idname));
+ node_set_typeinfo(C, ntree, node, nodeTypeFind(idname));
ntree->update |= NTREE_UPDATE_NODES;
return node;
}
+bNode *nodeAddStaticNode(const struct bContext *C, bNodeTree *ntree, int type)
+{
+ const char *idname = NULL;
+
+ NODE_TYPES_BEGIN(ntype)
+ if (ntype->type == type) {
+ idname = ntype->idname;
+ break;
+ }
+ NODE_TYPES_END
+ if (!idname) {
+ printf("Error: static node type %d undefined\n", type);
+ return NULL;
+ }
+ return nodeAddNode(C, ntree, idname);
+}
+
+static void node_socket_copy(bNodeSocket *dst, bNodeSocket *src)
+{
+ src->new_sock = dst;
+
+ if (src->prop)
+ dst->prop = IDP_CopyProperty(src->prop);
+
+ if (src->default_value)
+ dst->default_value = MEM_dupallocN(src->default_value);
+
+ dst->stack_index = 0;
+ /* XXX some compositor node (e.g. image, render layers) still store
+ * some persistent buffer data here, need to clear this to avoid dangling pointers.
+ */
+ dst->cache = NULL;
+}
+
/* keep socket listorder identical, for copying links */
/* ntree is the target tree */
bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
@@ -363,33 +862,16 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
BLI_duplicatelist(&nnode->inputs, &node->inputs);
oldsock = node->inputs.first;
- for (sock = nnode->inputs.first; sock; sock = sock->next, oldsock = oldsock->next) {
- oldsock->new_sock = sock;
- sock->stack_index = 0;
-
- sock->default_value = node_socket_make_default_value(oldsock->type);
- node_socket_copy_default_value(oldsock->type, sock->default_value, oldsock->default_value);
-
- /* XXX some compositor node (e.g. image, render layers) still store
- * some persistent buffer data here, need to clear this to avoid dangling pointers.
- */
- sock->cache = NULL;
- }
+ for (sock = nnode->inputs.first; sock; sock = sock->next, oldsock = oldsock->next)
+ node_socket_copy(sock, oldsock);
BLI_duplicatelist(&nnode->outputs, &node->outputs);
oldsock = node->outputs.first;
- for (sock = nnode->outputs.first; sock; sock = sock->next, oldsock = oldsock->next) {
- oldsock->new_sock = sock;
- sock->stack_index = 0;
-
- sock->default_value = node_socket_make_default_value(oldsock->type);
- node_socket_copy_default_value(oldsock->type, sock->default_value, oldsock->default_value);
-
- /* XXX some compositor node (e.g. image, render layers) still store
- * some persistent buffer data here, need to clear this to avoid dangling pointers.
- */
- sock->cache = NULL;
- }
+ for (sock = nnode->outputs.first; sock; sock = sock->next, oldsock = oldsock->next)
+ node_socket_copy(sock, oldsock);
+
+ if (node->prop)
+ nnode->prop = IDP_CopyProperty(node->prop);
BLI_duplicatelist(&nnode->internal_links, &node->internal_links);
oldlink = node->internal_links.first;
@@ -402,22 +884,17 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
/* don't increase node->id users, freenode doesn't decrement either */
- if (node->typeinfo->copystoragefunc)
- node->typeinfo->copystoragefunc(node, nnode);
+ if (node->typeinfo->copyfunc)
+ node->typeinfo->copyfunc(ntree, nnode, node);
node->new_node = nnode;
nnode->new_node = NULL;
- /* only shader nodes get pleasant preview updating this way, compo uses own system */
- if (node->preview) {
- if (ntree && (ntree->type == NTREE_SHADER)) {
- nnode->preview = MEM_dupallocN(node->preview);
- if (node->preview->rect)
- nnode->preview->rect = MEM_dupallocN(node->preview->rect);
- }
- else {
- nnode->preview = NULL;
- }
+ if (nnode->typeinfo->copyfunc_api) {
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_Node, nnode, &ptr);
+
+ nnode->typeinfo->copyfunc_api(&ptr, node);
}
if (ntree)
@@ -429,71 +906,13 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
/* also used via rna api, so we check for proper input output direction */
bNodeLink *nodeAddLink(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
{
- bNodeSocket *sock;
bNodeLink *link = NULL;
- int from = 0, to = 0;
- if (fromnode) {
- /* test valid input */
- for (sock = fromnode->outputs.first; sock; sock = sock->next)
- if (sock == fromsock)
- break;
- if (sock)
- from = 1; /* OK */
- else {
- for (sock = fromnode->inputs.first; sock; sock = sock->next)
- if (sock == fromsock)
- break;
- if (sock)
- from = -1; /* OK but flip */
- }
- }
- else if (ntree) {
- /* check tree sockets */
- for (sock = ntree->inputs.first; sock; sock = sock->next)
- if (sock == fromsock)
- break;
- if (sock)
- from = 1; /* OK */
- else {
- for (sock = ntree->outputs.first; sock; sock = sock->next)
- if (sock == fromsock)
- break;
- if (sock)
- from = -1; /* OK but flip */
- }
- }
- if (tonode) {
- for (sock = tonode->inputs.first; sock; sock = sock->next)
- if (sock == tosock)
- break;
- if (sock)
- to = 1; /* OK */
- else {
- for (sock = tonode->outputs.first; sock; sock = sock->next)
- if (sock == tosock)
- break;
- if (sock)
- to = -1; /* OK but flip */
- }
- }
- else if (ntree) {
- /* check tree sockets */
- for (sock = ntree->outputs.first; sock; sock = sock->next)
- if (sock == tosock)
- break;
- if (sock)
- to = 1; /* OK */
- else {
- for (sock = ntree->inputs.first; sock; sock = sock->next)
- if (sock == tosock)
- break;
- if (sock)
- to = -1; /* OK but flip */
- }
- }
+ /* test valid input */
+ BLI_assert(fromnode);
+ BLI_assert(tonode);
- if (from >= 0 && to >= 0) {
+ if (fromsock->in_out == SOCK_OUT && tosock->in_out == SOCK_IN) {
link = MEM_callocN(sizeof(bNodeLink), "link");
if (ntree)
BLI_addtail(&ntree->links, link);
@@ -502,7 +921,8 @@ bNodeLink *nodeAddLink(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock,
link->tonode = tonode;
link->tosock = tosock;
}
- else if (from <= 0 && to <= 0) {
+ else if (fromsock->in_out == SOCK_IN && tosock->in_out == SOCK_OUT) {
+ /* OK but flip */
link = MEM_callocN(sizeof(bNodeLink), "link");
if (ntree)
BLI_addtail(&ntree->links, link);
@@ -546,6 +966,11 @@ void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
ntree->update |= NTREE_UPDATE_LINKS;
}
+int nodeLinkIsHidden(bNodeLink *link)
+{
+ return nodeSocketIsHidden(link->fromsock) || nodeSocketIsHidden(link->tosock);
+}
+
void nodeInternalRelink(bNodeTree *ntree, bNode *node)
{
bNodeLink *link, *link_next;
@@ -571,6 +996,12 @@ void nodeInternalRelink(bNodeTree *ntree, bNode *node)
link->fromnode = fromlink->fromnode;
link->fromsock = fromlink->fromsock;
+ /* if the up- or downstream link is invalid,
+ * the replacement link will be invalid too.
+ */
+ if (!(fromlink->flag & NODE_LINK_VALID))
+ link->flag &= ~NODE_LINK_VALID;
+
ntree->update |= NTREE_UPDATE_LINKS;
}
else
@@ -656,30 +1087,29 @@ void nodeDetachNode(struct bNode *node)
}
}
-bNodeTree *ntreeAddTree(const char *name, int type, int nodetype)
+bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
{
bNodeTree *ntree;
- bNodeType *ntype;
- /* trees are created as local trees if they of compositor, material or texture type,
+ /* trees are created as local trees for compositor, material or texture nodes,
* node groups and other tree types are created as library data.
*/
- if (ELEM3(type, NTREE_COMPOSIT, NTREE_SHADER, NTREE_TEXTURE) && nodetype == 0) {
+ if (bmain) {
+ ntree = BKE_libblock_alloc(&bmain->nodetree, ID_NT, name);
+ }
+ else {
ntree = MEM_callocN(sizeof(bNodeTree), "new node tree");
- *( (short *)ntree->id.name) = ID_NT; /* not "type", as that is ntree->type */
+ *( (short *)ntree->id.name ) = ID_NT;
BLI_strncpy(ntree->id.name + 2, name, sizeof(ntree->id.name));
}
- else
- ntree = BKE_libblock_alloc(&G.main->nodetree, ID_NT, name);
-
- ntree->type = type;
- ntree->nodetype = nodetype;
- ntreeInitTypes(ntree);
+ /* Types are fully initialized at this point,
+ * if an undefined node is added later this will be reset.
+ */
+ ntree->init |= NTREE_TYPE_INIT;
- ntype = node_get_type(ntree, ntree->nodetype);
- if (ntype && ntype->inittreefunc)
- ntype->inittreefunc(ntree);
+ BLI_strncpy(ntree->idname, idname, sizeof(ntree->idname));
+ ntree_set_typeinfo(ntree, ntreeTypeFind(idname));
return ntree;
}
@@ -693,12 +1123,12 @@ bNodeTree *ntreeAddTree(const char *name, int type, int nodetype)
* copying for internal use (threads for eg), where you wont want it to modify the
* scene data.
*/
-static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_user, const short do_make_extern)
+static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_user, const short do_make_extern, const short copy_previews)
{
bNodeTree *newtree;
bNode *node /*, *nnode */ /* UNUSED */, *last;
+ bNodeSocket *sock, *oldsock;
bNodeLink *link;
- bNodeSocket *gsock, *oldgsock;
if (ntree == NULL) return NULL;
@@ -710,7 +1140,7 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_use
}
else {
newtree = MEM_dupallocN(ntree);
- BKE_libblock_copy_data(&newtree->id, &ntree->id, TRUE); /* copy animdata and ID props */
+ BKE_libblock_copy_data(&newtree->id, &ntree->id, true); /* copy animdata and ID props */
}
id_us_plus((ID *)newtree->gpd);
@@ -741,22 +1171,6 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_use
break;
}
- /* socket definition for group usage */
- BLI_duplicatelist(&newtree->inputs, &ntree->inputs);
- for (gsock = newtree->inputs.first, oldgsock = ntree->inputs.first; gsock; gsock = gsock->next, oldgsock = oldgsock->next) {
- oldgsock->new_sock = gsock;
- gsock->groupsock = (oldgsock->groupsock ? oldgsock->groupsock->new_sock : NULL);
- gsock->default_value = node_socket_make_default_value(oldgsock->type);
- node_socket_copy_default_value(oldgsock->type, gsock->default_value, oldgsock->default_value);
- }
- BLI_duplicatelist(&newtree->outputs, &ntree->outputs);
- for (gsock = newtree->outputs.first, oldgsock = ntree->outputs.first; gsock; gsock = gsock->next, oldgsock = oldgsock->next) {
- oldgsock->new_sock = gsock;
- gsock->groupsock = (oldgsock->groupsock ? oldgsock->groupsock->new_sock : NULL);
- gsock->default_value = node_socket_make_default_value(oldgsock->type);
- node_socket_copy_default_value(oldgsock->type, gsock->default_value, oldgsock->default_value);
- }
-
/* copy links */
BLI_duplicatelist(&newtree->links, &ntree->links);
for (link = newtree->links.first; link; link = link->next) {
@@ -769,18 +1183,47 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_use
link->tosock->link = link;
}
+ /* copy interface sockets */
+ BLI_duplicatelist(&newtree->inputs, &ntree->inputs);
+ oldsock = ntree->inputs.first;
+ for (sock = newtree->inputs.first; sock; sock = sock->next, oldsock = oldsock->next)
+ node_socket_copy(sock, oldsock);
+
+ BLI_duplicatelist(&newtree->outputs, &ntree->outputs);
+ oldsock = ntree->outputs.first;
+ for (sock = newtree->outputs.first; sock; sock = sock->next, oldsock = oldsock->next)
+ node_socket_copy(sock, oldsock);
+
+ /* copy preview hash */
+ if (ntree->previews && copy_previews) {
+ bNodeInstanceHashIterator iter;
+
+ newtree->previews = BKE_node_instance_hash_new("node previews");
+
+ NODE_INSTANCE_HASH_ITER(iter, ntree->previews) {
+ bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
+ bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
+ BKE_node_instance_hash_insert(newtree->previews, key, BKE_node_preview_copy(preview));
+ }
+ }
+ else
+ newtree->previews = NULL;
+
/* update node->parent pointers */
for (node = newtree->nodes.first; node; node = node->next) {
if (node->parent)
node->parent = node->parent->new_node;
}
+ /* node tree will generate its own interface type */
+ ntree->interface_type = NULL;
+
return newtree;
}
bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, const short do_id_user)
{
- return ntreeCopyTree_internal(ntree, do_id_user, TRUE);
+ return ntreeCopyTree_internal(ntree, do_id_user, TRUE, TRUE);
}
bNodeTree *ntreeCopyTree(bNodeTree *ntree)
{
@@ -829,62 +1272,245 @@ void ntreeUserDecrefID(bNodeTree *ntree)
}
}
-/* *************** preview *********** */
-/* if node->preview, then we assume the rect to exist */
+/* *************** Node Preview *********** */
-void nodeFreePreview(bNode *node)
+/* XXX this should be removed eventually ...
+ * Currently BKE functions are modelled closely on previous code,
+ * using BKE_node_preview_init_tree to set up previews for a whole node tree in advance.
+ * This should be left more to the individual node tree implementations.
+ */
+int BKE_node_preview_used(bNode *node)
{
- if (node->preview) {
- if (node->preview->rect)
- MEM_freeN(node->preview->rect);
- MEM_freeN(node->preview);
- node->preview = NULL;
- }
+ /* XXX check for closed nodes? */
+ return (node->typeinfo->flag & NODE_PREVIEW) != 0;
}
-static void node_init_preview(bNode *node, int xsize, int ysize)
+bNodePreview *BKE_node_preview_verify(bNodeInstanceHash *previews, bNodeInstanceKey key, int xsize, int ysize, int create)
{
+ bNodePreview *preview;
- if (node->preview == NULL) {
- node->preview = MEM_callocN(sizeof(bNodePreview), "node preview");
- // printf("added preview %s\n", node->name);
+ preview = BKE_node_instance_hash_lookup(previews, key);
+ if (!preview) {
+ if (create) {
+ preview = MEM_callocN(sizeof(bNodePreview), "node preview");
+ BKE_node_instance_hash_insert(previews, key, preview);
+ }
+ else
+ return NULL;
}
/* node previews can get added with variable size this way */
if (xsize == 0 || ysize == 0)
- return;
+ return preview;
/* sanity checks & initialize */
- if (node->preview->rect) {
- if (node->preview->xsize != xsize && node->preview->ysize != ysize) {
- MEM_freeN(node->preview->rect);
- node->preview->rect = NULL;
+ if (preview->rect) {
+ if (preview->xsize != xsize || preview->ysize != ysize) {
+ MEM_freeN(preview->rect);
+ preview->rect = NULL;
}
}
- if (node->preview->rect == NULL) {
- node->preview->rect = MEM_callocN(4 * xsize + xsize * ysize * sizeof(char) * 4, "node preview rect");
- node->preview->xsize = xsize;
- node->preview->ysize = ysize;
+ if (preview->rect == NULL) {
+ preview->rect = MEM_callocN(4 * xsize + xsize * ysize * sizeof(char) * 4, "node preview rect");
+ preview->xsize = xsize;
+ preview->ysize = ysize;
}
/* no clear, makes nicer previews */
+
+ return preview;
+}
+
+bNodePreview *BKE_node_preview_copy(bNodePreview *preview)
+{
+ bNodePreview *new_preview = MEM_dupallocN(preview);
+ if (preview->rect)
+ new_preview->rect = MEM_dupallocN(preview->rect);
+ return new_preview;
}
-void ntreeInitPreview(bNodeTree *ntree, int xsize, int ysize)
+void BKE_node_preview_free(bNodePreview *preview)
+{
+ if (preview->rect)
+ MEM_freeN(preview->rect);
+ MEM_freeN(preview);
+}
+
+static void node_preview_init_tree_recursive(bNodeInstanceHash *previews, bNodeTree *ntree, bNodeInstanceKey parent_key, int xsize, int ysize, int create)
{
bNode *node;
-
- if (ntree == NULL)
+ for (node = ntree->nodes.first; node; node = node->next) {
+ bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node);
+
+ if (BKE_node_preview_used(node)) {
+ node->preview_xsize = xsize;
+ node->preview_ysize = ysize;
+
+ BKE_node_preview_verify(previews, key, xsize, ysize, create);
+ }
+
+ if (node->type == NODE_GROUP && node->id)
+ node_preview_init_tree_recursive(previews, (bNodeTree *)node->id, key, xsize, ysize, create);
+ }
+}
+
+void BKE_node_preview_init_tree(bNodeTree *ntree, int xsize, int ysize, int create_previews)
+{
+ if (!ntree)
return;
+ if (!ntree->previews)
+ ntree->previews = BKE_node_instance_hash_new("node previews");
+
+ node_preview_init_tree_recursive(ntree->previews, ntree, NODE_INSTANCE_KEY_BASE, xsize, ysize, create_previews);
+}
+
+static void node_preview_tag_used_recursive(bNodeInstanceHash *previews, bNodeTree *ntree, bNodeInstanceKey parent_key)
+{
+ bNode *node;
for (node = ntree->nodes.first; node; node = node->next) {
- if (node->typeinfo->flag & NODE_PREVIEW) /* hrms, check for closed nodes? */
- node_init_preview(node, xsize, ysize);
- if (node->type == NODE_GROUP && (node->flag & NODE_GROUP_EDIT))
- ntreeInitPreview((bNodeTree *)node->id, xsize, ysize);
+ bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node);
+
+ if (BKE_node_preview_used(node))
+ BKE_node_instance_hash_tag_key(previews, key);
+
+ if (node->type == NODE_GROUP && node->id)
+ node_preview_tag_used_recursive(previews, (bNodeTree *)node->id, key);
+ }
+}
+
+void BKE_node_preview_remove_unused(bNodeTree *ntree)
+{
+ if (!ntree || !ntree->previews)
+ return;
+
+ /* use the instance hash functions for tagging and removing unused previews */
+ BKE_node_instance_hash_clear_tags(ntree->previews);
+ node_preview_tag_used_recursive(ntree->previews, ntree, NODE_INSTANCE_KEY_BASE);
+
+ BKE_node_instance_hash_remove_untagged(ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free);
+}
+
+void BKE_node_preview_free_tree(bNodeTree *ntree)
+{
+ if (!ntree)
+ return;
+
+ if (ntree->previews) {
+ BKE_node_instance_hash_free(ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free);
+ ntree->previews = NULL;
}
}
+void BKE_node_preview_clear(bNodePreview *preview)
+{
+ if (preview && preview->rect)
+ memset(preview->rect, 0, MEM_allocN_len(preview->rect));
+}
+
+void BKE_node_preview_clear_tree(bNodeTree *ntree)
+{
+ bNodeInstanceHashIterator iter;
+
+ if (!ntree || !ntree->previews)
+ return;
+
+ NODE_INSTANCE_HASH_ITER(iter, ntree->previews) {
+ bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
+ BKE_node_preview_clear(preview);
+ }
+}
+
+static void node_preview_sync(bNodePreview *to, bNodePreview *from)
+{
+ /* sizes should have been initialized by BKE_node_preview_init_tree */
+ BLI_assert(to->xsize == from->xsize && to->ysize == from->ysize);
+
+ /* copy over contents of previews */
+ 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);
+ }
+}
+
+void BKE_node_preview_sync_tree(bNodeTree *to_ntree, bNodeTree *from_ntree)
+{
+ bNodeInstanceHash *from_previews = from_ntree->previews;
+ bNodeInstanceHash *to_previews = to_ntree->previews;
+ bNodeInstanceHashIterator iter;
+
+ if (!from_previews || !to_previews)
+ return;
+
+ NODE_INSTANCE_HASH_ITER(iter, from_previews) {
+ bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
+ bNodePreview *from = BKE_node_instance_hash_iterator_get_value(&iter);
+ bNodePreview *to = BKE_node_instance_hash_lookup(to_previews, key);
+
+ if (from && to)
+ node_preview_sync(to, from);
+ }
+}
+
+void BKE_node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree, bool remove_old)
+{
+ if (remove_old || !to_ntree->previews) {
+ /* free old previews */
+ if (to_ntree->previews)
+ BKE_node_instance_hash_free(to_ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free);
+
+ /* transfer previews */
+ to_ntree->previews = from_ntree->previews;
+ from_ntree->previews = NULL;
+
+ /* clean up, in case any to_ntree nodes have been removed */
+ BKE_node_preview_remove_unused(to_ntree);
+ }
+ else {
+ bNodeInstanceHashIterator iter;
+
+ if (from_ntree->previews) {
+ NODE_INSTANCE_HASH_ITER(iter, from_ntree->previews) {
+ bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
+ bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
+
+ /* replace existing previews */
+ BKE_node_instance_hash_remove(to_ntree->previews, key, (bNodeInstanceValueFP)BKE_node_preview_free);
+ BKE_node_instance_hash_insert(to_ntree->previews, key, preview);
+ }
+
+ /* Note: NULL free function here, because pointers have already been moved over to to_ntree->previews! */
+ BKE_node_instance_hash_free(from_ntree->previews, NULL);
+ from_ntree->previews = NULL;
+ }
+ }
+}
+
+/* hack warning! this function is only used for shader previews, and
+ * since it gets called multiple times per pixel for Ztransp we only
+ * add the color once. Preview gets cleared before it starts render though */
+void BKE_node_preview_set_pixel(bNodePreview *preview, const float col[4], int x, int y, int do_manage)
+{
+ if (preview) {
+ if (x >= 0 && y >= 0) {
+ if (x < preview->xsize && y < preview->ysize) {
+ unsigned char *tar = preview->rect + 4 * ((preview->xsize * y) + x);
+
+ if (do_manage) {
+ linearrgb_to_srgb_uchar4(tar, col);
+ }
+ else {
+ rgba_float_to_uchar(tar, col);
+ }
+ }
+ //else printf("prv out bound x y %d %d\n", x, y);
+ }
+ //else printf("prv out bound x y %d %d\n", x, y);
+ }
+}
+
+#if 0
static void nodeClearPreview(bNode *node)
{
if (node->preview && node->preview->rect)
@@ -902,7 +1528,7 @@ void ntreeClearPreview(bNodeTree *ntree)
for (node = ntree->nodes.first; node; node = node->next) {
if (node->typeinfo->flag & NODE_PREVIEW)
nodeClearPreview(node);
- if (node->type == NODE_GROUP && (node->flag & NODE_GROUP_EDIT))
+ if (node->type == NODE_GROUP)
ntreeClearPreview((bNodeTree *)node->id);
}
}
@@ -930,6 +1556,7 @@ void nodeAddToPreview(bNode *node, const float col[4], int x, int y, int do_mana
//else printf("prv out bound x y %d %d\n", x, y);
}
}
+#endif
/* ************** Free stuff ********** */
@@ -979,39 +1606,54 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock, *nextsock;
+ /* extra free callback */
+ if (node->typeinfo && node->typeinfo->freefunc_api) {
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
+
+ node->typeinfo->freefunc_api(&ptr);
+ }
+
+ /* since it is called while free database, node->id is undefined */
+
/* can be called for nodes outside a node tree (e.g. clipboard) */
if (ntree) {
- bNodeTreeType *treetype = ntreeGetType(ntree->type);
-
/* remove all references to this node */
nodeUnlinkNode(ntree, node);
node_unlink_attached(ntree, node);
-
+
BLI_remlink(&ntree->nodes, node);
-
- if (treetype->free_node_cache)
- treetype->free_node_cache(ntree, node);
+
+ if (ntree->typeinfo && ntree->typeinfo->free_node_cache)
+ ntree->typeinfo->free_node_cache(ntree, node);
+
+ /* texture node has bad habit of keeping exec data around */
+ if (ntree->type == NTREE_TEXTURE && ntree->execdata) {
+ ntreeTexEndExecTree(ntree->execdata);
+ ntree->execdata = NULL;
+ }
+
+ if (node->typeinfo && node->typeinfo->freefunc)
+ node->typeinfo->freefunc(node);
}
- /* since it is called while free database, node->id is undefined */
-
- if (node->typeinfo && node->typeinfo->freestoragefunc)
- node->typeinfo->freestoragefunc(node);
-
for (sock = node->inputs.first; sock; sock = nextsock) {
nextsock = sock->next;
- node_socket_free_default_value(sock->type, sock->default_value);
+ node_socket_free(ntree, sock, node);
MEM_freeN(sock);
}
for (sock = node->outputs.first; sock; sock = nextsock) {
nextsock = sock->next;
- node_socket_free_default_value(sock->type, sock->default_value);
+ node_socket_free(ntree, sock, node);
MEM_freeN(sock);
}
BLI_freelistN(&node->internal_links);
- nodeFreePreview(node);
+ if (node->prop) {
+ IDP_FreeProperty(node->prop);
+ MEM_freeN(node->prop);
+ }
MEM_freeN(node);
@@ -1019,12 +1661,24 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
ntree->update |= NTREE_UPDATE_NODES;
}
+static void node_socket_interface_free(bNodeTree *UNUSED(ntree), bNodeSocket *sock)
+{
+ if (sock->prop) {
+ IDP_FreeProperty(sock->prop);
+ MEM_freeN(sock->prop);
+ }
+
+ /* can be left over from old files */
+ if (sock->default_value)
+ MEM_freeN(sock->default_value);
+}
+
/* do not free ntree itself here, BKE_libblock_free calls this function too */
void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user)
{
bNodeTree *tntree;
bNode *node, *next;
- bNodeSocket *sock;
+ bNodeSocket *sock, *nextsock;
if (ntree == NULL) return;
@@ -1035,18 +1689,19 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user)
*/
if (ntree->execdata) {
switch (ntree->type) {
- case NTREE_COMPOSIT:
- ntreeCompositEndExecTree(ntree->execdata, 1);
- break;
case NTREE_SHADER:
- ntreeShaderEndExecTree(ntree->execdata, 1);
+ ntreeShaderEndExecTree(ntree->execdata);
break;
case NTREE_TEXTURE:
- ntreeTexEndExecTree(ntree->execdata, 1);
+ ntreeTexEndExecTree(ntree->execdata);
+ ntree->execdata = NULL;
break;
}
}
+ /* unregister associated RNA types */
+ ntreeInterfaceTypeFree(ntree);
+
BKE_free_animdata((ID *)ntree);
id_us_min((ID *)ntree->gpd);
@@ -1072,13 +1727,23 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user)
nodeFreeNode(ntree, node);
}
+
+ /* free interface sockets */
+ for (sock = ntree->inputs.first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ node_socket_interface_free(ntree, sock);
+ MEM_freeN(sock);
+ }
+ for (sock = ntree->outputs.first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ node_socket_interface_free(ntree, sock);
+ MEM_freeN(sock);
+ }
- for (sock = ntree->inputs.first; sock; sock = sock->next)
- node_socket_free_default_value(sock->type, sock->default_value);
- BLI_freelistN(&ntree->inputs);
- for (sock = ntree->outputs.first; sock; sock = sock->next)
- node_socket_free_default_value(sock->type, sock->default_value);
- BLI_freelistN(&ntree->outputs);
+ /* free preview hash */
+ if (ntree->previews) {
+ BKE_node_instance_hash_free(ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free);
+ }
/* if ntree is not part of library, free the libblock data explicitly */
for (tntree = G.main->nodetree.first; tntree; tntree = tntree->id.next)
@@ -1096,13 +1761,10 @@ void ntreeFreeTree(bNodeTree *ntree)
void ntreeFreeCache(bNodeTree *ntree)
{
- bNodeTreeType *treetype;
-
if (ntree == NULL) return;
- treetype = ntreeGetType(ntree->type);
- if (treetype->free_cache)
- treetype->free_cache(ntree);
+ if (ntree->typeinfo->free_cache)
+ ntree->typeinfo->free_cache(ntree);
}
void ntreeSetOutput(bNodeTree *ntree)
@@ -1152,6 +1814,24 @@ void ntreeSetOutput(bNodeTree *ntree)
if (output == 0)
node->flag |= NODE_DO_OUTPUT;
}
+
+ /* group node outputs use this flag too */
+ if (node->type == NODE_GROUP_OUTPUT) {
+ bNode *tnode;
+ int output = 0;
+
+ for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
+ if (tnode->type == NODE_GROUP_OUTPUT) {
+ if (tnode->flag & NODE_DO_OUTPUT) {
+ output++;
+ if (output > 1)
+ tnode->flag &= ~NODE_DO_OUTPUT;
+ }
+ }
+ }
+ if (output == 0)
+ node->flag |= NODE_DO_OUTPUT;
+ }
}
/* here we could recursively set which nodes have to be done,
@@ -1161,61 +1841,19 @@ void ntreeSetOutput(bNodeTree *ntree)
bNodeTree *ntreeFromID(ID *id)
{
switch (GS(id->name)) {
- case ID_MA: return ((Material*)id)->nodetree;
- case ID_LA: return ((Lamp*)id)->nodetree;
- case ID_WO: return ((World*)id)->nodetree;
- case ID_TE: return ((Tex*)id)->nodetree;
- case ID_SCE: return ((Scene*)id)->nodetree;
+ case ID_MA: return ((Material *)id)->nodetree;
+ case ID_LA: return ((Lamp *)id)->nodetree;
+ case ID_WO: return ((World *)id)->nodetree;
+ case ID_TE: return ((Tex *)id)->nodetree;
+ case ID_SCE: return ((Scene *)id)->nodetree;
default: return NULL;
}
}
-typedef struct MakeLocalCallData {
- ID *group_id;
- ID *new_id;
- int lib, local;
-} MakeLocalCallData;
-
-static void ntreeMakeLocal_CheckLocal(void *calldata, ID *owner_id, bNodeTree *ntree)
-{
- MakeLocalCallData *cd = (MakeLocalCallData *)calldata;
- bNode *node;
-
- /* find if group is in tree */
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->id == cd->group_id) {
- if (owner_id->lib) {
- cd->lib = TRUE;
- }
- else {
- cd->local = TRUE;
- }
- }
- }
-}
-
-static void ntreeMakeLocal_LinkNew(void *calldata, ID *owner_id, bNodeTree *ntree)
-{
- MakeLocalCallData *cd = (MakeLocalCallData *)calldata;
- bNode *node;
-
- /* find if group is in tree */
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->id == cd->group_id) {
- if (owner_id->lib == NULL) {
- node->id = cd->new_id;
- cd->new_id->us++;
- cd->group_id->us--;
- }
- }
- }
-}
-
void ntreeMakeLocal(bNodeTree *ntree)
{
Main *bmain = G.main;
- bNodeTreeType *treetype = ntreeGetType(ntree->type);
- MakeLocalCallData cd;
+ int lib = FALSE, local = FALSE;
/* - only lib users: do nothing
* - only local users: set flag
@@ -1229,26 +1867,42 @@ void ntreeMakeLocal(bNodeTree *ntree)
}
/* now check users of groups... again typedepending, callback... */
- cd.group_id = &ntree->id;
- cd.new_id = NULL;
- cd.local = 0;
- cd.lib = 0;
-
- treetype->foreach_nodetree(G.main, &cd, &ntreeMakeLocal_CheckLocal);
+ FOREACH_NODETREE(G.main, tntree, owner_id) {
+ bNode *node;
+ /* find if group is in tree */
+ for (node = tntree->nodes.first; node; node = node->next) {
+ if (node->id == (ID *)ntree) {
+ if (owner_id->lib)
+ lib = TRUE;
+ else
+ local = TRUE;
+ }
+ }
+ } FOREACH_NODETREE_END
/* if all users are local, we simply make tree local */
- if (cd.local && cd.lib == 0) {
+ if (local && !lib) {
id_clear_lib_data(bmain, (ID *)ntree);
}
- else if (cd.local && cd.lib) {
+ else if (local && lib) {
/* this is the mixed case, we copy the tree and assign it to local users */
bNodeTree *newtree = ntreeCopyTree(ntree);
newtree->id.us = 0;
-
- cd.new_id = &newtree->id;
- treetype->foreach_nodetree(G.main, &cd, &ntreeMakeLocal_LinkNew);
+ FOREACH_NODETREE(G.main, tntree, owner_id) {
+ bNode *node;
+ /* find if group is in tree */
+ for (node = tntree->nodes.first; node; node = node->next) {
+ if (node->id == (ID *)ntree) {
+ if (owner_id->lib == NULL) {
+ node->id = (ID *)newtree;
+ newtree->id.us++;
+ ntree->id.us--;
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
}
}
@@ -1273,90 +1927,329 @@ int ntreeOutputExists(bNode *node, bNodeSocket *testsock)
/* returns localized tree for execution in threads */
bNodeTree *ntreeLocalize(bNodeTree *ntree)
{
- bNodeTreeType *ntreetype = ntreeGetType(ntree->type);
-
- bNodeTree *ltree;
- bNode *node;
+ if (ntree) {
+ bNodeTree *ltree;
+ bNode *node;
+
+ bAction *action_backup = NULL, *tmpact_backup = NULL;
+
+ /* 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);
- bAction *action_backup = NULL, *tmpact_backup = NULL;
+ if (adt) {
+ action_backup = adt->action;
+ tmpact_backup = adt->tmpact;
- /* 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->action = NULL;
+ adt->tmpact = NULL;
+ }
+
+ /* Make full copy.
+ * Note: previews are not copied here.
+ */
+ ltree = ntreeCopyTree_internal(ntree, FALSE, FALSE, FALSE);
+
+ 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);
+
+ return ltree;
+ }
+ else
+ return NULL;
+}
- if (adt) {
- action_backup = adt->action;
- tmpact_backup = adt->tmpact;
+/* sync local composite with real tree */
+/* local tree is supposed to be running, be careful moving previews! */
+/* is called by jobs manager, outside threads, so it doesnt happen during draw */
+void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree)
+{
+ if (localtree && ntree) {
+ if (ntree->typeinfo->local_sync)
+ ntree->typeinfo->local_sync(localtree, ntree);
+ }
+}
- adt->action = NULL;
- adt->tmpact = NULL;
+/* merge local tree results back, and free local tree */
+/* we have to assume the editor already changed completely */
+void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree)
+{
+ if (localtree && ntree) {
+ if (ntree->typeinfo->local_merge)
+ ntree->typeinfo->local_merge(localtree, ntree);
+
+ ntreeFreeTree_ex(localtree, FALSE);
+ MEM_freeN(localtree);
}
+}
- /* node copy func */
- ltree = ntreeCopyTree_internal(ntree, FALSE, FALSE);
- if (adt) {
- AnimData *ladt = BKE_animdata_from_id(&ltree->id);
+/* ************ NODE TREE INTERFACE *************** */
- adt->action = ladt->action = action_backup;
- adt->tmpact = ladt->tmpact = tmpact_backup;
+static bNodeSocket *make_socket_template(bNodeTree *ntree, int in_out,
+ const char *idname, const char *name)
+{
+ bNodeSocketType *stype = nodeSocketTypeFind(idname);
+ bNodeSocket *sock;
+ int own_index = ntree->cur_index++;
+
+ if (stype == NULL) {
+ printf("Error: node socket type '%s' undefined\n", idname);
+ return NULL;
+ }
+
+ sock = MEM_callocN(sizeof(bNodeSocket), "socket template");
+ sock->typeinfo = stype;
+ BLI_strncpy(sock->idname, stype->idname, sizeof(sock->idname));
+ sock->in_out = in_out;
+ sock->type = SOCK_CUSTOM; /* int type undefined by default */
+
+ /* assign new unique index */
+ own_index = ntree->cur_index++;
+ /* use the own_index as socket identifier */
+ if (in_out == SOCK_IN)
+ BLI_snprintf(sock->identifier, MAX_NAME, "Input_%d", own_index);
+ else
+ BLI_snprintf(sock->identifier, MAX_NAME, "Output_%d", own_index);
+#ifdef USE_NODE_COMPAT_CUSTOMNODES
+ /* XXX forward compatibility:
+ * own_index is deprecated, but needs to be set here.
+ * Node sockets generally use the identifier string instead now,
+ * but reconstructing own_index in writefile.c would require parsing the identifier string.
+ */
- if (action_backup) action_backup->id.us++;
- if (tmpact_backup) tmpact_backup->id.us++;
-
+#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) || defined(__clang__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
+ sock->own_index = own_index;
+
+#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) || defined(__clang__)
+# pragma GCC diagnostic pop
+#endif
+
+#endif /* USE_NODE_COMPAT_CUSTOMNODES */
+
+ sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF);
+
+ BLI_strncpy(sock->name, name, NODE_MAXSTR);
+ sock->storage = NULL;
+ sock->flag |= SOCK_COLLAPSED;
+
+ return sock;
+}
+
+bNodeSocket *ntreeFindSocketInterface(bNodeTree *ntree, int in_out, const char *identifier)
+{
+ bNodeSocket *iosock = (in_out == SOCK_IN ? ntree->inputs.first : ntree->outputs.first);
+ for (; iosock; iosock = iosock->next)
+ if (STREQ(iosock->identifier, identifier))
+ return iosock;
+ return NULL;
+}
+
+bNodeSocket *ntreeAddSocketInterface(bNodeTree *ntree, int in_out, const char *idname, const char *name)
+{
+ bNodeSocket *iosock;
+
+ iosock = make_socket_template(ntree, in_out, idname, name);
+ if (in_out == SOCK_IN) {
+ BLI_addtail(&ntree->inputs, iosock);
+ ntree->update |= NTREE_UPDATE_GROUP_IN;
+ }
+ else if (in_out == SOCK_OUT) {
+ BLI_addtail(&ntree->outputs, iosock);
+ ntree->update |= NTREE_UPDATE_GROUP_OUT;
}
- /* end animdata uglyness */
+
+ return iosock;
+}
- /* ensures only a single output node is enabled */
- ntreeSetOutput(ntree);
+bNodeSocket *ntreeInsertSocketInterface(bNodeTree *ntree, int in_out, const char *idname,
+ bNodeSocket *next_sock, const char *name)
+{
+ bNodeSocket *iosock;
+
+ iosock = make_socket_template(ntree, in_out, idname, name);
+ if (in_out == SOCK_IN) {
+ BLI_insertlinkbefore(&ntree->inputs, next_sock, iosock);
+ ntree->update |= NTREE_UPDATE_GROUP_IN;
+ }
+ else if (in_out == SOCK_OUT) {
+ BLI_insertlinkbefore(&ntree->outputs, next_sock, iosock);
+ ntree->update |= NTREE_UPDATE_GROUP_OUT;
+ }
+
+ return iosock;
+}
- for (node = ntree->nodes.first; node; node = node->next) {
- /* store new_node pointer to original */
- node->new_node->new_node = node;
+struct bNodeSocket *ntreeAddSocketInterfaceFromSocket(bNodeTree *ntree, bNode *from_node, bNodeSocket *from_sock)
+{
+ bNodeSocket *iosock = ntreeAddSocketInterface(ntree, from_sock->in_out, from_sock->idname, from_sock->name);
+ if (iosock) {
+ if (iosock->typeinfo->interface_from_socket)
+ iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock);
+ }
+ return iosock;
+}
+
+struct bNodeSocket *ntreeInsertSocketInterfaceFromSocket(bNodeTree *ntree, bNodeSocket *next_sock, bNode *from_node, bNodeSocket *from_sock)
+{
+ bNodeSocket *iosock = ntreeInsertSocketInterface(ntree, from_sock->in_out, from_sock->idname, next_sock, from_sock->name);
+ if (iosock) {
+ if (iosock->typeinfo->interface_from_socket)
+ iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock);
}
+ return iosock;
+}
- if (ntreetype->localize)
- ntreetype->localize(ltree, ntree);
+void ntreeRemoveSocketInterface(bNodeTree *ntree, bNodeSocket *sock)
+{
+ /* this is fast, this way we don't need an in_out argument */
+ BLI_remlink(&ntree->inputs, sock);
+ BLI_remlink(&ntree->outputs, sock);
+
+ node_socket_interface_free(ntree, sock);
+ MEM_freeN(sock);
+
+ ntree->update |= NTREE_UPDATE_GROUP;
+}
- return ltree;
+/* generates a valid RNA identifier from the node tree name */
+static void ntree_interface_identifier_base(bNodeTree *ntree, char *base)
+{
+ /* generate a valid RNA identifier */
+ sprintf(base, "NodeTreeInterface_%s", ntree->id.name + 2);
+ RNA_identifier_sanitize(base, FALSE);
}
-/* sync local composite with real tree */
-/* local tree is supposed to be running, be careful moving previews! */
-/* is called by jobs manager, outside threads, so it doesnt happen during draw */
-void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree)
+/* check if the identifier is already in use */
+static bool ntree_interface_unique_identifier_check(void *UNUSED(data), const char *identifier)
{
- bNodeTreeType *ntreetype = ntreeGetType(ntree->type);
+ return (RNA_struct_find(identifier) != NULL);
+}
- if (ntreetype->local_sync)
- ntreetype->local_sync(localtree, ntree);
+/* generates the actual unique identifier and ui name and description */
+static void ntree_interface_identifier(bNodeTree *ntree, const char *base, char *identifier, int maxlen, char *name, char *description)
+{
+ /* There is a possibility that different node tree names get mapped to the same identifier
+ * after sanitization (e.g. "SomeGroup_A", "SomeGroup.A" both get sanitized to "SomeGroup_A").
+ * On top of the sanitized id string add a number suffix if necessary to avoid duplicates.
+ */
+ identifier[0] = '\0';
+ BLI_uniquename_cb(ntree_interface_unique_identifier_check, NULL, base, '_', identifier, maxlen);
+
+ sprintf(name, "Node Tree %s Interface", ntree->id.name + 2);
+ sprintf(description, "Interface properties of node group %s", ntree->id.name + 2);
}
-/* merge local tree results back, and free local tree */
-/* we have to assume the editor already changed completely */
-void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree)
+static void ntree_interface_type_create(bNodeTree *ntree)
{
- bNodeTreeType *ntreetype = ntreeGetType(ntree->type);
- bNode *lnode;
+ StructRNA *srna;
+ bNodeSocket *sock;
+ /* strings are generated from base string + ID name, sizes are sufficient */
+ char base[MAX_ID_NAME + 64], identifier[MAX_ID_NAME + 64], name[MAX_ID_NAME + 64], description[MAX_ID_NAME + 64];
- /* move over the compbufs and previews */
- for (lnode = localtree->nodes.first; lnode; lnode = lnode->next) {
- if (ntreeNodeExists(ntree, lnode->new_node)) {
- if (lnode->preview && lnode->preview->rect) {
- nodeFreePreview(lnode->new_node);
- lnode->new_node->preview = lnode->preview;
- lnode->preview = NULL;
- }
+ /* generate a valid RNA identifier */
+ ntree_interface_identifier_base(ntree, base);
+ ntree_interface_identifier(ntree, base, identifier, sizeof(identifier), name, description);
+
+ /* register a subtype of PropertyGroup */
+ srna = RNA_def_struct_ptr(&BLENDER_RNA, identifier, &RNA_PropertyGroup);
+ RNA_def_struct_ui_text(srna, name, description);
+ RNA_def_struct_duplicate_pointers(srna);
+
+ /* associate the RNA type with the node tree */
+ ntree->interface_type = srna;
+ RNA_struct_blender_type_set(srna, ntree);
+
+ /* add socket properties */
+ for (sock = ntree->inputs.first; sock; sock = sock->next) {
+ bNodeSocketType *stype = sock->typeinfo;
+ if (stype && stype->interface_register_properties)
+ stype->interface_register_properties(ntree, sock, srna);
+ }
+ for (sock = ntree->outputs.first; sock; sock = sock->next) {
+ bNodeSocketType *stype = sock->typeinfo;
+ if (stype && stype->interface_register_properties)
+ stype->interface_register_properties(ntree, sock, srna);
+ }
+}
+
+StructRNA *ntreeInterfaceTypeGet(bNodeTree *ntree, int create)
+{
+ if (ntree->interface_type) {
+ /* strings are generated from base string + ID name, sizes are sufficient */
+ char base[MAX_ID_NAME + 64], identifier[MAX_ID_NAME + 64], name[MAX_ID_NAME + 64], description[MAX_ID_NAME + 64];
+
+ /* A bit of a hack: when changing the ID name, update the RNA type identifier too,
+ * so that the names match. This is not strictly necessary to keep it working,
+ * but better for identifying associated NodeTree blocks and RNA types.
+ */
+ StructRNA *srna = ntree->interface_type;
+
+ 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) {
+ /* generate new unique RNA identifier from the ID name */
+ ntree_interface_identifier(ntree, base, identifier, sizeof(identifier), name, description);
+
+ /* rename the RNA type */
+ RNA_def_struct_free_pointers(srna);
+ RNA_def_struct_identifier(srna, identifier);
+ RNA_def_struct_ui_text(srna, name, description);
+ RNA_def_struct_duplicate_pointers(srna);
}
}
+ else if (create) {
+ ntree_interface_type_create(ntree);
+ }
+
+ return ntree->interface_type;
+}
- if (ntreetype->local_merge)
- ntreetype->local_merge(localtree, ntree);
+void ntreeInterfaceTypeFree(bNodeTree *ntree)
+{
+ if (ntree->interface_type) {
+ RNA_struct_free(&BLENDER_RNA, ntree->interface_type);
+ ntree->interface_type = NULL;
+ }
+}
- ntreeFreeTree_ex(localtree, FALSE);
- MEM_freeN(localtree);
+void ntreeInterfaceTypeUpdate(bNodeTree *ntree)
+{
+ /* XXX it would be sufficient to just recreate all properties
+ * instead of re-registering the whole struct type,
+ * but there is currently no good way to do this in the RNA functions.
+ * Overhead should be negligible.
+ */
+ ntreeInterfaceTypeFree(ntree);
+ ntree_interface_type_create(ntree);
}
+
/* ************ find stuff *************** */
int ntreeHasType(bNodeTree *ntree, int type)
@@ -1410,43 +2303,34 @@ bNode *nodeGetActive(bNodeTree *ntree)
/* two active flags, ID nodes have special flag for buttons display */
bNode *nodeGetActiveID(bNodeTree *ntree, short idtype)
{
- bNode *node;
+ bNode *node, *tnode;
if (ntree == NULL) return NULL;
- /* check for group edit */
- for (node = ntree->nodes.first; node; node = node->next)
- if (node->flag & NODE_GROUP_EDIT)
- break;
-
- if (node)
- ntree = (bNodeTree *)node->id;
-
- /* now find active node with this id */
for (node = ntree->nodes.first; node; node = node->next)
if (node->id && GS(node->id->name) == idtype)
if (node->flag & NODE_ACTIVE_ID)
- break;
-
- return node;
+ return node;
+
+ /* no node with active ID in this tree, look inside groups */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP) {
+ tnode = nodeGetActiveID((bNodeTree *)node->id, idtype);
+ if (tnode)
+ return tnode;
+ }
+ }
+
+ return NULL;
}
-int nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id)
+bool nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id)
{
bNode *node;
- int ok = FALSE;
+ bool ok = false;
if (ntree == NULL) return ok;
- /* check for group edit */
- for (node = ntree->nodes.first; node; node = node->next)
- if (node->flag & NODE_GROUP_EDIT)
- break;
-
- if (node)
- ntree = (bNodeTree *)node->id;
-
- /* now find active node with this id */
for (node = ntree->nodes.first; node; node = node->next) {
if (node->id && GS(node->id->name) == idtype) {
if (id && ok == FALSE && node->id == id) {
@@ -1459,6 +2343,15 @@ int nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id)
}
}
+ /* update all groups linked from here
+ * if active ID node has been found already,
+ * just pass NULL so other matching nodes are deactivated.
+ */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP)
+ ok |= nodeSetActiveID((bNodeTree *)node->id, idtype, (ok == false ? id : NULL));
+ }
+
return ok;
}
@@ -1475,6 +2368,24 @@ void nodeClearActiveID(bNodeTree *ntree, short idtype)
node->flag &= ~NODE_ACTIVE_ID;
}
+void nodeSetSelected(bNode *node, int select)
+{
+ if (select) {
+ node->flag |= NODE_SELECT;
+ }
+ else {
+ bNodeSocket *sock;
+
+ node->flag &= ~NODE_SELECT;
+
+ /* deselect sockets too */
+ for (sock = node->inputs.first; sock; sock = sock->next)
+ sock->flag &= ~NODE_SELECT;
+ for (sock = node->outputs.first; sock; sock = sock->next)
+ sock->flag &= ~NODE_SELECT;
+ }
+}
+
void nodeClearActive(bNodeTree *ntree)
{
bNode *node;
@@ -1485,7 +2396,6 @@ void nodeClearActive(bNodeTree *ntree)
node->flag &= ~(NODE_ACTIVE | NODE_ACTIVE_ID);
}
-
/* two active flags, ID nodes have special flag for buttons display */
void nodeSetActive(bNodeTree *ntree, bNode *node)
{
@@ -1515,19 +2425,6 @@ int nodeSocketIsHidden(bNodeSocket *sock)
return ((sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) != 0);
}
-void nodeSocketSetType(bNodeSocket *sock, int type)
-{
- int old_type = sock->type;
- void *old_default_value = sock->default_value;
-
- sock->type = type;
-
- sock->default_value = node_socket_make_default_value(sock->type);
- node_socket_init_default_value(type, sock->default_value);
- node_socket_convert_default_value(sock->type, sock->default_value, old_type, old_default_value);
- node_socket_free_default_value(old_type, old_default_value);
-}
-
/* ************** Node Clipboard *********** */
#define USE_NODE_CB_VALIDATE
@@ -1560,7 +2457,7 @@ typedef struct bNodeClipboard {
int type;
} bNodeClipboard;
-bNodeClipboard node_clipboard = {{0}};
+static bNodeClipboard node_clipboard = {{NULL}};
void BKE_node_clipboard_init(struct bNodeTree *ntree)
{
@@ -1637,7 +2534,7 @@ void BKE_node_clipboard_add_node(bNode *node)
{
#ifdef USE_NODE_CB_VALIDATE
/* add extra info */
- bNodeClipboardExtraInfo *node_info = MEM_mallocN(sizeof(bNodeClipboardExtraInfo), STRINGIFY(bNodeClipboardExtraInfo));
+ bNodeClipboardExtraInfo *node_info = MEM_mallocN(sizeof(bNodeClipboardExtraInfo), "bNodeClipboardExtraInfo");
node_info->id = node->id;
if (node->id) {
@@ -1682,6 +2579,163 @@ int BKE_node_clipboard_get_type(void)
return node_clipboard.type;
}
+
+/* Node Instance Hash */
+
+/* magic number for initial hash key */
+const bNodeInstanceKey NODE_INSTANCE_KEY_BASE = {5381};
+
+/* Generate a hash key from ntree and node names
+ * Uses the djb2 algorithm with xor by Bernstein:
+ * http://www.cse.yorku.ca/~oz/hash.html
+ */
+static bNodeInstanceKey node_hash_int_str(bNodeInstanceKey hash, const char *str)
+{
+ char c;
+
+ while ((c = *str++))
+ hash.value = ((hash.value << 5) + hash.value) ^ c; /* (hash * 33) ^ c */
+
+ /* separator '\0' character, to avoid ambiguity from concatenated strings */
+ hash.value = (hash.value << 5) + hash.value; /* hash * 33 */
+
+ return hash;
+}
+
+bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key, bNodeTree *ntree, bNode *node)
+{
+ bNodeInstanceKey key;
+
+ key = node_hash_int_str(parent_key, ntree->id.name + 2);
+
+ if (node)
+ key = node_hash_int_str(key, node->name);
+
+ return key;
+}
+
+static unsigned int node_instance_hash_key(const void *key)
+{
+ return ((const bNodeInstanceKey *)key)->value;
+}
+
+static int node_instance_hash_key_cmp(const void *a, const void *b)
+{
+ unsigned int value_a = ((const bNodeInstanceKey *)a)->value;
+ unsigned int value_b = ((const bNodeInstanceKey *)b)->value;
+ if (value_a == value_b)
+ return 0;
+ else if (value_a < value_b)
+ return -1;
+ else
+ return 1;
+}
+
+bNodeInstanceHash *BKE_node_instance_hash_new(const char *info)
+{
+ bNodeInstanceHash *hash = MEM_mallocN(sizeof(bNodeInstanceHash), info);
+ hash->ghash = BLI_ghash_new(node_instance_hash_key, node_instance_hash_key_cmp, "node instance hash ghash");
+ return hash;
+}
+
+void BKE_node_instance_hash_free(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp)
+{
+ BLI_ghash_free(hash->ghash, NULL, (GHashValFreeFP)valfreefp);
+ MEM_freeN(hash);
+}
+
+void BKE_node_instance_hash_insert(bNodeInstanceHash *hash, bNodeInstanceKey key, void *value)
+{
+ bNodeInstanceHashEntry *entry = value;
+ entry->key = key;
+ entry->tag = 0;
+ BLI_ghash_insert(hash->ghash, &entry->key, value);
+}
+
+void *BKE_node_instance_hash_lookup(bNodeInstanceHash *hash, bNodeInstanceKey key)
+{
+ return BLI_ghash_lookup(hash->ghash, &key);
+}
+
+int BKE_node_instance_hash_remove(bNodeInstanceHash *hash, bNodeInstanceKey key, bNodeInstanceValueFP valfreefp)
+{
+ return BLI_ghash_remove(hash->ghash, &key, NULL, (GHashValFreeFP)valfreefp);
+}
+
+void BKE_node_instance_hash_clear(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp)
+{
+ BLI_ghash_clear(hash->ghash, NULL, (GHashValFreeFP)valfreefp);
+}
+
+void *BKE_node_instance_hash_pop(bNodeInstanceHash *hash, bNodeInstanceKey key)
+{
+ return BLI_ghash_pop(hash->ghash, &key, NULL);
+}
+
+int BKE_node_instance_hash_haskey(bNodeInstanceHash *hash, bNodeInstanceKey key)
+{
+ return BLI_ghash_haskey(hash->ghash, &key);
+}
+
+int BKE_node_instance_hash_size(bNodeInstanceHash *hash)
+{
+ return BLI_ghash_size(hash->ghash);
+}
+
+void BKE_node_instance_hash_clear_tags(bNodeInstanceHash *hash)
+{
+ bNodeInstanceHashIterator iter;
+
+ NODE_INSTANCE_HASH_ITER(iter, hash) {
+ bNodeInstanceHashEntry *value = BKE_node_instance_hash_iterator_get_value(&iter);
+
+ value->tag = 0;
+ }
+}
+
+void BKE_node_instance_hash_tag(bNodeInstanceHash *UNUSED(hash), void *value)
+{
+ bNodeInstanceHashEntry *entry = value;
+ entry->tag = 1;
+}
+
+int BKE_node_instance_hash_tag_key(bNodeInstanceHash *hash, bNodeInstanceKey key)
+{
+ bNodeInstanceHashEntry *entry = BKE_node_instance_hash_lookup(hash, key);
+
+ if (entry) {
+ entry->tag = 1;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+void BKE_node_instance_hash_remove_untagged(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp)
+{
+ /* NOTE: Hash must not be mutated during iterating!
+ * Store tagged entries in a separate list and remove items afterward.
+ */
+ bNodeInstanceKey *untagged = MEM_mallocN(sizeof(bNodeInstanceKey) * BKE_node_instance_hash_size(hash), "temporary node instance key list");
+ bNodeInstanceHashIterator iter;
+ int num_untagged, i;
+
+ num_untagged = 0;
+ NODE_INSTANCE_HASH_ITER(iter, hash) {
+ bNodeInstanceHashEntry *value = BKE_node_instance_hash_iterator_get_value(&iter);
+
+ if (!value->tag)
+ untagged[num_untagged++] = BKE_node_instance_hash_iterator_get_key(&iter);
+ }
+
+ for (i = 0; i < num_untagged; ++i) {
+ BKE_node_instance_hash_remove(hash, untagged[i], valfreefp);
+ }
+
+ MEM_freeN(untagged);
+}
+
+
/* ************** dependency stuff *********** */
/* node is guaranteed to be not checked before */
@@ -1697,12 +2751,10 @@ static int node_get_deplist_recurs(bNodeTree *ntree, bNode *node, bNode ***nsort
for (link = ntree->links.first; link; link = link->next) {
if (link->tonode == node) {
fromnode = link->fromnode;
- if (fromnode) {
- if (fromnode->done == 0)
- fromnode->level = node_get_deplist_recurs(ntree, fromnode, nsort);
- if (fromnode->level <= level)
- level = fromnode->level - 1;
- }
+ if (fromnode->done == 0)
+ fromnode->level = node_get_deplist_recurs(ntree, fromnode, nsort);
+ if (fromnode->level <= level)
+ level = fromnode->level - 1;
}
}
@@ -1782,13 +2834,6 @@ static void ntree_update_link_pointers(bNodeTree *ntree)
sock->flag &= ~SOCK_IN_USE;
}
}
- for (sock = ntree->inputs.first; sock; sock = sock->next) {
- sock->flag &= ~SOCK_IN_USE;
- }
- for (sock = ntree->outputs.first; sock; sock = sock->next) {
- sock->link = NULL;
- sock->flag &= ~SOCK_IN_USE;
- }
for (link = ntree->links.first; link; link = link->next) {
link->tosock->link = link;
@@ -1800,144 +2845,129 @@ static void ntree_update_link_pointers(bNodeTree *ntree)
static void ntree_validate_links(bNodeTree *ntree)
{
- bNodeTreeType *ntreetype = ntreeGetType(ntree->type);
bNodeLink *link;
for (link = ntree->links.first; link; link = link->next) {
link->flag |= NODE_LINK_VALID;
if (link->fromnode && link->tonode && link->fromnode->level <= link->tonode->level)
link->flag &= ~NODE_LINK_VALID;
- else if (ntreetype->validate_link) {
- if (!ntreetype->validate_link(ntree, link))
+ else if (ntree->typeinfo->validate_link) {
+ if (!ntree->typeinfo->validate_link(ntree, link))
link->flag &= ~NODE_LINK_VALID;
}
}
}
-static void ntree_verify_nodes_cb(void *calldata, struct ID *UNUSED(owner_id), struct bNodeTree *ntree)
-{
- ID *id = (ID *)calldata;
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next)
- if (node->typeinfo->verifyfunc)
- node->typeinfo->verifyfunc(ntree, node, id);
-}
-
void ntreeVerifyNodes(struct Main *main, struct ID *id)
{
- bNodeTreeType *ntreetype;
- bNodeTree *ntree;
- int n;
-
- for (n = 0; n < NUM_NTREE_TYPES; ++n) {
- ntreetype = ntreeGetType(n);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, id, ntree_verify_nodes_cb);
- }
- for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
- ntree_verify_nodes_cb(id, NULL, ntree);
+ FOREACH_NODETREE(main, ntree, owner_id) {
+ bNode *node;
+
+ for (node = ntree->nodes.first; node; node = node->next)
+ if (node->typeinfo->verifyfunc)
+ node->typeinfo->verifyfunc(ntree, node, id);
+ } FOREACH_NODETREE_END
}
void ntreeUpdateTree(bNodeTree *ntree)
{
- bNodeTreeType *ntreetype = ntreeGetType(ntree->type);
bNode *node;
+ if (!ntree)
+ return;
+
+ /* avoid reentrant updates, can be caused by RNA update callbacks */
+ if (ntree->is_updating)
+ return;
+ ntree->is_updating = TRUE;
+
if (ntree->update & (NTREE_UPDATE_LINKS | NTREE_UPDATE_NODES)) {
/* set the bNodeSocket->link pointers */
ntree_update_link_pointers(ntree);
-
- /* update the node level from link dependencies */
- ntree_update_node_level(ntree);
}
/* update individual nodes */
for (node = ntree->nodes.first; node; node = node->next) {
/* node tree update tags override individual node update flags */
if ((node->update & NODE_UPDATE) || (ntree->update & NTREE_UPDATE)) {
- if (ntreetype->update_node)
- ntreetype->update_node(ntree, node);
- else if (node->typeinfo->updatefunc)
+ if (node->typeinfo->updatefunc)
node->typeinfo->updatefunc(ntree, node);
nodeUpdateInternalLinks(ntree, node);
}
}
- /* check link validity */
- if (ntree->update & (NTREE_UPDATE_LINKS | NTREE_UPDATE_NODES))
- ntree_validate_links(ntree);
-
/* generic tree update callback */
- if (ntreetype->update)
- ntreetype->update(ntree);
- else {
- /* Trees can be associated with a specific node type (i.e. group nodes),
- * in that case a tree update function may be defined by that node type.
- */
- bNodeType *ntype = node_get_type(ntree, ntree->nodetype);
- if (ntype && ntype->updatetreefunc)
- ntype->updatetreefunc(ntree);
- }
+ if (ntree->typeinfo->update)
+ ntree->typeinfo->update(ntree);
+ /* XXX this should be moved into the tree type update callback for tree supporting node groups.
+ * Currently the node tree interface is still a generic feature of the base NodeTree type.
+ */
+ if (ntree->update & NTREE_UPDATE_GROUP)
+ ntreeInterfaceTypeUpdate(ntree);
/* XXX hack, should be done by depsgraph!! */
ntreeVerifyNodes(G.main, &ntree->id);
+ if (ntree->update & (NTREE_UPDATE_LINKS | NTREE_UPDATE_NODES)) {
+ /* node updates can change sockets or links, repeat link pointer update afterward */
+ ntree_update_link_pointers(ntree);
+
+ /* update the node level from link dependencies */
+ ntree_update_node_level(ntree);
+
+ /* check link validity */
+ ntree_validate_links(ntree);
+ }
+
/* clear update flags */
for (node = ntree->nodes.first; node; node = node->next) {
node->update = 0;
}
ntree->update = 0;
+
+ ntree->is_updating = FALSE;
}
void nodeUpdate(bNodeTree *ntree, bNode *node)
{
- bNodeTreeType *ntreetype = ntreeGetType(ntree->type);
+ /* avoid reentrant updates, can be caused by RNA update callbacks */
+ if (ntree->is_updating)
+ return;
+ ntree->is_updating = TRUE;
- if (ntreetype->update_node)
- ntreetype->update_node(ntree, node);
- else if (node->typeinfo->updatefunc)
+ if (node->typeinfo->updatefunc)
node->typeinfo->updatefunc(ntree, node);
nodeUpdateInternalLinks(ntree, node);
/* clear update flag */
node->update = 0;
+
+ ntree->is_updating = FALSE;
}
int nodeUpdateID(bNodeTree *ntree, ID *id)
{
- bNodeTreeType *ntreetype;
bNode *node;
int change = FALSE;
if (ELEM(NULL, id, ntree))
return change;
- ntreetype = ntreeGetType(ntree->type);
+ /* avoid reentrant updates, can be caused by RNA update callbacks */
+ if (ntree->is_updating)
+ return change;
+ ntree->is_updating = TRUE;
- if (ntreetype->update_node) {
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->id == id) {
- change = TRUE;
- node->update |= NODE_UPDATE_ID;
- ntreetype->update_node(ntree, node);
- /* clear update flag */
- node->update = 0;
- }
- }
- }
- else {
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->id == id) {
- change = TRUE;
- node->update |= NODE_UPDATE_ID;
- if (node->typeinfo->updatefunc)
- node->typeinfo->updatefunc(ntree, node);
- /* clear update flag */
- node->update = 0;
- }
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->id == id) {
+ change = TRUE;
+ node->update |= NODE_UPDATE_ID;
+ if (node->typeinfo->updatefunc)
+ node->typeinfo->updatefunc(ntree, node);
+ /* clear update flag */
+ node->update = 0;
}
}
@@ -1945,6 +2975,7 @@ int nodeUpdateID(bNodeTree *ntree, ID *id)
nodeUpdateInternalLinks(ntree, node);
}
+ ntree->is_updating = FALSE;
return change;
}
@@ -1957,21 +2988,75 @@ void nodeUpdateInternalLinks(bNodeTree *ntree, bNode *node)
}
-/* ************* node type access ********** */
-
-int nodeValid(bNodeTree *ntree, bNodeTemplate *ntemp)
+/* nodes that use ID data get synced with local data */
+void nodeSynchronizeID(bNode *node, bool copy_to_id)
{
- bNodeType *ntype = node_get_type(ntree, ntemp->type);
- if (ntype) {
- if (ntype->validfunc)
- return ntype->validfunc(ntree, ntemp);
- else
- return 1;
+ if (node->id == NULL) return;
+
+ if (ELEM(node->type, SH_NODE_MATERIAL, SH_NODE_MATERIAL_EXT)) {
+ bNodeSocket *sock;
+ Material *ma = (Material *)node->id;
+ int a;
+
+ /* 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 (copy_to_id) {
+ switch (a) {
+ case MAT_IN_COLOR:
+ copy_v3_v3(&ma->r, ((bNodeSocketValueRGBA *)sock->default_value)->value); break;
+ case MAT_IN_SPEC:
+ copy_v3_v3(&ma->specr, ((bNodeSocketValueRGBA *)sock->default_value)->value); break;
+ case MAT_IN_REFL:
+ ma->ref = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
+ case MAT_IN_MIR:
+ copy_v3_v3(&ma->mirr, ((bNodeSocketValueRGBA *)sock->default_value)->value); break;
+ case MAT_IN_AMB:
+ ma->amb = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
+ case MAT_IN_EMIT:
+ ma->emit = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
+ case MAT_IN_SPECTRA:
+ ma->spectra = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
+ case MAT_IN_RAY_MIRROR:
+ ma->ray_mirror = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
+ case MAT_IN_ALPHA:
+ ma->alpha = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
+ case MAT_IN_TRANSLUCENCY:
+ ma->translucency = ((bNodeSocketValueFloat *)sock->default_value)->value; break;
+ }
+ }
+ else {
+ switch (a) {
+ case MAT_IN_COLOR:
+ copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->r); break;
+ case MAT_IN_SPEC:
+ copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->specr); break;
+ case MAT_IN_REFL:
+ ((bNodeSocketValueFloat *)sock->default_value)->value = ma->ref; break;
+ case MAT_IN_MIR:
+ copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->mirr); break;
+ case MAT_IN_AMB:
+ ((bNodeSocketValueFloat *)sock->default_value)->value = ma->amb; break;
+ case MAT_IN_EMIT:
+ ((bNodeSocketValueFloat *)sock->default_value)->value = ma->emit; break;
+ case MAT_IN_SPECTRA:
+ ((bNodeSocketValueFloat *)sock->default_value)->value = ma->spectra; break;
+ case MAT_IN_RAY_MIRROR:
+ ((bNodeSocketValueFloat *)sock->default_value)->value = ma->ray_mirror; break;
+ case MAT_IN_ALPHA:
+ ((bNodeSocketValueFloat *)sock->default_value)->value = ma->alpha; break;
+ case MAT_IN_TRANSLUCENCY:
+ ((bNodeSocketValueFloat *)sock->default_value)->value = ma->translucency; break;
+ }
+ }
+ }
+ }
}
- else
- return 0;
}
+
+/* ************* node type access ********** */
+
const char *nodeLabel(bNode *node)
{
if (node->label[0] != '\0')
@@ -1979,82 +3064,136 @@ const char *nodeLabel(bNode *node)
else if (node->typeinfo->labelfunc)
return node->typeinfo->labelfunc(node);
else
- return IFACE_(node->typeinfo->name);
+ return IFACE_(node->typeinfo->ui_name);
}
-struct bNodeTree *nodeGroupEditGet(struct bNode *node)
+static void node_type_base_defaults(bNodeType *ntype)
{
- if (node->typeinfo->group_edit_get)
- return node->typeinfo->group_edit_get(node);
- else
- return NULL;
+ /* default size values */
+ node_type_size_preset(ntype, NODE_SIZE_DEFAULT);
+ ntype->height = 100;
+ ntype->minheight = 30;
+ ntype->maxheight = FLT_MAX;
}
-struct bNodeTree *nodeGroupEditSet(struct bNode *node, int edit)
+/* allow this node for any tree type */
+static int node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *UNUSED(ntree))
{
- if (node->typeinfo->group_edit_set)
- return node->typeinfo->group_edit_set(node, edit);
- else if (node->typeinfo->group_edit_get)
- return node->typeinfo->group_edit_get(node);
- else
- return NULL;
+ return TRUE;
}
-void nodeGroupEditClear(struct bNode *node)
+/* use the basic poll function */
+static int node_poll_instance_default(bNode *node, bNodeTree *ntree)
{
- if (node->typeinfo->group_edit_clear)
- node->typeinfo->group_edit_clear(node);
+ return node->typeinfo->poll(node->typeinfo, ntree);
}
-struct bNodeTemplate nodeMakeTemplate(struct bNode *node)
+void node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag)
{
- bNodeTemplate ntemp;
- if (node->typeinfo->templatefunc)
- return node->typeinfo->templatefunc(node);
- else {
- ntemp.type = node->type;
- return ntemp;
+ /* Use static type info header to map static int type to identifier string and RNA struct type.
+ * Associate the RNA struct type with the bNodeType.
+ * Dynamically registered nodes will create an RNA type at runtime
+ * and call RNA_struct_blender_type_set, so this only needs to be done for old RNA types
+ * created in makesrna, which can not be associated to a bNodeType immediately,
+ * since bNodeTypes are registered afterward ...
+ */
+ #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ case ID: \
+ BLI_strncpy(ntype->idname, #Category #StructName, sizeof(ntype->idname)); \
+ ntype->ext.srna = RNA_struct_find(#Category #StructName); \
+ BLI_assert(ntype->ext.srna != NULL); \
+ RNA_struct_blender_type_set(ntype->ext.srna, ntype); \
+ break;
+
+ switch (type) {
+ #include "NOD_static_types.h"
}
+
+ /* make sure we have a valid type (everything registered) */
+ BLI_assert(ntype->idname[0] != '\0');
+
+ ntype->type = type;
+ BLI_strncpy(ntype->ui_name, name, sizeof(ntype->ui_name));
+ ntype->nclass = nclass;
+ ntype->flag = flag;
+
+ node_type_base_defaults(ntype);
+
+ ntype->poll = node_poll_default;
+ ntype->poll_instance = node_poll_instance_default;
}
-void node_type_base(bNodeTreeType *ttype, bNodeType *ntype, int type, const char *name, short nclass, short flag)
+void node_type_base_custom(bNodeType *ntype, const char *idname, const char *name, short nclass, short flag)
{
- memset(ntype, 0, sizeof(bNodeType));
-
- ntype->type = type;
- BLI_strncpy(ntype->name, name, sizeof(ntype->name));
+ BLI_strncpy(ntype->idname, idname, sizeof(ntype->idname));
+ ntype->type = NODE_CUSTOM;
+ BLI_strncpy(ntype->ui_name, name, sizeof(ntype->ui_name));
ntype->nclass = nclass;
ntype->flag = flag;
- /* Default muting stuff. */
- if (ttype)
- ntype->update_internal_links = ttype->update_internal_links;
+ node_type_base_defaults(ntype);
+}
- /* default size values */
- ntype->width = 140;
- ntype->minwidth = 100;
- ntype->maxwidth = 320;
- ntype->height = 100;
- ntype->minheight = 30;
- ntype->maxheight = FLT_MAX;
+static bool unique_socket_template_identifier_check(void *arg, const char *name)
+{
+ bNodeSocketTemplate *ntemp;
+ struct {bNodeSocketTemplate *list; bNodeSocketTemplate *ntemp;} *data = arg;
+
+ for (ntemp = data->list; ntemp->type >= 0; ++ntemp) {
+ if (ntemp != data->ntemp) {
+ if (STREQ(ntemp->identifier, name)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static void unique_socket_template_identifier(bNodeSocketTemplate *list, bNodeSocketTemplate *ntemp, const char defname[], char delim)
+{
+ struct {bNodeSocketTemplate *list; bNodeSocketTemplate *ntemp;} data;
+ data.list = list;
+ data.ntemp = ntemp;
+
+ BLI_uniquename_cb(unique_socket_template_identifier_check, &data, defname, delim, ntemp->identifier, sizeof(ntemp->identifier));
}
void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs)
{
+ bNodeSocketTemplate *ntemp;
+
ntype->inputs = inputs;
ntype->outputs = outputs;
+
+ /* automatically generate unique identifiers */
+ if (inputs) {
+ /* clear identifier strings (uninitialized memory) */
+ for (ntemp = inputs; ntemp->type >= 0; ++ntemp)
+ ntemp->identifier[0] = '\0';
+
+ for (ntemp = inputs; ntemp->type >= 0; ++ntemp) {
+ BLI_strncpy(ntemp->identifier, ntemp->name, sizeof(ntemp->identifier));
+ unique_socket_template_identifier(inputs, ntemp, ntemp->identifier, '_');
+ }
+ }
+ if (outputs) {
+ /* clear identifier strings (uninitialized memory) */
+ for (ntemp = outputs; ntemp->type >= 0; ++ntemp)
+ ntemp->identifier[0] = '\0';
+
+ for (ntemp = outputs; ntemp->type >= 0; ++ntemp) {
+ BLI_strncpy(ntemp->identifier, ntemp->name, sizeof(ntemp->identifier));
+ unique_socket_template_identifier(outputs, ntemp, ntemp->identifier, '_');
+ }
+ }
}
-void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp))
+void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNodeTree *ntree, struct bNode *node))
{
ntype->initfunc = initfunc;
}
-void node_type_valid(struct bNodeType *ntype, int (*validfunc)(struct bNodeTree *ntree, struct bNodeTemplate *ntemp))
-{
- ntype->validfunc = validfunc;
-}
-
void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth)
{
ntype->width = width;
@@ -2065,14 +3204,32 @@ void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwid
ntype->maxwidth = maxwidth;
}
-void node_type_storage(bNodeType *ntype, const char *storagename, void (*freestoragefunc)(struct bNode *), void (*copystoragefunc)(struct bNode *, struct bNode *))
+void node_type_size_preset(struct bNodeType *ntype, eNodeSizePreset size)
+{
+ switch (size) {
+ case NODE_SIZE_DEFAULT:
+ node_type_size(ntype, 140, 100, 320);
+ break;
+ case NODE_SIZE_SMALL:
+ node_type_size(ntype, 100, 80, 320);
+ break;
+ case NODE_SIZE_LARGE:
+ node_type_size(ntype, 140, 120, 500);
+ break;
+ }
+}
+
+void node_type_storage(bNodeType *ntype,
+ const char *storagename,
+ void (*freefunc)(struct bNode *node),
+ void (*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node))
{
if (storagename)
BLI_strncpy(ntype->storagename, storagename, sizeof(ntype->storagename));
else
ntype->storagename[0] = '\0';
- ntype->copystoragefunc = copystoragefunc;
- ntype->freestoragefunc = freestoragefunc;
+ ntype->copyfunc = copyfunc;
+ ntype->freefunc = freefunc;
}
void node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bNode *))
@@ -2080,11 +3237,6 @@ void node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bN
ntype->labelfunc = labelfunc;
}
-void node_type_template(struct bNodeType *ntype, struct bNodeTemplate (*templatefunc)(struct bNode *))
-{
- ntype->templatefunc = templatefunc;
-}
-
void node_type_update(struct bNodeType *ntype,
void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node),
void (*verifyfunc)(struct bNodeTree *ntree, struct bNode *node, struct ID *id))
@@ -2093,35 +3245,16 @@ void node_type_update(struct bNodeType *ntype,
ntype->verifyfunc = verifyfunc;
}
-void node_type_tree(struct bNodeType *ntype, void (*inittreefunc)(struct bNodeTree *), void (*updatetreefunc)(struct bNodeTree *))
-{
- ntype->inittreefunc = inittreefunc;
- ntype->updatetreefunc = updatetreefunc;
-}
-
-void node_type_group_edit(struct bNodeType *ntype,
- struct bNodeTree *(*group_edit_get)(struct bNode *node),
- struct bNodeTree *(*group_edit_set)(struct bNode *node, int edit),
- void (*group_edit_clear)(struct bNode *node))
-{
- ntype->group_edit_get = group_edit_get;
- ntype->group_edit_set = group_edit_set;
- ntype->group_edit_clear = group_edit_clear;
-}
-
-void node_type_exec(struct bNodeType *ntype, void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, struct bNodeStack **))
+void node_type_exec(struct bNodeType *ntype, NodeInitExecFunction initexecfunc, NodeFreeExecFunction freeexecfunc, NodeExecFunction execfunc)
{
+ ntype->initexecfunc = initexecfunc;
+ ntype->freeexecfunc = freeexecfunc;
ntype->execfunc = execfunc;
}
-void node_type_exec_new(struct bNodeType *ntype,
- void *(*initexecfunc)(struct bNode *node),
- void (*freeexecfunc)(struct bNode *node, void *nodedata),
- void (*newexecfunc)(void *data, int thread, struct bNode *, void *nodedata, struct bNodeStack **, struct bNodeStack **))
+void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpufunc)
{
- ntype->initexecfunc = initexecfunc;
- ntype->freeexecfunc = freeexecfunc;
- ntype->newexecfunc = newexecfunc;
+ ntype->gpufunc = gpufunc;
}
void node_type_internal_links(bNodeType *ntype, void (*update_internal_links)(bNodeTree *, bNode *))
@@ -2129,294 +3262,311 @@ void node_type_internal_links(bNodeType *ntype, void (*update_internal_links)(bN
ntype->update_internal_links = update_internal_links;
}
-void node_type_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out))
+void node_type_compatibility(struct bNodeType *ntype, short compatibility)
{
- ntype->gpufunc = gpufunc;
+ ntype->compatibility = compatibility;
}
-void node_type_gpu_ext(struct bNodeType *ntype, int (*gpuextfunc)(struct GPUMaterial *mat, struct bNode *node, void *nodedata, struct GPUNodeStack *in, struct GPUNodeStack *out))
-{
- ntype->gpuextfunc = gpuextfunc;
-}
+/* callbacks for undefined types */
-void node_type_compatibility(struct bNodeType *ntype, short compatibility)
+static int node_undefined_poll(bNodeType *UNUSED(ntype), bNodeTree *UNUSED(nodetree))
{
- ntype->compatibility = compatibility;
+ /* this type can not be added deliberately, it's just a placeholder */
+ return false;
}
-static bNodeType *is_nodetype_registered(ListBase *typelist, int type)
+/* register fallback types used for undefined tree, nodes, sockets */
+static void register_undefined_types(void)
{
- bNodeType *ntype = typelist->first;
-
- for (; ntype; ntype = ntype->next)
- if (ntype->type == type)
- return ntype;
+ /* Note: these types are not registered in the type hashes,
+ * they are just used as placeholders in case the actual types are not registered.
+ */
- return NULL;
-}
-
-void nodeRegisterType(bNodeTreeType *ttype, bNodeType *ntype)
-{
- ListBase *typelist = &(ttype->node_types);
- bNodeType *found = is_nodetype_registered(typelist, ntype->type);
-
- if (found == NULL)
- BLI_addtail(typelist, ntype);
-}
-
-static void registerCompositNodes(bNodeTreeType *ttype)
-{
- register_node_type_frame(ttype);
- register_node_type_reroute(ttype);
-
- register_node_type_cmp_group(ttype);
-
- register_node_type_cmp_rlayers(ttype);
- register_node_type_cmp_image(ttype);
- register_node_type_cmp_texture(ttype);
- register_node_type_cmp_value(ttype);
- register_node_type_cmp_rgb(ttype);
- register_node_type_cmp_curve_time(ttype);
- register_node_type_cmp_movieclip(ttype);
-
- register_node_type_cmp_composite(ttype);
- register_node_type_cmp_viewer(ttype);
- register_node_type_cmp_splitviewer(ttype);
- register_node_type_cmp_output_file(ttype);
- register_node_type_cmp_view_levels(ttype);
-
- register_node_type_cmp_curve_rgb(ttype);
- register_node_type_cmp_mix_rgb(ttype);
- register_node_type_cmp_hue_sat(ttype);
- register_node_type_cmp_brightcontrast(ttype);
- register_node_type_cmp_gamma(ttype);
- register_node_type_cmp_invert(ttype);
- register_node_type_cmp_alphaover(ttype);
- register_node_type_cmp_zcombine(ttype);
- register_node_type_cmp_colorbalance(ttype);
- register_node_type_cmp_huecorrect(ttype);
-
- register_node_type_cmp_normal(ttype);
- register_node_type_cmp_curve_vec(ttype);
- register_node_type_cmp_map_value(ttype);
- register_node_type_cmp_map_range(ttype);
- register_node_type_cmp_normalize(ttype);
-
- register_node_type_cmp_filter(ttype);
- register_node_type_cmp_blur(ttype);
- register_node_type_cmp_dblur(ttype);
- register_node_type_cmp_bilateralblur(ttype);
- register_node_type_cmp_vecblur(ttype);
- register_node_type_cmp_dilateerode(ttype);
- register_node_type_cmp_inpaint(ttype);
- register_node_type_cmp_despeckle(ttype);
- register_node_type_cmp_defocus(ttype);
-
- register_node_type_cmp_valtorgb(ttype);
- register_node_type_cmp_rgbtobw(ttype);
- register_node_type_cmp_setalpha(ttype);
- register_node_type_cmp_idmask(ttype);
- register_node_type_cmp_math(ttype);
- register_node_type_cmp_seprgba(ttype);
- register_node_type_cmp_combrgba(ttype);
- register_node_type_cmp_sephsva(ttype);
- register_node_type_cmp_combhsva(ttype);
- register_node_type_cmp_sepyuva(ttype);
- register_node_type_cmp_combyuva(ttype);
- register_node_type_cmp_sepycca(ttype);
- register_node_type_cmp_combycca(ttype);
- register_node_type_cmp_premulkey(ttype);
-
- register_node_type_cmp_diff_matte(ttype);
- register_node_type_cmp_distance_matte(ttype);
- register_node_type_cmp_chroma_matte(ttype);
- register_node_type_cmp_color_matte(ttype);
- register_node_type_cmp_channel_matte(ttype);
- register_node_type_cmp_color_spill(ttype);
- register_node_type_cmp_luma_matte(ttype);
- register_node_type_cmp_doubleedgemask(ttype);
- register_node_type_cmp_keyingscreen(ttype);
- register_node_type_cmp_keying(ttype);
-
- register_node_type_cmp_translate(ttype);
- register_node_type_cmp_rotate(ttype);
- register_node_type_cmp_scale(ttype);
- register_node_type_cmp_flip(ttype);
- register_node_type_cmp_crop(ttype);
- register_node_type_cmp_displace(ttype);
- register_node_type_cmp_mapuv(ttype);
- register_node_type_cmp_glare(ttype);
- register_node_type_cmp_tonemap(ttype);
- register_node_type_cmp_lensdist(ttype);
- register_node_type_cmp_transform(ttype);
- register_node_type_cmp_stabilize2d(ttype);
- register_node_type_cmp_moviedistortion(ttype);
-
- register_node_type_cmp_colorcorrection(ttype);
- register_node_type_cmp_boxmask(ttype);
- register_node_type_cmp_ellipsemask(ttype);
- register_node_type_cmp_bokehimage(ttype);
- register_node_type_cmp_bokehblur(ttype);
- register_node_type_cmp_switch(ttype);
- register_node_type_cmp_pixelate(ttype);
-
- register_node_type_cmp_mask(ttype);
- register_node_type_cmp_trackpos(ttype);
-}
-
-static void registerShaderNodes(bNodeTreeType *ttype)
-{
- register_node_type_frame(ttype);
- register_node_type_reroute(ttype);
-
- register_node_type_sh_group(ttype);
-
- register_node_type_sh_output(ttype);
- register_node_type_sh_material(ttype);
- register_node_type_sh_camera(ttype);
- register_node_type_sh_gamma(ttype);
- register_node_type_sh_brightcontrast(ttype);
- register_node_type_sh_value(ttype);
- register_node_type_sh_rgb(ttype);
- register_node_type_sh_mix_rgb(ttype);
- register_node_type_sh_valtorgb(ttype);
- register_node_type_sh_rgbtobw(ttype);
- register_node_type_sh_texture(ttype);
- register_node_type_sh_normal(ttype);
- register_node_type_sh_geom(ttype);
- register_node_type_sh_mapping(ttype);
- register_node_type_sh_curve_vec(ttype);
- register_node_type_sh_curve_rgb(ttype);
- register_node_type_sh_math(ttype);
- register_node_type_sh_vect_math(ttype);
- register_node_type_sh_squeeze(ttype);
- register_node_type_sh_material_ext(ttype);
- register_node_type_sh_invert(ttype);
- register_node_type_sh_seprgb(ttype);
- register_node_type_sh_combrgb(ttype);
- register_node_type_sh_hue_sat(ttype);
-
- register_node_type_sh_attribute(ttype);
- register_node_type_sh_geometry(ttype);
- register_node_type_sh_light_path(ttype);
- register_node_type_sh_light_falloff(ttype);
- register_node_type_sh_object_info(ttype);
- register_node_type_sh_fresnel(ttype);
- register_node_type_sh_layer_weight(ttype);
- register_node_type_sh_tex_coord(ttype);
- register_node_type_sh_particle_info(ttype);
- register_node_type_sh_bump(ttype);
- register_node_type_sh_script(ttype);
- register_node_type_sh_tangent(ttype);
- register_node_type_sh_normal_map(ttype);
-
- register_node_type_sh_background(ttype);
- register_node_type_sh_bsdf_anisotropic(ttype);
- register_node_type_sh_bsdf_diffuse(ttype);
- register_node_type_sh_bsdf_glossy(ttype);
- register_node_type_sh_bsdf_glass(ttype);
- register_node_type_sh_bsdf_refraction(ttype);
- register_node_type_sh_bsdf_translucent(ttype);
- register_node_type_sh_bsdf_transparent(ttype);
- register_node_type_sh_bsdf_velvet(ttype);
- register_node_type_sh_emission(ttype);
- register_node_type_sh_holdout(ttype);
- register_node_type_sh_ambient_occlusion(ttype);
- //register_node_type_sh_volume_transparent(ttype);
- //register_node_type_sh_volume_isotropic(ttype);
- register_node_type_sh_mix_shader(ttype);
- register_node_type_sh_add_shader(ttype);
-
- register_node_type_sh_output_lamp(ttype);
- register_node_type_sh_output_material(ttype);
- register_node_type_sh_output_world(ttype);
-
- register_node_type_sh_tex_image(ttype);
- register_node_type_sh_tex_environment(ttype);
- register_node_type_sh_tex_sky(ttype);
- register_node_type_sh_tex_noise(ttype);
- register_node_type_sh_tex_wave(ttype);
- register_node_type_sh_tex_voronoi(ttype);
- register_node_type_sh_tex_musgrave(ttype);
- register_node_type_sh_tex_gradient(ttype);
- register_node_type_sh_tex_magic(ttype);
- register_node_type_sh_tex_checker(ttype);
- register_node_type_sh_tex_brick(ttype);
-}
-
-static void registerTextureNodes(bNodeTreeType *ttype)
-{
- register_node_type_frame(ttype);
- register_node_type_reroute(ttype);
-
- register_node_type_tex_group(ttype);
-
- register_node_type_tex_math(ttype);
- register_node_type_tex_mix_rgb(ttype);
- register_node_type_tex_valtorgb(ttype);
- register_node_type_tex_rgbtobw(ttype);
- register_node_type_tex_valtonor(ttype);
- register_node_type_tex_curve_rgb(ttype);
- register_node_type_tex_curve_time(ttype);
- register_node_type_tex_invert(ttype);
- register_node_type_tex_hue_sat(ttype);
- register_node_type_tex_coord(ttype);
- register_node_type_tex_distance(ttype);
- register_node_type_tex_compose(ttype);
- register_node_type_tex_decompose(ttype);
-
- register_node_type_tex_output(ttype);
- register_node_type_tex_viewer(ttype);
-
- register_node_type_tex_checker(ttype);
- register_node_type_tex_texture(ttype);
- register_node_type_tex_bricks(ttype);
- register_node_type_tex_image(ttype);
-
- register_node_type_tex_rotate(ttype);
- register_node_type_tex_translate(ttype);
- register_node_type_tex_scale(ttype);
- register_node_type_tex_at(ttype);
-
- register_node_type_tex_proc_voronoi(ttype);
- register_node_type_tex_proc_blend(ttype);
- register_node_type_tex_proc_magic(ttype);
- register_node_type_tex_proc_marble(ttype);
- register_node_type_tex_proc_clouds(ttype);
- register_node_type_tex_proc_wood(ttype);
- register_node_type_tex_proc_musgrave(ttype);
- register_node_type_tex_proc_noise(ttype);
- register_node_type_tex_proc_stucci(ttype);
- register_node_type_tex_proc_distnoise(ttype);
-}
-
-static void free_typeinfos(ListBase *list)
-{
- bNodeType *ntype, *next;
- for (ntype = list->first; ntype; ntype = next) {
- next = ntype->next;
-
- if (ntype->needs_free)
- MEM_freeN(ntype);
- }
+ strcpy(NodeTreeTypeUndefined.idname, "NodeTreeUndefined");
+ strcpy(NodeTreeTypeUndefined.ui_name, "Undefined");
+ strcpy(NodeTreeTypeUndefined.ui_description, "Undefined Node Tree Type");
+
+ node_type_base_custom(&NodeTypeUndefined, "NodeUndefined", "Undefined", 0, 0);
+ NodeTypeUndefined.poll = node_undefined_poll;
+
+ BLI_strncpy(NodeSocketTypeUndefined.idname, "NodeSocketUndefined", sizeof(NodeSocketTypeUndefined.idname));
+ /* extra type info for standard socket types */
+ NodeSocketTypeUndefined.type = SOCK_CUSTOM;
+ NodeSocketTypeUndefined.subtype = PROP_NONE;
+}
+
+static void registerCompositNodes(void)
+{
+ register_node_type_cmp_group();
+
+ register_node_type_cmp_rlayers();
+ register_node_type_cmp_image();
+ register_node_type_cmp_texture();
+ register_node_type_cmp_value();
+ register_node_type_cmp_rgb();
+ register_node_type_cmp_curve_time();
+ register_node_type_cmp_movieclip();
+
+ register_node_type_cmp_composite();
+ register_node_type_cmp_viewer();
+ register_node_type_cmp_splitviewer();
+ register_node_type_cmp_output_file();
+ register_node_type_cmp_view_levels();
+
+ register_node_type_cmp_curve_rgb();
+ register_node_type_cmp_mix_rgb();
+ register_node_type_cmp_hue_sat();
+ register_node_type_cmp_brightcontrast();
+ register_node_type_cmp_gamma();
+ register_node_type_cmp_invert();
+ register_node_type_cmp_alphaover();
+ register_node_type_cmp_zcombine();
+ register_node_type_cmp_colorbalance();
+ register_node_type_cmp_huecorrect();
+
+ register_node_type_cmp_normal();
+ register_node_type_cmp_curve_vec();
+ register_node_type_cmp_map_value();
+ register_node_type_cmp_map_range();
+ register_node_type_cmp_normalize();
+
+ register_node_type_cmp_filter();
+ register_node_type_cmp_blur();
+ register_node_type_cmp_dblur();
+ register_node_type_cmp_bilateralblur();
+ register_node_type_cmp_vecblur();
+ register_node_type_cmp_dilateerode();
+ register_node_type_cmp_inpaint();
+ register_node_type_cmp_despeckle();
+ register_node_type_cmp_defocus();
+
+ register_node_type_cmp_valtorgb();
+ register_node_type_cmp_rgbtobw();
+ register_node_type_cmp_setalpha();
+ register_node_type_cmp_idmask();
+ register_node_type_cmp_math();
+ register_node_type_cmp_seprgba();
+ register_node_type_cmp_combrgba();
+ register_node_type_cmp_sephsva();
+ register_node_type_cmp_combhsva();
+ register_node_type_cmp_sepyuva();
+ register_node_type_cmp_combyuva();
+ register_node_type_cmp_sepycca();
+ register_node_type_cmp_combycca();
+ register_node_type_cmp_premulkey();
+
+ register_node_type_cmp_diff_matte();
+ register_node_type_cmp_distance_matte();
+ register_node_type_cmp_chroma_matte();
+ register_node_type_cmp_color_matte();
+ register_node_type_cmp_channel_matte();
+ register_node_type_cmp_color_spill();
+ register_node_type_cmp_luma_matte();
+ register_node_type_cmp_doubleedgemask();
+ register_node_type_cmp_keyingscreen();
+ register_node_type_cmp_keying();
+
+ register_node_type_cmp_translate();
+ register_node_type_cmp_rotate();
+ register_node_type_cmp_scale();
+ register_node_type_cmp_flip();
+ register_node_type_cmp_crop();
+ register_node_type_cmp_displace();
+ register_node_type_cmp_mapuv();
+ register_node_type_cmp_glare();
+ register_node_type_cmp_tonemap();
+ register_node_type_cmp_lensdist();
+ register_node_type_cmp_transform();
+ register_node_type_cmp_stabilize2d();
+ register_node_type_cmp_moviedistortion();
+
+ register_node_type_cmp_colorcorrection();
+ register_node_type_cmp_boxmask();
+ register_node_type_cmp_ellipsemask();
+ register_node_type_cmp_bokehimage();
+ register_node_type_cmp_bokehblur();
+ register_node_type_cmp_switch();
+ register_node_type_cmp_pixelate();
+
+ register_node_type_cmp_mask();
+ register_node_type_cmp_trackpos();
+}
+
+static void registerShaderNodes(void)
+{
+ register_node_type_sh_group();
+
+ register_node_type_sh_output();
+ register_node_type_sh_material();
+ register_node_type_sh_camera();
+ register_node_type_sh_gamma();
+ register_node_type_sh_brightcontrast();
+ register_node_type_sh_value();
+ register_node_type_sh_rgb();
+ register_node_type_sh_mix_rgb();
+ register_node_type_sh_valtorgb();
+ register_node_type_sh_rgbtobw();
+ register_node_type_sh_texture();
+ register_node_type_sh_normal();
+ register_node_type_sh_geom();
+ register_node_type_sh_mapping();
+ register_node_type_sh_curve_vec();
+ register_node_type_sh_curve_rgb();
+ register_node_type_sh_math();
+ register_node_type_sh_vect_math();
+ register_node_type_sh_squeeze();
+ register_node_type_sh_material_ext();
+ register_node_type_sh_invert();
+ register_node_type_sh_seprgb();
+ register_node_type_sh_combrgb();
+ register_node_type_sh_hue_sat();
+
+ register_node_type_sh_attribute();
+ register_node_type_sh_geometry();
+ register_node_type_sh_light_path();
+ register_node_type_sh_light_falloff();
+ register_node_type_sh_object_info();
+ register_node_type_sh_fresnel();
+ register_node_type_sh_layer_weight();
+ register_node_type_sh_tex_coord();
+ register_node_type_sh_particle_info();
+ register_node_type_sh_bump();
+
+ register_node_type_sh_background();
+ register_node_type_sh_bsdf_anisotropic();
+ register_node_type_sh_bsdf_diffuse();
+ register_node_type_sh_bsdf_glossy();
+ register_node_type_sh_bsdf_glass();
+ register_node_type_sh_bsdf_translucent();
+ register_node_type_sh_bsdf_transparent();
+ register_node_type_sh_bsdf_velvet();
+ register_node_type_sh_emission();
+ register_node_type_sh_holdout();
+ //register_node_type_sh_volume_transparent();
+ //register_node_type_sh_volume_isotropic();
+ register_node_type_sh_mix_shader();
+ register_node_type_sh_add_shader();
+
+ register_node_type_sh_output_lamp();
+ register_node_type_sh_output_material();
+ register_node_type_sh_output_world();
+
+ register_node_type_sh_tex_image();
+ register_node_type_sh_tex_environment();
+ register_node_type_sh_tex_sky();
+ register_node_type_sh_tex_noise();
+ register_node_type_sh_tex_wave();
+ register_node_type_sh_tex_voronoi();
+ register_node_type_sh_tex_musgrave();
+ register_node_type_sh_tex_gradient();
+ register_node_type_sh_tex_magic();
+ register_node_type_sh_tex_checker();
+ register_node_type_sh_tex_brick();
+}
+
+static void registerTextureNodes(void)
+{
+ register_node_type_tex_group();
+
+
+ register_node_type_tex_math();
+ register_node_type_tex_mix_rgb();
+ register_node_type_tex_valtorgb();
+ register_node_type_tex_rgbtobw();
+ register_node_type_tex_valtonor();
+ register_node_type_tex_curve_rgb();
+ register_node_type_tex_curve_time();
+ register_node_type_tex_invert();
+ register_node_type_tex_hue_sat();
+ register_node_type_tex_coord();
+ register_node_type_tex_distance();
+ register_node_type_tex_compose();
+ register_node_type_tex_decompose();
+
+ register_node_type_tex_output();
+ register_node_type_tex_viewer();
+ register_node_type_sh_script();
+ register_node_type_sh_tangent();
+ register_node_type_sh_normal_map();
+ register_node_type_sh_hair_info();
+
+ register_node_type_tex_checker();
+ register_node_type_tex_texture();
+ register_node_type_tex_bricks();
+ register_node_type_tex_image();
+ register_node_type_sh_bsdf_refraction();
+ register_node_type_sh_ambient_occlusion();
+
+ register_node_type_tex_rotate();
+ register_node_type_tex_translate();
+ register_node_type_tex_scale();
+ register_node_type_tex_at();
+
+ register_node_type_tex_proc_voronoi();
+ register_node_type_tex_proc_blend();
+ register_node_type_tex_proc_magic();
+ register_node_type_tex_proc_marble();
+ register_node_type_tex_proc_clouds();
+ register_node_type_tex_proc_wood();
+ register_node_type_tex_proc_musgrave();
+ register_node_type_tex_proc_noise();
+ register_node_type_tex_proc_stucci();
+ register_node_type_tex_proc_distnoise();
}
void init_nodesystem(void)
{
- /* init clipboard */
- node_clipboard.nodes.first = node_clipboard.nodes.last = NULL;
- node_clipboard.links.first = node_clipboard.links.last = NULL;
+ nodetreetypes_hash = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "nodetreetypes_hash gh");
+ nodetypes_hash = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "nodetypes_hash gh");
+ nodesockettypes_hash = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "nodesockettypes_hash gh");
+
+ register_undefined_types();
+
+ register_standard_node_socket_types();
+
+ register_node_tree_type_cmp();
+ register_node_tree_type_sh();
+ register_node_tree_type_tex();
+
+ register_node_type_frame();
+ register_node_type_reroute();
+ register_node_type_group_input();
+ register_node_type_group_output();
- registerCompositNodes(ntreeGetType(NTREE_COMPOSIT));
- registerShaderNodes(ntreeGetType(NTREE_SHADER));
- registerTextureNodes(ntreeGetType(NTREE_TEXTURE));
+ registerCompositNodes();
+ registerShaderNodes();
+ registerTextureNodes();
}
void free_nodesystem(void)
{
- free_typeinfos(&ntreeGetType(NTREE_COMPOSIT)->node_types);
- free_typeinfos(&ntreeGetType(NTREE_SHADER)->node_types);
- free_typeinfos(&ntreeGetType(NTREE_TEXTURE)->node_types);
+ NODE_TYPES_BEGIN(nt)
+ if (nt->ext.free) {
+ nt->ext.free(nt->ext.data);
+ }
+ NODE_TYPES_END
+
+ NODE_SOCKET_TYPES_BEGIN(st)
+ if (st->ext_socket.free)
+ st->ext_socket.free(st->ext_socket.data);
+ if (st->ext_interface.free)
+ st->ext_interface.free(st->ext_interface.data);
+ NODE_SOCKET_TYPES_END
+
+ NODE_TREE_TYPES_BEGIN(nt)
+ if (nt->ext.free) {
+ nt->ext.free(nt->ext.data);
+ }
+ NODE_TREE_TYPES_END
+
+ BLI_ghash_free(nodetypes_hash, NULL, node_free_type);
+ nodetypes_hash = NULL;
+
+ BLI_ghash_free(nodesockettypes_hash, NULL, node_free_socket_type);
+ nodesockettypes_hash = NULL;
+
+ BLI_ghash_free(nodetreetypes_hash, NULL, ntree_free_type);
+ nodetreetypes_hash = NULL;
}
/* called from BKE_scene_unlink, when deleting a scene goes over all scenes
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 425990d7583..f3655e94eb0 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -57,14 +57,17 @@
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
#include "DNA_object_types.h"
+#include "DNA_property_types.h"
+#include "DNA_rigidbody_types.h"
#include "BLI_blenlib.h"
-#include "BLI_bpath.h"
#include "BLI_math.h"
-#include "BLI_pbvh.h"
#include "BLI_utildefines.h"
#include "BLI_linklist.h"
+#include "BLF_translation.h"
+
+#include "BKE_pbvh.h"
#include "BKE_main.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
@@ -73,6 +76,7 @@
#include "BKE_bullet.h"
#include "BKE_colortools.h"
#include "BKE_deform.h"
+#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_animsys.h"
#include "BKE_anim.h"
@@ -83,10 +87,12 @@
#include "BKE_fcurve.h"
#include "BKE_group.h"
#include "BKE_icons.h"
+#include "BKE_image.h"
#include "BKE_key.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
+#include "BKE_linestyle.h"
#include "BKE_mesh.h"
#include "BKE_tessmesh.h"
#include "BKE_mball.h"
@@ -97,6 +103,7 @@
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_property.h"
+#include "BKE_rigidbody.h"
#include "BKE_sca.h"
#include "BKE_scene.h"
#include "BKE_sequencer.h"
@@ -181,7 +188,7 @@ void BKE_object_free_modifiers(Object *ob)
BKE_object_free_softbody(ob);
}
-int BKE_object_support_modifier_type_check(Object *ob, int modifier_type)
+bool BKE_object_support_modifier_type_check(Object *ob, int modifier_type)
{
ModifierTypeInfo *mti;
@@ -190,10 +197,10 @@ int BKE_object_support_modifier_type_check(Object *ob, int modifier_type)
if (!((mti->flags & eModifierTypeFlag_AcceptsCVs) ||
(ob->type == OB_MESH && (mti->flags & eModifierTypeFlag_AcceptsMesh))))
{
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src)
@@ -264,20 +271,56 @@ void free_sculptsession_deformMats(SculptSession *ss)
ss->deform_imats = NULL;
}
+/* Write out the sculpt dynamic-topology BMesh to the Mesh */
+void sculptsession_bm_to_me(struct Object *ob, int reorder)
+{
+ if (ob && ob->sculpt) {
+ SculptSession *ss = ob->sculpt;
+
+ if (ss->bm) {
+ if (ob->data) {
+ BMIter iter;
+ BMFace *efa;
+ BM_ITER_MESH (efa, &iter, ss->bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_set(efa, BM_ELEM_SMOOTH,
+ ss->bm_smooth_shading);
+ }
+ if (reorder)
+ BM_log_mesh_elems_reorder(ss->bm, ss->bm_log);
+ BM_mesh_bm_to_me(ss->bm, ob->data, FALSE);
+ }
+ }
+
+ /* ensure the objects DerivedMesh mesh doesn't hold onto arrays now realloc'd in the mesh [#34473] */
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+}
+
void free_sculptsession(Object *ob)
{
if (ob && ob->sculpt) {
SculptSession *ss = ob->sculpt;
DerivedMesh *dm = ob->derivedFinal;
+ if (ss->bm) {
+ sculptsession_bm_to_me(ob, TRUE);
+ BM_mesh_free(ss->bm);
+ }
+
if (ss->pbvh)
- BLI_pbvh_free(ss->pbvh);
+ BKE_pbvh_free(ss->pbvh);
+ if (ss->bm_log)
+ BM_log_free(ss->bm_log);
+
if (dm && dm->getPBVH)
dm->getPBVH(NULL, dm); /* signal to clear */
if (ss->texcache)
MEM_freeN(ss->texcache);
+ if (ss->tex_pool)
+ BKE_image_pool_free(ss->tex_pool);
+
if (ss->layer_co)
MEM_freeN(ss->layer_co);
@@ -349,9 +392,11 @@ void BKE_object_free(Object *ob)
free_controllers(&ob->controllers);
free_actuators(&ob->actuators);
- free_constraints(&ob->constraints);
+ BKE_free_constraints(&ob->constraints);
free_partdeflect(ob->pd);
+ BKE_rigidbody_free_object(ob);
+ BKE_rigidbody_free_constraint(ob);
if (ob->soft) sbFree(ob->soft);
if (ob->bsoft) bsbFree(ob->bsoft);
@@ -368,7 +413,8 @@ static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Objec
if (*obpoin == unlinkOb) {
*obpoin = NULL;
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; // XXX: should this just be OB_RECALC_DATA?
+ // XXX: should this just be OB_RECALC_DATA?
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
}
@@ -380,6 +426,8 @@ void BKE_object_unlink(Object *ob)
World *wrld;
bScreen *sc;
Scene *sce;
+ SceneRenderLayer *srl;
+ FreestyleLineSet *lineset;
Curve *cu;
Tex *tex;
Group *group;
@@ -402,14 +450,14 @@ void BKE_object_unlink(Object *ob)
obt->proxy = NULL;
if (obt->proxy_from == ob) {
obt->proxy_from = NULL;
- obt->recalc |= OB_RECALC_OB;
+ DAG_id_tag_update(&obt->id, OB_RECALC_OB);
}
if (obt->proxy_group == ob)
obt->proxy_group = NULL;
if (obt->parent == ob) {
obt->parent = NULL;
- obt->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&obt->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
modifiers_foreachObjectLink(obt, unlink_object__unlinkModifierLinks, ob);
@@ -419,22 +467,22 @@ void BKE_object_unlink(Object *ob)
if (cu->bevobj == ob) {
cu->bevobj = NULL;
- obt->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&obt->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
if (cu->taperobj == ob) {
cu->taperobj = NULL;
- obt->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&obt->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
if (cu->textoncurve == ob) {
cu->textoncurve = NULL;
- obt->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&obt->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
}
else if (obt->type == OB_ARMATURE && obt->pose) {
bPoseChannel *pchan;
for (pchan = obt->pose->chanbase.first; pchan; pchan = pchan->next) {
for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -445,7 +493,7 @@ void BKE_object_unlink(Object *ob)
if (ct->tar == ob) {
ct->tar = NULL;
ct->subtarget[0] = '\0';
- obt->recalc |= OB_RECALC_DATA;
+ DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
}
}
@@ -459,13 +507,13 @@ void BKE_object_unlink(Object *ob)
}
else if (ELEM(OB_MBALL, ob->type, obt->type)) {
if (BKE_mball_is_basis_for(obt, ob))
- obt->recalc |= OB_RECALC_DATA;
+ DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
}
sca_remove_ob_poin(obt, ob);
for (con = obt->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -476,7 +524,7 @@ void BKE_object_unlink(Object *ob)
if (ct->tar == ob) {
ct->tar = NULL;
ct->subtarget[0] = '\0';
- obt->recalc |= OB_RECALC_DATA;
+ DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
}
}
@@ -488,12 +536,12 @@ void BKE_object_unlink(Object *ob)
/* object is deflector or field */
if (ob->pd) {
if (obt->soft)
- obt->recalc |= OB_RECALC_DATA;
+ DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
/* cloth */
for (md = obt->modifiers.first; md; md = md->next)
if (md->type == eModifierType_Cloth)
- obt->recalc |= OB_RECALC_DATA;
+ DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
}
/* strips */
@@ -522,14 +570,14 @@ void BKE_object_unlink(Object *ob)
for (; pt; pt = pt->next) {
if (pt->ob == ob) {
pt->ob = NULL;
- obt->recalc |= OB_RECALC_DATA;
+ DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
break;
}
}
if (tpsys->target_ob == ob) {
tpsys->target_ob = NULL;
- obt->recalc |= OB_RECALC_DATA;
+ DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
}
if (tpsys->part->dup_ob == ob)
@@ -564,7 +612,7 @@ void BKE_object_unlink(Object *ob)
}
}
if (ob->pd)
- obt->recalc |= OB_RECALC_DATA;
+ DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
}
obt = obt->id.next;
@@ -632,6 +680,13 @@ void BKE_object_unlink(Object *ob)
}
SEQ_END
}
+
+ for (srl= sce->r.layers.first; srl; srl= srl->next) {
+ for (lineset = (FreestyleLineSet *)&srl->freestyleConfig.linesets.first;
+ lineset; lineset = lineset->next) {
+ BKE_unlink_linestyle_target_object(lineset->linestyle, ob);
+ }
+ }
}
sce = sce->id.next;
@@ -729,18 +784,62 @@ void BKE_object_unlink(Object *ob)
}
}
-int BKE_object_exists_check(Object *obtest)
+/* actual check for internal data, not context or flags */
+bool BKE_object_is_in_editmode(Object *ob)
+{
+ if (ob->data == NULL)
+ return false;
+
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ if (me->edit_btmesh)
+ return true;
+ }
+ else if (ob->type == OB_ARMATURE) {
+ bArmature *arm = ob->data;
+
+ if (arm->edbo)
+ return true;
+ }
+ else if (ob->type == OB_FONT) {
+ Curve *cu = ob->data;
+
+ if (cu->editfont)
+ return true;
+ }
+ else if (ob->type == OB_MBALL) {
+ MetaBall *mb = ob->data;
+
+ if (mb->editelems)
+ return true;
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = ob->data;
+
+ if (lt->editlatt)
+ return true;
+ }
+ else if (ob->type == OB_SURF || ob->type == OB_CURVE) {
+ Curve *cu = ob->data;
+
+ if (cu->editnurb)
+ return true;
+ }
+ return false;
+}
+
+bool BKE_object_exists_check(Object *obtest)
{
Object *ob;
- if (obtest == NULL) return 0;
+ if (obtest == NULL) return false;
ob = G.main->object.first;
while (ob) {
- if (ob == obtest) return 1;
+ if (ob == obtest) return true;
ob = ob->id.next;
}
- return 0;
+ return false;
}
/* *************************************************** */
@@ -748,16 +847,16 @@ int BKE_object_exists_check(Object *obtest)
void *BKE_object_obdata_add_from_type(int type)
{
switch (type) {
- case OB_MESH: return BKE_mesh_add("Mesh");
- case OB_CURVE: return BKE_curve_add("Curve", OB_CURVE);
- case OB_SURF: return BKE_curve_add("Surf", OB_SURF);
- case OB_FONT: return BKE_curve_add("Text", OB_FONT);
- case OB_MBALL: return BKE_mball_add("Meta");
- case OB_CAMERA: return BKE_camera_add("Camera");
- case OB_LAMP: return BKE_lamp_add("Lamp");
- case OB_LATTICE: return BKE_lattice_add("Lattice");
- case OB_ARMATURE: return BKE_armature_add("Armature");
- case OB_SPEAKER: return BKE_speaker_add("Speaker");
+ case OB_MESH: return BKE_mesh_add(G.main, "Mesh");
+ case OB_CURVE: return BKE_curve_add(G.main, "Curve", OB_CURVE);
+ case OB_SURF: return BKE_curve_add(G.main, "Surf", OB_SURF);
+ case OB_FONT: return BKE_curve_add(G.main, "Text", OB_FONT);
+ case OB_MBALL: return BKE_mball_add(G.main, "Meta");
+ case OB_CAMERA: return BKE_camera_add(G.main, "Camera");
+ case OB_LAMP: return BKE_lamp_add(G.main, "Lamp");
+ case OB_LATTICE: return BKE_lattice_add(G.main, "Lattice");
+ case OB_ARMATURE: return BKE_armature_add(G.main, "Armature");
+ case OB_SPEAKER: return BKE_speaker_add(G.main, "Speaker");
case OB_EMPTY: return NULL;
default:
printf("BKE_object_obdata_add_from_type: Internal error, bad type: %d\n", type);
@@ -768,32 +867,32 @@ void *BKE_object_obdata_add_from_type(int type)
static const char *get_obdata_defname(int type)
{
switch (type) {
- case OB_MESH: return "Mesh";
- case OB_CURVE: return "Curve";
- case OB_SURF: return "Surf";
- case OB_FONT: return "Text";
- case OB_MBALL: return "Mball";
- case OB_CAMERA: return "Camera";
- case OB_LAMP: return "Lamp";
- case OB_LATTICE: return "Lattice";
- case OB_ARMATURE: return "Armature";
- case OB_SPEAKER: return "Speaker";
- case OB_EMPTY: return "Empty";
+ case OB_MESH: return DATA_("Mesh");
+ case OB_CURVE: return DATA_("Curve");
+ case OB_SURF: return DATA_("Surf");
+ case OB_FONT: return DATA_("Text");
+ case OB_MBALL: return DATA_("Mball");
+ case OB_CAMERA: return DATA_("Camera");
+ case OB_LAMP: return DATA_("Lamp");
+ case OB_LATTICE: return DATA_("Lattice");
+ case OB_ARMATURE: return DATA_("Armature");
+ case OB_SPEAKER: return DATA_("Speaker");
+ case OB_EMPTY: return DATA_("Empty");
default:
printf("get_obdata_defname: Internal error, bad type: %d\n", type);
- return "Empty";
+ return DATA_("Empty");
}
}
/* more general add: creates minimum required data, but without vertices etc. */
-Object *BKE_object_add_only_object(int type, const char *name)
+Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
{
Object *ob;
if (!name)
name = get_obdata_defname(type);
- ob = BKE_libblock_alloc(&G.main->object, ID_OB, name);
+ ob = BKE_libblock_alloc(&bmain->object, ID_OB, name);
/* default object vars */
ob->type = type;
@@ -879,7 +978,7 @@ Object *BKE_object_add(struct Scene *scene, int type)
char name[MAX_ID_NAME];
BLI_strncpy(name, get_obdata_defname(type), sizeof(name));
- ob = BKE_object_add_only_object(type, name);
+ ob = BKE_object_add_only_object(G.main, type, name);
ob->data = BKE_object_obdata_add_from_type(type);
@@ -888,7 +987,7 @@ Object *BKE_object_add(struct Scene *scene, int type)
base = BKE_scene_base_add(scene, ob);
BKE_scene_base_deselect_all(scene);
BKE_scene_base_select(scene, base);
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
return ob;
}
@@ -1085,7 +1184,7 @@ static void copy_object_pose(Object *obn, Object *ob)
}
for (con = chan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -1145,13 +1244,13 @@ void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
copy_v3_v3(ob_tar->size, ob_src->size);
}
-static Object *object_copy_do(Object *ob, int copy_caches)
+Object *BKE_object_copy_ex(Main *bmain, Object *ob, int copy_caches)
{
Object *obn;
ModifierData *md;
int a;
- obn = BKE_libblock_copy(&ob->id);
+ obn = BKE_libblock_copy_ex(bmain, &ob->id);
if (ob->totcol) {
obn->mat = MEM_dupallocN(ob->mat);
@@ -1185,7 +1284,7 @@ static Object *object_copy_do(Object *ob, int copy_caches)
BKE_pose_rebuild(obn, obn->data);
}
defgroup_copy_list(&obn->defbase, &ob->defbase);
- copy_constraints(&obn->constraints, &ob->constraints, TRUE);
+ BKE_copy_constraints(&obn->constraints, &ob->constraints, TRUE);
obn->mode = 0;
obn->sculpt = NULL;
@@ -1208,6 +1307,8 @@ static Object *object_copy_do(Object *ob, int copy_caches)
}
obn->soft = copy_softbody(ob->soft, copy_caches);
obn->bsoft = copy_bulletsoftbody(ob->bsoft);
+ obn->rigidbody_object = BKE_rigidbody_copy_object(ob);
+ obn->rigidbody_constraint = BKE_rigidbody_copy_constraint(ob);
BKE_object_copy_particlesystems(obn, ob);
@@ -1225,13 +1326,7 @@ static Object *object_copy_do(Object *ob, int copy_caches)
/* copy objects, will re-initialize cached simulation data */
Object *BKE_object_copy(Object *ob)
{
- return object_copy_do(ob, FALSE);
-}
-
-/* copy objects, will duplicate cached simulation data */
-Object *BKE_object_copy_with_caches(Object *ob)
-{
- return object_copy_do(ob, TRUE);
+ return BKE_object_copy_ex(G.main, ob, FALSE);
}
static void extern_local_object(Object *ob)
@@ -1311,24 +1406,24 @@ void BKE_object_make_local(Object *ob)
/*
* Returns true if the Object is a from an external blend file (libdata)
*/
-int BKE_object_is_libdata(Object *ob)
+bool BKE_object_is_libdata(Object *ob)
{
- if (!ob) return 0;
- if (ob->proxy) return 0;
- if (ob->id.lib) return 1;
- return 0;
+ if (!ob) return false;
+ if (ob->proxy) return false;
+ if (ob->id.lib) return true;
+ return false;
}
/* Returns true if the Object data is a from an external blend file (libdata) */
-int BKE_object_obdata_is_libdata(Object *ob)
+bool BKE_object_obdata_is_libdata(Object *ob)
{
- if (!ob) return 0;
- if (ob->proxy && (ob->data == NULL || ((ID *)ob->data)->lib == NULL)) return 0;
- if (ob->id.lib) return 1;
- if (ob->data == NULL) return 0;
- if (((ID *)ob->data)->lib) return 1;
+ if (!ob) return false;
+ if (ob->proxy && (ob->data == NULL || ((ID *)ob->data)->lib == NULL)) return false;
+ if (ob->id.lib) return true;
+ if (ob->data == NULL) return false;
+ if (((ID *)ob->data)->lib) return true;
- return 0;
+ return false;
}
/* *************** PROXY **************** */
@@ -1402,7 +1497,8 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob)
ob->proxy_group = gob;
id_lib_extern(&target->id);
- ob->recalc = target->recalc = OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DAG_id_tag_update(&target->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* copy transform
* - gob means this proxy comes from a group, just apply the matrix
@@ -1495,7 +1591,7 @@ void BKE_object_scale_to_mat3(Object *ob, float mat[3][3])
size_to_mat3(mat, vec);
}
-void BKE_object_rot_to_mat3(Object *ob, float mat[3][3])
+void BKE_object_rot_to_mat3(Object *ob, float mat[3][3], bool use_drot)
{
float rmat[3][3], dmat[3][3];
@@ -1526,10 +1622,13 @@ void BKE_object_rot_to_mat3(Object *ob, float mat[3][3])
}
/* combine these rotations */
- mul_m3_m3m3(mat, dmat, rmat);
+ if (use_drot)
+ mul_m3_m3m3(mat, dmat, rmat);
+ else
+ copy_m3_m3(mat, rmat);
}
-void BKE_object_mat3_to_rot(Object *ob, float mat[3][3], short use_compat)
+void BKE_object_mat3_to_rot(Object *ob, float mat[3][3], bool use_compat)
{
switch (ob->rotmode) {
case ROT_MODE_QUAT:
@@ -1632,7 +1731,7 @@ void BKE_object_tfm_protected_restore(Object *ob,
}
/* see BKE_pchan_apply_mat4() for the equivalent 'pchan' function */
-void BKE_object_apply_mat4(Object *ob, float mat[4][4], const short use_compat, const short use_parent)
+void BKE_object_apply_mat4(Object *ob, float mat[4][4], const bool use_compat, const bool use_parent)
{
float rot[3][3];
@@ -1671,7 +1770,7 @@ void BKE_object_to_mat3(Object *ob, float mat[3][3]) /* no parent */
BKE_object_scale_to_mat3(ob, smat);
/* rot */
- BKE_object_rot_to_mat3(ob, rmat);
+ BKE_object_rot_to_mat3(ob, rmat, TRUE);
mul_m3_m3m3(mat, rmat, smat);
}
@@ -1722,7 +1821,7 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
CLAMP(ctime, 0.0f, 1.0f);
}
else {
- ctime = scene->r.cfra;
+ ctime = BKE_scene_frame_get(scene);
if (IS_EQF(cu->pathlen, 0.0f) == 0)
ctime /= cu->pathlen;
@@ -1792,12 +1891,19 @@ static void ob_parbone(Object *ob, Object *par, float mat[4][4])
}
/* get bone transform */
- copy_m4_m4(mat, pchan->pose_mat);
+ if (pchan->bone->flag & BONE_RELATIVE_PARENTING) {
+ /* the new option uses the root - expected bahaviour, but differs from old... */
+ /* XXX check on version patching? */
+ copy_m4_m4(mat, pchan->chan_mat);
+ }
+ else {
+ copy_m4_m4(mat, pchan->pose_mat);
- /* but for backwards compatibility, the child has to move to the tail */
- copy_v3_v3(vec, mat[1]);
- mul_v3_fl(vec, pchan->bone->length);
- add_v3_v3(mat[3], vec);
+ /* but for backwards compatibility, the child has to move to the tail */
+ copy_v3_v3(vec, mat[1]);
+ mul_v3_fl(vec, pchan->bone->length);
+ add_v3_v3(mat[3], vec);
+ }
}
static void give_parvert(Object *par, int nr, float vec[3])
@@ -1875,7 +1981,7 @@ 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 = BKE_curve_nurbs_get(cu);
BKE_nurbList_index_get_co(nurb, nr, vec);
}
@@ -1926,7 +2032,7 @@ static void ob_parvert3(Object *ob, Object *par, float mat[4][4])
else {
add_v3_v3v3(mat[3], v1, v2);
add_v3_v3(mat[3], v3);
- mul_v3_fl(mat[3], 0.3333333f);
+ mul_v3_fl(mat[3], 1.0f / 3.0f);
}
}
}
@@ -2029,7 +2135,9 @@ static int where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat[
return 1;
}
-void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime)
+/* note, scene is the active scene while actual_scene is the scene the object resides in */
+void BKE_object_where_is_calc_time_ex(Scene *scene, Object *ob, float ctime,
+ RigidBodyWorld *rbw)
{
if (ob == NULL) return;
@@ -2054,14 +2162,19 @@ void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime)
else {
BKE_object_to_mat4(ob, ob->obmat);
}
+
+ /* try to fall back to the scene rigid body world if none given */
+ rbw = rbw ? rbw : scene->rigidbody_world;
+ /* read values pushed into RBO from sim/cache... */
+ BKE_rigidbody_sync_transforms(rbw, ob, ctime);
/* solve constraints */
if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) {
bConstraintOb *cob;
- cob = constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
- solve_constraints(&ob->constraints, cob, ctime);
- constraints_clear_evalob(cob);
+ cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
+ BKE_solve_constraints(&ob->constraints, cob, ctime);
+ BKE_constraints_clear_evalob(cob);
}
/* set negative scale flag in object */
@@ -2069,6 +2182,11 @@ void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime)
else ob->transflag &= ~OB_NEG_SCALE;
}
+void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime)
+{
+ BKE_object_where_is_calc_time_ex(scene, ob, ctime, NULL);
+}
+
/* get object transformation matrix without recalculating dependencies and
* constraints -- assume dependencies are already solved by depsgraph.
* no changes to object and it's parent would be done.
@@ -2090,15 +2208,19 @@ void BKE_object_where_is_calc_mat4(Scene *scene, Object *ob, float obmat[4][4])
}
}
-void BKE_object_where_is_calc(struct Scene *scene, Object *ob)
+void BKE_object_where_is_calc_ex(Scene *scene, RigidBodyWorld *rbw, Object *ob)
{
- BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra);
+ BKE_object_where_is_calc_time_ex(scene, ob, BKE_scene_frame_get(scene), rbw);
+}
+void BKE_object_where_is_calc(Scene *scene, Object *ob)
+{
+ BKE_object_where_is_calc_time_ex(scene, ob, BKE_scene_frame_get(scene), NULL);
}
-void BKE_object_where_is_calc_simul(Scene *scene, Object *ob)
/* was written for the old game engine (until 2.04) */
/* It seems that this function is only called
* for a lamp that is the child of another object */
+void BKE_object_where_is_calc_simul(Scene *scene, Object *ob)
{
Object *par;
float *fp1, *fp2;
@@ -2130,9 +2252,9 @@ void BKE_object_where_is_calc_simul(Scene *scene, Object *ob)
if (ob->constraints.first) {
bConstraintOb *cob;
- cob = constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
- solve_constraints(&ob->constraints, cob, (float)scene->r.cfra);
- constraints_clear_evalob(cob);
+ cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
+ BKE_solve_constraints(&ob->constraints, cob, BKE_scene_frame_get(scene));
+ BKE_constraints_clear_evalob(cob);
}
}
@@ -2250,7 +2372,7 @@ void BKE_object_dimensions_set(Object *ob, const float *value)
}
}
-void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const short use_hidden)
+void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool use_hidden)
{
BoundBox bb;
float vec[3];
@@ -2354,7 +2476,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const short u
}
}
-int BKE_object_minmax_dupli(Scene *scene, Object *ob, float r_min[3], float r_max[3], const short use_hidden)
+int BKE_object_minmax_dupli(Scene *scene, Object *ob, float r_min[3], float r_max[3], const bool use_hidden)
{
int ok = FALSE;
if ((ob->transflag & OB_DUPLI) == 0) {
@@ -2366,7 +2488,7 @@ int BKE_object_minmax_dupli(Scene *scene, Object *ob, float r_min[3], float r_ma
lb = object_duplilist(scene, ob, FALSE);
for (dob = lb->first; dob; dob = dob->next) {
- if ((use_hidden == FALSE) && (dob->no_draw != 0)) {
+ if ((use_hidden == false) && (dob->no_draw != 0)) {
/* pass */
}
else {
@@ -2513,11 +2635,11 @@ void BKE_object_tfm_restore(Object *ob, void *obtfm_pt)
copy_m4_m4(ob->imat, obtfm->imat);
}
-int BKE_object_parent_loop_check(const Object *par, const Object *ob)
+bool BKE_object_parent_loop_check(const Object *par, const Object *ob)
{
/* test if 'ob' is a parent somewhere in par's parents */
- if (par == NULL) return 0;
- if (ob == par) return 1;
+ if (par == NULL) return false;
+ if (ob == par) return true;
return BKE_object_parent_loop_check(par->parent, ob);
}
@@ -2528,7 +2650,9 @@ int BKE_object_parent_loop_check(const Object *par, const Object *ob)
/* the main object update call, for object matrix, constraints, keys and displist (modifiers) */
/* requires flags to be set! */
-void BKE_object_handle_update(Scene *scene, Object *ob)
+/* Ideally we shouldn't have to pass the rigid body world, but need bigger restructuring to avoid id */
+void BKE_object_handle_update_ex(Scene *scene, Object *ob,
+ RigidBodyWorld *rbw)
{
if (ob->recalc & OB_RECALC_ALL) {
/* speed optimization for animation lookups */
@@ -2569,13 +2693,13 @@ void BKE_object_handle_update(Scene *scene, Object *ob)
copy_m4_m4(ob->obmat, ob->proxy_from->obmat);
}
else
- BKE_object_where_is_calc(scene, ob);
+ BKE_object_where_is_calc_ex(scene, rbw, ob);
}
if (ob->recalc & OB_RECALC_DATA) {
ID *data_id = (ID *)ob->data;
AnimData *adt = BKE_animdata_from_id(data_id);
- float ctime = (float)scene->r.cfra; /* XXX this is bad... */
+ float ctime = BKE_scene_frame_get(scene);
if (G.debug & G_DEBUG)
printf("recalcdata %s\n", ob->id.name + 2);
@@ -2616,8 +2740,10 @@ void BKE_object_handle_update(Scene *scene, Object *ob)
case OB_ARMATURE:
if (ob->id.lib && ob->proxy_from) {
- // printf("pose proxy copy, lib ob %s proxy %s\n", ob->id.name, ob->proxy_from->id.name);
- BKE_pose_copy_result(ob->pose, ob->proxy_from->pose);
+ 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);
@@ -2721,6 +2847,15 @@ void BKE_object_handle_update(Scene *scene, Object *ob)
// printf("set proxy pointer for later group stuff %s\n", ob->id.name);
}
}
+/* WARNING: "scene" here may not be the scene object actually resides in.
+ * When dealing with background-sets, "scene" is actually the active scene.
+ * e.g. "scene" <-- set 1 <-- set 2 ("ob" lives here) <-- set 3 <-- ... <-- set n
+ * rigid bodies depend on their world so use BKE_object_handle_update_ex() to also pass along the corrent rigid body world
+ */
+void BKE_object_handle_update(Scene *scene, Object *ob)
+{
+ BKE_object_handle_update_ex(scene, ob, NULL);
+}
void BKE_object_sculpt_modifiers_changed(Object *ob)
{
@@ -2731,7 +2866,7 @@ void BKE_object_sculpt_modifiers_changed(Object *ob)
* changing PVBH node organization, we hope topology does not change in
* the meantime .. weak */
if (ss->pbvh) {
- BLI_pbvh_free(ss->pbvh);
+ BKE_pbvh_free(ss->pbvh);
ss->pbvh = NULL;
}
@@ -2741,10 +2876,10 @@ void BKE_object_sculpt_modifiers_changed(Object *ob)
PBVHNode **nodes;
int n, totnode;
- BLI_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
for (n = 0; n < totnode; n++)
- BLI_pbvh_node_mark_update(nodes[n]);
+ BKE_pbvh_node_mark_update(nodes[n]);
MEM_freeN(nodes);
}
@@ -2897,12 +3032,13 @@ static KeyBlock *insert_meshkey(Scene *scene, Object *ob, const char *name, int
}
else {
/* copy from current values */
- float *data = do_ob_key(scene, ob);
+ int totelem;
+ float *data = BKE_key_evaluate_object(scene, ob, &totelem);
/* create new block with prepared data */
kb = BKE_keyblock_add_ctime(key, name, FALSE);
kb->data = data;
- kb->totelem = me->totvert;
+ kb->totelem = totelem;
}
return kb;
@@ -2934,11 +3070,12 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, int
}
else {
/* copy from current values */
- float *data = do_ob_key(scene, ob);
+ int totelem;
+ float *data = BKE_key_evaluate_object(scene, ob, &totelem);
/* create new block with prepared data */
kb = BKE_keyblock_add_ctime(key, name, FALSE);
- kb->totelem = lt->pntsu * lt->pntsv * lt->pntsw;
+ kb->totelem = totelem;
kb->data = data;
}
@@ -2973,11 +3110,12 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, int
}
else {
/* copy from current values */
- float *data = do_ob_key(scene, ob);
+ int totelem;
+ float *data = BKE_key_evaluate_object(scene, ob, &totelem);
/* create new block with prepared data */
kb = BKE_keyblock_add_ctime(key, name, FALSE);
- kb->totelem = BKE_nurbList_verts_count(lb);
+ kb->totelem = totelem;
kb->data = data;
}
@@ -3000,6 +3138,16 @@ KeyBlock *BKE_object_insert_shape_key(Scene *scene, Object *ob, const char *name
}
+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) {
+ if (ob_child == ob_parent) {
+ return true;
+ }
+ }
+ return false;
+}
+
/* most important if this is modified it should _always_ return True, in certain
* cases false positives are hard to avoid (shape keys for example) */
int BKE_object_is_modified(Scene *scene, Object *ob)
@@ -3055,7 +3203,7 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob)
}
/* See if an object is using an animated modifier */
-int BKE_object_is_animated(Scene *scene, Object *ob)
+bool BKE_object_is_animated(Scene *scene, Object *ob)
{
ModifierData *md;
@@ -3064,9 +3212,9 @@ int BKE_object_is_animated(Scene *scene, Object *ob)
(modifier_isEnabled(scene, md, eModifierMode_Realtime) ||
modifier_isEnabled(scene, md, eModifierMode_Render)))
{
- return 1;
+ return true;
}
- return 0;
+ return false;
}
static void copy_object__forwardModifierLinks(void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin)
@@ -3080,17 +3228,20 @@ void BKE_object_relink(Object *ob)
if (ob->id.lib)
return;
- relink_constraints(&ob->constraints);
+ BKE_relink_constraints(&ob->constraints);
if (ob->pose) {
bPoseChannel *chan;
for (chan = ob->pose->chanbase.first; chan; chan = chan->next) {
- relink_constraints(&chan->constraints);
+ BKE_relink_constraints(&chan->constraints);
}
}
modifiers_foreachIDLink(ob, copy_object__forwardModifierLinks, NULL);
if (ob->adt)
BKE_relink_animdata(ob->adt);
+
+ if (ob->rigidbody_constraint)
+ BKE_rigidbody_relink_constraint(ob->rigidbody_constraint);
ID_NEW(ob->parent);
@@ -3146,18 +3297,6 @@ static Object *obrel_armature_find(Object *ob)
return ob_arm;
}
-static int obrel_is_recursive_child(Object *ob, Object *child)
-{
- Object *par;
- for (par = child->parent; par; par = par->parent) {
- if (par == ob) {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-
static int obrel_list_test(Object *ob)
{
return ob && !(ob->id.flag & LIB_DOIT);
@@ -3230,7 +3369,7 @@ LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectS
Object *child = local_base->object;
if (obrel_list_test(child)) {
- if ((includeFilter & OB_REL_CHILDREN_RECURSIVE && obrel_is_recursive_child(ob, child)) ||
+ if ((includeFilter & OB_REL_CHILDREN_RECURSIVE && BKE_object_is_child_recursive(ob, child)) ||
(includeFilter & OB_REL_CHILDREN && child->parent && child->parent == ob))
{
obrel_list_add(&links, child);
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index e694a7e7eb3..695ac7da792 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -35,18 +35,16 @@
#include "DNA_scene_types.h"
-#include "BKE_image.h"
-#include "BKE_ocean.h"
-#include "BKE_global.h" // XXX TESTING
-
-#include "BLI_math_base.h"
-#include "BLI_math_inline.h"
+#include "BLI_math.h"
+#include "BLI_path_util.h"
#include "BLI_rand.h"
#include "BLI_string.h"
#include "BLI_threads.h"
-#include "BLI_path_util.h"
#include "BLI_utildefines.h"
+#include "BKE_image.h"
+#include "BKE_ocean.h"
+
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -54,7 +52,7 @@
#ifdef WITH_OCEANSIM
-// Ocean code
+/* Ocean code */
#include "fftw3.h"
#define GRAVITY 9.81f
@@ -82,7 +80,7 @@ typedef struct Ocean {
float _Lx;
float _Lz;
- float normalize_factor; // init w
+ float normalize_factor; /* init w */
float time;
short _do_disp_y;
@@ -96,51 +94,52 @@ typedef struct Ocean {
/* ********* sim data arrays ********* */
/* two dimensional arrays of complex */
- fftw_complex *_fft_in; // init w sim w
- fftw_complex *_fft_in_x; // init w sim w
- fftw_complex *_fft_in_z; // init w sim w
- fftw_complex *_fft_in_jxx; // init w sim w
- fftw_complex *_fft_in_jzz; // init w sim w
- fftw_complex *_fft_in_jxz; // init w sim w
- fftw_complex *_fft_in_nx; // init w sim w
- fftw_complex *_fft_in_nz; // init w sim w
- fftw_complex *_htilda; // init w sim w (only once)
+ fftw_complex *_fft_in; /* init w sim w */
+ fftw_complex *_fft_in_x; /* init w sim w */
+ fftw_complex *_fft_in_z; /* init w sim w */
+ fftw_complex *_fft_in_jxx; /* init w sim w */
+ fftw_complex *_fft_in_jzz; /* init w sim w */
+ fftw_complex *_fft_in_jxz; /* init w sim w */
+ fftw_complex *_fft_in_nx; /* init w sim w */
+ fftw_complex *_fft_in_nz; /* init w sim w */
+ fftw_complex *_htilda; /* init w sim w (only once) */
/* fftw "plans" */
- fftw_plan _disp_y_plan; // init w sim r
- fftw_plan _disp_x_plan; // init w sim r
- fftw_plan _disp_z_plan; // init w sim r
- fftw_plan _N_x_plan; // init w sim r
- fftw_plan _N_z_plan; // init w sim r
- fftw_plan _Jxx_plan; // init w sim r
- fftw_plan _Jxz_plan; // init w sim r
- fftw_plan _Jzz_plan; // init w sim r
+ fftw_plan _disp_y_plan; /* init w sim r */
+ fftw_plan _disp_x_plan; /* init w sim r */
+ fftw_plan _disp_z_plan; /* init w sim r */
+ fftw_plan _N_x_plan; /* init w sim r */
+ fftw_plan _N_z_plan; /* init w sim r */
+ fftw_plan _Jxx_plan; /* init w sim r */
+ fftw_plan _Jxz_plan; /* init w sim r */
+ fftw_plan _Jzz_plan; /* init w sim r */
/* two dimensional arrays of float */
- double *_disp_y; // init w sim w via plan?
- double *_N_x; // init w sim w via plan?
- /*float * _N_y; all member of this array has same values, so convert this array to a float to reduce memory usage (MEM01)*/
- double _N_y; // sim w ********* can be rearranged?
- double *_N_z; // init w sim w via plan?
- double *_disp_x; // init w sim w via plan?
- double *_disp_z; // init w sim w via plan?
+ double *_disp_y; /* init w sim w via plan? */
+ double *_N_x; /* init w sim w via plan? */
+ /* all member of this array has same values, so convert this array to a float to reduce memory usage (MEM01)*/
+ /*float * _N_y; */
+ double _N_y; /* sim w ********* can be rearranged? */
+ double *_N_z; /* init w sim w via plan? */
+ double *_disp_x; /* init w sim w via plan? */
+ double *_disp_z; /* init w sim w via plan? */
/* two dimensional arrays of float */
/* Jacobian and minimum eigenvalue */
- double *_Jxx; // init w sim w
- double *_Jzz; // init w sim w
- double *_Jxz; // init w sim w
+ double *_Jxx; /* init w sim w */
+ double *_Jzz; /* init w sim w */
+ double *_Jxz; /* init w sim w */
/* one dimensional float array */
- float *_kx; // init w sim r
- float *_kz; // init w sim r
+ float *_kx; /* init w sim r */
+ float *_kz; /* init w sim r */
/* two dimensional complex array */
- fftw_complex *_h0; // init w sim r
- fftw_complex *_h0_minus; // init w sim r
+ fftw_complex *_h0; /* init w sim r */
+ fftw_complex *_h0_minus; /* init w sim r */
/* two dimensional float array */
- float *_k; // init w sim r
+ float *_k; /* init w sim r */
} Ocean;
@@ -152,10 +151,13 @@ static float nextfr(float min, float max)
static float gaussRand(void)
{
- float x; // Note: to avoid numerical problems with very small
- float y; // numbers, we make these variables singe-precision
- float length2; // floats, but later we call the double-precision log()
- // and sqrt() functions instead of logf() and sqrtf().
+ /* Note: to avoid numerical problems with very small numbers, we make these variables singe-precision floats,
+ * but later we call the double-precision log() and sqrt() functions instead of logf() and sqrtf().
+ */
+ float x;
+ float y;
+ float length2;
+
do {
x = (float) (nextfr(-1, 1));
y = (float)(nextfr(-1, 1));
@@ -167,12 +169,7 @@ static float gaussRand(void)
/**
* Some useful functions
- * */
-MINLINE float lerp(float a, float b, float f)
-{
- return a + (b - a) * f;
-}
-
+ */
MINLINE float catrom(float p0, float p1, float p2, float p3, float f)
{
return 0.5f * ((2.0f * p1) +
@@ -186,23 +183,24 @@ MINLINE float omega(float k, float depth)
return sqrtf(GRAVITY * k * tanhf(k * depth));
}
-// modified Phillips spectrum
+/* modified Phillips spectrum */
static float Ph(struct Ocean *o, float kx, float kz)
{
float tmp;
float k2 = kx * kx + kz * kz;
if (k2 == 0.0f) {
- return 0.0f; // no DC component
+ return 0.0f; /* no DC component */
}
- // damp out the waves going in the direction opposite the wind
+ /* damp out the waves going in the direction opposite the wind */
tmp = (o->_wx * kx + o->_wz * kz) / sqrtf(k2);
if (tmp < 0) {
tmp *= o->_damp_reflections;
}
- return o->_A * expf(-1.0f / (k2 * (o->_L * o->_L))) * expf(-k2 * (o->_l * o->_l)) * powf(fabsf(tmp), o->_wind_alignment) / (k2 * k2);
+ return o->_A * expf(-1.0f / (k2 * (o->_L * o->_L))) * expf(-k2 * (o->_l * o->_l)) *
+ powf(fabsf(tmp), o->_wind_alignment) / (k2 * k2);
}
static void compute_eigenstuff(struct OceanResult *ocr, float jxx, float jzz, float jxz)
@@ -240,7 +238,7 @@ static void init_complex(fftw_complex cmpl, float real, float image)
cmpl[1] = image;
}
-#if 0 // unused
+#if 0 /* unused */
static void add_complex_f(fftw_complex res, fftw_complex cmpl, float f)
{
res[0] = cmpl[0] + f;
@@ -306,7 +304,7 @@ void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float
float frac_x, frac_z;
float uu, vv;
- // first wrap the texture so 0 <= (u, v) < 1
+ /* first wrap the texture so 0 <= (u, v) < 1 */
u = fmodf(u, 1.0f);
v = fmodf(v, 1.0f);
@@ -334,7 +332,9 @@ void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float
j1 = j1 % oc->_N;
-#define BILERP(m) (lerp(lerp(m[i0 * oc->_N + j0], m[i1 * oc->_N + j0], frac_x), lerp(m[i0 * oc->_N + j1], m[i1 * oc->_N + j1], frac_x), frac_z))
+#define BILERP(m) (interpf(interpf(m[i1 * oc->_N + j1], m[i0 * oc->_N + j1], frac_x), \
+ interpf(m[i1 * oc->_N + j0], m[i0 * oc->_N + j0], frac_x), \
+ frac_z))
{
if (oc->_do_disp_y) {
ocr->disp[1] = BILERP(oc->_disp_y);
@@ -364,14 +364,14 @@ void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float
BLI_rw_mutex_unlock(&oc->oceanmutex);
}
-// use catmullrom interpolation rather than linear
+/* use catmullrom interpolation rather than linear */
void BKE_ocean_eval_uv_catrom(struct Ocean *oc, struct OceanResult *ocr, float u, float v)
{
int i0, i1, i2, i3, j0, j1, j2, j3;
float frac_x, frac_z;
float uu, vv;
- // first wrap the texture so 0 <= (u, v) < 1
+ /* first wrap the texture so 0 <= (u, v) < 1 */
u = fmod(u, 1.0f);
v = fmod(v, 1.0f);
@@ -408,11 +408,15 @@ void BKE_ocean_eval_uv_catrom(struct Ocean *oc, struct OceanResult *ocr, float u
j0 = j0 < 0 ? j0 + oc->_N : j0;
j3 = j3 >= oc->_N ? j3 - oc->_N : j3;
-#define INTERP(m) catrom(catrom(m[i0 * oc->_N + j0], m[i1 * oc->_N + j0], m[i2 * oc->_N + j0], m[i3 * oc->_N + j0], frac_x), \
- catrom(m[i0 * oc->_N + j1], m[i1 * oc->_N + j1], m[i2 * oc->_N + j1], m[i3 * oc->_N + j1], frac_x), \
- catrom(m[i0 * oc->_N + j2], m[i1 * oc->_N + j2], m[i2 * oc->_N + j2], m[i3 * oc->_N + j2], frac_x), \
- catrom(m[i0 * oc->_N + j3], m[i1 * oc->_N + j3], m[i2 * oc->_N + j3], m[i3 * oc->_N + j3], frac_x), \
- frac_z)
+#define INTERP(m) catrom(catrom(m[i0 * oc->_N + j0], m[i1 * oc->_N + j0], \
+ m[i2 * oc->_N + j0], m[i3 * oc->_N + j0], frac_x), \
+ catrom(m[i0 * oc->_N + j1], m[i1 * oc->_N + j1], \
+ m[i2 * oc->_N + j1], m[i3 * oc->_N + j1], frac_x), \
+ catrom(m[i0 * oc->_N + j2], m[i1 * oc->_N + j2], \
+ m[i2 * oc->_N + j2], m[i3 * oc->_N + j2], frac_x), \
+ catrom(m[i0 * oc->_N + j3], m[i1 * oc->_N + j3], \
+ m[i2 * oc->_N + j3], m[i3 * oc->_N + j3], frac_x), \
+ frac_z)
{
if (oc->_do_disp_y) {
@@ -452,9 +456,9 @@ void BKE_ocean_eval_xz_catrom(struct Ocean *oc, struct OceanResult *ocr, float x
BKE_ocean_eval_uv_catrom(oc, ocr, x / oc->_Lx, z / oc->_Lz);
}
-// note that this doesn't wrap properly for i, j < 0, but its
-// not really meant for that being just a way to get the raw data out
-// to save in some image format.
+/* note that this doesn't wrap properly for i, j < 0, but its not really meant for that being just a way to get
+ * the raw data out to save in some image format.
+ */
void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j)
{
BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_READ);
@@ -496,11 +500,10 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount
BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE);
- // compute a new htilda
+ /* compute a new htilda */
#pragma omp parallel for private(i, j)
for (i = 0; i < o->_M; ++i) {
- // note the <= _N/2 here, see the fftw doco about
- // the mechanics of the complex->real fft storage
+ /* note the <= _N/2 here, see the fftw doco about the mechanics of the complex->real fft storage */
for (j = 0; j <= o->_N / 2; ++j) {
fftw_complex exp_param1;
fftw_complex exp_param2;
@@ -527,15 +530,15 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount
#pragma omp section
{
if (o->_do_disp_y) {
- // y displacement
+ /* y displacement */
fftw_execute(o->_disp_y_plan);
}
- } // section 1
+ } /* section 1 */
#pragma omp section
{
if (o->_do_chop) {
- // x displacement
+ /* x displacement */
for (i = 0; i < o->_M; ++i) {
for (j = 0; j <= o->_N / 2; ++j) {
fftw_complex mul_param;
@@ -546,18 +549,21 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount
mul_complex_f(mul_param, mul_param, chop_amount);
mul_complex_c(mul_param, mul_param, minus_i);
mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
- mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j]));
+ mul_complex_f(mul_param, mul_param,
+ ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
+ 0.0f :
+ o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j]));
init_complex(o->_fft_in_x[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
}
}
fftw_execute(o->_disp_x_plan);
}
- } //section 2
+ } /* section 2 */
#pragma omp section
{
if (o->_do_chop) {
- // z displacement
+ /* z displacement */
for (i = 0; i < o->_M; ++i) {
for (j = 0; j <= o->_N / 2; ++j) {
fftw_complex mul_param;
@@ -568,28 +574,34 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount
mul_complex_f(mul_param, mul_param, chop_amount);
mul_complex_c(mul_param, mul_param, minus_i);
mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
- mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
+ mul_complex_f(mul_param, mul_param,
+ ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
+ 0.0f :
+ o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
init_complex(o->_fft_in_z[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
}
}
fftw_execute(o->_disp_z_plan);
}
- } // section 3
+ } /* section 3 */
#pragma omp section
{
if (o->_do_jacobian) {
- // Jxx
+ /* Jxx */
for (i = 0; i < o->_M; ++i) {
for (j = 0; j <= o->_N / 2; ++j) {
fftw_complex mul_param;
- //init_complex(mul_param, -scale, 0);
+ /* init_complex(mul_param, -scale, 0); */
init_complex(mul_param, -1, 0);
mul_complex_f(mul_param, mul_param, chop_amount);
mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
- mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kx[i] * o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j]));
+ mul_complex_f(mul_param, mul_param,
+ ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
+ 0.0f :
+ o->_kx[i] * o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j]));
init_complex(o->_fft_in_jxx[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
}
}
@@ -601,22 +613,25 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount
}
}
}
- } // section 4
+ } /* section 4 */
#pragma omp section
{
if (o->_do_jacobian) {
- // Jzz
+ /* Jzz */
for (i = 0; i < o->_M; ++i) {
for (j = 0; j <= o->_N / 2; ++j) {
fftw_complex mul_param;
- //init_complex(mul_param, -scale, 0);
+ /* init_complex(mul_param, -scale, 0); */
init_complex(mul_param, -1, 0);
mul_complex_f(mul_param, mul_param, chop_amount);
mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
- mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kz[j] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
+ mul_complex_f(mul_param, mul_param,
+ ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
+ 0.0f :
+ o->_kz[j] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
init_complex(o->_fft_in_jzz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
}
}
@@ -627,32 +642,35 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount
}
}
}
- } // section 5
+ } /* section 5 */
#pragma omp section
{
if (o->_do_jacobian) {
- // Jxz
+ /* Jxz */
for (i = 0; i < o->_M; ++i) {
for (j = 0; j <= o->_N / 2; ++j) {
fftw_complex mul_param;
- //init_complex(mul_param, -scale, 0);
+ /* init_complex(mul_param, -scale, 0); */
init_complex(mul_param, -1, 0);
mul_complex_f(mul_param, mul_param, chop_amount);
mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]);
- mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kx[i] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
+ mul_complex_f(mul_param, mul_param,
+ ((o->_k[i * (1 + o->_N / 2) + j] == 0.0f) ?
+ 0.0f :
+ o->_kx[i] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j]));
init_complex(o->_fft_in_jxz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param));
}
}
fftw_execute(o->_Jxz_plan);
}
- } // section 6
+ } /* section 6 */
#pragma omp section
{
- // fft normals
+ /* fft normals */
if (o->_do_normals) {
for (i = 0; i < o->_M; ++i) {
for (j = 0; j <= o->_N / 2; ++j) {
@@ -667,7 +685,7 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount
fftw_execute(o->_N_x_plan);
}
- } // section 7
+ } /* section 7 */
#pragma omp section
{
@@ -694,9 +712,9 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount
#endif
o->_N_y = 1.0f / scale;
}
- } // section 8
+ } /* section 8 */
- } // omp sections
+ } /* omp sections */
BLI_rw_mutex_unlock(&o->oceanmutex);
}
@@ -726,7 +744,8 @@ static void set_height_normalize_factor(struct Ocean *oc)
BLI_rw_mutex_unlock(&oc->oceanmutex);
- if (max_h == 0.0f) max_h = 0.00001f; // just in case ...
+ if (max_h == 0.0f)
+ max_h = 0.00001f; /* just in case ... */
res = 1.0f / (max_h);
@@ -743,7 +762,8 @@ struct Ocean *BKE_add_ocean(void)
}
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)
+ float alignment, float depth, float time, short do_height_field, short do_chop, short do_normals,
+ short do_jacobian, int seed)
{
int i, j, ii;
@@ -761,8 +781,8 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V,
o->_Lx = Lx;
o->_Lz = Lz;
o->_wx = cos(w);
- o->_wz = -sin(w); // wave direction
- o->_L = V * V / GRAVITY; // largest wave for a given velocity V
+ o->_wz = -sin(w); /* wave direction */
+ o->_L = V * V / GRAVITY; /* largest wave for a given velocity V */
o->time = time;
o->_do_disp_y = do_height_field;
@@ -776,30 +796,30 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V,
o->_kx = (float *) MEM_mallocN(o->_M * sizeof(float), "ocean_kx");
o->_kz = (float *) MEM_mallocN(o->_N * sizeof(float), "ocean_kz");
- // make this robust in the face of erroneous usage
+ /* make this robust in the face of erroneous usage */
if (o->_Lx == 0.0f)
o->_Lx = 0.001f;
if (o->_Lz == 0.0f)
o->_Lz = 0.001f;
- // the +ve components and DC
+ /* the +ve components and DC */
for (i = 0; i <= o->_M / 2; ++i)
o->_kx[i] = 2.0f * (float)M_PI * i / o->_Lx;
- // the -ve components
+ /* the -ve components */
for (i = o->_M - 1, ii = 0; i > o->_M / 2; --i, ++ii)
o->_kx[i] = -2.0f * (float)M_PI * ii / o->_Lx;
- // the +ve components and DC
+ /* the +ve components and DC */
for (i = 0; i <= o->_N / 2; ++i)
o->_kz[i] = 2.0f * (float)M_PI * i / o->_Lz;
- // the -ve components
+ /* the -ve components */
for (i = o->_N - 1, ii = 0; i > o->_N / 2; --i, ++ii)
o->_kz[i] = -2.0f * (float)M_PI * ii / o->_Lz;
- // pre-calculate the k matrix
+ /* pre-calculate the k matrix */
for (i = 0; i < o->_M; ++i)
for (j = 0; j <= o->_N / 2; ++j)
o->_k[i * (1 + o->_N / 2) + j] = sqrt(o->_kx[i] * o->_kx[i] + o->_kz[j] * o->_kz[j]);
@@ -819,11 +839,11 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V,
}
}
- o->_fft_in = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in");
- o->_htilda = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_htilda");
+ o->_fft_in = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in");
+ o->_htilda = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_htilda");
if (o->_do_disp_y) {
- o->_disp_y = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_y");
+ o->_disp_y = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_y");
o->_disp_y_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in, o->_disp_y, FFTW_ESTIMATE);
}
@@ -831,32 +851,35 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V,
o->_fft_in_nx = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_nx");
o->_fft_in_nz = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_nz");
- o->_N_x = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_x");
+ o->_N_x = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_x");
/* o->_N_y = (float *) fftwf_malloc(o->_M * o->_N * sizeof(float)); (MEM01) */
- o->_N_z = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_z");
+ o->_N_z = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_z");
o->_N_x_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_nx, o->_N_x, FFTW_ESTIMATE);
o->_N_z_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_nz, o->_N_z, FFTW_ESTIMATE);
}
if (o->_do_chop) {
- o->_fft_in_x = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_x");
- o->_fft_in_z = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_z");
+ o->_fft_in_x = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_x");
+ o->_fft_in_z = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_z");
- o->_disp_x = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_x");
- o->_disp_z = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_z");
+ o->_disp_x = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_x");
+ o->_disp_z = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_z");
o->_disp_x_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_x, o->_disp_x, FFTW_ESTIMATE);
o->_disp_z_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_z, o->_disp_z, FFTW_ESTIMATE);
}
if (o->_do_jacobian) {
- o->_fft_in_jxx = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_jxx");
- o->_fft_in_jzz = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_jzz");
- o->_fft_in_jxz = (fftw_complex *) MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in_jxz");
+ o->_fft_in_jxx = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
+ "ocean_fft_in_jxx");
+ o->_fft_in_jzz = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
+ "ocean_fft_in_jzz");
+ o->_fft_in_jxz = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex),
+ "ocean_fft_in_jxz");
- o->_Jxx = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxx");
- o->_Jzz = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jzz");
- o->_Jxz = (double *) MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxz");
+ o->_Jxx = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxx");
+ o->_Jzz = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jzz");
+ o->_Jxz = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_Jxz");
o->_Jxx_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jxx, o->_Jxx, FFTW_ESTIMATE);
o->_Jzz_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jzz, o->_Jzz, FFTW_ESTIMATE);
@@ -967,7 +990,7 @@ static void cache_filename(char *string, const char *path, const char *relbase,
BLI_join_dirfile(cachepath, sizeof(cachepath), path, fname);
- BKE_makepicstring(string, cachepath, relbase, frame, R_IMF_IMTYPE_OPENEXR, 1, TRUE);
+ BKE_makepicstring_from_type(string, cachepath, relbase, frame, R_IMF_IMTYPE_OPENEXR, 1, TRUE);
}
/* silly functions but useful to inline when the args do a lot of indirections */
@@ -1076,8 +1099,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_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)
{
OceanCache *och = MEM_callocN(sizeof(OceanCache), "ocean cache data");
@@ -1112,7 +1134,7 @@ void BKE_simulate_ocean_cache(struct OceanCache *och, int frame)
/* ibufs array is zero based, but filenames are based on frame numbers */
/* still need to clamp frame numbers to valid range of images on disk though */
CLAMP(frame, och->start, och->end);
- f = frame - och->start; // shift to 0 based
+ f = frame - och->start; /* shift to 0 based */
/* if image is already loaded in mem, return */
if (och->ibufs_disp[f] != NULL) return;
@@ -1121,22 +1143,35 @@ void BKE_simulate_ocean_cache(struct OceanCache *och, int frame)
cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_DISPLACE);
och->ibufs_disp[f] = IMB_loadiffname(string, 0, NULL);
- //if (och->ibufs_disp[f] == NULL) printf("error loading %s\n", string);
- //else printf("loaded cache %s\n", string);
+#if 0
+ if (och->ibufs_disp[f] == NULL)
+ printf("error loading %s\n", string);
+ else
+ printf("loaded cache %s\n", string);
+#endif
cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_FOAM);
och->ibufs_foam[f] = IMB_loadiffname(string, 0, NULL);
- //if (och->ibufs_foam[f] == NULL) printf("error loading %s\n", string);
- //else printf("loaded cache %s\n", string);
+#if 0
+ if (och->ibufs_foam[f] == NULL)
+ printf("error loading %s\n", string);
+ else
+ printf("loaded cache %s\n", string);
+#endif
cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_NORMAL);
och->ibufs_norm[f] = IMB_loadiffname(string, 0, NULL);
- //if (och->ibufs_norm[f] == NULL) printf("error loading %s\n", string);
- //else printf("loaded cache %s\n", string);
+#if 0
+ if (och->ibufs_norm[f] == NULL)
+ printf("error loading %s\n", string);
+ else
+ printf("loaded cache %s\n", string);
+#endif
}
-void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(void *, float progress, int *cancel), void *update_cb_data)
+void BKE_bake_ocean(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
* are enabled, take care that BKE_ocean_eval_ij() initializes a member
@@ -1197,13 +1232,13 @@ void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(v
pr = prev_foam[res_x * y + x];
}
- /* r = BLI_frand(); */ /* UNUSED */ // randomly reduce foam
+ /* r = BLI_frand(); */ /* UNUSED */ /* randomly reduce foam */
- //pr = pr * och->foam_fade; // overall fade
+ /* pr = pr * och->foam_fade; */ /* overall fade */
- // remember ocean coord sys is Y up!
- // break up the foam where height (Y) is low (wave valley),
- // and X and Z displacement is greatest
+ /* remember ocean coord sys is Y up!
+ * break up the foam where height (Y) is low (wave valley), and X and Z displacement is greatest
+ */
#if 0
vec[0] = ocr.disp[0];
@@ -1219,22 +1254,27 @@ void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(v
neg_eplus = ocr.Eplus[2] < 0.0f ? 1.0f + ocr.Eplus[2] : 1.0f;
neg_eplus = neg_eplus < 0.0f ? 0.0f : neg_eplus;
- //if (ocr.disp[1] < 0.0 || r > och->foam_fade)
- // pr *= och->foam_fade;
+#if 0
+ if (ocr.disp[1] < 0.0 || r > och->foam_fade)
+ pr *= och->foam_fade;
- //pr = pr * (1.0 - hor_stretch) * ocr.disp[1];
- //pr = pr * neg_disp * neg_eplus;
+ pr = pr * (1.0 - hor_stretch) * ocr.disp[1];
+ pr = pr * neg_disp * neg_eplus;
+#endif
- if (pr < 1.0f) pr *= pr;
+ if (pr < 1.0f)
+ pr *= pr;
pr *= och->foam_fade * (0.75f + neg_eplus * 0.25f);
-
- foam_result = pr + ocr.foam;
+ /* A full clamping should not be needed! */
+ foam_result = min_ff(pr + ocr.foam, 1.0f);
prev_foam[res_x * y + x] = foam_result;
+ /*foam_result = min_ff(foam_result, 1.0f); */
+
value_to_rgba_unit_alpha(&ibuf_foam->rect_float[4 * (res_x * y + x)], foam_result);
}
@@ -1279,7 +1319,7 @@ void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(v
och->baked = 1;
}
-#else // WITH_OCEANSIM
+#else /* WITH_OCEANSIM */
/* stub */
typedef struct Ocean {
@@ -1297,8 +1337,9 @@ void BKE_ocean_eval_uv(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr)
{
}
-// use catmullrom interpolation rather than linear
-void BKE_ocean_eval_uv_catrom(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr), float UNUSED(u), float UNUSED(v))
+/* use catmullrom interpolation rather than linear */
+void BKE_ocean_eval_uv_catrom(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr), float UNUSED(u),
+ float UNUSED(v))
{
}
@@ -1306,7 +1347,8 @@ void BKE_ocean_eval_xz(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr)
{
}
-void BKE_ocean_eval_xz_catrom(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr), float UNUSED(x), float UNUSED(z))
+void BKE_ocean_eval_xz_catrom(struct Ocean *UNUSED(oc), struct OceanResult *UNUSED(ocr), float UNUSED(x),
+ float UNUSED(z))
{
}
@@ -1325,8 +1367,10 @@ struct Ocean *BKE_add_ocean(void)
return oc;
}
-void BKE_init_ocean(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_init_ocean(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))
{
}
@@ -1351,17 +1395,19 @@ void BKE_free_ocean_cache(struct OceanCache *och)
MEM_freeN(och);
}
-void BKE_ocean_cache_eval_uv(struct OceanCache *UNUSED(och), struct OceanResult *UNUSED(ocr), int UNUSED(f), float UNUSED(u), float UNUSED(v))
+void BKE_ocean_cache_eval_uv(struct OceanCache *UNUSED(och), struct OceanResult *UNUSED(ocr), int UNUSED(f),
+ float UNUSED(u), float UNUSED(v))
{
}
-void BKE_ocean_cache_eval_ij(struct OceanCache *UNUSED(och), struct OceanResult *UNUSED(ocr), int UNUSED(f), int UNUSED(i), int UNUSED(j))
+void BKE_ocean_cache_eval_ij(struct OceanCache *UNUSED(och), struct OceanResult *UNUSED(ocr), int UNUSED(f),
+ int UNUSED(i), int UNUSED(j))
{
}
-OceanCache *BKE_init_ocean_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))
+OceanCache *BKE_init_ocean_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))
{
OceanCache *och = MEM_callocN(sizeof(OceanCache), "ocean cache data");
@@ -1372,9 +1418,10 @@ void BKE_simulate_ocean_cache(struct OceanCache *UNUSED(och), int UNUSED(frame))
{
}
-void BKE_bake_ocean(struct Ocean *UNUSED(o), struct OceanCache *UNUSED(och), void (*update_cb)(void *, float progress, int *cancel), void *UNUSED(update_cb_data))
+void BKE_bake_ocean(struct Ocean *UNUSED(o), struct OceanCache *UNUSED(och),
+ void (*update_cb)(void *, float progress, int *cancel), void *UNUSED(update_cb_data))
{
/* unused */
(void)update_cb;
}
-#endif // WITH_OCEANSIM
+#endif /* WITH_OCEANSIM */
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index dec49f417ae..5a02d929b76 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -43,9 +43,10 @@
#include "MEM_guardedalloc.h"
#include "DNA_image_types.h"
+#include "DNA_ID.h"
+#include "DNA_packedFile_types.h"
#include "DNA_sound_types.h"
#include "DNA_vfont_types.h"
-#include "DNA_packedFile_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -226,16 +227,19 @@ PackedFile *newPackedFile(ReportList *reports, const char *filename, const char
return (pf);
}
+/* no libraries for now */
void packAll(Main *bmain, ReportList *reports)
{
Image *ima;
VFont *vfont;
bSound *sound;
+ int tot = 0;
for (ima = bmain->image.first; ima; ima = ima->id.next) {
if (ima->packedfile == NULL && ima->id.lib == NULL) {
if (ima->source == IMA_SRC_FILE) {
ima->packedfile = newPackedFile(reports, ima->name, ID_BLEND_PATH(bmain, &ima->id));
+ tot ++;
}
else if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
BKE_reportf(reports, RPT_WARNING, "Image '%s' skipped, movies and image sequences not supported",
@@ -244,13 +248,26 @@ void packAll(Main *bmain, ReportList *reports)
}
}
- for (vfont = bmain->vfont.first; vfont; vfont = vfont->id.next)
- if (vfont->packedfile == NULL && vfont->id.lib == NULL && BKE_vfont_is_builtin(vfont) == FALSE)
+ for (vfont = bmain->vfont.first; vfont; vfont = vfont->id.next) {
+ if (vfont->packedfile == NULL && vfont->id.lib == NULL && BKE_vfont_is_builtin(vfont) == FALSE) {
vfont->packedfile = newPackedFile(reports, vfont->name, bmain->name);
+ tot ++;
+ }
+ }
- for (sound = bmain->sound.first; sound; sound = sound->id.next)
- if (sound->packedfile == NULL && sound->id.lib == NULL)
+ for (sound = bmain->sound.first; sound; sound = sound->id.next) {
+ if (sound->packedfile == NULL && sound->id.lib == NULL) {
sound->packedfile = newPackedFile(reports, sound->name, bmain->name);
+ tot++;
+ }
+ }
+
+ if (tot == 0)
+ BKE_report(reports, RPT_INFO, "No files have been packed");
+ else
+ BKE_reportf(reports, RPT_INFO, "Packed %d files", tot);
+
+
}
@@ -314,6 +331,9 @@ int writePackedFile(ReportList *reports, const char *filename, PackedFile *pf, i
BKE_reportf(reports, RPT_ERROR, "Error writing file '%s'", name);
ret_value = RET_ERROR;
}
+ else
+ BKE_reportf(reports, RPT_INFO, "Saved packed file to: %s", name);
+
close(file);
}
else {
@@ -328,7 +348,7 @@ int writePackedFile(ReportList *reports, const char *filename, PackedFile *pf, i
}
}
else {
- if (BLI_delete(tempname, 0, 0) != 0) {
+ if (BLI_delete(tempname, false, false) != 0) {
BKE_reportf(reports, RPT_ERROR, "Error deleting '%s' (ignored)", tempname);
}
}
@@ -437,6 +457,7 @@ char *unpackFile(ReportList *reports, const char *abs_name, const char *local_na
case PF_USE_ORIGINAL:
/* if file exists use it */
if (BLI_exists(abs_name)) {
+ BKE_reportf(reports, RPT_INFO, "Use existing file (instead of packed): %s", abs_name);
temp = abs_name;
break;
}
@@ -467,11 +488,8 @@ int unpackVFont(ReportList *reports, VFont *vfont, int how)
int ret_value = RET_ERROR;
if (vfont != NULL) {
- BLI_strncpy(localname, vfont->name, sizeof(localname));
- BLI_splitdirstring(localname, fi);
-
+ 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);
if (newname != NULL) {
ret_value = RET_OK;
@@ -492,10 +510,8 @@ int unpackSound(Main *bmain, ReportList *reports, bSound *sound, int how)
int ret_value = RET_ERROR;
if (sound != NULL) {
- BLI_strncpy(localname, sound->name, sizeof(localname));
- BLI_splitdirstring(localname, fi);
+ 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);
if (newname != NULL) {
BLI_strncpy(sound->name, newname, sizeof(sound->name));
@@ -520,10 +536,8 @@ int unpackImage(ReportList *reports, Image *ima, int how)
int ret_value = RET_ERROR;
if (ima != NULL && ima->name[0]) {
- BLI_strncpy(localname, ima->name, sizeof(localname));
- BLI_splitdirstring(localname, fi);
+ 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;
@@ -538,6 +552,51 @@ int unpackImage(ReportList *reports, Image *ima, int how)
return(ret_value);
}
+int unpackLibraries(Main *bmain, ReportList *reports)
+{
+ Library *lib;
+ char *newname;
+ int ret_value = RET_ERROR;
+
+ for (lib = bmain->library.first; lib; lib = lib->id.next) {
+ if (lib->packedfile && lib->name[0]) {
+
+ newname = unpackFile(reports, lib->filepath, lib->filepath, lib->packedfile, PF_WRITE_ORIGINAL);
+ if (newname != NULL) {
+ ret_value = RET_OK;
+
+ printf("Unpacked .blend library: %s\n", newname);
+
+ freePackedFile(lib->packedfile);
+ lib->packedfile = NULL;
+
+ MEM_freeN(newname);
+ }
+ }
+ }
+
+ return(ret_value);
+}
+
+void packLibraries(Main *bmain, ReportList *reports)
+{
+ Library *lib;
+
+ /* test for relativenss */
+ for (lib = bmain->library.first; lib; lib = lib->id.next)
+ if (!BLI_path_is_rel(lib->name))
+ break;
+
+ if (lib) {
+ BKE_reportf(reports, RPT_ERROR, "Cannot pack absolute file: '%s'", lib->name);
+ return;
+ }
+
+ for (lib = bmain->library.first; lib; lib = lib->id.next)
+ if (lib->packedfile == NULL)
+ lib->packedfile = newPackedFile(reports, lib->name, bmain->name);
+}
+
void unpackAll(Main *bmain, ReportList *reports, int how)
{
Image *ima;
@@ -557,3 +616,48 @@ void unpackAll(Main *bmain, ReportList *reports, int how)
unpackSound(bmain, reports, sound, how);
}
+/* ID should be not NULL, return 1 if there's a packed file */
+bool BKE_pack_check(ID *id)
+{
+ if (GS(id->name) == ID_IM) {
+ Image *ima = (Image *)id;
+ return ima->packedfile != NULL;
+ }
+ if (GS(id->name) == ID_VF) {
+ VFont *vf = (VFont *)id;
+ return vf->packedfile != NULL;
+ }
+ if (GS(id->name) == ID_SO) {
+ bSound *snd = (bSound *)id;
+ return snd->packedfile != NULL;
+ }
+ if (GS(id->name) == ID_LI) {
+ Library *li = (Library *)id;
+ return li->packedfile != NULL;
+ }
+ return false;
+}
+
+/* ID should be not NULL */
+void BKE_unpack_id(Main *bmain, ID *id, ReportList *reports, int how)
+{
+ if (GS(id->name) == ID_IM) {
+ Image *ima = (Image *)id;
+ if (ima->packedfile)
+ unpackImage(reports, ima, how);
+ }
+ if (GS(id->name) == ID_VF) {
+ VFont *vf = (VFont *)id;
+ if (vf->packedfile)
+ unpackVFont(reports, vf, how);
+ }
+ if (GS(id->name) == ID_SO) {
+ bSound *snd = (bSound *)id;
+ if (snd->packedfile)
+ unpackSound(bmain, reports, snd, how);
+ }
+ if (GS(id->name) == ID_LI) {
+ Library *li = (Library *)id;
+ BKE_reportf(reports, RPT_ERROR, "Cannot unpack individual Library file, '%s'", li->name);
+ }
+}
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 36f96045ced..cc647a90c8f 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -40,13 +40,17 @@
#include "BLI_bitmap.h"
#include "BLI_utildefines.h"
+#include "BLI_math_vector.h"
#include "BKE_brush.h"
#include "BKE_context.h"
+#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_paint.h"
#include "BKE_subsurf.h"
+#include "bmesh.h"
+
#include <stdlib.h>
#include <string.h>
@@ -134,6 +138,55 @@ Paint *paint_get_active_from_context(const bContext *C)
return NULL;
}
+PaintMode paintmode_get_active_from_context(const bContext *C)
+{
+ Scene *sce = CTX_data_scene(C);
+ SpaceImage *sima;
+
+ if (sce) {
+ ToolSettings *ts = sce->toolsettings;
+ Object *obact = NULL;
+
+ if (sce->basact && sce->basact->object)
+ obact = sce->basact->object;
+
+ 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;
+ else if (ts->use_uv_sculpt)
+ return PAINT_SCULPT_UV;
+ }
+ else {
+ return PAINT_TEXTURE_2D;
+ }
+ }
+ else if (obact) {
+ switch (obact->mode) {
+ case OB_MODE_SCULPT:
+ return PAINT_SCULPT;
+ case OB_MODE_VERTEX_PAINT:
+ return PAINT_VERTEX;
+ case OB_MODE_WEIGHT_PAINT:
+ return PAINT_WEIGHT;
+ case OB_MODE_TEXTURE_PAINT:
+ return PAINT_TEXTURE_PROJECTIVE;
+ case OB_MODE_EDIT:
+ if (ts->use_uv_sculpt)
+ return PAINT_SCULPT_UV;
+ else
+ return PAINT_TEXTURE_2D;
+ }
+ }
+ else {
+ /* default to image paint */
+ return PAINT_TEXTURE_2D;
+ }
+ }
+
+ return PAINT_INVALID;
+}
+
Brush *paint_brush(Paint *p)
{
return p ? p->brush : NULL;
@@ -154,7 +207,7 @@ int paint_facesel_test(Object *ob)
return ( (ob != NULL) &&
(ob->type == OB_MESH) &&
(ob->data != NULL) &&
- (((Mesh *)ob->data)->editflag & ME_EDIT_PAINT_MASK) &&
+ (((Mesh *)ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) &&
(ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))
);
}
@@ -165,7 +218,7 @@ int paint_vertsel_test(Object *ob)
return ( (ob != NULL) &&
(ob->type == OB_MESH) &&
(ob->data != NULL) &&
- (((Mesh *)ob->data)->editflag & ME_EDIT_VERT_SEL) &&
+ (((Mesh *)ob->data)->editflag & ME_EDIT_PAINT_VERT_SEL) &&
(ob->mode & OB_MODE_WEIGHT_PAINT)
);
}
@@ -177,7 +230,7 @@ void BKE_paint_init(Paint *p, const char col[3])
/* If there's no brush, create one */
brush = paint_brush(p);
if (brush == NULL)
- brush = BKE_brush_add("Brush");
+ brush = BKE_brush_add(G.main, "Brush");
paint_brush_set(p, brush);
memcpy(p->paint_cursor_col, col, 3);
@@ -212,7 +265,7 @@ int paint_is_face_hidden(const MFace *f, const MVert *mvert)
}
/* returns non-zero if any of the corners of the grid
- * face whose inner corner is at (x,y) are hidden,
+ * face whose inner corner is at (x, y) are hidden,
* zero otherwise */
int paint_is_grid_face_hidden(const unsigned int *grid_hidden,
int gridsize, int x, int y)
@@ -224,6 +277,22 @@ int paint_is_grid_face_hidden(const unsigned int *grid_hidden,
BLI_BITMAP_GET(grid_hidden, (y + 1) * gridsize + x));
}
+/* Return TRUE if all vertices in the face are visible, FALSE otherwise */
+int paint_is_bmesh_face_hidden(BMFace *f)
+{
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BM_elem_flag_test(l_iter->v, BM_ELEM_HIDDEN)) {
+ return true;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ return false;
+}
+
float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level,
unsigned x, unsigned y)
{
@@ -232,3 +301,22 @@ float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level,
return gpm->data[(y * factor) * gridsize + (x * factor)];
}
+
+/* threshhold to move before updating the brush rotation */
+#define RAKE_THRESHHOLD 20
+
+void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, const float mouse_pos[2])
+{
+ const float u = 0.5f;
+ const float r = RAKE_THRESHHOLD;
+
+ float dpos[2];
+ sub_v2_v2v2(dpos, ups->last_rake, mouse_pos);
+
+ if (len_squared_v2(dpos) >= r * r) {
+ ups->brush_rotation = atan2(dpos[0], dpos[1]);
+
+ interp_v2_v2v2(ups->last_rake, ups->last_rake,
+ mouse_pos, u);
+ }
+}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 97d8b06d3a7..d9dabf24ba0 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -55,7 +55,8 @@
#include "BLI_rand.h"
#include "BLI_threads.h"
#include "BLI_linklist.h"
-#include "BLI_bpath.h"
+
+#include "BLF_translation.h"
#include "BKE_anim.h"
#include "BKE_animsys.h"
@@ -685,8 +686,6 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], floa
ParticleRenderData *data;
ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
- if (G.is_rendering == FALSE)
- return;
if (psys->renderdata)
return;
@@ -2385,7 +2384,7 @@ void psys_find_parents(ParticleSimulationData *sim)
int from = PART_FROM_FACE;
totparent = (int)(totchild * part->parents * 0.3f);
- if (G.is_rendering && part->child_nbr && part->ren_child_nbr)
+ if ((sim->psys->renderdata || G.is_rendering) && part->child_nbr && part->ren_child_nbr)
totparent *= (float)part->child_nbr / (float)part->ren_child_nbr;
tree = BLI_kdtree_new(totparent);
@@ -2462,7 +2461,7 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c
if (totchild && part->childtype == PART_CHILD_FACES) {
totparent = (int)(totchild * part->parents * 0.3f);
- if (G.is_rendering && part->child_nbr && part->ren_child_nbr)
+ if ((psys->renderdata || G.is_rendering) && part->child_nbr && part->ren_child_nbr)
totparent *= (float)part->child_nbr / (float)part->ren_child_nbr;
/* part->parents could still be 0 so we can't test with totparent */
@@ -3491,17 +3490,19 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *n
psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
BLI_addtail(&ob->particlesystem, psys);
- psys->part = psys_new_settings("ParticleSettings", NULL);
+ psys->part = psys_new_settings(DATA_("ParticleSettings"), NULL);
if (BLI_countlist(&ob->particlesystem) > 1)
- BLI_snprintf(psys->name, sizeof(psys->name), "ParticleSystem %i", BLI_countlist(&ob->particlesystem));
+ BLI_snprintf(psys->name, sizeof(psys->name), DATA_("ParticleSystem %i"), BLI_countlist(&ob->particlesystem));
else
- strcpy(psys->name, "ParticleSystem");
+ strcpy(psys->name, DATA_("ParticleSystem"));
md = modifier_new(eModifierType_ParticleSystem);
- if (name) BLI_strncpy_utf8(md->name, name, sizeof(md->name));
- else BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", BLI_countlist(&ob->particlesystem));
+ 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));
modifier_unique_name(&ob->modifiers, md);
psmd = (ParticleSystemModifierData *) md;
@@ -3512,12 +3513,12 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *n
psys->flag = PSYS_ENABLED | PSYS_CURRENT;
psys->cfra = BKE_scene_frame_get_from_ctime(scene, CFRA + 1);
- DAG_scene_sort(G.main, scene);
+ DAG_relations_tag_update(G.main);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
return md;
}
-void object_remove_particle_system(Scene *scene, Object *ob)
+void object_remove_particle_system(Scene *UNUSED(scene), Object *ob)
{
ParticleSystem *psys = psys_get_current(ob);
ParticleSystemModifierData *psmd;
@@ -3555,7 +3556,7 @@ void object_remove_particle_system(Scene *scene, Object *ob)
else
ob->mode &= ~OB_MODE_PARTICLE_EDIT;
- DAG_scene_sort(G.main, scene);
+ DAG_relations_tag_update(G.main);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
static void default_particle_settings(ParticleSettings *part)
@@ -3850,7 +3851,7 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti
break;
}
- externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0);
+ externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL);
if ((event & mtex->mapto) & PAMAP_ROUGH)
ptex->rough1 = ptex->rough2 = ptex->roughe = texture_value_blend(def, ptex->rough1, value, mtex->roughfac, blend);
@@ -3921,7 +3922,7 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex
break;
}
- externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0);
+ externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL);
if ((event & mtex->mapto) & PAMAP_TIME) {
/* the first time has to set the base value for time regardless of blend mode */
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 90889d7c09e..3efe25794e1 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -23,7 +23,8 @@
* Contributor(s): Raul Fernandez Hernandez (Farsthary), Stephen Swhitehorn.
*
* Adaptive time step
- * Copyright 2011 AutoCRC
+ * Classical SPH
+ * Copyright 2011-2012 AutoCRC
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -521,9 +522,9 @@ static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
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;
+ 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)) {
@@ -801,7 +802,7 @@ static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, Ch
if (mface->v4)
psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv);
else
- psys_uv_to_w(0.33333f, 0.33333f, mface->v4, pa->fuv);
+ 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);
@@ -1889,7 +1890,6 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
bpa->data.acc[0]=bpa->data.acc[1]=bpa->data.acc[2]=0.0f;
}
-
if (part->type == PART_HAIR) {
pa->lifetime = 100.0f;
}
@@ -2390,33 +2390,37 @@ typedef struct SPHRangeData {
SPHNeighbor neighbors[SPH_NEIGHBORS];
int tot_neighbors;
- float density, near_density;
- float h;
+ float* data;
ParticleSystem *npsys;
ParticleData *pa;
+ float h;
+ float mass;
float massfac;
int use_size;
} SPHRangeData;
-typedef struct SPHData {
- ParticleSystem *psys[10];
- ParticleData *pa;
- float mass;
- EdgeHash *eh;
- float *gravity;
- /* Average distance to neighbors (other particles in the support domain),
- * for calculating the Courant number (adaptive time step). */
- int pass;
- float element_size;
- float flow[3];
-
- /* Integrator callbacks. This allows different SPH implementations. */
- void (*force_cb) (void *sphdata_v, ParticleKey *state, float *force, float *impulse);
- void (*density_cb) (void *rangedata_v, int index, float squared_dist);
-} SPHData;
+static void sph_evaluate_func(BVHTree *tree, ParticleSystem **psys, float co[3], SPHRangeData *pfr, float interaction_radius, BVHTree_RangeQuery callback)
+{
+ int i;
+ pfr->tot_neighbors = 0;
+
+ for (i=0; i < 10 && psys[i]; i++) {
+ pfr->npsys = psys[i];
+ pfr->massfac = psys[i]->part->mass / pfr->mass;
+ pfr->use_size = psys[i]->part->flag & PART_SIZEMASS;
+
+ if (tree) {
+ BLI_bvhtree_range_query(tree, co, interaction_radius, callback, pfr);
+ break;
+ }
+ else {
+ BLI_bvhtree_range_query(psys[i]->bvhtree, co, interaction_radius, callback, pfr);
+ }
+ }
+}
static void sph_density_accum_cb(void *userdata, int index, float squared_dist)
{
SPHRangeData *pfr = (SPHRangeData *)userdata;
@@ -2446,8 +2450,8 @@ static void sph_density_accum_cb(void *userdata, int index, float squared_dist)
if (pfr->use_size)
q *= npa->size;
- pfr->density += q*q;
- pfr->near_density += q*q*q;
+ pfr->data[0] += q*q;
+ pfr->data[1] += q*q*q;
}
/*
@@ -2488,7 +2492,6 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa
ParticleSpring *spring = NULL;
SPHRangeData pfr;
SPHNeighbor *pfn;
- float mass = sphdata->mass;
float *gravity = sphdata->gravity;
EdgeHash *springhash = sphdata->eh;
@@ -2498,10 +2501,12 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa
float visc = fluid->viscosity_omega;
float stiff_visc = fluid->viscosity_beta * (fluid->flag & SPH_FAC_VISCOSITY ? fluid->viscosity_omega : 1.f);
- float inv_mass = 1.0f/mass;
+ float inv_mass = 1.0f / sphdata->mass;
float spring_constant = fluid->spring_k;
-
- float h = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.f*pa->size : 1.f); /* 4.0 seems to be a pretty good value */
+
+ /* 4.0 seems to be a pretty good value */
+ float interaction_radius = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.0f * pa->size : 1.0f);
+ float h = interaction_radius * sphdata->hfac;
float rest_density = fluid->rest_density * (fluid->flag & SPH_FAC_DENSITY ? 4.77f : 1.f); /* 4.77 is an experimentally determined density factor */
float rest_length = fluid->rest_length * (fluid->flag & SPH_FAC_REST_LENGTH ? 2.588f * pa->size : 1.f);
@@ -2512,24 +2517,24 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa
float vec[3];
float vel[3];
float co[3];
+ float data[2];
+ float density, near_density;
int i, spring_index, index = pa - psys[0]->particles;
- pfr.tot_neighbors = 0;
- pfr.density = pfr.near_density = 0.f;
+ data[0] = data[1] = 0;
+ pfr.data = data;
pfr.h = h;
pfr.pa = pa;
+ pfr.mass = sphdata->mass;
- for (i=0; i<10 && psys[i]; i++) {
- pfr.npsys = psys[i];
- pfr.massfac = psys[i]->part->mass*inv_mass;
- pfr.use_size = psys[i]->part->flag & PART_SIZEMASS;
+ sph_evaluate_func( NULL, psys, state->co, &pfr, interaction_radius, sph_density_accum_cb);
- BLI_bvhtree_range_query(psys[i]->bvhtree, state->co, h, sphdata->density_cb, &pfr);
- }
+ density = data[0];
+ near_density = data[1];
- pressure = stiffness * (pfr.density - rest_density);
- near_pressure = stiffness_near_fac * pfr.near_density;
+ pressure = stiffness * (density - rest_density);
+ near_pressure = stiffness_near_fac * near_density;
pfn = pfr.neighbors;
for (i=0; i<pfr.tot_neighbors; i++, pfn++) {
@@ -2593,14 +2598,209 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa
/* Artificial buoyancy force in negative gravity direction */
if (fluid->buoyancy > 0.f && gravity)
- madd_v3_v3fl(force, gravity, fluid->buoyancy * (pfr.density-rest_density));
+ madd_v3_v3fl(force, gravity, fluid->buoyancy * (density-rest_density));
+
+ if (sphdata->pass == 0 && psys[0]->part->time_flag & PART_TIME_AUTOSF)
+ sph_particle_courant(sphdata, &pfr);
+ 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;
+ ParticleData *npa = pfr->npsys->particles + index;
+ float q;
+ float qfac = 21.0f / (256.f * (float)M_PI);
+ float rij, rij_h;
+ float vec[3];
+
+ /* Exclude particles that are more than 2h away. Can't use squared_dist here
+ * because it is not accurate enough. Use current state, i.e. the output of
+ * basic_integrate() - z0r */
+ sub_v3_v3v3(vec, npa->state.co, pfr->pa->state.co);
+ rij = len_v3(vec);
+ rij_h = rij / pfr->h;
+ if (rij_h > 2.0f)
+ return;
+
+ /* 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 *= pfr->npsys->part->mass;
+
+ if (pfr->use_size)
+ q *= pfr->pa->size;
+
+ pfr->data[0] += q;
+ pfr->data[1] += q / npa->sphdensity;
+}
+
+static void sphclassical_neighbour_accum_cb(void *userdata, int index, float UNUSED(squared_dist))
+{
+ SPHRangeData *pfr = (SPHRangeData *)userdata;
+ ParticleData *npa = pfr->npsys->particles + index;
+ float rij, rij_h;
+ float vec[3];
+
+ if (pfr->tot_neighbors >= SPH_NEIGHBORS)
+ return;
+
+ /* Exclude particles that are more than 2h away. Can't use squared_dist here
+ * because it is not accurate enough. Use current state, i.e. the output of
+ * basic_integrate() - z0r */
+ sub_v3_v3v3(vec, npa->state.co, pfr->pa->state.co);
+ rij = len_v3(vec);
+ rij_h = rij / pfr->h;
+ if (rij_h > 2.0f)
+ return;
+
+ pfr->neighbors[pfr->tot_neighbors].index = index;
+ pfr->neighbors[pfr->tot_neighbors].psys = pfr->npsys;
+ pfr->tot_neighbors++;
+}
+static void sphclassical_force_cb(void *sphdata_v, ParticleKey *state, float *force, float *UNUSED(impulse))
+{
+ SPHData *sphdata = (SPHData *)sphdata_v;
+ ParticleSystem **psys = sphdata->psys;
+ ParticleData *pa = sphdata->pa;
+ SPHFluidSettings *fluid = psys[0]->part->fluid;
+ SPHRangeData pfr;
+ SPHNeighbor *pfn;
+ float *gravity = sphdata->gravity;
+
+ float dq, u, rij, dv[3];
+ float pressure, npressure;
+
+ float visc = fluid->viscosity_omega;
+
+ float interaction_radius;
+ float h, hinv;
+ /* 4.77 is an experimentally determined density factor */
+ 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);
+
+ ParticleData *npa;
+ float vec[3];
+ float co[3];
+ float pressureTerm;
+
+ int i;
+
+ float qfac2 = 42.0f / (256.0f * (float)M_PI);
+ float rij_h;
+
+ /* 4.0 here is to be consistent with previous formulation/interface */
+ interaction_radius = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.0f * pa->size : 1.0f);
+ h = interaction_radius * sphdata->hfac;
+ hinv = 1.0f / h;
+
+ pfr.h = h;
+ 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);
+
+ /* multiply by mass so that we return a force, not accel */
+ qfac2 *= sphdata->mass / pow3(pfr.h);
+
+ pfn = pfr.neighbors;
+ for (i = 0; i < pfr.tot_neighbors; i++, pfn++) {
+ npa = pfn->psys->particles + pfn->index;
+ if (npa == pa) {
+ /* we do not contribute to ourselves */
+ continue;
+ }
+
+ /* Find vector to neighbour. Exclude particles that are more than 2h
+ * away. Can't use current state here because it may have changed on
+ * another thread - so do own mini integration. Unlike basic_integrate,
+ * SPH integration depends on neighbouring particles. - z0r */
+ madd_v3_v3v3fl(co, npa->prev_state.co, npa->prev_state.vel, state->time);
+ sub_v3_v3v3(vec, co, state->co);
+ rij = normalize_v3(vec);
+ rij_h = rij / pfr.h;
+ if (rij_h > 2.0f)
+ continue;
+
+ npressure = stiffness * (pow7(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) );
+
+ if (pfn->psys->part->flag & PART_SIZEMASS)
+ dq *= npa->size;
+
+ pressureTerm = pressure / pow2(pa->sphdensity) + npressure / pow2(npa->sphdensity);
+
+ /* Note that 'minus' is removed, because vec = vecBA, not vecAB.
+ * This applies to the viscosity calculation below, too. */
+ madd_v3_v3fl(force, vec, pressureTerm * dq);
+
+ /* Viscosity */
+ if (visc > 0.0f) {
+ sub_v3_v3v3(dv, npa->prev_state.vel, pa->prev_state.vel);
+ u = dot_v3v3(vec, dv);
+ /* Apply parameters */
+ u *= -dq * hinv * visc / (0.5f * npa->sphdensity + 0.5f * pa->sphdensity);
+ madd_v3_v3fl(force, vec, u);
+ }
+ }
+
+ /* Artificial buoyancy force in negative gravity direction */
+ if (fluid->buoyancy > 0.f && gravity)
+ madd_v3_v3fl(force, gravity, fluid->buoyancy * (pa->sphdensity - rest_density));
if (sphdata->pass == 0 && psys[0]->part->time_flag & PART_TIME_AUTOSF)
sph_particle_courant(sphdata, &pfr);
sphdata->pass++;
}
-static void sph_solver_init(ParticleSimulationData *sim, SPHData *sphdata)
+static void sphclassical_calc_dens(ParticleData *pa, float UNUSED(dfra), SPHData *sphdata)
+{
+ ParticleSystem **psys = sphdata->psys;
+ SPHFluidSettings *fluid = psys[0]->part->fluid;
+ /* 4.0 seems to be a pretty good value */
+ float interaction_radius = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.0f * psys[0]->part->size : 1.0f);
+ SPHRangeData pfr;
+ float data[2];
+
+ data[0] = 0;
+ data[1] = 0;
+ pfr.data = data;
+ pfr.h = interaction_radius * sphdata->hfac;
+ pfr.pa = pa;
+ pfr.mass = sphdata->mass;
+
+ sph_evaluate_func( NULL, psys, pa->state.co, &pfr, interaction_radius, sphclassical_density_accum_cb);
+ pa->sphdensity = MIN2(MAX2(data[0], fluid->rest_density * 0.9f), fluid->rest_density * 1.1f);
+}
+
+void psys_sph_init(ParticleSimulationData *sim, SPHData *sphdata)
{
ParticleTarget *pt;
int i;
@@ -2621,17 +2821,47 @@ static void sph_solver_init(ParticleSimulationData *sim, SPHData *sphdata)
sphdata->pa = NULL;
sphdata->mass = 1.0f;
- sphdata->force_cb = sph_force_cb;
- sphdata->density_cb = sph_density_accum_cb;
+ if (sim->psys->part->fluid->solver == SPH_SOLVER_DDR) {
+ sphdata->force_cb = sph_force_cb;
+ sphdata->density_cb = sph_density_accum_cb;
+ sphdata->hfac = 1.0f;
+ }
+ else {
+ /* SPH_SOLVER_CLASSICAL */
+ sphdata->force_cb = sphclassical_force_cb;
+ sphdata->density_cb = sphclassical_density_accum_cb;
+ sphdata->hfac = 0.5f;
+ }
+
}
-static void sph_solver_finalise(SPHData *sphdata)
+void psys_sph_finalise(SPHData *sphdata)
{
if (sphdata->eh) {
BLI_edgehash_free(sphdata->eh, NULL);
sphdata->eh = NULL;
}
}
+/* Sample the density field at a point in space. */
+void psys_sph_density(BVHTree *tree, SPHData *sphdata, float co[3], float vars[2])
+{
+ ParticleSystem **psys = sphdata->psys;
+ SPHFluidSettings *fluid = psys[0]->part->fluid;
+ /* 4.0 seems to be a pretty good value */
+ float interaction_radius = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.0f * psys[0]->part->size : 1.0f);
+ SPHRangeData pfr;
+ float density[2];
+
+ density[0] = density[1] = 0.0f;
+ pfr.data = density;
+ pfr.h = interaction_radius * sphdata->hfac;
+ pfr.mass = sphdata->mass;
+
+ sph_evaluate_func(tree, psys, co, &pfr, interaction_radius, sphdata->density_cb);
+
+ vars[0] = pfr.data[0];
+ vars[1] = pfr.data[1];
+}
static void sph_integrate(ParticleSimulationData *sim, ParticleData *pa, float dfra, SPHData *sphdata)
{
@@ -2798,13 +3028,20 @@ static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, f
normalize_qt(pa->state.rot);
}
-/************************************************/
-/* Collisions */
-/************************************************/
+/************************************************
+ * Collisions
+ *
+ * The algorithm is roughly:
+ * 1. Use a BVH tree to search for faces that a particle may collide with.
+ * 2. Use Newton's method to find the exact time at which the collision occurs.
+ * http://en.wikipedia.org/wiki/Newton's_method
+ *
+ ************************************************/
#define COLLISION_MAX_COLLISIONS 10
#define COLLISION_MIN_RADIUS 0.001f
#define COLLISION_MIN_DISTANCE 0.0001f
#define COLLISION_ZERO 0.00001f
+#define COLLISION_INIT_STEP 0.00008f
typedef float (*NRDistanceFunc)(float *p, float radius, ParticleCollisionElement *pce, float *nor);
static float nr_signed_distance_to_plane(float *p, float radius, ParticleCollisionElement *pce, float *nor)
{
@@ -2959,16 +3196,20 @@ static void collision_point_on_surface(float p[3], ParticleCollisionElement *pce
/* find first root in range [0-1] starting from 0 */
static float collision_newton_rhapson(ParticleCollision *col, float radius, ParticleCollisionElement *pce, NRDistanceFunc distance_func)
{
- float t0, t1, d0, d1, dd, n[3];
+ float t0, t1, dt_init, d0, d1, dd, n[3];
int iter;
pce->inv_nor = -1;
+ /* Initial step size should be small, but not too small or floating point
+ * precision errors will appear. - z0r */
+ dt_init = COLLISION_INIT_STEP * col->inv_total_time;
+
/* start from the beginning */
t0 = 0.f;
collision_interpolate_element(pce, t0, col->f, col);
d0 = distance_func(col->co1, radius, pce, n);
- t1 = 0.001f;
+ t1 = dt_init;
d1 = 0.f;
for (iter=0; iter<10; iter++) {//, itersum++) {
@@ -2978,11 +3219,6 @@ static float collision_newton_rhapson(ParticleCollision *col, float radius, Part
d1 = distance_func(pce->p, radius, pce, n);
- /* no movement, so no collision */
- if (d1 == d0) {
- return -1.f;
- }
-
/* particle already inside face, so report collision */
if (iter == 0 && d0 < 0.f && d0 > -radius) {
copy_v3_v3(pce->p, col->co1);
@@ -2990,7 +3226,24 @@ static float collision_newton_rhapson(ParticleCollision *col, float radius, Part
pce->inside = 1;
return 0.f;
}
-
+
+ /* Zero gradient (no movement relative to element). Can't step from
+ * here. */
+ if (d1 == d0) {
+ /* If first iteration, try from other end where the gradient may be
+ * greater. Note: code duplicated below. */
+ if (iter == 0) {
+ t0 = 1.f;
+ collision_interpolate_element(pce, t0, col->f, col);
+ d0 = distance_func(col->co2, radius, pce, n);
+ t1 = 1.0f - dt_init;
+ d1 = 0.f;
+ continue;
+ }
+ else
+ return -1.f;
+ }
+
dd = (t1-t0)/(d1-d0);
t0 = t1;
@@ -2998,14 +3251,14 @@ static float collision_newton_rhapson(ParticleCollision *col, float radius, Part
t1 -= d1*dd;
- /* particle movin away from plane could also mean a strangely rotating face, so check from end */
+ /* Particle moving away from plane could also mean a strangely rotating
+ * face, so check from end. Note: code duplicated above. */
if (iter == 0 && t1 < 0.f) {
t0 = 1.f;
collision_interpolate_element(pce, t0, col->f, col);
d0 = distance_func(col->co2, radius, pce, n);
- t1 = 0.999f;
+ t1 = 1.0f - dt_init;
d1 = 0.f;
-
continue;
}
else if (iter == 1 && (t1 < -COLLISION_ZERO || t1 > 1.f))
@@ -3453,6 +3706,7 @@ static void collision_check(ParticleSimulationData *sim, int p, float dfra, floa
memset(&col, 0, sizeof(ParticleCollision));
col.total_time = timestep * dfra;
+ col.inv_total_time = 1.0f/col.total_time;
col.inv_timestep = 1.0f/timestep;
col.cfra = cfra;
@@ -3781,18 +4035,19 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra))
/* Code for an adaptive time step based on the Courant-Friedrichs-Lewy
* condition. */
-#define MIN_TIMESTEP 1.0f / 101.0f
+static const float MIN_TIMESTEP = 1.0f / 101.0f;
/* Tolerance of 1.5 means the last subframe neither favors growing nor
* shrinking (e.g if it were 1.3, the last subframe would tend to be too
* small). */
-#define TIMESTEP_EXPANSION_TOLERANCE 1.5f
+static const float TIMESTEP_EXPANSION_FACTOR = 0.1f;
+static const float TIMESTEP_EXPANSION_TOLERANCE = 1.5f;
/* Calculate the speed of the particle relative to the local scale of the
* simulation. This should be called once per particle during a simulation
* step, after the velocity has been updated. element_size defines the scale of
* the simulation, and is typically the distance to neighboring particles. */
static void update_courant_num(ParticleSimulationData *sim, ParticleData *pa,
- float dtime, SPHData *sphdata)
+ float dtime, SPHData *sphdata)
{
float relative_vel[3];
float speed;
@@ -3802,14 +4057,31 @@ static void update_courant_num(ParticleSimulationData *sim, ParticleData *pa,
if (sim->courant_num < speed * dtime / sphdata->element_size)
sim->courant_num = speed * dtime / sphdata->element_size;
}
+static float get_base_time_step(ParticleSettings *part)
+{
+ return 1.0f / (float) (part->subframes + 1);
+}
/* Update time step size to suit current conditions. */
static float update_timestep(ParticleSystem *psys, ParticleSimulationData *sim, float t_frac)
{
+ float dt_target;
if (sim->courant_num == 0.0f)
- psys->dt_frac = 1.0f;
+ dt_target = 1.0f;
+ else
+ dt_target = psys->dt_frac * (psys->part->courant_target / sim->courant_num);
+
+ /* Make sure the time step is reasonable. For some reason, the CLAMP macro
+ * doesn't work here. The time step becomes too large. - z0r */
+ if (dt_target < MIN_TIMESTEP)
+ dt_target = MIN_TIMESTEP;
+ else if (dt_target > get_base_time_step(psys->part))
+ dt_target = get_base_time_step(psys->part);
+
+ /* Decrease time step instantly, but increase slowly. */
+ if (dt_target > psys->dt_frac)
+ psys->dt_frac = interpf(dt_target, psys->dt_frac, TIMESTEP_EXPANSION_FACTOR);
else
- psys->dt_frac *= (psys->part->courant_target / sim->courant_num);
- CLAMP(psys->dt_frac, MIN_TIMESTEP, 1.0f);
+ psys->dt_frac = dt_target;
/* Sync with frame end if it's close. */
if (t_frac == 1.0f)
@@ -3973,31 +4245,72 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
case PART_PHYS_FLUID:
{
SPHData sphdata;
- sph_solver_init(sim, &sphdata);
+ ParticleSettings *part = sim->psys->part;
+ psys_sph_init(sim, &sphdata);
- #pragma omp parallel for firstprivate (sphdata) private (pa) schedule(dynamic,5)
- LOOP_DYNAMIC_PARTICLES {
- /* do global forces & effectors */
- basic_integrate(sim, p, pa->state.time, cfra);
+ if (part->fluid->solver == SPH_SOLVER_DDR) {
+ /* Apply SPH forces using double-density relaxation algorithm
+ * (Clavat et. al.) */
+ #pragma omp parallel for firstprivate (sphdata) private (pa) schedule(dynamic,5)
+ LOOP_DYNAMIC_PARTICLES {
+ /* do global forces & effectors */
+ basic_integrate(sim, p, pa->state.time, cfra);
- /* actual fluids calculations */
- sph_integrate(sim, pa, pa->state.time, &sphdata);
+ /* actual fluids calculations */
+ sph_integrate(sim, pa, pa->state.time, &sphdata);
- if (sim->colliders)
- collision_check(sim, p, pa->state.time, cfra);
-
- /* SPH particles are not physical particles, just interpolation
- * particles, thus rotation has not a direct sense for them */
- basic_rotate(part, pa, pa->state.time, timestep);
+ if (sim->colliders)
+ collision_check(sim, p, pa->state.time, cfra);
+
+ /* SPH particles are not physical particles, just interpolation
+ * particles, thus rotation has not a direct sense for them */
+ basic_rotate(part, pa, pa->state.time, timestep);
+
+ #pragma omp critical
+ if (part->time_flag & PART_TIME_AUTOSF)
+ update_courant_num(sim, pa, dtime, &sphdata);
+ }
+
+ sph_springs_modify(psys, timestep);
- #pragma omp critical
- if (part->time_flag & PART_TIME_AUTOSF)
- update_courant_num(sim, pa, dtime, &sphdata);
}
+ else {
+ /* SPH_SOLVER_CLASSICAL */
+ /* Apply SPH forces using classical algorithm (due to Gingold
+ * and Monaghan). Note that, unlike double-density relaxation,
+ * this algorthim is separated into distinct loops. */
+
+ #pragma omp parallel for firstprivate (sphdata) private (pa) schedule(dynamic,5)
+ LOOP_DYNAMIC_PARTICLES {
+ basic_integrate(sim, p, pa->state.time, cfra);
+ }
- sph_springs_modify(psys, timestep);
+ /* calculate summation density */
+ #pragma omp parallel for firstprivate (sphdata) private (pa) schedule(dynamic,5)
+ LOOP_DYNAMIC_PARTICLES {
+ sphclassical_calc_dens(pa, pa->state.time, &sphdata);
+ }
- sph_solver_finalise(&sphdata);
+ /* do global forces & effectors */
+ #pragma omp parallel for firstprivate (sphdata) private (pa) schedule(dynamic,5)
+ LOOP_DYNAMIC_PARTICLES {
+ /* actual fluids calculations */
+ sph_integrate(sim, pa, pa->state.time, &sphdata);
+
+ if (sim->colliders)
+ collision_check(sim, p, pa->state.time, cfra);
+
+ /* SPH particles are not physical particles, just interpolation
+ * particles, thus rotation has not a direct sense for them */
+ basic_rotate(part, pa, pa->state.time, timestep);
+
+ #pragma omp critical
+ if (part->time_flag & PART_TIME_AUTOSF)
+ update_courant_num(sim, pa, dtime, &sphdata);
+ }
+ }
+
+ psys_sph_finalise(&sphdata);
break;
}
}
@@ -4211,7 +4524,7 @@ static void system_step(ParticleSimulationData *sim, float cfra)
int startframe = 0, endframe = 100, oldtotpart = 0;
/* cache shouldn't be used for hair or "continue physics" */
- if (part->type != PART_HAIR && BKE_ptcache_get_continue_physics() == 0) {
+ if (part->type != PART_HAIR) {
psys_clear_temp_pointcache(psys);
/* set suitable cache range automatically */
@@ -4309,14 +4622,14 @@ static void system_step(ParticleSimulationData *sim, float cfra)
if (!(part->time_flag & PART_TIME_AUTOSF)) {
/* Constant time step */
- psys->dt_frac = 1.0f / (float) (part->subframes + 1);
+ psys->dt_frac = get_base_time_step(part);
}
else if ((int)cfra == startframe) {
- /* Variable time step; use a very conservative value at the start.
- * If it doesn't need to be so small, it will quickly grow. */
- psys->dt_frac = 1.0;
+ /* Variable time step; initialise to subframes */
+ psys->dt_frac = get_base_time_step(part);
}
else if (psys->dt_frac < MIN_TIMESTEP) {
+ /* Variable time step; subsequent frames */
psys->dt_frac = MIN_TIMESTEP;
}
diff --git a/source/blender/blenlib/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 6fa6d86589f..5efeeaeedaa 100644
--- a/source/blender/blenlib/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -18,12 +18,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/blenlib/intern/pbvh.c
+/** \file blender/blenkernel/intern/pbvh.c
* \ingroup bli
*/
-
-
#include "DNA_meshdata_types.h"
#include "MEM_guardedalloc.h"
@@ -32,8 +30,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
-#include "BLI_pbvh.h"
+#include "BKE_pbvh.h"
#include "BKE_ccg.h"
#include "BKE_DerivedMesh.h"
#include "BKE_mesh.h" /* for BKE_mesh_calc_normals */
@@ -43,124 +41,12 @@
#include "GPU_buffers.h"
+#include "pbvh_intern.h"
+
#define LEAF_LIMIT 10000
//#define PERFCNTRS
-/* Axis-aligned bounding box */
-typedef struct {
- float bmin[3], bmax[3];
-} BB;
-
-/* Axis-aligned bounding box with centroid */
-typedef struct {
- float bmin[3], bmax[3], bcentroid[3];
-} BBC;
-
-struct PBVHNode {
- /* Opaque handle for drawing code */
- GPU_Buffers *draw_buffers;
-
- /* Voxel bounds */
- BB vb;
- BB orig_vb;
-
- /* For internal nodes, the offset of the children in the PBVH
- * 'nodes' array. */
- int children_offset;
-
- /* Pointer into the PBVH prim_indices array and the number of
- * primitives used by this leaf node.
- *
- * Used for leaf nodes in both mesh- and multires-based PBVHs.
- */
- int *prim_indices;
- unsigned int totprim;
-
- /* Array of indices into the mesh's MVert array. Contains the
- * indices of all vertices used by faces that are within this
- * node's bounding box.
- *
- * Note that a vertex might be used by a multiple faces, and
- * these faces might be in different leaf nodes. Such a vertex
- * will appear in the vert_indices array of each of those leaf
- * nodes.
- *
- * In order to support cases where you want access to multiple
- * nodes' vertices without duplication, the vert_indices array
- * is ordered such that the first part of the array, up to
- * index 'uniq_verts', contains "unique" vertex indices. These
- * vertices might not be truly unique to this node, but if
- * they appear in another node's vert_indices array, they will
- * be above that node's 'uniq_verts' value.
- *
- * Used for leaf nodes in a mesh-based PBVH (not multires.)
- */
- int *vert_indices;
- unsigned int uniq_verts, face_verts;
-
- /* An array mapping face corners into the vert_indices
- * array. The array is sized to match 'totprim', and each of
- * the face's corners gets an index into the vert_indices
- * array, in the same order as the corners in the original
- * MFace. The fourth value should not be used if the original
- * face is a triangle.
- *
- * Used for leaf nodes in a mesh-based PBVH (not multires.)
- */
- 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. */
- PBVHNodeFlags flag : 8;
-
- /* Used for raycasting: how close bb is to the ray point. */
- float tmin;
-
- int proxy_count;
- PBVHProxyNode *proxies;
-};
-
-struct PBVH {
- PBVHType type;
-
- PBVHNode *nodes;
- int node_mem_count, totnode;
-
- int *prim_indices;
- int totprim;
- int totvert;
-
- int leaf_limit;
-
- /* Mesh data */
- MVert *verts;
- MFace *faces;
- CustomData *vdata;
-
- /* Grid Data */
- CCGKey gridkey;
- CCGElem **grids;
- DMGridAdjacency *gridadj;
- void **gridfaces;
- const DMFlagMat *grid_flag_mats;
- int totgrid;
- BLI_bitmap *grid_hidden;
-
- /* Only used during BVH build and update,
- * don't need to remain valid after */
- BLI_bitmap vert_bitmap;
-
-#ifdef PERFCNTRS
- int perf_modified;
-#endif
-
- /* flag are verts/faces deformed */
- int deformed;
-
- int show_diffuse_color;
-};
-
#define STACK_FIXED_DEPTH 100
typedef struct PBVHStack {
@@ -170,7 +56,7 @@ typedef struct PBVHStack {
typedef struct PBVHIter {
PBVH *bvh;
- BLI_pbvh_SearchCallback scb;
+ BKE_pbvh_SearchCallback scb;
void *search_data;
PBVHStack *stack;
@@ -180,14 +66,14 @@ typedef struct PBVHIter {
int stackspace;
} PBVHIter;
-static void BB_reset(BB *bb)
+void BB_reset(BB *bb)
{
bb->bmin[0] = bb->bmin[1] = bb->bmin[2] = FLT_MAX;
bb->bmax[0] = bb->bmax[1] = bb->bmax[2] = -FLT_MAX;
}
/* Expand the bounding box to include a new coordinate */
-static void BB_expand(BB *bb, float co[3])
+void BB_expand(BB *bb, const float co[3])
{
int i;
for (i = 0; i < 3; ++i) {
@@ -197,7 +83,7 @@ static void BB_expand(BB *bb, float co[3])
}
/* Expand the bounding box to include another bounding box */
-static void BB_expand_with_bb(BB *bb, BB *bb2)
+void BB_expand_with_bb(BB *bb, BB *bb2)
{
int i;
for (i = 0; i < 3; ++i) {
@@ -207,7 +93,7 @@ static void BB_expand_with_bb(BB *bb, BB *bb2)
}
/* Return 0, 1, or 2 to indicate the widest axis of the bounding box */
-static int BB_widest_axis(BB *bb)
+int BB_widest_axis(const BB *bb)
{
float dim[3];
int i;
@@ -229,7 +115,7 @@ static int BB_widest_axis(BB *bb)
}
}
-static void BBC_update_centroid(BBC *bbc)
+void BBC_update_centroid(BBC *bbc)
{
int i;
for (i = 0; i < 3; ++i)
@@ -246,11 +132,11 @@ static void update_node_vb(PBVH *bvh, PBVHNode *node)
if (node->flag & PBVH_Leaf) {
PBVHVertexIter vd;
- BLI_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL)
+ BKE_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL)
{
BB_expand(&vb, vd.co);
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
else {
BB_expand_with_bb(&vb,
@@ -262,12 +148,12 @@ static void update_node_vb(PBVH *bvh, PBVHNode *node)
node->vb = vb;
}
-//void BLI_pbvh_node_BB_reset(PBVHNode *node)
+//void BKE_pbvh_node_BB_reset(PBVHNode *node)
//{
// BB_reset(&node->vb);
//}
//
-//void BLI_pbvh_node_BB_expand(PBVHNode *node, float co[3])
+//void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3])
//{
// BB_expand(&node->vb, co);
//}
@@ -334,7 +220,7 @@ static int partition_indices_material(PBVH *bvh, int lo, int hi)
}
}
-static void grow_nodes(PBVH *bvh, int totnode)
+void pbvh_grow_nodes(PBVH *bvh, int totnode)
{
if (totnode > bvh->node_mem_count) {
PBVHNode *prev = bvh->nodes;
@@ -408,7 +294,7 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
/* Build the vertex list, unique verts first */
for (iter = BLI_ghashIterator_new(map), i = 0;
- BLI_ghashIterator_isDone(iter) == FALSE;
+ BLI_ghashIterator_notDone(iter);
BLI_ghashIterator_step(iter), ++i)
{
void *value = BLI_ghashIterator_getValue(iter);
@@ -547,7 +433,7 @@ static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc,
/* Add two child nodes */
bvh->nodes[node_index].children_offset = bvh->totnode;
- grow_nodes(bvh, bvh->totnode + 2);
+ pbvh_grow_nodes(bvh, bvh->totnode + 2);
/* Update parent node bounding box */
update_vb(bvh, &bvh->nodes[node_index], prim_bbc, offset, count);
@@ -607,7 +493,7 @@ static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim)
}
/* Do a full rebuild with on Mesh data structure */
-void BLI_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int totface, int totvert, struct CustomData *vdata)
+void BKE_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int totface, int totvert, struct CustomData *vdata)
{
BBC *prim_bbc = NULL;
BB cb;
@@ -649,7 +535,7 @@ void BLI_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int totface, int
}
/* Do a full rebuild with on Grids data structure */
-void BLI_pbvh_build_grids(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj,
+void BKE_pbvh_build_grids(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj,
int totgrid, CCGKey *key, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap *grid_hidden)
{
BBC *prim_bbc = NULL;
@@ -692,14 +578,14 @@ void BLI_pbvh_build_grids(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj,
MEM_freeN(prim_bbc);
}
-PBVH *BLI_pbvh_new(void)
+PBVH *BKE_pbvh_new(void)
{
PBVH *bvh = MEM_callocN(sizeof(PBVH), "pbvh");
return bvh;
}
-void BLI_pbvh_free(PBVH *bvh)
+void BKE_pbvh_free(PBVH *bvh)
{
PBVHNode *node;
int i;
@@ -714,6 +600,14 @@ void BLI_pbvh_free(PBVH *bvh)
MEM_freeN(node->vert_indices);
if (node->face_vert_indices)
MEM_freeN(node->face_vert_indices);
+ BKE_pbvh_node_layer_disp_free(node);
+
+ if (node->bm_faces)
+ BLI_ghash_free(node->bm_faces, NULL, NULL);
+ if (node->bm_unique_verts)
+ BLI_ghash_free(node->bm_unique_verts, NULL, NULL);
+ if (node->bm_other_verts)
+ BLI_ghash_free(node->bm_other_verts, NULL, NULL);
}
}
@@ -733,10 +627,15 @@ void BLI_pbvh_free(PBVH *bvh)
if (bvh->prim_indices)
MEM_freeN(bvh->prim_indices);
+ if (bvh->bm_vert_to_node)
+ BLI_ghash_free(bvh->bm_vert_to_node, NULL, NULL);
+ if (bvh->bm_face_to_node)
+ BLI_ghash_free(bvh->bm_face_to_node, NULL, NULL);
+
MEM_freeN(bvh);
}
-static void pbvh_iter_begin(PBVHIter *iter, PBVH *bvh, BLI_pbvh_SearchCallback scb, void *search_data)
+static void pbvh_iter_begin(PBVHIter *iter, PBVH *bvh, BKE_pbvh_SearchCallback scb, void *search_data)
{
iter->bvh = bvh;
iter->scb = scb;
@@ -847,8 +746,8 @@ static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter)
return NULL;
}
-void BLI_pbvh_search_gather(PBVH *bvh,
- BLI_pbvh_SearchCallback scb, void *search_data,
+void BKE_pbvh_search_gather(PBVH *bvh,
+ BKE_pbvh_SearchCallback scb, void *search_data,
PBVHNode ***r_array, int *r_tot)
{
PBVHIter iter;
@@ -888,9 +787,9 @@ void BLI_pbvh_search_gather(PBVH *bvh,
*r_tot = tot;
}
-void BLI_pbvh_search_callback(PBVH *bvh,
- BLI_pbvh_SearchCallback scb, void *search_data,
- BLI_pbvh_HitCallback hcb, void *hit_data)
+void BKE_pbvh_search_callback(PBVH *bvh,
+ BKE_pbvh_SearchCallback scb, void *search_data,
+ BKE_pbvh_HitCallback hcb, void *hit_data)
{
PBVHIter iter;
PBVHNode *node;
@@ -931,7 +830,7 @@ static void node_tree_insert(node_tree *tree, node_tree *new_node)
}
}
-static void traverse_tree(node_tree *tree, BLI_pbvh_HitOccludedCallback hcb, void *hit_data, float *tmin)
+static void traverse_tree(node_tree *tree, BKE_pbvh_HitOccludedCallback hcb, void *hit_data, float *tmin)
{
if (tree->left) traverse_tree(tree->left, hcb, hit_data, tmin);
@@ -955,14 +854,14 @@ static void free_tree(node_tree *tree)
free(tree);
}
-float BLI_pbvh_node_get_tmin(PBVHNode *node)
+float BKE_pbvh_node_get_tmin(PBVHNode *node)
{
return node->tmin;
}
-static void BLI_pbvh_search_callback_occluded(PBVH *bvh,
- BLI_pbvh_SearchCallback scb, void *search_data,
- BLI_pbvh_HitOccludedCallback hcb, void *hit_data)
+static void BKE_pbvh_search_callback_occluded(PBVH *bvh,
+ BKE_pbvh_SearchCallback scb, void *search_data,
+ BKE_pbvh_HitOccludedCallback hcb, void *hit_data)
{
PBVHIter iter;
PBVHNode *node;
@@ -1013,6 +912,11 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
float (*vnor)[3];
int n;
+ if (bvh->type == PBVH_BMESH) {
+ pbvh_bmesh_normals_update(nodes, totnode);
+ return;
+ }
+
if (bvh->type != PBVH_FACES)
return;
@@ -1106,8 +1010,7 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
MEM_freeN(vnor);
}
-static void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes,
- int totnode, int flag)
+void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
{
int n;
@@ -1154,6 +1057,11 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
node->prim_indices,
node->totprim);
break;
+ case PBVH_BMESH:
+ node->draw_buffers =
+ GPU_build_bmesh_buffers(bvh->flags &
+ PBVH_DYNTOPO_SMOOTH_SHADING);
+ break;
}
node->flag &= ~PBVH_RebuildDrawBuffers;
@@ -1181,6 +1089,13 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
node->face_vert_indices,
bvh->show_diffuse_color);
break;
+ case PBVH_BMESH:
+ GPU_update_bmesh_buffers(node->draw_buffers,
+ bvh->bm,
+ node->bm_faces,
+ node->bm_unique_verts,
+ node->bm_other_verts);
+ break;
}
node->flag &= ~PBVH_UpdateDrawBuffers;
@@ -1219,7 +1134,7 @@ static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag)
return update;
}
-void BLI_pbvh_update(PBVH *bvh, int flag, float (*face_nors)[3])
+void BKE_pbvh_update(PBVH *bvh, int flag, float (*face_nors)[3])
{
PBVHNode **nodes;
int totnode;
@@ -1227,7 +1142,7 @@ void BLI_pbvh_update(PBVH *bvh, int flag, float (*face_nors)[3])
if (!bvh->nodes)
return;
- BLI_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(flag),
+ BKE_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(flag),
&nodes, &totnode);
if (flag & PBVH_UpdateNormals)
@@ -1242,7 +1157,7 @@ void BLI_pbvh_update(PBVH *bvh, int flag, float (*face_nors)[3])
if (nodes) MEM_freeN(nodes);
}
-void BLI_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3])
+void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3])
{
PBVHIter iter;
PBVHNode *node;
@@ -1262,7 +1177,7 @@ void BLI_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3])
copy_v3_v3(bb_max, bb.bmax);
}
-void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface)
+void BKE_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface)
{
PBVHIter iter;
PBVHNode *node;
@@ -1302,7 +1217,7 @@ void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *tot
faces = MEM_callocN(sizeof(void *) * tot, "PBVH Grid Faces");
for (hiter = BLI_ghashIterator_new(map), i = 0;
- !BLI_ghashIterator_isDone(hiter);
+ BLI_ghashIterator_notDone(hiter);
BLI_ghashIterator_step(hiter), ++i)
{
faces[i] = BLI_ghashIterator_getKey(hiter);
@@ -1318,36 +1233,55 @@ void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *tot
/***************************** PBVH Access ***********************************/
-PBVHType BLI_pbvh_type(const PBVH *bvh)
+PBVHType BKE_pbvh_type(const PBVH *bvh)
{
return bvh->type;
}
-BLI_bitmap *BLI_pbvh_grid_hidden(const PBVH *bvh)
+void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3])
+{
+ if (bvh->totnode) {
+ const BB *bb = &bvh->nodes[0].vb;
+ copy_v3_v3(min, bb->bmin);
+ copy_v3_v3(max, bb->bmax);
+ }
+ else {
+ zero_v3(min);
+ zero_v3(max);
+ }
+}
+
+BLI_bitmap *BKE_pbvh_grid_hidden(const PBVH *bvh)
{
BLI_assert(bvh->type == PBVH_GRIDS);
return bvh->grid_hidden;
}
-void BLI_pbvh_get_grid_key(const PBVH *bvh, CCGKey *key)
+void BKE_pbvh_get_grid_key(const PBVH *bvh, CCGKey *key)
{
BLI_assert(bvh->type == PBVH_GRIDS);
*key = bvh->gridkey;
}
+BMesh *BKE_pbvh_get_bmesh(PBVH *bvh)
+{
+ BLI_assert(bvh->type == PBVH_BMESH);
+ return bvh->bm;
+}
+
/***************************** Node Access ***********************************/
-void BLI_pbvh_node_mark_update(PBVHNode *node)
+void BKE_pbvh_node_mark_update(PBVHNode *node)
{
node->flag |= PBVH_UpdateNormals | PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
}
-void BLI_pbvh_node_mark_rebuild_draw(PBVHNode *node)
+void BKE_pbvh_node_mark_rebuild_draw(PBVHNode *node)
{
node->flag |= PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
}
-void BLI_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden)
+void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden)
{
BLI_assert(node->flag & PBVH_Leaf);
@@ -1357,13 +1291,13 @@ void BLI_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden)
node->flag &= ~PBVH_FullyHidden;
}
-void BLI_pbvh_node_get_verts(PBVH *bvh, PBVHNode *node, int **vert_indices, MVert **verts)
+void BKE_pbvh_node_get_verts(PBVH *bvh, PBVHNode *node, int **vert_indices, MVert **verts)
{
if (vert_indices) *vert_indices = node->vert_indices;
if (verts) *verts = bvh->verts;
}
-void BLI_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *uniquevert, int *totvert)
+void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *uniquevert, int *totvert)
{
int tot;
@@ -1377,10 +1311,15 @@ void BLI_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *uniquevert, int *to
if (totvert) *totvert = node->uniq_verts + node->face_verts;
if (uniquevert) *uniquevert = node->uniq_verts;
break;
+ case PBVH_BMESH:
+ tot = BLI_ghash_size(node->bm_unique_verts);
+ if (totvert) *totvert = tot + BLI_ghash_size(node->bm_other_verts);
+ if (uniquevert) *uniquevert = tot;
+ break;
}
}
-void BLI_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 **grid_indices, int *totgrid, int *maxgrid, int *gridsize, CCGElem ***griddata, DMGridAdjacency **gridadj)
{
switch (bvh->type) {
case PBVH_GRIDS:
@@ -1392,6 +1331,7 @@ void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, int **grid_indices, int
if (gridadj) *gridadj = bvh->gridadj;
break;
case PBVH_FACES:
+ case PBVH_BMESH:
if (grid_indices) *grid_indices = NULL;
if (totgrid) *totgrid = 0;
if (maxgrid) *maxgrid = 0;
@@ -1402,19 +1342,19 @@ void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, int **grid_indices, int
}
}
-void BLI_pbvh_node_get_BB(PBVHNode *node, float bb_min[3], float bb_max[3])
+void BKE_pbvh_node_get_BB(PBVHNode *node, float bb_min[3], float bb_max[3])
{
copy_v3_v3(bb_min, node->vb.bmin);
copy_v3_v3(bb_max, node->vb.bmax);
}
-void BLI_pbvh_node_get_original_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])
{
copy_v3_v3(bb_min, node->orig_vb.bmin);
copy_v3_v3(bb_max, node->orig_vb.bmax);
}
-void BLI_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count)
+void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count)
{
if (node->proxy_count > 0) {
if (proxies) *proxies = node->proxies;
@@ -1439,14 +1379,14 @@ static int ray_aabb_intersect(PBVHNode *node, void *data_v)
float bb_min[3], bb_max[3];
if (rcd->original)
- BLI_pbvh_node_get_original_BB(node, bb_min, bb_max);
+ BKE_pbvh_node_get_original_BB(node, bb_min, bb_max);
else
- BLI_pbvh_node_get_BB(node, bb_min, bb_max);
+ BKE_pbvh_node_get_BB(node, bb_min, bb_max);
return isect_ray_aabb(&rcd->ray, bb_min, bb_max, &node->tmin);
}
-void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data,
+void BKE_pbvh_raycast(PBVH *bvh, BKE_pbvh_HitOccludedCallback cb, void *data,
const float ray_start[3], const float ray_normal[3],
int original)
{
@@ -1455,14 +1395,14 @@ void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data,
isect_ray_aabb_initialize(&rcd.ray, ray_start, ray_normal);
rcd.original = original;
- BLI_pbvh_search_callback_occluded(bvh, ray_aabb_intersect, &rcd, cb, data);
+ BKE_pbvh_search_callback_occluded(bvh, ray_aabb_intersect, &rcd, cb, data);
}
-static int 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)
+int 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)
{
float dist;
@@ -1568,7 +1508,7 @@ static int pbvh_grids_node_raycast(PBVH *bvh, PBVHNode *node,
return hit;
}
-int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3],
+int 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)
{
@@ -1586,6 +1526,9 @@ int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3],
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);
+ break;
}
return hit;
@@ -1593,8 +1536,15 @@ int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3],
//#include <GL/glew.h>
-void BLI_pbvh_node_draw(PBVHNode *node, void *setMaterial)
+typedef struct {
+ DMSetMaterial setMaterial;
+ int wireframe;
+} PBVHNodeDrawData;
+
+void BKE_pbvh_node_draw(PBVHNode *node, void *data_v)
{
+ PBVHNodeDrawData *data = data_v;
+
#if 0
/* XXX: Just some quick code to show leaf nodes in different colors */
float col[3]; int i;
@@ -1613,7 +1563,9 @@ void BLI_pbvh_node_draw(PBVHNode *node, void *setMaterial)
#endif
if (!(node->flag & PBVH_FullyHidden))
- GPU_draw_buffers(node->draw_buffers, setMaterial);
+ GPU_draw_buffers(node->draw_buffers,
+ data->setMaterial,
+ data->wireframe);
}
typedef enum {
@@ -1656,19 +1608,19 @@ static PlaneAABBIsect test_planes_aabb(const float bb_min[3],
return ret;
}
-int BLI_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data)
+int BKE_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data)
{
float bb_min[3], bb_max[3];
- BLI_pbvh_node_get_BB(node, bb_min, bb_max);
+ BKE_pbvh_node_get_BB(node, bb_min, bb_max);
return test_planes_aabb(bb_min, bb_max, data) != ISECT_OUTSIDE;
}
-int BLI_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data)
+int BKE_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data)
{
float bb_min[3], bb_max[3];
- BLI_pbvh_node_get_BB(node, bb_min, bb_max);
+ BKE_pbvh_node_get_BB(node, bb_min, bb_max);
return test_planes_aabb(bb_min, bb_max, data) != ISECT_INSIDE;
}
@@ -1681,16 +1633,17 @@ static void pbvh_node_check_diffuse_changed(PBVH *bvh, PBVHNode *node)
node->flag |= PBVH_UpdateDrawBuffers;
}
-void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
- DMSetMaterial setMaterial)
+void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
+ DMSetMaterial setMaterial, int wireframe)
{
+ PBVHNodeDrawData draw_data = {setMaterial, wireframe};
PBVHNode **nodes;
int a, totnode;
for (a = 0; a < bvh->totnode; a++)
pbvh_node_check_diffuse_changed(bvh, &bvh->nodes[a]);
- BLI_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(PBVH_UpdateNormals | PBVH_UpdateDrawBuffers),
+ BKE_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(PBVH_UpdateNormals | PBVH_UpdateDrawBuffers),
&nodes, &totnode);
pbvh_update_normals(bvh, nodes, totnode, face_nors);
@@ -1699,15 +1652,15 @@ void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
if (nodes) MEM_freeN(nodes);
if (planes) {
- BLI_pbvh_search_callback(bvh, BLI_pbvh_node_planes_contain_AABB,
- planes, BLI_pbvh_node_draw, setMaterial);
+ BKE_pbvh_search_callback(bvh, BKE_pbvh_node_planes_contain_AABB,
+ planes, BKE_pbvh_node_draw, &draw_data);
}
else {
- BLI_pbvh_search_callback(bvh, NULL, NULL, BLI_pbvh_node_draw, setMaterial);
+ BKE_pbvh_search_callback(bvh, NULL, NULL, BKE_pbvh_node_draw, &draw_data);
}
}
-void BLI_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, void **gridfaces,
+void BKE_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, void **gridfaces,
DMFlagMat *flagmats, BLI_bitmap *grid_hidden)
{
int a;
@@ -1721,11 +1674,31 @@ void BLI_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj,
bvh->grid_hidden = grid_hidden;
for (a = 0; a < bvh->totnode; ++a)
- BLI_pbvh_node_mark_rebuild_draw(&bvh->nodes[a]);
+ BKE_pbvh_node_mark_rebuild_draw(&bvh->nodes[a]);
}
}
-float (*BLI_pbvh_get_vertCos(PBVH * pbvh))[3]
+/* Get the node's displacement layer, creating it if necessary */
+float *BKE_pbvh_node_layer_disp_get(PBVH *bvh, PBVHNode *node)
+{
+ if (!node->layer_disp) {
+ int totvert = 0;
+ BKE_pbvh_node_num_verts(bvh, node, &totvert, NULL);
+ node->layer_disp = MEM_callocN(sizeof(float) * totvert, "layer disp");
+ }
+ return node->layer_disp;
+}
+
+/* If the node has a displacement layer, free it and set to null */
+void BKE_pbvh_node_layer_disp_free(PBVHNode *node)
+{
+ if (node->layer_disp) {
+ MEM_freeN(node->layer_disp);
+ node->layer_disp = NULL;
+ }
+}
+
+float (*BKE_pbvh_get_vertCos(PBVH * pbvh))[3]
{
int a;
float (*vertCos)[3] = NULL;
@@ -1734,7 +1707,7 @@ float (*BLI_pbvh_get_vertCos(PBVH * pbvh))[3]
float *co;
MVert *mvert = pbvh->verts;
- vertCos = MEM_callocN(3 * pbvh->totvert * sizeof(float), "BLI_pbvh_get_vertCoords");
+ vertCos = MEM_callocN(3 * pbvh->totvert * sizeof(float), "BKE_pbvh_get_vertCoords");
co = (float *)vertCos;
for (a = 0; a < pbvh->totvert; a++, mvert++, co += 3) {
@@ -1745,7 +1718,7 @@ float (*BLI_pbvh_get_vertCos(PBVH * pbvh))[3]
return vertCos;
}
-void BLI_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3])
+void BKE_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3])
{
int a;
@@ -1774,21 +1747,21 @@ void BLI_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3])
BKE_mesh_calc_normals_tessface(pbvh->verts, pbvh->totvert, pbvh->faces, pbvh->totprim, NULL);
for (a = 0; a < pbvh->totnode; ++a)
- BLI_pbvh_node_mark_update(&pbvh->nodes[a]);
+ BKE_pbvh_node_mark_update(&pbvh->nodes[a]);
- BLI_pbvh_update(pbvh, PBVH_UpdateBB, NULL);
- BLI_pbvh_update(pbvh, PBVH_UpdateOriginalBB, NULL);
+ BKE_pbvh_update(pbvh, PBVH_UpdateBB, NULL);
+ BKE_pbvh_update(pbvh, PBVH_UpdateOriginalBB, NULL);
}
}
-int BLI_pbvh_isDeformed(PBVH *pbvh)
+int BKE_pbvh_isDeformed(PBVH *pbvh)
{
return pbvh->deformed;
}
/* Proxies */
-PBVHProxyNode *BLI_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node)
+PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node)
{
int index, totverts;
@@ -1804,14 +1777,14 @@ PBVHProxyNode *BLI_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node)
else
node->proxies = MEM_mallocN(sizeof(PBVHProxyNode), "PBVHNodeProxy");
- BLI_pbvh_node_num_verts(bvh, node, &totverts, NULL);
+ BKE_pbvh_node_num_verts(bvh, node, &totverts, NULL);
node->proxies[index].co = MEM_callocN(sizeof(float[3]) * totverts, "PBVHNodeProxy.co");
}
return node->proxies + index;
}
-void BLI_pbvh_node_free_proxies(PBVHNode *node)
+void BKE_pbvh_node_free_proxies(PBVHNode *node)
{
#pragma omp critical
{
@@ -1829,7 +1802,7 @@ void BLI_pbvh_node_free_proxies(PBVHNode *node)
}
}
-void BLI_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot)
+void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot)
{
PBVHNode **array = NULL, **newarray, *node;
int tot = 0, space = 0;
@@ -1842,7 +1815,7 @@ void BLI_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot)
if (tot == space) {
/* resize array if needed */
space = (tot == 0) ? 32 : space * 2;
- newarray = MEM_callocN(sizeof(PBVHNode) * space, "BLI_pbvh_gather_proxies");
+ newarray = MEM_callocN(sizeof(PBVHNode) * space, "BKE_pbvh_gather_proxies");
if (array) {
memcpy(newarray, array, sizeof(PBVHNode) * tot);
@@ -1879,9 +1852,9 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
vi->fno = 0;
vi->mvert = 0;
- BLI_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL, &gridsize, &grids, NULL);
- BLI_pbvh_node_num_verts(bvh, node, &uniq_verts, &totvert);
- BLI_pbvh_node_get_verts(bvh, node, &vert_indices, &verts);
+ BKE_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL, &gridsize, &grids, NULL);
+ BKE_pbvh_node_num_verts(bvh, node, &uniq_verts, &totvert);
+ BKE_pbvh_node_get_verts(bvh, node, &vert_indices, &verts);
vi->key = &bvh->gridkey;
vi->grids = grids;
@@ -1896,12 +1869,18 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
vi->vert_indices = vert_indices;
vi->mverts = verts;
+ if (bvh->type == PBVH_BMESH) {
+ BLI_ghashIterator_init(&vi->bm_unique_verts, node->bm_unique_verts);
+ BLI_ghashIterator_init(&vi->bm_other_verts, node->bm_other_verts);
+ vi->bm_vdata = &bvh->bm->vdata;
+ }
+
vi->gh = NULL;
if (vi->grids && mode == PBVH_ITER_UNIQUE)
vi->grid_hidden = bvh->grid_hidden;
vi->mask = NULL;
- if (!vi->grids)
+ if (bvh->type == PBVH_FACES)
vi->vmask = CustomData_get_layer(bvh->vdata, CD_PAINT_MASK);
}
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
new file mode 100644
index 00000000000..421821f3a2d
--- /dev/null
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -0,0 +1,1440 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_buffer.h"
+#include "BLI_ghash.h"
+#include "BLI_heap.h"
+#include "BLI_math.h"
+
+#include "BKE_ccg.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_global.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
+
+#include "GPU_buffers.h"
+
+#include "bmesh.h"
+#include "pbvh_intern.h"
+
+#include <assert.h>
+
+/****************************** Building ******************************/
+
+/* Update node data after splitting */
+static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index)
+{
+ GHashIterator gh_iter;
+ PBVHNode *n = &bvh->nodes[node_index];
+
+ /* Create vert hash sets */
+ n->bm_unique_verts = BLI_ghash_ptr_new("bm_unique_verts");
+ n->bm_other_verts = BLI_ghash_ptr_new("bm_other_verts");
+
+ BB_reset(&n->vb);
+
+ GHASH_ITER (gh_iter, n->bm_faces) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ BMVert *v;
+ void *node_val = SET_INT_IN_POINTER(node_index);
+
+ /* Update ownership of faces */
+ BLI_ghash_insert(bvh->bm_face_to_node, f, node_val);
+
+ /* Update vertices */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ v = l_iter->v;
+ if (!BLI_ghash_haskey(n->bm_unique_verts, v)) {
+ if (BLI_ghash_haskey(bvh->bm_vert_to_node, v)) {
+ if (!BLI_ghash_haskey(n->bm_other_verts, v))
+ BLI_ghash_insert(n->bm_other_verts, v, NULL);
+ }
+ else {
+ BLI_ghash_insert(n->bm_unique_verts, v, NULL);
+ BLI_ghash_insert(bvh->bm_vert_to_node, v, node_val);
+ }
+ }
+ /* Update node bounding box */
+ BB_expand(&n->vb, v->co);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ 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 */
+ if (!G.background) {
+ int smooth = bvh->flags & PBVH_DYNTOPO_SMOOTH_SHADING;
+ n->draw_buffers = GPU_build_bmesh_buffers(smooth);
+ n->flag |= PBVH_UpdateDrawBuffers;
+ }
+}
+
+/* Recursively split the node if it exceeds the leaf_limit */
+static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index)
+{
+ GHash *empty, *other;
+ GHashIterator gh_iter;
+ PBVHNode *n, *c1, *c2;
+ BB cb;
+ float mid;
+ int axis, children;
+
+ n = &bvh->nodes[node_index];
+
+ if (BLI_ghash_size(n->bm_faces) <= bvh->leaf_limit) {
+ /* Node limit not exceeded */
+ pbvh_bmesh_node_finalize(bvh, node_index);
+ return;
+ }
+
+ /* Calculate bounding box around primitive centroids */
+ BB_reset(&cb);
+ GHASH_ITER (gh_iter, n->bm_faces) {
+ const BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+ const BBC *bbc = BLI_ghash_lookup(prim_bbc, f);
+
+ BB_expand(&cb, bbc->bcentroid);
+ }
+
+ /* Find widest axis and its midpoint */
+ axis = BB_widest_axis(&cb);
+ mid = (cb.bmax[axis] + cb.bmin[axis]) * 0.5f;
+
+ /* Add two new child nodes */
+ children = bvh->totnode;
+ n->children_offset = children;
+ pbvh_grow_nodes(bvh, bvh->totnode + 2);
+
+ /* Array reallocated, update current node pointer */
+ n = &bvh->nodes[node_index];
+
+ /* Initialize children */
+ c1 = &bvh->nodes[children];
+ c2 = &bvh->nodes[children + 1];
+ c1->flag |= PBVH_Leaf;
+ c2->flag |= PBVH_Leaf;
+ c1->bm_faces = BLI_ghash_ptr_new("bm_faces");
+ c2->bm_faces = BLI_ghash_ptr_new("bm_faces");
+
+ /* Partition the parent node's faces between the two children */
+ GHASH_ITER (gh_iter, n->bm_faces) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+ const BBC *bbc = BLI_ghash_lookup(prim_bbc, f);
+
+ if (bbc->bcentroid[axis] < mid)
+ BLI_ghash_insert(c1->bm_faces, f, NULL);
+ else
+ BLI_ghash_insert(c2->bm_faces, f, NULL);
+ }
+
+ /* Enforce at least one primitive in each node */
+ empty = NULL;
+ if (BLI_ghash_size(c1->bm_faces) == 0) {
+ empty = c1->bm_faces;
+ other = c2->bm_faces;
+ }
+ else if (BLI_ghash_size(c2->bm_faces) == 0) {
+ empty = c2->bm_faces;
+ other = c1->bm_faces;
+ }
+ if (empty) {
+ GHASH_ITER (gh_iter, other) {
+ void *key = BLI_ghashIterator_getKey(&gh_iter);
+ BLI_ghash_insert(empty, key, NULL);
+ BLI_ghash_remove(other, key, NULL, NULL);
+ break;
+ }
+ }
+
+ /* Clear this node */
+
+ /* Mark this node's unique verts as unclaimed */
+ if (n->bm_unique_verts) {
+ GHASH_ITER (gh_iter, n->bm_unique_verts) {
+ BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL);
+ }
+ BLI_ghash_free(n->bm_unique_verts, NULL, NULL);
+ }
+
+ /* Unclaim faces */
+ GHASH_ITER (gh_iter, n->bm_faces) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+ BLI_ghash_remove(bvh->bm_face_to_node, f, NULL, NULL);
+ }
+ BLI_ghash_free(n->bm_faces, NULL, NULL);
+
+ if (n->bm_other_verts)
+ BLI_ghash_free(n->bm_other_verts, NULL, NULL);
+
+ if (n->layer_disp)
+ MEM_freeN(n->layer_disp);
+
+ n->bm_faces = NULL;
+ n->bm_unique_verts = NULL;
+ n->bm_other_verts = NULL;
+ n->layer_disp = NULL;
+
+ if (n->draw_buffers) {
+ GPU_free_buffers(n->draw_buffers);
+ n->draw_buffers = NULL;
+ }
+ n->flag &= ~PBVH_Leaf;
+
+ /* Recurse */
+ c1 = c2 = NULL;
+ pbvh_bmesh_node_split(bvh, prim_bbc, children);
+ pbvh_bmesh_node_split(bvh, prim_bbc, children + 1);
+
+ /* Array maybe reallocated, update current node pointer */
+ 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;
+}
+
+/* Recursively split the node if it exceeds the leaf_limit */
+static int pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
+{
+ GHash *prim_bbc;
+ GHashIterator gh_iter;
+
+ if (BLI_ghash_size(bvh->nodes[node_index].bm_faces) <= bvh->leaf_limit) {
+ /* Node limit not exceeded */
+ return FALSE;
+ }
+
+ /* For each BMFace, store the AABB and AABB centroid */
+ prim_bbc = BLI_ghash_ptr_new("prim_bbc");
+
+ GHASH_ITER (gh_iter, bvh->nodes[node_index].bm_faces) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+ BBC *bbc = MEM_callocN(sizeof(BBC), "BBC");
+ 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);
+
+ BLI_ghash_insert(prim_bbc, f, bbc);
+ }
+
+ pbvh_bmesh_node_split(bvh, prim_bbc, node_index);
+
+ BLI_ghash_free(prim_bbc, NULL, (void *)MEM_freeN);
+
+ return TRUE;
+}
+
+/**********************************************************************/
+
+static PBVHNode *pbvh_bmesh_node_lookup(PBVH *bvh, GHash *map, void *key)
+{
+ int node_index;
+
+ BLI_assert(BLI_ghash_haskey(map, key));
+
+ node_index = GET_INT_FROM_POINTER(BLI_ghash_lookup(map, key));
+ BLI_assert(node_index < bvh->totnode);
+
+ return &bvh->nodes[node_index];
+}
+
+static BMVert *pbvh_bmesh_vert_create(PBVH *bvh, int node_index,
+ const float co[3],
+ const BMVert *example)
+{
+ BMVert *v = BM_vert_create(bvh->bm, co, example, 0);
+ void *val = SET_INT_IN_POINTER(node_index);
+
+ BLI_assert((bvh->totnode == 1 || node_index) && node_index <= bvh->totnode);
+
+ BLI_ghash_insert(bvh->nodes[node_index].bm_unique_verts, v, NULL);
+ BLI_ghash_insert(bvh->bm_vert_to_node, v, val);
+
+ /* Log the new vertex */
+ BM_log_vert_added(bvh->bm, bvh->bm_log, v);
+
+ return v;
+}
+
+static BMFace *pbvh_bmesh_face_create(PBVH *bvh, int node_index,
+ BMVert *v1, BMVert *v2, BMVert *v3,
+ const BMFace *UNUSED(example))
+{
+ BMFace *f;
+ void *val = SET_INT_IN_POINTER(node_index);
+
+ /* Note: passing NULL for the 'example' parameter, profiling shows
+ * a small performance bump */
+ f = BM_face_create_quad_tri(bvh->bm, v1, v2, v3, NULL, NULL, true);
+ if (!BLI_ghash_haskey(bvh->bm_face_to_node, f)) {
+
+ BLI_ghash_insert(bvh->nodes[node_index].bm_faces, f, NULL);
+ BLI_ghash_insert(bvh->bm_face_to_node, f, val);
+
+ /* Log the new face */
+ BM_log_face_added(bvh->bm_log, f);
+ }
+
+ return f;
+}
+
+/* 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)
+{
+ BMIter bm_iter;
+ BMFace *f;
+ int count = 0;
+
+ BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
+ PBVHNode *f_node;
+
+ f_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f);
+
+ if (f_node == node)
+ count++;
+ }
+
+ 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)
+{
+ BMIter bm_iter;
+ BMFace *f;
+ PBVHNode *current_node;
+
+ current_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_vert_to_node, v);
+
+ BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
+ PBVHNode *f_node;
+
+ f_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f);
+
+ if (f_node != current_node)
+ return f_node;
+ }
+
+ return NULL;
+}
+
+static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner,
+ BMVert *v)
+{
+ PBVHNode *current_owner;
+
+ current_owner = pbvh_bmesh_node_lookup(bvh, bvh->bm_vert_to_node, v);
+ BLI_assert(current_owner != new_owner);
+
+ /* Remove current ownership */
+ BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL);
+ BLI_ghash_remove(current_owner->bm_unique_verts, v, NULL, NULL);
+
+ /* Set new ownership */
+ BLI_ghash_insert(bvh->bm_vert_to_node, v,
+ SET_INT_IN_POINTER(new_owner - bvh->nodes));
+ BLI_ghash_insert(new_owner->bm_unique_verts, v, NULL);
+ BLI_ghash_remove(new_owner->bm_other_verts, v, NULL, NULL);
+ BLI_assert(!BLI_ghash_haskey(new_owner->bm_other_verts, v));
+}
+
+static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v)
+{
+ PBVHNode *v_node;
+ BMIter bm_iter;
+ BMFace *f;
+
+ BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v));
+ v_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_vert_to_node, v);
+ BLI_ghash_remove(v_node->bm_unique_verts, v, NULL, NULL);
+ BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL);
+
+ /* 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, bvh->bm_face_to_node, f);
+
+ BLI_ghash_remove(f_node->bm_unique_verts, v, NULL, NULL);
+ BLI_ghash_remove(f_node->bm_other_verts, v, NULL, NULL);
+
+ BLI_assert(!BLI_ghash_haskey(f_node->bm_unique_verts, v));
+ BLI_assert(!BLI_ghash_haskey(f_node->bm_other_verts, v));
+ }
+}
+
+static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f)
+{
+ PBVHNode *f_node;
+ BMVert *v;
+
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ f_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, 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) == 1) {
+ if (BLI_ghash_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);
+ BLI_assert(new_node || BM_vert_face_count(v) == 1);
+
+ if (new_node) {
+ pbvh_bmesh_vert_ownership_transfer(bvh, new_node, v);
+ }
+ }
+ else {
+ /* Remove from other verts */
+ BLI_ghash_remove(f_node->bm_other_verts, v, NULL, NULL);
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ /* Remove face from node and top level */
+ BLI_ghash_remove(f_node->bm_faces, f, NULL, NULL);
+ BLI_ghash_remove(bvh->bm_face_to_node, f, NULL, NULL);
+
+ /* Log removed face */
+ BM_log_face_removed(bvh->bm_log, f);
+}
+
+static void pbvh_bmesh_edge_loops(BLI_Buffer *buf, BMEdge *e)
+{
+ /* fast-path for most common case where an edge has 2 faces,
+ * no need to iterate twice.
+ * This assumes that the buffer */
+ BMLoop **data = buf->data;
+ BLI_assert(buf->alloc_count >= 2);
+ if (LIKELY(BM_edge_loop_pair(e, &data[0], &data[1]))) {
+ buf->count = 2;
+ }
+ else {
+ BLI_buffer_resize(buf, BM_edge_face_count(e));
+ BM_iter_as_array(NULL, BM_LOOPS_OF_EDGE, e, buf->data, buf->count);
+ }
+}
+
+static void pbvh_bmesh_node_drop_orig(PBVHNode *node)
+{
+ if (node->bm_orco)
+ MEM_freeN(node->bm_orco);
+ if (node->bm_ortri)
+ MEM_freeN(node->bm_ortri);
+ node->bm_orco = NULL;
+ node->bm_ortri = NULL;
+ node->bm_tot_ortri = 0;
+}
+
+/****************************** EdgeQueue *****************************/
+
+typedef struct {
+ Heap *heap;
+ const float *center;
+ float radius_squared;
+ float limit_len_squared;
+} EdgeQueue;
+
+static int edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f)
+{
+ BMVert *v_tri[3];
+ float c[3];
+
+ /* Get closest point in triangle to sphere center */
+ // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v_tri, 3);
+ BM_face_as_array_vert_tri(f, v_tri);
+
+ closest_on_tri_to_point_v3(c, q->center, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co);
+
+ /* Check if triangle intersects the sphere */
+ return ((len_squared_v3v3(q->center, c) <= q->radius_squared));
+}
+
+/* Return true if the vertex mask is less than 0.5, false otherwise */
+static int check_mask_half(BMesh *bm, BMVert *v)
+{
+ const float *mask;
+
+ mask = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_PAINT_MASK);
+ return ((*mask) < 0.5f);
+}
+
+static void edge_queue_insert(EdgeQueue *q, BLI_mempool *pool, BMEdge *e,
+ float priority, BMesh *bm)
+{
+ BMVert **pair;
+
+ /* Don't let topology update affect masked vertices. Unlike with
+ * displacements, can't do 50% topology update, so instead set
+ * (arbitrary) cutoff: if both vertices' masks are less than 50%,
+ * topology update can happen. */
+ if (check_mask_half(bm, e->v1) && check_mask_half(bm, e->v2)) {
+ pair = BLI_mempool_alloc(pool);
+ pair[0] = e->v1;
+ pair[1] = e->v2;
+ BLI_heap_insert(q->heap, priority, pair);
+ }
+}
+
+static void long_edge_queue_edge_add(EdgeQueue *q, BLI_mempool *pool,
+ BMEdge *e, BMesh *bm)
+{
+ const float len_sq = BM_edge_calc_length_squared(e);
+ if (len_sq > q->limit_len_squared)
+ edge_queue_insert(q, pool, e, 1.0f / len_sq, bm);
+}
+
+static void short_edge_queue_edge_add(EdgeQueue *q, BLI_mempool *pool,
+ BMEdge *e, BMesh *bm)
+{
+ const float len_sq = BM_edge_calc_length_squared(e);
+ if (len_sq < q->limit_len_squared)
+ edge_queue_insert(q, pool, e, len_sq, bm);
+}
+
+static void long_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool,
+ BMFace *f, BMesh *bm)
+{
+ if (edge_queue_tri_in_sphere(q, f)) {
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ /* Check each edge of the face */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ long_edge_queue_edge_add(q, pool, l_iter->e, bm);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+}
+
+static void short_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool,
+ BMFace *f, BMesh *bm)
+{
+ if (edge_queue_tri_in_sphere(q, f)) {
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ /* Check each edge of the face */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ short_edge_queue_edge_add(q, pool, l_iter->e, bm);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+}
+
+/* Create a priority queue containing vertex pairs connected by a long
+ * edge as defined by PBVH.bm_max_edge_len.
+ *
+ * Only nodes marked for topology update are checked, and in those
+ * nodes only edges used by a face intersecting the (center, radius)
+ * sphere are checked.
+ *
+ * The highest priority (lowest number) is given to the longest edge.
+ */
+static void long_edge_queue_create(EdgeQueue *q, BLI_mempool *pool,
+ PBVH *bvh, const float center[3],
+ float radius)
+{
+ int n;
+
+ q->heap = BLI_heap_new();
+ q->center = center;
+ q->radius_squared = radius * radius;
+ q->limit_len_squared = bvh->bm_max_edge_len * bvh->bm_max_edge_len;
+
+ for (n = 0; n < bvh->totnode; n++) {
+ PBVHNode *node = &bvh->nodes[n];
+
+ /* Check leaf nodes marked for topology update */
+ if ((node->flag & PBVH_Leaf) &&
+ (node->flag & PBVH_UpdateTopology))
+ {
+ GHashIterator gh_iter;
+
+ /* Check each face */
+ GHASH_ITER (gh_iter, node->bm_faces) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+
+ long_edge_queue_face_add(q, pool, f, bvh->bm);
+ }
+ }
+ }
+}
+
+/* Create a priority queue containing vertex pairs connected by a
+ * short edge as defined by PBVH.bm_min_edge_len.
+ *
+ * Only nodes marked for topology update are checked, and in those
+ * nodes only edges used by a face intersecting the (center, radius)
+ * sphere are checked.
+ *
+ * The highest priority (lowest number) is given to the shortest edge.
+ */
+static void short_edge_queue_create(EdgeQueue *q, BLI_mempool *pool,
+ PBVH *bvh, const float center[3],
+ float radius)
+{
+ int n;
+
+ q->heap = BLI_heap_new();
+ q->center = center;
+ q->radius_squared = radius * radius;
+ q->limit_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len;
+
+ for (n = 0; n < bvh->totnode; n++) {
+ PBVHNode *node = &bvh->nodes[n];
+
+ /* Check leaf nodes marked for topology update */
+ if ((node->flag & PBVH_Leaf) &&
+ (node->flag & PBVH_UpdateTopology))
+ {
+ GHashIterator gh_iter;
+
+ /* Check each face */
+ GHASH_ITER (gh_iter, node->bm_faces) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+
+ short_edge_queue_face_add(q, pool, f, bvh->bm);
+ }
+ }
+ }
+}
+
+/*************************** Topology update **************************/
+
+static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool,
+ BMEdge *e, BLI_Buffer *edge_loops)
+{
+ BMVert *v_new;
+ float 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);
+
+ node_index = GET_INT_FROM_POINTER(BLI_ghash_lookup(bvh->bm_vert_to_node,
+ e->v1));
+ v_new = pbvh_bmesh_vert_create(bvh, node_index, mid, e->v1);
+
+ /* For each face, add two new triangles and delete the original */
+ for (i = 0; i < edge_loops->count; i++) {
+ BMLoop *l_adj = BLI_buffer_at(edge_loops, BMLoop *, i);
+ BMFace *f_adj = l_adj->f;
+ BMFace *f_new;
+ BMVert *opp, *v1, *v2;
+ void *nip;
+ int ni;
+
+ BLI_assert(f_adj->len == 3);
+ nip = BLI_ghash_lookup(bvh->bm_face_to_node, f_adj);
+ ni = GET_INT_FROM_POINTER(nip);
+
+ /* Ensure node gets redrawn */
+ bvh->nodes[ni].flag |= PBVH_UpdateDrawBuffers;
+
+ /* Find the vertex not in the edge */
+ opp = l_adj->prev->v;
+
+ /* Get e->v1 and e->v2 in the order they appear in the
+ * existing face so that the new faces' winding orders
+ * match */
+ v1 = l_adj->v;
+ v2 = l_adj->next->v;
+
+ if (ni != node_index && i == 0)
+ pbvh_bmesh_vert_ownership_transfer(bvh, &bvh->nodes[ni], v_new);
+
+ /* Create two new faces */
+ f_new = pbvh_bmesh_face_create(bvh, ni, v1, v_new, opp, f_adj);
+ long_edge_queue_face_add(q, pool, f_new, bvh->bm);
+ f_new = pbvh_bmesh_face_create(bvh, ni, v_new, v2, opp, f_adj);
+ long_edge_queue_face_add(q, pool, f_new, bvh->bm);
+
+ /* Delete original */
+ pbvh_bmesh_face_remove(bvh, f_adj);
+ BM_face_kill(bvh->bm, f_adj);
+
+ /* Ensure new vertex is in the node */
+ if (!BLI_ghash_haskey(bvh->nodes[ni].bm_unique_verts, v_new) &&
+ !BLI_ghash_haskey(bvh->nodes[ni].bm_other_verts, v_new))
+ {
+ BLI_ghash_insert(bvh->nodes[ni].bm_other_verts, v_new, NULL);
+ }
+
+ if (BM_vert_edge_count(opp) >= 9) {
+ BMIter bm_iter;
+ BMEdge *e2;
+
+ BM_ITER_ELEM (e2, &bm_iter, opp, BM_EDGES_OF_VERT) {
+ long_edge_queue_edge_add(q, pool, e2, bvh->bm);
+ }
+ }
+ }
+
+ BM_edge_kill(bvh->bm, e);
+}
+
+static int pbvh_bmesh_subdivide_long_edges(PBVH *bvh, EdgeQueue *q,
+ BLI_mempool *pool,
+ BLI_Buffer *edge_loops)
+{
+ int any_subdivided = FALSE;
+
+ while (!BLI_heap_is_empty(q->heap)) {
+ BMVert **pair = BLI_heap_popmin(q->heap);
+ BMEdge *e;
+
+ /* Check that the edge still exists */
+ if (!(e = BM_edge_exists(pair[0], pair[1]))) {
+ BLI_mempool_free(pool, pair);
+ continue;
+ }
+
+ BLI_mempool_free(pool, pair);
+ pair = NULL;
+
+ /* Check that the edge's vertices are still in the PBVH. It's
+ * possible that an edge collapse has deleted adjacent faces
+ * and the node has been split, thus leaving wire edges and
+ * associated vertices. */
+ if (!BLI_ghash_haskey(bvh->bm_vert_to_node, e->v1) ||
+ !BLI_ghash_haskey(bvh->bm_vert_to_node, e->v2))
+ {
+ continue;
+ }
+
+ if (BM_edge_calc_length_squared(e) <= q->limit_len_squared)
+ continue;
+
+ any_subdivided = TRUE;
+
+ pbvh_bmesh_split_edge(bvh, q, pool, e, edge_loops);
+ }
+
+ return any_subdivided;
+}
+
+static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1,
+ BMVert *v2, GHash *deleted_verts,
+ BLI_Buffer *edge_loops,
+ BLI_Buffer *deleted_faces)
+{
+ BMIter bm_iter;
+ BMFace *f;
+ int i;
+
+ /* 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, v2);
+
+ /* 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);
+ BMFace *f_adj = l_adj->f;
+
+ pbvh_bmesh_face_remove(bvh, f_adj);
+ BM_face_kill(bvh->bm, f_adj);
+ }
+
+ /* Kill the edge */
+ BLI_assert(BM_edge_face_count(e) == 0);
+ BM_edge_kill(bvh->bm, e);
+
+ /* For all remaining faces of v2, create a new face that is the
+ * same except it uses v1 instead of v2 */
+ /* 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;
+ BM_ITER_ELEM (f, &bm_iter, v2, BM_FACES_OF_VERT) {
+ BMVert *v_tri[3];
+ BMFace *existing_face;
+ PBVHNode *n;
+ int ni;
+
+ /* Get vertices, replace use of v2 with v1 */
+ // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v_tri, 3);
+ BM_face_as_array_vert_tri(f, v_tri);
+ for (i = 0; i < 3; i++) {
+ if (v_tri[i] == v2) {
+ v_tri[i] = v1;
+ }
+ }
+
+ /* Check if a face using these vertices already exists. If so,
+ * skip adding this face and mark the existing one for
+ * deletion as well. Prevents extraneous "flaps" from being
+ * created. */
+ if (BM_face_exists(v_tri, 3, &existing_face)) {
+ BLI_assert(existing_face);
+ BLI_buffer_append(deleted_faces, BMFace *, existing_face);
+ }
+ else {
+ n = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f);
+ ni = n - bvh->nodes;
+ pbvh_bmesh_face_create(bvh, ni, v_tri[0], v_tri[1], v_tri[2], f);
+
+ /* Ensure that v1 is in the new face's node */
+ if (!BLI_ghash_haskey(n->bm_unique_verts, v1) &&
+ !BLI_ghash_haskey(n->bm_other_verts, v1))
+ {
+ BLI_ghash_insert(n->bm_other_verts, v1, NULL);
+ }
+ }
+
+ BLI_buffer_append(deleted_faces, BMFace *, f);
+ }
+
+ /* Delete the tagged faces */
+ for (i = 0; i < deleted_faces->count; i++) {
+ BMFace *f_del = BLI_buffer_at(deleted_faces, BMFace *, i);
+ BMVert *v_tri[3];
+ BMEdge *e_tri[3];
+ int j;
+
+ /* Get vertices and edges of face */
+ BM_face_as_array_vert_tri(f_del, v_tri);
+ for (j = 0; j < 3; j++)
+ e_tri[j] = BM_edge_exists(v_tri[j], v_tri[j == 2 ? 0 : j + 1]);
+
+ /* 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] != v2 && BM_vert_face_count(v_tri[j]) == 1) {
+ BLI_ghash_insert(deleted_verts, v_tri[j], NULL);
+ pbvh_bmesh_vert_remove(bvh, v_tri[j]);
+ }
+ else {
+ v_tri[j] = NULL;
+ }
+ }
+
+ /* Remove the face */
+ 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
+ * face, if so delete them */
+ for (j = 0; j < 3; j++) {
+ if (BM_edge_face_count(e_tri[j]) == 0)
+ BM_edge_kill(bvh->bm, e_tri[j]);
+ }
+
+ /* Delete unused vertices */
+ for (j = 0; j < 3; j++) {
+ if (v_tri[j]) {
+ BM_log_vert_removed(bvh->bm, bvh->bm_log, v_tri[j]);
+ BM_vert_kill(bvh->bm, v_tri[j]);
+ }
+ }
+ }
+
+ /* Move v1 to the midpoint of v1 and v2 (if v1 still exists, it
+ * may have been deleted above) */
+ if (!BLI_ghash_haskey(deleted_verts, v1)) {
+ BM_log_vert_before_modified(bvh->bm, bvh->bm_log, v1);
+ mid_v3_v3v3(v1->co, v1->co, v2->co);
+ }
+
+ /* Delete v2 */
+ BLI_assert(BM_vert_face_count(v2) == 0);
+ BLI_ghash_insert(deleted_verts, v2, NULL);
+ BM_log_vert_removed(bvh->bm, bvh->bm_log, v2);
+ BM_vert_kill(bvh->bm, v2);
+}
+
+static int pbvh_bmesh_collapse_short_edges(PBVH *bvh, EdgeQueue *q,
+ BLI_mempool *pool,
+ BLI_Buffer *edge_loops,
+ BLI_Buffer *deleted_faces)
+{
+ float min_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len;
+ GHash *deleted_verts;
+ int any_collapsed = FALSE;
+
+ deleted_verts = BLI_ghash_ptr_new("deleted_verts");
+
+ while (!BLI_heap_is_empty(q->heap)) {
+ BMVert **pair = BLI_heap_popmin(q->heap);
+ BMEdge *e;
+ BMVert *v1, *v2;
+
+ v1 = pair[0];
+ v2 = pair[1];
+ BLI_mempool_free(pool, pair);
+ pair = NULL;
+
+ /* Check that the vertices/edge still exist */
+ if (BLI_ghash_haskey(deleted_verts, v1) ||
+ BLI_ghash_haskey(deleted_verts, v2) ||
+ !(e = BM_edge_exists(v1, v2)))
+ {
+ continue;
+ }
+
+ /* Check that the edge's vertices are still in the PBVH. It's
+ * possible that an edge collapse has deleted adjacent faces
+ * and the node has been split, thus leaving wire edges and
+ * associated vertices. */
+ if (!BLI_ghash_haskey(bvh->bm_vert_to_node, e->v1) ||
+ !BLI_ghash_haskey(bvh->bm_vert_to_node, e->v2))
+ {
+ continue;
+ }
+
+ if (BM_edge_calc_length_squared(e) >= min_len_squared)
+ continue;
+
+ any_collapsed = TRUE;
+
+ pbvh_bmesh_collapse_edge(bvh, e, v1, v2,
+ deleted_verts, edge_loops,
+ deleted_faces);
+ }
+
+ BLI_ghash_free(deleted_verts, NULL, NULL);
+
+ return any_collapsed;
+}
+
+/************************* Called from pbvh.c *************************/
+
+int pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3],
+ const float ray_normal[3], float *dist,
+ int use_original)
+{
+ GHashIterator gh_iter;
+ int hit = 0;
+
+ if (use_original && node->bm_tot_ortri) {
+ 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);
+ }
+ }
+ else {
+ GHASH_ITER (gh_iter, node->bm_faces) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+
+ BLI_assert(f->len == 3);
+ if (f->len == 3 && !paint_is_bmesh_face_hidden(f)) {
+ 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);
+ }
+ }
+ }
+
+ return hit;
+}
+
+void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode)
+{
+ int n;
+
+ for (n = 0; n < totnode; n++) {
+ PBVHNode *node = nodes[n];
+ GHashIterator gh_iter;
+
+ GHASH_ITER (gh_iter, node->bm_faces) {
+ BM_face_normal_update(BLI_ghashIterator_getKey(&gh_iter));
+ }
+ GHASH_ITER (gh_iter, node->bm_unique_verts) {
+ BM_vert_normal_update(BLI_ghashIterator_getKey(&gh_iter));
+ }
+ }
+}
+
+/***************************** Public API *****************************/
+
+/* Build a PBVH from a BMesh */
+void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, int smooth_shading,
+ BMLog *log)
+{
+ BMIter iter;
+ BMFace *f;
+ PBVHNode *n;
+ int node_index = 0;
+
+ bvh->bm = bm;
+
+ BKE_pbvh_bmesh_detail_size_set(bvh, 0.75);
+
+ bvh->type = PBVH_BMESH;
+ bvh->bm_face_to_node = BLI_ghash_ptr_new("bm_face_to_node");
+ bvh->bm_vert_to_node = BLI_ghash_ptr_new("bm_vert_to_node");
+ bvh->bm_log = log;
+
+ /* TODO: choose leaf limit better */
+ bvh->leaf_limit = 100;
+
+ if (smooth_shading)
+ bvh->flags |= PBVH_DYNTOPO_SMOOTH_SHADING;
+
+ /* Start with all faces in the root node */
+ n = bvh->nodes = MEM_callocN(sizeof(PBVHNode), "PBVHNode");
+ bvh->totnode = 1;
+ n->flag = PBVH_Leaf;
+ n->bm_faces = BLI_ghash_ptr_new("bm_faces");
+ BM_ITER_MESH (f, &iter, bvh->bm, BM_FACES_OF_MESH) {
+ BLI_ghash_insert(n->bm_faces, f, NULL);
+ }
+
+ /* 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);
+}
+
+/* Collapse short edges, subdivide long edges */
+int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
+ const float center[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(BMFace *, deleted_faces, BLI_BUFFER_NOP, 32);
+
+ int modified = FALSE;
+ int n;
+
+ if (mode & PBVH_Collapse) {
+ EdgeQueue q;
+ BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert) * 2,
+ 128, 128, 0);
+ short_edge_queue_create(&q, queue_pool, bvh, center, radius);
+ pbvh_bmesh_collapse_short_edges(bvh, &q, queue_pool, &edge_loops,
+ &deleted_faces);
+ BLI_heap_free(q.heap, NULL);
+ BLI_mempool_destroy(queue_pool);
+ }
+
+ if (mode & PBVH_Subdivide) {
+ EdgeQueue q;
+ BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert) * 2,
+ 128, 128, 0);
+ long_edge_queue_create(&q, queue_pool, bvh, center, radius);
+ pbvh_bmesh_subdivide_long_edges(bvh, &q, queue_pool, &edge_loops);
+ BLI_heap_free(q.heap, NULL);
+ BLI_mempool_destroy(queue_pool);
+ }
+
+ /* Unmark nodes */
+ for (n = 0; n < bvh->totnode; n++) {
+ PBVHNode *node = &bvh->nodes[n];
+
+ if (node->flag & PBVH_Leaf &&
+ node->flag & PBVH_UpdateTopology)
+ {
+ node->flag &= ~PBVH_UpdateTopology;
+ }
+ }
+ BLI_buffer_free(&edge_loops);
+ BLI_buffer_free(&deleted_faces);
+
+ return modified;
+}
+
+BLI_INLINE void bm_face_as_array_index_tri(BMFace *f, int r_index[3])
+{
+ BMLoop *l = BM_FACE_FIRST_LOOP(f);
+
+ BLI_assert(f->len == 3);
+
+ r_index[0] = BM_elem_index_get(l->v); l = l->next;
+ r_index[1] = BM_elem_index_get(l->v); l = l->next;
+ r_index[2] = BM_elem_index_get(l->v);
+}
+
+/* In order to perform operations on the original node coordinates
+ * (currently just raycast), store the node's triangles and vertices.
+ *
+ * Skips triangles that are hidden. */
+void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node)
+{
+ GHashIterator gh_iter;
+ int i, totvert, tottri;
+
+ /* Skip if original coords/triangles are already saved */
+ if (node->bm_orco)
+ return;
+
+ totvert = (BLI_ghash_size(node->bm_unique_verts) +
+ BLI_ghash_size(node->bm_other_verts));
+
+ tottri = BLI_ghash_size(node->bm_faces);
+
+ node->bm_orco = MEM_mallocN(sizeof(*node->bm_orco) * totvert, AT);
+ node->bm_ortri = MEM_mallocN(sizeof(*node->bm_ortri) * tottri, AT);
+
+ /* Copy out the vertices and assign a temporary index */
+ i = 0;
+ GHASH_ITER (gh_iter, node->bm_unique_verts) {
+ BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ copy_v3_v3(node->bm_orco[i], v->co);
+ BM_elem_index_set(v, i); /* set_dirty! */
+ i++;
+ }
+ GHASH_ITER (gh_iter, node->bm_other_verts) {
+ BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ copy_v3_v3(node->bm_orco[i], v->co);
+ BM_elem_index_set(v, i); /* set_dirty! */
+ i++;
+ }
+
+ /* Copy the triangles */
+ i = 0;
+ GHASH_ITER (gh_iter, node->bm_faces) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+
+ if (paint_is_bmesh_face_hidden(f))
+ continue;
+
+#if 0
+ BMIter bm_iter;
+ BMVert *v;
+ int j = 0;
+ BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) {
+ node->bm_ortri[i][j] = BM_elem_index_get(v);
+ j++;
+ }
+#else
+ bm_face_as_array_index_tri(f, node->bm_ortri[i]);
+#endif
+ i++;
+ }
+ node->bm_tot_ortri = i;
+}
+
+void BKE_pbvh_bmesh_after_stroke(PBVH *bvh)
+{
+ int i;
+ for (i = 0; i < bvh->totnode; i++) {
+ PBVHNode *n = &bvh->nodes[i];
+ if (n->flag & PBVH_Leaf) {
+ /* Free orco/ortri data */
+ pbvh_bmesh_node_drop_orig(n);
+
+ /* Recursively split nodes that have gotten too many
+ * elements */
+ pbvh_bmesh_node_limit_ensure(bvh, i);
+ }
+ }
+}
+
+void BKE_pbvh_bmesh_detail_size_set(PBVH *bvh, float detail_size)
+{
+ bvh->bm_max_edge_len = detail_size;
+ bvh->bm_min_edge_len = bvh->bm_max_edge_len * 0.4f;
+}
+
+void BKE_pbvh_node_mark_topology_update(PBVHNode *node)
+{
+ node->flag |= PBVH_UpdateTopology;
+}
+
+GHash *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node)
+{
+ return node->bm_unique_verts;
+}
+
+GHash *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node)
+{
+ return node->bm_other_verts;
+}
+
+/****************************** Debugging *****************************/
+
+#if 0
+void bli_ghash_duplicate_key_check(GHash *gh)
+{
+ GHashIterator gh_iter1, gh_iter2;
+
+ GHASH_ITER (gh_iter1, gh) {
+ void *key1 = BLI_ghashIterator_getKey(&gh_iter1);
+ int dup = -1;
+
+ GHASH_ITER (gh_iter2, gh) {
+ void *key2 = BLI_ghashIterator_getKey(&gh_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;
+ int n;
+
+ fprintf(stderr, "\npbvh=%p\n", bvh);
+ fprintf(stderr, "bm_face_to_node:\n");
+ GHASH_ITER (gh_iter, bvh->bm_face_to_node) {
+ fprintf(stderr, " %d -> %d\n",
+ BM_elem_index_get((BMFace *)BLI_ghashIterator_getKey(&gh_iter)),
+ GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter)));
+ }
+
+ fprintf(stderr, "bm_vert_to_node:\n");
+ GHASH_ITER (gh_iter, bvh->bm_vert_to_node) {
+ fprintf(stderr, " %d -> %d\n",
+ BM_elem_index_get((BMVert *)BLI_ghashIterator_getKey(&gh_iter)),
+ GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter)));
+ }
+
+ for (n = 0; n < bvh->totnode; n++) {
+ PBVHNode *node = &bvh->nodes[n];
+ if (!(node->flag & PBVH_Leaf))
+ continue;
+
+ fprintf(stderr, "node %d\n faces:\n", n);
+ GHASH_ITER (gh_iter, node->bm_faces)
+ fprintf(stderr, " %d\n",
+ BM_elem_index_get((BMFace *)BLI_ghashIterator_getKey(&gh_iter)));
+ fprintf(stderr, " unique verts:\n");
+ GHASH_ITER (gh_iter, node->bm_unique_verts)
+ fprintf(stderr, " %d\n",
+ BM_elem_index_get((BMVert *)BLI_ghashIterator_getKey(&gh_iter)));
+ fprintf(stderr, " other verts:\n");
+ GHASH_ITER (gh_iter, node->bm_other_verts)
+ fprintf(stderr, " %d\n",
+ BM_elem_index_get((BMVert *)BLI_ghashIterator_getKey(&gh_iter)));
+ }
+}
+
+void print_flag_factors(int flag)
+{
+ int i;
+ printf("flag=0x%x:\n", flag);
+ for (i = 0; i < 32; i++) {
+ if (flag & (1 << i)) {
+ printf(" %d (1 << %d)\n", 1 << i, i);
+ }
+ }
+}
+
+void pbvh_bmesh_verify(PBVH *bvh)
+{
+ GHashIterator gh_iter;
+ int i;
+
+ /* Check faces */
+ BLI_assert(bvh->bm->totface == BLI_ghash_size(bvh->bm_face_to_node));
+ GHASH_ITER (gh_iter, bvh->bm_face_to_node) {
+ 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];
+
+ /* Check that the face's node is a leaf */
+ BLI_assert(n->flag & PBVH_Leaf);
+
+ /* Check that the face's node knows it owns the face */
+ BLI_assert(BLI_ghash_haskey(n->bm_faces, f));
+
+ /* Check the face's vertices... */
+ BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) {
+ PBVHNode *nv;
+
+ /* Check that the vertex is in the node */
+ BLI_assert(BLI_ghash_haskey(n->bm_unique_verts, v) ^
+ BLI_ghash_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);
+
+ /* Check that the vertex's node knows it owns the vert */
+ BLI_assert(BLI_ghash_haskey(nv->bm_unique_verts, v));
+
+ /* Check that the vertex isn't duplicated as an 'other' vert */
+ BLI_assert(!BLI_ghash_haskey(nv->bm_other_verts, v));
+ }
+ }
+
+ /* Check verts */
+ BLI_assert(bvh->bm->totvert == BLI_ghash_size(bvh->bm_vert_to_node));
+ GHASH_ITER (gh_iter, bvh->bm_vert_to_node) {
+ 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];
+ int found;
+
+ /* Check that the vert's node is a leaf */
+ BLI_assert(n->flag & PBVH_Leaf);
+
+ /* Check that the vert's node knows it owns the vert */
+ BLI_assert(BLI_ghash_haskey(n->bm_unique_verts, v));
+
+ /* Check that the vertex isn't duplicated as an 'other' vert */
+ BLI_assert(!BLI_ghash_haskey(n->bm_other_verts, v));
+
+ /* 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) {
+ found = TRUE;
+ break;
+ }
+ }
+ BLI_assert(found);
+ }
+
+ /* Check that node elements are recorded in the top level */
+ 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_ghash_duplicate_key_check(n->bm_faces);
+ bli_ghash_duplicate_key_check(n->bm_unique_verts);
+ bli_ghash_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));
+ }
+
+ GHASH_ITER (gh_iter, n->bm_unique_verts) {
+ BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ void *nip = BLI_ghash_lookup(bvh->bm_vert_to_node, v);
+ BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v));
+ BLI_assert(!BLI_ghash_haskey(n->bm_other_verts, v));
+ BLI_assert(GET_INT_FROM_POINTER(nip) == (n - bvh->nodes));
+ }
+
+ GHASH_ITER (gh_iter, n->bm_other_verts) {
+ BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v));
+ BLI_assert(BM_vert_face_count(v) > 0);
+ }
+ }
+ }
+}
+
+#endif
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
new file mode 100644
index 00000000000..b3f7bf6e3d1
--- /dev/null
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -0,0 +1,186 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 __PBVH_INTERN_H__
+#define __PBVH_INTERN_H__
+
+/* Axis-aligned bounding box */
+typedef struct {
+ float bmin[3], bmax[3];
+} BB;
+
+/* Axis-aligned bounding box with centroid */
+typedef struct {
+ float bmin[3], bmax[3], bcentroid[3];
+} BBC;
+
+/* Note: this structure is getting large, might want to split it into
+ * union'd structs */
+struct PBVHNode {
+ /* Opaque handle for drawing code */
+ struct GPU_Buffers *draw_buffers;
+
+ /* Voxel bounds */
+ BB vb;
+ BB orig_vb;
+
+ /* For internal nodes, the offset of the children in the PBVH
+ * 'nodes' array. */
+ int children_offset;
+
+ /* Pointer into the PBVH prim_indices array and the number of
+ * primitives used by this leaf node.
+ *
+ * Used for leaf nodes in both mesh- and multires-based PBVHs.
+ */
+ int *prim_indices;
+ unsigned int totprim;
+
+ /* Array of indices into the mesh's MVert array. Contains the
+ * indices of all vertices used by faces that are within this
+ * node's bounding box.
+ *
+ * Note that a vertex might be used by a multiple faces, and
+ * these faces might be in different leaf nodes. Such a vertex
+ * will appear in the vert_indices array of each of those leaf
+ * nodes.
+ *
+ * In order to support cases where you want access to multiple
+ * nodes' vertices without duplication, the vert_indices array
+ * is ordered such that the first part of the array, up to
+ * index 'uniq_verts', contains "unique" vertex indices. These
+ * vertices might not be truly unique to this node, but if
+ * they appear in another node's vert_indices array, they will
+ * be above that node's 'uniq_verts' value.
+ *
+ * Used for leaf nodes in a mesh-based PBVH (not multires.)
+ */
+ int *vert_indices;
+ unsigned int uniq_verts, face_verts;
+
+ /* An array mapping face corners into the vert_indices
+ * array. The array is sized to match 'totprim', and each of
+ * the face's corners gets an index into the vert_indices
+ * array, in the same order as the corners in the original
+ * MFace. The fourth value should not be used if the original
+ * face is a triangle.
+ *
+ * Used for leaf nodes in a mesh-based PBVH (not multires.)
+ */
+ 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. */
+ PBVHNodeFlags flag : 16;
+
+ /* Used for raycasting: how close bb is to the ray point. */
+ float tmin;
+
+ /* Scalar displacements for sculpt mode's layer brush. */
+ float *layer_disp;
+
+ int proxy_count;
+ PBVHProxyNode *proxies;
+
+ /* Dyntopo */
+ GHash *bm_faces;
+ GHash *bm_unique_verts;
+ GHash *bm_other_verts;
+ float (*bm_orco)[3];
+ int (*bm_ortri)[3];
+ int bm_tot_ortri;
+};
+
+typedef enum {
+ PBVH_DYNTOPO_SMOOTH_SHADING = 1
+} PBVHFlags;
+
+typedef struct PBVHBMeshLog PBVHBMeshLog;
+
+struct PBVH {
+ PBVHType type;
+ PBVHFlags flags;
+
+ PBVHNode *nodes;
+ int node_mem_count, totnode;
+
+ int *prim_indices;
+ int totprim;
+ int totvert;
+
+ int leaf_limit;
+
+ /* Mesh data */
+ MVert *verts;
+ MFace *faces;
+ CustomData *vdata;
+
+ /* Grid Data */
+ CCGKey gridkey;
+ CCGElem **grids;
+ DMGridAdjacency *gridadj;
+ void **gridfaces;
+ const DMFlagMat *grid_flag_mats;
+ int totgrid;
+ BLI_bitmap *grid_hidden;
+
+ /* Only used during BVH build and update,
+ * don't need to remain valid after */
+ BLI_bitmap vert_bitmap;
+
+#ifdef PERFCNTRS
+ int perf_modified;
+#endif
+
+ /* flag are verts/faces deformed */
+ int deformed;
+
+ int show_diffuse_color;
+
+ /* Dynamic topology */
+ BMesh *bm;
+ GHash *bm_face_to_node;
+ GHash *bm_vert_to_node;
+ float bm_max_edge_len;
+ float bm_min_edge_len;
+
+ struct BMLog *bm_log;
+};
+
+/* pbvh.c */
+void BB_reset(BB *bb);
+void BB_expand(BB *bb, const float co[3]);
+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);
+int 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);
+void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag);
+
+/* pbvh_bmesh.c */
+int pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3],
+ const float ray_normal[3], float *dist,
+ int use_original);
+
+void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode);
+
+#endif
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 965a1e2b4a6..8034c4d1de9 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -43,6 +43,7 @@
#include "DNA_object_types.h"
#include "DNA_object_force.h"
#include "DNA_particle_types.h"
+#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_smoke_types.h"
@@ -51,6 +52,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "PIL_time.h"
#include "WM_api.h"
@@ -72,6 +75,10 @@
#include "BIK_api.h"
+#ifdef WITH_BULLET
+# include "RBI_api.h"
+#endif
+
/* both in intern */
#ifdef WITH_SMOKE
#include "smoke_API.h"
@@ -272,7 +279,7 @@ static void ptcache_particle_read(int index, void *psys_v, void **data, float cf
ParticleSystem *psys= psys_v;
ParticleData *pa;
BoidParticle *boid;
- float timestep = 0.04f*psys->part->timetweak;
+ float timestep = 0.04f * psys->part->timetweak;
if (index >= psys->totpart)
return;
@@ -308,8 +315,9 @@ static void ptcache_particle_read(int index, void *psys_v, void **data, float cf
pa->lifetime = times[2];
}
- if (boid)
+ if (boid) {
PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data);
+ }
/* determine velocity from previous location */
if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
@@ -333,7 +341,7 @@ static void ptcache_particle_interpolate(int index, void *psys_v, void **data, f
ParticleSystem *psys= psys_v;
ParticleData *pa;
ParticleKey keys[4];
- float dfra, timestep = 0.04f*psys->part->timetweak;
+ float dfra, timestep = 0.04f * psys->part->timetweak;
if (index >= psys->totpart)
return;
@@ -559,7 +567,7 @@ static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v)
float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
unsigned char *obstacles;
unsigned int in_len = sizeof(float)*(unsigned int)res;
- unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer");
+ unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len) * 4, "pointcache_lzo_buffer");
//int mode = res >= 1000000 ? 2 : 1;
int mode=1; // light
if (sds->cache_comp == SM_CACHE_HEAVY) mode=2; // heavy
@@ -649,6 +657,85 @@ static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v)
return ret;
}
+
+/* read old smoke cache from 2.64 */
+static int ptcache_smoke_read_old(PTCacheFile *pf, void *smoke_v)
+{
+ SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
+ SmokeDomainSettings *sds = smd->domain;
+
+ if (sds->fluid) {
+ size_t res = sds->res[0]*sds->res[1]*sds->res[2];
+ float dt, dx, *dens, *heat, *heatold, *vx, *vy, *vz;
+ unsigned char *obstacles;
+ unsigned int out_len = (unsigned int)res * sizeof(float);
+ float *tmp_array = MEM_callocN(out_len, "Smoke old cache tmp");
+
+ int fluid_fields = smoke_get_data_flags(sds);
+
+ /* Part part of the new cache header */
+ sds->active_color[0] = 0.7f;
+ sds->active_color[1] = 0.7f;
+ sds->active_color[2] = 0.7f;
+
+ smoke_export(sds->fluid, &dt, &dx, &dens, NULL, NULL, NULL, &heat, &heatold, &vx, &vy, &vz, NULL, NULL, NULL, &obstacles);
+
+ ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
+
+ if (fluid_fields & SM_ACTIVE_HEAT)
+ {
+ ptcache_file_compressed_read(pf, (unsigned char*)heat, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)heatold, out_len);
+ }
+ else
+ {
+ ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
+ }
+ ptcache_file_compressed_read(pf, (unsigned char*)vx, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)vy, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)vz, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)obstacles, (unsigned int)res);
+ ptcache_file_read(pf, &dt, 1, sizeof(float));
+ ptcache_file_read(pf, &dx, 1, sizeof(float));
+
+ MEM_freeN(tmp_array);
+
+ if (pf->data_types & (1<<BPHYS_DATA_SMOKE_HIGH) && sds->wt) {
+ int res = sds->res[0]*sds->res[1]*sds->res[2];
+ int res_big, res_big_array[3];
+ float *dens, *tcu, *tcv, *tcw;
+ unsigned int out_len = sizeof(float)*(unsigned int)res;
+ unsigned int out_len_big;
+ unsigned char *tmp_array_big;
+
+ smoke_turbulence_get_res(sds->wt, res_big_array);
+ res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
+ out_len_big = sizeof(float) * (unsigned int)res_big;
+
+ tmp_array_big = MEM_callocN(out_len_big, "Smoke old cache tmp");
+
+ smoke_turbulence_export(sds->wt, &dens, NULL, NULL, NULL, NULL, NULL, NULL, &tcu, &tcv, &tcw);
+
+ ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len_big);
+ ptcache_file_compressed_read(pf, (unsigned char*)tmp_array_big, out_len_big);
+
+ ptcache_file_compressed_read(pf, (unsigned char*)tcu, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)tcv, out_len);
+ ptcache_file_compressed_read(pf, (unsigned char*)tcw, out_len);
+
+ MEM_freeN(tmp_array_big);
+ }
+ }
+
+ return 1;
+}
+
static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
{
SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
@@ -663,7 +750,13 @@ 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)) return 0;
+ if (strncmp(version, SMOKE_CACHE_VERSION, 4))
+ {
+ /* reset file pointer */
+ fseek(pf->fp, -4, SEEK_CUR);
+ return ptcache_smoke_read_old(pf, smoke_v);
+ }
+
/* fluid info */
ptcache_file_read(pf, &cache_fields, 1, sizeof(int));
ptcache_file_read(pf, &active_fields, 1, sizeof(int));
@@ -792,7 +885,7 @@ static int ptcache_dynamicpaint_write(PTCacheFile *pf, void *dp_v)
int cache_compress = 1;
/* version header */
- ptcache_file_write(pf, DPAINT_CACHE_VERSION, 1, sizeof(char)*4);
+ ptcache_file_write(pf, DPAINT_CACHE_VERSION, 1, sizeof(char) * 4);
if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) {
int total_points=surface->data->total_points;
@@ -831,8 +924,11 @@ static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v)
char version[4];
/* version header */
- ptcache_file_read(pf, version, 1, sizeof(char)*4);
- if (strncmp(version, DPAINT_CACHE_VERSION, 4)) {printf("Dynamic Paint: Invalid cache version: %s!\n", version); return 0;}
+ ptcache_file_read(pf, version, 1, sizeof(char) * 4);
+ if (strncmp(version, DPAINT_CACHE_VERSION, 4)) {
+ printf("Dynamic Paint: Invalid cache version: %s!\n", version);
+ return 0;
+ }
if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) {
unsigned int data_len;
@@ -866,6 +962,97 @@ static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v)
return 1;
}
+/* Rigid Body functions */
+static int ptcache_rigidbody_write(int index, void *rb_v, void **data, int UNUSED(cfra))
+{
+ RigidBodyWorld *rbw = rb_v;
+ Object *ob = NULL;
+
+ if (rbw->objects)
+ ob = rbw->objects[index];
+
+ if (ob && ob->rigidbody_object) {
+ RigidBodyOb *rbo = ob->rigidbody_object;
+
+ if (rbo->type == RBO_TYPE_ACTIVE) {
+#ifdef WITH_BULLET
+ RB_body_get_position(rbo->physics_object, rbo->pos);
+ RB_body_get_orientation(rbo->physics_object, rbo->orn);
+#endif
+ PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, rbo->pos);
+ PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, rbo->orn);
+ }
+ }
+
+ return 1;
+}
+static void ptcache_rigidbody_read(int index, void *rb_v, void **data, float UNUSED(cfra), float *old_data)
+{
+ RigidBodyWorld *rbw = rb_v;
+ Object *ob = NULL;
+
+ if (rbw->objects)
+ ob = rbw->objects[index];
+
+ if (ob && ob->rigidbody_object) {
+ RigidBodyOb *rbo = ob->rigidbody_object;
+
+ if (rbo->type == RBO_TYPE_ACTIVE) {
+
+ if (old_data) {
+ memcpy(rbo->pos, data, 3 * sizeof(float));
+ memcpy(rbo->orn, data + 3, 4 * sizeof(float));
+ }
+ else {
+ PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, rbo->pos);
+ PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, 0, rbo->orn);
+ }
+ }
+ }
+}
+static void ptcache_rigidbody_interpolate(int index, void *rb_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
+{
+ RigidBodyWorld *rbw = rb_v;
+ Object *ob = NULL;
+ ParticleKey keys[4];
+ float dfra;
+
+ if (rbw->objects)
+ ob = rbw->objects[index];
+
+ if (ob && ob->rigidbody_object) {
+ RigidBodyOb *rbo = ob->rigidbody_object;
+
+ if (rbo->type == RBO_TYPE_ACTIVE) {
+
+ copy_v3_v3(keys[1].co, rbo->pos);
+ copy_v3_v3(keys[1].rot, rbo->orn);
+
+ if (old_data) {
+ memcpy(keys[2].co, data, 3 * sizeof(float));
+ memcpy(keys[2].rot, data + 3, 4 * sizeof(float));
+ }
+ else {
+ 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);
+
+ copy_v3_v3(rbo->pos, keys->co);
+ copy_v3_v3(rbo->orn, keys->rot);
+ }
+ }
+}
+static int ptcache_rigidbody_totpoint(void *rb_v, int UNUSED(cfra))
+{
+ RigidBodyWorld *rbw = rb_v;
+
+ return rbw->numbodies;
+}
+
/* Creating ID's */
void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
{
@@ -1071,6 +1258,42 @@ void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSu
pid->max_step = 1;
}
+void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *rbw)
+{
+
+ memset(pid, 0, sizeof(PTCacheID));
+
+ pid->ob= ob;
+ pid->calldata= rbw;
+ pid->type= PTCACHE_TYPE_RIGIDBODY;
+ pid->cache= rbw->pointcache;
+ pid->cache_ptr= &rbw->pointcache;
+ pid->ptcaches= &rbw->ptcaches;
+ pid->totpoint= pid->totwrite= ptcache_rigidbody_totpoint;
+
+ pid->write_point = ptcache_rigidbody_write;
+ pid->read_point = ptcache_rigidbody_read;
+ pid->interpolate_point = ptcache_rigidbody_interpolate;
+
+ pid->write_stream = NULL;
+ pid->read_stream = NULL;
+
+ pid->write_extra_data = NULL;
+ pid->read_extra_data = NULL;
+ pid->interpolate_extra_data = NULL;
+
+ pid->write_header = ptcache_basic_header_write;
+ pid->read_header = ptcache_basic_header_read;
+
+ pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_ROTATION);
+ pid->info_types= 0;
+
+ pid->stack_index = pid->cache->index;
+
+ pid->default_step = 1;
+ pid->max_step = 1;
+}
+
void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis)
{
PTCacheID *pid;
@@ -1132,11 +1355,17 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup
}
}
}
+
+ if (scene && ob->rigidbody_object && scene->rigidbody_world) {
+ pid = MEM_callocN(sizeof(PTCacheID), "PTCacheID");
+ BKE_ptcache_id_from_rigidbody(pid, ob, scene->rigidbody_world);
+ BLI_addtail(lb, pid);
+ }
if (scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) {
ListBase *lb_dupli_ob;
- /* don't update the dupli groups, we only wan't their pid's */
+ /* don't update the dupli groups, we only want their pid's */
if ((lb_dupli_ob = object_duplilist_ex(scene, ob, FALSE, FALSE))) {
DupliObject *dob;
for (dob= lb_dupli_ob->first; dob; dob= dob->next) {
@@ -1163,7 +1392,7 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup
*/
#define MAX_PTCACHE_PATH FILE_MAX
-#define MAX_PTCACHE_FILE ((FILE_MAX)*2)
+#define MAX_PTCACHE_FILE (FILE_MAX * 2)
static int ptcache_path(PTCacheID *pid, char *filename)
{
@@ -1218,7 +1447,7 @@ static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_p
newname += len;
}
if (pid->cache->name[0] == '\0' && (pid->cache->flag & PTCACHE_EXTERNAL)==0) {
- idname = (pid->ob->id.name+2);
+ idname = (pid->ob->id.name + 2);
/* convert chars to hex so they are always a valid filename */
while ('\0' != *idname) {
BLI_snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++));
@@ -1258,7 +1487,7 @@ static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra)
{
PTCacheFile *pf;
FILE *fp = NULL;
- char filename[(FILE_MAX)*2];
+ char filename[FILE_MAX * 2];
#ifndef DURIAN_POINTCACHE_LIB_OK
/* don't allow writing for linked objects */
@@ -1311,7 +1540,7 @@ static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result,
size_t out_len = len;
#endif
unsigned char *in;
- unsigned char *props = MEM_callocN(16*sizeof(char), "tmp");
+ unsigned char *props = MEM_callocN(16 * sizeof(char), "tmp");
ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char));
if (compressed) {
@@ -1354,7 +1583,7 @@ static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, uns
int r = 0;
unsigned char compressed = 0;
size_t out_len= 0;
- unsigned char *props = MEM_callocN(16*sizeof(char), "tmp");
+ unsigned char *props = MEM_callocN(16 * sizeof(char), "tmp");
size_t sizeOfIt = 5;
(void)mode; /* unused when building w/o compression */
@@ -1375,7 +1604,7 @@ static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, uns
if (mode == 2) {
r = LzmaCompress(out, &out_len, in, in_len, //assume sizeof(char)==1....
- props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2);
+ props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2);
if (!(r == SZ_OK) || (out_len >= in_len))
compressed = 0;
@@ -1540,7 +1769,7 @@ void BKE_ptcache_mem_pointers_incr(PTCacheMem *pm)
for (i=0; i<BPHYS_TOT_DATA; i++) {
if (pm->cur[i])
- pm->cur[i] = (char*)pm->cur[i] + ptcache_data_size[i];
+ pm->cur[i] = (char *)pm->cur[i] + ptcache_data_size[i];
}
}
int BKE_ptcache_mem_pointers_seek(int point_index, PTCacheMem *pm)
@@ -1558,7 +1787,7 @@ int BKE_ptcache_mem_pointers_seek(int point_index, PTCacheMem *pm)
}
for (i=0; i<BPHYS_TOT_DATA; i++)
- pm->cur[i] = data_types & (1<<i) ? (char*)pm->data[i] + index * ptcache_data_size[i] : NULL;
+ pm->cur[i] = data_types & (1<<i) ? (char *)pm->data[i] + index * ptcache_data_size[i] : NULL;
return 1;
}
@@ -1787,7 +2016,7 @@ static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm)
for (i=0; i<BPHYS_TOT_DATA; i++) {
if (pm->data[i]) {
unsigned int in_len = pm->totpoint*ptcache_data_size[i];
- unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer");
+ unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len) * 4, "pointcache_lzo_buffer");
ptcache_file_compressed_write(pf, (unsigned char *)(pm->data[i]), in_len, out, pid->cache->compression);
MEM_freeN(out);
}
@@ -1820,7 +2049,7 @@ static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm)
if (pid->cache->compression) {
unsigned int in_len = extra->totdata * ptcache_extra_datasize[extra->type];
- unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer");
+ unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len) * 4, "pointcache_lzo_buffer");
ptcache_file_compressed_write(pf, (unsigned char *)(extra->data), in_len, out, pid->cache->compression);
MEM_freeN(out);
}
@@ -2291,7 +2520,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
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);
- BLI_delete(path_full, 0, 0);
+ BLI_delete(path_full, false, false);
}
else {
/* read the number of the file */
@@ -2307,7 +2536,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
{
BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
- BLI_delete(path_full, 0, 0);
+ BLI_delete(path_full, false, false);
if (pid->cache->cached_frames && frame >=sta && frame <= end)
pid->cache->cached_frames[frame-sta] = 0;
}
@@ -2361,7 +2590,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
if (pid->cache->flag & PTCACHE_DISK_CACHE) {
if (BKE_ptcache_id_exist(pid, cfra)) {
ptcache_filename(pid, filename, cfra, 1, 1); /* no path */
- BLI_delete(filename, 0, 0);
+ BLI_delete(filename, false, false);
}
}
else {
@@ -2535,7 +2764,7 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
after= 0;
if (mode == PTCACHE_RESET_DEPSGRAPH) {
- if (!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) {
+ if (!(cache->flag & PTCACHE_BAKED)) {
after= 1;
}
@@ -2543,12 +2772,7 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
cache->flag |= PTCACHE_OUTDATED;
}
else if (mode == PTCACHE_RESET_BAKED) {
- if (!BKE_ptcache_get_continue_physics()) {
- reset= 1;
- clear= 1;
- }
- else
- cache->flag |= PTCACHE_OUTDATED;
+ cache->flag |= PTCACHE_OUTDATED;
}
else if (mode == PTCACHE_RESET_OUTDATED) {
reset = 1;
@@ -2645,6 +2869,14 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
}
}
+ if (scene->rigidbody_world && (ob->rigidbody_object || ob->rigidbody_constraint)) {
+ if (ob->rigidbody_object)
+ ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_RESHAPE;
+ BKE_ptcache_id_from_rigidbody(&pid, ob, scene->rigidbody_world);
+ /* only flag as outdated, resetting should happen on start frame */
+ pid.cache->flag |= PTCACHE_OUTDATED;
+ }
+
if (ob->type == OB_ARMATURE)
BIK_clear_cache(ob->pose);
@@ -2676,7 +2908,7 @@ void BKE_ptcache_remove(void)
}
else if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/
BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
- BLI_delete(path_full, 0, 0);
+ BLI_delete(path_full, false, false);
}
else {
rmdir = 0; /* unknown file, don't remove the dir */
@@ -2690,34 +2922,10 @@ void BKE_ptcache_remove(void)
}
if (rmdir) {
- BLI_delete(path, 1, 0);
+ BLI_delete(path, true, false);
}
}
-/* Continuous Interaction */
-
-static int CONTINUE_PHYSICS = 0;
-
-void BKE_ptcache_set_continue_physics(Main *bmain, Scene *scene, int enable)
-{
- Object *ob;
-
- if (CONTINUE_PHYSICS != enable) {
- CONTINUE_PHYSICS = enable;
-
- if (CONTINUE_PHYSICS == 0) {
- for (ob=bmain->object.first; ob; ob=ob->id.next)
- if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED))
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- }
- }
-}
-
-int BKE_ptcache_get_continue_physics(void)
-{
- return CONTINUE_PHYSICS;
-}
-
/* Point Cache handling */
PointCache *BKE_ptcache_add(ListBase *ptcaches)
@@ -2782,7 +2990,8 @@ static PointCache *ptcache_copy(PointCache *cache, int copy_data)
ncache->mem_cache.last = NULL;
ncache->cached_frames = NULL;
- ncache->flag= 0;
+ /* flag is a mix of user settings and simulator/baking state */
+ ncache->flag= ncache->flag & (PTCACHE_DISK_CACHE|PTCACHE_EXTERNAL|PTCACHE_IGNORE_LIBPATH);
ncache->simframe= 0;
}
else {
@@ -2918,7 +3127,7 @@ static void *ptcache_bake_thread(void *ptr)
}
/* if bake is not given run simulations to current frame */
-void BKE_ptcache_bake(PTCacheBaker* baker)
+void BKE_ptcache_bake(PTCacheBaker *baker)
{
Main *bmain = baker->main;
Scene *scene = baker->scene;
@@ -3386,11 +3595,11 @@ void BKE_ptcache_update_info(PTCacheID *pid)
/* smoke doesn't use frame 0 as info frame so can't check based on totpoint */
if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN && totframes)
- BLI_snprintf(cache->info, sizeof(cache->info), "%i frames found!", totframes);
+ BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%i frames found!"), totframes);
else if (totframes && cache->totpoint)
- BLI_snprintf(cache->info, sizeof(cache->info), "%i points found!", cache->totpoint);
+ BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%i points found!"), cache->totpoint);
else
- BLI_snprintf(cache->info, sizeof(cache->info), "No valid data to read!");
+ BLI_strncpy(cache->info, IFACE_("No valid data to read!"), sizeof(cache->info));
return;
}
@@ -3399,9 +3608,9 @@ void BKE_ptcache_update_info(PTCacheID *pid)
int totpoint = pid->totpoint(pid->calldata, 0);
if (cache->totpoint > totpoint)
- BLI_snprintf(mem_info, sizeof(mem_info), "%i cells + High Resolution cached", totpoint);
+ BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i cells + High Resolution cached"), totpoint);
else
- BLI_snprintf(mem_info, sizeof(mem_info), "%i cells cached", totpoint);
+ BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i cells cached"), totpoint);
}
else {
int cfra = cache->startframe;
@@ -3411,7 +3620,7 @@ void BKE_ptcache_update_info(PTCacheID *pid)
totframes++;
}
- BLI_snprintf(mem_info, sizeof(mem_info), "%i frames on disk", totframes);
+ BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i frames on disk"), totframes);
}
}
else {
@@ -3435,17 +3644,18 @@ void BKE_ptcache_update_info(PTCacheID *pid)
mb = (bytes > 1024.0f * 1024.0f);
- BLI_snprintf(mem_info, sizeof(mem_info), "%i frames in memory (%.1f %s)",
+ BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i frames in memory (%.1f %s)"),
totframes,
bytes / (mb ? 1024.0f * 1024.0f : 1024.0f),
- mb ? "Mb" : "kb");
+ mb ? IFACE_("Mb") : IFACE_("kb"));
}
if (cache->flag & PTCACHE_OUTDATED) {
- BLI_snprintf(cache->info, sizeof(cache->info), "%s, cache is outdated!", mem_info);
+ BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%s, cache is outdated!"), mem_info);
}
else if (cache->flag & PTCACHE_FRAMES_SKIPPED) {
- BLI_snprintf(cache->info, sizeof(cache->info), "%s, not exact since frame %i.", mem_info, cache->last_exact);
+ BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%s, not exact since frame %i"),
+ mem_info, cache->last_exact);
}
else {
BLI_snprintf(cache->info, sizeof(cache->info), "%s.", mem_info);
@@ -3467,4 +3677,3 @@ void BKE_ptcache_invalidate(PointCache *cache)
cache->last_exact = MIN2(cache->startframe, 0);
}
}
-
diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c
index 8da4f11fed3..ec23a7db8a1 100644
--- a/source/blender/blenkernel/intern/property.c
+++ b/source/blender/blenkernel/intern/property.c
@@ -74,8 +74,10 @@ bProperty *BKE_bproperty_copy(bProperty *prop)
if (prop->poin && prop->poin != &prop->data) {
propn->poin = MEM_dupallocN(prop->poin);
}
- else propn->poin = &propn->data;
-
+ else {
+ propn->poin = &propn->data;
+ }
+
return propn;
}
@@ -287,7 +289,7 @@ void BKE_bproperty_add(bProperty *prop, const char *str)
}
/* reads value of property, sets it in chars in str */
-void BKE_bproperty_set_valstr(bProperty *prop, char *str)
+void BKE_bproperty_set_valstr(bProperty *prop, char str[MAX_PROPSTRING])
{
// extern int Gdfra; /* sector.c */
diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c
index d925d736358..1fd7dc14c23 100644
--- a/source/blender/blenkernel/intern/report.c
+++ b/source/blender/blenkernel/intern/report.c
@@ -27,6 +27,10 @@
* \ingroup bke
*/
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
#include "MEM_guardedalloc.h"
@@ -39,10 +43,6 @@
#include "BKE_report.h"
#include "BKE_global.h" /* G.background only */
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
static const char *report_type_str(int type)
{
switch (type) {
@@ -52,6 +52,8 @@ static const char *report_type_str(int type)
return TIP_("Info");
case RPT_OPERATOR:
return TIP_("Operator");
+ case RPT_PROPERTY:
+ return TIP_("Property");
case RPT_WARNING:
return TIP_("Warning");
case RPT_ERROR:
@@ -300,3 +302,36 @@ int BKE_reports_contain(ReportList *reports, ReportType level)
return FALSE;
}
+bool BKE_report_write_file_fp(FILE *fp, ReportList *reports, const char *header)
+{
+ Report *report;
+
+ if (header) {
+ fputs(header, fp);
+ }
+
+ for (report = reports->list.first; report; report = report->next) {
+ fprintf((FILE *)fp, "%s # %s\n", report->message, report->typestr);
+ }
+
+ return true;
+}
+
+bool BKE_report_write_file(const char *filepath, ReportList *reports, const char *header)
+{
+ FILE *fp;
+
+ errno = 0;
+ fp = BLI_fopen(filepath, "wb");
+ if (fp == NULL) {
+ fprintf(stderr, "Unable to save '%s': %s\n",
+ filepath, errno ? strerror(errno) : "Unknown error opening file");
+ return false;
+ }
+
+ BKE_report_write_file_fp(fp, reports, header);
+
+ fclose(fp);
+
+ return true;
+}
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
new file mode 100644
index 00000000000..bccc6f9a93b
--- /dev/null
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -0,0 +1,1348 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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): Joshua Leung, Sergej Reich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file rigidbody.c
+ * \ingroup blenkernel
+ * \brief Blender-side interface and methods for dealing with Rigid Body simulations
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+#include <float.h>
+#include <math.h>
+#include <limits.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+
+#ifdef WITH_BULLET
+# include "RBI_api.h"
+#endif
+
+#include "DNA_anim_types.h"
+#include "DNA_group_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_rigidbody_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_animsys.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_effect.h"
+#include "BKE_group.h"
+#include "BKE_object.h"
+#include "BKE_mesh.h"
+#include "BKE_pointcache.h"
+#include "BKE_rigidbody.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+
+#ifdef WITH_BULLET
+
+/* ************************************** */
+/* Memory Management */
+
+/* Freeing Methods --------------------- */
+
+/* Free rigidbody world */
+void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
+{
+ /* sanity check */
+ if (!rbw)
+ return;
+
+ if (rbw->physics_world) {
+ /* free physics references, we assume that all physics objects in will have been added to the world */
+ GroupObject *go;
+ if (rbw->constraints) {
+ for (go = rbw->constraints->gobject.first; go; go = go->next) {
+ if (go->ob && go->ob->rigidbody_constraint) {
+ RigidBodyCon *rbc = go->ob->rigidbody_constraint;
+
+ if (rbc->physics_constraint)
+ RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
+ }
+ }
+ }
+ if (rbw->group) {
+ for (go = rbw->group->gobject.first; go; go = go->next) {
+ if (go->ob && go->ob->rigidbody_object) {
+ RigidBodyOb *rbo = go->ob->rigidbody_object;
+
+ if (rbo->physics_object)
+ RB_dworld_remove_body(rbw->physics_world, rbo->physics_object);
+ }
+ }
+ }
+ /* free dynamics world */
+ RB_dworld_delete(rbw->physics_world);
+ }
+ if (rbw->objects)
+ free(rbw->objects);
+
+ /* free cache */
+ BKE_ptcache_free_list(&(rbw->ptcaches));
+ rbw->pointcache = NULL;
+
+ /* free effector weights */
+ if (rbw->effector_weights)
+ MEM_freeN(rbw->effector_weights);
+
+ /* free rigidbody world itself */
+ MEM_freeN(rbw);
+}
+
+/* Free RigidBody settings and sim instances */
+void BKE_rigidbody_free_object(Object *ob)
+{
+ RigidBodyOb *rbo = (ob) ? ob->rigidbody_object : NULL;
+
+ /* sanity check */
+ if (rbo == NULL)
+ return;
+
+ /* free physics references */
+ if (rbo->physics_object) {
+ RB_body_delete(rbo->physics_object);
+ rbo->physics_object = NULL;
+ }
+
+ if (rbo->physics_shape) {
+ RB_shape_delete(rbo->physics_shape);
+ rbo->physics_shape = NULL;
+ }
+
+ /* free data itself */
+ MEM_freeN(rbo);
+ ob->rigidbody_object = NULL;
+}
+
+/* Free RigidBody constraint and sim instance */
+void BKE_rigidbody_free_constraint(Object *ob)
+{
+ RigidBodyCon *rbc = (ob) ? ob->rigidbody_constraint : NULL;
+
+ /* sanity check */
+ if (rbc == NULL)
+ return;
+
+ /* free physics reference */
+ if (rbc->physics_constraint) {
+ RB_constraint_delete(rbc->physics_constraint);
+ rbc->physics_constraint = NULL;
+ }
+
+ /* free data itself */
+ MEM_freeN(rbc);
+ ob->rigidbody_constraint = NULL;
+}
+
+/* Copying Methods --------------------- */
+
+/* These just copy the data, clearing out references to physics objects.
+ * Anything that uses them MUST verify that the copied object will
+ * be added to relevant groups later...
+ */
+
+RigidBodyOb *BKE_rigidbody_copy_object(Object *ob)
+{
+ RigidBodyOb *rboN = NULL;
+
+ if (ob->rigidbody_object) {
+ /* just duplicate the whole struct first (to catch all the settings) */
+ rboN = MEM_dupallocN(ob->rigidbody_object);
+
+ /* tag object as needing to be verified */
+ rboN->flag |= RBO_FLAG_NEEDS_VALIDATE;
+
+ /* clear out all the fields which need to be revalidated later */
+ rboN->physics_object = NULL;
+ rboN->physics_shape = NULL;
+ }
+
+ /* return new copy of settings */
+ return rboN;
+}
+
+RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob)
+{
+ RigidBodyCon *rbcN = NULL;
+
+ if (ob->rigidbody_constraint) {
+ /* just duplicate the whole struct first (to catch all the settings) */
+ rbcN = MEM_dupallocN(ob->rigidbody_constraint);
+
+ /* tag object as needing to be verified */
+ rbcN->flag |= RBC_FLAG_NEEDS_VALIDATE;
+
+ /* clear out all the fields which need to be revalidated later */
+ rbcN->physics_constraint = NULL;
+ }
+
+ /* return new copy of settings */
+ return rbcN;
+}
+
+/* preserve relationships between constraints and rigid bodies after duplication */
+void BKE_rigidbody_relink_constraint(RigidBodyCon *rbc)
+{
+ ID_NEW(rbc->ob1);
+ ID_NEW(rbc->ob2);
+}
+
+/* ************************************** */
+/* Setup Utilities - Validate Sim Instances */
+
+/* create collision shape of mesh - convex hull */
+static rbCollisionShape *rigidbody_get_shape_convexhull_from_mesh(Object *ob, float margin, bool *can_embed)
+{
+ rbCollisionShape *shape = NULL;
+ Mesh *me = NULL;
+
+ if (ob->type == OB_MESH && ob->data) {
+ me = ob->data;
+ }
+ else {
+ printf("ERROR: cannot make Convex Hull collision shape for non-Mesh object\n");
+ }
+
+ if (me && me->totvert) {
+ shape = RB_shape_new_convex_hull((float *)me->mvert, sizeof(MVert), me->totvert, margin, can_embed);
+ }
+ else {
+ printf("ERROR: no vertices to define Convex Hull collision shape with\n");
+ }
+
+ return shape;
+}
+
+/* create collision shape of mesh - triangulated mesh
+ * returns NULL if creation fails.
+ */
+static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
+{
+ rbCollisionShape *shape = NULL;
+
+ if (ob->type == OB_MESH) {
+ DerivedMesh *dm = CDDM_from_mesh(ob->data, ob);
+
+ MVert *mvert;
+ MFace *mface;
+ int totvert;
+ int totface;
+
+ /* ensure mesh validity, then grab data */
+ DM_ensure_tessface(dm);
+
+ mvert = (dm) ? dm->getVertArray(dm) : NULL;
+ totvert = (dm) ? dm->getNumVerts(dm) : 0;
+ mface = (dm) ? dm->getTessFaceArray(dm) : NULL;
+ totface = (dm) ? dm->getNumTessFaces(dm) : 0;
+
+ /* sanity checking - potential case when no data will be present */
+ if ((totvert == 0) || (totface == 0)) {
+ printf("WARNING: no geometry data converted for Mesh Collision Shape (ob = %s)\n", ob->id.name + 2);
+ }
+ else {
+ rbMeshData *mdata;
+ int i;
+
+ /* init mesh data for collision shape */
+ mdata = RB_trimesh_data_new();
+
+ /* 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 */
+ {
+ MVert *va = (IN_RANGE(mface->v1, 0, totvert)) ? (mvert + mface->v1) : (mvert);
+ MVert *vb = (IN_RANGE(mface->v2, 0, totvert)) ? (mvert + mface->v2) : (mvert);
+ MVert *vc = (IN_RANGE(mface->v3, 0, totvert)) ? (mvert + mface->v3) : (mvert);
+
+ RB_trimesh_add_triangle(mdata, va->co, vb->co, vc->co);
+ }
+
+ /* add second triangle if needed - verts 1,3,4 */
+ if (mface->v4) {
+ MVert *va = (IN_RANGE(mface->v1, 0, totvert)) ? (mvert + mface->v1) : (mvert);
+ MVert *vb = (IN_RANGE(mface->v3, 0, totvert)) ? (mvert + mface->v3) : (mvert);
+ MVert *vc = (IN_RANGE(mface->v4, 0, totvert)) ? (mvert + mface->v4) : (mvert);
+
+ RB_trimesh_add_triangle(mdata, va->co, vb->co, vc->co);
+ }
+ }
+
+ /* construct collision shape
+ *
+ * These have been chosen to get better speed/accuracy tradeoffs with regards
+ * to limitations of each:
+ * - BVH-Triangle Mesh: for passive objects only. Despite having greater
+ * speed/accuracy, they cannot be used for moving objects.
+ * - GImpact Mesh: for active objects. These are slower and less stable,
+ * but are more flexible for general usage.
+ */
+ if (ob->rigidbody_object->type == RBO_TYPE_PASSIVE) {
+ shape = RB_shape_new_trimesh(mdata);
+ }
+ else {
+ shape = RB_shape_new_gimpact_mesh(mdata);
+ }
+ }
+
+ /* cleanup temp data */
+ if (dm) {
+ dm->release(dm);
+ }
+ }
+ else {
+ printf("ERROR: cannot make Triangular Mesh collision shape for non-Mesh object\n");
+ }
+
+ return shape;
+}
+
+/* Create new physics sim collision shape for object and store it,
+ * or remove the existing one first and replace...
+ */
+void BKE_rigidbody_validate_sim_shape(Object *ob, short rebuild)
+{
+ RigidBodyOb *rbo = ob->rigidbody_object;
+ rbCollisionShape *new_shape = NULL;
+ BoundBox *bb = NULL;
+ float size[3] = {1.0f, 1.0f, 1.0f};
+ float radius = 1.0f;
+ float height = 1.0f;
+ float capsule_height;
+ float hull_margin = 0.0f;
+ bool can_embed = true;
+ bool has_volume;
+
+ /* sanity check */
+ if (rbo == NULL)
+ return;
+
+ /* don't create a new shape if we already have one and don't want to rebuild it */
+ if (rbo->physics_shape && !rebuild)
+ return;
+
+ /* if automatically determining dimensions, use the Object's boundbox
+ * - assume that all quadrics are standing upright on local z-axis
+ * - assume even distribution of mass around the Object's pivot
+ * (i.e. Object pivot is centralized in boundbox)
+ */
+ // XXX: all dimensions are auto-determined now... later can add stored settings for this
+ /* get object dimensions without scaling */
+ bb = BKE_object_boundbox_get(ob);
+ if (bb) {
+ size[0] = (bb->vec[4][0] - bb->vec[0][0]);
+ size[1] = (bb->vec[2][1] - bb->vec[0][1]);
+ size[2] = (bb->vec[1][2] - bb->vec[0][2]);
+ }
+ mul_v3_fl(size, 0.5f);
+
+ if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
+ /* take radius as largest x/y dimension, and height as z-dimension */
+ radius = MAX2(size[0], size[1]);
+ height = size[2];
+ }
+ else if (rbo->shape == RB_SHAPE_SPHERE) {
+ /* take radius to the the largest dimension to try and encompass everything */
+ radius = MAX3(size[0], size[1], size[2]);
+ }
+
+ /* create new shape */
+ switch (rbo->shape) {
+ case RB_SHAPE_BOX:
+ new_shape = RB_shape_new_box(size[0], size[1], size[2]);
+ break;
+
+ case RB_SHAPE_SPHERE:
+ new_shape = RB_shape_new_sphere(radius);
+ break;
+
+ case RB_SHAPE_CAPSULE:
+ capsule_height = (height - radius) * 2.0f;
+ new_shape = RB_shape_new_capsule(radius, (capsule_height > 0.0f) ? capsule_height : 0.0f);
+ break;
+ case RB_SHAPE_CYLINDER:
+ new_shape = RB_shape_new_cylinder(radius, height);
+ break;
+ case RB_SHAPE_CONE:
+ new_shape = RB_shape_new_cone(radius, height * 2.0f);
+ break;
+
+ case RB_SHAPE_CONVEXH:
+ /* try to emged collision margin */
+ has_volume = (MIN3(size[0], size[1], size[2]) > 0.0f);
+
+ if (!(rbo->flag & RBO_FLAG_USE_MARGIN) && has_volume)
+ hull_margin = 0.04f;
+ new_shape = rigidbody_get_shape_convexhull_from_mesh(ob, hull_margin, &can_embed);
+ if (!(rbo->flag & RBO_FLAG_USE_MARGIN))
+ rbo->margin = (can_embed && has_volume) ? 0.04f : 0.0f; /* RB_TODO ideally we shouldn't directly change the margin here */
+ break;
+ case RB_SHAPE_TRIMESH:
+ new_shape = rigidbody_get_shape_trimesh_from_mesh(ob);
+ break;
+ }
+ /* assign new collision shape if creation was successful */
+ if (new_shape) {
+ if (rbo->physics_shape)
+ RB_shape_delete(rbo->physics_shape);
+ rbo->physics_shape = new_shape;
+ RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo));
+ }
+ else { /* otherwise fall back to box shape */
+ rbo->shape = RB_SHAPE_BOX;
+ BKE_rigidbody_validate_sim_shape(ob, true);
+ }
+}
+
+/* --------------------- */
+
+/* Create physics sim representation of object given RigidBody settings
+ * < rebuild: even if an instance already exists, replace it
+ */
+void BKE_rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, short rebuild)
+{
+ RigidBodyOb *rbo = (ob) ? ob->rigidbody_object : NULL;
+ float loc[3];
+ float rot[4];
+
+ /* sanity checks:
+ * - object doesn't have RigidBody info already: then why is it here?
+ */
+ if (rbo == NULL)
+ return;
+
+ /* make sure collision shape exists */
+ /* FIXME we shouldn't always have to rebuild collision shapes when rebuilding objects, but it's needed for constraints to update correctly */
+ if (rbo->physics_shape == NULL || rebuild)
+ BKE_rigidbody_validate_sim_shape(ob, true);
+
+ if (rbo->physics_object) {
+ if (rebuild == false)
+ RB_dworld_remove_body(rbw->physics_world, rbo->physics_object);
+ }
+ if (!rbo->physics_object || rebuild) {
+ /* remove rigid body if it already exists before creating a new one */
+ if (rbo->physics_object) {
+ RB_body_delete(rbo->physics_object);
+ }
+
+ mat4_to_loc_quat(loc, rot, ob->obmat);
+
+ rbo->physics_object = RB_body_new(rbo->physics_shape, loc, rot);
+
+ RB_body_set_friction(rbo->physics_object, rbo->friction);
+ RB_body_set_restitution(rbo->physics_object, rbo->restitution);
+
+ RB_body_set_damping(rbo->physics_object, rbo->lin_damping, rbo->ang_damping);
+ RB_body_set_sleep_thresh(rbo->physics_object, rbo->lin_sleep_thresh, rbo->ang_sleep_thresh);
+ RB_body_set_activation_state(rbo->physics_object, rbo->flag & RBO_FLAG_USE_DEACTIVATION);
+
+ if (rbo->type == RBO_TYPE_PASSIVE || rbo->flag & RBO_FLAG_START_DEACTIVATED)
+ RB_body_deactivate(rbo->physics_object);
+
+
+ RB_body_set_linear_factor(rbo->physics_object,
+ (ob->protectflag & OB_LOCK_LOCX) == 0,
+ (ob->protectflag & OB_LOCK_LOCY) == 0,
+ (ob->protectflag & OB_LOCK_LOCZ) == 0);
+ RB_body_set_angular_factor(rbo->physics_object,
+ (ob->protectflag & OB_LOCK_ROTX) == 0,
+ (ob->protectflag & OB_LOCK_ROTY) == 0,
+ (ob->protectflag & OB_LOCK_ROTZ) == 0);
+
+ RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
+ RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
+ }
+
+ if (rbw && rbw->physics_world)
+ RB_dworld_add_body(rbw->physics_world, rbo->physics_object, rbo->col_groups);
+}
+
+/* --------------------- */
+
+/* Create physics sim representation of constraint given rigid body constraint settings
+ * < rebuild: even if an instance already exists, replace it
+ */
+void BKE_rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, short rebuild)
+{
+ RigidBodyCon *rbc = (ob) ? ob->rigidbody_constraint : NULL;
+ float loc[3];
+ float rot[4];
+ float lin_lower;
+ float lin_upper;
+ float ang_lower;
+ float ang_upper;
+
+ /* sanity checks:
+ * - object should have a rigid body constraint
+ * - rigid body constraint should have at least one constrained object
+ */
+ if (rbc == NULL) {
+ return;
+ }
+
+ if (ELEM4(NULL, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) {
+ if (rbc->physics_constraint) {
+ RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
+ RB_constraint_delete(rbc->physics_constraint);
+ rbc->physics_constraint = NULL;
+ }
+ return;
+ }
+
+ if (rbc->physics_constraint) {
+ if (rebuild == false)
+ RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
+ }
+ if (rbc->physics_constraint == NULL || rebuild) {
+ rbRigidBody *rb1 = rbc->ob1->rigidbody_object->physics_object;
+ rbRigidBody *rb2 = rbc->ob2->rigidbody_object->physics_object;
+
+ /* remove constraint if it already exists before creating a new one */
+ if (rbc->physics_constraint) {
+ RB_constraint_delete(rbc->physics_constraint);
+ rbc->physics_constraint = NULL;
+ }
+
+ mat4_to_loc_quat(loc, rot, ob->obmat);
+
+ if (rb1 && rb2) {
+ switch (rbc->type) {
+ case RBC_TYPE_POINT:
+ rbc->physics_constraint = RB_constraint_new_point(loc, rb1, rb2);
+ break;
+ case RBC_TYPE_FIXED:
+ rbc->physics_constraint = RB_constraint_new_fixed(loc, rot, rb1, rb2);
+ break;
+ case RBC_TYPE_HINGE:
+ rbc->physics_constraint = RB_constraint_new_hinge(loc, rot, rb1, rb2);
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Z) {
+ RB_constraint_set_limits_hinge(rbc->physics_constraint, rbc->limit_ang_z_lower, rbc->limit_ang_z_upper);
+ }
+ else
+ RB_constraint_set_limits_hinge(rbc->physics_constraint, 0.0f, -1.0f);
+ break;
+ case RBC_TYPE_SLIDER:
+ rbc->physics_constraint = RB_constraint_new_slider(loc, rot, rb1, rb2);
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X)
+ RB_constraint_set_limits_slider(rbc->physics_constraint, rbc->limit_lin_x_lower, rbc->limit_lin_x_upper);
+ else
+ RB_constraint_set_limits_slider(rbc->physics_constraint, 0.0f, -1.0f);
+ break;
+ case RBC_TYPE_PISTON:
+ rbc->physics_constraint = RB_constraint_new_piston(loc, rot, rb1, rb2);
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X) {
+ lin_lower = rbc->limit_lin_x_lower;
+ lin_upper = rbc->limit_lin_x_upper;
+ }
+ else {
+ lin_lower = 0.0f;
+ lin_upper = -1.0f;
+ }
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_X) {
+ ang_lower = rbc->limit_ang_x_lower;
+ ang_upper = rbc->limit_ang_x_upper;
+ }
+ else {
+ ang_lower = 0.0f;
+ ang_upper = -1.0f;
+ }
+ RB_constraint_set_limits_piston(rbc->physics_constraint, lin_lower, lin_upper, ang_lower, ang_upper);
+ break;
+ case RBC_TYPE_6DOF_SPRING:
+ rbc->physics_constraint = RB_constraint_new_6dof_spring(loc, rot, rb1, rb2);
+
+ RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->flag & RBC_FLAG_USE_SPRING_X);
+ RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_stiffness_x);
+ RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_damping_x);
+
+ RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->flag & RBC_FLAG_USE_SPRING_Y);
+ RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_stiffness_y);
+ RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_damping_y);
+
+ RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->flag & RBC_FLAG_USE_SPRING_Z);
+ RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_stiffness_z);
+ RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_damping_z);
+
+ RB_constraint_set_equilibrium_6dof_spring(rbc->physics_constraint);
+ /* fall through */
+ case RBC_TYPE_6DOF:
+ if (rbc->type == RBC_TYPE_6DOF) /* a litte awkward but avoids duplicate code for limits */
+ rbc->physics_constraint = RB_constraint_new_6dof(loc, rot, rb1, rb2);
+
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X)
+ RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->limit_lin_x_lower, rbc->limit_lin_x_upper);
+ else
+ RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_X, 0.0f, -1.0f);
+
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Y)
+ RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->limit_lin_y_lower, rbc->limit_lin_y_upper);
+ else
+ RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Y, 0.0f, -1.0f);
+
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Z)
+ RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->limit_lin_z_lower, rbc->limit_lin_z_upper);
+ else
+ RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Z, 0.0f, -1.0f);
+
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_X)
+ RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->limit_ang_x_lower, rbc->limit_ang_x_upper);
+ else
+ RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_X, 0.0f, -1.0f);
+
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Y)
+ RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->limit_ang_y_lower, rbc->limit_ang_y_upper);
+ else
+ RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Y, 0.0f, -1.0f);
+
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Z)
+ RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->limit_ang_z_lower, rbc->limit_ang_z_upper);
+ else
+ RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, 0.0f, -1.0f);
+ break;
+ case RBC_TYPE_MOTOR:
+ rbc->physics_constraint = RB_constraint_new_motor(loc, rot, rb1, rb2);
+
+ RB_constraint_set_enable_motor(rbc->physics_constraint, rbc->flag & RBC_FLAG_USE_MOTOR_LIN, rbc->flag & RBC_FLAG_USE_MOTOR_ANG);
+ RB_constraint_set_max_impulse_motor(rbc->physics_constraint, rbc->motor_lin_max_impulse, rbc->motor_ang_max_impulse);
+ RB_constraint_set_target_velocity_motor(rbc->physics_constraint, rbc->motor_lin_target_velocity, rbc->motor_ang_target_velocity);
+ break;
+ }
+ }
+ else { /* can't create constraint without both rigid bodies */
+ return;
+ }
+
+ RB_constraint_set_enabled(rbc->physics_constraint, rbc->flag & RBC_FLAG_ENABLED);
+
+ if (rbc->flag & RBC_FLAG_USE_BREAKING)
+ RB_constraint_set_breaking_threshold(rbc->physics_constraint, rbc->breaking_threshold);
+ else
+ RB_constraint_set_breaking_threshold(rbc->physics_constraint, FLT_MAX);
+
+ if (rbc->flag & RBC_FLAG_OVERRIDE_SOLVER_ITERATIONS)
+ RB_constraint_set_solver_iterations(rbc->physics_constraint, rbc->num_solver_iterations);
+ else
+ RB_constraint_set_solver_iterations(rbc->physics_constraint, -1);
+ }
+
+ if (rbw && rbw->physics_world && rbc->physics_constraint) {
+ RB_dworld_add_constraint(rbw->physics_world, rbc->physics_constraint, rbc->flag & RBC_FLAG_DISABLE_COLLISIONS);
+ }
+}
+
+/* --------------------- */
+
+/* Create physics sim world given RigidBody world settings */
+// NOTE: this does NOT update object references that the scene uses, in case those aren't ready yet!
+void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, short rebuild)
+{
+ /* sanity checks */
+ if (rbw == NULL)
+ return;
+
+ /* create new sim world */
+ if (rebuild || rbw->physics_world == NULL) {
+ if (rbw->physics_world)
+ RB_dworld_delete(rbw->physics_world);
+ rbw->physics_world = RB_dworld_new(scene->physics_settings.gravity);
+ }
+
+ RB_dworld_set_solver_iterations(rbw->physics_world, rbw->num_solver_iterations);
+ RB_dworld_set_split_impulse(rbw->physics_world, rbw->flag & RBW_FLAG_USE_SPLIT_IMPULSE);
+}
+
+/* ************************************** */
+/* Setup Utilities - Create Settings Blocks */
+
+/* Set up RigidBody world */
+RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene)
+{
+ /* try to get whatever RigidBody world that might be representing this already */
+ RigidBodyWorld *rbw;
+
+ /* sanity checks
+ * - there must be a valid scene to add world to
+ * - there mustn't be a sim world using this group already
+ */
+ if (scene == NULL)
+ return NULL;
+
+ /* create a new sim world */
+ rbw = MEM_callocN(sizeof(RigidBodyWorld), "RigidBodyWorld");
+
+ /* set default settings */
+ rbw->effector_weights = BKE_add_effector_weights(NULL);
+
+ rbw->ltime = PSFRA;
+
+ rbw->time_scale = 1.0f;
+
+ rbw->steps_per_second = 60; /* Bullet default (60 Hz) */
+ rbw->num_solver_iterations = 10; /* 10 is bullet default */
+
+ rbw->pointcache = BKE_ptcache_add(&(rbw->ptcaches));
+ rbw->pointcache->step = 1;
+
+ /* return this sim world */
+ return rbw;
+}
+
+/* Add rigid body settings to the specified object */
+RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
+{
+ RigidBodyOb *rbo;
+ RigidBodyWorld *rbw = scene->rigidbody_world;
+
+ /* sanity checks
+ * - rigidbody world must exist
+ * - object must exist
+ * - cannot add rigid body if it already exists
+ */
+ if (ob == NULL || (ob->rigidbody_object != NULL))
+ return NULL;
+
+ /* create new settings data, and link it up */
+ rbo = MEM_callocN(sizeof(RigidBodyOb), "RigidBodyOb");
+
+ /* set default settings */
+ rbo->type = type;
+
+ rbo->mass = 1.0f;
+
+ rbo->friction = 0.5f; /* best when non-zero. 0.5 is Bullet default */
+ rbo->restitution = 0.0f; /* best when zero. 0.0 is Bullet default */
+
+ rbo->margin = 0.04f; /* 0.04 (in meters) is Bullet default */
+
+ rbo->lin_sleep_thresh = 0.4f; /* 0.4 is half of Bullet default */
+ rbo->ang_sleep_thresh = 0.5f; /* 0.5 is half of Bullet default */
+
+ rbo->lin_damping = 0.04f; /* 0.04 is game engine default */
+ rbo->ang_damping = 0.1f; /* 0.1 is game engine default */
+
+ rbo->col_groups = 1;
+
+ /* use triangle meshes for passive objects
+ * use convex hulls for active objects since dynamic triangle meshes are very unstable
+ */
+ if (type == RBO_TYPE_ACTIVE)
+ rbo->shape = RB_SHAPE_CONVEXH;
+ else
+ rbo->shape = RB_SHAPE_TRIMESH;
+
+ /* set initial transform */
+ mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat);
+
+ /* flag cache as outdated */
+ BKE_rigidbody_cache_reset(rbw);
+
+ /* return this object */
+ return rbo;
+}
+
+/* Add rigid body constraint to the specified object */
+RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short type)
+{
+ RigidBodyCon *rbc;
+ RigidBodyWorld *rbw = scene->rigidbody_world;
+
+ /* sanity checks
+ * - rigidbody world must exist
+ * - object must exist
+ * - cannot add constraint if it already exists
+ */
+ if (ob == NULL || (ob->rigidbody_constraint != NULL))
+ return NULL;
+
+ /* create new settings data, and link it up */
+ rbc = MEM_callocN(sizeof(RigidBodyCon), "RigidBodyCon");
+
+ /* set default settings */
+ rbc->type = type;
+
+ rbc->ob1 = NULL;
+ rbc->ob2 = NULL;
+
+ rbc->flag |= RBC_FLAG_ENABLED;
+ rbc->flag |= RBC_FLAG_DISABLE_COLLISIONS;
+
+ rbc->breaking_threshold = 10.0f; /* no good default here, just use 10 for now */
+ rbc->num_solver_iterations = 10; /* 10 is Bullet default */
+
+ rbc->limit_lin_x_lower = -1.0f;
+ rbc->limit_lin_x_upper = 1.0f;
+ rbc->limit_lin_y_lower = -1.0f;
+ rbc->limit_lin_y_upper = 1.0f;
+ rbc->limit_lin_z_lower = -1.0f;
+ rbc->limit_lin_z_upper = 1.0f;
+ rbc->limit_ang_x_lower = -M_PI_4;
+ rbc->limit_ang_x_upper = M_PI_4;
+ rbc->limit_ang_y_lower = -M_PI_4;
+ rbc->limit_ang_y_upper = M_PI_4;
+ rbc->limit_ang_z_lower = -M_PI_4;
+ rbc->limit_ang_z_upper = M_PI_4;
+
+ rbc->spring_damping_x = 0.5f;
+ rbc->spring_damping_y = 0.5f;
+ rbc->spring_damping_z = 0.5f;
+ rbc->spring_stiffness_x = 10.0f;
+ rbc->spring_stiffness_y = 10.0f;
+ rbc->spring_stiffness_z = 10.0f;
+
+ rbc->motor_lin_max_impulse = 1.0f;
+ rbc->motor_lin_target_velocity = 1.0f;
+ rbc->motor_ang_max_impulse = 1.0f;
+ rbc->motor_ang_target_velocity = 1.0f;
+
+ /* flag cache as outdated */
+ BKE_rigidbody_cache_reset(rbw);
+
+ /* return this object */
+ return rbc;
+}
+
+/* ************************************** */
+/* Utilities API */
+
+/* Get RigidBody world for the given scene, creating one if needed
+ * < scene: Scene to find active Rigid Body world for
+ */
+RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene)
+{
+ /* sanity check */
+ if (scene == NULL)
+ return NULL;
+
+ return scene->rigidbody_world;
+}
+
+void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
+{
+ RigidBodyWorld *rbw = scene->rigidbody_world;
+ RigidBodyOb *rbo = ob->rigidbody_object;
+ RigidBodyCon *rbc;
+ GroupObject *go;
+ int i;
+
+ if (rbw) {
+ /* remove from rigidbody world, free object won't do this */
+ if (rbw->physics_world && rbo->physics_object)
+ RB_dworld_remove_body(rbw->physics_world, rbo->physics_object);
+
+ /* remove object from array */
+ if (rbw && rbw->objects) {
+ for (i = 0; i < rbw->numbodies; i++) {
+ if (rbw->objects[i] == ob) {
+ rbw->objects[i] = NULL;
+ break;
+ }
+ }
+ }
+
+ /* remove object from rigid body constraints */
+ if (rbw->constraints) {
+ for (go = rbw->constraints->gobject.first; go; go = go->next) {
+ Object *obt = go->ob;
+ if (obt && obt->rigidbody_constraint) {
+ rbc = obt->rigidbody_constraint;
+ if (rbc->ob1 == ob) {
+ rbc->ob1 = NULL;
+ rbc->flag |= RBC_FLAG_NEEDS_VALIDATE;
+ }
+ if (rbc->ob2 == ob) {
+ rbc->ob2 = NULL;
+ rbc->flag |= RBC_FLAG_NEEDS_VALIDATE;
+ }
+ }
+ }
+ }
+ }
+
+ /* remove object's settings */
+ BKE_rigidbody_free_object(ob);
+
+ /* flag cache as outdated */
+ BKE_rigidbody_cache_reset(rbw);
+}
+
+void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob)
+{
+ RigidBodyWorld *rbw = scene->rigidbody_world;
+ RigidBodyCon *rbc = ob->rigidbody_constraint;
+
+ if (rbw) {
+ /* remove from rigidbody world, free object won't do this */
+ if (rbw && rbw->physics_world && rbc->physics_constraint)
+ RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
+ }
+ /* remove object's settings */
+ BKE_rigidbody_free_constraint(ob);
+
+ /* flag cache as outdated */
+ BKE_rigidbody_cache_reset(rbw);
+}
+
+
+/* ************************************** */
+/* Simulation Interface - Bullet */
+
+/* Update object array and rigid body count so they're in sync with the rigid body group */
+static void rigidbody_update_ob_array(RigidBodyWorld *rbw)
+{
+ GroupObject *go;
+ int i, n;
+
+ n = BLI_countlist(&rbw->group->gobject);
+
+ if (rbw->numbodies != n) {
+ rbw->numbodies = n;
+ rbw->objects = realloc(rbw->objects, sizeof(Object *) * rbw->numbodies);
+ }
+
+ for (go = rbw->group->gobject.first, i = 0; go; go = go->next, i++) {
+ Object *ob = go->ob;
+ rbw->objects[i] = ob;
+ }
+}
+
+static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw)
+{
+ float adj_gravity[3];
+
+ /* adjust gravity to take effector weights into account */
+ if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
+ copy_v3_v3(adj_gravity, scene->physics_settings.gravity);
+ mul_v3_fl(adj_gravity, rbw->effector_weights->global_gravity * rbw->effector_weights->weight[0]);
+ }
+ else {
+ zero_v3(adj_gravity);
+ }
+
+ /* update gravity, since this RNA setting is not part of RigidBody settings */
+ RB_dworld_set_gravity(rbw->physics_world, adj_gravity);
+
+ /* update object array in case there are changes */
+ rigidbody_update_ob_array(rbw);
+}
+
+static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo)
+{
+ float loc[3];
+ float rot[4];
+ float scale[3];
+
+ /* only update if rigid body exists */
+ if (rbo->physics_object == NULL)
+ return;
+
+ mat4_decompose(loc, rot, scale, ob->obmat);
+
+ /* update scale for all objects */
+ RB_body_set_scale(rbo->physics_object, scale);
+ /* compensate for embedded convex hull collision margin */
+ if (!(rbo->flag & RBO_FLAG_USE_MARGIN) && rbo->shape == RB_SHAPE_CONVEXH)
+ RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo) * MIN3(scale[0], scale[1], scale[2]));
+
+ /* make transformed objects temporarily kinmatic so that they can be moved by the user during simulation */
+ if (ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ) {
+ RB_body_set_kinematic_state(rbo->physics_object, TRUE);
+ RB_body_set_mass(rbo->physics_object, 0.0f);
+ }
+
+ /* update rigid body location and rotation for kinematic bodies */
+ if (rbo->flag & RBO_FLAG_KINEMATIC || (ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ)) {
+ RB_body_activate(rbo->physics_object);
+ RB_body_set_loc_rot(rbo->physics_object, loc, rot);
+ }
+ /* update influence of effectors - but don't do it on an effector */
+ /* only dynamic bodies need effector update */
+ else if (rbo->type == RBO_TYPE_ACTIVE && ((ob->pd == NULL) || (ob->pd->forcefield == PFIELD_NULL))) {
+ EffectorWeights *effector_weights = rbw->effector_weights;
+ EffectedPoint epoint;
+ ListBase *effectors;
+
+ /* get effectors present in the group specified by effector_weights */
+ effectors = pdInitEffectors(scene, ob, NULL, effector_weights);
+ if (effectors) {
+ float force[3] = {0.0f, 0.0f, 0.0f};
+ float loc[3], vel[3];
+
+ /* create dummy 'point' which represents last known position of object as result of sim */
+ // XXX: this can create some inaccuracies with sim position, but is probably better than using unsimulated vals?
+ RB_body_get_position(rbo->physics_object, loc);
+ RB_body_get_linear_velocity(rbo->physics_object, vel);
+
+ pd_point_from_loc(scene, loc, vel, 0, &epoint);
+
+ /* calculate net force of effectors, and apply to sim object
+ * - we use 'central force' since apply force requires a "relative position" which we don't have...
+ */
+ pdDoEffectors(effectors, NULL, effector_weights, &epoint, force, NULL);
+ if (G.f & G_DEBUG)
+ printf("\tapplying force (%f,%f,%f) to '%s'\n", force[0], force[1], force[2], ob->id.name + 2);
+ /* activate object in case it is deactivated */
+ if (!is_zero_v3(force))
+ RB_body_activate(rbo->physics_object);
+ RB_body_apply_central_force(rbo->physics_object, force);
+ }
+ else if (G.f & G_DEBUG)
+ printf("\tno forces to apply to '%s'\n", ob->id.name + 2);
+
+ /* cleanup */
+ pdEndEffectors(&effectors);
+ }
+ /* NOTE: passive objects don't need to be updated since they don't move */
+
+ /* NOTE: no other settings need to be explicitly updated here,
+ * since RNA setters take care of the rest :)
+ */
+}
+
+/* Updates and validates world, bodies and shapes.
+ * < rebuild: rebuild entire simulation
+ */
+static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, int rebuild)
+{
+ GroupObject *go;
+
+ /* update world */
+ if (rebuild)
+ BKE_rigidbody_validate_sim_world(scene, rbw, true);
+ rigidbody_update_sim_world(scene, rbw);
+
+ /* update objects */
+ for (go = rbw->group->gobject.first; go; go = go->next) {
+ Object *ob = go->ob;
+
+ if (ob && ob->type == OB_MESH) {
+ /* validate that we've got valid object set up here... */
+ RigidBodyOb *rbo = ob->rigidbody_object;
+ /* update transformation matrix of the object so we don't get a frame of lag for simple animations */
+ BKE_object_where_is_calc(scene, ob);
+
+ if (rbo == NULL) {
+ /* Since this object is included in the sim group but doesn't have
+ * rigid body settings (perhaps it was added manually), add!
+ * - assume object to be active? That is the default for newly added settings...
+ */
+ ob->rigidbody_object = BKE_rigidbody_create_object(scene, ob, RBO_TYPE_ACTIVE);
+ BKE_rigidbody_validate_sim_object(rbw, ob, true);
+
+ rbo = ob->rigidbody_object;
+ }
+ else {
+ /* perform simulation data updates as tagged */
+ /* refresh object... */
+ if (rebuild) {
+ /* World has been rebuilt so rebuild object */
+ BKE_rigidbody_validate_sim_object(rbw, ob, true);
+ }
+ else if (rbo->flag & RBO_FLAG_NEEDS_VALIDATE) {
+ BKE_rigidbody_validate_sim_object(rbw, ob, false);
+ }
+ /* refresh shape... */
+ if (rbo->flag & RBO_FLAG_NEEDS_RESHAPE) {
+ /* mesh/shape data changed, so force shape refresh */
+ BKE_rigidbody_validate_sim_shape(ob, true);
+ /* now tell RB sim about it */
+ // XXX: we assume that this can only get applied for active/passive shapes that will be included as rigidbodies
+ RB_body_set_collision_shape(rbo->physics_object, rbo->physics_shape);
+ }
+ rbo->flag &= ~(RBO_FLAG_NEEDS_VALIDATE | RBO_FLAG_NEEDS_RESHAPE);
+ }
+
+ /* update simulation object... */
+ rigidbody_update_sim_ob(scene, rbw, ob, rbo);
+ }
+ }
+ /* update constraints */
+ if (rbw->constraints == NULL) /* no constraints, move on */
+ return;
+ for (go = rbw->constraints->gobject.first; go; go = go->next) {
+ Object *ob = go->ob;
+
+ if (ob) {
+ /* validate that we've got valid object set up here... */
+ RigidBodyCon *rbc = ob->rigidbody_constraint;
+ /* update transformation matrix of the object so we don't get a frame of lag for simple animations */
+ BKE_object_where_is_calc(scene, ob);
+
+ if (rbc == NULL) {
+ /* Since this object is included in the group but doesn't have
+ * constraint settings (perhaps it was added manually), add!
+ */
+ ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, RBC_TYPE_FIXED);
+ BKE_rigidbody_validate_sim_constraint(rbw, ob, true);
+
+ rbc = ob->rigidbody_constraint;
+ }
+ else {
+ /* perform simulation data updates as tagged */
+ if (rebuild) {
+ /* World has been rebuilt so rebuild constraint */
+ BKE_rigidbody_validate_sim_constraint(rbw, ob, true);
+ }
+ else if (rbc->flag & RBC_FLAG_NEEDS_VALIDATE) {
+ BKE_rigidbody_validate_sim_constraint(rbw, ob, false);
+ }
+ rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE;
+ }
+ }
+ }
+}
+
+static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw)
+{
+ GroupObject *go;
+
+ for (go = rbw->group->gobject.first; go; go = go->next) {
+ Object *ob = go->ob;
+
+ if (ob) {
+ RigidBodyOb *rbo = ob->rigidbody_object;
+ /* reset kinematic state for transformed objects */
+ if (ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ) {
+ RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
+ RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
+ /* deactivate passive objects so they don't interfere with deactivation of active objects */
+ if (rbo->type == RBO_TYPE_PASSIVE)
+ RB_body_deactivate(rbo->physics_object);
+ }
+ }
+ }
+}
+/* Sync rigid body and object transformations */
+void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime)
+{
+ RigidBodyOb *rbo = ob->rigidbody_object;
+
+ /* keep original transform for kinematic and passive objects */
+ if (ELEM(NULL, rbw, rbo) || rbo->flag & RBO_FLAG_KINEMATIC || rbo->type == RBO_TYPE_PASSIVE)
+ return;
+
+ /* use rigid body transform after cache start frame if objects is not being transformed */
+ if (ctime > rbw->pointcache->startframe && !(ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ)) {
+ float mat[4][4], size_mat[4][4], size[3];
+
+ /* keep original transform when the simulation is muted */
+ if (rbw->flag & RBW_FLAG_MUTED)
+ return;
+
+ normalize_qt(rbo->orn); // RB_TODO investigate why quaternion isn't normalized at this point
+ quat_to_mat4(mat, rbo->orn);
+ copy_v3_v3(mat[3], rbo->pos);
+
+ mat4_to_size(size, ob->obmat);
+ size_to_mat4(size_mat, size);
+ mult_m4_m4m4(mat, mat, size_mat);
+
+ copy_m4_m4(ob->obmat, mat);
+ }
+ /* otherwise set rigid body transform to current obmat */
+ else {
+ mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat);
+ }
+}
+
+/* Used when cancelling transforms - return rigidbody and object to initial states */
+void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle)
+{
+ RigidBodyOb *rbo = ob->rigidbody_object;
+
+ /* return rigid body and object to their initial states */
+ copy_v3_v3(rbo->pos, ob->loc);
+ copy_v3_v3(ob->loc, loc);
+
+ if (ob->rotmode > 0) {
+ eulO_to_quat(rbo->orn, ob->rot, ob->rotmode);
+ copy_v3_v3(ob->rot, rot);
+ }
+ else if (ob->rotmode == ROT_MODE_AXISANGLE) {
+ axis_angle_to_quat(rbo->orn, ob->rotAxis, ob->rotAngle);
+ copy_v3_v3(ob->rotAxis, rotAxis);
+ ob->rotAngle = rotAngle;
+ }
+ else {
+ copy_qt_qt(rbo->orn, ob->quat);
+ copy_qt_qt(ob->quat, quat);
+ }
+ if (rbo->physics_object) {
+ /* allow passive objects to return to original transform */
+ if (rbo->type == RBO_TYPE_PASSIVE)
+ RB_body_set_kinematic_state(rbo->physics_object, TRUE);
+ RB_body_set_loc_rot(rbo->physics_object, rbo->pos, rbo->orn);
+ }
+ // RB_TODO update rigid body physics object's loc/rot for dynamic objects here as well (needs to be done outside bullet's update loop)
+}
+
+void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw)
+{
+ if (rbw)
+ rbw->pointcache->flag |= PTCACHE_OUTDATED;
+}
+
+/* ------------------ */
+
+/* Rebuild rigid body world */
+/* NOTE: this needs to be called before frame update to work correctly */
+void BKE_rigidbody_rebuild_world(Scene *scene, float ctime)
+{
+ RigidBodyWorld *rbw = scene->rigidbody_world;
+ PointCache *cache;
+ PTCacheID pid;
+ int startframe, endframe;
+
+ BKE_ptcache_id_from_rigidbody(&pid, NULL, rbw);
+ BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, NULL);
+ 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)) {
+ cache->flag |= PTCACHE_OUTDATED;
+ }
+
+ if (ctime <= startframe + 1 && rbw->ltime == startframe) {
+ if (cache->flag & PTCACHE_OUTDATED) {
+ BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
+ rigidbody_update_simulation(scene, rbw, true);
+ BKE_ptcache_validate(cache, (int)ctime);
+ cache->last_exact = 0;
+ cache->flag &= ~PTCACHE_REDO_NEEDED;
+ }
+ }
+}
+
+/* Run RigidBody simulation for the specified physics world */
+void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
+{
+ float timestep;
+ RigidBodyWorld *rbw = scene->rigidbody_world;
+ PointCache *cache;
+ PTCacheID pid;
+ int startframe, endframe;
+
+ BKE_ptcache_id_from_rigidbody(&pid, NULL, rbw);
+ BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, NULL);
+ cache = rbw->pointcache;
+
+ if (ctime <= startframe) {
+ rbw->ltime = startframe;
+ return;
+ }
+ /* make sure we don't go out of cache frame range */
+ else if (ctime > endframe) {
+ ctime = endframe;
+ }
+
+ /* don't try to run the simulation if we don't have a world yet but allow reading baked cache */
+ if (rbw->physics_world == NULL && !(cache->flag & PTCACHE_BAKED))
+ return;
+ else if (rbw->objects == NULL)
+ rigidbody_update_ob_array(rbw);
+
+ /* try to read from cache */
+ // RB_TODO deal with interpolated, old and baked results
+ if (BKE_ptcache_read(&pid, ctime)) {
+ BKE_ptcache_validate(cache, (int)ctime);
+ rbw->ltime = ctime;
+ return;
+ }
+
+ /* advance simulation, we can only step one frame forward */
+ if (ctime == rbw->ltime + 1 && !(cache->flag & PTCACHE_BAKED)) {
+ /* write cache for first frame when on second frame */
+ if (rbw->ltime == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) {
+ BKE_ptcache_write(&pid, startframe);
+ }
+
+ /* update and validate simulation */
+ rigidbody_update_simulation(scene, rbw, false);
+
+ /* calculate how much time elapsed since last step in seconds */
+ timestep = 1.0f / (float)FPS * (ctime - rbw->ltime) * rbw->time_scale;
+ /* step simulation by the requested timestep, steps per second are adjusted to take time scale into account */
+ RB_dworld_step_simulation(rbw->physics_world, timestep, INT_MAX, 1.0f / (float)rbw->steps_per_second * min_ff(rbw->time_scale, 1.0f));
+
+ rigidbody_update_simulation_post_step(rbw);
+
+ /* write cache for current frame */
+ BKE_ptcache_validate(cache, (int)ctime);
+ BKE_ptcache_write(&pid, (unsigned int)ctime);
+
+ rbw->ltime = ctime;
+ }
+}
+/* ************************************** */
+
+#else /* WITH_BULLET */
+
+/* stubs */
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+void BKE_rigidbody_free_world(RigidBodyWorld *rbw) {}
+void BKE_rigidbody_free_object(Object *ob) {}
+void BKE_rigidbody_free_constraint(Object *ob) {}
+struct RigidBodyOb *BKE_rigidbody_copy_object(Object *ob) { return NULL; }
+struct RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob) { return NULL; }
+void BKE_rigidbody_relink_constraint(RigidBodyCon *rbc) {}
+void BKE_rigidbody_validate_sim_shape(Object *ob, short rebuild) {}
+void BKE_rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, short rebuild) {}
+void BKE_rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, short rebuild) {}
+void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, short rebuild) {}
+struct RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) { return NULL; }
+struct RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type) { return NULL; }
+struct RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short type) { return NULL; }
+struct RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene) { return NULL; }
+void BKE_rigidbody_remove_object(Scene *scene, Object *ob) {}
+void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob) {}
+void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime) {}
+void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle) {}
+void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) {}
+void BKE_rigidbody_rebuild_world(Scene *scene, float ctime) {}
+void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {}
+
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#endif
+
+#endif /* WITH_BULLET */
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
index eb4e0d9c679..6433b73fda0 100644
--- a/source/blender/blenkernel/intern/sca.c
+++ b/source/blender/blenkernel/intern/sca.c
@@ -734,7 +734,7 @@ void sca_move_sensor(bSensor *sens_to_move, Object *ob, int move_up)
}
if (tmp) {
BLI_remlink(&ob->sensors, sens);
- BLI_insertlink(&ob->sensors, tmp, sens);
+ BLI_insertlinkafter(&ob->sensors, tmp, sens);
}
}
}
@@ -778,7 +778,7 @@ void sca_move_controller(bController *cont_to_move, Object *ob, int move_up)
tmp = tmp->next;
}
BLI_remlink(&ob->controllers, cont);
- BLI_insertlink(&ob->controllers, tmp, cont);
+ BLI_insertlinkafter(&ob->controllers, tmp, cont);
}
}
@@ -818,7 +818,7 @@ void sca_move_actuator(bActuator *act_to_move, Object *ob, int move_up)
}
if (tmp) {
BLI_remlink(&ob->actuators, act);
- BLI_insertlink(&ob->actuators, tmp, act);
+ BLI_insertlinkafter(&ob->actuators, tmp, act);
}
}
}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 9bb2fb2de52..d01d7090d96 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -46,6 +46,7 @@
#include "DNA_group_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
+#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
@@ -62,6 +63,7 @@
#include "BKE_colortools.h"
#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
+#include "BKE_freestyle.h"
#include "BKE_global.h"
#include "BKE_group.h"
#include "BKE_idprop.h"
@@ -72,6 +74,7 @@
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pointcache.h"
+#include "BKE_rigidbody.h"
#include "BKE_scene.h"
#include "BKE_sequencer.h"
#include "BKE_world.h"
@@ -138,12 +141,14 @@ static void remove_sequencer_fcurves(Scene *sce)
Scene *BKE_scene_copy(Scene *sce, int type)
{
Scene *scen;
+ SceneRenderLayer *srl, *new_srl;
ToolSettings *ts;
Base *base, *obase;
if (type == SCE_COPY_EMPTY) {
ListBase lb;
- scen = BKE_scene_add(sce->id.name + 2);
+ /* XXX. main should become an arg */
+ scen = BKE_scene_add(G.main, sce->id.name + 2);
lb = scen->r.layers;
scen->r = sce->r;
@@ -170,6 +175,7 @@ Scene *BKE_scene_copy(Scene *sce, int type)
scen->obedit = NULL;
scen->stats = NULL;
scen->fps_info = NULL;
+ scen->rigidbody_world = NULL; /* RB_TODO figure out a way of copying the rigid body world */
BLI_duplicatelist(&(scen->markers), &(sce->markers));
BLI_duplicatelist(&(scen->transform_spaces), &(sce->transform_spaces));
@@ -203,6 +209,13 @@ Scene *BKE_scene_copy(Scene *sce, int type)
/* remove animation used by sequencer */
if (type != SCE_COPY_FULL)
remove_sequencer_fcurves(scen);
+
+ /* copy Freestyle settings */
+ 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);
+ new_srl = new_srl->next;
+ }
}
/* tool settings */
@@ -285,6 +298,10 @@ Scene *BKE_scene_copy(Scene *sce, int type)
void BKE_scene_free(Scene *sce)
{
Base *base;
+ SceneRenderLayer *srl;
+
+ /* check all sequences */
+ BKE_sequencer_clear_scene_in_allseqs(G.main, sce);
base = sce->base.first;
while (base) {
@@ -309,6 +326,9 @@ void BKE_scene_free(Scene *sce)
BKE_free_animdata((ID *)sce);
BKE_keyingsets_free(&sce->keyingsets);
+ if (sce->rigidbody_world)
+ BKE_rigidbody_free_world(sce->rigidbody_world);
+
if (sce->r.avicodecdata) {
free_avicodecdata(sce->r.avicodecdata);
MEM_freeN(sce->r.avicodecdata);
@@ -325,6 +345,10 @@ void BKE_scene_free(Scene *sce)
sce->r.ffcodecdata.properties = NULL;
}
+ for (srl = sce->r.layers.first; srl; srl = srl->next) {
+ BKE_freestyle_config_free(&srl->freestyleConfig);
+ }
+
BLI_freelistN(&sce->markers);
BLI_freelistN(&sce->transform_spaces);
BLI_freelistN(&sce->r.layers);
@@ -352,10 +376,7 @@ void BKE_scene_free(Scene *sce)
sce->toolsettings = NULL;
}
- if (sce->theDag) {
- free_forest(sce->theDag);
- MEM_freeN(sce->theDag);
- }
+ DAG_scene_free(sce);
if (sce->nodetree) {
ntreeFreeTree(sce->nodetree);
@@ -372,9 +393,8 @@ void BKE_scene_free(Scene *sce)
BKE_color_managed_view_settings_free(&sce->view_settings);
}
-Scene *BKE_scene_add(const char *name)
+Scene *BKE_scene_add(Main *bmain, const char *name)
{
- Main *bmain = G.main;
Scene *sce;
ParticleEditSettings *pset;
int a;
@@ -400,6 +420,7 @@ Scene *BKE_scene_add(const char *name)
sce->r.im_format.planes = R_IMF_PLANES_RGB;
sce->r.im_format.imtype = R_IMF_IMTYPE_PNG;
+ sce->r.im_format.depth = R_IMF_CHAN_DEPTH_8;
sce->r.im_format.quality = 90;
sce->r.im_format.compress = 90;
@@ -428,10 +449,12 @@ Scene *BKE_scene_add(const char *name)
sce->r.postsat = 1.0;
sce->r.bake_mode = 1; /* prevent to include render stuff here */
- sce->r.bake_filter = 2;
+ sce->r.bake_filter = 16;
sce->r.bake_osa = 5;
sce->r.bake_flag = R_BAKE_CLEAR;
sce->r.bake_normal_space = R_BAKE_SPACE_TANGENT;
+ sce->r.bake_samples = 256;
+ sce->r.bake_biasdist = 0.001;
sce->r.scemode = R_DOCOMP | R_DOSEQ | R_EXTENSION;
sce->r.stamp = R_STAMP_TIME | R_STAMP_FRAME | R_STAMP_DATE | R_STAMP_CAMERA | R_STAMP_SCENE | R_STAMP_FILENAME | R_STAMP_RENDERTIME;
sce->r.stamp_font_id = 12;
@@ -640,12 +663,11 @@ void BKE_scene_set_background(Main *bmain, Scene *scene)
}
/* sort baselist */
- DAG_scene_sort(bmain, scene);
+ DAG_scene_relations_rebuild(bmain, scene);
/* ensure dags are built for sets */
- for (sce = scene->set; sce; sce = sce->set)
- if (sce->theDag == NULL)
- DAG_scene_sort(bmain, sce);
+ for (sce = scene; sce; sce = sce->set)
+ DAG_scene_relations_update(bmain, sce);
/* copy layers and flags from bases to objects */
for (base = scene->base.first; base; base = base->next) {
@@ -688,9 +710,6 @@ void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce)
if (sce1->set == sce)
sce1->set = NULL;
- /* check all sequences */
- BKE_sequencer_clear_scene_in_allseqs(bmain, sce);
-
/* check render layer nodes in other scenes */
clear_scene_in_nodes(bmain, sce);
@@ -703,7 +722,7 @@ void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce)
}
/* used by metaballs
- * doesnt return the original duplicated object, only dupli's
+ * doesn't return the original duplicated object, only dupli's
*/
int BKE_scene_base_iter_next(Scene **scene, int val, Base **base, Object **ob)
{
@@ -755,7 +774,9 @@ int BKE_scene_base_iter_next(Scene **scene, int val, Base **base, Object **ob)
else {
if (*base && fase != F_DUPLI) {
*base = (*base)->next;
- if (*base) *ob = (*base)->object;
+ if (*base) {
+ *ob = (*base)->object;
+ }
else {
if (fase == F_SCENE) {
/* (*scene) is finished, now do the set */
@@ -772,7 +793,9 @@ int BKE_scene_base_iter_next(Scene **scene, int val, Base **base, Object **ob)
}
}
- if (*base == NULL) fase = F_START;
+ if (*base == NULL) {
+ fase = F_START;
+ }
else {
if (fase != F_DUPLI) {
if ( (*base)->object->transflag & OB_DUPLI) {
@@ -928,6 +951,18 @@ Base *BKE_scene_base_add(Scene *sce, Object *ob)
return b;
}
+void BKE_scene_base_unlink(Scene *sce, Base *base)
+{
+ /* remove rigid body constraint from world before removing object */
+ if (base->object->rigidbody_constraint)
+ BKE_rigidbody_remove_constraint(sce, base->object);
+ /* remove rigid body object from world before removing object */
+ if (base->object->rigidbody_object)
+ BKE_rigidbody_remove_object(sce, base->object);
+
+ BLI_remlink(&sce->base, base);
+}
+
void BKE_scene_base_deselect_all(Scene *sce)
{
Base *b;
@@ -1023,10 +1058,68 @@ static void scene_update_drivers(Main *UNUSED(bmain), Scene *scene)
}
}
-static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scene_parent)
+/* deps hack - do extra recalcs at end */
+static void scene_depsgraph_hack(Scene *scene, Scene *scene_parent)
{
Base *base;
+
+ scene->customdata_mask = scene_parent->customdata_mask;
+
+ /* sets first, we allow per definition current scene to have
+ * dependencies on sets, but not the other way around. */
+ if (scene->set)
+ scene_depsgraph_hack(scene->set, scene_parent);
+ for (base = scene->base.first; base; base = base->next) {
+ Object *ob = base->object;
+
+ if (ob->depsflag) {
+ int recalc = 0;
+ // printf("depshack %s\n", ob->id.name + 2);
+
+ if (ob->depsflag & OB_DEPS_EXTRA_OB_RECALC)
+ recalc |= OB_RECALC_OB;
+ if (ob->depsflag & OB_DEPS_EXTRA_DATA_RECALC)
+ recalc |= OB_RECALC_DATA;
+
+ ob->recalc |= recalc;
+ BKE_object_handle_update(scene_parent, ob);
+
+ if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP)) {
+ GroupObject *go;
+
+ for (go = ob->dup_group->gobject.first; go; go = go->next) {
+ if (go->ob)
+ go->ob->recalc |= recalc;
+ }
+ group_handle_recalc_and_update(scene_parent, ob, ob->dup_group);
+ }
+ }
+ }
+
+}
+
+static void scene_rebuild_rbw_recursive(Scene *scene, float ctime)
+{
+ if (scene->set)
+ scene_rebuild_rbw_recursive(scene->set, ctime);
+
+ if (BKE_scene_check_rigidbody_active(scene))
+ BKE_rigidbody_rebuild_world(scene, ctime);
+}
+
+static void scene_do_rb_simulation_recursive(Scene *scene, float ctime)
+{
+ if (scene->set)
+ scene_do_rb_simulation_recursive(scene->set, ctime);
+
+ if (BKE_scene_check_rigidbody_active(scene))
+ BKE_rigidbody_do_simulation(scene, ctime);
+}
+
+static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scene_parent)
+{
+ Base *base;
scene->customdata_mask = scene_parent->customdata_mask;
@@ -1039,7 +1132,7 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen
for (base = scene->base.first; base; base = base->next) {
Object *ob = base->object;
- BKE_object_handle_update(scene_parent, ob);
+ BKE_object_handle_update_ex(scene_parent, ob, scene->rigidbody_world);
if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP))
group_handle_recalc_and_update(scene_parent, ob, ob->dup_group);
@@ -1058,14 +1151,21 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen
/* update masking curves */
BKE_mask_update_scene(bmain, scene, FALSE);
+
}
/* this is called in main loop, doing tagged updates before redraw */
void BKE_scene_update_tagged(Main *bmain, Scene *scene)
{
+ Scene *sce_iter;
+
/* 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)
+ DAG_scene_relations_update(bmain, sce_iter);
+
/* flush recalc flags to dependencies */
DAG_ids_flush_tagged(bmain);
@@ -1106,6 +1206,12 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay)
{
float ctime = BKE_scene_frame_get(sce);
Scene *sce_iter;
+
+ /* 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);
/* keep this first */
BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_PRE);
@@ -1116,10 +1222,8 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay)
/* clear animation overrides */
/* XXX TODO... */
- for (sce_iter = sce; sce_iter; sce_iter = sce_iter->set) {
- if (sce_iter->theDag == NULL)
- DAG_scene_sort(bmain, sce_iter);
- }
+ 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
@@ -1139,7 +1243,7 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay)
* such as Scene->World->MTex/Texture) can still get correctly overridden.
*/
BKE_animsys_evaluate_all_animation(bmain, sce, ctime);
- /*...done with recusrive funcs */
+ /*...done with recursive funcs */
/* clear "LIB_DOIT" flag from all materials, to prevent infinite recursion problems later
* when trying to find materials with drivers that need evaluating [#32017]
@@ -1147,9 +1251,15 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay)
tag_main_idcode(bmain, ID_MA, FALSE);
tag_main_idcode(bmain, ID_LA, FALSE);
+ /* 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);
+
/* BKE_object_handle_update() on all objects, groups and sets */
scene_update_tagged_recursive(bmain, sce, sce);
+ scene_depsgraph_hack(sce, sce);
+
/* 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);
@@ -1177,6 +1287,7 @@ SceneRenderLayer *BKE_scene_add_render_layer(Scene *sce, const char *name)
srl->lay = (1 << 20) - 1;
srl->layflag = 0x7FFF; /* solid ztra halo edge strand */
srl->passflag = SCE_PASS_COMBINED | SCE_PASS_Z;
+ BKE_freestyle_config_init(&srl->freestyleConfig);
return srl;
}
@@ -1324,3 +1435,8 @@ int BKE_scene_check_color_management_enabled(const Scene *scene)
{
return strcmp(scene->display_settings.display_device, "None") != 0;
}
+
+int BKE_scene_check_rigidbody_active(const Scene *scene)
+{
+ return scene && scene->rigidbody_world && scene->rigidbody_world->group && !(scene->rigidbody_world->flag & RBW_FLAG_MUTED);
+}
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 56fddfdaa2b..01f57b95378 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -167,6 +167,7 @@ ARegion *BKE_area_region_copy(SpaceType *st, ARegion *ar)
newar->prev = newar->next = NULL;
newar->handlers.first = newar->handlers.last = NULL;
newar->uiblocks.first = newar->uiblocks.last = NULL;
+ newar->ui_lists.first = newar->ui_lists.last = NULL;
newar->swinid = 0;
/* use optional regiondata callback */
@@ -279,6 +280,7 @@ void BKE_area_region_free(SpaceType *st, ARegion *ar)
}
BLI_freelistN(&ar->panels);
+ BLI_freelistN(&ar->ui_lists);
}
/* not area itself */
@@ -353,6 +355,20 @@ ARegion *BKE_area_find_region_type(ScrArea *sa, int type)
return NULL;
}
+ARegion *BKE_area_find_region_active_win(ScrArea *sa)
+{
+ if (sa) {
+ ARegion *ar = BLI_findlink(&sa->regionbase, sa->region_active_win);
+ if (ar && (ar->regiontype == RGN_TYPE_WINDOW)) {
+ return ar;
+ }
+
+ /* fallback to any */
+ return BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ }
+ return NULL;
+}
+
/* note, using this function is generally a last resort, you really want to be
* using the context when you can - campbell
* -1 for any type */
diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c
index e3f0226c863..978c1a7c9b0 100644
--- a/source/blender/blenkernel/intern/seqcache.c
+++ b/source/blender/blenkernel/intern/seqcache.c
@@ -26,7 +26,6 @@
* \ingroup bke
*/
-
#include <stddef.h>
#include "BLO_sys_types.h" /* for intptr_t */
@@ -34,7 +33,6 @@
#include "MEM_guardedalloc.h"
#include "DNA_sequence_types.h"
-#include "BKE_sequencer.h"
#include "IMB_moviecache.h"
#include "IMB_imbuf.h"
@@ -42,6 +40,8 @@
#include "BLI_listbase.h"
+#include "BKE_sequencer.h"
+
typedef struct SeqCacheKey {
struct Sequence *seq;
SeqRenderData context;
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index 3bff209f53c..a1dc19e1ff7 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -156,42 +156,43 @@ static void init_alpha_over_or_under(Sequence *seq)
seq->seq1 = seq2;
}
-static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y, char *rect1, char *rect2, char *out)
+static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
{
- int fac2, mfac, fac, fac4;
- int xo, tempc;
- char *rt1, *rt2, *rt;
+ float fac2, mfac, fac, fac4;
+ int xo;
+ unsigned char *cp1, *cp2, *rt;
+ float tempc[4], rt1[4], rt2[4];
xo = x;
- rt1 = (char *) rect1;
- rt2 = (char *) rect2;
- rt = (char *) out;
+ cp1 = rect1;
+ cp2 = rect2;
+ rt = out;
- fac2 = (int) (256.0f * facf0);
- fac4 = (int) (256.0f * facf1);
+ fac2 = facf0;
+ fac4 = facf1;
while (y--) {
x = xo;
while (x--) {
-
/* rt = rt1 over rt2 (alpha from rt1) */
+ straight_uchar_to_premul_float(rt1, cp1);
+ straight_uchar_to_premul_float(rt2, cp2);
+
fac = fac2;
- mfac = 256 - ( (fac2 * rt1[3]) >> 8);
+ mfac = 1.0f - fac2 * rt1[3];
- if (fac == 0) *( (unsigned int *) rt) = *( (unsigned int *) rt2);
- else if (mfac == 0) *( (unsigned int *) rt) = *( (unsigned int *) rt1);
+ if (fac <= 0.0f) *((unsigned int *) rt) = *((unsigned int *) cp2);
+ else if (mfac <= 0.0f) *((unsigned int *) rt) = *((unsigned int *) cp1);
else {
- tempc = (fac * rt1[0] + mfac * rt2[0]) >> 8;
- if (tempc > 255) rt[0] = 255; else rt[0] = tempc;
- tempc = (fac * rt1[1] + mfac * rt2[1]) >> 8;
- if (tempc > 255) rt[1] = 255; else rt[1] = tempc;
- tempc = (fac * rt1[2] + mfac * rt2[2]) >> 8;
- if (tempc > 255) rt[2] = 255; else rt[2] = tempc;
- tempc = (fac * rt1[3] + mfac * rt2[3]) >> 8;
- if (tempc > 255) rt[3] = 255; else rt[3] = tempc;
+ tempc[0] = fac * rt1[0] + mfac * rt2[0];
+ tempc[1] = fac * rt1[1] + mfac * rt2[1];
+ tempc[2] = fac * rt1[2] + mfac * rt2[2];
+ tempc[3] = fac * rt1[3] + mfac * rt2[3];
+
+ premul_float_to_straight_uchar(rt, tempc);
}
- rt1 += 4; rt2 += 4; rt += 4;
+ cp1 += 4; cp2 += 4; rt += 4;
}
if (y == 0) break;
@@ -199,22 +200,23 @@ static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y, ch
x = xo;
while (x--) {
+ straight_uchar_to_premul_float(rt1, cp1);
+ straight_uchar_to_premul_float(rt2, cp2);
+
fac = fac4;
- mfac = 256 - ( (fac4 * rt1[3]) >> 8);
+ mfac = 1.0f - (fac4 * rt1[3]);
- if (fac == 0) *( (unsigned int *) rt) = *( (unsigned int *) rt2);
- else if (mfac == 0) *( (unsigned int *) rt) = *( (unsigned int *) rt1);
+ if (fac <= 0.0f) *((unsigned int *) rt) = *((unsigned int *) cp2);
+ else if (mfac <= 0.0f) *((unsigned int *) rt) = *((unsigned int *) cp1);
else {
- tempc = (fac * rt1[0] + mfac * rt2[0]) >> 8;
- if (tempc > 255) rt[0] = 255; else rt[0] = tempc;
- tempc = (fac * rt1[1] + mfac * rt2[1]) >> 8;
- if (tempc > 255) rt[1] = 255; else rt[1] = tempc;
- tempc = (fac * rt1[2] + mfac * rt2[2]) >> 8;
- if (tempc > 255) rt[2] = 255; else rt[2] = tempc;
- tempc = (fac * rt1[3] + mfac * rt2[3]) >> 8;
- if (tempc > 255) rt[3] = 255; else rt[3] = tempc;
+ tempc[0] = fac * rt1[0] + mfac * rt2[0];
+ tempc[1] = fac * rt1[1] + mfac * rt2[1];
+ tempc[2] = fac * rt1[2] + mfac * rt2[2];
+ tempc[3] = fac * rt1[3] + mfac * rt2[3];
+
+ premul_float_to_straight_uchar(rt, tempc);
}
- rt1 += 4; rt2 += 4; rt += 4;
+ cp1 += 4; cp2 += 4; rt += 4;
}
}
}
@@ -298,17 +300,17 @@ static void do_alphaover_effect(SeqRenderData context, Sequence *UNUSED(seq), fl
slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_alphaover_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
+ do_alphaover_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
}
}
/*********************** Alpha Under *************************/
-static void do_alphaunder_effect_byte(float facf0, float facf1, int x, int y, char *rect1, char *rect2, char *out)
+static void do_alphaunder_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
{
int fac2, mfac, fac, fac4;
int xo;
- char *rt1, *rt2, *rt;
+ unsigned char *rt1, *rt2, *rt;
xo = x;
rt1 = rect1;
@@ -326,13 +328,13 @@ static void do_alphaunder_effect_byte(float facf0, float facf1, int x, int y, ch
/* this complex optimization is because the
* 'skybuf' can be crossed in
*/
- if (rt2[3] == 0 && fac2 == 256) *( (unsigned int *) rt) = *( (unsigned int *) rt1);
- else if (rt2[3] == 255) *( (unsigned int *) rt) = *( (unsigned int *) rt2);
+ if (rt2[3] == 0 && fac2 == 256) *((unsigned int *) rt) = *((unsigned int *) rt1);
+ else if (rt2[3] == 255) *((unsigned int *) rt) = *((unsigned int *) rt2);
else {
mfac = rt2[3];
fac = (fac2 * (256 - mfac)) >> 8;
- if (fac == 0) *( (unsigned int *) rt) = *( (unsigned int *) rt2);
+ if (fac == 0) *((unsigned int *) rt) = *((unsigned int *) rt2);
else {
rt[0] = (fac * rt1[0] + mfac * rt2[0]) >> 8;
rt[1] = (fac * rt1[1] + mfac * rt2[1]) >> 8;
@@ -349,13 +351,13 @@ static void do_alphaunder_effect_byte(float facf0, float facf1, int x, int y, ch
x = xo;
while (x--) {
- if (rt2[3] == 0 && fac4 == 256) *( (unsigned int *) rt) = *( (unsigned int *) rt1);
- else if (rt2[3] == 255) *( (unsigned int *) rt) = *( (unsigned int *) rt2);
+ if (rt2[3] == 0 && fac4 == 256) *((unsigned int *) rt) = *((unsigned int *) rt1);
+ else if (rt2[3] == 255) *((unsigned int *) rt) = *((unsigned int *) rt2);
else {
mfac = rt2[3];
fac = (fac4 * (256 - mfac)) >> 8;
- if (fac == 0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+ if (fac == 0) *((unsigned int *)rt) = *((unsigned int *)rt2);
else {
rt[0] = (fac * rt1[0] + mfac * rt2[0]) >> 8;
rt[1] = (fac * rt1[1] + mfac * rt2[1]) >> 8;
@@ -460,17 +462,17 @@ static void do_alphaunder_effect(SeqRenderData context, Sequence *UNUSED(seq), f
slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_alphaunder_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
+ do_alphaunder_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
}
}
/*********************** Cross *************************/
-static void do_cross_effect_byte(float facf0, float facf1, int x, int y, char *rect1, char *rect2, char *out)
+static void do_cross_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
{
int fac1, fac2, fac3, fac4;
int xo;
- char *rt1, *rt2, *rt;
+ unsigned char *rt1, *rt2, *rt;
xo = x;
rt1 = rect1;
@@ -570,7 +572,7 @@ static void do_cross_effect(SeqRenderData context, Sequence *UNUSED(seq), float
slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_cross_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
+ do_cross_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
}
}
@@ -680,7 +682,7 @@ static void gamtabs(float gamma)
}
/* inverse gamtab1 : in byte, out short */
for (a = 1; a <= 256; a++) {
- if (gamma == 2.0f) igamtab1[a - 1] = a * a - 1;
+ if (gamma == 2.0f) igamtab1[a - 1] = a * a - 1;
else if (gamma == 1.0f) igamtab1[a - 1] = 256 * a - 1;
else {
val = a / 256.0f;
@@ -713,31 +715,32 @@ static void free_gammacross(Sequence *UNUSED(seq))
static void do_gammacross_effect_byte(float facf0, float UNUSED(facf1), int x, int y, unsigned char *rect1,
unsigned char *rect2, unsigned char *out)
{
- int fac1, fac2, col;
+ float fac1, fac2;
int xo;
- unsigned char *rt1, *rt2, *rt;
-
+ unsigned char *cp1, *cp2, *rt;
+ float rt1[4], rt2[4], tempc[4];
+
xo = x;
- rt1 = (unsigned char *) rect1;
- rt2 = (unsigned char *) rect2;
- rt = (unsigned char *) out;
+ cp1 = rect1;
+ cp2 = rect2;
+ rt = out;
- fac2 = (int)(256.0f * facf0);
- fac1 = 256 - fac2;
+ fac2 = facf0;
+ fac1 = 1.0f - fac2;
while (y--) {
x = xo;
while (x--) {
- col = (fac1 * igamtab1[rt1[0]] + fac2 * igamtab1[rt2[0]]) >> 8;
- if (col > 65535) rt[0] = 255; else rt[0] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
- col = (fac1 * igamtab1[rt1[1]] + fac2 * igamtab1[rt2[1]]) >> 8;
- if (col > 65535) rt[1] = 255; else rt[1] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
- col = (fac1 * igamtab1[rt1[2]] + fac2 * igamtab1[rt2[2]]) >> 8;
- if (col > 65535) rt[2] = 255; else rt[2] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
- col = (fac1 * igamtab1[rt1[3]] + fac2 * igamtab1[rt2[3]]) >> 8;
- if (col > 65535) rt[3] = 255; else rt[3] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
+ straight_uchar_to_premul_float(rt1, cp1);
+ straight_uchar_to_premul_float(rt2, cp2);
- rt1 += 4; rt2 += 4; rt += 4;
+ tempc[0] = gammaCorrect(fac1 * invGammaCorrect(rt1[0]) + fac2 * invGammaCorrect(rt2[0]));
+ tempc[1] = gammaCorrect(fac1 * invGammaCorrect(rt1[1]) + fac2 * invGammaCorrect(rt2[1]));
+ tempc[2] = gammaCorrect(fac1 * invGammaCorrect(rt1[2]) + fac2 * invGammaCorrect(rt2[2]));
+ tempc[3] = gammaCorrect(fac1 * invGammaCorrect(rt1[3]) + fac2 * invGammaCorrect(rt2[3]));
+
+ premul_float_to_straight_uchar(rt, tempc);
+ cp1 += 4; cp2 += 4; rt += 4;
}
if (y == 0)
@@ -746,16 +749,16 @@ static void do_gammacross_effect_byte(float facf0, float UNUSED(facf1), int x,
x = xo;
while (x--) {
- col = (fac1 * igamtab1[rt1[0]] + fac2 * igamtab1[rt2[0]]) >> 8;
- if (col > 65535) rt[0] = 255; else rt[0] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
- col = (fac1 * igamtab1[rt1[1]] + fac2 * igamtab1[rt2[1]]) >> 8;
- if (col > 65535) rt[1] = 255; else rt[1] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
- col = (fac1 * igamtab1[rt1[2]] + fac2 * igamtab1[rt2[2]]) >> 8;
- if (col > 65535) rt[2] = 255; else rt[2] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
- col = (fac1 * igamtab1[rt1[3]] + fac2 * igamtab1[rt2[3]]) >> 8;
- if (col > 65535) rt[3] = 255; else rt[3] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
+ straight_uchar_to_premul_float(rt1, cp1);
+ straight_uchar_to_premul_float(rt2, cp2);
- rt1 += 4; rt2 += 4; rt += 4;
+ tempc[0] = gammaCorrect(fac1 * invGammaCorrect(rt1[0]) + fac2 * invGammaCorrect(rt2[0]));
+ tempc[1] = gammaCorrect(fac1 * invGammaCorrect(rt1[1]) + fac2 * invGammaCorrect(rt2[1]));
+ tempc[2] = gammaCorrect(fac1 * invGammaCorrect(rt1[2]) + fac2 * invGammaCorrect(rt2[2]));
+ tempc[3] = gammaCorrect(fac1 * invGammaCorrect(rt1[3]) + fac2 * invGammaCorrect(rt2[3]));
+
+ premul_float_to_straight_uchar(rt, tempc);
+ cp1 += 4; cp2 += 4; rt += 4;
}
}
}
@@ -828,31 +831,34 @@ static void do_gammacross_effect(SeqRenderData context, Sequence *UNUSED(seq), f
static void do_add_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2,
unsigned char *out)
{
- int col, xo, fac1, fac3;
- char *rt1, *rt2, *rt;
+ int xo;
+ unsigned char *cp1, *cp2, *rt;
+ float fac1, fac3;
+ float tempc[4], rt1[4], rt2[4];
xo = x;
- rt1 = (char *)rect1;
- rt2 = (char *)rect2;
- rt = (char *)out;
+ cp1 = rect1;
+ cp2 = rect2;
+ rt = out;
- fac1 = (int)(256.0f * facf0);
- fac3 = (int)(256.0f * facf1);
+ fac1 = facf0;
+ fac3 = facf1;
while (y--) {
x = xo;
while (x--) {
- col = rt1[0] + ((fac1 * rt2[0]) >> 8);
- if (col > 255) rt[0] = 255; else rt[0] = col;
- col = rt1[1] + ((fac1 * rt2[1]) >> 8);
- if (col > 255) rt[1] = 255; else rt[1] = col;
- col = rt1[2] + ((fac1 * rt2[2]) >> 8);
- if (col > 255) rt[2] = 255; else rt[2] = col;
- col = rt1[3] + ((fac1 * rt2[3]) >> 8);
- if (col > 255) rt[3] = 255; else rt[3] = col;
+ straight_uchar_to_premul_float(rt1, cp1);
+ straight_uchar_to_premul_float(rt2, cp2);
- rt1 += 4; rt2 += 4; rt += 4;
+ tempc[0] = rt1[0] + fac1 * rt2[0];
+ tempc[1] = rt1[1] + fac1 * rt2[1];
+ tempc[2] = rt1[2] + fac1 * rt2[2];
+ tempc[3] = min_ff(1.0f, rt1[3] + fac1 * rt2[3]);
+
+ premul_float_to_straight_uchar(rt, tempc);
+
+ cp1 += 4; cp2 += 4; rt += 4;
}
if (y == 0)
@@ -861,16 +867,17 @@ static void do_add_effect_byte(float facf0, float facf1, int x, int y, unsigned
x = xo;
while (x--) {
- col = rt1[0] + ((fac3 * rt2[0]) >> 8);
- if (col > 255) rt[0] = 255; else rt[0] = col;
- col = rt1[1] + ((fac3 * rt2[1]) >> 8);
- if (col > 255) rt[1] = 255; else rt[1] = col;
- col = rt1[2] + ((fac3 * rt2[2]) >> 8);
- if (col > 255) rt[2] = 255; else rt[2] = col;
- col = rt1[3] + ((fac3 * rt2[3]) >> 8);
- if (col > 255) rt[3] = 255; else rt[3] = col;
+ straight_uchar_to_premul_float(rt1, cp1);
+ straight_uchar_to_premul_float(rt2, cp2);
- rt1 += 4; rt2 += 4; rt += 4;
+ tempc[0] = rt1[0] + fac3 * rt2[0];
+ tempc[1] = rt1[1] + fac3 * rt2[1];
+ tempc[2] = rt1[2] + fac3 * rt2[2];
+ tempc[3] = min_ff(1.0f, rt1[3] + fac3 * rt2[3]);
+
+ premul_float_to_straight_uchar(rt, tempc);
+
+ cp1 += 4; cp2 += 4; rt += 4;
}
}
}
@@ -890,22 +897,28 @@ static void do_add_effect_float(float facf0, float facf1, int x, int y, float *r
fac3 = facf1;
while (y--) {
- x = xo * 4;
+ x = xo;
while (x--) {
- *rt = *rt1 + fac1 * (*rt2);
+ rt[0] = rt1[0] + fac1 * rt2[0];
+ rt[1] = rt1[1] + fac1 * rt2[1];
+ rt[2] = rt1[2] + fac1 * rt2[2];
+ rt[3] = min_ff(1.0f, rt1[3] + fac1 * rt2[3]);
- rt1++; rt2++; rt++;
+ rt1 += 4; rt2 += 4; rt += 4;
}
if (y == 0)
break;
y--;
- x = xo * 4;
+ x = xo;
while (x--) {
- *rt = *rt1 + fac3 * (*rt2);
+ rt[0] = rt1[0] + fac1 * rt2[0];
+ rt[1] = rt1[1] + fac1 * rt2[1];
+ rt[2] = rt1[2] + fac1 * rt2[2];
+ rt[3] = min_ff(1.0f, rt1[3] + fac3 * rt2[3]);
- rt1++; rt2++; rt++;
+ rt1 += 4; rt2 += 4; rt += 4;
}
}
}
@@ -931,32 +944,35 @@ static void do_add_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN
/*********************** Sub *************************/
-static void do_sub_effect_byte(float facf0, float facf1, int x, int y, char *rect1, char *rect2, char *out)
+static void do_sub_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
{
- int col, xo, fac1, fac3;
- char *rt1, *rt2, *rt;
+ int xo;
+ unsigned char *cp1, *cp2, *rt;
+ float fac1, fac3;
+ float tempc[4], rt1[4], rt2[4];
xo = x;
- rt1 = (char *) rect1;
- rt2 = (char *) rect2;
- rt = (char *) out;
+ cp1 = rect1;
+ cp2 = rect2;
+ rt = out;
- fac1 = (int) (256.0f * facf0);
- fac3 = (int) (256.0f * facf1);
+ fac1 = facf0;
+ fac3 = facf1;
while (y--) {
x = xo;
while (x--) {
- col = rt1[0] - ((fac1 * rt2[0]) >> 8);
- if (col < 0) rt[0] = 0; else rt[0] = col;
- col = rt1[1] - ((fac1 * rt2[1]) >> 8);
- if (col < 0) rt[1] = 0; else rt[1] = col;
- col = rt1[2] - ((fac1 * rt2[2]) >> 8);
- if (col < 0) rt[2] = 0; else rt[2] = col;
- col = rt1[3] - ((fac1 * rt2[3]) >> 8);
- if (col < 0) rt[3] = 0; else rt[3] = col;
+ straight_uchar_to_premul_float(rt1, cp1);
+ straight_uchar_to_premul_float(rt2, cp2);
- rt1 += 4; rt2 += 4; rt += 4;
+ tempc[0] = rt1[0] - fac1 * rt2[0];
+ tempc[1] = rt1[1] - fac1 * rt2[1];
+ tempc[2] = rt1[2] - fac1 * rt2[2];
+ tempc[3] = rt1[3] - fac1 * rt2[3];
+
+ premul_float_to_straight_uchar(rt, tempc);
+
+ cp1 += 4; cp2 += 4; rt += 4;
}
if (y == 0)
@@ -965,16 +981,17 @@ static void do_sub_effect_byte(float facf0, float facf1, int x, int y, char *rec
x = xo;
while (x--) {
- col = rt1[0] - ((fac3 * rt2[0]) >> 8);
- if (col < 0) rt[0] = 0; else rt[0] = col;
- col = rt1[1] - ((fac3 * rt2[1]) >> 8);
- if (col < 0) rt[1] = 0; else rt[1] = col;
- col = rt1[2] - ((fac3 * rt2[2]) >> 8);
- if (col < 0) rt[2] = 0; else rt[2] = col;
- col = rt1[3] - ((fac3 * rt2[3]) >> 8);
- if (col < 0) rt[3] = 0; else rt[3] = col;
+ straight_uchar_to_premul_float(rt1, cp1);
+ straight_uchar_to_premul_float(rt2, cp2);
- rt1 += 4; rt2 += 4; rt += 4;
+ tempc[0] = rt1[0] - fac3 * rt2[0];
+ tempc[1] = rt1[1] - fac3 * rt2[1];
+ tempc[2] = rt1[2] - fac3 * rt2[2];
+ tempc[3] = rt1[3] - fac3 * rt2[3];
+
+ premul_float_to_straight_uchar(rt, tempc);
+
+ cp1 += 4; cp2 += 4; rt += 4;
}
}
}
@@ -1029,7 +1046,7 @@ static void do_sub_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN
slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_sub_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
+ do_sub_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
}
}
@@ -1039,10 +1056,10 @@ static void do_sub_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN
#define XOFF 8
#define YOFF 8
-static void do_drop_effect_byte(float facf0, float facf1, int x, int y, char *rect2i, char *rect1i, char *outi)
+static void do_drop_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect2i, unsigned char *rect1i, unsigned char *outi)
{
int height, width, temp, fac, fac1, fac2;
- char *rt1, *rt2, *out;
+ unsigned char *rt1, *rt2, *out;
int field = 1;
width = x;
@@ -1051,9 +1068,9 @@ static void do_drop_effect_byte(float facf0, float facf1, int x, int y, char *re
fac1 = (int) (70.0f * facf0);
fac2 = (int) (70.0f * facf1);
- rt2 = (char *) (rect2i + YOFF * width);
- rt1 = (char *) rect1i;
- out = (char *) outi;
+ rt2 = (unsigned char *) (rect2i + YOFF * width);
+ rt1 = (unsigned char *) rect1i;
+ out = (unsigned char *) outi;
for (y = 0; y < height - YOFF; y++) {
if (field) fac = fac1;
else fac = fac2;
@@ -1122,18 +1139,18 @@ static void do_mul_effect_byte(float facf0, float facf1, int x, int y, unsigned
unsigned char *out)
{
int xo, fac1, fac3;
- char *rt1, *rt2, *rt;
+ unsigned char *rt1, *rt2, *rt;
xo = x;
- rt1 = (char *)rect1;
- rt2 = (char *)rect2;
- rt = (char *)out;
+ rt1 = rect1;
+ rt2 = rect2;
+ rt = out;
fac1 = (int)(256.0f * facf0);
fac3 = (int)(256.0f * facf1);
/* formula:
- * fac * (a * b) + (1-fac)*a => fac * a * (b - 1) + axaux = c * px + py * s; //+centx
+ * fac * (a * b) + (1 - fac) * a => fac * a * (b - 1) + axaux = c * px + py * s; //+centx
* yaux = -s * px + c * py; //+centy
*/
@@ -1300,7 +1317,8 @@ static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float f
switch (wipe->wipetype) {
case DO_SINGLE_WIPE:
- width = wipezone->width;
+ width = min_ii(wipezone->width, facf0 * yo);
+ width = min_ii(width, yo - facf0 * yo);
if (angle == 0.0f) {
b1 = posy;
@@ -1539,13 +1557,13 @@ static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1),
WipeZone wipezone;
WipeVars *wipe = (WipeVars *)seq->effectdata;
int xo, yo;
- char *rt1, *rt2, *rt;
+ unsigned char *cp1, *cp2, *rt;
precalc_wipe_zone(&wipezone, wipe, x, y);
- rt1 = (char *)rect1;
- rt2 = (char *)rect2;
- rt = (char *)out;
+ cp1 = rect1;
+ cp2 = rect2;
+ rt = out;
xo = x;
yo = y;
@@ -1553,11 +1571,18 @@ static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1),
for (x = 0; x < xo; x++) {
float check = check_zone(&wipezone, x, y, seq, facf0);
if (check) {
- if (rt1) {
- rt[0] = (int)(rt1[0] * check) + (int)(rt2[0] * (1 - check));
- rt[1] = (int)(rt1[1] * check) + (int)(rt2[1] * (1 - check));
- rt[2] = (int)(rt1[2] * check) + (int)(rt2[2] * (1 - check));
- rt[3] = (int)(rt1[3] * check) + (int)(rt2[3] * (1 - check));
+ if (cp1) {
+ float rt1[4], rt2[4], tempc[4];
+
+ straight_uchar_to_premul_float(rt1, cp1);
+ straight_uchar_to_premul_float(rt2, cp2);
+
+ tempc[0] = rt1[0] * check + rt2[0] * (1 - check);
+ tempc[1] = rt1[1] * check + rt2[1] * (1 - check);
+ tempc[2] = rt1[2] * check + rt2[2] * (1 - check);
+ tempc[3] = rt1[3] * check + rt2[3] * (1 - check);
+
+ premul_float_to_straight_uchar(rt, tempc);
}
else {
rt[0] = 0;
@@ -1567,11 +1592,11 @@ static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1),
}
}
else {
- if (rt2) {
- rt[0] = rt2[0];
- rt[1] = rt2[1];
- rt[2] = rt2[2];
- rt[3] = rt2[3];
+ if (cp2) {
+ rt[0] = cp2[0];
+ rt[1] = cp2[1];
+ rt[2] = cp2[2];
+ rt[3] = cp2[3];
}
else {
rt[0] = 0;
@@ -1582,11 +1607,11 @@ static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1),
}
rt += 4;
- if (rt1 != NULL) {
- rt1 += 4;
+ if (cp1 != NULL) {
+ cp1 += 4;
}
- if (rt2 != NULL) {
- rt2 += 4;
+ if (cp2 != NULL) {
+ cp2 += 4;
}
}
}
@@ -1803,166 +1828,6 @@ static ImBuf *do_transform_effect(SeqRenderData context, Sequence *seq, float UN
/*********************** Glow *************************/
-static void RVBlurBitmap2_byte(unsigned char *map, int width, int height, float blur, int quality)
-/* MUUUCCH better than the previous blur. */
-/* We do the blurring in two passes which is a whole lot faster. */
-/* I changed the math arount to implement an actual Gaussian */
-/* distribution. */
-/* */
-/* Watch out though, it tends to misbehaven with large blur values on */
-/* a small bitmap. Avoid avoid avoid. */
-/*=============================== */
-{
- unsigned char *temp = NULL, *swap;
- float *filter = NULL;
- int x, y, i, fx, fy;
- int index, ix, halfWidth;
- float fval, k, curColor[3], curColor2[3], weight = 0;
-
- /* If we're not really blurring, bail out */
- if (blur <= 0)
- return;
-
- /*Allocate memory for the tempmap and the blur filter matrix */
- temp = MEM_mallocN((width * height * 4), "blurbitmaptemp");
- if (!temp)
- return;
-
- /*Allocate memory for the filter elements */
- halfWidth = ((quality + 1) * blur);
- filter = (float *)MEM_mallocN(sizeof(float) * halfWidth * 2, "blurbitmapfilter");
- if (!filter) {
- MEM_freeN(temp);
- return;
- }
-
- /* Apparently we're calculating a bell curve based on the standard deviation (or radius)
- * This code is based on an example posted to comp.graphics.algorithms by
- * Blancmange (bmange@airdmhor.gen.nz)
- */
-
- k = -1.0f / (2.0f * (float)M_PI * blur * blur);
- for (ix = 0; ix < halfWidth; ix++) {
- weight = (float)exp(k * (ix * ix));
- filter[halfWidth - ix] = weight;
- filter[halfWidth + ix] = weight;
- }
- filter[0] = weight;
-
- /* Normalize the array */
- fval = 0;
- for (ix = 0; ix < halfWidth * 2; ix++)
- fval += filter[ix];
-
- for (ix = 0; ix < halfWidth * 2; ix++)
- filter[ix] /= fval;
-
- /* Blur the rows */
- for (y = 0; y < height; y++) {
- /* Do the left & right strips */
- for (x = 0; x < halfWidth; x++) {
- index = (x + y * width) * 4;
- fx = 0;
- zero_v3(curColor);
- zero_v3(curColor2);
-
- for (i = x - halfWidth; i < x + halfWidth; i++) {
- if ((i >= 0) && (i < width)) {
- curColor[0] += map[(i + y * width) * 4 + GlowR] * filter[fx];
- curColor[1] += map[(i + y * width) * 4 + GlowG] * filter[fx];
- curColor[2] += map[(i + y * width) * 4 + GlowB] * filter[fx];
-
- curColor2[0] += map[(width - 1 - i + y * width) * 4 + GlowR] * filter[fx];
- curColor2[1] += map[(width - 1 - i + y * width) * 4 + GlowG] * filter[fx];
- curColor2[2] += map[(width - 1 - i + y * width) * 4 + GlowB] * filter[fx];
- }
- fx++;
- }
- temp[index + GlowR] = curColor[0];
- temp[index + GlowG] = curColor[1];
- temp[index + GlowB] = curColor[2];
-
- temp[((width - 1 - x + y * width) * 4) + GlowR] = curColor2[0];
- temp[((width - 1 - x + y * width) * 4) + GlowG] = curColor2[1];
- temp[((width - 1 - x + y * width) * 4) + GlowB] = curColor2[2];
-
- }
-
- /* Do the main body */
- for (x = halfWidth; x < width - halfWidth; x++) {
- index = (x + y * width) * 4;
- fx = 0;
- zero_v3(curColor);
- for (i = x - halfWidth; i < x + halfWidth; i++) {
- curColor[0] += map[(i + y * width) * 4 + GlowR] * filter[fx];
- curColor[1] += map[(i + y * width) * 4 + GlowG] * filter[fx];
- curColor[2] += map[(i + y * width) * 4 + GlowB] * filter[fx];
- fx++;
- }
- temp[index + GlowR] = curColor[0];
- temp[index + GlowG] = curColor[1];
- temp[index + GlowB] = curColor[2];
- }
- }
-
- /* Swap buffers */
- swap = temp; temp = map; map = swap;
-
- /* Blur the columns */
- for (x = 0; x < width; x++) {
- /* Do the top & bottom strips */
- for (y = 0; y < halfWidth; y++) {
- index = (x + y * width) * 4;
- fy = 0;
- zero_v3(curColor);
- zero_v3(curColor2);
- for (i = y - halfWidth; i < y + halfWidth; i++) {
- if ((i >= 0) && (i < height)) {
- /* Bottom */
- curColor[0] += map[(x + i * width) * 4 + GlowR] * filter[fy];
- curColor[1] += map[(x + i * width) * 4 + GlowG] * filter[fy];
- curColor[2] += map[(x + i * width) * 4 + GlowB] * filter[fy];
-
- /* Top */
- curColor2[0] += map[(x + (height - 1 - i) * width) * 4 + GlowR] * filter[fy];
- curColor2[1] += map[(x + (height - 1 - i) * width) * 4 + GlowG] * filter[fy];
- curColor2[2] += map[(x + (height - 1 - i) * width) * 4 + GlowB] * filter[fy];
- }
- fy++;
- }
- temp[index + GlowR] = curColor[0];
- temp[index + GlowG] = curColor[1];
- temp[index + GlowB] = curColor[2];
- temp[((x + (height - 1 - y) * width) * 4) + GlowR] = curColor2[0];
- temp[((x + (height - 1 - y) * width) * 4) + GlowG] = curColor2[1];
- temp[((x + (height - 1 - y) * width) * 4) + GlowB] = curColor2[2];
- }
-
- /* Do the main body */
- for (y = halfWidth; y < height - halfWidth; y++) {
- index = (x + y * width) * 4;
- fy = 0;
- zero_v3(curColor);
- for (i = y - halfWidth; i < y + halfWidth; i++) {
- curColor[0] += map[(x + i * width) * 4 + GlowR] * filter[fy];
- curColor[1] += map[(x + i * width) * 4 + GlowG] * filter[fy];
- curColor[2] += map[(x + i * width) * 4 + GlowB] * filter[fy];
- fy++;
- }
- temp[index + GlowR] = curColor[0];
- temp[index + GlowG] = curColor[1];
- temp[index + GlowB] = curColor[2];
- }
- }
-
- /* Swap buffers */
- swap = temp; temp = map; /* map = swap; */ /* UNUSED */
-
- /* Tidy up */
- MEM_freeN(filter);
- MEM_freeN(temp);
-}
-
static void RVBlurBitmap2_float(float *map, int width, int height, float blur, int quality)
/* MUUUCCH better than the previous blur. */
/* We do the blurring in two passes which is a whole lot faster. */
@@ -2124,26 +1989,6 @@ static void RVBlurBitmap2_float(float *map, int width, int height, float blur, i
MEM_freeN(temp);
}
-
-/* Adds two bitmaps and puts the results into a third map. */
-/* C must have been previously allocated but it may be A or B. */
-/* We clamp values to 255 to prevent weirdness */
-/*=============================== */
-static void RVAddBitmaps_byte(unsigned char *a, unsigned char *b, unsigned char *c, int width, int height)
-{
- int x, y, index;
-
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++) {
- index = (x + y * width) * 4;
- c[index + GlowR] = MIN2(255, a[index + GlowR] + b[index + GlowR]);
- c[index + GlowG] = MIN2(255, a[index + GlowG] + b[index + GlowG]);
- c[index + GlowB] = MIN2(255, a[index + GlowB] + b[index + GlowB]);
- c[index + GlowA] = MIN2(255, a[index + GlowA] + b[index + GlowA]);
- }
- }
-}
-
static void RVAddBitmaps_float(float *a, float *b, float *c, int width, int height)
{
int x, y, index;
@@ -2159,37 +2004,6 @@ static void RVAddBitmaps_float(float *a, float *b, float *c, int width, int heig
}
}
-/* For each pixel whose total luminance exceeds the threshold,
- * Multiply it's value by BOOST and add it to the output map
- */
-static void RVIsolateHighlights_byte(unsigned char *in, unsigned char *out, int width, int height, int threshold,
- float boost, float clamp)
-{
- int x, y, index;
- int intensity;
-
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++) {
- index = (x + y * width) * 4;
-
- /* Isolate the intensity */
- intensity = (in[index + GlowR] + in[index + GlowG] + in[index + GlowB] - threshold);
- if (intensity > 0) {
- out[index + GlowR] = MIN2(255 * clamp, (in[index + GlowR] * boost * intensity) / 255);
- out[index + GlowG] = MIN2(255 * clamp, (in[index + GlowG] * boost * intensity) / 255);
- out[index + GlowB] = MIN2(255 * clamp, (in[index + GlowB] * boost * intensity) / 255);
- out[index + GlowA] = MIN2(255 * clamp, (in[index + GlowA] * boost * intensity) / 255);
- }
- else {
- out[index + GlowR] = 0;
- out[index + GlowG] = 0;
- out[index + GlowB] = 0;
- out[index + GlowA] = 0;
- }
- }
- }
-}
-
static void RVIsolateHighlights_float(float *in, float *out, int width, int height, float threshold, float boost, float clamp)
{
int x, y, index;
@@ -2254,16 +2068,27 @@ static void copy_glow_effect(Sequence *dst, Sequence *src)
}
static void do_glow_effect_byte(Sequence *seq, int render_size, float facf0, float UNUSED(facf1), int x, int y,
- char *rect1, char *UNUSED(rect2), char *out)
+ unsigned char *rect1, unsigned char *UNUSED(rect2), unsigned char *out)
{
- unsigned char *outbuf = (unsigned char *)out;
- unsigned char *inbuf = (unsigned char *)rect1;
+ float *outbuf, *inbuf;
GlowVars *glow = (GlowVars *)seq->effectdata;
-
- RVIsolateHighlights_byte(inbuf, outbuf, x, y, glow->fMini * 765, glow->fBoost * facf0, glow->fClamp);
- RVBlurBitmap2_byte(outbuf, x, y, glow->dDist * (render_size / 100.0f), glow->dQuality);
+
+ inbuf = MEM_mallocN(4 * sizeof(float) * x * y, "glow effect input");
+ outbuf = MEM_mallocN(4 * sizeof(float) * x * y, "glow effect output");
+
+ IMB_buffer_float_from_byte(inbuf, rect1, IB_PROFILE_SRGB, IB_PROFILE_SRGB, FALSE, x, y, x, x);
+ IMB_buffer_float_premultiply(inbuf, x, y);
+
+ RVIsolateHighlights_float(inbuf, outbuf, x, y, glow->fMini * 3.0f, glow->fBoost * facf0, glow->fClamp);
+ RVBlurBitmap2_float(outbuf, x, y, glow->dDist * (render_size / 100.0f), glow->dQuality);
if (!glow->bNoComp)
- RVAddBitmaps_byte(inbuf, outbuf, outbuf, x, y);
+ RVAddBitmaps_float(inbuf, outbuf, outbuf, x, y);
+
+ IMB_buffer_float_unpremultiply(outbuf, x, y);
+ IMB_buffer_byte_from_float(out, outbuf, 4, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_SRGB, FALSE, x, y, x, x);
+
+ MEM_freeN(inbuf);
+ MEM_freeN(outbuf);
}
static void do_glow_effect_float(Sequence *seq, int render_size, float facf0, float UNUSED(facf1), int x, int y,
@@ -2292,7 +2117,7 @@ static ImBuf *do_glow_effect(SeqRenderData context, Sequence *seq, float UNUSED(
}
else {
do_glow_effect_byte(seq, render_size, facf0, facf1, context.rectx, context.recty,
- (char *) ibuf1->rect, (char *) ibuf2->rect, (char *) out->rect);
+ (unsigned char *) ibuf1->rect, (unsigned char *) ibuf2->rect, (unsigned char *) out->rect);
}
return out;
@@ -2735,7 +2560,7 @@ static ImBuf *do_speed_effect(SeqRenderData context, Sequence *UNUSED(seq), floa
}
else {
do_cross_effect_byte(facf0, facf1, context.rectx, context.recty,
- (char *) ibuf1->rect, (char *) ibuf2->rect, (char *) out->rect);
+ (unsigned char *) ibuf1->rect, (unsigned char *) ibuf2->rect, (unsigned char *) out->rect);
}
return out;
}
@@ -2761,8 +2586,8 @@ static void do_overdrop_effect(SeqRenderData context, Sequence *UNUSED(seq), flo
slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
- do_drop_effect_byte(facf0, facf1, x, y, (char *) rect1, (char *) rect2, (char *) rect_out);
- do_alphaover_effect_byte(facf0, facf1, x, y, (char *) rect1, (char *) rect2, (char *) rect_out);
+ do_drop_effect_byte(facf0, facf1, x, y, rect1, rect2, rect_out);
+ do_alphaover_effect_byte(facf0, facf1, x, y, rect1, rect2, rect_out);
}
}
diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c
index 5b2e9f2bf23..a64a4895e9b 100644
--- a/source/blender/blenkernel/intern/seqmodifier.c
+++ b/source/blender/blenkernel/intern/seqmodifier.c
@@ -135,7 +135,7 @@ static void modifier_apply_threaded(ImBuf *ibuf, ImBuf *mask, modifier_apply_thr
init_data.apply_callback = apply_callback;
IMB_processor_apply_threaded(ibuf->y, sizeof(ModifierThread), &init_data,
- modifier_init_handle, modifier_do_thread);
+ modifier_init_handle, modifier_do_thread);
}
/* **** Color Balance Modifier **** */
@@ -226,24 +226,28 @@ static void curves_apply_threaded(int width, int height, unsigned char *rect, fl
}
if (rect) {
unsigned char *pixel = rect + pixel_index;
- unsigned char result[3];
+ float result[3], tempc[4];
- curvemapping_evaluate_premulRGB(curve_mapping, result, pixel);
+ straight_uchar_to_premul_float(tempc, pixel);
+
+ curvemapping_evaluate_premulRGBF(curve_mapping, result, tempc);
if (mask_rect) {
float t[3];
rgb_uchar_to_float(t, mask_rect + pixel_index);
- pixel[0] = pixel[0] * (1.0f - t[0]) + result[0] * t[0];
- pixel[1] = pixel[1] * (1.0f - t[1]) + result[1] * t[1];
- pixel[2] = pixel[2] * (1.0f - t[2]) + result[2] * t[2];
+ tempc[0] = tempc[0] * (1.0f - t[0]) + result[0] * t[0];
+ tempc[1] = tempc[1] * (1.0f - t[1]) + result[1] * t[1];
+ tempc[2] = tempc[2] * (1.0f - t[2]) + result[2] * t[2];
}
else {
- pixel[0] = result[0];
- pixel[1] = result[1];
- pixel[2] = result[2];
+ tempc[0] = result[0];
+ tempc[1] = result[1];
+ tempc[2] = result[2];
}
+
+ premul_float_to_straight_uchar(pixel, tempc);
}
}
}
@@ -434,7 +438,7 @@ static void brightcontrast_apply_threaded(int width, int height, unsigned char *
unsigned char *m = mask_rect + pixel_index;
float t = (float) m[c] / 255.0f;
- v = (float) pixel[c] * (1.0f - t) + v * t;
+ v = (float) pixel[c] / 255.0f * (1.0f - t) + v * t;
}
pixel[c] = FTOCHAR(v);
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index acce3740c98..9b276912087 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -191,7 +191,9 @@ static void BKE_sequence_free_ex(Scene *scene, Sequence *seq, const int do_cache
((ID *)seq->sound)->us--;
}
- /* clipboard has no scene and will never have a sound handle or be active */
+ /* clipboard has no scene and will never have a sound handle or be active
+ * same goes to sequences copy for proxy rebuild job
+ */
if (scene) {
Editing *ed = scene->ed;
@@ -243,7 +245,7 @@ static void seq_free_sequence_recurse(Scene *scene, Sequence *seq)
}
-Editing *BKE_sequencer_editing_get(Scene *scene, int alloc)
+Editing *BKE_sequencer_editing_get(Scene *scene, bool alloc)
{
if (alloc) {
BKE_sequencer_editing_ensure(scene);
@@ -322,7 +324,6 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_
{
const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
const char *to_colorspace = scene->sequencer_colorspace_settings.name;
- int predivide = ibuf->flags & IB_cm_predivide;
if (!ibuf->rect_float) {
if (make_float && ibuf->rect) {
@@ -352,7 +353,7 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_
imb_freerectImBuf(ibuf);
IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
- from_colorspace, to_colorspace, predivide);
+ from_colorspace, to_colorspace, TRUE);
}
}
@@ -365,10 +366,8 @@ void BKE_sequencer_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf)
return;
if (to_colorspace && to_colorspace[0] != '\0') {
- int predivide = ibuf->flags & IB_cm_predivide;
-
IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
- from_colorspace, to_colorspace, predivide);
+ from_colorspace, to_colorspace, TRUE);
}
}
@@ -591,8 +590,8 @@ void BKE_sequence_calc(Scene *scene, Sequence *seq)
/* XXX These resets should not be necessary, but users used to be able to
* edit effect's length, leading to strange results. See [#29190] */
seq->startofs = seq->endofs = seq->startstill = seq->endstill = 0;
- seq->start = seq->startdisp = MAX3(seq->seq1->startdisp, seq->seq2->startdisp, seq->seq3->startdisp);
- seq->enddisp = MIN3(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp);
+ seq->start = seq->startdisp = max_iii(seq->seq1->startdisp, seq->seq2->startdisp, seq->seq3->startdisp);
+ seq->enddisp = min_iii(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp);
/* we cant help if strips don't overlap, it wont give useful results.
* but at least ensure 'len' is never negative which causes bad bugs elsewhere. */
if (seq->enddisp < seq->startdisp) {
@@ -634,7 +633,7 @@ void BKE_sequence_calc(Scene *scene, Sequence *seq)
}
}
-/* note: caller should run calc_sequence(scene, seq) after */
+/* note: caller should run BKE_sequence_calc(scene, seq) after */
void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, int lock_range)
{
char str[FILE_MAX];
@@ -816,6 +815,33 @@ void BKE_sequencer_clear_scene_in_allseqs(Main *bmain, Scene *scene)
BKE_sequencer_base_recursive_apply(&scene_iter->ed->seqbase, clear_scene_in_allseqs_cb, scene);
}
}
+
+ /* also clear clipboard */
+ BKE_sequencer_base_recursive_apply(&seqbase_clipboard, clear_scene_in_allseqs_cb, scene);
+}
+
+static int clear_movieclip_in_clipboard_cb(Sequence *seq, void *arg_pt)
+{
+ if (seq->clip == (MovieClip *)arg_pt)
+ seq->clip = NULL;
+ return 1;
+}
+
+void BKE_sequencer_clear_movieclip_in_clipboard(MovieClip *clip)
+{
+ BKE_sequencer_base_recursive_apply(&seqbase_clipboard, clear_movieclip_in_clipboard_cb, clip);
+}
+
+static int clear_mask_in_clipboard_cb(Sequence *seq, void *arg_pt)
+{
+ if (seq->mask == (Mask *)arg_pt)
+ seq->mask = NULL;
+ return 1;
+}
+
+void BKE_sequencer_clear_mask_in_clipboard(Mask *mask)
+{
+ BKE_sequencer_base_recursive_apply(&seqbase_clipboard, clear_mask_in_clipboard_cb, mask);
}
typedef struct SeqUniqueInfo {
@@ -830,7 +856,7 @@ static void seqbase_unique_name(ListBase *seqbasep, SeqUniqueInfo *sui)
{
Sequence *seq;
for (seq = seqbasep->first; seq; seq = seq->next) {
- if (sui->seq != seq && strcmp(sui->name_dest, seq->name + 2) == 0) {
+ if ((sui->seq != seq) && STREQ(sui->name_dest, seq->name + 2)) {
/* SEQ_NAME_MAXSTR - 2 for prefix, -1 for \0, -4 for the number */
BLI_snprintf(sui->name_dest, sizeof(sui->name_dest), "%.59s.%03d", sui->name_src, sui->count++);
sui->match = 1; /* be sure to re-scan */
@@ -1435,7 +1461,7 @@ void BKE_sequencer_proxy_rebuild(SeqIndexBuildContext *context, short *stop, sho
seq_proxy_build_frame(render_context, seq, cfra, 100);
}
- *progress = (float) cfra / (seq->enddisp - seq->endstill - seq->startdisp + seq->startstill);
+ *progress = (float) (cfra - seq->startdisp - seq->startstill) / (seq->enddisp - seq->endstill - seq->startdisp - seq->startstill);
*do_update = TRUE;
if (*stop || G.is_break)
@@ -1451,7 +1477,7 @@ void BKE_sequencer_proxy_rebuild_finish(SeqIndexBuildContext *context, short sto
IMB_anim_index_rebuild_finish(context->index_context, stop);
}
- seq_free_sequence_recurse(context->scene, context->seq);
+ seq_free_sequence_recurse(NULL, context->seq);
MEM_freeN(context);
}
@@ -1515,18 +1541,6 @@ MINLINE float color_balance_fl(float in, const float lift, const float gain, con
return powf(x, gamma) * mul;
}
-static void make_cb_table_byte(float lift, float gain, float gamma,
- unsigned char *table, float mul)
-{
- int y;
-
- for (y = 0; y < 256; y++) {
- float v = color_balance_fl((float)y * (1.0f / 255.0f), lift, gain, gamma, mul);
-
- table[y] = FTOCHAR(v);
- }
-}
-
static void make_cb_table_float(float lift, float gain, float gamma,
float *table, float mul)
{
@@ -1541,35 +1555,36 @@ static void make_cb_table_float(float lift, float gain, float gamma,
static void color_balance_byte_byte(StripColorBalance *cb_, unsigned char *rect, unsigned char *mask_rect, int width, int height, float mul)
{
- unsigned char cb_tab[3][256];
- int c;
- unsigned char *p = rect;
- unsigned char *e = p + width * 4 * height;
+ //unsigned char cb_tab[3][256];
+ unsigned char *cp = rect;
+ unsigned char *e = cp + width * 4 * height;
unsigned char *m = mask_rect;
StripColorBalance cb = calc_cb(cb_);
- for (c = 0; c < 3; c++) {
- make_cb_table_byte(cb.lift[c], cb.gain[c], cb.gamma[c], cb_tab[c], mul);
- }
+ while (cp < e) {
+ float p[4];
+ int c;
- while (p < e) {
- if (m) {
- float t[3] = {m[0] / 255.0f, m[1] / 255.0f, m[2] / 255.0f};
+ straight_uchar_to_premul_float(p, cp);
- p[0] = p[0] * (1.0f - t[0]) + t[0] * cb_tab[0][p[0]];
- p[1] = p[1] * (1.0f - t[1]) + t[1] * cb_tab[1][p[1]];
- p[2] = p[2] * (1.0f - t[2]) + t[2] * cb_tab[2][p[2]];
+ for (c = 0; c < 3; c++) {
+ float t = color_balance_fl(p[c], cb.lift[c], cb.gain[c], cb.gamma[c], mul);
- m += 4;
- }
- else {
- p[0] = cb_tab[0][p[0]];
- p[1] = cb_tab[1][p[1]];
- p[2] = cb_tab[2][p[2]];
+ if (m) {
+ float m_normal = (float) m[c] / 255.0f;
+
+ p[c] = p[c] * (1.0f - m_normal) + t * m_normal;
+ }
+ else
+ p[c] = t;
}
- p += 4;
+ premul_float_to_straight_uchar(cp, p);
+
+ cp += 4;
+ if (m)
+ m += 4;
}
}
@@ -1761,7 +1776,7 @@ void BKE_sequencer_color_balance_apply(StripColorBalance *cb, ImBuf *ibuf, float
init_data.mask = mask_input;
IMB_processor_apply_threaded(ibuf->y, sizeof(ColorBalanceThread), &init_data,
- color_balance_init_handle, color_balance_do_thread);
+ color_balance_init_handle, color_balance_do_thread);
/* color balance either happens on float buffer or byte buffer, but never on both,
* free byte buffer if there's float buffer since float buffer would be used for
@@ -1793,7 +1808,7 @@ int BKE_sequencer_input_have_to_preprocess(SeqRenderData UNUSED(context), Sequen
{
float mul;
- if (seq->flag & (SEQ_FILTERY | SEQ_USE_CROP | SEQ_USE_TRANSFORM | SEQ_FLIPX | SEQ_FLIPY | SEQ_MAKE_PREMUL | SEQ_MAKE_FLOAT)) {
+ if (seq->flag & (SEQ_FILTERY | SEQ_USE_CROP | SEQ_USE_TRANSFORM | SEQ_FLIPX | SEQ_FLIPY | SEQ_MAKE_FLOAT)) {
return TRUE;
}
@@ -1835,8 +1850,6 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra,
StripCrop c = {0};
StripTransform t = {0};
int sx, sy, dx, dy;
- double xscale = 1.0;
- double yscale = 1.0;
if (is_proxy_image) {
double f = seq_rendersize_to_scale_factor(context.preview_render_size);
@@ -1853,21 +1866,23 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra,
t = *seq->strip->transform;
}
- xscale = context.scene->r.xsch ? ((double)context.rectx / (double)context.scene->r.xsch) : 1.0;
- yscale = context.scene->r.ysch ? ((double)context.recty / (double)context.scene->r.ysch) : 1.0;
-
- xscale /= (double)context.rectx / (double)ibuf->x;
- yscale /= (double)context.recty / (double)ibuf->y;
-
- c.left *= xscale; c.right *= xscale;
- c.top *= yscale; c.bottom *= yscale;
-
- t.xofs *= xscale; t.yofs *= yscale;
+ if (is_preprocessed) {
+ double xscale = context.scene->r.xsch ? ((double)context.rectx / (double)context.scene->r.xsch) : 1.0;
+ double yscale = context.scene->r.ysch ? ((double)context.recty / (double)context.scene->r.ysch) : 1.0;
+ if (seq->flag & SEQ_USE_TRANSFORM) {
+ t.xofs *= xscale;
+ t.yofs *= yscale;
+ }
+ if (seq->flag & SEQ_USE_CROP) {
+ c.left *= xscale;
+ c.right *= xscale;
+ c.top *= yscale;
+ c.bottom *= yscale;
+ }
+ }
sx = ibuf->x - c.left - c.right;
sy = ibuf->y - c.top - c.bottom;
- dx = sx;
- dy = sy;
if (seq->flag & SEQ_USE_TRANSFORM) {
if (is_preprocessed) {
@@ -1879,6 +1894,10 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra,
dy = context.scene->r.ysch;
}
}
+ else {
+ dx = sx;
+ dy = sy;
+ }
if (c.top + c.bottom >= ibuf->y ||
c.left + c.right >= ibuf->x ||
@@ -1890,7 +1909,8 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra,
ImBuf *i = IMB_allocImBuf(dx, dy, 32, ibuf->rect_float ? IB_rectfloat : IB_rect);
IMB_rectcpy(i, ibuf, t.xofs, t.yofs, c.left, c.bottom, sx, sy);
-
+ sequencer_imbuf_assign_spaces(context.scene, i);
+
IMB_freeImBuf(ibuf);
ibuf = i;
@@ -1929,12 +1949,6 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra,
multibuf(ibuf, mul);
}
- if (seq->flag & SEQ_MAKE_PREMUL) {
- if (ibuf->planes == 32 && ibuf->zbuf == NULL) {
- IMB_premultiply_alpha(ibuf);
- }
- }
-
if (ibuf->x != context.rectx || ibuf->y != context.recty) {
if (context.scene->r.mode & R_OSA) {
IMB_scaleImBuf(ibuf, (short)context.rectx, (short)context.recty);
@@ -2409,8 +2423,9 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float
/* opengl offscreen render */
BKE_scene_update_for_newframe(context.bmain, scene, scene->lay);
- ibuf = sequencer_view3d_cb(scene, camera, context.rectx, context.recty,
- IB_rect, context.scene->r.seq_prev_type, TRUE, FALSE, err_out);
+ ibuf = sequencer_view3d_cb(scene, camera, context.rectx, context.recty, IB_rect,
+ context.scene->r.seq_prev_type, context.scene->r.seq_flag & R_SEQ_SOLID_TEX,
+ TRUE, scene->r.alphamode, err_out);
if (ibuf == NULL) {
fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out);
}
@@ -2543,13 +2558,18 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo
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);
}
- if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect, seq->strip->colorspace_settings.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);
@@ -2638,7 +2658,7 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo
static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra)
{
ImBuf *ibuf = NULL;
- int use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra);
+ int use_preprocess = FALSE;
int is_proxy_image = FALSE;
float nr = give_stripelem_index(seq, cfra);
/* all effects are handled similarly with the exception of speed effect */
@@ -2647,30 +2667,36 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra)
ibuf = BKE_sequencer_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
- /* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF,
- * but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL */
- if (ibuf)
- use_preprocess = FALSE;
-
- if (ibuf == NULL)
- ibuf = copy_from_ibuf_still(context, seq, nr);
-
if (ibuf == NULL) {
- ibuf = BKE_sequencer_preprocessed_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
+ if (ibuf == NULL)
+ ibuf = copy_from_ibuf_still(context, seq, nr);
if (ibuf == NULL) {
- /* MOVIECLIPs have their own proxy management */
- if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) {
- ibuf = seq_proxy_fetch(context, seq, cfra);
- is_proxy_image = (ibuf != NULL);
- }
+ ibuf = BKE_sequencer_preprocessed_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
- if (ibuf == NULL)
- ibuf = do_render_strip_uncached(context, seq, cfra);
+ if (ibuf == NULL) {
+ /* MOVIECLIPs have their own proxy management */
+ if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) {
+ ibuf = seq_proxy_fetch(context, seq, cfra);
+ is_proxy_image = (ibuf != NULL);
+ }
- if (ibuf)
- BKE_sequencer_preprocessed_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf);
+ if (ibuf == NULL)
+ ibuf = do_render_strip_uncached(context, seq, cfra);
+
+ if (ibuf)
+ BKE_sequencer_preprocessed_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf);
+ }
}
+
+ if (ibuf)
+ use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra);
+ }
+ else {
+ /* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF,
+ * but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL
+ * so, no need in check for preprocess here
+ */
}
if (ibuf == NULL) {
@@ -3036,30 +3062,30 @@ static void free_anim_seq(Sequence *seq)
}
/* check whether sequence cur depends on seq */
-int BKE_sequence_check_depend(Sequence *seq, Sequence *cur)
+bool BKE_sequence_check_depend(Sequence *seq, Sequence *cur)
{
if (cur->seq1 == seq || cur->seq2 == seq || cur->seq3 == seq)
- return TRUE;
+ return true;
/* sequences are not intersecting in time, assume no dependency exists between them */
if (cur->enddisp < seq->startdisp || cur->startdisp > seq->enddisp)
- return FALSE;
+ return false;
/* checking sequence is below reference one, not dependent on it */
if (cur->machine < seq->machine)
- return FALSE;
+ return false;
/* sequence is not blending with lower machines, no dependency here occurs
* check for non-effects only since effect could use lower machines as input
*/
if ((cur->type & SEQ_TYPE_EFFECT) == 0 &&
- ((cur->blend_mode == SEQ_BLEND_REPLACE) ||
- (cur->blend_mode == SEQ_TYPE_CROSS && cur->blend_opacity == 100.0f)))
+ ((cur->blend_mode == SEQ_BLEND_REPLACE) ||
+ (cur->blend_mode == SEQ_TYPE_CROSS && cur->blend_opacity == 100.0f)))
{
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
static void sequence_do_invalidate_dependent(Sequence *seq, ListBase *seqbase)
@@ -3265,7 +3291,7 @@ void BKE_sequence_tx_set_final_right(Sequence *seq, int val)
/* used so we can do a quick check for single image seq
* since they work a bit differently to normal image seq's (during transform) */
-int BKE_sequence_single_check(Sequence *seq)
+bool BKE_sequence_single_check(Sequence *seq)
{
return ((seq->len == 1) &&
(seq->type == SEQ_TYPE_IMAGE ||
@@ -3274,21 +3300,21 @@ int BKE_sequence_single_check(Sequence *seq)
}
/* check if the selected seq's reference unselected seq's */
-int BKE_sequence_base_isolated_sel_check(ListBase *seqbase)
+bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase)
{
Sequence *seq;
/* is there more than 1 select */
- int ok = FALSE;
+ bool ok = false;
for (seq = seqbase->first; seq; seq = seq->next) {
if (seq->flag & SELECT) {
- ok = TRUE;
+ ok = true;
break;
}
}
- if (ok == FALSE)
- return FALSE;
+ if (ok == false)
+ return false;
/* test relationships */
for (seq = seqbase->first; seq; seq = seq->next) {
@@ -3296,24 +3322,24 @@ int BKE_sequence_base_isolated_sel_check(ListBase *seqbase)
continue;
if (seq->flag & SELECT) {
- if ( (seq->seq1 && (seq->seq1->flag & SELECT) == 0) ||
- (seq->seq2 && (seq->seq2->flag & SELECT) == 0) ||
- (seq->seq3 && (seq->seq3->flag & SELECT) == 0) )
+ if ((seq->seq1 && (seq->seq1->flag & SELECT) == 0) ||
+ (seq->seq2 && (seq->seq2->flag & SELECT) == 0) ||
+ (seq->seq3 && (seq->seq3->flag & SELECT) == 0) )
{
- return FALSE;
+ return false;
}
}
else {
- if ( (seq->seq1 && (seq->seq1->flag & SELECT)) ||
- (seq->seq2 && (seq->seq2->flag & SELECT)) ||
- (seq->seq3 && (seq->seq3->flag & SELECT)) )
+ if ((seq->seq1 && (seq->seq1->flag & SELECT)) ||
+ (seq->seq2 && (seq->seq2->flag & SELECT)) ||
+ (seq->seq3 && (seq->seq3->flag & SELECT)) )
{
- return FALSE;
+ return false;
}
}
}
- return TRUE;
+ return true;
}
/* use to impose limits when dragging/extending - so impossible situations don't happen
@@ -3379,29 +3405,29 @@ void BKE_sequence_single_fix(Sequence *seq)
}
}
-int BKE_sequence_tx_test(Sequence *seq)
+bool BKE_sequence_tx_test(Sequence *seq)
{
return (seq->type < SEQ_TYPE_EFFECT) || (BKE_sequence_effect_get_num_inputs(seq->type) == 0);
}
-static int seq_overlap(Sequence *seq1, Sequence *seq2)
+static bool seq_overlap(Sequence *seq1, Sequence *seq2)
{
return (seq1 != seq2 && seq1->machine == seq2->machine &&
((seq1->enddisp <= seq2->startdisp) || (seq1->startdisp >= seq2->enddisp)) == 0);
}
-int BKE_sequence_test_overlap(ListBase *seqbasep, Sequence *test)
+bool BKE_sequence_test_overlap(ListBase *seqbasep, Sequence *test)
{
Sequence *seq;
seq = seqbasep->first;
while (seq) {
if (seq_overlap(test, seq))
- return 1;
+ return true;
seq = seq->next;
}
- return 0;
+ return false;
}
@@ -3461,7 +3487,7 @@ Sequence *BKE_sequencer_foreground_frame_get(Scene *scene, int frame)
}
/* return 0 if there werent enough space */
-int BKE_sequence_base_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene)
+bool BKE_sequence_base_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene)
{
int orig_machine = test->machine;
test->machine++;
@@ -3492,10 +3518,10 @@ int BKE_sequence_base_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_sc
BKE_sequence_translate(evil_scene, test, new_frame - test->start);
BKE_sequence_calc(evil_scene, test);
- return 0;
+ return false;
}
else {
- return 1;
+ return true;
}
}
@@ -3546,7 +3572,7 @@ static int shuffle_seq_time_offset(Scene *scene, ListBase *seqbasep, char dir)
return tot_ofs;
}
-int BKE_sequence_base_shuffle_time(ListBase *seqbasep, Scene *evil_scene)
+bool BKE_sequence_base_shuffle_time(ListBase *seqbasep, Scene *evil_scene)
{
/* note: seq->tmp is used to tag strips to move */
@@ -3565,7 +3591,7 @@ int BKE_sequence_base_shuffle_time(ListBase *seqbasep, Scene *evil_scene)
}
}
- return offset ? 0 : 1;
+ return offset ? false : true;
}
void BKE_sequencer_update_sound_bounds_all(Scene *scene)
@@ -3835,7 +3861,7 @@ Sequence *BKE_sequence_get_by_name(ListBase *seqbase, const char *name, int recu
Sequence *rseq = NULL;
for (iseq = seqbase->first; iseq; iseq = iseq->next) {
- if (strcmp(name, iseq->name + 2) == 0)
+ if (STREQ(name, iseq->name + 2))
return iseq;
else if (recursive && (iseq->seqbase.first) && (rseq = BKE_sequence_get_by_name(&iseq->seqbase, name, 1))) {
return rseq;
@@ -3959,6 +3985,24 @@ Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine)
return seq;
}
+void BKE_sequence_alpha_mode_from_extension(Sequence *seq)
+{
+ if (seq->strip && seq->strip->stripdata) {
+ char *name = seq->strip->stripdata->name;
+
+ if (BLI_testextensie(name, ".exr") ||
+ BLI_testextensie(name, ".cin") ||
+ BLI_testextensie(name, ".dpx") ||
+ BLI_testextensie(name, ".hdr"))
+ {
+ seq->alpha_mode = IMA_ALPHA_PREMUL;
+ }
+ else {
+ seq->alpha_mode = IMA_ALPHA_STRAIGHT;
+ }
+ }
+}
+
void BKE_sequence_init_colorspace(Sequence *seq)
{
if (seq->strip && seq->strip->stripdata) {
@@ -3970,10 +4014,18 @@ void BKE_sequence_init_colorspace(Sequence *seq)
/* initialize input color space */
if (seq->type == SEQ_TYPE_IMAGE) {
- ibuf = IMB_loadiffname(name, IB_rect, seq->strip->colorspace_settings.name);
+ ibuf = IMB_loadiffname(name, IB_test | IB_alphamode_detect, seq->strip->colorspace_settings.name);
+
+ /* byte images are default to straight alpha, however sequencer
+ * works in premul space, so mark strip to be premultiplied first
+ */
+ seq->alpha_mode = SEQ_ALPHA_STRAIGHT;
+ if (ibuf) {
+ if (ibuf->flags & IB_alphamode_premul)
+ seq->alpha_mode = IMA_ALPHA_PREMUL;
- if (ibuf)
IMB_freeImBuf(ibuf);
+ }
}
}
}
@@ -4020,7 +4072,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad
if (sound == NULL || sound->playback_handle == NULL) {
#if 0
- if (op)
+ if (op)
BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
#endif
@@ -4173,7 +4225,7 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup
seqn->seqbase.first = seqn->seqbase.last = NULL;
/* WATCH OUT!!! - This metastrip is not recursively duplicated here - do this after!!! */
- /* - seq_dupli_recursive(&seq->seqbase,&seqn->seqbase);*/
+ /* - seq_dupli_recursive(&seq->seqbase, &seqn->seqbase);*/
}
else if (seq->type == SEQ_TYPE_SCENE) {
seqn->strip->stripdata = NULL;
@@ -4272,7 +4324,7 @@ void BKE_sequence_base_dupli_recursive(Scene *scene, Scene *scene_to, ListBase *
/* called on draw, needs to be fast,
* we could cache and use a flag if we want to make checks for file paths resolving for eg. */
-int BKE_sequence_is_valid_check(Sequence *seq)
+bool BKE_sequence_is_valid_check(Sequence *seq)
{
switch (seq->type) {
case SEQ_TYPE_MASK:
@@ -4285,6 +4337,6 @@ int BKE_sequence_is_valid_check(Sequence *seq)
return (seq->sound != NULL);
}
- return TRUE;
+ return true;
}
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index 53dfbdcfb85..0863517c7d7 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -170,7 +170,7 @@ void smoke_reallocate_fluid(SmokeDomainSettings *sds, float dx, int res[3], int
if (free_old && sds->fluid)
smoke_free(sds->fluid);
- if (!MIN3(res[0], res[1], res[2])) {
+ if (!min_iii(res[0], res[1], res[2])) {
sds->fluid = NULL;
return;
}
@@ -191,7 +191,7 @@ void smoke_reallocate_highres_fluid(SmokeDomainSettings *sds, float dx, int res[
if (free_old && sds->wt)
smoke_turbulence_free(sds->wt);
- if (!MIN3(res[0], res[1], res[2])) {
+ if (!min_iii(res[0], res[1], res[2])) {
sds->wt = NULL;
return;
}
@@ -213,8 +213,8 @@ static void smoke_pos_to_cell(SmokeDomainSettings *sds, float pos[3])
pos[2] *= 1.0f / sds->cell_size[2];
}
-/* set domain resolution and dimensions from object derivedmesh */
-static void smoke_set_domain_from_derivedmesh(SmokeDomainSettings *sds, Object *ob, DerivedMesh *dm)
+/* set domain transformations and base resolution from object derivedmesh */
+static void smoke_set_domain_from_derivedmesh(SmokeDomainSettings *sds, Object *ob, DerivedMesh *dm, int init_resolution)
{
size_t i;
float min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}, max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
@@ -246,7 +246,10 @@ static void smoke_set_domain_from_derivedmesh(SmokeDomainSettings *sds, Object *
/* calculate domain dimensions */
sub_v3_v3v3(size, max, min);
- copy_v3_v3(sds->cell_size, size);
+ if (init_resolution) {
+ zero_v3_int(sds->base_res);
+ copy_v3_v3(sds->cell_size, size);
+ }
mul_v3_v3(size, ob->size);
copy_v3_v3(sds->global_size, size);
copy_v3_v3(sds->dp0, min);
@@ -254,18 +257,18 @@ static void smoke_set_domain_from_derivedmesh(SmokeDomainSettings *sds, Object *
invert_m4_m4(sds->imat, ob->obmat);
// prevent crash when initializing a plane as domain
- if ((size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) || (size[2] < FLT_EPSILON))
+ if (!init_resolution || (size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) || (size[2] < FLT_EPSILON))
return;
/* define grid resolutions from longest domain side */
- if (size[0] > MAX2(size[1], size[2])) {
+ if (size[0] >= MAX2(size[1], size[2])) {
scale = res / size[0];
sds->scale = size[0] / ob->size[0];
sds->base_res[0] = res;
sds->base_res[1] = (int)(size[1] * scale + 0.5f);
sds->base_res[2] = (int)(size[2] * scale + 0.5f);
}
- else if (size[1] > MAX2(size[0], size[2])) {
+ else if (size[1] >= MAX2(size[0], size[2])) {
scale = res / size[1];
sds->scale = size[1] / ob->size[1];
sds->base_res[0] = (int)(size[0] * scale + 0.5f);
@@ -293,7 +296,7 @@ static int smokeModifier_init(SmokeModifierData *smd, Object *ob, Scene *scene,
SmokeDomainSettings *sds = smd->domain;
int res[3];
/* set domain dimensions from derivedmesh */
- smoke_set_domain_from_derivedmesh(sds, ob, dm);
+ smoke_set_domain_from_derivedmesh(sds, ob, dm, TRUE);
/* reset domain values */
zero_v3_int(sds->shift);
zero_v3(sds->shift_f);
@@ -924,7 +927,8 @@ static void clampBoundsInDomain(SmokeDomainSettings *sds, int min[3], int max[3]
}
}
-static void em_allocateData(EmissionMap *em, int use_velocity) {
+static void em_allocateData(EmissionMap *em, int use_velocity)
+{
int i, res[3];
for (i = 0; i < 3; i++) {
@@ -941,7 +945,8 @@ static void em_allocateData(EmissionMap *em, int use_velocity) {
em->velocity = MEM_callocN(sizeof(float) * em->total_cells * 3, "smoke_flow_velocity");
}
-static void em_freeData(EmissionMap *em) {
+static void em_freeData(EmissionMap *em)
+{
if (em->influence)
MEM_freeN(em->influence);
if (em->velocity)
@@ -1058,7 +1063,7 @@ static void get_texture_value(Tex *texture, float tex_co[3], TexResult *texres)
int result_type;
/* no node textures for now */
- result_type = multitex_ext_safe(texture, tex_co, texres);
+ result_type = multitex_ext_safe(texture, tex_co, texres, NULL);
/* 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.
@@ -1298,9 +1303,17 @@ static void adjustDomainResolution(SmokeDomainSettings *sds, int new_shift[3], E
int x, y, z, i;
float *density = smoke_get_density(sds->fluid);
float *fuel = smoke_get_fuel(sds->fluid);
+ float *bigdensity = smoke_turbulence_get_density(sds->wt);
+ float *bigfuel = smoke_turbulence_get_fuel(sds->wt);
float *vx = smoke_get_velocity_x(sds->fluid);
float *vy = smoke_get_velocity_y(sds->fluid);
float *vz = smoke_get_velocity_z(sds->fluid);
+ int block_size = sds->amplify + 1;
+ int wt_res[3];
+
+ if (sds->flags & MOD_SMOKE_HIGHRES && sds->wt) {
+ smoke_turbulence_get_res(sds->wt, wt_res);
+ }
INIT_MINMAX(min_vel, max_vel);
@@ -1312,8 +1325,35 @@ static void adjustDomainResolution(SmokeDomainSettings *sds, int new_shift[3], E
int xn = x - new_shift[0];
int yn = y - new_shift[1];
int zn = z - new_shift[2];
- int index = smoke_get_index(x - sds->res_min[0], sds->res[0], y - sds->res_min[1], sds->res[1], z - sds->res_min[2]);
- float max_den = (fuel) ? MAX2(density[index], fuel[index]) : density[index];
+ int index;
+ float max_den;
+
+ /* skip if cell already belongs to new area */
+ if (xn >= min[0] && xn <= max[0] && yn >= min[1] && yn <= max[1] && zn >= min[2] && zn <= max[2])
+ continue;
+
+ index = smoke_get_index(x - sds->res_min[0], sds->res[0], y - sds->res_min[1], sds->res[1], z - sds->res_min[2]);
+ max_den = (fuel) ? MAX2(density[index], fuel[index]) : density[index];
+
+ /* check high resolution bounds if max density isnt already high enough */
+ if (max_den < sds->adapt_threshold && sds->flags & MOD_SMOKE_HIGHRES && sds->wt) {
+ int i, j, k;
+ /* high res grid index */
+ int xx = (x - sds->res_min[0]) * block_size;
+ int yy = (y - sds->res_min[1]) * block_size;
+ int zz = (z - sds->res_min[2]) * block_size;
+
+ for (i = 0; i < block_size; i++)
+ for (j = 0; j < block_size; j++)
+ for (k = 0; k < block_size; k++)
+ {
+ int big_index = smoke_get_index(xx + i, wt_res[0], yy + j, wt_res[1], zz + k);
+ float den = (bigfuel) ? MAX2(bigdensity[big_index], bigfuel[big_index]) : bigdensity[big_index];
+ if (den > max_den) {
+ max_den = den;
+ }
+ }
+ }
/* content bounds (use shifted coordinates) */
if (max_den >= sds->adapt_threshold) {
@@ -1324,6 +1364,7 @@ static void adjustDomainResolution(SmokeDomainSettings *sds, int new_shift[3], E
if (max[1] < yn) max[1] = yn;
if (max[2] < zn) max[2] = zn;
}
+
/* velocity bounds */
if (min_vel[0] > vx[index]) min_vel[0] = vx[index];
if (min_vel[1] > vy[index]) min_vel[1] = vy[index];
@@ -1578,7 +1619,7 @@ BLI_INLINE void apply_inflow_fields(SmokeFlowSettings *sfs, float emission_value
}
/* set fire reaction coordinate */
- if (fuel && fuel[index]) {
+ 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);
@@ -1586,6 +1627,7 @@ BLI_INLINE void apply_inflow_fields(SmokeFlowSettings *sfs, float emission_value
if (value > react[index]) {
float f = fuel_flow / fuel[index];
react[index] = value * f + (1.0f - f) * react[index];
+ CLAMP(react[index], 0.0f, value);
}
}
}
@@ -1770,6 +1812,8 @@ static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sd
dy = gy - sds->res_min[1];
dz = gz - sds->res_min[2];
d_index = smoke_get_index(dx, sds->res[0], dy, sds->res[1], dz);
+ /* make sure emission cell is inside the new domain boundary */
+ if (dx < 0 || dy < 0 || dz < 0 || dx >= sds->res[0] || dy >= sds->res[1] || dz >= sds->res[2]) continue;
if (sfs->type == MOD_SMOKE_FLOW_TYPE_OUTFLOW) { // outflow
apply_outflow_fields(d_index, density, heat, fuel, react, color_r, color_g, color_b);
@@ -1982,7 +2026,7 @@ static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh *
/* update object state */
invert_m4_m4(sds->imat, ob->obmat);
copy_m4_m4(sds->obmat, ob->obmat);
- smoke_set_domain_from_derivedmesh(sds, ob, domain_dm);
+ smoke_set_domain_from_derivedmesh(sds, ob, domain_dm, (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN));
/* use global gravity if enabled */
if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
@@ -2278,7 +2322,9 @@ struct DerivedMesh *smokeModifier_do(SmokeModifierData *smd, Scene *scene, Objec
{
return createDomainGeometry(smd->domain, ob);
}
- else return CDDM_copy(dm);
+ else {
+ return CDDM_copy(dm);
+ }
}
static float calc_voxel_transp(float *result, float *input, int res[3], int *pixel, float *tRay, float correct)
@@ -2405,7 +2451,7 @@ static void smoke_calc_transparency(SmokeDomainSettings *sds, Scene *scene)
bv[3] = (float)sds->res[1]; // y
bv[5] = (float)sds->res[2]; // z
-// #pragma omp parallel for schedule(static,1)
+// #pragma omp parallel for schedule(static, 1)
for (z = 0; z < sds->res[2]; z++)
{
size_t index = z * slabsize;
@@ -2509,7 +2555,8 @@ float smoke_get_velocity_at(struct Object *ob, float position[3], float velocity
return -1.0f;
}
-int smoke_get_data_flags(SmokeDomainSettings *sds) {
+int smoke_get_data_flags(SmokeDomainSettings *sds)
+{
int flags = 0;
if (smoke_has_heat(sds->fluid)) flags |= SM_ACTIVE_HEAT;
if (smoke_has_fuel(sds->fluid)) flags |= SM_ACTIVE_FIRE;
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index bb0cfe1a5c6..8e5e0da20f9 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -200,18 +200,18 @@ static float sb_time_scale(Object *ob)
SoftBody *sb= ob->soft; /* is supposed to be there */
if (sb) {
return(sb->physics_speed);
- /*hrms .. this could be IPO as well :)
- estimated range [0.001 sluggish slug - 100.0 very fast (i hope ODE solver can handle that)]
- 1 approx = a unit 1 pendulum at g = 9.8 [earth conditions] has period 65 frames
- theory would give a 50 frames period .. so there must be something inaccurate .. looking for that (BM)
+ /* hrms .. this could be IPO as well :)
+ * estimated range [0.001 sluggish slug - 100.0 very fast (i hope ODE solver can handle that)]
+ * 1 approx = a unit 1 pendulum at g = 9.8 [earth conditions] has period 65 frames
+ * theory would give a 50 frames period .. so there must be something inaccurate .. looking for that (BM)
*/
}
return (1.0f);
/*
- this would be frames/sec independent timing assuming 25 fps is default
- but does not work very well with NLA
- return (25.0f/scene->r.frs_sec)
- */
+ * this would be frames/sec independent timing assuming 25 fps is default
+ * but does not work very well with NLA
+ * return (25.0f/scene->r.frs_sec)
+ */
}
/*--- frame based timing ---*/
@@ -1034,7 +1034,7 @@ static int sb_detect_aabb_collisionCached(float UNUSED(force[3]), unsigned int U
hash = vertexowner->soft->scratch->colliderhash;
ihash = BLI_ghashIterator_new(hash);
- while (!BLI_ghashIterator_isDone(ihash) ) {
+ while (BLI_ghashIterator_notDone(ihash) ) {
ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
ob = BLI_ghashIterator_getKey (ihash);
@@ -1097,12 +1097,12 @@ static int sb_detect_face_pointCached(float face_v1[3], float face_v2[3], float
float facedist, outerfacethickness, tune = 10.f;
int a, deflected=0;
- aabbmin[0] = MIN3(face_v1[0], face_v2[0], face_v3[0]);
- aabbmin[1] = MIN3(face_v1[1], face_v2[1], face_v3[1]);
- aabbmin[2] = MIN3(face_v1[2], face_v2[2], face_v3[2]);
- aabbmax[0] = MAX3(face_v1[0], face_v2[0], face_v3[0]);
- aabbmax[1] = MAX3(face_v1[1], face_v2[1], face_v3[1]);
- aabbmax[2] = MAX3(face_v1[2], face_v2[2], face_v3[2]);
+ aabbmin[0] = min_fff(face_v1[0], face_v2[0], face_v3[0]);
+ aabbmin[1] = min_fff(face_v1[1], face_v2[1], face_v3[1]);
+ aabbmin[2] = min_fff(face_v1[2], face_v2[2], face_v3[2]);
+ aabbmax[0] = max_fff(face_v1[0], face_v2[0], face_v3[0]);
+ aabbmax[1] = max_fff(face_v1[1], face_v2[1], face_v3[1]);
+ aabbmax[2] = max_fff(face_v1[2], face_v2[2], face_v3[2]);
/* calculate face normal once again SIGH */
sub_v3_v3v3(edge1, face_v1, face_v2);
@@ -1113,7 +1113,7 @@ static int sb_detect_face_pointCached(float face_v1[3], float face_v2[3], float
hash = vertexowner->soft->scratch->colliderhash;
ihash = BLI_ghashIterator_new(hash);
- while (!BLI_ghashIterator_isDone(ihash) ) {
+ while (BLI_ghashIterator_notDone(ihash) ) {
ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
ob = BLI_ghashIterator_getKey (ihash);
@@ -1196,16 +1196,16 @@ static int sb_detect_face_collisionCached(float face_v1[3], float face_v2[3], fl
float t, tune = 10.0f;
int a, deflected=0;
- aabbmin[0] = MIN3(face_v1[0], face_v2[0], face_v3[0]);
- aabbmin[1] = MIN3(face_v1[1], face_v2[1], face_v3[1]);
- aabbmin[2] = MIN3(face_v1[2], face_v2[2], face_v3[2]);
- aabbmax[0] = MAX3(face_v1[0], face_v2[0], face_v3[0]);
- aabbmax[1] = MAX3(face_v1[1], face_v2[1], face_v3[1]);
- aabbmax[2] = MAX3(face_v1[2], face_v2[2], face_v3[2]);
+ aabbmin[0] = min_fff(face_v1[0], face_v2[0], face_v3[0]);
+ aabbmin[1] = min_fff(face_v1[1], face_v2[1], face_v3[1]);
+ aabbmin[2] = min_fff(face_v1[2], face_v2[2], face_v3[2]);
+ aabbmax[0] = max_fff(face_v1[0], face_v2[0], face_v3[0]);
+ aabbmax[1] = max_fff(face_v1[1], face_v2[1], face_v3[1]);
+ aabbmax[2] = max_fff(face_v1[2], face_v2[2], face_v3[2]);
hash = vertexowner->soft->scratch->colliderhash;
ihash = BLI_ghashIterator_new(hash);
- while (!BLI_ghashIterator_isDone(ihash) ) {
+ while (BLI_ghashIterator_notDone(ihash) ) {
ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
ob = BLI_ghashIterator_getKey (ihash);
@@ -1305,7 +1305,7 @@ static int sb_detect_face_collisionCached(float face_v1[3], float face_v2[3], fl
normalize_v3(d_nvect);
if (
/* isect_line_tri_v3(nv1, nv3, face_v1, face_v2, face_v3, &t, NULL) ||
- we did that edge already */
+ * 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);
@@ -1433,7 +1433,7 @@ static int sb_detect_edge_collisionCached(float edge_v1[3], float edge_v2[3], fl
hash = vertexowner->soft->scratch->colliderhash;
ihash = BLI_ghashIterator_new(hash);
- while (!BLI_ghashIterator_isDone(ihash) ) {
+ while (BLI_ghashIterator_notDone(ihash) ) {
ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
ob = BLI_ghashIterator_getKey (ihash);
@@ -1763,7 +1763,7 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3],
outerforceaccu[0]=outerforceaccu[1]=outerforceaccu[2]=0.0f;
innerforceaccu[0]=innerforceaccu[1]=innerforceaccu[2]=0.0f;
/* go */
- while (!BLI_ghashIterator_isDone(ihash) ) {
+ while (BLI_ghashIterator_notDone(ihash) ) {
ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash);
ob = BLI_ghashIterator_getKey (ihash);
@@ -1957,7 +1957,7 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3],
}
closest_to_line_segment_v3(ve, opco, nv2, nv3);
- sub_v3_v3v3(ve, opco, ve);
+ sub_v3_v3v3(ve, opco, ve);
dist = normalize_v3(ve);
if ((dist < outerfacethickness)&&(dist < mindistedge )) {
copy_v3_v3(coledge, ve);
@@ -1966,7 +1966,7 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3],
}
closest_to_line_segment_v3(ve, opco, nv3, nv1);
- sub_v3_v3v3(ve, opco, ve);
+ sub_v3_v3v3(ve, opco, ve);
dist = normalize_v3(ve);
if ((dist < outerfacethickness)&&(dist < mindistedge )) {
copy_v3_v3(coledge, ve);
@@ -4108,18 +4108,6 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
softbody_reset(ob, sb, vertexCos, numVerts);
}
- /* continue physics special case */
- if (BKE_ptcache_get_continue_physics()) {
- BKE_ptcache_invalidate(cache);
- /* do simulation */
- dtime = timescale;
- softbody_update_positions(ob, sb, vertexCos, numVerts);
- softbody_step(scene, ob, sb, dtime);
- softbody_to_object(ob, vertexCos, numVerts, 0);
- sb->last_frame = framenr;
- return;
- }
-
/* still no points? go away */
if (sb->totpoint==0) {
return;
diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c
index 09440591826..f3391803294 100644
--- a/source/blender/blenkernel/intern/speaker.c
+++ b/source/blender/blenkernel/intern/speaker.c
@@ -35,7 +35,6 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BLI_bpath.h"
#include "BKE_animsys.h"
#include "BKE_global.h"
@@ -43,11 +42,11 @@
#include "BKE_main.h"
#include "BKE_speaker.h"
-void *BKE_speaker_add(const char *name)
+void *BKE_speaker_add(Main *bmain, const char *name)
{
Speaker *spk;
- spk = BKE_libblock_alloc(&G.main->speaker, ID_SPK, name);
+ spk = BKE_libblock_alloc(&bmain->speaker, ID_SPK, name);
spk->attenuation = 1.0f;
spk->cone_angle_inner = 360.0f;
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index be8b572417e..d3ffde33f0d 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -50,8 +50,8 @@
#include "BLI_edgehash.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
-#include "BLI_pbvh.h"
+#include "BKE_pbvh.h"
#include "BKE_ccg.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
@@ -295,7 +295,7 @@ 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_make(mpoly, mloop, mloopuv, totface, totvert, 0, limit);
+ vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, 0, limit);
if (!vmap)
return 0;
@@ -1013,7 +1013,11 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf)
mf->flag = faceFlags[i].flag;
mf->mat_nr = faceFlags[i].mat_nr;
}
- else mf->flag = ME_SMOOTH;
+ else {
+ mf->flag = ME_SMOOTH;
+}
+
+ mf->edcode = 0;
}
/* Translate GridHidden into the ME_HIDE flag for MVerts. Assumes
@@ -1093,6 +1097,14 @@ void subsurf_copy_grid_paint_mask(DerivedMesh *dm, const MPoly *mpoly,
}
}
+/* utility functon */
+BLI_INLINE void ccgDM_to_MVert(MVert *mv, const CCGKey *key, CCGElem *elem)
+{
+ copy_v3_v3(mv->co, CCG_elem_co(key, elem));
+ normal_float_to_short_v3(mv->no, CCG_elem_no(key, elem));
+ mv->flag = mv->bweight = 0;
+}
+
static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
@@ -1103,7 +1115,7 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
int totvert, totedge, totface;
int gridSize = ccgSubSurf_getGridSize(ss);
int edgeSize = ccgSubSurf_getEdgeSize(ss);
- int i = 0;
+ unsigned int i = 0;
CCG_key_top_level(&key, ss);
@@ -1113,24 +1125,20 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
vd = ccgSubSurf_getFaceCenterData(f);
- copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd));
- normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd));
- i++;
+ ccgDM_to_MVert(&mvert[i++], &key, vd);
for (S = 0; S < numVerts; S++) {
- for (x = 1; x < gridSize - 1; x++, i++) {
+ for (x = 1; x < gridSize - 1; x++) {
vd = ccgSubSurf_getFaceGridEdgeData(ss, f, S, x);
- copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd));
- normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd));
+ ccgDM_to_MVert(&mvert[i++], &key, vd);
}
}
for (S = 0; S < numVerts; S++) {
for (y = 1; y < gridSize - 1; y++) {
- for (x = 1; x < gridSize - 1; x++, i++) {
+ for (x = 1; x < gridSize - 1; x++) {
vd = ccgSubSurf_getFaceGridData(ss, f, S, x, y);
- copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd));
- normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd));
+ ccgDM_to_MVert(&mvert[i++], &key, vd);
}
}
}
@@ -1141,15 +1149,14 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
CCGEdge *e = ccgdm->edgeMap[index].edge;
int x;
- for (x = 1; x < edgeSize - 1; x++, i++) {
- vd = ccgSubSurf_getEdgeData(ss, e, x);
- copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd));
+ for (x = 1; x < edgeSize - 1; x++) {
/* This gives errors with -debug-fpe
* the normals don't seem to be unit length.
* this is most likely caused by edges with no
* faces which are now zerod out, see comment in:
* ccgSubSurf__calcVertNormals(), - campbell */
- normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd));
+ vd = ccgSubSurf_getEdgeData(ss, e, x);
+ ccgDM_to_MVert(&mvert[i++], &key, vd);
}
}
@@ -1158,12 +1165,20 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
CCGVert *v = ccgdm->vertMap[index].vert;
vd = ccgSubSurf_getVertData(ss, v);
- copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd));
- normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd));
- i++;
+ ccgDM_to_MVert(&mvert[i++], &key, vd);
}
}
+
+/* utility functon */
+BLI_INLINE void ccgDM_to_MEdge(MEdge *med, const int v1, const int v2, const short flag)
+{
+ med->v1 = v1;
+ med->v2 = v2;
+ med->crease = med->bweight = 0;
+ med->flag = flag;
+}
+
static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
@@ -1172,8 +1187,9 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
int totedge, totface;
int gridSize = ccgSubSurf_getGridSize(ss);
int edgeSize = ccgSubSurf_getEdgeSize(ss);
- int i = 0;
+ unsigned int i = 0;
short *edgeFlags = ccgdm->edgeFlags;
+ const short ed_interior_flag = ccgdm->drawInteriorEdges ? (ME_EDGEDRAW | ME_EDGERENDER) : 0;
totface = ccgSubSurf_getNumFaces(ss);
for (index = 0; index < totface; index++) {
@@ -1182,36 +1198,22 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
for (S = 0; S < numVerts; S++) {
for (x = 0; x < gridSize - 1; x++) {
- MEdge *med = &medge[i];
-
- if (ccgdm->drawInteriorEdges)
- med->flag = ME_EDGEDRAW | ME_EDGERENDER;
- med->v1 = getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize);
- med->v2 = getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize);
- i++;
+ ccgDM_to_MEdge(&medge[i++],
+ getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize),
+ getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize),
+ ed_interior_flag);
}
for (x = 1; x < gridSize - 1; x++) {
for (y = 0; y < gridSize - 1; y++) {
- MEdge *med;
-
- med = &medge[i];
- if (ccgdm->drawInteriorEdges)
- med->flag = ME_EDGEDRAW | ME_EDGERENDER;
- med->v1 = getFaceIndex(ss, f, S, x, y,
- edgeSize, gridSize);
- med->v2 = getFaceIndex(ss, f, S, x, y + 1,
- edgeSize, gridSize);
- i++;
-
- med = &medge[i];
- if (ccgdm->drawInteriorEdges)
- med->flag = ME_EDGEDRAW | ME_EDGERENDER;
- med->v1 = getFaceIndex(ss, f, S, y, x,
- edgeSize, gridSize);
- med->v2 = getFaceIndex(ss, f, S, y + 1, x,
- edgeSize, gridSize);
- i++;
+ ccgDM_to_MEdge(&medge[i++],
+ getFaceIndex(ss, f, S, x, y, edgeSize, gridSize),
+ getFaceIndex(ss, f, S, x, y + 1, edgeSize, gridSize),
+ ed_interior_flag);
+ ccgDM_to_MEdge(&medge[i++],
+ getFaceIndex(ss, f, S, y, x, edgeSize, gridSize),
+ getFaceIndex(ss, f, S, y + 1, x, edgeSize, gridSize),
+ ed_interior_flag);
}
}
}
@@ -1220,27 +1222,28 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
totedge = ccgSubSurf_getNumEdges(ss);
for (index = 0; index < totedge; index++) {
CCGEdge *e = ccgdm->edgeMap[index].edge;
- unsigned int flags = 0;
+ short ed_flag = 0;
int x;
int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
- if (!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
+ if (!ccgSubSurf_getEdgeNumFaces(e)) {
+ ed_flag |= ME_LOOSEEDGE;
+ }
if (edgeFlags) {
if (edgeIdx != -1) {
- flags |= ((edgeFlags[index] & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW | ME_EDGERENDER);
+ ed_flag |= ((edgeFlags[index] & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW | ME_EDGERENDER);
}
}
else {
- flags |= ME_EDGEDRAW | ME_EDGERENDER;
+ ed_flag |= ME_EDGEDRAW | ME_EDGERENDER;
}
for (x = 0; x < edgeSize - 1; x++) {
- MEdge *med = &medge[i];
- med->v1 = getEdgeIndex(ss, e, x, edgeSize);
- med->v2 = getEdgeIndex(ss, e, x + 1, edgeSize);
- med->flag = flags;
- i++;
+ ccgDM_to_MEdge(&medge[i++],
+ getEdgeIndex(ss, e, x, edgeSize),
+ getEdgeIndex(ss, e, x + 1, edgeSize),
+ ed_flag);
}
}
}
@@ -1278,6 +1281,7 @@ static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
edgeSize, gridSize);
mf->mat_nr = mat_nr;
mf->flag = flag;
+ mf->edcode = 0;
i++;
}
@@ -1314,8 +1318,8 @@ static void ccgDM_copyFinalLoopArray(DerivedMesh *dm, MLoop *mloop)
for (index = 0; index < totface; index++) {
CCGFace *f = ccgdm->faceMap[index].face;
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
- /* int flag = (faceFlags)? faceFlags[index*2]: ME_SMOOTH; */ /* UNUSED */
- /* int mat_nr = (faceFlags)? faceFlags[index*2+1]: 0; */ /* UNUSED */
+ /* int flag = (faceFlags) ? faceFlags[index * 2]: ME_SMOOTH; */ /* UNUSED */
+ /* int mat_nr = (faceFlags) ? faceFlags[index * 2 + 1]: 0; */ /* UNUSED */
for (S = 0; S < numVerts; S++) {
for (y = 0; y < gridSize - 1; y++) {
@@ -1569,7 +1573,7 @@ static void ccgdm_pbvh_update(CCGDerivedMesh *ccgdm)
CCGFace **faces;
int totface;
- BLI_pbvh_get_grid_updates(ccgdm->pbvh, 1, (void ***)&faces, &totface);
+ BKE_pbvh_get_grid_updates(ccgdm->pbvh, 1, (void ***)&faces, &totface);
if (totface) {
ccgSubSurf_updateFromFaces(ccgdm->ss, 0, faces, totface);
ccgSubSurf_updateNormals(ccgdm->ss, faces, totface);
@@ -1707,7 +1711,8 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)
if (ccgdm->pbvh && ccgdm->multires.mmd && !fast) {
if (dm->numTessFaceData) {
- BLI_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL, setMaterial);
+ BKE_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL,
+ setMaterial, FALSE);
glShadeModel(GL_FLAT);
}
@@ -2980,7 +2985,7 @@ static const MeshElemMap *ccgDM_getPolyMap(Object *ob, DerivedMesh *dm)
if (!ccgdm->multires.mmd && !ccgdm->pmap && ob->type == OB_MESH) {
Mesh *me = ob->data;
- create_vert_poly_map(&ccgdm->pmap, &ccgdm->pmap_mem,
+ BKE_mesh_vert_poly_map_create(&ccgdm->pmap, &ccgdm->pmap_mem,
me->mpoly, me->mloop,
me->totvert, me->totpoly, me->totloop);
}
@@ -3025,7 +3030,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);
- BLI_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void **)ccgdm->gridFaces,
+ BKE_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void **)ccgdm->gridFaces,
ccgdm->gridFlagMats, ccgdm->gridHidden);
}
@@ -3043,15 +3048,15 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
numGrids = ccgDM_getNumGrids(dm);
- ob->sculpt->pbvh = ccgdm->pbvh = BLI_pbvh_new();
- BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency,
+ ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new();
+ BKE_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency,
numGrids, &key, (void **) ccgdm->gridFaces, ccgdm->gridFlagMats, ccgdm->gridHidden);
}
else if (ob->type == OB_MESH) {
Mesh *me = ob->data;
- ob->sculpt->pbvh = ccgdm->pbvh = BLI_pbvh_new();
+ 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 */
- BLI_pbvh_build_mesh(ccgdm->pbvh, me->mface, me->mvert,
+ BKE_pbvh_build_mesh(ccgdm->pbvh, me->mface, me->mvert,
me->totface, me->totvert, &me->vdata);
}
@@ -3098,12 +3103,15 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
int numTex, numCol;
int hasPCol, hasOrigSpace;
int gridInternalEdges;
- float *w = NULL;
WeightTable wtable = {0};
/* MCol *mcol; */ /* UNUSED */
MEdge *medge = NULL;
/* MFace *mface = NULL; */
MPoly *mpoly = NULL;
+#ifdef WITH_FREESTYLE
+ FreestyleEdge *fed = NULL, *ccgdm_fed = NULL;
+ FreestyleFace *ffa = NULL, *ccgdm_ffa = NULL;
+#endif
DM_from_template(&ccgdm->dm, dm, DM_TYPE_CCGDM,
ccgSubSurf_getNumFinalVerts(ss),
@@ -3278,6 +3286,18 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
has_edge_origindex = CustomData_has_layer(&ccgdm->dm.edgeData, CD_ORIGINDEX);
+#ifdef WITH_FREESTYLE
+ fed = DM_get_edge_data_layer(dm, CD_FREESTYLE_EDGE);
+ if (fed) {
+ ccgdm_fed = CustomData_add_layer(&ccgdm->dm.edgeData, CD_FREESTYLE_EDGE, CD_CALLOC, NULL,
+ ccgSubSurf_getNumFinalEdges(ss));
+ }
+ ffa = DM_get_poly_data_layer(dm, CD_FREESTYLE_FACE);
+ if (ffa) {
+ ccgdm_ffa = CustomData_add_layer(&ccgdm->dm.faceData, CD_FREESTYLE_FACE, CD_CALLOC, NULL,
+ ccgSubSurf_getNumFinalFaces(ss));
+ }
+#endif
loopindex = loopindex2 = 0; /* current loop index */
for (index = 0; index < totface; index++) {
@@ -3286,7 +3306,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
int numFinalEdges = numVerts * (gridSideEdges + gridInternalEdges);
int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
int g2_wid = gridCuts + 2;
- float *w2;
+ float *w, *w2;
int s, x, y;
w = get_ss_weights(&wtable, gridCuts, numVerts);
@@ -3299,8 +3319,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
faceFlags->mat_nr = mpoly ? mpoly[origIndex].mat_nr : 0;
faceFlags++;
- origIndex = base_polyOrigIndex ? base_polyOrigIndex[origIndex] : origIndex;
-
/* set the face base vert */
*((int *)ccgSubSurf_getFaceUserData(ss, f)) = vertNum;
@@ -3319,7 +3337,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
/*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);
+ w2 = w; // + numVerts*(g2_wid-1) * (g2_wid-1); //numVerts*((g2_wid-1) * g2_wid+g2_wid-1);
DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2,
numVerts, vertNum);
if (vertOrigIndex) {
@@ -3408,7 +3426,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
faceOrigIndex++;
}
if (polyOrigIndex) {
- *polyOrigIndex = origIndex;
+ *polyOrigIndex = base_polyOrigIndex ? base_polyOrigIndex[origIndex] : origIndex;
polyOrigIndex++;
}
@@ -3417,6 +3435,12 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
/* This is a simple one to one mapping, here... */
polyidx[faceNum] = faceNum;
+#ifdef WITH_FREESTYLE
+ if (ffa && ffa[index].flag & FREESTYLE_FACE_MARK) {
+ ccgdm_ffa[faceNum].flag |= FREESTYLE_FACE_MARK;
+ }
+#endif
+
faceNum++;
}
}
@@ -3466,6 +3490,14 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
}
}
+#ifdef WITH_FREESTYLE
+ if (fed && fed[index].flag & FREESTYLE_EDGE_MARK) {
+ for (i = 0; i < numFinalEdges; ++i) {
+ ccgdm_fed[edgeNum + i].flag |= FREESTYLE_EDGE_MARK;
+ }
+ }
+#endif
+
edgeNum += numFinalEdges;
}
diff --git a/source/blender/blenkernel/intern/suggestions.c b/source/blender/blenkernel/intern/suggestions.c
index ff9774f85af..6f9736df683 100644
--- a/source/blender/blenkernel/intern/suggestions.c
+++ b/source/blender/blenkernel/intern/suggestions.c
@@ -163,13 +163,13 @@ void texttool_suggest_add(const char *name, char type)
suggestions.top = 0;
}
-void texttool_suggest_prefix(const char *prefix)
+void texttool_suggest_prefix(const char *prefix, const int prefix_len)
{
SuggItem *match, *first, *last;
- int cmp, len = strlen(prefix), top = 0;
+ int cmp, top = 0;
if (!suggestions.first) return;
- if (len == 0) {
+ if (prefix_len == 0) {
suggestions.selected = suggestions.firstmatch = suggestions.first;
suggestions.lastmatch = suggestions.last;
return;
@@ -177,7 +177,7 @@ void texttool_suggest_prefix(const char *prefix)
first = last = NULL;
for (match = suggestions.first; match; match = match->next) {
- cmp = txttl_cmp(prefix, match->name, len);
+ cmp = txttl_cmp(prefix, match->name, prefix_len);
if (cmp == 0) {
if (!first) {
first = match;
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 322b77e0462..3936c533a41 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -38,12 +38,12 @@
#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_string_cursor_utf8.h"
#include "BLI_string_utf8.h"
#include "BLI_listbase.h"
-#include "BLI_utildefines.h"
#include "BLI_fileops.h"
#include "DNA_constraint_types.h"
@@ -171,9 +171,8 @@ void BKE_text_free(Text *text)
#endif
}
-Text *BKE_text_add(const char *name)
+Text *BKE_text_add(Main *bmain, const char *name)
{
- Main *bmain = G.main;
Text *ta;
TextLine *tmp;
@@ -363,9 +362,8 @@ int BKE_text_reload(Text *text)
return 1;
}
-Text *BKE_text_load(const char *file, const char *relpath)
+Text *BKE_text_load(Main *bmain, const char *file, const char *relpath)
{
- Main *bmain = G.main;
FILE *fp;
int i, llen, len;
unsigned char *buffer;
@@ -793,6 +791,29 @@ int txt_utf8_index_to_offset(const char *str, int index)
return offset;
}
+int txt_utf8_offset_to_column(const char *str, int offset)
+{
+ int column = 0, pos = 0;
+ while (pos < offset) {
+ column += BLI_str_utf8_char_width_safe(str + pos);
+ pos += BLI_str_utf8_size_safe(str + pos);
+ }
+ return column;
+}
+
+int txt_utf8_column_to_offset(const char *str, int column)
+{
+ int offset = 0, pos = 0, col;
+ while (pos < column) {
+ col = BLI_str_utf8_char_width_safe(str + offset);
+ if (pos + col > column)
+ break;
+ offset += BLI_str_utf8_size_safe(str + offset);
+ pos += col;
+ }
+ return offset;
+}
+
/* returns the real number of characters in string */
/* not the same as BLI_strlen_utf8, which returns length for wide characters */
static int txt_utf8_len(const char *src)
@@ -806,6 +827,17 @@ static int txt_utf8_len(const char *src)
return len;
}
+static int txt_utf8_width(const char *src)
+{
+ int col = 0;
+
+ for (; *src; src += BLI_str_utf8_size(src)) {
+ col += BLI_str_utf8_char_width(src);
+ }
+
+ return col;
+}
+
void txt_move_up(Text *text, short sel)
{
TextLine **linep;
@@ -817,10 +849,10 @@ void txt_move_up(Text *text, short sel)
if (!*linep) return;
if ((*linep)->prev) {
- int index = txt_utf8_offset_to_index((*linep)->line, *charp);
+ int column = txt_utf8_offset_to_column((*linep)->line, *charp);
*linep = (*linep)->prev;
- if (index > txt_utf8_len((*linep)->line)) *charp = (*linep)->len;
- else *charp = txt_utf8_index_to_offset((*linep)->line, index);
+ if (column > txt_utf8_width((*linep)->line)) *charp = (*linep)->len;
+ else *charp = txt_utf8_column_to_offset((*linep)->line, column);
}
else {
@@ -841,10 +873,10 @@ void txt_move_down(Text *text, short sel)
if (!*linep) return;
if ((*linep)->next) {
- int index = txt_utf8_offset_to_index((*linep)->line, *charp);
+ int column = txt_utf8_offset_to_column((*linep)->line, *charp);
*linep = (*linep)->next;
- if (index > txt_utf8_len((*linep)->line)) *charp = (*linep)->len;
- else *charp = txt_utf8_index_to_offset((*linep)->line, index);
+ if (column > txt_utf8_width((*linep)->line)) *charp = (*linep)->len;
+ else *charp = txt_utf8_column_to_offset((*linep)->line, column);
}
else {
txt_move_eol(text, sel);
@@ -932,13 +964,15 @@ void txt_move_right(Text *text, short sel)
tabsize++;
(*charp) = i;
}
- else (*charp) += BLI_str_utf8_size((*linep)->line + *charp);
+ else {
+ (*charp) += BLI_str_utf8_size((*linep)->line + *charp);
+ }
}
if (!sel) txt_pop_sel(text);
}
-void txt_jump_left(Text *text, short sel)
+void txt_jump_left(Text *text, bool sel, bool use_init_step)
{
TextLine **linep;
int *charp;
@@ -950,12 +984,12 @@ void txt_jump_left(Text *text, short sel)
BLI_str_cursor_step_utf8((*linep)->line, (*linep)->len,
charp, STRCUR_DIR_PREV,
- STRCUR_JUMP_DELIM);
+ STRCUR_JUMP_DELIM, use_init_step);
if (!sel) txt_pop_sel(text);
}
-void txt_jump_right(Text *text, short sel)
+void txt_jump_right(Text *text, bool sel, bool use_init_step)
{
TextLine **linep;
int *charp;
@@ -967,7 +1001,7 @@ void txt_jump_right(Text *text, short sel)
BLI_str_cursor_step_utf8((*linep)->line, (*linep)->len,
charp, STRCUR_DIR_NEXT,
- STRCUR_JUMP_DELIM);
+ STRCUR_JUMP_DELIM, use_init_step);
if (!sel) txt_pop_sel(text);
}
@@ -2404,7 +2438,7 @@ void txt_delete_char(Text *text)
void txt_delete_word(Text *text)
{
- txt_jump_right(text, 1);
+ txt_jump_right(text, true, true);
txt_delete_sel(text);
}
@@ -2453,7 +2487,7 @@ void txt_backspace_char(Text *text)
void txt_backspace_word(Text *text)
{
- txt_jump_left(text, 1);
+ txt_jump_left(text, true, true);
txt_delete_sel(text);
}
@@ -2562,6 +2596,7 @@ int txt_replace_char(Text *text, unsigned int add)
memcpy(text->curl->line + text->curc, ch, add_size);
text->curc += add_size;
+ text->curl->len += add_size - del_size;
txt_pop_sel(text);
txt_make_dirty(text);
@@ -2826,7 +2861,7 @@ void txt_move_lines(struct Text *text, const int direction)
}
}
-int setcurr_tab_spaces(Text *text, int space)
+int txt_setcurr_tab_spaces(Text *text, int space)
{
int i = 0;
int test = 0;
@@ -2930,9 +2965,46 @@ int text_check_identifier(const char ch)
return 0;
}
+int 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;
+}
+
+#ifndef WITH_PYTHON
+int text_check_identifier_unicode(const unsigned int ch)
+{
+ return (ch < 255 && text_check_identifier((char)ch));
+}
+
+int text_check_identifier_nodigit_unicode(const unsigned int ch)
+{
+ return (ch < 255 && text_check_identifier_nodigit((char)ch));
+}
+#endif /* WITH_PYTHON */
+
int text_check_whitespace(const char ch)
{
if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
return 1;
return 0;
}
+
+int text_find_identifier_start(const char *str, int i)
+{
+ if (UNLIKELY(i <= 0)) {
+ return 0;
+ }
+
+ while (i--) {
+ if (!text_check_identifier(str[i])) {
+ break;
+ }
+ }
+ i++;
+ return i;
+}
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 6d0313f6334..2517324242b 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -42,7 +42,6 @@
#include "BLI_math.h"
#include "BLI_kdopbvh.h"
#include "BLI_utildefines.h"
-#include "BLI_bpath.h"
#include "DNA_key_types.h"
#include "DNA_object_types.h"
@@ -149,7 +148,7 @@ void default_color_mapping(ColorMapping *colormap)
{
memset(colormap, 0, sizeof(ColorMapping));
- init_colorband(&colormap->coba, 1);
+ init_colorband(&colormap->coba, true);
colormap->bright = 1.0;
colormap->contrast = 1.0;
@@ -164,7 +163,7 @@ void default_color_mapping(ColorMapping *colormap)
/* ****************** COLORBAND ******************* */
-void init_colorband(ColorBand *coba, int rangetype)
+void init_colorband(ColorBand *coba, bool rangetype)
{
int a;
@@ -206,7 +205,7 @@ void init_colorband(ColorBand *coba, int rangetype)
}
-ColorBand *add_colorband(int rangetype)
+ColorBand *add_colorband(bool rangetype)
{
ColorBand *coba;
@@ -257,7 +256,9 @@ int do_colorband(const ColorBand *coba, float in, float out[4])
left.pos = 0.0f;
cbd2 = &left;
}
- else cbd2 = cbd1 - 1;
+ else {
+ cbd2 = cbd1 - 1;
+ }
if (in >= cbd1->pos && coba->ipotype < 2) {
out[0] = cbd1->r;
@@ -541,9 +542,8 @@ void tex_set_type(Tex *tex, int type)
/* ------------------------------------------------------------------------- */
-Tex *add_texture(const char *name)
+Tex *add_texture(Main *bmain, const char *name)
{
- Main *bmain = G.main;
Tex *tex;
tex = BKE_libblock_alloc(&bmain->tex, ID_TE, name);
@@ -616,6 +616,7 @@ void default_mtex(MTex *mtex)
mtex->gravityfac = 1.0f;
mtex->fieldfac = 1.0f;
mtex->normapspace = MTEX_NSPACE_TANGENT;
+ mtex->brush_map_mode = MTEX_MAP_MODE_TILED;
}
@@ -694,7 +695,7 @@ Tex *BKE_texture_copy(Tex *tex)
if (tex->nodetree) {
if (tex->nodetree->execdata) {
- ntreeTexEndExecTree(tex->nodetree->execdata, 1);
+ ntreeTexEndExecTree(tex->nodetree->execdata);
}
texn->nodetree = ntreeCopyTree(tex->nodetree);
}
@@ -912,15 +913,18 @@ void autotexname(Tex *tex)
else if (tex->type == TEX_IMAGE) {
ima = tex->ima;
if (ima) {
- BLI_strncpy(di, ima->name, sizeof(di));
- BLI_splitdirstring(di, fi);
+ BLI_split_file_part(ima->name, fi, sizeof(fi));
strcpy(di, "I.");
strcat(di, fi);
new_id(&bmain->tex, (ID *)tex, di);
}
- else new_id(&bmain->tex, (ID *)tex, texstr[tex->type]);
+ else {
+ new_id(&bmain->tex, (ID *)tex, texstr[tex->type]);
+ }
+ }
+ else {
+ new_id(&bmain->tex, (ID *)tex, texstr[tex->type]);
}
- else new_id(&bmain->tex, (ID *)tex, texstr[tex->type]);
}
}
#endif
@@ -1281,7 +1285,7 @@ PointDensity *BKE_add_pointdensity(void)
pd->noise_depth = 1;
pd->noise_fac = 1.0f;
pd->noise_influence = TEX_PD_NOISE_STATIC;
- pd->coba = add_colorband(1);
+ pd->coba = add_colorband(true);
pd->speed_scale = 1.0f;
pd->totpoints = 0;
pd->object = NULL;
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index 801fecc9f7c..df10d1374bb 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -141,8 +141,10 @@ static void tracking_dopesheet_free(MovieTrackingDopesheet *dopesheet)
}
BLI_freelistN(&dopesheet->channels);
+ BLI_freelistN(&dopesheet->coverage_segments);
dopesheet->channels.first = dopesheet->channels.last = NULL;
+ dopesheet->coverage_segments.first = dopesheet->coverage_segments.last = NULL;
dopesheet->tot_channel = 0;
}
@@ -169,8 +171,9 @@ void BKE_tracking_settings_init(MovieTracking *tracking)
tracking->settings.default_motion_model = TRACK_MOTION_MODEL_TRANSLATION;
tracking->settings.default_minimum_correlation = 0.75;
- tracking->settings.default_pattern_size = 11;
+ tracking->settings.default_pattern_size = 15;
tracking->settings.default_search_size = 61;
+ tracking->settings.default_algorithm_flag |= TRACK_ALGORITHM_FLAG_USE_BRUTE;
tracking->settings.dist = 1;
tracking->settings.object_distance = 1;
tracking->settings.reconstruction_success_threshold = 1e-3;
@@ -258,7 +261,9 @@ void BKE_tracking_get_projection_matrix(MovieTracking *tracking, MovieTrackingOb
invert_m4_m4(imat, camera->mat);
mult_m4_m4m4(mat, winmat, imat);
}
- else copy_m4_m4(mat, winmat);
+ else {
+ copy_m4_m4(mat, winmat);
+ }
}
/* **** space transformation functions **** */
@@ -1186,6 +1191,7 @@ MovieTrackingObject *BKE_tracking_object_add(MovieTracking *tracking, const char
object->keyframe2 = 30;
BKE_tracking_object_unique_name(tracking, object);
+ BKE_tracking_dopesheet_tag_update(tracking);
return object;
}
@@ -1220,6 +1226,9 @@ int BKE_tracking_object_delete(MovieTracking *tracking, MovieTrackingObject *obj
tracking->objectnr = index - 1;
else
tracking->objectnr = 0;
+
+ BKE_tracking_dopesheet_tag_update(tracking);
+
return TRUE;
}
@@ -1426,40 +1435,65 @@ void BKE_tracking_camera_get_reconstructed_interpolate(MovieTracking *tracking,
/*********************** Distortion/Undistortion *************************/
+#ifdef WITH_LIBMV
+static void cameraIntrinscisOptionsFromTracking(libmv_cameraIntrinsicsOptions *camera_intrinsics_options,
+ MovieTracking *tracking, int calibration_width, int calibration_height)
+{
+ MovieTrackingCamera *camera = &tracking->camera;
+ float aspy = 1.0f / tracking->camera.pixel_aspect;
+
+ camera_intrinsics_options->focal_length = camera->focal;
+
+ camera_intrinsics_options->principal_point_x = camera->principal[0];
+ camera_intrinsics_options->principal_point_y = camera->principal[1] * aspy;
+
+ camera_intrinsics_options->k1 = camera->k1;
+ camera_intrinsics_options->k2 = camera->k2;
+ camera_intrinsics_options->k3 = camera->k3;
+
+ camera_intrinsics_options->image_width = calibration_width;
+ camera_intrinsics_options->image_height = (double) (calibration_height * aspy);
+}
+#endif
+
MovieDistortion *BKE_tracking_distortion_new(void)
{
MovieDistortion *distortion;
distortion = MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create");
+#ifdef WITH_LIBMV
+ distortion->intrinsics = libmv_CameraIntrinsicsNewEmpty();
+#endif
+
return distortion;
}
void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking,
int calibration_width, int calibration_height)
{
- MovieTrackingCamera *camera = &tracking->camera;
- float aspy = 1.0f / tracking->camera.pixel_aspect;
-
#ifdef WITH_LIBMV
- if (!distortion->intrinsics) {
- distortion->intrinsics = libmv_CameraIntrinsicsNew(camera->focal,
- camera->principal[0], camera->principal[1] * aspy,
- camera->k1, camera->k2, camera->k3,
- calibration_width, calibration_height * aspy);
- }
- else {
- libmv_CameraIntrinsicsUpdate(distortion->intrinsics, camera->focal,
- camera->principal[0], camera->principal[1] * aspy,
- camera->k1, camera->k2, camera->k3,
- calibration_width, calibration_height * aspy);
- }
+ libmv_cameraIntrinsicsOptions camera_intrinsics_options;
+
+ cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking,
+ calibration_width, calibration_height);
+
+ libmv_CameraIntrinsicsUpdate(distortion->intrinsics, &camera_intrinsics_options);
#else
(void) distortion;
+ (void) tracking;
(void) calibration_width;
(void) calibration_height;
- (void) camera;
- (void) aspy;
+#endif
+}
+
+void BKE_tracking_distortion_set_threads(MovieDistortion *distortion, int threads)
+{
+#ifdef WITH_LIBMV
+ libmv_CameraIntrinsicsSetThreads(distortion->intrinsics, threads);
+#else
+ (void) distortion;
+ (void) threads;
#endif
}
@@ -1540,15 +1574,17 @@ void BKE_tracking_distort_v2(MovieTracking *tracking, const float co[2], float r
MovieTrackingCamera *camera = &tracking->camera;
#ifdef WITH_LIBMV
+ libmv_cameraIntrinsicsOptions camera_intrinsics_options;
double x, y;
float aspy = 1.0f / tracking->camera.pixel_aspect;
+ cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking, 0, 0);
+
/* normalize coords */
x = (co[0] - camera->principal[0]) / camera->focal;
y = (co[1] - camera->principal[1] * aspy) / camera->focal;
- libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
- camera->k1, camera->k2, camera->k3, x, y, &x, &y);
+ libmv_applyCameraIntrinsics(&camera_intrinsics_options, x, y, &x, &y);
/* result is in image coords already */
r_co[0] = x;
@@ -1565,14 +1601,16 @@ void BKE_tracking_undistort_v2(MovieTracking *tracking, const float co[2], float
MovieTrackingCamera *camera = &tracking->camera;
#ifdef WITH_LIBMV
+ libmv_cameraIntrinsicsOptions camera_intrinsics_options;
double x = co[0], y = co[1];
float aspy = 1.0f / tracking->camera.pixel_aspect;
- libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
- camera->k1, camera->k2, camera->k3, x, y, &x, &y);
+ cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking, 0, 0);
- r_co[0] = x * camera->focal + camera->principal[0];
- r_co[1] = y * camera->focal + camera->principal[1] * aspy;
+ libmv_InvertIntrinsics(&camera_intrinsics_options, x, y, &x, &y);
+
+ r_co[0] = (float)x * camera->focal + camera->principal[0];
+ r_co[1] = (float)y * camera->focal + camera->principal[1] * aspy;
#else
(void) camera;
(void) co;
@@ -1604,6 +1642,67 @@ ImBuf *BKE_tracking_distort_frame(MovieTracking *tracking, ImBuf *ibuf, int cali
calibration_height, overscan, FALSE);
}
+void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, rcti *rect, float delta[2])
+{
+ int a;
+ float pos[2], warped_pos[2];
+ const int coord_delta = 5;
+
+ delta[0] = delta[1] = -FLT_MAX;
+
+ for (a = rect->xmin; a <= rect->xmax + coord_delta; a += coord_delta) {
+ if (a > rect->xmax)
+ a = rect->xmax;
+
+ /* bottom edge */
+ pos[0] = a;
+ pos[1] = rect->ymin;
+
+ BKE_tracking_undistort_v2(tracking, pos, warped_pos);
+
+ delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
+ delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
+
+ /* top edge */
+ pos[0] = a;
+ pos[1] = rect->ymax;
+
+ BKE_tracking_undistort_v2(tracking, pos, warped_pos);
+
+ delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
+ delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
+
+ if (a >= rect->xmax)
+ break;
+ }
+
+ for (a = rect->ymin; a <= rect->ymax + coord_delta; a += coord_delta) {
+ if (a > rect->ymax)
+ a = rect->ymax;
+
+ /* left edge */
+ pos[0] = rect->xmin;
+ pos[1] = a;
+
+ BKE_tracking_undistort_v2(tracking, pos, warped_pos);
+
+ delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
+ delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
+
+ /* right edge */
+ pos[0] = rect->xmax;
+ pos[1] = a;
+
+ BKE_tracking_undistort_v2(tracking, pos, warped_pos);
+
+ delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
+ delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
+
+ if (a >= rect->ymax)
+ break;
+ }
+}
+
/*********************** Image sampling *************************/
static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale)
@@ -1615,7 +1714,7 @@ static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int g
ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *search_ibuf,
MovieTrackingTrack *track, MovieTrackingMarker *marker,
- int use_mask, int num_samples_x, int num_samples_y,
+ int from_anchor, int use_mask, int num_samples_x, int num_samples_y,
float pos[2])
{
#ifdef WITH_LIBMV
@@ -1635,6 +1734,28 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *sea
get_marker_coords_for_tracking(frame_width, frame_height, marker, src_pixel_x, src_pixel_y);
+ /* from_anchor means search buffer was obtained for an anchored position,
+ * which means applying track offset rounded to pixel space (we could not
+ * store search buffer with sub-pixel precision)
+ *
+ * in this case we need to alter coordinates a bit, to compensate rounded
+ * fractional part of offset
+ */
+ if (from_anchor) {
+ int a;
+
+ for (a = 0; a < 5; a++) {
+ src_pixel_x[a] += (double) ((track->offset[0] * frame_width) - ((int) (track->offset[0] * frame_width)));
+ src_pixel_y[a] += (double) ((track->offset[1] * frame_height) - ((int) (track->offset[1] * frame_height)));
+
+ /* when offset is negative, rounding happens in opposite direction */
+ if (track->offset[0] < 0.0f)
+ src_pixel_x[a] += 1.0;
+ if (track->offset[1] < 0.0f)
+ src_pixel_y[a] += 1.0;
+ }
+ }
+
if (use_mask) {
mask = BKE_tracking_track_get_mask(frame_width, frame_height, track, marker);
}
@@ -1660,13 +1781,14 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *sea
/* real sampling requires libmv, but areas are supposing pattern would be
* sampled if search area does exists, so we'll need to create empty
* pattern area here to prevent adding NULL-checks all over just to deal
- * with situation when lubmv is disabled
+ * with situation when libmv is disabled
*/
(void) frame_width;
(void) frame_height;
(void) search_ibuf;
(void) marker;
+ (void) from_anchor;
(void) track;
(void) use_mask;
@@ -1695,7 +1817,7 @@ ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mo
if (search_ibuf) {
pattern_ibuf = BKE_tracking_sample_pattern(ibuf->x, ibuf->y, search_ibuf, track, marker,
- FALSE, num_samples_x, num_samples_y, NULL);
+ anchored, FALSE, num_samples_x, num_samples_y, NULL);
IMB_freeImBuf(search_ibuf);
}
@@ -2578,6 +2700,8 @@ typedef struct MovieReconstructContext {
float principal_point[2];
float k1, k2, k3;
+ int width, height;
+
float reprojection_error;
TracksMap *tracks_map;
@@ -2638,11 +2762,13 @@ static void reconstruct_retrieve_libmv_intrinscis(MovieReconstructContext *conte
&k1, &k2, &k3, &width, &height);
tracking->camera.focal = focal_length;
+
tracking->camera.principal[0] = principal_x;
+ tracking->camera.principal[1] = principal_y / (double)aspy;
- tracking->camera.principal[1] = principal_y / aspy;
tracking->camera.k1 = k1;
tracking->camera.k2 = k2;
+ tracking->camera.k3 = k3;
}
static int reconstruct_retrieve_libmv_tracks(MovieReconstructContext *context, MovieTracking *tracking)
@@ -2776,10 +2902,10 @@ static int reconstruct_refine_intrinsics_get_flags(MovieTracking *tracking, Movi
flags |= LIBMV_REFINE_PRINCIPAL_POINT;
if (refine & REFINE_RADIAL_DISTORTION_K1)
- flags |= REFINE_RADIAL_DISTORTION_K1;
+ flags |= LIBMV_REFINE_RADIAL_DISTORTION_K1;
if (refine & REFINE_RADIAL_DISTORTION_K2)
- flags |= REFINE_RADIAL_DISTORTION_K2;
+ flags |= LIBMV_REFINE_RADIAL_DISTORTION_K2;
return flags;
}
@@ -2850,6 +2976,9 @@ MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieTracking *
context->principal_point[0] = camera->principal[0];
context->principal_point[1] = camera->principal[1] * aspy;
+ context->width = width;
+ context->height = height;
+
context->k1 = camera->k1;
context->k2 = camera->k2;
context->k3 = camera->k3;
@@ -2932,6 +3061,34 @@ static void reconstruct_update_solve_cb(void *customdata, double progress, const
BLI_snprintf(progressdata->stats_message, progressdata->message_size, "Solving camera | %s", message);
}
+
+static void camraIntrincicsOptionsFromContext(libmv_cameraIntrinsicsOptions *camera_intrinsics_options,
+ MovieReconstructContext *context)
+{
+ camera_intrinsics_options->focal_length = context->focal_length;
+
+ camera_intrinsics_options->principal_point_x = context->principal_point[0];
+ camera_intrinsics_options->principal_point_y = context->principal_point[1];
+
+ camera_intrinsics_options->k1 = context->k1;
+ camera_intrinsics_options->k2 = context->k2;
+ camera_intrinsics_options->k3 = context->k3;
+
+ camera_intrinsics_options->image_width = context->width;
+ camera_intrinsics_options->image_height = context->height;
+}
+
+static void reconstructionOptionsFromContext(libmv_reconstructionOptions *reconstruction_options,
+ MovieReconstructContext *context)
+{
+ reconstruction_options->keyframe1 = context->keyframe1;
+ reconstruction_options->keyframe2 = context->keyframe2;
+
+ reconstruction_options->refine_intrinsics = context->refine_flags;
+
+ reconstruction_options->success_threshold = context->success_threshold;
+ reconstruction_options->use_fallback_reconstruction = context->use_fallback_reconstruction;
+}
#endif
void BKE_tracking_reconstruction_solve(MovieReconstructContext *context, short *stop, short *do_update,
@@ -2942,32 +3099,28 @@ void BKE_tracking_reconstruction_solve(MovieReconstructContext *context, short *
ReconstructProgressData progressdata;
+ libmv_cameraIntrinsicsOptions camera_intrinsics_options;
+ libmv_reconstructionOptions reconstruction_options;
+
progressdata.stop = stop;
progressdata.do_update = do_update;
progressdata.progress = progress;
progressdata.stats_message = stats_message;
progressdata.message_size = message_size;
+ camraIntrincicsOptionsFromContext(&camera_intrinsics_options, context);
+ reconstructionOptionsFromContext(&reconstruction_options, context);
+
if (context->motion_flag & TRACKING_MOTION_MODAL) {
context->reconstruction = libmv_solveModal(context->tracks,
- context->focal_length,
- context->principal_point[0], context->principal_point[1],
- context->k1, context->k2, context->k3,
+ &camera_intrinsics_options,
+ &reconstruction_options,
reconstruct_update_solve_cb, &progressdata);
}
else {
- struct libmv_reconstructionOptions options;
-
- options.success_threshold = context->success_threshold;
- options.use_fallback_reconstruction = context->use_fallback_reconstruction;
-
context->reconstruction = libmv_solveReconstruction(context->tracks,
- context->keyframe1, context->keyframe2,
- context->refine_flags,
- context->focal_length,
- context->principal_point[0], context->principal_point[1],
- context->k1, context->k2, context->k3,
- &options,
+ &camera_intrinsics_options,
+ &reconstruction_options,
reconstruct_update_solve_cb, &progressdata);
}
@@ -3722,6 +3875,88 @@ static void tracking_dopesheet_sort(MovieTracking *tracking, int sort_method, in
}
}
+static int coverage_from_count(int count)
+{
+ if (count < 8)
+ return TRACKING_COVERAGE_BAD;
+ else if (count < 16)
+ return TRACKING_COVERAGE_ACCEPTABLE;
+ return TRACKING_COVERAGE_OK;
+}
+
+static void tracking_dopesheet_calc_coverage(MovieTracking *tracking)
+{
+ MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
+ MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
+ ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
+ MovieTrackingTrack *track;
+ int frames, start_frame = INT_MAX, end_frame = -INT_MAX;
+ int *per_frame_counter;
+ int prev_coverage, last_segment_frame;
+ int i;
+
+ /* find frame boundaries */
+ for (track = tracksbase->first; track; track = track->next) {
+ start_frame = min_ii(start_frame, track->markers[0].framenr);
+ end_frame = max_ii(end_frame, track->markers[track->markersnr - 1].framenr);
+ }
+
+ frames = end_frame - start_frame + 1;
+
+ /* this is a per-frame counter of markers (how many markers belongs to the same frame) */
+ per_frame_counter = MEM_callocN(sizeof(int) * frames, "per frame track counter");
+
+ /* find per-frame markers count */
+ for (track = tracksbase->first; track; track = track->next) {
+ int i;
+
+ for (i = 0; i < track->markersnr; i++) {
+ MovieTrackingMarker *marker = &track->markers[i];
+
+ /* TODO: perhaps we need to add check for non-single-frame track here */
+ if ((marker->flag & MARKER_DISABLED) == 0)
+ per_frame_counter[marker->framenr - start_frame]++;
+ }
+ }
+
+ /* convert markers count to coverage and detect segments with the same coverage */
+ prev_coverage = coverage_from_count(per_frame_counter[0]);
+ last_segment_frame = start_frame;
+
+ /* means only disabled tracks in the beginning, could be ignored */
+ if (!per_frame_counter[0])
+ prev_coverage = TRACKING_COVERAGE_OK;
+
+ for (i = 1; i < frames; i++) {
+ int coverage = coverage_from_count(per_frame_counter[i]);
+
+ /* means only disabled tracks in the end, could be ignored */
+ if (i == frames - 1 && !per_frame_counter[i])
+ coverage = TRACKING_COVERAGE_OK;
+
+ if (coverage != prev_coverage || i == frames - 1) {
+ MovieTrackingDopesheetCoverageSegment *coverage_segment;
+ int end_segment_frame = i - 1 + start_frame;
+
+ if (end_segment_frame == last_segment_frame)
+ end_segment_frame++;
+
+ coverage_segment = MEM_callocN(sizeof(MovieTrackingDopesheetCoverageSegment), "tracking coverage segment");
+ coverage_segment->coverage = prev_coverage;
+ coverage_segment->start_frame = last_segment_frame;
+ coverage_segment->end_frame = end_segment_frame;
+
+ BLI_addtail(&dopesheet->coverage_segments, coverage_segment);
+
+ last_segment_frame = end_segment_frame;
+ }
+
+ prev_coverage = coverage;
+ }
+
+ MEM_freeN(per_frame_counter);
+}
+
void BKE_tracking_dopesheet_tag_update(MovieTracking *tracking)
{
MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
@@ -3749,6 +3984,7 @@ void BKE_tracking_dopesheet_update(MovieTracking *tracking)
reconstruction = BKE_tracking_object_get_reconstruction(tracking, object);
+ /* channels */
for (track = tracksbase->first; track; track = track->next) {
MovieTrackingDopesheetChannel *channel;
@@ -3776,5 +4012,8 @@ void BKE_tracking_dopesheet_update(MovieTracking *tracking)
tracking_dopesheet_sort(tracking, sort_method, inverse);
+ /* frame coverage */
+ tracking_dopesheet_calc_coverage(tracking);
+
dopesheet->ok = TRUE;
}
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index 84e1f29f6c0..066b6eff5c5 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -104,7 +104,7 @@ typedef struct bUnitCollection {
/* Dummy */
static struct bUnitDef buDummyDef[] = { {"", NULL, "", NULL, NULL, 1.0, 0.0}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}};
-static struct bUnitCollection buDummyCollecton = {buDummyDef, 0, 0, sizeof(buDummyDef)};
+static struct bUnitCollection buDummyCollection = {buDummyDef, 0, 0, sizeof(buDummyDef)};
/* Lengths */
static struct bUnitDef buMetricLenDef[] = {
@@ -125,7 +125,7 @@ static struct bUnitDef buMetricLenDef[] = {
#endif
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buMetricLenCollecton = {buMetricLenDef, 3, 0, sizeof(buMetricLenDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buMetricLenCollection = {buMetricLenDef, 3, 0, sizeof(buMetricLenDef) / sizeof(bUnitDef)};
static struct bUnitDef buImperialLenDef[] = {
{"mile", "miles", "mi", "m", "Miles", UN_SC_MI, 0.0, B_UNIT_DEF_NONE},
@@ -137,12 +137,12 @@ static struct bUnitDef buImperialLenDef[] = {
{"thou", "thou", "thou", "mil", "Thou", UN_SC_MIL, 0.0, B_UNIT_DEF_NONE}, /* plural for thou has no 's' */
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buImperialLenCollecton = {buImperialLenDef, 4, 0, sizeof(buImperialLenDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buImperialLenCollection = {buImperialLenDef, 4, 0, sizeof(buImperialLenDef) / sizeof(bUnitDef)};
/* Areas */
static struct bUnitDef buMetricAreaDef[] = {
{"square kilometer", "square kilometers", "km²", "km2", "Square Kilometers", UN_SC_KM * UN_SC_KM, 0.0, B_UNIT_DEF_NONE},
- {"square hectometer", "square hectometers", "hm²", "hm2", "Square Hectometers", UN_SC_HM * UN_SC_HM, 0.0, B_UNIT_DEF_NONE}, /* hectare */
+ {"square hectometer", "square hectometers", "hm²", "hm2", "Square Hectometers", UN_SC_HM * UN_SC_HM, 0.0, B_UNIT_DEF_SUPPRESS}, /* hectare */
{"square dekameter", "square dekameters", "dam²", "dam2", "Square Dekameters", UN_SC_DAM * UN_SC_DAM, 0.0, B_UNIT_DEF_SUPPRESS}, /* are */
{"square meter", "square meters", "m²", "m2", "Square Meters", UN_SC_M * UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */
{"square decimeter", "square decimetees", "dm²", "dm2", "Square Decimeters", UN_SC_DM * UN_SC_DM, 0.0, B_UNIT_DEF_SUPPRESS},
@@ -151,7 +151,7 @@ static struct bUnitDef buMetricAreaDef[] = {
{"square micrometer", "square micrometers", "µm²", "um2", "Square Micrometers", UN_SC_UM * UN_SC_UM, 0.0, B_UNIT_DEF_NONE},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buMetricAreaCollecton = {buMetricAreaDef, 3, 0, sizeof(buMetricAreaDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buMetricAreaCollection = {buMetricAreaDef, 3, 0, sizeof(buMetricAreaDef) / sizeof(bUnitDef)};
static struct bUnitDef buImperialAreaDef[] = {
{"square mile", "square miles", "sq mi", "sq m", "Square Miles", UN_SC_MI * UN_SC_MI, 0.0, B_UNIT_DEF_NONE},
@@ -163,12 +163,12 @@ static struct bUnitDef buImperialAreaDef[] = {
{"square thou", "square thous", "sq mil", NULL, "Square Thous", UN_SC_MIL * UN_SC_MIL, 0.0, B_UNIT_DEF_NONE},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buImperialAreaCollecton = {buImperialAreaDef, 4, 0, sizeof(buImperialAreaDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buImperialAreaCollection = {buImperialAreaDef, 4, 0, sizeof(buImperialAreaDef) / sizeof(bUnitDef)};
/* Volumes */
static struct bUnitDef buMetricVolDef[] = {
{"cubic kilometer", "cubic kilometers", "km³", "km3", "Cubic Kilometers", UN_SC_KM * UN_SC_KM * UN_SC_KM, 0.0, B_UNIT_DEF_NONE},
- {"cubic hectometer", "cubic hectometers", "hm³", "hm3", "Cubic Hectometers", UN_SC_HM * UN_SC_HM * UN_SC_HM, 0.0, B_UNIT_DEF_NONE},
+ {"cubic hectometer", "cubic hectometers", "hm³", "hm3", "Cubic Hectometers", UN_SC_HM * UN_SC_HM * UN_SC_HM, 0.0, B_UNIT_DEF_SUPPRESS},
{"cubic dekameter", "cubic dekameters", "dam³", "dam3", "Cubic Dekameters", UN_SC_DAM * UN_SC_DAM * UN_SC_DAM, 0.0, B_UNIT_DEF_SUPPRESS},
{"cubic meter", "cubic meters", "m³", "m3", "Cubic Meters", UN_SC_M * UN_SC_M * UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */
{"cubic decimeter", "cubic decimeters", "dm³", "dm3", "Cubic Decimeters", UN_SC_DM * UN_SC_DM * UN_SC_DM, 0.0, B_UNIT_DEF_SUPPRESS},
@@ -177,7 +177,7 @@ static struct bUnitDef buMetricVolDef[] = {
{"cubic micrometer", "cubic micrometers", "µm³", "um3", "Cubic Micrometers", UN_SC_UM * UN_SC_UM * UN_SC_UM, 0.0, B_UNIT_DEF_NONE},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buMetricVolCollecton = {buMetricVolDef, 3, 0, sizeof(buMetricVolDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buMetricVolCollection = {buMetricVolDef, 3, 0, sizeof(buMetricVolDef) / sizeof(bUnitDef)};
static struct bUnitDef buImperialVolDef[] = {
{"cubic mile", "cubic miles", "cu mi", "cu m", "Cubic Miles", UN_SC_MI * UN_SC_MI * UN_SC_MI, 0.0, B_UNIT_DEF_NONE},
@@ -189,19 +189,19 @@ static struct bUnitDef buImperialVolDef[] = {
{"cubic thou", "cubic thous", "cu mil", NULL, "Cubic Thous", UN_SC_MIL * UN_SC_MIL * UN_SC_MIL, 0.0, B_UNIT_DEF_NONE},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buImperialVolCollecton = {buImperialVolDef, 4, 0, sizeof(buImperialVolDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buImperialVolCollection = {buImperialVolDef, 4, 0, sizeof(buImperialVolDef) / sizeof(bUnitDef)};
/* Mass */
static struct bUnitDef buMetricMassDef[] = {
{"ton", "tonnes", "ton", "t", "1000 Kilograms", UN_SC_MTON, 0.0, B_UNIT_DEF_NONE},
- {"quintal", "quintals", "ql", "q", "100 Kilograms", UN_SC_QL, 0.0, B_UNIT_DEF_NONE},
+ {"quintal", "quintals", "ql", "q", "100 Kilograms", UN_SC_QL, 0.0, B_UNIT_DEF_SUPPRESS},
{"kilogram", "kilograms", "kg", NULL, "Kilograms", UN_SC_KG, 0.0, B_UNIT_DEF_NONE}, /* base unit */
- {"hectogram", "hectograms", "hg", NULL, "Hectograms", UN_SC_HG, 0.0, B_UNIT_DEF_NONE},
+ {"hectogram", "hectograms", "hg", NULL, "Hectograms", UN_SC_HG, 0.0, B_UNIT_DEF_SUPPRESS},
{"dekagram", "dekagrams", "dag", NULL, "10 Grams", UN_SC_DAG, 0.0, B_UNIT_DEF_SUPPRESS},
{"gram", "grams", "g", NULL, "Grams", UN_SC_G, 0.0, B_UNIT_DEF_NONE},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buMetricMassCollecton = {buMetricMassDef, 2, 0, sizeof(buMetricMassDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buMetricMassCollection = {buMetricMassDef, 2, 0, sizeof(buMetricMassDef) / sizeof(bUnitDef)};
static struct bUnitDef buImperialMassDef[] = {
{"ton", "tonnes", "ton", "t", "Tonnes", UN_SC_ITON, 0.0, B_UNIT_DEF_NONE},
@@ -211,7 +211,7 @@ static struct bUnitDef buImperialMassDef[] = {
{"ounce", "ounces", "oz", NULL, "Ounces", UN_SC_OZ, 0.0, B_UNIT_DEF_NONE},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buImperialMassCollecton = {buImperialMassDef, 3, 0, sizeof(buImperialMassDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buImperialMassCollection = {buImperialMassDef, 3, 0, sizeof(buImperialMassDef) / sizeof(bUnitDef)};
/* Even if user scales the system to a point where km^3 is used, velocity and
* acceleration aren't scaled: that's why we have so few units for them */
@@ -222,27 +222,27 @@ static struct bUnitDef buMetricVelDef[] = {
{"kilometer per hour", "kilometers per hour", "km/h", NULL, "Kilometers per hour", UN_SC_KM / 3600.0f, 0.0, B_UNIT_DEF_SUPPRESS},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buMetricVelCollecton = {buMetricVelDef, 0, 0, sizeof(buMetricVelDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buMetricVelCollection = {buMetricVelDef, 0, 0, sizeof(buMetricVelDef) / sizeof(bUnitDef)};
static struct bUnitDef buImperialVelDef[] = {
{"foot per second", "feet per second", "ft/s", "fps", "Feet per second", UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */
{"mile per hour", "miles per hour", "mph", NULL, "Miles per hour", UN_SC_MI / 3600.0f, 0.0, B_UNIT_DEF_SUPPRESS},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buImperialVelCollecton = {buImperialVelDef, 0, 0, sizeof(buImperialVelDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buImperialVelCollection = {buImperialVelDef, 0, 0, sizeof(buImperialVelDef) / sizeof(bUnitDef)};
/* Acceleration */
static struct bUnitDef buMetricAclDef[] = {
{"meter per second squared", "meters per second squared", "m/s²", "m/s2", "Meters per second squared", UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buMetricAclCollecton = {buMetricAclDef, 0, 0, sizeof(buMetricAclDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buMetricAclCollection = {buMetricAclDef, 0, 0, sizeof(buMetricAclDef) / sizeof(bUnitDef)};
static struct bUnitDef buImperialAclDef[] = {
{"foot per second squared", "feet per second squared", "ft/s²", "ft/s2", "Feet per second squared", UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buImperialAclCollecton = {buImperialAclDef, 0, 0, sizeof(buImperialAclDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buImperialAclCollection = {buImperialAclDef, 0, 0, sizeof(buImperialAclDef) / sizeof(bUnitDef)};
/* Time */
static struct bUnitDef buNaturalTimeDef[] = {
@@ -255,7 +255,7 @@ static struct bUnitDef buNaturalTimeDef[] = {
{"microsecond", "microseconds", "µs", "us", "Microseconds", 0.000001, 0.0, B_UNIT_DEF_NONE},
{NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
};
-static struct bUnitCollection buNaturalTimeCollecton = {buNaturalTimeDef, 3, 0, sizeof(buNaturalTimeDef) / sizeof(bUnitDef)};
+static struct bUnitCollection buNaturalTimeCollection = {buNaturalTimeDef, 3, 0, sizeof(buNaturalTimeDef) / sizeof(bUnitDef)};
static struct bUnitDef buNaturalRotDef[] = {
@@ -266,12 +266,24 @@ static struct bUnitDef buNaturalRotDef[] = {
};
static struct bUnitCollection buNaturalRotCollection = {buNaturalRotDef, 0, 0, sizeof(buNaturalRotDef) / sizeof(bUnitDef)};
-#define UNIT_SYSTEM_TOT (((sizeof(bUnitSystems) / 9) / sizeof(void *)) - 1)
-static struct bUnitCollection *bUnitSystems[][9] = {
- {NULL, NULL, NULL, NULL, NULL, &buNaturalRotCollection, &buNaturalTimeCollecton, NULL, NULL},
- {NULL, &buMetricLenCollecton, &buMetricAreaCollecton, &buMetricVolCollecton, &buMetricMassCollecton, &buNaturalRotCollection, &buNaturalTimeCollecton, &buMetricVelCollecton, &buMetricAclCollecton}, /* metric */
- {NULL, &buImperialLenCollecton, &buImperialAreaCollecton, &buImperialVolCollecton, &buImperialMassCollecton, &buNaturalRotCollection, &buNaturalTimeCollecton, &buImperialVelCollecton, &buImperialAclCollecton}, /* imperial */
- {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
+/* Camera Lengths */
+static struct bUnitDef buCameraLenDef[] = {
+ {"meter", "meters", "m", NULL, "Meters", UN_SC_KM, 0.0, B_UNIT_DEF_NONE}, /* base unit */
+ {"decimeter", "decimeters", "dm", NULL, "10 Centimeters", UN_SC_HM, 0.0, B_UNIT_DEF_SUPPRESS},
+ {"centimeter", "centimeters", "cm", NULL, "Centimeters", UN_SC_DAM, 0.0, B_UNIT_DEF_SUPPRESS},
+ {"millimeter", "millimeters", "mm", NULL, "Millimeters", UN_SC_M, 0.0, B_UNIT_DEF_NONE},
+ {"micrometer", "micrometers", "µm", "um", "Micrometers", UN_SC_MM, 0.0, B_UNIT_DEF_SUPPRESS}, // micron too?
+ {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}
+};
+static struct bUnitCollection buCameraLenCollection = {buCameraLenDef, 3, 0, sizeof(buCameraLenDef) / sizeof(bUnitDef)};
+
+
+#define UNIT_SYSTEM_TOT (((sizeof(bUnitSystems) / B_UNIT_TYPE_TOT) / sizeof(void *)) - 1)
+static struct bUnitCollection *bUnitSystems[][B_UNIT_TYPE_TOT] = {
+ {NULL, NULL, NULL, NULL, NULL, &buNaturalRotCollection, &buNaturalTimeCollection, NULL, NULL, NULL},
+ {NULL, &buMetricLenCollection, &buMetricAreaCollection, &buMetricVolCollection, &buMetricMassCollection, &buNaturalRotCollection, &buNaturalTimeCollection, &buMetricVelCollection, &buMetricAclCollection, &buCameraLenCollection}, /* metric */
+ {NULL, &buImperialLenCollection, &buImperialAreaCollection, &buImperialVolCollection, &buImperialMassCollection, &buNaturalRotCollection, &buNaturalTimeCollection, &buImperialVelCollection, &buImperialAclCollection, &buCameraLenCollection}, /* imperial */
+ {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
};
@@ -395,10 +407,10 @@ void bUnit_AsString(char *str, int len_max, double value, int prec, int system,
bUnitCollection *usys = unit_get_system(system, type);
if (usys == NULL || usys->units[0].name == NULL)
- usys = &buDummyCollecton;
+ usys = &buDummyCollection;
/* split output makes sense only for length, mass and time */
- if (split && (type == B_UNIT_LENGTH || type == B_UNIT_MASS || type == B_UNIT_TIME)) {
+ if (split && (type == B_UNIT_LENGTH || type == B_UNIT_MASS || type == B_UNIT_TIME || type == B_UNIT_CAMERA)) {
bUnitDef *unit_a, *unit_b;
double value_a, value_b;
@@ -706,7 +718,7 @@ void bUnit_ToUnitAltName(char *str, int len_max, const char *orig_str, int syste
/* print the alt_name */
if (unit->name_alt)
- len_name = BLI_snprintf(str, len_max, "%s", unit->name_alt);
+ len_name = BLI_strncpy_rlen(str, unit->name_alt, len_max);
else
len_name = 0;
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 4bde895cf7d..206f829eaa8 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -40,7 +40,6 @@
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
-#include "BLI_bpath.h"
#include "BKE_animsys.h"
#include "BKE_global.h"
@@ -80,9 +79,8 @@ void BKE_world_free(World *wrld)
BKE_world_free_ex(wrld, TRUE);
}
-World *add_world(const char *name)
+World *add_world(Main *bmain, const char *name)
{
- Main *bmain = G.main;
World *wrld;
wrld = BKE_libblock_alloc(&bmain->world, ID_WO, name);
diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c
index d4428be3faf..ff6212f6b09 100644
--- a/source/blender/blenkernel/intern/writeavi.c
+++ b/source/blender/blenkernel/intern/writeavi.c
@@ -73,7 +73,7 @@ static void filepath_avi(char *string, RenderData *rd);
bMovieHandle *BKE_movie_handle_get(const char imtype)
{
- static bMovieHandle mh = {0};
+ static bMovieHandle mh = {NULL};
/* set the default handle, as builtin */
#ifdef WITH_AVI
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 0f861a7ed37..a88a9e4954b 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -111,8 +111,9 @@ static void delete_picture(AVFrame *f)
}
}
-static int use_float_audio_buffer(int codec_id)
+static int request_float_audio_buffer(int codec_id)
{
+ /* If any of these codecs, we prefer the float sample format (if supported) */
return codec_id == CODEC_ID_AAC || codec_id == CODEC_ID_AC3 || codec_id == CODEC_ID_VORBIS;
}
@@ -373,7 +374,7 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop)
{
char name[128];
char *param;
- const AVOption *rv = NULL;
+ int fail = TRUE;
PRINT("FFMPEG expert option: %s: ", prop->name);
@@ -388,30 +389,30 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop)
switch (prop->type) {
case IDP_STRING:
PRINT("%s.\n", IDP_String(prop));
- av_set_string3(c, prop->name, IDP_String(prop), 1, &rv);
+ fail = av_opt_set(c, prop->name, IDP_String(prop), 0);
break;
case IDP_FLOAT:
PRINT("%g.\n", IDP_Float(prop));
- rv = av_set_double(c, prop->name, IDP_Float(prop));
+ fail = av_opt_set_double(c, prop->name, IDP_Float(prop), 0);
break;
case IDP_INT:
PRINT("%d.\n", IDP_Int(prop));
if (param) {
if (IDP_Int(prop)) {
- av_set_string3(c, name, param, 1, &rv);
+ fail = av_opt_set(c, name, param, 0);
}
else {
return;
}
}
else {
- rv = av_set_int(c, prop->name, IDP_Int(prop));
+ fail = av_opt_set_int(c, prop->name, IDP_Int(prop), 0);
}
break;
}
- if (!rv) {
+ if (fail) {
PRINT("ffmpeg-option not supported: %s! Skipping.\n", prop->name);
}
}
@@ -464,8 +465,9 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
error[0] = '\0';
- st = av_new_stream(of, 0);
+ st = avformat_new_stream(of, NULL);
if (!st) return NULL;
+ st->id = 0;
/* Set up the codec context */
@@ -497,8 +499,15 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
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;
+
+#if 0
+ /* this options are not set in ffmpeg.c and leads to artifacts with MPEG-4
+ * see #33586: Encoding to mpeg4 makes first frame(s) blocky
+ */
c->rc_initial_buffer_occupancy = rd->ffcodecdata.rc_buffer_size * 3 / 4;
c->rc_buffer_aggressivity = 1.0;
+#endif
+
c->me_method = ME_EPZS;
codec = avcodec_find_encoder(c->codec_id);
@@ -534,16 +543,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
}
if (codec_id == CODEC_ID_FFV1) {
-#ifdef FFMPEG_FFV1_ALPHA_SUPPORTED
- if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
- c->pix_fmt = PIX_FMT_RGB32;
- }
- else {
- c->pix_fmt = PIX_FMT_BGR0;
- }
-#else
c->pix_fmt = PIX_FMT_RGB32;
-#endif
}
if (codec_id == CODEC_ID_QTRLE) {
@@ -552,6 +552,12 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
}
}
+ if (codec_id == CODEC_ID_PNG) {
+ if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
+ c->pix_fmt = PIX_FMT_ARGB;
+ }
+ }
+
if ((of->oformat->flags & AVFMT_GLOBALHEADER)
// || !strcmp(of->oformat->name, "mp4")
// || !strcmp(of->oformat->name, "mov")
@@ -575,7 +581,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
set_ffmpeg_properties(rd, c, "video");
- if (avcodec_open(c, codec) < 0) {
+ if (avcodec_open2(c, codec, NULL) < 0) {
BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
return NULL;
}
@@ -612,8 +618,9 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
error[0] = '\0';
- st = av_new_stream(of, 1);
+ st = avformat_new_stream(of, NULL);
if (!st) return NULL;
+ st->id = 1;
c = st->codec;
c->codec_id = codec_id;
@@ -623,19 +630,58 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
c->bit_rate = ffmpeg_audio_bitrate * 1000;
c->sample_fmt = AV_SAMPLE_FMT_S16;
c->channels = rd->ffcodecdata.audio_channels;
- if (use_float_audio_buffer(codec_id)) {
+
+ if (request_float_audio_buffer(codec_id)) {
+ /* mainly for AAC codec which is experimental */
c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
c->sample_fmt = AV_SAMPLE_FMT_FLT;
}
+
codec = avcodec_find_encoder(c->codec_id);
if (!codec) {
//XXX error("Couldn't find a valid audio codec");
return NULL;
}
+ if (codec->sample_fmts) {
+ /* check if the prefered 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.
+ */
+ const enum AVSampleFormat *p = codec->sample_fmts;
+ for (; *p!=-1; p++) {
+ if (*p == st->codec->sample_fmt)
+ break;
+ }
+ if (*p == -1) {
+ /* sample format incompatible with codec. Defaulting to a format known to work */
+ st->codec->sample_fmt = codec->sample_fmts[0];
+ }
+ }
+
+ if (c->sample_fmt == AV_SAMPLE_FMT_FLTP) {
+ BLI_strncpy(error, "Requested audio codec requires planar float sample format, which is not supported yet", error_size);
+ return NULL;
+ }
+
+ if (codec->supported_samplerates) {
+ const int *p = codec->supported_samplerates;
+ int best = 0;
+ int best_dist = INT_MAX;
+ for (; *p; p++) {
+ int dist = abs(st->codec->sample_rate - *p);
+ if (dist < best_dist) {
+ best_dist = dist;
+ best = *p;
+ }
+ }
+ /* best is the closest supported sample rate (same as selected if best_dist == 0) */
+ st->codec->sample_rate = best;
+ }
+
set_ffmpeg_properties(rd, c, "audio");
- if (avcodec_open(c, codec) < 0) {
+ if (avcodec_open2(c, codec, NULL) < 0) {
//XXX error("Couldn't initialize audio codec");
BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
return NULL;
@@ -658,7 +704,7 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
audio_output_buffer = (uint8_t *) av_malloc(audio_outbuf_size);
- if (use_float_audio_buffer(codec_id)) {
+ if (c->sample_fmt == AV_SAMPLE_FMT_FLT) {
audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(float));
}
else {
@@ -740,7 +786,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
fmt->audio_codec = ffmpeg_audio_codec;
- BLI_snprintf(of->filename, sizeof(of->filename), "%s", name);
+ BLI_strncpy(of->filename, name, sizeof(of->filename));
/* set the codec to the user's selection */
switch (ffmpeg_type) {
case FFMPEG_AVI:
@@ -837,7 +883,8 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
}
if (avformat_write_header(of, NULL) < 0) {
BKE_report(reports, RPT_ERROR, "Could not initialize streams, probably unsupported codec combination");
- av_dict_free(&opts);
+ av_dict_free(&opts);
+ avio_close(of->pb);
return 0;
}
@@ -963,7 +1010,7 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty,
AVCodecContext *c = audio_stream->codec;
AUD_DeviceSpecs specs;
specs.channels = c->channels;
- if (use_float_audio_buffer(c->codec_id)) {
+ if (c->sample_fmt == AV_SAMPLE_FMT_FLT) {
specs.format = AUD_FORMAT_FLOAT32;
}
else {
@@ -980,7 +1027,6 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty,
return success;
}
-void BKE_ffmpeg_end(void);
static void end_ffmpeg_impl(int is_autosplit);
#ifdef WITH_AUDASPACE
@@ -1144,7 +1190,7 @@ IDProperty *BKE_ffmpeg_property_add(RenderData *rd, const char *type, int opt_in
val.i = 0;
- avcodec_get_context_defaults(&c);
+ avcodec_get_context_defaults3(&c, NULL);
o = c.av_class->option + opt_index;
parent = c.av_class->option + parent_index;
@@ -1175,23 +1221,23 @@ IDProperty *BKE_ffmpeg_property_add(RenderData *rd, const char *type, int opt_in
}
switch (o->type) {
- case FF_OPT_TYPE_INT:
- case FF_OPT_TYPE_INT64:
+ case AV_OPT_TYPE_INT:
+ case AV_OPT_TYPE_INT64:
val.i = FFMPEG_DEF_OPT_VAL_INT(o);
idp_type = IDP_INT;
break;
- case FF_OPT_TYPE_DOUBLE:
- case FF_OPT_TYPE_FLOAT:
+ case AV_OPT_TYPE_DOUBLE:
+ case AV_OPT_TYPE_FLOAT:
val.f = FFMPEG_DEF_OPT_VAL_DOUBLE(o);
idp_type = IDP_FLOAT;
break;
- case FF_OPT_TYPE_STRING:
+ case AV_OPT_TYPE_STRING:
val.string.str = (char *)" ";
val.string.len = 80;
/* val.str = (char *)" ";*/
idp_type = IDP_STRING;
break;
- case FF_OPT_TYPE_CONST:
+ case AV_OPT_TYPE_CONST:
val.i = 1;
idp_type = IDP_INT;
break;
@@ -1231,7 +1277,7 @@ int BKE_ffmpeg_property_add_string(RenderData *rd, const char *type, const char
char *param;
IDProperty *prop = NULL;
- avcodec_get_context_defaults(&c);
+ avcodec_get_context_defaults3(&c, NULL);
strncpy(name_, str, sizeof(name_));
@@ -1252,10 +1298,10 @@ int BKE_ffmpeg_property_add_string(RenderData *rd, const char *type, const char
if (!o) {
return 0;
}
- if (param && o->type == FF_OPT_TYPE_CONST) {
+ if (param && o->type == AV_OPT_TYPE_CONST) {
return 0;
}
- if (param && o->type != FF_OPT_TYPE_CONST && o->unit) {
+ if (param && o->type != AV_OPT_TYPE_CONST && o->unit) {
p = my_av_find_opt(&c, param, o->unit, 0, 0);
if (p) {
prop = BKE_ffmpeg_property_add(rd, (char *) type, p - c.av_class->option, o - c.av_class->option);
@@ -1493,6 +1539,9 @@ int BKE_ffmpeg_alpha_channel_is_supported(RenderData *rd)
if (codec == CODEC_ID_QTRLE)
return TRUE;
+ if (codec == CODEC_ID_PNG)
+ return TRUE;
+
#ifdef FFMPEG_FFV1_ALPHA_SUPPORTED
if (codec == CODEC_ID_FFV1)
return TRUE;
diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h
index f068c4c58f0..2e38e33a308 100644
--- a/source/blender/blenkernel/nla_private.h
+++ b/source/blender/blenkernel/nla_private.h
@@ -49,7 +49,7 @@ typedef struct NlaEvalStrip {
} NlaEvalStrip;
/* NlaEvalStrip->strip_mode */
-enum {
+enum eNlaEvalStrip_StripMode {
/* standard evaluation */
NES_TIME_BEFORE = -1,
NES_TIME_WITHIN,
@@ -58,7 +58,7 @@ enum {
/* transition-strip evaluations */
NES_TIME_TRANSITION_START,
NES_TIME_TRANSITION_END,
-} eNlaEvalStrip_StripMode;
+};
/* temp channel for accumulating data from NLA (avoids needing to clear all values first) */
diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h
index c1b77077a4d..0ba0f138c28 100644
--- a/source/blender/blenlib/BLI_array.h
+++ b/source/blender/blenlib/BLI_array.h
@@ -25,53 +25,19 @@
* ***** END GPL LICENSE BLOCK *****
*/
+#ifndef __BLI_ARRAY_H__
+#define __BLI_ARRAY_H__
+
/** \file BLI_array.h
* \ingroup bli
- * \brief A 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.
- *
- * 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
- *
- * little array macro library. example of usage:
- *
- * int *arr = NULL;
- * BLI_array_declare(arr);
- * int i;
- *
- * for (i = 0; i < 10; i++) {
- * BLI_array_grow_one(arr);
- * arr[i] = something;
- * }
- * BLI_array_free(arr);
- *
- * 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.
+ * \brief A (mainly) macro array library.
*/
-#define BLI_array_declare(arr) \
- int _##arr##_count = 0; \
- void *_##arr##_tmp; \
- void *_##arr##_static = NULL
-
-/* 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; \
- void *_##arr##_tmp; \
- char _##arr##_static[maxstatic * sizeof(arr)]
-
+/* -------------------------------------------------------------------- */
+/* internal defines */
/* this returns the entire size of the array, including any buffering. */
-#define BLI_array_totalsize_dyn(arr) ( \
+#define _bli_array_totalsize_dynamic(arr) ( \
((arr) == NULL) ? \
0 : \
MEM_allocN_len(arr) / sizeof(*arr) \
@@ -80,55 +46,61 @@
#define _bli_array_totalsize_static(arr) \
(sizeof(_##arr##_static) / sizeof(*arr))
-#define BLI_array_totalsize(arr) ( \
+#define _bli_array_totalsize(arr) ( \
(size_t) \
(((void *)(arr) == (void *)_##arr##_static && (void *)(arr) != NULL) ? \
_bli_array_totalsize_static(arr) : \
- BLI_array_totalsize_dyn(arr)) \
+ _bli_array_totalsize_dynamic(arr)) \
)
+/* BLI_array.c
+ *
+ * Doing the realloc in a macro isn't so simple,
+ * so use a function the macros can use.
+ */
+void _bli_array_grow_func(void **arr_p, const void *arr_static,
+ const int sizeof_arr_p, const int arr_count, const int num,
+ const char *alloc_str);
+
+
+/* -------------------------------------------------------------------- */
+/* public defines */
+
+#define BLI_array_declare(arr) \
+ int _##arr##_count = 0; \
+ void *_##arr##_static = NULL
+
+/* 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. */
#define BLI_array_count(arr) _##arr##_count
-/* Grow the array by a fixed number of items. zeroes the new elements.
+/* Grow the array by a fixed number of items.
*
* Allow for a large 'num' value when the new size is more then double
* to allocate the exact sized array. */
-
-/* grow an array by a specified number of items */
-#define BLI_array_grow_items(arr, num) ( \
+#define BLI_array_grow_items(arr, num) (( \
(((void *)(arr) == NULL) && \
((void *)(_##arr##_static) != NULL) && \
- /* dont add _##arr##_count below because it must be zero */ \
+ /* don't add _##arr##_count below because it must be zero */ \
(_bli_array_totalsize_static(arr) >= _##arr##_count + num)) ? \
/* we have an empty array and a static var big enough */ \
- ((arr = (void *)_##arr##_static), (_##arr##_count += (num))) \
+ (arr = (void *)_##arr##_static) \
: \
/* use existing static array or allocate */ \
- ((BLI_array_totalsize(arr) >= _##arr##_count + num) ? \
- (_##arr##_count += num) : \
- ( \
- (void) (_##arr##_tmp = MEM_callocN( \
- sizeof(*arr) * (num < _##arr##_count ? \
- (_##arr##_count * 2 + 2) : \
- (_##arr##_count + num)), \
- #arr " " __FILE__ ":" STRINGIFY(__LINE__) \
- ) \
- ), \
- (void) (arr && memcpy(_##arr##_tmp, \
- arr, \
- sizeof(*arr) * _##arr##_count) \
- ), \
- (void) (arr && ((void *)(arr) != (void *)_##arr##_static ? \
- (MEM_freeN(arr), arr) : \
- arr) \
- ), \
- (void) (arr = _##arr##_tmp \
- ), \
- (_##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), \
+ (void)0) /* msvc2008 needs this */ \
+ ), \
+ /* 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)
@@ -167,20 +139,23 @@
/* 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
+ { _##arr##_count = 0; } (void)0
/* set the count of the array, doesn't actually increase the allocated array
* size. don't use this unless you know what you're doing. */
#define BLI_array_length_set(arr, count) \
- _##arr##_count = (count); (void)0
+ { _##arr##_count = (count); }(void)0
/* only to prevent unused warnings */
#define BLI_array_fake_user(arr) \
(void)_##arr##_count, \
- (void)_##arr##_tmp, \
(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()
* but use when the max size is known ahead of time */
@@ -203,6 +178,10 @@
# define alloca _alloca
#endif
+#if defined(__MINGW32__)
+# include <malloc.h> /* mingw needs for alloca() */
+#endif
+
#if defined(__GNUC__) || defined(__clang__)
#define BLI_array_alloca(arr, realsize) \
(typeof(arr))alloca(sizeof(*arr) * (realsize))
@@ -219,3 +198,5 @@
alloca(sizeof(*arr) * (realsize)); \
const int _##arr##_count = (realsize)
#endif
+
+#endif /* __BLI_ARRAY_H__ */
diff --git a/source/blender/blenlib/BLI_buffer.h b/source/blender/blenlib/BLI_buffer.h
new file mode 100644
index 00000000000..fe835e7cadc
--- /dev/null
+++ b/source/blender/blenlib/BLI_buffer.h
@@ -0,0 +1,106 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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_BUFFER_H__
+#define __BLI_BUFFER_H__
+
+/* Note: this more or less fills same purpose as BLI_array, but makes
+ * it much easier to resize the array outside of the function it was
+ * declared in since */
+
+/* Usage examples:
+ *
+ * {
+ * BLI_buffer_declare_static(int, my_int_array, BLI_BUFFER_NOP, 32);
+ *
+ * BLI_buffer_append(my_int_array, int, 42);
+ * assert(my_int_array.count == 1);
+ * assert(BLI_buffer_at(my_int_array, int, 0) == 42);
+ *
+ * BLI_buffer_free(&my_int_array);
+ * }
+ */
+
+typedef struct {
+ void *data;
+ const int elem_size;
+ int count, alloc_count;
+ int flag;
+} BLI_Buffer;
+
+enum {
+ BLI_BUFFER_NOP = 0,
+ BLI_BUFFER_USE_STATIC = (1 << 0),
+ BLI_BUFFER_USE_CALLOC = (1 << 1), /* ensure the array is always calloc'd */
+};
+
+#define BLI_buffer_declare_static(type_, name_, flag_, static_count_) \
+ char name_ ## user; /* warn for free only */ \
+ type_ *name_ ## _static_[static_count_]; \
+ BLI_Buffer name_ = { \
+ /* clear the static memory if this is a calloc'd array */ \
+ ((void)((flag_ & BLI_BUFFER_USE_CALLOC) ? \
+ memset(name_ ## _static_, 0, sizeof(name_ ## _static_)) : 0\
+ ), /* memset-end */ \
+ name_ ## _static_), \
+ sizeof(type_), \
+ 0, \
+ static_count_, \
+ BLI_BUFFER_USE_STATIC | flag_}
+
+/* never use static*/
+#define BLI_buffer_declare(type_, name_, flag_) \
+ bool name_ ## user; /* warn for free only */ \
+ BLI_Buffer name_ = {NULL, \
+ sizeof(type_), \
+ 0, \
+ 0, \
+ flag_}
+
+#define BLI_buffer_at(buffer_, type_, index_) ( \
+ (((type_ *)(buffer_)->data)[ \
+ (BLI_assert(sizeof(type_) == (buffer_)->elem_size)), \
+ (BLI_assert(index_ >= 0 && index_ < (buffer_)->count)), \
+ index_]))
+
+#define BLI_buffer_array(buffer_, type_) ( \
+ &(BLI_buffer_at(buffer_, type_, 0)))
+
+#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_) \
+)
+
+/* Never decreases the amount of memory allocated */
+void BLI_buffer_resize(BLI_Buffer *buffer, int new_count);
+
+/* Does not free the buffer structure itself */
+void _bli_buffer_free(BLI_Buffer *buffer);
+#define BLI_buffer_free(name_) { \
+ _bli_buffer_free(name_); \
+ (void)name_ ## user; /* ensure we free */ \
+} (void)0
+
+#endif /* __BLI_BUFFER_H__ */
diff --git a/source/blender/blenlib/BLI_callbacks.h b/source/blender/blenlib/BLI_callbacks.h
index 1e95510f6ec..e3d5a80b27f 100644
--- a/source/blender/blenlib/BLI_callbacks.h
+++ b/source/blender/blenlib/BLI_callbacks.h
@@ -54,7 +54,7 @@ typedef enum {
} eCbEvent;
-typedef struct {
+typedef struct bCallbackFuncStore {
struct bCallbackFuncStore *next, *prev;
void (*func)(struct Main *, struct ID *, void *arg);
void *arg;
diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h
index c278370d211..b0e3f47b627 100644
--- a/source/blender/blenlib/BLI_fileops.h
+++ b/source/blender/blenlib/BLI_fileops.h
@@ -34,14 +34,12 @@
#define __BLI_FILEOPS_H__
#include <stdio.h>
-
+#include <sys/stat.h>
#ifdef __cplusplus
extern "C" {
#endif
-#include "BLI_fileops_types.h"
-
/* for size_t (needed on windows) */
#include <stddef.h>
@@ -52,7 +50,7 @@ struct gzFile;
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, int dir, int recursive);
+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_stat(const char *path, struct stat *buffer);
@@ -61,22 +59,24 @@ int BLI_stat(const char *path, struct stat *buffer);
struct direntry;
-int BLI_is_dir(const char *path);
-int BLI_is_file(const char *path);
+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);
unsigned int BLI_dir_contents(const char *dir, struct direntry **filelist);
+void BLI_free_filelist(struct direntry * filelist, unsigned int nrentries);
/* 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);
-int BLI_file_is_writable(const char *file);
-int BLI_file_touch(const char *file);
+bool BLI_file_is_writable(const char *file);
+bool BLI_file_touch(const char *file);
int BLI_file_gzip(const char *from, const char *to);
char *BLI_file_ungzip_to_mem(const char *from_file, int *size_r);
@@ -85,7 +85,7 @@ size_t BLI_file_descriptor_size(int file);
size_t BLI_file_size(const char *file);
/* compare if one was last modified before the other */
-int BLI_file_older(const char *file1, const char *file2);
+bool BLI_file_older(const char *file1, const char *file2);
/* read ascii file as lines, empty list if reading fails */
struct LinkNode *BLI_file_read_as_lines(const char *file);
@@ -104,5 +104,4 @@ void BLI_get_short_name(char short_name[256], const char *filename);
}
#endif
-#endif
-
+#endif /* __BLI_FILEOPS_H__ */
diff --git a/source/blender/blenlib/BLI_fileops_types.h b/source/blender/blenlib/BLI_fileops_types.h
index 1c6463eb6ea..a7372c01e52 100644
--- a/source/blender/blenlib/BLI_fileops_types.h
+++ b/source/blender/blenlib/BLI_fileops_types.h
@@ -42,7 +42,6 @@ typedef unsigned int mode_t;
struct ImBuf;
struct direntry {
- char *string;
mode_t type;
char *relname;
char *path;
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index 7eac1425a5c..641aaa1f3fc 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -69,9 +69,10 @@ GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info);
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
void BLI_ghash_insert(GHash *gh, void *key, void *val);
void *BLI_ghash_lookup(GHash *gh, const void *key);
-int BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
+bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
+void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp);
-int BLI_ghash_haskey(GHash *gh, const void *key);
+bool BLI_ghash_haskey(GHash *gh, const void *key);
int BLI_ghash_size(GHash *gh);
/* *** */
@@ -130,11 +131,11 @@ void BLI_ghashIterator_step(GHashIterator *ghi);
* \param ghi The iterator.
* \return True if done, False otherwise.
*/
-int BLI_ghashIterator_isDone(GHashIterator *ghi);
+bool BLI_ghashIterator_notDone(GHashIterator *ghi);
#define GHASH_ITER(gh_iter_, ghash_) \
for (BLI_ghashIterator_init(&gh_iter_, ghash_); \
- !BLI_ghashIterator_isDone(&gh_iter_); \
+ BLI_ghashIterator_notDone(&gh_iter_); \
BLI_ghashIterator_step(&gh_iter_))
/* *** */
diff --git a/source/blender/blenlib/BLI_gsqueue.h b/source/blender/blenlib/BLI_gsqueue.h
index b4cb1edd45a..e002545d189 100644
--- a/source/blender/blenlib/BLI_gsqueue.h
+++ b/source/blender/blenlib/BLI_gsqueue.h
@@ -36,63 +36,13 @@
typedef struct _GSQueue GSQueue;
-/**
- * Create a new GSQueue.
- *
- * \param elem_size The size of the structures in the queue.
- * \retval The new queue
- */
GSQueue *BLI_gsqueue_new(int elem_size);
-
-/**
- * Query if the queue is empty
- */
-int BLI_gsqueue_is_empty(GSQueue *gq);
-
-/**
- * Query number elements in the queue
- */
+bool BLI_gsqueue_is_empty(GSQueue *gq);
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)
- */
void BLI_gsqueue_peek(GSQueue *gq, void *item_r);
-
-/**
- * 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).
- * Can be NULL if desired.
- */
void BLI_gsqueue_pop(GSQueue *gq, void *item_r);
-
-/**
- * Push an element onto the tail of the queue.
- *
- * \param item A pointer to an appropriately
- * sized structure (the size passed to BLI_gsqueue_new).
- */
void BLI_gsqueue_push(GSQueue *gq, void *item);
-
-/**
- * Push an element back onto the head of the queue (so
- * it would be returned from the next call to BLI_gsqueue_pop).
- *
- * \param item A pointer to an appropriately
- * sized structure (the size passed to BLI_gsqueue_new).
- */
void BLI_gsqueue_pushback(GSQueue *gq, void *item);
-
-/**
- * Free the queue
- */
void BLI_gsqueue_free(GSQueue *gq);
#endif /* __BLI_GSQUEUE_H__ */
diff --git a/source/blender/blenlib/BLI_heap.h b/source/blender/blenlib/BLI_heap.h
index c0941e00c9b..bc7b6000322 100644
--- a/source/blender/blenlib/BLI_heap.h
+++ b/source/blender/blenlib/BLI_heap.h
@@ -54,7 +54,7 @@ HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr);
void BLI_heap_remove(Heap *heap, HeapNode *node);
/* Return 0 if the heap is empty, 1 otherwise. */
-int BLI_heap_is_empty(Heap *heap);
+bool BLI_heap_is_empty(Heap *heap);
/* Return the size of the heap. */
unsigned int BLI_heap_size(Heap *heap);
diff --git a/source/blender/blenlib/BLI_lasso.h b/source/blender/blenlib/BLI_lasso.h
index a7e90a51e86..0addd463a70 100644
--- a/source/blender/blenlib/BLI_lasso.h
+++ b/source/blender/blenlib/BLI_lasso.h
@@ -35,7 +35,7 @@
struct rcti;
void BLI_lasso_boundbox(struct rcti *rect, const int mcords[][2], const short moves);
-int BLI_lasso_is_point_inside(const int mcords[][2], const short moves, const int sx, const int sy, const int error_value);
-int BLI_lasso_is_edge_inside(const int mcords[][2], const short moves, int x0, int y0, int x1, int y1, const int error_value);
+bool BLI_lasso_is_point_inside(const int mcords[][2], const short moves, const int sx, const int sy, const int error_value);
+bool BLI_lasso_is_edge_inside(const int mcords[][2], const short moves, int x0, int y0, int x1, int y1, const int error_value);
#endif
diff --git a/source/blender/blenlib/BLI_linklist.h b/source/blender/blenlib/BLI_linklist.h
index da56a300b9b..3e7fdc8bf75 100644
--- a/source/blender/blenlib/BLI_linklist.h
+++ b/source/blender/blenlib/BLI_linklist.h
@@ -59,6 +59,7 @@ void BLI_linklist_prepend_arena(struct LinkNode **listp, void *ptr, struct Me
void BLI_linklist_insert_after(struct LinkNode **listp, void *ptr);
void BLI_linklist_free(struct LinkNode *list, LinkNodeFreeFP freefunc);
+void BLI_linklist_freeN(struct LinkNode *list);
void BLI_linklist_apply(struct LinkNode *list, LinkNodeApplyFP applyfunc, void *userdata);
#endif
diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h
index 1330a74bea3..54cd687eeac 100644
--- a/source/blender/blenlib/BLI_listbase.h
+++ b/source/blender/blenlib/BLI_listbase.h
@@ -32,6 +32,7 @@
* \ingroup bli
*/
+#include "BLI_utildefines.h"
#include "DNA_listBase.h"
//struct ListBase;
//struct LinkData;
@@ -40,8 +41,7 @@
extern "C" {
#endif
-void BLI_insertlink(struct ListBase *listbase, void *vprevlink, void *vnewlink);
-int BLI_findindex(const struct ListBase *listbase, void *vlink);
+int BLI_findindex(const struct ListBase *listbase, const void *vlink);
int BLI_findstringindex(const struct ListBase *listbase, const char *id, const int offset);
/* find forwards */
@@ -59,7 +59,7 @@ void *BLI_rfindptr(const struct ListBase *listbase, const void *ptr, const int o
void BLI_freelistN(struct ListBase *listbase);
void BLI_addtail(struct ListBase *listbase, void *vlink);
void BLI_remlink(struct ListBase *listbase, void *vlink);
-int BLI_remlink_safe(struct ListBase *listbase, void *vlink);
+bool BLI_remlink_safe(struct ListBase *listbase, void *vlink);
void BLI_addhead(struct ListBase *listbase, void *vlink);
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink);
@@ -79,4 +79,4 @@ struct LinkData *BLI_genericNodeN(void *data);
}
#endif
-#endif
+#endif /* __BLI_LISTBASE_H__ */
diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h
index 69d6478e0e2..67c1ffcebc0 100644
--- a/source/blender/blenlib/BLI_math_base.h
+++ b/source/blender/blenlib/BLI_math_base.h
@@ -80,6 +80,9 @@
#define MAXFLOAT ((float)3.40282347e+38)
#endif
+/* do not redefine functions from C99 or POSIX.1-2001 */
+#if !(defined(_ISOC99_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L))
+
#ifndef sqrtf
#define sqrtf(a) ((float)sqrt(a))
#endif
@@ -129,6 +132,8 @@
#define hypotf(a, b) ((float)hypot(a, b))
#endif
+#endif /* C99 or POSIX.1-2001 */
+
#ifdef WIN32
# ifndef FREE_WINDOWS
# define isnan(n) _isnan(n)
@@ -174,6 +179,11 @@
#include "intern/math_base_inline.c"
#endif
+#ifdef BLI_MATH_GCC_WARN_PRAGMA
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wredundant-decls"
+#endif
+
/******************************* Float ******************************/
MINLINE float sqrt3f(float f);
@@ -212,5 +222,30 @@ extern double round(double x);
double double_round(double x, int ndigits);
-#endif /* __BLI_MATH_BASE_H__ */
+#ifdef BLI_MATH_GCC_WARN_PRAGMA
+# pragma GCC diagnostic pop
+#endif
+
+/* asserts, some math functions expect normalized inputs
+ * check the vector is unit length, or zero length (which can't be helped in some cases).
+ */
+#ifdef DEBUG
+/* note: 0.0001 is too small becaues normals may be converted from short's: see [#34322] */
+# define BLI_ASSERT_UNIT_EPSILON 0.0002f
+# define BLI_ASSERT_UNIT_V3(v) { \
+ const float _test_unit = len_squared_v3(v); \
+ BLI_assert((fabsf(_test_unit - 1.0f) < BLI_ASSERT_UNIT_EPSILON) || \
+ (fabsf(_test_unit) < BLI_ASSERT_UNIT_EPSILON)); \
+} (void)0
+# define BLI_ASSERT_UNIT_V2(v) { \
+ const float _test_unit = len_squared_v2(v); \
+ BLI_assert((fabsf(_test_unit - 1.0f) < BLI_ASSERT_UNIT_EPSILON) || \
+ (fabsf(_test_unit) < BLI_ASSERT_UNIT_EPSILON)); \
+} (void)0
+#else
+# define BLI_ASSERT_UNIT_V2(v) (void)0
+# define BLI_ASSERT_UNIT_V3(v) (void)0
+#endif
+
+#endif /* __BLI_MATH_BASE_H__ */
diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h
index c71463da61d..145427ea529 100644
--- a/source/blender/blenlib/BLI_math_color.h
+++ b/source/blender/blenlib/BLI_math_color.h
@@ -100,6 +100,15 @@ MINLINE void linearrgb_to_srgb_uchar4(unsigned char srgb[4], const float linear[
void BLI_init_srgb_conversion(void);
+/**************** Alpha Transformations *****************/
+
+MINLINE void premul_to_straight_v4_v4(float straight[4], const float premul[4]);
+MINLINE void premul_to_straight_v4(float color[4]);
+MINLINE void straight_to_premul_v4_v4(float straight[4], const float premul[4]);
+MINLINE void straight_to_premul_v4(float color[4]);
+MINLINE void straight_uchar_to_premul_float(float result[4], const unsigned char color[4]);
+MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float color[4]);
+
/************************** Other *************************/
int constrain_rgb(float *r, float *g, float *b);
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index 423765bad3d..7028c7c7530 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -40,6 +40,11 @@ extern "C" {
#include "intern/math_geom_inline.c"
#endif
+#ifdef BLI_MATH_GCC_WARN_PRAGMA
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wredundant-decls"
+#endif
+
/********************************** Polygons *********************************/
void cent_tri_v3(float r[3], const float a[3], const float b[3], const float c[3]);
@@ -51,8 +56,10 @@ float normal_quad_v3(float r[3], const float a[3], const float b[3], const float
float area_tri_v2(const float a[2], const float b[2], const float c[2]);
float area_tri_signed_v2(const float v1[2], const float v2[2], const float v3[2]);
float area_tri_v3(const float a[3], const float b[3], const float c[3]);
+float area_tri_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float normal[3]);
float area_quad_v3(const float a[3], const float b[3], const float c[3], const float d[3]);
float area_poly_v3(int nr, float verts[][3], const float normal[3]);
+float area_poly_v2(int nr, float verts[][2]);
int is_quad_convex_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]);
int is_quad_convex_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2]);
@@ -67,11 +74,15 @@ void closest_to_line_segment_v2(float closest[2], const float p[2], const float
float dist_to_plane_normalized_v3(const float p[3], const float plane_co[3], const float plane_no_unit[3]);
float dist_to_plane_v3(const float p[3], const float plane_co[3], const float plane_no[3]);
float dist_to_line_segment_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 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[3], const float p[3], const float l1[3], const float l2[3]);
void closest_to_plane_v3(float r[3], const float plane_co[3], const float plane_no_unit[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(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]);
@@ -107,7 +118,7 @@ int isect_ray_plane_v3(const float p1[3], const float d[3],
float *r_lambda, const int clip);
int 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], const short no_flip);
+ const float plane_co[3], const float plane_no[3], const bool no_flip);
void 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],
@@ -124,13 +135,15 @@ int 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);
/* point in polygon */
+bool isect_point_poly_v2(const float pt[2], const float verts[][2], const int nr);
+bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const int nr);
+
int isect_point_quad_v2(const float p[2], const float a[2], const float b[2], const float c[2], const float d[2]);
-int isect_point_tri_v2(const float v1[2], const float v2[2], const float v3[2], const float pt[2]);
+int isect_point_tri_v2(const float pt[2], const float v1[2], const float v2[2], const float v3[2]);
int isect_point_tri_v2_cw(const float pt[2], const float v1[2], const float v2[2], const float v3[2]);
int isect_point_tri_v2_int(const int x1, const int y1, const int x2, const int y2, const int a, const int b);
int isect_point_tri_prism_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3]);
-
void isect_point_quad_uv_v2(const float v0[2], const float v1[2], const float v2[2], const float v3[2],
const float pt[2], float r_uv[2]);
void isect_point_face_uv_v2(const int isquad, const float v0[2], const float v1[2], const float v2[2],
@@ -157,7 +170,7 @@ int isect_axial_line_tri_v3(const int axis, const float co1[3], const float co2[
int clip_line_plane(float p1[3], float p2[3], const float plane[4]);
-void plot_line_v2v2i(const int p1[2], const int p2[2], int (*callback)(int, int, void *), void *userData);
+void plot_line_v2v2i(const int p1[2], const int p2[2], bool (*callback)(int, int, void *), void *userData);
/****************************** Interpolation ********************************/
@@ -254,14 +267,31 @@ MINLINE void madd_sh_shfl(float r[9], const float sh[3], const float f);
/********************************* Form Factor *******************************/
+float form_factor_quad(const float p[3], const float n[3],
+ const float q0[3], const float q1[3], const float q2[3], const float q3[3]);
+int form_factor_visible_quad(const float p[3], const float n[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float q0[3], float q1[3], float q2[3], float q3[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(int *axis_a, int *axis_b, const float axis[3]);
+bool axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3]);
+void axis_dominant_v3(int *r_axis_a, int *r_axis_b, const float axis[3]);
+float axis_dominant_v3_max(int *r_axis_a, int *r_axis_b, const float axis[3])
+#ifdef __GNUC__
+__attribute__((warn_unused_result))
+#endif
+;
MINLINE int max_axis_v3(const float vec[3]);
MINLINE int min_axis_v3(const float vec[3]);
+MINLINE int poly_to_tri_count(const int poly_count, const int corner_count);
+
+#ifdef BLI_MATH_GCC_WARN_PRAGMA
+# pragma GCC diagnostic pop
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_math_inline.h b/source/blender/blenlib/BLI_math_inline.h
index 6dad44644f2..2bf3b9532dd 100644
--- a/source/blender/blenlib/BLI_math_inline.h
+++ b/source/blender/blenlib/BLI_math_inline.h
@@ -56,6 +56,11 @@ extern "C" {
# define MALWAYS_INLINE
#endif
+/* gcc 4.6 (supports push/pop) */
+#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406))
+# define BLI_MATH_GCC_WARN_PRAGMA 1
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index c97eb4c588c..97cd6a60862 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -88,13 +88,15 @@ void mul_serie_m4(float R[4][4],
void mul_m4_v3(float M[4][4], float r[3]);
void mul_v3_m4v3(float r[3], float M[4][4], const float v[3]);
+void mul_v2_m2v2(float r[2], float M[2][2], const float v[2]);
void mul_mat3_m4_v3(float M[4][4], float r[3]);
void mul_m4_v4(float M[4][4], float r[4]);
-void mul_v4_m4v4(float r[4], float M[4][4], float v[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]);
void mul_m3_v3(float M[3][3], float r[3]);
-void mul_v3_m3v3(float r[3], float M[3][3], float a[3]);
+void mul_v3_m3v3(float r[3], float M[3][3], const float a[3]);
+void mul_v2_m3v3(float r[2], float M[3][3], const float a[3]);
void mul_transposed_m3_v3(float M[3][3], float r[3]);
void mul_m3_v3_double(float M[3][3], double r[3]);
@@ -144,10 +146,14 @@ float determinant_m2(float a, float b,
float determinant_m3(float a, float b, float c,
float d, float e, float f,
float g, float h, float i);
+float determinant_m3_array(float m[3][3]);
float determinant_m4(float A[4][4]);
+#define PSEUDOINVERSE_EPSILON 1e-8f
+
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_m3_m3(float Ainv[3][3], float A[3][3], float epsilon);
/****************************** Transformations ******************************/
@@ -165,10 +171,13 @@ void mat4_to_size(float r[3], float M[4][4]);
void translate_m4(float mat[4][4], float tx, float ty, float tz);
void rotate_m4(float mat[4][4], const char axis, const float angle);
+void rotate_m2(float mat[2][2], const float angle);
void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3]);
void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wmat[4][4]);
+void mat4_to_loc_quat(float loc[3], float quat[4], float wmat[4][4]);
+void mat4_decompose(float loc[3], float quat[4], float size[3], float wmat[4][4]);
void loc_eul_size_to_mat4(float R[4][4],
const float loc[3], const float eul[3], const float size[3]);
diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h
index 652925fbe49..5ba37d70ca5 100644
--- a/source/blender/blenlib/BLI_math_rotation.h
+++ b/source/blender/blenlib/BLI_math_rotation.h
@@ -186,6 +186,11 @@ float fov_to_focallength(float fov, float sensor);
float angle_wrap_rad(float angle);
float angle_wrap_deg(float angle);
+float angle_compat_rad(float angle, float angle_compat);
+
+int mat3_from_axis_conversion(int from_forward, int from_up, int to_forward, int to_up,
+ float r_mat[3][3]);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index f4572afec84..c9ad19f74b4 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -42,6 +42,11 @@ extern "C" {
/************************************* Init ***********************************/
+#ifdef BLI_MATH_GCC_WARN_PRAGMA
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wredundant-decls"
+#endif
+
MINLINE void zero_v2(float r[2]);
MINLINE void zero_v3(float r[3]);
MINLINE void zero_v4(float r[4]);
@@ -108,6 +113,7 @@ MINLINE void mul_v3_v3(float r[3], const float a[3]);
MINLINE void mul_v3_v3v3(float r[3], const float a[3], const float b[3]);
MINLINE void mul_v4_fl(float r[4], float f);
MINLINE void mul_v4_v4fl(float r[3], const float a[3], float f);
+MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3]);
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f);
MINLINE void madd_v3_v3v3(float r[3], const float a[3], const float b[3]);
@@ -171,6 +177,10 @@ 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 flip_v4_v4v4(float v[4], const float v1[4], const float v2[4]);
+void flip_v3_v3v3(float v[3], const float v1[3], const float v2[3]);
+void flip_v2_v2v2(float v[2], const float v1[2], const float v2[2]);
+
/********************************* Comparison ********************************/
MINLINE int is_zero_v3(const float a[3]);
@@ -251,10 +261,15 @@ void sub_vn_vn(float *array_tar, const float *array_src, const int size);
void sub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size);
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_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);
+#ifdef BLI_MATH_GCC_WARN_PRAGMA
+# pragma GCC diagnostic pop
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h
index 8fd2166e6f8..a1cbad73239 100644
--- a/source/blender/blenlib/BLI_mempool.h
+++ b/source/blender/blenlib/BLI_mempool.h
@@ -86,6 +86,18 @@ __attribute__((warn_unused_result))
__attribute__((nonnull(1)))
#endif
;
+void BLI_mempool_as_array(BLI_mempool *pool, void **data)
+#ifdef __GNUC__
+__attribute__((nonnull(1)))
+#endif
+;
+
+void *BLI_mempool_as_arrayN(BLI_mempool *pool, const char *allocstr)
+#ifdef __GNUC__
+__attribute__((warn_unused_result))
+__attribute__((nonnull(1, 2)))
+#endif
+;
/** iteration stuff. note: this may easy to produce bugs with **/
/* private structure */
diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index 5e47adf25ef..1ba3c8b619c 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -40,10 +40,10 @@ struct direntry;
const char *BLI_getDefaultDocumentFolder(void);
-char *BLI_get_folder(int folder_id, const char *subfolder);
-char *BLI_get_folder_create(int folder_id, const char *subfolder);
-char *BLI_get_user_folder_notest(int folder_id, const char *subfolder);
-char *BLI_get_folder_version(const int id, const int ver, const int do_check);
+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 */
@@ -67,6 +67,8 @@ char *BLI_get_folder_version(const int id, const int ver, const int do_check);
#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"
@@ -88,7 +90,7 @@ void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t d
void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen);
void BLI_split_file_part(const char *string, char *file, const size_t filelen);
void BLI_join_dirfile(char *string, const size_t maxlen, const char *dir, const char *file);
-char *BLI_path_basename(char *path);
+const char *BLI_path_basename(const char *path);
typedef enum bli_rebase_state {
BLI_REBASE_NO_SRCDIR = 0,
@@ -98,42 +100,46 @@ typedef enum bli_rebase_state {
int BLI_rebase_path(char *abs, size_t abs_len, char *rel, size_t rel_len, const char *base_dir, const char *src_dir, const char *dest_dir);
-char *BLI_last_slash(const char *string);
-int BLI_add_slash(char *string);
-void BLI_del_slash(char *string);
-char *BLI_first_slash(char *string);
+const char *BLI_last_slash(const char *string);
+int BLI_add_slash(char *string);
+void BLI_del_slash(char *string);
+const char *BLI_first_slash(const char *string);
void BLI_getlastdir(const char *dir, char *last, const size_t maxlen);
-int BLI_testextensie(const char *str, const char *ext);
-int BLI_testextensie_array(const char *str, const char **ext_array);
-int BLI_testextensie_glob(const char *str, const char *ext_fnmatch);
-int BLI_replace_extension(char *path, size_t maxlen, const char *ext);
-int BLI_ensure_extension(char *path, size_t maxlen, const char *ext);
-void BLI_uniquename(struct ListBase *list, void *vlink, const char defname[], char delim, short name_offs, short len);
-int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, const char defname[], char delim, char *name, short name_len);
+bool BLI_testextensie(const char *str, const char *ext);
+bool BLI_testextensie_array(const char *str, const char **ext_array);
+bool BLI_testextensie_glob(const char *str, const char *ext_fnmatch);
+bool BLI_replace_extension(char *path, size_t maxlen, const char *ext);
+bool BLI_ensure_extension(char *path, size_t maxlen, const char *ext);
+void BLI_uniquename(struct ListBase *list, void *vlink, const char * defname, char delim, short name_offs, short len);
+bool BLI_uniquename_cb(bool (*unique_check)(void * arg, const char * name),
+ void *arg, const char * defname, char delim, char *name, short name_len);
void BLI_newname(char *name, int add);
int BLI_stringdec(const char *string, char *head, char *start, unsigned short *numlen);
void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic);
int BLI_split_name_num(char *left, int *nr, const char *name, const char delim);
-void BLI_splitdirstring(char *di, char *fi);
/* make sure path separators conform to system one */
-void BLI_clean(char *path);
+void BLI_clean(char *path)
+#ifdef __GNUC__
+__attribute__((nonnull(1)))
+#endif
+;
/**
* dir can be any input, like from buttons, and this function
* converts it to a regular full path.
* Also removes garbage from directory paths, like /../ or double slashes etc
*/
-void BLI_cleanup_file(const char *relabase, char *dir); /* removes trailing slash */
+void BLI_cleanup_file(const char *relabase, char *path); /* removes trailing slash */
void BLI_cleanup_dir(const char *relabase, char *dir); /* same as above but adds a trailing slash */
-void BLI_cleanup_path(const char *relabase, char *dir); /* doesn't touch trailing slash */
+void BLI_cleanup_path(const char *relabase, char *path); /* doesn't touch trailing slash */
/* go back one directory */
-int BLI_parent_dir(char *path);
+bool BLI_parent_dir(char *path);
/* return whether directory is root and thus has no parent dir */
-int BLI_has_parent(char *path);
+bool BLI_has_parent(char *path);
/**
* Blender's path code replacement function.
@@ -147,14 +153,15 @@ int BLI_has_parent(char *path);
* \a framenum The framenumber to replace the frame code with.
* \retval Returns true if the path was relative (started with "//").
*/
-int BLI_path_abs(char *path, const char *basepath);
-int BLI_path_frame(char *path, int frame, int digits);
-int BLI_path_frame_range(char *path, int sta, int end, int digits);
-int BLI_path_cwd(char *path);
+bool BLI_path_abs(char *path, const char *basepath);
+bool BLI_path_frame(char *path, int frame, int digits);
+bool BLI_path_frame_range(char *path, int sta, int end, int digits);
+bool BLI_path_cwd(char *path);
void BLI_path_rel(char *file, const char *relfile);
-int BLI_path_is_rel(const char *path);
+bool BLI_path_is_rel(const char *path);
+/* path string comparisons: case-insensitive for Windows, case-sensitive otherwise */
#ifdef WIN32
# define BLI_path_cmp BLI_strcasecmp
# define BLI_path_ncmp BLI_strncasecmp
@@ -163,15 +170,11 @@ int BLI_path_is_rel(const char *path);
# define BLI_path_ncmp strncmp
#endif
-/**
- * Change every \a from in \a string into \a to. The
- * result will be in \a string
- *
- * \a string The string to work on
- * \a from The character to replace
- * \a to The character to replace with
- */
-void BLI_char_switch(char *string, char from, char to);
+void BLI_char_switch(char *string, char from, char to)
+#ifdef __GNUC__
+__attribute__((nonnull(1)))
+#endif
+;
/* Initialize path to program executable */
void BLI_init_program_path(const char *argv0);
@@ -179,13 +182,9 @@ void BLI_init_program_path(const char *argv0);
* NOTE: On Window userdir will be set to the temporary directory! */
void BLI_init_temporary_dir(char *userdir);
-/* Path to executable */
const char *BLI_program_path(void);
-/* Path to directory of executable */
const char *BLI_program_dir(void);
-/* Path to temporary directory (with trailing slash) */
const char *BLI_temporary_dir(void);
-/* Path to the system temporary directory (with trailing slash) */
void BLI_system_temporary_dir(char *dir);
#ifdef WITH_ICONV
diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h
index f2e26093711..ac0ae22c656 100644
--- a/source/blender/blenlib/BLI_rect.h
+++ b/source/blender/blenlib/BLI_rect.h
@@ -43,8 +43,8 @@ struct rcti;
extern "C" {
#endif
-int BLI_rcti_is_empty(const struct rcti *rect);
-int BLI_rctf_is_empty(const struct rctf *rect);
+bool BLI_rcti_is_empty(const struct rcti *rect);
+bool BLI_rctf_is_empty(const struct rctf *rect);
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax);
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax);
void BLI_rcti_init_minmax(struct rcti *rect);
@@ -54,22 +54,26 @@ void BLI_rctf_do_minmax_v(struct rctf *rect, const float xy[2]);
void BLI_rctf_translate(struct rctf *rect, float x, float y);
void BLI_rcti_translate(struct rcti *rect, int x, int y);
+void BLI_rcti_recenter(struct rcti *rect, int x, int y);
+void BLI_rctf_recenter(struct rctf *rect, float x, float y);
void BLI_rcti_resize(struct rcti *rect, int x, int y);
void BLI_rctf_resize(struct rctf *rect, float x, float y);
+void BLI_rcti_scale(rcti *rect, const float scale);
+void BLI_rctf_scale(rctf *rect, const float scale);
void BLI_rctf_interp(struct rctf *rect, const struct rctf *rect_a, const struct rctf *rect_b, const float fac);
//void BLI_rcti_interp(struct rctf *rect, struct rctf *rect_a, struct rctf *rect_b, float fac);
-int BLI_rctf_clamp_pt_v(const struct rctf *rect, float xy[2]);
-int BLI_rcti_clamp_pt_v(const struct rcti *rect, int xy[2]);
-int BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, const float limit);
-int BLI_rcti_compare(const struct rcti *rect_a, const struct rcti *rect_b);
-int BLI_rctf_isect(const struct rctf *src1, const struct rctf *src2, struct rctf *dest);
-int BLI_rcti_isect(const struct rcti *src1, const struct rcti *src2, struct rcti *dest);
-int BLI_rcti_isect_pt(const struct rcti *rect, const int x, const int y);
-int BLI_rcti_isect_pt_v(const struct rcti *rect, const int xy[2]);
-int BLI_rctf_isect_pt(const struct rctf *rect, const float x, const float y);
-int BLI_rctf_isect_pt_v(const struct rctf *rect, const float xy[2]);
-int BLI_rcti_isect_segment(const struct rcti *rect, const int s1[2], const int s2[2]);
-int BLI_rctf_isect_segment(const struct rctf *rect, const float s1[2], const float s2[2]);
+bool BLI_rctf_clamp_pt_v(const struct rctf *rect, float xy[2]);
+bool BLI_rcti_clamp_pt_v(const struct rcti *rect, int xy[2]);
+bool BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, const float limit);
+bool BLI_rcti_compare(const struct rcti *rect_a, const struct rcti *rect_b);
+bool BLI_rctf_isect(const struct rctf *src1, const struct rctf *src2, struct rctf *dest);
+bool BLI_rcti_isect(const struct rcti *src1, const struct rcti *src2, struct rcti *dest);
+bool BLI_rcti_isect_pt(const struct rcti *rect, const int x, const int y);
+bool BLI_rcti_isect_pt_v(const struct rcti *rect, const int xy[2]);
+bool BLI_rctf_isect_pt(const struct rctf *rect, const float x, const float y);
+bool BLI_rctf_isect_pt_v(const struct rctf *rect, const float xy[2]);
+bool BLI_rcti_isect_segment(const struct rcti *rect, const int s1[2], const int s2[2]);
+bool BLI_rctf_isect_segment(const struct rctf *rect, const float s1[2], const float s2[2]);
void BLI_rctf_union(struct rctf *rctf1, const struct rctf *rctf2);
void BLI_rcti_union(struct rcti *rcti1, const struct rcti *rcti2);
void BLI_rcti_rctf_copy(struct rcti *dst, const struct rctf *src);
diff --git a/source/blender/blenlib/BLI_scanfill.h b/source/blender/blenlib/BLI_scanfill.h
index c8fd72bbbd2..ce2c6a4252f 100644
--- a/source/blender/blenlib/BLI_scanfill.h
+++ b/source/blender/blenlib/BLI_scanfill.h
@@ -72,7 +72,8 @@ typedef struct ScanFillVert {
float xy[2]; /* 2D copy of vertex location (using dominant axis) */
unsigned int keyindex; /* original index #, for restoring key information */
short poly_nr;
- unsigned char f, h;
+ unsigned char edge_tot; /* number of edges using this vertex */
+ unsigned char f;
} ScanFillVert;
typedef struct ScanFillEdge {
@@ -101,6 +102,10 @@ enum {
* Assumes ordered edges, otherwise we risk an eternal loop
* removing double verts. - campbell */
BLI_SCANFILL_CALC_REMOVE_DOUBLES = (1 << 1),
+
+ /* note: This flag removes checks for overlapping polygons.
+ * when this flag is set, we'll never get back more faces then (totvert - 2) */
+ BLI_SCANFILL_CALC_HOLES = (1 << 2)
};
int BLI_scanfill_begin(ScanFillContext *sf_ctx);
diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index 70c89773f02..3bc9d733254 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -38,42 +38,20 @@
extern "C" {
#endif
-/**
- * Duplicates the cstring \a str into a newly mallocN'd
- * string and returns it.
- *
- * \param str The string to be duplicated
- * \retval Returns the duplicated string
- */
-char *BLI_strdup(const char *str)
+char *BLI_strdupn(const char *str, const size_t len)
#ifdef __GNUC__
__attribute__((warn_unused_result))
__attribute__((nonnull))
#endif
;
-/**
- * Duplicates the first \a len bytes of cstring \a str
- * into a newly mallocN'd string and returns it. \a str
- * is assumed to be at least len bytes long.
- *
- * \param str The string to be duplicated
- * \param len The number of bytes to duplicate
- * \retval Returns the duplicated string
- */
-char *BLI_strdupn(const char *str, const size_t len)
+char *BLI_strdup(const char *str)
#ifdef __GNUC__
__attribute__((warn_unused_result))
__attribute__((nonnull))
#endif
;
-/**
- * Appends the two strings, and returns new mallocN'ed string
- * \param str1 first string for copy
- * \param str2 second string for append
- * \retval Returns dst
- */
char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2)
#ifdef __GNUC__
__attribute__((warn_unused_result))
@@ -81,32 +59,19 @@ __attribute__((nonnull))
#endif
;
-/**
- * Like strncpy but ensures dst is always
- * '\0' terminated.
- *
- * \param dst Destination for copy
- * \param src Source string to copy
- * \param maxncpy Maximum number of characters to copy (generally
- * the size of dst)
- * \retval Returns dst
- */
char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy)
#ifdef __GNUC__
__attribute__((nonnull))
#endif
;
-/**
- *Makes a copy of the text within the "" that appear after some text 'blahblah'
- * i.e. for string 'pose["apples"]' with prefix 'pose[', it should grab "apples"
- *
- * - str: is the entire string to chop
- * - prefix: is the part of the string to leave out
- *
- * Assume that the strings returned must be freed afterwards, and that the inputs will contain
- * data we want...
- */
+size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, const size_t maxncpy)
+#ifdef __GNUC__
+__attribute__((warn_unused_result))
+__attribute__((nonnull))
+#endif
+;
+
char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix)
#ifdef __GNUC__
__attribute__((warn_unused_result))
@@ -114,16 +79,6 @@ __attribute__((nonnull))
#endif
;
-/**
- * Returns a copy of the cstring \a str into a newly mallocN'd
- * string with all instances of oldText replaced with newText,
- * and returns it.
- *
- * \param str The string to replace occurrences of oldText in
- * \param oldText The text in the string to find and replace
- * \param newText The text in the string to find and replace
- * \retval Returns the duplicated string
- */
char *BLI_replacestr(char *__restrict str, const char *__restrict oldText, const char *__restrict newText)
#ifdef __GNUC__
__attribute__((warn_unused_result))
@@ -131,9 +86,6 @@ __attribute__((nonnull))
#endif
;
-/*
- * Replacement for snprintf
- */
size_t BLI_snprintf(char *__restrict buffer, size_t len, const char *__restrict format, ...)
#ifdef __GNUC__
__attribute__ ((format(printf, 3, 4)))
@@ -141,19 +93,12 @@ __attribute__((nonnull))
#endif
;
-/*
- * Replacement for vsnprintf
- */
size_t BLI_vsnprintf(char *__restrict buffer, size_t count, const char *__restrict format, va_list arg)
#ifdef __GNUC__
__attribute__ ((format(printf, 3, 0)))
#endif
;
-/*
- * Print formatted string into a newly mallocN'd string
- * and return it.
- */
char *BLI_sprintfN(const char *__restrict format, ...)
#ifdef __GNUC__
__attribute__ ((format(printf, 1, 2)))
@@ -168,11 +113,6 @@ __attribute__((nonnull))
#endif
;
-/**
- * Compare two strings without regard to case.
- *
- * \retval True if the strings are equal, false otherwise.
- */
int BLI_strcaseeq(const char *a, const char *b)
#ifdef __GNUC__
__attribute__((warn_unused_result))
@@ -214,7 +154,7 @@ void BLI_timestr(double _time, char *str)
#ifdef __GNUC__
__attribute__((nonnull))
#endif
-; /* time var is global */
+;
void BLI_ascii_strtolower(char *str, const size_t len)
#ifdef __GNUC__
@@ -226,6 +166,11 @@ void BLI_ascii_strtoupper(char *str, const size_t len)
__attribute__((nonnull))
#endif
;
+int BLI_str_rstrip_float_zero(char *str, const char pad)
+#ifdef __GNUC__
+__attribute__((nonnull))
+#endif
+;
#ifdef __cplusplus
}
diff --git a/source/blender/blenlib/BLI_string_cursor_utf8.h b/source/blender/blenlib/BLI_string_cursor_utf8.h
index 3c38c0380e0..04d9df2abda 100644
--- a/source/blender/blenlib/BLI_string_cursor_utf8.h
+++ b/source/blender/blenlib/BLI_string_cursor_utf8.h
@@ -46,6 +46,6 @@ int BLI_str_cursor_step_prev_utf8(const char *str, size_t maxlen, int *pos);
void BLI_str_cursor_step_utf8(const char *str, size_t maxlen,
int *pos, strCursorJumpDirection direction,
- strCursorJumpType jump);
+ strCursorJumpType jump, bool use_init_step);
#endif /* __BLI_STRING_CURSOR_UTF8_H__ */
diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h
index ecbc4cb1cd4..d20cbd2a91c 100644
--- a/source/blender/blenlib/BLI_string_utf8.h
+++ b/source/blender/blenlib/BLI_string_utf8.h
@@ -41,6 +41,7 @@ int BLI_str_utf8_size_safe(const char *p);
/* copied from glib */
unsigned int BLI_str_utf8_as_unicode(const char *p);
unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index);
+unsigned int BLI_str_utf8_as_unicode_and_size_safe(const char *__restrict p, size_t *__restrict index);
unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index);
size_t BLI_str_utf8_from_unicode(unsigned int c, char *outbuf);
@@ -55,7 +56,14 @@ size_t BLI_strnlen_utf8(const char *start, const size_t maxlen);
size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, const size_t maxcpy);
size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst, const char *__restrict src, const size_t maxcpy);
-#define BLI_UTF8_MAX 6
+/* count columns that character/string occupies, based on wcwidth.c */
+int BLI_wcwidth(wchar_t ucs);
+int BLI_wcswidth(const wchar_t *pwcs, size_t n);
+int BLI_str_utf8_char_width(const char *p); /* warning, can return -1 on bad chars */
+int BLI_str_utf8_char_width_safe(const char *p);
+
+#define BLI_UTF8_MAX 6 /* mem */
+#define BLI_UTF8_WIDTH_MAX 2 /* columns */
#define BLI_UTF8_ERR ((unsigned int)-1)
#ifdef __cplusplus
diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h
index 7c3b70545d6..bf5531d94af 100644
--- a/source/blender/blenlib/BLI_utildefines.h
+++ b/source/blender/blenlib/BLI_utildefines.h
@@ -32,12 +32,45 @@
* \ingroup bli
*/
-#ifndef FALSE
-# define FALSE 0
+#ifndef NDEBUG /* for BLI_assert */
+#include <stdio.h>
#endif
-#ifndef TRUE
-# define TRUE 1
+/* note: use of (int, TRUE / FALSE) is deprecated,
+ * use (bool, true / false) instead */
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# ifndef HAVE__BOOL
+# ifdef __cplusplus
+typedef bool _BLI_Bool;
+# else
+/* using char here may cause nasty tricky bugs, e.g.
+ * bool is_bit_flag = RNA_property_flag(prop) & PROP_ENUM_FLAG;
+ * as PROP_ENUM_FLAG is farther than 8th bit, do_translate would be always false!
+ */
+# define _BLI_Bool unsigned int
+# endif
+# else
+# define _BLI_Bool _Bool
+# endif
+# define bool _BLI_Bool
+# define false 0
+# define true 1
+# define __bool_true_false_are_defined 1
+#endif
+
+/* remove this when we're ready to remove TRUE/FALSE completely */
+#ifdef WITH_BOOL_COMPAT
+/* interim until all occurrences of these can be updated to stdbool */
+/* XXX Why not use the true/false velues here? */
+# ifndef FALSE
+# define FALSE 0
+# endif
+
+# ifndef TRUE
+# define TRUE 1
+# endif
#endif
/* useful for finding bad use of min/max */
@@ -134,7 +167,7 @@
(b) = (tval); \
} (void)0
-
+/* ELEM#(a, ...): is the first arg equal any of the others */
#define ELEM(a, b, c) ((a) == (b) || (a) == (c))
#define ELEM3(a, b, c, d) (ELEM(a, b, c) || (a) == (d) )
#define ELEM4(a, b, c, d, e) (ELEM(a, b, c) || ELEM(a, d, e) )
@@ -262,9 +295,9 @@
#define UNPACK3(a) ((a)[0]), ((a)[1]), ((a)[2])
#define UNPACK4(a) ((a)[0]), ((a)[1]), ((a)[2]), ((a)[3])
/* op may be '&' or '*' */
-#define UNPACK2OP(a, op) op((a)[0]), op((a)[1])
-#define UNPACK3OP(a, op) op((a)[0]), op((a)[1]), op((a)[2])
-#define UNPACK4OP(a, op) op((a)[0]), op((a)[1]), op((a)[2]), op((a)[3])
+#define UNPACK2OP(op, a) op((a)[0]), op((a)[1])
+#define UNPACK3OP(op, a) op((a)[0]), op((a)[1]), op((a)[2])
+#define UNPACK4OP(op, a) op((a)[0]), op((a)[1]), op((a)[2]), op((a)[3])
/* array helpers */
#define ARRAY_LAST_ITEM(arr_start, arr_dtype, elem_size, tot) \
@@ -293,6 +326,22 @@
#define STRINGIFY_APPEND(a, b) "" a #b
#define STRINGIFY(x) STRINGIFY_APPEND("", x)
+/* generic strcmp macros */
+#define STREQ(a, b) (strcmp(a, b) == 0)
+#define STRNEQ(a, b) (!STREQ(a, b))
+
+#define STRCASEEQ(a, b) (strcasecmp(a, b) == 0)
+#define STRCASENEQ(a, b) (!STRCASEEQ(a, b))
+
+#define STREQLEN(a, b, n) (strncmp(a, b, n) == 0)
+#define STRNEQLEN(a, b, n) (!STREQLEN(a, b, n))
+
+#define STRCASEEQLEN(a, b, n) (strncasecmp(a, b, n) == 0)
+#define STRCASENEQLEN(a, b, n) (!STRCASEEQLEN(a, b, n))
+
+#define STRPREFIX(a, b) (strncmp((a), (b), strlen(b)) == 0)
+
+
/* useful for debugging */
#define AT __FILE__ ":" STRINGIFY(__LINE__)
@@ -366,7 +415,8 @@
# define BLI_assert(a) (void)0
#endif
-#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) /* gcc4.6+ only */
+/* C++ can't use _Static_assert, expects static_assert() but c++0x only */
+#if (!defined(__cplusplus)) && (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) /* gcc4.6+ only */
# define BLI_STATIC_ASSERT(a, msg) _Static_assert(a, msg);
#else
/* TODO msvc, clang */
diff --git a/source/blender/blenlib/BLI_vfontdata.h b/source/blender/blenlib/BLI_vfontdata.h
index ed7d10ab257..b0a57ee9288 100644
--- a/source/blender/blenlib/BLI_vfontdata.h
+++ b/source/blender/blenlib/BLI_vfontdata.h
@@ -53,14 +53,6 @@ typedef struct VChar {
float *points;
} VChar;
-/**
- * Construct a new VFontData structure from
- * Freetype font data in a PackedFile.
- *
- * \param pf The font data.
- * \retval A new VFontData structure, or NULL
- * if unable to load.
- */
VFontData *BLI_vfontdata_from_freetypefont(struct PackedFile *pf);
int BLI_vfontchar_from_freetypefont(struct VFont *vfont, unsigned long character);
diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h
index 70c7f1d9cae..20a4c3c274e 100644
--- a/source/blender/blenlib/BLI_winstuff.h
+++ b/source/blender/blenlib/BLI_winstuff.h
@@ -94,6 +94,15 @@ extern "C" {
/* defines for using ISO C++ conformant names */
#define snprintf _snprintf
+#ifdef _MSC_VER
+# define R_OK 4
+# define W_OK 2
+// not accepted by access() on windows
+//# define X_OK 1
+# define F_OK 0
+# define PATH_MAX 4096
+#endif
+
#ifndef FREE_WINDOWS
typedef unsigned int mode_t;
#endif
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 8a3b1c9675b..e39ae395ffa 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -23,14 +23,16 @@
#
# ***** 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
- ../blenloader
- ../gpu
+ # ../blenkernel # dont add this back!
../makesdna
+ ../makesrna
../../../intern/ghost
../../../intern/guardedalloc
+ ../../../extern/wcwidth
)
set(INC_SYS
@@ -40,6 +42,7 @@ set(INC_SYS
set(SRC
intern/BLI_args.c
+ intern/BLI_array.c
intern/BLI_dynstr.c
intern/BLI_ghash.c
intern/BLI_heap.c
@@ -50,7 +53,7 @@ set(SRC
intern/BLI_mempool.c
intern/DLRB_tree.c
intern/boxpack2d.c
- intern/bpath.c
+ intern/buffer.c
intern/callbacks.c
intern/cpu.c
intern/dynlib.c
@@ -78,7 +81,6 @@ set(SRC
intern/md5.c
intern/noise.c
intern/path_util.c
- intern/pbvh.c
intern/quadric.c
intern/rand.c
intern/rct.c
@@ -100,8 +102,8 @@ set(SRC
BLI_array.h
BLI_bitmap.h
BLI_blenlib.h
+ BLI_buffer.h
BLI_boxpack2d.h
- BLI_bpath.h
BLI_callbacks.h
BLI_cpu.h
BLI_dlrbTree.h
@@ -137,7 +139,6 @@ set(SRC
BLI_mempool.h
BLI_noise.h
BLI_path_util.h
- BLI_pbvh.h
BLI_quadric.h
BLI_rand.h
BLI_rect.h
diff --git a/source/blender/blenlib/SConscript b/source/blender/blenlib/SConscript
index e53f622a5c4..41a9fe9e8b4 100644
--- a/source/blender/blenlib/SConscript
+++ b/source/blender/blenlib/SConscript
@@ -1,11 +1,37 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('intern/*.c')
cflags=''
-incs = '. ../makesdna ../blenkernel #/intern/guardedalloc #/intern/ghost ../editors/include ../gpu ../blenloader'
-incs += ' ../windowmanager ../bmesh #/extern/glew/include'
+# don't add ../blenkernel back!
+incs = '. ../makesdna #/intern/guardedalloc #/intern/ghost #/extern/wcwidth'
incs += ' ' + env['BF_FREETYPE_INC']
incs += ' ' + env['BF_ZLIB_INC']
diff --git a/source/blender/blenlib/intern/BLI_array.c b/source/blender/blenlib/intern/BLI_array.c
new file mode 100644
index 00000000000..5823b7db3f1
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_array.c
@@ -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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joseph Eagar,
+ * Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenlib/intern/BLI_array.c
+ * \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.
+ *
+ * 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
+ *
+ * little array macro library. example of usage:
+ *
+ * int *arr = NULL;
+ * BLI_array_declare(arr);
+ * int i;
+ *
+ * for (i = 0; i < 10; i++) {
+ * BLI_array_grow_one(arr);
+ * arr[i] = something;
+ * }
+ * BLI_array_free(arr);
+ *
+ * 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.
+ */
+
+#include <string.h>
+
+#include "BLI_array.h"
+
+#include "MEM_guardedalloc.h"
+
+/**
+ * This function is only to be called via macros.
+ *
+ * \note The caller must adjust \a arr_count
+ */
+void _bli_array_grow_func(void **arr_p, const void *arr_static,
+ const int sizeof_arr_p, const int arr_count, const int num,
+ const char *alloc_str)
+{
+ void *arr = *arr_p;
+ void *arr_tmp;
+
+ arr_tmp = MEM_mallocN(sizeof_arr_p *
+ ((num < arr_count) ?
+ (arr_count * 2 + 2) : (arr_count + num)), alloc_str);
+
+ if (arr) {
+ memcpy(arr_tmp, arr, sizeof_arr_p * arr_count);
+
+ if (arr != arr_static) {
+ MEM_freeN(arr);
+ }
+ }
+
+ *arr_p = arr_tmp;
+
+ /* caller must do */
+#if 0
+ arr_count += num;
+#endif
+}
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 8767a9ac14c..0887d646479 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -39,7 +39,7 @@
#include "BLI_mempool.h"
#include "BLI_ghash.h"
-#include "BLO_sys_types.h" // for intptr_t support
+#include "MEM_sys_types.h" /* for intptr_t support */
/***/
unsigned int hashsizes[] = {
@@ -62,8 +62,7 @@ GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info)
gh->nentries = 0;
gh->nbuckets = hashsizes[gh->cursize];
- gh->buckets = MEM_mallocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
- memset(gh->buckets, 0, gh->nbuckets * sizeof(*gh->buckets));
+ gh->buckets = MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
return gh;
}
@@ -78,9 +77,9 @@ void BLI_ghash_insert(GHash *gh, void *key, void *val)
unsigned int hash = gh->hashfp(key) % gh->nbuckets;
Entry *e = (Entry *)BLI_mempool_alloc(gh->entrypool);
+ e->next = gh->buckets[hash];
e->key = key;
e->val = val;
- e->next = gh->buckets[hash];
gh->buckets[hash] = e;
if (++gh->nentries > (float)gh->nbuckets / 2) {
@@ -88,8 +87,7 @@ void BLI_ghash_insert(GHash *gh, void *key, void *val)
int i, nold = gh->nbuckets;
gh->nbuckets = hashsizes[++gh->cursize];
- gh->buckets = (Entry **)MEM_mallocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
- memset(gh->buckets, 0, gh->nbuckets * sizeof(*gh->buckets));
+ gh->buckets = (Entry **)MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets");
for (i = 0; i < nold; i++) {
for (e = old[i]; e; ) {
@@ -109,18 +107,18 @@ void BLI_ghash_insert(GHash *gh, void *key, void *val)
void *BLI_ghash_lookup(GHash *gh, const void *key)
{
- if (gh) {
- unsigned int hash = gh->hashfp(key) % gh->nbuckets;
- Entry *e;
+ const unsigned int hash = gh->hashfp(key) % gh->nbuckets;
+ Entry *e;
- for (e = gh->buckets[hash]; e; e = e->next)
- if (gh->cmpfp(key, e->key) == 0)
- return e->val;
+ for (e = gh->buckets[hash]; e; e = e->next) {
+ if (gh->cmpfp(key, e->key) == 0) {
+ return e->val;
+ }
}
return NULL;
}
-int BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
+bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
{
unsigned int hash = gh->hashfp(key) % gh->nbuckets;
Entry *e;
@@ -140,12 +138,38 @@ int BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFre
else gh->buckets[hash] = n;
gh->nentries--;
- return 1;
+ return true;
}
p = e;
}
- return 0;
+ return false;
+}
+
+void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
+{
+ int i;
+
+ if (keyfreefp || valfreefp) {
+ for (i = 0; i < gh->nbuckets; i++) {
+ Entry *e;
+
+ for (e = gh->buckets[i]; e; ) {
+ Entry *n = e->next;
+
+ if (keyfreefp) keyfreefp(e->key);
+ if (valfreefp) valfreefp(e->val);
+
+ e = n;
+ }
+ }
+ }
+
+ gh->cursize = 0;
+ gh->nentries = 0;
+ gh->nbuckets = hashsizes[gh->cursize];
+
+ gh->buckets = MEM_recallocN(gh->buckets, gh->nbuckets * sizeof(*gh->buckets));
}
/* same as above but return the value,
@@ -178,16 +202,16 @@ void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp)
return NULL;
}
-int BLI_ghash_haskey(GHash *gh, const void *key)
+bool BLI_ghash_haskey(GHash *gh, const void *key)
{
unsigned int hash = gh->hashfp(key) % gh->nbuckets;
Entry *e;
for (e = gh->buckets[hash]; e; e = e->next)
if (gh->cmpfp(key, e->key) == 0)
- return 1;
+ return true;
- return 0;
+ return false;
}
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
@@ -271,9 +295,9 @@ void BLI_ghashIterator_step(GHashIterator *ghi)
}
}
}
-int BLI_ghashIterator_isDone(GHashIterator *ghi)
+bool BLI_ghashIterator_notDone(GHashIterator *ghi)
{
- return !ghi->curEntry;
+ return ghi->curEntry != NULL;
}
/***/
diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c
index dcc028630e2..53489c76962 100644
--- a/source/blender/blenlib/intern/BLI_heap.c
+++ b/source/blender/blenlib/intern/BLI_heap.c
@@ -33,9 +33,10 @@
#include <string.h>
#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
#include "BLI_memarena.h"
#include "BLI_heap.h"
-#include "BLI_utildefines.h"
/***/
@@ -167,7 +168,7 @@ HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr)
heap->freenodes = (HeapNode *)(((HeapNode *)heap->freenodes)->ptr);
}
else {
- node = (HeapNode *)BLI_memarena_alloc(heap->arena, sizeof *node);
+ node = (HeapNode *)BLI_memarena_alloc(heap->arena, sizeof(*node));
}
node->value = value;
@@ -183,7 +184,7 @@ HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr)
return node;
}
-int BLI_heap_is_empty(Heap *heap)
+bool BLI_heap_is_empty(Heap *heap)
{
return (heap->size == 0);
}
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index 6cf167b8823..b2d07b9ee4d 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -1237,7 +1237,7 @@ static void dfs_find_nearest_begin(BVHNearestData *data, BVHNode *node)
#define DEFAULT_FIND_NEAREST_HEAP_SIZE 1024
-#define NodeDistance_priority(a, b) ( (a).dist < (b).dist)
+#define NodeDistance_priority(a, b) ((a).dist < (b).dist)
static void NodeDistance_push_heap(NodeDistance *heap, int heap_size)
PUSH_HEAP_BODY(NodeDistance, NodeDistance_priority, heap, heap_size)
@@ -1554,7 +1554,7 @@ int BLI_bvhtree_ray_cast(BVHTree *tree, const float co[3], const float dir[3], f
float BLI_bvhtree_bb_raycast(const float bv[6], const float light_start[3], const float light_end[3], float pos[3])
{
BVHRayCastData data;
- float dist = 0.0;
+ float dist;
data.hit.dist = FLT_MAX;
diff --git a/source/blender/blenlib/intern/BLI_linklist.c b/source/blender/blenlib/intern/BLI_linklist.c
index 0e630efc349..b08fbe17a43 100644
--- a/source/blender/blenlib/intern/BLI_linklist.c
+++ b/source/blender/blenlib/intern/BLI_linklist.c
@@ -155,6 +155,18 @@ void BLI_linklist_free(LinkNode *list, LinkNodeFreeFP freefunc)
}
}
+void BLI_linklist_freeN(LinkNode *list)
+{
+ while (list) {
+ LinkNode *next = list->next;
+
+ MEM_freeN(list->link);
+ MEM_freeN(list);
+
+ list = next;
+ }
+}
+
void BLI_linklist_apply(LinkNode *list, LinkNodeApplyFP applyfunc, void *userdata)
{
for (; list; list = list->next)
diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c
index 0ac6209fc95..b6b5b600ab1 100644
--- a/source/blender/blenlib/intern/BLI_memarena.c
+++ b/source/blender/blenlib/intern/BLI_memarena.c
@@ -74,7 +74,7 @@ void BLI_memarena_use_align(struct MemArena *ma, const int align)
void BLI_memarena_free(MemArena *ma)
{
- BLI_linklist_free(ma->bufs, (void (*)(void *))MEM_freeN);
+ BLI_linklist_freeN(ma->bufs);
MEM_freeN(ma);
}
diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c
index d98e63d88dd..5f0c90f234d 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -27,9 +27,7 @@
/** \file blender/blenlib/intern/BLI_mempool.c
* \ingroup bli
- */
-
-/*
+ *
* Simple, fast memory allocator for allocating many elements of the same size.
*/
@@ -56,6 +54,9 @@
#define FREEWORD MAKE_ID('f', 'r', 'e', 'e')
+/* currently totalloc isnt used */
+// #define USE_TOTALLOC
+
typedef struct BLI_freenode {
struct BLI_freenode *next;
int freeword; /* used to identify this as a freed node */
@@ -112,6 +113,7 @@ BLI_mempool *BLI_mempool_create(int esize, int totelem, int pchunk, int flag)
pool->pchunk = pchunk;
pool->csize = esize * pchunk;
pool->chunks.first = pool->chunks.last = NULL;
+ pool->totalloc = 0;
pool->totused = 0;
maxchunks = totelem / pchunk + 1;
@@ -161,10 +163,11 @@ BLI_mempool *BLI_mempool_create(int esize, int totelem, int pchunk, int flag)
}
}
- /* set the end of this chunks memoryy to the new tail for next iteration */
+ /* set the end of this chunks memory to the new tail for next iteration */
lasttail = curnode;
-
+#ifdef USE_TOTALLOC
pool->totalloc += pool->pchunk;
+#endif
}
/* terminate the list */
curnode->next = NULL;
@@ -215,8 +218,9 @@ void *BLI_mempool_alloc(BLI_mempool *pool)
}
}
curnode->next = NULL; /* terminate the list */
-
+#ifdef USE_TOTALLOC
pool->totalloc += pool->pchunk;
+#endif
}
retval = pool->free;
@@ -237,12 +241,20 @@ void *BLI_mempool_calloc(BLI_mempool *pool)
return retval;
}
-/* doesnt protect against double frees, don't be stupid! */
+/**
+ * Free an element from the mempool.
+ *
+ * \note doesnt protect against double frees, don't be stupid!
+ */
void BLI_mempool_free(BLI_mempool *pool, void *addr)
{
BLI_freenode *newhead = addr;
if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
+#ifndef NDEBUG
+ /* this will detect double free's */
+ BLI_assert(newhead->freeword != FREEWORD);
+#endif
newhead->freeword = FREEWORD;
}
@@ -276,7 +288,9 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr)
}
BLI_addtail(&pool->chunks, first);
+#ifdef USE_TOTALLOC
pool->totalloc = pool->pchunk;
+#endif
pool->free = first->data; /* start of the list */
for (tmpaddr = first->data, i = 0; i < pool->pchunk; i++) {
@@ -295,33 +309,51 @@ int BLI_mempool_count(BLI_mempool *pool)
void *BLI_mempool_findelem(BLI_mempool *pool, int index)
{
- if (!(pool->flag & BLI_MEMPOOL_ALLOW_ITER)) {
- fprintf(stderr, "%s: Error! you can't iterate over this mempool!\n", __func__);
- return NULL;
- }
- else if ((index >= 0) && (index < pool->totused)) {
+ BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER);
+
+ if ((index >= 0) && (index < pool->totused)) {
/* we could have some faster mem chunk stepping code inline */
BLI_mempool_iter iter;
void *elem;
BLI_mempool_iternew(pool, &iter);
for (elem = BLI_mempool_iterstep(&iter); index-- != 0; elem = BLI_mempool_iterstep(&iter)) {
/* do nothing */
- };
+ }
return elem;
}
return NULL;
}
-void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter)
+/**
+ * \param data array of pointers at least the size of 'pool->totused'
+ */
+void BLI_mempool_as_array(BLI_mempool *pool, void **data)
{
- if (!(pool->flag & BLI_MEMPOOL_ALLOW_ITER)) {
- fprintf(stderr, "%s: Error! you can't iterate over this mempool!\n", __func__);
- iter->curchunk = NULL;
- iter->curindex = 0;
-
- return;
+ BLI_mempool_iter iter;
+ void *elem;
+ void **p = data;
+ BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER);
+ BLI_mempool_iternew(pool, &iter);
+ for (elem = BLI_mempool_iterstep(&iter); elem; elem = BLI_mempool_iterstep(&iter)) {
+ *p++ = elem;
}
+ BLI_assert((p - data) == pool->totused);
+}
+
+/**
+ * Allocate an array from the mempool.
+ */
+void *BLI_mempool_as_arrayN(BLI_mempool *pool, const char *allocstr)
+{
+ void *data = MEM_mallocN(BLI_mempool_count(pool) * pool->esize, allocstr);
+ BLI_mempool_as_array(pool, data);
+ return data;
+}
+
+void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter)
+{
+ BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER);
iter->pool = pool;
iter->curchunk = pool->chunks.first;
@@ -391,6 +423,9 @@ void *BLI_mempool_iterstep(BLI_mempool_iter *iter)
#endif
+/**
+ * Free the mempool its self (and all elements).
+ */
void BLI_mempool_destroy(BLI_mempool *pool)
{
BLI_mempool_chunk *mpchunk = NULL;
diff --git a/source/blender/blenlib/intern/buffer.c b/source/blender/blenlib/intern/buffer.c
new file mode 100644
index 00000000000..aac3a3bc3f3
--- /dev/null
+++ b/source/blender/blenlib/intern/buffer.c
@@ -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 *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_buffer.h"
+#include "BLI_utildefines.h"
+
+#include <string.h>
+
+static void *buffer_alloc(BLI_Buffer *buffer, int len)
+{
+ return ((buffer->flag & BLI_BUFFER_USE_CALLOC) ?
+ MEM_callocN : MEM_mallocN)
+ (buffer->elem_size * len, "BLI_Buffer.data");
+}
+
+static void *buffer_realloc(BLI_Buffer *buffer, int len)
+{
+ return ((buffer->flag & BLI_BUFFER_USE_CALLOC) ?
+ MEM_recallocN : MEM_reallocN)
+ (buffer->data, (buffer->elem_size * len));
+}
+
+void BLI_buffer_resize(BLI_Buffer *buffer, int new_count)
+{
+ if (new_count > buffer->alloc_count) {
+ if (buffer->flag & BLI_BUFFER_USE_STATIC) {
+ void *orig = buffer->data;
+
+ buffer->data = buffer_alloc(buffer, new_count);
+ memcpy(buffer->data, orig, buffer->elem_size * buffer->count);
+ buffer->alloc_count = new_count;
+ buffer->flag &= ~BLI_BUFFER_USE_STATIC;
+ }
+ else {
+ if (buffer->alloc_count && (new_count < buffer->alloc_count * 2)) {
+ buffer->alloc_count *= 2;
+ }
+ else {
+ 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->count = new_count;
+}
+
+/* callers use BLI_buffer_free */
+void _bli_buffer_free(BLI_Buffer *buffer)
+{
+ if ((buffer->flag & BLI_BUFFER_USE_STATIC) == 0) {
+ if (buffer->data) {
+ MEM_freeN(buffer->data);
+ }
+ }
+ memset(buffer, 0, sizeof(*buffer));
+}
diff --git a/source/blender/blenlib/intern/endian_switch.c b/source/blender/blenlib/intern/endian_switch.c
index b9b18136863..e3ed88b6f8d 100644
--- a/source/blender/blenlib/intern/endian_switch.c
+++ b/source/blender/blenlib/intern/endian_switch.c
@@ -24,7 +24,7 @@
* \ingroup bli
*/
-#include "BLO_sys_types.h"
+#include "MEM_sys_types.h"
#include "BLI_utildefines.h"
#include "BLI_endian_switch.h"
diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c
index 883cdfde426..8b3cfd07ee9 100644
--- a/source/blender/blenlib/intern/fileops.c
+++ b/source/blender/blenlib/intern/fileops.c
@@ -63,7 +63,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BLO_sys_types.h" // for intptr_t support
+#include "MEM_sys_types.h" // for intptr_t support
/* gzip the file in from and write it to "to".
@@ -111,7 +111,7 @@ int BLI_file_gzip(const char *from, const char *to)
return rval;
}
-/* gzip the file in from_file and write it to memery to_mem, at most size bytes.
+/* gzip the file in from_file and write it to memory to_mem, at most size bytes.
* return the unziped size
*/
char *BLI_file_ungzip_to_mem(const char *from_file, int *size_r)
@@ -138,7 +138,9 @@ char *BLI_file_ungzip_to_mem(const char *from_file, int *size_r)
if (readsize > 0) {
size += readsize;
}
- else break;
+ else {
+ break;
+ }
}
gzclose(gzfile);
@@ -155,37 +157,43 @@ char *BLI_file_ungzip_to_mem(const char *from_file, int *size_r)
return mem;
}
-
-/* return 1 when file can be written */
-int BLI_file_is_writable(const char *filename)
+/**
+ * Returns true if the file with the specified name can be written.
+ * This implementation uses access(2), which makes the check according
+ * to the real UID and GID of the process, not its effective UID and GID.
+ * This shouldn't matter for Blender, which is not going to run privileged
+ * anyway.
+ */
+bool BLI_file_is_writable(const char *filename)
{
- int file;
-
- /* first try to open without creating */
- file = BLI_open(filename, O_BINARY | O_RDWR, 0666);
-
- if (file < 0) {
- /* now try to open and create. a test without actually
- * creating a file would be nice, but how? */
- file = BLI_open(filename, O_BINARY | O_RDWR | O_CREAT, 0666);
-
- if (file < 0) {
- return 0;
- }
- else {
- /* success, delete the file we create */
- close(file);
- BLI_delete(filename, 0, 0);
- return 1;
- }
+ bool writable;
+ if (BLI_access(filename, W_OK) == 0) {
+ /* file exists and I can write to it */
+ writable = true;
+ }
+ else if (errno != ENOENT) {
+ /* most likely file or containing directory cannot be accessed */
+ writable = false;
}
else {
- close(file);
- return 1;
+ /* file doesn't exist -- check I can create it in parent directory */
+ char parent[FILE_MAX];
+ BLI_split_dirfile(filename, parent, NULL, sizeof(parent), 0);
+#ifdef WIN32
+ /* windows does not have X_OK */
+ writable = BLI_access(parent, W_OK) == 0;
+#else
+ writable = BLI_access(parent, X_OK | W_OK) == 0;
+#endif
}
+ return writable;
}
-int BLI_file_touch(const char *file)
+/**
+ * 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)
+ */
+bool BLI_file_touch(const char *file)
{
FILE *f = BLI_fopen(file, "r+b");
if (f != NULL) {
@@ -198,9 +206,9 @@ int BLI_file_touch(const char *file)
}
if (f) {
fclose(f);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
#ifdef WIN32
@@ -255,7 +263,12 @@ int BLI_open(const char *filename, int oflag, int pmode)
return uopen(filename, oflag, pmode);
}
-int BLI_delete(const char *file, int dir, int recursive)
+int BLI_access(const char *filename, int mode)
+{
+ return uaccess(filename, mode);
+}
+
+int BLI_delete(const char *file, bool dir, bool recursive)
{
int err;
@@ -279,11 +292,13 @@ int BLI_delete(const char *file, int dir, int recursive)
return err;
}
+/* Not used anywhere! */
+#if 0
int BLI_move(const char *file, const char *to)
{
int err;
- /* windows doesn't support moveing to a directory
+ /* windows doesn't support moving to a directory
* it has to be 'mv filename filename' and not
* 'mv filename destdir' */
@@ -308,7 +323,7 @@ int BLI_move(const char *file, const char *to)
return err;
}
-
+#endif
int BLI_copy(const char *file, const char *to)
{
@@ -391,15 +406,16 @@ int BLI_rename(const char *from, const char *to)
/* make sure the filenames are different (case insensitive) before removing */
if (BLI_exists(to) && BLI_strcasecmp(from, to))
- if (BLI_delete(to, 0, 0)) return 1;
+ if (BLI_delete(to, false, false)) return 1;
return urename(from, to);
}
#else /* The UNIX world */
+/* results from recursive_operation and its callbacks */
enum {
- /* operation succeeded succeeded */
+ /* operation succeeded */
RecursiveOp_Callback_OK = 0,
/* operation requested not to perform recursive digging for current path */
@@ -407,7 +423,7 @@ enum {
/* error occured in callback and recursive walking should stop immediately */
RecursiveOp_Callback_Error = 2
-} recuresiveOp_Callback_Result;
+};
typedef int (*RecursiveOp_Callback)(const char *from, const char *to);
@@ -434,120 +450,122 @@ static char *strip_last_slash(const char *dir)
return result;
}
-static int recursive_operation(const char *startfrom, const char *startto, RecursiveOp_Callback callback_dir_pre,
+
+
+/**
+ * Scans \a startfrom, generating a corresponding destination name for each item found by
+ * prefixing it with startto, recursively scanning subdirectories, and invoking the specified
+ * callbacks for files and subdirectories found as appropriate.
+ *
+ * \param startfrom Top-level source path.
+ * \param startto Top-level destination path.
+ * \param callback_dir_pre Optional, to be invoked before entering a subdirectory, can return
+ * RecursiveOp_Callback_StopRecurs to skip the subdirectory.
+ * \param callback_file Optional, to be invoked on each file found.
+ * \param callback_dir_post optional, to be invoked after leaving a subdirectory.
+ * \return
+ */
+static int recursive_operation(const char *startfrom, const char *startto,
+ RecursiveOp_Callback callback_dir_pre,
RecursiveOp_Callback callback_file, RecursiveOp_Callback callback_dir_post)
{
- struct dirent **dirlist;
struct stat st;
char *from = NULL, *to = NULL;
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;
- /* ensure there's no trailing slash in file path */
- from = strip_last_slash(startfrom);
- if (startto)
- to = strip_last_slash(startto);
+ do { /* once */
+ /* ensure there's no trailing slash in file path */
+ from = strip_last_slash(startfrom);
+ if (startto)
+ to = strip_last_slash(startto);
- ret = lstat(from, &st);
- if (ret < 0) {
- /* source wasn't found, nothing to operate with */
- return ret;
- }
-
- if (!S_ISDIR(st.st_mode)) {
- /* source isn't a directory, can't do recursive walking for it,
- * so just call file callback and leave */
- if (callback_file) {
- ret = callback_file(from, to);
+ ret = lstat(from, &st);
+ if (ret < 0)
+ /* source wasn't found, nothing to operate with */
+ break;
- if (ret != RecursiveOp_Callback_OK)
- ret = -1;
+ if (!S_ISDIR(st.st_mode)) {
+ /* source isn't a directory, can't do recursive walking for it,
+ * so just call file callback and leave */
+ if (callback_file != NULL) {
+ ret = callback_file(from, to);
+ if (ret != RecursiveOp_Callback_OK)
+ ret = -1;
+ }
+ break;
}
- MEM_freeN(from);
- if (to) MEM_freeN(to);
-
- return ret;
- }
-
-
- n = scandir(startfrom, &dirlist, 0, alphasort);
- if (n < 0) {
- /* error opening directory for listing */
- perror("scandir");
-
- MEM_freeN(from);
- if (to) MEM_freeN(to);
-
- return -1;
- }
-
- if (callback_dir_pre) {
- /* call pre-recursive walking directory callback */
- ret = callback_dir_pre(from, to);
-
- if (ret != RecursiveOp_Callback_OK) {
- MEM_freeN(from);
- if (to) free(to);
+ n = scandir(startfrom, &dirlist, NULL, alphasort);
+ if (n < 0) {
+ /* error opening directory for listing */
+ perror("scandir");
+ ret = -1;
+ break;
+ }
- if (ret == RecursiveOp_Callback_StopRecurs) {
- /* callback requested not to perform recursive walking, not an error */
- return 0;
+ if (callback_dir_pre != NULL) {
+ ret = callback_dir_pre(from, to);
+ if (ret != RecursiveOp_Callback_OK) {
+ if (ret == RecursiveOp_Callback_StopRecurs)
+ /* callback requested not to perform recursive walking, not an error */
+ ret = 0;
+ else
+ ret = -1;
+ break;
}
-
- return -1;
}
- }
- for (i = 0; i < n; i++) {
- struct dirent *dirent = dirlist[i];
+ for (i = 0; i < n; i++) {
+ const struct dirent * const dirent = dirlist[i];
- if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..")) {
- free(dirent);
- continue;
- }
+ if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, ".."))
+ continue;
- join_dirfile_alloc(&from_path, &from_alloc_len, from, dirent->d_name);
+ join_dirfile_alloc(&from_path, &from_alloc_len, from, dirent->d_name);
+ if (to)
+ join_dirfile_alloc(&to_path, &to_alloc_len, to, dirent->d_name);
- if (to)
- join_dirfile_alloc(&to_path, &to_alloc_len, to, dirent->d_name);
+ if (dirent->d_type == DT_DIR) {
+ /* recursively dig into a subfolder */
+ ret = recursive_operation(from_path, to_path, callback_dir_pre, callback_file, callback_dir_post);
+ }
+ else if (callback_file != NULL) {
+ ret = callback_file(from_path, to_path);
+ if (ret != RecursiveOp_Callback_OK)
+ ret = -1;
+ }
- if (dirent->d_type == DT_DIR) {
- /* recursively dig into a folder */
- ret = recursive_operation(from_path, to_path, callback_dir_pre, callback_file, callback_dir_post);
+ if (ret != 0)
+ break;
}
- else if (callback_file) {
- /* call file callback for current path */
- ret = callback_file(from_path, to_path);
- if (ret != RecursiveOp_Callback_OK)
- ret = -1;
- }
-
- if (ret != 0) {
- while (i < n) {
- free(dirlist[i++]);
- }
+ if (ret != 0)
break;
- }
- }
-
- free(dirlist);
- if (ret == 0) {
- if (callback_dir_post) {
- /* call post-recursive directory callback */
+ if (callback_dir_post != NULL) {
ret = callback_dir_post(from, to);
if (ret != RecursiveOp_Callback_OK)
ret = -1;
}
}
+ while (false);
- if (from_path) MEM_freeN(from_path);
- if (to_path) MEM_freeN(to_path);
-
- MEM_freeN(from);
- if (to) MEM_freeN(to);
+ if (dirlist != NULL) {
+ for (i = 0; i < n; i++) {
+ free(dirlist[i]);
+ }
+ free(dirlist);
+ }
+ if (from_path != NULL)
+ MEM_freeN(from_path);
+ if (to_path != NULL)
+ MEM_freeN(to_path);
+ if (from != NULL)
+ MEM_freeN(from);
+ if (to != NULL)
+ MEM_freeN(to);
return ret;
}
@@ -589,7 +607,17 @@ int BLI_open(const char *filename, int oflag, int pmode)
return open(filename, oflag, pmode);
}
-int BLI_delete(const char *file, int dir, int recursive)
+int BLI_access(const char *filename, int mode)
+{
+ return access(filename, mode);
+}
+
+
+/**
+ * Deletes the specified file or directory (depending on dir), optionally
+ * doing recursive delete of directory contents.
+ */
+int BLI_delete(const char *file, bool dir, bool recursive)
{
if (strchr(file, '"')) {
printf("Error: not deleted file %s because of quote!\n", file);
@@ -608,20 +636,26 @@ int BLI_delete(const char *file, int dir, int recursive)
return -1;
}
-static int check_the_same(const char *path_a, const char *path_b)
+/**
+ * Do the two paths denote the same filesystem object?
+ */
+static bool check_the_same(const char *path_a, const char *path_b)
{
struct stat st_a, st_b;
if (lstat(path_a, &st_a))
- return 0;
+ return false;
if (lstat(path_b, &st_b))
- return 0;
+ return false;
return st_a.st_dev == st_b.st_dev && st_a.st_ino == st_b.st_ino;
}
-static int set_permissions(const char *file, struct stat *st)
+/**
+ * Sets the mode and ownership of file to the values from st.
+ */
+static int set_permissions(const char *file, const struct stat *st)
{
if (chown(file, st->st_uid, st->st_gid)) {
perror("chown");
@@ -769,6 +803,8 @@ static int copy_single_file(const char *from, const char *to)
return RecursiveOp_Callback_OK;
}
+/* Not used anywhere! */
+#if 0
static int move_callback_pre(const char *from, const char *to)
{
int ret = rename(from, to);
@@ -789,16 +825,19 @@ static int move_single_file(const char *from, const char *to)
return RecursiveOp_Callback_OK;
}
+/* if *file represents a directory, moves all its contents into *to, else renames
+ * file itself to *to. */
int BLI_move(const char *file, const char *to)
{
int ret = recursive_operation(file, to, move_callback_pre, move_single_file, NULL);
- if (ret) {
+ if (ret && ret != -1) {
return recursive_operation(file, NULL, NULL, delete_single_file, delete_callback_post);
}
return ret;
}
+#endif
static char *check_destination(const char *file, const char *to)
{
@@ -806,7 +845,8 @@ static char *check_destination(const char *file, const char *to)
if (!stat(to, &st)) {
if (S_ISDIR(st.st_mode)) {
- char *str, *filename, *path;
+ char *str, *path;
+ const char *filename;
size_t len = 0;
str = strip_last_slash(file);
@@ -875,7 +915,7 @@ void BLI_dir_create_recursive(const char *dirname)
BLI_strncpy(tmp, dirname, size);
- lslash = BLI_last_slash(tmp);
+ lslash = (char *)BLI_last_slash(tmp);
if (lslash) {
/* Split about the last slash and recurse */
*lslash = 0;
@@ -893,10 +933,9 @@ int BLI_rename(const char *from, const char *to)
if (!BLI_exists(from)) return 0;
if (BLI_exists(to))
- if (BLI_delete(to, 0, 0)) return 1;
+ if (BLI_delete(to, false, false)) return 1;
return rename(from, to);
}
#endif
-
diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c
index 0a87316aa81..24a8edae325 100644
--- a/source/blender/blenlib/intern/freetypefont.c
+++ b/source/blender/blenlib/intern/freetypefont.c
@@ -52,8 +52,6 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "BKE_font.h"
-
#include "DNA_vfont_types.h"
#include "DNA_packedFile_types.h"
#include "DNA_curve_types.h"
@@ -451,7 +449,9 @@ static int check_freetypefont(PackedFile *pf)
glyph_index = FT_Get_Char_Index(face, 'A');
err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);
- if (err) success = 0;
+ if (err) {
+ success = 0;
+ }
else {
glyph = face->glyph;
if (glyph->format == ft_glyph_format_outline) {
@@ -467,7 +467,14 @@ static int check_freetypefont(PackedFile *pf)
return success;
}
-
+/**
+ * Construct a new VFontData structure from
+ * Freetype font data in a PackedFile.
+ *
+ * \param pf The font data.
+ * \retval A new VFontData structure, or NULL
+ * if unable to load.
+ */
VFontData *BLI_vfontdata_from_freetypefont(PackedFile *pf)
{
VFontData *vfd = NULL;
diff --git a/source/blender/blenlib/intern/gsqueue.c b/source/blender/blenlib/intern/gsqueue.c
index d569534f2f3..7f158bc3efb 100644
--- a/source/blender/blenlib/intern/gsqueue.c
+++ b/source/blender/blenlib/intern/gsqueue.c
@@ -32,6 +32,8 @@
#include <string.h>
#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
#include "BLI_gsqueue.h"
typedef struct _GSQueueElem GSQueueElem;
@@ -45,6 +47,12 @@ struct _GSQueue {
int elem_size;
};
+/**
+ * Create a new GSQueue.
+ *
+ * \param elem_size The size of the structures in the queue.
+ * \retval The new queue
+ */
GSQueue *BLI_gsqueue_new(int elem_size)
{
GSQueue *gq = MEM_mallocN(sizeof(*gq), "gqueue_new");
@@ -54,11 +62,17 @@ GSQueue *BLI_gsqueue_new(int elem_size)
return gq;
}
-int BLI_gsqueue_is_empty(GSQueue *gq)
+/**
+ * Query if the queue is empty
+ */
+bool BLI_gsqueue_is_empty(GSQueue *gq)
{
return (gq->head == NULL);
}
+/**
+ * Query number elements in the queue
+ */
int BLI_gsqueue_size(GSQueue *gq)
{
GSQueueElem *elem;
@@ -70,10 +84,26 @@ int BLI_gsqueue_size(GSQueue *gq)
return size;
}
+/**
+ * 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)
+ */
void BLI_gsqueue_peek(GSQueue *gq, void *item_r)
{
memcpy(item_r, &gq->head[1], gq->elem_size);
}
+
+/**
+ * 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).
+ * Can be NULL if desired.
+ */
void BLI_gsqueue_pop(GSQueue *gq, void *item_r)
{
GSQueueElem *elem = gq->head;
@@ -87,6 +117,13 @@ void BLI_gsqueue_pop(GSQueue *gq, void *item_r)
if (item_r) memcpy(item_r, &elem[1], gq->elem_size);
MEM_freeN(elem);
}
+
+/**
+ * Push an element onto the tail of the queue.
+ *
+ * \param item A pointer to an appropriately
+ * sized structure (the size passed to BLI_gsqueue_new).
+ */
void BLI_gsqueue_push(GSQueue *gq, void *item)
{
GSQueueElem *elem;
@@ -107,6 +144,14 @@ void BLI_gsqueue_push(GSQueue *gq, void *item)
gq->tail = gq->tail->next = elem;
}
}
+
+/**
+ * Push an element back onto the head of the queue (so
+ * it would be returned from the next call to BLI_gsqueue_pop).
+ *
+ * \param item A pointer to an appropriately
+ * sized structure (the size passed to BLI_gsqueue_new).
+ */
void BLI_gsqueue_pushback(GSQueue *gq, void *item)
{
GSQueueElem *elem = MEM_mallocN(sizeof(*elem) + gq->elem_size, "gqueue_push");
@@ -121,6 +166,9 @@ void BLI_gsqueue_pushback(GSQueue *gq, void *item)
}
}
+/**
+ * Free the queue
+ */
void BLI_gsqueue_free(GSQueue *gq)
{
while (gq->head) {
diff --git a/source/blender/blenlib/intern/jitter.c b/source/blender/blenlib/intern/jitter.c
index 6203a98828b..3fe0ef158df 100644
--- a/source/blender/blenlib/intern/jitter.c
+++ b/source/blender/blenlib/intern/jitter.c
@@ -165,7 +165,7 @@ void BLI_jitter_init(float *jitarr, int num)
MEM_freeN(jit2);
- /* finally, move jittertab to be centered around (0,0) */
+ /* finally, move jittertab to be centered around (0, 0) */
for (i = 0; i < 2 * num; i += 2) {
jitarr[i] -= 0.5f;
jitarr[i + 1] -= 0.5f;
diff --git a/source/blender/blenlib/intern/lasso.c b/source/blender/blenlib/intern/lasso.c
index 5cd8bb813a1..aa08a780394 100644
--- a/source/blender/blenlib/intern/lasso.c
+++ b/source/blender/blenlib/intern/lasso.c
@@ -53,77 +53,44 @@ void BLI_lasso_boundbox(rcti *rect, const int mcords[][2], const short moves)
}
-int BLI_lasso_is_point_inside(const int mcords[][2], const short moves,
- const int sx, const int sy,
- const int error_value)
+bool BLI_lasso_is_point_inside(const int mcords[][2], const short moves,
+ const int sx, const int sy,
+ const int error_value)
{
- /* we do the angle rule, define that all added angles should be about zero or (2 * PI) */
- float angletot = 0.0, dot, ang, cross, fp1[2], fp2[2];
- int a;
- const int *p1, *p2;
-
if (sx == error_value) {
- return 0;
+ return false;
}
-
- p1 = mcords[moves - 1];
- p2 = mcords[0];
-
- /* first vector */
- fp1[0] = (float)(p1[0] - sx);
- fp1[1] = (float)(p1[1] - sy);
- normalize_v2(fp1);
-
- for (a = 0; a < moves; a++) {
- /* second vector */
- fp2[0] = (float)(p2[0] - sx);
- fp2[1] = (float)(p2[1] - sy);
- normalize_v2(fp2);
-
- /* dot and angle and cross */
- dot = fp1[0] * fp2[0] + fp1[1] * fp2[1];
- ang = fabs(saacos(dot));
-
- cross = (float)((p1[1] - p2[1]) * (p1[0] - sx) + (p2[0] - p1[0]) * (p1[1] - sy));
-
- if (cross < 0.0f) angletot -= ang;
- else angletot += ang;
-
- /* circulate */
- fp1[0] = fp2[0]; fp1[1] = fp2[1];
- p1 = p2;
- p2 = mcords[a + 1];
+ else {
+ int pt[2] = {sx, sy};
+ return isect_point_poly_v2_int(pt, mcords, moves);
}
-
- if (fabsf(angletot) > 4.0f) return 1;
- return 0;
}
/* edge version for lasso select. we assume boundbox check was done */
-int BLI_lasso_is_edge_inside(const int mcords[][2], const short moves,
- int x0, int y0, int x1, int y1,
- const int error_value)
+bool BLI_lasso_is_edge_inside(const int mcords[][2], const short moves,
+ int x0, int y0, int x1, int y1,
+ const int error_value)
{
int v1[2], v2[2];
int a;
if (x0 == error_value || x1 == error_value) {
- return 0;
+ return false;
}
v1[0] = x0, v1[1] = y0;
v2[0] = x1, v2[1] = y1;
/* check points in lasso */
- if (BLI_lasso_is_point_inside(mcords, moves, v1[0], v1[1], error_value)) return 1;
- if (BLI_lasso_is_point_inside(mcords, moves, v2[0], v2[1], error_value)) return 1;
+ if (BLI_lasso_is_point_inside(mcords, moves, v1[0], v1[1], error_value)) return true;
+ if (BLI_lasso_is_point_inside(mcords, moves, v2[0], v2[1], error_value)) return true;
/* no points in lasso, so we have to intersect with lasso edge */
- if (isect_line_line_v2_int(mcords[0], mcords[moves - 1], v1, v2) > 0) return 1;
+ if (isect_line_line_v2_int(mcords[0], mcords[moves - 1], v1, v2) > 0) return true;
for (a = 0; a < moves - 1; a++) {
- if (isect_line_line_v2_int(mcords[a], mcords[a + 1], v1, v2) > 0) return 1;
+ if (isect_line_line_v2_int(mcords[a], mcords[a + 1], v1, v2) > 0) return true;
}
- return 0;
+ return false;
}
diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c
index 9f6f409c473..348efaf40a9 100644
--- a/source/blender/blenlib/intern/listbase.c
+++ b/source/blender/blenlib/intern/listbase.c
@@ -28,9 +28,10 @@
/** \file blender/blenlib/intern/listbase.c
* \ingroup bli
+ *
+ * Manipulations on ListBase structs
*/
-
#include <string.h>
#include <stdlib.h>
@@ -41,10 +42,11 @@
#include "BLI_listbase.h"
-
/* implementation */
-/* Ripped this from blender.c */
+/**
+ * moves the entire contents of \a src onto the end of \a dst.
+ */
void BLI_movelisttolist(ListBase *dst, ListBase *src)
{
if (src->first == NULL) return;
@@ -61,6 +63,9 @@ void BLI_movelisttolist(ListBase *dst, ListBase *src)
src->first = src->last = NULL;
}
+/**
+ * Prepends \a vlink (assumed to begin with a Link) onto listbase.
+ */
void BLI_addhead(ListBase *listbase, void *vlink)
{
Link *link = vlink;
@@ -77,6 +82,9 @@ void BLI_addhead(ListBase *listbase, void *vlink)
}
+/**
+ * Appends \a vlink (assumed to begin with a Link) onto listbase.
+ */
void BLI_addtail(ListBase *listbase, void *vlink)
{
Link *link = vlink;
@@ -93,6 +101,9 @@ void BLI_addtail(ListBase *listbase, void *vlink)
}
+/**
+ * Removes \a vlink from \a listbase. Assumes it is linked into there!
+ */
void BLI_remlink(ListBase *listbase, void *vlink)
{
Link *link = vlink;
@@ -107,18 +118,24 @@ void BLI_remlink(ListBase *listbase, void *vlink)
if (listbase->first == link) listbase->first = link->next;
}
-int BLI_remlink_safe(ListBase *listbase, void *vlink)
+/**
+ * Checks that \a vlink is linked into listbase, removing it from there if so.
+ */
+bool BLI_remlink_safe(ListBase *listbase, void *vlink)
{
if (BLI_findindex(listbase, vlink) != -1) {
BLI_remlink(listbase, vlink);
- return 1;
+ return true;
}
else {
- return 0;
+ return false;
}
}
+/**
+ * Removes \a vlink from listbase and disposes of it. Assumes it is linked into there!
+ */
void BLI_freelinkN(ListBase *listbase, void *vlink)
{
Link *link = vlink;
@@ -131,43 +148,11 @@ void BLI_freelinkN(ListBase *listbase, void *vlink)
}
-void BLI_insertlink(ListBase *listbase, void *vprevlink, void *vnewlink)
-{
- Link *prevlink = vprevlink;
- Link *newlink = vnewlink;
-
- /* newlink comes after prevlink */
- if (newlink == NULL) return;
- if (listbase == NULL) return;
-
- /* empty list */
- if (listbase->first == NULL) {
-
- listbase->first = newlink;
- listbase->last = newlink;
- return;
- }
-
- /* insert before first element */
- if (prevlink == NULL) {
- newlink->next = listbase->first;
- newlink->prev = NULL;
- newlink->next->prev = newlink;
- listbase->first = newlink;
- return;
- }
-
- /* at end of list */
- if (listbase->last == prevlink)
- listbase->last = newlink;
-
- newlink->next = prevlink->next;
- prevlink->next = newlink;
- if (newlink->next) newlink->next->prev = newlink;
- newlink->prev = prevlink;
-}
-
-/* This uses insertion sort, so NOT ok for large list */
+/**
+ * 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).
+ * This uses insertion sort, so NOT ok for large list.
+ */
void BLI_sortlist(ListBase *listbase, int (*cmp)(void *, void *))
{
Link *current = NULL;
@@ -193,6 +178,10 @@ void BLI_sortlist(ListBase *listbase, int (*cmp)(void *, void *))
}
}
+/**
+ * Inserts \a vnewlink immediately following \a vprevlink in \a listbase.
+ * Or, if \a vprevlink is NULL, puts \a vnewlink at the front of the list.
+ */
void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink)
{
Link *prevlink = vprevlink;
@@ -213,21 +202,28 @@ void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink)
if (prevlink == NULL) {
newlink->prev = NULL;
newlink->next = listbase->first;
- ((Link *)listbase->first)->prev = newlink;
+ newlink->next->prev = newlink;
listbase->first = newlink;
return;
}
/* at end of list */
- if (listbase->last == prevlink)
+ if (listbase->last == prevlink) {
listbase->last = newlink;
+ }
newlink->next = prevlink->next;
newlink->prev = prevlink;
prevlink->next = newlink;
- if (newlink->next) newlink->next->prev = newlink;
+ if (newlink->next) {
+ newlink->next->prev = newlink;
+ }
}
+/**
+ * Inserts \a vnewlink immediately preceding \a vnextlink in listbase.
+ * Or, if \a vnextlink is NULL, puts \a vnewlink at the end of the list.
+ */
void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink)
{
Link *nextlink = vnextlink;
@@ -254,16 +250,22 @@ void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink)
}
/* at beginning of list */
- if (listbase->first == nextlink)
+ if (listbase->first == nextlink) {
listbase->first = newlink;
+ }
newlink->next = nextlink;
newlink->prev = nextlink->prev;
nextlink->prev = newlink;
- if (newlink->prev) newlink->prev->next = newlink;
+ if (newlink->prev) {
+ newlink->prev->next = newlink;
+ }
}
+/**
+ * Removes and disposes of the entire contents of listbase using direct free(3).
+ */
void BLI_freelist(ListBase *listbase)
{
Link *link, *next;
@@ -282,6 +284,9 @@ void BLI_freelist(ListBase *listbase)
listbase->last = NULL;
}
+/**
+ * Removes and disposes of the entire contents of \a listbase using guardedalloc.
+ */
void BLI_freelistN(ListBase *listbase)
{
Link *link, *next;
@@ -300,6 +305,9 @@ void BLI_freelistN(ListBase *listbase)
}
+/**
+ * Returns the number of elements in \a listbase.
+ */
int BLI_countlist(const ListBase *listbase)
{
Link *link;
@@ -315,6 +323,9 @@ int BLI_countlist(const ListBase *listbase)
return count;
}
+/**
+ * Returns the nth element of \a listbase, numbering from 1.
+ */
void *BLI_findlink(const ListBase *listbase, int number)
{
Link *link = NULL;
@@ -330,6 +341,9 @@ void *BLI_findlink(const ListBase *listbase, int number)
return link;
}
+/**
+ * Returns the nth-last element of \a listbase, numbering from 1.
+ */
void *BLI_rfindlink(const ListBase *listbase, int number)
{
Link *link = NULL;
@@ -345,7 +359,10 @@ void *BLI_rfindlink(const ListBase *listbase, int number)
return link;
}
-int BLI_findindex(const ListBase *listbase, void *vlink)
+/**
+ * Returns the position of \a vlink within \a listbase, numbering from 1, or -1 if not found.
+ */
+int BLI_findindex(const ListBase *listbase, const void *vlink)
{
Link *link = NULL;
int number = 0;
@@ -365,6 +382,10 @@ int BLI_findindex(const ListBase *listbase, void *vlink)
return -1;
}
+/**
+ * Finds the first element of \a listbase which contains the null-terminated
+ * string \a id at the specified offset, returning NULL if not found.
+ */
void *BLI_findstring(const ListBase *listbase, const char *id, const int offset)
{
Link *link = NULL;
@@ -383,6 +404,10 @@ void *BLI_findstring(const ListBase *listbase, const char *id, const int offset)
return NULL;
}
/* same as above but find reverse */
+/**
+ * Finds the last element of \a listbase which contains the
+ * null-terminated string \a id at the specified offset, returning NULL if not found.
+ */
void *BLI_rfindstring(const ListBase *listbase, const char *id, const int offset)
{
Link *link = NULL;
@@ -401,6 +426,10 @@ void *BLI_rfindstring(const ListBase *listbase, const char *id, const int offset
return NULL;
}
+/**
+ * Finds the first element of \a listbase which contains a pointer to the
+ * null-terminated string \a id at the specified offset, returning NULL if not found.
+ */
void *BLI_findstring_ptr(const ListBase *listbase, const char *id, const int offset)
{
Link *link = NULL;
@@ -420,6 +449,10 @@ void *BLI_findstring_ptr(const ListBase *listbase, const char *id, const int off
return NULL;
}
/* same as above but find reverse */
+/**
+ * Finds the last element of \a listbase which contains a pointer to the
+ * null-terminated string \a id at the specified offset, returning NULL if not found.
+ */
void *BLI_rfindstring_ptr(const ListBase *listbase, const char *id, const int offset)
{
Link *link = NULL;
@@ -440,6 +473,8 @@ void *BLI_rfindstring_ptr(const ListBase *listbase, const char *id, const int of
}
void *BLI_findptr(const ListBase *listbase, const void *ptr, const int offset)
+/* finds the first element of listbase which contains the specified pointer value
+at the specified offset, returning NULL if not found. */
{
Link *link = NULL;
const void *ptr_iter;
@@ -448,7 +483,7 @@ void *BLI_findptr(const ListBase *listbase, const void *ptr, const int offset)
for (link = listbase->first; link; link = link->next) {
/* exact copy of BLI_findstring(), except for this line */
- ptr_iter = *((const char **)(((const char *)link) + offset));
+ ptr_iter = *((const void **)(((const char *)link) + offset));
if (ptr == ptr_iter) {
return link;
@@ -459,6 +494,8 @@ void *BLI_findptr(const ListBase *listbase, const void *ptr, const int offset)
}
/* same as above but find reverse */
void *BLI_rfindptr(const ListBase *listbase, const void *ptr, const int offset)
+/* finds the last element of listbase which contains the specified pointer value
+at the specified offset, returning NULL if not found. */
{
Link *link = NULL;
const void *ptr_iter;
@@ -467,7 +504,7 @@ void *BLI_rfindptr(const ListBase *listbase, const void *ptr, const int offset)
for (link = listbase->last; link; link = link->prev) {
/* exact copy of BLI_rfindstring(), except for this line */
- ptr_iter = *((const char **)(((const char *)link) + offset));
+ ptr_iter = *((const void **)(((const char *)link) + offset));
if (ptr == ptr_iter) {
return link;
@@ -478,6 +515,8 @@ void *BLI_rfindptr(const ListBase *listbase, const void *ptr, const int offset)
}
int BLI_findstringindex(const ListBase *listbase, const char *id, const int offset)
+/* returns the 1-based index of the first element of listbase which contains the specified
+null-terminated string at the specified offset, or -1 if not found. */
{
Link *link = NULL;
const char *id_iter;
@@ -499,6 +538,7 @@ int BLI_findstringindex(const ListBase *listbase, const char *id, const int offs
}
void BLI_duplicatelist(ListBase *dst, const ListBase *src)
+/* sets dst to a duplicate of the entire contents of src. dst may be the same as src. */
{
struct Link *dst_link, *src_link;
diff --git a/source/blender/blenlib/intern/math_base.c b/source/blender/blenlib/intern/math_base.c
index 6bb238ac612..38d303e667a 100644
--- a/source/blender/blenlib/intern/math_base.c
+++ b/source/blender/blenlib/intern/math_base.c
@@ -57,7 +57,14 @@ double round(double x)
return copysign(y, x);
}
#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
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index b9866f9c6e6..8eb6561003b 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -175,6 +175,42 @@ MINLINE int max_ii(int a, int b)
return (b < a) ? a : b;
}
+MINLINE float min_fff(float a, float b, float c)
+{
+ return min_ff(min_ff(a, b), c);
+}
+MINLINE float max_fff(float a, float b, float c)
+{
+ return max_ff(max_ff(a, b), c);
+}
+
+MINLINE int min_iii(int a, int b, int c)
+{
+ return min_ii(min_ii(a, b), c);
+}
+MINLINE int max_iii(int a, int b, int c)
+{
+ return max_ii(max_ii(a, b), c);
+}
+
+MINLINE float min_ffff(float a, float b, float c, float d)
+{
+ return min_ff(min_fff(a, b, c), d);
+}
+MINLINE float max_ffff(float a, float b, float c, float d)
+{
+ return max_ff(max_fff(a, b, c), d);
+}
+
+MINLINE int min_iiii(int a, int b, int c, int d)
+{
+ return min_ii(min_iii(a, b, c), d);
+}
+MINLINE int max_iiii(int a, int b, int c, int d)
+{
+ return max_ii(max_iii(a, b, c), d);
+}
+
MINLINE float signf(float f)
{
return (f < 0.f) ? -1.f : 1.f;
diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c
index 64851dbf12c..07cd85c4107 100644
--- a/source/blender/blenlib/intern/math_color.c
+++ b/source/blender/blenlib/intern/math_color.c
@@ -266,8 +266,8 @@ void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
void rgb_to_hsl(float r, float g, float b, float *lh, float *ls, float *ll)
{
- float cmax = MAX3(r, g, b);
- float cmin = MIN3(r, g, b);
+ const float cmax = max_fff(r, g, b);
+ const float cmin = min_fff(r, g, b);
float h, s, l = (cmax + cmin) / 2.0f;
if (cmax == cmin) {
diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c
index 4c8bd43ef73..e9a1c0abc38 100644
--- a/source/blender/blenlib/intern/math_color_inline.c
+++ b/source/blender/blenlib/intern/math_color_inline.c
@@ -149,31 +149,6 @@ MINLINE void linearrgb_to_srgb_ushort4(unsigned short srgb[4], const float linea
srgb[3] = FTOUSHORT(linear[3]);
}
-MINLINE void linearrgb_to_srgb_ushort4_predivide(unsigned short srgb[4], const float linear[4])
-{
- float alpha, inv_alpha, t;
- int i;
-
- if (linear[3] == 1.0f || linear[3] == 0.0f) {
- linearrgb_to_srgb_ushort4(srgb, linear);
- return;
- }
-
- alpha = linear[3];
- inv_alpha = 1.0f / alpha;
-
- for (i = 0; i < 3; ++i) {
- t = linear[i] * inv_alpha;
- srgb[i] = (t <= 1.0f) ?
- /* warning - converts: float -> short -> float -> short */
- (unsigned short) (to_srgb_table_lookup(t) * alpha) :
- /* if FTOUSHORT was an inline function this could be done less confusingly */
- ((t = linearrgb_to_srgb(t) * alpha), FTOUSHORT(t));
- }
-
- srgb[3] = FTOUSHORT(linear[3]);
-}
-
MINLINE void srgb_to_linearrgb_uchar4(float linear[4], const unsigned char srgb[4])
{
linear[0] = BLI_color_from_srgb_table[srgb[0]];
@@ -199,7 +174,8 @@ MINLINE void srgb_to_linearrgb_uchar4_predivide(float linear[4], const unsigned
}
/* color macros for themes */
-#define rgba_char_args_set_fl(col, r, g, b, a) rgba_char_args_set(col, r * 255, g * 255, b * 255, a * 255)
+#define rgba_char_args_set_fl(col, r, g, b, a) \
+ rgba_char_args_set(col, (r) * 255, (g) * 255, (b) * 255, (a) * 255)
MINLINE void rgba_char_args_set(char col[4], const char r, const char g, const char b, const char a)
{
@@ -293,4 +269,72 @@ MINLINE int compare_rgb_uchar(const unsigned char col_a[3], const unsigned char
return 0;
}
+/**************** Alpha Transformations *****************/
+
+MINLINE void premul_to_straight_v4_v4(float straight[4], const float premul[4])
+{
+ if (premul[3] == 0.0f || premul[3] == 1.0f) {
+ straight[0] = premul[0];
+ straight[1] = premul[1];
+ straight[2] = premul[2];
+ straight[3] = premul[3];
+ }
+ else {
+ float alpha_inv = 1.0f / premul[3];
+ straight[0] = premul[0] * alpha_inv;
+ straight[1] = premul[1] * alpha_inv;
+ straight[2] = premul[2] * alpha_inv;
+ straight[3] = premul[3];
+ }
+}
+
+MINLINE void premul_to_straight_v4(float color[4])
+{
+ premul_to_straight_v4_v4(color, color);
+}
+
+MINLINE void straight_to_premul_v4_v4(float premul[4], const float straight[4])
+{
+ float alpha = straight[3];
+ premul[0] = straight[0] * alpha;
+ premul[1] = straight[1] * alpha;
+ premul[2] = straight[2] * alpha;
+ premul[3] = straight[3];
+}
+
+MINLINE void straight_to_premul_v4(float color[4])
+{
+ straight_to_premul_v4_v4(color, color);
+}
+
+MINLINE void straight_uchar_to_premul_float(float result[4], const unsigned char color[4])
+{
+ float alpha = color[3] / 255.0f;
+ float fac = alpha / 255.0f;
+
+ result[0] = color[0] * fac;
+ result[1] = color[1] * fac;
+ result[2] = color[2] * fac;
+ result[3] = alpha;
+}
+
+MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float color[4])
+{
+ if (color[3] == 0.0f || color[3] == 1.0f) {
+ result[0] = FTOCHAR(color[0]);
+ result[1] = FTOCHAR(color[1]);
+ result[2] = FTOCHAR(color[2]);
+ result[3] = FTOCHAR(color[3]);
+ }
+ else {
+ float alpha_inv = 1.0f / color[3];
+
+ /* hopefully this would be optimized */
+ result[0] = FTOCHAR(color[0] * alpha_inv);
+ result[1] = FTOCHAR(color[1] * alpha_inv);
+ result[2] = FTOCHAR(color[2] * alpha_inv);
+ result[3] = FTOCHAR(color[3]);
+ }
+}
+
#endif /* __MATH_COLOR_INLINE_C__ */
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 931025606db..579f397f833 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -39,9 +39,9 @@
void cent_tri_v3(float cent[3], const float v1[3], const float v2[3], const float v3[3])
{
- cent[0] = 0.33333f * (v1[0] + v2[0] + v3[0]);
- cent[1] = 0.33333f * (v1[1] + v2[1] + v3[1]);
- cent[2] = 0.33333f * (v1[2] + v2[2] + v3[2]);
+ cent[0] = (v1[0] + v2[0] + v3[0]) / 3.0f;
+ cent[1] = (v1[1] + v2[1] + v3[1]) / 3.0f;
+ cent[2] = (v1[2] + v2[2] + v3[2]) / 3.0f;
}
void cent_quad_v3(float cent[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
@@ -106,12 +106,12 @@ float area_quad_v3(const float v1[3], const float v2[3], const float v3[3], cons
sub_v3_v3v3(vec1, v2, v1);
sub_v3_v3v3(vec2, v4, v1);
cross_v3_v3v3(n, vec1, vec2);
- len = normalize_v3(n);
+ len = len_v3(n);
sub_v3_v3v3(vec1, v4, v3);
sub_v3_v3v3(vec2, v2, v3);
cross_v3_v3v3(n, vec1, vec2);
- len += normalize_v3(n);
+ len += len_v3(n);
return (len / 2.0f);
}
@@ -119,45 +119,68 @@ float area_quad_v3(const float v1[3], const float v2[3], const float v3[3], cons
/* Triangles */
float area_tri_v3(const float v1[3], const float v2[3], const float v3[3])
{
- float len, vec1[3], vec2[3], n[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);
- len = normalize_v3(n);
- return (len / 2.0f);
+ return len_v3(n) / 2.0f;
+}
+
+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];
+
+ sub_v3_v3v3(vec1, v3, v2);
+ sub_v3_v3v3(vec2, v1, v2);
+ cross_v3_v3v3(n, vec1, vec2);
+ area = len_v3(n) / 2.0f;
+
+ /* negate area for flipped triangles */
+ if (dot_v3v3(n, normal) < 0.0f)
+ area = -area;
+
+ return area;
}
float area_poly_v3(int nr, float verts[][3], const float normal[3])
{
- float x, y, z, area, max;
- float *cur, *prev;
- int a, px = 0, py = 1;
+ int a, px, py;
+ const float max = axis_dominant_v3_max(&px, &py, normal);
+ float area;
+ float *co_curr, *co_prev;
- /* first: find dominant axis: 0==X, 1==Y, 2==Z
- * don't use 'axis_dominant_v3()' because we need max axis too */
- x = fabsf(normal[0]);
- y = fabsf(normal[1]);
- z = fabsf(normal[2]);
- max = MAX3(x, y, z);
- if (max == y) py = 2;
- else if (max == x) {
- px = 1;
- py = 2;
+ /* The Trapezium Area Rule */
+ co_prev = verts[nr - 1];
+ co_curr = verts[0];
+ area = 0.0f;
+ for (a = 0; a < nr; a++) {
+ area += (co_curr[px] - co_prev[px]) * (co_curr[py] + co_prev[py]);
+ co_prev = verts[a];
+ co_curr = verts[a + 1];
}
+ return fabsf(0.5f * area / max);
+}
+
+float area_poly_v2(int nr, float verts[][2])
+{
+ int a;
+ float area;
+ float *co_curr, *co_prev;
+
/* The Trapezium Area Rule */
- prev = verts[nr - 1];
- cur = verts[0];
- area = 0;
+ co_prev = verts[nr - 1];
+ co_curr = verts[0];
+ area = 0.0f;
for (a = 0; a < nr; a++) {
- area += (cur[px] - prev[px]) * (cur[py] + prev[py]);
- prev = verts[a];
- cur = verts[a + 1];
+ area += (co_curr[0] - co_prev[0]) * (co_curr[1] + co_prev[1]);
+ co_prev = verts[a];
+ co_curr = verts[a + 1];
}
- return fabsf(0.5f * area / max);
+ return fabsf(0.5f * area);
}
/********************************* Distance **********************************/
@@ -296,6 +319,97 @@ float dist_to_line_segment_v3(const float v1[3], const float v2[3], const float
return len_v3v3(closest, v1);
}
+float dist_to_line_v3(const float v1[3], const float v2[3], const float v3[3])
+{
+ float closest[3];
+
+ closest_to_line_v3(closest, v1, v2, v3);
+
+ return len_v3v3(closest, v1);
+}
+
+/* Adapted from "Real-Time Collision Detection" by Christer Ericson,
+ * published by Morgan Kaufmann Publishers, copyright 2005 Elsevier Inc.
+ *
+ * Set 'r' to the point in triangle (a, b, c) closest to point 'p' */
+void closest_on_tri_to_point_v3(float r[3], const float p[3],
+ const float a[3], const float b[3], const float c[3])
+{
+ float ab[3], ac[3], ap[3], d1, d2;
+ float bp[3], d3, d4, vc, cp[3], d5, d6, vb, va;
+ float denom, v, w;
+
+ /* Check if P in vertex region outside A */
+ sub_v3_v3v3(ab, b, a);
+ sub_v3_v3v3(ac, c, a);
+ sub_v3_v3v3(ap, p, a);
+ d1 = dot_v3v3(ab, ap);
+ d2 = dot_v3v3(ac, ap);
+ if (d1 <= 0.0f && d2 <= 0.0f) {
+ /* barycentric coordinates (1,0,0) */
+ copy_v3_v3(r, a);
+ return;
+ }
+
+ /* Check if P in vertex region outside B */
+ sub_v3_v3v3(bp, p, b);
+ d3 = dot_v3v3(ab, bp);
+ d4 = dot_v3v3(ac, bp);
+ if (d3 >= 0.0f && d4 <= d3) {
+ /* barycentric coordinates (0,1,0) */
+ copy_v3_v3(r, b);
+ return;
+ }
+ /* Check if P in edge region of AB, if so return projection of P onto AB */
+ vc = d1 * d4 - d3 * d2;
+ if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) {
+ float v = d1 / (d1 - d3);
+ /* barycentric coordinates (1-v,v,0) */
+ madd_v3_v3v3fl(r, a, ab, v);
+ return;
+ }
+ /* Check if P in vertex region outside C */
+ sub_v3_v3v3(cp, p, c);
+ d5 = dot_v3v3(ab, cp);
+ d6 = dot_v3v3(ac, cp);
+ if (d6 >= 0.0f && d5 <= d6) {
+ /* barycentric coordinates (0,0,1) */
+ copy_v3_v3(r, c);
+ return;
+ }
+ /* Check if P in edge region of AC, if so return projection of P onto AC */
+ vb = d5 * d2 - d1 * d6;
+ if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) {
+ float w = d2 / (d2 - d6);
+ /* barycentric coordinates (1-w,0,w) */
+ madd_v3_v3v3fl(r, a, ac, w);
+ return;
+ }
+ /* Check if P in edge region of BC, if so return projection of P onto BC */
+ va = d3 * d6 - d5 * d4;
+ if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) {
+ float w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
+ /* barycentric coordinates (0,1-w,w) */
+ sub_v3_v3v3(r, c, b);
+ mul_v3_fl(r, w);
+ add_v3_v3(r, b);
+ return;
+ }
+
+ /* P inside face region. Compute Q through its barycentric coordinates (u,v,w) */
+ denom = 1.0f / (va + vb + vc);
+ v = vb * denom;
+ w = vc * denom;
+
+ /* = u*a + v*b + w*c, u = va * denom = 1.0f - v - w */
+ /* ac * w */
+ mul_v3_fl(ac, w);
+ /* a + ab * v */
+ madd_v3_v3v3fl(r, a, ab, v);
+ /* a + ab * v + ac * w */
+ add_v3_v3(r, ac);
+}
+
/******************************* Intersection ********************************/
/* intersect Line-Line, shorts */
@@ -614,6 +728,86 @@ static short IsectLLPt2Df(const float x0, const float y0, const float x1, const
return 1;
}
+/* point in polygon (keep float and int versions in sync) */
+bool isect_point_poly_v2(const float pt[2], const float verts[][2], const int nr)
+{
+ /* we do the angle rule, define that all added angles should be about zero or (2 * PI) */
+ float angletot = 0.0;
+ float fp1[2], fp2[2];
+ int i;
+ const float *p1, *p2;
+
+ p1 = verts[nr - 1];
+ p2 = verts[0];
+
+ /* first vector */
+ fp1[0] = (float)(p1[0] - pt[0]);
+ fp1[1] = (float)(p1[1] - pt[1]);
+ normalize_v2(fp1);
+
+ for (i = 0; i < nr; i++) {
+ float dot, ang, cross;
+ /* second vector */
+ fp2[0] = (float)(p2[0] - pt[0]);
+ fp2[1] = (float)(p2[1] - pt[1]);
+ normalize_v2(fp2);
+
+ /* dot and angle and cross */
+ dot = dot_v2v2(fp1, fp2);
+ ang = fabsf(saacos(dot));
+ cross = (float)((p1[1] - p2[1]) * (p1[0] - pt[0]) + (p2[0] - p1[0]) * (p1[1] - pt[1]));
+
+ if (cross < 0.0f) angletot -= ang;
+ else angletot += ang;
+
+ /* circulate */
+ copy_v2_v2(fp1, fp2);
+ p1 = p2;
+ p2 = verts[i + 1];
+ }
+
+ return (fabsf(angletot) > 4.0f);
+}
+bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const int nr)
+{
+ /* we do the angle rule, define that all added angles should be about zero or (2 * PI) */
+ float angletot = 0.0;
+ float fp1[2], fp2[2];
+ int i;
+ const int *p1, *p2;
+
+ p1 = verts[nr - 1];
+ p2 = verts[0];
+
+ /* first vector */
+ fp1[0] = (float)(p1[0] - pt[0]);
+ fp1[1] = (float)(p1[1] - pt[1]);
+ normalize_v2(fp1);
+
+ for (i = 0; i < nr; i++) {
+ float dot, ang, cross;
+ /* second vector */
+ fp2[0] = (float)(p2[0] - pt[0]);
+ fp2[1] = (float)(p2[1] - pt[1]);
+ normalize_v2(fp2);
+
+ /* dot and angle and cross */
+ dot = dot_v2v2(fp1, fp2);
+ ang = fabsf(saacos(dot));
+ cross = (float)((p1[1] - p2[1]) * (p1[0] - pt[0]) + (p2[0] - p1[0]) * (p1[1] - pt[1]));
+
+ if (cross < 0.0f) angletot -= ang;
+ else angletot += ang;
+
+ /* circulate */
+ copy_v2_v2(fp1, fp2);
+ p1 = p2;
+ p2 = verts[i + 1];
+ }
+
+ return (fabsf(angletot) > 4.0f);
+}
+
/* point in tri */
/* only single direction */
@@ -893,7 +1087,7 @@ int isect_ray_tri_threshold_v3(const float p1[3], const float d[3],
*/
int 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], const short no_flip)
+ const float plane_co[3], const float plane_no[3], const bool no_flip)
{
float l_vec[3]; /* l1 -> l2 normalized vector */
float p_no[3]; /* 'plane_no' normalized */
@@ -1037,7 +1231,7 @@ int isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const flo
if (t0 > 1.0f || t1 < 0.0f) return 0;
- /* clamp to [0,1] */
+ /* clamp to [0, 1] */
CLAMP(t0, 0.0f, 1.0f);
CLAMP(t1, 0.0f, 1.0f);
@@ -1157,10 +1351,10 @@ int isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const flo
}
/*e3*/
- /* sub_v3_v3v3(bv,v0,p1); */ /* UNUSED */
- /* elen2 = dot_v3v3(e1,e1); */ /* UNUSED */
- /* edotv = dot_v3v3(e1,vel); */ /* UNUSED */
- /* edotbv = dot_v3v3(e1,bv); */ /* UNUSED */
+ /* sub_v3_v3v3(bv, v0, p1); */ /* UNUSED */
+ /* elen2 = dot_v3v3(e1, e1); */ /* UNUSED */
+ /* edotv = dot_v3v3(e1, vel); */ /* UNUSED */
+ /* edotbv = dot_v3v3(e1, bv); */ /* UNUSED */
sub_v3_v3v3(bv, v1, p1);
elen2 = dot_v3v3(e3, e3);
@@ -1195,13 +1389,13 @@ int isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3]
int a0 = axis, a1 = (axis + 1) % 3, a2 = (axis + 2) % 3;
#if 0
- return isect_line_tri_v3(p1,p2,v0,v1,v2,lambda);
+ return isect_line_tri_v3(p1, p2, v0, v1, v2, lambda);
/* first a simple bounding box test */
- if (MIN3(v0[a1],v1[a1],v2[a1]) > p1[a1]) return 0;
- if (MIN3(v0[a2],v1[a2],v2[a2]) > p1[a2]) return 0;
- if (MAX3(v0[a1],v1[a1],v2[a1]) < p1[a1]) return 0;
- if (MAX3(v0[a2],v1[a2],v2[a2]) < p1[a2]) return 0;
+ if (min_fff(v0[a1], v1[a1], v2[a1]) > p1[a1]) return 0;
+ if (min_fff(v0[a2], v1[a2], v2[a2]) > p1[a2]) return 0;
+ if (max_fff(v0[a1], v1[a1], v2[a1]) < p1[a1]) return 0;
+ if (max_fff(v0[a2], v1[a2], v2[a2]) < p1[a2]) return 0;
/* then a full intersection test */
#endif
@@ -1415,8 +1609,8 @@ int isect_ray_aabb(const IsectRayAABBData *data, const float bb_min[3],
return TRUE;
}
-/* find closest point to p on line through l1,l2 and return lambda,
- * where (0 <= lambda <= 1) when cp is in the line segment l1,l2
+/* find closest point to p on line through (l1, l2) and return lambda,
+ * where (0 <= lambda <= 1) when cp is in the line segment (l1, l2)
*/
float closest_to_line_v3(float cp[3], const float p[3], const float l1[3], const float l2[3])
{
@@ -1702,9 +1896,9 @@ static int point_in_slice(const float p[3], const float v1[3], const float l1[3]
/*
* what is a slice ?
* some maths:
- * a line including l1,l2 and a point not on the line
+ * a line including (l1, l2) and a point not on the line
* define a subset of R3 delimited by planes parallel to the line and orthogonal
- * to the (point --> line) distance vector,one plane on the line one on the point,
+ * to the (point --> line) distance vector, one plane on the line one on the point,
* the room inside usually is rather small compared to R3 though still infinite
* useful for restricting (speeding up) searches
* e.g. all points of triangular prism are within the intersection of 3 'slices'
@@ -1735,7 +1929,7 @@ static int point_in_slice_as(float p[3], float origin[3], float normal[3])
return 1;
}
-/*mama (knowing the squared length of the normal)*/
+/*mama (knowing the squared length of the normal) */
static int point_in_slice_m(float p[3], float origin[3], float normal[3], float lns)
{
float h, rp[3];
@@ -1803,7 +1997,7 @@ int clip_line_plane(float p1[3], float p2[3], const float plane[4])
}
}
-void plot_line_v2v2i(const int p1[2], const int p2[2], int (*callback)(int, int, void *), void *userData)
+void plot_line_v2v2i(const int p1[2], const int p2[2], bool (*callback)(int, int, void *), void *userData)
{
int x1 = p1[0];
int y1 = p1[1];
@@ -1867,20 +2061,73 @@ void plot_line_v2v2i(const int p1[2], const int p2[2], int (*callback)(int, int,
}
}
-/****************************** Interpolation ********************************/
+/****************************** Axis Utils ********************************/
+
+/**
+ * \brief Normal to x,y matrix
+ *
+ * Creates a 3x3 matrix from a normal.
+ * This matrix can be applied to vectors so their 'z' axis runs along \a normal.
+ * In practice it means you can use x,y as 2d coords. \see
+ *
+ * \param r_mat The matrix to return.
+ * \param normal A unit length vector.
+ */
+bool axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3])
+{
+ float up[3] = {0.0f, 0.0f, 1.0f};
+ float axis[3];
+ float angle;
+
+ /* double check they are normalized */
+ BLI_ASSERT_UNIT_V3(normal);
+
+ cross_v3_v3v3(axis, normal, up);
+ angle = saacos(dot_v3v3(normal, up));
+
+ if (angle >= FLT_EPSILON) {
+ if (len_squared_v3(axis) < FLT_EPSILON) {
+ axis[0] = 0.0f;
+ axis[1] = 1.0f;
+ axis[2] = 0.0f;
+ }
+
+ axis_angle_to_mat3(r_mat, axis, angle);
+ return true;
+ }
+ else {
+ unit_m3(r_mat);
+ return false;
+ }
+}
/* get the 2 dominant axis values, 0==X, 1==Y, 2==Z */
-void axis_dominant_v3(int *axis_a, int *axis_b, const float axis[3])
+void axis_dominant_v3(int *r_axis_a, int *r_axis_b, const float axis[3])
{
const float xn = fabsf(axis[0]);
const float yn = fabsf(axis[1]);
const float zn = fabsf(axis[2]);
- if (zn >= xn && zn >= yn) { *axis_a = 0; *axis_b = 1; }
- else if (yn >= xn && yn >= zn) { *axis_a = 0; *axis_b = 2; }
- else { *axis_a = 1; *axis_b = 2; }
+ if (zn >= xn && zn >= yn) { *r_axis_a = 0; *r_axis_b = 1; }
+ else if (yn >= xn && yn >= zn) { *r_axis_a = 0; *r_axis_b = 2; }
+ else { *r_axis_a = 1; *r_axis_b = 2; }
}
+/* same as axis_dominant_v3 but return the max value */
+float axis_dominant_v3_max(int *r_axis_a, int *r_axis_b, const float axis[3])
+{
+ const float xn = fabsf(axis[0]);
+ const float yn = fabsf(axis[1]);
+ const float zn = fabsf(axis[2]);
+
+ if (zn >= xn && zn >= yn) { *r_axis_a = 0; *r_axis_b = 1; return zn; }
+ else if (yn >= xn && yn >= zn) { *r_axis_a = 0; *r_axis_b = 2; return yn; }
+ else { *r_axis_a = 1; *r_axis_b = 2; return xn; }
+}
+
+
+/****************************** Interpolation ********************************/
+
static float tri_signed_area(const float v1[3], const float v2[3], const float v3[3], const int i, const int j)
{
return 0.5f * ((v1[i] - v2[i]) * (v2[j] - v3[j]) + (v1[j] - v2[j]) * (v3[i] - v2[i]));
@@ -2051,6 +2298,13 @@ void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const flo
len_v2(dirs[3]),
};
+ /* variable 'area' is just for storage,
+ * the order its initialized doesn't matter */
+#ifdef __clang__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wunsequenced"
+#endif
+
/* inline mean_value_half_tan four times here */
float t[4] = {
MEAN_VALUE_HALF_TAN_V2(area, 0, 1),
@@ -2059,6 +2313,10 @@ void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const flo
MEAN_VALUE_HALF_TAN_V2(area, 3, 0),
};
+#ifdef __clang__
+# pragma clang diagnostic pop
+#endif
+
#undef MEAN_VALUE_HALF_TAN_V2
w[0] = (t[3] + t[0]) / lens[0];
@@ -2252,59 +2510,106 @@ void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[
{
/* TODO: t1 and t2 overlap each iter, we could call this only once per iter and reuse previous value */
float totweight, t1, t2, len, *vmid, *vprev, *vnext;
- int i;
+ int i, i_next, i_curr;
+ bool edge_interp = false;
totweight = 0.0f;
for (i = 0; i < n; i++) {
+ i_curr = i;
+ i_next = (i == n - 1) ? 0 : i + 1;
+
vmid = v[i];
vprev = (i == 0) ? v[n - 1] : v[i - 1];
- vnext = (i == n - 1) ? v[0] : v[i + 1];
+ vnext = v[i_next];
+
+ /* 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 (dist_to_line_segment_v3(co, vmid, vnext) < 10 * FLT_EPSILON) {
+ edge_interp = true;
+ break;
+ }
t1 = mean_value_half_tan_v3(co, vprev, vmid);
t2 = mean_value_half_tan_v3(co, vmid, vnext);
len = len_v3v3(co, vmid);
- w[i] = (len != 0.0f)? (t1 + t2) / len: 0.0f;
+ w[i] = (len != 0.0f) ? (t1 + t2) / len: 0.0f;
totweight += w[i];
}
- if (totweight != 0.0f) {
- for (i = 0; i < n; i++) {
- w[i] /= totweight;
+ if (edge_interp) {
+ float len_curr = len_v3v3(co, vmid);
+ float len_next = len_v3v3(co, vnext);
+ float edge_len = len_curr + len_next;
+ for (i = 0; i < n; i++)
+ w[i] = 0.0;
+
+ w[i_curr] = len_next / edge_len;
+ w[i_next] = len_curr / edge_len;
+ }
+ else {
+ if (totweight != 0.0f) {
+ for (i = 0; i < n; i++) {
+ w[i] /= totweight;
+ }
}
}
}
+
void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[2])
{
/* TODO: t1 and t2 overlap each iter, we could call this only once per iter and reuse previous value */
float totweight, t1, t2, len, *vmid, *vprev, *vnext;
- int i;
+ int i, i_next, i_curr;
+ bool edge_interp = false;
totweight = 0.0f;
for (i = 0; i < n; i++) {
+ i_curr = i;
+ i_next = (i == n - 1) ? 0 : i + 1;
+
vmid = v[i];
vprev = (i == 0) ? v[n - 1] : v[i - 1];
- vnext = (i == n - 1) ? v[0] : v[i + 1];
+ vnext = v[i_next];
+
+ /* 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 (dist_to_line_segment_v2(co, vmid, vnext) < 10 * FLT_EPSILON) {
+ edge_interp = true;
+ break;
+ }
t1 = mean_value_half_tan_v2(co, vprev, vmid);
t2 = mean_value_half_tan_v2(co, vmid, vnext);
len = len_v2v2(co, vmid);
- w[i] = (len != 0.0f)? (t1 + t2) / len: 0.0f;
+ w[i] = (len != 0.0f) ? (t1 + t2) / len: 0.0f;
totweight += w[i];
}
- if (totweight != 0.0f) {
- for (i = 0; i < n; i++) {
- w[i] /= totweight;
+ if (edge_interp) {
+ float len_curr = len_v2v2(co, vmid);
+ float len_next = len_v2v2(co, vnext);
+ float edge_len = len_curr + len_next;
+ for (i = 0; i < n; i++)
+ w[i] = 0.0;
+
+ w[i_curr] = len_next / edge_len;
+ w[i_next] = len_curr / edge_len;
+ }
+ else {
+ if (totweight != 0.0f) {
+ for (i = 0; i < n; i++) {
+ w[i] /= totweight;
+ }
}
}
}
-/* (x1,v1)(t1=0)------(x2,v2)(t2=1), 0<t<1 --> (x,v)(t) */
+/* (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)
{
float a[3], b[3];
@@ -2349,7 +2654,9 @@ void resolve_tri_uv(float r_uv[2], const float st[2], const float st0[2], const
r_uv[0] = (float)((d * x[0] - b * x[1]) / det);
r_uv[1] = (float)(((-c) * x[0] + a * x[1]) / det);
}
- else zero_v2(r_uv);
+ else {
+ zero_v2(r_uv);
+ }
}
/* bilinear reverse */
@@ -2791,8 +3098,8 @@ void tangent_from_uv(float uv1[2], float uv2[2], float uv3[3], float co1[3], flo
/****************************** Vector Clouds ********************************/
/* vector clouds */
-/* void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight,float (*rpos)[3], float *rweight,
- * float lloc[3],float rloc[3],float lrot[3][3],float lscale[3][3])
+/* void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight, float (*rpos)[3], float *rweight,
+ * float lloc[3], float rloc[3], float lrot[3][3], float lscale[3][3])
*
* input
* (
@@ -2848,7 +3155,9 @@ void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight, fl
add_v3_v3(accu_com, v);
accu_weight += weight[a];
}
- else add_v3_v3(accu_com, pos[a]);
+ else {
+ add_v3_v3(accu_com, pos[a]);
+ }
if (rweight) {
float v[3];
@@ -2857,8 +3166,9 @@ void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight, fl
add_v3_v3(accu_rcom, v);
accu_rweight += rweight[a];
}
- else add_v3_v3(accu_rcom, rpos[a]);
-
+ else {
+ add_v3_v3(accu_rcom, rpos[a]);
+ }
}
if (!weight || !rweight) {
accu_weight = accu_rweight = list_size;
@@ -2881,9 +3191,9 @@ void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight, fl
/* build 'projection' matrix */
for (a = 0; a < list_size; a++) {
sub_v3_v3v3(va, rpos[a], accu_rcom);
- /* mul_v3_fl(va,bp->mass); mass needs renormalzation here ?? */
+ /* mul_v3_fl(va, bp->mass); mass needs renormalzation here ?? */
sub_v3_v3v3(vb, pos[a], accu_com);
- /* mul_v3_fl(va,rp->mass); */
+ /* mul_v3_fl(va, rp->mass); */
m[0][0] += va[0] * vb[0];
m[0][1] += va[0] * vb[1];
m[0][2] += va[0] * vb[2];
@@ -2956,9 +3266,9 @@ static void vec_add_dir(float r[3], const float v1[3], const float v2[3], const
r[2] = v1[2] + fac * (v2[2] - v1[2]);
}
-static int ff_visible_quad(const float p[3], const float n[3],
- const float v0[3], const float v1[3], const float v2[3],
- float q0[3], float q1[3], float q2[3], float q3[3])
+int form_factor_visible_quad(const float p[3], const float n[3],
+ const float v0[3], const float v1[3], const float v2[3],
+ float q0[3], float q1[3], float q2[3], float q3[3])
{
static const float epsilon = 1e-6f;
float c, sd[3];
@@ -3317,8 +3627,8 @@ static void ff_normalize(float n[3])
}
}
-static float ff_quad_form_factor(const float p[3], const float n[3],
- const float q0[3], const float q1[3], const float q2[3], const float q3[3])
+float form_factor_quad(const float p[3], const float n[3],
+ const float q0[3], const float q1[3], const float q2[3], const float q3[3])
{
float r0[3], r1[3], r2[3], r3[3], g0[3], g1[3], g2[3], g3[3];
float a1, a2, a3, a4, dot1, dot2, dot3, dot4, result;
@@ -3364,11 +3674,11 @@ float form_factor_hemi_poly(float p[3], float n[3], float v1[3], float v2[3], fl
* covered by a quad or triangle, cosine weighted */
float q0[3], q1[3], q2[3], q3[3], contrib = 0.0f;
- if (ff_visible_quad(p, n, v1, v2, v3, q0, q1, q2, q3))
- contrib += ff_quad_form_factor(p, n, q0, q1, q2, q3);
+ if (form_factor_visible_quad(p, n, v1, v2, v3, q0, q1, q2, q3))
+ contrib += form_factor_quad(p, n, q0, q1, q2, q3);
- if (v4 && ff_visible_quad(p, n, v1, v3, v4, q0, q1, q2, q3))
- contrib += ff_quad_form_factor(p, n, q0, q1, q2, q3);
+ if (v4 && form_factor_visible_quad(p, n, v1, v3, v4, q0, q1, q2, q3))
+ contrib += form_factor_quad(p, n, q0, q1, q2, q3);
return contrib;
}
@@ -3376,44 +3686,57 @@ float form_factor_hemi_poly(float p[3], float n[3], float v1[3], float v2[3], fl
/* evaluate if entire quad is a proper convex quad */
int is_quad_convex_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
{
- float nor[3], nor1[3], nor2[3], vec[4][2];
- int axis_a, axis_b;
+ float nor[3], nor_a[3], nor_b[3], vec[4][2];
+ float mat[3][3];
+ const bool is_ok_a = (normal_tri_v3(nor_a, v1, v2, v3) > FLT_EPSILON);
+ const bool is_ok_b = (normal_tri_v3(nor_b, v1, v3, v4) > FLT_EPSILON);
/* define projection, do both trias apart, quad is undefined! */
- normal_tri_v3(nor1, v1, v2, v3);
- normal_tri_v3(nor2, v1, v3, v4);
+ /* check normal length incase one size is zero area */
+ if (is_ok_a) {
+ if (is_ok_b) {
+ /* use both, most common outcome */
+
+ /* when the face is folded over as 2 tris we probably don't want to create
+ * a quad from it, but go ahead with the intersection test since this
+ * isn't a function for degenerate faces */
+ if (UNLIKELY(dot_v3v3(nor_a, nor_b) < 0.0f)) {
+ /* flip so adding normals in the opposite direction
+ * doesn't give a zero length vector */
+ negate_v3(nor_b);
+ }
- /* when the face is folded over as 2 tris we probably don't want to create
- * a quad from it, but go ahead with the intersection test since this
- * isn't a function for degenerate faces */
- if (UNLIKELY(dot_v3v3(nor1, nor2) < 0.0f)) {
- /* flip so adding normals in the opposite direction
- * doesnt give a zero length vector */
- negate_v3(nor2);
+ add_v3_v3v3(nor, nor_a, nor_b);
+ normalize_v3(nor);
+ }
+ else {
+ copy_v3_v3(nor, nor_a); /* only 'a' */
+ }
+ }
+ else {
+ if (is_ok_b) {
+ copy_v3_v3(nor, nor_b); /* only 'b' */
+ }
+ else {
+ return false; /* both zero, we can't do anything useful here */
+ }
}
- add_v3_v3v3(nor, nor1, nor2);
-
- axis_dominant_v3(&axis_a, &axis_b, nor);
-
- vec[0][0] = v1[axis_a];
- vec[0][1] = v1[axis_b];
- vec[1][0] = v2[axis_a];
- vec[1][1] = v2[axis_b];
+ axis_dominant_v3_to_m3(mat, nor);
- vec[2][0] = v3[axis_a];
- vec[2][1] = v3[axis_b];
- vec[3][0] = v4[axis_a];
- vec[3][1] = v4[axis_b];
+ mul_v2_m3v3(vec[0], mat, v1);
+ mul_v2_m3v3(vec[1], mat, v2);
+ mul_v2_m3v3(vec[2], mat, v3);
+ mul_v2_m3v3(vec[3], mat, v4);
/* linetests, the 2 diagonals have to instersect to be convex */
- return (isect_line_line_v2(vec[0], vec[2], vec[1], vec[3]) > 0) ? TRUE : FALSE;
+ return (isect_line_line_v2(vec[0], vec[2], vec[1], vec[3]) > 0);
}
int is_quad_convex_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2])
{
/* linetests, the 2 diagonals have to instersect to be convex */
- return (isect_line_line_v2(v1, v3, v2, v4) > 0) ? TRUE : FALSE;
+ return (isect_line_line_v2(v1, v3, v2, v4) > 0);
}
diff --git a/source/blender/blenlib/intern/math_geom_inline.c b/source/blender/blenlib/intern/math_geom_inline.c
index ba9770e1bd1..f32b477787b 100644
--- a/source/blender/blenlib/intern/math_geom_inline.c
+++ b/source/blender/blenlib/intern/math_geom_inline.c
@@ -158,4 +158,31 @@ MINLINE int min_axis_v3(const float vec[3])
((y < z) ? 1 : 2));
}
+/**
+ * Simple method to find how many tri's we need when we already know the corner+poly count.
+ *
+ * Formula is:
+ *
+ * tri = ((corner_count / poly_count) - 2) * poly_count;
+ *
+ * Use doubles since this is used for allocating and we
+ * don't want float precision to give incorrect results.
+ *
+ * \param poly_count The number of ngon's/tris (1-2 sided faces will give incorrect results)
+ * \param corner_count - also known as loops in BMesh/DNA
+ */
+MINLINE int poly_to_tri_count(const int poly_count, const int corner_count)
+{
+ if (poly_count != 0) {
+ const double poly_count_d = (double)poly_count;
+ const double corner_count_d = (double)corner_count;
+ BLI_assert(poly_count > 0);
+ BLI_assert(corner_count > 0);
+ return (int)((((corner_count_d / poly_count_d) - 2.0) * poly_count_d) + 0.5);
+ }
+ else {
+ return 0;
+ }
+}
+
#endif /* __MATH_GEOM_INLINE_C__ */
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 3ca771769a6..f116c9b8443 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -333,15 +333,24 @@ void mul_m4_v3(float mat[4][4], float vec[3])
vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2];
}
-void mul_v3_m4v3(float in[3], float mat[4][4], const float vec[3])
+void mul_v3_m4v3(float r[3], float mat[4][4], const float vec[3])
{
float x, y;
x = vec[0];
y = vec[1];
- in[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2] + mat[3][0];
- in[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2] + mat[3][1];
- in[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2];
+ r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2] + mat[3][0];
+ r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2] + mat[3][1];
+ r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2];
+}
+
+void mul_v2_m2v2(float r[2], float mat[2][2], const float vec[2])
+{
+ float x;
+
+ x = vec[0];
+ r[0] = mat[0][0] * x + mat[1][0] * vec[1];
+ r[1] = mat[0][1] * x + mat[1][1] * vec[1];
}
/* same as mul_m4_v3() but doesnt apply translation component */
@@ -358,7 +367,7 @@ void mul_mat3_m4_v3(float mat[4][4], float vec[3])
void mul_project_m4_v3(float mat[4][4], float vec[3])
{
- const float w = vec[0] * mat[0][3] + vec[1] * mat[1][3] + vec[2] * mat[2][3] + mat[3][3];
+ const float w = mul_project_m4_v3_zfac(mat, vec);
mul_m4_v3(mat, vec);
vec[0] /= w;
@@ -366,7 +375,7 @@ void mul_project_m4_v3(float mat[4][4], float vec[3])
vec[2] /= w;
}
-void mul_v4_m4v4(float r[4], float mat[4][4], float v[4])
+void mul_v4_m4v4(float r[4], float mat[4][4], const float v[4])
{
float x, y, z;
@@ -404,13 +413,19 @@ void mul_m4_v4d(float mat[4][4], double r[4])
mul_v4d_m4v4d(r, mat, r);
}
-void mul_v3_m3v3(float r[3], float M[3][3], float a[3])
+void mul_v3_m3v3(float r[3], float M[3][3], const float a[3])
{
r[0] = M[0][0] * a[0] + M[1][0] * a[1] + M[2][0] * a[2];
r[1] = M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2];
r[2] = M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2];
}
+void mul_v2_m3v3(float r[2], float M[3][3], const float a[3])
+{
+ r[0] = M[0][0] * a[0] + M[1][0] * a[1] + M[2][0] * a[2];
+ r[1] = M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2];
+}
+
void mul_m3_v3(float M[3][3], float r[3])
{
float tmp[3];
@@ -504,8 +519,7 @@ void sub_m4_m4m4(float m1[4][4], float m2[4][4], float m3[4][4])
m1[i][j] = m2[i][j] - m3[i][j];
}
-/* why not make this a standard part of the API? */
-static float determinant_m3_local(float m[3][3])
+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]) +
@@ -534,7 +548,7 @@ int invert_m3_m3_ex(float m1[3][3], float m2[3][3], const float epsilon)
adjoint_m3_m3(m1, m2);
/* then determinant old matrix! */
- det = determinant_m3_local(m2);
+ det = determinant_m3_array(m2);
success = (fabsf(det) > epsilon);
@@ -569,7 +583,7 @@ int invert_m3_m3(float m1[3][3], float m2[3][3])
adjoint_m3_m3(m1, m2);
/* then determinant old matrix! */
- det = determinant_m3_local(m2);
+ det = determinant_m3_array(m2);
success = (det != 0.0f);
@@ -613,6 +627,8 @@ int invert_m4_m4(float inverse[4][4], float mat[4][4])
float max;
int maxj;
+ BLI_assert(inverse != mat);
+
/* Set inverse to identity */
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
@@ -979,17 +995,11 @@ void normalize_m4(float mat[4][4])
void normalize_m4_m4(float rmat[4][4], float mat[4][4])
{
- float len;
-
- len = normalize_v3_v3(rmat[0], mat[0]);
- if (len != 0.0f) rmat[0][3] = mat[0][3] / len;
- len = normalize_v3_v3(rmat[1], mat[1]);
- if (len != 0.0f) rmat[1][3] = mat[1][3] / len;
- len = normalize_v3_v3(rmat[2], mat[2]);
- if (len != 0.0f) rmat[2][3] = mat[2][3] / len;
+ copy_m4_m4(rmat, mat);
+ normalize_m4(rmat);
}
-void adjoint_m2_m2(float m1[][2], float m[][2])
+void adjoint_m2_m2(float m1[2][2], float m[2][2])
{
BLI_assert(m1 != m);
m1[0][0] = m[1][1];
@@ -1211,6 +1221,33 @@ void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wm
copy_v3_v3(loc, wmat[3]);
}
+void mat4_to_loc_quat(float loc[3], float quat[4], float wmat[4][4])
+{
+ float mat3[3][3];
+ float mat3_n[3][3]; /* normalized mat3 */
+
+ copy_m3_m4(mat3, wmat);
+ normalize_m3_m3(mat3_n, mat3);
+
+ /* 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]);
+ }
+
+ mat3_to_quat(quat, mat3_n);
+ copy_v3_v3(loc, wmat[3]);
+}
+
+void mat4_decompose(float loc[3], float quat[4], float size[3], float wmat[4][4])
+{
+ float rot[3][3];
+ mat4_to_loc_rot_size(loc, rot, size, wmat);
+ mat3_to_quat(quat, rot);
+}
+
void scale_m3_fl(float m[3][3], float scale)
{
m[0][0] = m[1][1] = m[2][2] = scale;
@@ -1244,8 +1281,8 @@ void rotate_m4(float mat[4][4], const char axis, const float angle)
assert(axis >= 'X' && axis <= 'Z');
- cosine = (float)cos(angle);
- sine = (float)sin(angle);
+ cosine = cosf(angle);
+ sine = sinf(angle);
switch (axis) {
case 'X':
for (col = 0; col < 4; col++)
@@ -1276,6 +1313,13 @@ void rotate_m4(float mat[4][4], const char axis, const float angle)
}
}
+void rotate_m2(float mat[2][2], const float angle)
+{
+ mat[0][0] = mat[1][1] = cosf(angle);
+ mat[0][1] = sinf(angle);
+ mat[1][0] = -mat[0][1];
+}
+
void blend_m3_m3m3(float out[3][3], float dst[3][3], float src[3][3], const float srcweight)
{
float srot[3][3], drot[3][3];
@@ -1901,3 +1945,16 @@ void pseudoinverse_m4_m4(float Ainv[4][4], float A[4][4], float epsilon)
mul_serie_m4(Ainv, U, Wm, V, NULL, NULL, NULL, NULL, NULL);
}
+
+void pseudoinverse_m3_m3(float Ainv[3][3], float A[3][3], float epsilon)
+{
+ /* try regular inverse when possible, otherwise fall back to slow svd */
+ if (!invert_m3_m3(Ainv, A)) {
+ float tmp[4][4], tmpinv[4][4];
+
+ copy_m4_m3(tmp, A);
+ pseudoinverse_m4_m4(tmpinv, tmp, epsilon);
+ copy_m3_m4(Ainv, tmpinv);
+ }
+}
+
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index 71f146e8131..26576b2dcb2 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -84,6 +84,8 @@ void mul_qt_qtqt(float q[4], const float q1[4], const float q2[4])
* \note:
* Assumes a unit quaternion?
*
+ * \note: multiplying by 3x3 matrix is ~25% faster.
+ *
* in fact not, but you may want to use a unit quat, read on...
*
* Shortcut for 'q v q*' when \a v is actually a quaternion.
@@ -589,10 +591,10 @@ void interp_qt_qtqt(float result[4], const float quat1[4], const float quat2[4],
}
if ((1.0f - cosom) > 0.0001f) {
- omega = (float)acos(cosom);
- sinom = (float)sin(omega);
- sc1 = (float)sin((1 - t) * omega) / sinom;
- sc2 = (float)sin(t * omega) / sinom;
+ omega = acosf(cosom);
+ sinom = sinf(omega);
+ sc1 = sinf((1.0f - t) * omega) / sinom;
+ sc2 = sinf(t * omega) / sinom;
}
else {
sc1 = 1.0f - t;
@@ -1660,7 +1662,7 @@ void quat_apply_track(float quat[4], short axis, short upflag)
axis = axis - 3;
/* there are 2 possible up-axis for each axis used, the 'quat_track' applies so the first
- * up axis is used X->Y, Y->X, Z->X, if this first up axis isn used then rotate 90d
+ * up axis is used X->Y, Y->X, Z->X, if this first up axis isn't used then rotate 90d
* the strange bit shift below just find the low axis {X:Y, Y:X, Z:X} */
if (upflag != (2 - axis) >> 1) {
float q[4] = {M_SQRT1_2, 0.0, 0.0, 0.0}; /* assign 90d rotation axis */
@@ -1737,3 +1739,158 @@ float angle_wrap_deg(float angle)
{
return mod_inline(angle + 180.0f, 360.0f) - 180.0f;
}
+
+/* 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;
+}
+
+/* axis conversion */
+static float _axis_convert_matrix[23][3][3] = {
+ {{-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}},
+ {{-1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, {0.0, -1.0, 0.0}},
+ {{-1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 1.0, 0.0}},
+ {{-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}},
+ {{0.0, -1.0, 0.0}, {-1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}},
+ {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}},
+ {{0.0, 0.0, -1.0}, {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}},
+ {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}},
+ {{0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}},
+ {{0.0, 0.0, -1.0}, {0.0, -1.0, 0.0}, {-1.0, 0.0, 0.0}},
+ {{0.0, 0.0, 1.0}, {0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}},
+ {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, {-1.0, 0.0, 0.0}},
+ {{0.0, -1.0, 0.0}, {0.0, 0.0, -1.0}, {1.0, 0.0, 0.0}},
+ {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, {1.0, 0.0, 0.0}},
+ {{0.0, 0.0, -1.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0}},
+ {{0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {1.0, 0.0, 0.0}},
+ {{0.0, -1.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}},
+ {{0.0, 0.0, -1.0}, {1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}},
+ {{0.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}},
+ {{0.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}},
+ {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, -1.0}},
+ {{1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}},
+ {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, {0.0, 1.0, 0.0}},
+};
+
+static int _axis_convert_lut[23][24] = {
+ {0x8C8, 0x4D0, 0x2E0, 0xAE8, 0x701, 0x511, 0x119, 0xB29, 0x682, 0x88A,
+ 0x09A, 0x2A2, 0x80B, 0x413, 0x223, 0xA2B, 0x644, 0x454, 0x05C, 0xA6C,
+ 0x745, 0x94D, 0x15D, 0x365},
+ {0xAC8, 0x8D0, 0x4E0, 0x2E8, 0x741, 0x951, 0x159, 0x369, 0x702, 0xB0A,
+ 0x11A, 0x522, 0xA0B, 0x813, 0x423, 0x22B, 0x684, 0x894, 0x09C, 0x2AC,
+ 0x645, 0xA4D, 0x05D, 0x465},
+ {0x4C8, 0x2D0, 0xAE0, 0x8E8, 0x681, 0x291, 0x099, 0x8A9, 0x642, 0x44A,
+ 0x05A, 0xA62, 0x40B, 0x213, 0xA23, 0x82B, 0x744, 0x354, 0x15C, 0x96C,
+ 0x705, 0x50D, 0x11D, 0xB25},
+ {0x2C8, 0xAD0, 0x8E0, 0x4E8, 0x641, 0xA51, 0x059, 0x469, 0x742, 0x34A,
+ 0x15A, 0x962, 0x20B, 0xA13, 0x823, 0x42B, 0x704, 0xB14, 0x11C, 0x52C,
+ 0x685, 0x28D, 0x09D, 0x8A5},
+ {0x708, 0xB10, 0x120, 0x528, 0x8C1, 0xAD1, 0x2D9, 0x4E9, 0x942, 0x74A,
+ 0x35A, 0x162, 0x64B, 0xA53, 0x063, 0x46B, 0x804, 0xA14, 0x21C, 0x42C,
+ 0x885, 0x68D, 0x29D, 0x0A5},
+ {0xB08, 0x110, 0x520, 0x728, 0x941, 0x151, 0x359, 0x769, 0x802, 0xA0A,
+ 0x21A, 0x422, 0xA4B, 0x053, 0x463, 0x66B, 0x884, 0x094, 0x29C, 0x6AC,
+ 0x8C5, 0xACD, 0x2DD, 0x4E5},
+ {0x508, 0x710, 0xB20, 0x128, 0x881, 0x691, 0x299, 0x0A9, 0x8C2, 0x4CA,
+ 0x2DA, 0xAE2, 0x44B, 0x653, 0xA63, 0x06B, 0x944, 0x754, 0x35C, 0x16C,
+ 0x805, 0x40D, 0x21D, 0xA25},
+ {0x108, 0x510, 0x720, 0xB28, 0x801, 0x411, 0x219, 0xA29, 0x882, 0x08A,
+ 0x29A, 0x6A2, 0x04B, 0x453, 0x663, 0xA6B, 0x8C4, 0x4D4, 0x2DC, 0xAEC,
+ 0x945, 0x14D, 0x35D, 0x765},
+ {0x748, 0x350, 0x160, 0x968, 0xAC1, 0x2D1, 0x4D9, 0x8E9, 0xA42, 0x64A,
+ 0x45A, 0x062, 0x68B, 0x293, 0x0A3, 0x8AB, 0xA04, 0x214, 0x41C, 0x82C,
+ 0xB05, 0x70D, 0x51D, 0x125},
+ {0x948, 0x750, 0x360, 0x168, 0xB01, 0x711, 0x519, 0x129, 0xAC2, 0x8CA,
+ 0x4DA, 0x2E2, 0x88B, 0x693, 0x2A3, 0x0AB, 0xA44, 0x654, 0x45C, 0x06C,
+ 0xA05, 0x80D, 0x41D, 0x225},
+ {0x348, 0x150, 0x960, 0x768, 0xA41, 0x051, 0x459, 0x669, 0xA02, 0x20A,
+ 0x41A, 0x822, 0x28B, 0x093, 0x8A3, 0x6AB, 0xB04, 0x114, 0x51C, 0x72C,
+ 0xAC5, 0x2CD, 0x4DD, 0x8E5},
+ {0x148, 0x950, 0x760, 0x368, 0xA01, 0x811, 0x419, 0x229, 0xB02, 0x10A,
+ 0x51A, 0x722, 0x08B, 0x893, 0x6A3, 0x2AB, 0xAC4, 0x8D4, 0x4DC, 0x2EC,
+ 0xA45, 0x04D, 0x45D, 0x665},
+ {0x688, 0x890, 0x0A0, 0x2A8, 0x4C1, 0x8D1, 0xAD9, 0x2E9, 0x502, 0x70A,
+ 0xB1A, 0x122, 0x74B, 0x953, 0x163, 0x36B, 0x404, 0x814, 0xA1C, 0x22C,
+ 0x445, 0x64D, 0xA5D, 0x065},
+ {0x888, 0x090, 0x2A0, 0x6A8, 0x501, 0x111, 0xB19, 0x729, 0x402, 0x80A,
+ 0xA1A, 0x222, 0x94B, 0x153, 0x363, 0x76B, 0x444, 0x054, 0xA5C, 0x66C,
+ 0x4C5, 0x8CD, 0xADD, 0x2E5},
+ {0x288, 0x690, 0x8A0, 0x0A8, 0x441, 0x651, 0xA59, 0x069, 0x4C2, 0x2CA,
+ 0xADA, 0x8E2, 0x34B, 0x753, 0x963, 0x16B, 0x504, 0x714, 0xB1C, 0x12C,
+ 0x405, 0x20D, 0xA1D, 0x825},
+ {0x088, 0x290, 0x6A0, 0x8A8, 0x401, 0x211, 0xA19, 0x829, 0x442, 0x04A,
+ 0xA5A, 0x662, 0x14B, 0x353, 0x763, 0x96B, 0x4C4, 0x2D4, 0xADC, 0x8EC,
+ 0x505, 0x10D, 0xB1D, 0x725},
+ {0x648, 0x450, 0x060, 0xA68, 0x2C1, 0x4D1, 0x8D9, 0xAE9, 0x282, 0x68A,
+ 0x89A, 0x0A2, 0x70B, 0x513, 0x123, 0xB2B, 0x204, 0x414, 0x81C, 0xA2C,
+ 0x345, 0x74D, 0x95D, 0x165},
+ {0xA48, 0x650, 0x460, 0x068, 0x341, 0x751, 0x959, 0x169, 0x2C2, 0xACA,
+ 0x8DA, 0x4E2, 0xB0B, 0x713, 0x523, 0x12B, 0x284, 0x694, 0x89C, 0x0AC,
+ 0x205, 0xA0D, 0x81D, 0x425},
+ {0x448, 0x050, 0xA60, 0x668, 0x281, 0x091, 0x899, 0x6A9, 0x202, 0x40A,
+ 0x81A, 0xA22, 0x50B, 0x113, 0xB23, 0x72B, 0x344, 0x154, 0x95C, 0x76C,
+ 0x2C5, 0x4CD, 0x8DD, 0xAE5},
+ {0x048, 0xA50, 0x660, 0x468, 0x201, 0xA11, 0x819, 0x429, 0x342, 0x14A,
+ 0x95A, 0x762, 0x10B, 0xB13, 0x723, 0x52B, 0x2C4, 0xAD4, 0x8DC, 0x4EC,
+ 0x285, 0x08D, 0x89D, 0x6A5},
+ {0x808, 0xA10, 0x220, 0x428, 0x101, 0xB11, 0x719, 0x529, 0x142, 0x94A,
+ 0x75A, 0x362, 0x8CB, 0xAD3, 0x2E3, 0x4EB, 0x044, 0xA54, 0x65C, 0x46C,
+ 0x085, 0x88D, 0x69D, 0x2A5},
+ {0xA08, 0x210, 0x420, 0x828, 0x141, 0x351, 0x759, 0x969, 0x042, 0xA4A,
+ 0x65A, 0x462, 0xACB, 0x2D3, 0x4E3, 0x8EB, 0x084, 0x294, 0x69C, 0x8AC,
+ 0x105, 0xB0D, 0x71D, 0x525},
+ {0x408, 0x810, 0xA20, 0x228, 0x081, 0x891, 0x699, 0x2A9, 0x102, 0x50A,
+ 0x71A, 0xB22, 0x4CB, 0x8D3, 0xAE3, 0x2EB, 0x144, 0x954, 0x75C, 0x36C,
+ 0x045, 0x44D, 0x65D, 0xA65},
+ };
+
+// _axis_convert_num = {'X': 0, 'Y': 1, 'Z': 2, '-X': 3, '-Y': 4, '-Z': 5}
+
+MINLINE int _axis_signed(const int axis)
+{
+ return (axis < 3) ? axis : axis - 3;
+}
+
+/*
+ * Each argument us an axis in ['X', 'Y', 'Z', '-X', '-Y', '-Z']
+ * where the first 2 are a source and the second 2 are the target.
+ */
+int mat3_from_axis_conversion(int from_forward, int from_up, int to_forward, int to_up,
+ float r_mat[3][3])
+{
+ // from functools import reduce
+ int value;
+ int i;
+
+ if (from_forward == to_forward && from_up == to_up) {
+ unit_m3(r_mat);
+ return false;
+ }
+
+ if ((_axis_signed(from_forward) == _axis_signed(from_up)) ||
+ (_axis_signed(to_forward) == _axis_signed(to_up)))
+ {
+ /* we could assert here! */
+ unit_m3(r_mat);
+ return false;
+ }
+
+ value = ((from_forward << (0 * 3)) |
+ (from_up << (1 * 3)) |
+ (to_forward << (2 * 3)) |
+ (to_up << (3 * 3)));
+
+ for (i = 0; i < (sizeof(_axis_convert_matrix) / sizeof(*_axis_convert_matrix)); i++) {
+ int j;
+ for (j = 0; j < sizeof(*_axis_convert_lut) / sizeof(*_axis_convert_lut[0]); j++) {
+ if (_axis_convert_lut[i][j] == value) {
+ copy_m3_m3(r_mat, _axis_convert_matrix[i]);
+ return true;
+ }
+ }
+
+ }
+// BLI_assert(0);
+ return false;
+}
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index 812e2b3e63d..58d444f5794 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -122,6 +122,32 @@ 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;
}
+/**
+ * Equivalent to:
+ * interp_v3_v3v3(v, v1, v2, -1.0f);
+ */
+
+void flip_v4_v4v4(float v[4], const float v1[4], const float v2[4])
+{
+ v[0] = v1[0] + (v1[0] - v2[0]);
+ v[1] = v1[1] + (v1[1] - v2[1]);
+ v[2] = v1[2] + (v1[2] - v2[2]);
+ v[3] = v1[3] + (v1[3] - v2[3]);
+}
+
+void flip_v3_v3v3(float v[3], const float v1[3], const float v2[3])
+{
+ v[0] = v1[0] + (v1[0] - v2[0]);
+ v[1] = v1[1] + (v1[1] - v2[1]);
+ v[2] = v1[2] + (v1[2] - v2[2]);
+}
+
+void flip_v2_v2v2(float v[2], const float v1[2], const float v2[2])
+{
+ v[0] = v1[0] + (v1[0] - v2[0]);
+ v[1] = v1[1] + (v1[1] - v2[1]);
+}
+
/********************************** Angles ***********************************/
/* Return the angle in radians between vecs 1-2 and 2-3 in radians
@@ -209,11 +235,8 @@ float angle_signed_v2v2(const float v1[2], const float v2[2])
float angle_normalized_v3v3(const float v1[3], const float v2[3])
{
/* double check they are normalized */
-#ifdef DEBUG
- float test;
- BLI_assert(fabsf((test = len_squared_v3(v1)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f);
- BLI_assert(fabsf((test = len_squared_v3(v2)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f);
-#endif
+ BLI_ASSERT_UNIT_V3(v1);
+ BLI_ASSERT_UNIT_V3(v2);
/* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */
if (dot_v3v3(v1, v2) < 0.0f) {
@@ -232,11 +255,8 @@ float angle_normalized_v3v3(const float v1[3], const float v2[3])
float angle_normalized_v2v2(const float v1[2], const float v2[2])
{
/* double check they are normalized */
-#ifdef DEBUG
- float test;
- BLI_assert(fabsf((test = len_squared_v2(v1)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f);
- BLI_assert(fabsf((test = len_squared_v2(v2)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f);
-#endif
+ BLI_ASSERT_UNIT_V2(v1);
+ BLI_ASSERT_UNIT_V2(v2);
/* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */
if (dot_v2v2(v1, v2) < 0.0f) {
@@ -423,10 +443,7 @@ void rotate_normalized_v3_v3v3fl(float r[3], const float p[3], const float axis[
const float sintheta = sin(angle);
/* double check they are normalized */
-#ifdef DEBUG
- float test;
- BLI_assert(fabsf((test = len_squared_v3(axis)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f);
-#endif
+ BLI_ASSERT_UNIT_V3(axis);
r[0] = ((costheta + (1 - costheta) * axis[0] * axis[0]) * p[0]) +
(((1 - costheta) * axis[0] * axis[1] - axis[2] * sintheta) * p[1]) +
@@ -685,6 +702,19 @@ void msub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array
}
}
+void interp_vn_vn(float *array_tar, const float *array_src, const float t, const int size)
+{
+ const float s = 1.0f - t;
+ float *tar = array_tar + (size - 1);
+ const float *src = array_src + (size - 1);
+ int i = size;
+ while (i--) {
+ *(tar) = (s * *(tar)) + (t * *(src));
+ tar--;
+ src--;
+ }
+}
+
void fill_vn_i(int *array_tar, const int size, const int val)
{
int *tar = array_tar + (size - 1);
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index 04b9d574347..c8e8ff9602b 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -398,6 +398,15 @@ MINLINE void mul_v4_v4fl(float r[4], const float a[4], float f)
r[3] = a[3] * f;
}
+/* note: could add a matrix inline */
+MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3])
+{
+ return (mat[0][3] * co[0]) +
+ (mat[1][3] * co[1]) +
+ (mat[2][3] * co[2]) + mat[3][3];
+}
+
+
MINLINE void madd_v2_v2fl(float r[2], const float a[2], float f)
{
r[0] += a[0] * f;
@@ -461,7 +470,7 @@ MINLINE void mul_v3_v3v3(float r[3], const float v1[3], const float v2[3])
r[2] = v1[2] * v2[2];
}
-MINLINE void negate_v2(float r[3])
+MINLINE void negate_v2(float r[2])
{
r[0] = -r[0];
r[1] = -r[1];
@@ -528,6 +537,7 @@ MINLINE float cross_v2v2(const float a[2], const float b[2])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
{
+ BLI_assert(r != a && r != b);
r[0] = a[1] * b[2] - a[2] * b[1];
r[1] = a[2] * b[0] - a[0] * b[2];
r[2] = a[0] * b[1] - a[1] * b[0];
@@ -662,7 +672,7 @@ MINLINE float normalize_v3_v3(float r[3], const float a[3])
float d = dot_v3v3(a, a);
/* a larger value causes normalize errors in a
- * scaled down models with camera xtreme close */
+ * scaled down models with camera extreme close */
if (d > 1.0e-35f) {
d = sqrtf(d);
mul_v3_v3fl(r, a, 1.0f / d);
@@ -680,7 +690,7 @@ MINLINE double normalize_v3_d(double n[3])
double d = n[0] * n[0] + n[1] * n[1] + n[2] * n[2];
/* a larger value causes normalize errors in a
- * scaled down models with camera xtreme close */
+ * scaled down models with camera extreme close */
if (d > 1.0e-35) {
double mul;
diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c
index f37e1e03f39..6e52145c653 100644
--- a/source/blender/blenlib/intern/noise.c
+++ b/source/blender/blenlib/intern/noise.c
@@ -281,9 +281,9 @@ static float npfade(float t)
return (t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f));
}
-static float grad(int hash, float x, float y, float z)
+static float grad(int hash_val, float x, float y, float z)
{
- int h = hash & 15; /* CONVERT LO 4 BITS OF HASH CODE */
+ 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;
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
@@ -1460,7 +1460,8 @@ float BLI_gNoise(float noisesize, float x, float y, float z, int hard, int noise
noisefunc = cellNoiseU;
break;
case 0:
- default: {
+ default:
+ {
noisefunc = orgBlenderNoise;
/* add one to make return value same as BLI_hnoise */
x += 1;
@@ -1592,7 +1593,8 @@ float mg_fBm(float x, float y, float z, float H, float lacunarity, float octaves
noisefunc = cellNoise;
break;
case 0:
- default: {
+ default:
+ {
noisefunc = orgBlenderNoiseS;
}
}
@@ -1662,7 +1664,8 @@ float mg_MultiFractal(float x, float y, float z, float H, float lacunarity, floa
noisefunc = cellNoise;
break;
case 0:
- default: {
+ default:
+ {
noisefunc = orgBlenderNoiseS;
}
}
@@ -1728,7 +1731,8 @@ float mg_HeteroTerrain(float x, float y, float z, float H, float lacunarity, flo
noisefunc = cellNoise;
break;
case 0:
- default: {
+ default:
+ {
noisefunc = orgBlenderNoiseS;
}
}
@@ -1801,7 +1805,8 @@ float mg_HybridMultiFractal(float x, float y, float z, float H, float lacunarity
noisefunc = cellNoise;
break;
case 0:
- default: {
+ default:
+ {
noisefunc = orgBlenderNoiseS;
}
}
@@ -1876,7 +1881,8 @@ float mg_RidgedMultiFractal(float x, float y, float z, float H, float lacunarity
noisefunc = cellNoise;
break;
case 0:
- default: {
+ default:
+ {
noisefunc = orgBlenderNoiseS;
}
}
@@ -1941,7 +1947,8 @@ float mg_VLNoise(float x, float y, float z, float distortion, int nbas1, int nba
noisefunc1 = cellNoise;
break;
case 0:
- default: {
+ default:
+ {
noisefunc1 = orgBlenderNoiseS;
}
}
@@ -1975,7 +1982,8 @@ float mg_VLNoise(float x, float y, float z, float distortion, int nbas1, int nba
noisefunc2 = cellNoise;
break;
case 0:
- default: {
+ default:
+ {
noisefunc2 = orgBlenderNoiseS;
}
}
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index 444daf8817c..f9cf913157b 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -41,13 +41,13 @@
#include "DNA_listBase.h"
+#include "BLI_utildefines.h"
#include "BLI_fileops.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
-#include "BLI_utildefines.h"
-#include "BKE_blender.h" /* BLENDER_VERSION */
+#include "../blenkernel/BKE_blender.h" /* BLENDER_VERSION, bad level include (no function call) */
#include "GHOST_Path-api.h"
@@ -79,43 +79,51 @@
/* local */
#define UNIQUE_NAME_MAX 128
-static char bprogname[FILE_MAX]; /* path to program executable */
-static char bprogdir[FILE_MAX]; /* path in which executable is located */
+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[FILE_MAX]; /* temporary directory */
-static int add_win32_extension(char *name);
-static char *blender_version_decimal(const int ver);
-
/* implementation */
+/**
+ * Looks for a sequence of decimal digits in string, preceding any filename extension,
+ * returning the integer value if found, or 0 if not.
+ *
+ * \param string String to scan.
+ * \param head Optional area to return copy of part of string prior to digits, or before dot if no digits.
+ * \param tail Optional area to return copy of part of string following digits, or from dot if no digits.
+ * \param numlen Optional to return number of digits found.
+ */
int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *numlen)
{
- unsigned short len, len2, lenlslash = 0, nums = 0, nume = 0;
- short i, found = 0;
- char *lslash = BLI_last_slash(string);
- len2 = len = strlen(string);
- if (lslash)
- lenlslash = (int)(lslash - string);
+ unsigned short nums = 0, nume = 0;
+ short i;
+ bool found_digit = false;
+ const char * const lslash = BLI_last_slash(string);
+ const unsigned short string_len = strlen(string);
+ const unsigned short lslash_len = lslash != NULL ? (int)(lslash - string) : 0;
+ unsigned short name_end = string_len;
- while (len > lenlslash && string[--len] != '.') {}
- if (len == lenlslash && string[len] != '.') len = len2;
+ while (name_end > lslash_len && string[--name_end] != '.') {} /* name ends at dot if present */
+ if (name_end == lslash_len && string[name_end] != '.') name_end = string_len;
- for (i = len - 1; i >= lenlslash; i--) {
+ for (i = name_end - 1; i >= lslash_len; i--) {
if (isdigit(string[i])) {
- if (found) {
+ if (found_digit) {
nums = i;
}
else {
nume = i;
nums = i;
- found = 1;
+ found_digit = true;
}
}
else {
- if (found) break;
+ if (found_digit) break;
}
}
- if (found) {
+
+ if (found_digit) {
if (tail) strcpy(tail, &string[nume + 1]);
if (head) {
strcpy(head, string);
@@ -124,56 +132,72 @@ int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *nu
if (numlen) *numlen = nume - nums + 1;
return ((int)atoi(&(string[nums])));
}
- if (tail) strcpy(tail, string + len);
- if (head) {
- strncpy(head, string, len);
- head[len] = '\0';
+ else {
+ if (tail) strcpy(tail, string + name_end);
+ if (head) {
+ BLI_strncpy(head, string, name_end);
+ }
+ if (numlen) *numlen = 0;
+ return 0;
}
- if (numlen) *numlen = 0;
- return 0;
}
+/**
+ * Returns in area pointed to by string a string of the form "<head><pic><tail>", where pic
+ * is formatted as numlen digits with leading zeroes.
+ */
void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic)
{
- char fmtstr[16] = "";
- if (pic < 0) pic = 0;
- sprintf(fmtstr, "%%s%%.%dd%%s", numlen);
- sprintf(string, fmtstr, head, pic, tail);
+ sprintf(string, "%s%.*d%s", head, numlen, MAX2(0, pic), tail);
}
-/* Foo.001 -> "Foo", 1
- * Returns the length of "Foo" */
+/**
+ * Looks for a numeric suffix preceded by delim character on the end of
+ * name, puts preceding part into *left and value of suffix into *nr.
+ * Returns the length of *left.
+ *
+ * Foo.001 -> "Foo", 1
+ * Returning the length of "Foo"
+ *
+ * \param left Where to return copy of part preceding delim
+ * \param nr Where to return value of numeric suffix
+ * \param name String to split
+ * \param delim Delimiter character
+ * \return Length of \a left
+ */
int BLI_split_name_num(char *left, int *nr, const char *name, const char delim)
{
- int a;
+ const int name_len = strlen(name);
*nr = 0;
- a = strlen(name);
- memcpy(left, name, (a + 1) * sizeof(char));
-
- if (a > 1 && name[a - 1] == delim) return a;
-
- while (a--) {
- if (name[a] == delim) {
- left[a] = 0;
- *nr = atol(name + a + 1);
- /* casting down to an int, can overflow for large numbers */
- if (*nr < 0)
- *nr = 0;
- return a;
- }
- if (isdigit(name[a]) == 0) break;
-
- left[a] = 0;
+ memcpy(left, name, (name_len + 1) * sizeof(char));
+
+ /* name doesn't end with a delimiter "foo." */
+ if ((name_len > 1 && name[name_len - 1] == delim) == 0) {
+ int a = name_len;
+ while (a--) {
+ if (name[a] == delim) {
+ left[a] = '\0'; /* truncate left part here */
+ *nr = atol(name + a + 1);
+ /* casting down to an int, can overflow for large numbers */
+ if (*nr < 0)
+ *nr = 0;
+ return a;
+ }
+ else if (isdigit(name[a]) == 0) {
+ /* non-numeric suffix - give up */
+ break;
+ }
+ }
}
- for (a = 0; name[a]; a++)
- left[a] = name[a];
-
- return a;
+ return name_len;
}
+/**
+ * Looks for a string of digits within name (using BLI_stringdec) and adjusts it by add.
+ */
void BLI_newname(char *name, int add)
{
char head[UNIQUE_NAME_MAX], tail[UNIQUE_NAME_MAX];
@@ -196,9 +220,20 @@ void BLI_newname(char *name, int add)
BLI_stringenc(name, head, tail, digits, pic);
}
-
-
-int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, const char defname[], char delim, char *name, short name_len)
+/**
+ * Ensures name is unique (according to criteria specified by caller in unique_check callback),
+ * incrementing its numeric suffix as necessary. Returns true if name had to be adjusted.
+ *
+ * \param unique_check Return true if name is not unique
+ * \param arg Additional arg to unique_check--meaning is up to caller
+ * \param defname To initialize name if latter is empty
+ * \param delim Delimits numeric suffix in name
+ * \param name Name to be ensured unique
+ * \param name_len Maximum length of name area
+ * \return true if there if the name was changed
+ */
+bool BLI_uniquename_cb(bool (*unique_check)(void * arg, const char *name),
+ void *arg, const char *defname, char delim, char *name, short name_len)
{
if (name[0] == '\0') {
BLI_strncpy(name, defname, name_len);
@@ -211,7 +246,7 @@ int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, cons
int number;
int len = BLI_split_name_num(left, &number, name, delim);
do {
- int numlen = BLI_snprintf(numstr, sizeof(numstr), "%c%03d", delim, ++number);
+ const int numlen = BLI_snprintf(numstr, sizeof(numstr), "%c%03d", delim, ++number);
/* highly unlikely the string only has enough room for the number
* but support anyway */
@@ -229,10 +264,10 @@ int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, cons
BLI_strncpy(name, tempname, name_len);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* little helper macro for BLI_uniquename */
@@ -250,28 +285,39 @@ int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, cons
* defname: the name that should be used by default if none is specified already
* delim: the character which acts as a delimiter between parts of the name
*/
-static int uniquename_find_dupe(ListBase *list, void *vlink, const char *name, short name_offs)
+static bool uniquename_find_dupe(ListBase *list, void *vlink, const char *name, short name_offs)
{
Link *link;
for (link = list->first; link; link = link->next) {
if (link != vlink) {
if (!strcmp(GIVE_STRADDR(link, name_offs), name)) {
- return 1;
+ return true;
}
}
}
- return 0;
+ return false;
}
-static int uniquename_unique_check(void *arg, const char *name)
+static bool uniquename_unique_check(void *arg, const char *name)
{
struct {ListBase *lb; void *vlink; short name_offs; } *data = arg;
return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offs);
}
-void BLI_uniquename(ListBase *list, void *vlink, const char defname[], char delim, short name_offs, short name_len)
+/**
+ * Ensures that the specified block has a unique name within the containing list,
+ * incrementing its numeric suffix as necessary.
+ *
+ * \param list List containing the block
+ * \param vlink The block to check the name for
+ * \param defname To initialize block name if latter is empty
+ * \param delim Delimits numeric suffix in name
+ * \param name_offs Offset of name within block structure
+ * \param name_len Maximum length of name area
+ */
+void BLI_uniquename(ListBase *list, void *vlink, const char *defname, char delim, short name_offs, short name_len)
{
struct {ListBase *lb; void *vlink; short name_offs; } data;
data.lb = list;
@@ -299,19 +345,19 @@ void BLI_uniquename(ListBase *list, void *vlink, const char defname[], char deli
* If relbase is NULL then its ignored
*/
-void BLI_cleanup_path(const char *relabase, char *dir)
+void BLI_cleanup_path(const char *relabase, char *path)
{
ptrdiff_t a;
char *start, *eind;
if (relabase) {
- BLI_path_abs(dir, relabase);
+ BLI_path_abs(path, relabase);
}
else {
- if (dir[0] == '/' && dir[1] == '/') {
- if (dir[2] == '\0') {
+ if (path[0] == '/' && path[1] == '/') {
+ if (path[2] == '\0') {
return; /* path is "//" - cant clean it */
}
- dir = dir + 2; /* skip the first // */
+ path = path + 2; /* leave the initial "//" untouched */
}
}
@@ -327,70 +373,72 @@ void BLI_cleanup_path(const char *relabase, char *dir)
/* Note, this should really be moved to the file selector,
* since this function is used in many areas */
- if (strcmp(dir, ".") == 0) { /* happens for example in FILE_MAIN */
- get_default_root(dir);
+ if (strcmp(path, ".") == 0) { /* happens for example in FILE_MAIN */
+ get_default_root(path);
return;
}
- while ( (start = strstr(dir, "\\..\\")) ) {
+ while ( (start = strstr(path, "\\..\\")) ) {
eind = start + strlen("\\..\\") - 1;
- a = start - dir - 1;
+ a = start - path - 1;
while (a > 0) {
- if (dir[a] == '\\') break;
+ if (path[a] == '\\') break;
a--;
}
if (a < 0) {
break;
}
else {
- memmove(dir + a, eind, strlen(eind) + 1);
+ memmove(path + a, eind, strlen(eind) + 1);
}
}
- while ( (start = strstr(dir, "\\.\\")) ) {
+ while ( (start = strstr(path, "\\.\\")) ) {
eind = start + strlen("\\.\\") - 1;
memmove(start, eind, strlen(eind) + 1);
}
- while ( (start = strstr(dir, "\\\\")) ) {
+ while ( (start = strstr(path, "\\\\")) ) {
eind = start + strlen("\\\\") - 1;
memmove(start, eind, strlen(eind) + 1);
}
#else
- if (dir[0] == '.') { /* happens, for example in FILE_MAIN */
- dir[0] = '/';
- dir[1] = 0;
+ if (path[0] == '.') { /* happens, for example in FILE_MAIN */
+ path[0] = '/';
+ path[1] = 0;
return;
}
- /* support for odd paths: eg /../home/me --> /home/me
- * this is a valid path in blender but we cant handle this the usual way below
- * simply strip this prefix then evaluate the path as usual. pythons os.path.normpath() does this */
- while ((strncmp(dir, "/../", 4) == 0)) {
- memmove(dir, dir + 4, strlen(dir + 4) + 1);
- }
-
- while ( (start = strstr(dir, "/../")) ) {
- eind = start + (4 - 1) /* strlen("/../") - 1 */;
- a = start - dir - 1;
- while (a > 0) {
- if (dir[a] == '/') break;
- a--;
- }
- if (a < 0) {
- break;
+ while ( (start = strstr(path, "/../")) ) {
+ a = start - path - 1;
+ if (a > 0) {
+ /* <prefix>/<parent>/../<postfix> => <prefix>/<postfix> */
+ eind = start + (4 - 1) /* strlen("/../") - 1 */; /* strip "/.." and keep last "/" */
+ while (a > 0 && path[a] != '/') { /* find start of <parent> */
+ a--;
+ }
+ memmove(path + a, eind, strlen(eind) + 1);
}
else {
- memmove(dir + a, eind, strlen(eind) + 1);
+ /* support for odd paths: eg /../home/me --> /home/me
+ * this is a valid path in blender but we cant handle this the usual way below
+ * simply strip this prefix then evaluate the path as usual.
+ * pythons os.path.normpath() does this */
+
+ /* Note: previous version of following call used an offset of 3 instead of 4,
+ * which meant that the "/../home/me" example actually became "home/me".
+ * Using offset of 3 gives behaviour consistent with the abovementioned
+ * Python routine. */
+ memmove(path, path + 3, strlen(path + 3) + 1);
}
}
- while ( (start = strstr(dir, "/./")) ) {
+ while ( (start = strstr(path, "/./")) ) {
eind = start + (3 - 1) /* strlen("/./") - 1 */;
memmove(start, eind, strlen(eind) + 1);
}
- while ( (start = strstr(dir, "//")) ) {
+ while ( (start = strstr(path, "//")) ) {
eind = start + (2 - 1) /* strlen("//") - 1 */;
memmove(start, eind, strlen(eind) + 1);
}
@@ -404,20 +452,28 @@ void BLI_cleanup_dir(const char *relabase, char *dir)
}
-void BLI_cleanup_file(const char *relabase, char *dir)
+void BLI_cleanup_file(const char *relabase, char *path)
{
- BLI_cleanup_path(relabase, dir);
- BLI_del_slash(dir);
+ BLI_cleanup_path(relabase, path);
+ BLI_del_slash(path);
}
-int BLI_path_is_rel(const char *path)
+/**
+ * Does path begin with the special "//" prefix that Blender uses to indicate
+ * a path relative to the .blend file.
+ */
+bool BLI_path_is_rel(const char *path)
{
return path[0] == '/' && path[1] == '/';
}
+/**
+ * Replaces *file with a relative version (prefixed by "//") such that BLI_path_abs, given
+ * the same *relfile, will convert it back to its original value.
+ */
void BLI_path_rel(char *file, const char *relfile)
{
- char *lslash;
+ const char *lslash;
char temp[FILE_MAX];
char res[FILE_MAX];
@@ -519,7 +575,11 @@ void BLI_path_rel(char *file, const char *relfile)
}
}
-int BLI_has_parent(char *path)
+/**
+ * Cleans path and makes sure it ends with a slash.
+ * \return true if \a path has more than one other path separator in it.
+ */
+bool BLI_has_parent(char *path)
{
int len;
int slashes = 0;
@@ -534,25 +594,34 @@ int BLI_has_parent(char *path)
return slashes > 1;
}
-int BLI_parent_dir(char *path)
+/**
+ * Replaces path with the path of its parent directory, returning true if
+ * it was able to find a parent directory within the pathname.
+ */
+bool BLI_parent_dir(char *path)
{
static char parent_dir[] = {'.', '.', SEP, '\0'}; /* "../" or "..\\" */
char tmp[FILE_MAX + 4];
BLI_strncpy(tmp, path, sizeof(tmp) - 4);
BLI_add_slash(tmp);
strcat(tmp, parent_dir);
- BLI_cleanup_dir(NULL, tmp);
+ 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));
- return 1;
+ return true;
}
else {
- return 0;
+ return false;
}
}
-static int stringframe_chars(char *path, int *char_start, int *char_end)
+/**
+ * Looks for a sequence of "#" characters in the last slash-separated component of *path,
+ * returning the indexes of the first and one past the last character in the sequence in
+ * *char_start and *char_end respectively. Returns true if such a sequence was found.
+ */
+static bool stringframe_chars(const char *path, int *char_start, int *char_end)
{
int ch_sta, ch_end, i;
/* Insert current frame: file### -> file001 */
@@ -576,18 +645,22 @@ static int stringframe_chars(char *path, int *char_start, int *char_end)
if (ch_end) {
*char_start = ch_sta;
*char_end = ch_end;
- return 1;
+ return true;
}
else {
*char_start = -1;
*char_end = -1;
- return 0;
+ return false;
}
}
+/**
+ * Ensure *path contains at least one "#" character in its last slash-separated
+ * component, appending one digits long if not.
+ */
static void ensure_digits(char *path, int digits)
{
- char *file = BLI_last_slash(path);
+ char *file = (char *)BLI_last_slash(path);
if (file == NULL)
file = path;
@@ -602,7 +675,11 @@ static void ensure_digits(char *path, int digits)
}
}
-int BLI_path_frame(char *path, int frame, int digits)
+/**
+ * Replaces "#" character sequence in last slash-separated component of *path
+ * with frame as decimal integer, with leading zeroes as necessary, to make digits digits.
+ */
+bool BLI_path_frame(char *path, int frame, int digits)
{
int ch_sta, ch_end;
@@ -613,12 +690,17 @@ int BLI_path_frame(char *path, int frame, int digits)
char tmp[FILE_MAX];
sprintf(tmp, "%.*s%.*d%s", ch_sta, path, ch_end - ch_sta, frame, path + ch_end);
strcpy(path, tmp);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-int BLI_path_frame_range(char *path, int sta, int end, int digits)
+/**
+ * Replaces "#" character sequence in last slash-separated component of *path
+ * with sta and end as decimal integers, with leading zeroes as necessary, to make digits
+ * digits each, with a hyphen in-between.
+ */
+bool BLI_path_frame_range(char *path, int sta, int end, int digits)
{
int ch_sta, ch_end;
@@ -631,14 +713,19 @@ int BLI_path_frame_range(char *path, int sta, int end, int digits)
"%.*s%.*d-%.*d%s",
ch_sta, path, ch_end - ch_sta, sta, ch_end - ch_sta, end, path + ch_end);
BLI_strncpy(path, tmp, FILE_MAX);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-int BLI_path_abs(char *path, const char *basepath)
+/**
+ * If path begins with "//", strips that and replaces it with basepath directory. Also converts
+ * a drive-letter prefix to something more sensible if this is a non-drive-letter-based system.
+ * Returns true if "//" prefix expansion was done.
+ */
+bool BLI_path_abs(char *path, const char *basepath)
{
- int wasrelative = BLI_path_is_rel(path);
+ const bool wasrelative = BLI_path_is_rel(path);
char tmp[FILE_MAX];
char base[FILE_MAX];
#ifdef WIN32
@@ -696,21 +783,23 @@ int BLI_path_abs(char *path, const char *basepath)
/* 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 */
if (wasrelative) {
- char *lslash = BLI_last_slash(base);
+ const char * const lslash = BLI_last_slash(base);
if (lslash) {
- int baselen = (int) (lslash - base) + 1;
+ const int baselen = (int) (lslash - base) + 1; /* length up to and including last "/" */
/* use path for temp storage here, we copy back over it right away */
- BLI_strncpy(path, tmp + 2, FILE_MAX);
+ BLI_strncpy(path, tmp + 2, FILE_MAX); /* strip "//" */
- memcpy(tmp, base, baselen);
- BLI_strncpy(tmp + baselen, path, sizeof(tmp) - baselen);
- BLI_strncpy(path, tmp, FILE_MAX);
+ memcpy(tmp, base, baselen); /* prefix with base up to last "/" */
+ BLI_strncpy(tmp + baselen, path, sizeof(tmp) - baselen); /* append path after "//" */
+ BLI_strncpy(path, tmp, FILE_MAX); /* return as result */
}
else {
+ /* base doesn't seem to be a directory--ignore it and just strip "//" prefix on path */
BLI_strncpy(path, tmp + 2, FILE_MAX);
}
}
else {
+ /* base ignored */
BLI_strncpy(path, tmp, FILE_MAX);
}
@@ -730,24 +819,27 @@ int BLI_path_abs(char *path, const char *basepath)
}
-/*
- * Should only be done with command line paths.
- * this is NOT something blenders internal paths support like the // prefix
+/**
+ * Expands path relative to the current working directory, if it was relative.
+ * Returns true if such expansion was done.
+ *
+ * \note Should only be done with command line paths.
+ * this is _not_ something blenders internal paths support like the "//" prefix
*/
-int BLI_path_cwd(char *path)
+bool BLI_path_cwd(char *path)
{
- int wasrelative = 1;
- int filelen = strlen(path);
+ bool wasrelative = true;
+ const int filelen = strlen(path);
#ifdef WIN32
if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/'))
- wasrelative = 0;
+ wasrelative = false;
#else
if (filelen >= 2 && path[0] == '/')
- wasrelative = 0;
+ wasrelative = false;
#endif
- if (wasrelative == 1) {
+ if (wasrelative) {
char cwd[FILE_MAX] = "";
BLI_current_working_dir(cwd, sizeof(cwd)); /* in case the full path to the blend isn't used */
@@ -772,22 +864,9 @@ int BLI_path_cwd(char *path)
return wasrelative;
}
-
-/* 'di's filename component is moved into 'fi', di is made a dir path */
-void BLI_splitdirstring(char *di, char *fi)
-{
- char *lslash = BLI_last_slash(di);
-
- if (lslash) {
- BLI_strncpy(fi, lslash + 1, FILE_MAXFILE);
- *(lslash + 1) = 0;
- }
- else {
- BLI_strncpy(fi, di, FILE_MAXFILE);
- di[0] = 0;
- }
-}
-
+/**
+ * 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;
@@ -814,7 +893,7 @@ void BLI_getlastdir(const char *dir, char *last, const size_t maxlen)
const char *BLI_getDefaultDocumentFolder(void)
{
#ifndef WIN32
- const char *xdg_documents_dir = getenv("XDG_DOCUMENTS_DIR");
+ const char * const xdg_documents_dir = getenv("XDG_DOCUMENTS_DIR");
if (xdg_documents_dir)
return xdg_documents_dir;
@@ -848,8 +927,9 @@ const char *BLI_getDefaultDocumentFolder(void)
/* ************************************************************* */
/* ************************************************************* */
-// #define PATH_DEBUG2
+// #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];
@@ -857,7 +937,11 @@ static char *blender_version_decimal(const int ver)
return version_str;
}
-static int test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name)
+/**
+ * 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];
@@ -869,43 +953,65 @@ static int test_path(char *targetpath, const char *path_base, const char *path_s
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_DEBUG2
- printf("\tpath found: %s\n", targetpath);
+#ifdef PATH_DEBUG
+ printf("\t%s found: %s\n", __func__, targetpath);
#endif
- return 1;
+ return true;
}
else {
-#ifdef PATH_DEBUG2
- printf("\tpath missing: %s\n", targetpath);
+#ifdef PATH_DEBUG
+ printf("\t%s missing: %s\n", __func__, targetpath);
#endif
//targetpath[0] = '\0';
- return 0;
+ return false;
}
}
-static int test_env_path(char *path, const char *envvar)
+/**
+ * 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 0;
+ if (!env) return false;
if (BLI_is_dir(env)) {
BLI_strncpy(path, env, FILE_MAX);
- return 1;
+#ifdef PATH_DEBUG
+ printf("\t%s env %s found: %s\n", __func__, envvar, env);
+#endif
+ return true;
}
else {
path[0] = '\0';
- return 0;
+#ifdef PATH_DEBUG
+ printf("\t%s env %s missing: %s\n", __func__, envvar, env);
+#endif
+ return false;
}
}
-static int get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver)
+/**
+ * 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_DEBUG2
- printf("get_path_local...\n");
+#ifdef PATH_DEBUG
+ printf("%s...\n", __func__);
#endif
if (folder_name) {
@@ -921,22 +1027,34 @@ static int get_path_local(char *targetpath, const char *folder_name, const char
}
/* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
- if (test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder))
- return 1;
-
- return 0;
+ return test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder);
}
-static int is_portable_install(void)
+/**
+ * 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 existance of config folder */
+ /* 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);
}
-static int get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int 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;
@@ -953,7 +1071,7 @@ static int get_path_user(char *targetpath, const char *folder_name, const char *
}
else {
BLI_strncpy(targetpath, user_path, FILE_MAX);
- return 1;
+ return true;
}
}
@@ -962,30 +1080,34 @@ static int get_path_user(char *targetpath, const char *folder_name, const char *
BLI_strncpy(user_path, user_base_path, FILE_MAX);
if (!user_path[0])
- return 0;
+ return false;
-#ifdef PATH_DEBUG2
- printf("get_path_user: %s\n", user_path);
+#ifdef PATH_DEBUG
+ printf("%s: %s\n", __func__, user_path);
#endif
if (subfolder_name) {
- /* try $HOME/folder_name/subfolder_name */
return test_path(targetpath, user_path, folder_name, subfolder_name);
}
else {
- /* try $HOME/folder_name */
return test_path(targetpath, user_path, NULL, folder_name);
}
}
-static int get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
+/**
+ * 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;
-
-
- /* first allow developer only overrides to the system path
- * these are only used when running blender from source */
char cwd[FILE_MAX];
char relfolder[FILE_MAX];
@@ -1001,16 +1123,20 @@ static int get_path_system(char *targetpath, const char *folder_name, const char
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 1;
+ return true;
}
}
/* try EXECUTABLE_DIR/release/folder_name */
if (test_path(targetpath, bprogdir, "release", relfolder))
- return 1;
+ return true;
+
/* end developer overrides */
@@ -1023,7 +1149,7 @@ static int get_path_system(char *targetpath, const char *folder_name, const char
}
else {
BLI_strncpy(targetpath, system_path, FILE_MAX);
- return 1;
+ return true;
}
}
@@ -1032,10 +1158,10 @@ static int get_path_system(char *targetpath, const char *folder_name, const char
BLI_strncpy(system_path, system_base_path, FILE_MAX);
if (!system_path[0])
- return 0;
+ return false;
-#ifdef PATH_DEBUG2
- printf("get_path_system: %s\n", system_path);
+#ifdef PATH_DEBUG
+ printf("%s: %s\n", __func__, system_path);
#endif
if (subfolder_name) {
@@ -1050,7 +1176,7 @@ static int get_path_system(char *targetpath, const char *folder_name, const char
/* get a folder out of the 'folder_id' presets for paths */
/* returns the path if found, NULL string if not */
-char *BLI_get_folder(int folder_id, const char *subfolder)
+const char *BLI_get_folder(int folder_id, const char *subfolder)
{
const int ver = BLENDER_VERSION;
static char path[FILE_MAX] = "";
@@ -1097,7 +1223,10 @@ char *BLI_get_folder(int folder_id, const char *subfolder)
return path;
}
-char *BLI_get_user_folder_notest(int folder_id, const char *subfolder)
+/**
+ * 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] = "";
@@ -1122,9 +1251,12 @@ char *BLI_get_user_folder_notest(int folder_id, const char *subfolder)
return path;
}
-char *BLI_get_folder_create(int folder_id, const char *subfolder)
+/**
+ * Returns the path to a folder in the user area, creating it if it doesn't exist.
+ */
+const char *BLI_get_folder_create(int folder_id, const char *subfolder)
{
- char *path;
+ const char *path;
/* only for user folders */
if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
@@ -1140,10 +1272,14 @@ char *BLI_get_folder_create(int folder_id, const char *subfolder)
return path;
}
-char *BLI_get_folder_version(const int id, const int ver, const int do_check)
+/**
+ * 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] = "";
- int ok;
+ bool ok;
switch (id) {
case BLENDER_RESOURCE_PATH_USER:
ok = get_path_user(path, NULL, NULL, NULL, ver);
@@ -1156,11 +1292,11 @@ char *BLI_get_folder_version(const int id, const int ver, const int do_check)
break;
default:
path[0] = '\0'; /* in case do_check is false */
- ok = FALSE;
+ ok = false;
BLI_assert(!"incorrect ID");
}
- if ((ok == FALSE) && do_check) {
+ if (!ok && do_check) {
return NULL;
}
@@ -1174,9 +1310,12 @@ char *BLI_get_folder_version(const int id, const int ver, const int do_check)
#ifdef PATH_DEBUG
-#undef PATH_DEBUG
+# undef PATH_DEBUG
#endif
+/**
+ * Sets the specified environment variable to the specified value.
+ */
void BLI_setenv(const char *env, const char *val)
{
/* free windows */
@@ -1202,6 +1341,8 @@ void BLI_setenv(const char *env, const char *val)
/**
* Only set an env var if already not there.
* Like Unix setenv(env, val, 0);
+ *
+ * (not used anywhere).
*/
void BLI_setenv_if_new(const char *env, const char *val)
{
@@ -1210,10 +1351,11 @@ void BLI_setenv_if_new(const char *env, const char *val)
}
+/**
+ * Changes to the path separators to the native ones for this OS.
+ */
void BLI_clean(char *path)
{
- if (path == NULL) return;
-
#ifdef WIN32
if (path && BLI_strnlen(path, 3) > 2) {
BLI_char_switch(path + 2, '/', '\\');
@@ -1223,15 +1365,26 @@ void BLI_clean(char *path)
#endif
}
+/**
+ * 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)
{
- if (string == NULL) return;
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.
+ */
void BLI_make_exist(char *dir)
{
int a;
@@ -1240,7 +1393,7 @@ void BLI_make_exist(char *dir)
a = strlen(dir);
- while (BLI_is_dir(dir) == 0) {
+ while (!BLI_is_dir(dir)) {
a--;
while (dir[a] != SEP) {
a--;
@@ -1260,21 +1413,28 @@ void BLI_make_exist(char *dir)
}
}
+/**
+ * Ensures that the parent directory of *name exists.
+ */
void BLI_make_existing_file(const char *name)
{
- char di[FILE_MAX], fi[FILE_MAXFILE];
+ char di[FILE_MAX];
+ BLI_split_dir_part(name, di, sizeof(di));
- BLI_strncpy(di, name, sizeof(di));
- BLI_splitdirstring(di, fi);
-
- /* test exist */
- if (BLI_exists(di) == 0) {
- BLI_dir_create_recursive(di);
- }
+ /* make if if the dir doesn't exist */
+ BLI_dir_create_recursive(di);
}
-
-void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file)
+/**
+ * Returns in *string the concatenation of *dir and *file (also with *relabase on the
+ * front if specified and *dir begins with "//"). Normalizes all occurrences of path
+ * separators, including ensuring there is exactly one between the copies of *dir and *file,
+ * and between the copies of *relabase and *dir.
+ *
+ * \param relabase Optional prefix to substitute for "//" on front of *dir
+ * \param string Area to return result
+ */
+void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file)
{
int sl;
@@ -1307,7 +1467,7 @@ void BLI_make_file_string(const char *relabase, char *string, const char *dir,
/* Get the file name, chop everything past the last slash (ie. the filename) */
strcpy(string, relabase);
- lslash = BLI_last_slash(string);
+ lslash = (char *)BLI_last_slash(string);
if (lslash) *(lslash + 1) = 0;
dir += 2; /* Skip over the relative reference */
@@ -1356,43 +1516,34 @@ void BLI_make_file_string(const char *relabase, char *string, const char *dir,
BLI_clean(string);
}
-int BLI_testextensie(const char *str, const char *ext)
+/* does str end with ext. */
+bool BLI_testextensie(const char *str, const char *ext)
{
- short a, b;
- int retval;
-
- a = strlen(str);
- b = strlen(ext);
-
- if (a == 0 || b == 0 || b >= a) {
- retval = 0;
- }
- else if (BLI_strcasecmp(ext, str + a - b)) {
- retval = 0;
- }
- else {
- retval = 1;
- }
-
- return (retval);
+ const size_t a = strlen(str);
+ const size_t b = strlen(ext);
+ return !(a == 0 || b == 0 || b >= a) && (BLI_strcasecmp(ext, str + a - b) == 0);
}
-int BLI_testextensie_array(const char *str, const char **ext_array)
+/* does str end with any of the suffixes in *ext_array. */
+bool BLI_testextensie_array(const char *str, const char **ext_array)
{
int i = 0;
while (ext_array[i]) {
if (BLI_testextensie(str, ext_array[i])) {
- return 1;
+ return true;
}
i++;
}
- return 0;
+ return false;
}
-/* semicolon separated wildcards, eg:
- * '*.zip;*.py;*.exe' */
-int BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
+/**
+ * Semicolon separated wildcards, eg:
+ * '*.zip;*.py;*.exe'
+ * does str match any of the semicolon-separated glob patterns in fnmatch.
+ */
+bool BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
{
const char *ext_step = ext_fnmatch;
char pattern[16];
@@ -1411,19 +1562,23 @@ int BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
BLI_strncpy(pattern, ext_step, len_ext);
if (fnmatch(pattern, str, FNM_CASEFOLD) == 0) {
- return 1;
+ return true;
}
ext_step += len_ext;
}
- return 0;
+ return false;
}
-int BLI_replace_extension(char *path, size_t maxlen, const char *ext)
+/**
+ * Removes any existing extension on the end of \a path and appends \a ext.
+ * \return false if there was no room.
+ */
+bool BLI_replace_extension(char *path, size_t maxlen, const char *ext)
{
- size_t path_len = strlen(path);
- size_t ext_len = strlen(ext);
+ const size_t path_len = strlen(path);
+ const size_t ext_len = strlen(ext);
ssize_t a;
for (a = path_len - 1; a >= 0; a--) {
@@ -1437,24 +1592,26 @@ int BLI_replace_extension(char *path, size_t maxlen, const char *ext)
}
if (a + ext_len >= maxlen)
- return 0;
+ return false;
memcpy(path + a, ext, ext_len + 1);
- return 1;
+ return true;
}
-/* strip's trailing '.'s and adds the extension only when needed */
-int BLI_ensure_extension(char *path, size_t maxlen, const char *ext)
+/**
+ * Strip's trailing '.'s and adds the extension only when needed
+ */
+bool BLI_ensure_extension(char *path, size_t maxlen, const char *ext)
{
- size_t path_len = strlen(path);
- size_t ext_len = strlen(ext);
+ const size_t path_len = strlen(path);
+ const size_t ext_len = strlen(ext);
ssize_t a;
- /* first check the extension is alread there */
+ /* first check the extension is already there */
if ( (ext_len <= path_len) &&
(strcmp(path + (path_len - ext_len), ext) == 0))
{
- return 1;
+ return true;
}
for (a = path_len - 1; a >= 0; a--) {
@@ -1468,10 +1625,10 @@ int BLI_ensure_extension(char *path, size_t maxlen, const char *ext)
a++;
if (a + ext_len >= maxlen)
- return 0;
+ return false;
memcpy(path + a, ext, ext_len + 1);
- return 1;
+ return true;
}
/* Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
@@ -1482,8 +1639,8 @@ int BLI_ensure_extension(char *path, size_t maxlen, const char *ext)
* */
void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen)
{
- char *lslash_str = BLI_last_slash(string);
- size_t lslash = lslash_str ? (size_t)(lslash_str - string) + 1 : 0;
+ const char *lslash_str = BLI_last_slash(string);
+ const size_t lslash = lslash_str ? (size_t)(lslash_str - string) + 1 : 0;
if (dir) {
if (lslash) {
@@ -1499,17 +1656,26 @@ void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t d
}
}
+/**
+ * Copies the parent directory part of string into *dir, max length dirlen.
+ */
void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen)
{
BLI_split_dirfile(string, dir, NULL, dirlen, 0);
}
+/**
+ * Copies the leaf filename part of string into *file, max length filelen.
+ */
void BLI_split_file_part(const char *string, char *file, const size_t filelen)
{
BLI_split_dirfile(string, NULL, file, 0, filelen);
}
-/* simple appending of filename to dir, does not check for valid path! */
+/**
+ * Simple appending of filename to dir, does not check for valid path!
+ * Puts result into *dst, which may be same area as *dir.
+ */
void BLI_join_dirfile(char *dst, const size_t maxlen, const char *dir, const char *file)
{
size_t dirlen = BLI_strnlen(dir, maxlen);
@@ -1546,10 +1712,15 @@ void BLI_join_dirfile(char *dst, const size_t maxlen, const char *dir, const cha
BLI_strncpy(dst + dirlen, file, maxlen - dirlen);
}
-/* like pythons os.path.basename( ) */
-char *BLI_path_basename(char *path)
+/**
+ * like pythons os.path.basename()
+ *
+ * \return The pointer into \a path string immediately after last slash,
+ * or start of \a path if none found.
+ */
+const char *BLI_path_basename(const char *path)
{
- char *filename = BLI_last_slash(path);
+ const char * const filename = BLI_last_slash(path);
return filename ? filename + 1 : path;
}
@@ -1588,11 +1759,29 @@ char *BLI_path_basename(char *path)
* this function returns wrong results!
* XXX: test on empty base_dir and return an error ?
*/
-int BLI_rebase_path(char *abs, size_t abs_len, char *rel, size_t rel_len, const char *base_dir, const char *src_dir, const char *dest_dir)
+
+/**
+ *
+ * \param abs Optional string to return new full path
+ * \param abs_len Size of *abs string
+ * \param rel Optional area to return new path relative to parent directory of .blend file
+ * (only meaningful if item is in a subdirectory thereof)
+ * \param rel_len Size of *rel area
+ * \param base_dir Path of .blend file
+ * \param src_dir Original path of item (any initial "//" will be expanded to
+ * parent directory of .blend file)
+ * \param dest_dir New directory into which item will be moved
+ * \return bli_rebase_state
+ *
+ * \note Not actually used anywhere!
+ */
+int BLI_rebase_path(char *abs, size_t abs_len,
+ char *rel, size_t rel_len,
+ const char *base_dir, const char *src_dir, const char *dest_dir)
{
- char path[FILE_MAX];
- char dir[FILE_MAX];
- char base[FILE_MAX];
+ char path[FILE_MAX]; /* original full path of item */
+ char dir[FILE_MAX]; /* directory part of src_dir */
+ char base[FILE_MAX]; /* basename part of src_dir */
char blend_dir[FILE_MAX]; /* directory, where current .blend file resides */
char dest_path[FILE_MAX];
char rel_dir[FILE_MAX];
@@ -1622,23 +1811,25 @@ int BLI_rebase_path(char *abs, size_t abs_len, char *rel, size_t rel_len, const
rel_dir[0] = 0;
/* if image is "below" current .blend file directory */
- if (!strncmp(path, blend_dir, len)) {
+ if (!BLI_path_ncmp(path, blend_dir, len)) {
- /* if image is _in_ current .blend file directory */
if (BLI_path_cmp(dir, blend_dir) == 0) {
+ /* image is directly in .blend file parent directory => put directly in dest_dir */
BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base);
}
- /* "below" */
else {
+ /* "below" (in subdirectory of .blend file parent directory) => put in same relative directory structure in dest_dir */
/* rel = image_path_dir - blend_dir */
BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir));
-
+ /* subdirectories relative to blend_dir */
BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, rel_dir);
+ /* same subdirectories relative to dest_dir */
BLI_join_dirfile(dest_path, sizeof(dest_path), dest_path, base);
+ /* keeping original item basename */
}
}
- /* image is out of current directory */
+ /* image is out of current directory -- just put straight in dest_dir */
else {
BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base);
}
@@ -1648,7 +1839,7 @@ int BLI_rebase_path(char *abs, size_t abs_len, char *rel, size_t rel_len, const
if (rel) {
strncat(rel, rel_dir, rel_len);
- strncat(rel, base, rel_len);
+ strncat(rel, base, rel_len); /* FIXME: could overflow rel area! */
}
/* return 2 if (src == dest) */
@@ -1660,12 +1851,13 @@ int BLI_rebase_path(char *abs, size_t abs_len, char *rel, size_t rel_len, const
return BLI_REBASE_OK;
}
-char *BLI_first_slash(char *string)
+/**
+ * Returns pointer to the leftmost path separator in string. Not actually used anywhere.
+ */
+const char *BLI_first_slash(const char *string)
{
- char *ffslash, *fbslash;
-
- ffslash = strchr(string, '/');
- fbslash = strchr(string, '\\');
+ char * const ffslash = strchr(string, '/');
+ char * const fbslash = strchr(string, '\\');
if (!ffslash) return fbslash;
else if (!fbslash) return ffslash;
@@ -1674,12 +1866,13 @@ char *BLI_first_slash(char *string)
else return fbslash;
}
-char *BLI_last_slash(const char *string)
+/**
+ * Returns pointer to the rightmost path separator in string.
+ */
+const char *BLI_last_slash(const char *string)
{
- char *lfslash, *lbslash;
-
- lfslash = strrchr(string, '/');
- lbslash = strrchr(string, '\\');
+ const char * const lfslash = strrchr(string, '/');
+ const char * const lbslash = strrchr(string, '\\');
if (!lfslash) return lbslash;
else if (!lbslash) return lfslash;
@@ -1688,7 +1881,10 @@ char *BLI_last_slash(const char *string)
else return lfslash;
}
-/* adds a slash if there isn't one there already */
+/**
+ * Appends a slash to string if there isn't one there already.
+ * Returns the new length of the string.
+ */
int BLI_add_slash(char *string)
{
int len = strlen(string);
@@ -1700,7 +1896,9 @@ int BLI_add_slash(char *string)
return len;
}
-/* removes a slash if there is one */
+/**
+ * Removes the last slash and everything after it to the end of string, if there is one.
+ */
void BLI_del_slash(char *string)
{
int len = strlen(string);
@@ -1715,6 +1913,11 @@ void BLI_del_slash(char *string)
}
}
+/**
+ * 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;
@@ -1864,11 +2067,17 @@ void BLI_init_program_path(const char *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;
@@ -1931,16 +2140,26 @@ static void BLI_where_is_temp(char *fullname, const size_t maxlen, char *userdir
}
}
+/**
+ * Sets btempdir to userdir if specified and is a valid directory, otherwise
+ * chooses a suitable OS-specific temporary directory.
+ */
void BLI_init_temporary_dir(char *userdir)
{
BLI_where_is_temp(btempdir, FILE_MAX, userdir);
}
+/**
+ * Path to temporary directory (with trailing slash)
+ */
const char *BLI_temporary_dir(void)
{
return btempdir;
}
+/**
+ * Path to the system temporary directory (with trailing slash)
+ */
void BLI_system_temporary_dir(char *dir)
{
BLI_where_is_temp(dir, FILE_MAX, NULL);
@@ -1948,6 +2167,10 @@ void BLI_system_temporary_dir(char *dir)
#ifdef WITH_ICONV
+/**
+ * Converts a string encoded in the charset named by *code to UTF-8.
+ * Opens a new iconv context each time it is run, which is probably not the
+ * most efficient. */
void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
{
size_t inbytesleft = strlen(original);
@@ -1968,6 +2191,7 @@ void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
rv = iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
if (rv == (size_t) -1) {
printf("iconv Error\n");
+ iconv_close(cd);
return;
}
*utf_8 = '\0';
diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c
index fb767f54e55..91fcb5a5b83 100644
--- a/source/blender/blenlib/intern/rct.c
+++ b/source/blender/blenlib/intern/rct.c
@@ -48,23 +48,23 @@
*
* \return True if \a rect is empty.
*/
-int BLI_rcti_is_empty(const rcti *rect)
+bool BLI_rcti_is_empty(const rcti *rect)
{
return ((rect->xmax <= rect->xmin) || (rect->ymax <= rect->ymin));
}
-int BLI_rctf_is_empty(const rctf *rect)
+bool BLI_rctf_is_empty(const rctf *rect)
{
return ((rect->xmax <= rect->xmin) || (rect->ymax <= rect->ymin));
}
-int BLI_rcti_isect_pt(const rcti *rect, const int x, const int y)
+bool BLI_rcti_isect_pt(const rcti *rect, const int x, const int y)
{
- if (x < rect->xmin) return 0;
- if (x > rect->xmax) return 0;
- if (y < rect->ymin) return 0;
- if (y > rect->ymax) return 0;
- return 1;
+ if (x < rect->xmin) return false;
+ if (x > rect->xmax) return false;
+ if (y < rect->ymin) return false;
+ if (y > rect->ymax) return false;
+ return true;
}
/**
@@ -74,31 +74,31 @@ int BLI_rcti_isect_pt(const rcti *rect, const int x, const int y)
*
* \return True if \a rect is empty.
*/
-int BLI_rcti_isect_pt_v(const rcti *rect, const int xy[2])
+bool BLI_rcti_isect_pt_v(const rcti *rect, const int xy[2])
{
- if (xy[0] < rect->xmin) return 0;
- if (xy[0] > rect->xmax) return 0;
- if (xy[1] < rect->ymin) return 0;
- if (xy[1] > rect->ymax) return 0;
- return 1;
+ if (xy[0] < rect->xmin) return false;
+ if (xy[0] > rect->xmax) return false;
+ if (xy[1] < rect->ymin) return false;
+ if (xy[1] > rect->ymax) return false;
+ return true;
}
-int BLI_rctf_isect_pt(const rctf *rect, const float x, const float y)
+bool BLI_rctf_isect_pt(const rctf *rect, const float x, const float y)
{
- if (x < rect->xmin) return 0;
- if (x > rect->xmax) return 0;
- if (y < rect->ymin) return 0;
- if (y > rect->ymax) return 0;
- return 1;
+ if (x < rect->xmin) return false;
+ if (x > rect->xmax) return false;
+ if (y < rect->ymin) return false;
+ if (y > rect->ymax) return false;
+ return true;
}
-int BLI_rctf_isect_pt_v(const rctf *rect, const float xy[2])
+bool BLI_rctf_isect_pt_v(const rctf *rect, const float xy[2])
{
- if (xy[0] < rect->xmin) return 0;
- if (xy[0] > rect->xmax) return 0;
- if (xy[1] < rect->ymin) return 0;
- if (xy[1] > rect->ymax) return 0;
- return 1;
+ if (xy[0] < rect->xmin) return false;
+ if (xy[0] > rect->xmax) return false;
+ if (xy[1] < rect->ymin) return false;
+ if (xy[1] > rect->ymax) return false;
+ return true;
}
/* based closely on 'isect_line_line_v2_int', but in modified so corner cases are treated as intersections */
@@ -127,17 +127,17 @@ static int isect_segments_fl(const float v1[2], const float v2[2], const float v
}
}
-int BLI_rcti_isect_segment(const rcti *rect, const int s1[2], const int s2[2])
+bool BLI_rcti_isect_segment(const rcti *rect, const int s1[2], const int s2[2])
{
/* first do outside-bounds check for both points of the segment */
- if (s1[0] < rect->xmin && s2[0] < rect->xmin) return 0;
- if (s1[0] > rect->xmax && s2[0] > rect->xmax) return 0;
- if (s1[1] < rect->ymin && s2[1] < rect->ymin) return 0;
- if (s1[1] > rect->ymax && s2[1] > rect->ymax) return 0;
+ if (s1[0] < rect->xmin && s2[0] < rect->xmin) return false;
+ if (s1[0] > rect->xmax && s2[0] > rect->xmax) return false;
+ if (s1[1] < rect->ymin && s2[1] < rect->ymin) return false;
+ if (s1[1] > rect->ymax && s2[1] > rect->ymax) return false;
/* if either points intersect then we definetly intersect */
if (BLI_rcti_isect_pt_v(rect, s1) || BLI_rcti_isect_pt_v(rect, s2)) {
- return 1;
+ return true;
}
else {
/* both points are outside but may insersect the rect */
@@ -147,32 +147,32 @@ int BLI_rcti_isect_segment(const rcti *rect, const int s1[2], const int s2[2])
tvec1[0] = rect->xmin; tvec1[1] = rect->ymin;
tvec2[0] = rect->xmin; tvec2[1] = rect->ymax;
if (isect_segments_i(s1, s2, tvec1, tvec2)) {
- return 1;
+ return true;
}
/* diagonal: [\] */
tvec1[0] = rect->xmin; tvec1[1] = rect->ymax;
tvec2[0] = rect->xmax; tvec2[1] = rect->ymin;
if (isect_segments_i(s1, s2, tvec1, tvec2)) {
- return 1;
+ return true;
}
/* no intersection */
- return 0;
+ return false;
}
}
-int BLI_rctf_isect_segment(const rctf *rect, const float s1[2], const float s2[2])
+bool BLI_rctf_isect_segment(const rctf *rect, const float s1[2], const float s2[2])
{
/* first do outside-bounds check for both points of the segment */
- if (s1[0] < rect->xmin && s2[0] < rect->xmin) return 0;
- if (s1[0] > rect->xmax && s2[0] > rect->xmax) return 0;
- if (s1[1] < rect->ymin && s2[1] < rect->ymin) return 0;
- if (s1[1] > rect->ymax && s2[1] > rect->ymax) return 0;
+ if (s1[0] < rect->xmin && s2[0] < rect->xmin) return false;
+ if (s1[0] > rect->xmax && s2[0] > rect->xmax) return false;
+ if (s1[1] < rect->ymin && s2[1] < rect->ymin) return false;
+ if (s1[1] > rect->ymax && s2[1] > rect->ymax) return false;
/* if either points intersect then we definetly intersect */
if (BLI_rctf_isect_pt_v(rect, s1) || BLI_rctf_isect_pt_v(rect, s2)) {
- return 1;
+ return true;
}
else {
/* both points are outside but may insersect the rect */
@@ -182,18 +182,18 @@ int BLI_rctf_isect_segment(const rctf *rect, const float s1[2], const float s2[2
tvec1[0] = rect->xmin; tvec1[1] = rect->ymin;
tvec2[0] = rect->xmin; tvec2[1] = rect->ymax;
if (isect_segments_fl(s1, s2, tvec1, tvec2)) {
- return 1;
+ return true;
}
/* diagonal: [\] */
tvec1[0] = rect->xmin; tvec1[1] = rect->ymax;
tvec2[0] = rect->xmax; tvec2[1] = rect->ymin;
if (isect_segments_fl(s1, s2, tvec1, tvec2)) {
- return 1;
+ return true;
}
/* no intersection */
- return 0;
+ return false;
}
}
@@ -296,6 +296,19 @@ void BLI_rctf_translate(rctf *rect, float x, float y)
rect->ymax += y;
}
+void BLI_rcti_recenter(rcti *rect, int x, int y)
+{
+ const int dx = x - BLI_rcti_cent_x(rect);
+ const int dy = y - BLI_rcti_cent_y(rect);
+ BLI_rcti_translate(rect, dx, dy);
+}
+void BLI_rctf_recenter(rctf *rect, float x, float y)
+{
+ const float dx = x - BLI_rctf_cent_x(rect);
+ const float dy = y - BLI_rctf_cent_y(rect);
+ BLI_rctf_translate(rect, dx, dy);
+}
+
/* change width & height around the central location */
void BLI_rcti_resize(rcti *rect, int x, int y)
{
@@ -317,6 +330,30 @@ void BLI_rctf_resize(rctf *rect, float x, float y)
rect->ymax = rect->ymin + y;
}
+void BLI_rcti_scale(rcti *rect, const float scale)
+{
+ const int cent_x = BLI_rcti_cent_x(rect);
+ const int cent_y = BLI_rcti_cent_y(rect);
+ const int size_x_half = BLI_rcti_size_x(rect) * (scale * 0.5f);
+ const int size_y_half = BLI_rcti_size_y(rect) * (scale * 0.5f);
+ rect->xmin = cent_x - size_x_half;
+ rect->ymin = cent_y - size_y_half;
+ rect->xmax = cent_x + size_x_half;
+ rect->ymax = cent_y + size_y_half;
+}
+
+void BLI_rctf_scale(rctf *rect, const float scale)
+{
+ const float cent_x = BLI_rctf_cent_x(rect);
+ const float cent_y = BLI_rctf_cent_y(rect);
+ const float size_x_half = BLI_rctf_size_x(rect) * (scale * 0.5f);
+ const float size_y_half = BLI_rctf_size_y(rect) * (scale * 0.5f);
+ rect->xmin = cent_x - size_x_half;
+ rect->ymin = cent_y - size_y_half;
+ rect->xmax = cent_x + size_x_half;
+ rect->ymax = cent_y + size_y_half;
+}
+
void BLI_rctf_interp(rctf *rect, const rctf *rect_a, const rctf *rect_b, const float fac)
{
const float ifac = 1.0f - fac;
@@ -329,49 +366,49 @@ void BLI_rctf_interp(rctf *rect, const rctf *rect_a, const rctf *rect_b, const f
/* BLI_rcti_interp() not needed yet */
-int BLI_rctf_clamp_pt_v(const struct rctf *rect, float xy[2])
+bool BLI_rctf_clamp_pt_v(const struct rctf *rect, float xy[2])
{
- int change = 0;
- if (xy[0] < rect->xmin) { xy[0] = rect->xmin; change = 1; }
- if (xy[0] > rect->xmax) { xy[0] = rect->xmax; change = 1; }
- if (xy[1] < rect->ymin) { xy[1] = rect->ymin; change = 1; }
- if (xy[1] > rect->ymax) { xy[1] = rect->ymax; change = 1; }
+ bool change = false;
+ if (xy[0] < rect->xmin) { xy[0] = rect->xmin; change = true; }
+ if (xy[0] > rect->xmax) { xy[0] = rect->xmax; change = true; }
+ if (xy[1] < rect->ymin) { xy[1] = rect->ymin; change = true; }
+ if (xy[1] > rect->ymax) { xy[1] = rect->ymax; change = true; }
return change;
}
-int BLI_rcti_clamp_pt_v(const struct rcti *rect, int xy[2])
+bool BLI_rcti_clamp_pt_v(const struct rcti *rect, int xy[2])
{
- int change = 0;
- if (xy[0] < rect->xmin) { xy[0] = rect->xmin; change = 1; }
- if (xy[0] > rect->xmax) { xy[0] = rect->xmax; change = 1; }
- if (xy[1] < rect->ymin) { xy[1] = rect->ymin; change = 1; }
- if (xy[1] > rect->ymax) { xy[1] = rect->ymax; change = 1; }
+ bool change = false;
+ if (xy[0] < rect->xmin) { xy[0] = rect->xmin; change = true; }
+ if (xy[0] > rect->xmax) { xy[0] = rect->xmax; change = true; }
+ if (xy[1] < rect->ymin) { xy[1] = rect->ymin; change = true; }
+ if (xy[1] > rect->ymax) { xy[1] = rect->ymax; change = true; }
return change;
}
-int BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, const float limit)
+bool BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, const float limit)
{
if (fabsf(rect_a->xmin - rect_b->xmin) < limit)
if (fabsf(rect_a->xmax - rect_b->xmax) < limit)
if (fabsf(rect_a->ymin - rect_b->ymin) < limit)
if (fabsf(rect_a->ymax - rect_b->ymax) < limit)
- return 1;
+ return true;
- return 0;
+ return false;
}
-int BLI_rcti_compare(const struct rcti *rect_a, const struct rcti *rect_b)
+bool BLI_rcti_compare(const struct rcti *rect_a, const struct rcti *rect_b)
{
if (rect_a->xmin == rect_b->xmin)
if (rect_a->xmax == rect_b->xmax)
if (rect_a->ymin == rect_b->ymin)
if (rect_a->ymax == rect_b->ymax)
- return 1;
+ return true;
- return 0;
+ return false;
}
-int BLI_rctf_isect(const rctf *src1, const rctf *src2, rctf *dest)
+bool BLI_rctf_isect(const rctf *src1, const rctf *src2, rctf *dest)
{
float xmin, xmax;
float ymin, ymax;
@@ -388,7 +425,7 @@ int BLI_rctf_isect(const rctf *src1, const rctf *src2, rctf *dest)
dest->ymin = ymin;
dest->ymax = ymax;
}
- return 1;
+ return true;
}
else {
if (dest) {
@@ -397,11 +434,11 @@ int BLI_rctf_isect(const rctf *src1, const rctf *src2, rctf *dest)
dest->ymin = 0;
dest->ymax = 0;
}
- return 0;
+ return false;
}
}
-int BLI_rcti_isect(const rcti *src1, const rcti *src2, rcti *dest)
+bool BLI_rcti_isect(const rcti *src1, const rcti *src2, rcti *dest)
{
int xmin, xmax;
int ymin, ymax;
@@ -418,7 +455,7 @@ int BLI_rcti_isect(const rcti *src1, const rcti *src2, rcti *dest)
dest->ymin = ymin;
dest->ymax = ymax;
}
- return 1;
+ return true;
}
else {
if (dest) {
@@ -427,7 +464,7 @@ int BLI_rcti_isect(const rcti *src1, const rcti *src2, rcti *dest)
dest->ymin = 0;
dest->ymax = 0;
}
- return 0;
+ return false;
}
}
diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c
index defe500cb21..4d42d71f490 100644
--- a/source/blender/blenlib/intern/scanfill.c
+++ b/source/blender/blenlib/intern/scanfill.c
@@ -95,7 +95,7 @@ typedef struct ScanFillVertLink {
#define SF_EPSILON 0.00003f
-#define SF_VERT_UNKNOWN 1 /* TODO, what is this for exactly? - need to document it! */
+#define SF_VERT_AVAILABLE 1 /* available - in an edge */
#define SF_VERT_ZERO_LEN 255
/* Optionally set ScanFillEdge f to this to mark original boundary edges.
@@ -325,7 +325,9 @@ static short addedgetoscanvert(ScanFillVertLink *sc, ScanFillEdge *eed)
fac1 = 1.0e10f * (eed->v2->xy[0] - x);
}
- else fac1 = (x - eed->v2->xy[0]) / fac1;
+ else {
+ fac1 = (x - eed->v2->xy[0]) / fac1;
+ }
for (ed = sc->edge_first; ed; ed = ed->next) {
@@ -422,7 +424,7 @@ static void testvertexnearedge(ScanFillContext *sf_ctx)
ScanFillEdge *eed, *ed1;
for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) {
- if (eve->h == 1) {
+ if (eve->edge_tot == 1) {
/* find the edge which has vertex eve,
* note: we _know_ this will crash if 'ed1' becomes NULL
* but this will never happen. */
@@ -442,14 +444,14 @@ static void testvertexnearedge(ScanFillContext *sf_ctx)
if (eve != eed->v1 && eve != eed->v2 && eve->poly_nr == eed->poly_nr) {
if (compare_v3v3(eve->co, eed->v1->co, SF_EPSILON)) {
ed1->v2 = eed->v1;
- eed->v1->h++;
- eve->h = 0;
+ eed->v1->edge_tot++;
+ eve->edge_tot = 0;
break;
}
else if (compare_v3v3(eve->co, eed->v2->co, SF_EPSILON)) {
ed1->v2 = eed->v2;
- eed->v2->h++;
- eve->h = 0;
+ eed->v2->edge_tot++;
+ eve->edge_tot = 0;
break;
}
else {
@@ -459,11 +461,11 @@ static void testvertexnearedge(ScanFillContext *sf_ctx)
/* new edge */
ed1 = BLI_scanfill_edge_add(sf_ctx, eed->v1, eve);
- /* printf("fill: vertex near edge %x\n",eve); */
+ /* printf("fill: vertex near edge %x\n", eve); */
ed1->f = 0;
ed1->poly_nr = eed->poly_nr;
eed->v1 = eve;
- eve->h = 3;
+ eve->edge_tot = 3;
break;
}
}
@@ -509,7 +511,7 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
ScanFillVert *eve, *v1, *v2, *v3;
ScanFillEdge *eed, *nexted, *ed1, *ed2, *ed3;
int a, b, verts, maxface, totface;
- short nr, test, twoconnected = 0;
+ short nr, twoconnected = 0;
nr = pf->nr;
@@ -565,6 +567,7 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
verts++;
eve->f = 0; /* flag for connectedges later on */
sc->vert = eve;
+ /* if (even->tmp.v == NULL) eve->tmp.u = verts; */ /* Note, debug print only will work for curve polyfill, union is in use for mesh */
sc++;
}
}
@@ -630,21 +633,28 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
/* (temporal) security: never much more faces than vertices */
totface = 0;
- maxface = 2 * verts; /* 2*verts: based at a filled circle within a triangle */
+ if (flag & BLI_SCANFILL_CALC_HOLES) {
+ maxface = 2 * verts; /* 2*verts: based at a filled circle within a triangle */
+ }
+ else {
+ maxface = verts - 2; /* when we don't calc any holes, we assume face is a non overlapping loop */
+ }
sc = sf_ctx->_scdata;
for (a = 0; a < verts; a++) {
- /* printf("VERTEX %d %x\n",a,sc->v1); */
+ /* printf("VERTEX %d index %d\n", a, sc->vert->tmp.u); */
ed1 = sc->edge_first;
while (ed1) { /* set connectflags */
nexted = ed1->next;
- if (ed1->v1->h == 1 || ed1->v2->h == 1) {
+ if (ed1->v1->edge_tot == 1 || ed1->v2->edge_tot == 1) {
BLI_remlink((ListBase *)&(sc->edge_first), ed1);
BLI_addtail(&sf_ctx->filledgebase, ed1);
- if (ed1->v1->h > 1) ed1->v1->h--;
- if (ed1->v2->h > 1) ed1->v2->h--;
+ if (ed1->v1->edge_tot > 1) ed1->v1->edge_tot--;
+ if (ed1->v2->edge_tot > 1) ed1->v2->edge_tot--;
+ }
+ else {
+ ed1->v2->f = SF_VERT_AVAILABLE;
}
- else ed1->v2->f = SF_VERT_UNKNOWN;
ed1 = nexted;
}
@@ -654,7 +664,7 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
/* commented out... the ESC here delivers corrupted memory (and doesnt work during grab) */
/* if (callLocalInterruptCallBack()) break; */
- if (totface > maxface) {
+ if (totface >= maxface) {
/* printf("Fill error: endless loop. Escaped at vert %d, tot: %d.\n", a, verts); */
a = verts;
break;
@@ -664,83 +674,112 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
/* printf("just 1 edge to vert\n"); */
BLI_addtail(&sf_ctx->filledgebase, ed1);
ed1->v2->f = 0;
- ed1->v1->h--;
- ed1->v2->h--;
+ ed1->v1->edge_tot--;
+ ed1->v2->edge_tot--;
}
else {
/* test rest of vertices */
+ ScanFillVertLink *best_sc = NULL;
+ float best_angle = 3.14f;
float miny;
+ bool firsttime = false;
+
v1 = ed1->v2;
v2 = ed1->v1;
v3 = ed2->v2;
+
/* this happens with a serial of overlapping edges */
if (v1 == v2 || v2 == v3) break;
- /* printf("test verts %x %x %x\n",v1,v2,v3); */
+
+ /* printf("test verts %d %d %d\n", v1->tmp.u, v2->tmp.u, v3->tmp.u); */
miny = min_ff(v1->xy[1], v3->xy[1]);
- /* miny = min_ff(v1->xy[1],v3->xy[1]); */
sc1 = sc + 1;
- test = 0;
- for (b = a + 1; b < verts; b++) {
+ for (b = a + 1; b < verts; b++, sc1++) {
if (sc1->vert->f == 0) {
if (sc1->vert->xy[1] <= miny) break;
-
- if (testedgeside(v1->xy, v2->xy, sc1->vert->xy))
- if (testedgeside(v2->xy, v3->xy, sc1->vert->xy))
+ if (testedgeside(v1->xy, v2->xy, sc1->vert->xy)) {
+ if (testedgeside(v2->xy, v3->xy, sc1->vert->xy)) {
if (testedgeside(v3->xy, v1->xy, sc1->vert->xy)) {
- /* point in triangle */
-
- test = 1;
- break;
+ /* point is in triangle */
+
+ /* because multiple points can be inside triangle (concave holes) */
+ /* we continue searching and pick the one with sharpest corner */
+
+ if (best_sc == NULL) {
+ best_sc = sc1;
+ /* only need to continue checking with holes */
+ if ((flag & BLI_SCANFILL_CALC_HOLES) == 0) {
+ break;
+ }
+ }
+ else {
+ float angle;
+
+ /* prevent angle calc for the simple cases only 1 vertex is found */
+ if (firsttime == false) {
+ best_angle = angle_v2v2v2(v2->co, v1->co, best_sc->vert->co);
+ firsttime = true;
+ }
+
+ angle = angle_v2v2v2(v2->co, v1->co, sc1->vert->co);
+ if (angle < best_angle) {
+ best_sc = sc1;
+ best_angle = angle;
+ }
+ }
+
}
+ }
+ }
}
- sc1++;
}
- if (test) {
+
+ if (best_sc) {
/* make new edge, and start over */
- /* printf("add new edge %x %x and start again\n",v2,sc1->vert); */
+ /* printf("add new edge %d %d and start again\n", v2->tmp.u, best_sc->vert->tmp.u); */
- ed3 = BLI_scanfill_edge_add(sf_ctx, v2, sc1->vert);
+ ed3 = BLI_scanfill_edge_add(sf_ctx, v2, best_sc->vert);
BLI_remlink(&sf_ctx->filledgebase, ed3);
BLI_insertlinkbefore((ListBase *)&(sc->edge_first), ed2, ed3);
- ed3->v2->f = SF_VERT_UNKNOWN;
+ ed3->v2->f = SF_VERT_AVAILABLE;
ed3->f = SF_EDGE_UNKNOWN;
- ed3->v1->h++;
- ed3->v2->h++;
+ ed3->v1->edge_tot++;
+ ed3->v2->edge_tot++;
}
else {
/* new triangle */
- /* printf("add face %x %x %x\n",v1,v2,v3); */
+ /* printf("add face %d %d %d\n", v1->tmp.u, v2->tmp.u, v3->tmp.u); */
addfillface(sf_ctx, v1, v2, v3);
totface++;
BLI_remlink((ListBase *)&(sc->edge_first), ed1);
BLI_addtail(&sf_ctx->filledgebase, ed1);
ed1->v2->f = 0;
- ed1->v1->h--;
- ed1->v2->h--;
+ ed1->v1->edge_tot--;
+ ed1->v2->edge_tot--;
/* ed2 can be removed when it's a boundary edge */
if ((ed2->f == 0 && twoconnected) || (ed2->f == SF_EDGE_BOUNDARY)) {
BLI_remlink((ListBase *)&(sc->edge_first), ed2);
BLI_addtail(&sf_ctx->filledgebase, ed2);
ed2->v2->f = 0;
- ed2->v1->h--;
- ed2->v2->h--;
+ ed2->v1->edge_tot--;
+ ed2->v2->edge_tot--;
}
/* new edge */
ed3 = BLI_scanfill_edge_add(sf_ctx, v1, v3);
BLI_remlink(&sf_ctx->filledgebase, ed3);
ed3->f = SF_EDGE_UNKNOWN;
- ed3->v1->h++;
- ed3->v2->h++;
+ ed3->v1->edge_tot++;
+ ed3->v2->edge_tot++;
- /* printf("add new edge %x %x\n",v1,v3); */
+ /* printf("add new edge %x %x\n", v1, v3); */
sc1 = addedgetoscanlist(sf_ctx, ed3, verts);
if (sc1) { /* ed3 already exists: remove if a boundary */
/* printf("Edge exists\n"); */
- ed3->v1->h--;
- ed3->v2->h--;
+ ed3->v1->edge_tot--;
+ ed3->v2->edge_tot--;
ed3 = sc1->edge_first;
while (ed3) {
@@ -748,37 +787,41 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag)
if (twoconnected || ed3->f == SF_EDGE_BOUNDARY) {
BLI_remlink((ListBase *)&(sc1->edge_first), ed3);
BLI_addtail(&sf_ctx->filledgebase, ed3);
- ed3->v1->h--;
- ed3->v2->h--;
+ ed3->v1->edge_tot--;
+ ed3->v2->edge_tot--;
}
break;
}
ed3 = ed3->next;
}
}
-
}
}
+
/* test for loose edges */
ed1 = sc->edge_first;
while (ed1) {
nexted = ed1->next;
- if (ed1->v1->h < 2 || ed1->v2->h < 2) {
+ if (ed1->v1->edge_tot < 2 || ed1->v2->edge_tot < 2) {
BLI_remlink((ListBase *)&(sc->edge_first), ed1);
BLI_addtail(&sf_ctx->filledgebase, ed1);
- if (ed1->v1->h > 1) ed1->v1->h--;
- if (ed1->v2->h > 1) ed1->v2->h--;
+ if (ed1->v1->edge_tot > 1) ed1->v1->edge_tot--;
+ if (ed1->v2->edge_tot > 1) ed1->v2->edge_tot--;
}
ed1 = nexted;
}
+ /* done with loose edges */
}
+
sc++;
}
MEM_freeN(sf_ctx->_scdata);
sf_ctx->_scdata = NULL;
+ BLI_assert(totface <= maxface);
+
return totface;
}
@@ -820,7 +863,7 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
while (eve) {
eve->f = 0;
eve->poly_nr = 0;
- eve->h = 0;
+ eve->edge_tot = 0;
eve = eve->next;
a += 1;
}
@@ -858,15 +901,15 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
eed = sf_ctx->filledgebase.first;
while (eed) {
eed->poly_nr = 0;
- eed->v1->f = SF_VERT_UNKNOWN;
- eed->v2->f = SF_VERT_UNKNOWN;
+ eed->v1->f = SF_VERT_AVAILABLE;
+ eed->v2->f = SF_VERT_AVAILABLE;
eed = eed->next;
}
eve = sf_ctx->fillvertbase.first;
while (eve) {
- if (eve->f & SF_VERT_UNKNOWN) {
+ if (eve->f & SF_VERT_AVAILABLE) {
ok = 1;
break;
}
@@ -910,56 +953,74 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
/* STEP 1: COUNT POLYS */
- eve = sf_ctx->fillvertbase.first;
- while (eve) {
- eve->xy[0] = eve->co[co_x];
- eve->xy[1] = eve->co[co_y];
+ if (flag & BLI_SCANFILL_CALC_HOLES) {
+ eve = sf_ctx->fillvertbase.first;
+ while (eve) {
+ eve->xy[0] = eve->co[co_x];
+ eve->xy[1] = eve->co[co_y];
+
+ /* get first vertex with no poly number */
+ if (eve->poly_nr == 0) {
+ poly++;
+ /* now a sort of select connected */
+ ok = 1;
+ eve->poly_nr = poly;
- /* get first vertex with no poly number */
- if (eve->poly_nr == 0) {
- poly++;
- /* now a sort of select connected */
- ok = 1;
- eve->poly_nr = poly;
-
- while (ok) {
-
- ok = 0;
- toggle++;
- if (toggle & 1) eed = sf_ctx->filledgebase.first;
- else eed = sf_ctx->filledgebase.last;
-
- while (eed) {
- if (eed->v1->poly_nr == 0 && eed->v2->poly_nr == poly) {
- eed->v1->poly_nr = poly;
- eed->poly_nr = poly;
- ok = 1;
- }
- else if (eed->v2->poly_nr == 0 && eed->v1->poly_nr == poly) {
- eed->v2->poly_nr = poly;
- eed->poly_nr = poly;
- ok = 1;
- }
- else if (eed->poly_nr == 0) {
- if (eed->v1->poly_nr == poly && eed->v2->poly_nr == poly) {
+ while (ok) {
+
+ ok = 0;
+ toggle++;
+ if (toggle & 1) eed = sf_ctx->filledgebase.first;
+ else eed = sf_ctx->filledgebase.last;
+
+ while (eed) {
+ if (eed->v1->poly_nr == 0 && eed->v2->poly_nr == poly) {
+ eed->v1->poly_nr = poly;
eed->poly_nr = poly;
ok = 1;
}
+ else if (eed->v2->poly_nr == 0 && eed->v1->poly_nr == poly) {
+ eed->v2->poly_nr = poly;
+ eed->poly_nr = poly;
+ ok = 1;
+ }
+ else if (eed->poly_nr == 0) {
+ if (eed->v1->poly_nr == poly && eed->v2->poly_nr == poly) {
+ eed->poly_nr = poly;
+ ok = 1;
+ }
+ }
+ if (toggle & 1) eed = eed->next;
+ else eed = eed->prev;
}
- if (toggle & 1) eed = eed->next;
- else eed = eed->prev;
}
}
+ eve = eve->next;
+ }
+ /* printf("amount of poly's: %d\n", poly); */
+ }
+ else {
+ poly = 1;
+
+ eve = sf_ctx->fillvertbase.first;
+ while (eve) {
+ eve->xy[0] = eve->co[co_x];
+ eve->xy[1] = eve->co[co_y];
+ eve->poly_nr = poly;
+ eve = eve->next;
+ }
+ eed = sf_ctx->filledgebase.first;
+ while (eed) {
+ eed->poly_nr = poly;
+ eed = eed->next;
}
- eve = eve->next;
}
- /* printf("amount of poly's: %d\n",poly); */
/* STEP 2: remove loose edges and strings of edges */
eed = sf_ctx->filledgebase.first;
while (eed) {
- if (eed->v1->h++ > 250) break;
- if (eed->v2->h++ > 250) break;
+ if (eed->v1->edge_tot++ > 250) break;
+ if (eed->v2->edge_tot++ > 250) break;
eed = eed->next;
}
if (eed) {
@@ -980,14 +1041,14 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
while (eed) {
if (toggle & 1) nexted = eed->next;
else nexted = eed->prev;
- if (eed->v1->h == 1) {
- eed->v2->h--;
+ if (eed->v1->edge_tot == 1) {
+ eed->v2->edge_tot--;
BLI_remlink(&sf_ctx->fillvertbase, eed->v1);
BLI_remlink(&sf_ctx->filledgebase, eed);
ok = 1;
}
- else if (eed->v2->h == 1) {
- eed->v1->h--;
+ else if (eed->v2->edge_tot == 1) {
+ eed->v1->edge_tot--;
BLI_remlink(&sf_ctx->fillvertbase, eed->v2);
BLI_remlink(&sf_ctx->filledgebase, eed);
ok = 1;
@@ -1002,13 +1063,13 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
/* CURRENT STATUS:
- * - eve->f :1 = available in edges
- * - eve->xs :polynumber
- * - eve->h :amount of edges connected to vertex
- * - eve->tmp.v :store! original vertex number
+ * - eve->f :1 = available in edges
+ * - eve->poly_nr :polynumber
+ * - eve->edge_tot :amount of edges connected to vertex
+ * - eve->tmp.v :store! original vertex number
*
- * - eed->f :1 = boundary edge (optionally set by caller)
- * - eed->poly_nr :poly number
+ * - eed->f :1 = boundary edge (optionally set by caller)
+ * - eed->poly_nr :poly number
*/
@@ -1037,7 +1098,7 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no
min_xy_p[1] = (min_xy_p[1]) < (eve->xy[1]) ? (min_xy_p[1]) : (eve->xy[1]);
max_xy_p[0] = (max_xy_p[0]) > (eve->xy[0]) ? (max_xy_p[0]) : (eve->xy[0]);
max_xy_p[1] = (max_xy_p[1]) > (eve->xy[1]) ? (max_xy_p[1]) : (eve->xy[1]);
- if (eve->h > 2) pflist[eve->poly_nr - 1].f = 1;
+ if (eve->edge_tot > 2) pflist[eve->poly_nr - 1].f = 1;
eve = eve->next;
}
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index 1358fdd2a62..71cd5e529a2 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -71,6 +71,7 @@
#ifdef WIN32
# include <io.h>
# include <direct.h>
+# include <limits.h> /* PATH_MAX */
# include "BLI_winstuff.h"
# include "utfconv.h"
#else
@@ -91,14 +92,14 @@
#include "BLI_fileops_types.h"
#include "BLI_path_util.h"
-/* vars: */
-static int totnum, actnum;
-static struct direntry *files;
+#include "../imbuf/IMB_imbuf.h"
-static struct ListBase dirbase_ = {NULL, NULL};
-static struct ListBase *dirbase = &dirbase_;
-
-/* can return NULL when the size is not big enough */
+/**
+ * Copies the current working directory into *dir (max size maxncpy), and
+ * returns a pointer to same.
+ *
+ * \note can return NULL when the size is not big enough
+ */
char *BLI_current_working_dir(char *dir, const size_t maxncpy)
{
const char *pwd = getenv("PWD");
@@ -110,26 +111,33 @@ 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);
@@ -139,7 +147,10 @@ static int bli_compare(struct direntry *entry1, struct direntry *entry2)
return (BLI_natstrcmp(entry1->relname, entry2->relname));
}
-
+/**
+ * Returns the number of free bytes on the volume containing the specified pathname. */
+/* Not actually used anywhere.
+ */
double BLI_dir_free_space(const char *dir)
{
#ifdef WIN32
@@ -180,7 +191,9 @@ double BLI_dir_free_space(const char *dir)
slash = strrchr(name, '/');
if (slash) slash[1] = 0;
}
- else strcpy(name, "/");
+ else {
+ strcpy(name, "/");
+ }
#if defined(__FreeBSD__) || defined(linux) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__GNU__) || defined(__GLIBC__)
if (statfs(name, &disk)) return(-1);
@@ -197,89 +210,77 @@ double BLI_dir_free_space(const char *dir)
#endif
}
-static void bli_builddir(const char *dirname, const char *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 dirent *fname;
- struct dirlink *dlink;
- int rellen, newnum = 0;
- char buf[256];
+ struct ListBase dirbase = {NULL, NULL};
+ int newnum = 0;
DIR *dir;
- BLI_strncpy(buf, relname, sizeof(buf));
- rellen = strlen(relname);
-
- if (rellen) {
- buf[rellen] = '/';
- rellen++;
- }
-#ifndef WIN32
- if (chdir(dirname) == -1) {
- perror(dirname);
- return;
- }
-#else
- UTF16_ENCODE(dirname);
- if (!SetCurrentDirectoryW(dirname_16)) {
- perror(dirname);
- free(dirname_16);
- return;
- }
- UTF16_UN_ENCODE(dirname);
+ if ((dir = opendir(dirname)) != NULL) {
-#endif
- if ((dir = (DIR *)opendir("."))) {
- while ((fname = (struct dirent *) readdir(dir)) != NULL) {
- dlink = (struct dirlink *)malloc(sizeof(struct dirlink));
- if (dlink) {
- BLI_strncpy(buf + rellen, fname->d_name, sizeof(buf) - rellen);
- dlink->name = BLI_strdup(buf);
- BLI_addhead(dirbase, dlink);
+ 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 (files) {
- void *tmp = realloc(files, (totnum + newnum) * sizeof(struct direntry));
+ if (dir_ctx->files) {
+ void * const tmp = realloc(dir_ctx->files, (dir_ctx->nrfiles + newnum) * sizeof(struct direntry));
if (tmp) {
- files = (struct direntry *)tmp;
+ dir_ctx->files = (struct direntry *)tmp;
}
else { /* realloc fail */
- free(files);
- files = NULL;
+ free(dir_ctx->files);
+ dir_ctx->files = NULL;
}
}
- if (files == NULL)
- files = (struct direntry *)malloc(newnum * sizeof(struct direntry));
+ if (dir_ctx->files == NULL)
+ dir_ctx->files = (struct direntry *)malloc(newnum * sizeof(struct direntry));
- if (files) {
- dlink = (struct dirlink *) dirbase->first;
+ if (dir_ctx->files) {
+ struct dirlink * dlink = (struct dirlink *) dirbase.first;
+ struct direntry *file = &dir_ctx->files[dir_ctx->nrfiles];
while (dlink) {
- memset(&files[actnum], 0, sizeof(struct direntry));
- files[actnum].relname = dlink->name;
- files[actnum].path = BLI_strdupcat(dirname, dlink->name);
+ 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);
// use 64 bit file size, only needed for WIN32 and WIN64.
// Excluding other than current MSVC compiler until able to test
#ifdef WIN32
{
- wchar_t *name_16 = alloc_utf16_from_8(dlink->name, 0);
-#if (defined(WIN32) || defined(WIN64)) && (_MSC_VER >= 1500)
- _wstat64(name_16, &files[actnum].s);
+ wchar_t *name_16 = alloc_utf16_from_8(fullname, 0);
+#if defined(_MSC_VER) && (_MSC_VER >= 1500)
+ _wstat64(name_16, &file->s);
#elif defined(__MINGW32__)
- _stati64(dlink->name, &files[actnum].s);
+ _stati64(fullname, &file->s);
#endif
free(name_16);
}
#else
- stat(dlink->name, &files[actnum].s);
+ stat(fullname, &file->s);
#endif
- files[actnum].type = files[actnum].s.st_mode;
- files[actnum].flags = 0;
- totnum++;
- actnum++;
+ file->type = file->s.st_mode;
+ file->flags = 0;
+ dir_ctx->nrfiles++;
+ file++;
dlink = dlink->next;
}
}
@@ -288,8 +289,10 @@ static void bli_builddir(const char *dirname, const char *relname)
exit(1);
}
- BLI_freelist(dirbase);
- if (files) qsort(files, actnum, sizeof(struct direntry), (int (*)(const void *, const void *))bli_compare);
+ 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);
@@ -302,12 +305,17 @@ static void bli_builddir(const char *dirname, const char *relname)
}
}
-static void bli_adddirstrings(void)
+/**
+ * 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)
{
char datum[100];
- char buf[512];
+// char buf[512]; // UNUSED
char size[250];
- static const char *types[8] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"};
+ const char *types[8] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"};
+ /* symbolic display, indexed by mode field value */
int num, mode;
#ifdef WIN32
__int64 st_size;
@@ -319,7 +327,7 @@ static void bli_adddirstrings(void)
struct tm *tm;
time_t zero = 0;
- for (num = 0, file = files; num < actnum; num++, file++) {
+ for (num = 0, file = dir_ctx->files; num < dir_ctx->nrfiles; num++, file++) {
#ifdef WIN32
mode = 0;
BLI_strncpy(file->mode1, types[0], sizeof(file->mode1));
@@ -330,7 +338,7 @@ static void bli_adddirstrings(void)
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));
+ BLI_strncpy(file->mode3, types[(mode & 0007)], sizeof(file->mode3));
if (((mode & S_ISGID) == S_ISGID) && (file->mode2[2] == '-')) file->mode2[2] = 'l';
@@ -375,6 +383,9 @@ static void bli_adddirstrings(void)
*/
st_size = file->s.st_size;
+ /* FIXME: Either change decimal prefixes to binary ones
+ * <http://en.wikipedia.org/wiki/Binary_prefix>, or change
+ * divisor factors from 1024 to 1000. */
if (st_size > 1024 * 1024 * 1024) {
BLI_snprintf(file->size, sizeof(file->size), "%.2f GB", ((double)st_size) / (1024 * 1024 * 1024));
}
@@ -408,61 +419,86 @@ static void bli_adddirstrings(void)
BLI_snprintf(size, sizeof(size), "%10d", (int) st_size);
}
+#if 0
BLI_snprintf(buf, sizeof(buf), "%s %s %s %7s %s %s %10s %s",
file->mode1, file->mode2, file->mode3, file->owner,
file->date, file->time, size, file->relname);
-
- file->string = BLI_strdup(buf);
+#endif
}
}
+/**
+ * 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)
{
- /* reset global variables
- * memory stored in files is free()'d in
- * filesel.c:freefilelist() */
+ struct BuildDirCtx dir_ctx;
- actnum = totnum = 0;
- files = NULL;
+ dir_ctx.nrfiles = 0;
+ dir_ctx.files = NULL;
- bli_builddir(dirname, "");
- bli_adddirstrings();
+ bli_builddir(&dir_ctx, dirname);
+ bli_adddirstrings(&dir_ctx);
- if (files) {
- *(filelist) = files;
+ if (dir_ctx.files) {
+ *filelist = dir_ctx.files;
}
else {
// keep blender happy. Blender stores this in a variable
// where 0 has special meaning.....
- *(filelist) = files = malloc(sizeof(struct direntry));
+ *filelist = malloc(sizeof(struct direntry));
}
- return(actnum);
+ 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.
+ */
size_t BLI_file_descriptor_size(int file)
{
- struct stat buf;
-
- if (file <= 0) return (-1);
- fstat(file, &buf); /* CHANGE */
- return (buf.st_size);
+ struct stat st;
+ if ((file < 0) || (fstat(file, &st) == -1))
+ return -1;
+ return st.st_size;
}
+/**
+ * Returns the size of a file.
+ */
size_t BLI_file_size(const char *path)
{
- int size, file = BLI_open(path, O_BINARY | O_RDONLY, 0);
-
- if (file == -1)
+ struct stat stats;
+ if (BLI_stat(path, &stats) == -1)
return -1;
-
- size = BLI_file_descriptor_size(file);
- close(file);
- return size;
+ return stats.st_size;
}
-
+/**
+ * Returns the st_mode from statting the specified path name, or 0 if it couldn't be statted
+ * (most likely doesn't exist or no access).
+ */
int BLI_exists(const char *name)
{
#if defined(WIN32)
@@ -509,18 +545,27 @@ int BLI_stat(const char *path, struct stat *buffer)
}
#endif
-/* would be better in fileops.c except that it needs stat.h so add here */
-int BLI_is_dir(const char *file)
+/**
+ * Does the specified path point to a directory?
+ * \note Would be better in fileops.c except that it needs stat.h so add here
+ */
+bool BLI_is_dir(const char *file)
{
return S_ISDIR(BLI_exists(file));
}
-int BLI_is_file(const char *path)
+/**
+ * Does the specified path point to a non-directory?
+ */
+bool BLI_is_file(const char *path)
{
- int mode = BLI_exists(path);
+ const int mode = BLI_exists(path);
return (mode && !S_ISDIR(mode));
}
+/**
+ * Reads the contents of a text file and returns the lines in a linked list.
+ */
LinkNode *BLI_file_read_as_lines(const char *name)
{
FILE *fp = BLI_fopen(name, "r");
@@ -549,6 +594,9 @@ LinkNode *BLI_file_read_as_lines(const char *name)
char *line = BLI_strdupn(&buf[last], i - last);
BLI_linklist_prepend(&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 */
last = i + 1;
}
}
@@ -557,18 +605,22 @@ LinkNode *BLI_file_read_as_lines(const char *name)
}
fclose(fp);
-
+
+ /* get them the right way round */
BLI_linklist_reverse(&lines);
return lines;
}
+/*
+ * Frees memory from a previous call to BLI_file_read_as_lines.
+ */
void BLI_file_free_lines(LinkNode *lines)
{
- BLI_linklist_free(lines, (void (*)(void *))MEM_freeN);
+ BLI_linklist_freeN(lines);
}
/** is file1 older then file2 */
-int BLI_file_older(const char *file1, const char *file2)
+bool BLI_file_older(const char *file1, const char *file2)
{
#ifdef WIN32
struct _stat st1, st2;
@@ -576,16 +628,16 @@ int BLI_file_older(const char *file1, const char *file2)
UTF16_ENCODE(file1);
UTF16_ENCODE(file2);
- if (_wstat(file1_16, &st1)) return 0;
- if (_wstat(file2_16, &st2)) return 0;
+ if (_wstat(file1_16, &st1)) return false;
+ if (_wstat(file2_16, &st2)) return false;
UTF16_UN_ENCODE(file2);
UTF16_UN_ENCODE(file1);
#else
struct stat st1, st2;
- if (stat(file1, &st1)) return 0;
- if (stat(file2, &st2)) return 0;
+ if (stat(file1, &st1)) return false;
+ if (stat(file2, &st2)) return false;
#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 f23f75f69d9..906a3095f91 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -43,6 +43,15 @@
#include "BLI_utildefines.h"
+/**
+ * Duplicates the first \a len bytes of cstring \a str
+ * into a newly mallocN'd string and returns it. \a str
+ * is assumed to be at least len bytes long.
+ *
+ * \param str The string to be duplicated
+ * \param len The number of bytes to duplicate
+ * \retval Returns the duplicated string
+ */
char *BLI_strdupn(const char *str, const size_t len)
{
char *n = MEM_mallocN(len + 1, "strdup");
@@ -51,11 +60,25 @@ char *BLI_strdupn(const char *str, const size_t len)
return n;
}
+
+/**
+ * Duplicates the cstring \a str into a newly mallocN'd
+ * string and returns it.
+ *
+ * \param str The string to be duplicated
+ * \retval Returns the duplicated string
+ */
char *BLI_strdup(const char *str)
{
return BLI_strdupn(str, strlen(str));
}
+/**
+ * Appends the two strings, and returns new mallocN'ed string
+ * \param str1 first string for copy
+ * \param str2 second string for append
+ * \retval Returns dst
+ */
char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2)
{
size_t len;
@@ -69,18 +92,52 @@ char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2)
return n;
}
+/**
+ * Like strncpy but ensures dst is always
+ * '\0' terminated.
+ *
+ * \param dst Destination for copy
+ * \param src Source string to copy
+ * \param maxncpy Maximum number of characters to copy (generally
+ * the size of dst)
+ * \retval Returns dst
+ */
char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy)
{
- size_t srclen = strlen(src);
- size_t cpylen = (srclen > (maxncpy - 1)) ? (maxncpy - 1) : srclen;
+ size_t srclen = BLI_strnlen(src, maxncpy - 1);
BLI_assert(maxncpy != 0);
-
- memcpy(dst, src, cpylen);
- dst[cpylen] = '\0';
-
+
+ memcpy(dst, src, srclen);
+ dst[srclen] = '\0';
return dst;
}
+/**
+ * Like strncpy but ensures dst is always
+ * '\0' terminated.
+ *
+ * \note This is a duplicate of #BLI_strncpy that returns bytes copied.
+ * And is a drop in replacement for 'snprintf(str, sizeof(str), "%s", arg);'
+ *
+ * \param dst Destination for copy
+ * \param src Source string to copy
+ * \param maxncpy Maximum number of characters to copy (generally
+ * the size of dst)
+ * \retval The number of bytes copied (The only difference from BLI_strncpy).
+ */
+size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, const size_t maxncpy)
+{
+ size_t srclen = BLI_strnlen(src, maxncpy - 1);
+ BLI_assert(maxncpy != 0);
+
+ memcpy(dst, src, srclen);
+ dst[srclen] = '\0';
+ return srclen;
+}
+
+/**
+ * Portable replacement for #vsnprintf
+ */
size_t BLI_vsnprintf(char *__restrict buffer, size_t count, const char *__restrict format, va_list arg)
{
size_t n;
@@ -101,6 +158,9 @@ size_t BLI_vsnprintf(char *__restrict buffer, size_t count, const char *__restri
return n;
}
+/**
+ * Portable replacement for #snprintf
+ */
size_t BLI_snprintf(char *__restrict buffer, size_t count, const char *__restrict format, ...)
{
size_t n;
@@ -113,6 +173,10 @@ size_t BLI_snprintf(char *__restrict buffer, size_t count, const char *__restric
return n;
}
+/**
+ * Print formatted string into a newly #MEM_mallocN'd string
+ * and return it.
+ */
char *BLI_sprintfN(const char *__restrict format, ...)
{
DynStr *ds;
@@ -180,17 +244,17 @@ escape_finish:
return len;
}
-
-/* Makes a copy of the text within the "" that appear after some text 'blahblah'
+/**
+ * Makes a copy of the text within the "" that appear after some text 'blahblah'
* i.e. for string 'pose["apples"]' with prefix 'pose[', it should grab "apples"
- *
- * - str: is the entire string to chop
- * - prefix: is the part of the string to leave out
*
- * Assume that the strings returned must be freed afterwards, and that the inputs will contain
+ * - str: is the entire string to chop
+ * - prefix: is the part of the string to leave out
+ *
+ * Assume that the strings returned must be freed afterwards, and that the inputs will contain
* data we want...
*
- * TODO, return the offset and a length so as to avoid doing an allocation.
+ * \return the offset and a length so as to avoid doing an allocation.
*/
char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix)
{
@@ -199,20 +263,30 @@ char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict
/* 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;
-
- /* get the end point (i.e. where the next occurance of " is after the starting point) */
- endMatch = strchr(startMatch, '"'); /* " NOTE: this comment here is just so that my text editor still shows the functions ok... */
-
- /* return the slice indicated */
- return BLI_strdupn(startMatch, (size_t)(endMatch - startMatch));
+ if (startMatch) {
+ /* get the end point (i.e. where the next occurance of " is after the starting point) */
+ endMatch = strchr(startMatch, '"'); /* " NOTE: this comment here is just so that my text editor still shows the functions ok... */
+
+ if (endMatch)
+ /* return the slice indicated */
+ return BLI_strdupn(startMatch, (size_t)(endMatch - startMatch));
+ }
+ return BLI_strdupn("", 0);
}
-/* Replaces all occurrences of oldText with newText in str, returning a new string that doesn't
- * contain the 'replaced' occurrences.
+/**
+ * Returns a copy of the cstring \a str into a newly mallocN'd
+ * string with all instances of oldText replaced with newText,
+ * and returns it.
+ *
+ * \note A rather wasteful string-replacement utility, though this shall do for now...
+ * Feel free to replace this with an even safe + nicer alternative
+ *
+ * \param str The string to replace occurrences of oldText in
+ * \param oldText The text in the string to find and replace
+ * \param newText The text in the string to find and replace
+ * \retval Returns the duplicated string
*/
-
-/* A rather wasteful string-replacement utility, though this shall do for now...
- * Feel free to replace this with an even safe + nicer alternative */
char *BLI_replacestr(char *__restrict str, const char *__restrict oldText, const char *__restrict newText)
{
DynStr *ds = NULL;
@@ -279,12 +353,19 @@ char *BLI_replacestr(char *__restrict str, const char *__restrict oldText, const
}
}
+/**
+ * Compare two strings without regard to case.
+ *
+ * \retval True if the strings are equal, false otherwise.
+ */
int BLI_strcaseeq(const char *a, const char *b)
{
return (BLI_strcasecmp(a, b) == 0);
}
-/* strcasestr not available in MSVC */
+/**
+ * Portable replacement for #strcasestr (not available in MSVC)
+ */
char *BLI_strcasestr(const char *s, const char *find)
{
register char c, sc;
@@ -412,7 +493,7 @@ int BLI_natstrcmp(const char *s1, const char *s2)
void BLI_timestr(double _time, char *str)
{
/* format 00:00:00.00 (hr:min:sec) string has to be 12 long */
- int hr = ( (int) _time) / (60*60);
+ int hr = ( (int) _time) / (60 * 60);
int min = (((int) _time) / 60 ) % 60;
int sec = ( (int) (_time)) % 60;
int hun = ( (int) (_time * 100.0)) % 100;
@@ -428,10 +509,15 @@ void BLI_timestr(double _time, char *str)
}
/* determine the length of a fixed-size string */
-size_t BLI_strnlen(const char *str, const size_t maxlen)
+size_t BLI_strnlen(const char *s, size_t maxlen)
{
- const char *end = memchr(str, '\0', maxlen);
- return end ? (size_t) (end - str) : maxlen;
+ size_t len;
+
+ for (len = 0; len < maxlen; len++, s++) {
+ if (!*s)
+ break;
+ }
+ return len;
}
void BLI_ascii_strtolower(char *str, const size_t len)
@@ -451,3 +537,31 @@ void BLI_ascii_strtoupper(char *str, const size_t len)
if (str[i] >= 'a' && str[i] <= 'z')
str[i] -= 'a' - 'A';
}
+
+/**
+ * Strip trailing zeros from a float, eg:
+ * 0.0000 -> 0.0
+ * 2.0010 -> 2.001
+ *
+ * \param str
+ * \param len
+ * \return The number of zeto's stripped.
+ */
+int BLI_str_rstrip_float_zero(char *str, const char pad)
+{
+ char *p = strchr(str, '.');
+ int totstrip = 0;
+ if (p) {
+ char *end_p;
+ p++; /* position at first decimal place */
+ end_p = p + (strlen(p) - 1); /* position at last character */
+ if (end_p > p) {
+ while (end_p != p && *end_p == '0') {
+ *end_p = pad;
+ end_p--;
+ }
+ }
+ }
+
+ return totstrip;
+}
diff --git a/source/blender/blenlib/intern/string_cursor_utf8.c b/source/blender/blenlib/intern/string_cursor_utf8.c
index 65763f21b0f..674d5ae5c8d 100644
--- a/source/blender/blenlib/intern/string_cursor_utf8.c
+++ b/source/blender/blenlib/intern/string_cursor_utf8.c
@@ -139,12 +139,17 @@ int BLI_str_cursor_step_prev_utf8(const char *str, size_t UNUSED(maxlen), int *p
void BLI_str_cursor_step_utf8(const char *str, size_t maxlen,
int *pos, strCursorJumpDirection direction,
- strCursorJumpType jump)
+ strCursorJumpType jump, bool use_init_step)
{
const int pos_prev = *pos;
if (direction == STRCUR_DIR_NEXT) {
- BLI_str_cursor_step_next_utf8(str, maxlen, pos);
+ if (use_init_step) {
+ BLI_str_cursor_step_next_utf8(str, maxlen, pos);
+ }
+ else {
+ BLI_assert(jump == STRCUR_JUMP_DELIM);
+ }
if (jump != STRCUR_JUMP_NONE) {
const strCursorDelimType delim_type = (*pos) < maxlen ? cursor_delim_type(&str[*pos]) : STRCUR_DELIM_NONE;
@@ -163,7 +168,12 @@ void BLI_str_cursor_step_utf8(const char *str, size_t maxlen,
}
}
else if (direction == STRCUR_DIR_PREV) {
- BLI_str_cursor_step_prev_utf8(str, maxlen, pos);
+ if (use_init_step) {
+ BLI_str_cursor_step_prev_utf8(str, maxlen, pos);
+ }
+ else {
+ BLI_assert(jump == STRCUR_JUMP_DELIM);
+ }
if (jump != STRCUR_JUMP_NONE) {
const strCursorDelimType delim_type = (*pos) > 1 ? cursor_delim_type(&str[(*pos) - 1]) : STRCUR_DELIM_NONE;
diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c
index bf98f2ae77c..fe8f3c20ab4 100644
--- a/source/blender/blenlib/intern/string_utf8.c
+++ b/source/blender/blenlib/intern/string_utf8.c
@@ -33,6 +33,7 @@
#include <string.h>
#include <wchar.h>
#include <wctype.h>
+#include <wcwidth.h>
#include <stdio.h>
#include <stdlib.h>
@@ -114,7 +115,7 @@ int BLI_utf8_invalid_byte(const char *str, int length)
/* Check for valid bytes after the 2nd, if any; all must start 10 */
while (--ab > 0) {
- if ((*(p+1) & 0xc0) != 0x80) goto utf8_error;
+ if ((*(p + 1) & 0xc0) != 0x80) goto utf8_error;
p++; /* do this after so we get usable offset - campbell */
}
}
@@ -317,6 +318,42 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w, const char *__rest
/* end wchar_t / utf8 functions */
/* --------------------------------------------------------------------------*/
+/* count columns that character/string occupies, based on wcwidth.c */
+
+int BLI_wcwidth(wchar_t ucs)
+{
+ return mk_wcwidth(ucs);
+}
+
+int BLI_wcswidth(const wchar_t *pwcs, size_t n)
+{
+ return mk_wcswidth(pwcs, n);
+}
+
+int BLI_str_utf8_char_width(const char *p)
+{
+ unsigned int unicode = BLI_str_utf8_as_unicode(p);
+ if (unicode == BLI_UTF8_ERR)
+ return -1;
+
+ return BLI_wcwidth((wchar_t)unicode);
+}
+
+int BLI_str_utf8_char_width_safe(const char *p)
+{
+ int columns;
+
+ unsigned int unicode = BLI_str_utf8_as_unicode(p);
+ if (unicode == BLI_UTF8_ERR)
+ return 1;
+
+ columns = BLI_wcwidth((wchar_t)unicode);
+
+ return (columns < 0) ? 1 : columns;
+}
+
+/* --------------------------------------------------------------------------*/
+
/* copied from glib's gutf8.c, added 'Err' arg */
/* note, glib uses unsigned int for unicode, best we do the same,
@@ -369,7 +406,7 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w, const char *__rest
int BLI_str_utf8_size(const char *p)
{
int mask = 0, len;
- unsigned char c = (unsigned char) *p;
+ const unsigned char c = (unsigned char) *p;
UTF8_COMPUTE (c, mask, len, -1);
@@ -382,7 +419,7 @@ int BLI_str_utf8_size(const char *p)
int BLI_str_utf8_size_safe(const char *p)
{
int mask = 0, len;
- unsigned char c = (unsigned char) *p;
+ const unsigned char c = (unsigned char) *p;
UTF8_COMPUTE (c, mask, len, 1);
@@ -408,10 +445,10 @@ unsigned int BLI_str_utf8_as_unicode(const char *p)
{
int i, mask = 0, len;
unsigned int result;
- unsigned char c = (unsigned char) *p;
+ const unsigned char c = (unsigned char) *p;
UTF8_COMPUTE (c, mask, len, -1);
- if (len == -1)
+ if (UNLIKELY(len == -1))
return BLI_UTF8_ERR;
UTF8_GET (result, p, i, mask, len, BLI_UTF8_ERR);
@@ -423,16 +460,32 @@ unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *
{
int i, mask = 0, len;
unsigned int result;
- unsigned char c = (unsigned char) *p;
+ const unsigned char c = (unsigned char) *p;
UTF8_COMPUTE (c, mask, len, -1);
- if (len == -1)
+ if (UNLIKELY(len == -1))
return BLI_UTF8_ERR;
UTF8_GET (result, p, i, mask, len, BLI_UTF8_ERR);
*index += len;
return result;
}
+unsigned int BLI_str_utf8_as_unicode_and_size_safe(const char *__restrict p, size_t *__restrict index)
+{
+ int i, mask = 0, len;
+ unsigned int result;
+ const unsigned char c = (unsigned char) *p;
+
+ UTF8_COMPUTE (c, mask, len, -1);
+ if (UNLIKELY(len == -1)) {
+ *index += 1;
+ return c;
+ }
+ UTF8_GET (result, p, i, mask, len, BLI_UTF8_ERR);
+ *index += len;
+ return result;
+}
+
/* another variant that steps over the index,
* note, currently this also falls back to latin1 for text drawing. */
unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index)
@@ -445,7 +498,7 @@ unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__re
c = (unsigned char) *p;
UTF8_COMPUTE (c, mask, len, -1);
- if (len == -1) {
+ if (UNLIKELY(len == -1)) {
/* when called with NULL end, result will never be NULL,
* checks for a NULL character */
char *p_next = BLI_str_find_next_char_utf8(p, NULL);
diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c
index 146e1d531f1..a74f82ae965 100644
--- a/source/blender/blenlib/intern/threads.c
+++ b/source/blender/blenlib/intern/threads.c
@@ -429,12 +429,16 @@ void BLI_spin_unlock(SpinLock *spin)
#endif
}
+#ifndef __APPLE__
void BLI_spin_end(SpinLock *spin)
{
-#ifndef __APPLE__
pthread_spin_destroy(spin);
-#endif
}
+#else
+void BLI_spin_end(SpinLock *UNUSED(spin))
+{
+}
+#endif
/* Read/Write Mutex Lock */
@@ -729,6 +733,9 @@ void BLI_thread_queue_wait_finish(ThreadQueue *queue)
void BLI_begin_threaded_malloc(void)
{
+ /* Used for debug only */
+ /* BLI_assert(thread_levels >= 0); */
+
if (thread_levels == 0) {
MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread);
}
@@ -737,6 +744,9 @@ void BLI_begin_threaded_malloc(void)
void BLI_end_threaded_malloc(void)
{
+ /* Used for debug only */
+ /* BLI_assert(thread_levels >= 0); */
+
thread_levels--;
if (thread_levels == 0)
MEM_set_lock_callback(NULL, NULL);
diff --git a/source/blender/blenlib/intern/voronoi.c b/source/blender/blenlib/intern/voronoi.c
index 601b07c9a5d..7a545090090 100644
--- a/source/blender/blenlib/intern/voronoi.c
+++ b/source/blender/blenlib/intern/voronoi.c
@@ -44,7 +44,7 @@
enum {
voronoiEventType_Site = 0,
voronoiEventType_Circle = 1
-} voronoiEventType;
+};
typedef struct VoronoiEvent {
struct VoronoiEvent *next, *prev;
diff --git a/source/blender/blenlib/intern/winstuff.c b/source/blender/blenlib/intern/winstuff.c
index 68d9d74cca4..d11bee255c2 100644
--- a/source/blender/blenlib/intern/winstuff.c
+++ b/source/blender/blenlib/intern/winstuff.c
@@ -38,15 +38,14 @@
#include <conio.h>
#include "MEM_guardedalloc.h"
-#include "BLI_path_util.h"
-#include "BLI_string.h"
-#include "BKE_global.h"
+#include "../blenkernel/BKE_global.h" /* G.background, bad level include (no function calls) */
#define WIN32_SKIP_HKEY_PROTECTION // need to use HKEY
#include "BLI_winstuff.h"
#include "BLI_utildefines.h"
#include "BLI_path_util.h"
+#include "BLI_string.h"
#include "utf_winfunc.h"
#include "utfconv.h"
@@ -141,7 +140,7 @@ void RegisterBlendExtension(void)
lresult = RegCreateKeyEx(root, ".blend", 0,
NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd);
if (lresult == ERROR_SUCCESS) {
- sprintf(buffer, "%s", "blendfile");
+ strcpy(buffer, "blendfile");
lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1);
RegCloseKey(hkey);
}
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index 16a4d8d46ec..00ff5863e59 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -96,7 +96,7 @@ BlendFileData *BLO_read_from_file(const char *filepath, struct ReportList *repor
* indicating the cause of the failure.
* \return The data of the file.
*/
-BlendFileData *BLO_read_from_memory(void *mem, int memsize, struct ReportList *reports);
+BlendFileData *BLO_read_from_memory(const void *mem, int memsize, struct ReportList *reports);
/**
* oldmain is old main, from which we will keep libraries, images, ..
@@ -122,7 +122,7 @@ BLO_blendfiledata_free(BlendFileData *bfd);
* \return A handle on success, or NULL on failure.
*/
BlendHandle *
-BLO_blendhandle_from_file(char *file,
+BLO_blendhandle_from_file(const char *filepath,
struct ReportList *reports);
/**
@@ -134,7 +134,7 @@ BLO_blendhandle_from_file(char *file,
*/
BlendHandle *
-BLO_blendhandle_from_memory(void *mem,
+BLO_blendhandle_from_memory(const void *mem,
int memsize);
/**
@@ -240,13 +240,32 @@ struct ID *BLO_library_append_named_part_ex(const struct bContext *C, struct Mai
void BLO_library_append_end(const struct bContext *C, struct Main *mainl, BlendHandle **bh, int idcode, short flag);
+void BLO_library_append_all(struct Main *mainl, BlendHandle *bh);
+
void *BLO_library_read_struct(struct FileData *fd, struct BHead *bh, const char *blockname);
BlendFileData *blo_read_blendafterruntime(int file, const char *name, int actualsize, struct ReportList *reports);
-
+
/* internal function but we need to expose it */
void blo_lib_link_screen_restore(struct Main *newmain, struct bScreen *curscreen, struct Scene *curscene);
+/**
+ * BLO_expand_main() loops over all ID data in Main to mark relations.
+ * Set (id->flag & LIB_NEED_EXPAND) to mark expanding. Flags get cleared after expanding.
+ *
+ * \param expand_doit_func() gets called for each ID block it finds
+ */
+void BLO_main_expander(void (*expand_doit_func)(void *, struct Main *, void *));
+
+/**
+ * BLO_expand_main() loops over all ID data in Main to mark relations.
+ * Set (id->flag & LIB_NEED_EXPAND) to mark expanding. Flags get cleared after expanding.
+ *
+ * \param fdhandle usually filedata, or own handle
+ * \param mainvar the Main database to expand
+ */
+void BLO_expand_main(void *fdhandle, struct Main *mainvar);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt
index 3c5812fa513..5b929195aea 100644
--- a/source/blender/blenloader/CMakeLists.txt
+++ b/source/blender/blenloader/CMakeLists.txt
@@ -52,7 +52,6 @@ set(SRC
BLO_blend_defs.h
BLO_readfile.h
BLO_runtime.h
- BLO_soundfile.h
BLO_sys_types.h
BLO_undofile.h
BLO_writefile.h
diff --git a/source/blender/blenloader/SConscript b/source/blender/blenloader/SConscript
index 49e8869637e..8950c4f7702 100644
--- a/source/blender/blenloader/SConscript
+++ b/source/blender/blenloader/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('intern/*.c')
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index e9caa337129..9678dffe5af 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -74,16 +74,16 @@ void BLO_blendhandle_print_sizes(BlendHandle *, void *);
/* Access routines used by filesel. */
-BlendHandle *BLO_blendhandle_from_file(char *file, ReportList *reports)
+BlendHandle *BLO_blendhandle_from_file(const char *filepath, ReportList *reports)
{
BlendHandle *bh;
- bh = (BlendHandle *)blo_openblenderfile(file, reports);
+ bh = (BlendHandle *)blo_openblenderfile(filepath, reports);
return bh;
}
-BlendHandle *BLO_blendhandle_from_memory(void *mem, int memsize)
+BlendHandle *BLO_blendhandle_from_memory(const void *mem, int memsize)
{
BlendHandle *bh;
@@ -271,7 +271,7 @@ BlendFileData *BLO_read_from_file(const char *filepath, ReportList *reports)
return bfd;
}
-BlendFileData *BLO_read_from_memory(void *mem, int memsize, ReportList *reports)
+BlendFileData *BLO_read_from_memory(const void *mem, int memsize, ReportList *reports)
{
BlendFileData *bfd = NULL;
FileData *fd;
@@ -311,6 +311,8 @@ 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);
+ /* removed packed data from this trick - it's internal data that needs saves */
+
bfd = blo_read_file_internal(fd, filename);
/* ensures relinked images are not freed */
@@ -318,7 +320,7 @@ 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);
-
+
/* 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 203af1d8316..082702f6d9d 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -41,6 +41,7 @@
#include <math.h> // for fabs
#include <stdarg.h> /* for va_start/end */
+#include "BLI_utildefines.h"
#ifndef WIN32
# include <unistd.h> // for read close
#else
@@ -70,6 +71,7 @@
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
#include "DNA_lamp_types.h"
+#include "DNA_linestyle_types.h"
#include "DNA_meta_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
@@ -81,6 +83,7 @@
#include "DNA_packedFile_types.h"
#include "DNA_particle_types.h"
#include "DNA_property_types.h"
+#include "DNA_rigidbody_types.h"
#include "DNA_text_types.h"
#include "DNA_view3d_types.h"
#include "DNA_screen_types.h"
@@ -116,6 +119,7 @@
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_deform.h"
+#include "BKE_depsgraph.h"
#include "BKE_effect.h"
#include "BKE_fcurve.h"
#include "BKE_global.h" // for G
@@ -124,6 +128,7 @@
#include "BKE_lattice.h"
#include "BKE_library.h" // for which_libbase
#include "BKE_idcode.h"
+#include "BKE_idprop.h"
#include "BKE_material.h"
#include "BKE_main.h" // for Main
#include "BKE_mesh.h" // for ME_ defines (patching)
@@ -147,7 +152,11 @@
#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"
@@ -210,20 +219,6 @@
* - initialize FileGlobal and copy pointers to Global
*/
-/* also occurs in library.c */
-/* GS reads the memory pointed at in a specific ordering. There are,
- * however two definitions for it. I have jotted them down here, both,
- * but I think the first one is actually used. The thing is that
- * big-endian systems might read this the wrong way round. OTOH, we
- * constructed the IDs that are read out with this macro explicitly as
- * well. I expect we'll sort it out soon... */
-
-/* from blendef: */
-#define GS(a) (*((short *)(a)))
-
-/* from misc_util: flip the bytes from x */
-/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
-
/***/
typedef struct OldNew {
@@ -389,7 +384,7 @@ static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib)
for (i = 0, entry = onm->entries; i < nentries; i++, entry++) {
if (entry->old == addr) {
- ID *id = id = entry->newp;
+ ID *id = entry->newp;
if (id && (!lib || id->lib)) {
return id;
}
@@ -504,16 +499,6 @@ void blo_split_main(ListBase *mainlist, Main *main)
split_libdata(lbarray[i], main->next);
}
-/* removes things like /blah/blah/../../blah/ etc, then writes in *name the full path */
-static void cleanup_path(const char *relabase, char *name)
-{
- char filename[FILE_MAXFILE];
-
- BLI_splitdirstring(name, filename);
- BLI_cleanup_dir(relabase, name);
- strcat(name, filename);
-}
-
static void read_file_version(FileData *fd, Main *main)
{
BHead *bhead;
@@ -542,8 +527,10 @@ static Main *blo_find_main(FileData *fd, const char *filepath, const char *relab
char name1[FILE_MAX];
BLI_strncpy(name1, filepath, sizeof(name1));
- cleanup_path(relabase, name1);
-// printf("blo_find_main: original in %s\n", name);
+ BLI_cleanup_path(relabase, name1);
+
+// printf("blo_find_main: relabase %s\n", relabase);
+// printf("blo_find_main: original in %s\n", filepath);
// printf("blo_find_main: converted to %s\n", name1);
for (m = mainlist->first; m; m = m->next) {
@@ -839,7 +826,7 @@ static int read_file_dna(FileData *fd)
for (bhead = blo_firstbhead(fd); bhead; bhead = blo_nextbhead(fd, bhead)) {
if (bhead->code == DNA1) {
- int do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) ? 1 : 0;
+ const bool do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
fd->filesdna = DNA_sdna_from_data(&bhead[1], bhead->len, do_endian_swap);
if (fd->filesdna) {
@@ -962,11 +949,11 @@ static FileData *filedata_new(void)
fd->filedes = -1;
fd->gzfiledes = NULL;
- /* XXX, this doesn't need to be done all the time,
- * but it keeps us re-entrant, remove once we have
- * a lib that provides a nice lock. - zr
- */
- fd->memsdna = DNA_sdna_from_data(DNAstr, DNAlen, 0);
+ /* XXX, this doesn't need to be done all the time,
+ * but it keeps us re-entrant, remove once we have
+ * a lib that provides a nice lock. - zr
+ */
+ fd->memsdna = DNA_sdna_from_data(DNAstr, DNAlen, false);
fd->datamap = oldnewmap_new();
fd->globmap = oldnewmap_new();
@@ -1020,7 +1007,47 @@ FileData *blo_openblenderfile(const char *filepath, ReportList *reports)
}
}
-FileData *blo_openblendermemory(void *mem, int memsize, ReportList *reports)
+static int fd_read_gzip_from_memory(FileData *filedata, void *buffer, unsigned int size)
+{
+ int err;
+
+ filedata->strm.next_out = (Bytef *) buffer;
+ filedata->strm.avail_out = size;
+
+ // Inflate another chunk.
+ err = inflate (&filedata->strm, Z_SYNC_FLUSH);
+
+ if (err == Z_STREAM_END) {
+ return 0;
+ }
+ else if (err != Z_OK) {
+ printf("fd_read_gzip_from_memory: zlib error\n");
+ return 0;
+ }
+
+ filedata->seek += size;
+
+ return (size);
+}
+
+static int fd_read_gzip_from_memory_init(FileData *fd)
+{
+
+ fd->strm.next_in = (Bytef *) fd->buffer;
+ fd->strm.avail_in = fd->buffersize;
+ fd->strm.total_out = 0;
+ fd->strm.zalloc = Z_NULL;
+ fd->strm.zfree = Z_NULL;
+
+ if (inflateInit2(&fd->strm, (16+MAX_WBITS)) != Z_OK)
+ return 0;
+
+ fd->read = fd_read_gzip_from_memory;
+
+ return 1;
+}
+
+FileData *blo_openblendermemory(const void *mem, int memsize, ReportList *reports)
{
if (!mem || memsize<SIZEOFBLENDERHEADER) {
BKE_report(reports, RPT_WARNING, (mem) ? TIP_("Unable to read"): TIP_("Unable to open"));
@@ -1028,9 +1055,21 @@ FileData *blo_openblendermemory(void *mem, int memsize, ReportList *reports)
}
else {
FileData *fd = filedata_new();
+ const char *cp = mem;
+
fd->buffer = mem;
fd->buffersize = memsize;
+
+ /* test if gzip */
+ if (cp[0] == 0x1f && cp[1] == 0x8b) {
+ if (0 == fd_read_gzip_from_memory_init(fd)) {
+ blo_freefiledata(fd);
+ return NULL;
+ }
+ }
+ else
fd->read = fd_read_from_memory;
+
fd->flags |= FD_FLAGS_NOT_MY_BUFFER;
return blo_decode_and_check(fd, reports);
@@ -1066,8 +1105,14 @@ void blo_freefiledata(FileData *fd)
gzclose(fd->gzfiledes);
}
+ if (fd->strm.next_in) {
+ if (inflateEnd (&fd->strm) != Z_OK) {
+ printf("close gzip stream error\n");
+ }
+ }
+
if (fd->buffer && !(fd->flags & FD_FLAGS_NOT_MY_BUFFER)) {
- MEM_freeN(fd->buffer);
+ MEM_freeN((void *)fd->buffer);
fd->buffer = NULL;
}
@@ -1089,6 +1134,8 @@ void blo_freefiledata(FileData *fd)
oldnewmap_free(fd->imamap);
if (fd->movieclipmap)
oldnewmap_free(fd->movieclipmap);
+ if (fd->packedmap)
+ oldnewmap_free(fd->packedmap);
if (fd->libmap && !(fd->flags & FD_FLAGS_NOT_MY_LIBMAP))
oldnewmap_free(fd->libmap);
if (fd->bheadmap)
@@ -1124,7 +1171,7 @@ int BLO_is_a_library(const char *path, char *dir, char *group)
dir[len - 1] = '\0';
/* Find the last slash */
- fd = BLI_last_slash(dir);
+ fd = (char *)BLI_last_slash(dir);
if (fd == NULL) return 0;
*fd = 0;
@@ -1133,10 +1180,10 @@ int BLO_is_a_library(const char *path, char *dir, char *group)
*fd = '/'; /* put back the removed slash separating the dir and the .blend file name */
}
else {
- char *gp = fd + 1; // in case we have a .blend file, gp points to the group
+ const char * const gp = fd + 1; // in case we have a .blend file, gp points to the group
/* Find the last slash */
- fd = BLI_last_slash(dir);
+ 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
@@ -1173,6 +1220,14 @@ static void *newmclipadr(FileData *fd, void *adr) /* used to restor
return NULL;
}
+static void *newpackedadr(FileData *fd, void *adr) /* used to restore packed data after undo */
+{
+ if (fd->packedmap && adr)
+ return oldnewmap_lookup_and_inc(fd->packedmap, adr);
+
+ return oldnewmap_lookup_and_inc(fd->datamap, adr);
+}
+
static void *newlibadr(FileData *fd, void *lib, void *adr) /* only lib data */
{
@@ -1264,10 +1319,12 @@ void blo_make_image_pointer_map(FileData *fd, Main *oldmain)
oldnewmap_insert(fd->imamap, ima->renders[a], ima->renders[a], 0);
}
for (; sce; sce = sce->id.next) {
- if (sce->nodetree) {
- bNode *node;
- for (node = sce->nodetree->nodes.first; node; node = node->next)
- oldnewmap_insert(fd->imamap, node->preview, node->preview, 0);
+ if (sce->nodetree && sce->nodetree->previews) {
+ bNodeInstanceHashIterator iter;
+ NODE_INSTANCE_HASH_ITER(iter, sce->nodetree->previews) {
+ bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
+ oldnewmap_insert(fd->imamap, preview, preview, 0);
+ }
}
}
}
@@ -1306,10 +1363,23 @@ void blo_end_image_pointer_map(FileData *fd, Main *oldmain)
ima->gputexture = newimaadr(fd, ima->gputexture);
}
for (; sce; sce = sce->id.next) {
- if (sce->nodetree) {
- bNode *node;
- for (node = sce->nodetree->nodes.first; node; node = node->next)
- node->preview = newimaadr(fd, node->preview);
+ if (sce->nodetree && sce->nodetree->previews) {
+ bNodeInstanceHash *new_previews = BKE_node_instance_hash_new("node previews");
+ bNodeInstanceHashIterator iter;
+
+ /* reconstruct the preview hash, only using remaining pointers */
+ NODE_INSTANCE_HASH_ITER(iter, sce->nodetree->previews) {
+ bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
+ if (preview) {
+ bNodePreview *new_preview = newimaadr(fd, preview);
+ if (new_preview) {
+ bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
+ BKE_node_instance_hash_insert(new_previews, key, new_preview);
+ }
+ }
+ }
+ BKE_node_instance_hash_free(sce->nodetree->previews, NULL);
+ sce->nodetree->previews = new_previews;
}
}
}
@@ -1332,7 +1402,7 @@ void blo_make_movieclip_pointer_map(FileData *fd, Main *oldmain)
for (; sce; sce = sce->id.next) {
if (sce->nodetree) {
bNode *node;
- for (node = sce->nodetree->nodes.first; node; node= node->next)
+ for (node = sce->nodetree->nodes.first; node; node = node->next)
if (node->type == CMP_NODE_MOVIEDISTORTION)
oldnewmap_insert(fd->movieclipmap, node->storage, node->storage, 0);
}
@@ -1369,6 +1439,71 @@ void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain)
}
}
+/* 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)
+{
+ oldnewmap_insert(fd->packedmap, pf, pf, 0);
+ oldnewmap_insert(fd->packedmap, pf->data, pf->data, 0);
+}
+
+void blo_make_packed_pointer_map(FileData *fd, Main *oldmain)
+{
+ Image *ima;
+ VFont *vfont;
+ bSound *sound;
+ Library *lib;
+
+ fd->packedmap = oldnewmap_new();
+
+ for (ima = oldmain->image.first; ima; ima = ima->id.next)
+ if (ima->packedfile)
+ insert_packedmap(fd, ima->packedfile);
+
+ for (vfont = oldmain->vfont.first; vfont; vfont = vfont->id.next)
+ if (vfont->packedfile)
+ insert_packedmap(fd, vfont->packedfile);
+
+ for (sound = oldmain->sound.first; sound; sound = sound->id.next)
+ if (sound->packedfile)
+ insert_packedmap(fd, sound->packedfile);
+
+ for (lib = oldmain->library.first; lib; lib = lib->id.next)
+ if (lib->packedfile)
+ insert_packedmap(fd, lib->packedfile);
+
+}
+
+/* set old main packed data to zero if it has been restored */
+/* this works because freeing old main only happens after this call */
+void blo_end_packed_pointer_map(FileData *fd, Main *oldmain)
+{
+ Image *ima;
+ VFont *vfont;
+ bSound *sound;
+ Library *lib;
+ OldNew *entry = fd->packedmap->entries;
+ int i;
+
+ /* used entries were restored, so we put them to zero */
+ for (i=0; i < fd->packedmap->nentries; i++, entry++) {
+ if (entry->nr > 0)
+ entry->newp = NULL;
+ }
+
+ for (ima = oldmain->image.first; ima; ima = ima->id.next)
+ ima->packedfile = newpackedadr(fd, ima->packedfile);
+
+ for (vfont = oldmain->vfont.first; vfont; vfont = vfont->id.next)
+ vfont->packedfile = newpackedadr(fd, vfont->packedfile);
+
+ for (sound = oldmain->sound.first; sound; sound = sound->id.next)
+ sound->packedfile = newpackedadr(fd, sound->packedfile);
+
+ for (lib = oldmain->library.first; lib; lib = lib->id.next)
+ lib->packedfile = newpackedadr(fd, lib->packedfile);
+}
+
/* undo file support: add all library pointers in lookup */
void blo_add_library_pointer_map(ListBase *mainlist, FileData *fd)
@@ -1708,10 +1843,10 @@ static void direct_link_script(FileData *UNUSED(fd), Script *script)
static PackedFile *direct_link_packedfile(FileData *fd, PackedFile *oldpf)
{
- PackedFile *pf = newdataadr(fd, oldpf);
+ PackedFile *pf = newpackedadr(fd, oldpf);
if (pf) {
- pf->data = newdataadr(fd, pf->data);
+ pf->data = newpackedadr(fd, pf->data);
}
return pf;
@@ -1729,6 +1864,7 @@ static PreviewImage *direct_link_preview_image(FileData *fd, PreviewImage *old_p
if (prv->rect[i]) {
prv->rect[i] = newdataadr(fd, prv->rect[i]);
}
+ prv->gputexture[i] = NULL;
}
}
@@ -2171,17 +2307,42 @@ static void direct_link_motionpath(FileData *fd, bMotionPath *mpath)
/* ************ READ NODE TREE *************** */
+static void lib_link_node_socket(FileData *fd, ID *UNUSED(id), bNodeSocket *sock)
+{
+ /* Link ID Properties -- and copy this comment EXACTLY for easy finding
+ * of library blocks that implement this.*/
+ if (sock->prop)
+ IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+}
+
/* singe node tree (also used for material/scene trees), ntree is not NULL */
static void lib_link_ntree(FileData *fd, ID *id, bNodeTree *ntree)
{
bNode *node;
+ bNodeSocket *sock;
if (ntree->adt) lib_link_animdata(fd, &ntree->id, ntree->adt);
ntree->gpd = newlibadr_us(fd, id->lib, ntree->gpd);
- for (node = ntree->nodes.first; node; node = node->next)
- node->id = newlibadr_us(fd, id->lib, node->id);
+ for (node = ntree->nodes.first; node; node = node->next) {
+ /* Link ID Properties -- and copy this comment EXACTLY for easy finding
+ * of library blocks that implement this.*/
+ if (node->prop)
+ IDP_LibLinkProperty(node->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
+ node->id= newlibadr_us(fd, id->lib, node->id);
+
+ for (sock = node->inputs.first; sock; sock = sock->next)
+ lib_link_node_socket(fd, id, sock);
+ for (sock = node->outputs.first; sock; sock = sock->next)
+ lib_link_node_socket(fd, id, sock);
+ }
+
+ for (sock = ntree->inputs.first; sock; sock = sock->next)
+ lib_link_node_socket(fd, id, sock);
+ for (sock = ntree->outputs.first; sock; sock = sock->next)
+ lib_link_node_socket(fd, id, sock);
}
/* library ntree linking after fileread */
@@ -2198,131 +2359,49 @@ static void lib_link_nodetree(FileData *fd, Main *main)
}
}
-static void do_versions_socket_default_value(bNodeSocket *sock)
-{
- bNodeSocketValueFloat *valfloat;
- bNodeSocketValueVector *valvector;
- bNodeSocketValueRGBA *valrgba;
-
- if (sock->default_value)
- return;
-
- switch (sock->type) {
- case SOCK_FLOAT:
- valfloat = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueFloat), "default socket value");
- valfloat->value = sock->ns.vec[0];
- valfloat->min = sock->ns.min;
- valfloat->max = sock->ns.max;
- valfloat->subtype = PROP_NONE;
- break;
- case SOCK_VECTOR:
- valvector = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueVector), "default socket value");
- copy_v3_v3(valvector->value, sock->ns.vec);
- valvector->min = sock->ns.min;
- valvector->max = sock->ns.max;
- valvector->subtype = PROP_NONE;
- break;
- case SOCK_RGBA:
- valrgba = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueRGBA), "default socket value");
- copy_v4_v4(valrgba->value, sock->ns.vec);
- break;
- }
-}
-
-void blo_do_versions_nodetree_default_value(bNodeTree *ntree)
-{
- bNode *node;
- bNodeSocket *sock;
- for (node=ntree->nodes.first; node; node=node->next) {
- for (sock=node->inputs.first; sock; sock=sock->next)
- do_versions_socket_default_value(sock);
- for (sock=node->outputs.first; sock; sock=sock->next)
- do_versions_socket_default_value(sock);
- }
- for (sock=ntree->inputs.first; sock; sock=sock->next)
- do_versions_socket_default_value(sock);
- for (sock=ntree->outputs.first; sock; sock=sock->next)
- do_versions_socket_default_value(sock);
-}
-
-static void lib_nodetree_init_types_cb(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- ntreeInitTypes(ntree);
-
- /* need to do this here instead of in do_versions, otherwise next function can crash */
- blo_do_versions_nodetree_default_value(ntree);
-
- /* XXX could be replaced by do_versions for new nodes */
- for (node=ntree->nodes.first; node; node=node->next)
- node_verify_socket_templates(ntree, node);
-}
-
-/* updates group node socket own_index so that
+/* updates group node socket identifier so that
* external links to/from the group node are preserved.
*/
static void lib_node_do_versions_group_indices(bNode *gnode)
{
bNodeTree *ngroup = (bNodeTree*)gnode->id;
- bNode *intnode;
- bNodeSocket *sock, *gsock, *intsock;
- int found;
+ bNodeSocket *sock;
+ bNodeLink *link;
- for (sock=gnode->outputs.first; sock; sock=sock->next) {
+ for (sock=gnode->outputs.first; sock; sock = sock->next) {
int old_index = sock->to_index;
- for (gsock=ngroup->outputs.first; gsock; gsock=gsock->next) {
- if (gsock->link && gsock->link->fromsock->own_index == old_index) {
- sock->own_index = gsock->own_index;
- break;
+
+ for (link = ngroup->links.first; link; link = link->next) {
+ if (link->tonode->type == NODE_GROUP_OUTPUT && link->fromsock->own_index == old_index) {
+ strcpy(sock->identifier, link->fromsock->identifier);
+ /* deprecated */
+ sock->own_index = link->fromsock->own_index;
+ sock->to_index = 0;
+ sock->groupsock = NULL;
}
}
}
- for (sock=gnode->inputs.first; sock; sock=sock->next) {
+ for (sock=gnode->inputs.first; sock; sock = sock->next) {
int old_index = sock->to_index;
- /* can't use break in double loop */
- found = 0;
- for (intnode=ngroup->nodes.first; intnode && !found; intnode=intnode->next) {
- for (intsock=intnode->inputs.first; intsock; intsock=intsock->next) {
- if (intsock->own_index == old_index && intsock->link) {
- sock->own_index = intsock->link->fromsock->own_index;
- found = 1;
- break;
- }
+
+ for (link = ngroup->links.first; link; link = link->next) {
+ if (link->fromnode->type == NODE_GROUP_INPUT && link->tosock->own_index == old_index) {
+ strcpy(sock->identifier, link->tosock->identifier);
+ /* deprecated */
+ sock->own_index = link->tosock->own_index;
+ sock->to_index = 0;
+ sock->groupsock = NULL;
}
}
}
}
-/* updates external links for all group nodes in a tree */
-static void lib_nodetree_do_versions_group_indices_cb(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == NODE_GROUP) {
- bNodeTree *ngroup = (bNodeTree*)node->id;
- if (ngroup && (ngroup->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE))
- lib_node_do_versions_group_indices(node);
- }
- }
-}
-
-/* make an update call for the tree */
-static void lib_nodetree_do_versions_update_cb(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- if (ntree->update)
- ntreeUpdateTree(ntree);
-}
-
/* verify types for nodes and groups, all data has to be read */
/* open = 0: appending/linking, open = 1: open new file (need to clean out dynamic
* typedefs */
static void lib_verify_nodetree(Main *main, int UNUSED(open))
{
bNodeTree *ntree;
- int i;
- bNodeTreeType *ntreetype;
/* this crashes blender on undo/redo */
#if 0
@@ -2332,41 +2411,143 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open))
#endif
/* set node->typeinfo pointers */
- for (i = 0; i < NUM_NTREE_TYPES; ++i) {
- ntreetype = ntreeGetType(i);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, lib_nodetree_init_types_cb);
- }
- for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
- lib_nodetree_init_types_cb(NULL, NULL, ntree);
+ FOREACH_NODETREE(main, ntree, id) {
+ ntreeSetTypes(NULL, ntree);
+ } FOREACH_NODETREE_END
+
+ /* verify static socket templates */
+ FOREACH_NODETREE(main, ntree, id) {
+ bNode *node;
+ for (node=ntree->nodes.first; node; node=node->next)
+ node_verify_socket_templates(ntree, node);
+ } FOREACH_NODETREE_END
{
int has_old_groups = 0;
/* XXX this should actually be part of do_versions, but since we need
* finished library linking, it is not possible there. Instead in do_versions
- * we have set the NTREE_DO_VERSIONS flag, so at this point we can do the
+ * we have set the NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2 flag, so at this point we can do the
* actual group node updates.
*/
for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
- if (ntree->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE) {
- /* this adds copies and links from all unlinked internal sockets to group inputs/outputs. */
- node_group_expose_all_sockets(ntree);
+ if (ntree->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2)
has_old_groups = 1;
- }
}
if (has_old_groups) {
- for (i = 0; i < NUM_NTREE_TYPES; ++i) {
- ntreetype = ntreeGetType(i);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, lib_nodetree_do_versions_group_indices_cb);
- }
+ FOREACH_NODETREE(main, ntree, id) {
+ /* updates external links for all group nodes in a tree */
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP) {
+ bNodeTree *ngroup = (bNodeTree*)node->id;
+ if (ngroup && (ngroup->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2))
+ lib_node_do_versions_group_indices(node);
+ }
+ }
+ } FOREACH_NODETREE_END
}
for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
- ntree->flag &= ~NTREE_DO_VERSIONS_GROUP_EXPOSE;
+ ntree->flag &= ~NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2;
}
+
+ {
+ /* Convert the previously used ntree->inputs/ntree->outputs lists to interface nodes.
+ * Pre 2.56.2 node trees automatically have all unlinked sockets exposed already
+ * (see NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2).
+ *
+ * XXX this should actually be part of do_versions,
+ * but needs valid typeinfo pointers to create interface nodes.
+ *
+ * Note: theoretically only needed in node groups (main->nodetree),
+ * but due to a temporary bug such links could have been added in all trees,
+ * so have to clean up all of them ...
+ */
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->flag & NTREE_DO_VERSIONS_CUSTOMNODES_GROUP) {
+ bNode *input_node = NULL, *output_node = NULL;
+ int num_inputs = 0, num_outputs = 0;
+ bNodeLink *link, *next_link;
+ /* Only create new interface nodes for actual older files.
+ * 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);
+
+ float input_locx = 1000000.0f, input_locy = 0.0f;
+ float output_locx = -1000000.0f, output_locy = 0.0f;
+ /* rough guess, not nice but we don't have access to UI constants here ... */
+ static const float offsetx = 42 + 3*20 + 20;
+ /*static const float offsety = 0.0f;*/
+
+ if (create_io_nodes) {
+ if (ntree->inputs.first)
+ input_node = nodeAddStaticNode(NULL, ntree, NODE_GROUP_INPUT);
+
+ if (ntree->outputs.first)
+ output_node = nodeAddStaticNode(NULL, ntree, NODE_GROUP_OUTPUT);
+ }
+
+ /* Redirect links from/to the node tree interface to input/output node.
+ * If the fromnode/tonode pointers are NULL, this means a link from/to
+ * the ntree interface sockets, which need to be redirected to new interface nodes.
+ */
+ for (link = ntree->links.first; link; link = next_link) {
+ int free_link = FALSE;
+ next_link = link->next;
+
+ if (link->fromnode == NULL) {
+ if (input_node) {
+ link->fromnode = input_node;
+ link->fromsock = node_group_input_find_socket(input_node, link->fromsock->identifier);
+ ++num_inputs;
+
+ if (input_locx > link->tonode->locx - offsetx)
+ input_locx = link->tonode->locx - offsetx;
+ input_locy += link->tonode->locy;
+ }
+ else
+ free_link = TRUE;
+ }
+
+ if (link->tonode == NULL) {
+ if (output_node) {
+ link->tonode = output_node;
+ link->tosock = node_group_output_find_socket(output_node, link->tosock->identifier);
+ ++num_outputs;
+
+ if (output_locx < link->fromnode->locx + offsetx)
+ output_locx = link->fromnode->locx + offsetx;
+ output_locy += link->fromnode->locy;
+ }
+ else
+ free_link = TRUE;
+ }
+
+ if (free_link)
+ nodeRemLink(ntree, link);
+ }
+
+ if (num_inputs > 0) {
+ input_locy /= num_inputs;
+ input_node->locx = input_locx;
+ input_node->locy = input_locy;
+ }
+ if (num_outputs > 0) {
+ output_locy /= num_outputs;
+ output_node->locx = output_locx;
+ output_node->locy = output_locy;
+ }
+
+ /* clear do_versions flags */
+ ntree->flag &= ~(NTREE_DO_VERSIONS_CUSTOMNODES_GROUP | NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE);
+ }
+ }
+ FOREACH_NODETREE_END
+ }
+
/* verify all group user nodes */
for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
ntreeVerifyNodes(main, &ntree->id);
@@ -2374,21 +2555,22 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open))
/* make update calls where necessary */
{
- for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
+ FOREACH_NODETREE(main, ntree, id) {
+ /* make an update call for the tree */
if (ntree->update)
ntreeUpdateTree(ntree);
-
- for (i = 0; i < NUM_NTREE_TYPES; i++) {
- ntreetype = ntreeGetType(i);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, lib_nodetree_do_versions_update_cb);
- }
+ } FOREACH_NODETREE_END
}
}
static void direct_link_node_socket(FileData *fd, bNodeSocket *sock)
{
+ sock->prop = newdataadr(fd, sock->prop);
+ if (sock->prop)
+ IDP_DirectLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
sock->link = newdataadr(fd, sock->link);
+ sock->typeinfo = NULL;
sock->storage = newdataadr(fd, sock->storage);
sock->default_value = newdataadr(fd, sock->default_value);
sock->cache = NULL;
@@ -2403,6 +2585,10 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
bNodeLink *link;
ntree->init = 0; /* to set callbacks and force setting types */
+ ntree->is_updating = FALSE;
+ ntree->typeinfo= NULL;
+ ntree->interface_type = NULL;
+
ntree->progress = NULL;
ntree->execdata = NULL;
@@ -2418,6 +2604,10 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
link_list(fd, &node->inputs);
link_list(fd, &node->outputs);
+ node->prop = newdataadr(fd, node->prop);
+ if (node->prop)
+ IDP_DirectLinkProperty(node->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
link_list(fd, &node->internal_links);
for (link = node->internal_links.first; link; link = link->next) {
link->fromnode = newdataadr(fd, link->fromnode);
@@ -2429,8 +2619,9 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
if (node->type == CMP_NODE_MOVIEDISTORTION) {
node->storage = newmclipadr(fd, node->storage);
}
- else
+ else {
node->storage = newdataadr(fd, node->storage);
+ }
if (node->storage) {
/* could be handlerized at some point */
@@ -2441,9 +2632,6 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
else if (node->type==SH_NODE_SCRIPT) {
NodeShaderScript *nss = (NodeShaderScript *) node->storage;
nss->bytecode = newdataadr(fd, nss->bytecode);
- nss->prop = newdataadr(fd, nss->prop);
- if (nss->prop)
- IDP_DirectLinkProperty(nss->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
}
else if (ntree->type==NTREE_COMPOSIT) {
@@ -2462,14 +2650,9 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
}
link_list(fd, &ntree->links);
- /* external sockets */
- link_list(fd, &ntree->inputs);
- link_list(fd, &ntree->outputs);
-
/* and we connect the rest */
for (node = ntree->nodes.first; node; node = node->next) {
node->parent = newdataadr(fd, node->parent);
- node->preview = newimaadr(fd, node->preview);
node->lasty = 0;
for (sock = node->inputs.first; sock; sock = sock->next)
@@ -2477,6 +2660,10 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
for (sock = node->outputs.first; sock; sock = sock->next)
direct_link_node_socket(fd, sock);
}
+
+ /* interface socket lists */
+ link_list(fd, &ntree->inputs);
+ link_list(fd, &ntree->outputs);
for (sock = ntree->inputs.first; sock; sock = sock->next)
direct_link_node_socket(fd, sock);
for (sock = ntree->outputs.first; sock; sock = sock->next)
@@ -2489,6 +2676,29 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
link->tosock = newdataadr(fd, link->tosock);
}
+#if 0
+ if (ntree->previews) {
+ bNodeInstanceHash *new_previews = BKE_node_instance_hash_new("node previews");
+ bNodeInstanceHashIterator iter;
+
+ NODE_INSTANCE_HASH_ITER(iter, ntree->previews) {
+ bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
+ if (preview) {
+ bNodePreview *new_preview = newimaadr(fd, preview);
+ if (new_preview) {
+ bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
+ BKE_node_instance_hash_insert(new_previews, key, new_preview);
+ }
+ }
+ }
+ BKE_node_instance_hash_free(ntree->previews, NULL);
+ ntree->previews = new_previews;
+ }
+#else
+ /* XXX TODO */
+ ntree->previews = NULL;
+#endif
+
/* type verification is in lib-link */
}
@@ -2535,7 +2745,7 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
cld.fd = fd;
cld.id = id;
- id_loop_constraints(conlist, lib_link_constraint_cb, &cld);
+ BKE_id_loop_constraints(conlist, lib_link_constraint_cb, &cld);
}
static void direct_link_constraints(FileData *fd, ListBase *lb)
@@ -2556,15 +2766,15 @@ static void direct_link_constraints(FileData *fd, ListBase *lb)
data->prop = newdataadr(fd, data->prop);
if (data->prop)
IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
- }
break;
+ }
case CONSTRAINT_TYPE_SPLINEIK:
{
bSplineIKConstraint *data= con->data;
-
+
data->points= newdataadr(fd, data->points);
- }
break;
+ }
case CONSTRAINT_TYPE_KINEMATIC:
{
bKinematicConstraint *data = con->data;
@@ -2574,30 +2784,32 @@ static void direct_link_constraints(FileData *fd, ListBase *lb)
/* version patch for runtime flag, was not cleared in some case */
data->flag &= ~CONSTRAINT_IK_AUTO;
+ break;
}
case CONSTRAINT_TYPE_CHILDOF:
{
/* XXX version patch, in older code this flag wasn't always set, and is inherent to type */
if (con->ownspace == CONSTRAINT_SPACE_POSE)
con->flag |= CONSTRAINT_SPACEONCE;
- }
break;
+ }
}
}
}
-static void lib_link_pose(FileData *fd, Object *ob, bPose *pose)
+static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose)
{
bPoseChannel *pchan;
bArmature *arm = ob->data;
- int rebuild;
+ int rebuild = 0;
if (!pose || !arm)
return;
-
- /* always rebuild to match proxy or lib changes */
- rebuild = ob->proxy || (ob->id.lib==NULL && arm->id.lib);
+ /* always rebuild to match proxy or lib changes, but on Undo */
+ if (fd->memfile == NULL)
+ if (ob->proxy || (ob->id.lib==NULL && arm->id.lib))
+ rebuild = 1;
if (ob->proxy) {
/* sync proxy layer */
@@ -2629,7 +2841,7 @@ static void lib_link_pose(FileData *fd, Object *ob, bPose *pose)
}
if (rebuild) {
- ob->recalc = (OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DAG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
pose->flag |= POSE_RECALC;
}
}
@@ -2981,7 +3193,7 @@ static void direct_link_text(FileData *fd, Text *text)
if (text->flags & TXT_ISEXT) {
BKE_text_reload(text);
}
- else {
+ /* else { */
#endif
link_list(fd, &text->lines);
@@ -3129,7 +3341,9 @@ static void direct_link_curve(FileData *fd, Curve *cu)
cu->strinfo= newdataadr(fd, cu->strinfo);
cu->tb = newdataadr(fd, cu->tb);
- if (cu->vfont == NULL) link_list(fd, &(cu->nurb));
+ if (cu->vfont == NULL) {
+ link_list(fd, &(cu->nurb));
+ }
else {
cu->nurb.first=cu->nurb.last= NULL;
@@ -3709,8 +3923,10 @@ static void lib_link_mesh(FileData *fd, Main *main)
me->mat[i] = newlibadr_us(fd, me->id.lib, me->mat[i]);
}
}
- else me->totcol = 0;
-
+ else {
+ me->totcol = 0;
+ }
+
me->ipo = newlibadr_us(fd, me->id.lib, me->ipo); // XXX: deprecated: old anim sys
me->key = newlibadr_us(fd, me->id.lib, me->key);
me->texcomesh = newlibadr_us(fd, me->id.lib, me->texcomesh);
@@ -4035,15 +4251,13 @@ static void lib_link_object(FileData *fd, Main *main)
ob->proxy = NULL;
if (ob->id.lib)
- printf("Proxy lost from object %s lib %s\n", ob->id.name+2, ob->id.lib->name);
+ printf("Proxy lost from object %s lib %s\n", ob->id.name + 2, ob->id.lib->name);
else
- printf("Proxy lost from object %s lib <NONE>\n", ob->id.name+2);
+ printf("Proxy lost from object %s lib <NONE>\n", ob->id.name + 2);
}
else {
/* this triggers object_update to always use a copy */
ob->proxy->proxy_from = ob;
- /* force proxy updates after load/undo, a bit weak */
- ob->recalc = ob->proxy->recalc = (OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
}
ob->proxy_group = newlibadr(fd, ob->id.lib, ob->proxy_group);
@@ -4053,9 +4267,9 @@ static void lib_link_object(FileData *fd, Main *main)
if (ob->data==NULL && poin!=NULL) {
if (ob->id.lib)
- printf("Can't find obdata of %s lib %s\n", ob->id.name+2, ob->id.lib->name);
+ printf("Can't find obdata of %s lib %s\n", ob->id.name + 2, ob->id.lib->name);
else
- printf("Object %s lost data.\n", ob->id.name+2);
+ printf("Object %s lost data.\n", ob->id.name + 2);
ob->type = OB_EMPTY;
warn = 1;
@@ -4096,7 +4310,7 @@ static void lib_link_object(FileData *fd, Main *main)
/* if id.us==0 a new base will be created later on */
/* WARNING! Also check expand_object(), should reflect the stuff below. */
- lib_link_pose(fd, ob, ob->pose);
+ lib_link_pose(fd, main, ob, ob->pose);
lib_link_constraints(fd, &ob->id, &ob->constraints);
// XXX deprecated - old animation system <<<
@@ -4241,6 +4455,11 @@ static void lib_link_object(FileData *fd, Main *main)
lib_link_particlesystems(fd, ob, &ob->id, &ob->particlesystem);
lib_link_modifiers(fd, ob);
+
+ if (ob->rigidbody_constraint) {
+ ob->rigidbody_constraint->ob1 = newlibadr(fd, ob->id.lib, ob->rigidbody_constraint->ob1);
+ ob->rigidbody_constraint->ob2 = newlibadr(fd, ob->id.lib, ob->rigidbody_constraint->ob2);
+ }
}
}
@@ -4664,6 +4883,20 @@ static void direct_link_object(FileData *fd, Object *ob)
}
ob->bsoft = newdataadr(fd, ob->bsoft);
ob->fluidsimSettings= newdataadr(fd, ob->fluidsimSettings); /* NT */
+
+ ob->rigidbody_object = newdataadr(fd, ob->rigidbody_object);
+ if (ob->rigidbody_object) {
+ RigidBodyOb *rbo = ob->rigidbody_object;
+
+ /* must nullify the references to physics sim objects, since they no-longer exist
+ * (and will need to be recalculated)
+ */
+ rbo->physics_object = NULL;
+ rbo->physics_shape = NULL;
+ }
+ ob->rigidbody_constraint = newdataadr(fd, ob->rigidbody_constraint);
+ if (ob->rigidbody_constraint)
+ ob->rigidbody_constraint->physics_constraint = NULL;
link_list(fd, &ob->particlesystem);
direct_link_particlesystems(fd, &ob->particlesystem);
@@ -4757,7 +4990,7 @@ static void composite_patch(bNodeTree *ntree, Scene *scene)
{
bNode *node;
- for (node= ntree->nodes.first; node; node= node->next) {
+ for (node = ntree->nodes.first; node; node = node->next) {
if (node->id==NULL && ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE))
node->id = &scene->id;
}
@@ -4788,6 +5021,7 @@ static void lib_link_scene(FileData *fd, Main *main)
Sequence *seq;
SceneRenderLayer *srl;
TimeMarker *marker;
+ FreestyleLineSet *fls;
for (sce = main->scene.first; sce; sce = sce->id.next) {
if (sce->id.flag & LIB_NEED_LINK) {
@@ -4882,6 +5116,18 @@ static void lib_link_scene(FileData *fd, Main *main)
BKE_sequencer_update_muting(sce->ed);
BKE_sequencer_update_sound_bounds_all(sce);
+
+ /* rigidbody world relies on it's linked groups */
+ if (sce->rigidbody_world) {
+ RigidBodyWorld *rbw = sce->rigidbody_world;
+ if (rbw->group)
+ rbw->group = newlibadr(fd, sce->id.lib, rbw->group);
+ if (rbw->constraints)
+ rbw->constraints = newlibadr(fd, sce->id.lib, rbw->constraints);
+ if (rbw->effector_weights)
+ rbw->effector_weights->group = newlibadr(fd, sce->id.lib, rbw->effector_weights->group);
+ }
+
if (sce->nodetree) {
lib_link_ntree(fd, &sce->id, sce->nodetree);
composite_patch(sce->nodetree, sce);
@@ -4890,6 +5136,10 @@ static void lib_link_scene(FileData *fd, Main *main)
for (srl = sce->r.layers.first; srl; srl = srl->next) {
srl->mat_override = newlibadr_us(fd, sce->id.lib, srl->mat_override);
srl->light_override = newlibadr_us(fd, sce->id.lib, srl->light_override);
+ for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
+ fls->linestyle = newlibadr_us(fd, sce->id.lib, fls->linestyle);
+ fls->group = newlibadr_us(fd, sce->id.lib, fls->group);
+ }
}
/*Game Settings: Dome Warp Text*/
sce->gm.dome.warptext = newlibadr(fd, sce->id.lib, sce->gm.dome.warptext);
@@ -4958,9 +5208,10 @@ static void direct_link_scene(FileData *fd, Scene *sce)
Editing *ed;
Sequence *seq;
MetaStack *ms;
+ RigidBodyWorld *rbw;
+ SceneRenderLayer *srl;
sce->theDag = NULL;
- sce->dagisvalid = 0;
sce->obedit = NULL;
sce->stats = NULL;
sce->fps_info = NULL;
@@ -4991,6 +5242,16 @@ static void direct_link_scene(FileData *fd, Scene *sce)
sce->toolsettings->imapaint.paintcursor = NULL;
sce->toolsettings->particle.paintcursor = NULL;
+
+ /* in rare cases this is needed, see [#33806] */
+ if (sce->toolsettings->vpaint) {
+ sce->toolsettings->vpaint->vpaint_prev = NULL;
+ sce->toolsettings->vpaint->tot = 0;
+ }
+ if (sce->toolsettings->wpaint) {
+ sce->toolsettings->wpaint->wpaint_prev = NULL;
+ sce->toolsettings->wpaint->tot = 0;
+ }
}
if (sce->ed) {
@@ -5126,6 +5387,13 @@ 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));
+
+ for(srl = sce->r.layers.first; srl; srl = srl->next) {
+ link_list(fd, &(srl->freestyleConfig.modules));
+ }
+ for(srl = sce->r.layers.first; srl; srl = srl->next) {
+ link_list(fd, &(srl->freestyleConfig.linesets));
+ }
sce->nodetree = newdataadr(fd, sce->nodetree);
if (sce->nodetree) {
@@ -5134,6 +5402,29 @@ static void direct_link_scene(FileData *fd, Scene *sce)
}
direct_link_view_settings(fd, &sce->view_settings);
+
+ sce->rigidbody_world = newdataadr(fd, sce->rigidbody_world);
+ rbw = sce->rigidbody_world;
+ if (rbw) {
+ /* must nullify the reference to physics sim object, since it no-longer exist
+ * (and will need to be recalculated)
+ */
+ rbw->physics_world = NULL;
+ rbw->objects = NULL;
+ rbw->numbodies = 0;
+
+ /* set effector weights */
+ rbw->effector_weights = newdataadr(fd, rbw->effector_weights);
+ if (!rbw->effector_weights)
+ rbw->effector_weights = BKE_add_effector_weights(NULL);
+
+ /* link cache */
+ direct_link_pointcache_list(fd, &rbw->ptcaches, &rbw->pointcache, FALSE);
+ /* make sure simulation starts from the beginning after loading file */
+ if (rbw->pointcache) {
+ rbw->ltime = (float)rbw->pointcache->startframe;
+ }
+ }
}
/* ************ READ WM ***************** */
@@ -5160,6 +5451,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
win->drawdata = NULL;
win->drawmethod = -1;
win->drawfail = 0;
+ win->active = 0;
}
wm->timers.first = wm->timers.last = NULL;
@@ -5231,27 +5523,6 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
/* ****************** READ SCREEN ***************** */
-static void butspace_version_132(SpaceButs *buts)
-{
- buts->v2d.tot.xmin = 0.0f;
- buts->v2d.tot.ymin = 0.0f;
- buts->v2d.tot.xmax = 1279.0f;
- buts->v2d.tot.ymax = 228.0f;
-
- buts->v2d.min[0] = 256.0f;
- buts->v2d.min[1] = 42.0f;
-
- buts->v2d.max[0] = 2048.0f;
- buts->v2d.max[1] = 450.0f;
-
- buts->v2d.minzoom = 0.5f;
- buts->v2d.maxzoom = 1.21f;
-
- buts->v2d.scroll = 0;
- buts->v2d.keepzoom = 1;
- buts->v2d.keeptot = 1;
-}
-
/* note: file read without screens option G_FILE_NO_UI;
* check lib pointers in call below */
static void lib_link_screen(FileData *fd, Main *main)
@@ -5305,18 +5576,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);
- sbuts->mainbo = sbuts->mainb;
- sbuts->mainbuser = sbuts->mainb;
- if (main->versionfile < 132)
- butspace_version_132(sbuts);
}
else if (sl->spacetype == SPACE_FILE) {
- SpaceFile *sfile = (SpaceFile *)sl;
- sfile->files = NULL;
- sfile->op = NULL;
- sfile->layout = NULL;
- sfile->folders_prev = NULL;
- sfile->folders_next = NULL;
+ ;
}
else if (sl->spacetype == SPACE_ACTION) {
SpaceAction *saction = (SpaceAction *)sl;
@@ -5348,12 +5610,6 @@ static void lib_link_screen(FileData *fd, Main *main)
*/
sseq->gpd = newlibadr_us(fd, sc->id.lib, sseq->gpd);
- sseq->scopes.reference_ibuf = NULL;
- sseq->scopes.zebra_ibuf = NULL;
- sseq->scopes.waveform_ibuf = NULL;
- sseq->scopes.sep_waveform_ibuf = NULL;
- sseq->scopes.vector_ibuf = NULL;
- sseq->scopes.histogram_ibuf = NULL;
}
else if (sl->spacetype == SPACE_NLA) {
SpaceNla *snla= (SpaceNla *)sl;
@@ -5368,7 +5624,6 @@ static void lib_link_screen(FileData *fd, Main *main)
SpaceText *st= (SpaceText *)sl;
st->text= newlibadr(fd, sc->id.lib, st->text);
- st->drawcache= NULL;
}
else if (sl->spacetype == SPACE_SCRIPT) {
SpaceScript *scpt = (SpaceScript *)sl;
@@ -5385,7 +5640,6 @@ static void lib_link_screen(FileData *fd, Main *main)
TreeStoreElem *tselem;
int a;
- so->tree.first = so->tree.last= NULL;
so->search_tse.id = newlibadr(fd, NULL, so->search_tse.id);
if (so->treestore) {
@@ -5397,42 +5651,40 @@ static void lib_link_screen(FileData *fd, Main *main)
}
else if (sl->spacetype == SPACE_NODE) {
SpaceNode *snode = (SpaceNode *)sl;
+ bNodeTreePath *path, *path_next;
- snode->id = newlibadr(fd, sc->id.lib, snode->id);
- snode->edittree = NULL;
-
- if (ELEM3(snode->treetype, NTREE_COMPOSIT, NTREE_SHADER, NTREE_TEXTURE)) {
- /* internal data, a bit patchy */
- snode->nodetree = NULL;
- if (snode->id) {
- if (GS(snode->id->name)==ID_MA)
- snode->nodetree = ((Material *)snode->id)->nodetree;
- else if (GS(snode->id->name)==ID_WO)
- snode->nodetree = ((World *)snode->id)->nodetree;
- else if (GS(snode->id->name)==ID_LA)
- snode->nodetree = ((Lamp *)snode->id)->nodetree;
- else if (GS(snode->id->name)==ID_SCE)
- snode->nodetree = ((Scene *)snode->id)->nodetree;
- else if (GS(snode->id->name)==ID_TE)
- snode->nodetree = ((Tex *)snode->id)->nodetree;
- }
+ for (path=snode->treepath.first; path; path=path->next) {
+ path->nodetree = newlibadr(fd, sc->id.lib, path->nodetree);
+
+ if (!path->nodetree)
+ break;
}
- else {
- snode->nodetree = newlibadr_us(fd, sc->id.lib, snode->nodetree);
+
+ /* remaining path entries are invalid, remove */
+ for (; path; path = path_next) {
+ path_next = path->next;
+
+ BLI_remlink(&snode->treepath, path);
+ MEM_freeN(path);
}
- snode->linkdrag.first = snode->linkdrag.last = NULL;
+ snode->nodetree = newlibadr(fd, sc->id.lib, snode->nodetree);
+ /* edittree is just the last in the path,
+ * set this directly since the path may have been shortened above */
+ if (snode->treepath.last) {
+ path = snode->treepath.last;
+ snode->edittree = path->nodetree;
+ }
+ else
+ snode->edittree = NULL;
+ snode->id = newlibadr(fd, sc->id.lib, snode->id);
+ snode->from = newlibadr(fd, sc->id.lib, snode->from);
}
else if (sl->spacetype == SPACE_CLIP) {
SpaceClip *sclip = (SpaceClip *)sl;
sclip->clip = newlibadr_us(fd, sc->id.lib, sclip->clip);
sclip->mask_info.mask = newlibadr_us(fd, sc->id.lib, sclip->mask_info.mask);
-
- sclip->scopes.track_search = NULL;
- sclip->scopes.track_preview = NULL;
- sclip->draw_context = NULL;
- sclip->scopes.ok = 0;
}
else if (sl->spacetype == SPACE_LOGIC) {
SpaceLogic *slogic = (SpaceLogic *)sl;
@@ -5446,27 +5698,62 @@ static void lib_link_screen(FileData *fd, Main *main)
}
}
-/* Only for undo files, or to restore a screen after reading without UI... */
+static bool restore_pointer(ID *id, ID *newid, int user)
+{
+ if (strcmp(newid->name + 2, id->name + 2) == 0) {
+ if (newid->lib == id->lib) {
+ if (user == 1) {
+ if (newid->us == 0) {
+ newid->us++;
+ }
+ }
+ else if (user == 2) {
+ id_us_ensure_real(newid);
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Only for undo files, or to restore a screen after reading without UI...
+ *
+ * user
+ * - 0: no usercount change
+ * - 1: ensure a user
+ * - 2: ensure a real user (even if a fake one is set)
+ */
static void *restore_pointer_by_name(Main *mainp, ID *id, int user)
{
if (id) {
- ListBase *lb = which_libbase(mainp, GS(id->name));
-
- if (lb) { // there's still risk of checking corrupt mem (freed Ids in oops)
- ID *idn = lb->first;
- char *name = id->name + 2;
+ /* node trees can be stored locally in other IDs, needs special handling ... */
+ if (GS(id->name) == ID_NT) {
+ ID *idn = NULL;
- for (; idn; idn = idn->next) {
- if (idn->name[2] == name[0] && strcmp(idn->name+2, name) == 0) {
- if (idn->lib == id->lib) {
- if (user && idn->us == 0) idn->us++;
- break;
- }
+ FOREACH_NODETREE(mainp, ntree, owner_id) {
+ if (restore_pointer(id, &ntree->id, user)) {
+ idn = &ntree->id;
+ break;
}
}
+ FOREACH_NODETREE_END
return idn;
}
+ else {
+ ListBase *lb = which_libbase(mainp, GS(id->name));
+ if (lb) { // there's still risk of checking corrupt mem (freed Ids in oops)
+ ID *idn = lb->first;
+
+ for (; idn; idn = idn->next) {
+ if (restore_pointer(id, idn, user))
+ break;
+ }
+
+ return idn;
+ }
+ }
}
return NULL;
}
@@ -5567,7 +5854,9 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
}
#endif
}
- else if (v3d->scenelock) v3d->lay = sc->scene->lay;
+ else if (v3d->scenelock) {
+ v3d->lay = sc->scene->lay;
+ }
/* not very nice, but could help */
if ((v3d->layact & v3d->lay) == 0) v3d->layact = v3d->lay;
@@ -5625,7 +5914,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
else if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)sl;
- sima->image = restore_pointer_by_name(newmain, (ID *)sima->image, 1);
+ sima->image = restore_pointer_by_name(newmain, (ID *)sima->image, 2);
/* this will be freed, not worth attempting to find same scene,
* since it gets initialized later */
@@ -5641,7 +5930,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
* so assume that here we're doing for undo only...
*/
sima->gpd = restore_pointer_by_name(newmain, (ID *)sima->gpd, 1);
- sima->mask_info.mask = restore_pointer_by_name(newmain, (ID *)sima->mask_info.mask, 1);
+ sima->mask_info.mask = restore_pointer_by_name(newmain, (ID *)sima->mask_info.mask, 2);
}
else if (sl->spacetype == SPACE_SEQ) {
SpaceSeq *sseq = (SpaceSeq *)sl;
@@ -5694,30 +5983,40 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
}
else if (sl->spacetype == SPACE_NODE) {
SpaceNode *snode= (SpaceNode *)sl;
+ bNodeTreePath *path, *path_next;
- snode->id = restore_pointer_by_name(newmain, snode->id, 1);
- snode->edittree = NULL;
+ for (path=snode->treepath.first; path; path=path->next) {
+ path->nodetree= restore_pointer_by_name(newmain, (ID*)path->nodetree, 0);
+
+ if (!path->nodetree)
+ break;
+ }
- if (ELEM3(snode->treetype, NTREE_COMPOSIT, NTREE_SHADER, NTREE_TEXTURE)) {
- snode->nodetree = NULL;
- if (snode->id) {
- if (GS(snode->id->name)==ID_MA)
- snode->nodetree = ((Material *)snode->id)->nodetree;
- else if (GS(snode->id->name)==ID_SCE)
- snode->nodetree = ((Scene *)snode->id)->nodetree;
- else if (GS(snode->id->name)==ID_TE)
- snode->nodetree = ((Tex *)snode->id)->nodetree;
- }
+ /* remaining path entries are invalid, remove */
+ for (; path; path = path_next) {
+ path_next = path->next;
+
+ BLI_remlink(&snode->treepath, path);
+ MEM_freeN(path);
}
- else {
- snode->nodetree= restore_pointer_by_name(newmain, &snode->nodetree->id, 1);
+
+ snode->nodetree = restore_pointer_by_name(newmain, (ID*)snode->nodetree, 0);
+ /* edittree is just the last in the path,
+ * set this directly since the path may have been shortened above */
+ if (snode->treepath.last) {
+ path = snode->treepath.last;
+ snode->edittree = path->nodetree;
}
+ else
+ snode->edittree = NULL;
+ snode->id = restore_pointer_by_name(newmain, snode->id, 1);
+ snode->from = restore_pointer_by_name(newmain, snode->from, 0);
}
else if (sl->spacetype == SPACE_CLIP) {
SpaceClip *sclip = (SpaceClip *)sl;
- sclip->clip = restore_pointer_by_name(newmain, (ID *)sclip->clip, 1);
- sclip->mask_info.mask = restore_pointer_by_name(newmain, (ID *)sclip->mask_info.mask, 1);
+ sclip->clip = restore_pointer_by_name(newmain, (ID *)sclip->clip, 2);
+ sclip->mask_info.mask = restore_pointer_by_name(newmain, (ID *)sclip->mask_info.mask, 2);
sclip->scopes.ok = 0;
}
@@ -5737,6 +6036,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
{
Panel *pa;
+ uiList *ui_list;
link_list(fd, &ar->panels);
@@ -5747,6 +6047,12 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
pa->type = NULL;
}
+ link_list(fd, &ar->ui_lists);
+
+ for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next) {
+ ui_list->type = NULL;
+ }
+
ar->regiondata = newdataadr(fd, ar->regiondata);
if (ar->regiondata) {
if (spacetype == SPACE_VIEW3D) {
@@ -5756,6 +6062,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
rv3d->clipbb = newdataadr(fd, rv3d->clipbb);
rv3d->depths = NULL;
+ rv3d->gpuoffscreen = NULL;
rv3d->ri = NULL;
rv3d->render_engine = NULL;
rv3d->sms = NULL;
@@ -5774,6 +6081,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
ar->type = NULL;
ar->swap = 0;
ar->do_draw = FALSE;
+ ar->regiontimer = NULL;
memset(&ar->drawrct, 0, sizeof(ar->drawrct));
}
@@ -5842,6 +6150,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
sa->handlers.first = sa->handlers.last = NULL;
sa->type = NULL; /* spacetype callbacks */
+ sa->region_active_win = -1;
for (ar = sa->regionbase.first; ar; ar = ar->next)
direct_link_region(fd, ar, sa->spacetype);
@@ -5890,6 +6199,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
v3d->afterdraw_xray.first = v3d->afterdraw_xray.last = NULL;
v3d->afterdraw_xraytransp.first = v3d->afterdraw_xraytransp.last = NULL;
v3d->properties_storage = NULL;
+ v3d->defmaterial = NULL;
/* render can be quite heavy, set to wire on load */
if (v3d->drawtype == OB_RENDER)
@@ -5918,6 +6228,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
soops->treestore->totelem = soops->treestore->usedelem;
soops->storeflag |= SO_TREESTORE_CLEANUP; // at first draw
}
+ soops->tree.first = soops->tree.last= NULL;
}
else if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)sl;
@@ -5950,6 +6261,15 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
snode->gpd = newdataadr(fd, snode->gpd);
direct_link_gpencil(fd, snode->gpd);
}
+
+ link_list(fd, &snode->treepath);
+ snode->edittree = NULL;
+ snode->linkdrag.first = snode->linkdrag.last = NULL;
+ }
+ else if (sl->spacetype == SPACE_TEXT) {
+ SpaceText *st= (SpaceText *)sl;
+
+ st->drawcache= NULL;
}
else if (sl->spacetype == SPACE_TIME) {
SpaceTime *stime = (SpaceTime *)sl;
@@ -5965,6 +6285,8 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
}
}
else if (sl->spacetype == SPACE_SEQ) {
+ SpaceSeq *sseq = (SpaceSeq *)sl;
+
/* grease pencil data is not a direct data and can't be linked from direct_link*
* functions, it should be linked from lib_link* functions instead
*
@@ -5973,17 +6295,26 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
* simple return NULL here (sergey)
*/
#if 0
- SpaceSeq *sseq = (SpaceSeq *)sl;
if (sseq->gpd) {
sseq->gpd = newdataadr(fd, sseq->gpd);
direct_link_gpencil(fd, sseq->gpd);
}
#endif
+ sseq->scopes.reference_ibuf = NULL;
+ sseq->scopes.zebra_ibuf = NULL;
+ sseq->scopes.waveform_ibuf = NULL;
+ sseq->scopes.sep_waveform_ibuf = NULL;
+ sseq->scopes.vector_ibuf = NULL;
+ sseq->scopes.histogram_ibuf = NULL;
+
}
else if (sl->spacetype == SPACE_BUTS) {
SpaceButs *sbuts = (SpaceButs *)sl;
+
sbuts->path= NULL;
sbuts->texuser= NULL;
+ sbuts->mainbo = sbuts->mainb;
+ sbuts->mainbuser = sbuts->mainb;
}
else if (sl->spacetype == SPACE_CONSOLE) {
SpaceConsole *sconsole = (SpaceConsole *)sl;
@@ -6023,6 +6354,14 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
sfile->op = NULL;
sfile->params = newdataadr(fd, sfile->params);
}
+ else if (sl->spacetype == SPACE_CLIP) {
+ SpaceClip *sclip = (SpaceClip *)sl;
+
+ sclip->scopes.track_search = NULL;
+ sclip->scopes.track_preview = NULL;
+ sclip->draw_context = NULL;
+ sclip->scopes.ok = 0;
+ }
}
sa->actionzones.first = sa->actionzones.last = NULL;
@@ -6041,6 +6380,7 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main)
{
Main *newmain;
+ /* check if the library was already read */
for (newmain = fd->mainlist->first; newmain; newmain = newmain->next) {
if (newmain->curlib) {
if (BLI_path_cmp(newmain->curlib->filepath, lib->filepath) == 0) {
@@ -6059,14 +6399,14 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main)
}
}
}
- /* make sure we have full path in lib->filename */
+ /* make sure we have full path in lib->filepath */
BLI_strncpy(lib->filepath, lib->name, sizeof(lib->name));
- cleanup_path(fd->relabase, lib->filepath);
+ BLI_cleanup_path(fd->relabase, lib->filepath);
-#if 0
- printf("direct_link_library: name %s\n", lib->name);
- printf("direct_link_library: filename %s\n", lib->filename);
-#endif
+// printf("direct_link_library: name %s\n", lib->name);
+// printf("direct_link_library: filepath %s\n", lib->filepath);
+
+ lib->packedfile = direct_link_packedfile(fd, lib->packedfile);
/* new main */
newmain= MEM_callocN(sizeof(Main), "directlink");
@@ -6256,6 +6596,9 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip)
clip->tracking.dopesheet.ok = 0;
clip->tracking.dopesheet.channels.first = clip->tracking.dopesheet.channels.last = NULL;
+ clip->tracking.dopesheet.coverage_segments.first = clip->tracking.dopesheet.coverage_segments.last = NULL;
+
+ clip->prefetch_ok = FALSE;
link_list(fd, &tracking->objects);
@@ -6389,6 +6732,179 @@ static void lib_link_mask(FileData *fd, Main *main)
}
}
+/* ************ READ LINE STYLE ***************** */
+
+static void lib_link_linestyle(FileData *fd, Main *main)
+{
+ FreestyleLineStyle *linestyle;
+ LineStyleModifier *m;
+
+ linestyle = main->linestyle.first;
+ while (linestyle) {
+ if (linestyle->id.flag & LIB_NEED_LINK) {
+ linestyle->id.flag -= LIB_NEED_LINK;
+
+ if (linestyle->id.properties)
+ IDP_LibLinkProperty(linestyle->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ if (linestyle->adt)
+ lib_link_animdata(fd, &linestyle->id, linestyle->adt);
+ for (m = linestyle->color_modifiers.first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleColorModifier_DistanceFromObject *cm = (LineStyleColorModifier_DistanceFromObject *)m;
+ cm->target = newlibadr(fd, linestyle->id.lib, cm->target);
+ }
+ break;
+ }
+ }
+ for (m = linestyle->alpha_modifiers.first; m; m = m->next){
+ switch (m->type) {
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleAlphaModifier_DistanceFromObject *am = (LineStyleAlphaModifier_DistanceFromObject *)m;
+ am->target = newlibadr(fd, linestyle->id.lib, am->target);
+ }
+ break;
+ }
+ }
+ for (m = linestyle->thickness_modifiers.first; m; m = m->next){
+ switch (m->type) {
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleThicknessModifier_DistanceFromObject *tm = (LineStyleThicknessModifier_DistanceFromObject *)m;
+ tm->target = newlibadr(fd, linestyle->id.lib, tm->target);
+ }
+ break;
+ }
+ }
+ }
+ linestyle = linestyle->id.next;
+ }
+}
+
+static void direct_link_linestyle_color_modifier(FileData *fd, LineStyleModifier *modifier)
+{
+ switch (modifier->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ {
+ LineStyleColorModifier_AlongStroke *m = (LineStyleColorModifier_AlongStroke *)modifier;
+ m->color_ramp = newdataadr(fd, m->color_ramp);
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ {
+ LineStyleColorModifier_DistanceFromCamera *m = (LineStyleColorModifier_DistanceFromCamera *)modifier;
+ m->color_ramp = newdataadr(fd, m->color_ramp);
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleColorModifier_DistanceFromObject *m = (LineStyleColorModifier_DistanceFromObject *)modifier;
+ m->color_ramp = newdataadr(fd, m->color_ramp);
+ }
+ break;
+ case LS_MODIFIER_MATERIAL:
+ {
+ LineStyleColorModifier_Material *m = (LineStyleColorModifier_Material *)modifier;
+ m->color_ramp = newdataadr(fd, m->color_ramp);
+ }
+ break;
+ }
+}
+
+static void direct_link_linestyle_alpha_modifier(FileData *fd, LineStyleModifier *modifier)
+{
+ switch (modifier->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ {
+ LineStyleAlphaModifier_AlongStroke *m = (LineStyleAlphaModifier_AlongStroke *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ {
+ LineStyleAlphaModifier_DistanceFromCamera *m = (LineStyleAlphaModifier_DistanceFromCamera *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleAlphaModifier_DistanceFromObject *m = (LineStyleAlphaModifier_DistanceFromObject *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ case LS_MODIFIER_MATERIAL:
+ {
+ LineStyleAlphaModifier_Material *m = (LineStyleAlphaModifier_Material *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ }
+}
+
+static void direct_link_linestyle_thickness_modifier(FileData *fd, LineStyleModifier *modifier)
+{
+ switch (modifier->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ {
+ LineStyleThicknessModifier_AlongStroke *m = (LineStyleThicknessModifier_AlongStroke *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ {
+ LineStyleThicknessModifier_DistanceFromCamera *m = (LineStyleThicknessModifier_DistanceFromCamera *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ {
+ LineStyleThicknessModifier_DistanceFromObject *m = (LineStyleThicknessModifier_DistanceFromObject *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ case LS_MODIFIER_MATERIAL:
+ {
+ LineStyleThicknessModifier_Material *m = (LineStyleThicknessModifier_Material *)modifier;
+ m->curve = newdataadr(fd, m->curve);
+ direct_link_curvemapping(fd, m->curve);
+ }
+ break;
+ }
+}
+
+static void direct_link_linestyle_geometry_modifier(FileData *UNUSED(fd), LineStyleModifier *UNUSED(modifier))
+{
+}
+
+static void direct_link_linestyle(FileData *fd, FreestyleLineStyle *linestyle)
+{
+ LineStyleModifier *modifier;
+
+ linestyle->adt= newdataadr(fd, linestyle->adt);
+ direct_link_animdata(fd, linestyle->adt);
+ link_list(fd, &linestyle->color_modifiers);
+ for(modifier = linestyle->color_modifiers.first; modifier; modifier = modifier->next)
+ direct_link_linestyle_color_modifier(fd, modifier);
+ link_list(fd, &linestyle->alpha_modifiers);
+ for(modifier = linestyle->alpha_modifiers.first; modifier; modifier = modifier->next)
+ direct_link_linestyle_alpha_modifier(fd, modifier);
+ link_list(fd, &linestyle->thickness_modifiers);
+ for(modifier = linestyle->thickness_modifiers.first; modifier; modifier = modifier->next)
+ direct_link_linestyle_thickness_modifier(fd, modifier);
+ link_list(fd, &linestyle->geometry_modifiers);
+ for(modifier = linestyle->geometry_modifiers.first; modifier; modifier = modifier->next)
+ direct_link_linestyle_geometry_modifier(fd, modifier);
+}
+
/* ************** GENERAL & MAIN ******************** */
@@ -6423,6 +6939,7 @@ static const char *dataname(short id_code)
case ID_PA: return "Data from PA";
case ID_GD: return "Data from GD";
case ID_MC: return "Data from MC";
+ case ID_LS: return "Data from LS";
}
return "Data from Lib Block";
@@ -6599,6 +7116,9 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
case ID_MSK:
direct_link_mask(fd, (Mask *)id);
break;
+ case ID_LS:
+ direct_link_linestyle(fd, (FreestyleLineStyle *)id);
+ break;
}
oldnewmap_free_unused(fd->datamap);
@@ -6625,6 +7145,17 @@ static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
bfd->globalf = fg->globalf;
BLI_strncpy(bfd->filename, fg->filename, sizeof(bfd->filename));
+ /* error in 2.65 and older: main->name was not set if you save from startup (not after loading file) */
+ if (bfd->filename[0] == 0) {
+ if (fd->fileversion < 265 || (fd->fileversion == 265 && fg->subversion < 1))
+ if ((G.fileflags & G_FILE_RECOVER)==0)
+ BLI_strncpy(bfd->filename, bfd->main->name, sizeof(bfd->filename));
+
+ /* early 2.50 version patch - filename not in FileGlobal struct at all */
+ if (fd->fileversion <= 250)
+ BLI_strncpy(bfd->filename, bfd->main->name, sizeof(bfd->filename));
+ }
+
if (G.fileflags & G_FILE_RECOVER)
BLI_strncpy(fd->relabase, fg->filename, sizeof(fd->relabase));
@@ -6650,7 +7181,6 @@ static void link_global(FileData *fd, BlendFileData *bfd)
}
}
-/* deprecated, only keep this for readfile.c */
void convert_tface_mt(FileData *fd, Main *main)
{
Main *gmain;
@@ -6685,22 +7215,6 @@ static void do_versions_nodetree_image_default_alpha_output(bNodeTree *ntree)
}
}
-static void do_version_ntree_tex_mapping_260(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == SH_NODE_MAPPING) {
- TexMapping *tex_mapping;
-
- tex_mapping= node->storage;
- tex_mapping->projx= PROJ_X;
- tex_mapping->projy= PROJ_Y;
- tex_mapping->projz= PROJ_Z;
- }
- }
-}
-
static void do_versions_nodetree_convert_angle(bNodeTree *ntree)
{
bNode *node;
@@ -6922,7 +7436,7 @@ static void do_versions_nodetree_multi_file_output_format_2_62_1(Scene *sce, bNo
nimf->format = sce->r.im_format;
/* transfer render format toggle to node format toggle */
- for (sock=node->inputs.first; sock; sock=sock->next) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
NodeImageMultiFileSocket *simf = sock->storage;
simf->use_node_format = simf->use_render_format;
}
@@ -6976,7 +7490,7 @@ static void do_versions_nodetree_file_output_layers_2_64_5(bNodeTree *ntree)
for (node=ntree->nodes.first; node; node=node->next) {
if (node->type == CMP_NODE_OUTPUT_FILE) {
bNodeSocket *sock;
- for (sock=node->inputs.first; sock; sock=sock->next) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
NodeImageMultiFileSocket *input = sock->storage;
/* multilayer names are stored as separate strings now,
@@ -7035,123 +7549,6 @@ static void do_versions_nodetree_frame_2_64_6(bNodeTree *ntree)
}
}
-static void do_version_ntree_image_user_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT)) {
- NodeTexImage *tex = node->storage;
-
- tex->iuser.frames= 1;
- tex->iuser.sfra= 1;
- tex->iuser.fie_ima= 2;
- tex->iuser.ok= 1;
- }
- }
-}
-
-static void do_version_ntree_dilateerode_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_DILATEERODE) {
- if (node->storage == NULL) {
- NodeDilateErode *data = MEM_callocN(sizeof(NodeDilateErode), __func__);
- data->falloff = PROP_SMOOTH;
- node->storage = data;
- }
- }
- }
-}
-
-static void do_version_ntree_defocus_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_DEFOCUS) {
- NodeDefocus *data = node->storage;
- if (data->maxblur == 0.0f) {
- data->maxblur = 16.0f;
- }
- }
- }
-}
-
-static void do_version_ntree_mask_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_MASK) {
- if (node->storage == NULL) {
- NodeMask *data = MEM_callocN(sizeof(NodeMask), __func__);
- /* move settings into own struct */
- data->size_x = (int)node->custom3;
- data->size_y = (int)node->custom4;
- node->custom3 = 0.5f; /* default shutter */
- node->storage = data;
- }
- }
- }
-}
-
-static void do_version_ntree_keying_despill_balance(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_KEYING) {
- NodeKeyingData *data = node->storage;
-
- if (data->despill_balance == 0.0f) {
- data->despill_balance = 0.5f;
- }
- }
- }
-}
-
-static void do_version_ntree_tex_coord_from_dupli_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
-
- for (node = ntree->nodes.first; node; node = node->next)
- if (node->type == SH_NODE_TEX_COORD)
- node->flag |= NODE_OPTIONS;
-}
-
-static void do_version_node_cleanup_dynamic_sockets_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
- bNodeSocket *sock;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (!ELEM(node->type, NODE_GROUP, CMP_NODE_IMAGE)) {
- for (sock = node->inputs.first; sock; sock = sock->next)
- sock->flag &= ~SOCK_DYNAMIC;
- for (sock = node->outputs.first; sock; sock = sock->next)
- sock->flag &= ~SOCK_DYNAMIC;
- }
- }
-}
-
-static void do_version_node_fix_internal_links_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
- bNode *node;
- bNodeLink *link, *nextlink;
-
- for (node = ntree->nodes.first; node; node = node->next) {
- for (link = node->internal_links.first; link; link = nextlink) {
- nextlink = link->next;
- if (!link->fromnode || !link->fromsock || !link->tonode || !link->tosock) {
- BLI_remlink(&node->internal_links, link);
- }
- }
- }
-}
-
static void do_version_logic_264(ListBase *regionbase)
{
ARegion *ar;
@@ -7204,6 +7601,171 @@ static void do_versions_affine_tracker_track(MovieTrackingTrack *track)
}
+static const char *node_get_static_idname(int type, int treetype)
+{
+ /* use static type info header to map static int type to identifier string */
+ #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ case ID: return #Category #StructName;
+
+ /* XXX hack, group types share a single static integer identifier, but are registered as separate types */
+ if (type == NODE_GROUP) {
+ switch (treetype) {
+ case NTREE_COMPOSIT: return "CompositorNodeGroup";
+ case NTREE_SHADER: return "ShaderNodeGroup";
+ case NTREE_TEXTURE: return "TextureNodeGroup";
+ }
+ }
+ else {
+ switch (type) {
+ #include "NOD_static_types.h"
+ }
+ }
+ return "";
+}
+
+static const char *node_socket_get_static_idname(bNodeSocket *sock)
+{
+ switch (sock->type) {
+ case SOCK_FLOAT: {
+ bNodeSocketValueFloat *dval = sock->default_value;
+ return nodeStaticSocketType(SOCK_FLOAT, dval->subtype);
+ }
+ case SOCK_INT: {
+ bNodeSocketValueInt *dval = sock->default_value;
+ return nodeStaticSocketType(SOCK_INT, dval->subtype);
+ }
+ case SOCK_BOOLEAN: {
+ return nodeStaticSocketType(SOCK_BOOLEAN, PROP_NONE);
+ }
+ case SOCK_VECTOR: {
+ bNodeSocketValueVector *dval = sock->default_value;
+ return nodeStaticSocketType(SOCK_VECTOR, dval->subtype);
+ }
+ case SOCK_RGBA: {
+ return nodeStaticSocketType(SOCK_RGBA, PROP_NONE);
+ }
+ case SOCK_STRING: {
+ bNodeSocketValueString *dval = sock->default_value;
+ return nodeStaticSocketType(SOCK_STRING, dval->subtype);
+ }
+ case SOCK_SHADER: {
+ return nodeStaticSocketType(SOCK_SHADER, PROP_NONE);
+ }
+ }
+ return "";
+}
+
+static void do_versions_nodetree_customnodes(bNodeTree *ntree, int UNUSED(is_group))
+{
+ /* initialize node tree type idname */
+ {
+ bNode *node;
+ bNodeSocket *sock;
+
+ ntree->typeinfo = NULL;
+
+ /* tree type idname */
+ switch (ntree->type) {
+ case NTREE_COMPOSIT:
+ strcpy(ntree->idname, "CompositorNodeTree");
+ break;
+ case NTREE_SHADER:
+ strcpy(ntree->idname, "ShaderNodeTree");
+ break;
+ case NTREE_TEXTURE:
+ strcpy(ntree->idname, "TextureNodeTree");
+ break;
+ }
+
+ /* node type idname */
+ for (node=ntree->nodes.first; node; node=node->next) {
+ BLI_strncpy(node->idname, node_get_static_idname(node->type, ntree->type), sizeof(node->idname));
+
+ /* existing old nodes have been initialized already */
+ node->flag |= NODE_INIT;
+
+ /* sockets idname */
+ for (sock = node->inputs.first; sock; sock = sock->next)
+ BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
+ for (sock = node->outputs.first; sock; sock = sock->next)
+ BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
+ }
+ /* tree sockets idname */
+ for (sock = ntree->inputs.first; sock; sock = sock->next)
+ BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
+ for (sock = ntree->outputs.first; sock; sock = sock->next)
+ BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
+ }
+
+ /* initialize socket in_out values */
+ {
+ bNode *node;
+ bNodeSocket *sock;
+
+ for (node=ntree->nodes.first; node; node=node->next) {
+ for (sock = node->inputs.first; sock; sock = sock->next)
+ sock->in_out = SOCK_IN;
+ for (sock = node->outputs.first; sock; sock = sock->next)
+ sock->in_out = SOCK_OUT;
+ }
+ for (sock = ntree->inputs.first; sock; sock = sock->next)
+ sock->in_out = SOCK_IN;
+ for (sock = ntree->outputs.first; sock; sock = sock->next)
+ sock->in_out = SOCK_OUT;
+ }
+
+ /* initialize socket identifier strings */
+ {
+ bNode *node;
+ bNodeSocket *sock;
+
+ for (node=ntree->nodes.first; node; node=node->next) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
+ BLI_uniquename(&node->inputs, sock, sock->identifier, '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
+ }
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
+ BLI_uniquename(&node->outputs, sock, sock->identifier, '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
+ }
+ }
+ for (sock = ntree->inputs.first; sock; sock = sock->next) {
+ BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
+ BLI_uniquename(&ntree->inputs, sock, sock->identifier, '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
+ }
+ for (sock = ntree->outputs.first; sock; sock = sock->next) {
+ BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
+ BLI_uniquename(&ntree->outputs, sock, sock->identifier, '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
+ }
+ }
+}
+
+/* initialize userdef with non-UI dependency stuff */
+/* other initializers (such as theme color defaults) go to resources.c */
+static void do_versions_userdef(FileData *fd, BlendFileData *bfd)
+{
+ Main *bmain = bfd->main;
+ UserDef *user = bfd->user;
+
+ if (user == NULL) return;
+
+ if (MAIN_VERSION_OLDER(bmain, 266, 4)) {
+ bTheme *btheme;
+
+ /* themes for Node and Sequence editor were not using grid color, but back. we copy this over then */
+ for (btheme = user->themes.first; btheme; btheme = btheme->next) {
+ copy_v4_v4_char(btheme->tnode.grid, btheme->tnode.back);
+ copy_v4_v4_char(btheme->tseq.grid, btheme->tseq.back);
+ }
+ }
+
+ if (bmain->versionfile < 267) {
+
+ if (!DNA_struct_elem_find(fd->filesdna, "UserDef", "short", "image_gpubuffer_limit"))
+ user->image_gpubuffer_limit = 20;
+
+ }
+}
static void do_versions(FileData *fd, Library *lib, Main *main)
{
/* WATCH IT!!!: pointers from libdata have not been converted */
@@ -7269,10 +7831,21 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 2)) {
- bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER);
-
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_ntree_tex_mapping_260);
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_MAPPING) {
+ TexMapping *tex_mapping;
+
+ tex_mapping= node->storage;
+ tex_mapping->projx= PROJ_X;
+ tex_mapping->projy= PROJ_Y;
+ tex_mapping->projz= PROJ_Z;
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
}
if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 4)) {
@@ -7503,7 +8076,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
for (ob = main->object.first; ob; ob = ob->id.next) {
bConstraint *con;
for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
if (!cti)
continue;
@@ -7527,7 +8100,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
prop = BKE_bproperty_object_get(ob, "Text");
if (prop) {
BKE_reportf_wrap(fd->reports, RPT_WARNING,
- TIP_("Game property name conflict in object '%s':\ntext objects reserve the "
+ TIP_("Game property name conflict in object '%s': text objects reserve the "
"['Text'] game property to change their content through logic bricks"),
ob->id.name + 2);
}
@@ -7884,7 +8457,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
if (md->type == eModifierType_Smoke) {
SmokeModifierData *smd = (SmokeModifierData *)md;
if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
- int maxres = MAX3(smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]);
+ int maxres = max_iii(smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]);
smd->domain->scale = smd->domain->dx * maxres;
smd->domain->dx = 1.0f / smd->domain->scale;
}
@@ -7908,16 +8481,26 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 9)) {
- bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER);
-
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_ntree_image_user_264);
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT)) {
+ NodeTexImage *tex = node->storage;
+
+ tex->iuser.frames= 1;
+ tex->iuser.sfra= 1;
+ tex->iuser.fie_ima= 2;
+ tex->iuser.ok= 1;
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
}
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 10)) {
{
Scene *scene;
- bNodeTreeType *ntreetype;
// composite redesign
for (scene=main->scene.first; scene; scene=scene->id.next) {
if (scene->nodetree) {
@@ -7926,11 +8509,20 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
}
- ntreetype = ntreeGetType(NTREE_COMPOSIT);
-
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_ntree_defocus_264);
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_DEFOCUS) {
+ NodeDefocus *data = node->storage;
+ if (data->maxblur == 0.0f) {
+ data->maxblur = 16.0f;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
}
{
@@ -7988,19 +8580,40 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 13)) {
- bNodeTreeType *ntreetype = ntreeGetType(NTREE_COMPOSIT);
-
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_ntree_dilateerode_264);
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_DILATEERODE) {
+ if (node->storage == NULL) {
+ NodeDilateErode *data = MEM_callocN(sizeof(NodeDilateErode), __func__);
+ data->falloff = PROP_SMOOTH;
+ node->storage = data;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
}
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 14)) {
ParticleSettings *part;
- bNodeTreeType *ntreetype = ntreeGetType(NTREE_COMPOSIT);
-
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_ntree_keying_despill_balance);
-
+
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_KEYING) {
+ NodeKeyingData *data = node->storage;
+
+ if (data->despill_balance == 0.0f) {
+ data->despill_balance = 0.5f;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+
/* keep compatibility for dupliobject particle size */
for (part=main->particle.first; part; part=part->id.next)
if (ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR))
@@ -8009,12 +8622,25 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 17)) {
- bNodeTreeType *ntreetype = ntreeGetType(NTREE_COMPOSIT);
-
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_ntree_mask_264);
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_MASK) {
+ if (node->storage == NULL) {
+ NodeMask *data = MEM_callocN(sizeof(NodeMask), __func__);
+ /* move settings into own struct */
+ data->size_x = (int)node->custom3;
+ data->size_y = (int)node->custom4;
+ node->custom3 = 0.5f; /* default shutter */
+ node->storage = data;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
}
-
+
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 18)) {
Scene *scene;
@@ -8139,15 +8765,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 1)) {
- bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER);
- bNodeTree *ntree;
-
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_ntree_tex_coord_from_dupli_264);
-
- for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
- if (ntree->type==NTREE_SHADER)
- do_version_ntree_tex_coord_from_dupli_264(NULL, NULL, ntree);
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next)
+ if (node->type == SH_NODE_TEX_COORD)
+ node->flag |= NODE_OPTIONS;
+ }
+ } FOREACH_NODETREE_END
}
if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 2)) {
@@ -8233,28 +8858,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
- if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 4)) {
- /* Fix for old node flags: Apparently the SOCK_DYNAMIC flag has been in use for other
- * purposes before and then removed and later reused for SOCK_DYNAMIC. This socket should
- * only be used by certain node types which don't use template lists, cleaning this up here.
- */
- bNodeTreeType *ntreetype;
- bNodeTree *ntree;
-
- ntreetype = ntreeGetType(NTREE_COMPOSIT);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_node_cleanup_dynamic_sockets_264);
- ntreetype = ntreeGetType(NTREE_SHADER);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_node_cleanup_dynamic_sockets_264);
- ntreetype = ntreeGetType(NTREE_TEXTURE);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_node_cleanup_dynamic_sockets_264);
-
- for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
- do_version_node_cleanup_dynamic_sockets_264(NULL, NULL, ntree);
- }
-
if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 5)) {
/* set a unwrapping margin and ABF by default */
Scene *scene;
@@ -8271,22 +8874,19 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
/* Fix for bug #32982, internal_links list could get corrupted from r51630 onward.
* Simply remove bad internal_links lists to avoid NULL pointers.
*/
- bNodeTreeType *ntreetype;
- bNodeTree *ntree;
-
- ntreetype = ntreeGetType(NTREE_COMPOSIT);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_internal_links_264);
- ntreetype = ntreeGetType(NTREE_SHADER);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_internal_links_264);
- ntreetype = ntreeGetType(NTREE_TEXTURE);
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_internal_links_264);
-
- for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
- do_version_node_fix_internal_links_264(NULL, NULL, ntree);
-
+ FOREACH_NODETREE(main, ntree, id)
+ bNode *node;
+ bNodeLink *link, *nextlink;
+
+ for (node = ntree->nodes.first; node; node = node->next) {
+ for (link = node->internal_links.first; link; link = nextlink) {
+ nextlink = link->next;
+ if (!link->fromnode || !link->fromsock || !link->tonode || !link->tosock) {
+ BLI_remlink(&node->internal_links, link);
+ }
+ }
+ }
+ FOREACH_NODETREE_END
}
if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 6)) {
@@ -8382,8 +8982,390 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
+ if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 3)) {
+ bScreen *sc;
+ for (sc = main->screen.first; sc; sc = sc->id.next) {
+ ScrArea *sa;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ switch (sl->spacetype) {
+ case SPACE_VIEW3D:
+ {
+ View3D *v3d = (View3D *)sl;
+ v3d->flag2 |= V3D_SHOW_GPENCIL;
+ break;
+ }
+ case SPACE_SEQ:
+ {
+ SpaceSeq *sseq = (SpaceSeq *)sl;
+ sseq->flag |= SEQ_SHOW_GPENCIL;
+ break;
+ }
+ case SPACE_IMAGE:
+ {
+ SpaceImage *sima = (SpaceImage *)sl;
+ sima->flag |= SI_SHOW_GPENCIL;
+ break;
+ }
+ case SPACE_NODE:
+ {
+ SpaceNode *snode = (SpaceNode *)sl;
+ snode->flag |= SNODE_SHOW_GPENCIL;
+ break;
+ }
+ case SPACE_CLIP:
+ {
+ SpaceClip *sclip = (SpaceClip *)sl;
+ sclip->flag |= SC_SHOW_GPENCIL;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 5)) {
+ Scene *scene;
+ Image *image;
+ Tex *tex;
+
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ Sequence *seq;
+ bool set_premul = false;
+
+ SEQ_BEGIN (scene->ed, seq)
+ {
+ if (seq->flag & SEQ_MAKE_PREMUL) {
+ seq->alpha_mode = SEQ_ALPHA_STRAIGHT;
+ }
+ else {
+ BKE_sequence_alpha_mode_from_extension(seq);
+ }
+ }
+ SEQ_END
+
+ if (scene->r.bake_samples == 0)
+ scene->r.bake_samples = 256;
+
+ if (scene->world) {
+ World *world = blo_do_versions_newlibadr(fd, scene->id.lib, scene->world);
+
+ if (world && is_zero_v3(&world->horr)) {
+ if ((world->skytype & WO_SKYBLEND) == 0 || is_zero_v3(&world->zenr)) {
+ set_premul = true;
+ }
+ }
+ }
+ else
+ set_premul = true;
+
+ if (set_premul) {
+ printf("2.66 versioning fix: replacing black sky with premultiplied alpha for scene %s\n", scene->id.name + 2);
+ scene->r.alphamode = R_ALPHAPREMUL;
+ }
+ }
+
+ for (image = main->image.first; image; image = image->id.next) {
+ if (image->flag & IMA_DO_PREMUL) {
+ image->alpha_mode = IMA_ALPHA_STRAIGHT;
+ }
+ else {
+ BKE_image_alpha_mode_from_extension(image);
+ }
+ }
+
+ for (tex = main->tex.first; tex; tex = tex->id.next) {
+ if (tex->type == TEX_IMAGE && (tex->imaflag & TEX_USEALPHA) == 0) {
+ image = blo_do_versions_newlibadr(fd, tex->id.lib, tex->ima);
+
+ if (image && (image->flag & IMA_DO_PREMUL) == 0)
+ image->flag |= IMA_IGNORE_ALPHA;
+ }
+ }
+
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_IMAGE) {
+ Image *image = blo_do_versions_newlibadr(fd, ntree->id.lib, node->id);
+
+ if (image) {
+ if ((image->flag & IMA_DO_PREMUL) == 0 && image->alpha_mode == IMA_ALPHA_STRAIGHT)
+ node->custom1 |= CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
+ else if (main->versionfile < 266 || (main->versionfile == 266 && main->subversionfile < 1)) {
+ /* texture use alpha was removed for 2.66 but added back again for 2.66a,
+ * for compatibility all textures assumed it to be enabled */
+ Tex *tex;
+
+ for (tex = main->tex.first; tex; tex = tex->id.next)
+ if (tex->type == TEX_IMAGE)
+ tex->imaflag |= TEX_USEALPHA;
+ }
+
+ if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 7)) {
+ Curve *cu;
+
+ for (cu = main->curve.first; cu; cu = cu->id.next) {
+ if (cu->flag & (CU_FRONT | CU_BACK)) {
+ if ( cu->ext1 != 0.0f || cu->ext2 != 0.0f) {
+ Nurb *nu;
+
+ for (nu = cu->nurb.first; nu; nu = nu->next) {
+ int a;
+
+ if (nu->bezt) {
+ BezTriple *bezt = nu->bezt;
+ a = nu->pntsu;
+
+ while (a--) {
+ bezt->radius = 1.0f;
+ bezt++;
+ }
+ }
+ else if (nu->bp) {
+ BPoint *bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+
+ while (a--) {
+ bp->radius = 1.0f;
+ bp++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (MAIN_VERSION_OLDER(main, 265, 9)) {
+ Mesh *me;
+ for (me = main->mesh.first; me; me = me->id.next) {
+ BKE_mesh_do_versions_cd_flag_init(me);
+ }
+ }
+
+ if (MAIN_VERSION_OLDER(main, 265, 10)) {
+ Brush *br;
+ for (br = main->brush.first; br; br = br->id.next) {
+ if (br->ob_mode & OB_MODE_TEXTURE_PAINT) {
+ br->mtex.brush_map_mode = MTEX_MAP_MODE_TILED;
+ }
+ }
+ }
+
+ // add storage for compositor translate nodes when not existing
+ if (MAIN_VERSION_OLDER(main, 265, 11)) {
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ bNode *node;
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_TRANSLATE && node->storage == NULL) {
+ node->storage = MEM_callocN(sizeof(NodeTranslateData), "node translate data");
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
+
+ if (MAIN_VERSION_OLDER(main, 266, 2)) {
+ FOREACH_NODETREE(main, ntree, id) {
+ do_versions_nodetree_customnodes(ntree, ((ID *)ntree == id));
+ } FOREACH_NODETREE_END
+ }
+
+ if (MAIN_VERSION_OLDER(main, 266, 2)) {
+ bScreen *sc;
+ for (sc= main->screen.first; sc; sc= sc->id.next) {
+ ScrArea *sa;
+ for (sa= sc->areabase.first; sa; sa= sa->next) {
+ SpaceLink *sl;
+ for (sl= sa->spacedata.first; sl; sl= sl->next) {
+ if (sl->spacetype==SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)sl;
+
+ /* reset pointers to force tree path update from context */
+ snode->nodetree = NULL;
+ snode->edittree = NULL;
+ snode->id = NULL;
+ snode->from = NULL;
+
+ /* convert deprecated treetype setting to tree_idname */
+ switch (snode->treetype) {
+ case NTREE_COMPOSIT:
+ strcpy(snode->tree_idname, "CompositorNodeTree");
+ break;
+ case NTREE_SHADER:
+ strcpy(snode->tree_idname, "ShaderNodeTree");
+ break;
+ case NTREE_TEXTURE:
+ strcpy(snode->tree_idname, "TextureNodeTree");
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Set flag for delayed do_versions in lib_verify_nodetree. It needs valid typeinfo pointers ... */
+ {
+ FOREACH_NODETREE(main, ntree, id) {
+ /* XXX This should be kept without version check for now!
+ * As long as USE_NODE_COMPAT_CUSTOMNODES is active, files will write links
+ * to tree interface sockets for forward compatibility. These links need to be removed again
+ * on file load in new versions.
+ * Once forward compatibility is not required any longer, make a subversion bump
+ * and only execute this for older versions.
+ */
+ ntree->flag |= NTREE_DO_VERSIONS_CUSTOMNODES_GROUP;
+
+ /* Only add interface nodes once.
+ * In old Blender versions they will be removed automatically due to undefined type */
+ if (MAIN_VERSION_OLDER(main, 266, 2))
+ ntree->flag |= NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE;
+ }
+ FOREACH_NODETREE_END
+ }
+
+ if (MAIN_VERSION_OLDER(main, 266, 3)) {
+ {
+ /* Fix for a very old issue:
+ * Node names were nominally made unique in r24478 (2.50.8), but the do_versions check
+ * to update existing node names only applied to main->nodetree (i.e. group nodes).
+ * Uniqueness is now required for proper preview mapping,
+ * so do this now to ensure old files don't break.
+ */
+ bNode *node;
+ FOREACH_NODETREE(main, ntree, id) {
+ if (id == &ntree->id)
+ continue; /* already fixed for node groups */
+
+ for (node = ntree->nodes.first; node; node = node->next)
+ nodeUniqueName(ntree, node);
+ }
+ FOREACH_NODETREE_END
+ }
+ }
+
+ if (main->versionfile < 267) {
+
+ /* TIP: to initialize new variables added, use the new function
+ DNA_struct_elem_find(fd->filesdna, "structname", "typename", "varname")
+ example:
+ if (!DNA_struct_elem_find(fd->filesdna, "UserDef", "short", "image_gpubuffer_limit"))
+ user->image_gpubuffer_limit = 10;
+ */
+
+ }
+
+ /* default values in Freestyle settings */
+ {
+ Scene *sce;
+ SceneRenderLayer *srl;
+ FreestyleLineStyle *linestyle;
+
+ for(sce = main->scene.first; sce; sce = sce->id.next) {
+ if (sce->r.line_thickness_mode == 0) {
+ sce->r.line_thickness_mode = R_LINE_THICKNESS_ABSOLUTE;
+ sce->r.unit_line_thickness = 1.0f;
+ }
+ for(srl = sce->r.layers.first; srl; srl = srl->next) {
+ if (srl->freestyleConfig.mode == 0)
+ srl->freestyleConfig.mode = FREESTYLE_CONTROL_EDITOR_MODE;
+ if (srl->freestyleConfig.raycasting_algorithm == FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE ||
+ srl->freestyleConfig.raycasting_algorithm == FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL) {
+ srl->freestyleConfig.raycasting_algorithm = 0; /* deprecated */
+ srl->freestyleConfig.flags |= FREESTYLE_CULLING;
+ }
+ }
+ }
+ for(linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) {
+#if 1
+ /* disable the Misc panel for now */
+ if (linestyle->panel == LS_PANEL_MISC) {
+ linestyle->panel = LS_PANEL_STROKES;
+ }
+#endif
+ if (linestyle->thickness_position == 0) {
+ linestyle->thickness_position = LS_THICKNESS_CENTER;
+ linestyle->thickness_ratio = 0.5f;
+ }
+ if (linestyle->chaining == 0)
+ linestyle->chaining = LS_CHAINING_PLAIN;
+ if (linestyle->rounds == 0)
+ linestyle->rounds = 3;
+ }
+ }
+ /* The code segment below will be removed when the trunk merger is done.
+ For now it is kept for backward compatibility, giving branch users time
+ to migrate to the new CustomData-based edge/face marks. */
+ {
+ Mesh *me;
+ MEdge *medge;
+ MPoly *mpoly;
+ int i, found;
+
+ for (me = main->mesh.first; me; me = me->id.next) {
+ /* Freestyle edge marks */
+ found = 0;
+ medge = me->medge;
+ for (i = 0; i < me->totedge; i++) {
+ if (medge->flag & ME_FREESTYLE_EDGE) {
+ found = 1;
+ break;
+ }
+ medge++;
+ }
+ if (found) {
+ FreestyleEdge *fed = CustomData_add_layer(&me->edata, CD_FREESTYLE_EDGE, CD_CALLOC, NULL, me->totedge);
+ medge = me->medge;
+ for (i = 0; i < me->totedge; i++) {
+ if (medge->flag & ME_FREESTYLE_EDGE) {
+ medge->flag &= ~ME_FREESTYLE_EDGE;
+ fed->flag |= FREESTYLE_EDGE_MARK;
+ }
+ medge++;
+ fed++;
+ }
+ printf("Migrated to CustomData-based Freestyle edge marks\n");
+ }
+ /* Freestyle face marks */
+ found = 0;
+ mpoly = me->mpoly;
+ for (i = 0; i < me->totpoly; i++) {
+ if (mpoly->flag & ME_FREESTYLE_FACE) {
+ found = 1;
+ break;
+ }
+ mpoly++;
+ }
+ if (found) {
+ FreestyleFace *ffa = CustomData_add_layer(&me->pdata, CD_FREESTYLE_FACE, CD_CALLOC, NULL, me->totpoly);
+ mpoly = me->mpoly;
+ for (i = 0; i < me->totpoly; i++) {
+ if (mpoly->flag & ME_FREESTYLE_FACE) {
+ mpoly->flag &= ~ME_FREESTYLE_FACE;
+ ffa->flag |= FREESTYLE_FACE_MARK;
+ }
+ mpoly++;
+ ffa++;
+ }
+ printf("Migrated to CustomData-based Freestyle face marks\n");
+ }
+ }
+ }
+
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
- /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
+ /* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */
/* don't forget to set version number in blender.c! */
}
@@ -8401,8 +9383,11 @@ static void lib_link_all(FileData *fd, Main *main)
{
oldnewmap_sort(fd);
+ /* No load UI for undo memfiles */
+ if (fd->memfile == NULL) {
lib_link_windowmanager(fd, main);
lib_link_screen(fd, main);
+ }
lib_link_scene(fd, main);
lib_link_object(fd, main);
lib_link_curve(fd, main);
@@ -8428,6 +9413,7 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_particlesettings(fd, main);
lib_link_movieclip(fd, main);
lib_link_mask(fd, main);
+ lib_link_linestyle(fd, main);
lib_link_mesh(fd, main); /* as last: tpage images with users at zero */
@@ -8449,9 +9435,14 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
wmKeyMap *keymap;
wmKeyMapItem *kmi;
wmKeyMapDiffItem *kmdi;
+ bAddon *addon;
bfd->user = user= read_struct(fd, bhead, "user def");
+ /* User struct has separate do-version handling */
+ user->versionfile = bfd->main->versionfile;
+ user->subversionfile = bfd->main->subversionfile;
+
/* read all data into fd->datamap */
bhead = read_data_into_oldnewmap(fd, bhead, "user def");
@@ -8487,6 +9478,13 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
direct_link_keymapitem(fd, kmi);
}
+ for (addon = user->addons.first; addon; addon = addon->next) {
+ addon->prop = newdataadr(fd, addon->prop);
+ if (addon->prop) {
+ IDP_DirectLinkProperty(addon->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ }
+ }
+
// XXX
user->uifonts.first = user->uifonts.last= NULL;
@@ -8565,9 +9563,11 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
}
/* do before read_libraries, but skip undo case */
-// if (fd->memfile==NULL) (the mesh shuffle hacks don't work yet? ton)
+ if (fd->memfile==NULL)
do_versions(fd, NULL, bfd->main);
+ do_versions_userdef(fd, bfd);
+
read_libraries(fd, &mainlist);
blo_join_main(&mainlist);
@@ -8610,7 +9610,7 @@ static void sort_bhead_old_map(FileData *fd)
fd->tot_bheadmap = tot;
if (tot == 0) return;
- bhs = fd->bheadmap = MEM_mallocN(tot*sizeof(struct BHeadSort), STRINGIFY(BHeadSort));
+ bhs = fd->bheadmap = MEM_mallocN(tot * sizeof(struct BHeadSort), "BHeadSort");
for (bhead = blo_firstbhead(fd); bhead; bhead = blo_nextbhead(fd, bhead), bhs++) {
bhs->bhead = bhead;
@@ -8675,9 +9675,10 @@ static ID *is_yet_read(FileData *fd, Main *mainvar, BHead *bhead)
return BLI_findstring(which_libbase(mainvar, GS(idname)), idname, offsetof(ID, name));
}
-static void expand_doit(FileData *fd, Main *mainvar, void *old)
+static void expand_doit_library(void *fdhandle, Main *mainvar, void *old)
{
BHead *bhead;
+ FileData *fd = fdhandle;
ID *id;
bhead = find_bhead(fd, old);
@@ -8690,6 +9691,14 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old)
Library *lib = read_struct(fd, bheadlib, "Library");
Main *ptr = blo_find_main(fd, lib->name, fd->relabase);
+ if (ptr->curlib == NULL) {
+ const char *idname= bhead_id_name(fd, bhead);
+
+ BKE_reportf_wrap(fd->reports, RPT_WARNING, TIP_("LIB ERROR: Data refers to main .blend file: '%s' from %s"),
+ idname, mainvar->curlib->filepath);
+ return;
+ }
+ else
id = is_yet_read(fd, ptr, bhead);
if (id == NULL) {
@@ -8744,7 +9753,7 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old)
}
}
-
+static void (*expand_doit)(void *, Main *, void *);
// XXX deprecated - old animation system
static void expand_ipo(FileData *fd, Main *mainvar, Ipo *ipo)
@@ -9129,7 +10138,7 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
ced.fd = fd;
ced.mainvar = mainvar;
- id_loop_constraints(lb, expand_constraint_cb, &ced);
+ BKE_id_loop_constraints(lb, expand_constraint_cb, &ced);
/* deprecated manual expansion stuff */
for (curcon = lb->first; curcon; curcon = curcon->next) {
@@ -9335,13 +10344,19 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
if (ob->pd && ob->pd->tex)
expand_doit(fd, mainvar, ob->pd->tex);
-
+
+ if (ob->rigidbody_constraint) {
+ expand_doit(fd, mainvar, ob->rigidbody_constraint->ob1);
+ expand_doit(fd, mainvar, ob->rigidbody_constraint->ob2);
+ }
+
}
static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
{
Base *base;
SceneRenderLayer *srl;
+ FreestyleLineSet *lineset;
for (base = sce->base.first; base; base = base->next) {
expand_doit(fd, mainvar, base->object);
@@ -9362,6 +10377,11 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
for (srl = sce->r.layers.first; srl; srl = srl->next) {
expand_doit(fd, mainvar, srl->mat_override);
expand_doit(fd, mainvar, srl->light_override);
+ for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+ if (lineset->group)
+ expand_doit(fd, mainvar, lineset->group);
+ expand_doit(fd, mainvar, lineset->linestyle);
+ }
}
if (sce->r.dometext)
@@ -9381,6 +10401,11 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
}
SEQ_END
}
+
+ if (sce->rigidbody_world) {
+ expand_doit(fd, mainvar, sce->rigidbody_world->group);
+ expand_doit(fd, mainvar, sce->rigidbody_world->constraints);
+ }
#ifdef DURIAN_CAMERA_SWITCH
{
@@ -9455,20 +10480,44 @@ static void expand_mask(FileData *fd, Main *mainvar, Mask *mask)
}
}
-static void expand_main(FileData *fd, Main *mainvar)
+static void expand_linestyle(FileData *fd, Main *mainvar, FreestyleLineStyle *linestyle)
+{
+ LineStyleModifier *m;
+
+ if (linestyle->adt)
+ expand_animdata(fd, mainvar, linestyle->adt);
+ for (m = linestyle->color_modifiers.first; m; m = m->next) {
+ if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT)
+ expand_doit(fd, mainvar, ((LineStyleColorModifier_DistanceFromObject *)m)->target);
+ }
+ for (m = linestyle->alpha_modifiers.first; m; m = m->next){
+ if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT)
+ expand_doit(fd, mainvar, ((LineStyleAlphaModifier_DistanceFromObject *)m)->target);
+ }
+ for (m = linestyle->thickness_modifiers.first; m; m = m->next){
+ if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT)
+ expand_doit(fd, mainvar, ((LineStyleThicknessModifier_DistanceFromObject *)m)->target);
+ }
+}
+
+void BLO_main_expander(void (*expand_doit_func)(void *, Main *, void *))
+{
+ expand_doit = expand_doit_func;
+}
+
+void BLO_expand_main(void *fdhandle, Main *mainvar)
{
ListBase *lbarray[MAX_LIBARRAY];
+ FileData *fd = fdhandle;
ID *id;
int a, do_it = TRUE;
- if (fd == NULL) return;
-
while (do_it) {
do_it = FALSE;
a = set_listbasepointers(mainvar, lbarray);
while (a--) {
- id= lbarray[a]->first;
+ id = lbarray[a]->first;
while (id) {
if (id->flag & LIB_NEED_EXPAND) {
switch (GS(id->name)) {
@@ -9541,6 +10590,9 @@ static void expand_main(FileData *fd, Main *mainvar)
case ID_MSK:
expand_mask(fd, mainvar, (Mask *)id);
break;
+ case ID_LS:
+ expand_linestyle(fd, mainvar, (FreestyleLineStyle *)id);
+ break;
}
do_it = TRUE;
@@ -9553,6 +10605,9 @@ static void expand_main(FileData *fd, Main *mainvar)
}
}
+
+/* ***************************** */
+
static int object_in_any_scene(Main *mainvar, Object *ob)
{
Scene *sce;
@@ -9565,7 +10620,7 @@ static int object_in_any_scene(Main *mainvar, Object *ob)
return 0;
}
-static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, const short idcode, const short is_link)
+static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, const short idcode, const short is_link, const short active_lay)
{
Object *ob;
Base *base;
@@ -9608,7 +10663,10 @@ static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, const
if (do_it) {
base = MEM_callocN(sizeof(Base), "add_ext_base");
- BLI_addtail(&(sce->base), base);
+ BLI_addtail(&sce->base, base);
+
+ if (active_lay) ob->lay = sce->lay;
+
base->lay = ob->lay;
base->object = ob;
base->flag = ob->flag;
@@ -9632,7 +10690,7 @@ static void give_base_to_groups(Main *mainvar, Scene *scene)
Base *base;
/* BKE_object_add(...) messes with the selection */
- Object *ob = BKE_object_add_only_object(OB_EMPTY, group->id.name+2);
+ Object *ob = BKE_object_add_only_object(mainvar, OB_EMPTY, group->id.name + 2);
ob->type = OB_EMPTY;
ob->lay = scene->lay;
@@ -9640,13 +10698,13 @@ static void give_base_to_groups(Main *mainvar, Scene *scene)
base = BKE_scene_base_add(scene, ob);
base->flag |= SELECT;
base->object->flag= base->flag;
- ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
scene->basact = base;
/* assign the group */
ob->dup_group = group;
ob->transflag |= OB_DUPLIGROUP;
- rename_id(&ob->id, group->id.name+2);
+ rename_id(&ob->id, group->id.name + 2);
copy_v3_v3(ob->loc, scene->cursor);
}
}
@@ -9679,7 +10737,8 @@ static ID *append_named_part(Main *mainl, FileData *fd, const char *idname, cons
}
else {
/* already linked */
- printf("append: already linked\n");
+ 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;
@@ -9701,6 +10760,28 @@ static ID *append_named_part(Main *mainl, FileData *fd, const char *idname, cons
return (found) ? id : NULL;
}
+/* simple reader for copy/paste buffers */
+void BLO_library_append_all(Main *mainl, BlendHandle *bh)
+{
+ FileData *fd = (FileData *)(bh);
+ BHead *bhead;
+ ID *id = NULL;
+
+ for (bhead = blo_firstbhead(fd); bhead; bhead = blo_nextbhead(fd, bhead)) {
+ if (bhead->code == ENDB)
+ break;
+ if (bhead->code == ID_OB)
+ read_libblock(fd, mainl, bhead, LIB_TESTIND, &id);
+
+ if (id) {
+ /* sort by name in list */
+ ListBase *lb = which_libbase(mainl, GS(id->name));
+ id_sort_by_name(lb, id);
+ }
+ }
+}
+
+
static ID *append_named_part_ex(const bContext *C, Main *mainl, FileData *fd, const char *idname, const int idcode, const int flag)
{
ID *id= append_named_part(mainl, fd, idname, idcode);
@@ -9805,8 +10886,11 @@ static void library_append_end(const bContext *C, Main *mainl, FileData **fd, in
Main *mainvar;
Library *curlib;
+ /* expander now is callback function */
+ BLO_main_expander(expand_doit_library);
+
/* make main consistent */
- expand_main(*fd, mainl);
+ BLO_expand_main(*fd, mainl);
/* do this when expand found other libs */
read_libraries(*fd, (*fd)->mainlist);
@@ -9841,7 +10925,7 @@ static void library_append_end(const bContext *C, Main *mainl, FileData **fd, in
/* don't instance anything when linking in scenes, assume the scene its self instances the data */
}
else {
- give_base_to_objects(mainvar, scene, curlib, idcode, is_link);
+ give_base_to_objects(mainvar, scene, curlib, idcode, is_link, flag & FILE_ACTIVELAY);
if (flag & FILE_GROUP_INSTANCE) {
give_base_to_groups(mainvar, scene);
@@ -9901,6 +10985,9 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
ListBase *lbarray[MAX_LIBARRAY];
int a, do_it = TRUE;
+ /* expander now is callback function */
+ BLO_main_expander(expand_doit_library);
+
while (do_it) {
do_it = FALSE;
@@ -9914,12 +11001,26 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
FileData *fd = mainptr->curlib->filedata;
if (fd == NULL) {
+
/* printf and reports for now... its important users know this */
- BKE_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read library: '%s', '%s'"),
- mainptr->curlib->filepath, mainptr->curlib->name);
- fd = blo_openblenderfile(mainptr->curlib->filepath, basefd->reports);
-
+ /* if packed file... */
+ if (mainptr->curlib->packedfile) {
+ PackedFile *pf = mainptr->curlib->packedfile;
+
+ BKE_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read packed library: '%s'"),
+ mainptr->curlib->name);
+ fd = blo_openblendermemory(pf->data, pf->size, basefd->reports);
+
+
+ /* needed for library_append and read_libraries */
+ BLI_strncpy(fd->relabase, mainptr->curlib->filepath, sizeof(fd->relabase));
+ }
+ else {
+ BKE_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read library: '%s', '%s'"),
+ mainptr->curlib->filepath, mainptr->curlib->name);
+ fd = blo_openblenderfile(mainptr->curlib->filepath, basefd->reports);
+ }
/* allow typing in a new lib path */
if (G.debug_value == -666) {
while (fd == NULL) {
@@ -9933,7 +11034,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
if (scanf("%s", newlib_path) > 0) {
BLI_strncpy(mainptr->curlib->name, newlib_path, sizeof(mainptr->curlib->name));
BLI_strncpy(mainptr->curlib->filepath, newlib_path, sizeof(mainptr->curlib->filepath));
- cleanup_path(G.main->name, mainptr->curlib->filepath);
+ BLI_cleanup_path(G.main->name, mainptr->curlib->filepath);
fd = blo_openblenderfile(mainptr->curlib->filepath, basefd->reports);
@@ -9965,7 +11066,9 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
/* subversion */
read_file_version(fd, mainptr);
}
- else mainptr->curlib->filedata = NULL;
+ else {
+ mainptr->curlib->filedata = NULL;
+ }
if (fd == NULL) {
BKE_reportf_wrap(basefd->reports, RPT_WARNING, TIP_("Cannot find lib '%s'"),
@@ -9989,7 +11092,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
BKE_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);
+ id->name + 2, mainptr->curlib->filepath);
}
change_idid_adr(mainlist, basefd, id, realid);
@@ -10000,7 +11103,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
}
}
- expand_main(fd, mainptr);
+ BLO_expand_main(fd, mainptr);
}
}
diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h
index a979a16220d..6d5fc056d89 100644
--- a/source/blender/blenloader/intern/readfile.h
+++ b/source/blender/blenloader/intern/readfile.h
@@ -54,7 +54,7 @@ typedef struct FileData {
int (*read)(struct FileData *filedata, void *buffer, unsigned int size);
// variables needed for reading from memory / stream
- char *buffer;
+ const char *buffer;
// variables needed for reading from memfile (undo)
struct MemFile *memfile;
@@ -69,6 +69,9 @@ typedef struct FileData {
char headerdone;
int inbuffer;
+ // gzip stream for memory decompression
+ z_stream strm;
+
// general reading variables
struct SDNA *filesdna;
struct SDNA *memsdna;
@@ -83,6 +86,7 @@ typedef struct FileData {
struct OldNewMap *libmap;
struct OldNewMap *imamap;
struct OldNewMap *movieclipmap;
+ struct OldNewMap *packedmap;
struct BHeadSort *bheadmap;
int tot_bheadmap;
@@ -119,7 +123,7 @@ void blo_split_main(ListBase *mainlist, struct Main *main);
BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath);
FileData *blo_openblenderfile(const char *filepath, struct ReportList *reports);
-FileData *blo_openblendermemory(void *buffer, int buffersize, struct ReportList *reports);
+FileData *blo_openblendermemory(const void *buffer, int buffersize, struct ReportList *reports);
FileData *blo_openblendermemfile(struct MemFile *memfile, struct ReportList *reports);
void blo_clear_proxy_pointers_from_lib(Main *oldmain);
@@ -127,6 +131,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_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);
void blo_freefiledata(FileData *fd);
@@ -146,7 +152,6 @@ void *blo_do_versions_newlibadr_us(struct FileData *fd, void *lib, void *adr);
struct PartEff *blo_do_version_give_parteff_245(struct Object *ob);
void blo_do_version_old_trackto_to_constraints(struct Object *ob);
void blo_do_versions_view3d_split_250(struct View3D *v3d, struct ListBase *regions);
-void blo_do_versions_nodetree_default_value(struct bNodeTree *ntree);
void blo_do_versions_pre250(struct FileData *fd, struct Library *lib, struct Main *main);
void blo_do_versions_250(struct FileData *fd, struct Library *lib, struct Main *main);
diff --git a/source/blender/blenloader/intern/runtime.c b/source/blender/blenloader/intern/runtime.c
index 5d8a865eea8..cbbaf713e84 100644
--- a/source/blender/blenloader/intern/runtime.c
+++ b/source/blender/blenloader/intern/runtime.c
@@ -48,11 +48,12 @@
#include "BLO_readfile.h"
#include "BLO_runtime.h"
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+
#include "BKE_blender.h"
#include "BKE_report.h"
-#include "BLI_blenlib.h"
-
/* Runtime reading */
static int handle_read_msb_int(int handle)
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 1521739258e..3827a31ae95 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -292,7 +292,7 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
memcpy(&ar->v2d, &soops->v2d, sizeof(View2D));
ar->v2d.scroll &= ~V2D_SCROLL_LEFT;
- ar->v2d.scroll |= (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM_O);
+ ar->v2d.scroll |= (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM);
ar->v2d.align = (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_POS_Y);
ar->v2d.keepzoom |= (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_KEEPASPECT);
ar->v2d.keeptot = V2D_KEEPTOT_STRICT;
@@ -415,7 +415,7 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
ar->v2d.tot.ymax = ar->winy;
ar->v2d.cur = ar->v2d.tot;
ar->regiontype = RGN_TYPE_WINDOW;
- ar->v2d.scroll = (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM_O);
+ ar->v2d.scroll = (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM);
ar->v2d.align = (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_POS_Y);
ar->v2d.keepzoom = (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_LIMITZOOM|V2D_KEEPASPECT);
break;
@@ -480,7 +480,7 @@ static void versions_gpencil_add_main(ListBase *lb, ID *id, const char *name)
*( (short *)id->name )= ID_GD;
new_id(lb, id, name);
- /* alphabetic insterion: is in new_id */
+ /* alphabetic insertion: is in new_id */
if (G.debug & G_DEBUG)
printf("Converted GPencil to ID: %s\n", id->name + 2);
@@ -672,13 +672,90 @@ static void do_version_bone_roll_256(Bone *bone)
do_version_bone_roll_256(child);
}
-static void do_versions_nodetree_dynamic_sockets(bNodeTree *ntree)
+/* deprecated, only keep this for readfile.c */
+/* XXX Deprecated function to add a socket in ntree->inputs/ntree->outputs list
+ * (previously called node_group_add_socket). This function has been superseded
+ * by the implementation of proxy nodes. It is still necessary though
+ * for do_versions of pre-2.56.2 code (r35033), so later proxy nodes
+ * can be generated consistently from ntree socket lists.
+ */
+static bNodeSocket *do_versions_node_group_add_socket_2_56_2(bNodeTree *ngroup, const char *name, int type, int in_out)
+{
+// bNodeSocketType *stype = ntreeGetSocketType(type);
+ bNodeSocket *gsock = MEM_callocN(sizeof(bNodeSocket), "bNodeSocket");
+
+ BLI_strncpy(gsock->name, name, sizeof(gsock->name));
+ gsock->type = type;
+
+ gsock->next = gsock->prev = NULL;
+ gsock->new_sock = NULL;
+ gsock->link = NULL;
+ /* assign new unique index */
+ gsock->own_index = ngroup->cur_index++;
+ gsock->limit = (in_out==SOCK_IN ? 0xFFF : 1);
+
+// if (stype->value_structsize > 0)
+// gsock->default_value = MEM_callocN(stype->value_structsize, "default socket value");
+
+ BLI_addtail(in_out==SOCK_IN ? &ngroup->inputs : &ngroup->outputs, gsock);
+
+ ngroup->update |= (in_out==SOCK_IN ? NTREE_UPDATE_GROUP_IN : NTREE_UPDATE_GROUP_OUT);
+
+ return gsock;
+}
+
+/* Create default_value structs for node sockets from the internal bNodeStack value.
+ * These structs were used from 2.59.2 on, but are replaced in the subsequent do_versions for custom nodes
+ * by generic ID property values. This conversion happened _after_ do_versions originally due to messy type initialization
+ * for node sockets. Now created here intermediately for convenience and to keep do_versions consistent.
+ *
+ * Node compatibility code is gross ...
+ */
+static void do_versions_socket_default_value_259(bNodeSocket *sock)
{
+ bNodeSocketValueFloat *valfloat;
+ bNodeSocketValueVector *valvector;
+ bNodeSocketValueRGBA *valrgba;
+
+ if (sock->default_value)
+ return;
+
+ switch (sock->type) {
+ case SOCK_FLOAT:
+ valfloat = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueFloat), "default socket value");
+ valfloat->value = sock->ns.vec[0];
+ valfloat->min = sock->ns.min;
+ valfloat->max = sock->ns.max;
+ valfloat->subtype = PROP_NONE;
+ break;
+ case SOCK_VECTOR:
+ valvector = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueVector), "default socket value");
+ copy_v3_v3(valvector->value, sock->ns.vec);
+ valvector->min = sock->ns.min;
+ valvector->max = sock->ns.max;
+ valvector->subtype = PROP_NONE;
+ break;
+ case SOCK_RGBA:
+ valrgba = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueRGBA), "default socket value");
+ copy_v4_v4(valrgba->value, sock->ns.vec);
+ break;
+ }
+}
+
+static void do_versions_nodetree_default_value_259(bNodeTree *ntree)
+{
+ bNode *node;
bNodeSocket *sock;
+ for (node=ntree->nodes.first; node; node=node->next) {
+ for (sock = node->inputs.first; sock; sock = sock->next)
+ do_versions_socket_default_value_259(sock);
+ for (sock = node->outputs.first; sock; sock = sock->next)
+ do_versions_socket_default_value_259(sock);
+ }
for (sock = ntree->inputs.first; sock; sock = sock->next)
- sock->flag |= SOCK_DYNAMIC;
+ do_versions_socket_default_value_259(sock);
for (sock = ntree->outputs.first; sock; sock = sock->next)
- sock->flag |= SOCK_DYNAMIC;
+ do_versions_socket_default_value_259(sock);
}
void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
@@ -2289,16 +2366,79 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 2)) {
bNodeTree *ntree;
-
+ bNode *node;
+ bNodeSocket *sock, *gsock;
+ bNodeLink *link;
+
/* node sockets are not exposed automatically any more,
* this mimics the old behavior by adding all unlinked sockets to groups.
*/
- for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
- /* XXX Only setting a flag here. Actual adding of group sockets
- * is done in lib_verify_nodetree, because at this point the internal
- * nodes may not be up-to-date! (missing lib-link)
+ for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) {
+ /* this adds copies and links from all unlinked internal sockets to group inputs/outputs. */
+
+ /* first make sure the own_index for new sockets is valid */
+ for (node=ntree->nodes.first; node; node=node->next) {
+ for (sock = node->inputs.first; sock; sock = sock->next)
+ if (sock->own_index >= ntree->cur_index)
+ ntree->cur_index = sock->own_index+1;
+ for (sock = node->outputs.first; sock; sock = sock->next)
+ if (sock->own_index >= ntree->cur_index)
+ ntree->cur_index = sock->own_index+1;
+ }
+
+ /* add ntree->inputs/ntree->outputs sockets for all unlinked sockets in the group tree. */
+ for (node=ntree->nodes.first; node; node=node->next) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (!sock->link && !nodeSocketIsHidden(sock)) {
+
+ gsock = do_versions_node_group_add_socket_2_56_2(ntree, sock->name, sock->type, SOCK_IN);
+
+ /* initialize the default socket value */
+ copy_v4_v4(gsock->ns.vec, sock->ns.vec);
+
+ /* XXX nodeAddLink does not work with incomplete (node==NULL) links any longer,
+ * have to create these directly here. These links are updated again in subsequent do_version!
+ */
+ link = MEM_callocN(sizeof(bNodeLink), "link");
+ BLI_addtail(&ntree->links, link);
+ link->fromnode = NULL;
+ link->fromsock = gsock;
+ link->tonode = node;
+ link->tosock = sock;
+ ntree->update |= NTREE_UPDATE_LINKS;
+
+ sock->link = link;
+ }
+ }
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ if (nodeCountSocketLinks(ntree, sock)==0 && !nodeSocketIsHidden(sock)) {
+ gsock = do_versions_node_group_add_socket_2_56_2(ntree, sock->name, sock->type, SOCK_OUT);
+
+ /* initialize the default socket value */
+ copy_v4_v4(gsock->ns.vec, sock->ns.vec);
+
+ /* XXX nodeAddLink does not work with incomplete (node==NULL) links any longer,
+ * have to create these directly here. These links are updated again in subsequent do_version!
+ */
+ link = MEM_callocN(sizeof(bNodeLink), "link");
+ BLI_addtail(&ntree->links, link);
+ link->fromnode = node;
+ link->fromsock = sock;
+ link->tonode = NULL;
+ link->tosock = gsock;
+ ntree->update |= NTREE_UPDATE_LINKS;
+
+ gsock->link = link;
+ }
+ }
+ }
+
+ /* XXX The external group node sockets needs to adjust their own_index to point at
+ * associated ntree inputs/outputs internal sockets. However, this can only happen
+ * after lib-linking (needs access to internal node group tree)!
+ * Setting a temporary flag here, actual do_versions happens in lib_verify_nodetree.
*/
- ntree->flag |= NTREE_DO_VERSIONS_GROUP_EXPOSE;
+ ntree->flag |= NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2;
}
}
@@ -2601,39 +2741,29 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
bNodeTree *ntree;
for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
- blo_do_versions_nodetree_default_value(ntree);
+ do_versions_nodetree_default_value_259(ntree);
ntree->update |= NTREE_UPDATE;
}
for (sce = main->scene.first; sce; sce = sce->id.next)
if (sce->nodetree) {
- blo_do_versions_nodetree_default_value(sce->nodetree);
+ do_versions_nodetree_default_value_259(sce->nodetree);
sce->nodetree->update |= NTREE_UPDATE;
}
for (mat = main->mat.first; mat; mat = mat->id.next)
if (mat->nodetree) {
- blo_do_versions_nodetree_default_value(mat->nodetree);
+ do_versions_nodetree_default_value_259(mat->nodetree);
mat->nodetree->update |= NTREE_UPDATE;
}
for (tex = main->tex.first; tex; tex = tex->id.next)
if (tex->nodetree) {
- blo_do_versions_nodetree_default_value(tex->nodetree);
+ do_versions_nodetree_default_value_259(tex->nodetree);
tex->nodetree->update |= NTREE_UPDATE;
}
}
- /* add SOCK_DYNAMIC flag to existing group sockets */
- {
- bNodeTree *ntree;
- /* only need to do this for trees in main, local trees are not used as groups */
- for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
- do_versions_nodetree_dynamic_sockets(ntree);
- ntree->update |= NTREE_UPDATE;
- }
- }
-
{
/* Initialize group tree nodetypes.
* These are used to distinguish tree types and
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 8a56e3c2ab8..c6856d8b71d 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -289,11 +289,10 @@ static void ntree_version_245(FileData *fd, Library *lib, bNodeTree *ntree)
iuser = node->storage;
if (iuser->flag & IMA_OLD_PREMUL) {
iuser->flag &= ~IMA_OLD_PREMUL;
- iuser->flag |= IMA_DO_PREMUL;
}
if (iuser->flag & IMA_DO_PREMUL) {
image->flag &= ~IMA_OLD_PREMUL;
- image->flag |= IMA_DO_PREMUL;
+ image->alpha_mode = IMA_ALPHA_STRAIGHT;
}
}
}
@@ -454,7 +453,7 @@ static void customdata_version_242(Mesh *me)
}
}
- mesh_update_customdata_pointers(me, TRUE);
+ BKE_mesh_update_customdata_pointers(me, true);
}
/*only copy render texface layer from active*/
@@ -545,7 +544,7 @@ void blo_do_version_old_trackto_to_constraints(Object *ob)
{
/* create new trackto constraint from the relationship */
if (ob->track) {
- bConstraint *con = add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_TRACKTO);
+ bConstraint *con = BKE_add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_TRACKTO);
bTrackToConstraint *data = con->data;
/* copy tracking settings from the object */
@@ -1548,7 +1547,9 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
else if (sbuts->mainb == BUTS_EDIT) {
sbuts->mainb = CONTEXT_EDITING;
}
- else sbuts->mainb = CONTEXT_SCENE;
+ else {
+ sbuts->mainb = CONTEXT_SCENE;
+ }
}
}
}
@@ -1840,7 +1841,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
SEQ_BEGIN (sce->ed, seq)
{
if (seq->type == SEQ_TYPE_IMAGE || seq->type == SEQ_TYPE_MOVIE)
- seq->flag |= SEQ_MAKE_PREMUL;
+ seq->alpha_mode = SEQ_ALPHA_STRAIGHT;
}
SEQ_END
}
@@ -2305,7 +2306,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
Image *ima;
for (ima = main->image.first; ima; ima = ima->id.next)
if (strcmp(ima->name, "Compositor") == 0) {
- strcpy(ima->id.name+2, "Viewer Node");
+ strcpy(ima->id.name + 2, "Viewer Node");
strcpy(ima->name, "Viewer Node");
}
}
@@ -2494,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 (0 == strncmp(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 (0 == strncmp(ima->id.name + 2, "Render Result", sizeof(ima->id.name) - 2)) {
ima->source = IMA_SRC_VIEWER;
ima->type = IMA_TYPE_R_RESULT;
}
@@ -2551,7 +2552,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
if (main->subversionfile < 4) {
for (sce = main->scene.first; sce; sce = sce->id.next) {
sce->r.bake_mode = 1; /* prevent to include render stuff here */
- sce->r.bake_filter = 2;
+ sce->r.bake_filter = 16;
sce->r.bake_osa = 5;
sce->r.bake_flag = R_BAKE_CLEAR;
}
@@ -2901,20 +2902,19 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
for (ima = main->image.first; ima; ima = ima->id.next) {
if (ima->flag & IMA_OLD_PREMUL) {
ima->flag &= ~IMA_OLD_PREMUL;
- ima->flag |= IMA_DO_PREMUL;
+ ima->alpha_mode = IMA_ALPHA_STRAIGHT;
}
}
for (tex = main->tex.first; tex; tex = tex->id.next) {
if (tex->iuser.flag & IMA_OLD_PREMUL) {
tex->iuser.flag &= ~IMA_OLD_PREMUL;
- tex->iuser.flag |= IMA_DO_PREMUL;
}
ima = blo_do_versions_newlibadr(fd, lib, tex->ima);
if (ima && (tex->iuser.flag & IMA_DO_PREMUL)) {
ima->flag &= ~IMA_OLD_PREMUL;
- ima->flag |= IMA_DO_PREMUL;
+ ima->alpha_mode = IMA_ALPHA_STRAIGHT;
}
}
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index b010cae6893..3c6e646fe9c 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -74,6 +74,7 @@
#include <math.h>
#include <fcntl.h>
+#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -89,6 +90,8 @@
# include "BLI_winstuff.h"
#endif
+#include "BLI_utildefines.h"
+
/* allow writefile to use deprecated functionality (for forward compatibility code) */
#define DNA_DEPRECATED_ALLOW
@@ -108,6 +111,7 @@
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
#include "DNA_lamp_types.h"
+#include "DNA_linestyle_types.h"
#include "DNA_meta_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -118,6 +122,7 @@
#include "DNA_packedFile_types.h"
#include "DNA_particle_types.h"
#include "DNA_property_types.h"
+#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_sdna_types.h"
#include "DNA_sequence_types.h"
@@ -139,7 +144,7 @@
#include "BLI_bitmap.h"
#include "BLI_blenlib.h"
#include "BLI_linklist.h"
-#include "BLI_bpath.h"
+#include "BKE_bpath.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -148,6 +153,7 @@
#include "BKE_curve.h"
#include "BKE_constraint.h"
#include "BKE_global.h" // for G
+#include "BKE_idprop.h"
#include "BKE_library.h" // for set_listbasepointers
#include "BKE_main.h"
#include "BKE_node.h"
@@ -159,6 +165,13 @@
#include "BKE_pointcache.h"
#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"
#include "BLO_undofile.h"
@@ -197,7 +210,7 @@ static WriteData *writedata_new(int file)
if (wd == NULL) return NULL;
- wd->sdna = DNA_sdna_from_data(DNAstr, DNAlen, 0);
+ wd->sdna = DNA_sdna_from_data(DNAstr, DNAlen, false);
wd->file= file;
@@ -377,6 +390,17 @@ static void writedata(WriteData *wd, int filecode, int len, const void *adr) /*
if (len) mywrite(wd, adr, len);
}
+/* use this to force writing of lists in same order as reading (using link_list) */
+static void writelist(WriteData *wd, int filecode, const char *structname, ListBase *lb)
+{
+ Link *link = lb->first;
+
+ while (link) {
+ writestruct(wd, filecode, structname, 1, link);
+ link = link->next;
+ }
+}
+
/* *************** writing some direct data structs used in more code parts **************** */
/*These functions are used by blender's .blend system for file saving/loading.*/
void IDP_WriteProperty_OnlyData(IDProperty *prop, void *wd);
@@ -456,6 +480,9 @@ static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers)
{
FModifier *fcm;
+ /* Write all modifiers first (for faster reloading) */
+ writelist(wd, DATA, "FModifier", fmodifiers);
+
/* Modifiers */
for (fcm= fmodifiers->first; fcm; fcm= fcm->next) {
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
@@ -496,9 +523,6 @@ static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers)
break;
}
}
-
- /* Write the modifier */
- writestruct(wd, DATA, "FModifier", 1, fcm);
}
}
@@ -506,10 +530,8 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves)
{
FCurve *fcu;
+ writelist(wd, DATA, "FCurve", fcurves);
for (fcu=fcurves->first; fcu; fcu=fcu->next) {
- /* F-Curve */
- writestruct(wd, DATA, "FCurve", 1, fcu);
-
/* curve data */
if (fcu->bezt)
writestruct(wd, DATA, "BezTriple", fcu->totvert, fcu->bezt);
@@ -527,9 +549,8 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves)
writestruct(wd, DATA, "ChannelDriver", 1, driver);
/* variables */
- for (dvar= driver->variables.first; dvar; dvar= dvar->next) {
- writestruct(wd, DATA, "DriverVar", 1, dvar);
-
+ writelist(wd, DATA, "DriverVar", &driver->variables);
+ for (dvar= driver->variables.first; dvar; dvar= dvar->next) {
DRIVER_TARGETS_USED_LOOPER(dvar)
{
if (dtar->rna_path)
@@ -595,10 +616,8 @@ static void write_nlastrips(WriteData *wd, ListBase *strips)
{
NlaStrip *strip;
+ writelist(wd, DATA, "NlaStrip", strips);
for (strip= strips->first; strip; strip= strip->next) {
- /* write the strip first */
- writestruct(wd, DATA, "NlaStrip", 1, strip);
-
/* write the strip's F-Curves and modifiers */
write_fcurves(wd, &strip->fcurves);
write_fmodifiers(wd, &strip->modifiers);
@@ -661,46 +680,54 @@ static void write_curvemapping(WriteData *wd, CurveMapping *cumap)
write_curvemapping_curves(wd, cumap);
}
-static void write_node_socket(WriteData *wd, bNodeSocket *sock)
+static void write_node_socket(WriteData *wd, bNodeTree *UNUSED(ntree), bNode *node, bNodeSocket *sock)
{
- bNodeSocketType *stype= ntreeGetSocketType(sock->type);
-
+#ifdef USE_NODE_COMPAT_CUSTOMNODES
/* forward compatibility code, so older blenders still open */
sock->stack_type = 1;
- if (sock->default_value) {
- bNodeSocketValueFloat *valfloat;
- bNodeSocketValueVector *valvector;
- bNodeSocketValueRGBA *valrgba;
-
- switch (sock->type) {
- case SOCK_FLOAT:
- valfloat = sock->default_value;
- sock->ns.vec[0] = valfloat->value;
- sock->ns.min = valfloat->min;
- sock->ns.max = valfloat->max;
- break;
- case SOCK_VECTOR:
- valvector = sock->default_value;
- copy_v3_v3(sock->ns.vec, valvector->value);
- sock->ns.min = valvector->min;
- sock->ns.max = valvector->max;
- break;
- case SOCK_RGBA:
- valrgba = sock->default_value;
- copy_v4_v4(sock->ns.vec, valrgba->value);
- sock->ns.min = 0.0f;
- sock->ns.max = 1.0f;
- break;
+ if (node->type == NODE_GROUP) {
+ bNodeTree *ngroup = (bNodeTree *)node->id;
+ if (ngroup) {
+ /* for node groups: look up the deprecated groupsock pointer */
+ sock->groupsock = ntreeFindSocketInterface(ngroup, sock->in_out, sock->identifier);
+ BLI_assert(sock->groupsock != NULL);
+
+ /* node group sockets now use the generic identifier string to verify group nodes,
+ * old blender uses the own_index.
+ */
+ sock->own_index = sock->groupsock->own_index;
}
}
+#endif
/* actual socket writing */
writestruct(wd, DATA, "bNodeSocket", 1, sock);
+
+ if (sock->prop)
+ IDP_WriteProperty(sock->prop, wd);
+
if (sock->default_value)
- writestruct(wd, DATA, stype->value_structname, 1, sock->default_value);
+ writedata(wd, DATA, MEM_allocN_len(sock->default_value), sock->default_value);
}
+static void write_node_socket_interface(WriteData *wd, bNodeTree *UNUSED(ntree), bNodeSocket *sock)
+{
+#ifdef USE_NODE_COMPAT_CUSTOMNODES
+ /* forward compatibility code, so older blenders still open */
+ sock->stack_type = 1;
+
+ /* Reconstruct the deprecated default_value structs in socket interface DNA. */
+ if (sock->default_value == NULL && sock->typeinfo) {
+ node_socket_init_default_value(sock);
+ }
+#endif
+
+ /* actual socket writing */
+ writestruct(wd, DATA, "bNodeSocket", 1, sock);
+ if (sock->prop)
+ IDP_WriteProperty(sock->prop, wd);
+}
/* this is only direct data, tree itself should have been written */
static void write_nodetree(WriteData *wd, bNodeTree *ntree)
{
@@ -712,18 +739,19 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
if (ntree->adt) write_animdata(wd, ntree->adt);
- for (node= ntree->nodes.first; node; node= node->next)
+ for (node = ntree->nodes.first; node; node = node->next) {
writestruct(wd, DATA, "bNode", 1, node);
- for (node= ntree->nodes.first; node; node= node->next) {
+ if (node->prop)
+ IDP_WriteProperty(node->prop, wd);
+
for (sock= node->inputs.first; sock; sock= sock->next)
- write_node_socket(wd, sock);
+ write_node_socket(wd, ntree, node, sock);
for (sock= node->outputs.first; sock; sock= sock->next)
- write_node_socket(wd, sock);
+ write_node_socket(wd, ntree, node, sock);
for (link = node->internal_links.first; link; link = link->next)
writestruct(wd, DATA, "bNodeLink", 1, link);
-
if (node->storage) {
/* could be handlerized at some point, now only 1 exception still */
if (ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB))
@@ -732,10 +760,6 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
NodeShaderScript *nss = (NodeShaderScript *)node->storage;
if (nss->bytecode)
writedata(wd, DATA, strlen(nss->bytecode)+1, nss->bytecode);
- /* Write ID Properties -- and copy this comment EXACTLY for easy finding
- * of library blocks that implement this.*/
- if (nss->prop)
- IDP_WriteProperty(nss->prop, wd);
writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
}
else if (ntree->type==NTREE_COMPOSIT && ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
@@ -751,12 +775,12 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
if (node->type==CMP_NODE_OUTPUT_FILE) {
/* inputs have own storage data */
- for (sock=node->inputs.first; sock; sock=sock->next)
+ for (sock = node->inputs.first; sock; sock = sock->next)
writestruct(wd, DATA, "NodeImageMultiFileSocket", 1, sock->storage);
}
if (node->type==CMP_NODE_IMAGE) {
/* write extra socket info */
- for (sock=node->outputs.first; sock; sock=sock->next)
+ for (sock = node->outputs.first; sock; sock = sock->next)
writestruct(wd, DATA, "NodeImageLayer", 1, sock->storage);
}
}
@@ -764,11 +788,10 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
for (link= ntree->links.first; link; link= link->next)
writestruct(wd, DATA, "bNodeLink", 1, link);
- /* external sockets */
- for (sock= ntree->inputs.first; sock; sock= sock->next)
- write_node_socket(wd, sock);
- for (sock= ntree->outputs.first; sock; sock= sock->next)
- write_node_socket(wd, sock);
+ for (sock = ntree->inputs.first; sock; sock = sock->next)
+ write_node_socket_interface(wd, ntree, sock);
+ for (sock = ntree->outputs.first; sock; sock = sock->next)
+ write_node_socket_interface(wd, ntree, sock);
}
static void current_screen_compat(Main *mainvar, bScreen **screen)
@@ -795,14 +818,15 @@ typedef struct RenderInfo {
static void write_renderinfo(WriteData *wd, Main *mainvar)
{
bScreen *curscreen;
- Scene *sce;
+ Scene *sce, *curscene = NULL;
RenderInfo data;
/* XXX in future, handle multiple windows with multiple screens? */
current_screen_compat(mainvar, &curscreen);
-
+ if (curscreen) curscene = curscreen->scene;
+
for (sce= mainvar->scene.first; sce; sce= sce->id.next) {
- if (sce->id.lib == NULL && (sce == curscreen->scene || (sce->r.scemode & R_BG_RENDER))) {
+ if (sce->id.lib == NULL && (sce == curscene || (sce->r.scemode & R_BG_RENDER))) {
data.sfra = sce->r.sfra;
data.efra = sce->r.efra;
memset(data.scene_name, 0, sizeof(data.scene_name));
@@ -850,8 +874,12 @@ static void write_userdef(WriteData *wd)
write_keymapitem(wd, kmi);
}
- for (bext= U.addons.first; bext; bext=bext->next)
+ for (bext= U.addons.first; bext; bext=bext->next) {
writestruct(wd, DATA, "bAddon", 1, bext);
+ if (bext->prop) {
+ IDP_WriteProperty(bext->prop, wd);
+ }
+ }
for (style= U.uistyles.first; style; style= style->next) {
writestruct(wd, DATA, "uiStyle", 1, style);
@@ -1228,7 +1256,7 @@ static void write_constraints(WriteData *wd, ListBase *conlist)
bConstraint *con;
for (con=conlist->first; con; con=con->next) {
- bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti= BKE_constraint_get_typeinfo(con);
/* Write the specific data */
if (cti && con->data) {
@@ -1416,8 +1444,8 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
int size = mmd->dyngridsize;
writestruct(wd, DATA, "MDefInfluence", mmd->totinfluence, mmd->bindinfluences);
- writedata(wd, DATA, sizeof(int)*(mmd->totvert+1), mmd->bindoffsets);
- writedata(wd, DATA, sizeof(float)*3*mmd->totcagevert,
+ writedata(wd, DATA, sizeof(int) * (mmd->totvert + 1), mmd->bindoffsets);
+ writedata(wd, DATA, sizeof(float) * 3 * mmd->totcagevert,
mmd->bindcagecos);
writestruct(wd, DATA, "MDefCell", size*size*size, mmd->dyngrid);
writestruct(wd, DATA, "MDefInfluence", mmd->totinfluence, mmd->dyninfluences);
@@ -1483,6 +1511,14 @@ static void write_objects(WriteData *wd, ListBase *idbase)
}
writestruct(wd, DATA, "BulletSoftBody", 1, ob->bsoft);
+ if (ob->rigidbody_object) {
+ // TODO: if any extra data is added to handle duplis, will need separate function then
+ writestruct(wd, DATA, "RigidBodyOb", 1, ob->rigidbody_object);
+ }
+ if (ob->rigidbody_constraint) {
+ writestruct(wd, DATA, "RigidBodyCon", 1, ob->rigidbody_constraint);
+ }
+
write_particlesystems(wd, &ob->particlesystem);
write_modifiers(wd, &ob->modifiers);
}
@@ -1674,7 +1710,7 @@ static void write_mdisps(WriteData *wd, int count, MDisps *mdlist, int external)
MDisps *md = &mdlist[i];
if (md->disps) {
if (!external)
- writedata(wd, DATA, sizeof(float)*3*md->totdisp, md->disps);
+ writedata(wd, DATA, sizeof(float) * 3 * md->totdisp, md->disps);
}
if (md->hidden)
@@ -1768,7 +1804,7 @@ static void write_meshs(WriteData *wd, ListBase *idbase)
if (!save_for_old_blender) {
#ifdef USE_BMESH_SAVE_WITHOUT_MFACE
- Mesh backup_mesh = {{0}};
+ Mesh backup_mesh = {{NULL}};
/* cache only - don't write */
backup_mesh.mface = mesh->mface;
mesh->mface = NULL;
@@ -1811,7 +1847,7 @@ static void write_meshs(WriteData *wd, ListBase *idbase)
#ifdef USE_BMESH_SAVE_AS_COMPAT
- Mesh backup_mesh = {{0}};
+ Mesh backup_mesh = {{NULL}};
/* backup */
backup_mesh.mpoly = mesh->mpoly;
@@ -1847,7 +1883,7 @@ static void write_meshs(WriteData *wd, ListBase *idbase)
mesh->totface = BKE_mesh_mpoly_to_mface(&mesh->fdata, &backup_mesh.ldata, &backup_mesh.pdata,
mesh->totface, backup_mesh.totloop, backup_mesh.totpoly);
- mesh_update_customdata_pointers(mesh, FALSE);
+ BKE_mesh_update_customdata_pointers(mesh, false);
writestruct(wd, ID_ME, "Mesh", 1, mesh);
@@ -1884,7 +1920,7 @@ static void write_meshs(WriteData *wd, ListBase *idbase)
mesh->totpoly = backup_mesh.totpoly;
mesh->totloop = backup_mesh.totloop;
/* -- */
- mesh_update_customdata_pointers(mesh, FALSE);
+ BKE_mesh_update_customdata_pointers(mesh, false);
/* --*/
mesh->edit_btmesh = backup_mesh.edit_btmesh; /* keep this after updating custom pointers */
/* restore */
@@ -2160,6 +2196,8 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
TransformOrientation *ts;
SceneRenderLayer *srl;
ToolSettings *tos;
+ FreestyleModuleConfig *fmc;
+ FreestyleLineSet *fls;
sce= scebase->first;
while (sce) {
@@ -2283,8 +2321,15 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
for (ts = sce->transform_spaces.first; ts; ts = ts->next)
writestruct(wd, DATA, "TransformOrientation", 1, ts);
- for (srl= sce->r.layers.first; srl; srl= srl->next)
+ for (srl = sce->r.layers.first; srl; srl = srl->next) {
writestruct(wd, DATA, "SceneRenderLayer", 1, srl);
+ for(fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
+ writestruct(wd, DATA, "FreestyleModuleConfig", 1, fmc);
+ }
+ for(fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
+ writestruct(wd, DATA, "FreestyleLineSet", 1, fls);
+ }
+ }
if (sce->nodetree) {
writestruct(wd, DATA, "bNodeTree", 1, sce->nodetree);
@@ -2292,7 +2337,14 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
}
write_view_settings(wd, &sce->view_settings);
-
+
+ /* writing RigidBodyWorld data to the blend file */
+ if (sce->rigidbody_world) {
+ writestruct(wd, DATA, "RigidBodyWorld", 1, sce->rigidbody_world);
+ writestruct(wd, DATA, "EffectorWeights", 1, sce->rigidbody_world->effector_weights);
+ write_pointcaches(wd, &(sce->rigidbody_world->ptcaches));
+ }
+
sce= sce->id.next;
}
/* flush helps the compression for undo-save */
@@ -2312,16 +2364,16 @@ static void write_gpencils(WriteData *wd, ListBase *lb)
writestruct(wd, ID_GD, "bGPdata", 1, gpd);
/* write grease-pencil layers to file */
+ writelist(wd, DATA, "bGPDlayer", &gpd->layers);
for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
- writestruct(wd, DATA, "bGPDlayer", 1, gpl);
/* write this layer's frames to file */
+ writelist(wd, DATA, "bGPDframe", &gpl->frames);
for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
- writestruct(wd, DATA, "bGPDframe", 1, gpf);
/* write strokes */
+ writelist(wd, DATA, "bGPDstroke", &gpf->strokes);
for (gps= gpf->strokes.first; gps; gps= gps->next) {
- writestruct(wd, DATA, "bGPDstroke", 1, gps);
writestruct(wd, DATA, "bGPDspoint", gps->totpoints, gps->points);
}
}
@@ -2395,6 +2447,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
for (sa= sc->areabase.first; sa; sa= sa->next) {
SpaceLink *sl;
Panel *pa;
+ uiList *ui_list;
ARegion *ar;
writestruct(wd, DATA, "ScrArea", 1, sa);
@@ -2404,6 +2457,9 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
for (pa= ar->panels.first; pa; pa= pa->next)
writestruct(wd, DATA, "Panel", 1, pa);
+
+ for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next)
+ writestruct(wd, DATA, "uiList", 1, ui_list);
}
sl= sa->spacedata.first;
@@ -2485,7 +2541,12 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
writestruct(wd, DATA, "SpaceTime", 1, sl);
}
else if (sl->spacetype==SPACE_NODE) {
- writestruct(wd, DATA, "SpaceNode", 1, sl);
+ SpaceNode *snode = (SpaceNode *)sl;
+ bNodeTreePath *path;
+ writestruct(wd, DATA, "SpaceNode", 1, snode);
+
+ for (path=snode->treepath.first; path; path=path->next)
+ writestruct(wd, DATA, "bNodeTreePath", 1, path);
}
else if (sl->spacetype==SPACE_LOGIC) {
writestruct(wd, DATA, "SpaceLogic", 1, sl);
@@ -2515,6 +2576,9 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
sc= sc->id.next;
}
+
+ /* flush helps the compression for undo-save */
+ mywrite(wd, MYWRITE_FLUSH, 0);
}
static void write_libraries(WriteData *wd, Main *main)
@@ -2528,20 +2592,35 @@ static void write_libraries(WriteData *wd, Main *main)
a=tot= set_listbasepointers(main, lbarray);
/* test: is lib being used */
- foundone = FALSE;
- while (tot--) {
- for (id= lbarray[tot]->first; id; id= id->next) {
- if (id->us>0 && (id->flag & LIB_EXTERN)) {
- foundone = TRUE;
- break;
+ if (main->curlib && main->curlib->packedfile)
+ foundone = TRUE;
+ else {
+ foundone = FALSE;
+ while (tot--) {
+ for (id= lbarray[tot]->first; id; id= id->next) {
+ if (id->us>0 && (id->flag & LIB_EXTERN)) {
+ foundone = TRUE;
+ break;
+ }
}
+ if (foundone) break;
}
- if (foundone) break;
}
-
+
+ /* to be able to restore quit.blend and temp saves, the packed blend has to be in undo buffers... */
+ /* XXX needs rethink, just like save UI in undo files now - would be nice to append things only for the]
+ * quit.blend and temp saves */
if (foundone) {
writestruct(wd, ID_LI, "Library", 1, main->curlib);
+ if (main->curlib->packedfile) {
+ PackedFile *pf = main->curlib->packedfile;
+ writestruct(wd, DATA, "PackedFile", 1, pf);
+ writedata(wd, DATA, pf->size, pf->data);
+ if (wd->current == NULL)
+ printf("write packed .blend: %s\n", main->curlib->name);
+ }
+
while (a--) {
for (id= lbarray[a]->first; id; id= id->next) {
if (id->us>0 && (id->flag & LIB_EXTERN)) {
@@ -2719,6 +2798,73 @@ static void write_nodetrees(WriteData *wd, ListBase *idbase)
}
}
+#ifdef USE_NODE_COMPAT_CUSTOMNODES
+static void customnodes_add_deprecated_data(Main *mainvar)
+{
+ FOREACH_NODETREE(mainvar, ntree, id) {
+ bNodeLink *link, *last_link = ntree->links.last;
+
+ /* only do this for node groups */
+ if (id != &ntree->id)
+ continue;
+
+ /* Forward compatibility for group nodes: add links to node tree interface sockets.
+ * These links are invalid by new rules (missing node pointer)!
+ * They will be removed again in customnodes_free_deprecated_data,
+ * cannot do this directly lest bNodeLink pointer mapping becomes ambiguous.
+ * When loading files with such links in a new Blender version
+ * they will be removed as well.
+ */
+ for (link = ntree->links.first; link; link = link->next) {
+ bNode *fromnode = link->fromnode, *tonode = link->tonode;
+ bNodeSocket *fromsock = link->fromsock, *tosock = link->tosock;
+
+ /* check both sides of the link, to handle direct input-to-output links */
+ if (fromnode->type == NODE_GROUP_INPUT) {
+ fromnode = NULL;
+ fromsock = ntreeFindSocketInterface(ntree, SOCK_IN, fromsock->identifier);
+ }
+ /* only the active output node defines links */
+ if (tonode->type == NODE_GROUP_OUTPUT && (tonode->flag & NODE_DO_OUTPUT)) {
+ tonode = NULL;
+ tosock = ntreeFindSocketInterface(ntree, SOCK_OUT, tosock->identifier);
+ }
+
+ if (!fromnode || !tonode) {
+ /* Note: not using nodeAddLink here, it asserts existing node pointers */
+ bNodeLink *tlink = MEM_callocN(sizeof(bNodeLink), "group node link");
+ tlink->fromnode = fromnode;
+ tlink->fromsock = fromsock;
+ tlink->tonode = tonode;
+ tlink->tosock= tosock;
+ tosock->link = tlink;
+ tlink->flag |= NODE_LINK_VALID;
+ BLI_addtail(&ntree->links, tlink);
+ }
+
+ /* don't check newly created compatibility links */
+ if (link == last_link)
+ break;
+ }
+ }
+ FOREACH_NODETREE_END
+}
+
+static void customnodes_free_deprecated_data(Main *mainvar)
+{
+ FOREACH_NODETREE(mainvar, ntree, id) {
+ bNodeLink *link, *next_link;
+
+ for (link = ntree->links.first; link; link = next_link) {
+ next_link = link->next;
+ if (link->fromnode == NULL || link->tonode == NULL)
+ nodeRemLink(ntree, link);
+ }
+ }
+ FOREACH_NODETREE_END
+}
+#endif
+
static void write_brushes(WriteData *wd, ListBase *idbase)
{
Brush *brush;
@@ -2860,6 +3006,207 @@ static void write_masks(WriteData *wd, ListBase *idbase)
mywrite(wd, MYWRITE_FLUSH, 0);
}
+static void write_linestyle_color_modifiers(WriteData *wd, ListBase *modifiers)
+{
+ LineStyleModifier *m;
+ const char *struct_name;
+
+ for (m = modifiers->first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ struct_name = "LineStyleColorModifier_AlongStroke";
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ struct_name = "LineStyleColorModifier_DistanceFromCamera";
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ struct_name = "LineStyleColorModifier_DistanceFromObject";
+ break;
+ case LS_MODIFIER_MATERIAL:
+ struct_name = "LineStyleColorModifier_Material";
+ break;
+ default:
+ struct_name = "LineStyleColorModifier"; /* this should not happen */
+ }
+ writestruct(wd, DATA, struct_name, 1, m);
+ }
+ for (m = modifiers->first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ writestruct(wd, DATA, "ColorBand", 1, ((LineStyleColorModifier_AlongStroke *)m)->color_ramp);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ writestruct(wd, DATA, "ColorBand", 1, ((LineStyleColorModifier_DistanceFromCamera *)m)->color_ramp);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ writestruct(wd, DATA, "ColorBand", 1, ((LineStyleColorModifier_DistanceFromObject *)m)->color_ramp);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ writestruct(wd, DATA, "ColorBand", 1, ((LineStyleColorModifier_Material *)m)->color_ramp);
+ break;
+ }
+ }
+}
+
+static void write_linestyle_alpha_modifiers(WriteData *wd, ListBase *modifiers)
+{
+ LineStyleModifier *m;
+ const char *struct_name;
+
+ for (m = modifiers->first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ struct_name = "LineStyleAlphaModifier_AlongStroke";
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ struct_name = "LineStyleAlphaModifier_DistanceFromCamera";
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ struct_name = "LineStyleAlphaModifier_DistanceFromObject";
+ break;
+ case LS_MODIFIER_MATERIAL:
+ struct_name = "LineStyleAlphaModifier_Material";
+ break;
+ default:
+ struct_name = "LineStyleAlphaModifier"; /* this should not happen */
+ }
+ writestruct(wd, DATA, struct_name, 1, m);
+ }
+ for (m = modifiers->first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ write_curvemapping(wd, ((LineStyleAlphaModifier_AlongStroke *)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ write_curvemapping(wd, ((LineStyleAlphaModifier_DistanceFromCamera *)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ write_curvemapping(wd, ((LineStyleAlphaModifier_DistanceFromObject *)m)->curve);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ write_curvemapping(wd, ((LineStyleAlphaModifier_Material *)m)->curve);
+ break;
+ }
+ }
+}
+
+static void write_linestyle_thickness_modifiers(WriteData *wd, ListBase *modifiers)
+{
+ LineStyleModifier *m;
+ const char *struct_name;
+
+ for (m = modifiers->first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ struct_name = "LineStyleThicknessModifier_AlongStroke";
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ struct_name = "LineStyleThicknessModifier_DistanceFromCamera";
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ struct_name = "LineStyleThicknessModifier_DistanceFromObject";
+ break;
+ case LS_MODIFIER_MATERIAL:
+ struct_name = "LineStyleThicknessModifier_Material";
+ break;
+ case LS_MODIFIER_CALLIGRAPHY:
+ struct_name = "LineStyleThicknessModifier_Calligraphy";
+ break;
+ default:
+ struct_name = "LineStyleThicknessModifier"; /* this should not happen */
+ }
+ writestruct(wd, DATA, struct_name, 1, m);
+ }
+ for (m = modifiers->first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ write_curvemapping(wd, ((LineStyleThicknessModifier_AlongStroke *)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ write_curvemapping(wd, ((LineStyleThicknessModifier_DistanceFromCamera *)m)->curve);
+ break;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ write_curvemapping(wd, ((LineStyleThicknessModifier_DistanceFromObject *)m)->curve);
+ break;
+ case LS_MODIFIER_MATERIAL:
+ write_curvemapping(wd, ((LineStyleThicknessModifier_Material *)m)->curve);
+ break;
+ }
+ }
+}
+
+static void write_linestyle_geometry_modifiers(WriteData *wd, ListBase *modifiers)
+{
+ LineStyleModifier *m;
+ const char *struct_name;
+
+ for (m = modifiers->first; m; m = m->next) {
+ switch (m->type) {
+ case LS_MODIFIER_SAMPLING:
+ struct_name = "LineStyleGeometryModifier_Sampling";
+ break;
+ case LS_MODIFIER_BEZIER_CURVE:
+ struct_name = "LineStyleGeometryModifier_BezierCurve";
+ break;
+ case LS_MODIFIER_SINUS_DISPLACEMENT:
+ struct_name = "LineStyleGeometryModifier_SinusDisplacement";
+ break;
+ case LS_MODIFIER_SPATIAL_NOISE:
+ struct_name = "LineStyleGeometryModifier_SpatialNoise";
+ break;
+ case LS_MODIFIER_PERLIN_NOISE_1D:
+ struct_name = "LineStyleGeometryModifier_PerlinNoise1D";
+ break;
+ case LS_MODIFIER_PERLIN_NOISE_2D:
+ struct_name = "LineStyleGeometryModifier_PerlinNoise2D";
+ break;
+ case LS_MODIFIER_BACKBONE_STRETCHER:
+ struct_name = "LineStyleGeometryModifier_BackboneStretcher";
+ break;
+ case LS_MODIFIER_TIP_REMOVER:
+ struct_name = "LineStyleGeometryModifier_TipRemover";
+ break;
+ case LS_MODIFIER_POLYGONIZATION:
+ struct_name = "LineStyleGeometryModifier_Polygonalization";
+ break;
+ case LS_MODIFIER_GUIDING_LINES:
+ struct_name = "LineStyleGeometryModifier_GuidingLines";
+ break;
+ case LS_MODIFIER_BLUEPRINT:
+ struct_name = "LineStyleGeometryModifier_Blueprint";
+ break;
+ case LS_MODIFIER_2D_OFFSET:
+ struct_name = "LineStyleGeometryModifier_2DOffset";
+ break;
+ case LS_MODIFIER_2D_TRANSFORM:
+ struct_name = "LineStyleGeometryModifier_2DTransform";
+ break;
+ default:
+ struct_name = "LineStyleGeometryModifier"; /* this should not happen */
+ }
+ writestruct(wd, DATA, struct_name, 1, m);
+ }
+}
+
+static void write_linestyles(WriteData *wd, ListBase *idbase)
+{
+ FreestyleLineStyle *linestyle;
+
+ for (linestyle = idbase->first; linestyle; linestyle = linestyle->id.next) {
+ if (linestyle->id.us>0 || wd->current) {
+ writestruct(wd, ID_LS, "FreestyleLineStyle", 1, linestyle);
+ if (linestyle->id.properties)
+ IDP_WriteProperty(linestyle->id.properties, wd);
+ if (linestyle->adt)
+ write_animdata(wd, linestyle->adt);
+ write_linestyle_color_modifiers(wd, &linestyle->color_modifiers);
+ write_linestyle_alpha_modifiers(wd, &linestyle->alpha_modifiers);
+ write_linestyle_thickness_modifiers(wd, &linestyle->thickness_modifiers);
+ write_linestyle_geometry_modifiers(wd, &linestyle->geometry_modifiers);
+ }
+ }
+}
+
/* context is usually defined by WM, two cases where no WM is available:
* - for forward compatibility, curscreen has to be saved
* - for undofile, curscene needs to be saved */
@@ -2877,7 +3224,7 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
/* XXX still remap G */
fg.curscreen= screen;
- fg.curscene= screen->scene;
+ fg.curscene= screen? screen->scene : NULL;
fg.displaymode= G.displaymode;
fg.winpos= G.winpos;
@@ -2886,7 +3233,6 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
fg.globalf= G.f;
BLI_strncpy(fg.filename, mainvar->name, sizeof(fg.filename));
-
sprintf(subvstr, "%4d", BLENDER_SUBVERSION);
memcpy(fg.subvstr, subvstr, 4);
@@ -2931,6 +3277,14 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
wd->use_mesh_compat = (write_flags & G_FILE_MESH_COMPAT) != 0;
#endif
+#ifdef USE_NODE_COMPAT_CUSTOMNODES
+ /* don't write compatibility data on undo */
+ if (!current) {
+ /* deprecated forward compat data is freed again below */
+ customnodes_add_deprecated_data(mainvar);
+ }
+#endif
+
sprintf(buf, "BLENDER%c%c%.3d", (sizeof(void*)==8)?'-':'_', (ENDIAN_ORDER==B_ENDIAN)?'V':'v', BLENDER_VERSION);
mywrite(wd, buf, 12);
@@ -2938,11 +3292,8 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
write_thumb(wd, thumb);
write_global(wd, write_flags, mainvar);
- /* no UI save in undo */
- if (current==NULL) {
- write_windowmanagers(wd, &mainvar->wm);
- write_screens (wd, &mainvar->screen);
- }
+ write_windowmanagers(wd, &mainvar->wm);
+ write_screens (wd, &mainvar->screen);
write_movieclips (wd, &mainvar->movieclip);
write_masks (wd, &mainvar->mask);
write_scenes (wd, &mainvar->scene);
@@ -2970,6 +3321,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
write_brushes (wd, &mainvar->brush);
write_scripts (wd, &mainvar->script);
write_gpencils (wd, &mainvar->gpencil);
+ write_linestyles(wd, &mainvar->linestyle);
write_libraries(wd, mainvar->next);
if (write_user_block) {
@@ -2979,6 +3331,17 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
/* dna as last, because (to be implemented) test for which structs are written */
writedata(wd, DNA1, wd->sdna->datalen, wd->sdna->data);
+#ifdef USE_NODE_COMPAT_CUSTOMNODES
+ /* compatibility data not created on undo */
+ if (!current) {
+ /* Ugly, forward compatibility code generates deprecated data during writing,
+ * this has to be freed again. Can not be done directly after writing, otherwise
+ * the data pointers could be reused and not be mapped correctly.
+ */
+ customnodes_free_deprecated_data(mainvar);
+ }
+#endif
+
/* end of file */
memset(&bhead, 0, sizeof(BHead));
bhead.code= ENDB;
@@ -3027,13 +3390,12 @@ static int 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)
{
- char userfilename[FILE_MAX];
char tempname[FILE_MAX+1];
int file, err, write_user_block;
/* path backup/restore */
void *path_list_backup = NULL;
- const int path_list_flag = (BLI_BPATH_TRAVERSE_SKIP_LIBRARY | BLI_BPATH_TRAVERSE_SKIP_MULTIFILE);
+ const int path_list_flag = (BKE_BPATH_TRAVERSE_SKIP_LIBRARY | BKE_BPATH_TRAVERSE_SKIP_MULTIFILE);
/* open temporary file, so we preserve the original in case we crash */
BLI_snprintf(tempname, sizeof(tempname), "%s@", filepath);
@@ -3046,7 +3408,7 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL
/* check if we need to backup and restore paths */
if (UNLIKELY((write_flags & G_FILE_RELATIVE_REMAP) && (G_FILE_SAVE_COPY & write_flags))) {
- path_list_backup = BLI_bpath_list_backup(mainvar, path_list_flag);
+ path_list_backup = BKE_bpath_list_backup(mainvar, path_list_flag);
}
/* remapping of relative paths to new file location */
@@ -3069,24 +3431,23 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL
* we should not have any relative paths, but if there
* is somehow, an invalid or empty G.main->name it will
* print an error, don't try make the absolute in this case. */
- BLI_bpath_absolute_convert(mainvar, G.main->name, NULL);
+ BKE_bpath_absolute_convert(mainvar, G.main->name, NULL);
}
}
}
- BLI_make_file_string(G.main->name, userfilename, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE);
- write_user_block= (BLI_path_cmp(filepath, userfilename) == 0);
+ write_user_block= write_flags & G_FILE_USERPREFS;
if (write_flags & G_FILE_RELATIVE_REMAP)
- BLI_bpath_relative_convert(mainvar, filepath, NULL); /* note, making relative to something OTHER then G.main->name */
+ BKE_bpath_relative_convert(mainvar, filepath, NULL); /* note, making relative to something OTHER then G.main->name */
/* actual file writing */
err= write_file_handle(mainvar, file, NULL, NULL, write_user_block, write_flags, thumb);
close(file);
if (UNLIKELY(path_list_backup)) {
- BLI_bpath_list_restore(mainvar, path_list_flag, path_list_backup);
- BLI_bpath_list_free(path_list_backup);
+ BKE_bpath_list_restore(mainvar, path_list_flag, path_list_backup);
+ BKE_bpath_list_free(path_list_backup);
}
if (err) {
@@ -3122,7 +3483,7 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL
return 0;
}
- BLI_delete(tempname, 0, 0);
+ BLI_delete(tempname, false, false);
}
else if (-1==ret) {
BKE_report(reports, RPT_ERROR, "Failed opening .gz file");
@@ -3151,3 +3512,4 @@ int BLO_write_file_mem(Main *mainvar, MemFile *compare, MemFile *current, int wr
if (err==0) return 1;
return 0;
}
+
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index 2a23658f5d0..c3ec5dd83b3 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -30,7 +30,7 @@ set(INC
../blenlib
../makesdna
../../../intern/guardedalloc
- ../../../extern/bullet2/src
+ ../../../extern/rangetree
../../../intern/opennl/extern
)
@@ -41,7 +41,6 @@ set(INC_SYS
set(SRC
operators/bmo_bevel.c
operators/bmo_connect.c
- operators/bmo_slide.c
operators/bmo_create.c
operators/bmo_dissolve.c
operators/bmo_dupe.c
@@ -58,7 +57,6 @@ set(SRC
operators/bmo_smooth_laplacian.c
operators/bmo_symmetrize.c
operators/bmo_subdivide.c
- operators/bmo_subdivide.h
operators/bmo_triangulate.c
operators/bmo_unsubdivide.c
operators/bmo_utils.c
@@ -74,6 +72,8 @@ set(SRC
intern/bmesh_iterators.c
intern/bmesh_iterators.h
intern/bmesh_iterators_inline.h
+ intern/bmesh_log.c
+ intern/bmesh_log.h
intern/bmesh_marking.c
intern/bmesh_marking.h
intern/bmesh_mesh.c
@@ -111,6 +111,10 @@ set(SRC
tools/bmesh_decimate_dissolve.c
tools/bmesh_decimate_unsubdivide.c
tools/bmesh_decimate.h
+ tools/bmesh_edgesplit.c
+ tools/bmesh_edgesplit.h
+ tools/bmesh_triangulate.c
+ tools/bmesh_triangulate.h
bmesh.h
bmesh_class.h
@@ -122,10 +126,17 @@ endif()
if(WITH_BULLET)
add_definitions(-DWITH_BULLET)
+ list(APPEND INC_SYS
+ ${BULLET_INCLUDE_DIRS}
+ )
endif()
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_FREESTYLE)
+ add_definitions(-DWITH_FREESTYLE)
+endif()
+
blender_add_lib(bf_bmesh "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/bmesh/SConscript b/source/blender/bmesh/SConscript
index 6765d57cb3e..de839f7f6a6 100644
--- a/source/blender/bmesh/SConscript
+++ b/source/blender/bmesh/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
cflags=''
@@ -8,14 +34,16 @@ sources += env.Glob('operators/*.c')
sources += env.Glob('tools/*.c')
incs = [
- './',
- '../blenfont',
- '../blenlib',
- '../makesdna',
- '../blenkernel',
- '#/intern/guardedalloc',
- '#/extern/bullet2/src',
- '#/intern/opennl/extern', ]
+ './',
+ '../blenfont',
+ '../blenlib',
+ '../makesdna',
+ '../blenkernel',
+ '#/intern/guardedalloc',
+ '#/extern/bullet2/src',
+ '#/extern/rangetree',
+ '#/intern/opennl/extern'
+ ]
defs = []
@@ -25,4 +53,7 @@ if env['WITH_BF_BULLET']:
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
+if env['WITH_BF_FREESTYLE']:
+ defs.append('WITH_FREESTYLE')
+
env.BlenderLib ( libname = 'bf_bmesh', sources = sources, includes = Split(incs), libtype = ['core','player'], defines=defs, priority=[100, 100], compileflags=cflags )
diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h
index 6257aa4bf3e..3b33513b575 100644
--- a/source/blender/bmesh/bmesh.h
+++ b/source/blender/bmesh/bmesh.h
@@ -243,6 +243,7 @@ extern "C" {
#include <stdlib.h>
#include <stdio.h>
+#include <assert.h>
#include "bmesh_class.h"
@@ -254,6 +255,7 @@ extern "C" {
#include "intern/bmesh_core.h"
#include "intern/bmesh_interp.h"
#include "intern/bmesh_iterators.h"
+#include "intern/bmesh_log.h"
#include "intern/bmesh_marking.h"
#include "intern/bmesh_mesh.h"
#include "intern/bmesh_mesh_conv.h"
@@ -266,8 +268,9 @@ extern "C" {
#include "intern/bmesh_inline.h"
-#include "tools/bmesh_decimate.h"
#include "tools/bmesh_bevel.h"
+#include "tools/bmesh_decimate.h"
+#include "tools/bmesh_triangulate.h"
#ifdef __cplusplus
}
diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h
index 9d797c1e602..845785a26d7 100644
--- a/source/blender/bmesh/bmesh_class.h
+++ b/source/blender/bmesh/bmesh_class.h
@@ -45,7 +45,7 @@ struct Object;
* pointers. this is a requirement of mempool's method of
* iteration.
*
- * hrm. it doesn't but stull works ok, remove the comment above? - campbell.
+ * hrm. it doesn't but still works ok, remove the comment above? - campbell.
*/
// #pragma GCC diagnostic error "-Wpadded"
@@ -184,11 +184,12 @@ typedef struct BMesh {
* BM_LOOP isn't handled so far. */
char elem_index_dirty;
- /*element pools*/
+ /* element pools */
struct BLI_mempool *vpool, *epool, *lpool, *fpool;
- /*operator api stuff*/
- struct BLI_mempool *toolflagpool;
+ /* operator api stuff (must be all NULL or all alloc'd) */
+ struct BLI_mempool *vtoolflagpool, *etoolflagpool, *ftoolflagpool;
+
int stackdepth;
struct BMOperator *currentop;
@@ -204,7 +205,7 @@ typedef struct BMesh {
* Only use when the edit mesh cant be accessed - campbell */
short selectmode;
- /*ID of the shape key this bmesh came from*/
+ /* ID of the shape key this bmesh came from */
int shapenr;
int walkers, totflags;
@@ -251,7 +252,21 @@ enum {
* not have functions clobber them */
};
+struct BPy_BMGeneric;
+extern void bpy_bm_generic_invalidate(struct BPy_BMGeneric *self);
+
/* defines */
+#define BM_ELEM_CD_GET_VOID_P(ele, offset) \
+ (assert(offset != -1), (void *)((char *)(ele)->head.data + (offset)))
+
+#define BM_ELEM_CD_SET_FLOAT(ele, offset, f) \
+ { assert(offset != -1); *((float *)((char *)(ele)->head.data + (offset))) = (f); } (void)0
+
+#define BM_ELEM_CD_GET_FLOAT(ele, offset) \
+ (assert(offset != -1), *((float *)((char *)(ele)->head.data + (offset))))
+
+#define BM_ELEM_CD_GET_FLOAT_AS_UCHAR(ele, offset) \
+ (assert(offset != -1), (unsigned char)(BM_ELEM_CD_GET_FLOAT(ele, offset) * 255.0f))
/*forward declarations*/
@@ -276,5 +291,6 @@ enum {
* but should not error on valid cases */
#define BM_LOOP_RADIAL_MAX 10000
#define BM_NGON_MAX 100000
+#define BM_OMP_LIMIT 10000 /* setting zero so we can catch bugs in OpenMP/BMesh */
#endif /* __BMESH_CLASS_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index e12110b31ca..fddb7b4bf2c 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -53,7 +53,7 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
* \brief Make Quad/Triangle
*
* Creates a new quad or triangle from a list of 3 or 4 vertices.
- * If \a nodouble is TRUE, then a check is done to see if a face
+ * If \a no_double is true, then a check is done to see if a face
* with these vertices already exists and returns it instead.
*
* If a pointer to an example face is provided, it's custom data
@@ -65,16 +65,16 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
BMFace *BM_face_create_quad_tri(BMesh *bm,
BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- const BMFace *example, const int nodouble)
+ const BMFace *example, const bool no_double)
{
BMVert *vtar[4] = {v1, v2, v3, v4};
- return BM_face_create_quad_tri_v(bm, vtar, v4 ? 4 : 3, example, nodouble);
+ return BM_face_create_quad_tri_v(bm, vtar, v4 ? 4 : 3, example, no_double);
}
-BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFace *example, const int nodouble)
+BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFace *example, const bool no_double)
{
BMFace *f = NULL;
- int is_overlap = FALSE;
+ bool is_overlap = false;
/* sanity check - debug mode only */
if (len == 3) {
@@ -97,7 +97,7 @@ BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFa
}
- if (nodouble) {
+ if (no_double) {
/* check if face exists or overlaps */
is_overlap = BM_face_exists(verts, len, &f);
}
@@ -173,15 +173,16 @@ void BM_face_copy_shared(BMesh *bm, BMFace *f)
*/
BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, const int create_flag)
{
- BMEdge **edges2 = BLI_array_alloca_and_count(edges2, len);
- BMVert **verts = BLI_array_alloca_and_count(verts, len + 1);
- int e2_index = 0;
- int v_index = 0;
+ 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;
- int i, /* j, */ v1found, reverse;
+ int i;
+ bool is_v1_found, is_reverse;
/* this code is hideous, yeek. I'll have to think about ways of
@@ -189,10 +190,7 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, i
* _and_ the old bmesh_mf functions, so its kindof smashed together
* - joeedh */
- if (!len || !v1 || !v2 || !edges || !bm) {
- BLI_assert(0);
- return NULL;
- }
+ BLI_assert(len && v1 && v2 && edges && bm);
/* put edges in correct order */
for (i = 0; i < len; i++) {
@@ -209,14 +207,19 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, i
SWAP(BMVert *, ev1, ev2);
}
- verts[v_index++] = ev1;
+ verts_sort[vsort_index++] = ev1;
v = ev2;
e = edges[0];
do {
BMEdge *e2 = e;
- verts[v_index++] = v;
- edges2[e2_index++] = e;
+ /* vertex array is (len + 1) */
+ if (UNLIKELY(vsort_index > len)) {
+ goto err; /* vertex in loop twice */
+ }
+
+ verts_sort[vsort_index++] = v;
+ edges_sort[esort_index++] = e;
/* we only flag the verts to check if they are in the face more then once */
BM_ELEM_API_FLAG_ENABLE(v, _FLAG_MV);
@@ -229,66 +232,67 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, i
}
} while (e2 != e);
- if (e2 == e)
+ if (UNLIKELY(e2 == e)) {
goto err; /* the edges do not form a closed loop */
+ }
e = e2;
} while (e != edges[0]);
- if (BLI_array_count(edges2) != len) {
+ if (UNLIKELY(esort_index != len)) {
goto err; /* we didn't use all edges in forming the boundary loop */
}
/* ok, edges are in correct order, now ensure they are going
* in the correct direction */
- v1found = reverse = FALSE;
+ is_v1_found = is_reverse = false;
for (i = 0; i < len; i++) {
- if (BM_vert_in_edge(edges2[i], v1)) {
+ if (BM_vert_in_edge(edges_sort[i], v1)) {
/* see if v1 and v2 are in the same edge */
- if (BM_vert_in_edge(edges2[i], v2)) {
+ 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(edges2[(i + 1) % len], v1)) {
- reverse = TRUE;
+ if (BM_vert_in_edge(edges_sort[(i + 1) % len], v1)) {
+ is_reverse = true;
break;
}
}
- v1found = TRUE;
+ is_v1_found = true;
}
- if ((v1found == FALSE) && BM_vert_in_edge(edges2[i], v2)) {
- reverse = TRUE;
+ if ((is_v1_found == false) && BM_vert_in_edge(edges_sort[i], v2)) {
+ is_reverse = true;
break;
}
}
- if (reverse) {
+ if (is_reverse) {
for (i = 0; i < len / 2; i++) {
- v = verts[i];
- verts[i] = verts[len - i - 1];
- verts[len - i - 1] = v;
+ v = verts_sort[i];
+ verts_sort[i] = verts_sort[len - i - 1];
+ verts_sort[len - i - 1] = v;
}
}
for (i = 0; i < len; i++) {
- edges2[i] = BM_edge_exists(verts[i], verts[(i + 1) % len]);
- if (!edges2[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 then once. if the flag is disabled. we've already visited */
- if (!BM_ELEM_API_FLAG_TEST(verts[i], _FLAG_MV)) {
+ if (UNLIKELY(!BM_ELEM_API_FLAG_TEST(verts_sort[i], _FLAG_MV))) {
goto err;
}
- BM_ELEM_API_FLAG_DISABLE(verts[i], _FLAG_MV);
+ BM_ELEM_API_FLAG_DISABLE(verts_sort[i], _FLAG_MV);
}
- f = BM_face_create(bm, verts, edges2, len, create_flag);
+ f = BM_face_create(bm, verts_sort, edges_sort, len, create_flag);
/* clean up flags */
for (i = 0; i < len; i++) {
- BM_ELEM_API_FLAG_DISABLE(edges2[i], _FLAG_MF);
+ BM_ELEM_API_FLAG_DISABLE(edges_sort[i], _FLAG_MF);
}
return f;
@@ -296,10 +300,9 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, i
err:
for (i = 0; i < len; i++) {
BM_ELEM_API_FLAG_DISABLE(edges[i], _FLAG_MF);
- /* vert count may != len */
- if (i < BLI_array_count(verts)) {
- BM_ELEM_API_FLAG_DISABLE(verts[i], _FLAG_MV);
- }
+ }
+ for (i = 0; i < vsort_index; i++) {
+ BM_ELEM_API_FLAG_DISABLE(verts_sort[i], _FLAG_MV);
}
return NULL;
@@ -790,7 +793,7 @@ void BM_elem_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, const void *sour
/* First we copy select */
if (BM_elem_flag_test((BMElem *)sheader, BM_ELEM_SELECT)) {
- BM_elem_select_set(target_mesh, (BMElem *)target, TRUE);
+ BM_elem_select_set(target_mesh, (BMElem *)target, true);
}
/* Now we copy flags */
@@ -817,6 +820,8 @@ void BM_elem_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, const void *sour
BMesh *BM_mesh_copy(BMesh *bm_old)
{
+#define USE_FAST_FACE_COPY
+
BMesh *bm_new;
BMVert *v, *v2, **vtable = NULL;
BMEdge *e, *e2, **edges = NULL, **etable = NULL;
@@ -824,6 +829,10 @@ BMesh *BM_mesh_copy(BMesh *bm_old)
BLI_array_declare(edges);
BMLoop *l, /* *l2, */ **loops = NULL;
BLI_array_declare(loops);
+#ifdef USE_FAST_FACE_COPY
+ BMVert **verts = NULL;
+ BLI_array_declare(verts);
+#endif
BMFace *f, *f2, **ftable = NULL;
BMEditSelection *ese;
BMIter iter, liter;
@@ -891,12 +900,24 @@ BMesh *BM_mesh_copy(BMesh *bm_old)
BLI_array_grow_items(loops, f->len);
BLI_array_grow_items(edges, f->len);
+#ifdef USE_FAST_FACE_COPY
+ BLI_array_empty(verts);
+ BLI_array_grow_items(verts, f->len);
+#endif
+
l = BM_iter_new(&liter, bm_old, BM_LOOPS_OF_FACE, f);
for (j = 0; j < f->len; j++, l = BM_iter_step(&liter)) {
loops[j] = l;
edges[j] = etable[BM_elem_index_get(l->e)];
+
+#ifdef USE_FAST_FACE_COPY
+ verts[j] = vtable[BM_elem_index_get(l->v)];
+#endif
}
+#ifdef USE_FAST_FACE_COPY
+ f2 = BM_face_create(bm_new, verts, edges, f->len, BM_CREATE_SKIP_CD);
+#else
v = vtable[BM_elem_index_get(loops[0]->v)];
v2 = vtable[BM_elem_index_get(loops[1]->v)];
@@ -906,6 +927,8 @@ BMesh *BM_mesh_copy(BMesh *bm_old)
}
f2 = BM_face_create_ngon(bm_new, v, v2, edges, f->len, BM_CREATE_SKIP_CD);
+#endif
+
if (UNLIKELY(f2 == NULL)) {
continue;
}
@@ -961,9 +984,12 @@ BMesh *BM_mesh_copy(BMesh *bm_old)
MEM_freeN(vtable);
MEM_freeN(ftable);
+#ifdef USE_FAST_FACE_COPY
+ BLI_array_free(verts);
+#endif
+
BLI_array_free(loops);
BLI_array_free(edges);
-
return bm_new;
}
diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h
index 60c465e5f5a..0f597dbb1d8 100644
--- a/source/blender/bmesh/intern/bmesh_construct.h
+++ b/source/blender/bmesh/intern/bmesh_construct.h
@@ -29,10 +29,10 @@
BMFace *BM_face_create_quad_tri_v(BMesh *bm,
BMVert **verts, int len,
- const BMFace *example, const int nodouble);
+ const BMFace *example, const bool no_double);
BMFace *BM_face_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- const BMFace *example, const int nodouble);
+ const BMFace *example, const bool no_double);
void BM_face_copy_shared(BMesh *bm, BMFace *f);
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index 4442b4eac9c..a11d45a7a5a 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -79,8 +79,8 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, cons
}
/* allocate flags */
- if (bm->toolflagpool) {
- v->oflags = BLI_mempool_calloc(bm->toolflagpool);
+ if (bm->vtoolflagpool) {
+ v->oflags = BLI_mempool_calloc(bm->vtoolflagpool);
}
if (!(create_flag & BM_CREATE_SKIP_CD)) {
@@ -109,7 +109,7 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, cons
* \brief Main function for creating a new edge.
*
* \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 nodouble = TRUE
+ * 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 *example, const eBMCreateFlag create_flag)
{
@@ -133,8 +133,8 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example,
e->head.htype = BM_EDGE;
/* allocate flags */
- if (bm->toolflagpool) {
- e->oflags = BLI_mempool_calloc(bm->toolflagpool);
+ if (bm->etoolflagpool) {
+ e->oflags = BLI_mempool_calloc(bm->etoolflagpool);
}
e->v1 = v1;
@@ -209,7 +209,8 @@ static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge
return l;
}
-BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short copyedges)
+BMFace *BM_face_copy(BMesh *bm, 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);
@@ -222,7 +223,7 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
i = 0;
do {
- if (copyverts) {
+ if (copy_verts) {
verts[i] = BM_vert_create(bm, l_iter->v->co, l_iter->v, 0);
}
else {
@@ -234,7 +235,7 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
i = 0;
do {
- if (copyedges) {
+ if (copy_edges) {
BMVert *v1, *v2;
if (l_iter->e->v1 == verts[i]) {
@@ -291,8 +292,8 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm, const eBMCreateFlag creat
f->head.htype = BM_FACE;
/* allocate flags */
- if (bm->toolflagpool) {
- f->oflags = BLI_mempool_calloc(bm->toolflagpool);
+ if (bm->ftoolflagpool) {
+ f->oflags = BLI_mempool_calloc(bm->ftoolflagpool);
}
if (!(create_flag & BM_CREATE_SKIP_CD)) {
@@ -512,8 +513,8 @@ static void bm_kill_only_vert(BMesh *bm, BMVert *v)
if (v->head.data)
CustomData_bmesh_free_block(&bm->vdata, &v->head.data);
- if (bm->toolflagpool) {
- BLI_mempool_free(bm->toolflagpool, v->oflags);
+ if (bm->vtoolflagpool) {
+ BLI_mempool_free(bm->vtoolflagpool, v->oflags);
}
BLI_mempool_free(bm->vpool, v);
}
@@ -532,8 +533,8 @@ static void bm_kill_only_edge(BMesh *bm, BMEdge *e)
if (e->head.data)
CustomData_bmesh_free_block(&bm->edata, &e->head.data);
- if (bm->toolflagpool) {
- BLI_mempool_free(bm->toolflagpool, e->oflags);
+ if (bm->etoolflagpool) {
+ BLI_mempool_free(bm->etoolflagpool, e->oflags);
}
BLI_mempool_free(bm->epool, e);
}
@@ -555,8 +556,8 @@ static void bm_kill_only_face(BMesh *bm, BMFace *f)
if (f->head.data)
CustomData_bmesh_free_block(&bm->pdata, &f->head.data);
- if (bm->toolflagpool) {
- BLI_mempool_free(bm->toolflagpool, f->oflags);
+ if (bm->ftoolflagpool) {
+ BLI_mempool_free(bm->ftoolflagpool, f->oflags);
}
BLI_mempool_free(bm->fpool, f);
}
@@ -734,7 +735,7 @@ static int UNUSED_FUNCTION(bm_loop_length)(BMLoop *l)
*
* \return Success
*/
-static int bm_loop_reverse_loop(BMesh *bm, BMFace *f
+static bool bm_loop_reverse_loop(BMesh *bm, BMFace *f
#ifdef USE_BMESH_HOLES
, BMLoopList *lst
#endif
@@ -748,7 +749,7 @@ static int bm_loop_reverse_loop(BMesh *bm, BMFace *f
#endif
const int len = f->len;
- const int do_disps = CustomData_has_layer(&bm->ldata, CD_MDISPS);
+ const bool do_disps = CustomData_has_layer(&bm->ldata, CD_MDISPS);
BMLoop *l_iter, *oldprev, *oldnext;
BMEdge **edar = BLI_array_alloca(edar, len);
int i, j, edok;
@@ -816,13 +817,13 @@ static int bm_loop_reverse_loop(BMesh *bm, BMFace *f
BM_CHECK_ELEMENT(f);
- return 1;
+ return true;
}
/**
* \brief Flip the faces direction
*/
-int bmesh_loop_reverse(BMesh *bm, BMFace *f)
+bool bmesh_loop_reverse(BMesh *bm, BMFace *f)
{
#ifdef USE_BMESH_HOLES
return bm_loop_reverse_loop(bm, f, f->loops.first);
@@ -893,26 +894,26 @@ static int UNUSED_FUNCTION(count_flagged_disk)(BMVert *v, int flag)
return i;
}
-static int disk_is_flagged(BMVert *v, int flag)
+static bool disk_is_flagged(BMVert *v, int flag)
{
BMEdge *e = v->e;
if (!e)
- return FALSE;
+ return false;
do {
BMLoop *l = e->l;
if (!l) {
- return FALSE;
+ return false;
}
if (bmesh_radial_length(l) == 1)
- return FALSE;
+ return false;
do {
if (!BM_ELEM_API_FLAG_TEST(l->f, flag))
- return FALSE;
+ return false;
l = l->radial_next;
} while (l != e->l);
@@ -920,7 +921,7 @@ static int disk_is_flagged(BMVert *v, int flag)
e = bmesh_disk_edge_next(e, v);
} while (e != v->e);
- return TRUE;
+ return true;
}
/* Mid-level Topology Manipulation Functions */
@@ -939,9 +940,9 @@ static int disk_is_flagged(BMVert *v, int flag)
* \note this is a generic, flexible join faces function,
* almost everything uses this, including #BM_faces_join_pair
*/
-BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del)
+BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del)
{
- BMFace *f, *newf;
+ BMFace *f, *f_new;
#ifdef USE_BMESH_HOLES
BMLoopList *lst;
ListBase holes = {NULL, NULL};
@@ -1035,15 +1036,15 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del
}
/* create region face */
- newf = tote ? BM_face_create_ngon(bm, v1, v2, edges, tote, 0) : NULL;
- if (UNLIKELY(!newf || BMO_error_occurred(bm))) {
+ f_new = tote ? BM_face_create_ngon(bm, v1, v2, edges, tote, 0) : NULL;
+ if (UNLIKELY(!f_new || BMO_error_occurred(bm))) {
if (!BMO_error_occurred(bm))
err = N_("Invalid boundary region to join faces");
goto error;
}
/* copy over loop data */
- l_iter = l_first = BM_FACE_FIRST_LOOP(newf);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
do {
BMLoop *l2 = l_iter->radial_next;
@@ -1063,34 +1064,34 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del
}
} while ((l_iter = l_iter->next) != l_first);
- BM_elem_attrs_copy(bm, bm, faces[0], newf);
+ BM_elem_attrs_copy(bm, bm, faces[0], f_new);
#ifdef USE_BMESH_HOLES
/* add holes */
- BLI_movelisttolist(&newf->loops, &holes);
+ BLI_movelisttolist(&f_new->loops, &holes);
#endif
/* update loop face pointer */
#ifdef USE_BMESH_HOLES
- for (lst = newf->loops.first; lst; lst = lst->next)
+ for (lst = f_new->loops.first; lst; lst = lst->next)
#endif
{
#ifdef USE_BMESH_HOLES
l_iter = l_first = lst->first;
#else
- l_iter = l_first = BM_FACE_FIRST_LOOP(newf);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
#endif
do {
- l_iter->f = newf;
+ l_iter->f = f_new;
} while ((l_iter = l_iter->next) != l_first);
}
bm_elements_systag_disable(faces, totface, _FLAG_JF);
- BM_ELEM_API_FLAG_DISABLE(newf, _FLAG_JF);
+ BM_ELEM_API_FLAG_DISABLE(f_new, _FLAG_JF);
/* handle multi-res data */
if (CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
- l_iter = l_first = BM_FACE_FIRST_LOOP(newf);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
do {
for (i = 0; i < totface; i++) {
BM_loop_interp_multires(bm, l_iter, faces[i]);
@@ -1119,8 +1120,8 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del
BLI_array_free(deledges);
BLI_array_free(delverts);
- BM_CHECK_ELEMENT(newf);
- return newf;
+ BM_CHECK_ELEMENT(f_new);
+ return f_new;
error:
bm_elements_systag_disable(faces, totface, _FLAG_JF);
@@ -1198,7 +1199,7 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2,
ListBase *holes,
#endif
BMEdge *example,
- const short nodouble
+ const bool no_double
)
{
#ifdef USE_BMESH_HOLES
@@ -1209,47 +1210,47 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2,
BMFace *f2;
BMLoop *l_iter, *l_first;
- BMLoop *v1loop = NULL, *v2loop = NULL, *f1loop = NULL, *f2loop = NULL;
+ BMLoop *l_v1 = NULL, *l_v2 = NULL, *l_f1 = NULL, *l_f2 = NULL;
BMEdge *e;
int i, len, f1len, f2len;
/* verify that v1 and v2 are in face */
len = f->len;
for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < len; i++, l_iter = l_iter->next) {
- if (l_iter->v == v1) v1loop = l_iter;
- else if (l_iter->v == v2) v2loop = l_iter;
+ if (l_iter->v == v1) l_v1 = l_iter;
+ else if (l_iter->v == v2) l_v2 = l_iter;
}
- if (!v1loop || !v2loop) {
+ if (!l_v1 || !l_v2) {
return NULL;
}
/* allocate new edge between v1 and v2 */
- e = BM_edge_create(bm, v1, v2, example, nodouble ? BM_CREATE_NO_DOUBLE : 0);
+ e = BM_edge_create(bm, v1, v2, example, no_double ? BM_CREATE_NO_DOUBLE : 0);
f2 = bm_face_create__sfme(bm, f);
- f1loop = bm_loop_create(bm, v2, e, f, v2loop, 0);
- f2loop = bm_loop_create(bm, v1, e, f2, v1loop, 0);
+ l_f1 = bm_loop_create(bm, v2, e, f, l_v2, 0);
+ l_f2 = bm_loop_create(bm, v1, e, f2, l_v1, 0);
- f1loop->prev = v2loop->prev;
- f2loop->prev = v1loop->prev;
- v2loop->prev->next = f1loop;
- v1loop->prev->next = f2loop;
+ l_f1->prev = l_v2->prev;
+ l_f2->prev = l_v1->prev;
+ l_v2->prev->next = l_f1;
+ l_v1->prev->next = l_f2;
- f1loop->next = v1loop;
- f2loop->next = v2loop;
- v1loop->prev = f1loop;
- v2loop->prev = f2loop;
+ l_f1->next = l_v1;
+ l_f2->next = l_v2;
+ l_v1->prev = l_f1;
+ l_v2->prev = l_f2;
#ifdef USE_BMESH_HOLES
lst = f->loops.first;
lst2 = f2->loops.first;
- lst2->first = lst2->last = f2loop;
- lst->first = lst->last = f1loop;
+ lst2->first = lst2->last = l_f2;
+ lst->first = lst->last = l_f1;
#else
/* find which of the faces the original first loop is in */
- l_iter = l_first = f1loop;
+ l_iter = l_first = l_f1;
first_loop_f1 = 0;
do {
if (l_iter == f->l_first)
@@ -1260,23 +1261,23 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2,
/* original first loop was in f1, find a suitable first loop for f2
* which is as similar as possible to f1. the order matters for tools
* such as duplifaces. */
- if (f->l_first->prev == f1loop)
- f2->l_first = f2loop->prev;
- else if (f->l_first->next == f1loop)
- f2->l_first = f2loop->next;
+ if (f->l_first->prev == l_f1)
+ f2->l_first = l_f2->prev;
+ else if (f->l_first->next == l_f1)
+ f2->l_first = l_f2->next;
else
- f2->l_first = f2loop;
+ f2->l_first = l_f2;
}
else {
/* original first loop was in f2, further do same as above */
f2->l_first = f->l_first;
- if (f->l_first->prev == f2loop)
- f->l_first = f1loop->prev;
- else if (f->l_first->next == f2loop)
- f->l_first = f1loop->next;
+ if (f->l_first->prev == l_f2)
+ f->l_first = l_f1->prev;
+ else if (f->l_first->next == l_f2)
+ f->l_first = l_f1->next;
else
- f->l_first = f1loop;
+ f->l_first = l_f1;
}
#endif
@@ -1292,8 +1293,8 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2,
} while ((l_iter = l_iter->next) != l_first);
/* link up the new loops into the new edges radial */
- bmesh_radial_append(e, f1loop);
- bmesh_radial_append(e, f2loop);
+ bmesh_radial_append(e, l_f1);
+ bmesh_radial_append(e, l_f2);
f2->len = f2len;
@@ -1305,7 +1306,7 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2,
f->len = f1len;
- if (r_l) *r_l = f2loop;
+ if (r_l) *r_l = l_f2;
#ifdef USE_BMESH_HOLES
if (holes) {
@@ -1348,76 +1349,77 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2,
*/
BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
{
- BMLoop *nextl;
- BMEdge *ne;
- BMVert *nv, *ov;
- int i, edok, valence1 = 0, valence2 = 0;
+ BMLoop *l_next;
+ BMEdge *e_new;
+ BMVert *v_new, *v_old;
+ int i, valence1 = 0, valence2 = 0;
+ bool edok;
- BLI_assert(bmesh_vert_in_edge(e, tv) != FALSE);
+ BLI_assert(bmesh_vert_in_edge(e, tv) != false);
- ov = bmesh_edge_other_vert_get(e, tv);
+ v_old = bmesh_edge_other_vert_get(e, tv);
- valence1 = bmesh_disk_count(ov);
+ valence1 = bmesh_disk_count(v_old);
valence2 = bmesh_disk_count(tv);
- nv = BM_vert_create(bm, tv->co, tv, 0);
- ne = BM_edge_create(bm, nv, tv, e, 0);
+ v_new = BM_vert_create(bm, tv->co, tv, 0);
+ e_new = BM_edge_create(bm, v_new, tv, e, 0);
- bmesh_disk_edge_remove(ne, tv);
- bmesh_disk_edge_remove(ne, nv);
+ 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 nv in e */
- bmesh_edge_swapverts(e, tv, nv);
+ /* swap out tv for v_new in e */
+ bmesh_edge_swapverts(e, tv, v_new);
- /* add e to nv's disk cycle */
- bmesh_disk_edge_append(e, nv);
+ /* add e to v_new's disk cycle */
+ bmesh_disk_edge_append(e, v_new);
- /* add ne to nv's disk cycle */
- bmesh_disk_edge_append(ne, nv);
+ /* add e_new to v_new's disk cycle */
+ bmesh_disk_edge_append(e_new, v_new);
- /* add ne to tv's disk cycle */
- bmesh_disk_edge_append(ne, tv);
+ /* add e_new to tv's disk cycle */
+ bmesh_disk_edge_append(e_new, tv);
/* verify disk cycles */
- edok = bmesh_disk_validate(valence1, ov->e, ov);
- BMESH_ASSERT(edok != FALSE);
+ edok = bmesh_disk_validate(valence1, v_old->e, v_old);
+ BMESH_ASSERT(edok != false);
edok = bmesh_disk_validate(valence2, tv->e, tv);
- BMESH_ASSERT(edok != FALSE);
- edok = bmesh_disk_validate(2, nv->e, nv);
- BMESH_ASSERT(edok != FALSE);
+ BMESH_ASSERT(edok != false);
+ edok = bmesh_disk_validate(2, v_new->e, v_new);
+ BMESH_ASSERT(edok != false);
/* Split the radial cycle if present */
- nextl = e->l;
+ l_next = e->l;
e->l = NULL;
- if (nextl) {
- BMLoop *nl, *l;
- int radlen = bmesh_radial_length(nextl);
+ if (l_next) {
+ BMLoop *l_new, *l;
+ int radlen = bmesh_radial_length(l_next);
int first1 = 0, first2 = 0;
/* Take the next loop. Remove it from radial. Split it. Append to appropriate radials */
- while (nextl) {
- l = nextl;
+ while (l_next) {
+ l = l_next;
l->f->len++;
- nextl = nextl != nextl->radial_next ? nextl->radial_next : NULL;
+ l_next = l_next != l_next->radial_next ? l_next->radial_next : NULL;
bmesh_radial_loop_remove(l, NULL);
- nl = bm_loop_create(bm, NULL, NULL, l->f, l, 0);
- nl->prev = l;
- nl->next = (l->next);
- nl->prev->next = nl;
- nl->next->prev = nl;
- nl->v = nv;
+ l_new = bm_loop_create(bm, NULL, NULL, l->f, l, 0);
+ l_new->prev = l;
+ l_new->next = (l->next);
+ l_new->prev->next = l_new;
+ l_new->next->prev = l_new;
+ l_new->v = v_new;
/* assign the correct edge to the correct loop */
- if (bmesh_verts_in_edge(nl->v, nl->next->v, e)) {
- nl->e = e;
- l->e = ne;
+ if (bmesh_verts_in_edge(l_new->v, l_new->next->v, e)) {
+ l_new->e = e;
+ l->e = e_new;
- /* append l into ne's rad cycle */
+ /* append l into e_new's rad cycle */
if (!first1) {
first1 = 1;
l->radial_next = l->radial_prev = NULL;
@@ -1428,14 +1430,14 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
l->radial_next = l->radial_prev = NULL;
}
- bmesh_radial_append(nl->e, nl);
+ bmesh_radial_append(l_new->e, l_new);
bmesh_radial_append(l->e, l);
}
- else if (bmesh_verts_in_edge(nl->v, nl->next->v, ne)) {
- nl->e = ne;
+ else if (bmesh_verts_in_edge(l_new->v, l_new->next->v, e_new)) {
+ l_new->e = e_new;
l->e = e;
- /* append l into ne's rad cycle */
+ /* append l into e_new's rad cycle */
if (!first1) {
first1 = 1;
l->radial_next = l->radial_prev = NULL;
@@ -1446,7 +1448,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
l->radial_next = l->radial_prev = NULL;
}
- bmesh_radial_append(nl->e, nl);
+ bmesh_radial_append(l_new->e, l_new);
bmesh_radial_append(l->e, l);
}
@@ -1454,18 +1456,18 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
/* verify length of radial cycle */
edok = bmesh_radial_validate(radlen, e->l);
- BMESH_ASSERT(edok != FALSE);
- edok = bmesh_radial_validate(radlen, ne->l);
- BMESH_ASSERT(edok != FALSE);
+ BMESH_ASSERT(edok != false);
+ edok = bmesh_radial_validate(radlen, e_new->l);
+ BMESH_ASSERT(edok != false);
/* verify loop->v and loop->next->v pointers for e */
for (i = 0, l = e->l; i < radlen; i++, l = l->radial_next) {
BMESH_ASSERT(l->e == e);
//BMESH_ASSERT(l->radial_next == l);
- BMESH_ASSERT(!(l->prev->e != ne && l->next->e != ne));
+ BMESH_ASSERT(!(l->prev->e != e_new && l->next->e != e_new));
edok = bmesh_verts_in_edge(l->v, l->next->v, e);
- BMESH_ASSERT(edok != FALSE);
+ BMESH_ASSERT(edok != false);
BMESH_ASSERT(l->v != l->next->v);
BMESH_ASSERT(l->e != l->next->e);
@@ -1475,13 +1477,13 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
BM_CHECK_ELEMENT(l->e);
BM_CHECK_ELEMENT(l->f);
}
- /* verify loop->v and loop->next->v pointers for ne */
- for (i = 0, l = ne->l; i < radlen; i++, l = l->radial_next) {
- BMESH_ASSERT(l->e == ne);
+ /* verify loop->v and loop->next->v pointers for e_new */
+ for (i = 0, l = e_new->l; i < radlen; i++, l = l->radial_next) {
+ BMESH_ASSERT(l->e == e_new);
// BMESH_ASSERT(l->radial_next == l);
BMESH_ASSERT(!(l->prev->e != e && l->next->e != e));
- edok = bmesh_verts_in_edge(l->v, l->next->v, ne);
- BMESH_ASSERT(edok != FALSE);
+ edok = bmesh_verts_in_edge(l->v, l->next->v, e_new);
+ BMESH_ASSERT(edok != false);
BMESH_ASSERT(l->v != l->next->v);
BMESH_ASSERT(l->e != l->next->e);
@@ -1492,20 +1494,20 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
}
}
- BM_CHECK_ELEMENT(ne);
- BM_CHECK_ELEMENT(nv);
- BM_CHECK_ELEMENT(ov);
+ BM_CHECK_ELEMENT(e_new);
+ BM_CHECK_ELEMENT(v_new);
+ BM_CHECK_ELEMENT(v_old);
BM_CHECK_ELEMENT(e);
BM_CHECK_ELEMENT(tv);
- if (r_e) *r_e = ne;
- return nv;
+ if (r_e) *r_e = e_new;
+ return v_new;
}
/**
* \brief Join Edge Kill Vert (JEKV)
*
- * Takes an edge \a ke and pointer to one of its vertices \a kv
+ * Takes an edge \a e_kill and pointer to one of its vertices \a v_kill
* and collapses the edge on that vertex.
*
* \par Examples:
@@ -1533,24 +1535,25 @@ 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 *ke, BMVert *kv, const short check_edge_double)
+BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool check_edge_double)
{
- BMEdge *oe;
- BMVert *ov, *tv;
- BMLoop *killoop, *l;
- int len, radlen = 0, halt = 0, i, valence1, valence2, edok;
+ BMEdge *e_old;
+ BMVert *v_old, *tv;
+ BMLoop *l_kill, *l;
+ int len, radlen = 0, i, valence1, valence2;
+ bool edok, halt = false;
- if (bmesh_vert_in_edge(ke, kv) == 0) {
+ if (bmesh_vert_in_edge(e_kill, v_kill) == 0) {
return NULL;
}
- len = bmesh_disk_count(kv);
+ len = bmesh_disk_count(v_kill);
if (len == 2) {
- oe = bmesh_disk_edge_next(ke, kv);
- tv = bmesh_edge_other_vert_get(ke, kv);
- ov = bmesh_edge_other_vert_get(oe, kv);
- halt = bmesh_verts_in_edge(kv, tv, oe); /* check for double edges */
+ e_old = bmesh_disk_edge_next(e_kill, v_kill);
+ tv = bmesh_edge_other_vert_get(e_kill, v_kill);
+ v_old = bmesh_edge_other_vert_get(e_old, v_kill);
+ halt = bmesh_verts_in_edge(v_kill, tv, e_old); /* check for double edges */
if (halt) {
return NULL;
@@ -1558,56 +1561,56 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_dou
else {
BMEdge *e_splice;
- /* For verification later, count valence of ov and tv */
- valence1 = bmesh_disk_count(ov);
+ /* For verification later, count valence of v_old and tv */
+ valence1 = bmesh_disk_count(v_old);
valence2 = bmesh_disk_count(tv);
if (check_edge_double) {
- e_splice = BM_edge_exists(tv, ov);
+ e_splice = BM_edge_exists(tv, v_old);
}
- /* remove oe from kv's disk cycle */
- bmesh_disk_edge_remove(oe, kv);
- /* relink oe->kv to be oe->tv */
- bmesh_edge_swapverts(oe, kv, tv);
- /* append oe to tv's disk cycle */
- bmesh_disk_edge_append(oe, tv);
- /* remove ke from tv's disk cycle */
- bmesh_disk_edge_remove(ke, tv);
-
- /* deal with radial cycle of ke */
- radlen = bmesh_radial_length(ke->l);
- if (ke->l) {
- /* first step, fix the neighboring loops of all loops in ke's radial cycle */
- for (i = 0, killoop = ke->l; i < radlen; i++, killoop = killoop->radial_next) {
+ /* 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);
+ /* remove e_kill from tv's disk cycle */
+ bmesh_disk_edge_remove(e_kill, tv);
+
+ /* deal with radial cycle of e_kill */
+ radlen = bmesh_radial_length(e_kill->l);
+ if (e_kill->l) {
+ /* first step, fix the neighboring loops of all loops in e_kill's radial cycle */
+ for (i = 0, l_kill = e_kill->l; i < radlen; i++, l_kill = l_kill->radial_next) {
/* relink loops and fix vertex pointer */
- if (killoop->next->v == kv) {
- killoop->next->v = tv;
+ if (l_kill->next->v == v_kill) {
+ l_kill->next->v = tv;
}
- killoop->next->prev = killoop->prev;
- killoop->prev->next = killoop->next;
- if (BM_FACE_FIRST_LOOP(killoop->f) == killoop) {
- BM_FACE_FIRST_LOOP(killoop->f) = killoop->next;
+ l_kill->next->prev = l_kill->prev;
+ l_kill->prev->next = l_kill->next;
+ if (BM_FACE_FIRST_LOOP(l_kill->f) == l_kill) {
+ BM_FACE_FIRST_LOOP(l_kill->f) = l_kill->next;
}
- killoop->next = NULL;
- killoop->prev = NULL;
+ l_kill->next = NULL;
+ l_kill->prev = NULL;
/* fix len attribute of face */
- killoop->f->len--;
+ l_kill->f->len--;
}
- /* second step, remove all the hanging loops attached to ke */
- radlen = bmesh_radial_length(ke->l);
+ /* second step, remove all the hanging loops attached to e_kill */
+ radlen = bmesh_radial_length(e_kill->l);
if (LIKELY(radlen)) {
BMLoop **loops = BLI_array_alloca(loops, radlen);
- killoop = ke->l;
+ l_kill = e_kill->l;
/* this should be wrapped into a bme_free_radial function to be used by bmesh_KF as well... */
for (i = 0; i < radlen; i++) {
- loops[i] = killoop;
- killoop = killoop->radial_next;
+ loops[i] = l_kill;
+ l_kill = l_kill->radial_next;
}
for (i = 0; i < radlen; i++) {
bm->totloop--;
@@ -1615,30 +1618,30 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_dou
}
}
- /* Validate radial cycle of oe */
- edok = bmesh_radial_validate(radlen, oe->l);
- BMESH_ASSERT(edok != FALSE);
+ /* Validate radial cycle of e_old */
+ edok = bmesh_radial_validate(radlen, e_old->l);
+ BMESH_ASSERT(edok != false);
}
/* deallocate edge */
- bm_kill_only_edge(bm, ke);
+ bm_kill_only_edge(bm, e_kill);
/* deallocate vertex */
- bm_kill_only_vert(bm, kv);
+ bm_kill_only_vert(bm, v_kill);
- /* Validate disk cycle lengths of ov, tv are unchanged */
- edok = bmesh_disk_validate(valence1, ov->e, ov);
- BMESH_ASSERT(edok != FALSE);
+ /* Validate disk cycle lengths of v_old, tv are unchanged */
+ edok = bmesh_disk_validate(valence1, v_old->e, v_old);
+ BMESH_ASSERT(edok != false);
edok = bmesh_disk_validate(valence2, tv->e, tv);
- BMESH_ASSERT(edok != FALSE);
+ BMESH_ASSERT(edok != false);
- /* Validate loop cycle of all faces attached to 'oe' */
- for (i = 0, l = oe->l; i < radlen; i++, l = l->radial_next) {
- BMESH_ASSERT(l->e == oe);
- edok = bmesh_verts_in_edge(l->v, l->next->v, oe);
- BMESH_ASSERT(edok != FALSE);
+ /* Validate loop cycle of all faces attached to 'e_old' */
+ for (i = 0, l = e_old->l; i < radlen; i++, l = l->radial_next) {
+ BMESH_ASSERT(l->e == e_old);
+ edok = bmesh_verts_in_edge(l->v, l->next->v, e_old);
+ BMESH_ASSERT(edok != false);
edok = bmesh_loop_validate(l->f);
- BMESH_ASSERT(edok != FALSE);
+ BMESH_ASSERT(edok != false);
BM_CHECK_ELEMENT(l);
BM_CHECK_ELEMENT(l->v);
@@ -1649,15 +1652,15 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_dou
if (check_edge_double) {
if (e_splice) {
/* removes e_splice */
- BM_edge_splice(bm, e_splice, oe);
+ BM_edge_splice(bm, e_splice, e_old);
}
}
- BM_CHECK_ELEMENT(ov);
+ BM_CHECK_ELEMENT(v_old);
BM_CHECK_ELEMENT(tv);
- BM_CHECK_ELEMENT(oe);
+ BM_CHECK_ELEMENT(e_old);
- return oe;
+ return e_old;
}
}
return NULL;
@@ -1696,9 +1699,9 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_dou
*/
BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
{
- BMLoop *l_iter, *f1loop = NULL, *f2loop = NULL;
- int newlen = 0, i, f1len = 0, f2len = 0, edok;
-
+ BMLoop *l_iter, *l_f1 = NULL, *l_f2 = NULL;
+ int newlen = 0, i, f1len = 0, f2len = 0;
+ bool edok;
/* can't join a face to itself */
if (f1 == f2) {
return NULL;
@@ -1713,23 +1716,23 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
f1len = f1->len;
f2len = f2->len;
- if (!((f1loop = BM_face_edge_share_loop(f1, e)) &&
- (f2loop = BM_face_edge_share_loop(f2, e))))
+ if (!((l_f1 = BM_face_edge_share_loop(f1, e)) &&
+ (l_f2 = BM_face_edge_share_loop(f2, e))))
{
return NULL;
}
/* validate direction of f2's loop cycle is compatible */
- if (f1loop->v == f2loop->v) {
+ if (l_f1->v == l_f2->v) {
return NULL;
}
/* validate that for each face, each vertex has another edge in its disk cycle that is
* not e, and not shared. */
- if (bmesh_radial_face_find(f1loop->next->e, f2) ||
- bmesh_radial_face_find(f1loop->prev->e, f2) ||
- bmesh_radial_face_find(f2loop->next->e, f1) ||
- bmesh_radial_face_find(f2loop->prev->e, f1) )
+ if (bmesh_radial_face_find(l_f1->next->e, f2) ||
+ bmesh_radial_face_find(l_f1->prev->e, f2) ||
+ bmesh_radial_face_find(l_f2->next->e, f1) ||
+ bmesh_radial_face_find(l_f2->prev->e, f1) )
{
return NULL;
}
@@ -1748,12 +1751,12 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
}
for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < f1len; i++, l_iter = l_iter->next) {
- if (l_iter != f1loop) {
+ if (l_iter != l_f1) {
BM_elem_flag_enable(l_iter->v, BM_ELEM_INTERNAL_TAG);
}
}
for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f2); i < f2len; i++, l_iter = l_iter->next) {
- if (l_iter != f2loop) {
+ if (l_iter != l_f2) {
/* as soon as a duplicate is found, bail out */
if (BM_elem_flag_test(l_iter->v, BM_ELEM_INTERNAL_TAG)) {
return NULL;
@@ -1762,15 +1765,15 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
}
/* join the two loop */
- f1loop->prev->next = f2loop->next;
- f2loop->next->prev = f1loop->prev;
+ l_f1->prev->next = l_f2->next;
+ l_f2->next->prev = l_f1->prev;
- f1loop->next->prev = f2loop->prev;
- f2loop->prev->next = f1loop->next;
+ l_f1->next->prev = l_f2->prev;
+ l_f2->prev->next = l_f1->next;
- /* if f1loop was baseloop, make f1loop->next the base. */
- if (BM_FACE_FIRST_LOOP(f1) == f1loop)
- BM_FACE_FIRST_LOOP(f1) = f1loop->next;
+ /* if l_f1 was baseloop, make l_f1->next the base. */
+ if (BM_FACE_FIRST_LOOP(f1) == l_f1)
+ BM_FACE_FIRST_LOOP(f1) = l_f1->next;
/* increase length of f1 */
f1->len += (f2->len - 2);
@@ -1781,21 +1784,21 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
l_iter->f = f1;
/* remove edge from the disk cycle of its two vertices */
- bmesh_disk_edge_remove(f1loop->e, f1loop->e->v1);
- bmesh_disk_edge_remove(f1loop->e, f1loop->e->v2);
+ bmesh_disk_edge_remove(l_f1->e, l_f1->e->v1);
+ bmesh_disk_edge_remove(l_f1->e, l_f1->e->v2);
/* deallocate edge and its two loops as well as f2 */
- if (bm->toolflagpool) {
- BLI_mempool_free(bm->toolflagpool, f1loop->e->oflags);
+ if (bm->etoolflagpool) {
+ BLI_mempool_free(bm->etoolflagpool, l_f1->e->oflags);
}
- BLI_mempool_free(bm->epool, f1loop->e);
+ BLI_mempool_free(bm->epool, l_f1->e);
bm->totedge--;
- BLI_mempool_free(bm->lpool, f1loop);
+ BLI_mempool_free(bm->lpool, l_f1);
bm->totloop--;
- BLI_mempool_free(bm->lpool, f2loop);
+ BLI_mempool_free(bm->lpool, l_f2);
bm->totloop--;
- if (bm->toolflagpool) {
- BLI_mempool_free(bm->toolflagpool, f2->oflags);
+ if (bm->ftoolflagpool) {
+ BLI_mempool_free(bm->ftoolflagpool, f2->oflags);
}
BLI_mempool_free(bm->fpool, f2);
bm->totface--;
@@ -1806,7 +1809,7 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
/* validate the new loop cycle */
edok = bmesh_loop_validate(f1);
- BMESH_ASSERT(edok != FALSE);
+ BMESH_ASSERT(edok != false);
return f1;
}
@@ -1822,7 +1825,7 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
* where \a v and \a vtarget are connected by an edge
* (assert checks for this case).
*/
-int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target)
+bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target)
{
void *loops_stack[BM_DEFAULT_ITER_STACK_SIZE];
BMLoop **loops;
@@ -1832,7 +1835,7 @@ int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target)
/* verts already spliced */
if (v == v_target) {
- return FALSE;
+ return false;
}
/* we can't modify the vert while iterating so first allocate an array of loops */
@@ -1862,7 +1865,7 @@ int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target)
/* v is unused now, and can be killed */
BM_vert_kill(bm, v);
- return TRUE;
+ return true;
}
/**
@@ -1876,17 +1879,17 @@ int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target)
*
* \return Success
*/
-int bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len)
+bool bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len)
{
BMEdge **stack = NULL;
- BLI_array_declare(stack);
+ BLI_array_staticdeclare(stack, BM_DEFAULT_ITER_STACK_SIZE);
BMVert **verts = NULL;
GHash *visithash;
BMIter eiter, liter;
BMLoop *l;
BMEdge *e;
int i, maxindex;
- BMLoop *nl;
+ BMLoop *l_new;
visithash = BLI_ghash_ptr_new(__func__);
@@ -1905,9 +1908,9 @@ int bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len)
BLI_ghash_insert(visithash, e, SET_INT_IN_POINTER(maxindex));
BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) {
- nl = (l->v == v) ? l->prev : l->next;
- if (!BLI_ghash_haskey(visithash, nl->e)) {
- BLI_array_append(stack, nl->e);
+ l_new = (l->v == v) ? l->prev : l->next;
+ if (!BLI_ghash_haskey(visithash, l_new->e)) {
+ BLI_array_append(stack, l_new->e);
}
}
}
@@ -1993,13 +1996,13 @@ int bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len)
MEM_freeN(verts);
}
- return TRUE;
+ return true;
}
/**
* High level function which wraps both #bmesh_vert_separate and #bmesh_edge_separate
*/
-int BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
+bool BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
BMEdge **e_in, int e_in_len)
{
int i;
@@ -2023,7 +2026,7 @@ int BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
*
* \note Edges must already have the same vertices.
*/
-int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target)
+bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target)
{
BMLoop *l;
@@ -2034,7 +2037,7 @@ int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target)
* so assert on release builds */
BLI_assert(0);
- return FALSE;
+ return false;
}
while (e->l) {
@@ -2053,7 +2056,7 @@ int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target)
/* removes from disks too */
BM_edge_kill(bm, e);
- return TRUE;
+ return true;
}
/**
@@ -2067,9 +2070,9 @@ int 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.
*/
-int bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep)
+bool bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep)
{
- BMEdge *ne;
+ BMEdge *e_new;
int radlen;
BLI_assert(l_sep->e == e);
@@ -2078,81 +2081,81 @@ int bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep)
radlen = bmesh_radial_length(e->l);
if (radlen < 2) {
/* no cut required */
- return TRUE;
+ return true;
}
if (l_sep == e->l) {
e->l = l_sep->radial_next;
}
- ne = BM_edge_create(bm, e->v1, e->v2, e, 0);
+ e_new = BM_edge_create(bm, e->v1, e->v2, e, 0);
bmesh_radial_loop_remove(l_sep, e);
- bmesh_radial_append(ne, l_sep);
- l_sep->e = ne;
+ bmesh_radial_append(e_new, l_sep);
+ l_sep->e = e_new;
BLI_assert(bmesh_radial_length(e->l) == radlen - 1);
- BLI_assert(bmesh_radial_length(ne->l) == 1);
+ BLI_assert(bmesh_radial_length(e_new->l) == 1);
- BM_CHECK_ELEMENT(ne);
+ BM_CHECK_ELEMENT(e_new);
BM_CHECK_ELEMENT(e);
- return TRUE;
+ return true;
}
/**
- * \brief Unglue Region Make Vert (URMV)
+ * \brief Un-glue Region Make Vert (URMV)
*
- * Disconnects a face from its vertex fan at loop \a sl
+ * Disconnects a face from its vertex fan at loop \a l_sep
*
* \return The newly created BMVert
*/
-BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl)
+BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep)
{
BMVert **vtar;
int len, i;
- BMVert *nv = NULL;
- BMVert *sv = sl->v;
+ BMVert *v_new = NULL;
+ BMVert *v_sep = l_sep->v;
/* peel the face from the edge radials on both sides of the
* loop vert, disconnecting the face from its fan */
- bmesh_edge_separate(bm, sl->e, sl);
- bmesh_edge_separate(bm, sl->prev->e, sl->prev);
+ bmesh_edge_separate(bm, l_sep->e, l_sep);
+ bmesh_edge_separate(bm, l_sep->prev->e, l_sep->prev);
- if (bmesh_disk_count(sv) == 2) {
- /* If there are still only two edges out of sv, then
+ 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. */
- return sv;
+ return v_sep;
}
/* 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 sv on some *other* fan (not the
+ * will leave the original v_sep on some *other* fan (not the
* one-face fan that holds the unglue face). */
- while (sv->e == sl->e || sv->e == sl->prev->e) {
- sv->e = bmesh_disk_edge_next(sv->e, sv);
+ 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);
}
/* Split all fans connected to the vert, duplicating it for
* each fans. */
- bmesh_vert_separate(bm, sv, &vtar, &len);
+ bmesh_vert_separate(bm, v_sep, &vtar, &len);
/* There should have been at least two fans cut apart here,
* otherwise the early exit would have kicked in. */
BLI_assert(len >= 2);
- nv = sl->v;
+ v_new = l_sep->v;
/* 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(nv != sv);
- BLI_assert(sv == vtar[0]);
+ BLI_assert(v_new != v_sep);
+ BLI_assert(v_sep == vtar[0]);
/* 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] == nv) {
+ if (vtar[i] == v_new) {
break;
}
}
@@ -2171,18 +2174,18 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl)
MEM_freeN(vtar);
- return nv;
+ return v_new;
}
/**
* \brief Unglue Region Make Vert (URMV)
*
- * Disconnects sf from the vertex fan at \a sv
+ * Disconnects f_sep from the vertex fan at \a v_sep
*
* \return The newly created BMVert
*/
-BMVert *bmesh_urmv(BMesh *bm, BMFace *sf, BMVert *sv)
+BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep)
{
- BMLoop *l = BM_face_vert_share_loop(sf, sv);
+ BMLoop *l = BM_face_vert_share_loop(f_sep, v_sep);
return bmesh_urmv_loop(bm, l);
}
diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h
index 5fd4a6ec7df..a1f378aaa5d 100644
--- a/source/blender/bmesh/intern/bmesh_core.h
+++ b/source/blender/bmesh/intern/bmesh_core.h
@@ -27,7 +27,8 @@
* \ingroup bmesh
*/
-BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short copyedges);
+BMFace *BM_face_copy(BMesh *bm, BMFace *f,
+ const bool copy_verts, const bool copy_edges);
typedef enum eBMCreateFlag {
/* faces and edges only */
@@ -49,16 +50,16 @@ void BM_face_kill(BMesh *bm, BMFace *f);
void BM_edge_kill(BMesh *bm, BMEdge *e);
void BM_vert_kill(BMesh *bm, BMVert *v);
-int bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep);
-int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target);
-int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target);
+bool bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep);
+bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target);
+bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target);
-int bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len);
+bool bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len);
-int bmesh_loop_reverse(BMesh *bm, BMFace *f);
+bool bmesh_loop_reverse(BMesh *bm, BMFace *f);
-BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del);
-int BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
+BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del);
+bool BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
BMEdge **e_in, int e_in_len);
/* EULER API - For modifying structure */
@@ -68,13 +69,13 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1,
ListBase *holes,
#endif
BMEdge *example,
- const short nodouble
+ const bool no_double
);
BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e);
-BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_splice);
+BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool check_edge_splice);
BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e);
-BMVert *bmesh_urmv(BMesh *bm, BMFace *sf, BMVert *sv);
-BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl);
+BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep);
+BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep);
#endif /* __BMESH_CORE_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_error.h b/source/blender/bmesh/intern/bmesh_error.h
index 2ef146c7b38..0f23f87c143 100644
--- a/source/blender/bmesh/intern/bmesh_error.h
+++ b/source/blender/bmesh/intern/bmesh_error.h
@@ -35,11 +35,11 @@ void BMO_error_raise(BMesh *bm, BMOperator *owner, int errcode, const char *msg)
/* gets the topmost error from the stack.
* returns error code or 0 if no error.*/
-int BMO_error_get(BMesh *bm, const char **msg, BMOperator **op);
-int BMO_error_occurred(BMesh *bm);
+int BMO_error_get(BMesh *bm, const char **msg, BMOperator **op);
+bool BMO_error_occurred(BMesh *bm);
/* same as geterror, only pops the error off the stack as well */
-int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op);
+int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op);
void BMO_error_clear(BMesh *bm);
/* this is meant for handling errors, like self-intersection test failures.
diff --git a/source/blender/bmesh/intern/bmesh_inline.h b/source/blender/bmesh/intern/bmesh_inline.h
index 04b214f725a..102e9d47ffd 100644
--- a/source/blender/bmesh/intern/bmesh_inline.h
+++ b/source/blender/bmesh/intern/bmesh_inline.h
@@ -44,7 +44,7 @@ BLI_INLINE char _bm_elem_flag_test(const BMHeader *head, const char hflag)
return head->hflag & hflag;
}
-BLI_INLINE short _bm_elem_flag_test_bool(const BMHeader *head, const char hflag)
+BLI_INLINE bool _bm_elem_flag_test_bool(const BMHeader *head, const char hflag)
{
return (head->hflag & hflag) != 0;
}
diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c
index df58b90bc03..d0ab0ea5d60 100644
--- a/source/blender/bmesh/intern/bmesh_interp.c
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -126,7 +126,7 @@ void BM_data_interp_face_vert_edge(BMesh *bm, BMVert *v1, BMVert *UNUSED(v2), BM
{
void *src[2];
float w[2];
- BMLoop *v1loop = NULL, *vloop = NULL, *v2loop = NULL;
+ BMLoop *l_v1 = NULL, *l_v = NULL, *l_v2 = NULL;
BMLoop *l_iter = NULL;
if (!e1->l) {
@@ -139,23 +139,23 @@ void BM_data_interp_face_vert_edge(BMesh *bm, BMVert *v1, BMVert *UNUSED(v2), BM
l_iter = e1->l;
do {
if (l_iter->v == v1) {
- v1loop = l_iter;
- vloop = v1loop->next;
- v2loop = vloop->next;
+ l_v1 = l_iter;
+ l_v = l_v1->next;
+ l_v2 = l_v->next;
}
else if (l_iter->v == v) {
- v1loop = l_iter->next;
- vloop = l_iter;
- v2loop = l_iter->prev;
+ l_v1 = l_iter->next;
+ l_v = l_iter;
+ l_v2 = l_iter->prev;
}
- if (!v1loop || !v2loop)
+ if (!l_v1 || !l_v2)
return;
- src[0] = v1loop->head.data;
- src[1] = v2loop->head.data;
+ src[0] = l_v1->head.data;
+ src[1] = l_v2->head.data;
- CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, vloop->head.data);
+ CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_v->head.data);
} while ((l_iter = l_iter->radial_next) != e1->l);
}
@@ -599,16 +599,16 @@ void BM_loop_interp_multires(BMesh *bm, BMLoop *target, BMFace *source)
* 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,
- int do_vertex, int do_multires)
+ const bool do_vertex, const bool do_multires)
{
BMLoop *l_iter;
BMLoop *l_first;
- void **vblocks = BLI_array_alloca(vblocks, do_vertex ? source->len : 0);
+ void **vblocks = do_vertex ? BLI_array_alloca(vblocks, source->len) : NULL;
void **blocks = BLI_array_alloca(blocks, source->len);
float (*cos)[3] = BLI_array_alloca(cos, source->len);
+ float (*cos_2d)[2] = BLI_array_alloca(cos_2d, source->len);
float *w = BLI_array_alloca(w, source->len);
- float co[3];
- float cent[3] = {0.0f, 0.0f, 0.0f};
+ float co[2];
int i, ax, ay;
BM_elem_attrs_copy(bm, bm, source, target->f);
@@ -617,7 +617,6 @@ void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source,
l_iter = l_first = BM_FACE_FIRST_LOOP(source);
do {
copy_v3_v3(cos[i], l_iter->v->co);
- add_v3_v3(cent, cos[i]);
w[i] = 0.0f;
blocks[i] = l_iter->head.data;
@@ -634,28 +633,17 @@ void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source,
axis_dominant_v3(&ax, &ay, source->no);
- /* scale source face coordinates a bit, so points sitting directly on an
- * edge will work. */
- mul_v3_fl(cent, 1.0f / (float)source->len);
for (i = 0; i < source->len; i++) {
- float vec[3], tmp[3];
- sub_v3_v3v3(vec, cent, cos[i]);
- mul_v3_fl(vec, 0.001f);
- add_v3_v3(cos[i], vec);
-
- copy_v3_v3(tmp, cos[i]);
- cos[i][0] = tmp[ax];
- cos[i][1] = tmp[ay];
- cos[i][2] = 0.0f;
+ cos_2d[i][0] = cos[i][ax];
+ cos_2d[i][1] = cos[i][ay];
}
/* interpolate */
co[0] = target->v->co[ax];
co[1] = target->v->co[ay];
- co[2] = 0.0f;
- interp_weights_poly_v3(w, cos, source->len, co);
+ interp_weights_poly_v2(w, cos_2d, source->len, co);
CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, source->len, target->head.data);
if (do_vertex) {
CustomData_bmesh_interp(&bm->vdata, vblocks, w, NULL, source->len, target->v->head.data);
@@ -676,30 +664,18 @@ void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source)
void **blocks = BLI_array_alloca(blocks, source->len);
float (*cos)[3] = BLI_array_alloca(cos, source->len);
float *w = BLI_array_alloca(w, source->len);
- float cent[3] = {0.0f, 0.0f, 0.0f};
int i;
i = 0;
l_iter = l_first = BM_FACE_FIRST_LOOP(source);
do {
copy_v3_v3(cos[i], l_iter->v->co);
- add_v3_v3(cent, cos[i]);
w[i] = 0.0f;
blocks[i] = l_iter->v->head.data;
i++;
} while ((l_iter = l_iter->next) != l_first);
- /* scale source face coordinates a bit, so points sitting directly on an
- * edge will work. */
- mul_v3_fl(cent, 1.0f / (float)source->len);
- for (i = 0; i < source->len; i++) {
- float vec[3];
- sub_v3_v3v3(vec, cent, cos[i]);
- mul_v3_fl(vec, 0.01f);
- add_v3_v3(cos[i], vec);
- }
-
/* interpolate */
interp_weights_poly_v3(w, cos, source->len, v->co);
CustomData_bmesh_interp(&bm->vdata, blocks, w, NULL, source->len, v->head.data);
diff --git a/source/blender/bmesh/intern/bmesh_interp.h b/source/blender/bmesh/intern/bmesh_interp.h
index 8be963f5798..3563ed1f40e 100644
--- a/source/blender/bmesh/intern/bmesh_interp.h
+++ b/source/blender/bmesh/intern/bmesh_interp.h
@@ -44,7 +44,7 @@ void BM_elem_float_data_set(CustomData *cd, void *element, int type, const floa
void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source);
void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source,
- int do_vertex, int do_multires);
+ const bool do_vertex, const bool do_multires);
void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f);
diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c
index c3f33eb95e1..44b76df7432 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.c
+++ b/source/blender/bmesh/intern/bmesh_iterators.c
@@ -164,14 +164,12 @@ void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len,
*
* Counts how many flagged / unflagged items are found in this element.
*/
-int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const short value)
+int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value)
{
BMIter iter;
BMElem *ele;
int count = 0;
- BLI_assert(ELEM(value, TRUE, FALSE));
-
for (ele = BM_iter_new(&iter, NULL, itype, data); ele; ele = BM_iter_step(&iter)) {
if (BM_elem_flag_test_bool(ele, hflag) == value) {
count++;
@@ -186,14 +184,12 @@ 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 mesh.
*/
-int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const short value)
+int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value)
{
BMIter iter;
BMElem *ele;
int count = 0;
- BLI_assert(ELEM(value, TRUE, FALSE));
-
for (ele = BM_iter_new(&iter, bm, itype, NULL); ele; ele = BM_iter_step(&iter)) {
if (BM_elem_flag_test_bool(ele, hflag) == value) {
count++;
diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h
index 7291bca6356..3b795a253bd 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.h
+++ b/source/blender/bmesh/intern/bmesh_iterators.h
@@ -131,8 +131,8 @@ void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len,
__attribute__((warn_unused_result))
#endif
;
-int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const short value);
-int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const short value);
+int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value);
+int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value);
/* private for bmesh_iterators_inline.c */
void bmiter__vert_of_mesh_begin(struct BMIter *iter);
diff --git a/source/blender/bmesh/intern/bmesh_iterators_inline.h b/source/blender/bmesh/intern/bmesh_iterators_inline.h
index 96816521493..faa109617d5 100644
--- a/source/blender/bmesh/intern/bmesh_iterators_inline.h
+++ b/source/blender/bmesh/intern/bmesh_iterators_inline.h
@@ -35,7 +35,7 @@
/**
* \brief Iterator Step
*
- * Calls an iterators step fucntion to return the next element.
+ * Calls an iterators step function to return the next element.
*/
BLI_INLINE void *BM_iter_step(BMIter *iter)
{
@@ -50,7 +50,7 @@ BLI_INLINE void *BM_iter_step(BMIter *iter)
* it with the appropriate function pointers based
* upon its type.
*/
-BLI_INLINE int BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *data)
+BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *data)
{
/* int argtype; */
iter->itype = itype;
@@ -77,105 +77,75 @@ BLI_INLINE int BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *dat
iter->step = bmiter__face_of_mesh_step;
break;
case BM_EDGES_OF_VERT:
- if (UNLIKELY(!data)) {
- return FALSE;
- }
-
+ BLI_assert(data != NULL);
iter->begin = bmiter__edge_of_vert_begin;
iter->step = bmiter__edge_of_vert_step;
- iter->vdata = data;
+ iter->vdata = (BMVert *)data;
break;
case BM_FACES_OF_VERT:
- if (UNLIKELY(!data)) {
- return FALSE;
- }
-
+ BLI_assert(data != NULL);
iter->begin = bmiter__face_of_vert_begin;
iter->step = bmiter__face_of_vert_step;
- iter->vdata = data;
+ iter->vdata = (BMVert *)data;
break;
case BM_LOOPS_OF_VERT:
- if (UNLIKELY(!data)) {
- return FALSE;
- }
-
+ BLI_assert(data != NULL);
iter->begin = bmiter__loop_of_vert_begin;
iter->step = bmiter__loop_of_vert_step;
- iter->vdata = data;
+ iter->vdata = (BMVert *)data;
break;
case BM_VERTS_OF_EDGE:
- if (UNLIKELY(!data)) {
- return FALSE;
- }
-
+ BLI_assert(data != NULL);
iter->begin = bmiter__vert_of_edge_begin;
iter->step = bmiter__vert_of_edge_step;
- iter->edata = data;
+ iter->edata = (BMEdge *)data;
break;
case BM_FACES_OF_EDGE:
- if (UNLIKELY(!data)) {
- return FALSE;
- }
-
+ BLI_assert(data != NULL);
iter->begin = bmiter__face_of_edge_begin;
iter->step = bmiter__face_of_edge_step;
- iter->edata = data;
+ iter->edata = (BMEdge *)data;
break;
case BM_VERTS_OF_FACE:
- if (UNLIKELY(!data)) {
- return FALSE;
- }
-
+ BLI_assert(data != NULL);
iter->begin = bmiter__vert_of_face_begin;
iter->step = bmiter__vert_of_face_step;
- iter->pdata = data;
+ iter->pdata = (BMFace *)data;
break;
case BM_EDGES_OF_FACE:
- if (UNLIKELY(!data)) {
- return FALSE;
- }
-
+ BLI_assert(data != NULL);
iter->begin = bmiter__edge_of_face_begin;
iter->step = bmiter__edge_of_face_step;
- iter->pdata = data;
+ iter->pdata = (BMFace *)data;
break;
case BM_LOOPS_OF_FACE:
- if (UNLIKELY(!data)) {
- return FALSE;
- }
-
+ BLI_assert(data != NULL);
iter->begin = bmiter__loop_of_face_begin;
iter->step = bmiter__loop_of_face_step;
- iter->pdata = data;
+ iter->pdata = (BMFace *)data;
break;
case BM_LOOPS_OF_LOOP:
- if (UNLIKELY(!data)) {
- return FALSE;
- }
-
+ BLI_assert(data != NULL);
iter->begin = bmiter__loops_of_loop_begin;
iter->step = bmiter__loops_of_loop_step;
- iter->ldata = data;
+ iter->ldata = (BMLoop *)data;
break;
case BM_LOOPS_OF_EDGE:
- if (UNLIKELY(!data)) {
- return FALSE;
- }
-
+ BLI_assert(data != NULL);
iter->begin = bmiter__loops_of_edge_begin;
iter->step = bmiter__loops_of_edge_step;
- iter->edata = data;
+ iter->edata = (BMEdge *)data;
break;
default:
/* should never happen */
BLI_assert(0);
- return FALSE;
+ return false;
break;
}
iter->begin(iter);
- return TRUE;
+ return true;
}
/**
diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c
new file mode 100644
index 00000000000..c7be4424a21
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_log.c
@@ -0,0 +1,984 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_mempool.h"
+
+#include "BKE_customdata.h"
+
+#include "bmesh.h"
+#include "bmesh_log.h"
+#include "range_tree_c_api.h"
+
+struct BMLogEntry {
+ struct BMLogEntry *next, *prev;
+
+ /* The following GHashes map from an element ID to one of the log
+ * types above */
+
+ /* Elements that were in the previous entry, but have been
+ * deleted */
+ GHash *deleted_verts;
+ GHash *deleted_faces;
+ /* Elements that were not in the previous entry, but are in the
+ * result of this entry */
+ GHash *added_verts;
+ GHash *added_faces;
+
+ /* Vertices whose coordinates, mask value, or hflag have changed */
+ GHash *modified_verts;
+
+ BLI_mempool *pool_verts;
+ BLI_mempool *pool_faces;
+
+ /* This is only needed for dropping BMLogEntries while still in
+ * dynamic-topology mode, as that should release vert/face IDs
+ * back to the BMLog but no BMLog pointer is available at that
+ * time.
+ *
+ * This field is not guaranteed to be valid, any use of it should
+ * check for NULL. */
+ BMLog *log;
+};
+
+struct BMLog {
+ /* Tree of free IDs */
+ struct RangeTreeUInt *unused_ids;
+
+ /* Mapping from unique IDs to vertices and faces
+ *
+ * Each vertex and face in the log gets a unique unsigned integer
+ * assigned. That ID is taken from the set managed by the
+ * unused_ids range tree.
+ *
+ * The ID is needed because element pointers will change as they
+ * are created and deleted.
+ */
+ GHash *id_to_elem;
+ GHash *elem_to_id;
+
+ /* All BMLogEntrys, ordered from earliest to most recent */
+ ListBase entries;
+
+ /* The current log entry from entries list
+ *
+ * If null, then the original mesh from before any of the log
+ * entries is current (i.e. there is nothing left to undo.)
+ *
+ * If equal to the last entry in the entries list, then all log
+ * entries have been applied (i.e. there is nothing left to redo.)
+ */
+ BMLogEntry *current_entry;
+};
+
+typedef struct {
+ float co[3];
+ float mask;
+ char hflag;
+} BMLogVert;
+
+typedef struct {
+ unsigned int v_ids[3];
+} BMLogFace;
+
+/************************* Get/set element IDs ************************/
+
+/* Get the vertex's unique ID from the log */
+static unsigned int bm_log_vert_id_get(BMLog *log, BMVert *v)
+{
+ BLI_assert(BLI_ghash_haskey(log->elem_to_id, v));
+ return GET_INT_FROM_POINTER(BLI_ghash_lookup(log->elem_to_id, v));
+}
+
+/* Set the vertex's unique ID in the log */
+static void bm_log_vert_id_set(BMLog *log, BMVert *v, unsigned int id)
+{
+ void *vid = SET_INT_IN_POINTER(id);
+
+ BLI_ghash_remove(log->id_to_elem, vid, NULL, NULL);
+ BLI_ghash_insert(log->id_to_elem, vid, v);
+ BLI_ghash_remove(log->elem_to_id, v, NULL, NULL);
+ BLI_ghash_insert(log->elem_to_id, v, vid);
+}
+
+/* Get a vertex from its unique ID */
+static BMVert *bm_log_vert_from_id(BMLog *log, unsigned int id)
+{
+ void *key = SET_INT_IN_POINTER(id);
+ BLI_assert(BLI_ghash_haskey(log->id_to_elem, key));
+ return BLI_ghash_lookup(log->id_to_elem, key);
+}
+
+/* Get the face's unique ID from the log */
+static unsigned int bm_log_face_id_get(BMLog *log, BMFace *f)
+{
+ BLI_assert(BLI_ghash_haskey(log->elem_to_id, f));
+ return GET_INT_FROM_POINTER(BLI_ghash_lookup(log->elem_to_id, f));
+}
+
+/* Set the face's unique ID in the log */
+static void bm_log_face_id_set(BMLog *log, BMFace *f, unsigned int id)
+{
+ void *fid = SET_INT_IN_POINTER(id);
+
+ BLI_ghash_remove(log->id_to_elem, fid, NULL, NULL);
+ BLI_ghash_insert(log->id_to_elem, fid, f);
+ BLI_ghash_remove(log->elem_to_id, f, NULL, NULL);
+ BLI_ghash_insert(log->elem_to_id, f, fid);
+}
+
+/* Get a face from its unique ID */
+static BMFace *bm_log_face_from_id(BMLog *log, unsigned int id)
+{
+ void *key = SET_INT_IN_POINTER(id);
+ BLI_assert(BLI_ghash_haskey(log->id_to_elem, key));
+ return BLI_ghash_lookup(log->id_to_elem, key);
+}
+
+
+/************************ BMLogVert / BMLogFace ***********************/
+
+/* Get a vertex's paint-mask value
+ *
+ * Returns zero if no paint-mask layer is present */
+static float vert_mask_get(BMesh *bm, BMVert *v)
+{
+ float *mask = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_PAINT_MASK);
+ BLI_assert((CustomData_has_layer(&bm->vdata, CD_PAINT_MASK) == 0) == (mask == NULL));
+ if (mask) {
+ return *mask;
+ }
+ else {
+ return 0.0f;
+ }
+}
+
+/* Set a vertex's paint-mask value
+ *
+ * Has no effect is no paint-mask layer is present */
+static void vert_mask_set(BMesh *bm, BMVert *v, float new_mask)
+{
+ float *mask = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_PAINT_MASK);
+ BLI_assert((CustomData_has_layer(&bm->vdata, CD_PAINT_MASK) == 0) == (mask == NULL));
+ if (*mask) {
+ *mask = new_mask;
+ }
+}
+
+/* Update a BMLogVert with data from a BMVert */
+static void bm_log_vert_bmvert_copy(BMesh *bm, BMLogVert *lv, BMVert *v)
+{
+ copy_v3_v3(lv->co, v->co);
+ lv->mask = vert_mask_get(bm, v);
+ lv->hflag = v->head.hflag;
+}
+
+/* Allocate and initialize a BMLogVert */
+static BMLogVert *bm_log_vert_alloc(BMesh *bm, BMLog *log, BMVert *v)
+{
+ BMLogEntry *entry = log->current_entry;
+ BMLogVert *lv = BLI_mempool_alloc(entry->pool_verts);
+
+ bm_log_vert_bmvert_copy(bm, lv, v);
+
+ return lv;
+}
+
+/* Allocate and initialize a BMLogFace */
+static BMLogFace *bm_log_face_alloc(BMLog *log, BMFace *f)
+{
+ BMLogEntry *entry = log->current_entry;
+ BMLogFace *lf = BLI_mempool_alloc(entry->pool_faces);
+ BMVert *v[3];
+
+ BLI_assert(f->len == 3);
+
+ // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3);
+ BM_face_as_array_vert_tri(f, v);
+
+ lf->v_ids[0] = bm_log_vert_id_get(log, v[0]);
+ lf->v_ids[1] = bm_log_vert_id_get(log, v[1]);
+ lf->v_ids[2] = bm_log_vert_id_get(log, v[2]);
+
+ return lf;
+}
+
+
+/************************ Helpers for undo/redo ***********************/
+
+static void bm_log_verts_unmake(BMesh *bm, BMLog *log, GHash *verts)
+{
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, verts) {
+ void *key = BLI_ghashIterator_getKey(&gh_iter);
+ BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter);
+ unsigned int id = GET_INT_FROM_POINTER(key);
+ BMVert *v = bm_log_vert_from_id(log, id);
+
+ /* Ensure the log has the final values of the vertex before
+ * deleting it */
+ bm_log_vert_bmvert_copy(bm, lv, v);
+
+ BM_vert_kill(bm, v);
+ }
+}
+
+static void bm_log_faces_unmake(BMesh *bm, BMLog *log, GHash *faces)
+{
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, faces) {
+ void *key = BLI_ghashIterator_getKey(&gh_iter);
+ unsigned int id = GET_INT_FROM_POINTER(key);
+ BMFace *f = bm_log_face_from_id(log, id);
+ BMEdge *e_tri[3];
+ BMLoop *l_iter;
+ int i;
+
+ l_iter = BM_FACE_FIRST_LOOP(f);
+ for (i = 0; i < 3; i++, l_iter = l_iter->next) {
+ e_tri[i] = l_iter->e;
+ }
+
+ /* Remove any unused edges */
+ BM_face_kill(bm, f);
+ for (i = 0; i < 3; i++) {
+ if (BM_edge_is_wire(e_tri[i])) {
+ BM_edge_kill(bm, e_tri[i]);
+ }
+ }
+ }
+}
+
+static void bm_log_verts_restore(BMesh *bm, BMLog *log, GHash *verts)
+{
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, verts) {
+ void *key = BLI_ghashIterator_getKey(&gh_iter);
+ BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter);
+ BMVert *v = BM_vert_create(bm, lv->co, NULL, 0);
+ v->head.hflag = lv->hflag;
+ vert_mask_set(bm, v, lv->mask);
+ bm_log_vert_id_set(log, v, GET_INT_FROM_POINTER(key));
+ }
+}
+
+static void bm_log_faces_restore(BMesh *bm, BMLog *log, GHash *faces)
+{
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, faces) {
+ void *key = BLI_ghashIterator_getKey(&gh_iter);
+ BMLogFace *lf = BLI_ghashIterator_getValue(&gh_iter);
+ BMVert *v[3] = {bm_log_vert_from_id(log, lf->v_ids[0]),
+ bm_log_vert_from_id(log, lf->v_ids[1]),
+ bm_log_vert_from_id(log, lf->v_ids[2])};
+ BMFace *f;
+
+ f = BM_face_create_quad_tri_v(bm, v, 3, NULL, false);
+ bm_log_face_id_set(log, f, GET_INT_FROM_POINTER(key));
+ }
+}
+
+static void bm_log_vert_values_swap(BMesh *bm, BMLog *log, GHash *verts)
+{
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, verts) {
+ void *key = BLI_ghashIterator_getKey(&gh_iter);
+ BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter);
+ unsigned int id = GET_INT_FROM_POINTER(key);
+ BMVert *v = bm_log_vert_from_id(log, id);
+ float mask;
+
+ swap_v3_v3(v->co, lv->co);
+ SWAP(char, v->head.hflag, lv->hflag);
+ mask = lv->mask;
+ lv->mask = vert_mask_get(bm, v);
+ vert_mask_set(bm, v, mask);
+ }
+}
+
+
+/**********************************************************************/
+
+/* Assign unique IDs to all vertices and faces already in the BMesh */
+static void bm_log_assign_ids(BMesh *bm, BMLog *log)
+{
+ BMIter iter;
+ BMVert *v;
+ BMFace *f;
+
+ /* Generate vertex IDs */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ unsigned int id = range_tree_uint_take_any(log->unused_ids);
+ bm_log_vert_id_set(log, v, id);
+ }
+
+ /* Generate face IDs */
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ unsigned int id = range_tree_uint_take_any(log->unused_ids);
+ bm_log_face_id_set(log, f, id);
+ }
+}
+
+/* Allocate an empty log entry */
+static BMLogEntry *bm_log_entry_create(void)
+{
+ BMLogEntry *entry = MEM_callocN(sizeof(BMLogEntry), AT);
+
+ entry->deleted_verts = BLI_ghash_ptr_new(AT);
+ entry->deleted_faces = BLI_ghash_ptr_new(AT);
+ entry->added_verts = BLI_ghash_ptr_new(AT);
+ entry->added_faces = BLI_ghash_ptr_new(AT);
+ entry->modified_verts = BLI_ghash_ptr_new(AT);
+
+ entry->pool_verts = BLI_mempool_create(sizeof(BMLogVert), 1, 64, 0);
+ entry->pool_faces = BLI_mempool_create(sizeof(BMLogFace), 1, 64, 0);
+
+ return entry;
+}
+
+/* Free the data in a log entry
+ *
+ * Note: does not free the log entry itself */
+static void bm_log_entry_free(BMLogEntry *entry)
+{
+ BLI_ghash_free(entry->deleted_verts, NULL, NULL);
+ BLI_ghash_free(entry->deleted_faces, NULL, NULL);
+ BLI_ghash_free(entry->added_verts, NULL, NULL);
+ BLI_ghash_free(entry->added_faces, NULL, NULL);
+ BLI_ghash_free(entry->modified_verts, NULL, NULL);
+
+ BLI_mempool_destroy(entry->pool_verts);
+ BLI_mempool_destroy(entry->pool_faces);
+}
+
+static void bm_log_id_ghash_retake(RangeTreeUInt *unused_ids, GHash *id_ghash)
+{
+ GHashIterator gh_iter;
+
+ GHASH_ITER (gh_iter, id_ghash) {
+ void *key = BLI_ghashIterator_getKey(&gh_iter);
+ unsigned int id = GET_INT_FROM_POINTER(key);
+
+ if (range_tree_uint_has(unused_ids, id)) {
+ range_tree_uint_take(unused_ids, id);
+ }
+ }
+}
+
+static int uint_compare(const void *a_v, const void *b_v)
+{
+ const unsigned int *a = a_v;
+ const unsigned int *b = b_v;
+ return (*a) < (*b);
+}
+
+/* Remap IDs to contiguous indices
+ *
+ * E.g. if the vertex IDs are (4, 1, 10, 3), the mapping will be:
+ * 4 -> 2
+ * 1 -> 0
+ * 10 -> 3
+ * 3 -> 1
+ */
+static GHash *bm_log_compress_ids_to_indices(unsigned int *ids, int totid)
+{
+ GHash *map = BLI_ghash_int_new(AT);
+ int i;
+
+ qsort(ids, totid, sizeof(*ids), uint_compare);
+
+ for (i = 0; i < totid; i++) {
+ void *key = SET_INT_IN_POINTER(ids[i]);
+ void *val = SET_INT_IN_POINTER(i);
+ BLI_ghash_insert(map, key, val);
+ }
+
+ return map;
+}
+
+/* Release all ID keys in id_ghash */
+static void bm_log_id_ghash_release(BMLog *log, GHash *id_ghash)
+{
+ GHashIterator gh_iter;
+
+ GHASH_ITER (gh_iter, id_ghash) {
+ void *key = BLI_ghashIterator_getKey(&gh_iter);
+ unsigned int id = GET_INT_FROM_POINTER(key);
+ range_tree_uint_release(log->unused_ids, id);
+ }
+}
+
+/***************************** Public API *****************************/
+
+/* Allocate, initialize, and assign a new BMLog */
+BMLog *BM_log_create(BMesh *bm)
+{
+ BMLog *log = MEM_callocN(sizeof(*log), AT);
+
+ log->unused_ids = range_tree_uint_alloc(0, (unsigned)-1);
+ log->id_to_elem = BLI_ghash_ptr_new(AT);
+ log->elem_to_id = BLI_ghash_ptr_new(AT);
+
+ /* Assign IDs to all existing vertices and faces */
+ bm_log_assign_ids(bm, log);
+
+ return log;
+}
+
+/* Allocate and initialize a new BMLog using existing BMLogEntries
+ *
+ * The 'entry' should be the last entry in the BMLog. Its prev pointer
+ * will be followed back to find the first entry.
+ *
+ * The unused IDs field of the log will be initialized by taking all
+ * keys from all GHashes in the log entry.
+ */
+BMLog *BM_log_from_existing_entries_create(BMesh *bm, BMLogEntry *entry)
+{
+ BMLog *log = BM_log_create(bm);
+
+ if (entry->prev)
+ log->current_entry = entry;
+ else
+ log->current_entry = NULL;
+
+ /* Let BMLog manage the entry list again */
+ log->entries.first = log->entries.last = entry;
+
+ {
+ while (entry->prev) {
+ entry = entry->prev;
+ log->entries.first = entry;
+ }
+ entry = log->entries.last;
+ while (entry->next) {
+ entry = entry->next;
+ log->entries.last = entry;
+ }
+ }
+
+ for (entry = log->entries.first; entry; entry = entry->next) {
+ entry->log = log;
+
+ /* Take all used IDs */
+ bm_log_id_ghash_retake(log->unused_ids, entry->deleted_verts);
+ bm_log_id_ghash_retake(log->unused_ids, entry->deleted_faces);
+ bm_log_id_ghash_retake(log->unused_ids, entry->added_verts);
+ bm_log_id_ghash_retake(log->unused_ids, entry->added_faces);
+ bm_log_id_ghash_retake(log->unused_ids, entry->modified_verts);
+ }
+
+ return log;
+}
+
+/* Free all the data in a BMLog including the log itself */
+void BM_log_free(BMLog *log)
+{
+ BMLogEntry *entry;
+
+ if (log->unused_ids)
+ range_tree_uint_free(log->unused_ids);
+
+ if (log->id_to_elem)
+ BLI_ghash_free(log->id_to_elem, NULL, NULL);
+
+ if (log->elem_to_id)
+ BLI_ghash_free(log->elem_to_id, NULL, NULL);
+
+ /* Clear the BMLog references within each entry, but do not free
+ * the entries themselves */
+ for (entry = log->entries.first; entry; entry = entry->next)
+ entry->log = NULL;
+
+ MEM_freeN(log);
+}
+
+/* Get the number of log entries */
+int BM_log_length(const BMLog *log)
+{
+ return BLI_countlist(&log->entries);
+}
+
+/* Apply a consistent ordering to BMesh vertices */
+void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log)
+{
+ void *varr;
+ void *farr;
+
+ GHash *id_to_idx;
+
+ BMIter bm_iter;
+ BMVert *v;
+ BMFace *f;
+
+ int i;
+
+ /* Put all vertex IDs into an array */
+ i = 0;
+ varr = MEM_mallocN(sizeof(int) * bm->totvert, AT);
+ BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) {
+ ((unsigned int *)varr)[i++] = bm_log_vert_id_get(log, v);
+ }
+
+ /* Put all face IDs into an array */
+ i = 0;
+ farr = MEM_mallocN(sizeof(int) * bm->totface, AT);
+ BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) {
+ ((unsigned int *)farr)[i++] = bm_log_face_id_get(log, f);
+ }
+
+ /* Create BMVert index remap array */
+ id_to_idx = bm_log_compress_ids_to_indices(varr, bm->totvert);
+ i = 0;
+ BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) {
+ const unsigned id = bm_log_vert_id_get(log, v);
+ const void *key = SET_INT_IN_POINTER(id);
+ const void *val = BLI_ghash_lookup(id_to_idx, key);
+ ((int *)varr)[i++] = GET_INT_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, bm->totface);
+ i = 0;
+ BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) {
+ const unsigned id = bm_log_face_id_get(log, f);
+ const void *key = SET_INT_IN_POINTER(id);
+ const void *val = BLI_ghash_lookup(id_to_idx, key);
+ ((int *)farr)[i++] = GET_INT_FROM_POINTER(val);
+ }
+ BLI_ghash_free(id_to_idx, NULL, NULL);
+
+ BM_mesh_remap(bm, varr, NULL, farr);
+
+ MEM_freeN(varr);
+ MEM_freeN(farr);
+}
+
+/* Start a new log entry and update the log entry list
+ *
+ * If the log entry list is empty, or if the current log entry is the
+ * last entry, the new entry is simply appended to the end.
+ *
+ * Otherwise, the new entry is added after the current entry and all
+ * following entries are deleted.
+ *
+ * In either case, the new entry is set as the current log entry.
+ */
+BMLogEntry *BM_log_entry_add(BMLog *log)
+{
+ BMLogEntry *entry, *next;
+
+ /* Delete any entries after the current one */
+ entry = log->current_entry;
+ if (entry) {
+ for (entry = entry->next; entry; entry = next) {
+ next = entry->next;
+ bm_log_entry_free(entry);
+ BLI_freelinkN(&log->entries, entry);
+ }
+ }
+
+ /* Create and append the new entry */
+ entry = bm_log_entry_create();
+ BLI_addtail(&log->entries, entry);
+ entry->log = log;
+ log->current_entry = entry;
+
+ return entry;
+}
+
+/* Remove an entry from the log
+ *
+ * Uses entry->log as the log. If the log is NULL, the entry will be
+ * free'd but not removed from any list, nor shall its IDs be
+ * released.
+ *
+ * This operation is only valid on the first and last entries in the
+ * log. Deleting from the middle will assert.
+ */
+void BM_log_entry_drop(BMLogEntry *entry)
+{
+ BMLog *log = entry->log;
+
+ if (!log) {
+ /* Unlink */
+ BLI_assert(!(entry->prev && entry->next));
+ if (entry->prev)
+ entry->prev->next = NULL;
+ else if (entry->next)
+ entry->next->prev = NULL;
+
+ bm_log_entry_free(entry);
+ MEM_freeN(entry);
+ return;
+ }
+
+ if (!entry->prev) {
+ /* Release IDs of elements that are deleted by this
+ * entry. Since the entry is at the beginning of the undo
+ * stack, and it's being deleted, those elements can never be
+ * restored. Their IDs can go back into the pool. */
+ bm_log_id_ghash_release(log, entry->deleted_faces);
+ bm_log_id_ghash_release(log, entry->deleted_verts);
+ }
+ else if (!entry->next) {
+ /* Release IDs of elements that are added by this entry. Since
+ * the entry is at the end of the undo stack, and it's being
+ * deleted, those elements can never be restored. Their IDs
+ * can go back into the pool. */
+ bm_log_id_ghash_release(log, entry->added_faces);
+ bm_log_id_ghash_release(log, entry->added_verts);
+ }
+ else {
+ BLI_assert(!"Cannot drop BMLogEntry from middle");
+ }
+
+ if (log->current_entry == entry)
+ log->current_entry = entry->prev;
+
+ bm_log_entry_free(entry);
+ BLI_freelinkN(&log->entries, entry);
+}
+
+/* Undo one BMLogEntry
+ *
+ * Has no effect if there's nothing left to undo */
+void BM_log_undo(BMesh *bm, BMLog *log)
+{
+ BMLogEntry *entry = log->current_entry;
+
+ if (entry) {
+ log->current_entry = entry->prev;
+
+ /* Delete added faces and verts */
+ bm_log_faces_unmake(bm, log, entry->added_faces);
+ bm_log_verts_unmake(bm, log, entry->added_verts);
+
+ /* Restore deleted verts and faces */
+ bm_log_verts_restore(bm, log, entry->deleted_verts);
+ bm_log_faces_restore(bm, log, entry->deleted_faces);
+
+ /* Restore vertex coordinates, mask, and hflag */
+ bm_log_vert_values_swap(bm, log, entry->modified_verts);
+ }
+}
+
+/* Redo one BMLogEntry
+ *
+ * Has no effect if there's nothing left to redo */
+void BM_log_redo(BMesh *bm, BMLog *log)
+{
+ BMLogEntry *entry = log->current_entry;
+
+ if (!entry) {
+ /* Currently at the beginning of the undo stack, move to first entry */
+ entry = log->entries.first;
+ }
+ else if (entry && entry->next) {
+ /* Move to next undo entry */
+ entry = entry->next;
+ }
+ else {
+ /* Currently at the end of the undo stack, nothing left to redo */
+ return;
+ }
+
+ log->current_entry = entry;
+
+ if (entry) {
+ /* Re-delete previously deleted faces and verts */
+ bm_log_faces_unmake(bm, log, entry->deleted_faces);
+ bm_log_verts_unmake(bm, log, entry->deleted_verts);
+
+ /* Restore previously added verts and faces */
+ bm_log_verts_restore(bm, log, entry->added_verts);
+ bm_log_faces_restore(bm, log, entry->added_faces);
+
+ /* Restore vertex coordinates, mask, and hflag */
+ bm_log_vert_values_swap(bm, log, entry->modified_verts);
+ }
+}
+
+/* Log a vertex before it is modified
+ *
+ * Before modifying vertex coordinates, masks, or hflags, call this
+ * function to log it's current values. This is better than logging
+ * after the coordinates have been modified, because only those
+ * vertices that are modified need to have their original values
+ * stored.
+ *
+ * Handles two separate cases:
+ *
+ * If the vertex was added in the current log entry, update the
+ * vertex in the map of added vertices.
+ *
+ * If the vertex already existed prior to the current log entry, a
+ * separate key/value map of modified vertices is used (using the
+ * vertex's ID as the key). The values stored in that case are
+ * the vertex's original state so that an undo can restore the
+ * previous state.
+ *
+ * On undo, the current vertex state will be swapped with the stored
+ * state so that a subsequent redo operation will restore the newer
+ * vertex state.
+ */
+void BM_log_vert_before_modified(BMesh *bm, BMLog *log, BMVert *v)
+{
+ BMLogEntry *entry = log->current_entry;
+ BMLogVert *lv;
+ unsigned int v_id = bm_log_vert_id_get(log, v);
+ void *key = SET_INT_IN_POINTER(v_id);
+
+ /* Find or create the BMLogVert entry */
+ if ((lv = BLI_ghash_lookup(entry->added_verts, key))) {
+ bm_log_vert_bmvert_copy(bm, lv, v);
+ }
+ else if (!BLI_ghash_haskey(entry->modified_verts, key)) {
+ lv = bm_log_vert_alloc(bm, log, v);
+ BLI_ghash_insert(entry->modified_verts, key, lv);
+ }
+}
+
+/* Log a new vertex as added to the BMesh
+ *
+ * The new vertex gets a unique ID assigned. It is then added to a map
+ * of added vertices, with the key being its ID and the value
+ * containing everything needed to reconstruct that vertex.
+ */
+void BM_log_vert_added(BMesh *bm, BMLog *log, BMVert *v)
+{
+ BMLogVert *lv;
+ unsigned int v_id = range_tree_uint_take_any(log->unused_ids);
+ void *key = SET_INT_IN_POINTER(v_id);
+
+ bm_log_vert_id_set(log, v, v_id);
+ lv = bm_log_vert_alloc(bm, log, v);
+ BLI_ghash_insert(log->current_entry->added_verts, key, lv);
+}
+
+/* Log a new face as added to the BMesh
+ *
+ * The new face gets a unique ID assigned. It is then added to a map
+ * of added faces, with the key being its ID and the value containing
+ * everything needed to reconstruct that face.
+ */
+void BM_log_face_added(BMLog *log, BMFace *f)
+{
+ BMLogFace *lf;
+ unsigned int f_id = range_tree_uint_take_any(log->unused_ids);
+ void *key = SET_INT_IN_POINTER(f_id);
+
+ /* Only triangles are supported for now */
+ BLI_assert(f->len == 3);
+
+ bm_log_face_id_set(log, f, f_id);
+ lf = bm_log_face_alloc(log, f);
+ BLI_ghash_insert(log->current_entry->added_faces, key, lf);
+}
+
+/* Log a vertex as removed from the BMesh
+ *
+ * A couple things can happen here:
+ *
+ * If the vertex was added as part of the current log entry, then it's
+ * deleted and forgotten about entirely. Its unique ID is returned to
+ * the unused pool.
+ *
+ * If the vertex was already part of the BMesh before the current log
+ * entry, it is added to a map of deleted vertices, with the key being
+ * its ID and the value containing everything needed to reconstruct
+ * that vertex.
+ *
+ * If there's a move record for the vertex, that's used as the
+ * vertices original location, then the move record is deleted.
+ */
+void BM_log_vert_removed(BMesh *bm, BMLog *log, BMVert *v)
+{
+ BMLogEntry *entry = log->current_entry;
+ unsigned int v_id = bm_log_vert_id_get(log, v);
+ void *key = SET_INT_IN_POINTER(v_id);
+
+ /* if it has a key, it shouldn't be NULL */
+ BLI_assert(!!BLI_ghash_lookup(entry->added_verts, key) ==
+ !!BLI_ghash_haskey(entry->added_verts, key));
+
+ if (BLI_ghash_remove(entry->added_verts, key, NULL, NULL)) {
+ range_tree_uint_release(log->unused_ids, v_id);
+ }
+ else {
+ BMLogVert *lv, *lv_mod;
+
+ lv = bm_log_vert_alloc(bm, log, v);
+ BLI_ghash_insert(entry->deleted_verts, key, lv);
+
+ /* If the vertex was modified before deletion, ensure that the
+ * original vertex values are stored */
+ if ((lv_mod = BLI_ghash_lookup(entry->modified_verts, key))) {
+ (*lv) = (*lv_mod);
+ BLI_ghash_remove(entry->modified_verts, key, NULL, NULL);
+ }
+ }
+}
+
+/* Log a face as removed from the BMesh
+ *
+ * A couple things can happen here:
+ *
+ * If the face was added as part of the current log entry, then it's
+ * deleted and forgotten about entirely. Its unique ID is returned to
+ * the unused pool.
+ *
+ * If the face was already part of the BMesh before the current log
+ * entry, it is added to a map of deleted faces, with the key being
+ * its ID and the value containing everything needed to reconstruct
+ * that face.
+ */
+void BM_log_face_removed(BMLog *log, BMFace *f)
+{
+ BMLogEntry *entry = log->current_entry;
+ unsigned int f_id = bm_log_face_id_get(log, f);
+ void *key = SET_INT_IN_POINTER(f_id);
+
+ /* if it has a key, it shouldn't be NULL */
+ BLI_assert(!!BLI_ghash_lookup(entry->added_faces, key) ==
+ !!BLI_ghash_haskey(entry->added_faces, key));
+
+ if (BLI_ghash_remove(entry->added_faces, key, NULL, NULL)) {
+ range_tree_uint_release(log->unused_ids, f_id);
+ }
+ else {
+ BMLogFace *lf;
+
+ lf = bm_log_face_alloc(log, f);
+ BLI_ghash_insert(entry->deleted_faces, key, lf);
+ }
+}
+
+/* Log all vertices/faces in the BMesh as added */
+void BM_log_all_added(BMesh *bm, BMLog *log)
+{
+ BMIter bm_iter;
+ BMVert *v;
+ BMFace *f;
+
+ /* Log all vertices as newly created */
+ BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) {
+ BM_log_vert_added(bm, log, v);
+ }
+
+ /* Log all faces as newly created */
+ BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) {
+ BM_log_face_added(log, f);
+ }
+}
+
+/* Log all vertices/faces in the BMesh as removed */
+void BM_log_before_all_removed(BMesh *bm, BMLog *log)
+{
+ BMIter bm_iter;
+ BMVert *v;
+ BMFace *f;
+
+ /* Log deletion of all faces */
+ BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) {
+ BM_log_face_removed(log, f);
+ }
+
+ /* Log deletion of all vertices */
+ BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) {
+ BM_log_vert_removed(bm, log, v);
+ }
+}
+
+/* Get the logged coordinates of a vertex
+ *
+ * Does not modify the log or the vertex */
+const float *BM_log_original_vert_co(BMLog *log, BMVert *v)
+{
+ BMLogEntry *entry = log->current_entry;
+ const BMLogVert *lv;
+ unsigned v_id = bm_log_vert_id_get(log, v);
+ void *key = SET_INT_IN_POINTER(v_id);
+
+ BLI_assert(entry);
+
+ BLI_assert(BLI_ghash_haskey(entry->modified_verts, key));
+
+ lv = BLI_ghash_lookup(entry->modified_verts, key);
+ return lv->co;
+}
+
+/* Get the logged mask of a vertex
+ *
+ * Does not modify the log or the vertex */
+float BM_log_original_mask(BMLog *log, BMVert *v)
+{
+ BMLogEntry *entry = log->current_entry;
+ const BMLogVert *lv;
+ unsigned v_id = bm_log_vert_id_get(log, v);
+ void *key = SET_INT_IN_POINTER(v_id);
+
+ BLI_assert(entry);
+
+ BLI_assert(BLI_ghash_haskey(entry->modified_verts, key));
+
+ lv = BLI_ghash_lookup(entry->modified_verts, key);
+ return lv->mask;
+}
+
+/************************ Debugging and Testing ***********************/
+
+/* For internal use only (unit testing) */
+BMLogEntry *BM_log_current_entry(BMLog *log)
+{
+ return log->current_entry;
+}
+
+/* For internal use only (unit testing) */
+RangeTreeUInt *BM_log_unused_ids(BMLog *log)
+{
+ return log->unused_ids;
+}
+
+#if 0
+/* Print the list of entries, marking the current one
+ *
+ * Keep around for debugging */
+void bm_log_print(const BMLog *log, const char *description)
+{
+ const BMLogEntry *entry;
+ const char *current = " <-- current";
+ int i;
+
+ printf("%s:\n", description);
+ printf(" % 2d: [ initial ]%s\n", 0,
+ (!log->current_entry) ? current : "");
+ for (entry = log->entries.first, i = 1; entry; entry = entry->next, i++) {
+ printf(" % 2d: [%p]%s\n", i, entry,
+ (entry == log->current_entry) ? current : "");
+ }
+}
+#endif
diff --git a/source/blender/bmesh/intern/bmesh_log.h b/source/blender/bmesh/intern/bmesh_log.h
new file mode 100644
index 00000000000..958ff340b43
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_log.h
@@ -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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BMESH_LOG_H__
+#define __BMESH_LOG_H__
+
+/* The BMLog is an interface for storing undo/redo steps as a BMesh is
+ * modified. It only stores changes to the BMesh, not full copies.
+ *
+ * Currently it supports the following types of changes:
+ *
+ * - Adding and removing vertices
+ * - Adding and removing faces
+ * - Moving vertices
+ * - Setting vertex paint-mask values
+ * - Setting vertex hflags
+ */
+
+struct BMFace;
+struct BMVert;
+struct BMesh;
+struct RangeTreeUInt;
+
+typedef struct BMLog BMLog;
+typedef struct BMLogEntry BMLogEntry;
+
+/* Allocate and initialize a new BMLog */
+BMLog *BM_log_create(BMesh *bm);
+
+/* Allocate and initialize a new BMLog using existing BMLogEntries */
+BMLog *BM_log_from_existing_entries_create(BMesh *bm, BMLogEntry *entry);
+
+/* Free all the data in a BMLog including the log itself */
+void BM_log_free(BMLog *log);
+
+/* Get the number of log entries */
+int BM_log_length(const BMLog *log);
+
+/* Apply a consistent ordering to BMesh vertices and faces */
+void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log);
+
+/* Start a new log entry and update the log entry list */
+BMLogEntry *BM_log_entry_add(BMLog *log);
+
+/* Remove an entry from the log */
+void BM_log_entry_drop(BMLogEntry *entry);
+
+/* Undo one BMLogEntry */
+void BM_log_undo(BMesh *bm, BMLog *log);
+
+/* Redo one BMLogEntry */
+void BM_log_redo(BMesh *bm, BMLog *log);
+
+/* Log a vertex before it is modified */
+void BM_log_vert_before_modified(BMesh *bm, BMLog *log, struct BMVert *v);
+
+/* Log a new vertex as added to the BMesh */
+void BM_log_vert_added(BMesh *bm, BMLog *log, struct BMVert *v);
+
+/* Log a new face as added to the BMesh */
+void BM_log_face_added(BMLog *log, struct BMFace *f);
+
+/* Log a vertex as removed from the BMesh */
+void BM_log_vert_removed(BMesh *bm, BMLog *log, struct BMVert *v);
+
+/* Log a face as removed from the BMesh */
+void BM_log_face_removed(BMLog *log, struct BMFace *f);
+
+/* Log all vertices/faces in the BMesh as added */
+void BM_log_all_added(BMesh *bm, BMLog *log);
+
+/* Log all vertices/faces in the BMesh as removed */
+void BM_log_before_all_removed(BMesh *bm, BMLog *log);
+
+/* Get the logged coordinates of a vertex */
+const float *BM_log_original_vert_co(BMLog *log, BMVert *v);
+
+/* Get the logged mask of a vertex */
+float BM_log_original_mask(BMLog *log, BMVert *v);
+
+/* For internal use only (unit testing) */
+BMLogEntry *BM_log_current_entry(BMLog *log);
+struct RangeTreeUInt *BM_log_unused_ids(BMLog *log);
+
+#endif
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index 9af65d7dd7e..4e29756104a 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -44,8 +44,6 @@
static void recount_totsels(BMesh *bm)
{
- BMIter iter;
- BMElem *ele;
const char iter_types[3] = {BM_VERTS_OF_MESH,
BM_EDGES_OF_MESH,
BM_FACES_OF_MESH};
@@ -58,11 +56,16 @@ static void recount_totsels(BMesh *bm)
tots[1] = &bm->totedgesel;
tots[2] = &bm->totfacesel;
+#pragma omp parallel for schedule(dynamic)
for (i = 0; i < 3; i++) {
- ele = BM_iter_new(&iter, bm, iter_types[i], NULL);
- for ( ; ele; ele = BM_iter_step(&iter)) {
- if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) *tots[i] += 1;
+ BMIter iter;
+ BMElem *ele;
+ int count = 0;
+
+ BM_ITER_MESH (ele, &iter, bm, iter_types[i]) {
+ if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) count += 1;
}
+ *tots[i] = count;
}
}
@@ -83,52 +86,61 @@ void BM_mesh_select_mode_flush_ex(BMesh *bm, const short selectmode)
BMIter eiter;
BMIter fiter;
- int ok;
-
if (selectmode & SCE_SELECT_VERTEX) {
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
- BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
- !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
+ /* both loops only set edge/face flags and read off verts */
+#pragma omp parallel sections if (bm->totedge + bm->totface >= BM_OMP_LIMIT)
+ {
+#pragma omp section
{
- BM_elem_flag_enable(e, BM_ELEM_SELECT);
- }
- else {
- BM_elem_flag_disable(e, BM_ELEM_SELECT);
- }
- }
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- ok = TRUE;
- if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
- ok = FALSE;
- break;
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
+ BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
+ !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
+ {
+ BM_elem_flag_enable(e, BM_ELEM_SELECT);
}
- } while ((l_iter = l_iter->next) != l_first);
- }
- else {
- ok = FALSE;
+ else {
+ BM_elem_flag_disable(e, BM_ELEM_SELECT);
+ }
+ }
}
+#pragma omp section
+ {
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ bool ok = true;
+ if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
+ ok = false;
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ else {
+ ok = false;
+ }
- BM_elem_flag_set(f, BM_ELEM_SELECT, ok);
+ BM_elem_flag_set(f, BM_ELEM_SELECT, ok);
+ }
+ }
}
+ /* end sections */
}
else if (selectmode & SCE_SELECT_EDGE) {
BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- ok = TRUE;
+ bool ok = true;
if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
if (!BM_elem_flag_test(l_iter->e, BM_ELEM_SELECT)) {
- ok = FALSE;
+ ok = false;
break;
}
} while ((l_iter = l_iter->next) != l_first);
}
else {
- ok = FALSE;
+ ok = false;
}
BM_elem_flag_set(f, BM_ELEM_SELECT, ok);
@@ -159,36 +171,47 @@ void BM_mesh_deselect_flush(BMesh *bm)
BMIter eiter;
BMIter fiter;
- int ok;
+ bool ok;
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (!(BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
- BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
- !BM_elem_flag_test(e, BM_ELEM_HIDDEN)))
+ /* we can use 2 sections here because the second loop isnt checking edge selection */
+#pragma omp parallel sections if (bm->totedge + bm->totface >= BM_OMP_LIMIT)
+ {
+#pragma omp section
{
- BM_elem_flag_disable(e, BM_ELEM_SELECT);
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (!(BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
+ BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
+ !BM_elem_flag_test(e, BM_ELEM_HIDDEN)))
+ {
+ BM_elem_flag_disable(e, BM_ELEM_SELECT);
+ }
+ }
}
- }
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- ok = TRUE;
- if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
- ok = FALSE;
- break;
+#pragma omp section
+ {
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ ok = true;
+ if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
+ ok = false;
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ else {
+ ok = false;
}
- } while ((l_iter = l_iter->next) != l_first);
- }
- else {
- ok = FALSE;
- }
- if (ok == FALSE) {
- BM_elem_flag_disable(f, BM_ELEM_SELECT);
+ if (ok == false) {
+ BM_elem_flag_disable(f, BM_ELEM_SELECT);
+ }
+ }
}
}
+ /* end sections */
/* Remove any deselected elements from the BMEditSelection */
BM_select_history_validate(bm);
@@ -210,34 +233,44 @@ void BM_mesh_select_flush(BMesh *bm)
BMIter eiter;
BMIter fiter;
- int ok;
+ bool ok;
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
- BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
- !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
+ /* we can use 2 sections here because the second loop isnt checking edge selection */
+#pragma omp parallel sections if (bm->totedge + bm->totface >= BM_OMP_LIMIT)
+ {
+#pragma omp section
{
- BM_elem_flag_enable(e, BM_ELEM_SELECT);
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
+ BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
+ !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
+ {
+ BM_elem_flag_enable(e, BM_ELEM_SELECT);
+ }
+ }
}
- }
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- ok = TRUE;
- if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
- ok = FALSE;
- break;
+#pragma omp section
+ {
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ ok = true;
+ if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
+ ok = false;
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ else {
+ ok = false;
}
- } while ((l_iter = l_iter->next) != l_first);
- }
- else {
- ok = FALSE;
- }
- if (ok) {
- BM_elem_flag_enable(f, BM_ELEM_SELECT);
+ if (ok) {
+ BM_elem_flag_enable(f, BM_ELEM_SELECT);
+ }
+ }
}
}
@@ -250,7 +283,7 @@ void BM_mesh_select_flush(BMesh *bm)
* Changes selection state of a single vertex
* in a mesh
*/
-void BM_vert_select_set(BMesh *bm, BMVert *v, int select)
+void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select)
{
BLI_assert(v->head.htype == BM_VERT);
@@ -277,7 +310,7 @@ void BM_vert_select_set(BMesh *bm, BMVert *v, int select)
*
* Changes selection state of a single edge in a mesh.
*/
-void BM_edge_select_set(BMesh *bm, BMEdge *e, int select)
+void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select)
{
BLI_assert(e->head.htype == BM_EDGE);
@@ -289,8 +322,8 @@ void BM_edge_select_set(BMesh *bm, BMEdge *e, int select)
if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) bm->totedgesel += 1;
BM_elem_flag_enable(e, BM_ELEM_SELECT);
- BM_vert_select_set(bm, e->v1, TRUE);
- BM_vert_select_set(bm, e->v2, TRUE);
+ 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;
@@ -321,13 +354,13 @@ void BM_edge_select_set(BMesh *bm, BMEdge *e, int select)
}
if (deselect) {
- BM_vert_select_set(bm, verts[i], FALSE);
+ BM_vert_select_set(bm, verts[i], false);
}
}
}
else {
- BM_vert_select_set(bm, e->v1, FALSE);
- BM_vert_select_set(bm, e->v2, FALSE);
+ BM_vert_select_set(bm, e->v1, false);
+ BM_vert_select_set(bm, e->v2, false);
}
}
@@ -339,7 +372,7 @@ void BM_edge_select_set(BMesh *bm, BMEdge *e, int select)
* Changes selection state of a single
* face in a mesh.
*/
-void BM_face_select_set(BMesh *bm, BMFace *f, int select)
+void BM_face_select_set(BMesh *bm, BMFace *f, const bool select)
{
BMLoop *l_iter;
BMLoop *l_first;
@@ -358,8 +391,8 @@ void BM_face_select_set(BMesh *bm, BMFace *f, int select)
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);
- BM_edge_select_set(bm, l_iter->e, TRUE);
+ BM_vert_select_set(bm, l_iter->v, true);
+ BM_edge_select_set(bm, l_iter->e, true);
} while ((l_iter = l_iter->next) != l_first);
}
else {
@@ -379,7 +412,7 @@ void BM_face_select_set(BMesh *bm, BMFace *f, int select)
}
if (!f2) {
- BM_edge_select_set(bm, l->e, FALSE);
+ BM_edge_select_set(bm, l->e, false);
}
}
@@ -393,7 +426,7 @@ void BM_face_select_set(BMesh *bm, BMFace *f, int select)
}
if (!e) {
- BM_vert_select_set(bm, l->v, FALSE);
+ BM_vert_select_set(bm, l->v, false);
}
}
}
@@ -434,7 +467,7 @@ void BM_mesh_select_mode_set(BMesh *bm, int selectmode)
BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
- BM_edge_select_set(bm, (BMEdge *)ele, TRUE);
+ BM_edge_select_set(bm, (BMEdge *)ele, true);
}
}
BM_mesh_select_mode_flush(bm);
@@ -448,7 +481,7 @@ void BM_mesh_select_mode_set(BMesh *bm, int selectmode)
#endif
BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
- BM_face_select_set(bm, (BMFace *)ele, TRUE);
+ BM_face_select_set(bm, (BMFace *)ele, true);
}
}
BM_mesh_select_mode_flush(bm);
@@ -459,14 +492,12 @@ 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 short respecthide, const short test_for_enabled)
+ const short respecthide, const bool test_for_enabled)
{
BMElem *ele;
BMIter iter;
int tot = 0;
- BLI_assert(ELEM(test_for_enabled, TRUE, FALSE));
-
if (htype & BM_VERT) {
for (ele = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); ele; ele = BM_iter_step(&iter)) {
if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) continue;
@@ -489,21 +520,21 @@ static int bm_mesh_flag_count(BMesh *bm, const char htype, const char hflag,
return tot;
}
-int BM_mesh_elem_hflag_count_enabled(BMesh *bm, const char htype, const char hflag, int respecthide)
+int BM_mesh_elem_hflag_count_enabled(BMesh *bm, const char htype, const char hflag, const bool respecthide)
{
- return bm_mesh_flag_count(bm, htype, hflag, respecthide, TRUE);
+ return bm_mesh_flag_count(bm, htype, hflag, respecthide, true);
}
-int BM_mesh_elem_hflag_count_disabled(BMesh *bm, const char htype, const char hflag, int respecthide)
+int BM_mesh_elem_hflag_count_disabled(BMesh *bm, const char htype, const char hflag, const bool respecthide)
{
- return bm_mesh_flag_count(bm, htype, hflag, respecthide, FALSE);
+ return bm_mesh_flag_count(bm, htype, hflag, respecthide, false);
}
/**
* \note use BM_elem_flag_test(ele, BM_ELEM_SELECT) to test selection
* \note by design, this will not touch the editselection history stuff
*/
-void BM_elem_select_set(BMesh *bm, BMElem *ele, int select)
+void BM_elem_select_set(BMesh *bm, BMElem *ele, const bool select)
{
switch (ele->head.htype) {
case BM_VERT:
@@ -527,12 +558,12 @@ void BM_active_face_set(BMesh *bm, BMFace *efa)
bm->act_face = efa;
}
-BMFace *BM_active_face_get(BMesh *bm, int sloppy, int selected)
+BMFace *BM_active_face_get(BMesh *bm, const bool is_sloppy, const bool is_selected)
{
- if (bm->act_face && (!selected || BM_elem_flag_test(bm->act_face, BM_ELEM_SELECT))) {
+ if (bm->act_face && (!is_selected || BM_elem_flag_test(bm->act_face, BM_ELEM_SELECT))) {
return bm->act_face;
}
- else if (sloppy) {
+ else if (is_sloppy) {
BMIter iter;
BMFace *f = NULL;
BMEditSelection *ese;
@@ -546,7 +577,7 @@ BMFace *BM_active_face_get(BMesh *bm, int sloppy, int selected)
if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
f = NULL;
}
- else if (selected && !BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ else if (is_selected && !BM_elem_flag_test(f, BM_ELEM_SELECT)) {
f = NULL;
}
else {
@@ -679,12 +710,13 @@ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3])
cross_v3_v3v3(r_plane, efa->no, vec);
}
else {
- BMVert *verts[4] = {NULL};
-
- BM_iter_as_array(NULL, BM_VERTS_OF_FACE, efa, (void **)verts, 4);
-
if (efa->len == 4) {
+ BMVert *verts[4] = {NULL};
float vecA[3], vecB[3];
+
+ // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, efa, (void **)verts, 4);
+ BM_face_as_array_vert_quad(efa, verts);
+
sub_v3_v3v3(vecA, verts[3]->co, verts[2]->co);
sub_v3_v3v3(vecB, verts[0]->co, verts[1]->co);
add_v3_v3v3(r_plane, vecA, vecB);
@@ -710,20 +742,20 @@ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3])
/* --- macro wrapped funcs --- */
-int _bm_select_history_check(BMesh *bm, const BMHeader *ele)
+bool _bm_select_history_check(BMesh *bm, const BMHeader *ele)
{
return (BLI_findptr(&bm->selected, ele, offsetof(BMEditSelection, ele)) != NULL);
}
-int _bm_select_history_remove(BMesh *bm, BMHeader *ele)
+bool _bm_select_history_remove(BMesh *bm, BMHeader *ele)
{
BMEditSelection *ese = BLI_findptr(&bm->selected, ele, offsetof(BMEditSelection, ele));
if (ese) {
BLI_freelinkN(&bm->selected, ese);
- return TRUE;
+ return true;
}
else {
- return FALSE;
+ return false;
}
}
@@ -767,10 +799,10 @@ void BM_select_history_validate(BMesh *bm)
}
/* utility function */
-int BM_select_history_active_get(BMesh *bm, BMEditSelection *ese)
+bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese)
{
BMEditSelection *ese_last = bm->selected.last;
- BMFace *efa = BM_active_face_get(bm, FALSE, FALSE);
+ BMFace *efa = BM_active_face_get(bm, false, false);
ese->next = ese->prev = NULL;
@@ -795,14 +827,14 @@ int BM_select_history_active_get(BMesh *bm, BMEditSelection *ese)
}
else {
ese->ele = NULL;
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hflag,
- int respecthide, const char hflag_test)
+ const bool respecthide, const char hflag_test)
{
const char iter_types[3] = {BM_VERTS_OF_MESH,
BM_EDGES_OF_MESH,
@@ -810,8 +842,6 @@ void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hfl
const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE};
- BMIter iter;
- BMElem *ele;
int i;
if (hflag & BM_ELEM_SELECT) {
@@ -820,21 +850,30 @@ void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hfl
if ((htype == (BM_VERT | BM_EDGE | BM_FACE)) &&
(hflag == BM_ELEM_SELECT) &&
- (respecthide == FALSE) &&
+ (respecthide == false) &&
(hflag_test == 0))
{
/* fast path for deselect all, avoid topology loops
* since we know all will be de-selected anyway. */
+
+#pragma omp parallel for schedule(dynamic) if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)
for (i = 0; i < 3; i++) {
+ BMIter iter;
+ BMElem *ele;
+
ele = BM_iter_new(&iter, bm, iter_types[i], NULL);
for ( ; ele; ele = BM_iter_step(&iter)) {
BM_elem_flag_disable(ele, BM_ELEM_SELECT);
}
}
+
bm->totvertsel = bm->totedgesel = bm->totfacesel = 0;
}
else {
for (i = 0; i < 3; i++) {
+ BMIter iter;
+ BMElem *ele;
+
if (htype & flag_types[i]) {
ele = BM_iter_new(&iter, bm, iter_types[i], NULL);
for ( ; ele; ele = BM_iter_step(&iter)) {
@@ -847,7 +886,7 @@ void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hfl
}
if (hflag & BM_ELEM_SELECT) {
- BM_elem_select_set(bm, ele, FALSE);
+ BM_elem_select_set(bm, ele, false);
}
BM_elem_flag_disable(ele, hflag);
}
@@ -857,7 +896,7 @@ 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,
- int respecthide, const char hflag_test)
+ const bool respecthide, const char hflag_test)
{
const char iter_types[3] = {BM_VERTS_OF_MESH,
BM_EDGES_OF_MESH,
@@ -895,7 +934,7 @@ void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hfla
}
if (hflag & BM_ELEM_SELECT) {
- BM_elem_select_set(bm, ele, TRUE);
+ BM_elem_select_set(bm, ele, true);
}
BM_elem_flag_enable(ele, hflag_nosel);
}
@@ -904,14 +943,14 @@ 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,
- int respecthide)
+ const bool respecthide)
{
/* call with 0 hflag_test */
BM_mesh_elem_hflag_disable_test(bm, htype, hflag, respecthide, 0);
}
void BM_mesh_elem_hflag_enable_all(BMesh *bm, const char htype, const char hflag,
- int respecthide)
+ const bool respecthide)
{
/* call with 0 hflag_test */
BM_mesh_elem_hflag_enable_test(bm, htype, hflag, respecthide, 0);
@@ -923,7 +962,7 @@ static void vert_flush_hide_set(BMVert *v)
{
BMIter iter;
BMEdge *e;
- int hide = TRUE;
+ bool hide = true;
BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
hide = hide && BM_elem_flag_test(e, BM_ELEM_HIDDEN);
@@ -936,7 +975,7 @@ static void edge_flush_hide(BMEdge *e)
{
BMIter iter;
BMFace *f;
- int hide = TRUE;
+ bool hide = true;
BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
hide = hide && BM_elem_flag_test(f, BM_ELEM_HIDDEN);
@@ -945,13 +984,15 @@ static void edge_flush_hide(BMEdge *e)
BM_elem_flag_set(e, BM_ELEM_HIDDEN, hide);
}
-void BM_vert_hide_set(BMVert *v, int hide)
+void BM_vert_hide_set(BMVert *v, const bool hide)
{
/* vert hiding: vert + surrounding edges and faces */
BMIter iter, fiter;
BMEdge *e;
BMFace *f;
+ BLI_assert(v->head.htype == BM_VERT);
+
BM_elem_flag_set(v, BM_ELEM_HIDDEN, hide);
BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
@@ -963,12 +1004,14 @@ void BM_vert_hide_set(BMVert *v, int hide)
}
}
-void BM_edge_hide_set(BMEdge *e, int hide)
+void BM_edge_hide_set(BMEdge *e, const bool hide)
{
BMIter iter;
BMFace *f;
/* BMVert *v; */
+ BLI_assert(e->head.htype == BM_EDGE);
+
/* edge hiding: faces around the edge */
BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
BM_elem_flag_set(f, BM_ELEM_HIDDEN, hide);
@@ -981,11 +1024,13 @@ void BM_edge_hide_set(BMEdge *e, int hide)
vert_flush_hide_set(e->v2);
}
-void BM_face_hide_set(BMFace *f, int hide)
+void BM_face_hide_set(BMFace *f, const bool hide)
{
BMIter iter;
BMLoop *l;
+ BLI_assert(f->head.htype == BM_FACE);
+
BM_elem_flag_set(f, BM_ELEM_HIDDEN, hide);
BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
@@ -997,21 +1042,21 @@ void BM_face_hide_set(BMFace *f, int hide)
}
}
-void _bm_elem_hide_set(BMesh *bm, BMHeader *head, int hide)
+void _bm_elem_hide_set(BMesh *bm, BMHeader *head, const bool hide)
{
/* Follow convention of always deselecting before
* hiding an element */
switch (head->htype) {
case BM_VERT:
- if (hide) BM_vert_select_set(bm, (BMVert *)head, FALSE);
+ if (hide) BM_vert_select_set(bm, (BMVert *)head, false);
BM_vert_hide_set((BMVert *)head, hide);
break;
case BM_EDGE:
- if (hide) BM_edge_select_set(bm, (BMEdge *)head, FALSE);
+ if (hide) BM_edge_select_set(bm, (BMEdge *)head, false);
BM_edge_hide_set((BMEdge *)head, hide);
break;
case BM_FACE:
- if (hide) BM_face_select_set(bm, (BMFace *)head, FALSE);
+ if (hide) BM_face_select_set(bm, (BMFace *)head, false);
BM_face_hide_set((BMFace *)head, hide);
break;
default:
diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h
index 8d4397794d5..a3d2d4a6985 100644
--- a/source/blender/bmesh/intern/bmesh_marking.h
+++ b/source/blender/bmesh/intern/bmesh_marking.h
@@ -35,29 +35,29 @@ typedef struct BMEditSelection {
/* geometry hiding code */
#define BM_elem_hide_set(bm, ele, hide) _bm_elem_hide_set(bm, &(ele)->head, hide)
-void _bm_elem_hide_set(BMesh *bm, BMHeader *ele, int hide);
-void BM_vert_hide_set(BMVert *v, int hide);
-void BM_edge_hide_set(BMEdge *e, int hide);
-void BM_face_hide_set(BMFace *f, int hide);
+void _bm_elem_hide_set(BMesh *bm, BMHeader *ele, const bool hide);
+void BM_vert_hide_set(BMVert *v, const bool hide);
+void BM_edge_hide_set(BMEdge *e, const bool hide);
+void BM_face_hide_set(BMFace *f, const bool hide);
/* Selection code */
-void BM_elem_select_set(BMesh *bm, BMElem *ele, int select);
+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,
- int respecthide, const char hflag_test);
+ const bool respecthide, const char hflag_test);
void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hflag,
- int respecthide, const char hflag_test);
+ const bool respecthide, const char hflag_test);
void BM_mesh_elem_hflag_enable_all(BMesh *bm, const char htype, const char hflag,
- int respecthide);
+ const bool respecthide);
void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag,
- int respecthide);
+ const bool respecthide);
/* individual element select functions, BM_elem_select_set is a shortcut for these
* that automatically detects which one to use*/
-void BM_vert_select_set(BMesh *bm, BMVert *v, int select);
-void BM_edge_select_set(BMesh *bm, BMEdge *e, int select);
-void BM_face_select_set(BMesh *bm, BMFace *f, int select);
+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);
void BM_mesh_select_mode_set(BMesh *bm, int selectmode);
void BM_mesh_select_mode_flush_ex(BMesh *bm, const short selectmode);
@@ -66,12 +66,12 @@ void BM_mesh_select_mode_flush(BMesh *bm);
void BM_mesh_deselect_flush(BMesh *bm);
void BM_mesh_select_flush(BMesh *bm);
-int BM_mesh_elem_hflag_count_enabled(BMesh *bm, const char htype, const char hflag, int respecthide);
-int BM_mesh_elem_hflag_count_disabled(BMesh *bm, const char htype, const char hflag, int respecthide);
+int BM_mesh_elem_hflag_count_enabled(BMesh *bm, const char htype, const char hflag, const bool respecthide);
+int BM_mesh_elem_hflag_count_disabled(BMesh *bm, const char htype, const char hflag, const bool respecthide);
/* edit selection stuff */
void BM_active_face_set(BMesh *bm, BMFace *f);
-BMFace *BM_active_face_get(BMesh *bm, int sloppy, int selected);
+BMFace *BM_active_face_get(BMesh *bm, const bool is_sloppy, const bool is_selected);
void BM_editselection_center(BMEditSelection *ese, float r_center[3]);
void BM_editselection_normal(BMEditSelection *ese, float r_normal[3]);
@@ -82,13 +82,13 @@ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3]);
#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)
-int _bm_select_history_check(BMesh *bm, const BMHeader *ele);
-int _bm_select_history_remove(BMesh *bm, BMHeader *ele);
+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_validate(BMesh *bm);
void BM_select_history_clear(BMesh *em);
-int BM_select_history_active_get(BMesh *bm, struct BMEditSelection *ese);
+bool BM_select_history_active_get(BMesh *bm, struct BMEditSelection *ese);
#endif /* __BMESH_MARKING_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index 590edc45d07..55a22fd3613 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -63,40 +63,62 @@ static void bm_mempool_init(BMesh *bm, const BMAllocTemplate *allocsize)
void BM_mesh_elem_toolflags_ensure(BMesh *bm)
{
- if (bm->toolflagpool == NULL) {
- const int totflagpool_size = max_ii(512, bm->totvert + bm->totedge + bm->totface);
- BLI_mempool *toolflagpool;
-
- BMIter iter;
- BMElemF *ele;
- const char iter_types[3] = {BM_VERTS_OF_MESH,
- BM_EDGES_OF_MESH,
- BM_FACES_OF_MESH};
-
- int i;
-
- BLI_assert(bm->totflags == 0);
-
- /* allocate one flag pool that we don't get rid of. */
- toolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), totflagpool_size, 512, 0);
-
+ if (bm->vtoolflagpool && bm->etoolflagpool && bm->ftoolflagpool) {
+ return;
+ }
- for (i = 0; i < 3; i++) {
- BM_ITER_MESH (ele, &iter, bm, iter_types[i]) {
+ bm->vtoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), max_ii(512, bm->totvert), 512, 0);
+ bm->etoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), max_ii(512, bm->totedge), 512, 0);
+ bm->ftoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), max_ii(512, bm->totface), 512, 0);
+
+#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)
+ {
+#pragma omp section
+ {
+ BLI_mempool *toolflagpool = bm->vtoolflagpool;
+ BMIter iter;
+ BMElemF *ele;
+ BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
+ ele->oflags = BLI_mempool_calloc(toolflagpool);
+ }
+ }
+#pragma omp section
+ {
+ BLI_mempool *toolflagpool = bm->etoolflagpool;
+ BMIter iter;
+ BMElemF *ele;
+ BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
+ ele->oflags = BLI_mempool_calloc(toolflagpool);
+ }
+ }
+#pragma omp section
+ {
+ BLI_mempool *toolflagpool = bm->ftoolflagpool;
+ BMIter iter;
+ BMElemF *ele;
+ BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
ele->oflags = BLI_mempool_calloc(toolflagpool);
}
}
-
- bm->toolflagpool = toolflagpool;
- bm->totflags = 1;
}
+
+
+ bm->totflags = 1;
}
void BM_mesh_elem_toolflags_clear(BMesh *bm)
{
- if (bm->toolflagpool) {
- BLI_mempool_destroy(bm->toolflagpool);
- bm->toolflagpool = NULL;
+ if (bm->vtoolflagpool) {
+ BLI_mempool_destroy(bm->vtoolflagpool);
+ bm->vtoolflagpool = NULL;
+ }
+ if (bm->etoolflagpool) {
+ BLI_mempool_destroy(bm->etoolflagpool);
+ bm->etoolflagpool = NULL;
+ }
+ if (bm->ftoolflagpool) {
+ BLI_mempool_destroy(bm->ftoolflagpool);
+ bm->ftoolflagpool = NULL;
}
}
@@ -223,10 +245,8 @@ void BM_mesh_free(BMesh *bm)
BM_mesh_data_free(bm);
if (bm->py_handle) {
- /* keep this out of 'BM_mesh_data_free' because we wan't python
+ /* keep this out of 'BM_mesh_data_free' because we want python
* to be able to clear the mesh and maintain access. */
- extern void bpy_bm_generic_invalidate(void *self);
-
bpy_bm_generic_invalidate(bm->py_handle);
bm->py_handle = NULL;
}
@@ -239,7 +259,7 @@ void BM_mesh_free(BMesh *bm)
*
* Updates the normals of a mesh.
*/
-void BM_mesh_normals_update(BMesh *bm, const short skip_hidden)
+void BM_mesh_normals_update(BMesh *bm, const bool skip_hidden)
{
BMVert *v;
BMFace *f;
@@ -340,8 +360,8 @@ static void UNUSED_FUNCTION(bm_mdisps_space_set)(Object *ob, BMesh *bm, int from
{
/* switch multires data out of tangent space */
if (CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
- BMEditMesh *em = BMEdit_Create(bm, FALSE);
- DerivedMesh *dm = CDDM_from_editbmesh(em, TRUE, FALSE);
+ BMEditMesh *em = BMEdit_Create(bm, false);
+ DerivedMesh *dm = CDDM_from_editbmesh(em, true, false);
MDisps *mdisps;
BMFace *f;
BMIter iter;
@@ -433,63 +453,77 @@ void bmesh_edit_end(BMesh *bm, int UNUSED(flag))
#endif
/* compute normals, clear temp flags and flush selections */
- BM_mesh_normals_update(bm, TRUE);
+ BM_mesh_normals_update(bm, true);
BM_mesh_select_mode_flush(bm);
}
void BM_mesh_elem_index_ensure(BMesh *bm, const char hflag)
{
- BMIter iter;
- BMElem *ele;
-
#ifdef DEBUG
BM_ELEM_INDEX_VALIDATE(bm, "Should Never Fail!", __func__);
#endif
- if (hflag & BM_VERT) {
- if (bm->elem_index_dirty & BM_VERT) {
- int index = 0;
- BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_index_set(ele, index); /* set_ok */
- index++;
+#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)
+ {
+#pragma omp section
+ {
+ if (hflag & BM_VERT) {
+ if (bm->elem_index_dirty & BM_VERT) {
+ BMIter iter;
+ BMElem *ele;
+
+ int index;
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, index) {
+ BM_elem_index_set(ele, index); /* set_ok */
+ }
+ BLI_assert(index == bm->totvert);
+ }
+ else {
+ // printf("%s: skipping vert index calc!\n", __func__);
+ }
}
- bm->elem_index_dirty &= ~BM_VERT;
- BLI_assert(index == bm->totvert);
- }
- else {
- // printf("%s: skipping vert index calc!\n", __func__);
}
- }
- if (hflag & BM_EDGE) {
- if (bm->elem_index_dirty & BM_EDGE) {
- int index = 0;
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_index_set(ele, index); /* set_ok */
- index++;
+#pragma omp section
+ {
+ if (hflag & BM_EDGE) {
+ if (bm->elem_index_dirty & BM_EDGE) {
+ BMIter iter;
+ BMElem *ele;
+
+ int index;
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, index) {
+ BM_elem_index_set(ele, index); /* set_ok */
+ }
+ BLI_assert(index == bm->totedge);
+ }
+ else {
+ // printf("%s: skipping edge index calc!\n", __func__);
+ }
}
- bm->elem_index_dirty &= ~BM_EDGE;
- BLI_assert(index == bm->totedge);
- }
- else {
- // printf("%s: skipping edge index calc!\n", __func__);
}
- }
- if (hflag & BM_FACE) {
- if (bm->elem_index_dirty & BM_FACE) {
- int index = 0;
- BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
- BM_elem_index_set(ele, index); /* set_ok */
- index++;
+#pragma omp section
+ {
+ if (hflag & BM_FACE) {
+ if (bm->elem_index_dirty & BM_FACE) {
+ BMIter iter;
+ BMElem *ele;
+
+ int index;
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, index) {
+ BM_elem_index_set(ele, index); /* set_ok */
+ }
+ BLI_assert(index == bm->totface);
+ }
+ else {
+ // printf("%s: skipping face index calc!\n", __func__);
+ }
}
- bm->elem_index_dirty &= ~BM_FACE;
- BLI_assert(index == bm->totface);
- }
- else {
- // printf("%s: skipping face index calc!\n", __func__);
}
}
+
+ bm->elem_index_dirty &= ~hflag;
}
@@ -517,12 +551,12 @@ void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *fu
BMIter iter;
BMElem *ele;
int i;
- int is_any_error = 0;
+ bool is_any_error = 0;
for (i = 0; i < 3; i++) {
- const int is_dirty = (flag_types[i] & bm->elem_index_dirty);
+ const bool is_dirty = (flag_types[i] & bm->elem_index_dirty);
int index = 0;
- int is_error = FALSE;
+ bool is_error = false;
int err_val = 0;
int err_idx = 0;
@@ -531,7 +565,7 @@ void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *fu
if (BM_elem_index_get(ele) != index) {
err_val = BM_elem_index_get(ele);
err_idx = index;
- is_error = TRUE;
+ is_error = true;
}
}
@@ -539,13 +573,13 @@ void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *fu
index++;
}
- if ((is_error == TRUE) && (is_dirty == FALSE)) {
- is_any_error = TRUE;
+ if ((is_error == true) && (is_dirty == false)) {
+ is_any_error = true;
fprintf(stderr,
"Invalid Index: at %s, %s, %s[%d] invalid index %d, '%s', '%s'\n",
location, func, type_names[i], err_idx, err_val, msg_a, msg_b);
}
- else if ((is_error == FALSE) && (is_dirty == TRUE)) {
+ else if ((is_error == false) && (is_dirty == true)) {
#if 0 /* mostly annoying */
@@ -722,7 +756,7 @@ void BM_mesh_remap(BMesh *bm, int *vert_idx, int *edge_idx, int *face_idx)
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));*/
+/* 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);
}
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index 8baba568fb8..35ce1859c2b 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -37,7 +37,7 @@ void BM_mesh_free(BMesh *bm);
void BM_mesh_data_free(BMesh *bm);
void BM_mesh_clear(BMesh *bm);
-void BM_mesh_normals_update(BMesh *bm, const short skip_hidden);
+void BM_mesh_normals_update(BMesh *bm, const bool skip_hidden);
void bmesh_edit_begin(BMesh *bm, int type_flag);
void bmesh_edit_end(BMesh *bm, int type_flag);
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c
index 388d148377a..c68bb2cd20c 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c
@@ -98,8 +98,108 @@
#include "bmesh.h"
#include "intern/bmesh_private.h" /* for element checking */
-/* Mesh -> BMesh */
-void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr)
+void BM_mesh_cd_flag_ensure(BMesh *bm, Mesh *mesh, const char cd_flag)
+{
+ const char cd_flag_all = BM_mesh_cd_flag_from_bmesh(bm) | cd_flag;
+ BM_mesh_cd_flag_apply(bm, cd_flag_all);
+ if (mesh) {
+ mesh->cd_flag = cd_flag_all;
+ }
+}
+
+void BM_mesh_cd_flag_apply(BMesh *bm, const char cd_flag)
+{
+ /* CustomData_bmesh_init_pool() must run first */
+ BLI_assert(bm->vdata.totlayer == 0 || bm->vdata.pool != NULL);
+ BLI_assert(bm->edata.totlayer == 0 || bm->edata.pool != NULL);
+ BLI_assert(bm->pdata.totlayer == 0 || bm->pdata.pool != NULL);
+
+ if (cd_flag & ME_CDFLAG_VERT_BWEIGHT) {
+ if (!CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
+ BM_data_layer_add(bm, &bm->vdata, CD_BWEIGHT);
+ }
+ }
+ else {
+ if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
+ BM_data_layer_free(bm, &bm->vdata, CD_BWEIGHT);
+ }
+ }
+
+ if (cd_flag & ME_CDFLAG_EDGE_BWEIGHT) {
+ if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
+ BM_data_layer_add(bm, &bm->edata, CD_BWEIGHT);
+ }
+ }
+ else {
+ if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
+ BM_data_layer_free(bm, &bm->edata, CD_BWEIGHT);
+ }
+ }
+
+ if (cd_flag & ME_CDFLAG_EDGE_CREASE) {
+ if (!CustomData_has_layer(&bm->edata, CD_CREASE)) {
+ BM_data_layer_add(bm, &bm->edata, CD_CREASE);
+ }
+ }
+ else {
+ if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
+ BM_data_layer_free(bm, &bm->edata, CD_CREASE);
+ }
+ }
+#ifdef WITH_FREESTYLE
+ if (cd_flag & ME_CDFLAG_FREESTYLE_EDGE) {
+ if (!CustomData_has_layer(&bm->edata, CD_FREESTYLE_EDGE)) {
+ BM_data_layer_add(bm, &bm->edata, CD_FREESTYLE_EDGE);
+ }
+ }
+ else {
+ if (CustomData_has_layer(&bm->edata, CD_FREESTYLE_EDGE)) {
+ BM_data_layer_free(bm, &bm->edata, CD_FREESTYLE_EDGE);
+ }
+ }
+
+ if (cd_flag & ME_CDFLAG_FREESTYLE_FACE) {
+ if (!CustomData_has_layer(&bm->pdata, CD_FREESTYLE_FACE)) {
+ BM_data_layer_add(bm, &bm->pdata, CD_FREESTYLE_FACE);
+ }
+ }
+ else {
+ if (CustomData_has_layer(&bm->pdata, CD_FREESTYLE_FACE)) {
+ BM_data_layer_free(bm, &bm->pdata, CD_FREESTYLE_FACE);
+ }
+ }
+#endif
+}
+
+char BM_mesh_cd_flag_from_bmesh(BMesh *bm)
+{
+ char cd_flag = 0;
+ if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
+ cd_flag |= ME_CDFLAG_VERT_BWEIGHT;
+ }
+ if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
+ cd_flag |= ME_CDFLAG_EDGE_BWEIGHT;
+ }
+ if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
+ cd_flag |= ME_CDFLAG_EDGE_CREASE;
+ }
+#ifdef WITH_FREESTYLE
+ if (CustomData_has_layer(&bm->edata, CD_FREESTYLE_EDGE)) {
+ cd_flag |= ME_CDFLAG_FREESTYLE_EDGE;
+ }
+ if (CustomData_has_layer(&bm->pdata, CD_FREESTYLE_FACE)) {
+ cd_flag |= ME_CDFLAG_FREESTYLE_FACE;
+ }
+#endif
+ return cd_flag;
+}
+
+/**
+ * \brief Mesh -> BMesh
+ *
+ * \warning This function doesn't calculate face normals.
+ */
+void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, bool set_key, int act_key_nr)
{
MVert *mvert;
BLI_array_declare(verts);
@@ -110,12 +210,15 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr)
BMVert *v, **vt = NULL, **verts = NULL;
BMEdge *e, **fedges = NULL, **et = NULL;
BMFace *f;
- BMLoop *l;
BLI_array_declare(fedges);
float (*keyco)[3] = NULL;
int *keyi;
int totuv, i, j;
+ int cd_vert_bweight_offset;
+ int cd_edge_bweight_offset;
+ int cd_edge_crease_offset;
+
/* free custom data */
/* this isnt needed in most cases but do just incase */
CustomData_free(&bm->vdata, bm->totvert);
@@ -152,15 +255,6 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr)
CustomData_set_layer_name(&bm->ldata, CD_MLOOPUV, i, bm->pdata.layers[li].name);
}
- if (!CustomData_has_layer(&bm->edata, CD_CREASE))
- CustomData_add_layer(&bm->edata, CD_CREASE, CD_ASSIGN, NULL, 0);
-
- if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT))
- CustomData_add_layer(&bm->edata, CD_BWEIGHT, CD_ASSIGN, NULL, 0);
-
- if (!CustomData_has_layer(&bm->vdata, CD_BWEIGHT))
- CustomData_add_layer(&bm->vdata, CD_BWEIGHT, CD_ASSIGN, NULL, 0);
-
if ((act_key_nr != 0) && (me->key != NULL)) {
actkey = BLI_findlink(&me->key->block, act_key_nr - 1);
}
@@ -205,6 +299,12 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr)
CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP);
CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE);
+ BM_mesh_cd_flag_apply(bm, me->cd_flag);
+
+ cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
+ cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
+ cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
+
for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) {
v = BM_vert_create(bm, keyco && set_key ? keyco[i] : mvert->co, NULL, BM_CREATE_SKIP_CD);
BM_elem_index_set(v, i); /* set_ok */
@@ -215,15 +315,15 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr)
/* this is necessary for selection counts to work properly */
if (mvert->flag & SELECT) {
- BM_vert_select_set(bm, v, TRUE);
+ BM_vert_select_set(bm, v, true);
}
normal_short_to_float_v3(v->no, mvert->no);
/* Copy Custom Data */
- CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data);
+ CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data, true);
- BM_elem_float_data_set(&bm->vdata, v, CD_BWEIGHT, (float)mvert->bweight / 255.0f);
+ if (cd_vert_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(v, cd_vert_bweight_offset, (float)mvert->bweight / 255.0f);
/* set shapekey data */
if (me->key) {
@@ -263,21 +363,23 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr)
/* this is necessary for selection counts to work properly */
if (medge->flag & SELECT) {
- BM_edge_select_set(bm, e, TRUE);
+ BM_edge_select_set(bm, e, true);
}
/* Copy Custom Data */
- CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data);
+ CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data, true);
+
+ if (cd_edge_bweight_offset != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_bweight_offset, (float)medge->bweight / 255.0f);
+ if (cd_edge_crease_offset != -1) BM_ELEM_CD_SET_FLOAT(e, cd_edge_crease_offset, (float)medge->crease / 255.0f);
- BM_elem_float_data_set(&bm->edata, e, CD_CREASE, (float)medge->crease / 255.0f);
- BM_elem_float_data_set(&bm->edata, e, CD_BWEIGHT, (float)medge->bweight / 255.0f);
}
bm->elem_index_dirty &= ~BM_EDGE; /* added in order, clear dirty flag */
mpoly = me->mpoly;
for (i = 0; i < me->totpoly; i++, mpoly++) {
- BMIter iter;
+ BMLoop *l_iter;
+ BMLoop *l_first;
BLI_array_empty(fedges);
BLI_array_empty(verts);
@@ -329,42 +431,41 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr)
/* this is necessary for selection counts to work properly */
if (mpoly->flag & ME_FACE_SEL) {
- BM_face_select_set(bm, f, TRUE);
+ BM_face_select_set(bm, f, true);
}
f->mat_nr = mpoly->mat_nr;
if (i == me->act_face) bm->act_face = f;
- j = 0;
- BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, j) {
+ j = mpoly->loopstart;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
/* Save index of correspsonding MLoop */
- CustomData_to_bmesh_block(&me->ldata, &bm->ldata, mpoly->loopstart + j, &l->head.data);
- }
+ CustomData_to_bmesh_block(&me->ldata, &bm->ldata, j++, &l_iter->head.data, true);
+ } while ((l_iter = l_iter->next) != l_first);
/* Copy Custom Data */
- CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data);
+ CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data, true);
}
bm->elem_index_dirty &= ~BM_FACE; /* added in order, clear dirty flag */
if (me->mselect && me->totselect != 0) {
- BMVert **vert_array = MEM_callocN(sizeof(BMVert *) * bm->totvert,
- "Selection Conversion Vertex Pointer Array");
- BMEdge **edge_array = MEM_callocN(sizeof(BMEdge *) * bm->totedge,
- "Selection Conversion Edge Pointer Array");
- BMFace **face_array = MEM_callocN(sizeof(BMFace *) * bm->totface,
- "Selection Conversion Face Pointer Array");
-
- BMIter iter;
- BMVert *vert;
- BMEdge *edge;
- BMFace *face;
+ BMVert **vert_array = MEM_mallocN(sizeof(BMVert *) * bm->totvert, "VSelConv");
+ BMEdge **edge_array = MEM_mallocN(sizeof(BMEdge *) * bm->totedge, "ESelConv");
+ BMFace **face_array = MEM_mallocN(sizeof(BMFace *) * bm->totface, "FSelConv");
MSelect *msel;
- BM_ITER_MESH_INDEX (vert, &iter, bm, BM_VERTS_OF_MESH, i) { vert_array[i] = vert; }
- BM_ITER_MESH_INDEX (edge, &iter, bm, BM_EDGES_OF_MESH, i) { edge_array[i] = edge; }
- BM_ITER_MESH_INDEX (face, &iter, bm, BM_FACES_OF_MESH, i) { face_array[i] = face; }
+#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)
+ {
+#pragma omp section
+ { BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void **)vert_array, bm->totvert); }
+#pragma omp section
+ { BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void **)edge_array, bm->totedge); }
+#pragma omp section
+ { BM_iter_as_array(bm, BM_FACES_OF_MESH, NULL, (void **)face_array, bm->totface); }
+ }
for (i = 0, msel = me->mselect; i < me->totselect; i++, msel++) {
switch (msel->type) {
@@ -400,7 +501,9 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr)
}
-/* BMesh -> Mesh */
+/**
+ * \brief BMesh -> Mesh
+ */
static BMVert **bm_to_mesh_vertex_map(BMesh *bm, int ototvert)
{
BMVert **vertMap = NULL;
@@ -483,7 +586,7 @@ BLI_INLINE void bmesh_quick_edgedraw_flag(MEdge *med, BMEdge *e)
}
}
-void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, int dotess)
+void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, bool do_tessface)
{
MLoop *mloop;
MPoly *mpoly;
@@ -496,6 +599,10 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, int dotess)
BMIter iter, liter;
int i, j, ototvert;
+ const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
+ const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
+ const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
+
ototvert = me->totvert;
/* new vertex block */
@@ -550,15 +657,13 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, int dotess)
CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop);
CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly);
+ me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
+
/* this is called again, 'dotess' arg is used there */
- mesh_update_customdata_pointers(me, 0);
+ BKE_mesh_update_customdata_pointers(me, 0);
i = 0;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- float *bweight = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_BWEIGHT);
-
- mvert->bweight = bweight ? (char)((*bweight) * 255) : 0;
-
copy_v3_v3(mvert->co, v->co);
normal_float_to_short_v3(mvert->no, v->no);
@@ -569,6 +674,8 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, int dotess)
/* copy over customdat */
CustomData_from_bmesh_block(&bm->vdata, &me->vdata, v->head.data, i);
+ if (cd_vert_bweight_offset != -1) mvert->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(v, cd_vert_bweight_offset);
+
i++;
mvert++;
@@ -579,13 +686,8 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, int dotess)
med = medge;
i = 0;
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- float *crease = CustomData_bmesh_get(&bm->edata, e->head.data, CD_CREASE);
- float *bweight = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BWEIGHT);
-
med->v1 = BM_elem_index_get(e->v1);
med->v2 = BM_elem_index_get(e->v2);
- med->crease = crease ? (char)((*crease) * 255) : 0;
- med->bweight = bweight ? (char)((*bweight) * 255) : 0;
med->flag = BM_edge_flag_to_mflag(e);
@@ -596,6 +698,9 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, int dotess)
bmesh_quick_edgedraw_flag(med, e);
+ if (cd_edge_crease_offset != -1) med->crease = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(e, cd_edge_crease_offset);
+ if (cd_edge_bweight_offset != -1) med->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(e, cd_edge_bweight_offset);
+
i++;
med++;
BM_CHECK_ELEMENT(e);
@@ -677,7 +782,9 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, int dotess)
hmd->indexar[j++] = BM_elem_index_get(eve);
}
}
- else j++;
+ else {
+ j++;
+ }
}
hmd->totindex = j;
@@ -689,11 +796,11 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, int dotess)
if (vertMap) MEM_freeN(vertMap);
}
- if (dotess) {
+ if (do_tessface) {
BKE_mesh_tessface_calc(me);
}
- mesh_update_customdata_pointers(me, dotess);
+ BKE_mesh_update_customdata_pointers(me, do_tessface);
{
BMEditSelection *selected;
@@ -757,12 +864,12 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, int dotess)
* bmesh and the mesh are out of sync */
(oldverts != NULL)) /* not used here, but 'oldverts' is used later for applying 'ofs' */
{
- int act_is_basis = FALSE;
+ 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;
+ act_is_basis = true;
break;
}
}
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.h b/source/blender/bmesh/intern/bmesh_mesh_conv.h
index f9c51584081..7fe4b8fe58b 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.h
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.h
@@ -34,7 +34,11 @@
struct Mesh;
-void BM_mesh_bm_from_me(BMesh *bm, struct Mesh *me, int set_key, int act_key_nr);
-void BM_mesh_bm_to_me(BMesh *bm, struct Mesh *me, int dotess);
+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, 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 8ab5f10361f..e6eee16e49c 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_validate.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_validate.c
@@ -49,9 +49,9 @@
/**
* Check of this BMesh is valid, this function can be slow since its intended to help with debugging.
*
- * \return TRUE when the mesh is valid.
+ * \return true when the mesh is valid.
*/
-int BM_mesh_validate(BMesh *bm)
+bool BM_mesh_validate(BMesh *bm)
{
int errtot;
@@ -106,11 +106,11 @@ int BM_mesh_validate(BMesh *bm)
if (l_iter->e != e) {
ERRMSG("edge %d: has invalid loop, loop is of face %d", i, BM_elem_index_get(l_iter->f));
}
- else if (BM_vert_in_edge(e, l_iter->v) == FALSE) {
+ else if (BM_vert_in_edge(e, l_iter->v) == false) {
ERRMSG("edge %d: has invalid loop with vert not in edge, loop is of face %d",
i, BM_elem_index_get(l_iter->f));
}
- else if (BM_vert_in_edge(e, l_iter->next->v) == FALSE) {
+ else if (BM_vert_in_edge(e, l_iter->next->v) == false) {
ERRMSG("edge %d: has invalid loop with next vert not in edge, loop is of face %d",
i, BM_elem_index_get(l_iter->f));
}
@@ -181,7 +181,7 @@ int BM_mesh_validate(BMesh *bm)
ERRMSG("Finished - errors %d", errtot);
- return TRUE;
+ return true;
}
diff --git a/source/blender/bmesh/intern/bmesh_mesh_validate.h b/source/blender/bmesh/intern/bmesh_mesh_validate.h
index 6839dc74d25..f89141387d8 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_validate.h
+++ b/source/blender/bmesh/intern/bmesh_mesh_validate.h
@@ -30,6 +30,6 @@
* \ingroup bmesh
*/
-int BM_mesh_validate(BMesh *bm);
+bool BM_mesh_validate(BMesh *bm);
#endif /* __BMESH_MESH_VALIDATE_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
index 9a99d5b96d1..afb3fc8112c 100644
--- a/source/blender/bmesh/intern/bmesh_mods.c
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -64,36 +64,36 @@
* \note dissolves vert, in more situations then BM_disk_dissolve
* (e.g. if the vert is part of a wire edge, etc).
*/
-int BM_vert_dissolve(BMesh *bm, BMVert *v)
+bool BM_vert_dissolve(BMesh *bm, BMVert *v)
{
const int len = BM_vert_edge_count(v);
if (len == 1) {
BM_vert_kill(bm, v); /* will kill edges too */
- return TRUE;
+ return true;
}
else if (!BM_vert_is_manifold(v)) {
if (!v->e) {
BM_vert_kill(bm, v);
- return TRUE;
+ return true;
}
else if (!v->e->l) {
if (len == 2) {
- return (BM_vert_collapse_edge(bm, v->e, v, TRUE) != NULL);
+ return (BM_vert_collapse_edge(bm, v->e, v, true) != NULL);
}
else {
/* used to kill the vertex here, but it may be connected to faces.
* so better do nothing */
- return FALSE;
+ return false;
}
}
else {
- return FALSE;
+ return false;
}
}
else if (len == 2 && BM_vert_face_count(v) == 1) {
/* boundary vertex on a face */
- return (BM_vert_collapse_edge(bm, v->e, v, TRUE) != NULL);
+ return (BM_vert_collapse_edge(bm, v->e, v, true) != NULL);
}
else {
return BM_disk_dissolve(bm, v);
@@ -103,14 +103,14 @@ int BM_vert_dissolve(BMesh *bm, BMVert *v)
/**
* dissolves all faces around a vert, and removes it.
*/
-int BM_disk_dissolve(BMesh *bm, BMVert *v)
+bool BM_disk_dissolve(BMesh *bm, BMVert *v)
{
BMFace *f, *f2;
BMEdge *e, *keepedge = NULL, *baseedge = NULL;
int len = 0;
if (!BM_vert_is_manifold(v)) {
- return FALSE;
+ return false;
}
if (v->e) {
@@ -135,62 +135,62 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v)
* increasing valence to four. this may be hackish. . */
BMLoop *loop = e->l;
if (loop->v == v) loop = loop->next;
- if (!BM_face_split(bm, loop->f, v, loop->v, NULL, NULL, FALSE))
- return FALSE;
+ if (!BM_face_split(bm, loop->f, v, loop->v, NULL, NULL, false))
+ return false;
if (!BM_disk_dissolve(bm, v)) {
- return FALSE;
+ return false;
}
#else
- if (UNLIKELY(!BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, TRUE))) {
- return FALSE;
+ if (UNLIKELY(!BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, true))) {
+ return false;
}
- else if (UNLIKELY(!BM_vert_collapse_faces(bm, v->e, v, 1.0, FALSE, TRUE))) {
- return FALSE;
+ else if (UNLIKELY(!BM_vert_collapse_faces(bm, v->e, v, 1.0, false, true))) {
+ return false;
}
#endif
- return TRUE;
+ return true;
}
else if (keepedge == NULL && len == 2) {
/* collapse the vertex */
- e = BM_vert_collapse_faces(bm, v->e, v, 1.0, TRUE, TRUE);
+ e = BM_vert_collapse_faces(bm, v->e, v, 1.0, true, true);
if (!e) {
- return FALSE;
+ return false;
}
/* handle two-valence */
f = e->l->f;
f2 = e->l->radial_next->f;
- if (f != f2 && !BM_faces_join_pair(bm, f, f2, e, TRUE)) {
- return FALSE;
+ if (f != f2 && !BM_faces_join_pair(bm, f, f2, e, true)) {
+ return false;
}
- return TRUE;
+ return true;
}
if (keepedge) {
- int done = FALSE;
+ bool done = false;
while (!done) {
- done = TRUE;
+ done = true;
e = v->e;
do {
f = NULL;
len = bmesh_radial_length(e->l);
if (len == 2 && (e != baseedge) && (e != keepedge)) {
- f = BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, TRUE);
+ f = BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, true);
/* return if couldn't join faces in manifold
* conditions */
/* !disabled for testing why bad things happen */
if (!f) {
- return FALSE;
+ return false;
}
}
if (f) {
- done = FALSE;
+ done = false;
break;
}
e = bmesh_disk_edge_next(e, v);
@@ -199,10 +199,10 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v)
/* collapse the vertex */
/* note, the baseedge can be a boundary of manifold, use this as join_faces arg */
- e = BM_vert_collapse_faces(bm, baseedge, v, 1.0, !BM_edge_is_boundary(baseedge), TRUE);
+ e = BM_vert_collapse_faces(bm, baseedge, v, 1.0, !BM_edge_is_boundary(baseedge), true);
if (!e) {
- return FALSE;
+ return false;
}
/* get remaining two faces */
@@ -211,13 +211,13 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v)
if (f != f2) {
/* join two remaining faces */
- if (!BM_faces_join_pair(bm, f, f2, e, TRUE)) {
- return FALSE;
+ if (!BM_faces_join_pair(bm, f, f2, e, true)) {
+ return false;
}
}
}
- return TRUE;
+ return true;
}
/**
@@ -235,7 +235,7 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v)
*
* \return pointer to the combined face
*/
-BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e, const short do_del)
+BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e, const bool do_del)
{
BMLoop *l1, *l2;
BMEdge *jed = NULL;
@@ -300,14 +300,14 @@ BMEdge *BM_verts_connect(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **r_f)
BM_ITER_ELEM (f_iter, &fiter, v1, BM_FACES_OF_VERT) {
BM_ITER_ELEM (v_iter, &viter, f_iter, BM_FACES_OF_VERT) {
if (v_iter == v2) {
- BMLoop *nl;
+ BMLoop *l_new;
- f_iter = BM_face_split(bm, f_iter, v1, v2, &nl, NULL, FALSE);
+ f_iter = BM_face_split(bm, f_iter, v1, v2, &l_new, NULL, false);
if (r_f) {
*r_f = f_iter;
}
- return nl->e;
+ return l_new->e;
}
}
}
@@ -336,54 +336,54 @@ BMEdge *BM_verts_connect(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **r_f)
* other side). NULL if the split fails.
*/
BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l,
- BMEdge *example, const short nodouble)
+ BMEdge *example, const bool no_double)
{
- const int has_mdisp = CustomData_has_layer(&bm->ldata, CD_MDISPS);
- BMFace *nf, *of;
+ const bool has_mdisp = CustomData_has_layer(&bm->ldata, CD_MDISPS);
+ BMFace *f_new, *f_tmp;
BLI_assert(v1 != v2);
/* do we have a multires layer? */
if (has_mdisp) {
- of = BM_face_copy(bm, f, FALSE, FALSE);
+ f_tmp = BM_face_copy(bm, f, false, false);
}
#ifdef USE_BMESH_HOLES
- nf = bmesh_sfme(bm, f, v1, v2, r_l, NULL, example, nodouble);
+ f_new = bmesh_sfme(bm, f, v1, v2, r_l, NULL, example, no_double);
#else
- nf = bmesh_sfme(bm, f, v1, v2, r_l, example, nodouble);
+ f_new = bmesh_sfme(bm, f, v1, v2, r_l, example, no_double);
#endif
- if (nf) {
- BM_elem_attrs_copy(bm, bm, f, nf);
- copy_v3_v3(nf->no, f->no);
+ if (f_new) {
+ BM_elem_attrs_copy(bm, bm, f, f_new);
+ copy_v3_v3(f_new->no, f->no);
/* handle multires update */
- if (has_mdisp && (nf != f)) {
+ if (has_mdisp && (f_new != f)) {
BMLoop *l_iter;
BMLoop *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
- BM_loop_interp_multires(bm, l_iter, of);
+ BM_loop_interp_multires(bm, l_iter, f_tmp);
} while ((l_iter = l_iter->next) != l_first);
- l_iter = l_first = BM_FACE_FIRST_LOOP(nf);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
do {
- BM_loop_interp_multires(bm, l_iter, of);
+ BM_loop_interp_multires(bm, l_iter, f_tmp);
} while ((l_iter = l_iter->next) != l_first);
- BM_face_kill(bm, of);
+ BM_face_kill(bm, f_tmp);
#if 0
/* BM_face_multires_bounds_smooth doesn't flip displacement correct */
BM_face_multires_bounds_smooth(bm, f);
- BM_face_multires_bounds_smooth(bm, nf);
+ BM_face_multires_bounds_smooth(bm, f_new);
#endif
}
}
- return nf;
+ return f_new;
}
/**
@@ -406,62 +406,62 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l
BMFace *BM_face_split_n(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, float cos[][3], int n,
BMLoop **r_l, BMEdge *example)
{
- BMFace *nf, *of;
+ BMFace *f_new, *f_tmp;
BMLoop *l_dummy;
- BMEdge *e, *newe;
- BMVert *newv;
+ BMEdge *e, *e_new;
+ BMVert *v_new;
int i, j;
BLI_assert(v1 != v2);
- of = BM_face_copy(bm, f, TRUE, TRUE);
+ f_tmp = BM_face_copy(bm, f, true, true);
if (!r_l)
r_l = &l_dummy;
#ifdef USE_BMESH_HOLES
- nf = bmesh_sfme(bm, f, v1, v2, r_l, NULL, example, FALSE);
+ f_new = bmesh_sfme(bm, f, v1, v2, r_l, NULL, example, false);
#else
- nf = bmesh_sfme(bm, f, v1, v2, r_l, example, FALSE);
+ f_new = bmesh_sfme(bm, f, v1, v2, r_l, example, false);
#endif
- /* bmesh_sfme returns in r_l a Loop for nf going from v1 to v2.
+ /* bmesh_sfme returns in r_l a Loop for f_new going from v1 to v2.
* The radial_next is for f and goes from v2 to v1 */
- if (nf) {
- BM_elem_attrs_copy(bm, bm, f, nf);
- copy_v3_v3(nf->no, f->no);
+ if (f_new) {
+ BM_elem_attrs_copy(bm, bm, f, f_new);
+ copy_v3_v3(f_new->no, f->no);
e = (*r_l)->e;
for (i = 0; i < n; i++) {
- newv = bmesh_semv(bm, v2, e, &newe);
- BLI_assert(newv != NULL);
- /* bmesh_semv returns in newe the edge going from newv to tv */
- copy_v3_v3(newv->co, cos[i]);
+ v_new = bmesh_semv(bm, v2, e, &e_new);
+ BLI_assert(v_new != NULL);
+ /* bmesh_semv returns in e_new the edge going from v_new to tv */
+ copy_v3_v3(v_new->co, cos[i]);
- /* interpolate the loop data for the loops with (v == newv), using orig face */
+ /* interpolate the loop data for the loops with (v == v_new), using orig face */
for (j = 0; j < 2; j++) {
- BMEdge *e_iter = (j == 0) ? e : newe;
+ BMEdge *e_iter = (j == 0) ? e : e_new;
BMLoop *l_iter = e_iter->l;
do {
- if (l_iter->v == newv) {
+ if (l_iter->v == v_new) {
/* this interpolates both loop and vertex data */
- BM_loop_interp_from_face(bm, l_iter, of, TRUE, TRUE);
+ BM_loop_interp_from_face(bm, l_iter, f_tmp, true, true);
}
} while ((l_iter = l_iter->radial_next) != e_iter->l);
}
- e = newe;
+ e = e_new;
}
}
- BM_face_verts_kill(bm, of);
+ BM_face_verts_kill(bm, f_tmp);
- return nf;
+ return f_new;
}
/**
* \brief Vert Collapse Faces
*
- * Collapses vertex \a kv that has only two manifold edges
+ * Collapses vertex \a v_kill that has only two manifold edges
* onto a vertex it shares an edge with.
* \a fac defines the amount of interpolation for Custom Data.
*
@@ -472,8 +472,8 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, float cos[
* Except this takes a factor and merges custom data.
*
* \param bm The bmesh
- * \param ke The edge to collapse
- * \param kv The vertex to collapse into the edge
+ * \param e_kill The edge to collapse
+ * \param v_kill The vertex to collapse into the edge
* \param fac The factor along the edge
* \param join_faces When true the faces around the vertex will be joined
* otherwise collapse the vertex by merging the 2 edges this vert touches into one.
@@ -481,11 +481,11 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, float cos[
*
* \returns The New Edge
*/
-BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac,
- const short join_faces, const short kill_degenerate_faces)
+BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac,
+ const bool join_faces, const bool kill_degenerate_faces)
{
- BMEdge *ne = NULL;
- BMVert *tv = bmesh_edge_other_vert_get(ke, kv);
+ BMEdge *e_new = NULL;
+ BMVert *tv = bmesh_edge_other_vert_get(e_kill, v_kill);
BMEdge *e2;
BMVert *tv2;
@@ -497,17 +497,17 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac,
float w[2];
/* Only intended to be called for 2-valence vertices */
- BLI_assert(bmesh_disk_count(kv) <= 2);
+ BLI_assert(bmesh_disk_count(v_kill) <= 2);
/* first modify the face loop data */
w[0] = 1.0f - fac;
w[1] = fac;
- if (ke->l) {
- l_iter = ke->l;
+ if (e_kill->l) {
+ l_iter = e_kill->l;
do {
- if (l_iter->v == tv && l_iter->next->v == kv) {
+ if (l_iter->v == tv && l_iter->next->v == v_kill) {
tvloop = l_iter;
kvloop = l_iter->next;
@@ -515,30 +515,30 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac,
src[1] = tvloop->head.data;
CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, kvloop->head.data);
}
- } while ((l_iter = l_iter->radial_next) != ke->l);
+ } while ((l_iter = l_iter->radial_next) != e_kill->l);
}
/* now interpolate the vertex data */
- BM_data_interp_from_verts(bm, kv, tv, kv, fac);
+ BM_data_interp_from_verts(bm, v_kill, tv, v_kill, fac);
- e2 = bmesh_disk_edge_next(ke, kv);
- tv2 = BM_edge_other_vert(e2, kv);
+ e2 = bmesh_disk_edge_next(e_kill, v_kill);
+ tv2 = BM_edge_other_vert(e2, v_kill);
if (join_faces) {
BMFace **faces = NULL;
BMFace *f;
BLI_array_staticdeclare(faces, 8);
- BM_ITER_ELEM (f, &iter, kv, BM_FACES_OF_VERT) {
+ BM_ITER_ELEM (f, &iter, v_kill, BM_FACES_OF_VERT) {
BLI_array_append(faces, f);
}
if (BLI_array_count(faces) >= 2) {
- BMFace *f2 = BM_faces_join(bm, faces, BLI_array_count(faces), TRUE);
+ BMFace *f2 = BM_faces_join(bm, faces, BLI_array_count(faces), true);
if (f2) {
- BMLoop *nl = NULL;
- if (BM_face_split(bm, f2, tv, tv2, &nl, NULL, FALSE)) {
- ne = nl->e;
+ BMLoop *l_new = NULL;
+ if (BM_face_split(bm, f2, tv, tv2, &l_new, NULL, false)) {
+ e_new = l_new->e;
}
}
}
@@ -549,16 +549,16 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac,
/* single face or no faces */
/* same as BM_vert_collapse_edge() however we already
* have vars to perform this operation so don't call. */
- ne = bmesh_jekv(bm, ke, kv, TRUE);
- /* ne = BM_edge_exists(tv, tv2); */ /* same as return above */
+ e_new = bmesh_jekv(bm, e_kill, v_kill, true);
+ /* e_new = BM_edge_exists(tv, tv2); */ /* same as return above */
- if (ne && kill_degenerate_faces) {
+ if (e_new && kill_degenerate_faces) {
BLI_array_declare(bad_faces);
BMFace **bad_faces = NULL;
BMIter fiter;
BMFace *f;
- BMVert *verts[2] = {ne->v1, ne->v2};
+ BMVert *verts[2] = {e_new->v1, e_new->v2};
int i;
for (i = 0; i < 2; i++) {
@@ -577,7 +577,7 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac,
}
}
- return ne;
+ return e_new;
}
@@ -588,37 +588,37 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac,
*
* \return The New Edge
*/
-BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *ke, BMVert *kv,
- const short kill_degenerate_faces)
+BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
+ const bool kill_degenerate_faces)
{
/* nice example implementation but we want loops to have their customdata
* accounted for */
#if 0
- BMEdge *ne = NULL;
+ BMEdge *e_new = NULL;
/* Collapse between 2 edges */
/* in this case we want to keep all faces and not join them,
* rather just get rid of the vertex - see bug [#28645] */
- BMVert *tv = bmesh_edge_other_vert_get(ke, kv);
+ BMVert *tv = bmesh_edge_other_vert_get(e_kill, v_kill);
if (tv) {
- BMEdge *e2 = bmesh_disk_edge_next(ke, kv);
+ BMEdge *e2 = bmesh_disk_edge_next(e_kill, v_kill);
if (e2) {
- BMVert *tv2 = BM_edge_other_vert(e2, kv);
+ BMVert *tv2 = BM_edge_other_vert(e2, v_kill);
if (tv2) {
/* only action, other calls here only get the edge to return */
- ne = bmesh_jekv(bm, ke, kv);
+ e_new = bmesh_jekv(bm, e_kill, v_kill);
- /* ne = BM_edge_exists(tv, tv2); */ /* same as return above */
+ /* e_new = BM_edge_exists(tv, tv2); */ /* same as return above */
}
}
}
- return ne;
+ return e_new;
#else
/* with these args faces are never joined, same as above
* but account for loop customdata */
- return BM_vert_collapse_faces(bm, ke, kv, 1.0f, FALSE, kill_degenerate_faces);
+ return BM_vert_collapse_faces(bm, e_kill, v_kill, 1.0f, false, kill_degenerate_faces);
#endif
}
@@ -637,11 +637,11 @@ BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *ke, BMVert *kv,
*/
BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float percent)
{
- BMVert *nv, *v2;
+ BMVert *v_new, *v2;
BMFace **oldfaces = NULL;
BMEdge *e_dummy;
BLI_array_staticdeclare(oldfaces, 32);
- const int do_mdisp = (e->l && CustomData_has_layer(&bm->ldata, CD_MDISPS));
+ const bool do_mdisp = (e->l && CustomData_has_layer(&bm->ldata, CD_MDISPS));
/* we need this for handling multi-res */
if (!r_e) {
@@ -662,27 +662,27 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float perce
/* flag existing faces so we can differentiate oldfaces from new faces */
for (i = 0; i < BLI_array_count(oldfaces); i++) {
BM_ELEM_API_FLAG_ENABLE(oldfaces[i], _FLAG_OVERLAP);
- oldfaces[i] = BM_face_copy(bm, oldfaces[i], TRUE, TRUE);
+ oldfaces[i] = BM_face_copy(bm, oldfaces[i], true, true);
BM_ELEM_API_FLAG_DISABLE(oldfaces[i], _FLAG_OVERLAP);
}
}
v2 = bmesh_edge_other_vert_get(e, v);
- nv = bmesh_semv(bm, v, e, r_e);
+ v_new = bmesh_semv(bm, v, e, r_e);
- BLI_assert(nv != NULL);
+ BLI_assert(v_new != NULL);
- sub_v3_v3v3(nv->co, v2->co, v->co);
- madd_v3_v3v3fl(nv->co, v->co, nv->co, percent);
+ sub_v3_v3v3(v_new->co, v2->co, v->co);
+ madd_v3_v3v3fl(v_new->co, v->co, v_new->co, percent);
if (r_e) {
(*r_e)->head.hflag = e->head.hflag;
BM_elem_attrs_copy(bm, bm, e, *r_e);
}
- /* v->nv->v2 */
- BM_data_interp_face_vert_edge(bm, v2, v, nv, e, percent);
- BM_data_interp_from_verts(bm, v, v2, nv, percent);
+ /* v->v_new->v2 */
+ BM_data_interp_face_vert_edge(bm, v2, v, v_new, e, percent);
+ BM_data_interp_from_verts(bm, v, v2, v_new, percent);
if (do_mdisp) {
int i, j;
@@ -742,7 +742,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float perce
BLI_array_free(oldfaces);
}
- return nv;
+ return v_new;
}
/**
@@ -752,25 +752,27 @@ BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts)
{
int i;
float percent;
- BMVert *nv = NULL;
+ BMVert *v_new = NULL;
for (i = 0; i < numcuts; i++) {
percent = 1.0f / (float)(numcuts + 1 - i);
- nv = BM_edge_split(bm, e, e->v2, NULL, percent);
+ v_new = BM_edge_split(bm, e, e->v2, NULL, percent);
}
- return nv;
+ return v_new;
}
+#if 0
/**
* Checks if a face is valid in the data structure
*/
-int BM_face_validate(BMFace *face, FILE *err)
+bool BM_face_validate(BMFace *face, FILE *err)
{
BMIter iter;
BLI_array_declare(verts);
BMVert **verts = NULL;
BMLoop *l;
- int ret = 1, i, j;
+ int i, j;
+ bool ret = true;
if (face->len == 2) {
fprintf(err, "warning: found two-edged face. face ptr: %p\n", face);
@@ -784,7 +786,7 @@ int BM_face_validate(BMFace *face, FILE *err)
fprintf(err, "Found bmesh edge with identical verts!\n");
fprintf(err, " edge ptr: %p, vert: %p\n", l->e, l->e->v1);
fflush(err);
- ret = 0;
+ ret = false;
}
}
@@ -798,7 +800,7 @@ int BM_face_validate(BMFace *face, FILE *err)
fprintf(err, "Found duplicate verts in bmesh face!\n");
fprintf(err, " face ptr: %p, vert: %p\n", face, verts[i]);
fflush(err);
- ret = 0;
+ ret = false;
}
}
}
@@ -806,7 +808,7 @@ int BM_face_validate(BMFace *face, FILE *err)
BLI_array_free(verts);
return ret;
}
-
+#endif
/**
* Calculate the 2 loops which _would_ make up the newly rotated Edge
@@ -822,14 +824,14 @@ int BM_face_validate(BMFace *face, FILE *err)
*
* \note #BM_edge_rotate_check must have already run.
*/
-void BM_edge_calc_rotate(BMEdge *e, int ccw,
+void BM_edge_calc_rotate(BMEdge *e, const bool ccw,
BMLoop **r_l1, BMLoop **r_l2)
{
BMVert *v1, *v2;
BMFace *fa, *fb;
/* this should have already run */
- BLI_assert(BM_edge_rotate_check(e) == TRUE);
+ BLI_assert(BM_edge_rotate_check(e) == true);
/* we know this will work */
BM_edge_face_pair(e, &fa, &fb);
@@ -855,7 +857,7 @@ void BM_edge_calc_rotate(BMEdge *e, int ccw,
* Quick check to see if we could rotate the edge,
* use this to avoid calling exceptions on common cases.
*/
-int BM_edge_rotate_check(BMEdge *e)
+bool BM_edge_rotate_check(BMEdge *e)
{
BMFace *fa, *fb;
if (BM_edge_face_pair(e, &fa, &fb)) {
@@ -868,7 +870,7 @@ int BM_edge_rotate_check(BMEdge *e)
* (ie - the next edge doesn't share the same faces).
* since we can't rotate usefully in this case. */
if (la->v == lb->v) {
- return FALSE;
+ return false;
}
/* mirror of the check above but in the opposite direction */
@@ -876,13 +878,13 @@ int BM_edge_rotate_check(BMEdge *e)
lb = BM_face_other_vert_loop(fb, e->v1, e->v2);
if (la->v == lb->v) {
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
else {
- return FALSE;
+ return false;
}
}
@@ -897,7 +899,7 @@ int BM_edge_rotate_check(BMEdge *e)
* \param l1,l2 are the loops of the proposed verts to rotate too and should
* be the result of calling #BM_edge_calc_rotate
*/
-int BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2)
+bool BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2)
{
/* note: for these vars 'old' just means initial edge state. */
@@ -924,7 +926,7 @@ int BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2)
BMVert *v1_alt, *v2_alt;
/* this should have already run */
- BLI_assert(BM_edge_rotate_check(e) == TRUE);
+ BLI_assert(BM_edge_rotate_check(e) == true);
BM_edge_ordered_verts(e, &v1_old, &v2_old);
@@ -965,12 +967,12 @@ int BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2)
cross_v3_v3v3(cross_old, ed_dir_old, ed_dir_v1_old);
cross_v3_v3v3(cross_new, ed_dir_new, ed_dir_v1_new);
if (dot_v3v3(cross_old, cross_new) < 0.0f) { /* does this flip? */
- return FALSE;
+ return false;
}
cross_v3_v3v3(cross_old, ed_dir_old, ed_dir_v2_old);
cross_v3_v3v3(cross_new, ed_dir_new, ed_dir_v2_new);
if (dot_v3v3(cross_old, cross_new) < 0.0f) { /* does this flip? */
- return FALSE;
+ return false;
}
negate_v3_v3(ed_dir_new_flip, ed_dir_new);
@@ -979,14 +981,14 @@ int BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2)
if ((dot_v3v3(ed_dir_new, ed_dir_v1_new) > 0.999f) ||
(dot_v3v3(ed_dir_new_flip, ed_dir_v2_new) > 0.999f))
{
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
-int 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
@@ -1009,7 +1011,7 @@ int BM_edge_rotate_check_beauty(BMEdge *e,
*
* \see header definition for \a check_flag enum.
*/
-BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const short ccw, const short check_flag)
+BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_flag)
{
BMVert *v1, *v2;
BMLoop *l1, *l2;
@@ -1066,7 +1068,7 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const short ccw, const short check_
f_hflag_prev_2 = l2->f->head.hflag;
/* don't delete the edge, manually remove the egde after so we can copy its attributes */
- f = BM_faces_join_pair(bm, l1->f, l2->f, NULL, TRUE);
+ f = BM_faces_join_pair(bm, l1->f, l2->f, NULL, true);
if (f == NULL) {
return NULL;
@@ -1075,7 +1077,7 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const short ccw, const short check_
/* note, this assumes joining the faces _didnt_ also remove the verts.
* the #BM_edge_rotate_check will ensure this, but its possibly corrupt state or future edits
* break this */
- if (!BM_face_split(bm, f, v1, v2, NULL, NULL, TRUE)) {
+ if (!BM_face_split(bm, f, v1, v2, NULL, NULL, true)) {
return NULL;
}
else {
diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h
index 790f0cb6267..93d6ca10edb 100644
--- a/source/blender/bmesh/intern/bmesh_mods.h
+++ b/source/blender/bmesh/intern/bmesh_mods.h
@@ -29,44 +29,44 @@
#include <stdio.h>
-int BM_vert_dissolve(BMesh *bm, BMVert *v);
+bool BM_vert_dissolve(BMesh *bm, BMVert *v);
-int BM_disk_dissolve(BMesh *bm, BMVert *v);
+bool BM_disk_dissolve(BMesh *bm, BMVert *v);
-BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e, const short do_del);
+BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e, const bool do_del);
BMEdge *BM_verts_connect(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **r_f);
BMFace *BM_face_split(BMesh *bm, BMFace *f,
BMVert *v1, BMVert *v2,
BMLoop **r_l,
- BMEdge *example, const short nodouble);
+ BMEdge *example, const bool no_double);
BMFace *BM_face_split_n(BMesh *bm, BMFace *f,
BMVert *v1, BMVert *v2,
float cos[][3], int n,
BMLoop **r_l, BMEdge *example);
-BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac,
- const short join_faces, const short kill_degenerate_faces);
-BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *ke, BMVert *kv,
- const short kill_degenerate_faces);
+BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac,
+ const bool join_faces, const bool kill_degenerate_faces);
+BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
+ const bool kill_degenerate_faces);
BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float percent);
BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts);
-int BM_face_validate(BMFace *face, FILE *err);
+bool BM_face_validate(BMFace *face, FILE *err);
-void BM_edge_calc_rotate(BMEdge *e, int ccw,
+void BM_edge_calc_rotate(BMEdge *e, const bool ccw,
BMLoop **r_l1, BMLoop **r_l2);
-int BM_edge_rotate_check(BMEdge *e);
-int BM_edge_rotate_check_degenerate(BMEdge *e,
+bool BM_edge_rotate_check(BMEdge *e);
+bool BM_edge_rotate_check_degenerate(BMEdge *e,
BMLoop *l1, BMLoop *l2);
-int BM_edge_rotate_check_beauty(BMEdge *e,
+bool BM_edge_rotate_check_beauty(BMEdge *e,
BMLoop *l1, BMLoop *l2);
-BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const short ccw, const short check_flag);
+BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_flag);
/* flags for BM_edge_rotate */
enum {
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 3a7a1c4eaaa..7e3ee9d249e 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -128,7 +128,7 @@ static BMOpDefine bmo_smooth_laplacian_vert_def = {
"smooth_laplacian_vert",
/* slots_in */
{{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
- {"lambda", BMO_OP_SLOT_FLT}, /* lambda param */
+ {"lambda_factor", BMO_OP_SLOT_FLT}, /* lambda param */
{"lambda_border", BMO_OP_SLOT_FLT}, /* lambda param in border */
{"use_x", BMO_OP_SLOT_BOOL}, /* Smooth object along X axis */
{"use_y", BMO_OP_SLOT_BOOL}, /* Smooth object along Y axis */
@@ -1403,24 +1403,13 @@ static BMOpDefine bmo_bevel_def = {
{{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input edges and vertices */
{"offset", BMO_OP_SLOT_FLT}, /* amount to offset beveled edge */
{"segments", BMO_OP_SLOT_INT}, /* number of segments in bevel */
+ {"vertex_only", BMO_OP_SLOT_BOOL}, /* only bevel vertices, not edges */
{{'\0'}},
},
/* slots_out */
{{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
{{'\0'}},
},
-/* old bevel*/
-// {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input edges and vertices */
-// {"face_spans", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new geometry */
-// {"face_holes", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new geometry */
-// {"use_lengths", BMO_OP_SLOT_BOOL}, /* grab edge lengths from a PROP_FLT customdata layer */
-// {"use_even", BMO_OP_SLOT_BOOL}, /* corner vert placement: use shell/angle calculations */
-// {"use_dist", BMO_OP_SLOT_BOOL}, /* corner vert placement: evaluate percent as a distance,
-// * modifier uses this. We could do this as another float setting */
-// {"lengthlayer", BMO_OP_SLOT_INT}, /* which PROP_FLT layer to us */
-// {"percent", BMO_OP_SLOT_FLT}, /* percentage to expand beveled edge */
-// {{'\0'}},
-// },
bmo_bevel_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
@@ -1435,7 +1424,7 @@ static BMOpDefine bmo_beautify_fill_def = {
"beautify_fill",
/* slots_in */
{{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
- {"constrain_edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* edges that can't be flipped */
+ {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* edges that can be flipped */
{{'\0'}},
},
/* slots_out */
@@ -1454,7 +1443,8 @@ static BMOpDefine bmo_beautify_fill_def = {
static BMOpDefine bmo_triangle_fill_def = {
"triangle_fill",
/* slots_in */
- {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
+ {{"use_beauty", BMO_OP_SLOT_BOOL},
+ {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
{{'\0'}},
},
/* slots_out */
@@ -1535,27 +1525,6 @@ static BMOpDefine bmo_wireframe_def = {
0
};
-/*
- * Vertex Slide.
- *
- * Translates verts along an edge
- */
-static BMOpDefine bmo_slide_vert_def = {
- "slide_vert",
- /* slots_in */
- {{"vert", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}},
- {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
- {"factor", BMO_OP_SLOT_FLT},
- {{'\0'}},
- },
- /* slots_out */
- {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
- {{'\0'}},
- },
- bmo_slide_vert_exec,
- BMO_OP_FLAG_UNTAN_MULTIRES
-};
-
#ifdef WITH_BULLET
/*
* Convex Hull
@@ -1675,7 +1644,6 @@ const BMOpDefine *bmo_opdefines[] = {
&bmo_similar_edges_def,
&bmo_similar_faces_def,
&bmo_similar_verts_def,
- &bmo_slide_vert_def,
&bmo_smooth_vert_def,
&bmo_smooth_laplacian_vert_def,
&bmo_solidify_def,
diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h
index 7df9c94a2f1..978aec0c610 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api.h
@@ -244,19 +244,19 @@ void BMO_push(BMesh *bm, BMOperator *op);
void BMO_pop(BMesh *bm);
/*executes an operator*/
-int BMO_op_callf(BMesh *bm, const int flag, const char *fmt, ...);
+bool BMO_op_callf(BMesh *bm, const int flag, const char *fmt, ...);
/* initializes, but doesn't execute an operator. this is so you can
* gain access to the outputs of the operator. note that you have
* to execute/finish (BMO_op_exec and BMO_op_finish) yourself. */
-int BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ...);
+bool BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ...);
/* va_list version, used to implement the above two functions,
* plus EDBM_op_callf in editmesh_utils.c. */
-int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, va_list vlist);
+bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, va_list vlist);
/* test whether a named slot exists */
-int BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier);
+bool BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier);
/* get a pointer to a slot. this may be removed layer on from the public API. */
BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier);
@@ -301,8 +301,8 @@ void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_
float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i);
int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
-void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i);
-int BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
+void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const bool i);
+bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len);
@@ -360,11 +360,11 @@ void BMO_slot_buffer_flag_disable(BMesh *bm,
/* 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 char do_flush);
+ 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 char do_flush);
+ 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
@@ -435,7 +435,7 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_
* //whether it's a float, pointer, whatever.
* //
* // so to get a pointer, for example, use:
- * // *((void**)BMO_iter_map_value(&oiter));
+ * // *((void **)BMO_iter_map_value(&oiter));
* //or something like that.
* }
* \endcode
@@ -451,7 +451,7 @@ typedef struct BMOIter {
char restrictmask; /* bitwise '&' with BMHeader.htype */
} BMOIter;
-void *BMO_slot_buffer_elem_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
+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,
diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h
index ad116011421..0e1d4fec4d3 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h
@@ -80,7 +80,7 @@ BLI_INLINE void BMO_slot_map_bool_insert(BMOperator *op, BMOpSlot *slot,
void *element, const int val)
{
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL);
- BLI_assert(val == FALSE || val == TRUE);
+ BLI_assert(val == false || val == true);
BMO_slot_map_insert(op, slot, element, &val, sizeof(int));
}
@@ -120,13 +120,13 @@ BLI_INLINE void BMO_slot_map_empty_insert(BMOperator *op, BMOpSlot *slot,
BMO_slot_map_insert(op, slot, element, NULL, 0);
}
-BLI_INLINE int BMO_slot_map_contains(BMOpSlot *slot, const void *element)
+BLI_INLINE bool BMO_slot_map_contains(BMOpSlot *slot, const void *element)
{
BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
/* sanity check */
if (UNLIKELY(slot->data.ghash == NULL)) {
- return 0;
+ return false;
}
return BLI_ghash_haskey(slot->data.ghash, element);
@@ -173,16 +173,16 @@ BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element)
return 0;
}
-BLI_INLINE int BMO_slot_map_bool_get(BMOpSlot *slot, const void *element)
+BLI_INLINE bool BMO_slot_map_bool_get(BMOpSlot *slot, const void *element)
{
int *val;
BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL);
val = (int *) BMO_slot_map_data_get(slot, element);
- BLI_assert(val == NULL || *val == FALSE || *val == TRUE);
- if (val) return *val;
+ BLI_assert(val == NULL || *val == false || *val == true);
+ if (val) return (bool)*val;
- return 0;
+ return false;
}
BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element)
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index 19f2b2f8978..f52dd7f2be9 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -238,7 +238,7 @@ void BMO_op_finish(BMesh *bm, BMOperator *op)
*
* \return Success if the slot if found.
*/
-int BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
+bool BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
{
int slot_code = bmo_name_to_slotcode(slot_args, identifier);
return (slot_code >= 0);
@@ -390,7 +390,7 @@ void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_nam
slot->data.i = i;
}
-void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i)
+void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const bool i)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL);
@@ -495,7 +495,7 @@ int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name
return slot->data.i;
}
-int BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
+bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL);
@@ -549,7 +549,7 @@ 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 short test_for_enabled)
+ const bool test_for_enabled)
{
const char iter_types[3] = {BM_VERTS_OF_MESH,
BM_EDGES_OF_MESH,
@@ -562,7 +562,7 @@ static int bmo_mesh_flag_count(BMesh *bm, const char htype, const short oflag,
BMElemF *ele_f;
int i;
- BLI_assert(ELEM(TRUE, FALSE, test_for_enabled));
+ BLI_assert((unsigned int)test_for_enabled <= 1);
for (i = 0; i < 3; i++) {
if (htype & flag_types[i]) {
@@ -579,12 +579,12 @@ static int bmo_mesh_flag_count(BMesh *bm, const char htype, const short oflag,
int BMO_mesh_enabled_flag_count(BMesh *bm, const char htype, const short oflag)
{
- return bmo_mesh_flag_count(bm, htype, oflag, TRUE);
+ return bmo_mesh_flag_count(bm, htype, oflag, true);
}
int BMO_mesh_disabled_flag_count(BMesh *bm, const char htype, const short oflag)
{
- return bmo_mesh_flag_count(bm, htype, oflag, FALSE);
+ return bmo_mesh_flag_count(bm, htype, oflag, false);
}
void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char htype, const short oflag)
@@ -595,12 +595,13 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char hty
const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE};
- BMIter iter;
BMElemF *ele;
int i;
+#pragma omp parallel for schedule(dynamic) if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)
for (i = 0; i < 3; i++) {
if (htype & flag_types[i]) {
+ BMIter iter;
BM_ITER_MESH (ele, &iter, bm, iter_types[i]) {
BMO_elem_flag_disable(bm, ele, oflag);
}
@@ -794,14 +795,12 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_
*/
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 short test_for_enabled)
+ const bool test_for_enabled)
{
BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
int totelement = 0, i = 0;
const int respecthide = (op->flag & BMO_FLAG_RESPECT_HIDE) != 0;
- BLI_assert(ELEM(test_for_enabled, TRUE, FALSE));
-
if (test_for_enabled)
totelement = BM_mesh_elem_hflag_count_enabled(bm, htype, hflag, respecthide);
else
@@ -857,14 +856,14 @@ 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);
+ 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)
{
- bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, FALSE);
+ bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, false);
}
void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele)
@@ -933,13 +932,13 @@ void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const cha
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 short test_for_enabled)
+ const bool test_for_enabled)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
int totelement, i = 0;
BLI_assert(op->slots_in == slot_args || op->slots_out == slot_args);
- BLI_assert(ELEM(TRUE, FALSE, test_for_enabled));
+ BLI_assert((unsigned int)test_for_enabled <= 1);
if (test_for_enabled)
totelement = BMO_mesh_enabled_flag_count(bm, htype, oflag);
@@ -996,14 +995,14 @@ 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);
+ 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)
{
- bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, FALSE);
+ bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, false);
}
/**
@@ -1014,13 +1013,13 @@ void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op,
*/
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 char do_flush)
+ 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;
int i;
- const char do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT));
- const char do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN));
+ const bool do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT));
+ const bool do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN));
BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
@@ -1030,11 +1029,11 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm,
continue;
if (do_flush_select) {
- BM_elem_select_set(bm, *data, TRUE);
+ BM_elem_select_set(bm, *data, true);
}
if (do_flush_hide) {
- BM_elem_hide_set(bm, *data, FALSE);
+ BM_elem_hide_set(bm, *data, false);
}
BM_elem_flag_enable(*data, hflag);
@@ -1049,13 +1048,13 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm,
*/
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 char do_flush)
+ 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;
int i;
- const char do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT));
- const char do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN));
+ const bool do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT));
+ const bool do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN));
BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
@@ -1065,11 +1064,11 @@ void BMO_slot_buffer_hflag_disable(BMesh *bm,
continue;
if (do_flush_select) {
- BM_elem_select_set(bm, *data, FALSE);
+ BM_elem_select_set(bm, *data, false);
}
if (do_flush_hide) {
- BM_elem_hide_set(bm, *data, FALSE);
+ BM_elem_hide_set(bm, *data, false);
}
BM_elem_flag_disable(*data, hflag);
@@ -1159,100 +1158,161 @@ void BMO_slot_buffer_flag_disable(BMesh *bm,
*/
static void bmo_flag_layer_alloc(BMesh *bm)
{
- BMElemF *ele;
/* set the index values since we are looping over all data anyway,
* may save time later on */
- int i;
- BMIter iter;
- BLI_mempool *oldpool = bm->toolflagpool; /* old flag pool */
- BLI_mempool *newpool;
- void *oldflags;
+ BLI_mempool *voldpool = bm->vtoolflagpool; /* old flag pool */
+ BLI_mempool *eoldpool = bm->etoolflagpool; /* old flag pool */
+ BLI_mempool *foldpool = bm->ftoolflagpool; /* old flag pool */
/* store memcpy size for reuse */
const size_t old_totflags_size = (bm->totflags * sizeof(BMFlagLayer));
- BLI_assert(oldpool != NULL);
-
bm->totflags++;
- /* allocate new flag pool */
- bm->toolflagpool = newpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, 512, 512, 0);
-
- /* now go through and memcpy all the flags. Loops don't get a flag layer at this time.. */
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
- oldflags = ele->oflags;
- ele->oflags = BLI_mempool_calloc(newpool);
- memcpy(ele->oflags, oldflags, old_totflags_size);
- BM_elem_index_set(ele, i); /* set_inline */
- BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
- }
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
- oldflags = ele->oflags;
- ele->oflags = BLI_mempool_calloc(newpool);
- memcpy(ele->oflags, oldflags, old_totflags_size);
- BM_elem_index_set(ele, i); /* set_inline */
- BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
- }
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
- oldflags = ele->oflags;
- ele->oflags = BLI_mempool_calloc(newpool);
- memcpy(ele->oflags, oldflags, old_totflags_size);
- BM_elem_index_set(ele, i); /* set_inline */
- BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
+ bm->vtoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, max_ii(512, bm->totvert), 512, 0);
+ bm->etoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, max_ii(512, bm->totedge), 512, 0);
+ bm->ftoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, max_ii(512, bm->totface), 512, 0);
+
+#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)
+ {
+#pragma omp section
+ {
+ BMIter iter;
+ BMElemF *ele;
+ int i;
+
+ BLI_mempool *newpool = bm->vtoolflagpool;
+
+ /* now go through and memcpy all the flags. Loops don't get a flag layer at this time.. */
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
+ void *oldflags = ele->oflags;
+ ele->oflags = BLI_mempool_calloc(newpool);
+ memcpy(ele->oflags, oldflags, old_totflags_size);
+ BM_elem_index_set(ele, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
+ }
+ }
+#pragma omp section
+ {
+ BMIter iter;
+ BMElemF *ele;
+ int i;
+
+ BLI_mempool *newpool = bm->etoolflagpool;
+
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
+ void *oldflags = ele->oflags;
+ ele->oflags = BLI_mempool_calloc(newpool);
+ memcpy(ele->oflags, oldflags, old_totflags_size);
+ BM_elem_index_set(ele, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
+ }
+ }
+#pragma omp section
+ {
+ BMIter iter;
+ BMElemF *ele;
+ int i;
+
+ BLI_mempool *newpool = bm->ftoolflagpool;
+
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
+ void *oldflags = ele->oflags;
+ ele->oflags = BLI_mempool_calloc(newpool);
+ memcpy(ele->oflags, oldflags, old_totflags_size);
+ BM_elem_index_set(ele, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
+ }
+ }
}
+ BLI_mempool_destroy(voldpool);
+ BLI_mempool_destroy(eoldpool);
+ BLI_mempool_destroy(foldpool);
+
bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE);
- BLI_mempool_destroy(oldpool);
+
}
static void bmo_flag_layer_free(BMesh *bm)
{
- BMElemF *ele;
/* set the index values since we are looping over all data anyway,
* may save time later on */
- int i;
- BMIter iter;
- BLI_mempool *oldpool = bm->toolflagpool;
- BLI_mempool *newpool;
- void *oldflags;
-
+ BLI_mempool *voldpool = bm->vtoolflagpool;
+ BLI_mempool *eoldpool = bm->etoolflagpool;
+ BLI_mempool *foldpool = bm->ftoolflagpool;
+
/* store memcpy size for reuse */
const size_t new_totflags_size = ((bm->totflags - 1) * sizeof(BMFlagLayer));
/* de-increment the totflags first.. */
bm->totflags--;
- /* allocate new flag pool */
- bm->toolflagpool = newpool = BLI_mempool_create(new_totflags_size, 512, 512, 0);
-
- /* now go through and memcpy all the flags */
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
- oldflags = ele->oflags;
- ele->oflags = BLI_mempool_calloc(newpool);
- memcpy(ele->oflags, oldflags, new_totflags_size);
- BM_elem_index_set(ele, i); /* set_inline */
- BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
- }
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
- oldflags = ele->oflags;
- ele->oflags = BLI_mempool_calloc(newpool);
- memcpy(ele->oflags, oldflags, new_totflags_size);
- BM_elem_index_set(ele, i); /* set_inline */
- BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
- }
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
- oldflags = ele->oflags;
- ele->oflags = BLI_mempool_calloc(newpool);
- memcpy(ele->oflags, oldflags, new_totflags_size);
- BM_elem_index_set(ele, i); /* set_inline */
- BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
+
+ bm->vtoolflagpool = BLI_mempool_create(new_totflags_size, bm->totvert, 512, 0);
+ bm->etoolflagpool = BLI_mempool_create(new_totflags_size, bm->totedge, 512, 0);
+ bm->ftoolflagpool = BLI_mempool_create(new_totflags_size, bm->totface, 512, 0);
+
+#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)
+ {
+#pragma omp section
+ {
+ BMIter iter;
+ BMElemF *ele;
+ int i;
+
+ BLI_mempool *newpool = bm->vtoolflagpool;
+
+ /* now go through and memcpy all the flag */
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
+ void *oldflags = ele->oflags;
+ ele->oflags = BLI_mempool_calloc(newpool);
+ memcpy(ele->oflags, oldflags, new_totflags_size);
+ BM_elem_index_set(ele, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
+ }
+ }
+#pragma omp section
+ {
+ BMIter iter;
+ BMElemF *ele;
+ int i;
+
+ BLI_mempool *newpool = bm->etoolflagpool;
+
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
+ void *oldflags = ele->oflags;
+ ele->oflags = BLI_mempool_calloc(newpool);
+ memcpy(ele->oflags, oldflags, new_totflags_size);
+ BM_elem_index_set(ele, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
+ }
+ }
+#pragma omp section
+ {
+ BMIter iter;
+ BMElemF *ele;
+ int i;
+
+ BLI_mempool *newpool = bm->ftoolflagpool;
+
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
+ void *oldflags = ele->oflags;
+ ele->oflags = BLI_mempool_calloc(newpool);
+ memcpy(ele->oflags, oldflags, new_totflags_size);
+ BM_elem_index_set(ele, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele);
+ }
+ }
}
- bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE);
+ BLI_mempool_destroy(voldpool);
+ BLI_mempool_destroy(eoldpool);
+ BLI_mempool_destroy(foldpool);
- BLI_mempool_destroy(oldpool);
+ bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE);
}
static void bmo_flag_layer_clear(BMesh *bm)
@@ -1261,28 +1321,41 @@ static void bmo_flag_layer_clear(BMesh *bm)
/* set the index values since we are looping over all data anyway,
* may save time later on */
int i;
+ const BMFlagLayer zero_flag = {0};
BMIter iter;
const int totflags_offset = bm->totflags - 1;
- /* now go through and memcpy all the flags */
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
- memset(ele->oflags + totflags_offset, 0, sizeof(BMFlagLayer));
- BM_elem_index_set(ele, i); /* set_inline */
- }
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
- memset(ele->oflags + totflags_offset, 0, sizeof(BMFlagLayer));
- BM_elem_index_set(ele, i); /* set_inline */
- }
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
- memset(ele->oflags + totflags_offset, 0, sizeof(BMFlagLayer));
- BM_elem_index_set(ele, i); /* set_inline */
+#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)
+ {
+ /* now go through and memcpy all the flag */
+#pragma omp section
+ {
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
+ ele->oflags[totflags_offset] = zero_flag;
+ BM_elem_index_set(ele, i); /* set_inline */
+ }
+ }
+#pragma omp section
+ {
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
+ ele->oflags[totflags_offset] = zero_flag;
+ BM_elem_index_set(ele, i); /* set_inline */
+ }
+ }
+#pragma omp section
+ {
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
+ ele->oflags[totflags_offset] = zero_flag;
+ BM_elem_index_set(ele, i); /* set_inline */
+ }
+ }
}
bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE);
}
-void *BMO_slot_buffer_elem_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
+void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
@@ -1407,7 +1480,7 @@ void BMO_error_raise(BMesh *bm, BMOperator *owner, int errcode, const char *msg)
BLI_addhead(&bm->errorstack, err);
}
-int BMO_error_occurred(BMesh *bm)
+bool BMO_error_occurred(BMesh *bm)
{
return bm->errorstack.first != NULL;
}
@@ -1448,7 +1521,7 @@ static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char
int i = 0;
while (slot_args->slot_name) {
- if (strncmp(identifier, slot_args->slot_name, MAX_SLOTNAME) == 0) {
+ if (STREQLEN(identifier, slot_args->slot_name, MAX_SLOTNAME)) {
return i;
}
slot_args++;
@@ -1473,7 +1546,7 @@ static int bmo_opname_to_opcode(const char *opname)
int i;
for (i = 0; i < bmo_opdefines_total; i++) {
- if (!strcmp(opname, bmo_opdefines[i]->opname)) {
+ if (STREQ(opname, bmo_opdefines[i]->opname)) {
return i;
}
}
@@ -1513,7 +1586,7 @@ static int bmo_opname_to_opcode(const char *opname)
* **Utility**
*
* Pass an existing slot which is copied to either an input or output slot.
- * Taking the operator and slot-name pair of args.
+ * Taking the operator and slot-name pair of args (BMOperator *, const char *).
* - `s` - slot_in (lower case)
* - `S` - slot_out (upper case)
*
@@ -1541,7 +1614,7 @@ static int bmo_opname_to_opcode(const char *opname)
* Order is not important so `Hfev` is also valid (all unflagged verts, edges and faces).
*/
-int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, va_list vlist)
+bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, va_list vlist)
{
// BMOpDefine *def;
char *opname, *ofmt, *fmt;
@@ -1578,7 +1651,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v
if (i == -1) {
MEM_freeN(ofmt);
- return FALSE;
+ return false;
}
BMO_op_init(bm, op, flag, opname);
@@ -1741,7 +1814,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v
}
MEM_freeN(ofmt);
- return TRUE;
+ return true;
error:
/* non urgent todo - explain exactly what is failing */
@@ -1766,14 +1839,14 @@ error:
MEM_freeN(ofmt);
BMO_op_finish(bm, op);
- return FALSE;
+ return false;
#undef GOTO_ERROR
}
-int BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ...)
+bool BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ...)
{
va_list list;
@@ -1781,14 +1854,14 @@ int BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ...
if (!BMO_op_vinitf(bm, op, flag, fmt, list)) {
printf("%s: failed\n", __func__);
va_end(list);
- return FALSE;
+ return false;
}
va_end(list);
- return TRUE;
+ return true;
}
-int BMO_op_callf(BMesh *bm, const int flag, const char *fmt, ...)
+bool BMO_op_callf(BMesh *bm, const int flag, const char *fmt, ...)
{
va_list list;
BMOperator op;
@@ -1797,12 +1870,12 @@ int BMO_op_callf(BMesh *bm, const int flag, const char *fmt, ...)
if (!BMO_op_vinitf(bm, &op, flag, fmt, list)) {
printf("%s: failed, format is:\n \"%s\"\n", __func__, fmt);
va_end(list);
- return FALSE;
+ return false;
}
BMO_op_exec(bm, &op);
BMO_op_finish(bm, &op);
va_end(list);
- return TRUE;
+ return true;
}
diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h
index d02b0dce728..16b38c340ff 100644
--- a/source/blender/bmesh/intern/bmesh_operators.h
+++ b/source/blender/bmesh/intern/bmesh_operators.h
@@ -60,7 +60,10 @@ enum {
SIMFACE_SIDES,
SIMFACE_PERIMETER,
SIMFACE_NORMAL,
- SIMFACE_COPLANAR
+ SIMFACE_COPLANAR,
+#ifdef WITH_FREESTYLE
+ SIMFACE_FREESTYLE
+#endif
};
/* similar edge selection slot values */
@@ -72,7 +75,10 @@ enum {
SIMEDGE_CREASE,
SIMEDGE_BEVEL,
SIMEDGE_SEAM,
- SIMEDGE_SHARP
+ SIMEDGE_SHARP,
+#ifdef WITH_FREESTYLE
+ SIMEDGE_FREESTYLE
+#endif
};
/* similar vertex selection slot values */
diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h
index 9175af1c822..1aa4383d761 100644
--- a/source/blender/bmesh/intern/bmesh_operators_private.h
+++ b/source/blender/bmesh/intern/bmesh_operators_private.h
@@ -30,9 +30,6 @@
struct BMesh;
struct BMOperator;
-void BMO_push(BMesh *bm, BMOperator *op);
-void BMO_pop(BMesh *bm);
-
void bmo_automerge_exec(BMesh *bm, BMOperator *op);
void bmo_average_vert_facedata_exec(BMesh *bm, BMOperator *op);
void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op);
@@ -89,7 +86,6 @@ void bmo_shortest_path_exec(BMesh *bm, BMOperator *op);
void bmo_similar_edges_exec(BMesh *bm, BMOperator *op);
void bmo_similar_faces_exec(BMesh *bm, BMOperator *op);
void bmo_similar_verts_exec(BMesh *bm, BMOperator *op);
-void bmo_slide_vert_exec(BMesh *bm, BMOperator *op);
void bmo_smooth_vert_exec(BMesh *bm, BMOperator *op);
void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op);
void bmo_solidify_face_region_exec(BMesh *bm, BMOperator *op);
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index 953e7f4d20c..d235aaaa622 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -35,12 +35,17 @@
* degenerate faces.
*/
-#include "BLI_math.h"
-#include "BLI_array.h"
+#include "DNA_listBase.h"
#include "MEM_guardedalloc.h"
+#include "BLI_math.h"
+#include "BLI_array.h"
+#include "BLI_scanfill.h"
+#include "BLI_listbase.h"
+
#include "bmesh.h"
+
#include "intern/bmesh_private.h"
/**
@@ -50,7 +55,7 @@
* Used for tessellator
*/
-static short testedgesidef(const float v1[2], const float v2[2], const float v3[2])
+static bool testedgesidef(const float v1[2], const float v2[2], const float v3[2])
{
/* is v3 to the right of v1 - v2 ? With exception: v3 == v1 || v3 == v2 */
double inp;
@@ -59,13 +64,13 @@ static short testedgesidef(const float v1[2], const float v2[2], const float v3[
inp = (v2[0] - v1[0]) * (v1[1] - v3[1]) + (v1[1] - v2[1]) * (v1[0] - v3[0]);
if (inp < 0.0) {
- return FALSE;
+ return false;
}
else if (inp == 0) {
- if (v1[0] == v3[0] && v1[1] == v3[1]) return FALSE;
- if (v2[0] == v3[0] && v2[1] == v3[1]) return FALSE;
+ if (v1[0] == v3[0] && v1[1] == v3[1]) return false;
+ if (v2[0] == v3[0] && v2[1] == v3[1]) return false;
}
- return TRUE;
+ return true;
}
/**
@@ -151,6 +156,103 @@ static void bm_face_calc_poly_normal_vertex_cos(BMFace *f, float n[3],
}
/**
+ * For tools that insist on using triangles, ideally we would cache this data.
+ *
+ * \param r_loops Store face loop pointers, (f->len)
+ * \param r_index Store triangle triples, indicies into \a r_loops, ((f->len - 2) * 3)
+ */
+int BM_face_calc_tessellation(BMFace *f, BMLoop **r_loops, int (*_r_index)[3])
+{
+ int *r_index = (int *)_r_index;
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter;
+ int totfilltri;
+
+ if (f->len == 3) {
+ *r_loops++ = (l_iter = l_first);
+ *r_loops++ = (l_iter = l_iter->next);
+ *r_loops++ = ( l_iter->next);
+
+ r_index[0] = 0;
+ r_index[1] = 1;
+ r_index[2] = 2;
+ totfilltri = 1;
+ }
+ else if (f->len == 4) {
+ *r_loops++ = (l_iter = l_first);
+ *r_loops++ = (l_iter = l_iter->next);
+ *r_loops++ = (l_iter = l_iter->next);
+ *r_loops++ = ( l_iter->next);
+
+ r_index[0] = 0;
+ r_index[1] = 1;
+ r_index[2] = 2;
+
+ r_index[3] = 0;
+ r_index[4] = 2;
+ r_index[5] = 3;
+ totfilltri = 2;
+ }
+ else {
+ int j;
+
+ ScanFillContext sf_ctx;
+ ScanFillVert *sf_vert, *sf_vert_last = NULL, *sf_vert_first = NULL;
+ /* ScanFillEdge *e; */ /* UNUSED */
+ ScanFillFace *sf_tri;
+
+ BLI_scanfill_begin(&sf_ctx);
+
+ j = 0;
+ l_iter = l_first;
+ do {
+ sf_vert = BLI_scanfill_vert_add(&sf_ctx, l_iter->v->co);
+ sf_vert->tmp.p = l_iter;
+
+ if (sf_vert_last) {
+ /* e = */ BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
+ }
+
+ sf_vert_last = sf_vert;
+ if (sf_vert_first == NULL) {
+ sf_vert_first = sf_vert;
+ }
+
+ r_loops[j] = l_iter;
+
+ /* mark order */
+ BM_elem_index_set(l_iter, j++); /* set_loop */
+
+ } while ((l_iter = l_iter->next) != l_first);
+
+ /* complete the loop */
+ BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
+
+ totfilltri = BLI_scanfill_calc_ex(&sf_ctx, 0, f->no);
+ BLI_assert(totfilltri <= f->len - 2);
+ BLI_assert(totfilltri == BLI_countlist(&sf_ctx.fillfacebase));
+
+ for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
+ int i1 = BM_elem_index_get((BMLoop *)sf_tri->v1->tmp.p);
+ int i2 = BM_elem_index_get((BMLoop *)sf_tri->v2->tmp.p);
+ int i3 = BM_elem_index_get((BMLoop *)sf_tri->v3->tmp.p);
+
+ if (i1 > i2) { SWAP(int, i1, i2); }
+ if (i2 > i3) { SWAP(int, i2, i3); }
+ if (i1 > i2) { SWAP(int, i1, i2); }
+
+ *r_index++ = i1;
+ *r_index++ = i2;
+ *r_index++ = i3;
+ }
+
+ BLI_scanfill_end(&sf_ctx);
+ }
+
+ return totfilltri;
+}
+
+/**
* get the area of the face
*/
float BM_face_calc_area(BMFace *f)
@@ -158,7 +260,6 @@ float BM_face_calc_area(BMFace *f)
BMLoop *l;
BMIter iter;
float (*verts)[3] = BLI_array_alloca(verts, f->len);
- float normal[3];
float area;
int i;
@@ -173,6 +274,7 @@ float BM_face_calc_area(BMFace *f)
area = area_quad_v3(verts[0], verts[1], verts[2], verts[3]);
}
else {
+ float normal[3];
calc_poly_normal(normal, verts, f->len);
area = area_poly_v3(f->len, verts, normal);
}
@@ -297,7 +399,6 @@ static void scale_edge_v3f(float v1[3], float v2[3], const float fac)
add_v3_v3v3(v2, v2, mid);
}
-
/**
* \brief POLY ROTATE PLANE
*
@@ -306,30 +407,14 @@ static void scale_edge_v3f(float v1[3], float v2[3], const float fac)
*/
void poly_rotate_plane(const float normal[3], float (*verts)[3], const int nverts)
{
-
- float up[3] = {0.0f, 0.0f, 1.0f}, axis[3], q[4];
float mat[3][3];
- float angle;
- int i;
-
- cross_v3_v3v3(axis, normal, up);
-
- angle = saacos(dot_v3v3(normal, up));
- if (angle < FLT_EPSILON)
- return;
-
- if (len_v3(axis) < FLT_EPSILON) {
- axis[0] = 0.0f;
- axis[1] = 1.0f;
- axis[2] = 0.0f;
+ if (axis_dominant_v3_to_m3(mat, normal)) {
+ int i;
+ for (i = 0; i < nverts; i++) {
+ mul_m3_v3(mat, verts[i]);
+ }
}
-
- axis_angle_to_quat(q, axis, angle);
- quat_to_mat3(mat, q);
-
- for (i = 0; i < nverts; i++)
- mul_m3_v3(mat, verts[i]);
}
/**
@@ -498,7 +583,7 @@ void BM_face_normal_flip(BMesh *bm, BMFace *f)
/* detects if two line segments cross each other (intersects).
* note, there could be more winding cases then there needs to be. */
-static int line_crosses_v2f(const float v1[2], const float v2[2], const float v3[2], const float v4[2])
+static bool line_crosses_v2f(const float v1[2], const float v2[2], const float v3[2], const float v4[2])
{
#define GETMIN2_AXIS(a, b, ma, mb, axis) \
@@ -526,7 +611,7 @@ static int line_crosses_v2f(const float v1[2], const float v2[2], const float v3
w5 = !testedgesidef(v3, v1, v4);
if (w1 == w2 && w2 == w3 && w3 == w4 && w4 == w5) {
- return TRUE;
+ return true;
}
GETMIN2(v1, v2, mv1, mv2);
@@ -549,7 +634,7 @@ static int line_crosses_v2f(const float v1[2], const float v2[2], const float v3
return (mv4[1] >= mv1[1] && mv3[1] <= mv2[1]);
}
- return FALSE;
+ return false;
#undef GETMIN2_AXIS
#undef GETMIN2
@@ -567,7 +652,7 @@ static int line_crosses_v2f(const float v1[2], const float v2[2], const float v3
* instead of projecting co directly into f's orientation space,
* so there might be accuracy issues.
*/
-int BM_face_point_inside_test(BMFace *f, const float co[3])
+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};
@@ -614,26 +699,26 @@ int BM_face_point_inside_test(BMFace *f, const float co[3])
return crosses % 2 != 0;
}
-static int bm_face_goodline(float const (*projectverts)[3], BMFace *f, int v1i, int v2i, int v3i)
+static bool bm_face_goodline(float const (*projectverts)[2], BMFace *f, int v1i, int v2i, int v3i)
{
BMLoop *l_iter;
BMLoop *l_first;
- float v1[3], v2[3], v3[3], pv1[3];
- int i;
- copy_v3_v3(v1, projectverts[v1i]);
- copy_v3_v3(v2, projectverts[v2i]);
- copy_v3_v3(v3, projectverts[v3i]);
+ float pv1[2];
+ const float *v1 = projectverts[v1i];
+ const float *v2 = projectverts[v2i];
+ const float *v3 = projectverts[v3i];
+ int i;
/* v3 must be on the left side of [v1, v2] line, else we know [v1, v3] is outside of f! */
if (testedgesidef(v1, v2, v3)) {
- return FALSE;
+ return false;
}
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
i = BM_elem_index_get(l_iter->v);
- copy_v3_v3(pv1, projectverts[i]);
+ copy_v2_v2(pv1, projectverts[i]);
if (ELEM3(i, v1i, v2i, v3i)) {
#if 0
@@ -649,23 +734,24 @@ static int bm_face_goodline(float const (*projectverts)[3], BMFace *f, int v1i,
else
printf("%d in (%d, %d, %d)\n", v1i, i, v3i, v2i);
#endif
- return FALSE;
+ return false;
}
} while ((l_iter = l_iter->next) != l_first);
- return TRUE;
+ return true;
}
/**
* \brief Find Ear
*
* Used by tessellator to find the next triangle to 'clip off' of a polygon while tessellating.
+ *
* \param f The face to search.
- * \param verts an array of face vert coords.
+ * \param projectverts an array of face vert coords.
* \param use_beauty Currently only applies to quads, can be extended later on.
* \param abscoss Must be allocated by caller, and at least f->len length
* (allow to avoid allocating a new one for each tri!).
*/
-static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, float *abscoss)
+static BMLoop *poly_find_ear(BMFace *f, float (*projectverts)[2], const bool use_beauty, float *abscoss)
{
BMLoop *bestear = NULL;
@@ -690,7 +776,7 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa
i = (((len_squared_v3v3(larr[0]->v->co, larr[2]->v->co) >
len_squared_v3v3(larr[1]->v->co, larr[3]->v->co) * bias)) != use_beauty);
i4 = (i + 3) % 4;
- /* Check produced tris aren’t too flat/narrow...
+ /* Check produced tris aren't too flat/narrow...
* Probably not the best test, but is quite efficient and should at least avoid null-area faces! */
cos1 = fabsf(cos_v3v3v3(larr[i4]->v->co, larr[i]->v->co, larr[i + 1]->v->co));
cos2 = fabsf(cos_v3v3v3(larr[i4]->v->co, larr[i + 2]->v->co, larr[i + 1]->v->co));
@@ -711,7 +797,7 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa
/* Last check we do not get overlapping triangles
* (as much as possible, there are some cases with no good solution!) */
i4 = (i + 3) % 4;
- if (!bm_face_goodline((float const (*)[3])verts, f, BM_elem_index_get(larr[i4]->v),
+ if (!bm_face_goodline((float const (*)[2])projectverts, f, BM_elem_index_get(larr[i4]->v),
BM_elem_index_get(larr[i]->v), BM_elem_index_get(larr[i + 1]->v)))
{
i = !i;
@@ -721,77 +807,44 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa
}
else {
- BMVert *v1, *v2, *v3;
-
/* float angle, bestangle = 180.0f; */
- float cos, tcos, bestcos = 1.0f;
- float *tcoss;
- int isear, i = 0, j, len;
+ float cos, bestcos = 1.0f;
+ int i, j, len;
/* Compute cos of all corners! */
+ i = 0;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
len = l_iter->f->len;
- tcoss = abscoss;
do {
- v1 = l_iter->prev->v;
- v2 = l_iter->v;
- v3 = l_iter->next->v;
+ const BMVert *v1 = l_iter->prev->v;
+ const BMVert *v2 = l_iter->v;
+ const BMVert *v3 = l_iter->next->v;
- *tcoss = fabsf(cos_v3v3v3(v1->co, v2->co, v3->co));
+ abscoss[i] = fabsf(cos_v3v3v3(v1->co, v2->co, v3->co));
/* printf("tcoss: %f\n", *tcoss);*/
- tcoss++;
+ i++;
} while ((l_iter = l_iter->next) != l_first);
+ i = 0;
l_iter = l_first;
- tcoss = abscoss;
do {
- isear = TRUE;
+ const BMVert *v1 = l_iter->prev->v;
+ const BMVert *v2 = l_iter->v;
+ const BMVert *v3 = l_iter->next->v;
- v1 = l_iter->prev->v;
- v2 = l_iter->v;
- v3 = l_iter->next->v;
-
- /* We may have already internal edges... */
- if (BM_edge_exists(v1, v3)) {
- isear = FALSE;
- }
- else if (!bm_face_goodline((float const (*)[3])verts, f, BM_elem_index_get(v1),
- BM_elem_index_get(v2), BM_elem_index_get(v3)))
+ if (bm_face_goodline((float const (*)[2])projectverts, f,
+ BM_elem_index_get(v1), BM_elem_index_get(v2), BM_elem_index_get(v3)))
{
-#if 0
- printf("(%d, %d, %d) would not be a valid tri!\n",
- BM_elem_index_get(v1), BM_elem_index_get(v2), BM_elem_index_get(v3));
-#endif
- isear = FALSE;
- }
-
- if (isear) {
-#if 0 /* Old, already commented code */
- /* if this code comes back, it needs to be converted to radians */
- angle = angle_v3v3v3(verts[v1->head.eflag2], verts[v2->head.eflag2], verts[v3->head.eflag2]);
- if (!bestear || ABS(angle - 45.0f) < bestangle) {
- bestear = l;
- bestangle = ABS(45.0f - angle);
- }
-
- if (angle > 20 && angle < 90) break;
- if (angle < 100 && i > 5) break;
- i += 1;
-#endif
-
/* Compute highest cos (i.e. narrowest angle) of this tri. */
- cos = *tcoss;
- tcos = fabsf(cos_v3v3v3(v2->co, v3->co, v1->co));
- if (tcos > cos)
- cos = tcos;
- tcos = fabsf(cos_v3v3v3(v3->co, v1->co, v2->co));
- if (tcos > cos)
- cos = tcos;
+ cos = max_fff(abscoss[i],
+ fabsf(cos_v3v3v3(v2->co, v3->co, v1->co)),
+ fabsf(cos_v3v3v3(v3->co, v1->co, v2->co)));
/* Compare to prev best (i.e. lowest) cos. */
if (cos < bestcos) {
/* We must check this tri would not leave a (too much) degenerated remaining face! */
- /* For now just assume if the average of cos of all "remaining face"'s corners is below a given threshold, it’s OK. */
+ /* For now just assume if the average of cos of all
+ * "remaining face"'s corners is below a given threshold, it's OK. */
float avgcos = fabsf(cos_v3v3v3(v1->co, v3->co, l_iter->next->next->v->co));
const int i_limit = (i - 1 + len) % len;
avgcos += fabsf(cos_v3v3v3(l_iter->prev->prev->v->co, v1->co, v3->co));
@@ -815,7 +868,6 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa
#endif
}
}
- tcoss++;
i++;
} while ((l_iter = l_iter->next) != l_first);
}
@@ -826,120 +878,71 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa
/**
* \brief BMESH TRIANGULATE FACE
*
- * --- Prev description (wasn’t correct, ear clipping was currently simply picking the first tri in the loop!)
- * Triangulates a face using a simple 'ear clipping' algorithm that tries to
- * favor non-skinny triangles (angles less than 90 degrees).
- *
- * If the triangulator has bits left over (or cannot triangulate at all)
- * it uses a simple fan triangulation,
- * --- End of prev description
- *
- * Currently tries to repeatedly find the best triangle (i.e. the most "open" one), provided it does not
+ * Currently repeatedly find the best triangle (i.e. the most "open" one), provided it does not
* produces a "remaining" face with too much wide/narrow angles
* (using cos (i.e. dot product of normalized vectors) of angles).
*
- * newfaces, if non-null, must be an array of BMFace pointers,
- * with a length equal to f->len. It will be filled with the new
- * triangles, and will be NULL-terminated.
+ * \param r_faces_new if non-null, must be an array of BMFace pointers,
+ * with a length equal to (f->len - 2). It will be filled with the new
+ * triangles.
*
- * \note newedgeflag sets a flag layer flag, obviously not the header flag.
+ * \note use_tag tags new flags and edges.
*/
-void BM_face_triangulate(BMesh *bm, BMFace *f, float (*projectverts)[3], const short newedge_oflag,
- const short newface_oflag, BMFace **newfaces, const short use_beauty)
+void BM_face_triangulate(BMesh *bm, BMFace *f,
+ BMFace **r_faces_new,
+ const bool use_beauty, const bool use_tag)
{
- int i, done, nvert, nf_i = 0;
- BMLoop *newl;
+ const float f_len_orig = f->len;
+ int i, nf_i = 0;
+ BMLoop *l_new;
BMLoop *l_iter;
BMLoop *l_first;
/* BM_face_triangulate: temp absolute cosines of face corners */
- float *abscoss = BLI_array_alloca(abscoss, f->len);
+ float (*projectverts)[2] = BLI_array_alloca(projectverts, f_len_orig);
+ float *abscoss = BLI_array_alloca(abscoss, f_len_orig);
+ float mat[3][3];
+
+ axis_dominant_v3_to_m3(mat, f->no);
/* copy vertex coordinates to vertspace area */
i = 0;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
- copy_v3_v3(projectverts[i], l_iter->v->co);
- BM_elem_index_set(l_iter->v, i); /* set dirty! */
- i++;
+ mul_v2_m3v3(projectverts[i], mat, l_iter->v->co);
+ BM_elem_index_set(l_iter->v, i++); /* set dirty! */
} while ((l_iter = l_iter->next) != l_first);
bm->elem_index_dirty |= BM_VERT; /* see above */
- /* bmesh_face_normal_update(bm, f, f->no, projectverts); */
-
- calc_poly_normal(f->no, projectverts, f->len);
- poly_rotate_plane(f->no, projectverts, i);
+ while (f->len > 3) {
+ l_iter = poly_find_ear(f, projectverts, use_beauty, abscoss);
- nvert = f->len;
-
- /* calc_poly_plane(projectverts, i); */
- for (i = 0; i < nvert; i++) {
- projectverts[i][2] = 0.0f;
- }
+ /* force triangulation - if we can't find an ear the face is degenerate */
+ if (l_iter == NULL) {
+ l_iter = BM_FACE_FIRST_LOOP(f);
+ }
- done = FALSE;
- while (!done && f->len > 3) {
- done = TRUE;
- l_iter = find_ear(f, projectverts, use_beauty, abscoss);
- if (l_iter) {
- done = FALSE;
-/* printf("Subdividing face...\n");*/
- f = BM_face_split(bm, l_iter->f, l_iter->prev->v, l_iter->next->v, &newl, NULL, TRUE);
-
- if (UNLIKELY(!f)) {
- fprintf(stderr, "%s: triangulator failed to split face! (bmesh internal error)\n", __func__);
- break;
- }
+/* printf("Subdividing face...\n");*/
+ f = BM_face_split(bm, l_iter->f, l_iter->prev->v, l_iter->next->v, &l_new, NULL, true);
- copy_v3_v3(f->no, l_iter->f->no);
- BMO_elem_flag_enable(bm, newl->e, newedge_oflag);
- BMO_elem_flag_enable(bm, f, newface_oflag);
-
- if (newfaces)
- newfaces[nf_i++] = f;
+ if (UNLIKELY(!f)) {
+ fprintf(stderr, "%s: triangulator failed to split face! (bmesh internal error)\n", __func__);
+ break;
+ }
-#if 0
- l = f->loopbase;
- do {
- if (l->v == v) {
- f->loopbase = l;
- break;
- }
- l = l->next;
- } while (l != f->loopbase);
-#endif
+ copy_v3_v3(f->no, l_iter->f->no);
+ if (use_tag) {
+ BM_elem_flag_enable(l_new->e, BM_ELEM_TAG);
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
}
- }
-
-#if 0 /* XXX find_ear should now always return a corner, so no more need for this piece of code... */
- if (f->len > 3) {
- l_iter = BM_FACE_FIRST_LOOP(f);
- while (l_iter->f->len > 3) {
- nextloop = l_iter->next->next;
- f = BM_face_split(bm, l_iter->f, l_iter->v, nextloop->v,
- &newl, NULL, TRUE);
- if (!f) {
- printf("triangle fan step of triangulator failed.\n");
-
- /* NULL-terminate */
- if (newfaces) newfaces[nf_i] = NULL;
- return;
- }
- if (newfaces) newfaces[nf_i++] = f;
-
- BMO_elem_flag_enable(bm, newl->e, newedge_oflag);
- BMO_elem_flag_enable(bm, f, newface_oflag);
- l_iter = nextloop;
+ if (r_faces_new) {
+ r_faces_new[nf_i++] = f;
}
}
-#endif
- /* NULL-terminate */
- if (newfaces) {
- newfaces[nf_i] = NULL;
- }
+ BLI_assert(f->len == 3);
}
/**
@@ -1078,3 +1081,37 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len)
}
}
}
+
+
+/**
+ * Small utility functions for fast access
+ *
+ * faster alternative to:
+ * BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void **)v, 3);
+ */
+void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3])
+{
+ BMLoop *l = BM_FACE_FIRST_LOOP(f);
+
+ BLI_assert(f->len == 3);
+
+ r_verts[0] = l->v; l = l->next;
+ r_verts[1] = l->v; l = l->next;
+ r_verts[2] = l->v;
+}
+
+/**
+ * faster alternative to:
+ * BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void **)v, 4);
+ */
+void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4])
+{
+ BMLoop *l = BM_FACE_FIRST_LOOP(f);
+
+ BLI_assert(f->len == 4);
+
+ r_verts[0] = l->v; l = l->next;
+ r_verts[1] = l->v; l = l->next;
+ r_verts[2] = l->v; l = l->next;
+ r_verts[3] = l->v;
+}
diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h
index e5777d3611b..c439a41f672 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.h
+++ b/source/blender/bmesh/intern/bmesh_polygon.h
@@ -27,6 +27,12 @@
* \ingroup bmesh
*/
+int BM_face_calc_tessellation(BMFace *f, BMLoop **r_loops, int (*r_index)[3])
+#ifdef __GNUC__
+ __attribute__((warn_unused_result))
+ __attribute__((nonnull))
+#endif
+;
float BM_face_calc_area(BMFace *f);
float BM_face_calc_perimeter(BMFace *f);
void BM_face_calc_center_bounds(BMFace *f, float center[3]);
@@ -42,12 +48,14 @@ void BM_vert_normal_update(BMVert *v);
void BM_vert_normal_update_all(BMVert *v);
void BM_face_normal_flip(BMesh *bm, BMFace *f);
-int BM_face_point_inside_test(BMFace *f, const float co[3]);
+bool BM_face_point_inside_test(BMFace *f, const float co[3]);
-void BM_face_triangulate(BMesh *bm, BMFace *f, float (*projectverts)[3],
- const short newedge_oflag, const short newface_oflag, BMFace **newfaces,
- const short use_beauty);
+void BM_face_triangulate(BMesh *bm, BMFace *f, BMFace **newfaces,
+ const bool use_beauty, const bool use_tag);
void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len);
+void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3]);
+void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4]);
+
#endif /* __BMESH_POLYGON_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 633c715f257..26b0e42a1c1 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -43,7 +43,7 @@
* Returns whether or not a given vertex is
* is part of a given edge.
*/
-int BM_vert_in_edge(BMEdge *e, BMVert *v)
+bool BM_vert_in_edge(BMEdge *e, BMVert *v)
{
return bmesh_vert_in_edge(e, v);
}
@@ -208,9 +208,9 @@ BMLoop *BM_vert_find_first_loop(BMVert *v)
}
/**
- * Returns TRUE if the vertex is used in a given face.
+ * Returns true if the vertex is used in a given face.
*/
-int BM_vert_in_face(BMFace *f, BMVert *v)
+bool BM_vert_in_face(BMFace *f, BMVert *v)
{
BMLoop *l_iter, *l_first;
@@ -226,19 +226,19 @@ int BM_vert_in_face(BMFace *f, BMVert *v)
#endif
do {
if (l_iter->v == v) {
- return TRUE;
+ return true;
}
} while ((l_iter = l_iter->next) != l_first);
}
- return FALSE;
+ return false;
}
/**
* Compares the number of vertices in an array
* that appear in a given face
*/
-int BM_verts_in_face(BMFace *f, BMVert **varr, int len)
+int BM_verts_in_face_count(BMFace *f, BMVert **varr, int len)
{
BMLoop *l_iter, *l_first;
@@ -278,10 +278,64 @@ int BM_verts_in_face(BMFace *f, BMVert **varr, int len)
return count;
}
+
+/**
+ * Return true if all verts are in the face.
+ */
+bool BM_verts_in_face(BMFace *f, BMVert **varr, int len)
+{
+ BMLoop *l_iter, *l_first;
+
+#ifdef USE_BMESH_HOLES
+ BMLoopList *lst;
+#endif
+
+ int i;
+ bool ok = true;
+
+ /* simple check, we know can't succeed */
+ if (f->len < len) {
+ return false;
+ }
+
+ for (i = 0; i < len; i++) {
+ BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP);
+ }
+
+#ifdef USE_BMESH_HOLES
+ for (lst = f->loops.first; lst; lst = lst->next)
+#endif
+ {
+
+#ifdef USE_BMESH_HOLES
+ l_iter = l_first = lst->first;
+#else
+ l_iter = l_first = f->l_first;
+#endif
+
+ do {
+ if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) {
+ /* pass */
+ }
+ else {
+ ok = false;
+ break;
+ }
+
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ for (i = 0; i < len; i++) {
+ BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP);
+ }
+
+ return ok;
+}
+
/**
* Returns whether or not a given edge is is part of a given face.
*/
-int BM_edge_in_face(BMFace *f, BMEdge *e)
+bool BM_edge_in_face(BMFace *f, BMEdge *e)
{
BMLoop *l_iter;
BMLoop *l_first;
@@ -290,17 +344,17 @@ int BM_edge_in_face(BMFace *f, BMEdge *e)
do {
if (l_iter->e == e) {
- return TRUE;
+ return true;
}
} while ((l_iter = l_iter->next) != l_first);
- return FALSE;
+ return false;
}
/**
* Returns whether or not a given edge is is part of a given loop.
*/
-int BM_edge_in_loop(BMEdge *e, BMLoop *l)
+bool BM_edge_in_loop(BMEdge *e, BMLoop *l)
{
return (l->e == e || l->prev->e == e);
}
@@ -309,7 +363,7 @@ int BM_edge_in_loop(BMEdge *e, BMLoop *l)
* Returns whether or not two vertices are in
* a given edge
*/
-int BM_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e)
+bool BM_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e)
{
return bmesh_verts_in_edge(v1, v2, e);
}
@@ -418,7 +472,7 @@ BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step)
* The function takes a vertex at the center of a fan and returns the opposite edge in the fan.
* All edges in the fan must be manifold, otherwise return NULL.
*
- * \note This could (probably) be done more effieiently.
+ * \note This could (probably) be done more efficiently.
*/
BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e_first)
{
@@ -468,7 +522,7 @@ BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e_first)
}
/**
- * Returms edge length
+ * Returns edge length
*/
float BM_edge_calc_length(BMEdge *e)
{
@@ -476,12 +530,20 @@ float BM_edge_calc_length(BMEdge *e)
}
/**
+ * Returns edge length squared (for comparisons)
+ */
+float BM_edge_calc_length_squared(BMEdge *e)
+{
+ return len_squared_v3v3(e->v1->co, e->v2->co);
+}
+
+/**
* Utility function, since enough times we have an edge
* and want to access 2 connected faces.
*
- * \return TRUE when only 2 faces are found.
+ * \return true when only 2 faces are found.
*/
-int BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb)
+bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb)
{
BMLoop *la, *lb;
@@ -492,12 +554,12 @@ int BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb)
{
*r_fa = la->f;
*r_fb = lb->f;
- return TRUE;
+ return true;
}
else {
*r_fa = NULL;
*r_fb = NULL;
- return FALSE;
+ return false;
}
}
@@ -505,9 +567,9 @@ int BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb)
* Utility function, since enough times we have an edge
* and want to access 2 connected loops.
*
- * \return TRUE when only 2 faces are found.
+ * \return true when only 2 faces are found.
*/
-int BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb)
+bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb)
{
BMLoop *la, *lb;
@@ -518,12 +580,12 @@ int BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb)
{
*r_la = la;
*r_lb = lb;
- return TRUE;
+ return true;
}
else {
*r_la = NULL;
*r_lb = NULL;
- return FALSE;
+ return false;
}
}
@@ -581,7 +643,7 @@ int BM_vert_face_count(BMVert *v)
* Tests whether or not the vertex is part of a wire edge.
* (ie: has no faces attached to it)
*/
-int BM_vert_is_wire(BMVert *v)
+bool BM_vert_is_wire(BMVert *v)
{
if (v->e) {
BMEdge *e_first, *e_iter;
@@ -589,14 +651,14 @@ int BM_vert_is_wire(BMVert *v)
e_first = e_iter = v->e;
do {
if (e_iter->l) {
- return FALSE;
+ return false;
}
} while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
- return TRUE;
+ return true;
}
else {
- return FALSE;
+ return false;
}
}
@@ -604,9 +666,9 @@ int BM_vert_is_wire(BMVert *v)
* Tests whether or not the edge is part of a wire.
* (ie: has no faces attached to it)
*/
-int BM_edge_is_wire(BMEdge *e)
+bool BM_edge_is_wire(BMEdge *e)
{
- return (e->l) ? FALSE : TRUE;
+ return (e->l == NULL);
}
/**
@@ -616,36 +678,36 @@ int BM_edge_is_wire(BMEdge *e)
* 3: Is part of a an edge with more than 2 faces.
* 4: Is part of a wire edge.
*/
-int BM_vert_is_manifold(BMVert *v)
+bool BM_vert_is_manifold(BMVert *v)
{
- BMEdge *e, *oe;
+ BMEdge *e, *e_old;
BMLoop *l;
int len, count, flag;
if (v->e == NULL) {
/* loose vert */
- return FALSE;
+ return false;
}
/* count edges while looking for non-manifold edges */
len = 0;
- oe = e = v->e;
+ e_old = e = v->e;
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) {
- return FALSE;
+ return false;
}
len++;
- } while ((e = bmesh_disk_edge_next(e, v)) != oe);
+ } while ((e = bmesh_disk_edge_next(e, v)) != e_old);
count = 1;
flag = 1;
e = NULL;
- oe = v->e;
- l = oe->l;
- while (e != oe) {
+ 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 */
@@ -654,13 +716,13 @@ int BM_vert_is_manifold(BMVert *v)
/* we've hit the edge of an open mesh, reset once */
flag = 0;
count = 1;
- oe = e;
+ e_old = e;
e = NULL;
- l = oe->l;
+ l = e_old->l;
}
else if (l->radial_next == l) {
/* break the loop */
- e = oe;
+ e = e_old;
}
else {
l = l->radial_next;
@@ -669,10 +731,10 @@ int BM_vert_is_manifold(BMVert *v)
if (count < len) {
/* vert shared by multiple regions */
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
/**
@@ -681,7 +743,7 @@ int BM_vert_is_manifold(BMVert *v)
*/
#if 1 /* fast path for checking manifold */
-int BM_edge_is_manifold(BMEdge *e)
+bool BM_edge_is_manifold(BMEdge *e)
{
const BMLoop *l = e->l;
return (l && (l->radial_next != l) && /* not 0 or 1 face users */
@@ -692,21 +754,34 @@ int BM_edge_is_manifold(BMEdge *e)
{
int count = BM_edge_face_count(e);
if (count == 2) {
- return TRUE;
+ return true;
}
else {
- return FALSE;
+ return false;
}
}
#endif
/**
+ * Tests that the edge is manifold and
+ * that both its faces point the same way.
+ */
+bool BM_edge_is_contiguous(BMEdge *e)
+{
+ const BMLoop *l = e->l;
+ const BMLoop *l_other;
+ return (l && ((l_other = l->radial_next) != l) && /* not 0 or 1 face users */
+ (l_other->radial_next == l) && /* 2 face users */
+ (l_other->v != l->v));
+}
+
+/**
* Tests whether or not an edge is on the boundary
* of a shell (has one face associated with it)
*/
#if 1 /* fast path for checking boundary */
-int BM_edge_is_boundary(BMEdge *e)
+bool BM_edge_is_boundary(BMEdge *e)
{
const BMLoop *l = e->l;
return (l && (l->radial_next == l));
@@ -716,10 +791,10 @@ int BM_edge_is_boundary(BMEdge *e)
{
int count = BM_edge_face_count(e);
if (count == 1) {
- return TRUE;
+ return true;
}
else {
- return FALSE;
+ return false;
}
}
#endif
@@ -749,7 +824,7 @@ int BM_face_share_face_count(BMFace *f1, BMFace *f2)
/**
* same as #BM_face_share_face_count but returns a bool
*/
-int BM_face_share_face_check(BMFace *f1, BMFace *f2)
+bool BM_face_share_face_check(BMFace *f1, BMFace *f2)
{
BMIter iter1, iter2;
BMEdge *e;
@@ -758,11 +833,11 @@ int BM_face_share_face_check(BMFace *f1, BMFace *f2)
BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) {
BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) {
if (f != f1 && f != f2 && BM_face_share_edge_check(f, f2))
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
/**
@@ -785,9 +860,9 @@ int BM_face_share_edge_count(BMFace *f1, BMFace *f2)
}
/**
- * Returns TRUE if the faces share an edge
+ * Returns true if the faces share an edge
*/
-int BM_face_share_edge_check(BMFace *f1, BMFace *f2)
+bool BM_face_share_edge_check(BMFace *f1, BMFace *f2)
{
BMLoop *l_iter;
BMLoop *l_first;
@@ -795,17 +870,17 @@ int BM_face_share_edge_check(BMFace *f1, BMFace *f2)
l_iter = l_first = BM_FACE_FIRST_LOOP(f1);
do {
if (bmesh_radial_face_find(l_iter->e, f2)) {
- return TRUE;
+ return true;
}
} while ((l_iter = l_iter->next) != l_first);
- return FALSE;
+ return false;
}
/**
- * Test if e1 shares any faces with e2
+ * Test if e1 shares any faces with e2
*/
-int BM_edge_share_face_check(BMEdge *e1, BMEdge *e2)
+bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2)
{
BMLoop *l;
BMFace *f;
@@ -815,18 +890,18 @@ int BM_edge_share_face_check(BMEdge *e1, BMEdge *e2)
do {
f = l->f;
if (bmesh_radial_face_find(e2, f)) {
- return TRUE;
+ return true;
}
l = l->radial_next;
} while (l != e1->l);
}
- return FALSE;
+ return false;
}
/**
* Test if e1 shares any quad faces with e2
*/
-int BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2)
+bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2)
{
BMLoop *l;
BMFace *f;
@@ -837,19 +912,19 @@ int BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2)
f = l->f;
if (f->len == 4) {
if (bmesh_radial_face_find(e2, f)) {
- return TRUE;
+ return true;
}
}
l = l->radial_next;
} while (l != e1->l);
}
- return FALSE;
+ return false;
}
/**
* Tests to see if e1 shares a vertex with e2
*/
-int BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2)
+bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2)
{
return (e1->v1 == e2->v1 ||
e1->v1 == e2->v2 ||
@@ -945,6 +1020,22 @@ void BM_edge_ordered_verts(BMEdge *edge, BMVert **r_v1, BMVert **r_v2)
}
/**
+ * Check if the loop is convex or concave
+ * (depends on face normal)
+ */
+bool BM_loop_is_convex(BMLoop *l)
+{
+ float e_dir_prev[3];
+ float e_dir_next[3];
+ float l_no[3];
+
+ sub_v3_v3v3(e_dir_prev, l->prev->v->co, l->v->co);
+ sub_v3_v3v3(e_dir_next, l->next->v->co, l->v->co);
+ cross_v3_v3v3(l_no, e_dir_next, e_dir_prev);
+ return dot_v3v3(l_no, l->f->no) > 0.0f;
+}
+
+/**
* Calculates the angle between the previous and next loops
* (angle at this loops face corner).
*
@@ -972,7 +1063,7 @@ void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3])
l->v->co,
l->next->v->co) != 0.0f)
{
- return;
+ /* pass */
}
else {
copy_v3_v3(r_normal, l->f->no);
@@ -980,6 +1071,29 @@ void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3])
}
/**
+ * \brief BM_loop_calc_face_direction
+ *
+ * Calculate the direction a loop is pointing.
+ *
+ * \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])
+{
+ float v_prev[3];
+ float v_next[3];
+
+ sub_v3_v3v3(v_prev, l->v->co, l->prev->v->co);
+ sub_v3_v3v3(v_next, l->next->v->co, l->v->co);
+
+ normalize_v3(v_prev);
+ normalize_v3(v_next);
+
+ add_v3_v3v3(r_dir, v_prev, v_next);
+ normalize_v3(r_dir);
+}
+
+/**
* \brief BM_loop_calc_face_tangent
*
* Calculate the tangent at this loop corner or fallback to the face normal on straight lines.
@@ -992,23 +1106,27 @@ void BM_loop_calc_face_tangent(BMLoop *l, float r_tangent[3])
{
float v_prev[3];
float v_next[3];
+ float dir[3];
sub_v3_v3v3(v_prev, l->prev->v->co, l->v->co);
sub_v3_v3v3(v_next, l->v->co, l->next->v->co);
normalize_v3(v_prev);
normalize_v3(v_next);
+ add_v3_v3v3(dir, v_prev, v_next);
- if (compare_v3v3(v_prev, v_next, FLT_EPSILON) == FALSE) {
- float dir[3];
+ if (compare_v3v3(v_prev, v_next, FLT_EPSILON * 10.0f) == false) {
float nor[3]; /* for this purpose doesn't need to be normalized */
- add_v3_v3v3(dir, v_prev, v_next);
cross_v3_v3v3(nor, v_prev, v_next);
+ /* concave face check */
+ if (UNLIKELY(dot_v3v3(nor, l->f->no) < 0.0f)) {
+ negate_v3(nor);
+ }
cross_v3_v3v3(r_tangent, dir, nor);
}
else {
/* prev/next are the same - compare with face normal since we don't have one */
- cross_v3_v3v3(r_tangent, v_next, l->f->no);
+ cross_v3_v3v3(r_tangent, dir, l->f->no);
}
normalize_v3(r_tangent);
@@ -1113,6 +1231,40 @@ float BM_vert_calc_shell_factor(BMVert *v)
return 1.0f;
}
}
+/* 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)
+{
+ BMIter iter;
+ 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) {
+ 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_angle_to_dist(angle_normalized_v3v3(v->no, l->f->no)) * face_angle;
+ accum_angle += face_angle;
+ tot_sel++;
+ }
+ tot++;
+ }
+
+ if (accum_angle != 0.0f) {
+ return accum_shell / accum_angle;
+ }
+ else {
+ /* other main difference from BM_vert_calc_shell_factor! */
+ if (tot != 0 && tot_sel == 0) {
+ /* none selected, so use all */
+ return BM_vert_calc_shell_factor(v);
+ }
+ else {
+ return 1.0f;
+ }
+ }
+}
/**
* \note quite an obscure function.
@@ -1200,6 +1352,8 @@ BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2)
BMIter iter;
BMEdge *e;
+ BLI_assert(v1 != v2);
+
BM_ITER_ELEM (e, &iter, v1, BM_EDGES_OF_VERT) {
if (e->v1 == v2 || e->v2 == v2)
return e;
@@ -1231,67 +1385,94 @@ BMEdge *BM_edge_find_double(BMEdge *e)
}
/**
- * Given a set of vertices \a varr, find out if
- * all those vertices overlap an existing face.
- *
- * \note Making a face here is valid but in some cases you wont want to
- * make a face thats part of another.
- *
- * \returns TRUE for overlap
+ * Given a set of vertices (varr), find out if
+ * there is a face with exactly those vertices
+ * (and only those vertices).
*
+ * \note there used to be a BM_face_exists_overlap function that checked for partial overlap,
+ * however this is no longer used, simple to add back.
*/
-int BM_face_exists_overlap(BMVert **varr, int len, BMFace **r_overlapface)
+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 viter;
BMFace *f;
- int i, amount;
- for (i = 0; i < len; i++) {
- BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
- amount = BM_verts_in_face(f, varr, len);
- if (amount >= len) {
- if (r_overlapface) {
- *r_overlapface = f;
+
+#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;
+ return true;
}
}
}
- if (r_overlapface) {
- *r_overlapface = NULL;
+ if (r_existface) {
+ *r_existface = NULL;
}
+ return false;
- return FALSE;
-}
+#else
-/**
- * Given a set of vertices (varr), find out if
- * there is a face with exactly those vertices
- * (and only those vertices).
- */
-int BM_face_exists(BMVert **varr, int len, BMFace **r_existface)
-{
- BMIter viter;
- BMFace *f;
- int i, amount;
+ /* faster to do the flagging once, and inline */
+ bool is_init = false;
+ bool is_found = false;
+ int i;
- for (i = 0; i < len; i++) {
- BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
- amount = BM_verts_in_face(f, varr, len);
- if (amount == len && amount == f->len) {
+
+ BM_ITER_ELEM (f, &viter, v_search, BM_FACES_OF_VERT) {
+ if (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;
+ BMLoop *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+
+ do {
+ if (!BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) {
+ is_found = false;
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ if (is_found) {
if (r_existface) {
*r_existface = f;
}
- return TRUE;
+ break;
}
}
}
- if (r_existface) {
- *r_existface = NULL;
+ if (is_found == false) {
+ if (r_existface) {
+ *r_existface = NULL;
+ }
}
- return FALSE;
+
+ if (is_init == true) {
+ for (i = 0; i < len; i++) {
+ BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP);
+ }
+ }
+
+ return is_found;
+#endif
}
@@ -1307,12 +1488,12 @@ int BM_face_exists(BMVert **varr, int len, BMFace **r_existface)
*
* \a earr and \a varr can be in any order, however they _must_ form a closed loop.
*/
-int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
+bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
{
BMFace *f;
BMEdge *e;
BMVert *v;
- int ok;
+ bool ok;
int tot_tag;
BMIter fiter;
@@ -1352,10 +1533,10 @@ int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
for (i = 0; i < len; i++) {
BM_ITER_ELEM (f, &fiter, earr[i], BM_FACES_OF_EDGE) {
if (!BM_elem_flag_test(f, BM_ELEM_INTERNAL_TAG)) {
- ok = TRUE;
+ ok = true;
BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) {
if (!BM_elem_flag_test(v, BM_ELEM_INTERNAL_TAG)) {
- ok = FALSE;
+ ok = false;
break;
}
}
@@ -1374,20 +1555,20 @@ int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
if (tot_tag == 0) {
/* no faces use only boundary verts, quit early */
- return FALSE;
+ return false;
}
/* 2) loop over non-boundary edges that use boundary verts,
* check each have 2 tagges faces connected (faces that only use 'varr' verts) */
- ok = TRUE;
+ ok = true;
for (i = 0; i < len; i++) {
BM_ITER_ELEM (e, &fiter, varr[i], BM_EDGES_OF_VERT) {
if (/* non-boundary edge */
- BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG) == FALSE &&
+ 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) == true &&
+ BM_elem_flag_test(e->v2, BM_ELEM_INTERNAL_TAG) == true)
{
int tot_face_tag = 0;
BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
@@ -1397,14 +1578,14 @@ int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
}
if (tot_face_tag != 2) {
- ok = FALSE;
+ ok = false;
break;
}
}
}
- if (ok == FALSE) {
+ if (ok == false) {
break;
}
}
@@ -1413,25 +1594,25 @@ int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
}
/* same as 'BM_face_exists_multi' but built vert array from edges */
-int BM_face_exists_multi_edge(BMEdge **earr, int len)
+bool BM_face_exists_multi_edge(BMEdge **earr, int len)
{
BMVert **varr = BLI_array_alloca(varr, len);
- int ok;
+ bool ok;
int i, i_next;
/* first check if verts have edges, if not we can bail out early */
- ok = TRUE;
+ ok = true;
for (i = len - 1, i_next = 0; i_next < len; (i = i_next++)) {
if (!(varr[i] = BM_edge_share_vert(earr[i], earr[i_next]))) {
- ok = FALSE;
+ ok = false;
break;
}
}
- if (ok == FALSE) {
+ if (ok == false) {
BMESH_ASSERT(0);
- return FALSE;
+ return false;
}
ok = BM_face_exists_multi(varr, earr, len);
@@ -1440,13 +1621,13 @@ int BM_face_exists_multi_edge(BMEdge **earr, int len)
}
/* convenience functions for checking flags */
-int BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag)
+bool BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag)
{
return (BM_elem_flag_test(e->v1, hflag) ||
BM_elem_flag_test(e->v2, hflag));
}
-int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag)
+bool BM_face_is_any_vert_flag_test(BMFace *f, const char hflag)
{
BMLoop *l_iter;
BMLoop *l_first;
@@ -1454,13 +1635,13 @@ int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag)
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
if (BM_elem_flag_test(l_iter->v, hflag)) {
- return TRUE;
+ return true;
}
} while ((l_iter = l_iter->next) != l_first);
- return FALSE;
+ return false;
}
-int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag)
+bool BM_face_is_any_edge_flag_test(BMFace *f, const char hflag)
{
BMLoop *l_iter;
BMLoop *l_first;
@@ -1468,8 +1649,43 @@ int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag)
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
if (BM_elem_flag_test(l_iter->e, hflag)) {
- return TRUE;
+ return true;
}
} while ((l_iter = l_iter->next) != l_first);
- return FALSE;
+ return false;
+}
+
+static void bm_mesh_calc_volume_face(BMFace *f, float *r_vol)
+{
+ int tottri = f->len - 2;
+ BMLoop **loops = BLI_array_alloca(loops, f->len);
+ int (*index)[3] = BLI_array_alloca(index, tottri);
+ int j;
+
+ tottri = BM_face_calc_tessellation(f, loops, index);
+ BLI_assert(tottri <= f->len - 2);
+
+ for (j = 0; j < tottri; j++) {
+ const float *p1 = loops[index[j][0]]->v->co;
+ const float *p2 = loops[index[j][1]]->v->co;
+ const float *p3 = loops[index[j][2]]->v->co;
+
+ /* co1.dot(co2.cross(co3)) / 6.0 */
+ float cross[3];
+ cross_v3_v3v3(cross, p2, p3);
+ *r_vol += (1.0f / 6.0f) * dot_v3v3(p1, cross);
+ }
+}
+float BM_mesh_calc_volume(BMesh *bm)
+{
+ /* warning, calls own tessellation function, may be slow */
+ float vol = 0.0f;
+ BMFace *f;
+ BMIter fiter;
+
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ bm_mesh_calc_volume_face(f, &vol);
+ }
+
+ return fabsf(vol);
}
diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h
index 7a18f69371e..f894912aad3 100644
--- a/source/blender/bmesh/intern/bmesh_queries.h
+++ b/source/blender/bmesh/intern/bmesh_queries.h
@@ -27,18 +27,20 @@
* \ingroup bmesh
*/
-int BM_vert_in_face(BMFace *f, BMVert *v);
-int BM_verts_in_face(BMFace *f, BMVert **varr, int len);
+bool BM_vert_in_face(BMFace *f, BMVert *v);
+int BM_verts_in_face_count(BMFace *f, BMVert **varr, int len);
+bool BM_verts_in_face(BMFace *f, BMVert **varr, int len);
-int BM_edge_in_face(BMFace *f, BMEdge *e);
-int BM_edge_in_loop(BMEdge *e, BMLoop *l);
+bool BM_edge_in_face(BMFace *f, BMEdge *e);
+bool BM_edge_in_loop(BMEdge *e, BMLoop *l);
-int BM_vert_in_edge(BMEdge *e, BMVert *v);
-int BM_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e);
+bool BM_vert_in_edge(BMEdge *e, BMVert *v);
+bool BM_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e);
float BM_edge_calc_length(BMEdge *e);
-int BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb);
-int BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb);
+float BM_edge_calc_length_squared(BMEdge *e);
+bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb);
+bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb);
BMVert *BM_edge_other_vert(BMEdge *e, BMVert *v);
BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l);
BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v);
@@ -53,15 +55,19 @@ int BM_edge_face_count(BMEdge *e);
int BM_vert_face_count(BMVert *v);
BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e);
-int BM_vert_is_wire(BMVert *v);
-int BM_edge_is_wire(BMEdge *e);
+bool BM_vert_is_wire(BMVert *v);
+bool BM_edge_is_wire(BMEdge *e);
-int BM_vert_is_manifold(BMVert *v);
-int BM_edge_is_manifold(BMEdge *e);
-int BM_edge_is_boundary(BMEdge *e);
+bool BM_vert_is_manifold(BMVert *v);
+bool BM_edge_is_manifold(BMEdge *e);
+bool BM_edge_is_boundary(BMEdge *e);
+bool BM_edge_is_contiguous(BMEdge *e);
+
+bool BM_loop_is_convex(BMLoop *l);
float BM_loop_calc_face_angle(BMLoop *l);
void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3]);
+void BM_loop_calc_face_direction(BMLoop *l, float r_normal[3]);
void BM_loop_calc_face_tangent(BMLoop *l, float r_tangent[3]);
float BM_edge_calc_face_angle(BMEdge *e);
@@ -69,6 +75,7 @@ void BM_edge_calc_face_tangent(BMEdge *e, BMLoop *e_loop, float r_tangent[3])
float BM_vert_calc_edge_angle(BMVert *v);
float BM_vert_calc_shell_factor(BMVert *v);
+float BM_vert_calc_shell_factor_ex(BMVert *v, const char hflag);
float BM_vert_calc_mean_tagged_edge_length(BMVert *v);
BMLoop *BM_face_find_shortest_loop(BMFace *f);
@@ -77,21 +84,19 @@ BMLoop *BM_face_find_longest_loop(BMFace *f);
BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2);
BMEdge *BM_edge_find_double(BMEdge *e);
-int BM_face_exists_overlap(BMVert **varr, int len, BMFace **r_existface);
-
-int BM_face_exists(BMVert **varr, int len, BMFace **r_existface);
+bool BM_face_exists(BMVert **varr, int len, BMFace **r_existface);
-int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len);
-int BM_face_exists_multi_edge(BMEdge **earr, int len);
+bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len);
+bool BM_face_exists_multi_edge(BMEdge **earr, int len);
int BM_face_share_face_count(BMFace *f1, BMFace *f2);
int BM_face_share_edge_count(BMFace *f1, BMFace *f2);
-int BM_face_share_face_check(BMFace *f1, BMFace *f2);
-int BM_face_share_edge_check(BMFace *f1, BMFace *f2);
-int BM_edge_share_face_check(BMEdge *e1, BMEdge *e2);
-int BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2);
-int BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2);
+bool BM_face_share_face_check(BMFace *f1, BMFace *f2);
+bool BM_face_share_edge_check(BMFace *f1, BMFace *f2);
+bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2);
+bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2);
+bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2);
BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2);
BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v);
@@ -101,8 +106,10 @@ void BM_edge_ordered_verts(BMEdge *edge, BMVert **r_v1, BMVert **r_v2);
void BM_edge_ordered_verts_ex(BMEdge *edge, BMVert **r_v1, BMVert **r_v2,
BMLoop *edge_loop);
-int BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag);
-int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag);
-int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag);
+bool BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag);
+bool BM_face_is_any_vert_flag_test(BMFace *f, const char hflag);
+bool BM_face_is_any_edge_flag_test(BMFace *f, const char hflag);
+
+float BM_mesh_calc_volume(BMesh *bm);
#endif /* __BMESH_QUERIES_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c
index b58e61a3066..0398f9c558f 100644
--- a/source/blender/bmesh/intern/bmesh_structure.c
+++ b/source/blender/bmesh/intern/bmesh_structure.c
@@ -40,16 +40,16 @@
* MISC utility functions.
*/
-int bmesh_vert_in_edge(BMEdge *e, BMVert *v)
+bool bmesh_vert_in_edge(BMEdge *e, BMVert *v)
{
- if (e->v1 == v || e->v2 == v) return TRUE;
- return FALSE;
+ if (e->v1 == v || e->v2 == v) return true;
+ return false;
}
-int bmesh_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e)
+bool bmesh_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e)
{
- if (e->v1 == v1 && e->v2 == v2) return TRUE;
- else if (e->v1 == v2 && e->v2 == v1) return TRUE;
- return FALSE;
+ if (e->v1 == v1 && e->v2 == v2) return true;
+ else if (e->v1 == v2 && e->v2 == v1) return true;
+ return false;
}
BMVert *bmesh_edge_other_vert_get(BMEdge *e, BMVert *v)
@@ -63,19 +63,19 @@ BMVert *bmesh_edge_other_vert_get(BMEdge *e, BMVert *v)
return NULL;
}
-int bmesh_edge_swapverts(BMEdge *e, BMVert *orig, BMVert *newv)
+bool bmesh_edge_swapverts(BMEdge *e, BMVert *v_orig, BMVert *v_new)
{
- if (e->v1 == orig) {
- e->v1 = newv;
+ if (e->v1 == v_orig) {
+ e->v1 = v_new;
e->v1_disk_link.next = e->v1_disk_link.prev = NULL;
- return TRUE;
+ return true;
}
- else if (e->v2 == orig) {
- e->v2 = newv;
+ else if (e->v2 == v_orig) {
+ e->v2 = v_new;
e->v2_disk_link.next = e->v2_disk_link.prev = NULL;
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
/**
@@ -165,7 +165,7 @@ BLI_INLINE BMDiskLink *bmesh_disk_edge_link_from_vert(BMEdge *e, BMVert *v)
}
}
-int bmesh_disk_edge_append(BMEdge *e, BMVert *v)
+void bmesh_disk_edge_append(BMEdge *e, BMVert *v)
{
if (!v->e) {
BMDiskLink *dl1 = bmesh_disk_edge_link_from_vert(e, v);
@@ -187,8 +187,6 @@ int bmesh_disk_edge_append(BMEdge *e, BMVert *v)
if (dl3)
dl3->next = e;
}
-
- return TRUE;
}
void bmesh_disk_edge_remove(BMEdge *e, BMVert *v)
@@ -280,23 +278,23 @@ int bmesh_disk_count(BMVert *v)
}
}
-int bmesh_disk_validate(int len, BMEdge *e, BMVert *v)
+bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v)
{
BMEdge *e_iter;
if (!BM_vert_in_edge(e, v))
- return FALSE;
+ return false;
if (bmesh_disk_count(v) != len || len == 0)
- return FALSE;
+ return false;
e_iter = e;
do {
if (len != 1 && bmesh_disk_edge_prev(e_iter, v) == e_iter) {
- return FALSE;
+ return false;
}
} while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e);
- return TRUE;
+ return true;
}
/**
@@ -362,34 +360,34 @@ BMEdge *bmesh_disk_faceedge_find_next(BMEdge *e, BMVert *v)
}
/*****radial cycle functions, e.g. loops surrounding edges**** */
-int bmesh_radial_validate(int radlen, BMLoop *l)
+bool bmesh_radial_validate(int radlen, BMLoop *l)
{
BMLoop *l_iter = l;
int i = 0;
if (bmesh_radial_length(l) != radlen)
- return FALSE;
+ return false;
do {
if (UNLIKELY(!l_iter)) {
BMESH_ASSERT(0);
- return FALSE;
+ return false;
}
if (l_iter->e != l->e)
- return FALSE;
+ return false;
if (l_iter->v != l->e->v1 && l_iter->v != l->e->v2)
- return FALSE;
+ return false;
if (UNLIKELY(i > BM_LOOP_RADIAL_MAX)) {
BMESH_ASSERT(0);
- return FALSE;
+ return false;
}
i++;
} while ((l_iter = l_iter->radial_next) != l);
- return TRUE;
+ return true;
}
/**
@@ -511,7 +509,7 @@ void bmesh_radial_append(BMEdge *e, BMLoop *l)
l->e = e;
}
-int bmesh_radial_face_find(BMEdge *e, BMFace *f)
+bool bmesh_radial_face_find(BMEdge *e, BMFace *f)
{
BMLoop *l_iter;
int i, len;
@@ -519,9 +517,9 @@ int bmesh_radial_face_find(BMEdge *e, BMFace *f)
len = bmesh_radial_length(e->l);
for (i = 0, l_iter = e->l; i < len; i++, l_iter = l_iter->radial_next) {
if (l_iter->f == f)
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
/**
@@ -545,7 +543,7 @@ int bmesh_radial_facevert_count(BMLoop *l, BMVert *v)
}
/*****loop cycle functions, e.g. loops surrounding a face**** */
-int bmesh_loop_validate(BMFace *f)
+bool bmesh_loop_validate(BMFace *f)
{
int i;
int len = f->len;
@@ -554,7 +552,7 @@ int bmesh_loop_validate(BMFace *f)
l_first = BM_FACE_FIRST_LOOP(f);
if (l_first == NULL) {
- return FALSE;
+ return false;
}
/* Validate that the face loop cycle is the length specified by f->len */
@@ -562,22 +560,22 @@ int bmesh_loop_validate(BMFace *f)
if ((l_iter->f != f) ||
(l_iter == l_first))
{
- return FALSE;
+ return false;
}
}
if (l_iter != l_first) {
- return FALSE;
+ return false;
}
/* Validate the loop->prev links also form a cycle of length f->len */
for (i = 1, l_iter = l_first->prev; i < len; i++, l_iter = l_iter->prev) {
if (l_iter == l_first) {
- return FALSE;
+ return false;
}
}
if (l_iter != l_first) {
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h
index b19df4660b8..e67f1e4fb49 100644
--- a/source/blender/bmesh/intern/bmesh_structure.h
+++ b/source/blender/bmesh/intern/bmesh_structure.h
@@ -42,10 +42,10 @@
struct ListBase;
/* LOOP CYCLE MANAGEMENT */
-int bmesh_loop_validate(BMFace *f);
+bool bmesh_loop_validate(BMFace *f);
/* DISK CYCLE MANAGMENT */
-int bmesh_disk_edge_append(BMEdge *e, BMVert *v);
+void bmesh_disk_edge_append(BMEdge *e, BMVert *v);
void bmesh_disk_edge_remove(BMEdge *e, BMVert *v);
BMEdge *bmesh_disk_edge_next(BMEdge *e, BMVert *v);
BMEdge *bmesh_disk_edge_prev(BMEdge *e, BMVert *v);
@@ -60,19 +60,19 @@ void bmesh_radial_loop_remove(BMLoop *l, BMEdge *e);
* bmesh_radial_loop_next(BMLoop *l) / prev.
* just use member access l->radial_next, l->radial_prev now */
-int bmesh_radial_face_find(BMEdge *e, BMFace *f);
+bool bmesh_radial_face_find(BMEdge *e, BMFace *f);
int bmesh_radial_facevert_count(BMLoop *l, BMVert *v);
BMLoop *bmesh_radial_faceloop_find_first(BMLoop *l, BMVert *v);
BMLoop *bmesh_radial_faceloop_find_next(BMLoop *l, BMVert *v);
BMLoop *bmesh_radial_faceloop_find_vert(BMFace *f, BMVert *v);
-int bmesh_radial_validate(int radlen, BMLoop *l);
+bool bmesh_radial_validate(int radlen, BMLoop *l);
/* EDGE UTILITIES */
-int bmesh_vert_in_edge(BMEdge *e, BMVert *v);
-int bmesh_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e);
-int bmesh_edge_swapverts(BMEdge *e, BMVert *orig, BMVert *newv); /*relink edge*/
+bool bmesh_vert_in_edge(BMEdge *e, BMVert *v);
+bool bmesh_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e);
+bool bmesh_edge_swapverts(BMEdge *e, BMVert *orig, BMVert *newv); /* relink edge */
BMVert *bmesh_edge_other_vert_get(BMEdge *e, BMVert *v);
BMEdge *bmesh_disk_edge_exists(BMVert *v1, BMVert *v2);
-int bmesh_disk_validate(int len, BMEdge *e, BMVert *v);
+bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v);
#endif /* __BMESH_STRUCTURE_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_walkers.h b/source/blender/bmesh/intern/bmesh_walkers.h
index 4f81f38aeb3..8be362b5afa 100644
--- a/source/blender/bmesh/intern/bmesh_walkers.h
+++ b/source/blender/bmesh/intern/bmesh_walkers.h
@@ -100,10 +100,9 @@ void BMW_reset(BMWalker *walker);
* BMFace *f;
*
* BMW_init(&walker, bm, BMW_ISLAND, SOME_OP_FLAG);
- * f = BMW_begin(&walker, some_start_face);
- * for (; f; f = BMW_step(&walker))
- * {
- * //do something with f
+ *
+ * for (f = BMW_begin(&walker, some_start_face); f; f = BMW_step(&walker)) {
+ * // do something with f
* }
* BMW_end(&walker);
*/
diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c
index bb013e6428e..a50b708961c 100644
--- a/source/blender/bmesh/intern/bmesh_walkers_impl.c
+++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c
@@ -34,42 +34,42 @@
#include "intern/bmesh_private.h"
#include "intern/bmesh_walkers_private.h"
-static int bmw_mask_check_vert(BMWalker *walker, BMVert *v)
+static bool bmw_mask_check_vert(BMWalker *walker, BMVert *v)
{
if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
- return FALSE;
+ return false;
}
else if (walker->mask_vert && !BMO_elem_flag_test(walker->bm, v, walker->mask_vert)) {
- return FALSE;
+ return false;
}
else {
- return TRUE;
+ return true;
}
}
-static int bmw_mask_check_edge(BMWalker *walker, BMEdge *e)
+static bool bmw_mask_check_edge(BMWalker *walker, BMEdge *e)
{
if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- return FALSE;
+ return false;
}
else if (walker->mask_edge && !BMO_elem_flag_test(walker->bm, e, walker->mask_edge)) {
- return FALSE;
+ return false;
}
else {
- return TRUE;
+ return true;
}
}
-static int bmw_mask_check_face(BMWalker *walker, BMFace *f)
+static bool bmw_mask_check_face(BMWalker *walker, BMFace *f)
{
if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- return FALSE;
+ return false;
}
else if (walker->mask_face && !BMO_elem_flag_test(walker->bm, f, walker->mask_face)) {
- return FALSE;
+ return false;
}
else {
- return TRUE;
+ return true;
}
}
@@ -163,8 +163,8 @@ static void *bmw_ShellWalker_step(BMWalker *walker)
static void *bmw_ShellWalker_step(BMWalker *walker)
{
BMEdge *curedge, *next = NULL;
- BMVert *ov = NULL;
- int restrictpass = 1;
+ BMVert *v_old = NULL;
+ bool restrictpass = true;
BMwShellWalker shellWalk = *((BMwShellWalker *)BMW_current_state(walker));
if (!BLI_ghash_haskey(walker->visithash, shellWalk.base)) {
@@ -183,7 +183,7 @@ static void *bmw_ShellWalker_step(BMWalker *walker)
{
BMwShellWalker *newstate;
- ov = BM_edge_other_vert(curedge, shellWalk.base);
+ v_old = BM_edge_other_vert(curedge, shellWalk.base);
/* push a new state onto the stac */
newState = BMW_state_add(walker);
@@ -191,7 +191,7 @@ static void *bmw_ShellWalker_step(BMWalker *walker)
/* populate the new stat */
- newState->base = ov;
+ newState->base = v_old;
newState->curedge = curedge;
}
}
@@ -403,6 +403,11 @@ static void *bmw_IslandWalker_step(BMWalker *walker)
continue;
}
+ /* saves checking BLI_ghash_haskey below (manifold edges theres a 50% chance) */
+ if (f == iwalk->cur) {
+ continue;
+ }
+
if (BLI_ghash_haskey(walker->visithash, f)) {
continue;
}
@@ -442,7 +447,7 @@ static void bmw_LoopWalker_begin(BMWalker *walker, void *data)
lwalk->is_single = (vert_edge_count[0] == 2 && vert_edge_count[1] == 2);
/* could also check that vertex*/
- if ((lwalk->is_boundary == FALSE) &&
+ if ((lwalk->is_boundary == false) &&
(vert_edge_count[0] == 3 || vert_edge_count[1] == 3))
{
BMIter iter;
@@ -543,19 +548,19 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
/* typical loopiong over edges in the middle of a mesh */
/* however, why use 2 here at all? I guess for internal ngon loops it can be useful. Antony R. */
- ((vert_edge_tot == 4 || vert_edge_tot == 2) && owalk.is_boundary == FALSE) ||
+ ((vert_edge_tot == 4 || vert_edge_tot == 2) && owalk.is_boundary == false) ||
/* walk over boundary of faces but stop at corners */
- (owalk.is_boundary == TRUE && owalk.is_single == FALSE && vert_edge_tot > 2) ||
+ (owalk.is_boundary == true && 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 */
- (owalk.is_boundary == TRUE && owalk.is_single == TRUE && vert_edge_tot == 2 && BM_edge_is_boundary(e)))
+ (owalk.is_boundary == true && owalk.is_single == true && vert_edge_tot == 2 && BM_edge_is_boundary(e)))
{
i = 0;
stopi = vert_edge_tot / 2;
while (1) {
- if ((owalk.is_boundary == FALSE) && (i == stopi)) {
+ if ((owalk.is_boundary == false) && (i == stopi)) {
break;
}
@@ -584,7 +589,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
bmw_mask_check_edge(walker, l->e) &&
!BLI_ghash_haskey(walker->visithash, l->e))
{
- if (!(owalk.is_boundary == FALSE && i != stopi)) {
+ if (!(owalk.is_boundary == false && i != stopi)) {
lwalk = BMW_state_add(walker);
lwalk->cur = l->e;
lwalk->lastv = v;
@@ -637,47 +642,47 @@ static void *bmw_LoopWalker_step(BMWalker *walker)
/* Check whether the face loop should includes the face specified
* by the given BMLoop */
-static int bmw_FaceLoopWalker_include_face(BMWalker *walker, BMLoop *l)
+static bool bmw_FaceLoopWalker_include_face(BMWalker *walker, BMLoop *l)
{
/* face must have degree 4 */
if (l->f->len != 4) {
- return FALSE;
+ return false;
}
if (!bmw_mask_check_face(walker, l->f)) {
- return FALSE;
+ return false;
}
/* the face must not have been already visite */
if (BLI_ghash_haskey(walker->visithash, l->f) && BLI_ghash_haskey(walker->secvisithash, l->e)) {
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
/* Check whether the face loop can start from the given edge */
-static int bmw_FaceLoopWalker_edge_begins_loop(BMWalker *walker, BMEdge *e)
+static bool bmw_FaceLoopWalker_edge_begins_loop(BMWalker *walker, BMEdge *e)
{
/* There is no face loop starting from a wire edge */
if (BM_edge_is_wire(e)) {
- return FALSE;
+ return false;
}
/* Don't start a loop from a boundary edge if it cannot
* be extended to cover any faces */
if (BM_edge_is_boundary(e)) {
if (!bmw_FaceLoopWalker_include_face(walker, e->l)) {
- return FALSE;
+ return false;
}
}
/* Don't start a face loop from non-manifold edges */
if (!BM_edge_is_manifold(e)) {
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
static void bmw_FaceLoopWalker_begin(BMWalker *walker, void *data)
@@ -692,7 +697,7 @@ static void bmw_FaceLoopWalker_begin(BMWalker *walker, void *data)
lwalk = BMW_state_add(walker);
lwalk->l = e->l;
- lwalk->nocalc = 0;
+ lwalk->no_calc = false;
BLI_ghash_insert(walker->visithash, lwalk->l->f, NULL);
/* rewin */
@@ -703,7 +708,7 @@ static void bmw_FaceLoopWalker_begin(BMWalker *walker, void *data)
lwalk = BMW_state_add(walker);
*lwalk = owalk;
- lwalk->nocalc = 0;
+ lwalk->no_calc = false;
BLI_ghash_free(walker->secvisithash, NULL, NULL);
walker->secvisithash = BLI_ghash_ptr_new("bmesh walkers 3");
@@ -735,7 +740,7 @@ static void *bmw_FaceLoopWalker_step(BMWalker *walker)
l = l->radial_next;
- if (lwalk->nocalc) {
+ if (lwalk->no_calc) {
return f;
}
@@ -753,11 +758,11 @@ static void *bmw_FaceLoopWalker_step(BMWalker *walker)
lwalk->l = l;
if (l->f->len != 4) {
- lwalk->nocalc = 1;
+ lwalk->no_calc = true;
lwalk->l = origl;
}
else {
- lwalk->nocalc = 0;
+ lwalk->no_calc = false;
}
BLI_ghash_insert(walker->secvisithash, l->e, NULL);
@@ -853,7 +858,7 @@ static void *bmw_EdgeringWalker_step(BMWalker *walker)
if (!EDGE_CHECK(e)) {
/* walker won't traverse to a non-manifold edge, but may
* be started on one, and should not traverse *away* from
- * a non-manfold edge (non-manifold edges are never in an
+ * a non-manifold edge (non-manifold edges are never in an
* edge ring with manifold edges */
return e;
}
diff --git a/source/blender/bmesh/intern/bmesh_walkers_private.h b/source/blender/bmesh/intern/bmesh_walkers_private.h
index fc563932c3c..09dd4f18d89 100644
--- a/source/blender/bmesh/intern/bmesh_walkers_private.h
+++ b/source/blender/bmesh/intern/bmesh_walkers_private.h
@@ -62,14 +62,14 @@ typedef struct BMwLoopWalker {
BMEdge *cur, *start;
BMVert *lastv, *startv;
BMFace *f_hub;
- short is_boundary; /* boundary looping changes behavior */
- short is_single; /* single means the edge verts are only connected to 1 face */
+ bool is_boundary; /* boundary looping changes behavior */
+ bool is_single; /* single means the edge verts are only connected to 1 face */
} BMwLoopWalker;
typedef struct BMwFaceLoopWalker {
BMwGenericWalker header;
BMLoop *l;
- int nocalc;
+ bool no_calc;
} BMwFaceLoopWalker;
typedef struct BMwEdgeringWalker {
diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c
index 126d0f46119..052ae9336ab 100644
--- a/source/blender/bmesh/operators/bmo_bevel.c
+++ b/source/blender/bmesh/operators/bmo_bevel.c
@@ -34,6 +34,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
{
const float offset = BMO_slot_float_get(op->slots_in, "offset");
const int seg = BMO_slot_int_get(op->slots_in, "segments");
+ const bool vonly = BMO_slot_bool_get(op->slots_in, "vertex_only");
if (offset > 0) {
BMOIter siter;
@@ -42,7 +43,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
/* first flush 'geom' into flags, this makes it possible to check connected data,
* BM_FACE is cleared so we can put newly created faces into a bmesh slot. */
- BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, FALSE);
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) {
BM_elem_flag_enable(v, BM_ELEM_TAG);
@@ -54,7 +55,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op)
}
}
- BM_mesh_bevel(bm, offset, seg);
+ BM_mesh_bevel(bm, offset, seg, vonly, false, false, NULL, -1);
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_connect.c b/source/blender/bmesh/operators/bmo_connect.c
index c7cd1e742d8..dc00d020083 100644
--- a/source/blender/bmesh/operators/bmo_connect.c
+++ b/source/blender/bmesh/operators/bmo_connect.c
@@ -44,10 +44,10 @@
void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)
{
BMIter iter, liter;
- BMFace *f, *nf;
+ BMFace *f, *f_new;
BMLoop *(*loops_split)[2] = NULL;
BLI_array_declare(loops_split);
- BMLoop *l, *nl, *lastl = NULL;
+ BMLoop *l, *l_new;
BMVert *(*verts_pair)[2] = NULL;
BLI_array_declare(verts_pair);
int i;
@@ -56,7 +56,8 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)
/* BMESH_TODO, loop over vert faces:
* faster then looping over all faces, then searching each for flagged verts*/
- for (f = BM_iter_new(&iter, bm, BM_FACES_OF_MESH, NULL); f; f = BM_iter_step(&iter)) {
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ BMLoop *l_last;
BLI_array_empty(loops_split);
BLI_array_empty(verts_pair);
@@ -64,22 +65,21 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)
continue;
}
- l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f);
- lastl = NULL;
- for ( ; l; l = BM_iter_step(&liter)) {
+ l_last = NULL;
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
if (BMO_elem_flag_test(bm, l->v, VERT_INPUT)) {
- if (!lastl) {
- lastl = l;
+ if (!l_last) {
+ l_last = l;
continue;
}
- if (lastl != l->prev && lastl != l->next) {
+ if (l_last != l->prev && l_last != l->next) {
BLI_array_grow_one(loops_split);
- loops_split[BLI_array_count(loops_split) - 1][0] = lastl;
+ loops_split[BLI_array_count(loops_split) - 1][0] = l_last;
loops_split[BLI_array_count(loops_split) - 1][1] = l;
}
- lastl = l;
+ l_last = l;
}
}
@@ -106,16 +106,16 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)
}
for (i = 0; i < BLI_array_count(verts_pair); i++) {
- nf = BM_face_split(bm, f, verts_pair[i][0], verts_pair[i][1], &nl, NULL, FALSE);
- f = nf;
+ f_new = BM_face_split(bm, f, verts_pair[i][0], verts_pair[i][1], &l_new, NULL, false);
+ f = f_new;
- if (!nl || !nf) {
+ if (!l_new || !f_new) {
BMO_error_raise(bm, op, BMERR_CONNECTVERT_FAILED, NULL);
BLI_array_free(loops_split);
return;
}
- BMO_elem_flag_enable(bm, nf, FACE_NEW);
- BMO_elem_flag_enable(bm, nl->e, EDGE_OUT);
+ BMO_elem_flag_enable(bm, f_new, FACE_NEW);
+ BMO_elem_flag_enable(bm, l_new->e, EDGE_OUT);
}
}
@@ -160,19 +160,19 @@ static int clamp_index(const int x, const int len)
* isn't there should be... */
#define ARRAY_SWAP(elemtype, arr1, arr2) \
{ \
- int i; \
+ int i_; \
elemtype *arr_tmp = NULL; \
BLI_array_declare(arr_tmp); \
- for (i = 0; i < BLI_array_count(arr1); i++) { \
- BLI_array_append(arr_tmp, arr1[i]); \
+ for (i_ = 0; i_ < BLI_array_count(arr1); i_++) { \
+ BLI_array_append(arr_tmp, arr1[i_]); \
} \
BLI_array_empty(arr1); \
- for (i = 0; i < BLI_array_count(arr2); i++) { \
- BLI_array_append(arr1, arr2[i]); \
+ for (i_ = 0; i_ < BLI_array_count(arr2); i_++) { \
+ BLI_array_append(arr1, arr2[i_]); \
} \
BLI_array_empty(arr2); \
- for (i = 0; i < BLI_array_count(arr_tmp); i++) { \
- BLI_array_append(arr2, arr_tmp[i]); \
+ for (i_ = 0; i_ < BLI_array_count(arr_tmp); i_++) { \
+ BLI_array_append(arr2, arr_tmp[i_]); \
} \
BLI_array_free(arr_tmp); \
} (void)0
@@ -221,15 +221,15 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op)
int c = 0, cl1 = 0, cl2 = 0;
/* merge-bridge support */
- const int use_merge = BMO_slot_bool_get(op->slots_in, "use_merge");
+ const bool use_merge = BMO_slot_bool_get(op->slots_in, "use_merge");
const float merge_factor = BMO_slot_float_get(op->slots_in, "merge_factor");
BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
if (!BMO_elem_flag_test(bm, e, EDGE_DONE)) {
- BMVert *v, *ov;
- /* BMEdge *e2, *e3, *oe = e; */ /* UNUSED */
+ BMVert *v, *v_old;
+ /* BMEdge *e2, *e3, *e_old = e; */ /* UNUSED */
BMEdge *e2, *e3;
if (c > 2) {
@@ -265,7 +265,7 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op)
e2 = e;
e = e2;
- ov = v;
+ v_old = v;
do {
if (c == 0) {
BLI_array_append(ee1, e2);
@@ -301,7 +301,7 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op)
}
/* test for connected loops, and set cl1 or cl2 if so */
- if (v == ov) {
+ if (v == v_old) {
if (c == 0) {
cl1 = 1;
}
@@ -359,6 +359,17 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op)
/* Last point of loop 2 */
v4 = get_outer_vert(bm, ee2[clamp_index(-1, BLI_array_count(ee2))]);
+ /* ugh, happens when bridging single edges, user could just make a face
+ * but better support it for sake of completeness */
+ if (v1 == v2) {
+ BLI_assert(BLI_array_count(ee1) == 1);
+ v2 = (vv1[0] == v2) ? vv1[1] : vv1[0];
+ }
+ if (v3 == v4) {
+ BLI_assert(BLI_array_count(ee2) == 1);
+ v4 = (vv2[0] == v4) ? vv2[1] : vv2[0];
+ }
+
/* If v1 is a better match for v4 than v3, AND v2 is a better match
* for v3 than v4, the loops are in opposite directions, so reverse
* the order of reads from vv1. We can avoid sqrt for comparison */
@@ -508,7 +519,7 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op)
vv2[i2],
vv2[i2next],
vv1[i1next],
- f_example, TRUE);
+ f_example, true);
if (UNLIKELY((f == NULL) || (f->len != 4))) {
fprintf(stderr, "%s: in bridge! (bmesh internal error)\n", __func__);
}
diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c
index 2ea5914ca92..9fab89f8e0a 100644
--- a/source/blender/bmesh/operators/bmo_create.c
+++ b/source/blender/bmesh/operators/bmo_create.c
@@ -26,12 +26,12 @@
#include "MEM_guardedalloc.h"
-#include "BLI_heap.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_array.h"
#include "BLI_smallhash.h"
#include "BLI_rand.h"
+#include "BLI_heap.h"
#include "bmesh.h"
@@ -87,8 +87,8 @@ BLI_INLINE BMDiskLink *rs_edge_link_get(BMEdge *e, BMVert *v, EdgeData *e_data)
&(((EdgeData *)e_data)->v2_disk_link);
}
-static int rotsys_append_edge(BMEdge *e, BMVert *v,
- EdgeData *edata, VertData *vdata)
+static bool rotsys_append_edge(BMEdge *e, BMVert *v,
+ EdgeData *edata, VertData *vdata)
{
EdgeData *ed = &edata[BM_elem_index_get(e)];
VertData *vd = &vdata[BM_elem_index_get(v)];
@@ -116,7 +116,7 @@ static int rotsys_append_edge(BMEdge *e, BMVert *v,
}
}
- return TRUE;
+ return true;
}
static void UNUSED_FUNCTION(rotsys_remove_edge)(BMEdge *e, BMVert *v,
@@ -613,10 +613,10 @@ static void init_rotsys(BMesh *bm, EdgeData *edata, VertData *vdata)
BM_elem_index_set(v2, -1); /* set_dirty! */
//BM_edge_create(bm, cv, v2, NULL, 0);
- BM_vert_select_set(bm, v2, TRUE);
+ BM_vert_select_set(bm, v2, true);
if (lastv) {
e2 = BM_edge_create(bm, lastv, v2, NULL, 0);
- BM_edge_select_set(bm, e2, TRUE);
+ BM_edge_select_set(bm, e2, true);
}
lastv = v2;
@@ -742,7 +742,7 @@ static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, E
BMVert *endv;
EPathNode *node;
int i;
- const int use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict");
+ const bool use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict");
BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict");
@@ -810,9 +810,9 @@ static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, E
}
if (use_restrict) {
- int *group = (int *)BMO_slot_map_data_get(slot_restrict, e);
- if (group) {
- if (!(*group & path->group)) {
+ int *group_flag = (int *)BMO_slot_map_data_get(slot_restrict, e);
+ if (group_flag) {
+ if (!(*group_flag & path->group)) {
v2 = NULL;
continue;
}
@@ -899,10 +899,10 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op)
BMEdge **edges = NULL;
PathBase *pathbase;
BLI_array_declare(edges);
- int use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict");
- int use_fill_check = BMO_slot_bool_get(op->slots_in, "use_fill_check");
- const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
- const short use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
+ const bool use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict");
+ const bool use_fill_check = BMO_slot_bool_get(op->slots_in, "use_fill_check");
+ const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
+ const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
int i, j, group = 0;
unsigned int winding[2]; /* accumulte winding directions for each edge which has a face */
BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict");
@@ -925,15 +925,12 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op)
BMO_elem_flag_enable(bm, f, ELE_ORIG);
}
- i = 0;
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
BM_elem_index_set(e, i); /* set_inline */
if (!BMO_elem_flag_test(bm, e, EDGE_MARK)) {
edata[i].tag = 2;
}
-
- i++;
}
bm->elem_index_dirty &= ~BM_EDGE;
@@ -1047,9 +1044,9 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op)
v2 = verts[0];
}
- if ((use_fill_check == FALSE) ||
+ if ((use_fill_check == false) ||
/* fairly expensive check - see if there are already faces filling this area */
- (BM_face_exists_multi_edge(edges, i) == FALSE))
+ (BM_face_exists_multi_edge(edges, i) == false))
{
f = BM_face_create_ngon(bm, v1, v2, edges, i, BM_CREATE_NO_DOUBLE);
if (f && !BMO_elem_flag_test(bm, f, ELE_ORIG)) {
@@ -1287,7 +1284,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
BMFace *f;
int totv = 0, tote = 0, totf = 0, amount;
const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
- const short use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
+ const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
/* count number of each element type we were passe */
BMO_ITER (h, &oiter, op->slots_in, "geom", BM_VERT | BM_EDGE | BM_FACE) {
@@ -1321,7 +1318,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
if (totf == 0 && totv >= 4 && totv == tote + 2) {
/* find a free standing vertex and 2 endpoint verts */
BMVert *v_free = NULL, *v_a = NULL, *v_b = NULL;
- int ok = TRUE;
+ bool ok = true;
BMO_ITER (v, &oiter, op->slots_in, "geom", BM_VERT) {
@@ -1339,26 +1336,26 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
if (tot_edges == 0) {
/* only accept 1 free vert */
if (v_free == NULL) v_free = v;
- else ok = FALSE; /* only ever want one of these */
+ else ok = false; /* only ever want one of these */
}
else if (tot_edges == 1) {
if (v_a == NULL) v_a = v;
else if (v_b == NULL) v_b = v;
- else ok = FALSE; /* only ever want 2 of these */
+ else ok = false; /* only ever want 2 of these */
}
else if (tot_edges == 2) {
/* do nothing, regular case */
}
else {
- ok = FALSE; /* if a vertex has 3+ edge users then cancel - this is only simple cases */
+ ok = false; /* if a vertex has 3+ edge users then cancel - this is only simple cases */
}
- if (ok == FALSE) {
+ if (ok == false) {
break;
}
}
- if (ok == TRUE && v_free && v_a && v_b) {
+ if (ok == true && v_free && v_a && v_b) {
e = BM_edge_create(bm, v_free, v_a, NULL, BM_CREATE_NO_DOUBLE);
BMO_elem_flag_enable(bm, e, ELE_NEW);
@@ -1377,7 +1374,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
BMO_op_initf(bm, &op2, op->flag,
"edgenet_fill edges=%fe use_fill_check=%b mat_nr=%i use_smooth=%b",
- ELE_NEW, TRUE, mat_nr, use_smooth);
+ ELE_NEW, true, mat_nr, use_smooth);
BMO_op_exec(bm, &op2);
@@ -1491,6 +1488,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
if (use_smooth) {
BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
}
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_OUT);
}
MEM_freeN(vert_arr);
diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c
index 7c3bcd60daa..a78a8ec5197 100644
--- a/source/blender/bmesh/operators/bmo_dissolve.c
+++ b/source/blender/bmesh/operators/bmo_dissolve.c
@@ -41,7 +41,7 @@
#define VERT_MARK 1
-static int UNUSED_FUNCTION(check_hole_in_region) (BMesh * bm, BMFace * f)
+static bool UNUSED_FUNCTION(check_hole_in_region) (BMesh *bm, BMFace *f)
{
BMWalker regwalker;
BMIter liter2;
@@ -55,37 +55,36 @@ static int UNUSED_FUNCTION(check_hole_in_region) (BMesh * bm, BMFace * f)
BMW_FLAG_NOP,
BMW_NIL_LAY);
- f2 = BMW_begin(&regwalker, f);
- for ( ; f2; f2 = BMW_step(&regwalker)) {
- l2 = BM_iter_new(&liter2, bm, BM_LOOPS_OF_FACE, f2);
- for ( ; l2; l2 = BM_iter_step(&liter2)) {
+ for (f2 = BMW_begin(&regwalker, f); f2; f2 = BMW_step(&regwalker)) {
+ BM_ITER_ELEM (l2, &liter2, f2, BM_LOOPS_OF_FACE) {
l3 = l2->radial_next;
if (BMO_elem_flag_test(bm, l3->f, FACE_MARK) !=
BMO_elem_flag_test(bm, l2->f, FACE_MARK))
{
if (!BMO_elem_flag_test(bm, l2->e, EDGE_MARK)) {
- return FALSE;
+ return false;
}
}
}
}
BMW_end(&regwalker);
- return TRUE;
+ return true;
}
void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
{
BMOIter oiter;
- BMFace *f, *f2 /* , *nf = NULL */;
+ BMFace *f;
BLI_array_declare(faces);
BLI_array_declare(regions);
BMFace ***regions = NULL;
BMFace **faces = NULL;
+ BMFace *act_face = bm->act_face;
BMWalker regwalker;
int i;
- int use_verts = BMO_slot_bool_get(op->slots_in, "use_verts");
+ const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts");
if (use_verts) {
/* tag verts that start out with only 2 edges,
@@ -102,7 +101,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
/* collect region */
BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
-
+ BMFace *f_iter;
if (!BMO_elem_flag_test(bm, f, FACE_MARK)) {
continue;
}
@@ -115,16 +114,15 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
BMW_FLAG_NOP, /* no need to check BMW_FLAG_TEST_HIDDEN, faces are already marked by the bmo */
BMW_NIL_LAY);
- f2 = BMW_begin(&regwalker, f);
- for ( ; f2; f2 = BMW_step(&regwalker)) {
- BLI_array_append(faces, f2);
+ for (f_iter = BMW_begin(&regwalker, f); f_iter; f_iter = BMW_step(&regwalker)) {
+ BLI_array_append(faces, f_iter);
}
BMW_end(&regwalker);
for (i = 0; i < BLI_array_count(faces); i++) {
- f2 = faces[i];
- BMO_elem_flag_disable(bm, f2, FACE_MARK);
- BMO_elem_flag_enable(bm, f2, FACE_ORIG);
+ f_iter = faces[i];
+ BMO_elem_flag_disable(bm, f_iter, FACE_MARK);
+ BMO_elem_flag_enable(bm, f_iter, FACE_ORIG);
}
if (BMO_error_occurred(bm)) {
@@ -138,6 +136,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
}
for (i = 0; i < BLI_array_count(regions); i++) {
+ BMFace *f_new;
int tot = 0;
faces = regions[i];
@@ -150,8 +149,15 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
while (faces[tot])
tot++;
- f = BM_faces_join(bm, faces, tot, TRUE);
- if (!f) {
+ f_new = BM_faces_join(bm, faces, tot, true);
+
+ if (f_new) {
+ /* maintain active face */
+ if (act_face && bm->act_face == NULL) {
+ bm->act_face = f_new;
+ }
+ }
+ else {
BMO_error_raise(bm, op, BMERR_DISSOLVEFACES_FAILED,
"Could not create merged face");
goto cleanup;
@@ -159,8 +165,8 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
/* if making the new face failed (e.g. overlapping test)
* unmark the original faces for deletion */
- BMO_elem_flag_disable(bm, f, FACE_ORIG);
- BMO_elem_flag_enable(bm, f, FACE_NEW);
+ BMO_elem_flag_disable(bm, f_new, FACE_ORIG);
+ BMO_elem_flag_enable(bm, f_new, FACE_NEW);
}
@@ -174,7 +180,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
if (BM_vert_edge_count(v) == 2) {
- BM_vert_collapse_edge(bm, v->e, v, TRUE);
+ BM_vert_collapse_edge(bm, v->e, v, true);
}
}
}
@@ -199,23 +205,33 @@ cleanup:
void bmo_dissolve_edgeloop_exec(BMesh *bm, BMOperator *op)
{
/* BMOperator fop; */
+ BMFace *act_face = bm->act_face;
BMOIter oiter;
BMIter iter;
BMVert *v, **verts = NULL;
BLI_array_declare(verts);
BMEdge *e;
- BMFace *fa, *fb;
int i;
BMO_ITER (e, &oiter, op->slots_in, "edges", BM_EDGE) {
+ BMFace *fa, *fb;
+
if (BM_edge_face_pair(e, &fa, &fb)) {
+ BMFace *f_new;
BMO_elem_flag_enable(bm, e->v1, VERT_MARK);
BMO_elem_flag_enable(bm, e->v2, VERT_MARK);
/* BMESH_TODO - check on delaying edge removal since we may end up removing more then
* one edge, and later reference a removed edge */
- BM_faces_join_pair(bm, fa, fb, e, TRUE);
+ f_new = BM_faces_join_pair(bm, fa, fb, e, true);
+
+ if (f_new) {
+ /* maintain active face */
+ if (act_face && bm->act_face == NULL) {
+ bm->act_face = f_new;
+ }
+ }
}
}
@@ -228,7 +244,7 @@ void bmo_dissolve_edgeloop_exec(BMesh *bm, BMOperator *op)
/* clean up extreneous 2-valence vertice */
for (i = 0; i < BLI_array_count(verts); i++) {
if (verts[i]->e) {
- BM_vert_collapse_edge(bm, verts[i]->e, verts[i], TRUE);
+ BM_vert_collapse_edge(bm, verts[i]->e, verts[i], true);
}
}
@@ -248,13 +264,13 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
/* might want to make this an option or mode - campbell */
/* BMOperator fop; */
+ BMFace *act_face = bm->act_face;
BMOIter eiter;
BMEdge *e;
-
BMIter viter;
BMVert *v;
- int use_verts = BMO_slot_bool_get(op->slots_in, "use_verts");
+ const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts");
if (use_verts) {
BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
@@ -266,12 +282,20 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
BMFace *fa, *fb;
if (BM_edge_face_pair(e, &fa, &fb)) {
+ BMFace *f_new;
/* join faces */
/* BMESH_TODO - check on delaying edge removal since we may end up removing more then
* one edge, and later reference a removed edge */
- BM_faces_join_pair(bm, fa, fb, e, TRUE);
+ f_new = BM_faces_join_pair(bm, fa, fb, e, true);
+
+ if (f_new) {
+ /* maintain active face */
+ if (act_face && bm->act_face == NULL) {
+ bm->act_face = f_new;
+ }
+ }
}
}
@@ -279,57 +303,55 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
if (BM_vert_edge_count(v) == 2) {
- BM_vert_collapse_edge(bm, v->e, v, TRUE);
+ BM_vert_collapse_edge(bm, v->e, v, true);
}
}
}
}
}
-static int test_extra_verts(BMesh *bm, BMVert *v)
+static bool test_extra_verts(BMesh *bm, BMVert *v)
{
- BMIter iter, liter, iter2, iter3;
- BMFace *f, *f2;
+ BMIter fiter, liter, eiter, fiter_sub;
+ BMFace *f;
BMLoop *l;
BMEdge *e;
- int found;
/* test faces around verts for verts that would be wrongly killed
* by dissolve faces. */
- f = BM_iter_new(&iter, bm, BM_FACES_OF_VERT, v);
- for ( ; f; f = BM_iter_step(&iter)) {
- l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f);
- for ( ; l; l = BM_iter_step(&liter)) {
+ BM_ITER_ELEM(f, &fiter, v, BM_FACES_OF_VERT) {
+ BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) {
if (!BMO_elem_flag_test(bm, l->v, VERT_MARK)) {
/* if an edge around a vert is a boundary edge,
* then dissolve faces won't destroy it.
* also if it forms a boundary with one
* of the face region */
- found = FALSE;
- e = BM_iter_new(&iter2, bm, BM_EDGES_OF_VERT, l->v);
- for ( ; e; e = BM_iter_step(&iter2)) {
+ bool found = false;
+ BM_ITER_ELEM(e, &eiter, l->v, BM_EDGES_OF_VERT) {
+ BMFace *f_iter;
if (BM_edge_is_boundary(e)) {
- found = TRUE;
+ found = true;
}
- f2 = BM_iter_new(&iter3, bm, BM_FACES_OF_EDGE, e);
- for ( ; f2; f2 = BM_iter_step(&iter3)) {
- if (!BMO_elem_flag_test(bm, f2, FACE_MARK)) {
- found = TRUE;
- break;
+ else {
+ BM_ITER_ELEM(f_iter, &fiter_sub, e, BM_FACES_OF_EDGE) {
+ if (!BMO_elem_flag_test(bm, f_iter, FACE_MARK)) {
+ found = true;
+ break;
+ }
}
}
- if (found == TRUE) {
+ if (found == true) {
break;
}
}
- if (found == FALSE) {
- return FALSE;
+ if (found == false) {
+ return false;
}
}
}
}
- return TRUE;
+ return true;
}
void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
{
@@ -349,9 +371,9 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
/* previously the faces were joined, but collapsing between 2 edges
* gives some advantage/difference in using vertex-dissolve over edge-dissolve */
#if 0
- BM_vert_collapse_faces(bm, v->e, v, 1.0f, TRUE, TRUE);
+ BM_vert_collapse_faces(bm, v->e, v, 1.0f, true, true);
#else
- BM_vert_collapse_edge(bm, v->e, v, TRUE);
+ BM_vert_collapse_edge(bm, v->e, v, true);
#endif
continue;
@@ -483,7 +505,7 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op)
BMOpSlot *vinput = BMO_slot_get(op->slots_in, "verts");
const float angle_max = (float)M_PI / 2.0f;
const float angle_limit = min_ff(angle_max, BMO_slot_float_get(op->slots_in, "angle_limit"));
- const int do_dissolve_boundaries = BMO_slot_bool_get(op->slots_in, "use_dissolve_boundaries");
+ const bool do_dissolve_boundaries = BMO_slot_bool_get(op->slots_in, "use_dissolve_boundaries");
BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries,
(BMVert **)BMO_SLOT_AS_BUFFER(vinput), vinput->len,
diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c
index 9a58d7acfb9..1448129ccde 100644
--- a/source/blender/bmesh/operators/bmo_dupe.c
+++ b/source/blender/bmesh/operators/bmo_dupe.c
@@ -213,13 +213,13 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst)
!BMO_elem_flag_test(bm_src, v, DUPE_DONE))
{
BMIter iter;
- int isolated = 1;
+ bool isolated = true;
v2 = copy_vertex(bm_src, v, bm_dst, vhash);
BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
if (BMO_elem_flag_test(bm_src, f, DUPE_INPUT)) {
- isolated = 0;
+ isolated = false;
break;
}
}
@@ -227,7 +227,7 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst)
if (isolated) {
BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
if (BMO_elem_flag_test(bm_src, e, DUPE_INPUT)) {
- isolated = 0;
+ isolated = false;
break;
}
}
@@ -386,7 +386,7 @@ void bmo_split_exec(BMesh *bm, BMOperator *op)
BMOperator *splitop = op;
BMOperator dupeop;
BMOperator delop;
- const short use_only_faces = BMO_slot_bool_get(op->slots_in, "use_only_faces");
+ const bool use_only_faces = BMO_slot_bool_get(op->slots_in, "use_only_faces");
/* initialize our sub-operator */
BMO_op_init(bm, &dupeop, op->flag, "duplicate");
@@ -483,7 +483,7 @@ void bmo_spin_exec(BMesh *bm, BMOperator *op)
{
BMOperator dupop, extop;
float cent[3], dvec[3];
- float axis[3] = {0.0f, 0.0f, 1.0f};
+ float axis[3];
float rmat[3][3];
float phi;
int steps, do_dupli, a, usedvec;
diff --git a/source/blender/bmesh/operators/bmo_edgesplit.c b/source/blender/bmesh/operators/bmo_edgesplit.c
index 9e9e4b8c962..378f790ef32 100644
--- a/source/blender/bmesh/operators/bmo_edgesplit.c
+++ b/source/blender/bmesh/operators/bmo_edgesplit.c
@@ -22,152 +22,32 @@
/** \file blender/bmesh/operators/bmo_edgesplit.c
* \ingroup bmesh
+ *
+ * Just a wrapper around #BM_mesh_edgesplit
*/
-#include "MEM_guardedalloc.h"
-
#include "BLI_utildefines.h"
#include "bmesh.h"
+#include "tools/bmesh_edgesplit.h"
#include "intern/bmesh_operators_private.h" /* own include */
-enum {
- EDGE_SEAM = 1
-};
-
-enum {
- VERT_SEAM = 2
-};
-
-/**
- * Remove the EDGE_SEAM flag for edges we cant split
- *
- * un-tag edges not connected to other tagged edges,
- * unless they are on a boundary
- */
-static void bm_edgesplit_validate_seams(BMesh *bm, BMOperator *op)
-{
- BMOIter siter;
- BMIter iter;
- BMEdge *e;
-
- unsigned char *vtouch;
- unsigned char *vt;
-
- 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) {
- BMO_elem_flag_disable(bm, e, EDGE_SEAM);
- }
- else if (BM_edge_is_boundary(e)) {
- 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 */
- BMO_elem_flag_disable(bm, e, EDGE_SEAM);
- }
- }
-
- /* single marked edges unconnected to any other marked edges
- * are illegal, go through and unmark them */
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- /* 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)++;
- }
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- if (vtouch[BM_elem_index_get(e->v1)] == 1 &&
- vtouch[BM_elem_index_get(e->v2)] == 1)
- {
- BMO_elem_flag_disable(bm, e, EDGE_SEAM);
- }
- }
-
- MEM_freeN(vtouch);
-}
/* keep this operator fast, its used in a modifier */
void bmo_split_edges_exec(BMesh *bm, BMOperator *op)
{
- BMOIter siter;
- BMEdge *e;
- const int use_verts = BMO_slot_bool_get(op->slots_in, "use_verts");
+ const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts");
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_SEAM);
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, false);
if (use_verts) {
/* this slows down the operation but its ok because the modifier doesn't use */
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_SEAM);
-
- /* prevent one edge having both verts unflagged
- * we could alternately disable these edges, either way its a corner case.
- *
- * This is needed so we don't split off the edge but then none of its verts which
- * would leave a duplicate edge.
- */
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- if (UNLIKELY((BMO_elem_flag_test(bm, e->v1, VERT_SEAM) == FALSE &&
- (BMO_elem_flag_test(bm, e->v2, VERT_SEAM) == FALSE))))
- {
- BMO_elem_flag_enable(bm, e->v1, VERT_SEAM);
- BMO_elem_flag_enable(bm, e->v2, VERT_SEAM);
- }
- }
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "verts", BM_VERT, BM_ELEM_TAG, false);
}
- bm_edgesplit_validate_seams(bm, op);
-
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- if (BMO_elem_flag_test(bm, e, EDGE_SEAM)) {
- /* 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 */
- do {
- bmesh_edge_separate(bm, e, e->l);
- } while (!BM_edge_is_boundary(e));
-
- BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
- }
- }
-
- if (use_verts) {
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- if (BMO_elem_flag_test(bm, e->v1, VERT_SEAM) == FALSE) {
- BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
- }
- if (BMO_elem_flag_test(bm, e->v2, VERT_SEAM) == FALSE) {
- BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
- }
- }
- }
-
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- if (BMO_elem_flag_test(bm, e, EDGE_SEAM)) {
- if (BM_elem_flag_test(e->v1, BM_ELEM_TAG)) {
- BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
- bmesh_vert_separate(bm, e->v1, NULL, NULL);
- }
- if (BM_elem_flag_test(e->v2, BM_ELEM_TAG)) {
- BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
- bmesh_vert_separate(bm, e->v2, NULL, NULL);
- }
- }
- }
+ /* this is where everything happens */
+ BM_mesh_edgesplit(bm, use_verts, true);
BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_INTERNAL_TAG);
}
diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c
index bf3bafc57fb..62220510623 100644
--- a/source/blender/bmesh/operators/bmo_extrude.c
+++ b/source/blender/bmesh/operators/bmo_extrude.c
@@ -30,6 +30,7 @@
#include "BLI_math.h"
#include "BLI_array.h"
+#include "BLI_buffer.h"
#include "BKE_customdata.h"
@@ -51,28 +52,35 @@ enum {
void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
{
+ BMVert **verts = NULL;
+ BLI_array_declare(verts);
+ BMEdge **edges = NULL;
+ BLI_array_declare(edges);
+
BMOIter siter;
BMIter liter, liter2;
BMFace *f, *f2, *f3;
BMLoop *l, *l2, *l3, *l4, *l_tmp;
- BMEdge **edges = NULL, *e, *laste;
+ BMEdge *e, *laste;
BMVert *v, *lastv, *firstv;
- BLI_array_declare(edges);
int i;
BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
+ BLI_array_empty(verts);
BLI_array_empty(edges);
+ BLI_array_grow_items(verts, f->len);
BLI_array_grow_items(edges, f->len);
i = 0;
firstv = lastv = NULL;
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
v = BM_vert_create(bm, l->v->co, l->v, 0);
-
/* skip on the first iteration */
if (lastv) {
e = BM_edge_create(bm, lastv, v, l->e, 0);
- edges[i++] = e;
+ edges[i] = e;
+ verts[i] = lastv;
+ i++;
}
lastv = v;
@@ -82,11 +90,13 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
/* this fits in the array because we skip one in the loop above */
e = BM_edge_create(bm, v, firstv, laste, 0);
- edges[i++] = e;
+ edges[i] = e;
+ verts[i] = lastv;
+ i++;
BMO_elem_flag_enable(bm, f, EXT_DEL);
- f2 = BM_face_create_ngon(bm, firstv, BM_edge_other_vert(edges[0], firstv), edges, f->len, 0);
+ f2 = BM_face_create(bm, verts, edges, f->len, 0);
if (UNLIKELY(f2 == NULL)) {
BMO_error_raise(bm, op, BMERR_MESH_ERROR, "Extrude failed: could not create face");
BLI_array_free(edges);
@@ -103,7 +113,7 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
l3 = l->next;
l4 = l2->next;
- f3 = BM_face_create_quad_tri(bm, l3->v, l4->v, l2->v, l->v, f, FALSE);
+ f3 = BM_face_create_quad_tri(bm, l3->v, l4->v, l2->v, l->v, f, false);
/* XXX, no error check here, why? - Campbell */
l_tmp = BM_FACE_FIRST_LOOP(f3);
@@ -117,6 +127,7 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
}
}
+ BLI_array_free(verts);
BLI_array_free(edges);
BMO_op_callf(bm, op->flag,
@@ -215,7 +226,7 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op)
f_verts[3] = e_new->v2;
}
/* not sure what to do about example face, pass NULL for now */
- f = BM_face_create_quad_tri_v(bm, f_verts, 4, NULL, FALSE);
+ f = BM_face_create_quad_tri_v(bm, f_verts, 4, NULL, false);
bm_extrude_copy_face_loop_attributes(bm, f);
if (BMO_elem_flag_test(bm, e, EXT_INPUT))
@@ -238,7 +249,7 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
BMOIter siter;
BMVert *v, *dupev;
BMEdge *e;
- const int has_vskin = CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN);
+ const bool has_vskin = CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN);
for (v = BMO_iter_new(&siter, op->slots_in, "verts", BM_VERT); v; v = BMO_iter_step(&siter)) {
dupev = BM_vert_create(bm, v->co, v, 0);
@@ -261,9 +272,9 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
BMOIter siter;
BMIter iter, fiter, viter;
BMEdge *e, *e_new;
- BMVert *v, *v2;
+ BMVert *v;
BMFace *f;
- int found, fwd, delorig = FALSE;
+ bool found, fwd, delorig = false;
BMOpSlot *slot_facemap_out;
BMOpSlot *slot_edges_exclude;
@@ -283,20 +294,20 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
continue;
}
- found = FALSE; /* found a face that isn't input? */
+ found = false; /* found a face that isn't input? */
edge_face_tot = 0; /* edge/face count */
BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
if (!BMO_elem_flag_test(bm, f, EXT_INPUT)) {
- found = TRUE;
- delorig = TRUE;
+ found = true;
+ delorig = true;
break;
}
edge_face_tot++;
}
- if ((edge_face_tot > 1) && (found == FALSE)) {
+ if ((edge_face_tot > 1) && (found == false)) {
/* edge has a face user, that face isn't extrude input */
BMO_elem_flag_enable(bm, e, EXT_DEL);
}
@@ -305,27 +316,29 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
/* calculate verts to delete */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- found = FALSE;
+ if (v->e) { /* only deal with verts attached to geometry [#33651] */
+ found = false;
- BM_ITER_ELEM (e, &viter, v, BM_EDGES_OF_VERT) {
- if (!BMO_elem_flag_test(bm, e, EXT_INPUT) || !BMO_elem_flag_test(bm, e, EXT_DEL)) {
- found = TRUE;
- break;
+ BM_ITER_ELEM (e, &viter, v, BM_EDGES_OF_VERT) {
+ if (!BMO_elem_flag_test(bm, e, EXT_INPUT) || !BMO_elem_flag_test(bm, e, EXT_DEL)) {
+ found = true;
+ break;
+ }
}
- }
- /* avoid an extra loop */
- if (found == TRUE) {
- BM_ITER_ELEM (f, &viter, v, BM_FACES_OF_VERT) {
- if (!BMO_elem_flag_test(bm, f, EXT_INPUT)) {
- found = TRUE;
- break;
+ /* avoid an extra loop */
+ if (found == true) {
+ BM_ITER_ELEM (f, &viter, v, BM_FACES_OF_VERT) {
+ if (!BMO_elem_flag_test(bm, f, EXT_INPUT)) {
+ found = true;
+ break;
+ }
}
}
- }
- if (found == FALSE) {
- BMO_elem_flag_enable(bm, v, EXT_DEL);
+ if (found == false) {
+ BMO_elem_flag_enable(bm, v, EXT_DEL);
+ }
}
}
@@ -335,7 +348,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
}
}
- if (delorig == TRUE) {
+ if (delorig == true) {
BMO_op_initf(bm, &delop, op->flag,
"delete geom=%fvef context=%i",
EXT_DEL, DEL_ONLYTAGGED);
@@ -423,13 +436,13 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
}
/* not sure what to do about example face, pass NULL for now */
- f = BM_face_create_quad_tri_v(bm, f_verts, 4, NULL, FALSE);
+ f = BM_face_create_quad_tri_v(bm, f_verts, 4, NULL, false);
bm_extrude_copy_face_loop_attributes(bm, f);
}
/* link isolated vert */
for (v = BMO_iter_new(&siter, dupeop.slots_out, "isovert_map.out", 0); v; v = BMO_iter_step(&siter)) {
- v2 = *((void **)BMO_iter_map_value(&siter));
+ BMVert *v2 = *((void **)BMO_iter_map_value(&siter));
BM_edge_create(bm, v, v2, v->e, BM_CREATE_NO_DOUBLE);
}
@@ -600,15 +613,18 @@ static void solidify_add_thickness(BMesh *bm, const float dist)
float *vert_accum = vert_angles + bm->totvert;
int i, index;
+ BLI_buffer_declare_static(float, face_angles_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_buffer_declare_static(float *, verts_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
+
BM_mesh_elem_index_ensure(bm, BM_VERT);
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
if (BMO_elem_flag_test(bm, f, FACE_MARK)) {
/* array for passing verts to angle_poly_v3 */
- float *face_angles = BLI_array_alloca(face_angles, f->len);
+ float *face_angles = BLI_buffer_resize_data(&face_angles_buf, float, f->len);
/* array for receiving angles from angle_poly_v3 */
- float **verts = BLI_array_alloca(verts, f->len);
+ float **verts = BLI_buffer_resize_data(&verts_buf, float *, f->len);
BM_ITER_ELEM_INDEX (l, &loopIter, f, BM_LOOPS_OF_FACE, i) {
verts[i] = l->v->co;
@@ -627,6 +643,9 @@ static void solidify_add_thickness(BMesh *bm, const float dist)
}
}
+ BLI_buffer_free(&face_angles_buf);
+ BLI_buffer_free(&verts_buf);
+
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
index = BM_elem_index_get(v);
if (vert_accum[index]) { /* zero if unselected */
@@ -653,7 +672,7 @@ void bmo_solidify_face_region_exec(BMesh *bm, BMOperator *op)
BMO_op_finish(bm, &reverseop);
/* Extrude the region */
- BMO_op_initf(bm, &extrudeop, op->flag, "extrude_face_region use_keep_orig=%b", TRUE);
+ BMO_op_initf(bm, &extrudeop, op->flag, "extrude_face_region use_keep_orig=%b", true);
BMO_slot_copy(op, slots_in, "geom",
&extrudeop, slots_in, "geom");
BMO_op_exec(bm, &extrudeop);
diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c
index e2da4f4f89c..7dc2884c5ed 100644
--- a/source/blender/bmesh/operators/bmo_hull.c
+++ b/source/blender/bmesh/operators/bmo_hull.c
@@ -28,11 +28,11 @@
#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
#include "BLI_array.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
#include "Bullet-C-Api.h"
@@ -136,12 +136,12 @@ static void hull_output_triangles(BMesh *bm, GHash *hull_triangles)
}
/* Create new hull face */
- f = BM_face_create_quad_tri_v(bm, t->v, 3, example, TRUE);
+ f = BM_face_create_quad_tri_v(bm, t->v, 3, example, true);
BM_face_copy_shared(bm, f);
}
/* Mark face for 'geom.out' slot and select */
BMO_elem_flag_enable(bm, f, HULL_FLAG_OUTPUT_GEOM);
- BM_face_select_set(bm, f, TRUE);
+ BM_face_select_set(bm, f, true);
/* Mark edges for 'geom.out' slot */
for (i = 0; i < 3; i++) {
@@ -154,8 +154,9 @@ static void hull_output_triangles(BMesh *bm, GHash *hull_triangles)
const int next = (i == 2 ? 0 : i + 1);
BMEdge *e = BM_edge_exists(t->v[i], t->v[next]);
if (e &&
- BMO_elem_flag_test(bm, e, HULL_FLAG_INPUT) &&
- !BMO_elem_flag_test(bm, e, HULL_FLAG_HOLE)) {
+ BMO_elem_flag_test(bm, e, HULL_FLAG_INPUT) &&
+ !BMO_elem_flag_test(bm, e, HULL_FLAG_HOLE))
+ {
BMO_elem_flag_enable(bm, e, HULL_FLAG_OUTPUT_GEOM);
}
}
@@ -200,7 +201,7 @@ static int hull_final_edges_lookup(HullFinalEdges *final_edges,
adj = BLI_ghash_lookup(final_edges->edges, v1);
if (!adj)
- return FALSE;
+ return false;
return !!final_edges_find_link(adj, v2);
}
@@ -268,17 +269,17 @@ static void hull_remove_overlapping(BMesh *bm, GHash *hull_triangles,
HullTriangle *t = BLI_ghashIterator_getKey(&hull_iter);
BMIter bm_iter1, bm_iter2;
BMFace *f;
- int f_on_hull;
+ bool f_on_hull;
BM_ITER_ELEM (f, &bm_iter1, t->v[0], BM_FACES_OF_VERT) {
BMEdge *e;
/* Check that all the face's edges are on the hull,
* otherwise can't reuse it */
- f_on_hull = TRUE;
+ f_on_hull = true;
BM_ITER_ELEM (e, &bm_iter2, f, BM_EDGES_OF_FACE) {
if (!hull_final_edges_lookup(final_edges, e->v1, e->v2)) {
- f_on_hull = FALSE;
+ f_on_hull = false;
break;
}
}
@@ -288,7 +289,7 @@ static void hull_remove_overlapping(BMesh *bm, GHash *hull_triangles,
if (BM_vert_in_face(f, t->v[1]) &&
BM_vert_in_face(f, t->v[2]) && f_on_hull)
{
- t->skip = TRUE;
+ t->skip = true;
BMO_elem_flag_disable(bm, f, HULL_FLAG_INTERIOR_ELE);
BMO_elem_flag_enable(bm, f, HULL_FLAG_HOLE);
}
@@ -330,18 +331,18 @@ static void hull_tag_unused(BMesh *bm, BMOperator *op)
* input set */
BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) {
if (BMO_elem_flag_test(bm, v, HULL_FLAG_INTERIOR_ELE)) {
- int del = TRUE;
+ bool del = true;
BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
if (!BMO_elem_flag_test(bm, e, HULL_FLAG_INPUT)) {
- del = FALSE;
+ del = false;
break;
}
}
BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
if (!BMO_elem_flag_test(bm, f, HULL_FLAG_INPUT)) {
- del = FALSE;
+ del = false;
break;
}
}
@@ -353,11 +354,11 @@ static void hull_tag_unused(BMesh *bm, BMOperator *op)
BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) {
if (BMO_elem_flag_test(bm, e, HULL_FLAG_INTERIOR_ELE)) {
- int del = TRUE;
+ bool del = true;
BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
if (!BMO_elem_flag_test(bm, f, HULL_FLAG_INPUT)) {
- del = FALSE;
+ del = false;
break;
}
}
@@ -396,13 +397,13 @@ static void hull_tag_holes(BMesh *bm, BMOperator *op)
/* Mark edges too if all adjacent faces are holes and the edge is
* not already isolated */
BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) {
- int hole = TRUE;
- int any_faces = FALSE;
+ bool hole = true;
+ bool any_faces = false;
BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
- any_faces = TRUE;
+ any_faces = true;
if (!BMO_elem_flag_test(bm, f, HULL_FLAG_HOLE)) {
- hole = FALSE;
+ hole = false;
break;
}
}
diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c
index cef1181f63b..ef99dae5ac9 100644
--- a/source/blender/bmesh/operators/bmo_inset.c
+++ b/source/blender/bmesh/operators/bmo_inset.c
@@ -92,13 +92,13 @@ static BMLoop *bm_edge_is_mixed_face_tag(BMLoop *l)
void bmo_inset_exec(BMesh *bm, BMOperator *op)
{
- const int use_outset = BMO_slot_bool_get(op->slots_in, "use_outset");
- const int use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary") && (use_outset == FALSE);
- const int use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
- const int use_even_boundry = use_even_offset; /* could make own option */
- const int use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
- const float thickness = BMO_slot_float_get(op->slots_in, "thickness");
- const float depth = BMO_slot_float_get(op->slots_in, "depth");
+ const bool use_outset = BMO_slot_bool_get(op->slots_in, "use_outset");
+ const bool use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary") && (use_outset == false);
+ const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
+ const bool use_even_boundry = use_even_offset; /* could make own option */
+ const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
+ const float thickness = BMO_slot_float_get(op->slots_in, "thickness");
+ const float depth = BMO_slot_float_get(op->slots_in, "depth");
int edge_info_len = 0;
@@ -111,13 +111,13 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op)
BMFace *f;
int i, j, k;
- if (use_outset == FALSE) {
- BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, FALSE);
- BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, FALSE);
+ if (use_outset == false) {
+ BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false);
}
else {
- BM_mesh_elem_hflag_enable_all(bm, BM_FACE, BM_ELEM_TAG, FALSE);
- BMO_slot_buffer_hflag_disable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, FALSE);
+ BM_mesh_elem_hflag_enable_all(bm, BM_FACE, BM_ELEM_TAG, false);
+ BMO_slot_buffer_hflag_disable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false);
}
/* first count all inset edges we will split */
@@ -411,11 +411,11 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op)
/* this saves expensive/slow glue check for common cases */
if (r_vout_len > 2) {
- int ok = TRUE;
+ bool ok = true;
/* last step, NULL this vertex if has a tagged face */
BM_ITER_ELEM (f, &iter, v_split, BM_FACES_OF_VERT) {
if (BM_elem_flag_test(f, BM_ELEM_TAG)) {
- ok = FALSE;
+ ok = false;
break;
}
}
@@ -471,7 +471,7 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op)
#endif
/* no need to check doubles, we KNOW there won't be any */
/* yes - reverse face is correct in this case */
- f = BM_face_create_quad_tri_v(bm, varr, j, es->l->f, FALSE);
+ f = BM_face_create_quad_tri_v(bm, varr, j, es->l->f, false);
BMO_elem_flag_enable(bm, f, ELE_NEW);
/* copy for loop data, otherwise UV's and vcols are no good.
@@ -548,7 +548,7 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op)
/* done correcting edge verts normals */
/* untag verts */
- BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, FALSE);
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
/* tag face verts */
BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c
index 45ecdee014e..e052968a6a0 100644
--- a/source/blender/bmesh/operators/bmo_join_triangles.c
+++ b/source/blender/bmesh/operators/bmo_join_triangles.c
@@ -105,7 +105,7 @@ static float measure_facepair(BMVert *v1, BMVert *v2,
#define T2QUV_LIMIT 0.005f
#define T2QCOL_LIMIT 3
-static int bm_edge_faces_cmp(BMesh *bm, BMEdge *e, const int do_uv, const int do_tf, const int do_vcol)
+static bool bm_edge_faces_cmp(BMesh *bm, BMEdge *e, const bool do_uv, const bool do_tf, const bool do_vcol)
{
/* first get loops */
BMLoop *l[4];
@@ -138,7 +138,7 @@ static int bm_edge_faces_cmp(BMesh *bm, BMEdge *e, const int do_uv, const int do
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;
+ return false;
}
}
@@ -149,7 +149,7 @@ static int bm_edge_faces_cmp(BMesh *bm, BMEdge *e, const int do_uv, const int do
};
if (tp[0] && (tp[0]->tpage != tp[1]->tpage)) {
- return FALSE;
+ return false;
}
}
@@ -166,12 +166,12 @@ static int bm_edge_faces_cmp(BMesh *bm, BMEdge *e, const int do_uv, const int do
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;
+ return false;
}
}
}
- return TRUE;
+ return true;
}
typedef struct JoinEdge {
@@ -197,6 +197,13 @@ static int fplcmp(const void *v1, const void *v2)
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");
+
BMIter iter, liter;
BMOIter siter;
BMFace *f;
@@ -204,12 +211,6 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
BMEdge *e;
BLI_array_declare(jedges);
JoinEdge *jedges = NULL;
- int do_sharp = BMO_slot_bool_get(op->slots_in, "cmp_sharp");
- int do_uv = BMO_slot_bool_get(op->slots_in, "cmp_uvs");
- int do_tf = do_uv; /* texture face, make make its own option eventually */
- int do_vcol = BMO_slot_bool_get(op->slots_in, "cmp_vcols");
- int do_mat = BMO_slot_bool_get(op->slots_in, "cmp_materials");
- float limit = BMO_slot_float_get(op->slots_in, "limit");
int i, totedge;
/* flag all edges of all input face */
@@ -265,7 +266,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
if (do_mat && f1->mat_nr != f2->mat_nr)
continue;
- if ((do_uv || do_tf || do_vcol) && (bm_edge_faces_cmp(bm, e, do_uv, do_tf, do_vcol) == FALSE))
+ if ((do_uv || do_tf || do_vcol) && (bm_edge_faces_cmp(bm, e, do_uv, do_tf, do_vcol) == false))
continue;
measure = measure_facepair(v1, v2, v3, v4, limit);
@@ -308,7 +309,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
BM_edge_face_pair(e, &f1, &f2); /* checked above */
- BM_faces_join_pair(bm, f1, f2, e, TRUE);
+ BM_faces_join_pair(bm, f1, f2, e, true);
}
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
@@ -342,7 +343,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
continue;
}
- BM_faces_join_pair(bm, f1, f2, e, TRUE);
+ BM_faces_join_pair(bm, f1, f2, e, true);
}
}
diff --git a/source/blender/bmesh/operators/bmo_mesh_conv.c b/source/blender/bmesh/operators/bmo_mesh_conv.c
index 4b897a24c8a..0976c4cdfbb 100644
--- a/source/blender/bmesh/operators/bmo_mesh_conv.c
+++ b/source/blender/bmesh/operators/bmo_mesh_conv.c
@@ -36,6 +36,9 @@
#include "DNA_key_types.h"
#include "DNA_modifier_types.h"
+#include "BLI_math.h"
+#include "BLI_array.h"
+
#include "BKE_mesh.h"
#include "BLI_listbase.h"
#include "BKE_global.h"
@@ -43,9 +46,6 @@
#include "BKE_main.h"
#include "BKE_customdata.h"
-#include "BLI_math.h"
-#include "BLI_array.h"
-
#include "bmesh.h"
#include "intern/bmesh_private.h"
@@ -53,9 +53,9 @@
void bmo_mesh_to_bmesh_exec(BMesh *bm, BMOperator *op)
{
- Object *ob = BMO_slot_ptr_get(op->slots_in, "object");
- Mesh *me = BMO_slot_ptr_get(op->slots_in, "mesh");
- int set_key = BMO_slot_bool_get(op->slots_in, "use_shapekey");
+ Object *ob = BMO_slot_ptr_get(op->slots_in, "object");
+ Mesh *me = BMO_slot_ptr_get(op->slots_in, "mesh");
+ bool set_key = BMO_slot_bool_get(op->slots_in, "use_shapekey");
BM_mesh_bm_from_me(bm, me, set_key, ob->shapenr);
@@ -72,14 +72,14 @@ void bmo_object_load_bmesh_exec(BMesh *bm, BMOperator *op)
BMO_op_callf(bm, op->flag,
"bmesh_to_mesh mesh=%p object=%p skip_tessface=%b",
- me, ob, TRUE);
+ me, ob, true);
}
void bmo_bmesh_to_mesh_exec(BMesh *bm, BMOperator *op)
{
Mesh *me = BMO_slot_ptr_get(op->slots_in, "mesh");
/* Object *ob = BMO_slot_ptr_get(op, "object"); */
- int dotess = !BMO_slot_bool_get(op->slots_in, "skip_tessface");
+ const bool dotess = !BMO_slot_bool_get(op->slots_in, "skip_tessface");
BM_mesh_bm_to_me(bm, me, dotess);
}
diff --git a/source/blender/bmesh/operators/bmo_mirror.c b/source/blender/bmesh/operators/bmo_mirror.c
index 61b061dd21f..48b2f76665c 100644
--- a/source/blender/bmesh/operators/bmo_mirror.c
+++ b/source/blender/bmesh/operators/bmo_mirror.c
@@ -53,8 +53,8 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op)
float dist = BMO_slot_float_get(op->slots_in, "merge_dist");
int i, ototvert /*, ototedge */;
int axis = BMO_slot_int_get(op->slots_in, "axis");
- int mirroru = BMO_slot_bool_get(op->slots_in, "mirror_u");
- int mirrorv = BMO_slot_bool_get(op->slots_in, "mirror_v");
+ bool mirror_u = BMO_slot_bool_get(op->slots_in, "mirror_u");
+ bool mirror_v = BMO_slot_bool_get(op->slots_in, "mirror_v");
BMOpSlot *slot_targetmap;
ototvert = bm->totvert;
@@ -97,7 +97,7 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op)
v = BM_iter_step(&iter);
}
- if (mirroru || mirrorv) {
+ if (mirror_u || mirror_v) {
BMFace *f;
BMLoop *l;
MLoopUV *luv;
@@ -109,9 +109,9 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op)
totlayer = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
for (i = 0; i < totlayer; i++) {
luv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
- if (mirroru)
+ if (mirror_u)
luv->uv[0] = 1.0f - luv->uv[0];
- if (mirrorv)
+ if (mirror_v)
luv->uv[1] = 1.0f - luv->uv[1];
}
}
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index c582f710f43..011002718d3 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -420,7 +420,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op)
v2 = eva[icoface[a][1]];
v3 = eva[icoface[a][2]];
- eftemp = BM_face_create_quad_tri(bm, v1, v2, v3, NULL, NULL, FALSE);
+ eftemp = BM_face_create_quad_tri(bm, v1, v2, v3, NULL, NULL, false);
BM_ITER_ELEM (l, &liter, eftemp, BM_LOOPS_OF_FACE) {
BMO_elem_flag_enable(bm, l->e, EDGE_MARK);
@@ -438,7 +438,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op)
"cuts=%i "
"use_grid_fill=%b use_sphere=%b",
EDGE_MARK, dia, (1 << (subdiv - 1)) - 1,
- TRUE, TRUE);
+ true, true);
BMO_op_exec(bm, &bmop);
BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK);
@@ -488,14 +488,14 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op)
tv[monkeyf[i][1] + i - monkeyo],
tv[monkeyf[i][2] + i - monkeyo],
(monkeyf[i][3] != monkeyf[i][2]) ? tv[monkeyf[i][3] + i - monkeyo] : NULL,
- NULL, FALSE);
+ NULL, false);
BM_face_create_quad_tri(bm,
tv[monkeynv + monkeyf[i][2] + i - monkeyo],
tv[monkeynv + monkeyf[i][1] + i - monkeyo],
tv[monkeynv + monkeyf[i][0] + i - monkeyo],
(monkeyf[i][3] != monkeyf[i][2]) ? tv[monkeynv + monkeyf[i][3] + i - monkeyo] : NULL,
- NULL, FALSE);
+ NULL, false);
}
MEM_freeN(tv);
@@ -508,8 +508,8 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
{
const float dia = BMO_slot_float_get(op->slots_in, "diameter");
const int segs = BMO_slot_int_get(op->slots_in, "segments");
- const int cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends");
- const int cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris");
+ const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends");
+ const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris");
BMVert *v1, *lastv1 = NULL, *cent1, *firstv1 = NULL;
float vec[3], mat[4][4], phi, phid;
@@ -547,7 +547,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
if (a && cap_ends) {
BMFace *f;
- f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, FALSE);
+ f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, false);
BMO_elem_flag_enable(bm, f, FACE_NEW);
}
@@ -565,7 +565,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
if (cap_ends) {
BMFace *f;
- f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, FALSE);
+ f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, false);
BMO_elem_flag_enable(bm, f, FACE_NEW);
}
@@ -584,8 +584,8 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
float dia2 = BMO_slot_float_get(op->slots_in, "diameter2");
float depth = BMO_slot_float_get(op->slots_in, "depth");
int segs = BMO_slot_int_get(op->slots_in, "segments");
- int cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends");
- int cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris");
+ const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends");
+ const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris");
int a;
if (!segs)
@@ -634,12 +634,12 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
if (cap_ends) {
BMFace *f;
- f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, FALSE);
+ f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, false);
BMO_elem_flag_enable(bm, f, FACE_NEW);
- f = BM_face_create_quad_tri(bm, cent2, v2, lastv2, NULL, NULL, FALSE);
+ f = BM_face_create_quad_tri(bm, cent2, v2, lastv2, NULL, NULL, false);
BMO_elem_flag_enable(bm, f, FACE_NEW);
}
- BM_face_create_quad_tri(bm, lastv1, lastv2, v2, v1, NULL, FALSE);
+ BM_face_create_quad_tri(bm, lastv1, lastv2, v2, v1, NULL, false);
}
else {
firstv1 = v1;
@@ -656,9 +656,9 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
if (cap_ends) {
BMFace *f;
- f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, FALSE);
+ f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, false);
BMO_elem_flag_enable(bm, f, FACE_NEW);
- f = BM_face_create_quad_tri(bm, cent2, firstv2, v2, NULL, NULL, FALSE);
+ f = BM_face_create_quad_tri(bm, cent2, firstv2, v2, NULL, NULL, false);
BMO_elem_flag_enable(bm, f, FACE_NEW);
}
@@ -666,7 +666,7 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_NEW);
}
- BM_face_create_quad_tri(bm, v1, v2, firstv2, firstv1, NULL, FALSE);
+ BM_face_create_quad_tri(bm, v1, v2, firstv2, firstv1, NULL, false);
BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, 0.000001);
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
@@ -738,14 +738,14 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op)
BMO_elem_flag_enable(bm, v8, VERT_MARK);
/* the four sides */
- BM_face_create_quad_tri(bm, v5, v6, v2, v1, NULL, FALSE);
- BM_face_create_quad_tri(bm, v6, v7, v3, v2, NULL, FALSE);
- BM_face_create_quad_tri(bm, v7, v8, v4, v3, NULL, FALSE);
- BM_face_create_quad_tri(bm, v8, v5, v1, v4, NULL, FALSE);
+ BM_face_create_quad_tri(bm, v5, v6, v2, v1, NULL, false);
+ BM_face_create_quad_tri(bm, v6, v7, v3, v2, NULL, false);
+ BM_face_create_quad_tri(bm, v7, v8, v4, v3, NULL, false);
+ BM_face_create_quad_tri(bm, v8, v5, v1, v4, NULL, false);
/* top/bottom */
- BM_face_create_quad_tri(bm, v1, v2, v3, v4, NULL, FALSE);
- BM_face_create_quad_tri(bm, v8, v7, v6, v5, NULL, FALSE);
+ BM_face_create_quad_tri(bm, v1, v2, v3, v4, NULL, false);
+ BM_face_create_quad_tri(bm, v8, v7, v6, v5, NULL, false);
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 87e26f11d4b..8b65764fe1c 100644
--- a/source/blender/bmesh/operators/bmo_removedoubles.c
+++ b/source/blender/bmesh/operators/bmo_removedoubles.c
@@ -40,8 +40,8 @@ static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op, BMOpSlot
{
BMIter liter;
BMLoop *l;
- BMVert *v2, *doub;
- int split = FALSE;
+ BMVert *v2, *v_double;
+ bool split = false;
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
v2 = BMO_slot_map_elem_get(slot_targetmap, l->v);
@@ -51,15 +51,15 @@ static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op, BMOpSlot
(v2 != l->prev->v) &&
(v2 != l->next->v))
{
- doub = l->v;
- split = TRUE;
+ v_double = l->v;
+ split = true;
break;
}
}
- if (split && doub != v2) {
- BMLoop *nl;
- BMFace *f2 = BM_face_split(bm, f, doub, v2, &nl, NULL, FALSE);
+ if (split && v_double != v2) {
+ BMLoop *l_new;
+ BMFace *f2 = BM_face_split(bm, f, v_double, v2, &l_new, NULL, false);
remdoubles_splitface(f, bm, op, slot_targetmap);
remdoubles_splitface(f2, bm, op, slot_targetmap);
@@ -87,12 +87,12 @@ int remdoubles_face_overlaps(BMesh *bm, BMVert **varr,
amount = BM_verts_in_face(bm, f, varr, len);
if (amount >= len) {
if (overlapface) *overlapface = f;
- return TRUE;
+ return true;
}
f = BM_iter_step(&vertfaces);
}
}
- return FALSE;
+ return false;
}
#endif
@@ -394,11 +394,10 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op)
if (!BMO_elem_flag_test(bm, e, EDGE_MARK))
continue;
- e = BMW_begin(&walker, e->v1);
BLI_array_empty(edges);
INIT_MINMAX(min, max);
- for (tot = 0; e; tot++, e = BMW_step(&walker)) {
+ for (e = BMW_begin(&walker, e->v1), tot = 0; e; e = BMW_step(&walker), tot++) {
BLI_array_grow_one(edges);
edges[tot] = e;
@@ -454,11 +453,9 @@ static void bmo_collapsecon_do_layer(BMesh *bm, BMOperator *op, int layer)
if (BMO_elem_flag_test(bm, l->e, EDGE_MARK)) {
/* walk */
BLI_array_empty(blocks);
- tot = 0;
- l2 = BMW_begin(&walker, l);
CustomData_data_initminmax(type, &min, &max);
- for (tot = 0; l2; tot++, l2 = BMW_step(&walker)) {
+ 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);
diff --git a/source/blender/bmesh/operators/bmo_similar.c b/source/blender/bmesh/operators/bmo_similar.c
index 548e1adf17d..5bea47969da 100644
--- a/source/blender/bmesh/operators/bmo_similar.c
+++ b/source/blender/bmesh/operators/bmo_similar.c
@@ -185,21 +185,21 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
for (i = 0; i < num_total; i++) {
fm = f_ext[i].f;
if (!BMO_elem_flag_test(bm, fm, FACE_MARK) && !BM_elem_flag_test(fm, BM_ELEM_HIDDEN)) {
- int cont = TRUE;
- for (idx = 0; idx < num_sels && cont == TRUE; idx++) {
+ bool cont = true;
+ for (idx = 0; idx < num_sels && cont == true; idx++) {
fs = f_ext[indices[idx]].f;
switch (type) {
case SIMFACE_MATERIAL:
if (fm->mat_nr == fs->mat_nr) {
BMO_elem_flag_enable(bm, fm, FACE_MARK);
- cont = FALSE;
+ cont = false;
}
break;
case SIMFACE_IMAGE:
if (f_ext[i].t == f_ext[indices[idx]].t) {
BMO_elem_flag_enable(bm, fm, FACE_MARK);
- cont = FALSE;
+ cont = false;
}
break;
@@ -207,7 +207,7 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
angle = angle_normalized_v3v3(fs->no, fm->no); /* if the angle between the normals -> 0 */
if (angle <= thresh_radians) {
BMO_elem_flag_enable(bm, fm, FACE_MARK);
- cont = FALSE;
+ cont = false;
}
break;
@@ -217,7 +217,7 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
delta_fl = f_ext[i].d - f_ext[indices[idx]].d;
if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) {
BMO_elem_flag_enable(bm, fm, FACE_MARK);
- cont = FALSE;
+ cont = false;
}
}
break;
@@ -226,7 +226,7 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
delta_fl = f_ext[i].area - f_ext[indices[idx]].area;
if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) {
BMO_elem_flag_enable(bm, fm, FACE_MARK);
- cont = FALSE;
+ cont = false;
}
break;
@@ -234,7 +234,7 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
delta_i = fm->len - fs->len;
if (bm_sel_similar_cmp_i(delta_i, compare)) {
BMO_elem_flag_enable(bm, fm, FACE_MARK);
- cont = FALSE;
+ cont = false;
}
break;
@@ -242,9 +242,24 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op)
delta_fl = f_ext[i].perim - f_ext[indices[idx]].perim;
if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) {
BMO_elem_flag_enable(bm, fm, FACE_MARK);
- cont = FALSE;
+ cont = false;
}
break;
+#ifdef WITH_FREESTYLE
+ case SIMFACE_FREESTYLE:
+ if (CustomData_has_layer(&bm->pdata, CD_FREESTYLE_FACE)) {
+ FreestyleEdge *ffa1, *ffa2;
+
+ ffa1 = CustomData_bmesh_get(&bm->pdata, fs->head.data, CD_FREESTYLE_FACE);
+ ffa2 = CustomData_bmesh_get(&bm->pdata, fm->head.data, CD_FREESTYLE_FACE);
+
+ if (ffa1 && ffa2 && (ffa1->flag & FREESTYLE_FACE_MARK) == (ffa2->flag & FREESTYLE_FACE_MARK)) {
+ BMO_elem_flag_enable(bm, fm, FACE_MARK);
+ cont = false;
+ }
+ }
+ break;
+#endif
default:
BLI_assert(0);
}
@@ -373,15 +388,15 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op)
for (i = 0; i < num_total; i++) {
e = e_ext[i].e;
if (!BMO_elem_flag_test(bm, e, EDGE_MARK) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- int cont = TRUE;
- for (idx = 0; idx < num_sels && cont == TRUE; idx++) {
+ bool cont = true;
+ for (idx = 0; idx < num_sels && cont == true; idx++) {
es = e_ext[indices[idx]].e;
switch (type) {
case SIMEDGE_LENGTH:
delta_fl = e_ext[i].length - e_ext[indices[idx]].length;
if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) {
BMO_elem_flag_enable(bm, e, EDGE_MARK);
- cont = FALSE;
+ cont = false;
}
break;
@@ -394,7 +409,7 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op)
if (angle / (float)(M_PI / 2.0) <= thresh) {
BMO_elem_flag_enable(bm, e, EDGE_MARK);
- cont = FALSE;
+ cont = false;
}
break;
@@ -402,7 +417,7 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op)
delta_i = e_ext[i].faces - e_ext[indices[idx]].faces;
if (bm_sel_similar_cmp_i(delta_i, compare)) {
BMO_elem_flag_enable(bm, e, EDGE_MARK);
- cont = FALSE;
+ cont = false;
}
break;
@@ -411,12 +426,12 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op)
if (e_ext[indices[idx]].faces == 2) {
if (fabsf(e_ext[i].angle - e_ext[indices[idx]].angle) <= thresh) {
BMO_elem_flag_enable(bm, e, EDGE_MARK);
- cont = FALSE;
+ cont = false;
}
}
}
else {
- cont = FALSE;
+ cont = false;
}
break;
@@ -430,7 +445,7 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op)
if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) {
BMO_elem_flag_enable(bm, e, EDGE_MARK);
- cont = FALSE;
+ cont = false;
}
}
break;
@@ -445,7 +460,7 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op)
if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) {
BMO_elem_flag_enable(bm, e, EDGE_MARK);
- cont = FALSE;
+ cont = false;
}
}
break;
@@ -453,16 +468,31 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op)
case SIMEDGE_SEAM:
if (BM_elem_flag_test(e, BM_ELEM_SEAM) == BM_elem_flag_test(es, BM_ELEM_SEAM)) {
BMO_elem_flag_enable(bm, e, EDGE_MARK);
- cont = FALSE;
+ cont = false;
}
break;
case SIMEDGE_SHARP:
if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == BM_elem_flag_test(es, BM_ELEM_SMOOTH)) {
BMO_elem_flag_enable(bm, e, EDGE_MARK);
- cont = FALSE;
+ cont = false;
+ }
+ break;
+#ifdef WITH_FREESTYLE
+ case SIMEDGE_FREESTYLE:
+ if (CustomData_has_layer(&bm->edata, CD_FREESTYLE_EDGE)) {
+ FreestyleEdge *fed1, *fed2;
+
+ fed1 = CustomData_bmesh_get(&bm->edata, e->head.data, CD_FREESTYLE_EDGE);
+ fed2 = CustomData_bmesh_get(&bm->edata, es->head.data, CD_FREESTYLE_EDGE);
+
+ if (fed1 && fed2 && (fed1->flag & FREESTYLE_EDGE_MARK) == (fed2->flag & FREESTYLE_EDGE_MARK)) {
+ BMO_elem_flag_enable(bm, e, EDGE_MARK);
+ cont = false;
+ }
}
break;
+#endif
default:
BLI_assert(0);
}
@@ -562,15 +592,15 @@ void bmo_similar_verts_exec(BMesh *bm, BMOperator *op)
for (i = 0; i < num_total; i++) {
v = v_ext[i].v;
if (!BMO_elem_flag_test(bm, v, VERT_MARK) && !BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
- int cont = TRUE;
- for (idx = 0; idx < num_sels && cont == TRUE; idx++) {
+ bool cont = true;
+ for (idx = 0; idx < num_sels && cont == true; idx++) {
vs = v_ext[indices[idx]].v;
switch (type) {
case SIMVERT_NORMAL:
/* compare the angle between the normals */
if (angle_normalized_v3v3(v->no, vs->no) <= thresh_radians) {
BMO_elem_flag_enable(bm, v, VERT_MARK);
- cont = FALSE;
+ cont = false;
}
break;
case SIMVERT_FACE:
@@ -578,7 +608,7 @@ void bmo_similar_verts_exec(BMesh *bm, BMOperator *op)
delta_i = v_ext[i].num_faces - v_ext[indices[idx]].num_faces;
if (bm_sel_similar_cmp_i(delta_i, compare)) {
BMO_elem_flag_enable(bm, v, VERT_MARK);
- cont = FALSE;
+ cont = false;
}
break;
@@ -586,7 +616,7 @@ void bmo_similar_verts_exec(BMesh *bm, BMOperator *op)
if (v_ext[i].dvert != NULL && v_ext[indices[idx]].dvert != NULL) {
if (defvert_find_shared(v_ext[i].dvert, v_ext[indices[idx]].dvert) != -1) {
BMO_elem_flag_enable(bm, v, VERT_MARK);
- cont = FALSE;
+ cont = false;
}
}
break;
@@ -595,7 +625,7 @@ void bmo_similar_verts_exec(BMesh *bm, BMOperator *op)
delta_i = v_ext[i].num_edges - v_ext[indices[idx]].num_edges;
if (bm_sel_similar_cmp_i(delta_i, compare)) {
BMO_elem_flag_enable(bm, v, VERT_MARK);
- cont = FALSE;
+ cont = false;
}
break;
default:
diff --git a/source/blender/bmesh/operators/bmo_slide.c b/source/blender/bmesh/operators/bmo_slide.c
deleted file mode 100644
index ea9f9bf9eba..00000000000
--- a/source/blender/bmesh/operators/bmo_slide.c
+++ /dev/null
@@ -1,113 +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.
- *
- * Contributor(s): Francisco De La Cruz
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/bmesh/operators/bmo_slide.c
- * \ingroup bmesh
- */
-
-#include "MEM_guardedalloc.h"
-
-#include "BKE_global.h"
-
-#include "BLI_math.h"
-
-#include "bmesh.h"
-#include "intern/bmesh_operators_private.h" /* own include */
-
-#define EDGE_MARK 1
-#define VERT_MARK 2
-
-/*
- * Slides a vertex along a connected edge
- *
- */
-void bmo_slide_vert_exec(BMesh *bm, BMOperator *op)
-{
- BMOIter oiter;
- BMIter iter;
- BMHeader *h;
- BMVert *vertex;
- BMEdge *edge;
- BMEdge *slide_edge;
-
- /* Selection counts */
- int selected_edges = 0;
-
- /* Get slide amount */
- const float factor = BMO_slot_float_get(op->slots_in, "factor");
-
- /* Get start vertex */
- vertex = BMO_slot_buffer_get_single(BMO_slot_get(op->slots_in, "vert"));
-
- if (!vertex) {
- if (G.debug & G_DEBUG) {
- fprintf(stderr, "slide_vert: No vertex selected...");
- }
- BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Vertex Slide error: invalid selection");
- return;
- }
-
- /* BMESH_TODO - this is odd, it only uses one edge, why take a list at all? */
- /* Count selected edges */
- BMO_ITER (h, &oiter, op->slots_in, "edges", BM_EDGE) {
- selected_edges++;
- /* Mark all selected edges (cast BMHeader->BMEdge) */
- BMO_elem_flag_enable(bm, (BMElemF *)h, EDGE_MARK);
- break;
- }
-
- /* Only allow sliding if an edge is selected */
- if (selected_edges == 0) {
- if (G.debug & G_DEBUG) {
- fprintf(stderr, "slide_vert: select a single edge\n");
- }
- BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Vertex Slide error: invalid selection");
- return;
- }
-
- /* Make sure we get the correct edge. */
- slide_edge = NULL;
- BM_ITER_ELEM (edge, &iter, vertex, BM_EDGES_OF_VERT) {
- if (BMO_elem_flag_test(bm, edge, EDGE_MARK) && BM_vert_in_edge(edge, vertex)) {
- slide_edge = edge;
- break;
- }
- }
-
- /* Found edge */
- if (slide_edge) {
- BMVert *other = BM_edge_other_vert(slide_edge, vertex);
-
- /* mark */
- BMO_elem_flag_enable(bm, vertex, VERT_MARK);
-
- /* Interpolate */
- interp_v3_v3v3(vertex->co, vertex->co, other->co, factor);
- }
-
- /* Return the new edge. The same previously marked with VERT_MARK */
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
- return;
-}
-
-#undef EDGE_MARK
-#undef VERT_MARK
diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
index 4a367a8fd6f..6b91d5fded9 100644
--- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c
+++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
@@ -29,10 +29,10 @@
#include "DNA_meshdata_types.h"
#include "BLI_array.h"
-#include "BLI_heap.h"
#include "BLI_math.h"
#include "BLI_math_geom.h"
#include "BLI_smallhash.h"
+#include "BLI_heap.h"
#include "BKE_customdata.h"
#include "BKE_mesh.h"
@@ -69,7 +69,6 @@ struct BLaplacianSystem {
};
typedef struct BLaplacianSystem LaplacianSystem;
-static float compute_volume(BMesh *bm);
static float cotan_weight(float *v1, float *v2, float *v3);
static int vert_is_boundary(BMVert *v);
static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts);
@@ -85,7 +84,6 @@ static void delete_void_pointer(void *data)
{
if (data) {
MEM_freeN(data);
- data = NULL;
}
}
@@ -180,7 +178,7 @@ static void init_laplacian_matrix(LaplacianSystem *sys)
float *v1, *v2, *v3, *v4;
float w1, w2, w3, w4;
int i, j;
- int has_4_vert;
+ bool has_4_vert;
unsigned int idv1, idv2, idv3, idv4, idv[4];
BMEdge *e;
BMFace *f;
@@ -297,7 +295,7 @@ static void fill_laplacian_matrix(LaplacianSystem *sys)
float *v1, *v2, *v3, *v4;
float w2, w3, w4;
int i, j;
- int has_4_vert;
+ bool has_4_vert;
unsigned int idv1, idv2, idv3, idv4, idv[4];
BMEdge *e;
@@ -416,45 +414,6 @@ static int vert_is_boundary(BMVert *v)
return 0;
}
-static float compute_volume(BMesh *bm)
-{
- float vol = 0.0f;
- float x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4;
- int i;
- BMFace *f;
- BMIter fiter;
- BMIter vi;
- BMVert *vn;
- BMVert *vf[4];
-
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, i) {
- vf[i] = vn;
- }
- x1 = vf[0]->co[0];
- y1 = vf[0]->co[1];
- z1 = vf[0]->co[2];
-
- x2 = vf[1]->co[0];
- y2 = vf[1]->co[1];
- z2 = vf[1]->co[2];
-
- x3 = vf[2]->co[0];
- y3 = vf[2]->co[1];
- z3 = vf[2]->co[2];
-
- vol += (1.0f / 6.0f) * (0.0f - x3 * y2 * z1 + x2 * y3 * z1 + x3 * y1 * z2 - x1 * y3 * z2 - x2 * y1 * z3 + x1 * y2 * z3);
-
- if (i == 4) {
- x4 = vf[3]->co[0];
- y4 = vf[3]->co[1];
- z4 = vf[3]->co[2];
- vol += (1.0f / 6.0f) * (x1 * y3 * z4 - x1 * y4 * z3 - x3 * y1 * z4 + x3 * z1 * y4 + y1 * x4 * z3 - x4 * y3 * z1);
- }
- }
- return fabs(vol);
-}
-
static void volume_preservation(BMOperator *op, float vini, float vend, int usex, int usey, int usez)
{
float beta;
@@ -510,7 +469,7 @@ static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez
}
if (preserve_volume) {
- vini = compute_volume(sys->bm);
+ vini = BM_mesh_calc_volume(sys->bm);
}
BMO_ITER (v, &siter, sys->op->slots_in, "verts", BM_VERT) {
m_vertex_id = BM_elem_index_get(v);
@@ -527,7 +486,7 @@ static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez
}
}
if (preserve_volume) {
- vend = compute_volume(sys->bm);
+ vend = BM_mesh_calc_volume(sys->bm);
volume_preservation(sys->op, vini, vend, usex, usey, usez);
}
@@ -537,8 +496,8 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op)
{
int i;
int m_vertex_id;
- int usex, usey, usez, preserve_volume;
- float lambda, lambda_border;
+ bool usex, usey, usez, preserve_volume;
+ float lambda_factor, lambda_border;
float w;
BMOIter siter;
BMVert *v;
@@ -553,7 +512,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op)
memset_laplacian_system(sys, 0);
BM_mesh_elem_index_ensure(bm, BM_VERT);
- lambda = BMO_slot_float_get(op->slots_in, "lambda");
+ lambda_factor = BMO_slot_float_get(op->slots_in, "lambda_factor");
lambda_border = BMO_slot_float_get(op->slots_in, "lambda_border");
sys->min_area = 0.00001f;
usex = BMO_slot_bool_get(op->slots_in, "use_x");
@@ -592,12 +551,12 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op)
i = m_vertex_id;
if (sys->zerola[i] == 0) {
w = sys->vweights[i] * sys->ring_areas[i];
- sys->vweights[i] = (w == 0.0f) ? 0.0f : -lambda / (4.0f * w);
+ sys->vweights[i] = (w == 0.0f) ? 0.0f : -lambda_factor / (4.0f * w);
w = sys->vlengths[i];
sys->vlengths[i] = (w == 0.0f) ? 0.0f : -lambda_border * 2.0f / w;
if (!vert_is_boundary(v)) {
- nlMatrixAdd(i, i, 1.0f + lambda / (4.0f * sys->ring_areas[i]));
+ nlMatrixAdd(i, i, 1.0f + lambda_factor / (4.0f * sys->ring_areas[i]));
}
else {
nlMatrixAdd(i, i, 1.0f + lambda_border * 2.0f);
diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c
index 7407eb4423a..88e903c1651 100644
--- a/source/blender/bmesh/operators/bmo_subdivide.c
+++ b/source/blender/bmesh/operators/bmo_subdivide.c
@@ -40,7 +40,47 @@
#include "intern/bmesh_operators_private.h" /* own include */
-#include "bmo_subdivide.h" /* own include */
+typedef struct SubDParams {
+ int numcuts;
+ float smooth;
+ float fractal;
+ float along_normal;
+ //int beauty;
+ bool use_smooth;
+ bool use_sphere;
+ bool use_fractal;
+ int seed;
+ int origkey; /* shapekey holding displaced vertex coordinates for current geometry */
+ BMOperator *op;
+ BMOpSlot *slot_edge_percents; /* BMO_slot_get(params->op->slots_in, "edge_percents"); */
+ BMOpSlot *slot_custom_patterns; /* BMO_slot_get(params->op->slots_in, "custom_patterns"); */
+ float fractal_ofs[3];
+} SubDParams;
+
+typedef void (*subd_pattern_fill_fp)(BMesh *bm, BMFace *face, BMVert **verts,
+ const SubDParams *params);
+
+/*
+ * note: this is a pattern-based edge subdivider.
+ * it tries to match a pattern to edge selections on faces,
+ * then executes functions to cut them.
+ */
+typedef struct SubDPattern {
+ int seledges[20]; /* selected edges mask, for splitting */
+
+ /* verts starts at the first new vert cut, not the first vert in the face */
+ subd_pattern_fill_fp connectexec;
+ int len; /* total number of verts, before any subdivision */
+} SubDPattern;
+
+/* generic subdivision rules:
+ *
+ * - two selected edges in a face should make a link
+ * between them.
+ *
+ * - one edge should do, what? make pretty topology, or just
+ * split the edge only?
+ */
/* flags for all elements share a common bitfield space */
#define SUBD_SPLIT 1
@@ -71,29 +111,29 @@
/* connects face with smallest len, which I think should always be correct for
* edge subdivision */
-static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **r_nf)
+static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **r_f_new)
{
BMIter iter, iter2;
BMVert *v;
- BMLoop *nl;
- BMFace *face, *curf = NULL;
+ BMLoop *l_new;
+ BMFace *f, *f_cur = NULL;
/* this isn't the best thing in the world. it doesn't handle cases where there's
* multiple faces yet. that might require a convexity test to figure out which
* face is "best" and who knows what for non-manifold conditions. */
- for (face = BM_iter_new(&iter, bm, BM_FACES_OF_VERT, v1); face; face = BM_iter_step(&iter)) {
- for (v = BM_iter_new(&iter2, bm, BM_VERTS_OF_FACE, face); v; v = BM_iter_step(&iter2)) {
+ for (f = BM_iter_new(&iter, bm, BM_FACES_OF_VERT, v1); f; f = BM_iter_step(&iter)) {
+ for (v = BM_iter_new(&iter2, bm, BM_VERTS_OF_FACE, f); v; v = BM_iter_step(&iter2)) {
if (v == v2) {
- if (!curf || face->len < curf->len) curf = face;
+ if (!f_cur || f->len < f_cur->len) f_cur = f;
}
}
}
- if (curf) {
- face = BM_face_split(bm, curf, v1, v2, &nl, NULL, FALSE);
+ if (f_cur) {
+ f = BM_face_split(bm, f_cur, v1, v2, &l_new, NULL, false);
- if (r_nf) *r_nf = face;
- return nl ? nl->e : NULL;
+ if (r_f_new) *r_f_new = f;
+ return l_new ? l_new->e : NULL;
}
return NULL;
@@ -151,7 +191,7 @@ static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), const SubDPar
mid_v3_v3v3(normal, vsta->no, vend->no);
ortho_basis_v3v3_v3(base1, base2, normal);
- add_v3_v3v3(co2, v->co, params->off);
+ add_v3_v3v3(co2, v->co, params->fractal_ofs);
mul_v3_fl(co2, 10.0f);
tvec[0] = fac * (BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 2) - 0.5f);
@@ -165,7 +205,7 @@ static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), const SubDPar
}
/* apply the new difference to the rest of the shape keys,
- * note that this dosn't take rotations into account, we _could_ support
+ * note that this doesn't take rotations into account, we _could_ support
* 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 */
@@ -242,31 +282,31 @@ static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge,
static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *params,
BMVert *vsta, BMVert *vend)
{
- BMEdge *eed = edge, *newe, temp = *edge;
- BMVert *v, ov1 = *edge->v1, ov2 = *edge->v2, *v1 = edge->v1, *v2 = edge->v2;
+ BMEdge *eed = edge, *e_new, e_tmp = *edge;
+ BMVert *v, v1_tmp = *edge->v1, v2_tmp = *edge->v2, *v1 = edge->v1, *v2 = edge->v2;
int i, numcuts = params->numcuts;
- temp.v1 = &ov1;
- temp.v2 = &ov2;
+ e_tmp.v1 = &v1_tmp;
+ e_tmp.v2 = &v2_tmp;
for (i = 0; i < numcuts; i++) {
- v = subdivideedgenum(bm, eed, &temp, i, params->numcuts, params, &newe, vsta, vend);
+ 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, newe, SUBD_SPLIT);
+ BMO_elem_flag_enable(bm, e_new, SUBD_SPLIT);
BMO_elem_flag_enable(bm, v, ELE_SPLIT);
BMO_elem_flag_enable(bm, eed, ELE_SPLIT);
- BMO_elem_flag_enable(bm, newe, SUBD_SPLIT);
+ BMO_elem_flag_enable(bm, e_new, SUBD_SPLIT);
BM_CHECK_ELEMENT(v);
if (v->e) BM_CHECK_ELEMENT(v->e);
if (v->e && v->e->l) BM_CHECK_ELEMENT(v->e->l->f);
}
- alter_co(bm, v1, &temp, params, 0, &ov1, &ov2);
- alter_co(bm, v2, &temp, params, 1.0, &ov1, &ov2);
+ alter_co(bm, v1, &e_tmp, params, 0, &v1_tmp, &v2_tmp);
+ alter_co(bm, v2, &e_tmp, params, 1.0, &v1_tmp, &v2_tmp);
}
/* note: the patterns are rotated as necessary to
@@ -286,7 +326,7 @@ static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *par
static void quad_1edge_split(BMesh *bm, BMFace *UNUSED(face),
BMVert **verts, const SubDParams *params)
{
- BMFace *nf;
+ BMFace *f_new;
int i, add, numcuts = params->numcuts;
/* if it's odd, the middle face is a quad, otherwise it's a triangle */
@@ -296,16 +336,16 @@ static void quad_1edge_split(BMesh *bm, BMFace *UNUSED(face),
if (i == numcuts / 2) {
add -= 1;
}
- connect_smallest_face(bm, verts[i], verts[numcuts + add], &nf);
+ connect_smallest_face(bm, verts[i], verts[numcuts + add], &f_new);
}
}
else {
add = 2;
for (i = 0; i < numcuts; i++) {
- connect_smallest_face(bm, verts[i], verts[numcuts + add], &nf);
+ connect_smallest_face(bm, verts[i], verts[numcuts + add], &f_new);
if (i == numcuts / 2) {
add -= 1;
- connect_smallest_face(bm, verts[i], verts[numcuts + add], &nf);
+ connect_smallest_face(bm, verts[i], verts[numcuts + add], &f_new);
}
}
@@ -332,13 +372,13 @@ static const SubDPattern quad_1edge = {
static void quad_2edge_split_path(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
const SubDParams *params)
{
- BMFace *nf;
+ BMFace *f_new;
int i, numcuts = params->numcuts;
for (i = 0; i < numcuts; i++) {
- connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &nf);
+ connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &f_new);
}
- connect_smallest_face(bm, verts[numcuts * 2 + 3], verts[numcuts * 2 + 1], &nf);
+ connect_smallest_face(bm, verts[numcuts * 2 + 3], verts[numcuts * 2 + 1], &f_new);
}
static const SubDPattern quad_2edge_path = {
@@ -360,27 +400,27 @@ static const SubDPattern quad_2edge_path = {
static void quad_2edge_split_innervert(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
const SubDParams *params)
{
- BMFace *nf;
- BMVert *v, *lastv;
- BMEdge *e, *ne, olde;
+ BMFace *f_new;
+ BMVert *v, *v_last;
+ BMEdge *e, *e_new, e_tmp;
int i, numcuts = params->numcuts;
- lastv = verts[numcuts];
+ v_last = verts[numcuts];
for (i = numcuts - 1; i >= 0; i--) {
- e = connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &nf);
+ e = connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &f_new);
- olde = *e;
- v = bm_subdivide_edge_addvert(bm, e, &olde, params, 0.5f, 0.5f, &ne, e->v1, e->v2);
+ e_tmp = *e;
+ v = bm_subdivide_edge_addvert(bm, e, &e_tmp, params, 0.5f, 0.5f, &e_new, e->v1, e->v2);
if (i != numcuts - 1) {
- connect_smallest_face(bm, lastv, v, &nf);
+ connect_smallest_face(bm, v_last, v, &f_new);
}
- lastv = v;
+ v_last = v;
}
- connect_smallest_face(bm, lastv, verts[numcuts * 2 + 2], &nf);
+ connect_smallest_face(bm, v_last, verts[numcuts * 2 + 2], &f_new);
}
static const SubDPattern quad_2edge_innervert = {
@@ -402,15 +442,15 @@ static const SubDPattern quad_2edge_innervert = {
static void quad_2edge_split_fan(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
const SubDParams *params)
{
- BMFace *nf;
+ BMFace *f_new;
/* BMVert *v; */ /* UNUSED */
- /* BMVert *lastv = verts[2]; */ /* UNUSED */
- /* BMEdge *e, *ne; */ /* UNUSED */
+ /* BMVert *v_last = verts[2]; */ /* UNUSED */
+ /* BMEdge *e, *e_new; */ /* UNUSED */
int i, numcuts = params->numcuts;
for (i = 0; i < numcuts; i++) {
- connect_smallest_face(bm, verts[i], verts[numcuts * 2 + 2], &nf);
- connect_smallest_face(bm, verts[numcuts + (numcuts - i)], verts[numcuts * 2 + 2], &nf);
+ connect_smallest_face(bm, verts[i], verts[numcuts * 2 + 2], &f_new);
+ connect_smallest_face(bm, verts[numcuts + (numcuts - i)], verts[numcuts * 2 + 2], &f_new);
}
}
@@ -435,21 +475,21 @@ static const SubDPattern quad_2edge_fan = {
static void quad_3edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
const SubDParams *params)
{
- BMFace *nf;
+ BMFace *f_new;
int i, add = 0, numcuts = params->numcuts;
for (i = 0; i < numcuts; i++) {
if (i == numcuts / 2) {
if (numcuts % 2 != 0) {
- connect_smallest_face(bm, verts[numcuts - i - 1 + add], verts[i + numcuts + 1], &nf);
+ connect_smallest_face(bm, verts[numcuts - i - 1 + add], verts[i + numcuts + 1], &f_new);
}
add = numcuts * 2 + 2;
}
- connect_smallest_face(bm, verts[numcuts - i - 1 + add], verts[i + numcuts + 1], &nf);
+ connect_smallest_face(bm, verts[numcuts - i - 1 + add], verts[i + numcuts + 1], &f_new);
}
for (i = 0; i < numcuts / 2 + 1; i++) {
- connect_smallest_face(bm, verts[i], verts[(numcuts - i) + numcuts * 2 + 1], &nf);
+ connect_smallest_face(bm, verts[i], verts[(numcuts - i) + numcuts * 2 + 1], &f_new);
}
}
@@ -474,9 +514,9 @@ static const SubDPattern quad_3edge = {
static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
const SubDParams *params)
{
- BMFace *nf;
+ BMFace *f_new;
BMVert *v, *v1, *v2;
- BMEdge *e, *ne, temp;
+ BMEdge *e, *e_new, e_tmp;
BMVert **lines;
int numcuts = params->numcuts;
int i, j, a, b, s = numcuts + 2 /* , totv = numcuts * 4 + 4 */;
@@ -501,25 +541,25 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts
a = i;
b = numcuts + 1 + numcuts + 1 + (numcuts - i - 1);
- e = connect_smallest_face(bm, verts[a], verts[b], &nf);
+ e = connect_smallest_face(bm, verts[a], verts[b], &f_new);
if (!e)
continue;
BMO_elem_flag_enable(bm, e, ELE_INNER);
- BMO_elem_flag_enable(bm, nf, ELE_INNER);
+ BMO_elem_flag_enable(bm, f_new, ELE_INNER);
v1 = lines[(i + 1) * s] = verts[a];
v2 = lines[(i + 1) * s + s - 1] = verts[b];
- temp = *e;
+ e_tmp = *e;
for (a = 0; a < numcuts; a++) {
- v = subdivideedgenum(bm, e, &temp, a, numcuts, params, &ne,
+ v = subdivideedgenum(bm, e, &e_tmp, a, numcuts, params, &e_new,
v1, v2);
BMESH_ASSERT(v != NULL);
- BMO_elem_flag_enable(bm, ne, ELE_INNER);
+ BMO_elem_flag_enable(bm, e_new, ELE_INNER);
lines[(i + 1) * s + a + 1] = v;
}
}
@@ -528,12 +568,12 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts
for (j = 1; j < numcuts + 1; j++) {
a = i * s + j;
b = (i - 1) * s + j;
- e = connect_smallest_face(bm, lines[a], lines[b], &nf);
+ e = connect_smallest_face(bm, lines[a], lines[b], &f_new);
if (!e)
continue;
BMO_elem_flag_enable(bm, e, ELE_INNER);
- BMO_elem_flag_enable(bm, nf, ELE_INNER);
+ BMO_elem_flag_enable(bm, f_new, ELE_INNER);
}
}
@@ -555,11 +595,11 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts
static void tri_1edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
const SubDParams *params)
{
- BMFace *nf;
+ BMFace *f_new;
int i, numcuts = params->numcuts;
for (i = 0; i < numcuts; i++) {
- connect_smallest_face(bm, verts[i], verts[numcuts + 1], &nf);
+ connect_smallest_face(bm, verts[i], verts[numcuts + 1], &f_new);
}
}
@@ -584,9 +624,9 @@ static const SubDPattern tri_1edge = {
static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
const SubDParams *params)
{
- BMFace *nf;
- BMEdge *e, *ne, temp;
- BMVert ***lines, *v, ov1, ov2;
+ BMFace *f_new;
+ BMEdge *e, *e_new, e_tmp;
+ BMVert ***lines, *v, v1_tmp, v2_tmp;
void *stackarr[1];
int i, j, a, b, numcuts = params->numcuts;
@@ -607,26 +647,26 @@ static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
lines[i + 1] = MEM_callocN(sizeof(void *) * (2 + i), "triangle vert table row");
a = numcuts * 2 + 2 + i;
b = numcuts + numcuts - i;
- e = connect_smallest_face(bm, verts[a], verts[b], &nf);
+ e = connect_smallest_face(bm, verts[a], verts[b], &f_new);
if (!e) goto cleanup;
BMO_elem_flag_enable(bm, e, ELE_INNER);
- BMO_elem_flag_enable(bm, nf, ELE_INNER);
+ BMO_elem_flag_enable(bm, f_new, ELE_INNER);
lines[i + 1][0] = verts[a];
lines[i + 1][i + 1] = verts[b];
- temp = *e;
- ov1 = *verts[a];
- ov2 = *verts[b];
- temp.v1 = &ov1;
- temp.v2 = &ov2;
+ e_tmp = *e;
+ v1_tmp = *verts[a];
+ v2_tmp = *verts[b];
+ e_tmp.v1 = &v1_tmp;
+ e_tmp.v2 = &v2_tmp;
for (j = 0; j < i; j++) {
- v = subdivideedgenum(bm, e, &temp, j, i, params, &ne,
+ v = subdivideedgenum(bm, e, &e_tmp, j, i, params, &e_new,
verts[a], verts[b]);
lines[i + 1][j + 1] = v;
- BMO_elem_flag_enable(bm, ne, ELE_INNER);
+ BMO_elem_flag_enable(bm, e_new, ELE_INNER);
}
}
@@ -644,15 +684,15 @@ static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
*/
for (i = 1; i < numcuts + 1; i++) {
for (j = 0; j < i; j++) {
- e = connect_smallest_face(bm, lines[i][j], lines[i + 1][j + 1], &nf);
+ e = connect_smallest_face(bm, lines[i][j], lines[i + 1][j + 1], &f_new);
BMO_elem_flag_enable(bm, e, ELE_INNER);
- BMO_elem_flag_enable(bm, nf, ELE_INNER);
+ BMO_elem_flag_enable(bm, f_new, ELE_INNER);
- e = connect_smallest_face(bm, lines[i][j + 1], lines[i + 1][j + 1], &nf);
+ e = connect_smallest_face(bm, lines[i][j + 1], lines[i + 1][j + 1], &f_new);
BMO_elem_flag_enable(bm, e, ELE_INNER);
- BMO_elem_flag_enable(bm, nf, ELE_INNER);
+ BMO_elem_flag_enable(bm, f_new, ELE_INNER);
}
}
@@ -711,12 +751,12 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
BLI_array_declare(loops_split);
BMLoop **loops = NULL;
BLI_array_declare(loops);
- BMLoop *nl, *l;
+ BMLoop *l_new, *l;
BMFace *face;
BLI_array_declare(verts);
float smooth, fractal, along_normal;
- int use_sphere, cornertype, use_single_edge, use_grid_fill, use_only_quads;
- int skey, seed, i, j, matched, a, b, numcuts, totesel;
+ bool use_sphere, use_single_edge, use_grid_fill, use_only_quads;
+ int cornertype, skey, seed, i, j, matched, a, b, numcuts, totesel;
BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT);
@@ -731,9 +771,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
use_grid_fill = BMO_slot_bool_get(op->slots_in, "use_grid_fill");
use_only_quads = BMO_slot_bool_get(op->slots_in, "use_only_quads");
use_sphere = BMO_slot_bool_get(op->slots_in, "use_sphere");
-
- BLI_srandom(seed);
-
+
patterns[1] = NULL;
/* straight cut is patterns[1] == NULL */
switch (cornertype) {
@@ -790,9 +828,14 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
params.use_fractal = (fractal != 0.0f);
params.use_sphere = use_sphere;
params.origkey = skey;
- params.off[0] = (float)BLI_drand() * 200.0f;
- params.off[1] = (float)BLI_drand() * 200.0f;
- params.off[2] = (float)BLI_drand() * 200.0f;
+
+ if (params.use_fractal) {
+ BLI_srandom(seed);
+
+ params.fractal_ofs[0] = (float)BLI_drand() * 200.0f;
+ params.fractal_ofs[1] = (float)BLI_drand() * 200.0f;
+ params.fractal_ofs[2] = (float)BLI_drand() * 200.0f;
+ }
BMO_slot_map_to_flag(bm, op->slots_in, "custom_patterns",
BM_FACE, FACE_CUSTOMFILL);
@@ -820,9 +863,9 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
matched = 0;
totesel = 0;
- BM_ITER_ELEM_INDEX (nl, &liter, face, BM_LOOPS_OF_FACE, i) {
- edges[i] = nl->e;
- verts[i] = nl->v;
+ BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, i) {
+ edges[i] = l_new->e;
+ verts[i] = l_new->v;
if (BMO_elem_flag_test(bm, edges[i], SUBD_SPLIT)) {
if (!e1) e1 = edges[i];
@@ -912,6 +955,10 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
j = BLI_array_count(facedata) - 1;
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;
}
@@ -983,7 +1030,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
BLI_array_grow_items(loops_split, numcuts);
for (j = 0; j < numcuts; j++) {
- int ok = TRUE;
+ bool ok = true;
/* Check for special case: [#32500]
* This edge pair could be used by more then one face,
@@ -1006,7 +1053,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
BLI_assert(other_loop->prev->v != loops[a]->v);
BLI_assert(other_loop->next->v != loops[a]->v);
- ok = FALSE;
+ ok = false;
break;
}
}
@@ -1014,7 +1061,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
}
- if (ok == TRUE) {
+ if (ok == true) {
loops_split[j][0] = loops[a];
loops_split[j][1] = loops[b];
}
@@ -1036,10 +1083,10 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
for (j = 0; j < BLI_array_count(loops_split); j++) {
if (loops_split[j][0]) {
- BLI_assert(BM_edge_exists(loops_split[j][0]->v, loops_split[j][1]->v) == FALSE);
+ BLI_assert(BM_edge_exists(loops_split[j][0]->v, loops_split[j][1]->v) == NULL);
- /* BMFace *nf = */ /* UNUSED */
- BM_face_split(bm, face, loops_split[j][0]->v, loops_split[j][1]->v, &nl, NULL, FALSE);
+ /* BMFace *f_new = */ /* UNUSED */
+ BM_face_split(bm, face, loops_split[j][0]->v, loops_split[j][1]->v, &l_new, NULL, false);
}
}
@@ -1050,8 +1097,8 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
}
a = 0;
- BM_ITER_ELEM_INDEX (nl, &liter, face, BM_LOOPS_OF_FACE, j) {
- if (nl->v == facedata[i].start) {
+ BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, j) {
+ if (l_new->v == facedata[i].start) {
a = j + 1;
break;
}
@@ -1059,9 +1106,9 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
BLI_array_grow_items(verts, face->len);
- BM_ITER_ELEM_INDEX (nl, &liter, face, BM_LOOPS_OF_FACE, j) {
+ BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, j) {
b = (j - a + face->len) % face->len;
- verts[b] = nl->v;
+ verts[b] = l_new->v;
}
BM_CHECK_ELEMENT(face);
@@ -1123,7 +1170,7 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag,
BMElem *ele;
for (ele = BMO_iter_new(&iter, op.slots_out, "geom_inner.out", BM_EDGE | BM_VERT); ele; ele = BMO_iter_step(&iter)) {
- BM_elem_select_set(bm, ele, TRUE);
+ BM_elem_select_set(bm, ele, true);
}
}
else if (seltype == SUBDIV_SELECT_LOOPCUT) {
@@ -1131,10 +1178,10 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag,
BMElem *ele;
/* deselect input */
- BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE);
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
for (ele = BMO_iter_new(&iter, op.slots_out, "geom_inner.out", BM_EDGE | BM_VERT); ele; ele = BMO_iter_step(&iter)) {
- BM_elem_select_set(bm, ele, TRUE);
+ BM_elem_select_set(bm, ele, true);
if (ele->head.htype == BM_VERT) {
BMEdge *e;
@@ -1145,13 +1192,13 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag,
BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
BM_elem_flag_test(e->v2, BM_ELEM_SELECT))
{
- BM_edge_select_set(bm, e, TRUE);
+ BM_edge_select_set(bm, e, true);
}
else if (BM_elem_flag_test(e, BM_ELEM_SELECT) &&
(!BM_elem_flag_test(e->v1, BM_ELEM_SELECT) ||
!BM_elem_flag_test(e->v2, BM_ELEM_SELECT)))
{
- BM_edge_select_set(bm, e, FALSE);
+ BM_edge_select_set(bm, e, false);
}
}
}
diff --git a/source/blender/bmesh/operators/bmo_subdivide.h b/source/blender/bmesh/operators/bmo_subdivide.h
deleted file mode 100644
index 529075aab02..00000000000
--- a/source/blender/bmesh/operators/bmo_subdivide.h
+++ /dev/null
@@ -1,72 +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.
- *
- * Contributor(s): Joseph Eagar.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/bmesh/operators/bmo_subdivide.h
- * \ingroup bmesh
- */
-
-#ifndef __BMO_SUBDIVIDE_H__
-#define __BMO_SUBDIVIDE_H__
-
-typedef struct SubDParams {
- int numcuts;
- float smooth;
- float fractal;
- float along_normal;
- //int beauty;
- short use_smooth;
- short use_sphere;
- short use_fractal;
- int seed;
- int origkey; /* shapekey holding displaced vertex coordinates for current geometry */
- BMOperator *op;
- BMOpSlot *slot_edge_percents; /* BMO_slot_get(params->op->slots_in, "edge_percents"); */
- BMOpSlot *slot_custom_patterns; /* BMO_slot_get(params->op->slots_in, "custom_patterns"); */
- float off[3];
-} SubDParams;
-
-typedef void (*subd_pattern_fill_fp)(BMesh *bm, BMFace *face, BMVert **verts,
- const SubDParams *params);
-
-/*
- * note: this is a pattern-based edge subdivider.
- * it tries to match a pattern to edge selections on faces,
- * then executes functions to cut them.
- */
-typedef struct SubDPattern {
- int seledges[20]; /* selected edges mask, for splitting */
-
- /* verts starts at the first new vert cut, not the first vert in the face */
- subd_pattern_fill_fp connectexec;
- int len; /* total number of verts, before any subdivision */
-} SubDPattern;
-
-/* generic subdivision rules:
- *
- * - two selected edges in a face should make a link
- * between them.
- *
- * - one edge should do, what? make pretty topology, or just
- * split the edge only?
- */
-
-#endif /* __BMO_SUBDIVIDE_H__ */
diff --git a/source/blender/bmesh/operators/bmo_symmetrize.c b/source/blender/bmesh/operators/bmo_symmetrize.c
index 248c7268ac6..0bfc81f83cf 100644
--- a/source/blender/bmesh/operators/bmo_symmetrize.c
+++ b/source/blender/bmesh/operators/bmo_symmetrize.c
@@ -176,7 +176,7 @@ static void symm_split_asymmetric_edges(Symm *symm)
plane_co[symm->axis][0],
plane_co[symm->axis][1],
plane_co[symm->axis][2],
- &lambda, TRUE);
+ &lambda, true);
BLI_assert(r);
madd_v3_v3v3fl(co, e->v1->co, edge_dir, lambda);
@@ -244,7 +244,7 @@ typedef struct {
int len;
/* True only if none of the polygon's edges were split */
- int already_symmetric;
+ bool already_symmetric;
BMFace *src_face;
} SymmPoly;
@@ -261,11 +261,11 @@ static void symm_poly_with_splits(const Symm *symm,
/* Count vertices and check for edge splits */
out->len = f->len;
- out->already_symmetric = TRUE;
+ out->already_symmetric = true;
BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
if (BLI_ghash_haskey(symm->edge_split_map, l->e)) {
out->len++;
- out->already_symmetric = FALSE;
+ out->already_symmetric = false;
}
}
@@ -332,11 +332,11 @@ static BMVert *symm_poly_mirror_dst(const Symm *symm,
return NULL;
}
-static int symm_poly_next_crossing(const Symm *symm,
- const SymmPoly *sp,
- int start,
- int *l1,
- int *l2)
+static bool symm_poly_next_crossing(const Symm *symm,
+ const SymmPoly *sp,
+ int start,
+ int *l1,
+ int *l2)
{
int i;
@@ -347,12 +347,12 @@ static int symm_poly_next_crossing(const Symm *symm,
if ((symm_poly_co_side(symm, sp, *l1) == SYMM_SIDE_KILL) ^
(symm_poly_co_side(symm, sp, *l2) == SYMM_SIDE_KILL))
{
- return TRUE;
+ return true;
}
}
BLI_assert(!"symm_poly_next_crossing failed");
- return FALSE;
+ return false;
}
static BMFace *symm_face_create_v(BMesh *bm, BMFace *example,
@@ -361,6 +361,12 @@ static BMFace *symm_face_create_v(BMesh *bm, BMFace *example,
BMFace *f_new;
int i;
+ /* TODO: calling symmetrize in dynamic-topology sculpt mode
+ * frequently tries to create faces of length less than two,
+ * should investigate further */
+ if (len < 3)
+ return NULL;
+
for (i = 0; i < len; i++) {
int j = (i + 1) % len;
fe[i] = BM_edge_exists(fv[i], fv[j]);
@@ -372,8 +378,9 @@ static BMFace *symm_face_create_v(BMesh *bm, BMFace *example,
f_new = BM_face_create(bm, fv, fe, len, BM_CREATE_NO_DOUBLE);
if (example)
BM_elem_attrs_copy(bm, bm, example, f_new);
- BM_face_select_set(bm, f_new, TRUE);
+ BM_face_select_set(bm, f_new, true);
BMO_elem_flag_enable(bm, f_new, SYMM_OUTPUT_GEOM);
+
return f_new;
}
@@ -458,15 +465,15 @@ static void symm_mirror_polygons(Symm *symm)
BMO_ITER (f, &oiter, symm->op->slots_in, "input", BM_FACE) {
BMIter iter;
BMLoop *l;
- int mirror_all = TRUE, ignore_all = TRUE;
+ bool mirror_all = true, ignore_all = true;
/* Check if entire polygon can be mirrored or ignored */
BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
const SymmSide side = symm_co_side(symm, l->v->co);
if (side == SYMM_SIDE_KILL)
- mirror_all = FALSE;
+ mirror_all = false;
else if (side == SYMM_SIDE_KEEP)
- ignore_all = FALSE;
+ ignore_all = false;
}
if (mirror_all) {
diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c
index d20d01af114..1f04c7ce845 100644
--- a/source/blender/bmesh/operators/bmo_triangulate.c
+++ b/source/blender/bmesh/operators/bmo_triangulate.c
@@ -37,45 +37,22 @@
#include "intern/bmesh_operators_private.h" /* own include */
-#define EDGE_NEW 1
-#define FACE_NEW 1
-
#define ELE_NEW 1
#define FACE_MARK 2
#define EDGE_MARK 4
void bmo_triangulate_exec(BMesh *bm, BMOperator *op)
{
- BMOIter siter;
- BMFace *face, **newfaces = NULL;
- BLI_array_declare(newfaces);
- float (*projectverts)[3] = NULL;
- BLI_array_declare(projectverts);
- int i;
- const int use_beauty = BMO_slot_bool_get(op->slots_in, "use_beauty");
+ const bool use_beauty = BMO_slot_bool_get(op->slots_in, "use_beauty");
BMOpSlot *slot_facemap_out = BMO_slot_get(op->slots_out, "face_map.out");
- for (face = BMO_iter_new(&siter, op->slots_in, "faces", BM_FACE); face; face = BMO_iter_step(&siter)) {
-
- BLI_array_empty(projectverts);
- BLI_array_empty(newfaces);
-
- BLI_array_grow_items(projectverts, face->len * 3);
- BLI_array_grow_items(newfaces, face->len);
+ BM_mesh_elem_hflag_disable_all(bm, BM_FACE | BM_EDGE, BM_ELEM_TAG, false);
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false);
- BM_face_triangulate(bm, face, projectverts, EDGE_NEW, FACE_NEW, newfaces, use_beauty);
+ BM_mesh_triangulate(bm, use_beauty, true, op, slot_facemap_out);
- BMO_slot_map_elem_insert(op, slot_facemap_out, face, face);
- for (i = 0; newfaces[i]; i++) {
- BMO_slot_map_elem_insert(op, slot_facemap_out, newfaces[i], face);
- }
- }
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_NEW);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_NEW);
-
- BLI_array_free(projectverts);
- BLI_array_free(newfaces);
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_TAG);
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
}
void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op)
@@ -86,7 +63,7 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op)
BMEdge *e;
int stop = 0;
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "constrain_edges", BM_EDGE, EDGE_MARK);
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
if (f->len == 3) {
@@ -100,7 +77,7 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op)
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
BMVert *v1, *v2, *v3, *v4;
- if (!BM_edge_is_manifold(e) || BMO_elem_flag_test(bm, e, EDGE_MARK)) {
+ if (!BM_edge_is_manifold(e) || !BMO_elem_flag_test(bm, e, EDGE_MARK)) {
continue;
}
@@ -109,12 +86,12 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op)
{
continue;
}
-
+
v1 = e->l->prev->v;
v2 = e->l->v;
v3 = e->l->radial_next->prev->v;
v4 = e->l->next->v;
-
+
if (is_quad_convex_v3(v1->co, v2->co, v3->co, v4->co)) {
float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2;
/* testing rule:
@@ -138,9 +115,9 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op)
fac2 = opp1 / (len2 + len3 + len6) + opp2 / (len4 + len1 + len6);
if (fac1 > fac2) {
- e = BM_edge_rotate(bm, e, FALSE, BM_EDGEROT_CHECK_EXISTS);
+ e = BM_edge_rotate(bm, e, false, BM_EDGEROT_CHECK_EXISTS);
if (e) {
- BMO_elem_flag_enable(bm, e, ELE_NEW);
+ BMO_elem_flag_enable(bm, e, ELE_NEW | EDGE_MARK);
BMO_elem_flag_enable(bm, e->l->f, FACE_MARK | ELE_NEW);
BMO_elem_flag_enable(bm, e->l->radial_next->f, FACE_MARK | ELE_NEW);
@@ -156,9 +133,9 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op)
void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
{
+ const bool use_beauty = BMO_slot_bool_get(op->slots_in, "use_beauty");
BMOIter siter;
BMEdge *e;
- BMOperator bmop;
ScanFillContext sf_ctx;
/* ScanFillEdge *sf_edge; */ /* UNUSED */
ScanFillVert *sf_vert, *sf_vert_1, *sf_vert_2;
@@ -190,12 +167,12 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
/* sf_edge->tmp.p = e; */ /* UNUSED */
}
- BLI_scanfill_calc(&sf_ctx, 0);
+ BLI_scanfill_calc(&sf_ctx, BLI_SCANFILL_CALC_HOLES);
for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
BMFace *f = BM_face_create_quad_tri(bm,
sf_tri->v1->tmp.p, sf_tri->v2->tmp.p, sf_tri->v3->tmp.p, NULL,
- NULL, TRUE);
+ NULL, true);
BMLoop *l;
BMIter liter;
@@ -210,11 +187,14 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
BLI_scanfill_end(&sf_ctx);
BLI_smallhash_release(&hash);
- /* clean up fill */
- BMO_op_initf(bm, &bmop, op->flag, "beautify_fill faces=%ff constrain_edges=%fe", ELE_NEW, EDGE_MARK);
- BMO_op_exec(bm, &bmop);
- BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_FACE | BM_EDGE, ELE_NEW);
- BMO_op_finish(bm, &bmop);
+ if (use_beauty) {
+ BMOperator bmop;
+
+ BMO_op_initf(bm, &bmop, op->flag, "beautify_fill faces=%ff edges=%Fe", ELE_NEW, EDGE_MARK);
+ BMO_op_exec(bm, &bmop);
+ BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_FACE | BM_EDGE, ELE_NEW);
+ BMO_op_finish(bm, &bmop);
+ }
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_EDGE | BM_FACE, ELE_NEW);
}
diff --git a/source/blender/bmesh/operators/bmo_unsubdivide.c b/source/blender/bmesh/operators/bmo_unsubdivide.c
index fae7db3d175..784e695efb0 100644
--- a/source/blender/bmesh/operators/bmo_unsubdivide.c
+++ b/source/blender/bmesh/operators/bmo_unsubdivide.c
@@ -55,5 +55,5 @@ void bmo_unsubdivide_exec(BMesh *bm, BMOperator *op)
}
/* do all the real work here */
- BM_mesh_decimate_unsubdivide_ex(bm, iterations, TRUE);
+ BM_mesh_decimate_unsubdivide_ex(bm, iterations, true);
}
diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c
index 64dbf0cc0e7..76962807cd5 100644
--- a/source/blender/bmesh/operators/bmo_utils.c
+++ b/source/blender/bmesh/operators/bmo_utils.c
@@ -122,8 +122,8 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op)
{
BMOIter siter;
BMEdge *e, *e2;
- const int use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw");
- const int is_single = BMO_slot_buffer_count(op->slots_in, "edges") == 1;
+ const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw");
+ const bool is_single = BMO_slot_buffer_count(op->slots_in, "edges") == 1;
short check_flag = is_single ?
BM_EDGEROT_CHECK_EXISTS :
BM_EDGEROT_CHECK_EXISTS | BM_EDGEROT_CHECK_DEGENERATE;
@@ -140,8 +140,8 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op)
if (BM_edge_face_pair(e, &fa, &fb)) {
/* check we're untouched */
- if (BMO_elem_flag_test(bm, fa, FACE_TAINT) == FALSE &&
- BMO_elem_flag_test(bm, fb, FACE_TAINT) == FALSE)
+ if (BMO_elem_flag_test(bm, fa, FACE_TAINT) == false &&
+ BMO_elem_flag_test(bm, fb, FACE_TAINT) == false)
{
if (!(e2 = BM_edge_rotate(bm, e, use_ccw, check_flag))) {
@@ -172,14 +172,14 @@ 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, int usefaces)
+static void bmo_region_extend_extend(BMesh *bm, BMOperator *op, const bool use_faces)
{
BMVert *v;
BMEdge *e;
BMIter eiter;
BMOIter siter;
- if (!usefaces) {
+ if (!use_faces) {
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))
@@ -216,14 +216,14 @@ static void bmo_region_extend_extend(BMesh *bm, BMOperator *op, int usefaces)
}
}
-static void bmo_region_extend_constrict(BMesh *bm, BMOperator *op, int usefaces)
+static void bmo_region_extend_constrict(BMesh *bm, BMOperator *op, const bool use_faces)
{
BMVert *v;
BMEdge *e;
BMIter eiter;
BMOIter siter;
- if (!usefaces) {
+ if (!use_faces) {
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))
@@ -265,8 +265,8 @@ static void bmo_region_extend_constrict(BMesh *bm, BMOperator *op, int usefaces)
void bmo_region_extend_exec(BMesh *bm, BMOperator *op)
{
- int use_faces = BMO_slot_bool_get(op->slots_in, "use_faces");
- int constrict = BMO_slot_bool_get(op->slots_in, "use_constrict");
+ 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");
BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_ALL_NOLOOP, SEL_ORIG);
@@ -314,7 +314,8 @@ void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op)
BLI_array_declare(fstack);
BMLoop *l, *l2;
float maxx, maxx_test, cent[3];
- int i, i_max, flagflip = BMO_slot_bool_get(op->slots_in, "use_flip");
+ int i, i_max;
+ const bool use_flip = BMO_slot_bool_get(op->slots_in, "use_flip");
startf = NULL;
maxx = -1.0e10;
@@ -349,7 +350,7 @@ void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op)
BM_face_normal_flip(bm, startf);
BMO_elem_flag_toggle(bm, startf, FACE_FLIP);
- if (flagflip)
+ if (use_flip)
BM_elem_flag_toggle(startf, BM_ELEM_TAG);
}
@@ -381,11 +382,11 @@ void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op)
BM_face_normal_flip(bm, l2->f);
BMO_elem_flag_toggle(bm, l2->f, FACE_FLIP);
- if (flagflip)
+ if (use_flip)
BM_elem_flag_toggle(l2->f, BM_ELEM_TAG);
}
else if (BM_elem_flag_test(l2->f, BM_ELEM_TAG) || BM_elem_flag_test(l->f, BM_ELEM_TAG)) {
- if (flagflip) {
+ if (use_flip) {
BM_elem_flag_disable(l->f, BM_ELEM_TAG);
BM_elem_flag_disable(l2->f, BM_ELEM_TAG);
}
@@ -436,9 +437,11 @@ void bmo_smooth_vert_exec(BMesh *UNUSED(bm), BMOperator *op)
i = 0;
BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
BLI_array_grow_one(cos);
+
co = cos[i];
-
- j = 0;
+ zero_v3(co);
+
+ j = 0;
BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
co2 = BM_edge_other_vert(e, v)->co;
add_v3_v3v3(co, co, co2);
@@ -489,11 +492,11 @@ void bmo_rotate_uvs_exec(BMesh *bm, BMOperator *op)
BMFace *fs; /* current face */
BMIter l_iter; /* iteration loop */
- const int use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw");
+ const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw");
BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) {
if (CustomData_has_layer(&(bm->ldata), CD_MLOOPUV)) {
- if (use_ccw == FALSE) { /* same loops direction */
+ if (use_ccw == false) { /* same loops direction */
BMLoop *lf; /* current face loops */
MLoopUV *f_luv; /* first face loop uv */
float p_uv[2]; /* previous uvs */
@@ -572,7 +575,6 @@ void bmo_reverse_uvs_exec(BMesh *bm, BMOperator *op)
}
/* now that we have the uvs in the array, reverse! */
- i = 0;
BM_ITER_ELEM_INDEX (lf, &l_iter, fs, BM_LOOPS_OF_FACE, i) {
/* current loop uv is the previous loop uv */
MLoopUV *luv = CustomData_bmesh_get(&bm->ldata, lf->head.data, CD_MLOOPUV);
@@ -594,11 +596,11 @@ void bmo_rotate_colors_exec(BMesh *bm, BMOperator *op)
BMFace *fs; /* current face */
BMIter l_iter; /* iteration loop */
- const int use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw");
+ const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw");
BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) {
if (CustomData_has_layer(&(bm->ldata), CD_MLOOPCOL)) {
- if (use_ccw == FALSE) { /* same loops direction */
+ if (use_ccw == false) { /* same loops direction */
BMLoop *lf; /* current face loops */
MLoopCol *f_lcol; /* first face loop color */
MLoopCol p_col; /* previous color */
diff --git a/source/blender/bmesh/operators/bmo_wireframe.c b/source/blender/bmesh/operators/bmo_wireframe.c
index 7401704310f..00838533104 100644
--- a/source/blender/bmesh/operators/bmo_wireframe.c
+++ b/source/blender/bmesh/operators/bmo_wireframe.c
@@ -134,34 +134,32 @@ static void bm_vert_boundary_tangent(BMVert *v, float r_no[3], float r_no_face[3
}
/* check if we are the only tagged loop-face around this edge */
-static int bm_loop_is_radial_boundary(BMLoop *l_first)
+static bool bm_loop_is_radial_boundary(BMLoop *l_first)
{
BMLoop *l = l_first->radial_next;
if (l == l_first) {
- return TRUE; /* a real boundary */
+ return true; /* a real boundary */
}
else {
do {
if (BM_elem_flag_test(l->f, BM_ELEM_TAG)) {
- return FALSE;
+ return false;
}
} while ((l = l->radial_next) != l_first);
}
- return TRUE;
+ return true;
}
-extern float BM_vert_calc_mean_tagged_edge_length(BMVert *v);
-
void bmo_wireframe_exec(BMesh *bm, BMOperator *op)
{
- const int use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary");
- const int use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
- const int use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
- const int use_crease = (BMO_slot_bool_get(op->slots_in, "use_crease") &&
- CustomData_has_layer(&bm->edata, CD_CREASE));
- const float depth = BMO_slot_float_get(op->slots_in, "thickness");
- const float inset = depth;
+ const bool use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary");
+ const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
+ const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
+ const bool use_crease = (BMO_slot_bool_get(op->slots_in, "use_crease") &&
+ CustomData_has_layer(&bm->edata, CD_CREASE));
+ const float depth = BMO_slot_float_get(op->slots_in, "thickness");
+ const float inset = depth;
const int totvert_orig = bm->totvert;
@@ -203,7 +201,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op)
}
/* setup tags, all faces and verts will be tagged which will be duplicated */
- BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, FALSE);
+ BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
BMO_ITER (f_src, &oiter, op->slots_in, "faces", BM_FACE) {
verts_loop_tot += f_src->len;
@@ -239,13 +237,13 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op)
}
/* conflicts with BM_vert_calc_mean_tagged_edge_length */
- if (use_relative_offset == FALSE) {
+ if (use_relative_offset == false) {
BM_elem_flag_disable(v_src, BM_ELEM_TAG);
}
}
if (use_relative_offset) {
- BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, FALSE);
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
}
verts_loop = MEM_mallocN(sizeof(BMVert **) * verts_loop_tot, __func__);
@@ -332,7 +330,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op)
BMVert *v_pos1 = verts_pos[i_1];
BMVert *v_pos2 = verts_pos[i_2];
- f_new = BM_face_create_quad_tri(bm, v_l1, v_l2, v_neg2, v_neg1, f_src, FALSE);
+ f_new = BM_face_create_quad_tri(bm, v_l1, v_l2, v_neg2, v_neg1, f_src, false);
BM_elem_flag_enable(f_new, BM_ELEM_TAG);
l_new = BM_FACE_FIRST_LOOP(f_new);
@@ -341,7 +339,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op)
BM_elem_attrs_copy(bm, bm, l_next, l_new->next);
BM_elem_attrs_copy(bm, bm, l_next, l_new->next->next);
- f_new = BM_face_create_quad_tri(bm, v_l2, v_l1, v_pos1, v_pos2, f_src, FALSE);
+ f_new = BM_face_create_quad_tri(bm, v_l2, v_l1, v_pos1, v_pos2, f_src, false);
BM_elem_flag_enable(f_new, BM_ELEM_TAG);
l_new = BM_FACE_FIRST_LOOP(f_new);
@@ -357,7 +355,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op)
BMVert *v_b1 = verts_boundary[i_1];
BMVert *v_b2 = verts_boundary[i_2];
- f_new = BM_face_create_quad_tri(bm, v_b2, v_b1, v_neg1, v_neg2, f_src, FALSE);
+ f_new = BM_face_create_quad_tri(bm, v_b2, v_b1, v_neg1, v_neg2, f_src, false);
BM_elem_flag_enable(f_new, BM_ELEM_TAG);
l_new = BM_FACE_FIRST_LOOP(f_new);
@@ -366,7 +364,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op)
BM_elem_attrs_copy(bm, bm, l, l_new->next);
BM_elem_attrs_copy(bm, bm, l, l_new->next->next);
- f_new = BM_face_create_quad_tri(bm, v_b1, v_b2, v_pos2, v_pos1, f_src, FALSE);
+ f_new = BM_face_create_quad_tri(bm, v_b1, v_b2, v_pos2, v_pos1, f_src, false);
BM_elem_flag_enable(f_new, BM_ELEM_TAG);
l_new = BM_FACE_FIRST_LOOP(f_new);
diff --git a/source/blender/bmesh/tools/BME_bevel.c b/source/blender/bmesh/tools/BME_bevel.c
index 5e1d58150fa..47b507603f4 100644
--- a/source/blender/bmesh/tools/BME_bevel.c
+++ b/source/blender/bmesh/tools/BME_bevel.c
@@ -90,7 +90,7 @@ static BME_TransData *BME_assign_transdata(BME_TransData_Head *td, BMesh *bm, BM
float factor, float weight, float maxfactor, float *max)
{
BME_TransData *vtd;
- int is_new = 0;
+ int is_new = false;
if (v == NULL) {
return NULL;
@@ -100,7 +100,7 @@ static BME_TransData *BME_assign_transdata(BME_TransData_Head *td, BMesh *bm, BM
vtd = BLI_memarena_alloc(td->ma, sizeof(*vtd));
BLI_ghash_insert(td->gh, v, vtd);
td->len++;
- is_new = 1;
+ is_new = true;
}
vtd->bm = bm;
@@ -151,12 +151,12 @@ static void BME_Bevel_Dissolve_Disk(BMesh *bm, BMVert *v)
{
BMFace *f;
BMEdge *e;
- int done;
+ bool done;
if (v->e) {
- done = FALSE;
+ done = false;
while (!done) {
- done = TRUE;
+ done = true;
e = v->e; /*loop the edge looking for a edge to dissolve*/
do {
f = NULL;
@@ -164,14 +164,14 @@ static void BME_Bevel_Dissolve_Disk(BMesh *bm, BMVert *v)
f = bmesh_jfke(bm, e->l->f, e->l->radial_next->f, e);
}
if (f) {
- done = FALSE;
+ done = false;
break;
}
e = bmesh_disk_edge_next(e, v);
} while (e != v->e);
}
- BM_vert_collapse_edge(bm, v->e, v, TRUE);
- // bmesh_jekv(bm, v->e, v, FALSE);
+ BM_vert_collapse_edge(bm, v->e, v, true);
+ // bmesh_jekv(bm, v->e, v, false);
}
}
@@ -539,18 +539,18 @@ static BMLoop *BME_bevel_edge(BMesh *bm, BMLoop *l, float value, int UNUSED(opti
se = l->next->e;
jf = NULL;
if (kl->v == kv) {
- BM_face_split(bm, kl->f, kl->prev->v, kl->next->v, &nl, kl->prev->e, TRUE);
+ BM_face_split(bm, kl->f, kl->prev->v, kl->next->v, &nl, kl->prev->e, true);
ke = kl->e;
/* BMESH-TODO: jfke doesn't handle customdata */
jf = bmesh_jfke(bm, kl->prev->radial_next->f, kl->f, kl->prev->e);
- BM_vert_collapse_edge(bm, ke, kv, FALSE);
+ BM_vert_collapse_edge(bm, ke, kv, false);
}
else {
- BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e, TRUE);
+ BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e, true);
ke = kl->e;
/* BMESH-TODO: jfke doesn't handle customdata */
jf = bmesh_jfke(bm, kl->next->radial_next->f, kl->f, kl->next->e);
- BM_vert_collapse_edge(bm, ke, kv, FALSE);
+ BM_vert_collapse_edge(bm, ke, kv, false);
}
/* find saved loop pointer */
l = se->l;
@@ -585,18 +585,18 @@ static BMLoop *BME_bevel_edge(BMesh *bm, BMLoop *l, float value, int UNUSED(opti
se = l->e;
jf = NULL;
if (kl->v == kv) {
- BM_face_split(bm, kl->f, kl->prev->v, kl->next->v, &nl, kl->prev->e, TRUE);
+ BM_face_split(bm, kl->f, kl->prev->v, kl->next->v, &nl, kl->prev->e, true);
ke = kl->e;
/* BMESH-TODO: jfke doesn't handle customdata */
jf = bmesh_jfke(bm, kl->prev->radial_next->f, kl->f, kl->prev->e);
- BM_vert_collapse_edge(bm, ke, kv, FALSE);
+ BM_vert_collapse_edge(bm, ke, kv, false);
}
else {
- BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e, TRUE);
+ BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e, true);
ke = kl->e;
/* BMESH-TODO: jfke doesn't handle customdata */
jf = bmesh_jfke(bm, kl->next->radial_next->f, kl->f, kl->next->e);
- BM_vert_collapse_edge(bm, ke, kv, FALSE);
+ BM_vert_collapse_edge(bm, ke, kv, false);
}
/* find saved loop pointer */
l = se->l;
@@ -607,7 +607,7 @@ static BMLoop *BME_bevel_edge(BMesh *bm, BMLoop *l, float value, int UNUSED(opti
}
if (!BMO_elem_flag_test(bm, v1, BME_BEVEL_NONMAN) || !BMO_elem_flag_test(bm, v2, BME_BEVEL_NONMAN)) {
- BM_face_split(bm, f, v2, v1, &l, e, TRUE);
+ BM_face_split(bm, f, v2, v1, &l, e, true);
BMO_elem_flag_enable(bm, l->e, BME_BEVEL_BEVEL);
l = l->radial_next;
}
@@ -636,7 +636,7 @@ static BMLoop *BME_bevel_vert(BMesh *bm, BMLoop *l, float value, int UNUSED(opti
l = l->next->next;
/* "cut off" this corner */
- /* f = */ BM_face_split(bm, l->f, v2, v1, NULL, l->e, TRUE);
+ /* f = */ BM_face_split(bm, l->f, v2, v1, NULL, l->e, true);
return l;
}
@@ -1069,7 +1069,7 @@ static BMesh *BME_bevel_mesh(BMesh *bm, float value, int UNUSED(res), int option
/* get rid of beveled edge */
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (BMO_elem_flag_test(bm, e, BME_BEVEL_BEVEL) && BMO_elem_flag_test(bm, e, BME_BEVEL_ORIG)) {
- BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, TRUE);
+ BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, true);
}
}
@@ -1083,9 +1083,9 @@ static BMesh *BME_bevel_mesh(BMesh *bm, float value, int UNUSED(res), int option
if (l->v != v) l = l->next;
if (l2->v != v) l2 = l2->next;
if (l->f->len > 3)
- BM_face_split(bm, l->f, l->next->v, l->prev->v, &l, l->e, TRUE); /* clip this corner off */
+ BM_face_split(bm, l->f, l->next->v, l->prev->v, &l, l->e, true); /* clip this corner off */
if (l2->f->len > 3)
- BM_face_split(bm, l2->f, l2->next->v, l2->prev->v, &l, l2->e, TRUE); /* clip this corner off */
+ BM_face_split(bm, l2->f, l2->next->v, l2->prev->v, &l, l2->e, true); /* clip this corner off */
curedge = bmesh_disk_edge_next(curedge, v);
} while (curedge != v->e);
BME_Bevel_Dissolve_Disk(bm, v);
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index fe9b0f21812..f685b741176 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -30,20 +30,23 @@
#include "MEM_guardedalloc.h"
+#include "DNA_object_types.h"
+#include "DNA_meshdata_types.h"
+
#include "BLI_array.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BKE_customdata.h"
+#include "BKE_deform.h"
#include "bmesh.h"
+#include "./intern/bmesh_private.h"
-/* experemental - Campbell */
-// #define USE_ALTERNATE_ADJ
-
-#define BEVEL_EPSILON 1e-6
+#define BEVEL_EPSILON_D 1e-6
+#define BEVEL_EPSILON 1e-6f
/* for testing */
// #pragma GCC diagnostic error "-Wpadded"
@@ -93,7 +96,7 @@ typedef struct VMesh {
M_NONE, /* no polygon mesh needed */
M_POLY, /* a simple polygon */
M_ADJ, /* "adjacent edges" mesh pattern */
-// M_CROSS, /* "cross edges" mesh pattern */
+ M_ADJ_SUBDIV, /* like M_ADJ, but using subdivision */
M_TRI_FAN, /* a simple polygon - fan filled */
M_QUAD_STRIP, /* a simple polygon - cut into paralelle strips */
} mesh_kind;
@@ -105,6 +108,7 @@ typedef struct BevVert {
BMVert *v; /* original mesh vertex */
int edgecount; /* total number of edges around the vertex */
int selcount; /* number of selected edges around the vertex */
+ float offset; /* offset for this vertex, if vertex_only bevel */
EdgeHalf *edges; /* array of size edgecount; CCW order from vertex normal side */
VMesh *vmesh; /* mesh structure for replacing vertex */
} BevVert;
@@ -118,11 +122,15 @@ typedef struct BevelParams {
float offset; /* blender units to offset each side of a beveled edge */
int seg; /* number of segments in beveled edge profile */
+ bool vertex_only; /* bevel vertices only */
+ bool use_weights; /* bevel amount affected by weights on edges or verts */
+ const struct MDeformVert *dvert; /* vertex group array, maybe set if vertex_only */
+ int vertex_group; /* vertex group index, maybe set if vertex_only */
} BevelParams;
// #pragma GCC diagnostic ignored "-Wpadded"
-//#include "bevdebug.c"
+// #include "bevdebug.c"
/* Make a new BoundVert of the given kind, insert it at the end of the circular linked
* list with entry point bv->boundstart, and return it. */
@@ -165,6 +173,7 @@ static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert
{
NewVert *nv = mesh_vert(vm, i, j, k);
nv->v = BM_vert_create(bm, nv->co, eg, 0);
+ BM_elem_flag_disable(nv->v, BM_ELEM_TAG);
}
static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto,
@@ -268,7 +277,11 @@ static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv, BMF
for (i = 0; i < totv; i++) {
ee[i] = BM_edge_create(bm, vert_arr[i], vert_arr[(i + 1) % totv], NULL, BM_CREATE_NO_DOUBLE);
}
+#if 0
f = BM_face_create_ngon(bm, vert_arr[0], vert_arr[1], ee, totv, 0);
+#else
+ f = BM_face_create(bm, vert_arr, ee, totv, 0);
+#endif
}
if (facerep && f) {
int has_mdisps = CustomData_has_layer(&bm->ldata, CD_MDISPS);
@@ -316,7 +329,7 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f,
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 (angle_v3v3(dir1, dir2) < 100.0f * (float)BEVEL_EPSILON) {
+ if (angle_v3v3(dir1, dir2) < 100.0f * BEVEL_EPSILON) {
/* 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: just use e1->offset */
@@ -362,8 +375,8 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f,
}
}
-/* Like offset_meet, but here f1 and f2 must not be NULL and give the
- * planes in which to run the offset lines.
+/* Like offset_meet, but with a mid edge between them that is used
+ * to calculate the planes in which to run the offset lines.
* They may not meet exactly: the offsets for the edges may be different
* or both the planes and the lines may be angled so that they can't meet.
* In that case, pick a close point on emid, which should be the dividing
@@ -371,15 +384,13 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f,
* TODO: should have a global 'offset consistency' prepass to adjust offset
* widths so that all edges have the same offset at both ends. */
static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid,
- BMVert *v, BMFace *f1, BMFace *f2, float meetco[3])
+ BMVert *v, float meetco[3])
{
float dir1[3], dir2[3], dirmid[3], norm_perp1[3], norm_perp2[3],
off1a[3], off1b[3], off2a[3], off2b[3], isect2[3], co[3],
f1no[3], f2no[3];
int iret;
- BLI_assert(f1 != NULL && f2 != NULL);
-
/* 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);
@@ -402,7 +413,7 @@ static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid,
madd_v3_v3fl(off2a, norm_perp2, e2->offset);
add_v3_v3v3(off2b, off2a, dir2);
- if (angle_v3v3(dir1, dir2) < 100.0f * (float)BEVEL_EPSILON) {
+ if (angle_v3v3(dir1, dir2) < 100.0f * BEVEL_EPSILON) {
/* lines are parallel; off1a is a good meet point */
copy_v3_v3(meetco, off1a);
}
@@ -414,7 +425,7 @@ static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid,
}
else if (iret == 2) {
/* lines are not coplanar; meetco and isect2 are nearest to first and second lines */
- if (len_v3v3(meetco, isect2) > 100.0f * (float)BEVEL_EPSILON) {
+ if (len_v3v3(meetco, isect2) > 100.0f * BEVEL_EPSILON) {
/* offset lines don't meet: project average onto emid; this is not ideal (see TODO above) */
mid_v3_v3v3(co, meetco, isect2);
closest_to_line_v3(meetco, co, v->co, BM_edge_other_vert(emid->e, v)->co);
@@ -463,7 +474,7 @@ static void slide_dist(EdgeHalf *e, BMVert *v, float d, float slideco[3])
sub_v3_v3v3(dir, v->co, BM_edge_other_vert(e->e, v)->co);
len = normalize_v3(dir);
if (d > len)
- d = len - (float)(50.0 * BEVEL_EPSILON);
+ d = len - (float)(50.0 * BEVEL_EPSILON_D);
copy_v3_v3(slideco, v->co);
madd_v3_v3fl(slideco, dir, -d);
}
@@ -494,79 +505,6 @@ static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f)
return lb->next == la ? 1 : -1;
}
-#ifdef USE_ALTERNATE_ADJ
-
-static void vmesh_cent(VMesh *vm, float r_cent[3])
-{
- BoundVert *v;
- zero_v3(r_cent);
-
- v = vm->boundstart;
- do {
- add_v3_v3(r_cent, v->nv.co);
- } while ((v = v->next) != vm->boundstart);
- mul_v3_fl(r_cent, 1.0f / (float)vm->count);
-}
-
-/**
- *
- * This example shows a tri fan of quads,
- * but could be an NGon fan of quads too.
- * <pre>
- * The whole triangle X
- * represents the / \
- * new bevel face. / \
- * / \
- * Split into / \
- * a quad fan. / \
- * / \
- * / \
- * / \
- * co_prev +-. .-+
- * / `-._ _.-' \
- * / co_cent`-+-' \
- * / | \
- * Quad of / | \
- * interest -- / ---> X | \
- * / | \
- * / | \
- * / co_next| \
- * co_orig +-----------------+-----------------+
- *
- * For each quad, calcualte UV's based on the following:
- * U = k / (vm->seg * 2)
- * V = ring / (vm->seg * 2)
- * quad = (co_orig, co_prev, co_cent, co_next)
- * ... note that co_cent is the same for all quads in the fan.
- * </pre>
- *
- */
-
-static void get_point_uv(float uv[2],
- /* all these args are int's originally
- * but pass as floats to the function */
- const float seg, const float ring, const float k)
-{
- uv[0] = (ring / seg) * 2.0f;
- uv[1] = (k / seg) * 2.0f;
-}
-
-/* TODO: make this a lot smarter!,
- * this is the main reason USE_ALTERNATE_ADJ isn't so good right now :S */
-static float get_point_uv_factor(const float uv[2])
-{
- return sinf(1.0f - max_ff(uv[0], uv[1]) / 2.0f);
-}
-
-static void get_point_on_round_edge(const float uv[2],
- float quad[4][3],
- float r_co[3])
-{
- interp_bilinear_quad_v3(quad, uv[0], uv[1], r_co);
-}
-
-#else /* USE_ALTERNATE_ADJ */
-
/* Fill matrix r_mat so that a point in the sheared parallelogram with corners
* va, vmid, vb (and the 4th that is implied by it being a parallelogram)
* is transformed to the unit square by multiplication with r_mat.
@@ -586,7 +524,7 @@ static void get_point_on_round_edge(const float uv[2],
* We want M to make M*A=B where A has the left side above, as columns
* 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 int make_unit_square_map(const float va[3], const float vmid[3], const float vb[3],
float r_mat[4][4])
{
@@ -594,7 +532,7 @@ static int make_unit_square_map(const float va[3], const float vmid[3], const fl
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.f *(float)BEVEL_EPSILON) {
+ if (fabsf(angle_v3v3(va_vmid, vb_vmid) - (float)M_PI) > 100.0f * BEVEL_EPSILON) {
sub_v3_v3v3(vo, va, vb_vmid);
cross_v3_v3v3(vddir, vb_vmid, va_vmid);
normalize_v3(vddir);
@@ -687,14 +625,13 @@ static void snap_to_edge_profile(EdgeHalf *e, const float va[3], const float vb[
}
}
-#endif /* !USE_ALTERNATE_ADJ */
-
/* Make a circular list of BoundVerts for bv, each of which has the coordinates
* of a vertex on the the boundary of the beveled vertex bv->v.
* Also decide on the mesh pattern that will be used inside the boundary.
* Doesn't make the actual BMVerts */
-static void build_boundary(MemArena *mem_arena, BevVert *bv)
+static void build_boundary(BevelParams *bp, BevVert *bv)
{
+ MemArena *mem_arena = bp->mem_arena;
EdgeHalf *efirst, *e;
BoundVert *v;
VMesh *vm;
@@ -702,9 +639,13 @@ static void build_boundary(MemArena *mem_arena, BevVert *bv)
const float *no;
float lastd;
- e = efirst = next_bev(bv, NULL);
vm = bv->vmesh;
+ if (bp->vertex_only)
+ e = efirst = &bv->edges[0];
+ else
+ e = efirst = next_bev(bv, NULL);
+
BLI_assert(bv->edgecount >= 2); /* since bevel edges incident to 2 faces */
if (bv->edgecount == 2 && bv->selcount == 1) {
@@ -729,7 +670,7 @@ static void build_boundary(MemArena *mem_arena, BevVert *bv)
return;
}
- lastd = e->offset;
+ lastd = bp->vertex_only? bv->offset : e->offset;
vm->boundstart = NULL;
do {
if (e->is_bev) {
@@ -748,8 +689,7 @@ static void build_boundary(MemArena *mem_arena, BevVert *bv)
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 */
- offset_in_two_planes(e->prev->prev, e, e->prev, bv->v,
- e->prev->prev->fnext, e->fprev, co);
+ offset_in_two_planes(e->prev->prev, e, e->prev, bv->v, co);
v = add_new_bound_vert(mem_arena, vm, co);
v->efirst = e->prev->prev;
v->elast = v->ebev = e;
@@ -799,7 +739,10 @@ static void build_boundary(MemArena *mem_arena, BevVert *bv)
} while ((e = e->next) != efirst);
BLI_assert(vm->count >= 2);
- if (vm->count == 2 && bv->edgecount == 3) {
+ if (bp->vertex_only) {
+ vm->mesh_kind = bp->seg > 1 ? M_ADJ_SUBDIV : M_POLY;
+ }
+ else if (vm->count == 2 && bv->edgecount == 3) {
vm->mesh_kind = M_NONE;
}
else if (bv->selcount == 2) {
@@ -834,19 +777,6 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv)
float co[3], coa[3], cob[3], midco[3];
float va_pipe[3], vb_pipe[3];
-#ifdef USE_ALTERNATE_ADJ
- /* ordered as follows (orig, prev, center, next)*/
- float quad_plane[4][3];
- float quad_orig[4][3];
-#endif
-
-
-#ifdef USE_ALTERNATE_ADJ
- /* the rest are initialized inline, this remains the same for all */
- vmesh_cent(vm, quad_plane[2]);
- copy_v3_v3(quad_orig[2], bv->v->co);
-#endif
-
n = vm->count;
ns = vm->seg;
ns2 = ns / 2;
@@ -863,7 +793,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv)
float dir1[3], dir2[3];
sub_v3_v3v3(dir1, bv->v->co, BM_edge_other_vert(e1->e, bv->v)->co);
sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, bv->v)->co, bv->v->co);
- if (angle_v3v3(dir1, dir2) < 100.0f * (float)BEVEL_EPSILON) {
+ if (angle_v3v3(dir1, dir2) < 100.0f * BEVEL_EPSILON) {
epipe = e1;
break;
}
@@ -906,37 +836,6 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv)
copy_v3_v3(nv->co, cob);
nv->v = nvnext->v;
-#ifdef USE_ALTERNATE_ADJ
- /* plane */
- copy_v3_v3(quad_plane[0], v->nv.co);
- mid_v3_v3v3(quad_plane[1], v->nv.co, v->prev->nv.co);
- /* quad[2] is set */
- mid_v3_v3v3(quad_plane[3], v->nv.co, v->next->nv.co);
-
- /* orig */
- copy_v3_v3(quad_orig[0], v->nv.co); /* only shared location between 2 quads */
- project_to_edge(v->ebev->prev->e, v->nv.co, v->prev->nv.co, quad_orig[1]);
- project_to_edge(v->ebev->e, v->nv.co, v->next->nv.co, quad_orig[3]);
-
- //bl_debug_draw_quad_add(UNPACK4(quad_plane));
- //bl_debug_draw_quad_add(UNPACK4(quad_orig));
-#endif
-
-#ifdef USE_ALTERNATE_ADJ
- for (k = 1; k < ns; k++) {
- float uv[2];
- float fac;
- float co_plane[3];
- float co_orig[3];
-
- get_point_uv(uv, v->ebev->seg, ring, k);
- get_point_on_round_edge(uv, quad_plane, co_plane);
- get_point_on_round_edge(uv, quad_orig, co_orig);
- fac = get_point_uv_factor(uv);
- interp_v3_v3v3(co, co_plane, co_orig, fac);
- copy_v3_v3(mesh_vert(vm, i, ring, k)->co, co);
- }
-#else
/* TODO: better calculation of new midarc point? */
project_to_edge(v->ebev->e, coa, cob, midco);
@@ -950,7 +849,6 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv)
copy_v3_v3(va_pipe, mesh_vert(vm, i, 0, 0)->co);
copy_v3_v3(vb_pipe, mesh_vert(vm, i, 0, ns)->co);
}
-#endif
}
} while ((v = v->next) != vm->boundstart);
}
@@ -978,9 +876,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv)
if (epipe)
snap_to_edge_profile(epipe, va_pipe, vb_pipe, co);
-#ifndef USE_ALTERNATE_ADJ
copy_v3_v3(nv->co, co);
-#endif
BLI_assert(nv->v == NULL && nvprev->v == NULL);
create_mesh_bmvert(bm, vm, i, ring, k, bv->v);
copy_mesh_vert(vm, vprev->index, k, ns - ring, i, ring, k);
@@ -1029,9 +925,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv)
mid_v3_v3v3v3(co, nvprev->co, nv->co, nvnext->co);
if (epipe)
snap_to_edge_profile(epipe, va_pipe, vb_pipe, co);
-#ifndef USE_ALTERNATE_ADJ
copy_v3_v3(nv->co, co);
-#endif
create_mesh_bmvert(bm, vm, i, k, ns2, bv->v);
copy_mesh_vert(vm, vprev->index, ns2, ns - k, i, k, ns2);
copy_mesh_vert(vm, vnext->index, ns2, k, i, k, ns2);
@@ -1041,9 +935,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv)
mid_v3_v3v3(co, nvprev->co, nv->co);
if (epipe)
snap_to_edge_profile(epipe, va_pipe, vb_pipe, co);
-#ifndef USE_ALTERNATE_ADJ
copy_v3_v3(nv->co, co);
-#endif
create_mesh_bmvert(bm, vm, i, k, ns2, bv->v);
copy_mesh_vert(vm, vprev->index, ns2, ns - k, i, k, ns2);
@@ -1053,9 +945,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv)
mid_v3_v3v3(co, nv->co, nvnext->co);
if (epipe)
snap_to_edge_profile(epipe, va_pipe, vb_pipe, co);
-#ifndef USE_ALTERNATE_ADJ
copy_v3_v3(nv->co, co);
-#endif
create_mesh_bmvert(bm, vm, i, k, ns2, bv->v);
copy_mesh_vert(vm, vnext->index, ns2, k, i, k, ns2);
@@ -1135,7 +1025,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv)
/* Make center ngon if odd number of segments and fully beveled */
if (ns % 2 == 1 && vm->count == bv->selcount) {
BMVert **vv = NULL;
- BLI_array_declare(vv);
+ BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE);
v = vm->boundstart;
do {
@@ -1153,7 +1043,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv)
if (vm->count > bv->selcount) {
int j;
BMVert **vv = NULL;
- BLI_array_declare(vv);
+ BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE);
v = vm->boundstart;
f = boundvert_rep_face(v);
@@ -1208,6 +1098,413 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv)
}
}
+static VMesh *new_adj_subdiv_vmesh(MemArena *mem_arena, int count, int seg, BoundVert *bounds)
+{
+ VMesh *vm;
+
+ vm = (VMesh *)BLI_memarena_alloc(mem_arena, sizeof(VMesh));
+ vm->count = count;
+ vm->seg = seg;
+ vm->boundstart = bounds;
+ vm->mesh = (NewVert *)BLI_memarena_alloc(mem_arena, count * (1 + seg / 2) * (1 + seg) * sizeof(NewVert));
+ vm->mesh_kind = M_ADJ_SUBDIV;
+ return vm;
+}
+
+/* VMesh verts for vertex i have data for (i, 0 <= j <= ns2, 0 <= k <= ns), where ns2 = floor(nseg / 2).
+ * But these overlap data from previous and next i: there are some forced equivalences.
+ * Let's call these indices the canonical ones: we will just calculate data for these
+ * 0 <= j <= ns2, 0 <= k < ns2 (for odd ns2)
+ * 0 <= j < ns2, 0 <= k <= ns2 (for even ns2)
+ * also (j=ns2, k=ns2) at i=0 (for even ns2)
+ * This function returns the canonical one for any i, j, k in [0,n],[0,ns],[0,ns] */
+static NewVert *mesh_vert_canon(VMesh *vm, int i, int j, int k)
+{
+ int n, ns, ns2, odd;
+ NewVert *ans;
+
+ n = vm->count;
+ ns = vm->seg;
+ ns2 = ns / 2;
+ odd = ns % 2;
+ BLI_assert(0 <= i && i <= n && 0 <= j && j <= ns && 0 <= k && k <= ns);
+
+ if (!odd && j == ns2 && k == ns2)
+ ans = mesh_vert(vm, 0, j, k);
+ else if (j <= ns2 - 1 + odd && k <= ns2)
+ ans = mesh_vert(vm, i, j, k);
+ else if (k <= ns2)
+ ans = mesh_vert(vm, (i + n - 1) % n, k, ns - j);
+ else
+ ans = mesh_vert(vm, (i + 1) % n, ns - k, j);
+ return ans;
+}
+
+static int is_canon(VMesh *vm, int i, int j, int k)
+{
+ int ns2 = vm->seg / 2;
+ if (vm->seg % 2 == 1)
+ return (j <= ns2 && k <= ns2);
+ else
+ return ((j < ns2 && k <= ns2) || (j == ns2 && k == ns2 && i == 0));
+}
+
+/* Copy the vertex data to all of vm verts from canonical ones */
+static void vmesh_copy_equiv_verts(VMesh *vm)
+{
+ int n, ns, ns2, i, j, k;
+ NewVert *v0, *v1;
+
+ n = vm->count;
+ ns = vm->seg;
+ ns2 = ns / 2;
+ for (i = 0; i < n; i++) {
+ for (j = 0; j <= ns2; j++) {
+ for (k = 0; k <= ns; k++) {
+ if (is_canon(vm, i, j, k))
+ continue;
+ v1 = mesh_vert(vm, i, j, k);
+ v0 = mesh_vert_canon(vm, i, j, k);
+ copy_v3_v3(v1->co, v0->co);
+ v1->v = v0->v;
+ }
+ }
+ }
+}
+
+/* Calculate and return in r_cent the centroid of the center poly */
+static void vmesh_center(VMesh *vm, float r_cent[3])
+{
+ int n, ns2, i;
+
+ n = vm->count;
+ ns2 = vm->seg / 2;
+ if (vm->seg % 2) {
+ zero_v3(r_cent);
+ for (i = 0; i < n; i++) {
+ add_v3_v3(r_cent, mesh_vert(vm, i, ns2, ns2)->co);
+ }
+ mul_v3_fl(r_cent, 1.0f / (float) n);
+ }
+ else {
+ copy_v3_v3(r_cent, mesh_vert(vm, 0, ns2, ns2)->co);
+ }
+}
+
+/* Do one step of quadratic subdivision (Doo-Sabin), with special rules at boundaries.
+ * For now, this is written assuming vm0->nseg is odd.
+ * See Hwang-Chuang 2003 paper: "N-sided hole filling and vertex blending using subdivision surfaces" */
+static VMesh *quadratic_subdiv(MemArena *mem_arena, VMesh *vm0)
+{
+ int n, ns0, ns20, ns1 /*, ns21 */;
+ int i, j, k, j1, k1;
+ VMesh *vm1;
+ float co[3], co1[3], co2[3], co3[3], co4[3];
+ float co11[3], co21[3], co31[3], co41[3];
+ float denom;
+ const float wcorner[4] = {0.25f, 0.25f, 0.25f, 0.25f};
+ const float wboundary[4] = {0.375f, 0.375f, 0.125f, 0.125f}; /* {3, 3, 1, 1}/8 */
+ const float winterior[4] = {0.5625f, 0.1875f, 0.1875f, 0.0625f}; /* {9, 3, 3, 1}/16 */
+
+ n = vm0->count;
+ ns0 = vm0->seg;
+ ns20 = ns0 / 2;
+ BLI_assert(ns0 % 2 == 1);
+
+ ns1 = 2 * ns0 - 1;
+ // ns21 = ns1 / 2; /* UNUSED */
+ vm1 = new_adj_subdiv_vmesh(mem_arena, n, ns1, vm0->boundstart);
+
+ for (i = 0; i < n; i ++) {
+ /* For handle vm0 polys with lower left corner at (i,j,k) for
+ * j in [0, ns20], k in [0, ns20]; then the center ngon.
+ * but only fill in data for canonical verts of v1. */
+ for (j = 0; j <= ns20; j++) {
+ for (k = 0; k <= ns20; k++) {
+ if (j == ns20 && k == ns20)
+ continue; /* center ngon is special */
+ copy_v3_v3(co1, mesh_vert_canon(vm0, i, j, k)->co);
+ copy_v3_v3(co2, mesh_vert_canon(vm0, i, j, k + 1)->co);
+ copy_v3_v3(co3, mesh_vert_canon(vm0, i, j + 1, k + 1)->co);
+ copy_v3_v3(co4, mesh_vert_canon(vm0, i, j + 1, k)->co);
+ if (j == 0 && k == 0) {
+ /* corner */
+ copy_v3_v3(co11, co1);
+ interp_v3_v3v3(co21, co1, co2, 0.5f);
+ interp_v3_v3v3v3v3(co31, co1, co2, co3, co4, wcorner);
+ interp_v3_v3v3(co41, co1, co4, 0.5f);
+ }
+ else if (j == 0) {
+ /* ring 0 boundary */
+ interp_v3_v3v3(co11, co1, co2, 0.25f);
+ interp_v3_v3v3(co21, co1, co2, 0.75f);
+ interp_v3_v3v3v3v3(co31, co2, co3, co1, co4, wboundary);
+ interp_v3_v3v3v3v3(co41, co1, co4, co2, co3, wboundary);
+ }
+ else if (k == 0) {
+ /* ring-starts boundary */
+ interp_v3_v3v3(co11, co1, co4, 0.25f);
+ interp_v3_v3v3v3v3(co21, co1, co2, co3, co4, wboundary);
+ interp_v3_v3v3v3v3(co31, co3, co4, co1, co2, wboundary);
+ interp_v3_v3v3(co41, co1, co4, 0.75f);
+ }
+ else {
+ /* interior */
+ interp_v3_v3v3v3v3(co11, co1, co2, co4, co3, winterior);
+ interp_v3_v3v3v3v3(co21, co2, co1, co3, co4, winterior);
+ interp_v3_v3v3v3v3(co31, co3, co2, co4, co1, winterior);
+ interp_v3_v3v3v3v3(co41, co4, co1, co3, co2, winterior);
+ }
+ j1 = 2 * j;
+ k1 = 2 * k;
+ if (is_canon(vm1, i, j1, k1))
+ copy_v3_v3(mesh_vert(vm1, i, j1, k1)->co, co11);
+ if (is_canon(vm1, i, j1, k1 + 1))
+ copy_v3_v3(mesh_vert(vm1, i, j1, k1 + 1)->co, co21);
+ if (is_canon(vm1, i, j1 + 1, k1 + 1))
+ copy_v3_v3(mesh_vert(vm1, i, j1 + 1, k1 + 1)->co, co31);
+ if (is_canon(vm1, i, j1 + 1, k1))
+ copy_v3_v3(mesh_vert(vm1, i, j1 + 1, k1)->co, co41);
+ }
+ }
+
+ /* center ngon */
+ denom = 8.0f * (float) n;
+ zero_v3(co);
+ for (j = 0; j < n; j++) {
+ copy_v3_v3(co1, mesh_vert(vm0, j, ns20, ns20)->co);
+ if (i == j)
+ madd_v3_v3fl(co, co1, (4.0f * (float) n + 2.0f) / denom);
+ else if ((i + 1) % n == j || (i + n - 1) % n == j)
+ madd_v3_v3fl(co, co1, ((float) n + 2.0f) / denom);
+ else
+ madd_v3_v3fl(co, co1, 2.0f / denom);
+ }
+ copy_v3_v3(mesh_vert(vm1, i, 2 * ns20, 2 * ns20)->co, co);
+ }
+
+ vmesh_copy_equiv_verts(vm1);
+ return vm1;
+}
+
+/* After a step of quadratic_subdiv, adjust the ring 1 verts to be on the planes of their respective faces,
+ * so that the cross-tangents will match on further subdivision. */
+static void fix_vmesh_tangents(VMesh *vm, BevVert *bv)
+{
+ int i, n;
+ NewVert *v;
+ BoundVert *bndv;
+ float co[3];
+
+ n = vm->count;
+ bndv = vm->boundstart;
+ do {
+ i = bndv->index;
+
+ /* (i, 1, 1) snap to edge line */
+ v = mesh_vert(vm, i, 1, 1);
+ closest_to_line_v3(co, v->co, bndv->nv.co, bv->v->co);
+ copy_v3_v3(v->co, co);
+ copy_v3_v3(mesh_vert(vm, (i + n -1) % n, 1, vm->seg - 1)->co, co);
+
+ /* Also want (i, 1, k) snapped to plane of adjacent face for
+ * 1 < k < ns - 1, but current initial cage and subdiv rules
+ * ensure this, so nothing to do */
+ } while ((bndv = bndv->next) != vm->boundstart);
+}
+
+/* Fill frac with fractions of way along ring 0 for vertex i, for use with interp_range function */
+static void fill_vmesh_fracs(VMesh *vm, float *frac, int i)
+{
+ int k, ns;
+ float total = 0.0f;
+
+ ns = vm->seg;
+ frac[0] = 0.0f;
+ for (k = 0; k < ns; k++) {
+ total += len_v3v3(mesh_vert(vm, i, 0, k)->co, mesh_vert(vm, i, 0, k + 1)->co);
+ frac[k + 1] = total;
+ }
+ if (total > BEVEL_EPSILON) {
+ for (k = 1; k <= ns; k++)
+ frac[k] /= total;
+ }
+}
+
+/* Return i such that frac[i] <= f <= frac[i + 1], where frac[n] == 1.0
+ * and put fraction of rest of way between frac[i] and frac[i + 1] into r_rest */
+static int interp_range(const float *frac, int n, const float f, float *r_rest)
+{
+ int i;
+ float rest;
+
+ /* could binary search in frac, but expect n to be reasonably small */
+ for (i = 0; i < n; i++) {
+ if (f <= frac[i + 1]) {
+ rest = f - frac[i];
+ if (rest == 0)
+ *r_rest = 0.0f;
+ else
+ *r_rest = rest / (frac[i + 1] - frac[i]);
+ return i;
+ }
+ }
+ *r_rest = 0.0f;
+ return n;
+}
+
+/* Interpolate given vmesh to make one with target nseg and evenly spaced border vertices */
+static VMesh *interp_vmesh(MemArena *mem_arena, VMesh *vm0, int nseg)
+{
+ int n, ns0, nseg2, odd, i, j, k, j0, k0;
+ float *prev_frac, *frac, f, restj, restk;
+ float quad[4][3], co[3], center[3];
+ VMesh *vm1;
+
+ n = vm0->count;
+ ns0 = vm0->seg;
+ nseg2 = nseg / 2;
+ odd = nseg % 2;
+ vm1 = new_adj_subdiv_vmesh(mem_arena, n, nseg, vm0->boundstart);
+ prev_frac = (float *)BLI_memarena_alloc(mem_arena, (ns0 + 1 ) *sizeof(float));
+ frac = (float *)BLI_memarena_alloc(mem_arena, (ns0 + 1 ) *sizeof(float));
+
+ fill_vmesh_fracs(vm0, prev_frac, n - 1);
+ fill_vmesh_fracs(vm0, frac, 0);
+ for (i = 0; i < n; i++) {
+ for (j = 0; j <= nseg2 -1 + odd; j++) {
+ for (k = 0; k <= nseg2; k++) {
+ f = (float) k / (float) nseg;
+ k0 = interp_range(frac, ns0, f, &restk);
+ f = 1.0f - (float) j / (float) nseg;
+ j0 = interp_range(prev_frac, ns0, f, &restj);
+ if (restj < BEVEL_EPSILON) {
+ j0 = ns0 - j0;
+ restj = 0.0f;
+ }
+ else {
+ j0 = ns0 - j0 - 1;
+ restj = 1.0f - restj;
+ }
+ /* Use bilinear interpolation within the source quad; could be smarter here */
+ if (restj < BEVEL_EPSILON && restk < BEVEL_EPSILON) {
+ copy_v3_v3(co, mesh_vert_canon(vm0, i, j0, k0)->co);
+ }
+ else {
+ copy_v3_v3(quad[0], mesh_vert_canon(vm0, i, j0, k0)->co);
+ copy_v3_v3(quad[1], mesh_vert_canon(vm0, i, j0, k0 + 1)->co);
+ copy_v3_v3(quad[2], mesh_vert_canon(vm0, i, j0 + 1, k0 + 1)->co);
+ copy_v3_v3(quad[3], mesh_vert_canon(vm0, i, j0 + 1, k0)->co);
+ interp_bilinear_quad_v3(quad, restk, restj, co);
+ }
+ copy_v3_v3(mesh_vert(vm1, i, j, k)->co, co);
+ }
+ }
+ }
+ if (!odd) {
+ vmesh_center(vm0, center);
+ copy_v3_v3(mesh_vert(vm1, 0, nseg2, nseg2)->co, center);
+ }
+ vmesh_copy_equiv_verts(vm1);
+ return vm1;
+}
+
+/*
+ * 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_SUBDIV pattern,
+ * then make the BMVerts and the new faces. */
+static void bevel_build_rings_subdiv(BevelParams *bp, BMesh *bm, BevVert *bv)
+{
+ int n, ns, ns2, odd, i, j, k;
+ VMesh *vm0, *vm1, *vm;
+ float coa[3], cob[3], coc[3];
+ BoundVert *v;
+ BMVert *bmv1, *bmv2, *bmv3, *bmv4;
+ BMFace *f;
+ MemArena *mem_arena = bp->mem_arena;
+ const float fullness = 0.5f;
+
+ n = bv->edgecount;
+ ns = bv->vmesh->seg;
+ ns2 = ns / 2;
+ odd = ns % 2;
+ BLI_assert(n >= 3 && ns > 1);
+
+ /* First construct an initial control mesh, with nseg==3 */
+ vm0 = new_adj_subdiv_vmesh(mem_arena, n, 3, bv->vmesh->boundstart);
+
+ for (i = 0; i < n; i++) {
+ /* Boundaries just divide input polygon edges into 3 even segments */
+ copy_v3_v3(coa, mesh_vert(bv->vmesh, i, 0, 0)->co);
+ copy_v3_v3(cob, mesh_vert(bv->vmesh, (i + 1) % n, 0, 0)->co);
+ copy_v3_v3(coc, mesh_vert(bv->vmesh, (i + n -1) % n, 0, 0)->co);
+ copy_v3_v3(mesh_vert(vm0, i, 0, 0)->co, coa);
+ interp_v3_v3v3(mesh_vert(vm0, i, 0, 1)->co, coa, cob, 1.0f / 3.0f);
+ interp_v3_v3v3(mesh_vert(vm0, i, 1, 0)->co, coa, coc, 1.0f / 3.0f);
+ interp_v3_v3v3(mesh_vert(vm0, i, 1, 1)->co, coa, bv->v->co, fullness);
+ }
+ vmesh_copy_equiv_verts(vm0);
+
+ vm1 = vm0;
+ do {
+ vm1 = quadratic_subdiv(mem_arena, vm1);
+ fix_vmesh_tangents(vm1, bv);
+ } while (vm1->seg <= ns);
+ vm1 = interp_vmesh(mem_arena, vm1, ns);
+
+ /* copy final vmesh into bv->vmesh, make BMVerts and BMFaces */
+ vm = bv->vmesh;
+ for (i = 0; i < n; i ++) {
+ for (j = 0; j <= ns2; j++) {
+ for (k = 0; k <= ns; k++) {
+ if (j == 0 && (k == 0 || k == ns))
+ continue; /* boundary corners already made */
+ if (!is_canon(vm, i, j, k))
+ continue;
+ copy_v3_v3(mesh_vert(vm, i, j, k)->co, mesh_vert(vm1, i, j, k)->co);
+ create_mesh_bmvert(bm, vm, i, j, k, bv->v);
+ }
+ }
+ }
+ vmesh_copy_equiv_verts(vm);
+ /* make the polygons */
+ v = vm->boundstart;
+ do {
+ i = v->index;
+ f = boundvert_rep_face(v);
+ /* 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,
+ * j in [0, ns2-1], k in [0, ns2-1] */
+ for (j = 0; j < ns2; j++) {
+ for (k = 0; k < ns2 + odd; k++) {
+ bmv1 = mesh_vert(vm, i, j, k)->v;
+ bmv2 = mesh_vert(vm, i, j, k + 1)->v;
+ 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);
+ bev_create_quad_tri(bm, bmv1, bmv2, bmv3, bmv4, f);
+ }
+ }
+ } while ((v = v->next) != vm->boundstart);
+
+ /* center ngon */
+ if (odd) {
+ BMVert **vv = NULL;
+ BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE);
+
+ v = vm->boundstart;
+ do {
+ i = v->index;
+ BLI_array_append(vv, mesh_vert(vm, i, ns2, ns2)->v);
+ } while ((v = v->next) != vm->boundstart);
+ f = boundvert_rep_face(vm->boundstart);
+ bev_create_ngon(bm, vv, BLI_array_count(vv), f);
+
+ BLI_array_free(vv);
+ }
+}
+
static BMFace *bevel_build_poly_ex(BMesh *bm, BevVert *bv)
{
BMFace *f;
@@ -1215,7 +1512,7 @@ static BMFace *bevel_build_poly_ex(BMesh *bm, BevVert *bv)
VMesh *vm = bv->vmesh;
BoundVert *v;
BMVert **vv = NULL;
- BLI_array_declare(vv);
+ BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE);
v = vm->boundstart;
n = 0;
@@ -1271,7 +1568,7 @@ static void bevel_build_trifan(BMesh *bm, BevVert *bv)
else { BLI_assert(0); }
}
else {
- if (l_fan->v == v_fan) { l_fan = l_fan; }
+ if (l_fan->v == v_fan) { /* l_fan = l_fan; */ }
else if (l_fan->next->v == v_fan) { l_fan = l_fan->next; }
else if (l_fan->prev->v == v_fan) { l_fan = l_fan->prev; }
else { BLI_assert(0); }
@@ -1320,30 +1617,14 @@ static void bevel_build_quadstrip(BMesh *bm, BevVert *bv)
/* Given that the boundary is built, now make the actual BMVerts
* for the boundary and the interior of the vertex mesh. */
-static void build_vmesh(MemArena *mem_arena, BMesh *bm, BevVert *bv)
+static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv)
{
+ MemArena *mem_arena = bp->mem_arena;
VMesh *vm = bv->vmesh;
BoundVert *v, *weld1, *weld2;
int n, ns, ns2, i, k, weld;
float *va, *vb, co[3];
-
-#ifdef USE_ALTERNATE_ADJ
- /* ordered as follows (orig, prev, center, next)*/
- float quad_plane[4][3];
- float quad_orig_a[4][3];
- float quad_orig_b[4][3];
- const int is_odd = (vm->seg % 2);
-#else
float midco[3];
-#endif
-
-#ifdef USE_ALTERNATE_ADJ
- /* the rest are initialized inline, this remains the same for all */
- /* NOTE; in this usage we only interpolate on the 'V' so cent and next points are unused (2,3)*/
- vmesh_cent(vm, quad_plane[2]);
- copy_v3_v3(quad_orig_a[2], bv->v->co);
- copy_v3_v3(quad_orig_b[2], bv->v->co);
-#endif
n = vm->count;
ns = vm->seg;
@@ -1376,69 +1657,21 @@ static void build_vmesh(MemArena *mem_arena, BMesh *bm, BevVert *bv)
i = v->index;
copy_mesh_vert(vm, i, 0, ns, v->next->index, 0, 0);
if (v->ebev) {
-
-#ifdef USE_ALTERNATE_ADJ
- copy_v3_v3(quad_plane[0], v->nv.co);
- mid_v3_v3v3(quad_plane[1], v->nv.co, v->prev->nv.co);
- /* quad[2] is set */
- mid_v3_v3v3(quad_plane[3], v->nv.co, v->next->nv.co);
-
- /* orig 'A' */
- copy_v3_v3(quad_orig_a[0], v->nv.co); /* only shared location between 2 quads */
- project_to_edge(v->ebev->prev->e, v->nv.co, v->prev->nv.co, quad_orig_a[1]);
- project_to_edge(v->ebev->e, v->nv.co, v->next->nv.co, quad_orig_a[3]);
-
- /* orig 'B' */
- copy_v3_v3(quad_orig_b[3], v->next->nv.co); /* only shared location between 2 quads */
- project_to_edge(v->ebev->prev->e, v->nv.co, v->prev->nv.co, quad_orig_b[1]);
- project_to_edge(v->ebev->e, v->nv.co, v->next->nv.co, quad_orig_b[0]);
-
- //bl_debug_draw_quad_add(UNPACK4(quad_plane));
- //bl_debug_draw_quad_add(UNPACK4(quad_orig_a));
- //bl_debug_draw_quad_add(UNPACK4(quad_orig_b));
-#endif /* USE_ALTERNATE_ADJ */
-
-#ifdef USE_ALTERNATE_ADJ
- for (k = 1; k < ns; k++) {
- float uv[2];
- float fac;
- float co_plane[3];
- float co_orig[3];
-
- /* quad_plane */
- get_point_uv(uv, v->ebev->seg, 0, k);
- get_point_on_round_edge(uv, quad_plane, co_plane);
-
- /* quad_orig */
- /* each half has different UV's */
- if (k <= ns2) {
- get_point_uv(uv, v->ebev->seg, 0, k);
- get_point_on_round_edge(uv, quad_orig_a, co_orig);
- }
- else {
- get_point_uv(uv, v->ebev->seg, 0, (k - ns2) - (is_odd ? 0.5f : 0.0f));
- get_point_on_round_edge(uv, quad_orig_b, co_orig);
- uv[1] = 1.0f - uv[1]; /* so we can get the factor */
- }
- fac = get_point_uv_factor(uv);
-
- /* done. interp */
- interp_v3_v3v3(co, co_plane, co_orig, fac);
- copy_v3_v3(mesh_vert(vm, i, 0, k)->co, co);
- if (!weld)
- create_mesh_bmvert(bm, vm, i, 0, k, bv->v);
- }
-#else /* USE_ALTERNATE_ADJ */
va = mesh_vert(vm, i, 0, 0)->co;
vb = mesh_vert(vm, i, 0, ns)->co;
- project_to_edge(v->ebev->e, va, vb, midco);
+ if (bv->edgecount == 3 && bv->selcount == 1) {
+ /* special case: profile cuts the third face, so line it up with that */
+ copy_v3_v3(midco, bv->v->co);
+ }
+ else {
+ project_to_edge(v->ebev->e, va, vb, midco);
+ }
for (k = 1; k < ns; k++) {
get_point_on_round_edge(v->ebev, k, va, midco, vb, co);
copy_v3_v3(mesh_vert(vm, i, 0, k)->co, co);
if (!weld)
create_mesh_bmvert(bm, vm, i, 0, k, bv->v);
}
-#endif /* !USE_ALTERNATE_ADJ */
}
} while ((v = v->next) != vm->boundstart);
@@ -1465,6 +1698,9 @@ static void build_vmesh(MemArena *mem_arena, BMesh *bm, BevVert *bv)
case M_ADJ:
bevel_build_rings(bm, bv);
break;
+ case M_ADJ_SUBDIV:
+ bevel_build_rings_subdiv(bp, bm, bv);
+ break;
case M_TRI_FAN:
bevel_build_trifan(bm, bv);
break;
@@ -1475,9 +1711,9 @@ static void build_vmesh(MemArena *mem_arena, BMesh *bm, BevVert *bv)
}
/* take care, this flag isn't cleared before use, it just so happens that its not set */
-#define BM_BEVEL_EDGE_TAG_ENABLE(bme) BM_elem_flag_enable( (bme)->l, BM_ELEM_TAG)
-#define BM_BEVEL_EDGE_TAG_DISABLE(bme) BM_elem_flag_disable( (bme)->l, BM_ELEM_TAG)
-#define BM_BEVEL_EDGE_TAG_TEST(bme) BM_elem_flag_test( (bme)->l, BM_ELEM_TAG)
+#define BM_BEVEL_EDGE_TAG_ENABLE(bme) BM_ELEM_API_FLAG_ENABLE( (bme), _FLAG_OVERLAP)
+#define BM_BEVEL_EDGE_TAG_DISABLE(bme) BM_ELEM_API_FLAG_DISABLE( (bme), _FLAG_OVERLAP)
+#define BM_BEVEL_EDGE_TAG_TEST(bme) BM_ELEM_API_FLAG_TEST( (bme), _FLAG_OVERLAP)
/*
* Construction around the vertex
@@ -1486,10 +1722,11 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
{
BMEdge *bme;
BevVert *bv;
- BMEdge *bme2, *unflagged_bme;
+ BMEdge *bme2, *unflagged_bme, *first_bme;
BMFace *f;
BMIter iter, iter2;
EdgeHalf *e;
+ float weight;
int i, found_shared_face, ccw_test_sum;
int nsel = 0;
int ntot = 0;
@@ -1498,15 +1735,23 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
* Only bevel selected edges that have exactly two incident faces.
*/
+ if (bp->vertex_only)
+ first_bme = v->e;
+ else
+ first_bme = NULL;
BM_ITER_ELEM (bme, &iter, v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(bme, BM_ELEM_TAG)) {
+ if (BM_elem_flag_test(bme, BM_ELEM_TAG) && !bp->vertex_only) {
BLI_assert(BM_edge_is_manifold(bme));
nsel++;
+ if (!first_bme)
+ first_bme = bme;
}
ntot++;
+
+ BM_BEVEL_EDGE_TAG_DISABLE(bme);
}
- if (nsel == 0) {
+ if ((nsel == 0 && !bp->vertex_only) || (ntot < 3 && bp->vertex_only)) {
/* signal this vert isn't being beveled */
BM_elem_flag_disable(v, BM_ELEM_TAG);
return;
@@ -1520,15 +1765,29 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
bv->v = v;
bv->edgecount = ntot;
bv->selcount = nsel;
+ bv->offset = bp->offset;
bv->edges = (EdgeHalf *)BLI_memarena_alloc(bp->mem_arena, ntot * sizeof(EdgeHalf));
bv->vmesh = (VMesh *)BLI_memarena_alloc(bp->mem_arena, sizeof(VMesh));
bv->vmesh->seg = bp->seg;
BLI_ghash_insert(bp->vert_hash, v, bv);
+ if (bp->vertex_only) {
+ /* if weighted, modify offset by weight */
+ if (bp->dvert != NULL && bp->vertex_group != -1) {
+ weight = defvert_find_weight(bp->dvert + BM_elem_index_get(v), bp->vertex_group);
+ if (weight <= 0.0f) {
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ return;
+ }
+ bv->offset *= weight;
+ }
+ }
+
/* add edges to bv->edges in order that keeps adjacent edges sharing
* a face, if possible */
i = 0;
- bme = v->e;
+
+ bme = first_bme;
BM_BEVEL_EDGE_TAG_ENABLE(bme);
e = &bv->edges[0];
e->e = bme;
@@ -1542,6 +1801,8 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
continue;
if (!unflagged_bme)
unflagged_bme = bme2;
+ if (!bme->l)
+ continue;
BM_ITER_ELEM (f, &iter2, bme2, BM_FACES_OF_EDGE) {
if (BM_face_edge_share_loop(f, bme)) {
found_shared_face = 1;
@@ -1563,7 +1824,7 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
}
bme = e->e;
BM_BEVEL_EDGE_TAG_ENABLE(bme);
- if (BM_elem_flag_test(bme, BM_ELEM_TAG)) {
+ if (BM_elem_flag_test(bme, BM_ELEM_TAG) && !bp->vertex_only) {
e->is_bev = TRUE;
e->seg = bp->seg;
}
@@ -1572,11 +1833,20 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
e->seg = 0;
}
e->is_rev = (bme->v2 == v);
- e->offset = e->is_bev ? bp->offset : 0.0f;
+ if (e->is_bev) {
+ e->offset = bp->offset;
+ if (bp->use_weights) {
+ weight = BM_elem_float_data_get(&bm->edata, bme, CD_BWEIGHT);
+ e->offset *= weight;
+ }
+ }
+ else {
+ e->offset = 0.0f;
+ }
}
/* find wrap-around shared face */
BM_ITER_ELEM (f, &iter2, bme, BM_FACES_OF_EDGE) {
- if (BM_face_edge_share_loop(f, bv->edges[0].e)) {
+ if (bv->edges[0].e->l && BM_face_edge_share_loop(f, bv->edges[0].e)) {
if (bv->edges[0].fnext == f)
continue; /* if two shared faces, want the other one now */
bv->edges[ntot - 1].fnext = f;
@@ -1619,8 +1889,8 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
BM_BEVEL_EDGE_TAG_DISABLE(e->e);
}
- build_boundary(bp->mem_arena, bv);
- build_vmesh(bp->mem_arena, bm, bv);
+ build_boundary(bp, bv);
+ build_vmesh(bp, bm, bv);
}
/* Face f has at least one beveled vertex. Rebuild f */
@@ -1663,6 +1933,14 @@ static int bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
BLI_array_append(vv, bmv);
}
}
+ else if (bp->vertex_only && vm->mesh_kind == M_ADJ_SUBDIV && vm->seg > 1) {
+ BLI_assert(v->prev == vend);
+ i = vend->index;
+ for (k = vm->seg - 1; k > 0; k--) {
+ bmv = mesh_vert(vm, i, 0, k)->v;
+ BLI_array_append(vv, bmv);
+ }
+ }
v = v->prev;
BLI_array_append(vv, v->nv.v);
}
@@ -1774,6 +2052,51 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
}
}
+/*
+ * Calculate and return an offset that is the lesser of the current
+ * bp.offset and the maximum possible offset before geometry
+ * collisions happen.
+ * Currently this is a quick and dirty estimate of the max
+ * possible: half the minimum edge length of any vertex involved
+ * in a bevel. This is usually conservative.
+ * The correct calculation is quite complicated.
+ * TODO: implement this correctly.
+ */
+static float bevel_limit_offset(BMesh *bm, BevelParams *bp)
+{
+ BMVert *v;
+ BMEdge *e;
+ BMIter v_iter, e_iter;
+ float limited_offset, half_elen;
+ bool vbeveled;
+
+ limited_offset = bp->offset;
+ BM_ITER_MESH(v, &v_iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ if (bp->vertex_only) {
+ vbeveled = true;
+ }
+ else {
+ vbeveled = false;
+ BM_ITER_ELEM(e, &e_iter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(BM_edge_other_vert(e, v), BM_ELEM_TAG)) {
+ vbeveled = true;
+ break;
+ }
+ }
+ }
+ if (vbeveled) {
+ BM_ITER_ELEM(e, &e_iter, v, BM_EDGES_OF_VERT) {
+ half_elen = 0.5f * BM_edge_calc_length(e);
+ if (half_elen < limited_offset)
+ limited_offset = half_elen;
+ }
+ }
+ }
+ }
+ return limited_offset;
+}
+
/**
* - Currently only bevels BM_ELEM_TAG'd verts and edges.
*
@@ -1781,9 +2104,14 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
* the caller needs to ensure this is cleared before calling
* if its going to use this face tag.
*
+ * - If limit_offset is set, adjusts offset down if necessary
+ * to avoid geometry collisions.
+ *
* \warning all tagged edges _must_ be manifold.
*/
-void BM_mesh_bevel(BMesh *bm, const float offset, const float segments)
+void BM_mesh_bevel(BMesh *bm, const float offset, const float segments,
+ const bool vertex_only, const bool use_weights, const bool limit_offset,
+ const struct MDeformVert *dvert, const int vertex_group)
{
BMIter iter;
BMVert *v;
@@ -1792,6 +2120,10 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments)
bp.offset = offset;
bp.seg = segments;
+ bp.vertex_only = vertex_only;
+ bp.use_weights = use_weights;
+ bp.dvert = dvert;
+ bp.vertex_group = vertex_group;
if (bp.offset > 0) {
/* primary alloc */
@@ -1799,6 +2131,9 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments)
bp.mem_arena = BLI_memarena_new((1 << 16), __func__);
BLI_memarena_use_calloc(bp.mem_arena);
+ if (limit_offset)
+ bp.offset = bevel_limit_offset(bm, &bp);
+
/* The analysis of the input vertices and execution additional constructions */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
@@ -1807,9 +2142,11 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments)
}
/* Build polygons for edges */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- bevel_build_edge_polygons(bm, &bp, e);
+ if (!bp.vertex_only) {
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ bevel_build_edge_polygons(bm, &bp, e);
+ }
}
}
diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h
index a80e4f3a4a2..bee26357aca 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.h
+++ b/source/blender/bmesh/tools/bmesh_bevel.h
@@ -27,6 +27,10 @@
* \ingroup bmesh
*/
-void BM_mesh_bevel(BMesh *bm, const float offset, const float segments);
+struct MDeformVert;
+
+void BM_mesh_bevel(BMesh *bm, const float offset, const float segments,
+ const bool vertex_only, const bool use_weights, const bool limit_offset,
+ const struct MDeformVert *dvert, const int vertex_group);
#endif /* __BMESH_BEVEL_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_decimate.h b/source/blender/bmesh/tools/bmesh_decimate.h
index 4a557c20ae3..d3eaf1c6670 100644
--- a/source/blender/bmesh/tools/bmesh_decimate.h
+++ b/source/blender/bmesh/tools/bmesh_decimate.h
@@ -27,15 +27,15 @@
* \ingroup bmesh
*/
-void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const int do_triangulate);
+void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const bool do_triangulate);
-void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int tag_only);
+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 int do_dissolve_boundaries,
+void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
BMVert **vinput_arr, const int vinput_len,
BMEdge **einput_arr, const int einput_len);
-void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries);
+void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries);
/* these weights are accumulated so too high values may reach 'inf' too quickly */
#define BM_MESH_DECIM_WEIGHT_MAX 100000.0f
diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
index 7c054d84405..e94bb9f5417 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
@@ -134,7 +134,7 @@ static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3],
}
}
-static int bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_co[3])
+static bool bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_co[3])
{
BMIter liter;
BMLoop *l;
@@ -172,16 +172,16 @@ static int bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_c
#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)*/
+ * (first making it zero area, then flipping again) */
if (dot_v3v3(cross_exist, cross_optim) <= FLT_EPSILON) {
//printf("no flip\n");
- return TRUE;
+ return true;
}
}
}
}
- return FALSE;
+ return false;
}
static void bm_decim_build_edge_cost_single(BMEdge *e,
@@ -291,15 +291,15 @@ static void bm_decim_build_edge_cost(BMesh *bm,
* collapsing edges so even has some advantage over decimating quads
* directly.
*
- * \return TRUE if any faces were triangulated.
+ * \return true if any faces were triangulated.
*/
-static int bm_decim_triangulate_begin(BMesh *bm)
+static bool bm_decim_triangulate_begin(BMesh *bm)
{
BMIter iter;
BMFace *f;
- // int has_quad; // could optimize this a little
- int has_cut = FALSE;
+ // bool has_quad; // could optimize this a little
+ bool has_cut = false;
BLI_assert((bm->elem_index_dirty & BM_VERT) == 0);
@@ -345,7 +345,7 @@ static int bm_decim_triangulate_begin(BMesh *bm)
}
#ifdef USE_SAFETY_CHECKS
- if (BM_edge_exists(l_a->v, l_b->v) == FALSE)
+ if (BM_edge_exists(l_a->v, l_b->v) == false)
#endif
{
BMFace *f_new;
@@ -355,7 +355,7 @@ static int bm_decim_triangulate_begin(BMesh *bm)
* - if there is a quad that has a free standing edge joining it along
* where we want to split the face, there isnt a good way we can handle this.
* currently that edge will get removed when joining the tris back into a quad. */
- f_new = BM_face_split(bm, f, l_a->v, l_b->v, &l_new, NULL, FALSE);
+ f_new = BM_face_split(bm, f, l_a->v, l_b->v, &l_new, NULL, false);
if (f_new) {
/* the value of this doesn't matter, only that the 2 loops match and have unique values */
@@ -370,7 +370,7 @@ static int bm_decim_triangulate_begin(BMesh *bm)
BM_face_normal_update(f);
BM_face_normal_update(f_new);
- has_cut = TRUE;
+ has_cut = true;
}
}
}
@@ -410,15 +410,15 @@ static void bm_decim_triangulate_end(BMesh *bm)
BM_vert_in_edge(e, l_b->next->v) ? l_b->prev->v : l_b->next->v,
};
- BLI_assert(ELEM3(vquad[0], vquad[1], vquad[2], vquad[3]) == FALSE);
- BLI_assert(ELEM3(vquad[1], vquad[0], vquad[2], vquad[3]) == FALSE);
- BLI_assert(ELEM3(vquad[2], vquad[1], vquad[0], vquad[3]) == FALSE);
- BLI_assert(ELEM3(vquad[3], vquad[1], vquad[2], vquad[0]) == FALSE);
+ BLI_assert(ELEM3(vquad[0], vquad[1], vquad[2], vquad[3]) == false);
+ BLI_assert(ELEM3(vquad[1], vquad[0], vquad[2], vquad[3]) == false);
+ BLI_assert(ELEM3(vquad[2], vquad[1], vquad[0], vquad[3]) == false);
+ BLI_assert(ELEM3(vquad[3], vquad[1], vquad[2], vquad[0]) == false);
if (is_quad_convex_v3(vquad[0]->co, vquad[1]->co, vquad[2]->co, vquad[3]->co)) {
/* highly unlikely to fail, but prevents possible double-ups */
BMFace *f[2] = {l_a->f, l_b->f};
- BM_faces_join(bm, f, 2, TRUE);
+ BM_faces_join(bm, f, 2, true);
}
}
}
@@ -441,9 +441,11 @@ static void bm_decim_triangulate_end(BMesh *bm)
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
/* these don't need to be updated, since they will get removed when the edge collapses */
BMLoop *l_clear, *l_other;
- const int is_manifold = BM_edge_is_manifold(l->e);
+ const bool is_manifold = BM_edge_is_manifold(l->e);
int side;
/* l defines the vert to collapse into */
@@ -464,7 +466,9 @@ static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_cle
/* now we have both corners of the face 'l->f' */
for (side = 0; side < 2; side++) {
- int is_seam = FALSE;
+#ifdef USE_SEAM
+ bool is_seam = false;
+#endif
void *src[2];
BMFace *f_exit = is_manifold ? l->radial_next->f : NULL;
BMEdge *e_prev = l->e;
@@ -501,34 +505,40 @@ static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_cle
break;
}
+#ifdef USE_SEAM
/* break out unless we find a match */
- is_seam = TRUE;
+ is_seam = true;
+#endif
/* ok. we have a loop. now be smart with it! */
for (i = 0; i < bm->ldata.totlayer; i++) {
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, *cd_iter;
-
- /* todo, make nicer macros for this */
- cd_src = (char *)src[0] + offset;
- // cd_dst = (char *)src[1] + offset; // UNUSED
- cd_iter = (char *)l_iter->head.data + offset;
+ void *cd_src[2] = {(char *)src[0] + offset,
+ (char *)src[1] + offset};
+ void *cd_iter = (char *)l_iter->head.data + offset;
/* detect seams */
- if (CustomData_data_equals(type, cd_src, cd_iter)) {
- CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_iter->head.data);
- is_seam = FALSE;
+ 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);
+#ifdef USE_SEAM
+ is_seam = false;
+#endif
}
}
}
+#ifdef USE_SEAM
if (is_seam) {
break;
}
+#endif
}
}
+
+//#undef USE_SEAM
+
}
#endif /* USE_CUSTOMDATA */
@@ -588,7 +598,7 @@ BLI_INLINE int bm_edge_is_manifold_or_boundary(BMLoop *l)
#endif
}
-static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first)
+static bool bm_edge_collapse_is_degenerate_topology(BMEdge *e_first)
{
/* simply check that there is no overlap between faces and edges of each vert,
* (excluding the 2 faces attached to 'e' and 'e' its self) */
@@ -599,7 +609,7 @@ static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first)
e_iter = e_first;
do {
if (!bm_edge_is_manifold_or_boundary(e_iter->l)) {
- return TRUE;
+ return true;
}
bm_edge_tag_disable(e_iter);
} while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v1)) != e_first);
@@ -607,7 +617,7 @@ static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first)
e_iter = e_first;
do {
if (!bm_edge_is_manifold_or_boundary(e_iter->l)) {
- return TRUE;
+ return true;
}
bm_edge_tag_disable(e_iter);
} while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first);
@@ -663,11 +673,11 @@ static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first)
e_iter = e_first;
do {
if (bm_edge_tag_test(e_iter)) {
- return TRUE;
+ return true;
}
} while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first);
- return FALSE;
+ return false;
}
/**
@@ -680,13 +690,13 @@ static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first)
* \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')
*/
-static int 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
)
{
@@ -698,11 +708,11 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e
if (BM_edge_is_manifold(e_clear)) {
BMLoop *l_a, *l_b;
BMEdge *e_a_other[2], *e_b_other[2];
- int ok;
+ bool ok;
ok = BM_edge_loop_pair(e_clear, &l_a, &l_b);
- BLI_assert(ok == TRUE);
+ BLI_assert(ok == true);
BLI_assert(l_a->f->len == 3);
BLI_assert(l_b->f->len == 3);
@@ -739,7 +749,7 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e
if (ELEM(e_a_other[0], e_b_other[0], e_b_other[1]) ||
ELEM(e_a_other[1], e_b_other[0], e_b_other[1]))
{
- return FALSE;
+ return false;
}
r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]);
@@ -772,7 +782,7 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e
// BM_mesh_validate(bm);
- return TRUE;
+ return true;
}
else if (BM_edge_is_boundary(e_clear)) {
/* same as above but only one triangle */
@@ -819,10 +829,10 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e
// BM_mesh_validate(bm);
- return TRUE;
+ return true;
}
else {
- return FALSE;
+ return false;
}
}
@@ -859,7 +869,7 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e,
}
/* use for customdata merging */
- if (LIKELY(compare_v3v3(e->v1->co, e->v2->co, FLT_EPSILON) == FALSE)) {
+ if (LIKELY(compare_v3v3(e->v1->co, e->v2->co, FLT_EPSILON) == false)) {
customdata_fac = line_point_factor_v3(optimize_co, e->v1->co, e->v2->co);
#if 0
/* simple test for stupid collapse */
@@ -936,7 +946,7 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e,
else
e_outer = l->prev->e;
- BLI_assert(BM_vert_in_edge(e_outer, l->v) == FALSE);
+ BLI_assert(BM_vert_in_edge(e_outer, l->v) == false);
bm_decim_build_edge_cost_single(e_outer, vquadrics, vweights, eheap, eheap_table);
}
@@ -962,14 +972,14 @@ 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 int do_triangulate)
+void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const bool do_triangulate)
{
Heap *eheap; /* edge heap */
HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */
Quadric *vquadrics; /* vert index aligned quadrics */
int tot_edge_orig;
int face_tot_target;
- int use_triangulate;
+ bool use_triangulate;
CD_UseFlag customdata_flag = 0;
@@ -1005,7 +1015,7 @@ void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, c
/* iterative edge collapse and maintain the eheap */
while ((bm->totface > face_tot_target) &&
- (BLI_heap_is_empty(eheap) == FALSE) &&
+ (BLI_heap_is_empty(eheap) == false) &&
(BLI_heap_node_value(BLI_heap_top(eheap)) != COST_INVALID))
{
// const float value = BLI_heap_node_value(BLI_heap_top(eheap));
@@ -1023,7 +1033,7 @@ void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, c
#ifdef USE_TRIANGULATE
- if (do_triangulate == FALSE) {
+ if (do_triangulate == false) {
/* its possible we only had triangles, skip this step in that case */
if (LIKELY(use_triangulate)) {
/* temp convert quads to triangles */
diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
index f67f01e4585..a5122b242be 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
@@ -69,7 +69,7 @@ static int dissolve_elem_cmp(const void *a1, const void *a2)
return 0;
}
-void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries,
+void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
BMVert **vinput_arr, const int vinput_len,
BMEdge **einput_arr, const int einput_len)
{
@@ -114,14 +114,14 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int
/* check twice because cumulative effect could dissolve over angle limit */
(BM_edge_calc_face_angle(e) < angle_limit))
{
- BMFace *nf = BM_faces_join_pair(bm, e->l->f,
- e->l->radial_next->f,
- e,
- FALSE); /* join faces */
+ BMFace *f_new = BM_faces_join_pair(bm, e->l->f,
+ e->l->radial_next->f,
+ e,
+ false); /* join faces */
/* there may be some errors, we don't mind, just move on */
- if (nf) {
- BM_face_normal_update(nf);
+ if (f_new) {
+ BM_face_normal_update(f_new);
}
else {
BMO_error_clear(bm);
@@ -148,7 +148,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int
for (i = bm->totedge - 1; i != -1; i--) {
e_iter = earray[i];
- if (BM_edge_is_wire(e_iter) && (BM_elem_flag_test(e_iter, BM_ELEM_TAG) == FALSE)) {
+ if (BM_edge_is_wire(e_iter) && (BM_elem_flag_test(e_iter, BM_ELEM_TAG) == false)) {
/* edge has become wire */
int vidx_reverse;
BMVert *v1 = e_iter->v1;
@@ -179,7 +179,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int
if (LIKELY(v != NULL) &&
BM_vert_edge_count(v) == 2)
{
- BM_vert_collapse_edge(bm, v->e, v, TRUE); /* join edges */
+ BM_vert_collapse_edge(bm, v->e, v, true); /* join edges */
}
}
}
@@ -210,10 +210,10 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int
/* check twice because cumulative effect could dissolve over angle limit */
bm_vert_edge_face_angle(v) < angle_limit)
{
- BMEdge *ne = BM_vert_collapse_edge(bm, v->e, v, TRUE); /* join edges */
+ BMEdge *e_new = BM_vert_collapse_edge(bm, v->e, v, true); /* join edges */
- if (ne && ne->l) {
- BM_edge_normals_update(ne);
+ if (e_new && e_new->l) {
+ BM_edge_normals_update(e_new);
}
}
}
@@ -223,7 +223,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int
MEM_freeN(weight_elems);
}
-void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries)
+void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries)
{
int vinput_len;
int einput_len;
diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
index acdab2510a4..c48e83686b5 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
@@ -36,7 +36,7 @@
#include "intern/bmesh_operators_private.h" /* own include */
-static int bm_vert_dissolve_fan_test(BMVert *v)
+static bool bm_vert_dissolve_fan_test(BMVert *v)
{
/* check if we should walk over these verts */
BMIter iter;
@@ -61,21 +61,21 @@ static int bm_vert_dissolve_fan_test(BMVert *v)
}
if ((tot_edge == 4) && (tot_edge_boundary == 0) && (tot_edge_manifold == 4)) {
- return TRUE;
+ return true;
}
else if ((tot_edge == 3) && (tot_edge_boundary == 0) && (tot_edge_manifold == 3)) {
- return TRUE;
+ return true;
}
else if ((tot_edge == 3) && (tot_edge_boundary == 2) && (tot_edge_manifold == 1)) {
- return TRUE;
+ return true;
}
else if ((tot_edge == 2) && (tot_edge_wire == 2)) {
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
-static int bm_vert_dissolve_fan(BMesh *bm, BMVert *v)
+static bool bm_vert_dissolve_fan(BMesh *bm, BMVert *v)
{
/* collapse under 2 conditions.
* - vert connects to 4 manifold edges (and 4 faces).
@@ -110,7 +110,7 @@ static int bm_vert_dissolve_fan(BMesh *bm, BMVert *v)
if (tot_edge == 2) {
/* check for 2 wire verts only */
if (tot_edge_wire == 2) {
- return (BM_vert_collapse_edge(bm, v->e, v, TRUE) != NULL);
+ return (BM_vert_collapse_edge(bm, v->e, v, true) != NULL);
}
}
else if (tot_edge == 4) {
@@ -145,7 +145,7 @@ static int bm_vert_dissolve_fan(BMesh *bm, BMVert *v)
if (l->f->len > 3) {
BMLoop *l_new;
BLI_assert(l->prev->v != l->next->v);
- BM_face_split(bm, l->f, l->prev->v, l->next->v, &l_new, NULL, TRUE);
+ BM_face_split(bm, l->f, l->prev->v, l->next->v, &l_new, NULL, true);
BM_elem_flag_merge_into(l_new->e, l->e, l->prev->e);
}
}
@@ -153,7 +153,7 @@ static int bm_vert_dissolve_fan(BMesh *bm, BMVert *v)
return BM_vert_dissolve(bm, v);
}
- return FALSE;
+ return false;
}
enum {
@@ -170,7 +170,7 @@ enum {
/**
* \param tag_only so we can call this from an operator */
-void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int tag_only)
+void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool tag_only)
{
#ifdef USE_WALKER
# define ELE_VERT_TAG 1
@@ -181,7 +181,6 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int
unsigned vert_seek_b_tot = 0;
#endif
- BMVert *v;
BMIter iter;
const unsigned int offset = 0;
@@ -189,16 +188,18 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int
int iter_step;
- /* if tag_only is set, we assyme the caller knows what verts to tag
+ /* if tag_only is set, we assume the caller knows what verts to tag
* needed for the operator */
- if (tag_only == FALSE) {
+ if (tag_only == false) {
+ BMVert *v;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
BM_elem_flag_enable(v, BM_ELEM_TAG);
}
}
for (iter_step = 0; iter_step < iterations; iter_step++) {
- int iter_done;
+ BMVert *v;
+ bool iter_done;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG) && bm_vert_dissolve_fan_test(v)) {
@@ -215,7 +216,7 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int
/* main loop, keep tagging until we can't tag any more islands */
- while (TRUE) {
+ while (true) {
#ifdef USE_WALKER
BMWalker walker;
#else
@@ -223,7 +224,6 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int
unsigned int i;
#endif
BMVert *v_first = NULL;
- BMVert *v;
/* we could avoid iterating from the start each time */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
@@ -268,12 +268,12 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int
BMW_end(&walker);
#else
- BM_elem_index_set(v_first, (offset + depth) % nth ? VERT_INDEX_IGNORE : VERT_INDEX_DO_COLLAPSE); /* set_dirty! */
+ BM_elem_index_set(v_first, ((offset + depth) % nth) ? VERT_INDEX_IGNORE : VERT_INDEX_DO_COLLAPSE); /* set_dirty! */
vert_seek_b_tot = 0;
vert_seek_b[vert_seek_b_tot++] = v_first;
- while (TRUE) {
+ while (true) {
BMEdge *e;
if ((offset + depth) % nth) {
@@ -318,14 +318,16 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int
}
/* now we tagged all verts -1 for removal, lets loop over and rebuild faces */
- iter_done = FALSE;
+ iter_done = false;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE) {
- iter_done |= bm_vert_dissolve_fan(bm, v);
+ if (bm_vert_dissolve_fan(bm, v)) {
+ iter_done = true;
+ }
}
}
- if (iter_done == FALSE) {
+ if (iter_done == false) {
break;
}
}
@@ -340,5 +342,5 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int
void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations)
{
- BM_mesh_decimate_unsubdivide_ex(bm, iterations, FALSE);
+ BM_mesh_decimate_unsubdivide_ex(bm, iterations, false);
}
diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c
new file mode 100644
index 00000000000..3ae5c712f0a
--- /dev/null
+++ b/source/blender/bmesh/tools/bmesh_edgesplit.c
@@ -0,0 +1,170 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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/tools/bmesh_edgesplit.c
+ * \ingroup bmesh
+ *
+ * Edge-Split.
+ *
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
+#include "bmesh.h"
+
+#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
+ */
+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)
+{
+ BMIter iter;
+ BMEdge *e;
+
+
+ if (tag_only == false) {
+ BM_mesh_elem_hflag_enable_all(bm, BM_EDGE | (use_verts ? BM_VERT : 0), BM_ELEM_TAG, false);
+ }
+
+ if (use_verts) {
+ /* prevent one edge having both verts unflagged
+ * we could alternately disable these edges, either way its a corner case.
+ *
+ * This is needed so we don't split off the edge but then none of its verts which
+ * would leave a duplicate edge.
+ */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ if (UNLIKELY(((BM_elem_flag_test(e->v1, BM_ELEM_TAG) == false) &&
+ (BM_elem_flag_test(e->v2, BM_ELEM_TAG) == false))))
+ {
+ BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
+ }
+ }
+ }
+ }
+
+ 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 */
+ do {
+ bmesh_edge_separate(bm, e, e->l);
+ } while (!BM_edge_is_boundary(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)) {
+ if (BM_elem_flag_test(e->v1, BM_ELEM_TAG)) {
+ BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
+ bmesh_vert_separate(bm, e->v1, NULL, NULL);
+ }
+ if (BM_elem_flag_test(e->v2, BM_ELEM_TAG)) {
+ BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
+ bmesh_vert_separate(bm, e->v2, NULL, NULL);
+ }
+ }
+ }
+}
diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.h b/source/blender/bmesh/tools/bmesh_edgesplit.h
new file mode 100644
index 00000000000..8c1231dd794
--- /dev/null
+++ b/source/blender/bmesh/tools/bmesh_edgesplit.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):
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BMESH_EDGESPLIT_H__
+#define __BMESH_EDGESPLIT_H__
+
+/** \file blender/bmesh/tools/bmesh_edgesplit.h
+ * \ingroup bmesh
+ */
+
+void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only);
+
+#endif /* __BMESH_EDGESPLIT_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_triangulate.c b/source/blender/bmesh/tools/bmesh_triangulate.c
new file mode 100644
index 00000000000..79f6c76afc7
--- /dev/null
+++ b/source/blender/bmesh/tools/bmesh_triangulate.c
@@ -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.
+ *
+ * Contributor(s): Joseph Eagar
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/tools/bmesh_triangulate.c
+ * \ingroup bmesh
+ *
+ * Triangulate.
+ *
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_array.h"
+
+#include "bmesh.h"
+
+#include "bmesh_triangulate.h" /* own include */
+
+/**
+ * a version of #BM_face_triangulate that maps to #BMOpSlot
+ */
+static void bm_face_triangulate_mapping(BMesh *bm, BMFace *face, const bool use_beauty, const bool use_tag,
+ BMOperator *op, BMOpSlot *slot_facemap_out)
+{
+ const 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, use_beauty, use_tag);
+
+ if (faces_array) {
+ int i;
+ BMO_slot_map_elem_insert(op, slot_facemap_out, face, face);
+ for (i = 0; i < faces_array_tot; i++) {
+ BMO_slot_map_elem_insert(op, slot_facemap_out, faces_array[i], face);
+ }
+ }
+}
+
+
+void BM_mesh_triangulate(BMesh *bm, const bool use_beauty, const bool tag_only,
+ BMOperator *op, BMOpSlot *slot_facemap_out)
+{
+ BMIter iter;
+ BMFace *face;
+
+ 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, use_beauty, tag_only,
+ op, slot_facemap_out);
+ }
+ }
+ }
+ }
+ else {
+ 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, use_beauty, tag_only);
+ }
+ }
+ }
+ }
+}
diff --git a/source/blender/bmesh/tools/bmesh_triangulate.h b/source/blender/bmesh/tools/bmesh_triangulate.h
new file mode 100644
index 00000000000..936a90d3a16
--- /dev/null
+++ b/source/blender/bmesh/tools/bmesh_triangulate.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.
+ *
+ * Contributor(s): Joseph Eagar
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/tools/bmesh_triangulate.h
+ * \ingroup bmesh
+ *
+ * Triangulate.
+ *
+ */
+
+#ifndef __BMESH_TRIAMGULATE_H__
+#define __BMESH_TRIAMGULATE_H__
+
+void BM_mesh_triangulate(BMesh *bm, const bool use_beauty, const bool tag_only,
+ BMOperator *op, BMOpSlot *slot_facemap_out);
+
+#endif /* __BMESH_TRIAMGULATE_H__ */
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp
index 26b5edf7ea6..89bcebc41d6 100644
--- a/source/blender/collada/AnimationExporter.cpp
+++ b/source/blender/collada/AnimationExporter.cpp
@@ -24,6 +24,8 @@
#include "AnimationExporter.h"
#include "MaterialExporter.h"
+Global G;
+
template<class Functor>
void forEachObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set)
{
@@ -34,9 +36,10 @@ void forEachObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set)
}
}
-void AnimationExporter::exportAnimations(Scene *sce)
+bool AnimationExporter::exportAnimations(Scene *sce)
{
- if (hasAnimations(sce)) {
+ bool has_animations = hasAnimations(sce);
+ if (has_animations) {
this->scene = sce;
openLibrary();
@@ -45,6 +48,7 @@ void AnimationExporter::exportAnimations(Scene *sce)
closeLibrary();
}
+ return has_animations;
}
// called for each exported object
@@ -83,6 +87,11 @@ void AnimationExporter::operator()(Object *ob)
}
+ export_object_constraint_animation(ob);
+
+ //This needs to be handled by extra profiles, so postponed for now
+ //export_morph_animation(ob);
+
//Export Lamp parameter animations
if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action) {
fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
@@ -134,7 +143,69 @@ void AnimationExporter::operator()(Object *ob)
fcu = fcu->next;
}
}
+ }
+
+
+}
+
+void AnimationExporter::export_object_constraint_animation(Object *ob)
+{
+ std::vector<float> fra;
+ //Takes frames of target animations
+ make_anim_frames_from_targets(ob, fra);
+
+ if (fra.size())
+ dae_baked_object_animation(fra, ob);
+}
+
+void AnimationExporter::export_morph_animation(Object *ob)
+{
+ FCurve *fcu;
+ char *transformName;
+ Key *key = BKE_key_from_object(ob);
+ if (!key) return;
+
+ if (key->adt && key->adt->action) {
+ fcu = (FCurve *)key->adt->action->curves.first;
+
+ while (fcu) {
+ transformName = extract_transform_name(fcu->rna_path);
+
+ dae_animation(ob, fcu, transformName, true);
+
+ fcu = fcu->next;
+ }
+ }
+
+}
+void AnimationExporter::make_anim_frames_from_targets(Object *ob, std::vector<float> &frames )
+{
+ ListBase *conlist = get_active_constraints(ob);
+ if (conlist == NULL) return;
+ bConstraint *con;
+ for (con = (bConstraint *)conlist->first; con; con = con->next) {
+ ListBase targets = {NULL, NULL};
+
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
+
+ if (!validateConstraints(con)) continue;
+
+ if (cti && cti->get_constraint_targets) {
+ bConstraintTarget *ct;
+ Object *obtar;
+ /* get targets
+ * - constraints should use ct->matrix, not directly accessing values
+ * - ct->matrix members have not yet been calculated here!
+ */
+ cti->get_constraint_targets(con, &targets);
+ if (cti) {
+ for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
+ obtar = ct->tar;
+ find_frames(obtar, frames);
+ }
+ }
+ }
}
}
@@ -188,6 +259,12 @@ std::string AnimationExporter::getObjectBoneName(Object *ob, const FCurve *fcu)
return id_name(ob);
}
+std::string AnimationExporter::getAnimationPathId(const FCurve *fcu)
+{
+ std::string rna_path = std::string(fcu->rna_path);
+ return translate_id(rna_path);
+}
+
//convert f-curves to animation curves and write
void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma)
{
@@ -205,8 +282,8 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
//axis names for colors
else if (!strcmp(transformName, "color") ||
- !strcmp(transformName, "specular_color") ||
- !strcmp(transformName, "diffuse_color") ||
+ !strcmp(transformName, "specular_color") ||
+ !strcmp(transformName, "diffuse_color") ||
!strcmp(transformName, "alpha"))
{
const char *axis_names[] = {"R", "G", "B"};
@@ -216,9 +293,9 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
//axis names for transforms
else if (!strcmp(transformName, "location") ||
- !strcmp(transformName, "scale") ||
+ !strcmp(transformName, "scale") ||
!strcmp(transformName, "rotation_euler") ||
- !strcmp(transformName, "rotation_quaternion"))
+ !strcmp(transformName, "rotation_quaternion"))
{
const char *axis_names[] = {"X", "Y", "Z"};
if (fcu->array_index < 3)
@@ -234,16 +311,27 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
//Create anim Id
if (ob->type == OB_ARMATURE) {
ob_name = getObjectBoneName(ob, fcu);
- BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s.%s", (char *)translate_id(ob_name).c_str(),
- transformName, axis_name);
+ BLI_snprintf(
+ anim_id,
+ sizeof(anim_id),
+ "%s_%s.%s",
+ (char *)translate_id(ob_name).c_str(),
+ (char *)translate_id(transformName).c_str(),
+ axis_name);
}
else {
if (ma)
ob_name = id_name(ob) + "_material";
else
ob_name = id_name(ob);
- BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(),
- fcu->rna_path, axis_name);
+
+ BLI_snprintf(
+ anim_id,
+ sizeof(anim_id),
+ "%s_%s_%s",
+ (char *)translate_id(ob_name).c_str(),
+ (char *)getAnimationPathId(fcu).c_str(),
+ axis_name);
}
openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
@@ -320,6 +408,9 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
if (ma)
target = translate_id(id_name(ma)) + "-effect" +
"/common/" /*profile common is only supported */ + get_transform_sid(fcu->rna_path, -1, axis_name, true);
+ //if shape key animation, this is the main problem, how to define the channel targets.
+ /*target = get_morph_id(ob) +
+ "/value" +*/
}
addChannel(COLLADABU::URI(empty, sampler_id), target);
@@ -367,7 +458,10 @@ void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, B
std::vector<float> fra;
//char prefix[256];
- FCurve *fcu = (FCurve *)ob_arm->adt->action->curves.first;
+ //Check if there is a fcurve in the armature for the bone in param
+ //when baking this check is not needed, solve every bone for every frame.
+ /*FCurve *fcu = (FCurve *)ob_arm->adt->action->curves.first;
+
while (fcu) {
std::string bone_name = getObjectBoneName(ob_arm, fcu);
int val = BLI_strcasecmp((char *)bone_name.c_str(), bone->name);
@@ -375,11 +469,13 @@ void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, B
fcu = fcu->next;
}
- if (!(fcu)) return;
+ if (!(fcu)) return;*/
+
bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
if (!pchan)
return;
+ //every inserted keyframe of bones.
find_frames(ob_arm, fra);
if (flag & ARM_RESTPOS) {
@@ -415,7 +511,8 @@ void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_
// create output source
std::string output_id;
- output_id = create_4x4_source(fra, ob_arm, bone, anim_id);
+
+ output_id = create_4x4_source(fra, ob_arm, bone, anim_id);
// create interpolations source
std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
@@ -439,6 +536,48 @@ void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_
closeAnimation();
}
+void AnimationExporter::dae_baked_object_animation(std::vector<float> &fra, Object *ob)
+{
+ std::string ob_name = id_name(ob);
+ char anim_id[200];
+
+ if (!fra.size())
+ return;
+
+ BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s", (char *)translate_id(ob_name).c_str(),
+ "object_matrix");
+
+ openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
+
+ // create input source
+ std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, "");
+
+ // create output source
+ std::string output_id;
+ output_id = create_4x4_source( fra, ob, NULL, anim_id);
+
+ // create interpolations source
+ std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
+
+ std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
+ COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
+ std::string empty;
+ sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
+ sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
+
+ // TODO create in/out tangents source
+
+ // this input is required
+ sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
+
+ addSampler(sampler);
+
+ std::string target = translate_id(ob_name) + "/transform";
+ addChannel(COLLADABU::URI(empty, sampler_id), target);
+
+ closeAnimation();
+}
+
// dae_bone_animation -> add_bone_animation
// (blend this into dae_bone_animation)
void AnimationExporter::dae_bone_animation(std::vector<float> &fra, float *values, int tm_type, int axis, std::string ob_name, std::string bone_name)
@@ -610,7 +749,6 @@ void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSeman
values[1] = bezt->vec[2][1];
}
break;
- break;
default:
*length = 0;
break;
@@ -762,7 +900,8 @@ std::string AnimationExporter::create_source_from_vector(COLLADASW::InputSemanti
return source_id;
}
-std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object *ob_arm, Bone *bone, const std::string& anim_id)
+
+std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object *ob, Bone *bone, const std::string &anim_id)
{
COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
std::string source_id = anim_id + get_semantic_suffix(semantic);
@@ -780,71 +919,90 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
bPoseChannel *parchan = NULL;
bPoseChannel *pchan = NULL;
- bPose *pose = ob_arm->pose;
-
- pchan = BKE_pose_channel_find_name(pose, bone->name);
- if (!pchan)
- return "";
+ if (ob->type == OB_ARMATURE ) {
+ bPose *pose = ob->pose;
+ pchan = BKE_pose_channel_find_name(pose, bone->name);
+ if (!pchan)
+ return "";
- parchan = pchan->parent;
-
- enable_fcurves(ob_arm->adt->action, bone->name);
+ parchan = pchan->parent;
+ enable_fcurves(ob->adt->action, bone->name);
+ }
+
std::vector<float>::iterator it;
int j = 0;
for (it = frames.begin(); it != frames.end(); it++) {
float mat[4][4], ipar[4][4];
float ctime = BKE_scene_frame_get_from_ctime(scene, *it);
-
- BKE_animsys_evaluate_animdata(scene, &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
- BKE_pose_where_is_bone(scene, ob_arm, pchan, ctime, 1);
-
- // compute bone local mat
- if (bone->parent) {
- invert_m4_m4(ipar, parchan->pose_mat);
- mult_m4_m4m4(mat, ipar, pchan->pose_mat);
- }
- else
- copy_m4_m4(mat, pchan->pose_mat);
- UnitConverter converter;
-
+ CFRA = BKE_scene_frame_get_from_ctime(scene, *it);
+ //BKE_scene_update_for_newframe(G.main,scene,scene->lay);
+ BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
+
+ if (bone) {
+ if (pchan->flag & POSE_CHAIN) {
+ enable_fcurves(ob->adt->action, NULL);
+ BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
+ BKE_pose_where_is(scene, ob);
+ }
+ else {
+ BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
+ }
+
+ // compute bone local mat
+ if (bone->parent) {
+ invert_m4_m4(ipar, parchan->pose_mat);
+ mult_m4_m4m4(mat, ipar, pchan->pose_mat);
+ }
+ else
+ copy_m4_m4(mat, pchan->pose_mat);
+
// SECOND_LIFE_COMPATIBILITY
// AFAIK animation to second life is via BVH, but no
// reason to not have the collada-animation be correct
- if (export_settings->second_life) {
- float temp[4][4];
- copy_m4_m4(temp, bone->arm_mat);
- temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
- invert_m4(temp);
+ if (export_settings->second_life) {
+ float temp[4][4];
+ copy_m4_m4(temp, bone->arm_mat);
+ temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+ invert_m4(temp);
- mult_m4_m4m4(mat, mat, temp);
+ mult_m4_m4m4(mat, mat, temp);
- if (bone->parent) {
- copy_m4_m4(temp, bone->parent->arm_mat);
- temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+ if (bone->parent) {
+ copy_m4_m4(temp, bone->parent->arm_mat);
+ temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
- mult_m4_m4m4(mat, temp, mat);
+ mult_m4_m4m4(mat, temp, mat);
+ }
}
- }
- float outmat[4][4];
- converter.mat4_to_dae(outmat, mat);
+ }
+ else {
+ calc_ob_mat_at_time(ob, ctime, mat);
+ }
+
+ UnitConverter converter;
+ double outmat[4][4];
+ converter.mat4_to_dae_double(outmat, mat);
source.appendValues(outmat);
-
j++;
+
+ BIK_release_tree(scene, ob, ctime);
}
- enable_fcurves(ob_arm->adt->action, NULL);
+ enable_fcurves(ob->adt->action, NULL);
source.finish();
return source_id;
}
+
+
// only used for sources with OUTPUT semantic ( locations and scale)
std::string AnimationExporter::create_xyz_source(float *v, int tot, const std::string& anim_id)
{
@@ -1184,6 +1342,12 @@ bool AnimationExporter::hasAnimations(Scene *sce)
}
}
+ //check shape key animation
+ if (!fcu) {
+ Key *key = BKE_key_from_object(ob);
+ if (key && key->adt && key->adt->action)
+ fcu = (FCurve *)key->adt->action->curves.first;
+ }
if (fcu)
return true;
}
@@ -1351,3 +1515,43 @@ void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, i
enable_fcurves(ob_arm->adt->action, NULL);
}
+
+bool AnimationExporter::validateConstraints(bConstraint *con)
+{
+ bool valid = true;
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
+ /* these we can skip completely (invalid constraints...) */
+ if (cti == NULL) valid = false;
+ if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) valid = false;
+ /* these constraints can't be evaluated anyway */
+ if (cti->evaluate_constraint == NULL) valid = false;
+ /* influence == 0 should be ignored */
+ if (con->enforce == 0.0f) valid = false;
+
+ return valid;
+}
+
+void AnimationExporter::calc_ob_mat_at_time(Object *ob, float ctime , float mat[][4])
+{
+ ListBase *conlist = get_active_constraints(ob);
+ bConstraint *con;
+ for (con = (bConstraint *)conlist->first; con; con = con->next) {
+ ListBase targets = {NULL, NULL};
+
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
+
+ if (cti && cti->get_constraint_targets) {
+ bConstraintTarget *ct;
+ Object *obtar;
+ cti->get_constraint_targets(con, &targets);
+ for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
+ obtar = ct->tar;
+ BKE_animsys_evaluate_animdata(scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM);
+ BKE_object_where_is_calc_time(scene, obtar, ctime);
+ }
+ }
+ }
+ BKE_object_where_is_calc_time(scene, ob, ctime);
+ copy_m4_m4(mat, ob->obmat);
+}
+
diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h
index 349930dea8f..a6f1b89aedb 100644
--- a/source/blender/collada/AnimationExporter.h
+++ b/source/blender/collada/AnimationExporter.h
@@ -34,6 +34,7 @@ extern "C"
#include "DNA_camera_types.h"
#include "DNA_armature_types.h"
#include "DNA_material_types.h"
+#include "DNA_constraint_types.h"
#include "BLI_math.h"
#include "BLI_string.h"
@@ -47,6 +48,10 @@ extern "C"
#include "BKE_action.h" // pose functions
#include "BKE_armature.h"
#include "BKE_object.h"
+#include "BKE_constraint.h"
+#include "BIK_api.h"
+#include "BKE_global.h"
+#include "ED_object.h"
#ifdef NAN_BUILDINFO
extern char build_rev[];
@@ -73,9 +78,13 @@ extern char build_rev[];
#include "collada_internal.h"
+#include "IK_solver.h"
+
#include <vector>
#include <algorithm> // std::find
+
+
class AnimationExporter: COLLADASW::LibraryAnimations
{
private:
@@ -89,7 +98,7 @@ public:
{ this->sw = sw; }
- void exportAnimations(Scene *sce);
+ bool exportAnimations(Scene *sce);
// called for each exported object
void operator() (Object *ob);
@@ -98,6 +107,10 @@ 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);
void write_bone_animation_matrix(Object *ob_arm, Bone *bone);
@@ -119,6 +132,8 @@ protected:
void dae_baked_animation(std::vector<float> &fra, Object *ob_arm, Bone *bone);
+ void dae_baked_object_animation(std::vector<float> &fra, Object *ob);
+
float convert_time(float frame);
float convert_angle(float angle);
@@ -126,11 +141,11 @@ protected:
std::string get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic);
void add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param,
- COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis, bool transform);
+ COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis, bool transform);
void get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool rotation, float *values, int *length);
- float * get_eul_source_for_quat(Object *ob );
+ float* get_eul_source_for_quat(Object *ob );
std::string create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name);
@@ -143,17 +158,21 @@ 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);
+
// for rotation, axis name is always appended and the value of append_axis is ignored
std::string get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis);
std::string get_light_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis);
std::string get_camera_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis);
+
void find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name);
void find_frames(Object *ob, std::vector<float> &fra);
+ void make_anim_frames_from_targets(Object *ob, std::vector<float> &frames );
+
void find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode);
// enable fcurves driving a specific bone, disable all the rest
@@ -165,4 +184,12 @@ protected:
char *extract_transform_name(char *rna_path);
std::string getObjectBoneName(Object *ob, const FCurve * fcu);
+ std::string getAnimationPathId(const FCurve *fcu);
+
+ void getBakedPoseData(Object *obarm, int startFrame, int endFrame, bool ActionBake, bool ActionBakeFirstFrame);
+
+ bool validateConstraints(bConstraint *con);
+
+ void calc_ob_mat_at_time(Object *ob, float ctime , float mat[][4]);
+
};
diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp
index 44e74e320cc..60188071832 100644
--- a/source/blender/collada/AnimationImporter.cpp
+++ b/source/blender/collada/AnimationImporter.cpp
@@ -937,10 +937,9 @@ void AnimationImporter::translate_Animations(COLLADAFW::Node *node,
if (is_matrix) {
apply_matrix_curves(ob, animcurves, root, node, transform);
}
- else {
+ else {
if (is_joint) {
-
add_bone_animation_sampled(ob, animcurves, root, node, transform);
}
else {
@@ -1194,7 +1193,7 @@ void AnimationImporter::add_bone_animation_sampled(Object *ob, std::vector<FCurv
calc_joint_parent_mat_rest(par, NULL, root, node);
mult_m4_m4m4(temp, par, matfra);
- // evaluate_joint_world_transform_at_frame(temp, NULL,, node, fra);
+ // evaluate_joint_world_transform_at_frame(temp, NULL, node, fra);
// calc special matrix
mul_serie_m4(mat, irest, temp, irest_dae, rest, NULL, NULL, NULL, NULL);
@@ -1529,7 +1528,7 @@ Object *AnimationImporter::translate_animation_OLD(COLLADAFW::Node *node,
calc_joint_parent_mat_rest(par, NULL, root, node);
mult_m4_m4m4(temp, par, matfra);
- // evaluate_joint_world_transform_at_frame(temp, NULL,, node, fra);
+ // evaluate_joint_world_transform_at_frame(temp, NULL, node, fra);
// calc special matrix
mul_serie_m4(mat, irest, temp, irest_dae, rest, NULL, NULL, NULL, NULL);
@@ -1676,8 +1675,6 @@ void AnimationImporter::evaluate_transform_at_frame(float mat[4][4], COLLADAFW::
default:
fprintf(stderr, "unsupported transformation type %d\n", type);
}
- // dae_matrix_to_mat4(tm, m);
-
}
float temp[4][4];
@@ -1891,7 +1888,7 @@ Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, COLLADAFW::No
job->lay = BKE_scene_base_find(scene, job)->lay = 2;
mul_v3_fl(job->size, 0.5f);
- job->recalc |= OB_RECALC_OB;
+ DAG_id_tag_update(&job->id, OB_RECALC_OB);
verify_adt_action((ID *)&job->id, 1);
@@ -1912,14 +1909,14 @@ Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, COLLADAFW::No
if (par_job) {
job->parent = par_job;
- par_job->recalc |= OB_RECALC_OB;
+ DAG_id_tag_update(&par_job->id, OB_RECALC_OB);
job->parsubstr[0] = 0;
}
BKE_object_where_is_calc(scene, job);
// after parenting and layer change
- DAG_scene_sort(CTX_data_main(C), scene);
+ DAG_relations_tag_update(CTX_data_main(C));
joint_objects[node->getUniqueId()] = job;
}
diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp
index 134fd639a73..2d3dc979416 100644
--- a/source/blender/collada/ArmatureExporter.cpp
+++ b/source/blender/collada/ArmatureExporter.cpp
@@ -75,12 +75,6 @@ void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene *sce,
}
}
-bool ArmatureExporter::is_skinned_mesh(Object *ob)
-{
- return bc_get_assigned_armature(ob) != NULL;
-}
-
-
void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone)
{
if (bc_is_root_bone(bone, this->export_settings->deform_bones_only))
@@ -117,26 +111,12 @@ bool ArmatureExporter::add_instance_controller(Object *ob)
return true;
}
-void ArmatureExporter::export_controllers(Scene *sce)
-{
- scene = sce;
-
- openLibrary();
-
- GeometryFunctor gf;
- gf.forEachMeshObjectInExportSet<ArmatureExporter>(sce, *this, this->export_settings->export_set);
-
- closeLibrary();
-}
-
+#if 0
void ArmatureExporter::operator()(Object *ob)
{
Object *ob_arm = bc_get_assigned_armature(ob);
- if (ob_arm /*&& !already_written(ob_arm)*/)
- export_controller(ob, ob_arm);
}
-#if 0
bool ArmatureExporter::already_written(Object *ob_arm)
{
@@ -187,67 +167,67 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce,
node.setNodeName(node_name);
node.setNodeSid(node_sid);
-#if 0
+#if 0
if (bone->childbase.first == NULL || BLI_countlist(&(bone->childbase)) >= 2) {
add_blender_leaf_bone( bone, ob_arm, node);
}
else {
#endif
- node.start();
+ node.start();
- add_bone_transform(ob_arm, bone, node);
+ add_bone_transform(ob_arm, bone, node);
- // Write nodes of childobjects, remove written objects from list
- std::list<Object *>::iterator i = child_objects.begin();
+ // Write nodes of childobjects, remove written objects from list
+ std::list<Object *>::iterator i = child_objects.begin();
- while (i != child_objects.end()) {
- if ((*i)->partype == PARBONE && (0 == strcmp((*i)->parsubstr, bone->name))) {
- float backup_parinv[4][4];
- copy_m4_m4(backup_parinv, (*i)->parentinv);
+ while (i != child_objects.end()) {
+ if ((*i)->partype == PARBONE && (0 == strcmp((*i)->parsubstr, bone->name))) {
+ float backup_parinv[4][4];
+ copy_m4_m4(backup_parinv, (*i)->parentinv);
- // crude, temporary change to parentinv
- // so transform gets exported correctly.
+ // crude, temporary change to parentinv
+ // so transform gets exported correctly.
- // Add bone tail- translation... don't know why
- // bone parenting is against the tail of a bone
- // and not it's head, seems arbitrary.
- (*i)->parentinv[3][1] += bone->length;
+ // Add bone tail- translation... don't know why
+ // bone parenting is against the tail of a bone
+ // and not it's head, seems arbitrary.
+ (*i)->parentinv[3][1] += bone->length;
- // SECOND_LIFE_COMPATIBILITY
- // TODO: when such objects are animated as
- // single matrix the tweak must be applied
- // to the result.
- if (export_settings->second_life) {
- // tweak objects parentinverse to match compatibility
- float temp[4][4];
+ // SECOND_LIFE_COMPATIBILITY
+ // TODO: when such objects are animated as
+ // single matrix the tweak must be applied
+ // to the result.
+ if (export_settings->second_life) {
+ // tweak objects parentinverse to match compatibility
+ float temp[4][4];
- copy_m4_m4(temp, bone->arm_mat);
- temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+ copy_m4_m4(temp, bone->arm_mat);
+ temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
- mult_m4_m4m4((*i)->parentinv, temp, (*i)->parentinv);
- }
+ mult_m4_m4m4((*i)->parentinv, temp, (*i)->parentinv);
+ }
- se->writeNodes(*i, sce);
+ se->writeNodes(*i, sce);
- copy_m4_m4((*i)->parentinv, backup_parinv);
- child_objects.erase(i++);
+ copy_m4_m4((*i)->parentinv, backup_parinv);
+ child_objects.erase(i++);
+ }
+ else i++;
}
- else i++;
- }
- for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
- add_bone_node(child, ob_arm, sce, se, child_objects);
+ for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
+ add_bone_node(child, ob_arm, sce, se, child_objects);
+ }
+ node.end();
}
- node.end();
- }
- else {
- for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
- add_bone_node(child, ob_arm, sce, se, child_objects);
+ else {
+ for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
+ add_bone_node(child, ob_arm, sce, se, child_objects);
+ }
}
- }
}
-#if 0
+//#if 1
void ArmatureExporter::add_blender_leaf_bone(Bone *bone, Object *ob_arm, COLLADASW::Node& node)
{
node.start();
@@ -258,33 +238,38 @@ void ArmatureExporter::add_blender_leaf_bone(Bone *bone, Object *ob_arm, COLLADA
node.addExtraTechniqueParameter("blender", "tip_y", bone->tail[1]);
node.addExtraTechniqueParameter("blender", "tip_z", bone->tail[2]);
- for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
+ /*for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
add_bone_node(child, ob_arm, sce, se, child_objects);
- }
+ }*/
node.end();
}
-#endif
+//#endif
void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node)
{
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
+ //bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
float mat[4][4];
if (bone->parent) {
- // get bone-space matrix from armature-space
- bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name);
-
+ // get bone-space matrix from parent pose
+ /*bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name);
float invpar[4][4];
invert_m4_m4(invpar, parchan->pose_mat);
- mult_m4_m4m4(mat, invpar, pchan->pose_mat);
+ mult_m4_m4m4(mat, invpar, pchan->pose_mat);*/
+
+ float invpar[4][4];
+ invert_m4_m4(invpar, bone->parent->arm_mat);
+ mult_m4_m4m4(mat, invpar, bone->arm_mat);
+
}
else {
- copy_m4_m4(mat, pchan->pose_mat);
- // Why? Joint's localspace is still it's parent node
- //get world-space from armature-space
- //mult_m4_m4m4(mat, ob_arm->obmat, pchan->pose_mat);
+
+ //copy_m4_m4(mat, pchan->pose_mat);
+ //pose mat is object space
+ //New change: export bone->arm_mat
+ copy_m4_m4(mat, bone->arm_mat);
}
// SECOND_LIFE_COMPATIBILITY
@@ -313,315 +298,3 @@ std::string ArmatureExporter::get_controller_id(Object *ob_arm, Object *ob)
{
return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX;
}
-
-// ob should be of type OB_MESH
-// both args are required
-void ArmatureExporter::export_controller(Object *ob, Object *ob_arm)
-{
- // joint names
- // joint inverse bind matrices
- // vertex weights
-
- // input:
- // joint names: ob -> vertex group names
- // vertex group weights: me->dvert -> groups -> index, weight
-
-#if 0
- me->dvert :
-
- typedef struct MDeformVert {
- struct MDeformWeight *dw;
- int totweight;
- int flag; // flag only in use for weightpaint now
- } MDeformVert;
-
- typedef struct MDeformWeight {
- int def_nr;
- float weight;
- } MDeformWeight;
-#endif
-
- bool use_instantiation = this->export_settings->use_object_instantiation;
- Mesh *me;
-
- if (this->export_settings->apply_modifiers) {
- me = bc_to_mesh_apply_modifiers(scene, ob, this->export_settings->export_mesh_type);
- }
- else {
- me = (Mesh *)ob->data;
- }
- BKE_mesh_tessface_ensure(me);
-
- if (!me->dvert) return;
-
- std::string controller_name = id_name(ob_arm);
- std::string controller_id = get_controller_id(ob_arm, ob);
-
- openSkin(controller_id, controller_name,
- COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, use_instantiation)));
-
- add_bind_shape_mat(ob);
-
- std::string joints_source_id = add_joints_source(ob_arm, &ob->defbase, controller_id);
- std::string inv_bind_mat_source_id = add_inv_bind_mats_source(ob_arm, &ob->defbase, controller_id);
-
- std::list<int> vcounts;
- std::list<int> joints;
- std::list<float> weights;
-
- {
- int i, j;
-
- // def group index -> joint index
- std::vector<int> joint_index_by_def_index;
- bDeformGroup *def;
-
- for (def = (bDeformGroup *)ob->defbase.first, i = 0, j = 0; def; def = def->next, i++) {
- if (is_bone_defgroup(ob_arm, def))
- joint_index_by_def_index.push_back(j++);
- else
- joint_index_by_def_index.push_back(-1);
- }
-
- for (i = 0; i < me->totvert; i++) {
- MDeformVert *vert = &me->dvert[i];
- std::map<int, float> jw;
-
- // We're normalizing the weights later
- float sumw = 0.0f;
-
- for (j = 0; j < vert->totweight; j++) {
- int joint_index = joint_index_by_def_index[vert->dw[j].def_nr];
- if (joint_index != -1 && vert->dw[j].weight > 0.0f) {
- jw[joint_index] += vert->dw[j].weight;
- sumw += vert->dw[j].weight;
- }
- }
-
- if (sumw > 0.0f) {
- float invsumw = 1.0f / sumw;
- vcounts.push_back(jw.size());
- for (std::map<int, float>::iterator m = jw.begin(); m != jw.end(); ++m) {
- joints.push_back((*m).first);
- weights.push_back(invsumw * (*m).second);
- }
- }
- else {
- vcounts.push_back(0);
-#if 0
- vcounts.push_back(1);
- joints.push_back(-1);
- weights.push_back(1.0f);
-#endif
- }
- }
- }
-
- std::string weights_source_id = add_weights_source(me, controller_id, weights);
- add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id);
- add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints);
-
- if (this->export_settings->apply_modifiers)
- {
- BKE_libblock_free_us(&(G.main->mesh), me);
- }
- closeSkin();
- closeController();
-}
-
-void ArmatureExporter::add_joints_element(ListBase *defbase,
- const std::string& joints_source_id, const std::string& inv_bind_mat_source_id)
-{
- COLLADASW::JointsElement joints(mSW);
- COLLADASW::InputList &input = joints.getInputList();
-
- input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h
- COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id)));
- input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::BINDMATRIX,
- COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, inv_bind_mat_source_id)));
- joints.add();
-}
-
-void ArmatureExporter::add_bind_shape_mat(Object *ob)
-{
- double bind_mat[4][4];
-
- converter.mat4_to_dae_double(bind_mat, ob->obmat);
-
- addBindShapeTransform(bind_mat);
-}
-
-std::string ArmatureExporter::add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
-{
- std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX;
-
- int totjoint = 0;
- bDeformGroup *def;
- for (def = (bDeformGroup *)defbase->first; def; def = def->next) {
- if (is_bone_defgroup(ob_arm, def))
- totjoint++;
- }
-
- COLLADASW::NameSource source(mSW);
- source.setId(source_id);
- source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(totjoint);
- source.setAccessorStride(1);
-
- COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- param.push_back("JOINT");
-
- source.prepareToAppendValues();
-
- for (def = (bDeformGroup *)defbase->first; def; def = def->next) {
- Bone *bone = get_bone_from_defgroup(ob_arm, def);
- if (bone)
- source.appendValues(get_joint_sid(bone, ob_arm));
- }
-
- source.finish();
-
- return source_id;
-}
-
-std::string ArmatureExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
-{
- std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX;
-
- int totjoint = 0;
- for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) {
- if (is_bone_defgroup(ob_arm, def))
- totjoint++;
- }
-
- COLLADASW::FloatSourceF source(mSW);
- source.setId(source_id);
- source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(totjoint); //BLI_countlist(defbase));
- source.setAccessorStride(16);
-
- source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4);
- COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- param.push_back("TRANSFORM");
-
- source.prepareToAppendValues();
-
- bPose *pose = ob_arm->pose;
- bArmature *arm = (bArmature *)ob_arm->data;
-
- int flag = arm->flag;
-
- // put armature in rest position
- if (!(arm->flag & ARM_RESTPOS)) {
- arm->flag |= ARM_RESTPOS;
- BKE_pose_where_is(scene, ob_arm);
- }
-
- for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) {
- if (is_bone_defgroup(ob_arm, def)) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(pose, def->name);
-
- float mat[4][4];
- float world[4][4];
- float inv_bind_mat[4][4];
-
- // SECOND_LIFE_COMPATIBILITY
- if (export_settings->second_life) {
- // Only translations, no rotation vs armature
- float temp[4][4];
- unit_m4(temp);
- copy_v3_v3(temp[3], pchan->bone->arm_mat[3]);
- mult_m4_m4m4(world, ob_arm->obmat, temp);
- }
- else {
- // make world-space matrix, arm_mat is armature-space
- mult_m4_m4m4(world, ob_arm->obmat, pchan->bone->arm_mat);
- }
-
- invert_m4_m4(mat, world);
- converter.mat4_to_dae(inv_bind_mat, mat);
-
- source.appendValues(inv_bind_mat);
- }
- }
-
- // back from rest positon
- if (!(flag & ARM_RESTPOS)) {
- arm->flag = flag;
- BKE_pose_where_is(scene, ob_arm);
- }
-
- source.finish();
-
- return source_id;
-}
-
-Bone *ArmatureExporter::get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def)
-{
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, def->name);
- return pchan ? pchan->bone : NULL;
-}
-
-bool ArmatureExporter::is_bone_defgroup(Object *ob_arm, bDeformGroup *def)
-{
- return get_bone_from_defgroup(ob_arm, def) != NULL;
-}
-
-std::string ArmatureExporter::add_weights_source(Mesh *me, const std::string& controller_id, const std::list<float>& weights)
-{
- std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX;
-
- COLLADASW::FloatSourceF source(mSW);
- source.setId(source_id);
- source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(weights.size());
- source.setAccessorStride(1);
-
- COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- param.push_back("WEIGHT");
-
- source.prepareToAppendValues();
-
- for (std::list<float>::const_iterator i = weights.begin(); i != weights.end(); ++i) {
- source.appendValues(*i);
- }
-
- source.finish();
-
- return source_id;
-}
-
-void ArmatureExporter::add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id,
- const std::list<int>& vcounts,
- const std::list<int>& joints)
-{
- COLLADASW::VertexWeightsElement weightselem(mSW);
- COLLADASW::InputList &input = weightselem.getInputList();
-
- int offset = 0;
- input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h
- COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id), offset++));
- input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::WEIGHT,
- COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, weights_source_id), offset++));
-
- weightselem.setCount(vcounts.size());
-
- // write number of deformers per vertex
- COLLADASW::PrimitivesBase::VCountList vcountlist;
-
- vcountlist.resize(vcounts.size());
- std::copy(vcounts.begin(), vcounts.end(), vcountlist.begin());
-
- weightselem.prepareToAppendVCountValues();
- weightselem.appendVertexCount(vcountlist);
-
- weightselem.CloseVCountAndOpenVElement();
-
- // write deformer index - weight index pairs
- int weight_index = 0;
- for (std::list<int>::const_iterator i = joints.begin(); i != joints.end(); ++i) {
- weightselem.appendValues(*i, weight_index++);
- }
-
- weightselem.finish();
-}
diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h
index 086c16f0cd5..931cc5d2988 100644
--- a/source/blender/collada/ArmatureExporter.h
+++ b/source/blender/collada/ArmatureExporter.h
@@ -41,6 +41,7 @@
#include "DNA_listBase.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
+#include "DNA_constraint_types.h"
#include "DNA_scene_types.h"
#include "TransformWriter.h"
@@ -62,16 +63,13 @@ public:
void add_armature_bones(Object *ob_arm, Scene *sce, SceneExporter *se,
std::list<Object *>& child_objects);
- bool is_skinned_mesh(Object *ob);
-
bool add_instance_controller(Object *ob);
- void export_controllers(Scene *sce);
+ //void export_controllers(Scene *sce);*/
- void operator()(Object *ob);
+ //void operator()(Object *ob);
private:
- Scene *scene;
UnitConverter converter;
const ExportSettings *export_settings;
@@ -98,29 +96,6 @@ private:
std::string get_controller_id(Object *ob_arm, Object *ob);
- // ob should be of type OB_MESH
- // both args are required
- void export_controller(Object *ob, Object *ob_arm);
-
- void add_joints_element(ListBase *defbase,
- const std::string& joints_source_id, const std::string& inv_bind_mat_source_id);
-
- void add_bind_shape_mat(Object *ob);
-
- std::string add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id);
-
- std::string add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id);
-
- Bone *get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def);
-
- bool is_bone_defgroup(Object *ob_arm, bDeformGroup *def);
-
- std::string add_weights_source(Mesh *me, const std::string& controller_id,
- const std::list<float>& weights);
-
- void add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id,
- const std::list<int>& vcount, const std::list<int>& joints);
-
void write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone);
};
diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp
index f1cf732e695..0f8a4e5af76 100644
--- a/source/blender/collada/ArmatureImporter.cpp
+++ b/source/blender/collada/ArmatureImporter.cpp
@@ -49,8 +49,8 @@ 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, AnimationImporterBase *anim, Scene *sce) :
- TransformReader(conv), scene(sce), empty(NULL), mesh_importer(mesh), anim_importer(anim) {
+ArmatureImporter::ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce) :
+ TransformReader(conv), scene(sce), empty(NULL), mesh_importer(mesh) {
}
ArmatureImporter::~ArmatureImporter()
@@ -78,84 +78,8 @@ JointData *ArmatureImporter::get_joint_data(COLLADAFW::Node *node);
return &joint_index_to_joint_info_map[joint_index];
}
#endif
-void ArmatureImporter::create_unskinned_bone(COLLADAFW::Node *node, EditBone *parent, int totchild,
- float parent_mat[4][4], Object *ob_arm)
-{
- std::vector<COLLADAFW::Node *>::iterator it;
- it = std::find(finished_joints.begin(), finished_joints.end(), node);
- if (it != finished_joints.end()) return;
-
- float mat[4][4];
- float obmat[4][4];
-
- // object-space
- get_node_mat(obmat, node, NULL, NULL);
- EditBone *bone = ED_armature_edit_bone_add((bArmature *)ob_arm->data, (char *)bc_get_joint_name(node));
- totbone++;
-
- if (parent) bone->parent = parent;
-
- float angle = 0;
-
- // get world-space
- if (parent) {
- mult_m4_m4m4(mat, parent_mat, obmat);
-
- }
- else {
- copy_m4_m4(mat, obmat);
-
- }
- float loc[3], size[3], rot[3][3];
- mat4_to_loc_rot_size(loc, rot, size, obmat);
- mat3_to_vec_roll(rot, NULL, &angle);
- bone->roll = angle;
- // set head
- copy_v3_v3(bone->head, mat[3]);
-
- // set tail, don't set it to head because 0-length bones are not allowed
- float vec[3] = {0.0f, 0.5f, 0.0f};
- add_v3_v3v3(bone->tail, bone->head, vec);
-
- // set parent tail
- if (parent && 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;
-
- // XXX increase this to prevent "very" small bones?
- const float epsilon = 0.000001f;
-
- // derive leaf bone length
- float length = len_v3v3(parent->head, parent->tail);
- if ((length < leaf_bone_length || totbone == 0) && length > epsilon) {
- leaf_bone_length = length;
- }
-
- // treat zero-sized bone like a leaf bone
- if (length <= epsilon) {
- add_leaf_bone(parent_mat, parent, node);
- }
-
- }
-
- COLLADAFW::NodePointerArray& children = node->getChildNodes();
- for (unsigned int i = 0; i < children.getCount(); i++) {
- create_unskinned_bone(children[i], bone, children.getCount(), mat, ob_arm);
- }
-
- // 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);
- }
-
- finished_joints.push_back(node);
-
-}
-
-void ArmatureImporter::create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
+void ArmatureImporter::create_bone(SkinInfo* skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
float parent_mat[4][4], bArmature *arm)
{
//Checking if bone is already made.
@@ -168,42 +92,44 @@ void ArmatureImporter::create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBo
// JointData* jd = get_joint_data(node);
float mat[4][4];
-
+ float obmat[4][4];
+
// TODO rename from Node "name" attrs later
EditBone *bone = ED_armature_edit_bone_add(arm, (char *)bc_get_joint_name(node));
totbone++;
- if (skin.get_joint_inv_bind_matrix(joint_inv_bind_mat, node)) {
+ if (skin && skin->get_joint_inv_bind_matrix(joint_inv_bind_mat, node)) {
// get original world-space matrix
invert_m4_m4(mat, joint_inv_bind_mat);
}
// create a bone even if there's no joint data for it (i.e. it has no influence)
else {
- float obmat[4][4];
-
- // object-space
+ // bone-space
get_node_mat(obmat, node, NULL, NULL);
// get world-space
- if (parent)
+ if (parent) {
mult_m4_m4m4(mat, parent_mat, obmat);
- else
+ }
+ else {
copy_m4_m4(mat, obmat);
-
- float loc[3], size[3], rot[3][3], angle;
- mat4_to_loc_rot_size(loc, rot, size, obmat);
- mat3_to_vec_roll(rot, NULL, &angle);
- bone->roll = angle;
+ }
}
-
if (parent) bone->parent = parent;
+ float loc[3], size[3], rot[3][3];
+ float angle;
+ float vec[3] = {0.0f, 0.5f, 0.0f};
+ mat4_to_loc_rot_size(loc, rot, size, mat);
+ //copy_m3_m4(bonemat,mat);
+ mat3_to_vec_roll(rot, vec, &angle);
+
+ bone->roll = angle;
// set head
copy_v3_v3(bone->head, mat[3]);
// set tail, don't set it to head because 0-length bones are not allowed
- float vec[3] = {0.0f, 0.5f, 0.0f};
add_v3_v3v3(bone->tail, bone->head, vec);
// set parent tail
@@ -211,7 +137,7 @@ void ArmatureImporter::create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBo
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;
+ bone->flag |= BONE_CONNECTED;
// XXX increase this to prevent "very" small bones?
const float epsilon = 0.000001f;
@@ -227,32 +153,6 @@ void ArmatureImporter::create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBo
add_leaf_bone(parent_mat, parent, node);
}
- /*
-#if 0
- // and which row in mat is bone direction
- float vec[3];
- sub_v3_v3v3(vec, parent->tail, parent->head);
-#ifdef COLLADA_DEBUG
- print_v3("tail - head", vec);
- print_m4("matrix", parent_mat);
-#endif
- for (int i = 0; i < 3; i++) {
-#ifdef COLLADA_DEBUG
- char *axis_names[] = {"X", "Y", "Z"};
- printf("%s-axis length is %f\n", axis_names[i], len_v3(parent_mat[i]));
-#endif
- float angle = angle_v2v2(vec, parent_mat[i]);
- if (angle < min_angle) {
-#ifdef COLLADA_DEBUG
- print_v3("picking", parent_mat[i]);
- printf("^ %s axis of %s's matrix\n", axis_names[i], get_dae_name(node));
-#endif
- bone_direction_row = i;
- min_angle = angle;
- }
- }
-#endif
- */
}
COLLADAFW::NodePointerArray& children = node->getChildNodes();
@@ -265,6 +165,8 @@ void ArmatureImporter::create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBo
add_leaf_bone(mat, bone, node);
}
+ bone->length = len_v3v3(bone->head, bone->tail);
+
finished_joints.push_back(node);
}
@@ -299,7 +201,6 @@ void ArmatureImporter::add_leaf_bone(float mat[4][4], EditBone *bone, COLLADAFW
void ArmatureImporter::fix_leaf_bones( )
{
// 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;
@@ -307,11 +208,10 @@ void ArmatureImporter::fix_leaf_bones( )
// pointing up
float vec[3] = {0.0f, 0.0f, 0.1f};
- // if parent: take parent length and direction
- if (leaf.bone->parent) sub_v3_v3v3(vec, leaf.bone->parent->tail, leaf.bone->parent->head);
+ sub_v3_v3v3(vec, leaf.bone->tail , leaf.bone->head);
+ mul_v3_fl(vec, leaf_bone_length);
+ add_v3_v3v3(leaf.bone->tail, leaf.bone->head , vec);
- copy_v3_v3(leaf.bone->tail, leaf.bone->head);
- add_v3_v3v3(leaf.bone->tail, leaf.bone->head, vec);
}
}
@@ -410,46 +310,40 @@ ArmatureJoints& ArmatureImporter::get_armature_joints(Object *ob_arm)
void ArmatureImporter::create_armature_bones( )
{
std::vector<COLLADAFW::Node *>::iterator ri;
+
+ leaf_bone_length = FLT_MAX;
//if there is an armature created for root_joint next root_joint
for (ri = root_joints.begin(); ri != root_joints.end(); ri++) {
if (get_armature_for_joint(*ri) != NULL) continue;
- //add armature object for current joint
- //Object *ob_arm = bc_add_object(scene, OB_ARMATURE, NULL);
-
Object *ob_arm = joint_parent_map[(*ri)->getUniqueId()];
if (!ob_arm)
continue;
- //ob_arm->type = OB_ARMATURE;
ED_armature_to_edit(ob_arm);
- // min_angle = 360.0f; // minimum angle between bone head-tail and a row of bone matrix
-
- // create unskinned bones
/*
* TODO:
* check if bones have already been created for a given joint
*/
- leaf_bone_length = FLT_MAX;
- create_unskinned_bone(*ri, NULL, (*ri)->getChildNodes().getCount(), NULL, ob_arm);
+ create_bone(NULL, *ri , NULL, (*ri)->getChildNodes().getCount(), NULL, (bArmature *)ob_arm->data);
+
+ //leaf bone tails are derived from the matrix, so no need of this.
fix_leaf_bones();
// exit armature edit mode
-
unskinned_armature_map[(*ri)->getUniqueId()] = ob_arm;
ED_armature_from_edit(ob_arm);
- set_pose(ob_arm, *ri, NULL, NULL);
+ //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(ob_arm);
DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
}
-
-
}
void ArmatureImporter::create_armature_bones(SkinInfo& skin)
@@ -521,10 +415,23 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin)
break;
}
- if (shared)
+ if (!shared && this->joint_parent_map.size() > 0) {
+ // All armatures have been created while creating the Node tree.
+ // The Collada exporter currently does not create a
+ // strict relationship between geometries and armatures
+ // So when we reimport a Blender collada file, then we have
+ // to guess what is meant.
+ // XXX This is not safe when we have more than one armatures
+ // in the import.
+ shared = this->joint_parent_map.begin()->second;
+ }
+
+ if (shared) {
ob_arm = skin.set_armature(shared);
- else
+ }
+ else {
ob_arm = skin.create_armature(scene); //once for every armature
+ }
// enter armature edit mode
ED_armature_to_edit(ob_arm);
@@ -533,7 +440,6 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin)
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;
- // min_angle = 360.0f; // minimum angle between bone head-tail and a row of bone matrix
// create bones
/*
@@ -549,7 +455,7 @@ 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, (bArmature *)ob_arm->data);
if (joint_parent_map.find((*ri)->getUniqueId()) != joint_parent_map.end() && !skin.get_parent())
skin.set_parent(joint_parent_map[(*ri)->getUniqueId()]);
@@ -563,24 +469,14 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin)
ED_armature_edit_free(ob_arm);
DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
- // set_leaf_bone_shapes(ob_arm);
- // set_euler_rotmode();
}
-
-// 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::set_pose(Object *ob_arm, COLLADAFW::Node *root_node, const char *parentname, float parent_mat[4][4])
{
char *bone_name = (char *) bc_get_joint_name(root_node);
float mat[4][4];
float obmat[4][4];
- float ax[3];
- float angle = 0.0f;
-
// object-space
get_node_mat(obmat, root_node, NULL, NULL);
@@ -597,14 +493,17 @@ void ArmatureImporter::set_pose(Object *ob_arm, COLLADAFW::Node *root_node, con
}
else {
+
copy_m4_m4(mat, obmat);
float invObmat[4][4];
invert_m4_m4(invObmat, ob_arm->obmat);
mult_m4_m4m4(pchan->pose_mat, invObmat, mat);
+
}
- mat4_to_axis_angle(ax, &angle, mat);
- pchan->bone->roll = angle;
+ //float angle = 0.0f;
+ ///*mat4_to_axis_angle(ax, &angle, mat);
+ //pchan->bone->roll = angle;*/
COLLADAFW::NodePointerArray& children = root_node->getChildNodes();
@@ -614,6 +513,10 @@ 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
void ArmatureImporter::add_joint(COLLADAFW::Node *node, bool root, Object *parent, Scene *sce)
{
joint_by_uid[node->getUniqueId()] = node;
@@ -729,13 +632,12 @@ bool ArmatureImporter::write_skin_controller_data(const COLLADAFW::SkinControlle
bool ArmatureImporter::write_controller(const COLLADAFW::Controller *controller)
{
// - create and store armature object
-
- const COLLADAFW::UniqueId& skin_id = controller->getUniqueId();
+ const COLLADAFW::UniqueId& con_id = controller->getUniqueId();
if (controller->getControllerType() == COLLADAFW::Controller::CONTROLLER_TYPE_SKIN) {
COLLADAFW::SkinController *co = (COLLADAFW::SkinController *)controller;
// to be able to find geom id by controller id
- geom_uid_by_controller_uid[skin_id] = co->getSource();
+ geom_uid_by_controller_uid[con_id] = co->getSource();
const COLLADAFW::UniqueId& data_uid = co->getSkinControllerData();
if (skin_by_data_uid.find(data_uid) == skin_by_data_uid.end()) {
@@ -746,14 +648,71 @@ bool ArmatureImporter::write_controller(const COLLADAFW::Controller *controller)
skin_by_data_uid[data_uid].set_controller(co);
}
// morph controller
- else {
- // shape keys? :)
- fprintf(stderr, "Morph controller is not supported yet.\n");
+ else if (controller->getControllerType() == COLLADAFW::Controller::CONTROLLER_TYPE_MORPH) {
+ COLLADAFW::MorphController *co = (COLLADAFW::MorphController *)controller;
+ // to be able to find geom id by controller id
+ geom_uid_by_controller_uid[con_id] = co->getSource();
+ //Shape keys are applied in DocumentImporter->finish()
+ morph_controllers.push_back(co);
}
return true;
}
+void ArmatureImporter::make_shape_keys()
+{
+ std::vector<COLLADAFW::MorphController *>::iterator mc;
+ float weight;
+
+ for (mc = morph_controllers.begin(); mc != morph_controllers.end(); mc++) {
+ //Controller data
+ COLLADAFW::UniqueIdArray& morphTargetIds = (*mc)->getMorphTargets();
+ COLLADAFW::FloatOrDoubleArray& morphWeights = (*mc)->getMorphWeights();
+
+ //Prereq: all the geometries must be imported and mesh objects must be made
+ Object *source_ob = this->mesh_importer->get_object_by_geom_uid((*mc)->getSource());
+
+ if (source_ob) {
+
+ Mesh *source_me = (Mesh *)source_ob->data;
+ //insert key to source mesh
+ Key *key = source_me->key = BKE_key_add((ID *)source_me);
+ key->type = KEY_RELATIVE;
+ KeyBlock *kb;
+
+ //insert basis key
+ kb = BKE_keyblock_add_ctime(key, "Basis", FALSE);
+ BKE_key_convert_from_mesh(source_me, kb);
+
+ //insert other shape keys
+ for (int i = 0 ; i < morphTargetIds.getCount() ; i++ ) {
+ //better to have a seperate map of morph objects,
+ //This'll do for now since only mesh morphing is imported
+
+ Mesh *me = this->mesh_importer->get_mesh_by_geom_uid(morphTargetIds[i]);
+
+ if (me) {
+ me->key = key;
+ 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);
+
+ //apply weights
+ weight = morphWeights.getFloatValues()->getData()[i];
+ kb->curval = weight;
+ }
+ else {
+ fprintf(stderr, "Morph target geometry not found.\n");
+ }
+ }
+ }
+ else {
+ fprintf(stderr, "Morph target object not found.\n");
+ }
+ }
+}
+
COLLADAFW::UniqueId *ArmatureImporter::get_geometry_uid(const COLLADAFW::UniqueId& controller_uid)
{
diff --git a/source/blender/collada/ArmatureImporter.h b/source/blender/collada/ArmatureImporter.h
index bb710f09490..2a8f1a65e21 100644
--- a/source/blender/collada/ArmatureImporter.h
+++ b/source/blender/collada/ArmatureImporter.h
@@ -29,13 +29,16 @@
#include "COLLADAFWNode.h"
#include "COLLADAFWUniqueId.h"
+#include "COLLADAFWMorphController.h"
extern "C" {
#include "BKE_context.h"
+#include "BKE_key.h"
#include "DNA_armature_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_key_types.h"
#include "ED_armature.h"
}
@@ -88,11 +91,11 @@ private:
std::map<COLLADAFW::UniqueId, COLLADAFW::Node*> joint_by_uid; // contains all joints
std::vector<COLLADAFW::Node*> root_joints;
std::vector<COLLADAFW::Node*> finished_joints;
+ std::vector<COLLADAFW::MorphController*> morph_controllers;
std::map<COLLADAFW::UniqueId, Object*> joint_parent_map;
std::map<COLLADAFW::UniqueId, Object*> unskinned_armature_map;
MeshImporterBase *mesh_importer;
- AnimationImporterBase *anim_importer;
// This is used to store data passed in write_controller_data.
// Arrays from COLLADAFW::SkinControllerData lose ownership, so do this class members
@@ -103,12 +106,9 @@ private:
JointData *get_joint_data(COLLADAFW::Node *node);
#endif
- void create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
+ void create_bone(SkinInfo* skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
float parent_mat[4][4], bArmature *arm);
- void create_unskinned_bone(COLLADAFW::Node *node, EditBone *parent, int totchild,
- float parent_mat[4][4], Object * ob_arm);
-
void add_leaf_bone(float mat[4][4], EditBone *bone, COLLADAFW::Node * node);
void fix_leaf_bones();
@@ -137,12 +137,9 @@ private:
TagsMap uid_tags_map;
public:
- ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, AnimationImporterBase *anim, Scene *sce);
+ ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce);
~ArmatureImporter();
- // 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 add_joint(COLLADAFW::Node *node, bool root, Object *parent, Scene *sce);
#if 0
@@ -152,6 +149,8 @@ public:
// here we add bones to armatures, having armatures previously created in write_controller
void make_armatures(bContext *C);
+ void make_shape_keys();
+
#if 0
// link with meshes, create vertex groups, assign weights
void link_armature(Object *ob_arm, const COLLADAFW::UniqueId& geom_id, const COLLADAFW::UniqueId& controller_data_id);
diff --git a/source/blender/collada/CMakeLists.txt b/source/blender/collada/CMakeLists.txt
index 0091df3c502..8747d2995f2 100644
--- a/source/blender/collada/CMakeLists.txt
+++ b/source/blender/collada/CMakeLists.txt
@@ -36,6 +36,9 @@ set(INC
../windowmanager
../imbuf
../../../intern/guardedalloc
+ ../ikplugin
+ ../../../intern/iksolver/extern
+ ../bmesh
)
set(INC_SYS
@@ -48,11 +51,13 @@ set(SRC
ArmatureExporter.cpp
ArmatureImporter.cpp
CameraExporter.cpp
+ ControllerExporter.cpp
DocumentExporter.cpp
DocumentImporter.cpp
EffectExporter.cpp
ErrorHandler.cpp
ExportSettings.cpp
+ ImportSettings.cpp
ExtraHandler.cpp
ExtraTags.cpp
GeometryExporter.cpp
@@ -74,11 +79,13 @@ set(SRC
ArmatureExporter.h
ArmatureImporter.h
CameraExporter.h
+ ControllerExporter.h
DocumentExporter.h
DocumentImporter.h
EffectExporter.h
ErrorHandler.h
ExportSettings.h
+ ImportSettings.h
ExtraHandler.h
ExtraTags.h
GeometryExporter.h
diff --git a/source/blender/collada/CameraExporter.cpp b/source/blender/collada/CameraExporter.cpp
index 7d438f7f12f..fc56ff8c63c 100644
--- a/source/blender/collada/CameraExporter.cpp
+++ b/source/blender/collada/CameraExporter.cpp
@@ -70,7 +70,8 @@ void CamerasExporter::operator()(Object *ob, Scene *sce)
switch (cam->type) {
case CAM_PANO:
- case CAM_PERSP: {
+ case CAM_PERSP:
+ {
COLLADASW::PerspectiveOptic persp(mSW);
persp.setXFov(RAD2DEGF(focallength_to_fov(cam->lens, cam->sensor_x)), "xfov");
persp.setAspectRatio((float)(sce->r.xsch) / (float)(sce->r.ysch), false, "aspect_ratio");
diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp
new file mode 100644
index 00000000000..71a16df3b26
--- /dev/null
+++ b/source/blender/collada/ControllerExporter.cpp
@@ -0,0 +1,609 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed,
+ * Nathan Letwory, Sukhitha Jayathilake
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/collada/ControllerExporter.cpp
+ * \ingroup collada
+ */
+
+#include "COLLADASWBaseInputElement.h"
+#include "COLLADASWInstanceController.h"
+#include "COLLADASWPrimitves.h"
+#include "COLLADASWSource.h"
+
+#include "DNA_action_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+
+extern "C" {
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+}
+
+#include "ED_armature.h"
+
+#include "BLI_listbase.h"
+
+#include "GeometryExporter.h"
+#include "ArmatureExporter.h"
+#include "ControllerExporter.h"
+#include "SceneExporter.h"
+
+#include "collada_utils.h"
+
+// XXX exporter writes wrong data for shared armatures. A separate
+// controller should be written for each armature-mesh binding how do
+// we make controller ids then?
+ControllerExporter::ControllerExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryControllers(sw), export_settings(export_settings) {
+}
+
+bool ControllerExporter::is_skinned_mesh(Object *ob)
+{
+ return bc_get_assigned_armature(ob) != NULL;
+}
+
+
+void ControllerExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone)
+{
+ if (bc_is_root_bone(bone, this->export_settings->deform_bones_only))
+ ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(bone, ob_arm)));
+ else {
+ for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
+ write_bone_URLs(ins, ob_arm, child);
+ }
+ }
+}
+
+bool ControllerExporter::add_instance_controller(Object *ob)
+{
+ Object *ob_arm = bc_get_assigned_armature(ob);
+ bArmature *arm = (bArmature *)ob_arm->data;
+
+ const std::string& controller_id = get_controller_id(ob_arm, ob);
+
+ COLLADASW::InstanceController ins(mSW);
+ ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id));
+
+ Mesh *me = (Mesh *)ob->data;
+ if (!me->dvert) return false;
+
+ // write root bone URLs
+ Bone *bone;
+ for (bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) {
+ write_bone_URLs(ins, ob_arm, bone);
+ }
+
+ InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only);
+
+ ins.add();
+ return true;
+}
+
+void ControllerExporter::export_controllers(Scene *sce)
+{
+ scene = sce;
+
+ openLibrary();
+
+ GeometryFunctor gf;
+ gf.forEachMeshObjectInExportSet<ControllerExporter>(sce, *this, this->export_settings->export_set);
+
+ closeLibrary();
+}
+
+void ControllerExporter::operator()(Object *ob)
+{
+ Object *ob_arm = bc_get_assigned_armature(ob);
+ Key *key = BKE_key_from_object(ob);
+
+ if (ob_arm) {
+ export_skin_controller(ob, ob_arm);
+ }
+ if (key) {
+ export_morph_controller(ob, key);
+ }
+}
+#if 0
+
+bool ArmatureExporter::already_written(Object *ob_arm)
+{
+ return std::find(written_armatures.begin(), written_armatures.end(), ob_arm) != written_armatures.end();
+}
+
+void ArmatureExporter::wrote(Object *ob_arm)
+{
+ written_armatures.push_back(ob_arm);
+}
+
+void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce)
+{
+ objects.clear();
+
+ Base *base = (Base *) sce->base.first;
+ while (base) {
+ Object *ob = base->object;
+
+ if (ob->type == OB_MESH && get_assigned_armature(ob) == ob_arm) {
+ objects.push_back(ob);
+ }
+
+ base = base->next;
+ }
+}
+#endif
+
+std::string ControllerExporter::get_joint_sid(Bone *bone, Object *ob_arm)
+{
+ return get_joint_id(bone, ob_arm);
+}
+
+std::string ControllerExporter::get_controller_id(Object *ob_arm, Object *ob)
+{
+ return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX;
+}
+
+std::string ControllerExporter::get_controller_id(Key *key, Object *ob)
+{
+ return translate_id(id_name(ob)) + MORPH_CONTROLLER_ID_SUFFIX;
+}
+
+// ob should be of type OB_MESH
+// both args are required
+void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
+{
+ // joint names
+ // joint inverse bind matrices
+ // vertex weights
+
+ // input:
+ // joint names: ob -> vertex group names
+ // vertex group weights: me->dvert -> groups -> index, weight
+
+#if 0
+ me->dvert :
+
+ typedef struct MDeformVert {
+ struct MDeformWeight *dw;
+ int totweight;
+ int flag; // flag only in use for weightpaint now
+ } MDeformVert;
+
+ typedef struct MDeformWeight {
+ int def_nr;
+ float weight;
+ } MDeformWeight;
+#endif
+
+ bool use_instantiation = this->export_settings->use_object_instantiation;
+ Mesh *me;
+
+ me = bc_get_mesh_copy(scene,
+ ob,
+ this->export_settings->export_mesh_type,
+ this->export_settings->apply_modifiers,
+ this->export_settings->triangulate);
+
+ if (!me->dvert) return;
+
+ std::string controller_name = id_name(ob_arm);
+ std::string controller_id = get_controller_id(ob_arm, ob);
+
+ openSkin(controller_id, controller_name,
+ COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, use_instantiation)));
+
+ add_bind_shape_mat(ob);
+
+ std::string joints_source_id = add_joints_source(ob_arm, &ob->defbase, controller_id);
+ std::string inv_bind_mat_source_id = add_inv_bind_mats_source(ob_arm, &ob->defbase, controller_id);
+
+ std::list<int> vcounts;
+ std::list<int> joints;
+ std::list<float> weights;
+
+ {
+ int i, j;
+
+ // def group index -> joint index
+ std::vector<int> joint_index_by_def_index;
+ bDeformGroup *def;
+
+ for (def = (bDeformGroup *)ob->defbase.first, i = 0, j = 0; def; def = def->next, i++) {
+ if (is_bone_defgroup(ob_arm, def))
+ joint_index_by_def_index.push_back(j++);
+ else
+ joint_index_by_def_index.push_back(-1);
+ }
+
+ int oob_counter = 0;
+ for (i = 0; i < me->totvert; i++) {
+ MDeformVert *vert = &me->dvert[i];
+ std::map<int, float> jw;
+
+ // We're normalizing the weights later
+ float sumw = 0.0f;
+
+ for (j = 0; j < vert->totweight; j++) {
+ int idx = vert->dw[j].def_nr;
+ if (idx >= joint_index_by_def_index.size()) {
+ // XXX: Maybe better find out where and
+ // why the Out Of Bound indexes get created ?
+ oob_counter += 1;
+ }
+ else {
+ if (idx >= 0) {
+ int joint_index = joint_index_by_def_index[idx];
+ if (joint_index != -1 && vert->dw[j].weight > 0.0f) {
+ jw[joint_index] += vert->dw[j].weight;
+ sumw += vert->dw[j].weight;
+ }
+ }
+ }
+ }
+
+ if (sumw > 0.0f) {
+ float invsumw = 1.0f / sumw;
+ vcounts.push_back(jw.size());
+ for (std::map<int, float>::iterator m = jw.begin(); m != jw.end(); ++m) {
+ joints.push_back((*m).first);
+ weights.push_back(invsumw * (*m).second);
+ }
+ }
+ else {
+ vcounts.push_back(0);
+#if 0
+ vcounts.push_back(1);
+ joints.push_back(-1);
+ weights.push_back(1.0f);
+#endif
+ }
+ }
+
+ if (oob_counter > 0) {
+ fprintf(stderr, "Ignored %d Vertex weigths which use index to non existing VGroup %ld.\n", oob_counter, joint_index_by_def_index.size());
+ }
+ }
+
+ std::string weights_source_id = add_weights_source(me, controller_id, weights);
+ add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id);
+ add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints);
+
+ BKE_libblock_free_us(&(G.main->mesh), me);
+
+ closeSkin();
+ closeController();
+}
+
+void ControllerExporter::export_morph_controller(Object *ob, Key *key)
+{
+ bool use_instantiation = this->export_settings->use_object_instantiation;
+ Mesh *me;
+
+ me = bc_get_mesh_copy(scene,
+ ob,
+ this->export_settings->export_mesh_type,
+ this->export_settings->apply_modifiers,
+ this->export_settings->triangulate);
+
+ std::string controller_name = id_name(ob) + "-morph";
+ std::string controller_id = get_controller_id(key, ob);
+
+ openMorph(controller_id, controller_name,
+ COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, use_instantiation)));
+
+ std::string targets_id = add_morph_targets(key, ob);
+ std::string morph_weights_id = add_morph_weights(key, ob);
+
+ COLLADASW::TargetsElement targets(mSW);
+
+ COLLADASW::InputList &input = targets.getInputList();
+
+ input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::MORPH_TARGET, // constant declared in COLLADASWInputList.h
+ COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, targets_id)));
+ input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::MORPH_WEIGHT,
+ COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, morph_weights_id)));
+ targets.add();
+
+ BKE_libblock_free_us(&(G.main->mesh), me);
+
+
+ //support for animations
+ //can also try the base element and param alternative
+ add_weight_extras(key);
+ closeMorph();
+ closeController();
+}
+
+std::string ControllerExporter::add_morph_targets(Key *key, Object *ob)
+{
+ std::string source_id = translate_id(id_name(ob)) + TARGETS_SOURCE_ID_SUFFIX;
+
+ COLLADASW::IdRefSource source(mSW);
+ source.setId(source_id);
+ source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+ source.setAccessorCount(key->totkey - 1);
+ source.setAccessorStride(1);
+
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ param.push_back("IDREF");
+
+ source.prepareToAppendValues();
+
+ KeyBlock *kb = (KeyBlock *)key->block.first;
+ //skip the basis
+ kb = kb->next;
+ for (; kb; kb = kb->next) {
+ std::string geom_id = get_geometry_id(ob, false) + "_morph_" + translate_id(kb->name);
+ source.appendValues(geom_id);
+
+ }
+
+ source.finish();
+
+ return source_id;
+}
+
+std::string ControllerExporter::add_morph_weights(Key *key, Object *ob)
+{
+ std::string source_id = translate_id(id_name(ob)) + WEIGHTS_SOURCE_ID_SUFFIX;
+
+ COLLADASW::FloatSourceF source(mSW);
+ source.setId(source_id);
+ source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+ source.setAccessorCount(key->totkey - 1);
+ source.setAccessorStride(1);
+
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ param.push_back("MORPH_WEIGHT");
+
+ source.prepareToAppendValues();
+
+ KeyBlock *kb = (KeyBlock *)key->block.first;
+ //skip the basis
+ kb = kb->next;
+ for (; kb; kb = kb->next) {
+ float weight = kb->curval;
+ source.appendValues(weight);
+ }
+ source.finish();
+
+ return source_id;
+}
+
+//Added to implemente support for animations.
+void ControllerExporter::add_weight_extras(Key *key)
+{
+ // can also try the base element and param alternative
+ COLLADASW::BaseExtraTechnique extra;
+
+ KeyBlock * kb = (KeyBlock *)key->block.first;
+ //skip the basis
+ kb = kb->next;
+ for (; kb; kb = kb->next) {
+ // XXX why is the weight not used here and set to 0.0?
+ // float weight = kb->curval;
+ extra.addExtraTechniqueParameter ("KHR", "morph_weights" , 0.000, "MORPH_WEIGHT_TO_TARGET");
+ }
+}
+
+
+
+void ControllerExporter::add_joints_element(ListBase *defbase,
+ const std::string& joints_source_id, const std::string& inv_bind_mat_source_id)
+{
+ COLLADASW::JointsElement joints(mSW);
+ COLLADASW::InputList &input = joints.getInputList();
+
+ input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h
+ COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id)));
+ input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::BINDMATRIX,
+ COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, inv_bind_mat_source_id)));
+ joints.add();
+}
+
+void ControllerExporter::add_bind_shape_mat(Object *ob)
+{
+ double bind_mat[4][4];
+
+ converter.mat4_to_dae_double(bind_mat, ob->obmat);
+
+ addBindShapeTransform(bind_mat);
+}
+
+std::string ControllerExporter::add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
+{
+ std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX;
+
+ int totjoint = 0;
+ bDeformGroup *def;
+ for (def = (bDeformGroup *)defbase->first; def; def = def->next) {
+ if (is_bone_defgroup(ob_arm, def))
+ totjoint++;
+ }
+
+ COLLADASW::NameSource source(mSW);
+ source.setId(source_id);
+ source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+ source.setAccessorCount(totjoint);
+ source.setAccessorStride(1);
+
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ param.push_back("JOINT");
+
+ source.prepareToAppendValues();
+
+ for (def = (bDeformGroup *)defbase->first; def; def = def->next) {
+ Bone *bone = get_bone_from_defgroup(ob_arm, def);
+ if (bone)
+ source.appendValues(get_joint_sid(bone, ob_arm));
+ }
+
+ source.finish();
+
+ return source_id;
+}
+
+std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
+{
+ std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX;
+
+ int totjoint = 0;
+ for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) {
+ if (is_bone_defgroup(ob_arm, def))
+ totjoint++;
+ }
+
+ COLLADASW::FloatSourceF source(mSW);
+ source.setId(source_id);
+ source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+ source.setAccessorCount(totjoint); //BLI_countlist(defbase));
+ source.setAccessorStride(16);
+
+ source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4);
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ param.push_back("TRANSFORM");
+
+ source.prepareToAppendValues();
+
+ bPose *pose = ob_arm->pose;
+ bArmature *arm = (bArmature *)ob_arm->data;
+
+ int flag = arm->flag;
+
+ // put armature in rest position
+ if (!(arm->flag & ARM_RESTPOS)) {
+ arm->flag |= ARM_RESTPOS;
+ BKE_pose_where_is(scene, ob_arm);
+ }
+
+ for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) {
+ if (is_bone_defgroup(ob_arm, def)) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(pose, def->name);
+
+ float mat[4][4];
+ float world[4][4];
+ float inv_bind_mat[4][4];
+
+ // SECOND_LIFE_COMPATIBILITY
+ if (export_settings->second_life) {
+ // Only translations, no rotation vs armature
+ float temp[4][4];
+ unit_m4(temp);
+ copy_v3_v3(temp[3], pchan->bone->arm_mat[3]);
+ mult_m4_m4m4(world, ob_arm->obmat, temp);
+ }
+ else {
+ // make world-space matrix, arm_mat is armature-space
+ mult_m4_m4m4(world, ob_arm->obmat, pchan->bone->arm_mat);
+ }
+
+ invert_m4_m4(mat, world);
+ converter.mat4_to_dae(inv_bind_mat, mat);
+
+ source.appendValues(inv_bind_mat);
+ }
+ }
+
+ // back from rest positon
+ if (!(flag & ARM_RESTPOS)) {
+ arm->flag = flag;
+ BKE_pose_where_is(scene, ob_arm);
+ }
+
+ source.finish();
+
+ return source_id;
+}
+
+Bone *ControllerExporter::get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def)
+{
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, def->name);
+ return pchan ? pchan->bone : NULL;
+}
+
+bool ControllerExporter::is_bone_defgroup(Object *ob_arm, bDeformGroup *def)
+{
+ return get_bone_from_defgroup(ob_arm, def) != NULL;
+}
+
+std::string ControllerExporter::add_weights_source(Mesh *me, const std::string& controller_id, const std::list<float>& weights)
+{
+ std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX;
+
+ COLLADASW::FloatSourceF source(mSW);
+ source.setId(source_id);
+ source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+ source.setAccessorCount(weights.size());
+ source.setAccessorStride(1);
+
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ param.push_back("WEIGHT");
+
+ source.prepareToAppendValues();
+
+ for (std::list<float>::const_iterator i = weights.begin(); i != weights.end(); ++i) {
+ source.appendValues(*i);
+ }
+
+ source.finish();
+
+ return source_id;
+}
+
+void ControllerExporter::add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id,
+ const std::list<int>& vcounts,
+ const std::list<int>& joints)
+{
+ COLLADASW::VertexWeightsElement weightselem(mSW);
+ COLLADASW::InputList &input = weightselem.getInputList();
+
+ int offset = 0;
+ input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h
+ COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id), offset++));
+ input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::WEIGHT,
+ COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, weights_source_id), offset++));
+
+ weightselem.setCount(vcounts.size());
+
+ // write number of deformers per vertex
+ COLLADASW::PrimitivesBase::VCountList vcountlist;
+
+ vcountlist.resize(vcounts.size());
+ std::copy(vcounts.begin(), vcounts.end(), vcountlist.begin());
+
+ weightselem.prepareToAppendVCountValues();
+ weightselem.appendVertexCount(vcountlist);
+
+ weightselem.CloseVCountAndOpenVElement();
+
+ // write deformer index - weight index pairs
+ int weight_index = 0;
+ for (std::list<int>::const_iterator i = joints.begin(); i != joints.end(); ++i) {
+ weightselem.appendValues(*i, weight_index++);
+ }
+
+ weightselem.finish();
+}
diff --git a/source/blender/collada/ControllerExporter.h b/source/blender/collada/ControllerExporter.h
new file mode 100644
index 00000000000..0be51187f6f
--- /dev/null
+++ b/source/blender/collada/ControllerExporter.h
@@ -0,0 +1,127 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed,
+ * Nathan Letwory, Sukhitha Jayathilake
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ControllerExporter.h
+ * \ingroup collada
+ */
+
+#ifndef __CONTROLLEREXPORTER_H__
+#define __CONTROLLEREXPORTER_H__
+
+#include <list>
+#include <string>
+//#include <vector>
+
+#include "COLLADASWStreamWriter.h"
+#include "COLLADASWLibraryControllers.h"
+#include "COLLADASWInstanceController.h"
+#include "COLLADASWInputList.h"
+#include "COLLADASWNode.h"
+#include "COLLADASWExtraTechnique.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_listBase.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_key_types.h"
+
+#include "TransformWriter.h"
+#include "InstanceWriter.h"
+
+#include "ExportSettings.h"
+
+#include "BKE_key.h"
+
+class SceneExporter;
+
+class ControllerExporter : public COLLADASW::LibraryControllers, protected TransformWriter, protected InstanceWriter
+{
+public:
+ ControllerExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
+
+ bool is_skinned_mesh(Object *ob);
+
+ bool add_instance_controller(Object *ob);
+
+ void export_controllers(Scene *sce);
+
+ void operator()(Object *ob);
+
+private:
+ Scene *scene;
+ UnitConverter converter;
+ const ExportSettings *export_settings;
+
+#if 0
+ std::vector<Object *> written_armatures;
+
+ bool already_written(Object *ob_arm);
+
+ void wrote(Object *ob_arm);
+
+ void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce);
+#endif
+
+ std::string get_joint_sid(Bone *bone, Object *ob_arm);
+
+ std::string get_controller_id(Object *ob_arm, Object *ob);
+
+ std::string get_controller_id(Key *key, Object *ob);
+
+ // ob should be of type OB_MESH
+ // both args are required
+ void export_skin_controller(Object *ob, Object *ob_arm);
+
+ void export_morph_controller(Object *ob, Key *key);
+
+ void add_joints_element(ListBase *defbase,
+ const std::string& joints_source_id, const std::string& inv_bind_mat_source_id);
+
+ void add_bind_shape_mat(Object *ob);
+
+ std::string add_morph_targets(Key *key, Object *ob);
+
+ std::string add_morph_weights(Key *key, Object *ob);
+
+ void add_weight_extras(Key *key);
+
+ std::string add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id);
+
+ std::string add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id);
+
+ Bone *get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def);
+
+ bool is_bone_defgroup(Object *ob_arm, bDeformGroup *def);
+
+ std::string add_weights_source(Mesh *me, const std::string& controller_id,
+ const std::list<float>& weights);
+
+ void add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id,
+ const std::list<int>& vcount, const std::list<int>& joints);
+
+ void write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone);
+};
+
+#endif
diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp
index c491326519f..c03316e1fe5 100644
--- a/source/blender/collada/DocumentExporter.cpp
+++ b/source/blender/collada/DocumentExporter.cpp
@@ -123,6 +123,7 @@ extern bool bc_has_object_type(LinkNode *export_set, short obtype);
#include "ArmatureExporter.h"
#include "AnimationExporter.h"
#include "CameraExporter.h"
+#include "ControllerExporter.h"
#include "EffectExporter.h"
#include "GeometryExporter.h"
#include "ImageExporter.h"
@@ -265,16 +266,32 @@ void DocumentExporter::exportCurrentScene(Scene *sce)
// <library_animations>
AnimationExporter ae(&sw, this->export_settings);
- ae.exportAnimations(sce);
+ bool has_animations = ae.exportAnimations(sce);
// <library_controllers>
ArmatureExporter arm_exporter(&sw, this->export_settings);
- if (bc_has_object_type(export_set, OB_ARMATURE)) {
- arm_exporter.export_controllers(sce);
+ ControllerExporter controller_exporter(&sw , this->export_settings);
+ if (bc_has_object_type(export_set, OB_ARMATURE) || this->export_settings->include_shapekeys)
+ {
+ controller_exporter.export_controllers(sce);
}
// <library_visual_scenes>
+
SceneExporter se(&sw, &arm_exporter, this->export_settings);
+
+ if (has_animations && this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) {
+ // channels adressing <matrix> objects is not (yet) supported
+ // So we force usage of <location>, <translation> and <scale>
+ fprintf(stdout,
+ "For animated Ojects we must use decomposed <matrix> elements,\n" \
+ "Forcing usage of TransLocRot transformation type.");
+ se.setExportTransformationType(BC_TRANSFORMATION_TYPE_TRANSROTLOC);
+ }
+ else {
+ se.setExportTransformationType(this->export_settings->export_transformation_type);
+ }
+
se.exportScene(sce);
// <scene>
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index 084f71e0afc..49db6f033d9 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -54,6 +54,7 @@ extern "C" {
#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "BLI_fileops.h"
#include "BKE_camera.h"
#include "BKE_main.h"
@@ -76,6 +77,9 @@ extern "C" {
#include "MEM_guardedalloc.h"
+#include "WM_api.h"
+#include "WM_types.h"
+
}
#include "ExtraHandler.h"
@@ -96,11 +100,11 @@ extern "C" {
// creates empties for each imported bone on layer 2, for debugging
// #define ARMATURE_TEST
-DocumentImporter::DocumentImporter(bContext *C, const char *filename) :
+DocumentImporter::DocumentImporter(bContext *C, const ImportSettings *import_settings) :
+ import_settings(import_settings),
mImportStage(General),
- mFilename(filename),
mContext(C),
- armature_importer(&unit_converter, &mesh_importer, &anim_importer, CTX_data_scene(C)),
+ armature_importer(&unit_converter, &mesh_importer, CTX_data_scene(C)),
mesh_importer(&unit_converter, &armature_importer, CTX_data_scene(C)),
anim_importer(&unit_converter, &armature_importer, CTX_data_scene(C))
{
@@ -128,7 +132,9 @@ bool DocumentImporter::import()
// deselect all to select new objects
BKE_scene_base_deselect_all(CTX_data_scene(mContext));
- if (!root.loadDocument(mFilename)) {
+ std::string mFilename = std::string(this->import_settings->filepath);
+ const std::string encodedFilename = bc_url_encode(mFilename);
+ if (!root.loadDocument(encodedFilename)) {
fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 1st pass\n");
return false;
}
@@ -143,7 +149,7 @@ bool DocumentImporter::import()
COLLADASaxFWL::Loader loader2;
COLLADAFW::Root root2(&loader2, this);
- if (!root2.loadDocument(mFilename)) {
+ if (!root2.loadDocument(encodedFilename)) {
fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 2nd pass\n");
return false;
}
@@ -151,7 +157,8 @@ bool DocumentImporter::import()
delete ehandler;
- mesh_importer.bmeshConversion();
+ //XXX No longer needed (geometries are now created as bmesh)
+ //mesh_importer.bmeshConversion();
return true;
}
@@ -174,46 +181,68 @@ void DocumentImporter::finish()
{
if (mImportStage != General)
return;
-
+
+ Main *bmain = CTX_data_main(mContext);
+ // TODO: create a new scene except the selected <visual_scene> - use current blender scene for it
+ Scene *sce = CTX_data_scene(mContext);
+
/** TODO Break up and put into 2-pass parsing of DAE */
std::vector<const COLLADAFW::VisualScene *>::iterator it;
for (it = vscenes.begin(); it != vscenes.end(); it++) {
PointerRNA sceneptr, unit_settings;
PropertyRNA *system, *scale;
- // TODO: create a new scene except the selected <visual_scene> - use current blender scene for it
- Scene *sce = CTX_data_scene(mContext);
// for scene unit settings: system, scale_length
+
RNA_id_pointer_create(&sce->id, &sceneptr);
unit_settings = RNA_pointer_get(&sceneptr, "unit_settings");
system = RNA_struct_find_property(&unit_settings, "system");
scale = RNA_struct_find_property(&unit_settings, "scale_length");
-
- switch (unit_converter.isMetricSystem()) {
- case UnitConverter::Metric:
- RNA_property_enum_set(&unit_settings, system, USER_UNIT_METRIC);
- break;
- case UnitConverter::Imperial:
- RNA_property_enum_set(&unit_settings, system, USER_UNIT_IMPERIAL);
- break;
- default:
- RNA_property_enum_set(&unit_settings, system, USER_UNIT_NONE);
- break;
+
+ if (this->import_settings->import_units) {
+
+ switch (unit_converter.isMetricSystem()) {
+ case UnitConverter::Metric:
+ RNA_property_enum_set(&unit_settings, system, USER_UNIT_METRIC);
+ break;
+ case UnitConverter::Imperial:
+ RNA_property_enum_set(&unit_settings, system, USER_UNIT_IMPERIAL);
+ break;
+ default:
+ RNA_property_enum_set(&unit_settings, system, USER_UNIT_NONE);
+ break;
+ }
+ float unit_factor = unit_converter.getLinearMeter();
+ RNA_property_float_set(&unit_settings, scale, unit_factor);
+ fprintf(stdout, "Collada: Adjusting Blender units to Importset units: %f.\n", unit_factor);
+
}
- RNA_property_float_set(&unit_settings, scale, unit_converter.getLinearMeter());
-
- const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
+ // Write nodes to scene
+ const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
for (unsigned int i = 0; i < roots.getCount(); i++) {
- write_node(roots[i], NULL, sce, NULL, false);
+ std::vector<Object *> *objects_done;
+ objects_done = write_node(roots[i], NULL, sce, NULL, false);
+
+ if (!this->import_settings->import_units) {
+ // Match incoming scene with current unit settings
+ bc_match_scale(objects_done, *sce, unit_converter);
+ }
}
+
+ // update scene
+ DAG_relations_tag_update(bmain);
+ WM_event_add_notifier(mContext, NC_OBJECT | ND_TRANSFORM, NULL);
+
}
- mesh_importer.optimize_material_assignments();
+ mesh_importer.optimize_material_assignements();
armature_importer.set_tags_map(this->uid_tags_map);
armature_importer.make_armatures(mContext);
+ armature_importer.make_shape_keys();
+ DAG_relations_tag_update(bmain);
#if 0
armature_importer.fix_animation();
@@ -222,8 +251,9 @@ void DocumentImporter::finish()
for (std::vector<const COLLADAFW::VisualScene *>::iterator it = vscenes.begin(); it != vscenes.end(); it++) {
const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
- for (unsigned int i = 0; i < roots.getCount(); i++)
+ for (unsigned int i = 0; i < roots.getCount(); i++) {
translate_anim_recursive(roots[i], NULL, NULL);
+ }
}
if (libnode_ob.size()) {
@@ -246,8 +276,7 @@ void DocumentImporter::finish()
}
libnode_ob.clear();
- DAG_scene_sort(CTX_data_main(mContext), sce);
- DAG_ids_flush_update(CTX_data_main(mContext), 0);
+ DAG_relations_tag_update(bmain);
}
}
@@ -256,7 +285,7 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW
{
// The split in #29246, rootmap must point at actual root when
- // calculating bones in apply_curves_as_matrix.
+ // calculating bones in apply_curves_as_matrix. - actual root is the root node.
// This has to do with inverse bind poses being world space
// (the sources for skinned bones' restposes) and the way
// non-skinning nodes have their "restpose" recursively calculated.
@@ -265,7 +294,7 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW
if (par) { // && par->getType() == COLLADAFW::Node::JOINT) {
// par is root if there's no corresp. key in root_map
if (root_map.find(par->getUniqueId()) == root_map.end())
- root_map[node->getUniqueId()] = par;
+ root_map[node->getUniqueId()] = node;
else
root_map[node->getUniqueId()] = root_map[par->getUniqueId()];
}
@@ -282,13 +311,22 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW
#endif
unsigned int i;
+
//for (i = 0; i < 4; i++)
// ob =
anim_importer.translate_Animations(node, root_map, object_map, FW_object_map);
- COLLADAFW::NodePointerArray &children = node->getChildNodes();
- for (i = 0; i < children.getCount(); i++) {
- translate_anim_recursive(children[i], node, NULL);
+ if (node->getType() == COLLADAFW::Node::JOINT && par == NULL) {
+ // For Skeletons without root node we have to simulate the
+ // root node here and recursively enter the same function
+ // XXX: maybe this can be made more elegant.
+ translate_anim_recursive(node, node, parob);
+ }
+ else {
+ COLLADAFW::NodePointerArray &children = node->getChildNodes();
+ for (i = 0; i < children.getCount(); i++) {
+ translate_anim_recursive(children[i], node, NULL);
+ }
}
}
@@ -349,7 +387,7 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod
fprintf(stderr, "create <instance_node> under node id=%s from node id=%s\n", instance_node ? instance_node->getOriginalId().c_str() : NULL, source_node ? source_node->getOriginalId().c_str() : NULL);
Object *obn = BKE_object_copy(source_ob);
- obn->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
BKE_scene_base_add(sce, obn);
if (instance_node) {
@@ -376,8 +414,7 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod
anim_importer.read_node_transform(source_node, obn);
}
- DAG_scene_sort(CTX_data_main(mContext), sce);
- DAG_ids_flush_update(CTX_data_main(mContext), 0);
+ /*DAG_relations_tag_update(CTX_data_main(mContext));*/
COLLADAFW::NodePointerArray &children = source_node->getChildNodes();
if (children.getCount()) {
@@ -406,23 +443,50 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod
return obn;
}
-void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node)
+// to create constraints off node <extra> tags. Assumes only constraint data in
+// current <extra> with blender profile.
+void DocumentImporter::create_constraints(ExtraTags *et, Object *ob)
+{
+ if (et && et->isProfile("blender")) {
+ std::string name;
+ short* type = 0;
+ et->setData("type", type);
+ BKE_add_ob_constraint(ob, "Test_con", *type);
+
+ }
+}
+
+std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node)
{
Object *ob = NULL;
bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
bool read_transform = true;
+ std::string id = node->getOriginalId();
+ std::string name = node->getName();
std::vector<Object *> *objects_done = new std::vector<Object *>();
+ fprintf(stderr,
+ "Writing node id='%s', name='%s'\n",
+ id.c_str(),
+ name.c_str());
+
if (is_joint) {
- if (par) {
- Object *empty = par;
- par = bc_add_object(sce, OB_ARMATURE, NULL);
- bc_set_parent(par, empty->parent, mContext);
- //remove empty : todo
- object_map.insert(std::make_pair<COLLADAFW::UniqueId, Object *>(parent_node->getUniqueId(), par));
+ if (parent_node == NULL) {
+ // A Joint on root level is a skeleton without root node.
+ // Here we add the armature "on the fly":
+ par = bc_add_object(sce, OB_ARMATURE, std::string("Armature").c_str());
+ objects_done->push_back(par);
+ object_map.insert(std::make_pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), par));
+ node_map[node->getUniqueId()] = node;
}
armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par, sce);
+
+ if (parent_node == NULL) {
+ // for skeletons without root node all has been done above.
+ // Skeletons with root node are handled further down.
+ return objects_done;
+ }
}
else {
COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries();
@@ -442,13 +506,21 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent
while (geom_done < geom.getCount()) {
ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map,
material_texture_mapping_map);
- objects_done->push_back(ob);
+ if (ob == NULL) {
+ fprintf(stderr,
+ "<node id=\"%s\", name=\"%s\" >...contains a reference to an unknown instance_mesh.\n",
+ id.c_str(),
+ name.c_str());
+ }
+ else {
+ objects_done->push_back(ob);
+ }
++geom_done;
}
while (camera_done < camera.getCount()) {
ob = create_camera_object(camera[camera_done], sce);
if (ob == NULL) {
- std::string id = node->getOriginalId();
+ std::string id = node->getOriginalId();
std::string name = node->getName();
fprintf(stderr, "<node id=\"%s\", name=\"%s\" >...contains a reference to an unknown instance_camera.\n", id.c_str(), name.c_str());
}
@@ -487,16 +559,25 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent
read_transform = false;
}
+
// if node is empty - create empty object
// XXX empty node may not mean it is empty object, not sure about this
if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) {
- ob = bc_add_object(sce, OB_EMPTY, NULL);
+ //Check if Object is armature, by checking if immediate child is a JOINT node.
+ if (is_armature(node)) {
+ ob = bc_add_object(sce, OB_ARMATURE, name.c_str());
+ }
+ else {
+ ob = bc_add_object(sce, OB_EMPTY, NULL);
+ }
objects_done->push_back(ob);
+
}
// XXX: if there're multiple instances, only one is stored
- if (!ob) return;
+ if (!ob) return objects_done;
+
for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) {
ob = *it;
std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId();
@@ -508,6 +589,9 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent
libnode_ob.push_back(ob);
}
+
+ //create_constraints(et,ob);
+
}
for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) {
@@ -524,9 +608,19 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent
}
// if node has child nodes write them
COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
+
+ if (objects_done->size() > 0) {
+ ob = *objects_done->begin();
+ }
+ else {
+ ob = NULL;
+ }
+
for (unsigned int i = 0; i < child_nodes.getCount(); i++) {
write_node(child_nodes[i], node, sce, ob, is_library_node);
}
+
+ return objects_done;
}
/** When this method is called, the writer must write the entire visual scene.
@@ -588,7 +682,7 @@ bool DocumentImporter::writeMaterial(const COLLADAFW::Material *cmat)
return true;
const std::string& str_mat_id = cmat->getName().size() ? cmat->getName() : cmat->getOriginalId();
- Material *ma = BKE_material_add((char *)str_mat_id.c_str());
+ Material *ma = BKE_material_add(G.main, (char *)str_mat_id.c_str());
this->uid_effect_map[cmat->getInstantiatedEffect()] = ma;
this->uid_material_map[cmat->getUniqueId()] = ma;
@@ -612,9 +706,8 @@ MTex *DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::T
ma->mtex[i] = add_mtex();
ma->mtex[i]->texco = TEXCO_UV;
- ma->mtex[i]->tex = add_texture("Texture");
+ ma->mtex[i]->tex = add_texture(G.main, "Texture");
ma->mtex[i]->tex->type = TEX_IMAGE;
- ma->mtex[i]->tex->imaflag &= ~TEX_USEALPHA;
ma->mtex[i]->tex->ima = uid_image_map[ima_uid];
texindex_texarray_map[ctex.getTextureMapId()].push_back(ma->mtex[i]);
@@ -745,7 +838,6 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia
mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
if (mtex != NULL) {
mtex->mapto = MAP_ALPHA;
- mtex->tex->imaflag |= TEX_USEALPHA;
i++;
ma->spectra = ma->alpha = 0;
ma->mode |= MA_ZTRANSP | MA_TRANSP;
@@ -820,8 +912,8 @@ bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera)
cam_id = camera->getOriginalId();
cam_name = camera->getName();
- if (cam_name.size()) cam = (Camera *)BKE_camera_add((char *)cam_name.c_str());
- else cam = (Camera *)BKE_camera_add((char *)cam_id.c_str());
+ if (cam_name.size()) cam = (Camera *)BKE_camera_add(G.main, (char *)cam_name.c_str());
+ else cam = (Camera *)BKE_camera_add(G.main, (char *)cam_id.c_str());
if (!cam) {
fprintf(stderr, "Cannot create camera.\n");
@@ -933,17 +1025,29 @@ bool DocumentImporter::writeImage(const COLLADAFW::Image *image)
if (mImportStage != General)
return true;
- // XXX maybe it is necessary to check if the path is absolute or relative
- const std::string& filepath = image->getImageURI().toNativePath();
- const char *filename = (const char *)mFilename.c_str();
+ const std::string& imagepath = image->getImageURI().toNativePath();
+
char dir[FILE_MAX];
- char full_path[FILE_MAX];
-
- BLI_split_dir_part(filename, dir, sizeof(dir));
- BLI_join_dirfile(full_path, sizeof(full_path), dir, filepath.c_str());
- Image *ima = BKE_image_load_exists(full_path);
+ char absolute_path[FILE_MAX];
+ const char *workpath;
+
+ BLI_split_dir_part(this->import_settings->filepath, dir, sizeof(dir));
+ BLI_join_dirfile(absolute_path, sizeof(absolute_path), dir, imagepath.c_str());
+ if (BLI_exists(absolute_path)) {
+ workpath = absolute_path;
+ }
+ else {
+ // Maybe imagepath was already absolute ?
+ if (!BLI_exists(imagepath.c_str())) {
+ fprintf(stderr, "Image not found: %s.\n", imagepath.c_str() );
+ return true;
+ }
+ workpath = imagepath.c_str();
+ }
+
+ Image *ima = BKE_image_load_exists(workpath);
if (!ima) {
- fprintf(stderr, "Cannot create image.\n");
+ fprintf(stderr, "Cannot create image: %s\n", workpath);
return true;
}
this->uid_image_map[image->getUniqueId()] = ima;
@@ -961,16 +1065,17 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
Lamp *lamp = NULL;
std::string la_id, la_name;
- TagsMap::iterator etit;
+ ExtraTags *et = getExtraTags(light->getUniqueId());
+ /*TagsMap::iterator etit;
ExtraTags *et = 0;
etit = uid_tags_map.find(light->getUniqueId().toAscii());
if (etit != uid_tags_map.end())
- et = etit->second;
+ et = etit->second;*/
la_id = light->getOriginalId();
la_name = light->getName();
- if (la_name.size()) lamp = (Lamp *)BKE_lamp_add((char *)la_name.c_str());
- else lamp = (Lamp *)BKE_lamp_add((char *)la_id.c_str());
+ if (la_name.size()) lamp = (Lamp *)BKE_lamp_add(G.main, (char *)la_name.c_str());
+ else lamp = (Lamp *)BKE_lamp_add(G.main, (char *)la_id.c_str());
if (!lamp) {
fprintf(stderr, "Cannot create lamp.\n");
@@ -1185,3 +1290,18 @@ bool DocumentImporter::addExtraTags(const COLLADAFW::UniqueId &uid, ExtraTags *e
return true;
}
+bool DocumentImporter::is_armature(COLLADAFW::Node *node)
+{
+ COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
+ for (unsigned int i = 0; i < child_nodes.getCount(); i++) {
+ if (child_nodes[i]->getType() == COLLADAFW::Node::JOINT) {
+ return true;
+ }
+ else {
+ continue;
+ }
+ }
+
+ //no child is JOINT
+ return false;
+}
diff --git a/source/blender/collada/DocumentImporter.h b/source/blender/collada/DocumentImporter.h
index d54b8db9f00..ff0cbd44043 100644
--- a/source/blender/collada/DocumentImporter.h
+++ b/source/blender/collada/DocumentImporter.h
@@ -40,11 +40,14 @@
#include "BKE_object.h"
+#include "BKE_constraint.h"
#include "TransformReader.h"
#include "AnimationImporter.h"
#include "ArmatureImporter.h"
+#include "ControllerExporter.h"
#include "MeshImporter.h"
+#include "ImportSettings.h"
@@ -61,7 +64,7 @@ public:
Controller, //!< Second pass to collect controller data
};
/** Constructor */
- DocumentImporter(bContext *C, const char *filename);
+ DocumentImporter(bContext *C, const ImportSettings *import_settings);
/** Destructor */
~DocumentImporter();
@@ -73,9 +76,11 @@ public:
Object* create_camera_object(COLLADAFW::InstanceCamera*, Scene*);
Object* create_lamp_object(COLLADAFW::InstanceLight*, Scene*);
Object* create_instance_node(Object*, COLLADAFW::Node*, COLLADAFW::Node*, Scene*, bool);
- void write_node(COLLADAFW::Node*, COLLADAFW::Node*, Scene*, Object*, bool);
+ void create_constraints(ExtraTags *et, Object *ob);
+ std::vector<Object *> *write_node(COLLADAFW::Node*, COLLADAFW::Node*, Scene*, Object*, bool);
MTex* create_texture(COLLADAFW::EffectCommon*, COLLADAFW::Texture&, Material*, int, TexIndexTextureArrayMap&);
void write_profile_COMMON(COLLADAFW::EffectCommon*, Material*);
+
void translate_anim_recursive(COLLADAFW::Node*, COLLADAFW::Node*, Object*);
/**
@@ -128,11 +133,15 @@ public:
/** Get an extisting ExtraTags for uid */
ExtraTags* getExtraTags(const COLLADAFW::UniqueId &uid);
+ bool is_armature(COLLADAFW::Node * node);
+
+
+
private:
+ const ImportSettings *import_settings;
/** Current import stage we're in. */
ImportStage mImportStage;
- std::string mFilename;
bContext *mContext;
diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp
index e4a654dc99a..6741e92cb5c 100644
--- a/source/blender/collada/EffectExporter.cpp
+++ b/source/blender/collada/EffectExporter.cpp
@@ -323,10 +323,10 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
{
if (me->pdata.layers[i].type == CD_MTEXPOLY) {
MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
- MFace *mface = me->mface;
- for (int j = 0; j < me->totpoly; j++, mface++, txface++) {
+ MPoly *mpoly = me->mpoly;
+ for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
- Material *mat = give_current_material(ob, mface->mat_nr + 1);
+ Material *mat = give_current_material(ob, mpoly->mat_nr + 1);
if (mat != ma)
continue;
diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h
index 2504c276036..f9eb4cbc26f 100644
--- a/source/blender/collada/ExportSettings.h
+++ b/source/blender/collada/ExportSettings.h
@@ -28,6 +28,7 @@
#define __EXPORTSETTINGS_H__
#include "collada.h"
+#include "collada.h"
struct ExportSettings {
public:
@@ -37,6 +38,7 @@ public:
bool selected;
bool include_children;
bool include_armatures;
+ bool include_shapekeys;
bool deform_bones_only;
bool active_uv_only;
@@ -44,8 +46,10 @@ public:
bool include_material_textures;
bool use_texture_copies;
+ bool triangulate;
bool use_object_instantiation;
bool sort_by_name;
+ BC_export_transformation_type export_transformation_type;
bool second_life;
char *filepath;
diff --git a/source/blender/collada/ExtraHandler.cpp b/source/blender/collada/ExtraHandler.cpp
index df49b4fe8b4..7b8d315b8c5 100644
--- a/source/blender/collada/ExtraHandler.cpp
+++ b/source/blender/collada/ExtraHandler.cpp
@@ -57,7 +57,7 @@ bool ExtraHandler::textData(const char *text, size_t textLength)
if (currentElement.length() == 0 || currentExtraTags == 0) return false;
- BLI_snprintf(buf, textLength + 1, "%s", text);
+ BLI_strncpy(buf, text, textLength + 1);
currentExtraTags->addTag(currentElement, std::string(buf));
return true;
}
@@ -74,6 +74,7 @@ bool ExtraHandler::parseElement(
if (!et) {
et = new ExtraTags(std::string(profileName));
dimp->addExtraTags(uniqueId, et);
+
}
currentExtraTags = et;
return true;
diff --git a/source/blender/collada/ExtraHandler.h b/source/blender/collada/ExtraHandler.h
index 900e7b70331..aa1ae52a521 100644
--- a/source/blender/collada/ExtraHandler.h
+++ b/source/blender/collada/ExtraHandler.h
@@ -31,6 +31,7 @@
#include "COLLADASaxFWLIExtraDataCallbackHandler.h"
#include "COLLADASaxFWLFilePartLoader.h"
+#include "COLLADASWInstanceController.h"
#include "DocumentImporter.h"
#include "AnimationImporter.h"
diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp
index f33f0fa110d..669b787062a 100644
--- a/source/blender/collada/GeometryExporter.cpp
+++ b/source/blender/collada/GeometryExporter.cpp
@@ -53,10 +53,10 @@ extern "C" {
#include "collada_utils.h"
// TODO: optimize UV sets by making indexed list with duplicates removed
-GeometryExporter::GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryGeometries(sw), export_settings(export_settings) {
+GeometryExporter::GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryGeometries(sw), export_settings(export_settings)
+{
}
-
void GeometryExporter::exportGeom(Scene *sce)
{
openLibrary();
@@ -69,26 +69,22 @@ void GeometryExporter::exportGeom(Scene *sce)
}
void GeometryExporter::operator()(Object *ob)
-{
+{
// XXX don't use DerivedMesh, Mesh instead?
-
#if 0
DerivedMesh *dm = mesh_get_derived_final(mScene, ob, CD_MASK_BAREMESH);
#endif
bool use_instantiation = this->export_settings->use_object_instantiation;
- Mesh *me;
- if (this->export_settings->apply_modifiers) {
- me = bc_to_mesh_apply_modifiers(mScene, ob, this->export_settings->export_mesh_type);
- }
- else {
- me = (Mesh *)ob->data;
- }
- BKE_mesh_tessface_ensure(me);
+ Mesh *me = bc_get_mesh_copy( mScene,
+ ob,
+ this->export_settings->export_mesh_type,
+ this->export_settings->apply_modifiers,
+ this->export_settings->triangulate);
std::string geom_id = get_geometry_id(ob, use_instantiation);
std::vector<Normal> nor;
- std::vector<Face> norind;
+ std::vector<BCPolygonNormalsIndices> norind;
// Skip if linked geometry was already exported from another reference
if (use_instantiation &&
@@ -117,12 +113,13 @@ void GeometryExporter::operator()(Object *ob)
bool has_uvs = (bool)CustomData_has_layer(&me->fdata, CD_MTFACE);
// writes <source> for uv coords if mesh has uv coords
- if (has_uvs)
+ if (has_uvs) {
createTexcoordsSource(geom_id, me);
+ }
- if (has_color)
+ if (has_color) {
createVertexColorSource(geom_id, me);
-
+ }
// <vertices>
COLLADASW::Vertices verts(mSW);
@@ -132,7 +129,7 @@ void GeometryExporter::operator()(Object *ob)
input_list.push_back(input);
verts.add();
- createLooseEdgeList(ob, me, geom_id, norind);
+ createLooseEdgeList(ob, me, geom_id);
// Only create Polylists if number of faces > 0
if (me->totface > 0) {
@@ -155,22 +152,95 @@ void GeometryExporter::operator()(Object *ob)
closeGeometry();
- if (this->export_settings->apply_modifiers)
- {
- BKE_libblock_free_us(&(G.main->mesh), me);
+ if (this->export_settings->include_shapekeys) {
+ Key * key = BKE_key_from_object(ob);
+ if (key) {
+ KeyBlock * kb = (KeyBlock *)key->block.first;
+ //skip the basis
+ kb = kb->next;
+ for (; kb; kb = kb->next) {
+ BKE_key_convert_to_mesh(kb, me);
+ export_key_mesh(ob, me, kb);
+ }
+ }
}
+ BKE_libblock_free_us(&(G.main->mesh), me);
-#if 0
- dm->release(dm);
-#endif
}
+void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb)
+{
+ std::string geom_id = get_geometry_id(ob, false) + "_morph_" + translate_id(kb->name);
+ std::vector<Normal> nor;
+ std::vector<BCPolygonNormalsIndices> norind;
+
+ if (exportedGeometry.find(geom_id) != exportedGeometry.end())
+ {
+ return;
+ }
+
+ std::string geom_name = kb->name;
+
+ exportedGeometry.insert(geom_id);
+
+ bool has_color = (bool)CustomData_has_layer(&me->fdata, CD_MCOL);
+
+ create_normals(nor, norind, me);
+
+ // openMesh(geoId, geoName, meshId)
+ openMesh(geom_id, geom_name);
+
+ // writes <source> for vertex coords
+ createVertsSource(geom_id, me);
+
+ // writes <source> for normal coords
+ createNormalsSource(geom_id, me, nor);
+
+ bool has_uvs = (bool)CustomData_has_layer(&me->fdata, CD_MTFACE);
+
+ // writes <source> for uv coords if mesh has uv coords
+ if (has_uvs) {
+ createTexcoordsSource(geom_id, me);
+ }
+
+ if (has_color) {
+ createVertexColorSource(geom_id, me);
+ }
+
+ // <vertices>
+
+ COLLADASW::Vertices verts(mSW);
+ verts.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX));
+ COLLADASW::InputList &input_list = verts.getInputList();
+ COLLADASW::Input input(COLLADASW::InputSemantic::POSITION, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::POSITION));
+ input_list.push_back(input);
+ verts.add();
+
+ //createLooseEdgeList(ob, me, geom_id, norind);
+
+ // XXX slow
+ if (ob->totcol) {
+ for (int a = 0; a < ob->totcol; a++) {
+ createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
+ }
+ }
+ else {
+ createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind);
+ }
+
+ closeMesh();
+
+ if (me->flag & ME_TWOSIDED) {
+ mSW->appendTextBlock("<extra><technique profile=\"MAYA\"><double_sided>1</double_sided></technique></extra>");
+ }
+
+ closeGeometry();
+}
void GeometryExporter::createLooseEdgeList(Object *ob,
Mesh *me,
- std::string& geom_id,
- std::vector<Face>& norind)
+ std::string& geom_id)
{
MEdge *medges = me->medge;
@@ -226,10 +296,12 @@ void GeometryExporter::createPolylist(short material_index,
Object *ob,
Mesh *me,
std::string& geom_id,
- std::vector<Face>& norind)
+ std::vector<BCPolygonNormalsIndices>& norind)
{
- MFace *mfaces = me->mface;
- int totfaces = me->totface;
+
+ MPoly *mpolys = me->mpoly;
+ MLoop *mloops = me->mloop;
+ int totpolys = me->totpoly;
// <vcount>
int i;
@@ -237,17 +309,12 @@ void GeometryExporter::createPolylist(short material_index,
std::vector<unsigned long> vcount_list;
// count faces with this material
- for (i = 0; i < totfaces; i++) {
- MFace *f = &mfaces[i];
+ for (i = 0; i < totpolys; i++) {
+ MPoly *p = &mpolys[i];
- if (f->mat_nr == material_index) {
+ if (p->mat_nr == material_index) {
faces_in_polylist++;
- if (f->v4 == 0) {
- vcount_list.push_back(3);
- }
- else {
- vcount_list.push_back(4);
- }
+ vcount_list.push_back(p->totloop);
}
}
@@ -309,21 +376,19 @@ void GeometryExporter::createPolylist(short material_index,
// performs the actual writing
polylist.prepareToAppendValues();
-
-
// <p>
int texindex = 0;
- for (i = 0; i < totfaces; i++) {
- MFace *f = &mfaces[i];
+ for (i = 0; i < totpolys; i++) {
+ MPoly *p = &mpolys[i];
+ int loop_count = p->totloop;
- if (f->mat_nr == material_index) {
-
- unsigned int *v = &f->v1;
- unsigned int *n = &norind[i].v1;
- for (int j = 0; j < (f->v4 == 0 ? 3 : 4); j++) {
- polylist.appendValues(v[j]);
- polylist.appendValues(n[j]);
+ if (p->mat_nr == material_index) {
+ MLoop *l = &mloops[p->loopstart];
+ BCPolygonNormalsIndices normal_indices = norind[i];
+ for (int j = 0; j < loop_count; j++) {
+ polylist.appendValues(l[j].v);
+ polylist.appendValues(normal_indices[j]);
if (has_uvs)
polylist.appendValues(texindex + j);
@@ -332,14 +397,13 @@ void GeometryExporter::createPolylist(short material_index,
}
}
- texindex += 3;
- if (f->v4 != 0)
- texindex++;
+ texindex += loop_count;
}
polylist.finish();
}
+
// creates <source> for positions
void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me)
{
@@ -375,19 +439,14 @@ void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me)
void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me)
{
- if (!CustomData_has_layer(&me->fdata, CD_MCOL))
+ if (!CustomData_has_layer(&me->ldata, CD_MLOOPCOL))
return;
- MFace *f;
- int totcolor = 0, i, j;
-
- for (i = 0, f = me->mface; i < me->totface; i++, f++)
- totcolor += f->v4 ? 4 : 3;
COLLADASW::FloatSourceF source(mSW);
source.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::COLOR));
source.setArrayId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::COLOR) + ARRAY_ID_SUFFIX);
- source.setAccessorCount(totcolor);
+ source.setAccessorCount(me->totloop);
source.setAccessorStride(3);
COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
@@ -397,18 +456,26 @@ void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me)
source.prepareToAppendValues();
- int index = CustomData_get_active_layer_index(&me->fdata, CD_MCOL);
-
- MCol *mcol = (MCol *)me->fdata.layers[index].data;
- MCol *c = mcol;
+ int index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPCOL);
+ MCol *mcol = (MCol *)me->ldata.layers[index].data;
- for (i = 0, f = me->mface; i < me->totface; i++, c += 4, f++)
- for (j = 0; j < (f->v4 ? 4 : 3); j++)
- source.appendValues(c[j].b / 255.0f, c[j].g / 255.0f, c[j].r / 255.0f);
+ MPoly *mpoly;
+ int i;
+ for (i = 0, mpoly = me->mpoly; i < me->totpoly; i++, mpoly++) {
+ MCol *color = mcol + mpoly->loopstart;
+ for (int j = 0; j < mpoly->totloop; j++, color++) {
+ source.appendValues(
+ color->b / 255.0f,
+ color->g / 255.0f,
+ color->r / 255.0f
+ );
+ }
+ }
source.finish();
}
+
std::string GeometryExporter::makeTexcoordSourceId(std::string& geom_id, int layer_index)
{
char suffix[20];
@@ -419,38 +486,21 @@ std::string GeometryExporter::makeTexcoordSourceId(std::string& geom_id, int lay
//creates <source> for texcoords
void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
{
-#if 0
- int totfaces = dm->getNumTessFaces(dm);
- MFace *mfaces = dm->getTessFaceArray(dm);
-#endif
- int totfaces = me->totface;
- MFace *mfaces = me->mface;
-
- int totuv = 0;
- int i;
- // count totuv
- for (i = 0; i < totfaces; i++) {
- MFace *f = &mfaces[i];
- if (f->v4 == 0) {
- totuv += 3;
- }
- else {
- totuv += 4;
- }
- }
+ int totpoly = me->totpoly;
+ int totuv = me->totloop;
+ MPoly *mpolys = me->mpoly;
- int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
// write <source> for each layer
// each <source> will get id like meshName + "map-channel-1"
int map_index = 0;
- int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE)-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) {
- MTFace *tface = (MTFace *)CustomData_get_layer_n(&me->fdata, CD_MTFACE, a);
- // char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, a);
+ MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a);
COLLADASW::FloatSourceF source(mSW);
std::string layer_id = makeTexcoordSourceId(geom_id, map_index++);
@@ -465,12 +515,12 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
source.prepareToAppendValues();
- for (i = 0; i < totfaces; i++) {
- MFace *f = &mfaces[i];
-
- for (int j = 0; j < (f->v4 == 0 ? 3 : 4); j++) {
- source.appendValues(tface[i].uv[j][0],
- tface[i].uv[j][1]);
+ for (int index = 0; index < totpoly; index++) {
+ MPoly *mpoly = mpolys+index;
+ MLoopUV *mloop = mloops+mpoly->loopstart;
+ for (int j = 0; j < mpoly->totloop; j++) {
+ source.appendValues(mloop[j].uv[0],
+ mloop[j].uv[1]);
}
}
@@ -510,53 +560,54 @@ void GeometryExporter::createNormalsSource(std::string geom_id, Mesh *me, std::v
source.finish();
}
-void GeometryExporter::create_normals(std::vector<Normal> &nor, std::vector<Face> &ind, Mesh *me)
+void GeometryExporter::create_normals(std::vector<Normal> &normals, std::vector<BCPolygonNormalsIndices> &polygons_normals, Mesh *me)
{
- int i, j, v;
- MVert *vert = me->mvert;
- std::map<unsigned int, unsigned int> nshar;
-
- for (i = 0; i < me->totface; i++) {
- MFace *fa = &me->mface[i];
- Face f;
- unsigned int *nn = &f.v1;
- unsigned int *vv = &fa->v1;
-
- memset(&f, 0, sizeof(f));
- v = fa->v4 == 0 ? 3 : 4;
-
- if (!(fa->flag & ME_SMOOTH)) {
- Normal n;
- if (v == 4)
- normal_quad_v3(&n.x, vert[fa->v1].co, vert[fa->v2].co, vert[fa->v3].co, vert[fa->v4].co);
- else
- normal_tri_v3(&n.x, vert[fa->v1].co, vert[fa->v2].co, vert[fa->v3].co);
- nor.push_back(n);
+ std::map<unsigned int, unsigned int> shared_normal_indices;
+ int last_normal_index = -1;
+
+ MVert *verts = me->mvert;
+ MLoop *mloops = me->mloop;
+ for (int poly_index = 0; poly_index < me->totpoly; poly_index++) {
+ MPoly *mpoly = &me->mpoly[poly_index];
+
+ if (!(mpoly->flag & ME_SMOOTH)) {
+ // For flat faces use face normal as vertex normal:
+
+ float vector[3];
+ BKE_mesh_calc_poly_normal(mpoly, mloops, verts, vector);
+
+ Normal n = { vector[0], vector[1], vector[2] };
+ normals.push_back(n);
+ last_normal_index++;
}
- for (j = 0; j < v; j++) {
- if (fa->flag & ME_SMOOTH) {
- if (nshar.find(*vv) != nshar.end())
- *nn = nshar[*vv];
+
+ 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 {
- Normal n = {
- (float)vert[*vv].no[0] / 32767.0f,
- (float)vert[*vv].no[1] / 32767.0f,
- (float)vert[*vv].no[2] / 32767.0f
- };
- nor.push_back(n);
- *nn = (unsigned int)nor.size() - 1;
- nshar[*vv] = *nn;
+
+ float vector[3];
+ normal_short_to_float_v3(vector, verts[vertex_index].no);
+
+ Normal n = { vector[0], vector[1], vector[2] };
+ normals.push_back(n);
+ last_normal_index++;
+
+ poly_indices.add_index(last_normal_index);
+ shared_normal_indices[vertex_index] = last_normal_index;
}
- vv++;
}
else {
- *nn = (unsigned int)nor.size() - 1;
+ poly_indices.add_index(last_normal_index);
}
- nn++;
}
- ind.push_back(f);
+ polygons_normals.push_back(poly_indices);
}
}
@@ -579,19 +630,4 @@ COLLADASW::URI GeometryExporter::makeUrl(std::string id)
return COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, id);
}
-#if 0
-int GeometryExporter::getTriCount(MFace *faces, int totface)
-{
- int i;
- int tris = 0;
- for (i = 0; i < totface; i++) {
- // if quad
- if (faces[i].v4 != 0)
- tris += 2;
- else
- tris++;
- }
- return tris;
-}
-#endif
diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h
index 7161bb751dd..3719072fe0c 100644
--- a/source/blender/collada/GeometryExporter.h
+++ b/source/blender/collada/GeometryExporter.h
@@ -39,8 +39,12 @@
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_key_types.h"
#include "ExportSettings.h"
+#include "collada_utils.h"
+
+#include "BKE_key.h"
extern Object *bc_get_highest_selected_ancestor_or_self(Object *ob);
@@ -68,8 +72,7 @@ public:
void createLooseEdgeList(Object *ob,
Mesh *me,
- std::string& geom_id,
- std::vector<Face>& norind);
+ std::string& geom_id);
// powerful because it handles both cases when there is material and when there's not
void createPolylist(short material_index,
@@ -78,7 +81,7 @@ public:
Object *ob,
Mesh *me,
std::string& geom_id,
- std::vector<Face>& norind);
+ std::vector<BCPolygonNormalsIndices>& norind);
// creates <source> for positions
void createVertsSource(std::string geom_id, Mesh *me);
@@ -89,19 +92,21 @@ public:
//creates <source> for texcoords
void createTexcoordsSource(std::string geom_id, Mesh *me);
+ void createTesselatedTexcoordsSource(std::string geom_id, Mesh *me);
//creates <source> for normals
void createNormalsSource(std::string geom_id, Mesh *me, std::vector<Normal>& nor);
- void create_normals(std::vector<Normal> &nor, std::vector<Face> &ind, Mesh *me);
+ void create_normals(std::vector<Normal> &nor, std::vector<BCPolygonNormalsIndices> &ind, Mesh *me);
std::string getIdBySemantics(std::string geom_id, COLLADASW::InputSemantic::Semantics type, std::string other_suffix = "");
COLLADASW::URI getUrlBySemantics(std::string geom_id, COLLADASW::InputSemantic::Semantics type, std::string other_suffix = "");
COLLADASW::URI makeUrl(std::string id);
+
+ void export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb);
- /* int getTriCount(MFace *faces, int totface);*/
private:
std::set<std::string> exportedGeometry;
@@ -112,7 +117,7 @@ private:
struct GeometryFunctor {
// f should have
- // void operator()(Object* ob)
+ // void operator()(Object *ob)
template<class Functor>
void forEachMeshObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set)
{
diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp
index aba290f5ce4..55fe2034869 100644
--- a/source/blender/collada/ImageExporter.cpp
+++ b/source/blender/collada/ImageExporter.cpp
@@ -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.imtype);
+ BKE_add_image_extension(export_file, &imageFormat);
BLI_join_dirfile(export_path, sizeof(export_path), export_dir, export_file);
diff --git a/intern/cycles/util/util_attribute.h b/source/blender/collada/ImportSettings.cpp
index 334864c7f44..74607787f25 100644
--- a/intern/cycles/util/util_attribute.h
+++ b/source/blender/collada/ImportSettings.cpp
@@ -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
@@ -14,18 +14,14 @@
* You should have received a copy of the GNU General Public 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): Gaia Clary.
+ *
+ * ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __UTIL_ATTRIBUTE_H__
-#define __UTIL_ATTRIBUTE_H__
-
-#include "util_types.h"
-
-CCL_NAMESPACE_BEGIN
-
-const char *attribute_standard_name(AttributeStandard std);
-
-CCL_NAMESPACE_END
-
-#endif /* __UTIL_ATTRIBUTE_H__ */
+/** \file blender/collada/ExportSettings.cpp
+ * \ingroup collada
+ */
+#include "ImportSettings.h"
diff --git a/source/blender/collada/ImportSettings.h b/source/blender/collada/ImportSettings.h
new file mode 100644
index 00000000000..3f3a9fb354e
--- /dev/null
+++ b/source/blender/collada/ImportSettings.h
@@ -0,0 +1,39 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Gaia Clary
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ExportSettings.h
+ * \ingroup collada
+ */
+
+#ifndef __IMPORTSETTINGS_H__
+#define __IMPORTSETTINGS_H__
+
+#include "collada.h"
+
+struct ImportSettings {
+public:
+ bool import_units;
+
+ char *filepath;
+};
+
+#endif
diff --git a/source/blender/collada/MaterialExporter.h b/source/blender/collada/MaterialExporter.h
index 09d10846b53..ef44bf8a03e 100644
--- a/source/blender/collada/MaterialExporter.h
+++ b/source/blender/collada/MaterialExporter.h
@@ -88,7 +88,7 @@ public:
struct MaterialFunctor {
// calls f for each unique material linked to each object in sce
// f should have
- // void operator()(Material* ma)
+ // void operator()(Material *ma)
template<class Functor>
void forEachMaterialInExportSet(Scene *sce, Functor &f, LinkNode *export_set)
{
diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp
index de8d1e85eb9..c3efac55fe7 100644
--- a/source/blender/collada/MeshImporter.cpp
+++ b/source/blender/collada/MeshImporter.cpp
@@ -63,10 +63,9 @@ extern "C" {
// get node name, or fall back to original id if not present (name is optional)
template<class T>
-static const char *bc_get_dae_name(T *node)
+static const std::string bc_get_dae_name(T *node)
{
- const std::string& name = node->getName();
- return name.size() ? name.c_str() : node->getOriginalId().c_str();
+ return node->getName().size() ? node->getName(): node->getOriginalId();
}
static const char *bc_primTypeToStr(COLLADAFW::MeshPrimitive::PrimitiveType type)
@@ -174,83 +173,30 @@ void UVDataWrapper::getUV(int uv_index, float *uv)
}
}
-void MeshImporter::set_face_indices(MFace *mface, unsigned int *indices, bool quad)
-{
- mface->v1 = indices[0];
- mface->v2 = indices[1];
- mface->v3 = indices[2];
- if (quad) mface->v4 = indices[3];
- else mface->v4 = 0;
-#ifdef COLLADA_DEBUG
- // fprintf(stderr, "%u, %u, %u\n", indices[0], indices[1], indices[2]);
-#endif
-}
-
-// not used anymore, test_index_face from blenkernel is better
-#if 0
-// change face indices order so that v4 is not 0
-void MeshImporter::rotate_face_indices(MFace *mface)
-{
- mface->v4 = mface->v1;
- mface->v1 = mface->v2;
- mface->v2 = mface->v3;
- mface->v3 = 0;
+MeshImporter::MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Scene *sce) : unitconverter(unitconv), scene(sce), armature_importer(arm) {
}
-#endif
-void MeshImporter::set_face_uv(MTFace *mtface, UVDataWrapper &uvs,
- COLLADAFW::IndexList& index_list, unsigned int *tris_indices)
+void MeshImporter::set_poly_indices(MPoly *mpoly, MLoop *mloop, int loop_index, unsigned int *indices, int loop_count)
{
- // per face vertex indices, this means for quad we have 4 indices, not 8
- COLLADAFW::UIntValuesArray& indices = index_list.getIndices();
+ mpoly->loopstart = loop_index;
+ mpoly->totloop = loop_count;
- uvs.getUV(indices[tris_indices[0]], mtface->uv[0]);
- uvs.getUV(indices[tris_indices[1]], mtface->uv[1]);
- uvs.getUV(indices[tris_indices[2]], mtface->uv[2]);
+ for (int index=0; index < loop_count; index++) {
+ mloop->v = indices[index];
+ mloop++;
+ }
}
-void MeshImporter::set_face_uv(MTFace *mtface, UVDataWrapper &uvs,
- COLLADAFW::IndexList& index_list, int index, bool quad)
+void MeshImporter::set_face_uv(MLoopUV *mloopuv, UVDataWrapper &uvs,
+ int start_index, COLLADAFW::IndexList& index_list, int count)
{
// per face vertex indices, this means for quad we have 4 indices, not 8
COLLADAFW::UIntValuesArray& indices = index_list.getIndices();
- uvs.getUV(indices[index + 0], mtface->uv[0]);
- uvs.getUV(indices[index + 1], mtface->uv[1]);
- uvs.getUV(indices[index + 2], mtface->uv[2]);
-
- if (quad) uvs.getUV(indices[index + 3], mtface->uv[3]);
-
-#ifdef COLLADA_DEBUG
- if (quad) {
- fprintf(stderr, "face uv:\n"
- "((%d, %d, %d, %d))\n"
- "((%.1f, %.1f), (%.1f, %.1f), (%.1f, %.1f), (%.1f, %.1f))\n",
-
- indices[index + 0],
- indices[index + 1],
- indices[index + 2],
- indices[index + 3],
-
- mtface->uv[0][0], mtface->uv[0][1],
- mtface->uv[1][0], mtface->uv[1][1],
- mtface->uv[2][0], mtface->uv[2][1],
- mtface->uv[3][0], mtface->uv[3][1]);
- }
- else {
- fprintf(stderr, "face uv:\n"
- "((%d, %d, %d))\n"
- "((%.1f, %.1f), (%.1f, %.1f), (%.1f, %.1f))\n",
-
- indices[index + 0],
- indices[index + 1],
- indices[index + 2],
-
- mtface->uv[0][0], mtface->uv[0][1],
- mtface->uv[1][0], mtface->uv[1][1],
- mtface->uv[2][0], mtface->uv[2][1]);
+ for (int index = 0; index < count; index++) {
+ int uv_index = indices[index+start_index];
+ uvs.getUV(uv_index, mloopuv[index].uv);
}
-#endif
}
#ifdef COLLADA_DEBUG
@@ -268,7 +214,7 @@ bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh) // checks if mesh has su
{
COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
- const char *name = bc_get_dae_name(mesh);
+ const std::string &name = bc_get_dae_name(mesh);
for (unsigned i = 0; i < prim_arr.getCount(); i++) {
@@ -287,7 +233,7 @@ bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh) // checks if mesh has su
int count = vca[j];
if (count < 3) {
fprintf(stderr, "Primitive %s in %s has at least one face with vertex count < 3\n",
- type_str, name);
+ type_str, name.c_str());
return false;
}
}
@@ -305,7 +251,7 @@ bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh) // checks if mesh has su
}
if (mesh->getPositions().empty()) {
- fprintf(stderr, "Mesh %s has no vertices.\n", name);
+ fprintf(stderr, "Mesh %s has no vertices.\n", name.c_str());
return false;
}
@@ -330,91 +276,6 @@ void MeshImporter::read_vertices(COLLADAFW::Mesh *mesh, Mesh *me)
}
}
-int MeshImporter::triangulate_poly(unsigned int *indices, int totvert, MVert *verts, std::vector<unsigned int>& tri)
-{
- ListBase dispbase;
- DispList *dl;
- float *vert;
- int i = 0;
-
- dispbase.first = dispbase.last = NULL;
-
- dl = (DispList *)MEM_callocN(sizeof(DispList), "poly disp");
- dl->nr = totvert;
- dl->type = DL_POLY;
- dl->parts = 1;
- dl->verts = vert = (float *)MEM_callocN(totvert * 3 * sizeof(float), "poly verts");
- dl->index = (int *)MEM_callocN(sizeof(int) * 3 * totvert, "dl index");
-
- BLI_addtail(&dispbase, dl);
-
- for (i = 0; i < totvert; i++) {
- copy_v3_v3(vert, verts[indices[i]].co);
- vert += 3;
- }
-
- BKE_displist_fill(&dispbase, &dispbase, 0);
-
- int tottri = 0;
- dl = (DispList *)dispbase.first;
-
- if (dl->type == DL_INDEX3) {
- tottri = dl->parts;
-
- int *index = dl->index;
- for (i = 0; i < tottri; i++) {
- int t[3] = {*index, *(index + 1), *(index + 2)};
-
- std::sort(t, t + 3);
-
- tri.push_back(t[0]);
- tri.push_back(t[1]);
- tri.push_back(t[2]);
-
- index += 3;
- }
- }
-
- BKE_displist_free(&dispbase);
-
- return tottri;
-}
-
-int MeshImporter::count_new_tris(COLLADAFW::Mesh *mesh, Mesh *me)
-{
- COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
- unsigned int i;
- int tottri = 0;
-
- for (i = 0; i < prim_arr.getCount(); i++) {
-
- COLLADAFW::MeshPrimitive *mp = prim_arr[i];
- int type = mp->getPrimitiveType();
- size_t prim_totface = mp->getFaceCount();
- unsigned int *indices = mp->getPositionIndices().getData();
-
- if (type == COLLADAFW::MeshPrimitive::POLYLIST ||
- type == COLLADAFW::MeshPrimitive::POLYGONS)
- {
- COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
- COLLADAFW::Polygons::VertexCountArray& vcounta = mpvc->getGroupedVerticesVertexCountArray();
-
- for (unsigned int j = 0; j < prim_totface; j++) {
- int vcount = vcounta[j];
-
- if (vcount > 4) {
- std::vector<unsigned int> tri;
-
- // tottri += triangulate_poly(indices, vcount, me->mvert, tri) - 1; // XXX why - 1?!
- tottri += triangulate_poly(indices, vcount, me->mvert, tri);
- }
-
- indices += vcount;
- }
- }
- }
- return tottri;
-}
// =====================================================================
// condition 1: The Primitive has normals
@@ -472,10 +333,11 @@ bool MeshImporter::primitive_has_faces(COLLADAFW::MeshPrimitive *mp) {
// hint: This is done because mesh->getFacesCount() does
// count loose edges as extra faces, which is not what we want here.
// =================================================================
-void MeshImporter::allocate_face_data(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris)
+void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me)
{
- COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
- int total_facecount = 0;
+ COLLADAFW::MeshPrimitiveArray& prim_arr = collada_mesh->getMeshPrimitives();
+ int total_poly_count = 0;
+ int total_loop_count = 0;
// collect edge_count and face_count from all parts
for (int i = 0; i < prim_arr.getCount(); i++) {
@@ -486,21 +348,76 @@ void MeshImporter::allocate_face_data(COLLADAFW::Mesh *mesh, Mesh *me, int new_t
case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
case COLLADAFW::MeshPrimitive::POLYLIST:
case COLLADAFW::MeshPrimitive::POLYGONS: {
- size_t prim_totface = mp->getFaceCount();
- total_facecount += prim_totface;
+
+ COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
+ size_t prim_poly_count = mpvc->getFaceCount();
+
+ size_t prim_loop_count = 0;
+ for (int index=0; index < prim_poly_count; index++) {
+ prim_loop_count += get_vertex_count(mpvc, index);
+ }
+
+ total_poly_count += prim_poly_count;
+ total_loop_count += prim_loop_count;
break;
}
default: break;
}
}
- // allocate space for faces
- if (total_facecount > 0) {
- me->totface = total_facecount + new_tris;
- me->mface = (MFace *)CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface);
+ // Add the data containers
+ if (total_poly_count > 0) {
+ me->totpoly = total_poly_count;
+ me->totloop = total_loop_count;
+ me->mpoly = (MPoly *)CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, me->totpoly);
+ me->mloop = (MLoop *)CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, me->totloop);
+
+ unsigned int totuvset = collada_mesh->getUVCoords().getInputInfosArray().getCount();
+ for (int i = 0; i < totuvset; i++) {
+ if (collada_mesh->getUVCoords().getLength(i) == 0) {
+ totuvset = 0;
+ break;
+ }
+ }
+
+ if (totuvset > 0) {
+ for (int i = 0; i < totuvset; i++) {
+ COLLADAFW::MeshVertexData::InputInfos *info = collada_mesh->getUVCoords().getInputInfosArray()[i];
+ COLLADAFW::String &uvname = info->mName;
+ // Allocate space for UV_data
+ CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, uvname.c_str());
+ CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, uvname.c_str());
+ }
+ // activate the first uv map
+ me->mtpoly = (MTexPoly *)CustomData_get_layer_n(&me->pdata, CD_MTEXPOLY, 0);
+ me->mloopuv = (MLoopUV *) CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, 0);
+ }
}
}
+unsigned int MeshImporter::get_vertex_count(COLLADAFW::Polygons *mp, int index) {
+ int type = mp->getPrimitiveType();
+ int result;
+ switch (type) {
+ case COLLADAFW::MeshPrimitive::TRIANGLES:
+ case COLLADAFW::MeshPrimitive::TRIANGLE_FANS: {
+ result = 3;
+ break;
+ }
+ case COLLADAFW::MeshPrimitive::POLYLIST:
+ case COLLADAFW::MeshPrimitive::POLYGONS: {
+ result = mp->getGroupedVerticesVertexCountArray()[index];
+ break;
+ }
+ default: {
+ result = -1;
+ break;
+ }
+ }
+ return result;
+}
+
+
unsigned int MeshImporter::get_loose_edge_count(COLLADAFW::Mesh *mesh) {
COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
int loose_edge_count = 0;
@@ -548,7 +465,7 @@ void MeshImporter::mesh_add_edges(Mesh *mesh, int len)
CustomData_free(&mesh->edata, mesh->totedge);
mesh->edata = edata;
- mesh_update_customdata_pointers(mesh, FALSE); /* new edges don't change tessellation */
+ BKE_mesh_update_customdata_pointers(mesh, false); /* new edges don't change tessellation */
/* set default flags */
medge = &mesh->medge[mesh->totedge];
@@ -607,256 +524,118 @@ void MeshImporter::read_lines(COLLADAFW::Mesh *mesh, Mesh *me)
//
// TODO: import uv set names
// ========================================================================
-void MeshImporter::read_faces(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris) //TODO:: Refactor. Possibly replace by iterators
+void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
{
unsigned int i;
- allocate_face_data(mesh, me, new_tris);
-
- // allocate UV Maps
- unsigned int totuvset = mesh->getUVCoords().getInputInfosArray().getCount();
-
- for (i = 0; i < totuvset; i++) {
- if (mesh->getUVCoords().getLength(i) == 0) {
- totuvset = 0;
- break;
- }
- }
-
- for (i = 0; i < totuvset; i++) {
- COLLADAFW::MeshVertexData::InputInfos *info = mesh->getUVCoords().getInputInfosArray()[i];
- CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_CALLOC, NULL, me->totface, info->mName.c_str());
- //this->set_layername_map[i] = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i);
- }
-
- // activate the first uv map
- if (totuvset) me->mtface = (MTFace *)CustomData_get_layer_n(&me->fdata, CD_MTFACE, 0);
-
- UVDataWrapper uvs(mesh->getUVCoords());
+ allocate_poly_data(collada_mesh, me);
-#ifdef COLLADA_DEBUG
- // uvs.print();
-#endif
+ UVDataWrapper uvs(collada_mesh->getUVCoords());
- MFace *mface = me->mface;
+ MPoly *mpoly = me->mpoly;
+ MLoop *mloop = me->mloop;
+ int loop_index = 0;
MaterialIdPrimitiveArrayMap mat_prim_map;
- int face_index = 0;
-
- COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
-
- COLLADAFW::MeshVertexData& nor = mesh->getNormals();
+ COLLADAFW::MeshPrimitiveArray& prim_arr = collada_mesh->getMeshPrimitives();
+ COLLADAFW::MeshVertexData& nor = collada_mesh->getNormals();
for (i = 0; i < prim_arr.getCount(); i++) {
COLLADAFW::MeshPrimitive *mp = prim_arr[i];
// faces
- size_t prim_totface = mp->getFaceCount();
- unsigned int *indices = mp->getPositionIndices().getData();
- unsigned int *nind = mp->getNormalIndices().getData();
+ size_t prim_totpoly = mp->getFaceCount();
+ 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);
- int type = mp->getPrimitiveType();
- int index = 0;
+ int collada_meshtype = mp->getPrimitiveType();
- // since we cannot set mface->mat_nr here, we store a portion of me->mface in Primitive
- Primitive prim = {mface, 0};
+ // since we cannot set mpoly->mat_nr here, we store a portion of me->mpoly in Primitive
+ Primitive prim = {mpoly, 0};
COLLADAFW::IndexListArray& index_list_array = mp->getUVCoordIndicesArray();
-#ifdef COLLADA_DEBUG
- /*
- fprintf(stderr, "Primitive %d:\n", i);
- for (unsigned int j = 0; j < totuvset; j++) {
- print_index_list(*index_list_array[j]);
- }
- */
-#endif
-
- if (type == COLLADAFW::MeshPrimitive::TRIANGLES) {
- for (unsigned int j = 0; j < prim_totface; j++) {
-
- set_face_indices(mface, indices, false);
- indices += 3;
-
-#if 0
- for (unsigned int k = 0; k < totuvset; k++) {
- if (!index_list_array.empty() && index_list_array[k]) {
- // get mtface by face index and uv set index
- MTFace *mtface = (MTFace *)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k);
- set_face_uv(&mtface[face_index], uvs, k, *index_list_array[k], index, false);
- }
- }
-#else
- for (unsigned int k = 0; k < index_list_array.getCount(); k++) {
- // get mtface by face index and uv set index
- MTFace *mtface = (MTFace *)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k);
- set_face_uv(&mtface[face_index], uvs, *index_list_array[k], index, false);
- }
-#endif
-
- test_index_face(mface, &me->fdata, face_index, 3);
-
- if (mp_has_normals) {
- if (!flat_face(nind, nor, 3))
- mface->flag |= ME_SMOOTH;
-
- nind += 3;
- }
-
- index += 3;
- mface++;
- face_index++;
- prim.totface++;
- }
- }
-
// If MeshPrimitive is TRIANGLE_FANS we split it into triangles
// The first trifan vertex will be the first vertex in every triangle
- if (type == COLLADAFW::MeshPrimitive::TRIANGLE_FANS) {
+ // XXX The proper function of TRIANGLE_FANS is not tested!!!
+ // XXX In particular the handling of the normal_indices looks very wrong to me
+ if (collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLE_FANS) {
unsigned grouped_vertex_count = mp->getGroupedVertexElementsCount();
for (unsigned int group_index = 0; group_index < grouped_vertex_count; group_index++) {
- unsigned int first_vertex = indices[0]; // Store first trifan vertex
- unsigned int first_normal = nind[0]; // Store first trifan vertex normal
+ unsigned int first_vertex = position_indices[0]; // Store first trifan vertex
+ unsigned int first_normal = normal_indices[0]; // Store first trifan vertex normal
unsigned int vertex_count = mp->getGroupedVerticesVertexCount(group_index);
for (unsigned int vertex_index = 0; vertex_index < vertex_count - 2; vertex_index++) {
// For each triangle store indeces of its 3 vertices
- unsigned int triangle_vertex_indices[3] = {first_vertex, indices[1], indices[2]};
- set_face_indices(mface, triangle_vertex_indices, false);
- test_index_face(mface, &me->fdata, face_index, 3);
+ unsigned int triangle_vertex_indices[3] = {first_vertex, position_indices[1], position_indices[2]};
+ set_poly_indices(mpoly, mloop, loop_index, triangle_vertex_indices, 3);
if (mp_has_normals) { // vertex normals, same inplementation as for the triangles
// the same for vertces normals
- unsigned int vertex_normal_indices[3] = {first_normal, nind[1], nind[2]};
- if (!flat_face(vertex_normal_indices, nor, 3))
- mface->flag |= ME_SMOOTH;
- nind++;
+ unsigned int vertex_normal_indices[3] = {first_normal, normal_indices[1], normal_indices[2]};
+ if (!is_flat_face(vertex_normal_indices, nor, 3))
+ mpoly->flag |= ME_SMOOTH;
+ normal_indices++;
}
- mface++; // same inplementation as for the triangles
- indices++;
- face_index++;
- prim.totface++;
+ mpoly++;
+ mloop += 3;
+ loop_index += 3;
+ prim.totpoly++;
+
}
// Moving cursor to the next triangle fan.
if (mp_has_normals)
- nind += 2;
+ normal_indices += 2;
- indices += 2;
+ position_indices += 2;
}
}
- else if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) {
- COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
- COLLADAFW::Polygons::VertexCountArray& vcounta = mpvc->getGroupedVerticesVertexCountArray();
- for (unsigned int j = 0; j < prim_totface; j++) {
+ if (collada_meshtype == COLLADAFW::MeshPrimitive::POLYLIST ||
+ collada_meshtype == COLLADAFW::MeshPrimitive::POLYGONS ||
+ collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLES) {
+ COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
+ for (unsigned int j = 0; j < prim_totpoly; j++) {
- // face
- int vcount = vcounta[j];
- if (vcount == 3 || vcount == 4) {
-
- set_face_indices(mface, indices, vcount == 4);
-
- // set mtface for each uv set
- // it is assumed that all primitives have equal number of UV sets
-
-#if 0
- for (unsigned int k = 0; k < totuvset; k++) {
- if (!index_list_array.empty() && index_list_array[k]) {
- // get mtface by face index and uv set index
- MTFace *mtface = (MTFace *)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k);
- set_face_uv(&mtface[face_index], uvs, k, *index_list_array[k], index, mface->v4 != 0);
- }
- }
-#else
- for (unsigned int k = 0; k < index_list_array.getCount(); k++) {
- // get mtface by face index and uv set index
- MTFace *mtface = (MTFace *)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k);
- set_face_uv(&mtface[face_index], uvs, *index_list_array[k], index, vcount == 4);
- }
-#endif
-
- test_index_face(mface, &me->fdata, face_index, vcount);
-
- if (mp_has_normals) {
- if (!flat_face(nind, nor, vcount))
- mface->flag |= ME_SMOOTH;
+ // Vertices in polygon:
+ int vcount = get_vertex_count(mpvc, j);
+ set_poly_indices(mpoly, mloop, loop_index, position_indices, vcount);
- nind += vcount;
- }
-
- mface++;
- face_index++;
- prim.totface++;
-
- }
- else {
- std::vector<unsigned int> tri;
-
- triangulate_poly(indices, vcount, me->mvert, tri);
-
- for (unsigned int k = 0; k < tri.size() / 3; k++) {
- int v = k * 3;
- unsigned int uv_indices[3] = {
- index + tri[v],
- index + tri[v + 1],
- index + tri[v + 2]
- };
- unsigned int tri_indices[3] = {
- indices[tri[v]],
- indices[tri[v + 1]],
- indices[tri[v + 2]]
- };
-
- set_face_indices(mface, tri_indices, false);
-
-#if 0
- for (unsigned int l = 0; l < totuvset; l++) {
- if (!index_list_array.empty() && index_list_array[l]) {
- // get mtface by face index and uv set index
- MTFace *mtface = (MTFace *)CustomData_get_layer_n(&me->fdata, CD_MTFACE, l);
- set_face_uv(&mtface[face_index], uvs, l, *index_list_array[l], uv_indices);
- }
- }
-#else
- for (unsigned int l = 0; l < index_list_array.getCount(); l++) {
- int uvset_index = index_list_array[l]->getSetIndex();
-
- // get mtface by face index and uv set index
- MTFace *mtface = (MTFace *)CustomData_get_layer_n(&me->fdata, CD_MTFACE, uvset_index);
- set_face_uv(&mtface[face_index], uvs, *index_list_array[l], uv_indices);
- }
-#endif
+ for (unsigned int l = 0; l < index_list_array.getCount(); l++) {
+ int uvset_index = index_list_array[l]->getSetIndex();
- test_index_face(mface, &me->fdata, face_index, 3);
-
- if (mp_has_normals) {
- unsigned int ntri[3] = {nind[tri[v]], nind[tri[v + 1]], nind[tri[v + 2]]};
+ // get mtface by face index and uv set index
+ MLoopUV *mloopuv = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, uvset_index);
- if (!flat_face(ntri, nor, 3))
- mface->flag |= ME_SMOOTH;
- }
-
- mface++;
- face_index++;
- prim.totface++;
- }
+ set_face_uv(mloopuv+loop_index, uvs, loop_index, *index_list_array[l], vcount);
+ }
- if (mp_has_normals)
- nind += vcount;
+ if (mp_has_normals) {
+ if (!is_flat_face(normal_indices, nor, vcount))
+ mpoly->flag |= ME_SMOOTH;
}
+
+ mpoly++;
+ mloop += vcount;
+ loop_index += vcount;
+ prim.totpoly++;
+
+ if (mp_has_normals)
+ normal_indices += vcount;
- index += vcount;
- indices += vcount;
+ position_indices += vcount;
}
}
- else if (type == COLLADAFW::MeshPrimitive::LINES) {
+
+ else if (collada_meshtype == COLLADAFW::MeshPrimitive::LINES) {
continue; // read the lines later after all the rest is done
}
@@ -864,7 +643,7 @@ void MeshImporter::read_faces(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris) //T
mat_prim_map[mp->getMaterialId()].push_back(prim);
}
- geom_uid_mat_mapping_map[mesh->getUniqueId()] = mat_prim_map;
+ geom_uid_mat_mapping_map[collada_mesh->getUniqueId()] = mat_prim_map;
}
void MeshImporter::get_vector(float v[3], COLLADAFW::MeshVertexData& arr, int i, int stride)
@@ -897,8 +676,7 @@ void MeshImporter::get_vector(float v[3], COLLADAFW::MeshVertexData& arr, int i,
break;
}
}
-
-bool MeshImporter::flat_face(unsigned int *nind, COLLADAFW::MeshVertexData& nor, int count)
+bool MeshImporter::is_flat_face(unsigned int *nind, COLLADAFW::MeshVertexData& nor, int count)
{
float a[3], b[3];
@@ -920,8 +698,6 @@ bool MeshImporter::flat_face(unsigned int *nind, COLLADAFW::MeshVertexData& nor,
return true;
}
-MeshImporter::MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Scene *sce) : unitconverter(unitconv), scene(sce), armature_importer(arm) {
-}
void MeshImporter::bmeshConversion()
{
@@ -930,10 +706,9 @@ void MeshImporter::bmeshConversion()
{
if ((*m).second) {
Mesh *me = (*m).second;
- BKE_mesh_convert_mfaces_to_mpolys(me);
BKE_mesh_tessface_clear(me);
-
BKE_mesh_calc_normals_mapping(me->mvert, me->totvert, me->mloop, me->mpoly, me->totloop, me->totpoly, NULL, NULL, 0, NULL, NULL);
+ //BKE_mesh_validate(me, 1);
}
}
}
@@ -946,6 +721,20 @@ Object *MeshImporter::get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid
return NULL;
}
+Mesh *MeshImporter::get_mesh_by_geom_uid(const COLLADAFW::UniqueId& mesh_uid)
+{
+ if (uid_mesh_map.find(mesh_uid) != uid_mesh_map.end())
+ return uid_mesh_map[mesh_uid];
+ return NULL;
+}
+
+std::string *MeshImporter::get_geometry_name(const std::string &mesh_name)
+{
+ if (this->mesh_geom_map.find(mesh_name) != this->mesh_geom_map.end())
+ return &this->mesh_geom_map[mesh_name];
+ return NULL;
+}
+
MTex *MeshImporter::assign_textures_to_uvlayer(COLLADAFW::TextureCoordinateBinding &ctexture,
Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map,
MTex *color_texture)
@@ -1061,7 +850,7 @@ std::vector<Object *> MeshImporter::get_all_users_of(Mesh *reference_mesh)
*
* During import all materials have been assigned to Object.
* Now we iterate over the imported objects and optimize
- * the assignments as follows:
+ * the assignements as follows:
*
* for each imported geometry:
* if number of users is 1:
@@ -1075,7 +864,7 @@ std::vector<Object *> MeshImporter::get_all_users_of(Mesh *reference_mesh)
* adjust all other users accordingly.
*
**/
-void MeshImporter::optimize_material_assignments()
+void MeshImporter::optimize_material_assignements()
{
for (std::vector<Object *>::iterator it = imported_objects.begin();
it != imported_objects.end(); ++it)
@@ -1083,8 +872,8 @@ void MeshImporter::optimize_material_assignments()
Object *ob = (*it);
Mesh *me = (Mesh *) ob->data;
if (me->id.us==1) {
- bc_copy_materials_to_data(ob,me);
- bc_remove_materials_from_object(ob,me);
+ bc_copy_materials_to_data(ob, me);
+ bc_remove_materials_from_object(ob, me);
bc_remove_mark(ob);
}
else if (me->id.us > 1)
@@ -1101,10 +890,10 @@ void MeshImporter::optimize_material_assignments()
}
}
if (can_move) {
- bc_copy_materials_to_data(ref_ob,me);
+ bc_copy_materials_to_data(ref_ob, me);
for (int index = 0; index < mesh_users.size(); index++) {
Object *object = mesh_users[index];
- bc_remove_materials_from_object(object,me);
+ bc_remove_materials_from_object(object, me);
bc_remove_mark(object);
}
}
@@ -1119,14 +908,15 @@ void MeshImporter::optimize_material_assignments()
* come along with different materials. So we first create the objects
* and assign the materials to Object, then in a later cleanup we decide
* which materials shall be moved to the created geometries. Also see
- * optimize_material_assignments() above.
+ * optimize_material_assignements() above.
*/
MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial,
std::map<COLLADAFW::UniqueId, Material *>& uid_material_map,
Object *ob, const COLLADAFW::UniqueId *geom_uid,
- MTex **color_texture, char *layername, MTFace *texture_face,
+ char *layername, MTFace *texture_face,
std::map<Material *, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index)
{
+ MTex *color_texture = NULL;
Mesh *me = (Mesh *)ob->data;
const COLLADAFW::UniqueId& ma_uid = cmaterial.getReferencedMaterial();
@@ -1154,17 +944,17 @@ MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmateri
// loop through <bind_vertex_inputs>
for (i = 0; i < tex_array.getCount(); i++) {
- *color_texture = assign_textures_to_uvlayer(tex_array[i], me, texindex_texarray_map,
- *color_texture);
+ color_texture = assign_textures_to_uvlayer(tex_array[i], me, texindex_texarray_map,
+ color_texture);
}
// set texture face
- if (*color_texture &&
- strlen((*color_texture)->uvname) &&
- strcmp(layername, (*color_texture)->uvname) != 0) {
+ if (color_texture &&
+ strlen((color_texture)->uvname) &&
+ strcmp(layername, color_texture->uvname) != 0) {
texture_face = (MTFace *)CustomData_get_layer_named(&me->fdata, CD_MTFACE,
- (*color_texture)->uvname);
- strcpy(layername, (*color_texture)->uvname);
+ color_texture->uvname);
+ strcpy(layername, color_texture->uvname);
}
MaterialIdPrimitiveArrayMap& mat_prim_map = geom_uid_mat_mapping_map[*geom_uid];
@@ -1179,19 +969,18 @@ MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmateri
for (it = prims.begin(); it != prims.end(); it++) {
Primitive& prim = *it;
- MFace *mface = prim.mface;
+ MPoly *mpoly = prim.mpoly;
- for (i = 0; i < prim.totface; i++, mface++) {
- mface->mat_nr = mat_index;
+ for (i = 0; i < prim.totpoly; i++, mpoly++) {
+ mpoly->mat_nr = mat_index;
// bind texture images to faces
- if (texture_face && (*color_texture)) {
- texture_face->tpage = (Image *)(*color_texture)->tex->ima;
+ if (texture_face && color_texture) {
+ texture_face->tpage = (Image *)color_texture->tex->ima;
texture_face++;
}
}
}
- }
-
+ }
return texture_face;
}
@@ -1238,15 +1027,15 @@ Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::Insta
// replace ob->data freeing the old one
Mesh *old_mesh = (Mesh *)ob->data;
+ Mesh *new_mesh = uid_mesh_map[*geom_uid];
- set_mesh(ob, uid_mesh_map[*geom_uid]);
+ BKE_mesh_assign_object(ob, new_mesh);
if (old_mesh->id.us == 0) BKE_libblock_free(&G.main->mesh, old_mesh);
char layername[100];
layername[0] = '\0';
MTFace *texture_face = NULL;
- MTex *color_texture = NULL;
COLLADAFW::MaterialBindingArray& mat_array =
geom->getMaterialBindings();
@@ -1256,7 +1045,7 @@ Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::Insta
if (mat_array[i].getReferencedMaterial().isValid()) {
texture_face = assign_material_to_geom(mat_array[i], uid_material_map, ob, geom_uid,
- &color_texture, layername, texture_face,
+ layername, texture_face,
material_texture_mapping_map, i);
}
else {
@@ -1270,11 +1059,7 @@ Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::Insta
// create a mesh storing a pointer in a map so it can be retrieved later by geometry UID
bool MeshImporter::write_geometry(const COLLADAFW::Geometry *geom)
{
- // TODO: import also uvs, normals
- // XXX what to do with normal indices?
- // XXX num_normals may be != num verts, then what to do?
- // check geometry->getType() first
if (geom->getType() != COLLADAFW::Geometry::GEO_TYPE_MESH) {
// TODO: report warning
fprintf(stderr, "Mesh type %s is not supported\n", bc_geomTypeToStr(geom->getType()));
@@ -1284,30 +1069,25 @@ bool MeshImporter::write_geometry(const COLLADAFW::Geometry *geom)
COLLADAFW::Mesh *mesh = (COLLADAFW::Mesh *)geom;
if (!is_nice_mesh(mesh)) {
- fprintf(stderr, "Ignoring mesh %s\n", bc_get_dae_name(mesh));
+ fprintf(stderr, "Ignoring mesh %s\n", bc_get_dae_name(mesh).c_str());
return true;
}
const std::string& str_geom_id = mesh->getName().size() ? mesh->getName() : mesh->getOriginalId();
- Mesh *me = BKE_mesh_add((char *)str_geom_id.c_str());
- me->id.us--; // is already 1 here, but will be set later in set_mesh
+ Mesh *me = BKE_mesh_add(G.main, (char *)str_geom_id.c_str());
+ me->id.us--; // is already 1 here, but will be set later in BKE_mesh_assign_object
// store the Mesh pointer to link it later with an Object
+ // mesh_geom_map needed to map mesh to its geometry name (for shape key naming)
this->uid_mesh_map[mesh->getUniqueId()] = me;
-
- int new_tris = 0;
+ this->mesh_geom_map[std::string(me->id.name)] = str_geom_id;
read_vertices(mesh, me);
-
- new_tris = count_new_tris(mesh, me);
-
- read_faces(mesh, me, new_tris);
-
- BKE_mesh_make_edges(me, 0);
+ read_polys(mesh, me);
+ 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.
read_lines(mesh, me);
-
return true;
}
diff --git a/source/blender/collada/MeshImporter.h b/source/blender/collada/MeshImporter.h
index 746b0738108..5275420f4b5 100644
--- a/source/blender/collada/MeshImporter.h
+++ b/source/blender/collada/MeshImporter.h
@@ -31,6 +31,7 @@
#include <vector>
#include "COLLADAFWIndexList.h"
+#include "COLLADAFWPolygons.h"
#include "COLLADAFWInstanceGeometry.h"
#include "COLLADAFWMaterialBinding.h"
#include "COLLADAFWMesh.h"
@@ -59,6 +60,8 @@ class MeshImporterBase
{
public:
virtual Object *get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid) = 0;
+ virtual Mesh *get_mesh_by_geom_uid(const COLLADAFW::UniqueId& mesh_uid) = 0;
+ virtual std::string *get_geometry_name(const std::string &mesh_name) = 0;
};
class UVDataWrapper
@@ -83,33 +86,32 @@ private:
Scene *scene;
ArmatureImporter *armature_importer;
+ std::map<std::string, std::string> mesh_geom_map; // needed for correct shape key naming
std::map<COLLADAFW::UniqueId, Mesh*> uid_mesh_map; // geometry unique id-to-mesh map
std::map<COLLADAFW::UniqueId, Object*> uid_object_map; // geom uid-to-object
std::vector<Object*> imported_objects; // list of imported objects
- // this structure is used to assign material indices to faces
+
+ // this structure is used to assign material indices to polygons
// it holds a portion of Mesh faces and corresponds to a DAE primitive list (<triangles>, <polylist>, etc.)
struct Primitive {
- MFace *mface;
- unsigned int totface;
+ MPoly *mpoly;
+ unsigned int totpoly;
};
typedef std::map<COLLADAFW::MaterialId, std::vector<Primitive> > MaterialIdPrimitiveArrayMap;
std::map<COLLADAFW::UniqueId, MaterialIdPrimitiveArrayMap> geom_uid_mat_mapping_map; // crazy name!
std::multimap<COLLADAFW::UniqueId, COLLADAFW::UniqueId> materials_mapped_to_geom; //< materials that have already been mapped to a geometry. A pair of geom uid and mat uid, one geometry can have several materials
-
- void set_face_indices(MFace *mface, unsigned int *indices, bool quad);
-
- // not used anymore, test_index_face from blenkernel is better
-#if 0
- // change face indices order so that v4 is not 0
- void rotate_face_indices(MFace *mface);
-#endif
-
- void set_face_uv(MTFace *mtface, UVDataWrapper &uvs,
- COLLADAFW::IndexList& index_list, unsigned int *tris_indices);
-
- void set_face_uv(MTFace *mtface, UVDataWrapper &uvs,
- COLLADAFW::IndexList& index_list, int index, bool quad);
+ void set_poly_indices(MPoly *mpoly,
+ MLoop *mloop,
+ int loop_index,
+ unsigned int *indices,
+ int loop_count);
+
+ void set_face_uv(MLoopUV *mloopuv,
+ UVDataWrapper &uvs,
+ int loop_index,
+ COLLADAFW::IndexList& index_list,
+ int count);
#ifdef COLLADA_DEBUG
void print_index_list(COLLADAFW::IndexList& index_list);
@@ -118,11 +120,7 @@ private:
bool is_nice_mesh(COLLADAFW::Mesh *mesh);
void read_vertices(COLLADAFW::Mesh *mesh, Mesh *me);
-
- int triangulate_poly(unsigned int *indices, int totvert, MVert *verts, std::vector<unsigned int>& tri);
-
- int count_new_tris(COLLADAFW::Mesh *mesh, Mesh *me);
-
+
bool primitive_has_useable_normals(COLLADAFW::MeshPrimitive *mp);
bool primitive_has_faces(COLLADAFW::MeshPrimitive *mp);
@@ -132,15 +130,16 @@ private:
CustomData create_edge_custom_data(EdgeHash *eh);
- void allocate_face_data(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris);
+ void allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me);
// TODO: import uv set names
- void read_faces(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris);
+ void read_polys(COLLADAFW::Mesh *mesh, Mesh *me);
void read_lines(COLLADAFW::Mesh *mesh, Mesh *me);
+ unsigned int get_vertex_count(COLLADAFW::Polygons *mp, int index);
void get_vector(float v[3], COLLADAFW::MeshVertexData& arr, int i, int stride);
- bool flat_face(unsigned int *nind, COLLADAFW::MeshVertexData& nor, int count);
+ bool is_flat_face(unsigned int *nind, COLLADAFW::MeshVertexData& nor, int count);
std::vector<Object *> get_all_users_of(Mesh *reference_mesh);
@@ -151,17 +150,19 @@ public:
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);
MTex *assign_textures_to_uvlayer(COLLADAFW::TextureCoordinateBinding &ctexture,
Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map,
MTex *color_texture);
- void optimize_material_assignments();
+ void optimize_material_assignements();
MTFace *assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial,
std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
Object *ob, const COLLADAFW::UniqueId *geom_uid,
- MTex **color_texture, char *layername, MTFace *texture_face,
+ char *layername, MTFace *texture_face,
std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index);
@@ -172,7 +173,7 @@ public:
// create a mesh storing a pointer in a map so it can be retrieved later by geometry UID
bool write_geometry(const COLLADAFW::Geometry* geom);
-
+ std::string *get_geometry_name(const std::string &mesh_name);
};
#endif
diff --git a/source/blender/collada/SConscript b/source/blender/collada/SConscript
index 5d921681aea..4da99a21517 100644
--- a/source/blender/collada/SConscript
+++ b/source/blender/collada/SConscript
@@ -1,4 +1,5 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
@@ -32,9 +33,9 @@ defs = []
# TODO sanitize inc path building
# relative paths to include dirs, space-separated, string
if env['OURPLATFORM']=='darwin':
- incs = '../blenlib ../blenkernel ../windowmanager ../blenloader ../makesdna ../makesrna ../editors/include ../imbuf ../../../intern/guardedalloc [OPENCOLLADA]/COLLADAStreamWriter [OPENCOLLADA]/COLLADABaseUtils [OPENCOLLADA]/COLLADAFramework [OPENCOLLADA]/COLLADASaxFrameworkLoader [OPENCOLLADA]/GeneratedSaxParser '.replace('[OPENCOLLADA]', env['BF_OPENCOLLADA_INC'])
+ incs = '../ikplugin ../../../intern/iksolver/extern ../blenlib ../blenkernel ../windowmanager ../blenloader ../makesdna ../makesrna ../editors/include ../imbuf ../bmesh ../../../intern/guardedalloc [OPENCOLLADA]/COLLADAStreamWriter [OPENCOLLADA]/COLLADABaseUtils [OPENCOLLADA]/COLLADAFramework [OPENCOLLADA]/COLLADASaxFrameworkLoader [OPENCOLLADA]/GeneratedSaxParser '.replace('[OPENCOLLADA]', env['BF_OPENCOLLADA_INC'])
else:
- incs = '../blenlib ../blenkernel ../windowmanager ../makesdna ../blenloader ../makesrna ../editors/include ../imbuf ../../../intern/guardedalloc [OPENCOLLADA]/COLLADAStreamWriter/include [OPENCOLLADA]/COLLADABaseUtils/include [OPENCOLLADA]/COLLADAFramework/include [OPENCOLLADA]/COLLADASaxFrameworkLoader/include [OPENCOLLADA]/GeneratedSaxParser/include '.replace('[OPENCOLLADA]', env['BF_OPENCOLLADA_INC'])
+ incs = '../ikplugin ../../../intern/iksolver/extern ../blenlib ../blenkernel ../windowmanager ../makesdna ../blenloader ../makesrna ../editors/include ../imbuf ../bmesh ../../../intern/guardedalloc [OPENCOLLADA]/COLLADAStreamWriter/include [OPENCOLLADA]/COLLADABaseUtils/include [OPENCOLLADA]/COLLADAFramework/include [OPENCOLLADA]/COLLADASaxFrameworkLoader/include [OPENCOLLADA]/GeneratedSaxParser/include '.replace('[OPENCOLLADA]', env['BF_OPENCOLLADA_INC'])
if env['BF_BUILDINFO']:
defs.append('WITH_BUILDINFO')
diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp
index 6d239ae0fb1..604e131b44b 100644
--- a/source/blender/collada/SceneExporter.cpp
+++ b/source/blender/collada/SceneExporter.cpp
@@ -36,7 +36,12 @@ SceneExporter::SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm,
: COLLADASW::LibraryVisualScenes(sw), arm_exporter(arm), export_settings(export_settings)
{
}
-
+
+void SceneExporter::setExportTransformationType(BC_export_transformation_type transformation_type)
+{
+ this->transformation_type = transformation_type;
+}
+
void SceneExporter::exportScene(Scene *sce)
{
// <library_visual_scenes> <visual_scene>
@@ -84,6 +89,7 @@ void SceneExporter::exportHierarchy(Scene *sce)
}
}
+
void SceneExporter::writeNodes(Object *ob, Scene *sce)
{
// Add associated armature first if available
@@ -130,8 +136,9 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
if (ob->type == OB_MESH && armature_exported)
// for skinned mesh we write obmat in <bind_shape_matrix>
TransformWriter::add_node_transform_identity(colladaNode);
- else
- TransformWriter::add_node_transform_ob(colladaNode, ob);
+ else {
+ TransformWriter::add_node_transform_ob(colladaNode, ob, this->transformation_type);
+ }
// <instance_geometry>
if (ob->type == OB_MESH) {
@@ -171,7 +178,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
if ((ob->transflag & OB_DUPLIGROUP) == OB_DUPLIGROUP && ob->dup_group) {
GroupObject *go = NULL;
Group *gr = ob->dup_group;
- /* printf("group detected '%s'\n", gr->id.name+2); */
+ /* printf("group detected '%s'\n", gr->id.name + 2); */
for (go = (GroupObject *)(gr->gobject.first); go; go = go->next) {
printf("\t%s\n", go->ob->id.name);
}
@@ -182,6 +189,45 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
colladaNode.end();
}
+ if (ob->constraints.first != NULL ) {
+ bConstraint *con = (bConstraint *) ob->constraints.first;
+ while (con) {
+ std::string con_name(id_name(con));
+ std::string con_tag = con_name + "_constraint";
+ colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"type",con->type);
+ colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"enforce",con->enforce);
+ colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"flag",con->flag);
+ colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"headtail",con->headtail);
+ colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"lin_error",con->lin_error);
+ colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"own_space",con->ownspace);
+ colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"rot_error",con->rot_error);
+ colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"tar_space",con->tarspace);
+ colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"lin_error",con->lin_error);
+
+ //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_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ if (cti && cti->get_constraint_targets) {
+
+ bConstraintTarget *ct;
+ Object *obtar;
+
+ cti->get_constraint_targets(con, &targets);
+ if (cti) {
+ for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
+ obtar = ct->tar;
+ std::string tar_id(id_name(obtar));
+ colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"target_id",tar_id);
+ }
+ }
+ }
+
+ con = con->next;
+ }
+ }
+
for (std::list<Object *>::iterator i = child_objects.begin(); i != child_objects.end(); ++i) {
if (bc_is_marked(*i)) {
bc_remove_mark(*i);
@@ -189,8 +235,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
}
}
- if (ob->type != OB_ARMATURE) {
+ if (ob->type != OB_ARMATURE)
colladaNode.end();
- }
}
diff --git a/source/blender/collada/SceneExporter.h b/source/blender/collada/SceneExporter.h
index 31b471a3e4c..c7c15dba2cb 100644
--- a/source/blender/collada/SceneExporter.h
+++ b/source/blender/collada/SceneExporter.h
@@ -43,6 +43,7 @@ extern "C" {
#include "DNA_anim_types.h"
#include "DNA_action_types.h"
#include "DNA_curve_types.h"
+#include "DNA_constraint_types.h"
#include "DNA_armature_types.h"
#include "DNA_modifier_types.h"
#include "DNA_userdef_types.h"
@@ -51,6 +52,7 @@ extern "C" {
#include "BKE_fcurve.h"
#include "BKE_animsys.h"
#include "BLI_path_util.h"
+#include "BKE_constraint.h"
#include "BLI_fileops.h"
#include "ED_keyframing.h"
}
@@ -95,8 +97,10 @@ class SceneExporter: COLLADASW::LibraryVisualScenes, protected TransformWriter,
public:
SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings);
void exportScene(Scene *sce);
+ void setExportTransformationType(BC_export_transformation_type transformation_type);
private:
+ BC_export_transformation_type transformation_type;
// required for writeNodes() for bone-parented objects
friend class ArmatureExporter;
void exportHierarchy(Scene *sce);
diff --git a/source/blender/collada/SkinInfo.cpp b/source/blender/collada/SkinInfo.cpp
index 470f663f716..15320a8f221 100644
--- a/source/blender/collada/SkinInfo.cpp
+++ b/source/blender/collada/SkinInfo.cpp
@@ -237,10 +237,9 @@ void SkinInfo::link_armature(bContext *C, Object *ob, std::map<COLLADAFW::Unique
BKE_object_workob_calc_parent(scene, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA;
+ DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA);
- DAG_scene_sort(bmain, scene);
- DAG_ids_flush_update(bmain, 0);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
#endif
diff --git a/source/blender/collada/TransformReader.cpp b/source/blender/collada/TransformReader.cpp
index 5bc135e9b67..e0ba77e2554 100644
--- a/source/blender/collada/TransformReader.cpp
+++ b/source/blender/collada/TransformReader.cpp
@@ -47,6 +47,10 @@ void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::
COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
switch (type) {
+ case COLLADAFW::Transformation::MATRIX:
+ // XXX why does this return and discard all following transformations?
+ dae_matrix_to_mat4(tm, mat);
+ return;
case COLLADAFW::Transformation::TRANSLATE:
dae_translate_to_mat4(tm, cur);
break;
@@ -56,9 +60,6 @@ void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::
case COLLADAFW::Transformation::SCALE:
dae_scale_to_mat4(tm, cur);
break;
- case COLLADAFW::Transformation::MATRIX:
- dae_matrix_to_mat4(tm, cur);
- break;
case COLLADAFW::Transformation::LOOKAT:
case COLLADAFW::Transformation::SKEW:
fprintf(stderr, "LOOKAT and SKEW transformations are not supported yet.\n");
@@ -67,7 +68,7 @@ void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::
copy_m4_m4(copy, mat);
mult_m4_m4m4(mat, copy, cur);
-
+
if (animation_map) {
// AnimationList that drives this Transformation
const COLLADAFW::UniqueId& anim_list_id = tm->getAnimationList();
diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp
index 3fe3f620a68..e1c32482835 100644
--- a/source/blender/collada/TransformWriter.cpp
+++ b/source/blender/collada/TransformWriter.cpp
@@ -51,13 +51,17 @@ void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4],
converter->mat4_to_dae_double(dmat, local);
TransformBase::decompose(local, loc, rot, NULL, scale);
- if (node.getType() == COLLADASW::Node::JOINT)
+
+ if (node.getType() == COLLADASW::Node::JOINT) {
+ // XXX Why are joints handled differently ?
node.addMatrix("transform", dmat);
- else
+ }
+ else {
add_transform(node, loc, rot, scale);
+ }
}
-void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob)
+void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob, BC_export_transformation_type transformation_type)
{
#if 0
float rot[3], loc[3], scale[3];
@@ -93,12 +97,13 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob)
add_transform(node, loc, rot, scale);
#endif
-
+ UnitConverter converter;
+
/* Using parentinv should allow use of existing curves */
if (ob->parent) {
// If parentinv is identity don't add it.
bool add_parinv = false;
-
+
for (int i = 0; i < 16; ++i) {
float f = (i % 4 == i / 4) ? 1.0f : 0.0f;
add_parinv |= (ob->parentinv[i % 4][i / 4] != f);
@@ -106,13 +111,30 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob)
if (add_parinv) {
double dmat[4][4];
- UnitConverter converter;
converter.mat4_to_dae_double(dmat, ob->parentinv);
node.addMatrix("parentinverse", dmat);
}
}
- add_transform(node, ob->loc, ob->rot, ob->size);
+ double d_obmat[4][4];
+ converter.mat4_to_dae_double(d_obmat, ob->obmat);
+
+ switch (transformation_type) {
+ case BC_TRANSFORMATION_TYPE_MATRIX : {
+ node.addMatrix("transform",d_obmat);
+ break;
+ }
+ case BC_TRANSFORMATION_TYPE_TRANSROTLOC: {
+ add_transform(node, ob->loc, ob->rot, ob->size);
+ break;
+ }
+ case BC_TRANSFORMATION_TYPE_BOTH : {
+ node.addMatrix("transform",d_obmat);
+ add_transform(node, ob->loc, ob->rot, ob->size);
+ break;
+ }
+ }
+
}
void TransformWriter::add_node_transform_identity(COLLADASW::Node& node)
@@ -123,15 +145,15 @@ void TransformWriter::add_node_transform_identity(COLLADASW::Node& node)
void TransformWriter::add_transform(COLLADASW::Node& node, float loc[3], float rot[3], float scale[3])
{
- node.addTranslate("location", loc[0], loc[1], loc[2]);
#if 0
node.addRotateZ("rotationZ", COLLADABU::Math::Utils::radToDegF(rot[2]));
node.addRotateY("rotationY", COLLADABU::Math::Utils::radToDegF(rot[1]));
node.addRotateX("rotationX", COLLADABU::Math::Utils::radToDegF(rot[0]));
#endif
+ node.addTranslate("location", loc[0], loc[1], loc[2]);
node.addRotateZ("rotationZ", RAD2DEGF(rot[2]));
node.addRotateY("rotationY", RAD2DEGF(rot[1]));
node.addRotateX("rotationX", RAD2DEGF(rot[0]));
-
node.addScale("scale", scale[0], scale[1], scale[2]);
+
}
diff --git a/source/blender/collada/TransformWriter.h b/source/blender/collada/TransformWriter.h
index d2a4b54a570..7f69a4b9c95 100644
--- a/source/blender/collada/TransformWriter.h
+++ b/source/blender/collada/TransformWriter.h
@@ -33,13 +33,14 @@
#include "DNA_object_types.h"
#include "collada_internal.h"
+#include "collada.h"
class TransformWriter : protected TransformBase
{
protected:
void add_node_transform(COLLADASW::Node& node, float mat[4][4], float parent_mat[4][4]);
- void add_node_transform_ob(COLLADASW::Node& node, Object *ob);
+ void add_node_transform_ob(COLLADASW::Node& node, Object *ob, BC_export_transformation_type transformation_type);
void add_node_transform_identity(COLLADASW::Node& node);
diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp
index fbb18887d1b..1eb5ac6ca4d 100644
--- a/source/blender/collada/collada.cpp
+++ b/source/blender/collada/collada.cpp
@@ -31,6 +31,7 @@
#include "DocumentExporter.h"
#include "DocumentImporter.h"
#include "ExportSettings.h"
+#include "ImportSettings.h"
extern "C"
{
@@ -39,12 +40,19 @@ extern "C"
/* make dummy file */
#include "BLI_fileops.h"
-#include "BLI_path_util.h"
#include "BLI_linklist.h"
-int collada_import(bContext *C, const char *filepath)
+int collada_import(bContext *C,
+ const char *filepath,
+ int import_units)
{
- DocumentImporter imp(C, filepath);
+
+ ImportSettings import_settings;
+ import_settings.filepath = (char *)filepath;
+
+ import_settings.import_units = import_units != 0;
+
+ DocumentImporter imp(C, &import_settings);
if (imp.import()) return 1;
return 0;
@@ -59,6 +67,7 @@ int collada_export(Scene *sce,
int selected,
int include_children,
int include_armatures,
+ int include_shapekeys,
int deform_bones_only,
int active_uv_only,
@@ -66,8 +75,10 @@ int collada_export(Scene *sce,
int include_material_textures,
int use_texture_copies,
+ int triangulate,
int use_object_instantiation,
int sort_by_name,
+ BC_export_transformation_type export_transformation_type,
int second_life)
{
ExportSettings export_settings;
@@ -75,7 +86,7 @@ int collada_export(Scene *sce,
/* annoying, collada crashes if file cant be created! [#27162] */
if (!BLI_exists(filepath)) {
BLI_make_existing_file(filepath); /* makes the dir if its not there */
- if (BLI_file_touch(filepath) == 0) {
+ if (!BLI_file_touch(filepath)) {
fprintf(stdout, "Collada export: Can not create: %s\n", filepath);
return 0;
}
@@ -89,6 +100,7 @@ int collada_export(Scene *sce,
export_settings.selected = selected != 0;
export_settings.include_children = include_children != 0;
export_settings.include_armatures = include_armatures != 0;
+ export_settings.include_shapekeys = include_shapekeys != 0;
export_settings.deform_bones_only = deform_bones_only != 0;
export_settings.active_uv_only = active_uv_only != 0;
@@ -96,9 +108,11 @@ int collada_export(Scene *sce,
export_settings.include_material_textures= include_material_textures != 0;
export_settings.use_texture_copies = use_texture_copies != 0;
- export_settings.use_object_instantiation = use_object_instantiation != 0;
- export_settings.sort_by_name = sort_by_name != 0;
- export_settings.second_life = second_life != 0;
+ export_settings.triangulate = triangulate != 0;
+ export_settings.use_object_instantiation = use_object_instantiation != 0;
+ export_settings.sort_by_name = sort_by_name != 0;
+ export_settings.export_transformation_type = export_transformation_type;
+ export_settings.second_life = second_life != 0;
int includeFilter = OB_REL_NONE;
diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h
index 13f8151da3d..b3a8156b6fe 100644
--- a/source/blender/collada/collada.h
+++ b/source/blender/collada/collada.h
@@ -33,6 +33,7 @@ extern "C" {
#endif
#include "BLI_linklist.h"
+#include "BLI_path_util.h"
#include "RNA_types.h"
typedef enum BC_export_mesh_type {
@@ -40,13 +41,22 @@ typedef enum BC_export_mesh_type {
BC_MESH_TYPE_RENDER
} BC_export_mesh_type;
+typedef enum BC_export_transformation_type {
+ BC_TRANSFORMATION_TYPE_MATRIX,
+ BC_TRANSFORMATION_TYPE_TRANSROTLOC,
+ BC_TRANSFORMATION_TYPE_BOTH
+} BC_export_transformation_type;
+
struct bContext;
struct Scene;
/*
* both return 1 on success, 0 on error
*/
-int collada_import(bContext *C, const char *filepath);
+int collada_import(bContext *C,
+ const char *filepath,
+ int import_units);
+
int collada_export(Scene *sce,
const char *filepath,
int apply_modifiers,
@@ -55,15 +65,18 @@ int collada_export(Scene *sce,
int selected,
int include_children,
int include_armatures,
+ int include_shapekeys,
int deform_bones_only,
- int active_uv_only,
- int include_uv_textures,
- int include_material_textures,
- int use_texture_copies,
+ int active_uv_only,
+ int include_uv_textures,
+ int include_material_textures,
+ int use_texture_copies,
+ int triangulate,
int use_object_instantiation,
int sort_by_name,
+ BC_export_transformation_type export_transformation_type,
int second_life);
diff --git a/source/blender/collada/collada_internal.cpp b/source/blender/collada/collada_internal.cpp
index 13ff69d3abf..069419f938b 100644
--- a/source/blender/collada/collada_internal.cpp
+++ b/source/blender/collada/collada_internal.cpp
@@ -33,7 +33,14 @@
UnitConverter::UnitConverter() : unit(), up_axis(COLLADAFW::FileInfo::Z_UP)
{
- /* pass */
+ unit_m4(x_up_mat4);
+ rotate_m4(x_up_mat4, 'Y', -0.5 * M_PI);
+
+ unit_m4(y_up_mat4);
+ rotate_m4(y_up_mat4, 'X', 0.5 * M_PI);
+
+ unit_m4(z_up_mat4);
+
}
void UnitConverter::read_asset(const COLLADAFW::FileInfo *asset)
@@ -85,13 +92,13 @@ void UnitConverter::dae_matrix_to_mat4_(float out[4][4], const COLLADABU::Math::
}
}
-void UnitConverter::mat4_to_dae(float out[4][4], float const in[4][4])
+void UnitConverter::mat4_to_dae(float out[4][4], float in[4][4])
{
copy_m4_m4(out, in);
transpose_m4(out);
}
-void UnitConverter::mat4_to_dae_double(double out[4][4], float const in[4][4])
+void UnitConverter::mat4_to_dae_double(double out[4][4], float in[4][4])
{
float mat[4][4];
@@ -102,6 +109,21 @@ void UnitConverter::mat4_to_dae_double(double out[4][4], float const in[4][4])
out[i][j] = mat[i][j];
}
+float(&UnitConverter::get_rotation())[4][4]
+{
+ switch (up_axis) {
+ case COLLADAFW::FileInfo::X_UP:
+ return x_up_mat4;
+ break;
+ case COLLADAFW::FileInfo::Y_UP:
+ return y_up_mat4;
+ break;
+ default:
+ return z_up_mat4;
+ break;
+ }
+}
+
void TransformBase::decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
{
mat4_to_size(size, mat);
@@ -202,6 +224,12 @@ void clear_global_id_map()
}
/** Look at documentation of translate_map */
+std::string translate_id(const char *idString)
+{
+ std::string id = std::string(idString);
+ return translate_id(id);
+}
+
std::string translate_id(const std::string &id)
{
if (id.size() == 0) {
@@ -283,3 +311,9 @@ std::string get_material_id(Material *mat)
{
return translate_id(id_name(mat)) + "-material";
}
+
+std::string get_morph_id(Object *ob)
+{
+ return translate_id(id_name(ob)) + "-morph";
+}
+
diff --git a/source/blender/collada/collada_internal.h b/source/blender/collada/collada_internal.h
index 5a5126025de..2e855764f4b 100644
--- a/source/blender/collada/collada_internal.h
+++ b/source/blender/collada/collada_internal.h
@@ -39,7 +39,6 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BLI_math.h"
-#include "BLI_math.h"
#include "BLI_linklist.h"
class UnitConverter
@@ -48,6 +47,10 @@ private:
COLLADAFW::FileInfo::Unit unit;
COLLADAFW::FileInfo::UpAxisType up_axis;
+ float x_up_mat4[4][4];
+ float y_up_mat4[4][4];
+ float z_up_mat4[4][4];
+
public:
enum UnitSystem {
@@ -71,9 +74,13 @@ public:
void dae_matrix_to_mat4_(float out[4][4], const COLLADABU::Math::Matrix4& in);
- void mat4_to_dae(float out[4][4], float const in[4][4]);
+ void mat4_to_dae(float out[4][4], float in[4][4]);
+
+ void mat4_to_dae_double(double out[4][4], float in[4][4]);
+
+ float(&get_rotation())[4][4];
+
- void mat4_to_dae_double(double out[4][4], float const in[4][4]);
};
class TransformBase
@@ -85,6 +92,7 @@ public:
extern void clear_global_id_map();
/** Look at documentation of translate_map */
extern std::string translate_id(const std::string &id);
+extern std::string translate_id(const char *idString);
extern std::string id_name(void *id);
@@ -99,4 +107,6 @@ extern std::string get_camera_id(Object *ob);
extern std::string get_material_id(Material *mat);
+extern std::string get_morph_id(Object *ob);
+
#endif /* __COLLADA_INTERNAL_H__ */
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index 7bdda387d5e..84b81f4d332 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -49,12 +49,14 @@ extern "C" {
#include "BKE_customdata.h"
#include "BKE_depsgraph.h"
#include "BKE_object.h"
+#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_scene.h"
#include "BKE_DerivedMesh.h"
#include "WM_api.h" // XXX hrm, see if we can do without this
#include "WM_types.h"
+#include "bmesh.h"
}
float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index)
@@ -84,7 +86,6 @@ int bc_test_parent_loop(Object *par, Object *ob)
int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
{
Object workob;
- Main *bmain = CTX_data_main(C);
Scene *sce = CTX_data_scene(C);
if (!par || bc_test_parent_loop(par, ob))
@@ -112,48 +113,63 @@ int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
BKE_object_workob_calc_parent(sce, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA;
- par->recalc |= OB_RECALC_OB;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DAG_id_tag_update(&par->id, OB_RECALC_OB);
- DAG_scene_sort(bmain, sce);
- DAG_ids_flush_update(bmain, 0);
+ /** done once after import */
+#if 0
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+#endif
return true;
}
Object *bc_add_object(Scene *scene, int type, const char *name)
{
- Object *ob = BKE_object_add_only_object(type, name);
+ Object *ob = BKE_object_add_only_object(G.main, type, name);
ob->data = BKE_object_obdata_add_from_type(type);
ob->lay = scene->lay;
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
BKE_scene_base_select(scene, BKE_scene_base_add(scene, ob));
return ob;
}
-Mesh *bc_to_mesh_apply_modifiers(Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type)
+Mesh *bc_get_mesh_copy(Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate)
{
Mesh *tmpmesh;
CustomDataMask mask = CD_MASK_MESH;
DerivedMesh *dm = NULL;
- switch (export_mesh_type) {
- case BC_MESH_TYPE_VIEW: {
- dm = mesh_create_derived_view(scene, ob, mask);
- break;
- }
- case BC_MESH_TYPE_RENDER: {
- dm = mesh_create_derived_render(scene, ob, mask);
- break;
+ if (apply_modifiers) {
+ switch (export_mesh_type) {
+ case BC_MESH_TYPE_VIEW: {
+ dm = mesh_create_derived_view(scene, ob, mask);
+ break;
+ }
+ case BC_MESH_TYPE_RENDER: {
+ dm = mesh_create_derived_render(scene, ob, mask);
+ break;
+ }
}
}
+ else {
+ dm = mesh_create_derived((Mesh *)ob->data, ob, NULL);
+ }
- tmpmesh = BKE_mesh_add("ColladaMesh"); // name is not important here
+ tmpmesh = BKE_mesh_add(G.main, "ColladaMesh"); // name is not important here
DM_to_mesh(dm, tmpmesh, ob);
dm->release(dm);
+
+ 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;
}
@@ -282,3 +298,98 @@ int bc_get_active_UVLayer(Object *ob)
Mesh *me = (Mesh *)ob->data;
return CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
}
+
+std::string bc_url_encode(std::string data)
+{
+ /* XXX We probably do not need to do a full encoding.
+ * But in case that is necessary,then it can be added here.
+ */
+ return bc_replace_string(data,"#", "%23");
+}
+
+std::string bc_replace_string(std::string data, const std::string& pattern,
+ const std::string& replacement)
+{
+ size_t pos = 0;
+ while((pos = data.find(pattern, pos)) != std::string::npos) {
+ data.replace(pos, pattern.length(), replacement);
+ pos += replacement.length();
+ }
+ return data;
+}
+
+/**
+ * Calculate a rescale factor such that the imported scene's scale
+ * is preserved. I.e. 1 meter in the import will also be
+ * 1 meter in the current scene.
+ * XXX : I am not sure if it is correct to map 1 Blender Unit
+ * to 1 Meter for unit type NONE. But it looks reasonable to me.
+ */
+void bc_match_scale(std::vector<Object *> *objects_done,
+ Scene &sce,
+ UnitConverter &bc_unit) {
+
+ Object *ob = NULL;
+
+ PointerRNA scene_ptr, unit_settings;
+ PropertyRNA *system_ptr, *scale_ptr;
+ RNA_id_pointer_create(&sce.id, &scene_ptr);
+
+ unit_settings = RNA_pointer_get(&scene_ptr, "unit_settings");
+ system_ptr = RNA_struct_find_property(&unit_settings, "system");
+ scale_ptr = RNA_struct_find_property(&unit_settings, "scale_length");
+
+ int type = RNA_property_enum_get(&unit_settings, system_ptr);
+
+ float bl_scale;
+
+ switch (type) {
+ case USER_UNIT_NONE:
+ bl_scale = 1.0; // map 1 Blender unit to 1 Meter
+ break;
+
+ case USER_UNIT_METRIC:
+ bl_scale = RNA_property_float_get(&unit_settings, scale_ptr);
+ break;
+
+ default :
+ bl_scale = RNA_property_float_get(&unit_settings, scale_ptr);
+ // it looks like the conversion to Imperial is done implicitly.
+ // So nothing to do here.
+ break;
+ }
+
+ float scale_conv = bc_unit.getLinearMeter() / bl_scale;
+
+ float rescale[3];
+ rescale[0] = rescale[1] = rescale[2] = scale_conv;
+
+ float size_mat4[4][4];
+
+ float axis_mat4[4][4];
+ unit_m4(axis_mat4);
+
+ size_to_mat4(size_mat4, rescale);
+
+ for (std::vector<Object *>::iterator it = objects_done->begin();
+ it != objects_done->end();
+ ++it)
+ {
+ ob = *it;
+ mult_m4_m4m4(ob->obmat, size_mat4, ob->obmat);
+ mult_m4_m4m4(ob->obmat, bc_unit.get_rotation(), ob->obmat);
+ BKE_object_apply_mat4(ob, ob->obmat, 0, 0);
+ }
+
+}
+
+void bc_triangulate_mesh(Mesh *me) {
+ bool use_beauty = false;
+ bool tag_only = false;
+
+ BMesh *bm = BM_mesh_create(&bm_mesh_allocsize_default);
+ BM_mesh_bm_from_me(bm, me, FALSE, 0);
+ BM_mesh_triangulate(bm, use_beauty, tag_only, NULL, NULL);
+ BM_mesh_bm_to_me(bm, me, FALSE);
+ BM_mesh_free(bm);
+}
diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h
index b8990c3fcdd..f8e6f09e498 100644
--- a/source/blender/collada/collada_utils.h
+++ b/source/blender/collada/collada_utils.h
@@ -42,15 +42,19 @@ extern "C" {
#include "DNA_texture_types.h"
#include "DNA_scene_types.h"
+#include "RNA_access.h"
+
#include "BLI_linklist.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_object.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_scene.h"
}
#include "ExportSettings.h"
+#include "collada_internal.h"
typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex *> > TexIndexTextureArrayMap;
@@ -58,7 +62,7 @@ extern float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsi
extern int bc_test_parent_loop(Object *par, Object *ob);
extern int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space = true);
extern Object *bc_add_object(Scene *scene, int type, const char *name);
-extern Mesh *bc_to_mesh_apply_modifiers(Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type);
+extern Mesh *bc_get_mesh_copy(Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate);
extern Object *bc_get_assigned_armature(Object *ob);
extern Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *ob);
@@ -77,4 +81,27 @@ extern void bc_bubble_sort_by_Object_name(LinkNode *export_set);
extern bool bc_is_root_bone(Bone *aBone, bool deform_bones_only);
extern int bc_get_active_UVLayer(Object *ob);
+extern std::string bc_replace_string(std::string data, const std::string& pattern, const std::string& replacement);
+extern std::string bc_url_encode(std::string data);
+extern void bc_match_scale(std::vector<Object *> *objects_done, Scene &sce, UnitConverter &unit_converter);
+
+extern void bc_triangulate_mesh(Mesh *me);
+
+
+class BCPolygonNormalsIndices
+{
+ std::vector<unsigned int> normal_indices;
+
+ public:
+
+ void add_index(unsigned int index) {
+ normal_indices.push_back(index);
+ }
+
+ unsigned int operator[](unsigned int i) {
+ return normal_indices[i];
+ }
+
+};
+
#endif
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index 8259cb6f297..4b058a41f71 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -35,13 +35,13 @@ set(INC
../imbuf
../makesdna
../makesrna
- ../opencl
../windowmanager
../nodes
../nodes/composite
../nodes/intern
../render/extern/include
../render/intern/include
+ ../../../intern/opencl
../../../intern/guardedalloc
)
@@ -491,10 +491,10 @@ set(SRC
operations/COM_ColorMatteOperation.h
operations/COM_ChannelMatteOperation.cpp
operations/COM_ChannelMatteOperation.h
- operations/COM_ConvertPremulToKeyOperation.cpp
- operations/COM_ConvertPremulToKeyOperation.h
- operations/COM_ConvertKeyToPremulOperation.cpp
- operations/COM_ConvertKeyToPremulOperation.h
+ operations/COM_ConvertPremulToStraightOperation.cpp
+ operations/COM_ConvertPremulToStraightOperation.h
+ operations/COM_ConvertStraightToPremulOperation.cpp
+ operations/COM_ConvertStraightToPremulOperation.h
operations/COM_ReadBufferOperation.cpp
operations/COM_ReadBufferOperation.h
@@ -580,6 +580,8 @@ set(SRC
# Distort operation
operations/COM_TranslateOperation.h
operations/COM_TranslateOperation.cpp
+ operations/COM_WrapOperation.h
+ operations/COM_WrapOperation.cpp
operations/COM_RotateOperation.h
operations/COM_RotateOperation.cpp
operations/COM_ScaleOperation.h
@@ -658,6 +660,6 @@ list(APPEND INC
${CMAKE_CURRENT_BINARY_DIR}/operations
)
data_to_c(${CMAKE_CURRENT_SOURCE_DIR}/operations/COM_OpenCLKernels.cl
- ${CMAKE_CURRENT_BINARY_DIR}/operations/COM_OpenCLKernels.cl.h SRC)
+ ${CMAKE_CURRENT_BINARY_DIR}/operations/COM_OpenCLKernels.cl.h SRC)
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 a64583b68ff..fc546188816 100644
--- a/source/blender/compositor/COM_compositor.h
+++ b/source/blender/compositor/COM_compositor.h
@@ -20,9 +20,9 @@
* Monique Dewanchand
*/
- #ifdef __cplusplus
+#ifdef __cplusplus
extern "C" {
- #endif
+#endif
#include "DNA_color_types.h"
#include "DNA_node_types.h"
diff --git a/source/blender/compositor/SConscript b/source/blender/compositor/SConscript
index 9f947ca7327..64169ac7403 100644
--- a/source/blender/compositor/SConscript
+++ b/source/blender/compositor/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/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 = ['GLEW_STATIC']
@@ -6,7 +32,7 @@ sources = env.Glob('intern/*.cpp') + env.Glob('nodes/*.cpp') + env.Glob('operati
incs = '. nodes intern operations ../blenlib ../blenkernel ../makesdna ../render/extern/include ../render/intern/include'
incs += ' ../makesrna ../blenloader ../../../intern/guardedalloc ../imbuf ../windowmanager '
-incs += '../opencl ../nodes ../nodes/intern ../nodes/composite '
+incs += '#intern/opencl ../nodes ../nodes/intern ../nodes/composite '
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
incs += ' ' + env['BF_PTHREADS_INC']
diff --git a/source/blender/compositor/intern/COM_CompositorContext.cpp b/source/blender/compositor/intern/COM_CompositorContext.cpp
index e1cc25d028a..6008a889205 100644
--- a/source/blender/compositor/intern/COM_CompositorContext.cpp
+++ b/source/blender/compositor/intern/COM_CompositorContext.cpp
@@ -29,7 +29,6 @@ CompositorContext::CompositorContext()
this->m_rd = NULL;
this->m_quality = COM_QUALITY_HIGH;
this->m_hasActiveOpenCLDevices = false;
- this->m_activegNode = NULL;
this->m_fastCalculation = false;
this->m_viewSettings = NULL;
this->m_displaySettings = NULL;
diff --git a/source/blender/compositor/intern/COM_CompositorContext.h b/source/blender/compositor/intern/COM_CompositorContext.h
index 2f5e8c0648d..3c7db703bf9 100644
--- a/source/blender/compositor/intern/COM_CompositorContext.h
+++ b/source/blender/compositor/intern/COM_CompositorContext.h
@@ -64,17 +64,18 @@ private:
* @see ExecutionSystem
*/
bNodeTree *m_bnodetree;
-
+
/**
- * @brief activegNode the group node that is currently being edited.
+ * @brief Preview image hash table
+ * This field is initialized in ExecutionSystem and must only be read from that point on.
*/
- bNode *m_activegNode;
+ bNodeInstanceHash *m_previews;
/**
* @brief does this system have active opencl devices?
*/
bool m_hasActiveOpenCLDevices;
-
+
/**
* @brief Skip slow nodes
*/
@@ -115,19 +116,19 @@ public:
const bNodeTree *getbNodeTree() const { return this->m_bnodetree; }
/**
- * @brief set the active groupnode of the context
+ * @brief get the scene of the context
*/
- void setActivegNode(bNode *gnode) { this->m_activegNode = gnode; }
+ const RenderData *getRenderData() const { return this->m_rd; }
/**
- * @brief get the active groupnode of the context
+ * @brief set the preview image hash table
*/
- const bNode *getActivegNode() const { return this->m_activegNode; }
+ void setPreviewHash(bNodeInstanceHash *previews) { this->m_previews = previews; }
/**
- * @brief get the scene of the context
+ * @brief get the preview image hash table
*/
- const RenderData *getRenderData() const { return this->m_rd; }
+ bNodeInstanceHash *getPreviewHash() const { return this->m_previews; }
/**
* @brief set view settings of color color management
@@ -178,6 +179,7 @@ public:
void setFastCalculation(bool fastCalculation) {this->m_fastCalculation = fastCalculation;}
bool isFastCalculation() {return this->m_fastCalculation;}
+ inline bool isGroupnodeBufferEnabled() {return this->getbNodeTree()->flag & NTREE_COM_GROUPNODE_BUFFER;}
};
diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp
index 9c4a32f20c9..80ae952b87f 100644
--- a/source/blender/compositor/intern/COM_Converter.cpp
+++ b/source/blender/compositor/intern/COM_Converter.cpp
@@ -124,7 +124,7 @@
Node *Converter::convert(bNode *b_node, bool fast)
{
- Node *node;
+ Node *node = NULL;
if (b_node->flag & NODE_MUTED) {
node = new MuteNode(b_node);
@@ -226,6 +226,10 @@ Node *Converter::convert(bNode *b_node, bool fast)
case NODE_GROUP:
node = new GroupNode(b_node);
break;
+ case NODE_GROUP_INPUT:
+ case NODE_GROUP_OUTPUT:
+ /* handled in GroupNode::ungroup */
+ break;
case CMP_NODE_NORMAL:
node = new NormalNode(b_node);
break;
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp
index ffc36281874..82d1c7883e1 100644
--- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp
@@ -40,6 +40,8 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
+#include "BLI_string.h"
+#include "BKE_global.h"
#include "PIL_time.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -60,6 +62,8 @@ ExecutionGroup::ExecutionGroup()
this->m_openCL = false;
this->m_singleThreaded = false;
this->m_chunksFinished = 0;
+ BLI_rcti_init(&this->m_viewerBorder, 0, 0, 0, 0);
+ this->m_executionStartTime = 0;
}
CompositorPriority ExecutionGroup::getRenderPriotrity()
@@ -196,6 +200,7 @@ void ExecutionGroup::determineResolution(unsigned int resolution[2])
resolution[0] = operation->getWidth();
resolution[1] = operation->getHeight();
this->setResolution(resolution);
+ BLI_rcti_init(&this->m_viewerBorder, 0, this->m_width, 0, this->m_height);
}
void ExecutionGroup::determineNumberOfChunks()
@@ -207,8 +212,10 @@ void ExecutionGroup::determineNumberOfChunks()
}
else {
const float chunkSizef = this->m_chunkSize;
- this->m_numberOfXChunks = ceil(this->m_width / chunkSizef);
- this->m_numberOfYChunks = ceil(this->m_height / chunkSizef);
+ const int border_width = BLI_rcti_size_x(&this->m_viewerBorder);
+ const int border_height = BLI_rcti_size_y(&this->m_viewerBorder);
+ this->m_numberOfXChunks = ceil(border_width / chunkSizef);
+ this->m_numberOfYChunks = ceil(border_height / chunkSizef);
this->m_numberOfChunks = this->m_numberOfXChunks * this->m_numberOfYChunks;
}
}
@@ -225,6 +232,8 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
if (this->m_numberOfChunks == 0) {return; } /// @note: early break out
unsigned int chunkNumber;
+ this->m_executionStartTime = PIL_check_seconds_timer();
+
this->m_chunksFinished = 0;
this->m_bTree = bTree;
unsigned int index;
@@ -245,6 +254,9 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
chunkorder = viewer->getChunkOrder();
}
+ const int border_width = BLI_rcti_size_x(&this->m_viewerBorder);
+ const int border_height = BLI_rcti_size_y(&this->m_viewerBorder);
+
switch (chunkorder) {
case COM_TO_RANDOM:
for (index = 0; index < 2 * this->m_numberOfChunks; index++) {
@@ -258,14 +270,14 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
case COM_TO_CENTER_OUT:
{
ChunkOrderHotspot *hotspots[1];
- hotspots[0] = new ChunkOrderHotspot(this->m_width * centerX, this->m_height * centerY, 0.0f);
+ hotspots[0] = new ChunkOrderHotspot(border_width * centerX, border_height * centerY, 0.0f);
rcti rect;
ChunkOrder *chunkOrders = (ChunkOrder *)MEM_mallocN(sizeof(ChunkOrder) * this->m_numberOfChunks, __func__);
for (index = 0; index < this->m_numberOfChunks; index++) {
determineChunkRect(&rect, index);
chunkOrders[index].setChunkNumber(index);
- chunkOrders[index].setX(rect.xmin);
- chunkOrders[index].setY(rect.ymin);
+ chunkOrders[index].setX(rect.xmin - this->m_viewerBorder.xmin);
+ chunkOrders[index].setY(rect.ymin - this->m_viewerBorder.ymin);
chunkOrders[index].determineDistance(hotspots, 1);
}
@@ -281,10 +293,10 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
case COM_TO_RULE_OF_THIRDS:
{
ChunkOrderHotspot *hotspots[9];
- unsigned int tx = this->m_width / 6;
- unsigned int ty = this->m_height / 6;
- unsigned int mx = this->m_width / 2;
- unsigned int my = this->m_height / 2;
+ unsigned int tx = border_width / 6;
+ unsigned int ty = border_height / 6;
+ unsigned int mx = border_width / 2;
+ unsigned int my = border_height / 2;
unsigned int bx = mx + 2 * tx;
unsigned int by = my + 2 * ty;
@@ -303,8 +315,8 @@ void ExecutionGroup::execute(ExecutionSystem *graph)
for (index = 0; index < this->m_numberOfChunks; index++) {
determineChunkRect(&rect, index);
chunkOrders[index].setChunkNumber(index);
- chunkOrders[index].setX(rect.xmin);
- chunkOrders[index].setY(rect.ymin);
+ chunkOrders[index].setX(rect.xmin - this->m_viewerBorder.xmin);
+ chunkOrders[index].setY(rect.ymin - this->m_viewerBorder.ymin);
chunkOrders[index].determineDistance(hotspots, 9);
}
@@ -403,6 +415,35 @@ 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);
+ printf("| Elapsed %s ", timestr);
+ printf("| Tree %s, Tile %d-%d ", 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)
@@ -426,18 +467,26 @@ void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer **memo
float progress = this->m_chunksFinished;
progress /= this->m_numberOfChunks;
this->m_bTree->progress(this->m_bTree->prh, progress);
+
+ if (G.background)
+ printBackgroundStats();
}
}
inline void ExecutionGroup::determineChunkRect(rcti *rect, const unsigned int xChunk, const unsigned int yChunk) const
{
+ const int border_width = BLI_rcti_size_x(&this->m_viewerBorder);
+ const int border_height = BLI_rcti_size_y(&this->m_viewerBorder);
+
if (this->m_singleThreaded) {
- BLI_rcti_init(rect, 0, this->m_width, 0, this->m_height);
+ BLI_rcti_init(rect, this->m_viewerBorder.xmin, border_width, this->m_viewerBorder.ymin, border_height);
}
else {
- const unsigned int minx = xChunk * this->m_chunkSize;
- const unsigned int miny = yChunk * this->m_chunkSize;
- BLI_rcti_init(rect, minx, min(minx + this->m_chunkSize, this->m_width), miny, min(miny + this->m_chunkSize, this->m_height));
+ const unsigned int minx = xChunk * this->m_chunkSize + this->m_viewerBorder.xmin;
+ const unsigned int miny = yChunk * this->m_chunkSize + this->m_viewerBorder.ymin;
+ const unsigned int width = min((unsigned int) this->m_viewerBorder.xmax, this->m_width);
+ const unsigned int height = min((unsigned int) this->m_viewerBorder.ymax, this->m_height);
+ BLI_rcti_init(rect, min(minx, this->m_width), min(minx + this->m_chunkSize, width), min(miny, this->m_height), min(miny + this->m_chunkSize, height));
}
}
@@ -472,9 +521,9 @@ bool ExecutionGroup::scheduleAreaWhenPossible(ExecutionSystem *graph, rcti *area
float chunkSizef = this->m_chunkSize;
int indexx, indexy;
- int minxchunk = floor(area->xmin / chunkSizef);
+ int minxchunk = floor((area->xmin - this->m_viewerBorder.xmin) / chunkSizef);
int maxxchunk = ceil((area->xmax - 1) / chunkSizef);
- int minychunk = floor(area->ymin / chunkSizef);
+ int minychunk = floor((area->ymin - this->m_viewerBorder.ymin) / chunkSizef);
int maxychunk = ceil((area->ymax - 1) / chunkSizef);
minxchunk = max(minxchunk, 0);
minychunk = max(minychunk, 0);
@@ -574,3 +623,23 @@ bool ExecutionGroup::isOpenCL()
{
return this->m_openCL;
}
+
+void ExecutionGroup::setViewerBorder(float xmin, float xmax, float ymin, float ymax)
+{
+ NodeOperation *operation = this->getOutputNodeOperation();
+
+ if (operation->isViewerOperation() || operation->isPreviewOperation()) {
+ BLI_rcti_init(&this->m_viewerBorder, xmin * this->m_width, xmax * this->m_width,
+ ymin * this->m_height, ymax * this->m_height);
+ }
+}
+
+void ExecutionGroup::setRenderBorder(float xmin, float xmax, float ymin, float ymax)
+{
+ NodeOperation *operation = this->getOutputNodeOperation();
+
+ if (operation->isOutputOperation(true) && !(operation->isViewerOperation() || operation->isPreviewOperation())) {
+ BLI_rcti_init(&this->m_viewerBorder, xmin * this->m_width, xmax * this->m_width,
+ ymin * this->m_height, ymax * this->m_height);
+ }
+}
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.h b/source/blender/compositor/intern/COM_ExecutionGroup.h
index 00104c24194..537dcb5974a 100644
--- a/source/blender/compositor/intern/COM_ExecutionGroup.h
+++ b/source/blender/compositor/intern/COM_ExecutionGroup.h
@@ -161,7 +161,18 @@ private:
* @see openCL
*/
bool m_initialized;
-
+
+ /**
+ * @brief denotes boundary for border compositing
+ * @note measured in pixel space
+ */
+ rcti m_viewerBorder;
+
+ /**
+ * @brief start time of execution
+ */
+ double m_executionStartTime;
+
// methods
/**
* @brief check whether parameter operation can be added to the execution group
@@ -335,6 +346,11 @@ public:
* @see determineChunkRect
*/
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.
@@ -395,6 +411,14 @@ public:
*/
CompositorPriority getRenderPriotrity();
+ /**
+ * @brief set border for viewer operation
+ * @note all the coordinates are assumed to be in normalized space
+ */
+ void setViewerBorder(float xmin, float xmax, float ymin, float ymax);
+
+ void setRenderBorder(float xmin, float xmax, float ymin, float ymax);
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionGroup")
#endif
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp
index 1ec4ac7699b..450d1b03917 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp
@@ -26,7 +26,9 @@
#include "PIL_time.h"
#include "BLI_utildefines.h"
+extern "C" {
#include "BKE_node.h"
+}
#include "COM_Converter.h"
#include "COM_NodeOperation.h"
@@ -49,7 +51,9 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re
const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings)
{
this->m_context.setbNodeTree(editingtree);
+ this->m_context.setPreviewHash(editingtree->previews);
this->m_context.setFastCalculation(fastcalculation);
+#if 0 /* XXX TODO find a better way to define visible output nodes from all editors */
bNode *gnode;
for (gnode = (bNode *)editingtree->nodes.first; gnode; gnode = gnode->next) {
if (gnode->type == NODE_GROUP && gnode->typeinfo->group_edit_get(gnode)) {
@@ -57,6 +61,7 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re
break;
}
}
+#endif
/* initialize the CompositorContext */
if (rendering) {
@@ -68,7 +73,7 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re
this->m_context.setRendering(rendering);
this->m_context.setHasActiveOpenCLDevices(WorkScheduler::hasGPUDevices() && (editingtree->flag & NTREE_COM_OPENCL));
- ExecutionSystemHelper::addbNodeTree(*this, 0, editingtree, NULL);
+ ExecutionSystemHelper::addbNodeTree(*this, 0, editingtree, NODE_INSTANCE_KEY_BASE);
this->m_context.setRenderData(rd);
this->m_context.setViewSettings(viewSettings);
@@ -78,11 +83,32 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re
this->groupOperations(); /* group operations in ExecutionGroups */
unsigned int index;
unsigned int resolution[2];
+
+ rctf *viewer_border = &editingtree->viewer_border;
+ bool use_viewer_border = (editingtree->flag & NTREE_VIEWER_BORDER) &&
+ viewer_border->xmin < viewer_border->xmax &&
+ viewer_border->ymin < viewer_border->ymax;
+
for (index = 0; index < this->m_groups.size(); index++) {
resolution[0] = 0;
resolution[1] = 0;
ExecutionGroup *executionGroup = this->m_groups[index];
executionGroup->determineResolution(resolution);
+
+ if (rendering) {
+ /* case when cropping to render border happens is handled in
+ * compositor output and render layer nodes
+ */
+ if ((rd->mode & R_BORDER) && !(rd->mode & R_CROP)) {
+ executionGroup->setRenderBorder(rd->border.xmin, rd->border.xmax,
+ rd->border.ymin, rd->border.ymax);
+ }
+ }
+
+ if (use_viewer_border) {
+ executionGroup->setViewerBorder(viewer_border->xmin, viewer_border->xmax,
+ viewer_border->ymin, viewer_border->ymax);
+ }
}
#ifdef COM_DEBUG
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.h b/source/blender/compositor/intern/COM_ExecutionSystem.h
index 25f06108d96..9beccba0c73 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.h
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.h
@@ -41,7 +41,8 @@ using namespace std;
* In order to get to an efficient model for execution, several steps are being done. these steps are explained below.
*
* @section EM_Step1 Step 1: translating blender node system to the new compsitor system
- * Blenders node structure is based on C structs (DNA). These structs are not efficient in the new architecture. We want to use classes in order to simplify the system.
+ * Blenders node structure is based on C structs (DNA). These structs are not efficient in the new architecture.
+ * We want to use classes in order to simplify the system.
* during this step the blender node_tree is evaluated and converted to a CPP node system.
*
* @see ExecutionSystem
@@ -49,13 +50,17 @@ using namespace std;
* @see Node
*
* @section EM_Step2 Step2: translating nodes to operations
- * Ungrouping the GroupNodes. Group nodes are node_tree's in node_tree's. The new system only supports a single level of node_tree. We will 'flatten' the system in a single level.
+ * Ungrouping the GroupNodes. Group nodes are node_tree's in node_tree's.
+ * The new system only supports a single level of node_tree. We will 'flatten' the system in a single level.
* @see GroupNode
* @see ExecutionSystemHelper.ungroup
*
- * Every node has the ability to convert itself to operations. The node itself is responsible to create a correct NodeOperation setup based on its internal settings.
- * Most Node only need to convert it to its NodeOperation. Like a ColorToBWNode doesn't check anything, but replaces itself with a ConvertColorToBWOperation.
- * More complex nodes can use different NodeOperation based on settings; like MixNode. based on the selected Mixtype a different operation will be used.
+ * Every node has the ability to convert itself to operations. The node itself is responsible to create a correct
+ * NodeOperation setup based on its internal settings.
+ * Most Node only need to convert it to its NodeOperation. Like a ColorToBWNode doesn't check anything,
+ * but replaces itself with a ConvertColorToBWOperation.
+ * More complex nodes can use different NodeOperation based on settings; like MixNode.
+ * based on the selected Mixtype a different operation will be used.
* for more information see the page about creating new Nodes. [@subpage newnode]
*
* @see ExecutionSystem.convertToOperations
@@ -63,9 +68,12 @@ using namespace std;
* @see NodeOperation base class for all operations in the system
*
* @section EM_Step3 Step3: add additional conversions to the operation system
- * - Data type conversions: the system has 3 data types COM_DT_VALUE, COM_DT_VECTOR, COM_DT_COLOR. The user can connect a Value socket to a color socket. As values are ordered differently than colors a conversion happens.
+ * - Data type conversions: the system has 3 data types COM_DT_VALUE, COM_DT_VECTOR, COM_DT_COLOR.
+ * The user can connect a Value socket to a color socket.
+ * As values are ordered differently than colors a conversion happens.
*
- * - Image size conversions: the system can automatically convert when resolutions do not match. An InputSocket has a resize mode. This can be any of the following settings.
+ * - Image size conversions: the system can automatically convert when resolutions do not match.
+ * An InputSocket has a resize mode. This can be any of the following settings.
* - [@ref InputSocketResizeMode.COM_SC_CENTER]: The center of both images are aligned
* - [@ref InputSocketResizeMode.COM_SC_FIT_WIDTH]: The width of both images are aligned
* - [@ref InputSocketResizeMode.COM_SC_FIT_HEIGHT]: the height of both images are aligned
@@ -77,8 +85,10 @@ using namespace std;
* @see Converter.convertResolution Image size conversions
*
* @section EM_Step4 Step4: group operations in executions groups
- * ExecutionGroup are groups of operations that are calculated as being one bigger operation. All operations will be part of an ExecutionGroup.
- * Complex nodes will be added to separate groups. Between ExecutionGroup's the data will be stored in MemoryBuffers. ReadBufferOperations and WriteBufferOperations are added where needed.
+ * ExecutionGroup are groups of operations that are calculated as being one bigger operation.
+ * All operations will be part of an ExecutionGroup.
+ * Complex nodes will be added to separate groups. Between ExecutionGroup's the data will be stored in MemoryBuffers.
+ * ReadBufferOperations and WriteBufferOperations are added where needed.
*
* <pre>
*
diff --git a/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp b/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp
index 506bd42ace3..ad396e053f2 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp
@@ -26,7 +26,6 @@
#include <stdio.h>
#include "PIL_time.h"
-#include "BKE_node.h"
#include "COM_Converter.h"
#include "COM_NodeOperation.h"
@@ -39,18 +38,25 @@
#include "COM_ReadBufferOperation.h"
#include "COM_ViewerBaseOperation.h"
-void ExecutionSystemHelper::addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNode *groupnode)
+extern "C" {
+#include "BKE_node.h"
+}
+
+void ExecutionSystemHelper::addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNodeInstanceKey parent_key)
{
vector<Node *>& nodes = system.getNodes();
vector<SocketConnection *>& links = system.getConnections();
- const bNode *activeGroupNode = system.getContext().getActivegNode();
- bool isActiveGroup = activeGroupNode == groupnode;
/* add all nodes of the tree to the node list */
bNode *node = (bNode *)tree->nodes.first;
while (node != NULL) {
+ /* XXX TODO replace isActiveGroup by a more accurate check, all visible editors should do this! */
+ bool isActiveGroup = true;
Node *nnode = addNode(nodes, node, isActiveGroup, system.getContext().isFastCalculation());
- nnode->setbNodeGroup(groupnode);
+ if (nnode) {
+ nnode->setbNodeTree(tree);
+ nnode->setInstanceKey(BKE_node_instance_key(parent_key, tree, node));
+ }
node = node->next;
}
@@ -81,8 +87,10 @@ void ExecutionSystemHelper::addNode(vector<Node *>& nodes, Node *node)
Node *ExecutionSystemHelper::addNode(vector<Node *>& nodes, bNode *b_node, bool inActiveGroup, bool fast)
{
Node *node = Converter::convert(b_node, fast);
- node->setIsInActiveGroup(inActiveGroup);
- addNode(nodes, node);
+ if (node) {
+ node->setIsInActiveGroup(inActiveGroup);
+ addNode(nodes, node);
+ }
return node;
}
void ExecutionSystemHelper::addOperation(vector<NodeOperation *>& operations, NodeOperation *operation)
@@ -109,43 +117,21 @@ void ExecutionSystemHelper::findOutputNodeOperations(vector<NodeOperation *> *re
static InputSocket *find_input(NodeRange &node_range, bNode *bnode, bNodeSocket *bsocket)
{
- if (bnode != NULL) {
- for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
- Node *node = *it;
- if (node->getbNode() == bnode)
- return node->findInputSocketBybNodeSocket(bsocket);
- }
- }
- else {
- for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
- Node *node = *it;
- if (node->isProxyNode()) {
- InputSocket *proxySocket = node->getInputSocket(0);
- if (proxySocket->getbNodeSocket() == bsocket)
- return proxySocket;
- }
- }
+ for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
+ Node *node = *it;
+ InputSocket *input = node->findInputSocketBybNodeSocket(bsocket);
+ if (input)
+ return input;
}
return NULL;
}
static OutputSocket *find_output(NodeRange &node_range, bNode *bnode, bNodeSocket *bsocket)
{
- if (bnode != NULL) {
- for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
- Node *node = *it;
- if (node->getbNode() == bnode)
- return node->findOutputSocketBybNodeSocket(bsocket);
- }
- }
- else {
- for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
- Node *node = *it;
- if (node->isProxyNode()) {
- OutputSocket *proxySocket = node->getOutputSocket(0);
- if (proxySocket->getbNodeSocket() == bsocket)
- return proxySocket;
- }
- }
+ for (NodeIterator it = node_range.first; it != node_range.second; ++it) {
+ Node *node = *it;
+ OutputSocket *output = node->findOutputSocketBybNodeSocket(bsocket);
+ if (output)
+ return output;
}
return NULL;
}
@@ -190,7 +176,7 @@ void ExecutionSystemHelper::debugDump(ExecutionSystem *system)
tot = system->getNodes().size();
for (int i = 0; i < tot; i++) {
node = system->getNodes()[i];
- printf("// NODE: %s\r\n", node->getbNode()->typeinfo->name);
+ printf("// NODE: %s\r\n", node->getbNode()->typeinfo->ui_name);
}
tot = system->getOperations().size();
for (int i = 0; i < tot; i++) {
diff --git a/source/blender/compositor/intern/COM_ExecutionSystemHelper.h b/source/blender/compositor/intern/COM_ExecutionSystemHelper.h
index 307e082ea80..e05796b9127 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystemHelper.h
+++ b/source/blender/compositor/intern/COM_ExecutionSystemHelper.h
@@ -48,7 +48,7 @@ public:
* @param tree bNodeTree to add
* @return Node representing the "Compositor node" of the maintree. or NULL when a subtree is added
*/
- static void addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNode *groupnode);
+ static void addbNodeTree(ExecutionSystem &system, int nodes_start, bNodeTree *tree, bNodeInstanceKey parent_key);
/**
* @brief add an editor node to the system.
diff --git a/source/blender/compositor/intern/COM_InputSocket.cpp b/source/blender/compositor/intern/COM_InputSocket.cpp
index 2493d4e5a27..6868745d631 100644
--- a/source/blender/compositor/intern/COM_InputSocket.cpp
+++ b/source/blender/compositor/intern/COM_InputSocket.cpp
@@ -157,24 +157,3 @@ NodeOperation *InputSocket::getOperation() const
return NULL;
}
}
-
-float *InputSocket::getStaticValues()
-{
- /* XXX only works for socket types with actual float input values.
- * currently all compositor socket types (value, rgba, vector) support this.
- */
- bNodeSocket *b_socket = this->getbNodeSocket();
- static float default_null = 0.0f;
-
- switch (this->getDataType()) {
- case COM_DT_VALUE:
- return &((bNodeSocketValueFloat *)b_socket->default_value)->value;
- case COM_DT_COLOR:
- return ((bNodeSocketValueRGBA *)b_socket->default_value)->value;
- case COM_DT_VECTOR:
- return ((bNodeSocketValueVector *)b_socket->default_value)->value;
- default:
- /* XXX this should never happen, just added to please the compiler */
- return &default_null;
- }
-}
diff --git a/source/blender/compositor/intern/COM_InputSocket.h b/source/blender/compositor/intern/COM_InputSocket.h
index 5cd4cf3beb7..5a36fe3f33b 100644
--- a/source/blender/compositor/intern/COM_InputSocket.h
+++ b/source/blender/compositor/intern/COM_InputSocket.h
@@ -143,7 +143,6 @@ public:
bool isStatic();
- float *getStaticValues();
SocketReader *getReader();
NodeOperation *getOperation() const;
};
diff --git a/source/blender/compositor/intern/COM_Node.cpp b/source/blender/compositor/intern/COM_Node.cpp
index d49bb5f96fb..f59580acb50 100644
--- a/source/blender/compositor/intern/COM_Node.cpp
+++ b/source/blender/compositor/intern/COM_Node.cpp
@@ -67,10 +67,9 @@ Node::Node(bNode *editorNode, bool create_sockets): NodeBase()
void Node::addSetValueOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex)
{
- bNodeSocket *bSock = this->getEditorInputSocket(editorNodeInputSocketIndex);
+ InputSocket *input = getInputSocket(editorNodeInputSocketIndex);
SetValueOperation *operation = new SetValueOperation();
- bNodeSocketValueFloat *val = (bNodeSocketValueFloat *)bSock->default_value;
- operation->setValue(val->value);
+ operation->setValue(input->getEditorValueFloat());
this->addLink(graph, operation->getOutputSocket(), inputsocket);
graph->addOperation(operation);
}
@@ -79,11 +78,13 @@ void Node::addPreviewOperation(ExecutionSystem *system, CompositorContext *conte
{
if (this->isInActiveGroup()) {
if (!(this->getbNode()->flag & NODE_HIDDEN)) { // do not calculate previews of hidden nodes.
- if (this->getbNode()->flag & NODE_PREVIEW) {
+ bNodeInstanceHash *previews = context->getPreviewHash();
+ if (previews && (this->getbNode()->flag & NODE_PREVIEW)) {
PreviewOperation *operation = new PreviewOperation(context->getViewSettings(), context->getDisplaySettings());
system->addOperation(operation);
operation->setbNode(this->getbNode());
operation->setbNodeTree(system->getContext().getbNodeTree());
+ operation->verifyPreview(previews, this->getInstanceKey());
this->addLink(system, outputSocket, operation->getInputSocket(0));
}
}
@@ -114,25 +115,27 @@ SocketConnection *Node::addLink(ExecutionSystem *graph, OutputSocket *outputSock
void Node::addSetColorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex)
{
- bNodeSocket *bSock = this->getEditorInputSocket(editorNodeInputSocketIndex);
+ InputSocket *input = getInputSocket(editorNodeInputSocketIndex);
SetColorOperation *operation = new SetColorOperation();
- bNodeSocketValueRGBA *val = (bNodeSocketValueRGBA *)bSock->default_value;
- operation->setChannel1(val->value[0]);
- operation->setChannel2(val->value[1]);
- operation->setChannel3(val->value[2]);
- operation->setChannel4(val->value[3]);
+ float col[4];
+ input->getEditorValueColor(col);
+ operation->setChannel1(col[0]);
+ operation->setChannel2(col[1]);
+ operation->setChannel3(col[2]);
+ operation->setChannel4(col[3]);
this->addLink(graph, operation->getOutputSocket(), inputsocket);
graph->addOperation(operation);
}
void Node::addSetVectorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex)
{
- bNodeSocket *bSock = this->getEditorInputSocket(editorNodeInputSocketIndex);
- bNodeSocketValueVector *val = (bNodeSocketValueVector *)bSock->default_value;
+ InputSocket *input = getInputSocket(editorNodeInputSocketIndex);
SetVectorOperation *operation = new SetVectorOperation();
- operation->setX(val->value[0]);
- operation->setY(val->value[1]);
- operation->setZ(val->value[2]);
+ float vec[3];
+ input->getEditorValueVector(vec);
+ operation->setX(vec[0]);
+ operation->setY(vec[1]);
+ operation->setZ(vec[2]);
this->addLink(graph, operation->getOutputSocket(), inputsocket);
graph->addOperation(operation);
}
diff --git a/source/blender/compositor/intern/COM_Node.h b/source/blender/compositor/intern/COM_Node.h
index c098d6da32b..fb5dfe2e9b7 100644
--- a/source/blender/compositor/intern/COM_Node.h
+++ b/source/blender/compositor/intern/COM_Node.h
@@ -53,12 +53,11 @@ private:
* @brief Is this node part of the active group
*/
bool m_inActiveGroup;
-
+
/**
- * @brief The group node this node belongs to.
- * @note: used to find the links in the current subtree for muting nodes
+ * @brief Instance key to identify the node in an instance hash table
*/
- bNode* m_bNodeGroup;
+ bNodeInstanceKey m_instanceKey;
public:
Node(bNode *editorNode, bool create_sockets = true);
@@ -145,8 +144,9 @@ public:
*/
OutputSocket *findOutputSocketBybNodeSocket(bNodeSocket *socket);
- inline void setbNodeGroup(bNode* group) {this->m_bNodeGroup = group;}
- inline bNode* getbNodeGroup() {return this->m_bNodeGroup;}
+ void setInstanceKey(bNodeInstanceKey instance_key) { m_instanceKey = instance_key; }
+ bNodeInstanceKey getInstanceKey() const { return m_instanceKey; }
+
protected:
void addPreviewOperation(ExecutionSystem *system, CompositorContext *context, InputSocket *inputSocket);
void addPreviewOperation(ExecutionSystem *system, CompositorContext *context, OutputSocket *outputSocket);
diff --git a/source/blender/compositor/intern/COM_NodeBase.h b/source/blender/compositor/intern/COM_NodeBase.h
index e386b5e08a0..41b6ab70bf9 100644
--- a/source/blender/compositor/intern/COM_NodeBase.h
+++ b/source/blender/compositor/intern/COM_NodeBase.h
@@ -59,6 +59,11 @@ private:
*/
bNode *m_editorNode;
+ /**
+ * @brief stores the reference to the SDNA bNode struct
+ */
+ bNodeTree *m_editorNodeTree;
+
protected:
/**
* @brief get access to the vector of input sockets
@@ -82,14 +87,25 @@ public:
/**
* @brief get the reference to the SDNA bNode struct
*/
- bNode *getbNode() {return m_editorNode;}
+ bNode *getbNode() const {return m_editorNode;}
+
+ /**
+ * @brief get the reference to the SDNA bNodeTree struct
+ */
+ bNodeTree *getbNodeTree() const {return m_editorNodeTree;}
/**
* @brief set the reference to the bNode
* @note used in Node instances to receive the storage/settings and complex node for highlight during execution
* @param bNode
*/
- void setbNode(bNode *bNode) {this->m_editorNode = bNode;}
+ void setbNode(bNode *node) {this->m_editorNode = node;}
+
+ /**
+ * @brief set the reference to the bNodeTree
+ * @param bNodeTree
+ */
+ void setbNodeTree(bNodeTree *nodetree) {this->m_editorNodeTree = nodetree;}
/**
* @brief is this node an operation?
diff --git a/source/blender/compositor/intern/COM_NodeOperation.cpp b/source/blender/compositor/intern/COM_NodeOperation.cpp
index a05c37e1b09..d33b8085022 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.cpp
+++ b/source/blender/compositor/intern/COM_NodeOperation.cpp
@@ -34,6 +34,7 @@ NodeOperation::NodeOperation() : NodeBase()
this->m_complex = false;
this->m_width = 0;
this->m_height = 0;
+ this->m_isResolutionSet = false;
this->m_openCL = false;
this->m_btree = NULL;
}
diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h
index f856d8e6a11..26a382929cb 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.h
+++ b/source/blender/compositor/intern/COM_NodeOperation.h
@@ -81,6 +81,10 @@ private:
*/
const bNodeTree *m_btree;
+ /**
+ * @brief set to truth when resolution for this operation is set
+ */
+ bool m_isResolutionSet;
public:
/**
* @brief is this node an operation?
@@ -170,7 +174,7 @@ public:
virtual void deinitExecution();
bool isResolutionSet() {
- return this->m_width != 0 && this->m_height != 0;
+ return this->m_isResolutionSet;
}
/**
@@ -181,6 +185,7 @@ public:
if (!isResolutionSet()) {
this->m_width = resolution[0];
this->m_height = resolution[1];
+ this->m_isResolutionSet = true;
}
}
@@ -254,8 +259,8 @@ public:
protected:
NodeOperation();
- void setWidth(unsigned int width) { this->m_width = width; }
- void setHeight(unsigned int height) { this->m_height = height; }
+ void setWidth(unsigned int width) { this->m_width = width; this->m_isResolutionSet = true; }
+ void setHeight(unsigned int height) { this->m_height = height; this->m_isResolutionSet = true; }
SocketReader *getInputSocketReader(unsigned int inputSocketindex);
NodeOperation *getInputOperation(unsigned int inputSocketindex);
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp
index d5da079c9fd..bb60a629812 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp
@@ -65,12 +65,16 @@ void OpenCLDevice::execute(WorkPackage *work)
executionGroup->finalizeChunkExecution(chunkNumber, inputBuffers);
}
-cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, int offsetIndex, list<cl_mem> *cleanup, MemoryBuffer **inputMemoryBuffers, SocketReader *reader)
+cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, int offsetIndex,
+ list<cl_mem> *cleanup, MemoryBuffer **inputMemoryBuffers,
+ SocketReader *reader)
{
return COM_clAttachMemoryBufferToKernelParameter(kernel, parameterIndex, offsetIndex, cleanup, inputMemoryBuffers, (ReadBufferOperation *)reader);
}
-cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, int offsetIndex, list<cl_mem> *cleanup, MemoryBuffer **inputMemoryBuffers, ReadBufferOperation *reader)
+cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, int parameterIndex, int offsetIndex,
+ list<cl_mem> *cleanup, MemoryBuffer **inputMemoryBuffers,
+ ReadBufferOperation *reader)
{
cl_int error;
diff --git a/source/blender/compositor/intern/COM_Socket.cpp b/source/blender/compositor/intern/COM_Socket.cpp
index 30f28f9dddb..3465fa6f56d 100644
--- a/source/blender/compositor/intern/COM_Socket.cpp
+++ b/source/blender/compositor/intern/COM_Socket.cpp
@@ -24,6 +24,10 @@
#include "COM_Node.h"
#include "COM_SocketConnection.h"
+extern "C" {
+#include "RNA_access.h"
+}
+
Socket::Socket(DataType datatype)
{
this->m_datatype = datatype;
@@ -41,3 +45,24 @@ int Socket::isOutputSocket() const { return false; }
const int Socket::isConnected() const { return false; }
void Socket::setNode(NodeBase *node) { this->m_node = node; }
NodeBase *Socket::getNode() const { return this->m_node; }
+
+float Socket::getEditorValueFloat()
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
+ return RNA_float_get(&ptr, "default_value");
+}
+
+void Socket::getEditorValueColor(float *value)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
+ return RNA_float_get_array(&ptr, "default_value", value);
+}
+
+void Socket::getEditorValueVector(float *value)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)getNode()->getbNodeTree(), &RNA_NodeSocket, getbNodeSocket(), &ptr);
+ return RNA_float_get_array(&ptr, "default_value", value);
+}
diff --git a/source/blender/compositor/intern/COM_Socket.h b/source/blender/compositor/intern/COM_Socket.h
index bad112d20c7..6532864a4d9 100644
--- a/source/blender/compositor/intern/COM_Socket.h
+++ b/source/blender/compositor/intern/COM_Socket.h
@@ -36,6 +36,7 @@
using namespace std;
class SocketConnection;
class NodeBase;
+struct PointerRNA;
/**
* @brief Base class for InputSocket and OutputSocket.
@@ -86,6 +87,10 @@ public:
void setEditorSocket(bNodeSocket *editorSocket) { this->m_editorSocket = editorSocket; }
bNodeSocket *getbNodeSocket() const { return this->m_editorSocket; }
+ float getEditorValueFloat();
+ void getEditorValueColor(float *value);
+ void getEditorValueVector(float *value);
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:Socket")
#endif
diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp
index 49ab9db5dd8..a0f660058f9 100644
--- a/source/blender/compositor/intern/COM_compositor.cpp
+++ b/source/blender/compositor/intern/COM_compositor.cpp
@@ -21,9 +21,9 @@
*/
-#include "BKE_node.h"
extern "C" {
- #include "BLI_threads.h"
+#include "BKE_node.h"
+#include "BLI_threads.h"
}
#include "BKE_main.h"
#include "BKE_global.h"
@@ -63,6 +63,13 @@ void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering,
return;
}
+ /* Make sure node tree has previews.
+ * Don't create previews in advance, this is done when adding preview operations.
+ * Reserved preview size is determined by render output for now.
+ */
+ float aspect = rd->xsch > 0 ? (float)rd->ysch / (float)rd->xsch : 1.0;
+ BKE_node_preview_init_tree(editingtree, COM_PREVIEW_SIZE, (int)(COM_PREVIEW_SIZE * aspect), FALSE);
+
/* initialize workscheduler, will check if already done. TODO deinitialize somewhere */
bool use_opencl = (editingtree->flag & NTREE_COM_OPENCL);
WorkScheduler::initialize(use_opencl);
@@ -85,7 +92,6 @@ void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering,
}
}
-
ExecutionSystem *system = new ExecutionSystem(rd, editingtree, rendering, false, viewSettings, displaySettings);
system->execute();
delete system;
diff --git a/source/blender/compositor/nodes/COM_BlurNode.cpp b/source/blender/compositor/nodes/COM_BlurNode.cpp
index 6a4987c2075..b59a92710bc 100644
--- a/source/blender/compositor/nodes/COM_BlurNode.cpp
+++ b/source/blender/compositor/nodes/COM_BlurNode.cpp
@@ -45,8 +45,7 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co
InputSocket *inputSizeSocket = this->getInputSocket(1);
bool connectedSizeSocket = inputSizeSocket->isConnected();
- const bNodeSocket *sock = this->getInputSocket(1)->getbNodeSocket();
- const float size = ((const bNodeSocketValueFloat *)sock->default_value)->value;
+ const float size = this->getInputSocket(1)->getEditorValueFloat();
CompositorQuality quality = context->getQuality();
NodeOperation *input_operation = NULL, *output_operation = NULL;
diff --git a/source/blender/compositor/nodes/COM_BokehBlurNode.cpp b/source/blender/compositor/nodes/COM_BokehBlurNode.cpp
index 70f20e3235b..5725bc6cb32 100644
--- a/source/blender/compositor/nodes/COM_BokehBlurNode.cpp
+++ b/source/blender/compositor/nodes/COM_BokehBlurNode.cpp
@@ -60,21 +60,17 @@ void BokehBlurNode::convertToOperations(ExecutionSystem *graph, CompositorContex
else {
BokehBlurOperation *operation = new BokehBlurOperation();
- const bNodeSocket *sock = this->getInputSocket(2)->getbNodeSocket();
- const float size = ((const bNodeSocketValueFloat *)sock->default_value)->value;
-
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
this->getInputSocket(2)->relinkConnections(operation->getInputSocket(3), 2, graph);
this->getInputSocket(3)->relinkConnections(operation->getInputSocket(2), 3, graph);
- //operation->setSize(((bNodeSocketValueFloat *)this->getInputSocket(2)->getbNodeSocket()->default_value)->value);
operation->setQuality(context->getQuality());
operation->setbNode(this->getbNode());
graph->addOperation(operation);
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
if (!connectedSizeSocket) {
- operation->setSize(size);
+ operation->setSize(this->getInputSocket(2)->getEditorValueFloat());
}
}
}
diff --git a/source/blender/compositor/nodes/COM_ColorCurveNode.cpp b/source/blender/compositor/nodes/COM_ColorCurveNode.cpp
index 93ff304afd8..103fbf26c7d 100644
--- a/source/blender/compositor/nodes/COM_ColorCurveNode.cpp
+++ b/source/blender/compositor/nodes/COM_ColorCurveNode.cpp
@@ -50,10 +50,11 @@ void ColorCurveNode::convertToOperations(ExecutionSystem *graph, CompositorConte
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
- bNodeSocketValueRGBA *val = (bNodeSocketValueRGBA *)this->getInputSocket(2)->getbNodeSocket()->default_value;
- operation->setBlackLevel(val->value);
- val = (bNodeSocketValueRGBA *)this->getInputSocket(3)->getbNodeSocket()->default_value;
- operation->setWhiteLevel(val->value);
+ float col[4];
+ this->getInputSocket(2)->getEditorValueColor(col);
+ operation->setBlackLevel(col);
+ this->getInputSocket(3)->getEditorValueColor(col);
+ operation->setWhiteLevel(col);
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
operation->setCurveMapping((CurveMapping *)this->getbNode()->storage);
diff --git a/source/blender/compositor/nodes/COM_ColorNode.cpp b/source/blender/compositor/nodes/COM_ColorNode.cpp
index 088f8bbb19d..fc2566e5a47 100644
--- a/source/blender/compositor/nodes/COM_ColorNode.cpp
+++ b/source/blender/compositor/nodes/COM_ColorNode.cpp
@@ -32,9 +32,10 @@ ColorNode::ColorNode(bNode *editorNode) : Node(editorNode)
void ColorNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
SetColorOperation *operation = new SetColorOperation();
- bNodeSocket *socket = this->getEditorOutputSocket(0);
- bNodeSocketValueRGBA *dval = (bNodeSocketValueRGBA *)socket->default_value;
- this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
- operation->setChannels(dval->value);
+ OutputSocket *output = this->getOutputSocket(0);
+ output->relinkConnections(operation->getOutputSocket());
+ float col[4];
+ output->getEditorValueColor(col);
+ operation->setChannels(col);
graph->addOperation(operation);
}
diff --git a/source/blender/compositor/nodes/COM_CompositorNode.cpp b/source/blender/compositor/nodes/COM_CompositorNode.cpp
index e3313750e66..f555e53f156 100644
--- a/source/blender/compositor/nodes/COM_CompositorNode.cpp
+++ b/source/blender/compositor/nodes/COM_CompositorNode.cpp
@@ -32,6 +32,8 @@ CompositorNode::CompositorNode(bNode *editorNode) : Node(editorNode)
void CompositorNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
bNode *editorNode = this->getbNode();
+ bool is_active = (editorNode->flag & NODE_DO_OUTPUT_RECALC) ||
+ context->isRendering();
InputSocket *imageSocket = this->getInputSocket(0);
InputSocket *alphaSocket = this->getInputSocket(1);
@@ -41,9 +43,12 @@ void CompositorNode::convertToOperations(ExecutionSystem *graph, CompositorConte
compositorOperation->setSceneName(editorNode->id->name);
compositorOperation->setRenderData(context->getRenderData());
compositorOperation->setbNodeTree(context->getbNodeTree());
+ compositorOperation->setIgnoreAlpha(editorNode->custom2 & CMP_NODE_OUTPUT_IGNORE_ALPHA);
+ compositorOperation->setActive(is_active);
imageSocket->relinkConnections(compositorOperation->getInputSocket(0), 0, graph);
alphaSocket->relinkConnections(compositorOperation->getInputSocket(1));
depthSocket->relinkConnections(compositorOperation->getInputSocket(2));
graph->addOperation(compositorOperation);
+
addPreviewOperation(graph, context, compositorOperation->getInputSocket(0));
}
diff --git a/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp b/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp
index 254dfb7b9c7..a7149cc63b2 100644
--- a/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp
+++ b/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp
@@ -20,8 +20,8 @@
*/
#include "COM_ConvertAlphaNode.h"
-#include "COM_ConvertPremulToKeyOperation.h"
-#include "COM_ConvertKeyToPremulOperation.h"
+#include "COM_ConvertPremulToStraightOperation.h"
+#include "COM_ConvertStraightToPremulOperation.h"
#include "COM_ExecutionSystem.h"
void ConvertAlphaNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
@@ -31,10 +31,10 @@ void ConvertAlphaNode::convertToOperations(ExecutionSystem *graph, CompositorCon
/* value hardcoded in rna_nodetree.c */
if (node->custom1 == 1) {
- operation = new ConvertPremulToKeyOperation();
+ operation = new ConvertPremulToStraightOperation();
}
else {
- operation = new ConvertKeyToPremulOperation();
+ operation = new ConvertStraightToPremulOperation();
}
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
diff --git a/source/blender/compositor/nodes/COM_GroupNode.cpp b/source/blender/compositor/nodes/COM_GroupNode.cpp
index e10d7dbad2e..09824a7b439 100644
--- a/source/blender/compositor/nodes/COM_GroupNode.cpp
+++ b/source/blender/compositor/nodes/COM_GroupNode.cpp
@@ -20,6 +20,8 @@
* Monique Dewanchand
*/
+#include "BKE_node.h"
+
#include "COM_GroupNode.h"
#include "COM_SocketProxyNode.h"
#include "COM_SetColorOperation.h"
@@ -37,13 +39,38 @@ void GroupNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
}
}
+static int find_group_input(GroupNode *gnode, const char *identifier, InputSocket **r_sock)
+{
+ int index;
+ for (index = 0; index < gnode->getNumberOfInputSockets(); ++index) {
+ InputSocket *sock = gnode->getInputSocket(index);
+ if (STREQ(sock->getbNodeSocket()->identifier, identifier)) {
+ *r_sock = sock;
+ return index;
+ }
+ }
+ *r_sock = NULL;
+ return -1;
+}
+
+static int find_group_output(GroupNode *gnode, const char *identifier, OutputSocket **r_sock)
+{
+ int index;
+ for (index = 0; index < gnode->getNumberOfOutputSockets(); ++index) {
+ OutputSocket *sock = gnode->getOutputSocket(index);
+ if (STREQ(sock->getbNodeSocket()->identifier, identifier)) {
+ *r_sock = sock;
+ return index;
+ }
+ }
+ *r_sock = NULL;
+ return -1;
+}
+
void GroupNode::ungroup(ExecutionSystem &system)
{
bNode *bnode = this->getbNode();
bNodeTree *subtree = (bNodeTree *)bnode->id;
- vector<InputSocket *> &inputsockets = this->getInputSockets();
- vector<OutputSocket *> &outputsockets = this->getOutputSockets();
- unsigned int index;
/* get the node list size _before_ adding proxy nodes, so they are available for linking */
int nodes_start = system.getNodes().size();
@@ -54,25 +81,44 @@ void GroupNode::ungroup(ExecutionSystem &system)
return;
}
- for (index = 0; index < inputsockets.size(); index++) {
- InputSocket *inputSocket = inputsockets[index];
- bNodeSocket *editorInput = inputSocket->getbNodeSocket();
- if (editorInput->groupsock) {
- SocketProxyNode *proxy = new SocketProxyNode(bnode, editorInput, editorInput->groupsock);
- inputSocket->relinkConnections(proxy->getInputSocket(0), index, &system);
- ExecutionSystemHelper::addNode(system.getNodes(), proxy);
- }
- }
+ const bool groupnodeBuffering = system.getContext().isGroupnodeBufferEnabled();
- for (index = 0; index < outputsockets.size(); index++) {
- OutputSocket *outputSocket = outputsockets[index];
- bNodeSocket *editorOutput = outputSocket->getbNodeSocket();
- if (editorOutput->groupsock) {
- SocketProxyNode *proxy = new SocketProxyNode(bnode, editorOutput->groupsock, editorOutput);
- outputSocket->relinkConnections(proxy->getOutputSocket(0));
- ExecutionSystemHelper::addNode(system.getNodes(), proxy);
+ /* create proxy nodes for group input/output nodes */
+ for (bNode *bionode = (bNode *)subtree->nodes.first; bionode; bionode = bionode->next) {
+ if (bionode->type == NODE_GROUP_INPUT) {
+ for (bNodeSocket *bsock = (bNodeSocket *)bionode->outputs.first; bsock; bsock = bsock->next) {
+ InputSocket *gsock;
+ int gsock_index = find_group_input(this, bsock->identifier, &gsock);
+ /* ignore virtual sockets */
+ if (gsock) {
+ SocketProxyNode *proxy = new SocketProxyNode(bionode, gsock->getbNodeSocket(), bsock, false);
+ ExecutionSystemHelper::addNode(system.getNodes(), proxy);
+
+ gsock->relinkConnectionsDuplicate(proxy->getInputSocket(0), gsock_index, &system);
+ }
+ }
+ }
+
+ if (bionode->type == NODE_GROUP_OUTPUT && (bionode->flag & NODE_DO_OUTPUT)) {
+ for (bNodeSocket *bsock = (bNodeSocket *)bionode->inputs.first; bsock; bsock = bsock->next) {
+ OutputSocket *gsock;
+ find_group_output(this, bsock->identifier, &gsock);
+ /* ignore virtual sockets */
+ if (gsock) {
+ SocketProxyNode *proxy = new SocketProxyNode(bionode, bsock, gsock->getbNodeSocket(), groupnodeBuffering);
+ ExecutionSystemHelper::addNode(system.getNodes(), proxy);
+
+ gsock->relinkConnections(proxy->getOutputSocket(0));
+ }
+ }
}
}
-
- ExecutionSystemHelper::addbNodeTree(system, nodes_start, subtree, bnode);
+
+ /* unlink the group node itself, input links have been duplicated */
+ for (int index = 0; index < this->getNumberOfInputSockets(); ++index) {
+ InputSocket *sock = this->getInputSocket(index);
+ sock->unlinkConnections(&system);
+ }
+
+ ExecutionSystemHelper::addbNodeTree(system, nodes_start, subtree, this->getInstanceKey());
}
diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp
index 4293e344c65..e4dd72d79e9 100644
--- a/source/blender/compositor/nodes/COM_ImageNode.cpp
+++ b/source/blender/compositor/nodes/COM_ImageNode.cpp
@@ -25,9 +25,14 @@
#include "COM_ExecutionSystem.h"
#include "COM_ImageOperation.h"
#include "COM_MultilayerImageOperation.h"
+#include "COM_ConvertPremulToStraightOperation.h"
#include "BKE_node.h"
#include "BLI_utildefines.h"
+#include "COM_SetValueOperation.h"
+#include "COM_SetVectorOperation.h"
+#include "COM_SetColorOperation.h"
+
ImageNode::ImageNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
@@ -68,6 +73,7 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
ImageUser *imageuser = (ImageUser *)editorNode->storage;
int framenumber = context->getFramenumber();
int numberOfOutputs = this->getNumberOfOutputSockets();
+ bool outputStraightAlpha = editorNode->custom1 & CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT;
BKE_image_user_frame_calc(imageuser, context->getFramenumber(), 0);
/* force a load, we assume iuser index will be set OK anyway */
@@ -134,7 +140,15 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
if (numberOfOutputs > 0) {
ImageOperation *operation = new ImageOperation();
if (outputImage->isConnected()) {
- outputImage->relinkConnections(operation->getOutputSocket());
+ if (outputStraightAlpha) {
+ NodeOperation *alphaConvertOperation = new ConvertPremulToStraightOperation();
+ addLink(graph, operation->getOutputSocket(0), alphaConvertOperation->getInputSocket(0));
+ outputImage->relinkConnections(alphaConvertOperation->getOutputSocket());
+ graph->addOperation(alphaConvertOperation);
+ }
+ else {
+ outputImage->relinkConnections(operation->getOutputSocket());
+ }
}
operation->setImage(image);
operation->setImageUser(imageuser);
@@ -165,6 +179,46 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
graph->addOperation(depthOperation);
}
}
+ if (numberOfOutputs > 3) {
+ /* happens when unlinking image datablock from multilayer node */
+ for (int i = 3; i < numberOfOutputs; i++) {
+ OutputSocket *output = this->getOutputSocket(i);
+ NodeOperation *operation = NULL;
+ switch (output->getDataType()) {
+ case COM_DT_VALUE:
+ {
+ SetValueOperation *valueoperation = new SetValueOperation();
+ valueoperation->setValue(0.0f);
+ operation = valueoperation;
+ break;
+ }
+ case COM_DT_VECTOR:
+ {
+ SetVectorOperation *vectoroperation = new SetVectorOperation();
+ vectoroperation->setX(0.0f);
+ vectoroperation->setY(0.0f);
+ vectoroperation->setW(0.0f);
+ operation = vectoroperation;
+ break;
+ }
+ case COM_DT_COLOR:
+ {
+ SetColorOperation *coloroperation = new SetColorOperation();
+ coloroperation->setChannel1(0.0f);
+ coloroperation->setChannel2(0.0f);
+ coloroperation->setChannel3(0.0f);
+ coloroperation->setChannel4(0.0f);
+ operation = coloroperation;
+ break;
+ }
+ }
+
+ if (operation) {
+ output->relinkConnections(operation->getOutputSocket());
+ graph->addOperation(operation);
+ }
+ }
+ }
}
}
diff --git a/source/blender/compositor/nodes/COM_LensDistortionNode.cpp b/source/blender/compositor/nodes/COM_LensDistortionNode.cpp
index 94c2fc885fb..f91744d88b6 100644
--- a/source/blender/compositor/nodes/COM_LensDistortionNode.cpp
+++ b/source/blender/compositor/nodes/COM_LensDistortionNode.cpp
@@ -51,8 +51,8 @@ void LensDistortionNode::convertToOperations(ExecutionSystem *graph, CompositorC
operation->setData(data);
if (!(this->getInputSocket(1)->isConnected() || this->getInputSocket(2)->isConnected())) {
// no nodes connected to the distortion and dispersion. We can precalculate some values
- float distortion = ((const bNodeSocketValueFloat *)this->getInputSocket(1)->getbNodeSocket()->default_value)->value;
- float dispersion = ((const bNodeSocketValueFloat *)this->getInputSocket(2)->getbNodeSocket()->default_value)->value;
+ float distortion = this->getInputSocket(1)->getEditorValueFloat();
+ float dispersion = this->getInputSocket(2)->getEditorValueFloat();
operation->setDistortionAndDispersion(distortion, dispersion);
}
diff --git a/source/blender/compositor/nodes/COM_MixNode.cpp b/source/blender/compositor/nodes/COM_MixNode.cpp
index ab4e464327d..3e8f1fb0f74 100644
--- a/source/blender/compositor/nodes/COM_MixNode.cpp
+++ b/source/blender/compositor/nodes/COM_MixNode.cpp
@@ -124,6 +124,16 @@ void MixNode::convertToOperations(ExecutionSystem *graph, CompositorContext *con
convertProg->setUseValueAlphaMultiply(useAlphaPremultiply);
convertProg->setUseClamp(useClamp);
+ if (color1Socket->isConnected()) {
+ convertProg->setResolutionInputSocketIndex(1);
+ }
+ else {
+ if (color2Socket->isConnected())
+ convertProg->setResolutionInputSocketIndex(2);
+ else
+ convertProg->setResolutionInputSocketIndex(0);
+ }
+
valueSocket->relinkConnections(convertProg->getInputSocket(0), 0, graph);
color1Socket->relinkConnections(convertProg->getInputSocket(1), 1, graph);
color2Socket->relinkConnections(convertProg->getInputSocket(2), 2, graph);
diff --git a/source/blender/compositor/nodes/COM_MovieClipNode.cpp b/source/blender/compositor/nodes/COM_MovieClipNode.cpp
index 5d5e68fba37..10dd72ec7bf 100644
--- a/source/blender/compositor/nodes/COM_MovieClipNode.cpp
+++ b/source/blender/compositor/nodes/COM_MovieClipNode.cpp
@@ -41,10 +41,11 @@ MovieClipNode::MovieClipNode(bNode *editorNode) : Node(editorNode)
void MovieClipNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
OutputSocket *outputMovieClip = this->getOutputSocket(0);
- OutputSocket *offsetXMovieClip = this->getOutputSocket(1);
- OutputSocket *offsetYMovieClip = this->getOutputSocket(2);
- OutputSocket *scaleMovieClip = this->getOutputSocket(3);
- OutputSocket *angleMovieClip = this->getOutputSocket(4);
+ OutputSocket *alphaMovieClip = this->getOutputSocket(1);
+ OutputSocket *offsetXMovieClip = this->getOutputSocket(2);
+ OutputSocket *offsetYMovieClip = this->getOutputSocket(3);
+ OutputSocket *scaleMovieClip = this->getOutputSocket(4);
+ OutputSocket *angleMovieClip = this->getOutputSocket(5);
bNode *editorNode = this->getbNode();
MovieClip *movieClip = (MovieClip *)editorNode->id;
@@ -73,6 +74,16 @@ void MovieClipNode::convertToOperations(ExecutionSystem *graph, CompositorContex
operation->setCacheFrame(cacheFrame);
graph->addOperation(operation);
+ if (alphaMovieClip->isConnected()) {
+ MovieClipAlphaOperation *alphaOperation = new MovieClipAlphaOperation();
+ alphaOperation->setMovieClip(movieClip);
+ alphaOperation->setMovieClipUser(movieClipUser);
+ alphaOperation->setFramenumber(context->getFramenumber());
+ alphaOperation->setCacheFrame(cacheFrame);
+ alphaMovieClip->relinkConnections(alphaOperation->getOutputSocket());
+ graph->addOperation(alphaOperation);
+ }
+
MovieTrackingStabilization *stab = &movieClip->tracking.stabilization;
float loc[2], scale, angle;
loc[0] = 0.0f;
@@ -87,7 +98,7 @@ void MovieClipNode::convertToOperations(ExecutionSystem *graph, CompositorContex
BKE_tracking_stabilization_data_get(&movieClip->tracking, clip_framenr, ibuf->x, ibuf->y, loc, &scale, &angle);
}
}
-
+
if (offsetXMovieClip->isConnected()) {
SetValueOperation *operationSetValue = new SetValueOperation();
operationSetValue->setValue(loc[0]);
diff --git a/source/blender/compositor/nodes/COM_NormalNode.cpp b/source/blender/compositor/nodes/COM_NormalNode.cpp
index fbfff8386d0..41b91f61328 100644
--- a/source/blender/compositor/nodes/COM_NormalNode.cpp
+++ b/source/blender/compositor/nodes/COM_NormalNode.cpp
@@ -36,15 +36,13 @@ void NormalNode::convertToOperations(ExecutionSystem *graph, CompositorContext *
InputSocket *inputSocket = this->getInputSocket(0);
OutputSocket *outputSocket = this->getOutputSocket(0);
OutputSocket *outputSocketDotproduct = this->getOutputSocket(1);
- bNode *editorNode = this->getbNode();
SetVectorOperation *operationSet = new SetVectorOperation();
- bNodeSocket *insock = (bNodeSocket *)editorNode->outputs.first;
- bNodeSocketValueVector *dval = (bNodeSocketValueVector *)insock->default_value;
float normal[3];
+ outputSocket->getEditorValueVector(normal);
/* animation can break normalization, this restores it */
- normalize_v3_v3(normal, dval->value);
+ normalize_v3(normal);
operationSet->setX(normal[0]);
operationSet->setY(normal[1]);
diff --git a/source/blender/compositor/nodes/COM_PixelateNode.cpp b/source/blender/compositor/nodes/COM_PixelateNode.cpp
index f1c7c616a30..b751c9a6e9f 100644
--- a/source/blender/compositor/nodes/COM_PixelateNode.cpp
+++ b/source/blender/compositor/nodes/COM_PixelateNode.cpp
@@ -36,8 +36,8 @@ void PixelateNode::convertToOperations(ExecutionSystem *graph, CompositorContext
OutputSocket *outputSocket = this->getOutputSocket(0);
DataType datatype = inputSocket->getDataType();
if (inputSocket->isConnected()) {
- SocketConnection * connection = inputSocket->getConnection();
- OutputSocket* otherOutputSocket = connection->getFromSocket();
+ SocketConnection *connection = inputSocket->getConnection();
+ OutputSocket *otherOutputSocket = connection->getFromSocket();
datatype = otherOutputSocket->getDataType();
}
diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp
index b57e99754d6..5259fbc7dc5 100644
--- a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp
+++ b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp
@@ -61,6 +61,7 @@ void RenderLayersNode::testSocketConnection(ExecutionSystem *system, CompositorC
if (outputSocket->isConnected()) {
operation->setScene(scene);
operation->setLayerId(layerId);
+ operation->setRenderData(context->getRenderData());
outputSocket->relinkConnections(operation->getOutputSocket());
system->addOperation(operation);
if (outputSocketNumber == 0) { // only do for image socket if connected
@@ -72,6 +73,7 @@ void RenderLayersNode::testSocketConnection(ExecutionSystem *system, CompositorC
system->addOperation(operation);
operation->setScene(scene);
operation->setLayerId(layerId);
+ operation->setRenderData(context->getRenderData());
addPreviewOperation(system, context, operation->getOutputSocket());
}
else {
diff --git a/source/blender/compositor/nodes/COM_ScaleNode.cpp b/source/blender/compositor/nodes/COM_ScaleNode.cpp
index 6f7bd33db6f..e139eb83e04 100644
--- a/source/blender/compositor/nodes/COM_ScaleNode.cpp
+++ b/source/blender/compositor/nodes/COM_ScaleNode.cpp
@@ -43,7 +43,8 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
bNode *bnode = this->getbNode();
switch (bnode->custom1) {
- case CMP_SCALE_RELATIVE: {
+ case CMP_SCALE_RELATIVE:
+ {
ScaleOperation *operation = new ScaleOperation();
inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph);
@@ -51,9 +52,10 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
inputYSocket->relinkConnections(operation->getInputSocket(2), 2, graph);
scaleoperation = operation;
+ break;
}
- break;
- case CMP_SCALE_SCENEPERCENT: {
+ case CMP_SCALE_SCENEPERCENT:
+ {
SetValueOperation *scaleFactorOperation = new SetValueOperation();
scaleFactorOperation->setValue(context->getRenderData()->size / 100.0f);
ScaleOperation *operation = new ScaleOperation();
@@ -63,10 +65,10 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
graph->addOperation(scaleFactorOperation);
scaleoperation = operation;
+ break;
}
- break;
-
- case CMP_SCALE_RENDERPERCENT: {
+ case CMP_SCALE_RENDERPERCENT:
+ {
const RenderData *rd = context->getRenderData();
ScaleFixedSizeOperation *operation = new ScaleFixedSizeOperation();
@@ -81,10 +83,10 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
operation->getInputSocket(0)->getConnection()->setIgnoreResizeCheck(true);
scaleoperation = operation;
+ break;
}
- break;
-
- case CMP_SCALE_ABSOLUTE: {
+ case CMP_SCALE_ABSOLUTE:
+ {
ScaleAbsoluteOperation *operation = new ScaleAbsoluteOperation(); // TODO: what is the use of this one.... perhaps some issues when the ui was updated....
inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph);
@@ -92,8 +94,8 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
inputYSocket->relinkConnections(operation->getInputSocket(2), 2, graph);
scaleoperation = operation;
+ break;
}
- break;
}
outputSocket->relinkConnections(scaleoperation->getOutputSocket(0));
diff --git a/source/blender/compositor/nodes/COM_SetAlphaNode.cpp b/source/blender/compositor/nodes/COM_SetAlphaNode.cpp
index 709dc75b502..dd3ff5fbaa7 100644
--- a/source/blender/compositor/nodes/COM_SetAlphaNode.cpp
+++ b/source/blender/compositor/nodes/COM_SetAlphaNode.cpp
@@ -27,7 +27,11 @@
void SetAlphaNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
SetAlphaOperation *operation = new SetAlphaOperation();
-
+
+ if (!this->getInputSocket(0)->isConnected() && this->getInputSocket(1)->isConnected()) {
+ operation->setResolutionInputSocketIndex(1);
+ }
+
this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph);
this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph);
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
diff --git a/source/blender/compositor/nodes/COM_SocketProxyNode.cpp b/source/blender/compositor/nodes/COM_SocketProxyNode.cpp
index bfb32a96156..c822d2107ec 100644
--- a/source/blender/compositor/nodes/COM_SocketProxyNode.cpp
+++ b/source/blender/compositor/nodes/COM_SocketProxyNode.cpp
@@ -27,11 +27,14 @@
#include "COM_SetValueOperation.h"
#include "COM_SetVectorOperation.h"
#include "COM_SetColorOperation.h"
+#include "COM_WriteBufferOperation.h"
+#include "COM_ReadBufferOperation.h"
-SocketProxyNode::SocketProxyNode(bNode *editorNode, bNodeSocket *editorInput, bNodeSocket *editorOutput) : Node(editorNode, false)
+SocketProxyNode::SocketProxyNode(bNode *editorNode, bNodeSocket *editorInput, bNodeSocket *editorOutput, bool buffer) : Node(editorNode, false)
{
DataType dt;
-
+ this->m_buffer = buffer;
+
dt = COM_DT_VALUE;
if (editorInput->type == SOCK_RGBA) dt = COM_DT_COLOR;
if (editorInput->type == SOCK_VECTOR) dt = COM_DT_VECTOR;
@@ -47,43 +50,54 @@ void SocketProxyNode::convertToOperations(ExecutionSystem *graph, CompositorCont
{
OutputSocket *outputsocket = this->getOutputSocket(0);
InputSocket *inputsocket = this->getInputSocket(0);
- if (outputsocket->isConnected()) {
- if (inputsocket->isConnected()) {
- SocketProxyOperation *operation = new SocketProxyOperation(this->getOutputSocket()->getDataType());
- inputsocket->relinkConnections(operation->getInputSocket(0));
- outputsocket->relinkConnections(operation->getOutputSocket(0));
- graph->addOperation(operation);
+ if (inputsocket->isConnected()) {
+ SocketProxyOperation *operation = new SocketProxyOperation(this->getOutputSocket()->getDataType());
+ inputsocket->relinkConnections(operation->getInputSocket(0));
+ outputsocket->relinkConnections(operation->getOutputSocket(0));
+ graph->addOperation(operation);
+
+ if (m_buffer) {
+ WriteBufferOperation *writeOperation = new WriteBufferOperation();
+ ReadBufferOperation *readOperation = new ReadBufferOperation();
+ readOperation->setMemoryProxy(writeOperation->getMemoryProxy());
+
+ operation->getOutputSocket()->relinkConnections(readOperation->getOutputSocket());
+ addLink(graph, operation->getOutputSocket(), writeOperation->getInputSocket(0));
+
+ graph->addOperation(writeOperation);
+ graph->addOperation(readOperation);
}
- else {
- /* If input is not connected, add a constant value operation instead */
- switch (outputsocket->getDataType()) {
- case COM_DT_VALUE:
- {
- SetValueOperation *operation = new SetValueOperation();
- bNodeSocketValueFloat *dval = (bNodeSocketValueFloat *)inputsocket->getbNodeSocket()->default_value;
- operation->setValue(dval->value);
- outputsocket->relinkConnections(operation->getOutputSocket(0));
- graph->addOperation(operation);
- break;
- }
- case COM_DT_COLOR:
- {
- SetColorOperation *operation = new SetColorOperation();
- bNodeSocketValueRGBA *dval = (bNodeSocketValueRGBA *)inputsocket->getbNodeSocket()->default_value;
- operation->setChannels(dval->value);
- outputsocket->relinkConnections(operation->getOutputSocket(0));
- graph->addOperation(operation);
- break;
- }
- case COM_DT_VECTOR:
- {
- SetVectorOperation *operation = new SetVectorOperation();
- bNodeSocketValueVector *dval = (bNodeSocketValueVector *)inputsocket->getbNodeSocket()->default_value;
- operation->setVector(dval->value);
- outputsocket->relinkConnections(operation->getOutputSocket(0));
- graph->addOperation(operation);
- break;
- }
+ }
+ else if (outputsocket->isConnected()) {
+ /* If input is not connected, add a constant value operation instead */
+ switch (outputsocket->getDataType()) {
+ case COM_DT_VALUE:
+ {
+ SetValueOperation *operation = new SetValueOperation();
+ operation->setValue(inputsocket->getEditorValueFloat());
+ outputsocket->relinkConnections(operation->getOutputSocket(0));
+ graph->addOperation(operation);
+ break;
+ }
+ case COM_DT_COLOR:
+ {
+ SetColorOperation *operation = new SetColorOperation();
+ float col[4];
+ inputsocket->getEditorValueColor(col);
+ operation->setChannels(col);
+ outputsocket->relinkConnections(operation->getOutputSocket(0));
+ graph->addOperation(operation);
+ break;
+ }
+ case COM_DT_VECTOR:
+ {
+ SetVectorOperation *operation = new SetVectorOperation();
+ float vec[3];
+ inputsocket->getEditorValueVector(vec);
+ operation->setVector(vec);
+ outputsocket->relinkConnections(operation->getOutputSocket(0));
+ graph->addOperation(operation);
+ break;
}
}
}
diff --git a/source/blender/compositor/nodes/COM_SocketProxyNode.h b/source/blender/compositor/nodes/COM_SocketProxyNode.h
index ea50be418e2..b679901ba2c 100644
--- a/source/blender/compositor/nodes/COM_SocketProxyNode.h
+++ b/source/blender/compositor/nodes/COM_SocketProxyNode.h
@@ -30,8 +30,10 @@
* @ingroup Node
*/
class SocketProxyNode : public Node {
+private:
+ bool m_buffer;
public:
- SocketProxyNode(bNode *editorNode, bNodeSocket *editorInput, bNodeSocket *editorOutput);
+ SocketProxyNode(bNode *editorNode, bNodeSocket *editorInput, bNodeSocket *editorOutput, bool buffer);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
virtual bool isProxyNode() const { return true; }
diff --git a/source/blender/compositor/nodes/COM_SplitViewerNode.cpp b/source/blender/compositor/nodes/COM_SplitViewerNode.cpp
index 37b888becca..0293f4926db 100644
--- a/source/blender/compositor/nodes/COM_SplitViewerNode.cpp
+++ b/source/blender/compositor/nodes/COM_SplitViewerNode.cpp
@@ -33,6 +33,11 @@ SplitViewerNode::SplitViewerNode(bNode *editorNode) : Node(editorNode)
void SplitViewerNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
+ bNode *editorNode = this->getbNode();
+ bool is_active = ((editorNode->flag & NODE_DO_OUTPUT_RECALC) &&
+ (editorNode->flag & NODE_DO_OUTPUT) && this->isInActiveGroup()) ||
+ context->isRendering();
+
InputSocket *image1Socket = this->getInputSocket(0);
InputSocket *image2Socket = this->getInputSocket(1);
Image *image = (Image *)this->getbNode()->id;
@@ -41,7 +46,7 @@ void SplitViewerNode::convertToOperations(ExecutionSystem *graph, CompositorCont
SplitViewerOperation *splitViewerOperation = new SplitViewerOperation();
splitViewerOperation->setImage(image);
splitViewerOperation->setImageUser(imageUser);
- splitViewerOperation->setActive((this->getbNode()->flag & NODE_DO_OUTPUT) && this->isInActiveGroup());
+ splitViewerOperation->setActive(is_active);
splitViewerOperation->setSplitPercentage(this->getbNode()->custom1);
splitViewerOperation->setViewSettings(context->getViewSettings());
@@ -56,7 +61,10 @@ void SplitViewerNode::convertToOperations(ExecutionSystem *graph, CompositorCont
splitViewerOperation->setXSplit(!this->getbNode()->custom2);
image1Socket->relinkConnections(splitViewerOperation->getInputSocket(0), 0, graph);
image2Socket->relinkConnections(splitViewerOperation->getInputSocket(1), 1, graph);
- addPreviewOperation(graph, context, splitViewerOperation->getInputSocket(0));
+
+ if (is_active)
+ addPreviewOperation(graph, context, splitViewerOperation->getInputSocket(0));
+
graph->addOperation(splitViewerOperation);
}
}
diff --git a/source/blender/compositor/nodes/COM_TranslateNode.cpp b/source/blender/compositor/nodes/COM_TranslateNode.cpp
index c805f8f8baa..44d796c2911 100644
--- a/source/blender/compositor/nodes/COM_TranslateNode.cpp
+++ b/source/blender/compositor/nodes/COM_TranslateNode.cpp
@@ -23,6 +23,7 @@
#include "COM_TranslateNode.h"
#include "COM_TranslateOperation.h"
+#include "COM_WrapOperation.h"
#include "COM_ExecutionSystem.h"
TranslateNode::TranslateNode(bNode *editorNode) : Node(editorNode)
@@ -37,10 +38,32 @@ void TranslateNode::convertToOperations(ExecutionSystem *graph, CompositorContex
InputSocket *inputYSocket = this->getInputSocket(2);
OutputSocket *outputSocket = this->getOutputSocket(0);
TranslateOperation *operation = new TranslateOperation();
-
- inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph);
+
+ bNode *bnode = this->getbNode();
+ NodeTranslateData *data = (NodeTranslateData *)bnode->storage;
+
+ if (data->wrap_axis) {
+ WrapOperation *wrapOperation = new WrapOperation();
+ wrapOperation->setWrapping(data->wrap_axis);
+ inputSocket->relinkConnections(wrapOperation->getInputSocket(0), 0, graph);
+ addLink(graph, wrapOperation->getOutputSocket(), operation->getInputSocket(0));
+ graph->addOperation(wrapOperation);
+ }
+ else {
+ inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph);
+ }
+
+ if (data->relative) {
+ const RenderData *rd = context->getRenderData();
+ float fx = rd->xsch * rd->size / 100.0f;
+ float fy = rd->ysch * rd->size / 100.0f;
+
+ operation->setFactorXY(fx, fy);
+ }
+
inputXSocket->relinkConnections(operation->getInputSocket(1), 1, graph);
inputYSocket->relinkConnections(operation->getInputSocket(2), 2, graph);
outputSocket->relinkConnections(operation->getOutputSocket(0));
graph->addOperation(operation);
}
+
diff --git a/source/blender/compositor/nodes/COM_ValueNode.cpp b/source/blender/compositor/nodes/COM_ValueNode.cpp
index 593d74952ee..ed4440aa099 100644
--- a/source/blender/compositor/nodes/COM_ValueNode.cpp
+++ b/source/blender/compositor/nodes/COM_ValueNode.cpp
@@ -32,9 +32,8 @@ ValueNode::ValueNode(bNode *editorNode) : Node(editorNode)
void ValueNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
SetValueOperation *operation = new SetValueOperation();
- bNodeSocket *socket = this->getEditorOutputSocket(0);
- bNodeSocketValueFloat *dval = (bNodeSocketValueFloat *)socket->default_value;
- this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
- operation->setValue(dval->value);
+ OutputSocket *output = this->getOutputSocket(0);
+ output->relinkConnections(operation->getOutputSocket());
+ operation->setValue(output->getEditorValueFloat());
graph->addOperation(operation);
}
diff --git a/source/blender/compositor/nodes/COM_ViewerNode.cpp b/source/blender/compositor/nodes/COM_ViewerNode.cpp
index f44470a9b9a..70cc3a288ee 100644
--- a/source/blender/compositor/nodes/COM_ViewerNode.cpp
+++ b/source/blender/compositor/nodes/COM_ViewerNode.cpp
@@ -33,20 +33,25 @@ ViewerNode::ViewerNode(bNode *editorNode) : Node(editorNode)
void ViewerNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
+ bNode *editorNode = this->getbNode();
+ bool is_active = ((editorNode->flag & NODE_DO_OUTPUT_RECALC) &&
+ (editorNode->flag & NODE_DO_OUTPUT) && this->isInActiveGroup()) ||
+ context->isRendering();
+
InputSocket *imageSocket = this->getInputSocket(0);
InputSocket *alphaSocket = this->getInputSocket(1);
InputSocket *depthSocket = this->getInputSocket(2);
Image *image = (Image *)this->getbNode()->id;
ImageUser *imageUser = (ImageUser *) this->getbNode()->storage;
- bNode *editorNode = this->getbNode();
ViewerOperation *viewerOperation = new ViewerOperation();
viewerOperation->setbNodeTree(context->getbNodeTree());
viewerOperation->setImage(image);
viewerOperation->setImageUser(imageUser);
- viewerOperation->setActive((editorNode->flag & NODE_DO_OUTPUT) && this->isInActiveGroup());
+ viewerOperation->setActive(is_active);
viewerOperation->setChunkOrder((OrderOfChunks)editorNode->custom1);
viewerOperation->setCenterX(editorNode->custom3);
viewerOperation->setCenterY(editorNode->custom4);
+ viewerOperation->setIgnoreAlpha(editorNode->custom2 & CMP_NODE_OUTPUT_IGNORE_ALPHA);
viewerOperation->setViewSettings(context->getViewSettings());
viewerOperation->setDisplaySettings(context->getDisplaySettings());
@@ -62,5 +67,6 @@ void ViewerNode::convertToOperations(ExecutionSystem *graph, CompositorContext *
alphaSocket->relinkConnections(viewerOperation->getInputSocket(1));
depthSocket->relinkConnections(viewerOperation->getInputSocket(2));
graph->addOperation(viewerOperation);
+
addPreviewOperation(graph, context, viewerOperation->getInputSocket(0));
}
diff --git a/source/blender/compositor/operations/COM_ChannelMatteOperation.cpp b/source/blender/compositor/operations/COM_ChannelMatteOperation.cpp
index 234a1c7b1e5..84cc8aad950 100644
--- a/source/blender/compositor/operations/COM_ChannelMatteOperation.cpp
+++ b/source/blender/compositor/operations/COM_ChannelMatteOperation.cpp
@@ -38,7 +38,8 @@ void ChannelMatteOperation::initExecution()
switch (this->m_limit_method) {
/* SINGLE */
- case 0: {
+ case 0:
+ {
/* 123 / RGB / HSV / YUV / YCC */
const int matte_channel = this->m_matte_channel - 1;
const int limit_channel = this->m_limit_channel - 1;
@@ -48,21 +49,25 @@ void ChannelMatteOperation::initExecution()
break;
}
/* MAX */
- case 1: {
+ case 1:
+ {
switch (this->m_matte_channel) {
- case 1: {
+ case 1:
+ {
this->m_ids[0] = 0;
this->m_ids[1] = 1;
this->m_ids[2] = 2;
break;
}
- case 2: {
+ case 2:
+ {
this->m_ids[0] = 1;
this->m_ids[1] = 0;
this->m_ids[2] = 2;
break;
}
- case 3: {
+ case 3:
+ {
this->m_ids[0] = 2;
this->m_ids[1] = 0;
this->m_ids[2] = 1;
diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cpp b/source/blender/compositor/operations/COM_CompositorOperation.cpp
index 141d071dddc..56527da47bc 100644
--- a/source/blender/compositor/operations/COM_CompositorOperation.cpp
+++ b/source/blender/compositor/operations/COM_CompositorOperation.cpp
@@ -49,11 +49,17 @@ CompositorOperation::CompositorOperation() : NodeOperation()
this->m_alphaInput = NULL;
this->m_depthInput = NULL;
+ this->m_ignoreAlpha = false;
+ this->m_active = false;
+
this->m_sceneName[0] = '\0';
}
void CompositorOperation::initExecution()
{
+ if (!this->m_active)
+ return;
+
// When initializing the tree during initial load the width and height can be zero.
this->m_imageInput = getInputSocketReader(0);
this->m_alphaInput = getInputSocketReader(1);
@@ -68,6 +74,9 @@ void CompositorOperation::initExecution()
void CompositorOperation::deinitExecution()
{
+ if (!this->m_active)
+ return;
+
if (!isBreaked()) {
Render *re = RE_GetRender(this->m_sceneName);
RenderResult *rr = RE_AcquireResultWrite(re);
@@ -91,14 +100,14 @@ void CompositorOperation::deinitExecution()
}
}
- BLI_lock_thread(LOCK_DRAW_IMAGE);
- BKE_image_signal(BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE);
- BLI_unlock_thread(LOCK_DRAW_IMAGE);
-
if (re) {
RE_ReleaseResult(re);
re = NULL;
}
+
+ BLI_lock_thread(LOCK_DRAW_IMAGE);
+ BKE_image_signal(BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE);
+ BLI_unlock_thread(LOCK_DRAW_IMAGE);
}
else {
if (this->m_outputBuffer) {
@@ -134,17 +143,63 @@ void CompositorOperation::executeRegion(rcti *rect, unsigned int tileNumber)
int x;
int y;
bool breaked = false;
+ int dx = 0, dy = 0;
+
+ const RenderData *rd = this->m_rd;
+
+ if (rd->mode & R_BORDER && rd->mode & R_CROP) {
+ /*!
+ When using cropped render result, need to re-position area of interest,
+ so it'll natch bounds of render border within frame. By default, canvas
+ will be centered between full frame and cropped frame, so we use such
+ scheme to map cropped coordinates to full-frame coordinates
+
+ ^ Y
+ | Width
+ +------------------------------------------------+
+ | |
+ | |
+ | Centered canvas, we map coordinate from it |
+ | +------------------+ |
+ | | | | H
+ | | | | e
+ | +------------------+ . Center | | i
+ | | | | | | g
+ | | | | | | h
+ | |....dx.... +------|-----------+ | t
+ | | . dy | |
+ | +------------------+ |
+ | Render border, we map coordinates to it |
+ | | X
+ +------------------------------------------------+---->
+ Full frame
+ */
+
+ int full_width = rd->xsch * rd->size / 100;
+ int full_height =rd->ysch * rd->size / 100;
+
+ dx = rd->border.xmin * full_width - (full_width - this->getWidth()) / 2.0f;
+ dy = rd->border.ymin * full_height - (full_height - this->getHeight()) / 2.0f;
+ }
for (y = y1; y < y2 && (!breaked); y++) {
for (x = x1; x < x2 && (!breaked); x++) {
- this->m_imageInput->read(color, x, y, COM_PS_NEAREST);
- if (this->m_alphaInput != NULL) {
- this->m_alphaInput->read(&(color[3]), x, y, COM_PS_NEAREST);
+ int input_x = x + dx, input_y = y + dy;
+
+ this->m_imageInput->read(color, input_x, input_y, COM_PS_NEAREST);
+ if (this->m_ignoreAlpha) {
+ color[3] = 1.0f;
+ }
+ else {
+ if (this->m_alphaInput != NULL) {
+ this->m_alphaInput->read(&(color[3]), input_x, input_y, COM_PS_NEAREST);
+ }
}
+
copy_v4_v4(buffer + offset4, color);
if (this->m_depthInput != NULL) {
- this->m_depthInput->read(color, x, y, COM_PS_NEAREST);
+ this->m_depthInput->read(color, input_x, input_y, COM_PS_NEAREST);
zbuffer[offset] = color[0];
}
offset4 += COM_NUMBER_OF_CHANNELS;
diff --git a/source/blender/compositor/operations/COM_CompositorOperation.h b/source/blender/compositor/operations/COM_CompositorOperation.h
index c1d91c16a3c..d33e89ed742 100644
--- a/source/blender/compositor/operations/COM_CompositorOperation.h
+++ b/source/blender/compositor/operations/COM_CompositorOperation.h
@@ -65,15 +65,29 @@ private:
* @brief local reference to the depth operation
*/
SocketReader *m_depthInput;
+
+ /**
+ * @brief Ignore any alpha input
+ */
+ bool m_ignoreAlpha;
+
+ /**
+ * @brief operation is active for calculating final compo result
+ */
+ bool m_active;
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 setRenderData(const RenderData *rd) { this->m_rd = rd; }
- bool isOutputOperation(bool rendering) const { return true; }
+ bool isOutputOperation(bool rendering) const { return this->isActiveCompositorOutput(); }
void initExecution();
void deinitExecution();
const CompositorPriority getRenderPriority() const { return COM_PRIORITY_MEDIUM; }
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+ void setIgnoreAlpha(bool value) { this->m_ignoreAlpha = value; }
+ void setActive(bool active) { this->m_active = active; }
};
#endif
+
diff --git a/source/blender/compositor/operations/COM_ConvertPremulToKeyOperation.cpp b/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.cpp
index b92da4c324f..2af4b55de1a 100644
--- a/source/blender/compositor/operations/COM_ConvertPremulToKeyOperation.cpp
+++ b/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.cpp
@@ -19,10 +19,10 @@
* Dalai Felinto
*/
-#include "COM_ConvertPremulToKeyOperation.h"
+#include "COM_ConvertPremulToStraightOperation.h"
#include "BLI_math.h"
-ConvertPremulToKeyOperation::ConvertPremulToKeyOperation() : NodeOperation()
+ConvertPremulToStraightOperation::ConvertPremulToStraightOperation() : NodeOperation()
{
this->addInputSocket(COM_DT_COLOR);
this->addOutputSocket(COM_DT_COLOR);
@@ -30,12 +30,12 @@ ConvertPremulToKeyOperation::ConvertPremulToKeyOperation() : NodeOperation()
this->m_inputColor = NULL;
}
-void ConvertPremulToKeyOperation::initExecution()
+void ConvertPremulToStraightOperation::initExecution()
{
this->m_inputColor = getInputSocketReader(0);
}
-void ConvertPremulToKeyOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+void ConvertPremulToStraightOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
{
float inputValue[4];
float alpha;
@@ -54,7 +54,7 @@ void ConvertPremulToKeyOperation::executePixel(float output[4], float x, float y
output[3] = alpha;
}
-void ConvertPremulToKeyOperation::deinitExecution()
+void ConvertPremulToStraightOperation::deinitExecution()
{
this->m_inputColor = NULL;
}
diff --git a/source/blender/compositor/operations/COM_ConvertPremulToKeyOperation.h b/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.h
index 04a9965858d..9d3ab156555 100644
--- a/source/blender/compositor/operations/COM_ConvertPremulToKeyOperation.h
+++ b/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_ConvertPremulToKeyOperation_h
-#define _COM_ConvertPremulToKeyOperation_h
+#ifndef _COM_ConvertPremulToStraightOperation_h
+#define _COM_ConvertPremulToStraightOperation_h
#include "COM_NodeOperation.h"
@@ -28,14 +28,14 @@
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
-class ConvertPremulToKeyOperation : public NodeOperation {
+class ConvertPremulToStraightOperation : public NodeOperation {
private:
SocketReader *m_inputColor;
public:
/**
* Default constructor
*/
- ConvertPremulToKeyOperation();
+ ConvertPremulToStraightOperation();
/**
* the inner loop of this program
diff --git a/source/blender/compositor/operations/COM_ConvertKeyToPremulOperation.cpp b/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.cpp
index 4497db52a0f..ae55d949ff2 100644
--- a/source/blender/compositor/operations/COM_ConvertKeyToPremulOperation.cpp
+++ b/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.cpp
@@ -19,10 +19,10 @@
* Dalai Felinto
*/
-#include "COM_ConvertKeyToPremulOperation.h"
+#include "COM_ConvertStraightToPremulOperation.h"
#include "BLI_math.h"
-ConvertKeyToPremulOperation::ConvertKeyToPremulOperation() : NodeOperation()
+ConvertStraightToPremulOperation::ConvertStraightToPremulOperation() : NodeOperation()
{
this->addInputSocket(COM_DT_COLOR);
this->addOutputSocket(COM_DT_COLOR);
@@ -30,12 +30,12 @@ ConvertKeyToPremulOperation::ConvertKeyToPremulOperation() : NodeOperation()
this->m_inputColor = NULL;
}
-void ConvertKeyToPremulOperation::initExecution()
+void ConvertStraightToPremulOperation::initExecution()
{
this->m_inputColor = getInputSocketReader(0);
}
-void ConvertKeyToPremulOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+void ConvertStraightToPremulOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
{
float inputValue[4];
float alpha;
@@ -49,7 +49,7 @@ void ConvertKeyToPremulOperation::executePixel(float output[4], float x, float y
output[3] = alpha;
}
-void ConvertKeyToPremulOperation::deinitExecution()
+void ConvertStraightToPremulOperation::deinitExecution()
{
this->m_inputColor = NULL;
}
diff --git a/source/blender/compositor/operations/COM_ConvertKeyToPremulOperation.h b/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.h
index 502674e26db..d0191f292d2 100644
--- a/source/blender/compositor/operations/COM_ConvertKeyToPremulOperation.h
+++ b/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.h
@@ -19,8 +19,8 @@
* Dalai Felinto
*/
-#ifndef _COM_ConvertKeyToPremulOperation_h
-#define _COM_ConvertKeyToPremulOperation_h
+#ifndef _COM_ConvertStraightToPremulOperation_h
+#define _COM_ConvertStraightToPremulOperation_h
#include "COM_NodeOperation.h"
@@ -28,14 +28,14 @@
* this program converts an input color to an output value.
* it assumes we are in sRGB color space.
*/
-class ConvertKeyToPremulOperation : public NodeOperation {
+class ConvertStraightToPremulOperation : public NodeOperation {
private:
SocketReader *m_inputColor;
public:
/**
* Default constructor
*/
- ConvertKeyToPremulOperation();
+ ConvertStraightToPremulOperation();
/**
* the inner loop of this program
diff --git a/source/blender/compositor/operations/COM_CropOperation.cpp b/source/blender/compositor/operations/COM_CropOperation.cpp
index 4f9cd771988..844d23db2ac 100644
--- a/source/blender/compositor/operations/COM_CropOperation.cpp
+++ b/source/blender/compositor/operations/COM_CropOperation.cpp
@@ -119,7 +119,7 @@ void CropImageOperation::determineResolution(unsigned int resolution[2], unsigne
void CropImageOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
{
- if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
+ if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
this->m_inputOperation->read(output, (x + this->m_xmin), (y + this->m_ymin), sampler);
}
else {
diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp
index f0fffa770f8..b54e47c136d 100644
--- a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp
+++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp
@@ -323,89 +323,147 @@ DilateStepOperation::DilateStepOperation() : NodeOperation()
void DilateStepOperation::initExecution()
{
this->m_inputProgram = this->getInputSocketReader(0);
- this->m_cached_buffer = NULL;
- this->initMutex();
+}
+
+
+// small helper to pass data from initializeTileData to executePixel
+typedef struct tile_info {
+ rcti rect;
+ int width;
+ float *buffer;
+} tile_info;
+
+static tile_info *create_cache(int xmin, int xmax, int ymin, int ymax)
+{
+ tile_info *result = (tile_info *)MEM_mallocN(sizeof(tile_info), "dilate erode tile");
+ result->rect.xmin = xmin;
+ result->rect.xmax = xmax;
+ result->rect.ymin = ymin;
+ result->rect.ymax = ymax;
+ result->width = xmax - xmin;
+ result->buffer = (float *)MEM_callocN(sizeof(float) * (ymax - ymin) * result->width, "dilate erode cache");
+ return result;
}
void *DilateStepOperation::initializeTileData(rcti *rect)
{
- if (this->m_cached_buffer != NULL) {
- return this->m_cached_buffer;
- }
- lockMutex();
- if (this->m_cached_buffer == NULL) {
- MemoryBuffer *buffer = (MemoryBuffer *)this->m_inputProgram->initializeTileData(NULL);
- float *rectf = buffer->convertToValueBuffer();
- int x, y, i;
- float *p;
- int bwidth = buffer->getWidth();
- int bheight = buffer->getHeight();
- for (i = 0; i < this->m_iterations; i++) {
- for (y = 0; y < bheight; y++) {
- for (x = 0; x < bwidth - 1; x++) {
- p = rectf + (bwidth * y + x);
- *p = max(*p, *(p + 1));
- }
+ MemoryBuffer *tile = (MemoryBuffer *)this->m_inputProgram->initializeTileData(NULL);
+ int x, y, i;
+ int width = tile->getWidth();
+ int height = tile->getHeight();
+ float *buffer = tile->getBuffer();
+
+ int half_window = this->m_iterations;
+ int window = half_window * 2 + 1;
+
+ int xmin = max(0, rect->xmin - half_window);
+ int ymin = max(0, rect->ymin - half_window);
+ int xmax = min(width, rect->xmax + half_window);
+ int ymax = min(height, rect->ymax + half_window);
+
+ int bwidth = rect->xmax - rect->xmin;
+ int bheight = rect->ymax - rect->ymin;
+
+ // Note: Cache buffer has original tilesize width, but new height.
+ // We have to calculate the additional rows in the first pass,
+ // to have valid data available for the second pass.
+ tile_info *result = create_cache(rect->xmin, rect->xmax, ymin, ymax);
+ float *rectf = result->buffer;
+
+ // temp holds maxima for every step in the algorithm, buf holds a
+ // single row or column of input values, padded with MAXFLOATs to
+ // simplify the logic.
+ float *temp = (float *)MEM_mallocN(sizeof(float) * (2 * window - 1), "dilate erode temp");
+ float *buf = (float *)MEM_mallocN(sizeof(float) * (max(bwidth, bheight) + 5 * half_window), "dilate erode buf");
+
+ // The following is based on the van Herk/Gil-Werman algorithm for morphology operations.
+ // first pass, horizontal dilate/erode
+ for (y = ymin; y < ymax; y++) {
+ for (x = 0; x < bwidth + 5 * half_window; x++) {
+ buf[x] = -MAXFLOAT;
+ }
+ for (x = xmin; x < xmax; ++x) {
+ buf[x - rect->xmin + window - 1] = buffer[4 * (y * width + x)];
+ }
+
+ for (i = 0; i < (bwidth + 3 * half_window) / window; i++) {
+ int start = (i + 1) * window - 1;
+
+ temp[window - 1] = buf[start];
+ for (x = 1; x < window; x++) {
+ temp[window - 1 - x] = max(temp[window - x], buf[start - x]);
+ temp[window - 1 + x] = max(temp[window + x - 2], buf[start + x]);
}
-
- for (y = 0; y < bheight; y++) {
- for (x = bwidth - 1; x >= 1; x--) {
- p = rectf + (bwidth * y + x);
- *p = max(*p, *(p - 1));
- }
+
+ start = half_window + (i - 1) * window + 1;
+ for (x = -min(0, start); x < window - max(0, start + window - bwidth); x++) {
+ rectf[bwidth * (y - ymin) + (start + x)] = max(temp[x], temp[x + window - 1]);
}
-
- for (x = 0; x < bwidth; x++) {
- for (y = 0; y < bheight - 1; y++) {
- p = rectf + (bwidth * y + x);
- *p = max(*p, *(p + bwidth));
- }
+ }
+ }
+
+ // second pass, vertical dilate/erode
+ for (x = 0; x < bwidth; x++) {
+ for (y = 0; y < bheight + 5 * half_window; y++) {
+ buf[y] = -MAXFLOAT;
+ }
+ for (y = ymin; y < ymax; y++) {
+ buf[y - rect->ymin + window - 1] = rectf[(y - ymin) * bwidth + x];
+ }
+
+ for (i = 0; i < (bheight + 3 * half_window) / window; i++) {
+ int start = (i + 1) * window - 1;
+
+ temp[window - 1] = buf[start];
+ for (y = 1; y < window; y++) {
+ temp[window - 1 - y] = max(temp[window - y], buf[start - y]);
+ temp[window - 1 + y] = max(temp[window + y - 2], buf[start + y]);
}
-
- for (x = 0; x < bwidth; x++) {
- for (y = bheight - 1; y >= 1; y--) {
- p = rectf + (bwidth * y + x);
- *p = max(*p, *(p - bwidth));
- }
+
+ start = half_window + (i - 1) * window + 1;
+ for (y = -min(0, start); y < window - max(0, start + window - bheight); y++) {
+ rectf[bwidth * (y + start + (rect->ymin - ymin)) + x] = max(temp[y], temp[y + window - 1]);
}
}
- this->m_cached_buffer = rectf;
}
- unlockMutex();
- return this->m_cached_buffer;
+
+ MEM_freeN(temp);
+ MEM_freeN(buf);
+
+ return result;
}
void DilateStepOperation::executePixel(float output[4], int x, int y, void *data)
{
- output[0] = this->m_cached_buffer[y * this->getWidth() + x];
+ tile_info *tile = (tile_info *)data;
+ int nx = x - tile->rect.xmin;
+ int ny = y - tile->rect.ymin;
+ output[0] = tile->buffer[tile->width * ny + nx];
}
void DilateStepOperation::deinitExecution()
{
this->m_inputProgram = NULL;
- this->deinitMutex();
- if (this->m_cached_buffer) {
- MEM_freeN(this->m_cached_buffer);
- this->m_cached_buffer = NULL;
- }
+}
+
+void DilateStepOperation::deinitializeTileData(rcti *rect, void *data)
+{
+ tile_info *tile = (tile_info *)data;
+ MEM_freeN(tile->buffer);
+ MEM_freeN(tile);
}
bool DilateStepOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
{
- if (this->m_cached_buffer) {
- return false;
- }
- else {
- rcti newInput;
-
- newInput.xmax = getWidth();
- newInput.xmin = 0;
- newInput.ymax = getHeight();
- newInput.ymin = 0;
-
- return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
- }
+ rcti newInput;
+ int it = this->m_iterations;
+ newInput.xmax = input->xmax + it;
+ newInput.xmin = input->xmin - it;
+ newInput.ymax = input->ymax + it;
+ newInput.ymin = input->ymin - it;
+
+ return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
// Erode step
@@ -416,48 +474,88 @@ ErodeStepOperation::ErodeStepOperation() : DilateStepOperation()
void *ErodeStepOperation::initializeTileData(rcti *rect)
{
- if (this->m_cached_buffer != NULL) {
- return this->m_cached_buffer;
- }
- lockMutex();
- if (this->m_cached_buffer == NULL) {
- MemoryBuffer *buffer = (MemoryBuffer *)this->m_inputProgram->initializeTileData(NULL);
- float *rectf = buffer->convertToValueBuffer();
- int x, y, i;
- float *p;
- int bwidth = buffer->getWidth();
- int bheight = buffer->getHeight();
- for (i = 0; i < this->m_iterations; i++) {
- for (y = 0; y < bheight; y++) {
- for (x = 0; x < bwidth - 1; x++) {
- p = rectf + (bwidth * y + x);
- *p = MIN2(*p, *(p + 1));
- }
+ MemoryBuffer *tile = (MemoryBuffer *)this->m_inputProgram->initializeTileData(NULL);
+ int x, y, i;
+ int width = tile->getWidth();
+ int height = tile->getHeight();
+ float *buffer = tile->getBuffer();
+
+ int half_window = this->m_iterations;
+ int window = half_window * 2 + 1;
+
+ int xmin = max(0, rect->xmin - half_window);
+ int ymin = max(0, rect->ymin - half_window);
+ int xmax = min(width, rect->xmax + half_window);
+ int ymax = min(height, rect->ymax + half_window);
+
+ int bwidth = rect->xmax - rect->xmin;
+ int bheight = rect->ymax - rect->ymin;
+
+ // Note: Cache buffer has original tilesize width, but new height.
+ // We have to calculate the additional rows in the first pass,
+ // to have valid data available for the second pass.
+ tile_info *result = create_cache(rect->xmin, rect->xmax, ymin, ymax);
+ float *rectf = result->buffer;
+
+ // temp holds maxima for every step in the algorithm, buf holds a
+ // single row or column of input values, padded with MAXFLOATs to
+ // simplify the logic.
+ float *temp = (float *)MEM_mallocN(sizeof(float) * (2 * window - 1), "dilate erode temp");
+ float *buf = (float *)MEM_mallocN(sizeof(float) * (max(bwidth, bheight) + 5 * half_window), "dilate erode buf");
+
+ // The following is based on the van Herk/Gil-Werman algorithm for morphology operations.
+ // first pass, horizontal dilate/erode
+ for (y = ymin; y < ymax; y++) {
+ for (x = 0; x < bwidth + 5 * half_window; x++) {
+ buf[x] = MAXFLOAT;
+ }
+ for (x = xmin; x < xmax; ++x) {
+ buf[x - rect->xmin + window - 1] = buffer[4 * (y * width + x)];
+ }
+
+ for (i = 0; i < (bwidth + 3 * half_window) / window; i++) {
+ int start = (i + 1) * window - 1;
+
+ temp[window - 1] = buf[start];
+ for (x = 1; x < window; x++) {
+ temp[window - 1 - x] = min(temp[window - x], buf[start - x]);
+ temp[window - 1 + x] = min(temp[window + x - 2], buf[start + x]);
}
-
- for (y = 0; y < bheight; y++) {
- for (x = bwidth - 1; x >= 1; x--) {
- p = rectf + (bwidth * y + x);
- *p = MIN2(*p, *(p - 1));
- }
+
+ start = half_window + (i - 1) * window + 1;
+ for (x = -min(0, start); x < window - max(0, start + window - bwidth); x++) {
+ rectf[bwidth * (y - ymin) + (start + x)] = min(temp[x], temp[x + window - 1]);
}
-
- for (x = 0; x < bwidth; x++) {
- for (y = 0; y < bheight - 1; y++) {
- p = rectf + (bwidth * y + x);
- *p = MIN2(*p, *(p + bwidth));
- }
+ }
+ }
+
+ // second pass, vertical dilate/erode
+ for (x = 0; x < bwidth; x++) {
+ for (y = 0; y < bheight + 5 * half_window; y++) {
+ buf[y] = MAXFLOAT;
+ }
+ for (y = ymin; y < ymax; y++) {
+ buf[y - rect->ymin + window - 1] = rectf[(y - ymin) * bwidth + x];
+ }
+
+ for (i = 0; i < (bheight + 3 * half_window) / window; i++) {
+ int start = (i + 1) * window - 1;
+
+ temp[window - 1] = buf[start];
+ for (y = 1; y < window; y++) {
+ temp[window - 1 - y] = min(temp[window - y], buf[start - y]);
+ temp[window - 1 + y] = min(temp[window + y - 2], buf[start + y]);
}
-
- for (x = 0; x < bwidth; x++) {
- for (y = bheight - 1; y >= 1; y--) {
- p = rectf + (bwidth * y + x);
- *p = MIN2(*p, *(p - bwidth));
- }
+
+ start = half_window + (i - 1) * window + 1;
+ for (y = -min(0, start); y < window - max(0, start + window - bheight); y++) {
+ rectf[bwidth * (y + start + (rect->ymin - ymin)) + x] = min(temp[y], temp[y + window - 1]);
}
}
- this->m_cached_buffer = rectf;
}
- unlockMutex();
- return this->m_cached_buffer;
+
+ MEM_freeN(temp);
+ MEM_freeN(buf);
+
+ return result;
}
diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.h b/source/blender/compositor/operations/COM_DilateErodeOperation.h
index 47480d47c3b..51bad81d0ca 100644
--- a/source/blender/compositor/operations/COM_DilateErodeOperation.h
+++ b/source/blender/compositor/operations/COM_DilateErodeOperation.h
@@ -128,7 +128,6 @@ protected:
int m_iterations;
- float *m_cached_buffer;
public:
DilateStepOperation();
@@ -147,6 +146,7 @@ public:
* Deinitialize the execution
*/
void deinitExecution();
+ void deinitializeTileData(rcti *rect, void *data);
void setIterations(int iterations) { this->m_iterations = iterations; }
diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp
index 0efead77cd4..aaf5f92505b 100644
--- a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp
@@ -182,8 +182,8 @@ bool GaussianAlphaXBlurOperation::determineDependingAreaOfInterest(rcti *input,
#endif
{
if (this->m_sizeavailable && this->m_gausstab != NULL) {
- newInput.xmax = input->xmax + this->m_rad;
- newInput.xmin = input->xmin - this->m_rad;
+ newInput.xmax = input->xmax + this->m_rad + 1;
+ newInput.xmin = input->xmin - this->m_rad - 1;
newInput.ymax = input->ymax;
newInput.ymin = input->ymin;
}
diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp
index 1f9cc8e461a..650805f91d5 100644
--- a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp
@@ -184,8 +184,8 @@ bool GaussianAlphaYBlurOperation::determineDependingAreaOfInterest(rcti *input,
if (this->m_sizeavailable && this->m_gausstab != NULL) {
newInput.xmax = input->xmax;
newInput.xmin = input->xmin;
- newInput.ymax = input->ymax + this->m_rad;
- newInput.ymin = input->ymin - this->m_rad;
+ newInput.ymax = input->ymax + this->m_rad + 1;
+ newInput.ymin = input->ymin - this->m_rad - 1;
}
else {
newInput.xmax = this->getWidth();
diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp
index 2d662c1061e..c236c73e50f 100644
--- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp
@@ -62,7 +62,6 @@ void GaussianBokehBlurOperation::updateGauss()
int n;
float *dgauss;
float *ddgauss;
- float val;
int j, i;
const float width = this->getWidth();
const float height = this->getHeight();
@@ -84,13 +83,15 @@ void GaussianBokehBlurOperation::updateGauss()
this->m_radx = ceil(radxf);
this->m_rady = ceil(radyf);
-
- n = (2 * this->m_radx + 1) * (2 * this->m_rady + 1);
+
+ int ddwidth = 2 * this->m_radx + 1;
+ int ddheight = 2 * this->m_rady + 1;
+ n = ddwidth * ddheight;
/* create a full filter image */
ddgauss = (float *)MEM_mallocN(sizeof(float) * n, __func__);
dgauss = ddgauss;
- val = 0.0f;
+ float sum = 0.0f;
for (j = -this->m_rady; j <= this->m_rady; j++) {
for (i = -this->m_radx; i <= this->m_radx; i++, dgauss++) {
float fj = (float)j / radyf;
@@ -98,16 +99,19 @@ void GaussianBokehBlurOperation::updateGauss()
float dist = sqrt(fj * fj + fi * fi);
*dgauss = RE_filter_value(this->m_data->filtertype, dist);
- val += *dgauss;
+ sum += *dgauss;
}
}
- if (val != 0.0f) {
- val = 1.0f / val;
- for (j = n - 1; j >= 0; j--) {
- ddgauss[j] *= val;
- }
+ if (sum > 0.0f) {
+ /* normalize */
+ float norm = 1.0f / sum;
+ for (j = n - 1; j >= 0; j--)
+ ddgauss[j] *= norm;
+ }
+ else {
+ int center = m_rady * ddwidth + m_radx;
+ ddgauss[center] = 1.0f;
}
- else ddgauss[4] = 1.0f;
this->m_gausstab = ddgauss;
}
diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp
index 573a19466e8..af231d118a6 100644
--- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp
@@ -133,8 +133,8 @@ bool GaussianXBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadB
}
{
if (this->m_sizeavailable && this->m_gausstab != NULL) {
- newInput.xmax = input->xmax + this->m_rad;
- newInput.xmin = input->xmin - this->m_rad;
+ newInput.xmax = input->xmax + this->m_rad + 1;
+ newInput.xmin = input->xmin - this->m_rad - 1;
newInput.ymax = input->ymax;
newInput.ymin = input->ymin;
}
diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp
index 0c0a4d8aa4f..7bf85a953f4 100644
--- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp
@@ -136,8 +136,8 @@ bool GaussianYBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadB
if (this->m_sizeavailable && this->m_gausstab != NULL) {
newInput.xmax = input->xmax;
newInput.xmin = input->xmin;
- newInput.ymax = input->ymax + this->m_rad;
- newInput.ymin = input->ymin - this->m_rad;
+ newInput.ymax = input->ymax + this->m_rad + 1;
+ newInput.ymin = input->ymin - this->m_rad - 1;
}
else {
newInput.xmax = this->getWidth();
diff --git a/source/blender/compositor/operations/COM_InpaintOperation.cpp b/source/blender/compositor/operations/COM_InpaintOperation.cpp
index 81ca06cfff0..edcd1563e03 100644
--- a/source/blender/compositor/operations/COM_InpaintOperation.cpp
+++ b/source/blender/compositor/operations/COM_InpaintOperation.cpp
@@ -84,8 +84,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_NUMBER_OF_CHANNELS +
+ x * COM_NUMBER_OF_CHANNELS];
}
int InpaintSimpleOperation::mdist(int x, int y)
diff --git a/source/blender/compositor/operations/COM_MixBaseOperation.cpp b/source/blender/compositor/operations/COM_MixBaseOperation.cpp
index 2d40629e764..438fb84ebb7 100644
--- a/source/blender/compositor/operations/COM_MixBaseOperation.cpp
+++ b/source/blender/compositor/operations/COM_MixBaseOperation.cpp
@@ -69,29 +69,3 @@ void MixBaseOperation::deinitExecution()
this->m_inputColor1Operation = NULL;
this->m_inputColor2Operation = NULL;
}
-
-void MixBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
-{
- InputSocket *socket;
- unsigned int tempPreferredResolution[2] = {0, 0};
- unsigned int tempResolution[2];
-
- socket = this->getInputSocket(1);
- socket->determineResolution(tempResolution, tempPreferredResolution);
- if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) {
- this->setResolutionInputSocketIndex(1);
- }
- else {
- socket = this->getInputSocket(2);
- tempPreferredResolution[0] = 0;
- tempPreferredResolution[1] = 0;
- socket->determineResolution(tempResolution, tempPreferredResolution);
- if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) {
- this->setResolutionInputSocketIndex(2);
- }
- else {
- this->setResolutionInputSocketIndex(0);
- }
- }
- NodeOperation::determineResolution(resolution, preferredResolution);
-}
diff --git a/source/blender/compositor/operations/COM_MixBaseOperation.h b/source/blender/compositor/operations/COM_MixBaseOperation.h
index 88d1d00c2bf..75ca1c3f6c6 100644
--- a/source/blender/compositor/operations/COM_MixBaseOperation.h
+++ b/source/blender/compositor/operations/COM_MixBaseOperation.h
@@ -71,8 +71,6 @@ public:
*/
void deinitExecution();
- void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
-
void setUseValueAlphaMultiply(const bool value) { this->m_valueAlphaMultiply = value; }
bool useValueAlphaMultiply() { return this->m_valueAlphaMultiply; }
void setUseClamp(bool value) { this->m_useClamp = value; }
diff --git a/source/blender/compositor/operations/COM_MovieClipOperation.cpp b/source/blender/compositor/operations/COM_MovieClipOperation.cpp
index 74761f00e1f..a74f2c7299b 100644
--- a/source/blender/compositor/operations/COM_MovieClipOperation.cpp
+++ b/source/blender/compositor/operations/COM_MovieClipOperation.cpp
@@ -30,9 +30,8 @@ extern "C" {
}
#include "BKE_image.h"
-MovieClipOperation::MovieClipOperation() : NodeOperation()
+MovieClipBaseOperation::MovieClipBaseOperation() : NodeOperation()
{
- this->addOutputSocket(COM_DT_COLOR);
this->m_movieClip = NULL;
this->m_movieClipBuffer = NULL;
this->m_movieClipUser = NULL;
@@ -42,7 +41,7 @@ MovieClipOperation::MovieClipOperation() : NodeOperation()
}
-void MovieClipOperation::initExecution()
+void MovieClipBaseOperation::initExecution()
{
if (this->m_movieClip) {
BKE_movieclip_user_set_frame(this->m_movieClipUser, this->m_framenumber);
@@ -63,7 +62,7 @@ void MovieClipOperation::initExecution()
}
}
-void MovieClipOperation::deinitExecution()
+void MovieClipBaseOperation::deinitExecution()
{
if (this->m_movieClipBuffer) {
IMB_freeImBuf(this->m_movieClipBuffer);
@@ -72,7 +71,7 @@ void MovieClipOperation::deinitExecution()
}
}
-void MovieClipOperation::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;
@@ -87,7 +86,7 @@ void MovieClipOperation::determineResolution(unsigned int resolution[2], unsigne
}
}
-void MovieClipOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+void MovieClipBaseOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
{
if (this->m_movieClipBuffer == NULL || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight() ) {
zero_v4(output);
@@ -106,3 +105,22 @@ void MovieClipOperation::executePixel(float output[4], float x, float y, PixelSa
}
}
}
+
+MovieClipOperation::MovieClipOperation() : MovieClipBaseOperation()
+{
+ this->addOutputSocket(COM_DT_COLOR);
+}
+
+MovieClipAlphaOperation::MovieClipAlphaOperation() : MovieClipBaseOperation()
+{
+ this->addOutputSocket(COM_DT_VALUE);
+}
+
+void MovieClipAlphaOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ MovieClipBaseOperation::executePixel(output, x, y, sampler);
+ output[0] = output[3];
+ output[1] = 0.0f;
+ output[2] = 0.0f;
+ output[3] = 0.0f;
+}
diff --git a/source/blender/compositor/operations/COM_MovieClipOperation.h b/source/blender/compositor/operations/COM_MovieClipOperation.h
index 7cce42f6727..a368dca423c 100644
--- a/source/blender/compositor/operations/COM_MovieClipOperation.h
+++ b/source/blender/compositor/operations/COM_MovieClipOperation.h
@@ -30,11 +30,9 @@
#include "IMB_imbuf_types.h"
/**
- * Base class for all renderlayeroperations
- *
- * @todo: rename to operation.
+ * Base class for movie clip
*/
-class MovieClipOperation : public NodeOperation {
+class MovieClipBaseOperation : public NodeOperation {
protected:
MovieClip *m_movieClip;
MovieClipUser *m_movieClipUser;
@@ -50,7 +48,7 @@ protected:
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
public:
- MovieClipOperation();
+ MovieClipBaseOperation();
void initExecution();
void deinitExecution();
@@ -62,4 +60,15 @@ public:
void executePixel(float output[4], float x, float y, PixelSampler sampler);
};
+class MovieClipOperation : public MovieClipBaseOperation {
+public:
+ MovieClipOperation();
+};
+
+class MovieClipAlphaOperation : public MovieClipBaseOperation {
+public:
+ MovieClipAlphaOperation();
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
#endif
diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp
index 68a61dff801..863a404ba67 100644
--- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp
+++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp
@@ -75,9 +75,31 @@ void MovieDistortionOperation::initExecution()
calibration_width, calibration_height, this->m_distortion);
s_cache.push_back(newC);
this->m_cache = newC;
+
+ if (this->m_distortion) {
+ float delta[2];
+ rcti full_frame;
+ full_frame.xmin = full_frame.ymin = 0;
+ full_frame.xmax = this->m_width;
+ full_frame.ymax = this->m_height;
+ BKE_tracking_max_undistortion_delta_across_bound(&this->m_movieClip->tracking, &full_frame, delta);
+
+ /* 5 is just in case we didn't hit real max of distortion in
+ * BKE_tracking_max_undistortion_delta_across_bound
+ */
+ m_margin[0] = delta[0] + 5;
+ m_margin[1] = delta[1] + 5;
+ }
+ else {
+ /* undistortion with sane distortion coefficients would be mapped inside
+ * of each tile, should be no need in margin in this case
+ */
+ m_margin[0] = m_margin[1] = 0;
+ }
}
else {
this->m_cache = NULL;
+ m_margin[0] = m_margin[1] = 0;
}
}
@@ -112,3 +134,13 @@ void MovieDistortionOperation::executePixel(float output[4], float x, float y, P
this->m_inputOperation->read(output, x, y, COM_PS_BILINEAR);
}
}
+
+bool MovieDistortionOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+{
+ rcti newInput;
+ newInput.xmin = input->xmin - m_margin[0];
+ newInput.ymin = input->ymin - m_margin[1];
+ newInput.xmax = input->xmax + m_margin[0];
+ newInput.ymax = input->ymax + m_margin[1];
+ return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+}
diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.h b/source/blender/compositor/operations/COM_MovieDistortionOperation.h
index 9f8aa065e3e..c9629451992 100644
--- a/source/blender/compositor/operations/COM_MovieDistortionOperation.h
+++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.h
@@ -148,6 +148,7 @@ private:
DistortionCache *m_cache;
SocketReader *m_inputOperation;
MovieClip *m_movieClip;
+ int m_margin[2];
protected:
bool m_distortion;
@@ -162,6 +163,8 @@ public:
void setMovieClip(MovieClip *clip) { this->m_movieClip = clip; }
void setFramenumber(int framenumber) { this->m_framenumber = framenumber; }
+ bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
+
};
void deintializeDistortionCache(void);
diff --git a/source/blender/compositor/operations/COM_OpenCLKernels.cl b/source/blender/compositor/operations/COM_OpenCLKernels.cl
index 36205bb94cc..d7a81001531 100644
--- a/source/blender/compositor/operations/COM_OpenCLKernels.cl
+++ b/source/blender/compositor/operations/COM_OpenCLKernels.cl
@@ -66,7 +66,8 @@ __kernel void bokehBlurKernel(__read_only image2d_t boundingBox, __read_only ima
}
color /= multiplyer;
- } else {
+ }
+ else {
int2 imageCoordinates = realCoordinate - offsetInput;
color = read_imagef(inputImage, SAMPLER_NEAREST, imageCoordinates);
}
@@ -111,7 +112,7 @@ __kernel void defocusKernel(__read_only image2d_t inputImage, __read_only image2
float dx = nx - realCoordinate.s0;
if (dx != 0 || dy != 0) {
inputCoordinate.s0 = nx - offsetInput.s0;
- size = read_imagef(inputSize, SAMPLER_NEAREST, inputCoordinate).s0 * scalar;
+ size = min(read_imagef(inputSize, SAMPLER_NEAREST, inputCoordinate).s0 * scalar, size_center);
if (size > threshold) {
if (size >= fabs(dx) && size >= fabs(dy)) {
float2 uv = {256.0f + dx * 255.0f / size,
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp
index 7d05202df96..15e5ab947d4 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.cpp
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp
@@ -141,7 +141,7 @@ 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->imtype,
+ BKE_makepicstring(filename, this->m_path, bmain->name, this->m_rd->cfra, this->m_format,
(this->m_rd->scemode & R_EXTENSION), true);
if (0 == BKE_imbuf_write(ibuf, filename, this->m_format))
@@ -166,7 +166,7 @@ OutputOpenExrLayer::OutputOpenExrLayer(const char *name_, DataType datatype_)
}
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)
{
this->m_rd = rd;
this->m_tree = tree;
@@ -205,7 +205,7 @@ void OutputOpenExrMultiLayerOperation::deinitExecution()
char filename[FILE_MAX];
void *exrhandle = IMB_exr_get_handle();
- BKE_makepicstring(filename, this->m_path, bmain->name, this->m_rd->cfra, R_IMF_IMTYPE_MULTILAYER,
+ BKE_makepicstring_from_type(filename, this->m_path, bmain->name, this->m_rd->cfra, R_IMF_IMTYPE_MULTILAYER,
(this->m_rd->scemode & R_EXTENSION), true);
BLI_make_existing_file(filename);
diff --git a/source/blender/compositor/operations/COM_PreviewOperation.cpp b/source/blender/compositor/operations/COM_PreviewOperation.cpp
index 6e58b277f66..ba158fb2509 100644
--- a/source/blender/compositor/operations/COM_PreviewOperation.cpp
+++ b/source/blender/compositor/operations/COM_PreviewOperation.cpp
@@ -36,42 +36,47 @@ extern "C" {
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_colormanagement.h"
+ #include "BKE_node.h"
}
PreviewOperation::PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings) : NodeOperation()
{
this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE);
+ this->m_preview = NULL;
this->m_outputBuffer = NULL;
this->m_input = NULL;
this->m_divider = 1.0f;
- this->m_node = NULL;
this->m_viewSettings = viewSettings;
this->m_displaySettings = displaySettings;
}
+void PreviewOperation::verifyPreview(bNodeInstanceHash *previews, bNodeInstanceKey key)
+{
+ /* Size (0, 0) ensures the preview rect is not allocated in advance,
+ * this is set later in initExecution once the resolution is determined.
+ */
+ this->m_preview = BKE_node_preview_verify(previews, key, 0, 0, TRUE);
+}
+
void PreviewOperation::initExecution()
{
this->m_input = getInputSocketReader(0);
- if (!this->m_node->preview) {
- this->m_node->preview = (bNodePreview *)MEM_callocN(sizeof(bNodePreview), "node preview");
- }
- else {
- if (this->getWidth() == (unsigned int)this->m_node->preview->xsize &&
- this->getHeight() == (unsigned int)this->m_node->preview->ysize)
- {
- this->m_outputBuffer = this->m_node->preview->rect;
- }
+
+ if (this->getWidth() == (unsigned int)this->m_preview->xsize &&
+ this->getHeight() == (unsigned int)this->m_preview->ysize)
+ {
+ this->m_outputBuffer = this->m_preview->rect;
}
if (this->m_outputBuffer == NULL) {
this->m_outputBuffer = (unsigned char *)MEM_callocN(sizeof(unsigned char) * 4 * getWidth() * getHeight(), "PreviewOperation");
- if (this->m_node->preview->rect) {
- MEM_freeN(this->m_node->preview->rect);
+ if (this->m_preview->rect) {
+ MEM_freeN(this->m_preview->rect);
}
- this->m_node->preview->xsize = getWidth();
- this->m_node->preview->ysize = getHeight();
- this->m_node->preview->rect = this->m_outputBuffer;
+ this->m_preview->xsize = getWidth();
+ this->m_preview->ysize = getHeight();
+ this->m_preview->rect = this->m_outputBuffer;
}
}
diff --git a/source/blender/compositor/operations/COM_PreviewOperation.h b/source/blender/compositor/operations/COM_PreviewOperation.h
index 9e774d0e41b..bb60dfa0420 100644
--- a/source/blender/compositor/operations/COM_PreviewOperation.h
+++ b/source/blender/compositor/operations/COM_PreviewOperation.h
@@ -26,6 +26,7 @@
#include "DNA_image_types.h"
#include "DNA_color_types.h"
#include "BLI_rect.h"
+#include "BKE_global.h"
class PreviewOperation : public NodeOperation {
protected:
@@ -34,7 +35,7 @@ protected:
/**
* @brief holds reference to the SDNA bNode, where this nodes will render the preview image for
*/
- bNode *m_node;
+ bNodePreview *m_preview;
SocketReader *m_input;
float m_divider;
@@ -42,14 +43,15 @@ protected:
const ColorManagedDisplaySettings *m_displaySettings;
public:
PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings);
- bool isOutputOperation(bool rendering) const { return true; }
+ void verifyPreview(bNodeInstanceHash *previews, bNodeInstanceKey key);
+
+ bool isOutputOperation(bool rendering) const { return !G.background; }
void initExecution();
void deinitExecution();
const CompositorPriority getRenderPriority() const;
void executeRegion(rcti *rect, unsigned int tileNumber);
void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
- void setbNode(bNode *node) { this->m_node = node; }
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
bool isPreviewOperation() { return true; }
diff --git a/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp b/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp
index 2ca499683d3..3421b0a2b34 100644
--- a/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp
+++ b/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp
@@ -37,6 +37,7 @@ RenderLayersBaseProg::RenderLayersBaseProg(int renderpass, int elementsize) : No
this->setScene(NULL);
this->m_inputBuffer = NULL;
this->m_elementsize = elementsize;
+ this->m_rd = NULL;
}
@@ -111,14 +112,29 @@ void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, Pi
void RenderLayersBaseProg::executePixel(float output[4], float x, float y, PixelSampler sampler)
{
- int ix = x;
- int iy = y;
-
+ const RenderData *rd = this->m_rd;
+
+ int dx = 0, dy = 0;
+
+ if (rd->mode & R_BORDER && rd->mode & R_CROP) {
+ /* see comment in executeRegion describing coordinate mapping,
+ * here it simply goes other way around
+ */
+ int full_width = rd->xsch * rd->size / 100;
+ int full_height = rd->ysch * rd->size / 100;
+
+ dx = rd->border.xmin * full_width - (full_width - this->getWidth()) / 2.0f;
+ dy = rd->border.ymin * full_height - (full_height - this->getHeight()) / 2.0f;
+ }
+
+ int ix = x - dx;
+ int iy = y - dy;
+
if (this->m_inputBuffer == NULL || ix < 0 || iy < 0 || ix >= (int)this->getWidth() || iy >= (int)this->getHeight() ) {
zero_v4(output);
}
else {
- doInterpolation(output, x, y, sampler);
+ doInterpolation(output, ix, iy, sampler);
}
}
diff --git a/source/blender/compositor/operations/COM_RenderLayersBaseProg.h b/source/blender/compositor/operations/COM_RenderLayersBaseProg.h
index 3916862a0b3..84d6c1ee188 100644
--- a/source/blender/compositor/operations/COM_RenderLayersBaseProg.h
+++ b/source/blender/compositor/operations/COM_RenderLayersBaseProg.h
@@ -63,7 +63,12 @@ private:
int m_renderpass;
int m_elementsize;
-
+
+ /**
+ * @brief render data used for active rendering
+ */
+ const RenderData *m_rd;
+
protected:
/**
* Constructor
@@ -89,6 +94,7 @@ public:
*/
void setScene(Scene *scene) { this->m_scene = scene; }
Scene *getScene() { return this->m_scene; }
+ void setRenderData(const RenderData *rd) { this->m_rd = rd; }
void setLayerId(short layerId) { this->m_layerId = layerId; }
short getLayerId() { return this->m_layerId; }
void initExecution();
diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp
index d2c6c833e2e..fb996f2abaf 100644
--- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp
+++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp
@@ -204,10 +204,10 @@ bool ScreenLensDistortionOperation::determineDependingAreaOfInterest(rcti *input
}
#define UPDATE_INPUT { \
- newInput.xmin = MIN4(newInput.xmin, coords[0], coords[2], coords[4]); \
- newInput.ymin = MIN4(newInput.ymin, coords[1], coords[3], coords[5]); \
- newInput.xmax = MAX4(newInput.xmax, coords[0], coords[2], coords[4]); \
- newInput.ymax = MAX4(newInput.ymax, coords[1], coords[3], coords[5]); \
+ newInput.xmin = min_ffff(newInput.xmin, coords[0], coords[2], coords[4]); \
+ newInput.ymin = min_ffff(newInput.ymin, coords[1], coords[3], coords[5]); \
+ newInput.xmax = max_ffff(newInput.xmax, coords[0], coords[2], coords[4]); \
+ newInput.ymax = max_ffff(newInput.ymax, coords[1], coords[3], coords[5]); \
} (void)0
rcti newInput;
@@ -273,7 +273,7 @@ void ScreenLensDistortionOperation::updateVariables(float distortion, float disp
const float d = 0.25f * max_ff(min_ff(dispersion, 1.0f), 0.0f);
this->m_kr = max_ff(min_ff((this->m_kg + d), 1.0f), -0.999f);
this->m_kb = max_ff(min_ff((this->m_kg - d), 1.0f), -0.999f);
- this->m_maxk = MAX3(this->m_kr, this->m_kg, this->m_kb);
+ this->m_maxk = max_fff(this->m_kr, this->m_kg, this->m_kb);
this->m_sc = (this->m_data->fit && (this->m_maxk > 0.0f)) ? (1.0f / (1.0f + 2.0f * this->m_maxk)) :
(1.0f / (1.0f + this->m_maxk));
this->m_drg = 4.0f * (this->m_kg - this->m_kr);
diff --git a/source/blender/compositor/operations/COM_TextureOperation.cpp b/source/blender/compositor/operations/COM_TextureOperation.cpp
index f8d6c0cfc01..08f6f8ada4a 100644
--- a/source/blender/compositor/operations/COM_TextureOperation.cpp
+++ b/source/blender/compositor/operations/COM_TextureOperation.cpp
@@ -23,8 +23,9 @@
#include "COM_TextureOperation.h"
#include "BLI_listbase.h"
+#include "BKE_image.h"
-TextureBaseOperation::TextureBaseOperation() : NodeOperation()
+TextureBaseOperation::TextureBaseOperation() : SingleThreadedNodeOperation()
{
this->addInputSocket(COM_DT_VECTOR); //offset
this->addInputSocket(COM_DT_VECTOR); //size
@@ -46,11 +47,16 @@ void TextureBaseOperation::initExecution()
{
this->m_inputOffset = getInputSocketReader(0);
this->m_inputSize = getInputSocketReader(1);
+ this->m_pool = BKE_image_pool_new();
+ SingleThreadedNodeOperation::initExecution();
}
void TextureBaseOperation::deinitExecution()
{
this->m_inputSize = NULL;
this->m_inputOffset = NULL;
+ BKE_image_pool_free(this->m_pool);
+ this->m_pool = NULL;
+ SingleThreadedNodeOperation::deinitExecution();
}
void TextureBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
@@ -85,8 +91,8 @@ void TextureBaseOperation::executePixel(float output[4], float x, float y, Pixel
int retval;
const float cx = this->getWidth() / 2;
const float cy = this->getHeight() / 2;
- const float u = (cx - x) / this->getWidth() * 2;
- const float v = (cy - y) / this->getHeight() * 2;
+ const float u = (x - cx) / this->getWidth() * 2;
+ const float v = (y - cy) / this->getHeight() * 2;
this->m_inputSize->read(textureSize, x, y, sampler);
this->m_inputOffset->read(textureOffset, x, y, sampler);
@@ -95,7 +101,7 @@ void TextureBaseOperation::executePixel(float output[4], float x, float y, Pixel
vec[1] = textureSize[1] * (v + textureOffset[1]);
vec[2] = textureSize[2] * textureOffset[2];
- retval = multitex_ext(this->m_texture, vec, NULL, NULL, 0, &texres);
+ retval = multitex_ext(this->m_texture, vec, NULL, NULL, 0, &texres, m_pool);
if (texres.talpha)
output[3] = texres.ta;
@@ -111,3 +117,26 @@ void TextureBaseOperation::executePixel(float output[4], float x, float y, Pixel
output[0] = output[1] = output[2] = output[3];
}
}
+
+MemoryBuffer *TextureBaseOperation::createMemoryBuffer(rcti *rect2)
+{
+ int height = getHeight();
+ int width = getWidth();
+
+ rcti rect;
+ rect.xmin = 0;
+ rect.ymin = 0;
+ rect.xmax = width;
+ rect.ymax = height;
+ MemoryBuffer *result = new MemoryBuffer(NULL, &rect);
+
+ float *data = result->getBuffer();
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++, data += 4) {
+ this->executePixel(data, x, y, COM_PS_NEAREST);
+ }
+ }
+
+ return result;
+}
diff --git a/source/blender/compositor/operations/COM_TextureOperation.h b/source/blender/compositor/operations/COM_TextureOperation.h
index f8435ecdaa2..fc9369099a6 100644
--- a/source/blender/compositor/operations/COM_TextureOperation.h
+++ b/source/blender/compositor/operations/COM_TextureOperation.h
@@ -24,7 +24,7 @@
#ifndef _COM_TextureOperation_h
#define _COM_TextureOperation_h
-#include "COM_NodeOperation.h"
+#include "COM_SingleThreadedNodeOperation.h"
#include "DNA_texture_types.h"
#include "BLI_listbase.h"
extern "C" {
@@ -39,12 +39,13 @@ extern "C" {
*
* @todo: rename to operation.
*/
-class TextureBaseOperation : public NodeOperation {
+class TextureBaseOperation : public SingleThreadedNodeOperation {
private:
Tex *m_texture;
const RenderData *m_rd;
SocketReader *m_inputSize;
SocketReader *m_inputOffset;
+ struct ImagePool *m_pool;
protected:
@@ -58,6 +59,7 @@ protected:
*/
TextureBaseOperation();
+ MemoryBuffer *createMemoryBuffer(rcti *rect2);
public:
void executePixel(float output[4], float x, float y, PixelSampler sampler);
diff --git a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp
index 8b5288321c1..e647ae975ff 100644
--- a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp
+++ b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp
@@ -42,7 +42,7 @@ TrackPositionOperation::TrackPositionOperation() : NodeOperation()
this->m_trackingObjectName[0] = 0;
this->m_trackName[0] = 0;
this->m_axis = 0;
- this->m_position = POSITION_ABSOLUTE;;
+ this->m_position = POSITION_ABSOLUTE;
this->m_relativeFrame = 0;
}
diff --git a/source/blender/compositor/operations/COM_TranslateOperation.cpp b/source/blender/compositor/operations/COM_TranslateOperation.cpp
index 761f55a1455..e2582c3b67b 100644
--- a/source/blender/compositor/operations/COM_TranslateOperation.cpp
+++ b/source/blender/compositor/operations/COM_TranslateOperation.cpp
@@ -15,9 +15,10 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor:
- * Jeroen Bakker
+ * Contributor:
+ * Jeroen Bakker
* Monique Dewanchand
+ * Thomas Beck (plasmasolutions.de)
*/
#include "COM_TranslateOperation.h"
@@ -33,13 +34,14 @@ TranslateOperation::TranslateOperation() : NodeOperation()
this->m_inputXOperation = NULL;
this->m_inputYOperation = NULL;
this->m_isDeltaSet = false;
+ this->m_factorX = 1.0f;
+ this->m_factorY = 1.0f;
}
void TranslateOperation::initExecution()
{
this->m_inputOperation = this->getInputSocketReader(0);
this->m_inputXOperation = this->getInputSocketReader(1);
this->m_inputYOperation = this->getInputSocketReader(2);
-
}
void TranslateOperation::deinitExecution()
@@ -53,18 +55,30 @@ void TranslateOperation::deinitExecution()
void TranslateOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
{
ensureDelta();
- this->m_inputOperation->read(output, x - this->getDeltaX(), y - this->getDeltaY(), sampler);
+
+ float originalXPos = x - this->getDeltaX();
+ float originalYPos = y - this->getDeltaY();
+
+ this->m_inputOperation->read(output, originalXPos, originalYPos, sampler);
}
bool TranslateOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
{
- ensureDelta();
rcti newInput;
-
- newInput.xmax = input->xmax - this->getDeltaX();
+
+ ensureDelta();
+
newInput.xmin = input->xmin - this->getDeltaX();
- newInput.ymax = input->ymax - this->getDeltaY();
+ newInput.xmax = input->xmax - this->getDeltaX();
newInput.ymin = input->ymin - this->getDeltaY();
-
+ newInput.ymax = input->ymax - this->getDeltaY();
+
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+
+void TranslateOperation::setFactorXY(float factorX, float factorY)
+{
+ m_factorX = factorX;
+ m_factorY = factorY;
+}
+
diff --git a/source/blender/compositor/operations/COM_TranslateOperation.h b/source/blender/compositor/operations/COM_TranslateOperation.h
index faaadb1ced2..a638ae7ce69 100644
--- a/source/blender/compositor/operations/COM_TranslateOperation.h
+++ b/source/blender/compositor/operations/COM_TranslateOperation.h
@@ -33,6 +33,8 @@ private:
float m_deltaX;
float m_deltaY;
bool m_isDeltaSet;
+ float m_factorX;
+ float m_factorY;
public:
TranslateOperation();
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
@@ -41,8 +43,8 @@ public:
void initExecution();
void deinitExecution();
- float getDeltaX() { return this->m_deltaX; }
- float getDeltaY() { return this->m_deltaY; }
+ float getDeltaX() { return this->m_deltaX * this->m_factorX; }
+ float getDeltaY() { return this->m_deltaY * this->m_factorY; }
inline void ensureDelta() {
if (!this->m_isDeltaSet) {
@@ -54,6 +56,8 @@ public:
this->m_isDeltaSet = true;
}
}
+
+ void setFactorXY(float factorX, float factorY);
};
#endif
diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp
index 61720c7676d..03031e0f764 100644
--- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp
@@ -146,7 +146,7 @@ void VariableSizeBokehBlurOperation::executePixel(float output[4], int x, int y,
int offsetNxNy = offsetNy + (minx * COM_NUMBER_OF_CHANNELS);
for (int nx = minx; nx < maxx; nx += QualityStepHelper::getStep()) {
if (nx != x || ny != y) {
- float size = inputSizeFloatBuffer[offsetNxNy] * scalar;
+ float size = min(inputSizeFloatBuffer[offsetNxNy] * scalar, size_center);
if (size > this->m_threshold) {
float dx = nx - x;
if (size > fabsf(dx) && size > fabsf(dy)) {
diff --git a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp
index d5f2c283c72..072246932db 100644
--- a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp
+++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp
@@ -48,6 +48,7 @@ ViewerBaseOperation::ViewerBaseOperation() : NodeOperation()
this->m_doDepthBuffer = false;
this->m_viewSettings = NULL;
this->m_displaySettings = NULL;
+ this->m_ignoreAlpha = false;
}
void ViewerBaseOperation::initExecution()
diff --git a/source/blender/compositor/operations/COM_ViewerBaseOperation.h b/source/blender/compositor/operations/COM_ViewerBaseOperation.h
index f7d479eb3b8..7ead96b5c29 100644
--- a/source/blender/compositor/operations/COM_ViewerBaseOperation.h
+++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.h
@@ -25,6 +25,7 @@
#include "COM_NodeOperation.h"
#include "DNA_image_types.h"
#include "BLI_rect.h"
+#include "BKE_global.h"
class ViewerBaseOperation : public NodeOperation {
protected:
@@ -39,12 +40,13 @@ protected:
OrderOfChunks m_chunkOrder;
bool m_doDepthBuffer;
ImBuf *m_ibuf;
+ bool m_ignoreAlpha;
const ColorManagedViewSettings *m_viewSettings;
const ColorManagedDisplaySettings *m_displaySettings;
public:
- bool isOutputOperation(bool rendering) const { return isActiveViewerOutput(); }
+ bool isOutputOperation(bool rendering) const { if (G.background) return false; return isActiveViewerOutput(); }
void initExecution();
void deinitExecution();
void setImage(Image *image) { this->m_image = image; }
@@ -59,6 +61,7 @@ public:
OrderOfChunks getChunkOrder() { return this->m_chunkOrder; }
const CompositorPriority getRenderPriority() const;
bool isViewerOperation() { return true; }
+ void setIgnoreAlpha(bool value) { this->m_ignoreAlpha = value; }
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_ViewerOperation.cpp b/source/blender/compositor/operations/COM_ViewerOperation.cpp
index d1ac7d74ead..4d10e49aeeb 100644
--- a/source/blender/compositor/operations/COM_ViewerOperation.cpp
+++ b/source/blender/compositor/operations/COM_ViewerOperation.cpp
@@ -89,9 +89,14 @@ void ViewerOperation::executeRegion(rcti *rect, unsigned int tileNumber)
for (y = y1; y < y2 && (!breaked); y++) {
for (x = x1; x < x2; x++) {
this->m_imageInput->read(&(buffer[offset4]), x, y, COM_PS_NEAREST);
- if (this->m_alphaInput != NULL) {
- this->m_alphaInput->read(alpha, x, y, COM_PS_NEAREST);
- buffer[offset4 + 3] = alpha[0];
+ if (this->m_ignoreAlpha) {
+ buffer[offset4 + 3] = 1.0f;
+ }
+ else {
+ if (this->m_alphaInput != NULL) {
+ this->m_alphaInput->read(alpha, x, y, COM_PS_NEAREST);
+ buffer[offset4 + 3] = alpha[0];
+ }
}
if (m_depthInput) {
this->m_depthInput->read(depth, x, y, COM_PS_NEAREST);
diff --git a/source/blender/compositor/operations/COM_WrapOperation.cpp b/source/blender/compositor/operations/COM_WrapOperation.cpp
new file mode 100644
index 00000000000..37a93520c7c
--- /dev/null
+++ b/source/blender/compositor/operations/COM_WrapOperation.cpp
@@ -0,0 +1,117 @@
+/*
+ * 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
+ * Thomas Beck (plasmasolutions.de)
+ */
+
+#include "COM_WrapOperation.h"
+
+WrapOperation::WrapOperation() : NodeOperation()
+{
+ this->addInputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_COLOR);
+ this->setResolutionInputSocketIndex(0);
+ this->m_inputOperation = NULL;
+}
+void WrapOperation::initExecution()
+{
+ this->m_inputOperation = this->getInputSocketReader(0);
+}
+
+void WrapOperation::deinitExecution()
+{
+ this->m_inputOperation = NULL;
+}
+
+inline float WrapOperation::getWrappedOriginalXPos(float x)
+{
+ while (x < 0) x += this->m_width;
+ return fmodf(x, this->getWidth());
+}
+
+inline float WrapOperation::getWrappedOriginalYPos(float y)
+{
+ while (y < 0) y += this->m_height;
+ return fmodf(y, this->getHeight());
+}
+
+void WrapOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+ float nx, ny;
+ nx = x;
+ ny = y;
+ switch (m_wrappingType) {
+ case CMP_NODE_WRAP_NONE:
+ //Intentionally empty, originalXPos and originalYPos have been set before
+ break;
+ case CMP_NODE_WRAP_X:
+ // wrap only on the x-axis
+ nx = this->getWrappedOriginalXPos(x);
+ break;
+ case CMP_NODE_WRAP_Y:
+ // wrap only on the y-axis
+ ny = this->getWrappedOriginalYPos(y);
+ break;
+ case CMP_NODE_WRAP_XY:
+ // wrap on both
+ nx = this->getWrappedOriginalXPos(x);
+ ny = this->getWrappedOriginalYPos(y);
+ break;
+ }
+
+ this->m_inputOperation->read(output, nx, ny, sampler);
+
+}
+
+bool WrapOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+{
+ rcti newInput;
+
+ newInput.xmin = input->xmin;
+ newInput.xmax = input->xmax;
+ newInput.ymin = input->ymin;
+ newInput.ymax = input->ymax;
+
+ if (m_wrappingType == 1 || m_wrappingType == 3) {
+ // wrap only on the x-axis if tile is wrapping
+ newInput.xmin = getWrappedOriginalXPos(input->xmin);
+ newInput.xmax = getWrappedOriginalXPos(input->xmax);
+ if (newInput.xmin > newInput.xmax) {
+ newInput.xmin = 0;
+ newInput.xmax = this->getWidth();
+ }
+ }
+ if (m_wrappingType == 2 || m_wrappingType == 3) {
+ // wrap only on the y-axis if tile is wrapping
+ newInput.ymin = getWrappedOriginalYPos(input->ymin);
+ newInput.ymax = getWrappedOriginalYPos(input->ymax);
+ if (newInput.ymin > newInput.ymax) {
+ newInput.ymin = 0;
+ newInput.ymax = this->getHeight();
+ }
+ }
+
+ return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+}
+
+void WrapOperation::setWrapping(int wrapping_type)
+{
+ m_wrappingType = wrapping_type;
+}
diff --git a/source/blender/compositor/operations/COM_WrapOperation.h b/source/blender/compositor/operations/COM_WrapOperation.h
new file mode 100644
index 00000000000..b84d85e7b5d
--- /dev/null
+++ b/source/blender/compositor/operations/COM_WrapOperation.h
@@ -0,0 +1,47 @@
+/*
+ * 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_WrapOperation_h_
+#define _COM_WrapOperation_h_
+
+#include "COM_NodeOperation.h"
+
+class WrapOperation : public NodeOperation {
+private:
+ SocketReader *m_inputOperation;
+ int m_wrappingType;
+public:
+ WrapOperation();
+ bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
+ void executePixel(float output[4], float x, float y, PixelSampler sampler);
+
+ void initExecution();
+ void deinitExecution();
+
+ void setWrapping(int wrapping_type);
+ float getWrappedOriginalXPos(float x);
+ float getWrappedOriginalYPos(float y);
+
+ void setFactorXY(float factorX, float factorY);
+};
+
+#endif
diff --git a/source/blender/datatoc/datatoc.c b/source/blender/datatoc/datatoc.c
index 379658bb4c4..236d9af8ef1 100644
--- a/source/blender/datatoc/datatoc.c
+++ b/source/blender/datatoc/datatoc.c
@@ -51,6 +51,7 @@ int main(int argc, char **argv)
FILE *fpin, *fpout;
long size;
int i;
+ int argv_len;
if (argc < 2) {
printf("Usage: datatoc <data_file_from> <data_file_to>\n");
@@ -75,7 +76,8 @@ int main(int argc, char **argv)
printf("Making C file <%s>\n", argv[2]);
#endif
- for (i = 0; i < (int)strlen(argv[1]); i++)
+ argv_len = (int)strlen(argv[1]);
+ for (i = 0; i < argv_len; i++)
if (argv[1][i] == '.') argv[1][i] = '_';
fpout = fopen(argv[2], "w");
diff --git a/source/blender/editors/SConscript b/source/blender/editors/SConscript
index 6233ea0dc39..1ea2bc0e4ef 100644
--- a/source/blender/editors/SConscript
+++ b/source/blender/editors/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
diff --git a/source/blender/editors/animation/SConscript b/source/blender/editors/animation/SConscript
index 658ad2794a1..2a6b381ba66 100644
--- a/source/blender/editors/animation/SConscript
+++ b/source/blender/editors/animation/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 9ceecd60bef..c7b28587e47 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -36,6 +36,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_camera_types.h"
@@ -47,6 +49,7 @@
#include "DNA_key_types.h"
#include "DNA_lamp_types.h"
#include "DNA_lattice_types.h"
+#include "DNA_linestyle_types.h"
#include "DNA_mesh_types.h"
#include "DNA_material_types.h"
#include "DNA_meta_types.h"
@@ -82,7 +85,7 @@
#define EXTRA_SCROLL_PAD 100.0f
/* size of indent steps */
-#define INDENT_STEP_SIZE 7
+#define INDENT_STEP_SIZE (0.35f * U.widget_unit)
/* size of string buffers used for animation channel displayed names */
#define ANIM_CHAN_NAME_SIZE 256
@@ -305,15 +308,15 @@ static short acf_generic_group_offset(bAnimContext *ac, bAnimListElem *ale)
if (ale->id) {
/* texture animdata */
if (GS(ale->id->name) == ID_TE) {
- offset += 21;
+ offset += U.widget_unit;
}
/* materials and particles animdata */
else if (ELEM(GS(ale->id->name), ID_MA, ID_PA))
- offset += 14;
+ offset += (short)(0.7f * U.widget_unit);
/* if not in Action Editor mode, action-groups (and their children) must carry some offset too... */
else if (ac->datatype != ANIMCONT_ACTION)
- offset += 14;
+ offset += (short)(0.7f * U.widget_unit);
/* nodetree animdata */
if (GS(ale->id->name) == ID_NT) {
@@ -379,6 +382,10 @@ static short acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListEle
case ACHANNEL_SETTING_MUTE:
return ((ac) && (ac->spacetype == SPACE_NLA));
+ /* select is ok for most "ds*" channels (e.g. dsmat) */
+ case ACHANNEL_SETTING_SELECT:
+ return 1;
+
/* other flags are never supported */
default:
return 0;
@@ -420,7 +427,7 @@ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float ymi
static void acf_summary_name(bAnimListElem *UNUSED(ale), char *name)
{
if (name)
- BLI_strncpy(name, "DopeSheet Summary", ANIM_CHAN_NAME_SIZE);
+ BLI_strncpy(name, IFACE_("DopeSheet Summary"), ANIM_CHAN_NAME_SIZE);
}
// FIXME: this is really a temp icon I think
@@ -891,6 +898,27 @@ static void acf_fcurve_name(bAnimListElem *ale, char *name)
getname_anim_fcurve(name, ale->id, ale->data);
}
+/* "name" property for fcurve entries */
+static short acf_fcurve_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
+{
+ FCurve *fcu = (FCurve *)ale->data;
+
+ /* Ctrl-Click Usability Convenience Hack:
+ * For disabled F-Curves, allow access to the RNA Path
+ * as our "name" so that user can perform quick fixes
+ */
+ if (fcu->flag & FCURVE_DISABLED) {
+ RNA_pointer_create(ale->id, &RNA_FCurve, ale->data, ptr);
+ *prop = RNA_struct_find_property(ptr, "data_path");
+ }
+ else {
+ /* for "normal" F-Curves - no editable name, but *prop may not be set properly yet... */
+ *prop = NULL;
+ }
+
+ return (*prop != NULL);
+}
+
/* check if some setting exists for this channel */
static short acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
{
@@ -962,7 +990,7 @@ static bAnimChannelType ACF_FCURVE =
acf_generic_group_offset, /* offset */
acf_fcurve_name, /* name */
- NULL, /* name prop */
+ acf_fcurve_name_prop, /* name prop */
NULL, /* icon */
acf_fcurve_setting_valid, /* has setting */
@@ -1065,7 +1093,7 @@ static int acf_filldrivers_icon(bAnimListElem *UNUSED(ale))
static void acf_filldrivers_name(bAnimListElem *UNUSED(ale), char *name)
{
- BLI_strncpy(name, "Drivers", ANIM_CHAN_NAME_SIZE);
+ BLI_strncpy(name, IFACE_("Drivers"), ANIM_CHAN_NAME_SIZE);
}
/* check if some setting exists for this channel */
@@ -2010,6 +2038,83 @@ static bAnimChannelType ACF_DSNTREE =
acf_dsntree_setting_ptr /* pointer for setting */
};
+/* LineStyle Expander ------------------------------------------- */
+
+/* TODO: just get this from RNA? */
+static int acf_dslinestyle_icon(bAnimListElem *UNUSED(ale))
+{
+ return ICON_BRUSH_DATA; /* FIXME */
+}
+
+/* get the appropriate flag(s) for the setting when it is valid */
+static int acf_dslinestyle_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+{
+ /* clear extra return data first */
+ *neg = 0;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return LS_DS_EXPAND;
+
+ case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
+ return ADT_NLA_EVAL_OFF;
+
+ case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = 1;
+ 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_dslinestyle_setting_ptr(bAnimListElem *ale, int setting, short *type)
+{
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ale->data;
+
+ /* clear extra return data first */
+ *type = 0;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(linestyle->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 (linestyle->adt)
+ return GET_ACF_FLAG_PTR(linestyle->adt->flag, type);
+ else
+ return NULL;
+
+ default: /* unsupported */
+ return NULL;
+ }
+}
+
+/* node tree expander type define */
+static bAnimChannelType ACF_DSLINESTYLE=
+{
+ "Line Style Expander", /* type name */
+
+ 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_nameprop, /* name prop */
+ acf_dslinestyle_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dslinestyle_setting_flag, /* flag for setting */
+ acf_dslinestyle_setting_ptr /* pointer for setting */
+};
+
/* Mesh Expander ------------------------------------------- */
// TODO: just get this from RNA?
@@ -2254,7 +2359,7 @@ static void acf_shapekey_name(bAnimListElem *ale, char *name)
if (kb->name[0])
BLI_strncpy(name, kb->name, ANIM_CHAN_NAME_SIZE);
else
- BLI_snprintf(name, ANIM_CHAN_NAME_SIZE, "Key %d", ale->index);
+ BLI_snprintf(name, ANIM_CHAN_NAME_SIZE, IFACE_("Key %d"), ale->index);
}
}
@@ -2722,6 +2827,7 @@ static void ANIM_init_channel_typeinfo_data(void)
animchannelTypeInfo[type++] = &ACF_DSTEX; /* Texture Channel */
animchannelTypeInfo[type++] = &ACF_DSLAT; /* Lattice Channel */
animchannelTypeInfo[type++] = &ACF_DSSPK; /* Speaker Channel */
+ animchannelTypeInfo[type++] = &ACF_DSLINESTYLE; /* LineStyle Channel */
animchannelTypeInfo[type++] = &ACF_SHAPEKEY; /* ShapeKey */
@@ -2911,12 +3017,12 @@ void ANIM_channel_setting_set(bAnimContext *ac, bAnimListElem *ale, int setting,
/* --------------------------- */
-// XXX hardcoded size of icons
-#define ICON_WIDTH 17
-// XXX hardcoded width of sliders
-#define SLIDER_WIDTH 80
-// XXX hardcoded width of rename textboxes
-#define RENAME_TEXT_WIDTH 100
+// size of icons
+#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)
/* Draw the given channel */
void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
@@ -2936,13 +3042,11 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
else
offset = 0;
- /* calculate appropriate y-coordinates for icon buttons
- * 7 is hardcoded factor for half-height of icons
- */
+ /* calculate appropriate y-coordinates for icon buttons */
y = (ymaxc - yminc) / 2 + yminc;
- ymid = y - 7;
+ ymid = y - 0.5f * ICON_WIDTH;
/* y-coordinates for text is only 4 down from middle */
- ytext = y - 4;
+ ytext = y - 0.2f * U.widget_unit;
/* check if channel is selected */
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT))
@@ -2989,10 +3093,8 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
glColor3fv(fcu->color);
/* just a solid color rect
- * hardcoded 17 pixels width is slightly wider than icon width, so that
- * there's a slight border around it
*/
- glRectf(offset, yminc, offset + 17, ymaxc);
+ glRectf(offset, yminc, offset + ICON_WIDTH, ymaxc);
}
/* icon is drawn as widget now... */
@@ -3086,7 +3188,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
}
- /* finally draw a backdrop rect behind these
+ /* finally draw a backdrop rect behind these
* - starts from the point where the first toggle/slider starts,
* - ends past the space that might be reserved for a scroller
*/
@@ -3260,21 +3362,21 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChann
icon = ICON_VISIBLE_IPO_OFF;
if (ale->type == ANIMTYPE_FCURVE)
- tooltip = "Channel is visible in Graph Editor for editing";
+ tooltip = TIP_("Channel is visible in Graph Editor for editing");
else
- tooltip = "Channel(s) are visible in Graph Editor for editing";
+ tooltip = TIP_("Channels are visible in Graph Editor for editing");
break;
case ACHANNEL_SETTING_EXPAND: /* expanded triangle */
//icon = ((enabled)? ICON_TRIA_DOWN : ICON_TRIA_RIGHT);
icon = ICON_TRIA_RIGHT;
- tooltip = "Make channels grouped under this channel visible";
+ tooltip = TIP_("Make channels grouped under this channel visible");
break;
case ACHANNEL_SETTING_SOLO: /* NLA Tracks only */
//icon = ((enabled)? ICON_LAYER_ACTIVE : ICON_LAYER_USED);
icon = ICON_LAYER_USED;
- tooltip = "NLA Track is the only one evaluated for the AnimData block it belongs to";
+ tooltip = TIP_("NLA Track is the only one evaluated for the AnimData block it belongs to");
break;
/* --- */
@@ -3283,7 +3385,7 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChann
// TODO: what about when there's no protect needed?
//icon = ((enabled)? ICON_LOCKED : ICON_UNLOCKED);
icon = ICON_UNLOCKED;
- tooltip = "Editability of keyframes for this channel";
+ tooltip = TIP_("Editability of keyframes for this channel");
break;
case ACHANNEL_SETTING_MUTE: /* muted speaker */
@@ -3291,9 +3393,9 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChann
icon = ICON_MUTE_IPO_OFF;
if (ale->type == ALE_FCURVE)
- tooltip = "Does F-Curve contribute to result";
+ tooltip = TIP_("Does F-Curve contribute to result");
else
- tooltip = "Do channels contribute to result";
+ tooltip = TIP_("Do channels contribute to result");
break;
default:
@@ -3365,12 +3467,9 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale
offset = 0;
/* calculate appropriate y-coordinates for icon buttons
- * 7 is hardcoded factor for half-height of icons
*/
y = (ymaxc - yminc) / 2 + yminc;
- ymid = y - 7;
- /* y-coordinates for text is only 4 down from middle */
- /* ytext = y - 4; */
+ ymid = y - 0.5f * ICON_WIDTH;
/* no button backdrop behind icons */
uiBlockSetEmboss(block, UI_EMBOSSN);
@@ -3410,10 +3509,13 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale
/* if rename index matches, add widget for this */
if (ac->ads->renameIndex == channel_index + 1) {
- PointerRNA ptr;
- PropertyRNA *prop;
+ PointerRNA ptr = {{NULL}};
+ PropertyRNA *prop = NULL;
- /* draw renaming widget if we can get RNA pointer for it */
+ /* 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;
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index fe836204c27..481430f37e4 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -124,6 +124,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int f
case ANIMTYPE_DSMESH:
case ANIMTYPE_DSTEX:
case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
/* need to verify that this data is valid for now */
@@ -169,6 +170,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int f
case ANIMTYPE_DSARM:
case ANIMTYPE_DSMESH:
case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
/* need to verify that this data is valid for now */
@@ -249,6 +251,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
case ANIMTYPE_DSNTREE:
case ANIMTYPE_DSTEX:
case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED))
@@ -343,6 +346,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
case ANIMTYPE_DSNTREE:
case ANIMTYPE_DSTEX:
case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
/* need to verify that this data is valid for now */
@@ -538,12 +542,26 @@ void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *f
BLI_remlink(&adt->drivers, fcu);
}
else if (adt->action) {
+ bAction *act = adt->action;
+
/* remove from group or action, whichever one "owns" the F-Curve */
- if (fcu->grp)
- action_groups_remove_channel(adt->action, fcu);
- else
- BLI_remlink(&adt->action->curves, fcu);
+ if (fcu->grp) {
+ bActionGroup *agrp = fcu->grp;
+
+ /* remove F-Curve from group+action */
+ action_groups_remove_channel(act, fcu);
+ /* if group has no more channels, remove it too,
+ * otherwise can have many dangling groups [#33541]
+ */
+ if (agrp->channels.first == NULL) {
+ BLI_freelinkN(&act->groups, agrp);
+ }
+ }
+ else {
+ BLI_remlink(&act->curves, fcu);
+ }
+
/* if action has no more F-Curves as a result of this, unlink it from
* AnimData if it did not come from a NLA Strip being tweaked.
*
@@ -551,12 +569,8 @@ void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *f
* channel list that are empty, and linger around long after the data they
* are for has disappeared (and probably won't come back).
*/
- // XXX: does everybody always want this?
- /* XXX: there's a problem where many actions could build up in the file if multiple
- * full add/delete cycles are performed on the same objects, but assume that this is rare
- */
- if ((adt->action->curves.first == NULL) && (adt->flag & ADT_NLA_EDIT_ON) == 0) {
- id_us_min(&adt->action->id);
+ if ((act->curves.first == NULL) && (adt->flag & ADT_NLA_EDIT_ON) == 0) {
+ id_us_min(&act->id);
adt->action = NULL;
}
}
@@ -1137,6 +1151,218 @@ static void ANIM_OT_channels_move(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "direction", prop_animchannel_rearrange_types, REARRANGE_ANIMCHAN_DOWN, "Direction", "");
}
+/* ******************** Group Channel Operator ************************ */
+
+static int animchannels_grouping_poll(bContext *C)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceLink *sl;
+
+ /* channels region test */
+ /* TODO: could enhance with actually testing if channels region? */
+ if (ELEM(NULL, sa, CTX_wm_region(C)))
+ return 0;
+
+ /* animation editor test - must be suitable modes only */
+ sl = CTX_wm_space_data(C);
+
+ switch (sa->spacetype) {
+ /* supported... */
+ case SPACE_ACTION:
+ {
+ SpaceAction *saction = (SpaceAction *)sl;
+
+ /* 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;
+
+ /* drivers can't have groups... */
+ if (sipo->mode != SIPO_MODE_ANIMATION)
+ return 0;
+ }
+ break;
+
+ /* unsupported... */
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+/* ----------------------------------------------------------- */
+
+static void animchannels_group_channels(bAnimContext *ac, bAnimListElem *adt_ref, const char name[])
+{
+ AnimData *adt = adt_ref->adt;
+ bAction *act = adt->action;
+
+ if (act) {
+ ListBase anim_data = {NULL, NULL};
+ int filter;
+
+ /* find selected F-Curves to re-group */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL);
+ ANIM_animdata_filter(ac, &anim_data, filter, adt_ref, ANIMCONT_CHANNEL);
+
+ if (anim_data.first) {
+ bActionGroup *agrp;
+ bAnimListElem *ale;
+
+ /* create new group, which should now be part of the action */
+ agrp = action_groups_add_new(act, name);
+ BLI_assert(agrp != NULL);
+
+ /* transfer selected F-Curves across to new group */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->data;
+ bActionGroup *grp = fcu->grp;
+
+ /* remove F-Curve from group, then group too if it is now empty */
+ action_groups_remove_channel(act, fcu);
+
+ if ((grp) && (grp->channels.first == NULL)) {
+ BLI_freelinkN(&act->groups, grp);
+ }
+
+ /* add F-Curve to group */
+ action_groups_add_channel(act, agrp, fcu);
+ }
+ }
+
+ /* cleanup */
+ BLI_freelistN(&anim_data);
+ }
+}
+
+static int animchannels_group_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ char name[MAX_NAME];
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get name for new group */
+ RNA_string_get(op->ptr, "name", name);
+
+ /* XXX: name for group should never be empty... */
+ if (name[0]) {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* handle each animdata block separately, so that the regrouping doesn't flow into blocks */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ animchannels_group_channels(&ac, ale, name);
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+
+ /* updatss */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void ANIM_OT_channels_group(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Group Channels";
+ ot->idname = "ANIM_OT_channels_group";
+ ot->description = "Add selected F-Curves to a new group";
+
+ /* callbacks */
+ ot->invoke = WM_operator_props_popup;
+ ot->exec = animchannels_group_exec;
+ ot->poll = animchannels_grouping_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ ot->prop = RNA_def_string(ot->srna, "name", "New Group",
+ sizeof(((bActionGroup *)NULL)->name),
+ "Name", "Name of newly created group");
+ /* RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); */ /* XXX: still not too sure about this - keeping same text is confusing... */
+}
+
+/* ----------------------------------------------------------- */
+
+static int animchannels_ungroup_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* just selected F-Curves... */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* find action for this F-Curve... */
+ if (ale->adt && ale->adt->action) {
+ FCurve *fcu = (FCurve *)ale->data;
+ bAction *act = ale->adt->action;
+
+ /* only proceed to remove if F-Curve is in a group... */
+ if (fcu->grp) {
+ bActionGroup *agrp = fcu->grp;
+
+ /* remove F-Curve from group and add at tail (ungrouped) */
+ action_groups_remove_channel(act, fcu);
+ BLI_addtail(&act->curves, fcu);
+
+ /* delete group if it is now empty */
+ if (agrp->channels.first == NULL) {
+ BLI_freelinkN(&act->groups, agrp);
+ }
+ }
+ }
+ }
+
+ /* cleanup */
+ BLI_freelistN(&anim_data);
+
+ /* updates */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static void ANIM_OT_channels_ungroup(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Ungroup Channels";
+ ot->idname = "ANIM_OT_channels_ungroup";
+ ot->description = "Remove selected F-Curves from their current groups";
+
+ /* callbacks */
+ ot->exec = animchannels_ungroup_exec;
+ ot->poll = animchannels_grouping_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
/* ******************** Delete Channel Operator *********************** */
static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
@@ -1223,13 +1449,13 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
BLI_freelinkN(&gpd->layers, gpl);
}
break;
-
+
case ANIMTYPE_MASKLAYER:
{
- /* Grease Pencil layer */
+ /* Mask layer */
Mask *mask = (Mask *)ale->id;
MaskLayer *masklay = (MaskLayer *)ale->data;
-
+
/* try to delete the layer's data and the layer itself */
BKE_mask_layer_remove(mask, masklay);
}
@@ -1320,10 +1546,10 @@ static int animchannels_visibility_set_exec(bContext *C, wmOperator *UNUSED(op))
/* 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);
}
@@ -1397,10 +1623,10 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *UNUSED(o
/* 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));
}
@@ -2038,7 +2264,7 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index)
ED_region_tag_redraw(ac->ar);
}
-static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *evt)
+static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
bAnimContext ac;
ARegion *ar;
@@ -2059,7 +2285,7 @@ static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), wmEve
* 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, evt->mval[0], evt->mval[1], &x, &y);
+ UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y);
if (ac.datatype == ANIMCONT_NLA) {
SpaceNla *snla = (SpaceNla *)ac.sl;
@@ -2197,6 +2423,7 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
case ANIMTYPE_DSNTREE:
case ANIMTYPE_DSTEX:
case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
/* sanity checking... */
@@ -2218,7 +2445,7 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
}
notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
- }
+ }
break;
case ANIMTYPE_GROUP:
@@ -2372,7 +2599,7 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
/* ------------------- */
/* handle clicking */
-static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
bAnimContext ac;
ARegion *ar;
@@ -2430,7 +2657,7 @@ static void ANIM_OT_channels_click(wmOperatorType *ot)
ot->poll = animedit_poll_channels_active;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_UNDO;
/* properties */
/* NOTE: don't save settings, otherwise, can end up with some weird behaviour (sticky extend) */
@@ -2470,6 +2697,9 @@ void ED_operatortypes_animchannels(void)
WM_operatortype_append(ANIM_OT_channels_visibility_set);
WM_operatortype_append(ANIM_OT_channels_fcurves_enable);
+
+ WM_operatortype_append(ANIM_OT_channels_group);
+ WM_operatortype_append(ANIM_OT_channels_ungroup);
}
// TODO: check on a poll callback for this, to get hotkeys into menus
@@ -2523,6 +2753,10 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_move", PAGEUPKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "direction", REARRANGE_ANIMCHAN_TOP);
RNA_enum_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_move", PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "direction", REARRANGE_ANIMCHAN_BOTTOM);
+ /* 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_draw.c b/source/blender/editors/animation/anim_draw.c
index 0f0584ad8fe..eb1f5ef1043 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -33,9 +33,12 @@
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+
#include "BLI_math.h"
#include "BKE_context.h"
+#include "BKE_blender.h"
#include "BKE_global.h"
#include "BKE_nla.h"
#include "BKE_object.h"
@@ -197,15 +200,15 @@ static void draw_cfra_number(Scene *scene, View2D *v2d, float cfra, short time)
/* get starting coordinates for drawing */
x = cfra * xscale;
- y = 18;
+ y = 0.9f * U.widget_unit;
/* draw green box around/behind text */
UI_ThemeColorShade(TH_CFRAME, 0);
- glRectf(x, y, x + slen, y + 15);
+ glRectf(x, y, x + slen, y + 0.75f * U.widget_unit);
/* draw current frame number - black text */
UI_ThemeColor(TH_TEXT);
- UI_DrawString(x - 5, y + 3, numstr);
+ UI_DrawString(x - 0.25f * U.widget_unit, y + 0.15f * U.widget_unit, numstr);
/* restore view transform */
glScalef(xscale, 1.0, 1.0);
@@ -396,20 +399,23 @@ float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short rest
static short bezt_unit_mapping_apply(KeyframeEditData *ked, BezTriple *bezt)
{
/* mapping factor is stored in f1, flags are stored in i1 */
- short only_keys = (ked->i1 & ANIM_UNITCONV_ONLYKEYS);
- short sel_vs = (ked->i1 & ANIM_UNITCONV_SELVERTS);
+ const bool only_keys = (ked->i1 & ANIM_UNITCONV_ONLYKEYS);
+ const bool sel_vs = (ked->i1 & ANIM_UNITCONV_SELVERTS);
+ const bool skip_knot = (ked->i1 & ANIM_UNITCONV_SKIPKNOTS);
float fac = ked->f1;
/* adjust BezTriple handles only if allowed to */
- if (only_keys == 0) {
- if ((sel_vs == 0) || (bezt->f1 & SELECT))
+ if (only_keys == false) {
+ if ((sel_vs == false) || (bezt->f1 & SELECT))
bezt->vec[0][1] *= fac;
- if ((sel_vs == 0) || (bezt->f3 & SELECT))
+ if ((sel_vs == false) || (bezt->f3 & SELECT))
bezt->vec[2][1] *= fac;
}
- if ((sel_vs == 0) || (bezt->f2 & SELECT))
- bezt->vec[1][1] *= fac;
+ if (skip_knot == false) {
+ if ((sel_vs == false) || (bezt->f2 & SELECT))
+ bezt->vec[1][1] *= fac;
+ }
return 0;
}
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 5e215fbd6a2..61e03806391 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -55,6 +55,7 @@
#include "DNA_camera_types.h"
#include "DNA_lamp_types.h"
#include "DNA_lattice_types.h"
+#include "DNA_linestyle_types.h"
#include "DNA_key_types.h"
#include "DNA_mask_types.h"
#include "DNA_material_types.h"
@@ -290,7 +291,7 @@ static short nlaedit_get_context(bAnimContext *ac, SpaceNla *snla)
short ANIM_animdata_context_getdata(bAnimContext *ac)
{
SpaceLink *sl = ac->sl;
- short ok = 0;
+ short ok = FALSE;
/* context depends on editor we are currently in */
if (sl) {
@@ -319,10 +320,7 @@ short ANIM_animdata_context_getdata(bAnimContext *ac)
}
/* check if there's any valid data */
- if (ok && ac->data)
- return 1;
- else
- return 0;
+ return (ok && ac->data);
}
/* Obtain current anim-data context from Blender Context info
@@ -354,6 +352,7 @@ short ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
ac->regiontype = (ar) ? ar->regiontype : 0;
/* get data context info */
+ // XXX: if the below fails, try to grab this info from context instead... (to allow for scripting)
return ANIM_animdata_context_getdata(ac);
}
@@ -448,7 +447,7 @@ short ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
if (ANIMDATA_HAS_NLA(id)) { \
nlaOk \
} \
- else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) && ANIMDATA_HAS_KEYS(id)) { \
+ else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) || ANIMDATA_HAS_KEYS(id)) { \
nlaOk \
} \
} \
@@ -736,6 +735,19 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
ale->adt = BKE_animdata_from_id(data);
}
break;
+ case ANIMTYPE_DSLINESTYLE:
+ {
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)data;
+ AnimData *adt = linestyle->adt;
+
+ ale->flag = FILTER_LS_SCED(linestyle);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ }
+ break;
case ANIMTYPE_DSPART:
{
ParticleSettings *part = (ParticleSettings *)ale->data;
@@ -913,14 +925,14 @@ static short skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_i
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
Sequence *seq = NULL;
char *seq_name;
-
+
if (ed) {
/* get strip name, and check if this strip is selected */
seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all[");
seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, FALSE);
if (seq_name) MEM_freeN(seq_name);
}
-
+
/* can only add this F-Curve if it is selected */
if (ads->filterflag & ADS_FILTER_ONLYSEL) {
if ((seq == NULL) || (seq->flag & SELECT) == 0)
@@ -985,22 +997,39 @@ static short skip_fcurve_with_name(bDopeSheet *ads, FCurve *fcu, ID *owner_id)
/* Check if F-Curve has errors and/or is disabled
* > returns: (bool) True if F-Curve has errors/is disabled
*/
-static short fcurve_has_errors(FCurve *fcu)
+static bool fcurve_has_errors(FCurve *fcu)
{
/* F-Curve disabled - path eval error */
if (fcu->flag & FCURVE_DISABLED) {
- return 1;
+ return true;
}
/* driver? */
if (fcu->driver) {
- /* for now, just check if the entire thing got disabled... */
- if (fcu->driver->flag & DRIVER_FLAG_INVALID)
- return 1;
+ ChannelDriver *driver = fcu->driver;
+ DriverVar *dvar;
+
+ /* error flag on driver usually means that there is an error
+ * BUT this may not hold with PyDrivers as this flag gets cleared
+ * if no critical errors prevent the driver from working...
+ */
+ if (driver->flag & DRIVER_FLAG_INVALID)
+ return true;
+
+ /* check variables for other things that need linting... */
+ // TODO: maybe it would be more efficient just to have a quick flag for this?
+ for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
+ DRIVER_TARGETS_USED_LOOPER(dvar)
+ {
+ if (dtar->flag & DTAR_FLAG_INVALID)
+ return true;
+ }
+ DRIVER_TARGETS_LOOPER_END
+ }
}
/* no errors found */
- return 0;
+ return false;
}
/* find the next F-Curve that is usable for inclusion */
@@ -1044,7 +1073,7 @@ static FCurve *animfilter_fcurve_next(bDopeSheet *ads, FCurve *first, bActionGro
/* error-based filtering... */
if ((ads) && (ads->filterflag & ADS_FILTER_ONLY_ERRORS)) {
/* skip if no errors... */
- if (fcurve_has_errors(fcu) == 0)
+ if (fcurve_has_errors(fcu) == false)
continue;
}
@@ -1281,7 +1310,9 @@ static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDope
ANIMDATA_FILTER_CASES(iat,
{ /* AnimData */
/* specifically filter animdata block */
- ANIMCHANNEL_NEW_CHANNEL(adt, ANIMTYPE_ANIMDATA, id);
+ if (ANIMCHANNEL_SELOK(SEL_ANIMDATA(adt)) ) {
+ ANIMCHANNEL_NEW_CHANNEL(adt, ANIMTYPE_ANIMDATA, id);
+ }
},
{ /* NLA */
items += animfilter_nla(ac, anim_data, ads, adt, filter_mode, id);
@@ -1331,7 +1362,9 @@ static size_t animdata_filter_shapekey(bAnimContext *ac, ListBase *anim_data, Ke
// TODO: somehow manage to pass dopesheet info down here too?
if (key->adt) {
if (filter_mode & ANIMFILTER_ANIMDATA) {
- ANIMCHANNEL_NEW_CHANNEL(key->adt, ANIMTYPE_ANIMDATA, key);
+ if (ANIMCHANNEL_SELOK(SEL_ANIMDATA(key->adt)) ) {
+ ANIMCHANNEL_NEW_CHANNEL(key->adt, ANIMTYPE_ANIMDATA, key);
+ }
}
else if (key->adt->action) {
items = animfilter_action(ac, anim_data, NULL, key->adt->action, filter_mode, (ID *)key);
@@ -1513,6 +1546,54 @@ static size_t animdata_filter_ds_nodetree(bAnimContext *ac, ListBase *anim_data,
return items;
}
+static size_t animdata_filter_ds_linestyle (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
+{
+ SceneRenderLayer *srl;
+ size_t items = 0;
+
+ for (srl = sce->r.layers.first; srl; srl = srl->next) {
+ FreestyleLineSet *lineset;
+
+ /* skip render layers without Freestyle enabled */
+ if (!(srl->layflag & SCE_LAY_FRS))
+ continue;
+
+ /* loop over linesets defined in the render layer */
+ for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+ FreestyleLineStyle *linestyle = lineset->linestyle;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+
+ /* add scene-level animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_LS_SCED(linestyle))
+ {
+ /* animation data filtering */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)linestyle, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include anim-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by active status */
+ if ANIMCHANNEL_ACTIVEOK(linestyle) {
+ ANIMCHANNEL_NEW_CHANNEL(linestyle, ANIMTYPE_DSLINESTYLE, sce);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL));
+ items += tmp_items;
+ }
+ }
+ }
+
+ /* return the number of items added to the list */
+ return items;
+}
+
/* NOTE: owner_id is either material, lamp, or world block, which is the direct owner of the texture stack in question */
static size_t animdata_filter_ds_textures(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, int filter_mode)
{
@@ -2146,7 +2227,12 @@ static size_t animdata_filter_dopesheet_scene(bAnimContext *ac, ListBase *anim_d
if ((ntree) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, (ID *)sce, ntree, filter_mode);
}
-
+
+ /* line styles */
+ if ((ads->filterflag & ADS_FILTER_NOLINESTYLE) == 0) {
+ tmp_items += animdata_filter_ds_linestyle(ac, &tmp_data, ads, sce, filter_mode);
+ }
+
/* TODO: one day, when sequencer becomes its own datatype, perhaps it should be included here */
}
END_ANIMFILTER_SUBCHANNELS;
@@ -2318,6 +2404,10 @@ static size_t animdata_filter_animchan(bAnimContext *ac, ListBase *anim_data, bD
items += animdata_filter_dopesheet_ob(ac, anim_data, ads, channel->data, filter_mode);
break;
+ case ANIMTYPE_ANIMDATA:
+ items += animfilter_block_data(ac, anim_data, ads, channel->id, filter_mode);
+ break;
+
default:
printf("ERROR: Unsupported channel type (%d) in animdata_filter_animchan()\n", channel->type);
break;
diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c
index d8e3349e998..2352cad0cbc 100644
--- a/source/blender/editors/animation/anim_ipo_utils.c
+++ b/source/blender/editors/animation/anim_ipo_utils.c
@@ -42,6 +42,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "DNA_anim_types.h"
#include "RNA_access.h"
@@ -63,9 +65,9 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
return icon;
else if (ELEM3(NULL, id, fcu, fcu->rna_path)) {
if (fcu == NULL)
- strcpy(name, "<invalid>");
+ strcpy(name, IFACE_("<invalid>"));
else if (fcu->rna_path == NULL)
- strcpy(name, "<no path>");
+ strcpy(name, IFACE_("<no path>"));
else /* id == NULL */
BLI_snprintf(name, 256, "%s[%d]", fcu->rna_path, fcu->array_index);
}
@@ -143,7 +145,7 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
/* no array index */
arrayname = "";
}
-
+
/* putting this all together into the buffer */
/* XXX we need to check for invalid names...
* XXX the name length limit needs to be passed in or as some define */
@@ -151,7 +153,7 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
BLI_snprintf(name, 256, "%s%s (%s)", arrayname, propname, structname);
else
BLI_snprintf(name, 256, "%s%s", arrayname, propname);
-
+
/* free temp name if nameprop is set */
if (free_structname)
MEM_freeN((void *)structname);
@@ -170,11 +172,11 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
else {
/* invalid path */
BLI_snprintf(name, 256, "\"%s[%d]\"", fcu->rna_path, fcu->array_index);
-
+
/* icon for this should be the icon for the base ID */
/* TODO: or should we just use the error icon? */
icon = RNA_struct_ui_icon(id_ptr.type);
-
+
/* tag F-Curve as disabled - as not usable path */
fcu->flag |= FCURVE_DISABLED;
}
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 1b980790fdc..205f67cf96a 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -28,7 +28,6 @@
* \ingroup edanimation
*/
-
#include <math.h>
#include "MEM_guardedalloc.h"
@@ -36,11 +35,8 @@
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
-#include "RNA_access.h"
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
#include "BLI_blenlib.h"
+#include "BLI_math_base.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -50,6 +46,10 @@
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -146,16 +146,15 @@ int ED_markers_post_apply_transform(ListBase *markers, Scene *scene, int mode, f
marker->frame += (int)floorf(value + 0.5f);
changed++;
}
+ break;
}
- break;
-
case TFM_TIME_SCALE:
{
/* rescale the distance between the marker and the current frame */
marker->frame = cfra + (int)floorf(((float)(marker->frame - cfra) * value) + 0.5f);
changed++;
+ break;
}
- break;
}
}
}
@@ -277,7 +276,9 @@ static void add_marker_to_cfra_elem(ListBase *lb, TimeMarker *marker, short only
ce->sel = marker->flag;
return;
}
- else if (ce->cfra > marker->frame) break;
+ else if (ce->cfra > marker->frame) {
+ break;
+ }
}
cen = MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem");
@@ -395,28 +396,33 @@ static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag)
ICON_MARKER;
}
- UI_icon_draw(xpos * xscale - 5.0f, 16.0f, icon_id);
+ UI_icon_draw(xpos * xscale - 0.3f * UI_DPI_ICON_SIZE, UI_DPI_ICON_SIZE, icon_id);
glDisable(GL_BLEND);
/* and the marker name too, shifted slightly to the top-right */
if (marker->name && marker->name[0]) {
float x, y;
+
+ /* minimal y coordinate which wouldn't be occluded by scroll */
+ int min_y = 17.0f * UI_DPI_FAC;
if (marker->flag & SELECT) {
UI_ThemeColor(TH_TEXT_HI);
- x = xpos * xscale + 4.0f;
- y = (ypixels <= 39.0f) ? (ypixels - 10.0f) : 29.0f;
+ x = xpos * xscale + 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 + 4.0f;
- y = (ypixels <= 39.0f) ? (ypixels - 10.0f) : 29.0f;
+ x = xpos * xscale + 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 + 4.0f;
- y = 17.0f;
+ x = xpos * xscale + 8.0f * UI_DPI_FAC;
+ y = 17.0f * UI_DPI_FAC;
}
}
@@ -508,8 +514,8 @@ static int ed_markers_poll_markers_exist(bContext *C)
* that operator would otherwise have used. If NULL, the operator's standard
* exec() callback will be called instead in the appropriate places.
*/
-static int ed_markers_opwrap_invoke_custom(bContext *C, wmOperator *op, wmEvent *evt,
- int (*invoke_func)(bContext *, wmOperator *, wmEvent *))
+static int ed_markers_opwrap_invoke_custom(bContext *C, wmOperator *op, const wmEvent *event,
+ int (*invoke_func)(bContext *, wmOperator *, const wmEvent *))
{
ScrArea *sa = CTX_wm_area(C);
int retval = OPERATOR_PASS_THROUGH;
@@ -518,7 +524,7 @@ static int ed_markers_opwrap_invoke_custom(bContext *C, wmOperator *op, wmEvent
/* allow operator to run now */
if (invoke_func)
- retval = invoke_func(C, op, evt);
+ retval = invoke_func(C, op, event);
else if (op->type->exec)
retval = op->type->exec(C, op);
else
@@ -539,9 +545,9 @@ static int ed_markers_opwrap_invoke_custom(bContext *C, wmOperator *op, wmEvent
* though will need to implement their own wrapper which calls the second-tier callback themselves
* (passing through the custom invoke function they use)
*/
-static int ed_markers_opwrap_invoke(bContext *C, wmOperator *op, wmEvent *evt)
+static int ed_markers_opwrap_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- return ed_markers_opwrap_invoke_custom(C, op, evt, NULL);
+ return ed_markers_opwrap_invoke_custom(C, op, event, NULL);
}
/* ************************** add markers *************************** */
@@ -679,14 +685,14 @@ static void ed_marker_move_exit(bContext *C, wmOperator *op)
ED_area_headerprint(CTX_wm_area(C), NULL);
}
-static int ed_marker_move_invoke(bContext *C, wmOperator *op, wmEvent *evt)
+static int ed_marker_move_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (ed_marker_move_init(C, op)) {
MarkerMove *mm = op->customdata;
- mm->evtx = evt->x;
- mm->firstx = evt->x;
- mm->event_type = evt->type;
+ mm->evtx = event->x;
+ mm->firstx = event->x;
+ mm->event_type = event->type;
/* add temp handler */
WM_event_add_modal_handler(C, op);
@@ -700,9 +706,9 @@ static int ed_marker_move_invoke(bContext *C, wmOperator *op, wmEvent *evt)
return OPERATOR_CANCELLED;
}
-static int ed_marker_move_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
+static int ed_marker_move_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event)
{
- return ed_markers_opwrap_invoke_custom(C, op, evt, ed_marker_move_invoke);
+ return ed_markers_opwrap_invoke_custom(C, op, event, ed_marker_move_invoke);
}
/* note, init has to be called succesfully */
@@ -751,7 +757,7 @@ static int ed_marker_move_cancel(bContext *C, wmOperator *op)
-static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt)
+static int ed_marker_move_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
MarkerMove *mm = op->customdata;
@@ -760,14 +766,14 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt)
float dx, fac;
char str[256];
- switch (evt->type) {
+ switch (event->type) {
case ESCKEY:
ed_marker_move_cancel(C, op);
return OPERATOR_CANCELLED;
case RIGHTMOUSE:
/* press = user manually demands transform to be canceled */
- if (evt->val == KM_PRESS) {
+ if (event->val == KM_PRESS) {
ed_marker_move_cancel(C, op);
return OPERATOR_CANCELLED;
}
@@ -777,7 +783,7 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt)
case PADENTER:
case LEFTMOUSE:
case MIDDLEMOUSE:
- if (WM_modal_tweak_exit(evt, mm->event_type)) {
+ if (WM_modal_tweak_exit(event, mm->event_type)) {
ed_marker_move_exit(C, op);
WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
@@ -790,17 +796,17 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt)
dx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
- if (evt->x != mm->evtx) { /* XXX maybe init for first time */
+ if (event->x != mm->evtx) { /* XXX maybe init for first time */
int a, offs, totmark = 0;
- mm->evtx = evt->x;
+ mm->evtx = event->x;
- fac = ((float)(evt->x - mm->firstx) * dx);
+ fac = ((float)(event->x - mm->firstx) * dx);
if (mm->slink->spacetype == SPACE_TIME)
- apply_keyb_grid(evt->shift, evt->ctrl, &fac, 0.0, FPS, 0.1 * FPS, 0);
+ apply_keyb_grid(event->shift, event->ctrl, &fac, 0.0, FPS, 0.1 * FPS, 0);
else
- apply_keyb_grid(evt->shift, evt->ctrl, &fac, 0.0, 1.0, 0.1, 0 /*was: U.flag & USER_AUTOGRABGRID*/);
+ apply_keyb_grid(event->shift, event->ctrl, &fac, 0.0, 1.0, 0.1, 0 /*was: U.flag & USER_AUTOGRABGRID*/);
offs = (int)fac;
RNA_int_set(op->ptr, "frames", offs);
@@ -859,8 +865,8 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt)
}
}
- if (evt->val == KM_PRESS) {
- if (handleNumInput(&mm->num, evt)) {
+ if (event->val == KM_PRESS) {
+ if (handleNumInput(&mm->num, event)) {
char str_tx[NUM_STR_REP_LEN];
float value = RNA_int_get(op->ptr, "frames");
applyNumInput(&mm->num, &value);
@@ -976,15 +982,15 @@ static int ed_marker_duplicate_exec(bContext *C, wmOperator *op)
}
-static int ed_marker_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *evt)
+static int ed_marker_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ed_marker_duplicate_apply(C);
- return ed_marker_move_invoke(C, op, evt);
+ return ed_marker_move_invoke(C, op, event);
}
-static int ed_marker_duplicate_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
+static int ed_marker_duplicate_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event)
{
- return ed_markers_opwrap_invoke_custom(C, op, evt, ed_marker_duplicate_invoke);
+ return ed_markers_opwrap_invoke_custom(C, op, event, ed_marker_duplicate_invoke);
}
static void MARKER_OT_duplicate(wmOperatorType *ot)
@@ -1031,7 +1037,7 @@ static void select_timeline_marker_frame(ListBase *markers, int frame, unsigned
}
}
-static int ed_marker_select(bContext *C, wmEvent *evt, int extend, int camera)
+static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool camera)
{
ListBase *markers = ED_context_get_markers(C);
ARegion *ar = CTX_wm_region(C);
@@ -1042,8 +1048,8 @@ static int ed_marker_select(bContext *C, wmEvent *evt, int extend, int camera)
if (markers == NULL)
return OPERATOR_PASS_THROUGH;
- x = evt->x - ar->winrct.xmin;
- y = evt->y - ar->winrct.ymin;
+ x = event->x - ar->winrct.xmin;
+ y = event->y - ar->winrct.ymin;
UI_view2d_region_to_view(v2d, x, y, &viewx, NULL);
@@ -1098,19 +1104,19 @@ static int ed_marker_select(bContext *C, wmEvent *evt, int extend, int camera)
return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
}
-static int ed_marker_select_invoke(bContext *C, wmOperator *op, wmEvent *evt)
+static int ed_marker_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- short extend = RNA_boolean_get(op->ptr, "extend");
- short camera = 0;
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+ bool camera = false;
#ifdef DURIAN_CAMERA_SWITCH
camera = RNA_boolean_get(op->ptr, "camera");
#endif
- return ed_marker_select(C, evt, extend, camera);
+ return ed_marker_select(C, event, extend, camera);
}
-static int ed_marker_select_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
+static int ed_marker_select_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event)
{
- return ed_markers_opwrap_invoke_custom(C, op, evt, ed_marker_select_invoke);
+ return ed_markers_opwrap_invoke_custom(C, op, event, ed_marker_select_invoke);
}
static void MARKER_OT_select(wmOperatorType *ot)
@@ -1195,15 +1201,15 @@ static int ed_marker_border_select_exec(bContext *C, wmOperator *op)
return 1;
}
-static int ed_marker_select_border_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
+static int ed_marker_select_border_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event)
{
- return ed_markers_opwrap_invoke_custom(C, op, evt, WM_border_select_invoke);
+ return ed_markers_opwrap_invoke_custom(C, op, event, WM_border_select_invoke);
}
static void MARKER_OT_select_border(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Marker Border select";
+ ot->name = "Marker Border Select";
ot->description = "Select all time markers using border selection";
ot->idname = "MARKER_OT_select_border";
@@ -1260,7 +1266,7 @@ static int ed_marker_select_all_exec(bContext *C, wmOperator *op)
static void MARKER_OT_select_all(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "(De)select all markers";
+ ot->name = "(De)select all Markers";
ot->description = "Change selection of all time markers";
ot->idname = "MARKER_OT_select_all";
@@ -1304,10 +1310,10 @@ static int ed_marker_delete_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-static int ed_marker_delete_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
+static int ed_marker_delete_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event)
{
// XXX: must we keep these confirmations?
- return ed_markers_opwrap_invoke_custom(C, op, evt, WM_operator_confirm);
+ return ed_markers_opwrap_invoke_custom(C, op, event, WM_operator_confirm);
}
static void MARKER_OT_delete(wmOperatorType *ot)
@@ -1347,7 +1353,7 @@ static int ed_marker_rename_exec(bContext *C, wmOperator *op)
}
}
-static int ed_marker_rename_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
+static int ed_marker_rename_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event)
{
/* must initialize the marker name first if there is a marker selected */
TimeMarker *marker = ED_markers_get_first_selected(ED_context_get_markers(C));
@@ -1355,7 +1361,7 @@ static int ed_marker_rename_invoke_wrapper(bContext *C, wmOperator *op, wmEvent
RNA_string_set(op->ptr, "name", marker->name);
/* now see if the operator is usable */
- return ed_markers_opwrap_invoke_custom(C, op, evt, WM_operator_props_popup);
+ return ed_markers_opwrap_invoke_custom(C, op, event, WM_operator_props_popup);
}
static void MARKER_OT_rename(wmOperatorType *ot)
@@ -1409,9 +1415,9 @@ static int ed_marker_make_links_scene_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int ed_marker_make_links_scene_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
+static int ed_marker_make_links_scene_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event)
{
- return ed_markers_opwrap_invoke_custom(C, op, evt, WM_menu_invoke);
+ return ed_markers_opwrap_invoke_custom(C, op, event, WM_menu_invoke);
}
static void MARKER_OT_make_links_scene(wmOperatorType *ot)
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index ca036a8540e..b9a3daa4e51 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -62,16 +62,28 @@
/* Check if the operator can be run from the current context */
static int change_frame_poll(bContext *C)
{
- ScrArea *curarea = CTX_wm_area(C);
+ ScrArea *sa = CTX_wm_area(C);
/* XXX temp? prevent changes during render */
- if (G.is_rendering) return 0;
+ if (G.is_rendering) return FALSE;
- /* as long as there is an active area, and it isn't a Graph Editor
- * (since the Graph Editor has its own version which does extra stuff),
- * we're fine
+ /* although it's only included in keymaps for regions using ED_KEYMAP_ANIMATION,
+ * this shouldn't show up in 3D editor (or others without 2D timeline view) via search
*/
- return ((curarea) && (curarea->spacetype != SPACE_IPO));
+ if (sa) {
+ if (ELEM5(sa->spacetype, SPACE_TIME, SPACE_ACTION, SPACE_NLA, SPACE_SEQ, SPACE_CLIP)) {
+ return TRUE;
+ }
+ else if (sa->spacetype == SPACE_IPO) {
+ /* NOTE: Graph Editor has special version which does some extra stuff.
+ * No need to show the generic error message for that case though!
+ */
+ return FALSE;
+ }
+ }
+
+ CTX_wm_operator_poll_msg_set(C, "Expected an timeline/animation area to be active");
+ return FALSE;
}
/* Set the new frame number */
@@ -83,7 +95,7 @@ static void change_frame_apply(bContext *C, wmOperator *op)
/* set the new frame number */
CFRA = RNA_int_get(op->ptr, "frame");
FRAMENUMBER_MIN_CLAMP(CFRA);
- SUBFRA = 0.f;
+ SUBFRA = 0.0f;
/* do updates */
sound_seek_scene(bmain, scene);
@@ -103,7 +115,7 @@ static int change_frame_exec(bContext *C, wmOperator *op)
/* ---- */
/* Get frame from mouse coordinates */
-static int frame_from_event(bContext *C, wmEvent *event)
+static int frame_from_event(bContext *C, const wmEvent *event)
{
ARegion *region = CTX_wm_region(C);
float viewx;
@@ -116,7 +128,7 @@ static int frame_from_event(bContext *C, wmEvent *event)
}
/* Modal Operator init */
-static int change_frame_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
/* 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
@@ -133,7 +145,7 @@ static int change_frame_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
/* Modal event handling of frame changing */
-static int change_frame_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
/* execute the events */
switch (event->type) {
@@ -161,7 +173,7 @@ static int change_frame_modal(bContext *C, wmOperator *op, wmEvent *event)
static void ANIM_OT_change_frame(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Change frame";
+ ot->name = "Change Frame";
ot->idname = "ANIM_OT_change_frame";
ot->description = "Interactively change the current frame number";
@@ -175,7 +187,7 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO | OPTYPE_GRAB_POINTER;
/* rna */
- RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
+ ot->prop = RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
}
/* ****************** set preview range operator ****************************/
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 25833c13925..cd5e873f40d 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -489,8 +489,6 @@ static int add_driver_button_exec(bContext *C, wmOperator *op)
/* send updates */
uiContextAnimUpdate(C);
- DAG_ids_flush_update(CTX_data_main(C), 0);
-
WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX
}
@@ -541,8 +539,6 @@ static int remove_driver_button_exec(bContext *C, wmOperator *op)
/* send updates */
uiContextAnimUpdate(C);
- DAG_ids_flush_update(CTX_data_main(C), 0);
-
WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX
}
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
index 79a4c9a769d..dcdab8dba37 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -151,7 +151,7 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
}
else {
/* basic size (just "x") */
- maxXWidth = 15;
+ maxXWidth = UI_GetStringWidth("x") + 10;
}
/* draw controls for each coefficient and a + sign at end of row */
@@ -231,16 +231,16 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s
uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 100, 20, cp + 1, -UI_FLT_MAX, UI_FLT_MAX,
10, 3, TIP_("Second coefficient"));
- /* closing bracket and '+' sign */
+ /* closing bracket and multiplication sign */
if ( (i != (data->poly_order - 1)) || ((i == 0) && data->poly_order == 2) ) {
- uiDefBut(block, LABEL, 1, ") +", 0, 0, 30, 20, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, LABEL, 1, ") ×", 0, 0, 40, 20, 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, 20, 20, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, LABEL, 1, ") ", 0, 0, 40, 20, NULL, 0.0, 0.0, 0, 0, "");
}
}
break;
@@ -327,88 +327,7 @@ static void draw_modifier__noise(uiLayout *layout, ID *id, FModifier *fcm, short
uiItemR(col, &ptr, "depth", 0, NULL, ICON_NONE);
}
-/* --------------- */
-
-#define BINARYSEARCH_FRAMEEQ_THRESH 0.0001f
-
-/* Binary search algorithm for finding where to insert Envelope Data Point.
- * Returns the index to insert at (data already at that index will be offset if replace is 0)
- */
-static int binarysearch_fcm_envelopedata_index(FCM_EnvelopeData array[], float frame, int arraylen, short *exists)
-{
- int start = 0, end = arraylen;
- int loopbreaker = 0, maxloop = arraylen * 2;
-
- /* initialize exists-flag first */
- *exists = 0;
-
- /* sneaky optimizations (don't go through searching process if...):
- * - keyframe to be added is to be added out of current bounds
- * - keyframe to be added would replace one of the existing ones on bounds
- */
- if ((arraylen <= 0) || (array == NULL)) {
- printf("Warning: binarysearch_fcm_envelopedata_index() encountered invalid array\n");
- return 0;
- }
- else {
- /* check whether to add before/after/on */
- float framenum;
-
- /* 'First' Point (when only one point, this case is used) */
- framenum = array[0].time;
- if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
- *exists = 1;
- return 0;
- }
- else if (frame < framenum)
- return 0;
-
- /* 'Last' Point */
- framenum = array[(arraylen - 1)].time;
- if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
- *exists = 1;
- return (arraylen - 1);
- }
- else if (frame > framenum)
- return arraylen;
- }
-
-
- /* most of the time, this loop is just to find where to put it
- * - 'loopbreaker' is just here to prevent infinite loops
- */
- for (loopbreaker = 0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) {
- /* compute and get midpoint */
- int mid = start + ((end - start) / 2); /* we calculate the midpoint this way to avoid int overflows... */
- float midfra = array[mid].time;
-
- /* check if exactly equal to midpoint */
- if (IS_EQT(frame, midfra, BINARYSEARCH_FRAMEEQ_THRESH)) {
- *exists = 1;
- return mid;
- }
-
- /* repeat in upper/lower half */
- if (frame > midfra)
- start = mid + 1;
- else if (frame < midfra)
- end = mid - 1;
- }
-
- /* print error if loop-limit exceeded */
- if (loopbreaker == (maxloop - 1)) {
- printf("Error: binarysearch_fcm_envelopedata_index() was taking too long\n");
-
- // include debug info
- printf("\tround = %d: start = %d, end = %d, arraylen = %d\n", loopbreaker, start, end, arraylen);
- }
-
- /* not found, so return where to place it */
- return start;
-}
-
/* callback to add new envelope data point */
-// TODO: should we have a separate file for things like this?
static void fmod_envelope_addpoint_cb(bContext *C, void *fcm_dv, void *UNUSED(arg))
{
Scene *scene = CTX_data_scene(C);
@@ -424,8 +343,8 @@ static void fmod_envelope_addpoint_cb(bContext *C, void *fcm_dv, void *UNUSED(ar
/* check that no data exists for the current frame... */
if (env->data) {
- short exists = -1;
- int i = binarysearch_fcm_envelopedata_index(env->data, (float)(scene->r.cfra), env->totvert, &exists);
+ bool exists;
+ int i = BKE_fcm_envelope_find_index(env->data, (float)(scene->r.cfra), env->totvert, &exists);
/* binarysearch_...() will set exists by default to 0, so if it is non-zero, that means that the point exists already */
if (exists)
@@ -665,9 +584,9 @@ void ANIM_uiTemplate_fmodifier_draw(uiLayout *layout, ID *id, ListBase *modifier
/* name */
if (fmi)
- uiItemL(sub, fmi->name, ICON_NONE);
+ uiItemL(sub, IFACE_(fmi->name), ICON_NONE);
else
- uiItemL(sub, "<Unknown Modifier>", ICON_NONE);
+ uiItemL(sub, IFACE_("<Unknown Modifier>"), ICON_NONE);
/* right-align ------------------------------------------- */
sub = uiLayoutRow(row, TRUE);
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index e520a95aa95..d9d2180e184 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -649,7 +649,7 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
ActKeyColumn *ak;
ActKeyBlock *ab;
float xscale;
-
+ float iconsize = U.widget_unit / 4.0f;
glEnable(GL_BLEND);
/* get View2D scaling factor */
@@ -665,7 +665,7 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
else
UI_ThemeColor4(TH_STRIP);
- glRectf(ab->start, ypos - 5, ab->end, ypos + 5);
+ glRectf(ab->start, ypos - iconsize, ab->end, ypos + iconsize);
}
}
}
@@ -686,7 +686,7 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
/* draw using OpenGL - uglier but faster */
/* NOTE1: a previous version of this didn't work nice for some intel cards
* NOTE2: if we wanted to go back to icons, these are icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3; */
- draw_keyframe_shape(ak->cfra, ypos, xscale, 5.0f, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, kalpha);
+ draw_keyframe_shape(ak->cfra, ypos, xscale, iconsize, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, kalpha);
}
}
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index 015c2667a93..decbc351cad 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -300,7 +300,14 @@ static short summary_keyframes_loop(KeyframeEditData *ked, bAnimContext *ac, Key
/* loop through each F-Curve, working on the keyframes until the first curve aborts */
for (ale = anim_data.first; ale; ale = ale->next) {
- ret_code = ANIM_fcurve_keyframes_loop(ked, ale->data, key_ok, key_cb, fcu_cb);
+ switch (ale->datatype) {
+ case ALE_MASKLAY:
+ case ALE_GPFRAME:
+ break;
+ default:
+ ret_code = ANIM_fcurve_keyframes_loop(ked, ale->data, key_ok, key_cb, fcu_cb);
+ break;
+ }
if (ret_code)
break;
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 8ba330e7c3c..bc20311f773 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -52,6 +52,7 @@
#include "DNA_material_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
+#include "DNA_rigidbody_types.h"
#include "BKE_animsys.h"
#include "BKE_action.h"
@@ -142,7 +143,7 @@ bAction *verify_adt_action(ID *id, short add)
if ((adt->action == NULL) && (add)) {
char actname[sizeof(id->name) - 2];
BLI_snprintf(actname, sizeof(actname), "%sAction", id->name + 2);
- adt->action = add_empty_action(actname);
+ adt->action = add_empty_action(G.main, actname);
}
/* return the action */
@@ -236,7 +237,7 @@ int insert_bezt_fcurve(FCurve *fcu, BezTriple *bezt, short flag)
/* are there already keyframes? */
if (fcu->bezt) {
- short replace = -1;
+ bool replace;
i = binarysearch_bezt_index(fcu->bezt, bezt->vec[1][0], fcu->totvert, &replace);
/* replace an existing keyframe? */
@@ -540,8 +541,8 @@ static float setting_get_rna_value(PointerRNA *ptr, PropertyRNA *prop, int index
enum {
VISUALKEY_NONE = 0,
VISUALKEY_LOC,
- VISUALKEY_ROT
- /* VISUALKEY_SCA */ /* TODO - looks like support can be added now */
+ VISUALKEY_ROT,
+ VISUALKEY_SCA,
};
/* This helper function determines if visual-keyframing should be used when
@@ -550,17 +551,18 @@ enum {
* blocktypes, when using "standard" keying but 'Visual Keying' option in Auto-Keying
* settings is on.
*/
-static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
+static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
{
bConstraint *con = NULL;
short searchtype = VISUALKEY_NONE;
- short has_parent = FALSE;
+ bool has_rigidbody = false;
+ bool has_parent = false;
const char *identifier = NULL;
/* validate data */
if (ELEM3(NULL, ptr, ptr->data, prop))
return 0;
-
+
/* 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
* ptr->type is RNA_Object or RNA_PoseBone, which are the RNA wrapping-info for
@@ -569,10 +571,14 @@ static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
if (ptr->type == &RNA_Object) {
/* Object */
Object *ob = (Object *)ptr->data;
+ RigidBodyOb *rbo = ob->rigidbody_object;
con = ob->constraints.first;
identifier = RNA_property_identifier(prop);
has_parent = (ob->parent != NULL);
+
+ /* active rigidbody objects only, as only those are affected by sim */
+ has_rigidbody = ((rbo) && (rbo->type == RBO_TYPE_ACTIVE));
}
else if (ptr->type == &RNA_PoseBone) {
/* Pose Channel */
@@ -584,13 +590,13 @@ static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
}
/* check if any data to search using */
- if (ELEM(NULL, con, identifier) && (has_parent == FALSE))
- return 0;
-
+ if (ELEM(NULL, con, identifier) && (has_parent == false) && (has_rigidbody == false))
+ return false;
+
/* location or rotation identifiers only... */
if (identifier == NULL) {
printf("%s failed: NULL identifier\n", __func__);
- return 0;
+ return false;
}
else if (strstr(identifier, "location")) {
searchtype = VISUALKEY_LOC;
@@ -598,17 +604,20 @@ static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
else if (strstr(identifier, "rotation")) {
searchtype = VISUALKEY_ROT;
}
+ else if (strstr(identifier, "scale")) {
+ searchtype = VISUALKEY_SCA;
+ }
else {
printf("%s failed: identifier - '%s'\n", __func__, identifier);
- return 0;
+ return false;
}
/* only search if a searchtype and initial constraint are available */
if (searchtype) {
- /* parent is always matching */
- if (has_parent)
- return 1;
+ /* parent or rigidbody are always matching */
+ if (has_parent || has_rigidbody)
+ return true;
/* constraints */
for (; con; con = con->next) {
@@ -620,42 +629,48 @@ static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
switch (con->type) {
/* multi-transform constraints */
case CONSTRAINT_TYPE_CHILDOF:
- return 1;
+ return true;
case CONSTRAINT_TYPE_TRANSFORM:
case CONSTRAINT_TYPE_TRANSLIKE:
- return 1;
+ return true;
case CONSTRAINT_TYPE_FOLLOWPATH:
- return 1;
+ return true;
case CONSTRAINT_TYPE_KINEMATIC:
- return 1;
-
+ return true;
+
/* single-transform constraits */
case CONSTRAINT_TYPE_TRACKTO:
- if (searchtype == VISUALKEY_ROT) return 1;
+ if (searchtype == VISUALKEY_ROT) return true;
break;
case CONSTRAINT_TYPE_DAMPTRACK:
- if (searchtype == VISUALKEY_ROT) return 1;
+ if (searchtype == VISUALKEY_ROT) return true;
break;
case CONSTRAINT_TYPE_ROTLIMIT:
- if (searchtype == VISUALKEY_ROT) return 1;
+ if (searchtype == VISUALKEY_ROT) return true;
break;
case CONSTRAINT_TYPE_LOCLIMIT:
- if (searchtype == VISUALKEY_LOC) return 1;
+ if (searchtype == VISUALKEY_LOC) return true;
break;
- case CONSTRAINT_TYPE_ROTLIKE:
- if (searchtype == VISUALKEY_ROT) return 1;
+ case CONSTRAINT_TYPE_SIZELIMIT:
+ if (searchtype == VISUALKEY_SCA) return true;
break;
case CONSTRAINT_TYPE_DISTLIMIT:
- if (searchtype == VISUALKEY_LOC) return 1;
+ if (searchtype == VISUALKEY_LOC) return true;
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ if (searchtype == VISUALKEY_ROT) return true;
break;
case CONSTRAINT_TYPE_LOCLIKE:
- if (searchtype == VISUALKEY_LOC) return 1;
+ if (searchtype == VISUALKEY_LOC) return true;
+ break;
+ case CONSTRAINT_TYPE_SIZELIKE:
+ if (searchtype == VISUALKEY_SCA) return true;
break;
case CONSTRAINT_TYPE_LOCKTRACK:
- if (searchtype == VISUALKEY_ROT) return 1;
+ if (searchtype == VISUALKEY_ROT) return true;
break;
case CONSTRAINT_TYPE_MINMAX:
- if (searchtype == VISUALKEY_LOC) return 1;
+ if (searchtype == VISUALKEY_LOC) return true;
break;
default:
@@ -664,8 +679,8 @@ static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
}
}
- /* when some condition is met, this function returns, so here it can be 0 */
- return 0;
+ /* when some condition is met, this function returns, so that means we've got nothing */
+ return false;
}
/* This helper function extracts the value to use for visual-keyframing
@@ -675,50 +690,30 @@ static short visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
static float visualkey_get_value(PointerRNA *ptr, PropertyRNA *prop, int array_index)
{
const char *identifier = RNA_property_identifier(prop);
+ float tmat[4][4];
+ int rotmode;
/* handle for Objects or PoseChannels only
+ * - only Location, Rotation or Scale keyframes are supported curently
* - constraints can be on either Objects or PoseChannels, so we only check if the
- * ptr->type is RNA_Object or RNA_PoseBone, which are the RNA wrapping-info for
+ * ptr->type is RNA_Object or RNA_PoseBone, which are the RNA wrapping-info for
* those structs, allowing us to identify the owner of the data
- * - assume that array_index will be sane
+ * - assume that array_index will be sane
*/
if (ptr->type == &RNA_Object) {
Object *ob = (Object *)ptr->data;
- /* only Location or Rotation keyframes are supported now */
+ /* Loc code is specific... */
if (strstr(identifier, "location")) {
return ob->obmat[3][array_index];
}
- else if (strstr(identifier, "rotation_euler")) {
- float eul[3];
-
- mat4_to_eulO(eul, ob->rotmode, ob->obmat);
- return eul[array_index];
- }
- else if (strstr(identifier, "rotation_quaternion")) {
- float trimat[3][3], quat[4];
-
- copy_m3_m4(trimat, ob->obmat);
- mat3_to_quat_is_ok(quat, trimat);
-
- return quat[array_index];
- }
- else if (strstr(identifier, "rotation_axis_angle")) {
- float axis[3], angle;
-
- mat4_to_axis_angle(axis, &angle, ob->obmat);
-
- /* w = 0, x,y,z = 1,2,3 */
- if (array_index == 0)
- return angle;
- else
- return axis[array_index - 1];
- }
+
+ copy_m4_m4(tmat, ob->obmat);
+ rotmode = ob->rotmode;
}
else if (ptr->type == &RNA_PoseBone) {
Object *ob = (Object *)ptr->id.data; /* we assume that this is always set, and is an object */
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
- float tmat[4][4];
/* Although it is not strictly required for this particular space conversion,
* arg1 must not be null, as there is a null check for the other conversions to
@@ -726,42 +721,53 @@ static float visualkey_get_value(PointerRNA *ptr, PropertyRNA *prop, int array_i
* will be what owns the pose-channel that is getting this anyway.
*/
copy_m4_m4(tmat, pchan->pose_mat);
- constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
+ BKE_constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
+ rotmode = pchan->rotmode;
- /* Loc, Rot/Quat keyframes are supported... */
+ /* Loc code is specific... */
if (strstr(identifier, "location")) {
/* only use for non-connected bones */
- if ((pchan->bone->parent) && !(pchan->bone->flag & BONE_CONNECTED))
+ if ((pchan->bone->parent == NULL) || !(pchan->bone->flag & BONE_CONNECTED))
return tmat[3][array_index];
- else if (pchan->bone->parent == NULL)
- return tmat[3][array_index];
- }
- else if (strstr(identifier, "rotation_euler")) {
- float eul[3];
-
- mat4_to_eulO(eul, pchan->rotmode, tmat);
- return eul[array_index];
- }
- else if (strstr(identifier, "rotation_quaternion")) {
- float trimat[3][3], quat[4];
-
- copy_m3_m4(trimat, tmat);
- mat3_to_quat_is_ok(quat, trimat);
-
- return quat[array_index];
- }
- else if (strstr(identifier, "rotation_axis_angle")) {
- float axis[3], angle;
-
- mat4_to_axis_angle(axis, &angle, tmat);
-
- /* w = 0, x,y,z = 1,2,3 */
- if (array_index == 0)
- return angle;
- else
- return axis[array_index - 1];
}
}
+ else {
+ return setting_get_rna_value(ptr, prop, array_index);
+ }
+
+ /* Rot/Scale code are common! */
+ if (strstr(identifier, "rotation_euler")) {
+ float eul[3];
+
+ mat4_to_eulO(eul, rotmode, tmat);
+ return eul[array_index];
+ }
+ else if (strstr(identifier, "rotation_quaternion")) {
+ float mat3[3][3], quat[4];
+
+ copy_m3_m4(mat3, tmat);
+ mat3_to_quat_is_ok(quat, mat3);
+
+ return quat[array_index];
+ }
+ else if (strstr(identifier, "rotation_axis_angle")) {
+ float axis[3], angle;
+
+ mat4_to_axis_angle(axis, &angle, tmat);
+
+ /* w = 0, x,y,z = 1,2,3 */
+ if (array_index == 0)
+ return angle;
+ else
+ return axis[array_index - 1];
+ }
+ else if (strstr(identifier, "scale")) {
+ float scale[3];
+
+ mat4_to_size(scale, tmat);
+
+ return scale[array_index];
+ }
/* as the function hasn't returned yet, read value from system in the default way */
return setting_get_rna_value(ptr, prop, array_index);
@@ -1049,7 +1055,7 @@ short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
/* will only loop once unless the array index was -1 */
for (; array_index < array_index_max; array_index++) {
FCurve *fcu = verify_fcurve(act, group, &ptr, rna_path, array_index, 0);
- short found = -1;
+ bool found;
int i;
/* check if F-Curve exists and/or whether it can be edited */
@@ -1208,7 +1214,6 @@ static int modify_key_op_poll(bContext *C)
static int insert_key_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
KeyingSet *ks = NULL;
int type = RNA_enum_get(op->ptr, "type");
@@ -1254,9 +1259,6 @@ static int insert_key_exec(bContext *C, wmOperator *op)
else
BKE_report(op->reports, RPT_WARNING, "Keying set failed to insert any keyframes");
- /* send updates */
- DAG_ids_flush_update(bmain, 0);
-
return OPERATOR_FINISHED;
}
@@ -1295,7 +1297,7 @@ void ANIM_OT_keyframe_insert(wmOperatorType *ot)
* then calls the menu if necessary before
*/
-static int insert_key_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int insert_key_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Scene *scene = CTX_data_scene(C);
@@ -1305,7 +1307,7 @@ static int insert_key_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(e
uiLayout *layout;
/* call the menu, which will call this operator again, hence the canceled */
- pup = uiPupMenuBegin(C, op->type->name, ICON_NONE);
+ pup = uiPupMenuBegin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
layout = uiPupMenuLayout(pup);
uiItemsEnumO(layout, "ANIM_OT_keyframe_insert_menu", "type");
uiPupMenuEnd(C, pup);
@@ -1364,7 +1366,6 @@ void ANIM_OT_keyframe_insert_menu(wmOperatorType *ot)
static int delete_key_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
KeyingSet *ks = NULL;
int type = RNA_enum_get(op->ptr, "type");
@@ -1410,9 +1411,6 @@ static int delete_key_exec(bContext *C, wmOperator *op)
else
BKE_report(op->reports, RPT_WARNING, "Keying set failed to remove any keyframes");
- /* send updates */
- DAG_ids_flush_update(bmain, 0);
-
return OPERATOR_FINISHED;
}
@@ -1452,8 +1450,6 @@ void ANIM_OT_keyframe_delete(wmOperatorType *ot)
static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
-
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
/* just those in active action... */
@@ -1498,12 +1494,11 @@ static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op))
}
/* update... */
- ob->recalc |= OB_RECALC_OB;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB);
}
CTX_DATA_END;
/* send updates */
- DAG_ids_flush_update(bmain, 0);
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
return OPERATOR_FINISHED;
@@ -1529,7 +1524,6 @@ void ANIM_OT_keyframe_clear_v3d(wmOperatorType *ot)
static int delete_key_v3d_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
float cfra = (float)CFRA;
@@ -1556,12 +1550,11 @@ static int delete_key_v3d_exec(bContext *C, wmOperator *op)
/* report success (or failure) */
BKE_reportf(op->reports, RPT_INFO, "Object '%s' successfully had %d keyframes removed", id->name + 2, success);
- ob->recalc |= OB_RECALC_OB;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB);
}
CTX_DATA_END;
/* send updates */
- DAG_ids_flush_update(bmain, 0);
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
return OPERATOR_FINISHED;
@@ -1589,7 +1582,6 @@ void ANIM_OT_keyframe_delete_v3d(wmOperatorType *ot)
static int insert_key_button_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
PointerRNA ptr = {{NULL}};
PropertyRNA *prop = NULL;
@@ -1631,25 +1623,27 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
success += insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, 0);
}
else {
- if (G.debug & G_DEBUG)
- printf("Button Insert-Key: no path to property\n");
- BKE_report(op->reports, RPT_WARNING, "Failed to resolve path to property, try using a keying set instead");
+ BKE_report(op->reports, RPT_WARNING,
+ "Failed to resolve path to property, try manually specifying this using a Keying Set instead");
}
}
- else if (G.debug & G_DEBUG) {
- printf("ptr.data = %p, prop = %p,", (void *)ptr.data, (void *)prop);
- if (prop)
- printf("animatable = %d\n", RNA_property_animateable(&ptr, prop));
- else
- printf("animatable = NULL\n");
+ else {
+ if (prop && !RNA_property_animateable(&ptr, prop)) {
+ BKE_reportf(op->reports, RPT_WARNING,
+ "\"%s\" property cannot be animated",
+ RNA_property_identifier(prop));
+ }
+ else {
+ BKE_reportf(op->reports, RPT_WARNING,
+ "Button doesn't appear to have any property information attached (ptr.data = %p, prop = %p)",
+ (void *)ptr.data, (void *)prop);
+ }
}
if (success) {
/* send updates */
uiContextAnimUpdate(C);
- DAG_ids_flush_update(bmain, 0);
-
/* send notifiers that keyframes have been changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
}
@@ -1679,7 +1673,6 @@ void ANIM_OT_keyframe_insert_button(wmOperatorType *ot)
static int delete_key_button_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
PointerRNA ptr = {{NULL}};
PropertyRNA *prop = NULL;
@@ -1721,8 +1714,6 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
/* send updates */
uiContextAnimUpdate(C);
- DAG_ids_flush_update(bmain, 0);
-
/* send notifiers that keyframes have been changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
}
@@ -1753,7 +1744,6 @@ void ANIM_OT_keyframe_delete_button(wmOperatorType *ot)
static int clear_key_button_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
PointerRNA ptr = {{NULL}};
PropertyRNA *prop = NULL;
char *path;
@@ -1793,8 +1783,6 @@ static int clear_key_button_exec(bContext *C, wmOperator *op)
/* send updates */
uiContextAnimUpdate(C);
- DAG_ids_flush_update(bmain, 0);
-
/* send notifiers that keyframes have been changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
}
@@ -1857,7 +1845,7 @@ short fcurve_frame_has_keyframe(FCurve *fcu, float frame, short filter)
/* we either include all regardless of muting, or only non-muted */
if ((filter & ANIMFILTER_KEYS_MUTED) || (fcu->flag & FCURVE_MUTED) == 0) {
- short replace = -1;
+ bool replace;
int i = binarysearch_bezt_index(fcu->bezt, frame, fcu->totvert, &replace);
/* binarysearch_bezt_index will set replace to be 0 or 1
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index 28db7bf572d..ad09fcb5966 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -289,7 +289,6 @@ void ANIM_OT_keying_set_path_remove(wmOperatorType *ot)
static int add_keyingset_button_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
KeyingSet *ks = NULL;
PropertyRNA *prop = NULL;
@@ -360,7 +359,6 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op)
if (success) {
/* send updates */
- DAG_ids_flush_update(bmain, 0);
WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
/* show notification/report header, so that users notice that something changed */
@@ -392,7 +390,6 @@ void ANIM_OT_keyingset_button_add(wmOperatorType *ot)
static int remove_keyingset_button_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
KeyingSet *ks = NULL;
PropertyRNA *prop = NULL;
@@ -442,7 +439,6 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op)
if (success) {
/* send updates */
- DAG_ids_flush_update(bmain, 0);
WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL);
/* show warning */
@@ -472,7 +468,7 @@ void ANIM_OT_keyingset_button_remove(wmOperatorType *ot)
/* Change Active KeyingSet Operator ------------------------ */
/* This operator checks if a menu should be shown for choosing the KeyingSet to make the active one */
-static int keyingset_active_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int keyingset_active_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
uiPopupMenu *pup;
uiLayout *layout;
@@ -883,7 +879,7 @@ short ANIM_validate_keyingset(bContext *C, ListBase *dsources, KeyingSet *ks)
if (ksi == NULL)
return MODIFYKEY_MISSING_TYPEINFO;
/* TODO: check for missing callbacks! */
-
+
/* check if it can be used in the current context */
if (ksi->poll(ksi, C)) {
/* if a list of data sources are provided, run a special iterator over them,
@@ -1006,7 +1002,8 @@ int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSe
{
Object *ob = (Object *)ksp->id;
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; // XXX: only object transforms only?
+ // XXX: only object transforms?
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
break;
}
diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt
index 2bd9956ef5a..d9555108733 100644
--- a/source/blender/editors/armature/CMakeLists.txt
+++ b/source/blender/editors/armature/CMakeLists.txt
@@ -36,16 +36,25 @@ set(INC_SYS
)
set(SRC
+ armature_add.c
+ armature_edit.c
+ armature_naming.c
armature_ops.c
- editarmature.c
+ armature_relations.c
+ armature_select.c
+ armature_skinning.c
+ armature_utils.c
editarmature_generate.c
editarmature_retarget.c
editarmature_sketch.c
meshlaplacian.c
- poseSlide.c
- poseUtils.c
- poselib.c
- poseobject.c
+ pose_edit.c
+ pose_lib.c
+ pose_group.c
+ pose_select.c
+ pose_slide.c
+ pose_transform.c
+ pose_utils.c
reeb.c
BIF_generate.h
diff --git a/source/blender/editors/armature/SConscript b/source/blender/editors/armature/SConscript
index ba375f30093..1911d76a894 100644
--- a/source/blender/editors/armature/SConscript
+++ b/source/blender/editors/armature/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
new file mode 100644
index 00000000000..28fb74f0cdd
--- /dev/null
+++ b/source/blender/editors/armature/armature_add.c
@@ -0,0 +1,849 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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, 2002-2009 full recode.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Operators and API's for creating bones
+ */
+
+/** \file blender/editors/armature/armature_add.c
+ * \ingroup edarmature
+ */
+
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+
+#include "BKE_action.h"
+#include "BKE_constraint.h"
+#include "BKE_context.h"
+#include "BKE_idprop.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_armature.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "armature_intern.h"
+
+/* *************** Adding stuff in editmode *************** */
+
+/* default bone add, returns it selected, but without tail set */
+/* XXX should be used everywhere, now it mallocs bones still locally in functions */
+EditBone *ED_armature_edit_bone_add(bArmature *arm, const char *name)
+{
+ EditBone *bone = MEM_callocN(sizeof(EditBone), "eBone");
+
+ BLI_strncpy(bone->name, name, sizeof(bone->name));
+ unique_editbone_name(arm->edbo, bone->name, NULL);
+
+ BLI_addtail(arm->edbo, bone);
+
+ bone->flag |= BONE_TIPSEL;
+ bone->weight = 1.0f;
+ bone->dist = 0.25f;
+ bone->xwidth = 0.1f;
+ bone->zwidth = 0.1f;
+ bone->ease1 = 1.0f;
+ bone->ease2 = 1.0f;
+ bone->rad_head = 0.10f;
+ bone->rad_tail = 0.05f;
+ bone->segments = 1;
+ bone->layer = arm->layer;
+
+ return bone;
+}
+
+/* v3d and rv3d are allowed to be NULL */
+void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d)
+{
+ Object *obedit = scene->obedit; // XXX get from context
+ bArmature *arm = obedit->data;
+ float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
+ EditBone *bone;
+
+ /* Get inverse point for head and orientation for tail */
+ invert_m4_m4(obedit->imat, obedit->obmat);
+ mul_v3_m4v3(curs, obedit->imat, give_cursor(scene, v3d));
+
+ if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
+ copy_m3_m4(obmat, rv3d->viewmat);
+ else unit_m3(obmat);
+
+ copy_m3_m4(viewmat, obedit->obmat);
+ mul_m3_m3m3(totmat, obmat, viewmat);
+ invert_m3_m3(imat, totmat);
+
+ ED_armature_deselect_all(obedit, 0);
+
+ /* Create a bone */
+ bone = ED_armature_edit_bone_add(arm, "Bone");
+
+ arm->act_edbone = bone;
+
+ copy_v3_v3(bone->head, curs);
+
+ if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
+ add_v3_v3v3(bone->tail, bone->head, imat[1]); // bone with unit length 1
+ else
+ add_v3_v3v3(bone->tail, bone->head, imat[2]); // bone with unit length 1, pointing up Z
+}
+
+
+/* previously addvert_armature */
+/* the ctrl-click method */
+static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ View3D *v3d;
+ bArmature *arm;
+ EditBone *ebone, *newbone, *flipbone;
+ float mat[3][3], imat[3][3];
+ const float *curs;
+ int a, to_root = 0;
+ Object *obedit;
+ Scene *scene;
+
+ scene = CTX_data_scene(C);
+ v3d = CTX_wm_view3d(C);
+ obedit = CTX_data_edit_object(C);
+ arm = obedit->data;
+
+ /* find the active or selected bone */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (ebone->flag & BONE_TIPSEL || arm->act_edbone == ebone)
+ break;
+ }
+ }
+
+ if (ebone == NULL) {
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (ebone->flag & BONE_ROOTSEL || arm->act_edbone == ebone)
+ break;
+ }
+ }
+ if (ebone == NULL)
+ return OPERATOR_CANCELLED;
+
+ to_root = 1;
+ }
+
+ ED_armature_deselect_all(obedit, 0);
+
+ /* we re-use code for mirror editing... */
+ flipbone = NULL;
+ if (arm->flag & ARM_MIRROR_EDIT)
+ flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone);
+
+ for (a = 0; a < 2; a++) {
+ if (a == 1) {
+ if (flipbone == NULL)
+ break;
+ else {
+ SWAP(EditBone *, flipbone, ebone);
+ }
+ }
+
+ newbone = ED_armature_edit_bone_add(arm, ebone->name);
+ arm->act_edbone = newbone;
+
+ if (to_root) {
+ copy_v3_v3(newbone->head, ebone->head);
+ newbone->rad_head = ebone->rad_tail;
+ newbone->parent = ebone->parent;
+ }
+ else {
+ copy_v3_v3(newbone->head, ebone->tail);
+ newbone->rad_head = ebone->rad_tail;
+ newbone->parent = ebone;
+ newbone->flag |= BONE_CONNECTED;
+ }
+
+ curs = give_cursor(scene, v3d);
+ copy_v3_v3(newbone->tail, curs);
+ sub_v3_v3v3(newbone->tail, newbone->tail, obedit->obmat[3]);
+
+ if (a == 1)
+ newbone->tail[0] = -newbone->tail[0];
+
+ copy_m3_m4(mat, obedit->obmat);
+ invert_m3_m3(imat, mat);
+ mul_m3_v3(imat, newbone->tail);
+
+ newbone->length = len_v3v3(newbone->head, newbone->tail);
+ newbone->rad_tail = newbone->length * 0.05f;
+ newbone->dist = newbone->length * 0.25f;
+
+ }
+
+ ED_armature_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+static int armature_click_extrude_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ /* TODO most of this code is copied from set3dcursor_invoke,
+ * it would be better to reuse code in set3dcursor_invoke */
+
+ /* temporarily change 3d cursor position */
+ Scene *scene;
+ ARegion *ar;
+ View3D *v3d;
+ float *fp, tvec[3], oldcurs[3], mval_f[2];
+ int retv;
+
+ scene = CTX_data_scene(C);
+ ar = CTX_wm_region(C);
+ v3d = CTX_wm_view3d(C);
+
+ fp = give_cursor(scene, v3d);
+
+ copy_v3_v3(oldcurs, fp);
+
+ VECCOPY2D(mval_f, event->mval);
+ ED_view3d_win_to_3d(ar, fp, mval_f, tvec);
+ copy_v3_v3(fp, tvec);
+
+ /* extrude to the where new cursor is and store the operation result */
+ retv = armature_click_extrude_exec(C, op);
+
+ /* restore previous 3d cursor position */
+ copy_v3_v3(fp, oldcurs);
+
+ return retv;
+}
+
+void ARMATURE_OT_click_extrude(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Click-Extrude";
+ ot->idname = "ARMATURE_OT_click_extrude";
+ ot->description = "Create a new bone going from the last selected joint to the mouse position";
+
+ /* api callbacks */
+ ot->invoke = armature_click_extrude_invoke;
+ ot->exec = armature_click_extrude_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+}
+
+/* adds an EditBone between the nominated locations (should be in the right space) */
+EditBone *add_points_bone(Object *obedit, float head[3], float tail[3])
+{
+ EditBone *ebo;
+
+ ebo = ED_armature_edit_bone_add(obedit->data, "Bone");
+
+ copy_v3_v3(ebo->head, head);
+ copy_v3_v3(ebo->tail, tail);
+
+ return ebo;
+}
+
+
+static EditBone *get_named_editbone(ListBase *edbo, char *name)
+{
+ EditBone *eBone;
+
+ if (name) {
+ for (eBone = edbo->first; eBone; eBone = eBone->next) {
+ if (!strcmp(name, eBone->name))
+ return eBone;
+ }
+ }
+
+ return NULL;
+}
+
+/* Call this before doing any duplications
+ * */
+void preEditBoneDuplicate(ListBase *editbones)
+{
+ EditBone *eBone;
+
+ /* clear temp */
+ for (eBone = editbones->first; eBone; eBone = eBone->next) {
+ eBone->temp = NULL;
+ }
+}
+
+/*
+ * Note: When duplicating cross objects, editbones here is the list of bones
+ * from the SOURCE object but ob is the DESTINATION object
+ * */
+void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Object *src_ob, Object *dst_ob)
+{
+ /* If an edit bone has been duplicated, lets
+ * update it's constraints if the subtarget
+ * they point to has also been duplicated
+ */
+ EditBone *oldtarget, *newtarget;
+ bPoseChannel *pchan;
+ bConstraint *curcon;
+ ListBase *conlist;
+
+ if ((pchan = BKE_pose_channel_verify(dst_ob->pose, dupBone->name))) {
+ if ((conlist = &pchan->constraints)) {
+ for (curcon = conlist->first; curcon; curcon = curcon->next) {
+ /* does this constraint have a subtarget in
+ * this armature?
+ */
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(curcon);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(curcon, &targets);
+
+ for (ct = targets.first; ct; ct = ct->next) {
+ if ((ct->tar == src_ob) && (ct->subtarget[0])) {
+ ct->tar = dst_ob; /* update target */
+ oldtarget = get_named_editbone(editbones, ct->subtarget);
+ if (oldtarget) {
+ /* was the subtarget bone duplicated too? If
+ * so, update the constraint to point at the
+ * duplicate of the old subtarget.
+ */
+ if (oldtarget->temp) {
+ newtarget = (EditBone *) oldtarget->temp;
+ BLI_strncpy(ct->subtarget, newtarget->name, sizeof(ct->subtarget));
+ }
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(curcon, &targets, 0);
+ }
+ }
+ }
+ }
+}
+
+void updateDuplicateSubtarget(EditBone *dupBone, ListBase *editbones, Object *ob)
+{
+ updateDuplicateSubtargetObjects(dupBone, editbones, ob, ob);
+}
+
+
+EditBone *duplicateEditBoneObjects(EditBone *curBone, const char *name, ListBase *editbones,
+ Object *src_ob, Object *dst_ob)
+{
+ EditBone *eBone = MEM_mallocN(sizeof(EditBone), "addup_editbone");
+
+ /* Copy data from old bone to new bone */
+ memcpy(eBone, curBone, sizeof(EditBone));
+
+ curBone->temp = eBone;
+ eBone->temp = curBone;
+
+ if (name != NULL) {
+ BLI_strncpy(eBone->name, name, sizeof(eBone->name));
+ }
+
+ unique_editbone_name(editbones, eBone->name, NULL);
+ BLI_addtail(editbones, eBone);
+
+ /* copy the ID property */
+ if (curBone->prop)
+ eBone->prop = IDP_CopyProperty(curBone->prop);
+
+ /* Lets duplicate the list of constraints that the
+ * current bone has.
+ */
+ if (src_ob->pose) {
+ bPoseChannel *chanold, *channew;
+
+ chanold = BKE_pose_channel_verify(src_ob->pose, curBone->name);
+ if (chanold) {
+ /* WARNING: this creates a new posechannel, but there will not be an attached bone
+ * yet as the new bones created here are still 'EditBones' not 'Bones'.
+ */
+ channew = BKE_pose_channel_verify(dst_ob->pose, eBone->name);
+
+ if (channew) {
+ BKE_pose_channel_copy_data(channew, chanold);
+ }
+ }
+ }
+
+ return eBone;
+}
+
+EditBone *duplicateEditBone(EditBone *curBone, const char *name, ListBase *editbones, Object *ob)
+{
+ 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 */
+
+ Object *obedit = CTX_data_edit_object(C);
+ 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 */
+ 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;
+ }
+ }
+ }
+ }
+
+
+ /* 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;
+
+ }
+ }
+ }
+
+ /* 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
+ */
+ 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;
+ }
+
+ /* 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);
+ }
+
+ ED_armature_validate_active(arm);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void ARMATURE_OT_duplicate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Duplicate Selected Bone(s)";
+ ot->idname = "ARMATURE_OT_duplicate";
+ ot->description = "Make copies of the selected bones within the same armature";
+
+ /* api callbacks */
+ ot->exec = armature_duplicate_selected_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ------------------------------------------ */
+
+/* previously extrude_armature */
+/* context; editmode armature */
+/* if forked && mirror-edit: makes two bones with flipped names */
+static int armature_extrude_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit;
+ bArmature *arm;
+ EditBone *newbone, *ebone, *flipbone, *first = NULL;
+ int a, totbone = 0, do_extrude;
+ int forked = RNA_boolean_get(op->ptr, "forked");
+
+ obedit = CTX_data_edit_object(C);
+ arm = obedit->data;
+
+ /* since we allow root extrude too, we have to make sure selection is OK */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if (ebone->flag & BONE_ROOTSEL) {
+ if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+ if (ebone->parent->flag & BONE_TIPSEL)
+ ebone->flag &= ~BONE_ROOTSEL;
+ }
+ }
+ }
+ }
+
+ /* Duplicate the necessary bones */
+ for (ebone = arm->edbo->first; ((ebone) && (ebone != first)); ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ /* we extrude per definition the tip */
+ do_extrude = FALSE;
+ if (ebone->flag & (BONE_TIPSEL | BONE_SELECTED)) {
+ do_extrude = TRUE;
+ }
+ else if (ebone->flag & BONE_ROOTSEL) {
+ /* but, a bone with parent deselected we do the root... */
+ if (ebone->parent && (ebone->parent->flag & BONE_TIPSEL)) {
+ /* pass */
+ }
+ else {
+ do_extrude = 2;
+ }
+ }
+
+ if (do_extrude) {
+ /* we re-use code for mirror editing... */
+ flipbone = NULL;
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone);
+ if (flipbone) {
+ forked = 0; // we extrude 2 different bones
+ if (flipbone->flag & (BONE_TIPSEL | BONE_ROOTSEL | BONE_SELECTED))
+ /* don't want this bone to be selected... */
+ flipbone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ }
+ if ((flipbone == NULL) && (forked))
+ flipbone = ebone;
+ }
+
+ for (a = 0; a < 2; a++) {
+ if (a == 1) {
+ if (flipbone == NULL)
+ break;
+ else {
+ SWAP(EditBone *, flipbone, ebone);
+ }
+ }
+
+ totbone++;
+ newbone = MEM_callocN(sizeof(EditBone), "extrudebone");
+
+ if (do_extrude == TRUE) {
+ copy_v3_v3(newbone->head, ebone->tail);
+ copy_v3_v3(newbone->tail, newbone->head);
+ newbone->parent = ebone;
+
+ newbone->flag = ebone->flag & (BONE_TIPSEL | BONE_RELATIVE_PARENTING); // copies it, in case mirrored bone
+
+ if (newbone->parent) newbone->flag |= BONE_CONNECTED;
+ }
+ else {
+ copy_v3_v3(newbone->head, ebone->head);
+ copy_v3_v3(newbone->tail, ebone->head);
+ newbone->parent = ebone->parent;
+
+ newbone->flag = BONE_TIPSEL;
+
+ if (newbone->parent && (ebone->flag & BONE_CONNECTED)) {
+ newbone->flag |= BONE_CONNECTED;
+ }
+ }
+
+ newbone->weight = ebone->weight;
+ newbone->dist = ebone->dist;
+ newbone->xwidth = ebone->xwidth;
+ newbone->zwidth = ebone->zwidth;
+ newbone->ease1 = ebone->ease1;
+ newbone->ease2 = ebone->ease2;
+ newbone->rad_head = ebone->rad_tail; // don't copy entire bone...
+ newbone->rad_tail = ebone->rad_tail;
+ newbone->segments = 1;
+ newbone->layer = ebone->layer;
+
+ BLI_strncpy(newbone->name, ebone->name, sizeof(newbone->name));
+
+ if (flipbone && forked) { // only set if mirror edit
+ if (strlen(newbone->name) < 30) {
+ if (a == 0) strcat(newbone->name, "_L");
+ else strcat(newbone->name, "_R");
+ }
+ }
+ unique_editbone_name(arm->edbo, newbone->name, NULL);
+
+ /* Add the new bone to the list */
+ BLI_addtail(arm->edbo, newbone);
+ if (!first)
+ first = newbone;
+
+ /* restore ebone if we were flipping */
+ if (a == 1 && flipbone)
+ SWAP(EditBone *, flipbone, ebone);
+ }
+ }
+
+ /* Deselect the old bone */
+ ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ }
+ }
+ /* if only one bone, make this one active */
+ if (totbone == 1 && first) arm->act_edbone = first;
+
+ if (totbone == 0) return OPERATOR_CANCELLED;
+
+ /* Transform the endpoints */
+ ED_armature_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_extrude(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Extrude";
+ ot->idname = "ARMATURE_OT_extrude";
+ ot->description = "Create new bones from the selected joints";
+
+ /* api callbacks */
+ ot->exec = armature_extrude_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "forked", 0, "Forked", "");
+}
+
+/* ********************** Bone Add *************************************/
+
+/*op makes a new bone and returns it with its tip selected */
+
+static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
+{
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ Object *obedit = CTX_data_edit_object(C);
+ EditBone *bone;
+ float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
+ char name[MAXBONENAME];
+
+ RNA_string_get(op->ptr, "name", name);
+
+ copy_v3_v3(curs, give_cursor(CTX_data_scene(C), CTX_wm_view3d(C)));
+
+ /* Get inverse point for head and orientation for tail */
+ invert_m4_m4(obedit->imat, obedit->obmat);
+ mul_m4_v3(obedit->imat, curs);
+
+ if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
+ copy_m3_m4(obmat, rv3d->viewmat);
+ else unit_m3(obmat);
+
+ copy_m3_m4(viewmat, obedit->obmat);
+ mul_m3_m3m3(totmat, obmat, viewmat);
+ invert_m3_m3(imat, totmat);
+
+ ED_armature_deselect_all(obedit, 0);
+
+ /* Create a bone */
+ bone = ED_armature_edit_bone_add(obedit->data, name);
+
+ copy_v3_v3(bone->head, curs);
+
+ if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
+ add_v3_v3v3(bone->tail, bone->head, imat[1]); // bone with unit length 1
+ else
+ add_v3_v3v3(bone->tail, bone->head, imat[2]); // bone with unit length 1, pointing up Z
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_bone_primitive_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Bone";
+ ot->idname = "ARMATURE_OT_bone_primitive_add";
+ ot->description = "Add a new bone located at the 3D-Cursor";
+
+ /* api callbacks */
+ ot->exec = armature_bone_primitive_add_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_string(ot->srna, "name", "Bone", MAXBONENAME, "Name", "Name of the newly created bone");
+
+}
+
+/* ********************** Subdivide *******************************/
+
+/* Subdivide Operators:
+ * This group of operators all use the same 'exec' callback, but they are called
+ * through several different operators - a combined menu (which just calls the exec in the
+ * appropriate ways), and two separate ones.
+ */
+
+static int armature_subdivide_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm = obedit->data;
+ EditBone *newbone, *tbone;
+ int cuts, i;
+
+ /* there may not be a number_cuts property defined (for 'simple' subdivide) */
+ cuts = RNA_int_get(op->ptr, "number_cuts");
+
+ /* loop over all editable bones */
+ // XXX the old code did this in reverse order though!
+ CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
+ {
+ for (i = cuts + 1; i > 1; i--) {
+ /* compute cut ratio first */
+ float cutratio = 1.0f / (float)i;
+ float cutratioI = 1.0f - cutratio;
+
+ float val1[3];
+ float val2[3];
+ float val3[3];
+
+ newbone = MEM_mallocN(sizeof(EditBone), "ebone subdiv");
+ *newbone = *ebone;
+ BLI_addtail(arm->edbo, newbone);
+
+ /* calculate location of newbone->head */
+ copy_v3_v3(val1, ebone->head);
+ copy_v3_v3(val2, ebone->tail);
+ copy_v3_v3(val3, newbone->head);
+
+ val3[0] = val1[0] * cutratio + val2[0] * cutratioI;
+ val3[1] = val1[1] * cutratio + val2[1] * cutratioI;
+ val3[2] = val1[2] * cutratio + val2[2] * cutratioI;
+
+ copy_v3_v3(newbone->head, val3);
+ copy_v3_v3(newbone->tail, ebone->tail);
+ copy_v3_v3(ebone->tail, newbone->head);
+
+ newbone->rad_head = 0.5f * (ebone->rad_head + ebone->rad_tail);
+ ebone->rad_tail = newbone->rad_head;
+
+ newbone->flag |= BONE_CONNECTED;
+
+ unique_editbone_name(arm->edbo, newbone->name, NULL);
+
+ /* correct parent bones */
+ for (tbone = arm->edbo->first; tbone; tbone = tbone->next) {
+ if (tbone->parent == ebone)
+ tbone->parent = newbone;
+ }
+ newbone->parent = ebone;
+ }
+ }
+ CTX_DATA_END;
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_subdivide(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Subdivide Multi";
+ ot->idname = "ARMATURE_OT_subdivide";
+ ot->description = "Break selected bones into chains of smaller bones";
+
+ /* api callbacks */
+ ot->exec = armature_subdivide_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* Properties */
+ prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, INT_MAX, "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
new file mode 100644
index 00000000000..12602c10955
--- /dev/null
+++ b/source/blender/editors/armature/armature_edit.c
@@ -0,0 +1,1245 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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, 2002-2009 full recode.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Armature EditMode tools - transforms, chain based editing, and other settings
+ */
+
+/** \file blender/editors/armature/armature_edit.c
+ * \ingroup edarmature
+ */
+
+#include <assert.h>
+
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_constraint.h"
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_report.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_armature.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "armature_intern.h"
+
+/* ************************** Object Tools Exports ******************************* */
+/* NOTE: these functions are exported to the Object module to be called from the tools there */
+
+void ED_armature_apply_transform(Object *ob, float mat[4][4])
+{
+ EditBone *ebone;
+ bArmature *arm = ob->data;
+ float scale = mat4_to_scale(mat); /* store the scale of the matrix here to use on envelopes */
+ float mat3[3][3];
+
+ copy_m3_m4(mat3, mat);
+ normalize_m3(mat3);
+
+ /* Put the armature into editmode */
+ ED_armature_to_edit(ob);
+
+ /* Do the rotations */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ float delta[3], tmat[3][3];
+
+ /* find the current bone's roll matrix */
+ sub_v3_v3v3(delta, ebone->tail, ebone->head);
+ vec_roll_to_mat3(delta, ebone->roll, tmat);
+
+ /* transform the roll matrix */
+ mul_m3_m3m3(tmat, mat3, tmat);
+
+ /* transform the bone */
+ mul_m4_v3(mat, ebone->head);
+ mul_m4_v3(mat, ebone->tail);
+
+ /* apply the transfiormed roll back */
+ mat3_to_vec_roll(tmat, NULL, &ebone->roll);
+
+ ebone->rad_head *= scale;
+ ebone->rad_tail *= scale;
+ ebone->dist *= scale;
+
+ /* we could be smarter and scale by the matrix along the x & z axis */
+ ebone->xwidth *= scale;
+ ebone->zwidth *= scale;
+ }
+
+ /* Turn the list into an armature */
+ ED_armature_from_edit(ob);
+ ED_armature_edit_free(ob);
+}
+
+/* exported for use in editors/object/ */
+/* 0 == do center, 1 == center new, 2 == center cursor */
+void ED_armature_origin_set(Scene *scene, Object *ob, float cursor[3], int centermode, int around)
+{
+ Object *obedit = scene->obedit; // XXX get from context
+ EditBone *ebone;
+ bArmature *arm = ob->data;
+ float cent[3];
+
+ /* Put the armature into editmode */
+ if (ob != obedit) {
+ ED_armature_to_edit(ob);
+ obedit = NULL; /* we cant use this so behave as if there is no obedit */
+ }
+
+ /* Find the centerpoint */
+ if (centermode == 2) {
+ copy_v3_v3(cent, cursor);
+ invert_m4_m4(ob->imat, ob->obmat);
+ mul_m4_v3(ob->imat, cent);
+ }
+ else {
+ if (around == V3D_CENTROID) {
+ int total = 0;
+ zero_v3(cent);
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ total += 2;
+ add_v3_v3(cent, ebone->head);
+ add_v3_v3(cent, ebone->tail);
+ }
+ if (total) {
+ mul_v3_fl(cent, 1.0f / (float)total);
+ }
+ }
+ else {
+ float min[3], max[3];
+ INIT_MINMAX(min, max);
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ minmax_v3v3_v3(min, max, ebone->head);
+ minmax_v3v3_v3(min, max, ebone->tail);
+ }
+ mid_v3_v3v3(cent, min, max);
+ }
+ }
+
+ /* Do the adjustments */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ sub_v3_v3(ebone->head, cent);
+ sub_v3_v3(ebone->tail, cent);
+ }
+
+ /* Turn the list into an armature */
+ if (obedit == NULL) {
+ ED_armature_from_edit(ob);
+ ED_armature_edit_free(ob);
+ }
+
+ /* Adjust object location for new centerpoint */
+ if (centermode && obedit == NULL) {
+ mul_mat3_m4_v3(ob->obmat, cent); /* ommit translation part */
+ add_v3_v3(ob->loc, cent);
+ }
+}
+
+/* ********************************* Roll ******************************* */
+
+/* adjust bone roll to align Z axis with vector
+ * vec is in local space and is normalized
+ */
+float ED_rollBoneToVector(EditBone *bone, const float align_axis[3], const short axis_only)
+{
+ float mat[3][3], nor[3];
+
+ sub_v3_v3v3(nor, bone->tail, bone->head);
+ vec_roll_to_mat3(nor, 0.0f, mat);
+
+ /* check the bone isn't aligned with the axis */
+ if (!is_zero_v3(align_axis) && angle_v3v3(align_axis, mat[2]) > FLT_EPSILON) {
+ float vec[3], align_axis_proj[3], roll;
+
+ /* project the new_up_axis along the normal */
+ project_v3_v3v3(vec, align_axis, nor);
+ sub_v3_v3v3(align_axis_proj, align_axis, vec);
+
+ if (axis_only) {
+ if (angle_v3v3(align_axis_proj, mat[2]) > (float)(M_PI / 2.0)) {
+ negate_v3(align_axis_proj);
+ }
+ }
+
+ roll = angle_v3v3(align_axis_proj, mat[2]);
+
+ cross_v3_v3v3(vec, mat[2], align_axis_proj);
+
+ if (dot_v3v3(vec, nor) < 0) {
+ roll = -roll;
+ }
+
+ return roll;
+ }
+
+ return 0.0f;
+}
+
+
+typedef enum eCalcRollTypes {
+ CALC_ROLL_X = 0,
+ CALC_ROLL_Y = 1,
+ CALC_ROLL_Z = 2,
+
+ CALC_ROLL_ACTIVE = 5,
+ CALC_ROLL_VIEW = 6,
+ CALC_ROLL_CURSOR = 7
+} eCalcRollTypes;
+
+static EnumPropertyItem prop_calc_roll_types[] = {
+ {CALC_ROLL_X, "X", 0, "X Axis", ""},
+ {CALC_ROLL_Y, "Y", 0, "Y Axis", ""},
+ {CALC_ROLL_Z, "Z", 0, "Z Axis", ""},
+ {CALC_ROLL_ACTIVE, "ACTIVE", 0, "Active Bone", ""},
+ {CALC_ROLL_VIEW, "VIEW", 0, "View Axis", ""},
+ {CALC_ROLL_CURSOR, "CURSOR", 0, "Cursor", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+
+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");
+ const short axis_only = RNA_boolean_get(op->ptr, "axis_only");
+ const short axis_flip = RNA_boolean_get(op->ptr, "axis_flip");
+
+ float imat[3][3];
+
+ bArmature *arm = ob->data;
+ EditBone *ebone;
+
+ copy_m3_m4(imat, ob->obmat);
+ invert_m3(imat);
+
+ if (type == CALC_ROLL_CURSOR) { /* Cursor */
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C); /* can be NULL */
+ float cursor_local[3];
+ const float *cursor = give_cursor(scene, v3d);
+
+
+ copy_v3_v3(cursor_local, cursor);
+ mul_m3_v3(imat, cursor_local);
+
+ /* cursor */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
+ 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);
+ }
+ }
+ }
+ else {
+ float vec[3] = {0.0f, 0.0f, 0.0f};
+ if (type == CALC_ROLL_VIEW) { /* View */
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if (rv3d == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No region view3d available");
+ return OPERATOR_CANCELLED;
+ }
+
+ copy_v3_v3(vec, rv3d->viewinv[2]);
+ mul_m3_v3(imat, vec);
+ }
+ else if (type == CALC_ROLL_ACTIVE) {
+ float mat[3][3], nor[3];
+ ebone = (EditBone *)arm->act_edbone;
+ if (ebone == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active bone set");
+ return OPERATOR_CANCELLED;
+ }
+
+ sub_v3_v3v3(nor, ebone->tail, ebone->head);
+ vec_roll_to_mat3(nor, ebone->roll, mat);
+ copy_v3_v3(vec, mat[2]);
+ }
+ else { /* Axis */
+ assert(type >= 0 && type <= 5);
+ if (type < 3) vec[type] = 1.0f;
+ else vec[type - 2] = -1.0f;
+ mul_m3_v3(imat, vec);
+ }
+
+ if (axis_flip) negate_v3(vec);
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
+ /* roll func is a callback which assumes that all is well */
+ ebone->roll = ED_rollBoneToVector(ebone, vec, axis_only);
+ }
+ }
+ }
+
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if ((EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) == 0) {
+ EditBone *ebone_mirr = ED_armature_bone_get_mirrored(arm->edbo, ebone);
+ if (ebone_mirr && (EBONE_VISIBLE(arm, ebone_mirr) && EBONE_EDITABLE(ebone_mirr))) {
+ ebone->roll = -ebone_mirr->roll;
+ }
+ }
+ }
+ }
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_calculate_roll(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Recalculate Roll";
+ ot->idname = "ARMATURE_OT_calculate_roll";
+ ot->description = "Automatically fix alignment of select bones' axes";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = armature_calc_roll_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_calc_roll_types, 0, "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");
+}
+
+/* ******************************** Chain-Based Tools ********************************* */
+
+/* temporary data-structure for merge/fill bones */
+typedef struct EditBonePoint {
+ struct EditBonePoint *next, *prev;
+
+ EditBone *head_owner; /* EditBone which uses this point as a 'head' point */
+ EditBone *tail_owner; /* EditBone which uses this point as a 'tail' point */
+
+ float vec[3]; /* the actual location of the point in local/EditMode space */
+} EditBonePoint;
+
+/* find chain-tips (i.e. bones without children) */
+static void chains_find_tips(ListBase *edbo, ListBase *list)
+{
+ EditBone *curBone, *ebo;
+ LinkData *ld;
+
+ /* note: this is potentially very slow ... there's got to be a better way */
+ for (curBone = edbo->first; curBone; curBone = curBone->next) {
+ short stop = 0;
+
+ /* is this bone contained within any existing chain? (skip if so) */
+ for (ld = list->first; ld; ld = ld->next) {
+ for (ebo = ld->data; ebo; ebo = ebo->parent) {
+ if (ebo == curBone) {
+ stop = 1;
+ break;
+ }
+ }
+
+ if (stop) break;
+ }
+ /* skip current bone if it is part of an existing chain */
+ if (stop) continue;
+
+ /* is any existing chain part of the chain formed by this bone? */
+ stop = 0;
+ for (ebo = curBone->parent; ebo; ebo = ebo->parent) {
+ for (ld = list->first; ld; ld = ld->next) {
+ if (ld->data == ebo) {
+ ld->data = curBone;
+ stop = 1;
+ break;
+ }
+ }
+
+ if (stop) break;
+ }
+ /* current bone has already been added to a chain? */
+ if (stop) continue;
+
+ /* add current bone to a new chain */
+ ld = MEM_callocN(sizeof(LinkData), "BoneChain");
+ ld->data = curBone;
+ BLI_addtail(list, ld);
+ }
+}
+
+/* --------------------- */
+
+static void fill_add_joint(EditBone *ebo, short eb_tail, ListBase *points)
+{
+ EditBonePoint *ebp;
+ float vec[3];
+ short found = 0;
+
+ if (eb_tail) {
+ copy_v3_v3(vec, ebo->tail);
+ }
+ else {
+ copy_v3_v3(vec, ebo->head);
+ }
+
+ for (ebp = points->first; ebp; ebp = ebp->next) {
+ if (equals_v3v3(ebp->vec, vec)) {
+ if (eb_tail) {
+ if ((ebp->head_owner) && (ebp->head_owner->parent == ebo)) {
+ /* so this bone's tail owner is this bone */
+ ebp->tail_owner = ebo;
+ found = 1;
+ break;
+ }
+ }
+ else {
+ if ((ebp->tail_owner) && (ebo->parent == ebp->tail_owner)) {
+ /* so this bone's head owner is this bone */
+ ebp->head_owner = ebo;
+ found = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ /* allocate a new point if no existing point was related */
+ if (found == 0) {
+ ebp = MEM_callocN(sizeof(EditBonePoint), "EditBonePoint");
+
+ if (eb_tail) {
+ copy_v3_v3(ebp->vec, ebo->tail);
+ ebp->tail_owner = ebo;
+ }
+ else {
+ copy_v3_v3(ebp->vec, ebo->head);
+ ebp->head_owner = ebo;
+ }
+
+ BLI_addtail(points, ebp);
+ }
+}
+
+/* bone adding between selected joints */
+static int armature_fill_bones_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm = (obedit) ? obedit->data : NULL;
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ ListBase points = {NULL, NULL};
+ int count;
+
+ /* sanity checks */
+ if (ELEM(NULL, obedit, arm))
+ return OPERATOR_CANCELLED;
+
+ /* loop over all bones, and only consider if visible */
+ CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
+ {
+ if (!(ebone->flag & BONE_CONNECTED) && (ebone->flag & BONE_ROOTSEL))
+ fill_add_joint(ebone, 0, &points);
+ if (ebone->flag & BONE_TIPSEL)
+ fill_add_joint(ebone, 1, &points);
+ }
+ CTX_DATA_END;
+
+ /* the number of joints determines how we fill:
+ * 1) between joint and cursor (joint=head, cursor=tail)
+ * 2) between the two joints (order is dependent on active-bone/hierachy)
+ * 3+) error (a smarter method involving finding chains needs to be worked out
+ */
+ count = BLI_countlist(&points);
+
+ if (count == 0) {
+ BKE_report(op->reports, RPT_ERROR, "No joints selected");
+ return OPERATOR_CANCELLED;
+ }
+ else if (count == 1) {
+ EditBonePoint *ebp;
+ float curs[3];
+
+ /* Get Points - selected joint */
+ ebp = (EditBonePoint *)points.first;
+
+ /* Get points - cursor (tail) */
+ invert_m4_m4(obedit->imat, obedit->obmat);
+ mul_v3_m4v3(curs, obedit->imat, give_cursor(scene, v3d));
+
+ /* Create a bone */
+ /* newbone = */ add_points_bone(obedit, ebp->vec, curs);
+ }
+ else if (count == 2) {
+ EditBonePoint *ebp, *ebp2;
+ 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;
+
+ 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)) {
+ 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, give_cursor(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;
+ }
+ else if (ebp->head_owner) {
+ headtail = 1;
+ }
+ else if (ebp2->head_owner) {
+ headtail = 2;
+ }
+
+ /* assign head/tail combinations */
+ if (headtail == 2) {
+ copy_v3_v3(head, ebp->vec);
+ copy_v3_v3(tail, ebp2->vec);
+ }
+ else if (headtail == 1) {
+ copy_v3_v3(head, ebp2->vec);
+ copy_v3_v3(tail, ebp->vec);
+ }
+
+ /* add new bone and parent it to the appropriate end */
+ if (headtail) {
+ EditBone *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;
+ else
+ newbone->parent = ebp->head_owner;
+ }
+ else {
+ /* ebp2 tail or head - tail gets priority */
+ if (ebp2->tail_owner)
+ newbone->parent = ebp2->tail_owner;
+ else
+ newbone->parent = ebp2->head_owner;
+ }
+
+ newbone->flag |= BONE_CONNECTED;
+ }
+ }
+ else {
+ /* FIXME.. figure out a method for multiple bones */
+ BKE_reportf(op->reports, RPT_ERROR, "Too many points selected: %d", count);
+ BLI_freelistN(&points);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
+
+ /* free points */
+ BLI_freelistN(&points);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_fill(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Fill Between Joints";
+ ot->idname = "ARMATURE_OT_fill";
+ ot->description = "Add bone between selected joint(s) and/or 3D-Cursor";
+
+ /* callbacks */
+ ot->exec = armature_fill_bones_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* --------------------- */
+
+/* this function merges between two bones, removes them and those in-between,
+ * and adjusts the parent relationships for those in-between
+ */
+static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone *endchild, ListBase *chains)
+{
+ bArmature *arm = obedit->data;
+ EditBone *ebo, *ebone, *newbone;
+ LinkData *chain;
+ float head[3], tail[3];
+
+ /* check if same bone */
+ if (start == end) {
+ if (G.debug & G_DEBUG) {
+ printf("Error: same bone!\n");
+ printf("\tstart = %s, end = %s\n", start->name, end->name);
+ }
+ }
+
+ /* step 1: add a new bone
+ * - head = head/tail of start (default head)
+ * - tail = head/tail of end (default tail)
+ * - parent = parent of start
+ */
+ if ((start->flag & BONE_TIPSEL) && (start->flag & BONE_SELECTED) == 0) {
+ copy_v3_v3(head, start->tail);
+ }
+ else {
+ copy_v3_v3(head, start->head);
+ }
+ if ((end->flag & BONE_ROOTSEL) && (end->flag & BONE_SELECTED) == 0) {
+ copy_v3_v3(tail, end->head);
+ }
+ else {
+ copy_v3_v3(tail, end->tail);
+ }
+ newbone = add_points_bone(obedit, head, tail);
+ newbone->parent = start->parent;
+
+ /* TODO, copy more things to the new bone */
+ newbone->flag = start->flag & (BONE_HINGE | BONE_NO_DEFORM | BONE_NO_SCALE |
+ BONE_NO_CYCLICOFFSET | BONE_NO_LOCAL_LOCATION | BONE_DONE);
+
+ /* step 2a: reparent any side chains which may be parented to any bone in the chain of bones to merge
+ * - potentially several tips for side chains leading to some tree exist...
+ */
+ for (chain = chains->first; chain; chain = chain->next) {
+ /* traverse down chain until we hit the bottom or if we run into the tip of the chain of bones we're
+ * merging (need to stop in this case to avoid corrupting this chain too!)
+ */
+ for (ebone = chain->data; (ebone) && (ebone != end); ebone = ebone->parent) {
+ short found = 0;
+
+ /* check if this bone is parented to one in the merging chain
+ * ! WATCHIT: must only go check until end of checking chain
+ */
+ for (ebo = end; (ebo) && (ebo != start->parent); ebo = ebo->parent) {
+ /* side-chain found? --> remap parent to new bone, then we're done with this chain :) */
+ if (ebone->parent == ebo) {
+ ebone->parent = newbone;
+ found = 1;
+ break;
+ }
+ }
+
+ /* carry on to the next tip now */
+ if (found)
+ break;
+ }
+ }
+
+ /* step 2b: parent child of end to newbone (child from this chain) */
+ if (endchild)
+ endchild->parent = newbone;
+
+ /* step 3: delete all bones between and including start and end */
+ for (ebo = end; ebo; ebo = ebone) {
+ ebone = (ebo == start) ? (NULL) : (ebo->parent);
+ bone_free(arm, ebo);
+ }
+
+ newbone->flag |= (BONE_ROOTSEL | BONE_TIPSEL | BONE_SELECTED);
+ ED_armature_sync_selection(arm->edbo);
+}
+
+
+static int armature_merge_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm = (obedit) ? obedit->data : NULL;
+ short type = RNA_enum_get(op->ptr, "type");
+
+ /* sanity checks */
+ if (ELEM(NULL, obedit, arm))
+ return OPERATOR_CANCELLED;
+
+ /* for now, there's only really one type of merging that's performed... */
+ if (type == 1) {
+ /* go down chains, merging bones */
+ ListBase chains = {NULL, NULL};
+ LinkData *chain, *nchain;
+ EditBone *ebo;
+
+ armature_tag_select_mirrored(arm);
+
+ /* get chains (ends on chains) */
+ chains_find_tips(arm->edbo, &chains);
+ if (chains.first == NULL) return OPERATOR_CANCELLED;
+
+ /* each 'chain' is the last bone in the chain (with no children) */
+ for (chain = chains.first; chain; chain = nchain) {
+ EditBone *bstart = NULL, *bend = NULL;
+ EditBone *bchild = NULL, *child = NULL;
+
+ /* temporarily remove chain from list of chains */
+ nchain = chain->next;
+ BLI_remlink(&chains, chain);
+
+ /* only consider bones that are visible and selected */
+ for (ebo = chain->data; ebo; child = ebo, ebo = ebo->parent) {
+ /* check if visible + selected */
+ if (EBONE_VISIBLE(arm, ebo) &&
+ ((ebo->flag & BONE_CONNECTED) || (ebo->parent == NULL)) &&
+ (ebo->flag & BONE_SELECTED) )
+ {
+ /* set either end or start (end gets priority, unless it is already set) */
+ if (bend == NULL) {
+ bend = ebo;
+ bchild = child;
+ }
+ else
+ bstart = ebo;
+ }
+ else {
+ /* chain is broken... merge any continous segments then clear */
+ if (bstart && bend)
+ bones_merge(obedit, bstart, bend, bchild, &chains);
+
+ bstart = NULL;
+ bend = NULL;
+ bchild = NULL;
+ }
+ }
+
+ /* merge from bstart to bend if something not merged */
+ if (bstart && bend)
+ bones_merge(obedit, bstart, bend, bchild, &chains);
+
+ /* put back link */
+ BLI_insertlinkbefore(&chains, nchain, chain);
+ }
+
+ armature_tag_unselect(arm);
+
+ BLI_freelistN(&chains);
+ }
+
+ /* updates */
+ ED_armature_sync_selection(arm->edbo);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_merge(wmOperatorType *ot)
+{
+ static EnumPropertyItem merge_types[] = {
+ {1, "WITHIN_CHAIN", 0, "Within Chains", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Merge Bones";
+ ot->idname = "ARMATURE_OT_merge";
+ ot->description = "Merge continuous chains of selected bones";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = armature_merge_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", merge_types, 0, "Type", "");
+}
+
+/* --------------------- */
+
+/* Switch Direction operator:
+ * Currently, this does not use context loops, as context loops do not make it
+ * easy to retrieve any hierarchical/chain relationships which are necessary for
+ * this to be done easily.
+ */
+
+/* helper to clear BONE_TRANSFORM flags */
+static void armature_clear_swap_done_flags(bArmature *arm)
+{
+ EditBone *ebone;
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ ebone->flag &= ~BONE_TRANSFORM;
+ }
+}
+
+static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = CTX_data_edit_object(C);
+ bArmature *arm = (bArmature *)ob->data;
+ ListBase chains = {NULL, NULL};
+ LinkData *chain;
+
+ /* get chains of bones (ends on chains) */
+ chains_find_tips(arm->edbo, &chains);
+ if (chains.first == NULL) return OPERATOR_CANCELLED;
+
+ /* ensure that mirror bones will also be operated on */
+ armature_tag_select_mirrored(arm);
+
+ /* clear BONE_TRANSFORM flags
+ * - used to prevent duplicate/cancelling operations from occurring [#34123]
+ * - BONE_DONE cannot be used here as that's already used for mirroring
+ */
+ armature_clear_swap_done_flags(arm);
+
+ /* loop over chains, only considering selected and visible bones */
+ for (chain = chains.first; chain; chain = chain->next) {
+ EditBone *ebo, *child = NULL, *parent = NULL;
+
+ /* loop over bones in chain */
+ for (ebo = chain->data; ebo; ebo = parent) {
+ /* parent is this bone's original parent
+ * - we store this, as the next bone that is checked is this one
+ * but the value of ebo->parent may change here...
+ */
+ parent = ebo->parent;
+
+ /* skip bone if already handled... [#34123] */
+ if ((ebo->flag & BONE_TRANSFORM) == 0) {
+ /* 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]);
+
+ /* do parent swapping:
+ * - use 'child' as new parent
+ * - connected flag is only set if points are coincidental
+ */
+ ebo->parent = child;
+ if ((child) && equals_v3v3(ebo->head, child->tail))
+ ebo->flag |= BONE_CONNECTED;
+ else
+ ebo->flag &= ~BONE_CONNECTED;
+
+ /* get next bones
+ * - child will become the new parent of next bone
+ */
+ child = ebo;
+ }
+ else {
+ /* not swapping this bone, however, if its 'parent' got swapped, unparent us from it
+ * as it will be facing in opposite direction
+ */
+ if ((parent) && (EBONE_VISIBLE(arm, parent) && EBONE_EDITABLE(parent))) {
+ ebo->parent = NULL;
+ ebo->flag &= ~BONE_CONNECTED;
+ }
+
+ /* get next bones
+ * - child will become new parent of next bone (not swapping occurred,
+ * so set to NULL to prevent infinite-loop)
+ */
+ child = NULL;
+ }
+
+ /* tag as done (to prevent double-swaps) */
+ ebo->flag |= BONE_TRANSFORM;
+ }
+ }
+ }
+
+ /* free chains */
+ BLI_freelistN(&chains);
+
+ /* clear temp flags */
+ armature_clear_swap_done_flags(arm);
+ armature_tag_unselect(arm);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_switch_direction(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Switch Direction";
+ ot->idname = "ARMATURE_OT_switch_direction";
+ ot->description = "Change the direction that a chain of bones points in (head <-> tail swap)";
+
+ /* api callbacks */
+ ot->exec = armature_switch_direction_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ********************************* Align ******************************* */
+
+/* helper to fix a ebone position if its parent has moved due to alignment*/
+static void fix_connected_bone(EditBone *ebone)
+{
+ float diff[3];
+
+ if (!(ebone->parent) || !(ebone->flag & BONE_CONNECTED) || equals_v3v3(ebone->parent->tail, ebone->head))
+ return;
+
+ /* if the parent has moved we translate child's head and tail accordingly */
+ sub_v3_v3v3(diff, ebone->parent->tail, ebone->head);
+ add_v3_v3(ebone->head, diff);
+ add_v3_v3(ebone->tail, diff);
+}
+
+/* helper to recursively find chains of connected bones starting at ebone and fix their position */
+static void fix_editbone_connected_children(ListBase *edbo, EditBone *ebone)
+{
+ EditBone *selbone;
+
+ for (selbone = edbo->first; selbone; selbone = selbone->next) {
+ if ((selbone->parent) && (selbone->parent == ebone) && (selbone->flag & BONE_CONNECTED)) {
+ fix_connected_bone(selbone);
+ fix_editbone_connected_children(edbo, selbone);
+ }
+ }
+}
+
+static void bone_align_to_bone(ListBase *edbo, EditBone *selbone, EditBone *actbone)
+{
+ float selboneaxis[3], actboneaxis[3], length;
+
+ sub_v3_v3v3(actboneaxis, actbone->tail, actbone->head);
+ normalize_v3(actboneaxis);
+
+ sub_v3_v3v3(selboneaxis, selbone->tail, selbone->head);
+ length = len_v3(selboneaxis);
+
+ mul_v3_fl(actboneaxis, length);
+ add_v3_v3v3(selbone->tail, selbone->head, actboneaxis);
+ selbone->roll = actbone->roll;
+
+ /* if the bone being aligned has connected descendants they must be moved
+ * according to their parent new position, otherwise they would be left
+ * in an inconsistent state: connected but away from the parent*/
+ fix_editbone_connected_children(edbo, selbone);
+}
+
+static int armature_align_bones_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_edit_object(C);
+ bArmature *arm = (bArmature *)ob->data;
+ EditBone *actbone = CTX_data_active_bone(C);
+ EditBone *actmirb = NULL;
+
+ /* there must be an active bone */
+ if (actbone == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
+ return OPERATOR_CANCELLED;
+ }
+ else if (arm->flag & ARM_MIRROR_EDIT) {
+ /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
+ * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone
+ * (i.e. selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
+ * This is useful for arm-chains, for example parenting lower arm to upper arm
+ * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
+ * then just use actbone. Useful when doing upper arm to spine.
+ */
+ actmirb = ED_armature_bone_get_mirrored(arm->edbo, actbone);
+ if (actmirb == NULL)
+ actmirb = actbone;
+ }
+
+ /* if there is only 1 selected bone, we assume that that is the active bone,
+ * since a user will need to have clicked on a bone (thus selecting it) to make it active
+ */
+ if (CTX_DATA_COUNT(C, selected_editable_bones) <= 1) {
+ /* When only the active bone is selected, and it has a parent,
+ * align it to the parent, as that is the only possible outcome.
+ */
+ if (actbone->parent) {
+ bone_align_to_bone(arm->edbo, actbone, actbone->parent);
+
+ if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
+ bone_align_to_bone(arm->edbo, actmirb, actmirb->parent);
+ }
+ }
+ else {
+ /* Align 'selected' bones to the active one
+ * - the context iterator contains both selected bones and their mirrored copies,
+ * so we assume that unselected bones are mirrored copies of some selected bone
+ * - since the active one (and/or its mirror) will also be selected, we also need
+ * to check that we are not trying to operate on them, since such an operation
+ * would cause errors
+ */
+
+ /* align selected bones to the active one */
+ CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
+ {
+ if (ELEM(ebone, actbone, actmirb) == 0) {
+ if (ebone->flag & BONE_SELECTED)
+ bone_align_to_bone(arm->edbo, ebone, actbone);
+ else
+ bone_align_to_bone(arm->edbo, ebone, actmirb);
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_align(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Align Bones";
+ ot->idname = "ARMATURE_OT_align";
+ ot->description = "Align selected bones to the active bone (or to their parent)";
+
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = armature_align_bones_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ********************************* Delete ******************************* */
+
+/* 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
+ arm = obedit->data;
+
+ /* cancel if nothing selected */
+ if (CTX_DATA_COUNT(C, selected_bones) == 0)
+ return OPERATOR_CANCELLED;
+
+ 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 = editbone_name_exists(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_get_typeinfo(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 = editbone_name_exists(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);
+ }
+ }
+ }
+ }
+ }
+
+
+ for (curBone = arm->edbo->first; curBone; curBone = ebone_next) {
+ ebone_next = curBone->next;
+ if (arm->layer & curBone->layer) {
+ if (curBone->flag & BONE_SELECTED) {
+ if (curBone == arm->act_edbone) arm->act_edbone = NULL;
+ ED_armature_edit_bone_remove(arm, curBone);
+ }
+ }
+ }
+
+
+ ED_armature_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Delete Selected Bone(s)";
+ ot->idname = "ARMATURE_OT_delete";
+ ot->description = "Remove selected bones from the armature";
+
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = armature_delete_selected_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ********************************* Show/Hide ******************************* */
+
+static int armature_hide_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm = obedit->data;
+ EditBone *ebone;
+ const int invert = RNA_boolean_get(op->ptr, "unselected") ? BONE_SELECTED : 0;
+
+ /* cancel if nothing selected */
+ if (CTX_DATA_COUNT(C, selected_bones) == 0)
+ return OPERATOR_CANCELLED;
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_VISIBLE(arm, ebone)) {
+ if ((ebone->flag & BONE_SELECTED) != invert) {
+ ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ ebone->flag |= BONE_HIDDEN_A;
+ }
+ }
+ }
+ ED_armature_validate_active(arm);
+ ED_armature_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_hide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Hide Selected Bones";
+ ot->idname = "ARMATURE_OT_hide";
+ ot->description = "Tag selected bones to not be visible in Edit Mode";
+
+ /* api callbacks */
+ ot->exec = armature_hide_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
+}
+
+static int armature_reveal_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm = obedit->data;
+ EditBone *ebone;
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (arm->layer & ebone->layer) {
+ if (ebone->flag & BONE_HIDDEN_A) {
+ ebone->flag |= (BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ ebone->flag &= ~BONE_HIDDEN_A;
+ }
+ }
+ }
+ ED_armature_validate_active(arm);
+ ED_armature_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_reveal(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Reveal Bones";
+ ot->idname = "ARMATURE_OT_reveal";
+ ot->description = "Unhide all bones that have been tagged to be hidden in Edit Mode";
+
+ /* api callbacks */
+ ot->exec = armature_reveal_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+}
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index ddf66a6169b..bfebc68ea46 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -37,17 +37,19 @@ struct wmOperatorType;
struct bContext;
struct Scene;
struct Object;
+struct Base;
struct bAction;
struct bPoseChannel;
struct bArmature;
struct EditBone;
+struct Bone;
struct ListBase;
struct LinkData;
/* ******************************************************* */
-/* editarmature.c operators */
+/* Armature EditMode Operators */
void ARMATURE_OT_bone_primitive_add(struct wmOperatorType *ot);
void ARMATURE_OT_align(struct wmOperatorType *ot);
@@ -131,7 +133,7 @@ void POSE_OT_armature_layers(struct wmOperatorType *ot);
void POSE_OT_bone_layers(struct wmOperatorType *ot);
/* ******************************************************* */
-/* Etch-A-Ton */
+/* Etch-A-Ton (Skeleton Sketching) Operators */
void SKETCH_OT_gesture(struct wmOperatorType *ot);
void SKETCH_OT_delete(struct wmOperatorType *ot);
@@ -144,7 +146,7 @@ void SKETCH_OT_select(struct wmOperatorType *ot);
/* ******************************************************* */
/* Pose Tool Utilities (for PoseLib, Pose Sliding, etc.) */
-/* poseUtils.c */
+/* pose_utils.c */
/* Temporary data linking PoseChannels with the F-Curves they affect */
typedef struct tPChanFCurveLink {
@@ -178,7 +180,7 @@ LinkData *poseAnim_mapping_getNextFCurve(ListBase *fcuLinks, LinkData *prev, con
/* ******************************************************* */
/* PoseLib */
-/* poselib.c */
+/* pose_lib.c */
void POSELIB_OT_new(struct wmOperatorType *ot);
void POSELIB_OT_unlink(struct wmOperatorType *ot);
@@ -194,7 +196,7 @@ void POSELIB_OT_apply_pose(struct wmOperatorType *ot);
/* ******************************************************* */
/* Pose Sliding Tools */
-/* poseSlide.c */
+/* pose_slide.c */
void POSE_OT_push(struct wmOperatorType *ot);
void POSE_OT_relax(struct wmOperatorType *ot);
@@ -203,7 +205,11 @@ void POSE_OT_breakdown(struct wmOperatorType *ot);
void POSE_OT_propagate(struct wmOperatorType *ot);
/* ******************************************************* */
-/* editarmature.c */
+/* Various Armature Edit/Pose Editing API's */
+
+/* Ideally, many of these defines would not be needed as everything would be strictly self-contained
+ * within each file, but some tools still have a bit of overlap which makes things messy -- Feb 2013
+ */
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);
@@ -213,13 +219,29 @@ void preEditBoneDuplicate(struct ListBase *editbones);
struct EditBone *duplicateEditBone(struct EditBone *curBone, const char *name, struct ListBase *editbones, struct Object *ob);
void updateDuplicateSubtarget(struct EditBone *dupBone, struct ListBase *editbones, struct Object *ob);
-/* duplicate method (cross objects */
-
+/* duplicate method (cross objects) */
/* editbones is the target list */
struct EditBone *duplicateEditBoneObjects(struct EditBone *curBone, const char *name, struct ListBase *editbones, struct Object *src_ob, struct Object *dst_ob);
/* editbones is the source list */
void updateDuplicateSubtargetObjects(struct EditBone *dupBone, struct ListBase *editbones, struct Object *src_ob, struct Object *dst_ob);
+
+EditBone *editbone_name_exists(struct ListBase *edbo, const char *name);
+
+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(struct bArmature *arm);
+void armature_tag_unselect(struct bArmature *arm);
+
+void *get_nearest_bone(struct bContext *C, short findunsel, int x, int y);
+void *get_bone_from_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer, short hits, short findunsel);
+
+int bone_looper(struct Object *ob, struct Bone *bone, void *data,
+ int (*bone_func)(struct Object *, struct Bone *, void *));
+
+
#endif /* __ARMATURE_INTERN_H__ */
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
new file mode 100644
index 00000000000..561e196bf41
--- /dev/null
+++ b/source/blender/editors/armature/armature_naming.c
@@ -0,0 +1,372 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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, 2002-2009 full recode.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Operators and API's for renaming bones both in and out of Edit Mode
+ */
+
+/** \file blender/editors/armature/armature_naming.c
+ * \ingroup edarmature
+ */
+
+#include <string.h>
+
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+
+#include "BKE_animsys.h"
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_constraint.h"
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_modifier.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_armature.h"
+#include "ED_screen.h"
+
+#include "armature_intern.h"
+
+/* This file contains functions/API's for renaming bones and/or working with them */
+
+/* ************************************************** */
+/* EditBone Names */
+
+/* checks if an EditBone with a matching name already, returning the matching bone if it exists */
+EditBone *editbone_name_exists(ListBase *edbo, const char *name)
+{
+ return BLI_findstring(edbo, name, offsetof(EditBone, name));
+}
+
+/* note: there's a unique_bone_name() too! */
+static bool editbone_unique_check(void *arg, const char *name)
+{
+ struct {ListBase *lb; void *bone; } *data = arg;
+ EditBone *dupli = editbone_name_exists(data->lb, name);
+ return dupli && dupli != data->bone;
+}
+
+void unique_editbone_name(ListBase *edbo, char *name, EditBone *bone)
+{
+ struct {ListBase *lb; void *bone; } data;
+ data.lb = edbo;
+ data.bone = bone;
+
+ BLI_uniquename_cb(editbone_unique_check, &data, "Bone", '.', name, sizeof(bone->name));
+}
+
+/* ************************************************** */
+/* Bone Renaming - API */
+
+static bool bone_unique_check(void *arg, const char *name)
+{
+ return BKE_armature_find_bone_name((bArmature *)arg, name) != NULL;
+}
+
+static void unique_bone_name(bArmature *arm, char *name)
+{
+ BLI_uniquename_cb(bone_unique_check, (void *)arm, "Bone", '.', name, sizeof(((Bone *)NULL)->name));
+}
+
+/* helper call for armature_bone_rename */
+static void constraint_bone_name_fix(Object *ob, ListBase *conlist, char *oldname, char *newname)
+{
+ bConstraint *curcon;
+ bConstraintTarget *ct;
+
+ for (curcon = conlist->first; curcon; curcon = curcon->next) {
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(curcon);
+ ListBase targets = {NULL, NULL};
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(curcon, &targets);
+
+ for (ct = targets.first; ct; ct = ct->next) {
+ if (ct->tar == ob) {
+ if (!strcmp(ct->subtarget, oldname) )
+ BLI_strncpy(ct->subtarget, newname, MAXBONENAME);
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(curcon, &targets, 0);
+ }
+ }
+}
+
+/* called by UI for renaming a bone */
+/* warning: make sure the original bone was not renamed yet! */
+/* seems messy, but thats what you get with not using pointers but channel names :) */
+void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *newnamep)
+{
+ Object *ob;
+ char newname[MAXBONENAME];
+ char oldname[MAXBONENAME];
+
+ /* names better differ! */
+ if (strncmp(oldnamep, newnamep, MAXBONENAME)) {
+
+ /* we alter newname string... so make copy */
+ BLI_strncpy(newname, newnamep, MAXBONENAME);
+ /* we use oldname for search... so make copy */
+ BLI_strncpy(oldname, oldnamep, MAXBONENAME);
+
+ /* now check if we're in editmode, we need to find the unique name */
+ if (arm->edbo) {
+ EditBone *eBone = editbone_name_exists(arm->edbo, oldname);
+
+ if (eBone) {
+ unique_editbone_name(arm->edbo, newname, NULL);
+ BLI_strncpy(eBone->name, newname, MAXBONENAME);
+ }
+ else {
+ return;
+ }
+ }
+ else {
+ Bone *bone = BKE_armature_find_bone_name(arm, oldname);
+
+ if (bone) {
+ unique_bone_name(arm, newname);
+ BLI_strncpy(bone->name, newname, MAXBONENAME);
+ }
+ else {
+ return;
+ }
+ }
+
+ /* do entire dbase - objects */
+ for (ob = G.main->object.first; ob; ob = ob->id.next) {
+ ModifierData *md;
+
+ /* we have the object using the armature */
+ if (arm == ob->data) {
+ Object *cob;
+
+ /* Rename the pose channel, if it exists */
+ if (ob->pose) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, oldname);
+ if (pchan) {
+ BLI_strncpy(pchan->name, newname, MAXBONENAME);
+
+ if (ob->pose->chanhash) {
+ GHash *gh = ob->pose->chanhash;
+
+ /* remove the old hash entry, and replace with the new name */
+ BLI_ghash_remove(gh, oldname, NULL, NULL);
+ BLI_ghash_insert(gh, pchan->name, pchan);
+ }
+ }
+ }
+
+ /* Update any object constraints to use the new bone name */
+ for (cob = G.main->object.first; cob; cob = cob->id.next) {
+ if (cob->constraints.first)
+ constraint_bone_name_fix(ob, &cob->constraints, oldname, newname);
+ if (cob->pose) {
+ bPoseChannel *pchan;
+ for (pchan = cob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ constraint_bone_name_fix(ob, &pchan->constraints, oldname, newname);
+ }
+ }
+ }
+ }
+
+ /* See if an object is parented to this armature */
+ if (ob->parent && (ob->parent->data == arm)) {
+ if (ob->partype == PARBONE) {
+ /* bone name in object */
+ if (!strcmp(ob->parsubstr, oldname))
+ BLI_strncpy(ob->parsubstr, newname, MAXBONENAME);
+ }
+ }
+
+ if (modifiers_usesArmature(ob, arm)) {
+ bDeformGroup *dg = defgroup_find_name(ob, oldname);
+ if (dg) {
+ BLI_strncpy(dg->name, newname, MAXBONENAME);
+ }
+ }
+
+ /* fix modifiers that might be using this name */
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Hook) {
+ HookModifierData *hmd = (HookModifierData *)md;
+
+ /* uses armature, so may use the affected bone name */
+ if (hmd->object && (hmd->object->data == arm)) {
+ if (!strcmp(hmd->subtarget, oldname))
+ BLI_strncpy(hmd->subtarget, newname, MAXBONENAME);
+ }
+ }
+ }
+ }
+
+ /* 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]
+ */
+ {
+
+ BKE_all_animdata_fix_paths_rename(&arm->id, "pose.bones", oldname, newname);
+ }
+
+ /* correct view locking */
+ {
+ bScreen *screen;
+ for (screen = G.main->screen.first; screen; screen = screen->id.next) {
+ ScrArea *sa;
+ /* add regions */
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ if (v3d->ob_centre && v3d->ob_centre->data == arm) {
+ if (!strcmp(v3d->ob_centre_bone, oldname)) {
+ BLI_strncpy(v3d->ob_centre_bone, newname, MAXBONENAME);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/* ************************************************** */
+/* Bone Renaming - EditMode */
+
+static int armature_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = CTX_data_edit_object(C);
+ bArmature *arm;
+ char newname[MAXBONENAME];
+
+ /* paranoia checks */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+ arm = ob->data;
+
+ /* loop through selected bones, auto-naming them */
+ CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
+ {
+ flip_side_name(newname, ebone->name, TRUE); // 1 = do strip off number extensions
+ ED_armature_bone_rename(arm, ebone->name, newname);
+ }
+ CTX_DATA_END;
+
+ /* since we renamed stuff... */
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_flip_names(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Flip Names";
+ ot->idname = "ARMATURE_OT_flip_names";
+ ot->description = "Flips (and corrects) the axis suffixes of the names of selected bones";
+
+ /* api callbacks */
+ ot->exec = armature_flip_names_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
+static int armature_autoside_names_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_edit_object(C);
+ bArmature *arm;
+ char newname[MAXBONENAME];
+ short axis = RNA_enum_get(op->ptr, "type");
+
+ /* paranoia checks */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+ arm = ob->data;
+
+ /* loop through selected bones, auto-naming them */
+ CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
+ {
+ BLI_strncpy(newname, ebone->name, sizeof(newname));
+ if (bone_autoside_name(newname, 1, axis, ebone->head[axis], ebone->tail[axis]))
+ ED_armature_bone_rename(arm, ebone->name, newname);
+ }
+ CTX_DATA_END;
+
+ /* since we renamed stuff... */
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_autoside_names(wmOperatorType *ot)
+{
+ static EnumPropertyItem axis_items[] = {
+ {0, "XAXIS", 0, "X-Axis", "Left/Right"},
+ {1, "YAXIS", 0, "Y-Axis", "Front/Back"},
+ {2, "ZAXIS", 0, "Z-Axis", "Top/Bottom"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "AutoName by Axis";
+ ot->idname = "ARMATURE_OT_autoside_names";
+ ot->description = "Automatically renames the selected bones according to which side of the target axis they fall on";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = armature_autoside_names_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* settings */
+ ot->prop = RNA_def_enum(ot->srna, "type", axis_items, 0, "Axis", "Axis tag names with");
+}
+
diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c
index 7c5b75e56ae..f87d4bc4d47 100644
--- a/source/blender/editors/armature/armature_ops.c
+++ b/source/blender/editors/armature/armature_ops.c
@@ -28,15 +28,7 @@
* \ingroup edarmature
*/
-
-#include <stdlib.h>
-#include <math.h>
-
-#include "BLO_sys_types.h"
-
#include "BLI_math.h"
-#include "BLI_blenlib.h"
-
#include "RNA_access.h"
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
new file mode 100644
index 00000000000..3a4dc31c82d
--- /dev/null
+++ b/source/blender/editors/armature/armature_relations.c
@@ -0,0 +1,774 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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, 2002-2009 full recode.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Operators for relations between bones and for transferring bones between armature objects
+ */
+
+/** \file blender/editors/armature/armature_relations.c
+ * \ingroup edarmature
+ */
+
+#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_math.h"
+
+#include "BLF_translation.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_constraint.h"
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_armature.h"
+#include "ED_object.h"
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "armature_intern.h"
+
+/* *************************************** Join *************************************** */
+/* NOTE: no operator define here as this is exported to the Object-level operator */
+
+/* Helper function for armature joining - link fixing */
+static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone)
+{
+ Object *ob;
+ bPose *pose;
+ bPoseChannel *pchant;
+ bConstraint *con;
+
+ /* let's go through all objects in database */
+ for (ob = G.main->object.first; ob; ob = ob->id.next) {
+ /* do some object-type specific things */
+ if (ob->type == OB_ARMATURE) {
+ pose = ob->pose;
+ for (pchant = pose->chanbase.first; pchant; pchant = pchant->next) {
+ for (con = pchant->constraints.first; con; con = con->next) {
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ /* constraint targets */
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct = targets.first; ct; ct = ct->next) {
+ if (ct->tar == srcArm) {
+ if (ct->subtarget[0] == '\0') {
+ ct->tar = tarArm;
+ }
+ else if (strcmp(ct->subtarget, pchan->name) == 0) {
+ ct->tar = tarArm;
+ BLI_strncpy(ct->subtarget, curbone->name, sizeof(ct->subtarget));
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+
+ /* action constraint? */
+ if (con->type == CONSTRAINT_TYPE_ACTION) {
+ bActionConstraint *data = con->data; // XXX old animation system
+ bAction *act;
+ bActionChannel *achan;
+
+ if (data->act) {
+ act = data->act;
+
+ for (achan = act->chanbase.first; achan; achan = achan->next) {
+ if (strcmp(achan->name, pchan->name) == 0)
+ BLI_strncpy(achan->name, curbone->name, sizeof(achan->name));
+ }
+ }
+ }
+
+ }
+ }
+ }
+
+ /* fix object-level constraints */
+ if (ob != srcArm) {
+ for (con = ob->constraints.first; con; con = con->next) {
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ /* constraint targets */
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct = targets.first; ct; ct = ct->next) {
+ if (ct->tar == srcArm) {
+ if (ct->subtarget[0] == '\0') {
+ ct->tar = tarArm;
+ }
+ else if (strcmp(ct->subtarget, pchan->name) == 0) {
+ ct->tar = tarArm;
+ BLI_strncpy(ct->subtarget, curbone->name, sizeof(ct->subtarget));
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+ }
+ }
+
+ /* See if an object is parented to this armature */
+ if (ob->parent && (ob->parent == srcArm)) {
+ /* Is object parented to a bone of this src armature? */
+ if (ob->partype == PARBONE) {
+ /* bone name in object */
+ if (!strcmp(ob->parsubstr, pchan->name))
+ BLI_strncpy(ob->parsubstr, curbone->name, sizeof(ob->parsubstr));
+ }
+
+ /* make tar armature be new parent */
+ ob->parent = tarArm;
+ }
+ }
+}
+
+/* join armature exec is exported for use in object->join objects operator... */
+int join_armature_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ bArmature *arm = (ob) ? ob->data : NULL;
+ bPose *pose, *opose;
+ bPoseChannel *pchan, *pchann;
+ EditBone *curbone;
+ float mat[4][4], oimat[4][4];
+
+ /* Ensure we're not in editmode and that the active object is an armature*/
+ if (!ob || ob->type != OB_ARMATURE)
+ return OPERATOR_CANCELLED;
+ if (!arm || arm->edbo)
+ return OPERATOR_CANCELLED;
+
+ /* Get editbones of active armature to add editbones to */
+ ED_armature_to_edit(ob);
+
+ /* get pose of active object and move it out of posemode */
+ pose = ob->pose;
+ ob->mode &= ~OB_MODE_POSE;
+
+ CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
+ {
+ if ((base->object->type == OB_ARMATURE) && (base->object != ob)) {
+ bArmature *curarm = base->object->data;
+
+ /* Make a list of editbones in current armature */
+ ED_armature_to_edit(base->object);
+
+ /* Get Pose of current armature */
+ opose = base->object->pose;
+ base->object->mode &= ~OB_MODE_POSE;
+ //BASACT->flag &= ~OB_MODE_POSE;
+
+ /* Find the difference matrix */
+ invert_m4_m4(oimat, ob->obmat);
+ mult_m4_m4m4(mat, oimat, base->object->obmat);
+
+ /* Copy bones and posechannels from the object to the edit armature */
+ for (pchan = opose->chanbase.first; pchan; pchan = pchann) {
+ pchann = pchan->next;
+ curbone = editbone_name_exists(curarm->edbo, pchan->name);
+
+ /* Get new name */
+ unique_editbone_name(arm->edbo, curbone->name, NULL);
+
+ /* Transform the bone */
+ {
+ float premat[4][4];
+ float postmat[4][4];
+ float difmat[4][4];
+ float imat[4][4];
+ float temp[3][3];
+ float delta[3];
+
+ /* Get the premat */
+ sub_v3_v3v3(delta, curbone->tail, curbone->head);
+ vec_roll_to_mat3(delta, curbone->roll, temp);
+
+ unit_m4(premat); /* Mat4MulMat34 only sets 3x3 part */
+ mul_m4_m3m4(premat, temp, mat);
+
+ mul_m4_v3(mat, curbone->head);
+ mul_m4_v3(mat, curbone->tail);
+
+ /* Get the postmat */
+ sub_v3_v3v3(delta, curbone->tail, curbone->head);
+ vec_roll_to_mat3(delta, curbone->roll, temp);
+ copy_m4_m3(postmat, temp);
+
+ /* Find the roll */
+ invert_m4_m4(imat, premat);
+ mult_m4_m4m4(difmat, imat, postmat);
+
+ curbone->roll -= (float)atan2(difmat[2][0], difmat[2][2]);
+ }
+
+ /* Fix Constraints and Other Links to this Bone and Armature */
+ joined_armature_fix_links(ob, base->object, pchan, curbone);
+
+ /* Rename pchan */
+ BLI_strncpy(pchan->name, curbone->name, sizeof(pchan->name));
+
+ /* Jump Ship! */
+ BLI_remlink(curarm->edbo, curbone);
+ BLI_addtail(arm->edbo, curbone);
+
+ BLI_remlink(&opose->chanbase, pchan);
+ BLI_addtail(&pose->chanbase, pchan);
+ BKE_pose_channels_hash_free(opose);
+ BKE_pose_channels_hash_free(pose);
+ }
+
+ ED_base_object_free_and_unlink(bmain, scene, base);
+ }
+ }
+ CTX_DATA_END;
+
+ DAG_relations_tag_update(bmain); /* because we removed object(s) */
+
+ ED_armature_from_edit(ob);
+ ED_armature_edit_free(ob);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+/* *********************************** Separate *********************************************** */
+
+/* Helper function for armature separating - link fixing */
+static void separated_armature_fix_links(Object *origArm, Object *newArm)
+{
+ Object *ob;
+ bPoseChannel *pchan;
+ bConstraint *con;
+ ListBase *opchans, *npchans;
+
+ /* get reference to list of bones in original and new armatures */
+ opchans = &origArm->pose->chanbase;
+ npchans = &newArm->pose->chanbase;
+
+ /* let's go through all objects in database */
+ for (ob = G.main->object.first; ob; ob = ob->id.next) {
+ /* do some object-type specific things */
+ 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_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ /* constraint targets */
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct = targets.first; ct; ct = ct->next) {
+ /* any targets which point to original armature are redirected to the new one only if:
+ * - the target isn't origArm/newArm itself
+ * - the target is one that can be found in newArm/origArm
+ */
+ if (ct->subtarget[0] != 0) {
+ if (ct->tar == origArm) {
+ if (BLI_findstring(npchans, ct->subtarget, offsetof(bPoseChannel, name))) {
+ ct->tar = newArm;
+ }
+ }
+ else if (ct->tar == newArm) {
+ if (BLI_findstring(opchans, ct->subtarget, offsetof(bPoseChannel, name))) {
+ ct->tar = origArm;
+ }
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets) {
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+ }
+ }
+ }
+ }
+
+ /* fix object-level constraints */
+ if (ob != origArm) {
+ for (con = ob->constraints.first; con; con = con->next) {
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ /* constraint targets */
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct = targets.first; ct; ct = ct->next) {
+ /* any targets which point to original armature are redirected to the new one only if:
+ * - the target isn't origArm/newArm itself
+ * - the target is one that can be found in newArm/origArm
+ */
+ if (ct->subtarget[0] != '\0') {
+ if (ct->tar == origArm) {
+ if (BLI_findstring(npchans, ct->subtarget, offsetof(bPoseChannel, name))) {
+ ct->tar = newArm;
+ }
+ }
+ else if (ct->tar == newArm) {
+ if (BLI_findstring(opchans, ct->subtarget, offsetof(bPoseChannel, name))) {
+ ct->tar = origArm;
+ }
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets) {
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+ }
+ }
+ }
+
+ /* See if an object is parented to this armature */
+ if (ob->parent && (ob->parent == origArm)) {
+ /* Is object parented to a bone of this src armature? */
+ if ((ob->partype == PARBONE) && (ob->parsubstr[0] != '\0')) {
+ if (BLI_findstring(npchans, ob->parsubstr, offsetof(bPoseChannel, name))) {
+ ob->parent = newArm;
+ }
+ }
+ }
+ }
+}
+
+/* Helper function for armature separating - remove certain bones from the given armature
+ * sel: remove selected bones from the armature, otherwise the unselected bones are removed
+ * (ob is not in editmode)
+ */
+static void separate_armature_bones(Object *ob, short sel)
+{
+ bArmature *arm = (bArmature *)ob->data;
+ bPoseChannel *pchan, *pchann;
+ EditBone *curbone;
+
+ /* make local set of editbones to manipulate here */
+ ED_armature_to_edit(ob);
+
+ /* go through pose-channels, checking if a bone should be removed */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchann) {
+ pchann = pchan->next;
+ curbone = editbone_name_exists(arm->edbo, pchan->name);
+
+ /* check if bone needs to be removed */
+ if ( (sel && (curbone->flag & BONE_SELECTED)) ||
+ (!sel && !(curbone->flag & BONE_SELECTED)) )
+ {
+ EditBone *ebo;
+ bPoseChannel *pchn;
+
+ /* clear the bone->parent var of any bone that had this as its parent */
+ 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->flag &= ~BONE_CONNECTED;
+ }
+ }
+
+ /* clear the pchan->parent var of any pchan that had this as its parent */
+ for (pchn = ob->pose->chanbase.first; pchn; pchn = pchn->next) {
+ if (pchn->parent == pchan)
+ pchn->parent = NULL;
+ }
+
+ /* free any of the extra-data this pchan might have */
+ BKE_pose_channel_free(pchan);
+ BKE_pose_channels_hash_free(ob->pose);
+
+ /* get rid of unneeded bone */
+ bone_free(arm, curbone);
+ BLI_freelinkN(&ob->pose->chanbase, pchan);
+ }
+ }
+
+ /* exit editmode (recalculates pchans too) */
+ ED_armature_from_edit(ob);
+ ED_armature_edit_free(ob);
+}
+
+/* separate selected bones into their armature */
+static int separate_armature_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ Object *oldob, *newob;
+ Base *oldbase, *newbase;
+
+ /* sanity checks */
+ if (obedit == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* set wait cursor in case this takes a while */
+ WM_cursor_wait(1);
+
+ /* we are going to do this as follows (unlike every other instance of separate):
+ * 1. exit editmode +posemode for active armature/base. Take note of what this is.
+ * 2. duplicate base - BASACT is the new one now
+ * 3. for each of the two armatures, enter editmode -> remove appropriate bones -> exit editmode + recalc
+ * 4. fix constraint links
+ * 5. make original armature active and enter editmode
+ */
+
+ /* 1) only edit-base selected */
+ /* TODO: use context iterators for this? */
+ CTX_DATA_BEGIN(C, Base *, base, visible_bases)
+ {
+ if (base->object == obedit) base->flag |= 1;
+ else base->flag &= ~1;
+ }
+ CTX_DATA_END;
+
+ /* 1) store starting settings and exit editmode */
+ oldob = obedit;
+ oldbase = BASACT;
+ oldob->mode &= ~OB_MODE_POSE;
+ //oldbase->flag &= ~OB_POSEMODE;
+
+ ED_armature_from_edit(obedit);
+ ED_armature_edit_free(obedit);
+
+ /* 2) duplicate base */
+ newbase = ED_object_add_duplicate(bmain, scene, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
+ DAG_relations_tag_update(bmain);
+
+ newob = newbase->object;
+ newbase->flag &= ~SELECT;
+
+
+ /* 3) remove bones that shouldn't still be around on both armatures */
+ separate_armature_bones(oldob, 1);
+ separate_armature_bones(newob, 0);
+
+
+ /* 4) fix links before depsgraph flushes */ // err... or after?
+ separated_armature_fix_links(oldob, newob);
+
+ DAG_id_tag_update(&oldob->id, OB_RECALC_DATA); /* this is the original one */
+ DAG_id_tag_update(&newob->id, OB_RECALC_DATA); /* this is the separated one */
+
+
+ /* 5) restore original conditions */
+ obedit = oldob;
+
+ ED_armature_to_edit(obedit);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
+
+ /* recalc/redraw + cleanup */
+ WM_cursor_wait(0);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_separate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Separate Bones";
+ ot->idname = "ARMATURE_OT_separate";
+ 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;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ******************************************** Parenting ************************************************* */
+
+/* armature parenting options */
+#define ARM_PAR_CONNECT 1
+#define ARM_PAR_OFFSET 2
+
+
+/* check for null, before calling! */
+static void bone_connect_to_existing_parent(EditBone *bone)
+{
+ bone->flag |= BONE_CONNECTED;
+ copy_v3_v3(bone->head, bone->parent->tail);
+ bone->rad_head = bone->parent->rad_tail;
+}
+
+static void bone_connect_to_new_parent(ListBase *edbo, EditBone *selbone, EditBone *actbone, short mode)
+{
+ EditBone *ebone;
+ float offset[3];
+
+ if ((selbone->parent) && (selbone->flag & BONE_CONNECTED))
+ selbone->parent->flag &= ~(BONE_TIPSEL);
+
+ /* make actbone the parent of selbone */
+ selbone->parent = actbone;
+
+ /* in actbone tree we cannot have a loop */
+ for (ebone = actbone->parent; ebone; ebone = ebone->parent) {
+ if (ebone->parent == selbone) {
+ ebone->parent = NULL;
+ ebone->flag &= ~BONE_CONNECTED;
+ }
+ }
+
+ if (mode == ARM_PAR_CONNECT) {
+ /* Connected: Child bones will be moved to the parent tip */
+ selbone->flag |= BONE_CONNECTED;
+ sub_v3_v3v3(offset, actbone->tail, selbone->head);
+
+ copy_v3_v3(selbone->head, actbone->tail);
+ selbone->rad_head = actbone->rad_tail;
+
+ add_v3_v3(selbone->tail, offset);
+
+ /* offset for all its children */
+ for (ebone = edbo->first; ebone; ebone = ebone->next) {
+ EditBone *par;
+
+ for (par = ebone->parent; par; par = par->parent) {
+ if (par == selbone) {
+ add_v3_v3(ebone->head, offset);
+ add_v3_v3(ebone->tail, offset);
+ break;
+ }
+ }
+ }
+ }
+ else {
+ /* Offset: Child bones will retain their distance from the parent tip */
+ selbone->flag &= ~BONE_CONNECTED;
+ }
+}
+
+
+static EnumPropertyItem prop_editarm_make_parent_types[] = {
+ {ARM_PAR_CONNECT, "CONNECTED", 0, "Connected", ""},
+ {ARM_PAR_OFFSET, "OFFSET", 0, "Keep Offset", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static int armature_parent_set_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_edit_object(C);
+ bArmature *arm = (bArmature *)ob->data;
+ EditBone *actbone = CTX_data_active_bone(C);
+ EditBone *actmirb = NULL;
+ short val = RNA_enum_get(op->ptr, "type");
+
+ /* there must be an active bone */
+ if (actbone == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
+ return OPERATOR_CANCELLED;
+ }
+ else if (arm->flag & ARM_MIRROR_EDIT) {
+ /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
+ * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone
+ * (i.e. selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
+ * This is useful for arm-chains, for example parenting lower arm to upper arm
+ * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
+ * then just use actbone. Useful when doing upper arm to spine.
+ */
+ actmirb = ED_armature_bone_get_mirrored(arm->edbo, actbone);
+ if (actmirb == NULL)
+ actmirb = actbone;
+ }
+
+ /* if there is only 1 selected bone, we assume that that is the active bone,
+ * since a user will need to have clicked on a bone (thus selecting it) to make it active
+ */
+ if (CTX_DATA_COUNT(C, selected_editable_bones) <= 1) {
+ /* When only the active bone is selected, and it has a parent,
+ * connect it to the parent, as that is the only possible outcome.
+ */
+ if (actbone->parent) {
+ bone_connect_to_existing_parent(actbone);
+
+ if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
+ bone_connect_to_existing_parent(actmirb);
+ }
+ }
+ else {
+ /* Parent 'selected' bones to the active one
+ * - the context iterator contains both selected bones and their mirrored copies,
+ * so we assume that unselected bones are mirrored copies of some selected bone
+ * - since the active one (and/or its mirror) will also be selected, we also need
+ * to check that we are not trying to operate on them, since such an operation
+ * would cause errors
+ */
+
+ /* parent selected bones to the active one */
+ CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
+ {
+ if (ELEM(ebone, actbone, actmirb) == 0) {
+ if (ebone->flag & BONE_SELECTED)
+ bone_connect_to_new_parent(arm->edbo, ebone, actbone, val);
+ else
+ bone_connect_to_new_parent(arm->edbo, ebone, actmirb, val);
+ }
+ }
+ CTX_DATA_END;
+ }
+
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+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);
+ int allchildbones = 0;
+
+ CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
+ {
+ if (ebone != actbone) {
+ if (ebone->parent != actbone) allchildbones = 1;
+ }
+ }
+ CTX_DATA_END;
+
+ uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_CONNECT);
+
+ /* ob becomes parent, make the associated menus */
+ if (allchildbones)
+ uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_OFFSET);
+
+ uiPupMenuEnd(C, pup);
+
+ return OPERATOR_CANCELLED;
+}
+
+void ARMATURE_OT_parent_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Make Parent";
+ ot->idname = "ARMATURE_OT_parent_set";
+ ot->description = "Set the active bone as the parent of the selected bones";
+
+ /* api callbacks */
+ ot->invoke = armature_parent_set_invoke;
+ ot->exec = armature_parent_set_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", prop_editarm_make_parent_types, 0, "ParentType", "Type of parenting");
+}
+
+
+
+static EnumPropertyItem prop_editarm_clear_parent_types[] = {
+ {1, "CLEAR", 0, "Clear Parent", ""},
+ {2, "DISCONNECT", 0, "Disconnect Bone", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static void editbone_clear_parent(EditBone *ebone, int mode)
+{
+ if (ebone->parent) {
+ /* for nice selection */
+ ebone->parent->flag &= ~(BONE_TIPSEL);
+ }
+
+ if (mode == 1) ebone->parent = NULL;
+ ebone->flag &= ~BONE_CONNECTED;
+}
+
+static int armature_parent_clear_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_edit_object(C);
+ bArmature *arm = (bArmature *)ob->data;
+ int val = RNA_enum_get(op->ptr, "type");
+
+ CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
+ {
+ editbone_clear_parent(ebone, val);
+ }
+ CTX_DATA_END;
+
+ ED_armature_sync_selection(arm->edbo);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_parent_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Clear Parent";
+ ot->idname = "ARMATURE_OT_parent_clear";
+ ot->description = "Remove the parent-child relationship between selected bones and their parents";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = armature_parent_clear_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_editarm_clear_parent_types, 0, "ClearType", "What way to clear parenting");
+}
+
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
new file mode 100644
index 00000000000..bbdc0df41a7
--- /dev/null
+++ b/source/blender/editors/armature/armature_select.c
@@ -0,0 +1,946 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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, 2002-2009 full recode.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * API's and Operators for selecting armature bones in EditMode
+ */
+
+/** \file blender/editors/armature/armature_select.c
+ * \ingroup edarmature
+ */
+
+#include "DNA_armature_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_report.h"
+
+#include "BIF_gl.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_armature.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "armature_intern.h"
+
+/* **************** PoseMode & EditMode Selection Buffer Queries *************************** */
+
+/* only for opengl selection indices */
+Bone *get_indexed_bone(Object *ob, int index)
+{
+ bPoseChannel *pchan;
+ if (ob->pose == NULL) return NULL;
+ index >>= 16; // bone selection codes use left 2 bytes
+
+ pchan = BLI_findlink(&ob->pose->chanbase, index);
+ return pchan ? pchan->bone : NULL;
+}
+
+/* See if there are any selected bones in this buffer */
+/* only bones from base are checked on */
+void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short findunsel)
+{
+ Object *obedit = scene->obedit; // XXX get from context
+ Bone *bone;
+ EditBone *ebone;
+ void *firstunSel = NULL, *firstSel = NULL, *data;
+ unsigned int hitresult;
+ short i, takeNext = 0, sel;
+
+ for (i = 0; i < hits; i++) {
+ hitresult = buffer[3 + (i * 4)];
+
+ if (!(hitresult & BONESEL_NOSEL)) { // -1
+ if (hitresult & BONESEL_ANY) { // to avoid including objects in selection
+
+ hitresult &= ~(BONESEL_ANY);
+ /* Determine what the current bone is */
+ if (obedit == NULL || base->object != obedit) {
+ /* no singular posemode, so check for correct object */
+ if (base->selcol == (hitresult & 0xFFFF)) {
+ bone = get_indexed_bone(base->object, hitresult);
+
+ if (findunsel)
+ sel = (bone->flag & BONE_SELECTED);
+ else
+ sel = !(bone->flag & BONE_SELECTED);
+
+ data = bone;
+ }
+ else {
+ data = NULL;
+ sel = 0;
+ }
+ }
+ else {
+ bArmature *arm = obedit->data;
+
+ ebone = BLI_findlink(arm->edbo, hitresult);
+ if (findunsel)
+ sel = (ebone->flag & BONE_SELECTED);
+ else
+ sel = !(ebone->flag & BONE_SELECTED);
+
+ data = ebone;
+ }
+
+ if (data) {
+ if (sel) {
+ if (!firstSel) firstSel = data;
+ takeNext = 1;
+ }
+ else {
+ if (!firstunSel)
+ firstunSel = data;
+ if (takeNext)
+ return data;
+ }
+ }
+ }
+ }
+ }
+
+ if (firstunSel)
+ return firstunSel;
+ else
+ return firstSel;
+}
+
+/* used by posemode as well editmode */
+/* only checks scene->basact! */
+/* x and y are mouse coords (area space) */
+void *get_nearest_bone(bContext *C, short findunsel, int x, int y)
+{
+ ViewContext vc;
+ rcti rect;
+ unsigned int buffer[MAXPICKBUF];
+ short hits;
+
+ view3d_set_viewcontext(C, &vc);
+
+ // rect.xmin = ... mouseco!
+ rect.xmin = rect.xmax = x;
+ rect.ymin = rect.ymax = y;
+
+ glInitNames();
+ hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
+
+ if (hits > 0)
+ return get_bone_from_selectbuffer(vc.scene, vc.scene->basact, buffer, hits, findunsel);
+
+ return NULL;
+}
+
+/* **************** EditMode stuff ********************** */
+
+/* called in space.c */
+/* previously "selectconnected_armature" */
+static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ bArmature *arm;
+ EditBone *bone, *curBone, *next;
+ int extend = RNA_boolean_get(op->ptr, "extend");
+ Object *obedit = CTX_data_edit_object(C);
+ arm = obedit->data;
+
+ view3d_operator_needs_opengl(C);
+
+ if (extend)
+ bone = get_nearest_bone(C, 0, event->mval[0], event->mval[1]);
+ else
+ bone = get_nearest_bone(C, 1, event->mval[0], event->mval[1]);
+
+ if (!bone)
+ return OPERATOR_CANCELLED;
+
+ /* Select parents */
+ for (curBone = bone; curBone; curBone = next) {
+ if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
+ if (extend) {
+ curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else {
+ curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
+
+ if (curBone->flag & BONE_CONNECTED)
+ next = curBone->parent;
+ else
+ next = NULL;
+ }
+
+ /* Select children */
+ while (bone) {
+ for (curBone = arm->edbo->first; curBone; curBone = next) {
+ next = curBone->next;
+ if ((curBone->parent == bone) && (curBone->flag & BONE_UNSELECTABLE) == 0) {
+ if (curBone->flag & BONE_CONNECTED) {
+ if (extend)
+ curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ else
+ curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ bone = curBone;
+ break;
+ }
+ else {
+ bone = NULL;
+ break;
+ }
+ }
+ }
+ if (!curBone)
+ bone = NULL;
+ }
+
+ ED_armature_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+static int armature_select_linked_poll(bContext *C)
+{
+ return (ED_operator_view3d_active(C) && ED_operator_editarmature(C) );
+}
+
+void ARMATURE_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Connected";
+ ot->idname = "ARMATURE_OT_select_linked";
+ ot->description = "Select bones related to selected ones by parent/child relationships";
+
+ /* api callbacks */
+ ot->exec = NULL;
+ ot->invoke = armature_select_linked_invoke;
+ ot->poll = armature_select_linked_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first");
+}
+
+/* does bones and points */
+/* note that BONE ROOT only gets drawn for root bones (or without IK) */
+static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2],
+ ListBase *edbo, int findunsel, int *selmask)
+{
+ bArmature *arm = (bArmature *)vc->obedit->data;
+ EditBone *ebone_next_act = arm->act_edbone;
+
+ EditBone *ebone;
+ rcti rect;
+ unsigned int buffer[MAXPICKBUF];
+ unsigned int hitresult, besthitresult = BONESEL_NOSEL;
+ int i, mindep = 4;
+ 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 &&
+ EBONE_VISIBLE(arm, ebone_next_act) &&
+ ebone_next_act->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL))
+ {
+ ebone_next_act = ebone_next_act->next ? ebone_next_act->next : arm->edbo->first;
+ }
+ else {
+ ebone_next_act = NULL;
+ }
+
+ rect.xmin = mval[0] - 5;
+ rect.xmax = mval[0] + 5;
+ rect.ymin = mval[1] - 5;
+ rect.ymax = mval[1] + 5;
+
+ hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
+ if (hits == 0) {
+ rect.xmin = mval[0] - 12;
+ rect.xmax = mval[0] + 12;
+ rect.ymin = mval[1] - 12;
+ rect.ymax = mval[1] + 12;
+ hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
+ }
+ /* See if there are any selected bones in this group */
+ if (hits > 0) {
+
+ if (hits == 1) {
+ if (!(buffer[3] & BONESEL_NOSEL))
+ besthitresult = buffer[3];
+ }
+ else {
+ for (i = 0; i < hits; i++) {
+ hitresult = buffer[3 + (i * 4)];
+ if (!(hitresult & BONESEL_NOSEL)) {
+ int dep;
+
+ ebone = BLI_findlink(edbo, hitresult & ~BONESEL_ANY);
+
+ /* clicks on bone points get advantage */
+ if (hitresult & (BONESEL_ROOT | BONESEL_TIP)) {
+ /* but also the unselected one */
+ if (findunsel) {
+ if ( (hitresult & BONESEL_ROOT) && (ebone->flag & BONE_ROOTSEL) == 0)
+ dep = 1;
+ else if ( (hitresult & BONESEL_TIP) && (ebone->flag & BONE_TIPSEL) == 0)
+ dep = 1;
+ else
+ dep = 2;
+ }
+ else {
+ dep = 2;
+ }
+ }
+ else {
+ /* bone found */
+ if (findunsel) {
+ if ((ebone->flag & BONE_SELECTED) == 0)
+ dep = 2;
+ else
+ dep = 3;
+ }
+ else {
+ dep = 3;
+ }
+ }
+
+ if (ebone == ebone_next_act) {
+ dep -= 1;
+ }
+
+ if (dep < mindep) {
+ mindep = dep;
+ besthitresult = hitresult;
+ }
+ }
+ }
+ }
+
+ if (!(besthitresult & BONESEL_NOSEL)) {
+
+ ebone = BLI_findlink(edbo, besthitresult & ~BONESEL_ANY);
+
+ *selmask = 0;
+ if (besthitresult & BONESEL_ROOT)
+ *selmask |= BONE_ROOTSEL;
+ if (besthitresult & BONESEL_TIP)
+ *selmask |= BONE_TIPSEL;
+ if (besthitresult & BONESEL_BONE)
+ *selmask |= BONE_SELECTED;
+ return ebone;
+ }
+ }
+ *selmask = 0;
+ 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)
+{
+ 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;
+ }
+
+ /* 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;
+ }
+ }
+
+ ED_armature_sync_selection(arm->edbo);
+}
+
+void ED_armature_deselect_all_visible(Object *obedit)
+{
+ bArmature *arm = obedit->data;
+ EditBone *ebone;
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ /* first and foremost, bone must be visible and selected */
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
+
+ ED_armature_sync_selection(arm->edbo);
+}
+
+/* accounts for connected parents */
+static int ebone_select_flag(EditBone *ebone)
+{
+ if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+ return ((ebone->parent->flag & BONE_TIPSEL) ? BONE_ROOTSEL : 0) | (ebone->flag & (BONE_SELECTED | BONE_TIPSEL));
+ }
+ else {
+ return ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
+ }
+}
+
+/* context: editmode armature in view3d */
+bool mouse_armature(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm = obedit->data;
+ ViewContext vc;
+ EditBone *nearBone = NULL;
+ int selmask;
+
+ view3d_set_viewcontext(C, &vc);
+
+ BIF_sk_selectStroke(C, mval, extend);
+
+ nearBone = get_nearest_editbonepoint(&vc, mval, arm->edbo, 1, &selmask);
+ if (nearBone) {
+
+ if (!extend && !deselect && !toggle)
+ ED_armature_deselect_all(obedit, 0);
+
+ /* by definition the non-root connected bones have no root point drawn,
+ * so a root selection needs to be delivered to the parent tip */
+
+ if (selmask & BONE_SELECTED) {
+ if (nearBone->parent && (nearBone->flag & BONE_CONNECTED)) {
+ /* click in a chain */
+ if (extend) {
+ /* select this bone */
+ nearBone->flag |= BONE_TIPSEL;
+ nearBone->parent->flag |= BONE_TIPSEL;
+ }
+ else if (deselect) {
+ /* deselect this bone */
+ nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
+ /* only deselect parent tip if it is not selected */
+ if (!(nearBone->parent->flag & BONE_SELECTED))
+ nearBone->parent->flag &= ~BONE_TIPSEL;
+ }
+ else if (toggle) {
+ /* hold shift inverts this bone's selection */
+ if (nearBone->flag & BONE_SELECTED) {
+ /* deselect this bone */
+ nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
+ /* only deselect parent tip if it is not selected */
+ if (!(nearBone->parent->flag & BONE_SELECTED))
+ nearBone->parent->flag &= ~BONE_TIPSEL;
+ }
+ else {
+ /* select this bone */
+ nearBone->flag |= BONE_TIPSEL;
+ nearBone->parent->flag |= BONE_TIPSEL;
+ }
+ }
+ else {
+ /* select this bone */
+ nearBone->flag |= BONE_TIPSEL;
+ nearBone->parent->flag |= BONE_TIPSEL;
+ }
+ }
+ else {
+ if (extend) {
+ nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else if (deselect) {
+ nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else if (toggle) {
+ /* hold shift inverts this bone's selection */
+ if (nearBone->flag & BONE_SELECTED)
+ nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
+ else
+ nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else
+ nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
+ else {
+ if (extend)
+ nearBone->flag |= selmask;
+ else if (deselect)
+ nearBone->flag &= ~selmask;
+ else if (toggle && (nearBone->flag & selmask))
+ nearBone->flag &= ~selmask;
+ else
+ nearBone->flag |= selmask;
+ }
+
+ ED_armature_sync_selection(arm->edbo);
+
+ if (nearBone) {
+ /* then now check for active status */
+ if (ebone_select_flag(nearBone)) {
+ arm->act_edbone = nearBone;
+ }
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit);
+ return true;
+ }
+
+ return false;
+}
+
+
+/* **************** Selections ******************/
+
+static int armature_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ /* Set the flags */
+ CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
+ {
+ /* ignore bone if selection can't change */
+ if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
+ /* select bone */
+ ebone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
+ CTX_DATA_END;
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_select_inverse(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Inverse";
+ ot->idname = "ARMATURE_OT_select_inverse";
+ ot->description = "Flip the selection status of bones (selected -> unselected, unselected -> selected)";
+
+ /* api callbacks */
+ ot->exec = armature_select_inverse_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+}
+static int armature_de_select_all_exec(bContext *C, wmOperator *op)
+{
+ int action = RNA_enum_get(op->ptr, "action");
+
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+ /* Determine if there are any selected bones
+ * And therefore whether we are selecting or deselecting */
+ if (CTX_DATA_COUNT(C, selected_bones) > 0)
+ action = SEL_DESELECT;
+ }
+
+ /* Set the flags */
+ CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
+ {
+ /* ignore bone if selection can't change */
+ if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
+ switch (action) {
+ case SEL_SELECT:
+ ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ if (ebone->parent)
+ ebone->parent->flag |= (BONE_TIPSEL);
+ break;
+ case SEL_DESELECT:
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ break;
+ case SEL_INVERT:
+ if (ebone->flag & BONE_SELECTED) {
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else {
+ ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ if (ebone->parent)
+ ebone->parent->flag |= (BONE_TIPSEL);
+ }
+ break;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_select_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->idname = "ARMATURE_OT_select_all";
+ ot->description = "Toggle selection status of all bones";
+
+ /* api callbacks */
+ ot->exec = armature_de_select_all_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ WM_operator_properties_select_all(ot);
+}
+
+enum {
+ SIMEDBONE_LENGTH = 1,
+ SIMEDBONE_DIRECTION,
+ SIMEDBONE_PREFIX,
+ SIMEDBONE_SUFFIX,
+ SIMEDBONE_LAYER
+};
+
+static EnumPropertyItem prop_similar_types[] = {
+ {SIMEDBONE_LENGTH, "LENGTH", 0, "Length", ""},
+ {SIMEDBONE_DIRECTION, "DIRECTION", 0, "Direction (Y axis)", ""},
+ {SIMEDBONE_PREFIX, "PREFIX", 0, "Prefix", ""},
+ {SIMEDBONE_SUFFIX, "SUFFIX", 0, "Suffix", ""},
+ {SIMEDBONE_LAYER, "LAYER", 0, "Layer", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+/* could be used in more places */
+static void ED_armature_edit_bone_select(EditBone *ebone)
+{
+ BLI_assert((ebone->flag & BONE_UNSELECTABLE) == 0);
+ ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+
+ if ((ebone->flag & BONE_CONNECTED) && (ebone->parent != NULL)) {
+ ebone->parent->flag |= BONE_TIPSEL;
+ }
+}
+
+static void select_similar_length(bArmature *arm, EditBone *ebone_act, const float thresh)
+{
+ EditBone *ebone;
+
+ /* thresh is always relative to current length */
+ const float len_min = ebone_act->length / (1.0f + thresh);
+ const float len_max = ebone_act->length * (1.0f + thresh);
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ if ((ebone->length >= len_min) &&
+ (ebone->length <= len_max))
+ {
+ ED_armature_edit_bone_select(ebone);
+ }
+ }
+ }
+}
+
+static void select_similar_direction(bArmature *arm, EditBone *ebone_act, const float thresh)
+{
+ EditBone *ebone;
+ float dir_act[3];
+ sub_v3_v3v3(dir_act, ebone_act->head, ebone_act->tail);
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ float dir[3];
+ sub_v3_v3v3(dir, ebone->head, ebone->tail);
+
+ if (angle_v3v3(dir_act, dir) / (float)M_PI < thresh) {
+ ED_armature_edit_bone_select(ebone);
+ }
+ }
+ }
+}
+
+static void select_similar_layer(bArmature *arm, EditBone *ebone_act)
+{
+ EditBone *ebone;
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ if (ebone->layer & ebone_act->layer) {
+ ED_armature_edit_bone_select(ebone);
+ }
+ }
+ }
+}
+
+static void select_similar_prefix(bArmature *arm, EditBone *ebone_act)
+{
+ EditBone *ebone;
+
+ char body_tmp[MAX_VGROUP_NAME];
+ char prefix_act[MAX_VGROUP_NAME];
+
+ BKE_deform_split_prefix(ebone_act->name, prefix_act, body_tmp);
+
+ if (prefix_act[0] == '\0')
+ return;
+
+ /* Find matches */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ char prefix_other[MAX_VGROUP_NAME];
+ BKE_deform_split_prefix(ebone->name, prefix_other, body_tmp);
+ if (!strcmp(prefix_act, prefix_other)) {
+ ED_armature_edit_bone_select(ebone);
+ }
+ }
+ }
+}
+
+static void select_similar_suffix(bArmature *arm, EditBone *ebone_act)
+{
+ EditBone *ebone;
+
+ char body_tmp[MAX_VGROUP_NAME];
+ char suffix_act[MAX_VGROUP_NAME];
+
+ BKE_deform_split_suffix(ebone_act->name, body_tmp, suffix_act);
+
+ if (suffix_act[0] == '\0')
+ return;
+
+ /* Find matches */
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ char suffix_other[MAX_VGROUP_NAME];
+ BKE_deform_split_suffix(ebone->name, body_tmp, suffix_other);
+ if (!strcmp(suffix_act, suffix_other)) {
+ ED_armature_edit_bone_select(ebone);
+ }
+ }
+ }
+}
+
+static int armature_select_similar_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm = obedit->data;
+ EditBone *ebone_act = CTX_data_active_bone(C);
+
+ /* Get props */
+ int type = RNA_enum_get(op->ptr, "type");
+ float thresh = RNA_float_get(op->ptr, "threshold");
+
+ /* Check for active bone */
+ if (ebone_act == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (type) {
+ case SIMEDBONE_LENGTH:
+ select_similar_length(arm, ebone_act, thresh);
+ break;
+ case SIMEDBONE_DIRECTION:
+ select_similar_direction(arm, ebone_act, thresh);
+ break;
+ case SIMEDBONE_PREFIX:
+ select_similar_prefix(arm, ebone_act);
+ break;
+ case SIMEDBONE_SUFFIX:
+ select_similar_suffix(arm, ebone_act);
+ break;
+ case SIMEDBONE_LAYER:
+ select_similar_layer(arm, ebone_act);
+ break;
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_select_similar(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Similar";
+ ot->idname = "ARMATURE_OT_select_similar";
+
+ /* callback functions */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = armature_select_similar_exec;
+ ot->poll = ED_operator_editarmature;
+ ot->description = "Select similar bones by property types";
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, 0, "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;
+ int direction = RNA_enum_get(op->ptr, "direction");
+ int add_to_sel = RNA_boolean_get(op->ptr, "extend");
+
+ 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;
+ }
+
+ }
+ 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;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ ED_armature_sync_selection(arm->edbo);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_select_hierarchy(wmOperatorType *ot)
+{
+ static EnumPropertyItem direction_items[] = {
+ {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
+ {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Select Hierarchy";
+ ot->idname = "ARMATURE_OT_select_hierarchy";
+ ot->description = "Select immediate parent/children of selected bones";
+
+ /* api callbacks */
+ ot->exec = armature_select_hierarchy_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", direction_items,
+ BONE_SELECT_PARENT, "Direction", "");
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+}
+
diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c
new file mode 100644
index 00000000000..2e43c388fa8
--- /dev/null
+++ b/source/blender/editors/armature/armature_skinning.c
@@ -0,0 +1,441 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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, 2002-2009 full recode.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * API's for creating vertex groups from bones
+ * - Interfaces with heat weighting in meshlaplacian
+ */
+
+/** \file blender/editors/armature/armature_skinning.c
+ * \ingroup edarmature
+ */
+
+#include "DNA_mesh_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_deform.h"
+#include "BKE_report.h"
+#include "BKE_subsurf.h"
+#include "BKE_modifier.h"
+
+#include "ED_armature.h"
+#include "ED_mesh.h"
+
+
+#include "armature_intern.h"
+#include "meshlaplacian.h"
+
+#if 0
+#include "reeb.h"
+#endif
+
+/* ********************************** Bone Skinning *********************************************** */
+
+static int bone_skinnable_cb(Object *ob, Bone *bone, void *datap)
+{
+ /* Bones that are deforming
+ * are regarded to be "skinnable" and are eligible for
+ * auto-skinning.
+ *
+ * This function performs 2 functions:
+ *
+ * a) It returns 1 if the bone is skinnable.
+ * If we loop over all bones with this
+ * function, we can count the number of
+ * skinnable bones.
+ * b) If the pointer data is non null,
+ * it is treated like a handle to a
+ * bone pointer -- the bone pointer
+ * is set to point at this bone, and
+ * the pointer the handle points to
+ * is incremented to point to the
+ * next member of an array of pointers
+ * to bones. This way we can loop using
+ * this function to construct an array of
+ * pointers to bones that point to all
+ * skinnable bones.
+ */
+ Bone ***hbone;
+ int a, segments;
+ struct { Object *armob; void *list; int heat; } *data = datap;
+
+ if (!(ob->mode & OB_MODE_WEIGHT_PAINT) || !(bone->flag & BONE_HIDDEN_P)) {
+ if (!(bone->flag & BONE_NO_DEFORM)) {
+ if (data->heat && data->armob->pose && BKE_pose_channel_find_name(data->armob->pose, bone->name))
+ segments = bone->segments;
+ else
+ segments = 1;
+
+ if (data->list != NULL) {
+ hbone = (Bone ***) &data->list;
+
+ for (a = 0; a < segments; a++) {
+ **hbone = bone;
+ ++*hbone;
+ }
+ }
+ return segments;
+ }
+ }
+ return 0;
+}
+
+static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
+{
+ /* This group creates a vertex group to ob that has the
+ * same name as bone (provided the bone is skinnable).
+ * If such a vertex group aleady exist the routine exits.
+ */
+ if (!(bone->flag & BONE_NO_DEFORM)) {
+ if (!defgroup_find_name(ob, bone->name)) {
+ ED_vgroup_add_name(ob, bone->name);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
+{
+ /* Bones that are deforming
+ * are regarded to be "skinnable" and are eligible for
+ * auto-skinning.
+ *
+ * This function performs 2 functions:
+ *
+ * a) If the bone is skinnable, it creates
+ * a vertex group for ob that has
+ * the name of the skinnable bone
+ * (if one doesn't exist already).
+ * b) If the pointer data is non null,
+ * it is treated like a handle to a
+ * bDeformGroup pointer -- the
+ * bDeformGroup pointer is set to point
+ * to the deform group with the bone's
+ * name, and the pointer the handle
+ * points to is incremented to point to the
+ * next member of an array of pointers
+ * to bDeformGroups. This way we can loop using
+ * this function to construct an array of
+ * pointers to bDeformGroups, all with names
+ * of skinnable bones.
+ */
+ bDeformGroup ***hgroup, *defgroup = NULL;
+ int a, segments;
+ struct { Object *armob; void *list; int heat; } *data = datap;
+ int wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT);
+ bArmature *arm = data->armob->data;
+
+ if (!wpmode || !(bone->flag & BONE_HIDDEN_P)) {
+ if (!(bone->flag & BONE_NO_DEFORM)) {
+ if (data->heat && data->armob->pose && BKE_pose_channel_find_name(data->armob->pose, bone->name))
+ segments = bone->segments;
+ 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 (data->list != NULL) {
+ hgroup = (bDeformGroup ***) &data->list;
+
+ for (a = 0; a < segments; a++) {
+ **hgroup = defgroup;
+ ++*hgroup;
+ }
+ }
+ return segments;
+ }
+ }
+ return 0;
+}
+
+static void add_vgroups__mapFunc(void *userData, int index, const float co[3],
+ const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+{
+ /* DerivedMesh mapFunc for getting final coords in weight paint mode */
+
+ float (*verts)[3] = userData;
+ copy_v3_v3(verts[index], co);
+}
+
+static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], int numbones, Bone **bonelist,
+ bDeformGroup **dgrouplist, bDeformGroup **dgroupflip,
+ float (*root)[3], float (*tip)[3], int *selected, float scale)
+{
+ /* Create vertex group weights from envelopes */
+
+ Bone *bone;
+ bDeformGroup *dgroup;
+ float distance;
+ int i, iflip, j;
+
+ /* for each vertex in the mesh */
+ for (i = 0; i < mesh->totvert; i++) {
+ iflip = (dgroupflip) ? mesh_get_x_mirror_vert(ob, i) : 0;
+
+ /* for each skinnable bone */
+ for (j = 0; j < numbones; ++j) {
+ if (!selected[j])
+ continue;
+
+ bone = bonelist[j];
+ dgroup = dgrouplist[j];
+
+ /* store the distance-factor from the vertex to the bone */
+ distance = distfactor_to_bone(verts[i], root[j], tip[j],
+ bone->rad_head * scale, bone->rad_tail * scale, bone->dist * scale);
+
+ /* add the vert to the deform group if (weight != 0.0) */
+ if (distance != 0.0f)
+ ED_vgroup_vert_add(ob, dgroup, i, distance, WEIGHT_REPLACE);
+ else
+ ED_vgroup_vert_remove(ob, dgroup, i);
+
+ /* do same for mirror */
+ if (dgroupflip && dgroupflip[j] && iflip >= 0) {
+ if (distance != 0.0f)
+ ED_vgroup_vert_add(ob, dgroupflip[j], iflip, distance,
+ WEIGHT_REPLACE);
+ else
+ ED_vgroup_vert_remove(ob, dgroupflip[j], iflip);
+ }
+ }
+ }
+}
+
+static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob, Object *par, int heat, int mirror)
+{
+ /* This functions implements the automatic computation of vertex group
+ * weights, either through envelopes or using a heat equilibrium.
+ *
+ * This function can be called both when parenting a mesh to an armature,
+ * or in weightpaint + posemode. In the latter case selection is taken
+ * into account and vertex weights can be mirrored.
+ *
+ * The mesh vertex positions used are either the final deformed coords
+ * from the derivedmesh in weightpaint mode, the final subsurf coords
+ * when parenting, or simply the original mesh coords.
+ */
+
+ bArmature *arm = par->data;
+ Bone **bonelist, *bone;
+ bDeformGroup **dgrouplist, **dgroupflip;
+ bDeformGroup *dgroup;
+ bPoseChannel *pchan;
+ Mesh *mesh;
+ Mat4 *bbone = NULL;
+ float (*root)[3], (*tip)[3], (*verts)[3];
+ int *selected;
+ int numbones, vertsfilled = 0, i, j, segments = 0;
+ int wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT);
+ struct { Object *armob; void *list; int heat; } looper_data;
+
+ looper_data.armob = par;
+ looper_data.heat = heat;
+ looper_data.list = NULL;
+
+ /* count the number of skinnable bones */
+ numbones = bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
+
+ if (numbones == 0)
+ return;
+
+ if (ED_vgroup_data_create(ob->data) == FALSE)
+ return;
+
+ /* create an array of pointer to bones that are skinnable
+ * and fill it with all of the skinnable bones */
+ bonelist = MEM_callocN(numbones * sizeof(Bone *), "bonelist");
+ looper_data.list = bonelist;
+ bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
+
+ /* create an array of pointers to the deform groups that
+ * correspond to the skinnable bones (creating them
+ * as necessary. */
+ dgrouplist = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgrouplist");
+ dgroupflip = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgroupflip");
+
+ looper_data.list = dgrouplist;
+ bone_looper(ob, arm->bonebase.first, &looper_data, dgroup_skinnable_cb);
+
+ /* create an array of root and tip positions transformed into
+ * global coords */
+ root = MEM_callocN(numbones * sizeof(float) * 3, "root");
+ tip = MEM_callocN(numbones * sizeof(float) * 3, "tip");
+ selected = MEM_callocN(numbones * sizeof(int), "selected");
+
+ for (j = 0; j < numbones; ++j) {
+ bone = bonelist[j];
+ dgroup = dgrouplist[j];
+
+ /* handle bbone */
+ if (heat) {
+ if (segments == 0) {
+ segments = 1;
+ bbone = NULL;
+
+ if ((par->pose) && (pchan = BKE_pose_channel_find_name(par->pose, bone->name))) {
+ if (bone->segments > 1) {
+ segments = bone->segments;
+ bbone = b_bone_spline_setup(pchan, 1);
+ }
+ }
+ }
+
+ segments--;
+ }
+
+ /* compute root and tip */
+ if (bbone) {
+ mul_v3_m4v3(root[j], bone->arm_mat, bbone[segments].mat[3]);
+ if ((segments + 1) < bone->segments) {
+ mul_v3_m4v3(tip[j], bone->arm_mat, bbone[segments + 1].mat[3]);
+ }
+ else {
+ copy_v3_v3(tip[j], bone->arm_tail);
+ }
+ }
+ else {
+ copy_v3_v3(root[j], bone->arm_head);
+ copy_v3_v3(tip[j], bone->arm_tail);
+ }
+
+ mul_m4_v3(par->obmat, root[j]);
+ mul_m4_v3(par->obmat, tip[j]);
+
+ /* set selected */
+ if (wpmode) {
+ if ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))
+ selected[j] = 1;
+ }
+ else
+ selected[j] = 1;
+
+ /* find flipped group */
+ if (dgroup && mirror) {
+ char name[MAXBONENAME];
+
+ // 0 = don't strip off number extensions
+ flip_side_name(name, dgroup->name, FALSE);
+ dgroupflip[j] = defgroup_find_name(ob, name);
+ }
+ }
+
+ /* create verts */
+ mesh = (Mesh *)ob->data;
+ verts = MEM_callocN(mesh->totvert * sizeof(*verts), "closestboneverts");
+
+ if (wpmode) {
+ /* if in weight paint mode, use final verts from derivedmesh */
+ DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+
+ if (dm->foreachMappedVert) {
+ dm->foreachMappedVert(dm, add_vgroups__mapFunc, (void *)verts);
+ vertsfilled = 1;
+ }
+
+ dm->release(dm);
+ }
+ else if (modifiers_findByType(ob, eModifierType_Subsurf)) {
+ /* is subsurf on? Lets use the verts on the limit surface then.
+ * = same amount of vertices as mesh, but vertices moved to the
+ * subsurfed position, like for 'optimal'. */
+ subsurf_calculate_limit_positions(mesh, verts);
+ vertsfilled = 1;
+ }
+
+ /* transform verts to global space */
+ for (i = 0; i < mesh->totvert; i++) {
+ if (!vertsfilled)
+ copy_v3_v3(verts[i], mesh->mvert[i].co);
+ mul_m4_v3(ob->obmat, verts[i]);
+ }
+
+ /* compute the weights based on gathered vertices and bones */
+ if (heat) {
+ const char *error = NULL;
+ heat_bone_weighting(ob, mesh, verts, numbones, dgrouplist, dgroupflip,
+ root, tip, selected, &error);
+
+ if (error) {
+ BKE_report(reports, RPT_WARNING, error);
+ }
+ }
+ else {
+ envelope_bone_weighting(ob, mesh, verts, numbones, bonelist, dgrouplist,
+ dgroupflip, root, tip, selected, mat4_to_scale(par->obmat));
+ }
+
+ /* only generated in some cases but can call anyway */
+ mesh_octree_table(ob, NULL, NULL, 'e');
+
+ /* free the memory allocated */
+ MEM_freeN(bonelist);
+ MEM_freeN(dgrouplist);
+ MEM_freeN(dgroupflip);
+ MEM_freeN(root);
+ MEM_freeN(tip);
+ MEM_freeN(selected);
+ MEM_freeN(verts);
+}
+
+void create_vgroups_from_armature(ReportList *reports, Scene *scene, Object *ob, Object *par, int mode, int mirror)
+{
+ /* Lets try to create some vertex groups
+ * based on the bones of the parent armature.
+ */
+ bArmature *arm = par->data;
+
+ if (mode == ARM_GROUPS_NAME) {
+ const int defbase_tot = BLI_countlist(&ob->defbase);
+ int defbase_add;
+ /* Traverse the bone list, trying to create empty vertex
+ * groups corresponding to the bone.
+ */
+ defbase_add = bone_looper(ob, arm->bonebase.first, NULL, vgroup_add_unique_bone_cb);
+
+ if (defbase_add) {
+ /* its possible there are DWeight's outside the range of the current
+ * objects deform groups, in this case the new groups wont be empty [#33889] */
+ ED_vgroup_data_clamp_range(ob->data, defbase_tot);
+ }
+ }
+ else if (mode == ARM_GROUPS_ENVELOPE || mode == ARM_GROUPS_AUTO) {
+ /* Traverse the bone list, trying to create vertex groups
+ * that are populated with the vertices for which the
+ * bone is closest.
+ */
+ add_verts_to_dgroups(reports, scene, ob, par, (mode == ARM_GROUPS_AUTO), mirror);
+ }
+}
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
new file mode 100644
index 00000000000..4120be08b46
--- /dev/null
+++ b/source/blender/editors/armature/armature_utils.c
@@ -0,0 +1,680 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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, 2002-2009 full recode.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/armature/armature_utils.c
+ * \ingroup edarmature
+ */
+
+#include "DNA_armature_types.h"
+#include "DNA_object_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+
+#include "BKE_armature.h"
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_idprop.h"
+#include "BKE_main.h"
+
+#include "ED_armature.h"
+#include "ED_util.h"
+
+#include "armature_intern.h"
+
+/* *************************************************************** */
+/* Validation */
+
+/* Sync selection to parent for connected children */
+void ED_armature_sync_selection(ListBase *edbo)
+{
+ EditBone *ebo;
+
+ for (ebo = edbo->first; ebo; ebo = ebo->next) {
+ /* if bone is not selectable, we shouldn't alter this setting... */
+ if ((ebo->flag & BONE_UNSELECTABLE) == 0) {
+ if ((ebo->flag & BONE_CONNECTED) && (ebo->parent)) {
+ if (ebo->parent->flag & BONE_TIPSEL)
+ ebo->flag |= BONE_ROOTSEL;
+ else
+ ebo->flag &= ~BONE_ROOTSEL;
+ }
+
+ if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL))
+ ebo->flag |= BONE_SELECTED;
+ else
+ ebo->flag &= ~BONE_SELECTED;
+ }
+ }
+}
+
+void ED_armature_validate_active(struct bArmature *arm)
+{
+ EditBone *ebone = arm->act_edbone;
+
+ if (ebone) {
+ if (ebone->flag & BONE_HIDDEN_A)
+ arm->act_edbone = NULL;
+ }
+}
+
+/* *************************************************************** */
+/* Bone Operations */
+
+/* XXX bone_looper is only to be used when we want to access settings
+ * (i.e. editability/visibility/selected) that context doesn't offer */
+int bone_looper(Object *ob, Bone *bone, void *data,
+ int (*bone_func)(Object *, Bone *, void *))
+{
+ /* We want to apply the function bone_func to every bone
+ * in an armature -- feed bone_looper the first bone and
+ * a pointer to the bone_func and watch it go!. The int count
+ * can be useful for counting bones with a certain property
+ * (e.g. skinnable)
+ */
+ int count = 0;
+
+ if (bone) {
+ /* only do bone_func if the bone is non null */
+ count += bone_func(ob, bone, data);
+
+ /* try to execute bone_func for the first child */
+ count += bone_looper(ob, bone->childbase.first, data, bone_func);
+
+ /* try to execute bone_func for the next bone at this
+ * depth of the recursion.
+ */
+ count += bone_looper(ob, bone->next, data, bone_func);
+ }
+
+ return count;
+}
+
+/* *************************************************************** */
+/* Bone Removal */
+
+void bone_free(bArmature *arm, EditBone *bone)
+{
+ if (arm->act_edbone == bone)
+ arm->act_edbone = NULL;
+
+ if (bone->prop) {
+ IDP_FreeProperty(bone->prop);
+ MEM_freeN(bone->prop);
+ }
+
+ BLI_freelinkN(arm->edbo, bone);
+}
+
+void ED_armature_edit_bone_remove(bArmature *arm, EditBone *exBone)
+{
+ EditBone *curBone;
+
+ /* Find any bones that refer to this bone */
+ for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
+ if (curBone->parent == exBone) {
+ curBone->parent = exBone->parent;
+ curBone->flag &= ~BONE_CONNECTED;
+ }
+ }
+
+ bone_free(arm, exBone);
+}
+
+bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebone_child)
+{
+ for (ebone_child = ebone_child->parent; ebone_child; ebone_child = ebone_child->parent) {
+ if (ebone_child == ebone_parent)
+ return true;
+ }
+ return false;
+}
+
+/* *************************************************************** */
+/* Mirroring */
+
+/* context: editmode armature */
+EditBone *ED_armature_bone_get_mirrored(ListBase *edbo, EditBone *ebo)
+{
+ EditBone *eboflip = NULL;
+ char name[MAXBONENAME];
+
+ if (ebo == NULL)
+ return NULL;
+
+ flip_side_name(name, ebo->name, FALSE);
+
+ for (eboflip = edbo->first; eboflip; eboflip = eboflip->next) {
+ if (ebo != eboflip) {
+ if (!strcmp(name, eboflip->name))
+ break;
+ }
+ }
+
+ return eboflip;
+}
+
+/* ------------------------------------- */
+
+/* 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)
+{
+ /* 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) {
+ ebone_mirr = ED_armature_bone_get_mirrored(arm->edbo, curBone);
+ if (ebone_mirr)
+ ebone_mirr->flag |= BONE_SELECTED;
+ }
+ }
+ }
+ }
+
+}
+
+void armature_tag_select_mirrored(bArmature *arm)
+{
+ EditBone *curBone;
+
+ /* always untag */
+ for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
+ curBone->flag &= ~BONE_DONE;
+ }
+
+ /* Select mirrored bones */
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
+ if (arm->layer & curBone->layer) {
+ if (curBone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) {
+ EditBone *ebone_mirr = ED_armature_bone_get_mirrored(arm->edbo, curBone);
+ if (ebone_mirr && (ebone_mirr->flag & BONE_SELECTED) == 0) {
+ ebone_mirr->flag |= BONE_DONE;
+ }
+ }
+ }
+ }
+
+ for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
+ if (curBone->flag & BONE_DONE) {
+ EditBone *ebone_mirr = ED_armature_bone_get_mirrored(arm->edbo, curBone);
+ curBone->flag |= ebone_mirr->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
+ }
+ }
+ }
+}
+
+/* only works when tagged */
+void armature_tag_unselect(bArmature *arm)
+{
+ EditBone *curBone;
+
+ for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
+ if (curBone->flag & BONE_DONE) {
+ curBone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL | BONE_DONE);
+ }
+ }
+}
+
+/* ------------------------------------- */
+
+/* if editbone (partial) selected, copy data */
+/* context; editmode armature, with mirror editing enabled */
+void transform_armature_mirror_update(Object *obedit)
+{
+ bArmature *arm = obedit->data;
+ EditBone *ebo, *eboflip;
+
+ for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ /* no layer check, correct mirror is more important */
+ if (ebo->flag & (BONE_TIPSEL | BONE_ROOTSEL)) {
+ eboflip = ED_armature_bone_get_mirrored(arm->edbo, ebo);
+
+ if (eboflip) {
+ /* we assume X-axis flipping for now */
+ if (ebo->flag & BONE_TIPSEL) {
+ EditBone *children;
+
+ eboflip->tail[0] = -ebo->tail[0];
+ eboflip->tail[1] = ebo->tail[1];
+ eboflip->tail[2] = ebo->tail[2];
+ eboflip->rad_tail = ebo->rad_tail;
+ eboflip->roll = -ebo->roll;
+
+ /* Also move connected children, in case children's name aren't mirrored properly */
+ for (children = arm->edbo->first; children; children = children->next) {
+ if (children->parent == eboflip && children->flag & BONE_CONNECTED) {
+ copy_v3_v3(children->head, eboflip->tail);
+ children->rad_head = ebo->rad_tail;
+ }
+ }
+ }
+ if (ebo->flag & BONE_ROOTSEL) {
+ eboflip->head[0] = -ebo->head[0];
+ eboflip->head[1] = ebo->head[1];
+ eboflip->head[2] = ebo->head[2];
+ eboflip->rad_head = ebo->rad_head;
+ eboflip->roll = -ebo->roll;
+
+ /* Also move connected parent, in case parent's name isn't mirrored properly */
+ if (eboflip->parent && eboflip->flag & BONE_CONNECTED) {
+ EditBone *parent = eboflip->parent;
+ copy_v3_v3(parent->tail, eboflip->head);
+ parent->rad_tail = ebo->rad_head;
+ }
+ }
+ if (ebo->flag & BONE_SELECTED) {
+ eboflip->dist = ebo->dist;
+ eboflip->roll = -ebo->roll;
+ eboflip->xwidth = ebo->xwidth;
+ eboflip->zwidth = ebo->zwidth;
+ }
+ }
+ }
+ }
+}
+
+/* *************************************************************** */
+/* Armature EditMode Conversions */
+
+/* converts Bones to EditBone list, used for tools as well */
+EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone *actBone)
+{
+ EditBone *eBone;
+ EditBone *eBoneAct = NULL;
+ EditBone *eBoneTest = NULL;
+ Bone *curBone;
+
+ for (curBone = bones->first; curBone; curBone = curBone->next) {
+ eBone = MEM_callocN(sizeof(EditBone), "make_editbone");
+
+ /* Copy relevant data from bone to eBone */
+ eBone->parent = parent;
+ BLI_strncpy(eBone->name, curBone->name, sizeof(eBone->name));
+ eBone->flag = curBone->flag;
+
+ /* fix selection flags */
+ if (eBone->flag & BONE_SELECTED) {
+ /* if the bone is selected the copy its root selection to the parents tip */
+ eBone->flag |= BONE_TIPSEL;
+ if (eBone->parent && (eBone->flag & BONE_CONNECTED)) {
+ eBone->parent->flag |= BONE_TIPSEL;
+ eBone->flag &= ~BONE_ROOTSEL; /* this is ignored when there is a connected parent, so unset it */
+ }
+ else {
+ eBone->flag |= BONE_ROOTSEL;
+ }
+ }
+ else {
+ /* if the bone is not selected, but connected to its parent
+ * copy the parents tip selection state */
+ if (eBone->parent && (eBone->flag & BONE_CONNECTED)) {
+ /* selecting with the mouse gives this behavior */
+ if (eBone->parent->flag & BONE_TIPSEL) {
+ eBone->flag |= BONE_ROOTSEL;
+ }
+ else {
+ eBone->flag &= ~BONE_ROOTSEL;
+ }
+
+ /* probably not selected but just in case */
+ eBone->flag &= ~BONE_TIPSEL;
+ }
+ }
+
+ copy_v3_v3(eBone->head, curBone->arm_head);
+ copy_v3_v3(eBone->tail, curBone->arm_tail);
+ eBone->roll = curBone->arm_roll;
+
+ /* rest of stuff copy */
+ eBone->length = curBone->length;
+ eBone->dist = curBone->dist;
+ eBone->weight = curBone->weight;
+ eBone->xwidth = curBone->xwidth;
+ eBone->zwidth = curBone->zwidth;
+ eBone->ease1 = curBone->ease1;
+ eBone->ease2 = curBone->ease2;
+ eBone->rad_head = curBone->rad_head;
+ eBone->rad_tail = curBone->rad_tail;
+ eBone->segments = curBone->segments;
+ eBone->layer = curBone->layer;
+
+ if (curBone->prop)
+ eBone->prop = IDP_CopyProperty(curBone->prop);
+
+ BLI_addtail(edbo, eBone);
+
+ /* Add children if necessary */
+ if (curBone->childbase.first) {
+ eBoneTest = make_boneList(edbo, &curBone->childbase, eBone, actBone);
+ if (eBoneTest)
+ eBoneAct = eBoneTest;
+ }
+
+ if (curBone == actBone)
+ eBoneAct = eBone;
+ }
+
+ 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)
+{
+ Bone *curBone;
+ EditBone *ebone;
+ float premat[3][3];
+ float postmat[3][3];
+ float difmat[3][3];
+ float imat[3][3];
+ float delta[3];
+
+ for (curBone = bonelist->first; curBone; curBone = curBone->next) {
+ /* sets local matrix and arm_mat (restpos) */
+ BKE_armature_where_is_bone(curBone, curBone->parent);
+
+ /* Find the associated editbone */
+ for (ebone = editbonelist->first; ebone; ebone = ebone->next)
+ if ((Bone *)ebone->temp == curBone)
+ break;
+
+ if (ebone) {
+ /* Get the ebone premat */
+ sub_v3_v3v3(delta, ebone->tail, ebone->head);
+ vec_roll_to_mat3(delta, ebone->roll, premat);
+
+ /* Get the bone postmat */
+ copy_m3_m4(postmat, curBone->arm_mat);
+
+ invert_m3_m3(imat, premat);
+ 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])));
+#endif
+ curBone->roll = (float)-atan2(difmat[2][0], difmat[2][2]);
+
+ /* and set restposition again */
+ BKE_armature_where_is_bone(curBone, curBone->parent);
+ }
+ fix_bonelist_roll(&curBone->childbase, editbonelist);
+ }
+}
+
+/* put EditMode back in Object */
+void ED_armature_from_edit(Object *obedit)
+{
+ bArmature *arm = obedit->data;
+ EditBone *eBone, *neBone;
+ Bone *newBone;
+ Object *obt;
+
+ /* armature bones */
+ BKE_armature_bonelist_free(&arm->bonebase);
+
+ /* remove zero sized bones, this gives instable restposes */
+ for (eBone = arm->edbo->first; eBone; eBone = neBone) {
+ float len = len_v3v3(eBone->head, eBone->tail);
+ neBone = eBone->next;
+ if (len <= 0.000001f) { /* FLT_EPSILON is too large? */
+ EditBone *fBone;
+
+ /* Find any bones that refer to this bone */
+ for (fBone = arm->edbo->first; fBone; fBone = fBone->next) {
+ if (fBone->parent == eBone)
+ fBone->parent = eBone->parent;
+ }
+ if (G.debug & G_DEBUG)
+ printf("Warning: removed zero sized bone: %s\n", eBone->name);
+ bone_free(arm, eBone);
+ }
+ }
+
+ /* 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 */
+
+ BLI_strncpy(newBone->name, eBone->name, sizeof(newBone->name));
+ copy_v3_v3(newBone->arm_head, eBone->head);
+ copy_v3_v3(newBone->arm_tail, eBone->tail);
+ newBone->arm_roll = eBone->roll;
+
+ newBone->flag = eBone->flag;
+
+ if (eBone == arm->act_edbone) {
+ /* don't change active selection, this messes up separate which uses
+ * editmode toggle and can separate active bone which is de-selected originally */
+ /* newBone->flag |= BONE_SELECTED; */ /* important, editbones can be active with only 1 point selected */
+ arm->act_edbone = NULL;
+ arm->act_bone = newBone;
+ }
+ newBone->roll = 0.0f;
+
+ newBone->weight = eBone->weight;
+ newBone->dist = eBone->dist;
+
+ newBone->xwidth = eBone->xwidth;
+ newBone->zwidth = eBone->zwidth;
+ newBone->ease1 = eBone->ease1;
+ newBone->ease2 = eBone->ease2;
+ newBone->rad_head = eBone->rad_head;
+ newBone->rad_tail = eBone->rad_tail;
+ newBone->segments = eBone->segments;
+ newBone->layer = eBone->layer;
+
+ if (eBone->prop)
+ newBone->prop = IDP_CopyProperty(eBone->prop);
+ }
+
+ /* Fix parenting in a separate pass to ensure ebone->bone connections
+ * are valid at this point */
+ for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
+ newBone = (Bone *)eBone->temp;
+ if (eBone->parent) {
+ newBone->parent = (Bone *)eBone->parent->temp;
+ BLI_addtail(&newBone->parent->childbase, newBone);
+
+ {
+ float M_parentRest[3][3];
+ float iM_parentRest[3][3];
+ float delta[3];
+
+ /* Get the parent's matrix (rotation only) */
+ sub_v3_v3v3(delta, eBone->parent->tail, eBone->parent->head);
+ vec_roll_to_mat3(delta, eBone->parent->roll, 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);
+
+ /* so all users of this armature should get rebuilt */
+ for (obt = G.main->object.first; obt; obt = obt->id.next) {
+ if (obt->data == arm)
+ BKE_pose_rebuild(obt, arm);
+ }
+
+ DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+}
+
+void ED_armature_edit_free(struct Object *ob)
+{
+ bArmature *arm = ob->data;
+ EditBone *eBone;
+
+ /* Clear the editbones list */
+ if (arm->edbo) {
+ if (arm->edbo->first) {
+ for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
+ if (eBone->prop) {
+ IDP_FreeProperty(eBone->prop);
+ MEM_freeN(eBone->prop);
+ }
+ }
+
+ BLI_freelistN(arm->edbo);
+ }
+ MEM_freeN(arm->edbo);
+ arm->edbo = NULL;
+ }
+}
+
+/* Put armature in EditMode */
+void ED_armature_to_edit(Object *ob)
+{
+ bArmature *arm = ob->data;
+
+ ED_armature_edit_free(ob);
+ arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature");
+ arm->act_edbone = make_boneList(arm->edbo, &arm->bonebase, NULL, arm->act_bone);
+ arm->act_bone = NULL;
+
+// BIF_freeTemplates(); /* force template update when entering editmode */
+}
+
+/* *************************************************************** */
+/* Undo for Armature EditMode*/
+
+typedef struct UndoArmature {
+ EditBone *act_edbone;
+ ListBase lb;
+} UndoArmature;
+
+static void undoBones_to_editBones(void *uarmv, void *armv, void *UNUSED(data))
+{
+ UndoArmature *uarm = uarmv;
+ bArmature *arm = armv;
+ EditBone *ebo, *newebo;
+
+ BLI_freelistN(arm->edbo);
+
+ /* copy */
+ for (ebo = uarm->lb.first; ebo; ebo = ebo->next) {
+ newebo = MEM_dupallocN(ebo);
+ ebo->temp = newebo;
+ BLI_addtail(arm->edbo, newebo);
+ }
+
+ /* active bone */
+ if (uarm->act_edbone) {
+ ebo = uarm->act_edbone;
+ arm->act_edbone = ebo->temp;
+ }
+ else
+ arm->act_edbone = NULL;
+
+ /* set pointers */
+ for (newebo = arm->edbo->first; newebo; newebo = newebo->next) {
+ if (newebo->parent) newebo->parent = newebo->parent->temp;
+ }
+ /* be sure they don't hang ever */
+ for (newebo = arm->edbo->first; newebo; newebo = newebo->next) {
+ newebo->temp = NULL;
+ }
+}
+
+static void *editBones_to_undoBones(void *armv, void *UNUSED(obdata))
+{
+ bArmature *arm = armv;
+ UndoArmature *uarm;
+ EditBone *ebo, *newebo;
+
+ uarm = MEM_callocN(sizeof(UndoArmature), "listbase undo");
+
+ /* copy */
+ for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ newebo = MEM_dupallocN(ebo);
+ ebo->temp = newebo;
+ BLI_addtail(&uarm->lb, newebo);
+ }
+
+ /* active bone */
+ if (arm->act_edbone) {
+ ebo = arm->act_edbone;
+ uarm->act_edbone = ebo->temp;
+ }
+
+ /* set pointers */
+ for (newebo = uarm->lb.first; newebo; newebo = newebo->next) {
+ if (newebo->parent) newebo->parent = newebo->parent->temp;
+ }
+
+ return uarm;
+}
+
+static void free_undoBones(void *uarmv)
+{
+ UndoArmature *uarm = uarmv;
+
+ BLI_freelistN(&uarm->lb);
+ MEM_freeN(uarm);
+}
+
+static void *get_armature_edit(bContext *C)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_ARMATURE) {
+ return obedit->data;
+ }
+ return NULL;
+}
+
+/* and this is all the undo system needs to know */
+void undo_push_armature(bContext *C, const char *name)
+{
+ // XXX solve getdata()
+ undo_editmode_push(C, name, get_armature_edit, free_undoBones, undoBones_to_editBones, editBones_to_undoBones, NULL);
+}
diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c
deleted file mode 100644
index e801d3689e5..00000000000
--- a/source/blender/editors/armature/editarmature.c
+++ /dev/null
@@ -1,6163 +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.
- *
- * Contributor(s): Blender Foundation, 2002-2009 full recode.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/armature/editarmature.c
- * \ingroup edarmature
- */
-
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <math.h>
-#include <float.h>
-#include <assert.h>
-
-
-#include "DNA_anim_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_armature_types.h"
-#include "DNA_constraint_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLI_utildefines.h"
-#include "BLI_ghash.h"
-
-#include "BKE_animsys.h"
-#include "BKE_action.h"
-#include "BKE_armature.h"
-#include "BKE_constraint.h"
-#include "BKE_context.h"
-#include "BKE_deform.h"
-#include "BKE_depsgraph.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_global.h"
-#include "BKE_idprop.h"
-#include "BKE_main.h"
-#include "BKE_object.h"
-#include "BKE_report.h"
-#include "BKE_subsurf.h"
-#include "BKE_modifier.h"
-#include "DNA_object_types.h"
-
-#include "BIF_gl.h"
-
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "ED_armature.h"
-#include "ED_keyframing.h"
-#include "ED_mesh.h"
-#include "ED_object.h"
-#include "ED_screen.h"
-#include "ED_util.h"
-#include "ED_view3d.h"
-
-#include "UI_interface.h"
-#include "UI_resources.h"
-
-#include "armature_intern.h"
-#include "meshlaplacian.h"
-
-#if 0
-#include "reeb.h"
-#endif
-
-/* **************** tools on Editmode Armature **************** */
-
-/* Sync selection to parent for connected children */
-void ED_armature_sync_selection(ListBase *edbo)
-{
- EditBone *ebo;
-
- for (ebo = edbo->first; ebo; ebo = ebo->next) {
- /* if bone is not selectable, we shouldn't alter this setting... */
- if ((ebo->flag & BONE_UNSELECTABLE) == 0) {
- if ((ebo->flag & BONE_CONNECTED) && (ebo->parent)) {
- if (ebo->parent->flag & BONE_TIPSEL)
- ebo->flag |= BONE_ROOTSEL;
- else
- ebo->flag &= ~BONE_ROOTSEL;
- }
-
- if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL))
- ebo->flag |= BONE_SELECTED;
- else
- ebo->flag &= ~BONE_SELECTED;
- }
- }
-}
-
-void ED_armature_validate_active(struct bArmature *arm)
-{
- EditBone *ebone = arm->act_edbone;
-
- if (ebone) {
- if (ebone->flag & BONE_HIDDEN_A)
- arm->act_edbone = NULL;
- }
-}
-
-static void bone_free(bArmature *arm, EditBone *bone)
-{
- if (arm->act_edbone == bone)
- arm->act_edbone = NULL;
-
- if (bone->prop) {
- IDP_FreeProperty(bone->prop);
- MEM_freeN(bone->prop);
- }
-
- BLI_freelinkN(arm->edbo, bone);
-}
-
-void ED_armature_edit_bone_remove(bArmature *arm, EditBone *exBone)
-{
- EditBone *curBone;
-
- /* Find any bones that refer to this bone */
- for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
- if (curBone->parent == exBone) {
- curBone->parent = exBone->parent;
- curBone->flag &= ~BONE_CONNECTED;
- }
- }
-
- bone_free(arm, exBone);
-}
-
-/* context: editmode armature */
-EditBone *ED_armature_bone_get_mirrored(ListBase *edbo, EditBone *ebo)
-{
- EditBone *eboflip = NULL;
- char name[MAXBONENAME];
-
- if (ebo == NULL)
- return NULL;
-
- flip_side_name(name, ebo->name, FALSE);
-
- for (eboflip = edbo->first; eboflip; eboflip = eboflip->next) {
- if (ebo != eboflip) {
- if (!strcmp(name, eboflip->name))
- break;
- }
- }
-
- return eboflip;
-}
-
-/* helper function for tools to work on mirrored parts.
- * it leaves mirrored bones selected then too, which is a good indication of what happened */
-static void armature_select_mirrored(bArmature *arm)
-{
- /* 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) {
- ebone_mirr = ED_armature_bone_get_mirrored(arm->edbo, curBone);
- if (ebone_mirr)
- ebone_mirr->flag |= BONE_SELECTED;
- }
- }
- }
- }
-
-}
-
-static void armature_tag_select_mirrored(bArmature *arm)
-{
- EditBone *curBone;
-
- /* always untag */
- for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
- curBone->flag &= ~BONE_DONE;
- }
-
- /* Select mirrored bones */
- if (arm->flag & ARM_MIRROR_EDIT) {
- for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
- if (arm->layer & curBone->layer) {
- if (curBone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) {
- EditBone *ebone_mirr = ED_armature_bone_get_mirrored(arm->edbo, curBone);
- if (ebone_mirr && (ebone_mirr->flag & BONE_SELECTED) == 0) {
- ebone_mirr->flag |= BONE_DONE;
- }
- }
- }
- }
-
- for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
- if (curBone->flag & BONE_DONE) {
- EditBone *ebone_mirr = ED_armature_bone_get_mirrored(arm->edbo, curBone);
- curBone->flag |= ebone_mirr->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
- }
- }
- }
-}
-
-
-/* only works when tagged */
-static void armature_tag_unselect(bArmature *arm)
-{
- EditBone *curBone;
-
- for (curBone = arm->edbo->first; curBone; curBone = curBone->next) {
- if (curBone->flag & BONE_DONE) {
- curBone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL | BONE_DONE);
- }
- }
-}
-
-/* converts Bones to EditBone list, used for tools as well */
-EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone *actBone)
-{
- EditBone *eBone;
- EditBone *eBoneAct = NULL;
- EditBone *eBoneTest = NULL;
- Bone *curBone;
-
- for (curBone = bones->first; curBone; curBone = curBone->next) {
- eBone = MEM_callocN(sizeof(EditBone), "make_editbone");
-
- /* Copy relevant data from bone to eBone */
- eBone->parent = parent;
- BLI_strncpy(eBone->name, curBone->name, sizeof(eBone->name));
- eBone->flag = curBone->flag;
-
- /* fix selection flags */
-
- if (eBone->flag & BONE_SELECTED) {
- /* if the bone is selected the copy its root selection to the parents tip */
- eBone->flag |= BONE_TIPSEL;
- if (eBone->parent && (eBone->flag & BONE_CONNECTED)) {
- eBone->parent->flag |= BONE_TIPSEL;
- eBone->flag &= ~BONE_ROOTSEL; /* this is ignored when there is a connected parent, so unset it */
- }
- else {
- eBone->flag |= BONE_ROOTSEL;
- }
- }
- else {
- /* if the bone is not selected, but connected to its parent
- * copy the parents tip selection state */
- if (eBone->parent && (eBone->flag & BONE_CONNECTED)) {
- /* selecting with the mouse gives this behavior */
- if (eBone->parent->flag & BONE_TIPSEL) {
- eBone->flag |= BONE_ROOTSEL;
- }
- else {
- eBone->flag &= ~BONE_ROOTSEL;
- }
-
- /* probably not selected but just in case */
- eBone->flag &= ~BONE_TIPSEL;
- }
- }
-
- copy_v3_v3(eBone->head, curBone->arm_head);
- copy_v3_v3(eBone->tail, curBone->arm_tail);
- eBone->roll = curBone->arm_roll;
-
- /* rest of stuff copy */
- eBone->length = curBone->length;
- eBone->dist = curBone->dist;
- eBone->weight = curBone->weight;
- eBone->xwidth = curBone->xwidth;
- eBone->zwidth = curBone->zwidth;
- eBone->ease1 = curBone->ease1;
- eBone->ease2 = curBone->ease2;
- eBone->rad_head = curBone->rad_head;
- eBone->rad_tail = curBone->rad_tail;
- eBone->segments = curBone->segments;
- eBone->layer = curBone->layer;
-
- if (curBone->prop)
- eBone->prop = IDP_CopyProperty(curBone->prop);
-
- BLI_addtail(edbo, eBone);
-
- /* Add children if necessary */
- if (curBone->childbase.first) {
- eBoneTest = make_boneList(edbo, &curBone->childbase, eBone, actBone);
- if (eBoneTest)
- eBoneAct = eBoneTest;
- }
-
- if (curBone == actBone)
- eBoneAct = eBone;
- }
-
- 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)
-{
- Bone *curBone;
- EditBone *ebone;
- float premat[3][3];
- float postmat[3][3];
- float difmat[3][3];
- float imat[3][3];
- float delta[3];
-
- for (curBone = bonelist->first; curBone; curBone = curBone->next) {
- /* sets local matrix and arm_mat (restpos) */
- BKE_armature_where_is_bone(curBone, curBone->parent);
-
- /* Find the associated editbone */
- for (ebone = editbonelist->first; ebone; ebone = ebone->next)
- if ((Bone *)ebone->temp == curBone)
- break;
-
- if (ebone) {
- /* Get the ebone premat */
- sub_v3_v3v3(delta, ebone->tail, ebone->head);
- vec_roll_to_mat3(delta, ebone->roll, premat);
-
- /* Get the bone postmat */
- copy_m3_m4(postmat, curBone->arm_mat);
-
- invert_m3_m3(imat, premat);
- 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])));
-#endif
- curBone->roll = (float)-atan2(difmat[2][0], difmat[2][2]);
-
- /* and set restposition again */
- BKE_armature_where_is_bone(curBone, curBone->parent);
- }
- fix_bonelist_roll(&curBone->childbase, editbonelist);
- }
-}
-
-/* put EditMode back in Object */
-void ED_armature_from_edit(Object *obedit)
-{
- bArmature *arm = obedit->data;
- EditBone *eBone, *neBone;
- Bone *newBone;
- Object *obt;
-
- /* armature bones */
- BKE_armature_bonelist_free(&arm->bonebase);
-
- /* remove zero sized bones, this gives instable restposes */
- for (eBone = arm->edbo->first; eBone; eBone = neBone) {
- float len = len_v3v3(eBone->head, eBone->tail);
- neBone = eBone->next;
- if (len <= 0.000001f) { /* FLT_EPSILON is too large? */
- EditBone *fBone;
-
- /* Find any bones that refer to this bone */
- for (fBone = arm->edbo->first; fBone; fBone = fBone->next) {
- if (fBone->parent == eBone)
- fBone->parent = eBone->parent;
- }
- if (G.debug & G_DEBUG)
- printf("Warning: removed zero sized bone: %s\n", eBone->name);
- bone_free(arm, eBone);
- }
- }
-
- /* 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 */
-
- BLI_strncpy(newBone->name, eBone->name, sizeof(newBone->name));
- copy_v3_v3(newBone->arm_head, eBone->head);
- copy_v3_v3(newBone->arm_tail, eBone->tail);
- newBone->arm_roll = eBone->roll;
-
- newBone->flag = eBone->flag;
-
- if (eBone == arm->act_edbone) {
- /* don't change active selection, this messes up separate which uses
- * editmode toggle and can separate active bone which is de-selected originally */
- /* newBone->flag |= BONE_SELECTED; */ /* important, editbones can be active with only 1 point selected */
- arm->act_edbone = NULL;
- arm->act_bone = newBone;
- }
- newBone->roll = 0.0f;
-
- newBone->weight = eBone->weight;
- newBone->dist = eBone->dist;
-
- newBone->xwidth = eBone->xwidth;
- newBone->zwidth = eBone->zwidth;
- newBone->ease1 = eBone->ease1;
- newBone->ease2 = eBone->ease2;
- newBone->rad_head = eBone->rad_head;
- newBone->rad_tail = eBone->rad_tail;
- newBone->segments = eBone->segments;
- newBone->layer = eBone->layer;
-
- if (eBone->prop)
- newBone->prop = IDP_CopyProperty(eBone->prop);
- }
-
- /* Fix parenting in a separate pass to ensure ebone->bone connections
- * are valid at this point */
- for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
- newBone = (Bone *)eBone->temp;
- if (eBone->parent) {
- newBone->parent = (Bone *)eBone->parent->temp;
- BLI_addtail(&newBone->parent->childbase, newBone);
-
- {
- float M_parentRest[3][3];
- float iM_parentRest[3][3];
- float delta[3];
-
- /* Get the parent's matrix (rotation only) */
- sub_v3_v3v3(delta, eBone->parent->tail, eBone->parent->head);
- vec_roll_to_mat3(delta, eBone->parent->roll, 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);
-
- /* so all users of this armature should get rebuilt */
- for (obt = G.main->object.first; obt; obt = obt->id.next) {
- if (obt->data == arm)
- BKE_pose_rebuild(obt, arm);
- }
-
- DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
-}
-
-void ED_armature_apply_transform(Object *ob, float mat[4][4])
-{
- EditBone *ebone;
- bArmature *arm = ob->data;
- float scale = mat4_to_scale(mat); /* store the scale of the matrix here to use on envelopes */
- float mat3[3][3];
-
- copy_m3_m4(mat3, mat);
- normalize_m3(mat3);
-
- /* Put the armature into editmode */
- ED_armature_to_edit(ob);
-
- /* Do the rotations */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- float delta[3], tmat[3][3];
-
- /* find the current bone's roll matrix */
- sub_v3_v3v3(delta, ebone->tail, ebone->head);
- vec_roll_to_mat3(delta, ebone->roll, tmat);
-
- /* transform the roll matrix */
- mul_m3_m3m3(tmat, mat3, tmat);
-
- /* transform the bone */
- mul_m4_v3(mat, ebone->head);
- mul_m4_v3(mat, ebone->tail);
-
- /* apply the transfiormed roll back */
- mat3_to_vec_roll(tmat, NULL, &ebone->roll);
-
- ebone->rad_head *= scale;
- ebone->rad_tail *= scale;
- ebone->dist *= scale;
-
- /* we could be smarter and scale by the matrix along the x & z axis */
- ebone->xwidth *= scale;
- ebone->zwidth *= scale;
- }
-
- /* Turn the list into an armature */
- ED_armature_from_edit(ob);
- ED_armature_edit_free(ob);
-}
-
-/* exported for use in editors/object/ */
-/* 0 == do center, 1 == center new, 2 == center cursor */
-void docenter_armature(Scene *scene, Object *ob, float cursor[3], int centermode, int around)
-{
- Object *obedit = scene->obedit; // XXX get from context
- EditBone *ebone;
- bArmature *arm = ob->data;
- float cent[3];
-
- /* Put the armature into editmode */
- if (ob != obedit) {
- ED_armature_to_edit(ob);
- obedit = NULL; /* we cant use this so behave as if there is no obedit */
- }
-
- /* Find the centerpoint */
- if (centermode == 2) {
- copy_v3_v3(cent, cursor);
- invert_m4_m4(ob->imat, ob->obmat);
- mul_m4_v3(ob->imat, cent);
- }
- else {
- if (around == V3D_CENTROID) {
- int total = 0;
- zero_v3(cent);
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- total += 2;
- add_v3_v3(cent, ebone->head);
- add_v3_v3(cent, ebone->tail);
- }
- mul_v3_fl(cent, 1.0f / (float)total);
- }
- else {
- float min[3], max[3];
- INIT_MINMAX(min, max);
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- minmax_v3v3_v3(min, max, ebone->head);
- minmax_v3v3_v3(min, max, ebone->tail);
- }
- mid_v3_v3v3(cent, min, max);
- }
- }
-
- /* Do the adjustments */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- sub_v3_v3(ebone->head, cent);
- sub_v3_v3(ebone->tail, cent);
- }
-
- /* Turn the list into an armature */
- if (obedit == NULL) {
- ED_armature_from_edit(ob);
- ED_armature_edit_free(ob);
- }
-
- /* Adjust object location for new centerpoint */
- if (centermode && obedit == NULL) {
- mul_mat3_m4_v3(ob->obmat, cent); /* ommit translation part */
- add_v3_v3(ob->loc, cent);
- }
-}
-
-/* ---------------------- */
-
-/* checks if an EditBone with a matching name already, returning the matching bone if it exists */
-static EditBone *editbone_name_exists(ListBase *edbo, const char *name)
-{
- return BLI_findstring(edbo, name, offsetof(EditBone, name));
-}
-
-/* note: there's a unique_bone_name() too! */
-static int editbone_unique_check(void *arg, const char *name)
-{
- struct {ListBase *lb; void *bone; } *data = arg;
- EditBone *dupli = editbone_name_exists(data->lb, name);
- return dupli && dupli != data->bone;
-}
-
-void unique_editbone_name(ListBase *edbo, char *name, EditBone *bone)
-{
- struct {ListBase *lb; void *bone; } data;
- data.lb = edbo;
- data.bone = bone;
-
- BLI_uniquename_cb(editbone_unique_check, &data, "Bone", '.', name, sizeof(bone->name));
-}
-
-/* helper for apply_armature_pose2bones - fixes parenting of objects that are bone-parented to armature */
-static void applyarmature_fix_boneparents(Scene *scene, Object *armob)
-{
- Object workob, *ob;
-
- /* go through all objects in database */
- for (ob = G.main->object.first; ob; ob = ob->id.next) {
- /* if parent is bone in this armature, apply corrections */
- if ((ob->parent == armob) && (ob->partype == PARBONE)) {
- /* apply current transform from parent (not yet destroyed),
- * then calculate new parent inverse matrix
- */
- BKE_object_apply_mat4(ob, ob->obmat, FALSE, FALSE);
-
- BKE_object_workob_calc_parent(scene, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
- }
- }
-}
-
-/* set the current pose as the restpose */
-static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object
- bArmature *arm = BKE_armature_from_object(ob);
- bPose *pose;
- bPoseChannel *pchan;
- EditBone *curbone;
-
- /* don't check if editmode (should be done by caller) */
- if (ob->type != OB_ARMATURE)
- return OPERATOR_CANCELLED;
- if (BKE_object_obdata_is_libdata(ob)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot apply pose to lib-linked armature"); /* error_libdata(); */
- return OPERATOR_CANCELLED;
- }
-
- /* helpful warnings... */
- /* TODO: add warnings to be careful about actions, applying deforms first, etc. */
- if (ob->adt && ob->adt->action)
- BKE_report(op->reports, RPT_WARNING,
- "Actions on this armature will be destroyed by this new rest pose as the "
- "transforms stored are relative to the old rest pose");
-
- /* Get editbones of active armature to alter */
- ED_armature_to_edit(ob);
-
- /* get pose of active object and move it out of posemode */
- pose = ob->pose;
-
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- curbone = editbone_name_exists(arm->edbo, pchan->name);
-
- /* simply copy the head/tail values from pchan over to curbone */
- copy_v3_v3(curbone->head, pchan->pose_head);
- copy_v3_v3(curbone->tail, pchan->pose_tail);
-
- /* fix roll:
- * 1. find auto-calculated roll value for this bone now
- * 2. remove this from the 'visual' y-rotation
- */
- {
- float premat[3][3], imat[3][3], pmat[3][3], tmat[3][3];
- float delta[3], eul[3];
-
- /* obtain new auto y-rotation */
- sub_v3_v3v3(delta, curbone->tail, curbone->head);
- vec_roll_to_mat3(delta, 0.0f, premat);
- invert_m3_m3(imat, premat);
-
- /* get pchan 'visual' matrix */
- copy_m3_m4(pmat, pchan->pose_mat);
-
- /* remove auto from visual and get euler rotation */
- mul_m3_m3m3(tmat, imat, pmat);
- mat3_to_eul(eul, tmat);
-
- /* just use this euler-y as new roll value */
- curbone->roll = eul[1];
- }
-
- /* clear transform values for pchan */
- zero_v3(pchan->loc);
- zero_v3(pchan->eul);
- unit_qt(pchan->quat);
- unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
- pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f;
-
- /* set anim lock */
- curbone->flag |= BONE_UNKEYED;
- }
-
- /* convert editbones back to bones, and then free the edit-data */
- ED_armature_from_edit(ob);
- ED_armature_edit_free(ob);
-
- /* flush positions of posebones */
- BKE_pose_where_is(scene, ob);
-
- /* fix parenting of objects which are bone-parented */
- applyarmature_fix_boneparents(scene, ob);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_armature_apply(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Apply Pose as Rest Pose";
- ot->idname = "POSE_OT_armature_apply";
- ot->description = "Apply the current pose as the new rest pose";
-
- /* callbacks */
- ot->exec = apply_armature_pose2bones_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-
-/* set the current pose as the restpose */
-static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object
-
- /* don't check if editmode (should be done by caller) */
- if (ob->type != OB_ARMATURE)
- return OPERATOR_CANCELLED;
-
- /* loop over all selected pchans
- *
- * TODO, loop over children before parents if multiple bones
- * at once are to be predictable*/
- CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones)
- {
- float delta_mat[4][4];
-
- /* chan_mat already contains the delta transform from rest pose to pose-mode pose
- * as that is baked into there so that B-Bones will work. Once we've set this as the
- * new raw-transform components, don't recalc the poses yet, otherwise IK result will
- * change, thus changing the result we may be trying to record.
- */
- copy_m4_m4(delta_mat, pchan->chan_mat);
- BKE_pchan_apply_mat4(pchan, delta_mat, TRUE);
- }
- CTX_DATA_END;
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_visual_transform_apply(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Apply Visual Transform to Pose";
- ot->idname = "POSE_OT_visual_transform_apply";
- ot->description = "Apply final constrained position of pose bones to their transform";
-
- /* callbacks */
- ot->exec = pose_visual_transform_apply_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* ---------------------- */
-
-/* Helper function for armature joining - link fixing */
-static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone)
-{
- Object *ob;
- bPose *pose;
- bPoseChannel *pchant;
- bConstraint *con;
-
- /* let's go through all objects in database */
- for (ob = G.main->object.first; ob; ob = ob->id.next) {
- /* do some object-type specific things */
- if (ob->type == OB_ARMATURE) {
- pose = ob->pose;
- for (pchant = pose->chanbase.first; pchant; pchant = pchant->next) {
- for (con = pchant->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- /* constraint targets */
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar == srcArm) {
- if (ct->subtarget[0] == '\0') {
- ct->tar = tarArm;
- }
- else if (strcmp(ct->subtarget, pchan->name) == 0) {
- ct->tar = tarArm;
- BLI_strncpy(ct->subtarget, curbone->name, sizeof(ct->subtarget));
- }
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 0);
- }
-
- /* action constraint? */
- if (con->type == CONSTRAINT_TYPE_ACTION) {
- bActionConstraint *data = con->data; // XXX old animation system
- bAction *act;
- bActionChannel *achan;
-
- if (data->act) {
- act = data->act;
-
- for (achan = act->chanbase.first; achan; achan = achan->next) {
- if (strcmp(achan->name, pchan->name) == 0)
- BLI_strncpy(achan->name, curbone->name, sizeof(achan->name));
- }
- }
- }
-
- }
- }
- }
-
- /* fix object-level constraints */
- if (ob != srcArm) {
- for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- /* constraint targets */
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar == srcArm) {
- if (ct->subtarget[0] == '\0') {
- ct->tar = tarArm;
- }
- else if (strcmp(ct->subtarget, pchan->name) == 0) {
- ct->tar = tarArm;
- BLI_strncpy(ct->subtarget, curbone->name, sizeof(ct->subtarget));
- }
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 0);
- }
- }
- }
-
- /* See if an object is parented to this armature */
- if (ob->parent && (ob->parent == srcArm)) {
- /* Is object parented to a bone of this src armature? */
- if (ob->partype == PARBONE) {
- /* bone name in object */
- if (!strcmp(ob->parsubstr, pchan->name))
- BLI_strncpy(ob->parsubstr, curbone->name, sizeof(ob->parsubstr));
- }
-
- /* make tar armature be new parent */
- ob->parent = tarArm;
- }
- }
-}
-
-/* join armature exec is exported for use in object->join objects operator... */
-int join_armature_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- bArmature *arm = (ob) ? ob->data : NULL;
- bPose *pose, *opose;
- bPoseChannel *pchan, *pchann;
- EditBone *curbone;
- float mat[4][4], oimat[4][4];
-
- /* Ensure we're not in editmode and that the active object is an armature*/
- if (!ob || ob->type != OB_ARMATURE)
- return OPERATOR_CANCELLED;
- if (!arm || arm->edbo)
- return OPERATOR_CANCELLED;
-
- /* Get editbones of active armature to add editbones to */
- ED_armature_to_edit(ob);
-
- /* get pose of active object and move it out of posemode */
- pose = ob->pose;
- ob->mode &= ~OB_MODE_POSE;
-
- CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
- {
- if ((base->object->type == OB_ARMATURE) && (base->object != ob)) {
- bArmature *curarm = base->object->data;
-
- /* Make a list of editbones in current armature */
- ED_armature_to_edit(base->object);
-
- /* Get Pose of current armature */
- opose = base->object->pose;
- base->object->mode &= ~OB_MODE_POSE;
- //BASACT->flag &= ~OB_MODE_POSE;
-
- /* Find the difference matrix */
- invert_m4_m4(oimat, ob->obmat);
- mult_m4_m4m4(mat, oimat, base->object->obmat);
-
- /* Copy bones and posechannels from the object to the edit armature */
- for (pchan = opose->chanbase.first; pchan; pchan = pchann) {
- pchann = pchan->next;
- curbone = editbone_name_exists(curarm->edbo, pchan->name);
-
- /* Get new name */
- unique_editbone_name(arm->edbo, curbone->name, NULL);
-
- /* Transform the bone */
- {
- float premat[4][4];
- float postmat[4][4];
- float difmat[4][4];
- float imat[4][4];
- float temp[3][3];
- float delta[3];
-
- /* Get the premat */
- sub_v3_v3v3(delta, curbone->tail, curbone->head);
- vec_roll_to_mat3(delta, curbone->roll, temp);
-
- unit_m4(premat); /* Mat4MulMat34 only sets 3x3 part */
- mul_m4_m3m4(premat, temp, mat);
-
- mul_m4_v3(mat, curbone->head);
- mul_m4_v3(mat, curbone->tail);
-
- /* Get the postmat */
- sub_v3_v3v3(delta, curbone->tail, curbone->head);
- vec_roll_to_mat3(delta, curbone->roll, temp);
- copy_m4_m3(postmat, temp);
-
- /* Find the roll */
- invert_m4_m4(imat, premat);
- mult_m4_m4m4(difmat, imat, postmat);
-
- curbone->roll -= (float)atan2(difmat[2][0], difmat[2][2]);
- }
-
- /* Fix Constraints and Other Links to this Bone and Armature */
- joined_armature_fix_links(ob, base->object, pchan, curbone);
-
- /* Rename pchan */
- BLI_strncpy(pchan->name, curbone->name, sizeof(pchan->name));
-
- /* Jump Ship! */
- BLI_remlink(curarm->edbo, curbone);
- BLI_addtail(arm->edbo, curbone);
-
- BLI_remlink(&opose->chanbase, pchan);
- BLI_addtail(&pose->chanbase, pchan);
- BKE_pose_channels_hash_free(opose);
- BKE_pose_channels_hash_free(pose);
- }
-
- ED_base_object_free_and_unlink(bmain, scene, base);
- }
- }
- CTX_DATA_END;
-
- DAG_scene_sort(bmain, scene); /* because we removed object(s) */
-
- ED_armature_from_edit(ob);
- ED_armature_edit_free(ob);
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
-
- return OPERATOR_FINISHED;
-}
-
-/* ---------------------- */
-
-/* Helper function for armature separating - link fixing */
-static void separated_armature_fix_links(Object *origArm, Object *newArm)
-{
- Object *ob;
- bPoseChannel *pchan;
- bConstraint *con;
- ListBase *opchans, *npchans;
-
- /* get reference to list of bones in original and new armatures */
- opchans = &origArm->pose->chanbase;
- npchans = &newArm->pose->chanbase;
-
- /* let's go through all objects in database */
- for (ob = G.main->object.first; ob; ob = ob->id.next) {
- /* do some object-type specific things */
- 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 = constraint_get_typeinfo(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- /* constraint targets */
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- /* any targets which point to original armature are redirected to the new one only if:
- * - the target isn't origArm/newArm itself
- * - the target is one that can be found in newArm/origArm
- */
- if (ct->subtarget[0] != 0) {
- if (ct->tar == origArm) {
- if (BLI_findstring(npchans, ct->subtarget, offsetof(bPoseChannel, name))) {
- ct->tar = newArm;
- }
- }
- else if (ct->tar == newArm) {
- if (BLI_findstring(opchans, ct->subtarget, offsetof(bPoseChannel, name))) {
- ct->tar = origArm;
- }
- }
- }
- }
-
- if (cti->flush_constraint_targets) {
- cti->flush_constraint_targets(con, &targets, 0);
- }
- }
- }
- }
- }
-
- /* fix object-level constraints */
- if (ob != origArm) {
- for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- /* constraint targets */
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- /* any targets which point to original armature are redirected to the new one only if:
- * - the target isn't origArm/newArm itself
- * - the target is one that can be found in newArm/origArm
- */
- if (ct->subtarget[0] != '\0') {
- if (ct->tar == origArm) {
- if (BLI_findstring(npchans, ct->subtarget, offsetof(bPoseChannel, name))) {
- ct->tar = newArm;
- }
- }
- else if (ct->tar == newArm) {
- if (BLI_findstring(opchans, ct->subtarget, offsetof(bPoseChannel, name))) {
- ct->tar = origArm;
- }
- }
- }
- }
-
- if (cti->flush_constraint_targets) {
- cti->flush_constraint_targets(con, &targets, 0);
- }
- }
- }
- }
-
- /* See if an object is parented to this armature */
- if (ob->parent && (ob->parent == origArm)) {
- /* Is object parented to a bone of this src armature? */
- if ((ob->partype == PARBONE) && (ob->parsubstr[0] != '\0')) {
- if (BLI_findstring(npchans, ob->parsubstr, offsetof(bPoseChannel, name))) {
- ob->parent = newArm;
- }
- }
- }
- }
-}
-
-/* Helper function for armature separating - remove certain bones from the given armature
- * sel: remove selected bones from the armature, otherwise the unselected bones are removed
- * (ob is not in editmode)
- */
-static void separate_armature_bones(Object *ob, short sel)
-{
- bArmature *arm = (bArmature *)ob->data;
- bPoseChannel *pchan, *pchann;
- EditBone *curbone;
-
- /* make local set of editbones to manipulate here */
- ED_armature_to_edit(ob);
-
- /* go through pose-channels, checking if a bone should be removed */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchann) {
- pchann = pchan->next;
- curbone = editbone_name_exists(arm->edbo, pchan->name);
-
- /* check if bone needs to be removed */
- if ( (sel && (curbone->flag & BONE_SELECTED)) ||
- (!sel && !(curbone->flag & BONE_SELECTED)) )
- {
- EditBone *ebo;
- bPoseChannel *pchn;
-
- /* clear the bone->parent var of any bone that had this as its parent */
- 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->flag &= ~BONE_CONNECTED;
- }
- }
-
- /* clear the pchan->parent var of any pchan that had this as its parent */
- for (pchn = ob->pose->chanbase.first; pchn; pchn = pchn->next) {
- if (pchn->parent == pchan)
- pchn->parent = NULL;
- }
-
- /* free any of the extra-data this pchan might have */
- BKE_pose_channel_free(pchan);
- BKE_pose_channels_hash_free(ob->pose);
-
- /* get rid of unneeded bone */
- bone_free(arm, curbone);
- BLI_freelinkN(&ob->pose->chanbase, pchan);
- }
- }
-
- /* exit editmode (recalculates pchans too) */
- ED_armature_from_edit(ob);
- ED_armature_edit_free(ob);
-}
-
-/* separate selected bones into their armature */
-static int separate_armature_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- Object *oldob, *newob;
- Base *oldbase, *newbase;
-
- /* sanity checks */
- if (obedit == NULL)
- return OPERATOR_CANCELLED;
-
- /* set wait cursor in case this takes a while */
- WM_cursor_wait(1);
-
- /* we are going to do this as follows (unlike every other instance of separate):
- * 1. exit editmode +posemode for active armature/base. Take note of what this is.
- * 2. duplicate base - BASACT is the new one now
- * 3. for each of the two armatures, enter editmode -> remove appropriate bones -> exit editmode + recalc
- * 4. fix constraint links
- * 5. make original armature active and enter editmode
- */
-
- /* 1) only edit-base selected */
- /* TODO: use context iterators for this? */
- CTX_DATA_BEGIN(C, Base *, base, visible_bases)
- {
- if (base->object == obedit) base->flag |= 1;
- else base->flag &= ~1;
- }
- CTX_DATA_END;
-
- /* 1) store starting settings and exit editmode */
- oldob = obedit;
- oldbase = BASACT;
- oldob->mode &= ~OB_MODE_POSE;
- //oldbase->flag &= ~OB_POSEMODE;
-
- ED_armature_from_edit(obedit);
- ED_armature_edit_free(obedit);
-
- /* 2) duplicate base */
- newbase = ED_object_add_duplicate(bmain, scene, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
- DAG_scene_sort(bmain, scene);
-
- newob = newbase->object;
- newbase->flag &= ~SELECT;
-
-
- /* 3) remove bones that shouldn't still be around on both armatures */
- separate_armature_bones(oldob, 1);
- separate_armature_bones(newob, 0);
-
-
- /* 4) fix links before depsgraph flushes */ // err... or after?
- separated_armature_fix_links(oldob, newob);
-
- DAG_id_tag_update(&oldob->id, OB_RECALC_DATA); /* this is the original one */
- DAG_id_tag_update(&newob->id, OB_RECALC_DATA); /* this is the separated one */
-
-
- /* 5) restore original conditions */
- obedit = oldob;
-
- ED_armature_to_edit(obedit);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
-
- /* recalc/redraw + cleanup */
- WM_cursor_wait(0);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_separate(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Separate Bones";
- ot->idname = "ARMATURE_OT_separate";
- 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;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* **************** END tools on Editmode Armature **************** */
-/* **************** PoseMode & EditMode *************************** */
-
-/* only for opengl selection indices */
-Bone *get_indexed_bone(Object *ob, int index)
-{
- bPoseChannel *pchan;
- if (ob->pose == NULL) return NULL;
- index >>= 16; // bone selection codes use left 2 bytes
-
- pchan = BLI_findlink(&ob->pose->chanbase, index);
- return pchan ? pchan->bone : NULL;
-}
-
-/* See if there are any selected bones in this buffer */
-/* only bones from base are checked on */
-static void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short findunsel)
-{
- Object *obedit = scene->obedit; // XXX get from context
- Bone *bone;
- EditBone *ebone;
- void *firstunSel = NULL, *firstSel = NULL, *data;
- unsigned int hitresult;
- short i, takeNext = 0, sel;
-
- for (i = 0; i < hits; i++) {
- hitresult = buffer[3 + (i * 4)];
-
- if (!(hitresult & BONESEL_NOSEL)) { // -1
- if (hitresult & BONESEL_ANY) { // to avoid including objects in selection
-
- hitresult &= ~(BONESEL_ANY);
- /* Determine what the current bone is */
- if (obedit == NULL || base->object != obedit) {
- /* no singular posemode, so check for correct object */
- if (base->selcol == (hitresult & 0xFFFF)) {
- bone = get_indexed_bone(base->object, hitresult);
-
- if (findunsel)
- sel = (bone->flag & BONE_SELECTED);
- else
- sel = !(bone->flag & BONE_SELECTED);
-
- data = bone;
- }
- else {
- data = NULL;
- sel = 0;
- }
- }
- else {
- bArmature *arm = obedit->data;
-
- ebone = BLI_findlink(arm->edbo, hitresult);
- if (findunsel)
- sel = (ebone->flag & BONE_SELECTED);
- else
- sel = !(ebone->flag & BONE_SELECTED);
-
- data = ebone;
- }
-
- if (data) {
- if (sel) {
- if (!firstSel) firstSel = data;
- takeNext = 1;
- }
- else {
- if (!firstunSel)
- firstunSel = data;
- if (takeNext)
- return data;
- }
- }
- }
- }
- }
-
- if (firstunSel)
- return firstunSel;
- else
- return firstSel;
-}
-
-
-
-/* used by posemode as well editmode */
-/* only checks scene->basact! */
-/* x and y are mouse coords (area space) */
-static void *get_nearest_bone(bContext *C, short findunsel, int x, int y)
-{
- ViewContext vc;
- rcti rect;
- unsigned int buffer[MAXPICKBUF];
- short hits;
-
- view3d_set_viewcontext(C, &vc);
-
- // rect.xmin = ... mouseco!
- rect.xmin = rect.xmax = x;
- rect.ymin = rect.ymax = y;
-
- glInitNames();
- hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
-
- if (hits > 0)
- return get_bone_from_selectbuffer(vc.scene, vc.scene->basact, buffer, hits, findunsel);
-
- return NULL;
-}
-
-/* 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;
-}
-
-/* **************** END PoseMode & EditMode *************************** */
-/* **************** Posemode stuff ********************** */
-
-
-static void selectconnected_posebonechildren(Object *ob, Bone *bone, int extend)
-{
- Bone *curBone;
-
- /* stop when unconnected child is encontered, or when unselectable bone is encountered */
- if (!(bone->flag & BONE_CONNECTED) || (bone->flag & BONE_UNSELECTABLE))
- return;
-
- /* XXX old cruft! use notifiers instead */
- //select_actionchannel_by_name (ob->action, bone->name, !(shift));
-
- if (extend)
- bone->flag &= ~BONE_SELECTED;
- else
- bone->flag |= BONE_SELECTED;
-
- for (curBone = bone->childbase.first; curBone; curBone = curBone->next)
- selectconnected_posebonechildren(ob, curBone, extend);
-}
-
-/* within active object context */
-/* previously known as "selectconnected_posearmature" */
-static int pose_select_connected_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bArmature *arm = (bArmature *)ob->data;
- Bone *bone, *curBone, *next = NULL;
- int extend = RNA_boolean_get(op->ptr, "extend");
-
- view3d_operator_needs_opengl(C);
-
- if (extend)
- bone = get_nearest_bone(C, 0, event->mval[0], event->mval[1]);
- else
- bone = get_nearest_bone(C, 1, event->mval[0], event->mval[1]);
-
- if (!bone)
- return OPERATOR_CANCELLED;
-
- /* Select parents */
- for (curBone = bone; curBone; curBone = next) {
- /* ignore bone if cannot be selected */
- if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
- // XXX old cruft! use notifiers instead
- //select_actionchannel_by_name (ob->action, curBone->name, !(shift));
-
- if (extend)
- curBone->flag &= ~BONE_SELECTED;
- else
- curBone->flag |= BONE_SELECTED;
-
- if (curBone->flag & BONE_CONNECTED)
- next = curBone->parent;
- else
- next = NULL;
- }
- else
- next = NULL;
- }
-
- /* Select children */
- for (curBone = bone->childbase.first; curBone; curBone = next)
- selectconnected_posebonechildren(ob, curBone, extend);
-
- /* updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
- if (arm->flag & ARM_HAS_VIZ_DEPS) {
- /* mask modifier ('armature' mode), etc. */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- }
-
- return OPERATOR_FINISHED;
-}
-
-static int pose_select_linked_poll(bContext *C)
-{
- return (ED_operator_view3d_active(C) && ED_operator_posemode(C));
-}
-
-void POSE_OT_select_linked(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Connected";
- ot->idname = "POSE_OT_select_linked";
- ot->description = "Select bones related to selected ones by parent/child relationships";
-
- /* api callbacks */
- ot->exec = NULL;
- ot->invoke = pose_select_connected_invoke;
- ot->poll = pose_select_linked_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first");
-}
-
-/* **************** END Posemode stuff ********************** */
-/* **************** EditMode stuff ********************** */
-
-/* called in space.c */
-/* previously "selectconnected_armature" */
-static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
- bArmature *arm;
- EditBone *bone, *curBone, *next;
- int extend = RNA_boolean_get(op->ptr, "extend");
- Object *obedit = CTX_data_edit_object(C);
- arm = obedit->data;
-
- view3d_operator_needs_opengl(C);
-
- if (extend)
- bone = get_nearest_bone(C, 0, event->mval[0], event->mval[1]);
- else
- bone = get_nearest_bone(C, 1, event->mval[0], event->mval[1]);
-
- if (!bone)
- return OPERATOR_CANCELLED;
-
- /* Select parents */
- for (curBone = bone; curBone; curBone = next) {
- if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
- if (extend) {
- curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else {
- curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- }
-
- if (curBone->flag & BONE_CONNECTED)
- next = curBone->parent;
- else
- next = NULL;
- }
-
- /* Select children */
- while (bone) {
- for (curBone = arm->edbo->first; curBone; curBone = next) {
- next = curBone->next;
- if ((curBone->parent == bone) && (curBone->flag & BONE_UNSELECTABLE) == 0) {
- if (curBone->flag & BONE_CONNECTED) {
- if (extend)
- curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- else
- curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- bone = curBone;
- break;
- }
- else {
- bone = NULL;
- break;
- }
- }
- }
- if (!curBone)
- bone = NULL;
- }
-
- ED_armature_sync_selection(arm->edbo);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
-
- return OPERATOR_FINISHED;
-}
-
-static int armature_select_linked_poll(bContext *C)
-{
- return (ED_operator_view3d_active(C) && ED_operator_editarmature(C) );
-}
-
-void ARMATURE_OT_select_linked(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Connected";
- ot->idname = "ARMATURE_OT_select_linked";
- ot->description = "Select bones related to selected ones by parent/child relationships";
-
- /* api callbacks */
- ot->exec = NULL;
- ot->invoke = armature_select_linked_invoke;
- ot->poll = armature_select_linked_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first");
-}
-
-/* does bones and points */
-/* note that BONE ROOT only gets drawn for root bones (or without IK) */
-static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2],
- ListBase *edbo, int findunsel, int *selmask)
-{
- EditBone *ebone;
- rcti rect;
- unsigned int buffer[MAXPICKBUF];
- unsigned int hitresult, besthitresult = BONESEL_NOSEL;
- int i, mindep = 4;
- short hits;
-
- glInitNames();
-
- rect.xmin = mval[0] - 5;
- rect.xmax = mval[0] + 5;
- rect.ymin = mval[1] - 5;
- rect.ymax = mval[1] + 5;
-
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
- if (hits == 0) {
- rect.xmin = mval[0] - 12;
- rect.xmax = mval[0] + 12;
- rect.ymin = mval[1] - 12;
- rect.ymax = mval[1] + 12;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
- }
- /* See if there are any selected bones in this group */
- if (hits > 0) {
-
- if (hits == 1) {
- if (!(buffer[3] & BONESEL_NOSEL))
- besthitresult = buffer[3];
- }
- else {
- for (i = 0; i < hits; i++) {
- hitresult = buffer[3 + (i * 4)];
- if (!(hitresult & BONESEL_NOSEL)) {
- int dep;
-
- ebone = BLI_findlink(edbo, hitresult & ~BONESEL_ANY);
-
- /* clicks on bone points get advantage */
- if (hitresult & (BONESEL_ROOT | BONESEL_TIP)) {
- /* but also the unselected one */
- if (findunsel) {
- if ( (hitresult & BONESEL_ROOT) && (ebone->flag & BONE_ROOTSEL) == 0)
- dep = 1;
- else if ( (hitresult & BONESEL_TIP) && (ebone->flag & BONE_TIPSEL) == 0)
- dep = 1;
- else
- dep = 2;
- }
- else dep = 2;
- }
- else {
- /* bone found */
- if (findunsel) {
- if ((ebone->flag & BONE_SELECTED) == 0)
- dep = 2;
- else
- dep = 3;
- }
- else dep = 3;
- }
- if (dep < mindep) {
- mindep = dep;
- besthitresult = hitresult;
- }
- }
- }
- }
-
- if (!(besthitresult & BONESEL_NOSEL)) {
-
- ebone = BLI_findlink(edbo, besthitresult & ~BONESEL_ANY);
-
- *selmask = 0;
- if (besthitresult & BONESEL_ROOT)
- *selmask |= BONE_ROOTSEL;
- if (besthitresult & BONESEL_TIP)
- *selmask |= BONE_TIPSEL;
- if (besthitresult & BONESEL_BONE)
- *selmask |= BONE_SELECTED;
- return ebone;
- }
- }
- *selmask = 0;
- return NULL;
-}
-
-/* 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
- arm = obedit->data;
-
- /* cancel if nothing selected */
- if (CTX_DATA_COUNT(C, selected_bones) == 0)
- return OPERATOR_CANCELLED;
-
- 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 = editbone_name_exists(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 = constraint_get_typeinfo(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 = editbone_name_exists(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);
- }
- }
- }
- }
- }
-
-
- for (curBone = arm->edbo->first; curBone; curBone = ebone_next) {
- ebone_next = curBone->next;
- if (arm->layer & curBone->layer) {
- if (curBone->flag & BONE_SELECTED) {
- if (curBone == arm->act_edbone) arm->act_edbone = NULL;
- ED_armature_edit_bone_remove(arm, curBone);
- }
- }
- }
-
-
- ED_armature_sync_selection(arm->edbo);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_delete(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Delete Selected Bone(s)";
- ot->idname = "ARMATURE_OT_delete";
- ot->description = "Remove selected bones from the armature";
-
- /* api callbacks */
- ot->invoke = WM_operator_confirm;
- ot->exec = armature_delete_selected_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* 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)
-{
- 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;
-
- /* 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;
- }
- }
-
- ED_armature_sync_selection(arm->edbo);
-}
-
-void ED_armature_deselect_all_visible(Object *obedit)
-{
- bArmature *arm = obedit->data;
- EditBone *ebone;
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- /* first and foremost, bone must be visible and selected */
- if (EBONE_SELECTABLE(arm, ebone)) {
- ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- }
-
- ED_armature_sync_selection(arm->edbo);
-}
-
-/* accounts for connected parents */
-static int ebone_select_flag(EditBone *ebone)
-{
- if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
- return ((ebone->parent->flag & BONE_TIPSEL) ? BONE_ROOTSEL : 0) | (ebone->flag & (BONE_SELECTED | BONE_TIPSEL));
- }
- else {
- return ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
- }
-}
-
-/* context: editmode armature in view3d */
-int mouse_armature(bContext *C, const int mval[2], int extend, int deselect, int toggle)
-{
- Object *obedit = CTX_data_edit_object(C);
- bArmature *arm = obedit->data;
- ViewContext vc;
- EditBone *nearBone = NULL;
- int selmask;
-
- view3d_set_viewcontext(C, &vc);
-
- BIF_sk_selectStroke(C, mval, extend);
-
- nearBone = get_nearest_editbonepoint(&vc, mval, arm->edbo, 1, &selmask);
- if (nearBone) {
-
- if (!extend && !deselect && !toggle)
- ED_armature_deselect_all(obedit, 0);
-
- /* by definition the non-root connected bones have no root point drawn,
- * so a root selection needs to be delivered to the parent tip */
-
- if (selmask & BONE_SELECTED) {
- if (nearBone->parent && (nearBone->flag & BONE_CONNECTED)) {
- /* click in a chain */
- if (extend) {
- /* select this bone */
- nearBone->flag |= BONE_TIPSEL;
- nearBone->parent->flag |= BONE_TIPSEL;
- }
- else if (deselect) {
- /* deselect this bone */
- nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
- /* only deselect parent tip if it is not selected */
- if (!(nearBone->parent->flag & BONE_SELECTED))
- nearBone->parent->flag &= ~BONE_TIPSEL;
- }
- else if (toggle) {
- /* hold shift inverts this bone's selection */
- if (nearBone->flag & BONE_SELECTED) {
- /* deselect this bone */
- nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
- /* only deselect parent tip if it is not selected */
- if (!(nearBone->parent->flag & BONE_SELECTED))
- nearBone->parent->flag &= ~BONE_TIPSEL;
- }
- else {
- /* select this bone */
- nearBone->flag |= BONE_TIPSEL;
- nearBone->parent->flag |= BONE_TIPSEL;
- }
- }
- else {
- /* select this bone */
- nearBone->flag |= BONE_TIPSEL;
- nearBone->parent->flag |= BONE_TIPSEL;
- }
- }
- else {
- if (extend) {
- nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
- }
- else if (deselect) {
- nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
- }
- else if (toggle) {
- /* hold shift inverts this bone's selection */
- if (nearBone->flag & BONE_SELECTED)
- nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
- else
- nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
- }
- else
- nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
- }
- }
- else {
- if (extend)
- nearBone->flag |= selmask;
- else if (deselect)
- nearBone->flag &= ~selmask;
- else if (toggle && (nearBone->flag & selmask))
- nearBone->flag &= ~selmask;
- else
- nearBone->flag |= selmask;
- }
-
- ED_armature_sync_selection(arm->edbo);
-
- if (nearBone) {
- /* then now check for active status */
- if (ebone_select_flag(nearBone)) {
- arm->act_edbone = nearBone;
- }
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit);
- return 1;
- }
-
- return 0;
-}
-
-void ED_armature_edit_free(struct Object *ob)
-{
- bArmature *arm = ob->data;
- EditBone *eBone;
-
- /* Clear the editbones list */
- if (arm->edbo) {
- if (arm->edbo->first) {
- for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
- if (eBone->prop) {
- IDP_FreeProperty(eBone->prop);
- MEM_freeN(eBone->prop);
- }
- }
-
- BLI_freelistN(arm->edbo);
- }
- MEM_freeN(arm->edbo);
- arm->edbo = NULL;
- }
-}
-
-/* Put armature in EditMode */
-void ED_armature_to_edit(Object *ob)
-{
- bArmature *arm = ob->data;
-
- ED_armature_edit_free(ob);
- arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature");
- arm->act_edbone = make_boneList(arm->edbo, &arm->bonebase, NULL, arm->act_bone);
- arm->act_bone = NULL;
-
-// BIF_freeTemplates(); /* force template update when entering editmode */
-}
-
-
-/* adjust bone roll to align Z axis with vector
- * vec is in local space and is normalized
- */
-
-float ED_rollBoneToVector(EditBone *bone, const float align_axis[3], const short axis_only)
-{
- float mat[3][3], nor[3];
-
- sub_v3_v3v3(nor, bone->tail, bone->head);
- vec_roll_to_mat3(nor, 0.0f, mat);
-
- /* check the bone isn't aligned with the axis */
- if (!is_zero_v3(align_axis) && angle_v3v3(align_axis, mat[2]) > FLT_EPSILON) {
- float vec[3], align_axis_proj[3], roll;
-
- /* project the new_up_axis along the normal */
- project_v3_v3v3(vec, align_axis, nor);
- sub_v3_v3v3(align_axis_proj, align_axis, vec);
-
- if (axis_only) {
- if (angle_v3v3(align_axis_proj, mat[2]) > (float)(M_PI / 2.0)) {
- negate_v3(align_axis_proj);
- }
- }
-
- roll = angle_v3v3(align_axis_proj, mat[2]);
-
- cross_v3_v3v3(vec, mat[2], align_axis_proj);
-
- if (dot_v3v3(vec, nor) < 0) {
- roll = -roll;
- }
-
- return roll;
- }
-
- return 0.0f;
-}
-
-
-static EnumPropertyItem prop_calc_roll_types[] = {
- {0, "X", 0, "X Axis", ""},
- {1, "Y", 0, "Y Axis", ""},
- {2, "Z", 0, "Z Axis", ""},
- {5, "ACTIVE", 0, "Active Bone", ""},
- {6, "VIEW", 0, "View Axis", ""},
- {7, "CURSOR", 0, "Cursor", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-
-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");
- const short axis_only = RNA_boolean_get(op->ptr, "axis_only");
- const short axis_flip = RNA_boolean_get(op->ptr, "axis_flip");
-
- float imat[3][3];
-
- bArmature *arm = ob->data;
- EditBone *ebone;
-
- copy_m3_m4(imat, ob->obmat);
- invert_m3(imat);
-
- if (type == 7) { /* Cursor */
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C); /* can be NULL */
- float cursor_local[3];
- float *cursor = give_cursor(scene, v3d);
-
-
- copy_v3_v3(cursor_local, cursor);
- mul_m3_v3(imat, cursor_local);
-
- /* cursor */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
- 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);
- }
- }
- }
- else {
- float vec[3] = {0.0f, 0.0f, 0.0f};
- if (type == 6) { /* View */
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- if (rv3d == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No region view3d available");
- return OPERATOR_CANCELLED;
- }
-
- copy_v3_v3(vec, rv3d->viewinv[2]);
- mul_m3_v3(imat, vec);
- }
- else if (type == 5) {
- float mat[3][3], nor[3];
- ebone = (EditBone *)arm->act_edbone;
- if (ebone == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active bone set");
- return OPERATOR_CANCELLED;
- }
-
- sub_v3_v3v3(nor, ebone->tail, ebone->head);
- vec_roll_to_mat3(nor, ebone->roll, mat);
- copy_v3_v3(vec, mat[2]);
- }
- else { /* Axis */
- assert(type >= 0 && type <= 5);
- if (type < 3) vec[type] = 1.0f;
- else vec[type - 2] = -1.0f;
- mul_m3_v3(imat, vec);
- }
-
- if (axis_flip) negate_v3(vec);
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
- /* roll func is a callback which assumes that all is well */
- ebone->roll = ED_rollBoneToVector(ebone, vec, axis_only);
- }
- }
- }
-
- if (arm->flag & ARM_MIRROR_EDIT) {
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if ((EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) == 0) {
- EditBone *ebone_mirr = ED_armature_bone_get_mirrored(arm->edbo, ebone);
- if (ebone_mirr && (EBONE_VISIBLE(arm, ebone_mirr) && EBONE_EDITABLE(ebone_mirr))) {
- ebone->roll = -ebone_mirr->roll;
- }
- }
- }
- }
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_calculate_roll(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Recalculate Roll";
- ot->idname = "ARMATURE_OT_calculate_roll";
- ot->description = "Automatically fix alignment of select bones' axes";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = armature_calc_roll_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_calc_roll_types, 0, "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");
-}
-
-/* **************** undo for armatures ************** */
-
-typedef struct UndoArmature {
- EditBone *act_edbone;
- ListBase lb;
-} UndoArmature;
-
-static void undoBones_to_editBones(void *uarmv, void *armv, void *UNUSED(data))
-{
- UndoArmature *uarm = uarmv;
- bArmature *arm = armv;
- EditBone *ebo, *newebo;
-
- BLI_freelistN(arm->edbo);
-
- /* copy */
- for (ebo = uarm->lb.first; ebo; ebo = ebo->next) {
- newebo = MEM_dupallocN(ebo);
- ebo->temp = newebo;
- BLI_addtail(arm->edbo, newebo);
- }
-
- /* active bone */
- if (uarm->act_edbone) {
- ebo = uarm->act_edbone;
- arm->act_edbone = ebo->temp;
- }
- else
- arm->act_edbone = NULL;
-
- /* set pointers */
- for (newebo = arm->edbo->first; newebo; newebo = newebo->next) {
- if (newebo->parent) newebo->parent = newebo->parent->temp;
- }
- /* be sure they don't hang ever */
- for (newebo = arm->edbo->first; newebo; newebo = newebo->next) {
- newebo->temp = NULL;
- }
-}
-
-static void *editBones_to_undoBones(void *armv, void *UNUSED(obdata))
-{
- bArmature *arm = armv;
- UndoArmature *uarm;
- EditBone *ebo, *newebo;
-
- uarm = MEM_callocN(sizeof(UndoArmature), "listbase undo");
-
- /* copy */
- for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
- newebo = MEM_dupallocN(ebo);
- ebo->temp = newebo;
- BLI_addtail(&uarm->lb, newebo);
- }
-
- /* active bone */
- if (arm->act_edbone) {
- ebo = arm->act_edbone;
- uarm->act_edbone = ebo->temp;
- }
-
- /* set pointers */
- for (newebo = uarm->lb.first; newebo; newebo = newebo->next) {
- if (newebo->parent) newebo->parent = newebo->parent->temp;
- }
-
- return uarm;
-}
-
-static void free_undoBones(void *uarmv)
-{
- UndoArmature *uarm = uarmv;
-
- BLI_freelistN(&uarm->lb);
- MEM_freeN(uarm);
-}
-
-static void *get_armature_edit(bContext *C)
-{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_ARMATURE) {
- return obedit->data;
- }
- return NULL;
-}
-
-/* and this is all the undo system needs to know */
-void undo_push_armature(bContext *C, const char *name)
-{
- // XXX solve getdata()
- undo_editmode_push(C, name, get_armature_edit, free_undoBones, undoBones_to_editBones, editBones_to_undoBones, NULL);
-}
-
-
-
-/* **************** END EditMode stuff ********************** */
-/* *************** Adding stuff in editmode *************** */
-
-/* default bone add, returns it selected, but without tail set */
-EditBone *ED_armature_edit_bone_add(bArmature *arm, const char *name)
-{
- EditBone *bone = MEM_callocN(sizeof(EditBone), "eBone");
-
- BLI_strncpy(bone->name, name, sizeof(bone->name));
- unique_editbone_name(arm->edbo, bone->name, NULL);
-
- BLI_addtail(arm->edbo, bone);
-
- bone->flag |= BONE_TIPSEL;
- bone->weight = 1.0f;
- bone->dist = 0.25f;
- bone->xwidth = 0.1f;
- bone->zwidth = 0.1f;
- bone->ease1 = 1.0f;
- bone->ease2 = 1.0f;
- bone->rad_head = 0.10f;
- bone->rad_tail = 0.05f;
- bone->segments = 1;
- bone->layer = arm->layer;
-
- return bone;
-}
-
-/* v3d and rv3d are allowed to be NULL */
-void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d)
-{
- Object *obedit = scene->obedit; // XXX get from context
- bArmature *arm = obedit->data;
- float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
- EditBone *bone;
-
- /* Get inverse point for head and orientation for tail */
- invert_m4_m4(obedit->imat, obedit->obmat);
- mul_v3_m4v3(curs, obedit->imat, give_cursor(scene, v3d));
-
- if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
- copy_m3_m4(obmat, rv3d->viewmat);
- else unit_m3(obmat);
-
- copy_m3_m4(viewmat, obedit->obmat);
- mul_m3_m3m3(totmat, obmat, viewmat);
- invert_m3_m3(imat, totmat);
-
- ED_armature_deselect_all(obedit, 0);
-
- /* Create a bone */
- bone = ED_armature_edit_bone_add(arm, "Bone");
-
- arm->act_edbone = bone;
-
- copy_v3_v3(bone->head, curs);
-
- if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
- add_v3_v3v3(bone->tail, bone->head, imat[1]); // bone with unit length 1
- else
- add_v3_v3v3(bone->tail, bone->head, imat[2]); // bone with unit length 1, pointing up Z
-}
-
-
-/* previously addvert_armature */
-/* the ctrl-click method */
-static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
-{
- View3D *v3d;
- bArmature *arm;
- EditBone *ebone, *newbone, *flipbone;
- float *curs, mat[3][3], imat[3][3];
- int a, to_root = 0;
- Object *obedit;
- Scene *scene;
-
- scene = CTX_data_scene(C);
- v3d = CTX_wm_view3d(C);
- obedit = CTX_data_edit_object(C);
- arm = obedit->data;
-
- /* find the active or selected bone */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone)) {
- if (ebone->flag & BONE_TIPSEL || arm->act_edbone == ebone)
- break;
- }
- }
-
- if (ebone == NULL) {
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone)) {
- if (ebone->flag & BONE_ROOTSEL || arm->act_edbone == ebone)
- break;
- }
- }
- if (ebone == NULL)
- return OPERATOR_CANCELLED;
-
- to_root = 1;
- }
-
- ED_armature_deselect_all(obedit, 0);
-
- /* we re-use code for mirror editing... */
- flipbone = NULL;
- if (arm->flag & ARM_MIRROR_EDIT)
- flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone);
-
- for (a = 0; a < 2; a++) {
- if (a == 1) {
- if (flipbone == NULL)
- break;
- else {
- SWAP(EditBone *, flipbone, ebone);
- }
- }
-
- newbone = ED_armature_edit_bone_add(arm, ebone->name);
- arm->act_edbone = newbone;
-
- if (to_root) {
- copy_v3_v3(newbone->head, ebone->head);
- newbone->rad_head = ebone->rad_tail;
- newbone->parent = ebone->parent;
- }
- else {
- copy_v3_v3(newbone->head, ebone->tail);
- newbone->rad_head = ebone->rad_tail;
- newbone->parent = ebone;
- newbone->flag |= BONE_CONNECTED;
- }
-
- curs = give_cursor(scene, v3d);
- copy_v3_v3(newbone->tail, curs);
- sub_v3_v3v3(newbone->tail, newbone->tail, obedit->obmat[3]);
-
- if (a == 1)
- newbone->tail[0] = -newbone->tail[0];
-
- copy_m3_m4(mat, obedit->obmat);
- invert_m3_m3(imat, mat);
- mul_m3_v3(imat, newbone->tail);
-
- newbone->length = len_v3v3(newbone->head, newbone->tail);
- newbone->rad_tail = newbone->length * 0.05f;
- newbone->dist = newbone->length * 0.25f;
-
- }
-
- ED_armature_sync_selection(arm->edbo);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
-
- return OPERATOR_FINISHED;
-}
-
-static int armature_click_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
- /* TODO most of this code is copied from set3dcursor_invoke,
- * it would be better to reuse code in set3dcursor_invoke */
-
- /* temporarily change 3d cursor position */
- Scene *scene;
- ARegion *ar;
- View3D *v3d;
- float *fp = NULL, tvec[3], oldcurs[3], mval_f[2];
- int retv;
-
- scene = CTX_data_scene(C);
- ar = CTX_wm_region(C);
- v3d = CTX_wm_view3d(C);
-
- fp = give_cursor(scene, v3d);
-
- copy_v3_v3(oldcurs, fp);
-
- VECCOPY2D(mval_f, event->mval);
- ED_view3d_win_to_3d(ar, fp, mval_f, tvec);
- copy_v3_v3(fp, tvec);
-
- /* extrude to the where new cursor is and store the operation result */
- retv = armature_click_extrude_exec(C, op);
-
- /* restore previous 3d cursor position */
- copy_v3_v3(fp, oldcurs);
-
- return retv;
-}
-
-void ARMATURE_OT_click_extrude(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Click-Extrude";
- ot->idname = "ARMATURE_OT_click_extrude";
- ot->description = "Create a new bone going from the last selected joint to the mouse position";
-
- /* api callbacks */
- ot->invoke = armature_click_extrude_invoke;
- ot->exec = armature_click_extrude_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
-}
-
-/* adds an EditBone between the nominated locations (should be in the right space) */
-static EditBone *add_points_bone(Object *obedit, float head[], float tail[])
-{
- EditBone *ebo;
-
- ebo = ED_armature_edit_bone_add(obedit->data, "Bone");
-
- copy_v3_v3(ebo->head, head);
- copy_v3_v3(ebo->tail, tail);
-
- return ebo;
-}
-
-
-static EditBone *get_named_editbone(ListBase *edbo, char *name)
-{
- EditBone *eBone;
-
- if (name) {
- for (eBone = edbo->first; eBone; eBone = eBone->next) {
- if (!strcmp(name, eBone->name))
- return eBone;
- }
- }
-
- return NULL;
-}
-
-/* Call this before doing any duplications
- * */
-void preEditBoneDuplicate(ListBase *editbones)
-{
- EditBone *eBone;
-
- /* clear temp */
- for (eBone = editbones->first; eBone; eBone = eBone->next) {
- eBone->temp = NULL;
- }
-}
-
-/*
- * Note: When duplicating cross objects, editbones here is the list of bones
- * from the SOURCE object but ob is the DESTINATION object
- * */
-void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Object *src_ob, Object *dst_ob)
-{
- /* If an edit bone has been duplicated, lets
- * update it's constraints if the subtarget
- * they point to has also been duplicated
- */
- EditBone *oldtarget, *newtarget;
- bPoseChannel *pchan;
- bConstraint *curcon;
- ListBase *conlist;
-
- if ( (pchan = BKE_pose_channel_verify(dst_ob->pose, dupBone->name)) ) {
- if ( (conlist = &pchan->constraints) ) {
- for (curcon = conlist->first; curcon; curcon = curcon->next) {
- /* does this constraint have a subtarget in
- * this armature?
- */
- bConstraintTypeInfo *cti = constraint_get_typeinfo(curcon);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(curcon, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if ((ct->tar == src_ob) && (ct->subtarget[0])) {
- ct->tar = dst_ob; /* update target */
- oldtarget = get_named_editbone(editbones, ct->subtarget);
- if (oldtarget) {
- /* was the subtarget bone duplicated too? If
- * so, update the constraint to point at the
- * duplicate of the old subtarget.
- */
- if (oldtarget->temp) {
- newtarget = (EditBone *) oldtarget->temp;
- BLI_strncpy(ct->subtarget, newtarget->name, sizeof(ct->subtarget));
- }
- }
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(curcon, &targets, 0);
- }
- }
- }
- }
-}
-
-void updateDuplicateSubtarget(EditBone *dupBone, ListBase *editbones, Object *ob)
-{
- updateDuplicateSubtargetObjects(dupBone, editbones, ob, ob);
-}
-
-
-EditBone *duplicateEditBoneObjects(EditBone *curBone, const char *name, ListBase *editbones,
- Object *src_ob, Object *dst_ob)
-{
- EditBone *eBone = MEM_mallocN(sizeof(EditBone), "addup_editbone");
-
- /* Copy data from old bone to new bone */
- memcpy(eBone, curBone, sizeof(EditBone));
-
- curBone->temp = eBone;
- eBone->temp = curBone;
-
- if (name != NULL) {
- BLI_strncpy(eBone->name, name, sizeof(eBone->name));
- }
-
- unique_editbone_name(editbones, eBone->name, NULL);
- BLI_addtail(editbones, eBone);
-
- /* copy the ID property */
- if (curBone->prop)
- eBone->prop = IDP_CopyProperty(curBone->prop);
-
- /* Lets duplicate the list of constraints that the
- * current bone has.
- */
- if (src_ob->pose) {
- bPoseChannel *chanold, *channew;
-
- chanold = BKE_pose_channel_verify(src_ob->pose, curBone->name);
- if (chanold) {
- /* WARNING: this creates a new posechannel, but there will not be an attached bone
- * yet as the new bones created here are still 'EditBones' not 'Bones'.
- */
- channew = BKE_pose_channel_verify(dst_ob->pose, eBone->name);
-
- if (channew) {
- BKE_pose_channel_copy_data(channew, chanold);
- }
- }
- }
-
- return eBone;
-}
-
-EditBone *duplicateEditBone(EditBone *curBone, const char *name, ListBase *editbones, Object *ob)
-{
- 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 */
-
- Object *obedit = CTX_data_edit_object(C);
- 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 */
- 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;
- }
- }
- }
- }
-
-
- /* 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;
-
- }
- }
- }
-
- /* 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
- */
- 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;
- }
-
- /* 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);
- }
-
- ED_armature_validate_active(arm);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
-
- return OPERATOR_FINISHED;
-}
-
-
-void ARMATURE_OT_duplicate(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Duplicate Selected Bone(s)";
- ot->idname = "ARMATURE_OT_duplicate";
- ot->description = "Make copies of the selected bones within the same armature";
-
- /* api callbacks */
- ot->exec = armature_duplicate_selected_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-
-/* *************** END Adding stuff in editmode *************** */
-/* ************** Add/Remove stuff in editmode **************** */
-
-/* temporary data-structure for merge/fill bones */
-typedef struct EditBonePoint {
- struct EditBonePoint *next, *prev;
-
- EditBone *head_owner; /* EditBone which uses this point as a 'head' point */
- EditBone *tail_owner; /* EditBone which uses this point as a 'tail' point */
-
- float vec[3]; /* the actual location of the point in local/EditMode space */
-} EditBonePoint;
-
-/* find chain-tips (i.e. bones without children) */
-static void chains_find_tips(ListBase *edbo, ListBase *list)
-{
- EditBone *curBone, *ebo;
- LinkData *ld;
-
- /* note: this is potentially very slow ... there's got to be a better way */
- for (curBone = edbo->first; curBone; curBone = curBone->next) {
- short stop = 0;
-
- /* is this bone contained within any existing chain? (skip if so) */
- for (ld = list->first; ld; ld = ld->next) {
- for (ebo = ld->data; ebo; ebo = ebo->parent) {
- if (ebo == curBone) {
- stop = 1;
- break;
- }
- }
-
- if (stop) break;
- }
- /* skip current bone if it is part of an existing chain */
- if (stop) continue;
-
- /* is any existing chain part of the chain formed by this bone? */
- stop = 0;
- for (ebo = curBone->parent; ebo; ebo = ebo->parent) {
- for (ld = list->first; ld; ld = ld->next) {
- if (ld->data == ebo) {
- ld->data = curBone;
- stop = 1;
- break;
- }
- }
-
- if (stop) break;
- }
- /* current bone has already been added to a chain? */
- if (stop) continue;
-
- /* add current bone to a new chain */
- ld = MEM_callocN(sizeof(LinkData), "BoneChain");
- ld->data = curBone;
- BLI_addtail(list, ld);
- }
-}
-
-/* --------------------- */
-
-static void fill_add_joint(EditBone *ebo, short eb_tail, ListBase *points)
-{
- EditBonePoint *ebp;
- float vec[3];
- short found = 0;
-
- if (eb_tail) {
- copy_v3_v3(vec, ebo->tail);
- }
- else {
- copy_v3_v3(vec, ebo->head);
- }
-
- for (ebp = points->first; ebp; ebp = ebp->next) {
- if (equals_v3v3(ebp->vec, vec)) {
- if (eb_tail) {
- if ((ebp->head_owner) && (ebp->head_owner->parent == ebo)) {
- /* so this bone's tail owner is this bone */
- ebp->tail_owner = ebo;
- found = 1;
- break;
- }
- }
- else {
- if ((ebp->tail_owner) && (ebo->parent == ebp->tail_owner)) {
- /* so this bone's head owner is this bone */
- ebp->head_owner = ebo;
- found = 1;
- break;
- }
- }
- }
- }
-
- /* allocate a new point if no existing point was related */
- if (found == 0) {
- ebp = MEM_callocN(sizeof(EditBonePoint), "EditBonePoint");
-
- if (eb_tail) {
- copy_v3_v3(ebp->vec, ebo->tail);
- ebp->tail_owner = ebo;
- }
- else {
- copy_v3_v3(ebp->vec, ebo->head);
- ebp->head_owner = ebo;
- }
-
- BLI_addtail(points, ebp);
- }
-}
-
-/* bone adding between selected joints */
-static int armature_fill_bones_exec(bContext *C, wmOperator *op)
-{
- Object *obedit = CTX_data_edit_object(C);
- bArmature *arm = (obedit) ? obedit->data : NULL;
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- ListBase points = {NULL, NULL};
- int count;
-
- /* sanity checks */
- if (ELEM(NULL, obedit, arm))
- return OPERATOR_CANCELLED;
-
- /* loop over all bones, and only consider if visible */
- CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
- {
- if (!(ebone->flag & BONE_CONNECTED) && (ebone->flag & BONE_ROOTSEL))
- fill_add_joint(ebone, 0, &points);
- if (ebone->flag & BONE_TIPSEL)
- fill_add_joint(ebone, 1, &points);
- }
- CTX_DATA_END;
-
- /* the number of joints determines how we fill:
- * 1) between joint and cursor (joint=head, cursor=tail)
- * 2) between the two joints (order is dependent on active-bone/hierachy)
- * 3+) error (a smarter method involving finding chains needs to be worked out
- */
- count = BLI_countlist(&points);
-
- if (count == 0) {
- BKE_report(op->reports, RPT_ERROR, "No joints selected");
- return OPERATOR_CANCELLED;
- }
- else if (count == 1) {
- EditBonePoint *ebp;
- float curs[3];
-
- /* Get Points - selected joint */
- ebp = (EditBonePoint *)points.first;
-
- /* Get points - cursor (tail) */
- invert_m4_m4(obedit->imat, obedit->obmat);
- mul_v3_m4v3(curs, obedit->imat, give_cursor(scene, v3d));
-
- /* Create a bone */
- /* newbone = */ add_points_bone(obedit, ebp->vec, curs);
- }
- else if (count == 2) {
- EditBonePoint *ebp, *ebp2;
- 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;
-
- 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)) {
- 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, give_cursor(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;
- }
- else if (ebp->head_owner) {
- headtail = 1;
- }
- else if (ebp2->head_owner) {
- headtail = 2;
- }
-
- /* assign head/tail combinations */
- if (headtail == 2) {
- copy_v3_v3(head, ebp->vec);
- copy_v3_v3(tail, ebp2->vec);
- }
- else if (headtail == 1) {
- copy_v3_v3(head, ebp2->vec);
- copy_v3_v3(tail, ebp->vec);
- }
-
- /* add new bone and parent it to the appropriate end */
- if (headtail) {
- EditBone *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;
- else
- newbone->parent = ebp->head_owner;
- }
- else {
- /* ebp2 tail or head - tail gets priority */
- if (ebp2->tail_owner)
- newbone->parent = ebp2->tail_owner;
- else
- newbone->parent = ebp2->head_owner;
- }
-
- newbone->flag |= BONE_CONNECTED;
- }
- }
- else {
- /* FIXME.. figure out a method for multiple bones */
- BKE_reportf(op->reports, RPT_ERROR, "Too many points selected: %d", count);
- BLI_freelistN(&points);
- return OPERATOR_CANCELLED;
- }
-
- /* updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
-
- /* free points */
- BLI_freelistN(&points);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_fill(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Fill Between Joints";
- ot->idname = "ARMATURE_OT_fill";
- ot->description = "Add bone between selected joint(s) and/or 3D-Cursor";
-
- /* callbacks */
- ot->exec = armature_fill_bones_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* --------------------- */
-
-/* this function merges between two bones, removes them and those in-between,
- * and adjusts the parent relationships for those in-between
- */
-static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone *endchild, ListBase *chains)
-{
- bArmature *arm = obedit->data;
- EditBone *ebo, *ebone, *newbone;
- LinkData *chain;
- float head[3], tail[3];
-
- /* check if same bone */
- if (start == end) {
- if (G.debug & G_DEBUG) {
- printf("Error: same bone!\n");
- printf("\tstart = %s, end = %s\n", start->name, end->name);
- }
- }
-
- /* step 1: add a new bone
- * - head = head/tail of start (default head)
- * - tail = head/tail of end (default tail)
- * - parent = parent of start
- */
- if ((start->flag & BONE_TIPSEL) && (start->flag & BONE_SELECTED) == 0) {
- copy_v3_v3(head, start->tail);
- }
- else {
- copy_v3_v3(head, start->head);
- }
- if ((end->flag & BONE_ROOTSEL) && (end->flag & BONE_SELECTED) == 0) {
- copy_v3_v3(tail, end->head);
- }
- else {
- copy_v3_v3(tail, end->tail);
- }
- newbone = add_points_bone(obedit, head, tail);
- newbone->parent = start->parent;
-
- /* TODO, copy more things to the new bone */
- newbone->flag = start->flag & (BONE_HINGE | BONE_NO_DEFORM | BONE_NO_SCALE |
- BONE_NO_CYCLICOFFSET | BONE_NO_LOCAL_LOCATION | BONE_DONE);
-
- /* step 2a: reparent any side chains which may be parented to any bone in the chain of bones to merge
- * - potentially several tips for side chains leading to some tree exist...
- */
- for (chain = chains->first; chain; chain = chain->next) {
- /* traverse down chain until we hit the bottom or if we run into the tip of the chain of bones we're
- * merging (need to stop in this case to avoid corrupting this chain too!)
- */
- for (ebone = chain->data; (ebone) && (ebone != end); ebone = ebone->parent) {
- short found = 0;
-
- /* check if this bone is parented to one in the merging chain
- * ! WATCHIT: must only go check until end of checking chain
- */
- for (ebo = end; (ebo) && (ebo != start->parent); ebo = ebo->parent) {
- /* side-chain found? --> remap parent to new bone, then we're done with this chain :) */
- if (ebone->parent == ebo) {
- ebone->parent = newbone;
- found = 1;
- break;
- }
- }
-
- /* carry on to the next tip now */
- if (found)
- break;
- }
- }
-
- /* step 2b: parent child of end to newbone (child from this chain) */
- if (endchild)
- endchild->parent = newbone;
-
- /* step 3: delete all bones between and including start and end */
- for (ebo = end; ebo; ebo = ebone) {
- ebone = (ebo == start) ? (NULL) : (ebo->parent);
- bone_free(arm, ebo);
- }
-
- newbone->flag |= (BONE_ROOTSEL | BONE_TIPSEL | BONE_SELECTED);
- ED_armature_sync_selection(arm->edbo);
-}
-
-
-static int armature_merge_exec(bContext *C, wmOperator *op)
-{
- Object *obedit = CTX_data_edit_object(C);
- bArmature *arm = (obedit) ? obedit->data : NULL;
- short type = RNA_enum_get(op->ptr, "type");
-
- /* sanity checks */
- if (ELEM(NULL, obedit, arm))
- return OPERATOR_CANCELLED;
-
- /* for now, there's only really one type of merging that's performed... */
- if (type == 1) {
- /* go down chains, merging bones */
- ListBase chains = {NULL, NULL};
- LinkData *chain, *nchain;
- EditBone *ebo;
-
- armature_tag_select_mirrored(arm);
-
- /* get chains (ends on chains) */
- chains_find_tips(arm->edbo, &chains);
- if (chains.first == NULL) return OPERATOR_CANCELLED;
-
- /* each 'chain' is the last bone in the chain (with no children) */
- for (chain = chains.first; chain; chain = nchain) {
- EditBone *bstart = NULL, *bend = NULL;
- EditBone *bchild = NULL, *child = NULL;
-
- /* temporarily remove chain from list of chains */
- nchain = chain->next;
- BLI_remlink(&chains, chain);
-
- /* only consider bones that are visible and selected */
- for (ebo = chain->data; ebo; child = ebo, ebo = ebo->parent) {
- /* check if visible + selected */
- if (EBONE_VISIBLE(arm, ebo) &&
- ((ebo->flag & BONE_CONNECTED) || (ebo->parent == NULL)) &&
- (ebo->flag & BONE_SELECTED) )
- {
- /* set either end or start (end gets priority, unless it is already set) */
- if (bend == NULL) {
- bend = ebo;
- bchild = child;
- }
- else
- bstart = ebo;
- }
- else {
- /* chain is broken... merge any continous segments then clear */
- if (bstart && bend)
- bones_merge(obedit, bstart, bend, bchild, &chains);
-
- bstart = NULL;
- bend = NULL;
- bchild = NULL;
- }
- }
-
- /* merge from bstart to bend if something not merged */
- if (bstart && bend)
- bones_merge(obedit, bstart, bend, bchild, &chains);
-
- /* put back link */
- BLI_insertlinkbefore(&chains, nchain, chain);
- }
-
- armature_tag_unselect(arm);
-
- BLI_freelistN(&chains);
- }
-
- /* updates */
- ED_armature_sync_selection(arm->edbo);
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_merge(wmOperatorType *ot)
-{
- static EnumPropertyItem merge_types[] = {
- {1, "WITHIN_CHAIN", 0, "Within Chains", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- /* identifiers */
- ot->name = "Merge Bones";
- ot->idname = "ARMATURE_OT_merge";
- ot->description = "Merge continuous chains of selected bones";
-
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = armature_merge_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", merge_types, 0, "Type", "");
-}
-
-/* ************** END Add/Remove stuff in editmode ************ */
-/* *************** Tools in editmode *********** */
-
-static int armature_hide_exec(bContext *C, wmOperator *op)
-{
- Object *obedit = CTX_data_edit_object(C);
- bArmature *arm = obedit->data;
- EditBone *ebone;
- const int invert = RNA_boolean_get(op->ptr, "unselected") ? BONE_SELECTED : 0;
-
- /* cancel if nothing selected */
- if (CTX_DATA_COUNT(C, selected_bones) == 0)
- return OPERATOR_CANCELLED;
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone)) {
- if ((ebone->flag & BONE_SELECTED) != invert) {
- ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
- ebone->flag |= BONE_HIDDEN_A;
- }
- }
- }
- ED_armature_validate_active(arm);
- ED_armature_sync_selection(arm->edbo);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_hide(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Hide Selected Bones";
- ot->idname = "ARMATURE_OT_hide";
- ot->description = "Tag selected bones to not be visible in Edit Mode";
-
- /* api callbacks */
- ot->exec = armature_hide_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
-}
-
-static int armature_reveal_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *obedit = CTX_data_edit_object(C);
- bArmature *arm = obedit->data;
- EditBone *ebone;
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (arm->layer & ebone->layer) {
- if (ebone->flag & BONE_HIDDEN_A) {
- ebone->flag |= (BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
- ebone->flag &= ~BONE_HIDDEN_A;
- }
- }
- }
- ED_armature_validate_active(arm);
- ED_armature_sync_selection(arm->edbo);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_reveal(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Reveal Bones";
- ot->idname = "ARMATURE_OT_reveal";
- ot->description = "Unhide all bones that have been tagged to be hidden in Edit Mode";
-
- /* api callbacks */
- ot->exec = armature_reveal_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
-}
-#if 0 // remove this?
-static void hide_selected_armature_bones(Scene *scene)
-{
- Object *obedit = scene->obedit; // XXX get from context
- bArmature *arm = obedit->data;
- EditBone *ebone;
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone)) {
- if (ebone->flag & BONE_SELECTED) {
- ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
- ebone->flag |= BONE_HIDDEN_A;
- }
- }
- }
- ED_armature_validate_active(arm);
- ED_armature_sync_selection(arm->edbo);
-}
-
-static void hide_unselected_armature_bones(Scene *scene)
-{
- Object *obedit = scene->obedit; // XXX get from context
- bArmature *arm = obedit->data;
- EditBone *ebone;
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- bArmature *arm = obedit->data;
- if (EBONE_VISIBLE(arm, ebone)) {
- if (ebone->flag & (BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL)) {
- /* pass */
- }
- else {
- ebone->flag |= BONE_HIDDEN_A;
- }
- }
- }
-
- ED_armature_validate_active(arm);
- ED_armature_sync_selection(arm->edbo);
-}
-
-void show_all_armature_bones(Scene *scene)
-{
- Object *obedit = scene->obedit; // XXX get from context
- bArmature *arm = obedit->data;
- EditBone *ebone;
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (arm->layer & ebone->layer) {
- if (ebone->flag & BONE_HIDDEN_A) {
- ebone->flag |= (BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
- ebone->flag &= ~BONE_HIDDEN_A;
- }
- }
- }
- ED_armature_validate_active(arm);
- ED_armature_sync_selection(arm->edbo);
-}
-#endif
-
-/* previously extrude_armature */
-/* context; editmode armature */
-/* if forked && mirror-edit: makes two bones with flipped names */
-static int armature_extrude_exec(bContext *C, wmOperator *op)
-{
- Object *obedit;
- bArmature *arm;
- EditBone *newbone, *ebone, *flipbone, *first = NULL;
- int a, totbone = 0, do_extrude;
- int forked = RNA_boolean_get(op->ptr, "forked");
-
- obedit = CTX_data_edit_object(C);
- arm = obedit->data;
-
- /* since we allow root extrude too, we have to make sure selection is OK */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone)) {
- if (ebone->flag & BONE_ROOTSEL) {
- if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
- if (ebone->parent->flag & BONE_TIPSEL)
- ebone->flag &= ~BONE_ROOTSEL;
- }
- }
- }
- }
-
- /* Duplicate the necessary bones */
- for (ebone = arm->edbo->first; ((ebone) && (ebone != first)); ebone = ebone->next) {
- if (EBONE_VISIBLE(arm, ebone)) {
- /* we extrude per definition the tip */
- do_extrude = FALSE;
- if (ebone->flag & (BONE_TIPSEL | BONE_SELECTED)) {
- do_extrude = TRUE;
- }
- else if (ebone->flag & BONE_ROOTSEL) {
- /* but, a bone with parent deselected we do the root... */
- if (ebone->parent && (ebone->parent->flag & BONE_TIPSEL)) {
- /* pass */
- }
- else {
- do_extrude = 2;
- }
- }
-
- if (do_extrude) {
- /* we re-use code for mirror editing... */
- flipbone = NULL;
- if (arm->flag & ARM_MIRROR_EDIT) {
- flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone);
- if (flipbone) {
- forked = 0; // we extrude 2 different bones
- if (flipbone->flag & (BONE_TIPSEL | BONE_ROOTSEL | BONE_SELECTED))
- /* don't want this bone to be selected... */
- flipbone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
- }
- if ((flipbone == NULL) && (forked))
- flipbone = ebone;
- }
-
- for (a = 0; a < 2; a++) {
- if (a == 1) {
- if (flipbone == NULL)
- break;
- else {
- SWAP(EditBone *, flipbone, ebone);
- }
- }
-
- totbone++;
- newbone = MEM_callocN(sizeof(EditBone), "extrudebone");
-
- if (do_extrude == TRUE) {
- copy_v3_v3(newbone->head, ebone->tail);
- copy_v3_v3(newbone->tail, newbone->head);
- newbone->parent = ebone;
-
- newbone->flag = ebone->flag & BONE_TIPSEL; // copies it, in case mirrored bone
-
- if (newbone->parent) newbone->flag |= BONE_CONNECTED;
- }
- else {
- copy_v3_v3(newbone->head, ebone->head);
- copy_v3_v3(newbone->tail, ebone->head);
- newbone->parent = ebone->parent;
-
- newbone->flag = BONE_TIPSEL;
-
- if (newbone->parent && (ebone->flag & BONE_CONNECTED)) {
- newbone->flag |= BONE_CONNECTED;
- }
- }
-
- newbone->weight = ebone->weight;
- newbone->dist = ebone->dist;
- newbone->xwidth = ebone->xwidth;
- newbone->zwidth = ebone->zwidth;
- newbone->ease1 = ebone->ease1;
- newbone->ease2 = ebone->ease2;
- newbone->rad_head = ebone->rad_tail; // don't copy entire bone...
- newbone->rad_tail = ebone->rad_tail;
- newbone->segments = 1;
- newbone->layer = ebone->layer;
-
- BLI_strncpy(newbone->name, ebone->name, sizeof(newbone->name));
-
- if (flipbone && forked) { // only set if mirror edit
- if (strlen(newbone->name) < 30) {
- if (a == 0) strcat(newbone->name, "_L");
- else strcat(newbone->name, "_R");
- }
- }
- unique_editbone_name(arm->edbo, newbone->name, NULL);
-
- /* Add the new bone to the list */
- BLI_addtail(arm->edbo, newbone);
- if (!first)
- first = newbone;
-
- /* restore ebone if we were flipping */
- if (a == 1 && flipbone)
- SWAP(EditBone *, flipbone, ebone);
- }
- }
-
- /* Deselect the old bone */
- ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
- }
- }
- /* if only one bone, make this one active */
- if (totbone == 1 && first) arm->act_edbone = first;
-
- if (totbone == 0) return OPERATOR_CANCELLED;
-
- /* Transform the endpoints */
- ED_armature_sync_selection(arm->edbo);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_extrude(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Extrude";
- ot->idname = "ARMATURE_OT_extrude";
- ot->description = "Create new bones from the selected joints";
-
- /* api callbacks */
- ot->exec = armature_extrude_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- RNA_def_boolean(ot->srna, "forked", 0, "Forked", "");
-}
-/* ********************** Bone Add ********************/
-
-/*op makes a new bone and returns it with its tip selected */
-
-static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
-{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- Object *obedit = CTX_data_edit_object(C);
- EditBone *bone;
- float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
- char name[MAXBONENAME];
-
- RNA_string_get(op->ptr, "name", name);
-
- copy_v3_v3(curs, give_cursor(CTX_data_scene(C), CTX_wm_view3d(C)));
-
- /* Get inverse point for head and orientation for tail */
- invert_m4_m4(obedit->imat, obedit->obmat);
- mul_m4_v3(obedit->imat, curs);
-
- if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
- copy_m3_m4(obmat, rv3d->viewmat);
- else unit_m3(obmat);
-
- copy_m3_m4(viewmat, obedit->obmat);
- mul_m3_m3m3(totmat, obmat, viewmat);
- invert_m3_m3(imat, totmat);
-
- ED_armature_deselect_all(obedit, 0);
-
- /* Create a bone */
- bone = ED_armature_edit_bone_add(obedit->data, name);
-
- copy_v3_v3(bone->head, curs);
-
- if (rv3d && (U.flag & USER_ADD_VIEWALIGNED))
- add_v3_v3v3(bone->tail, bone->head, imat[1]); // bone with unit length 1
- else
- add_v3_v3v3(bone->tail, bone->head, imat[2]); // bone with unit length 1, pointing up Z
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_bone_primitive_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Bone";
- ot->idname = "ARMATURE_OT_bone_primitive_add";
- ot->description = "Add a new bone located at the 3D-Cursor";
-
- /* api callbacks */
- ot->exec = armature_bone_primitive_add_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_string(ot->srna, "name", "Bone", MAXBONENAME, "Name", "Name of the newly created bone");
-
-}
-
-
-/* ----------- */
-
-/* Subdivide Operators:
- * This group of operators all use the same 'exec' callback, but they are called
- * through several different operators - a combined menu (which just calls the exec in the
- * appropriate ways), and two separate ones.
- */
-
-static int armature_subdivide_exec(bContext *C, wmOperator *op)
-{
- Object *obedit = CTX_data_edit_object(C);
- bArmature *arm = obedit->data;
- EditBone *newbone, *tbone;
- int cuts, i;
-
- /* there may not be a number_cuts property defined (for 'simple' subdivide) */
- cuts = RNA_int_get(op->ptr, "number_cuts");
-
- /* loop over all editable bones */
- // XXX the old code did this in reverse order though!
- CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
- {
- for (i = cuts + 1; i > 1; i--) {
- /* compute cut ratio first */
- float cutratio = 1.0f / (float)i;
- float cutratioI = 1.0f - cutratio;
-
- float val1[3];
- float val2[3];
- float val3[3];
-
- newbone = MEM_mallocN(sizeof(EditBone), "ebone subdiv");
- *newbone = *ebone;
- BLI_addtail(arm->edbo, newbone);
-
- /* calculate location of newbone->head */
- copy_v3_v3(val1, ebone->head);
- copy_v3_v3(val2, ebone->tail);
- copy_v3_v3(val3, newbone->head);
-
- val3[0] = val1[0] * cutratio + val2[0] * cutratioI;
- val3[1] = val1[1] * cutratio + val2[1] * cutratioI;
- val3[2] = val1[2] * cutratio + val2[2] * cutratioI;
-
- copy_v3_v3(newbone->head, val3);
- copy_v3_v3(newbone->tail, ebone->tail);
- copy_v3_v3(ebone->tail, newbone->head);
-
- newbone->rad_head = 0.5f * (ebone->rad_head + ebone->rad_tail);
- ebone->rad_tail = newbone->rad_head;
-
- newbone->flag |= BONE_CONNECTED;
-
- unique_editbone_name(arm->edbo, newbone->name, NULL);
-
- /* correct parent bones */
- for (tbone = arm->edbo->first; tbone; tbone = tbone->next) {
- if (tbone->parent == ebone)
- tbone->parent = newbone;
- }
- newbone->parent = ebone;
- }
- }
- CTX_DATA_END;
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_subdivide(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Subdivide Multi";
- ot->idname = "ARMATURE_OT_subdivide";
- ot->description = "Break selected bones into chains of smaller bones";
-
- /* api callbacks */
- ot->exec = armature_subdivide_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* Properties */
- prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, INT_MAX, "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);
-}
-
-/* ----------- */
-
-/* Switch Direction operator:
- * Currently, this does not use context loops, as context loops do not make it
- * easy to retrieve any hierarchical/chain relationships which are necessary for
- * this to be done easily.
- */
-
-static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = CTX_data_edit_object(C);
- bArmature *arm = (bArmature *)ob->data;
- ListBase chains = {NULL, NULL};
- LinkData *chain;
-
- /* get chains of bones (ends on chains) */
- chains_find_tips(arm->edbo, &chains);
- if (chains.first == NULL) return OPERATOR_CANCELLED;
-
- armature_tag_select_mirrored(arm);
-
- /* loop over chains, only considering selected and visible bones */
- for (chain = chains.first; chain; chain = chain->next) {
- EditBone *ebo, *child = NULL, *parent = NULL;
-
- /* loop over bones in chain */
- for (ebo = chain->data; ebo; ebo = parent) {
- /* parent is this bone's original parent
- * - we store this, as the next bone that is checked is this one
- * but the value of ebo->parent may change here...
- */
- parent = ebo->parent;
-
- /* 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]);
-
- /* do parent swapping:
- * - use 'child' as new parent
- * - connected flag is only set if points are coincidental
- */
- ebo->parent = child;
- if ((child) && equals_v3v3(ebo->head, child->tail))
- ebo->flag |= BONE_CONNECTED;
- else
- ebo->flag &= ~BONE_CONNECTED;
-
- /* get next bones
- * - child will become the new parent of next bone
- */
- child = ebo;
- }
- else {
- /* not swapping this bone, however, if its 'parent' got swapped, unparent us from it
- * as it will be facing in opposite direction
- */
- if ((parent) && (EBONE_VISIBLE(arm, parent) && EBONE_EDITABLE(parent))) {
- ebo->parent = NULL;
- ebo->flag &= ~BONE_CONNECTED;
- }
-
- /* get next bones
- * - child will become new parent of next bone (not swapping occurred,
- * so set to NULL to prevent infinite-loop)
- */
- child = NULL;
- }
- }
- }
-
- /* free chains */
- BLI_freelistN(&chains);
-
- armature_tag_unselect(arm);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_switch_direction(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Switch Direction";
- ot->idname = "ARMATURE_OT_switch_direction";
- ot->description = "Change the direction that a chain of bones points in (head <-> tail swap)";
-
- /* api callbacks */
- ot->exec = armature_switch_direction_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-/* ***************** Parenting *********************** */
-
-/* armature parenting options */
-#define ARM_PAR_CONNECT 1
-#define ARM_PAR_OFFSET 2
-
-/* check for null, before calling! */
-static void bone_connect_to_existing_parent(EditBone *bone)
-{
- bone->flag |= BONE_CONNECTED;
- copy_v3_v3(bone->head, bone->parent->tail);
- bone->rad_head = bone->parent->rad_tail;
-}
-
-static void bone_connect_to_new_parent(ListBase *edbo, EditBone *selbone, EditBone *actbone, short mode)
-{
- EditBone *ebone;
- float offset[3];
-
- if ((selbone->parent) && (selbone->flag & BONE_CONNECTED))
- selbone->parent->flag &= ~(BONE_TIPSEL);
-
- /* make actbone the parent of selbone */
- selbone->parent = actbone;
-
- /* in actbone tree we cannot have a loop */
- for (ebone = actbone->parent; ebone; ebone = ebone->parent) {
- if (ebone->parent == selbone) {
- ebone->parent = NULL;
- ebone->flag &= ~BONE_CONNECTED;
- }
- }
-
- if (mode == ARM_PAR_CONNECT) {
- /* Connected: Child bones will be moved to the parent tip */
- selbone->flag |= BONE_CONNECTED;
- sub_v3_v3v3(offset, actbone->tail, selbone->head);
-
- copy_v3_v3(selbone->head, actbone->tail);
- selbone->rad_head = actbone->rad_tail;
-
- add_v3_v3(selbone->tail, offset);
-
- /* offset for all its children */
- for (ebone = edbo->first; ebone; ebone = ebone->next) {
- EditBone *par;
-
- for (par = ebone->parent; par; par = par->parent) {
- if (par == selbone) {
- add_v3_v3(ebone->head, offset);
- add_v3_v3(ebone->tail, offset);
- break;
- }
- }
- }
- }
- else {
- /* Offset: Child bones will retain their distance from the parent tip */
- selbone->flag &= ~BONE_CONNECTED;
- }
-}
-
-static EnumPropertyItem prop_editarm_make_parent_types[] = {
- {ARM_PAR_CONNECT, "CONNECTED", 0, "Connected", ""},
- {ARM_PAR_OFFSET, "OFFSET", 0, "Keep Offset", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-static int armature_parent_set_exec(bContext *C, wmOperator *op)
-{
- Object *ob = CTX_data_edit_object(C);
- bArmature *arm = (bArmature *)ob->data;
- EditBone *actbone = CTX_data_active_bone(C);
- EditBone *actmirb = NULL;
- short val = RNA_enum_get(op->ptr, "type");
-
- /* there must be an active bone */
- if (actbone == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
- return OPERATOR_CANCELLED;
- }
- else if (arm->flag & ARM_MIRROR_EDIT) {
- /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
- * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone
- * (i.e. selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
- * This is useful for arm-chains, for example parenting lower arm to upper arm
- * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
- * then just use actbone. Useful when doing upper arm to spine.
- */
- actmirb = ED_armature_bone_get_mirrored(arm->edbo, actbone);
- if (actmirb == NULL)
- actmirb = actbone;
- }
-
- /* if there is only 1 selected bone, we assume that that is the active bone,
- * since a user will need to have clicked on a bone (thus selecting it) to make it active
- */
- if (CTX_DATA_COUNT(C, selected_editable_bones) <= 1) {
- /* When only the active bone is selected, and it has a parent,
- * connect it to the parent, as that is the only possible outcome.
- */
- if (actbone->parent) {
- bone_connect_to_existing_parent(actbone);
-
- if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
- bone_connect_to_existing_parent(actmirb);
- }
- }
- else {
- /* Parent 'selected' bones to the active one
- * - the context iterator contains both selected bones and their mirrored copies,
- * so we assume that unselected bones are mirrored copies of some selected bone
- * - since the active one (and/or its mirror) will also be selected, we also need
- * to check that we are not trying to operate on them, since such an operation
- * would cause errors
- */
-
- /* parent selected bones to the active one */
- CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
- {
- if (ELEM(ebone, actbone, actmirb) == 0) {
- if (ebone->flag & BONE_SELECTED)
- bone_connect_to_new_parent(arm->edbo, ebone, actbone, val);
- else
- bone_connect_to_new_parent(arm->edbo, ebone, actmirb, val);
- }
- }
- CTX_DATA_END;
- }
-
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
- return OPERATOR_FINISHED;
-}
-
-static int armature_parent_set_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
-{
- EditBone *actbone = CTX_data_active_bone(C);
- uiPopupMenu *pup = uiPupMenuBegin(C, "Make Parent ", ICON_NONE);
- uiLayout *layout = uiPupMenuLayout(pup);
- int allchildbones = 0;
-
- CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
- {
- if (ebone != actbone) {
- if (ebone->parent != actbone) allchildbones = 1;
- }
- }
- CTX_DATA_END;
-
- uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_CONNECT);
-
- /* ob becomes parent, make the associated menus */
- if (allchildbones)
- uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_OFFSET);
-
- uiPupMenuEnd(C, pup);
-
- return OPERATOR_CANCELLED;
-}
-
-void ARMATURE_OT_parent_set(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Make Parent";
- ot->idname = "ARMATURE_OT_parent_set";
- ot->description = "Set the active bone as the parent of the selected bones";
-
- /* api callbacks */
- ot->invoke = armature_parent_set_invoke;
- ot->exec = armature_parent_set_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "type", prop_editarm_make_parent_types, 0, "ParentType", "Type of parenting");
-}
-
-static EnumPropertyItem prop_editarm_clear_parent_types[] = {
- {1, "CLEAR", 0, "Clear Parent", ""},
- {2, "DISCONNECT", 0, "Disconnect Bone", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-static void editbone_clear_parent(EditBone *ebone, int mode)
-{
- if (ebone->parent) {
- /* for nice selection */
- ebone->parent->flag &= ~(BONE_TIPSEL);
- }
-
- if (mode == 1) ebone->parent = NULL;
- ebone->flag &= ~BONE_CONNECTED;
-}
-
-static int armature_parent_clear_exec(bContext *C, wmOperator *op)
-{
- Object *ob = CTX_data_edit_object(C);
- bArmature *arm = (bArmature *)ob->data;
- int val = RNA_enum_get(op->ptr, "type");
-
- CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
- {
- editbone_clear_parent(ebone, val);
- }
- CTX_DATA_END;
-
- ED_armature_sync_selection(arm->edbo);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_parent_clear(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Clear Parent";
- ot->idname = "ARMATURE_OT_parent_clear";
- ot->description = "Remove the parent-child relationship between selected bones and their parents";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = armature_parent_clear_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ot->prop = RNA_def_enum(ot->srna, "type", prop_editarm_clear_parent_types, 0, "ClearType", "What way to clear parenting");
-}
-
-/* **************** Selections ******************/
-
-static int armature_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
-{
- /* Set the flags */
- CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
- {
- /* ignore bone if selection can't change */
- if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
- /* select bone */
- ebone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- }
- CTX_DATA_END;
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_select_inverse(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Inverse";
- ot->idname = "ARMATURE_OT_select_inverse";
- ot->description = "Flip the selection status of bones (selected -> unselected, unselected -> selected)";
-
- /* api callbacks */
- ot->exec = armature_select_inverse_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
-}
-static int armature_de_select_all_exec(bContext *C, wmOperator *op)
-{
- int action = RNA_enum_get(op->ptr, "action");
-
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
- /* Determine if there are any selected bones
- * And therefore whether we are selecting or deselecting */
- if (CTX_DATA_COUNT(C, selected_bones) > 0)
- action = SEL_DESELECT;
- }
-
- /* Set the flags */
- CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
- {
- /* ignore bone if selection can't change */
- if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
- switch (action) {
- case SEL_SELECT:
- ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- if (ebone->parent)
- ebone->parent->flag |= (BONE_TIPSEL);
- break;
- case SEL_DESELECT:
- ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- break;
- case SEL_INVERT:
- if (ebone->flag & BONE_SELECTED) {
- ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else {
- ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- if (ebone->parent)
- ebone->parent->flag |= (BONE_TIPSEL);
- }
- break;
- }
- }
- }
- CTX_DATA_END;
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_select_all(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "(De)select All";
- ot->idname = "ARMATURE_OT_select_all";
- ot->description = "Toggle selection status of all bones";
-
- /* api callbacks */
- ot->exec = armature_de_select_all_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- WM_operator_properties_select_all(ot);
-}
-
-enum {
- SIMEDBONE_LENGTH = 1,
- SIMEDBONE_DIRECTION,
- SIMEDBONE_PREFIX,
- SIMEDBONE_SUFFIX,
- SIMEDBONE_LAYER
-};
-
-static EnumPropertyItem prop_similar_types[] = {
- {SIMEDBONE_LENGTH, "LENGTH", 0, "Length", ""},
- {SIMEDBONE_DIRECTION, "DIRECTION", 0, "Direction (Y axis)", ""},
- {SIMEDBONE_PREFIX, "PREFIX", 0, "Prefix", ""},
- {SIMEDBONE_SUFFIX, "SUFFIX", 0, "Suffix", ""},
- {SIMEDBONE_LAYER, "LAYER", 0, "Layer", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-/* could be used in more places */
-static void ED_armature_edit_bone_select(EditBone *ebone)
-{
- BLI_assert((ebone->flag & BONE_UNSELECTABLE) == 0);
- ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
-
- if ((ebone->flag & BONE_CONNECTED) && (ebone->parent != NULL)) {
- ebone->parent->flag |= BONE_TIPSEL;
- }
-}
-
-static void select_similar_length(bArmature *arm, EditBone *ebone_act, const float thresh)
-{
- EditBone *ebone;
-
- /* thresh is always relative to current length */
- const float len_min = ebone_act->length / (1.0f + thresh);
- const float len_max = ebone_act->length * (1.0f + thresh);
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- if ((ebone->length >= len_min) &&
- (ebone->length <= len_max))
- {
- ED_armature_edit_bone_select(ebone);
- }
- }
- }
-}
-
-static void select_similar_direction(bArmature *arm, EditBone *ebone_act, const float thresh)
-{
- EditBone *ebone;
- float dir_act[3];
- sub_v3_v3v3(dir_act, ebone_act->head, ebone_act->tail);
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- float dir[3];
- sub_v3_v3v3(dir, ebone->head, ebone->tail);
-
- if (angle_v3v3(dir_act, dir) / (float)M_PI < thresh) {
- ED_armature_edit_bone_select(ebone);
- }
- }
- }
-}
-
-static void select_similar_layer(bArmature *arm, EditBone *ebone_act)
-{
- EditBone *ebone;
-
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- if (ebone->layer & ebone_act->layer) {
- ED_armature_edit_bone_select(ebone);
- }
- }
- }
-}
-
-static void select_similar_prefix(bArmature *arm, EditBone *ebone_act)
-{
- EditBone *ebone;
-
- char body_tmp[MAX_VGROUP_NAME];
- char prefix_act[MAX_VGROUP_NAME];
-
- BKE_deform_split_prefix(ebone_act->name, prefix_act, body_tmp);
-
- if (prefix_act[0] == '\0')
- return;
-
- /* Find matches */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- char prefix_other[MAX_VGROUP_NAME];
- BKE_deform_split_prefix(ebone->name, prefix_other, body_tmp);
- if (!strcmp(prefix_act, prefix_other)) {
- ED_armature_edit_bone_select(ebone);
- }
- }
- }
-}
-
-static void select_similar_suffix(bArmature *arm, EditBone *ebone_act)
-{
- EditBone *ebone;
-
- char body_tmp[MAX_VGROUP_NAME];
- char suffix_act[MAX_VGROUP_NAME];
-
- BKE_deform_split_suffix(ebone_act->name, body_tmp, suffix_act);
-
- if (suffix_act[0] == '\0')
- return;
-
- /* Find matches */
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (EBONE_SELECTABLE(arm, ebone)) {
- char suffix_other[MAX_VGROUP_NAME];
- BKE_deform_split_suffix(ebone->name, body_tmp, suffix_other);
- if (!strcmp(suffix_act, suffix_other)) {
- ED_armature_edit_bone_select(ebone);
- }
- }
- }
-}
-
-static int armature_select_similar_exec(bContext *C, wmOperator *op)
-{
- Object *obedit = CTX_data_edit_object(C);
- bArmature *arm = obedit->data;
- EditBone *ebone_act = CTX_data_active_bone(C);
-
- /* Get props */
- int type = RNA_enum_get(op->ptr, "type");
- float thresh = RNA_float_get(op->ptr, "threshold");
-
- /* Check for active bone */
- if (ebone_act == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
- return OPERATOR_CANCELLED;
- }
-
- switch (type) {
- case SIMEDBONE_LENGTH:
- select_similar_length(arm, ebone_act, thresh);
- break;
- case SIMEDBONE_DIRECTION:
- select_similar_direction(arm, ebone_act, thresh);
- break;
- case SIMEDBONE_PREFIX:
- select_similar_prefix(arm, ebone_act);
- break;
- case SIMEDBONE_SUFFIX:
- select_similar_suffix(arm, ebone_act);
- break;
- case SIMEDBONE_LAYER:
- select_similar_layer(arm, ebone_act);
- break;
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_select_similar(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Similar";
- ot->idname = "ARMATURE_OT_select_similar";
-
- /* callback functions */
- ot->invoke = WM_menu_invoke;
- ot->exec = armature_select_similar_exec;
- ot->poll = ED_operator_editarmature;
- ot->description = "Select similar bones by property types";
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, 0, "Type", "");
- RNA_def_float(ot->srna, "threshold", 0.1f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
-}
-
-/* ********************* select hierarchy operator ************** */
-
-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;
- int direction = RNA_enum_get(op->ptr, "direction");
- int add_to_sel = RNA_boolean_get(op->ptr, "extend");
-
- 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;
- }
-
- }
- 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;
- }
- break;
- }
- }
- }
- }
- }
-
- ED_armature_sync_selection(arm->edbo);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_select_hierarchy(wmOperatorType *ot)
-{
- static EnumPropertyItem direction_items[] = {
- {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
- {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- /* identifiers */
- ot->name = "Select Hierarchy";
- ot->idname = "ARMATURE_OT_select_hierarchy";
- ot->description = "Select immediate parent/children of selected bones";
-
- /* api callbacks */
- ot->exec = armature_select_hierarchy_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- RNA_def_enum(ot->srna, "direction", direction_items,
- BONE_SELECT_PARENT, "Direction", "");
- RNA_def_boolean(ot->srna, "extend", 0, "Add to Selection", "");
-}
-
-/* ***************** EditBone Alignment ********************* */
-
-/* helper to fix a ebone position if its parent has moved due to alignment*/
-static void fix_connected_bone(EditBone *ebone)
-{
- float diff[3];
-
- if (!(ebone->parent) || !(ebone->flag & BONE_CONNECTED) || equals_v3v3(ebone->parent->tail, ebone->head))
- return;
-
- /* if the parent has moved we translate child's head and tail accordingly*/
- sub_v3_v3v3(diff, ebone->parent->tail, ebone->head);
- add_v3_v3(ebone->head, diff);
- add_v3_v3(ebone->tail, diff);
- return;
-}
-
-/* helper to recursively find chains of connected bones starting at ebone and fix their position */
-static void fix_editbone_connected_children(ListBase *edbo, EditBone *ebone)
-{
- EditBone *selbone;
-
- for (selbone = edbo->first; selbone; selbone = selbone->next) {
- if ((selbone->parent) && (selbone->parent == ebone) && (selbone->flag & BONE_CONNECTED)) {
- fix_connected_bone(selbone);
- fix_editbone_connected_children(edbo, selbone);
- }
- }
- return;
-}
-
-static void bone_align_to_bone(ListBase *edbo, EditBone *selbone, EditBone *actbone)
-{
- float selboneaxis[3], actboneaxis[3], length;
-
- sub_v3_v3v3(actboneaxis, actbone->tail, actbone->head);
- normalize_v3(actboneaxis);
-
- sub_v3_v3v3(selboneaxis, selbone->tail, selbone->head);
- length = len_v3(selboneaxis);
-
- mul_v3_fl(actboneaxis, length);
- add_v3_v3v3(selbone->tail, selbone->head, actboneaxis);
- selbone->roll = actbone->roll;
-
- /* if the bone being aligned has connected descendants they must be moved
- * according to their parent new position, otherwise they would be left
- * in an inconsistent state: connected but away from the parent*/
- fix_editbone_connected_children(edbo, selbone);
- return;
-}
-
-static int armature_align_bones_exec(bContext *C, wmOperator *op)
-{
- Object *ob = CTX_data_edit_object(C);
- bArmature *arm = (bArmature *)ob->data;
- EditBone *actbone = CTX_data_active_bone(C);
- EditBone *actmirb = NULL;
-
- /* there must be an active bone */
- if (actbone == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
- return OPERATOR_CANCELLED;
- }
- else if (arm->flag & ARM_MIRROR_EDIT) {
- /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
- * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone
- * (i.e. selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
- * This is useful for arm-chains, for example parenting lower arm to upper arm
- * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
- * then just use actbone. Useful when doing upper arm to spine.
- */
- actmirb = ED_armature_bone_get_mirrored(arm->edbo, actbone);
- if (actmirb == NULL)
- actmirb = actbone;
- }
-
- /* if there is only 1 selected bone, we assume that that is the active bone,
- * since a user will need to have clicked on a bone (thus selecting it) to make it active
- */
- if (CTX_DATA_COUNT(C, selected_editable_bones) <= 1) {
- /* When only the active bone is selected, and it has a parent,
- * align it to the parent, as that is the only possible outcome.
- */
- if (actbone->parent) {
- bone_align_to_bone(arm->edbo, actbone, actbone->parent);
-
- if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
- bone_align_to_bone(arm->edbo, actmirb, actmirb->parent);
- }
- }
- else {
- /* Align 'selected' bones to the active one
- * - the context iterator contains both selected bones and their mirrored copies,
- * so we assume that unselected bones are mirrored copies of some selected bone
- * - since the active one (and/or its mirror) will also be selected, we also need
- * to check that we are not trying to operate on them, since such an operation
- * would cause errors
- */
-
- /* align selected bones to the active one */
- CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
- {
- if (ELEM(ebone, actbone, actmirb) == 0) {
- if (ebone->flag & BONE_SELECTED)
- bone_align_to_bone(arm->edbo, ebone, actbone);
- else
- bone_align_to_bone(arm->edbo, ebone, actmirb);
- }
- }
- CTX_DATA_END;
- }
-
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_align(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Align Bones";
- ot->idname = "ARMATURE_OT_align";
- ot->description = "Align selected bones to the active bone (or to their parent)";
-
- /* api callbacks */
- ot->invoke = WM_operator_confirm;
- ot->exec = armature_align_bones_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* ***************** Pose tools ********************* */
-
-/* XXX bone_looper is only to be used when we want to access settings
- * (i.e. editability/visibility/selected) that context doesn't offer */
-static int bone_looper(Object *ob, Bone *bone, void *data,
- int (*bone_func)(Object *, Bone *, void *))
-{
- /* We want to apply the function bone_func to every bone
- * in an armature -- feed bone_looper the first bone and
- * a pointer to the bone_func and watch it go!. The int count
- * can be useful for counting bones with a certain property
- * (e.g. skinnable)
- */
- int count = 0;
-
- if (bone) {
- /* only do bone_func if the bone is non null */
- count += bone_func(ob, bone, data);
-
- /* try to execute bone_func for the first child */
- count += bone_looper(ob, bone->childbase.first, data, bone_func);
-
- /* try to execute bone_func for the next bone at this
- * depth of the recursion.
- */
- count += bone_looper(ob, bone->next, data, bone_func);
- }
-
- return count;
-}
-
-/* called from editview.c, for mode-less pose selection */
-/* assumes scene obact and basact is still on old situation */
-int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits,
- short extend, short deselect, short toggle)
-{
- Object *ob = base->object;
- Bone *nearBone;
-
- if (!ob || !ob->pose) return 0;
-
- nearBone = get_bone_from_selectbuffer(scene, base, buffer, hits, 1);
-
- /* if the bone cannot be affected, don't do anything */
- if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) {
- Object *ob_act = OBACT;
- bArmature *arm = ob->data;
-
- /* since we do unified select, we don't shift+select a bone if the
- * armature object was not active yet.
- * note, special exception for armature mode so we can do multi-select
- * we could check for multi-select explicitly but think its fine to
- * always give predictable behavior in weight paint mode - campbell */
- if ((!extend && !deselect && !toggle) ||
- ((ob_act && (ob_act != ob) && (ob_act->mode & OB_MODE_WEIGHT_PAINT) == 0)))
- {
- ED_pose_deselectall(ob, 0);
- nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- arm->act_bone = nearBone;
- }
- else {
- if (extend) {
- nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- arm->act_bone = nearBone;
- }
- else if (deselect) {
- nearBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else if (toggle) {
- if (nearBone->flag & BONE_SELECTED) {
- /* if not active, we make it active */
- if (nearBone != arm->act_bone) {
- arm->act_bone = nearBone;
- }
- else {
- nearBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- }
- else {
- nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- arm->act_bone = nearBone;
- }
- }
- }
-
- if (ob_act) {
- /* in weightpaint we select the associated vertex group too */
- if (ob_act->mode & OB_MODE_WEIGHT_PAINT) {
- if (nearBone == arm->act_bone) {
- ED_vgroup_select_by_name(ob_act, nearBone->name);
- DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
- }
- }
- /* if there are some dependencies for visualizing armature state
- * (e.g. Mask Modifier in 'Armature' mode), force update
- */
- else if (arm->flag & ARM_HAS_VIZ_DEPS) {
- DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
- }
- }
- }
-
- return nearBone != NULL;
-}
-
-/* test==0: deselect all
- * test==1: swap select (apply to all the opposite of current situation)
- * test==2: only clear active tag
- * test==3: swap select (no test / inverse selection status of all independently)
- */
-void ED_pose_deselectall(Object *ob, int test)
-{
- bArmature *arm = ob->data;
- bPoseChannel *pchan;
- int selectmode = 0;
-
- /* we call this from outliner too */
- if (ob->pose == NULL) {
- return;
- }
-
- /* Determine if we're selecting or deselecting */
- if (test == 1) {
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (PBONE_VISIBLE(arm, pchan->bone)) {
- if (pchan->bone->flag & BONE_SELECTED)
- break;
- }
- }
-
- if (pchan == NULL)
- selectmode = 1;
- }
- else if (test == 2)
- selectmode = 2;
-
- /* Set the flags accordingly */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- /* ignore the pchan if it isn't visible or if its selection cannot be changed */
- if ((pchan->bone->layer & arm->layer) && !(pchan->bone->flag & (BONE_HIDDEN_P | BONE_UNSELECTABLE))) {
- if (test == 3) {
- pchan->bone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else {
- if (selectmode == 0) pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- else if (selectmode == 1) pchan->bone->flag |= BONE_SELECTED;
- }
- }
- }
-}
-
-static int bone_skinnable_cb(Object *ob, Bone *bone, void *datap)
-{
- /* Bones that are deforming
- * are regarded to be "skinnable" and are eligible for
- * auto-skinning.
- *
- * This function performs 2 functions:
- *
- * a) It returns 1 if the bone is skinnable.
- * If we loop over all bones with this
- * function, we can count the number of
- * skinnable bones.
- * b) If the pointer data is non null,
- * it is treated like a handle to a
- * bone pointer -- the bone pointer
- * is set to point at this bone, and
- * the pointer the handle points to
- * is incremented to point to the
- * next member of an array of pointers
- * to bones. This way we can loop using
- * this function to construct an array of
- * pointers to bones that point to all
- * skinnable bones.
- */
- Bone ***hbone;
- int a, segments;
- struct { Object *armob; void *list; int heat; } *data = datap;
-
- if (!(ob->mode & OB_MODE_WEIGHT_PAINT) || !(bone->flag & BONE_HIDDEN_P)) {
- if (!(bone->flag & BONE_NO_DEFORM)) {
- if (data->heat && data->armob->pose && BKE_pose_channel_find_name(data->armob->pose, bone->name))
- segments = bone->segments;
- else
- segments = 1;
-
- if (data->list != NULL) {
- hbone = (Bone ***) &data->list;
-
- for (a = 0; a < segments; a++) {
- **hbone = bone;
- ++*hbone;
- }
- }
- return segments;
- }
- }
- return 0;
-}
-
-static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
-{
- /* This group creates a vertex group to ob that has the
- * same name as bone (provided the bone is skinnable).
- * If such a vertex group aleady exist the routine exits.
- */
- if (!(bone->flag & BONE_NO_DEFORM)) {
- if (!defgroup_find_name(ob, bone->name)) {
- ED_vgroup_add_name(ob, bone->name);
- return 1;
- }
- }
- return 0;
-}
-
-static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
-{
- /* Bones that are deforming
- * are regarded to be "skinnable" and are eligible for
- * auto-skinning.
- *
- * This function performs 2 functions:
- *
- * a) If the bone is skinnable, it creates
- * a vertex group for ob that has
- * the name of the skinnable bone
- * (if one doesn't exist already).
- * b) If the pointer data is non null,
- * it is treated like a handle to a
- * bDeformGroup pointer -- the
- * bDeformGroup pointer is set to point
- * to the deform group with the bone's
- * name, and the pointer the handle
- * points to is incremented to point to the
- * next member of an array of pointers
- * to bDeformGroups. This way we can loop using
- * this function to construct an array of
- * pointers to bDeformGroups, all with names
- * of skinnable bones.
- */
- bDeformGroup ***hgroup, *defgroup = NULL;
- int a, segments;
- struct { Object *armob; void *list; int heat; } *data = datap;
- int wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT);
- bArmature *arm = data->armob->data;
-
- if (!wpmode || !(bone->flag & BONE_HIDDEN_P)) {
- if (!(bone->flag & BONE_NO_DEFORM)) {
- if (data->heat && data->armob->pose && BKE_pose_channel_find_name(data->armob->pose, bone->name))
- segments = bone->segments;
- 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 (data->list != NULL) {
- hgroup = (bDeformGroup ***) &data->list;
-
- for (a = 0; a < segments; a++) {
- **hgroup = defgroup;
- ++*hgroup;
- }
- }
- return segments;
- }
- }
- return 0;
-}
-
-static void add_vgroups__mapFunc(void *userData, int index, const float co[3],
- const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
-{
- /* DerivedMesh mapFunc for getting final coords in weight paint mode */
-
- float (*verts)[3] = userData;
- copy_v3_v3(verts[index], co);
-}
-
-static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], int numbones, Bone **bonelist,
- bDeformGroup **dgrouplist, bDeformGroup **dgroupflip,
- float (*root)[3], float (*tip)[3], int *selected, float scale)
-{
- /* Create vertex group weights from envelopes */
-
- Bone *bone;
- bDeformGroup *dgroup;
- float distance;
- int i, iflip, j;
-
- /* for each vertex in the mesh */
- for (i = 0; i < mesh->totvert; i++) {
- iflip = (dgroupflip) ? mesh_get_x_mirror_vert(ob, i) : 0;
-
- /* for each skinnable bone */
- for (j = 0; j < numbones; ++j) {
- if (!selected[j])
- continue;
-
- bone = bonelist[j];
- dgroup = dgrouplist[j];
-
- /* store the distance-factor from the vertex to the bone */
- distance = distfactor_to_bone(verts[i], root[j], tip[j],
- bone->rad_head * scale, bone->rad_tail * scale, bone->dist * scale);
-
- /* add the vert to the deform group if (weight != 0.0) */
- if (distance != 0.0f)
- ED_vgroup_vert_add(ob, dgroup, i, distance, WEIGHT_REPLACE);
- else
- ED_vgroup_vert_remove(ob, dgroup, i);
-
- /* do same for mirror */
- if (dgroupflip && dgroupflip[j] && iflip >= 0) {
- if (distance != 0.0f)
- ED_vgroup_vert_add(ob, dgroupflip[j], iflip, distance,
- WEIGHT_REPLACE);
- else
- ED_vgroup_vert_remove(ob, dgroupflip[j], iflip);
- }
- }
- }
-}
-
-static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob, Object *par, int heat, int mirror)
-{
- /* This functions implements the automatic computation of vertex group
- * weights, either through envelopes or using a heat equilibrium.
- *
- * This function can be called both when parenting a mesh to an armature,
- * or in weightpaint + posemode. In the latter case selection is taken
- * into account and vertex weights can be mirrored.
- *
- * The mesh vertex positions used are either the final deformed coords
- * from the derivedmesh in weightpaint mode, the final subsurf coords
- * when parenting, or simply the original mesh coords.
- */
-
- bArmature *arm = par->data;
- Bone **bonelist, *bone;
- bDeformGroup **dgrouplist, **dgroupflip;
- bDeformGroup *dgroup;
- bPoseChannel *pchan;
- Mesh *mesh;
- Mat4 *bbone = NULL;
- float (*root)[3], (*tip)[3], (*verts)[3];
- int *selected;
- int numbones, vertsfilled = 0, i, j, segments = 0;
- int wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT);
- struct { Object *armob; void *list; int heat; } looper_data;
-
- looper_data.armob = par;
- looper_data.heat = heat;
- looper_data.list = NULL;
-
- /* count the number of skinnable bones */
- numbones = bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
-
- if (numbones == 0)
- return;
-
- if (ED_vgroup_data_create(ob->data) == FALSE)
- return;
-
- /* create an array of pointer to bones that are skinnable
- * and fill it with all of the skinnable bones */
- bonelist = MEM_callocN(numbones * sizeof(Bone *), "bonelist");
- looper_data.list = bonelist;
- bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
-
- /* create an array of pointers to the deform groups that
- * correspond to the skinnable bones (creating them
- * as necessary. */
- dgrouplist = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgrouplist");
- dgroupflip = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgroupflip");
-
- looper_data.list = dgrouplist;
- bone_looper(ob, arm->bonebase.first, &looper_data, dgroup_skinnable_cb);
-
- /* create an array of root and tip positions transformed into
- * global coords */
- root = MEM_callocN(numbones * sizeof(float) * 3, "root");
- tip = MEM_callocN(numbones * sizeof(float) * 3, "tip");
- selected = MEM_callocN(numbones * sizeof(int), "selected");
-
- for (j = 0; j < numbones; ++j) {
- bone = bonelist[j];
- dgroup = dgrouplist[j];
-
- /* handle bbone */
- if (heat) {
- if (segments == 0) {
- segments = 1;
- bbone = NULL;
-
- if ((par->pose) && (pchan = BKE_pose_channel_find_name(par->pose, bone->name))) {
- if (bone->segments > 1) {
- segments = bone->segments;
- bbone = b_bone_spline_setup(pchan, 1);
- }
- }
- }
-
- segments--;
- }
-
- /* compute root and tip */
- if (bbone) {
- mul_v3_m4v3(root[j], bone->arm_mat, bbone[segments].mat[3]);
- if ((segments + 1) < bone->segments) {
- mul_v3_m4v3(tip[j], bone->arm_mat, bbone[segments + 1].mat[3]);
- }
- else {
- copy_v3_v3(tip[j], bone->arm_tail);
- }
- }
- else {
- copy_v3_v3(root[j], bone->arm_head);
- copy_v3_v3(tip[j], bone->arm_tail);
- }
-
- mul_m4_v3(par->obmat, root[j]);
- mul_m4_v3(par->obmat, tip[j]);
-
- /* set selected */
- if (wpmode) {
- if ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))
- selected[j] = 1;
- }
- else
- selected[j] = 1;
-
- /* find flipped group */
- if (dgroup && mirror) {
- char name[MAXBONENAME];
-
- // 0 = don't strip off number extensions
- flip_side_name(name, dgroup->name, FALSE);
- dgroupflip[j] = defgroup_find_name(ob, name);
- }
- }
-
- /* create verts */
- mesh = (Mesh *)ob->data;
- verts = MEM_callocN(mesh->totvert * sizeof(*verts), "closestboneverts");
-
- if (wpmode) {
- /* if in weight paint mode, use final verts from derivedmesh */
- DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
-
- if (dm->foreachMappedVert) {
- dm->foreachMappedVert(dm, add_vgroups__mapFunc, (void *)verts);
- vertsfilled = 1;
- }
-
- dm->release(dm);
- }
- else if (modifiers_findByType(ob, eModifierType_Subsurf)) {
- /* is subsurf on? Lets use the verts on the limit surface then.
- * = same amount of vertices as mesh, but vertices moved to the
- * subsurfed position, like for 'optimal'. */
- subsurf_calculate_limit_positions(mesh, verts);
- vertsfilled = 1;
- }
-
- /* transform verts to global space */
- for (i = 0; i < mesh->totvert; i++) {
- if (!vertsfilled)
- copy_v3_v3(verts[i], mesh->mvert[i].co);
- mul_m4_v3(ob->obmat, verts[i]);
- }
-
- /* compute the weights based on gathered vertices and bones */
- if (heat) {
- const char *error = NULL;
- heat_bone_weighting(ob, mesh, verts, numbones, dgrouplist, dgroupflip,
- root, tip, selected, &error);
-
- if (error) {
- BKE_report(reports, RPT_WARNING, error);
- }
- }
- else {
- envelope_bone_weighting(ob, mesh, verts, numbones, bonelist, dgrouplist,
- dgroupflip, root, tip, selected, mat4_to_scale(par->obmat));
- }
-
- /* only generated in some cases but can call anyway */
- mesh_octree_table(ob, NULL, NULL, 'e');
-
- /* free the memory allocated */
- MEM_freeN(bonelist);
- MEM_freeN(dgrouplist);
- MEM_freeN(dgroupflip);
- MEM_freeN(root);
- MEM_freeN(tip);
- MEM_freeN(selected);
- MEM_freeN(verts);
-}
-
-void create_vgroups_from_armature(ReportList *reports, Scene *scene, Object *ob, Object *par, int mode, int mirror)
-{
- /* Lets try to create some vertex groups
- * based on the bones of the parent armature.
- */
- bArmature *arm = par->data;
-
- if (mode == ARM_GROUPS_NAME) {
- /* Traverse the bone list, trying to create empty vertex
- * groups corresponding to the bone.
- */
- bone_looper(ob, arm->bonebase.first, NULL, vgroup_add_unique_bone_cb);
-
- if (ob->type == OB_MESH)
- ED_vgroup_data_create(ob->data);
- }
- else if (mode == ARM_GROUPS_ENVELOPE || mode == ARM_GROUPS_AUTO) {
- /* Traverse the bone list, trying to create vertex groups
- * that are populated with the vertices for which the
- * bone is closest.
- */
- add_verts_to_dgroups(reports, scene, ob, par, (mode == ARM_GROUPS_AUTO), mirror);
- }
-}
-/* ************* Clear Pose *****************************/
-
-/* clear scale of pose-channel */
-static void pchan_clear_scale(bPoseChannel *pchan)
-{
- if ((pchan->protectflag & OB_LOCK_SCALEX) == 0)
- pchan->size[0] = 1.0f;
- if ((pchan->protectflag & OB_LOCK_SCALEY) == 0)
- pchan->size[1] = 1.0f;
- if ((pchan->protectflag & OB_LOCK_SCALEZ) == 0)
- pchan->size[2] = 1.0f;
-}
-
-/* clear location of pose-channel */
-static void pchan_clear_loc(bPoseChannel *pchan)
-{
- if ((pchan->protectflag & OB_LOCK_LOCX) == 0)
- pchan->loc[0] = 0.0f;
- if ((pchan->protectflag & OB_LOCK_LOCY) == 0)
- pchan->loc[1] = 0.0f;
- if ((pchan->protectflag & OB_LOCK_LOCZ) == 0)
- pchan->loc[2] = 0.0f;
-}
-
-/* clear rotation of pose-channel */
-static void pchan_clear_rot(bPoseChannel *pchan)
-{
- if (pchan->protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) {
- /* check if convert to eulers for locking... */
- if (pchan->protectflag & OB_LOCK_ROT4D) {
- /* perform clamping on a component by component basis */
- if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
- pchan->rotAngle = 0.0f;
- if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
- pchan->rotAxis[0] = 0.0f;
- if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
- pchan->rotAxis[1] = 0.0f;
- if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
- pchan->rotAxis[2] = 0.0f;
-
- /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */
- if (IS_EQF(pchan->rotAxis[0], pchan->rotAxis[1]) && IS_EQF(pchan->rotAxis[1], pchan->rotAxis[2]))
- pchan->rotAxis[1] = 1.0f;
- }
- else if (pchan->rotmode == ROT_MODE_QUAT) {
- if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
- pchan->quat[0] = 1.0f;
- if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
- pchan->quat[1] = 0.0f;
- if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
- pchan->quat[2] = 0.0f;
- if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
- pchan->quat[3] = 0.0f;
- }
- else {
- /* the flag may have been set for the other modes, so just ignore the extra flag... */
- if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
- pchan->eul[0] = 0.0f;
- if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
- pchan->eul[1] = 0.0f;
- if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
- pchan->eul[2] = 0.0f;
- }
- }
- else {
- /* perform clamping using euler form (3-components) */
- float eul[3], oldeul[3], quat1[4] = {0};
- float qlen = 0.0f;
-
- if (pchan->rotmode == ROT_MODE_QUAT) {
- qlen = normalize_qt_qt(quat1, pchan->quat);
- quat_to_eul(oldeul, quat1);
- }
- else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, pchan->rotAxis, pchan->rotAngle);
- }
- else {
- copy_v3_v3(oldeul, pchan->eul);
- }
-
- eul[0] = eul[1] = eul[2] = 0.0f;
-
- if (pchan->protectflag & OB_LOCK_ROTX)
- eul[0] = oldeul[0];
- if (pchan->protectflag & OB_LOCK_ROTY)
- eul[1] = oldeul[1];
- if (pchan->protectflag & OB_LOCK_ROTZ)
- eul[2] = oldeul[2];
-
- if (pchan->rotmode == ROT_MODE_QUAT) {
- eul_to_quat(pchan->quat, eul);
-
- /* restore original quat size */
- mul_qt_fl(pchan->quat, qlen);
-
- /* quaternions flip w sign to accumulate rotations correctly */
- if ((quat1[0] < 0.0f && pchan->quat[0] > 0.0f) || (quat1[0] > 0.0f && pchan->quat[0] < 0.0f)) {
- mul_qt_fl(pchan->quat, -1.0f);
- }
- }
- else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, eul, EULER_ORDER_DEFAULT);
- }
- else {
- copy_v3_v3(pchan->eul, eul);
- }
- }
- } /* Duplicated in source/blender/editors/object/object_transform.c */
- else {
- if (pchan->rotmode == ROT_MODE_QUAT) {
- unit_qt(pchan->quat);
- }
- else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- /* by default, make rotation of 0 radians around y-axis (roll) */
- unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
- }
- else {
- zero_v3(pchan->eul);
- }
- }
-}
-
-/* clear loc/rot/scale of pose-channel */
-static void pchan_clear_transforms(bPoseChannel *pchan)
-{
- pchan_clear_loc(pchan);
- pchan_clear_rot(pchan);
- pchan_clear_scale(pchan);
-}
-
-/* --------------- */
-
-/* generic exec for clear-pose operators */
-static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op,
- void (*clear_func)(bPoseChannel *), const char default_ksName[])
-{
- Scene *scene = CTX_data_scene(C);
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- short autokey = 0;
-
- /* sanity checks */
- if (ELEM(NULL, clear_func, default_ksName)) {
- BKE_report(op->reports, RPT_ERROR, "Programming error: missing clear transform function or keying set name");
- return OPERATOR_CANCELLED;
- }
-
- /* only clear relevant transforms for selected bones */
- CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones)
- {
- /* run provided clearing function */
- clear_func(pchan);
-
- /* do auto-keyframing as appropriate */
- if (autokeyframe_cfra_can_key(scene, &ob->id)) {
- /* clear any unkeyed tags */
- if (pchan->bone)
- pchan->bone->flag &= ~BONE_UNKEYED;
-
- /* tag for autokeying later */
- autokey = 1;
- }
- else {
- /* add unkeyed tags */
- if (pchan->bone)
- pchan->bone->flag |= BONE_UNKEYED;
- }
- }
- CTX_DATA_END;
-
- /* perform autokeying on the bones if needed */
- if (autokey) {
- /* get KeyingSet to use */
- KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
-
- /* insert keyframes */
- ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
-
- /* now recalculate paths */
- if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS))
- ED_pose_recalculate_paths(scene, ob);
- }
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
-
- return OPERATOR_FINISHED;
-}
-
-/* --------------- */
-
-static int pose_clear_scale_exec(bContext *C, wmOperator *op)
-{
- return pose_clear_transform_generic_exec(C, op, pchan_clear_scale, ANIM_KS_SCALING_ID);
-}
-
-void POSE_OT_scale_clear(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Clear Pose Scale";
- ot->idname = "POSE_OT_scale_clear";
- ot->description = "Reset scaling of selected bones to their default values";
-
- /* api callbacks */
- ot->exec = pose_clear_scale_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-
-static int pose_clear_rot_exec(bContext *C, wmOperator *op)
-{
- return pose_clear_transform_generic_exec(C, op, pchan_clear_rot, ANIM_KS_ROTATION_ID);
-}
-
-void POSE_OT_rot_clear(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Clear Pose Rotation";
- ot->idname = "POSE_OT_rot_clear";
- ot->description = "Reset rotations of selected bones to their default values";
-
- /* api callbacks */
- ot->exec = pose_clear_rot_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-
-static int pose_clear_loc_exec(bContext *C, wmOperator *op)
-{
- return pose_clear_transform_generic_exec(C, op, pchan_clear_loc, ANIM_KS_LOCATION_ID);
-}
-
-void POSE_OT_loc_clear(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Clear Pose Location";
- ot->idname = "POSE_OT_loc_clear";
- ot->description = "Reset locations of selected bones to their default values";
-
- /* api callbacks */
- ot->exec = pose_clear_loc_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-
-static int pose_clear_transforms_exec(bContext *C, wmOperator *op)
-{
- return pose_clear_transform_generic_exec(C, op, pchan_clear_transforms, ANIM_KS_LOC_ROT_SCALE_ID);
-}
-
-void POSE_OT_transforms_clear(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Clear Pose Transforms";
- ot->idname = "POSE_OT_transforms_clear";
- ot->description = "Reset location, rotation, and scaling of selected bones to their default values";
-
- /* api callbacks */
- ot->exec = pose_clear_transforms_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* ***************** selections ********************** */
-
-static int pose_de_select_all_exec(bContext *C, wmOperator *op)
-{
- int action = RNA_enum_get(op->ptr, "action");
-
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_context(C);
- bArmature *arm = ob->data;
- int multipaint = scene->toolsettings->multipaint;
-
- if (action == SEL_TOGGLE) {
- action = CTX_DATA_COUNT(C, selected_pose_bones) ? SEL_DESELECT : SEL_SELECT;
- }
-
- /* Set the flags */
- CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones)
- {
- /* select pchan only if selectable, but deselect works always */
- switch (action) {
- case SEL_SELECT:
- if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0)
- pchan->bone->flag |= BONE_SELECTED;
- break;
- case SEL_DESELECT:
- pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- break;
- case SEL_INVERT:
- if (pchan->bone->flag & BONE_SELECTED) {
- pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
- pchan->bone->flag |= BONE_SELECTED;
- }
- break;
- }
- }
- CTX_DATA_END;
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
-
- /* weightpaint or mask modifiers need depsgraph updates */
- if (multipaint || (arm->flag & ARM_HAS_VIZ_DEPS)) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_select_all(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "(De)select All";
- ot->idname = "POSE_OT_select_all";
- ot->description = "Toggle selection status of all bones";
-
- /* api callbacks */
- ot->exec = pose_de_select_all_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- WM_operator_properties_select_all(ot);
-}
-
-static int pose_select_parent_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bArmature *arm = (bArmature *)ob->data;
- bPoseChannel *pchan, *parent;
-
- /* Determine if there is an active bone */
- pchan = CTX_data_active_pose_bone(C);
- if (pchan) {
- parent = pchan->parent;
- if ((parent) && !(parent->bone->flag & (BONE_HIDDEN_P | BONE_UNSELECTABLE))) {
- parent->bone->flag |= BONE_SELECTED;
- arm->act_bone = parent->bone;
- }
- else {
- return OPERATOR_CANCELLED;
- }
- }
- else {
- return OPERATOR_CANCELLED;
- }
-
- /* updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
- if (arm->flag & ARM_HAS_VIZ_DEPS) {
- /* mask modifier ('armature' mode), etc. */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_select_parent(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Parent Bone";
- ot->idname = "POSE_OT_select_parent";
- ot->description = "Select bones that are parents of the currently selected bones";
-
- /* api callbacks */
- ot->exec = pose_select_parent_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
-}
-
-/* ************* hide/unhide pose bones ******************* */
-
-static int hide_selected_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
-{
- bArmature *arm = ob->data;
-
- if (arm->layer & bone->layer) {
- if (bone->flag & BONE_SELECTED) {
- bone->flag |= BONE_HIDDEN_P;
- bone->flag &= ~BONE_SELECTED;
- if (arm->act_bone == bone)
- arm->act_bone = NULL;
- }
- }
- return 0;
-}
-
-static int hide_unselected_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
-{
- bArmature *arm = ob->data;
-
- if (arm->layer & bone->layer) {
- /* hrm... typo here? */
- if ((bone->flag & BONE_SELECTED) == 0) {
- bone->flag |= BONE_HIDDEN_P;
- if (arm->act_bone == bone)
- arm->act_bone = NULL;
- }
- }
- return 0;
-}
-
-/* active object is armature in posemode, poll checked */
-static int pose_hide_exec(bContext *C, wmOperator *op)
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bArmature *arm = ob->data;
-
- if (RNA_boolean_get(op->ptr, "unselected"))
- bone_looper(ob, arm->bonebase.first, NULL, hide_unselected_pose_bone_cb);
- else
- bone_looper(ob, arm->bonebase.first, NULL, hide_selected_pose_bone_cb);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_hide(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Hide Selected";
- ot->idname = "POSE_OT_hide";
- ot->description = "Tag selected bones to not be visible in Pose Mode";
-
- /* api callbacks */
- ot->exec = pose_hide_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "");
-}
-
-static int show_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
-{
- bArmature *arm = ob->data;
-
- if (arm->layer & bone->layer) {
- if (bone->flag & BONE_HIDDEN_P) {
- bone->flag &= ~BONE_HIDDEN_P;
- bone->flag |= BONE_SELECTED;
- }
- }
-
- return 0;
-}
-
-/* active object is armature in posemode, poll checked */
-static int pose_reveal_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bArmature *arm = ob->data;
-
- bone_looper(ob, arm->bonebase.first, NULL, show_pose_bone_cb);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_reveal(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Reveal Selected";
- ot->idname = "POSE_OT_reveal";
- ot->description = "Unhide all bones that have been tagged to be hidden in Pose Mode";
-
- /* api callbacks */
- ot->exec = pose_reveal_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* ************* RENAMING DISASTERS ************ */
-
-static int bone_unique_check(void *arg, const char *name)
-{
- return BKE_armature_find_bone_name((bArmature *)arg, name) != NULL;
-}
-
-static void unique_bone_name(bArmature *arm, char *name)
-{
- BLI_uniquename_cb(bone_unique_check, (void *)arm, "Bone", '.', name, sizeof(((Bone *)NULL)->name));
-}
-
-/* helper call for armature_bone_rename */
-static void constraint_bone_name_fix(Object *ob, ListBase *conlist, char *oldname, char *newname)
-{
- bConstraint *curcon;
- bConstraintTarget *ct;
-
- for (curcon = conlist->first; curcon; curcon = curcon->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(curcon);
- ListBase targets = {NULL, NULL};
-
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(curcon, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar == ob) {
- if (!strcmp(ct->subtarget, oldname) )
- BLI_strncpy(ct->subtarget, newname, MAXBONENAME);
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(curcon, &targets, 0);
- }
- }
-}
-
-/* called by UI for renaming a bone */
-/* warning: make sure the original bone was not renamed yet! */
-/* seems messy, but thats what you get with not using pointers but channel names :) */
-void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *newnamep)
-{
- Object *ob;
- char newname[MAXBONENAME];
- char oldname[MAXBONENAME];
-
- /* names better differ! */
- if (strncmp(oldnamep, newnamep, MAXBONENAME)) {
-
- /* we alter newname string... so make copy */
- BLI_strncpy(newname, newnamep, MAXBONENAME);
- /* we use oldname for search... so make copy */
- BLI_strncpy(oldname, oldnamep, MAXBONENAME);
-
- /* now check if we're in editmode, we need to find the unique name */
- if (arm->edbo) {
- EditBone *eBone = editbone_name_exists(arm->edbo, oldname);
-
- if (eBone) {
- unique_editbone_name(arm->edbo, newname, NULL);
- BLI_strncpy(eBone->name, newname, MAXBONENAME);
- }
- else return;
- }
- else {
- Bone *bone = BKE_armature_find_bone_name(arm, oldname);
-
- if (bone) {
- unique_bone_name(arm, newname);
- BLI_strncpy(bone->name, newname, MAXBONENAME);
- }
- else return;
- }
-
- /* do entire dbase - objects */
- for (ob = G.main->object.first; ob; ob = ob->id.next) {
- ModifierData *md;
-
- /* we have the object using the armature */
- if (arm == ob->data) {
- Object *cob;
-
- /* Rename the pose channel, if it exists */
- if (ob->pose) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, oldname);
- if (pchan) {
- BLI_strncpy(pchan->name, newname, MAXBONENAME);
-
- if (ob->pose->chanhash) {
- GHash *gh = ob->pose->chanhash;
-
- /* remove the old hash entry, and replace with the new name */
- BLI_ghash_remove(gh, oldname, NULL, NULL);
- BLI_ghash_insert(gh, pchan->name, pchan);
- }
- }
- }
-
- /* Update any object constraints to use the new bone name */
- for (cob = G.main->object.first; cob; cob = cob->id.next) {
- if (cob->constraints.first)
- constraint_bone_name_fix(ob, &cob->constraints, oldname, newname);
- if (cob->pose) {
- bPoseChannel *pchan;
- for (pchan = cob->pose->chanbase.first; pchan; pchan = pchan->next) {
- constraint_bone_name_fix(ob, &pchan->constraints, oldname, newname);
- }
- }
- }
- }
-
- /* See if an object is parented to this armature */
- if (ob->parent && (ob->parent->data == arm)) {
- if (ob->partype == PARBONE) {
- /* bone name in object */
- if (!strcmp(ob->parsubstr, oldname))
- BLI_strncpy(ob->parsubstr, newname, MAXBONENAME);
- }
- }
-
- if (modifiers_usesArmature(ob, arm)) {
- bDeformGroup *dg = defgroup_find_name(ob, oldname);
- if (dg) {
- BLI_strncpy(dg->name, newname, MAXBONENAME);
- }
- }
-
- /* fix modifiers that might be using this name */
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Hook) {
- HookModifierData *hmd = (HookModifierData *)md;
-
- /* uses armature, so may use the affected bone name */
- if (hmd->object && (hmd->object->data == arm)) {
- if (!strcmp(hmd->subtarget, oldname))
- BLI_strncpy(hmd->subtarget, newname, MAXBONENAME);
- }
- }
- }
- }
-
- /* 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]
- */
- {
-
- BKE_all_animdata_fix_paths_rename(&arm->id, "pose.bones", oldname, newname);
- }
-
- /* correct view locking */
- {
- bScreen *screen;
- for (screen = G.main->screen.first; screen; screen = screen->id.next) {
- ScrArea *sa;
- /* add regions */
- for (sa = screen->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- if (v3d->ob_centre && v3d->ob_centre->data == arm) {
- if (!strcmp(v3d->ob_centre_bone, oldname)) {
- BLI_strncpy(v3d->ob_centre_bone, newname, MAXBONENAME);
- }
- }
- }
- }
- }
- }
- }
- }
-}
-
-
-static int armature_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = CTX_data_edit_object(C);
- bArmature *arm;
- char newname[MAXBONENAME];
-
- /* paranoia checks */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
- arm = ob->data;
-
- /* loop through selected bones, auto-naming them */
- CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
- {
- flip_side_name(newname, ebone->name, TRUE); // 1 = do strip off number extensions
- ED_armature_bone_rename(arm, ebone->name, newname);
- }
- CTX_DATA_END;
-
- /* since we renamed stuff... */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_flip_names(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Flip Names";
- ot->idname = "ARMATURE_OT_flip_names";
- ot->description = "Flips (and corrects) the axis suffixes of the names of selected bones";
-
- /* api callbacks */
- ot->exec = armature_flip_names_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-
-static int armature_autoside_names_exec(bContext *C, wmOperator *op)
-{
- Object *ob = CTX_data_edit_object(C);
- bArmature *arm;
- char newname[MAXBONENAME];
- short axis = RNA_enum_get(op->ptr, "type");
-
- /* paranoia checks */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
- arm = ob->data;
-
- /* loop through selected bones, auto-naming them */
- CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
- {
- BLI_strncpy(newname, ebone->name, sizeof(newname));
- if (bone_autoside_name(newname, 1, axis, ebone->head[axis], ebone->tail[axis]))
- ED_armature_bone_rename(arm, ebone->name, newname);
- }
- CTX_DATA_END;
-
- /* since we renamed stuff... */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_autoside_names(wmOperatorType *ot)
-{
- static EnumPropertyItem axis_items[] = {
- {0, "XAXIS", 0, "X-Axis", "Left/Right"},
- {1, "YAXIS", 0, "Y-Axis", "Front/Back"},
- {2, "ZAXIS", 0, "Z-Axis", "Top/Bottom"},
- {0, NULL, 0, NULL, NULL}
- };
-
- /* identifiers */
- ot->name = "AutoName by Axis";
- ot->idname = "ARMATURE_OT_autoside_names";
- ot->description = "Automatically renames the selected bones according to which side of the target axis they fall on";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = armature_autoside_names_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* settings */
- ot->prop = RNA_def_enum(ot->srna, "type", axis_items, 0, "Axis", "Axis tag names with");
-}
-
-
-
-/* if editbone (partial) selected, copy data */
-/* context; editmode armature, with mirror editing enabled */
-void transform_armature_mirror_update(Object *obedit)
-{
- bArmature *arm = obedit->data;
- EditBone *ebo, *eboflip;
-
- for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
- /* no layer check, correct mirror is more important */
- if (ebo->flag & (BONE_TIPSEL | BONE_ROOTSEL)) {
- eboflip = ED_armature_bone_get_mirrored(arm->edbo, ebo);
-
- if (eboflip) {
- /* we assume X-axis flipping for now */
- if (ebo->flag & BONE_TIPSEL) {
- EditBone *children;
-
- eboflip->tail[0] = -ebo->tail[0];
- eboflip->tail[1] = ebo->tail[1];
- eboflip->tail[2] = ebo->tail[2];
- eboflip->rad_tail = ebo->rad_tail;
- eboflip->roll = -ebo->roll;
-
- /* Also move connected children, in case children's name aren't mirrored properly */
- for (children = arm->edbo->first; children; children = children->next) {
- if (children->parent == eboflip && children->flag & BONE_CONNECTED) {
- copy_v3_v3(children->head, eboflip->tail);
- children->rad_head = ebo->rad_tail;
- }
- }
- }
- if (ebo->flag & BONE_ROOTSEL) {
- eboflip->head[0] = -ebo->head[0];
- eboflip->head[1] = ebo->head[1];
- eboflip->head[2] = ebo->head[2];
- eboflip->rad_head = ebo->rad_head;
- eboflip->roll = -ebo->roll;
-
- /* Also move connected parent, in case parent's name isn't mirrored properly */
- if (eboflip->parent && eboflip->flag & BONE_CONNECTED) {
- EditBone *parent = eboflip->parent;
- copy_v3_v3(parent->tail, eboflip->head);
- parent->rad_tail = ebo->rad_head;
- }
- }
- if (ebo->flag & BONE_SELECTED) {
- eboflip->dist = ebo->dist;
- eboflip->roll = -ebo->roll;
- eboflip->xwidth = ebo->xwidth;
- eboflip->zwidth = ebo->zwidth;
- }
- }
- }
- }
-}
-
-
-/*****************************************************************************************************/
-/*************************************** SKELETON GENERATOR ******************************************/
-/*****************************************************************************************************/
-
-#if 0
-
-/**************************************** SUBDIVISION ALGOS ******************************************/
-
-EditBone *subdivideByAngle(Scene *scene, Object *obedit, ReebArc *arc, ReebNode *head, ReebNode *tail)
-{
- bArmature *arm = obedit->data;
- EditBone *lastBone = NULL;
-
- if (scene->toolsettings->skgen_options & SKGEN_CUT_ANGLE) {
- ReebArcIterator arc_iter;
- BArcIterator *iter = (BArcIterator *)&arc_iter;
- float *previous = NULL, *current = NULL;
- EditBone *child = NULL;
- EditBone *parent = NULL;
- EditBone *root = NULL;
- float angleLimit = (float)cos(scene->toolsettings->skgen_angle_limit * M_PI / 180.0f);
-
- parent = ED_armature_edit_bone_add(arm, "Bone");
- parent->flag |= BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL;
- copy_v3_v3(parent->head, head->p);
-
- root = parent;
-
- initArcIterator(iter, arc, head);
- IT_next(iter);
- previous = iter->p;
-
- for (IT_next(iter);
- IT_stopped(iter) == 0;
- previous = iter->p, IT_next(iter))
- {
- float vec1[3], vec2[3];
- float len1, len2;
-
- current = iter->p;
-
- sub_v3_v3v3(vec1, previous, parent->head);
- sub_v3_v3v3(vec2, current, previous);
-
- len1 = normalize_v3(vec1);
- len2 = normalize_v3(vec2);
-
- if (len1 > 0.0f && len2 > 0.0f && dot_v3v3(vec1, vec2) < angleLimit) {
- copy_v3_v3(parent->tail, previous);
-
- child = ED_armature_edit_bone_add(arm, "Bone");
- copy_v3_v3(child->head, parent->tail);
- child->parent = parent;
- child->flag |= BONE_CONNECTED | BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL;
-
- parent = child; /* new child is next parent */
- }
- }
- copy_v3_v3(parent->tail, tail->p);
-
- /* If the bone wasn't subdivided, delete it and return NULL
- * to let subsequent subdivision methods do their thing.
- * */
- if (parent == root) {
- if (parent == arm->act_edbone) arm->act_edbone = NULL;
- ED_armature_edit_bone_remove(arm, parent);
- parent = NULL;
- }
-
- lastBone = parent; /* set last bone in the chain */
- }
-
- return lastBone;
-}
-
-EditBone *test_subdivideByCorrelation(Scene *scene, Object *obedit, ReebArc *arc, ReebNode *head, ReebNode *tail)
-{
- EditBone *lastBone = NULL;
-
- if (scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION) {
- float invmat[4][4] = MAT4_UNITY;
- float tmat[3][3] = MAT3_UNITY;
- ReebArcIterator arc_iter;
- BArcIterator *iter = (BArcIterator *)&arc_iter;
- bArmature *arm = obedit->data;
-
- initArcIterator(iter, arc, head);
-
- lastBone = subdivideArcBy(arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
- }
-
- return lastBone;
-}
-
-float arcLengthRatio(ReebArc *arc)
-{
- float arcLength = 0.0f;
- float embedLength = 0.0f;
- int i;
-
- arcLength = len_v3v3(arc->head->p, arc->tail->p);
-
- if (arc->bcount > 0) {
- /* Add the embedding */
- for (i = 1; i < arc->bcount; i++) {
- embedLength += len_v3v3(arc->buckets[i - 1].p, arc->buckets[i].p);
- }
- /* Add head and tail -> embedding vectors */
- embedLength += len_v3v3(arc->head->p, arc->buckets[0].p);
- embedLength += len_v3v3(arc->tail->p, arc->buckets[arc->bcount - 1].p);
- }
- else {
- embedLength = arcLength;
- }
-
- return embedLength / arcLength;
-}
-
-EditBone *test_subdivideByLength(Scene *scene, Object *obedit, ReebArc *arc, ReebNode *head, ReebNode *tail)
-{
- EditBone *lastBone = NULL;
- if ((scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) &&
- arcLengthRatio(arc) >= G.scene->toolsettings->skgen_length_ratio)
- {
- float invmat[4][4] = MAT4_UNITY;
- float tmat[3][3] = MAT3_UNITY;
- ReebArcIterator arc_iter;
- BArcIterator *iter = (BArcIterator *)&arc_iter;
- bArmature *arm = obedit->data;
-
- initArcIterator(iter, arc, head);
-
- lastBone = subdivideArcBy(arm, arm->edbo, iter, invmat, tmat, nextLengthSubdivision);
- }
-
- return lastBone;
-}
-
-/***************************************** MAIN ALGORITHM ********************************************/
-
-void generateSkeletonFromReebGraph(Scene *scene, ReebGraph *rg)
-{
- Object *obedit = scene->obedit; // XXX get from context
- GHash *arcBoneMap = NULL;
- ReebArc *arc = NULL;
- ReebNode *node = NULL;
- Object *src = NULL;
- Object *dst = NULL;
-
- src = scene->basact->object;
-
- if (obedit != NULL) {
- ED_armature_from_edit(obedit);
- ED_armature_edit_free(obedit);
- }
-
- dst = BKE_object_add(scene, OB_ARMATURE);
- ED_object_base_init_transform(NULL, scene->basact, NULL, NULL); // XXX NULL is C, loc, rot
- obedit = scene->basact->object;
-
- /* Copy orientation from source */
- copy_v3_v3(dst->loc, src->obmat[3]);
- mat4_to_eul(dst->rot, src->obmat);
- mat4_to_size(dst->size, src->obmat);
-
- BKE_object_where_is_calc(scene, obedit);
-
- ED_armature_to_edit(obedit);
-
- arcBoneMap = BLI_ghash_ptr_new("SkeletonFromReebGraph gh");
-
- BLI_markdownSymmetry((BGraph *)rg, rg->nodes.first, scene->toolsettings->skgen_symmetry_limit);
-
- for (arc = rg->arcs.first; arc; arc = arc->next)
- {
- EditBone *lastBone = NULL;
- ReebNode *head, *tail;
- int i;
-
- /* Find out the direction of the arc through simple heuristics (in order of priority) :
- *
- * 1- Arcs on primary symmetry axis (symmetry == 1) point up (head: high weight -> tail: low weight)
- * 2- Arcs starting on a primary axis point away from it (head: node on primary axis)
- * 3- Arcs point down (head: low weight -> tail: high weight)
- *
- * Finally, the arc direction is stored in its flag: 1 (low -> high), -1 (high -> low)
- */
-
- /* if arc is a symmetry axis, internal bones go up the tree */
- if (arc->symmetry_level == 1 && arc->tail->degree != 1) {
- head = arc->tail;
- tail = arc->head;
-
- arc->flag = -1; /* mark arc direction */
- }
- /* Bones point AWAY from the symmetry axis */
- else if (arc->head->symmetry_level == 1) {
- head = arc->head;
- tail = arc->tail;
-
- arc->flag = 1; /* mark arc direction */
- }
- else if (arc->tail->symmetry_level == 1) {
- head = arc->tail;
- tail = arc->head;
-
- arc->flag = -1; /* mark arc direction */
- }
- /* otherwise, always go from low weight to high weight */
- else {
- head = arc->head;
- tail = arc->tail;
-
- arc->flag = 1; /* mark arc direction */
- }
-
- /* Loop over subdivision methods */
- for (i = 0; lastBone == NULL && i < SKGEN_SUB_TOTAL; i++) {
- switch (scene->toolsettings->skgen_subdivisions[i]) {
- case SKGEN_SUB_LENGTH:
- lastBone = test_subdivideByLength(scene, obedit, arc, head, tail);
- break;
- case SKGEN_SUB_ANGLE:
- lastBone = subdivideByAngle(scene, obedit, arc, head, tail);
- break;
- case SKGEN_SUB_CORRELATION:
- lastBone = test_subdivideByCorrelation(scene, obedit, arc, head, tail);
- break;
- }
- }
-
- if (lastBone == NULL) {
- EditBone *bone;
- bone = ED_armature_edit_bone_add(obedit->data, "Bone");
- bone->flag |= BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL;
-
- copy_v3_v3(bone->head, head->p);
- copy_v3_v3(bone->tail, tail->p);
-
- /* set first and last bone, since there's only one */
- lastBone = bone;
- }
-
- BLI_ghash_insert(arcBoneMap, arc, lastBone);
- }
-
- /* Second pass, setup parent relationship between arcs */
- for (node = rg->nodes.first; node; node = node->next)
- {
- ReebArc *incomingArc = NULL;
- int i;
-
- for (i = 0; i < node->degree; i++) {
- arc = (ReebArc *)node->arcs[i];
-
- /* if arc is incoming into the node */
- if ((arc->head == node && arc->flag == -1) ||
- (arc->tail == node && arc->flag == 1))
- {
- if (incomingArc == NULL) {
- incomingArc = arc;
- /* loop further to make sure there's only one incoming arc */
- }
- else {
- /* skip this node if more than one incomingArc */
- incomingArc = NULL;
- break; /* No need to look further, we are skipping already */
- }
- }
- }
-
- if (incomingArc != NULL) {
- EditBone *parentBone = BLI_ghash_lookup(arcBoneMap, incomingArc);
-
- /* Look for outgoing arcs and parent their bones */
- for (i = 0; i < node->degree; i++)
- {
- arc = node->arcs[i];
-
- /* if arc is outgoing from the node */
- if ((arc->head == node && arc->flag == 1) || (arc->tail == node && arc->flag == -1)) {
- EditBone *childBone = BLI_ghash_lookup(arcBoneMap, arc);
-
- /* find the root bone */
- while (childBone->parent != NULL)
- {
- childBone = childBone->parent;
- }
-
- childBone->parent = parentBone;
- childBone->flag |= BONE_CONNECTED;
- }
- }
- }
- }
-
- BLI_ghash_free(arcBoneMap, NULL, NULL);
-}
-
-void generateSkeleton(Scene *scene)
-{
- ReebGraph *reebg;
-
-// setcursor_space(SPACE_VIEW3D, CURSOR_WAIT);
-
- reebg = BIF_ReebGraphFromEditMesh();
-
- generateSkeletonFromReebGraph(scene, reebg);
-
- REEB_freeGraph(reebg);
-
- //setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
-}
-
-#endif
diff --git a/source/blender/editors/armature/editarmature_generate.c b/source/blender/editors/armature/editarmature_generate.c
index 979c352c4b2..bade93af8c1 100644
--- a/source/blender/editors/armature/editarmature_generate.c
+++ b/source/blender/editors/armature/editarmature_generate.c
@@ -30,24 +30,13 @@
* \ingroup edarmature
*/
-
-#include <string.h>
-#include <math.h>
-#include <float.h>
-
-
#include "DNA_scene_types.h"
#include "DNA_armature_types.h"
-#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_graph.h"
-#include "BLI_utildefines.h"
-
-
#include "ED_armature.h"
-#include "armature_intern.h"
#include "BIF_generate.h"
void setBoneRollFromNormal(EditBone *bone, const float no[3], float UNUSED(invmat[4][4]), float tmat[3][3])
@@ -274,7 +263,7 @@ EditBone *subdivideArcBy(ToolSettings *toolsettings, bArmature *arm, ListBase *U
parent = ED_armature_edit_bone_add(arm, "Bone");
copy_v3_v3(parent->head, iter->p);
- if (iter->size > 0) {
+ if (iter->size > FLT_EPSILON) {
parent->rad_head = iter->size * size_buffer;
}
@@ -289,7 +278,7 @@ EditBone *subdivideArcBy(ToolSettings *toolsettings, bArmature *arm, ListBase *U
child->parent = parent;
child->flag |= BONE_CONNECTED;
- if (iter->size > 0) {
+ if (iter->size > FLT_EPSILON) {
child->rad_head = iter->size * size_buffer;
parent->rad_tail = iter->size * size_buffer;
}
@@ -310,7 +299,7 @@ EditBone *subdivideArcBy(ToolSettings *toolsettings, bArmature *arm, ListBase *U
iter->tail(iter);
copy_v3_v3(parent->tail, iter->p);
- if (iter->size > 0) {
+ if (iter->size > FLT_EPSILON) {
parent->rad_tail = iter->size * size_buffer;
}
diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c
index 68cfc7fb8c0..536c5ff1f7c 100644
--- a/source/blender/editors/armature/editarmature_retarget.c
+++ b/source/blender/editors/armature/editarmature_retarget.c
@@ -25,12 +25,6 @@
* \ingroup edarmature
*/
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include <float.h>
-
#include "MEM_guardedalloc.h"
#include "PIL_time.h"
@@ -42,11 +36,6 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
-#include "BLI_ghash.h"
-#include "BLI_graph.h"
-#include "BLI_rand.h"
-#include "BLI_threads.h"
#include "BKE_constraint.h"
#include "BKE_armature.h"
@@ -57,8 +46,6 @@
#include "BIF_retarget.h"
-#include "reeb.h" /* FIX ME */
-
#include "armature_intern.h"
/************ RIG RETARGET DATA STRUCTURES ***************/
@@ -422,11 +409,11 @@ static void renameTemplateBone(char *name, char *template_name, ListBase *editbo
for (i = 0, j = 0; i < (MAXBONENAME - 1) && j < (MAXBONENAME - 1) && template_name[i] != '\0'; i++) {
if (template_name[i] == '&') {
if (template_name[i + 1] == 'S' || template_name[i + 1] == 's') {
- j += sprintf(name + j, "%s", side_string);
+ j += BLI_strncpy_rlen(name + j, side_string, MAXBONENAME);
i++;
}
else if (template_name[i + 1] == 'N' || template_name[i + 1] == 'n') {
- j += sprintf(name + j, "%s", num_string);
+ j += BLI_strncpy_rlen(name + j, num_string, MAXBONENAME);
i++;
}
else {
@@ -725,7 +712,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 = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -850,7 +837,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 = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -909,7 +896,7 @@ static void RIG_reconnectControlBones(RigGraph *rg)
/* look on deform bones first */
BLI_ghashIterator_init(&ghi, rg->bones_map);
- for (; !BLI_ghashIterator_isDone(&ghi); BLI_ghashIterator_step(&ghi)) {
+ for (; BLI_ghashIterator_notDone(&ghi); BLI_ghashIterator_step(&ghi)) {
EditBone *bone = (EditBone *)BLI_ghashIterator_getValue(&ghi);
/* don't link with parent */
@@ -1830,7 +1817,9 @@ static float calcCostLengthDistance(BArcIterator *iter, float **vec_cache, RigEd
}
#endif
-static float calcCostAngleLengthDistance(BArcIterator *iter, float **UNUSED(vec_cache), RigEdge *edge, float *vec0, float *vec1, float *vec2, int i1, int i2, float angle_weight, float length_weight, float distance_weight)
+static float calcCostAngleLengthDistance(BArcIterator *iter, float **UNUSED(vec_cache), RigEdge *edge,
+ float *vec0, float *vec1, float *vec2, int i1, int i2,
+ float angle_weight, float length_weight, float distance_weight)
{
float vec_second[3], vec_first[3];
float length2;
@@ -1878,7 +1867,9 @@ static void copyMemoPositions(int *positions, MemoNode *table, int nb_positions,
}
}
-static MemoNode *solveJoints(MemoNode *table, BArcIterator *iter, float **vec_cache, int nb_joints, int nb_positions, int previous, int current, RigEdge *edge, int joints_left, float angle_weight, float length_weight, float distance_weight)
+static MemoNode *solveJoints(MemoNode *table, BArcIterator *iter, float **vec_cache,
+ int nb_joints, int nb_positions, int previous, int current, RigEdge *edge,
+ int joints_left, float angle_weight, float length_weight, float distance_weight)
{
MemoNode *node;
int index = indexMemoNode(nb_positions, previous, current, joints_left);
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index b61aa86a52f..a3515e0983d 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -22,30 +22,23 @@
* \ingroup edarmature
*/
-#include <string.h>
-#include <math.h>
-#include <float.h>
-
#include "MEM_guardedalloc.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_armature_types.h"
-#include "RNA_define.h"
-#include "RNA_access.h"
-
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
-#include "BLI_graph.h"
-#include "BLI_ghash.h"
#include "BLF_translation.h"
#include "BKE_context.h"
#include "BKE_sketch.h"
+#include "RNA_define.h"
+#include "RNA_access.h"
+
#include "ED_view3d.h"
#include "ED_screen.h"
@@ -60,8 +53,6 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "reeb.h"
-
typedef int (*GestureDetectFct)(bContext *, SK_Gesture *, SK_Sketch *);
typedef void (*GestureApplyFct)(bContext *, SK_Gesture *, SK_Sketch *);
@@ -179,20 +170,20 @@ const char *BIF_listTemplates(const bContext *UNUSED(C))
GHashIterator ghi;
const char *menu_header = IFACE_("Template %t|None %x0|");
char *p;
+ const size_t template_size = (BLI_ghash_size(TEMPLATES_HASH) * 32 + 30);
if (TEMPLATES_MENU != NULL) {
MEM_freeN(TEMPLATES_MENU);
}
- TEMPLATES_MENU = MEM_callocN(sizeof(char) * (BLI_ghash_size(TEMPLATES_HASH) * 32 + 30), "skeleton template menu");
+ TEMPLATES_MENU = MEM_callocN(sizeof(char) * template_size, "skeleton template menu");
p = TEMPLATES_MENU;
-
- p += sprintf(TEMPLATES_MENU, "%s", menu_header);
+ p += BLI_strncpy_rlen(p, menu_header, template_size);
BLI_ghashIterator_init(&ghi, TEMPLATES_HASH);
- while (!BLI_ghashIterator_isDone(&ghi)) {
+ while (BLI_ghashIterator_notDone(&ghi)) {
Object *ob = BLI_ghashIterator_getValue(&ghi);
int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi));
@@ -212,7 +203,7 @@ int BIF_currentTemplate(const bContext *C)
GHashIterator ghi;
BLI_ghashIterator_init(&ghi, TEMPLATES_HASH);
- while (!BLI_ghashIterator_isDone(&ghi)) {
+ while (BLI_ghashIterator_notDone(&ghi)) {
Object *ob = BLI_ghashIterator_getValue(&ghi);
int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi));
@@ -931,17 +922,18 @@ static void sk_projectDrawPoint(bContext *C, float vec[3], SK_Stroke *stk, SK_Dr
float fp[3] = {0, 0, 0};
float dvec[3];
float mval_f[2];
+ float zfac;
if (last != NULL) {
copy_v3_v3(fp, last->p);
}
- initgrabz(ar->regiondata, fp[0], fp[1], fp[2]);
+ zfac = ED_view3d_calc_zfac(ar->regiondata, fp, NULL);
/* method taken from editview.c - mouse_cursor() */
if (ED_view3d_project_short_global(ar, fp, cval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
VECSUB2D(mval_f, cval, dd->mval);
- ED_view3d_win_to_delta(ar, mval_f, dvec);
+ ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
sub_v3_v3v3(vec, fp, dvec);
}
else {
@@ -2240,7 +2232,7 @@ void BDR_drawSketch(const bContext *C)
}
}
-static int sketch_delete(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
+static int sketch_delete(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
SK_Sketch *sketch = contextSketch(C, 0);
if (sketch) {
@@ -2337,7 +2329,7 @@ SK_Sketch *viewcontextSketch(ViewContext *vc, int create)
return sketch;
}
-static int sketch_convert(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
+static int sketch_convert(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
SK_Sketch *sketch = contextSketch(C, 0);
if (sketch != NULL) {
@@ -2347,7 +2339,7 @@ static int sketch_convert(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(e
return OPERATOR_FINISHED;
}
-static int sketch_cancel(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
+static int sketch_cancel(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
SK_Sketch *sketch = contextSketch(C, 0);
if (sketch != NULL) {
@@ -2358,7 +2350,7 @@ static int sketch_cancel(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(ev
return OPERATOR_PASS_THROUGH;
}
-static int sketch_finish(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
+static int sketch_finish(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
SK_Sketch *sketch = contextSketch(C, 0);
if (sketch != NULL) {
@@ -2370,7 +2362,7 @@ static int sketch_finish(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(ev
return OPERATOR_PASS_THROUGH;
}
-static int sketch_select(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int sketch_select(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
SK_Sketch *sketch = contextSketch(C, 0);
if (sketch) {
@@ -2390,7 +2382,7 @@ static int sketch_draw_stroke_cancel(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int sketch_draw_stroke(bContext *C, wmOperator *op, wmEvent *event)
+static int sketch_draw_stroke(bContext *C, wmOperator *op, const wmEvent *event)
{
short snap = RNA_boolean_get(op->ptr, "snap");
SK_DrawData *dd;
@@ -2416,7 +2408,7 @@ static int sketch_draw_gesture_cancel(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int sketch_draw_gesture(bContext *C, wmOperator *op, wmEvent *event)
+static int sketch_draw_gesture(bContext *C, wmOperator *op, const wmEvent *event)
{
short snap = RNA_boolean_get(op->ptr, "snap");
SK_DrawData *dd;
@@ -2434,7 +2426,7 @@ static int sketch_draw_gesture(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static int sketch_draw_modal(bContext *C, wmOperator *op, wmEvent *event, short gesture, SK_Stroke *stk)
+static int sketch_draw_modal(bContext *C, wmOperator *op, const wmEvent *event, short gesture, SK_Stroke *stk)
{
short snap = RNA_boolean_get(op->ptr, "snap");
SK_DrawData *dd = op->customdata;
@@ -2492,19 +2484,19 @@ static int sketch_draw_modal(bContext *C, wmOperator *op, wmEvent *event, short
return retval;
}
-static int sketch_draw_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int sketch_draw_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
return sketch_draw_modal(C, op, event, 0, sketch->active_stroke);
}
-static int sketch_draw_gesture_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int sketch_draw_gesture_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
return sketch_draw_modal(C, op, event, 1, sketch->gesture);
}
-static int sketch_draw_preview(bContext *C, wmOperator *op, wmEvent *event)
+static int sketch_draw_preview(bContext *C, wmOperator *op, const wmEvent *event)
{
short snap = RNA_boolean_get(op->ptr, "snap");
SK_Sketch *sketch = contextSketch(C, 0);
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 5376c897c29..3ac514f1465 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -30,18 +30,12 @@
* \ingroup edarmature
*/
-
-#include <math.h>
-#include <string.h>
-
#include "MEM_guardedalloc.h"
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_edgehash.h"
#include "BLI_memarena.h"
@@ -59,8 +53,6 @@
#include "ONL_opennl.h"
-#include "BLO_sys_types.h" // for intptr_t support
-
#include "ED_mesh.h"
#include "ED_armature.h"
@@ -649,7 +641,9 @@ static float heat_limit_weight(float weight)
return weight;
}
-void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3], int *selected, const char **err_str)
+void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
+ bDeformGroup **dgrouplist, bDeformGroup **dgroupflip,
+ float (*root)[3], float (*tip)[3], int *selected, const char **err_str)
{
LaplacianSystem *sys;
MPoly *mp;
@@ -666,8 +660,8 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
*err_str = NULL;
/* count triangles and create mask */
- if ((use_face_sel = ((me->editflag & ME_EDIT_PAINT_MASK) != 0)) ||
- (use_vert_sel = ((me->editflag & ME_EDIT_VERT_SEL) != 0)))
+ if ((use_face_sel = ((me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0)) ||
+ (use_vert_sel = ((me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0)))
{
mask = MEM_callocN(sizeof(int) * me->totvert, "heat_bone_weighting mask");
@@ -1767,7 +1761,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_faces(&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)
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
new file mode 100644
index 00000000000..40b96132699
--- /dev/null
+++ b/source/blender/editors/armature/pose_edit.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.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Ton Roosendaal, Blender Foundation '05, full recode.
+ * Joshua Leung
+ * Reevan McKay (original NaN code)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Pose Mode API's and Operators for Pose Mode armatures
+ */
+
+/** \file blender/editors/armature/pose_edit.c
+ * \ingroup edarmature
+ */
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_anim.h"
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_depsgraph.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_armature.h"
+#include "ED_keyframing.h"
+#include "ED_screen.h"
+#include "ED_object.h"
+
+#include "UI_interface.h"
+
+#include "armature_intern.h"
+
+/* matches logic with ED_operator_posemode_context() */
+Object *ED_pose_object_from_context(bContext *C)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ Object *ob;
+
+ /* since this call may also be used from the buttons window, we need to check for where to get the object */
+ if (sa && sa->spacetype == SPACE_BUTS) {
+ ob = ED_object_context(C);
+ }
+ else {
+ ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ }
+
+ return ob;
+}
+
+/* This function is used to process the necessary updates for */
+void ED_armature_enter_posemode(bContext *C, Base *base)
+{
+ ReportList *reports = CTX_wm_reports(C);
+ Object *ob = base->object;
+
+ if (ob->id.lib) {
+ BKE_report(reports, RPT_WARNING, "Cannot pose libdata");
+ return;
+ }
+
+ switch (ob->type) {
+ case OB_ARMATURE:
+ ob->restore_mode = ob->mode;
+ ob->mode |= OB_MODE_POSE;
+
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_POSE, NULL);
+
+ break;
+ default:
+ return;
+ }
+
+ /* XXX: disabled as this would otherwise cause a nasty loop... */
+ //ED_object_toggle_modes(C, ob->mode);
+}
+
+void ED_armature_exit_posemode(bContext *C, Base *base)
+{
+ if (base) {
+ Object *ob = base->object;
+
+ ob->restore_mode = ob->mode;
+ ob->mode &= ~OB_MODE_POSE;
+
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
+ }
+}
+
+/* if a selected or active bone is protected, throw error (oonly if warn == 1) and return 1 */
+/* only_selected == 1: the active bone is allowed to be protected */
+#if 0 /* UNUSED 2.5 */
+static short pose_has_protected_selected(Object *ob, short warn)
+{
+ /* check protection */
+ if (ob->proxy) {
+ bPoseChannel *pchan;
+ bArmature *arm = ob->data;
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->bone && (pchan->bone->layer & arm->layer)) {
+ if (pchan->bone->layer & arm->layer_protected) {
+ if (pchan->bone->flag & BONE_SELECTED)
+ break;
+ }
+ }
+ }
+ if (pchan) {
+ if (warn) error("Cannot change Proxy protected bones");
+ return 1;
+ }
+ }
+ return 0;
+}
+#endif
+
+/* only for real IK, not for auto-IK */
+static int pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan, int level)
+{
+ bConstraint *con;
+ Bone *bone;
+
+ /* No need to check if constraint is active (has influence),
+ * since all constraints with CONSTRAINT_IK_AUTO are active */
+ for (con = pchan->constraints.first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
+ bKinematicConstraint *data = con->data;
+ if (data->rootbone == 0 || data->rootbone > level) {
+ if ((data->flag & CONSTRAINT_IK_AUTO) == 0)
+ return 1;
+ }
+ }
+ }
+ for (bone = pchan->bone->childbase.first; bone; bone = bone->next) {
+ pchan = BKE_pose_channel_find_name(ob->pose, bone->name);
+ if (pchan && pose_channel_in_IK_chain(ob, pchan, level + 1))
+ return 1;
+ }
+ return 0;
+}
+
+int ED_pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan)
+{
+ return pose_channel_in_IK_chain(ob, pchan, 0);
+}
+
+/* ********************************************** */
+/* Motion Paths */
+
+/* For the object with pose/action: update paths for those that have got them
+ * This should selectively update paths that exist...
+ *
+ * To be called from various tools that do incremental updates
+ */
+void ED_pose_recalculate_paths(Scene *scene, Object *ob)
+{
+ ListBase targets = {NULL, NULL};
+
+ /* set flag to force recalc, then grab the relevant bones to target */
+ ob->pose->avs.recalc |= ANIMVIZ_RECALC_PATHS;
+ animviz_get_object_motionpaths(ob, &targets);
+
+ /* recalculate paths, then free */
+ animviz_calc_motionpaths(scene, &targets);
+ BLI_freelistN(&targets);
+}
+
+
+/* show popup to determine settings */
+static int pose_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+
+ /* set default settings from existing/stored settings */
+ {
+ bAnimVizSettings *avs = &ob->pose->avs;
+ PointerRNA avs_ptr;
+
+ RNA_int_set(op->ptr, "start_frame", avs->path_sf);
+ RNA_int_set(op->ptr, "end_frame", avs->path_ef);
+
+ RNA_pointer_create(NULL, &RNA_AnimVizMotionPaths, avs, &avs_ptr);
+ RNA_enum_set(op->ptr, "bake_location", RNA_enum_get(&avs_ptr, "bake_location"));
+ }
+
+ /* show popup dialog to allow editing of range... */
+ // FIXME: hardcoded dimensions here are just arbitrary
+ return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 10 * UI_UNIT_Y);
+}
+
+/* For the object with pose/action: create path curves for selected bones
+ * This recalculates the WHOLE path within the pchan->pathsf and pchan->pathef range
+ */
+static int pose_calculate_paths_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ Scene *scene = CTX_data_scene(C);
+
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+
+ /* grab baking settings from operator settings */
+ {
+ bAnimVizSettings *avs = &ob->pose->avs;
+ PointerRNA avs_ptr;
+
+ avs->path_sf = RNA_int_get(op->ptr, "start_frame");
+ avs->path_ef = RNA_int_get(op->ptr, "end_frame");
+
+ RNA_pointer_create(NULL, &RNA_AnimVizMotionPaths, avs, &avs_ptr);
+ RNA_enum_set(&avs_ptr, "bake_location", RNA_enum_get(op->ptr, "bake_location"));
+ }
+
+ /* set up path data for bones being calculated */
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
+ {
+ /* verify makes sure that the selected bone has a bone with the appropriate settings */
+ animviz_verify_motionpaths(op->reports, scene, ob, pchan);
+ }
+ CTX_DATA_END;
+
+ /* calculate the bones that now have motionpaths... */
+ /* TODO: only make for the selected bones? */
+ ED_pose_recalculate_paths(scene, ob);
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_paths_calculate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Calculate Bone Paths";
+ ot->idname = "POSE_OT_paths_calculate";
+ ot->description = "Calculate paths for the selected bones";
+
+ /* api callbacks */
+ ot->invoke = pose_calculate_paths_invoke;
+ ot->exec = pose_calculate_paths_exec;
+ ot->poll = ED_operator_posemode_exclusive;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "start_frame", 1, MINAFRAME, MAXFRAME, "Start",
+ "First frame to calculate bone paths on", MINFRAME, MAXFRAME / 2.0);
+ RNA_def_int(ot->srna, "end_frame", 250, MINAFRAME, MAXFRAME, "End",
+ "Last frame to calculate bone paths on", MINFRAME, MAXFRAME / 2.0);
+
+ RNA_def_enum(ot->srna, "bake_location", motionpath_bake_location_items, 0,
+ "Bake Location",
+ "Which point on the bones is used when calculating paths");
+}
+
+/* --------- */
+
+static int pose_update_paths_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ Scene *scene = CTX_data_scene(C);
+
+ if (ELEM(NULL, ob, scene))
+ return OPERATOR_CANCELLED;
+
+ /* calculate the bones that now have motionpaths... */
+ /* TODO: only make for the selected bones? */
+ ED_pose_recalculate_paths(scene, ob);
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_paths_update(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Update Bone Paths";
+ ot->idname = "POSE_OT_paths_update";
+ ot->description = "Recalculate paths for bones that already have them";
+
+ /* api callbakcs */
+ ot->exec = pose_update_paths_exec;
+ ot->poll = ED_operator_posemode_exclusive; /* TODO: this should probably check for active bone and/or existing paths */
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* --------- */
+
+/* for the object with pose/action: clear path curves for selected bones only */
+static void ED_pose_clear_paths(Object *ob)
+{
+ bPoseChannel *pchan;
+ short skipped = 0;
+
+ if (ELEM(NULL, ob, ob->pose))
+ return;
+
+ /* free the motionpath blocks, but also take note of whether we skipped some... */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->mpath) {
+ if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) {
+ animviz_free_motionpath(pchan->mpath);
+ pchan->mpath = NULL;
+ }
+ else
+ skipped = 1;
+ }
+ }
+
+ /* if we didn't skip any, we shouldn't have any paths left */
+ if (skipped == 0)
+ ob->pose->avs.path_bakeflag &= ~MOTIONPATH_BAKE_HAS_PATHS;
+}
+
+/* operator callback for this */
+static int pose_clear_paths_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+
+ /* only continue if there's an object */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+
+ /* use the backend function for this */
+ ED_pose_clear_paths(ob);
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_paths_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Clear Bone Paths";
+ ot->idname = "POSE_OT_paths_clear";
+ ot->description = "Clear path caches for selected bones";
+
+ /* api callbacks */
+ ot->exec = pose_clear_paths_exec;
+ ot->poll = ED_operator_posemode_exclusive;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ********************************************** */
+#if 0 /* UNUSED 2.5 */
+static void pose_copy_menu(Scene *scene)
+{
+ Object *obedit = scene->obedit; // XXX context
+ Object *ob = OBACT;
+ bArmature *arm;
+ bPoseChannel *pchan, *pchanact;
+ short nr = 0;
+ int i = 0;
+
+ /* paranoia checks */
+ if (ELEM(NULL, ob, ob->pose)) return;
+ if ((ob == obedit) || (ob->mode & OB_MODE_POSE) == 0) return;
+
+ pchan = BKE_pose_channel_active(ob);
+
+ if (pchan == NULL) return;
+ pchanact = pchan;
+ arm = ob->data;
+
+ /* if proxy-protected bones selected, some things (such as locks + displays) shouldn't be changeable,
+ * 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 */
+ 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 */
+ 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
+ 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|%l|Transform Locks %x6|IK Limits %x7|Bone Shape %x8");
+ }
+
+ if (nr <= 0)
+ return;
+
+ if (nr != 5) {
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if ((arm->layer & pchan->bone->layer) &&
+ (pchan->bone->flag & BONE_SELECTED) &&
+ (pchan != pchanact) )
+ {
+ switch (nr) {
+ case 1: /* Local Location */
+ copy_v3_v3(pchan->loc, pchanact->loc);
+ break;
+ case 2: /* Local Rotation */
+ copy_qt_qt(pchan->quat, pchanact->quat);
+ copy_v3_v3(pchan->eul, pchanact->eul);
+ break;
+ case 3: /* Local Size */
+ copy_v3_v3(pchan->size, pchanact->size);
+ break;
+ case 4: /* All Constraints */
+ {
+ ListBase tmp_constraints = {NULL, NULL};
+
+ /* copy constraints to tmpbase and apply 'local' tags before
+ * appending to list of constraints for this channel
+ */
+ BKE_copy_constraints(&tmp_constraints, &pchanact->constraints, TRUE);
+ if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) {
+ bConstraint *con;
+
+ /* add proxy-local tags */
+ for (con = tmp_constraints.first; con; con = con->next)
+ con->flag |= CONSTRAINT_PROXY_LOCAL;
+ }
+ BLI_movelisttolist(&pchan->constraints, &tmp_constraints);
+
+ /* update flags (need to add here, not just copy) */
+ pchan->constflag |= pchanact->constflag;
+
+ if (ob->pose)
+ ob->pose->flag |= POSE_RECALC;
+ }
+ break;
+ case 6: /* Transform Locks */
+ pchan->protectflag = pchanact->protectflag;
+ break;
+ case 7: /* IK (DOF) settings */
+ {
+ pchan->ikflag = pchanact->ikflag;
+ copy_v3_v3(pchan->limitmin, pchanact->limitmin);
+ copy_v3_v3(pchan->limitmax, pchanact->limitmax);
+ copy_v3_v3(pchan->stiffness, pchanact->stiffness);
+ pchan->ikstretch = pchanact->ikstretch;
+ pchan->ikrotweight = pchanact->ikrotweight;
+ pchan->iklinweight = pchanact->iklinweight;
+ }
+ break;
+ case 8: /* Custom Bone Shape */
+ pchan->custom = pchanact->custom;
+ break;
+ case 9: /* Visual Location */
+ BKE_armature_loc_pose_to_bone(pchan, pchanact->pose_mat[3], pchan->loc);
+ break;
+ case 10: /* Visual Rotation */
+ {
+ float delta_mat[4][4];
+
+ BKE_armature_mat_pose_to_bone(pchan, pchanact->pose_mat, delta_mat);
+
+ if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ float tmp_quat[4];
+
+ /* need to convert to quat first (in temp var)... */
+ mat4_to_quat(tmp_quat, delta_mat);
+ quat_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, tmp_quat);
+ }
+ else if (pchan->rotmode == ROT_MODE_QUAT)
+ mat4_to_quat(pchan->quat, delta_mat);
+ else
+ mat4_to_eulO(pchan->eul, pchan->rotmode, delta_mat);
+ }
+ break;
+ case 11: /* Visual Size */
+ {
+ float delta_mat[4][4], size[4];
+
+ BKE_armature_mat_pose_to_bone(pchan, pchanact->pose_mat, delta_mat);
+ mat4_to_size(size, delta_mat);
+ copy_v3_v3(pchan->size, size);
+ }
+ }
+ }
+ }
+ }
+ else { /* constraints, optional (note: max we can have is 24 constraints) */
+ bConstraint *con, *con_back;
+ int const_toggle[24] = {0}; /* XXX, initialize as 0 to quiet errors */
+ ListBase const_copy = {NULL, NULL};
+
+ BLI_duplicatelist(&const_copy, &(pchanact->constraints));
+
+ /* 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]), "");
+ }
+
+// if (!do_clever_numbuts("Select Constraints", i, REDRAW)) {
+// BLI_freelistN(&const_copy);
+// return;
+// }
+
+ /* now build a new listbase from the options selected */
+ for (i = 0, con = const_copy.first; con; i++) {
+ /* if not selected, free/remove it from the list */
+ if (!const_toggle[i]) {
+ con_back = con->next;
+ BLI_freelinkN(&const_copy, con);
+ con = con_back;
+ }
+ else
+ con = con->next;
+ }
+
+ /* Copy the temo listbase to the selected posebones */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if ((arm->layer & pchan->bone->layer) &&
+ (pchan->bone->flag & BONE_SELECTED) &&
+ (pchan != pchanact) )
+ {
+ ListBase tmp_constraints = {NULL, NULL};
+
+ /* copy constraints to tmpbase and apply 'local' tags before
+ * appending to list of constraints for this channel
+ */
+ BKE_copy_constraints(&tmp_constraints, &const_copy, TRUE);
+ if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) {
+ /* add proxy-local tags */
+ for (con = tmp_constraints.first; con; con = con->next)
+ con->flag |= CONSTRAINT_PROXY_LOCAL;
+ }
+ BLI_movelisttolist(&pchan->constraints, &tmp_constraints);
+
+ /* update flags (need to add here, not just copy) */
+ pchan->constflag |= pchanact->constflag;
+ }
+ }
+ BLI_freelistN(&const_copy);
+ 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;
+ }
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA); // and all its relations
+
+ BIF_undo_push("Copy Pose Attributes");
+
+}
+#endif
+
+/* ********************************************** */
+
+static int pose_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ bArmature *arm;
+
+ /* paranoia checks */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+ arm = ob->data;
+
+ /* loop through selected bones, auto-naming them */
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
+ {
+ char newname[MAXBONENAME];
+ flip_side_name(newname, pchan->name, TRUE);
+ ED_armature_bone_rename(arm, pchan->name, newname);
+ }
+ CTX_DATA_END;
+
+ /* since we renamed stuff... */
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+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";
+
+ /* api callbacks */
+ ot->exec = pose_flip_names_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ------------------ */
+
+static int pose_autoside_names_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ bArmature *arm;
+ char newname[MAXBONENAME];
+ short axis = RNA_enum_get(op->ptr, "axis");
+
+ /* paranoia checks */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+ arm = ob->data;
+
+ /* loop through selected bones, auto-naming them */
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
+ {
+ BLI_strncpy(newname, pchan->name, sizeof(newname));
+ if (bone_autoside_name(newname, 1, axis, pchan->bone->head[axis], pchan->bone->tail[axis]))
+ ED_armature_bone_rename(arm, pchan->name, newname);
+ }
+ CTX_DATA_END;
+
+ /* since we renamed stuff... */
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_autoside_names(wmOperatorType *ot)
+{
+ static EnumPropertyItem axis_items[] = {
+ {0, "XAXIS", 0, "X-Axis", "Left/Right"},
+ {1, "YAXIS", 0, "Y-Axis", "Front/Back"},
+ {2, "ZAXIS", 0, "Z-Axis", "Top/Bottom"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "AutoName by Axis";
+ ot->idname = "POSE_OT_autoside_names";
+ ot->description = "Automatically renames the selected bones according to which side of the target axis they fall on";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = pose_autoside_names_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* settings */
+ ot->prop = RNA_def_enum(ot->srna, "axis", axis_items, 0, "Axis", "Axis tag names with");
+}
+
+/* ********************************************** */
+
+static int pose_bone_rotmode_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ int mode = RNA_enum_get(op->ptr, "type");
+
+ /* set rotation mode of selected bones */
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
+ {
+ pchan->rotmode = mode;
+ }
+ CTX_DATA_END;
+
+ /* notifiers and updates */
+ DAG_id_tag_update((ID *)ob, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_rotation_mode_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Set Rotation Mode";
+ ot->idname = "POSE_OT_rotation_mode_set";
+ ot->description = "Set the rotation representation used by selected bones";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = pose_bone_rotmode_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", posebone_rotmode_items, 0, "Rotation Mode", "");
+}
+
+/* ********************************************** */
+
+/* Show all armature layers */
+static int pose_armature_layers_showall_poll(bContext *C)
+{
+ /* this single operator can be used in posemode OR editmode for armatures */
+ return ED_operator_posemode(C) || ED_operator_editarmature(C);
+}
+
+static int pose_armature_layers_showall_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ bArmature *arm = (ob) ? ob->data : NULL;
+ PointerRNA ptr;
+ int maxLayers = (RNA_boolean_get(op->ptr, "all")) ? 32 : 16;
+ int layers[32] = {0}; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
+ int i;
+
+ /* sanity checking */
+ if (arm == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* use RNA to set the layers
+ * although it would be faster to just set directly using bitflags, we still
+ * need to setup a RNA pointer so that we get the "update" callbacks for free...
+ */
+ RNA_id_pointer_create(&arm->id, &ptr);
+
+ for (i = 0; i < maxLayers; i++)
+ layers[i] = 1;
+
+ RNA_boolean_set_array(&ptr, "layers", layers);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_layers_show_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Show All Layers";
+ ot->idname = "ARMATURE_OT_layers_show_all";
+ ot->description = "Make all armature layers visible";
+
+ /* callbacks */
+ ot->exec = pose_armature_layers_showall_exec;
+ ot->poll = pose_armature_layers_showall_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_boolean(ot->srna, "all", 1, "All Layers", "Enable all layers or just the first 16 (top row)");
+}
+
+/* ------------------- */
+
+/* Present a popup to get the layers that should be used */
+static int pose_armature_layers_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ bArmature *arm = (ob) ? ob->data : NULL;
+ PointerRNA ptr;
+ int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
+
+ /* sanity checking */
+ if (arm == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* get RNA pointer to armature data to use that to retrieve the layers as ints to init the operator */
+ RNA_id_pointer_create((ID *)arm, &ptr);
+ RNA_boolean_get_array(&ptr, "layers", layers);
+ RNA_boolean_set_array(op->ptr, "layers", layers);
+
+ /* part to sync with other similar operators... */
+ return WM_operator_props_popup(C, op, event);
+}
+
+/* Set the visible layers for the active armature (edit and pose modes) */
+static int pose_armature_layers_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ PointerRNA ptr;
+ int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
+
+ if (ELEM(NULL, ob, ob->data)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get the values set in the operator properties */
+ RNA_boolean_get_array(op->ptr, "layers", layers);
+
+ /* get pointer for armature, and write data there... */
+ RNA_id_pointer_create((ID *)ob->data, &ptr);
+ RNA_boolean_set_array(&ptr, "layers", layers);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void POSE_OT_armature_layers(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Change Armature Layers";
+ ot->idname = "POSE_OT_armature_layers";
+ ot->description = "Change the visible armature layers";
+
+ /* callbacks */
+ ot->invoke = pose_armature_layers_invoke;
+ ot->exec = pose_armature_layers_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers to make visible");
+}
+
+void ARMATURE_OT_armature_layers(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Change Armature Layers";
+ ot->idname = "ARMATURE_OT_armature_layers";
+ ot->description = "Change the visible armature layers";
+
+ /* callbacks */
+ ot->invoke = pose_armature_layers_invoke;
+ ot->exec = pose_armature_layers_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers to make visible");
+}
+
+/* ------------------- */
+
+/* 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... */
+
+ /* get layers that are active already */
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
+ {
+ short bit;
+
+ /* 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;
+ }
+ }
+ CTX_DATA_END;
+
+ /* copy layers to operator */
+ RNA_boolean_set_array(op->ptr, "layers", layers);
+
+ /* part to sync with other similar operators... */
+ return WM_operator_props_popup(C, op, event);
+}
+
+/* Set the visible layers for the active armature (edit and pose modes) */
+static int pose_bone_layers_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ PointerRNA ptr;
+ int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
+
+ if (ob == NULL || ob->data == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get the values set in the operator properties */
+ RNA_boolean_get_array(op->ptr, "layers", layers);
+
+ /* set layers of pchans based on the values set in the operator props */
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
+ {
+ /* get pointer for pchan, and write flags this way */
+ RNA_pointer_create((ID *)ob->data, &RNA_Bone, pchan->bone, &ptr);
+ RNA_boolean_set_array(&ptr, "layers", layers);
+ }
+ CTX_DATA_END;
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_bone_layers(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Change Bone Layers";
+ ot->idname = "POSE_OT_bone_layers";
+ ot->description = "Change the layers that the selected bones belong to";
+
+ /* callbacks */
+ ot->invoke = pose_bone_layers_invoke;
+ ot->exec = pose_bone_layers_exec;
+ ot->poll = ED_operator_posemode_exclusive;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers that bone belongs to");
+}
+
+/* ------------------- */
+
+/* Present a popup to get the layers that should be used */
+static int armature_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... */
+
+ /* get layers that are active already */
+ CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones)
+ {
+ short bit;
+
+ /* 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))
+ layers[bit] = 1;
+ }
+ }
+ CTX_DATA_END;
+
+ /* copy layers to operator */
+ RNA_boolean_set_array(op->ptr, "layers", layers);
+
+ /* part to sync with other similar operators... */
+ return WM_operator_props_popup(C, op, event);
+}
+
+/* Set the visible layers for the active armature (edit and pose modes) */
+static int armature_bone_layers_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_edit_object(C);
+ bArmature *arm = (ob) ? ob->data : NULL;
+ PointerRNA ptr;
+ int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
+
+ /* get the values set in the operator properties */
+ RNA_boolean_get_array(op->ptr, "layers", layers);
+
+ /* set layers of pchans based on the values set in the operator props */
+ CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones)
+ {
+ /* get pointer for pchan, and write flags this way */
+ RNA_pointer_create((ID *)arm, &RNA_EditBone, ebone, &ptr);
+ RNA_boolean_set_array(&ptr, "layers", layers);
+ }
+ CTX_DATA_END;
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void ARMATURE_OT_bone_layers(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Change Bone Layers";
+ ot->idname = "ARMATURE_OT_bone_layers";
+ ot->description = "Change the layers that the selected bones belong to";
+
+ /* callbacks */
+ ot->invoke = armature_bone_layers_invoke;
+ ot->exec = armature_bone_layers_exec;
+ ot->poll = ED_operator_editarmature;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers that bone belongs to");
+}
+
+/* ********************************************** */
+/* Show/Hide Bones */
+
+static int hide_selected_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
+{
+ bArmature *arm = ob->data;
+
+ if (arm->layer & bone->layer) {
+ if (bone->flag & BONE_SELECTED) {
+ bone->flag |= BONE_HIDDEN_P;
+ bone->flag &= ~BONE_SELECTED;
+ if (arm->act_bone == bone)
+ arm->act_bone = NULL;
+ }
+ }
+ return 0;
+}
+
+static int hide_unselected_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
+{
+ bArmature *arm = ob->data;
+
+ if (arm->layer & bone->layer) {
+ /* hrm... typo here? */
+ if ((bone->flag & BONE_SELECTED) == 0) {
+ bone->flag |= BONE_HIDDEN_P;
+ if (arm->act_bone == bone)
+ arm->act_bone = NULL;
+ }
+ }
+ return 0;
+}
+
+/* active object is armature in posemode, poll checked */
+static int pose_hide_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ bArmature *arm = ob->data;
+
+ if (RNA_boolean_get(op->ptr, "unselected"))
+ bone_looper(ob, arm->bonebase.first, NULL, hide_unselected_pose_bone_cb);
+ else
+ bone_looper(ob, arm->bonebase.first, NULL, hide_selected_pose_bone_cb);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_hide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Hide Selected";
+ ot->idname = "POSE_OT_hide";
+ ot->description = "Tag selected bones to not be visible in Pose Mode";
+
+ /* api callbacks */
+ ot->exec = pose_hide_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "");
+}
+
+static int show_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
+{
+ bArmature *arm = ob->data;
+
+ if (arm->layer & bone->layer) {
+ if (bone->flag & BONE_HIDDEN_P) {
+ bone->flag &= ~BONE_HIDDEN_P;
+ bone->flag |= BONE_SELECTED;
+ }
+ }
+
+ return 0;
+}
+
+/* active object is armature in posemode, poll checked */
+static int pose_reveal_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ bArmature *arm = ob->data;
+
+ bone_looper(ob, arm->bonebase.first, NULL, show_pose_bone_cb);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_reveal(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Reveal Selected";
+ ot->idname = "POSE_OT_reveal";
+ ot->description = "Unhide all bones that have been tagged to be hidden in Pose Mode";
+
+ /* api callbacks */
+ ot->exec = pose_reveal_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ********************************************** */
+/* Flip Quats */
+
+static int pose_flip_quats_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID);
+
+ /* loop through all selected pchans, flipping and keying (as needed) */
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
+ {
+ /* only if bone is using quaternion rotation */
+ if (pchan->rotmode == ROT_MODE_QUAT) {
+ /* quaternions have 720 degree range */
+ negate_v4(pchan->quat);
+
+ ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
+ }
+ }
+ CTX_DATA_END;
+
+ /* notifiers and updates */
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_quaternions_flip(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Flip Quats";
+ ot->idname = "POSE_OT_quaternions_flip";
+ ot->description = "Flip quaternion values to achieve desired rotations, while maintaining the same orientations";
+
+ /* callbacks */
+ ot->exec = pose_flip_quats_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
diff --git a/source/blender/editors/armature/pose_group.c b/source/blender/editors/armature/pose_group.c
new file mode 100644
index 00000000000..99f54de134a
--- /dev/null
+++ b/source/blender/editors/armature/pose_group.c
@@ -0,0 +1,523 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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.
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Implementation of Bone Groups operators and editing API's
+ */
+
+/** \file blender/editors/armature/pose_group.c
+ * \ingroup edarmature
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_action.h"
+#include "BKE_context.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_armature.h"
+#include "ED_screen.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "armature_intern.h"
+
+/* ********************************************** */
+/* Bone Groups */
+
+static int pose_group_add_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_pose_object_from_context(C);
+
+ /* only continue if there's an object */
+ if (ob == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* for now, just call the API function for this */
+ BKE_pose_add_group(ob);
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_group_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Bone Group";
+ ot->idname = "POSE_OT_group_add";
+ ot->description = "Add a new bone group";
+
+ /* api callbacks */
+ ot->exec = pose_group_add_exec;
+ ot->poll = ED_operator_posemode_context;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
+static int pose_group_remove_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_pose_object_from_context(C);
+
+ /* only continue if there's an object */
+ if (ob == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* for now, just call the API function for this */
+ BKE_pose_remove_group(ob);
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_group_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Bone Group";
+ ot->idname = "POSE_OT_group_remove";
+ ot->description = "Remove the active bone group";
+
+ /* api callbacks */
+ ot->exec = pose_group_remove_exec;
+ ot->poll = ED_operator_posemode_context;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ------------ */
+
+/* invoke callback which presents a list of bone-groups for the user to choose from */
+static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ Object *ob = ED_pose_object_from_context(C);
+ bPose *pose;
+
+ uiPopupMenu *pup;
+ uiLayout *layout;
+ bActionGroup *grp;
+ int i;
+
+ /* only continue if there's an object, and a pose there too */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+ pose = ob->pose;
+
+ /* 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);
+
+ /* special entry - allow to create new group, then use that
+ * (not to be used for removing though)
+ */
+ if (strstr(op->idname, "assign")) {
+ uiItemIntO(layout, "New Group", ICON_NONE, op->idname, "type", 0);
+ uiItemS(layout);
+ }
+
+ /* add entries for each group */
+ for (grp = pose->agroups.first, i = 1; grp; grp = grp->next, i++)
+ 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);
+
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* just use the active group index, and call the exec callback for the calling operator */
+ RNA_int_set(op->ptr, "type", pose->active_group);
+ return op->type->exec(C, op);
+ }
+}
+
+/* Assign selected pchans to the bone group that the user selects */
+static int pose_group_assign_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_pose_object_from_context(C);
+ bPose *pose;
+ short done = FALSE;
+
+ /* only continue if there's an object, and a pose there too */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+
+ pose = ob->pose;
+
+ /* set the active group number to the one from operator props
+ * - if 0 after this, make a new group...
+ */
+ pose->active_group = RNA_int_get(op->ptr, "type");
+ if (pose->active_group == 0)
+ BKE_pose_add_group(ob);
+
+ /* add selected bones to group then */
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
+ {
+ pchan->agrp_index = pose->active_group;
+ done = TRUE;
+ }
+ CTX_DATA_END;
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ /* report done status */
+ if (done)
+ return OPERATOR_FINISHED;
+ else
+ return OPERATOR_CANCELLED;
+}
+
+void POSE_OT_group_assign(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Selected to Bone Group";
+ ot->idname = "POSE_OT_group_assign";
+ ot->description = "Add selected bones to the chosen bone group";
+
+ /* api callbacks */
+ ot->invoke = pose_groups_menu_invoke;
+ ot->exec = pose_group_assign_exec;
+ ot->poll = ED_operator_posemode_context;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "type", 0, 0, INT_MAX, "Bone Group Index", "", 0, 10);
+}
+
+
+static int pose_group_unassign_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_pose_object_from_context(C);
+ short done = FALSE;
+
+ /* only continue if there's an object, and a pose there too */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+
+ /* find selected bones to remove from all bone groups */
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
+ {
+ if (pchan->agrp_index) {
+ pchan->agrp_index = 0;
+ done = TRUE;
+ }
+ }
+ CTX_DATA_END;
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ /* report done status */
+ if (done)
+ return OPERATOR_FINISHED;
+ else
+ return OPERATOR_CANCELLED;
+}
+
+void POSE_OT_group_unassign(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Selected from Bone Groups";
+ ot->idname = "POSE_OT_group_unassign";
+ ot->description = "Remove selected bones from all bone groups";
+
+ /* api callbacks */
+ ot->exec = pose_group_unassign_exec;
+ ot->poll = ED_operator_posemode_context;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int group_move_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_pose_object_from_context(C);
+ bPose *pose = (ob) ? ob->pose : NULL;
+ bPoseChannel *pchan;
+ bActionGroup *grp;
+ int dir = RNA_enum_get(op->ptr, "direction");
+ int grpIndexA, grpIndexB;
+
+ if (ELEM(NULL, ob, pose))
+ return OPERATOR_CANCELLED;
+ if (pose->active_group <= 0)
+ return OPERATOR_CANCELLED;
+
+ /* get group to move */
+ grp = BLI_findlink(&pose->agroups, pose->active_group - 1);
+ if (grp == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* move bone group */
+ grpIndexA = pose->active_group;
+ if (dir == 1) { /* up */
+ void *prev = grp->prev;
+
+ if (prev == NULL)
+ return OPERATOR_FINISHED;
+
+ BLI_remlink(&pose->agroups, grp);
+ BLI_insertlinkbefore(&pose->agroups, prev, grp);
+
+ grpIndexB = grpIndexA - 1;
+ pose->active_group--;
+ }
+ else { /* down */
+ void *next = grp->next;
+
+ if (next == NULL)
+ return OPERATOR_FINISHED;
+
+ BLI_remlink(&pose->agroups, grp);
+ BLI_insertlinkafter(&pose->agroups, next, grp);
+
+ grpIndexB = grpIndexA + 1;
+ pose->active_group++;
+ }
+
+ /* fix changed bone group indices in bones (swap grpIndexA with grpIndexB) */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->agrp_index == grpIndexB)
+ pchan->agrp_index = grpIndexA;
+ else if (pchan->agrp_index == grpIndexA)
+ pchan->agrp_index = grpIndexB;
+ }
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_group_move(wmOperatorType *ot)
+{
+ static EnumPropertyItem group_slot_move[] = {
+ {1, "UP", 0, "Up", ""},
+ {-1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Move Bone Group";
+ ot->idname = "POSE_OT_group_move";
+ ot->description = "Change position of active Bone Group in list of Bone Groups";
+
+ /* api callbacks */
+ ot->exec = group_move_exec;
+ ot->poll = ED_operator_posemode_context;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "direction", group_slot_move, 0, "Direction", "Direction to move, UP or DOWN");
+}
+
+/* bone group sort element */
+typedef struct tSortActionGroup {
+ bActionGroup *agrp;
+ int index;
+} 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;
+
+ return strcmp(sgrp_a->agrp->name, sgrp_b->agrp->name);
+}
+
+static int group_sort_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_pose_object_from_context(C);
+ bPose *pose = (ob) ? ob->pose : NULL;
+ bPoseChannel *pchan;
+ tSortActionGroup *agrp_array;
+ bActionGroup *agrp;
+ int agrp_count;
+ int i;
+
+ if (ELEM(NULL, ob, pose))
+ return OPERATOR_CANCELLED;
+ if (pose->active_group <= 0)
+ return OPERATOR_CANCELLED;
+
+ /* create temporary array with bone groups and indices */
+ agrp_count = BLI_countlist(&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);
+ agrp_array[i].agrp = agrp;
+ agrp_array[i].index = i + 1;
+ }
+
+ /* sort bone groups by name */
+ qsort(agrp_array, agrp_count, sizeof(tSortActionGroup), compare_agroup);
+
+ /* create sorted bone group list from sorted array */
+ pose->agroups.first = pose->agroups.last = NULL;
+ for (i = 0; i < agrp_count; i++) {
+ BLI_addtail(&pose->agroups, agrp_array[i].agrp);
+ }
+
+ /* fix changed bone group indizes in bones */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ for (i = 0; i < agrp_count; i++) {
+ if (pchan->agrp_index == agrp_array[i].index) {
+ pchan->agrp_index = i + 1;
+ break;
+ }
+ }
+ }
+
+ /* free temp resources */
+ MEM_freeN(agrp_array);
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_group_sort(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Sort Bone Groups";
+ ot->idname = "POSE_OT_group_sort";
+ ot->description = "Sort Bone Groups by their names in ascending order";
+
+ /* api callbacks */
+ ot->exec = group_sort_exec;
+ ot->poll = ED_operator_posemode_context;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static void pose_group_select(bContext *C, Object *ob, int select)
+{
+ bPose *pose = ob->pose;
+
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
+ {
+ if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
+ if (select) {
+ if (pchan->agrp_index == pose->active_group)
+ pchan->bone->flag |= BONE_SELECTED;
+ }
+ else {
+ if (pchan->agrp_index == pose->active_group)
+ pchan->bone->flag &= ~BONE_SELECTED;
+ }
+ }
+ }
+ CTX_DATA_END;
+}
+
+static int pose_group_select_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_pose_object_from_context(C);
+
+ /* only continue if there's an object, and a pose there too */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+
+ pose_group_select(C, ob, 1);
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_group_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Bones of Bone Group";
+ ot->idname = "POSE_OT_group_select";
+ ot->description = "Select bones in active Bone Group";
+
+ /* api callbacks */
+ ot->exec = pose_group_select_exec;
+ ot->poll = ED_operator_posemode_context;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int pose_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_pose_object_from_context(C);
+
+ /* only continue if there's an object, and a pose there too */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+
+ pose_group_select(C, ob, 0);
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_group_deselect(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Deselect Bone Group";
+ ot->idname = "POSE_OT_group_deselect";
+ ot->description = "Deselect bones of active Bone Group";
+
+ /* api callbacks */
+ ot->exec = pose_group_deselect_exec;
+ ot->poll = ED_operator_posemode_context;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ********************************************** */
diff --git a/source/blender/editors/armature/poselib.c b/source/blender/editors/armature/pose_lib.c
index ae3d496b641..09c0f7e9647 100644
--- a/source/blender/editors/armature/poselib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -23,25 +23,17 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/editors/armature/poselib.c
+/** \file blender/editors/armature/pose_lib.c
* \ingroup edarmature
*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stddef.h>
#include <string.h>
#include <math.h>
-#include <float.h>
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
-#include "BLI_dynstr.h"
#include "BLI_dlrbTree.h"
-#include "BLI_utildefines.h"
#include "BLF_translation.h"
@@ -54,6 +46,7 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_depsgraph.h"
+#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
#include "BKE_object.h"
@@ -196,7 +189,7 @@ static bAction *poselib_init_new(Object *ob)
/* init object's poselib action (unlink old one if there) */
if (ob->poselib)
id_us_min(&ob->poselib->id);
- ob->poselib = add_empty_action("PoseLib");
+ ob->poselib = add_empty_action(G.main, "PoseLib");
return ob->poselib;
}
@@ -396,7 +389,7 @@ static void poselib_add_menu_invoke__replacemenu(bContext *C, uiLayout *layout,
}
}
-static int poselib_add_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt))
+static int poselib_add_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Scene *scene = CTX_data_scene(C);
Object *ob = get_poselib_object(C);
@@ -620,7 +613,7 @@ void POSELIB_OT_pose_remove(wmOperatorType *ot)
ot->prop = prop;
}
-static int poselib_rename_invoke(bContext *C, wmOperator *op, wmEvent *evt)
+static int poselib_rename_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Object *ob = get_poselib_object(C);
bAction *act = (ob) ? ob->poselib : NULL;
@@ -645,7 +638,7 @@ static int poselib_rename_invoke(bContext *C, wmOperator *op, wmEvent *evt)
}
/* part to sync with other similar operators... */
- return WM_operator_props_popup(C, op, evt);
+ return WM_operator_props_popup(C, op, event);
}
static int poselib_rename_exec(bContext *C, wmOperator *op)
@@ -662,7 +655,7 @@ static int poselib_rename_exec(bContext *C, wmOperator *op)
}
/* get index (and pointer) of pose to remove */
- marker = BLI_findlink(&act->markers, RNA_int_get(op->ptr, "pose"));
+ marker = BLI_findlink(&act->markers, RNA_enum_get(op->ptr, "pose"));
if (marker == NULL) {
BKE_report(op->reports, RPT_ERROR, "Invalid index for pose");
return OPERATOR_CANCELLED;
@@ -687,9 +680,6 @@ static int poselib_rename_exec(bContext *C, wmOperator *op)
void POSELIB_OT_pose_rename(wmOperatorType *ot)
{
PropertyRNA *prop;
- static EnumPropertyItem prop_poses_dummy_types[] = {
- {0, NULL, 0, NULL, NULL}
- };
/* identifiers */
ot->name = "PoseLib Rename Pose";
@@ -707,7 +697,7 @@ void POSELIB_OT_pose_rename(wmOperatorType *ot)
/* properties */
/* NOTE: name not pose is the operator's "main" property, so that it will get activated in the popup for easy renaming */
ot->prop = RNA_def_string(ot->srna, "name", "RenamedPose", 64, "New Pose Name", "New name for pose");
- prop = RNA_def_enum(ot->srna, "pose", prop_poses_dummy_types, 0, "Pose", "The pose to rename");
+ prop = RNA_def_enum(ot->srna, "pose", DummyRNA_NULL_items, 0, "Pose", "The pose to rename");
RNA_def_enum_funcs(prop, poselib_stored_pose_itemf);
}
@@ -1195,7 +1185,7 @@ static void poselib_preview_handle_search(tPoseLib_PreviewData *pld, unsigned sh
}
/* handle events for poselib_preview_poses */
-static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, wmEvent *event)
+static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, const wmEvent *event)
{
tPoseLib_PreviewData *pld = op->customdata;
int ret = OPERATOR_RUNNING_MODAL;
@@ -1549,7 +1539,7 @@ static int poselib_preview_cancel(bContext *C, wmOperator *op)
}
/* main modal status check */
-static int poselib_preview_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int poselib_preview_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
tPoseLib_PreviewData *pld = op->customdata;
int ret;
@@ -1569,7 +1559,7 @@ static int poselib_preview_modal(bContext *C, wmOperator *op, wmEvent *event)
}
/* Modal Operator init */
-static int poselib_preview_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int poselib_preview_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
tPoseLib_PreviewData *pld;
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
new file mode 100644
index 00000000000..c599e978e58
--- /dev/null
+++ b/source/blender/editors/armature/pose_select.c
@@ -0,0 +1,853 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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, 2002-2009 full recode.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/armature/pose_select.c
+ * \ingroup edarmature
+ */
+
+#include <string.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 "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_constraint.h"
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_depsgraph.h"
+#include "BKE_object.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_armature.h"
+#include "ED_keyframing.h"
+#include "ED_mesh.h"
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "armature_intern.h"
+
+/* ***************** Pose Select Utilities ********************* */
+
+/* called from editview.c, for mode-less pose selection */
+/* assumes scene obact and basact is still on old situation */
+int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits,
+ bool extend, bool deselect, bool toggle)
+{
+ Object *ob = base->object;
+ Bone *nearBone;
+
+ if (!ob || !ob->pose) return 0;
+
+ nearBone = get_bone_from_selectbuffer(scene, base, buffer, hits, 1);
+
+ /* if the bone cannot be affected, don't do anything */
+ if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) {
+ Object *ob_act = OBACT;
+ bArmature *arm = ob->data;
+
+ /* since we do unified select, we don't shift+select a bone if the
+ * armature object was not active yet.
+ * note, special exception for armature mode so we can do multi-select
+ * we could check for multi-select explicitly but think its fine to
+ * always give predictable behavior in weight paint mode - campbell */
+ if ((!extend && !deselect && !toggle) ||
+ ((ob_act && (ob_act != ob) && (ob_act->mode & OB_MODE_WEIGHT_PAINT) == 0)))
+ {
+ ED_pose_deselectall(ob, 0);
+ nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ arm->act_bone = nearBone;
+ }
+ else {
+ if (extend) {
+ nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ arm->act_bone = nearBone;
+ }
+ else if (deselect) {
+ nearBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else if (toggle) {
+ if (nearBone->flag & BONE_SELECTED) {
+ /* if not active, we make it active */
+ if (nearBone != arm->act_bone) {
+ arm->act_bone = nearBone;
+ }
+ else {
+ nearBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
+ else {
+ nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ arm->act_bone = nearBone;
+ }
+ }
+ }
+
+ if (ob_act) {
+ /* in weightpaint we select the associated vertex group too */
+ if (ob_act->mode & OB_MODE_WEIGHT_PAINT) {
+ if (nearBone == arm->act_bone) {
+ ED_vgroup_select_by_name(ob_act, nearBone->name);
+ DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
+ }
+ }
+ /* if there are some dependencies for visualizing armature state
+ * (e.g. Mask Modifier in 'Armature' mode), force update
+ */
+ else if (arm->flag & ARM_HAS_VIZ_DEPS) {
+ DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
+ }
+ }
+ }
+
+ return nearBone != NULL;
+}
+
+/* test==0: deselect all
+ * test==1: swap select (apply to all the opposite of current situation)
+ * test==2: only clear active tag
+ * test==3: swap select (no test / inverse selection status of all independently)
+ */
+void ED_pose_deselectall(Object *ob, int test)
+{
+ bArmature *arm = ob->data;
+ bPoseChannel *pchan;
+ int selectmode = 0;
+
+ /* we call this from outliner too */
+ if (ob->pose == NULL) {
+ return;
+ }
+
+ /* Determine if we're selecting or deselecting */
+ if (test == 1) {
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (PBONE_VISIBLE(arm, pchan->bone)) {
+ if (pchan->bone->flag & BONE_SELECTED)
+ break;
+ }
+ }
+
+ if (pchan == NULL)
+ selectmode = 1;
+ }
+ else if (test == 2)
+ selectmode = 2;
+
+ /* Set the flags accordingly */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ /* ignore the pchan if it isn't visible or if its selection cannot be changed */
+ if ((pchan->bone->layer & arm->layer) && !(pchan->bone->flag & (BONE_HIDDEN_P | BONE_UNSELECTABLE))) {
+ if (test == 3) {
+ pchan->bone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else {
+ if (selectmode == 0) pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ else if (selectmode == 1) pchan->bone->flag |= BONE_SELECTED;
+ }
+ }
+ }
+}
+
+/* ***************** Selections ********************** */
+
+static void selectconnected_posebonechildren(Object *ob, Bone *bone, int extend)
+{
+ Bone *curBone;
+
+ /* stop when unconnected child is encontered, or when unselectable bone is encountered */
+ if (!(bone->flag & BONE_CONNECTED) || (bone->flag & BONE_UNSELECTABLE))
+ return;
+
+ /* XXX old cruft! use notifiers instead */
+ //select_actionchannel_by_name (ob->action, bone->name, !(shift));
+
+ if (extend)
+ bone->flag &= ~BONE_SELECTED;
+ else
+ bone->flag |= BONE_SELECTED;
+
+ for (curBone = bone->childbase.first; curBone; curBone = curBone->next)
+ selectconnected_posebonechildren(ob, curBone, extend);
+}
+
+/* within active object context */
+/* previously known as "selectconnected_posearmature" */
+static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ bArmature *arm = (bArmature *)ob->data;
+ Bone *bone, *curBone, *next = NULL;
+ int extend = RNA_boolean_get(op->ptr, "extend");
+
+ view3d_operator_needs_opengl(C);
+
+ if (extend)
+ bone = get_nearest_bone(C, 0, event->mval[0], event->mval[1]);
+ else
+ bone = get_nearest_bone(C, 1, event->mval[0], event->mval[1]);
+
+ if (!bone)
+ return OPERATOR_CANCELLED;
+
+ /* Select parents */
+ for (curBone = bone; curBone; curBone = next) {
+ /* ignore bone if cannot be selected */
+ if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
+ if (extend)
+ curBone->flag &= ~BONE_SELECTED;
+ else
+ curBone->flag |= BONE_SELECTED;
+
+ if (curBone->flag & BONE_CONNECTED)
+ next = curBone->parent;
+ else
+ next = NULL;
+ }
+ else
+ next = NULL;
+ }
+
+ /* Select children */
+ for (curBone = bone->childbase.first; curBone; curBone = next)
+ selectconnected_posebonechildren(ob, curBone, extend);
+
+ /* updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+
+ if (arm->flag & ARM_HAS_VIZ_DEPS) {
+ /* mask modifier ('armature' mode), etc. */
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static int pose_select_linked_poll(bContext *C)
+{
+ return (ED_operator_view3d_active(C) && ED_operator_posemode(C));
+}
+
+void POSE_OT_select_linked(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Connected";
+ ot->idname = "POSE_OT_select_linked";
+ ot->description = "Select bones related to selected ones by parent/child relationships";
+
+ /* api callbacks */
+ ot->exec = NULL;
+ ot->invoke = pose_select_connected_invoke;
+ ot->poll = pose_select_linked_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first");
+}
+
+/* -------------------------------------- */
+
+static int pose_de_select_all_exec(bContext *C, wmOperator *op)
+{
+ int action = RNA_enum_get(op->ptr, "action");
+
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_context(C);
+ bArmature *arm = ob->data;
+ int multipaint = scene->toolsettings->multipaint;
+
+ if (action == SEL_TOGGLE) {
+ action = CTX_DATA_COUNT(C, selected_pose_bones) ? SEL_DESELECT : SEL_SELECT;
+ }
+
+ /* Set the flags */
+ CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones)
+ {
+ /* select pchan only if selectable, but deselect works always */
+ switch (action) {
+ case SEL_SELECT:
+ if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0)
+ pchan->bone->flag |= BONE_SELECTED;
+ break;
+ case SEL_DESELECT:
+ pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ break;
+ case SEL_INVERT:
+ if (pchan->bone->flag & BONE_SELECTED) {
+ pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
+ pchan->bone->flag |= BONE_SELECTED;
+ }
+ break;
+ }
+ }
+ CTX_DATA_END;
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
+
+ /* weightpaint or mask modifiers need depsgraph updates */
+ if (multipaint || (arm->flag & ARM_HAS_VIZ_DEPS)) {
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_select_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->idname = "POSE_OT_select_all";
+ ot->description = "Toggle selection status of all bones";
+
+ /* api callbacks */
+ ot->exec = pose_de_select_all_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ WM_operator_properties_select_all(ot);
+}
+
+/* -------------------------------------- */
+
+static int pose_select_parent_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ bArmature *arm = (bArmature *)ob->data;
+ bPoseChannel *pchan, *parent;
+
+ /* Determine if there is an active bone */
+ pchan = CTX_data_active_pose_bone(C);
+ if (pchan) {
+ parent = pchan->parent;
+ if ((parent) && !(parent->bone->flag & (BONE_HIDDEN_P | BONE_UNSELECTABLE))) {
+ parent->bone->flag |= BONE_SELECTED;
+ arm->act_bone = parent->bone;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+
+ if (arm->flag & ARM_HAS_VIZ_DEPS) {
+ /* mask modifier ('armature' mode), etc. */
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_select_parent(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Parent Bone";
+ ot->idname = "POSE_OT_select_parent";
+ ot->description = "Select bones that are parents of the currently selected bones";
+
+ /* api callbacks */
+ ot->exec = pose_select_parent_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* -------------------------------------- */
+
+static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ bArmature *arm = (bArmature *)ob->data;
+ bConstraint *con;
+ int found = 0;
+
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
+ {
+ if (pchan->bone->flag & BONE_SELECTED) {
+ for (con = pchan->constraints.first; con; con = con->next) {
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(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) && (ct->subtarget[0])) {
+ bPoseChannel *pchanc = BKE_pose_channel_find_name(ob->pose, ct->subtarget);
+ if ((pchanc) && !(pchanc->bone->flag & BONE_UNSELECTABLE)) {
+ pchanc->bone->flag |= BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL;
+ found = 1;
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 1);
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ if (!found)
+ return OPERATOR_CANCELLED;
+
+ /* updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+
+ if (arm->flag & ARM_HAS_VIZ_DEPS) {
+ /* mask modifier ('armature' mode), etc. */
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_select_constraint_target(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Constraint Target";
+ ot->idname = "POSE_OT_select_constraint_target";
+ ot->description = "Select bones used as targets for the currently selected bones";
+
+ /* api callbacks */
+ ot->exec = pose_select_constraint_target_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* -------------------------------------- */
+
+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;
+ int direction = RNA_enum_get(op->ptr, "direction");
+ int add_to_sel = RNA_boolean_get(op->ptr, "extend");
+ int found = 0;
+
+ 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;
+ }
+ }
+ 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;
+ }
+ }
+ }
+ }
+
+ 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;
+ }
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ if (found == 0)
+ return OPERATOR_CANCELLED;
+
+ /* updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+
+ if (arm->flag & ARM_HAS_VIZ_DEPS) {
+ /* mask modifier ('armature' mode), etc. */
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_select_hierarchy(wmOperatorType *ot)
+{
+ static EnumPropertyItem direction_items[] = {
+ {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
+ {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Select Hierarchy";
+ ot->idname = "POSE_OT_select_hierarchy";
+ ot->description = "Select immediate parent/children of selected bones";
+
+ /* api callbacks */
+ ot->exec = pose_select_hierarchy_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ ot->prop = RNA_def_enum(ot->srna, "direction", direction_items, BONE_SELECT_PARENT, "Direction", "");
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+}
+
+/* -------------------------------------- */
+
+static short pose_select_same_group(bContext *C, Object *ob, bool extend)
+{
+ bArmature *arm = (ob) ? ob->data : NULL;
+ bPose *pose = (ob) ? ob->pose : NULL;
+ char *group_flags;
+ int numGroups = 0;
+ short changed = 0, tagged = 0;
+
+ /* sanity checks */
+ if (ELEM3(NULL, ob, pose, arm))
+ return 0;
+
+ /* count the number of groups */
+ numGroups = BLI_countlist(&pose->agroups);
+ if (numGroups == 0)
+ return 0;
+
+ /* alloc a small array to keep track of the groups to use
+ * - each cell stores on/off state for whether group should be used
+ * - size is (numGroups + 1), since (index = 0) is used for no-group
+ */
+ group_flags = MEM_callocN(numGroups + 1, "pose_select_same_group");
+
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
+ {
+ /* keep track of group as group to use later? */
+ if (pchan->bone->flag & BONE_SELECTED) {
+ group_flags[pchan->agrp_index] = 1;
+ tagged = 1;
+ }
+
+ /* deselect all bones before selecting new ones? */
+ if ((extend == false) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0)
+ pchan->bone->flag &= ~BONE_SELECTED;
+ }
+ CTX_DATA_END;
+
+ /* small optimization: only loop through bones a second time if there are any groups tagged */
+ if (tagged) {
+ /* only if group matches (and is not selected or current bone) */
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
+ {
+ if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
+ /* check if the group used by this bone is counted */
+ if (group_flags[pchan->agrp_index]) {
+ pchan->bone->flag |= BONE_SELECTED;
+ changed = 1;
+ }
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ /* free temp info */
+ MEM_freeN(group_flags);
+
+ return changed;
+}
+
+static short pose_select_same_layer(bContext *C, Object *ob, bool extend)
+{
+ bPose *pose = (ob) ? ob->pose : NULL;
+ bArmature *arm = (ob) ? ob->data : NULL;
+ short changed = 0;
+ int layers = 0;
+
+ if (ELEM3(NULL, ob, pose, arm))
+ return 0;
+
+ /* figure out what bones are selected */
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
+ {
+ /* keep track of layers to use later? */
+ if (pchan->bone->flag & BONE_SELECTED)
+ layers |= pchan->bone->layer;
+
+ /* deselect all bones before selecting new ones? */
+ if ((extend == false) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0)
+ pchan->bone->flag &= ~BONE_SELECTED;
+ }
+ CTX_DATA_END;
+ if (layers == 0)
+ return 0;
+
+ /* select bones that are on same layers as layers flag */
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
+ {
+ /* if bone is on a suitable layer, and the bone can have its selection changed, select it */
+ if ((layers & pchan->bone->layer) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
+ pchan->bone->flag |= BONE_SELECTED;
+ changed = 1;
+ }
+ }
+ CTX_DATA_END;
+
+ return changed;
+}
+
+static int pose_select_same_keyingset(bContext *C, Object *ob, bool extend)
+{
+ KeyingSet *ks = ANIM_scene_get_active_keyingset(CTX_data_scene(C));
+ KS_Path *ksp;
+
+ bArmature *arm = (ob) ? ob->data : NULL;
+ bPose *pose = (ob) ? ob->pose : NULL;
+ short changed = 0;
+
+ /* sanity checks: validate Keying Set and object */
+ if ((ks == NULL) || (ANIM_validate_keyingset(C, NULL, ks) != 0))
+ return 0;
+
+ if (ELEM3(NULL, ob, pose, arm))
+ return 0;
+
+ /* if not extending selection, deselect all selected first */
+ if (extend == false) {
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
+ {
+ if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0)
+ pchan->bone->flag &= ~BONE_SELECTED;
+ }
+ CTX_DATA_END;
+ }
+
+ /* iterate over elements in the Keying Set, setting selection depending on whether
+ * that bone is visible or not...
+ */
+ for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
+ /* only items related to this object will be relevant */
+ if ((ksp->id == &ob->id) && (ksp->rna_path != NULL)) {
+ if (strstr(ksp->rna_path, "bones")) {
+ char *boneName = BLI_str_quoted_substrN(ksp->rna_path, "bones[");
+
+ if (boneName) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(pose, boneName);
+
+ if (pchan) {
+ /* select if bone is visible and can be affected */
+ if (PBONE_SELECTABLE(arm, pchan->bone)) {
+ pchan->bone->flag |= BONE_SELECTED;
+ changed = 1;
+ }
+ }
+
+ /* free temp memory */
+ MEM_freeN(boneName);
+ }
+ }
+ }
+ }
+
+ return changed;
+}
+
+static int pose_select_grouped_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ bArmature *arm = (bArmature *)ob->data;
+ short extend = RNA_boolean_get(op->ptr, "extend");
+ short changed = 0;
+
+ /* sanity check */
+ if (ob->pose == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* selection types
+ * NOTE: for the order of these, see the enum in POSE_OT_select_grouped()
+ */
+ switch (RNA_enum_get(op->ptr, "type")) {
+ case 1: /* group */
+ changed = pose_select_same_group(C, ob, extend);
+ break;
+ case 2: /* Keying Set */
+ changed = pose_select_same_keyingset(C, ob, extend);
+ break;
+ default: /* layer */
+ changed = pose_select_same_layer(C, ob, extend);
+ break;
+ }
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ if (arm->flag & ARM_HAS_VIZ_DEPS) {
+ /* mask modifier ('armature' mode), etc. */
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
+
+ /* report done status */
+ if (changed)
+ return OPERATOR_FINISHED;
+ else
+ return OPERATOR_CANCELLED;
+}
+
+void POSE_OT_select_grouped(wmOperatorType *ot)
+{
+ static EnumPropertyItem prop_select_grouped_types[] = {
+ {0, "LAYER", 0, "Layer", "Shared layers"},
+ {1, "GROUP", 0, "Group", "Shared group"},
+ {2, "KEYINGSET", 0, "Keying Set", "All bones affected by active Keying Set"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Select Grouped";
+ ot->description = "Select all visible bones grouped by similar properties";
+ ot->idname = "POSE_OT_select_grouped";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = pose_select_grouped_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
+}
+
+/* -------------------------------------- */
+
+/* context active object, or weightpainted object with armature in posemode */
+static int pose_bone_flip_active_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob_act = CTX_data_active_object(C);
+ Object *ob = BKE_object_pose_armature_get(ob_act);
+
+ if (ob && (ob->mode & OB_MODE_POSE)) {
+ bArmature *arm = ob->data;
+
+ if (arm->act_bone) {
+ bPoseChannel *pchanf;
+ char name[MAXBONENAME];
+ flip_side_name(name, arm->act_bone->name, TRUE);
+
+ pchanf = BKE_pose_channel_find_name(ob->pose, name);
+ if (pchanf && pchanf->bone != arm->act_bone) {
+ arm->act_bone->flag &= ~BONE_SELECTED;
+ pchanf->bone->flag |= BONE_SELECTED;
+
+ arm->act_bone = pchanf->bone;
+
+ /* in weightpaint we select the associated vertex group too */
+ if (ob_act->mode & OB_MODE_WEIGHT_PAINT) {
+ ED_vgroup_select_by_name(ob_act, name);
+ DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
+
+ return OPERATOR_FINISHED;
+ }
+ }
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void POSE_OT_select_flip_active(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Flip Selected Active Bone";
+ ot->idname = "POSE_OT_select_flip_active";
+ ot->description = "Activate the bone with a flipped name";
+
+ /* api callbacks */
+ ot->exec = pose_bone_flip_active_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
diff --git a/source/blender/editors/armature/poseSlide.c b/source/blender/editors/armature/pose_slide.c
index 3fd65de6c04..d19d8084608 100644
--- a/source/blender/editors/armature/poseSlide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -23,25 +23,15 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/editors/armature/poseSlide.c
+/** \file blender/editors/armature/pose_slide.c
* \ingroup edarmature
*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <string.h>
-#include <math.h>
-#include <float.h>
-
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
-#include "BLI_dynstr.h"
#include "BLI_dlrbTree.h"
-#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
@@ -624,12 +614,12 @@ static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *p
}
/* common code for modal() */
-static int pose_slide_modal(bContext *C, wmOperator *op, wmEvent *evt)
+static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
tPoseSlideOp *pso = op->customdata;
wmWindow *win = CTX_wm_window(C);
- switch (evt->type) {
+ switch (event->type) {
case LEFTMOUSE: /* confirm */
case RETKEY:
{
@@ -670,7 +660,7 @@ static int pose_slide_modal(bContext *C, wmOperator *op, wmEvent *evt)
/* 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 = (evt->x - pso->ar->winrct.xmin) / ((float)pso->ar->winx);
+ 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 */
@@ -727,7 +717,7 @@ static void pose_slide_opdef_properties(wmOperatorType *ot)
/* ------------------------------------ */
/* invoke() - for 'push' mode */
-static int pose_slide_push_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt))
+static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
tPoseSlideOp *pso;
@@ -784,7 +774,7 @@ void POSE_OT_push(wmOperatorType *ot)
/* ........................ */
/* invoke() - for 'relax' mode */
-static int pose_slide_relax_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt))
+static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
tPoseSlideOp *pso;
@@ -841,7 +831,7 @@ void POSE_OT_relax(wmOperatorType *ot)
/* ........................ */
/* invoke() - for 'breakdown' mode */
-static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt))
+static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
tPoseSlideOp *pso;
@@ -1091,7 +1081,7 @@ static void pose_propagate_fcurve(wmOperator *op, Object *ob, FCurve *fcu,
BezTriple *bezt;
float refVal = 0.0f;
- short keyExists;
+ bool keyExists;
int i, match;
short first = 1;
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
new file mode 100644
index 00000000000..c530faedd68
--- /dev/null
+++ b/source/blender/editors/armature/pose_transform.c
@@ -0,0 +1,879 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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, 2002-2009 full recode.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/armature/pose_transform.c
+ * \ingroup edarmature
+ */
+
+#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+
+#include "BKE_animsys.h"
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_idprop.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_report.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_armature.h"
+#include "ED_keyframing.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+
+#include "armature_intern.h"
+
+
+/* ********************************************** */
+/* Pose Apply */
+
+/* helper for apply_armature_pose2bones - fixes parenting of objects that are bone-parented to armature */
+static void applyarmature_fix_boneparents(Scene *scene, Object *armob)
+{
+ Object workob, *ob;
+
+ /* go through all objects in database */
+ for (ob = G.main->object.first; ob; ob = ob->id.next) {
+ /* if parent is bone in this armature, apply corrections */
+ if ((ob->parent == armob) && (ob->partype == PARBONE)) {
+ /* apply current transform from parent (not yet destroyed),
+ * then calculate new parent inverse matrix
+ */
+ BKE_object_apply_mat4(ob, ob->obmat, FALSE, FALSE);
+
+ BKE_object_workob_calc_parent(scene, ob, &workob);
+ invert_m4_m4(ob->parentinv, workob.obmat);
+ }
+ }
+}
+
+/* set the current pose as the restpose */
+static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object
+ bArmature *arm = BKE_armature_from_object(ob);
+ bPose *pose;
+ bPoseChannel *pchan;
+ EditBone *curbone;
+
+ /* don't check if editmode (should be done by caller) */
+ if (ob->type != OB_ARMATURE)
+ return OPERATOR_CANCELLED;
+ if (BKE_object_obdata_is_libdata(ob)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot apply pose to lib-linked armature"); /* error_libdata(); */
+ return OPERATOR_CANCELLED;
+ }
+
+ /* helpful warnings... */
+ /* TODO: add warnings to be careful about actions, applying deforms first, etc. */
+ if (ob->adt && ob->adt->action)
+ BKE_report(op->reports, RPT_WARNING,
+ "Actions on this armature will be destroyed by this new rest pose as the "
+ "transforms stored are relative to the old rest pose");
+
+ /* Get editbones of active armature to alter */
+ ED_armature_to_edit(ob);
+
+ /* get pose of active object and move it out of posemode */
+ pose = ob->pose;
+
+ for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
+ curbone = editbone_name_exists(arm->edbo, pchan->name);
+
+ /* simply copy the head/tail values from pchan over to curbone */
+ copy_v3_v3(curbone->head, pchan->pose_head);
+ copy_v3_v3(curbone->tail, pchan->pose_tail);
+
+ /* fix roll:
+ * 1. find auto-calculated roll value for this bone now
+ * 2. remove this from the 'visual' y-rotation
+ */
+ {
+ float premat[3][3], imat[3][3], pmat[3][3], tmat[3][3];
+ float delta[3], eul[3];
+
+ /* obtain new auto y-rotation */
+ sub_v3_v3v3(delta, curbone->tail, curbone->head);
+ vec_roll_to_mat3(delta, 0.0f, premat);
+ invert_m3_m3(imat, premat);
+
+ /* get pchan 'visual' matrix */
+ copy_m3_m4(pmat, pchan->pose_mat);
+
+ /* remove auto from visual and get euler rotation */
+ mul_m3_m3m3(tmat, imat, pmat);
+ mat3_to_eul(eul, tmat);
+
+ /* just use this euler-y as new roll value */
+ curbone->roll = eul[1];
+ }
+
+ /* clear transform values for pchan */
+ zero_v3(pchan->loc);
+ zero_v3(pchan->eul);
+ unit_qt(pchan->quat);
+ unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
+ pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f;
+
+ /* set anim lock */
+ curbone->flag |= BONE_UNKEYED;
+ }
+
+ /* convert editbones back to bones, and then free the edit-data */
+ ED_armature_from_edit(ob);
+ ED_armature_edit_free(ob);
+
+ /* flush positions of posebones */
+ BKE_pose_where_is(scene, ob);
+
+ /* fix parenting of objects which are bone-parented */
+ applyarmature_fix_boneparents(scene, ob);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_armature_apply(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Apply Pose as Rest Pose";
+ ot->idname = "POSE_OT_armature_apply";
+ ot->description = "Apply the current pose as the new rest pose";
+
+ /* callbacks */
+ ot->exec = apply_armature_pose2bones_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
+/* set the current pose as the restpose */
+static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); // must be active object, not edit-object
+
+ /* don't check if editmode (should be done by caller) */
+ if (ob->type != OB_ARMATURE)
+ return OPERATOR_CANCELLED;
+
+ /* loop over all selected pchans
+ *
+ * TODO, loop over children before parents if multiple bones
+ * at once are to be predictable*/
+ CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones)
+ {
+ float delta_mat[4][4];
+
+ /* chan_mat already contains the delta transform from rest pose to pose-mode pose
+ * as that is baked into there so that B-Bones will work. Once we've set this as the
+ * new raw-transform components, don't recalc the poses yet, otherwise IK result will
+ * change, thus changing the result we may be trying to record.
+ */
+ copy_m4_m4(delta_mat, pchan->chan_mat);
+ BKE_pchan_apply_mat4(pchan, delta_mat, TRUE);
+ }
+ CTX_DATA_END;
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_visual_transform_apply(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Apply Visual Transform to Pose";
+ ot->idname = "POSE_OT_visual_transform_apply";
+ ot->description = "Apply final constrained position of pose bones to their transform";
+
+ /* callbacks */
+ ot->exec = pose_visual_transform_apply_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ********************************************** */
+/* Copy/Paste */
+
+/* Global copy/paste buffer for pose - cleared on start/end session + before every copy operation */
+static bPose *g_posebuf = NULL;
+
+void ED_clipboard_posebuf_free(void)
+{
+ if (g_posebuf) {
+ bPoseChannel *pchan;
+
+ for (pchan = g_posebuf->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->prop) {
+ IDP_FreeProperty(pchan->prop);
+ MEM_freeN(pchan->prop);
+ }
+ }
+
+ /* was copied without constraints */
+ BLI_freelistN(&g_posebuf->chanbase);
+ MEM_freeN(g_posebuf);
+ }
+
+ g_posebuf = NULL;
+}
+
+/* This function is used to indicate that a bone is selected
+ * and needs to be included in copy buffer (used to be for inserting keys)
+ */
+static void set_pose_keys(Object *ob)
+{
+ bArmature *arm = ob->data;
+ bPoseChannel *chan;
+
+ if (ob->pose) {
+ for (chan = ob->pose->chanbase.first; chan; chan = chan->next) {
+ Bone *bone = chan->bone;
+ if ((bone) && (bone->flag & BONE_SELECTED) && (arm->layer & bone->layer))
+ chan->flag |= POSE_KEY;
+ else
+ chan->flag &= ~POSE_KEY;
+ }
+ }
+}
+
+/* perform paste pose, for a single bone
+ * < ob: object where bone to paste to lives
+ * < chan: bone that pose to paste comes from
+ * < selOnly: only paste on selected bones
+ * < flip: flip on x-axis
+ *
+ * > returns: whether the bone that we pasted to if we succeeded
+ */
+static bPoseChannel *pose_bone_do_paste(Object *ob, bPoseChannel *chan, short selOnly, short flip)
+{
+ bPoseChannel *pchan;
+ char name[MAXBONENAME];
+ short paste_ok;
+
+ /* get the name - if flipping, we must flip this first */
+ if (flip)
+ flip_side_name(name, chan->name, 0); /* 0 = don't strip off number extensions */
+ else
+ BLI_strncpy(name, chan->name, sizeof(name));
+
+ /* only copy when:
+ * 1) channel exists - poses are not meant to add random channels to anymore
+ * 2) if selection-masking is on, channel is selected - only selected bones get pasted on, allowing making both sides symmetrical
+ */
+ pchan = BKE_pose_channel_find_name(ob->pose, name);
+
+ if (selOnly)
+ paste_ok = ((pchan) && (pchan->bone->flag & BONE_SELECTED));
+ else
+ paste_ok = ((pchan != NULL));
+
+ /* continue? */
+ if (paste_ok) {
+ /* only loc rot size
+ * - only copies transform info for the pose
+ */
+ copy_v3_v3(pchan->loc, chan->loc);
+ copy_v3_v3(pchan->size, chan->size);
+ pchan->flag = chan->flag;
+
+ /* check if rotation modes are compatible (i.e. do they need any conversions) */
+ if (pchan->rotmode == chan->rotmode) {
+ /* copy the type of rotation in use */
+ if (pchan->rotmode > 0) {
+ copy_v3_v3(pchan->eul, chan->eul);
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ copy_v3_v3(pchan->rotAxis, chan->rotAxis);
+ pchan->rotAngle = chan->rotAngle;
+ }
+ else {
+ copy_qt_qt(pchan->quat, chan->quat);
+ }
+ }
+ else if (pchan->rotmode > 0) {
+ /* quat/axis-angle to euler */
+ if (chan->rotmode == ROT_MODE_AXISANGLE)
+ axis_angle_to_eulO(pchan->eul, pchan->rotmode, chan->rotAxis, chan->rotAngle);
+ else
+ quat_to_eulO(pchan->eul, pchan->rotmode, chan->quat);
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ /* quat/euler to axis angle */
+ if (chan->rotmode > 0)
+ eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->eul, chan->rotmode);
+ else
+ quat_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->quat);
+ }
+ else {
+ /* euler/axis-angle to quat */
+ if (chan->rotmode > 0)
+ eulO_to_quat(pchan->quat, chan->eul, chan->rotmode);
+ else
+ axis_angle_to_quat(pchan->quat, chan->rotAxis, pchan->rotAngle);
+ }
+
+ /* paste flipped pose? */
+ if (flip) {
+ pchan->loc[0] *= -1;
+
+ /* has to be done as eulers... */
+ if (pchan->rotmode > 0) {
+ pchan->eul[1] *= -1;
+ pchan->eul[2] *= -1;
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ float eul[3];
+
+ axis_angle_to_eulO(eul, EULER_ORDER_DEFAULT, pchan->rotAxis, pchan->rotAngle);
+ eul[1] *= -1;
+ eul[2] *= -1;
+ eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, eul, EULER_ORDER_DEFAULT);
+ }
+ else {
+ float eul[3];
+
+ normalize_qt(pchan->quat);
+ quat_to_eul(eul, pchan->quat);
+ eul[1] *= -1;
+ eul[2] *= -1;
+ eul_to_quat(pchan->quat, eul);
+ }
+ }
+
+ /* ID properties */
+ if (chan->prop) {
+ if (pchan->prop) {
+ /* if we have existing properties on a bone, just copy over the values of
+ * matching properties (i.e. ones which will have some impact) on to the
+ * target instead of just blinding replacing all [
+ */
+ IDP_SyncGroupValues(pchan->prop, chan->prop);
+ }
+ else {
+ /* no existing properties, so assume that we want copies too? */
+ pchan->prop = IDP_CopyProperty(chan->prop);
+ }
+ }
+ }
+
+ /* return whether paste went ahead */
+ return pchan;
+}
+
+/* ---- */
+
+static int pose_copy_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+
+ /* sanity checking */
+ if (ELEM(NULL, ob, ob->pose)) {
+ BKE_report(op->reports, RPT_ERROR, "No pose to copy");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* free existing pose buffer */
+ ED_clipboard_posebuf_free();
+
+ /* sets chan->flag to POSE_KEY if bone selected, then copy those bones to the buffer */
+ set_pose_keys(ob);
+ BKE_pose_copy_data(&g_posebuf, ob->pose, 0);
+
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_copy(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Copy Pose";
+ ot->idname = "POSE_OT_copy";
+ ot->description = "Copies the current pose of the selected bones to copy/paste buffer";
+
+ /* api callbacks */
+ ot->exec = pose_copy_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flag */
+ ot->flag = OPTYPE_REGISTER;
+}
+
+/* ---- */
+
+static int pose_paste_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ Scene *scene = CTX_data_scene(C);
+ bPoseChannel *chan;
+ int flip = RNA_boolean_get(op->ptr, "flipped");
+ int selOnly = RNA_boolean_get(op->ptr, "selected_mask");
+
+ /* get KeyingSet to use */
+ KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
+
+ /* sanity checks */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+
+ if (g_posebuf == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Copy buffer is empty");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* if selOnly option is enabled, if user hasn't selected any bones,
+ * just go back to default behavior to be more in line with other pose tools
+ */
+ if (selOnly) {
+ if (CTX_DATA_COUNT(C, selected_pose_bones) == 0)
+ selOnly = 0;
+ }
+
+ /* Safely merge all of the channels in the buffer pose into any existing pose */
+ for (chan = g_posebuf->chanbase.first; chan; chan = chan->next) {
+ if (chan->flag & POSE_KEY) {
+ /* try to perform paste on this bone */
+ bPoseChannel *pchan = pose_bone_do_paste(ob, chan, selOnly, flip);
+
+ if (pchan) {
+ /* keyframing tagging for successful paste */
+ ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
+ }
+ }
+ }
+
+ /* Update event for pose and deformation children */
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_paste(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Paste Pose";
+ ot->idname = "POSE_OT_paste";
+ ot->description = "Paste the stored pose on to the current pose";
+
+ /* api callbacks */
+ ot->exec = pose_paste_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flag */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "flipped", FALSE, "Flipped on X-Axis", "Paste the stored pose flipped on to current pose");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ RNA_def_boolean(ot->srna, "selected_mask", FALSE, "On Selected Only", "Only paste the stored pose on to selected bones in the current pose");
+}
+
+/* ********************************************** */
+/* Clear Pose Transforms */
+
+/* clear scale of pose-channel */
+static void pchan_clear_scale(bPoseChannel *pchan)
+{
+ if ((pchan->protectflag & OB_LOCK_SCALEX) == 0)
+ pchan->size[0] = 1.0f;
+ if ((pchan->protectflag & OB_LOCK_SCALEY) == 0)
+ pchan->size[1] = 1.0f;
+ if ((pchan->protectflag & OB_LOCK_SCALEZ) == 0)
+ pchan->size[2] = 1.0f;
+}
+
+/* clear location of pose-channel */
+static void pchan_clear_loc(bPoseChannel *pchan)
+{
+ if ((pchan->protectflag & OB_LOCK_LOCX) == 0)
+ pchan->loc[0] = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_LOCY) == 0)
+ pchan->loc[1] = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_LOCZ) == 0)
+ pchan->loc[2] = 0.0f;
+}
+
+/* clear rotation of pose-channel */
+static void pchan_clear_rot(bPoseChannel *pchan)
+{
+ if (pchan->protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) {
+ /* check if convert to eulers for locking... */
+ if (pchan->protectflag & OB_LOCK_ROT4D) {
+ /* perform clamping on a component by component basis */
+ if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
+ pchan->rotAngle = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
+ pchan->rotAxis[0] = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
+ pchan->rotAxis[1] = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
+ pchan->rotAxis[2] = 0.0f;
+
+ /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */
+ if (IS_EQF(pchan->rotAxis[0], pchan->rotAxis[1]) && IS_EQF(pchan->rotAxis[1], pchan->rotAxis[2]))
+ pchan->rotAxis[1] = 1.0f;
+ }
+ else if (pchan->rotmode == ROT_MODE_QUAT) {
+ if ((pchan->protectflag & OB_LOCK_ROTW) == 0)
+ pchan->quat[0] = 1.0f;
+ if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
+ pchan->quat[1] = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
+ pchan->quat[2] = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
+ pchan->quat[3] = 0.0f;
+ }
+ else {
+ /* the flag may have been set for the other modes, so just ignore the extra flag... */
+ if ((pchan->protectflag & OB_LOCK_ROTX) == 0)
+ pchan->eul[0] = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_ROTY) == 0)
+ pchan->eul[1] = 0.0f;
+ if ((pchan->protectflag & OB_LOCK_ROTZ) == 0)
+ pchan->eul[2] = 0.0f;
+ }
+ }
+ else {
+ /* perform clamping using euler form (3-components) */
+ float eul[3], oldeul[3], quat1[4] = {0};
+ float qlen = 0.0f;
+
+ if (pchan->rotmode == ROT_MODE_QUAT) {
+ qlen = normalize_qt_qt(quat1, pchan->quat);
+ quat_to_eul(oldeul, quat1);
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, pchan->rotAxis, pchan->rotAngle);
+ }
+ else {
+ copy_v3_v3(oldeul, pchan->eul);
+ }
+
+ eul[0] = eul[1] = eul[2] = 0.0f;
+
+ if (pchan->protectflag & OB_LOCK_ROTX)
+ eul[0] = oldeul[0];
+ if (pchan->protectflag & OB_LOCK_ROTY)
+ eul[1] = oldeul[1];
+ if (pchan->protectflag & OB_LOCK_ROTZ)
+ eul[2] = oldeul[2];
+
+ if (pchan->rotmode == ROT_MODE_QUAT) {
+ eul_to_quat(pchan->quat, eul);
+
+ /* restore original quat size */
+ mul_qt_fl(pchan->quat, qlen);
+
+ /* quaternions flip w sign to accumulate rotations correctly */
+ if ((quat1[0] < 0.0f && pchan->quat[0] > 0.0f) || (quat1[0] > 0.0f && pchan->quat[0] < 0.0f)) {
+ mul_qt_fl(pchan->quat, -1.0f);
+ }
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, eul, EULER_ORDER_DEFAULT);
+ }
+ else {
+ copy_v3_v3(pchan->eul, eul);
+ }
+ }
+ } /* Duplicated in source/blender/editors/object/object_transform.c */
+ else {
+ if (pchan->rotmode == ROT_MODE_QUAT) {
+ unit_qt(pchan->quat);
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ /* by default, make rotation of 0 radians around y-axis (roll) */
+ unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
+ }
+ else {
+ zero_v3(pchan->eul);
+ }
+ }
+}
+
+/* clear loc/rot/scale of pose-channel */
+static void pchan_clear_transforms(bPoseChannel *pchan)
+{
+ pchan_clear_loc(pchan);
+ pchan_clear_rot(pchan);
+ pchan_clear_scale(pchan);
+}
+
+/* --------------- */
+
+/* generic exec for clear-pose operators */
+static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op,
+ void (*clear_func)(bPoseChannel *), const char default_ksName[])
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ short autokey = 0;
+
+ /* sanity checks */
+ if (ELEM(NULL, clear_func, default_ksName)) {
+ BKE_report(op->reports, RPT_ERROR, "Programming error: missing clear transform function or keying set name");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* only clear relevant transforms for selected bones */
+ CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones)
+ {
+ /* run provided clearing function */
+ clear_func(pchan);
+
+ /* do auto-keyframing as appropriate */
+ if (autokeyframe_cfra_can_key(scene, &ob->id)) {
+ /* clear any unkeyed tags */
+ if (pchan->bone)
+ pchan->bone->flag &= ~BONE_UNKEYED;
+
+ /* tag for autokeying later */
+ autokey = 1;
+ }
+ else {
+ /* add unkeyed tags */
+ if (pchan->bone)
+ pchan->bone->flag |= BONE_UNKEYED;
+ }
+ }
+ CTX_DATA_END;
+
+ /* perform autokeying on the bones if needed */
+ if (autokey) {
+ /* get KeyingSet to use */
+ KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
+
+ /* insert keyframes */
+ ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+
+ /* now recalculate paths */
+ if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS))
+ ED_pose_recalculate_paths(scene, ob);
+ }
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+/* --------------- */
+
+static int pose_clear_scale_exec(bContext *C, wmOperator *op)
+{
+ return pose_clear_transform_generic_exec(C, op, pchan_clear_scale, ANIM_KS_SCALING_ID);
+}
+
+void POSE_OT_scale_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Clear Pose Scale";
+ ot->idname = "POSE_OT_scale_clear";
+ ot->description = "Reset scaling of selected bones to their default values";
+
+ /* api callbacks */
+ ot->exec = pose_clear_scale_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
+static int pose_clear_rot_exec(bContext *C, wmOperator *op)
+{
+ return pose_clear_transform_generic_exec(C, op, pchan_clear_rot, ANIM_KS_ROTATION_ID);
+}
+
+void POSE_OT_rot_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Clear Pose Rotation";
+ ot->idname = "POSE_OT_rot_clear";
+ ot->description = "Reset rotations of selected bones to their default values";
+
+ /* api callbacks */
+ ot->exec = pose_clear_rot_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
+static int pose_clear_loc_exec(bContext *C, wmOperator *op)
+{
+ return pose_clear_transform_generic_exec(C, op, pchan_clear_loc, ANIM_KS_LOCATION_ID);
+}
+
+void POSE_OT_loc_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Clear Pose Location";
+ ot->idname = "POSE_OT_loc_clear";
+ ot->description = "Reset locations of selected bones to their default values";
+
+ /* api callbacks */
+ ot->exec = pose_clear_loc_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
+static int pose_clear_transforms_exec(bContext *C, wmOperator *op)
+{
+ return pose_clear_transform_generic_exec(C, op, pchan_clear_transforms, ANIM_KS_LOC_ROT_SCALE_ID);
+}
+
+void POSE_OT_transforms_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Clear Pose Transforms";
+ ot->idname = "POSE_OT_transforms_clear";
+ ot->description = "Reset location, rotation, and scaling of selected bones to their default values";
+
+ /* api callbacks */
+ ot->exec = pose_clear_transforms_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ********************************************** */
+/* Clear User Transforms */
+
+static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ float cframe = (float)CFRA;
+ const short only_select = RNA_boolean_get(op->ptr, "only_selected");
+
+ if ((ob->adt) && (ob->adt->action)) {
+ /* XXX: this is just like this to avoid contaminating anything else;
+ * just pose values should change, so this should be fine
+ */
+ bPose *dummyPose = NULL;
+ Object workob = {{0}};
+ bPoseChannel *pchan;
+
+ /* execute animation step for current frame using a dummy copy of the pose */
+ BKE_pose_copy_data(&dummyPose, ob->pose, 0);
+
+ BLI_strncpy(workob.id.name, "OB<ClearTfmWorkOb>", sizeof(workob.id.name));
+ workob.type = OB_ARMATURE;
+ workob.data = ob->data;
+ workob.adt = ob->adt;
+ workob.pose = dummyPose;
+
+ BKE_animsys_evaluate_animdata(scene, &workob.id, workob.adt, cframe, ADT_RECALC_ANIM);
+
+ /* copy back values, but on selected bones only */
+ for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
+ pose_bone_do_paste(ob, pchan, only_select, 0);
+ }
+
+ /* free temp data - free manually as was copied without constraints */
+ for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->prop) {
+ IDP_FreeProperty(pchan->prop);
+ MEM_freeN(pchan->prop);
+ }
+ }
+
+ /* was copied without constraints */
+ BLI_freelistN(&dummyPose->chanbase);
+ MEM_freeN(dummyPose);
+ }
+ else {
+ /* no animation, so just reset whole pose to rest pose
+ * (cannot just restore for selected though)
+ */
+ BKE_pose_rest(ob->pose);
+ }
+
+ /* notifiers and updates */
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_user_transforms_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Clear User Transforms";
+ ot->idname = "POSE_OT_user_transforms_clear";
+ ot->description = "Reset pose on selected bones to keyframed state";
+
+ /* callbacks */
+ ot->exec = pose_clear_user_transforms_exec;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "only_selected", TRUE, "Only Selected", "Only visible/selected bones");
+}
diff --git a/source/blender/editors/armature/poseUtils.c b/source/blender/editors/armature/pose_utils.c
index f3c32399ad6..a5e51ccf32a 100644
--- a/source/blender/editors/armature/poseUtils.c
+++ b/source/blender/editors/armature/pose_utils.c
@@ -23,25 +23,14 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/editors/armature/poseUtils.c
+/** \file blender/editors/armature/pose_utils.c
* \ingroup edarmature
*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stddef.h>
-#include <string.h>
-#include <math.h>
-#include <float.h>
-
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
-#include "BLI_dynstr.h"
-#include "BLI_dlrbTree.h"
-#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c
deleted file mode 100644
index 576e5983d16..00000000000
--- a/source/blender/editors/armature/poseobject.c
+++ /dev/null
@@ -1,2364 +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.
- *
- * Contributor(s): Ton Roosendaal, Blender Foundation '05, full recode.
- * Joshua Leung
- *
- * ***** END GPL LICENSE BLOCK *****
- * support for animation modes - Reevan McKay
- */
-
-/** \file blender/editors/armature/poseobject.c
- * \ingroup edarmature
- */
-
-
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_math.h"
-#include "BLI_blenlib.h"
-#include "BLI_dynstr.h"
-#include "BLI_utildefines.h"
-
-#include "DNA_anim_types.h"
-#include "DNA_armature_types.h"
-#include "DNA_constraint_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
-
-#include "BKE_animsys.h"
-#include "BKE_anim.h"
-#include "BKE_idprop.h"
-#include "BKE_action.h"
-#include "BKE_armature.h"
-#include "BKE_context.h"
-#include "BKE_constraint.h"
-#include "BKE_deform.h"
-#include "BKE_depsgraph.h"
-#include "BKE_fcurve.h"
-#include "BKE_modifier.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_armature.h"
-#include "ED_keyframing.h"
-#include "ED_mesh.h"
-#include "ED_screen.h"
-#include "ED_object.h"
-#include "ED_util.h" /* clipboard */
-
-#include "UI_interface.h"
-#include "UI_resources.h"
-
-#include "armature_intern.h"
-
-/* matches logic with ED_operator_posemode_context() */
-Object *ED_pose_object_from_context(bContext *C)
-{
- ScrArea *sa = CTX_wm_area(C);
- Object *ob;
-
- /* since this call may also be used from the buttons window, we need to check for where to get the object */
- if (sa && sa->spacetype == SPACE_BUTS) {
- ob = ED_object_context(C);
- }
- else {
- ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- }
-
- return ob;
-}
-
-/* This function is used to process the necessary updates for */
-void ED_armature_enter_posemode(bContext *C, Base *base)
-{
- ReportList *reports = CTX_wm_reports(C);
- Object *ob = base->object;
-
- if (ob->id.lib) {
- BKE_report(reports, RPT_WARNING, "Cannot pose libdata");
- return;
- }
-
- switch (ob->type) {
- case OB_ARMATURE:
- ob->restore_mode = ob->mode;
- ob->mode |= OB_MODE_POSE;
-
- WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_POSE, NULL);
-
- break;
- default:
- return;
- }
-
- /* XXX: disabled as this would otherwise cause a nasty loop... */
- //ED_object_toggle_modes(C, ob->mode);
-}
-
-void ED_armature_exit_posemode(bContext *C, Base *base)
-{
- if (base) {
- Object *ob = base->object;
-
- ob->restore_mode = ob->mode;
- ob->mode &= ~OB_MODE_POSE;
-
- WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
- }
-}
-
-/* if a selected or active bone is protected, throw error (oonly if warn == 1) and return 1 */
-/* only_selected == 1: the active bone is allowed to be protected */
-#if 0 /* UNUSED 2.5 */
-static short pose_has_protected_selected(Object *ob, short warn)
-{
- /* check protection */
- if (ob->proxy) {
- bPoseChannel *pchan;
- bArmature *arm = ob->data;
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone && (pchan->bone->layer & arm->layer)) {
- if (pchan->bone->layer & arm->layer_protected) {
- if (pchan->bone->flag & BONE_SELECTED)
- break;
- }
- }
- }
- if (pchan) {
- if (warn) error("Cannot change Proxy protected bones");
- return 1;
- }
- }
- return 0;
-}
-#endif
-
-/* only for real IK, not for auto-IK */
-static int pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan, int level)
-{
- bConstraint *con;
- Bone *bone;
-
- /* No need to check if constraint is active (has influence),
- * since all constraints with CONSTRAINT_IK_AUTO are active */
- for (con = pchan->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
- bKinematicConstraint *data = con->data;
- if (data->rootbone == 0 || data->rootbone > level) {
- if ((data->flag & CONSTRAINT_IK_AUTO) == 0)
- return 1;
- }
- }
- }
- for (bone = pchan->bone->childbase.first; bone; bone = bone->next) {
- pchan = BKE_pose_channel_find_name(ob->pose, bone->name);
- if (pchan && pose_channel_in_IK_chain(ob, pchan, level + 1))
- return 1;
- }
- return 0;
-}
-
-int ED_pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan)
-{
- return pose_channel_in_IK_chain(ob, pchan, 0);
-}
-
-/* ********************************************** */
-/* Motion Paths */
-
-/* For the object with pose/action: update paths for those that have got them
- * This should selectively update paths that exist...
- *
- * To be called from various tools that do incremental updates
- */
-void ED_pose_recalculate_paths(Scene *scene, Object *ob)
-{
- ListBase targets = {NULL, NULL};
-
- /* set flag to force recalc, then grab the relevant bones to target */
- ob->pose->avs.recalc |= ANIMVIZ_RECALC_PATHS;
- animviz_get_object_motionpaths(ob, &targets);
-
- /* recalculate paths, then free */
- animviz_calc_motionpaths(scene, &targets);
- BLI_freelistN(&targets);
-}
-
-
-/* show popup to determine settings */
-static int pose_calculate_paths_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
-
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
-
- /* set default settings from existing/stored settings */
- {
- bAnimVizSettings *avs = &ob->pose->avs;
- PointerRNA avs_ptr;
-
- RNA_int_set(op->ptr, "start_frame", avs->path_sf);
- RNA_int_set(op->ptr, "end_frame", avs->path_ef);
-
- RNA_pointer_create(NULL, &RNA_AnimVizMotionPaths, avs, &avs_ptr);
- RNA_enum_set(op->ptr, "bake_location", RNA_enum_get(&avs_ptr, "bake_location"));
- }
-
- /* show popup dialog to allow editing of range... */
- // FIXME: hardcoded dimensions here are just arbitrary
- return WM_operator_props_dialog_popup(C, op, 200, 200);
-}
-
-/* For the object with pose/action: create path curves for selected bones
- * This recalculates the WHOLE path within the pchan->pathsf and pchan->pathef range
- */
-static int pose_calculate_paths_exec(bContext *C, wmOperator *op)
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- Scene *scene = CTX_data_scene(C);
-
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
-
- /* grab baking settings from operator settings */
- {
- bAnimVizSettings *avs = &ob->pose->avs;
- PointerRNA avs_ptr;
-
- avs->path_sf = RNA_int_get(op->ptr, "start_frame");
- avs->path_ef = RNA_int_get(op->ptr, "end_frame");
-
- RNA_pointer_create(NULL, &RNA_AnimVizMotionPaths, avs, &avs_ptr);
- RNA_enum_set(&avs_ptr, "bake_location", RNA_enum_get(op->ptr, "bake_location"));
- }
-
- /* set up path data for bones being calculated */
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
- {
- /* verify makes sure that the selected bone has a bone with the appropriate settings */
- animviz_verify_motionpaths(op->reports, scene, ob, pchan);
- }
- CTX_DATA_END;
-
- /* calculate the bones that now have motionpaths... */
- /* TODO: only make for the selected bones? */
- ED_pose_recalculate_paths(scene, ob);
-
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_paths_calculate(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Calculate Bone Paths";
- ot->idname = "POSE_OT_paths_calculate";
- ot->description = "Calculate paths for the selected bones";
-
- /* api callbacks */
- ot->invoke = pose_calculate_paths_invoke;
- ot->exec = pose_calculate_paths_exec;
- ot->poll = ED_operator_posemode_exclusive;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_int(ot->srna, "start_frame", 1, MINAFRAME, MAXFRAME, "Start",
- "First frame to calculate bone paths on", MINFRAME, MAXFRAME / 2.0);
- RNA_def_int(ot->srna, "end_frame", 250, MINAFRAME, MAXFRAME, "End",
- "Last frame to calculate bone paths on", MINFRAME, MAXFRAME / 2.0);
-
- RNA_def_enum(ot->srna, "bake_location", motionpath_bake_location_items, 0,
- "Bake Location",
- "Which point on the bones is used when calculating paths");
-}
-
-/* --------- */
-
-static int pose_update_paths_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- Scene *scene = CTX_data_scene(C);
-
- if (ELEM(NULL, ob, scene))
- return OPERATOR_CANCELLED;
-
- /* calculate the bones that now have motionpaths... */
- /* TODO: only make for the selected bones? */
- ED_pose_recalculate_paths(scene, ob);
-
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_paths_update(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Update Bone Paths";
- ot->idname = "POSE_OT_paths_update";
- ot->description = "Recalculate paths for bones that already have them";
-
- /* api callbakcs */
- ot->exec = pose_update_paths_exec;
- ot->poll = ED_operator_posemode_exclusive; /* TODO: this should probably check for active bone and/or existing paths */
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* --------- */
-
-/* for the object with pose/action: clear path curves for selected bones only */
-static void ED_pose_clear_paths(Object *ob)
-{
- bPoseChannel *pchan;
- short skipped = 0;
-
- if (ELEM(NULL, ob, ob->pose))
- return;
-
- /* free the motionpath blocks, but also take note of whether we skipped some... */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->mpath) {
- if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) {
- animviz_free_motionpath(pchan->mpath);
- pchan->mpath = NULL;
- }
- else
- skipped = 1;
- }
- }
-
- /* if we didn't skip any, we shouldn't have any paths left */
- if (skipped == 0)
- ob->pose->avs.path_bakeflag &= ~MOTIONPATH_BAKE_HAS_PATHS;
-}
-
-/* operator callback for this */
-static int pose_clear_paths_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
-
- /* only continue if there's an object */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
-
- /* use the backend function for this */
- ED_pose_clear_paths(ob);
-
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_paths_clear(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Clear Bone Paths";
- ot->idname = "POSE_OT_paths_clear";
- ot->description = "Clear path caches for selected bones";
-
- /* api callbacks */
- ot->exec = pose_clear_paths_exec;
- ot->poll = ED_operator_posemode_exclusive;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* ******************* Select Constraint Target Operator ************* */
-
-static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bArmature *arm = (bArmature *)ob->data;
- bConstraint *con;
- int found = 0;
-
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
- {
- if (pchan->bone->flag & BONE_SELECTED) {
- for (con = pchan->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(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) && (ct->subtarget[0])) {
- bPoseChannel *pchanc = BKE_pose_channel_find_name(ob->pose, ct->subtarget);
- if ((pchanc) && !(pchanc->bone->flag & BONE_UNSELECTABLE)) {
- pchanc->bone->flag |= BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL;
- found = 1;
- }
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
- }
- }
- }
- }
- CTX_DATA_END;
-
- if (!found)
- return OPERATOR_CANCELLED;
-
- /* updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
- if (arm->flag & ARM_HAS_VIZ_DEPS) {
- /* mask modifier ('armature' mode), etc. */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_select_constraint_target(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Constraint Target";
- ot->idname = "POSE_OT_select_constraint_target";
- ot->description = "Select bones used as targets for the currently selected bones";
-
- /* api callbacks */
- ot->exec = pose_select_constraint_target_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* ******************* select hierarchy operator ************* */
-
-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;
- int direction = RNA_enum_get(op->ptr, "direction");
- int add_to_sel = RNA_boolean_get(op->ptr, "extend");
- int found = 0;
-
- 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;
- }
- }
- 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;
- }
- }
- }
- }
-
- 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;
- }
- }
- }
- }
- }
- CTX_DATA_END;
-
- if (found == 0)
- return OPERATOR_CANCELLED;
-
- /* updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
- if (arm->flag & ARM_HAS_VIZ_DEPS) {
- /* mask modifier ('armature' mode), etc. */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_select_hierarchy(wmOperatorType *ot)
-{
- static EnumPropertyItem direction_items[] = {
- {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
- {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- /* identifiers */
- ot->name = "Select Hierarchy";
- ot->idname = "POSE_OT_select_hierarchy";
- ot->description = "Select immediate parent/children of selected bones";
-
- /* api callbacks */
- ot->exec = pose_select_hierarchy_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- ot->prop = RNA_def_enum(ot->srna, "direction", direction_items, BONE_SELECT_PARENT, "Direction", "");
- RNA_def_boolean(ot->srna, "extend", 0, "Add to Selection", "");
-}
-
-/* ******************* select grouped operator ************* */
-
-static short pose_select_same_group(bContext *C, Object *ob, short extend)
-{
- bArmature *arm = (ob) ? ob->data : NULL;
- bPose *pose = (ob) ? ob->pose : NULL;
- char *group_flags;
- int numGroups = 0;
- short changed = 0, tagged = 0;
-
- /* sanity checks */
- if (ELEM3(NULL, ob, pose, arm))
- return 0;
-
- /* count the number of groups */
- numGroups = BLI_countlist(&pose->agroups);
- if (numGroups == 0)
- return 0;
-
- /* alloc a small array to keep track of the groups to use
- * - each cell stores on/off state for whether group should be used
- * - size is (numGroups + 1), since (index = 0) is used for no-group
- */
- group_flags = MEM_callocN(numGroups + 1, "pose_select_same_group");
-
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
- {
- /* keep track of group as group to use later? */
- if (pchan->bone->flag & BONE_SELECTED) {
- group_flags[pchan->agrp_index] = 1;
- tagged = 1;
- }
-
- /* deselect all bones before selecting new ones? */
- if ((extend == 0) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0)
- pchan->bone->flag &= ~BONE_SELECTED;
- }
- CTX_DATA_END;
-
- /* small optimization: only loop through bones a second time if there are any groups tagged */
- if (tagged) {
- /* only if group matches (and is not selected or current bone) */
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
- {
- if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
- /* check if the group used by this bone is counted */
- if (group_flags[pchan->agrp_index]) {
- pchan->bone->flag |= BONE_SELECTED;
- changed = 1;
- }
- }
- }
- CTX_DATA_END;
- }
-
- /* free temp info */
- MEM_freeN(group_flags);
-
- return changed;
-}
-
-static short pose_select_same_layer(bContext *C, Object *ob, short extend)
-{
- bPose *pose = (ob) ? ob->pose : NULL;
- bArmature *arm = (ob) ? ob->data : NULL;
- short changed = 0;
- int layers = 0;
-
- if (ELEM3(NULL, ob, pose, arm))
- return 0;
-
- /* figure out what bones are selected */
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
- {
- /* keep track of layers to use later? */
- if (pchan->bone->flag & BONE_SELECTED)
- layers |= pchan->bone->layer;
-
- /* deselect all bones before selecting new ones? */
- if ((extend == 0) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0)
- pchan->bone->flag &= ~BONE_SELECTED;
- }
- CTX_DATA_END;
- if (layers == 0)
- return 0;
-
- /* select bones that are on same layers as layers flag */
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
- {
- /* if bone is on a suitable layer, and the bone can have its selection changed, select it */
- if ((layers & pchan->bone->layer) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
- pchan->bone->flag |= BONE_SELECTED;
- changed = 1;
- }
- }
- CTX_DATA_END;
-
- return changed;
-}
-
-static int pose_select_same_keyingset(bContext *C, Object *ob, short extend)
-{
- KeyingSet *ks = ANIM_scene_get_active_keyingset(CTX_data_scene(C));
- KS_Path *ksp;
-
- bArmature *arm = (ob) ? ob->data : NULL;
- bPose *pose = (ob) ? ob->pose : NULL;
- short changed = 0;
-
- /* sanity checks: validate Keying Set and object */
- if ((ks == NULL) || (ANIM_validate_keyingset(C, NULL, ks) != 0))
- return 0;
-
- if (ELEM3(NULL, ob, pose, arm))
- return 0;
-
- /* if not extending selection, deselect all selected first */
- if (extend == 0) {
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
- {
- if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0)
- pchan->bone->flag &= ~BONE_SELECTED;
- }
- CTX_DATA_END;
- }
-
- /* iterate over elements in the Keying Set, setting selection depending on whether
- * that bone is visible or not...
- */
- for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
- /* only items related to this object will be relevant */
- if ((ksp->id == &ob->id) && (ksp->rna_path != NULL)) {
- if (strstr(ksp->rna_path, "bones")) {
- char *boneName = BLI_str_quoted_substrN(ksp->rna_path, "bones[");
-
- if (boneName) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(pose, boneName);
-
- if (pchan) {
- /* select if bone is visible and can be affected */
- if (PBONE_SELECTABLE(arm, pchan->bone)) {
- pchan->bone->flag |= BONE_SELECTED;
- changed = 1;
- }
- }
-
- /* free temp memory */
- MEM_freeN(boneName);
- }
- }
- }
- }
-
- return changed;
-}
-
-static int pose_select_grouped_exec(bContext *C, wmOperator *op)
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bArmature *arm = (bArmature *)ob->data;
- short extend = RNA_boolean_get(op->ptr, "extend");
- short changed = 0;
-
- /* sanity check */
- if (ob->pose == NULL)
- return OPERATOR_CANCELLED;
-
- /* selection types
- * NOTE: for the order of these, see the enum in POSE_OT_select_grouped()
- */
- switch (RNA_enum_get(op->ptr, "type")) {
- case 1: /* group */
- changed = pose_select_same_group(C, ob, extend);
- break;
- case 2: /* Keying Set */
- changed = pose_select_same_keyingset(C, ob, extend);
- break;
- default: /* layer */
- changed = pose_select_same_layer(C, ob, extend);
- break;
- }
-
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- if (arm->flag & ARM_HAS_VIZ_DEPS) {
- /* mask modifier ('armature' mode), etc. */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- }
-
- /* report done status */
- if (changed)
- return OPERATOR_FINISHED;
- else
- return OPERATOR_CANCELLED;
-}
-
-void POSE_OT_select_grouped(wmOperatorType *ot)
-{
- static EnumPropertyItem prop_select_grouped_types[] = {
- {0, "LAYER", 0, "Layer", "Shared layers"},
- {1, "GROUP", 0, "Group", "Shared group"},
- {2, "KEYINGSET", 0, "Keying Set", "All bones affected by active Keying Set"},
- {0, NULL, 0, NULL, NULL}
- };
-
- /* identifiers */
- ot->name = "Select Grouped";
- ot->description = "Select all visible bones grouped by similar properties";
- ot->idname = "POSE_OT_select_grouped";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = pose_select_grouped_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first");
- ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
-}
-
-
-/* ********************************************** */
-
-/* context active object, or weightpainted object with armature in posemode */
-static int pose_bone_flip_active_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob_act = CTX_data_active_object(C);
- Object *ob = BKE_object_pose_armature_get(ob_act);
-
- if (ob && (ob->mode & OB_MODE_POSE)) {
- bArmature *arm = ob->data;
-
- if (arm->act_bone) {
- bPoseChannel *pchanf;
- char name[MAXBONENAME];
- flip_side_name(name, arm->act_bone->name, TRUE);
-
- pchanf = BKE_pose_channel_find_name(ob->pose, name);
- if (pchanf && pchanf->bone != arm->act_bone) {
- arm->act_bone->flag &= ~BONE_SELECTED;
- pchanf->bone->flag |= BONE_SELECTED;
-
- arm->act_bone = pchanf->bone;
-
- /* in weightpaint we select the associated vertex group too */
- if (ob_act->mode & OB_MODE_WEIGHT_PAINT) {
- ED_vgroup_select_by_name(ob_act, name);
- DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
-
- return OPERATOR_FINISHED;
- }
- }
- }
-
- return OPERATOR_CANCELLED;
-}
-
-void POSE_OT_select_flip_active(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Flip Selected Active Bone";
- ot->idname = "POSE_OT_select_flip_active";
- ot->description = "Activate the bone with a flipped name";
-
- /* api callbacks */
- ot->exec = pose_bone_flip_active_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-
-/* ********************************************** */
-#if 0 /* UNUSED 2.5 */
-static void pose_copy_menu(Scene *scene)
-{
- Object *obedit = scene->obedit; // XXX context
- Object *ob = OBACT;
- bArmature *arm;
- bPoseChannel *pchan, *pchanact;
- short nr = 0;
- int i = 0;
-
- /* paranoia checks */
- if (ELEM(NULL, ob, ob->pose)) return;
- if ((ob == obedit) || (ob->mode & OB_MODE_POSE) == 0) return;
-
- pchan = BKE_pose_channel_active(ob);
-
- if (pchan == NULL) return;
- pchanact = pchan;
- arm = ob->data;
-
- /* if proxy-protected bones selected, some things (such as locks + displays) shouldn't be changeable,
- * 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 */
- 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 */
- 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
- 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|%l|Transform Locks %x6|IK Limits %x7|Bone Shape %x8");
- }
-
- if (nr <= 0)
- return;
-
- if (nr != 5) {
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if ((arm->layer & pchan->bone->layer) &&
- (pchan->bone->flag & BONE_SELECTED) &&
- (pchan != pchanact) )
- {
- switch (nr) {
- case 1: /* Local Location */
- copy_v3_v3(pchan->loc, pchanact->loc);
- break;
- case 2: /* Local Rotation */
- copy_qt_qt(pchan->quat, pchanact->quat);
- copy_v3_v3(pchan->eul, pchanact->eul);
- break;
- case 3: /* Local Size */
- copy_v3_v3(pchan->size, pchanact->size);
- break;
- case 4: /* All Constraints */
- {
- ListBase tmp_constraints = {NULL, NULL};
-
- /* copy constraints to tmpbase and apply 'local' tags before
- * appending to list of constraints for this channel
- */
- copy_constraints(&tmp_constraints, &pchanact->constraints, TRUE);
- if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) {
- bConstraint *con;
-
- /* add proxy-local tags */
- for (con = tmp_constraints.first; con; con = con->next)
- con->flag |= CONSTRAINT_PROXY_LOCAL;
- }
- BLI_movelisttolist(&pchan->constraints, &tmp_constraints);
-
- /* update flags (need to add here, not just copy) */
- pchan->constflag |= pchanact->constflag;
-
- if (ob->pose)
- ob->pose->flag |= POSE_RECALC;
- }
- break;
- case 6: /* Transform Locks */
- pchan->protectflag = pchanact->protectflag;
- break;
- case 7: /* IK (DOF) settings */
- {
- pchan->ikflag = pchanact->ikflag;
- copy_v3_v3(pchan->limitmin, pchanact->limitmin);
- copy_v3_v3(pchan->limitmax, pchanact->limitmax);
- copy_v3_v3(pchan->stiffness, pchanact->stiffness);
- pchan->ikstretch = pchanact->ikstretch;
- pchan->ikrotweight = pchanact->ikrotweight;
- pchan->iklinweight = pchanact->iklinweight;
- }
- break;
- case 8: /* Custom Bone Shape */
- pchan->custom = pchanact->custom;
- break;
- case 9: /* Visual Location */
- BKE_armature_loc_pose_to_bone(pchan, pchanact->pose_mat[3], pchan->loc);
- break;
- case 10: /* Visual Rotation */
- {
- float delta_mat[4][4];
-
- BKE_armature_mat_pose_to_bone(pchan, pchanact->pose_mat, delta_mat);
-
- if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- float tmp_quat[4];
-
- /* need to convert to quat first (in temp var)... */
- mat4_to_quat(tmp_quat, delta_mat);
- quat_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, tmp_quat);
- }
- else if (pchan->rotmode == ROT_MODE_QUAT)
- mat4_to_quat(pchan->quat, delta_mat);
- else
- mat4_to_eulO(pchan->eul, pchan->rotmode, delta_mat);
- }
- break;
- case 11: /* Visual Size */
- {
- float delta_mat[4][4], size[4];
-
- BKE_armature_mat_pose_to_bone(pchan, pchanact->pose_mat, delta_mat);
- mat4_to_size(size, delta_mat);
- copy_v3_v3(pchan->size, size);
- }
- }
- }
- }
- }
- else { /* constraints, optional (note: max we can have is 24 constraints) */
- bConstraint *con, *con_back;
- int const_toggle[24] = {0}; /* XXX, initialize as 0 to quiet errors */
- ListBase const_copy = {NULL, NULL};
-
- BLI_duplicatelist(&const_copy, &(pchanact->constraints));
-
- /* 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]), "");
- }
-
-// if (!do_clever_numbuts("Select Constraints", i, REDRAW)) {
-// BLI_freelistN(&const_copy);
-// return;
-// }
-
- /* now build a new listbase from the options selected */
- for (i = 0, con = const_copy.first; con; i++) {
- /* if not selected, free/remove it from the list */
- if (!const_toggle[i]) {
- con_back = con->next;
- BLI_freelinkN(&const_copy, con);
- con = con_back;
- }
- else
- con = con->next;
- }
-
- /* Copy the temo listbase to the selected posebones */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if ((arm->layer & pchan->bone->layer) &&
- (pchan->bone->flag & BONE_SELECTED) &&
- (pchan != pchanact) )
- {
- ListBase tmp_constraints = {NULL, NULL};
-
- /* copy constraints to tmpbase and apply 'local' tags before
- * appending to list of constraints for this channel
- */
- copy_constraints(&tmp_constraints, &const_copy, TRUE);
- if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) {
- /* add proxy-local tags */
- for (con = tmp_constraints.first; con; con = con->next)
- con->flag |= CONSTRAINT_PROXY_LOCAL;
- }
- BLI_movelisttolist(&pchan->constraints, &tmp_constraints);
-
- /* update flags (need to add here, not just copy) */
- pchan->constflag |= pchanact->constflag;
- }
- }
- BLI_freelistN(&const_copy);
- 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;
- }
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA); // and all its relations
-
- BIF_undo_push("Copy Pose Attributes");
-
-}
-#endif
-
-/* ******************** copy/paste pose ********************** */
-
-/* Global copy/paste buffer for pose - cleared on start/end session + before every copy operation */
-static bPose *g_posebuf = NULL;
-
-void ED_clipboard_posebuf_free(void)
-{
- if (g_posebuf) {
- bPoseChannel *pchan;
-
- for (pchan = g_posebuf->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->prop) {
- IDP_FreeProperty(pchan->prop);
- MEM_freeN(pchan->prop);
- }
- }
-
- /* was copied without constraints */
- BLI_freelistN(&g_posebuf->chanbase);
- MEM_freeN(g_posebuf);
- }
-
- g_posebuf = NULL;
-}
-
-/* This function is used to indicate that a bone is selected
- * and needs to be included in copy buffer (used to be for inserting keys)
- */
-static void set_pose_keys(Object *ob)
-{
- bArmature *arm = ob->data;
- bPoseChannel *chan;
-
- if (ob->pose) {
- for (chan = ob->pose->chanbase.first; chan; chan = chan->next) {
- Bone *bone = chan->bone;
- if ((bone) && (bone->flag & BONE_SELECTED) && (arm->layer & bone->layer))
- chan->flag |= POSE_KEY;
- else
- chan->flag &= ~POSE_KEY;
- }
- }
-}
-
-/* perform paste pose, for a single bone
- * < ob: object where bone to paste to lives
- * < chan: bone that pose to paste comes from
- * < selOnly: only paste on selected bones
- * < flip: flip on x-axis
- *
- * > returns: whether the bone that we pasted to if we succeeded
- */
-static bPoseChannel *pose_bone_do_paste(Object *ob, bPoseChannel *chan, short selOnly, short flip)
-{
- bPoseChannel *pchan;
- char name[MAXBONENAME];
- short paste_ok;
-
- /* get the name - if flipping, we must flip this first */
- if (flip)
- flip_side_name(name, chan->name, 0); /* 0 = don't strip off number extensions */
- else
- BLI_strncpy(name, chan->name, sizeof(name));
-
- /* only copy when:
- * 1) channel exists - poses are not meant to add random channels to anymore
- * 2) if selection-masking is on, channel is selected - only selected bones get pasted on, allowing making both sides symmetrical
- */
- pchan = BKE_pose_channel_find_name(ob->pose, name);
-
- if (selOnly)
- paste_ok = ((pchan) && (pchan->bone->flag & BONE_SELECTED));
- else
- paste_ok = ((pchan != NULL));
-
- /* continue? */
- if (paste_ok) {
- /* only loc rot size
- * - only copies transform info for the pose
- */
- copy_v3_v3(pchan->loc, chan->loc);
- copy_v3_v3(pchan->size, chan->size);
- pchan->flag = chan->flag;
-
- /* check if rotation modes are compatible (i.e. do they need any conversions) */
- if (pchan->rotmode == chan->rotmode) {
- /* copy the type of rotation in use */
- if (pchan->rotmode > 0) {
- copy_v3_v3(pchan->eul, chan->eul);
- }
- else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- copy_v3_v3(pchan->rotAxis, chan->rotAxis);
- pchan->rotAngle = chan->rotAngle;
- }
- else {
- copy_qt_qt(pchan->quat, chan->quat);
- }
- }
- else if (pchan->rotmode > 0) {
- /* quat/axis-angle to euler */
- if (chan->rotmode == ROT_MODE_AXISANGLE)
- axis_angle_to_eulO(pchan->eul, pchan->rotmode, chan->rotAxis, chan->rotAngle);
- else
- quat_to_eulO(pchan->eul, pchan->rotmode, chan->quat);
- }
- else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- /* quat/euler to axis angle */
- if (chan->rotmode > 0)
- eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->eul, chan->rotmode);
- else
- quat_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->quat);
- }
- else {
- /* euler/axis-angle to quat */
- if (chan->rotmode > 0)
- eulO_to_quat(pchan->quat, chan->eul, chan->rotmode);
- else
- axis_angle_to_quat(pchan->quat, chan->rotAxis, pchan->rotAngle);
- }
-
- /* paste flipped pose? */
- if (flip) {
- pchan->loc[0] *= -1;
-
- /* has to be done as eulers... */
- if (pchan->rotmode > 0) {
- pchan->eul[1] *= -1;
- pchan->eul[2] *= -1;
- }
- else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
- float eul[3];
-
- axis_angle_to_eulO(eul, EULER_ORDER_DEFAULT, pchan->rotAxis, pchan->rotAngle);
- eul[1] *= -1;
- eul[2] *= -1;
- eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, eul, EULER_ORDER_DEFAULT);
- }
- else {
- float eul[3];
-
- normalize_qt(pchan->quat);
- quat_to_eul(eul, pchan->quat);
- eul[1] *= -1;
- eul[2] *= -1;
- eul_to_quat(pchan->quat, eul);
- }
- }
-
- /* ID properties */
- if (chan->prop) {
- if (pchan->prop) {
- /* if we have existing properties on a bone, just copy over the values of
- * matching properties (i.e. ones which will have some impact) on to the
- * target instead of just blinding replacing all [
- */
- IDP_SyncGroupValues(pchan->prop, chan->prop);
- }
- else {
- /* no existing properties, so assume that we want copies too? */
- pchan->prop = IDP_CopyProperty(chan->prop);
- }
- }
- }
-
- /* return whether paste went ahead */
- return pchan;
-}
-
-/* ---- */
-
-static int pose_copy_exec(bContext *C, wmOperator *op)
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
-
- /* sanity checking */
- if (ELEM(NULL, ob, ob->pose)) {
- BKE_report(op->reports, RPT_ERROR, "No pose to copy");
- return OPERATOR_CANCELLED;
- }
-
- /* free existing pose buffer */
- ED_clipboard_posebuf_free();
-
- /* sets chan->flag to POSE_KEY if bone selected, then copy those bones to the buffer */
- set_pose_keys(ob);
- BKE_pose_copy_data(&g_posebuf, ob->pose, 0);
-
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_copy(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Copy Pose";
- ot->idname = "POSE_OT_copy";
- ot->description = "Copies the current pose of the selected bones to copy/paste buffer";
-
- /* api callbacks */
- ot->exec = pose_copy_exec;
- ot->poll = ED_operator_posemode;
-
- /* flag */
- ot->flag = OPTYPE_REGISTER;
-}
-
-/* ---- */
-
-static int pose_paste_exec(bContext *C, wmOperator *op)
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- Scene *scene = CTX_data_scene(C);
- bPoseChannel *chan;
- int flip = RNA_boolean_get(op->ptr, "flipped");
- int selOnly = RNA_boolean_get(op->ptr, "selected_mask");
-
- /* get KeyingSet to use */
- KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOC_ROT_SCALE_ID);
-
- /* sanity checks */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
-
- if (g_posebuf == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Copy buffer is empty");
- return OPERATOR_CANCELLED;
- }
-
- /* if selOnly option is enabled, if user hasn't selected any bones,
- * just go back to default behavior to be more in line with other pose tools
- */
- if (selOnly) {
- if (CTX_DATA_COUNT(C, selected_pose_bones) == 0)
- selOnly = 0;
- }
-
- /* Safely merge all of the channels in the buffer pose into any existing pose */
- for (chan = g_posebuf->chanbase.first; chan; chan = chan->next) {
- if (chan->flag & POSE_KEY) {
- /* try to perform paste on this bone */
- bPoseChannel *pchan = pose_bone_do_paste(ob, chan, selOnly, flip);
-
- if (pchan) {
- /* keyframing tagging for successful paste */
- ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
- }
- }
- }
-
- /* Update event for pose and deformation children */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_paste(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Paste Pose";
- ot->idname = "POSE_OT_paste";
- ot->description = "Paste the stored pose on to the current pose";
-
- /* api callbacks */
- ot->exec = pose_paste_exec;
- ot->poll = ED_operator_posemode;
-
- /* flag */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_boolean(ot->srna, "flipped", FALSE, "Flipped on X-Axis", "Paste the stored pose flipped on to current pose");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
- RNA_def_boolean(ot->srna, "selected_mask", FALSE, "On Selected Only", "Only paste the stored pose on to selected bones in the current pose");
-}
-
-/* ********************************************** */
-/* Bone Groups */
-
-static int pose_group_add_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = ED_pose_object_from_context(C);
-
- /* only continue if there's an object */
- if (ob == NULL)
- return OPERATOR_CANCELLED;
-
- /* for now, just call the API function for this */
- BKE_pose_add_group(ob);
-
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_group_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Bone Group";
- ot->idname = "POSE_OT_group_add";
- ot->description = "Add a new bone group";
-
- /* api callbacks */
- ot->exec = pose_group_add_exec;
- ot->poll = ED_operator_posemode_context;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-
-static int pose_group_remove_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = ED_pose_object_from_context(C);
-
- /* only continue if there's an object */
- if (ob == NULL)
- return OPERATOR_CANCELLED;
-
- /* for now, just call the API function for this */
- BKE_pose_remove_group(ob);
-
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_group_remove(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Remove Bone Group";
- ot->idname = "POSE_OT_group_remove";
- ot->description = "Remove the active bone group";
-
- /* api callbacks */
- ot->exec = pose_group_remove_exec;
- ot->poll = ED_operator_posemode_context;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* ------------ */
-
-/* invoke callback which presents a list of bone-groups for the user to choose from */
-static int pose_groups_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt))
-{
- Object *ob = ED_pose_object_from_context(C);
- bPose *pose;
-
- uiPopupMenu *pup;
- uiLayout *layout;
- bActionGroup *grp;
- int i;
-
- /* only continue if there's an object, and a pose there too */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
- pose = ob->pose;
-
- /* 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);
-
- /* special entry - allow to create new group, then use that
- * (not to be used for removing though)
- */
- if (strstr(op->idname, "assign")) {
- uiItemIntO(layout, "New Group", ICON_NONE, op->idname, "type", 0);
- uiItemS(layout);
- }
-
- /* add entries for each group */
- for (grp = pose->agroups.first, i = 1; grp; grp = grp->next, i++)
- 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);
-
- return OPERATOR_CANCELLED;
- }
- else {
- /* just use the active group index, and call the exec callback for the calling operator */
- RNA_int_set(op->ptr, "type", pose->active_group);
- return op->type->exec(C, op);
- }
-}
-
-/* Assign selected pchans to the bone group that the user selects */
-static int pose_group_assign_exec(bContext *C, wmOperator *op)
-{
- Object *ob = ED_pose_object_from_context(C);
- bPose *pose;
- short done = FALSE;
-
- /* only continue if there's an object, and a pose there too */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
-
- pose = ob->pose;
-
- /* set the active group number to the one from operator props
- * - if 0 after this, make a new group...
- */
- pose->active_group = RNA_int_get(op->ptr, "type");
- if (pose->active_group == 0)
- BKE_pose_add_group(ob);
-
- /* add selected bones to group then */
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
- {
- pchan->agrp_index = pose->active_group;
- done = TRUE;
- }
- CTX_DATA_END;
-
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- /* report done status */
- if (done)
- return OPERATOR_FINISHED;
- else
- return OPERATOR_CANCELLED;
-}
-
-void POSE_OT_group_assign(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Selected to Bone Group";
- ot->idname = "POSE_OT_group_assign";
- ot->description = "Add selected bones to the chosen bone group";
-
- /* api callbacks */
- ot->invoke = pose_groups_menu_invoke;
- ot->exec = pose_group_assign_exec;
- ot->poll = ED_operator_posemode_context;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_int(ot->srna, "type", 0, 0, INT_MAX, "Bone Group Index", "", 0, 10);
-}
-
-
-static int pose_group_unassign_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = ED_pose_object_from_context(C);
- short done = FALSE;
-
- /* only continue if there's an object, and a pose there too */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
-
- /* find selected bones to remove from all bone groups */
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
- {
- if (pchan->agrp_index) {
- pchan->agrp_index = 0;
- done = TRUE;
- }
- }
- CTX_DATA_END;
-
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- /* report done status */
- if (done)
- return OPERATOR_FINISHED;
- else
- return OPERATOR_CANCELLED;
-}
-
-void POSE_OT_group_unassign(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Remove Selected from Bone Groups";
- ot->idname = "POSE_OT_group_unassign";
- ot->description = "Remove selected bones from all bone groups";
-
- /* api callbacks */
- ot->exec = pose_group_unassign_exec;
- ot->poll = ED_operator_posemode_context;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static int group_move_exec(bContext *C, wmOperator *op)
-{
- Object *ob = ED_pose_object_from_context(C);
- bPose *pose = (ob) ? ob->pose : NULL;
- bPoseChannel *pchan;
- bActionGroup *grp;
- int dir = RNA_enum_get(op->ptr, "direction");
- int grpIndexA, grpIndexB;
-
- if (ELEM(NULL, ob, pose))
- return OPERATOR_CANCELLED;
- if (pose->active_group <= 0)
- return OPERATOR_CANCELLED;
-
- /* get group to move */
- grp = BLI_findlink(&pose->agroups, pose->active_group - 1);
- if (grp == NULL)
- return OPERATOR_CANCELLED;
-
- /* move bone group */
- grpIndexA = pose->active_group;
- if (dir == 1) { /* up */
- void *prev = grp->prev;
-
- if (prev == NULL)
- return OPERATOR_FINISHED;
-
- BLI_remlink(&pose->agroups, grp);
- BLI_insertlinkbefore(&pose->agroups, prev, grp);
-
- grpIndexB = grpIndexA - 1;
- pose->active_group--;
- }
- else { /* down */
- void *next = grp->next;
-
- if (next == NULL)
- return OPERATOR_FINISHED;
-
- BLI_remlink(&pose->agroups, grp);
- BLI_insertlinkafter(&pose->agroups, next, grp);
-
- grpIndexB = grpIndexA + 1;
- pose->active_group++;
- }
-
- /* fix changed bone group indices in bones (swap grpIndexA with grpIndexB) */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->agrp_index == grpIndexB)
- pchan->agrp_index = grpIndexA;
- else if (pchan->agrp_index == grpIndexA)
- pchan->agrp_index = grpIndexB;
- }
-
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_group_move(wmOperatorType *ot)
-{
- static EnumPropertyItem group_slot_move[] = {
- {1, "UP", 0, "Up", ""},
- {-1, "DOWN", 0, "Down", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- /* identifiers */
- ot->name = "Move Bone Group";
- ot->idname = "POSE_OT_group_move";
- ot->description = "Change position of active Bone Group in list of Bone Groups";
-
- /* api callbacks */
- ot->exec = group_move_exec;
- ot->poll = ED_operator_posemode_context;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "direction", group_slot_move, 0, "Direction", "Direction to move, UP or DOWN");
-}
-
-/* bone group sort element */
-typedef struct tSortActionGroup {
- bActionGroup *agrp;
- int index;
-} 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;
-
- return strcmp(sgrp_a->agrp->name, sgrp_b->agrp->name);
-}
-
-static int group_sort_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = ED_pose_object_from_context(C);
- bPose *pose = (ob) ? ob->pose : NULL;
- bPoseChannel *pchan;
- tSortActionGroup *agrp_array;
- bActionGroup *agrp;
- int agrp_count;
- int i;
-
- if (ELEM(NULL, ob, pose))
- return OPERATOR_CANCELLED;
- if (pose->active_group <= 0)
- return OPERATOR_CANCELLED;
-
- /* create temporary array with bone groups and indices */
- agrp_count = BLI_countlist(&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);
- agrp_array[i].agrp = agrp;
- agrp_array[i].index = i + 1;
- }
-
- /* sort bone groups by name */
- qsort(agrp_array, agrp_count, sizeof(tSortActionGroup), compare_agroup);
-
- /* create sorted bone group list from sorted array */
- pose->agroups.first = pose->agroups.last = NULL;
- for (i = 0; i < agrp_count; i++) {
- BLI_addtail(&pose->agroups, agrp_array[i].agrp);
- }
-
- /* fix changed bone group indizes in bones */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- for (i = 0; i < agrp_count; i++) {
- if (pchan->agrp_index == agrp_array[i].index) {
- pchan->agrp_index = i + 1;
- break;
- }
- }
- }
-
- /* free temp resources */
- MEM_freeN(agrp_array);
-
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_group_sort(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Sort Bone Groups";
- ot->idname = "POSE_OT_group_sort";
- ot->description = "Sort Bone Groups by their names in ascending order";
-
- /* api callbacks */
- ot->exec = group_sort_exec;
- ot->poll = ED_operator_posemode_context;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static void pose_group_select(bContext *C, Object *ob, int select)
-{
- bPose *pose = ob->pose;
-
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
- {
- if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
- if (select) {
- if (pchan->agrp_index == pose->active_group)
- pchan->bone->flag |= BONE_SELECTED;
- }
- else {
- if (pchan->agrp_index == pose->active_group)
- pchan->bone->flag &= ~BONE_SELECTED;
- }
- }
- }
- CTX_DATA_END;
-}
-
-static int pose_group_select_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = ED_pose_object_from_context(C);
-
- /* only continue if there's an object, and a pose there too */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
-
- pose_group_select(C, ob, 1);
-
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_group_select(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Bones of Bone Group";
- ot->idname = "POSE_OT_group_select";
- ot->description = "Select bones in active Bone Group";
-
- /* api callbacks */
- ot->exec = pose_group_select_exec;
- ot->poll = ED_operator_posemode_context;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static int pose_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = ED_pose_object_from_context(C);
-
- /* only continue if there's an object, and a pose there too */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
-
- pose_group_select(C, ob, 0);
-
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_group_deselect(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Deselect Bone Group";
- ot->idname = "POSE_OT_group_deselect";
- ot->description = "Deselect bones of active Bone Group";
-
- /* api callbacks */
- ot->exec = pose_group_deselect_exec;
- ot->poll = ED_operator_posemode_context;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* ********************************************** */
-
-static int pose_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bArmature *arm;
-
- /* paranoia checks */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
- arm = ob->data;
-
- /* loop through selected bones, auto-naming them */
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
- {
- char newname[MAXBONENAME];
- flip_side_name(newname, pchan->name, TRUE);
- ED_armature_bone_rename(arm, pchan->name, newname);
- }
- CTX_DATA_END;
-
- /* since we renamed stuff... */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-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";
-
- /* api callbacks */
- ot->exec = pose_flip_names_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* ------------------ */
-
-static int pose_autoside_names_exec(bContext *C, wmOperator *op)
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bArmature *arm;
- char newname[MAXBONENAME];
- short axis = RNA_enum_get(op->ptr, "axis");
-
- /* paranoia checks */
- if (ELEM(NULL, ob, ob->pose))
- return OPERATOR_CANCELLED;
- arm = ob->data;
-
- /* loop through selected bones, auto-naming them */
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
- {
- BLI_strncpy(newname, pchan->name, sizeof(newname));
- if (bone_autoside_name(newname, 1, axis, pchan->bone->head[axis], pchan->bone->tail[axis]))
- ED_armature_bone_rename(arm, pchan->name, newname);
- }
- CTX_DATA_END;
-
- /* since we renamed stuff... */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_autoside_names(wmOperatorType *ot)
-{
- static EnumPropertyItem axis_items[] = {
- {0, "XAXIS", 0, "X-Axis", "Left/Right"},
- {1, "YAXIS", 0, "Y-Axis", "Front/Back"},
- {2, "ZAXIS", 0, "Z-Axis", "Top/Bottom"},
- {0, NULL, 0, NULL, NULL}
- };
-
- /* identifiers */
- ot->name = "AutoName by Axis";
- ot->idname = "POSE_OT_autoside_names";
- ot->description = "Automatically renames the selected bones according to which side of the target axis they fall on";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = pose_autoside_names_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* settings */
- ot->prop = RNA_def_enum(ot->srna, "axis", axis_items, 0, "Axis", "Axis tag names with");
-}
-
-/* ********************************************** */
-
-static int pose_bone_rotmode_exec(bContext *C, wmOperator *op)
-{
- Object *ob = CTX_data_active_object(C);
- int mode = RNA_enum_get(op->ptr, "type");
-
- /* set rotation mode of selected bones */
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
- {
- pchan->rotmode = mode;
- }
- CTX_DATA_END;
-
- /* notifiers and updates */
- DAG_id_tag_update((ID *)ob, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_rotation_mode_set(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Set Rotation Mode";
- ot->idname = "POSE_OT_rotation_mode_set";
- ot->description = "Set the rotation representation used by selected bones";
-
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = pose_bone_rotmode_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", posebone_rotmode_items, 0, "Rotation Mode", "");
-}
-
-/* ********************************************** */
-
-/* Show all armature layers */
-static int pose_armature_layers_showall_poll(bContext *C)
-{
- /* this single operator can be used in posemode OR editmode for armatures */
- return ED_operator_posemode(C) || ED_operator_editarmature(C);
-}
-
-static int pose_armature_layers_showall_exec(bContext *C, wmOperator *op)
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bArmature *arm = (ob) ? ob->data : NULL;
- PointerRNA ptr;
- int maxLayers = (RNA_boolean_get(op->ptr, "all")) ? 32 : 16;
- int layers[32] = {0}; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
- int i;
-
- /* sanity checking */
- if (arm == NULL)
- return OPERATOR_CANCELLED;
-
- /* use RNA to set the layers
- * although it would be faster to just set directly using bitflags, we still
- * need to setup a RNA pointer so that we get the "update" callbacks for free...
- */
- RNA_id_pointer_create(&arm->id, &ptr);
-
- for (i = 0; i < maxLayers; i++)
- layers[i] = 1;
-
- RNA_boolean_set_array(&ptr, "layers", layers);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- /* done */
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_layers_show_all(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Show All Layers";
- ot->idname = "ARMATURE_OT_layers_show_all";
- ot->description = "Make all armature layers visible";
-
- /* callbacks */
- ot->exec = pose_armature_layers_showall_exec;
- ot->poll = pose_armature_layers_showall_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_boolean(ot->srna, "all", 1, "All Layers", "Enable all layers or just the first 16 (top row)");
-}
-
-/* ------------------- */
-
-/* Present a popup to get the layers that should be used */
-static int pose_armature_layers_invoke(bContext *C, wmOperator *op, wmEvent *evt)
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bArmature *arm = (ob) ? ob->data : NULL;
- PointerRNA ptr;
- int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
-
- /* sanity checking */
- if (arm == NULL)
- return OPERATOR_CANCELLED;
-
- /* get RNA pointer to armature data to use that to retrieve the layers as ints to init the operator */
- RNA_id_pointer_create((ID *)arm, &ptr);
- RNA_boolean_get_array(&ptr, "layers", layers);
- RNA_boolean_set_array(op->ptr, "layers", layers);
-
- /* part to sync with other similar operators... */
- return WM_operator_props_popup(C, op, evt);
-}
-
-/* Set the visible layers for the active armature (edit and pose modes) */
-static int pose_armature_layers_exec(bContext *C, wmOperator *op)
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- PointerRNA ptr;
- int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
-
- if (ELEM(NULL, ob, ob->data)) {
- return OPERATOR_CANCELLED;
- }
-
- /* get the values set in the operator properties */
- RNA_boolean_get_array(op->ptr, "layers", layers);
-
- /* get pointer for armature, and write data there... */
- RNA_id_pointer_create((ID *)ob->data, &ptr);
- RNA_boolean_set_array(&ptr, "layers", layers);
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-
-void POSE_OT_armature_layers(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Change Armature Layers";
- ot->idname = "POSE_OT_armature_layers";
- ot->description = "Change the visible armature layers";
-
- /* callbacks */
- ot->invoke = pose_armature_layers_invoke;
- ot->exec = pose_armature_layers_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers to make visible");
-}
-
-void ARMATURE_OT_armature_layers(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Change Armature Layers";
- ot->idname = "ARMATURE_OT_armature_layers";
- ot->description = "Change the visible armature layers";
-
- /* callbacks */
- ot->invoke = pose_armature_layers_invoke;
- ot->exec = pose_armature_layers_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers to make visible");
-}
-
-/* ------------------- */
-
-/* Present a popup to get the layers that should be used */
-static int pose_bone_layers_invoke(bContext *C, wmOperator *op, wmEvent *evt)
-{
- int layers[32] = {0}; /* 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)
- {
- short bit;
-
- /* 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;
- }
- }
- CTX_DATA_END;
-
- /* copy layers to operator */
- RNA_boolean_set_array(op->ptr, "layers", layers);
-
- /* part to sync with other similar operators... */
- return WM_operator_props_popup(C, op, evt);
-}
-
-/* Set the visible layers for the active armature (edit and pose modes) */
-static int pose_bone_layers_exec(bContext *C, wmOperator *op)
-{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- PointerRNA ptr;
- int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
-
- if (ob == NULL || ob->data == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- /* get the values set in the operator properties */
- RNA_boolean_get_array(op->ptr, "layers", layers);
-
- /* set layers of pchans based on the values set in the operator props */
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
- {
- /* get pointer for pchan, and write flags this way */
- RNA_pointer_create((ID *)ob->data, &RNA_Bone, pchan->bone, &ptr);
- RNA_boolean_set_array(&ptr, "layers", layers);
- }
- CTX_DATA_END;
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_bone_layers(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Change Bone Layers";
- ot->idname = "POSE_OT_bone_layers";
- ot->description = "Change the layers that the selected bones belong to";
-
- /* callbacks */
- ot->invoke = pose_bone_layers_invoke;
- ot->exec = pose_bone_layers_exec;
- ot->poll = ED_operator_posemode_exclusive;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers that bone belongs to");
-}
-
-/* ------------------- */
-
-/* Present a popup to get the layers that should be used */
-static int armature_bone_layers_invoke(bContext *C, wmOperator *op, wmEvent *evt)
-{
- int layers[32] = {0}; /* 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, EditBone *, ebone, selected_editable_bones)
- {
- short bit;
-
- /* 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))
- layers[bit] = 1;
- }
- }
- CTX_DATA_END;
-
- /* copy layers to operator */
- RNA_boolean_set_array(op->ptr, "layers", layers);
-
- /* part to sync with other similar operators... */
- return WM_operator_props_popup(C, op, evt);
-}
-
-/* Set the visible layers for the active armature (edit and pose modes) */
-static int armature_bone_layers_exec(bContext *C, wmOperator *op)
-{
- Object *ob = CTX_data_edit_object(C);
- bArmature *arm = (ob) ? ob->data : NULL;
- PointerRNA ptr;
- int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
-
- /* get the values set in the operator properties */
- RNA_boolean_get_array(op->ptr, "layers", layers);
-
- /* set layers of pchans based on the values set in the operator props */
- CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones)
- {
- /* get pointer for pchan, and write flags this way */
- RNA_pointer_create((ID *)arm, &RNA_EditBone, ebone, &ptr);
- RNA_boolean_set_array(&ptr, "layers", layers);
- }
- CTX_DATA_END;
-
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_bone_layers(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Change Bone Layers";
- ot->idname = "ARMATURE_OT_bone_layers";
- ot->description = "Change the layers that the selected bones belong to";
-
- /* callbacks */
- ot->invoke = armature_bone_layers_invoke;
- ot->exec = armature_bone_layers_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers that bone belongs to");
-}
-
-/* ********************************************** */
-/* Flip Quats */
-
-static int pose_flip_quats_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Scene *scene = CTX_data_scene(C);
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID);
-
- /* loop through all selected pchans, flipping and keying (as needed) */
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
- {
- /* only if bone is using quaternion rotation */
- if (pchan->rotmode == ROT_MODE_QUAT) {
- /* quaternions have 720 degree range */
- negate_v4(pchan->quat);
-
- ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
- }
- }
- CTX_DATA_END;
-
- /* notifiers and updates */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_quaternions_flip(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Flip Quats";
- ot->idname = "POSE_OT_quaternions_flip";
- ot->description = "Flip quaternion values to achieve desired rotations, while maintaining the same orientations";
-
- /* callbacks */
- ot->exec = pose_flip_quats_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* ********************************************** */
-/* Clear User Transforms */
-
-static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- float cframe = (float)CFRA;
- const short only_select = RNA_boolean_get(op->ptr, "only_selected");
-
- if ((ob->adt) && (ob->adt->action)) {
- /* XXX: this is just like this to avoid contaminating anything else;
- * just pose values should change, so this should be fine
- */
- bPose *dummyPose = NULL;
- Object workob = {{0}};
- bPoseChannel *pchan;
-
- /* execute animation step for current frame using a dummy copy of the pose */
- BKE_pose_copy_data(&dummyPose, ob->pose, 0);
-
- BLI_strncpy(workob.id.name, "OB<ClearTfmWorkOb>", sizeof(workob.id.name));
- workob.type = OB_ARMATURE;
- workob.data = ob->data;
- workob.adt = ob->adt;
- workob.pose = dummyPose;
-
- BKE_animsys_evaluate_animdata(scene, &workob.id, workob.adt, cframe, ADT_RECALC_ANIM);
-
- /* copy back values, but on selected bones only */
- for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
- pose_bone_do_paste(ob, pchan, only_select, 0);
- }
-
- /* free temp data - free manually as was copied without constraints */
- for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->prop) {
- IDP_FreeProperty(pchan->prop);
- MEM_freeN(pchan->prop);
- }
- }
-
- /* was copied without constraints */
- BLI_freelistN(&dummyPose->chanbase);
- MEM_freeN(dummyPose);
- }
- else {
- /* no animation, so just reset whole pose to rest pose
- * (cannot just restore for selected though)
- */
- BKE_pose_rest(ob->pose);
- }
-
- /* notifiers and updates */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void POSE_OT_user_transforms_clear(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Clear User Transforms";
- ot->idname = "POSE_OT_user_transforms_clear";
- ot->description = "Reset pose on selected bones to keyframed state";
-
- /* callbacks */
- ot->exec = pose_clear_user_transforms_exec;
- ot->poll = ED_operator_posemode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "only_selected", TRUE, "Only Selected", "Only visible/selected bones");
-}
-
diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c
index b1bf13db69b..d04938fd59b 100644
--- a/source/blender/editors/armature/reeb.c
+++ b/source/blender/editors/armature/reeb.c
@@ -24,29 +24,14 @@
* \ingroup edarmature
*/
-#include <math.h>
-#include <string.h> /* for memcpy */
-#include <stdio.h>
-#include <stdlib.h> /* for qsort */
-#include <float.h>
-
-#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
-
#include "MEM_guardedalloc.h"
#include "BKE_context.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
#include "BLI_edgehash.h"
#include "BLI_ghash.h"
-#include "BLI_heap.h"
-
-#include "BKE_mesh.h"
-
-#include "ONL_opennl.h"
#include "reeb.h"
@@ -634,7 +619,7 @@ static void mergeArcBuckets(ReebArc *aDst, ReebArc *aSrc, float start, float end
if (aDst->bcount > 0 && aSrc->bcount > 0) {
int indexDst = 0, indexSrc = 0;
- start = MAX3(start, aDst->buckets[0].val, aSrc->buckets[0].val);
+ start = max_fff(start, aDst->buckets[0].val, aSrc->buckets[0].val);
while (indexDst < aDst->bcount && aDst->buckets[indexDst].val < start) {
indexDst++;
@@ -1674,7 +1659,7 @@ int filterSmartReebGraph(ReebGraph *UNUSED(rg), float UNUSED(threshold))
float avg_vec[3] = {0, 0, 0};
for (BLI_ghashIterator_init(&ghi, arc->faces);
- !BLI_ghashIterator_isDone(&ghi);
+ BLI_ghashIterator_notDone(&ghi);
BLI_ghashIterator_step(&ghi))
{
EditFace *efa = BLI_ghashIterator_getValue(&ghi);
@@ -2060,7 +2045,7 @@ void mergeArcFaces(ReebGraph *UNUSED(rg), ReebArc *aDst, ReebArc *aSrc)
GHashIterator ghi;
for (BLI_ghashIterator_init(&ghi, aSrc->faces);
- !BLI_ghashIterator_isDone(&ghi);
+ BLI_ghashIterator_notDone(&ghi);
BLI_ghashIterator_step(&ghi))
{
EditFace *efa = BLI_ghashIterator_getValue(&ghi);
diff --git a/source/blender/editors/curve/CMakeLists.txt b/source/blender/editors/curve/CMakeLists.txt
index 25df17d232a..c38ded49830 100644
--- a/source/blender/editors/curve/CMakeLists.txt
+++ b/source/blender/editors/curve/CMakeLists.txt
@@ -20,6 +20,7 @@
set(INC
../include
+ ../../blenfont
../../blenkernel
../../blenlib
../../blenloader
@@ -42,4 +43,8 @@ set(SRC
curve_intern.h
)
+if(WITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
+endif()
+
blender_add_lib(bf_editor_curve "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/curve/SConscript b/source/blender/editors/curve/SConscript
index 95dd7fc6233..21c6a3732fa 100644
--- a/source/blender/editors/curve/SConscript
+++ b/source/blender/editors/curve/SConscript
@@ -1,11 +1,42 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
-incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+defs = []
+
+incs = '../include ../../blenfont ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
incs += ' ../../bmesh ../../gpu ../../blenloader'
incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern'
-env.BlenderLib ( 'bf_editors_curve', sources, Split(incs), [], libtype=['core'], priority=[45] )
+if env['WITH_BF_INTERNATIONAL']:
+ defs.append('WITH_INTERNATIONAL')
+
+env.BlenderLib ( 'bf_editors_curve', sources, Split(incs), defs, libtype=['core'], priority=[45] )
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index f4dccd01007..f95fbd1eacb 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -53,6 +53,8 @@
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
+#include "BLF_translation.h"
+
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
@@ -624,7 +626,9 @@ static void switch_keys_direction(Curve *cu, Nurb *actnu)
bezt++;
}
}
- else fp += a * 12;
+ else {
+ fp += a * 12;
+ }
}
else {
BPoint *bp = nu->bp;
@@ -638,7 +642,9 @@ static void switch_keys_direction(Curve *cu, Nurb *actnu)
bp++;
}
}
- else fp += a * 4;
+ else {
+ fp += a * 4;
+ }
}
nu = nu->next;
@@ -670,7 +676,7 @@ static GHash *dupli_keyIndexHash(GHash *keyindex)
gh = BLI_ghash_ptr_new("dupli_keyIndex gh");
for (hashIter = BLI_ghashIterator_new(keyindex);
- !BLI_ghashIterator_isDone(hashIter);
+ BLI_ghashIterator_notDone(hashIter);
BLI_ghashIterator_step(hashIter))
{
void *cv = BLI_ghashIterator_getKey(hashIter);
@@ -1022,13 +1028,12 @@ static int curve_is_animated(Curve *cu)
return ad && (ad->action || ad->drivers.first);
}
-static void fcurve_path_rename(AnimData *ad, char *orig_rna_path, char *rna_path, ListBase *orig_curves, ListBase *curves)
+static void fcurve_path_rename(AnimData *adt, char *orig_rna_path, char *rna_path, ListBase *orig_curves, ListBase *curves)
{
FCurve *fcu, *nfcu, *nextfcu;
int len = strlen(orig_rna_path);
- fcu = orig_curves->first;
- while (fcu) {
+ for (fcu = orig_curves->first; fcu; fcu = nextfcu) {
nextfcu = fcu->next;
if (!strncmp(fcu->rna_path, orig_rna_path, len)) {
char *spath, *suffix = fcu->rna_path + len;
@@ -1038,26 +1043,25 @@ static void fcurve_path_rename(AnimData *ad, char *orig_rna_path, char *rna_path
BLI_addtail(curves, nfcu);
if (fcu->grp) {
- action_groups_remove_channel(ad->action, fcu);
- action_groups_add_channel(ad->action, fcu->grp, nfcu);
+ action_groups_remove_channel(adt->action, fcu);
+ action_groups_add_channel(adt->action, fcu->grp, nfcu);
}
- else if (ad->action && &ad->action->curves == orig_curves)
- BLI_remlink(&ad->action->curves, fcu);
+ else if ((adt->action) && (&adt->action->curves == orig_curves))
+ BLI_remlink(&adt->action->curves, fcu);
else
- BLI_remlink(&ad->drivers, fcu);
+ BLI_remlink(&adt->drivers, fcu);
free_fcurve(fcu);
MEM_freeN(spath);
}
- fcu = nextfcu;
}
}
-static void fcurve_remove(AnimData *ad, ListBase *orig_curves, FCurve *fcu)
+static void fcurve_remove(AnimData *adt, ListBase *orig_curves, FCurve *fcu)
{
- if (orig_curves == &ad->drivers) BLI_remlink(&ad->drivers, fcu);
- else action_groups_remove_channel(ad->action, fcu);
+ if (orig_curves == &adt->drivers) BLI_remlink(&adt->drivers, fcu);
+ else action_groups_remove_channel(adt->action, fcu);
free_fcurve(fcu);
}
@@ -1073,7 +1077,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves)
ListBase curves = {NULL, NULL};
FCurve *fcu, *next;
- while (nu) {
+ for (nu = editnurb->nurbs.first, nu_index = 0; nu != NULL; nu = nu->next, nu_index++) {
if (nu->bezt) {
BezTriple *bezt = nu->bezt;
a = nu->pntsu;
@@ -1126,8 +1130,6 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves)
pt_index++;
}
}
- nu = nu->next;
- nu_index++;
}
/* remove paths for removed control points
@@ -1144,9 +1146,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves)
}
}
- nu_index = 0;
- nu = editnurb->nurbs.first;
- while (nu) {
+ for (nu = editnurb->nurbs.first, nu_index = 0; nu != NULL; nu = nu->next, nu_index++) {
keyIndex = NULL;
if (nu->pntsu) {
if (nu->bezt) keyIndex = getCVKeyIndex(editnurb, &nu->bezt[0]);
@@ -1158,9 +1158,6 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves)
BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d]", keyIndex->nu_index);
fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves);
}
-
- nu_index++;
- nu = nu->next;
}
/* the remainders in orig_curves can be copied back (like follow path) */
@@ -1288,8 +1285,24 @@ void CU_deselect_all(Object *obedit)
ListBase *editnurb = object_editcurve_get(obedit);
if (editnurb) {
- selectend_nurb(obedit, FIRST, 0, DESELECT); /* set first control points as unselected */
- select_adjacent_cp(editnurb, 1, 1, DESELECT); /* cascade selection */
+ Nurb *nu;
+ int a;
+ for (nu = editnurb->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;
+ }
+ }
+ }
}
}
@@ -1298,8 +1311,27 @@ void CU_select_all(Object *obedit)
ListBase *editnurb = object_editcurve_get(obedit);
if (editnurb) {
- selectend_nurb(obedit, FIRST, 0, SELECT); /* set first control points as unselected */
- select_adjacent_cp(editnurb, 1, 1, SELECT); /* cascade selection */
+ Nurb *nu;
+ int a;
+ for (nu = editnurb->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;
+ }
+ }
+ }
}
}
@@ -1369,7 +1401,7 @@ static int separate_exec(bContext *C, wmOperator *op)
/* 1. duplicate the object and data */
newbase = ED_object_add_duplicate(bmain, scene, oldbase, 0); /* 0 = fully linked */
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
ED_base_object_select(newbase, BA_DESELECT);
newob = newbase->object;
@@ -1445,7 +1477,9 @@ static short isNurbselUV(Nurb *nu, int *u, int *v, int flag)
if (*u == -1) *u = b;
else return 0;
}
- else if (sel > 1) return 0; /* because sel == 1 is still ok */
+ else if (sel > 1) {
+ return 0; /* because sel == 1 is still ok */
+ }
}
for (a = 0; a < nu->pntsu; a++) {
@@ -1458,7 +1492,9 @@ static short isNurbselUV(Nurb *nu, int *u, int *v, int flag)
if (*v == -1) *v = a;
else return 0;
}
- else if (sel > 1) return 0;
+ else if (sel > 1) {
+ return 0;
+ }
}
if (*u == -1 && *v > -1) return 1;
@@ -1753,7 +1789,7 @@ static short extrudeflagNurb(EditNurb *editnurb, int flag)
else {
/* which row or column is selected */
- if (isNurbselUV(nu, &u, &v, flag) ) {
+ if (isNurbselUV(nu, &u, &v, flag)) {
/* deselect all */
bp = nu->bp;
@@ -1844,7 +1880,7 @@ static void adduplicateflagNurb(Object *obedit, short flag)
for (a = 0; a < nu->pntsu; a++) {
enda = -1;
starta = a;
- while ( (bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag) ) {
+ while ((bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag)) {
select_beztriple(bezt, DESELECT, flag, HIDDEN);
enda = a;
if (a >= nu->pntsu - 1) break;
@@ -2008,11 +2044,12 @@ static int switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
EditNurb *editnurb = cu->editnurb;
Nurb *nu;
- for (nu = editnurb->nurbs.first; nu; nu = nu->next)
+ for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
if (isNurbsel(nu)) {
BKE_nurb_direction_switch(nu);
keyData_switchDirectionNurb(cu, nu);
}
+ }
if (ED_curve_updateAnimPaths(obedit->data))
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
@@ -2402,12 +2439,12 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short
BezTriple *bezt;
BPoint *bp;
int a;
- short lastsel = 0;
+ short lastsel = false;
if (next == 0) return;
for (nu = editnurb->first; nu; nu = nu->next) {
- lastsel = 0;
+ lastsel = false;
if (nu->type == CU_BEZIER) {
a = nu->pntsu;
bezt = nu->bezt;
@@ -2418,12 +2455,12 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short
bezt += next;
if (!(bezt->f2 & SELECT) || (selstatus == 0)) {
short sel = select_beztriple(bezt, selstatus, 1, VISIBLE);
- if ((sel == 1) && (cont == 0)) lastsel = 1;
+ if ((sel == 1) && (cont == 0)) lastsel = true;
}
}
else {
bezt += next;
- lastsel = 0;
+ lastsel = false;
}
/* move around in zigzag way so that we go through each */
bezt -= (next - next / abs(next));
@@ -2439,12 +2476,12 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short
bp += next;
if (!(bp->f1 & SELECT) || (selstatus == 0)) {
short sel = select_bpoint(bp, selstatus, 1, VISIBLE);
- if ((sel == 1) && (cont == 0)) lastsel = 1;
+ if ((sel == 1) && (cont == 0)) lastsel = true;
}
}
else {
bp += next;
- lastsel = 0;
+ lastsel = false;
}
/* move around in zigzag way so that we go through each */
bp -= (next - next / abs(next));
@@ -2455,10 +2492,11 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short
/**************** 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 */
+/* (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, short selfirst, short doswap, short selstatus)
{
ListBase *editnurb = object_editcurve_get(obedit);
@@ -2532,7 +2570,7 @@ 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 Nurb";
+ ot->description = "(De)select first of visible part of each NURBS";
/* api cfirstbacks */
ot->exec = de_select_first_exec;
@@ -2557,7 +2595,7 @@ 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 Nurb";
+ ot->description = "(De)select last of visible part of each NURBS";
/* api clastbacks */
ot->exec = de_select_last_exec;
@@ -2848,7 +2886,7 @@ static void subdividenurb(Object *obedit, int number_cuts)
keyIndex_updateBezt(editnurb, prevbezt, beztn, 1);
beztn++;
- if (BEZSELECTED_HIDDENHANDLES(cu, prevbezt) && BEZSELECTED_HIDDENHANDLES(cu, bezt) ) {
+ if (BEZSELECTED_HIDDENHANDLES(cu, prevbezt) && BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
float prevvec[3][3];
memcpy(prevvec, prevbezt->vec, sizeof(float) * 9);
@@ -3032,7 +3070,7 @@ static void subdividenurb(Object *obedit, int number_cuts)
bp++;
}
}
- if (sel == (nu->pntsu * nu->pntsv) ) { /* subdivide entire nurb */
+ if (sel == (nu->pntsu * nu->pntsv)) { /* subdivide entire nurb */
/* Global subdivision is a special case of partial
* subdivision. Strange it is considered separately... */
@@ -3302,7 +3340,7 @@ static void findselectedNurbvert(ListBase *editnurb, Nurb **nu, BezTriple **bezt
bezt1 = nu1->bezt;
a = nu1->pntsu;
while (a--) {
- if ( (bezt1->f1 & SELECT) || (bezt1->f2 & SELECT) || (bezt1->f3 & SELECT) ) {
+ if ((bezt1->f1 & SELECT) || (bezt1->f2 & SELECT) || (bezt1->f3 & SELECT)) {
if (*nu != NULL && *nu != nu1) {
*nu = NULL;
*bp = NULL;
@@ -3349,156 +3387,14 @@ static void findselectedNurbvert(ListBase *editnurb, Nurb **nu, BezTriple **bezt
/***************** set spline type operator *******************/
-static int convertspline(short type, Nurb *nu)
-{
- BezTriple *bezt;
- BPoint *bp;
- int a, c, nr;
-
- if (nu->type == CU_POLY) {
- if (type == CU_BEZIER) { /* to Bezier with vecthandles */
- nr = nu->pntsu;
- bezt = (BezTriple *)MEM_callocN(nr * sizeof(BezTriple), "setsplinetype2");
- nu->bezt = bezt;
- a = nr;
- bp = nu->bp;
- while (a--) {
- copy_v3_v3(bezt->vec[1], bp->vec);
- bezt->f1 = bezt->f2 = bezt->f3 = bp->f1;
- bezt->h1 = bezt->h2 = HD_VECT;
- bezt->weight = bp->weight;
- bezt->radius = bp->radius;
- bp++;
- bezt++;
- }
- MEM_freeN(nu->bp);
- nu->bp = NULL;
- nu->pntsu = nr;
- nu->type = CU_BEZIER;
- BKE_nurb_handles_calc(nu);
- }
- else if (type == CU_NURBS) {
- nu->type = CU_NURBS;
- nu->orderu = 4;
- nu->flagu &= CU_NURB_CYCLIC; /* disable all flags except for cyclic */
- BKE_nurb_knot_calc_u(nu);
- a = nu->pntsu * nu->pntsv;
- bp = nu->bp;
- while (a--) {
- bp->vec[3] = 1.0;
- bp++;
- }
- }
- }
- else if (nu->type == CU_BEZIER) { /* Bezier */
- if (type == CU_POLY || type == CU_NURBS) {
- nr = 3 * nu->pntsu;
- nu->bp = MEM_callocN(nr * sizeof(BPoint), "setsplinetype");
- a = nu->pntsu;
- bezt = nu->bezt;
- bp = nu->bp;
- while (a--) {
- if (type == CU_POLY && bezt->h1 == HD_VECT && bezt->h2 == HD_VECT) {
- /* vector handle becomes 1 poly vertice */
- copy_v3_v3(bp->vec, bezt->vec[1]);
- bp->vec[3] = 1.0;
- bp->f1 = bezt->f2;
- nr -= 2;
- bp->radius = bezt->radius;
- bp->weight = bezt->weight;
- bp++;
- }
- else {
- for (c = 0; c < 3; c++) {
- copy_v3_v3(bp->vec, bezt->vec[c]);
- bp->vec[3] = 1.0;
- if (c == 0) bp->f1 = bezt->f1;
- else if (c == 1) bp->f1 = bezt->f2;
- else bp->f1 = bezt->f3;
- bp->radius = bezt->radius;
- bp->weight = bezt->weight;
- bp++;
- }
- }
- bezt++;
- }
- MEM_freeN(nu->bezt);
- nu->bezt = NULL;
- nu->pntsu = nr;
- nu->pntsv = 1;
- nu->orderu = 4;
- nu->orderv = 1;
- nu->type = type;
-
-#if 0 /* UNUSED */
- if (nu->flagu & CU_NURB_CYCLIC) c = nu->orderu - 1;
- else c = 0;
-#endif
-
- if (type == CU_NURBS) {
- nu->flagu &= CU_NURB_CYCLIC; /* disable all flags except for cyclic */
- nu->flagu |= CU_NURB_BEZIER;
- BKE_nurb_knot_calc_u(nu);
- }
- }
- }
- else if (nu->type == CU_NURBS) {
- if (type == CU_POLY) {
- nu->type = CU_POLY;
- if (nu->knotsu) MEM_freeN(nu->knotsu); /* python created nurbs have a knotsu of zero */
- nu->knotsu = NULL;
- if (nu->knotsv) MEM_freeN(nu->knotsv);
- nu->knotsv = NULL;
- }
- else if (type == CU_BEZIER) { /* to Bezier */
- nr = nu->pntsu / 3;
-
- if (nr < 2) {
- return 1; /* conversion impossible */
- }
- else {
- bezt = MEM_callocN(nr * sizeof(BezTriple), "setsplinetype2");
- nu->bezt = bezt;
- a = nr;
- bp = nu->bp;
- while (a--) {
- copy_v3_v3(bezt->vec[0], bp->vec);
- bezt->f1 = bp->f1;
- bp++;
- copy_v3_v3(bezt->vec[1], bp->vec);
- bezt->f2 = bp->f1;
- bp++;
- copy_v3_v3(bezt->vec[2], bp->vec);
- bezt->f3 = bp->f1;
- bezt->radius = bp->radius;
- bezt->weight = bp->weight;
- bp++;
- bezt++;
- }
- MEM_freeN(nu->bp);
- nu->bp = NULL;
- MEM_freeN(nu->knotsu);
- nu->knotsu = NULL;
- nu->pntsu = nr;
- nu->type = CU_BEZIER;
- }
- }
- }
-
- return 0;
-}
-
-void ED_nurb_set_spline_type(Nurb *nu, int type)
-{
- convertspline(type, nu);
-}
-
static int set_spline_type_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
ListBase *editnurb = object_editcurve_get(obedit);
Nurb *nu;
- int changed = 0, type = RNA_enum_get(op->ptr, "type");
+ bool change = false;
+ const bool use_handles = RNA_boolean_get(op->ptr, "use_handles");
+ const int type = RNA_enum_get(op->ptr, "type");
if (type == CU_CARDINAL || type == CU_BSPLINE) {
BKE_report(op->reports, RPT_ERROR, "Not yet implemented");
@@ -3507,14 +3403,14 @@ static int set_spline_type_exec(bContext *C, wmOperator *op)
for (nu = editnurb->first; nu; nu = nu->next) {
if (isNurbsel(nu)) {
- if (convertspline(type, nu))
+ if (BKE_nurb_type_convert(nu, type, use_handles) == false)
BKE_report(op->reports, RPT_ERROR, "No conversion possible");
else
- changed = 1;
+ change = true;
}
}
- if (changed) {
+ if (change) {
if (ED_curve_updateAnimPaths(obedit->data))
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
@@ -3554,6 +3450,7 @@ void CURVE_OT_spline_type_set(wmOperatorType *ot)
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", type_items, CU_POLY, "Type", "Spline type");
+ RNA_def_boolean(ot->srna, "use_handles", 0, "Handles", "Use handles when converting bezier curves into polygons");
}
/***************** set handle type operator *******************/
@@ -3773,7 +3670,7 @@ static void merge_2_nurb(wmOperator *op, ListBase *editnurb, Nurb *nu1, Nurb *nu
/* first nurbs: u = resolu-1 selected */
- if (is_u_selected(nu1, nu1->pntsu - 1) ) {
+ if (is_u_selected(nu1, nu1->pntsu - 1)) {
/* pass */
}
else {
@@ -3805,7 +3702,7 @@ static void merge_2_nurb(wmOperator *op, ListBase *editnurb, Nurb *nu1, Nurb *nu
}
/* 2nd nurbs: u = 0 selected */
- if (is_u_selected(nu2, 0) ) {
+ if (is_u_selected(nu2, 0)) {
/* pass */
}
else {
@@ -4011,9 +3908,11 @@ static int make_segment_exec(bContext *C, wmOperator *op)
if ((nu->flagu & CU_NURB_CYCLIC) == 0) { /* not cyclic */
if (nu->type == CU_BEZIER) {
if (nu1 == NULL) {
- if (BEZSELECTED_HIDDENHANDLES(cu, nu->bezt) ) nu1 = nu;
+ if (BEZSELECTED_HIDDENHANDLES(cu, nu->bezt)) {
+ nu1 = nu;
+ }
else {
- if (BEZSELECTED_HIDDENHANDLES(cu, &(nu->bezt[nu->pntsu - 1])) ) {
+ if (BEZSELECTED_HIDDENHANDLES(cu, &(nu->bezt[nu->pntsu - 1]))) {
nu1 = nu;
BKE_nurb_direction_switch(nu);
keyData_switchDirectionNurb(cu, nu);
@@ -4021,23 +3920,27 @@ static int make_segment_exec(bContext *C, wmOperator *op)
}
}
else if (nu2 == NULL) {
- if (BEZSELECTED_HIDDENHANDLES(cu, nu->bezt) ) {
+ if (BEZSELECTED_HIDDENHANDLES(cu, nu->bezt)) {
nu2 = nu;
BKE_nurb_direction_switch(nu);
keyData_switchDirectionNurb(cu, nu);
}
else {
- if (BEZSELECTED_HIDDENHANDLES(cu, &(nu->bezt[nu->pntsu - 1])) ) {
+ if (BEZSELECTED_HIDDENHANDLES(cu, &(nu->bezt[nu->pntsu - 1]))) {
nu2 = nu;
}
}
}
- else break;
+ else {
+ break;
+ }
}
else if (nu->pntsv == 1) {
bp = nu->bp;
if (nu1 == NULL) {
- if (bp->f1 & SELECT) nu1 = nu;
+ if (bp->f1 & SELECT) {
+ nu1 = nu;
+ }
else {
bp = bp + (nu->pntsu - 1);
if (bp->f1 & SELECT) {
@@ -4060,7 +3963,9 @@ static int make_segment_exec(bContext *C, wmOperator *op)
}
}
}
- else break;
+ else {
+ break;
+ }
}
}
}
@@ -4155,7 +4060,7 @@ void CURVE_OT_make_segment(wmOperatorType *ot)
/***************** pick select from 3d view **********************/
-int mouse_nurb(bContext *C, const int mval[2], int extend, int deselect, int toggle)
+bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
{
Object *obedit = CTX_data_edit_object(C);
Curve *cu = obedit->data;
@@ -4268,10 +4173,10 @@ int mouse_nurb(bContext *C, const int mval[2], int extend, int deselect, int tog
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/******************** spin operator ***********************/
@@ -4391,7 +4296,7 @@ static int spin_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int spin_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int spin_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -4465,7 +4370,9 @@ static int addvert_Nurb(bContext *C, short mode, float location[3])
newnu->resolu = cu->resolu;
newnu->flag |= CU_SMOOTH;
}
- else memcpy(newnu, nu, sizeof(Nurb));
+ else {
+ memcpy(newnu, nu, sizeof(Nurb));
+ }
BLI_addtail(&editnurb->nurbs, newnu);
set_actNurb(obedit, newnu);
@@ -4579,7 +4486,9 @@ static int addvert_Nurb(bContext *C, short mode, float location[3])
bezt = newbezt;
ok = 1;
}
- else bezt = NULL;
+ else {
+ bezt = NULL;
+ }
if (bezt) {
if (!newnu) nu->pntsu++;
@@ -4657,7 +4566,9 @@ static int addvert_Nurb(bContext *C, short mode, float location[3])
bp = newbp;
ok = 1;
}
- else bp = NULL;
+ else {
+ bp = NULL;
+ }
if (bp) {
if (mode == 'e') {
@@ -4675,7 +4586,9 @@ static int addvert_Nurb(bContext *C, short mode, float location[3])
nu->pntsu++;
BKE_nurb_knot_calc_u(nu);
}
- else BKE_nurb_knot_calc_u(newnu);
+ else {
+ BKE_nurb_knot_calc_u(newnu);
+ }
}
}
@@ -4702,7 +4615,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op)
return addvert_Nurb(C, 0, location);
}
-static int add_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
@@ -4731,7 +4644,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event)
copy_v3_v3(location, give_cursor(vc.scene, vc.v3d));
}
- view3d_get_view_aligned_coordinate(&vc, location, event->mval, TRUE);
+ view3d_get_view_aligned_coordinate(vc.ar, location, event->mval, true);
RNA_float_set_array(op->ptr, "location", location);
}
@@ -4834,7 +4747,7 @@ static int toggle_cyclic_exec(bContext *C, wmOperator *op)
a = nu->pntsu;
bezt = nu->bezt;
while (a--) {
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt) ) {
+ if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
nu->flagu ^= CU_NURB_CYCLIC;
break;
}
@@ -4885,7 +4798,7 @@ static int toggle_cyclic_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int toggle_cyclic_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int toggle_cyclic_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Object *obedit = CTX_data_edit_object(C);
ListBase *editnurb = object_editcurve_get(obedit);
@@ -4897,7 +4810,7 @@ static int toggle_cyclic_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(eve
for (nu = editnurb->first; nu; nu = nu->next) {
if (nu->pntsu > 1 || nu->pntsv > 1) {
if (nu->type == CU_NURBS) {
- pup = uiPupMenuBegin(C, "Direction", ICON_NONE);
+ pup = uiPupMenuBegin(C, IFACE_("Direction"), ICON_NONE);
layout = uiPupMenuLayout(pup);
uiItemsEnumO(layout, op->type->idname, "direction");
uiPupMenuEnd(C, pup);
@@ -4953,7 +4866,7 @@ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op))
bezt = nu->bezt;
a = nu->pntsu;
while (a--) {
- if ( (bezt->f1 & SELECT) || (bezt->f2 & SELECT) || (bezt->f3 & SELECT) ) {
+ if ((bezt->f1 & SELECT) || (bezt->f2 & SELECT) || (bezt->f3 & SELECT)) {
a = nu->pntsu;
bezt = nu->bezt;
while (a--) {
@@ -4988,7 +4901,7 @@ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-static int select_linked_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
return select_linked_exec(C, op);
}
@@ -5014,7 +4927,7 @@ void CURVE_OT_select_linked(wmOperatorType *ot)
/***************** select linked pick operator ******************/
-static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Object *obedit = CTX_data_edit_object(C);
ViewContext vc;
@@ -5303,7 +5216,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
BPoint *bp;
BezTriple *bezt;
int a;
- short sel = 0, lastsel = 0;
+ short sel = 0, lastsel = false;
short *selbpoints;
if (obedit->type == OB_SURF) {
@@ -5314,44 +5227,54 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
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++;
+ if ((a + 1) % nu->pntsu == 0) {
+ sel++;
+ }
else {
bp--;
if ((selbpoints[a + 1] == 1) || ((bp->hide == 0) && (bp->f1 & SELECT))) sel++;
bp++;
}
- if ((a + 1) % nu->pntsu == 1) sel++;
+ 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++;
+ if (a + 1 > nu->pntsu * nu->pntsv - nu->pntsu) {
+ sel++;
+ }
else {
bp -= nu->pntsu;
if ((selbpoints[a + nu->pntsu] == 1) || ((bp->hide == 0) && (bp->f1 & SELECT))) sel++;
bp += nu->pntsu;
}
-
- if (a < nu->pntsu) sel++;
+
+ 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, 1, VISIBLE);
selbpoints[a] = 1;
}
}
- else lastsel = 0;
-
+ else {
+ lastsel = false;
+ }
+
bp++;
}
@@ -5360,26 +5283,29 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
}
else {
for (nu = editnurb->first; nu; nu = nu->next) {
- lastsel = 0;
+ 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)) {
- if (lastsel == 1) sel = 1;
- else sel = 0;
-
+ sel = (lastsel == 1);
+
/* check if neighbors have been selected */
/* first and last are exceptions */
- if (a == nu->pntsu - 1) sel++;
+ if (a == nu->pntsu - 1) {
+ sel++;
+ }
else {
bezt--;
if ((bezt->hide == 0) && (bezt->f2 & SELECT)) sel++;
bezt++;
}
- if (a == 0) sel++;
+ if (a == 0) {
+ sel++;
+ }
else {
bezt++;
if ((bezt->hide == 0) && (bezt->f2 & SELECT)) sel++;
@@ -5388,12 +5314,16 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
if (sel != 2) {
select_beztriple(bezt, DESELECT, 1, VISIBLE);
- lastsel = 1;
+ lastsel = true;
+ }
+ else {
+ lastsel = false;
}
- else lastsel = 0;
}
- else lastsel = 0;
-
+ else {
+ lastsel = false;
+ }
+
bezt++;
}
}
@@ -5406,28 +5336,36 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
else sel = 0;
/* first and last are exceptions */
- if (a == nu->pntsu * nu->pntsv - 1) sel++;
+ if (a == nu->pntsu * nu->pntsv - 1) {
+ sel++;
+ }
else {
bp--;
if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
bp++;
}
- if (a == 0) sel++;
+ if (a == 0) {
+ sel++;
+ }
else {
bp++;
if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
bp--;
}
-
+
if (sel != 2) {
select_bpoint(bp, DESELECT, 1, VISIBLE);
- lastsel = 1;
+ lastsel = true;
+ }
+ else {
+ lastsel = false;
}
- else lastsel = 0;
}
- else lastsel = 0;
-
+ else {
+ lastsel = false;
+ }
+
bp++;
}
}
@@ -5519,7 +5457,7 @@ void CURVE_OT_select_random(wmOperatorType *ot)
/* 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_boolean(ot->srna, "extend", FALSE, "Extend Selection", "Extend selection instead of deselecting everything first");
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
/********************* every nth number of point *******************/
@@ -5790,7 +5728,7 @@ static int delete_exec(bContext *C, wmOperator *op)
int delta = 0;
bezt = nu->bezt;
for (a = 0; a < nu->pntsu; a++) {
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt) ) {
+ if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
memmove(bezt, bezt + 1, (nu->pntsu - a - 1) * sizeof(BezTriple));
keyIndex_delBezt(editnurb, bezt + delta);
keyIndex_updateBezt(editnurb, bezt + 1, bezt, nu->pntsu - a - 1);
@@ -5799,7 +5737,9 @@ static int delete_exec(bContext *C, wmOperator *op)
type = 1;
delta++;
}
- else bezt++;
+ else {
+ bezt++;
+ }
}
if (type) {
bezt1 = (BezTriple *)MEM_mallocN((nu->pntsu) * sizeof(BezTriple), "delNurb");
@@ -5859,16 +5799,16 @@ static int delete_exec(bContext *C, wmOperator *op)
if (nu->type == CU_BEZIER) {
bezt = nu->bezt;
for (a = 0; a < nu->pntsu - 1; a++) {
- if (BEZSELECTED_HIDDENHANDLES(cu, bezt) ) {
+ if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
bezt1 = bezt;
bezt2 = bezt + 1;
if ((bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT)) {
/* pass */
}
else { /* maybe do not make cyclic */
- if (a == 0 && (nu->flagu & CU_NURB_CYCLIC) ) {
+ if (a == 0 && (nu->flagu & CU_NURB_CYCLIC)) {
bezt2 = bezt + (nu->pntsu - 1);
- if ( (bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT) ) {
+ if ((bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT)) {
nu->flagu &= ~CU_NURB_CYCLIC;
BKE_nurb_handles_calc(nu);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
@@ -5895,7 +5835,7 @@ static int delete_exec(bContext *C, wmOperator *op)
/* pass */
}
else { /* maybe do not make cyclic */
- if (a == 0 && (nu->flagu & CU_NURB_CYCLIC) ) {
+ if (a == 0 && (nu->flagu & CU_NURB_CYCLIC)) {
bp2 = bp + (nu->pntsu - 1);
if (bp2->f1 & SELECT) {
nu->flagu &= ~CU_NURB_CYCLIC;
@@ -6016,21 +5956,21 @@ static int delete_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int delete_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int delete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Object *obedit = CTX_data_edit_object(C);
uiPopupMenu *pup;
uiLayout *layout;
if (obedit->type == OB_SURF) {
- pup = uiPupMenuBegin(C, "Delete", ICON_NONE);
+ pup = uiPupMenuBegin(C, IFACE_("Delete"), ICON_NONE);
layout = uiPupMenuLayout(pup);
uiItemEnumO_ptr(layout, op->type, NULL, 0, "type", 0);
uiItemEnumO_ptr(layout, op->type, NULL, 0, "type", 2);
uiPupMenuEnd(C, pup);
}
else {
- pup = uiPupMenuBegin(C, "Delete", ICON_NONE);
+ pup = uiPupMenuBegin(C, IFACE_("Delete"), ICON_NONE);
layout = uiPupMenuLayout(pup);
uiItemsEnumO(layout, op->type->idname, "type");
uiPupMenuEnd(C, pup);
@@ -6157,10 +6097,12 @@ int join_curve_exec(bContext *C, wmOperator *UNUSED(op))
if (ob->totcol) { /* TODO, merge material lists */
CLAMP(newnu->mat_nr, 0, ob->totcol - 1);
}
- else newnu->mat_nr = 0;
+ else {
+ newnu->mat_nr = 0;
+ }
BLI_addtail(&tempbase, newnu);
- if ( (bezt = newnu->bezt) ) {
+ if ((bezt = newnu->bezt)) {
a = newnu->pntsu;
while (a--) {
mul_m4_v3(cmat, bezt->vec[0]);
@@ -6170,7 +6112,7 @@ int join_curve_exec(bContext *C, wmOperator *UNUSED(op))
}
BKE_nurb_handles_calc(newnu);
}
- if ( (bp = newnu->bp) ) {
+ if ((bp = newnu->bp)) {
a = newnu->pntsu * nu->pntsv;
while (a--) {
mul_m4_v3(cmat, bp->vec);
@@ -6190,10 +6132,10 @@ int join_curve_exec(bContext *C, wmOperator *UNUSED(op))
cu = ob->data;
BLI_movelisttolist(&cu->nurb, &tempbase);
- DAG_scene_sort(bmain, scene); // because we removed object(s), call before editmode!
+ DAG_relations_tag_update(bmain); // because we removed object(s), call before editmode!
- ED_object_enter_editmode(C, EM_WAITCURSOR);
- ED_object_exit_editmode(C, EM_FREEDATA | EM_WAITCURSOR | EM_DO_UNDO);
+ ED_object_editmode_enter(C, EM_WAITCURSOR);
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR | EM_DO_UNDO);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
@@ -6208,20 +6150,20 @@ static const char *get_curve_defname(int type)
if ((type & CU_TYPE) == CU_BEZIER) {
switch (stype) {
- case CU_PRIM_CURVE: return "BezierCurve";
- case CU_PRIM_CIRCLE: return "BezierCircle";
- case CU_PRIM_PATH: return "CurvePath";
+ case CU_PRIM_CURVE: return DATA_("BezierCurve");
+ case CU_PRIM_CIRCLE: return DATA_("BezierCircle");
+ case CU_PRIM_PATH: return DATA_("CurvePath");
default:
- return "Curve";
+ return DATA_("Curve");
}
}
else {
switch (stype) {
- case CU_PRIM_CURVE: return "NurbsCurve";
- case CU_PRIM_CIRCLE: return "NurbsCircle";
- case CU_PRIM_PATH: return "NurbsPath";
+ case CU_PRIM_CURVE: return DATA_("NurbsCurve");
+ case CU_PRIM_CIRCLE: return DATA_("NurbsCircle");
+ case CU_PRIM_PATH: return DATA_("NurbsPath");
default:
- return "Curve";
+ return DATA_("Curve");
}
}
}
@@ -6231,13 +6173,13 @@ static const char *get_surf_defname(int type)
int stype = type & CU_PRIMITIVE;
switch (stype) {
- case CU_PRIM_CURVE: return "SurfCurve";
- case CU_PRIM_CIRCLE: return "SurfCircle";
- case CU_PRIM_PATCH: return "SurfPatch";
- case CU_PRIM_SPHERE: return "SurfSphere";
- case CU_PRIM_DONUT: return "SurfTorus";
+ case CU_PRIM_CURVE: return DATA_("SurfCurve");
+ case CU_PRIM_CIRCLE: return DATA_("SurfCircle");
+ case CU_PRIM_PATCH: return DATA_("SurfPatch");
+ case CU_PRIM_SPHERE: return DATA_("SurfSphere");
+ case CU_PRIM_DONUT: return DATA_("SurfTorus");
default:
- return "Surface";
+ return DATA_("Surface");
}
}
@@ -6623,14 +6565,18 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
if (type & CU_PRIM_PATH)
cu->flag |= CU_PATH | CU_3D;
}
- else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ else {
+ DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ }
}
else { /* adding surface */
if (obedit == NULL || obedit->type != OB_SURF) {
obedit = ED_object_add_type(C, OB_SURF, loc, rot, TRUE, layer);
newob = 1;
}
- else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ else {
+ DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ }
}
/* rename here, the undo stack checks name for valid undo pushes */
@@ -6657,7 +6603,7 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
/* userdef */
if (newob && !enter_editmode) {
- ED_object_exit_editmode(C, EM_FREEDATA);
+ ED_object_editmode_exit(C, EM_FREEDATA);
}
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 257dfca051f..63444c5c17e 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -405,7 +405,7 @@ static int paste_file_exec(bContext *C, wmOperator *op)
return retval;
}
-static int paste_file_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int paste_file_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (RNA_struct_property_is_set(op->ptr, "filepath"))
return paste_file_exec(C, op);
@@ -1070,21 +1070,13 @@ void FONT_OT_change_character(wmOperatorType *ot)
/******************* line break operator ********************/
-static int line_break_exec(bContext *C, wmOperator *op)
+static int line_break_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
- const int ctrl = RNA_boolean_get(op->ptr, "ctrl");
- if (ctrl) {
- insert_into_textbuf(obedit, 1);
- if (ef->textbuf[cu->pos] != '\n')
- insert_into_textbuf(obedit, '\n');
- }
- else
- insert_into_textbuf(obedit, '\n');
+ insert_into_textbuf(obedit, '\n');
cu->selstart = cu->selend = 0;
@@ -1106,9 +1098,6 @@ void FONT_OT_line_break(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "ctrl", 0, "Ctrl", ""); // XXX what is this?
}
/******************* delete operator **********************/
@@ -1232,16 +1221,16 @@ static int insert_text_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int insert_text_invoke(bContext *C, wmOperator *op, wmEvent *evt)
+static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
Curve *cu = obedit->data;
EditFont *ef = cu->editfont;
static int accentcode = 0;
- uintptr_t ascii = evt->ascii;
- int alt = evt->alt, shift = evt->shift, ctrl = evt->ctrl;
- int event = evt->type, val = evt->val;
+ uintptr_t ascii = event->ascii;
+ int alt = event->alt, shift = event->shift, ctrl = event->ctrl;
+ int event_type = event->type, event_val = event->val;
wchar_t inserted_text[2] = {0};
if (RNA_struct_property_is_set(op->ptr, "text"))
@@ -1254,26 +1243,26 @@ static int insert_text_invoke(bContext *C, wmOperator *op, wmEvent *evt)
}
/* tab should exit editmode, but we allow it to be typed using modifier keys */
- if (event == TABKEY) {
+ if (event_type == TABKEY) {
if ((alt || ctrl || shift) == 0)
return OPERATOR_PASS_THROUGH;
else
ascii = 9;
}
- if (event == BACKSPACEKEY) {
+ if (event_type == BACKSPACEKEY) {
if (alt && cu->len != 0 && cu->pos > 0)
accentcode = 1;
return OPERATOR_PASS_THROUGH;
}
- if (val && (ascii || evt->utf8_buf[0])) {
+ if (event_val && (ascii || event->utf8_buf[0])) {
/* handle case like TAB (== 9) */
if ( (ascii > 31 && ascii < 254 && ascii != 127) ||
(ascii == 13) ||
(ascii == 10) ||
(ascii == 8) ||
- (evt->utf8_buf[0]))
+ (event->utf8_buf[0]))
{
if (accentcode) {
@@ -1283,8 +1272,8 @@ static int insert_text_invoke(bContext *C, wmOperator *op, wmEvent *evt)
}
accentcode = 0;
}
- else if (evt->utf8_buf[0]) {
- BLI_strncpy_wchar_from_utf8(inserted_text, evt->utf8_buf, 1);
+ else if (event->utf8_buf[0]) {
+ BLI_strncpy_wchar_from_utf8(inserted_text, event->utf8_buf, 1);
ascii = inserted_text[0];
insert_into_textbuf(obedit, ascii);
accentcode = 0;
@@ -1318,7 +1307,7 @@ static int insert_text_invoke(bContext *C, wmOperator *op, wmEvent *evt)
}
/* reset property? */
- if (val == 0)
+ if (event_val == 0)
accentcode = 0;
return OPERATOR_FINISHED;
@@ -1654,7 +1643,7 @@ static int font_open_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int open_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
VFont *vfont = NULL;
char *path;
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index ec20e2d3d09..8d108644470 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -43,10 +43,12 @@ if(WITH_BLENDER)
# blends
data_to_c_simple(../../../../release/datafiles/preview.blend SRC)
+ data_to_c_simple(../../../../release/datafiles/preview_cycles.blend SRC)
# images
data_to_c_simple(../../../../release/datafiles/splash.png SRC)
- data_to_c_simple(../../../../release/datafiles/blender_icons.png SRC)
+ data_to_c_simple(../../../../release/datafiles/blender_icons16.png SRC)
+ data_to_c_simple(../../../../release/datafiles/blender_icons32.png SRC)
data_to_c_simple(../../../../release/datafiles/prvicons.png SRC)
# brushes
@@ -80,6 +82,33 @@ if(WITH_BLENDER)
data_to_c_simple(../../../../release/datafiles/brushicons/thumb.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/twist.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/vertexdraw.png SRC)
+
+ # matcap
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc01.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc02.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc03.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc04.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc05.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc06.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc07.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc08.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc09.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc10.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc11.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc12.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc13.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc14.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc15.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc16.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc17.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc18.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc19.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc20.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc21.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc22.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc23.jpg SRC)
+ data_to_c_simple(../../../../release/datafiles/matcaps/mc24.jpg SRC)
+
endif()
data_to_c_simple(../../../../release/datafiles/startup.blend SRC)
diff --git a/source/blender/editors/datafiles/SConscript b/source/blender/editors/datafiles/SConscript
index e0816f783d3..d4e6ed4aff8 100644
--- a/source/blender/editors/datafiles/SConscript
+++ b/source/blender/editors/datafiles/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
# all source generated now
@@ -9,47 +35,75 @@ incs = ""
# generated data files
import os
sources.extend((
- os.path.join(env['DATA_SOURCES'], "bfont.pfb.c"),
- os.path.join(env['DATA_SOURCES'], "bfont.ttf.c"),
- os.path.join(env['DATA_SOURCES'], "bmonofont.ttf.c"),
-
- os.path.join(env['DATA_SOURCES'], "splash.png.c"),
- os.path.join(env['DATA_SOURCES'], "blender_icons.png.c"),
- os.path.join(env['DATA_SOURCES'], "prvicons.png.c"),
-
- os.path.join(env['DATA_SOURCES'], "startup.blend.c"),
- os.path.join(env['DATA_SOURCES'], "preview.blend.c"),
-
- os.path.join(env['DATA_SOURCES'], "add.png.c"),
- os.path.join(env['DATA_SOURCES'], "blob.png.c"),
- os.path.join(env['DATA_SOURCES'], "blur.png.c"),
- os.path.join(env['DATA_SOURCES'], "clay.png.c"),
- os.path.join(env['DATA_SOURCES'], "claystrips.png.c"),
- os.path.join(env['DATA_SOURCES'], "clone.png.c"),
- os.path.join(env['DATA_SOURCES'], "crease.png.c"),
- os.path.join(env['DATA_SOURCES'], "darken.png.c"),
- os.path.join(env['DATA_SOURCES'], "draw.png.c"),
- os.path.join(env['DATA_SOURCES'], "fill.png.c"),
- os.path.join(env['DATA_SOURCES'], "flatten.png.c"),
- os.path.join(env['DATA_SOURCES'], "grab.png.c"),
- os.path.join(env['DATA_SOURCES'], "inflate.png.c"),
- os.path.join(env['DATA_SOURCES'], "layer.png.c"),
- os.path.join(env['DATA_SOURCES'], "lighten.png.c"),
- os.path.join(env['DATA_SOURCES'], "mask.png.c"),
- os.path.join(env['DATA_SOURCES'], "mix.png.c"),
- os.path.join(env['DATA_SOURCES'], "multiply.png.c"),
- os.path.join(env['DATA_SOURCES'], "nudge.png.c"),
- os.path.join(env['DATA_SOURCES'], "pinch.png.c"),
- os.path.join(env['DATA_SOURCES'], "scrape.png.c"),
- os.path.join(env['DATA_SOURCES'], "smear.png.c"),
- os.path.join(env['DATA_SOURCES'], "smooth.png.c"),
- os.path.join(env['DATA_SOURCES'], "snake_hook.png.c"),
- os.path.join(env['DATA_SOURCES'], "soften.png.c"),
- os.path.join(env['DATA_SOURCES'], "subtract.png.c"),
- os.path.join(env['DATA_SOURCES'], "texdraw.png.c"),
- os.path.join(env['DATA_SOURCES'], "thumb.png.c"),
- os.path.join(env['DATA_SOURCES'], "twist.png.c"),
- os.path.join(env['DATA_SOURCES'], "vertexdraw.png.c"),
- ))
+ os.path.join(env['DATA_SOURCES'], "bfont.pfb.c"),
+ os.path.join(env['DATA_SOURCES'], "bfont.ttf.c"),
+ os.path.join(env['DATA_SOURCES'], "bmonofont.ttf.c"),
+
+ os.path.join(env['DATA_SOURCES'], "splash.png.c"),
+ os.path.join(env['DATA_SOURCES'], "blender_icons16.png.c"),
+ os.path.join(env['DATA_SOURCES'], "blender_icons32.png.c"),
+ os.path.join(env['DATA_SOURCES'], "prvicons.png.c"),
+
+ os.path.join(env['DATA_SOURCES'], "startup.blend.c"),
+ os.path.join(env['DATA_SOURCES'], "preview.blend.c"),
+ os.path.join(env['DATA_SOURCES'], "preview_cycles.blend.c"),
+
+ os.path.join(env['DATA_SOURCES'], "add.png.c"),
+ os.path.join(env['DATA_SOURCES'], "blob.png.c"),
+ os.path.join(env['DATA_SOURCES'], "blur.png.c"),
+ os.path.join(env['DATA_SOURCES'], "clay.png.c"),
+ os.path.join(env['DATA_SOURCES'], "claystrips.png.c"),
+ os.path.join(env['DATA_SOURCES'], "clone.png.c"),
+ os.path.join(env['DATA_SOURCES'], "crease.png.c"),
+ os.path.join(env['DATA_SOURCES'], "darken.png.c"),
+ os.path.join(env['DATA_SOURCES'], "draw.png.c"),
+ os.path.join(env['DATA_SOURCES'], "fill.png.c"),
+ os.path.join(env['DATA_SOURCES'], "flatten.png.c"),
+ os.path.join(env['DATA_SOURCES'], "grab.png.c"),
+ os.path.join(env['DATA_SOURCES'], "inflate.png.c"),
+ os.path.join(env['DATA_SOURCES'], "layer.png.c"),
+ os.path.join(env['DATA_SOURCES'], "lighten.png.c"),
+ os.path.join(env['DATA_SOURCES'], "mask.png.c"),
+ os.path.join(env['DATA_SOURCES'], "mix.png.c"),
+ os.path.join(env['DATA_SOURCES'], "multiply.png.c"),
+ os.path.join(env['DATA_SOURCES'], "nudge.png.c"),
+ os.path.join(env['DATA_SOURCES'], "pinch.png.c"),
+ os.path.join(env['DATA_SOURCES'], "scrape.png.c"),
+ os.path.join(env['DATA_SOURCES'], "smear.png.c"),
+ os.path.join(env['DATA_SOURCES'], "smooth.png.c"),
+ os.path.join(env['DATA_SOURCES'], "snake_hook.png.c"),
+ os.path.join(env['DATA_SOURCES'], "soften.png.c"),
+ os.path.join(env['DATA_SOURCES'], "subtract.png.c"),
+ os.path.join(env['DATA_SOURCES'], "texdraw.png.c"),
+ os.path.join(env['DATA_SOURCES'], "thumb.png.c"),
+ os.path.join(env['DATA_SOURCES'], "twist.png.c"),
+ os.path.join(env['DATA_SOURCES'], "vertexdraw.png.c"),
+
+ os.path.join(env['DATA_SOURCES'], "mc01.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc02.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc03.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc04.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc05.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc06.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc07.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc08.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc09.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc10.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc11.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc12.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc13.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc14.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc15.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc16.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc17.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc18.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc19.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc20.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc21.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc22.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc23.jpg.c"),
+ os.path.join(env['DATA_SOURCES'], "mc24.jpg.c"),
+
+ ))
env.BlenderLib ( 'bf_editor_datafiles', sources, Split(incs), [], libtype=['core', 'player'], priority=[235, 30] )
diff --git a/source/blender/editors/gpencil/SConscript b/source/blender/editors/gpencil/SConscript
index 9d92a238eb7..f72e124e862 100644
--- a/source/blender/editors/gpencil/SConscript
+++ b/source/blender/editors/gpencil/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 11e07584405..59850aff72f 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -27,7 +27,6 @@
* \ingroup edgpencil
*/
-
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -45,8 +44,10 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
#include "DNA_view3d_types.h"
+#include "BKE_blender.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
@@ -756,7 +757,7 @@ void draw_gpencil_view2d(const bContext *C, short onlyv2d)
/* 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 draw_gpencil_view3d(Scene *scene, View3D *v3d, ARegion *ar, short only3d)
+void draw_gpencil_view3d(Scene *scene, View3D *v3d, ARegion *ar, bool only3d)
{
bGPdata *gpd;
int dflag = 0;
diff --git a/source/blender/editors/gpencil/gpencil_buttons.c b/source/blender/editors/gpencil/gpencil_buttons.c
index 8a3c996a481..e7033ef0147 100644
--- a/source/blender/editors/gpencil/gpencil_buttons.c
+++ b/source/blender/editors/gpencil/gpencil_buttons.c
@@ -86,6 +86,29 @@ static void gp_ui_dellayer_cb(bContext *C, void *gpd, void *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 ------- */
@@ -174,6 +197,22 @@ static void gp_drawui_layer(uiLayout *layout, bGPdata *gpd, bGPDlayer *gpl, cons
/* 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 ............................... */
@@ -312,6 +351,13 @@ static void draw_gpencil_panel(bContext *C, uiLayout *layout, bGPdata *gpd, Poin
}
}
+void 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 gpencil_panel_standard(const bContext *C, Panel *pa)
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index e9ca7392752..e4c7a1edbcb 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -63,6 +63,7 @@
#include "BKE_library.h"
#include "BKE_object.h"
#include "BKE_report.h"
+#include "BKE_scene.h"
#include "BKE_tracking.h"
#include "UI_interface.h"
@@ -393,6 +394,7 @@ void GPENCIL_OT_active_frame_delete(wmOperatorType *ot)
enum {
GP_STROKECONVERT_PATH = 1,
GP_STROKECONVERT_CURVE,
+ GP_STROKECONVERT_POLY,
};
/* Defines for possible timing modes */
@@ -407,6 +409,7 @@ enum {
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}
};
@@ -451,7 +454,7 @@ static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoin
copy_v3_v3(p3d, &pt->x);
}
else {
- float *fp = give_cursor(scene, v3d);
+ const float *fp = give_cursor(scene, v3d);
float mvalf[2];
/* get screen coordinate */
@@ -1278,13 +1281,14 @@ static void gp_stroke_norm_curve_weights(Curve *cu, float minmax_weights[2])
static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bGPDlayer *gpl, int mode,
int norm_weights, float rad_fac, int link_strokes, tGpTimingData *gtd)
{
+ struct Main *bmain = CTX_data_main(C);
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 = BASACT, *newbase = NULL;
+ Base *base_orig = BASACT, *base_new = NULL;
float minmax_weights[2] = {1.0f, 0.0f};
/* camera framing */
@@ -1306,16 +1310,12 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
/* 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(scene, OB_CURVE);
- zero_v3(ob->loc);
- zero_v3(ob->rot);
- cu = ob->data;
+ 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;
- /* rename object and curve to layer name */
- rename_id((ID *)ob, gpl->info);
- rename_id((ID *)cu, gpl->info);
-
gtd->inittime = ((bGPDstroke *)gpf->strokes.first)->inittime;
/* add points to curve */
@@ -1344,6 +1344,7 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, 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, gtd);
break;
default:
@@ -1364,19 +1365,15 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
/* Create the path animation, if needed */
gp_stroke_path_animation(C, reports, cu, gtd);
- /* Reset original object as active, else we can't edit operator's settings!!! */
- /* set layers OK */
- newbase = BASACT;
- if (base) {
- newbase->lay = base->lay;
- ob->lay = newbase->lay;
- }
-
- /* restore, BKE_object_add sets active */
- BASACT = base;
- if (base) {
- base->flag |= SELECT;
+ 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 : scene->lay;
+ base_new->flag = ob->flag = base_new->flag | SELECT;
}
/* --- */
@@ -1387,12 +1384,15 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
static int gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0);
- bGPDstroke *gps = gpf->strokes.first;
+ bGPDframe *gpf = NULL;
+ bGPDstroke *gps = NULL;
bGPDspoint *pt;
double base_time, cur_time, prev_time = -1.0;
int i, 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) {
@@ -1438,11 +1438,19 @@ static void gp_convert_set_end_frame(struct Main *UNUSED(main), struct Scene *UN
static int gp_convert_poll(bContext *C)
{
bGPdata *gpd = 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 there's valid data, and the current view is 3D View */
- return ((sa && sa->spacetype == SPACE_VIEW3D) && gpencil_layer_getactive(gpd) && (scene->obedit == NULL));
+ /* 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)
@@ -1515,7 +1523,7 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
+static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
{
const char *prop_id = RNA_property_identifier(prop);
int link_strokes = RNA_boolean_get(ptr, "use_link_strokes");
@@ -1531,7 +1539,7 @@ static int gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
strcmp(prop_id, "radius_multiplier") == 0 ||
strcmp(prop_id, "use_link_strokes") == 0)
{
- return TRUE;
+ return true;
}
/* Never show this prop */
@@ -1539,44 +1547,44 @@ static int gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
return FALSE;
if (link_strokes) {
- /* Only show when link_stroke is TRUE */
+ /* Only show when link_stroke is true */
if (strcmp(prop_id, "timing_mode") == 0)
- return TRUE;
+ return true;
if (timing_mode != GP_STROKECONVERT_TIMING_NONE) {
- /* Only show when link_stroke is TRUE and stroke timing is enabled */
+ /* 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;
+ return true;
}
/* Only show if we have valid timing data! */
if (valid_timing && strcmp(prop_id, "use_realtime") == 0)
- return TRUE;
+ return true;
/* Only show if realtime or valid_timing is FALSE! */
if ((!realtime || !valid_timing) && strcmp(prop_id, "end_frame") == 0)
- return TRUE;
+ 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;
+ return true;
/* Only show randomness for non-null custom gaps! */
if (strcmp(prop_id, "gap_randomness") == 0 && (gap_duration > 0.0f))
- return TRUE;
+ return true;
/* Only show seed for randomize action! */
if (strcmp(prop_id, "seed") == 0 && (gap_duration > 0.0f) && (gap_randomness > 0.0f))
- return TRUE;
+ return true;
}
}
}
/* Else, hidden! */
- return FALSE;
+ return false;
}
static void gp_convert_ui(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 8fdca730674..bc68ad8869a 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -39,6 +39,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "PIL_time.h"
#include "BKE_gpencil.h"
@@ -208,7 +210,7 @@ static int gpencil_project_check(tGPsdata *p)
static void gp_get_3d_reference(tGPsdata *p, float vec[3])
{
View3D *v3d = p->sa->spacedata.first;
- float *fp = give_cursor(p->scene, v3d);
+ const float *fp = give_cursor(p->scene, v3d);
/* the reference point used depends on the owner... */
#if 0 /* XXX: disabled for now, since we can't draw relative to the owner yet */
@@ -275,6 +277,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3]
int mval_prj[2];
float rvec[3], dvec[3];
float mval_f[2];
+ float zfac;
/* Current method just converts each point in screen-coordinates to
* 3D-coordinates using the 3D-cursor as reference. In general, this
@@ -286,12 +289,13 @@ 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);
/* method taken from editview.c - mouse_cursor() */
/* TODO, use ED_view3d_project_float_global */
if (ED_view3d_project_int_global(p->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
VECSUB2D(mval_f, mval_prj, mval);
- ED_view3d_win_to_delta(p->ar, mval_f, dvec);
+ ED_view3d_win_to_delta(p->ar, mval_f, dvec, zfac);
sub_v3_v3v3(out, rvec, dvec);
}
else {
@@ -929,7 +933,8 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p,
/* 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)) ||
- ((!ELEM(V2D_IS_CLIPPED, x1, y1)) && BLI_rcti_isect_pt(rect, x1, y1))) {
+ ((!ELEM(V2D_IS_CLIPPED, x1, y1)) && BLI_rcti_isect_pt(rect, x1, y1)))
+ {
/* 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
@@ -1234,13 +1239,6 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode)
switch (p->sa->spacetype) {
case SPACE_VIEW3D:
{
- RegionView3D *rv3d = p->ar->regiondata;
- float rvec[3];
-
- /* get reference point for 3d space placement */
- gp_get_3d_reference(p, rvec);
- initgrabz(rv3d, rvec[0], rvec[1], rvec[2]);
-
p->gpd->sbuffer_sflag |= GP_STROKE_3DSPACE;
}
break;
@@ -1457,28 +1455,27 @@ static void gpencil_draw_status_indicators(tGPsdata *p)
case GP_STATUS_PAINTING:
/* only print this for paint-sessions, otherwise it gets annoying */
if (GPENCIL_SKETCH_SESSIONS_ON(p->scene))
- ED_area_headerprint(p->sa, "Grease Pencil: Drawing/erasing stroke... Release to end stroke");
+ ED_area_headerprint(p->sa, IFACE_("Grease Pencil: Drawing/erasing stroke... Release to end stroke"));
break;
case GP_STATUS_IDLING:
/* print status info */
switch (p->paintmode) {
case GP_PAINTMODE_ERASER:
- ED_area_headerprint(p->sa,
- "Grease Pencil Erase Session: Hold and drag LMB or RMB to erase |"
- " ESC/Enter to end");
+ ED_area_headerprint(p->sa, IFACE_("Grease Pencil Erase Session: Hold and drag LMB or RMB to erase |"
+ " ESC/Enter to end"));
break;
case GP_PAINTMODE_DRAW_STRAIGHT:
- ED_area_headerprint(p->sa, "Grease Pencil Line Session: Hold and drag LMB to draw | "
- "ESC/Enter to end");
+ ED_area_headerprint(p->sa, IFACE_("Grease Pencil Line Session: Hold and drag LMB to draw | "
+ "ESC/Enter to end"));
break;
case GP_PAINTMODE_DRAW:
- ED_area_headerprint(p->sa, "Grease Pencil Freehand Session: Hold and drag LMB to draw | "
- "ESC/Enter to end");
+ 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, "Grease Pencil Session: ESC/Enter to end");
+ ED_area_headerprint(p->sa, IFACE_("Grease Pencil Session: ESC/Enter to end"));
break;
}
break;
@@ -1549,7 +1546,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p)
}
/* handle draw event */
-static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event)
+static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event)
{
tGPsdata *p = op->customdata;
PointerRNA itemptr;
@@ -1564,8 +1561,8 @@ static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event)
p->curtime = PIL_check_seconds_timer();
/* handle pressure sensitivity (which is supplied by tablets) */
- if (event->custom == EVT_DATA_TABLET) {
- wmTabletData *wmtab = event->customdata;
+ if (event->tablet_data) {
+ wmTabletData *wmtab = event->tablet_data;
tablet = (wmtab->Active != EVT_TABLET_NONE);
p->pressure = wmtab->Pressure;
@@ -1687,7 +1684,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
/* ------------------------------- */
/* start of interactive drawing part of operator */
-static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
tGPsdata *p = NULL;
wmWindow *win = CTX_wm_window(C);
@@ -1798,7 +1795,7 @@ static void gpencil_stroke_end(wmOperator *op)
}
/* events handling during interactive drawing part of operator */
-static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
tGPsdata *p = op->customdata;
int estate = OPERATOR_PASS_THROUGH; /* default exit state - pass through to support MMB view nav, etc. */
diff --git a/source/blender/editors/include/BIF_gl.h b/source/blender/editors/include/BIF_gl.h
index 479e0b65177..cdf9b71972d 100644
--- a/source/blender/editors/include/BIF_gl.h
+++ b/source/blender/editors/include/BIF_gl.h
@@ -35,6 +35,14 @@
#include "GL/glew.h"
+#ifdef __APPLE__
+
+/* hacking pointsize and linewidth */
+#define glPointSize(f) glPointSize(U.pixelsize*(f))
+#define glLineWidth(f) glLineWidth(U.pixelsize*(f))
+
+#endif
+
/*
* these should be phased out. cpack should be replaced in
* code with calls to glColor3ub. - zr
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
index 577113927d1..39d1e283f54 100644
--- a/source/blender/editors/include/BIF_glutil.h
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -51,10 +51,10 @@ void fdrawcheckerboard(float x1, float y1, float x2, float y2);
/* OpenGL stipple defines */
/* OpenGL stipple defines */
-extern unsigned char stipple_halftone[128];
-extern unsigned char stipple_quarttone[128];
-extern unsigned char stipple_diag_stripes_pos[128];
-extern unsigned char stipple_diag_stripes_neg[128];
+extern const unsigned char stipple_halftone[128];
+extern const unsigned char stipple_quarttone[128];
+extern const unsigned char stipple_diag_stripes_pos[128];
+extern const unsigned char stipple_diag_stripes_neg[128];
/**
* Draw a lined (non-looping) arc with the given
@@ -129,7 +129,7 @@ void glaRasterPosSafe2f(float x, float y, float known_good_x, float known_good_y
void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect);
/**
- * Functions like a limited glDrawPixels, but actually draws the
+ * glaDrawPixelsTex - Functions like a limited glDrawPixels, but actually draws the
* image using textures, which can be tremendously faster on low-end
* cards, and also avoids problems with the raster position being
* clipped when offscreen. The routine respects the glPixelZoom values,
@@ -141,9 +141,17 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo
* 1-to-1 mapping to screen space.
*/
-void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, void *rect);
+void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect);
-void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, void *rect, float scaleX, float scaleY);
+/**
+ * glaDrawPixelsAuto - Switches between texture or pixel drawing using UserDef.
+ * only RGBA
+ * needs glaDefine2DArea to be set.
+ */
+void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect);
+
+
+void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect, float scaleX, float scaleY);
/* 2D Drawing Assistance */
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 8d7ae3aad6a..b8ad40b2bd9 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -155,6 +155,7 @@ typedef enum eAnim_ChannelType {
ANIMTYPE_DSMESH,
ANIMTYPE_DSTEX,
ANIMTYPE_DSLAT,
+ ANIMTYPE_DSLINESTYLE,
ANIMTYPE_DSSPK,
ANIMTYPE_SHAPEKEY,
@@ -236,6 +237,7 @@ typedef enum eAnimFilter_Flags {
#define EXPANDED_SCEC(sce) (CHECK_TYPE_INLINE(sce, Scene), ((sce->flag & SCE_DS_COLLAPSED) == 0))
/* 'Sub-Scene' channels (flags stored in Data block) */
#define FILTER_WOR_SCED(wo) (CHECK_TYPE_INLINE(wo, World), (wo->flag & WO_DS_EXPAND))
+#define FILTER_LS_SCED(linestyle) ((linestyle->flag & LS_DS_EXPAND))
/* 'Object' channels */
#define SEL_OBJC(base) (CHECK_TYPE_INLINE(base, Base), ((base->flag & SELECT)))
#define EXPANDED_OBJC(ob) (CHECK_TYPE_INLINE(ob, Object), ((ob->nlaflag & OB_ADS_COLLAPSED) == 0))
@@ -292,42 +294,45 @@ typedef enum eAnimFilter_Flags {
#define SEL_MASKLAY(masklay) (masklay->flag & SELECT)
-
/* NLA only */
#define SEL_NLT(nlt) (nlt->flag & NLATRACK_SELECTED)
#define EDITABLE_NLT(nlt) ((nlt->flag & NLATRACK_PROTECTED) == 0)
+
+/* AnimData - NLA mostly... */
+#define SEL_ANIMDATA(adt) (adt->flag & ADT_UI_SELECTED)
+
/* -------------- Channel Defines -------------- */
/* channel heights */
-#define ACHANNEL_FIRST -16
-#define ACHANNEL_HEIGHT 16
-#define ACHANNEL_HEIGHT_HALF 8
-#define ACHANNEL_SKIP 2
+#define ACHANNEL_FIRST (-0.8f * U.widget_unit)
+#define ACHANNEL_HEIGHT (0.8f * U.widget_unit)
+#define ACHANNEL_HEIGHT_HALF (0.4f * U.widget_unit)
+#define ACHANNEL_SKIP (0.1f * U.widget_unit)
#define ACHANNEL_STEP (ACHANNEL_HEIGHT + ACHANNEL_SKIP)
/* channel widths */
-#define ACHANNEL_NAMEWIDTH 200
+#define ACHANNEL_NAMEWIDTH (10 * U.widget_unit)
/* channel toggle-buttons */
-#define ACHANNEL_BUTTON_WIDTH 16
+#define ACHANNEL_BUTTON_WIDTH (0.8f * U.widget_unit)
/* -------------- NLA Channel Defines -------------- */
/* NLA channel heights */
// XXX: NLACHANNEL_FIRST isn't used?
-#define NLACHANNEL_FIRST -16
-#define NLACHANNEL_HEIGHT(snla) ((snla && (snla->flag & SNLA_NOSTRIPCURVES)) ? 16 : 24)
-#define NLACHANNEL_HEIGHT_HALF(snla) ((snla && (snla->flag & SNLA_NOSTRIPCURVES)) ? 8 : 12)
-#define NLACHANNEL_SKIP 2
+#define NLACHANNEL_FIRST (-0.8f * U.widget_unit)
+#define NLACHANNEL_HEIGHT(snla) ((snla && (snla->flag & SNLA_NOSTRIPCURVES)) ? (0.8f * U.widget_unit) : (1.2f * U.widget_unit))
+#define NLACHANNEL_HEIGHT_HALF(snla) ((snla && (snla->flag & SNLA_NOSTRIPCURVES)) ? (0.4f * U.widget_unit) : (0.6f * U.widget_unit))
+#define NLACHANNEL_SKIP (0.1f * U.widget_unit)
#define NLACHANNEL_STEP(snla) (NLACHANNEL_HEIGHT(snla) + NLACHANNEL_SKIP)
/* channel widths */
-#define NLACHANNEL_NAMEWIDTH 200
+#define NLACHANNEL_NAMEWIDTH (10 * U.widget_unit)
/* channel toggle-buttons */
-#define NLACHANNEL_BUTTON_WIDTH 16
+#define NLACHANNEL_BUTTON_WIDTH (0.8f * U.widget_unit)
/* ---------------- API -------------------- */
@@ -469,7 +474,7 @@ void ANIM_timecode_string_from_frame(char *str, struct Scene *scene, int power,
/* ---------- Current Frame Drawing ---------------- */
/* flags for Current Frame Drawing */
-enum {
+enum eAnimEditDraw_CurrentFrame {
/* plain time indicator with no special indicators */
DRAWCFRA_PLAIN = 0,
/* draw box indicating current frame number */
@@ -478,7 +483,7 @@ enum {
DRAWCFRA_UNIT_SECONDS = (1 << 1),
/* draw indicator extra wide (for timeline) */
DRAWCFRA_WIDE = (1 << 2)
-} eAnimEditDraw_CurrentFrame;
+};
/* main call to draw current-frame indicator in an Animation Editor */
void ANIM_draw_cfra(const struct bContext *C, struct View2D *v2d, short flag);
@@ -552,7 +557,8 @@ typedef enum eAnimUnitConv_Flags {
/* only touch selected BezTriples */
ANIM_UNITCONV_ONLYSEL = (1 << 2),
/* only touch selected vertices */
- ANIM_UNITCONV_SELVERTS = (1 << 3)
+ ANIM_UNITCONV_SELVERTS = (1 << 3),
+ ANIM_UNITCONV_SKIPKNOTS = (1 << 4),
} eAnimUnitConv_Flags;
/* Get unit conversion factor for given ID + F-Curve */
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 4db79df033e..3367dcb9c4c 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -61,7 +61,7 @@ typedef struct EditBone {
* normal bones when leaving editmode. */
void *temp; /* Used to store temporary data */
- char name[64]; /* MAX_NAME */
+ 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
* is tail-head while roll provides the angle. Refer to Graphics
@@ -123,8 +123,8 @@ void ED_armature_deselect_all(struct Object *obedit, int toggle);
void ED_armature_deselect_all_visible(struct Object *obedit);
int ED_do_pose_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer,
- short hits, short extend, short deselect, short toggle);
-int mouse_armature(struct bContext *C, const int mval[2], int extend, int deselect, int toggle);
+ short hits, bool extend, bool deselect, bool toggle);
+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);
struct Bone *get_indexed_bone(struct Object *ob, int index);
float ED_rollBoneToVector(EditBone *bone, const float new_up_axis[3], const short axis_only);
@@ -135,9 +135,10 @@ void ED_armature_validate_active(struct bArmature *arm);
void add_primitive_bone(struct Scene *scene, struct View3D *v3d, struct RegionView3D *rv3d);
struct EditBone *ED_armature_edit_bone_add(struct bArmature *arm, const char *name);
void ED_armature_edit_bone_remove(struct bArmature *arm, EditBone *exBone);
+bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebone_child);
void transform_armature_mirror_update(struct Object *obedit);
-void docenter_armature(struct Scene *scene, struct Object *ob, float cursor[3], int centermode, int around);
+void ED_armature_origin_set(struct Scene *scene, struct Object *ob, float cursor[3], int centermode, int around);
void ED_armature_apply_transform(struct Object *ob, float mat[4][4]);
diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h
index d66cc49a5d0..1d26204095c 100644
--- a/source/blender/editors/include/ED_curve.h
+++ b/source/blender/editors/include/ED_curve.h
@@ -63,14 +63,11 @@ void load_editNurb(struct Object *obedit);
void make_editNurb(struct Object *obedit);
void free_editNurb(struct Object *obedit);
-void BKE_curve_editNurb_free(struct Curve *cu);
-
-int mouse_nurb(struct bContext *C, const int mval[2], int extend, int deselect, int toggle);
+bool mouse_nurb(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
struct Nurb *add_nurbs_primitive(struct bContext *C, struct Object *obedit, float mat[4][4], int type, int newob);
int isNurbsel(struct Nurb *nu);
-void ED_nurb_set_spline_type(struct Nurb *nu, int type);
int join_curve_exec(struct bContext *C, struct wmOperator *op);
diff --git a/source/blender/editors/include/ED_datafiles.h b/source/blender/editors/include/ED_datafiles.h
index 8ad36397ce5..81dbb8e9aa5 100644
--- a/source/blender/editors/include/ED_datafiles.h
+++ b/source/blender/editors/include/ED_datafiles.h
@@ -36,8 +36,17 @@
extern int datatoc_startup_blend_size;
extern char datatoc_startup_blend[];
-extern int datatoc_blender_icons_png_size;
-extern char datatoc_blender_icons_png[];
+extern int datatoc_preview_blend_size;
+extern char datatoc_preview_blend[];
+
+extern int datatoc_preview_cycles_blend_size;
+extern char datatoc_preview_cycles_blend[];
+
+extern int datatoc_blender_icons16_png_size;
+extern char datatoc_blender_icons16_png[];
+
+extern int datatoc_blender_icons32_png_size;
+extern char datatoc_blender_icons32_png[];
extern int datatoc_prvicons_png_size;
extern char datatoc_prvicons_png[];
@@ -147,6 +156,81 @@ extern char datatoc_twist_png[];
extern int datatoc_vertexdraw_png_size;
extern char datatoc_vertexdraw_png[];
+/* Matcap files */
+
+extern int datatoc_mc01_jpg_size;
+extern char datatoc_mc01_jpg[];
+
+extern int datatoc_mc02_jpg_size;
+extern char datatoc_mc02_jpg[];
+
+extern int datatoc_mc03_jpg_size;
+extern char datatoc_mc03_jpg[];
+
+extern int datatoc_mc04_jpg_size;
+extern char datatoc_mc04_jpg[];
+
+extern int datatoc_mc05_jpg_size;
+extern char datatoc_mc05_jpg[];
+
+extern int datatoc_mc06_jpg_size;
+extern char datatoc_mc06_jpg[];
+
+extern int datatoc_mc07_jpg_size;
+extern char datatoc_mc07_jpg[];
+
+extern int datatoc_mc08_jpg_size;
+extern char datatoc_mc08_jpg[];
+
+extern int datatoc_mc09_jpg_size;
+extern char datatoc_mc09_jpg[];
+
+extern int datatoc_mc10_jpg_size;
+extern char datatoc_mc10_jpg[];
+
+extern int datatoc_mc11_jpg_size;
+extern char datatoc_mc11_jpg[];
+
+extern int datatoc_mc12_jpg_size;
+extern char datatoc_mc12_jpg[];
+
+extern int datatoc_mc13_jpg_size;
+extern char datatoc_mc13_jpg[];
+
+extern int datatoc_mc14_jpg_size;
+extern char datatoc_mc14_jpg[];
+
+extern int datatoc_mc15_jpg_size;
+extern char datatoc_mc15_jpg[];
+
+extern int datatoc_mc16_jpg_size;
+extern char datatoc_mc16_jpg[];
+
+extern int datatoc_mc17_jpg_size;
+extern char datatoc_mc17_jpg[];
+
+extern int datatoc_mc18_jpg_size;
+extern char datatoc_mc18_jpg[];
+
+extern int datatoc_mc19_jpg_size;
+extern char datatoc_mc19_jpg[];
+
+extern int datatoc_mc20_jpg_size;
+extern char datatoc_mc20_jpg[];
+
+extern int datatoc_mc21_jpg_size;
+extern char datatoc_mc21_jpg[];
+
+extern int datatoc_mc22_jpg_size;
+extern char datatoc_mc22_jpg[];
+
+extern int datatoc_mc23_jpg_size;
+extern char datatoc_mc23_jpg[];
+
+extern int datatoc_mc24_jpg_size;
+extern char datatoc_mc24_jpg[];
+
+
#endif /* __ED_DATAFILES_H__ */
diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h
index d45504b3325..b7d9f811349 100644
--- a/source/blender/editors/include/ED_fileselect.h
+++ b/source/blender/editors/include/ED_fileselect.h
@@ -31,10 +31,11 @@
#ifndef __ED_FILESELECT_H__
#define __ED_FILESELECT_H__
-struct SpaceFile;
struct ARegion;
struct FileSelectParams;
+struct SpaceFile;
struct bContext;
+struct wmWindowManager;
#define FILE_LAYOUT_HOR 1
#define FILE_LAYOUT_VER 2
@@ -99,9 +100,9 @@ void ED_fileselect_layout_tilepos(FileLayout *layout, int tile, int *x, int *y);
void ED_operatormacros_file(void);
-void ED_fileselect_clear(struct bContext *C, struct SpaceFile *sfile);
+void ED_fileselect_clear(struct wmWindowManager *wm, struct SpaceFile *sfile);
-void ED_fileselect_exit(struct bContext *C, struct SpaceFile *sfile);
+void ED_fileselect_exit(struct wmWindowManager *wm, struct SpaceFile *sfile);
int ED_file_extension_icon(const char *relname);
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index 5cc1ecade3e..cb4a81be8b8 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -79,8 +79,9 @@ void ED_operatortypes_gpencil(void);
void draw_gpencil_2dimage(const struct bContext *C);
void draw_gpencil_view2d(const struct bContext *C, short onlyv2d);
-void draw_gpencil_view3d(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, short only3d);
+void draw_gpencil_view3d(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, bool only3d);
+void gpencil_panel_standard_header(const struct bContext *C, struct Panel *pa);
void gpencil_panel_standard(const struct bContext *C, struct Panel *pa);
/* ----------- Grease-Pencil AnimEdit API ------------------ */
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index 9b726cea56c..11b8aa5e60a 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -79,7 +79,7 @@ int ED_space_image_maskedit_mask_poll(struct bContext *C);
void ED_image_update_frame(const struct Main *mainp, int cfra);
void ED_image_draw_info(struct Scene *scene, struct ARegion *ar, int color_manage, int use_default_view, int channels, int x, int y,
- const unsigned char cp[4], const float fp[4], int *zp, float *zpf);
+ const unsigned char cp[4], const float fp[4], const float linearcol[4], int *zp, float *zpf);
#endif /* __ED_IMAGE_H__ */
diff --git a/source/blender/editors/include/ED_mball.h b/source/blender/editors/include/ED_mball.h
index 1321765588d..da96aba011e 100644
--- a/source/blender/editors/include/ED_mball.h
+++ b/source/blender/editors/include/ED_mball.h
@@ -32,6 +32,7 @@
#define __ED_MBALL_H__
struct bContext;
+struct MetaBall;
struct Object;
struct wmKeyConfig;
@@ -40,7 +41,7 @@ void ED_keymap_metaball(struct wmKeyConfig *keyconf);
struct MetaElem *add_metaball_primitive(struct bContext *C, struct Object *obedit, float mat[4][4], float dia, int type, int newname);
-int mouse_mball(struct bContext *C, const int mval[2], int extend, int deselect, int toggle);
+bool mouse_mball(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
void free_editMball(struct Object *obedit);
void make_editMball(struct Object *obedit);
@@ -48,5 +49,6 @@ void load_editMball(struct Object *obedit);
void undo_push_mball(struct bContext *C, const char *name);
-#endif
+void ED_mball_transform(struct MetaBall *mb, float *mat);
+#endif /* __ED_MBALL_H__ */
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 865da8f0e6e..f84281a4f08 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -74,7 +74,7 @@ struct rcti;
/* editmesh_utils.c */
-void EDBM_verts_mirror_cache_begin(struct BMEditMesh *em, const short use_select); /* note, replaces EM_cache_x_mirror_vert in trunk */
+void EDBM_verts_mirror_cache_begin(struct BMEditMesh *em, const bool use_select); /* note, replaces EM_cache_x_mirror_vert in trunk */
void EDBM_verts_mirror_apply(struct BMEditMesh *em, const int sel_from, const int sel_to);
struct BMVert *EDBM_verts_mirror_get(struct BMEditMesh *em, struct BMVert *v);
void EDBM_verts_mirror_cache_clear(struct BMEditMesh *em, struct BMVert *v);
@@ -86,11 +86,15 @@ void EDBM_mesh_clear(struct BMEditMesh *em);
void EDBM_selectmode_to_scene(struct bContext *C);
void EDBM_mesh_make(struct ToolSettings *ts, struct Scene *scene, struct Object *ob);
-void EDBM_mesh_free(struct BMEditMesh *tm);
+void EDBM_mesh_free(struct BMEditMesh *em);
void EDBM_mesh_load(struct Object *ob);
-void EDBM_index_arrays_init(struct BMEditMesh *em, int forvert, int foredge, int forface);
+void EDBM_index_arrays_ensure(struct BMEditMesh *em, const char htype);
+void EDBM_index_arrays_init(struct BMEditMesh *em, const char htype);
void EDBM_index_arrays_free(struct BMEditMesh *em);
+#ifndef NDEBUG
+bool EDBM_index_arrays_check(struct BMEditMesh *em);
+#endif
struct BMVert *EDBM_vert_at_index(struct BMEditMesh *em, int index);
struct BMEdge *EDBM_edge_at_index(struct BMEditMesh *em, int index);
struct BMFace *EDBM_face_at_index(struct BMEditMesh *em, int index);
@@ -115,7 +119,7 @@ int EDBM_vert_color_check(struct BMEditMesh *em);
void EDBM_mesh_hide(struct BMEditMesh *em, int swap);
void EDBM_mesh_reveal(struct BMEditMesh *em);
-void EDBM_update_generic(struct bContext *C, struct BMEditMesh *em, const short do_tessface);
+void EDBM_update_generic(struct BMEditMesh *em, const bool do_tessface, const bool is_destructive);
struct UvElementMap *EDBM_uv_element_map_create(struct BMEditMesh *em, int selected, int doIslands);
void EDBM_uv_element_map_free(struct UvElementMap *vmap);
@@ -126,37 +130,40 @@ struct MTexPoly *EDBM_mtexpoly_active_get(struct BMEditMesh *em, struct BMFace *
void EDBM_uv_vert_map_free(struct UvVertMap *vmap);
struct UvMapVert *EDBM_uv_vert_map_at_index(struct UvVertMap *vmap, unsigned int v);
-struct UvVertMap *EDBM_uv_vert_map_create(struct BMEditMesh *em, int selected, int do_face_idx_array, const float limit[2]);
+struct UvVertMap *EDBM_uv_vert_map_create(struct BMEditMesh *em, bool use_select, const float limit[2]);
void EDBM_flag_enable_all(struct BMEditMesh *em, const char hflag);
void EDBM_flag_disable_all(struct BMEditMesh *em, const char hflag);
/* editmesh_select.c */
-void EDBM_select_mirrored(struct Object *obedit, struct BMEditMesh *em, int extend);
+void EDBM_select_mirrored(struct Object *obedit, struct BMEditMesh *em, bool extend);
void EDBM_automerge(struct Scene *scene, struct Object *ob, int update);
-int EDBM_backbuf_border_init(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
+bool EDBM_backbuf_border_init(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
int EDBM_backbuf_check(unsigned int index);
void EDBM_backbuf_free(void);
-int EDBM_backbuf_border_mask_init(struct ViewContext *vc, const int mcords[][2], short tot,
+bool EDBM_backbuf_border_mask_init(struct ViewContext *vc, const int mcords[][2], short tot,
short xmin, short ymin, short xmax, short ymax);
-int EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads);
+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 short sel, const short strict);
+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);
-int EDBM_select_pick(struct bContext *C, const int mval[2], short extend, short deselect, short toggle);
+bool EDBM_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
void EDBM_selectmode_set(struct BMEditMesh *em);
void EDBM_selectmode_convert(struct BMEditMesh *em, const short selectmode_old, const short selectmode_new);
/* user access this */
-int EDBM_selectmode_toggle(struct bContext *C, const short selectmode_new,
- const int action, const int use_extend, const int use_expand);
+bool EDBM_selectmode_toggle(struct bContext *C, const short selectmode_new,
+ const int action, const bool use_extend, const bool use_expand);
+bool EDBM_selectmode_disable(struct Scene *scene, struct BMEditMesh *em,
+ const short selectmode_disable,
+ const short selectmode_fallback);
void EDBM_deselect_by_material(struct BMEditMesh *em, const short index, const short select);
@@ -168,17 +175,10 @@ void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc); /* renam
extern unsigned int bm_vertoffs, bm_solidoffs, bm_wireoffs;
-
/* mesh_ops.c */
void ED_operatortypes_mesh(void);
void ED_operatormacros_mesh(void);
void ED_keymap_mesh(struct wmKeyConfig *keyconf);
-void ED_keymap_mesh(struct wmKeyConfig *keyconf);
-
-
-/* spacetypes.c */
-void ED_spacetypes_init(void);
-
/* editmesh_tools.c (could be moved) */
void EMBM_project_snap_verts(struct bContext *C, struct ARegion *ar, struct BMEditMesh *em);
@@ -186,16 +186,17 @@ void EMBM_project_snap_verts(struct bContext *C, struct ARegion *ar, struct BMEd
/* editface.c */
void paintface_flush_flags(struct Object *ob);
-int paintface_mouse_select(struct bContext *C, struct Object *ob, const int mval[2], int extend, int deselect, int toggle);
-int do_paintface_box_select(struct ViewContext *vc, struct rcti *rect, int select, int extend);
-void paintface_deselect_all_visible(struct Object *ob, int action, short flush_flags);
-void paintface_select_linked(struct bContext *C, struct Object *ob, int mval[2], int mode);
-int paintface_minmax(struct Object *ob, float r_min[3], float r_max[3]);
+bool paintface_mouse_select(struct bContext *C, struct Object *ob, const int mval[2], bool extend, bool deselect, bool toggle);
+int do_paintface_box_select(struct ViewContext *vc, struct rcti *rect, bool select, bool extend);
+void paintface_deselect_all_visible(struct Object *ob, int action, bool flush_flags);
+void paintface_select_linked(struct bContext *C, struct Object *ob, const int mval[2], int mode);
+bool paintface_minmax(struct Object *ob, float r_min[3], float r_max[3]);
void paintface_hide(struct Object *ob, const int unselected);
void paintface_reveal(struct Object *ob);
-void paintvert_deselect_all_visible(struct Object *ob, int action, short flush_flags);
+void paintvert_deselect_all_visible(struct Object *ob, int action, bool flush_flags);
+void paintvert_select_ungrouped(struct Object *ob, bool extend, bool flush_flags);
void paintvert_flush_flags(struct Object *ob);
/* mirrtopo */
@@ -206,9 +207,9 @@ typedef struct MirrTopoStore_t {
int prev_ob_mode;
} MirrTopoStore_t;
-int ED_mesh_mirrtopo_recalc_check(struct Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store);
+bool ED_mesh_mirrtopo_recalc_check(struct Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store);
void ED_mesh_mirrtopo_init(struct Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store,
- const short skip_em_vert_array_init);
+ const bool skip_em_vert_array_init);
void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store);
@@ -223,6 +224,7 @@ void ED_vgroup_delete(struct Object *ob, struct bDeformGroup *de
void ED_vgroup_clear(struct Object *ob);
void ED_vgroup_select_by_name(struct Object *ob, const char *name);
int ED_vgroup_data_create(struct ID *id);
+void ED_vgroup_data_clamp_range(struct ID *id, const int total);
int ED_vgroup_give_array(struct ID *id, struct MDeformVert **dvert_arr, int *dvert_tot);
int ED_vgroup_copy_array(struct Object *ob, struct Object *ob_from);
void ED_vgroup_mirror(struct Object *ob, const short mirror_weights, const short flip_vgroups, const short all_vgroups);
@@ -252,13 +254,16 @@ void ED_mesh_calc_tessface(struct Mesh *mesh);
void ED_mesh_material_link(struct Mesh *me, struct Material *ma);
void ED_mesh_update(struct Mesh *mesh, struct bContext *C, int calc_edges, int calc_tessface);
-int ED_mesh_uv_texture_add(struct bContext *C, struct Mesh *me, const char *name, int active_set);
-int ED_mesh_uv_texture_remove(struct bContext *C, struct Object *ob, struct Mesh *me);
+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);
+bool ED_mesh_uv_texture_remove_named(struct Mesh *me, const char *name);
int ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me);
int ED_mesh_uv_loop_reset_ex(struct Mesh *me, const int layernum);
-int ED_mesh_color_add(struct bContext *C, struct Scene *scene, struct Object *ob, struct Mesh *me, const char *name, int active_set);
-int ED_mesh_color_remove(struct bContext *C, struct Object *ob, struct Mesh *me);
-int ED_mesh_color_remove_named(struct bContext *C, struct Object *ob, struct Mesh *me, const char *name);
+int ED_mesh_color_add(struct Mesh *me, const char *name, const bool active_set);
+bool ED_mesh_color_remove_index(struct Mesh *me, const int n);
+bool ED_mesh_color_remove_active(struct Mesh *me);
+bool ED_mesh_color_remove_named(struct Mesh *me, const char *name);
/* mesh backup */
typedef struct BMBackup {
@@ -287,9 +292,9 @@ int mesh_get_x_mirror_vert(struct Object *ob, int index);
struct BMVert *editbmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh *em, struct BMVert *eve, const float co[3], int index);
int *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em);
-int ED_mesh_pick_vert(struct bContext *C, struct Mesh *me, const int mval[2], unsigned int *index, int size);
-int ED_mesh_pick_face(struct bContext *C, struct Mesh *me, const int mval[2], unsigned int *index, int size);
-int ED_mesh_pick_face_vert(struct bContext *C, struct Mesh *me, struct Object *ob, const int mval[2], unsigned int *index, int size);
+bool ED_mesh_pick_vert(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int size, bool use_zbuf);
+bool ED_mesh_pick_face(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int size);
+bool ED_mesh_pick_face_vert(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int size);
#define ED_MESH_PICK_DEFAULT_VERT_SIZE 50
#define ED_MESH_PICK_DEFAULT_FACE_SIZE 3
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index 32baa8883e1..448a15334c7 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -39,7 +39,10 @@ struct Tex;
struct bContext;
struct bNodeTree;
struct bNode;
+struct bNodeType;
+struct bNodeSocketType;
struct bNodeTree;
+struct bNodeTreeType;
struct ScrArea;
struct Scene;
struct View2D;
@@ -51,15 +54,30 @@ typedef enum {
NODE_RIGHT = 8
} NodeBorder;
+/* space_node.c */
+int ED_node_tree_path_length(struct SpaceNode *snode);
+void ED_node_tree_path_get(struct SpaceNode *snode, char *value);
+void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length);
+
+void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, struct ID *id, struct ID *from);
+void ED_node_tree_push(struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *gnode);
+void ED_node_tree_pop(struct SpaceNode *snode);
+int ED_node_tree_depth(struct SpaceNode *snode);
+struct bNodeTree *ED_node_tree_get(struct SpaceNode *snode, int level);
+
/* drawnode.c */
void ED_node_init_butfuncs(void);
+void ED_init_custom_node_type(struct bNodeType *ntype);
+void ED_init_custom_node_socket_type(struct bNodeSocketType *stype);
+void ED_init_standard_node_socket_type(struct bNodeSocketType *stype);
+void ED_init_node_socket_type_virtual(struct bNodeSocketType *stype);
void ED_node_sample_set(const float col[4]);
void ED_node_draw_snap(struct View2D *v2d, const float cent[2], float size, NodeBorder border);
/* node_draw.c */
-void ED_node_tree_update(struct SpaceNode *snode, struct Scene *scene);
-void ED_node_changed_update(struct ID *id, struct bNode *node);
-void ED_node_generic_update(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node);
+void ED_node_tree_update(const struct bContext *C);
+void ED_node_tag_update_id(struct ID *id);
+void ED_node_tag_update_nodetree(struct Main *bmain, struct bNodeTree *ntree);
void ED_node_sort(struct bNodeTree *ntree);
/* node_relationships.c */
@@ -67,9 +85,14 @@ void ED_node_link_intersect_test(struct ScrArea *sa, int test);
void ED_node_link_insert(struct ScrArea *sa);
/* node_edit.c */
-void ED_node_shader_default(struct Scene *scene, struct ID *id);
-void ED_node_composit_default(struct Scene *sce);
-void ED_node_texture_default(struct Tex *tex);
+void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo);
+int ED_node_is_compositor(struct SpaceNode *snode);
+int ED_node_is_shader(struct SpaceNode *snode);
+int ED_node_is_texture(struct SpaceNode *snode);
+
+void ED_node_shader_default(const struct bContext *C, struct ID *id);
+void ED_node_composit_default(const struct bContext *C, struct Scene *scene);
+void ED_node_texture_default(const struct bContext *C, struct Tex *tex);
int ED_node_select_check(ListBase *lb);
void ED_node_post_apply_transform(struct bContext *C, struct bNodeTree *ntree);
void ED_node_set_active(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node);
diff --git a/source/blender/editors/include/ED_numinput.h b/source/blender/editors/include/ED_numinput.h
index 126ea13f0b2..e7d80d96f89 100644
--- a/source/blender/editors/include/ED_numinput.h
+++ b/source/blender/editors/include/ED_numinput.h
@@ -61,7 +61,7 @@ void initNumInput(NumInput *n);
void outputNumInput(NumInput *n, char *str);
short hasNumInput(NumInput *n);
void applyNumInput(NumInput *n, float *vec);
-char handleNumInput(NumInput *n, struct wmEvent *event);
+char handleNumInput(NumInput *n, const struct wmEvent *event);
#define NUM_MODAL_INCREMENT_UP 18
#define NUM_MODAL_INCREMENT_DOWN 19
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 533bfe2fa20..e23465f15a8 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -83,6 +83,7 @@ typedef enum eParentType {
PAR_ARMATURE_ENVELOPE,
PAR_ARMATURE_AUTO,
PAR_BONE,
+ PAR_BONE_RELATIVE,
PAR_CURVE,
PAR_FOLLOW,
PAR_PATH_CONST,
@@ -127,8 +128,9 @@ void ED_object_toggle_modes(struct bContext *C, int mode);
#define EM_WAITCURSOR 4
#define EM_DO_UNDO 8
#define EM_IGNORE_LAYER 16
-void ED_object_exit_editmode(struct bContext *C, int flag);
-void ED_object_enter_editmode(struct bContext *C, int flag);
+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);
void ED_object_location_from_view(struct bContext *C, float loc[3]);
void ED_object_rotation_from_view(struct bContext *C, float rot[3]);
@@ -160,10 +162,10 @@ void object_test_constraints(struct Object *ob);
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 Scene *scene, struct Object *ob);
+void ED_object_constraint_dependency_update(struct Main *bmain, struct Object *ob);
/* object_lattice.c */
-int mouse_lattice(struct bContext *C, const int mval[2], int extend, int deselect, int toggle);
+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);
/* object_lattice.c */
@@ -178,9 +180,9 @@ enum {
struct ModifierData *ED_object_modifier_add(struct ReportList *reports, struct Main *bmain, struct Scene *scene,
struct Object *ob, const char *name, int type);
-int ED_object_modifier_remove(struct ReportList *reports, struct Main *bmain, struct Scene *scene,
+int ED_object_modifier_remove(struct ReportList *reports, struct Main *bmain,
struct Object *ob, struct ModifierData *md);
-void ED_object_modifier_clear(struct Main *bmain, struct Scene *scene, struct Object *ob);
+void ED_object_modifier_clear(struct Main *bmain, struct Object *ob);
int ED_object_modifier_move_down(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
int ED_object_modifier_move_up(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
int ED_object_modifier_convert(struct ReportList *reports, struct Main *bmain, struct Scene *scene,
@@ -189,7 +191,7 @@ int ED_object_modifier_apply(struct ReportList *reports, struct Scene *scene,
struct Object *ob, struct ModifierData *md, int mode);
int ED_object_modifier_copy(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
-int ED_object_iter_other(struct Main *bmain, struct Object *orig_ob, int include_orig,
+int ED_object_iter_other(struct Main *bmain, struct Object *orig_ob, const bool include_orig,
int (*callback)(struct Object *ob, void *callback_data),
void *callback_data);
diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h
index dee97c7882a..f9516f255cf 100644
--- a/source/blender/editors/include/ED_particle.h
+++ b/source/blender/editors/include/ED_particle.h
@@ -58,10 +58,10 @@ void PE_hide_keys_time(struct Scene *scene, struct PTCacheEdit *edit, float cfra
void PE_update_object(struct Scene *scene, struct Object *ob, int useflag);
/* selection tools */
-int PE_mouse_particles(struct bContext *C, const int mval[2], int extend, int deselect, int toggle);
-int PE_border_select(struct bContext *C, struct rcti *rect, int select, int extend);
+int PE_mouse_particles(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
+int PE_border_select(struct bContext *C, struct rcti *rect, bool select, bool extend);
int PE_circle_select(struct bContext *C, int selecting, const int mval[2], float rad);
-int PE_lasso_select(struct bContext *C, const int mcords[][2], const short moves, short extend, short select);
+int PE_lasso_select(struct bContext *C, const int mcords[][2], const short moves, bool extend, bool select);
void PE_deselect_all_visible(struct PTCacheEdit *edit);
/* undo */
diff --git a/source/blender/editors/include/ED_physics.h b/source/blender/editors/include/ED_physics.h
index cd9ddd3d7d1..192bcd8f712 100644
--- a/source/blender/editors/include/ED_physics.h
+++ b/source/blender/editors/include/ED_physics.h
@@ -32,13 +32,26 @@
#ifndef __ED_PHYSICS_H__
#define __ED_PHYSICS_H__
+struct bContext;
+struct wmOperator;
struct wmKeyConfig;
+struct Scene;
+struct Object;
+
/* particle_edit.c */
int PE_poll(struct bContext *C);
int PE_hair_poll(struct bContext *C);
int PE_poll_view3d(struct bContext *C);
+/* rigidbody_object.c */
+void ED_rigidbody_ob_add(struct wmOperator *op, struct Scene *scene, struct Object *ob, int type);
+void ED_rigidbody_ob_remove(struct Scene *scene, struct Object *ob);
+
+/* rigidbody_constraint.c */
+void ED_rigidbody_con_add(struct wmOperator *op, struct Scene *scene, struct Object *ob, int type);
+void ED_rigidbody_con_remove(struct Scene *scene, struct Object *ob);
+
/* operators */
void ED_operatortypes_physics(void);
void ED_keymap_physics(struct wmKeyConfig *keyconf);
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 860d176ffb3..d073eaa5607 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -64,12 +64,13 @@ void ED_region_panels(const struct bContext *C, struct ARegion *ar, int verti
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 region_scissor_winrct(struct ARegion *ar, struct rcti *winrct);
void ED_region_info_draw(struct ARegion *ar, const char *text, int block, float alpha);
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);
+
/* spaces */
-void ED_spacetypes_init(void);
void ED_spacetypes_keymap(struct wmKeyConfig *keyconf);
int ED_area_header_switchbutton(const struct bContext *C, struct uiBlock *block, int yco);
int ED_area_header_standardbuttons(const struct bContext *C, struct uiBlock *block, int yco);
diff --git a/source/blender/editors/include/ED_sequencer.h b/source/blender/editors/include/ED_sequencer.h
index 84fd5332316..21477a72014 100644
--- a/source/blender/editors/include/ED_sequencer.h
+++ b/source/blender/editors/include/ED_sequencer.h
@@ -31,13 +31,15 @@ struct Scene;
struct Sequence;
struct SpaceSeq;
-void ED_sequencer_select_sequence_single(struct Scene *scene, struct Sequence *seq, int deselect_all);
+void ED_sequencer_select_sequence_single(struct Scene *scene, struct Sequence *seq, bool deselect_all);
void ED_sequencer_deselect_all(struct Scene *scene);
int ED_space_sequencer_maskedit_mask_poll(struct bContext *C);
int ED_space_sequencer_check_show_maskedit(struct SpaceSeq *sseq, struct Scene *scene);
int ED_space_sequencer_maskedit_poll(struct bContext *C);
+int ED_space_sequencer_check_show_imbuf(struct SpaceSeq *sseq);
+
void ED_operatormacros_sequencer(void);
#endif /* __ED_SEQUENCER_H__ */
diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h
index c8521cb194a..a40cf90f7ad 100644
--- a/source/blender/editors/include/ED_space_api.h
+++ b/source/blender/editors/include/ED_space_api.h
@@ -34,6 +34,8 @@
struct ARegionType;
struct bContext;
+void ED_spacetypes_init(void);
+
/* the pluginnable API for export to editors */
/* calls for registering default spaces */
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index 03c1dd5a86d..d43582fa8d1 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -52,7 +52,7 @@ void transform_operatortypes(void);
/* ******************** Macros & Prototypes *********************** */
/* MODE AND NUMINPUT FLAGS */
-enum {
+enum TfmMode {
TFM_INIT = -1,
TFM_DUMMY,
TFM_TRANSLATION,
@@ -83,8 +83,9 @@ enum {
TFM_BWEIGHT,
TFM_ALIGN,
TFM_EDGE_SLIDE,
+ TFM_VERT_SLIDE,
TFM_SEQ_SLIDE
-} TfmMode;
+};
/* TRANSFORM CONTEXTS */
#define CTX_NONE 0
@@ -124,7 +125,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], int activeOnly);
+void ED_getTransformOrientationMatrix(const struct bContext *C, float orientation_mat[3][3], const bool activeOnly);
struct EnumPropertyItem *BIF_enumTransformOrientation(struct bContext *C);
const char *BIF_menustringTransformOrientation(const struct bContext *C, const char *title); /* the returned value was allocated and needs to be freed after use */
@@ -150,7 +151,7 @@ void Transform_Properties(struct wmOperatorType *ot, int flags);
/* view3d manipulators */
-int BIF_do_manipulator(struct bContext *C, struct wmEvent *event, struct wmOperator *op);
+int BIF_do_manipulator(struct bContext *C, const struct wmEvent *event, struct wmOperator *op);
void BIF_draw_manipulator(const struct bContext *C);
/* Snapping */
@@ -176,12 +177,12 @@ typedef enum SnapMode {
#define SNAP_MIN_DISTANCE 30
-int peelObjectsTransForm(struct TransInfo *t, struct ListBase *depth_peels, const float mval[2], SnapMode mode);
-int peelObjectsContext(struct bContext *C, struct ListBase *depth_peels, const float mval[2], SnapMode mode);
-int snapObjectsTransform(struct TransInfo *t, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode);
-int snapObjectsContext(struct bContext *C, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode);
-int snapNodesTransform(struct TransInfo *t, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode);
-int snapNodesContext(struct bContext *C, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode);
+bool peelObjectsTransForm(struct TransInfo *t, struct ListBase *depth_peels, const float mval[2], SnapMode mode);
+bool peelObjectsContext(struct bContext *C, struct ListBase *depth_peels, const float mval[2], SnapMode mode);
+bool snapObjectsTransform(struct TransInfo *t, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode);
+bool snapObjectsContext(struct bContext *C, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode);
+bool snapNodesTransform(struct TransInfo *t, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode);
+bool snapNodesContext(struct bContext *C, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode);
#endif
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index e3d14fb4aac..81f49b4e1f8 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -39,7 +39,6 @@ struct BMVert;
struct BPoint;
struct Base;
struct BezTriple;
-struct BezTriple;
struct BoundBox;
struct EditBone;
struct ImBuf;
@@ -47,7 +46,6 @@ struct MVert;
struct Main;
struct MetaElem;
struct Nurb;
-struct Nurb;
struct Object;
struct RegionView3D;
struct Scene;
@@ -81,10 +79,11 @@ typedef struct ViewDepths {
float *depths;
double depth_range[2];
- char damaged;
+ bool damaged;
} ViewDepths;
float *give_cursor(struct Scene *scene, struct View3D *v3d);
+void ED_view3d_cursor3d_position(struct bContext *C, float fp[3], const int mval[2]);
void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], const float dist);
void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist);
@@ -104,9 +103,10 @@ void ED_view3d_depth_tag_update(struct RegionView3D *rv3d);
typedef enum {
V3D_PROJ_RET_OK = 0,
V3D_PROJ_RET_CLIP_NEAR = 1, /* can't avoid this when in perspective mode, (can't avoid) */
- V3D_PROJ_RET_CLIP_BB = 2, /* bounding box clip - RV3D_CLIPPING */
- V3D_PROJ_RET_CLIP_WIN = 3, /* outside window bounds */
- V3D_PROJ_RET_OVERFLOW = 4 /* outside range (mainly for short), (can't avoid) */
+ V3D_PROJ_RET_CLIP_ZERO = 2, /* so close to zero we can't apply a perspective matrix usefully */
+ V3D_PROJ_RET_CLIP_BB = 3, /* bounding box clip - RV3D_CLIPPING */
+ V3D_PROJ_RET_CLIP_WIN = 4, /* outside window bounds */
+ V3D_PROJ_RET_OVERFLOW = 5 /* outside range (mainly for short), (can't avoid) */
} eV3DProjStatus;
/* some clipping tests are optional */
@@ -114,15 +114,23 @@ typedef enum {
V3D_PROJ_TEST_NOP = 0,
V3D_PROJ_TEST_CLIP_BB = (1 << 0),
V3D_PROJ_TEST_CLIP_WIN = (1 << 1),
+ V3D_PROJ_TEST_CLIP_NEAR = (1 << 2),
+ V3D_PROJ_TEST_CLIP_ZERO = (1 << 3)
} eV3DProjTest;
-#define V3D_PROJ_TEST_CLIP_DEFAULT (V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN)
-#define V3D_PROJ_TEST_ALL (V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN)
+#define V3D_PROJ_TEST_CLIP_DEFAULT \
+ (V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR)
+#define V3D_PROJ_TEST_ALL \
+ (V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_ZERO)
/* view3d_iterators.c */
/* foreach iterators */
+void meshobject_foreachScreenVert(
+ struct ViewContext *vc,
+ void (*func)(void *userData, struct MVert *eve, const float screen_co[2], int index),
+ void *userData, const eV3DProjTest clip_flag);
void mesh_foreachScreenVert(
struct ViewContext *vc,
void (*func)(void *userData, struct BMVert *eve, const float screen_co[2], int index),
@@ -164,52 +172,60 @@ void pose_foreachScreenBone(
/* view3d_project.c */
-void ED_view3d_project_float_v2_m4(const struct ARegion *a, const float co[3], float r_co[2], float mat[4][4]);
-void ED_view3d_project_float_v3_m4(struct ARegion *a, const float co[3], float r_co[3], float mat[4][4]);
+void ED_view3d_project_float_v2_m4(const struct ARegion *ar, const float co[3], float r_co[2], float mat[4][4]);
+void ED_view3d_project_float_v3_m4(const struct ARegion *ar, const float co[3], float r_co[3], float mat[4][4]);
-eV3DProjStatus ED_view3d_project_base(struct ARegion *ar, struct Base *base);
+eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct Base *base);
/* *** short *** */
-eV3DProjStatus ED_view3d_project_short_ex(struct ARegion *ar, float perspmat[4][4], const int is_local,
+eV3DProjStatus ED_view3d_project_short_ex(const struct ARegion *ar, float perspmat[4][4], const bool is_local,
const float co[3], short r_co[2], const eV3DProjTest flag);
-eV3DProjStatus ED_view3d_project_short_global(struct ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag);
-eV3DProjStatus ED_view3d_project_short_object(struct ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag);
+eV3DProjStatus ED_view3d_project_short_global(const struct ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag);
+eV3DProjStatus ED_view3d_project_short_object(const struct ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag);
/* *** int *** */
-eV3DProjStatus ED_view3d_project_int_ex(struct ARegion *ar, float perspmat[4][4], const int is_local,
+eV3DProjStatus ED_view3d_project_int_ex(const struct ARegion *ar, float perspmat[4][4], const bool is_local,
const float co[3], int r_co[2], const eV3DProjTest flag);
-eV3DProjStatus ED_view3d_project_int_global(struct ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag);
-eV3DProjStatus ED_view3d_project_int_object(struct ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag);
+eV3DProjStatus ED_view3d_project_int_global(const struct ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag);
+eV3DProjStatus ED_view3d_project_int_object(const struct ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag);
/* *** float *** */
-eV3DProjStatus ED_view3d_project_float_ex(struct ARegion *ar, float perspmat[4][4], const int is_local,
- const float co[3], float r_co[2], const eV3DProjTest flag);
-eV3DProjStatus ED_view3d_project_float_global(struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag);
-eV3DProjStatus ED_view3d_project_float_object(struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag);
-
-int initgrabz(struct RegionView3D *rv3d, float x, float y, float z);
-void ED_view3d_win_to_ray(struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_normal[3]);
-void ED_view3d_global_to_vector(struct RegionView3D *rv3d, const float coord[3], float vec[3]);
-void ED_view3d_win_to_3d(struct ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]);
-void ED_view3d_win_to_delta(struct ARegion *ar, const float mval[2], float out[3]);
-void ED_view3d_win_to_vector(struct ARegion *ar, const float mval[2], float out[3]);
-void ED_view3d_win_to_segment(struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]);
-int ED_view3d_win_to_segment_clip(struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]);
-void ED_view3d_ob_project_mat_get(struct RegionView3D *v3d, struct Object *ob, float pmat[4][4]);
+eV3DProjStatus ED_view3d_project_float_ex(const struct ARegion *ar, float perspmat[4][4], const bool is_local,
+ const float co[3], float r_co[2], const eV3DProjTest flag);
+eV3DProjStatus ED_view3d_project_float_global(const struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag);
+eV3DProjStatus ED_view3d_project_float_object(const struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag);
+
+float ED_view3d_calc_zfac(const struct RegionView3D *rv3d, const float co[3], bool *r_flip);
+void ED_view3d_win_to_ray(const struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_normal[3]);
+void ED_view3d_global_to_vector(const struct RegionView3D *rv3d, const float coord[3], float vec[3]);
+void ED_view3d_win_to_3d(const struct ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]);
+void ED_view3d_win_to_delta(const struct ARegion *ar, const float mval[2], float out[3], const float zfac);
+void ED_view3d_win_to_vector(const struct ARegion *ar, const float mval[2], float out[3]);
+void ED_view3d_win_to_segment(const struct ARegion *ar, struct View3D *v3d, const float mval[2],
+ float ray_start[3], float ray_end[3]);
+bool ED_view3d_win_to_segment_clip(const struct ARegion *ar, struct View3D *v3d, const float mval[2],
+ float ray_start[3], float ray_end[3]);
+void ED_view3d_ob_project_mat_get(const struct RegionView3D *v3d, struct Object *ob, float pmat[4][4]);
void ED_view3d_unproject(struct bglMats *mats, float out[3], const float x, const float y, const float z);
/* end */
-int ED_view3d_clip_range_get(struct View3D *v3d, struct RegionView3D *rv3d, float *clipsta, float *clipend);
-int ED_view3d_viewplane_get(struct View3D *v3d, struct RegionView3D *rv3d, int winxi, int winyi, struct rctf *viewplane, float *clipsta, float *clipend);
-void ED_view3d_calc_camera_border(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, struct RegionView3D *rv3d, struct rctf *viewborder_r, short no_shift);
-void ED_view3d_calc_camera_border_size(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, struct RegionView3D *rv3d, float size_r[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);
+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_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]);
-int ED_view3d_clipping_test(struct RegionView3D *rv3d, const float vec[3], const int is_local);
+bool ED_view3d_clipping_test(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);
@@ -230,13 +246,13 @@ unsigned int view3d_sample_backbuf_rect(struct ViewContext *vc, const int mval[2
unsigned int view3d_sample_backbuf(struct ViewContext *vc, int x, int y);
/* draws and does a 4x4 sample */
-int ED_view3d_autodist(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, const int mval[2], float mouse_worldloc[3]);
+bool ED_view3d_autodist(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, const int mval[2], float mouse_worldloc[3], bool alphaoverride);
/* only draw so ED_view3d_autodist_simple can be called many times after */
-int ED_view3d_autodist_init(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, int mode);
-int ED_view3d_autodist_simple(struct ARegion *ar, const int mval[2], float mouse_worldloc[3], int margin, float *force_depth);
-int ED_view3d_autodist_depth(struct ARegion *ar, const int mval[2], int margin, float *depth);
-int ED_view3d_autodist_depth_seg(struct ARegion *ar, const int mval_sta[2], const int mval_end[2], int margin, float *depth);
+void ED_view3d_autodist_init(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, int mode);
+bool ED_view3d_autodist_simple(struct ARegion *ar, const int mval[2], float mouse_worldloc[3], int margin, float *force_depth);
+bool ED_view3d_autodist_depth(struct ARegion *ar, const int mval[2], int margin, float *depth);
+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
@@ -245,15 +261,16 @@ short view3d_opengl_select(struct ViewContext *vc, unsigned int *buffer, unsigne
void view3d_set_viewcontext(struct bContext *C, struct ViewContext *vc);
void view3d_operator_needs_opengl(const struct bContext *C);
void view3d_region_operator_needs_opengl(struct wmWindow *win, struct ARegion *ar);
-int view3d_get_view_aligned_coordinate(struct ViewContext *vc, float fp[3], const int mval[2], const short do_fallback);
+bool view3d_get_view_aligned_coordinate(struct ARegion *ar, float fp[3], const int mval[2], const bool do_fallback);
+void view3d_opengl_read_pixels(struct ARegion *ar, int x, int y, int w, int h, int format, int type, void *data);
void view3d_get_transformation(const struct ARegion *ar, struct RegionView3D *rv3d, struct Object *ob, struct bglMats *mats);
/* XXX should move to BLI_math */
-int edge_inside_circle(const float cent[2], float radius, const float screen_co_a[2], const float screen_co_b[2]);
+bool edge_inside_circle(const float cent[2], float radius, const float screen_co_a[2], const float screen_co_b[2]);
/* get 3d region from context, also if mouse is in header or toolbar */
struct RegionView3D *ED_view3d_context_rv3d(struct bContext *C);
-int ED_view3d_context_user_region(struct bContext *C, struct View3D **v3d_r, struct ARegion **ar_r);
+bool ED_view3d_context_user_region(struct bContext *C, struct View3D **r_v3d, struct ARegion **r_ar);
int ED_operator_rv3d_user_region_poll(struct bContext *C);
void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d);
@@ -261,32 +278,32 @@ void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d);
int ED_view3d_scene_layer_set(int lay, const int *values, int *active);
-int ED_view3d_context_activate(struct bContext *C);
+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], int do_bgpic, int colormanage_background);
+ int winx, int winy, float viewmat[4][4], float winmat[4][4], bool do_bgpic);
struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, unsigned int flag,
- int draw_background, int colormanage_background, char err_out[256]);
+ bool draw_background, int alpha_mode, char err_out[256]);
struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Scene *scene, struct Object *camera, int width, int height, unsigned int flag, int drawtype,
- int draw_background, int colormanage_background, char err_out[256]);
-
+ 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]);
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, short do_clip);
+void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip);
void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4]);
-int ED_view3d_lock(struct RegionView3D *rv3d);
+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_object_datamask(struct Scene *scene);
/* camera lock functions */
-int ED_view3d_camera_lock_check(struct View3D *v3d, struct RegionView3D *rv3d);
+bool ED_view3d_camera_lock_check(struct View3D *v3d, struct RegionView3D *rv3d);
/* copy the camera to the view before starting a view transformation */
void ED_view3d_camera_lock_init(struct View3D *v3d, struct RegionView3D *rv3d);
/* copy the view to the camera, return TRUE if */
-int ED_view3d_camera_lock_sync(struct View3D *v3d, struct RegionView3D *rv3d);
+bool ED_view3d_camera_lock_sync(struct View3D *v3d, struct RegionView3D *rv3d);
void ED_view3D_lock_clear(struct View3D *v3d);
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 99f7f0856b3..2e2842210c2 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -699,9 +699,7 @@ DEF_ICON(RNDCURVE)
DEF_ICON(PROP_OFF)
DEF_ICON(PROP_ON)
DEF_ICON(PROP_CON)
-#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK212)
-#endif
+DEF_ICON(SCULPT_DYNTOPO)
DEF_ICON(PARTICLE_POINT)
DEF_ICON(PARTICLE_TIP)
DEF_ICON(PARTICLE_PATH)
@@ -750,10 +748,8 @@ DEF_ICON(PASTEFLIPDOWN)
DEF_ICON(BLANK230)
#endif
DEF_ICON(SNAP_SURFACE)
-#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK232)
- DEF_ICON(BLANK233)
-#endif
+DEF_ICON(AUTOMERGE_ON)
+DEF_ICON(AUTOMERGE_OFF)
DEF_ICON(RETOPO)
DEF_ICON(UV_VERTEXSEL)
DEF_ICON(UV_EDGESEL)
@@ -992,11 +988,37 @@ DEF_ICON(BRUSH_THUMB)
DEF_ICON(BRUSH_ROTATE)
DEF_ICON(BRUSH_VERTEXDRAW)
+ /* Matcaps */
+DEF_ICON(MATCAP_01)
+DEF_ICON(MATCAP_02)
+DEF_ICON(MATCAP_03)
+DEF_ICON(MATCAP_04)
+DEF_ICON(MATCAP_05)
+DEF_ICON(MATCAP_06)
+DEF_ICON(MATCAP_07)
+DEF_ICON(MATCAP_08)
+DEF_ICON(MATCAP_09)
+DEF_ICON(MATCAP_10)
+DEF_ICON(MATCAP_11)
+DEF_ICON(MATCAP_12)
+DEF_ICON(MATCAP_13)
+DEF_ICON(MATCAP_14)
+DEF_ICON(MATCAP_15)
+DEF_ICON(MATCAP_16)
+DEF_ICON(MATCAP_17)
+DEF_ICON(MATCAP_18)
+DEF_ICON(MATCAP_19)
+DEF_ICON(MATCAP_20)
+DEF_ICON(MATCAP_21)
+DEF_ICON(MATCAP_22)
+DEF_ICON(MATCAP_23)
+DEF_ICON(MATCAP_24)
+
/* vector icons, VICO_ prefix added */
DEF_VICO(VIEW3D_VEC)
DEF_VICO(EDIT_VEC)
-DEF_VICO(EDITMODE_DEHLT)
-DEF_VICO(EDITMODE_HLT)
+DEF_VICO(EDITMODE_VEC_DEHLT)
+DEF_VICO(EDITMODE_VEC_HLT)
DEF_VICO(DISCLOSURE_TRI_RIGHT_VEC)
DEF_VICO(DISCLOSURE_TRI_DOWN_VEC)
DEF_VICO(MOVE_UP_VEC)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 2dc552d0fce..3b4415703d5 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -42,6 +42,7 @@ struct ID;
struct Main;
struct ListBase;
struct ARegion;
+struct ARegionType;
struct ScrArea;
struct wmWindow;
struct wmWindowManager;
@@ -56,6 +57,7 @@ struct PropertyRNA;
struct ReportList;
struct rcti;
struct rctf;
+struct uiList;
struct uiStyle;
struct uiFontStyle;
struct uiWidgetColors;
@@ -83,6 +85,9 @@ typedef struct uiLayout uiLayout;
#define UI_MAX_DRAW_STR 400
#define UI_MAX_NAME_STR 128
+/* use for clamping popups within the screen */
+#define UI_SCREEN_MARGIN 10
+
/* uiBlock->dt */
#define UI_EMBOSS 0 /* use widget style for drawing */
#define UI_EMBOSSN 1 /* Nothing, only icon and/or text */
@@ -175,12 +180,12 @@ typedef struct uiLayout uiLayout;
/* uiBut->drawflag */
#define UI_BUT_DRAW_ENUM_ARROWS (1 << 0) /* draw enum-like up/down arrows for button */
-/* scale fixed button widths by this to account for DPI
- * 8.4852 == sqrtf(72.0f)) */
-#define UI_DPI_FAC (sqrtf((float)U.dpi) / 8.48528137423857f)
-#define UI_DPI_ICON_FAC (((float)U.dpi) / 72.0f)
+/* scale fixed button widths by this to account for DPI */
+
+#define UI_DPI_FAC ((U.pixelsize * (float)U.dpi) / 72.0f)
+#define UI_DPI_WINDOW_FAC (((float)U.dpi) / 72.0f)
/* 16 to copy ICON_DEFAULT_HEIGHT */
-#define UI_DPI_ICON_SIZE ((float)16 * UI_DPI_ICON_FAC)
+#define UI_DPI_ICON_SIZE ((float)16 * UI_DPI_FAC)
/* Button types, bits stored in 1 value... and a short even!
* - bits 0-4: bitnr (0-31)
@@ -218,7 +223,7 @@ typedef enum {
NUMSLI = (14 << 9),
COLOR = (15 << 9),
IDPOIN = (16 << 9),
- HSVSLI = (17 << 9),
+ /* HSVSLI = (17 << 9), */ /* UNUSED */
SCROLL = (18 << 9),
BLOCK = (19 << 9),
BUTM = (20 << 9),
@@ -253,7 +258,9 @@ typedef enum {
HISTOGRAM = (48 << 9),
WAVEFORM = (49 << 9),
VECTORSCOPE = (50 << 9),
- PROGRESSBAR = (51 << 9)
+ PROGRESSBAR = (51 << 9),
+ SEARCH_MENU_UNLINK = (52 << 9),
+ NODESOCKET = (53 << 9)
} eButType;
#define BUTTYPE (63 << 9)
@@ -287,7 +294,7 @@ void uiDrawBoxVerticalShade(int mode, float minx, float miny, float maxx, float
#define UI_SCROLL_PRESSED 1
#define UI_SCROLL_ARROWS 2
#define UI_SCROLL_NO_OUTLINE 4
-void uiWidgetScrollDraw(struct uiWidgetColors *wcol, struct rcti *rect, struct rcti *slider, int state);
+void uiWidgetScrollDraw(struct uiWidgetColors *wcol, const struct rcti *rect, const struct rcti *slider, int state);
/* Callbacks
*
@@ -356,7 +363,7 @@ void uiPupMenuInvoke(struct bContext *C, const char *idname); /* popup registere
* but allow using all button types and creating an own layout. */
typedef uiBlock * (*uiBlockCreateFunc)(struct bContext *C, struct ARegion *ar, void *arg1);
-typedef void (*uiBlockCancelFunc)(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);
@@ -432,6 +439,7 @@ void uiButSetDragValue(uiBut *but);
void uiButSetDragImage(uiBut *but, const char *path, int icon, struct ImBuf *ima, float scale);
int UI_but_active_drop_name(struct bContext *C);
+struct uiBut *ui_but_find_mouse_over(struct ARegion *ar, int x, int y);
void uiButSetFlag(uiBut *but, int flag);
void uiButClearFlag(uiBut *but, int flag);
@@ -442,6 +450,8 @@ void uiButClearDrawFlag(uiBut *but, int flag);
/* special button case, only draw it when used actively, for outliner etc */
int uiButActiveOnly(const struct bContext *C, uiBlock *block, uiBut *but);
+void uiButExecute(const struct bContext *C, uiBut *but);
+
/* Buttons
*
@@ -598,7 +608,7 @@ uiBut *uiDefHotKeyevtButS(uiBlock *block, int retval, const char *str, int x, in
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 *uiDefAutoButR(uiBlock *block, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, const char *name, int icon, int x1, int y1, int x2, int y2);
-int uiDefAutoButsRNA(uiLayout *layout, struct PointerRNA *ptr, int (*check_prop)(struct PointerRNA *, struct PropertyRNA *), const char label_align);
+int uiDefAutoButsRNA(uiLayout *layout, struct PointerRNA *ptr, bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *), const char label_align);
/* Links
*
@@ -659,6 +669,7 @@ void uiDrawPanels(const struct bContext *C, struct ARegion *ar);
struct Panel *uiBeginPanel(struct ScrArea *sa, struct ARegion *ar, uiBlock *block, struct PanelType *pt, int *open);
void uiEndPanel(uiBlock *block, int width, int height);
+void uiScalePanels(struct ARegion *ar, float new_width);
/* Handlers
*
@@ -751,7 +762,7 @@ void uiLayoutSetContextPointer(uiLayout *layout, const char *name, struct Pointe
void uiLayoutContextCopy(uiLayout *layout, struct bContextStore *context);
const char *uiLayoutIntrospect(uiLayout *layout); // XXX - testing
void uiLayoutOperatorButs(const struct bContext *C, struct uiLayout *layout, struct wmOperator *op,
- int (*check_prop)(struct PointerRNA *, struct PropertyRNA *),
+ bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *),
const char label_align, const short flag);
struct MenuType *uiButGetMenuType(uiBut *but);
@@ -779,7 +790,7 @@ uiLayout *uiLayoutRow(uiLayout *layout, int align);
uiLayout *uiLayoutColumn(uiLayout *layout, int align);
uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align);
uiLayout *uiLayoutBox(uiLayout *layout);
-uiLayout *uiLayoutListBox(uiLayout *layout, struct PointerRNA *ptr, struct PropertyRNA *prop,
+uiLayout *uiLayoutListBox(uiLayout *layout, struct uiList *ui_list, struct PointerRNA *ptr, struct PropertyRNA *prop,
struct PointerRNA *actptr, struct PropertyRNA *actprop);
uiLayout *uiLayoutAbsolute(uiLayout *layout, int align);
uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align);
@@ -804,6 +815,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, struct bContext *C, struct Pointe
uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr);
void uiTemplatePreview(uiLayout *layout, struct ID *id, int show_buttons, struct ID *parent, struct MTex *slot);
void uiTemplateColorRamp(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int expand);
+void uiTemplateIconView(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
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);
@@ -824,8 +836,14 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C);
void uiTemplateTextureImage(uiLayout *layout, struct bContext *C, struct Tex *tex);
void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C);
void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr);
-
-void uiTemplateList(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, struct PointerRNA *activeptr, const char *activeprop, const char *prop_list, int rows, int maxrows, int type);
+void uiTemplateComponentMenu(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name);
+void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color);
+
+/* Default UIList class name, keep in sync with its declaration in bl_ui/__init__.py */
+#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);
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);
@@ -885,7 +903,7 @@ void uiIDContextProperty(struct bContext *C, struct PointerRNA *ptr, struct Prop
/* Styled text draw */
void uiStyleFontSet(struct uiFontStyle *fs);
-void uiStyleFontDrawExt(struct uiFontStyle *fs, struct rcti *rect, const char *str,
+void uiStyleFontDrawExt(struct uiFontStyle *fs, const struct rcti *rect, const char *str,
float *r_xofs, float *r_yofs);
void uiStyleFontDraw(struct uiFontStyle *fs, struct rcti *rect, const char *str);
void uiStyleFontDrawRotated(struct uiFontStyle *fs, struct rcti *rect, const char *str);
@@ -893,7 +911,10 @@ void uiStyleFontDrawRotated(struct uiFontStyle *fs, struct rcti *rect, const cha
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);
-uiStyle *UI_GetStyle(void);
+
+uiStyle *UI_GetStyle(void); /* use for fonts etc */
+uiStyle *UI_GetStyleDraw(void); /* DPI scaled settings for drawing */
+
/* linker workaround ack! */
void UI_template_fix_linking(void);
@@ -901,5 +922,4 @@ void UI_template_fix_linking(void);
int UI_editsource_enable_check(void);
void UI_editsource_active_but_test(uiBut *but);
-#endif /* __UI_INTERFACE_H__ */
-
+#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 aa94bdec724..10026bbd50f 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -32,12 +32,15 @@
#ifndef __UI_INTERFACE_ICONS_H__
#define __UI_INTERFACE_ICONS_H__
+struct bContext;
struct Image;
struct ImBuf;
struct World;
struct Tex;
struct Lamp;
struct Material;
+struct PreviewImage;
+struct PointerRNA;
typedef struct IconFile {
struct IconFile *next, *prev;
@@ -74,5 +77,8 @@ void UI_icons_free_drawinfo(void *drawinfo);
struct ListBase *UI_iconfile_list(void);
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, int big);
#endif /* __UI_INTERFACE_ICONS_H__ */
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index f4e921e2fa4..050e9c81f2a 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -64,10 +64,11 @@ enum {
TH_HEADER_TEXT,
TH_HEADER_TEXT_HI,
- /* float panels */
- TH_PANEL,
- TH_PANEL_TEXT,
- TH_PANEL_TEXT_HI,
+ /* panels */
+ TH_PANEL_HEADER,
+ TH_PANEL_BACK,
+ TH_PANEL_SHOW_HEADER,
+ TH_PANEL_SHOW_BACK,
TH_BUTBACK,
TH_BUTBACK_TEXT,
@@ -86,6 +87,7 @@ enum {
TH_TRANSFORM,
TH_VERTEX,
TH_VERTEX_SELECT,
+ TH_VERTEX_UNREFERENCED,
TH_VERTEX_SIZE,
TH_OUTLINE_WIDTH,
TH_EDGE,
@@ -121,9 +123,12 @@ enum {
TH_SYNTAX_B,
TH_SYNTAX_V,
+ TH_SYNTAX_R,
TH_SYNTAX_C,
TH_SYNTAX_L,
+ TH_SYNTAX_D,
TH_SYNTAX_N,
+ TH_SYNTAX_S,
TH_BONE_SOLID,
TH_BONE_POSE,
@@ -139,16 +144,20 @@ enum {
TH_NODE,
TH_NODE_IN_OUT,
+ TH_NODE_INTERFACE,
TH_NODE_OPERATOR,
TH_NODE_CONVERTOR,
TH_NODE_GROUP,
TH_NODE_FRAME,
+ TH_NODE_MATTE,
+ TH_NODE_DISTORT,
TH_CONSOLE_OUTPUT,
TH_CONSOLE_INPUT,
TH_CONSOLE_INFO,
TH_CONSOLE_ERROR,
TH_CONSOLE_CURSOR,
+ TH_CONSOLE_SELECT,
TH_SEQ_MOVIE,
TH_SEQ_MOVIECLIP,
@@ -199,6 +208,9 @@ enum {
TH_STITCH_PREVIEW_UNSTITCHABLE,
TH_STITCH_PREVIEW_ACTIVE,
+ TH_FREESTYLE_EDGE_MARK,
+ TH_FREESTYLE_FACE_MARK,
+
TH_MATCH, /* highlight color for search matches */
TH_SELECT_HIGHLIGHT, /* highlight color for selected outliner item */
@@ -219,7 +231,11 @@ enum {
TH_AXIS_X, /* X/Y/Z Axis */
TH_AXIS_Y,
- TH_AXIS_Z
+ TH_AXIS_Z,
+
+ TH_LOW_GRAD,
+ TH_HIGH_GRAD,
+ TH_SHOW_BACK_GRAD
};
/* XXX WARNING: previous is saved in file, so do not change order! */
@@ -286,9 +302,12 @@ void UI_SetTheme(int spacetype, int regionid);
// get current theme
struct bTheme *UI_GetTheme(void);
+// return shadow width outside menus and popups */
+int UI_ThemeMenuShadowWidth(void);
+
/* only for buttons in theme editor! */
const unsigned char *UI_ThemeGetColorPtr(struct bTheme *btheme, int spacetype, int colorid);
void UI_make_axis_color(const unsigned char *src_col, unsigned char *dst_col, const char axis);
-#endif /* UI_ICONS_H */
+#endif /* UI_RESOURCES_H */
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 24759fa778a..100e72e18ed 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -47,7 +47,7 @@
* and settings for a View2D region, and that set of settings is used in more
* than one specific place
*/
-enum {
+enum eView2D_CommonViewTypes {
/* custom view type (region has defined all necessary flags already) */
V2D_COMMONVIEW_CUSTOM = -1,
/* standard (only use this when setting up a new view, as a sensible base for most settings) */
@@ -60,7 +60,7 @@ enum {
V2D_COMMONVIEW_HEADER,
/* ui region containing panels */
V2D_COMMONVIEW_PANELS_UI
-} eView2D_CommonViewTypes;
+};
/* ---- Defines for Scroller/Grid Arguments ----- */
@@ -68,7 +68,7 @@ enum {
#define V2D_ARG_DUMMY -1
/* Grid units */
-enum {
+enum eView2D_Units {
/* for drawing time */
V2D_UNIT_SECONDS = 0,
V2D_UNIT_FRAMES,
@@ -79,16 +79,16 @@ enum {
V2D_UNIT_DEGREES,
V2D_UNIT_TIME,
V2D_UNIT_SECONDSSEQ
-} eView2D_Units;
+};
/* clamping of grid values to whole numbers */
-enum {
+enum eView2D_Clamp {
V2D_GRID_NOCLAMP = 0,
V2D_GRID_CLAMP
-} eView2D_Clamp;
+};
/* flags for grid-lines to draw */
-enum {
+enum eView2D_Gridlines {
V2D_HORIZONTAL_LINES = (1 << 0),
V2D_VERTICAL_LINES = (1 << 1),
V2D_HORIZONTAL_AXIS = (1 << 2),
@@ -97,16 +97,16 @@ enum {
V2D_GRIDLINES_MAJOR = (V2D_VERTICAL_LINES | V2D_VERTICAL_AXIS | V2D_HORIZONTAL_LINES | V2D_HORIZONTAL_AXIS),
V2D_GRIDLINES_ALL = (V2D_GRIDLINES_MAJOR | V2D_HORIZONTAL_FINELINES),
-} eView2D_Gridlines;
+};
/* ------ Defines for Scrollers ----- */
/* scroller area */
-#define V2D_SCROLL_HEIGHT 17
-#define V2D_SCROLL_WIDTH 17
+#define V2D_SCROLL_HEIGHT (0.85f * U.widget_unit)
+#define V2D_SCROLL_WIDTH (0.85f * U.widget_unit)
/* scroller 'handles' hotspot radius for mouse */
-#define V2D_SCROLLER_HANDLE_SIZE 12
+#define V2D_SCROLLER_HANDLE_SIZE (0.6f * U.widget_unit)
/* ------ Define for UI_view2d_sync ----- */
@@ -132,6 +132,7 @@ struct View2DScrollers;
struct wmKeyConfig;
struct bScreen;
+struct Scene;
struct ScrArea;
struct ARegion;
struct bContext;
@@ -147,7 +148,6 @@ typedef struct View2DScrollers View2DScrollers;
void UI_view2d_region_reinit(struct View2D *v2d, short type, int winx, int winy);
void UI_view2d_curRect_validate(struct View2D *v2d);
-void UI_view2d_curRect_validate_resize(struct View2D *v2d, int resize);
void UI_view2d_curRect_reset(struct View2D *v2d);
void UI_view2d_sync(struct bScreen *screen, struct ScrArea *sa, struct View2D *v2dcur, int flag);
@@ -167,7 +167,7 @@ View2DGrid *UI_view2d_grid_calc(struct Scene *scene, struct View2D *v2d,
short xunits, short xclamp, short yunits, short yclamp, int winx, int winy);
void UI_view2d_grid_draw(struct View2D *v2d, View2DGrid *grid, int flag);
void UI_view2d_constant_grid_draw(struct View2D *v2d);
-void UI_view2d_multi_grid_draw(struct View2D *v2d, float step, int level_size, int totlevels);
+void UI_view2d_multi_grid_draw(struct View2D *v2d, int colorid, float step, int level_size, int totlevels);
void UI_view2d_grid_size(View2DGrid *grid, float *r_dx, float *r_dy);
void UI_view2d_grid_free(View2DGrid *grid);
@@ -198,6 +198,10 @@ struct View2D *UI_view2d_fromcontext(const struct bContext *C);
struct View2D *UI_view2d_fromcontext_rwin(const struct bContext *C);
void UI_view2d_getscale(struct View2D *v2d, float *x, float *y);
+void UI_view2d_getscale_inverse(struct View2D *v2d, float *x, float *y);
+
+void UI_view2d_getcenter(struct View2D *v2d, float *x, float *y);
+void UI_view2d_setcenter(struct View2D *v2d, float x, float y);
short UI_view2d_mouse_in_scrollers(const struct bContext *C, struct View2D *v2d, int x, int y);
diff --git a/source/blender/editors/interface/SConscript b/source/blender/editors/interface/SConscript
index 2d6d5cd235e..8d277d6cd35 100644
--- a/source/blender/editors/interface/SConscript
+++ b/source/blender/editors/interface/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index ce82e064531..16598511921 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -69,7 +69,6 @@
#include "WM_api.h"
#include "WM_types.h"
#include "wm_subwindow.h"
-#include "wm_window.h"
#include "RNA_access.h"
@@ -232,7 +231,9 @@ static void ui_text_bounds_block(uiBlock *block, float offset)
nextcol = 1;
col++;
}
- else nextcol = 0;
+ else {
+ nextcol = 0;
+ }
bt->rect.xmin = x1addval;
bt->rect.xmax = bt->rect.xmin + i + block->bounds;
@@ -298,9 +299,9 @@ static void ui_centered_bounds_block(const bContext *C, uiBlock *block)
/* note: this is used for the splash where window bounds event has not been
* updated by ghost, get the window bounds from ghost directly */
- // wm_window_get_size(window, &xmax, &ymax);
- wm_window_get_size_ghost(window, &xmax, &ymax);
-
+ xmax = WM_window_pixels_x(window);
+ ymax = WM_window_pixels_y(window);
+
ui_bounds_block(block);
width = BLI_rctf_size_x(&block->rect);
@@ -320,13 +321,15 @@ static void ui_popup_bounds_block(const bContext *C, uiBlock *block, eBlockBound
wmWindow *window = CTX_wm_window(C);
int startx, starty, endx, endy, width, height, oldwidth, oldheight;
int oldbounds, xmax, ymax;
+ const int margin = UI_SCREEN_MARGIN;
oldbounds = block->bounds;
/* compute mouse position with user defined offset */
ui_bounds_block(block);
- wm_window_get_size(window, &xmax, &ymax);
+ xmax = WM_window_pixels_x(window);
+ ymax = WM_window_pixels_y(window);
oldwidth = BLI_rctf_size_x(&block->rect);
oldheight = BLI_rctf_size_y(&block->rect);
@@ -334,7 +337,7 @@ static void ui_popup_bounds_block(const bContext *C, uiBlock *block, eBlockBound
/* first we ensure wide enough text bounds */
if (bounds_calc == UI_BLOCK_BOUNDS_POPUP_MENU) {
if (block->flag & UI_BLOCK_LOOP) {
- block->bounds = 50;
+ block->bounds = 2.5f * UI_UNIT_X;
ui_text_bounds_block(block, block->rect.xmin);
}
}
@@ -356,20 +359,20 @@ static void ui_popup_bounds_block(const bContext *C, uiBlock *block, eBlockBound
startx = window->eventstate->x + block->rect.xmin + (block->mx * width) / oldwidth;
starty = window->eventstate->y + block->rect.ymin + (block->my * height) / oldheight;
- if (startx < 10)
- startx = 10;
- if (starty < 10)
- starty = 10;
+ if (startx < margin)
+ startx = margin;
+ if (starty < margin)
+ starty = margin;
endx = startx + width;
endy = starty + height;
if (endx > xmax) {
- endx = xmax - 10;
+ endx = xmax - margin;
startx = endx - width;
}
- if (endy > ymax - 20) {
- endy = ymax - 20;
+ if (endy > ymax - margin) {
+ endy = ymax - margin;
starty = endy - height;
}
@@ -635,7 +638,7 @@ static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut
/* move button over from oldblock to new block */
BLI_remlink(&oldblock->buttons, oldbut);
- BLI_insertlink(&block->buttons, but, oldbut);
+ BLI_insertlinkafter(&block->buttons, but, oldbut);
oldbut->block = block;
*butpp = oldbut;
@@ -712,6 +715,12 @@ int uiButActiveOnly(const bContext *C, uiBlock *block, uiBut *but)
return 1;
}
+/* simulate button click */
+void uiButExecute(const bContext *C, uiBut *but)
+{
+ ui_button_execute_do((bContext *)C, CTX_wm_region(C), but);
+}
+
/* use to check if we need to disable undo, but don't make any changes
* returns FALSE if undo needs to be disabled. */
static int ui_but_is_rna_undo(uiBut *but)
@@ -927,6 +936,8 @@ void uiEndBlock(const bContext *C, uiBlock *block)
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));
block->oldblock = NULL;
}
@@ -983,7 +994,8 @@ void ui_fontscale(short *points, float aspect)
float pointsf = *points;
/* for some reason scaling fonts goes too fast compared to widget size */
- aspect = sqrt(aspect);
+ /* XXX not true anymore? (ton) */
+ //aspect = sqrt(aspect);
pointsf /= aspect;
if (aspect > 1.0f)
@@ -996,11 +1008,11 @@ void ui_fontscale(short *points, float aspect)
/* project button or block (but==NULL) to pixels in regionspace */
static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, uiBut *but)
{
- rctf rectf = (but)? but->rect: block->rect;
+ rctf rectf = (but) ? but->rect : block->rect;
ui_block_to_window_fl(ar, block, &rectf.xmin, &rectf.ymin);
ui_block_to_window_fl(ar, block, &rectf.xmax, &rectf.ymax);
-
+
rectf.xmin -= ar->winrct.xmin;
rectf.ymin -= ar->winrct.ymin;
rectf.xmax -= ar->winrct.xmin;
@@ -1015,7 +1027,7 @@ static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, u
/* uses local copy of style, to scale things down, and allow widgets to change stuff */
void uiDrawBlock(const bContext *C, uiBlock *block)
{
- uiStyle style = *UI_GetStyle(); /* XXX pass on as arg */
+ uiStyle style = *UI_GetStyleDraw(); /* XXX pass on as arg */
ARegion *ar;
uiBut *but;
rcti rect;
@@ -1087,34 +1099,29 @@ void uiDrawBlock(const bContext *C, uiBlock *block)
/* ************* EVENTS ************* */
-static void ui_is_but_sel(uiBut *but, double *value)
+int ui_is_but_push_ex(uiBut *but, double *value)
{
- short is_push = 0; /* (0 == UNSELECT), (1 == SELECT), (2 == DO-NOHING) */
- short is_true = TRUE;
-
- if (ELEM3(but->type, TOGN, ICONTOGN, OPTIONN)) {
- is_true = FALSE;
- }
+ int is_push = false; /* (0 == UNSELECT), (1 == SELECT), (-1 == DO-NOHING) */
if (but->bit) {
+ const bool state = ELEM3(but->type, TOGN, ICONTOGN, OPTIONN) ? false : true;
int lvalue;
UI_GET_BUT_VALUE_INIT(but, *value);
lvalue = (int)*value;
if (UI_BITBUT_TEST(lvalue, (but->bitnr))) {
- is_push = is_true;
+ is_push = state;
}
else {
- is_push = !is_true;
+ is_push = !state;
}
}
else {
switch (but->type) {
case BUT:
- is_push = 2;
- break;
case HOTKEYEVT:
case KEYEVT:
- is_push = 2;
+ case COLOR:
+ is_push = -1;
break;
case TOGBUT:
case TOG:
@@ -1124,42 +1131,48 @@ static void ui_is_but_sel(uiBut *but, double *value)
case ICONTOG:
case OPTION:
UI_GET_BUT_VALUE_INIT(but, *value);
- if (*value != (double)but->hardmin) is_push = 1;
+ if (*value != (double)but->hardmin) is_push = true;
break;
case ICONTOGN:
case TOGN:
case OPTIONN:
UI_GET_BUT_VALUE_INIT(but, *value);
- if (*value == 0.0) is_push = 1;
+ if (*value == 0.0) is_push = true;
break;
case ROW:
case LISTROW:
UI_GET_BUT_VALUE_INIT(but, *value);
/* support for rna enum buts */
if (but->rnaprop && (RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG)) {
- if ((int)*value & (int)but->hardmax) is_push = 1;
+ if ((int)*value & (int)but->hardmax) is_push = true;
}
else {
- if (*value == (double)but->hardmax) is_push = 1;
+ if (*value == (double)but->hardmax) is_push = true;
}
break;
- case COLOR:
- is_push = 2;
- break;
default:
- is_push = 2;
+ is_push = -1;
break;
}
}
-
- if (is_push == 2) {
- /* pass */
- }
- else if (is_push == 1) {
- but->flag |= UI_SELECT;
- }
- else {
- but->flag &= ~UI_SELECT;
+
+ return is_push;
+}
+int ui_is_but_push(uiBut *but)
+{
+ double value = UI_BUT_VALUE_UNSET;
+ return ui_is_but_push_ex(but, &value);
+}
+
+static void ui_check_but_select(uiBut *but, double *value)
+{
+ switch (ui_is_but_push_ex(but, value)) {
+ case true:
+ but->flag |= UI_SELECT;
+ break;
+ case false:
+ but->flag &= ~UI_SELECT;
+ break;
}
}
@@ -1290,7 +1303,7 @@ void ui_delete_linkline(uiLinkLine *line, uiBut *but)
void ui_get_but_vectorf(uiBut *but, float vec[3])
{
PropertyRNA *prop;
- int a, tot;
+ int a;
if (but->editvec) {
copy_v3_v3(vec, but->editvec);
@@ -1299,18 +1312,25 @@ void ui_get_but_vectorf(uiBut *but, float vec[3])
if (but->rnaprop) {
prop = but->rnaprop;
- vec[0] = vec[1] = vec[2] = 0.0f;
+ zero_v3(vec);
if (RNA_property_type(prop) == PROP_FLOAT) {
- tot = RNA_property_array_length(&but->rnapoin, prop);
- tot = min_ii(tot, 3);
-
- for (a = 0; a < tot; a++)
- vec[a] = RNA_property_float_get_index(&but->rnapoin, prop, a);
+ int tot = RNA_property_array_length(&but->rnapoin, prop);
+ BLI_assert(tot > 0);
+ if (tot == 3) {
+ RNA_property_float_get_array(&but->rnapoin, prop, vec);
+ }
+ else {
+ tot = min_ii(tot, 3);
+ for (a = 0; a < tot; a++) {
+ vec[a] = RNA_property_float_get_index(&but->rnapoin, prop, a);
+ }
+ }
}
}
else if (but->pointype == UI_BUT_POIN_CHAR) {
char *cp = (char *)but->poin;
+
vec[0] = ((float)cp[0]) / 255.0f;
vec[1] = ((float)cp[1]) / 255.0f;
vec[2] = ((float)cp[2]) / 255.0f;
@@ -1321,8 +1341,8 @@ void ui_get_but_vectorf(uiBut *but, float vec[3])
}
else {
if (but->editvec == NULL) {
- fprintf(stderr, "ui_get_but_vectorf: can't get color, should never happen\n");
- vec[0] = vec[1] = vec[2] = 0.0f;
+ fprintf(stderr, "%s: can't get color, should never happen\n", __func__);
+ zero_v3(vec);
}
}
@@ -1348,10 +1368,15 @@ void ui_set_but_vectorf(uiBut *but, const float vec[3])
int a;
tot = RNA_property_array_length(&but->rnapoin, prop);
- tot = min_ii(tot, 3);
-
- for (a = 0; a < tot; a++) {
- RNA_property_float_set_index(&but->rnapoin, prop, a, vec[a]);
+ BLI_assert(tot > 0);
+ if (tot == 3) {
+ RNA_property_float_set_array(&but->rnapoin, prop, vec);
+ }
+ else {
+ tot = min_ii(tot, 3);
+ for (a = 0; a < tot; a++) {
+ RNA_property_float_set_index(&but->rnapoin, prop, a, vec[a]);
+ }
}
}
}
@@ -1378,6 +1403,18 @@ int ui_is_but_float(uiBut *but)
return 0;
}
+int ui_is_but_bool(uiBut *but)
+{
+ if (ELEM5(but->type, TOG, TOGN, TOGR, ICONTOG, ICONTOGN))
+ return 1;
+
+ if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_BOOLEAN)
+ return 1;
+
+ return 0;
+}
+
+
int ui_is_but_unit(uiBut *but)
{
UnitSettings *unit = but->block->unit;
@@ -1426,6 +1463,8 @@ double ui_get_but_val(uiBut *but)
if (but->rnaprop) {
prop = but->rnaprop;
+ BLI_assert(but->rnaindex != -1);
+
switch (RNA_property_type(prop)) {
case PROP_BOOLEAN:
if (RNA_property_array_check(prop))
@@ -1453,18 +1492,6 @@ double ui_get_but_val(uiBut *but)
break;
}
}
- else if (but->type == HSVSLI) {
- float *fp, hsv[3];
-
- fp = (but->editvec) ? but->editvec : (float *)but->poin;
- rgb_to_hsv_v(fp, hsv);
-
- switch (but->str[0]) {
- case 'H': value = hsv[0]; break;
- case 'S': value = hsv[1]; break;
- case 'V': value = hsv[2]; break;
- }
- }
else if (but->pointype == UI_BUT_POIN_CHAR) {
value = *(char *)but->poin;
}
@@ -1531,21 +1558,6 @@ void ui_set_but_val(uiBut *but, double value)
else if (but->pointype == 0) {
/* pass */
}
- else if (but->type == HSVSLI) {
- float *fp, hsv[3];
-
- fp = (but->editvec) ? but->editvec : (float *)but->poin;
- rgb_to_hsv_v(fp, hsv);
-
- switch (but->str[0]) {
- case 'H': hsv[0] = value; break;
- case 'S': hsv[1] = value; break;
- case 'V': hsv[2] = value; break;
- }
-
- hsv_to_rgb_v(hsv, fp);
-
- }
else {
/* first do rounding */
if (but->pointype == UI_BUT_POIN_CHAR) {
@@ -1586,13 +1598,12 @@ void ui_set_but_val(uiBut *but, double value)
value = *((float *)but->poin) = (float)value;
}
- /* update select flag */
- ui_is_but_sel(but, &value);
+ ui_check_but_select(but, &value);
}
int ui_get_but_string_max_length(uiBut *but)
{
- if (ELEM(but->type, TEX, SEARCH_MENU))
+ if (ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK))
return but->hardmax;
else if (but->type == IDPOIN)
return MAX_ID_NAME - 2;
@@ -1608,6 +1619,9 @@ static double ui_get_but_scale_unit(uiBut *but, double value)
if (unit_type == PROP_UNIT_LENGTH) {
return value * (double)unit->scale_length;
}
+ else if (unit_type == PROP_UNIT_CAMERA) {
+ return value * (double)unit->scale_length;
+ }
else if (unit_type == PROP_UNIT_AREA) {
return value * pow(unit->scale_length, 2);
}
@@ -1640,18 +1654,28 @@ void ui_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen)
}
}
-static void ui_get_but_string_unit(uiBut *but, char *str, int len_max, double value, int pad)
+/**
+ * \param float_precision Override the button precision.
+ */
+static void ui_get_but_string_unit(uiBut *but, char *str, int len_max, double value, int pad, int float_precision)
{
UnitSettings *unit = but->block->unit;
int do_split = unit->flag & USER_UNIT_OPT_SPLIT;
int unit_type = uiButGetUnitType(but);
- int precision = but->a2;
+ int precision;
if (unit->scale_length < 0.0001f) unit->scale_length = 1.0f; // XXX do_versions
- /* Sanity checks */
- if (precision > PRECISION_FLOAT_MAX) precision = PRECISION_FLOAT_MAX;
- else if (precision == 0) precision = 2;
+ /* Use precision override? */
+ if (float_precision == -1) {
+ /* Sanity checks */
+ precision = (int)but->a2;
+ if (precision > PRECISION_FLOAT_MAX) precision = PRECISION_FLOAT_MAX;
+ else if (precision == 0) precision = 2;
+ }
+ else {
+ precision = float_precision;
+ }
bUnit_AsString(str, len_max, ui_get_but_scale_unit(but, value), precision,
unit->system, RNA_SUBTYPE_UNIT_VALUE(unit_type), do_split, pad);
@@ -1672,10 +1696,12 @@ static float ui_get_but_step_unit(uiBut *but, float step_default)
}
}
-
-void ui_get_but_string(uiBut *but, char *str, size_t maxlen)
+/**
+ * \param float_precision For number buttons the precission 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)
{
- if (but->rnaprop && ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) {
+ if (but->rnaprop && ELEM4(but->type, TEX, IDPOIN, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
PropertyType type;
const char *buf = NULL;
int buf_len;
@@ -1729,7 +1755,7 @@ void ui_get_but_string(uiBut *but, char *str, size_t maxlen)
BLI_strncpy(str, but->poin, maxlen);
return;
}
- else if (but->type == SEARCH_MENU) {
+ else if (ELEM(but->type, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
/* string */
BLI_strncpy(str, but->poin, maxlen);
return;
@@ -1745,10 +1771,10 @@ void ui_get_but_string(uiBut *but, char *str, size_t maxlen)
if (ui_is_but_float(but)) {
if (ui_is_but_unit(but)) {
- ui_get_but_string_unit(but, str, maxlen, value, 0);
+ ui_get_but_string_unit(but, str, maxlen, value, 0, float_precision);
}
else {
- const int prec = ui_but_float_precision(but, value);
+ const int prec = (float_precision == -1) ? ui_but_float_precision(but, value) : float_precision;
BLI_snprintf(str, maxlen, "%.*f", prec, value);
}
}
@@ -1756,6 +1782,10 @@ void ui_get_but_string(uiBut *but, char *str, size_t maxlen)
BLI_snprintf(str, maxlen, "%d", (int)value);
}
}
+void ui_get_but_string(uiBut *but, char *str, const size_t maxlen)
+{
+ ui_get_but_string_ex(but, str, maxlen, -1);
+}
#ifdef WITH_PYTHON
@@ -1784,9 +1814,9 @@ int ui_set_but_string_eval_num(bContext *C, uiBut *but, const char *str, double
#ifdef WITH_PYTHON
if (str[0] != '\0') {
- int is_unit_but = ui_is_but_unit(but);
+ bool is_unit_but = (ui_is_but_float(but) && ui_is_but_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 (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 */
if (is_unit_but) {
char str_new[128];
@@ -1820,7 +1850,7 @@ int ui_set_but_string_eval_num(bContext *C, uiBut *but, const char *str, double
int ui_set_but_string(bContext *C, uiBut *but, const char *str)
{
- if (but->rnaprop && ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) {
+ if (but->rnaprop && ELEM4(but->type, TEX, IDPOIN, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
if (RNA_property_editable(&but->rnapoin, but->rnaprop)) {
PropertyType type;
@@ -1877,7 +1907,7 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str)
return 1;
}
- else if (but->type == SEARCH_MENU) {
+ else if (ELEM(but->type, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
/* string */
BLI_strncpy(but->poin, str, but->hardmax);
return 1;
@@ -1950,7 +1980,8 @@ static double soft_range_round_down(double value, double max)
return newmax;
}
-void ui_set_but_soft_range(uiBut *but, double value)
+/* note: this could be split up into functions which handle arrays and not */
+static void ui_set_but_soft_range(uiBut *but)
{
/* ideally we would not limit this but practically, its more then
* enough worst case is very long vectors wont use a smart soft-range
@@ -1959,14 +1990,14 @@ void ui_set_but_soft_range(uiBut *but, double value)
if (but->rnaprop) {
const PropertyType type = RNA_property_type(but->rnaprop);
double softmin, softmax /*, step, precision*/;
- double value_min = value;
- double value_max = value;
+ double value_min;
+ double value_max;
/* clamp button range to something reasonable in case
* we get -inf/inf from RNA properties */
if (type == PROP_INT) {
+ const bool is_array = RNA_property_array_check(but->rnaprop);
int imin, imax, istep;
- const int array_len = RNA_property_array_length(&but->rnapoin, but->rnaprop);
RNA_property_int_ui_range(&but->rnapoin, but->rnaprop, &imin, &imax, &istep);
softmin = (imin == INT_MIN) ? -1e4 : imin;
@@ -1974,16 +2005,19 @@ void ui_set_but_soft_range(uiBut *but, double value)
/*step = istep;*/ /*UNUSED*/
/*precision = 1;*/ /*UNUSED*/
- if (array_len >= 2) {
+ if (is_array) {
int value_range[2];
RNA_property_int_get_array_range(&but->rnapoin, but->rnaprop, value_range);
value_min = (double)value_range[0];
value_max = (double)value_range[1];
}
+ else {
+ value_min = value_max = (double)RNA_property_int_get(&but->rnapoin, but->rnaprop);
+ }
}
else if (type == PROP_FLOAT) {
+ const bool is_array = RNA_property_array_check(but->rnaprop);
float fmin, fmax, fstep, fprecision;
- const int array_len = RNA_property_array_length(&but->rnapoin, but->rnaprop);
RNA_property_float_ui_range(&but->rnapoin, but->rnaprop, &fmin, &fmax, &fstep, &fprecision);
softmin = (fmin == -FLT_MAX) ? (float)-1e4 : fmin;
@@ -1991,15 +2025,19 @@ void ui_set_but_soft_range(uiBut *but, double value)
/*step = fstep;*/ /*UNUSED*/
/*precision = fprecision;*/ /*UNUSED*/
- if (array_len >= 2) {
+ if (is_array) {
float value_range[2];
RNA_property_float_get_array_range(&but->rnapoin, but->rnaprop, value_range);
value_min = (double)value_range[0];
value_max = (double)value_range[1];
}
+ else {
+ value_min = value_max = (double)RNA_property_float_get(&but->rnapoin, but->rnaprop);
+ }
}
- else
+ else {
return;
+ }
/* if the value goes out of the soft/max range, adapt the range */
if (value_min + 1e-10 < softmin) {
@@ -2222,12 +2260,11 @@ void ui_check_but(uiBut *but)
double value = UI_BUT_VALUE_UNSET;
// float okwidth; // UNUSED
- ui_is_but_sel(but, &value);
+ ui_check_but_select(but, &value);
/* only update soft range while not editing */
if (but->rnaprop && !(but->editval || but->editstr || but->editvec)) {
- UI_GET_BUT_VALUE_INIT(but, value);
- ui_set_but_soft_range(but, value);
+ ui_set_but_soft_range(but);
}
/* test for min and max, icon sliders, etc */
@@ -2236,7 +2273,6 @@ void ui_check_but(uiBut *but)
case SLI:
case SCROLL:
case NUMSLI:
- case HSVSLI:
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);
@@ -2296,7 +2332,6 @@ void ui_check_but(uiBut *but)
case NUM:
case NUMSLI:
- case HSVSLI:
case NUMABS:
UI_GET_BUT_VALUE_INIT(but, value);
@@ -2311,7 +2346,7 @@ void ui_check_but(uiBut *but)
/* support length type buttons */
else if (ui_is_but_unit(but)) {
char new_str[sizeof(but->drawstr)];
- ui_get_but_string_unit(but, new_str, sizeof(new_str), value, TRUE);
+ ui_get_but_string_unit(but, new_str, sizeof(new_str), value, TRUE, -1);
BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%s", but->str, new_str);
}
else {
@@ -2347,6 +2382,7 @@ void ui_check_but(uiBut *but)
case IDPOIN:
case TEX:
case SEARCH_MENU:
+ case SEARCH_MENU_UNLINK:
if (!but->editstr) {
char str[UI_MAX_DRAW_STR];
@@ -2495,7 +2531,9 @@ static void ui_block_do_align_but(uiBut *first, short nr)
else
flag = UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_LEFT;
}
- else flag = UI_BUT_ALIGN_TOP;
+ else {
+ flag = UI_BUT_ALIGN_TOP;
+ }
}
}
else if (buts_are_horiz(but, next)) {
@@ -2515,7 +2553,9 @@ static void ui_block_do_align_but(uiBut *first, short nr)
if (bt == NULL || bt->alignnr != nr) flag = UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_RIGHT;
}
}
- else flag |= UI_BUT_ALIGN_LEFT;
+ else {
+ flag |= UI_BUT_ALIGN_LEFT;
+ }
}
else {
if (cols == 0) {
@@ -2650,9 +2690,11 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
BLI_assert(width >= 0);
BLI_assert(height >= 0);
-
+
/* we could do some more error checks here */
if ((type & BUTTYPE) == LABEL) {
+ if ((poin != NULL || min != 0.0f || max != 0.0f || (a1 == 0.0f && a2 != 0.0f) || (a1 != 0.0f && a1 != 1.0f)))
+ printf("blah\n");
BLI_assert((poin != NULL || min != 0.0f || max != 0.0f || (a1 == 0.0f && a2 != 0.0f) || (a1 != 0.0f && a1 != 1.0f)) == FALSE);
}
@@ -2675,8 +2717,8 @@ 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 - 1) {
- but->str = MEM_mallocN(slen + 2, "ui_def_but str"); /* why +2 ? */
+ if (slen >= UI_MAX_NAME_STR) {
+ but->str = MEM_mallocN(slen + 1, "ui_def_but str");
}
else {
but->str = but->strdata;
@@ -2715,7 +2757,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
but->pos = -1; /* cursor invisible */
- if (ELEM4(but->type, NUM, NUMABS, NUMSLI, HSVSLI)) { /* add a space to name */
+ if (ELEM3(but->type, NUM, NUMABS, NUMSLI)) { /* 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] != ' ') {
@@ -2726,7 +2768,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
}
if ((block->flag & UI_BLOCK_LOOP) ||
- ELEM8(but->type, MENU, TEX, LABEL, IDPOIN, BLOCK, BUTM, SEARCH_MENU, PROGRESSBAR))
+ ELEM9(but->type, MENU, TEX, LABEL, IDPOIN, BLOCK, BUTM, SEARCH_MENU, PROGRESSBAR, SEARCH_MENU_UNLINK))
{
but->flag |= (UI_TEXT_LEFT | UI_ICON_LEFT);
}
@@ -2762,21 +2804,21 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
return but;
}
-/* ui_def_but_rna_propname and ui_def_but_rna
+static void ui_def_but_rna__disable(uiBut *but)
+{
+ but->flag |= UI_BUT_DISABLED;
+ but->lock = true;
+ but->lockstr = "";
+}
+
+/**
+ * ui_def_but_rna_propname and ui_def_but_rna
* both take the same args except for propname vs prop, this is done so we can
* avoid an extra lookup on 'prop' when its already available.
*
* When this kind of change won't disrupt branches, best look into making more
* of our UI functions take prop rather then propname.
*/
-
-#define UI_DEF_BUT_RNA_DISABLE(but) { \
- but->flag |= UI_BUT_DISABLED; \
- but->lock = TRUE; \
- but->lockstr = ""; \
- } (void)0
-
-
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,
@@ -2786,6 +2828,10 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s
uiBut *but;
int freestr = 0, icon = 0;
+ if (ELEM3(type, COLOR, HSVCIRCLE, HSVCUBE)) {
+ BLI_assert(index == -1);
+ }
+
/* use rna values if parameters are not specified */
if (!str) {
if (type == MENU && proptype == PROP_ENUM) {
@@ -2826,12 +2872,13 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s
EnumPropertyItem *item;
int i, totitem, free;
- /* TODO, translate after getting the item, saves many lookups */
- RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item, &totitem, &free);
+ /* get untranslated, then translate the single string we need */
+ RNA_property_enum_items(block->evil_C, ptr, prop, &item, &totitem, &free);
for (i = 0; i < totitem; i++) {
if (item[i].identifier[0] && item[i].value == (int)max) {
- str = item[i].name;
+ str = CTX_IFACE_(RNA_property_translation_context(prop), item[i].name);
icon = item[i].icon;
+ break;
}
}
@@ -2908,7 +2955,7 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s
}
if (!RNA_property_editable(&but->rnapoin, prop)) {
- UI_DEF_BUT_RNA_DISABLE(but);
+ ui_def_but_rna__disable(but);
}
if (but->flag & UI_BUT_UNDO && (ui_but_is_rna_undo(but) == FALSE)) {
@@ -2938,7 +2985,7 @@ static uiBut *ui_def_but_rna_propname(uiBlock *block, int type, int retval, cons
else {
but = ui_def_but(block, type, retval, propname, x, y, width, height, NULL, min, max, a1, a2, tip);
- UI_DEF_BUT_RNA_DISABLE(but);
+ ui_def_but_rna__disable(but);
}
return but;
@@ -2974,7 +3021,7 @@ static uiBut *ui_def_but_operator_ptr(uiBlock *block, int type, wmOperatorType *
}
#if 0 /* UNUSED */
-static uiBut *UNUSED_FUNCTION(ui_def_but_operator) (uiBlock * block, int type, const char *opname, int opcontext, const char *str, int x, int y, short width, short height, const char *tip)
+static uiBut *UNUSED_FUNCTION(ui_def_but_operator) (uiBlock *block, int type, const char *opname, int opcontext, const char *str, int x, int y, short width, short height, const char *tip)
{
wmOperatorType *ot = WM_operatortype_find(opname, 0);
if (str == NULL && ot == NULL) str = opname;
@@ -3887,15 +3934,20 @@ void uiButGetStrInfo(bContext *C, uiBut *but, ...)
}
}
else if (type == BUT_GET_RNA_LABEL_CONTEXT) {
+ const char *_tmp = BLF_I18NCONTEXT_DEFAULT;
if (but->rnaprop)
- tmp = BLI_strdup(RNA_property_translation_context(but->rnaprop));
+ _tmp = RNA_property_translation_context(but->rnaprop);
else if (but->optype)
- tmp = BLI_strdup(RNA_struct_translation_context(but->optype->srna));
+ _tmp = RNA_struct_translation_context(but->optype->srna);
else if (ELEM(but->type, MENU, PULLDOWN)) {
MenuType *mt = uiButGetMenuType(but);
if (mt)
- tmp = BLI_strdup(RNA_struct_translation_context(mt->ext.srna));
+ _tmp = RNA_struct_translation_context(mt->ext.srna);
+ }
+ if (BLF_is_default_context(_tmp)) {
+ _tmp = BLF_I18NCONTEXT_DEFAULT_BPYRNA;
}
+ tmp = BLI_strdup(_tmp);
}
else if (ELEM3(type, BUT_GET_RNAENUM_IDENTIFIER, BUT_GET_RNAENUM_LABEL, BUT_GET_RNAENUM_TIP)) {
PointerRNA *ptr = NULL;
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index 5d62ef768d2..3feb563d3ee 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -55,15 +55,19 @@
#include "interface_intern.h"
-static FCurve *ui_but_get_fcurve(uiBut *but, bAction **action, int *driven)
+static FCurve *ui_but_get_fcurve(uiBut *but, bAction **action, bool *r_driven)
{
- return rna_get_fcurve(&but->rnapoin, but->rnaprop, but->rnaindex, action, driven);
+ /* 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);
}
void ui_but_anim_flag(uiBut *but, float cfra)
{
FCurve *fcu;
- int driven;
+ bool driven;
but->flag &= ~(UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN);
@@ -86,7 +90,7 @@ int ui_but_anim_expression_get(uiBut *but, char *str, size_t maxlen)
{
FCurve *fcu;
ChannelDriver *driver;
- int driven;
+ bool driven;
fcu = ui_but_get_fcurve(but, NULL, &driven);
@@ -106,7 +110,7 @@ int ui_but_anim_expression_set(uiBut *but, const char *str)
{
FCurve *fcu;
ChannelDriver *driver;
- int driven;
+ bool driven;
fcu = ui_but_get_fcurve(but, NULL, &driven);
@@ -131,7 +135,7 @@ int ui_but_anim_expression_create(uiBut *but, const char *str)
ID *id;
FCurve *fcu;
char *path;
- short ok = 0;
+ bool ok = false;
/* button must have RNA-pointer to a numeric-capable property */
if (ELEM(NULL, but->rnapoin.data, but->rnaprop)) {
@@ -140,6 +144,14 @@ int ui_but_anim_expression_create(uiBut *but, const char *str)
return 0;
}
+ if (RNA_property_array_length(&but->rnapoin, but->rnaprop) != 0) {
+ if (but->rnaindex == -1) {
+ if (G.debug & G_DEBUG)
+ printf("ERROR: create expression failed - can't create expression for entire array\n");
+ return 0;
+ }
+ }
+
/* make sure we have animdata for this */
/* FIXME: until materials can be handled by depsgraph, don't allow drivers to be created for them */
id = (ID *)but->rnapoin.id.data;
@@ -168,6 +180,7 @@ int ui_but_anim_expression_create(uiBut *but, const char *str)
/* updates */
driver->flag |= DRIVER_FLAG_RECOMPILE;
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME, NULL);
+ ok = true;
}
}
@@ -181,7 +194,7 @@ void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
ID *id;
bAction *action;
FCurve *fcu;
- int driven;
+ bool driven;
fcu = ui_but_get_fcurve(but, &action, &driven);
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 4d96ad810d4..7fc5c21f052 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -42,6 +42,7 @@
#include "BLI_utildefines.h"
#include "BKE_colortools.h"
+#include "BKE_node.h"
#include "BKE_texture.h"
#include "BKE_tracking.h"
@@ -97,7 +98,9 @@ void uiDrawBox(int mode, float minx, float miny, float maxx, float maxy, float r
}
glVertex2f(maxx, miny + rad);
}
- else glVertex2f(maxx, miny);
+ else {
+ glVertex2f(maxx, miny);
+ }
/* corner right-top */
if (roundboxtype & UI_CNR_TOP_RIGHT) {
@@ -107,7 +110,9 @@ void uiDrawBox(int mode, float minx, float miny, float maxx, float maxy, float r
}
glVertex2f(maxx - rad, maxy);
}
- else glVertex2f(maxx, maxy);
+ else {
+ glVertex2f(maxx, maxy);
+ }
/* corner left-top */
if (roundboxtype & UI_CNR_TOP_LEFT) {
@@ -117,7 +122,9 @@ void uiDrawBox(int mode, float minx, float miny, float maxx, float maxy, float r
}
glVertex2f(minx, maxy - rad);
}
- else glVertex2f(minx, maxy);
+ else {
+ glVertex2f(minx, maxy);
+ }
/* corner left-bottom */
if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
@@ -127,7 +134,9 @@ void uiDrawBox(int mode, float minx, float miny, float maxx, float maxy, float r
}
glVertex2f(minx + rad, miny);
}
- else glVertex2f(minx, miny);
+ else {
+ glVertex2f(minx, miny);
+ }
glEnd();
}
@@ -373,7 +382,7 @@ void uiRoundRect(float minx, float miny, float maxx, float maxy, float rad)
glEnable(GL_BLEND);
uiDrawBox(GL_LINE_LOOP, minx, miny, maxx, maxy, rad);
-
+
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
}
@@ -381,16 +390,7 @@ void uiRoundRect(float minx, float miny, float maxx, float maxy, float rad)
/* (old, used in outliner) plain antialiased filled box */
void uiRoundBox(float minx, float miny, float maxx, float maxy, float rad)
{
- float color[4];
-
- if (roundboxtype & UI_RB_ALPHA) {
- glGetFloatv(GL_CURRENT_COLOR, color);
- color[3] = 0.5;
- glColor4fv(color);
- glEnable(GL_BLEND);
- }
-
- ui_draw_anti_roundbox(GL_POLYGON, minx, miny, maxx, maxy, rad);
+ ui_draw_anti_roundbox(GL_POLYGON, minx, miny, maxx, maxy, rad, roundboxtype & UI_RB_ALPHA);
}
@@ -429,17 +429,18 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w
#else
ImBuf *ibuf = (ImBuf *)but->poin;
//GLint scissor[4];
- //int w, h;
+ int w, h;
if (!ibuf) return;
+ w = BLI_rcti_size_x(rect);
+ h = BLI_rcti_size_y(rect);
+
/* scissor doesn't seem to be doing the right thing...? */
#if 0
//glColor4f(1.0, 0.f, 0.f, 1.f);
//fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax)
- w = BLI_rcti_size_x(rect);
- h = BLI_rcti_size_y(rect);
/* prevent drawing outside widget area */
glGetIntegerv(GL_SCISSOR_BOX, scissor);
glScissor(ar->winrct.xmin + rect->xmin, ar->winrct.ymin + rect->ymin, w, h);
@@ -448,8 +449,14 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w
glEnable(GL_BLEND);
glColor4f(0.0, 0.0, 0.0, 0.0);
- glaDrawPixelsSafe((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
- //glaDrawPixelsTex((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect);
+ if (w != ibuf->x || h != ibuf->y) {
+ float facx = (float)w / (float)ibuf->x;
+ float facy = (float)h / (float)ibuf->y;
+ glPixelZoom(facx, facy);
+ }
+ glaDrawPixelsAuto((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect);
+
+ glPixelZoom(1.0f, 1.0f);
glDisable(GL_BLEND);
@@ -1293,8 +1300,10 @@ void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, rcti *rect)
glEndList();
}
- else glCallList(displist);
-
+ else {
+ glCallList(displist);
+ }
+
/* restore */
glDisable(GL_LIGHTING);
glDisable(GL_CULL_FACE);
@@ -1594,7 +1603,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
tmpibuf = BKE_tracking_sample_pattern(scopes->frame_width, scopes->frame_height,
scopes->track_search, scopes->track,
- &scopes->undist_marker, scopes->use_track_mask,
+ &scopes->undist_marker, TRUE, scopes->use_track_mask,
width, height, scopes->track_pos);
if (tmpibuf) {
@@ -1677,6 +1686,71 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
glDisable(GL_BLEND);
}
+void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *recti)
+{
+ static const float size = 5.0f;
+
+ /* 16 values of sin function */
+ static float si[16] = {
+ 0.00000000f, 0.39435585f, 0.72479278f, 0.93775213f,
+ 0.99871650f, 0.89780453f, 0.65137248f, 0.29936312f,
+ -0.10116832f, -0.48530196f, -0.79077573f, -0.96807711f,
+ -0.98846832f, -0.84864425f, -0.57126821f, -0.20129852f
+ };
+ /* 16 values of cos function */
+ static float co[16] = {
+ 1.00000000f, 0.91895781f, 0.68896691f, 0.34730525f,
+ -0.05064916f, -0.44039415f, -0.75875812f, -0.95413925f,
+ -0.99486932f, -0.87434661f, -0.61210598f, -0.25065253f,
+ 0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f,
+ };
+
+ unsigned char *col = but->col;
+ int a;
+ GLint scissor[4];
+ rcti scissor_new;
+ float x, y;
+
+ x = 0.5f * (recti->xmin + recti->xmax);
+ y = 0.5f * (recti->ymin + recti->ymax);
+
+ /* need scissor test, can draw outside of boundary */
+ glGetIntegerv(GL_VIEWPORT, scissor);
+ scissor_new.xmin = ar->winrct.xmin + recti->xmin;
+ scissor_new.ymin = ar->winrct.ymin + recti->ymin;
+ scissor_new.xmax = ar->winrct.xmin + recti->xmax;
+ scissor_new.ymax = ar->winrct.ymin + recti->ymax;
+ BLI_rcti_isect(&scissor_new, &ar->winrct, &scissor_new);
+ glScissor(scissor_new.xmin,
+ scissor_new.ymin,
+ BLI_rcti_size_x(&scissor_new),
+ BLI_rcti_size_y(&scissor_new));
+
+ glColor4ubv(col);
+
+ glEnable(GL_BLEND);
+ glBegin(GL_POLYGON);
+ for (a = 0; a < 16; a++)
+ glVertex2f(x + size * si[a], y + size * co[a]);
+ glEnd();
+ glDisable(GL_BLEND);
+
+ glColor4ub(0, 0, 0, 150);
+
+ glEnable(GL_BLEND);
+ glEnable(GL_LINE_SMOOTH);
+ glBegin(GL_LINE_LOOP);
+ for (a = 0; a < 16; a++)
+ glVertex2f(x + size * si[a], y + size * co[a]);
+ glEnd();
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
+ glLineWidth(1.0f);
+
+ /* restore scissortest */
+ glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+}
+
/* ****************************************************** */
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index b80025e0d77..b34f4c9653f 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -44,6 +44,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
@@ -80,10 +81,13 @@
/* place the mouse at the scaled down location when un-grabbing */
#define USE_CONT_MOUSE_CORRECT
+/* support dragging toggle buttons */
+#define USE_DRAG_TOGGLE
/* 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 int ui_do_but_EXIT(bContext *C, uiBut *but, struct uiHandleButtonData *data, const wmEvent *event);
/***************** structs and defines ****************/
@@ -149,6 +153,7 @@ typedef struct uiHandleButtonData {
int maxlen, selextend, selstartx;
/* number editing / dragging */
+ /* coords are Window/uiBlock relative (depends on the button) */
int draglastx, draglasty;
int dragstartx, dragstarty;
int dragchange, draglock, dragsel;
@@ -213,12 +218,45 @@ typedef struct uiAfterFunc {
static int ui_but_contains_pt(uiBut *but, int mx, int my);
static int ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y);
static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state);
-static int ui_handler_region_menu(bContext *C, wmEvent *event, void *userdata);
+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);
/* ******************** menu navigation helpers ************** */
+/* assumes event type is MOUSEPAN */
+void ui_pan_to_scroll(const wmEvent *event, int *type, int *val)
+{
+ static int lastdy = 0;
+ int dy = event->prevy - event->y;
+
+ /* This event should be originally from event->type,
+ * converting wrong event into wheel is bad, see [#33803] */
+ BLI_assert(*type == MOUSEPAN);
+
+ /* sign differs, reset */
+ if ((dy > 0 && lastdy < 0) || (dy < 0 && lastdy > 0)) {
+ lastdy = dy;
+ }
+ else {
+ lastdy += dy;
+
+ if (ABS(lastdy) > (int)UI_UNIT_Y) {
+ if (U.uiflag2 & USER_TRACKPAD_NATURAL)
+ dy = -dy;
+
+ *val = KM_PRESS;
+
+ if (dy > 0)
+ *type = WHEELUPMOUSE;
+ else
+ *type = WHEELDOWNMOUSE;
+
+ lastdy = 0;
+ }
+ }
+}
+
static int ui_but_editable(uiBut *but)
{
return ELEM5(but->type, LABEL, SEPR, ROUNDBOX, LISTBOX, PROGRESSBAR);
@@ -266,15 +304,15 @@ static uiBut *ui_but_last(uiBlock *block)
return NULL;
}
-static int ui_is_a_warp_but(uiBut *but)
+static bool ui_is_a_warp_but(uiBut *but)
{
if (U.uiflag & USER_CONTINUOUS_MOUSE) {
- if (ELEM6(but->type, NUM, NUMABS, HSVCIRCLE, TRACKPREVIEW, HSVCUBE, BUT_CURVE)) {
- return TRUE;
+ if (ELEM7(but->type, NUM, NUMSLI, NUMABS, HSVCIRCLE, TRACKPREVIEW, HSVCUBE, BUT_CURVE)) {
+ return true;
}
}
- return FALSE;
+ return false;
}
static float ui_mouse_scale_warp_factor(const short shift)
@@ -370,9 +408,9 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
}
}
-static void ui_apply_autokey_undo(bContext *C, uiBut *but)
+/* typically call ui_apply_undo(), ui_apply_autokey() */
+static void ui_apply_undo(uiBut *but)
{
- Scene *scene = CTX_data_scene(C);
uiAfterFunc *after;
if (but->flag & UI_BUT_UNDO) {
@@ -394,9 +432,25 @@ static void ui_apply_autokey_undo(bContext *C, uiBut *but)
BLI_strncpy(after->undostr, str, sizeof(after->undostr));
BLI_addtail(&UIAfterFuncs, after);
}
+}
+
+static void ui_apply_autokey(bContext *C, uiBut *but)
+{
+ Scene *scene = CTX_data_scene(C);
/* try autokey */
ui_but_anim_autokey(C, but, scene, scene->r.cfra);
+
+ /* make a little report about what we've done! */
+ if (but->rnaprop) {
+ char *buf = WM_prop_pystring_assign(C, &but->rnapoin, but->rnaprop, but->rnaindex);
+ if (buf) {
+ BKE_report(CTX_wm_reports(C), RPT_PROPERTY, buf);
+ MEM_freeN(buf);
+
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO_REPORT, NULL);
+ }
+ }
}
static void ui_apply_but_funcs_after(bContext *C)
@@ -685,7 +739,152 @@ static void ui_apply_but_CHARTAB(bContext *C, uiBut *but, uiHandleButtonData *da
/* ****************** drag drop code *********************** */
-static int ui_but_mouse_inside_icon(uiBut *but, ARegion *ar, wmEvent *event)
+#ifdef USE_DRAG_TOGGLE
+
+typedef struct uiDragToggleHandle {
+ /* init */
+ bool is_set;
+ float but_cent_start[2];
+ eButType but_type_start;
+
+ bool xy_lock[2];
+ 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])
+{
+ bool change = false;
+ uiBlock *block;
+
+ for (block = ar->uiblocks.first; block; block = block->next) {
+ uiBut *but;
+
+ float xy_a_block[2] = {UNPACK2(xy_src)};
+ float xy_b_block[2] = {UNPACK2(xy_dst)};
+
+ 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]);
+
+ for (but = block->buttons.first; but; but = but->next) {
+ if (ui_is_but_interactive(but)) {
+ 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) {
+ /* is it pressed? */
+ bool is_set_but = ui_is_but_push(but);
+ BLI_assert(ui_is_but_bool(but) == true);
+ if (is_set_but != is_set) {
+ uiButExecute(C, but);
+ change = true;
+ }
+ }
+ /* done */
+
+ }
+ }
+ }
+ }
+
+ return change;
+}
+
+static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const int xy_input[2])
+{
+ ARegion *ar = CTX_wm_region(C);
+ bool do_draw = false;
+ int xy[2];
+
+ /**
+ * Initialize Locking:
+ *
+ * Check if we need to initialize the lock axis by finding if the first
+ * button we mouse over is X or Y aligned, then lock the mouse to that axis after.
+ */
+ if (drag_info->xy_lock[0] == false && drag_info->xy_lock[1] == false) {
+ /* first store the buttons original coords */
+ uiBut *but = ui_but_find_mouse_over(ar, xy_input[0], xy_input[1]);
+ if (but) {
+ const float but_cent_new[2] = {BLI_rctf_cent_x(&but->rect),
+ BLI_rctf_cent_y(&but->rect)};
+
+ /* check if this is a different button, chances are high the button wont move about :) */
+ if (len_manhattan_v2v2(drag_info->but_cent_start, but_cent_new) > 1.0f) {
+ if (fabsf(drag_info->but_cent_start[0] - but_cent_new[0]) <
+ fabsf(drag_info->but_cent_start[1] - but_cent_new[1]))
+ {
+ drag_info->xy_lock[0] = true;
+ }
+ else {
+ drag_info->xy_lock[1] = true;
+ }
+ }
+ }
+ }
+ /* done with axis locking */
+
+
+ xy[0] = (drag_info->xy_lock[0] == false) ? xy_input[0] : drag_info->xy_last[0];
+ xy[1] = (drag_info->xy_lock[1] == false) ? xy_input[1] : drag_info->xy_last[1];
+
+
+ /* touch all buttons between last mouse coord and this one */
+ do_draw = ui_drag_toggle_set_xy_xy(C, ar, drag_info->is_set, drag_info->but_type_start, drag_info->xy_last, xy);
+
+ if (do_draw) {
+ ED_region_tag_redraw(ar);
+ }
+
+ copy_v2_v2_int(drag_info->xy_last, xy);
+}
+
+static void ui_handler_region_drag_toggle_remove(bContext *UNUSED(C), void *userdata)
+{
+ uiDragToggleHandle *drag_info = userdata;
+ MEM_freeN(drag_info);
+}
+
+static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void *userdata)
+{
+ uiDragToggleHandle *drag_info = userdata;
+ bool done = false;
+
+ switch (event->type) {
+ case LEFTMOUSE:
+ {
+ if (event->val != KM_PRESS) {
+ done = true;
+ }
+ break;
+ }
+ case MOUSEMOVE:
+ {
+ ui_drag_toggle_set(C, drag_info, &event->x);
+ break;
+ }
+ }
+
+ if (done) {
+ wmWindow *win = CTX_wm_window(C);
+ WM_event_remove_ui_handler(&win->modalhandlers,
+ ui_handler_region_drag_toggle,
+ ui_handler_region_drag_toggle_remove,
+ drag_info, false);
+ ui_handler_region_drag_toggle_remove(C, drag_info);
+
+ WM_event_add_mousemove(C);
+ return WM_UI_HANDLER_BREAK;
+ }
+ else {
+ return WM_UI_HANDLER_CONTINUE;
+ }
+}
+
+#endif /* USE_DRAG_TOGGLE */
+
+
+static int ui_but_mouse_inside_icon(uiBut *but, ARegion *ar, const wmEvent *event)
{
rcti rect;
int x = event->x, y = event->y;
@@ -709,20 +908,39 @@ static int ui_but_mouse_inside_icon(uiBut *but, ARegion *ar, wmEvent *event)
return BLI_rcti_isect_pt(&rect, x, y);
}
-static int ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
/* prevent other WM gestures to start while we try to drag */
WM_gestures_remove(C);
if (ABS(data->dragstartx - event->x) + ABS(data->dragstarty - event->y) > U.dragthreshold) {
- wmDrag *drag;
-
+
button_activate_state(C, but, BUTTON_STATE_EXIT);
data->cancel = TRUE;
-
- drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but));
- 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));
+#ifdef USE_DRAG_TOGGLE
+ if (ui_is_but_bool(but)) {
+ uiDragToggleHandle *drag_info = MEM_callocN(sizeof(*drag_info), __func__);
+
+ drag_info->is_set = ui_is_but_push(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;
+ copy_v2_v2_int(drag_info->xy_last, &event->x);
+
+ WM_event_add_ui_handler(C, &data->window->modalhandlers,
+ ui_handler_region_drag_toggle,
+ ui_handler_region_drag_toggle_remove,
+ drag_info);
+ }
+ else
+#endif
+ {
+ wmDrag *drag;
+
+ drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but));
+ 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));
+ }
return 1;
}
@@ -1026,6 +1244,7 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
ui_apply_but_BUT(C, but, data);
break;
case TEX:
+ case SEARCH_MENU_UNLINK:
case SEARCH_MENU:
ui_apply_but_TEX(C, but, data);
break;
@@ -1051,8 +1270,6 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
case NUMSLI:
ui_apply_but_NUM(C, but, data);
break;
- case HSVSLI:
- break;
case TOG3:
ui_apply_but_TOG3(C, but, data);
break;
@@ -1125,7 +1342,7 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
/* ******************* drop event ******************** */
/* only call if event type is EVT_DROP */
-static void ui_but_drop(bContext *C, wmEvent *event, uiBut *but, uiHandleButtonData *data)
+static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleButtonData *data)
{
wmDrag *wmd;
ListBase *drags = event->customdata; /* drop event type has listbase customdata by default */
@@ -1133,7 +1350,7 @@ static void ui_but_drop(bContext *C, wmEvent *event, uiBut *but, uiHandleButtonD
for (wmd = drags->first; wmd; wmd = wmd->next) {
if (wmd->type == WM_DRAG_ID) {
/* align these types with UI_but_active_drop_name */
- if (ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) {
+ if (ELEM4(but->type, TEX, IDPOIN, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
ID *id = (ID *)wmd->poin;
if (but->poin == NULL && but->rnapoin.data == NULL) {}
@@ -1174,13 +1391,17 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
}
/* numeric value */
- if (ELEM4(but->type, NUM, NUMABS, NUMSLI, HSVSLI)) {
+ if (ELEM3(but->type, NUM, NUMABS, NUMSLI)) {
if (but->poin == NULL && but->rnapoin.data == NULL) {
/* pass */
}
else if (mode == 'c') {
- ui_get_but_string(but, buf, sizeof(buf));
+ /* Get many decimal places, then strip trailing zeros.
+ * note: too high values start to give strange results (6 or so is ok) */
+ ui_get_but_string_ex(but, buf, sizeof(buf), 6);
+ BLI_str_rstrip_float_zero(buf, '\0');
+
WM_clipboard_text_set(buf, 0);
}
else {
@@ -1197,37 +1418,44 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
/* RGB triple */
else if (but->type == COLOR) {
- float rgb[3];
+ float rgba[4];
if (but->poin == NULL && but->rnapoin.data == NULL) {
/* pass */
}
else if (mode == 'c') {
-
- ui_get_but_vectorf(but, rgb);
+ if (RNA_property_array_length(&but->rnapoin, but->rnaprop) == 4)
+ rgba[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
+ else
+ rgba[3] = 1.0f;
+
+ ui_get_but_vectorf(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(rgb, rgb);
+ srgb_to_linearrgb_v3_v3(rgba, rgba);
- BLI_snprintf(buf, sizeof(buf), "[%f, %f, %f]", rgb[0], rgb[1], rgb[2]);
+ BLI_snprintf(buf, sizeof(buf), "[%f, %f, %f, %f]", rgba[0], rgba[1], rgba[2], rgba[3]);
WM_clipboard_text_set(buf, 0);
}
else {
- if (sscanf(buf, "[%f, %f, %f]", &rgb[0], &rgb[1], &rgb[2]) == 3) {
+ if (sscanf(buf, "[%f, %f, %f, %f]", &rgba[0], &rgba[1], &rgba[2], &rgba[3]) == 4) {
/* assume linear colors in buffer */
if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
- linearrgb_to_srgb_v3_v3(rgb, rgb);
+ linearrgb_to_srgb_v3_v3(rgba, rgba);
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- ui_set_but_vectorf(but, rgb);
+ ui_set_but_vectorf(but, rgba);
+ if (RNA_property_array_length(&but->rnapoin, but->rnaprop) == 4)
+ RNA_property_float_set_index(&but->rnapoin, but->rnaprop, 3, rgba[3]);
+
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
}
}
/* text/string and ID data */
- else if (ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) {
+ else if (ELEM4(but->type, TEX, IDPOIN, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
uiHandleButtonData *active_data = but->active;
if (but->poin == NULL && but->rnapoin.data == NULL) {
@@ -1246,7 +1474,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
if (ui_is_but_utf8(but)) BLI_strncpy_utf8(active_data->str, buf, active_data->maxlen);
else BLI_strncpy(active_data->str, buf, active_data->maxlen);
- if (but->type == SEARCH_MENU) {
+ if (ELEM(but->type, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
/* else uiSearchboxData.active member is not updated [#26856] */
ui_searchbox_update(C, data->searchbox, but, 1);
}
@@ -1372,11 +1600,11 @@ static int ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data)
}
/* note, but->block->aspect is used here, when drawing button style is getting scaled too */
-static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, short x)
+static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, const float x)
{
uiStyle *style = UI_GetStyle(); // XXX pass on as arg
uiFontStyle *fstyle = &style->widget;
- int startx = but->rect.xmin;
+ float startx = but->rect.xmin;
char *origstr, password_str[UI_MAX_DRAW_STR];
uiStyleFontSet(fstyle);
@@ -1386,24 +1614,27 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho
ui_button_text_password_hide(password_str, but, FALSE);
- origstr = MEM_callocN(sizeof(char) * data->maxlen, "ui_textedit origstr");
+ origstr = MEM_mallocN(sizeof(char) * data->maxlen, "ui_textedit origstr");
BLI_strncpy(origstr, but->drawstr, data->maxlen);
- /* XXX solve generic */
- if (but->type == NUM || but->type == NUMSLI)
+ /* XXX solve generic, see: #widget_draw_text_icon */
+ if (but->type == NUM || but->type == NUMSLI) {
startx += (int)(0.5f * (BLI_rctf_size_y(&but->rect)));
- else if (ELEM(but->type, TEX, SEARCH_MENU)) {
- startx += 5;
- if (but->flag & UI_HAS_ICON)
+ }
+ else if (ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (but->flag & UI_HAS_ICON) {
startx += UI_DPI_ICON_SIZE;
+ }
+ /* but this extra .05 makes clicks inbetween characters feel nicer */
+ startx += ((UI_TEXT_MARGIN_X + 0.05f) * U.widget_unit);
}
/* mouse dragged outside the widget to the left */
- if (x < startx && but->ofs > 0) {
+ if (x < startx) {
int i = but->ofs;
- origstr[but->ofs] = 0;
+ origstr[but->ofs] = '\0';
while (i > 0) {
if (BLI_str_cursor_step_prev_utf8(origstr, but->ofs, &i)) {
@@ -1419,21 +1650,18 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho
but->ofs = i;
but->pos = but->ofs;
}
- /* mouse inside the widget */
- else if (x >= startx) {
+ /* mouse inside the widget, mouse coords mapped in widget space */
+ else { /* (x >= startx) */
int pos_i;
/* keep track of previous distance from the cursor to the char */
float cdist, cdist_prev = 0.0f;
short pos_prev;
-
- const float aspect_sqrt = sqrtf(but->block->aspect);
but->pos = pos_prev = strlen(origstr) - but->ofs;
- while (TRUE) {
- /* XXX does not take zoom level into account */
- cdist = startx + aspect_sqrt * BLF_width(fstyle->uifont_id, origstr + but->ofs);
+ while (true) {
+ cdist = startx + BLF_width(fstyle->uifont_id, origstr + but->ofs);
/* check if position is found */
if (cdist < x) {
@@ -1469,7 +1697,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho
MEM_freeN(origstr);
}
-static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data, short x)
+static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data, const float x)
{
if (x > data->selstartx) data->selextend = EXTEND_RIGHT;
else if (x < data->selstartx) data->selextend = EXTEND_LEFT;
@@ -1556,7 +1784,7 @@ static void ui_textedit_move(uiBut *but, uiHandleButtonData *data, strCursorJump
}
else {
int pos_i = but->pos;
- BLI_str_cursor_step_utf8(str, len, &pos_i, direction, jump);
+ BLI_str_cursor_step_utf8(str, len, &pos_i, direction, jump, true);
but->pos = pos_i;
if (select) {
@@ -1625,7 +1853,7 @@ static int ui_textedit_delete(uiBut *but, uiHandleButtonData *data, int directio
else if (but->pos >= 0 && but->pos < len) {
int pos = but->pos;
int step;
- BLI_str_cursor_step_utf8(str, len, &pos, direction, jump);
+ BLI_str_cursor_step_utf8(str, len, &pos, direction, jump, true);
step = pos - but->pos;
memmove(&str[but->pos], &str[but->pos + step], (len + 1) - but->pos);
changed = 1;
@@ -1640,7 +1868,7 @@ static int ui_textedit_delete(uiBut *but, uiHandleButtonData *data, int directio
int pos = but->pos;
int step;
- BLI_str_cursor_step_utf8(str, len, &pos, direction, jump);
+ BLI_str_cursor_step_utf8(str, len, &pos, direction, jump, true);
step = but->pos - pos;
memmove(&str[but->pos - step], &str[but->pos], (len + 1) - but->pos);
but->pos -= step;
@@ -1674,10 +1902,11 @@ static int ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, int paste
{
char buf[UI_MAX_DRAW_STR] = {0};
char *str, *p, *pbuf;
- int len, x, i, changed = 0;
+ int x, changed = 0;
+ int str_len, buf_len;
str = data->str;
- len = strlen(str);
+ str_len = strlen(str);
/* paste */
if (paste) {
@@ -1687,28 +1916,28 @@ static int ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, int paste
if (p && p[0]) {
unsigned int y;
- i = 0;
- while (*p && *p != '\r' && *p != '\n' && i < UI_MAX_DRAW_STR - 1) {
- buf[i++] = *p;
+ buf_len = 0;
+ while (*p && *p != '\r' && *p != '\n' && buf_len < UI_MAX_DRAW_STR - 1) {
+ buf[buf_len++] = *p;
p++;
}
- buf[i] = 0;
+ buf[buf_len] = 0;
/* paste over the current selection */
if ((but->selend - but->selsta) > 0) {
ui_textedit_delete_selection(but, data);
- len = strlen(str);
+ str_len = strlen(str);
}
- for (y = 0; y < strlen(buf); y++) {
+ for (y = 0; y < buf_len; y++) {
/* add contents of buffer */
- if (len + 1 < data->maxlen) {
+ if (str_len + 1 < data->maxlen) {
for (x = data->maxlen; x > but->pos; x--)
str[x] = str[x - 1];
str[but->pos] = buf[y];
but->pos++;
- len++;
- str[len] = '\0';
+ str_len++;
+ str[str_len] = '\0';
}
}
@@ -1754,6 +1983,10 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
data->str = MEM_callocN(sizeof(char) * data->maxlen + 1, "textedit str");
ui_get_but_string(but, data->str, data->maxlen);
+ if (ui_is_but_float(but) && !ui_is_but_unit(but)) {
+ BLI_str_rstrip_float_zero(data->str, '\0');
+ }
+
if (ELEM3(but->type, NUM, NUMABS, NUMSLI)) {
ui_convert_to_unit_alt_name(but, data->str, data->maxlen);
}
@@ -1772,7 +2005,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
but->selend = len;
/* optional searchbox */
- if (but->type == SEARCH_MENU) {
+ if (ELEM(but->type, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
data->searchbox = ui_searchbox_create(C, data->region, but);
ui_searchbox_update(C, data->searchbox, but, 1); /* 1 = reset */
}
@@ -1818,7 +2051,7 @@ static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
return;
for (but = actbut->next; but; but = but->next) {
- if (ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) {
+ if (ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, IDPOIN, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
if (!(but->flag & UI_BUT_DISABLED)) {
data->postbut = but;
data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
@@ -1827,7 +2060,7 @@ static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
}
}
for (but = block->buttons.first; but != actbut; but = but->next) {
- if (ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) {
+ if (ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, IDPOIN, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
if (!(but->flag & UI_BUT_DISABLED)) {
data->postbut = but;
data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
@@ -1846,7 +2079,7 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
return;
for (but = actbut->prev; but; but = but->prev) {
- if (ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) {
+ if (ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, IDPOIN, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
if (!(but->flag & UI_BUT_DISABLED)) {
data->postbut = but;
data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
@@ -1855,7 +2088,7 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
}
}
for (but = block->buttons.last; but != actbut; but = but->prev) {
- if (ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) {
+ if (ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, IDPOIN, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
if (!(but->flag & UI_BUT_DISABLED)) {
data->postbut = but;
data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
@@ -1866,7 +2099,7 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
}
-static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
int mx, my, changed = 0, inbox = 0, update = 0, retval = WM_UI_HANDLER_CONTINUE;
@@ -1874,6 +2107,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
case WHEELUPMOUSE:
case WHEELDOWNMOUSE:
case MOUSEMOVE:
+ case MOUSEPAN:
if (data->searchbox)
ui_searchbox_event(C, data->searchbox, but, event);
@@ -2057,7 +2291,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
ED_region_tag_redraw(data->region);
}
-static void ui_do_but_textedit_select(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static void ui_do_but_textedit_select(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
int mx, my, retval = WM_UI_HANDLER_CONTINUE;
@@ -2096,7 +2330,7 @@ static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data)
data->coba = (ColorBand *)but->poin;
but->editcoba = data->coba;
}
- else if (ELEM3(but->type, BUT_NORMAL, HSVCUBE, HSVCIRCLE)) {
+ else if (ELEM4(but->type, BUT_NORMAL, HSVCUBE, HSVCIRCLE, COLOR)) {
ui_get_but_vectorf(but, data->origvec);
copy_v3_v3(data->vec, data->origvec);
but->editvec = data->vec;
@@ -2246,7 +2480,7 @@ int ui_button_open_menu_direction(uiBut *but)
/* ***************** events for different button types *************** */
-static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
@@ -2274,7 +2508,7 @@ static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEv
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
@@ -2335,7 +2569,7 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
@@ -2360,7 +2594,7 @@ static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, w
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN) && event->val == KM_PRESS) {
@@ -2385,8 +2619,54 @@ static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ /* unlink icon is on right */
+ if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN) && event->val == KM_PRESS) {
+ ARegion *ar = CTX_wm_region(C);
+ rcti rect;
+ int x = event->x, y = event->y;
+
+ ui_window_to_block(ar, but->block, &x, &y);
+
+ BLI_rcti_rctf_copy(&rect, &but->rect);
+
+ rect.xmin = rect.xmax - (BLI_rcti_size_y(&rect));
+ 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(16, "temp str");
+ data->str[0] = 0;
+
+ ui_apply_but_TEX(C, but, data);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ return ui_do_but_TEX(C, block, but, data, event);
+}
+
+static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
+#ifdef USE_DRAG_TOGGLE
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS && ui_is_but_bool(but)) {
+ data->togdual = event->ctrl;
+ data->togonly = !event->shift;
+ ui_apply_button(C, but->block, but, data, true);
+ button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if (data->state == BUTTON_STATE_WAIT_DRAG) {
+ /* note: the 'BUTTON_STATE_WAIT_DRAG' part of 'ui_do_but_EXIT' could be refactored into its own function */
+ data->applied = false;
+ return ui_do_but_EXIT(C, but, data, event);
+ }
+#endif
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
data->togdual = event->ctrl;
@@ -2398,7 +2678,7 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, wmEv
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
@@ -2415,7 +2695,15 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, wmE
return WM_UI_HANDLER_CONTINUE;
}
}
-
+#ifdef USE_DRAG_TOGGLE
+ if (event->type == LEFTMOUSE && ui_is_but_bool(but)) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ return WM_UI_HANDLER_CONTINUE;
+ }
+#endif
+
if (ELEM3(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 */
@@ -2519,6 +2807,7 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
{
float deler, tempf, softmin, softmax, softrange;
int lvalue, temp, changed = 0;
+ const bool is_float = ui_is_but_float(but);
if (mx == data->draglastx)
return changed;
@@ -2540,7 +2829,7 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
if (ui_is_a_warp_but(but)) {
/* Mouse location isn't screen clamped to the screen so use a linear mapping
* 2px == 1-int, or 1px == 1-ClickStep */
- if (ui_is_but_float(but)) {
+ if (is_float) {
fac *= 0.01f * but->a1;
tempf = (float)data->startvalue + ((float)(mx - data->dragstartx) * fac);
tempf = ui_numedit_apply_snapf(but, tempf, softmin, softmax, softrange, snap);
@@ -2597,21 +2886,21 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
else {
/* Use a non-linear mapping of the mouse drag especially for large floats (normal behavior) */
deler = 500;
- if (!ui_is_but_float(but)) {
+ if (!is_float) {
/* prevent large ranges from getting too out of control */
- if (softrange > 600) deler = powf(softrange, 0.75);
- else if (softrange < 100) deler = 200.0;
+ if (softrange > 600) deler = powf(softrange, 0.75f);
else if (softrange < 25) deler = 50.0;
+ else if (softrange < 100) deler = 100.0;
}
deler /= fac;
- if (softrange > 11) {
+ if ((is_float == true) && (softrange > 11)) {
/* non linear change in mouse input- good for high precicsion */
- data->dragf += (((float)(mx - data->draglastx)) / deler) * (fabsf(data->dragstartx - mx) * 0.002f);
+ data->dragf += (((float)(mx - data->draglastx)) / deler) * (fabsf(mx - data->dragstartx) / 500.0f);
}
- else if (softrange > 129) { /* only scale large int buttons */
+ else if ((is_float == false) && (softrange > 129)) { /* only scale large int buttons */
/* non linear change in mouse input- good for high precicsionm ints need less fine tuning */
- data->dragf += (((float)(mx - data->draglastx)) / deler) * (fabsf(data->dragstartx - mx) * 0.004f);
+ data->dragf += (((float)(mx - data->draglastx)) / deler) * (fabsf(mx - data->dragstartx) / 250.0f);
}
else {
/*no scaling */
@@ -2623,7 +2912,7 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
tempf = (softmin + data->dragf * softrange);
- if (!ui_is_but_float(but)) {
+ if (!is_float) {
temp = floorf(tempf + 0.5f);
temp = ui_numedit_apply_snap(temp, softmin, softmax, snap);
@@ -2655,7 +2944,7 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
return changed;
}
-static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
int mx, my; /* mouse location scaled to fit the UI */
int screen_mx, screen_my; /* mouse location kept at screen pixel coords */
@@ -2668,12 +2957,20 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
ui_window_to_block(data->region, block, &mx, &my);
if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ int type = event->type, val = event->val;
+
+ if (type == MOUSEPAN) {
+ ui_pan_to_scroll(event, &type, &val);
+ }
+
/* XXX hardcoded keymap check.... */
- if (event->type == WHEELDOWNMOUSE && event->alt) {
+ if (type == MOUSEPAN && event->alt)
+ retval = WM_UI_HANDLER_BREAK; /* allow accumulating values, otherwise scrolling gets preference */
+ else if (type == WHEELDOWNMOUSE && event->alt) {
mx = but->rect.xmin;
click = 1;
}
- else if (event->type == WHEELUPMOUSE && event->alt) {
+ else if (type == WHEELUPMOUSE && event->alt) {
mx = but->rect.xmax;
click = 1;
}
@@ -2801,36 +3098,59 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
return retval;
}
-static int ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, const short shift, const short ctrl, int mx)
+static bool ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data,
+ const bool is_horizontal, const bool shift, const bool ctrl, int mx)
{
float deler, f, tempf, softmin, softmax, softrange;
- int temp, lvalue, changed = 0;
+ int temp, lvalue;
+ bool changed = false;
+ float mx_fl, my_fl;
+ /* note, 'offs' is really from the widget drawing rounded corners see 'widget_numslider' */
+ float offs;
softmin = but->softmin;
softmax = but->softmax;
softrange = softmax - softmin;
+ /* yes, 'mx' as both x/y is intentional */
+ ui_mouse_scale_warp(data, mx, mx, &mx_fl, &my_fl, shift);
+
if (but->type == NUMSLI) {
- deler = (BLI_rctf_size_x(&but->rect) - 5.0f * but->aspect);
- }
- else if (but->type == HSVSLI) {
- deler = (BLI_rctf_size_x(&but->rect) / 2.0f - 5.0f * but->aspect);
+ offs = (BLI_rctf_size_y(&but->rect) / 2.0f) * but->aspect;
+ deler = BLI_rctf_size_x(&but->rect) - offs;
}
else if (but->type == SCROLL) {
- int horizontal = (BLI_rctf_size_x(&but->rect) > BLI_rctf_size_y(&but->rect));
- float size = (horizontal) ? BLI_rctf_size_x(&but->rect) : -BLI_rctf_size_y(&but->rect);
+ 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;
}
else {
- deler = (BLI_rctf_size_x(&but->rect) - 5.0f * but->aspect);
+ offs = (BLI_rctf_size_y(&but->rect) / 2.0f) * but->aspect;
+ deler = (BLI_rctf_size_x(&but->rect) - offs);
}
- f = (float)(mx - data->dragstartx) / deler + data->dragfstart;
-
- if (shift)
- f = (f - data->dragfstart) / 10.0f + data->dragfstart;
-
+ f = (mx_fl - data->dragstartx) / deler + data->dragfstart;
CLAMP(f, 0.0f, 1.0f);
+
+
+ /* deal with mouse correction */
+#ifdef USE_CONT_MOUSE_CORRECT
+ if (ui_is_a_warp_but(but)) {
+ /* OK but can go outside bounds */
+ if (is_horizontal) {
+ data->ungrab_mval[0] = (but->rect.xmin + offs / but->aspect) + (f * deler);
+ data->ungrab_mval[1] = BLI_rctf_cent_y(&but->rect);
+ }
+ else {
+ data->ungrab_mval[1] = (but->rect.ymin + offs / but->aspect) + (f * deler);
+ data->ungrab_mval[0] = BLI_rctf_cent_x(&but->rect);
+ }
+ BLI_rctf_clamp_pt_v(&but->rect, data->ungrab_mval);
+ }
+#endif
+ /* done correcting mouse */
+
+
tempf = softmin + f * softrange;
temp = floorf(tempf + 0.5f);
@@ -2866,7 +3186,7 @@ static int ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, const short
if (temp != lvalue) {
data->value = temp;
data->dragchange = 1;
- changed = 1;
+ changed = true;
}
}
else {
@@ -2875,14 +3195,14 @@ static int ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, const short
if (tempf != (float)data->value) {
data->value = tempf;
data->dragchange = 1;
- changed = 1;
+ changed = true;
}
}
return changed;
}
-static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
int mx, my, click = 0;
int retval = WM_UI_HANDLER_CONTINUE;
@@ -2892,12 +3212,20 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
ui_window_to_block(data->region, block, &mx, &my);
if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ int type = event->type, val = event->val;
+
+ if (type == MOUSEPAN) {
+ ui_pan_to_scroll(event, &type, &val);
+ }
+
/* XXX hardcoded keymap check.... */
- if (event->type == WHEELDOWNMOUSE && event->alt) {
+ if (type == MOUSEPAN && event->alt)
+ retval = WM_UI_HANDLER_BREAK; /* allow accumulating values, otherwise scrolling gets preference */
+ else if (type == WHEELDOWNMOUSE && event->alt) {
mx = but->rect.xmin;
click = 2;
}
- else if (event->type == WHEELUPMOUSE && event->alt) {
+ else if (type == WHEELUPMOUSE && event->alt) {
mx = but->rect.xmax;
click = 2;
}
@@ -2945,7 +3273,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
click = 1;
}
else if (event->type == MOUSEMOVE) {
- if (ui_numedit_but_SLI(but, data, event->shift, event->ctrl, mx))
+ if (ui_numedit_but_SLI(but, data, true, event->shift, event->ctrl, mx))
ui_numedit_apply(C, block, but, data);
}
retval = WM_UI_HANDLER_BREAK;
@@ -3018,11 +3346,11 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
return retval;
}
-static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
int mx, my /*, click = 0 */;
int retval = WM_UI_HANDLER_CONTINUE;
- int horizontal = (BLI_rctf_size_x(&but->rect) > BLI_rctf_size_y(&but->rect));
+ bool horizontal = (BLI_rctf_size_x(&but->rect) > BLI_rctf_size_y(&but->rect));
mx = event->x;
my = event->y;
@@ -3059,7 +3387,7 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
else if (event->type == MOUSEMOVE) {
- if (ui_numedit_but_SLI(but, data, 0, 0, (horizontal) ? mx : my))
+ if (ui_numedit_but_SLI(but, data, horizontal, false, false, (horizontal) ? mx : my))
ui_numedit_apply(C, block, but, data);
}
@@ -3070,7 +3398,7 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
}
-static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
@@ -3084,7 +3412,14 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wm
return WM_UI_HANDLER_BREAK;
}
}
-
+#ifdef USE_DRAG_TOGGLE
+ if (event->type == LEFTMOUSE && ui_is_but_bool(but)) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ return WM_UI_HANDLER_BREAK;
+ }
+#endif
/* regular open menu */
if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
@@ -3123,7 +3458,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wm
}
}
else if (but->type == COLOR) {
- if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
+ if (ELEM3(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
float *hsv = ui_block_hsv_get(but->block);
float col[3];
@@ -3132,8 +3467,12 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wm
if (event->type == WHEELDOWNMOUSE)
hsv[2] = CLAMPIS(hsv[2] - 0.05f, 0.0f, 1.0f);
- else
+ else if (event->type == WHEELUPMOUSE)
hsv[2] = CLAMPIS(hsv[2] + 0.05f, 0.0f, 1.0f);
+ else {
+ float fac = 0.005 * (event->y - event->prevy);
+ hsv[2] = CLAMPIS(hsv[2] + fac, 0.0f, 1.0f);
+ }
hsv_to_rgb_v(hsv, data->vec);
ui_set_but_vectorf(but, data->vec);
@@ -3229,7 +3568,7 @@ static int ui_numedit_but_NORMAL(uiBut *but, uiHandleButtonData *data, int mx, i
return changed;
}
-static int ui_do_but_NORMAL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_NORMAL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -3269,6 +3608,19 @@ static int ui_do_but_NORMAL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
return WM_UI_HANDLER_CONTINUE;
}
+/* scales a vector so no axis exceeds max
+ * (could become BLI_math func) */
+static void clamp_axis_max_v3(float v[3], const float max)
+{
+ const float v_max = max_fff(v[0], v[1], v[2]);
+ if (v_max > max) {
+ mul_v3_fl(v, max / v_max);
+ if (v[0] > max) v[0] = max;
+ if (v[1] > max) v[1] = max;
+ if (v[2] > max) v[2] = max;
+ }
+}
+
static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, int my, const short shift)
{
float rgb[3];
@@ -3345,6 +3697,11 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx,
if (color_profile && ((int)but->a1 != UI_GRAD_SV))
ui_block_to_scene_linear_v3(but->block, rgb);
+ /* clamp because with color conversion we can exceed range [#34295] */
+ if ((int)but->a1 == UI_GRAD_V_ALT) {
+ clamp_axis_max_v3(rgb, but->softmax);
+ }
+
copy_v3_v3(data->vec, rgb);
data->draglastx = mx;
@@ -3415,7 +3772,7 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, wmNDOF
ui_set_but_vectorf(but, data->vec);
}
-static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -3615,7 +3972,7 @@ static void ui_ndofedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, wmND
}
-static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
mx = event->x;
@@ -3734,7 +4091,7 @@ static int ui_numedit_but_COLORBAND(uiBut *but, uiHandleButtonData *data, int mx
return changed;
}
-static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
ColorBand *coba;
CBData *cbd;
@@ -3795,20 +4152,27 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap,
- float mx, float my, const short shift)
+static int ui_numedit_but_CURVE(uiBlock *block, uiBut *but, uiHandleButtonData *data, int snap,
+ int evtx, int evty, const short shift)
{
CurveMapping *cumap = (CurveMapping *)but->poin;
CurveMap *cuma = cumap->cm + cumap->cur;
CurveMapPoint *cmp = cuma->curve;
- float fx, fy, zoomx, zoomy /*, offsx, offsy */ /* UNUSED */;
+ float fx, fy, zoomx, zoomy;
+ int mx, my, dragx, dragy;
int a, changed = 0;
+ /* evtx evty and drag coords are absolute mousecoords, prevents errors when editing when layout changes */
+ mx = evtx;
+ my = evty;
+ ui_window_to_block(data->region, block, &mx, &my);
+ dragx = data->draglastx;
+ dragy = data->draglasty;
+ ui_window_to_block(data->region, block, &dragx, &dragy);
+
zoomx = BLI_rctf_size_x(&but->rect) / BLI_rctf_size_x(&cumap->curr);
zoomy = BLI_rctf_size_y(&but->rect) / BLI_rctf_size_y(&cumap->curr);
- /* offsx = cumap->curr.xmin; */
- /* offsy = cumap->curr.ymin; */
-
+
if (snap) {
float d[2];
@@ -3824,8 +4188,8 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap,
const float mval_factor = ui_mouse_scale_warp_factor(shift);
int moved_point = 0; /* for ctrl grid, can't use orig coords because of sorting */
- fx = (mx - data->draglastx) / zoomx;
- fy = (my - data->draglasty) / zoomy;
+ fx = (mx - dragx) / zoomx;
+ fy = (my - dragy) / zoomy;
fx *= mval_factor;
fy *= mval_factor;
@@ -3849,8 +4213,8 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap,
curvemapping_changed(cumap, FALSE);
if (moved_point) {
- data->draglastx = mx;
- data->draglasty = my;
+ data->draglastx = evtx;
+ data->draglasty = evty;
changed = 1;
#ifdef USE_CONT_MOUSE_CORRECT
@@ -3869,8 +4233,8 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap,
data->dragchange = 1; /* mark for selection */
}
else {
- fx = (mx - data->draglastx) / zoomx;
- fy = (my - data->draglasty) / zoomy;
+ fx = (mx - dragx) / zoomx;
+ fy = (my - dragy) / zoomy;
/* clamp for clip */
if (cumap->flag & CUMA_DO_CLIP) {
@@ -3889,8 +4253,8 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap,
cumap->curr.xmax -= fx;
cumap->curr.ymax -= fy;
- data->draglastx = mx;
- data->draglasty = my;
+ data->draglastx = evtx;
+ data->draglasty = evty;
changed = 1;
}
@@ -3898,14 +4262,14 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap,
return changed;
}
-static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
int mx, my, a, changed = 0;
mx = event->x;
my = event->y;
ui_window_to_block(data->region, block, &mx, &my);
-
+
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
CurveMapping *cumap = (CurveMapping *)but->poin;
@@ -3995,11 +4359,11 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt
}
data->dragsel = sel;
-
- data->dragstartx = mx;
- data->dragstarty = my;
- data->draglastx = mx;
- data->draglasty = my;
+
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ data->draglastx = event->x;
+ data->draglasty = event->y;
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
return WM_UI_HANDLER_BREAK;
@@ -4007,8 +4371,9 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt
}
else if (data->state == BUTTON_STATE_NUM_EDITING) {
if (event->type == MOUSEMOVE) {
- if (mx != data->draglastx || my != data->draglasty) {
- if (ui_numedit_but_CURVE(but, data, event->ctrl, mx, my, event->shift))
+ if (event->x != data->draglastx || event->y != data->draglasty) {
+
+ if (ui_numedit_but_CURVE(block, but, data, event->ctrl, event->x, event->y, event->shift))
ui_numedit_apply(C, block, but, data);
}
}
@@ -4063,7 +4428,7 @@ static int ui_numedit_but_HISTOGRAM(uiBut *but, uiHandleButtonData *data, int mx
if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) {
/* resize histogram widget itself */
- hist->height = BLI_rctf_size_y(&but->rect) + (data->dragstarty - my);
+ hist->height = (BLI_rctf_size_y(&but->rect) + (data->dragstarty - my)) / UI_DPI_FAC;
}
else {
/* scale histogram values (dy / 10 for better control) */
@@ -4080,7 +4445,7 @@ static int ui_numedit_but_HISTOGRAM(uiBut *but, uiHandleButtonData *data, int mx
return changed;
}
-static int ui_do_but_HISTOGRAM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_HISTOGRAM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -4147,7 +4512,7 @@ static int ui_numedit_but_WAVEFORM(uiBut *but, uiHandleButtonData *data, int mx,
if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) {
/* resize waveform widget itself */
- scopes->wavefrm_height = BLI_rctf_size_y(&but->rect) + (data->dragstarty - my);
+ scopes->wavefrm_height = (BLI_rctf_size_y(&but->rect) + (data->dragstarty - my)) / UI_DPI_FAC;
}
else {
/* scale waveform values */
@@ -4163,7 +4528,7 @@ static int ui_numedit_but_WAVEFORM(uiBut *but, uiHandleButtonData *data, int mx,
return changed;
}
-static int ui_do_but_WAVEFORM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_WAVEFORM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -4229,7 +4594,7 @@ static int ui_numedit_but_VECTORSCOPE(uiBut *but, uiHandleButtonData *data, int
if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) {
/* resize vectorscope widget itself */
- scopes->vecscope_height = BLI_rctf_size_y(&but->rect) + (data->dragstarty - my);
+ scopes->vecscope_height = (BLI_rctf_size_y(&but->rect) + (data->dragstarty - my)) / UI_DPI_FAC;
}
data->draglastx = mx;
@@ -4238,7 +4603,7 @@ static int ui_numedit_but_VECTORSCOPE(uiBut *but, uiHandleButtonData *data, int
return changed;
}
-static int ui_do_but_VECTORSCOPE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_VECTORSCOPE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -4283,7 +4648,7 @@ static int ui_do_but_VECTORSCOPE(bContext *C, uiBlock *block, uiBut *but, uiHand
}
#ifdef WITH_INTERNATIONAL
-static int ui_do_but_CHARTAB(bContext *UNUSED(C), uiBlock *UNUSED(block), uiBut *UNUSED(but), uiHandleButtonData *UNUSED(data), wmEvent *UNUSED(event))
+static int ui_do_but_CHARTAB(bContext *UNUSED(C), uiBlock *UNUSED(block), uiBut *UNUSED(but), uiHandleButtonData *UNUSED(data), const wmEvent *UNUSED(event))
{
/* XXX 2.50 bad global and state access */
#if 0
@@ -4388,7 +4753,7 @@ static int ui_do_but_CHARTAB(bContext *UNUSED(C), uiBlock *UNUSED(block), uiBut
#endif
-static int ui_do_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
VECCOPY2D(but->linkto, event->mval);
@@ -4432,7 +4797,7 @@ static int ui_numedit_but_TRACKPREVIEW(bContext *C, uiBut *but, uiHandleButtonDa
if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) {
/* resize preview widget itself */
- scopes->track_preview_height = BLI_rctf_size_y(&but->rect) + (data->dragstarty - my);
+ scopes->track_preview_height = (BLI_rctf_size_y(&but->rect) + (data->dragstarty - my)) / UI_DPI_FAC;
}
else {
if (!scopes->track_locked) {
@@ -4455,7 +4820,7 @@ static int ui_numedit_but_TRACKPREVIEW(bContext *C, uiBut *but, uiHandleButtonDa
return changed;
}
-static int ui_do_but_TRACKPREVIEW(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+static int ui_do_but_TRACKPREVIEW(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -4530,7 +4895,7 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
wmKeyMapItem *kmi;
PointerRNA ptr;
uiLayout *layout;
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_GetStyleDraw();
IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
int kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, 1, &km);
@@ -4562,7 +4927,7 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
wmKeyMapItem *kmi;
PointerRNA ptr;
uiLayout *layout;
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_GetStyleDraw();
IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
int kmi_id;
@@ -4629,10 +4994,9 @@ static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
static int ui_but_menu(bContext *C, uiBut *but)
{
- ARegion *ar = CTX_wm_region(C);
uiPopupMenu *pup;
uiLayout *layout;
- int length;
+ bool is_array, is_array_component;
const char *name;
uiStringInfo label = {BUT_GET_LABEL, NULL};
@@ -4653,18 +5017,20 @@ static int ui_but_menu(bContext *C, uiBut *but)
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
if (but->rnapoin.data && but->rnaprop) {
- short is_anim = RNA_property_animateable(&but->rnapoin, but->rnaprop);
+ bool is_anim = RNA_property_animateable(&but->rnapoin, but->rnaprop);
/* second slower test, saved people finding keyframe items in menus when its not possible */
if (is_anim)
is_anim = RNA_property_path_from_ID_check(&but->rnapoin, but->rnaprop);
- length = RNA_property_array_length(&but->rnapoin, but->rnaprop);
+ /* determine if we can key a single component of an array */
+ is_array = RNA_property_array_length(&but->rnapoin, but->rnaprop) != 0;
+ is_array_component = (is_array && but->rnaindex != -1);
/* Keyframes */
if (but->flag & UI_BUT_ANIMATED_KEY) {
/* replace/delete keyfraemes */
- if (length) {
+ if (is_array_component) {
uiItemBooleanO(layout, CTX_IFACE_(BLF_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"),
@@ -4676,9 +5042,9 @@ static int ui_but_menu(bContext *C, uiBut *but)
}
else {
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframe"),
- ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0);
+ ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 1);
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframe"),
- ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 0);
+ ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 1);
}
/* keyframe settings */
@@ -4690,7 +5056,7 @@ static int ui_but_menu(bContext *C, uiBut *but)
/* pass */
}
else if (is_anim) {
- if (length) {
+ if (is_array_component) {
uiItemBooleanO(layout, CTX_IFACE_(BLF_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"),
@@ -4698,12 +5064,12 @@ static int ui_but_menu(bContext *C, uiBut *but)
}
else {
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframe"),
- ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0);
+ ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 1);
}
}
if (but->flag & UI_BUT_ANIMATED) {
- if (length) {
+ if (is_array_component) {
uiItemBooleanO(layout, CTX_IFACE_(BLF_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"),
@@ -4711,7 +5077,7 @@ static int ui_but_menu(bContext *C, uiBut *but)
}
else {
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"),
- ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 0);
+ ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 1);
}
}
@@ -4719,7 +5085,7 @@ static int ui_but_menu(bContext *C, uiBut *but)
if (but->flag & UI_BUT_DRIVEN) {
uiItemS(layout);
- if (length) {
+ if (is_array_component) {
uiItemBooleanO(layout, CTX_IFACE_(BLF_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"),
@@ -4727,7 +5093,7 @@ static int ui_but_menu(bContext *C, uiBut *but)
}
else {
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Driver"),
- ICON_NONE, "ANIM_OT_driver_button_remove", "all", 0);
+ ICON_NONE, "ANIM_OT_driver_button_remove", "all", 1);
}
uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Driver"),
@@ -4743,7 +5109,7 @@ static int ui_but_menu(bContext *C, uiBut *but)
else if (is_anim) {
uiItemS(layout);
- if (length) {
+ if (is_array_component) {
uiItemBooleanO(layout, CTX_IFACE_(BLF_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"),
@@ -4751,7 +5117,7 @@ static int ui_but_menu(bContext *C, uiBut *but)
}
else {
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"),
- ICON_NONE, "ANIM_OT_driver_button_add", "all", 0);
+ ICON_NONE, "ANIM_OT_driver_button_add", "all", 1);
}
if (ANIM_driver_can_paste()) {
@@ -4765,7 +5131,7 @@ static int ui_but_menu(bContext *C, uiBut *but)
if (is_anim) {
uiItemS(layout);
- if (length) {
+ if (is_array_component) {
uiItemBooleanO(layout, CTX_IFACE_(BLF_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"),
@@ -4775,7 +5141,7 @@ static int ui_but_menu(bContext *C, uiBut *but)
}
else {
uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add to Keying Set"),
- ICON_NONE, "ANIM_OT_keyingset_button_add", "all", 0);
+ ICON_NONE, "ANIM_OT_keyingset_button_add", "all", 1);
uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"),
ICON_NONE, "ANIM_OT_keyingset_button_remove");
}
@@ -4788,15 +5154,15 @@ static int ui_but_menu(bContext *C, uiBut *but)
/* Copy Property Value
* Paste Property Value */
- if (length) {
+ if (is_array_component) {
uiItemBooleanO(layout, CTX_IFACE_(BLF_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"),
ICON_NONE, "UI_OT_reset_default_button", "all", 0);
}
else {
- uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Reset to Default Value"),
- ICON_NONE, "UI_OT_reset_default_button");
+ uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Reset to Default Value"),
+ ICON_NONE, "UI_OT_reset_default_button", "all", 1);
}
uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Data Path"),
@@ -4845,9 +5211,13 @@ static int ui_but_menu(bContext *C, uiBut *but)
}
/* Show header tools for header buttons. */
- if (ar->regiontype == RGN_TYPE_HEADER) {
- uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL);
- uiItemS(layout);
+ if (CTX_wm_region(C)) {
+ ARegion *ar = CTX_wm_region(C);
+ if (ar->regiontype == RGN_TYPE_HEADER) {
+
+ uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL);
+ uiItemS(layout);
+ }
}
{ /* Docs */
@@ -4912,7 +5282,7 @@ static int ui_but_menu(bContext *C, uiBut *but)
return 1;
}
-static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
+static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *event)
{
uiHandleButtonData *data;
int retval;
@@ -5047,7 +5417,6 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
break;
case SLI:
case NUMSLI:
- case HSVSLI:
retval = ui_do_but_SLI(C, block, but, data, event);
break;
case ROUNDBOX:
@@ -5058,6 +5427,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
case LISTROW:
case BUT_IMAGE:
case PROGRESSBAR:
+ case NODESOCKET:
retval = ui_do_but_EXIT(C, but, data, event);
break;
case HISTOGRAM:
@@ -5074,6 +5444,9 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
case SEARCH_MENU:
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 ICONROW:
case ICONTEXTROW:
@@ -5187,7 +5560,7 @@ int UI_but_active_drop_name(bContext *C)
uiBut *but = ui_but_find_activated(ar);
if (but) {
- if (ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU))
+ if (ELEM4(but->type, TEX, IDPOIN, SEARCH_MENU, SEARCH_MENU_UNLINK))
return 1;
}
@@ -5226,32 +5599,15 @@ static int ui_mouse_inside_region(ARegion *ar, int x, int y)
*/
if (ar->v2d.mask.xmin != ar->v2d.mask.xmax) {
View2D *v2d = &ar->v2d;
- rcti mask_rct;
int mx, my;
/* convert window coordinates to region coordinates */
mx = x;
my = y;
ui_window_to_region(ar, &mx, &my);
-
- /* make a copy of the mask rect, and tweak accordingly for hidden scrollbars */
- mask_rct = v2d->mask;
-
- if (v2d->scroll & (V2D_SCROLL_VERTICAL_HIDE | V2D_SCROLL_VERTICAL_FULLR)) {
- if (v2d->scroll & V2D_SCROLL_LEFT)
- mask_rct.xmin = v2d->vert.xmin;
- else if (v2d->scroll & V2D_SCROLL_RIGHT)
- mask_rct.xmax = v2d->vert.xmax;
- }
- if (v2d->scroll & (V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_HORIZONTAL_FULLR)) {
- if (v2d->scroll & (V2D_SCROLL_BOTTOM | V2D_SCROLL_BOTTOM_O))
- mask_rct.ymin = v2d->hor.ymin;
- else if (v2d->scroll & V2D_SCROLL_TOP)
- mask_rct.ymax = v2d->hor.ymax;
- }
-
+
/* check if in the rect */
- if (!BLI_rcti_isect_pt(&mask_rct, mx, my))
+ if (!BLI_rcti_isect_pt(&v2d->mask, mx, my))
return 0;
}
@@ -5271,7 +5627,25 @@ static int ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y)
return 1;
}
-static uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
+/**
+ * Can we mouse over the button or is it hidden/disabled/layout.
+ */
+bool ui_is_but_interactive(uiBut *but)
+{
+ /* note, LABEL is included for highlights, this allows drags */
+ if (but->type == LABEL && but->dragpoin == NULL)
+ return false;
+ if (ELEM3(but->type, ROUNDBOX, SEPR, LISTBOX))
+ return false;
+ if (but->flag & UI_HIDDEN)
+ return false;
+ if (but->flag & UI_SCROLLED)
+ return false;
+
+ return true;
+}
+
+uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
{
uiBlock *block;
uiBut *but, *butover = NULL;
@@ -5288,17 +5662,11 @@ static uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
ui_window_to_block(ar, block, &mx, &my);
for (but = block->buttons.first; but; but = but->next) {
- /* note, LABEL is included for highlights, this allows drags */
- if (but->type == LABEL && but->dragpoin == NULL)
- continue;
- if (ELEM3(but->type, ROUNDBOX, SEPR, LISTBOX))
- continue;
- if (but->flag & UI_HIDDEN)
- continue;
- if (but->flag & UI_SCROLLED)
- continue;
- if (ui_but_contains_pt(but, mx, my))
- butover = but;
+ if (ui_is_but_interactive(but)) {
+ if (ui_but_contains_pt(but, mx, my)) {
+ butover = but;
+ }
+ }
}
/* CLIP_EVENTS prevents the event from reaching other blocks */
@@ -5530,7 +5898,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)) {
+ if (ELEM3(but->type, BUT_CURVE, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
/* XXX curve is temp */
}
else {
@@ -5585,7 +5953,8 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
button_activate_state(C, but, BUTTON_STATE_WAIT_FLASH);
}
-static void button_activate_exit(bContext *C, uiHandleButtonData *data, uiBut *but, int mousemove, int onfree)
+static void button_activate_exit(bContext *C, uiBut *but, uiHandleButtonData *data,
+ const bool mousemove, const bool onfree)
{
uiBlock *block = but->block;
uiBut *bt;
@@ -5613,7 +5982,8 @@ static void button_activate_exit(bContext *C, uiHandleButtonData *data, uiBut *b
if (!onfree && !data->cancel) {
/* autokey & undo push */
- ui_apply_autokey_undo(C, but);
+ ui_apply_undo(but);
+ ui_apply_autokey(C, but);
/* popup menu memory */
if (block->flag & UI_BLOCK_POPUP_MEMORY)
@@ -5638,10 +6008,13 @@ static void button_activate_exit(bContext *C, uiHandleButtonData *data, uiBut *b
/* redraw (data is but->active!) */
ED_region_tag_redraw(data->region);
-
+
/* clean up button */
- MEM_freeN(but->active);
- but->active = NULL;
+ if (but->active) {
+ MEM_freeN(but->active);
+ but->active = NULL;
+ }
+
but->flag &= ~(UI_ACTIVE | UI_SELECT);
but->flag |= UI_BUT_LAST_ACTIVE;
if (!onfree)
@@ -5664,7 +6037,7 @@ void ui_button_active_free(const bContext *C, uiBut *but)
if (but->active) {
data = but->active;
data->cancel = TRUE;
- button_activate_exit((bContext *)C, data, but, 0, 1);
+ button_activate_exit((bContext *)C, but, data, false, true);
}
}
@@ -5839,7 +6212,7 @@ void uiContextAnimUpdate(const bContext *C)
/************** handle activating a button *************/
-static uiBut *uit_but_find_open_event(ARegion *ar, wmEvent *event)
+static uiBut *uit_but_find_open_event(ARegion *ar, const wmEvent *event)
{
uiBlock *block;
uiBut *but;
@@ -5852,7 +6225,7 @@ static uiBut *uit_but_find_open_event(ARegion *ar, wmEvent *event)
return NULL;
}
-static int ui_handle_button_over(bContext *C, wmEvent *event, ARegion *ar)
+static int ui_handle_button_over(bContext *C, const wmEvent *event, ARegion *ar)
{
uiBut *but;
@@ -5890,6 +6263,21 @@ void ui_button_activate_do(bContext *C, ARegion *ar, uiBut *but)
ui_do_button(C, but->block, but, &event);
}
+void ui_button_execute_do(struct bContext *C, struct ARegion *ar, uiBut *but)
+{
+ /* note: ideally we would not have to change 'but->active' howevwer
+ * some functions we call don't use data (as they should be doing) */
+ void *active_back = but->active;
+ uiHandleButtonData *data = MEM_callocN(sizeof(uiHandleButtonData), "uiHandleButtonData_Fake");
+ but->active = data;
+ data->region = ar;
+ ui_apply_button(C, but->block, but, data, true);
+ /* use onfree event so undo is handled by caller and apply is already done above */
+ ui_apply_autokey(C, but);
+ button_activate_exit((bContext *)C, but, data, false, true);
+ but->active = active_back;
+}
+
static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type)
{
uiBut *oldbut;
@@ -5899,7 +6287,7 @@ static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiBu
if (oldbut) {
data = oldbut->active;
data->cancel = TRUE;
- button_activate_exit(C, data, oldbut, 0, 0);
+ button_activate_exit(C, oldbut, data, false, false);
}
button_activate_init(C, ar, but, type);
@@ -5907,16 +6295,14 @@ static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiBu
/************ handle events for an activated button ***********/
-static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
+static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
{
- uiHandleButtonData *data;
+ uiHandleButtonData *data = but->active;
+ const uiHandleButtonState state_orig = data->state;
uiBlock *block;
ARegion *ar;
- uiBut *postbut;
- uiButtonActivateType posttype;
int retval;
- data = but->active;
block = but->block;
ar = data->region;
@@ -5968,19 +6354,18 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
retval = WM_UI_HANDLER_CONTINUE;
break;
- case WHEELUPMOUSE:
- case WHEELDOWNMOUSE:
- case MIDDLEMOUSE:
- /* XXX hardcoded keymap check... but anyway, while view changes, tooltips should be removed */
- if (data->tooltiptimer) {
- WM_event_remove_timer(data->wm, data->window, data->tooltiptimer);
- data->tooltiptimer = NULL;
- }
- /* pass on purposedly */
- default:
- /* handle button type specific events */
- retval = ui_do_button(C, block, but, event);
}
+ /* 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);
+
+ /* pass on purposedly */
+ default:
+ /* handle button type specific events */
+ retval = ui_do_button(C, block, but, event);
}
}
else if (data->state == BUTTON_STATE_WAIT_RELEASE) {
@@ -6069,82 +6454,113 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
}
if (data->state == BUTTON_STATE_EXIT) {
- postbut = data->postbut;
- posttype = data->posttype;
+ uiBut *post_but = data->postbut;
+ uiButtonActivateType post_type = data->posttype;
- button_activate_exit(C, data, but, (postbut == NULL), 0);
+ button_activate_exit(C, but, data, (post_but == NULL), false);
/* for jumping to the next button with tab while text editing */
- if (postbut)
- button_activate_init(C, ar, postbut, posttype);
+ if (post_but) {
+ button_activate_init(C, ar, post_but, post_type);
+ }
+ else {
+ /* XXX issue is because WM_event_add_mousemove(C) is a bad hack and not reliable,
+ *if that gets coded better this bypass can go away too.
+ *
+ * This is needed to make sure if a button was active,
+ * it stays active while the mouse is over it.
+ * This avoids adding mousemoves, see: [#33466] */
+ if (ELEM(state_orig, BUTTON_STATE_INIT, BUTTON_STATE_HIGHLIGHT)) {
+ if (ui_but_find_mouse_over(ar, event->x, event->y) == but) {
+ button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+ }
+ }
+ }
}
return retval;
}
-static int ui_handle_list_event(bContext *C, wmEvent *event, ARegion *ar)
+static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar)
{
uiBut *but = ui_list_find_mouse_over(ar, event->x, event->y);
int retval = WM_UI_HANDLER_CONTINUE;
int value, min, max;
+ int type = event->type, val = event->val;
- if (but && (event->val == KM_PRESS)) {
- Panel *pa = but->block->panel;
+ if (but) {
+ uiList *ui_list = but->custom_data;
- if (ELEM(event->type, UPARROWKEY, DOWNARROWKEY) ||
- ((ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt)))
- {
- /* activate up/down the list */
- value = RNA_property_int_get(&but->rnapoin, but->rnaprop);
+ if (ui_list) {
+
+ /* convert pan to scrollwheel */
+ if (type == MOUSEPAN) {
+ ui_pan_to_scroll(event, &type, &val);
+
+ /* if type still is mousepan, we call it handled, since delta-y accumulate */
+ /* also see wm_event_system.c do_wheel_ui hack */
+ if (type == MOUSEPAN)
+ retval = WM_UI_HANDLER_BREAK;
+ }
+
+ if (val == KM_PRESS) {
+
+ if (ELEM(type, UPARROWKEY, DOWNARROWKEY) ||
+ ((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt)))
+ {
+ /* activate up/down the list */
+ value = RNA_property_int_get(&but->rnapoin, but->rnaprop);
- if (ELEM(event->type, UPARROWKEY, WHEELUPMOUSE))
- value--;
- else
- value++;
+ if (ELEM(type, UPARROWKEY, WHEELUPMOUSE))
+ value--;
+ else
+ value++;
- CLAMP(value, 0, pa->list_last_len - 1);
+ CLAMP(value, 0, ui_list->list_last_len - 1);
- if (value < pa->list_scroll)
- pa->list_scroll = value;
- else if (value >= pa->list_scroll + pa->list_size)
- pa->list_scroll = value - pa->list_size + 1;
+ if (value < ui_list->list_scroll)
+ ui_list->list_scroll = value;
+ else if (value >= ui_list->list_scroll + ui_list->list_size)
+ ui_list->list_scroll = value - ui_list->list_size + 1;
- RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max);
- value = CLAMPIS(value, min, max);
+ RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max);
+ value = CLAMPIS(value, min, max);
- RNA_property_int_set(&but->rnapoin, but->rnaprop, value);
- RNA_property_update(C, &but->rnapoin, but->rnaprop);
- ED_region_tag_redraw(ar);
+ RNA_property_int_set(&but->rnapoin, but->rnaprop, value);
+ RNA_property_update(C, &but->rnapoin, but->rnaprop);
+ ED_region_tag_redraw(ar);
- retval = WM_UI_HANDLER_BREAK;
- }
- else if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
- /* silly replacement for proper grip */
- if (pa->list_grip_size == 0)
- pa->list_grip_size = pa->list_size;
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
+ /* silly replacement for proper grip */
+ if (ui_list->list_grip_size == 0)
+ ui_list->list_grip_size = ui_list->list_size;
- if (event->type == WHEELUPMOUSE)
- pa->list_grip_size--;
- else
- pa->list_grip_size++;
+ if (type == WHEELUPMOUSE)
+ ui_list->list_grip_size--;
+ else
+ ui_list->list_grip_size++;
- pa->list_grip_size = MAX2(pa->list_grip_size, 1);
+ ui_list->list_grip_size = MAX2(ui_list->list_grip_size, 1);
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- retval = WM_UI_HANDLER_BREAK;
- }
- else if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
- if (pa->list_last_len > pa->list_size) {
- /* list template will clamp */
- if (event->type == WHEELUPMOUSE)
- pa->list_scroll--;
- else
- pa->list_scroll++;
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
+ if (ui_list->list_last_len > ui_list->list_size) {
+ /* list template will clamp */
+ if (type == WHEELUPMOUSE)
+ ui_list->list_scroll--;
+ else
+ ui_list->list_scroll++;
- ED_region_tag_redraw(ar);
+ ED_region_tag_redraw(ar);
- retval = WM_UI_HANDLER_BREAK;
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
}
}
}
@@ -6152,7 +6568,7 @@ static int ui_handle_list_event(bContext *C, wmEvent *event, ARegion *ar)
return retval;
}
-static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut *but)
+static void ui_handle_button_return_submenu(bContext *C, const wmEvent *event, uiBut *but)
{
uiHandleButtonData *data;
uiPopupBlockHandle *menu;
@@ -6184,7 +6600,7 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut *
if (menu->menuretval != UI_RETURN_OK)
data->cancel = TRUE;
- button_activate_exit(C, data, but, 1, 0);
+ 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)) {
@@ -6198,7 +6614,7 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut *
}
else {
data->cancel = TRUE;
- button_activate_exit(C, data, but, 1, 0);
+ button_activate_exit(C, but, data, true, false);
}
}
}
@@ -6324,7 +6740,7 @@ static int ui_menu_scroll(ARegion *ar, uiBlock *block, int my, uiBut *to_bt)
for (bt = block->buttons.first; bt; bt = bt->next)
ymax = max_ff(ymax, bt->rect.ymax);
- if (ymax + dy - UI_UNIT_Y*0.5f < block->rect.ymax - UI_MENU_SCROLL_PAD)
+ if (ymax + dy - UI_UNIT_Y * 0.5f < block->rect.ymax - UI_MENU_SCROLL_PAD)
dy = block->rect.ymax - ymax - UI_MENU_SCROLL_PAD;
}
else {
@@ -6334,7 +6750,7 @@ static int ui_menu_scroll(ARegion *ar, uiBlock *block, int my, uiBut *to_bt)
for (bt = block->buttons.first; bt; bt = bt->next)
ymin = min_ff(ymin, bt->rect.ymin);
- if (ymin + dy + UI_UNIT_Y*0.5f > block->rect.ymin + UI_MENU_SCROLL_PAD)
+ if (ymin + dy + UI_UNIT_Y * 0.5f > block->rect.ymin + UI_MENU_SCROLL_PAD)
dy = block->rect.ymin - ymin + UI_MENU_SCROLL_PAD;
}
@@ -6355,7 +6771,7 @@ static int ui_menu_scroll(ARegion *ar, uiBlock *block, int my, uiBut *to_bt)
return 0;
}
-static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle *menu, int level)
+static int ui_handle_menu_event(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu, int level)
{
ARegion *ar;
uiBlock *block;
@@ -6377,7 +6793,7 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
/* if there's an active modal button, don't check events or outside, except for search menu */
but = ui_but_find_activated(ar);
- if (but && button_modal_state(but->active->state) && but->type != SEARCH_MENU) {
+ if (but && button_modal_state(but->active->state) && but->type != SEARCH_MENU && but->type != SEARCH_MENU_UNLINK) {
/* if a button is activated modal, always reset the start mouse
* position of the towards mechanism to avoid loosing focus,
* and don't handle events */
@@ -6403,7 +6819,7 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
if (block->block_event_func && block->block_event_func(C, block, event)) {
/* pass */
} /* events not for active search menu button */
- else if (but == NULL || but->type != SEARCH_MENU) {
+ else if (but == NULL || (but->type != SEARCH_MENU && but->type != SEARCH_MENU_UNLINK)) {
switch (event->type) {
@@ -6450,31 +6866,40 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
case DOWNARROWKEY:
case WHEELUPMOUSE:
case WHEELDOWNMOUSE:
+ case MOUSEPAN:
/* arrowkeys: only handle for block_loop blocks */
if (event->alt || event->shift || event->ctrl || event->oskey) {
/* pass */
}
else if (inside || (block->flag & UI_BLOCK_LOOP)) {
- if (event->val == KM_PRESS) {
+ int type = event->type;
+ int val = event->val;
+
+ /* convert pan to scrollwheel */
+ if (type == MOUSEPAN)
+ ui_pan_to_scroll(event, &type, &val);
+
+ if (val == KM_PRESS) {
+ const eButType type_flip = BUT | ROW;
PASS_EVENT_TO_PARENT_IF_NONACTIVE;
but = ui_but_find_activated(ar);
if (but) {
/* is there a situation where UI_LEFT or UI_RIGHT would also change navigation direction? */
- if (((ELEM(event->type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_DOWN)) ||
- ((ELEM(event->type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_RIGHT)) ||
- ((ELEM(event->type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_TOP)))
+ 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 & BUT)
+ if (but->type & type_flip)
but = ui_but_next(but);
else
but = ui_but_prev(but);
}
else {
- if (but->type & BUT)
+ if (but->type & type_flip)
but = ui_but_prev(but);
else
but = ui_but_next(but);
@@ -6487,11 +6912,11 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
}
if (!but) {
- if (((ELEM(event->type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_DOWN)) ||
- ((ELEM(event->type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_RIGHT)) ||
- ((ELEM(event->type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_TOP)))
+ 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 & BUT)) {
+ if ((bt = ui_but_first(block)) && (bt->type & type_flip)) {
bt = ui_but_last(block);
}
else {
@@ -6499,7 +6924,7 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
}
}
else {
- if ((bt = ui_but_first(block)) && (bt->type & BUT)) {
+ if ((bt = ui_but_first(block)) && (bt->type & type_flip)) {
/* keep ui_but_first() */
}
else {
@@ -6757,7 +7182,7 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
return retval;
}
-static int ui_handle_menu_return_submenu(bContext *C, wmEvent *event, uiPopupBlockHandle *menu)
+static int ui_handle_menu_return_submenu(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu)
{
ARegion *ar;
uiBut *but;
@@ -6806,7 +7231,7 @@ static int ui_handle_menu_return_submenu(bContext *C, wmEvent *event, uiPopupBlo
return WM_UI_HANDLER_BREAK;
}
-static int ui_handle_menus_recursive(bContext *C, wmEvent *event, uiPopupBlockHandle *menu, int level)
+static int ui_handle_menus_recursive(bContext *C, const wmEvent *event, uiPopupBlockHandle *menu, int level)
{
uiBut *but;
uiHandleButtonData *data;
@@ -6828,7 +7253,7 @@ static int ui_handle_menus_recursive(bContext *C, wmEvent *event, uiPopupBlockHa
retval = ui_handle_menu_return_submenu(C, event, menu);
submenu = NULL; /* hint not to use this, it may be freed by call above */
(void)submenu;
- /* we may wan't to quit the submenu and handle the even in this menu,
+ /* we may want to quit the submenu and handle the even in this menu,
* if its important to use it, check 'data->menu' first */
if ((retval == WM_UI_HANDLER_BREAK) && do_ret_out_parent) {
retval = ui_handle_menu_event(C, event, menu, level);
@@ -6844,7 +7269,7 @@ static int ui_handle_menus_recursive(bContext *C, wmEvent *event, uiPopupBlockHa
/* *************** UI event handlers **************** */
-static int ui_handler_region(bContext *C, wmEvent *event, void *UNUSED(userdata))
+static int ui_handler_region(bContext *C, const wmEvent *event, void *UNUSED(userdata))
{
ARegion *ar;
uiBut *but;
@@ -6902,12 +7327,10 @@ static void ui_handler_remove_region(bContext *C, void *UNUSED(userdata))
ui_apply_but_funcs_after(C);
}
-static int ui_handler_region_menu(bContext *C, wmEvent *event, void *UNUSED(userdata))
+static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSED(userdata))
{
ARegion *ar;
uiBut *but;
- uiHandleButtonData *data;
- int retval;
/* here we handle buttons at the window level, modal, for example
* while number sliding, text editing, or when a menu block is open */
@@ -6918,17 +7341,24 @@ static int ui_handler_region_menu(bContext *C, wmEvent *event, void *UNUSED(user
but = ui_but_find_activated(ar);
if (but) {
+ uiHandleButtonData *data;
+
/* handle activated button events */
data = but->active;
if (data->state == BUTTON_STATE_MENU_OPEN) {
+ int retval;
+
/* handle events for menus and their buttons recursively,
* this will handle events from the top to the bottom menu */
- retval = ui_handle_menus_recursive(C, event, data->menu, 0);
+ if (data->menu)
+ retval = ui_handle_menus_recursive(C, event, data->menu, 0);
/* handle events for the activated button */
- if (retval == WM_UI_HANDLER_CONTINUE || event->type == TIMER) {
- if (data->menu->menuretval)
+ if ((data->menu && (retval == WM_UI_HANDLER_CONTINUE)) ||
+ (event->type == TIMER))
+ {
+ if (data->menu && data->menu->menuretval)
ui_handle_button_return_submenu(C, event, but);
else
ui_handle_button_event(C, event, but);
@@ -6952,7 +7382,7 @@ static int ui_handler_region_menu(bContext *C, wmEvent *event, void *UNUSED(user
}
/* two types of popups, one with operator + enum, other with regular callbacks */
-static int ui_handler_popup(bContext *C, wmEvent *event, void *userdata)
+static int ui_handler_popup(bContext *C, const wmEvent *event, void *userdata)
{
uiPopupBlockHandle *menu = userdata;
@@ -6985,7 +7415,7 @@ static int ui_handler_popup(bContext *C, wmEvent *event, void *userdata)
WM_operator_name_call(C, temp.optype->idname, temp.opcontext, NULL);
}
else if (temp.cancel_func)
- temp.cancel_func(temp.popup_arg);
+ temp.cancel_func(C, temp.popup_arg);
}
else {
/* re-enable tooltips */
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index bb0cc1176d8..09686d7b416 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -47,8 +47,10 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_fileops_types.h"
#include "DNA_brush_types.h"
+#include "DNA_dynamicpaint_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -74,21 +76,19 @@
#include "interface_intern.h"
-
-#define ICON_IMAGE_W 600
-#define ICON_IMAGE_H 640
-
#define ICON_GRID_COLS 26
#define ICON_GRID_ROWS 30
-#define ICON_GRID_MARGIN 5
-#define ICON_GRID_W 16
-#define ICON_GRID_H 16
+#define ICON_GRID_MARGIN 10
+#define ICON_GRID_W 32
+#define ICON_GRID_H 32
typedef struct IconImage {
int w;
int h;
- unsigned int *rect;
+ unsigned int *rect;
+ unsigned char *datatoc_rect;
+ int datatoc_size;
} IconImage;
typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
@@ -131,13 +131,13 @@ static IconTexture icongltex = {0, 0, 0, 0.0f, 0.0f};
/* **************************************************** */
-static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int size, int type)
+#ifndef WITH_HEADLESS
+
+static DrawInfo *def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int size, int type)
{
Icon *new_icon = NULL;
IconImage *iimg = NULL;
DrawInfo *di;
- int y = 0;
- int imgsize = 0;
new_icon = MEM_callocN(sizeof(Icon), "texicon");
@@ -154,17 +154,27 @@ static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int
di->data.texture.h = size;
}
else if (type == ICON_TYPE_BUFFER) {
- iimg = MEM_mallocN(sizeof(IconImage), "icon_img");
- iimg->rect = MEM_mallocN(size * size * sizeof(unsigned int), "icon_rect");
+ iimg = MEM_callocN(sizeof(IconImage), "icon_img");
iimg->w = size;
iimg->h = size;
- /* Here we store the rect in the icon - same as before */
- imgsize = bbuf->x;
- for (y = 0; y < size; y++) {
- memcpy(&iimg->rect[y * size], &bbuf->rect[(y + yofs) * imgsize + xofs], size * sizeof(int));
+ /* icon buffers can get initialized runtime now, via datatoc */
+ if (bbuf) {
+ int y, imgsize;
+
+ iimg->rect = MEM_mallocN(size * size * sizeof(unsigned int), "icon_rect");
+
+ /* Here we store the rect in the icon - same as before */
+ if (size == bbuf->x && size == bbuf->y && xofs == 0 && yofs == 0)
+ memcpy(iimg->rect, bbuf->rect, size * size * sizeof(int));
+ else {
+ /* this code assumes square images */
+ imgsize = bbuf->x;
+ for (y = 0; y < size; y++) {
+ memcpy(&iimg->rect[y * size], &bbuf->rect[(y + yofs) * imgsize + xofs], size * sizeof(int));
+ }
+ }
}
-
di->data.buffer.image = iimg;
}
@@ -172,6 +182,8 @@ static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int
new_icon->drawinfo = di;
BKE_icon_set(icon_id, new_icon);
+
+ return di;
}
static void def_internal_vicon(int icon_id, VectorDrawFunc drawFunc)
@@ -459,21 +471,23 @@ static void vicon_move_down_draw(int x, int y, int w, int h, float UNUSED(alpha)
}
#ifndef WITH_HEADLESS
+
static void init_brush_icons(void)
{
-#define INIT_BRUSH_ICON(icon_id, name) \
- { \
- bbuf = IMB_ibImageFromMemory((unsigned char *)datatoc_ ##name## _png, \
- datatoc_ ##name## _png_size, \
- IB_rect, NULL, "<brush icon>"); \
- def_internal_icon(bbuf, icon_id, 0, 0, w, ICON_TYPE_BUFFER); \
- IMB_freeImBuf(bbuf); \
- } (void)0
+#define INIT_BRUSH_ICON(icon_id, name) \
+ { \
+ unsigned char *rect = (unsigned char *)datatoc_ ##name## _png; \
+ int size = datatoc_ ##name## _png_size; \
+ DrawInfo *di; \
+ \
+ di = def_internal_icon(NULL, icon_id, 0, 0, w, ICON_TYPE_BUFFER); \
+ di->data.buffer.image->datatoc_rect = rect; \
+ di->data.buffer.image->datatoc_size = size; \
+ }
/* end INIT_BRUSH_ICON */
- ImBuf *bbuf;
- const int w = 96;
+ const int w = 96; /* warning, brush size hardcoded in C, but it gets scaled */
INIT_BRUSH_ICON(ICON_BRUSH_ADD, add);
INIT_BRUSH_ICON(ICON_BRUSH_BLOB, blob);
@@ -509,15 +523,79 @@ static void init_brush_icons(void)
#undef INIT_BRUSH_ICON
}
+static void icon_verify_datatoc(IconImage *iimg)
+{
+ /* if it has own rect, things are all OK */
+ if (iimg->rect)
+ return;
+
+ if (iimg->datatoc_rect) {
+ ImBuf *bbuf = IMB_ibImageFromMemory(iimg->datatoc_rect,
+ iimg->datatoc_size, IB_rect, NULL, "<matcap icon>");
+ /* w and h were set on initialize */
+ if (bbuf->x != iimg->h && bbuf->y != iimg->w)
+ IMB_scaleImBuf(bbuf, iimg->w, iimg->h);
+
+ iimg->rect = bbuf->rect;
+ bbuf->rect = NULL;
+ IMB_freeImBuf(bbuf);
+ }
+}
+
+static void init_matcap_icons(void)
+{
+ /* dynamic allocation now, tucking datatoc pointers in DrawInfo */
+#define INIT_MATCAP_ICON(icon_id, name) \
+ { \
+ unsigned char *rect = (unsigned char *)datatoc_ ##name## _jpg; \
+ int size = datatoc_ ##name## _jpg_size; \
+ DrawInfo *di; \
+ \
+ di = def_internal_icon(NULL, icon_id, 0, 0, 96, ICON_TYPE_BUFFER); \
+ di->data.buffer.image->datatoc_rect = rect; \
+ di->data.buffer.image->datatoc_size = size; \
+ } (void)0
+
+ INIT_MATCAP_ICON(ICON_MATCAP_01, mc01);
+ INIT_MATCAP_ICON(ICON_MATCAP_02, mc02);
+ INIT_MATCAP_ICON(ICON_MATCAP_03, mc03);
+ INIT_MATCAP_ICON(ICON_MATCAP_04, mc04);
+ INIT_MATCAP_ICON(ICON_MATCAP_05, mc05);
+ INIT_MATCAP_ICON(ICON_MATCAP_06, mc06);
+ INIT_MATCAP_ICON(ICON_MATCAP_07, mc07);
+ INIT_MATCAP_ICON(ICON_MATCAP_08, mc08);
+ INIT_MATCAP_ICON(ICON_MATCAP_09, mc09);
+ INIT_MATCAP_ICON(ICON_MATCAP_10, mc10);
+ INIT_MATCAP_ICON(ICON_MATCAP_11, mc11);
+ INIT_MATCAP_ICON(ICON_MATCAP_12, mc12);
+ INIT_MATCAP_ICON(ICON_MATCAP_13, mc13);
+ INIT_MATCAP_ICON(ICON_MATCAP_14, mc14);
+ INIT_MATCAP_ICON(ICON_MATCAP_15, mc15);
+ INIT_MATCAP_ICON(ICON_MATCAP_16, mc16);
+ INIT_MATCAP_ICON(ICON_MATCAP_17, mc17);
+ INIT_MATCAP_ICON(ICON_MATCAP_18, mc18);
+ INIT_MATCAP_ICON(ICON_MATCAP_19, mc19);
+ INIT_MATCAP_ICON(ICON_MATCAP_20, mc20);
+ INIT_MATCAP_ICON(ICON_MATCAP_21, mc21);
+ INIT_MATCAP_ICON(ICON_MATCAP_22, mc22);
+ INIT_MATCAP_ICON(ICON_MATCAP_23, mc23);
+ INIT_MATCAP_ICON(ICON_MATCAP_24, mc24);
+
+#undef INIT_MATCAP_ICON
+
+}
+
static void init_internal_icons(void)
{
- bTheme *btheme = UI_GetTheme();
- ImBuf *bbuf = NULL;
+// bTheme *btheme = UI_GetTheme();
+ ImBuf *b16buf = NULL, *b32buf = NULL;
int x, y, icontype;
- char iconfilestr[FILE_MAX];
-
+
+#if 0 // temp disabled
if ((btheme != NULL) && btheme->tui.iconfile[0]) {
char *icondir = BLI_get_folder(BLENDER_DATAFILES, "icons");
+ char iconfilestr[FILE_MAX];
+
if (icondir) {
BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile);
bbuf = IMB_loadiffname(iconfilestr, IB_rect, NULL); /* if the image is missing bbuf will just be NULL */
@@ -531,11 +609,20 @@ static void init_internal_icons(void)
printf("%s: 'icons' data path not found, continuing\n", __func__);
}
}
- if (bbuf == NULL)
- bbuf = IMB_ibImageFromMemory((unsigned char *)datatoc_blender_icons_png,
- datatoc_blender_icons_png_size, IB_rect, NULL, "<blender icons>");
-
- if (bbuf) {
+#endif
+ if (b16buf == NULL)
+ b16buf = IMB_ibImageFromMemory((unsigned char *)datatoc_blender_icons16_png,
+ datatoc_blender_icons16_png_size, IB_rect, NULL, "<blender icons>");
+ if (b16buf)
+ IMB_premultiply_alpha(b16buf);
+
+ if (b32buf == NULL)
+ b32buf = IMB_ibImageFromMemory((unsigned char *)datatoc_blender_icons32_png,
+ datatoc_blender_icons32_png_size, IB_rect, NULL, "<blender icons>");
+ if (b32buf)
+ IMB_premultiply_alpha(b32buf);
+
+ if (b16buf && b32buf) {
/* free existing texture if any */
if (icongltex.id) {
glDeleteTextures(1, &icongltex.id);
@@ -547,17 +634,31 @@ static void init_internal_icons(void)
glGenTextures(1, &icongltex.id);
if (icongltex.id) {
- icongltex.w = bbuf->x;
- icongltex.h = bbuf->y;
- icongltex.invw = 1.0f / bbuf->x;
- icongltex.invh = 1.0f / bbuf->y;
+ int level = 2;
+
+ icongltex.w = b32buf->x;
+ icongltex.h = b32buf->y;
+ icongltex.invw = 1.0f / b32buf->x;
+ icongltex.invh = 1.0f / b32buf->y;
glBindTexture(GL_TEXTURE_2D, icongltex.id);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bbuf->x, bbuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, bbuf->rect);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, b32buf->x, b32buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b32buf->rect);
+ glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, b16buf->x, b16buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b16buf->rect);
+
+ while (b16buf->x > 1) {
+ ImBuf *nbuf = IMB_onehalf(b16buf);
+ glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, nbuf->x, nbuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nbuf->rect);
+ level++;
+ IMB_freeImBuf(b16buf);
+ b16buf = nbuf;
+ }
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
glBindTexture(GL_TEXTURE_2D, 0);
-
+
if (glGetError() == GL_OUT_OF_MEMORY) {
glDeleteTextures(1, &icongltex.id);
icongltex.id = 0;
@@ -571,10 +672,10 @@ static void init_internal_icons(void)
else
icontype = ICON_TYPE_BUFFER;
- if (bbuf) {
+ if (b32buf) {
for (y = 0; y < ICON_GRID_ROWS; y++) {
for (x = 0; x < ICON_GRID_COLS; x++) {
- def_internal_icon(bbuf, BIFICONID_FIRST + y * ICON_GRID_COLS + x,
+ def_internal_icon(b32buf, BIFICONID_FIRST + y * ICON_GRID_COLS + x,
x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN, ICON_GRID_W,
icontype);
@@ -584,8 +685,8 @@ static void init_internal_icons(void)
def_internal_vicon(VICO_VIEW3D_VEC, vicon_view3d_draw);
def_internal_vicon(VICO_EDIT_VEC, vicon_edit_draw);
- def_internal_vicon(VICO_EDITMODE_DEHLT, vicon_editmode_dehlt_draw);
- def_internal_vicon(VICO_EDITMODE_HLT, vicon_editmode_hlt_draw);
+ def_internal_vicon(VICO_EDITMODE_VEC_DEHLT, vicon_editmode_dehlt_draw);
+ def_internal_vicon(VICO_EDITMODE_VEC_HLT, vicon_editmode_hlt_draw);
def_internal_vicon(VICO_DISCLOSURE_TRI_RIGHT_VEC, vicon_disclosure_tri_right_draw);
def_internal_vicon(VICO_DISCLOSURE_TRI_DOWN_VEC, vicon_disclosure_tri_down_draw);
def_internal_vicon(VICO_MOVE_UP_VEC, vicon_move_up_draw);
@@ -593,7 +694,9 @@ static void init_internal_icons(void)
def_internal_vicon(VICO_X_VEC, vicon_x_draw);
def_internal_vicon(VICO_SMALL_TRI_RIGHT_VEC, vicon_small_tri_right_draw);
- IMB_freeImBuf(bbuf);
+ IMB_freeImBuf(b16buf);
+ IMB_freeImBuf(b32buf);
+
}
#endif /* WITH_HEADLESS */
@@ -601,10 +704,8 @@ static void init_iconfile_list(struct ListBase *list)
{
IconFile *ifile;
struct direntry *dir;
- int restoredir = 1; /* restore to current directory */
int totfile, i, index = 1;
const char *icondir;
- char olddir[FILE_MAX];
list->first = list->last = NULL;
icondir = BLI_get_folder(BLENDER_DATAFILES, "icons");
@@ -612,12 +713,7 @@ static void init_iconfile_list(struct ListBase *list)
if (icondir == NULL)
return;
- /* since BLI_dir_contents changes the current working directory, restore it
- * back to old value afterwards */
- if (!BLI_current_working_dir(olddir, sizeof(olddir)))
- restoredir = 0;
totfile = BLI_dir_contents(icondir, &dir);
- if (restoredir && !chdir(olddir)) {} /* fix warning about checking return value */
for (i = 0; i < totfile; i++) {
if ((dir[i].type & S_IFREG)) {
@@ -664,18 +760,8 @@ static void init_iconfile_list(struct ListBase *list)
}
}
}
-
- /* free temporary direntry structure that's been created by BLI_dir_contents() */
- i = totfile - 1;
-
- for (; i >= 0; i--) {
- MEM_freeN(dir[i].relname);
- MEM_freeN(dir[i].path);
- if (dir[i].string) {
- MEM_freeN(dir[i].string);
- }
- }
- free(dir);
+
+ BLI_free_filelist(dir, totfile);
dir = NULL;
}
@@ -689,6 +775,8 @@ static void free_iconfile_list(struct ListBase *list)
}
}
+#endif /* WITH_HEADLESS */
+
int UI_iconfile_get_index(const char *filename)
{
IconFile *ifile;
@@ -731,7 +819,8 @@ void UI_icons_free_drawinfo(void *drawinfo)
if (di) {
if (di->type == ICON_TYPE_BUFFER) {
if (di->data.buffer.image) {
- MEM_freeN(di->data.buffer.image->rect);
+ if (di->data.buffer.image->rect)
+ MEM_freeN(di->data.buffer.image->rect);
MEM_freeN(di->data.buffer.image);
}
}
@@ -750,7 +839,7 @@ static DrawInfo *icon_create_drawinfo(void)
return di;
}
-/* note!, returns unscaled by DPI, may need to multiply result by UI_DPI_ICON_FAC */
+/* note!, returns unscaled by DPI */
int UI_icon_get_width(int icon_id)
{
Icon *icon = NULL;
@@ -811,6 +900,7 @@ void UI_icons_init(int first_dyn_id)
BKE_icons_init(first_dyn_id);
init_internal_icons();
init_brush_icons();
+ init_matcap_icons();
#endif
}
@@ -860,6 +950,34 @@ static void icon_set_image(bContext *C, ID *id, PreviewImage *prv_img, enum eIco
prv_img->w[size], prv_img->h[size]);
}
+PreviewImage *UI_icon_to_preview(int icon_id)
+{
+ Icon *icon = BKE_icon_get(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;
+
+ prv->w[0] = bbuf->x;
+ prv->h[0] = bbuf->y;
+
+ bbuf->rect = NULL;
+ IMB_freeImBuf(bbuf);
+
+ return prv;
+ }
+ }
+ }
+ return NULL;
+}
+
static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), int rw, int rh,
unsigned int *rect, float alpha, const float rgb[3], short is_preview)
{
@@ -920,7 +1038,7 @@ static void icon_draw_texture(float x, float y, float w, float h, int ix, int iy
float x1, x2, y1, y2;
if (rgb) glColor4f(rgb[0], rgb[1], rgb[2], alpha);
- else glColor4f(1.0f, 1.0f, 1.0f, alpha);
+ else glColor4f(alpha, alpha, alpha, alpha);
x1 = ix * icongltex.invw;
x2 = (ix + ih) * icongltex.invw;
@@ -930,6 +1048,9 @@ static void icon_draw_texture(float x, float y, float w, float h, int ix, int iy
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, icongltex.id);
+ /* sharper downscaling, has no effect when scale matches with a mip level */
+ glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, -0.5f);
+
glBegin(GL_QUADS);
glTexCoord2f(x1, y1);
glVertex2f(x, y);
@@ -944,6 +1065,8 @@ static void icon_draw_texture(float x, float y, float w, float h, int ix, int iy
glVertex2f(x, y + h);
glEnd();
+ glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, 0.0f);
+
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}
@@ -958,6 +1081,8 @@ static int get_draw_size(enum eIconSizes size)
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, int UNUSED(nocreate), short is_preview)
{
@@ -965,7 +1090,7 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al
Icon *icon = NULL;
DrawInfo *di = NULL;
IconImage *iimg;
- float fdraw_size = is_preview ? draw_size : (draw_size * UI_DPI_ICON_FAC);
+ const float fdraw_size = (float)draw_size;
int w, h;
icon = BKE_icon_get(icon_id);
@@ -993,19 +1118,26 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al
if (di->type == ICON_TYPE_VECTOR) {
/* vector icons use the uiBlock transformation, they are not drawn
* with untransformed coordinates like the other icons */
- di->data.vector.func((int)x, (int)y, ICON_DEFAULT_HEIGHT, ICON_DEFAULT_HEIGHT, 1.0f);
+ di->data.vector.func((int)x, (int)y, w, h, 1.0f);
}
else if (di->type == ICON_TYPE_TEXTURE) {
+ /* texture image use premul alpha for correct scaling */
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
icon_draw_texture(x, y, (float)w, (float)h, di->data.texture.x, di->data.texture.y,
di->data.texture.w, di->data.texture.h, alpha, rgb);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else if (di->type == ICON_TYPE_BUFFER) {
/* it is a builtin icon */
iimg = di->data.buffer.image;
-
+#ifndef WITH_HEADLESS
+ icon_verify_datatoc(iimg);
+#endif
if (!iimg->rect) return; /* something has gone wrong! */
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, rgb, is_preview);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else if (di->type == ICON_TYPE_PREVIEW) {
PreviewImage *pi = BKE_previewimg_get((ID *)icon->obj);
@@ -1141,6 +1273,44 @@ int ui_id_icon_get(bContext *C, ID *id, int big)
return iconid;
}
+int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, int big)
+{
+ ID *id = NULL;
+
+ if (!ptr->data)
+ return rnaicon;
+
+ /* try ID, material, texture or dynapaint slot */
+ if (RNA_struct_is_ID(ptr->type)) {
+ id = ptr->id.data;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_MaterialSlot)) {
+ id = RNA_pointer_get(ptr, "material").data;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_TextureSlot)) {
+ id = RNA_pointer_get(ptr, "texture").data;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_DynamicPaintSurface)) {
+ DynamicPaintSurface *surface = (DynamicPaintSurface *)ptr->data;
+
+ if (surface->format == MOD_DPAINT_SURFACE_F_PTEX)
+ return ICON_TEXTURE_SHADED;
+ else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX)
+ return ICON_OUTLINER_DATA_MESH;
+ else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ)
+ return ICON_FILE_IMAGE;
+ }
+
+ /* get icon from ID */
+ if (id) {
+ int icon = ui_id_icon_get(C, id, big);
+
+ return icon ? icon : rnaicon;
+ }
+
+ return rnaicon;
+}
+
static void icon_draw_at_size(float x, float y, int icon_id, float aspect, float alpha, enum eIconSizes size, int nocreate)
{
int draw_size = get_draw_size(size);
@@ -1158,9 +1328,10 @@ void UI_icon_draw_aspect_color(float x, float y, int icon_id, float aspect, cons
icon_draw_size(x, y, icon_id, aspect, 1.0f, rgb, ICON_SIZE_ICON, draw_size, FALSE, FALSE);
}
+/* draws icon with dpi scale factor */
void UI_icon_draw(float x, float y, int icon_id)
{
- UI_icon_draw_aspect(x, y, icon_id, 1.0f, 1.0f);
+ UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, 1.0f);
}
void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha)
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 1dc98639fe7..9f836ed789f 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -171,8 +171,8 @@ struct uiBut {
char *str;
char strdata[UI_MAX_NAME_STR];
char drawstr[UI_MAX_DRAW_STR];
-
- rctf rect;
+
+ rctf rect; /* block relative coords */
char *poin;
float hardmin, hardmax, softmin, softmax;
@@ -208,12 +208,6 @@ struct uiBut {
struct bContextStore *context;
- /* not used yet, was used in 2.4x for ui_draw_pulldown_round & friends */
-#if 0
- void (*embossfunc)(int, int, float, float, float, float, float, int);
- void (*sliderfunc)(int, float, float, float, float, float, float, int);
-#endif
-
uiButCompleteFunc autocomplete_func;
void *autofunc_arg;
@@ -225,7 +219,7 @@ struct uiBut {
void *rename_orig;
uiLink *link;
- short linkto[2];
+ short linkto[2]; /* region relative coords */
const char *tip, *lockstr;
@@ -267,10 +261,13 @@ struct uiBut {
void *dragpoin;
struct ImBuf *imb;
float imb_scale;
-
+
/* active button data */
struct uiHandleButtonData *active;
+ /* Custom button data. */
+ void *custom_data;
+
char *editstr;
double *editval;
float *editvec;
@@ -316,7 +313,7 @@ struct uiBlock {
void *handle_func_arg;
/* custom extra handling */
- int (*block_event_func)(const struct bContext *C, struct uiBlock *, struct wmEvent *);
+ int (*block_event_func)(const struct bContext *C, struct uiBlock *, const struct wmEvent *);
/* extra draw function for custom blocks */
void (*drawextra)(const struct bContext *C, void *idv, void *arg1, void *arg2, rcti *rect);
@@ -391,7 +388,8 @@ 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_get_but_string(uiBut *but, char *str, size_t maxlen);
+extern void ui_get_but_string_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision);
+extern void ui_get_but_string(uiBut *but, char *str, const size_t maxlen);
extern void ui_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen);
extern int ui_set_but_string(struct bContext *C, uiBut *but, const char *str);
extern int ui_get_but_string_max_length(uiBut *but);
@@ -399,13 +397,17 @@ extern int ui_set_but_string_eval_num(struct bContext *C, uiBut *but, const char
extern void ui_set_but_default(struct bContext *C, short all);
-extern void ui_set_but_soft_range(uiBut *but, double value);
-
extern void ui_check_but(uiBut *but);
extern int ui_is_but_float(uiBut *but);
+extern int ui_is_but_bool(uiBut *but);
extern int ui_is_but_unit(uiBut *but);
extern int ui_is_but_rna_valid(uiBut *but);
extern int ui_is_but_utf8(uiBut *but);
+extern bool ui_is_but_interactive(uiBut *but);
+
+extern int ui_is_but_push_ex(uiBut *but, double *value);
+extern int ui_is_but_push(uiBut *but);
+
extern void ui_bounds_block(uiBlock *block);
extern void ui_block_translate(uiBlock *block, int x, int y);
@@ -426,7 +428,7 @@ struct uiPopupBlockHandle {
int popup;
void (*popup_func)(struct bContext *C, void *arg, int event);
- void (*cancel_func)(void *arg);
+ void (*cancel_func)(struct bContext *C, void *arg);
void *popup_arg;
struct wmTimer *scrolltimer;
@@ -465,7 +467,7 @@ ARegion *ui_searchbox_create(struct bContext *C, struct ARegion *butregion, uiBu
int ui_searchbox_inside(struct ARegion *ar, int x, int y);
void ui_searchbox_update(struct bContext *C, struct ARegion *ar, uiBut *but, int reset);
void ui_searchbox_autocomplete(struct bContext *C, struct ARegion *ar, uiBut *but, char *str);
-void ui_searchbox_event(struct bContext *C, struct ARegion *ar, uiBut *but, struct wmEvent *event);
+void ui_searchbox_event(struct bContext *C, struct ARegion *ar, uiBut *but, const struct wmEvent *event);
void 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);
@@ -486,13 +488,13 @@ int ui_step_name_menu(uiBut *but, int step);
struct AutoComplete;
/* interface_panel.c */
-extern int ui_handler_panel_region(struct bContext *C, struct wmEvent *event);
+extern int ui_handler_panel_region(struct bContext *C, const struct wmEvent *event);
extern void ui_draw_aligned_panel(struct uiStyle *style, uiBlock *block, rcti *rect);
/* interface_draw.c */
extern void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select);
-void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const float alpha);
+void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, const float alpha);
void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
@@ -502,9 +504,12 @@ void ui_draw_but_NORMAL(uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
void ui_draw_but_CURVE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
void ui_draw_but_IMAGE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
+void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
/* interface_handlers.c */
+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_execute_do(struct bContext *C, struct ARegion *ar, uiBut *but);
extern void ui_button_active_free(const struct bContext *C, uiBut *but);
extern int ui_button_is_active(struct ARegion *ar);
extern int ui_button_open_menu_direction(uiBut *but);
@@ -512,13 +517,13 @@ extern void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiB
/* 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);
+void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad, bool use_alpha);
void ui_draw_menu_back(struct uiStyle *style, uiBlock *block, rcti *rect);
uiWidgetColors *ui_tooltip_get_theme(void);
void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock * block, rcti * rect);
void ui_draw_search_back(struct uiStyle *style, uiBlock *block, rcti *rect);
-int ui_link_bezier_points(rcti * rect, float coord_array[][2], int resol);
-void ui_draw_link_bezier(rcti *rect);
+int ui_link_bezier_points(const rcti * rect, float coord_array[][2], int resol);
+void ui_draw_link_bezier(const rcti *rect);
extern void ui_draw_but(const struct bContext *C, ARegion *ar, struct uiStyle *style, uiBut *but, rcti *rect);
/* theme color init */
@@ -533,6 +538,8 @@ extern unsigned char checker_stipple_sml[32 * 32 / 8];
#define UI_TRANSP_DARK 100
#define UI_TRANSP_LIGHT 160
+#define UI_TEXT_MARGIN_X 0.4f
+
/* interface_style.c */
void uiStyleInit(void);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 9759c22f30e..53887163778 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -65,8 +65,6 @@
#define RNA_NO_INDEX -1
#define RNA_ENUM_VALUE -2
-#define EM_SEPR_X 6
-#define EM_SEPR_Y 6
// #define USE_OP_RESET_BUT // we may want to make this optional, disable for now.
@@ -188,13 +186,13 @@ static const char *ui_item_name_add_colon(const char *name, char namestr[UI_MAX_
static int ui_item_fit(int item, int pos, int all, int available, int last, int alignment, int *offset)
{
+ if (offset)
+ *offset = 0;
+
/* available == 0 is unlimited */
if (available == 0)
return item;
-
- if (offset)
- *offset = 0;
-
+
if (all > available) {
/* contents is bigger than available space */
if (last)
@@ -227,14 +225,16 @@ static int ui_layout_vary_direction(uiLayout *layout)
/* estimated size of text + icon */
static int ui_text_icon_width(uiLayout *layout, const char *name, int icon, int compact)
{
+ float f5 = 0.25f * UI_UNIT_X;
+ float f10 = 0.5f * UI_UNIT_X;
int variable = ui_layout_vary_direction(layout) == UI_ITEM_VARY_X;
if (icon && !name[0])
return UI_UNIT_X; /* icon only */
else if (icon)
- return (variable) ? UI_GetStringWidth(name) + (compact ? 5 : 10) + UI_UNIT_X : 10 * UI_UNIT_X; /* icon + text */
+ return (variable) ? UI_GetStringWidth(name) + (compact ? f5 : f10) + UI_UNIT_X : 10 * UI_UNIT_X; /* icon + text */
else
- return (variable) ? UI_GetStringWidth(name) + (compact ? 5 : 10) + UI_UNIT_X : 10 * UI_UNIT_X; /* text only */
+ return (variable) ? UI_GetStringWidth(name) + (compact ? f5 : f10) + UI_UNIT_X : 10 * UI_UNIT_X; /* text only */
}
static void ui_item_size(uiItem *item, int *r_w, int *r_h)
@@ -346,7 +346,9 @@ static void ui_layer_but_cb(bContext *C, void *arg_but, void *arg_index)
}
/* 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),
+ int expand, int slider, int toggle, int icon_only)
{
uiStyle *style = layout->root->style;
uiBut *but;
@@ -489,7 +491,14 @@ static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *pt
RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item, &totitem, &free);
- uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, layout, 1));
+ /* we dont want nested rows, cols in menus */
+ if (layout->root->type != UI_LAYOUT_MENU) {
+ uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, layout, 1));
+ }
+ else {
+ uiBlockSetCurLayout(block, layout);
+ }
+
for (a = 0; a < totitem; a++) {
if (!item[a].identifier[0])
continue;
@@ -615,6 +624,18 @@ void uiFileBrowseContextProperty(const bContext *C, PointerRNA *ptr, PropertyRNA
/********************* Button Items *************************/
+/**
+ * Update a buttons tip with an enum's description if possible.
+ */
+static void ui_but_tip_from_enum_item(uiBut *but, EnumPropertyItem *item)
+{
+ if (but->tip == NULL || but->tip[0] == '\0') {
+ if (item->description && item->description[0]) {
+ but->tip = item->description;
+ }
+ }
+}
+
/* disabled item */
static void ui_item_disabled(uiLayout *layout, const char *name)
{
@@ -718,8 +739,11 @@ static const char *ui_menu_enumpropname(uiLayout *layout, PointerRNA *ptr, Prope
int totitem, free;
const char *name;
- RNA_property_enum_items_gettexted(layout->root->block->evil_C, ptr, prop, &item, &totitem, &free);
- if (RNA_enum_name(item, retval, &name) == 0) {
+ RNA_property_enum_items(layout->root->block->evil_C, ptr, prop, &item, &totitem, &free);
+ if (RNA_enum_name(item, retval, &name)) {
+ name = CTX_IFACE_(RNA_property_translation_context(prop), name);
+ }
+ else {
name = "";
}
@@ -825,6 +849,7 @@ void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname
else {
uiItemEnumO_ptr__internal(column, ot, item[i].name, item[i].icon, prop, item[i].value);
}
+ ui_but_tip_from_enum_item(block->buttons.last, &item[i]);
}
else {
if (item[i].name) {
@@ -837,6 +862,8 @@ void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname
uiItemL(column, item[i].name, ICON_NONE);
bt = block->buttons.last;
bt->flag = UI_TEXT_LEFT;
+
+ ui_but_tip_from_enum_item(bt, &item[i]);
}
else { /* XXX bug here, colums draw bottom item badly */
uiItemS(column);
@@ -904,10 +931,11 @@ void uiItemEnumO_string(uiLayout *layout, const char *name, int icon, const char
UI_OPERATOR_ERROR_RET(ot, opname, return );
WM_operator_properties_create_ptr(&ptr, ot);
-
+
/* enum lookup */
if ((prop = RNA_struct_find_property(&ptr, propname))) {
- RNA_property_enum_items_gettexted(layout->root->block->evil_C, &ptr, prop, &item, NULL, &free);
+ /* no need for translations here */
+ RNA_property_enum_items(layout->root->block->evil_C, &ptr, prop, &item, NULL, &free);
if (item == NULL || RNA_enum_value_from_id(item, value_str, &value) == 0) {
if (free) {
MEM_freeN(item);
@@ -924,9 +952,9 @@ void uiItemEnumO_string(uiLayout *layout, const char *name, int icon, const char
RNA_warning("%s.%s not found", RNA_struct_identifier(ptr.type), propname);
return;
}
-
+
RNA_property_enum_set(&ptr, prop, value);
-
+
/* same as uiItemEnumO */
if (!name)
name = ui_menu_enumpropname(layout, &ptr, prop, value);
@@ -1172,7 +1200,7 @@ void uiItemEnumR_string(uiLayout *layout, struct PointerRNA *ptr, const char *pr
return;
}
- RNA_property_enum_items_gettexted(layout->root->block->evil_C, ptr, prop, &item, NULL, &free);
+ RNA_property_enum_items(layout->root->block->evil_C, ptr, prop, &item, NULL, &free);
if (!RNA_enum_value_from_id(item, value, &ivalue)) {
if (free) {
@@ -1185,7 +1213,9 @@ void uiItemEnumR_string(uiLayout *layout, struct PointerRNA *ptr, const char *pr
for (a = 0; item[a].identifier; a++) {
if (item[a].value == ivalue) {
- uiItemFullR(layout, ptr, prop, RNA_ENUM_VALUE, ivalue, 0, name ? name : item[a].name, icon ? icon : item[a].icon);
+ const char *item_name = CTX_IFACE_(RNA_property_translation_context(prop), item[a].name);
+
+ uiItemFullR(layout, ptr, prop, RNA_ENUM_VALUE, ivalue, 0, item_name ? item_name : name, icon ? icon : item[a].icon);
break;
}
}
@@ -1224,6 +1254,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);
+ ui_but_tip_from_enum_item(block->buttons.last, &item[i]);
}
else {
if (item[i].name) {
@@ -1236,6 +1267,8 @@ void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname
uiItemL(column, item[i].name, ICON_NONE);
bt = block->buttons.last;
bt->flag = UI_TEXT_LEFT;
+
+ ui_but_tip_from_enum_item(bt, &item[i]);
}
else
uiItemS(column);
@@ -1378,7 +1411,11 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN
/* turn button into search button */
if (searchprop) {
- but->type = SEARCH_MENU;
+ if (RNA_property_flag(prop) & PROP_NEVER_UNLINK)
+ but->type = SEARCH_MENU;
+ else
+ but->type = SEARCH_MENU_UNLINK;
+
but->hardmax = MAX2(but->hardmax, 256.0f);
but->rnasearchpoin = *searchptr;
but->rnasearchprop = searchprop;
@@ -1448,6 +1485,7 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna
block = uiLayoutGetBlock(layout);
ui_item_rna_size(layout, name, icon, ptr, prop, 0, 0, &w, &h);
+ w += UI_UNIT_X; /* X icon needs more space */
but = ui_item_with_label(layout, block, name, icon, ptr, prop, 0, 0, 0, w, h, 0);
ui_but_add_search(but, ptr, prop, searchptr, searchprop);
@@ -1466,7 +1504,13 @@ static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
printf("%s: opening menu \"%s\"\n", __func__, mt->idname);
}
+ if (layout->context)
+ CTX_store_set(C, layout->context);
+
mt->draw(C, &menu);
+
+ if (layout->context)
+ CTX_store_set(C, NULL);
}
static void ui_item_menu(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg, void *argN, const char *tip)
@@ -1489,7 +1533,7 @@ static void ui_item_menu(uiLayout *layout, const char *name, int icon, uiMenuCre
h = UI_UNIT_Y;
if (layout->root->type == UI_LAYOUT_HEADER) /* ugly .. */
- w -= 10;
+ w -= UI_UNIT_Y / 2;
if (name[0] && icon)
but = uiDefIconTextMenuBut(block, func, arg, icon, name, 0, 0, w, h, tip);
@@ -1523,7 +1567,7 @@ void uiItemM(uiLayout *layout, bContext *UNUSED(C), const char *menuname, const
}
if (!name) {
- name = IFACE_(mt->label);
+ name = CTX_IFACE_(mt->translation_context, mt->label);
}
if (layout->root->type == UI_LAYOUT_MENU && !icon)
@@ -1555,6 +1599,14 @@ static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon)
else
but = uiDefBut(block, 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.
+ */
+ if (uiLayoutGetAlignment(layout) == UI_LAYOUT_ALIGN_RIGHT) {
+ but->flag &= ~UI_TEXT_LEFT; /* default, needs to be unset */
+ but->flag |= UI_TEXT_RIGHT;
+ }
+
return but;
}
@@ -1604,7 +1656,7 @@ void uiItemS(uiLayout *layout)
uiBlock *block = layout->root->block;
uiBlockSetCurLayout(block, layout);
- uiDefBut(block, SEPR, 0, "", 0, 0, EM_SEPR_X, EM_SEPR_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, SEPR, 0, "", 0, 0, 0.3f * UI_UNIT_X, 0.3f * UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
}
/* level items */
@@ -2219,6 +2271,7 @@ uiLayout *uiLayoutRow(uiLayout *layout, int align)
litem->enabled = 1;
litem->context = layout->context;
litem->space = (align) ? 0 : layout->root->style->buttonspacex;
+ litem->redalert = layout->redalert;
litem->w = layout->w;
BLI_addtail(&layout->items, litem);
@@ -2239,6 +2292,7 @@ uiLayout *uiLayoutColumn(uiLayout *layout, int align)
litem->enabled = 1;
litem->context = layout->context;
litem->space = (litem->align) ? 0 : layout->root->style->buttonspacey;
+ litem->redalert = layout->redalert;
litem->w = layout->w;
BLI_addtail(&layout->items, litem);
@@ -2259,6 +2313,7 @@ uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align)
flow->litem.enabled = 1;
flow->litem.context = layout->context;
flow->litem.space = (flow->litem.align) ? 0 : layout->root->style->columnspace;
+ flow->litem.redalert = layout->redalert;
flow->litem.w = layout->w;
flow->number = number;
BLI_addtail(&layout->items, flow);
@@ -2279,6 +2334,7 @@ static uiLayoutItemBx *ui_layout_box(uiLayout *layout, int type)
box->litem.enabled = 1;
box->litem.context = layout->context;
box->litem.space = layout->root->style->columnspace;
+ box->litem.redalert = layout->redalert;
box->litem.w = layout->w;
BLI_addtail(&layout->items, box);
@@ -2294,11 +2350,14 @@ uiLayout *uiLayoutBox(uiLayout *layout)
return (uiLayout *)ui_layout_box(layout, ROUNDBOX);
}
-uiLayout *uiLayoutListBox(uiLayout *layout, 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);
uiBut *but = box->roundbox;
+ but->custom_data = ui_list;
+
but->rnasearchpoin = *ptr;
but->rnasearchprop = prop;
but->rnapoin = *actptr;
@@ -2318,6 +2377,7 @@ uiLayout *uiLayoutAbsolute(uiLayout *layout, int align)
litem->active = 1;
litem->enabled = 1;
litem->context = layout->context;
+ litem->redalert = layout->redalert;
BLI_addtail(&layout->items, litem);
uiBlockSetCurLayout(layout->root->block, litem);
@@ -2345,6 +2405,7 @@ uiLayout *uiLayoutOverlap(uiLayout *layout)
litem->active = 1;
litem->enabled = 1;
litem->context = layout->context;
+ litem->redalert = layout->redalert;
BLI_addtail(&layout->items, litem);
uiBlockSetCurLayout(layout->root->block, litem);
@@ -2364,6 +2425,7 @@ uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align)
split->litem.enabled = 1;
split->litem.context = layout->context;
split->litem.space = layout->root->style->columnspace;
+ split->litem.redalert = layout->redalert;
split->litem.w = layout->w;
split->percentage = percentage;
BLI_addtail(&layout->items, split);
@@ -2860,7 +2922,7 @@ static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), void *op_pt,
/* 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,
- int (*check_prop)(struct PointerRNA *, struct PropertyRNA *),
+ bool (*check_prop)(struct PointerRNA *, struct PropertyRNA *),
const char label_align, const short flag)
{
if (!op->properties) {
@@ -2935,7 +2997,7 @@ 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, 18, 20,
+ but = uiDefIconTextBut(block, 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);
}
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index e57e52d74b6..145deb35667 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -239,7 +239,7 @@ static void eyedropper_color_sample_accum(bContext *C, Eyedropper *eye, int mx,
}
/* main modal status check */
-static int eyedropper_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int eyedropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
Eyedropper *eye = (Eyedropper *)op->customdata;
@@ -285,7 +285,7 @@ static int eyedropper_modal(bContext *C, wmOperator *op, wmEvent *event)
}
/* Modal Operator init */
-static int eyedropper_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int eyedropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
/* init */
if (eyedropper_init(C, op)) {
@@ -661,11 +661,12 @@ static int reports_to_text_poll(bContext *C)
static int reports_to_text_exec(bContext *C, wmOperator *UNUSED(op))
{
ReportList *reports = CTX_wm_reports(C);
+ Main *bmain = CTX_data_main(C);
Text *txt;
char *str;
/* create new text-block to write to */
- txt = BKE_text_add("Recent Reports");
+ txt = BKE_text_add(bmain, "Recent Reports");
/* convert entire list to a display string, and add this to the text-block
* - if commandline debug option enabled, show debug reports too
@@ -803,7 +804,7 @@ static int editsource_text_edit(bContext *C, wmOperator *op,
}
if (text == NULL) {
- text = BKE_text_load(filepath, bmain->name);
+ text = BKE_text_load(bmain, filepath, bmain->name);
}
if (text == NULL) {
@@ -852,7 +853,7 @@ static int editsource_exec(bContext *C, wmOperator *op)
ED_region_do_draw(C, ar);
for (BLI_ghashIterator_init(&ghi, ui_editsource_info->hash);
- !BLI_ghashIterator_isDone(&ghi);
+ BLI_ghashIterator_notDone(&ghi);
BLI_ghashIterator_step(&ghi))
{
uiBut *but_key = BLI_ghashIterator_getKey(&ghi);
@@ -1088,4 +1089,3 @@ void UI_buttons_operatortypes(void)
#endif
WM_operatortype_append(UI_OT_reloadtranslation);
}
-
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 2b170ea546b..ca26044f662 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -112,7 +112,7 @@ static int panel_aligned(ScrArea *sa, ARegion *ar)
else if (sa->spacetype == SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS)
return BUT_VERTICAL;
else if (sa->spacetype == SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW)
- return BUT_VERTICAL;
+ return BUT_VERTICAL;
else if (ELEM3(ar->regiontype, RGN_TYPE_UI, RGN_TYPE_TOOLS, RGN_TYPE_TOOL_PROPS))
return BUT_VERTICAL;
@@ -133,8 +133,6 @@ static int panels_re_align(ScrArea *sa, ARegion *ar, Panel **r_pa)
if (sbuts->re_align || sbuts->mainbo != sbuts->mainb)
return 1;
}
- else if (ar->regiontype == RGN_TYPE_UI)
- return 1;
else if (sa->spacetype == SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW)
return 1;
else if (sa->spacetype == SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS)
@@ -164,15 +162,20 @@ static int panels_re_align(ScrArea *sa, ARegion *ar, Panel **r_pa)
/****************************** panels ******************************/
-static void panels_collapse_all(ScrArea *sa, ARegion *ar)
+static void panels_collapse_all(ScrArea *sa, ARegion *ar, Panel *from_pa)
{
Panel *pa;
+ PanelType *pt, *from_pt;
int flag = ((panel_aligned(sa, ar) == BUT_HORIZONTAL) ? PNL_CLOSEDX : PNL_CLOSEDY);
for (pa = ar->panels.first; pa; pa = pa->next) {
- if (pa->type && !(pa->type->flag & PNL_NO_HEADER)) {
- pa->flag = flag;
- }
+ pt = pa->type;
+ from_pt = from_pa->type;
+
+ /* close panels with headers in the same context */
+ if (pt && from_pt && !(pt->flag & PNL_NO_HEADER))
+ if (!pt->context[0] || strcmp(pt->context, from_pt->context) == 0)
+ pa->flag = flag;
}
}
@@ -188,7 +191,7 @@ static void ui_panel_copy_offset(Panel *pa, Panel *papar)
Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, int *open)
{
Panel *pa, *patab, *palast, *panext;
- char *drawname = pt->label;
+ const char *drawname = CTX_IFACE_(pt->translation_context, pt->label);
char *idname = pt->idname;
char *tabname = pt->idname;
char *hookname = NULL;
@@ -244,6 +247,14 @@ Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, int
}
}
+ /* Do not allow closed panels without headers! Else user could get "disappeared" UI! */
+ if ((pt->flag & PNL_NO_HEADER) && (pa->flag & PNL_CLOSED)) {
+ pa->flag &= ~PNL_CLOSED;
+ /* Force update of panels' positions! */
+ pa->sizex = 0;
+ pa->sizey = 0;
+ }
+
BLI_strncpy(pa->drawname, drawname, UI_MAX_NAME_STR);
/* if a new panel is added, we insert it right after the panel
@@ -305,7 +316,7 @@ void uiEndPanel(uiBlock *block, int width, int height)
static void ui_offset_panel_block(uiBlock *block)
{
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_GetStyleDraw();
uiBut *but;
int ofsy;
@@ -345,14 +356,18 @@ static void uiPanelPop(uiBlock *UNUSED(block))
/* triangle 'icon' for panel header */
void UI_DrawTriIcon(float x, float y, char dir)
{
+ float f3 = 0.15 * U.widget_unit;
+ float f5 = 0.25 * U.widget_unit;
+ float f7 = 0.35 * U.widget_unit;
+
if (dir == 'h') {
- ui_draw_anti_tria(x - 3, y - 5, x - 3, y + 5, x + 7, y);
+ ui_draw_anti_tria(x - f3, y - f5, x - f3, y + f5, x + f7, y);
}
else if (dir == 't') {
- ui_draw_anti_tria(x - 5, y - 7, x + 5, y - 7, x, y + 3);
+ ui_draw_anti_tria(x - f5, y - f7, x + f5, y - f7, x, y + f3);
}
else { /* 'v' = vertical, down */
- ui_draw_anti_tria(x - 5, y + 3, x + 5, y + 3, x, y - 7);
+ ui_draw_anti_tria(x - f5, y + f3, x + f5, y + f3, x, y - f7);
}
}
@@ -432,8 +447,8 @@ static void ui_draw_panel_dragwidget(const rctf *rect)
ymin = rect->ymin;
ymax = rect->ymax;
- dx = 0.333f * (xmax - xmin);
- dy = 0.333f * (ymax - ymin);
+ dx = (xmax - xmin) / 3.0f;
+ dy = (ymax - ymin) / 3.0f;
glEnable(GL_BLEND);
glColor4ub(255, 255, 255, 50);
@@ -454,7 +469,7 @@ static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, rcti *r
Panel *panel = block->panel;
rcti hrect;
int pnl_icons;
- const char *activename = IFACE_(panel->drawname[0] ? panel->drawname : panel->panelname);
+ const char *activename = panel->drawname[0] ? panel->drawname : panel->panelname;
/* + 0.001f to avoid flirting with float inaccuracy */
if (panel->control & UI_PNL_CLOSE) pnl_icons = (panel->labelofs + 2 * PNL_ICON + 5) / block->aspect + 0.001f;
@@ -495,7 +510,6 @@ static void rectf_scale(rctf *rect, const float scale)
/* panel integrated in buttonswindow, tool/property lists etc */
void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect)
{
- bTheme *btheme = UI_GetTheme();
Panel *panel = block->panel;
rcti headrect;
rctf itemrect;
@@ -516,11 +530,10 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect)
float y = headrect.ymax;
glEnable(GL_BLEND);
-
- if (btheme->tui.panel.show_header) {
+
+ if (UI_GetThemeValue(TH_PANEL_SHOW_HEADER)) {
/* draw with background color */
- glEnable(GL_BLEND);
- glColor4ubv((unsigned char *)btheme->tui.panel.header);
+ UI_ThemeColor4(TH_PANEL_HEADER);
glRectf(minx, headrect.ymin + 1, maxx, y);
fdrawline(minx, y, maxx, y);
@@ -535,7 +548,6 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect)
fdrawline(minx, y, maxx, y);
glColor4f(1.0f, 1.0f, 1.0f, 0.25f);
fdrawline(minx, y - 1, maxx, y - 1);
- glDisable(GL_BLEND);
}
glDisable(GL_BLEND);
@@ -577,6 +589,14 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect)
uiRoundRect(0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax + 1, 8);
}
+ /* panel backdrop */
+ if (UI_GetThemeValue(TH_PANEL_SHOW_BACK)) {
+ /* draw with background color */
+ glEnable(GL_BLEND);
+ UI_ThemeColor4(TH_PANEL_BACK);
+ glRecti(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ }
+
if (panel->control & UI_PNL_SCALE)
ui_draw_panel_scalewidget(rect);
}
@@ -797,8 +817,8 @@ static void ui_panels_size(ScrArea *sa, ARegion *ar, int *x, int *y)
{
Panel *pa;
int align = panel_aligned(sa, ar);
- int sizex = UI_PANEL_WIDTH;
- int sizey = UI_PANEL_WIDTH;
+ int sizex = 0;
+ int sizey = 0;
/* compute size taken up by panels, for setting in view2d */
for (pa = ar->panels.first; pa; pa = pa->next) {
@@ -819,6 +839,11 @@ static void ui_panels_size(ScrArea *sa, ARegion *ar, int *x, int *y)
}
}
+ if (sizex == 0)
+ sizex = UI_PANEL_WIDTH;
+ if (sizey == 0)
+ sizey = -UI_PANEL_WIDTH;
+
*x = sizex;
*y = sizey;
}
@@ -850,7 +875,7 @@ static void ui_do_animate(const bContext *C, Panel *panel)
void uiBeginPanels(const bContext *UNUSED(C), ARegion *ar)
{
Panel *pa;
-
+
/* set all panels as inactive, so that at the end we know
* which ones were used */
for (pa = ar->panels.first; pa; pa = pa->next) {
@@ -900,6 +925,7 @@ void uiEndPanels(const bContext *C, ARegion *ar, int *x, int *y)
/* re-align, possibly with animation */
if (panels_re_align(sa, ar, &pa)) {
+ /* XXX code never gets here... PNL_ANIM_ALIGN flag is never set */
if (pa)
panel_activate_state(C, pa, PANEL_STATE_ANIMATION);
else
@@ -940,6 +966,25 @@ void uiDrawPanels(const bContext *C, ARegion *ar)
}
}
+void uiScalePanels(ARegion *ar, float new_width)
+{
+ uiBlock *block;
+ uiBut *but;
+
+ 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) {
+ but->rect.xmin *= fac;
+ but->rect.xmax *= fac;
+ }
+ }
+ }
+}
+
/* ------------ panel merging ---------------- */
static void check_panel_overlap(ARegion *ar, Panel *panel)
@@ -971,7 +1016,7 @@ static void check_panel_overlap(ARegion *ar, Panel *panel)
/************************ panel dragging ****************************/
-static void ui_do_drag(const bContext *C, wmEvent *event, Panel *panel)
+static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel)
{
uiHandlePanelData *data = panel->activedata;
ScrArea *sa = CTX_wm_area(C);
@@ -1016,7 +1061,7 @@ static void ui_do_drag(const bContext *C, wmEvent *event, Panel *panel)
/* this function is supposed to call general window drawing too */
/* also it supposes a block has panel, and isn't a menu */
-static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, int my, int event)
+static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, int my, int event, int ctrl)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
@@ -1049,6 +1094,9 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
ED_region_tag_redraw(ar);
}
else { /* collapse */
+ if (ctrl)
+ panels_collapse_all(sa, ar, block->panel);
+
if (block->panel->flag & PNL_CLOSED) {
block->panel->flag &= ~PNL_CLOSED;
/* snap back up so full panel aligns with screen edge */
@@ -1086,43 +1134,64 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
/* XXX should become modal keymap */
/* AKey is opening/closing panels, independent of button state now */
-int ui_handler_panel_region(bContext *C, wmEvent *event)
+int ui_handler_panel_region(bContext *C, const wmEvent *event)
{
- ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
uiBlock *block;
Panel *pa;
- int retval, mx, my, inside_header = 0, inside_scale = 0, inside;
+ int retval, mx, my;
retval = WM_UI_HANDLER_CONTINUE;
for (block = ar->uiblocks.last; block; block = block->prev) {
+ int inside = 0, inside_header = 0, inside_scale = 0;
+
mx = event->x;
my = event->y;
ui_window_to_block(ar, block, &mx, &my);
- /* check if inside boundbox */
- inside = 0;
+ /* checks for mouse position inside */
pa = block->panel;
if (!pa || pa->paneltab != NULL)
continue;
if (pa->type && pa->type->flag & PNL_NO_HEADER) /* XXX - accessed freed panels when scripts reload, need to fix. */
continue;
-
- if (block->rect.xmin <= mx && block->rect.xmax >= mx)
- if (block->rect.ymin <= my && block->rect.ymax + PNL_HEADER >= my)
- inside = 1;
- if (inside && event->val == KM_PRESS) {
+ /* clicked at panel header? */
+ if (pa->flag & PNL_CLOSEDX) {
+ if (block->rect.xmin <= mx && block->rect.xmin + PNL_HEADER >= mx)
+ inside_header = 1;
+ }
+ else if (block->rect.xmin > mx || block->rect.xmax < mx) {
+ /* outside left/right side */
+ }
+ else if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) {
+ inside_header = 1;
+ }
+ else if (!(pa->flag & PNL_CLOSEDY)) {
+ /* open panel */
+ if (pa->control & UI_PNL_SCALE) {
+ if (block->rect.xmax - PNL_HEADER <= mx)
+ if (block->rect.ymin + PNL_HEADER >= my)
+ inside_scale = 1;
+ }
+ if (block->rect.xmin <= mx && block->rect.xmax >= mx)
+ if (block->rect.ymin <= my && block->rect.ymax + PNL_HEADER >= my)
+ inside = 1;
+ }
+
+ /* XXX hardcoded key warning */
+ if ((inside || inside_header) && event->val == KM_PRESS) {
if (event->type == AKEY && !ELEM4(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift, event->alt)) {
if (pa->flag & PNL_CLOSEDY) {
if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my))
- ui_handle_panel_header(C, block, mx, my, event->type);
+ ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl);
}
else
- ui_handle_panel_header(C, block, mx, my, event->type);
+ ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl);
+ retval = WM_UI_HANDLER_BREAK;
continue;
}
}
@@ -1131,40 +1200,33 @@ int ui_handler_panel_region(bContext *C, wmEvent *event)
if (ui_button_is_active(ar))
continue;
- if (inside) {
- /* clicked at panel header? */
- if (pa->flag & PNL_CLOSEDX) {
- if (block->rect.xmin <= mx && block->rect.xmin + PNL_HEADER >= mx)
- inside_header = 1;
- }
- else if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) {
- inside_header = 1;
- }
- else if (pa->control & UI_PNL_SCALE) {
- if (block->rect.xmax - PNL_HEADER <= mx)
- if (block->rect.ymin + PNL_HEADER >= my)
- inside_scale = 1;
- }
+ if (inside || inside_header) {
if (event->val == KM_PRESS) {
+
/* open close on header */
if (ELEM(event->type, RETKEY, PADENTER)) {
if (inside_header) {
- ui_handle_panel_header(C, block, mx, my, RETKEY);
+ ui_handle_panel_header(C, block, mx, my, RETKEY, event->ctrl);
+ retval = WM_UI_HANDLER_BREAK;
break;
}
}
else if (event->type == LEFTMOUSE) {
+ /* all inside clicks should return in break - overlapping/float panels */
+ retval = WM_UI_HANDLER_BREAK;
+
if (inside_header) {
- if (event->ctrl)
- panels_collapse_all(sa, ar);
- ui_handle_panel_header(C, block, mx, my, 0);
+ ui_handle_panel_header(C, block, mx, my, 0, event->ctrl);
+ retval = WM_UI_HANDLER_BREAK;
break;
}
else if (inside_scale && !(pa->flag & PNL_CLOSED)) {
panel_activate_state(C, pa, PANEL_STATE_DRAG_SCALE);
+ retval = WM_UI_HANDLER_BREAK;
break;
}
+
}
else if (event->type == ESCKEY) {
/*XXX 2.50*/
@@ -1215,7 +1277,7 @@ int ui_handler_panel_region(bContext *C, wmEvent *event)
/**************** window level modal panel interaction **************/
/* note, this is modal handler and should not swallow events for animation */
-static int ui_handler_panel(bContext *C, wmEvent *event, void *userdata)
+static int ui_handler_panel(bContext *C, const wmEvent *event, void *userdata)
{
Panel *panel = userdata;
uiHandlePanelData *data = panel->activedata;
@@ -1316,19 +1378,5 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
}
ED_region_tag_redraw(ar);
-
- /* XXX exception handling, 3d window preview panel */
-#if 0
- if (block->drawextra == BIF_view3d_previewdraw)
- BIF_view3d_previewrender_clear(curarea);
-#endif
-
- /* XXX exception handling, 3d window preview panel */
-#if 0
- if (block->drawextra == BIF_view3d_previewdraw)
- BIF_view3d_previewrender_signal(curarea, PR_DISPRECT);
- else if (strcmp(block->name, "image_panel_preview") == 0)
- image_preview_event(2);
-#endif
}
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index b62e634b1eb..febd1820e5c 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -73,8 +73,6 @@
#include "interface_intern.h"
#define B_NOP -1
-#define MENU_SHADOW_SIDE 8
-#define MENU_SHADOW_BOTTOM 10
#define MENU_TOP 8
/*********************** Menu Data Parsing ********************* */
@@ -306,8 +304,9 @@ static ARegion *ui_add_temporary_region(bScreen *sc)
static void ui_remove_temporary_region(bContext *C, bScreen *sc, ARegion *ar)
{
- if (CTX_wm_window(C))
- wm_draw_region_clear(CTX_wm_window(C), ar);
+ wmWindow *win = CTX_wm_window(C);
+ if (win)
+ wm_draw_region_clear(win, ar);
ED_region_exit(C, ar);
BKE_area_region_free(NULL, ar); /* NULL: no spacetype */
@@ -416,6 +415,7 @@ static void ui_tooltip_region_free_cb(ARegion *ar)
ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
{
+ wmWindow *win = CTX_wm_window(C);
uiStyle *style = UI_GetStyle();
static ARegionType type;
ARegion *ar;
@@ -423,7 +423,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
/* IDProperty *prop;*/
char buf[512];
float fonth, fontw, aspect = but->block->aspect;
- int winx, winy, ofsx, ofsy, w, h, a;
+ int winx /*, winy */, ofsx, ofsy, w, h, a;
rctf rect_fl;
rcti rect_i;
@@ -466,7 +466,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
data->totline++;
}
- if (ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) {
+ if (ELEM4(but->type, TEX, IDPOIN, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
/* full string */
ui_get_but_string(but, buf, sizeof(buf));
if (buf[0]) {
@@ -565,7 +565,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
char *data_path = NULL;
/* never fails */
- id_path = RNA_path_from_ID_python(id);
+ id_path = RNA_path_full_ID_py(id);
if (ptr->id.data && ptr->data && prop) {
data_path = RNA_path_from_ID_to_property(ptr, prop);
@@ -622,12 +622,14 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
/* set font, get bb */
data->fstyle = style->widget; /* copy struct */
data->fstyle.align = UI_STYLE_TEXT_CENTER;
+ ui_fontscale(&data->fstyle.points, aspect);
+
uiStyleFontSet(&data->fstyle);
- /* these defines may need to be tweaked depending on font */
-#define TIP_MARGIN_Y 2
-#define TIP_BORDER_X 16.0f
-#define TIP_BORDER_Y 6.0f
+ /* these defines tweaked depending on font */
+#define TIP_MARGIN_Y (2.0f / aspect)
+#define TIP_BORDER_X (16.0f / aspect)
+#define TIP_BORDER_Y (6.0f / aspect)
h = BLF_height_max(data->fstyle.uifont_id);
@@ -637,7 +639,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
fonth += (a == 0) ? h : h + TIP_MARGIN_Y;
}
- fontw *= aspect;
+ //fontw *= aspect;
ar->regiondata = data;
@@ -645,34 +647,30 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
data->lineh = h;
data->spaceh = TIP_MARGIN_Y;
-
/* compute position */
- ofsx = (but->block->panel) ? but->block->panel->ofsx : 0;
- ofsy = (but->block->panel) ? but->block->panel->ofsy : 0;
+ ofsx = 0; //(but->block->panel) ? but->block->panel->ofsx : 0;
+ ofsy = 0; //(but->block->panel) ? but->block->panel->ofsy : 0;
+
+ rect_fl.xmin = BLI_rctf_cent_x(&but->rect) + ofsx - TIP_BORDER_X;
+ rect_fl.xmax = rect_fl.xmin + fontw + TIP_BORDER_X;
+ rect_fl.ymax = but->rect.ymin + ofsy - TIP_BORDER_Y;
+ rect_fl.ymin = rect_fl.ymax - fonth - TIP_BORDER_Y;
- rect_fl.xmin = (but->rect.xmin + but->rect.xmax) * 0.5f + ofsx - (TIP_BORDER_X * aspect);
- rect_fl.xmax = rect_fl.xmin + fontw + (TIP_BORDER_X * aspect);
- rect_fl.ymax = but->rect.ymin + ofsy - (TIP_BORDER_Y * aspect);
- rect_fl.ymin = rect_fl.ymax - fonth * aspect - (TIP_BORDER_Y * aspect);
-
#undef TIP_MARGIN_Y
#undef TIP_BORDER_X
#undef TIP_BORDER_Y
-
- /* copy to int, gets projected if possible too */
- BLI_rcti_rctf_copy(&rect_i, &rect_fl);
+ /* since the text has beens caled already, the size of tooltips is defined now */
+ /* here we try to figure out the right location */
if (butregion) {
- /* XXX temp, region v2ds can be empty still */
- if (butregion->v2d.cur.xmin != butregion->v2d.cur.xmax) {
- UI_view2d_to_region_no_clip(&butregion->v2d, rect_fl.xmin, rect_fl.ymin, &rect_i.xmin, &rect_i.ymin);
- UI_view2d_to_region_no_clip(&butregion->v2d, rect_fl.xmax, rect_fl.ymax, &rect_i.xmax, &rect_i.ymax);
- }
-
- BLI_rcti_translate(&rect_i, butregion->winrct.xmin, butregion->winrct.ymin);
+ float ofsx_fl = rect_fl.xmin, ofsy_fl = rect_fl.ymax;
+ ui_block_to_window_fl(butregion, but->block, &ofsx_fl, &ofsy_fl);
+ BLI_rctf_translate(&rect_fl, ofsx_fl - rect_fl.xmin, ofsy_fl - rect_fl.ymax);
}
+ BLI_rcti_rctf_copy(&rect_i, &rect_fl);
- wm_window_get_size(CTX_wm_window(C), &winx, &winy);
+ /* clip with window boundaries */
+ winx = WM_window_pixels_x(win);
if (rect_i.xmax > winx) {
/* super size */
@@ -693,16 +691,20 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
}
/* widget rect, in region coords */
- data->bbox.xmin = MENU_SHADOW_SIDE;
- data->bbox.xmax = BLI_rcti_size_x(&rect_i) + MENU_SHADOW_SIDE;
- data->bbox.ymin = MENU_SHADOW_BOTTOM;
- data->bbox.ymax = BLI_rcti_size_y(&rect_i) + MENU_SHADOW_BOTTOM;
-
- /* region bigger for shadow */
- ar->winrct.xmin = rect_i.xmin - MENU_SHADOW_SIDE;
- ar->winrct.xmax = rect_i.xmax + MENU_SHADOW_SIDE;
- ar->winrct.ymin = rect_i.ymin - MENU_SHADOW_BOTTOM;
- ar->winrct.ymax = rect_i.ymax + MENU_TOP;
+ {
+ int width = UI_ThemeMenuShadowWidth();
+
+ data->bbox.xmin = width;
+ data->bbox.xmax = BLI_rcti_size_x(&rect_i) + width;
+ data->bbox.ymin = width;
+ data->bbox.ymax = BLI_rcti_size_y(&rect_i) + width;
+
+ /* 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 + MENU_TOP;
+ }
/* adds subwindow */
ED_region_init(C, ar);
@@ -891,11 +893,15 @@ void ui_searchbox_apply(uiBut *but, ARegion *ar)
}
}
-void ui_searchbox_event(bContext *C, ARegion *ar, uiBut *but, wmEvent *event)
+void ui_searchbox_event(bContext *C, ARegion *ar, uiBut *but, const wmEvent *event)
{
uiSearchboxData *data = ar->regiondata;
+ int type = event->type, val = event->val;
- switch (event->type) {
+ if (type == MOUSEPAN)
+ ui_pan_to_scroll(event, &type, &val);
+
+ switch (type) {
case WHEELUPMOUSE:
case UPARROWKEY:
ui_searchbox_select(C, ar, but, -1);
@@ -1097,6 +1103,7 @@ 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();
static ARegionType type;
ARegion *ar;
@@ -1104,7 +1111,7 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
float aspect = but->block->aspect;
rctf rect_fl;
rcti rect_i;
- int winx, winy, ofsx, ofsy;
+ int winx /*, winy */, ofsx, ofsy;
int i;
/* create area region */
@@ -1139,16 +1146,17 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
/* compute position */
if (but->block->flag & UI_BLOCK_SEARCH_MENU) {
+ int width = UI_ThemeMenuShadowWidth();
/* this case is search menu inside other menu */
/* we copy region size */
ar->winrct = butregion->winrct;
/* widget rect, in region coords */
- data->bbox.xmin = MENU_SHADOW_SIDE;
- data->bbox.xmax = BLI_rcti_size_x(&ar->winrct) - MENU_SHADOW_SIDE;
- data->bbox.ymin = MENU_SHADOW_BOTTOM;
- data->bbox.ymax = BLI_rcti_size_y(&ar->winrct) - MENU_SHADOW_BOTTOM;
+ data->bbox.xmin = width;
+ data->bbox.xmax = BLI_rcti_size_x(&ar->winrct) - width;
+ data->bbox.ymin = width;
+ data->bbox.ymax = BLI_rcti_size_y(&ar->winrct) - width;
/* check if button is lower half */
if (but->rect.ymax < BLI_rctf_cent_y(&but->block->rect)) {
@@ -1160,6 +1168,8 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
}
else {
const int searchbox_width = uiSearchBoxWidth();
+ const int shadow_width = UI_ThemeMenuShadowWidth();
+
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;
@@ -1185,7 +1195,9 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
BLI_rcti_translate(&rect_i, butregion->winrct.xmin, butregion->winrct.ymin);
- wm_window_get_size(CTX_wm_window(C), &winx, &winy);
+ winx = WM_window_pixels_x(win);
+ // winy = WM_window_pixels_y(win); /* UNUSED */
+ //wm_window_get_size(win, &winx, &winy);
if (rect_i.xmax > winx) {
/* super size */
@@ -1209,15 +1221,15 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
}
/* widget rect, in region coords */
- data->bbox.xmin = MENU_SHADOW_SIDE;
- data->bbox.xmax = BLI_rcti_size_x(&rect_i) + MENU_SHADOW_SIDE;
- data->bbox.ymin = MENU_SHADOW_BOTTOM;
- data->bbox.ymax = BLI_rcti_size_y(&rect_i) + MENU_SHADOW_BOTTOM;
+ 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;
/* region bigger for shadow */
- ar->winrct.xmin = rect_i.xmin - MENU_SHADOW_SIDE;
- ar->winrct.xmax = rect_i.xmax + MENU_SHADOW_SIDE;
- ar->winrct.ymin = rect_i.ymin - MENU_SHADOW_BOTTOM;
+ 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.ymax = rect_i.ymax;
}
@@ -1314,11 +1326,11 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
/* widget_roundbox_set has this correction too, keep in sync */
if (but->type != PULLDOWN) {
if (but->flag & UI_BUT_ALIGN_TOP)
- butrct.ymax += 1.0f;
+ butrct.ymax += U.pixelsize;
if (but->flag & UI_BUT_ALIGN_LEFT)
- butrct.xmin -= 1.0f;
+ butrct.xmin -= U.pixelsize;
}
-
+
/* calc block rect */
if (block->rect.xmin == 0.0f && block->rect.xmax == 0.0f) {
if (block->buttons.first) {
@@ -1334,7 +1346,7 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
block->rect.xmax = block->rect.ymax = 20;
}
}
-
+
/* aspect = (float)(BLI_rcti_size_x(&block->rect) + 4);*/ /*UNUSED*/
ui_block_to_window_fl(butregion, but->block, &block->rect.xmin, &block->rect.ymin);
ui_block_to_window_fl(butregion, but->block, &block->rect.xmax, &block->rect.ymax);
@@ -1342,8 +1354,8 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
//block->rect.xmin -= 2.0; block->rect.ymin -= 2.0;
//block->rect.xmax += 2.0; block->rect.ymax += 2.0;
- xsize = BLI_rctf_size_x(&block->rect) + 4; /* 4 for shadow */
- ysize = BLI_rctf_size_y(&block->rect) + 4;
+ xsize = BLI_rctf_size_x(&block->rect) + 0.2f * UI_UNIT_X; /* 4 for shadow */
+ ysize = BLI_rctf_size_y(&block->rect) + 0.2f * UI_UNIT_Y;
/* aspect /= (float)xsize;*/ /*UNUSED*/
{
@@ -1351,7 +1363,9 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but,
int winx, winy;
// int offscreen;
- wm_window_get_size(window, &winx, &winy);
+ winx = WM_window_pixels_x(window);
+ winy = WM_window_pixels_y(window);
+ // wm_window_get_size(window, &winx, &winy);
if (block->direction & UI_CENTER) center = ysize / 2;
else center = 0;
@@ -1517,23 +1531,35 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar)
static void ui_popup_block_clip(wmWindow *window, uiBlock *block)
{
+ uiBut *bt;
+ int width = UI_SCREEN_MARGIN;
int winx, winy;
if (block->flag & UI_BLOCK_NO_WIN_CLIP) {
return;
}
- wm_window_get_size(window, &winx, &winy);
+ winx = WM_window_pixels_x(window);
+ winy = WM_window_pixels_y(window);
- if (block->rect.xmin < MENU_SHADOW_SIDE)
- block->rect.xmin = MENU_SHADOW_SIDE;
- if (block->rect.xmax > winx - MENU_SHADOW_SIDE)
- block->rect.xmax = winx - MENU_SHADOW_SIDE;
+ if (block->rect.xmin < width)
+ block->rect.xmin = width;
+ if (block->rect.xmax > winx - width)
+ block->rect.xmax = winx - width;
- if (block->rect.ymin < MENU_SHADOW_BOTTOM)
- block->rect.ymin = MENU_SHADOW_BOTTOM;
+ if (block->rect.ymin < width)
+ block->rect.ymin = width;
if (block->rect.ymax > winy - MENU_TOP)
block->rect.ymax = winy - MENU_TOP;
+
+ /* ensure menu items draw inside left/right boundary */
+ for (bt = block->buttons.first; bt; bt = bt->next) {
+ if (bt->rect.xmin < block->rect.xmin)
+ bt->rect.xmin = block->rect.xmin;
+ if (bt->rect.xmax > block->rect.xmax)
+ bt->rect.xmax = block->rect.xmax;
+ }
+
}
void ui_popup_block_scrolltest(uiBlock *block)
@@ -1583,6 +1609,7 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut
uiBlock *block;
uiPopupBlockHandle *handle;
uiSafetyRct *saferct;
+ int width = UI_ThemeMenuShadowWidth();
/* create handle */
handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle");
@@ -1635,7 +1662,6 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut
/* if this is being created from a button */
if (but) {
block->aspect = but->block->aspect;
-
ui_block_position(window, butregion, but, block);
handle->direction = block->direction;
}
@@ -1652,9 +1678,9 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut
/* 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 - MENU_SHADOW_SIDE;
- ar->winrct.xmax = block->rect.xmax + MENU_SHADOW_SIDE;
- ar->winrct.ymin = block->rect.ymin - MENU_SHADOW_BOTTOM;
+ ar->winrct.xmin = block->rect.xmin - width;
+ ar->winrct.xmax = block->rect.xmax + width;
+ ar->winrct.ymin = block->rect.ymin - width;
ar->winrct.ymax = block->rect.ymax + MENU_TOP;
ui_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin);
@@ -2019,10 +2045,10 @@ static void do_picker_new_mode_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(a
picker_new_hide_reveal(bt->block, colormode);
}
-#define PICKER_H 150
-#define PICKER_W 150
-#define PICKER_SPACE 6
-#define PICKER_BAR 14
+#define PICKER_H (7.5f * U.widget_unit)
+#define PICKER_W (7.5f * U.widget_unit)
+#define PICKER_SPACE (0.3f * U.widget_unit)
+#define PICKER_BAR (0.7f * U.widget_unit)
#define PICKER_TOTAL_W (PICKER_W + PICKER_SPACE + PICKER_BAR)
@@ -2031,11 +2057,11 @@ static void circle_picker(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop)
uiBut *bt;
/* HS circle */
- bt = uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, PICKER_H, PICKER_W, ptr, prop, 0, 0.0, 0.0, 0, 0, "Color");
+ bt = uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, PICKER_H, PICKER_W, ptr, prop, -1, 0.0, 0.0, 0, 0, "Color");
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
/* value */
- bt = uiDefButR_prop(block, HSVCUBE, 0, "", PICKER_W + PICKER_SPACE, 0, PICKER_BAR, PICKER_H, ptr, prop, 0, 0.0, 0.0, UI_GRAD_V_ALT, 0, "Value");
+ 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, "Value");
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
}
@@ -2046,11 +2072,11 @@ static void square_picker(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, in
int bartype = type + 3;
/* HS square */
- bt = uiDefButR_prop(block, HSVCUBE, 0, "", 0, PICKER_BAR + PICKER_SPACE, PICKER_TOTAL_W, PICKER_H, ptr, prop, 0, 0.0, 0.0, type, 0, "Color");
+ 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, "Color");
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
/* value */
- bt = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, PICKER_TOTAL_W, PICKER_BAR, ptr, prop, 0, 0.0, 0.0, bartype, 0, "Value");
+ bt = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, PICKER_TOTAL_W, PICKER_BAR, ptr, prop, -1, 0.0, 0.0, bartype, 0, "Value");
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
}
@@ -2066,11 +2092,12 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper
float rgb_gamma[3];
float min, max, step, precision;
float *hsv = ui_block_hsv_get(block);
+ int yco;
ui_block_hsv_get(block);
width = PICKER_TOTAL_W;
- butwidth = width - UI_UNIT_X - 10;
+ butwidth = width - 1.5f * UI_UNIT_X;
/* existence of profile means storage is in linear color space, with display correction */
/* XXX That tip message is not use anywhere! */
@@ -2108,44 +2135,47 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper
}
/* mode */
+ yco = -1.5f * UI_UNIT_Y;
uiBlockBeginAlign(block);
- bt = uiDefButS(block, ROW, 0, IFACE_("RGB"), 0, -30, width / 3, UI_UNIT_Y, &colormode, 0.0, 0.0, 0, 0, "");
+ 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);
- bt = uiDefButS(block, ROW, 0, IFACE_("HSV"), width / 3, -30, width / 3, UI_UNIT_Y, &colormode, 0.0, 1.0, 0, 0, "");
+ 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, -30, width / 3, UI_UNIT_Y, &colormode, 0.0, 2.0, 0, 0, "");
+ 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);
+ yco = -3.0f * UI_UNIT_Y;
if (show_picker) {
- bt = uiDefIconButO(block, BUT, "UI_OT_eyedropper", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER, butwidth + 10, -60, UI_UNIT_X, UI_UNIT_Y, NULL);
+ bt = uiDefIconButO(block, BUT, "UI_OT_eyedropper", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER, butwidth + 10, yco, UI_UNIT_X, UI_UNIT_Y, NULL);
uiButSetFunc(bt, close_popup_cb, bt, NULL);
}
/* RGB values */
uiBlockBeginAlign(block);
- bt = uiDefButR_prop(block, NUMSLI, 0, IFACE_("R "), 0, -60, butwidth, UI_UNIT_Y, ptr, prop, 0, 0.0, 0.0, 0, 3, TIP_("Red"));
+ bt = uiDefButR_prop(block, NUMSLI, 0, IFACE_("R "), 0, yco, butwidth, UI_UNIT_Y, ptr, prop, 0, 0.0, 0.0, 0, 3, TIP_("Red"));
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
- bt = uiDefButR_prop(block, NUMSLI, 0, IFACE_("G "), 0, -80, butwidth, UI_UNIT_Y, ptr, prop, 1, 0.0, 0.0, 0, 3, TIP_("Green"));
+ bt = uiDefButR_prop(block, NUMSLI, 0, IFACE_("G "), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, ptr, prop, 1, 0.0, 0.0, 0, 3, TIP_("Green"));
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
- bt = uiDefButR_prop(block, NUMSLI, 0, IFACE_("B "), 0, -100, butwidth, UI_UNIT_Y, ptr, prop, 2, 0.0, 0.0, 0, 3, TIP_("Blue"));
+ bt = uiDefButR_prop(block, NUMSLI, 0, IFACE_("B "), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, ptr, prop, 2, 0.0, 0.0, 0, 3, TIP_("Blue"));
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
/* could use uiItemFullR(col, ptr, prop, -1, 0, UI_ITEM_R_EXPAND|UI_ITEM_R_SLIDER, "", ICON_NONE);
* but need to use uiButSetFunc for updating other fake buttons */
/* HSV values */
+ yco = -3.0f * UI_UNIT_Y;
uiBlockBeginAlign(block);
- bt = uiDefButF(block, NUMSLI, 0, IFACE_("H "), 0, -60, butwidth, UI_UNIT_Y, hsv, 0.0, 1.0, 10, 3, TIP_("Hue"));
+ bt = uiDefButF(block, NUMSLI, 0, IFACE_("H "), 0, yco, butwidth, UI_UNIT_Y, hsv, 0.0, 1.0, 10, 3, TIP_("Hue"));
uiButSetFunc(bt, do_hsv_rna_cb, bt, hsv);
- bt = uiDefButF(block, NUMSLI, 0, IFACE_("S "), 0, -80, butwidth, UI_UNIT_Y, hsv + 1, 0.0, 1.0, 10, 3, TIP_("Saturation"));
+ bt = uiDefButF(block, NUMSLI, 0, IFACE_("S "), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, hsv + 1, 0.0, 1.0, 10, 3, TIP_("Saturation"));
uiButSetFunc(bt, do_hsv_rna_cb, bt, hsv);
- bt = uiDefButF(block, NUMSLI, 0, IFACE_("V "), 0, -100, butwidth, UI_UNIT_Y, hsv + 2, 0.0, max, 10, 3, TIP_("Value"));
+ bt = uiDefButF(block, NUMSLI, 0, IFACE_("V "), 0, yco -= UI_UNIT_Y, butwidth, UI_UNIT_Y, hsv + 2, 0.0, max, 10, 3, TIP_("Value"));
uiButSetFunc(bt, do_hsv_rna_cb, bt, hsv);
uiBlockEndAlign(block);
if (rgba[3] != FLT_MAX) {
- bt = uiDefButR_prop(block, NUMSLI, 0, IFACE_("A "), 0, -120, butwidth, UI_UNIT_Y, ptr, prop, 3, 0.0, 0.0, 0, 0, TIP_("Alpha"));
+ 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, 0, TIP_("Alpha"));
uiButSetFunc(bt, do_picker_rna_cb, bt, NULL);
}
else {
@@ -2154,9 +2184,10 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper
BLI_snprintf(hexcol, sizeof(hexcol), "%02X%02X%02X", FTOCHAR(rgb_gamma[0]), FTOCHAR(rgb_gamma[1]), FTOCHAR(rgb_gamma[2]));
- bt = uiDefBut(block, TEX, 0, IFACE_("Hex: "), 0, -60, butwidth, UI_UNIT_Y, hexcol, 0, 8, 0, 0, TIP_("Hex triplet for color (#RRGGBB)"));
+ 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, -80, butwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, LABEL, 0, IFACE_("(Gamma Corrected)"), 0, yco - UI_UNIT_Y, butwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
rgb_to_hsv_v(rgba, hsv);
@@ -2164,7 +2195,7 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper
}
-static int ui_picker_small_wheel_cb(const bContext *UNUSED(C), uiBlock *block, wmEvent *event)
+static int ui_picker_small_wheel_cb(const bContext *UNUSED(C), uiBlock *block, const wmEvent *event)
{
float add = 0.0f;
@@ -2228,7 +2259,7 @@ uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_
uiBlockPicker(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, 10);
+ uiBoundsBlock(block, 0.5 * UI_UNIT_X);
block->block_event_func = ui_picker_small_wheel_cb;
@@ -2386,7 +2417,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
}
block->minbounds = minwidth;
- uiTextBoundsBlock(block, 50);
+ uiTextBoundsBlock(block, 2.5 * UI_UNIT_X);
}
/* if menu slides out of other menu, override direction */
@@ -2402,7 +2433,7 @@ uiPopupBlockHandle *ui_popup_menu_create(bContext *C, ARegion *butregion, uiBut
uiMenuCreateFunc menu_func, void *arg, char *str)
{
wmWindow *window = CTX_wm_window(C);
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_GetStyleDraw();
uiPopupBlockHandle *handle;
uiPopupMenu *pup;
pup = MEM_callocN(sizeof(uiPopupMenu), __func__);
@@ -2466,7 +2497,7 @@ uiPopupBlockHandle *ui_popup_menu_create(bContext *C, ARegion *butregion, uiBut
/* only return handler, and set optional title */
uiPopupMenu *uiPupMenuBegin(bContext *C, const char *title, int icon)
{
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_GetStyleDraw();
uiPopupMenu *pup = MEM_callocN(sizeof(uiPopupMenu), "popup menu");
uiBut *but;
@@ -2543,7 +2574,7 @@ static void operator_cb(bContext *C, void *arg, int retval)
WM_operator_free(op);
}
-static void confirm_cancel_operator(void *opv)
+static void confirm_cancel_operator(bContext *UNUSED(C), void *opv)
{
WM_operator_free(opv);
}
@@ -2590,7 +2621,7 @@ void uiPupMenuOkee(bContext *C, const char *opname, const char *str, ...)
va_list ap;
char titlestr[256];
- BLI_snprintf(titlestr, sizeof(titlestr), "OK? %%i%d", ICON_QUESTION);
+ BLI_snprintf(titlestr, sizeof(titlestr), IFACE_("OK? %%i%d"), ICON_QUESTION);
va_start(ap, str);
vconfirm_opname(C, opname, titlestr, str, ap);
@@ -2604,7 +2635,7 @@ void uiPupMenuOkee(bContext *C, const char *opname, const char *str, ...)
* The operator state for this is implicitly OPERATOR_RUNNING_MODAL */
void uiPupMenuSaveOver(bContext *C, wmOperator *op, const char *filename)
{
- confirm_operator(C, op, "Save Over?", filename);
+ confirm_operator(C, op, IFACE_("Save Over?"), filename);
}
void uiPupMenuNotice(bContext *C, const char *str, ...)
@@ -2622,7 +2653,7 @@ void uiPupMenuError(bContext *C, const char *str, ...)
char nfmt[256];
char titlestr[256];
- BLI_snprintf(titlestr, sizeof(titlestr), "Error %%i%d", ICON_ERROR);
+ BLI_snprintf(titlestr, sizeof(titlestr), IFACE_("Error %%i%d"), ICON_ERROR);
BLI_strncpy(nfmt, str, sizeof(nfmt));
@@ -2649,13 +2680,13 @@ void uiPupMenuReports(bContext *C, ReportList *reports)
/* pass */
}
else if (report->type >= RPT_ERROR) {
- BLI_dynstr_appendf(ds, "Error %%i%d%%t|%s", ICON_ERROR, report->message);
+ BLI_dynstr_appendf(ds, IFACE_("Error %%i%d%%t|%s"), ICON_ERROR, report->message);
}
else if (report->type >= RPT_WARNING) {
- BLI_dynstr_appendf(ds, "Warning %%i%d%%t|%s", ICON_ERROR, report->message);
+ BLI_dynstr_appendf(ds, IFACE_("Warning %%i%d%%t|%s"), ICON_ERROR, report->message);
}
else if (report->type >= RPT_INFO) {
- BLI_dynstr_appendf(ds, "Info %%i%d%%t|%s", ICON_INFO, report->message);
+ BLI_dynstr_appendf(ds, IFACE_("Info %%i%d%%t|%s"), ICON_INFO, report->message);
}
}
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index 7e7db6aeaaa..dd4886a7243 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -143,7 +143,7 @@ static uiFont *uifont_to_blfont(int id)
/* *************** draw ************************ */
-void uiStyleFontDrawExt(uiFontStyle *fs, rcti *rect, const char *str,
+void uiStyleFontDrawExt(uiFontStyle *fs, const rcti *rect, const char *str,
float *r_xofs, float *r_yofs)
{
float height;
@@ -166,7 +166,7 @@ void uiStyleFontDrawExt(uiFontStyle *fs, rcti *rect, const char *str,
}
/* clip is very strict, so we give it some space */
- BLF_clipping(fs->uifont_id, rect->xmin - 1, rect->ymin - 4, rect->xmax + 1, rect->ymax + 4);
+ 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);
@@ -216,7 +216,7 @@ void uiStyleFontDrawRotated(uiFontStyle *fs, rcti *rect, const char *str)
/* rotate counter-clockwise for now (assumes left-to-right language)*/
xofs += height;
yofs = BLF_width(fs->uifont_id, str) + 5;
- angle = 90.0f;
+ angle = (float)M_PI / 2.0f;
/* translate rect to vertical */
txtrect.xmin = rect->xmin - BLI_rcti_size_y(rect);
@@ -261,6 +261,32 @@ uiStyle *UI_GetStyle(void)
return (style != NULL) ? style : U.uistyles.first;
}
+/* for drawing, scaled with DPI setting */
+uiStyle *UI_GetStyleDraw(void)
+{
+ uiStyle *style = UI_GetStyle();
+ static uiStyle _style;
+
+ _style = *style;
+
+ _style.paneltitle.shadx = (short)(UI_DPI_FAC * _style.paneltitle.shadx);
+ _style.paneltitle.shady = (short)(UI_DPI_FAC * _style.grouplabel.shady);
+ _style.grouplabel.shadx = (short)(UI_DPI_FAC * _style.grouplabel.shadx);
+ _style.grouplabel.shady = (short)(UI_DPI_FAC * _style.paneltitle.shady);
+ _style.widgetlabel.shadx = (short)(UI_DPI_FAC * _style.widgetlabel.shadx);
+ _style.widgetlabel.shady = (short)(UI_DPI_FAC * _style.widgetlabel.shady);
+
+ _style.columnspace = (short)(UI_DPI_FAC * _style.columnspace);
+ _style.templatespace = (short)(UI_DPI_FAC * _style.templatespace);
+ _style.boxspace = (short)(UI_DPI_FAC * _style.boxspace);
+ _style.buttonspacex = (short)(UI_DPI_FAC * _style.buttonspacex);
+ _style.buttonspacey = (short)(UI_DPI_FAC * _style.buttonspacey);
+ _style.panelspace = (short)(UI_DPI_FAC * _style.panelspace);
+ _style.panelouter = (short)(UI_DPI_FAC * _style.panelouter);
+
+ return &_style;
+}
+
/* temporarily, does widget font */
int UI_GetStringWidth(const char *str)
{
@@ -304,6 +330,8 @@ void uiStyleInit(void)
{
uiFont *font = U.uifonts.first;
uiStyle *style = U.uistyles.first;
+ int monofont_size = datatoc_bmonofont_ttf_size;
+ unsigned char *monofont_ttf = (unsigned char *)datatoc_bmonofont_ttf;
/* recover from uninitialized dpi */
if (U.dpi == 0)
@@ -364,9 +392,9 @@ void uiStyleInit(void)
* Yes, this build the glyph cache and create
* the texture.
*/
- BLF_size(font->blf_id, 11, U.dpi);
- BLF_size(font->blf_id, 12, U.dpi);
- BLF_size(font->blf_id, 14, U.dpi);
+ BLF_size(font->blf_id, 11 * U.pixelsize, U.dpi);
+ BLF_size(font->blf_id, 12 * U.pixelsize, U.dpi);
+ BLF_size(font->blf_id, 14 * U.pixelsize, U.dpi);
}
}
@@ -374,23 +402,41 @@ void uiStyleInit(void)
ui_style_new(&U.uistyles, "Default Style", UIFONT_DEFAULT);
}
+#ifdef WITH_INTERNATIONAL
+ /* use unicode font for text editor and interactive console */
+ if (U.transopts & USER_DOTRANSLATE) {
+ monofont_ttf = BLF_get_unifont_mono(&monofont_size);
+
+ if (!monofont_ttf) {
+ /* fall back if not found */
+ monofont_size = datatoc_bmonofont_ttf_size;
+ monofont_ttf = (unsigned char *)datatoc_bmonofont_ttf;
+ }
+ }
+
+ /* reload */
+ BLF_unload("monospace");
+ blf_mono_font = -1;
+ blf_mono_font_render = -1;
+#endif
+
/* XXX, this should be moved into a style, but for now best only load the monospaced font once. */
if (blf_mono_font == -1)
- blf_mono_font = BLF_load_mem_unique("monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size);
+ blf_mono_font = BLF_load_mem_unique("monospace", monofont_ttf, monofont_size);
- BLF_size(blf_mono_font, 12, 72);
+ BLF_size(blf_mono_font, 12 * U.pixelsize, 72);
/* second for rendering else we get threading problems */
if (blf_mono_font_render == -1)
- blf_mono_font_render = BLF_load_mem_unique("monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size);
+ blf_mono_font_render = BLF_load_mem_unique("monospace", monofont_ttf, monofont_size);
- BLF_size(blf_mono_font_render, 12, 72);
+ BLF_size(blf_mono_font_render, 12 * U.pixelsize, 72 );
}
void uiStyleFontSet(uiFontStyle *fs)
{
uiFont *font = uifont_to_blfont(fs->uifont_id);
- BLF_size(font->blf_id, fs->points, U.dpi);
+ BLF_size(font->blf_id, fs->points * U.pixelsize, U.dpi);
}
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index f7a53c6bab2..30d360363c6 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -31,38 +31,47 @@
#include "MEM_guardedalloc.h"
-#include "DNA_anim_types.h"
#include "DNA_dynamicpaint_types.h"
-#include "DNA_key_types.h"
+#include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
-#include "DNA_userdef_types.h"
+#include "DNA_object_force.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"
#include "BLI_ghash.h"
#include "BLI_rect.h"
+#include "BLI_math.h"
+#include "BLI_listbase.h"
+#include "BLF_api.h"
#include "BLF_translation.h"
#include "BKE_animsys.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_displist.h"
#include "BKE_dynamicpaint.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
-#include "BKE_object.h"
#include "BKE_material.h"
-#include "BKE_texture.h"
+#include "BKE_modifier.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_packedFile.h"
+#include "BKE_particle.h"
#include "BKE_report.h"
-#include "BKE_displist.h"
#include "BKE_sca.h"
#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_texture.h"
#include "ED_screen.h"
#include "ED_object.h"
#include "ED_render.h"
+#include "ED_util.h"
#include "RNA_access.h"
#include "RNA_enum_types.h"
@@ -71,11 +80,9 @@
#include "WM_types.h"
#include "UI_interface.h"
+#include "UI_interface_icons.h"
#include "interface_intern.h"
-#include "BLF_api.h"
-#include "BLF_translation.h"
-
void UI_template_fix_linking(void)
{
}
@@ -179,13 +186,13 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
/* preview thumbnails */
if (template.prv_rows > 0 && template.prv_cols > 0) {
- int w = 96 * template.prv_cols;
- int h = 96 * template.prv_rows + 20;
+ int w = 4 * U.widget_unit * template.prv_cols;
+ int h = 4 * U.widget_unit * template.prv_rows + U.widget_unit;
/* fake button, it holds space for search items */
uiDefBut(block, LABEL, 0, "", 10, 15, w, h, NULL, 0, 0, 0, 0, NULL);
- but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, 19,
+ 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);
}
@@ -193,15 +200,15 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
else {
const int searchbox_width = uiSearchBoxWidth();
const int searchbox_height = uiSearchBoxHeight();
+
/* fake button, it holds space for search items */
uiDefBut(block, 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);
}
- uiBoundsBlock(block, 6);
+ uiBoundsBlock(block, 0.3f * U.widget_unit);
uiBlockSetDirection(block, UI_DOWN);
uiEndBlock(C, block);
@@ -276,11 +283,13 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
if (id->flag & LIB_FAKEUSER) id_us_plus(id);
else id_us_min(id);
}
- else return;
+ else {
+ return;
+ }
break;
case UI_ID_LOCAL:
if (id) {
- if (id_make_local(id, 0)) {
+ if (id_make_local(id, false)) {
/* reassign to get get proper updates/notifiers */
idptr = RNA_property_pointer_get(&template->ptr, template->prop);
RNA_property_pointer_set(&template->ptr, template->prop, idptr);
@@ -325,6 +334,7 @@ static const char *template_id_browse_tip(StructRNA *type)
case ID_MA: return N_("Browse Material to be linked");
case ID_TE: return N_("Browse Texture to be linked");
case ID_IM: return N_("Browse Image to be linked");
+ case ID_LS: return N_("Browse Line Style Data to be linked");
case ID_LT: return N_("Browse Lattice Data to be linked");
case ID_LA: return N_("Browse Lamp Data to be linked");
case ID_CA: return N_("Browse Camera Data to be linked");
@@ -347,6 +357,7 @@ static const char *template_id_browse_tip(StructRNA *type)
/* 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) {
@@ -359,6 +370,7 @@ static const char *template_id_context(StructRNA *type)
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;
@@ -377,6 +389,7 @@ static const char *template_id_context(StructRNA *type)
}
return BLF_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)
@@ -387,7 +400,6 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
// ListBase *lb; // UNUSED
ID *id, *idfrom;
int editable = RNA_property_editable(&template->ptr, template->prop);
- const char *i18n_ctxt = template_id_context(type);
idptr = RNA_property_pointer_get(&template->ptr, template->prop);
id = idptr.data;
@@ -453,7 +465,7 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
else {
but = uiDefIconBut(block, 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, 1 /* test */) || (idfrom && idfrom->lib))
+ if (!id_make_local(id, true /* test */) || (idfrom && idfrom->lib))
uiButSetFlag(but, UI_BUT_DISABLED);
}
@@ -471,7 +483,7 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE));
if (/* test only */
- (id_copy(id, NULL, 1) == FALSE) ||
+ (id_copy(id, NULL, true) == false) ||
(idfrom && idfrom->lib) ||
(editable == FALSE) ||
/* object in editmode - don't change data */
@@ -506,7 +518,8 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
BLF_I18NCONTEXT_ID_CAMERA,
BLF_I18NCONTEXT_ID_WORLD,
BLF_I18NCONTEXT_ID_SCREEN,
- BLF_I18NCONTEXT_ID_TEXT);
+ BLF_I18NCONTEXT_ID_TEXT,
+ );
BLF_I18N_MSGID_MULTI_CTXT("New", BLF_I18NCONTEXT_ID_SPEAKER,
BLF_I18NCONTEXT_ID_SOUND,
BLF_I18NCONTEXT_ID_ARMATURE,
@@ -514,15 +527,17 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
BLF_I18NCONTEXT_ID_NODETREE,
BLF_I18NCONTEXT_ID_BRUSH,
BLF_I18NCONTEXT_ID_PARTICLESETTINGS,
- BLF_I18NCONTEXT_ID_GPENCIL);
+ BLF_I18NCONTEXT_ID_GPENCIL,
+ BLF_I18NCONTEXT_ID_FREESTYLELINESTYLE,
+ );
if (newop) {
but = uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN,
- (id) ? "" : CTX_IFACE_(i18n_ctxt, "New"), 0, 0, w, UI_UNIT_Y, NULL);
+ (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));
}
else {
- but = uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id) ? "" : CTX_IFACE_(i18n_ctxt, "New"),
+ but = uiDefIconTextBut(block, 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));
}
@@ -531,7 +546,18 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
uiButSetFlag(but, UI_BUT_DISABLED);
}
- if (flag & UI_ID_OPEN) {
+ /* 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,
+ UI_UNIT_X, UI_UNIT_Y, TIP_("Packed File, click to unpack"));
+ uiButGetOperatorPtrRNA(but);
+
+ RNA_string_set(but->opptr, "id_name", id->name + 2);
+ RNA_int_set(but->opptr, "id_type", GS(id->name));
+
+ }
+ else if (flag & UI_ID_OPEN) {
int w = id ? UI_UNIT_X : (flag & UI_ID_ADD_NEW) ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
if (openop) {
@@ -648,7 +674,7 @@ void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, co
const char *text)
{
PropertyRNA *propID, *propType;
- uiLayout *row;
+ uiLayout *split, *row, *sub;
/* get properties... */
propID = RNA_struct_find_property(ptr, propname);
@@ -664,22 +690,34 @@ void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, co
}
/* Start drawing UI Elements using standard defines */
- row = uiLayoutRow(layout, TRUE);
+ split = uiLayoutSplit(layout, 0.33f, FALSE); /* NOTE: split amount here needs to be synced with normal labels */
+
+ /* FIRST PART ................................................ */
+ row = uiLayoutRow(split, FALSE);
/* Label - either use the provided text, or will become "ID-Block:" */
if (text) {
if (text[0])
uiItemL(row, text, ICON_NONE);
}
- else
- uiItemL(row, "ID-Block:", ICON_NONE);
+ else {
+ uiItemL(row, IFACE_("ID-Block:"), ICON_NONE);
+ }
+
+ /* SECOND PART ................................................ */
+ row = uiLayoutRow(split, TRUE);
/* ID-Type Selector - just have a menu of icons */
- /* FIXME: the icon-only setting doesn't work when we supply a blank name */
- uiItemFullR(row, ptr, propType, 0, 0, UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ sub = uiLayoutRow(row, TRUE); /* HACK: special group just for the enum, otherwise we */
+ uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT); /* we get ugly layout with text included too... */
+
+ uiItemFullR(sub, ptr, propType, 0, 0, UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
/* ID-Block Selector - just use pointer widget... */
- uiItemFullR(row, ptr, propID, 0, 0, 0, "", ICON_NONE);
+ sub = uiLayoutRow(row, TRUE); /* HACK: special group to counteract the effects of the previous */
+ uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_EXPAND); /* enum, which now pushes everything too far right */
+
+ uiItemFullR(sub, ptr, propID, 0, 0, 0, "", ICON_NONE);
}
/********************* RNA Path Builder Template ********************/
@@ -716,22 +754,7 @@ void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propna
/************************ Modifier Template *************************/
-#define ERROR_LIBDATA_MESSAGE "Can't edit external libdata"
-
-#include <string.h>
-
-#include "DNA_object_force.h"
-
-#include "BKE_depsgraph.h"
-#include "BKE_modifier.h"
-#include "BKE_particle.h"
-
-#include "ED_util.h"
-
-#include "BLI_math.h"
-#include "BLI_listbase.h"
-
-#include "ED_object.h"
+#define ERROR_LIBDATA_MESSAGE IFACE_("Can't edit external libdata")
static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v)
{
@@ -831,8 +854,8 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob,
block = uiLayoutGetBlock(row);
/* VIRTUAL MODIFIER */
/* XXX this is not used now, since these cannot be accessed via RNA */
- BLI_snprintf(str, sizeof(str), "%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, "Modifier name");
+ 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"));
but = uiDefBut(block, 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"));
@@ -939,18 +962,22 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob,
if (!(ob->mode & OB_MODE_PARTICLE_EDIT) && psys->pathcache) {
if (ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB))
- uiItemO(row, "Convert", ICON_NONE, "OBJECT_OT_duplicates_make_real");
+ uiItemO(row, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"), ICON_NONE,
+ "OBJECT_OT_duplicates_make_real");
else if (psys->part->ren_as == PART_DRAW_PATH)
- uiItemO(row, "Convert", ICON_NONE, "OBJECT_OT_modifier_convert");
+ uiItemO(row, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"), ICON_NONE,
+ "OBJECT_OT_modifier_convert");
}
}
else {
uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
- uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply"), 0, "apply_as", MODIFIER_APPLY_DATA);
+ uiItemEnumO(row, "OBJECT_OT_modifier_apply", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
+ 0, "apply_as", MODIFIER_APPLY_DATA);
if (modifier_isSameTopology(md) && !modifier_isNonGeometrical(md)) {
- uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply as Shape Key"), 0,
- "apply_as", MODIFIER_APPLY_SHAPE);
+ uiItemEnumO(row, "OBJECT_OT_modifier_apply",
+ CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Apply as Shape Key"),
+ 0, "apply_as", MODIFIER_APPLY_SHAPE);
}
}
@@ -960,7 +987,8 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob,
if (!ELEM5(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem,
eModifierType_Cloth, eModifierType_Smoke))
{
- uiItemO(row, IFACE_("Copy"), ICON_NONE, "OBJECT_OT_modifier_copy");
+ uiItemO(row, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Copy"), ICON_NONE,
+ "OBJECT_OT_modifier_copy");
}
}
@@ -1039,9 +1067,8 @@ static void do_constraint_panels(bContext *C, void *ob_pt, int event)
case B_CONSTRAINT_CHANGETARGET:
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
if (ob->pose) ob->pose->flag |= POSE_RECALC; /* checks & sorts pose channels */
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
break;
}
#endif
@@ -1079,16 +1106,16 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
// int rb_col; // UNUSED
/* get constraint typeinfo */
- cti = constraint_get_typeinfo(con);
+ cti = BKE_constraint_get_typeinfo(con);
if (cti == NULL) {
/* exception for 'Null' constraint - it doesn't have constraint typeinfo! */
- BLI_strncpy(typestr, (con->type == CONSTRAINT_TYPE_NULL) ? "Null" : "Unknown", sizeof(typestr));
+ BLI_strncpy(typestr, (con->type == CONSTRAINT_TYPE_NULL) ? IFACE_("Null") : IFACE_("Unknown"), sizeof(typestr));
}
else
- BLI_strncpy(typestr, cti->name, sizeof(typestr));
+ BLI_strncpy(typestr, IFACE_(cti->name), sizeof(typestr));
/* determine whether constraint is proxy protected or not */
- if (proxylocked_constraints_owner(ob, pchan))
+ if (BKE_proxylocked_constraints_owner(ob, pchan))
proxy_protected = (con->flag & CONSTRAINT_PROXY_LOCAL) == 0;
else
proxy_protected = 0;
@@ -1150,7 +1177,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
*
* Up/Down buttons should only be shown (or not grayed - todo) if they serve some purpose.
*/
- if (proxylocked_constraints_owner(ob, pchan)) {
+ if (BKE_proxylocked_constraints_owner(ob, pchan)) {
if (con->prev) {
prev_proxylock = (con->prev->flag & CONSTRAINT_PROXY_LOCAL) ? 0 : 1;
}
@@ -1190,7 +1217,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
/* Set but-locks for protected settings (magic numbers are used here!) */
if (proxy_protected)
- uiBlockSetButLock(block, 1, "Cannot edit Proxy-Protected Constraint");
+ uiBlockSetButLock(block, 1, IFACE_("Cannot edit Proxy-Protected Constraint"));
/* Draw constraint data */
if ((con->flag & CONSTRAINT_EXPAND) == 0) {
@@ -1437,7 +1464,7 @@ static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand
const int line2_y = yoffs + 65;
if (coba == NULL) return;
-
+
bt = uiDefBut(block, BUT, 0, IFACE_("Add"), 0 + xoffs, line1_y, 40, 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);
@@ -1474,7 +1501,7 @@ static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand
RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
row = uiLayoutRow(layout, FALSE);
- uiItemR(row, &ptr, "position", 0, "Pos", ICON_NONE);
+ uiItemR(row, &ptr, "position", 0, IFACE_("Pos"), ICON_NONE);
bt = block->buttons.last;
uiButSetFunc(bt, colorband_update_cb, bt, coba);
@@ -1547,8 +1574,8 @@ void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname
cb->ptr = *ptr;
cb->prop = prop;
- rect.xmin = 0; rect.xmax = 200;
- rect.ymin = 0; rect.ymax = 190;
+ rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X;
+ rect.ymin = 0; rect.ymax = 19.5f * UI_UNIT_X;
block = uiLayoutAbsoluteBlock(layout);
colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb);
@@ -1556,6 +1583,90 @@ void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname
MEM_freeN(cb);
}
+
+/********************* Icon viewer Template ************************/
+
+/* ID Search browse menu, open */
+static uiBlock *icon_view_menu(bContext *C, ARegion *ar, void *arg_litem)
+{
+ static RNAUpdateCb cb;
+ uiBlock *block;
+ uiBut *but;
+ int icon;
+ EnumPropertyItem *item;
+ int a, free;
+
+ /* 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);
+
+ 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;
+
+ 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);
+ }
+
+ uiBoundsBlock(block, 0.3f * U.widget_unit);
+ uiBlockSetDirection(block, UI_TOP);
+ uiEndBlock(C, block);
+
+ if (free) {
+ MEM_freeN(item);
+ }
+
+ return block;
+}
+
+void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname)
+{
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ RNAUpdateCb *cb;
+ uiBlock *block;
+ uiBut *but;
+// rctf rect; /* UNUSED */
+ int icon;
+
+ if (!prop || RNA_property_type(prop) != PROP_ENUM)
+ 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, "");
+
+
+// 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);
+}
+
/********************* Histogram Template ************************/
void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname)
@@ -1579,18 +1690,19 @@ void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname
cb->ptr = *ptr;
cb->prop = prop;
- rect.xmin = 0; rect.xmax = 200;
- rect.ymin = 0; rect.ymax = 190;
+ rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X;
+ rect.ymin = 0; rect.ymax = 9.5f * UI_UNIT_Y;
block = uiLayoutAbsoluteBlock(layout);
//colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb);
hist = (Histogram *)cptr.data;
- hist->height = (hist->height <= UI_UNIT_Y) ? UI_UNIT_Y : hist->height;
+ hist->height = (hist->height <= 20) ? 20 : hist->height;
+
+ bt = uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), UI_DPI_FAC * hist->height,
+ hist, 0, 0, 0, 0, "");
- bt = uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), hist->height, hist,
- 0, 0, 0, 0, "");
uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
MEM_freeN(cb);
@@ -1620,15 +1732,15 @@ void uiTemplateWaveform(uiLayout *layout, PointerRNA *ptr, const char *propname)
cb->ptr = *ptr;
cb->prop = prop;
- rect.xmin = 0; rect.xmax = 200;
- rect.ymin = 0; rect.ymax = 190;
+ rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X;
+ rect.ymin = 0; rect.ymax = 9.5f * UI_UNIT_Y;
block = uiLayoutAbsoluteBlock(layout);
- scopes->wavefrm_height = (scopes->wavefrm_height <= UI_UNIT_Y) ? UI_UNIT_Y : scopes->wavefrm_height;
+ scopes->wavefrm_height = (scopes->wavefrm_height <= 20) ? 20 : scopes->wavefrm_height;
- bt = uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), scopes->wavefrm_height, scopes,
- 0, 0, 0, 0, "");
+ bt = uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), UI_DPI_FAC * scopes->wavefrm_height,
+ scopes, 0, 0, 0, 0, "");
(void)bt; /* UNUSED */
MEM_freeN(cb);
@@ -1658,15 +1770,15 @@ void uiTemplateVectorscope(uiLayout *layout, PointerRNA *ptr, const char *propna
cb->ptr = *ptr;
cb->prop = prop;
- rect.xmin = 0; rect.xmax = 200;
- rect.ymin = 0; rect.ymax = 190;
+ rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X;
+ rect.ymin = 0; rect.ymax = 9.5f * UI_UNIT_Y;
block = uiLayoutAbsoluteBlock(layout);
- scopes->vecscope_height = (scopes->vecscope_height <= UI_UNIT_Y) ? UI_UNIT_Y : scopes->vecscope_height;
+ scopes->vecscope_height = (scopes->vecscope_height <= 20) ? 20 : scopes->vecscope_height;
bt = uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect),
- scopes->vecscope_height, scopes, 0, 0, 0, 0, "");
+ UI_DPI_FAC * scopes->vecscope_height, scopes, 0, 0, 0, 0, "");
uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
MEM_freeN(cb);
@@ -1760,7 +1872,7 @@ static uiBlock *curvemap_clipping_func(bContext *C, ARegion *ar, void *cumap_v)
/* 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, "");
- bt = uiDefButBitI(block, TOG, CUMA_DO_CLIP, 1, "Use Clipping",
+ bt = uiDefButBitI(block, TOG, 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);
@@ -2010,7 +2122,7 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe
/* curve itself */
size = uiLayoutGetWidth(layout);
row = uiLayoutRow(layout, FALSE);
- uiDefBut(block, BUT_CURVE, 0, "", 0, 0, size, MIN2(size, 200), cumap, 0.0f, 1.0f, bg, 0, "");
+ uiDefBut(block, BUT_CURVE, 0, "", 0, 0, size, MIN2(size, 10.0f * UI_UNIT_X), cumap, 0.0f, 1.0f, bg, 0, "");
/* sliders for selected point */
for (i = 0; i < cm->totpoint; i++) {
@@ -2021,16 +2133,22 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe
}
if (cmp) {
- const float range_clamp[2] = {0.0f, 1.0f};
- const float range_unclamp[2] = {-1000.0f, 1000.0f}; /* arbitrary limits here */
- const float *range = (cumap->flag & CUMA_DO_CLIP) ? range_clamp : range_unclamp;
+ rctf bounds;
+
+ if (cumap->flag & CUMA_DO_CLIP) {
+ bounds = cumap->clipr;
+ }
+ else {
+ bounds.xmin = bounds.ymin = -1000.0;
+ bounds.xmax = bounds.ymax = 1000.0;
+ }
uiLayoutRow(layout, TRUE);
uiBlockSetNFunc(block, curvemap_buttons_update, MEM_dupallocN(cb), cumap);
- bt = uiDefButF(block, NUM, 0, "X", 0, 2 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y,
- &cmp->x, range[0], range[1], 1, 5, "");
- bt = uiDefButF(block, NUM, 0, "Y", 0, 1 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y,
- &cmp->y, range[0], range[1], 1, 5, "");
+ uiDefButF(block, 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,
+ &cmp->y, bounds.ymin, bounds.ymax, 1, 5, "");
}
/* black/white levels */
@@ -2081,7 +2199,7 @@ void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propn
/********************* ColorPicker Template ************************/
-#define WHEEL_SIZE 100
+#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,
@@ -2329,432 +2447,203 @@ void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propnam
/************************* List Template **************************/
-
-static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon, int big)
-{
- ID *id = NULL;
- int icon;
-
- if (!itemptr->data)
- return rnaicon;
-
- /* try ID, material or texture slot */
- if (RNA_struct_is_ID(itemptr->type)) {
- id = itemptr->id.data;
- }
- else if (RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
- id = RNA_pointer_get(itemptr, "material").data;
- }
- else if (RNA_struct_is_a(itemptr->type, &RNA_TextureSlot)) {
- id = RNA_pointer_get(itemptr, "texture").data;
- }
- else if (RNA_struct_is_a(itemptr->type, &RNA_DynamicPaintSurface)) {
- DynamicPaintSurface *surface = (DynamicPaintSurface *)itemptr->data;
-
- if (surface->format == MOD_DPAINT_SURFACE_F_PTEX) return ICON_TEXTURE_SHADED;
- else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) return ICON_OUTLINER_DATA_MESH;
- else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return ICON_FILE_IMAGE;
- }
-
- /* get icon from ID */
- if (id) {
- icon = ui_id_icon_get(C, id, big);
-
- if (icon)
- return icon;
- }
-
- return rnaicon;
-}
-
-static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i,
- int rnaicon, PointerRNA *activeptr, PropertyRNA *activeprop, const char *prop_list_id)
+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))
{
- uiBlock *block = uiLayoutGetBlock(layout);
- uiBut *but;
- uiLayout *split, *overlap, *sub, *row;
char *namebuf;
const char *name;
- int icon;
-
- overlap = uiLayoutOverlap(layout);
-
- /* list item behind label & other buttons */
- sub = uiLayoutRow(overlap, FALSE);
-
- but = uiDefButR_prop(block, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr, activeprop,
- 0, 0, i, 0, 0, "");
- uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
-
- sub = uiLayoutRow(overlap, FALSE);
-
- /* retrieve icon and name */
- icon = list_item_icon_get(C, itemptr, rnaicon, 0);
- if (icon == ICON_NONE || icon == ICON_DOT)
- icon = 0;
namebuf = RNA_struct_name_get_alloc(itemptr, NULL, 0, NULL);
name = (namebuf) ? namebuf : "";
- /* hardcoded types */
- if (itemptr->type == &RNA_MeshTexturePolyLayer || itemptr->type == &RNA_MeshLoopColorLayer) {
- uiItemL(sub, name, icon);
- uiBlockSetEmboss(block, UI_EMBOSSN);
- uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render",
- 0, 0, 0, 0, 0, NULL);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ /* Simplest one! */
+ switch (ui_list->layout_type) {
+ case UILST_LAYOUT_GRID:
+ uiItemL(layout, "", icon);
+ break;
+ case UILST_LAYOUT_DEFAULT:
+ case UILST_LAYOUT_COMPACT:
+ default:
+ uiItemL(layout, name, icon);
+ break;
}
- else if (RNA_struct_is_a(itemptr->type, &RNA_MaterialTextureSlot)) {
- uiItemL(sub, name, icon);
- uiBlockSetEmboss(block, UI_EMBOSS);
- uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, ptr, "use_textures", i, 0, 0, 0, 0, NULL);
- }
- else if (RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer)) {
- uiItemL(sub, name, icon);
- uiBlockSetEmboss(block, UI_EMBOSS);
- uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "use", 0, 0, 0, 0, 0, NULL);
- }
- else if (RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
- /* provision to draw active node name */
- Material *ma, *manode;
- Scene *scene = CTX_data_scene(C);
- Object *ob = (Object *)ptr->id.data;
- int index = (Material **)itemptr->data - ob->mat;
- /* default item with material base name */
- uiItemL(sub, name, icon);
-
- ma = give_current_material(ob, index + 1);
- if (ma && !BKE_scene_use_new_shading_nodes(scene)) {
- manode = give_node_material(ma);
- if (manode) {
- char str[MAX_ID_NAME + 12];
- BLI_snprintf(str, sizeof(str), IFACE_("Node %s"), manode->id.name + 2);
- uiItemL(sub, str, ui_id_icon_get(C, &manode->id, 1));
- }
- else if (ma->use_nodes) {
- uiItemL(sub, IFACE_("Node <none>"), ICON_NONE);
- }
- }
- }
- else if (itemptr->type == &RNA_ShapeKey) {
- Object *ob = (Object *)activeptr->data;
- Key *key = (Key *)itemptr->id.data;
- KeyBlock *kb = (KeyBlock *)itemptr->data;
-
- split = uiLayoutSplit(sub, 0.66f, FALSE);
-
- uiItemL(split, name, icon);
-
- uiBlockSetEmboss(block, UI_EMBOSSN);
- row = uiLayoutRow(split, TRUE);
- if (i == 0 || (key->type != KEY_RELATIVE)) uiItemL(row, "", ICON_NONE);
- else uiItemR(row, itemptr, "value", 0, "", ICON_NONE);
- uiItemR(row, itemptr, "mute", 0, "", ICON_NONE);
-
- if ((kb->flag & KEYBLOCK_MUTE) ||
- (ob->mode == OB_MODE_EDIT && !((ob->shapeflag & OB_SHAPE_EDIT_MODE) && ob->type == OB_MESH)))
- {
- uiLayoutSetActive(row, FALSE);
- }
- uiBlockSetEmboss(block, UI_EMBOSS);
- }
- else if (itemptr->type == &RNA_VertexGroup) {
- bDeformGroup *dg = (bDeformGroup *)itemptr->data;
- uiItemL(sub, name, icon);
- /* RNA does not allow nice lock icons, use lower level buttons */
-#if 0
- uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "lock_weight", 0, 0, 0, 0, 0, NULL);
-#else
- uiBlockSetEmboss(block, UI_EMBOSSN);
- uiDefIconButBitC(block, TOG, DG_LOCK_WEIGHT, 0, (dg->flag & DG_LOCK_WEIGHT) ? ICON_LOCKED : ICON_UNLOCKED,
- 0, 0, UI_UNIT_X, UI_UNIT_Y, &dg->flag, 0, 0, 0, 0,
- TIP_("Maintain relative weights while painting"));
- uiBlockSetEmboss(block, UI_EMBOSS);
-#endif
- }
- else if (itemptr->type == &RNA_KeyingSetPath) {
- KS_Path *ksp = (KS_Path *)itemptr->data;
-
- /* icon needs to be the type of ID which is currently active */
- RNA_enum_icon_from_value(id_type_items, ksp->idtype, &icon);
-
- /* nothing else special to do... */
- uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */
- }
- else if (itemptr->type == &RNA_DynamicPaintSurface) {
- char name_final[96];
- const char *enum_name;
- PropertyRNA *prop = RNA_struct_find_property(itemptr, "surface_type");
- DynamicPaintSurface *surface = (DynamicPaintSurface *)itemptr->data;
-
- RNA_property_enum_name(C, itemptr, prop, RNA_property_enum_get(itemptr, prop), &enum_name);
-
- BLI_snprintf(name_final, sizeof(name_final), "%s (%s)", name, enum_name);
- uiItemL(sub, name_final, icon);
- if (dynamicPaint_surfaceHasColorPreview(surface)) {
- uiBlockSetEmboss(block, UI_EMBOSSN);
- uiDefIconButR(block, OPTION, 0,
- (surface->flags & MOD_DPAINT_PREVIEW) ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON,
- 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "show_preview", 0, 0, 0, 0, 0, NULL);
- uiBlockSetEmboss(block, UI_EMBOSS);
- }
- uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "is_active", i, 0, 0, 0, 0, NULL);
- }
- else if (itemptr->type == &RNA_MovieTrackingObject) {
- MovieTrackingObject *tracking_object = (MovieTrackingObject *)itemptr->data;
-
- split = uiLayoutSplit(sub, 0.75f, FALSE);
- if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
- uiItemL(split, name, ICON_CAMERA_DATA);
- }
- else {
- uiItemL(split, name, ICON_OBJECT_DATA);
- }
- }
- else if (itemptr->type == &RNA_MaskLayer) {
- split = uiLayoutRow(sub, FALSE);
-
- uiItemL(split, name, icon);
-
- uiBlockSetEmboss(block, UI_EMBOSSN);
- row = uiLayoutRow(split, TRUE);
- uiItemR(row, itemptr, "alpha", 0, "", ICON_NONE);
- uiItemR(row, itemptr, "hide", 0, "", ICON_NONE);
- uiItemR(row, itemptr, "hide_select", 0, "", ICON_NONE);
- uiItemR(row, itemptr, "hide_render", 0, "", ICON_NONE);
-
- uiBlockSetEmboss(block, UI_EMBOSS);
- }
-
- /* There is a last chance to display custom controls (in addition to the name/label):
- * If the given item property group features a string property named as prop_list,
- * this tries to add controls for all properties of the item listed in that string property.
- * (colon-separated names).
- *
- * This is especially useful for python. E.g., if you list a collection of this property
- * group:
- *
- * class TestPropertyGroup(bpy.types.PropertyGroup):
- * bool = BoolProperty(default=False)
- * integer = IntProperty()
- * string = StringProperty()
- *
- * # A string of all identifiers (colon-separated) which property's controls should be
- * # displayed in a template_list.
- * template_list_controls = StringProperty(default="integer:bool:string", options={"HIDDEN"})
- *
- * ... you'll get a numfield for the integer prop, a check box for the bool prop, and a textfield
- * for the string prop, after the name of each item of the collection.
- */
- else if (prop_list_id) {
- row = uiLayoutRow(sub, TRUE);
- uiItemL(row, name, icon);
-
- /* XXX: Check, as sometimes we get an itemptr looking like
- * {id = {data = 0x0}, type = 0x0, data = 0x0}
- * which would obviously produce a sigsev... */
- if (itemptr->type) {
- /* If the special property is set for the item, and it is a collection... */
- PropertyRNA *prop_list = RNA_struct_find_property(itemptr, prop_list_id);
-
- if (prop_list && RNA_property_type(prop_list) == PROP_STRING) {
- int prop_names_len;
- char *prop_names = RNA_property_string_get_alloc(itemptr, prop_list, NULL, 0, &prop_names_len);
- char *prop_names_end = prop_names + prop_names_len;
- char *id = prop_names;
- char *id_next;
- while (id < prop_names_end) {
- if ((id_next = strchr(id, ':'))) *id_next++ = '\0';
- else id_next = prop_names_end;
- uiItemR(row, itemptr, id, 0, NULL, ICON_NONE);
- id = id_next;
- }
- MEM_freeN(prop_names);
- }
- }
- }
-
- else
- uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */
-
/* free name */
if (namebuf) {
MEM_freeN(namebuf);
}
}
-void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *activeptr,
- const char *activepropname, const char *prop_list, int rows, int maxrows, int listtype)
+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)
{
+ uiListType *ui_list_type;
+ uiList *ui_list = NULL;
+ ARegion *ar;
+ uiListDrawItemFunc draw_item;
+
PropertyRNA *prop = NULL, *activeprop;
PropertyType type, activetype;
StructRNA *ptype;
- uiLayout *box, *row, *col;
- uiBlock *block;
+ uiLayout *box, *row, *col, *sub, *overlap;
+ uiBlock *block, *subblock;
uiBut *but;
- Panel *pa;
- const char *name;
+
+ char ui_list_id[UI_MAX_NAME_STR];
char numstr[32];
- int rnaicon = 0, icon = 0, i = 0, activei = 0, len = 0, items, found, min, max;
+ int rnaicon = ICON_NONE, icon = ICON_NONE;
+ int i = 0, activei = 0;
+ int len = 0;
+ int items;
+ int found;
+ int min, max;
/* 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])) {
+ RNA_warning("template_list using default '%s' UIList class must provide a custom list_id",
+ UI_UL_DEFAULT_CLASS_NAME);
+ return;
+ }
+
block = uiLayoutGetBlock(layout);
- pa = block->panel;
- if (!pa) {
- RNA_warning("Only works inside a panel");
+ if (!active_dataptr->data) {
+ RNA_warning("No active data");
return;
}
- if (!activeptr->data)
- return;
-
- if (ptr->data) {
- prop = RNA_struct_find_property(ptr, propname);
+ if (dataptr->data) {
+ prop = RNA_struct_find_property(dataptr, propname);
if (!prop) {
- RNA_warning("Property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ RNA_warning("Property not found: %s.%s", RNA_struct_identifier(dataptr->type), propname);
return;
}
}
- activeprop = RNA_struct_find_property(activeptr, activepropname);
+ activeprop = RNA_struct_find_property(active_dataptr, active_propname);
if (!activeprop) {
- RNA_warning("Property not found: %s.%s", RNA_struct_identifier(ptr->type), activepropname);
+ RNA_warning("Property not found: %s.%s", RNA_struct_identifier(active_dataptr->type), active_propname);
return;
}
if (prop) {
type = RNA_property_type(prop);
if (type != PROP_COLLECTION) {
- RNA_warning("uiExpected collection property");
+ RNA_warning("Expected a collection data property");
return;
}
}
activetype = RNA_property_type(activeprop);
if (activetype != PROP_INT) {
- RNA_warning("Expected integer property");
+ RNA_warning("Expected an integer active data property");
return;
}
/* get icon */
- if (ptr->data && prop) {
- ptype = RNA_property_pointer_type(ptr, prop);
+ if (dataptr->data && prop) {
+ ptype = RNA_property_pointer_type(dataptr, prop);
rnaicon = RNA_struct_ui_icon(ptype);
}
/* get active data */
- activei = RNA_property_int_get(activeptr, activeprop);
-
- if (listtype == 'i') {
- box = uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
- col = uiLayoutColumn(box, TRUE);
- row = uiLayoutRow(col, FALSE);
+ activei = RNA_property_int_get(active_dataptr, activeprop);
- if (ptr->data && prop) {
- /* create list items */
- RNA_PROP_BEGIN (ptr, itemptr, prop)
- {
- /* create button */
- if (!(i % 9))
- row = uiLayoutRow(col, FALSE);
+ /* Find the uiList type. */
+ ui_list_type = WM_uilisttype_find(listtype_name, FALSE);
- icon = list_item_icon_get(C, &itemptr, rnaicon, 1);
- but = uiDefIconButR_prop(block, LISTROW, 0, icon, 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr,
- activeprop, 0, 0, i, 0, 0, "");
- uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
-
-
- i++;
+ if (ui_list_type == NULL) {
+ RNA_warning("List type %s not found", listtype_name);
+ return;
}
- RNA_PROP_END;
- }
- }
- else if (listtype == 'c') {
- /* compact layout */
- row = uiLayoutRow(layout, TRUE);
+ draw_item = ui_list_type->draw_item ? ui_list_type->draw_item : uilist_draw_item_default;
- if (ptr->data && prop) {
- /* create list items */
- RNA_PROP_BEGIN (ptr, itemptr, prop)
- {
- found = (activei == i);
+ /* Find or add the uiList to the current Region. */
+ /* We tag the list id with the list type... */
+ BLI_snprintf(ui_list_id, sizeof(ui_list_id), "%s_%s", ui_list_type->idname, list_id ? list_id : "");
- if (found) {
- /* create button */
- name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL);
- icon = list_item_icon_get(C, &itemptr, rnaicon, 0);
- uiItemL(row, (name) ? name : "", icon);
+ ar = CTX_wm_region(C);
+ ui_list = BLI_findstring(&ar->ui_lists, ui_list_id, offsetof(uiList, list_id));
- if (name) {
- MEM_freeN((void *)name);
+ if (!ui_list) {
+ ui_list = MEM_callocN(sizeof(uiList), __func__);
+ BLI_strncpy(ui_list->list_id, ui_list_id, sizeof(ui_list->list_id));
+ BLI_addtail(&ar->ui_lists, ui_list);
}
- }
- i++;
- }
- RNA_PROP_END;
- }
-
- /* if not found, add in dummy button */
- if (i == 0)
- uiItemL(row, "", ICON_NONE);
+ /* Because we can't actually pass type across save&load... */
+ ui_list->type = ui_list_type;
+ ui_list->layout_type = layout_type;
- /* next/prev button */
- BLI_snprintf(numstr, sizeof(numstr), "%d :", i);
- but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, activeptr,
- activeprop, 0, 0, 0, 0, 0, "");
- if (i == 0)
- uiButSetFlag(but, UI_BUT_DISABLED);
- }
- else {
+ switch (layout_type) {
+ case UILST_LAYOUT_DEFAULT:
/* default rows */
if (rows == 0)
rows = 5;
if (maxrows == 0)
maxrows = 5;
- if (pa->list_grip_size != 0)
- rows = pa->list_grip_size;
+ if (ui_list->list_grip_size != 0)
+ rows = ui_list->list_grip_size;
/* layout */
- box = uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
+ box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
row = uiLayoutRow(box, FALSE);
col = uiLayoutColumn(row, TRUE);
/* init numbers */
- RNA_property_int_range(activeptr, activeprop, &min, &max);
+ RNA_property_int_range(active_dataptr, activeprop, &min, &max);
if (prop)
- len = RNA_property_collection_length(ptr, prop);
+ len = RNA_property_collection_length(dataptr, prop);
items = CLAMPIS(len, rows, MAX2(rows, maxrows));
/* if list length changes and active is out of view, scroll to it */
- if (pa->list_last_len != len)
- if ((activei < pa->list_scroll || activei >= pa->list_scroll + items))
- pa->list_scroll = activei;
+ if ((ui_list->list_last_len != len) &&
+ (activei < ui_list->list_scroll || activei >= ui_list->list_scroll + items))
+ {
+ ui_list->list_scroll = activei;
+ }
- pa->list_scroll = MIN2(pa->list_scroll, len - items);
- pa->list_scroll = MAX2(pa->list_scroll, 0);
- pa->list_size = items;
- pa->list_last_len = len;
+ ui_list->list_scroll = min_ii(ui_list->list_scroll, len - items);
+ ui_list->list_scroll = max_ii(ui_list->list_scroll, 0);
+ ui_list->list_size = items;
+ ui_list->list_last_len = len;
- if (ptr->data && prop) {
+ if (dataptr->data && prop) {
/* create list items */
- RNA_PROP_BEGIN (ptr, itemptr, prop)
+ RNA_PROP_BEGIN (dataptr, itemptr, prop)
{
- if (i >= pa->list_scroll && i < pa->list_scroll + items)
- list_item_row(C, col, ptr, &itemptr, i, rnaicon, activeptr, activeprop, prop_list);
+ if (i >= ui_list->list_scroll && i < ui_list->list_scroll + items) {
+ subblock = uiLayoutGetBlock(col);
+ overlap = uiLayoutOverlap(col);
+
+ /* 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, i, 0, 0, "");
+ uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
+
+ sub = uiLayoutRow(overlap, FALSE);
+
+ icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE);
+ if (icon == ICON_DOT)
+ icon = ICON_NONE;
+ draw_item(ui_list, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+ }
i++;
}
RNA_PROP_END;
}
/* add dummy buttons to fill space */
- while (i < pa->list_scroll + items) {
- if (i >= pa->list_scroll)
+ while (i < ui_list->list_scroll + items) {
+ if (i >= ui_list->list_scroll)
uiItemL(col, "", ICON_NONE);
i++;
}
@@ -2762,9 +2651,75 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *
/* add scrollbar */
if (len > items) {
col = uiLayoutColumn(row, FALSE);
- uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &pa->list_scroll,
+ uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &ui_list->list_scroll,
0, len - items, items, 0, "");
}
+ break;
+ case UILST_LAYOUT_COMPACT:
+ row = uiLayoutRow(layout, TRUE);
+
+ if (dataptr->data && prop) {
+ /* create list items */
+ RNA_PROP_BEGIN (dataptr, itemptr, prop)
+ {
+ found = (activei == i);
+
+ if (found) {
+ icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE);
+ if (icon == ICON_DOT)
+ icon = ICON_NONE;
+ draw_item(ui_list, C, row, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+ }
+
+ i++;
+}
+ RNA_PROP_END;
+ }
+
+ /* if list is empty, add in dummy button */
+ if (i == 0)
+ uiItemL(row, "", ICON_NONE);
+
+ /* next/prev button */
+ BLI_snprintf(numstr, sizeof(numstr), "%d :", i);
+ but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y,
+ active_dataptr, activeprop, 0, 0, 0, 0, 0, "");
+ if (i == 0)
+ uiButSetFlag(but, UI_BUT_DISABLED);
+ break;
+ case UILST_LAYOUT_GRID:
+ box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop);
+ col = uiLayoutColumn(box, TRUE);
+ row = uiLayoutRow(col, FALSE);
+
+ if (dataptr->data && prop) {
+ /* create list items */
+ RNA_PROP_BEGIN (dataptr, itemptr, prop)
+ {
+ /* create button */
+ if (!(i % 9))
+ row = uiLayoutRow(col, FALSE);
+
+ subblock = uiLayoutGetBlock(row);
+ overlap = uiLayoutOverlap(row);
+
+ /* 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, i, 0, 0, "");
+ uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
+
+ sub = uiLayoutRow(overlap, FALSE);
+
+ icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE);
+ draw_item(ui_list, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+
+ i++;
+ }
+ RNA_PROP_END;
+ }
+ break;
}
}
@@ -2782,7 +2737,7 @@ static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char
{
GHashIterator *iter = WM_operatortype_iter();
- for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
+ for (; BLI_ghashIterator_notDone(iter); BLI_ghashIterator_step(iter)) {
wmOperatorType *ot = BLI_ghashIterator_getValue(iter);
if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0)
@@ -3078,7 +3033,7 @@ void uiTemplateColorspaceSettings(uiLayout *layout, PointerRNA *ptr, const char
colorspace_settings_ptr = RNA_property_pointer_get(ptr, prop);
- uiItemL(layout, "Color Space:", ICON_NONE);
+ uiItemL(layout, IFACE_("Input Color Space:"), ICON_NONE);
uiItemR(layout, &colorspace_settings_ptr, "name", 0, "", ICON_NONE);
}
@@ -3114,3 +3069,65 @@ void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *UNUSED(C), P
if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES)
uiTemplateCurveMapping(col, &view_transform_ptr, "curve_mapping", 'c', TRUE, 0);
}
+
+/********************************* Component Menu *************************************/
+
+typedef struct ComponentMenuArgs {
+ PointerRNA ptr;
+ char propname[64]; /* XXX arbitrary */
+} ComponentMenuArgs;
+/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
+static uiBlock *component_menu(bContext *C, ARegion *ar, void *args_v)
+{
+ ComponentMenuArgs *args = (ComponentMenuArgs *)args_v;
+ uiBlock *block;
+ uiLayout *layout;
+
+ block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
+ uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN);
+
+ layout = uiLayoutColumn(uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, UI_GetStyle()), 0);
+
+ uiItemR(layout, &args->ptr, args->propname, UI_ITEM_R_EXPAND, "", ICON_NONE);
+
+ uiBoundsBlock(block, 6);
+ uiBlockSetDirection(block, UI_DOWN);
+ uiEndBlock(C, block);
+
+ return block;
+}
+void uiTemplateComponentMenu(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *name)
+{
+ ComponentMenuArgs *args = MEM_callocN(sizeof(ComponentMenuArgs), "component menu template args");
+ uiBlock *block;
+
+ args->ptr = *ptr;
+ BLI_strncpy(args->propname, propname, sizeof(args->propname));
+
+ block = uiLayoutGetBlock(layout);
+ uiBlockBeginAlign(block);
+
+ uiDefBlockButN(block, component_menu, args, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, "");
+
+ uiBlockEndAlign(block);
+}
+
+/************************* Node Socket Icon **************************/
+
+void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float *color)
+{
+ uiBlock *block;
+ uiBut *but;
+
+ block = uiLayoutGetBlock(layout);
+ uiBlockBeginAlign(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, "");
+ rgba_float_to_uchar(but->col, color);
+
+ uiBlockEndAlign(block);
+}
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index d363609fbd9..3bf1a1a7701 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -78,7 +78,7 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
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, 0, 0, 0, -1, -1, NULL);
+ but = uiDefButR_prop(block, COLOR, 0, name, x1, y1, x2, y2, ptr, prop, -1, 0, 0, -1, -1, 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);
@@ -137,7 +137,7 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
* in cases where PROP_HIDDEN flag can't be used for a property.
*/
int uiDefAutoButsRNA(uiLayout *layout, PointerRNA *ptr,
- int (*check_prop)(PointerRNA *, PropertyRNA *),
+ bool (*check_prop)(PointerRNA *, PropertyRNA *),
const char label_align)
{
uiLayout *split, *col;
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index c4b80f0a42f..96c8ded46da 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -119,7 +119,7 @@ typedef struct uiWidgetType {
void (*state)(struct uiWidgetType *, int state);
void (*draw)(uiWidgetColors *, rcti *, int state, int roundboxalign);
void (*custom)(uiBut *, uiWidgetColors *, rcti *, int state, int roundboxalign);
- void (*text)(uiFontStyle *, uiWidgetColors *, uiBut *, rcti *);
+ void (*text)(uiFontStyle *, uiWidgetColors *, uiBut *, rcti *);
} uiWidgetType;
@@ -218,13 +218,16 @@ void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y
glDisable(GL_BLEND);
}
-void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad)
+void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad, bool use_alpha)
{
float color[4];
int j;
glEnable(GL_BLEND);
glGetFloatv(GL_CURRENT_COLOR, color);
+ if (use_alpha) {
+ color[3] = 0.5f;
+ }
color[3] *= 0.125f;
glColor4fv(color);
@@ -251,7 +254,7 @@ static void widget_init(uiWidgetBase *wtb)
/* helper call, makes shadow rect, with 'sun' above menu, so only shadow to left/right/bottom */
/* return tot */
-static int round_box_shadow_edges(float (*vert)[2], rcti *rect, float rad, int roundboxalign, float step)
+static int round_box_shadow_edges(float (*vert)[2], const rcti *rect, float rad, int roundboxalign, float step)
{
float vec[WIDGET_CURVE_RESOLU][2];
float minx, miny, maxx, maxy;
@@ -261,7 +264,7 @@ static int round_box_shadow_edges(float (*vert)[2], rcti *rect, float rad, int r
if (2.0f * rad > BLI_rcti_size_y(rect))
rad = 0.5f * BLI_rcti_size_y(rect);
-
+
minx = rect->xmin - step;
miny = rect->ymin - step;
maxx = rect->xmax + step;
@@ -329,14 +332,14 @@ static int round_box_shadow_edges(float (*vert)[2], rcti *rect, float rad, int r
}
/* this call has 1 extra arg to allow mask outline */
-static void round_box__edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, float rad, float radi)
+static void round_box__edges(uiWidgetBase *wt, int roundboxalign, const rcti *rect, float rad, float radi)
{
float vec[WIDGET_CURVE_RESOLU][2], veci[WIDGET_CURVE_RESOLU][2];
float minx = rect->xmin, miny = rect->ymin, maxx = rect->xmax, maxy = rect->ymax;
- float minxi = minx + 1.0f; /* boundbox inner */
- float maxxi = maxx - 1.0f;
- float minyi = miny + 1.0f;
- float maxyi = maxy - 1.0f;
+ float minxi = minx + U.pixelsize; /* boundbox inner */
+ float maxxi = maxx - U.pixelsize;
+ float minyi = miny + U.pixelsize;
+ float maxyi = maxy - U.pixelsize;
float facxi = (maxxi != minxi) ? 1.0f / (maxxi - minxi) : 0.0f; /* for uv, can divide by zero */
float facyi = (maxyi != minyi) ? 1.0f / (maxyi - minyi) : 0.0f;
int a, tot = 0, minsize;
@@ -346,13 +349,13 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, fl
(roundboxalign & (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) == (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) ? 1 : 2;
minsize = min_ii(BLI_rcti_size_x(rect) * hnum,
- BLI_rcti_size_y(rect) * vnum);
+ BLI_rcti_size_y(rect) * vnum);
if (2.0f * rad > minsize)
rad = 0.5f * minsize;
if (2.0f * (radi + 1.0f) > minsize)
- radi = 0.5f * minsize - 1.0f;
+ radi = 0.5f * minsize - U.pixelsize;
/* mult */
for (a = 0; a < WIDGET_CURVE_RESOLU; a++) {
@@ -479,14 +482,14 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, fl
wt->totvert = tot;
}
-static void round_box_edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, float rad)
+static void round_box_edges(uiWidgetBase *wt, int roundboxalign, const rcti *rect, float rad)
{
- round_box__edges(wt, roundboxalign, rect, rad, rad - 1.0f);
+ round_box__edges(wt, roundboxalign, rect, rad, rad - U.pixelsize);
}
/* based on button rect, return scaled array of triangles */
-static void widget_num_tria(uiWidgetTrias *tria, rcti *rect, float triasize, char where)
+static void widget_num_tria(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
{
float centx, centy, sizex, sizey, minsize;
int a, i1 = 0, i2 = 1;
@@ -521,7 +524,7 @@ static void widget_num_tria(uiWidgetTrias *tria, rcti *rect, float triasize, cha
tria->index = num_tria_face;
}
-static void widget_scroll_circle(uiWidgetTrias *tria, rcti *rect, float triasize, char where)
+static void widget_scroll_circle(uiWidgetTrias *tria, const rcti *rect, float triasize, char where)
{
float centx, centy, sizex, sizey, minsize;
int a, i1 = 0, i2 = 1;
@@ -564,21 +567,16 @@ static void widget_trias_draw(uiWidgetTrias *tria)
glDisableClientState(GL_VERTEX_ARRAY);
}
-static void widget_menu_trias(uiWidgetTrias *tria, rcti *rect)
+static void widget_menu_trias(uiWidgetTrias *tria, const rcti *rect)
{
- float centx, centy, size, asp;
+ float centx, centy, size;
int a;
/* center position and size */
- centx = rect->xmax - 0.5f * BLI_rcti_size_y(rect);
- centy = rect->ymin + 0.5f * BLI_rcti_size_y(rect);
+ 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);
- /* XXX exception */
- asp = ((float)BLI_rcti_size_x(rect)) / ((float)BLI_rcti_size_y(rect));
- if (asp > 1.2f && asp < 2.6f)
- centx = rect->xmax - 0.4f * (float)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;
@@ -588,7 +586,7 @@ static void widget_menu_trias(uiWidgetTrias *tria, rcti *rect)
tria->index = menu_tria_face;
}
-static void widget_check_trias(uiWidgetTrias *tria, rcti *rect)
+static void widget_check_trias(uiWidgetTrias *tria, const rcti *rect)
{
float centx, centy, size;
int a;
@@ -651,8 +649,8 @@ static void widget_verts_to_quad_strip_open(uiWidgetBase *wtb, const int totvert
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->inner_v[a][0];
- quad_strip[a * 2 + 1][1] = wtb->inner_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;
}
}
@@ -769,7 +767,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
const unsigned char tcol[4] = {wcol->outline[0],
wcol->outline[1],
wcol->outline[2],
- UCHAR_MAX / WIDGET_AA_JITTER};
+ wcol->outline[3] / WIDGET_AA_JITTER};
widget_verts_to_quad_strip(wtb, wtb->totvert, quad_strip);
@@ -833,7 +831,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
#define PREVIEW_PAD 4
-static void widget_draw_preview(BIFIconID icon, float UNUSED(alpha), rcti *rect)
+static void widget_draw_preview(BIFIconID icon, float UNUSED(alpha), const rcti *rect)
{
int w, h, size;
@@ -861,9 +859,9 @@ static int ui_but_draw_menu_icon(uiBut *but)
/* icons have been standardized... and this call draws in untransformed coordinates */
-static void widget_draw_icon(uiBut *but, BIFIconID icon, float alpha, rcti *rect)
+static void widget_draw_icon(uiBut *but, BIFIconID icon, float alpha, const rcti *rect)
{
- int xs = 0, ys = 0;
+ float xs = 0.0f, ys = 0.0f;
float aspect, height;
if (but->flag & UI_ICON_PREVIEW) {
@@ -874,21 +872,9 @@ static void widget_draw_icon(uiBut *but, BIFIconID icon, float alpha, rcti *rect
/* this icon doesn't need draw... */
if (icon == ICON_BLANK1 && (but->flag & UI_ICON_SUBMENU) == 0) return;
- /* we need aspect from block, for menus... these buttons are scaled in uiPositionBlock() */
- aspect = but->block->aspect;
- if (aspect != but->aspect) {
- /* prevent scaling up icon in pupmenu */
- if (aspect < 1.0f) {
- height = UI_DPI_ICON_SIZE;
- aspect = 1.0f;
-
- }
- else
- height = UI_DPI_ICON_SIZE / aspect;
- }
- else
- height = UI_DPI_ICON_SIZE;
-
+ aspect = but->block->aspect / UI_DPI_FAC;
+ height = ICON_DEFAULT_HEIGHT / aspect;
+
/* calculate blend color */
if (ELEM4(but->type, TOG, ROW, TOGN, LISTROW)) {
if (but->flag & UI_SELECT) {}
@@ -902,32 +888,40 @@ static void widget_draw_icon(uiBut *but, BIFIconID icon, float alpha, rcti *rect
glEnable(GL_BLEND);
if (icon && icon != ICON_BLANK1) {
+ float ofs = 1.0f / aspect;
+
if (but->flag & UI_ICON_LEFT) {
if (but->type == BUT_TOGDUAL) {
if (but->drawstr[0]) {
- xs = rect->xmin - 1;
+ xs = rect->xmin - ofs;
}
else {
- xs = (rect->xmin + rect->xmax - height) / 2;
+ xs = (rect->xmin + rect->xmax - height) / 2.0f;
}
}
else if (but->block->flag & UI_BLOCK_LOOP) {
- if (but->type == SEARCH_MENU)
- xs = rect->xmin + 4;
+ if (ELEM(but->type, SEARCH_MENU, SEARCH_MENU_UNLINK))
+ xs = rect->xmin + 4.0f * ofs;
else
- xs = rect->xmin + 1;
+ xs = rect->xmin + ofs;
}
else if ((but->type == ICONROW) || (but->type == ICONTEXTROW)) {
- xs = rect->xmin + 3;
+ xs = rect->xmin + 3.0f * ofs;
}
else {
- xs = rect->xmin + 4;
+ xs = rect->xmin + 4.0f * ofs;
}
- ys = (rect->ymin + rect->ymax - height) / 2;
+ ys = (rect->ymin + rect->ymax - height) / 2.0f;
}
else {
- xs = (rect->xmin + rect->xmax - height) / 2;
- ys = (rect->ymin + rect->ymax - height) / 2;
+ xs = (rect->xmin + rect->xmax - height) / 2.0f;
+ ys = (rect->ymin + rect->ymax - height) / 2.0f;
+ }
+
+ /* force positions to integers, for zoom levels near 1. draws icons crisp. */
+ if (aspect > 0.95f && aspect < 1.05f) {
+ xs = (int)(xs + 0.1f);
+ ys = (int)(ys + 0.1f);
}
/* to indicate draggable */
@@ -940,8 +934,8 @@ static void widget_draw_icon(uiBut *but, BIFIconID icon, float alpha, rcti *rect
}
if (ui_but_draw_menu_icon(but)) {
- xs = rect->xmax - UI_DPI_ICON_SIZE - 1;
- ys = (rect->ymin + rect->ymax - height) / 2;
+ xs = rect->xmax - UI_DPI_ICON_SIZE - aspect;
+ ys = (rect->ymin + rect->ymax - height) / 2.0f;
UI_icon_draw_aspect(xs, ys, ICON_RIGHTARROW_THIN, aspect, alpha);
}
@@ -971,7 +965,7 @@ static void ui_text_clip_give_next_off(uiBut *but)
* \note Sets but->ofs to make sure text is correctly visible.
* \note Clips right in some cases, this function could be cleaned up.
*/
-static void ui_text_clip_left(uiFontStyle *fstyle, uiBut *but, rcti *rect)
+static void ui_text_clip_left(uiFontStyle *fstyle, uiBut *but, const rcti *rect)
{
int border = (but->flag & UI_BUT_ALIGN_RIGHT) ? 8 : 10;
int okwidth = BLI_rcti_size_x(rect) - border;
@@ -1000,7 +994,7 @@ static void ui_text_clip_left(uiFontStyle *fstyle, uiBut *but, rcti *rect)
/**
* Cut off the text, taking into account the cursor location (text display while editing).
*/
-static void ui_text_clip_cursor(uiFontStyle *fstyle, uiBut *but, rcti *rect)
+static void ui_text_clip_cursor(uiFontStyle *fstyle, uiBut *but, const rcti *rect)
{
int border = (but->flag & UI_BUT_ALIGN_RIGHT) ? 8 : 10;
int okwidth = BLI_rcti_size_x(rect) - border;
@@ -1064,7 +1058,7 @@ static void ui_text_clip_cursor(uiFontStyle *fstyle, uiBut *but, rcti *rect)
*
* \note deals with ': ' especially for number buttons
*/
-static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, rcti *rect)
+static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, const rcti *rect)
{
int border = (but->flag & UI_BUT_ALIGN_RIGHT) ? 8 : 10;
int okwidth = BLI_rcti_size_x(rect) - border;
@@ -1153,6 +1147,8 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
if (but->editstr || (but->flag & UI_TEXT_LEFT))
fstyle->align = UI_STYLE_TEXT_LEFT;
+ else if (but->flag & UI_TEXT_RIGHT)
+ fstyle->align = UI_STYLE_TEXT_RIGHT;
else
fstyle->align = UI_STYLE_TEXT_CENTER;
@@ -1190,7 +1186,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
but->drawstr[selend_tmp] = ch;
- glColor3ubv((unsigned char *)wcol->item);
+ glColor4ubv((unsigned char *)wcol->item);
glRects(rect->xmin + selsta_draw, rect->ymin + 2, rect->xmin + selwidth_draw, rect->ymax - 2);
}
}
@@ -1230,7 +1226,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
}
}
- glColor3ubv((unsigned char *)wcol->text);
+ glColor4ubv((unsigned char *)wcol->text);
uiStyleFontDrawExt(fstyle, rect, but->drawstr + but->ofs, &font_xofs, &font_yofs);
@@ -1278,6 +1274,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
/* draws text and icons for buttons */
static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect)
{
+ float alpha = (float)wcol->text[3] / 255.0f;
char password_str[UI_MAX_DRAW_STR];
if (but == NULL)
@@ -1292,13 +1289,15 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
else if (ELEM4(but->type, NUM, NUMABS, NUMSLI, SLI)) {
ui_text_clip_right_label(fstyle, but, rect);
}
- else if (ELEM(but->type, TEX, SEARCH_MENU)) {
+ else if (ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
ui_text_clip_left(fstyle, but, rect);
}
else if ((but->block->flag & UI_BLOCK_LOOP) && (but->type == BUT)) {
ui_text_clip_left(fstyle, but, rect);
}
- else but->ofs = 0;
+ else {
+ but->ofs = 0;
+ }
/* check for button text label */
if (but->type == ICONTEXTROW) {
@@ -1315,12 +1314,12 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
dualset = UI_BITBUT_TEST(*(((int *)but->poin) + 1), but->bitnr);
}
- widget_draw_icon(but, ICON_DOT, dualset ? 1.0f : 0.25f, rect);
+ widget_draw_icon(but, ICON_DOT, dualset ? alpha : 0.25f, rect);
}
else if (but->type == MENU && (but->flag & UI_BUT_NODE_LINK)) {
int tmp = rect->xmin;
rect->xmin = rect->xmax - BLI_rcti_size_y(rect) - 1;
- widget_draw_icon(but, ICON_LAYER_USED, 1.0f, rect);
+ widget_draw_icon(but, ICON_LAYER_USED, alpha, rect);
rect->xmin = tmp;
}
@@ -1328,15 +1327,32 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
* and offset the text label to accommodate it */
if (but->flag & UI_HAS_ICON) {
- widget_draw_icon(but, but->icon + but->iconadd, 1.0f, rect);
-
- rect->xmin += (int)((float)UI_icon_get_width(but->icon + but->iconadd) * UI_DPI_ICON_FAC);
+ widget_draw_icon(but, but->icon + but->iconadd, alpha, rect);
+
+ /* icons default draw 0.8f x height */
+ rect->xmin += (int)(0.8f * BLI_rcti_size_y(rect));
- if (but->editstr || (but->flag & UI_TEXT_LEFT))
- rect->xmin += 5;
+ if (but->editstr || (but->flag & UI_TEXT_LEFT)) {
+ rect->xmin += (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
+ }
+ else if ((but->flag & UI_TEXT_RIGHT)) {
+ rect->xmax -= (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
+ }
+ }
+ else if ((but->flag & UI_TEXT_LEFT)) {
+ rect->xmin += (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
+ }
+ else if ((but->flag & UI_TEXT_RIGHT)) {
+ rect->xmax -= (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
+ }
+
+ /* unlink icon for this button type */
+ if (but->type == SEARCH_MENU_UNLINK && but->drawstr[0]) {
+ rcti temp = *rect;
+
+ temp.xmin = temp.xmax - BLI_rcti_size_y(rect);
+ widget_draw_icon(but, ICON_X, alpha, &temp);
}
- else if ((but->flag & UI_TEXT_LEFT))
- rect->xmin += 5;
/* always draw text for textbutton cursor */
widget_draw_text(fstyle, wcol, but, rect);
@@ -1372,12 +1388,12 @@ static struct uiWidgetStateColors wcol_state_colors = {
};
/* uiWidgetColors
- * float outline[3];
- * float inner[4];
- * float inner_sel[4];
- * float item[3];
- * float text[3];
- * float text_sel[3];
+ * 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;
@@ -1792,11 +1808,19 @@ static void widget_state_menu_item(uiWidgetType *wt, int state)
{
wt->wcol = *(wt->wcol_theme);
- if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
- wt->wcol.text[0] = 0.5f * (wt->wcol.text[0] + wt->wcol.text_sel[0]);
- wt->wcol.text[1] = 0.5f * (wt->wcol.text[1] + wt->wcol.text_sel[1]);
- wt->wcol.text[2] = 0.5f * (wt->wcol.text[2] + wt->wcol.text_sel[2]);
+ /* active and disabled (not so common) */
+ if ((state & UI_BUT_DISABLED) && (state & UI_ACTIVE)) {
+ widget_state_blend(wt->wcol.text, wt->wcol.text_sel, 0.5f);
+ /* draw the backdrop at low alpha, helps navigating with keys
+ * when disabled items are active */
+ copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
+ wt->wcol.inner[3] = 64;
+ }
+ /* regular disabled */
+ else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
+ widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f);
}
+ /* regular active */
else if (state & UI_ACTIVE) {
copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
@@ -1807,38 +1831,45 @@ static void widget_state_menu_item(uiWidgetType *wt, int state)
/* ************ menu backdrop ************************* */
/* outside of rect, rad to left/bottom/right */
-static void widget_softshadow(rcti *rect, int roundboxalign, float radin, float radout)
+static void widget_softshadow(const rcti *rect, int roundboxalign, const float radin)
{
+ bTheme *btheme = UI_GetTheme();
uiWidgetBase wtb;
rcti rect1 = *rect;
- float alpha, alphastep;
+ float alphastep;
int step, totvert;
- float quad_strip[WIDGET_SIZE_MAX * 2][2];
+ float quad_strip[WIDGET_SIZE_MAX * 2 + 2][2];
+ const float radout = UI_ThemeMenuShadowWidth();
+
+ /* disabled shadow */
+ if (radout == 0.0f)
+ return;
/* prevent tooltips to not show round shadow */
- if (2.0f * radout > 0.2f * BLI_rcti_size_y(&rect1))
+ if (radout > 0.2f * BLI_rcti_size_y(&rect1))
rect1.ymax -= 0.2f * BLI_rcti_size_y(&rect1);
else
- rect1.ymax -= 2.0f * radout;
+ rect1.ymax -= radout;
/* inner part */
totvert = round_box_shadow_edges(wtb.inner_v, &rect1, radin, roundboxalign & (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT), 0.0f);
- /* inverse linear shadow alpha */
- alpha = 0.15;
- alphastep = 0.67;
+ /* we draw a number of increasing size alpha quad strips */
+ alphastep = 3.0f * btheme->tui.menu_shadow_fac / radout;
glEnableClientState(GL_VERTEX_ARRAY);
- for (step = 1; step <= radout; step++, alpha *= alphastep) {
+ for (step = 1; step <= (int)radout; step++) {
+ float expfac = sqrt(step / radout);
+
round_box_shadow_edges(wtb.outer_v, &rect1, radin, UI_CNR_ALL, (float)step);
- glColor4f(0.0f, 0.0f, 0.0f, alpha);
+ glColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac));
- widget_verts_to_quad_strip_open(&wtb, totvert, quad_strip);
+ widget_verts_to_quad_strip(&wtb, totvert, quad_strip);
glVertexPointer(2, GL_FLOAT, 0, quad_strip);
- glDrawArrays(GL_QUAD_STRIP, 0, totvert * 2);
+ glDrawArrays(GL_QUAD_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);
@@ -1858,17 +1889,17 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir
}
else if (direction == UI_DOWN) {
roundboxalign = (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT);
- rect->ymin -= 4.0;
+ rect->ymin -= 0.1f * U.widget_unit;
}
else if (direction == UI_TOP) {
roundboxalign = UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT;
- rect->ymax += 4.0;
+ rect->ymax += 0.1f * U.widget_unit;
}
glEnable(GL_BLEND);
- widget_softshadow(rect, roundboxalign, 5.0f, 8.0f);
+ widget_softshadow(rect, roundboxalign, 0.25f * U.widget_unit);
- round_box_edges(&wtb, roundboxalign, rect, 5.0f);
+ round_box_edges(&wtb, roundboxalign, rect, 0.25f * U.widget_unit);
wtb.emboss = 0;
widgetbase_draw(&wtb, wcol);
@@ -1883,12 +1914,12 @@ static void ui_hsv_cursor(float x, float y)
glTranslatef(x, y, 0.0f);
glColor3f(1.0f, 1.0f, 1.0f);
- glutil_draw_filled_arc(0.0f, M_PI * 2.0, 3.0f, 8);
+ glutil_draw_filled_arc(0.0f, M_PI * 2.0, 3.0f * U.pixelsize, 8);
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
glColor3f(0.0f, 0.0f, 0.0f);
- glutil_draw_lined_arc(0.0f, M_PI * 2.0, 3.0f, 12);
+ glutil_draw_lined_arc(0.0f, M_PI * 2.0, 3.0f * U.pixelsize, 12);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
@@ -1912,7 +1943,7 @@ void ui_hsvcircle_vals_from_pos(float *val_rad, float *val_dist, const rcti *rec
static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
{
- const int tot = 32;
+ const int tot = 64;
const float radstep = 2.0f * (float)M_PI / (float)tot;
const float centx = BLI_rcti_cent_x_fl(rect);
@@ -2000,7 +2031,7 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
/* ************ custom buttons, old stuff ************** */
/* draws in resolution of 20x4 colors */
-void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const float alpha)
+void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, const float alpha)
{
const float color_step = (type == UI_GRAD_H) ? 0.02f : 0.05f;
int a;
@@ -2139,16 +2170,24 @@ void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const floa
-static void ui_draw_but_HSVCUBE(uiBut *but, rcti *rect)
+static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect)
{
float rgb[3];
float x = 0.0f, y = 0.0f;
float *hsv = ui_block_hsv_get(but->block);
float hsv_n[3];
+ int color_profile = but->block->color_profile;
+
+ if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
+ color_profile = FALSE;
copy_v3_v3(hsv_n, hsv);
ui_get_but_vectorf(but, rgb);
+
+ if (color_profile && (int)but->a1 != UI_GRAD_SV)
+ ui_block_to_display_space_v3(but->block, rgb);
+
rgb_to_hsv_compat_v(rgb, hsv_n);
ui_draw_gradient(rect, hsv_n, but->a1, 1.0f);
@@ -2182,10 +2221,10 @@ static void ui_draw_but_HSVCUBE(uiBut *but, rcti *rect)
}
/* vertical 'value' slider, using new widget code */
-static void ui_draw_but_HSV_v(uiBut *but, rcti *rect)
+static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
{
uiWidgetBase wtb;
- float rad = 0.5f * BLI_rcti_size_x(rect);
+ const float rad = 0.5f * BLI_rcti_size_x(rect);
float x, y;
float rgb[3], hsv[3], v, range;
int color_profile = but->block->color_profile;
@@ -2230,7 +2269,7 @@ static void ui_draw_but_HSV_v(uiBut *but, rcti *rect)
/* ************ separator, for menus etc ***************** */
-static void ui_draw_separator(rcti *rect, uiWidgetColors *wcol)
+static void ui_draw_separator(const rcti *rect, uiWidgetColors *wcol)
{
int y = rect->ymin + BLI_rcti_size_y(rect) / 2 - 1;
unsigned char col[4];
@@ -2251,7 +2290,7 @@ static void ui_draw_separator(rcti *rect, uiWidgetColors *wcol)
static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
uiWidgetBase wtb;
- float rad = 0.5f * BLI_rcti_size_y(rect);
+ const float rad = 0.5f * BLI_rcti_size_y(rect);
float textofs = rad * 0.75f;
if (state & UI_SELECT)
@@ -2275,7 +2314,7 @@ static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int round
rect->xmax -= textofs;
}
-int ui_link_bezier_points(rcti *rect, float coord_array[][2], int resol)
+int ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol)
{
float dist, vec[4][2];
@@ -2299,7 +2338,7 @@ int ui_link_bezier_points(rcti *rect, float coord_array[][2], int resol)
}
#define LINK_RESOL 24
-void ui_draw_link_bezier(rcti *rect)
+void ui_draw_link_bezier(const rcti *rect)
{
float coord_array[LINK_RESOL + 1][2];
@@ -2312,7 +2351,7 @@ void ui_draw_link_bezier(rcti *rect)
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, coord_array);
- glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL);
+ glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL + 1);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_BLEND);
@@ -2322,18 +2361,18 @@ void ui_draw_link_bezier(rcti *rect)
}
/* function in use for buttons and for view2d sliders */
-void uiWidgetScrollDraw(uiWidgetColors *wcol, rcti *rect, rcti *slider, int state)
+void uiWidgetScrollDraw(uiWidgetColors *wcol, const rcti *rect, const rcti *slider, int state)
{
uiWidgetBase wtb;
- float rad;
int horizontal;
+ float rad;
short outline = 0;
widget_init(&wtb);
/* determine horizontal/vertical */
horizontal = (BLI_rcti_size_x(rect) > BLI_rcti_size_y(rect));
-
+
if (horizontal)
rad = 0.5f * BLI_rcti_size_y(rect);
else
@@ -2540,14 +2579,15 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s
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 + 1.0f);
+ 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;
widgetbase_draw(&wtb1, wcol);
/* right part of slider, interpolate roundness */
rect1.xmax = rect1.xmin + fac + offs;
- rect1.xmin += floor(offs - 1.0f);
+ rect1.xmin += floor(offs - U.pixelsize);
+
if (rect1.xmax + offs > rect->xmax)
offs *= (rect1.xmax + offs - rect->xmax) / offs;
else
@@ -2577,12 +2617,14 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s
static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
uiWidgetBase wtb;
- float col[4];
+ float rad, col[4];
int color_profile = but->block->color_profile;
col[3] = 1.0f;
if (but->rnaprop) {
+ BLI_assert(but->rnaindex == -1);
+
if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
color_profile = FALSE;
@@ -2594,7 +2636,8 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
widget_init(&wtb);
/* half rounded */
- round_box_edges(&wtb, roundboxalign, rect, 5.0f);
+ rad = 0.25f * U.widget_unit;
+ round_box_edges(&wtb, roundboxalign, rect, rad);
ui_get_but_vectorf(but, col);
@@ -2608,7 +2651,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
rect->ymin += SWATCH_KEYED_BORDER;
rect->ymax -= SWATCH_KEYED_BORDER;
- round_box_edges(&wtb, roundboxalign, rect, 5.0f);
+ round_box_edges(&wtb, roundboxalign, rect, rad);
}
if (color_profile)
@@ -2632,12 +2675,14 @@ static void widget_icon_has_anim(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti
{
if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) {
uiWidgetBase wtb;
-
+ float rad;
+
widget_init(&wtb);
wtb.outline = 0;
/* rounded */
- round_box_edges(&wtb, UI_CNR_ALL, rect, 10.0f);
+ rad = 0.5f * BLI_rcti_size_y(rect);
+ round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
widgetbase_draw(&wtb, wcol);
}
}
@@ -2646,6 +2691,7 @@ static void widget_icon_has_anim(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti
static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
{
uiWidgetBase wtb;
+ float rad;
if (state & UI_SELECT)
SWAP(short, wcol->shadetop, wcol->shadedown);
@@ -2653,7 +2699,8 @@ static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roun
widget_init(&wtb);
/* half rounded */
- round_box_edges(&wtb, roundboxalign, rect, 4.0f);
+ rad = 0.2f * U.widget_unit;
+ round_box_edges(&wtb, roundboxalign, rect, rad);
widgetbase_draw(&wtb, wcol);
@@ -2663,11 +2710,13 @@ static void widget_textbut(uiWidgetColors *wcol, rcti *rect, int state, int roun
static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
{
uiWidgetBase wtb;
+ float rad;
widget_init(&wtb);
/* half rounded */
- round_box_edges(&wtb, roundboxalign, rect, 4.0f);
+ rad = 0.2f * U.widget_unit;
+ round_box_edges(&wtb, roundboxalign, rect, rad);
/* decoration */
widget_menu_trias(&wtb.tria1, rect);
@@ -2681,11 +2730,13 @@ static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
static void widget_menuiconbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
{
uiWidgetBase wtb;
+ float rad;
widget_init(&wtb);
/* half rounded */
- round_box_edges(&wtb, roundboxalign, rect, 4.0f);
+ rad = 0.2f * U.widget_unit;
+ round_box_edges(&wtb, roundboxalign, rect, rad);
/* decoration */
widgetbase_draw(&wtb, wcol);
@@ -2696,11 +2747,13 @@ static void widget_menunodebut(uiWidgetColors *wcol, rcti *rect, int UNUSED(stat
/* silly node link button hacks */
uiWidgetBase wtb;
uiWidgetColors wcol_backup = *wcol;
+ float rad;
widget_init(&wtb);
/* half rounded */
- round_box_edges(&wtb, roundboxalign, rect, 4.0f);
+ rad = 0.2f * U.widget_unit;
+ round_box_edges(&wtb, roundboxalign, rect, rad);
wcol->inner[0] += 15;
wcol->inner[1] += 15;
@@ -2718,7 +2771,7 @@ static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int
{
if (state & UI_ACTIVE) {
uiWidgetBase wtb;
- float rad = 0.25f * BLI_rcti_size_y(rect); /* 4.0f */
+ const float rad = 0.2f * U.widget_unit;
widget_init(&wtb);
@@ -2745,12 +2798,14 @@ static void widget_menu_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(sta
static void widget_list_itembut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
{
uiWidgetBase wtb;
+ float rad;
widget_init(&wtb);
/* rounded, but no outline */
wtb.outline = 0;
- round_box_edges(&wtb, UI_CNR_ALL, rect, 4.0f);
+ rad = 0.2f * U.widget_unit;
+ round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
widgetbase_draw(&wtb, wcol);
}
@@ -2759,6 +2814,7 @@ static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UN
{
uiWidgetBase wtb;
rcti recttemp = *rect;
+ float rad;
int delta;
widget_init(&wtb);
@@ -2774,7 +2830,8 @@ static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UN
recttemp.ymax -= delta;
/* half rounded */
- round_box_edges(&wtb, UI_CNR_ALL, &recttemp, 4.0f);
+ rad = 0.2f * U.widget_unit;
+ round_box_edges(&wtb, UI_CNR_ALL, &recttemp, rad);
/* decoration */
if (state & UI_SELECT) {
@@ -2791,11 +2848,13 @@ static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UN
static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
{
uiWidgetBase wtb;
+ float rad;
widget_init(&wtb);
/* half rounded */
- round_box_edges(&wtb, roundboxalign, rect, 4.0f);
+ rad = 0.2f * U.widget_unit;
+ round_box_edges(&wtb, roundboxalign, rect, rad);
widgetbase_draw(&wtb, wcol);
@@ -2804,6 +2863,7 @@ static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
{
uiWidgetBase wtb;
+ float rad;
char old_col[3];
widget_init(&wtb);
@@ -2818,27 +2878,25 @@ static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(
}
/* half rounded */
- round_box_edges(&wtb, roundboxalign, rect, 4.0f);
+ rad = 0.2f * U.widget_unit;
+ round_box_edges(&wtb, roundboxalign, rect, rad);
widgetbase_draw(&wtb, wcol);
-
- /* store the box bg as gl clearcolor, to retrieve later when drawing semi-transparent rects
- * over the top to indicate disabled buttons */
- /* XXX, this doesnt work right since the color applies to buttons outside the box too. */
- glClearColor(wcol->inner[0] / 255.0, wcol->inner[1] / 255.0, wcol->inner[2] / 255.0, 1.0);
-
+
copy_v3_v3_char(wcol->inner, old_col);
}
static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
{
uiWidgetBase wtb;
+ float rad;
widget_init(&wtb);
/* half rounded */
- round_box_edges(&wtb, roundboxalign, rect, 4.0f);
-
+ rad = 0.2f * U.widget_unit;
+ round_box_edges(&wtb, roundboxalign, rect, rad);
+
widgetbase_draw(&wtb, wcol);
}
@@ -2846,7 +2904,7 @@ static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int
static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
{
uiWidgetBase wtb;
- float rad = 5.0f; /* 0.5f * BLI_rcti_size_y(rect); */
+ const float rad = 0.25f * U.widget_unit;
widget_init(&wtb);
@@ -2859,6 +2917,7 @@ static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect)
{
uiWidgetBase wtb;
+ const float rad = 0.25f * U.widget_unit;
unsigned char col[4];
/* state copy! */
@@ -2874,36 +2933,18 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *
UI_GetThemeColor3ubv(TH_BACK, col);
glColor3ubv(col);
- round_box__edges(&wtb, UI_CNR_ALL, rect, 0.0f, 4.0);
+ round_box__edges(&wtb, UI_CNR_ALL, rect, 0.0f, rad);
widgetbase_outline(&wtb);
}
/* outline */
- round_box_edges(&wtb, UI_CNR_ALL, rect, 5.0f);
+ round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
wtb.outline = 1;
wtb.inner = 0;
widgetbase_draw(&wtb, &wt->wcol);
}
-
-static void widget_disabled(rcti *rect)
-{
- float col[4];
-
- glEnable(GL_BLEND);
-
- /* can't use theme TH_BACK or TH_PANEL... undefined */
- glGetFloatv(GL_COLOR_CLEAR_VALUE, col);
- glColor4f(col[0], col[1], col[2], 0.5f);
-
- /* need -1 and +1 to make it work right for aligned buttons,
- * but problem may be somewhere else? */
- glRectf(rect->xmin - 1, rect->ymin - 1, rect->xmax, rect->ymax + 1);
-
- glDisable(GL_BLEND);
-}
-
static uiWidgetType *widget_type(uiWidgetTypeEnum type)
{
bTheme *btheme = UI_GetTheme();
@@ -3068,9 +3109,9 @@ static int widget_roundbox_set(uiBut *but, rcti *rect)
/* ui_block_position has this correction too, keep in sync */
if (but->flag & UI_BUT_ALIGN_TOP)
- rect->ymax += 1;
+ rect->ymax += U.pixelsize;
if (but->flag & UI_BUT_ALIGN_LEFT)
- rect->xmin -= 1;
+ rect->xmin -= U.pixelsize;
switch (but->flag & UI_BUT_ALIGN) {
case UI_BUT_ALIGN_TOP:
@@ -3116,6 +3157,23 @@ static int widget_roundbox_set(uiBut *but, rcti *rect)
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)
{
@@ -3166,7 +3224,6 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
break;
case NUMSLI:
- case HSVSLI:
wt = widget_type(UI_WTYPE_SLIDER);
break;
@@ -3181,7 +3238,8 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
case TEX:
wt = widget_type(UI_WTYPE_NAME);
break;
-
+
+ case SEARCH_MENU_UNLINK:
case SEARCH_MENU:
wt = widget_type(UI_WTYPE_NAME);
if (but->block->flag & UI_BLOCK_LOOP)
@@ -3311,30 +3369,47 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
ui_draw_but_TRACKPREVIEW(ar, but, &tui->wcol_regular, rect);
break;
+ case NODESOCKET:
+ ui_draw_but_NODESOCKET(ar, but, &tui->wcol_regular, rect);
+ break;
+
default:
wt = widget_type(UI_WTYPE_REGULAR);
}
}
if (wt) {
- rcti disablerect = *rect; /* rect gets clipped smaller for text */
+ //rcti disablerect = *rect; /* rect gets clipped smaller for text */
int roundboxalign, state;
+ bool disabled = FALSE;
roundboxalign = widget_roundbox_set(but, rect);
state = but->flag;
if (but->editstr) state |= UI_TEXTINPUT;
+ if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE))
+ if (but->dt != UI_EMBOSSP)
+ 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);
+ if (disabled)
+ glDisable(GL_BLEND);
- if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE))
- if (but->dt != UI_EMBOSSP)
- widget_disabled(&disablerect);
+// if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE))
+// if (but->dt != UI_EMBOSSP)
+// widget_disabled(&disablerect);
}
}
@@ -3381,7 +3456,7 @@ void ui_draw_search_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
uiWidgetType *wt = widget_type(UI_WTYPE_BOX);
glEnable(GL_BLEND);
- widget_softshadow(rect, UI_CNR_ALL, 5.0f, 8.0f);
+ widget_softshadow(rect, UI_CNR_ALL, 0.25f * U.widget_unit);
glDisable(GL_BLEND);
wt->state(wt, 0);
@@ -3400,7 +3475,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM);
rcti _rect = *rect;
char *cpoin;
-
+
wt->state(wt, state);
wt->draw(&wt->wcol, rect, 0, 0);
@@ -3408,7 +3483,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
fstyle->align = UI_STYLE_TEXT_LEFT;
/* text location offset */
- rect->xmin += 5;
+ rect->xmin += 0.25f * UI_UNIT_X;
if (iconid) rect->xmin += UI_DPI_ICON_SIZE;
/* cut string in 2 parts? */
@@ -3418,7 +3493,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
rect->xmax -= BLF_width(fstyle->uifont_id, cpoin + 1) + 10;
}
- glColor3ubv((unsigned char *)wt->wcol.text);
+ glColor4ubv((unsigned char *)wt->wcol.text);
uiStyleFontDraw(fstyle, rect, name);
/* part text right aligned */
@@ -3433,10 +3508,16 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
*rect = _rect;
if (iconid) {
- int xs = rect->xmin + 4;
- int ys = 1 + (rect->ymin + rect->ymax - UI_DPI_ICON_SIZE) / 2;
+ float height, aspect;
+ int xs = rect->xmin + 0.2f * UI_UNIT_X;
+ int ys = rect->ymin + 0.1f * BLI_rcti_size_y(rect);
+
+ /* icons are 80% of height of button (16 pixels inside 20 height) */
+ height = 0.8f * BLI_rcti_size_y(rect);
+ aspect = ICON_DEFAULT_HEIGHT / height;
+
glEnable(GL_BLEND);
- UI_icon_draw_aspect(xs, ys, iconid, 1.2f, 0.5f); /* XXX scale weak get from fstyle? */
+ UI_icon_draw_aspect(xs, ys, iconid, aspect, 1.0f); /* XXX scale weak get from fstyle? */
glDisable(GL_BLEND);
}
}
@@ -3479,9 +3560,9 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int
glDisable(GL_BLEND);
if (state == UI_ACTIVE)
- glColor3ubv((unsigned char *)wt->wcol.text);
+ glColor4ubv((unsigned char *)wt->wcol.text);
else
- glColor3ubv((unsigned char *)wt->wcol.text_sel);
+ glColor4ubv((unsigned char *)wt->wcol.text_sel);
uiStyleFontDraw(fstyle, &trect, name);
}
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index fa5d5806bb8..288b8b43e82 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -86,7 +86,7 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
static char error[4] = {240, 0, 240, 255};
static char alert[4] = {240, 60, 60, 255};
static char headerdesel[4] = {0, 0, 0, 255};
-
+ static char setting = 0;
const char *cp = error;
if (btheme) {
@@ -170,6 +170,16 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
else
cp = ts->button;
break;
+ case TH_LOW_GRAD:
+ cp = ts->gradients.gradient;
+ break;
+ case TH_HIGH_GRAD:
+ cp = ts->gradients.high_gradient;
+ break;
+ case TH_SHOW_BACK_GRAD:
+ cp = &setting;
+ setting = ts->gradients.show_grad;
+ break;
case TH_TEXT:
if (theme_regionid == RGN_TYPE_WINDOW)
cp = ts->text;
@@ -216,13 +226,19 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case TH_HEADER_TEXT_HI:
cp = ts->header_text_hi; break;
- case TH_PANEL:
- cp = ts->panel; break;
- case TH_PANEL_TEXT:
- cp = ts->panel_text; break;
- case TH_PANEL_TEXT_HI:
- cp = ts->panel_text_hi; break;
-
+ case TH_PANEL_HEADER:
+ cp = ts->panelcolors.header; break;
+ case TH_PANEL_BACK:
+ cp = ts->panelcolors.back; break;
+ case TH_PANEL_SHOW_HEADER:
+ cp = &setting;
+ setting = ts->panelcolors.show_header;
+ break;
+ case TH_PANEL_SHOW_BACK:
+ cp = &setting;
+ setting = ts->panelcolors.show_back;
+ break;
+
case TH_BUTBACK:
cp = ts->button; break;
case TH_BUTBACK_TEXT:
@@ -263,6 +279,8 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->vertex; break;
case TH_VERTEX_SELECT:
cp = ts->vertex_select; break;
+ case TH_VERTEX_UNREFERENCED:
+ cp = ts->vertex_unreferenced; break;
case TH_VERTEX_SIZE:
cp = &ts->vertex_size; break;
case TH_OUTLINE_WIDTH:
@@ -343,6 +361,10 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->handle_sel_vect; break;
case TH_HANDLE_SEL_ALIGN:
cp = ts->handle_sel_align; break;
+ case TH_FREESTYLE_EDGE_MARK:
+ cp = ts->freestyle_edge_mark; break;
+ case TH_FREESTYLE_FACE_MARK:
+ cp = ts->freestyle_face_mark; break;
case TH_SYNTAX_B:
cp = ts->syntaxb; break;
@@ -352,8 +374,14 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->syntaxc; break;
case TH_SYNTAX_L:
cp = ts->syntaxl; break;
+ case TH_SYNTAX_D:
+ cp = ts->syntaxd; break;
+ case TH_SYNTAX_R:
+ cp = ts->syntaxr; break;
case TH_SYNTAX_N:
cp = ts->syntaxn; break;
+ case TH_SYNTAX_S:
+ cp = ts->syntaxs; break;
case TH_NODE:
cp = ts->syntaxl; break;
@@ -365,8 +393,14 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->syntaxv; break;
case TH_NODE_GROUP:
cp = ts->syntaxc; break;
+ case TH_NODE_INTERFACE:
+ cp = ts->console_output; break;
case TH_NODE_FRAME:
cp = ts->movie; break;
+ case TH_NODE_MATTE:
+ cp = ts->syntaxs; break;
+ case TH_NODE_DISTORT:
+ cp = ts->syntaxd; break;
case TH_NODE_CURVING:
cp = &ts->noodle_curving; break;
@@ -401,6 +435,8 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->console_error; break;
case TH_CONSOLE_CURSOR:
cp = ts->console_cursor; break;
+ case TH_CONSOLE_SELECT:
+ cp = ts->console_select; break;
case TH_HANDLE_VERTEX:
cp = ts->handle_vertex;
@@ -411,7 +447,6 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case TH_HANDLE_VERTEX_SIZE:
cp = &ts->handle_vertex_size;
break;
-
case TH_DOPESHEET_CHANNELOB:
cp = ts->ds_channel;
break;
@@ -603,9 +638,9 @@ static void ui_theme_init_new_do(ThemeSpace *ts)
rgba_char_args_test_set(ts->header_title, 0, 0, 0, 255);
rgba_char_args_test_set(ts->header_text_hi, 255, 255, 255, 255);
- rgba_char_args_test_set(ts->panel_text, 0, 0, 0, 255);
- rgba_char_args_test_set(ts->panel_title, 0, 0, 0, 255);
- rgba_char_args_test_set(ts->panel_text_hi, 255, 255, 255, 255);
+// rgba_char_args_test_set(ts->panel_text, 0, 0, 0, 255);
+// rgba_char_args_test_set(ts->panel_title, 0, 0, 0, 255);
+// rgba_char_args_test_set(ts->panel_text_hi, 255, 255, 255, 255);
rgba_char_args_test_set(ts->button, 145, 145, 145, 245);
rgba_char_args_test_set(ts->button_title, 0, 0, 0, 255);
@@ -664,6 +699,7 @@ void ui_theme_init_default(void)
ui_widget_color_init(&btheme->tui);
btheme->tui.iconfile[0] = 0;
+ btheme->tui.panel.show_back = FALSE;
btheme->tui.panel.show_header = FALSE;
rgba_char_args_set(btheme->tui.panel.header, 0, 0, 0, 25);
@@ -671,6 +707,9 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tui.yaxis, 0, 220, 0, 255);
rgba_char_args_set(btheme->tui.zaxis, 0, 0, 220, 255);
+ btheme->tui.menu_shadow_fac = 0.5f;
+ btheme->tui.menu_shadow_width = 12;
+
/* Bone Color Sets */
ui_theme_init_boneColorSets(btheme);
@@ -678,13 +717,17 @@ void ui_theme_init_default(void)
ui_theme_init_new(btheme);
/* space view3d */
+ btheme->tv3d.panelcolors.show_back = FALSE;
+ btheme->tv3d.panelcolors.show_header = FALSE;
+ rgba_char_args_set_fl(btheme->tv3d.panelcolors.back, 0.45, 0.45, 0.45, 0.5);
+ rgba_char_args_set_fl(btheme->tv3d.panelcolors.header, 0, 0, 0, 0.01);
rgba_char_args_set_fl(btheme->tv3d.back, 0.225, 0.225, 0.225, 1.0);
rgba_char_args_set(btheme->tv3d.text, 0, 0, 0, 255);
rgba_char_args_set(btheme->tv3d.text_hi, 255, 255, 255, 255);
rgba_char_args_set_fl(btheme->tv3d.header, 0.45, 0.45, 0.45, 1.0);
- rgba_char_args_set_fl(btheme->tv3d.button, 0.45, 0.45, 0.45, 1.0);
- rgba_char_args_set(btheme->tv3d.panel, 165, 165, 165, 127);
+ rgba_char_args_set_fl(btheme->tv3d.button, 0.45, 0.45, 0.45, 0.5);
+// rgba_char_args_set(btheme->tv3d.panel, 165, 165, 165, 127);
rgba_char_args_set(btheme->tv3d.shade1, 160, 160, 160, 100);
rgba_char_args_set(btheme->tv3d.shade2, 0x7f, 0x70, 0x70, 100);
@@ -702,6 +745,7 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tv3d.transform, 0xff, 0xff, 0xff, 255);
rgba_char_args_set(btheme->tv3d.vertex, 0, 0, 0, 255);
rgba_char_args_set(btheme->tv3d.vertex_select, 255, 133, 0, 255);
+ rgba_char_args_set(btheme->tv3d.vertex_unreferenced, 0, 0, 0, 255);
btheme->tv3d.vertex_size = 3;
btheme->tv3d.outline_width = 1;
rgba_char_args_set(btheme->tv3d.edge, 0x0, 0x0, 0x0, 255);
@@ -722,6 +766,8 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tv3d.button_text_hi, 255, 255, 255, 255);
rgba_char_args_set(btheme->tv3d.button_title, 0, 0, 0, 255);
rgba_char_args_set(btheme->tv3d.title, 0, 0, 0, 255);
+ rgba_char_args_set(btheme->tv3d.freestyle_edge_mark, 0x7f, 0xff, 0x7f, 255);
+ rgba_char_args_set(btheme->tv3d.freestyle_face_mark, 0x7f, 0xff, 0x7f, 51);
btheme->tv3d.facedot_size = 4;
@@ -757,20 +803,23 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tv3d.camera_path, 0x00, 0x00, 0x00, 255);
rgba_char_args_set(btheme->tv3d.skin_root, 180, 77, 77, 255);
-
+ rgba_char_args_set(btheme->tv3d.gradients.gradient, 0, 0, 0, 0);
+ rgba_char_args_set(btheme->tv3d.gradients.high_gradient, 58, 58, 58, 255);
+ btheme->tv3d.gradients.show_grad = FALSE;
+
/* space buttons */
/* to have something initialized */
btheme->tbuts = btheme->tv3d;
rgba_char_args_set_fl(btheme->tbuts.back, 0.45, 0.45, 0.45, 1.0);
- rgba_char_args_set(btheme->tbuts.panel, 0x82, 0x82, 0x82, 255);
+// rgba_char_args_set(btheme->tbuts.panel, 0x82, 0x82, 0x82, 255);
/* graph editor */
btheme->tipo = btheme->tv3d;
rgba_char_args_set_fl(btheme->tipo.back, 0.42, 0.42, 0.42, 1.0);
rgba_char_args_set_fl(btheme->tipo.list, 0.4, 0.4, 0.4, 1.0);
rgba_char_args_set(btheme->tipo.grid, 94, 94, 94, 255);
- rgba_char_args_set(btheme->tipo.panel, 255, 255, 255, 150);
+// rgba_char_args_set(btheme->tipo.panel, 255, 255, 255, 150);
rgba_char_args_set(btheme->tipo.shade1, 150, 150, 150, 100); /* scrollbars */
rgba_char_args_set(btheme->tipo.shade2, 0x70, 0x70, 0x70, 100);
rgba_char_args_set(btheme->tipo.vertex, 0, 0, 0, 255);
@@ -816,11 +865,11 @@ void ui_theme_init_default(void)
/* to have something initialized */
btheme->tfile = btheme->tv3d;
rgba_char_args_set_fl(btheme->tfile.back, 0.3, 0.3, 0.3, 1);
- rgba_char_args_set_fl(btheme->tfile.panel, 0.3, 0.3, 0.3, 1);
+// rgba_char_args_set_fl(btheme->tfile.panel, 0.3, 0.3, 0.3, 1);
rgba_char_args_set_fl(btheme->tfile.list, 0.4, 0.4, 0.4, 1);
rgba_char_args_set(btheme->tfile.text, 250, 250, 250, 255);
rgba_char_args_set(btheme->tfile.text_hi, 15, 15, 15, 255);
- rgba_char_args_set(btheme->tfile.panel, 145, 145, 145, 255); /* bookmark/ui regions */
+// rgba_char_args_set(btheme->tfile.panel, 145, 145, 145, 255); /* bookmark/ui regions */
rgba_char_args_set(btheme->tfile.active, 130, 130, 130, 255); /* selected files */
rgba_char_args_set(btheme->tfile.hilite, 255, 140, 25, 255); /* selected files */
@@ -860,6 +909,7 @@ void ui_theme_init_default(void)
rgba_char_args_set_fl(btheme->tima.preview_stitch_vert, 0.0, 0.0, 1.0, 0.2);
rgba_char_args_set_fl(btheme->tima.preview_stitch_stitchable, 0.0, 1.0, 0.0, 1.0);
rgba_char_args_set_fl(btheme->tima.preview_stitch_unstitchable, 1.0, 0.0, 0.0, 1.0);
+ rgba_char_args_set_fl(btheme->tima.preview_stitch_active, 0.886, 0.824, 0.765, 0.140);
/* space text */
btheme->text = btheme->tv3d;
@@ -870,10 +920,13 @@ void ui_theme_init_default(void)
/* syntax highlighting */
rgba_char_args_set(btheme->text.syntaxn, 0, 0, 200, 255); /* Numbers Blue*/
- rgba_char_args_set(btheme->text.syntaxl, 100, 0, 0, 255); /* Strings red */
- rgba_char_args_set(btheme->text.syntaxc, 0, 100, 50, 255); /* Comments greenish */
- rgba_char_args_set(btheme->text.syntaxv, 95, 95, 0, 255); /* Special */
- rgba_char_args_set(btheme->text.syntaxb, 128, 0, 80, 255); /* Builtin, red-purple */
+ rgba_char_args_set(btheme->text.syntaxl, 100, 0, 0, 255); /* Strings Red */
+ rgba_char_args_set(btheme->text.syntaxc, 0, 100, 50, 255); /* Comments Greenish */
+ rgba_char_args_set(btheme->text.syntaxv, 95, 95, 0, 255); /* Special Yellow*/
+ 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) */
/* space oops */
btheme->toops = btheme->tv3d;
@@ -898,6 +951,7 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tconsole.console_info, 0, 170, 0, 255);
rgba_char_args_set(btheme->tconsole.console_error, 220, 96, 96, 255);
rgba_char_args_set(btheme->tconsole.console_cursor, 220, 96, 96, 255);
+ rgba_char_args_set(btheme->tconsole.console_select, 255, 255, 255, 48);
/* space time */
btheme->ttime = btheme->tv3d;
@@ -905,7 +959,7 @@ 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 */
- /* space node, re-uses syntax color storage */
+ /* space node, re-uses syntax and console color storage */
btheme->tnode = btheme->tv3d;
rgba_char_args_set(btheme->tnode.edge_select, 255, 255, 255, 255); /* wire selected */
rgba_char_args_set(btheme->tnode.syntaxl, 155, 155, 155, 160); /* TH_NODE, backdrop */
@@ -914,6 +968,7 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tnode.syntaxv, 104, 106, 117, 255); /* generator */
rgba_char_args_set(btheme->tnode.syntaxc, 105, 117, 110, 255); /* group */
rgba_char_args_set(btheme->tnode.movie, 155, 155, 155, 160); /* frame */
+ rgba_char_args_set(btheme->tnode.console_output, 190, 190, 80, 255); /* group input/output */
btheme->tnode.noodle_curving = 5;
/* space logic */
@@ -1252,6 +1307,12 @@ void UI_ThemeClearColor(int colorid)
glClearColor(col[0], col[1], col[2], 0.0);
}
+int UI_ThemeMenuShadowWidth(void)
+{
+ bTheme *btheme = UI_GetTheme();
+ return (int)(btheme->tui.menu_shadow_width * UI_DPI_FAC);
+}
+
void UI_make_axis_color(const unsigned char src_col[3], unsigned char dst_col[3], const char axis)
{
unsigned char col[3];
@@ -1280,7 +1341,6 @@ void UI_make_axis_color(const unsigned char src_col[3], unsigned char dst_col[3]
void init_userdef_do_versions(void)
{
Main *bmain = G.main;
-// countall();
/* the UserDef struct is not corrected with do_versions() .... ugh! */
if (U.wheellinescroll == 0) U.wheellinescroll = 3;
@@ -1319,7 +1379,7 @@ void init_userdef_do_versions(void)
/* signal for derivedmesh to use colorband */
/* 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);
+ vDM_ColorBand_store((U.flag & USER_CUSTOM_RANGE) ? (&U.coba_weight) : NULL, UI_GetTheme()->tv3d.vertex_unreferenced);
if (bmain->versionfile <= 191) {
strcpy(U.sounddir, "/");
@@ -1484,7 +1544,7 @@ void init_userdef_do_versions(void)
rgba_char_args_set(btheme->tv3d.editmesh_active, 255, 255, 255, 128);
}
if (U.coba_weight.tot == 0)
- init_colorband(&U.coba_weight, 1);
+ init_colorband(&U.coba_weight, true);
}
if ((bmain->versionfile < 245) || (bmain->versionfile == 245 && bmain->subversionfile < 11)) {
bTheme *btheme;
@@ -1966,6 +2026,19 @@ void init_userdef_do_versions(void)
}
}
+ /* Freestyle color settings */
+ {
+ bTheme *btheme;
+
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ /* check for alpha == 0 is safe, then color was never set */
+ if (btheme->tv3d.freestyle_edge_mark[3] == 0) {
+ rgba_char_args_set(btheme->tv3d.freestyle_edge_mark, 0x7f, 0xff, 0x7f, 255);
+ rgba_char_args_set(btheme->tv3d.freestyle_face_mark, 0x7f, 0xff, 0x7f, 51);
+ }
+ }
+ }
+
/* GL Texture Garbage Collection (variable abused above!) */
if (U.textimeout == 0) {
U.texcollectrate = 60;
@@ -1990,7 +2063,7 @@ void init_userdef_do_versions(void)
if (U.dragthreshold == 0)
U.dragthreshold = 5;
if (U.widget_unit == 0)
- U.widget_unit = (U.dpi * 20 + 36) / 72;
+ U.widget_unit = 20;
if (U.anisotropic_filter <= 0)
U.anisotropic_filter = 1;
@@ -2009,6 +2082,108 @@ void init_userdef_do_versions(void)
if (U.tweak_threshold == 0)
U.tweak_threshold = 10;
+ if (bmain->versionfile < 265 || (bmain->versionfile == 265 && bmain->subversionfile < 1)) {
+ bTheme *btheme;
+
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ /* note: the toggle operator for transparent backdrops limits to these spacetypes */
+ if (btheme->tnode.button[3] == 255) {
+ btheme->tv3d.button[3] = 128;
+ btheme->tnode.button[3] = 128;
+ btheme->tima.button[3] = 128;
+ btheme->tseq.button[3] = 128;
+ btheme->tclip.button[3] = 128;
+ }
+ }
+ }
+
+ /* panel header/backdrop supported locally per editor now */
+ if (bmain->versionfile < 265 || (bmain->versionfile == 265 && bmain->subversionfile < 2)) {
+ bTheme *btheme;
+
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+
+ /* new color, panel backdrop. Not used anywhere yet, until you enable it */
+ copy_v3_v3_char(btheme->tui.panel.back, btheme->tbuts.button);
+ btheme->tui.panel.back[3] = 128;
+
+ btheme->tbuts.panelcolors = btheme->tui.panel;
+ btheme->tv3d.panelcolors = btheme->tui.panel;
+ btheme->tfile.panelcolors = btheme->tui.panel;
+ btheme->tipo.panelcolors = btheme->tui.panel;
+ btheme->tinfo.panelcolors = btheme->tui.panel;
+ btheme->tact.panelcolors = btheme->tui.panel;
+ btheme->tnla.panelcolors = btheme->tui.panel;
+ btheme->tseq.panelcolors = btheme->tui.panel;
+ btheme->tima.panelcolors = btheme->tui.panel;
+ btheme->text.panelcolors = btheme->tui.panel;
+ btheme->toops.panelcolors = btheme->tui.panel;
+ btheme->ttime.panelcolors = btheme->tui.panel;
+ btheme->tnode.panelcolors = btheme->tui.panel;
+ btheme->tlogic.panelcolors = btheme->tui.panel;
+ btheme->tuserpref.panelcolors = btheme->tui.panel;
+ btheme->tconsole.panelcolors = btheme->tui.panel;
+ btheme->tclip.panelcolors = btheme->tui.panel;
+ }
+ }
+
+ /* NOTE!! from now on use U.versionfile and U.subversionfile */
+ if (U.versionfile < 266) {
+ bTheme *btheme;
+
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ /* rna definition limits fac to 0.01 */
+ if (btheme->tui.menu_shadow_fac == 0.0f) {
+ btheme->tui.menu_shadow_fac = 0.5f;
+ btheme->tui.menu_shadow_width = 12;
+ }
+ }
+ }
+
+ if (U.versionfile < 265 || (U.versionfile == 265 && U.subversionfile < 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) */
+ }
+ }
+
+ if (U.versionfile < 265 || (U.versionfile == 265 && U.subversionfile < 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)) {
+ 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 */
+ rgba_char_args_test_set(btheme->tnode.syntaxd, 116, 151, 151, 255); /* distort nodes */
+ }
+ }
+
+ if (U.versionfile < 265 || (U.versionfile == 265 && U.subversionfile < 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)) {
+ 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.pixelsize == 0.0f)
+ U.pixelsize = 1.0f;
+
/* 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 f1a3f59bc22..a66169d54ae 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -39,6 +39,7 @@
#include "DNA_userdef_types.h"
#include "BLI_blenlib.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -60,6 +61,8 @@
#include "interface_intern.h"
+static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_scrollers);
+
/* *********************************************************************** */
/* XXX still unresolved: scrolls hide/unhide vs region mask handling */
@@ -73,15 +76,15 @@
*/
static int view2d_scroll_mapped(int scroll)
{
- if (scroll & V2D_SCROLL_HORIZONTAL_HIDE)
+ if (scroll & V2D_SCROLL_HORIZONTAL_FULLR)
scroll &= ~(V2D_SCROLL_HORIZONTAL);
- if (scroll & V2D_SCROLL_VERTICAL_HIDE)
+ if (scroll & V2D_SCROLL_VERTICAL_FULLR)
scroll &= ~(V2D_SCROLL_VERTICAL);
return scroll;
}
/* called each time cur changes, to dynamically update masks */
-static void view2d_masks(View2D *v2d)
+static void view2d_masks(View2D *v2d, int check_scrollers)
{
int scroll;
@@ -90,19 +93,26 @@ static void view2d_masks(View2D *v2d)
v2d->mask.xmax = v2d->winx - 1; /* -1 yes! masks are pixels */
v2d->mask.ymax = v2d->winy - 1;
-#if 0
- /* XXX see above */
- v2d->scroll &= ~(V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_VERTICAL_HIDE);
- /* check size if: */
- if (v2d->scroll & V2D_SCROLL_HORIZONTAL)
- if (!(v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL))
- if (BLI_rctf_size_x(&v2d->tot) <= BLI_rcti_size_x(&v2d->cur))
- v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
- if (v2d->scroll & V2D_SCROLL_VERTICAL)
- if (!(v2d->scroll & V2D_SCROLL_SCALE_VERTICAL))
- if (BLI_rctf_size_y(&v2d->tot) <= BLI_rctf_size_y(&v2d->cur))
- v2d->scroll |= V2D_SCROLL_VERTICAL_HIDE;
-#endif
+ if (check_scrollers) {
+ /* check size if hiding flag is set: */
+ if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) {
+ if (!(v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL)) {
+ if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur))
+ v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR;
+ else
+ v2d->scroll |= V2D_SCROLL_HORIZONTAL_FULLR;
+ }
+ }
+ if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) {
+ if (!(v2d->scroll & V2D_SCROLL_SCALE_VERTICAL)) {
+ if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur))
+ v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR;
+ else
+ v2d->scroll |= V2D_SCROLL_VERTICAL_FULLR;
+ }
+ }
+ }
+
scroll = view2d_scroll_mapped(v2d->scroll);
/* scrollers shrink mask area, but should be based off regionsize
@@ -126,8 +136,8 @@ static void view2d_masks(View2D *v2d)
}
/* horizontal scroller */
- if (scroll & (V2D_SCROLL_BOTTOM | V2D_SCROLL_BOTTOM_O)) {
- /* on bottom edge of region (V2D_SCROLL_BOTTOM_O is outliner, the other is for standard) */
+ if (scroll & (V2D_SCROLL_BOTTOM)) {
+ /* on bottom edge of region */
v2d->hor = v2d->mask;
v2d->hor.ymax = V2D_SCROLL_HEIGHT;
v2d->mask.ymin = v2d->hor.ymax + 1;
@@ -142,8 +152,8 @@ static void view2d_masks(View2D *v2d)
/* adjust vertical scroller if there's a horizontal scroller, to leave corner free */
if (scroll & V2D_SCROLL_VERTICAL) {
/* just set y min/max for vertical scroller to y min/max of mask as appropriate */
- if (scroll & (V2D_SCROLL_BOTTOM | V2D_SCROLL_BOTTOM_O)) {
- /* on bottom edge of region (V2D_SCROLL_BOTTOM_O is outliner, the other is for standard) */
+ if (scroll & (V2D_SCROLL_BOTTOM)) {
+ /* on bottom edge of region */
v2d->vert.ymin = v2d->mask.ymin;
}
else if (scroll & V2D_SCROLL_TOP) {
@@ -152,7 +162,6 @@ static void view2d_masks(View2D *v2d)
}
}
}
-
}
/* Refresh and Validation */
@@ -165,163 +174,173 @@ static void view2d_masks(View2D *v2d)
*/
void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
{
- short tot_changed = 0, init = 0;
+ short tot_changed = 0, do_init;
uiStyle *style = UI_GetStyle();
- /* initialize data if there is a need for such */
- if ((v2d->flag & V2D_IS_INITIALISED) == 0) {
- /* set initialized flag so that View2D doesn't get reinitialised next time again */
- v2d->flag |= V2D_IS_INITIALISED;
-
- init = 1;
+ do_init = (v2d->flag & V2D_IS_INITIALISED) == 0;
- /* see eView2D_CommonViewTypes in UI_view2d.h for available view presets */
- switch (type) {
- /* 'standard view' - optimum setup for 'standard' view behavior,
- * that should be used new views as basis for their
- * own unique View2D settings, which should be used instead of this in most cases...
+ /* see eView2D_CommonViewTypes in UI_view2d.h for available view presets */
+ switch (type) {
+ /* 'standard view' - optimum setup for 'standard' view behavior,
+ * that should be used new views as basis for their
+ * own unique View2D settings, which should be used instead of this in most cases...
+ */
+ case V2D_COMMONVIEW_STANDARD:
+ {
+ /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
+ v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM);
+ v2d->minzoom = 0.01f;
+ v2d->maxzoom = 1000.0f;
+
+ /* tot rect and cur should be same size, and aligned using 'standard' OpenGL coordinates for now
+ * - region can resize 'tot' later to fit other data
+ * - keeptot is only within bounds, as strict locking is not that critical
+ * - view is aligned for (0,0) -> (winx-1, winy-1) setup
*/
- case V2D_COMMONVIEW_STANDARD:
- {
- /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
- v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM);
- v2d->minzoom = 0.01f;
- v2d->maxzoom = 1000.0f;
-
- /* tot rect and cur should be same size, and aligned using 'standard' OpenGL coordinates for now
- * - region can resize 'tot' later to fit other data
- * - keeptot is only within bounds, as strict locking is not that critical
- * - view is aligned for (0,0) -> (winx-1, winy-1) setup
- */
- v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
- v2d->keeptot = V2D_KEEPTOT_BOUNDS;
-
+ v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
+ v2d->keeptot = V2D_KEEPTOT_BOUNDS;
+
+ if (do_init) {
v2d->tot.xmin = v2d->tot.ymin = 0.0f;
v2d->tot.xmax = (float)(winx - 1);
v2d->tot.ymax = (float)(winy - 1);
v2d->cur = v2d->tot;
-
- /* scrollers - should we have these by default? */
- /* XXX for now, we don't override this, or set it either! */
}
- break;
+ /* scrollers - should we have these by default? */
+ /* XXX for now, we don't override this, or set it either! */
+ }
+ break;
+
+ /* 'list/channel view' - zoom, aspect ratio, and alignment restrictions are set here */
+ case V2D_COMMONVIEW_LIST:
+ {
+ /* zoom + aspect ratio are locked */
+ v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+ v2d->minzoom = v2d->maxzoom = 1.0f;
- /* 'list/channel view' - zoom, aspect ratio, and alignment restrictions are set here */
- case V2D_COMMONVIEW_LIST:
- {
- /* zoom + aspect ratio are locked */
- v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
- v2d->minzoom = v2d->maxzoom = 1.0f;
-
- /* tot rect has strictly regulated placement, and must only occur in +/- quadrant */
- v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
- v2d->keeptot = V2D_KEEPTOT_STRICT;
- tot_changed = 1;
-
- /* scroller settings are currently not set here... that is left for regions... */
- }
- break;
-
- /* 'stack view' - practically the same as list/channel view, except is located in the pos y half instead.
- * zoom, aspect ratio, and alignment restrictions are set here */
- case V2D_COMMONVIEW_STACK:
- {
- /* zoom + aspect ratio are locked */
- v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
- v2d->minzoom = v2d->maxzoom = 1.0f;
-
- /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
- v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
- v2d->keeptot = V2D_KEEPTOT_STRICT;
- tot_changed = 1;
-
- /* scroller settings are currently not set here... that is left for regions... */
- }
- break;
+ /* tot rect has strictly regulated placement, and must only occur in +/- quadrant */
+ v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
+ v2d->keeptot = V2D_KEEPTOT_STRICT;
+ tot_changed = do_init;
+
+ /* scroller settings are currently not set here... that is left for regions... */
+ }
+ break;
+
+ /* 'stack view' - practically the same as list/channel view, except is located in the pos y half instead.
+ * zoom, aspect ratio, and alignment restrictions are set here */
+ case V2D_COMMONVIEW_STACK:
+ {
+ /* zoom + aspect ratio are locked */
+ v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+ v2d->minzoom = v2d->maxzoom = 1.0f;
+
+ /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
+ v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
+ v2d->keeptot = V2D_KEEPTOT_STRICT;
+ tot_changed = do_init;
+
+ /* scroller settings are currently not set here... that is left for regions... */
+ }
+ break;
+
+ /* 'header' regions - zoom, aspect ratio, alignment, and panning restrictions are set here */
+ case V2D_COMMONVIEW_HEADER:
+ {
+ /* zoom + aspect ratio are locked */
+ v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+ v2d->minzoom = v2d->maxzoom = 1.0f;
+
+ if (do_init) {
+ v2d->tot.xmin = 0.0f;
+ v2d->tot.xmax = winx;
+ v2d->tot.ymin = 0.0f;
+ v2d->tot.ymax = winy;
+ v2d->cur = v2d->tot;
- /* 'header' regions - zoom, aspect ratio, alignment, and panning restrictions are set here */
- case V2D_COMMONVIEW_HEADER:
- {
- /* zoom + aspect ratio are locked */
- v2d->keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
- v2d->minzoom = v2d->maxzoom = 1.0f;
v2d->min[0] = v2d->max[0] = (float)(winx - 1);
v2d->min[1] = v2d->max[1] = (float)(winy - 1);
-
- /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
- v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
- v2d->keeptot = V2D_KEEPTOT_STRICT;
- tot_changed = 1;
-
- /* panning in y-axis is prohibited */
- v2d->keepofs = V2D_LOCKOFS_Y;
-
- /* absolutely no scrollers allowed */
- v2d->scroll = 0;
-
}
- break;
+ /* tot rect has strictly regulated placement, and must only occur in +/+ quadrant */
+ v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_NEG_Y);
+ v2d->keeptot = V2D_KEEPTOT_STRICT;
+ tot_changed = do_init;
+
+ /* panning in y-axis is prohibited */
+ v2d->keepofs = V2D_LOCKOFS_Y;
- /* panels view, with horizontal/vertical align */
- case V2D_COMMONVIEW_PANELS_UI:
- {
+ /* absolutely no scrollers allowed */
+ v2d->scroll = 0;
+
+ }
+ break;
+
+ /* panels view, with horizontal/vertical align */
+ case V2D_COMMONVIEW_PANELS_UI:
+ {
+
+ /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
+ v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM | V2D_KEEPZOOM);
+ v2d->minzoom = 0.5f;
+ v2d->maxzoom = 2.0f;
+
+ v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
+ v2d->keeptot = V2D_KEEPTOT_BOUNDS;
+
+ /* note, scroll is being flipped in ED_region_panels() drawing */
+ v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
+ v2d->scroll |= V2D_SCROLL_VERTICAL_HIDE;
+
+ if (do_init) {
float panelzoom = (style) ? style->panelzoom : 1.0f;
+ float scrolw = v2d->scroll & V2D_SCROLL_RIGHT ? V2D_SCROLL_WIDTH : 0.0f;
- /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
- v2d->keepzoom = (V2D_KEEPASPECT | V2D_LIMITZOOM | V2D_KEEPZOOM);
- v2d->minzoom = 0.5f;
- v2d->maxzoom = 2.0f;
- //tot_changed = 1;
-
- v2d->align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
- v2d->keeptot = V2D_KEEPTOT_BOUNDS;
-
- v2d->scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
- v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
- v2d->scroll &= ~V2D_SCROLL_VERTICAL_HIDE;
-
v2d->tot.xmin = 0.0f;
- v2d->tot.xmax = winx;
+ v2d->tot.xmax = winx - scrolw;
v2d->tot.ymax = 0.0f;
v2d->tot.ymin = -winy;
v2d->cur.xmin = 0.0f;
- /* bad workaround for keeping zoom level with scrollers */
- v2d->cur.xmax = (winx - V2D_SCROLL_WIDTH) * panelzoom;
+ v2d->cur.xmax = (winx) * panelzoom - scrolw;
v2d->cur.ymax = 0.0f;
v2d->cur.ymin = (-winy) * panelzoom;
}
- break;
-
- /* other view types are completely defined using their own settings already */
- default:
- /* we don't do anything here, as settings should be fine, but just make sure that rect */
- break;
}
+ break;
+
+ /* other view types are completely defined using their own settings already */
+ default:
+ /* we don't do anything here, as settings should be fine, but just make sure that rect */
+ break;
}
+ /* set initialized flag so that View2D doesn't get reinitialised next time again */
+ v2d->flag |= V2D_IS_INITIALISED;
+
/* store view size */
v2d->winx = winx;
v2d->winy = winy;
- /* set masks */
- view2d_masks(v2d);
+ /* set masks (always do), but leave scroller scheck to totrect_set */
+ view2d_masks(v2d, 0);
/* set 'tot' rect before setting cur? */
- if (tot_changed)
- UI_view2d_totRect_set_resize(v2d, winx, winy, !init);
+ /* XXX confusing stuff here still - I made this function not check scroller hide - that happens in totrect_set */
+ if (tot_changed)
+ UI_view2d_totRect_set_resize(v2d, winx, winy, !do_init);
else
- UI_view2d_curRect_validate_resize(v2d, !init);
+ ui_view2d_curRect_validate_resize(v2d, !do_init, 0);
+
}
/* 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()
-void UI_view2d_curRect_validate_resize(View2D *v2d, int resize)
+static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_scrollers)
{
float totwidth, totheight, curwidth, curheight, width, height;
float winx, winy;
@@ -438,8 +457,12 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize)
if (ABS(winx - v2d->oldwinx) > ABS(winy - v2d->oldwiny)) do_y = FALSE;
else do_x = FALSE;
}
- else if (winRatio > 1.0f) do_x = FALSE;
- else do_x = TRUE;
+ else if (winRatio > 1.0f) {
+ do_x = FALSE;
+ }
+ else {
+ do_x = TRUE;
+ }
}
do_cur = do_x;
/* do_win = do_y; */ /* UNUSED */
@@ -715,12 +738,12 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize)
}
/* set masks */
- view2d_masks(v2d);
+ view2d_masks(v2d, mask_scrollers);
}
void UI_view2d_curRect_validate(View2D *v2d)
{
- UI_view2d_curRect_validate_resize(v2d, 0);
+ ui_view2d_curRect_validate_resize(v2d, 0, 1);
}
/* ------------------ */
@@ -844,7 +867,7 @@ void UI_view2d_curRect_reset(View2D *v2d)
/* Change the size of the maximum viewable area (i.e. 'tot' rect) */
void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, int resize)
{
- int scroll = view2d_scroll_mapped(v2d->scroll);
+// int scroll = view2d_scroll_mapped(v2d->scroll);
/* don't do anything if either value is 0 */
width = abs(width);
@@ -852,10 +875,11 @@ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, int resize
/* hrumf! */
/* XXX: there are work arounds for this in the panel and file browse code. */
- if (scroll & V2D_SCROLL_HORIZONTAL)
- width -= V2D_SCROLL_WIDTH;
- if (scroll & V2D_SCROLL_VERTICAL)
- height -= V2D_SCROLL_HEIGHT;
+ /* round to int, because this is called with width + V2D_SCROLL_WIDTH */
+// if (scroll & V2D_SCROLL_HORIZONTAL)
+// width -= (int)V2D_SCROLL_WIDTH;
+// if (scroll & V2D_SCROLL_VERTICAL)
+// height -= (int)V2D_SCROLL_HEIGHT;
if (ELEM(0, width, height)) {
if (G.debug & G_DEBUG)
@@ -902,12 +926,21 @@ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, int resize
}
/* make sure that 'cur' rect is in a valid state as a result of these changes */
- UI_view2d_curRect_validate_resize(v2d, resize);
+ ui_view2d_curRect_validate_resize(v2d, resize, 1);
+
}
void UI_view2d_totRect_set(View2D *v2d, int width, int height)
{
+ int scroll = view2d_scroll_mapped(v2d->scroll);
+
UI_view2d_totRect_set_resize(v2d, width, height, 0);
+
+ /* solve bad recursion... if scroller state changed, mask is different, so you get different rects */
+ if (scroll != view2d_scroll_mapped(v2d->scroll)) {
+ UI_view2d_totRect_set_resize(v2d, width, height, 0);
+ }
+
}
int UI_view2d_tab_set(View2D *v2d, int tab)
@@ -1001,16 +1034,16 @@ void UI_view2d_view_ortho(View2D *v2d)
/* XXX ton: this flag set by outliner, for icons */
if (v2d->flag & V2D_PIXELOFS_X) {
- curmasked.xmin = floorf(curmasked.xmin) - 0.001f;
- curmasked.xmax = floorf(curmasked.xmax) - 0.001f;
+ curmasked.xmin = floorf(curmasked.xmin) - (0.001f + xofs);
+ curmasked.xmax = floorf(curmasked.xmax) - (0.001f + xofs);
}
if (v2d->flag & V2D_PIXELOFS_Y) {
- curmasked.ymin = floorf(curmasked.ymin) - 0.001f;
- curmasked.ymax = floorf(curmasked.ymax) - 0.001f;
+ curmasked.ymin = floorf(curmasked.ymin) - (0.001f + yofs);
+ curmasked.ymax = floorf(curmasked.ymax) - (0.001f + yofs);
}
/* set matrix on all appropriate axes */
- wmOrtho2(curmasked.xmin - xofs, curmasked.xmax - xofs, curmasked.ymin - yofs, curmasked.ymax - yofs);
+ wmOrtho2(curmasked.xmin, curmasked.xmax, curmasked.ymin, curmasked.ymax);
/* XXX is this necessary? */
glLoadIdentity();
@@ -1150,7 +1183,7 @@ View2DGrid *UI_view2d_grid_calc(Scene *scene, View2D *v2d,
pixels = (float)BLI_rcti_size_x(&v2d->mask);
if (pixels != 0.0f) {
- grid->dx = (U.v2d_min_gridsize * space) / (seconddiv * pixels);
+ grid->dx = (U.v2d_min_gridsize * UI_DPI_FAC * space) / (seconddiv * pixels);
step_to_grid(&grid->dx, &grid->powerx, xunits);
grid->dx *= seconddiv;
}
@@ -1167,7 +1200,7 @@ View2DGrid *UI_view2d_grid_calc(Scene *scene, View2D *v2d,
space = BLI_rctf_size_y(&v2d->cur);
pixels = (float)winy;
- grid->dy = U.v2d_min_gridsize * space / pixels;
+ grid->dy = U.v2d_min_gridsize * UI_DPI_FAC * space / pixels;
step_to_grid(&grid->dy, &grid->powery, yunits);
if (yclamp == V2D_GRID_CLAMP) {
@@ -1212,7 +1245,7 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
vec2[1] = v2d->cur.ymax;
/* minor gridlines */
- step = (BLI_rcti_size_x(&v2d->mask) + 1) / U.v2d_min_gridsize;
+ step = (BLI_rcti_size_x(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC);
UI_ThemeColor(TH_GRID);
for (a = 0; a < step; a++) {
@@ -1246,7 +1279,7 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag)
vec1[0] = grid->startx;
vec2[0] = v2d->cur.xmax;
- step = (BLI_rcti_size_y(&v2d->mask) + 1) / U.v2d_min_gridsize;
+ step = (BLI_rcti_size_y(&v2d->mask) + 1) / (U.v2d_min_gridsize * UI_DPI_FAC);
UI_ThemeColor(TH_GRID);
for (a = 0; a <= step; a++) {
@@ -1335,7 +1368,7 @@ void UI_view2d_constant_grid_draw(View2D *v2d)
}
/* Draw a multi-level grid in given 2d-region */
-void UI_view2d_multi_grid_draw(View2D *v2d, float step, int level_size, int totlevels)
+void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_size, int totlevels)
{
int offset = -10;
float lstep = step;
@@ -1345,7 +1378,7 @@ void UI_view2d_multi_grid_draw(View2D *v2d, float step, int level_size, int totl
int i;
float start;
- UI_ThemeColorShade(TH_BACK, offset);
+ UI_ThemeColorShade(colorid, offset);
i = (v2d->cur.xmin >= 0.0f ? -(int)(-v2d->cur.xmin / lstep) : (int)(v2d->cur.xmin / lstep));
start = i * lstep;
@@ -1369,7 +1402,7 @@ void UI_view2d_multi_grid_draw(View2D *v2d, float step, int level_size, int totl
}
/* X and Y axis */
- UI_ThemeColorShade(TH_BACK, offset - 8);
+ UI_ThemeColorShade(colorid, offset - 8);
glVertex2f(0.0f, v2d->cur.ymin);
glVertex2f(0.0f, v2d->cur.ymax);
glVertex2f(v2d->cur.xmin, 0.0f);
@@ -1427,6 +1460,7 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d,
rcti vert, hor;
float fac1, fac2, totsize, scrollsize;
int scroll = view2d_scroll_mapped(v2d->scroll);
+ int smaller;
/* scrollers is allocated here... */
scrollers = MEM_callocN(sizeof(View2DScrollers), "View2DScrollers");
@@ -1435,19 +1469,20 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d,
hor = v2d->hor;
/* slider rects need to be smaller than region */
- hor.xmin += 4;
- hor.xmax -= 4;
+ smaller = (int)(0.2f * U.widget_unit);
+ hor.xmin += smaller;
+ hor.xmax -= smaller;
if (scroll & V2D_SCROLL_BOTTOM)
- hor.ymin += 4;
+ hor.ymin += smaller;
else
- hor.ymax -= 4;
+ hor.ymax -= smaller;
if (scroll & V2D_SCROLL_LEFT)
- vert.xmin += 4;
+ vert.xmin += smaller;
else
- vert.xmax -= 4;
- vert.ymin += 4;
- vert.ymax -= 4;
+ vert.xmax -= smaller;
+ vert.ymin += smaller;
+ vert.ymax -= smaller;
CLAMP(vert.ymin, vert.ymin, vert.ymax - V2D_SCROLLER_HANDLE_SIZE);
CLAMP(hor.xmin, hor.xmin, hor.xmax - V2D_SCROLLER_HANDLE_SIZE);
@@ -1491,15 +1526,6 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d,
CLAMP(scrollers->hor_min, hor.xmin, hor.xmax - V2D_SCROLLER_HANDLE_SIZE);
}
- /* check whether sliders can disappear due to the full-range being used */
- if (v2d->keeptot) {
- if ((fac1 <= 0.0f) && (fac2 >= 1.0f)) {
- v2d->scroll |= V2D_SCROLL_HORIZONTAL_FULLR;
- scrollers->horfull = 1;
- }
- else
- v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR;
- }
}
/* vertical scrollers */
@@ -1533,15 +1559,6 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d,
CLAMP(scrollers->vert_min, vert.ymin, vert.ymax - V2D_SCROLLER_HANDLE_SIZE);
}
- /* check whether sliders can disappear due to the full-range being used */
- if (v2d->keeptot) {
- if ((fac1 <= 0.0f) && (fac2 >= 1.0f)) {
- v2d->scroll |= V2D_SCROLL_VERTICAL_FULLR;
- scrollers->vertfull = 1;
- }
- else
- v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR;
- }
}
/* grid markings on scrollbars */
@@ -1615,40 +1632,42 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
/* horizontal scrollbar */
if (scroll & V2D_SCROLL_HORIZONTAL) {
- /* only draw scrollbar when it doesn't fill the entire space */
- if (vs->horfull == 0) {
- bTheme *btheme = UI_GetTheme();
- uiWidgetColors wcol = btheme->tui.wcol_scroll;
- rcti slider;
- int state;
-
- slider.xmin = vs->hor_min;
- slider.xmax = vs->hor_max;
- slider.ymin = hor.ymin;
- slider.ymax = hor.ymax;
-
- state = (v2d->scroll_ui & V2D_SCROLL_H_ACTIVE) ? UI_SCROLL_PRESSED : 0;
-
- /* show zoom handles if:
- * - zooming on x-axis is allowed (no scroll otherwise)
- * - slider bubble is large enough (no overdraw confusion)
- * - scale is shown on the scroller
- * (workaround to make sure that button windows don't show these,
- * and only the time-grids with their zoomability can do so)
- */
- if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 &&
- (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) &&
- (BLI_rcti_size_x(&slider) > V2D_SCROLLER_HANDLE_SIZE))
- {
- state |= UI_SCROLL_ARROWS;
- }
-
- UI_ThemeColor(TH_BACK);
+ bTheme *btheme = UI_GetTheme();
+ uiWidgetColors wcol = btheme->tui.wcol_scroll;
+ rcti slider;
+ int state;
+ unsigned char col[4];
+
+ slider.xmin = vs->hor_min;
+ slider.xmax = vs->hor_max;
+ slider.ymin = hor.ymin;
+ slider.ymax = hor.ymax;
+
+ state = (v2d->scroll_ui & V2D_SCROLL_H_ACTIVE) ? UI_SCROLL_PRESSED : 0;
+
+ /* show zoom handles if:
+ * - zooming on x-axis is allowed (no scroll otherwise)
+ * - slider bubble is large enough (no overdraw confusion)
+ * - scale is shown on the scroller
+ * (workaround to make sure that button windows don't show these,
+ * and only the time-grids with their zoomability can do so)
+ */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 &&
+ (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) &&
+ (BLI_rcti_size_x(&slider) > V2D_SCROLLER_HANDLE_SIZE))
+ {
+ state |= UI_SCROLL_ARROWS;
+ }
+
+ /* clean rect behind slider, but not with transparent background */
+ UI_GetThemeColor4ubv(TH_BACK, col);
+ if (col[3] == 255) {
+ glColor3ub(col[0], col[1], col[2]);
glRecti(v2d->hor.xmin, v2d->hor.ymin, v2d->hor.xmax, v2d->hor.ymax);
-
- uiWidgetScrollDraw(&wcol, &hor, &slider, state);
}
+ uiWidgetScrollDraw(&wcol, &hor, &slider, state);
+
/* scale indicators */
if ((scroll & V2D_SCROLL_SCALE_HORIZONTAL) && (vs->grid)) {
View2DGrid *grid = vs->grid;
@@ -1680,12 +1699,12 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
/* draw numbers in the appropriate range */
if (dfac > 0.0f) {
- float h = 2.0f + (float)(hor.ymin);
+ float h = 0.1f * UI_UNIT_Y + (float)(hor.ymin);
- for (; fac < hor.xmax - 10; fac += dfac, val += grid->dx) {
+ for (; fac < hor.xmax - 0.5f * U.widget_unit; fac += dfac, val += grid->dx) {
/* make prints look nicer for scrollers */
- if (fac < hor.xmin + 10)
+ if (fac < hor.xmin + 0.5f * U.widget_unit)
continue;
switch (vs->xunits) {
@@ -1726,40 +1745,42 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
/* vertical scrollbar */
if (scroll & V2D_SCROLL_VERTICAL) {
- /* only draw scrollbar when it doesn't fill the entire space */
- if (vs->vertfull == 0) {
- bTheme *btheme = UI_GetTheme();
- uiWidgetColors wcol = btheme->tui.wcol_scroll;
- rcti slider;
- int state;
-
- slider.xmin = vert.xmin;
- slider.xmax = vert.xmax;
- slider.ymin = vs->vert_min;
- slider.ymax = vs->vert_max;
-
- state = (v2d->scroll_ui & V2D_SCROLL_V_ACTIVE) ? UI_SCROLL_PRESSED : 0;
-
- /* show zoom handles if:
- * - zooming on y-axis is allowed (no scroll otherwise)
- * - slider bubble is large enough (no overdraw confusion)
- * - scale is shown on the scroller
- * (workaround to make sure that button windows don't show these,
- * and only the time-grids with their zoomability can do so)
- */
- if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 &&
- (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) &&
- (BLI_rcti_size_y(&slider) > V2D_SCROLLER_HANDLE_SIZE))
- {
- state |= UI_SCROLL_ARROWS;
- }
-
- UI_ThemeColor(TH_BACK);
+ bTheme *btheme = UI_GetTheme();
+ uiWidgetColors wcol = btheme->tui.wcol_scroll;
+ rcti slider;
+ int state;
+ unsigned char col[4];
+
+ slider.xmin = vert.xmin;
+ slider.xmax = vert.xmax;
+ slider.ymin = vs->vert_min;
+ slider.ymax = vs->vert_max;
+
+ state = (v2d->scroll_ui & V2D_SCROLL_V_ACTIVE) ? UI_SCROLL_PRESSED : 0;
+
+ /* show zoom handles if:
+ * - zooming on y-axis is allowed (no scroll otherwise)
+ * - slider bubble is large enough (no overdraw confusion)
+ * - scale is shown on the scroller
+ * (workaround to make sure that button windows don't show these,
+ * and only the time-grids with their zoomability can do so)
+ */
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 &&
+ (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) &&
+ (BLI_rcti_size_y(&slider) > V2D_SCROLLER_HANDLE_SIZE))
+ {
+ state |= UI_SCROLL_ARROWS;
+ }
+
+ /* clean rect behind slider, but not with transparent background */
+ UI_GetThemeColor4ubv(TH_BACK, col);
+ if (col[3] == 255) {
+ glColor3ub(col[0], col[1], col[2]);
glRecti(v2d->vert.xmin, v2d->vert.ymin, v2d->vert.xmax, v2d->vert.ymax);
-
- uiWidgetScrollDraw(&wcol, &vert, &slider, state);
}
+ uiWidgetScrollDraw(&wcol, &vert, &slider, state);
+
/* scale indiators */
if ((scroll & V2D_SCROLL_SCALE_VERTICAL) && (vs->grid)) {
@@ -1789,7 +1810,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v
/* draw vertical steps */
if (dfac > 0.0f) {
- BLF_rotation_default(90.0f);
+ BLF_rotation_default(M_PI / 2);
BLF_enable_default(BLF_ROTATION);
for (; fac < vert.ymax - 10; fac += dfac, val += grid->dy) {
@@ -2047,6 +2068,29 @@ void UI_view2d_getscale(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_getscale() - 1.0f / x, y */
+void UI_view2d_getscale_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.
+ * Used by node editor to shift view center for each individual node tree.
+ */
+void UI_view2d_getcenter(struct View2D *v2d, float *x, float *y)
+{
+ /* get center */
+ if (x) *x = BLI_rctf_cent_x(&v2d->cur);
+ if (y) *y = BLI_rctf_cent_y(&v2d->cur);
+}
+void UI_view2d_setcenter(struct View2D *v2d, float x, float y)
+{
+ BLI_rctf_recenter(&v2d->cur, x, y);
+
+ /* make sure that 'cur' rect is in a valid state as a result of these changes */
+ UI_view2d_curRect_validate(v2d);
+}
/* Check if mouse is within scrollers
* - Returns appropriate code for match
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 48a1f8bf0f3..e283bd1351a 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -187,7 +187,7 @@ static int view_pan_exec(bContext *C, wmOperator *op)
}
/* set up modal operator and relevant settings */
-static int view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int view_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
wmWindow *window = CTX_wm_window(C);
v2dViewPanData *vpd;
@@ -231,7 +231,7 @@ static int view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
/* handle user input - calculations of mouse-movement need to be done here, not in the apply callback! */
-static int view_pan_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
v2dViewPanData *vpd = op->customdata;
@@ -700,7 +700,7 @@ static int view_zoomin_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int view_zoomin_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int view_zoomin_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
v2dViewZoomData *vzd;
@@ -769,7 +769,7 @@ static int view_zoomout_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int view_zoomout_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int view_zoomout_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
v2dViewZoomData *vzd;
@@ -924,7 +924,7 @@ static int view_zoomdrag_exec(bContext *C, wmOperator *op)
}
/* set up modal operator and relevant settings */
-static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
wmWindow *window = CTX_wm_window(C);
v2dViewZoomData *vzd;
@@ -937,7 +937,7 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event)
vzd = op->customdata;
v2d = vzd->v2d;
- if (event->type == MOUSEZOOM) {
+ if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
float dx, dy, fac;
vzd->lastx = event->prevx;
@@ -946,10 +946,19 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event)
/* As we have only 1D information (magnify value), feed both axes
* with magnify information that is stored in x axis
*/
- fac = 0.01f * (event->x - event->prevx);
+ fac = 0.01f * (event->prevx - event->x);
dx = fac * BLI_rctf_size_x(&v2d->cur) / 10.0f;
+ if (event->type == MOUSEPAN)
+ fac = 0.01f * (event->prevy - event->y);
dy = fac * BLI_rctf_size_y(&v2d->cur) / 10.0f;
+ /* support trackpad zoom to always zoom entirely - the v2d code uses portrait or landscape exceptions */
+ if (v2d->keepzoom & V2D_KEEPASPECT) {
+ if (fabsf(dx) > fabsf(dy))
+ dy = dx;
+ else
+ dx = dy;
+ }
RNA_float_set(op->ptr, "deltax", dx);
RNA_float_set(op->ptr, "deltay", dy);
@@ -996,7 +1005,7 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
/* handle user input - calculations of mouse-movement need to be done here, not in the apply callback! */
-static int view_zoomdrag_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
v2dViewZoomData *vzd = op->customdata;
View2D *v2d = vzd->v2d;
@@ -1015,37 +1024,38 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, wmEvent *event)
/* x-axis transform */
dist = BLI_rcti_size_x(&v2d->mask) / 2.0f;
- dx = 1.0f - (fabsf(vzd->lastx - dist) + 2.0f) / (fabsf(event->x - dist) + 2.0f);
+ dx = 1.0f - (fabsf(vzd->lastx - vzd->ar->winrct.xmin - dist) + 2.0f) / (fabsf(event->mval[0] - dist) + 2.0f);
dx *= 0.5f * BLI_rctf_size_x(&v2d->cur);
/* y-axis transform */
dist = BLI_rcti_size_y(&v2d->mask) / 2.0f;
- dy = 1.0f - (fabsf(vzd->lasty - dist) + 2.0f) / (fabsf(event->y - dist) + 2.0f);
+ dy = 1.0f - (fabsf(vzd->lasty - vzd->ar->winrct.ymin - dist) + 2.0f) / (fabsf(event->mval[1] - dist) + 2.0f);
dy *= 0.5f * BLI_rctf_size_y(&v2d->cur);
}
else {
/* 'continuous' or 'dolly' */
- float fac;
+ float fac, zoomfac = 0.01f;
+
+ /* some view2d's (graph) don't have min/max zoom, or extreme ones */
+ if (v2d->maxzoom > 0.0f)
+ zoomfac = CLAMPIS(0.001f * v2d->maxzoom, 0.001f, 0.01f);
/* x-axis transform */
- fac = 0.01f * (event->x - vzd->lastx);
+ fac = zoomfac * (event->x - vzd->lastx);
dx = fac * BLI_rctf_size_x(&v2d->cur);
/* y-axis transform */
- fac = 0.01f * (event->y - vzd->lasty);
+ fac = zoomfac * (event->y - vzd->lasty);
dy = fac * BLI_rctf_size_y(&v2d->cur);
-#if 0
- /* continuous zoom shouldn't move that fast... */
- if (U.viewzoom == USER_ZOOM_CONT) { // XXX store this setting as RNA prop?
- double time = PIL_check_seconds_timer();
- float time_step = (float)(time - vzd->timer_lastdraw);
-
- dx /= (0.1f / time_step);
- dy /= (0.1f / time_step);
-
- vzd->timer_lastdraw = time;
- }
-#endif
+
+ }
+
+ /* support zoom to always zoom entirely - the v2d code uses portrait or landscape exceptions */
+ if (v2d->keepzoom & V2D_KEEPASPECT) {
+ if (fabsf(dx) > fabsf(dy))
+ dy = dx;
+ else
+ dx = dy;
}
/* set transform amount, and add current deltas to stored total delta (for redo) */
@@ -1107,7 +1117,7 @@ static void VIEW2D_OT_zoom(wmOperatorType *ot)
ot->poll = view_zoom_poll;
/* operator is repeatable */
- // ot->flag = OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
/* rna - must keep these in sync with the other operators */
RNA_def_float(ot->srna, "deltax", 0, -FLT_MAX, FLT_MAX, "Delta X", "", -FLT_MAX, FLT_MAX);
@@ -1318,7 +1328,7 @@ void UI_view2d_smooth_view(bContext *C, ARegion *ar,
}
/* only meant for timer usage */
-static int view2d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int view2d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
View2D *v2d = &ar->v2d;
@@ -1478,7 +1488,7 @@ static short mouse_in_scroller_handle(int mouse, int sc_min, int sc_max, int sh_
}
/* initialize customdata for scroller manipulation operator */
-static void scroller_activate_init(bContext *C, wmOperator *op, wmEvent *event, short in_scroller)
+static void scroller_activate_init(bContext *C, wmOperator *op, const wmEvent *event, short in_scroller)
{
v2dScrollerMove *vsm;
View2DScrollers *scrollers;
@@ -1627,7 +1637,7 @@ static void scroller_activate_apply(bContext *C, wmOperator *op)
}
/* 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, wmEvent *event)
+static int scroller_activate_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
v2dScrollerMove *vsm = op->customdata;
@@ -1697,7 +1707,7 @@ static int scroller_activate_modal(bContext *C, wmOperator *op, wmEvent *event)
/* a click (or click drag in progress) should have occurred, so check if it happened in scrollbar */
-static int scroller_activate_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
View2D *v2d = &ar->v2d;
@@ -1755,8 +1765,8 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
/* zone is also inappropriate if scroller is not visible... */
- if (((vsm->scroller == 'h') && (v2d->scroll & (V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_HORIZONTAL_FULLR))) ||
- ((vsm->scroller == 'v') && (v2d->scroll & (V2D_SCROLL_VERTICAL_HIDE | V2D_SCROLL_VERTICAL_FULLR))) )
+ if (((vsm->scroller == 'h') && (v2d->scroll & (V2D_SCROLL_HORIZONTAL_FULLR))) ||
+ ((vsm->scroller == 'v') && (v2d->scroll & (V2D_SCROLL_VERTICAL_FULLR))) )
{
/* free customdata initialized */
scroller_activate_exit(C, op);
@@ -1914,6 +1924,7 @@ void UI_view2d_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", WHEELINMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_out", PADMINUS, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MOUSEPAN, 0, KM_CTRL, 0);
WM_keymap_verify_item(keymap, "VIEW2D_OT_smoothview", TIMER1, KM_ANY, KM_ANY, 0);
@@ -1962,6 +1973,7 @@ void UI_view2d_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MOUSEZOOM, 0, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MOUSEPAN, 0, KM_CTRL, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_out", PADMINUS, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "VIEW2D_OT_reset", HOMEKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/io/CMakeLists.txt b/source/blender/editors/io/CMakeLists.txt
index 7db23041c88..d4ae5b8b29b 100644
--- a/source/blender/editors/io/CMakeLists.txt
+++ b/source/blender/editors/io/CMakeLists.txt
@@ -47,4 +47,8 @@ if(WITH_OPENCOLLADA)
add_definitions(-DWITH_COLLADA)
endif()
+if(WITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
+endif()
+
blender_add_lib(bf_editor_io "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/io/SConscript b/source/blender/editors/io/SConscript
index d012576637c..b7449ccad79 100644
--- a/source/blender/editors/io/SConscript
+++ b/source/blender/editors/io/SConscript
@@ -1,4 +1,29 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
Import ('env')
@@ -11,4 +36,7 @@ incs += '../../makesdna ../../makesrna ../../windowmanager ../../collada'
if env['WITH_BF_COLLADA']:
defs += ['WITH_COLLADA']
+if env['WITH_BF_INTERNATIONAL']:
+ defs += ['WITH_INTERNATIONAL']
+
env.BlenderLib ( 'bf_editor_io', sources, Split(incs), defines=defs, libtype=['core','player'], priority=[330,210] )
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index ba93206e63a..a1bb7a8ae88 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -56,7 +56,7 @@
#include "io_collada.h"
-static int wm_collada_export_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int wm_collada_export_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
char filepath[FILE_MAX];
@@ -84,6 +84,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
int selected;
int include_children;
int include_armatures;
+ int include_shapekeys;
int deform_bones_only;
int include_uv_textures;
@@ -91,8 +92,10 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
int use_texture_copies;
int active_uv_only;
+ int triangulate;
int use_object_instantiation;
int sort_by_name;
+ int export_transformation_type;
int second_life;
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
@@ -109,19 +112,22 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
selected = RNA_boolean_get(op->ptr, "selected");
include_children = RNA_boolean_get(op->ptr, "include_children");
include_armatures = RNA_boolean_get(op->ptr, "include_armatures");
+ include_shapekeys = RNA_boolean_get(op->ptr, "include_shapekeys");
deform_bones_only = RNA_boolean_get(op->ptr, "deform_bones_only");
include_uv_textures = RNA_boolean_get(op->ptr, "include_uv_textures");
- include_material_textures= RNA_boolean_get(op->ptr, "include_material_textures");
+ include_material_textures = RNA_boolean_get(op->ptr, "include_material_textures");
use_texture_copies = RNA_boolean_get(op->ptr, "use_texture_copies");
active_uv_only = RNA_boolean_get(op->ptr, "active_uv_only");
- use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation");
- sort_by_name = RNA_boolean_get(op->ptr, "sort_by_name");
- second_life = RNA_boolean_get(op->ptr, "second_life");
+ triangulate = RNA_boolean_get(op->ptr, "triangulate");
+ use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation");
+ sort_by_name = RNA_boolean_get(op->ptr, "sort_by_name");
+ export_transformation_type = RNA_enum_get(op->ptr, "export_transformation_type_selection");
+ second_life = RNA_boolean_get(op->ptr, "second_life");
/* get editmode results */
- ED_object_exit_editmode(C, 0); /* 0 = does not exit editmode */
+ ED_object_editmode_load(CTX_data_edit_object(C));
if (collada_export(CTX_data_scene(C),
filepath,
@@ -130,6 +136,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
selected,
include_children,
include_armatures,
+ include_shapekeys,
deform_bones_only,
active_uv_only,
@@ -137,9 +144,12 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
include_material_textures,
use_texture_copies,
+ triangulate,
use_object_instantiation,
sort_by_name,
- second_life)) {
+ export_transformation_type,
+ second_life))
+ {
return OPERATOR_FINISHED;
}
else {
@@ -176,6 +186,10 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
uiItemR(row, imfptr, "include_armatures", 0, NULL, ICON_NONE);
uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
+ row = uiLayoutRow(box, FALSE);
+ uiItemR(row, imfptr, "include_shapekeys", 0, NULL, ICON_NONE);
+ uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
+
/* Texture options */
box = uiLayoutBox(layout);
row = uiLayoutRow(box, FALSE);
@@ -210,7 +224,15 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
uiItemL(row, IFACE_("Collada Options:"), ICON_MODIFIER);
row = uiLayoutRow(box, FALSE);
+ uiItemR(row, imfptr, "triangulate", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, FALSE);
uiItemR(row, imfptr, "use_object_instantiation", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, FALSE);
+ split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
+ uiItemL(split, IFACE_("Transformation Type"), ICON_NONE);
+ uiItemR(split, imfptr, "export_transformation_type_selection", 0, "", ICON_NONE);
+
row = uiLayoutRow(box, FALSE);
uiItemR(row, imfptr, "sort_by_name", 0, NULL, ICON_NONE);
@@ -232,6 +254,13 @@ void WM_OT_collada_export(wmOperatorType *ot)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem prop_bc_export_transformation_type[] = {
+ {BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations"},
+ {BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations"},
+ {BC_TRANSFORMATION_TYPE_BOTH, "both", 0, "Both", "Use <matrix> AND <translate>, <rotate>, <scale> to specify transformations"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
ot->name = "Export COLLADA";
ot->description = "Save a Collada file";
ot->idname = "WM_OT_collada_export";
@@ -266,6 +295,9 @@ void WM_OT_collada_export(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "include_armatures", 0, "Include Armatures",
"Export related armatures (even if not selected)");
+ RNA_def_boolean(ot->srna, "include_shapekeys", 1, "Include Shape Keys",
+ "Export all Shape Keys from Mesh Objects");
+
RNA_def_boolean(ot->srna, "deform_bones_only", 0, "Deform Bones only",
"Only export deforming bones with armatures");
@@ -283,12 +315,21 @@ void WM_OT_collada_export(wmOperatorType *ot)
"Copy textures to same folder where the .dae file is exported");
+ RNA_def_boolean(ot->srna, "triangulate", 1, "Triangulate",
+ "Export Polygons (Quads & NGons) as Triangles");
+
RNA_def_boolean(ot->srna, "use_object_instantiation", 1, "Use Object Instances",
"Instantiate multiple Objects from same Data");
RNA_def_boolean(ot->srna, "sort_by_name", 0, "Sort by Object name",
"Sort exported data by Object name");
+ RNA_def_int(ot->srna, "export_transformation_type", 0, INT_MIN, INT_MAX,
+ "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
+
+ 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, "second_life", 0, "Export for Second Life",
"Compatibility mode for Second Life");
}
@@ -298,18 +339,45 @@ void WM_OT_collada_export(wmOperatorType *ot)
static int wm_collada_import_exec(bContext *C, wmOperator *op)
{
char filename[FILE_MAX];
+ int import_units;
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
BKE_report(op->reports, RPT_ERROR, "No filename given");
return OPERATOR_CANCELLED;
}
+ /* Options panel */
+ import_units = RNA_boolean_get(op->ptr, "import_units");
+
RNA_string_get(op->ptr, "filepath", filename);
- if (collada_import(C, filename)) return OPERATOR_FINISHED;
+ if (collada_import(C, filename, import_units)) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Errors found during parsing COLLADA document (see console for details)");
+ return OPERATOR_CANCELLED;
+ }
+}
+
+static void uiCollada_importSettings(uiLayout *layout, PointerRNA *imfptr)
+{
+ uiLayout *box, *row;
- BKE_report(op->reports, RPT_ERROR, "Errors found during parsing COLLADA document (see console for details)");
+ /* Import Options: */
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, FALSE);
+ uiItemL(row, IFACE_("Import Data Options:"), ICON_MESH_DATA);
- return OPERATOR_FINISHED;
+ row = uiLayoutRow(box, FALSE);
+ uiItemR(row, imfptr, "import_units", 0, NULL, ICON_NONE);
+}
+
+static void wm_collada_import_draw(bContext *UNUSED(C), wmOperator *op)
+{
+ PointerRNA ptr;
+
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+ uiCollada_importSettings(op->layout, &ptr);
}
void WM_OT_collada_import(wmOperatorType *ot)
@@ -322,7 +390,17 @@ void WM_OT_collada_import(wmOperatorType *ot)
ot->exec = wm_collada_import_exec;
ot->poll = WM_operator_winactive;
+ //ot->flag |= OPTYPE_PRESET;
+
+ ot->ui = wm_collada_import_draw;
+
WM_operator_properties_filesel(ot, FOLDERFILE | COLLADAFILE, FILE_BLENDER, FILE_OPENFILE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
+
+ RNA_def_boolean(ot->srna,
+ "import_units", 0, "Import Units",
+ "If disabled match import to Blender's current Unit settings, "
+ "otherwise use the settings from the Imported scene");
+
}
#endif
diff --git a/source/blender/editors/io/io_ops.c b/source/blender/editors/io/io_ops.c
index f2a0532932d..a33340cc39a 100644
--- a/source/blender/editors/io/io_ops.c
+++ b/source/blender/editors/io/io_ops.c
@@ -31,6 +31,8 @@
#include "io_collada.h"
+#include "BLI_utildefines.h"
+
#include "WM_types.h"
#include "WM_api.h"
diff --git a/source/blender/editors/mask/SConscript b/source/blender/editors/mask/SConscript
index 4af000d038d..3200362b580 100644
--- a/source/blender/editors/mask/SConscript
+++ b/source/blender/editors/mask/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index e43c8a2b53b..33a6aa2d43d 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -629,7 +629,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int add_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
@@ -703,7 +703,7 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int add_feather_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int add_feather_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
@@ -720,7 +720,7 @@ static int add_feather_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event
void MASK_OT_add_feather_vertex(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Add feather Vertex";
+ ot->name = "Add Feather Vertex";
ot->description = "Add vertex to feather";
ot->idname = "MASK_OT_add_feather_vertex";
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index 74cdf4c2a11..af9d3341e61 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -409,7 +409,7 @@ static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline
int width, int height)
{
const unsigned int resol = max_ii(BKE_mask_spline_feather_resolution(spline, width, height),
- BKE_mask_spline_resolution(spline, width, height));
+ BKE_mask_spline_resolution(spline, width, height));
unsigned char rgb_tmp[4];
diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c
index 18384ad9de4..cd2995be439 100644
--- a/source/blender/editors/mask/mask_edit.c
+++ b/source/blender/editors/mask/mask_edit.c
@@ -324,15 +324,13 @@ void ED_mask_pixelspace_factor(ScrArea *sa, ARegion *ar, float *scalex, float *s
case SPACE_CLIP:
{
SpaceClip *sc = sa->spacedata.first;
- int width, height;
- float zoomx, zoomy, aspx, aspy;
+ float aspx, aspy;
- ED_space_clip_get_size(sc, &width, &height);
- ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy);
+ UI_view2d_getscale(&ar->v2d, scalex, scaley);
ED_space_clip_get_aspect(sc, &aspx, &aspy);
- *scalex = ((float)width * aspx) * zoomx;
- *scaley = ((float)height * aspy) * zoomy;
+ *scalex *= aspx;
+ *scaley *= aspy;
break;
}
case SPACE_SEQ:
@@ -343,15 +341,13 @@ void ED_mask_pixelspace_factor(ScrArea *sa, ARegion *ar, float *scalex, float *s
case SPACE_IMAGE:
{
SpaceImage *sima = sa->spacedata.first;
- int width, height;
- float zoomx, zoomy, aspx, aspy;
+ float aspx, aspy;
- ED_space_image_get_size(sima, &width, &height);
- ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
+ UI_view2d_getscale(&ar->v2d, scalex, scaley);
ED_space_image_get_aspect(sima, &aspx, &aspy);
- *scalex = ((float)width * aspx) * zoomx;
- *scaley = ((float)height * aspy) * zoomy;
+ *scalex *= aspx;
+ *scaley *= aspy;
break;
}
default:
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index 35f85f3faee..ff8e27ac264 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -36,6 +36,7 @@
#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#include "BKE_main.h"
#include "BKE_mask.h"
#include "DNA_scene_types.h"
@@ -261,9 +262,10 @@ int ED_mask_feather_find_nearest(const bContext *C, Mask *mask, float normal_co[
Mask *ED_mask_new(bContext *C, const char *name)
{
ScrArea *sa = CTX_wm_area(C);
+ Main *bmain = CTX_data_main(C);
Mask *mask;
- mask = BKE_mask_new(name);
+ mask = BKE_mask_new(bmain, name);
if (sa && sa->spacedata.first) {
switch (sa->spacetype) {
@@ -436,7 +438,7 @@ static int slide_point_check_initial_feather(MaskSpline *spline)
return TRUE;
}
-static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event)
+static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *event)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
@@ -523,7 +525,7 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event)
return customdata;
}
-static int slide_point_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int slide_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SlidePointData *slidedata = slide_point_customdata(C, op, event);
@@ -632,7 +634,7 @@ static void free_slide_point_data(SlidePointData *data)
MEM_freeN(data);
}
-static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
SlidePointData *data = (SlidePointData *)op->customdata;
BezTriple *bezt = &data->point->bezt;
diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c
index a1f2539ce7c..2a1bdee32f7 100644
--- a/source/blender/editors/mask/mask_relationships.c
+++ b/source/blender/editors/mask/mask_relationships.c
@@ -31,6 +31,7 @@
#include "BLI_math.h"
+#include "BLI_string.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
@@ -143,8 +144,8 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
if (MASKPOINT_ISSEL_ANY(point)) {
point->parent.id_type = ID_MC;
point->parent.id = &clip->id;
- strcpy(point->parent.parent, tracking_object->name);
- strcpy(point->parent.sub_parent, track->name);
+ BLI_strncpy(point->parent.parent, tracking_object->name, sizeof(point->parent.parent));
+ BLI_strncpy(point->parent.sub_parent, track->name, sizeof(point->parent.sub_parent));
copy_v2_v2(point->parent.parent_orig, parmask_pos);
}
diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c
index cd1a47754f8..7de6f66f2ef 100644
--- a/source/blender/editors/mask/mask_select.c
+++ b/source/blender/editors/mask/mask_select.c
@@ -252,9 +252,9 @@ static int select_exec(bContext *C, wmOperator *op)
MaskSpline *spline;
MaskSplinePoint *point = NULL;
float co[2];
- short extend = RNA_boolean_get(op->ptr, "extend");
- short deselect = RNA_boolean_get(op->ptr, "deselect");
- short toggle = RNA_boolean_get(op->ptr, "toggle");
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+ bool deselect = RNA_boolean_get(op->ptr, "deselect");
+ bool toggle = RNA_boolean_get(op->ptr, "toggle");
int is_handle = 0;
const float threshold = 19;
@@ -263,7 +263,7 @@ static int select_exec(bContext *C, wmOperator *op)
point = ED_mask_point_find_nearest(C, mask, co, threshold, &masklay, &spline, &is_handle, NULL);
- if (extend == 0 && deselect == 0 && toggle == 0)
+ if (extend == false && deselect == false && toggle == false)
ED_mask_select_toggle_all(mask, SEL_DESELECT);
if (point) {
@@ -361,7 +361,7 @@ static int select_exec(bContext *C, wmOperator *op)
return OPERATOR_PASS_THROUGH;
}
-static int select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
@@ -689,7 +689,7 @@ void MASK_OT_select_circle(wmOperatorType *ot)
RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Gesture Mode", "", INT_MIN, INT_MAX);
}
-static int mask_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int mask_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt
index c51d2cfb2e5..a76872d6e30 100644
--- a/source/blender/editors/mesh/CMakeLists.txt
+++ b/source/blender/editors/mesh/CMakeLists.txt
@@ -26,6 +26,7 @@ set(INC
../../blenlib
../../blenloader
../../bmesh
+ ../../gpu
../../imbuf
../../makesdna
../../makesrna
@@ -43,12 +44,12 @@ set(SRC
editmesh_add.c
editmesh_bvh.c
editmesh_knife.c
+ editmesh_knife_project.c
editmesh_loopcut.c
editmesh_rip.c
editmesh_select.c
editmesh_tools.c
editmesh_utils.c
- editmesh_slide.c
mesh_data.c
mesh_ops.c
meshtools.c
@@ -73,6 +74,10 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_FREESTYLE)
+ add_definitions(-DWITH_FREESTYLE)
+endif()
+
if(WITH_BULLET)
add_definitions(-DWITH_BULLET)
endif()
diff --git a/source/blender/editors/mesh/SConscript b/source/blender/editors/mesh/SConscript
index 91ffdc91685..55ad14a50fc 100644
--- a/source/blender/editors/mesh/SConscript
+++ b/source/blender/editors/mesh/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
@@ -27,6 +53,9 @@ else:
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
+if env['WITH_BF_FREESTYLE']:
+ defs.append('WITH_FREESTYLE')
+
if env['WITH_BF_BULLET']:
defs.append('WITH_BULLET')
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 4350c005f95..d6ae2497cbb 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -27,23 +27,20 @@
* \ingroup edmesh
*/
-#include <math.h>
-#include <string.h>
#include "MEM_guardedalloc.h"
-#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_edgehash.h"
+#include "BLF_translation.h"
+
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
@@ -61,7 +58,6 @@
#include "WM_types.h"
/* own include */
-#include "mesh_intern.h"
/* copy the face flags, most importantly selection from the mesh to the final derived mesh,
* use in object mode when selecting faces (while painting) */
@@ -75,7 +71,14 @@ void paintface_flush_flags(Object *ob)
int totface, totpoly;
int i;
- if (me == NULL || dm == NULL)
+ if (me == NULL)
+ return;
+
+ /* we could call this directly in all areas that change selection,
+ * since this could become slow for realtime updates (circle-select for eg) */
+ BKE_mesh_flush_select_from_polys(me);
+
+ if (dm == NULL)
return;
/*
@@ -178,11 +181,17 @@ void paintface_reveal(Object *ob)
static void hash_add_face(EdgeHash *ehash, MPoly *mp, MLoop *mloop)
{
- MLoop *ml;
- int i;
+ MLoop *ml, *ml_next;
+ int i = mp->totloop;
+
+ ml_next = mloop; /* first loop */
+ ml = &ml_next[i - 1]; /* last loop */
- for (i = 0, ml = mloop; i < mp->totloop; i++, ml++) {
- BLI_edgehash_insert(ehash, ml->v, ME_POLY_LOOP_NEXT(mloop, mp, i)->v, NULL);
+ while (i-- != 0) {
+ BLI_edgehash_insert(ehash, ml->v, ml_next->v, NULL);
+
+ ml = ml_next;
+ ml_next++;
}
}
@@ -194,7 +203,8 @@ static void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int ind
MLoop *ml;
MEdge *med;
char *linkflag;
- int a, b, do_it = TRUE, mark = 0;
+ int a, b, mark = 0;
+ bool do_it = true;
ehash = BLI_edgehash_new();
seamhash = BLI_edgehash_new();
@@ -225,7 +235,7 @@ static void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int ind
}
while (do_it) {
- do_it = FALSE;
+ do_it = false;
/* expand selection */
mp = me->mpoly;
@@ -248,7 +258,7 @@ static void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int ind
if (mark) {
linkflag[a] = 1;
hash_add_face(ehash, mp, me->mloop + mp->loopstart);
- do_it = TRUE;
+ do_it = true;
}
}
}
@@ -285,7 +295,7 @@ static void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int ind
MEM_freeN(linkflag);
}
-void paintface_select_linked(bContext *UNUSED(C), Object *ob, int UNUSED(mval[2]), int mode)
+void paintface_select_linked(bContext *UNUSED(C), Object *ob, const int UNUSED(mval[2]), int mode)
{
Mesh *me;
unsigned int index = 0;
@@ -306,7 +316,7 @@ void paintface_select_linked(bContext *UNUSED(C), Object *ob, int UNUSED(mval[2]
paintface_flush_flags(ob);
}
-void paintface_deselect_all_visible(Object *ob, int action, short flush_flags)
+void paintface_deselect_all_visible(Object *ob, int action, bool flush_flags)
{
Mesh *me;
MPoly *mpoly;
@@ -365,14 +375,15 @@ void paintface_deselect_all_visible(Object *ob, int action, short flush_flags)
}
}
-int paintface_minmax(Object *ob, float r_min[3], float r_max[3])
+bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
{
Mesh *me;
MPoly *mp;
MTexPoly *tf;
MLoop *ml;
MVert *mvert;
- int a, b, ok = FALSE;
+ int a, b;
+ bool ok = false;
float vec[3], bmat[3][3];
me = BKE_mesh_from_object(ob);
@@ -395,7 +406,7 @@ int paintface_minmax(Object *ob, float r_min[3], float r_max[3])
minmax_v3v3_v3(r_min, r_max, vec);
}
- ok = TRUE;
+ ok = true;
}
return ok;
@@ -428,7 +439,7 @@ void seam_mark_clear_tface(Scene *scene, short mode)
if (me == 0 || me->totpoly == 0) return;
if (mode == 0)
- mode = pupmenu("Seams %t|Mark Border Seam %x1|Clear Seam %x2");
+ mode = pupmenu(IFACE_("Seams %t|Mark Border Seam %x1|Clear Seam %x2"));
if (mode != 1 && mode != 2)
return;
@@ -474,7 +485,7 @@ void seam_mark_clear_tface(Scene *scene, short mode)
}
#endif
-int paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], int extend, int deselect, int toggle)
+bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], bool extend, bool deselect, bool toggle)
{
Mesh *me;
MPoly *mpoly, *mpoly_sel;
@@ -483,14 +494,14 @@ int paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], in
/* Get the face under the cursor */
me = BKE_mesh_from_object(ob);
- if (!ED_mesh_pick_face(C, me, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE))
- return 0;
+ if (!ED_mesh_pick_face(C, ob, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE))
+ return false;
if (index >= me->totpoly)
- return 0;
+ return false;
mpoly_sel = me->mpoly + index;
- if (mpoly_sel->flag & ME_HIDE) return 0;
+ if (mpoly_sel->flag & ME_HIDE) return false;
/* clear flags */
mpoly = me->mpoly;
@@ -516,17 +527,19 @@ int paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], in
else
mpoly_sel->flag |= ME_FACE_SEL;
}
- else mpoly_sel->flag |= ME_FACE_SEL;
+ else {
+ mpoly_sel->flag |= ME_FACE_SEL;
+ }
/* image window redraw */
paintface_flush_flags(ob);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
- return 1;
+ return true;
}
-int do_paintface_box_select(ViewContext *vc, rcti *rect, int select, int extend)
+int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
{
Object *ob = vc->obact;
Mesh *me;
@@ -545,8 +558,8 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, int select, int extend)
selar = MEM_callocN(me->totpoly + 1, "selar");
- if (extend == 0 && select) {
- paintface_deselect_all_visible(vc->obact, SEL_DESELECT, FALSE);
+ if (extend == false && select) {
+ paintface_deselect_all_visible(vc->obact, SEL_DESELECT, false);
mpoly = me->mpoly;
for (a = 1; a <= me->totpoly; a++, mpoly++) {
@@ -559,7 +572,7 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, int select, int extend)
ibuf = IMB_allocImBuf(sx, sy, 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);
+ 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);
a = sx * sy;
@@ -609,7 +622,14 @@ void paintvert_flush_flags(Object *ob)
int totvert;
int i;
- if (me == NULL || dm == NULL)
+ if (me == NULL)
+ return;
+
+ /* we could call this directly in all areas that change selection,
+ * since this could become slow for realtime updates (circle-select for eg) */
+ BKE_mesh_flush_select_from_verts(me);
+
+ if (dm == NULL)
return;
index_array = dm->getVertDataArray(dm, CD_ORIGINDEX);
@@ -634,8 +654,8 @@ void paintvert_flush_flags(Object *ob)
}
}
}
-/* note: if the caller passes FALSE to flush_flags, then they will need to run paintvert_flush_flags(ob) themselves */
-void paintvert_deselect_all_visible(Object *ob, int action, short flush_flags)
+/* note: if the caller passes false to flush_flags, then they will need to run paintvert_flush_flags(ob) themselves */
+void paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
{
Mesh *me;
MVert *mvert;
@@ -694,6 +714,37 @@ void paintvert_deselect_all_visible(Object *ob, int action, short flush_flags)
}
}
+void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
+{
+ Mesh *me = BKE_mesh_from_object(ob);
+ MVert *mv;
+ MDeformVert *dv;
+ int a, tot;
+
+ if (me == NULL || me->dvert == NULL) {
+ return;
+ }
+
+ if (!extend) {
+ paintvert_deselect_all_visible(ob, SEL_DESELECT, false);
+ }
+
+ dv = me->dvert;
+ tot = me->totvert;
+
+ for (a = 0, mv = me->mvert; a < tot; a++, mv++, dv++) {
+ if ((mv->flag & ME_HIDE) == 0) {
+ if (dv->dw == NULL) {
+ /* if null weight then not grouped */
+ mv->flag |= SELECT;
+ }
+ }
+ }
+
+ if (flush_flags) {
+ paintvert_flush_flags(ob);
+ }
+}
/* ********************* MESH VERTEX MIRR TOPO LOOKUP *************** */
/* note, this is not the best place for the function to be but moved
@@ -720,7 +771,7 @@ static int mirrtopo_vert_sort(const void *v1, const void *v2)
return 0;
}
-int ED_mesh_mirrtopo_recalc_check(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store)
+bool ED_mesh_mirrtopo_recalc_check(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store)
{
int totvert;
int totedge;
@@ -739,16 +790,16 @@ int ED_mesh_mirrtopo_recalc_check(Mesh *me, const int ob_mode, MirrTopoStore_t *
(totvert != mesh_topo_store->prev_vert_tot) ||
(totedge != mesh_topo_store->prev_edge_tot))
{
- return TRUE;
+ return true;
}
else {
- return FALSE;
+ return false;
}
}
void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store,
- const short skip_em_vert_array_init)
+ const bool skip_em_vert_array_init)
{
MEdge *medge;
BMEditMesh *em = me->edit_btmesh;
@@ -851,8 +902,8 @@ void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_to
index_lookup = MEM_mallocN(totvert * sizeof(*index_lookup), "mesh_topo_lookup");
if (em) {
- if (skip_em_vert_array_init == FALSE) {
- EDBM_index_arrays_init(em, 1, 0, 0);
+ if (skip_em_vert_array_init == false) {
+ EDBM_index_arrays_ensure(em, BM_VERT);
}
}
@@ -888,11 +939,6 @@ void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_to
last = a;
}
}
- if (em) {
- if (skip_em_vert_array_init == FALSE) {
- EDBM_index_arrays_free(em);
- }
- }
MEM_freeN(topo_pairs);
topo_pairs = NULL;
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index 763c6c98a99..1daf39d3319 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -29,20 +29,19 @@
* \ingroup edmesh
*/
-#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "RNA_define.h"
-#include "RNA_access.h"
-
#include "BLI_math.h"
+#include "BLF_translation.h"
+
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_library.h"
#include "BKE_tessmesh.h"
+#include "RNA_define.h"
+#include "RNA_access.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -65,17 +64,17 @@ static Object *make_prim_init(bContext *C, const char *idname,
*state = 0;
if (obedit == NULL || obedit->type != OB_MESH) {
- obedit = ED_object_add_type(C, OB_MESH, loc, rot, FALSE, layer);
+ obedit = ED_object_add_type(C, OB_MESH, loc, rot, false, layer);
rename_id((ID *)obedit, idname);
rename_id((ID *)obedit->data, idname);
/* create editmode */
- ED_object_enter_editmode(C, EM_DO_UNDO | EM_IGNORE_LAYER); /* rare cases the active layer is messed up */
+ ED_object_editmode_enter(C, EM_DO_UNDO | EM_IGNORE_LAYER); /* rare cases the active layer is messed up */
*state = 1;
}
- *dia = ED_object_new_primitive_matrix(C, obedit, loc, rot, mat, FALSE);
+ *dia = ED_object_new_primitive_matrix(C, obedit, loc, rot, mat, false);
return obedit;
}
@@ -90,11 +89,11 @@ static void make_prim_finish(bContext *C, Object *obedit, int *state, int enter_
EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX);
/* only recalc editmode tessface if we are staying in editmode */
- EDBM_update_generic(C, em, !exit_editmode);
+ EDBM_update_generic(em, !exit_editmode, true);
/* userdef */
if (exit_editmode) {
- ED_object_exit_editmode(C, EM_FREEDATA); /* adding EM_DO_UNDO messes up operator redo */
+ ED_object_editmode_exit(C, EM_FREEDATA); /* adding EM_DO_UNDO messes up operator redo */
}
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
}
@@ -109,7 +108,7 @@ static int add_primitive_plane_exec(bContext *C, wmOperator *op)
unsigned int layer;
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, "Plane", &dia, mat, &state, loc, rot, layer);
+ obedit = make_prim_init(C, DATA_("Plane"), &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(em, op, "verts.out",
@@ -137,7 +136,7 @@ void MESH_OT_primitive_plane_add(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_generic_props(ot, TRUE);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_cube_exec(bContext *C, wmOperator *op)
@@ -150,7 +149,7 @@ static int add_primitive_cube_exec(bContext *C, wmOperator *op)
unsigned int layer;
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, "Cube", &dia, mat, &state, loc, rot, layer);
+ obedit = make_prim_init(C, DATA_("Cube"), &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(em, op, "verts.out", "create_cube matrix=%m4 size=%f", mat, dia * 2.0f)) {
@@ -177,7 +176,7 @@ void MESH_OT_primitive_cube_add(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_generic_props(ot, TRUE);
+ ED_object_add_generic_props(ot, true);
}
static const EnumPropertyItem fill_type_items[] = {
@@ -199,7 +198,7 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op)
cap_tri = (cap_end == 2);
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, "Circle", &dia, mat, &state, loc, rot, layer);
+ obedit = make_prim_init(C, DATA_("Circle"), &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(em, op, "verts.out",
@@ -238,7 +237,7 @@ void MESH_OT_primitive_circle_add(wmOperatorType *ot)
RNA_def_property_subtype(prop, PROP_DISTANCE);
RNA_def_enum(ot->srna, "fill_type", fill_type_items, 0, "Fill Type", "");
- ED_object_add_generic_props(ot, TRUE);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
@@ -254,7 +253,7 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
cap_tri = (cap_end == 2);
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, "Cylinder", &dia, mat, &state, loc, rot, layer);
+ obedit = make_prim_init(C, DATA_("Cylinder"), &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(
@@ -299,7 +298,7 @@ void MESH_OT_primitive_cylinder_add(wmOperatorType *ot)
RNA_def_property_subtype(prop, PROP_DISTANCE);
RNA_def_enum(ot->srna, "end_fill_type", fill_type_items, 1, "Cap Fill Type", "");
- ED_object_add_generic_props(ot, TRUE);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_cone_exec(bContext *C, wmOperator *op)
@@ -315,7 +314,7 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op)
cap_tri = (cap_end == 2);
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, "Cone", &dia, mat, &state, loc, rot, layer);
+ obedit = make_prim_init(C, DATA_("Cone"), &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(
@@ -359,7 +358,7 @@ void MESH_OT_primitive_cone_add(wmOperatorType *ot)
RNA_def_property_subtype(prop, PROP_DISTANCE);
RNA_def_enum(ot->srna, "end_fill_type", fill_type_items, 1, "Base Fill Type", "");
- ED_object_add_generic_props(ot, TRUE);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_grid_exec(bContext *C, wmOperator *op)
@@ -372,7 +371,7 @@ static int add_primitive_grid_exec(bContext *C, wmOperator *op)
unsigned int layer;
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, "Grid", &dia, mat, &state, loc, rot, layer);
+ obedit = make_prim_init(C, DATA_("Grid"), &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(em, op, "verts.out",
@@ -412,7 +411,7 @@ void MESH_OT_primitive_grid_add(wmOperatorType *ot)
prop = RNA_def_float(ot->srna, "size", 1.0f, 0.0, FLT_MAX, "Size", "", 0.001, FLT_MAX);
RNA_def_property_subtype(prop, PROP_DISTANCE);
- ED_object_add_generic_props(ot, TRUE);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
@@ -428,7 +427,7 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
if (!view_aligned)
rot[0] += (float)M_PI / 2.0f;
- obedit = make_prim_init(C, "Suzanne", &dia, mat, &state, loc, rot, layer);
+ obedit = make_prim_init(C, DATA_("Suzanne"), &dia, mat, &state, loc, rot, layer);
mat[0][0] *= dia;
mat[1][1] *= dia;
mat[2][2] *= dia;
@@ -458,7 +457,7 @@ void MESH_OT_primitive_monkey_add(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_generic_props(ot, TRUE);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
@@ -471,7 +470,7 @@ static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
unsigned int layer;
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, "Sphere", &dia, mat, &state, loc, rot, layer);
+ obedit = make_prim_init(C, DATA_("Sphere"), &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(em, op, "verts.out",
@@ -510,7 +509,7 @@ void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot)
prop = RNA_def_float(ot->srna, "size", 1.0f, 0.0, FLT_MAX, "Size", "", 0.001, 100.00);
RNA_def_property_subtype(prop, PROP_DISTANCE);
- ED_object_add_generic_props(ot, TRUE);
+ ED_object_add_generic_props(ot, true);
}
static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
@@ -523,7 +522,7 @@ static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
unsigned int layer;
ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, "Icosphere", &dia, mat, &state, loc, rot, layer);
+ obedit = make_prim_init(C, DATA_("Icosphere"), &dia, mat, &state, loc, rot, layer);
em = BMEdit_FromObject(obedit);
if (!EDBM_op_call_and_selectf(
@@ -562,5 +561,5 @@ void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot)
prop = RNA_def_float(ot->srna, "size", 1.0f, 0.0f, FLT_MAX, "Size", "", 0.001f, 100.00);
RNA_def_property_subtype(prop, PROP_DISTANCE);
- ED_object_add_generic_props(ot, TRUE);
+ ED_object_add_generic_props(ot, true);
}
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index b7b71be0df9..57d3f7406ca 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -37,15 +37,15 @@
#include "BLI_blenlib.h"
#include "BLI_array.h"
+#include "BLI_linklist.h"
#include "BLI_math.h"
-#include "BLI_rand.h"
#include "BLI_smallhash.h"
-#include "BLI_scanfill.h"
#include "BLI_memarena.h"
+#include "BLF_translation.h"
+
#include "BKE_DerivedMesh.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BIF_gl.h"
#include "BIF_glutil.h" /* for paint cursor */
@@ -59,7 +59,6 @@
#include "WM_types.h"
#include "DNA_scene_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "BKE_tessmesh.h"
#include "UI_resources.h"
@@ -92,7 +91,8 @@ typedef struct KnifeVert {
ListBase faces;
float co[3], cageco[3], sco[3]; /* sco is screen coordinates for cageco */
- short flag, draw, isface, inspace;
+ bool is_face, in_space;
+ bool draw;
} KnifeVert;
typedef struct Ref {
@@ -104,9 +104,9 @@ typedef struct KnifeEdge {
KnifeVert *v1, *v2;
BMFace *basef; /* face to restrict face fill to */
ListBase faces;
- int draw;
- BMEdge *e, *oe; /* non-NULL if this is an original edge */
+ BMEdge *e /* , *e_old */; /* non-NULL if this is an original edge */
+ bool draw;
} KnifeEdge;
typedef struct BMEdgeHit {
@@ -130,16 +130,17 @@ typedef struct KnifePosData {
KnifeVert *vert;
KnifeEdge *edge;
BMFace *bmface;
- int is_space;
+ bool is_space;
- int mval[2]; /* mouse screen position */
+ float mval[2]; /* mouse screen position (may be non-integral if snapped to something) */
} KnifePosData;
/* struct for properties used while drawing */
typedef struct KnifeTool_OpData {
ARegion *ar; /* region that knifetool was activated in */
void *draw_handle; /* for drawing preview loop */
- ViewContext vc;
+ ViewContext vc; /* note: _don't_ use 'mval', instead use the one we define below */
+ float mval[2]; /* mouse value with snapping applied */
//bContext *C;
Object *ob;
@@ -175,12 +176,15 @@ typedef struct KnifeTool_OpData {
KnifeColors colors;
+ /* run by the UI or not */
+ bool is_interactive;
+
/* operatpr options */
- char cut_through; /* preference, can be modified at runtime (that feature may go) */
- char only_select; /* set on initialization */
- char select_result; /* set on initialization */
+ bool cut_through; /* preference, can be modified at runtime (that feature may go) */
+ bool only_select; /* set on initialization */
+ bool select_result; /* set on initialization */
- short is_ortho;
+ bool is_ortho;
float ortho_extent;
float clipsta, clipend;
@@ -191,8 +195,10 @@ typedef struct KnifeTool_OpData {
MODE_PANNING
} mode;
- int snap_midpoints, prevmode, extend;
- int ignore_edge_snapping, ignore_vert_snapping;
+ int prevmode;
+ bool snap_midpoints, extend;
+ bool ignore_edge_snapping;
+ bool ignore_vert_snapping;
enum {
ANGLE_FREE,
@@ -208,31 +214,38 @@ typedef struct KnifeTool_OpData {
static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd, BMFace *f);
#if 0
-static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2],
+static void knife_input_ray_cast(KnifeTool_OpData *kcd, const float mval[2],
float r_origin[3], float r_ray[3]);
#endif
-static void knife_input_ray_segment(KnifeTool_OpData *kcd, const int mval_i[2], const float ofs,
+static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2], const float ofs,
float r_origin[3], float r_dest[3]);
static void knife_update_header(bContext *C, KnifeTool_OpData *kcd)
{
- #define HEADER_LENGTH 190
+ #define HEADER_LENGTH 256
char header[HEADER_LENGTH];
- BLI_snprintf(header, HEADER_LENGTH, "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)",
- kcd->snap_midpoints ? "On" : "Off",
- kcd->ignore_edge_snapping ? "On" : "Off",
- kcd->angle_snapping ? "On" : "Off",
- kcd->cut_through ? "On" : "Off");
+ 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)"),
+ kcd->snap_midpoints ? IFACE_("On") : IFACE_("Off"),
+ kcd->ignore_edge_snapping ? IFACE_("On") : IFACE_("Off"),
+ kcd->angle_snapping ? IFACE_("On") : IFACE_("Off"),
+ kcd->cut_through ? IFACE_("On") : IFACE_("Off"));
ED_area_headerprint(CTX_wm_area(C), header);
}
+#if 0
+BLI_INLINE int round_ftoi(float x)
+{
+ return x > 0.0f ? (int)(x + 0.5f) : (int)(x - 0.5f);
+}
+#endif
-static void knife_project_v3(KnifeTool_OpData *kcd, const float co[3], float sco[3])
+static void knife_project_v3(const KnifeTool_OpData *kcd, const float co[3], float sco[3])
{
- ED_view3d_project_float_v3_m4(kcd->ar, co, sco, kcd->projmat);
+ ED_view3d_project_float_v3_m4(kcd->ar, co, sco, (float (*)[4])kcd->projmat);
}
static void knife_pos_data_clear(KnifePosData *kpd)
@@ -242,8 +255,7 @@ static void knife_pos_data_clear(KnifePosData *kpd)
kpd->vert = NULL;
kpd->edge = NULL;
kpd->bmface = NULL;
- kpd->mval[0] = 0;
- kpd->mval[1] = 0;
+ zero_v2(kpd->mval);
}
static ListBase *knife_empty_list(KnifeTool_OpData *kcd)
@@ -491,7 +503,7 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd)
if (kcd->prev.edge && kcd->prev.edge == kcd->curr.edge)
return;
- kfe->draw = 1;
+ kfe->draw = true;
if (kcd->prev.vert) {
kfe->v1 = kcd->prev.vert;
@@ -502,9 +514,9 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd)
else {
kfe->v1 = new_knife_vert(kcd, kcd->prev.co, kcd->prev.co);
kfe->v1->draw = kfe->draw = !kcd->prev.is_space;
- kfe->v1->inspace = kcd->prev.is_space;
+ kfe->v1->in_space = kcd->prev.is_space;
kfe->draw = !kcd->prev.is_space;
- kfe->v1->isface = 1;
+ kfe->v1->is_face = true;
if (kfe->v1->draw && kcd->prev.bmface)
knife_append_list(kcd, &kfe->v1->faces, kcd->prev.bmface);
}
@@ -519,13 +531,13 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd)
else {
kfe->v2 = new_knife_vert(kcd, kcd->curr.co, kcd->curr.co);
kfe->v2->draw = !kcd->curr.is_space;
- kfe->v2->isface = 1;
- kfe->v2->inspace = kcd->curr.is_space;
+ kfe->v2->is_face = true;
+ kfe->v2->in_space = kcd->curr.is_space;
if (kfe->v2->draw && kcd->curr.bmface)
knife_append_list(kcd, &kfe->v2->faces, kcd->curr.bmface);
if (kcd->curr.is_space)
- kfe->draw = 0;
+ kfe->draw = false;
kcd->curr.vert = kfe->v2;
}
@@ -629,11 +641,10 @@ static void knife_add_single_cut_through(KnifeTool_OpData *kcd, KnifeVert *v1, K
KnifeEdge *kfenew;
kfenew = new_knife_edge(kcd);
- kfenew->draw = 1;
kfenew->basef = f;
kfenew->v1 = v1;
kfenew->v2 = v2;
- kfenew->draw = 1;
+ kfenew->draw = true;
knife_add_to_vert_edges(kcd, kfenew);
@@ -645,8 +656,9 @@ static void knife_get_vert_faces(KnifeTool_OpData *kcd, KnifeVert *kfv, BMFace *
{
BMIter bmiter;
BMFace *f;
+ Ref *r;
- if (kfv->isface && facef) {
+ if (kfv->is_face && facef) {
knife_append_list(kcd, lst, facef);
}
else if (kfv->v) {
@@ -654,6 +666,11 @@ static void knife_get_vert_faces(KnifeTool_OpData *kcd, KnifeVert *kfv, BMFace *
knife_append_list(kcd, lst, f);
}
}
+ else {
+ for (r = kfv->faces.first; r; r = r->next) {
+ knife_append_list(kcd, lst, r->ref);
+ }
+ }
}
static void knife_get_edge_faces(KnifeTool_OpData *kcd, KnifeEdge *kfe, ListBase *lst)
@@ -680,7 +697,7 @@ static void knife_cut_through(KnifeTool_OpData *kcd)
ListBase firstfaces = {NULL, NULL}, lastfaces = {NULL, NULL};
Ref *r, *r2;
KnifeEdge **splitkfe;
- int i, j, found;
+ int i, j;
if (!kcd->totlinehit) {
/* if no linehits then no interesting back face stuff to do */
@@ -718,15 +735,15 @@ static void knife_cut_through(KnifeTool_OpData *kcd)
/* For each face incident to firstv,
* find the first following linehit (if any) sharing that face and connect */
for (r = firstfaces.first; r; r = r->next) {
+ bool found = false;
f = r->ref;
- found = 0;
- for (j = 0, lh2 = kcd->linehits; j < kcd->totlinehit; j++, lh2++) {
+ for (j = 0, lh2 = kcd->linehits; j < kcd->totlinehit && !found; j++, lh2++) {
kfe2 = lh2->kfe;
for (r2 = kfe2->faces.first; r2; r2 = r2->next) {
if (r2->ref == f) {
v2 = splitkfe[j] ? kfe2->v1 : knife_split_edge(kcd, kfe2, lh2->hit, &splitkfe[j]);
knife_add_single_cut_through(kcd, firstv, v2, f);
- found = 1;
+ found = true;
break;
}
}
@@ -748,16 +765,16 @@ static void knife_cut_through(KnifeTool_OpData *kcd)
/* For each face attached to edge for this linehit,
* find the first following linehit (if any) sharing that face and connect */
for (r = kfe->faces.first; r; r = r->next) {
+ bool found = false;
f = r->ref;
- found = 0;
- for (j = i + 1, lh2 = lh + 1; j < kcd->totlinehit; j++, lh2++) {
+ for (j = i + 1, lh2 = lh + 1; j < kcd->totlinehit && !found; j++, lh2++) {
kfe2 = lh2->kfe;
for (r2 = kfe2->faces.first; r2; r2 = r2->next) {
if (r2->ref == f) {
v1 = splitkfe[i] ? kfe->v1 : knife_split_edge(kcd, kfe, lh->hit, &splitkfe[i]);
v2 = splitkfe[j] ? kfe2->v1 : knife_split_edge(kcd, kfe2, lh2->hit, &splitkfe[j]);
knife_add_single_cut_through(kcd, v1, v2, f);
- found = 1;
+ found = true;
break;
}
}
@@ -780,6 +797,7 @@ static void knife_cut_through(KnifeTool_OpData *kcd)
kcd->totlinehit = 0;
/* set up for next cut */
+ kcd->curr.vert = lastv;
kcd->prev = kcd->curr;
}
@@ -880,7 +898,7 @@ static void knife_finish_cut(KnifeTool_OpData *UNUSED(kcd))
}
-static void knifetool_draw_angle_snapping(KnifeTool_OpData *kcd)
+static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd)
{
bglMats mats;
double u[3], u1[2], u2[2], v1[3], v2[3], dx, dy;
@@ -996,7 +1014,7 @@ static void knife_init_colors(KnifeColors *colors)
static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
{
View3D *v3d = CTX_wm_view3d(C);
- KnifeTool_OpData *kcd = arg;
+ const KnifeTool_OpData *kcd = arg;
if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
@@ -1052,7 +1070,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
if (kcd->totlinehit > 0) {
const float vthresh4 = kcd->vthresh / 4.0f;
- const float vthresh4_squared = vthresh4 * vthresh4;
+ const float vthresh4_sq = vthresh4 * vthresh4;
BMEdgeHit *lh;
int i;
@@ -1072,12 +1090,12 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
knife_project_v3(kcd, lh->kfe->v2->cageco, sv2);
knife_project_v3(kcd, lh->cagehit, lh->schit);
- if (len_squared_v2v2(lh->schit, sv1) < vthresh4_squared) {
+ if (len_squared_v2v2(lh->schit, sv1) < vthresh4_sq) {
copy_v3_v3(lh->cagehit, lh->kfe->v1->cageco);
glVertex3fv(lh->cagehit);
lh->v = lh->kfe->v1;
}
- else if (len_squared_v2v2(lh->schit, sv2) < vthresh4_squared) {
+ else if (len_squared_v2v2(lh->schit, sv2) < vthresh4_sq) {
copy_v3_v3(lh->cagehit, lh->kfe->v2->cageco);
glVertex3fv(lh->cagehit);
lh->v = lh->kfe->v2;
@@ -1150,7 +1168,7 @@ static float len_v3_tri_side_max(const float v1[3], const float v2[3], const flo
const float s2 = len_squared_v3v3(v2, v3);
const float s3 = len_squared_v3v3(v3, v1);
- return sqrtf(MAX3(s1, s2, s3));
+ return sqrtf(max_fff(s1, s2, s3));
}
static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
@@ -1169,7 +1187,7 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
/* for comparing distances, error of intersection depends on triangle scale.
* need to scale down before squaring for accurate comparison */
const float depsilon = (FLT_EPSILON / 2.0f) * len_v3_tri_side_max(v1, v2, v3);
- const float depsilon_squared = depsilon * depsilon;
+ const float depsilon_sq = depsilon * depsilon;
copy_v3_v3(cos + 0, v1);
copy_v3_v3(cos + 3, v2);
@@ -1182,7 +1200,7 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
for (i = 0; i < tot; i++, result++) {
BMLoop *l1;
- BMFace *hitf;
+ BMFace *f_hit;
ListBase *lst;
Ref *ref;
@@ -1203,19 +1221,19 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
interp_v3_v3v3(p, kfe->v1->cageco, kfe->v2->cageco, lambda);
- if (kcd->curr.vert && len_squared_v3v3(kcd->curr.vert->cageco, p) < depsilon_squared) {
+ if (kcd->curr.vert && len_squared_v3v3(kcd->curr.vert->cageco, p) < depsilon_sq) {
continue;
}
- if (kcd->prev.vert && len_squared_v3v3(kcd->prev.vert->cageco, p) < depsilon_squared) {
+ if (kcd->prev.vert && len_squared_v3v3(kcd->prev.vert->cageco, p) < depsilon_sq) {
continue;
}
- if (len_squared_v3v3(kcd->prev.cage, p) < depsilon_squared ||
- len_squared_v3v3(kcd->curr.cage, p) < depsilon_squared)
+ if (len_squared_v3v3(kcd->prev.cage, p) < depsilon_sq ||
+ len_squared_v3v3(kcd->curr.cage, p) < depsilon_sq)
{
continue;
}
if ((kcd->vc.rv3d->rflag & RV3D_CLIPPING) &&
- ED_view3d_clipping_test(kcd->vc.rv3d, p, TRUE))
+ ED_view3d_clipping_test(kcd->vc.rv3d, p, true))
{
continue;
}
@@ -1225,7 +1243,7 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
mul_m4_v3(kcd->ob->imat, view);
if (kcd->cut_through) {
- hitf = FALSE;
+ f_hit = NULL;
}
else {
/* check if this point is visible in the viewport */
@@ -1249,15 +1267,15 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
add_v3_v3(p1, no);
/* ray cast */
- hitf = BMBVH_RayCast(bmtree, p1, no, NULL, NULL);
+ f_hit = BMBVH_RayCast(bmtree, p1, no, NULL, NULL);
}
/* ok, if visible add the new point */
- if (!hitf && !BLI_smallhash_haskey(ehash, (intptr_t)kfe)) {
+ if (!f_hit && !BLI_smallhash_haskey(ehash, (intptr_t)kfe)) {
BMEdgeHit hit;
- if (len_squared_v3v3(p, kcd->curr.co) < depsilon_squared ||
- len_squared_v3v3(p, kcd->prev.co) < depsilon_squared)
+ if (len_squared_v3v3(p, kcd->curr.co) < depsilon_sq ||
+ len_squared_v3v3(p, kcd->prev.co) < depsilon_sq)
{
continue;
}
@@ -1319,12 +1337,12 @@ static void knife_bgl_get_mats(KnifeTool_OpData *UNUSED(kcd), bglMats *mats)
//copy_m4_m4(mats->projection, kcd->vc.rv3d->winmat);
}
-/* Calculate maximum excursion (doubled) from (0,0,0) of mesh */
+/* Calculate maximum excursion from (0,0,0) of mesh */
static void calc_ortho_extent(KnifeTool_OpData *kcd)
{
BMIter iter;
BMVert *v;
- BMesh* bm = kcd->em->bm;
+ BMesh *bm = kcd->em->bm;
float max_xyz = 0.0f;
int i;
@@ -1332,7 +1350,19 @@ static void calc_ortho_extent(KnifeTool_OpData *kcd)
for (i = 0; i < 3; i++)
max_xyz = max_ff(max_xyz, fabs(v->co[i]));
}
- kcd->ortho_extent = 2 * max_xyz;
+ kcd->ortho_extent = max_xyz;
+}
+
+/* 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)
+{
+ float closest[3];
+ const float origin[3] = {0.0f, 0.0f, 0.0f};
+
+ closest_to_line_v3(closest, origin, v1, v2);
+ dist_ensure_v3_v3fl(v1, closest, d);
+ dist_ensure_v3_v3fl(v2, closest, d);
}
/* Finds visible (or all, if cutting through) edges that intersects the current screen drag line */
@@ -1359,7 +1389,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
knife_project_v3(kcd, v1, s1);
knife_project_v3(kcd, v2, s2);
- if (len_v2v2(s1, s2) < 1)
+ if (len_squared_v2v2(s1, s2) < 1)
return;
/* unproject screen line */
@@ -1379,8 +1409,8 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
if (kcd->is_ortho) {
if (kcd->ortho_extent == 0.0f)
calc_ortho_extent(kcd);
- limit_dist_v3(v1, v3, kcd->ortho_extent + 10.0f);
- limit_dist_v3(v2, v4, kcd->ortho_extent + 10.0f);
+ clip_to_ortho_planes(v1, v3, kcd->ortho_extent + 10.0f);
+ clip_to_ortho_planes(v2, v4, kcd->ortho_extent + 10.0f);
}
BLI_smallhash_init(ehash);
@@ -1412,17 +1442,14 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
/* this works but gives numeric problems [#33400] */
#if 0
-static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2],
+static void knife_input_ray_cast(KnifeTool_OpData *kcd, const float mval[2],
float r_origin[3], float r_ray[3])
{
bglMats mats;
- float mval[2], imat[3][3];
+ float imat[3][3];
knife_bgl_get_mats(kcd, &mats);
- mval[0] = (float)mval_i[0];
- mval[1] = (float)mval_i[1];
-
/* unproject to find view ray */
ED_view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f);
@@ -1444,29 +1471,25 @@ static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2],
}
#endif
-static void knife_input_ray_segment(KnifeTool_OpData *kcd, const int mval_i[2], const float ofs,
+static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2], const float ofs,
float r_origin[3], float r_origin_ofs[3])
{
bglMats mats;
- float mval[2];
knife_bgl_get_mats(kcd, &mats);
- mval[0] = (float)mval_i[0];
- mval[1] = (float)mval_i[1];
-
/* unproject to find view ray */
ED_view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f);
ED_view3d_unproject(&mats, r_origin_ofs, mval[0], mval[1], ofs);
/* transform into object space */
- invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
+ invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
mul_m4_v3(kcd->ob->imat, r_origin);
mul_m4_v3(kcd->ob->imat, r_origin_ofs);
}
-static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float cageco[3], int *is_space)
+static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float cageco[3], bool *is_space)
{
BMFace *f;
float dist = KMAXDIST;
@@ -1475,7 +1498,7 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float
float ray[3];
/* unproject to find view ray */
- knife_input_ray_segment(kcd, kcd->vc.mval, 1.0f, origin, origin_ofs);
+ knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
sub_v3_v3v3(ray, origin_ofs, origin);
f = BMBVH_RayCast(kcd->bmbvh, origin, ray, co, cageco);
@@ -1484,13 +1507,15 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float
*is_space = !f;
if (!f) {
- /* try to use backbuffer selection method if ray casting failed */
- f = EDBM_face_find_nearest(&kcd->vc, &dist);
+ if (kcd->is_interactive) {
+ /* try to use backbuffer selection method if ray casting failed */
+ f = EDBM_face_find_nearest(&kcd->vc, &dist);
- /* cheat for now; just put in the origin instead
- * of a true coordinate on the face.
- * This just puts a point 1.0f infront of the view. */
- add_v3_v3v3(co, origin, ray);
+ /* cheat for now; just put in the origin instead
+ * of a true coordinate on the face.
+ * This just puts a point 1.0f infront of the view. */
+ add_v3_v3v3(co, origin, ray);
+ }
}
return f;
@@ -1498,18 +1523,21 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float
/* find the 2d screen space density of vertices within a radius. used to scale snapping
* distance for picking edges/verts.*/
-static int knife_sample_screen_density(KnifeTool_OpData *kcd, float radius)
+static int knife_sample_screen_density(KnifeTool_OpData *kcd, const float radius)
{
BMFace *f;
- int is_space;
+ bool is_space;
float co[3], cageco[3], sco[3];
+ BLI_assert(kcd->is_interactive == true);
+
f = knife_find_closest_face(kcd, co, cageco, &is_space);
if (f && !is_space) {
+ const float radius_sq = radius * radius;
ListBase *lst;
Ref *ref;
- float dis;
+ float dis_sq;
int c = 0;
knife_project_v3(kcd, cageco, sco);
@@ -1524,10 +1552,10 @@ static int knife_sample_screen_density(KnifeTool_OpData *kcd, float radius)
knife_project_v3(kcd, kfv->cageco, kfv->sco);
- dis = len_v2v2(kfv->sco, sco);
- if (dis < radius) {
+ dis_sq = len_squared_v2v2(kfv->sco, sco);
+ if (dis_sq < radius_sq) {
if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
- if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, TRUE) == 0) {
+ if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, true) == 0) {
c++;
}
}
@@ -1548,7 +1576,14 @@ static int knife_sample_screen_density(KnifeTool_OpData *kcd, float radius)
* surrounding mesh (in screen space)*/
static float knife_snap_size(KnifeTool_OpData *kcd, float maxsize)
{
- float density = (float)knife_sample_screen_density(kcd, maxsize * 2.0f);
+ float density;
+
+ if (kcd->is_interactive) {
+ density = (float)knife_sample_screen_density(kcd, maxsize * 2.0f);
+ }
+ else {
+ density = 1.0f;
+ }
if (density < 1.0f)
density = 1.0f;
@@ -1557,7 +1592,7 @@ static float knife_snap_size(KnifeTool_OpData *kcd, float maxsize)
}
/* p is closest point on edge to the mouse cursor */
-static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], float cagep[3], BMFace **fptr, int *is_space)
+static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], float cagep[3], BMFace **fptr, bool *is_space)
{
BMFace *f;
float co[3], cageco[3], sco[3], maxdist = knife_snap_size(kcd, kcd->ethresh);
@@ -1599,7 +1634,7 @@ static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], flo
interp_v3_v3v3(vec, kfe->v1->cageco, kfe->v2->cageco, lambda);
- if (ED_view3d_clipping_test(kcd->vc.rv3d, vec, TRUE) == 0) {
+ if (ED_view3d_clipping_test(kcd->vc.rv3d, vec, true) == 0) {
cure = kfe;
curdis = dis;
}
@@ -1633,8 +1668,8 @@ static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], flo
/* update mouse coordinates to the snapped-to edge's screen coordinates
* this is important for angle snap, which uses the previous mouse position */
edgesnap = new_knife_vert(kcd, p, cagep);
- kcd->curr.mval[0] = (int)edgesnap->sco[0];
- kcd->curr.mval[1] = (int)edgesnap->sco[1];
+ kcd->curr.mval[0] = edgesnap->sco[0];
+ kcd->curr.mval[1] = edgesnap->sco[1];
}
else {
@@ -1653,7 +1688,7 @@ static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], flo
/* find a vertex near the mouse cursor, if it exists */
static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], float cagep[3], BMFace **fptr,
- int *is_space)
+ bool *is_space)
{
BMFace *f;
float co[3], cageco[3], sco[3], maxdist = knife_snap_size(kcd, kcd->vthresh);
@@ -1669,10 +1704,11 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo
kcd->curr.bmface = f;
if (f) {
+ const float maxdist_sq = maxdist * maxdist;
ListBase *lst;
Ref *ref;
KnifeVert *curv = NULL;
- float dis, curdis = FLT_MAX;
+ float dis_sq, curdis_sq = FLT_MAX;
knife_project_v3(kcd, cageco, sco);
@@ -1686,17 +1722,17 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo
knife_project_v3(kcd, kfv->cageco, kfv->sco);
- dis = len_v2v2(kfv->sco, sco);
- if (dis < curdis && dis < maxdist) {
+ dis_sq = len_squared_v2v2(kfv->sco, sco);
+ if (dis_sq < curdis_sq && dis_sq < maxdist_sq) {
if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
- if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, TRUE) == 0) {
+ if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, true) == 0) {
curv = kfv;
- curdis = dis;
+ curdis_sq = dis_sq;
}
}
else {
curv = kfv;
- curdis = dis;
+ curdis_sq = dis_sq;
}
}
}
@@ -1712,8 +1748,8 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo
/* update mouse coordinates to the snapped-to vertex's screen coordinates
* this is important for angle snap, which uses the previous mouse position */
- kcd->curr.mval[0] = (int)curv->sco[0];
- kcd->curr.mval[1] = (int)curv->sco[1];
+ kcd->curr.mval[0] = curv->sco[0];
+ kcd->curr.mval[1] = curv->sco[1];
}
return curv;
@@ -1732,48 +1768,54 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo
return NULL;
}
+/* update both kcd->curr.mval and kcd->mval to snap to required angle */
static void knife_snap_angle(KnifeTool_OpData *kcd)
{
- int dx, dy;
+ float dx, dy;
float w, abs_tan;
- dx = kcd->vc.mval[0] - kcd->prev.mval[0];
- dy = kcd->vc.mval[1] - kcd->prev.mval[1];
- if (dx == 0 || dy == 0)
+ dx = kcd->curr.mval[0] - kcd->prev.mval[0];
+ dy = kcd->curr.mval[1] - kcd->prev.mval[1];
+ if (dx == 0.0f && dy == 0.0f)
return;
- w = (float)dy / (float)dx;
+ if (dx == 0.0f) {
+ kcd->angle_snapping = ANGLE_90;
+ kcd->curr.mval[0] = kcd->prev.mval[0];
+ }
+
+ w = dy / dx;
abs_tan = fabsf(w);
if (abs_tan <= 0.4142f) { /* tan(22.5 degrees) = 0.4142 */
kcd->angle_snapping = ANGLE_0;
- kcd->vc.mval[1] = kcd->prev.mval[1];
+ kcd->curr.mval[1] = kcd->prev.mval[1];
}
else if (abs_tan < 2.4142f) { /* tan(67.5 degrees) = 2.4142 */
if (w > 0) {
kcd->angle_snapping = ANGLE_45;
- kcd->vc.mval[1] = kcd->prev.mval[1] + dx;
+ kcd->curr.mval[1] = kcd->prev.mval[1] + dx;
}
else {
kcd->angle_snapping = ANGLE_135;
- kcd->vc.mval[1] = kcd->prev.mval[1] - dx;
+ kcd->curr.mval[1] = kcd->prev.mval[1] - dx;
}
}
else {
kcd->angle_snapping = ANGLE_90;
- kcd->vc.mval[0] = kcd->prev.mval[0];
+ kcd->curr.mval[0] = kcd->prev.mval[0];
}
+
+ copy_v2_v2(kcd->mval, kcd->curr.mval);
}
/* update active knife edge/vert pointers */
static int knife_update_active(KnifeTool_OpData *kcd)
{
+ knife_pos_data_clear(&kcd->curr);
+ copy_v2_v2(kcd->curr.mval, kcd->mval);
if (kcd->angle_snapping != ANGLE_FREE && kcd->mode == MODE_DRAGGING)
knife_snap_angle(kcd);
- knife_pos_data_clear(&kcd->curr);
- kcd->curr.mval[0] = kcd->vc.mval[0];
- kcd->curr.mval[1] = kcd->vc.mval[1];
-
/* XXX knife_snap_angle updates the view coordinate mouse values to constrained angles,
* which current mouse values are set to current mouse values are then used
* for vertex and edge snap detection, without regard to the exact angle constraint */
@@ -1791,7 +1833,7 @@ static int knife_update_active(KnifeTool_OpData *kcd)
float origin[3];
float origin_ofs[3];
- knife_input_ray_segment(kcd, kcd->vc.mval, 1.0f, origin, origin_ofs);
+ knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
closest_to_line_v3(kcd->curr.cage, kcd->prev.cage, origin_ofs, origin);
}
@@ -1840,7 +1882,7 @@ static void remerge_faces(KnifeTool_OpData *kcd)
BMOperator bmop;
int idx;
- BMO_op_initf(bm, &bmop, "beautify_fill faces=%ff constrain_edges=%fe", FACE_NEW, BOUNDARY);
+ BMO_op_initf(bm, &bmop, "beautify_fill faces=%ff edges=%Fe", FACE_NEW, BOUNDARY);
BMO_op_exec(bm, &bmop);
BMO_slot_buffer_flag_enable(bm, &bmop, "geom.out", BM_FACE, FACE_NEW);
@@ -1891,7 +1933,7 @@ static void remerge_faces(KnifeTool_OpData *kcd)
if (BLI_array_count(faces) > 0) {
idx = BM_elem_index_get(faces[0]);
- f2 = BM_faces_join(bm, faces, BLI_array_count(faces), TRUE);
+ f2 = BM_faces_join(bm, faces, BLI_array_count(faces), true);
if (f2) {
BMO_elem_flag_enable(bm, f2, FACE_NEW);
BM_elem_index_set(f2, idx); /* set_dirty! *//* BMESH_TODO, check if this is valid or not */
@@ -1971,14 +2013,14 @@ static void knifenet_fill_faces(KnifeTool_OpData *kcd)
i++;
if (kfe->e && kfe->v1->v == kfe->e->v1 && kfe->v2->v == kfe->e->v2) {
- kfe->oe = kfe->e;
+ kfe->e_old = kfe->e;
continue;
}
j++;
if (kfe->e) {
- kfe->oe = kfe->e;
+ kfe->e_old = kfe->e;
BMO_elem_flag_enable(bm, kfe->e, DEL);
BMO_elem_flag_disable(bm, kfe->e, BOUNDARY);
@@ -2004,13 +2046,13 @@ static void knifenet_fill_faces(KnifeTool_OpData *kcd)
if (!kfe->v1 || !kfe->v2 || kfe->v1->inspace || kfe->v2->inspace)
continue;
- if (!(kfe->oe && kfe->v1->v == kfe->oe->v1 && kfe->v2->v == kfe->oe->v2))
+ if (!(kfe->e_old && kfe->v1->v == kfe->e_old->v1 && kfe->v2->v == kfe->e_old->v2))
continue;
k++;
BMO_elem_flag_enable(bm, kfe->e, BOUNDARY);
- kfe->oe = kfe->e;
+ kfe->e_old = kfe->e;
for (ref = kfe->faces.first; ref; ref = ref->next) {
f = ref->ref;
@@ -2073,7 +2115,7 @@ static void knifenet_fill_faces(KnifeTool_OpData *kcd)
if (sf_vert->poly_nr > 1 && sf_vert_last->poly_nr > 1) {
ScanFillEdge *sf_edge;
sf_edge = BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
- if (entry->kfe->oe)
+ if (entry->kfe->e_old)
sf_edge->f = SF_EDGE_BOUNDARY; /* mark as original boundary edge */
BMO_elem_flag_disable(bm, entry->kfe->e->v1, DEL);
@@ -2102,7 +2144,7 @@ static void knifenet_fill_faces(KnifeTool_OpData *kcd)
f2 = BM_face_create_quad_tri(bm,
v1, v2, v3, NULL,
- NULL, FALSE);
+ NULL, false);
BMO_elem_flag_enable(bm, f2, FACE_NEW);
@@ -2142,7 +2184,7 @@ static void knifenet_fill_faces(KnifeTool_OpData *kcd)
BM_elem_attrs_copy(bm, bm, f2, f);
BM_ITER_ELEM (l1, &liter1, f, BM_LOOPS_OF_FACE) {
- BM_loop_interp_from_face(bm, l1, f2, TRUE, TRUE);
+ BM_loop_interp_from_face(bm, l1, f2, true, true);
}
}
@@ -2216,15 +2258,15 @@ static void sort_by_frac_along(ListBase *lst, BMEdge *e)
/* The chain so far goes from an instantiated vertex to kfv (some may be reversed).
* If possible, complete the chain to another instantiated vertex and return 1, else return 0.
* The visited hash says which KnifeVert's have already been tried, not including kfv. */
-static int find_chain_search(KnifeTool_OpData *kcd, KnifeVert *kfv, ListBase *fedges, SmallHash *visited,
- ListBase *chain)
+static bool find_chain_search(KnifeTool_OpData *kcd, KnifeVert *kfv, ListBase *fedges, SmallHash *visited,
+ ListBase *chain)
{
Ref *r;
KnifeEdge *kfe;
KnifeVert *kfv_other;
if (kfv->v)
- return TRUE;
+ return true;
BLI_smallhash_insert(visited, (uintptr_t)kfv, NULL);
/* Try all possible next edges. Could either go through fedges
@@ -2241,22 +2283,22 @@ static int find_chain_search(KnifeTool_OpData *kcd, KnifeVert *kfv, ListBase *fe
if (kfv_other && !BLI_smallhash_haskey(visited, (uintptr_t)kfv_other)) {
knife_append_list(kcd, chain, kfe);
if (find_chain_search(kcd, kfv_other, fedges, visited, chain))
- return TRUE;
+ return true;
BLI_remlink(chain, chain->last);
}
}
- return FALSE;
+ return false;
}
static ListBase *find_chain_from_vertex(KnifeTool_OpData *kcd, KnifeEdge *kfe, BMVert *v, ListBase *fedges)
{
SmallHash visited_, *visited = &visited_;
ListBase *ans;
- int found;
+ bool found;
ans = knife_empty_list(kcd);
knife_append_list(kcd, ans, kfe);
- found = 0;
+ found = false;
BLI_smallhash_init(visited);
if (kfe->v1->v == v) {
BLI_smallhash_insert(visited, (uintptr_t)(kfe->v1), NULL);
@@ -2317,15 +2359,15 @@ static ListBase *find_chain(KnifeTool_OpData *kcd, ListBase *fedges)
/* The hole so far goes from kfvfirst to kfv (some may be reversed).
* If possible, complete the hole back to kfvfirst and return 1, else return 0.
* The visited hash says which KnifeVert's have already been tried, not including kfv or kfvfirst. */
-static int find_hole_search(KnifeTool_OpData *kcd, KnifeVert *kfvfirst, KnifeVert *kfv, ListBase *fedges,
- SmallHash *visited, ListBase *hole)
+static bool find_hole_search(KnifeTool_OpData *kcd, KnifeVert *kfvfirst, KnifeVert *kfv, ListBase *fedges,
+ SmallHash *visited, ListBase *hole)
{
Ref *r;
KnifeEdge *kfe, *kfelast;
KnifeVert *kfv_other;
if (kfv == kfvfirst)
- return TRUE;
+ return true;
BLI_smallhash_insert(visited, (uintptr_t)kfv, NULL);
kfelast = ((Ref *)hole->last)->ref;
@@ -2343,11 +2385,11 @@ static int find_hole_search(KnifeTool_OpData *kcd, KnifeVert *kfvfirst, KnifeVer
if (kfv_other && !BLI_smallhash_haskey(visited, (uintptr_t)kfv_other)) {
knife_append_list(kcd, hole, kfe);
if (find_hole_search(kcd, kfvfirst, kfv_other, fedges, visited, hole))
- return TRUE;
+ return true;
BLI_remlink(hole, hole->last);
}
}
- return FALSE;
+ return false;
}
/* Find a hole (simple cycle with no instantiated vertices).
@@ -2358,10 +2400,10 @@ static ListBase *find_hole(KnifeTool_OpData *kcd, ListBase *fedges)
Ref *r, *ref;
KnifeEdge *kfe;
SmallHash visited_, *visited = &visited_;
- int found;
+ bool found;
ans = NULL;
- found = FALSE;
+ found = false;
for (r = fedges->first; r && !found; r = r->next) {
kfe = r->ref;
@@ -2392,11 +2434,11 @@ static ListBase *find_hole(KnifeTool_OpData *kcd, ListBase *fedges)
}
/* Try to find "nice" diagonals - short, and far apart from each other.
- * If found, return TRUE and make a 'main chain' going across f which uses
+ * If found, return true and make a 'main chain' going across f which uses
* the two diagonals and one part of the hole, and a 'side chain' that
* completes the hole. */
-static int find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, ListBase **mainchain,
- ListBase **sidechain)
+static bool find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, ListBase **mainchain,
+ ListBase **sidechain)
{
float **fco, **hco;
BMVert **fv;
@@ -2408,14 +2450,14 @@ static int find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, Li
ListBase *chain;
BMVert *v;
BMIter iter;
- int nh, nf, i, j, k, m, ax, ay, ok, sep = 0 /* Quite warnings */, bestsep;
+ int nh, nf, i, j, k, m, ax, ay, sep = 0 /* Quite warnings */, bestsep;
int besti[2], bestj[2];
float d, bestd;
nh = BLI_countlist(hole);
nf = f->len;
if (nh < 2 || nf < 3)
- return 0;
+ return false;
/* Gather 2d projections of hole and face vertex coordinates.
* Use best-axis projection - not completely accurate, maybe revisit */
@@ -2476,18 +2518,20 @@ static int find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, Li
bestd = FLT_MAX;
}
for (j = 0; j < nf; j++) {
+ bool ok;
+
if (m == 1 && j == bestj[0])
continue;
d = len_squared_v2v2(hco[i], fco[j]);
if (d > bestd)
continue;
- ok = TRUE;
+ ok = true;
for (k = 0; k < nh && ok; k++) {
if (k == i || (k + 1) % nh == i)
continue;
if (isect_line_line_v2(hco[i], fco[j], hco[k], hco[(k + 1) % nh]))
- ok = FALSE;
+ ok = false;
}
if (!ok)
continue;
@@ -2495,7 +2539,7 @@ static int find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, Li
if (k == j || (k + 1) % nf == j)
continue;
if (isect_line_line_v2(hco[i], fco[j], fco[k], fco[(k + 1) % nf]))
- ok = FALSE;
+ ok = false;
}
if (ok) {
besti[m] = i;
@@ -2530,14 +2574,14 @@ static int find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, Li
}
*sidechain = chain;
- return TRUE;
+ return true;
}
else {
- return FALSE;
+ return false;
}
}
-static int knife_edge_in_face(KnifeTool_OpData *UNUSED(kcd), KnifeEdge *kfe, BMFace *f)
+static bool knife_edge_in_face(KnifeTool_OpData *UNUSED(kcd), KnifeEdge *kfe, BMFace *f)
{
/* BMesh *bm = kcd->em->bm; */ /* UNUSED */
BMVert *v1, *v2;
@@ -2547,7 +2591,7 @@ static int knife_edge_in_face(KnifeTool_OpData *UNUSED(kcd), KnifeEdge *kfe, BMF
int v1inside, v2inside;
if (!f)
- return FALSE;
+ return false;
v1 = kfe->v1->v;
v2 = kfe->v2->v;
@@ -2566,7 +2610,7 @@ static int knife_edge_in_face(KnifeTool_OpData *UNUSED(kcd), KnifeEdge *kfe, BMF
v1inside = l1 ? 0 : BM_face_point_inside_test(f, kfe->v1->co);
v2inside = l2 ? 0 : BM_face_point_inside_test(f, kfe->v2->co);
if ((l1 && v2inside) || (l2 && v1inside) || (v1inside && v2inside))
- return TRUE;
+ return true;
if (l1 && l2) {
/* Can have case where v1 and v2 are on shared chain between two faces.
* BM_face_legal_splits does visibility and self-intersection tests,
@@ -2575,7 +2619,7 @@ static int knife_edge_in_face(KnifeTool_OpData *UNUSED(kcd), KnifeEdge *kfe, BMF
mid_v3_v3v3(mid, kfe->v1->co, kfe->v2->co);
return BM_face_point_inside_test(f, mid);
}
- return FALSE;
+ return false;
}
/* Split face f with KnifeEdges on chain. f remains as one side, the face formed is put in *newface.
@@ -2616,7 +2660,7 @@ static void knife_make_chain_cut(KnifeTool_OpData *kcd, BMFace *f, ListBase *cha
*newface = NULL;
}
else {
- *newface = BM_face_split(bm, f, v1, v2, &lnew, NULL, TRUE);
+ *newface = BM_face_split(bm, f, v1, v2, &lnew, NULL, true);
}
}
else {
@@ -2628,7 +2672,7 @@ static void knife_make_chain_cut(KnifeTool_OpData *kcd, BMFace *f, ListBase *cha
for (l_iter = lnew->next, i = 0; i < nco; l_iter = l_iter->next, i++) {
BLI_assert(equals_v3v3(cos[i], l_iter->v->co));
if (kcd->select_result) {
- BM_edge_select_set(bm, l_iter->e, TRUE);
+ BM_edge_select_set(bm, l_iter->e, true);
}
kverts[i]->v = l_iter->v;
}
@@ -2638,7 +2682,7 @@ static void knife_make_chain_cut(KnifeTool_OpData *kcd, BMFace *f, ListBase *cha
/* the select chain above doesnt account for the first loop */
if (kcd->select_result) {
if (lnew) {
- BM_edge_select_set(bm, lnew->e, TRUE);
+ BM_edge_select_set(bm, lnew->e, true);
}
}
}
@@ -2675,7 +2719,7 @@ static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfe
if (fnew_kfedges->first)
knife_make_face_cuts(kcd, fnew, fnew_kfedges);
- /* find_chain should always remove edges if it returns TRUE,
+ /* find_chain should always remove edges if it returns true,
* but guard against infinite loop anyway */
count = BLI_countlist(kfedges);
if (count >= oldcount) {
@@ -2698,10 +2742,16 @@ static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfe
kfe = ((Ref *)sidechain->first)->ref;
if (knife_edge_in_face(kcd, kfe, f)) {
knife_make_chain_cut(kcd, f, sidechain, &fnew2);
+ if (fnew2 == NULL) {
+ return;
+ }
fhole = f;
}
else if (knife_edge_in_face(kcd, kfe, fnew)) {
knife_make_chain_cut(kcd, fnew, sidechain, &fnew2);
+ if (fnew2 == NULL) {
+ return;
+ }
fhole = fnew2;
}
else {
@@ -2735,7 +2785,7 @@ static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfe
knife_make_face_cuts(kcd, fnew2, fnew2_kfedges);
if (f == fhole)
break;
- /* find_hole should always remove edges if it returns TRUE,
+ /* find_hole should always remove edges if it returns true,
* but guard against infinite loop anyway */
count = BLI_countlist(kfedges);
if (count >= oldcount) {
@@ -2830,10 +2880,8 @@ static void knife_make_cuts(KnifeTool_OpData *kcd)
#endif
/* called on tool confirmation */
-static void knifetool_finish(bContext *C, wmOperator *op)
+static void knifetool_finish_ex(KnifeTool_OpData *kcd)
{
- KnifeTool_OpData *kcd = op->customdata;
-
#if SCANFILL_CUTS
knifenet_fill_faces(kcd);
#else
@@ -2841,21 +2889,12 @@ static void knifetool_finish(bContext *C, wmOperator *op)
#endif
EDBM_mesh_normals_update(kcd->em);
- EDBM_update_generic(C, kcd->em, TRUE);
+ EDBM_update_generic(kcd->em, true, true);
}
-
-/* copied from paint_image.c */
-static int project_knife_view_clip(View3D *v3d, RegionView3D *rv3d, float *clipsta, float *clipend)
+static void knifetool_finish(wmOperator *op)
{
- int orth = ED_view3d_clip_range_get(v3d, rv3d, clipsta, clipend);
-
- if (orth) { /* only needed for ortho */
- float fac = 2.0f / ((*clipend) - (*clipsta));
- *clipsta *= fac;
- *clipend *= fac;
- }
-
- return orth;
+ KnifeTool_OpData *kcd = op->customdata;
+ knifetool_finish_ex(kcd);
}
static void knife_recalc_projmat(KnifeTool_OpData *kcd)
@@ -2864,22 +2903,22 @@ static void knife_recalc_projmat(KnifeTool_OpData *kcd)
ED_view3d_ob_project_mat_get(kcd->ar->regiondata, kcd->ob, kcd->projmat);
//mult_m4_m4m4(kcd->projmat, kcd->vc.rv3d->winmat, kcd->vc.rv3d->viewmat);
- kcd->is_ortho = project_knife_view_clip(kcd->vc.v3d, kcd->vc.rv3d,
- &kcd->clipsta, &kcd->clipend);
+ kcd->is_ortho = ED_view3d_clip_range_get(kcd->vc.v3d, kcd->vc.rv3d,
+ &kcd->clipsta, &kcd->clipend, true);
}
/* called when modal loop selection is done... */
-static void knifetool_exit(bContext *C, wmOperator *op)
+static void knifetool_exit_ex(bContext *C, KnifeTool_OpData *kcd)
{
- KnifeTool_OpData *kcd = op->customdata;
-
if (!kcd)
return;
- WM_cursor_restore(CTX_wm_window(C));
+ if (kcd->is_interactive) {
+ WM_cursor_restore(CTX_wm_window(C));
- /* deactivate the extra drawing stuff in 3D-View */
- ED_region_draw_cb_exit(kcd->ar->type, kcd->draw_handle);
+ /* deactivate the extra drawing stuff in 3D-View */
+ ED_region_draw_cb_exit(kcd->ar->type, kcd->draw_handle);
+ }
/* free the custom data */
BLI_mempool_destroy(kcd->refs);
@@ -2904,6 +2943,11 @@ static void knifetool_exit(bContext *C, wmOperator *op)
/* destroy kcd itself */
MEM_freeN(kcd);
+}
+static void knifetool_exit(bContext *C, wmOperator *op)
+{
+ KnifeTool_OpData *kcd = op->customdata;
+ knifetool_exit_ex(C, kcd);
op->customdata = NULL;
}
@@ -2921,35 +2965,36 @@ static void cage_mapped_verts_callback(void *userData, int index, const float co
}
}
-static void knifetool_update_mval(KnifeTool_OpData *kcd, int mval[2])
+static void knifetool_update_mval(KnifeTool_OpData *kcd, const float mval[2])
{
knife_recalc_projmat(kcd);
- kcd->vc.mval[0] = mval[0];
- kcd->vc.mval[1] = mval[1];
+ copy_v2_v2(kcd->mval, mval);
if (knife_update_active(kcd)) {
ED_region_tag_redraw(kcd->ar);
}
}
+static void knifetool_update_mval_i(KnifeTool_OpData *kcd, const int mval_i[2])
+{
+ float mval[2] = {UNPACK2(mval_i)};
+ knifetool_update_mval(kcd, mval);
+}
+
/* called when modal loop selection gets set up... */
-static int knifetool_init(bContext *C, wmOperator *op, int UNUSED(do_cut))
+static void knifetool_init(bContext *C, KnifeTool_OpData *kcd,
+ const bool only_select, const bool cut_through, const bool is_interactive)
{
- KnifeTool_OpData *kcd;
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
DerivedMesh *cage, *final;
SmallHash shash;
void *data[3];
- const short only_select = RNA_boolean_get(op->ptr, "only_selected");
-
- /* alloc new customdata */
- kcd = op->customdata = MEM_callocN(sizeof(KnifeTool_OpData), "knifetool Modal Op Data");
/* assign the drawing handle for drawing preview line... */
kcd->ob = obedit;
kcd->ar = CTX_wm_region(C);
- kcd->draw_handle = ED_region_draw_cb_activate(kcd->ar->type, knifetool_draw, kcd, REGION_DRAW_POST_VIEW);
+
em_setup_viewcontext(C, &kcd->vc);
kcd->em = BMEdit_FromObject(kcd->ob);
@@ -2975,7 +3020,7 @@ static int knifetool_init(bContext *C, wmOperator *op, int UNUSED(do_cut))
kcd->vthresh = KMAXDIST - 1;
kcd->ethresh = KMAXDIST;
- kcd->extend = 1;
+ kcd->extend = true;
knife_recalc_projmat(kcd);
@@ -2990,7 +3035,8 @@ static int knifetool_init(bContext *C, wmOperator *op, int UNUSED(do_cut))
kcd->kedgefacemap = BLI_ghash_ptr_new("knife origvertmap");
/* cut all the way through the mesh if use_occlude_geometry button not pushed */
- kcd->cut_through = !RNA_boolean_get(op->ptr, "use_occlude_geometry");
+ kcd->is_interactive = is_interactive;
+ kcd->cut_through = cut_through;
kcd->only_select = only_select;
/* can't usefully select resulting edges in face mode */
@@ -2999,9 +3045,11 @@ static int knifetool_init(bContext *C, wmOperator *op, int UNUSED(do_cut))
knife_pos_data_clear(&kcd->curr);
knife_pos_data_clear(&kcd->prev);
- knife_init_colors(&kcd->colors);
+ if (is_interactive) {
+ kcd->draw_handle = ED_region_draw_cb_activate(kcd->ar->type, knifetool_draw, kcd, REGION_DRAW_POST_VIEW);
- return 1;
+ knife_init_colors(&kcd->colors);
+ }
}
static int knifetool_cancel(bContext *C, wmOperator *op)
@@ -3011,21 +3059,25 @@ static int knifetool_cancel(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int knifetool_invoke(bContext *C, wmOperator *op, wmEvent *evt)
+static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ const bool only_select = RNA_boolean_get(op->ptr, "only_selected");
+ const bool cut_through = !RNA_boolean_get(op->ptr, "use_occlude_geometry");
+
KnifeTool_OpData *kcd;
view3d_operator_needs_opengl(C);
- if (!knifetool_init(C, op, 0))
- return OPERATOR_CANCELLED;
+ /* alloc new customdata */
+ kcd = op->customdata = MEM_callocN(sizeof(KnifeTool_OpData), __func__);
+
+ knifetool_init(C, kcd, only_select, cut_through, true);
/* add a modal handler for this operator - handles loop selection */
WM_cursor_modal(CTX_wm_window(C), BC_KNIFECURSOR);
WM_event_add_modal_handler(C, op);
- kcd = op->customdata;
- knifetool_update_mval(kcd, evt->mval);
+ knifetool_update_mval_i(kcd, event->mval);
knife_update_header(C, kcd);
@@ -3096,11 +3148,11 @@ wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf)
return keymap;
}
-static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
Object *obedit = CTX_data_edit_object(C);
KnifeTool_OpData *kcd = op->customdata;
- int do_refresh = FALSE;
+ bool do_refresh = false;
if (!obedit || obedit->type != OB_MESH || BMEdit_FromObject(obedit) != kcd->em) {
knifetool_exit(C, op);
@@ -3129,50 +3181,50 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event)
/* finish */
ED_region_tag_redraw(kcd->ar);
- knifetool_finish(C, op);
+ knifetool_finish(op);
knifetool_exit(C, op);
ED_area_headerprint(CTX_wm_area(C), NULL);
return OPERATOR_FINISHED;
case KNF_MODAL_MIDPOINT_ON:
- kcd->snap_midpoints = 1;
+ kcd->snap_midpoints = true;
knife_recalc_projmat(kcd);
knife_update_active(kcd);
knife_update_header(C, kcd);
ED_region_tag_redraw(kcd->ar);
- do_refresh = TRUE;
+ do_refresh = true;
break;
case KNF_MODAL_MIDPOINT_OFF:
- kcd->snap_midpoints = 0;
+ kcd->snap_midpoints = false;
knife_recalc_projmat(kcd);
knife_update_active(kcd);
knife_update_header(C, kcd);
ED_region_tag_redraw(kcd->ar);
- do_refresh = TRUE;
+ do_refresh = true;
break;
case KNF_MODEL_IGNORE_SNAP_ON:
ED_region_tag_redraw(kcd->ar);
- kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = 1;
+ kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = true;
knife_update_header(C, kcd);
- do_refresh = TRUE;
+ do_refresh = true;
break;
case KNF_MODEL_IGNORE_SNAP_OFF:
ED_region_tag_redraw(kcd->ar);
- kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = 0;
+ kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = false;
knife_update_header(C, kcd);
- do_refresh = TRUE;
+ do_refresh = true;
break;
case KNF_MODAL_ANGLE_SNAP_TOGGLE:
kcd->angle_snapping = !kcd->angle_snapping;
knife_update_header(C, kcd);
- do_refresh = TRUE;
+ do_refresh = true;
break;
case KNF_MODAL_CUT_THROUGH_TOGGLE:
kcd->cut_through = !kcd->cut_through;
knife_update_header(C, kcd);
- do_refresh = TRUE;
+ do_refresh = true;
break;
case KNF_MODAL_NEW_CUT:
ED_region_tag_redraw(kcd->ar);
@@ -3218,7 +3270,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event)
case MOUSEMOVE: /* mouse moved somewhere to select another loop */
if (kcd->mode != MODE_PANNING) {
- knifetool_update_mval(kcd, event->mval);
+ knifetool_update_mval_i(kcd, event->mval);
}
break;
@@ -3228,7 +3280,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event)
if (do_refresh) {
/* we don't really need to update mval,
* but this happens to be the best way to refresh at the moment */
- knifetool_update_mval(kcd, event->mval);
+ knifetool_update_mval_i(kcd, event->mval);
}
/* keep going until the user confirms */
@@ -3251,6 +3303,232 @@ void MESH_OT_knife_tool(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
- RNA_def_boolean(ot->srna, "use_occlude_geometry", TRUE, "Occlude Geometry", "Only cut the front most geometry");
- RNA_def_boolean(ot->srna, "only_selected", FALSE, "Only Selected", "Only cut selected geometry");
+ RNA_def_boolean(ot->srna, "use_occlude_geometry", true, "Occlude Geometry", "Only cut the front most geometry");
+ RNA_def_boolean(ot->srna, "only_selected", false, "Only Selected", "Only cut selected geometry");
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Knife tool as a utility function
+ * that can be used for internal slicing operations */
+
+/**
+ * Return a point inside the face.
+ *
+ * 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])
+{
+ int tottri = f->len - 2;
+ BMLoop **loops = BLI_array_alloca(loops, f->len);
+ int (*index)[3] = BLI_array_alloca(index, tottri);
+ int j;
+
+ float const *best_co[3] = {NULL};
+ float best_area = -1.0f;
+ bool ok = false;
+
+ tottri = BM_face_calc_tessellation(f, loops, index);
+ BLI_assert(tottri <= f->len - 2);
+
+ for (j = 0; j < tottri; j++) {
+ const float *p1 = loops[index[j][0]]->v->co;
+ const float *p2 = loops[index[j][1]]->v->co;
+ 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;
+ }
+ }
+
+ 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);
+ }
+}
+
+static bool edbm_mesh_knife_face_isect(ARegion *ar, LinkNode *polys, BMFace *f, float projmat[4][4])
+{
+ float cent_ss[2];
+ float cent[3];
+
+ edvm_mesh_knife_face_point(f, cent);
+
+ ED_view3d_project_float_v2_m4(ar, cent, cent_ss, projmat);
+
+ /* check */
+ {
+ LinkNode *p = polys;
+ int isect = 0;
+
+ while (p) {
+ const float (*mval_fl)[2] = p->link;
+ const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl);
+ isect += (int)isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1);
+ p = p->next;
+ }
+
+ if (isect % 2) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * \param use_tag When set, tag all faces inside the polylines.
+ */
+void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag)
+{
+ KnifeTool_OpData *kcd;
+
+ view3d_operator_needs_opengl(C);
+
+ /* init */
+ {
+ const bool only_select = false;
+ const bool cut_through = false;
+ const bool is_interactive = false; /* can enable for testing */
+
+ kcd = MEM_callocN(sizeof(KnifeTool_OpData), __func__);
+
+ knifetool_init(C, kcd, only_select, cut_through, is_interactive);
+
+ kcd->ignore_edge_snapping = true;
+ kcd->ignore_vert_snapping = true;
+
+ if (use_tag) {
+ BM_mesh_elem_hflag_enable_all(kcd->em->bm, BM_EDGE, BM_ELEM_TAG, false);
+ }
+ }
+
+ /* execute */
+ {
+ LinkNode *p = polys;
+
+ knife_recalc_projmat(kcd);
+
+ while (p) {
+ const float (*mval_fl)[2] = p->link;
+ const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl);
+ int i;
+
+ for (i = 0; i < mval_tot; i++) {
+ knifetool_update_mval(kcd, mval_fl[i]);
+ if (i == 0) {
+ knife_start_cut(kcd);
+ kcd->mode = MODE_DRAGGING;
+ }
+ else {
+ knife_add_cut(kcd);
+ }
+ }
+ knife_finish_cut(kcd);
+ kcd->mode = MODE_IDLE;
+ p = p->next;
+ }
+ }
+
+ /* finish */
+ {
+ knifetool_finish_ex(kcd);
+
+ /* tag faces inside! */
+ if (use_tag) {
+ BMesh *bm = kcd->em->bm;
+ float projmat[4][4];
+
+ BMEdge *e;
+ BMIter iter;
+
+ bool keep_search;
+
+ ED_view3d_ob_project_mat_get(kcd->ar->regiondata, kcd->ob, projmat);
+
+ /* use face-loop tag to store if we have intersected */
+#define F_ISECT_IS_UNKNOWN(f) BM_elem_flag_test(BM_FACE_FIRST_LOOP(f), BM_ELEM_TAG)
+#define F_ISECT_SET_UNKNOWN(f) BM_elem_flag_enable(BM_FACE_FIRST_LOOP(f), BM_ELEM_TAG)
+#define F_ISECT_SET_OUTSIDE(f) BM_elem_flag_disable(BM_FACE_FIRST_LOOP(f), BM_ELEM_TAG)
+ {
+ BMFace *f;
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ F_ISECT_SET_UNKNOWN(f);
+ BM_elem_flag_disable(f, BM_ELEM_TAG);
+ }
+ }
+
+ /* tag all faces linked to cut edges */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ /* check are we tagged?, then we are an original face */
+ if (BM_elem_flag_test(e, BM_ELEM_TAG) == false) {
+ 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)) {
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+ }
+ }
+ }
+ }
+
+ /* expand tags for faces which are not cut, but are inside the polys */
+ do {
+ BMFace *f;
+ keep_search = false;
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_TAG) == false && (F_ISECT_IS_UNKNOWN(f))) {
+ /* am I connected to a tagged face via an un-tagged edge (ie, not across a cut) */
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter = l_first;
+ bool found = false;
+
+ do {
+ if (BM_elem_flag_test(l_iter->e, BM_ELEM_TAG) != false) {
+ /* now check if the adjacent faces is tagged */
+ BMLoop *l_radial_iter = l_iter->radial_next;
+ if (l_radial_iter != l_iter) {
+ do {
+ if (BM_elem_flag_test(l_radial_iter->f, BM_ELEM_TAG)) {
+ found = true;
+ }
+ } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter && (found == false));
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_first && (found == false));
+
+ if (found) {
+ if (edbm_mesh_knife_face_isect(kcd->ar, polys, f, projmat)) {
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+ keep_search = true;
+ }
+ else {
+ /* don't loose time on this face again, set it as outside */
+ F_ISECT_SET_OUTSIDE(f);
+ }
+ }
+ }
+ }
+ } while (keep_search);
+
+#undef F_ISECT_IS_UNKNOWN
+#undef F_ISECT_SET_UNKNOWN
+#undef F_ISECT_SET_OUTSIDE
+
+ }
+
+ knifetool_exit_ex(C, kcd);
+ kcd = NULL;
+ }
}
diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c
new file mode 100644
index 00000000000..c8256914884
--- /dev/null
+++ b/source/blender/editors/mesh/editmesh_knife_project.c
@@ -0,0 +1,174 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/mesh/editmesh_knife_project.c
+ * \ingroup edmesh
+ */
+
+#include "DNA_curve_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+#include "BLI_linklist.h"
+#include "BLI_listbase.h"
+
+#include "BKE_library.h"
+#include "BKE_mesh.h"
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_tessmesh.h"
+#include "BKE_report.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "WM_types.h"
+
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "mesh_intern.h"
+
+
+static LinkNode *knifeproject_poly_from_object(ARegion *ar, Scene *scene, Object *ob, LinkNode *polys)
+{
+ DerivedMesh *dm;
+ bool dm_needsFree;
+
+ if (ob->type == OB_MESH || ob->derivedFinal) {
+ dm = ob->derivedFinal ? ob->derivedFinal : mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+ dm_needsFree = false;
+ }
+ else if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
+ dm = CDDM_from_curve(ob);
+ dm_needsFree = true;
+ }
+ else {
+ dm = NULL;
+ }
+
+ if (dm) {
+ ListBase nurbslist = {NULL, NULL};
+ float projmat[4][4];
+
+ BKE_mesh_to_curve_nurblist(dm, &nurbslist, 0); /* wire */
+ BKE_mesh_to_curve_nurblist(dm, &nurbslist, 1); /* boundary */
+
+ ED_view3d_ob_project_mat_get(ar->regiondata, ob, projmat);
+
+ if (nurbslist.first) {
+ Nurb *nu;
+ for (nu = nurbslist.first; nu; nu = nu->next) {
+ if (nu->bp) {
+ int a;
+ BPoint *bp;
+ bool is_cyclic = (nu->flagu & CU_NURB_CYCLIC) != 0;
+ float (*mval)[2] = MEM_mallocN(sizeof(*mval) * (nu->pntsu + is_cyclic), __func__);
+
+ for (bp = nu->bp, a = 0; a < nu->pntsu; a++, bp++) {
+ ED_view3d_project_float_v3_m4(ar, bp->vec, mval[a], projmat);
+ }
+ if (is_cyclic) {
+ copy_v2_v2(mval[a], mval[0]);
+ }
+
+ BLI_linklist_prepend(&polys, mval);
+ }
+ }
+ }
+
+ BKE_nurbList_free(&nurbslist);
+
+ if (dm_needsFree) {
+ dm->release(dm);
+ }
+ }
+
+
+ return polys;
+}
+
+static int knifeproject_exec(bContext *C, wmOperator *op)
+{
+ ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BMEdit_FromObject(obedit);
+
+ LinkNode *polys = NULL;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
+ {
+ if (ob != obedit) {
+ polys = knifeproject_poly_from_object(ar, scene, ob, polys);
+ }
+ }
+ CTX_DATA_END;
+
+ if (polys) {
+ EDBM_mesh_knife(C, polys, true);
+
+ /* select only tagged faces */
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
+
+ /* not essential, but switch out of vertex mode since the
+ * selected regions wont be nicely isolated after flushing.
+ * note: call after de-select to avoid selection flushing */
+ EDBM_selectmode_disable(scene, em, SCE_SELECT_VERTEX, SCE_SELECT_EDGE);
+
+ BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, BM_ELEM_TAG);
+
+ BM_mesh_select_mode_flush(em->bm);
+
+ BLI_linklist_freeN(polys);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No other selected objects found to use for projection");
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void MESH_OT_knife_project(wmOperatorType *ot)
+{
+ /* description */
+ ot->name = "Knife Project";
+ ot->idname = "MESH_OT_knife_project";
+ ot->description = "Use other objects outlines & boundaries to project knife cuts";
+
+ /* callbacks */
+ ot->exec = knifeproject_exec;
+ ot->poll = ED_operator_editmesh_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 dec45b7f326..ee1c274b154 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -28,46 +28,23 @@
* \ingroup edmesh
*/
-#include <float.h>
-#ifdef _MSC_VER
-# define _USE_MATH_DEFINES
-#endif
-#include <math.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdio.h>
-
-#include "DNA_ID.h"
#include "DNA_object_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
-#include "DNA_userdef_types.h"
#include "MEM_guardedalloc.h"
-#include "PIL_time.h"
-
#include "BLI_array.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLI_dynstr.h" /*for WM_operator_pystring */
-#include "BLI_utildefines.h"
-#include "BKE_blender.h"
+#include "BLF_translation.h"
+
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
-#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_report.h"
-#include "BKE_scene.h"
#include "BKE_tessmesh.h"
-#include "BKE_depsgraph.h"
#include "BIF_gl.h"
-#include "BIF_glutil.h" /* for paint cursor */
-
-#include "IMB_imbuf_types.h"
#include "ED_screen.h"
#include "ED_space_api.h"
@@ -78,8 +55,6 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "UI_interface.h"
-
#include "WM_api.h"
#include "WM_types.h"
@@ -102,8 +77,8 @@ typedef struct RingSelOpData {
BMEdge *eed;
NumInput num;
- int extend;
- int do_cut;
+ bool extend;
+ bool do_cut;
} RingSelOpData;
/* modal loop selection drawing callback */
@@ -181,18 +156,17 @@ static void edgering_find_order(BMEdge *lasteed, BMEdge *eed,
static void edgering_sel(RingSelOpData *lcd, int previewlines, int select)
{
BMEditMesh *em = lcd->em;
- BMEdge *startedge = lcd->eed;
- BMEdge *eed, *lasteed;
- BMVert *v[2][2], *lastv1;
+ BMEdge *eed_start = lcd->eed;
+ BMEdge *eed, *eed_last;
+ BMVert *v[2][2], *v_last;
BMWalker walker;
float (*edges)[2][3] = NULL;
BLI_array_declare(edges);
- float co[2][3];
int i, tot = 0;
memset(v, 0, sizeof(v));
- if (!startedge)
+ if (!eed_start)
return;
if (lcd->edges) {
@@ -211,9 +185,8 @@ static void edgering_sel(RingSelOpData *lcd, int previewlines, int select)
BMW_FLAG_TEST_HIDDEN,
BMW_NIL_LAY);
- eed = BMW_begin(&walker, startedge);
- for ( ; eed; eed = BMW_step(&walker)) {
- BM_edge_select_set(em->bm, eed, TRUE);
+ for (eed = BMW_begin(&walker, eed_start); eed; eed = BMW_step(&walker)) {
+ BM_edge_select_set(em->bm, eed, true);
}
BMW_end(&walker);
@@ -225,68 +198,57 @@ static void edgering_sel(RingSelOpData *lcd, int previewlines, int select)
BMW_FLAG_TEST_HIDDEN,
BMW_NIL_LAY);
- eed = startedge = BMW_begin(&walker, startedge);
- lastv1 = NULL;
- for (lasteed = NULL; eed; eed = BMW_step(&walker)) {
- if (lasteed) {
- if (lastv1) {
+ v_last = NULL;
+ eed_last = NULL;
+
+ for (eed = eed_start = BMW_begin(&walker, eed_start); eed; eed = BMW_step(&walker)) {
+ if (eed_last) {
+ if (v_last) {
v[1][0] = v[0][0];
v[1][1] = v[0][1];
}
else {
- v[1][0] = lasteed->v1;
- v[1][1] = lasteed->v2;
- lastv1 = lasteed->v1;
+ v[1][0] = eed_last->v1;
+ v[1][1] = eed_last->v2;
+ v_last = eed_last->v1;
}
- edgering_find_order(lasteed, eed, lastv1, v);
- lastv1 = v[0][0];
+ 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++) {
- co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0]) * (i / ((float)previewlines + 1)) + v[0][0]->co[0];
- co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1]) * (i / ((float)previewlines + 1)) + v[0][0]->co[1];
- co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2]) * (i / ((float)previewlines + 1)) + v[0][0]->co[2];
-
- co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0]) * (i / ((float)previewlines + 1)) + v[1][0]->co[0];
- co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1]) * (i / ((float)previewlines + 1)) + v[1][0]->co[1];
- co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2]) * (i / ((float)previewlines + 1)) + v[1][0]->co[2];
-
- copy_v3_v3(edges[tot][0], co[0]);
- copy_v3_v3(edges[tot][1], co[1]);
+ const float fac = (i / ((float)previewlines + 1));
+ interp_v3_v3v3(edges[tot][0], v[0][0]->co, v[0][1]->co, fac);
+ interp_v3_v3v3(edges[tot][1], v[1][0]->co, v[1][1]->co, fac);
tot++;
}
}
- lasteed = eed;
+ eed_last = eed;
}
#ifdef BMW_EDGERING_NGON
if (lasteed != startedge && BM_edge_share_face_check(lasteed, startedge)) {
#else
- if (lasteed != startedge && BM_edge_share_quad_check(lasteed, startedge)) {
+ if (eed_last != eed_start && BM_edge_share_quad_check(eed_last, eed_start)) {
#endif
v[1][0] = v[0][0];
v[1][1] = v[0][1];
- edgering_find_order(lasteed, startedge, lastv1, v);
+ edgering_find_order(eed_last, eed_start, v_last, v);
BLI_array_grow_items(edges, previewlines);
for (i = 1; i <= previewlines; i++) {
- if (!v[0][0] || !v[0][1] || !v[1][0] || !v[1][1])
+ const float fac = (i / ((float)previewlines + 1));
+
+ if (!v[0][0] || !v[0][1] || !v[1][0] || !v[1][1]) {
continue;
-
- co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0]) * (i / ((float)previewlines + 1)) + v[0][0]->co[0];
- co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1]) * (i / ((float)previewlines + 1)) + v[0][0]->co[1];
- co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2]) * (i / ((float)previewlines + 1)) + v[0][0]->co[2];
+ }
- co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0]) * (i / ((float)previewlines + 1)) + v[1][0]->co[0];
- co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1]) * (i / ((float)previewlines + 1)) + v[1][0]->co[1];
- co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2]) * (i / ((float)previewlines + 1)) + v[1][0]->co[2];
-
- copy_v3_v3(edges[tot][0], co[0]);
- copy_v3_v3(edges[tot][1], co[1]);
+ interp_v3_v3v3(edges[tot][0], v[0][0]->co, v[0][1]->co, fac);
+ interp_v3_v3v3(edges[tot][1], v[1][0]->co, v[1][1]->co, fac);
tot++;
}
}
@@ -314,9 +276,9 @@ static void ringsel_finish(bContext *C, wmOperator *op)
const int cuts = RNA_int_get(op->ptr, "number_cuts");
const float smoothness = 0.292f * RNA_float_get(op->ptr, "smoothness");
#ifdef BMW_EDGERING_NGON
- const int use_only_quads = FALSE;
+ const bool use_only_quads = false;
#else
- const int use_only_quads = TRUE;
+ const bool use_only_quads = false;
#endif
if (lcd->eed) {
@@ -331,25 +293,20 @@ static void ringsel_finish(bContext *C, wmOperator *op)
BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT,
smoothness, 0.0f, 0.0f,
cuts,
- SUBDIV_SELECT_LOOPCUT, SUBD_PATH, 0, TRUE,
+ SUBDIV_SELECT_LOOPCUT, SUBD_PATH, 0, true,
use_only_quads, 0);
+ /* tessface is already re-recalculated */
+ EDBM_update_generic(em, false, true);
+
/* force edge slide to edge select mode in in face select mode */
- if (em->selectmode & SCE_SELECT_FACE) {
- if (em->selectmode == SCE_SELECT_FACE)
- em->selectmode = SCE_SELECT_EDGE;
- else
- em->selectmode &= ~SCE_SELECT_FACE;
- CTX_data_tool_settings(C)->selectmode = em->selectmode;
- EDBM_selectmode_set(em);
-
- WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, CTX_data_scene(C));
+ if (EDBM_selectmode_disable(lcd->vc.scene, em, SCE_SELECT_FACE, SCE_SELECT_EDGE)) {
+ /* pass, the change will flush selection */
}
- else
+ else {
+ /* else flush explicitly */
EDBM_selectmode_flush(lcd->em);
-
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT | ND_DATA, lcd->ob->data);
- DAG_id_tag_update(lcd->ob->data, 0);
+ }
}
else {
/* XXX Is this piece of code ever used now? Simple loop select is now
@@ -386,7 +343,7 @@ static void ringsel_exit(bContext *UNUSED(C), wmOperator *op)
/* called when modal loop selection gets set up... */
-static int ringsel_init(bContext *C, wmOperator *op, int do_cut)
+static int ringsel_init(bContext *C, wmOperator *op, bool do_cut)
{
RingSelOpData *lcd;
@@ -422,7 +379,7 @@ static int ringcut_cancel(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int ringcut_invoke(bContext *C, wmOperator *op, wmEvent *evt)
+static int ringcut_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ScrArea *sa = CTX_wm_area(C);
Object *obedit = CTX_data_edit_object(C);
@@ -442,28 +399,25 @@ static int ringcut_invoke(bContext *C, wmOperator *op, wmEvent *evt)
WM_event_add_modal_handler(C, op);
lcd = op->customdata;
- lcd->vc.mval[0] = evt->mval[0];
- lcd->vc.mval[1] = evt->mval[1];
+ copy_v2_v2_int(lcd->vc.mval, event->mval);
edge = EDBM_edge_find_nearest(&lcd->vc, &dist);
if (edge != lcd->eed) {
lcd->eed = edge;
ringsel_find_edge(lcd, 1);
}
- ED_area_headerprint(sa,
- "Select a ring to be cut, "
- "use mouse-wheel or page-up/down for number of cuts, "
- "Hold Alt for smooth");
+ ED_area_headerprint(sa, IFACE_("Select a ring to be cut, use mouse-wheel or page-up/down for number of cuts, "
+ "hold Alt for smooth"));
return OPERATOR_RUNNING_MODAL;
}
-static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
float smoothness = RNA_float_get(op->ptr, "smoothness");
int cuts = RNA_int_get(op->ptr, "number_cuts");
RingSelOpData *lcd = op->customdata;
- int show_cuts = 0;
+ bool show_cuts = false;
view3d_operator_needs_opengl(C);
@@ -511,12 +465,12 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event)
cuts++;
RNA_int_set(op->ptr, "number_cuts", cuts);
ringsel_find_edge(lcd, cuts);
- show_cuts = TRUE;
+ show_cuts = true;
}
else {
smoothness = min_ff(smoothness + 0.05f, 4.0f);
RNA_float_set(op->ptr, "smoothness", smoothness);
- show_cuts = TRUE;
+ show_cuts = true;
}
ED_region_tag_redraw(lcd->ar);
@@ -531,17 +485,18 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event)
cuts = max_ii(cuts - 1, 0);
RNA_int_set(op->ptr, "number_cuts", cuts);
ringsel_find_edge(lcd, cuts);
- show_cuts = TRUE;
+ show_cuts = true;
}
else {
smoothness = max_ff(smoothness - 0.05f, 0.0f);
RNA_float_set(op->ptr, "smoothness", smoothness);
- show_cuts = TRUE;
+ show_cuts = true;
}
ED_region_tag_redraw(lcd->ar);
break;
- case MOUSEMOVE: { /* mouse moved somewhere to select another loop */
+ case MOUSEMOVE: /* mouse moved somewhere to select another loop */
+ {
float dist = 75.0f;
BMEdge *edge;
@@ -573,7 +528,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event)
RNA_int_set(op->ptr, "number_cuts", cuts);
ringsel_find_edge(lcd, cuts);
- show_cuts = TRUE;
+ show_cuts = true;
ED_region_tag_redraw(lcd->ar);
}
@@ -581,7 +536,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event)
if (show_cuts) {
char buf[64];
- BLI_snprintf(buf, sizeof(buf), "Number of Cuts: %d, Smooth: %.2f (Alt)", cuts, smoothness);
+ BLI_snprintf(buf, sizeof(buf), IFACE_("Number of Cuts: %d, Smooth: %.2f (Alt)"), cuts, smoothness);
ED_area_headerprint(CTX_wm_area(C), buf);
}
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index 9b8f90bc7cf..0ea02f371f0 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -31,21 +31,18 @@
#include "MEM_guardedalloc.h"
-#include "DNA_scene_types.h"
#include "DNA_object_types.h"
-#include "RNA_define.h"
-#include "RNA_access.h"
-
#include "BLI_math.h"
#include "BLI_array.h"
#include "BKE_context.h"
-#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_tessmesh.h"
-#include "WM_api.h"
+#include "RNA_define.h"
+#include "RNA_access.h"
+
#include "WM_types.h"
#include "ED_mesh.h"
@@ -210,7 +207,7 @@ static BMEdge *edbm_ripsel_edge_mark_step(BMVert *v, const int uid)
BM_edge_loop_pair(e, &l_a, &l_b); /* no need to check, we know this will be true */
- /* so (IS_VISIT_DONE == TRUE) */
+ /* so (IS_VISIT_DONE == true) */
BM_elem_index_set(l_a, uid);
BM_elem_index_set(l_b, uid);
@@ -249,7 +246,7 @@ static EdgeLoopPair *edbm_ripsel_looptag_helper(BMesh *bm)
}
/* set contiguous loops ordered 'uid' values for walking after split */
- while (TRUE) {
+ while (true) {
int tot = 0;
BMIter eiter;
BMEdge *e_step;
@@ -376,7 +373,7 @@ static void edbm_ripsel_deselect_helper(BMesh *bm, EdgeLoopPair *eloop_pairs,
e = (score_a > score_b) ? lp->l_a->e : lp->l_b->e;
v_prev = edbm_ripsel_edloop_pair_start_vert(e);
for (; e; e = edbm_ripsel_edge_uid_step(e, &v_prev)) {
- BM_edge_select_set(bm, e, FALSE);
+ BM_edge_select_set(bm, e, false);
}
}
}
@@ -489,9 +486,9 @@ static void edbm_tagged_loop_pairs_do_fill_faces(BMesh *bm, UnorderedLoopPair *u
}
/* face should never exist */
- BLI_assert(BM_face_exists(f_verts, f_verts[3] ? 4 : 3, &f) == FALSE);
+ BLI_assert(BM_face_exists(f_verts, f_verts[3] ? 4 : 3, &f) == false);
- f = BM_face_create_quad_tri_v(bm, f_verts, f_verts[3] ? 4 : 3, f_example, FALSE);
+ f = BM_face_create_quad_tri_v(bm, f_verts, f_verts[3] ? 4 : 3, f_example, false);
l_iter = BM_FACE_FIRST_LOOP(f);
@@ -502,16 +499,9 @@ static void edbm_tagged_loop_pairs_do_fill_faces(BMesh *bm, UnorderedLoopPair *u
BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter);
}
else {
- if (v_shared == f_verts[0]) {
- BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next;
- BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next;
- BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter);
- }
- else {
- BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next;
- BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next;
- BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter);
- }
+ BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next;
+ BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next;
+ BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter);
}
}
@@ -521,29 +511,29 @@ static void edbm_tagged_loop_pairs_do_fill_faces(BMesh *bm, UnorderedLoopPair *u
/* --- end 'face-fill' code --- */
-static int edbm_rip_call_edgesplit(BMEditMesh *em, wmOperator *op)
+static bool edbm_rip_call_edgesplit(BMEditMesh *em, wmOperator *op)
{
BMOperator bmop;
if (!EDBM_op_init(em, &bmop, op, "split_edges edges=%he verts=%hv use_verts=%b",
- BM_ELEM_TAG, BM_ELEM_SELECT, TRUE))
+ BM_ELEM_TAG, BM_ELEM_SELECT, true))
{
- return FALSE;
+ return false;
}
BMO_op_exec(em->bm, &bmop);
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
- return FALSE;
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ return false;
}
- return TRUE;
+ return true;
}
/**
* This is the main vert ripping function (rip when one vertex is selected)
*/
-static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event)
+static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *event)
{
- const int do_fill = RNA_boolean_get(op->ptr, "use_fill");
+ const bool do_fill = RNA_boolean_get(op->ptr, "use_fill");
UnorderedLoopPair *fill_uloop_pairs = NULL;
Object *obedit = CTX_data_edit_object(C);
ARegion *ar = CTX_wm_region(C);
@@ -559,7 +549,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event)
float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]};
float dist = FLT_MAX;
float d;
- int is_wire;
+ bool is_wire;
BMEditSelection ese;
int totboundary_edge = 0;
@@ -595,7 +585,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event)
* otherwise we can't a face away from a wire edge */
totboundary_edge += (is_boundary != 0 || 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_boundary == false && BM_edge_is_manifold(e)) {
d = edbm_rip_edgedist(ar, projectMat, e->v1->co, e->v2->co, fmval, INSET_DEFAULT);
if (d < dist) {
dist = d;
@@ -650,22 +640,22 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event)
* - the boundary edge total is greater then 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) ||
- (is_wire == TRUE && totboundary_edge > 1))
+ if ((is_wire == false && totboundary_edge > 2) ||
+ (is_wire == true && totboundary_edge > 1))
{
BMVert **vout;
int vout_len;
- BM_vert_select_set(bm, v, FALSE);
+ BM_vert_select_set(bm, v, false);
- if (bmesh_vert_separate(bm, v, &vout, &vout_len) == FALSE) {
+ if (bmesh_vert_separate(bm, v, &vout, &vout_len) == false) {
BKE_report(op->reports, RPT_ERROR, "Error ripping vertex from faces");
return OPERATOR_CANCELLED;
}
else if (vout_len < 2) {
MEM_freeN(vout);
/* set selection back to avoid active-unselected vertex */
- BM_vert_select_set(bm, v, TRUE);
+ BM_vert_select_set(bm, v, true);
/* should never happen */
BKE_report(op->reports, RPT_ERROR, "Error ripping vertex from faces");
return OPERATOR_CANCELLED;
@@ -683,7 +673,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event)
* either by its face corner, or connected edge (when no faces are attached) */
for (i = 0; i < vout_len; i++) {
- if (BM_vert_is_wire(vout[i]) == FALSE) {
+ if (BM_vert_is_wire(vout[i]) == false) {
/* find the best face corner */
BM_ITER_ELEM (l, &iter, vout[i], BM_LOOPS_OF_VERT) {
if (!BM_elem_flag_test(l->f, BM_ELEM_HIDDEN)) {
@@ -719,7 +709,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event)
/* select the vert from the best region */
v = vout[vi_best];
- BM_vert_select_set(bm, v, TRUE);
+ BM_vert_select_set(bm, v, true);
if (ese.ele) {
BM_select_history_store(bm, v);
@@ -814,7 +804,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event)
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
/* disable by default, re-enable winner at end */
- BM_vert_select_set(bm, v, FALSE);
+ BM_vert_select_set(bm, v, false);
BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
/* calculate a point in the face, rather then calculate the middle,
@@ -839,7 +829,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event)
}
if (v_best) {
- BM_vert_select_set(bm, v_best, TRUE);
+ BM_vert_select_set(bm, v_best, true);
if (ese.ele) {
BM_select_history_store(bm, v_best);
}
@@ -863,9 +853,9 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event)
/**
* This is the main edge ripping function
*/
-static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, wmEvent *event)
+static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, const wmEvent *event)
{
- const int do_fill = RNA_boolean_get(op->ptr, "use_fill");
+ const bool do_fill = RNA_boolean_get(op->ptr, "use_fill");
UnorderedLoopPair *fill_uloop_pairs = NULL;
Object *obedit = CTX_data_edit_object(C);
ARegion *ar = CTX_wm_region(C);
@@ -888,14 +878,14 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, wmEvent *event)
/* expand edge selection */
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- int all_manifold;
+ bool all_manifold;
int totedge_manifold; /* manifold, visible edges */
int i;
e2 = NULL;
i = 0;
totedge_manifold = 0;
- all_manifold = TRUE;
+ all_manifold = true;
BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
if (!BM_edge_is_wire(e) &&
@@ -911,8 +901,8 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, wmEvent *event)
}
/** #BM_vert_other_disk_edge has no hidden checks so don't check hidden here */
- if ((all_manifold == TRUE) && (BM_edge_is_manifold(e) == FALSE)) {
- all_manifold = FALSE;
+ if ((all_manifold == true) && (BM_edge_is_manifold(e) == false)) {
+ all_manifold = false;
}
}
@@ -921,7 +911,7 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, wmEvent *event)
/* 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)) {
+ if ((totedge_manifold == 4 || totedge_manifold == 3) || (all_manifold == false)) {
BMLoop *l_a = e2->l;
BMLoop *l_b = l_a->radial_next;
@@ -991,7 +981,7 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, wmEvent *event)
}
/* based on mouse cursor position, it defines how is being ripped */
-static int edbm_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int edbm_rip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
@@ -1044,7 +1034,7 @@ static int edbm_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_CANCELLED;
}
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -1066,6 +1056,6 @@ void MESH_OT_rip(wmOperatorType *ot)
/* to give to transform */
Transform_Properties(ot, P_PROPORTIONAL);
- RNA_def_boolean(ot->srna, "mirror", FALSE, "Mirror Editing", "");
- RNA_def_boolean(ot->srna, "use_fill", FALSE, "Fill", "Fill the ripped region");
+ RNA_def_boolean(ot->srna, "mirror", false, "Mirror Editing", "");
+ RNA_def_boolean(ot->srna, "use_fill", false, "Fill", "Fill the ripped region");
}
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index a98345cacec..9474c051cee 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -40,9 +40,9 @@
#include "BKE_context.h"
#include "BKE_displist.h"
-#include "BKE_depsgraph.h"
#include "BKE_report.h"
#include "BKE_paint.h"
+#include "BKE_mesh.h"
#include "BKE_tessmesh.h"
#include "IMB_imbuf_types.h"
@@ -56,9 +56,7 @@
#include "ED_mesh.h"
#include "ED_screen.h"
-#include "ED_util.h"
#include "ED_uvedit.h"
-#include "ED_object.h"
#include "ED_view3d.h"
#include "BIF_gl.h"
@@ -66,6 +64,9 @@
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "GPU_extensions.h"
#include "mesh_intern.h"
@@ -73,7 +74,7 @@
/* ****************************** MIRROR **************** */
-void EDBM_select_mirrored(Object *UNUSED(obedit), BMEditMesh *em, int extend)
+void EDBM_select_mirrored(Object *UNUSED(obedit), BMEditMesh *em, bool extend)
{
BMVert *v1, *v2;
BMIter iter;
@@ -87,7 +88,7 @@ void EDBM_select_mirrored(Object *UNUSED(obedit), BMEditMesh *em, int extend)
}
}
- EDBM_verts_mirror_cache_begin(em, TRUE);
+ EDBM_verts_mirror_cache_begin(em, true);
if (!extend)
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
@@ -98,7 +99,7 @@ void EDBM_select_mirrored(Object *UNUSED(obedit), BMEditMesh *em, int extend)
v2 = EDBM_verts_mirror_get(em, v1);
if (v2 && !BM_elem_flag_test(v2, BM_ELEM_HIDDEN)) {
- BM_vert_select_set(em->bm, v2, TRUE);
+ BM_vert_select_set(em->bm, v2, true);
}
}
@@ -107,21 +108,23 @@ void EDBM_select_mirrored(Object *UNUSED(obedit), BMEditMesh *em, int extend)
void EDBM_automerge(Scene *scene, Object *obedit, int update)
{
- BMEditMesh *em;
if ((scene->toolsettings->automerge) &&
(obedit && obedit->type == OB_MESH))
{
- em = BMEdit_FromObject(obedit);
- if (!em)
+ int ok;
+ BMEditMesh *em = BMEdit_FromObject(obedit);
+
+ if (!em) {
return;
+ }
+
+ ok = BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS,
+ "automerge verts=%hv dist=%f",
+ BM_ELEM_SELECT, scene->toolsettings->doublimit);
- BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS,
- "automerge verts=%hv dist=%f",
- BM_ELEM_SELECT, scene->toolsettings->doublimit);
- if (update) {
- DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
- BMEdit_RecalcTessellation(em);
+ if (LIKELY(ok) && update) {
+ EDBM_update_generic(em, true, true);
}
}
}
@@ -181,19 +184,19 @@ static void draw_triangulated(const int mcords[][2], const short tot)
/* reads rect, and builds selection array for quick lookup */
/* returns if all is OK */
-int EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
+bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
{
struct ImBuf *buf;
unsigned int *dr;
int a;
if (vc->obedit == NULL || vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) {
- return 0;
+ return false;
}
buf = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
- if (buf == NULL) return 0;
- if (bm_vertoffs == 0) return 0;
+ if (buf == NULL) return false;
+ if (bm_vertoffs == 0) return false;
dr = buf->rect;
@@ -207,7 +210,7 @@ int EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax
dr++;
}
IMB_freeImBuf(buf);
- return 1;
+ return true;
}
int EDBM_backbuf_check(unsigned int index)
@@ -230,7 +233,7 @@ void EDBM_backbuf_free(void)
* - grab again and compare
* returns 'OK'
*/
-int EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
+bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
{
unsigned int *dr, *drm;
struct ImBuf *buf, *bufmask;
@@ -239,19 +242,22 @@ int EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short
/* method in use for face selecting too */
if (vc->obedit == NULL) {
if (!(paint_facesel_test(vc->obact) || paint_vertsel_test(vc->obact))) {
- return 0;
+ return false;
}
}
else if (vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) {
- return 0;
+ return false;
}
buf = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
- if (buf == NULL) return 0;
- if (bm_vertoffs == 0) return 0;
+ if (buf == NULL) return false;
+ if (bm_vertoffs == 0) return false;
dr = buf->rect;
+ if (vc->rv3d->gpuoffscreen)
+ GPU_offscreen_bind(vc->rv3d->gpuoffscreen);
+
/* draw the mask */
glDisable(GL_DEPTH_TEST);
@@ -269,11 +275,14 @@ int EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short
glFinish(); /* to be sure readpixels sees mask */
+ if (vc->rv3d->gpuoffscreen)
+ GPU_offscreen_unbind(vc->rv3d->gpuoffscreen);
+
/* grab mask */
bufmask = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
if (bufmask == NULL) {
- return 0; /* only when mem alloc fails, go crash somewhere else! */
+ return false; /* only when mem alloc fails, go crash somewhere else! */
}
else {
drm = bufmask->rect;
@@ -290,11 +299,11 @@ int EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short
IMB_freeImBuf(buf);
IMB_freeImBuf(bufmask);
- return 1;
+ return true;
}
/* circle shaped sample area */
-int EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads)
+bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads)
{
struct ImBuf *buf;
unsigned int *dr;
@@ -304,16 +313,18 @@ int EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads)
/* method in use for face selecting too */
if (vc->obedit == NULL) {
if (!(paint_facesel_test(vc->obact) || paint_vertsel_test(vc->obact))) {
- return 0;
+ return false;
}
}
- else if (vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) return 0;
-
+ else if (vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) {
+ 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 0;
- if (buf == NULL) return 0;
+ if (bm_vertoffs == 0) return false;
+ if (buf == NULL) return false;
dr = buf->rect;
@@ -329,7 +340,7 @@ int EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads)
}
IMB_freeImBuf(buf);
- return 1;
+ return true;
}
@@ -385,7 +396,7 @@ static unsigned int findnearestvert__backbufIndextest(void *handle, unsigned int
* if 0, unselected vertice are given the bias
* strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased
*/
-BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist, const short sel, const short strict)
+BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist, const bool sel, const bool strict)
{
if (vc->v3d->drawtype > OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) {
float distance;
@@ -425,7 +436,7 @@ BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist, const short sel,
data.lastIndex = lastSelectedIndex;
data.mval_fl[0] = vc->mval[0];
data.mval_fl[1] = vc->mval[1];
- data.select = sel;
+ data.select = sel ? BM_ELEM_SELECT : 0;
data.dist = *r_dist;
data.strict = strict;
data.closest = NULL;
@@ -471,7 +482,7 @@ static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float
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 (ED_view3d_clipping_test(data->vc.rv3d, vec, TRUE) == 0) {
+ if (ED_view3d_clipping_test(data->vc.rv3d, vec, true) == 0) {
data->dist = distance;
data->closest = eed;
}
@@ -681,6 +692,9 @@ static EnumPropertyItem prop_similar_types[] = {
{SIMEDGE_BEVEL, "BEVEL", 0, "Bevel", ""},
{SIMEDGE_SEAM, "SEAM", 0, "Seam", ""},
{SIMEDGE_SHARP, "SHARP", 0, "Sharpness", ""},
+#ifdef WITH_FREESTYLE
+ {SIMEDGE_FREESTYLE, "FREESTYLE_EDGE", 0, "Freestyle Edge Marks", ""},
+#endif
{SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""},
{SIMFACE_IMAGE, "IMAGE", 0, "Image", ""},
@@ -689,6 +703,9 @@ static EnumPropertyItem prop_similar_types[] = {
{SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""},
{SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""},
{SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""},
+#ifdef WITH_FREESTYLE
+ {SIMFACE_FREESTYLE, "FREESTYLE_FACE", 0, "Freestyle Face Marks", ""},
+#endif
{0, NULL, 0, NULL, NULL}
};
@@ -718,14 +735,14 @@ static int similar_face_select_exec(bContext *C, wmOperator *op)
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
/* select the output */
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
/* finish the operator */
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
- EDBM_update_generic(C, em, FALSE);
+ EDBM_update_generic(em, false, false);
/* we succeeded */
return OPERATOR_FINISHED;
@@ -759,15 +776,15 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op)
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
/* select the output */
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, TRUE);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
EDBM_selectmode_flush(em);
/* finish the operator */
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
- EDBM_update_generic(C, em, FALSE);
+ EDBM_update_generic(em, false, false);
/* we succeeded */
return OPERATOR_FINISHED;
@@ -788,7 +805,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op)
BMOperator bmop;
/* get the type from RNA */
const int type = RNA_enum_get(op->ptr, "type");
- float thresh = RNA_float_get(op->ptr, "threshold");
+ const float thresh = RNA_float_get(op->ptr, "threshold");
const int compare = RNA_enum_get(op->ptr, "compare");
/* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
@@ -803,16 +820,16 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op)
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
/* select the output */
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, TRUE);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, true);
/* finish the operator */
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
EDBM_selectmode_flush(em);
- EDBM_update_generic(C, em, FALSE);
+ EDBM_update_generic(em, false, false);
/* we succeeded */
return OPERATOR_FINISHED;
@@ -863,7 +880,11 @@ static EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA *UNUS
}
}
else if (em->selectmode & SCE_SELECT_FACE) {
+#ifdef WITH_FREESTYLE
+ for (a = SIMFACE_MATERIAL; a <= SIMFACE_FREESTYLE; a++) {
+#else
for (a = SIMFACE_MATERIAL; a <= SIMFACE_COPLANAR; a++) {
+#endif
RNA_enum_items_add_value(&item, &totitem, prop_similar_types, a);
}
}
@@ -908,10 +929,10 @@ void MESH_OT_select_similar(wmOperatorType *ot)
static int edbm_select_mode_exec(bContext *C, wmOperator *op)
{
- const int type = RNA_enum_get(op->ptr, "type");
- const int action = RNA_enum_get(op->ptr, "action");
- const int use_extend = RNA_boolean_get(op->ptr, "use_extend");
- const int use_expand = RNA_boolean_get(op->ptr, "use_expand");
+ const int type = RNA_enum_get(op->ptr, "type");
+ const int action = RNA_enum_get(op->ptr, "action");
+ const bool use_extend = RNA_boolean_get(op->ptr, "use_extend");
+ const bool use_expand = RNA_boolean_get(op->ptr, "use_expand");
if (EDBM_selectmode_toggle(C, type, action, use_extend, use_expand)) {
return OPERATOR_FINISHED;
@@ -921,11 +942,15 @@ static int edbm_select_mode_exec(bContext *C, wmOperator *op)
}
}
-static int edbm_select_mode_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int edbm_select_mode_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- // RNA_enum_set(op->ptr, "type"); /* type must be set already */
- RNA_boolean_set(op->ptr, "use_extend", event->shift);
- RNA_boolean_set(op->ptr, "use_expand", event->ctrl);
+ /* detecting these options based on shift/ctrl here is weak, but it's done
+ * to make this work when clicking buttons or menus */
+ if (!RNA_struct_property_is_set(op->ptr, "use_extend"))
+ RNA_boolean_set(op->ptr, "use_extend", event->shift);
+ if (!RNA_struct_property_is_set(op->ptr, "use_expand"))
+ RNA_boolean_set(op->ptr, "use_expand", event->ctrl);
+
return edbm_select_mode_exec(C, op);
}
@@ -961,9 +986,9 @@ void MESH_OT_select_mode(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_boolean(ot->srna, "use_extend", FALSE, "Extend", "");
+ prop = RNA_def_boolean(ot->srna, "use_extend", false, "Extend", "");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "use_expand", FALSE, "Expand", "");
+ prop = RNA_def_boolean(ot->srna, "use_expand", false, "Expand", "");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
ot->prop = prop = RNA_def_enum(ot->srna, "type", elem_items, 0, "Type", "");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
@@ -975,7 +1000,7 @@ void MESH_OT_select_mode(wmOperatorType *ot)
/* **************** LOOP SELECTS *************** */
-static void walker_select(BMEditMesh *em, int walkercode, void *start, int select)
+static void walker_select(BMEditMesh *em, int walkercode, void *start, const bool select)
{
BMesh *bm = em->bm;
BMElem *ele;
@@ -985,8 +1010,8 @@ static void walker_select(BMEditMesh *em, int walkercode, void *start, int selec
BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP,
BMW_FLAG_TEST_HIDDEN,
BMW_NIL_LAY);
- ele = BMW_begin(&walker, start);
- for (; ele; ele = BMW_step(&walker)) {
+
+ for (ele = BMW_begin(&walker, start); ele; ele = BMW_step(&walker)) {
if (!select) {
BM_select_history_remove(bm, ele);
}
@@ -1002,7 +1027,7 @@ static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op)
BMEdge *eed;
BMEdge **edarray;
int edindex;
- int looptype = RNA_boolean_get(op->ptr, "ring");
+ const bool is_ring = RNA_boolean_get(op->ptr, "ring");
BMIter iter;
int totedgesel = 0;
@@ -1023,17 +1048,17 @@ static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op)
}
}
- if (looptype) {
+ if (is_ring) {
for (edindex = 0; edindex < totedgesel; edindex += 1) {
eed = edarray[edindex];
- walker_select(em, BMW_EDGERING, eed, TRUE);
+ walker_select(em, BMW_EDGERING, eed, true);
}
EDBM_selectmode_flush(em);
}
else {
for (edindex = 0; edindex < totedgesel; edindex += 1) {
eed = edarray[edindex];
- walker_select(em, BMW_LOOP, eed, TRUE);
+ walker_select(em, BMW_LOOP, eed, true);
}
EDBM_selectmode_flush(em);
}
@@ -1069,12 +1094,12 @@ void MESH_OT_loop_multi_select(wmOperatorType *ot)
/* ***************** loop select (non modal) ************** */
-static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short deselect, short toggle, short ring)
+static void mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, bool ring)
{
ViewContext vc;
BMEditMesh *em;
BMEdge *eed;
- int select = TRUE;
+ bool select = true;
float dist = 50.0f;
float mvalf[2];
@@ -1088,21 +1113,21 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short desele
eed = EDBM_edge_find_nearest(&vc, &dist);
if (eed) {
- if (extend == 0 && deselect == 0 && toggle == 0) {
+ if (extend == false && deselect == false && toggle == false) {
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
}
if (extend) {
- select = TRUE;
+ select = true;
}
else if (deselect) {
- select = FALSE;
+ select = false;
}
else if (BM_elem_flag_test(eed, BM_ELEM_SELECT) == 0) {
- select = TRUE;
+ select = true;
}
else if (toggle) {
- select = FALSE;
+ select = false;
}
if (em->selectmode & SCE_SELECT_FACE) {
@@ -1136,11 +1161,11 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short desele
/* We can't be sure this has already been set... */
ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
- if (ED_view3d_project_float_object(vc.ar, eed->v1->co, v1_co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_object(vc.ar, eed->v1->co, v1_co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) {
length_1 = len_squared_v2v2(mvalf, v1_co);
}
- if (ED_view3d_project_float_object(vc.ar, eed->v2->co, v2_co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_object(vc.ar, eed->v2->co, v2_co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) {
length_2 = len_squared_v2v2(mvalf, v2_co);
}
#if 0
@@ -1156,7 +1181,7 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short desele
/* Select the face of eed which is the nearest of mouse. */
BMFace *f, *efa = NULL;
BMIter iterf;
- float best_dist = MAXFLOAT;
+ float best_dist = FLT_MAX;
/* We can't be sure this has already been set... */
ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
@@ -1167,7 +1192,7 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short desele
float co[2], tdist;
BM_face_calc_center_mean(f, cent);
- if (ED_view3d_project_float_object(vc.ar, cent, co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_object(vc.ar, cent, co, V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) {
tdist = len_squared_v2v2(mvalf, co);
if (tdist < best_dist) {
/* printf("Best face: %p (%f)\n", f, tdist);*/
@@ -1188,12 +1213,13 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short desele
}
}
-static int edbm_select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int edbm_select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
view3d_operator_needs_opengl(C);
- mouse_mesh_loop(C, event->mval, RNA_boolean_get(op->ptr, "extend"),
+ mouse_mesh_loop(C, event->mval,
+ RNA_boolean_get(op->ptr, "extend"),
RNA_boolean_get(op->ptr, "deselect"),
RNA_boolean_get(op->ptr, "toggle"),
RNA_boolean_get(op->ptr, "ring"));
@@ -1319,6 +1345,23 @@ static void edgetag_context_set(BMesh *bm, Scene *scene, BMEdge *e, int val)
case EDGE_MODE_TAG_BEVEL:
BM_elem_float_data_set(&bm->edata, e, CD_BWEIGHT, (val) ? 1.0f : 0.0f);
break;
+#ifdef WITH_FREESTYLE
+ case EDGE_MODE_TAG_FREESTYLE:
+ {
+ FreestyleEdge *fed;
+
+ if (!CustomData_has_layer(&bm->pdata, CD_FREESTYLE_FACE)) {
+ BM_data_layer_add(bm, &bm->pdata, CD_FREESTYLE_FACE);
+ }
+
+ fed = CustomData_bmesh_get(&bm->edata, e->head.data, CD_FREESTYLE_EDGE);
+ if (!val)
+ fed->flag &= ~FREESTYLE_EDGE_MARK;
+ else
+ fed->flag |= FREESTYLE_EDGE_MARK;
+ }
+ break;
+#endif
}
}
@@ -1326,19 +1369,43 @@ static int edgetag_context_check(Scene *scene, BMesh *bm, BMEdge *e)
{
switch (scene->toolsettings->edge_mode) {
case EDGE_MODE_SELECT:
- return BM_elem_flag_test(e, BM_ELEM_SELECT) ? TRUE : FALSE;
+ return BM_elem_flag_test(e, BM_ELEM_SELECT) ? true : false;
case EDGE_MODE_TAG_SEAM:
return BM_elem_flag_test(e, BM_ELEM_SEAM);
case EDGE_MODE_TAG_SHARP:
return !BM_elem_flag_test(e, BM_ELEM_SMOOTH);
case EDGE_MODE_TAG_CREASE:
- return BM_elem_float_data_get(&bm->edata, e, CD_CREASE) ? TRUE : FALSE;
+ return BM_elem_float_data_get(&bm->edata, e, CD_CREASE) ? true : false;
case EDGE_MODE_TAG_BEVEL:
- return BM_elem_float_data_get(&bm->edata, e, CD_BWEIGHT) ? TRUE : FALSE;
+ return BM_elem_float_data_get(&bm->edata, e, CD_BWEIGHT) ? true : false;
+#ifdef WITH_FREESTYLE
+ case EDGE_MODE_TAG_FREESTYLE:
+ {
+ FreestyleEdge *fed = CustomData_bmesh_get(&bm->edata, e->head.data, CD_FREESTYLE_EDGE);
+ return (!fed) ? FALSE : (fed->flag & FREESTYLE_EDGE_MARK) ? TRUE : FALSE;
+ }
+ break;
+#endif
}
return 0;
}
+static void edgetag_ensure_cd_flag(Scene *scene, Mesh *me)
+{
+ BMesh *bm = me->edit_btmesh->bm;
+
+ switch (scene->toolsettings->edge_mode) {
+ case EDGE_MODE_TAG_CREASE:
+ BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_CREASE);
+ break;
+ case EDGE_MODE_TAG_BEVEL:
+ BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_BWEIGHT);
+ break;
+ default:
+ break;
+ }
+}
+
static int edgetag_shortest_path(Scene *scene, BMesh *bm, BMEdge *e_src, BMEdge *e_dst)
{
/* BM_ELEM_TAG flag is used to store visited edges */
@@ -1352,8 +1419,10 @@ static int edgetag_shortest_path(Scene *scene, BMesh *bm, BMEdge *e_src, BMEdge
/* note, would pass BM_EDGE except we are looping over all edges anyway */
BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */);
+ edgetag_ensure_cd_flag(scene, OBACT->data);
+
BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) {
- if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == FALSE) {
+ if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) {
BM_elem_flag_disable(e, BM_ELEM_TAG);
}
else {
@@ -1402,14 +1471,14 @@ static int edgetag_shortest_path(Scene *scene, BMesh *bm, BMEdge *e_src, BMEdge
}
if (e == e_dst) {
- short all_set = TRUE;
+ bool all_set = true;
/* Check whether the path is already completely tagged.
* if it is, the tags will be cleared instead of set. */
e = e_dst;
do {
if (!edgetag_context_check(scene, bm, e)) {
- all_set = FALSE;
+ all_set = false;
break;
}
} while ((e = edges_prev[BM_elem_index_get(e)]));
@@ -1431,7 +1500,7 @@ static int edgetag_shortest_path(Scene *scene, BMesh *bm, BMEdge *e_src, BMEdge
/* ******************* mesh shortest path select, uses prev-selected edge ****************** */
/* since you want to create paths with multiple selects, it doesn't have extend option */
-static int mouse_mesh_shortest_path_edge(bContext *C, ViewContext *vc)
+static int mouse_mesh_shortest_path_edge(ViewContext *vc)
{
BMEditMesh *em = vc->em;
BMEdge *e_dst;
@@ -1440,7 +1509,7 @@ static int mouse_mesh_shortest_path_edge(bContext *C, ViewContext *vc)
e_dst = EDBM_edge_find_nearest(vc, &dist);
if (e_dst) {
Mesh *me = vc->obedit->data;
- int path = 0;
+ bool is_path = false;
if (em->bm->selected.last) {
BMEditSelection *ese = em->bm->selected.last;
@@ -1451,13 +1520,14 @@ static int mouse_mesh_shortest_path_edge(bContext *C, ViewContext *vc)
if (e_act != e_dst) {
if (edgetag_shortest_path(vc->scene, em->bm, e_act, e_dst)) {
BM_select_history_remove(em->bm, e_act);
- path = 1;
+ is_path = true;
}
}
}
}
- if (path == 0) {
+ if (is_path == false) {
int act = (edgetag_context_check(vc->scene, em->bm, e_dst) == 0);
+ edgetag_ensure_cd_flag(vc->scene, vc->obedit->data);
edgetag_context_set(em->bm, vc->scene, e_dst, act); /* switch the edge option */
}
@@ -1470,7 +1540,7 @@ static int mouse_mesh_shortest_path_edge(bContext *C, ViewContext *vc)
BM_select_history_store(em->bm, e_dst);
/* force drawmode for mesh */
- switch (CTX_data_tool_settings(C)->edge_mode) {
+ switch (vc->scene->toolsettings->edge_mode) {
case EDGE_MODE_TAG_SEAM:
me->drawflag |= ME_DRAWSEAMS;
@@ -1485,14 +1555,19 @@ static int mouse_mesh_shortest_path_edge(bContext *C, ViewContext *vc)
case EDGE_MODE_TAG_BEVEL:
me->drawflag |= ME_DRAWBWEIGHTS;
break;
+#ifdef WITH_FREESTYLE
+ case EDGE_MODE_TAG_FREESTYLE:
+ me->drawflag |= ME_DRAW_FREESTYLE_EDGE;
+ break;
+#endif
}
- EDBM_update_generic(C, em, FALSE);
+ EDBM_update_generic(em, false, false);
- return TRUE;
+ return true;
}
else {
- return FALSE;
+ return false;
}
}
@@ -1569,7 +1644,7 @@ static int facetag_shortest_path(Scene *scene, BMesh *bm, BMFace *f_src, BMFace
// BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); // NOT NEEDED FOR FACETAG
BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, i) {
- if (BM_elem_flag_test(f, BM_ELEM_HIDDEN) == FALSE) {
+ if (BM_elem_flag_test(f, BM_ELEM_HIDDEN) == false) {
BM_elem_flag_disable(f, BM_ELEM_TAG);
}
else {
@@ -1618,14 +1693,14 @@ static int facetag_shortest_path(Scene *scene, BMesh *bm, BMFace *f_src, BMFace
}
if (f == f_dst) {
- short all_set = TRUE;
+ bool all_set = true;
/* Check whether the path is already completely tagged.
* if it is, the tags will be cleared instead of set. */
f = f_dst;
do {
if (!facetag_context_check(scene, bm, f)) {
- all_set = FALSE;
+ all_set = false;
break;
}
} while ((f = faces_prev[BM_elem_index_get(f)]));
@@ -1644,7 +1719,7 @@ static int facetag_shortest_path(Scene *scene, BMesh *bm, BMFace *f_src, BMFace
return 1;
}
-static int mouse_mesh_shortest_path_face(bContext *C, ViewContext *vc)
+static int mouse_mesh_shortest_path_face(ViewContext *vc)
{
BMEditMesh *em = vc->em;
BMFace *f_dst;
@@ -1653,7 +1728,7 @@ static int mouse_mesh_shortest_path_face(bContext *C, ViewContext *vc)
f_dst = EDBM_face_find_nearest(vc, &dist);
if (f_dst) {
int path = 0;
- BMFace *f_act = BM_active_face_get(em->bm, FALSE, TRUE);
+ BMFace *f_act = BM_active_face_get(em->bm, false, true);
if (f_act) {
if (f_act != f_dst) {
@@ -1678,19 +1753,19 @@ static int mouse_mesh_shortest_path_face(bContext *C, ViewContext *vc)
BM_active_face_set(em->bm, f_dst);
- EDBM_update_generic(C, em, FALSE);
+ EDBM_update_generic(em, false, false);
- return TRUE;
+ return true;
}
else {
- return FALSE;
+ return false;
}
}
/* ******************* operator for edge and face tag ****************** */
-static int edbm_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int edbm_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
ViewContext vc;
BMEditMesh *em;
@@ -1703,7 +1778,7 @@ static int edbm_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op),
em = vc.em;
if (em->selectmode & SCE_SELECT_EDGE) {
- if (mouse_mesh_shortest_path_edge(C, &vc)) {
+ if (mouse_mesh_shortest_path_edge(&vc)) {
return OPERATOR_FINISHED;
}
else {
@@ -1711,7 +1786,7 @@ static int edbm_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op),
}
}
else if (em->selectmode & SCE_SELECT_FACE) {
- if (mouse_mesh_shortest_path_face(C, &vc)) {
+ if (mouse_mesh_shortest_path_face(&vc)) {
return OPERATOR_FINISHED;
}
else {
@@ -1747,13 +1822,13 @@ void MESH_OT_select_shortest_path(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
/* ************************************************** */
/* here actual select happens */
/* gets called via generic mouse select operator */
-int EDBM_select_pick(bContext *C, const int mval[2], short extend, short deselect, short toggle)
+bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
{
ViewContext vc;
BMVert *eve = NULL;
@@ -1768,7 +1843,7 @@ int EDBM_select_pick(bContext *C, const int mval[2], short extend, short deselec
if (unified_findnearest(&vc, &eve, &eed, &efa)) {
/* Deselect everything */
- if (extend == 0 && deselect == 0 && toggle == 0)
+ if (extend == false && deselect == false && toggle == false)
EDBM_flag_disable_all(vc.em, BM_ELEM_SELECT);
if (efa) {
@@ -1779,13 +1854,13 @@ int EDBM_select_pick(bContext *C, const int mval[2], short extend, short deselec
/* Work-around: deselect first, so we can guarantee it will */
/* be active even if it was already selected */
BM_select_history_remove(vc.em->bm, efa);
- BM_face_select_set(vc.em->bm, efa, FALSE);
+ BM_face_select_set(vc.em->bm, efa, false);
BM_select_history_store(vc.em->bm, efa);
- BM_face_select_set(vc.em->bm, efa, TRUE);
+ BM_face_select_set(vc.em->bm, efa, true);
}
else if (deselect) {
BM_select_history_remove(vc.em->bm, efa);
- BM_face_select_set(vc.em->bm, efa, FALSE);
+ BM_face_select_set(vc.em->bm, efa, false);
}
else {
/* set the last selected face */
@@ -1793,11 +1868,11 @@ int EDBM_select_pick(bContext *C, const int mval[2], short extend, short deselec
if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_select_history_store(vc.em->bm, efa);
- BM_face_select_set(vc.em->bm, efa, TRUE);
+ BM_face_select_set(vc.em->bm, efa, true);
}
else if (toggle) {
BM_select_history_remove(vc.em->bm, efa);
- BM_face_select_set(vc.em->bm, efa, FALSE);
+ BM_face_select_set(vc.em->bm, efa, false);
}
}
}
@@ -1806,22 +1881,22 @@ int EDBM_select_pick(bContext *C, const int mval[2], short extend, short deselec
/* Work-around: deselect first, so we can guarantee it will */
/* be active even if it was already selected */
BM_select_history_remove(vc.em->bm, eed);
- BM_edge_select_set(vc.em->bm, eed, FALSE);
+ BM_edge_select_set(vc.em->bm, eed, false);
BM_select_history_store(vc.em->bm, eed);
- BM_edge_select_set(vc.em->bm, eed, TRUE);
+ BM_edge_select_set(vc.em->bm, eed, true);
}
else if (deselect) {
BM_select_history_remove(vc.em->bm, eed);
- BM_edge_select_set(vc.em->bm, eed, FALSE);
+ BM_edge_select_set(vc.em->bm, eed, false);
}
else {
if (!BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
BM_select_history_store(vc.em->bm, eed);
- BM_edge_select_set(vc.em->bm, eed, TRUE);
+ BM_edge_select_set(vc.em->bm, eed, true);
}
else if (toggle) {
BM_select_history_remove(vc.em->bm, eed);
- BM_edge_select_set(vc.em->bm, eed, FALSE);
+ BM_edge_select_set(vc.em->bm, eed, false);
}
}
}
@@ -1830,22 +1905,22 @@ int EDBM_select_pick(bContext *C, const int mval[2], short extend, short deselec
/* Work-around: deselect first, so we can guarantee it will */
/* be active even if it was already selected */
BM_select_history_remove(vc.em->bm, eve);
- BM_vert_select_set(vc.em->bm, eve, FALSE);
+ BM_vert_select_set(vc.em->bm, eve, false);
BM_select_history_store(vc.em->bm, eve);
- BM_vert_select_set(vc.em->bm, eve, TRUE);
+ BM_vert_select_set(vc.em->bm, eve, true);
}
else if (deselect) {
BM_select_history_remove(vc.em->bm, eve);
- BM_vert_select_set(vc.em->bm, eve, FALSE);
+ BM_vert_select_set(vc.em->bm, eve, false);
}
else {
if (!BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
BM_select_history_store(vc.em->bm, eve);
- BM_vert_select_set(vc.em->bm, eve, TRUE);
+ BM_vert_select_set(vc.em->bm, eve, true);
}
else if (toggle) {
BM_select_history_remove(vc.em->bm, eve);
- BM_vert_select_set(vc.em->bm, eve, FALSE);
+ BM_vert_select_set(vc.em->bm, eve, false);
}
}
}
@@ -1862,10 +1937,10 @@ int EDBM_select_pick(bContext *C, const int mval[2], short extend, short deselec
}
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
static void edbm_strip_selections(BMEditMesh *em)
@@ -1911,38 +1986,57 @@ void EDBM_selectmode_set(BMEditMesh *em)
edbm_strip_selections(em); /* strip BMEditSelections from em->selected that are not relevant to new mode */
+ if (em->bm->totvertsel == 0 &&
+ em->bm->totedgesel == 0 &&
+ em->bm->totfacesel == 0)
+ {
+ return;
+ }
+
if (em->selectmode & SCE_SELECT_VERTEX) {
- EDBM_select_flush(em);
+ if (em->bm->totvertsel) {
+ EDBM_select_flush(em);
+ }
}
else if (em->selectmode & SCE_SELECT_EDGE) {
/* deselect vertices, and select again based on edge select */
- eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
- for (; eve; eve = BM_iter_step(&iter)) BM_vert_select_set(em->bm, eve, FALSE);
-
- eed = BM_iter_new(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
- for (; eed; eed = BM_iter_step(&iter)) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- BM_edge_select_set(em->bm, eed, TRUE);
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ BM_vert_select_set(em->bm, eve, false);
+ }
+
+ if (em->bm->totedgesel) {
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
+ BM_edge_select_set(em->bm, eed, true);
+ }
}
+
+ /* selects faces based on edge status */
+ EDBM_selectmode_flush(em);
}
-
- /* selects faces based on edge status */
- EDBM_selectmode_flush(em);
}
else if (em->selectmode & SCE_SELECT_FACE) {
/* deselect eges, and select again based on face select */
- eed = BM_iter_new(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
- for (; eed; eed = BM_iter_step(&iter)) BM_edge_select_set(em->bm, eed, FALSE);
-
- efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL);
- for (; efa; efa = BM_iter_step(&iter)) {
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- BM_face_select_set(em->bm, efa, TRUE);
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ BM_edge_select_set(em->bm, eed, false);
+ }
+
+ if (em->bm->totfacesel) {
+ efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL);
+ for (; efa; efa = BM_iter_step(&iter)) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ BM_face_select_set(em->bm, efa, true);
+ }
}
}
}
}
+/**
+ * Flush the selection up:
+ * - vert -> edge
+ * - edge -> face
+ */
void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const short selectmode_new)
{
BMEdge *eed;
@@ -1953,7 +2047,10 @@ void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const s
/* have to find out what the selectionmode was previously */
if (selectmode_old == SCE_SELECT_VERTEX) {
- if (selectmode_new == SCE_SELECT_EDGE) {
+ if (em->bm->totvertsel == 0) {
+ /* pass */
+ }
+ else if (selectmode_new == SCE_SELECT_EDGE) {
/* select all edges associated with every selected vert */
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
BM_elem_flag_set(eed, BM_ELEM_TAG, BM_edge_is_any_vert_flag_test(eed, BM_ELEM_SELECT));
@@ -1961,7 +2058,7 @@ void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const s
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(eed, BM_ELEM_TAG)) {
- BM_edge_select_set(em->bm, eed, TRUE);
+ BM_edge_select_set(em->bm, eed, true);
}
}
}
@@ -1973,13 +2070,16 @@ void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const s
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- BM_face_select_set(em->bm, efa, TRUE);
+ BM_face_select_set(em->bm, efa, true);
}
}
}
}
else if (selectmode_old == SCE_SELECT_EDGE) {
- if (selectmode_new == SCE_SELECT_FACE) {
+ if (em->bm->totedgesel == 0) {
+ /* pass */
+ }
+ else if (selectmode_new == SCE_SELECT_FACE) {
/* select all faces associated with every selected edge */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_edge_flag_test(efa, BM_ELEM_SELECT));
@@ -1987,7 +2087,7 @@ void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const s
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- BM_face_select_set(em->bm, efa, TRUE);
+ BM_face_select_set(em->bm, efa, true);
}
}
}
@@ -1995,13 +2095,13 @@ void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const s
}
/* user facing function, does notification and undo push */
-int EDBM_selectmode_toggle(bContext *C, const short selectmode_new,
- const int action, const int use_extend, const int use_expand)
+bool EDBM_selectmode_toggle(bContext *C, const short selectmode_new,
+ const int action, const bool use_extend, const bool use_expand)
{
ToolSettings *ts = CTX_data_tool_settings(C);
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = NULL;
- int ret = FALSE;
+ bool ret = false;
if (obedit && obedit->type == OB_MESH) {
em = BMEdit_FromObject(obedit);
@@ -2018,21 +2118,21 @@ int EDBM_selectmode_toggle(bContext *C, const short selectmode_new,
case 0: /* disable */
/* check we have something to do */
if ((em->selectmode & selectmode_new) == 0) {
- return FALSE;
+ return false;
}
em->selectmode &= ~selectmode_new;
break;
case 1: /* enable */
/* check we have something to do */
if ((em->selectmode & selectmode_new) != 0) {
- return FALSE;
+ return false;
}
em->selectmode |= selectmode_new;
break;
case 2: /* toggle */
/* can't disable this flag if its the only one set */
if (em->selectmode == selectmode_new) {
- return FALSE;
+ return false;
}
em->selectmode ^= selectmode_new;
break;
@@ -2046,7 +2146,7 @@ int EDBM_selectmode_toggle(bContext *C, const short selectmode_new,
em->selectmode = SCE_SELECT_VERTEX;
ts->selectmode = em->selectmode;
EDBM_selectmode_set(em);
- ret = TRUE;
+ ret = true;
break;
case SCE_SELECT_EDGE:
if (use_extend == 0 || em->selectmode == 0) {
@@ -2060,7 +2160,7 @@ int EDBM_selectmode_toggle(bContext *C, const short selectmode_new,
}
ts->selectmode = em->selectmode;
EDBM_selectmode_set(em);
- ret = TRUE;
+ ret = true;
break;
case SCE_SELECT_FACE:
if (use_extend == 0 || em->selectmode == 0) {
@@ -2075,14 +2175,14 @@ int EDBM_selectmode_toggle(bContext *C, const short selectmode_new,
}
ts->selectmode = em->selectmode;
EDBM_selectmode_set(em);
- ret = TRUE;
+ ret = true;
break;
default:
BLI_assert(0);
break;
}
- if (ret == TRUE) {
+ if (ret == true) {
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
}
@@ -2090,6 +2190,37 @@ int EDBM_selectmode_toggle(bContext *C, const short selectmode_new,
return ret;
}
+/**
+ * Use to disable a selectmode if its enabled, Using another mode as a fallback
+ * if the disabled mode is the only mode set.
+ *
+ * \return true if the mode is changed.
+ */
+bool EDBM_selectmode_disable(Scene *scene, BMEditMesh *em,
+ const short selectmode_disable,
+ const short selectmode_fallback)
+{
+ /* note essential, but switch out of vertex mode since the
+ * selected regions wont be nicely isolated after flushing */
+ if (em->selectmode & selectmode_disable) {
+ if (em->selectmode == selectmode_disable) {
+ em->selectmode = selectmode_fallback;
+ }
+ else {
+ em->selectmode &= ~selectmode_disable;
+ }
+ scene->toolsettings->selectmode = em->selectmode;
+ EDBM_selectmode_set(em);
+
+ WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, scene);
+
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
void EDBM_deselect_by_material(BMEditMesh *em, const short index, const short select)
{
BMIter iter;
@@ -2151,25 +2282,25 @@ int EDBM_select_interior_faces(BMEditMesh *em)
BMIter eiter;
BMFace *efa;
BMEdge *eed;
- int ok;
- int change = FALSE;
+ bool ok;
+ bool change = false;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
continue;
- ok = TRUE;
+ ok = true;
BM_ITER_ELEM (eed, &eiter, efa, BM_EDGES_OF_FACE) {
if (BM_edge_face_count(eed) < 3) {
- ok = FALSE;
+ ok = false;
break;
}
}
if (ok) {
- BM_face_select_set(bm, efa, TRUE);
- change = TRUE;
+ BM_face_select_set(bm, efa, true);
+ change = true;
}
}
@@ -2182,13 +2313,13 @@ static void linked_limit_default(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
if (em->selectmode == SCE_SELECT_FACE)
- RNA_boolean_set(op->ptr, "limit", TRUE);
+ RNA_boolean_set(op->ptr, "limit", true);
else
- RNA_boolean_set(op->ptr, "limit", FALSE);
+ RNA_boolean_set(op->ptr, "limit", false);
}
}
-static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Object *obedit = CTX_data_edit_object(C);
ViewContext vc;
@@ -2251,8 +2382,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *
BMW_FLAG_TEST_HIDDEN,
BMW_NIL_LAY);
- e = BMW_begin(&walker, efa);
- for (; efa; efa = BMW_step(&walker)) {
+ for (efa = BMW_begin(&walker, efa); efa; efa = BMW_step(&walker)) {
BM_face_select_set(bm, efa, sel);
}
BMW_end(&walker);
@@ -2273,8 +2403,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *
BMW_FLAG_TEST_HIDDEN,
BMW_NIL_LAY);
- e = BMW_begin(&walker, eed->v1);
- for (; e; e = BMW_step(&walker)) {
+ for (e = BMW_begin(&walker, eed->v1); e; e = BMW_step(&walker)) {
BM_edge_select_set(bm, e, sel);
}
BMW_end(&walker);
@@ -2345,9 +2474,8 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- e = BMW_begin(&walker, efa);
- for (; efa; efa = BMW_step(&walker)) {
- BM_face_select_set(bm, efa, TRUE);
+ for (efa = BMW_begin(&walker, efa); efa; efa = BMW_step(&walker)) {
+ BM_face_select_set(bm, efa, true);
}
}
}
@@ -2374,16 +2502,15 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- e = BMW_begin(&walker, v);
- for (; e; e = BMW_step(&walker)) {
- BM_vert_select_set(em->bm, e->v1, TRUE);
- BM_vert_select_set(em->bm, e->v2, TRUE);
+ for (e = BMW_begin(&walker, v); e; e = BMW_step(&walker)) {
+ BM_edge_select_set(em->bm, e, true);
}
}
}
BMW_end(&walker);
+
+ EDBM_selectmode_flush(em);
}
- EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
@@ -2530,7 +2657,7 @@ static void walker_deselect_nth(BMEditMesh *em, int nth, int offset, BMHeader *h
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) {
- BM_elem_select_set(bm, ele, FALSE);
+ BM_elem_select_set(bm, ele, false);
}
BM_elem_flag_enable(ele, BM_ELEM_TAG);
}
@@ -2589,7 +2716,7 @@ static void deselect_nth_active(BMEditMesh *em, BMVert **r_eve, BMEdge **r_eed,
}
}
else if (em->selectmode & SCE_SELECT_FACE) {
- f = BM_active_face_get(em->bm, TRUE, FALSE);
+ f = BM_active_face_get(em->bm, true, false);
if (f) {
*r_efa = f;
return;
@@ -2625,17 +2752,18 @@ static int edbm_select_nth_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
- int nth = RNA_int_get(op->ptr, "nth");
+ const int nth = RNA_int_get(op->ptr, "nth");
int offset = RNA_int_get(op->ptr, "offset");
- offset = MIN2(nth, offset);
+ /* so input of offset zero ends up being (nth - 1) */
+ offset = (offset + (nth - 1)) % nth;
if (edbm_deselect_nth(em, nth, offset) == 0) {
BKE_report(op->reports, RPT_ERROR, "Mesh has no active vert/edge/face");
return OPERATOR_CANCELLED;
}
- EDBM_update_generic(C, em, FALSE);
+ EDBM_update_generic(em, false, false);
return OPERATOR_FINISHED;
}
@@ -2646,7 +2774,7 @@ void MESH_OT_select_nth(wmOperatorType *ot)
/* identifiers */
ot->name = "Checker Deselect";
ot->idname = "MESH_OT_select_nth";
- ot->description = "Deselect every Nth element starting from a selected vertex, edge or face";
+ ot->description = "Deselect every Nth element starting from the active vertex, edge or face";
/* api callbacks */
ot->exec = edbm_select_nth_exec;
@@ -2692,14 +2820,14 @@ static int edbm_select_sharp_edges_exec(bContext *C, wmOperator *op)
const float sharp = RNA_float_get(op->ptr, "sharpness");
BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == FALSE &&
+ if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false &&
BM_edge_loop_pair(e, &l1, &l2))
{
/* edge has exactly two neighboring faces, check angle */
const float angle = angle_normalized_v3v3(l1->f->no, l2->f->no);
if (fabsf(angle) > sharp) {
- BM_edge_select_set(em->bm, e, TRUE);
+ BM_edge_select_set(em->bm, e, true);
}
}
}
@@ -2739,7 +2867,7 @@ static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op)
BMFace *f, **stack = NULL;
BLI_array_declare(stack);
BMLoop *l, *l2;
- float sharp = RNA_float_get(op->ptr, "sharpness");
+ const float sharp = RNA_float_get(op->ptr, "sharpness");
int i;
BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
@@ -2760,7 +2888,7 @@ static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op)
f = stack[i - 1];
i--;
- BM_face_select_set(em->bm, f, TRUE);
+ BM_face_select_set(em->bm, f, true);
BM_elem_flag_enable(f, BM_ELEM_TAG);
@@ -2822,6 +2950,9 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op)
BMEdge *e;
BMIter iter;
+ if (!RNA_boolean_get(op->ptr, "extend"))
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+
/* Selects isolated verts, and edges that do not have 2 neighboring
* faces
*/
@@ -2833,13 +2964,13 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op)
BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN) && !BM_vert_is_manifold(v)) {
- BM_vert_select_set(em->bm, v, TRUE);
+ BM_vert_select_set(em->bm, v, true);
}
}
BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN) && !BM_edge_is_manifold(e)) {
- BM_edge_select_set(em->bm, e, TRUE);
+ BM_edge_select_set(em->bm, e, true);
}
}
@@ -2861,6 +2992,9 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend the selection");
}
static int edbm_select_random_exec(bContext *C, wmOperator *op)
@@ -2871,7 +3005,7 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op)
BMEdge *eed;
BMFace *efa;
BMIter iter;
- float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
+ const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
BLI_srand(BLI_rand()); /* random seed */
@@ -2881,7 +3015,7 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op)
if (em->selectmode & SCE_SELECT_VERTEX) {
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BLI_frand() < randfac) {
- BM_vert_select_set(em->bm, eve, TRUE);
+ BM_vert_select_set(em->bm, eve, true);
}
}
EDBM_selectmode_flush(em);
@@ -2889,7 +3023,7 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op)
else if (em->selectmode & SCE_SELECT_EDGE) {
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BLI_frand() < randfac) {
- BM_edge_select_set(em->bm, eed, TRUE);
+ BM_edge_select_set(em->bm, eed, true);
}
}
EDBM_selectmode_flush(em);
@@ -2897,7 +3031,7 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op)
else {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BLI_frand() < randfac) {
- BM_face_select_set(em->bm, efa, TRUE);
+ BM_face_select_set(em->bm, efa, true);
}
}
EDBM_selectmode_flush(em);
@@ -2925,8 +3059,60 @@ void MESH_OT_select_random(wmOperatorType *ot)
/* 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_boolean(ot->srna, "extend", 0,
- "Extend Selection", "Extend selection instead of deselecting everything first");
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+}
+
+static int edbm_select_ungrouped_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BMEdit_FromObject(obedit);
+ BMVert *eve;
+ BMIter iter;
+
+ if ((em->selectmode & SCE_SELECT_VERTEX) == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Does not work out of vertex selection mode");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (obedit->defbase.first == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No weights/vertex groups on object");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!RNA_boolean_get(op->ptr, "extend")) {
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ }
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+ MDeformVert *dv = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
+ /* no dv or dv set with no weight */
+ if (dv == NULL || (dv && dv->dw == NULL)) {
+ BM_vert_select_set(em->bm, eve, true);
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_select_ungrouped(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Ungrouped";
+ ot->idname = "MESH_OT_select_ungrouped";
+ ot->description = "Select vertices without a group";
+
+ /* api callbacks */
+ ot->exec = edbm_select_ungrouped_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
static int edbm_select_next_loop_exec(bContext *C, wmOperator *UNUSED(op))
@@ -2948,14 +3134,14 @@ static int edbm_select_next_loop_exec(bContext *C, wmOperator *UNUSED(op))
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l->v, BM_ELEM_SELECT)) {
BM_elem_flag_enable(l->next->v, BM_ELEM_TAG);
- BM_vert_select_set(em->bm, l->v, FALSE);
+ BM_vert_select_set(em->bm, l->v, false);
}
}
}
BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- BM_vert_select_set(em->bm, v, TRUE);
+ BM_vert_select_set(em->bm, v, true);
}
}
@@ -2987,7 +3173,7 @@ static int edbm_region_to_loop_exec(bContext *C, wmOperator *UNUSED(op))
BMEdge *e;
BMIter iter;
- BM_mesh_elem_hflag_disable_all(em->bm, BM_EDGE, BM_ELEM_TAG, FALSE);
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_EDGE, BM_ELEM_TAG, false);
BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
BMLoop *l1, *l2;
@@ -3010,7 +3196,7 @@ static int edbm_region_to_loop_exec(bContext *C, wmOperator *UNUSED(op))
BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BM_edge_select_set(em->bm, e, TRUE);
+ BM_edge_select_set(em->bm, e, true);
}
}
@@ -3186,22 +3372,22 @@ static int edbm_loop_to_region_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BMEdit_FromObject(obedit);
BMIter iter;
BMFace *f;
- int selbigger = RNA_boolean_get(op->ptr, "select_bigger");
+ const bool select_bigger = RNA_boolean_get(op->ptr, "select_bigger");
int a, b;
/* find the set of regions with smallest number of total faces */
- a = loop_find_regions(em, selbigger);
- b = loop_find_regions(em, !selbigger);
+ a = loop_find_regions(em, select_bigger);
+ b = loop_find_regions(em, !select_bigger);
- if ((a <= b) ^ selbigger) {
- loop_find_regions(em, selbigger);
+ if ((a <= b) ^ select_bigger) {
+ loop_find_regions(em, select_bigger);
}
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(f, BM_ELEM_TAG) && !BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- BM_face_select_set(em->bm, f, TRUE);
+ BM_face_select_set(em->bm, f, true);
}
}
diff --git a/source/blender/editors/mesh/editmesh_slide.c b/source/blender/editors/mesh/editmesh_slide.c
deleted file mode 100644
index 4fbe9c2534f..00000000000
--- a/source/blender/editors/mesh/editmesh_slide.c
+++ /dev/null
@@ -1,793 +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.
- *
- * Contributor(s): Francisco De La Cruz
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/mesh/editmesh_slide.c
- * \ingroup edmesh
- */
-
-/* Takes heavily from editmesh_loopcut.c */
-
-#include "DNA_object_types.h"
-#include "DNA_mesh_types.h"
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_array.h"
-#include "BLI_math.h"
-
-#include "BLF_translation.h"
-
-#include "BKE_context.h"
-#include "BKE_report.h"
-#include "BKE_tessmesh.h"
-
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
-
-#include "ED_screen.h"
-#include "ED_view3d.h"
-#include "ED_mesh.h"
-#include "ED_space_api.h"
-
-#include "UI_resources.h"
-
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "mesh_intern.h"
-
-#define VTX_SLIDE_SNAP_THRSH 15
-
-/* Cusom VertexSlide Operator data */
-typedef struct VertexSlideOp {
- /* Starting Vertex */
- BMVert *start_vtx;
- BMEdge *sel_edge;
-
- ViewContext *view_context;
- ARegion *active_region;
-
- /* Draw callback handle */
- void *draw_handle;
-
- /* Active Object */
- Object *obj;
-
- /* Are we in slide mode */
- int slide_mode;
- int snap_n_merge;
- int snap_to_end_vtx;
- int snap_to_mid;
-
- /* Snap threshold */
- float snap_threshold;
-
- float distance;
- float interp[3];
-
- /* Edge Frame Count */
- int disk_edges;
-
- /* Edges */
- BMEdge **edge_frame;
-
- /* Slide Frame Endpoints */
- float (*vtx_frame)[3];
-
- /* Mouse Click 2d pos */
- int m_co[2];
-
-} VertexSlideOp;
-
-static void vtx_slide_draw(const bContext *C, ARegion *ar, void *arg);
-static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_update);
-static void vtx_slide_exit(const bContext *C, wmOperator *op);
-static int vtx_slide_set_frame(VertexSlideOp *vso);
-
-static int vtx_slide_init(bContext *C, wmOperator *op)
-{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BMEdit_FromObject(obedit);
- BMEditSelection *ese;
-
- /* Custom data */
- VertexSlideOp *vso;
-
- const char *header_str = TIP_("Vertex Slide: Hover over an edge and left-click to select slide edge. "
- "Left-Shift: Midpoint Snap, Left-Alt: Snap, Left-Ctrl: Snap & Merge");
-
- if (!obedit) {
- BKE_report(op->reports, RPT_ERROR, "Vertex slide error: no object in context");
- return FALSE;
- }
-
- EDBM_selectmode_flush(em);
- ese = em->bm->selected.last;
-
- /* Is there a starting vertex ? */
- if (ese == NULL || (ese->htype != BM_VERT && ese->htype != BM_EDGE)) {
- BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex slide error: select a (single) vertex");
- return FALSE;
- }
-
- vso = MEM_callocN(sizeof(VertexSlideOp), "Vertex Slide Operator");
- vso->view_context = MEM_callocN(sizeof(ViewContext), "Vertex Slide View Context");
-
- op->customdata = vso;
-
- /* Set the start vertex */
- vso->start_vtx = (BMVert *)ese->ele;
-
- vso->sel_edge = NULL;
-
- /* Edges */
- vso->edge_frame = NULL;
-
- vso->vtx_frame = NULL;
-
- vso->disk_edges = 0;
-
- vso->slide_mode = FALSE;
-
- vso->snap_n_merge = FALSE;
-
- vso->snap_to_end_vtx = FALSE;
-
- vso->snap_to_mid = FALSE;
-
- vso->distance = 0.0f;
-
- vso->snap_threshold = 0.2f;
-
- /* Notify the viewport */
- view3d_operator_needs_opengl(C);
-
- /* Set the drawing region */
- vso->active_region = CTX_wm_region(C);
-
- /* Set the draw callback */
- vso->draw_handle = ED_region_draw_cb_activate(vso->active_region->type, vtx_slide_draw, vso, REGION_DRAW_POST_VIEW);
-
- ED_area_headerprint(CTX_wm_area(C), header_str);
-
- em_setup_viewcontext(C, vso->view_context);
-
- /* Set the object */
- vso->obj = obedit;
-
- /* Init frame */
- if (!vtx_slide_set_frame(vso)) {
- BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex slide error: cannot find starting vertex!");
- vtx_slide_exit(C, op);
- return FALSE;
- }
-
- /* Add handler for the vertex sliding */
- WM_event_add_modal_handler(C, op);
-
- /* Tag for redraw */
- ED_region_tag_redraw(vso->active_region);
-
- return TRUE;
-}
-
-static void vtx_slide_confirm(bContext *C, wmOperator *op)
-{
- VertexSlideOp *vso = op->customdata;
- BMEditMesh *em = BMEdit_FromObject(vso->obj);
- BMesh *bm = em->bm;
- BMVert *other = NULL;
-
- BMVert *mirr_vtx = NULL;
- BMVert *mirr_vtx_other = NULL;
-
- /* Select new edge */
- BM_edge_select_set(bm, vso->sel_edge, TRUE);
-
- if (vso->snap_n_merge) {
- other = BM_edge_other_vert(vso->sel_edge, vso->start_vtx);
- }
-
- if (((Mesh *)em->ob->data)->editflag & ME_EDIT_MIRROR_X) {
- EDBM_verts_mirror_cache_begin(em, TRUE);
-
- mirr_vtx = EDBM_verts_mirror_get(em, vso->start_vtx);
- if (vso->snap_n_merge) {
- mirr_vtx_other = EDBM_verts_mirror_get(em, other);
- }
- }
-
- /* Invoke operator - warning */
- edbm_vertex_slide_exec_ex(C, op, FALSE);
-
- if (mirr_vtx) {
- mirr_vtx->co[0] = -vso->start_vtx->co[0];
- mirr_vtx->co[1] = vso->start_vtx->co[1];
- mirr_vtx->co[2] = vso->start_vtx->co[2];
- }
-
- if (vso->snap_n_merge) {
- float other_d;
- other_d = len_v3v3(vso->interp, other->co);
-
- /* Only snap if within threshold */
- if (other_d < vso->snap_threshold) {
- BM_vert_select_set(bm, other, TRUE);
- BM_vert_select_set(bm, vso->start_vtx, TRUE);
- EDBM_op_callf(em, op, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, other->co);
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
-
- if (mirr_vtx_other) {
- BM_vert_select_set(bm, mirr_vtx, TRUE);
- BM_vert_select_set(bm, mirr_vtx_other, TRUE);
- EDBM_op_callf(em, op, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, mirr_vtx_other->co);
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- }
- }
- else {
- /* Store in historty if not merging */
- BM_select_history_store(em->bm, vso->start_vtx);
- }
- }
- else {
- /* Store edit selection of the active vertex, allows other
- * ops to run without reselecting */
- BM_select_history_store(em->bm, vso->start_vtx);
- }
-
- if (((Mesh *)em->ob->data)->editflag & ME_EDIT_MIRROR_X) {
- EDBM_verts_mirror_cache_end(em);
- }
-
- EDBM_selectmode_flush(em);
-
- /* NC_GEOM | ND_DATA & Retess */
- EDBM_update_generic(C, em, TRUE);
-
- ED_region_tag_redraw(vso->active_region);
-}
-
-static void vtx_slide_exit(const bContext *C, wmOperator *op)
-{
- /* Fetch custom data */
- VertexSlideOp *vso = op->customdata;
-
- /* Clean-up the custom data */
- ED_region_draw_cb_exit(vso->active_region->type, vso->draw_handle);
-
- /* Free Custom Data
- *
- */
- MEM_freeN(vso->view_context);
-
- vso->view_context = NULL;
-
- if (vso->edge_frame) {
- MEM_freeN(vso->edge_frame);
- }
-
- if (vso->vtx_frame) {
- MEM_freeN(vso->vtx_frame);
- }
-
- vso->edge_frame = NULL;
-
- vso->vtx_frame = NULL;
-
- vso->slide_mode = FALSE;
-
- MEM_freeN(vso);
- vso = NULL;
- op->customdata = NULL;
-
- /* Clear the header */
- ED_area_headerprint(CTX_wm_area(C), NULL);
-}
-
-static void vtx_slide_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
-{
- VertexSlideOp *vso = arg;
-
- /* Have an edge to draw */
- if (vso && vso->sel_edge) {
- /* Get 3d view */
- View3D *view3d = CTX_wm_view3d(C);
- const float outline_w = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.8f;
- const float pt_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f;
-
- int i = 0;
-
- if (view3d && view3d->zbuf)
- glDisable(GL_DEPTH_TEST);
-
- glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT | GL_POINT_BIT);
-
- glPushMatrix();
- glMultMatrixf(vso->obj->obmat);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-
- if (vso->slide_mode && vso->disk_edges > 0) {
- /* Draw intermediate edge frame */
- UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 50, -50);
-
- for (i = 0; i < vso->disk_edges; i++) {
- glBegin(GL_LINES);
- glVertex3fv(vso->vtx_frame[i]);
- glVertex3fv(vso->interp);
- glEnd();
- }
- }
-
- /* Draw selected edge
- * Add color offset and reduce alpha */
- UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 40, -50);
-
- glLineWidth(outline_w);
-
- glBegin(GL_LINES);
- bglVertex3fv(vso->sel_edge->v1->co);
- bglVertex3fv(vso->sel_edge->v2->co);
- glEnd();
-
- if (vso->slide_mode) {
- /* Draw interpolated vertex */
-
- UI_ThemeColorShadeAlpha(TH_FACE_DOT, -80, -50);
-
- glPointSize(pt_size);
-
- bglBegin(GL_POINTS);
- bglVertex3fv(vso->interp);
- bglEnd();
- }
-
- glDisable(GL_BLEND);
- glPopMatrix();
- glPopAttrib();
-
- if (view3d && view3d->zbuf)
- glEnable(GL_DEPTH_TEST);
- }
-}
-
-static BMEdge *vtx_slide_nrst_in_frame(VertexSlideOp *vso, const float mval[2])
-{
- BMEdge *cl_edge = NULL;
- if (vso->disk_edges > 0) {
- int i = 0;
- BMEdge *edge = NULL;
-
- float v1_proj[3], v2_proj[3];
- float min_dist = FLT_MAX;
-
- for (i = 0; i < vso->disk_edges; i++) {
- edge = vso->edge_frame[i];
-
- mul_v3_m4v3(v1_proj, vso->obj->obmat, edge->v1->co);
- mul_v3_m4v3(v2_proj, vso->obj->obmat, edge->v2->co);
-
- /* we could use ED_view3d_project_float_object here, but for now dont since we dont have the context */
- if ((ED_view3d_project_float_global(vso->active_region, v1_proj, v1_proj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) &&
- (ED_view3d_project_float_global(vso->active_region, v2_proj, v2_proj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK))
- {
- const float dist = dist_to_line_segment_v2(mval, v1_proj, v2_proj);
- if (dist < min_dist) {
- min_dist = dist;
- cl_edge = edge;
- }
- }
- }
- }
- return cl_edge;
-}
-
-static void vtx_slide_find_edge(VertexSlideOp *vso, wmEvent *event)
-{
- /* Nearest edge */
- BMEdge *nst_edge = NULL;
-
- const float mval_float[2] = {(float)event->mval[0],
- (float)event->mval[1]};
-
- /* Set mouse coords */
- copy_v2_v2_int(vso->view_context->mval, event->mval);
-
- /* Find nearest edge */
- nst_edge = vtx_slide_nrst_in_frame(vso, mval_float);
-
- if (nst_edge) {
- /* Find a connected edge */
- if (BM_vert_in_edge(nst_edge, vso->start_vtx)) {
-
- /* Save mouse coords */
- copy_v2_v2_int(vso->m_co, event->mval);
-
- /* Set edge */
- vso->sel_edge = nst_edge;
- }
- }
-}
-
-/* Updates the status of the operator - Invoked on mouse movement */
-static void vtx_slide_update(VertexSlideOp *vso, wmEvent *event)
-{
- BMEdge *edge;
-
- /* Find nearest edge */
- edge = vso->sel_edge;
-
- if (edge) {
- float edge_other_proj[3];
- float start_vtx_proj[3];
- float edge_len;
- BMVert *other;
-
- float interp[3];
-
- /* Calculate interpolation value for preview */
- float t_val;
-
- float mval_float[2] = { (float)event->mval[0], (float)event->mval[1]};
- float closest_2d[2];
-
- other = BM_edge_other_vert(edge, vso->start_vtx);
-
- /* Project points onto screen and do interpolation in 2D */
- mul_v3_m4v3(start_vtx_proj, vso->obj->obmat, vso->start_vtx->co);
- mul_v3_m4v3(edge_other_proj, vso->obj->obmat, other->co);
-
- if ((ED_view3d_project_float_global(vso->active_region, edge_other_proj, edge_other_proj, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) ||
- (ED_view3d_project_float_global(vso->active_region, start_vtx_proj, start_vtx_proj, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK))
- {
- /* not much we can do here */
- return;
- }
-
- closest_to_line_v2(closest_2d, mval_float, start_vtx_proj, edge_other_proj);
-
- t_val = line_point_factor_v2(closest_2d, start_vtx_proj, edge_other_proj);
-
- /* Set snap threshold to be proportional to edge length */
- edge_len = len_v3v3(start_vtx_proj, edge_other_proj);
-
- if (edge_len <= 0.0f)
- edge_len = VTX_SLIDE_SNAP_THRSH;
-
- edge_len = (BM_edge_calc_length(edge) * VTX_SLIDE_SNAP_THRSH) / edge_len;
-
- vso->snap_threshold = edge_len;
-
- /* Snap to mid */
- if (vso->snap_to_mid) {
- t_val = 0.5f;
- }
-
- /* Interpolate preview vertex 3D */
- interp_v3_v3v3(interp, vso->start_vtx->co, other->co, t_val);
- copy_v3_v3(vso->interp, interp);
-
- vso->distance = t_val;
-
- /* If snapping */
- if (vso->snap_to_end_vtx) {
- int start_at_v1 = edge->v1 == vso->start_vtx;
- float v1_d = len_v3v3(vso->interp, edge->v1->co);
- float v2_d = len_v3v3(vso->interp, edge->v2->co);
-
- if (v1_d > v2_d && v2_d < vso->snap_threshold) {
- copy_v3_v3(vso->interp, edge->v2->co);
-
- if (start_at_v1)
- vso->distance = 1.0f;
- else
- vso->distance = 0.0f;
- }
- if (v2_d > v1_d && v1_d < vso->snap_threshold) {
- copy_v3_v3(vso->interp, edge->v1->co);
- if (start_at_v1)
- vso->distance = 0.0f;
- else
- vso->distance = 1.0f;
- }
- }
- }
-}
-
-/* Sets the outline frame */
-static int vtx_slide_set_frame(VertexSlideOp *vso)
-{
- BMEdge *edge;
- float (*vtx_frame)[3] = NULL;
- BMEdge **edge_frame = NULL;
- BMVert *curr_vert = NULL;
- BLI_array_declare(vtx_frame);
- BLI_array_declare(edge_frame);
- BMIter iter;
- BMVert *sel_vtx = vso->start_vtx;
- int idx = 0;
-
- vso->disk_edges = 0;
-
- if (vso->edge_frame) {
- MEM_freeN(vso->edge_frame);
- vso->edge_frame = NULL;
- }
-
- if (vso->vtx_frame) {
- MEM_freeN(vso->vtx_frame);
- vso->vtx_frame = NULL;
- }
-
- /* Iterate over edges of vertex and copy them */
- BM_ITER_ELEM_INDEX (edge, &iter, sel_vtx, BM_EDGES_OF_VERT, idx) {
- curr_vert = BM_edge_other_vert(edge, sel_vtx);
- if (curr_vert) {
- BLI_array_grow_one(vtx_frame);
-
- copy_v3_v3(vtx_frame[idx], curr_vert->co);
-
- BLI_array_append(edge_frame, edge);
- vso->disk_edges++;
- }
- }
-
- vso->edge_frame = edge_frame;
- vso->vtx_frame = vtx_frame;
-
- /* Set the interp at starting vtx */
- copy_v3_v3(vso->interp, sel_vtx->co);
-
- return vso->disk_edges > 0;
-}
-
-static int edbm_vertex_slide_modal(bContext *C, wmOperator *op, wmEvent *event)
-{
- VertexSlideOp *vso = op->customdata;
- char buff[128];
-
- if (!vso)
- return OPERATOR_CANCELLED;
-
- /* Notify the viewport */
- view3d_operator_needs_opengl(C);
-
- switch (event->type) {
- case LEFTSHIFTKEY:
- {
- switch (event->val) {
- case KM_PRESS:
- vso->snap_to_mid = TRUE;
- break;
- case KM_RELEASE:
- vso->snap_to_mid = FALSE;
- break;
- }
-
- break;
- }
- case LEFTCTRLKEY:
- {
- switch (event->val) {
- case KM_PRESS:
- vso->snap_n_merge = TRUE;
- vso->snap_to_end_vtx = TRUE;
- break;
- case KM_RELEASE:
- vso->snap_n_merge = FALSE;
- vso->snap_to_end_vtx = FALSE;
- break;
- }
-
- break;
- }
- case LEFTALTKEY:
- {
- switch (event->val) {
- case KM_PRESS:
- vso->snap_to_end_vtx = TRUE;
- break;
- case KM_RELEASE:
- vso->snap_to_end_vtx = FALSE;
- break;
- }
-
- break;
- }
- case RIGHTMOUSE:
- case ESCKEY:
- {
- /* Enforce redraw */
- ED_region_tag_redraw(vso->active_region);
-
- /* Clean-up */
- vtx_slide_exit(C, op);
-
- return OPERATOR_CANCELLED;
- }
- case LEFTMOUSE:
- {
- if (event->val == KM_PRESS) {
- /* Update mouse coords */
- copy_v2_v2_int(vso->m_co, event->mval);
-
- if (vso->slide_mode) {
- vtx_slide_confirm(C, op);
- /* Clean-up */
- vtx_slide_exit(C, op);
- return OPERATOR_FINISHED;
- }
- else if (vso->sel_edge) {
- vso->slide_mode = TRUE;
- }
- }
-
- ED_region_tag_redraw(vso->active_region);
- break;
-
- }
- case MOUSEMOVE:
- {
- sprintf(buff, "Vertex Slide: %f", vso->distance);
- if (!vso->slide_mode) {
- vtx_slide_find_edge(vso, event);
- }
- else {
- vtx_slide_update(vso, event);
- }
- ED_area_headerprint(CTX_wm_area(C), buff);
- ED_region_tag_redraw(vso->active_region);
- break;
- }
- }
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static int edbm_vertex_slide_cancel(bContext *C, wmOperator *op)
-{
- /* Exit the modal */
- vtx_slide_exit(C, op);
-
- return OPERATOR_CANCELLED;
-}
-
-static int edbm_vertex_slide_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
-{
- /* Initialize the operator */
- if (vtx_slide_init(C, op))
- return OPERATOR_RUNNING_MODAL;
- else
- return OPERATOR_CANCELLED;
-}
-
-/* Vertex Slide */
-static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_update)
-{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BMEdit_FromObject(obedit);
- BMesh *bm = em->bm;
- BMVert *start_vert;
- BMOperator bmop;
- BMEditSelection *ese = (BMEditSelection *)em->bm->selected.last;
-
- float factor = 0.0f;
-
- /* Invoked modally? */
- if (op->type->modal == edbm_vertex_slide_modal && op->customdata) {
- VertexSlideOp *vso = (VertexSlideOp *)op->customdata;
-
- if (bm->totedgesel > 1) {
- /* Reset selections */
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BM_edge_select_set(bm, vso->sel_edge, TRUE);
- BM_vert_select_set(bm, vso->start_vtx, TRUE);
-
- BM_select_history_store(em->bm, vso->sel_edge);
- BM_select_history_store(em->bm, vso->start_vtx);
- ese = (BMEditSelection *)em->bm->selected.last;
- }
- factor = vso->distance;
- RNA_float_set(op->ptr, "factor", factor);
- }
- else {
- /* Get Properties */
- factor = RNA_float_get(op->ptr, "factor");
- }
-
- /* Is there a starting vertex ? */
- if ((ese == NULL) || (ese->htype != BM_VERT && ese->htype != BM_EDGE)) {
- BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex slide error: select a (single) vertex");
- return OPERATOR_CANCELLED;
- }
-
- start_vert = (BMVert *)ese->ele;
-
- /* Prepare operator */
- if (!EDBM_op_init(em, &bmop, op,
- "slide_vert vert=%e edges=%he factor=%f",
- start_vert, BM_ELEM_SELECT, factor))
- {
- return OPERATOR_CANCELLED;
- }
- /* Execute operator */
- BMO_op_exec(bm, &bmop);
-
- /* Deselect the input edges */
- BMO_slot_buffer_hflag_disable(bm, bmop.slots_in, "edges", BM_EDGE, BM_ELEM_SELECT, TRUE);
-
- /* Select the output vert */
- BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, TRUE);
-
- /* Flush the select buffers */
- EDBM_selectmode_flush(em);
-
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
- return OPERATOR_CANCELLED;
- }
-
- if (do_update) {
- /* Update Geometry */
- EDBM_update_generic(C, em, TRUE);
- }
-
- return OPERATOR_FINISHED;
-}
-
-#if 0
-static int edbm_vertex_slide_exec(bContext *C, wmOperator *op)
-{
- return edbm_vertex_slide_exec_ex(C, op, TRUE);
-}
-#endif
-
-void MESH_OT_vert_slide(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Vertex Slide";
- ot->idname = "MESH_OT_vert_slide";
- ot->description = "Vertex slide";
-
- /* api callback */
- ot->invoke = edbm_vertex_slide_invoke;
- ot->modal = edbm_vertex_slide_modal;
- ot->cancel = edbm_vertex_slide_cancel;
- ot->poll = ED_operator_editmesh_region_view3d;
-
- /* ot->exec = edbm_vertex_slide_exec;
- * ot->poll = ED_operator_editmesh; */
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* Properties for vertex slide */
- prop = RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Distance", "Distance", -5.0f, 5.0f);
- RNA_def_property_ui_range(prop, -5.0f, 5.0f, 0.1, 4);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-}
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index ad1077156ba..13660a47248 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -34,30 +34,31 @@
#include "DNA_key_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "RNA_define.h"
-#include "RNA_access.h"
-
-#include "BLI_array.h"
#include "BLI_blenlib.h"
#include "BLI_noise.h"
#include "BLI_math.h"
#include "BLI_rand.h"
+#include "BLF_translation.h"
+
#include "BKE_material.h"
#include "BKE_context.h"
-#include "BKE_cdderivedmesh.h"
#include "BKE_depsgraph.h"
-#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_texture.h"
#include "BKE_main.h"
#include "BKE_tessmesh.h"
+#include "RNA_define.h"
+#include "RNA_access.h"
+#include "RNA_enum_types.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -76,6 +77,8 @@
#include "mesh_intern.h"
+#define USE_FACE_CREATE_SEL_EXTEND
+
#define MVAL_PIXEL_MARGIN 5.0f
/* allow accumulated normals to form a new direction but don't
@@ -94,10 +97,10 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
- int cuts = RNA_int_get(op->ptr, "number_cuts");
+ const int cuts = RNA_int_get(op->ptr, "number_cuts");
float smooth = 0.292f * RNA_float_get(op->ptr, "smoothness");
- float fractal = RNA_float_get(op->ptr, "fractal") / 2.5f;
- float along_normal = RNA_float_get(op->ptr, "fractal_along_normal");
+ const float fractal = RNA_float_get(op->ptr, "fractal") / 2.5f;
+ 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)
@@ -109,10 +112,10 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op)
smooth, fractal, along_normal,
cuts,
SUBDIV_SELECT_ORIG, RNA_enum_get(op->ptr, "quadcorner"),
- RNA_boolean_get(op->ptr, "quadtri"), TRUE, FALSE,
+ RNA_boolean_get(op->ptr, "quadtri"), true, false,
RNA_int_get(op->ptr, "seed"));
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -165,14 +168,14 @@ static int edbm_unsubdivide_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BMEdit_FromObject(obedit);
BMOperator bmop;
- int iterations = RNA_int_get(op->ptr, "iterations");
+ const int iterations = RNA_int_get(op->ptr, "iterations");
EDBM_op_init(em, &bmop, op,
"unsubdivide verts=%hv iterations=%i", BM_ELEM_SELECT, iterations);
BMO_op_exec(em->bm, &bmop);
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return 0;
}
@@ -181,7 +184,7 @@ static int edbm_unsubdivide_exec(bContext *C, wmOperator *op)
}
EDBM_selectmode_flush(em);
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -244,7 +247,7 @@ static short edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const c
BMO_op_exec(em->bm, &bmop);
BMO_ITER (f, &siter, bmop.slots_out, "faces.out", BM_FACE) {
- BM_face_select_set(em->bm, f, TRUE);
+ BM_face_select_set(em->bm, f, true);
/* set face vertex normals to face normal */
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
@@ -252,7 +255,7 @@ static short edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const c
}
}
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return 0;
}
@@ -270,9 +273,9 @@ static short edbm_extrude_edges_indiv(BMEditMesh *em, wmOperator *op, const char
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
BMO_op_exec(em->bm, &bmop);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, TRUE);
+ 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)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return 0;
}
@@ -287,12 +290,12 @@ static short edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char
EDBM_op_init(em, &bmop, op, "extrude_vert_indiv verts=%hv", hflag);
/* deselect original verts */
- BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "verts", BM_VERT, BM_ELEM_SELECT, TRUE);
+ BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "verts", BM_VERT, BM_ELEM_SELECT, true);
BMO_op_exec(em->bm, &bmop);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, TRUE);
+ 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)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return 0;
}
@@ -332,10 +335,7 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag,
mult_m4_m4m4(mtx, imtx, obedit->obmat);
}
- for (edge = BM_iter_new(&iter, bm, BM_EDGES_OF_MESH, NULL);
- edge;
- edge = BM_iter_step(&iter))
- {
+ BM_ITER_MESH (edge, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(edge, hflag) &&
BM_edge_is_boundary(edge) &&
BM_elem_flag_test(edge->l->f, hflag))
@@ -384,12 +384,12 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag,
zero_v3(nor);
BMO_ITER (ele, &siter, extop.slots_out, "geom.out", BM_ALL) {
- BM_elem_select_set(bm, ele, TRUE);
+ 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);
@@ -409,8 +409,8 @@ static short edbm_extrude_vert(Object *obedit, BMEditMesh *em, const char hflag,
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_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);
@@ -419,7 +419,7 @@ static short edbm_extrude_vert(Object *obedit, BMEditMesh *em, const char hflag,
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_edge_select_set(em->bm, eed, true);
}
BM_elem_flag_enable(eed, hflag & ~BM_ELEM_SELECT);
@@ -436,9 +436,9 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BMEdit_FromObject(obedit);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
- int steps = RNA_int_get(op->ptr, "steps");
+ const int steps = RNA_int_get(op->ptr, "steps");
- float offs = RNA_float_get(op->ptr, "offset");
+ 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};
short a;
@@ -463,7 +463,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
EDBM_mesh_normals_update(em);
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -585,7 +585,7 @@ static int edbm_extrude_region_exec(bContext *C, wmOperator *op)
* done.*/
EDBM_mesh_normals_update(em);
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -616,7 +616,7 @@ static int edbm_extrude_verts_exec(bContext *C, wmOperator *op)
edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT, nor);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -647,7 +647,7 @@ static int edbm_extrude_edges_exec(bContext *C, wmOperator *op)
edbm_extrude_edges_indiv(em, op, BM_ELEM_SELECT, nor);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -678,7 +678,7 @@ static int edbm_extrude_faces_exec(bContext *C, wmOperator *op)
edbm_extrude_discrete_faces(em, op, BM_ELEM_SELECT, nor);
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -706,7 +706,7 @@ static int edbm_select_all_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
- int action = RNA_enum_get(op->ptr, "action");
+ const int action = RNA_enum_get(op->ptr, "action");
switch (action) {
case SEL_TOGGLE:
@@ -778,14 +778,14 @@ void MESH_OT_select_interior_faces(wmOperatorType *ot)
}
/* *************** add-click-mesh (extrude) operator ************** */
-static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewContext vc;
BMVert *v1;
BMIter iter;
float min[3], max[3];
- int done = FALSE;
- short use_proj;
+ bool done = false;
+ bool use_proj;
em_setup_viewcontext(C, &vc);
@@ -800,13 +800,13 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent
BM_ITER_MESH (v1, &iter, vc.em->bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v1, BM_ELEM_SELECT)) {
minmax_v3v3_v3(min, max, v1->co);
- done = TRUE;
+ done = true;
}
}
/* call extrude? */
if (done) {
- const short rot_src = RNA_boolean_get(op->ptr, "rotate_source");
+ const bool rot_src = RNA_boolean_get(op->ptr, "rotate_source");
BMEdge *eed;
float vec[3], cent[3], mat[3][3];
float nor[3] = {0.0, 0.0, 0.0};
@@ -816,7 +816,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent
(float)event->mval[1]};
/* check for edges that are half selected, use for rotation */
- done = FALSE;
+ done = false;
BM_ITER_MESH (eed, &iter, vc.em->bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
float co1[2], co2[2];
@@ -837,7 +837,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent
nor[0] += (co2[1] - co1[1]);
nor[1] += -(co2[0] - co1[0]);
}
- done = TRUE;
+ done = true;
}
}
}
@@ -862,7 +862,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent
copy_v3_v3(min, cent);
mul_m4_v3(vc.obedit->obmat, min); /* view space */
- view3d_get_view_aligned_coordinate(&vc, min, event->mval, TRUE);
+ view3d_get_view_aligned_coordinate(vc.ar, min, event->mval, true);
mul_m4_v3(vc.obedit->imat, min); // back in object space
sub_v3_v3(min, cent);
@@ -906,12 +906,12 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent
BM_ELEM_SELECT, min);
}
else {
- float *curs = give_cursor(vc.scene, vc.v3d);
+ const float *curs = give_cursor(vc.scene, vc.v3d);
BMOperator bmop;
BMOIter oiter;
copy_v3_v3(min, curs);
- view3d_get_view_aligned_coordinate(&vc, min, event->mval, 0);
+ view3d_get_view_aligned_coordinate(vc.ar, min, event->mval, false);
invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
mul_m4_v3(vc.obedit->imat, min); // back in object space
@@ -920,10 +920,10 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent
BMO_op_exec(vc.em->bm, &bmop);
BMO_ITER (v1, &oiter, bmop.slots_out, "vert.out", BM_VERT) {
- BM_vert_select_set(vc.em->bm, v1, TRUE);
+ BM_vert_select_set(vc.em->bm, v1, true);
}
- if (!EDBM_op_finish(vc.em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(vc.em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
}
@@ -936,7 +936,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent
* done. */
EDBM_mesh_normals_update(vc.em);
- EDBM_update_generic(C, vc.em, TRUE);
+ EDBM_update_generic(vc.em, true, true);
return OPERATOR_FINISHED;
}
@@ -972,7 +972,7 @@ static int edbm_delete_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
- int type = RNA_enum_get(op->ptr, "type");
+ 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 */
@@ -1001,7 +1001,7 @@ static int edbm_delete_exec(bContext *C, wmOperator *op)
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -1034,7 +1034,7 @@ static int edbm_collapse_edge_exec(bContext *C, wmOperator *op)
if (!EDBM_op_callf(em, op, "collapse edges=%he", BM_ELEM_SELECT))
return OPERATOR_CANCELLED;
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -1062,7 +1062,7 @@ static int edbm_collapse_edge_loop_exec(bContext *C, wmOperator *op)
if (!EDBM_op_callf(em, op, "dissolve_edge_loop edges=%he", BM_ELEM_SELECT))
return OPERATOR_CANCELLED;
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -1098,6 +1098,140 @@ static int edbm_add_edge_face__smooth_get(BMesh *bm)
return (vote_on_smooth[0] < vote_on_smooth[1]);
}
+#ifdef USE_FACE_CREATE_SEL_EXTEND
+/**
+ * Function used to get a fixed number of edges linked to a vertex that passes a test function.
+ * This is used so we can request all boundary edges connected to a vertex for eg.
+ */
+static int edbm_add_edge_face_exec__vert_edge_lookup(BMVert *v, BMEdge *e_used, BMEdge **e_arr, const int e_arr_len,
+ bool (* func)(BMEdge *))
+{
+ BMIter iter;
+ BMEdge *e_iter;
+ int i = 0;
+ BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) {
+ if ((e_used == NULL) || (e_used != e_iter)) {
+ if (func(e_iter)) {
+ e_arr[i++] = e_iter;
+ if (i >= e_arr_len) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ return i;
+}
+
+static BMElem *edbm_add_edge_face_exec__tricky_extend_sel(BMesh *bm)
+{
+ BMIter iter;
+ bool found = false;
+
+ if (bm->totvertsel == 1 && bm->totedgesel == 0 && bm->totfacesel == 0) {
+ /* first look for 2 boundary edges */
+ BMVert *v;
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ BMEdge *ed_pair[3];
+ if (
+ ((edbm_add_edge_face_exec__vert_edge_lookup(v, NULL, ed_pair, 3, BM_edge_is_wire) == 2) &&
+ (BM_edge_share_face_check(ed_pair[0], ed_pair[1]) == false)) ||
+
+ ((edbm_add_edge_face_exec__vert_edge_lookup(v, NULL, ed_pair, 3, BM_edge_is_boundary) == 2) &&
+ (BM_edge_share_face_check(ed_pair[0], ed_pair[1]) == false))
+ )
+ {
+ BMEdge *e_other = BM_edge_exists(BM_edge_other_vert(ed_pair[0], v),
+ BM_edge_other_vert(ed_pair[1], v));
+ BM_edge_select_set(bm, ed_pair[0], true);
+ BM_edge_select_set(bm, ed_pair[1], true);
+ if (e_other) {
+ BM_edge_select_set(bm, e_other, true);
+ }
+ return (BMElem *)v;
+ }
+ }
+ }
+ else if (bm->totvertsel == 2 && bm->totedgesel == 1 && bm->totfacesel == 0) {
+ /* first look for 2 boundary edges */
+ BMEdge *e;
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ BMEdge *ed_pair_v1[2];
+ BMEdge *ed_pair_v2[2];
+ if (
+ ((edbm_add_edge_face_exec__vert_edge_lookup(e->v1, e, ed_pair_v1, 2, BM_edge_is_wire) == 1) &&
+ (edbm_add_edge_face_exec__vert_edge_lookup(e->v2, e, ed_pair_v2, 2, BM_edge_is_wire) == 1) &&
+ (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) &&
+ (BM_edge_share_face_check(e, ed_pair_v2[0]) == false)) ||
+
+ ((edbm_add_edge_face_exec__vert_edge_lookup(e->v1, e, ed_pair_v1, 2, BM_edge_is_boundary) == 1) &&
+ (edbm_add_edge_face_exec__vert_edge_lookup(e->v2, e, ed_pair_v2, 2, BM_edge_is_boundary) == 1) &&
+ (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) &&
+ (BM_edge_share_face_check(e, ed_pair_v2[0]) == false))
+ )
+ {
+ BMVert *v1_other = BM_edge_other_vert(ed_pair_v1[0], e->v1);
+ BMVert *v2_other = BM_edge_other_vert(ed_pair_v2[0], e->v2);
+ BMEdge *e_other = (v1_other != v2_other) ? BM_edge_exists(v1_other, v2_other) : NULL;
+ BM_edge_select_set(bm, ed_pair_v1[0], true);
+ BM_edge_select_set(bm, ed_pair_v2[0], true);
+ if (e_other) {
+ BM_edge_select_set(bm, e_other, true);
+ }
+ return (BMElem *)e;
+ }
+ }
+ }
+
+ return NULL;
+}
+static void edbm_add_edge_face_exec__tricky_finalize_sel(BMesh *bm, BMElem *ele_desel, BMFace *f)
+{
+ /* now we need to find the edge that isnt connected to this element */
+ BM_select_history_clear(bm);
+
+ if (ele_desel->head.htype == BM_VERT) {
+ BMLoop *l = BM_face_vert_share_loop(f, (BMVert *)ele_desel);
+ BLI_assert(f->len == 3);
+ BM_face_select_set(bm, f, false);
+ BM_vert_select_set(bm, (BMVert *)ele_desel, false);
+
+ BM_edge_select_set(bm, l->next->e, true);
+ BM_select_history_store(bm, l->next->e);
+ }
+ else {
+ BMLoop *l = BM_face_edge_share_loop(f, (BMEdge *)ele_desel);
+ BLI_assert(f->len == 4 || f->len == 3);
+ BM_face_select_set(bm, f, false);
+ BM_edge_select_set(bm, (BMEdge *)ele_desel, false);
+ if (f->len == 4) {
+ BM_edge_select_set(bm, l->next->next->e, true);
+ BM_select_history_store(bm, l->next->next->e);
+ }
+ else {
+ BM_vert_select_set(bm, l->next->next->v, true);
+ BM_select_history_store(bm, l->next->next->v);
+ }
+ }
+}
+#endif /* USE_FACE_CREATE_SEL_EXTEND */
+
static int edbm_add_edge_face_exec(bContext *C, wmOperator *op)
{
BMOperator bmop;
@@ -1106,6 +1240,15 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op)
const short use_smooth = edbm_add_edge_face__smooth_get(em->bm);
/* when this is used to dissolve we could avoid this, but checking isnt too slow */
+#ifdef USE_FACE_CREATE_SEL_EXTEND
+ BMElem *ele_desel;
+ BMFace *ele_desel_face;
+
+ /* be extra clever, figure out if a partial selection should be extended so we can create geometry
+ * with single vert or single edge selection */
+ ele_desel = edbm_add_edge_face_exec__tricky_extend_sel(em->bm);
+#endif
+
if (!EDBM_op_init(em, &bmop, op,
"contextual_create geom=%hfev mat_nr=%i use_smooth=%b",
BM_ELEM_SELECT, em->mat_nr, use_smooth))
@@ -1114,14 +1257,28 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op)
}
BMO_op_exec(em->bm, &bmop);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE);
- 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)) {
+#ifdef USE_FACE_CREATE_SEL_EXTEND
+ /* normally we would want to leave the new geometry selected,
+ * but being able to press F many times to add geometry is too useful! */
+ if (ele_desel &&
+ (BMO_slot_buffer_count(bmop.slots_out, "faces.out") == 1) &&
+ (ele_desel_face = BMO_slot_buffer_get_first(bmop.slots_out, "faces.out")))
+ {
+ edbm_add_edge_face_exec__tricky_finalize_sel(em->bm, ele_desel, ele_desel_face);
+ }
+ else
+#endif
+ {
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
+ 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;
}
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -1152,7 +1309,7 @@ static int edbm_mark_seam(bContext *C, wmOperator *op)
BMesh *bm = em->bm;
BMEdge *eed;
BMIter iter;
- int clear = RNA_boolean_get(op->ptr, "clear");
+ const bool clear = RNA_boolean_get(op->ptr, "clear");
/* auto-enable seams drawing */
if (clear == 0) {
@@ -1176,7 +1333,7 @@ static int edbm_mark_seam(bContext *C, wmOperator *op)
}
ED_uvedit_live_unwrap(scene, obedit);
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, false);
return OPERATOR_FINISHED;
}
@@ -1206,7 +1363,7 @@ static int edbm_mark_sharp(bContext *C, wmOperator *op)
BMesh *bm = em->bm;
BMEdge *eed;
BMIter iter;
- int clear = RNA_boolean_get(op->ptr, "clear");
+ const bool clear = RNA_boolean_get(op->ptr, "clear");
/* auto-enable sharp edge drawing */
if (clear == 0) {
@@ -1230,7 +1387,7 @@ static int edbm_mark_sharp(bContext *C, wmOperator *op)
}
}
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, false);
return OPERATOR_FINISHED;
}
@@ -1266,13 +1423,13 @@ static int edbm_vert_connect(bContext *C, wmOperator *op)
}
BMO_op_exec(bm, &bmop);
len = BMO_slot_get(bmop.slots_out, "edges.out")->len;
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
else {
EDBM_selectmode_flush(em); /* so newly created edges get the selection state from the vertex */
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return len ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
@@ -1306,11 +1463,11 @@ static int edbm_edge_split_exec(bContext *C, wmOperator *op)
}
BMO_op_exec(bm, &bmop);
len = BMO_slot_get(bmop.slots_out, "edges.out")->len;
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return len ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
@@ -1343,18 +1500,18 @@ static int edbm_duplicate_exec(bContext *C, wmOperator *op)
BMO_op_exec(em->bm, &bmop);
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, TRUE);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
-static int edbm_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int edbm_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
WM_cursor_wait(1);
edbm_duplicate_exec(C, op);
@@ -1388,7 +1545,7 @@ static int edbm_flip_normals_exec(bContext *C, wmOperator *op)
if (!EDBM_op_callf(em, op, "reverse_faces faces=%hf", BM_ELEM_SELECT))
return OPERATOR_CANCELLED;
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, false);
return OPERATOR_FINISHED;
}
@@ -1409,8 +1566,8 @@ void MESH_OT_flip_normals(wmOperatorType *ot)
}
static const EnumPropertyItem direction_items[] = {
- {FALSE, "CW", 0, "Clockwise", ""},
- {TRUE, "CCW", 0, "Counter Clockwise", ""},
+ {false, "CW", 0, "Clockwise", ""},
+ {true, "CCW", 0, "Counter Clockwise", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -1422,7 +1579,7 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op)
BMOperator bmop;
BMEdge *eed;
BMIter iter;
- const int use_ccw = RNA_boolean_get(op->ptr, "use_ccw");
+ const bool use_ccw = RNA_boolean_get(op->ptr, "use_ccw");
int tot = 0;
if (em->bm->totedgesel == 0) {
@@ -1457,19 +1614,19 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op)
/* avoids leaving old verts selected which can be a problem running multiple times,
* since this means the edges become selected around the face which then attempt to rotate */
- BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "edges", BM_EDGE, BM_ELEM_SELECT, TRUE);
+ BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "edges", BM_EDGE, BM_ELEM_SELECT, true);
BMO_op_exec(em->bm, &bmop);
/* edges may rotate into hidden vertices, if this does _not_ run we get an ilogical state */
- BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_HIDDEN, TRUE);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, TRUE);
+ BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_HIDDEN, true);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
EDBM_selectmode_flush(em);
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -1489,7 +1646,7 @@ void MESH_OT_edge_rotate(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_boolean(ot->srna, "use_ccw", FALSE, "Counter Clockwise", "");
+ RNA_def_boolean(ot->srna, "use_ccw", false, "Counter Clockwise", "");
}
@@ -1500,7 +1657,7 @@ static int edbm_hide_exec(bContext *C, wmOperator *op)
EDBM_mesh_hide(em, RNA_boolean_get(op->ptr, "unselected"));
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, false);
return OPERATOR_FINISHED;
}
@@ -1530,7 +1687,7 @@ static int edbm_reveal_exec(bContext *C, wmOperator *UNUSED(op))
EDBM_mesh_reveal(em);
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, false);
return OPERATOR_FINISHED;
}
@@ -1557,13 +1714,13 @@ static int edbm_normals_make_consistent_exec(bContext *C, wmOperator *op)
/* doflip has to do with bmesh_rationalize_normals, it's an internal
* thing */
- if (!EDBM_op_callf(em, op, "recalc_face_normals faces=%hf use_flip=%b", BM_ELEM_SELECT, TRUE))
+ if (!EDBM_op_callf(em, op, "recalc_face_normals faces=%hf use_flip=%b", BM_ELEM_SELECT, true))
return OPERATOR_CANCELLED;
if (RNA_boolean_get(op->ptr, "inside"))
EDBM_op_callf(em, op, "reverse_faces faces=%hf", BM_ELEM_SELECT);
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, false);
return OPERATOR_FINISHED;
}
@@ -1592,17 +1749,17 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
ModifierData *md;
- int mirrx = FALSE, mirry = FALSE, mirrz = FALSE;
+ int mirrx = false, mirry = false, mirrz = false;
int i, repeat;
float clip_dist = 0.0f;
- int xaxis = RNA_boolean_get(op->ptr, "xaxis");
- int yaxis = RNA_boolean_get(op->ptr, "yaxis");
- int zaxis = RNA_boolean_get(op->ptr, "zaxis");
+ const bool xaxis = RNA_boolean_get(op->ptr, "xaxis");
+ const bool yaxis = RNA_boolean_get(op->ptr, "yaxis");
+ const bool zaxis = RNA_boolean_get(op->ptr, "zaxis");
/* mirror before smooth */
if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
- EDBM_verts_mirror_cache_begin(em, TRUE);
+ EDBM_verts_mirror_cache_begin(em, true);
}
/* if there is a mirror modifier with clipping, flag the verts that
@@ -1614,11 +1771,11 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
if (mmd->flag & MOD_MIR_CLIPPING) {
if (mmd->flag & MOD_MIR_AXIS_X)
- mirrx = TRUE;
+ mirrx = true;
if (mmd->flag & MOD_MIR_AXIS_Y)
- mirry = TRUE;
+ mirry = true;
if (mmd->flag & MOD_MIR_AXIS_Z)
- mirrz = TRUE;
+ mirrz = true;
clip_dist = mmd->tolerance;
}
@@ -1645,7 +1802,7 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
EDBM_verts_mirror_cache_end(em);
}
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, false);
return OPERATOR_FINISHED;
}
@@ -1674,9 +1831,9 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
- int usex = TRUE, usey = TRUE, usez = TRUE, preserve_volume = TRUE;
+ int usex = true, usey = true, usez = true, preserve_volume = true;
int i, repeat;
- float lambda;
+ float lambda_factor;
float lambda_border;
BMIter fiter;
BMFace *f;
@@ -1693,11 +1850,11 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
/* mirror before smooth */
if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
- EDBM_verts_mirror_cache_begin(em, TRUE);
+ EDBM_verts_mirror_cache_begin(em, true);
}
repeat = RNA_int_get(op->ptr, "repeat");
- lambda = RNA_float_get(op->ptr, "lambda");
+ lambda_factor = RNA_float_get(op->ptr, "lambda_factor");
lambda_border = RNA_float_get(op->ptr, "lambda_border");
usex = RNA_boolean_get(op->ptr, "use_x");
usey = RNA_boolean_get(op->ptr, "use_y");
@@ -1708,8 +1865,8 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
for (i = 0; i < repeat; i++) {
if (!EDBM_op_callf(em, op,
- "smooth_laplacian_vert verts=%hv lambda=%f lambda_border=%f use_x=%b use_y=%b use_z=%b preserve_volume=%b",
- BM_ELEM_SELECT, lambda, lambda_border, usex, usey, usez, preserve_volume))
+ "smooth_laplacian_vert verts=%hv lambda_factor=%f lambda_border=%f use_x=%b use_y=%b use_z=%b preserve_volume=%b",
+ BM_ELEM_SELECT, lambda_factor, lambda_border, usex, usey, usez, preserve_volume))
{
return OPERATOR_CANCELLED;
}
@@ -1721,7 +1878,7 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
EDBM_verts_mirror_cache_end(em);
}
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, false);
return OPERATOR_FINISHED;
}
@@ -1742,13 +1899,13 @@ void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot)
RNA_def_int(ot->srna, "repeat", 1, 1, 200,
"Number of iterations to smooth the mesh", "", 1, 200);
- RNA_def_float(ot->srna, "lambda", 0.00005f, 0.0000001f, 1000.0f,
+ 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, "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");
}
@@ -1775,7 +1932,7 @@ static int edbm_faces_shade_smooth_exec(bContext *C, wmOperator *UNUSED(op))
mesh_set_smooth_faces(em, 1);
- EDBM_update_generic(C, em, FALSE);
+ EDBM_update_generic(em, false, false);
return OPERATOR_FINISHED;
}
@@ -1802,7 +1959,7 @@ static int edbm_faces_shade_flat_exec(bContext *C, wmOperator *UNUSED(op))
mesh_set_smooth_faces(em, 0);
- EDBM_update_generic(C, em, FALSE);
+ EDBM_update_generic(em, false, false);
return OPERATOR_FINISHED;
}
@@ -1832,7 +1989,7 @@ static int edbm_rotate_uvs_exec(bContext *C, wmOperator *op)
BMOperator bmop;
/* get the direction from RNA */
- const int use_ccw = RNA_boolean_get(op->ptr, "use_ccw");
+ const bool use_ccw = RNA_boolean_get(op->ptr, "use_ccw");
/* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
EDBM_op_init(em, &bmop, op, "rotate_uvs faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw);
@@ -1841,11 +1998,11 @@ static int edbm_rotate_uvs_exec(bContext *C, wmOperator *op)
BMO_op_exec(em->bm, &bmop);
/* finish the operator */
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
- EDBM_update_generic(C, em, FALSE);
+ EDBM_update_generic(em, false, false);
/* we succeeded */
return OPERATOR_FINISHED;
@@ -1864,11 +2021,11 @@ static int edbm_reverse_uvs_exec(bContext *C, wmOperator *op)
BMO_op_exec(em->bm, &bmop);
/* finish the operator */
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
- EDBM_update_generic(C, em, FALSE);
+ EDBM_update_generic(em, false, false);
/* we succeeded */
return OPERATOR_FINISHED;
@@ -1881,7 +2038,7 @@ static int edbm_rotate_colors_exec(bContext *C, wmOperator *op)
BMOperator bmop;
/* get the direction from RNA */
- const int use_ccw = RNA_boolean_get(op->ptr, "use_ccw");
+ const bool use_ccw = RNA_boolean_get(op->ptr, "use_ccw");
/* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */
EDBM_op_init(em, &bmop, op, "rotate_colors faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw);
@@ -1890,12 +2047,12 @@ static int edbm_rotate_colors_exec(bContext *C, wmOperator *op)
BMO_op_exec(em->bm, &bmop);
/* finish the operator */
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
/* dependencies graph and notification stuff */
- EDBM_update_generic(C, em, FALSE);
+ EDBM_update_generic(em, false, false);
/* we succeeded */
return OPERATOR_FINISHED;
@@ -1915,11 +2072,11 @@ static int edbm_reverse_colors_exec(bContext *C, wmOperator *op)
BMO_op_exec(em->bm, &bmop);
/* finish the operator */
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
- EDBM_update_generic(C, em, FALSE);
+ EDBM_update_generic(em, false, false);
/* we succeeded */
return OPERATOR_FINISHED;
@@ -1940,7 +2097,7 @@ void MESH_OT_uvs_rotate(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_boolean(ot->srna, "use_ccw", FALSE, "Counter Clockwise", "");
+ RNA_def_boolean(ot->srna, "use_ccw", false, "Counter Clockwise", "");
}
//void MESH_OT_uvs_mirror(wmOperatorType *ot)
@@ -1977,7 +2134,7 @@ void MESH_OT_colors_rotate(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_boolean(ot->srna, "use_ccw", FALSE, "Counter Clockwise", "");
+ RNA_def_boolean(ot->srna, "use_ccw", false, "Counter Clockwise", "");
}
void MESH_OT_colors_reverse(wmOperatorType *ot)
@@ -1999,43 +2156,54 @@ void MESH_OT_colors_reverse(wmOperatorType *ot)
}
-static int merge_firstlast(BMEditMesh *em, int first, int uvmerge, wmOperator *wmop)
+static bool merge_firstlast(BMEditMesh *em, const bool use_first, const bool use_uvmerge, wmOperator *wmop)
{
BMVert *mergevert;
BMEditSelection *ese;
+ /* operator could be called directly from shortcut or python,
+ * so do extra check for data here
+ */
+
/* do sanity check in mergemenu in edit.c ?*/
- if (first == 0) {
+ if (use_first == false) {
+ if (!em->bm->selected.last || ((BMEditSelection *)em->bm->selected.last)->htype != BM_VERT)
+ return false;
+
ese = em->bm->selected.last;
mergevert = (BMVert *)ese->ele;
}
else {
+ if (!em->bm->selected.first || ((BMEditSelection *)em->bm->selected.first)->htype != BM_VERT)
+ return false;
+
ese = em->bm->selected.first;
mergevert = (BMVert *)ese->ele;
}
if (!BM_elem_flag_test(mergevert, BM_ELEM_SELECT))
- return OPERATOR_CANCELLED;
+ return false;
- if (uvmerge) {
+ if (use_uvmerge) {
if (!EDBM_op_callf(em, wmop, "pointmerge_facedata verts=%hv vert_snap=%e", BM_ELEM_SELECT, mergevert))
- return OPERATOR_CANCELLED;
+ return false;
}
if (!EDBM_op_callf(em, wmop, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, mergevert->co))
- return OPERATOR_CANCELLED;
+ return false;
- return OPERATOR_FINISHED;
+ return true;
}
-static int merge_target(BMEditMesh *em, Scene *scene, View3D *v3d, Object *ob,
- int target, int uvmerge, wmOperator *wmop)
+static bool merge_target(BMEditMesh *em, Scene *scene, View3D *v3d, Object *ob,
+ const bool use_cursor, const bool use_uvmerge, wmOperator *wmop)
{
BMIter iter;
BMVert *v;
- float *vco = NULL, co[3], cent[3] = {0.0f, 0.0f, 0.0f};
+ float co[3], cent[3] = {0.0f, 0.0f, 0.0f};
+ const float *vco = NULL;
- if (target) {
+ if (use_cursor) {
vco = give_cursor(scene, v3d);
copy_v3_v3(co, vco);
mul_m4_v3(ob->imat, co);
@@ -2051,7 +2219,7 @@ static int merge_target(BMEditMesh *em, Scene *scene, View3D *v3d, Object *ob,
}
if (!i)
- return OPERATOR_CANCELLED;
+ return false;
fac = 1.0f / (float)i;
mul_v3_fl(cent, fac);
@@ -2060,17 +2228,17 @@ static int merge_target(BMEditMesh *em, Scene *scene, View3D *v3d, Object *ob,
}
if (!vco)
- return OPERATOR_CANCELLED;
+ return false;
- if (uvmerge) {
+ if (use_uvmerge) {
if (!EDBM_op_callf(em, wmop, "average_vert_facedata verts=%hv", BM_ELEM_SELECT))
- return OPERATOR_CANCELLED;
+ return false;
}
if (!EDBM_op_callf(em, wmop, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, co))
- return OPERATOR_CANCELLED;
+ return false;
- return OPERATOR_FINISHED;
+ return true;
}
static int edbm_merge_exec(bContext *C, wmOperator *op)
@@ -2079,32 +2247,37 @@ static int edbm_merge_exec(bContext *C, wmOperator *op)
View3D *v3d = CTX_wm_view3d(C);
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
- int status = 0, uvs = RNA_boolean_get(op->ptr, "uvs");
+ const int type = RNA_enum_get(op->ptr, "type");
+ const bool uvs = RNA_boolean_get(op->ptr, "uvs");
+ bool ok = false;
- switch (RNA_enum_get(op->ptr, "type")) {
+ switch (type) {
case 3:
- status = merge_target(em, scene, v3d, obedit, 0, uvs, op);
+ ok = merge_target(em, scene, v3d, obedit, false, uvs, op);
break;
case 4:
- status = merge_target(em, scene, v3d, obedit, 1, uvs, op);
+ ok = merge_target(em, scene, v3d, obedit, true, uvs, op);
break;
case 1:
- status = merge_firstlast(em, 0, uvs, op);
+ ok = merge_firstlast(em, false, uvs, op);
break;
case 6:
- status = merge_firstlast(em, 1, uvs, op);
+ ok = merge_firstlast(em, true, uvs, op);
break;
case 5:
- status = 1;
+ ok = true;
if (!EDBM_op_callf(em, op, "collapse edges=%he", BM_ELEM_SELECT))
- status = 0;
+ ok = false;
break;
+ default:
+ BLI_assert(0);
}
- if (!status)
+ if (!ok) {
return OPERATOR_CANCELLED;
+ }
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -2188,8 +2361,8 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BMEdit_FromObject(obedit);
BMOperator bmop;
const float threshold = RNA_float_get(op->ptr, "threshold");
- int use_unselected = RNA_boolean_get(op->ptr, "use_unselected");
- int totvert_orig = em->bm->totvert;
+ const bool use_unselected = RNA_boolean_get(op->ptr, "use_unselected");
+ const int totvert_orig = em->bm->totvert;
int count;
if (use_unselected) {
@@ -2198,7 +2371,7 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op)
BM_ELEM_SELECT, threshold);
BMO_op_exec(em->bm, &bmop);
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
}
@@ -2213,7 +2386,7 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
}
@@ -2221,7 +2394,7 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op)
count = totvert_orig - em->bm->totvert;
BKE_reportf(op->reports, RPT_INFO, "Removed %d vertices", count);
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -2271,7 +2444,7 @@ static int edbm_select_vertex_path_exec(bContext *C, wmOperator *op)
BMEditSelection *sv, *ev;
/* get the type from RNA */
- int type = RNA_enum_get(op->ptr, "type");
+ const int type = RNA_enum_get(op->ptr, "type");
/* first try to find vertices in edit selection */
sv = em->bm->selected.last;
@@ -2291,8 +2464,12 @@ static int edbm_select_vertex_path_exec(bContext *C, wmOperator *op)
if (!BM_elem_flag_test(eve, BM_ELEM_SELECT) || BM_elem_flag_test(eve, BM_ELEM_HIDDEN))
continue;
- if (svert == NULL) svert = eve;
- else if (evert == NULL) evert = eve;
+ if (svert == NULL) {
+ svert = eve;
+ }
+ else if (evert == NULL) {
+ evert = eve;
+ }
else {
/* more than two vertices are selected,
* show warning message and cancel operator */
@@ -2319,16 +2496,16 @@ static int edbm_select_vertex_path_exec(bContext *C, wmOperator *op)
/* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */
/* select the output */
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, TRUE);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, true);
/* finish the operator */
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
EDBM_selectmode_flush(em);
- EDBM_update_generic(C, em, FALSE);
+ EDBM_update_generic(em, false, false);
/* we succeeded */
return OPERATOR_FINISHED;
@@ -2388,7 +2565,7 @@ static void shape_propagate(BMEditMesh *em, wmOperator *op)
//TAG Mesh Objects that share this data
for (base = scene->base.first; base; base = base->next) {
if (base->object && base->object->data == me) {
- base->object->recalc = OB_RECALC_DATA;
+ DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
}
}
#endif
@@ -2403,7 +2580,7 @@ static int edbm_shape_propagate_to_all_exec(bContext *C, wmOperator *op)
shape_propagate(em, op);
- EDBM_update_generic(C, em, FALSE);
+ EDBM_update_generic(em, false, false);
return OPERATOR_FINISHED;
}
@@ -2435,11 +2612,12 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op)
BMVert *eve;
BMIter iter;
float co[3], *sco;
- float blend = RNA_float_get(op->ptr, "blend");
- int shape = RNA_enum_get(op->ptr, "shape");
- int add = RNA_boolean_get(op->ptr, "add");
int totshape;
+ const float blend = RNA_float_get(op->ptr, "blend");
+ const int shape = RNA_enum_get(op->ptr, "shape");
+ const bool use_add = RNA_boolean_get(op->ptr, "add");
+
/* sanity check */
totshape = CustomData_number_of_layers(&em->bm->vdata, CD_SHAPEKEY);
if (totshape == 0 || shape < 0 || shape >= totshape)
@@ -2459,7 +2637,7 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op)
sco = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, shape);
copy_v3_v3(co, sco);
- if (add) {
+ if (use_add) {
/* in add mode, we add relative shape key offset */
if (kb) {
float *rco = CustomData_bmesh_get_n(&em->bm->vdata, eve->head.data, CD_SHAPEKEY, kb->relative);
@@ -2474,7 +2652,7 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op)
}
}
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, false);
return OPERATOR_FINISHED;
}
@@ -2530,7 +2708,6 @@ static void edbm_blend_from_shape_ui(bContext *C, wmOperator *op)
void MESH_OT_blend_from_shape(wmOperatorType *ot)
{
PropertyRNA *prop;
- static EnumPropertyItem shape_items[] = {{0, NULL, 0, NULL, NULL}};
/* identifiers */
ot->name = "Blend From Shape";
@@ -2547,7 +2724,7 @@ void MESH_OT_blend_from_shape(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_enum(ot->srna, "shape", shape_items, 0, "Shape", "Shape key to use for blending");
+ 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_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");
@@ -2559,8 +2736,8 @@ static int edbm_select_axis_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
BMEditSelection *ese = em->bm->selected.last;
- int axis = RNA_enum_get(op->ptr, "axis");
- int mode = RNA_enum_get(op->ptr, "mode"); /* -1 == aligned, 0 == neg, 1 == pos */
+ const int axis = RNA_enum_get(op->ptr, "axis");
+ const int mode = RNA_enum_get(op->ptr, "mode"); /* -1 == aligned, 0 == neg, 1 == pos */
if (ese == NULL || ese->htype != BM_VERT) {
BKE_report(op->reports, RPT_WARNING, "This operator requires an active vertex (last selected)");
@@ -2582,15 +2759,15 @@ static int edbm_select_axis_exec(bContext *C, wmOperator *op)
switch (mode) {
case -1: /* aligned */
if (fabsf(ev->co[axis] - value) < limit)
- BM_vert_select_set(em->bm, ev, TRUE);
+ BM_vert_select_set(em->bm, ev, true);
break;
case 0: /* neg */
if (ev->co[axis] > value)
- BM_vert_select_set(em->bm, ev, TRUE);
+ BM_vert_select_set(em->bm, ev, true);
break;
case 1: /* pos */
if (ev->co[axis] < value)
- BM_vert_select_set(em->bm, ev, TRUE);
+ BM_vert_select_set(em->bm, ev, true);
break;
}
}
@@ -2644,7 +2821,7 @@ static int edbm_solidify_exec(bContext *C, wmOperator *op)
BMesh *bm = em->bm;
BMOperator bmop;
- float thickness = RNA_float_get(op->ptr, "thickness");
+ const float thickness = RNA_float_get(op->ptr, "thickness");
if (!EDBM_op_init(em, &bmop, op, "solidify geom=%hf thickness=%f", BM_ELEM_SELECT, thickness)) {
return OPERATOR_CANCELLED;
@@ -2653,19 +2830,19 @@ static int edbm_solidify_exec(bContext *C, wmOperator *op)
/* deselect only the faces in the region to be solidified (leave wire
* edges and loose verts selected, as there will be no corresponding
* geometry selected below) */
- BMO_slot_buffer_hflag_disable(bm, bmop.slots_in, "geom", BM_FACE, BM_ELEM_SELECT, TRUE);
+ BMO_slot_buffer_hflag_disable(bm, bmop.slots_in, "geom", BM_FACE, BM_ELEM_SELECT, true);
/* run the solidify operator */
BMO_op_exec(bm, &bmop);
/* select the newly generated faces */
- BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, TRUE);
+ BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -2890,7 +3067,8 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
BMOperator bmop;
float isect = 0.0f;
int len = 0, isected, i;
- short numcuts = 1, mode = RNA_int_get(op->ptr, "type");
+ short numcuts = 1;
+ const short mode = RNA_int_get(op->ptr, "type");
BMOpSlot *slot_edge_percents;
/* allocd vars */
@@ -2930,7 +3108,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
screen_vert_coords = sco = MEM_mallocN(bm->totvert * sizeof(float) * 2, __func__);
BM_ITER_MESH_INDEX (bv, &iter, bm, BM_VERTS_OF_MESH, i) {
- if (ED_view3d_project_float_object(ar, bv->co, *sco, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_object(ar, bv->co, *sco, V3D_PROJ_TEST_CLIP_NEAR) != V3D_PROJ_RET_OK) {
copy_v2_fl(*sco, FLT_MAX); /* set error value */
}
BM_elem_index_set(bv, i); /* set_ok */
@@ -2948,7 +3126,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
/* store percentage of edge cut for KNIFE_EXACT here.*/
slot_edge_percents = BMO_slot_get(bmop.slots_in, "edge_percents");
for (be = BM_iter_new(&iter, bm, BM_EDGES_OF_MESH, NULL); be; be = BM_iter_step(&iter)) {
- int is_cut = FALSE;
+ bool is_cut = false;
if (BM_elem_flag_test(be, BM_ELEM_SELECT)) {
const float *sco_a = screen_vert_coords[BM_elem_index_get(be->v1)];
const float *sco_b = screen_vert_coords[BM_elem_index_get(be->v2)];
@@ -2980,17 +3158,17 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
BMO_slot_int_set(bmop.slots_in, "cuts", numcuts);
BMO_slot_int_set(bmop.slots_in, "quad_corner_type", SUBD_STRAIGHT_CUT);
- BMO_slot_bool_set(bmop.slots_in, "use_single_edge", FALSE);
- BMO_slot_bool_set(bmop.slots_in, "use_grid_fill", FALSE);
+ BMO_slot_bool_set(bmop.slots_in, "use_single_edge", false);
+ BMO_slot_bool_set(bmop.slots_in, "use_grid_fill", false);
BMO_slot_float_set(bmop.slots_in, "radius", 0);
BMO_op_exec(bm, &bmop);
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -3042,7 +3220,7 @@ static int mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh
CustomData_bmesh_init_pool(&bm_new->pdata, bm_mesh_allocsize_default.totface, BM_FACE);
base_new = ED_object_add_duplicate(bmain, scene, base_old, USER_DUP_MESH);
- /* DAG_scene_sort(bmain, scene); */ /* normally would call directly after but in this case delay recalc */
+ /* DAG_relations_tag_update(bmain); */ /* normally would call directly after but in this case delay recalc */
assign_matarar(base_new->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */
ED_base_object_select(base_new, BA_SELECT);
@@ -3055,25 +3233,25 @@ static int mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh
/* deselect loose data - this used to get deleted,
* we could de-select edges and verts only, but this turns out to be less complicated
* since de-selecting all skips selection flushing logic */
- BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE);
+ BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
- BM_mesh_normals_update(bm_new, FALSE);
+ BM_mesh_normals_update(bm_new, false);
- BM_mesh_bm_to_me(bm_new, base_new->object->data, FALSE);
+ BM_mesh_bm_to_me(bm_new, base_new->object->data, false);
BM_mesh_free(bm_new);
((Mesh *)base_new->object->data)->edit_btmesh = NULL;
- return TRUE;
+ return true;
}
-static int mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
+static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
{
/* we may have tags from previous operators */
- BM_mesh_elem_hflag_disable_all(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, FALSE);
+ BM_mesh_elem_hflag_disable_all(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, false);
/* sel -> tag */
- BM_mesh_elem_hflag_enable_test(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, TRUE, BM_ELEM_SELECT);
+ BM_mesh_elem_hflag_enable_test(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, true, BM_ELEM_SELECT);
return mesh_separate_tagged(bmain, scene, base_old, bm_old);
}
@@ -3089,7 +3267,7 @@ static void bm_mesh_hflag_flush_vert(BMesh *bm, const char hflag)
BMIter eiter;
BMIter fiter;
- int ok;
+ bool ok;
BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e->v1, hflag) &&
@@ -3102,11 +3280,11 @@ static void bm_mesh_hflag_flush_vert(BMesh *bm, const char hflag)
}
}
BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- ok = TRUE;
+ ok = true;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
if (!BM_elem_flag_test(l_iter->v, hflag)) {
- ok = FALSE;
+ ok = false;
break;
}
} while ((l_iter = l_iter->next) != l_first);
@@ -3115,17 +3293,17 @@ static void bm_mesh_hflag_flush_vert(BMesh *bm, const char hflag)
}
}
-static int mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
+static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
{
BMFace *f_cmp, *f;
BMIter iter;
- int result = FALSE;
+ bool result = false;
while ((f_cmp = BM_iter_at_index(bm_old, BM_FACES_OF_MESH, NULL, 0))) {
const short mat_nr = f_cmp->mat_nr;
int tot = 0;
- BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, FALSE);
+ BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
BM_ITER_MESH (f, &iter, bm_old, BM_FACES_OF_MESH) {
if (f->mat_nr == mat_nr) {
@@ -3155,17 +3333,17 @@ static int mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BMe
return result;
}
-static int mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
+static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
{
int i;
BMEdge *e;
BMVert *v_seed;
BMWalker walker;
- int result = FALSE;
+ bool result = false;
int max_iter = bm_old->totvert;
/* Clear all selected vertices */
- BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, FALSE);
+ BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
/* A "while (true)" loop should work here as each iteration should
* select and remove at least one vertex and when all vertices
@@ -3192,8 +3370,7 @@ static int mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh
BMW_FLAG_NOP,
BMW_NIL_LAY);
- e = BMW_begin(&walker, v_seed);
- for (; e; e = BMW_step(&walker)) {
+ for (e = BMW_begin(&walker, v_seed); e; e = BMW_step(&walker)) {
if (!BM_elem_flag_test(e->v1, BM_ELEM_TAG)) { BM_elem_flag_enable(e->v1, BM_ELEM_TAG); tot++; }
if (!BM_elem_flag_test(e->v2, BM_ELEM_TAG)) { BM_elem_flag_enable(e->v2, BM_ELEM_TAG); tot++; }
}
@@ -3219,12 +3396,23 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- int retval = 0, type = RNA_enum_get(op->ptr, "type");
+ const int type = RNA_enum_get(op->ptr, "type");
+ int retval = 0;
if (ED_operator_editmesh(C)) {
Base *base = CTX_data_active_base(C);
BMEditMesh *em = BMEdit_FromObject(base->object);
+ if (type == 0) {
+ if ((em->bm->totvertsel == 0) &&
+ (em->bm->totedgesel == 0) &&
+ (em->bm->totfacesel == 0))
+ {
+ BKE_report(op->reports, RPT_ERROR, "Nothing selected");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
/* 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);
@@ -3232,7 +3420,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
else BLI_assert(0);
if (retval) {
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
}
}
else {
@@ -3253,14 +3441,14 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
bm_old = BM_mesh_create(&bm_mesh_allocsize_default);
- BM_mesh_bm_from_me(bm_old, me, FALSE, 0);
+ BM_mesh_bm_from_me(bm_old, me, 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);
if (retval_iter) {
- BM_mesh_bm_to_me(bm_old, me, FALSE);
+ BM_mesh_bm_to_me(bm_old, me, false);
DAG_id_tag_update(&me->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
@@ -3277,7 +3465,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
if (retval) {
/* delay depsgraph recalc until all objects are duplicated */
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
return OPERATOR_FINISHED;
}
@@ -3317,22 +3505,26 @@ static int edbm_fill_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
+ const bool use_beauty = RNA_boolean_get(op->ptr, "use_beauty");
BMOperator bmop;
- if (!EDBM_op_init(em, &bmop, op, "triangle_fill edges=%he", BM_ELEM_SELECT)) {
+ if (!EDBM_op_init(em, &bmop, op,
+ "triangle_fill edges=%he use_beauty=%b",
+ BM_ELEM_SELECT, use_beauty))
+ {
return OPERATOR_CANCELLED;
}
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);
+ 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)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
@@ -3351,6 +3543,8 @@ void MESH_OT_fill(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "use_beauty", true, "Beauty", "Use best triangulation division");
}
static int edbm_beautify_fill_exec(bContext *C, wmOperator *op)
@@ -3358,10 +3552,10 @@ static int edbm_beautify_fill_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
- if (!EDBM_op_callf(em, op, "beautify_fill faces=%hf", BM_ELEM_SELECT))
+ if (!EDBM_op_callf(em, op, "beautify_fill faces=%hf edges=ae", BM_ELEM_SELECT))
return OPERATOR_CANCELLED;
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -3387,12 +3581,24 @@ static int edbm_quads_convert_to_tris_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
- int use_beauty = RNA_boolean_get(op->ptr, "use_beauty");
+ BMOperator bmop;
+ const bool use_beauty = RNA_boolean_get(op->ptr, "use_beauty");
+
+ EDBM_op_init(em, &bmop, op, "triangulate faces=%hf use_beauty=%b", BM_ELEM_SELECT, use_beauty);
+ BMO_op_exec(em->bm, &bmop);
+
+ /* now call beauty fill */
+ if (use_beauty) {
+ EDBM_op_callf(em, op,
+ "beautify_fill faces=%S edges=%S",
+ &bmop, "faces.out", &bmop, "edges.out");
+ }
- if (!EDBM_op_callf(em, op, "triangulate faces=%hf use_beauty=%b", BM_ELEM_SELECT, use_beauty))
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
+ }
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -3411,7 +3617,7 @@ void MESH_OT_quads_convert_to_tris(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "use_beauty", 1, "Beauty", "Use best triangulation division (currently quads only)");
+ RNA_def_boolean(ot->srna, "use_beauty", 1, "Beauty", "Use best triangulation division");
}
static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op)
@@ -3419,7 +3625,7 @@ static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
int dosharp, douvs, dovcols, domaterials;
- float limit = RNA_float_get(op->ptr, "limit");
+ const float limit = RNA_float_get(op->ptr, "limit");
dosharp = RNA_boolean_get(op->ptr, "sharp");
douvs = RNA_boolean_get(op->ptr, "uvs");
@@ -3433,7 +3639,7 @@ static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -3474,7 +3680,7 @@ static int edbm_dissolve_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
- int use_verts = RNA_boolean_get(op->ptr, "use_verts");
+ const bool use_verts = RNA_boolean_get(op->ptr, "use_verts");
if (em->selectmode & SCE_SELECT_FACE) {
if (!EDBM_op_callf(em, op, "dissolve_faces faces=%hf use_verts=%b", BM_ELEM_SELECT, use_verts))
@@ -3489,7 +3695,7 @@ static int edbm_dissolve_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -3519,7 +3725,7 @@ static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BMEdit_FromObject(obedit);
BMesh *bm = em->bm;
const float angle_limit = RNA_float_get(op->ptr, "angle_limit");
- const int use_dissolve_boundaries = RNA_boolean_get(op->ptr, "use_dissolve_boundaries");
+ const bool use_dissolve_boundaries = RNA_boolean_get(op->ptr, "use_dissolve_boundaries");
char dissolve_flag;
@@ -3561,7 +3767,7 @@ static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -3584,7 +3790,7 @@ 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(15.0f));
+ RNA_def_property_float_default(prop, DEG2RADF(5.0f));
RNA_def_boolean(ot->srna, "use_dissolve_boundaries", 0, "All Boundaries",
"Dissolve all vertices inbetween face boundaries");
}
@@ -3595,18 +3801,18 @@ static int edbm_split_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BMEdit_FromObject(ob);
BMOperator bmop;
- EDBM_op_init(em, &bmop, op, "split geom=%hvef use_only_faces=%b", BM_ELEM_SELECT, FALSE);
+ EDBM_op_init(em, &bmop, op, "split geom=%hvef use_only_faces=%b", BM_ELEM_SELECT, false);
BMO_op_exec(em->bm, &bmop);
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, TRUE);
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
/* Geometry has changed, need to recalc normals and looptris */
EDBM_mesh_normals_update(em);
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
@@ -3660,18 +3866,18 @@ static int edbm_spin_exec(bContext *C, wmOperator *op)
}
BMO_op_exec(bm, &spinop);
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_slot_buffer_hflag_enable(bm, spinop.slots_out, "geom_last.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, TRUE);
- if (!EDBM_op_finish(em, &spinop, op, TRUE)) {
+ BMO_slot_buffer_hflag_enable(bm, spinop.slots_out, "geom_last.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
+ if (!EDBM_op_finish(em, &spinop, op, true)) {
return OPERATOR_CANCELLED;
}
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
/* get center and axis, in global coords */
-static int edbm_spin_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int edbm_spin_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -3741,9 +3947,10 @@ static int edbm_screw_exec(bContext *C, wmOperator *op)
/* find two vertices with valence count == 1, more or less is wrong */
v1 = NULL;
v2 = NULL;
- for (eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL); eve; eve = BM_iter_step(&iter)) {
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
valence = 0;
- for (eed = BM_iter_new(&eiter, em->bm, BM_EDGES_OF_VERT, eve); eed; eed = BM_iter_step(&eiter)) {
+ BM_ITER_ELEM (eed, &eiter, eve, BM_EDGES_OF_VERT) {
if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
valence++;
}
@@ -3777,24 +3984,24 @@ static int edbm_screw_exec(bContext *C, wmOperator *op)
if (!EDBM_op_init(em, &spinop, op,
"spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i angle=%f use_duplicate=%b",
- BM_ELEM_SELECT, cent, axis, dvec, turns * steps, 360.0f * turns, FALSE))
+ BM_ELEM_SELECT, cent, axis, dvec, turns * steps, DEG2RADF(360.0f * turns), false))
{
return OPERATOR_CANCELLED;
}
BMO_op_exec(bm, &spinop);
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_slot_buffer_hflag_enable(bm, spinop.slots_out, "geom_last.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, TRUE);
- if (!EDBM_op_finish(em, &spinop, op, TRUE)) {
+ BMO_slot_buffer_hflag_enable(bm, spinop.slots_out, "geom_last.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
+ if (!EDBM_op_finish(em, &spinop, op, true)) {
return OPERATOR_CANCELLED;
}
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
/* get center and axis, in global coords */
-static int edbm_screw_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int edbm_screw_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -3822,8 +4029,8 @@ void MESH_OT_screw(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, 256);
- RNA_def_int(ot->srna, "turns", 1, 0, INT_MAX, "Turns", "Turns", 0, 256);
+ 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_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX,
"Center", "Center in global view space", -FLT_MAX, FLT_MAX);
@@ -3840,6 +4047,9 @@ static int edbm_select_face_by_sides_exec(bContext *C, wmOperator *op)
const int numverts = RNA_int_get(op->ptr, "number");
const int type = RNA_enum_get(op->ptr, "type");
+ if (!RNA_boolean_get(op->ptr, "extend"))
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
int select;
@@ -3859,12 +4069,12 @@ static int edbm_select_face_by_sides_exec(bContext *C, wmOperator *op)
break;
default:
BLI_assert(0);
- select = FALSE;
+ select = false;
break;
}
if (select) {
- BM_face_select_set(em->bm, efa, TRUE);
+ BM_face_select_set(em->bm, efa, true);
}
}
@@ -3899,9 +4109,10 @@ void MESH_OT_select_face_by_sides(wmOperatorType *ot)
/* properties */
RNA_def_int(ot->srna, "number", 4, 3, INT_MAX, "Number of Vertices", "", 3, INT_MAX);
RNA_def_enum(ot->srna, "type", type_items, 1, "Type", "Type of comparison to make");
+ RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend the selection");
}
-static int edbm_select_loose_verts_exec(bContext *C, wmOperator *UNUSED(op))
+static int edbm_select_loose_verts_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
@@ -3909,15 +4120,18 @@ static int edbm_select_loose_verts_exec(bContext *C, wmOperator *UNUSED(op))
BMEdge *eed;
BMIter iter;
+ if (!RNA_boolean_get(op->ptr, "extend"))
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (!eve->e) {
- BM_vert_select_set(em->bm, eve, TRUE);
+ BM_vert_select_set(em->bm, eve, true);
}
}
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
if (!eed->l) {
- BM_edge_select_set(em->bm, eed, TRUE);
+ BM_edge_select_set(em->bm, eed, true);
}
}
@@ -3940,17 +4154,22 @@ void MESH_OT_select_loose_verts(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
static int edbm_select_mirror_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
- int extend = RNA_boolean_get(op->ptr, "extend");
+ bool extend = RNA_boolean_get(op->ptr, "extend");
- EDBM_select_mirrored(obedit, em, extend);
- EDBM_selectmode_flush(em);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ if (em->bm->totvert && em->bm->totvertsel) {
+ EDBM_select_mirrored(obedit, em, extend);
+ EDBM_selectmode_flush(em);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
return OPERATOR_FINISHED;
}
@@ -4048,12 +4267,12 @@ static void sort_bmelem_flag(Scene *scene, Object *ob,
float co[3];
mul_v3_m4v3(co, mat, ve->co);
- pb[i] = FALSE;
+ pb[i] = false;
sb[affected[0]].org_idx = i;
sb[affected[0]++].srt = co[coidx] * fact;
}
else {
- pb[i] = TRUE;
+ pb[i] = true;
}
}
}
@@ -4068,12 +4287,12 @@ static void sort_bmelem_flag(Scene *scene, Object *ob,
mid_v3_v3v3(co, ed->v1->co, ed->v2->co);
mul_m4_v3(mat, co);
- pb[i] = FALSE;
+ pb[i] = false;
sb[affected[1]].org_idx = i;
sb[affected[1]++].srt = co[coidx] * fact;
}
else {
- pb[i] = TRUE;
+ pb[i] = true;
}
}
}
@@ -4088,12 +4307,12 @@ static void sort_bmelem_flag(Scene *scene, Object *ob,
BM_face_calc_center_mean(fa, co);
mul_m4_v3(mat, co);
- pb[i] = FALSE;
+ pb[i] = false;
sb[affected[2]].org_idx = i;
sb[affected[2]++].srt = co[coidx] * fact;
}
else {
- pb[i] = TRUE;
+ pb[i] = true;
}
}
}
@@ -4117,12 +4336,12 @@ static void sort_bmelem_flag(Scene *scene, Object *ob,
BM_ITER_MESH_INDEX (ve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
if (BM_elem_flag_test(ve, flag)) {
- pb[i] = FALSE;
+ pb[i] = false;
sb[affected[0]].org_idx = i;
sb[affected[0]++].srt = len_squared_v3v3(cur, ve->co) * fact;
}
else {
- pb[i] = TRUE;
+ pb[i] = true;
}
}
}
@@ -4136,12 +4355,12 @@ static void sort_bmelem_flag(Scene *scene, Object *ob,
float co[3];
mid_v3_v3v3(co, ed->v1->co, ed->v2->co);
- pb[i] = FALSE;
+ pb[i] = false;
sb[affected[1]].org_idx = i;
sb[affected[1]++].srt = len_squared_v3v3(cur, co) * fact;
}
else {
- pb[i] = TRUE;
+ pb[i] = true;
}
}
}
@@ -4155,12 +4374,12 @@ static void sort_bmelem_flag(Scene *scene, Object *ob,
float co[3];
BM_face_calc_center_mean(fa, co);
- pb[i] = FALSE;
+ pb[i] = false;
sb[affected[2]].org_idx = i;
sb[affected[2]++].srt = len_squared_v3v3(cur, co) * fact;
}
else {
- pb[i] = TRUE;
+ pb[i] = true;
}
}
}
@@ -4176,14 +4395,14 @@ static void sort_bmelem_flag(Scene *scene, Object *ob,
/* Reverse materials' order, not order of faces inside each mat! */
/* Note: cannot use totcol, as mat_nr may sometimes be greater... */
float srt = reverse ? (float)(MAXMAT - fa->mat_nr) : (float)fa->mat_nr;
- pb[i] = FALSE;
+ pb[i] = false;
sb[affected[2]].org_idx = i;
/* Multiplying with totface and adding i ensures us we keep current order for all faces of same mat. */
sb[affected[2]++].srt = srt * ((float)totelem[2]) + ((float)i);
/* printf("e: %d; srt: %f; final: %f\n", i, srt, srt * ((float)totface) + ((float)i));*/
}
else {
- pb[i] = TRUE;
+ pb[i] = true;
}
}
}
@@ -4277,12 +4496,12 @@ static void sort_bmelem_flag(Scene *scene, Object *ob,
BM_ITER_MESH_INDEX (ve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
if (BM_elem_flag_test(ve, flag)) {
- pb[i] = FALSE;
+ pb[i] = false;
sb[affected[0]].org_idx = i;
sb[affected[0]++].srt = BLI_frand();
}
else {
- pb[i] = TRUE;
+ pb[i] = true;
}
}
}
@@ -4294,12 +4513,12 @@ static void sort_bmelem_flag(Scene *scene, Object *ob,
BM_ITER_MESH_INDEX (ed, &iter, em->bm, BM_EDGES_OF_MESH, i) {
if (BM_elem_flag_test(ed, flag)) {
- pb[i] = FALSE;
+ pb[i] = false;
sb[affected[1]].org_idx = i;
sb[affected[1]++].srt = BLI_frand();
}
else {
- pb[i] = TRUE;
+ pb[i] = true;
}
}
}
@@ -4311,12 +4530,12 @@ static void sort_bmelem_flag(Scene *scene, Object *ob,
BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) {
if (BM_elem_flag_test(fa, flag)) {
- pb[i] = FALSE;
+ pb[i] = false;
sb[affected[2]].org_idx = i;
sb[affected[2]++].srt = BLI_frand();
}
else {
- pb[i] = TRUE;
+ pb[i] = true;
}
}
}
@@ -4329,12 +4548,12 @@ static void sort_bmelem_flag(Scene *scene, Object *ob,
BM_ITER_MESH_INDEX (ve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
if (BM_elem_flag_test(ve, flag)) {
- pb[i] = FALSE;
+ pb[i] = false;
sb[affected[0]].org_idx = i;
sb[affected[0]++].srt = (float)-i;
}
else {
- pb[i] = TRUE;
+ pb[i] = true;
}
}
}
@@ -4345,12 +4564,12 @@ static void sort_bmelem_flag(Scene *scene, Object *ob,
BM_ITER_MESH_INDEX (ed, &iter, em->bm, BM_EDGES_OF_MESH, i) {
if (BM_elem_flag_test(ed, flag)) {
- pb[i] = FALSE;
+ pb[i] = false;
sb[affected[1]].org_idx = i;
sb[affected[1]++].srt = (float)-i;
}
else {
- pb[i] = TRUE;
+ pb[i] = true;
}
}
}
@@ -4361,12 +4580,12 @@ static void sort_bmelem_flag(Scene *scene, Object *ob,
BM_ITER_MESH_INDEX (fa, &iter, em->bm, BM_FACES_OF_MESH, i) {
if (BM_elem_flag_test(fa, flag)) {
- pb[i] = FALSE;
+ pb[i] = false;
sb[affected[2]].org_idx = i;
sb[affected[2]++].srt = (float)-i;
}
else {
- pb[i] = TRUE;
+ pb[i] = true;
}
}
}
@@ -4436,9 +4655,9 @@ static int edbm_sort_elements_exec(bContext *C, wmOperator *op)
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = ED_view3d_context_rv3d(C);
- int action = RNA_enum_get(op->ptr, "type");
+ const int action = RNA_enum_get(op->ptr, "type");
PropertyRNA *prop_elem_types = RNA_struct_find_property(op->ptr, "elements");
- int reverse = RNA_boolean_get(op->ptr, "reverse");
+ const bool use_reverse = RNA_boolean_get(op->ptr, "reverse");
unsigned int seed = RNA_int_get(op->ptr, "seed");
int elem_types = 0;
@@ -4465,32 +4684,32 @@ static int edbm_sort_elements_exec(bContext *C, wmOperator *op)
}
sort_bmelem_flag(scene, ob, v3d, rv3d,
- elem_types, BM_ELEM_SELECT, action, reverse, seed);
+ elem_types, BM_ELEM_SELECT, action, use_reverse, seed);
return OPERATOR_FINISHED;
}
-static int edbm_sort_elements_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
+static bool edbm_sort_elements_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
{
const char *prop_id = RNA_property_identifier(prop);
- int action = RNA_enum_get(ptr, "type");
+ const int action = RNA_enum_get(ptr, "type");
/* Only show seed for randomize action! */
- if (strcmp(prop_id, "seed") == 0) {
+ if (STREQ(prop_id, "seed")) {
if (action == SRT_RANDOMIZE)
- return TRUE;
+ return true;
else
- return FALSE;
+ return false;
}
/* Hide seed for reverse and randomize actions! */
- if (strcmp(prop_id, "reverse") == 0) {
+ if (STREQ(prop_id, "reverse")) {
if (ELEM(action, SRT_RANDOMIZE, SRT_REVERSE))
- return FALSE;
+ return false;
else
- return TRUE;
+ return true;
}
- return TRUE;
+ return true;
}
static void edbm_sort_elements_ui(bContext *C, wmOperator *op)
@@ -4549,7 +4768,7 @@ void MESH_OT_sort_elements(wmOperatorType *ot)
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",
"Which elements to affect (vertices, edges and/or faces)");
- RNA_def_boolean(ot->srna, "reverse", FALSE, "Reverse", "Reverse the sorting effect");
+ 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);
}
@@ -4563,7 +4782,7 @@ static int edbm_noise_exec(bContext *C, wmOperator *op)
Tex *tex;
BMVert *eve;
BMIter iter;
- float fac = RNA_float_get(op->ptr, "factor");
+ const float fac = RNA_float_get(op->ptr, "factor");
if (em == NULL) {
return OPERATOR_FINISHED;
@@ -4595,7 +4814,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);
+ externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum, 0, NULL);
eve->co[2] += fac * tin;
}
}
@@ -4603,7 +4822,7 @@ static int edbm_noise_exec(bContext *C, wmOperator *op)
EDBM_mesh_normals_update(em);
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, false);
return OPERATOR_FINISHED;
}
@@ -4625,15 +4844,9 @@ void MESH_OT_noise(wmOperatorType *ot)
RNA_def_float(ot->srna, "factor", 0.1f, -FLT_MAX, FLT_MAX, "Factor", "", 0.0f, 1.0f);
}
-#define NEW_BEVEL 1
-
typedef struct {
BMEditMesh *em;
BMBackup mesh_backup;
-#ifndef NEW_BEVEL
- float *weights;
- int li;
-#endif
int mcenter[2];
float initial_length;
float pixel_size; /* use when mouse input is interpreted as spatial distance */
@@ -4646,104 +4859,34 @@ typedef struct {
static void edbm_bevel_update_header(wmOperator *op, bContext *C)
{
-#ifdef NEW_BEVEL
- static char str[] = "Confirm: Enter/LClick, Cancel: (Esc/RMB), offset: %s, segments: %d";
-#else
- static char str[] = "Confirm: Enter/LClick, Cancel: (Esc/RMB), factor: %s, Use Dist (D): %s: Use Even (E): %s";
- BevelData *opdata = op->customdata;
-#endif
+ const char *str = IFACE_("Confirm: Enter/LClick, Cancel: (Esc/RMB), Offset: %s, Segments: %d");
char msg[HEADER_LENGTH];
ScrArea *sa = CTX_wm_area(C);
if (sa) {
-#ifdef NEW_BEVEL
char offset_str[NUM_STR_REP_LEN];
BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "offset"));
BLI_snprintf(msg, HEADER_LENGTH, str,
offset_str,
RNA_int_get(op->ptr, "segments")
);
-#else
- char factor_str[NUM_STR_REP_LEN];
- if (hasNumInput(&opdata->num_input))
- outputNumInput(&opdata->num_input, factor_str);
- else
- BLI_snprintf(factor_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "percent"));
- BLI_snprintf(msg, HEADER_LENGTH, str,
- factor_str,
- RNA_boolean_get(op->ptr, "use_dist") ? "On" : "Off",
- RNA_boolean_get(op->ptr, "use_even") ? "On" : "Off"
- );
-#endif
ED_area_headerprint(sa, msg);
}
}
-#ifndef NEW_BEVEL
-static void edbm_bevel_recalc_weights(wmOperator *op)
-{
- float df, s, ftot;
- int i;
- int recursion = 1; /* RNA_int_get(op->ptr, "recursion"); */ /* temp removed, see comment below */
- BevelData *opdata = op->customdata;
-
- if (opdata->weights) {
- /* TODO should change to free only when new recursion is greater than old */
- MEM_freeN(opdata->weights);
- }
- opdata->weights = MEM_mallocN(sizeof(float) * recursion, "bevel weights");
-
- /* ugh, stupid math depends somewhat on angles!*/
- /* dfac = 1.0/(float)(recursion + 1); */ /* UNUSED */
- df = 1.0;
- for (i = 0, ftot = 0.0f; i < recursion; i++) {
- s = powf(df, 1.25f);
-
- opdata->weights[i] = s;
- ftot += s;
-
- df *= 2.0f;
- }
-
- mul_vn_fl(opdata->weights, recursion, 1.0f / (float)ftot);
-}
-#endif
-
static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
-#ifdef NEW_BEVEL
BevelData *opdata;
-#else
- BMIter iter;
- BMEdge *eed;
- BevelData *opdata;
- int li;
-#endif
if (em == NULL) {
return 0;
}
op->customdata = opdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator");
-
-#ifndef NEW_BEVEL
- BM_data_layer_add(em->bm, &em->bm->edata, CD_PROP_FLT);
- li = CustomData_number_of_layers(&em->bm->edata, CD_PROP_FLT) - 1;
-
- BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- float d = len_v3v3(eed->v1->co, eed->v2->co);
- float *dv = CustomData_bmesh_get_n(&em->bm->edata, eed->head.data, CD_PROP_FLT, li);
-
- *dv = d;
- }
-
- opdata->li = li;
- opdata->weights = NULL;
-#endif
opdata->em = em;
opdata->is_modal = is_modal;
@@ -4755,30 +4898,27 @@ static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal)
/* avoid the cost of allocating a bm copy */
if (is_modal)
opdata->mesh_backup = EDBM_redo_state_store(em);
-#ifndef NEW_BEVEL
- edbm_bevel_recalc_weights(op);
-#endif
return 1;
}
-static int edbm_bevel_calc(bContext *C, wmOperator *op)
+static int edbm_bevel_calc(wmOperator *op)
{
BevelData *opdata = op->customdata;
BMEditMesh *em = opdata->em;
BMOperator bmop;
-#ifdef NEW_BEVEL
- float offset = RNA_float_get(op->ptr, "offset");
- int segments = RNA_int_get(op->ptr, "segments");
+ const float offset = RNA_float_get(op->ptr, "offset");
+ const int segments = RNA_int_get(op->ptr, "segments");
+ const bool vertex_only = RNA_boolean_get(op->ptr, "vertex_only");
/* revert to original mesh */
if (opdata->is_modal) {
- EDBM_redo_state_restore(opdata->mesh_backup, em, FALSE);
+ EDBM_redo_state_restore(opdata->mesh_backup, em, false);
}
if (!EDBM_op_init(em, &bmop, op,
- "bevel geom=%hev offset=%f segments=%i",
- BM_ELEM_SELECT, offset, segments))
+ "bevel geom=%hev offset=%f segments=%i vertex_only=%b",
+ BM_ELEM_SELECT, offset, segments, vertex_only))
{
return 0;
}
@@ -4789,45 +4929,16 @@ static int edbm_bevel_calc(bContext *C, wmOperator *op)
/* not essential, but we may have some loose geometry that
* won't get bevel'd and better not leave it selected */
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
}
/* no need to de-select existing geometry */
- if (!EDBM_op_finish(em, &bmop, op, TRUE))
+ if (!EDBM_op_finish(em, &bmop, op, true))
return 0;
-#else
- int i;
-
- float factor = RNA_float_get(op->ptr, "percent") /*, dfac */ /* UNUSED */;
- int recursion = 1; /* RNA_int_get(op->ptr, "recursion"); */ /* temp removed, see comment below */
- const int use_even = RNA_boolean_get(op->ptr, "use_even");
- const int use_dist = RNA_boolean_get(op->ptr, "use_dist");
-
- /* revert to original mesh */
- if (opdata->is_modal) {
- EDBM_redo_state_restore(opdata->mesh_backup, em, FALSE);
- }
-
- for (i = 0; i < recursion; i++) {
- float fac = opdata->weights[recursion - i - 1] * factor;
-
-
- if (!EDBM_op_init(em, &bmop, op,
- "bevel geom=%hev percent=%f lengthlayer=%i use_lengths=%b use_even=%b use_dist=%b",
- BM_ELEM_SELECT, fac, opdata->li, TRUE, use_even, use_dist))
- {
- return 0;
- }
-
- BMO_op_exec(em->bm, &bmop);
- if (!EDBM_op_finish(em, &bmop, op, TRUE))
- return 0;
- }
-#endif
EDBM_mesh_normals_update(opdata->em);
- EDBM_update_generic(C, opdata->em, TRUE);
+ EDBM_update_generic(opdata->em, true, true);
return 1;
}
@@ -4841,14 +4952,9 @@ static void edbm_bevel_exit(bContext *C, wmOperator *op)
if (sa) {
ED_area_headerprint(sa, NULL);
}
-#ifndef NEW_BEVEL
- BM_data_layer_free_n(opdata->em->bm, &opdata->em->bm->edata, CD_PROP_FLT, opdata->li);
- if (opdata->weights)
- MEM_freeN(opdata->weights);
-#endif
if (opdata->is_modal) {
- EDBM_redo_state_free(&opdata->mesh_backup, NULL, FALSE);
+ EDBM_redo_state_free(&opdata->mesh_backup, NULL, false);
}
MEM_freeN(opdata);
op->customdata = NULL;
@@ -4858,8 +4964,8 @@ static int edbm_bevel_cancel(bContext *C, wmOperator *op)
{
BevelData *opdata = op->customdata;
if (opdata->is_modal) {
- EDBM_redo_state_free(&opdata->mesh_backup, opdata->em, TRUE);
- EDBM_update_generic(C, opdata->em, FALSE);
+ EDBM_redo_state_free(&opdata->mesh_backup, opdata->em, true);
+ EDBM_update_generic(opdata->em, false, true);
}
edbm_bevel_exit(C, op);
@@ -4872,12 +4978,12 @@ static int edbm_bevel_cancel(bContext *C, wmOperator *op)
/* bevel! yay!!*/
static int edbm_bevel_exec(bContext *C, wmOperator *op)
{
- if (!edbm_bevel_init(C, op, FALSE)) {
+ if (!edbm_bevel_init(C, op, false)) {
edbm_bevel_exit(C, op);
return OPERATOR_CANCELLED;
}
- if (!edbm_bevel_calc(C, op)) {
+ if (!edbm_bevel_calc(op)) {
edbm_bevel_cancel(C, op);
return OPERATOR_CANCELLED;
}
@@ -4887,7 +4993,7 @@ static int edbm_bevel_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
/* TODO make modal keymap (see fly mode) */
RegionView3D *rv3d = CTX_wm_region_view3d(C);
@@ -4895,7 +5001,7 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event)
float mlen[2];
float center_3d[3];
- if (!edbm_bevel_init(C, op, TRUE)) {
+ if (!edbm_bevel_init(C, op, true)) {
return OPERATOR_CANCELLED;
}
@@ -4914,7 +5020,7 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event)
edbm_bevel_update_header(op, C);
- if (!edbm_bevel_calc(C, op)) {
+ if (!edbm_bevel_calc(op)) {
edbm_bevel_cancel(C, op);
return OPERATOR_CANCELLED;
}
@@ -4924,14 +5030,10 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static float edbm_bevel_mval_factor(wmOperator *op, wmEvent *event)
+static float edbm_bevel_mval_factor(wmOperator *op, const wmEvent *event)
{
BevelData *opdata = op->customdata;
-#ifdef NEW_BEVEL
- int use_dist = TRUE;
-#else
- int use_dist = RNA_boolean_get(op->ptr, "use_dist");
-#endif
+ int use_dist = true;
float mdiff[2];
float factor;
@@ -4949,11 +5051,7 @@ static float edbm_bevel_mval_factor(wmOperator *op, wmEvent *event)
/* Fake shift-transform... */
if (event->shift) {
if (opdata->shift_factor < 0.0f) {
-#ifdef NEW_BEVEL
- opdata->shift_factor = RNA_float_get(op->ptr, "factor");
-#else
- opdata->shift_factor = RNA_float_get(op->ptr, "percent");
-#endif
+ opdata->shift_factor = RNA_float_get(op->ptr, "offset");
}
factor = (factor - opdata->shift_factor) * 0.1f + opdata->shift_factor;
}
@@ -4971,35 +5069,22 @@ static float edbm_bevel_mval_factor(wmOperator *op, wmEvent *event)
return factor;
}
-static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
BevelData *opdata = op->customdata;
int segments = RNA_int_get(op->ptr, "segments");
if (event->val == KM_PRESS) {
/* Try to handle numeric inputs... */
-#ifdef NEW_BEVEL
if (handleNumInput(&opdata->num_input, event)) {
float value = RNA_float_get(op->ptr, "offset");
applyNumInput(&opdata->num_input, &value);
RNA_float_set(op->ptr, "offset", value);
- edbm_bevel_calc(C, op);
- edbm_bevel_update_header(op, C);
- return OPERATOR_RUNNING_MODAL;
- }
-#else
- if (handleNumInput(&opdata->num_input, event)) {
- float factor = RNA_float_get(op->ptr, "percent");
- applyNumInput(&opdata->num_input, &factor);
- CLAMP(factor, 0.0f, 1.0f);
- RNA_float_set(op->ptr, "percent", factor);
-
- edbm_bevel_calc(C, op);
+ edbm_bevel_calc(op);
edbm_bevel_update_header(op, C);
return OPERATOR_RUNNING_MODAL;
}
-#endif
}
switch (event->type) {
@@ -5011,13 +5096,9 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event)
case MOUSEMOVE:
if (!hasNumInput(&opdata->num_input)) {
const float factor = edbm_bevel_mval_factor(op, event);
-#ifdef NEW_BEVEL
RNA_float_set(op->ptr, "offset", factor);
-#else
- RNA_float_set(op->ptr, "percent", factor);
-#endif
- edbm_bevel_calc(C, op);
+ edbm_bevel_calc(op);
edbm_bevel_update_header(op, C);
}
break;
@@ -5025,11 +5106,10 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event)
case LEFTMOUSE:
case PADENTER:
case RETKEY:
- edbm_bevel_calc(C, op);
+ edbm_bevel_calc(op);
edbm_bevel_exit(C, op);
return OPERATOR_FINISHED;
-#ifdef NEW_BEVEL
case WHEELUPMOUSE: /* change number of segments */
case PAGEUPKEY:
if (event->val == KM_RELEASE)
@@ -5037,7 +5117,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event)
segments++;
RNA_int_set(op->ptr, "segments", segments);
- edbm_bevel_calc(C, op);
+ edbm_bevel_calc(op);
edbm_bevel_update_header(op, C);
break;
@@ -5048,36 +5128,9 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event)
segments = max_ii(segments - 1, 1);
RNA_int_set(op->ptr, "segments", segments);
- edbm_bevel_calc(C, op);
+ edbm_bevel_calc(op);
edbm_bevel_update_header(op, C);
break;
-
-#else
- case EKEY:
- if (event->val == KM_PRESS) {
- int use_even = RNA_boolean_get(op->ptr, "use_even");
- RNA_boolean_set(op->ptr, "use_even", !use_even);
-
- edbm_bevel_calc(C, op);
- edbm_bevel_update_header(op, C);
- }
- break;
-
- case DKEY:
- if (event->val == KM_PRESS) {
- int use_dist = RNA_boolean_get(op->ptr, "use_dist");
- RNA_boolean_set(op->ptr, "use_dist", !use_dist);
-
- {
- const float factor = edbm_bevel_mval_factor(op, event);
- RNA_float_set(op->ptr, "percent", factor);
- }
-
- edbm_bevel_calc(C, op);
- edbm_bevel_update_header(op, C);
- }
- break;
-#endif
}
return OPERATOR_RUNNING_MODAL;
@@ -5100,19 +5153,9 @@ void MESH_OT_bevel(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING;
-#ifdef NEW_BEVEL
RNA_def_float(ot->srna, "offset", 0.0f, -FLT_MAX, FLT_MAX, "Offset", "", 0.0f, 1.0f);
RNA_def_int(ot->srna, "segments", 1, 1, 50, "Segments", "Segments for curved edge", 1, 8);
-#else
- /* take note, used as a factor _and_ a distance depending on 'use_dist' */
- RNA_def_float(ot->srna, "percent", 0.0f, -FLT_MAX, FLT_MAX, "Percentage", "", 0.0f, 1.0f);
- /* XXX, disabled for 2.63 release, needs to work much better without overlap before we can give to users. */
-/* RNA_def_int(ot->srna, "recursion", 1, 1, 50, "Recursion Level", "Recursion Level", 1, 8); */
-
- RNA_def_boolean(ot->srna, "use_even", FALSE, "Even", "Calculate evenly spaced bevel");
- RNA_def_boolean(ot->srna, "use_dist", FALSE, "Distance", "Interpret the percent in blender units");
-#endif
-
+ RNA_def_boolean(ot->srna, "vertex_only", false, "Vertex only", "Bevel only vertices");
}
static int edbm_bridge_edge_loops_exec(bContext *C, wmOperator *op)
@@ -5120,7 +5163,7 @@ static int edbm_bridge_edge_loops_exec(bContext *C, wmOperator *op)
BMOperator bmop;
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
- const int use_merge = RNA_boolean_get(op->ptr, "use_merge");
+ const bool use_merge = RNA_boolean_get(op->ptr, "use_merge");
const float merge_factor = RNA_float_get(op->ptr, "merge_factor");
EDBM_op_init(em, &bmop, op,
@@ -5130,17 +5173,17 @@ static int edbm_bridge_edge_loops_exec(bContext *C, wmOperator *op)
BMO_op_exec(em->bm, &bmop);
/* when merge is used the edges are joined and remain selected */
- if (use_merge == FALSE) {
+ if (use_merge == false) {
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
}
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
else {
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
}
@@ -5161,7 +5204,7 @@ void MESH_OT_bridge_edge_loops(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "inside", 0, "Inside", "");
- RNA_def_boolean(ot->srna, "use_merge", FALSE, "Merge", "Merge rather than creating faces");
+ RNA_def_boolean(ot->srna, "use_merge", false, "Merge", "Merge rather than creating faces");
RNA_def_float(ot->srna, "merge_factor", 0.5f, 0.0f, 1.0f, "Merge Factor", "", 0.0f, 1.0f);
}
@@ -5184,12 +5227,8 @@ static void edbm_inset_update_header(wmOperator *op, bContext *C)
{
InsetData *opdata = op->customdata;
- static const char str[] = "Confirm: Enter/LClick, "
- "Cancel: (Esc/RClick), "
- "thickness: %s, "
- "depth (Ctrl to tweak): %s (%s), "
- "Outset (O): (%s), "
- "Boundary (B): (%s)";
+ const char *str = IFACE_("Confirm: Enter/LClick, Cancel: (Esc/RClick), Thickness: %s, "
+ "Depth (Ctrl to tweak): %s (%s), Outset (O): (%s), Boundary (B): (%s)");
char msg[HEADER_LENGTH];
ScrArea *sa = CTX_wm_area(C);
@@ -5205,9 +5244,9 @@ static void edbm_inset_update_header(wmOperator *op, bContext *C)
BLI_snprintf(msg, HEADER_LENGTH, str,
flts_str,
flts_str + NUM_STR_REP_LEN,
- opdata->modify_depth ? "On" : "Off",
- RNA_boolean_get(op->ptr, "use_outset") ? "On" : "Off",
- RNA_boolean_get(op->ptr, "use_boundary") ? "On" : "Off"
+ opdata->modify_depth ? IFACE_("On") : IFACE_("Off"),
+ RNA_boolean_get(op->ptr, "use_outset") ? IFACE_("On") : IFACE_("Off"),
+ RNA_boolean_get(op->ptr, "use_boundary") ? IFACE_("On") : IFACE_("Off")
);
ED_area_headerprint(sa, msg);
@@ -5225,8 +5264,8 @@ static int edbm_inset_init(bContext *C, wmOperator *op, int is_modal)
opdata->old_thickness = 0.01;
opdata->old_depth = 0.0;
- opdata->modify_depth = FALSE;
- opdata->shift = FALSE;
+ opdata->modify_depth = false;
+ opdata->shift = false;
opdata->shift_amount = 0.0f;
opdata->is_modal = is_modal;
opdata->em = em;
@@ -5248,7 +5287,7 @@ static void edbm_inset_exit(bContext *C, wmOperator *op)
opdata = op->customdata;
if (opdata->is_modal)
- EDBM_redo_state_free(&opdata->backup, NULL, FALSE);
+ EDBM_redo_state_free(&opdata->backup, NULL, false);
if (sa) {
ED_area_headerprint(sa, NULL);
@@ -5262,8 +5301,8 @@ static int edbm_inset_cancel(bContext *C, wmOperator *op)
opdata = op->customdata;
if (opdata->is_modal) {
- EDBM_redo_state_free(&opdata->backup, opdata->em, TRUE);
- EDBM_update_generic(C, opdata->em, FALSE);
+ EDBM_redo_state_free(&opdata->backup, opdata->em, true);
+ EDBM_update_generic(opdata->em, false, true);
}
edbm_inset_exit(C, op);
@@ -5273,25 +5312,25 @@ static int edbm_inset_cancel(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int edbm_inset_calc(bContext *C, wmOperator *op)
+static int edbm_inset_calc(wmOperator *op)
{
InsetData *opdata;
BMEditMesh *em;
BMOperator bmop;
- int use_boundary = RNA_boolean_get(op->ptr, "use_boundary");
- int use_even_offset = RNA_boolean_get(op->ptr, "use_even_offset");
- int use_relative_offset = RNA_boolean_get(op->ptr, "use_relative_offset");
- float thickness = RNA_float_get(op->ptr, "thickness");
- float depth = RNA_float_get(op->ptr, "depth");
- int use_outset = RNA_boolean_get(op->ptr, "use_outset");
- int use_select_inset = RNA_boolean_get(op->ptr, "use_select_inset"); /* not passed onto the BMO */
+ const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary");
+ const bool use_even_offset = RNA_boolean_get(op->ptr, "use_even_offset");
+ const bool use_relative_offset = RNA_boolean_get(op->ptr, "use_relative_offset");
+ const float thickness = RNA_float_get(op->ptr, "thickness");
+ const float depth = RNA_float_get(op->ptr, "depth");
+ const bool use_outset = RNA_boolean_get(op->ptr, "use_outset");
+ const bool use_select_inset = RNA_boolean_get(op->ptr, "use_select_inset"); /* not passed onto the BMO */
opdata = op->customdata;
em = opdata->em;
if (opdata->is_modal) {
- EDBM_redo_state_restore(opdata->backup, em, FALSE);
+ EDBM_redo_state_restore(opdata->backup, em, false);
}
EDBM_op_init(em, &bmop, op,
@@ -5305,29 +5344,29 @@ static int edbm_inset_calc(bContext *C, wmOperator *op)
if (use_select_inset) {
/* deselect original faces/verts */
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
}
else {
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE, BM_ELEM_SELECT, FALSE);
- BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, FALSE);
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE, BM_ELEM_SELECT, false);
+ BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, false);
/* re-select faces so the verts and edges get selected too */
- BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, TRUE, BM_ELEM_SELECT);
+ BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, BM_ELEM_SELECT);
}
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return 0;
}
else {
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return 1;
}
}
static int edbm_inset_exec(bContext *C, wmOperator *op)
{
- edbm_inset_init(C, op, FALSE);
+ edbm_inset_init(C, op, false);
- if (!edbm_inset_calc(C, op)) {
+ if (!edbm_inset_calc(op)) {
edbm_inset_exit(C, op);
return OPERATOR_CANCELLED;
}
@@ -5336,14 +5375,14 @@ static int edbm_inset_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int edbm_inset_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int edbm_inset_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
InsetData *opdata;
float mlen[2];
float center_3d[3];
- edbm_inset_init(C, op, TRUE);
+ edbm_inset_init(C, op, true);
opdata = op->customdata;
@@ -5358,7 +5397,7 @@ static int edbm_inset_invoke(bContext *C, wmOperator *op, wmEvent *event)
opdata->initial_length = len_v2(mlen);
opdata->pixel_size = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f;
- edbm_inset_calc(C, op);
+ edbm_inset_calc(op);
edbm_inset_update_header(op, C);
@@ -5366,7 +5405,7 @@ static int edbm_inset_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int edbm_inset_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
InsetData *opdata = op->customdata;
@@ -5381,7 +5420,7 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event)
RNA_float_set(op->ptr, "thickness", amounts[0]);
RNA_float_set(op->ptr, "depth", amounts[1]);
- if (edbm_inset_calc(C, op)) {
+ if (edbm_inset_calc(op)) {
edbm_inset_update_header(op, C);
return OPERATOR_RUNNING_MODAL;
}
@@ -5422,7 +5461,7 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event)
RNA_float_set(op->ptr, "thickness", amount);
}
- if (edbm_inset_calc(C, op))
+ if (edbm_inset_calc(op))
edbm_inset_update_header(op, C);
else {
edbm_inset_cancel(C, op);
@@ -5434,7 +5473,7 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event)
case LEFTMOUSE:
case PADENTER:
case RETKEY:
- edbm_inset_calc(C, op);
+ edbm_inset_calc(op);
edbm_inset_exit(C, op);
return OPERATOR_FINISHED;
@@ -5445,11 +5484,11 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event)
opdata->shift_amount = RNA_float_get(op->ptr, "depth");
else
opdata->shift_amount = RNA_float_get(op->ptr, "thickness");
- opdata->shift = TRUE;
+ opdata->shift = true;
}
else {
opdata->shift_amount = 0.0f;
- opdata->shift = FALSE;
+ opdata->shift = false;
}
break;
@@ -5465,13 +5504,13 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event)
opdata->old_thickness = RNA_float_get(op->ptr, "thickness");
if (opdata->shift)
opdata->shift_amount = opdata->old_thickness;
- opdata->modify_depth = TRUE;
+ opdata->modify_depth = true;
}
else {
opdata->old_depth = RNA_float_get(op->ptr, "depth");
if (opdata->shift)
opdata->shift_amount = opdata->old_depth;
- opdata->modify_depth = FALSE;
+ opdata->modify_depth = false;
}
opdata->initial_length = len_v2(mlen);
@@ -5481,9 +5520,9 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event)
case OKEY:
if (event->val == KM_PRESS) {
- int use_outset = RNA_boolean_get(op->ptr, "use_outset");
+ const bool use_outset = RNA_boolean_get(op->ptr, "use_outset");
RNA_boolean_set(op->ptr, "use_outset", !use_outset);
- if (edbm_inset_calc(C, op)) {
+ if (edbm_inset_calc(op)) {
edbm_inset_update_header(op, C);
}
else {
@@ -5494,9 +5533,9 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event)
break;
case BKEY:
if (event->val == KM_PRESS) {
- int use_boundary = RNA_boolean_get(op->ptr, "use_boundary");
+ const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary");
RNA_boolean_set(op->ptr, "use_boundary", !use_boundary);
- if (edbm_inset_calc(C, op)) {
+ if (edbm_inset_calc(op)) {
edbm_inset_update_header(op, C);
}
else {
@@ -5531,9 +5570,9 @@ void MESH_OT_inset(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING;
/* 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_relative_offset", FALSE, "Offset Relative", "Scale the offset by surrounding geometry");
+ 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");
prop = RNA_def_float(ot->srna, "thickness", 0.01f, 0.0f, FLT_MAX, "Thickness", "", 0.0f, 10.0f);
/* use 1 rather then 10 for max else dragging the button moves too far */
@@ -5541,8 +5580,8 @@ void MESH_OT_inset(wmOperatorType *ot)
prop = RNA_def_float(ot->srna, "depth", 0.0f, -FLT_MAX, FLT_MAX, "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_outset", false, "Outset", "Outset rather than inset");
+ RNA_def_boolean(ot->srna, "use_select_inset", true, "Select Outer", "Select the new inset faces");
}
static int edbm_wireframe_exec(bContext *C, wmOperator *op)
@@ -5550,12 +5589,12 @@ static int edbm_wireframe_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
BMOperator bmop;
- const int use_boundary = RNA_boolean_get(op->ptr, "use_boundary");
- const int use_even_offset = RNA_boolean_get(op->ptr, "use_even_offset");
- const int use_replace = RNA_boolean_get(op->ptr, "use_replace");
- const int use_relative_offset = RNA_boolean_get(op->ptr, "use_relative_offset");
- const int use_crease = RNA_boolean_get(op->ptr, "use_crease");
- const float thickness = RNA_float_get(op->ptr, "thickness");
+ const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary");
+ const bool use_even_offset = RNA_boolean_get(op->ptr, "use_even_offset");
+ const bool use_replace = RNA_boolean_get(op->ptr, "use_replace");
+ const bool use_relative_offset = RNA_boolean_get(op->ptr, "use_relative_offset");
+ const bool use_crease = RNA_boolean_get(op->ptr, "use_crease");
+ const float thickness = RNA_float_get(op->ptr, "thickness");
EDBM_op_init(em, &bmop, op,
"wireframe faces=%hf use_boundary=%b use_even_offset=%b use_relative_offset=%b use_crease=%b "
@@ -5566,22 +5605,22 @@ static int edbm_wireframe_exec(bContext *C, wmOperator *op)
BMO_op_exec(em->bm, &bmop);
if (use_replace) {
- BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, FALSE);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_in, "faces", BM_FACE, BM_ELEM_TAG, FALSE);
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_in, "faces", BM_FACE, BM_ELEM_TAG, false);
BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS,
"delete geom=%hvef context=%i",
BM_ELEM_TAG, DEL_FACES);
}
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE);
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
else {
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
return OPERATOR_FINISHED;
}
}
@@ -5603,17 +5642,17 @@ 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_relative_offset", FALSE, "Offset Relative", "Scale the offset by surrounding geometry");
- RNA_def_boolean(ot->srna, "use_crease", FALSE, "Crease", "Crease hub edges for improved subsurf");
+ 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_crease", false, "Crease", "Crease hub edges for improved subsurf");
prop = RNA_def_float(ot->srna, "thickness", 0.01f, 0.0f, FLT_MAX, "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_boolean(ot->srna, "use_replace", TRUE, "Replace", "Remove original faces");
+ RNA_def_boolean(ot->srna, "use_replace", true, "Replace", "Remove original faces");
}
#ifdef WITH_BULLET
@@ -5631,7 +5670,7 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
/* Hull fails if input is coplanar */
if (BMO_error_occurred(em->bm)) {
- EDBM_op_finish(em, &bmop, op, TRUE);
+ EDBM_op_finish(em, &bmop, op, true);
return OPERATOR_CANCELLED;
}
@@ -5641,7 +5680,7 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
if (!EDBM_op_callf(em, op, "delete geom=%S context=%i",
&bmop, "geom_unused.out", DEL_ONLYTAGGED))
{
- EDBM_op_finish(em, &bmop, op, TRUE);
+ EDBM_op_finish(em, &bmop, op, true);
return OPERATOR_CANCELLED;
}
}
@@ -5651,7 +5690,7 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
if (!EDBM_op_callf(em, op, "delete geom=%S context=%i",
&bmop, "geom_holes.out", DEL_ONLYTAGGED))
{
- EDBM_op_finish(em, &bmop, op, TRUE);
+ EDBM_op_finish(em, &bmop, op, true);
return OPERATOR_CANCELLED;
}
}
@@ -5662,16 +5701,16 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
&bmop, "geom.out",
RNA_float_get(op->ptr, "limit")))
{
- EDBM_op_finish(em, &bmop, op, TRUE);
+ EDBM_op_finish(em, &bmop, op, true);
return OPERATOR_CANCELLED;
}
}
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
else {
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
EDBM_selectmode_flush(em);
return OPERATOR_FINISHED;
}
@@ -5692,19 +5731,19 @@ void MESH_OT_convex_hull(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_boolean(ot->srna, "delete_unused", TRUE,
+ RNA_def_boolean(ot->srna, "delete_unused", true,
"Delete Unused",
"Delete selected elements that are not used by the hull");
- RNA_def_boolean(ot->srna, "use_existing_faces", TRUE,
+ RNA_def_boolean(ot->srna, "use_existing_faces", true,
"Use Existing Faces",
"Skip hull triangles that are covered by a pre-existing face");
- RNA_def_boolean(ot->srna, "make_holes", FALSE,
+ RNA_def_boolean(ot->srna, "make_holes", false,
"Make Holes",
"Delete selected faces that are used by the hull");
- RNA_def_boolean(ot->srna, "join_triangles", TRUE,
+ RNA_def_boolean(ot->srna, "join_triangles", true,
"Join Triangles",
"Merge adjacent triangles into quads");
@@ -5722,11 +5761,11 @@ static int mesh_symmetrize_exec(bContext *C, wmOperator *op)
BM_ELEM_SELECT, RNA_enum_get(op->ptr, "direction"));
BMO_op_exec(em->bm, &bmop);
- if (!EDBM_op_finish(em, &bmop, op, TRUE)) {
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
else {
- EDBM_update_generic(C, em, TRUE);
+ EDBM_update_generic(em, true, true);
EDBM_selectmode_flush(em);
return OPERATOR_FINISHED;
}
@@ -5734,18 +5773,6 @@ static int mesh_symmetrize_exec(bContext *C, wmOperator *op)
void MESH_OT_symmetrize(struct wmOperatorType *ot)
{
- static EnumPropertyItem axis_direction_items[] = {
- {BMO_SYMMETRIZE_NEGATIVE_X, "NEGATIVE_X", 0, "-X to +X", ""},
- {BMO_SYMMETRIZE_POSITIVE_X, "POSITIVE_X", 0, "+X to -X", ""},
-
- {BMO_SYMMETRIZE_NEGATIVE_Y, "NEGATIVE_Y", 0, "-Y to +Y", ""},
- {BMO_SYMMETRIZE_POSITIVE_Y, "POSITIVE_Y", 0, "+Y to -Y", ""},
-
- {BMO_SYMMETRIZE_NEGATIVE_Z, "NEGATIVE_Z", 0, "-Z to +Z", ""},
- {BMO_SYMMETRIZE_POSITIVE_Z, "POSITIVE_Z", 0, "+Z to -Z", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
/* identifiers */
ot->name = "Symmetrize";
ot->description = "Enforce symmetry (both form and topological) across an axis";
@@ -5758,7 +5785,134 @@ void MESH_OT_symmetrize(struct wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "direction", axis_direction_items,
+ ot->prop = RNA_def_enum(ot->srna, "direction", symmetrize_direction_items,
BMO_SYMMETRIZE_NEGATIVE_X,
"Direction", "Which sides to copy from and to");
}
+
+#ifdef WITH_FREESTYLE
+
+static int edbm_mark_freestyle_edge(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Mesh *me = (Mesh *)obedit->data;
+ BMEditMesh *em = BMEdit_FromObject(obedit);
+ BMEdge *eed;
+ BMIter iter;
+ FreestyleEdge *fed;
+ int clear = RNA_boolean_get(op->ptr, "clear");
+
+ if (em == NULL)
+ return OPERATOR_FINISHED;
+
+ /* auto-enable Freestyle edge mark drawing */
+ if (clear == 0) {
+ me->drawflag |= ME_DRAW_FREESTYLE_EDGE;
+ }
+
+ if (!CustomData_has_layer(&em->bm->edata, CD_FREESTYLE_EDGE)) {
+ BM_data_layer_add(em->bm, &em->bm->edata, CD_FREESTYLE_EDGE);
+ }
+
+ if (clear) {
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT) && !BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+ fed = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_FREESTYLE_EDGE);
+ fed->flag &= ~FREESTYLE_EDGE_MARK;
+ }
+ }
+ }
+ else {
+ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(eed, BM_ELEM_SELECT) && !BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
+ fed = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_FREESTYLE_EDGE);
+ fed->flag |= FREESTYLE_EDGE_MARK;
+ }
+ }
+ }
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_mark_freestyle_edge(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Mark Freestyle Edge";
+ ot->description = "(un)mark selected edges as Freestyle feature edges";
+ ot->idname = "MESH_OT_mark_freestyle_edge";
+
+ /* api callbacks */
+ ot->exec = edbm_mark_freestyle_edge;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
+}
+
+static int edbm_mark_freestyle_face_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Mesh *me = (Mesh *)obedit->data;
+ BMEditMesh *em = BMEdit_FromObject(obedit);
+ BMFace *efa;
+ BMIter iter;
+ FreestyleFace *ffa;
+ int clear = RNA_boolean_get(op->ptr, "clear");
+
+ if (em == NULL) return OPERATOR_FINISHED;
+
+ /* auto-enable Freestyle face mark drawing */
+ if (!clear) {
+ me->drawflag |= ME_DRAW_FREESTYLE_FACE;
+ }
+
+ if (!CustomData_has_layer(&em->bm->pdata, CD_FREESTYLE_FACE)) {
+ BM_data_layer_add(em->bm, &em->bm->pdata, CD_FREESTYLE_FACE);
+ }
+
+ if (clear) {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ ffa = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_FREESTYLE_FACE);
+ ffa->flag &= ~FREESTYLE_FACE_MARK;
+ }
+ }
+ }
+ else {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ ffa = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_FREESTYLE_FACE);
+ ffa->flag |= FREESTYLE_FACE_MARK;
+ }
+ }
+ }
+
+ DAG_id_tag_update(obedit->data, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_mark_freestyle_face(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Mark Freestyle Face";
+ ot->description = "(un)mark selected faces for exclusion from Freestyle feature edge detection";
+ ot->idname = "MESH_OT_mark_freestyle_face";
+
+ /* api callbacks */
+ ot->exec = edbm_mark_freestyle_face_exec;
+ ot->poll = ED_operator_editmesh;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
+}
+
+#endif
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 2cf63586142..cb15fdef880 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -35,15 +35,12 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BKE_DerivedMesh.h"
-#include "BKE_bmesh.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_key.h"
-#include "BKE_library.h"
#include "BKE_mesh.h"
#include "BKE_report.h"
#include "BKE_tessmesh.h"
@@ -56,7 +53,6 @@
#include "ED_mesh.h"
#include "ED_util.h"
-#include "bmesh.h"
#include "mesh_intern.h"
@@ -118,7 +114,7 @@ void EDBM_mesh_ensure_valid_dm_hack(Scene *scene, BMEditMesh *em)
void EDBM_mesh_normals_update(BMEditMesh *em)
{
- BM_mesh_normals_update(em->bm, TRUE);
+ BM_mesh_normals_update(em->bm, true);
}
void EDBM_mesh_clear(BMEditMesh *em)
@@ -140,8 +136,10 @@ void EDBM_mesh_clear(BMEditMesh *em)
/* free tessellation data */
em->tottri = 0;
- if (em->looptris)
+ if (em->looptris) {
MEM_freeN(em->looptris);
+ em->looptris = NULL;
+ }
}
void EDBM_stats_update(BMEditMesh *em)
@@ -171,7 +169,7 @@ void EDBM_stats_update(BMEditMesh *em)
}
}
-int EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char *fmt, ...)
+bool EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char *fmt, ...)
{
BMesh *bm = em->bm;
va_list list;
@@ -181,7 +179,7 @@ int EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char *f
if (!BMO_op_vinitf(bm, bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
BKE_reportf(op->reports, RPT_ERROR, "Parse error in %s", __func__);
va_end(list);
- return 0;
+ return false;
}
if (!em->emcopy)
@@ -190,12 +188,12 @@ int EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char *f
va_end(list);
- return 1;
+ return true;
}
/* returns 0 on error, 1 on success. executes and finishes a bmesh operator */
-int EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const int report)
+bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool do_report)
{
const char *errmsg;
@@ -204,7 +202,7 @@ int EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const int r
if (BMO_error_get(em->bm, &errmsg, NULL)) {
BMEditMesh *emcopy = em->emcopy;
- if (report) {
+ if (do_report) {
BKE_report(op->reports, RPT_ERROR, errmsg);
}
@@ -221,7 +219,7 @@ int EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const int r
BMEdit_RecalcTessellation(em);
}
- return FALSE;
+ return false;
}
else {
em->emcopyusers--;
@@ -235,11 +233,11 @@ int EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const int r
em->emcopy = NULL;
}
- return TRUE;
+ return true;
}
}
-int EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...)
+bool EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...)
{
BMesh *bm = em->bm;
BMOperator bmop;
@@ -250,7 +248,7 @@ int EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...)
if (!BMO_op_vinitf(bm, &bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
BKE_reportf(op->reports, RPT_ERROR, "Parse error in %s", __func__);
va_end(list);
- return 0;
+ return false;
}
if (!em->emcopy)
@@ -260,10 +258,10 @@ int EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...)
BMO_op_exec(bm, &bmop);
va_end(list);
- return EDBM_op_finish(em, &bmop, op, TRUE);
+ return EDBM_op_finish(em, &bmop, op, true);
}
-int EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op, const char *select_slot_out, const char *fmt, ...)
+bool EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op, const char *select_slot_out, const char *fmt, ...)
{
BMOpSlot *slot_select_out;
BMesh *bm = em->bm;
@@ -276,7 +274,7 @@ int EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op, const char *select_
if (!BMO_op_vinitf(bm, &bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
BKE_reportf(op->reports, RPT_ERROR, "Parse error in %s", __func__);
va_end(list);
- return 0;
+ return false;
}
if (!em->emcopy)
@@ -288,15 +286,15 @@ int EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op, const char *select_
slot_select_out = BMO_slot_get(bmop.slots_out, select_slot_out);
hflag = slot_select_out->slot_subtype.elem & BM_ALL_NOLOOP;
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE);
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, select_slot_out, hflag, BM_ELEM_SELECT, TRUE);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, select_slot_out, hflag, BM_ELEM_SELECT, true);
va_end(list);
- return EDBM_op_finish(em, &bmop, op, TRUE);
+ return EDBM_op_finish(em, &bmop, op, true);
}
-int EDBM_op_call_silentf(BMEditMesh *em, const char *fmt, ...)
+bool EDBM_op_call_silentf(BMEditMesh *em, const char *fmt, ...)
{
BMesh *bm = em->bm;
BMOperator bmop;
@@ -306,7 +304,7 @@ int EDBM_op_call_silentf(BMEditMesh *em, const char *fmt, ...)
if (!BMO_op_vinitf(bm, &bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
va_end(list);
- return 0;
+ return false;
}
if (!em->emcopy)
@@ -316,7 +314,7 @@ int EDBM_op_call_silentf(BMEditMesh *em, const char *fmt, ...)
BMO_op_exec(bm, &bmop);
va_end(list);
- return EDBM_op_finish(em, &bmop, NULL, FALSE);
+ return EDBM_op_finish(em, &bmop, NULL, false);
}
void EDBM_selectmode_to_scene(bContext *C)
@@ -354,9 +352,9 @@ void EDBM_mesh_make(ToolSettings *ts, Scene *UNUSED(scene), Object *ob)
/* currently executing operators re-tessellates, so we can avoid doing here
* but at some point it may need to be added back. */
#if 0
- me->edit_btmesh = BMEdit_Create(bm, TRUE);
+ me->edit_btmesh = BMEdit_Create(bm, true);
#else
- me->edit_btmesh = BMEdit_Create(bm, FALSE);
+ me->edit_btmesh = BMEdit_Create(bm, false);
#endif
me->edit_btmesh->selectmode = me->edit_btmesh->bm->selectmode = ts->selectmode;
@@ -370,7 +368,7 @@ void EDBM_mesh_load(Object *ob)
Mesh *me = ob->data;
BMesh *bm = me->edit_btmesh->bm;
- BM_mesh_bm_to_me(bm, me, FALSE);
+ BM_mesh_bm_to_me(bm, me, false);
#ifdef USE_TESSFACE_DEFAULT
BKE_mesh_tessface_calc(me);
@@ -391,81 +389,129 @@ void EDBM_mesh_free(BMEditMesh *em)
BMEdit_Free(em);
}
-void EDBM_index_arrays_init(BMEditMesh *tm, int forvert, int foredge, int forface)
+
+void EDBM_index_arrays_ensure(BMEditMesh *em, const char htype)
{
- EDBM_index_arrays_free(tm);
+ /* assume if the array is non-null then its valid and no need to recalc */
+ const char htype_needed = ((em->vert_index ? 0 : BM_VERT) |
+ (em->edge_index ? 0 : BM_EDGE) |
+ (em->face_index ? 0 : BM_FACE)) & htype;
- if (forvert) {
- BMIter iter;
- BMVert *ele;
- int i = 0;
-
- tm->vert_index = MEM_mallocN(sizeof(void **) * tm->bm->totvert, "tm->vert_index");
+ BLI_assert((htype & ~BM_ALL_NOLOOP) == 0);
- ele = BM_iter_new(&iter, tm->bm, BM_VERTS_OF_MESH, NULL);
- for ( ; ele; ele = BM_iter_step(&iter)) {
- tm->vert_index[i++] = ele;
+ /* in debug mode double check we didn't need to recalculate */
+ BLI_assert(EDBM_index_arrays_check(em) == true);
+
+ if (htype_needed & BM_VERT) {
+ em->vert_index = MEM_mallocN(sizeof(void **) * em->bm->totvert, "em->vert_index");
+ }
+ if (htype_needed & BM_EDGE) {
+ em->edge_index = MEM_mallocN(sizeof(void **) * em->bm->totedge, "em->edge_index");
+ }
+ if (htype_needed & BM_FACE) {
+ em->face_index = MEM_mallocN(sizeof(void **) * em->bm->totface, "em->face_index");
+ }
+
+#pragma omp parallel sections if (em->bm->totvert + em->bm->totedge + em->bm->totface >= BM_OMP_LIMIT)
+ {
+#pragma omp section
+ {
+ if (htype_needed & BM_VERT) {
+ BM_iter_as_array(em->bm, BM_VERTS_OF_MESH, NULL, (void **)em->vert_index, em->bm->totvert);
+ }
+ }
+#pragma omp section
+ {
+ if (htype_needed & BM_EDGE) {
+ BM_iter_as_array(em->bm, BM_EDGES_OF_MESH, NULL, (void **)em->edge_index, em->bm->totedge);
+ }
+ }
+#pragma omp section
+ {
+ if (htype_needed & BM_FACE) {
+ BM_iter_as_array(em->bm, BM_FACES_OF_MESH, NULL, (void **)em->face_index, em->bm->totface);
+ }
}
}
+}
- if (foredge) {
- BMIter iter;
- BMEdge *ele;
- int i = 0;
-
- tm->edge_index = MEM_mallocN(sizeof(void **) * tm->bm->totedge, "tm->edge_index");
+/* use EDBM_index_arrays_ensure where possible to avoid full rebuild */
+void EDBM_index_arrays_init(BMEditMesh *em, const char htype)
+{
+ BLI_assert((htype & ~BM_ALL_NOLOOP) == 0);
- ele = BM_iter_new(&iter, tm->bm, BM_EDGES_OF_MESH, NULL);
- for ( ; ele; ele = BM_iter_step(&iter)) {
- tm->edge_index[i++] = ele;
- }
+ /* force recalc */
+ EDBM_index_arrays_free(em);
+ EDBM_index_arrays_ensure(em, htype);
+}
+
+void EDBM_index_arrays_free(BMEditMesh *em)
+{
+ if (em->vert_index) {
+ MEM_freeN(em->vert_index);
+ em->vert_index = NULL;
}
- if (forface) {
- BMIter iter;
- BMFace *ele;
- int i = 0;
-
- tm->face_index = MEM_mallocN(sizeof(void **) * tm->bm->totface, "tm->face_index");
+ if (em->edge_index) {
+ MEM_freeN(em->edge_index);
+ em->edge_index = NULL;
+ }
- ele = BM_iter_new(&iter, tm->bm, BM_FACES_OF_MESH, NULL);
- for ( ; ele; ele = BM_iter_step(&iter)) {
- tm->face_index[i++] = ele;
- }
+ if (em->face_index) {
+ MEM_freeN(em->face_index);
+ em->face_index = NULL;
}
}
-void EDBM_index_arrays_free(BMEditMesh *tm)
+/* debug check only - no need to optimize */
+#ifndef NDEBUG
+bool EDBM_index_arrays_check(BMEditMesh *em)
{
- if (tm->vert_index) {
- MEM_freeN(tm->vert_index);
- tm->vert_index = NULL;
+ BMIter iter;
+ BMElem *ele;
+ int i;
+
+ if (em->vert_index) {
+ BM_ITER_MESH_INDEX (ele, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ if (ele != (BMElem *)em->vert_index[i]) {
+ return false;
+ }
+ }
}
- if (tm->edge_index) {
- MEM_freeN(tm->edge_index);
- tm->edge_index = NULL;
+ if (em->edge_index) {
+ BM_ITER_MESH_INDEX (ele, &iter, em->bm, BM_EDGES_OF_MESH, i) {
+ if (ele != (BMElem *)em->edge_index[i]) {
+ return false;
+ }
+ }
}
- if (tm->face_index) {
- MEM_freeN(tm->face_index);
- tm->face_index = NULL;
+ if (em->face_index) {
+ BM_ITER_MESH_INDEX (ele, &iter, em->bm, BM_FACES_OF_MESH, i) {
+ if (ele != (BMElem *)em->face_index[i]) {
+ return false;
+ }
+ }
}
+
+ return true;
}
+#endif
-BMVert *EDBM_vert_at_index(BMEditMesh *tm, int index)
+BMVert *EDBM_vert_at_index(BMEditMesh *em, int index)
{
- return tm->vert_index && index < tm->bm->totvert ? tm->vert_index[index] : NULL;
+ return em->vert_index && index < em->bm->totvert ? em->vert_index[index] : NULL;
}
-BMEdge *EDBM_edge_at_index(BMEditMesh *tm, int index)
+BMEdge *EDBM_edge_at_index(BMEditMesh *em, int index)
{
- return tm->edge_index && index < tm->bm->totedge ? tm->edge_index[index] : NULL;
+ return em->edge_index && index < em->bm->totedge ? em->edge_index[index] : NULL;
}
-BMFace *EDBM_face_at_index(BMEditMesh *tm, int index)
+BMFace *EDBM_face_at_index(BMEditMesh *em, int index)
{
- return (tm->face_index && index < tm->bm->totface && index >= 0) ? tm->face_index[index] : NULL;
+ return (em->face_index && index < em->bm->totface && index >= 0) ? em->face_index[index] : NULL;
}
void EDBM_selectmode_flush_ex(BMEditMesh *em, const short selectmode)
@@ -500,13 +546,13 @@ void EDBM_select_more(BMEditMesh *em)
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);
+ BM_ELEM_SELECT, false, use_faces);
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);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? true : false);
BMO_op_finish(em->bm, &bmop);
- EDBM_select_flush(em);
+ EDBM_selectmode_flush(em);
}
void EDBM_select_less(BMEditMesh *em)
@@ -516,10 +562,10 @@ void EDBM_select_less(BMEditMesh *em)
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);
+ BM_ELEM_SELECT, true, use_faces);
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);
+ BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? true : false);
BMO_op_finish(em->bm, &bmop);
EDBM_selectmode_flush(em);
@@ -527,12 +573,12 @@ void EDBM_select_less(BMEditMesh *em)
void EDBM_flag_disable_all(BMEditMesh *em, const char hflag)
{
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, hflag, FALSE);
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, hflag, false);
}
void EDBM_flag_enable_all(BMEditMesh *em, const char hflag)
{
- BM_mesh_elem_hflag_enable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, hflag, TRUE);
+ BM_mesh_elem_hflag_enable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, hflag, true);
}
/**************-------------- Undo ------------*****************/
@@ -577,7 +623,7 @@ static void *editbtMesh_to_undoMesh(void *emv, void *obdata)
/* BM_mesh_validate(em->bm); */ /* for troubleshooting */
- BM_mesh_bm_to_me(em->bm, &um->me, FALSE);
+ BM_mesh_bm_to_me(em->bm, &um->me, false);
um->selectmode = em->selectmode;
um->shapenr = em->bm->shapenr;
@@ -598,12 +644,12 @@ static void undoMesh_to_editbtMesh(void *umv, void *em_v, void *UNUSED(obdata))
bm = BM_mesh_create(&bm_mesh_allocsize_default);
- BM_mesh_bm_from_me(bm, &um->me, FALSE, ob->shapenr);
+ BM_mesh_bm_from_me(bm, &um->me, false, ob->shapenr);
/* face normals need recalculation since we are not calling through an operator */
- BM_mesh_normals_update(bm, TRUE);
+ BM_mesh_normals_update(bm, true);
- em_tmp = BMEdit_Create(bm, TRUE);
+ em_tmp = BMEdit_Create(bm, true);
*em = *em_tmp;
em->selectmode = um->selectmode;
@@ -621,7 +667,7 @@ static void free_undo(void *me_v)
MEM_freeN(me->key);
}
- BKE_mesh_free(me, FALSE);
+ BKE_mesh_free(me, false);
MEM_freeN(me);
}
@@ -638,8 +684,10 @@ void undo_push_mesh(bContext *C, const char *name)
undo_editmode_push(C, name, getEditMesh, free_undo, undoMesh_to_editbtMesh, editbtMesh_to_undoMesh, NULL);
}
-/* write comment here */
-UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, int selected, int do_face_idx_array, const float limit[2])
+/**
+ * Return a new UVVertMap from the editmesh
+ */
+UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, bool use_select, const float limit[2])
{
BMVert *ev;
BMFace *efa;
@@ -652,30 +700,25 @@ UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, int selected, int do_face_idx
MLoopUV *luv;
unsigned int a;
int totverts, i, totuv;
-
- if (do_face_idx_array)
- EDBM_index_arrays_init(em, 0, 0, 1);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
- BM_mesh_elem_index_ensure(em->bm, BM_VERT);
+ BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
totverts = em->bm->totvert;
totuv = 0;
/* generate UvMapVert array */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!selected || ((!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) && BM_elem_flag_test(efa, BM_ELEM_SELECT)))
+ if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
totuv += efa->len;
+ }
}
if (totuv == 0) {
- if (do_face_idx_array)
- EDBM_index_arrays_free(em);
return NULL;
}
vmap = (UvVertMap *)MEM_callocN(sizeof(*vmap), "UvVertMap");
if (!vmap) {
- if (do_face_idx_array)
- EDBM_index_arrays_free(em);
return NULL;
}
@@ -684,14 +727,12 @@ UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, int selected, int do_face_idx
if (!vmap->vert || !vmap->buf) {
BKE_mesh_uv_vert_map_free(vmap);
- if (do_face_idx_array)
- EDBM_index_arrays_free(em);
return NULL;
}
a = 0;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!selected || ((!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) && BM_elem_flag_test(efa, BM_ELEM_SELECT))) {
+ if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
i = 0;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
buf->tfindex = i;
@@ -726,7 +767,7 @@ UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, int selected, int do_face_idx
/* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
l = BM_iter_at_index(em->bm, BM_LOOPS_OF_FACE, efa, v->tfindex);
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
uv = luv->uv;
lastv = NULL;
@@ -738,7 +779,7 @@ UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, int selected, int do_face_idx
/* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
l = BM_iter_at_index(em->bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex);
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
uv2 = luv->uv;
sub_v2_v2v2(uvdiff, uv2, uv);
@@ -762,10 +803,7 @@ UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, int selected, int do_face_idx
vmap->vert[a] = newvlist;
a++;
}
-
- if (do_face_idx_array)
- EDBM_index_arrays_free(em);
-
+
return vmap;
}
@@ -799,6 +837,8 @@ UvElementMap *EDBM_uv_element_map_create(BMEditMesh *em, int selected, int do_is
BMFace **stack;
int stacksize = 0;
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
totverts = em->bm->totvert;
@@ -811,8 +851,9 @@ UvElementMap *EDBM_uv_element_map_create(BMEditMesh *em, int selected, int do_is
/* generate UvElement array */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!selected || ((!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) && BM_elem_flag_test(efa, BM_ELEM_SELECT)))
+ if (!selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
totuv += efa->len;
+ }
}
if (totuv == 0) {
@@ -837,10 +878,9 @@ UvElementMap *EDBM_uv_element_map_create(BMEditMesh *em, int selected, int do_is
j = 0;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
island_number[j++] = INVALID_ISLAND;
- if (!selected || ((!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) && BM_elem_flag_test(efa, BM_ELEM_SELECT))) {
+ if (!selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
buf->l = l;
- buf->face = efa;
buf->separate = 0;
buf->island = INVALID_ISLAND;
buf->tfindex = i;
@@ -867,7 +907,7 @@ UvElementMap *EDBM_uv_element_map_create(BMEditMesh *em, int selected, int do_is
newvlist = v;
l = v->l;
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
uv = luv->uv;
lastv = NULL;
@@ -877,7 +917,7 @@ UvElementMap *EDBM_uv_element_map_create(BMEditMesh *em, int selected, int do_is
next = iterv->next;
l = iterv->l;
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
uv2 = luv->uv;
sub_v2_v2v2(uvdiff, uv2, uv);
@@ -912,7 +952,7 @@ UvElementMap *EDBM_uv_element_map_create(BMEditMesh *em, int selected, int do_is
for (i = 0; i < totuv; i++) {
if (element_map->buf[i].island == INVALID_ISLAND) {
element_map->buf[i].island = nislands;
- stack[0] = element_map->buf[i].face;
+ stack[0] = element_map->buf[i].l->f;
island_number[BM_elem_index_get(stack[0])] = nislands;
stacksize = 1;
@@ -926,12 +966,11 @@ UvElementMap *EDBM_uv_element_map_create(BMEditMesh *em, int selected, int do_is
if (element->separate)
initelement = element;
- if (element->face == efa) {
+ if (element->l->f == efa) {
/* found the uv corresponding to our face and vertex. Now fill it to the buffer */
element->island = nislands;
map[element - element_map->buf] = islandbufsize;
islandbuf[islandbufsize].l = element->l;
- islandbuf[islandbufsize].face = element->face;
islandbuf[islandbufsize].separate = element->separate;
islandbuf[islandbufsize].tfindex = element->tfindex;
islandbuf[islandbufsize].island = nislands;
@@ -941,9 +980,9 @@ UvElementMap *EDBM_uv_element_map_create(BMEditMesh *em, int selected, int do_is
if (element->separate && element != initelement)
break;
- if (island_number[BM_elem_index_get(element->face)] == INVALID_ISLAND) {
- stack[stacksize++] = element->face;
- island_number[BM_elem_index_get(element->face)] = nislands;
+ if (island_number[BM_elem_index_get(element->l->f)] == INVALID_ISLAND) {
+ stack[stacksize++] = element->l->f;
+ island_number[BM_elem_index_get(element->l->f)] = nislands;
}
}
break;
@@ -1024,7 +1063,7 @@ UvElement *ED_uv_element_get(UvElementMap *map, BMFace *efa, BMLoop *l)
element = map->vert[BM_elem_index_get(l->v)];
for (; element; element = element->next)
- if (element->face == efa)
+ if (element->l->f == efa)
return element;
return NULL;
@@ -1094,7 +1133,7 @@ static BMVert *cache_mirr_intptr_as_bmvert(intptr_t *index_lookup, int index)
* preference */
#define BM_SEARCH_MAXDIST_MIRR 0.00002f
#define BM_CD_LAYER_ID "__mirror_index"
-void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const short use_select)
+void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const bool use_select)
{
Mesh *me = (Mesh *)em->ob->data;
BMesh *bm = em->bm;
@@ -1110,10 +1149,7 @@ void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const short use_select)
topo = 1;
}
- if (!em->vert_index) {
- EDBM_index_arrays_init(em, 1, 0, 0);
- em->mirr_free_arrays = 1;
- }
+ EDBM_index_arrays_ensure(em, BM_VERT);
if (!CustomData_get_layer_named(&bm->vdata, CD_PROP_INT, BM_CD_LAYER_ID)) {
BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_INT, BM_CD_LAYER_ID);
@@ -1126,7 +1162,7 @@ void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const short use_select)
BM_mesh_elem_index_ensure(bm, BM_VERT);
if (topo) {
- ED_mesh_mirrtopo_init(me, -1, &mesh_topo_store, TRUE);
+ ED_mesh_mirrtopo_init(me, -1, &mesh_topo_store, true);
}
else {
tree = BMBVH_NewBVH(em, 0, NULL, NULL);
@@ -1205,11 +1241,6 @@ void EDBM_verts_mirror_cache_clear(BMEditMesh *em, BMVert *v)
void EDBM_verts_mirror_cache_end(BMEditMesh *em)
{
- if (em->mirr_free_arrays) {
- MEM_freeN(em->vert_index);
- em->vert_index = NULL;
- }
-
em->mirror_cdlayer = -1;
}
@@ -1252,7 +1283,7 @@ void EDBM_mesh_hide(BMEditMesh *em, int swap)
BM_ITER_MESH (ele, &iter, em->bm, itermode) {
if (BM_elem_flag_test(ele, BM_ELEM_SELECT) ^ swap)
- BM_elem_hide_set(em->bm, ele, TRUE);
+ BM_elem_hide_set(em->bm, ele, true);
}
EDBM_selectmode_flush(em);
@@ -1276,14 +1307,15 @@ void EDBM_mesh_reveal(BMEditMesh *em)
int sels[3] = {(em->selectmode & SCE_SELECT_VERTEX),
(em->selectmode & SCE_SELECT_EDGE),
(em->selectmode & SCE_SELECT_FACE), };
-
- BMIter iter;
- BMElem *ele;
int i;
/* Use tag flag to remember what was hidden before all is revealed.
* BM_ELEM_HIDDEN --> BM_ELEM_TAG */
+#pragma omp parallel for schedule(dynamic) if (em->bm->totvert + em->bm->totedge + em->bm->totface >= BM_OMP_LIMIT)
for (i = 0; i < 3; i++) {
+ BMIter iter;
+ BMElem *ele;
+
BM_ITER_MESH (ele, &iter, em->bm, iter_types[i]) {
BM_elem_flag_set(ele, BM_ELEM_TAG, BM_elem_flag_test(ele, BM_ELEM_HIDDEN));
}
@@ -1294,13 +1326,16 @@ void EDBM_mesh_reveal(BMEditMesh *em)
/* Select relevant just-revealed elements */
for (i = 0; i < 3; i++) {
+ BMIter iter;
+ BMElem *ele;
+
if (!sels[i]) {
continue;
}
BM_ITER_MESH (ele, &iter, em->bm, iter_types[i]) {
if (BM_elem_flag_test(ele, BM_ELEM_TAG)) {
- BM_elem_select_set(em->bm, ele, TRUE);
+ BM_elem_select_set(em->bm, ele, true);
}
}
}
@@ -1313,14 +1348,22 @@ void EDBM_mesh_reveal(BMEditMesh *em)
/* so many tools call these that we better make it a generic function.
*/
-void EDBM_update_generic(bContext *C, BMEditMesh *em, const short do_tessface)
+void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_destructive)
{
Object *ob = em->ob;
/* order of calling isn't important */
DAG_id_tag_update(ob->data, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, ob->data);
if (do_tessface) {
BMEdit_RecalcTessellation(em);
}
+
+ if (is_destructive) {
+ EDBM_index_arrays_free(em);
+ }
+ else {
+ /* in debug mode double check we didn't need to recalculate */
+ BLI_assert(EDBM_index_arrays_check(em) == true);
+ }
}
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index e9906f852de..20633aa0c87 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -28,14 +28,8 @@
* \ingroup edmesh
*/
-
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-
#include "MEM_guardedalloc.h"
-#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -46,17 +40,12 @@
#include "BLI_path_util.h"
#include "BLI_array.h"
#include "BLI_math.h"
-#include "BLI_edgehash.h"
-#include "BLI_linklist.h"
-#include "BLI_listbase.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
-#include "BKE_displist.h"
#include "BKE_image.h"
#include "BKE_library.h"
#include "BKE_main.h"
-#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_report.h"
#include "BKE_tessmesh.h"
@@ -72,10 +61,9 @@
#include "ED_uvedit.h"
#include "ED_view3d.h"
-#include "RE_render_ext.h"
-
#include "mesh_intern.h"
+
static CustomData *mesh_customdata_get_type(Mesh *me, const char htype, int *r_tot)
{
CustomData *data;
@@ -135,9 +123,8 @@ static CustomData *mesh_customdata_get_type(Mesh *me, const char htype, int *r_t
}
#define GET_CD_DATA(me, data) (me->edit_btmesh ? &me->edit_btmesh->bm->data : &me->data)
-static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *layer)
+static void delete_customdata_layer(Mesh *me, CustomDataLayer *layer)
{
- Mesh *me = ob->data;
CustomData *data;
void *actlayerdata, *rndlayerdata, *clonelayerdata, *stencillayerdata, *layerdata = layer->data;
int type = layer->type;
@@ -171,12 +158,9 @@ static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *la
}
else {
CustomData_free_layer_active(data, type, tot);
- mesh_update_customdata_pointers(me, TRUE);
+ BKE_mesh_update_customdata_pointers(me, true);
}
- if (!CustomData_has_layer(data, type) && (type == CD_MLOOPCOL && (ob->mode & OB_MODE_VERTEX_PAINT)))
- ED_object_toggle_modes(C, OB_MODE_VERTEX_PAINT);
-
/* reconstruct active layer */
if (actlayerdata != layerdata) {
/* find index */
@@ -356,12 +340,12 @@ int ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me)
}
/* note: keep in sync with ED_mesh_color_add */
-int ED_mesh_uv_texture_add(bContext *C, Mesh *me, const char *name, int active_set)
+int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set)
{
BMEditMesh *em;
int layernum_dst;
- short is_init = FALSE;
+ bool is_init = false;
if (me->edit_btmesh) {
em = me->edit_btmesh;
@@ -388,7 +372,7 @@ int ED_mesh_uv_texture_add(bContext *C, Mesh *me, const char *name, int active_s
const int layernum_src = CustomData_get_active_layer(&em->bm->ldata, CD_MLOOPUV);
BM_data_layer_copy(em->bm, &em->bm->ldata, CD_MLOOPUV, layernum_src, layernum_dst);
- is_init = TRUE;
+ is_init = true;
}
if (active_set || layernum_dst == 0) {
CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPUV, layernum_dst);
@@ -403,7 +387,7 @@ int ED_mesh_uv_texture_add(bContext *C, Mesh *me, const char *name, int active_s
CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DUPLICATE, me->mtpoly, me->totpoly, name);
CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DUPLICATE, me->mloopuv, me->totloop, name);
CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface, name);
- is_init = TRUE;
+ is_init = true;
}
else {
CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, name);
@@ -418,46 +402,77 @@ int ED_mesh_uv_texture_add(bContext *C, Mesh *me, const char *name, int active_s
CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum_dst);
}
- mesh_update_customdata_pointers(me, TRUE);
+ BKE_mesh_update_customdata_pointers(me, true);
}
/* don't overwrite our copied coords */
- if (is_init == FALSE) {
+ if (is_init == false) {
ED_mesh_uv_loop_reset_ex(me, layernum_dst);
}
DAG_id_tag_update(&me->id, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, me);
return layernum_dst;
}
-int ED_mesh_uv_texture_remove(bContext *C, Object *ob, Mesh *me)
+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);
CustomDataLayer *cdlp, *cdlu;
int index;
- index = CustomData_get_active_layer_index(pdata, CD_MTEXPOLY);
+ index = CustomData_get_layer_index_n(pdata, CD_MTEXPOLY, n);
cdlp = (index == -1) ? NULL : &pdata->layers[index];
- index = CustomData_get_active_layer_index(ldata, CD_MLOOPUV);
+ index = CustomData_get_layer_index_n(ldata, CD_MLOOPUV, n);
cdlu = (index == -1) ? NULL : &ldata->layers[index];
-
+
if (!cdlp || !cdlu)
- return 0;
+ return false;
+
+ delete_customdata_layer(me, cdlp);
+ delete_customdata_layer(me, cdlu);
- delete_customdata_layer(C, ob, cdlp);
- delete_customdata_layer(C, ob, cdlu);
-
DAG_id_tag_update(&me->id, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, me);
- return 1;
+ return true;
+}
+bool ED_mesh_uv_texture_remove_active(Mesh *me)
+{
+ /* texpoly/uv are assumed to be in sync */
+ CustomData *pdata = GET_CD_DATA(me, pdata);
+ const int n = CustomData_get_active_layer(pdata, CD_MTEXPOLY);
+
+ /* double check active layers align! */
+#ifdef DEBUG
+ CustomData *ldata = GET_CD_DATA(me, ldata);
+ BLI_assert(CustomData_get_active_layer(ldata, CD_MLOOPUV) == n);
+#endif
+
+ if (n != -1) {
+ return ED_mesh_uv_texture_remove_index(me, n);
+ }
+ else {
+ return false;
+ }
+}
+bool ED_mesh_uv_texture_remove_named(Mesh *me, const char *name)
+{
+ /* texpoly/uv are assumed to be in sync */
+ CustomData *pdata = GET_CD_DATA(me, pdata);
+ const int n = CustomData_get_named_layer(pdata, CD_MTEXPOLY, name);
+ if (n != -1) {
+ return ED_mesh_uv_texture_remove_index(me, n);
+ }
+ else {
+ return false;
+ }
}
/* note: keep in sync with ED_mesh_uv_texture_add */
-int ED_mesh_color_add(bContext *C, Scene *UNUSED(scene), Object *UNUSED(ob), Mesh *me, const char *name, int active_set)
+int ED_mesh_color_add(Mesh *me, const char *name, const bool active_set)
{
BMEditMesh *em;
int layernum;
@@ -475,7 +490,7 @@ int ED_mesh_color_add(bContext *C, Scene *UNUSED(scene), Object *UNUSED(ob), Mes
/* 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_MLOOPUV, layernum, layernum_dst);
+ BM_data_layer_copy(em->bm, &em->bm->ldata, CD_MLOOPCOL, layernum, layernum_dst);
}
if (active_set || layernum == 0) {
CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPCOL, layernum);
@@ -501,51 +516,54 @@ int ED_mesh_color_add(bContext *C, Scene *UNUSED(scene), Object *UNUSED(ob), Mes
CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
}
- mesh_update_customdata_pointers(me, TRUE);
+ BKE_mesh_update_customdata_pointers(me, true);
}
DAG_id_tag_update(&me->id, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, me);
return layernum;
}
-int ED_mesh_color_remove(bContext *C, Object *ob, Mesh *me)
+bool ED_mesh_color_remove_index(Mesh *me, const int n)
{
CustomData *ldata = GET_CD_DATA(me, ldata);
CustomDataLayer *cdl;
int index;
- index = CustomData_get_active_layer_index(ldata, CD_MLOOPCOL);
+ index = CustomData_get_layer_index_n(ldata, CD_MLOOPCOL, n);
cdl = (index == -1) ? NULL : &ldata->layers[index];
if (!cdl)
- return 0;
+ return false;
- delete_customdata_layer(C, ob, cdl);
+ delete_customdata_layer(me, cdl);
DAG_id_tag_update(&me->id, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, me);
- return 1;
+ return true;
}
-
-int ED_mesh_color_remove_named(bContext *C, Object *ob, Mesh *me, const char *name)
+bool ED_mesh_color_remove_active(Mesh *me)
{
CustomData *ldata = GET_CD_DATA(me, ldata);
- CustomDataLayer *cdl;
- int index;
-
- index = CustomData_get_named_layer_index(ldata, CD_MLOOPCOL, name);
- cdl = (index == -1) ? NULL : &ldata->layers[index];
-
- if (!cdl)
- return 0;
-
- delete_customdata_layer(C, ob, cdl);
- DAG_id_tag_update(&me->id, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
-
- return 1;
+ const int n = CustomData_get_active_layer(ldata, CD_MLOOPCOL);
+ if (n != -1) {
+ return ED_mesh_color_remove_index(me, n);
+ }
+ else {
+ return false;
+ }
+}
+bool ED_mesh_color_remove_named(Mesh *me, const char *name)
+{
+ CustomData *ldata = GET_CD_DATA(me, ldata);
+ const int n = CustomData_get_named_layer(ldata, CD_MLOOPCOL, name);
+ if (n != -1) {
+ return ED_mesh_color_remove_index(me, n);
+ }
+ else {
+ return false;
+ }
}
/*********************** UV texture operators ************************/
@@ -562,7 +580,7 @@ static int mesh_uv_texture_add_exec(bContext *C, wmOperator *UNUSED(op))
Object *ob = ED_object_context(C);
Mesh *me = ob->data;
- if (ED_mesh_uv_texture_add(C, me, NULL, TRUE) == -1)
+ if (ED_mesh_uv_texture_add(me, NULL, true) == -1)
return OPERATOR_CANCELLED;
return OPERATOR_FINISHED;
@@ -583,18 +601,24 @@ void MESH_OT_uv_texture_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int drop_named_image_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
- Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
+ Base *base;
Image *ima = NULL;
Mesh *me;
Object *obedit;
int exitmode = 0;
- char name[MAX_ID_NAME - 2];
+ if (v3d == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No 3D View Available");
+ return OPERATOR_CANCELLED;
+ }
+
+ base = ED_view3d_give_base_under_cursor(C, event->mval);
+
/* Check context */
if (base == NULL || base->object->type != OB_MESH) {
BKE_report(op->reports, RPT_ERROR, "Not an object or mesh");
@@ -609,6 +633,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, wmEvent *event)
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);
}
@@ -654,7 +679,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, wmEvent *event)
void MESH_OT_drop_named_image(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Assign Image to UV Map";
+ ot->name = "Drop Image to Mesh UV Map";
ot->description = "Assign Image to active UV Map, or create an UV Map";
ot->idname = "MESH_OT_drop_named_image";
@@ -663,7 +688,7 @@ void MESH_OT_drop_named_image(wmOperatorType *ot)
ot->invoke = drop_named_image_invoke;
/* flags */
- ot->flag = OPTYPE_UNDO;
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
/* properties */
RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Image name to assign");
@@ -675,7 +700,7 @@ static int mesh_uv_texture_remove_exec(bContext *C, wmOperator *UNUSED(op))
Object *ob = ED_object_context(C);
Mesh *me = ob->data;
- if (!ED_mesh_uv_texture_remove(C, ob, me))
+ if (!ED_mesh_uv_texture_remove_active(me))
return OPERATOR_CANCELLED;
return OPERATOR_FINISHED;
@@ -700,11 +725,10 @@ void MESH_OT_uv_texture_remove(wmOperatorType *ot)
static int mesh_vertex_color_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_context(C);
Mesh *me = ob->data;
- if (ED_mesh_color_add(C, scene, ob, me, NULL, TRUE) == -1)
+ if (ED_mesh_color_add(me, NULL, true) == -1)
return OPERATOR_CANCELLED;
return OPERATOR_FINISHED;
@@ -730,7 +754,7 @@ static int mesh_vertex_color_remove_exec(bContext *C, wmOperator *UNUSED(op))
Object *ob = ED_object_context(C);
Mesh *me = ob->data;
- if (!ED_mesh_color_remove(C, ob, me))
+ if (!ED_mesh_color_remove_active(me))
return OPERATOR_CANCELLED;
return OPERATOR_FINISHED;
@@ -762,7 +786,7 @@ static int mesh_customdata_clear_exec__internal(bContext *C,
int tot;
CustomData *data = mesh_customdata_get_type(me, htype, &tot);
- BLI_assert(CustomData_layertype_is_singleton(type) == TRUE);
+ BLI_assert(CustomData_layertype_is_singleton(type) == true);
if (CustomData_has_layer(data, type)) {
if (me->edit_btmesh) {
@@ -791,21 +815,21 @@ static int mesh_customdata_clear_mask_poll(bContext *C)
/* special case - can't run this if we're in sculpt mode */
if (ob->mode & OB_MODE_SCULPT) {
- return FALSE;
+ return false;
}
if (me->id.lib == NULL) {
CustomData *data = GET_CD_DATA(me, vdata);
if (CustomData_has_layer(data, CD_PAINT_MASK)) {
- return TRUE;
+ return true;
}
data = GET_CD_DATA(me, ldata);
if (CustomData_has_layer(data, CD_GRID_PAINT_MASK)) {
- return TRUE;
+ return true;
}
}
}
- return FALSE;
+ return false;
}
static int mesh_customdata_clear_mask_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -848,11 +872,11 @@ static int mesh_customdata_clear_skin_poll(bContext *C)
if (me->id.lib == NULL) {
CustomData *data = GET_CD_DATA(me, vdata);
if (CustomData_has_layer(data, CD_MVERT_SKIN)) {
- return TRUE;
+ return true;
}
}
}
- return FALSE;
+ return false;
}
static int mesh_customdata_clear_skin_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -880,20 +904,20 @@ void ED_mesh_update(Mesh *mesh, bContext *C, int calc_edges, int calc_tessface)
{
int *polyindex = NULL;
float (*face_nors)[3];
- int tessface_input = FALSE;
+ bool tessface_input = false;
if (mesh->totface > 0 && mesh->totpoly == 0) {
BKE_mesh_convert_mfaces_to_mpolys(mesh);
/* would only be converting back again, don't bother */
- tessface_input = TRUE;
+ tessface_input = true;
}
if (calc_edges || ((mesh->totpoly || mesh->totface) && mesh->totedge == 0))
- BKE_mesh_calc_edges(mesh, calc_edges);
+ BKE_mesh_calc_edges(mesh, calc_edges, true);
if (calc_tessface) {
- if (tessface_input == FALSE) {
+ if (tessface_input == false) {
BKE_mesh_tessface_calc(mesh);
}
}
@@ -916,7 +940,7 @@ void ED_mesh_update(Mesh *mesh, bContext *C, int calc_edges, int calc_tessface)
mesh->totloop, mesh->totpoly,
NULL /* polyNors_r */,
mesh->mface, mesh->totface,
- polyindex, face_nors, FALSE);
+ polyindex, face_nors, false);
#else
BKE_mesh_calc_normals(mesh->mvert, mesh->totvert,
mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly,
@@ -947,7 +971,7 @@ static void mesh_add_verts(Mesh *mesh, int len)
CustomData_free(&mesh->vdata, mesh->totvert);
mesh->vdata = vdata;
- mesh_update_customdata_pointers(mesh, FALSE);
+ BKE_mesh_update_customdata_pointers(mesh, false);
/* scan the input list and insert the new vertices */
@@ -991,7 +1015,7 @@ static void mesh_add_edges(Mesh *mesh, int len)
CustomData_free(&mesh->edata, mesh->totedge);
mesh->edata = edata;
- mesh_update_customdata_pointers(mesh, FALSE); /* new edges don't change tessellation */
+ BKE_mesh_update_customdata_pointers(mesh, false); /* new edges don't change tessellation */
/* set default flags */
medge = &mesh->medge[mesh->totedge];
@@ -1021,7 +1045,7 @@ static void mesh_add_tessfaces(Mesh *mesh, int len)
CustomData_free(&mesh->fdata, mesh->totface);
mesh->fdata = fdata;
- mesh_update_customdata_pointers(mesh, TRUE);
+ BKE_mesh_update_customdata_pointers(mesh, true);
/* set default flags */
mface = &mesh->mface[mesh->totface];
@@ -1050,7 +1074,7 @@ static void mesh_add_loops(Mesh *mesh, int len)
CustomData_free(&mesh->ldata, mesh->totloop);
mesh->ldata = ldata;
- mesh_update_customdata_pointers(mesh, TRUE);
+ BKE_mesh_update_customdata_pointers(mesh, true);
mesh->totloop = totloop;
}
@@ -1075,7 +1099,7 @@ static void mesh_add_polys(Mesh *mesh, int len)
CustomData_free(&mesh->pdata, mesh->totpoly);
mesh->pdata = pdata;
- mesh_update_customdata_pointers(mesh, TRUE);
+ BKE_mesh_update_customdata_pointers(mesh, true);
/* set default flags */
mpoly = &mesh->mpoly[mesh->totpoly];
@@ -1244,7 +1268,7 @@ void ED_mesh_calc_normals(Mesh *mesh)
#ifdef USE_BMESH_MPOLY_NORMALS
BKE_mesh_calc_normals_mapping_ex(mesh->mvert, mesh->totvert,
mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly,
- NULL, NULL, 0, NULL, NULL, FALSE);
+ NULL, NULL, 0, NULL, NULL, false);
#else
BKE_mesh_calc_normals(mesh->mvert, mesh->totvert,
mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly,
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index e335c909e8e..89a320ca928 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -48,6 +48,7 @@ struct wmKeyConfig;
struct wmKeyMap;
struct wmOperator;
struct wmOperatorType;
+struct LinkNode;
/* ******************** editmesh_utils.c */
@@ -58,26 +59,25 @@ struct wmOperatorType;
*/
/*calls a bmesh op, reporting errors to the user, etc*/
-int EDBM_op_callf(struct BMEditMesh *em, struct wmOperator *op, const char *fmt, ...);
+bool EDBM_op_callf(struct BMEditMesh *em, struct wmOperator *op, const char *fmt, ...);
-int EDBM_op_call_and_selectf(struct BMEditMesh *em, struct wmOperator *op,
- const char *selectslot, const char *fmt, ...);
+bool EDBM_op_call_and_selectf(struct BMEditMesh *em, struct wmOperator *op,
+ const char *selectslot, const char *fmt, ...);
/* same as above, but doesn't report errors.*/
-int EDBM_op_call_silentf(struct BMEditMesh *em, const char *fmt, ...);
+bool EDBM_op_call_silentf(struct BMEditMesh *em, const char *fmt, ...);
/* these next two functions are the split version of EDBM_op_callf, so you can
* do stuff with a bmesh operator, after initializing it but before executing
* it.
*
* execute the operator with BM_Exec_Op */
-int EDBM_op_init(struct BMEditMesh *em, struct BMOperator *bmop,
- struct wmOperator *op, const char *fmt, ...);
+bool EDBM_op_init(struct BMEditMesh *em, struct BMOperator *bmop,
+ struct wmOperator *op, const char *fmt, ...);
/*cleans up after a bmesh operator*/
-int EDBM_op_finish(struct BMEditMesh *em, struct BMOperator *bmop,
- struct wmOperator *op, const int report);
+bool EDBM_op_finish(struct BMEditMesh *em, struct BMOperator *bmop,
+ struct wmOperator *op, const bool do_report);
-void EDBM_flag_disable_all(struct BMEditMesh *em, const char hflag);
void EDBM_stats_update(struct BMEditMesh *em);
/* ******************** editface.c */
@@ -128,9 +128,13 @@ void MESH_OT_select_shortest_path(struct wmOperatorType *ot);
void MESH_OT_select_similar(struct wmOperatorType *ot);
void MESH_OT_select_mode(struct wmOperatorType *ot);
void MESH_OT_select_random(struct wmOperatorType *ot);
+void MESH_OT_select_ungrouped(struct wmOperatorType *ot);
void MESH_OT_loop_multi_select(struct wmOperatorType *ot);
void MESH_OT_mark_seam(struct wmOperatorType *ot);
void MESH_OT_mark_sharp(struct wmOperatorType *ot);
+#ifdef WITH_FREESTYLE
+void MESH_OT_mark_freestyle_edge(struct wmOperatorType *ot);
+#endif
void MESH_OT_vertices_smooth(struct wmOperatorType *ot);
void MESH_OT_vertices_smooth_laplacian(struct wmOperatorType *ot);
void MESH_OT_noise(struct wmOperatorType *ot);
@@ -180,6 +184,9 @@ void MESH_OT_rip(struct wmOperatorType *ot);
void MESH_OT_shape_propagate_to_all(struct wmOperatorType *ot);
void MESH_OT_blend_from_shape(struct wmOperatorType *ot);
void MESH_OT_sort_elements(struct wmOperatorType *ot);
+#ifdef WITH_FREESTYLE
+void MESH_OT_mark_freestyle_face(struct wmOperatorType *ot);
+#endif
/* ******************* mesh_data.c */
@@ -205,12 +212,13 @@ void MESH_OT_edgering_select(struct wmOperatorType *ot);
void MESH_OT_loopcut(struct wmOperatorType *ot);
void MESH_OT_knife_tool(struct wmOperatorType *ot);
+void MESH_OT_knife_project(wmOperatorType *ot);
+
void MESH_OT_bevel(struct wmOperatorType *ot);
void MESH_OT_bridge_edge_loops(struct wmOperatorType *ot);
void MESH_OT_inset(struct wmOperatorType *ot);
void MESH_OT_wireframe(struct wmOperatorType *ot);
-void MESH_OT_vert_slide(struct wmOperatorType *ot);
void MESH_OT_convex_hull(struct wmOperatorType *ot);
@@ -223,4 +231,6 @@ void MESH_OT_navmesh_face_add(struct wmOperatorType *ot);
void MESH_OT_navmesh_reset(struct wmOperatorType *ot);
void MESH_OT_navmesh_clear(struct wmOperatorType *ot);
+void EDBM_mesh_knife(struct bContext *C, struct LinkNode *polys, bool use_tag);
+
#endif /* __MESH_INTERN_H__ */
diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c
index 83a1261e981..2111b6f3409 100644
--- a/source/blender/editors/mesh/mesh_navmesh.c
+++ b/source/blender/editors/mesh/mesh_navmesh.c
@@ -26,31 +26,22 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#include <math.h>
-
#include "MEM_guardedalloc.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_ID.h"
#include "BLI_listbase.h"
-#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
#include "BLI_linklist.h"
#include "BKE_library.h"
#include "BKE_depsgraph.h"
#include "BKE_context.h"
-#include "BKE_main.h"
#include "BKE_mesh.h"
-#include "BKE_modifier.h"
#include "BKE_scene.h"
#include "BKE_DerivedMesh.h"
-#include "BKE_cdderivedmesh.h"
#include "BKE_report.h"
#include "BKE_tessmesh.h"
@@ -58,15 +49,15 @@
#include "ED_mesh.h"
#include "ED_screen.h"
-#include "RNA_access.h"
-
#include "WM_api.h"
#include "WM_types.h"
#include "mesh_intern.h"
#include "recast-capi.h"
-static void createVertsTrisData(bContext *C, LinkNode *obs, int *nverts_r, float **verts_r, int *ntris_r, int **tris_r)
+
+static void createVertsTrisData(bContext *C, LinkNode *obs,
+ int *nverts_r, float **verts_r, int *ntris_r, int **tris_r, unsigned int *r_lay)
{
MVert *mvert;
int nfaces = 0, *tri, i, curnverts, basenverts, curnfaces;
@@ -101,6 +92,8 @@ static void createVertsTrisData(bContext *C, LinkNode *obs, int *nverts_r, float
if (mf->v4)
ntris += 1;
}
+
+ *r_lay |= ob->lay;
}
/* create data */
@@ -167,8 +160,9 @@ static void createVertsTrisData(bContext *C, LinkNode *obs, int *nverts_r, float
*tris_r = tris;
}
-static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts, int ntris, int *tris,
- struct recast_polyMesh **pmesh, struct recast_polyMeshDetail **dmesh)
+static bool buildNavMesh(const RecastData *recastParams, int nverts, float *verts, int ntris, int *tris,
+ struct recast_polyMesh **pmesh, struct recast_polyMeshDetail **dmesh,
+ ReportList *reports)
{
float bmin[3], bmax[3];
struct recast_heightfield *solid;
@@ -195,14 +189,20 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
/* Set the area where the navigation will be build. */
recast_calcGridSize(bmin, bmax, recastParams->cellsize, &width, &height);
+ /* zero dimensions cause zero alloc later on [#33758] */
+ if (width <= 0 || height <= 0) {
+ BKE_report(reports, RPT_ERROR, "Object has a width or height of zero");
+ return false;
+ }
+
/* ** Step 2: Rasterize input polygon soup ** */
/* Allocate voxel heightfield where we rasterize our input data to */
solid = recast_newHeightfield();
if (!recast_createHeightfield(solid, width, height, bmin, bmax, recastParams->cellsize, recastParams->cellheight)) {
recast_destroyHeightfield(solid);
-
- return 0;
+ BKE_report(reports, RPT_ERROR, "Failed to create height field");
+ return false;
}
/* Allocate array that can hold triangle flags */
@@ -225,7 +225,8 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
recast_destroyHeightfield(solid);
recast_destroyCompactHeightfield(chf);
- return 0;
+ BKE_report(reports, RPT_ERROR, "Failed to create compact height field");
+ return false;
}
recast_destroyHeightfield(solid);
@@ -234,21 +235,24 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
if (!recast_erodeWalkableArea(walkableRadius, chf)) {
recast_destroyCompactHeightfield(chf);
- return 0;
+ BKE_report(reports, RPT_ERROR, "Failed to erode walkable area");
+ return false;
}
/* Prepare for region partitioning, by calculating distance field along the walkable surface */
if (!recast_buildDistanceField(chf)) {
recast_destroyCompactHeightfield(chf);
- return 0;
+ BKE_report(reports, RPT_ERROR, "Failed to build distance field");
+ return false;
}
/* Partition the walkable surface into simple regions without holes */
if (!recast_buildRegions(chf, 0, minRegionArea, mergeRegionArea)) {
recast_destroyCompactHeightfield(chf);
- return 0;
+ BKE_report(reports, RPT_ERROR, "Failed to build regions");
+ return false;
}
/* ** Step 5: Trace and simplify region contours ** */
@@ -259,7 +263,8 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
recast_destroyCompactHeightfield(chf);
recast_destroyContourSet(cset);
- return 0;
+ BKE_report(reports, RPT_ERROR, "Failed to build contours");
+ return false;
}
/* ** Step 6: Build polygons mesh from contours ** */
@@ -269,7 +274,8 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
recast_destroyContourSet(cset);
recast_destroyPolyMesh(*pmesh);
- return 0;
+ BKE_report(reports, RPT_ERROR, "Failed to build poly mesh");
+ return false;
}
@@ -282,16 +288,18 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
recast_destroyPolyMesh(*pmesh);
recast_destroyPolyMeshDetail(*dmesh);
- return 0;
+ BKE_report(reports, RPT_ERROR, "Failed to build poly mesh detail");
+ return false;
}
recast_destroyCompactHeightfield(chf);
recast_destroyContourSet(cset);
- return 1;
+ return true;
}
-static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, struct recast_polyMeshDetail *dmesh, Base *base)
+static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, struct recast_polyMeshDetail *dmesh,
+ Base *base, unsigned int lay)
{
float co[3], rot[3];
BMEditMesh *em;
@@ -312,7 +320,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, 1);
+ obedit = ED_object_add_type(C, OB_MESH, co, rot, false, lay);
}
else {
obedit = base->object;
@@ -322,7 +330,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
copy_v3_v3(obedit->rot, rot);
}
- ED_object_enter_editmode(C, EM_DO_UNDO | EM_IGNORE_LAYER);
+ ED_object_editmode_enter(C, EM_DO_UNDO | EM_IGNORE_LAYER);
em = BMEdit_FromObject(obedit);
if (!createob) {
@@ -375,7 +383,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
BM_vert_create(em->bm, co, NULL, 0);
}
- EDBM_index_arrays_init(em, 1, 0, 0);
+ EDBM_index_arrays_ensure(em, BM_VERT);
/* create faces */
for (j = 0; j < trinum; j++) {
@@ -393,14 +401,12 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
EDBM_vert_at_index(em, face[0]),
EDBM_vert_at_index(em, face[2]),
EDBM_vert_at_index(em, face[1]), NULL,
- NULL, FALSE);
+ NULL, false);
/* set navigation polygon idx to the custom layer */
polygonIdx = (int *)CustomData_bmesh_get(&em->bm->pdata, newFace->head.data, CD_RECAST);
*polygonIdx = i + 1; /* add 1 to avoid zero idx */
}
-
- EDBM_index_arrays_free(em);
}
recast_destroyPolyMesh(pmesh);
@@ -410,7 +416,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- ED_object_exit_editmode(C, EM_FREEDATA);
+ ED_object_editmode_exit(C, EM_FREEDATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
if (createob) {
@@ -449,20 +455,23 @@ static int navmesh_create_exec(bContext *C, wmOperator *op)
if (obs) {
struct recast_polyMesh *pmesh = NULL;
struct recast_polyMeshDetail *dmesh = NULL;
+ bool ok;
+ unsigned int lay = 0;
int nverts = 0, ntris = 0;
int *tris = 0;
float *verts = NULL;
- createVertsTrisData(C, obs, &nverts, &verts, &ntris, &tris);
+ createVertsTrisData(C, obs, &nverts, &verts, &ntris, &tris, &lay);
BLI_linklist_free(obs, NULL);
- buildNavMesh(&scene->gm.recastData, nverts, verts, ntris, tris, &pmesh, &dmesh);
- createRepresentation(C, pmesh, dmesh, navmeshBase);
+ if ((ok = buildNavMesh(&scene->gm.recastData, nverts, verts, ntris, tris, &pmesh, &dmesh, op->reports))) {
+ createRepresentation(C, pmesh, dmesh, navmeshBase, lay);
+ }
MEM_freeN(verts);
MEM_freeN(tris);
- return OPERATOR_FINISHED;
+ return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
else {
BKE_report(op->reports, RPT_ERROR, "No mesh objects found");
@@ -474,7 +483,7 @@ static int navmesh_create_exec(bContext *C, wmOperator *op)
void MESH_OT_navmesh_make(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Create navigation mesh";
+ ot->name = "Create Navigation Mesh";
ot->description = "Create navigation mesh for selected objects";
ot->idname = "MESH_OT_navmesh_make";
@@ -491,7 +500,7 @@ static int navmesh_face_copy_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BMEdit_FromObject(obedit);
/* do work here */
- BMFace *efa_act = BM_active_face_get(em->bm, FALSE, FALSE);
+ BMFace *efa_act = BM_active_face_get(em->bm, false, false);
if (efa_act) {
if (CustomData_has_layer(&em->bm->pdata, CD_RECAST)) {
@@ -624,16 +633,16 @@ static int navmesh_obmode_data_poll(bContext *C)
Mesh *me = ob->data;
return CustomData_has_layer(&me->pdata, CD_RECAST);
}
- return FALSE;
+ return false;
}
static int navmesh_obmode_poll(bContext *C)
{
Object *ob = ED_object_active_context(C);
if (ob && (ob->mode == OB_MODE_OBJECT) && (ob->type == OB_MESH)) {
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
static int navmesh_reset_exec(bContext *C, wmOperator *UNUSED(op))
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index a413a60412c..42a139d7961 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -29,17 +29,11 @@
*/
-#include <stdlib.h>
-#include <math.h>
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
#include "BLI_math.h"
-#include "BLI_blenlib.h"
-#include "BKE_context.h"
#include "RNA_access.h"
@@ -49,7 +43,6 @@
#include "ED_object.h"
#include "ED_mesh.h"
#include "ED_screen.h"
-#include "ED_view3d.h"
#include "mesh_intern.h"
@@ -66,6 +59,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_select_linked);
WM_operatortype_append(MESH_OT_select_linked_pick);
WM_operatortype_append(MESH_OT_select_random);
+ WM_operatortype_append(MESH_OT_select_ungrouped);
WM_operatortype_append(MESH_OT_hide);
WM_operatortype_append(MESH_OT_reveal);
WM_operatortype_append(MESH_OT_select_face_by_sides);
@@ -118,6 +112,9 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_faces_shade_smooth);
WM_operatortype_append(MESH_OT_faces_shade_flat);
WM_operatortype_append(MESH_OT_sort_elements);
+#ifdef WITH_FREESTYLE
+ WM_operatortype_append(MESH_OT_mark_freestyle_face);
+#endif
WM_operatortype_append(MESH_OT_delete);
WM_operatortype_append(MESH_OT_edge_collapse);
@@ -133,6 +130,9 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_loop_multi_select);
WM_operatortype_append(MESH_OT_mark_seam);
WM_operatortype_append(MESH_OT_mark_sharp);
+#ifdef WITH_FREESTYLE
+ WM_operatortype_append(MESH_OT_mark_freestyle_edge);
+#endif
WM_operatortype_append(MESH_OT_vertices_smooth);
WM_operatortype_append(MESH_OT_vertices_smooth_laplacian);
WM_operatortype_append(MESH_OT_noise);
@@ -155,8 +155,8 @@ 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_slide);
WM_operatortype_append(MESH_OT_knife_tool);
+ WM_operatortype_append(MESH_OT_knife_project);
WM_operatortype_append(MESH_OT_bevel);
@@ -205,59 +205,59 @@ void ED_operatormacros_mesh(void)
OPTYPE_UNDO | OPTYPE_REGISTER);
WM_operatortype_macro_define(ot, "MESH_OT_loopcut");
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_edge_slide");
- RNA_struct_idprops_unset(otmacro->ptr, "release_confirm");
+ RNA_boolean_set(otmacro->ptr, "release_confirm", false);
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");
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", FALSE);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
ot = WM_operatortype_append_macro("MESH_OT_rip_move", "Rip", "Rip polygons and move the result",
OPTYPE_UNDO | OPTYPE_REGISTER);
otmacro = WM_operatortype_macro_define(ot, "MESH_OT_rip");
- RNA_boolean_set(otmacro->ptr, "use_fill", FALSE);
+ RNA_boolean_set(otmacro->ptr, "use_fill", false);
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", FALSE);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
/* annoying we can't pass 'use_fill' through the macro */
ot = WM_operatortype_append_macro("MESH_OT_rip_move_fill", "Rip Fill", "Rip-fill polygons and move the result",
OPTYPE_UNDO | OPTYPE_REGISTER);
otmacro = WM_operatortype_macro_define(ot, "MESH_OT_rip");
- RNA_boolean_set(otmacro->ptr, "use_fill", TRUE);
+ RNA_boolean_set(otmacro->ptr, "use_fill", true);
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", FALSE);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
ot = WM_operatortype_append_macro("MESH_OT_extrude_region_move", "Extrude Region and Move",
"Extrude region and move result", OPTYPE_UNDO | OPTYPE_REGISTER);
otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_region");
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", FALSE);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
ot = WM_operatortype_append_macro("MESH_OT_extrude_faces_move", "Extrude Individual Faces and Move",
"Extrude faces and move result", OPTYPE_UNDO | OPTYPE_REGISTER);
otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_faces_indiv");
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_shrink_fatten");
RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", FALSE);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
ot = WM_operatortype_append_macro("MESH_OT_extrude_edges_move", "Extrude Only Edges and Move",
"Extrude edges and move result", OPTYPE_UNDO | OPTYPE_REGISTER);
otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_edges_indiv");
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", FALSE);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
ot = WM_operatortype_append_macro("MESH_OT_extrude_vertices_move", "Extrude Only Vertices and Move",
"Extrude vertices and move result", OPTYPE_UNDO | OPTYPE_REGISTER);
otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_verts_indiv");
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
RNA_enum_set(otmacro->ptr, "proportional", 0);
- RNA_boolean_set(otmacro->ptr, "mirror", FALSE);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
}
/* note mesh keymap also for other space? */
@@ -270,29 +270,33 @@ 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_bevel", BKEY, 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_inset", IKEY, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "MESH_OT_bevel", BKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "vertex_only", false);
+ kmi = WM_keymap_add_item(keymap, "MESH_OT_bevel", BKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "vertex_only", true);
+
/* selecting */
/* standard mouse selection goes via space_view3d */
kmi = WM_keymap_add_item(keymap, "MESH_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
- RNA_boolean_set(kmi->ptr, "extend", FALSE);
- RNA_boolean_set(kmi->ptr, "deselect", FALSE);
- RNA_boolean_set(kmi->ptr, "toggle", FALSE);
+ RNA_boolean_set(kmi->ptr, "extend", false);
+ RNA_boolean_set(kmi->ptr, "deselect", false);
+ RNA_boolean_set(kmi->ptr, "toggle", false);
kmi = WM_keymap_add_item(keymap, "MESH_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, 0);
- RNA_boolean_set(kmi->ptr, "extend", FALSE);
- RNA_boolean_set(kmi->ptr, "deselect", FALSE);
- RNA_boolean_set(kmi->ptr, "toggle", TRUE);
+ RNA_boolean_set(kmi->ptr, "extend", false);
+ RNA_boolean_set(kmi->ptr, "deselect", false);
+ RNA_boolean_set(kmi->ptr, "toggle", true);
kmi = WM_keymap_add_item(keymap, "MESH_OT_edgering_select", SELECTMOUSE, KM_PRESS, KM_ALT | KM_CTRL, 0);
- RNA_boolean_set(kmi->ptr, "extend", FALSE);
- RNA_boolean_set(kmi->ptr, "deselect", FALSE);
- RNA_boolean_set(kmi->ptr, "toggle", FALSE);
+ RNA_boolean_set(kmi->ptr, "extend", false);
+ RNA_boolean_set(kmi->ptr, "deselect", false);
+ RNA_boolean_set(kmi->ptr, "toggle", false);
kmi = WM_keymap_add_item(keymap, "MESH_OT_edgering_select", SELECTMOUSE, KM_PRESS, KM_SHIFT | KM_ALT | KM_CTRL, 0);
- RNA_boolean_set(kmi->ptr, "extend", FALSE);
- RNA_boolean_set(kmi->ptr, "deselect", FALSE);
- RNA_boolean_set(kmi->ptr, "toggle", TRUE);
+ RNA_boolean_set(kmi->ptr, "extend", false);
+ RNA_boolean_set(kmi->ptr, "deselect", false);
+ RNA_boolean_set(kmi->ptr, "toggle", true);
WM_keymap_add_item(keymap, "MESH_OT_select_shortest_path", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
@@ -307,9 +311,9 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MESH_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0);
kmi = WM_keymap_add_item(keymap, "MESH_OT_select_linked_pick", LKEY, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "deselect", FALSE);
+ RNA_boolean_set(kmi->ptr, "deselect", false);
kmi = WM_keymap_add_item(keymap, "MESH_OT_select_linked_pick", LKEY, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "deselect", TRUE);
+ RNA_boolean_set(kmi->ptr, "deselect", true);
WM_keymap_add_item(keymap, "MESH_OT_faces_select_linked_flat", FKEY, KM_PRESS, (KM_CTRL | KM_SHIFT | KM_ALT), 0);
@@ -320,16 +324,16 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
/* hide */
kmi = WM_keymap_add_item(keymap, "MESH_OT_hide", HKEY, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "unselected", FALSE);
+ RNA_boolean_set(kmi->ptr, "unselected", false);
kmi = WM_keymap_add_item(keymap, "MESH_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "unselected", TRUE);
+ RNA_boolean_set(kmi->ptr, "unselected", true);
WM_keymap_add_item(keymap, "MESH_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
/* tools */
kmi = WM_keymap_add_item(keymap, "MESH_OT_normals_make_consistent", NKEY, KM_PRESS, KM_CTRL, 0);
- RNA_boolean_set(kmi->ptr, "inside", FALSE);
+ RNA_boolean_set(kmi->ptr, "inside", false);
kmi = WM_keymap_add_item(keymap, "MESH_OT_normals_make_consistent", NKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
- RNA_boolean_set(kmi->ptr, "inside", TRUE);
+ RNA_boolean_set(kmi->ptr, "inside", true);
WM_keymap_add_item(keymap, "VIEW3D_OT_edit_mesh_extrude_move_normal", EKEY, KM_PRESS, 0, 0); /* python operator */
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_extrude", EKEY, KM_PRESS, KM_ALT, 0);
@@ -342,9 +346,9 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MESH_OT_beautify_fill", FKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0);
kmi = WM_keymap_add_item(keymap, "MESH_OT_quads_convert_to_tris", TKEY, KM_PRESS, KM_CTRL, 0);
- RNA_boolean_set(kmi->ptr, "use_beauty", TRUE);
+ RNA_boolean_set(kmi->ptr, "use_beauty", true);
kmi = WM_keymap_add_item(keymap, "MESH_OT_quads_convert_to_tris", TKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "use_beauty", FALSE);
+ RNA_boolean_set(kmi->ptr, "use_beauty", false);
WM_keymap_add_item(keymap, "MESH_OT_tris_convert_to_quads", JKEY, KM_PRESS, KM_ALT, 0);
@@ -367,23 +371,23 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MESH_OT_vert_connect", JKEY, KM_PRESS, 0, 0);
/* Vertex Slide */
- WM_keymap_add_item(keymap, "MESH_OT_vert_slide", VKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "TRANSFORM_OT_vert_slide", VKEY, KM_PRESS, KM_SHIFT, 0);
/* use KM_CLICK because same key is used for tweaks */
kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0);
- RNA_boolean_set(kmi->ptr, "rotate_source", TRUE);
+ RNA_boolean_set(kmi->ptr, "rotate_source", true);
kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_SHIFT | KM_CTRL, 0);
- RNA_boolean_set(kmi->ptr, "rotate_source", FALSE);
+ RNA_boolean_set(kmi->ptr, "rotate_source", false);
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_delete", XKEY, KM_PRESS, 0, 0);
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_delete", DELKEY, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "MESH_OT_knife_tool", KKEY, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "use_occlude_geometry", TRUE);
- RNA_boolean_set(kmi->ptr, "only_selected", FALSE);
+ RNA_boolean_set(kmi->ptr, "use_occlude_geometry", true);
+ RNA_boolean_set(kmi->ptr, "only_selected", false);
kmi = WM_keymap_add_item(keymap, "MESH_OT_knife_tool", KKEY, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "use_occlude_geometry", FALSE);
- RNA_boolean_set(kmi->ptr, "only_selected", TRUE);
+ RNA_boolean_set(kmi->ptr, "use_occlude_geometry", false);
+ RNA_boolean_set(kmi->ptr, "only_selected", true);
WM_keymap_add_item(keymap, "OBJECT_OT_vertex_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
@@ -403,7 +407,7 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
}
ED_keymap_proportional_cycle(keyconf, keymap);
- ED_keymap_proportional_editmode(keyconf, keymap, TRUE);
+ ED_keymap_proportional_editmode(keyconf, keymap, true);
knifetool_modal_keymap(keyconf);
}
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index c0b6327d740..562bc4a8e02 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -27,35 +27,24 @@
/** \file blender/editors/mesh/meshtools.c
* \ingroup edmesh
+ *
+ * meshtools.c: no editmode (violated already :), mirror & join),
+ * tools operating on meshes
*/
-
-/*
- * meshtools.c: no editmode (violated already :), tools operating on meshes
- */
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <math.h>
-#include <float.h>
-
#include "MEM_guardedalloc.h"
#include "DNA_mesh_types.h"
-#include "DNA_view3d_types.h"
#include "DNA_key_types.h"
#include "DNA_material_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
-#include "BLI_ghash.h"
-#include "BLI_rand.h" /* for randome face sorting */
-#include "BLI_threads.h"
#include "BKE_context.h"
@@ -71,7 +60,6 @@
#include "BKE_tessmesh.h"
#include "BKE_multires.h"
-#include "BLO_sys_types.h" // for intptr_t support
#include "ED_mesh.h"
#include "ED_object.h"
@@ -80,10 +68,6 @@
#include "WM_api.h"
#include "WM_types.h"
-/* own include */
-#include "mesh_intern.h"
-#include "uvedit_intern.h"
-
/* * ********************** no editmode!!! *********** */
/*********************** JOIN ***************************/
@@ -165,7 +149,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- /* remove tessface to ensure we don't old references to invalid faces */
+ /* remove tessface to ensure we don't hold references to invalid faces */
BKE_mesh_tessface_clear(me);
/* new material indices and material array */
@@ -325,6 +309,10 @@ int join_mesh_exec(bContext *C, wmOperator *op)
me = base->object->data;
if (me->totvert) {
+
+ /* merge customdata flag */
+ ((Mesh *)ob->data)->cd_flag |= me->cd_flag;
+
/* standard data */
CustomData_merge(&me->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
CustomData_copy_data(&me->vdata, &vdata, 0, vertofs, me->totvert);
@@ -442,8 +430,8 @@ int join_mesh_exec(bContext *C, wmOperator *op)
multiresModifier_prepare_join(scene, base->object, ob);
- if ((mmd = get_multires_modifier(scene, base->object, TRUE))) {
- ED_object_iter_other(bmain, base->object, TRUE,
+ if ((mmd = get_multires_modifier(scene, base->object, true))) {
+ ED_object_iter_other(bmain, base->object, true,
ED_object_multires_update_totlevels_cb,
&mmd->totlvl);
}
@@ -517,7 +505,10 @@ int join_mesh_exec(bContext *C, wmOperator *op)
me->pdata = pdata;
/* tessface data removed above, no need to update */
- mesh_update_customdata_pointers(me, FALSE);
+ BKE_mesh_update_customdata_pointers(me, false);
+
+ /* update normals in case objects with non-uniform scale are joined */
+ ED_mesh_calc_normals(me);
/* old material array */
for (a = 1; a <= ob->totcol; a++) {
@@ -572,11 +563,11 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
- DAG_scene_sort(bmain, scene); // removed objects, need to rebuild dag before editmode call
+ DAG_relations_tag_update(bmain); // removed objects, need to rebuild dag
#if 0
- ED_object_enter_editmode(C, EM_WAITCURSOR);
- ED_object_exit_editmode(C, EM_FREEDATA | EM_WAITCURSOR | EM_DO_UNDO);
+ ED_object_editmode_enter(C, EM_WAITCURSOR);
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR | EM_DO_UNDO);
#else
/* toggle editmode using lower level functions so this can be called from python */
EDBM_mesh_make(scene->toolsettings, scene, ob);
@@ -733,9 +724,9 @@ static void mesh_octree_add_nodes(MocNode **basetable, const float co[3], const
float fx, fy, fz;
int vx, vy, vz;
- if ((finite(co[0]) == FALSE) ||
- (finite(co[1]) == FALSE) ||
- (finite(co[2]) == FALSE))
+ if ((finite(co[0]) == false) ||
+ (finite(co[1]) == false) ||
+ (finite(co[2]) == false))
{
return;
}
@@ -798,7 +789,9 @@ static intptr_t mesh_octree_find_index(MocNode **bt, MVert *mvert, const float c
return (*bt)->index[a];
}
}
- else return -1;
+ else {
+ return -1;
+ }
}
if ( (*bt)->next)
return mesh_octree_find_index(&(*bt)->next, mvert, co);
@@ -917,7 +910,7 @@ int mesh_mirrtopo_table(Object *ob, char mode)
}
}
else if (mode == 's') { /* start table */
- ED_mesh_mirrtopo_init(ob->data, ob->mode, &mesh_topo_store, FALSE);
+ ED_mesh_mirrtopo_init(ob->data, ob->mode, &mesh_topo_store, false);
}
else if (mode == 'e') { /* end table */
ED_mesh_mirrtopo_free(&mesh_topo_store);
@@ -964,9 +957,9 @@ static BMVert *editbmesh_get_x_mirror_vert_spatial(Object *ob, BMEditMesh *em, c
intptr_t poinval;
/* ignore nan verts */
- if ((finite(co[0]) == FALSE) ||
- (finite(co[1]) == FALSE) ||
- (finite(co[2]) == FALSE))
+ if ((finite(co[0]) == false) ||
+ (finite(co[1]) == false) ||
+ (finite(co[2]) == false))
{
return NULL;
}
@@ -1080,7 +1073,7 @@ static float *editmesh_get_mirror_uv(BMEditMesh *em, int axis, float *uv, float
static unsigned int mirror_facehash(const void *ptr)
{
const MFace *mf = ptr;
- int v0, v1;
+ unsigned int v0, v1;
if (mf->v4) {
v0 = MIN4(mf->v1, mf->v2, mf->v3, mf->v4);
@@ -1181,14 +1174,17 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em)
* Face selection in object mode,
* currently only weight-paint and vertex-paint use this.
*
- * \return boolean TRUE == Found
+ * \return boolean true == Found
*/
-int ED_mesh_pick_face(bContext *C, Mesh *me, const int mval[2], unsigned int *index, int size)
+bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size)
{
ViewContext vc;
+ Mesh *me = ob->data;
+
+ BLI_assert(me && GS(me->id.name) == ID_ME);
if (!me || me->totpoly == 0)
- return 0;
+ return false;
view3d_set_viewcontext(C, &vc);
@@ -1205,21 +1201,24 @@ int ED_mesh_pick_face(bContext *C, Mesh *me, const int mval[2], unsigned int *in
}
if ((*index) <= 0 || (*index) > (unsigned int)me->totpoly)
- return 0;
+ return false;
(*index)--;
- return 1;
+ return true;
}
/**
* Use when the back buffer stores face index values. but we want a vert.
* This gets the face then finds the closest vertex to mval.
*/
-int ED_mesh_pick_face_vert(bContext *C, Mesh *me, Object *ob, const int mval[2], unsigned int *index, int size)
+bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size)
{
unsigned int poly_index;
+ Mesh *me = ob->data;
- if (ED_mesh_pick_face(C, me, mval, &poly_index, size)) {
+ BLI_assert(me && GS(me->id.name) == ID_ME);
+
+ if (ED_mesh_pick_face(C, ob, mval, &poly_index, size)) {
Scene *scene = CTX_data_scene(C);
struct ARegion *ar = CTX_wm_region(C);
@@ -1228,6 +1227,8 @@ int ED_mesh_pick_face_vert(bContext *C, Mesh *me, Object *ob, const int mval[2],
int v_idx_best = -1;
if (dm->getVertCo) {
+ RegionView3D *rv3d = ar->regiondata;
+
/* find the vert closest to 'mval' */
const float mval_f[2] = {(float)mval[0],
(float)mval[1]};
@@ -1235,14 +1236,15 @@ int ED_mesh_pick_face_vert(bContext *C, Mesh *me, Object *ob, const int mval[2],
int fidx;
float len_best = FLT_MAX;
+ ED_view3d_init_mats_rv3d(ob, rv3d);
+
fidx = mp->totloop - 1;
do {
float co[3], sco[2], len;
const int v_idx = me->mloop[mp->loopstart + fidx].v;
dm->getVertCo(dm, v_idx, co);
- mul_m4_v3(ob->obmat, co);
- if (ED_view3d_project_float_global(ar, co, sco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- len = len_squared_v2v2(mval_f, sco);
+ if (ED_view3d_project_float_object(ar, co, sco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ len = len_manhattan_v2v2(mval_f, sco);
if (len < len_best) {
len_best = len;
v_idx_best = v_idx;
@@ -1255,44 +1257,110 @@ int ED_mesh_pick_face_vert(bContext *C, Mesh *me, Object *ob, const int mval[2],
if (v_idx_best != -1) {
*index = v_idx_best;
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
/**
* Vertex selection in object mode,
* currently only weight paint uses this.
*
- * \return boolean TRUE == Found
+ * \return boolean true == Found
*/
-int ED_mesh_pick_vert(bContext *C, Mesh *me, const int mval[2], unsigned int *index, int size)
+typedef struct VertPickData {
+ const MVert *mvert;
+ const float *mval_f; /* [2] */
+ ARegion *ar;
+
+ /* runtime */
+ float len_best;
+ int v_idx_best;
+} VertPickData;
+
+static void ed_mesh_pick_vert__mapFunc(void *userData, int index, const float co[3],
+ const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+{
+ VertPickData *data = userData;
+ if ((data->mvert[index].flag & ME_HIDE) == 0) {
+ float sco[2];
+
+ if (ED_view3d_project_float_object(data->ar, co, sco, V3D_PROJ_TEST_CLIP_DEFAULT) == V3D_PROJ_RET_OK) {
+ const float len = len_manhattan_v2v2(data->mval_f, sco);
+ if (len < data->len_best) {
+ data->len_best = len;
+ data->v_idx_best = index;
+ }
+ }
+ }
+}
+bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size, bool use_zbuf)
{
ViewContext vc;
+ Mesh *me = ob->data;
+
+ BLI_assert(me && GS(me->id.name) == ID_ME);
if (!me || me->totvert == 0)
- return 0;
+ return false;
view3d_set_viewcontext(C, &vc);
- if (size > 0) {
- /* sample rect to increase chances of selecting, so that when clicking
- * on an face in the backbuf, we can still select a vert */
+ if (use_zbuf) {
+ if (size > 0) {
+ /* sample rect to increase chances of selecting, so that when clicking
+ * 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);
+ float dummy_dist;
+ *index = view3d_sample_backbuf_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist, 0, NULL, NULL);
+ }
+ else {
+ /* sample only on the exact position */
+ *index = view3d_sample_backbuf(&vc, mval[0], mval[1]);
+ }
+
+ if ((*index) <= 0 || (*index) > (unsigned int)me->totvert)
+ return false;
+
+ (*index)--;
}
else {
- /* sample only on the exact position */
- *index = view3d_sample_backbuf(&vc, mval[0], mval[1]);
- }
+ /* derived mesh to find deformed locations */
+ DerivedMesh *dm = mesh_get_derived_final(vc.scene, ob, CD_MASK_BAREMESH);
+ ARegion *ar = vc.ar;
+ RegionView3D *rv3d = ar->regiondata;
- if ((*index) <= 0 || (*index) > (unsigned int)me->totvert)
- return 0;
+ /* find the vert closest to 'mval' */
+ const float mval_f[2] = {(float)mval[0],
+ (float)mval[1]};
- (*index)--;
+ VertPickData data = {0};
+
+ ED_view3d_init_mats_rv3d(ob, rv3d);
+
+ if (dm == NULL) {
+ return false;
+ }
+
+ /* setup data */
+ data.mvert = me->mvert;
+ data.ar = ar;
+ data.mval_f = mval_f;
+ data.len_best = FLT_MAX;
+ data.v_idx_best = -1;
+
+ dm->foreachMappedVert(dm, ed_mesh_pick_vert__mapFunc, &data);
+
+ dm->release(dm);
+
+ if (data.v_idx_best == -1) {
+ return false;
+ }
+
+ *index = data.v_idx_best;
+ }
- return 1;
+ return true;
}
diff --git a/source/blender/editors/metaball/SConscript b/source/blender/editors/metaball/SConscript
index b1a1ce935db..7083eff863e 100644
--- a/source/blender/editors/metaball/SConscript
+++ b/source/blender/editors/metaball/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index 8633a7a9b38..3fe8b93ada3 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -254,7 +254,7 @@ static int duplicate_metaelems_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-static int duplicate_metaelems_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int duplicate_metaelems_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
int retv = duplicate_metaelems_exec(C, op);
@@ -411,7 +411,7 @@ void MBALL_OT_reveal_metaelems(wmOperatorType *ot)
/* Select MetaElement with mouse click (user can select radius circle or
* stiffness circle) */
-int mouse_mball(bContext *C, const int mval[2], int extend, int deselect, int toggle)
+bool mouse_mball(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
{
static MetaElem *startelem = NULL;
Object *obedit = CTX_data_edit_object(C);
@@ -487,11 +487,11 @@ int mouse_mball(bContext *C, const int mval[2], int extend, int deselect, int to
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
@@ -586,3 +586,27 @@ void undo_push_mball(bContext *C, const char *name)
undo_editmode_push(C, name, get_data, free_undoMball, undoMball_to_editMball, editMball_to_undoMball, NULL);
}
+/* matrix is 4x4 */
+void ED_mball_transform(MetaBall *mb, float *mat)
+{
+ MetaElem *me;
+ float quat[4];
+ const float scale = mat4_to_scale((float (*)[4])mat);
+ const float scale_sqrt = sqrtf(scale);
+
+ mat4_to_quat(quat, (float (*)[4])mat);
+
+ for (me = mb->elems.first; me; me = me->next) {
+ mul_m4_v3((float (*)[4])mat, &me->x);
+ mul_qt_qtqt(me->quat, quat, me->quat);
+ me->rad *= scale;
+ /* hrmf, probably elems shouldn't be
+ * treating scale differently - campbell */
+ if (!MB_TYPE_SIZE_SQUARED(me->type)) {
+ mul_v3_fl(&me->expx, scale);
+ }
+ else {
+ mul_v3_fl(&me->expx, scale_sqrt);
+ }
+ }
+}
diff --git a/source/blender/editors/metaball/mball_ops.c b/source/blender/editors/metaball/mball_ops.c
index e98654f589a..8c705aac0d2 100644
--- a/source/blender/editors/metaball/mball_ops.c
+++ b/source/blender/editors/metaball/mball_ops.c
@@ -28,18 +28,17 @@
* \ingroup edmeta
*/
+#include "BLI_utildefines.h"
+
+#include "RNA_access.h"
#include "WM_api.h"
#include "WM_types.h"
-#include "RNA_access.h"
-
#include "ED_mball.h"
#include "ED_screen.h"
#include "ED_object.h"
-#include "BLI_utildefines.h"
-
#include "mball_intern.h"
void ED_operatortypes_metaball(void)
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt
index 05c042a4182..a92b25c6c85 100644
--- a/source/blender/editors/object/CMakeLists.txt
+++ b/source/blender/editors/object/CMakeLists.txt
@@ -20,6 +20,7 @@
set(INC
../include
+ ../../blenfont
../../blenkernel
../../blenlib
../../blenloader
@@ -66,4 +67,8 @@ if(WITH_GAMEENGINE)
add_definitions(-DWITH_GAMEENGINE)
endif()
+if(WITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
+endif()
+
blender_add_lib(bf_editor_object "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/object/SConscript b/source/blender/editors/object/SConscript
index b53ea549853..203d7dff768 100644
--- a/source/blender/editors/object/SConscript
+++ b/source/blender/editors/object/SConscript
@@ -1,9 +1,35 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
-incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs = '../include ../../blenlib ../../blenfont ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc ../../blenloader'
incs += ' ../../makesrna ../../python ../../ikplugin ../../bmesh'
incs += ' ../../render/extern/include ../../gpu' # for object_bake.c
@@ -24,4 +50,7 @@ if env['WITH_BF_PYTHON']:
if env['WITH_BF_GAMEENGINE']:
defs.append('WITH_GAMEENGINE')
+if env['WITH_BF_INTERNATIONAL']:
+ defs.append('WITH_INTERNATIONAL')
+
env.BlenderLib ( 'bf_editors_object', sources, Split(incs), defs, libtype=['core'], priority=[35] )
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index b3c0368adfe..63582feadb7 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -49,11 +49,13 @@
#include "DNA_vfont_types.h"
#include "DNA_actuator_types.h"
+#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_string.h"
-#include "BLI_utildefines.h"
+
+#include "BLF_translation.h"
#include "BKE_anim.h"
#include "BKE_animsys.h"
@@ -67,6 +69,7 @@
#include "BKE_displist.h"
#include "BKE_effect.h"
#include "BKE_group.h"
+#include "BKE_image.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
@@ -146,7 +149,7 @@ void ED_object_location_from_view(bContext *C, float loc[3])
{
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
- float *cursor;
+ const float *cursor;
cursor = give_cursor(scene, v3d);
@@ -369,7 +372,7 @@ Object *ED_object_add_type(bContext *C, int type, const float loc[3], const floa
/* for as long scene has editmode... */
if (CTX_data_edit_object(C))
- ED_object_exit_editmode(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); /* freedata, and undo */
+ 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(scene, type);
@@ -381,13 +384,13 @@ Object *ED_object_add_type(bContext *C, int type, const float loc[3], const floa
ED_object_base_init_transform(C, BASACT, loc, rot);
DAG_id_type_tag(bmain, ID_OB);
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
if (ob->data) {
ED_render_id_flush_update(bmain, ob->data);
}
if (enter_editmode)
- ED_object_enter_editmode(C, EM_IGNORE_LAYER);
+ ED_object_editmode_enter(C, EM_IGNORE_LAYER);
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
@@ -449,27 +452,27 @@ static int effector_add_exec(bContext *C, wmOperator *op)
if (!ob)
return OPERATOR_CANCELLED;
- rename_id(&ob->id, "CurveGuide");
+ rename_id(&ob->id, DATA_("CurveGuide"));
((Curve *)ob->data)->flag |= CU_PATH | CU_3D;
- ED_object_enter_editmode(C, 0);
+ ED_object_editmode_enter(C, 0);
ED_object_new_primitive_matrix(C, ob, loc, rot, mat, FALSE);
BLI_addtail(object_editcurve_get(ob), add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, 1));
if (!enter_editmode)
- ED_object_exit_editmode(C, EM_FREEDATA);
+ ED_object_editmode_exit(C, EM_FREEDATA);
}
else {
ob = ED_object_add_type(C, OB_EMPTY, loc, rot, FALSE, layer);
if (!ob)
return OPERATOR_CANCELLED;
- rename_id(&ob->id, "Field");
+ rename_id(&ob->id, DATA_("Field"));
if (ELEM(type, PFIELD_WIND, PFIELD_VORTEX))
ob->empty_drawtype = OB_SINGLE_ARROW;
}
ob->pd = object_add_collision_fields(type);
- DAG_scene_sort(CTX_data_main(C), CTX_data_scene(C));
+ DAG_relations_tag_update(CTX_data_main(C));
return OPERATOR_FINISHED;
}
@@ -575,7 +578,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op)
/* userdef */
if (newob && !enter_editmode) {
- ED_object_exit_editmode(C, EM_FREEDATA);
+ ED_object_editmode_exit(C, EM_FREEDATA);
}
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
@@ -658,10 +661,12 @@ static int object_armature_add_exec(bContext *C, wmOperator *op)
if ((obedit == NULL) || (obedit->type != OB_ARMATURE)) {
obedit = ED_object_add_type(C, OB_ARMATURE, loc, rot, TRUE, layer);
- ED_object_enter_editmode(C, 0);
+ ED_object_editmode_enter(C, 0);
newob = 1;
}
- else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ else {
+ DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+ }
if (obedit == NULL) {
BKE_report(op->reports, RPT_ERROR, "Cannot create editmode armature");
@@ -673,7 +678,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op)
/* userdef */
if (newob && !enter_editmode)
- ED_object_exit_editmode(C, EM_FREEDATA);
+ ED_object_editmode_exit(C, EM_FREEDATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
@@ -735,18 +740,95 @@ void OBJECT_OT_empty_add(wmOperatorType *ot)
ED_object_add_generic_props(ot, FALSE);
}
+static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Base *base = NULL;
+ 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");
+ return OPERATOR_CANCELLED;
+ }
+
+ base = ED_view3d_give_base_under_cursor(C, event->mval);
+
+ /* if empty under cursor, then set object */
+ if (base && base->object->type == OB_EMPTY) {
+ ob = base->object;
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, CTX_data_scene(C));
+ }
+ else {
+ /* add new empty */
+ unsigned int layer;
+ float rot[3];
+
+ if (!ED_object_add_generic_get_opts(C, op, NULL, rot, NULL, &layer, NULL))
+ return OPERATOR_CANCELLED;
+
+ ob = ED_object_add_type(C, OB_EMPTY, NULL, rot, FALSE, layer);
+
+ /* add under the mouse */
+ ED_object_location_from_view(C, ob->loc);
+ ED_view3d_cursor3d_position(C, ob->loc, event->mval);
+ }
+
+ ob->empty_drawtype = OB_EMPTY_IMAGE;
+ ob->data = ima;
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_drop_named_image(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Add Empty Image/Drop Image To Empty";
+ ot->description = "Add an empty image type to scene with data";
+ ot->idname = "OBJECT_OT_drop_named_image";
+
+ /* api callbacks */
+ ot->invoke = empty_drop_named_image_invoke;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_string(ot->srna, "filepath", "", FILE_MAX, "Filepath", "Path to image file");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_string(ot->srna, "name", "", 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);
+}
+
/********************* Add Lamp Operator ********************/
static const char *get_lamp_defname(int type)
{
switch (type) {
- case LA_LOCAL: return "Point";
- case LA_SUN: return "Sun";
- case LA_SPOT: return "Spot";
- case LA_HEMI: return "Hemi";
- case LA_AREA: return "Area";
+ case LA_LOCAL: return DATA_("Point");
+ case LA_SUN: return DATA_("Sun");
+ case LA_SPOT: return DATA_("Spot");
+ case LA_HEMI: return DATA_("Hemi");
+ case LA_AREA: return DATA_("Area");
default:
- return "Lamp";
+ return DATA_("Lamp");
}
}
@@ -770,7 +852,7 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op)
rename_id(&la->id, get_lamp_defname(type));
if (BKE_scene_use_new_shading_nodes(scene)) {
- ED_node_shader_default(scene, &la->id);
+ ED_node_shader_default(C, &la->id);
la->use_nodes = TRUE;
}
@@ -794,6 +876,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);
ED_object_add_generic_props(ot, FALSE);
}
@@ -802,10 +885,25 @@ void OBJECT_OT_lamp_add(wmOperatorType *ot)
static int group_instance_add_exec(bContext *C, wmOperator *op)
{
- Group *group = BLI_findlink(&CTX_data_main(C)->group, RNA_enum_get(op->ptr, "group"));
-
+ Group *group;
unsigned int layer;
float loc[3], rot[3];
+
+ if (RNA_struct_property_is_set(op->ptr, "name")) {
+ char name[MAX_ID_NAME - 2];
+
+ RNA_string_get(op->ptr, "name", name);
+ group = (Group *)BKE_libblock_find_name(ID_GR, name);
+
+ if (0 == RNA_struct_property_is_set(op->ptr, "location")) {
+ wmEvent *event = CTX_wm_window(C)->eventstate;
+ ED_object_location_from_view(C, loc);
+ ED_view3d_cursor3d_position(C, loc, event->mval);
+ RNA_float_set_array(op->ptr, "location", loc);
+ }
+ }
+ else
+ group = BLI_findlink(&CTX_data_main(C)->group, RNA_enum_get(op->ptr, "group"));
if (!ED_object_add_generic_get_opts(C, op, loc, rot, NULL, &layer, NULL))
return OPERATOR_CANCELLED;
@@ -820,9 +918,9 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
id_lib_extern(&group->id);
/* works without this except if you try render right after, see: 22027 */
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, CTX_data_scene(C));
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
return OPERATOR_FINISHED;
}
@@ -847,6 +945,7 @@ void OBJECT_OT_group_instance_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
+ RNA_def_string(ot->srna, "name", "Group", MAX_ID_NAME - 2, "Name", "Group name to add");
ot->prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "");
RNA_def_enum_funcs(ot->prop, RNA_group_itemf);
ED_object_add_generic_props(ot, FALSE);
@@ -881,7 +980,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op)
BKE_nlatrack_add_strip(nlt, strip);
/* auto-name the strip, and give the track an interesting name */
- strcpy(nlt->name, "SoundTrack");
+ strcpy(nlt->name, DATA_("SoundTrack"));
BKE_nlastrip_validate_name(adt, strip);
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
@@ -925,7 +1024,7 @@ static void object_delete_check_glsl_update(Object *ob)
void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Base *base)
{
DAG_id_type_tag(bmain, ID_OB);
- BLI_remlink(&scene->base, base);
+ BKE_scene_base_unlink(scene, base);
object_delete_check_glsl_update(base->object);
BKE_libblock_free_us(&bmain->object, base->object);
if (scene->basact == base) scene->basact = NULL;
@@ -936,6 +1035,8 @@ static int object_delete_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win;
const short use_global = RNA_boolean_get(op->ptr, "use_global");
if (CTX_data_edit_object(C))
@@ -967,11 +1068,20 @@ static int object_delete_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- DAG_scene_sort(bmain, scene);
- DAG_ids_flush_update(bmain, 0);
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
+ /* delete has to handle all open scenes */
+ flag_listbase_ids(&bmain->scene, LIB_DOIT, 1);
+ for (win = wm->windows.first; win; win = win->next) {
+ scene = win->screen->scene;
+
+ if (scene->id.flag & LIB_DOIT) {
+ scene->id.flag &= ~LIB_DOIT;
+
+ DAG_relations_tag_update(bmain);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
+ }
+ }
return OPERATOR_FINISHED;
}
@@ -1232,8 +1342,7 @@ static int object_duplicates_make_real_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- DAG_scene_sort(bmain, scene);
- DAG_ids_flush_update(bmain, 0);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SCENE, scene);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
@@ -1297,7 +1406,7 @@ static Base *duplibase_for_convert(Scene *scene, Base *base, Object *ob)
}
obn = BKE_object_copy(ob);
- obn->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
basen = MEM_mallocN(sizeof(Base), "duplibase");
*basen = *base;
@@ -1378,7 +1487,7 @@ static int convert_exec(bContext *C, wmOperator *op)
newob = ob;
}
- BKE_mesh_from_curve(scene, newob);
+ BKE_mesh_to_curve(scene, newob);
if (newob->type == OB_CURVE)
BKE_object_free_modifiers(newob); /* after derivedmesh calls! */
@@ -1399,7 +1508,7 @@ static int convert_exec(bContext *C, wmOperator *op)
}
else {
newob = ob;
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
/* make new mesh data from the original copy */
@@ -1464,7 +1573,7 @@ static int convert_exec(bContext *C, wmOperator *op)
for (ob1 = bmain->object.first; ob1; ob1 = ob1->id.next) {
if (ob1->data == ob->data) {
ob1->type = OB_CURVE;
- ob1->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&ob1->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
}
}
@@ -1530,7 +1639,7 @@ static int convert_exec(bContext *C, wmOperator *op)
mb = newob->data;
mb->id.us--;
- newob->data = BKE_mesh_add("Mesh");
+ newob->data = BKE_mesh_add(bmain, "Mesh");
newob->type = OB_MESH;
me = newob->data;
@@ -1595,10 +1704,10 @@ static int convert_exec(bContext *C, wmOperator *op)
}
/* delete object should renew depsgraph */
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
}
-// XXX ED_object_enter_editmode(C, 0);
+// XXX ED_object_editmode_enter(C, 0);
// XXX exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR); /* freedata, but no undo */
if (basact) {
@@ -1611,7 +1720,7 @@ static int convert_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT->object);
}
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -1663,14 +1772,18 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
}
else {
obn = BKE_object_copy(ob);
- obn->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
basen = MEM_mallocN(sizeof(Base), "duplibase");
*basen = *base;
BLI_addhead(&scene->base, basen); /* addhead: prevent eternal loop */
basen->object = obn;
- if (basen->flag & OB_FROMGROUP) {
+ /* 1) duplis should end up in same group as the original
+ * 2) Rigid Body sim participants MUST always be part of a group...
+ */
+ // XXX: is 2) really a good measure here?
+ if ((basen->flag & OB_FROMGROUP) || ob->rigidbody_object || ob->rigidbody_constraint) {
Group *group;
for (group = bmain->group.first; group; group = group->id.next) {
if (object_in_group(ob, group))
@@ -1784,7 +1897,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
}
break;
case OB_ARMATURE:
- obn->recalc |= OB_RECALC_DATA;
+ DAG_id_tag_update(&obn->id, OB_RECALC_DATA);
if (obn->pose)
obn->pose->flag |= POSE_RECALC;
if (dupflag & USER_DUP_ARM) {
@@ -1874,7 +1987,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
/* single object duplicate, if dupflag==0, fully linked, else it uses the flags given */
/* leaves selection of base/object unaltered.
* note: don't call this within a loop since clear_* funcs loop over the entire database.
- * note: caller must do DAG_scene_sort(bmain, scene);
+ * note: caller must do DAG_relations_tag_update(bmain);
* this is not done automatic since we may duplicate many objects in a batch */
Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag)
{
@@ -1895,7 +2008,7 @@ Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag
BKE_object_relink(ob);
set_sca_new_poins_ob(ob);
- /* DAG_scene_sort(bmain, scene); */ /* caller must do */
+ /* DAG_relations_tag_update(bmain); */ /* caller must do */
if (ob->data) {
ED_render_id_flush_update(bmain, ob->data);
@@ -1939,8 +2052,7 @@ static int duplicate_exec(bContext *C, wmOperator *op)
copy_object_set_idnew(C, dupflag);
- DAG_scene_sort(bmain, scene);
- DAG_ids_flush_update(bmain, 0);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -1973,6 +2085,8 @@ void OBJECT_OT_duplicate(wmOperatorType *ot)
static int add_named_exec(bContext *C, wmOperator *op)
{
+ wmWindow *win = CTX_wm_window(C);
+ wmEvent *event = win ? win->eventstate : NULL;
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Base *basen, *base;
@@ -2003,14 +2117,22 @@ static int add_named_exec(bContext *C, wmOperator *op)
}
basen->lay = basen->object->lay = scene->lay;
-
- ED_object_location_from_view(C, basen->object->loc);
+ basen->object->restrictflag &= ~OB_RESTRICT_VIEW;
+
+ if (event) {
+ 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, basen->object->loc);
+ ED_view3d_cursor3d_position(C, basen->object->loc, mval);
+ }
+
+ ED_base_object_select(basen, BA_SELECT);
ED_base_object_activate(C, basen);
copy_object_set_idnew(C, dupflag);
- DAG_scene_sort(bmain, scene);
- DAG_ids_flush_update(bmain, 0);
+ DAG_relations_tag_update(bmain);
MEM_freeN(base);
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index e144c38a350..00af771e45d 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -64,6 +64,7 @@
#include "RE_pipeline.h"
#include "RE_shader_ext.h"
+#include "RE_multires_bake.h"
#include "PIL_time.h"
@@ -88,6 +89,7 @@ typedef struct MultiresBakerJobData {
struct MultiresBakerJobData *next, *prev;
DerivedMesh *lores_dm, *hires_dm;
int simple, lvl, tot_lvl;
+ ListBase images;
} MultiresBakerJobData;
/* data passing to multires-baker job */
@@ -95,829 +97,13 @@ typedef struct {
ListBase data;
int bake_clear, bake_filter;
short mode, use_lores_mesh;
+ int number_of_rays;
+ float bias;
+ int raytrace_structure;
+ int octree_resolution;
+ int threads;
} MultiresBakeJob;
-/* data passing to multires baker */
-typedef struct {
- DerivedMesh *lores_dm, *hires_dm;
- int simple, lvl, tot_lvl, bake_filter;
- short mode, use_lores_mesh;
-
- int tot_obj, tot_image;
- ListBase image;
-
- int baked_objects, baked_faces;
-
- short *stop;
- short *do_update;
- float *progress;
-} MultiresBakeRender;
-
-typedef void (*MPassKnownData)(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data,
- ImBuf *ibuf, const int face_index, const int lvl, const float st[2],
- float tangmat[3][3], const int x, const int y);
-
-typedef void * (*MInitBakeData)(MultiresBakeRender *bkr, Image *ima);
-typedef void (*MApplyBakeData)(void *bake_data);
-typedef void (*MFreeBakeData)(void *bake_data);
-
-typedef struct {
- MVert *mvert;
- MFace *mface;
- MTFace *mtface;
- float *pvtangent;
- float *precomputed_normals;
- int w, h;
- int face_index;
- int i0, i1, i2;
- DerivedMesh *lores_dm, *hires_dm;
- int lvl;
- void *bake_data;
- ImBuf *ibuf;
- MPassKnownData pass_data;
-} MResolvePixelData;
-
-typedef void (*MFlushPixel)(const MResolvePixelData *data, const int x, const int y);
-
-typedef struct {
- int w, h;
- char *texels;
- const MResolvePixelData *data;
- MFlushPixel flush_pixel;
-} MBakeRast;
-
-typedef struct {
- float *heights;
- float height_min, height_max;
- 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;
-
-static void multiresbake_get_normal(const MResolvePixelData *data, float norm[], const int face_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);
-
- if (!smoothnormal) { /* flat */
- if (data->precomputed_normals) {
- copy_v3_v3(norm, &data->precomputed_normals[3 * face_num]);
- }
- else {
- float nor[3];
- 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) {
- 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);
- }
- }
- else {
- short *no = data->mvert[indices[vert_index]].no;
-
- normal_short_to_float_v3(norm, no);
- normalize_v3(norm);
- }
-}
-
-static void init_bake_rast(MBakeRast *bake_rast, const ImBuf *ibuf, const MResolvePixelData *data, MFlushPixel flush_pixel)
-{
- memset(bake_rast, 0, sizeof(MBakeRast));
-
- bake_rast->texels = ibuf->userdata;
- bake_rast->w = ibuf->x;
- bake_rast->h = ibuf->y;
- bake_rast->data = data;
- bake_rast->flush_pixel = flush_pixel;
-}
-
-static void flush_pixel(const MResolvePixelData *data, const int x, const int y)
-{
- float st[2] = {(x + 0.5f) / data->w, (y + 0.5f) / data->h};
- float *st0, *st1, *st2;
- float *tang0, *tang1, *tang2;
- float no0[3], no1[3], no2[3];
- float fUV[2], from_tang[3][3], to_tang[3][3];
- float u, v, w, sign;
- int r;
-
- const int i0 = data->i0;
- const int i1 = data->i1;
- const int i2 = data->i2;
-
- st0 = data->mtface[data->face_index].uv[i0];
- st1 = data->mtface[data->face_index].uv[i1];
- st2 = data->mtface[data->face_index].uv[i2];
-
- 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;
-
- 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);
-
- resolve_tri_uv(fUV, st, st0, st1, st2);
-
- u = fUV[0];
- v = fUV[1];
- w = 1 - u - v;
-
- /* the sign is the same at all face vertices for any non degenerate face.
- * Just in case we clamp the interpolated value though. */
- sign = (tang0[3] * u + tang1[3] * v + tang2[3] * w) < 0 ? (-1.0f) : 1.0f;
-
- /* this sequence of math is designed specifically as is with great care
- * to be compatible with our shader. Please don't change without good reason. */
- for (r = 0; r < 3; r++) {
- from_tang[0][r] = tang0[r] * u + tang1[r] * v + tang2[r] * w;
- from_tang[2][r] = no0[r] * u + no1[r] * v + no2[r] * w;
- }
-
- cross_v3_v3v3(from_tang[1], from_tang[2], from_tang[0]); /* B = sign * cross(N, T) */
- mul_v3_fl(from_tang[1], sign);
- invert_m3_m3(to_tang, from_tang);
- /* sequence end */
-
- data->pass_data(data->lores_dm, data->hires_dm, data->bake_data,
- data->ibuf, data->face_index, data->lvl, st, to_tang, x, y);
-}
-
-static void set_rast_triangle(const MBakeRast *bake_rast, const int x, const int y)
-{
- const int w = bake_rast->w;
- const int h = bake_rast->h;
-
- if (x >= 0 && x < w && y >= 0 && y < h) {
- if ((bake_rast->texels[y * w + x]) == 0) {
- flush_pixel(bake_rast->data, x, y);
- bake_rast->texels[y * w + x] = FILTER_MASK_USED;
- }
- }
-}
-
-static void rasterize_half(const MBakeRast *bake_rast,
- const float s0_s, const float t0_s, const float s1_s, const float t1_s,
- const float s0_l, const float t0_l, const float s1_l, const float t1_l,
- const int y0_in, const int y1_in, const int is_mid_right)
-{
- const int s_stable = fabsf(t1_s - t0_s) > FLT_EPSILON ? 1 : 0;
- const int l_stable = fabsf(t1_l - t0_l) > FLT_EPSILON ? 1 : 0;
- const int w = bake_rast->w;
- const int h = bake_rast->h;
- int y, y0, y1;
-
- if (y1_in <= 0 || y0_in >= h)
- return;
-
- y0 = y0_in < 0 ? 0 : y0_in;
- y1 = y1_in >= h ? h : y1_in;
-
- for (y = y0; y < y1; y++) {
- /*-b(x-x0) + a(y-y0) = 0 */
- int iXl, iXr, x;
- float x_l = s_stable != 0 ? (s0_s + (((s1_s - s0_s) * (y - t0_s)) / (t1_s - t0_s))) : s0_s;
- float x_r = l_stable != 0 ? (s0_l + (((s1_l - s0_l) * (y - t0_l)) / (t1_l - t0_l))) : s0_l;
-
- if (is_mid_right != 0)
- SWAP(float, x_l, x_r);
-
- iXl = (int)ceilf(x_l);
- iXr = (int)ceilf(x_r);
-
- if (iXr > 0 && iXl < w) {
- iXl = iXl < 0 ? 0 : iXl;
- iXr = iXr >= w ? w : iXr;
-
- for (x = iXl; x < iXr; x++)
- set_rast_triangle(bake_rast, x, y);
- }
- }
-}
-
-static void bake_rasterize(const MBakeRast *bake_rast, const float st0_in[2], const float st1_in[2], const float st2_in[2])
-{
- const int w = bake_rast->w;
- const int h = bake_rast->h;
- float slo = st0_in[0] * w - 0.5f;
- float tlo = st0_in[1] * h - 0.5f;
- float smi = st1_in[0] * w - 0.5f;
- float tmi = st1_in[1] * h - 0.5f;
- float shi = st2_in[0] * w - 0.5f;
- float thi = st2_in[1] * h - 0.5f;
- int is_mid_right = 0, ylo, yhi, yhi_beg;
-
- /* skip degenerates */
- if ((slo == smi && tlo == tmi) || (slo == shi && tlo == thi) || (smi == shi && tmi == thi))
- return;
-
- /* sort by T */
- if (tlo > tmi && tlo > thi) {
- SWAP(float, shi, slo);
- SWAP(float, thi, tlo);
- }
- else if (tmi > thi) {
- SWAP(float, shi, smi);
- SWAP(float, thi, tmi);
- }
-
- if (tlo > tmi) {
- SWAP(float, slo, smi);
- SWAP(float, tlo, tmi);
- }
-
- /* check if mid point is to the left or to the right of the lo-hi edge */
- is_mid_right = (-(shi - slo) * (tmi - thi) + (thi - tlo) * (smi - shi)) > 0 ? 1 : 0;
- ylo = (int) ceilf(tlo);
- yhi_beg = (int) ceilf(tmi);
- yhi = (int) ceilf(thi);
-
- /*if (fTmi>ceilf(fTlo))*/
- rasterize_half(bake_rast, slo, tlo, smi, tmi, slo, tlo, shi, thi, ylo, yhi_beg, is_mid_right);
- rasterize_half(bake_rast, smi, tmi, shi, thi, slo, tlo, shi, thi, yhi_beg, yhi, is_mid_right);
-}
-
-static int multiresbake_test_break(MultiresBakeRender *bkr)
-{
- if (!bkr->stop) {
- /* this means baker is executed outside from job system */
- return 0;
- }
-
- return G.is_break;
-}
-
-static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, MPassKnownData passKnownData,
- MInitBakeData initBakeData, MApplyBakeData applyBakeData, MFreeBakeData freeBakeData)
-{
- DerivedMesh *dm = bkr->lores_dm;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
- const int lvl = bkr->lvl;
- const int tot_face = dm->getNumTessFaces(dm);
- MVert *mvert = dm->getVertArray(dm);
- MFace *mface = dm->getTessFaceArray(dm);
- MTFace *mtface = dm->getTessFaceDataArray(dm, CD_MTFACE);
- float *pvtangent = NULL;
-
- if (CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1)
- DM_add_tangent_layer(dm);
-
- pvtangent = DM_get_tessface_data_layer(dm, CD_TANGENT);
-
- if (tot_face > 0) { /* sanity check */
- int f = 0;
- MBakeRast bake_rast;
- MResolvePixelData data = {NULL};
-
- data.mface = mface;
- data.mvert = mvert;
- data.mtface = mtface;
- data.pvtangent = pvtangent;
- data.precomputed_normals = dm->getTessFaceDataArray(dm, CD_NORMAL); /* don't strictly need this */
- data.w = ibuf->x;
- data.h = ibuf->y;
- data.lores_dm = dm;
- data.hires_dm = bkr->hires_dm;
- data.lvl = lvl;
- data.pass_data = passKnownData;
-
- if (initBakeData)
- data.bake_data = initBakeData(bkr, ima);
-
- init_bake_rast(&bake_rast, ibuf, &data, flush_pixel);
-
- for (f = 0; f < tot_face; f++) {
- MTFace *mtfate = &mtface[f];
- int verts[3][2], nr_tris, t;
-
- if (multiresbake_test_break(bkr))
- break;
-
- if (mtfate->tpage != ima)
- continue;
-
- data.face_index = f;
- data.ibuf = ibuf;
-
- /* 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;
-
- verts[0][1] = 0;
- verts[1][1] = 2;
- verts[2][1] = 3;
-
- nr_tris = 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];
-
- bake_rasterize(&bake_rast, mtfate->uv[data.i0], mtfate->uv[data.i1], mtfate->uv[data.i2]);
- }
-
- bkr->baked_faces++;
-
- if (bkr->do_update)
- *bkr->do_update = TRUE;
-
- if (bkr->progress)
- *bkr->progress = ((float)bkr->baked_objects + (float)bkr->baked_faces / tot_face) / bkr->tot_obj;
- }
-
- if (applyBakeData)
- applyBakeData(data.bake_data);
-
- if (freeBakeData)
- freeBakeData(data.bake_data);
- }
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
-}
-
-/* mode = 0: interpolate normals,
- * mode = 1: interpolate coord */
-static void interp_bilinear_grid(CCGKey *key, CCGElem *grid, float crn_x, float crn_y, int mode, float res[3])
-{
- int x0, x1, y0, y1;
- float u, v;
- float data[4][3];
-
- x0 = (int) crn_x;
- x1 = x0 >= (key->grid_size - 1) ? (key->grid_size - 1) : (x0 + 1);
-
- y0 = (int) crn_y;
- y1 = y0 >= (key->grid_size - 1) ? (key->grid_size - 1) : (y0 + 1);
-
- u = crn_x - x0;
- v = crn_y - y0;
-
- if (mode == 0) {
- copy_v3_v3(data[0], CCG_grid_elem_no(key, grid, x0, y0));
- copy_v3_v3(data[1], CCG_grid_elem_no(key, grid, x1, y0));
- copy_v3_v3(data[2], CCG_grid_elem_no(key, grid, x1, y1));
- copy_v3_v3(data[3], CCG_grid_elem_no(key, grid, x0, y1));
- }
- else {
- copy_v3_v3(data[0], CCG_grid_elem_co(key, grid, x0, y0));
- copy_v3_v3(data[1], CCG_grid_elem_co(key, grid, x1, y0));
- copy_v3_v3(data[2], CCG_grid_elem_co(key, grid, x1, y1));
- copy_v3_v3(data[3], CCG_grid_elem_co(key, grid, x0, y1));
- }
-
- interp_bilinear_quad_v3(data, u, v, res);
-}
-
-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])
-{
- 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);
-
- 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);
- }
- 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];
-
- crn_y = (row * cell_side) + u * cell_side;
- crn_x = (col * cell_side) + v * cell_side;
- }
-
- CLAMP(crn_x, 0.0f, grid_size);
- CLAMP(crn_y, 0.0f, grid_size);
-
- if (n != NULL)
- interp_bilinear_grid(&key, grid_data[g_index + S], crn_x, crn_y, 0, n);
-
- if (co != NULL)
- interp_bilinear_grid(&key, grid_data[g_index + S], crn_x, crn_y, 1, co);
-}
-
-/* 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])
-{
- 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]);
- }
- 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]);
- }
-
- 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])
-{
- 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]);
- }
- else {
- dm->getVertCo(dm, mface->v1, data[0]);
- dm->getVertCo(dm, mface->v2, data[1]);
- dm->getVertCo(dm, mface->v3, data[2]);
- }
-
- interp_barycentric_tri_v3(data, u, v, res);
-}
-
-static void *init_heights_data(MultiresBakeRender *bkr, Image *ima)
-{
- MHeightBakeData *height_data;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
- DerivedMesh *lodm = bkr->lores_dm;
-
- height_data = MEM_callocN(sizeof(MHeightBakeData), "MultiresBake heightData");
-
- height_data->ima = ima;
- height_data->heights = MEM_callocN(sizeof(float) * ibuf->x * ibuf->y, "MultiresBake heights");
- height_data->height_max = -FLT_MAX;
- height_data->height_min = FLT_MAX;
-
- if (!bkr->use_lores_mesh) {
- SubsurfModifierData smd = {{NULL}};
- int ss_lvl = bkr->tot_lvl - bkr->lvl;
-
- CLAMP(ss_lvl, 0, 6);
-
- if (ss_lvl > 0) {
- smd.levels = smd.renderLevels = ss_lvl;
- smd.flags |= eSubsurfModifierFlag_SubsurfUv;
-
- if (bkr->simple)
- smd.subdivType = ME_SIMPLE_SUBSURF;
-
- height_data->ssdm = subsurf_make_derived_from_derived(bkr->lores_dm, &smd, NULL, 0);
- }
- }
-
- 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);
-
- return (void *)height_data;
-}
-
-static void *init_normal_data(MultiresBakeRender *bkr, Image *UNUSED(ima))
-{
- MNormalBakeData *normal_data;
- DerivedMesh *lodm = bkr->lores_dm;
-
- 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;
-}
-
-static void free_normal_data(void *bake_data)
-{
- MNormalBakeData *normal_data = (MNormalBakeData *)bake_data;
-
- MEM_freeN(normal_data);
-}
-
-static void apply_heights_data(void *bake_data)
-{
- MHeightBakeData *height_data = (MHeightBakeData *)bake_data;
- ImBuf *ibuf = BKE_image_acquire_ibuf(height_data->ima, NULL, NULL);
- int x, y, i;
- float height, *heights = height_data->heights;
- float min = height_data->height_min, max = height_data->height_max;
-
- for (x = 0; x < ibuf->x; x++) {
- for (y = 0; y < ibuf->y; y++) {
- i = ibuf->x * y + x;
-
- if (((char *)ibuf->userdata)[i] != FILTER_MASK_USED)
- continue;
-
- if (ibuf->rect_float) {
- float *rrgbf = ibuf->rect_float + i * 4;
-
- if (max - min > 1e-5f) height = (heights[i] - min) / (max - min);
- else height = 0;
-
- rrgbf[0] = rrgbf[1] = rrgbf[2] = height;
- }
- else {
- char *rrgb = (char *)ibuf->rect + i * 4;
-
- if (max - min > 1e-5f) height = (heights[i] - min) / (max - min);
- else height = 0;
-
- rrgb[0] = rrgb[1] = rrgb[2] = FTOCHAR(height);
- }
- }
- }
-
- ibuf->userflags = IB_RECT_INVALID | IB_DISPLAY_BUFFER_INVALID;
-
- BKE_image_release_ibuf(height_data->ima, ibuf, NULL);
-}
-
-static void free_heights_data(void *bake_data)
-{
- MHeightBakeData *height_data = (MHeightBakeData *)bake_data;
-
- if (height_data->ssdm)
- height_data->ssdm->release(height_data->ssdm);
-
- MEM_freeN(height_data->heights);
- MEM_freeN(height_data);
-}
-
-/* MultiresBake callback for heights baking
- * general idea:
- * - find coord of point with specified UV in hi-res mesh (let's call it p1)
- * - find coord of point and normal with specified UV in lo-res mesh (or subdivided lo-res
- * 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, const void *bake_data,
- ImBuf *ibuf, const int face_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;
- MHeightBakeData *height_data = (MHeightBakeData *)bake_data;
- 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];
- resolve_quad_uv(uv, st, st0, st1, st2, st3);
- }
- else
- resolve_tri_uv(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_mf_to_mpoly,
- lvl, face_index, uv[0], uv[1], p1, 0);
-
- if (height_data->ssdm) {
- get_ccgdm_data(lores_dm, height_data->ssdm,
- height_data->orig_index_mf_to_mpoly, height_data->orig_index_mf_to_mpoly,
- 0, face_index, 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);
- }
- 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);
- }
- }
-
- sub_v3_v3v3(vec, p1, p0);
- len = dot_v3v3(n, vec);
-
- height_data->heights[pixel] = len;
- if (len < height_data->height_min) height_data->height_min = len;
- if (len > height_data->height_max) height_data->height_max = len;
-
- if (ibuf->rect_float) {
- float *rrgbf = ibuf->rect_float + pixel * 4;
- rrgbf[3] = 1.0f;
-
- ibuf->userflags = IB_RECT_INVALID;
- }
- else {
- char *rrgb = (char *)ibuf->rect + pixel * 4;
- rrgb[3] = 255;
- }
-
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
-}
-
-/* MultiresBake callback for normals' baking
- * general idea:
- * - find coord and normal of point with specified UV in hi-res mesh
- * - 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, const void *bake_data,
- ImBuf *ibuf, const int face_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;
- 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];
- resolve_quad_uv(uv, st, st0, st1, st2, st3);
- }
- else
- resolve_tri_uv(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);
-
- mul_v3_m3v3(vec, tangmat, n);
- normalize_v3(vec);
- mul_v3_fl(vec, 0.5);
- add_v3_v3(vec, tmp);
-
- if (ibuf->rect_float) {
- float *rrgbf = ibuf->rect_float + pixel * 4;
- rrgbf[0] = vec[0];
- rrgbf[1] = vec[1];
- rrgbf[2] = vec[2];
- rrgbf[3] = 1.0f;
-
- ibuf->userflags = IB_RECT_INVALID;
- }
- else {
- unsigned char *rrgb = (unsigned char *)ibuf->rect + pixel * 4;
- rgb_float_to_uchar(rrgb, vec);
- rrgb[3] = 255;
- }
-
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
-}
-
-static void count_images(MultiresBakeRender *bkr)
-{
- int a, totface;
- DerivedMesh *dm = bkr->lores_dm;
- MTFace *mtface = CustomData_get_layer(&dm->faceData, CD_MTFACE);
-
- bkr->image.first = bkr->image.last = NULL;
- bkr->tot_image = 0;
-
- totface = dm->getNumTessFaces(dm);
-
- for (a = 0; a < totface; a++)
- mtface[a].tpage->id.flag &= ~LIB_DOIT;
-
- for (a = 0; a < totface; a++) {
- Image *ima = mtface[a].tpage;
- if ((ima->id.flag & LIB_DOIT) == 0) {
- LinkData *data = BLI_genericNodeN(ima);
- BLI_addtail(&bkr->image, data);
- bkr->tot_image++;
- ima->id.flag |= LIB_DOIT;
- }
- }
-
- for (a = 0; a < totface; a++)
- mtface[a].tpage->id.flag &= ~LIB_DOIT;
-}
-
-static void bake_images(MultiresBakeRender *bkr)
-{
- LinkData *link;
-
- for (link = bkr->image.first; link; link = link->next) {
- Image *ima = (Image *)link->data;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
-
- if (ibuf->x > 0 && ibuf->y > 0) {
- ibuf->userdata = MEM_callocN(ibuf->y * ibuf->x, "MultiresBake imbuf mask");
-
- switch (bkr->mode) {
- case RE_BAKE_NORMALS:
- do_multires_bake(bkr, ima, apply_tangmat_callback, init_normal_data, NULL, free_normal_data);
- break;
- case RE_BAKE_DISPLACEMENT:
- do_multires_bake(bkr, ima, apply_heights_callback, init_heights_data,
- apply_heights_data, free_heights_data);
- break;
- }
- }
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
-
- ima->id.flag |= LIB_DOIT;
- }
-}
-
-static void finish_images(MultiresBakeRender *bkr)
-{
- LinkData *link;
-
- for (link = bkr->image.first; link; link = link->next) {
- Image *ima = (Image *)link->data;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
-
- if (ibuf->x <= 0 || ibuf->y <= 0)
- continue;
-
- RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, bkr->bake_filter);
-
- ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID;
-
- if (ibuf->rect_float)
- ibuf->userflags |= IB_RECT_INVALID;
-
- if (ibuf->mipmap[0]) {
- ibuf->userflags |= IB_MIPMAP_INVALID;
- imb_freemipmapImBuf(ibuf);
- }
-
- if (ibuf->userdata) {
- MEM_freeN(ibuf->userdata);
- ibuf->userdata = NULL;
- }
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
-}
-
-static void multiresbake_start(MultiresBakeRender *bkr)
-{
- count_images(bkr);
- bake_images(bkr);
- finish_images(bkr);
-}
-
static int multiresbake_check(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -952,7 +138,9 @@ static int multiresbake_check(bContext *C, wmOperator *op)
}
}
}
- else ok = 0;
+ else {
+ ok = 0;
+ }
if (!ok) {
BKE_report(op->reports, RPT_ERROR, "Multires data baking requires multi-resolution object");
@@ -1023,6 +211,9 @@ static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *l
if (*lvl == 0) {
DerivedMesh *tmp_dm = CDDM_from_mesh(me, ob);
+
+ DM_set_only_copy(tmp_dm, CD_MASK_BAREMESH | CD_MASK_MTFACE);
+
dm = CDDM_copy(tmp_dm);
tmp_dm->release(tmp_dm);
}
@@ -1030,6 +221,8 @@ static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *l
MultiresModifierData tmp_mmd = *mmd;
DerivedMesh *cddm = CDDM_from_mesh(me, ob);
+ DM_set_only_copy(cddm, CD_MASK_BAREMESH | CD_MASK_MTFACE);
+
tmp_mmd.lvl = *lvl;
tmp_mmd.sculptlvl = *lvl;
dm = multires_make_derived_from_derived(cddm, &tmp_mmd, ob, 0);
@@ -1047,6 +240,14 @@ static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *l
DerivedMesh *cddm = CDDM_from_mesh(me, ob);
DerivedMesh *dm;
+ DM_set_only_copy(cddm, CD_MASK_BAREMESH);
+
+ /* TODO: DM_set_only_copy wouldn't set mask for loop and poly data,
+ * but we really need BAREMESH only to save lots of memory
+ */
+ CustomData_set_only_copy(&cddm->loopData, CD_MASK_BAREMESH);
+ CustomData_set_only_copy(&cddm->polyData, CD_MASK_BAREMESH);
+
*lvl = mmd->totlvl;
*simple = mmd->simple;
@@ -1058,11 +259,18 @@ static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *l
return dm;
}
-static void clear_images(MTFace *mtface, int totface)
+typedef enum ClearFlag {
+ CLEAR_NORMAL = 1
+} ClearFlag;
+
+
+static void clear_images(MTFace *mtface, int totface, ClearFlag flag)
{
int a;
const float vec_alpha[4] = {0.0f, 0.0f, 0.0f, 0.0f};
const float vec_solid[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ const float nor_alpha[4] = {0.5f, 0.5f, 1.0f, 0.0f};
+ const float nor_solid[4] = {0.5f, 0.5f, 1.0f, 1.0f};
for (a = 0; a < totface; a++)
mtface[a].tpage->id.flag &= ~LIB_DOIT;
@@ -1073,7 +281,11 @@ static void clear_images(MTFace *mtface, int totface)
if ((ima->id.flag & LIB_DOIT) == 0) {
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
- IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
+ if (flag == CLEAR_NORMAL)
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid);
+ else
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
+
ima->id.flag |= LIB_DOIT;
BKE_image_release_ibuf(ima, ibuf, NULL);
@@ -1101,14 +313,17 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
ob = base->object;
me = (Mesh *)ob->data;
- clear_images(me->mtface, me->totface);
+ if (scene->r.bake_mode == RE_BAKE_NORMALS && scene->r.bake_normal_space == R_BAKE_SPACE_TANGENT)
+ clear_images(me->mtface, me->totface, CLEAR_NORMAL);
+ else
+ clear_images(me->mtface, me->totface, 0);
}
CTX_DATA_END;
}
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- MultiresBakeRender bkr = {0};
+ MultiresBakeRender bkr = {NULL};
ob = base->object;
@@ -1118,16 +333,17 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
bkr.bake_filter = scene->r.bake_filter;
bkr.mode = scene->r.bake_mode;
bkr.use_lores_mesh = scene->r.bake_flag & R_BAKE_LORES_MESH;
+ bkr.bias = scene->r.bake_biasdist;
+ bkr.number_of_rays = scene->r.bake_samples;
+ bkr.raytrace_structure = scene->r.raytrace_structure;
+ bkr.octree_resolution = scene->r.ocres;
+ bkr.threads = scene->r.mode & R_FIXED_THREADS ? scene->r.threads : 0;
/* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
- bkr.lores_dm = multiresbake_create_loresdm(scene, ob, &bkr.lvl);
-
- if (!bkr.lores_dm)
- continue;
-
bkr.hires_dm = multiresbake_create_hiresdm(scene, ob, &bkr.tot_lvl, &bkr.simple);
+ bkr.lores_dm = multiresbake_create_loresdm(scene, ob, &bkr.lvl);
- multiresbake_start(&bkr);
+ RE_multires_bake_images(&bkr);
BLI_freelistN(&bkr.image);
@@ -1155,24 +371,27 @@ static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj)
bkj->mode = scene->r.bake_mode;
bkj->use_lores_mesh = scene->r.bake_flag & R_BAKE_LORES_MESH;
bkj->bake_clear = scene->r.bake_flag & R_BAKE_CLEAR;
+ bkj->bias = scene->r.bake_biasdist;
+ bkj->number_of_rays = scene->r.bake_samples;
+ bkj->raytrace_structure = scene->r.raytrace_structure;
+ bkj->octree_resolution = scene->r.ocres;
+ bkj->threads = scene->r.mode & R_FIXED_THREADS ? scene->r.threads : 0;
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
MultiresBakerJobData *data;
- DerivedMesh *lores_dm;
int lvl;
+
ob = base->object;
multires_force_update(ob);
- lores_dm = multiresbake_create_loresdm(scene, ob, &lvl);
- if (!lores_dm)
- continue;
-
data = MEM_callocN(sizeof(MultiresBakerJobData), "multiresBaker derivedMesh_data");
- data->lores_dm = lores_dm;
- data->lvl = lvl;
+
+ /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
data->hires_dm = multiresbake_create_hiresdm(scene, ob, &data->tot_lvl, &data->simple);
+ data->lores_dm = multiresbake_create_loresdm(scene, ob, &lvl);
+ data->lvl = lvl;
BLI_addtail(&bkj->data, data);
}
@@ -1192,12 +411,15 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa
DerivedMesh *dm = data->lores_dm;
MTFace *mtface = CustomData_get_layer(&dm->faceData, CD_MTFACE);
- clear_images(mtface, dm->getNumTessFaces(dm));
+ if (bkj->mode == RE_BAKE_NORMALS)
+ clear_images(mtface, dm->getNumTessFaces(dm), CLEAR_NORMAL);
+ else
+ clear_images(mtface, dm->getNumTessFaces(dm), 0);
}
}
for (data = bkj->data.first; data; data = data->next) {
- MultiresBakeRender bkr = {0};
+ MultiresBakeRender bkr = {NULL};
/* copy data stored in job descriptor */
bkr.bake_filter = bkj->bake_filter;
@@ -1219,9 +441,15 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa
bkr.do_update = do_update;
bkr.progress = progress;
- multiresbake_start(&bkr);
+ bkr.bias = bkj->bias;
+ bkr.number_of_rays = bkj->number_of_rays;
+ bkr.raytrace_structure = bkj->raytrace_structure;
+ bkr.octree_resolution = bkj->octree_resolution;
+ bkr.threads = bkj->threads;
- BLI_freelistN(&bkr.image);
+ RE_multires_bake_images(&bkr);
+
+ data->images = bkr.image;
baked_objects++;
}
@@ -1231,12 +459,22 @@ static void multiresbake_freejob(void *bkv)
{
MultiresBakeJob *bkj = bkv;
MultiresBakerJobData *data, *next;
+ LinkData *link;
data = bkj->data.first;
while (data) {
next = data->next;
data->lores_dm->release(data->lores_dm);
data->hires_dm->release(data->hires_dm);
+
+ /* delete here, since this delete will be called from main thread */
+ for (link = data->images.first; link; link = link->next) {
+ Image *ima = (Image *)link->data;
+ GPU_free_image(ima);
+ }
+
+ BLI_freelistN(&data->images);
+
MEM_freeN(data);
data = next;
}
@@ -1334,7 +572,7 @@ static void init_bake_internal(BakeRender *bkr, bContext *C)
bScreen *sc = CTX_wm_screen(C);
/* get editmode results */
- ED_object_exit_editmode(C, 0); /* 0 = does not exit editmode */
+ ED_object_editmode_load(CTX_data_edit_object(C));
bkr->sa = sc ? BKE_screen_find_big_area(sc, SPACE_IMAGE, 10) : NULL; /* can be NULL */
bkr->main = CTX_data_main(C);
@@ -1391,7 +629,12 @@ static void finish_bake_internal(BakeRender *bkr)
/* freed when baking is done, but if its canceled we need to free here */
if (ibuf) {
if (ibuf->userdata) {
- MEM_freeN(ibuf->userdata);
+ BakeImBufuserData *userdata = (BakeImBufuserData *) ibuf->userdata;
+ if (userdata->mask_buffer)
+ MEM_freeN(userdata->mask_buffer);
+ if (userdata->displacement_buffer)
+ MEM_freeN(userdata->displacement_buffer);
+ MEM_freeN(userdata);
ibuf->userdata = NULL;
}
}
@@ -1455,7 +698,7 @@ static void bake_freejob(void *bkv)
}
/* catch esc */
-static int objects_bake_render_modal(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int objects_bake_render_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
/* no running blender, remove handler and pass through */
if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_BAKE_TEXTURE))
@@ -1472,13 +715,13 @@ static int objects_bake_render_modal(bContext *C, wmOperator *UNUSED(op), wmEven
static int is_multires_bake(Scene *scene)
{
- if (ELEM(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT))
+ if (ELEM3(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT, RE_BAKE_AO))
return scene->r.bake_flag & R_BAKE_MULTIRES;
return 0;
}
-static int objects_bake_render_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(_event))
+static int objects_bake_render_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(_event))
{
Scene *scene = CTX_data_scene(C);
int result = OPERATOR_CANCELLED;
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index f78e1203bc4..9b61fa44955 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -40,6 +40,8 @@
#include "BLI_dynstr.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "DNA_anim_types.h"
#include "DNA_constraint_types.h"
#include "DNA_curve_types.h"
@@ -141,7 +143,7 @@ ListBase *get_constraint_lb(Object *ob, bConstraint *con, bPoseChannel **pchan_r
/* single constraint */
bConstraint *get_active_constraint(Object *ob)
{
- return constraints_get_active(get_active_constraints(ob));
+ return BKE_constraints_get_active(get_active_constraints(ob));
}
/* -------------- Constraint Management (Add New, Remove, Rename) -------------------- */
@@ -225,7 +227,7 @@ 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 = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
int num_targets, i;
@@ -297,7 +299,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 = constraint_get_typeinfo(curcon);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(curcon);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -433,7 +435,9 @@ static void test_constraints(Object *owner, bPoseChannel *pchan)
curcon->flag |= CONSTRAINT_DISABLE;
}
}
- else curcon->flag |= CONSTRAINT_DISABLE;
+ else {
+ curcon->flag |= CONSTRAINT_DISABLE;
+ }
}
}
else if (curcon->type == CONSTRAINT_TYPE_CAMERASOLVER) {
@@ -600,7 +604,7 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int
list = &pchan->constraints;
else {
//if (G.debug & G_DEBUG)
- //printf("edit_constraint_property_get: No active bone for object '%s'\n", (ob)? ob->id.name+2 : "<None>");
+ //printf("edit_constraint_property_get: No active bone for object '%s'\n", (ob)? ob->id.name + 2 : "<None>");
return NULL;
}
}
@@ -610,7 +614,7 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int
list = get_active_constraints(ob);
}
- con = constraints_findByName(list, constraint_name);
+ con = BKE_constraints_findByName(list, constraint_name);
//if (G.debug & G_DEBUG)
//printf("constraint found = %p, %s\n", (void *)con, (con)?con->name:"<Not found>");
@@ -643,7 +647,7 @@ static int stretchto_reset_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int stretchto_reset_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int stretchto_reset_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_constraint_invoke_properties(C, op))
return stretchto_reset_exec(C, op);
@@ -689,7 +693,7 @@ static int limitdistance_reset_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int limitdistance_reset_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int limitdistance_reset_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_constraint_invoke_properties(C, op))
return limitdistance_reset_exec(C, op);
@@ -718,81 +722,87 @@ void CONSTRAINT_OT_limitdistance_reset(wmOperatorType *ot)
/* ------------- Child-Of Constraint ------------------ */
-static void child_get_inverse_matrix(Scene *scene, Object *ob, bConstraint *con, float invmat[4][4])
+static void child_get_inverse_matrix(Scene *scene, Object *ob, bConstraint *con, float invmat[4][4], const int owner)
{
- bConstraint *lastcon = NULL;
- bPoseChannel *pchan = NULL;
-
/* nullify inverse matrix first */
unit_m4(invmat);
- /* try to find a pose channel - assume that this is the constraint owner */
- /* TODO: get from context instead? */
- if (ob && ob->pose)
- pchan = BKE_pose_channel_active(ob);
-
- /* calculate/set inverse matrix:
- * We just calculate all transform-stack eval up to but not including this constraint.
- * This is because inverse should just inverse correct for just the constraint's influence
- * when it gets applied; that is, at the time of application, we don't know anything about
- * what follows.
- */
- if (pchan) {
- float imat[4][4], tmat[4][4];
- float pmat[4][4];
-
- /* 1. calculate posemat where inverse doesn't exist yet (inverse was cleared above),
- * to use as baseline ("pmat") to derive delta from. This extra calc saves users
- * from having pressing "Clear Inverse" first
- */
- BKE_pose_where_is(scene, ob);
- copy_m4_m4(pmat, pchan->pose_mat);
-
- /* 2. knock out constraints starting from this one */
- lastcon = pchan->constraints.last;
- pchan->constraints.last = con->prev;
-
- if (con->prev) {
- /* new end must not point to this one, else this chain cutting is useless */
- con->prev->next = NULL;
- }
- else {
- /* constraint was first */
- pchan->constraints.first = NULL;
- }
-
- /* 3. solve pose without disabled constraints */
- BKE_pose_where_is(scene, ob);
-
- /* 4. determine effect of constraint by removing the newly calculated
- * pchan->pose_mat from the original pchan->pose_mat, thus determining
- * the effect of the constraint
- */
- invert_m4_m4(imat, pchan->pose_mat);
- mult_m4_m4m4(tmat, pmat, imat);
- invert_m4_m4(invmat, tmat);
-
- /* 5. restore constraints */
- pchan->constraints.last = lastcon;
-
- if (con->prev) {
- /* hook up prev to this one again */
- con->prev->next = con;
- }
- else {
- /* set as first again */
- pchan->constraints.first = con;
+ if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
+ bPoseChannel *pchan;
+ /* try to find a pose channel - assume that this is the constraint owner */
+ /* TODO: get from context instead? */
+ if (ob && ob->pose && (pchan = BKE_pose_channel_active(ob))) {
+ bConstraint *con_last;
+ /* calculate/set inverse matrix:
+ * We just calculate all transform-stack eval up to but not including this constraint.
+ * This is because inverse should just inverse correct for just the constraint's influence
+ * when it gets applied; that is, at the time of application, we don't know anything about
+ * what follows.
+ */
+ float imat[4][4], tmat[4][4];
+ float pmat[4][4];
+
+ /* make sure we passed the correct constraint */
+ BLI_assert(BLI_findindex(&pchan->constraints, con) != -1);
+
+ /* 1. calculate posemat where inverse doesn't exist yet (inverse was cleared above),
+ * to use as baseline ("pmat") to derive delta from. This extra calc saves users
+ * from having pressing "Clear Inverse" first
+ */
+ BKE_pose_where_is(scene, ob);
+ copy_m4_m4(pmat, pchan->pose_mat);
+
+ /* 2. knock out constraints starting from this one */
+ con_last = pchan->constraints.last;
+ pchan->constraints.last = con->prev;
+
+ if (con->prev) {
+ /* new end must not point to this one, else this chain cutting is useless */
+ con->prev->next = NULL;
+ }
+ else {
+ /* constraint was first */
+ pchan->constraints.first = NULL;
+ }
+
+ /* 3. solve pose without disabled constraints */
+ BKE_pose_where_is(scene, ob);
+
+ /* 4. determine effect of constraint by removing the newly calculated
+ * pchan->pose_mat from the original pchan->pose_mat, thus determining
+ * the effect of the constraint
+ */
+ invert_m4_m4(imat, pchan->pose_mat);
+ mult_m4_m4m4(tmat, pmat, imat);
+ invert_m4_m4(invmat, tmat);
+
+ /* 5. restore constraints */
+ pchan->constraints.last = con_last;
+
+ if (con->prev) {
+ /* hook up prev to this one again */
+ con->prev->next = con;
+ }
+ else {
+ /* set as first again */
+ pchan->constraints.first = con;
+ }
+
+ /* 6. recalculate pose with new inv-mat applied */
+ BKE_pose_where_is(scene, ob);
}
-
- /* 6. recalculate pose with new inv-mat applied */
- BKE_pose_where_is(scene, ob);
}
- else if (ob) {
- Object workob;
-
- /* use BKE_object_workob_calc_parent to find inverse - just like for normal parenting */
- BKE_object_workob_calc_parent(scene, ob, &workob);
- invert_m4_m4(invmat, workob.obmat);
+ if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
+ if (ob) {
+ Object workob;
+
+ /* make sure we passed the correct constraint */
+ BLI_assert(BLI_findindex(&ob->constraints, con) != -1);
+
+ /* use BKE_object_workob_calc_parent to find inverse - just like for normal parenting */
+ BKE_object_workob_calc_parent(scene, ob, &workob);
+ invert_m4_m4(invmat, workob.obmat);
+ }
}
}
@@ -803,6 +813,7 @@ static int childof_set_inverse_exec(bContext *C, wmOperator *op)
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF);
bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL;
+ const int owner = RNA_enum_get(op->ptr, "owner");
/* despite 3 layers of checks, we may still not be able to find a constraint */
if (data == NULL) {
@@ -811,14 +822,14 @@ static int childof_set_inverse_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- child_get_inverse_matrix(scene, ob, con, data->invmat);
+ child_get_inverse_matrix(scene, ob, con, data->invmat, owner);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
return OPERATOR_FINISHED;
}
-static int childof_set_inverse_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int childof_set_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_constraint_invoke_properties(C, op))
return childof_set_inverse_exec(C, op);
@@ -865,7 +876,7 @@ static int childof_clear_inverse_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int childof_clear_inverse_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int childof_clear_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_constraint_invoke_properties(C, op))
return childof_clear_inverse_exec(C, op);
@@ -982,7 +993,7 @@ static int followpath_path_animate_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int followpath_path_animate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int followpath_path_animate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
/* hook up invoke properties for figuring out which constraint we're dealing with */
if (edit_constraint_invoke_properties(C, op)) {
@@ -1024,6 +1035,7 @@ static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL;
+ const int owner = RNA_enum_get(op->ptr, "owner");
/* despite 3 layers of checks, we may still not be able to find a constraint */
if (data == NULL) {
@@ -1032,14 +1044,14 @@ static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- child_get_inverse_matrix(scene, ob, con, data->invmat);
+ child_get_inverse_matrix(scene, ob, con, data->invmat, owner);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
return OPERATOR_FINISHED;
}
-static int objectsolver_set_inverse_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int objectsolver_set_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_constraint_invoke_properties(C, op))
return objectsolver_set_inverse_exec(C, op);
@@ -1085,7 +1097,7 @@ static int objectsolver_clear_inverse_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int objectsolver_clear_inverse_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int objectsolver_clear_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_constraint_invoke_properties(C, op))
return objectsolver_clear_inverse_exec(C, op);
@@ -1123,7 +1135,7 @@ void ED_object_constraint_set_active(Object *ob, bConstraint *con)
if ((lb && con) && (con->flag & CONSTRAINT_ACTIVE))
return;
- constraints_set_active(lb, con);
+ BKE_constraints_set_active(lb, con);
}
void ED_object_constraint_update(Object *ob)
@@ -1138,12 +1150,12 @@ void ED_object_constraint_update(Object *ob)
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
}
-void ED_object_constraint_dependency_update(Main *bmain, Scene *scene, Object *ob)
+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
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
}
static int constraint_poll(bContext *C)
@@ -1162,9 +1174,9 @@ static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op))
const short is_ik = ELEM(con->type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK);
/* free the constraint */
- if (remove_constraint(lb, con)) {
+ if (BKE_remove_constraint(lb, con)) {
/* there's no active constraint now, so make sure this is the case */
- constraints_set_active(lb, NULL);
+ BKE_constraints_set_active(lb, NULL);
ED_object_constraint_update(ob); /* needed to set the flags on posebones correctly */
@@ -1221,7 +1233,7 @@ static int constraint_move_down_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int constraint_move_down_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int constraint_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_constraint_invoke_properties(C, op))
return constraint_move_down_exec(C, op);
@@ -1270,7 +1282,7 @@ static int constraint_move_up_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int constraint_move_up_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int constraint_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_constraint_invoke_properties(C, op))
return constraint_move_up_exec(C, op);
@@ -1302,19 +1314,18 @@ void CONSTRAINT_OT_move_up(wmOperatorType *ot)
static int pose_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
/* free constraints for all selected bones */
CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
{
- free_constraints(&pchan->constraints);
+ BKE_free_constraints(&pchan->constraints);
pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_SPLINEIK | PCHAN_HAS_CONST);
}
CTX_DATA_END;
/* force depsgraph to get recalculated since relationships removed */
- DAG_scene_sort(bmain, scene); /* sort order of objects */
+ DAG_relations_tag_update(bmain);
/* note, calling BIK_clear_data() isn't needed here */
@@ -1341,18 +1352,17 @@ void POSE_OT_constraints_clear(wmOperatorType *ot)
static int object_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
/* do freeing */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
- free_constraints(&ob->constraints);
+ BKE_free_constraints(&ob->constraints);
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
}
CTX_DATA_END;
/* force depsgraph to get recalculated since relationships removed */
- DAG_scene_sort(bmain, scene); /* sort order of objects */
+ DAG_relations_tag_update(bmain);
/* do updates */
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
@@ -1377,7 +1387,6 @@ void OBJECT_OT_constraints_clear(wmOperatorType *ot)
static int pose_constraint_copy_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
bPoseChannel *pchan = CTX_data_active_pose_bone(C);
/* don't do anything if bone doesn't exist or doesn't have any constraints */
@@ -1391,7 +1400,7 @@ static int pose_constraint_copy_exec(bContext *C, wmOperator *op)
{
/* if we're not handling the object we're copying from, copy all constraints over */
if (pchan != chan) {
- copy_constraints(&chan->constraints, &pchan->constraints, TRUE);
+ BKE_copy_constraints(&chan->constraints, &pchan->constraints, TRUE);
/* update flags (need to add here, not just copy) */
chan->constflag |= pchan->constflag;
}
@@ -1399,7 +1408,7 @@ static int pose_constraint_copy_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* force depsgraph to get recalculated since new relationships added */
- DAG_scene_sort(bmain, scene); /* sort order of objects/bones */
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
@@ -1424,7 +1433,6 @@ void POSE_OT_constraints_copy(wmOperatorType *ot)
static int object_constraint_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
Object *obact = ED_object_active_context(C);
/* copy all constraints from active object to all selected objects */
@@ -1432,14 +1440,14 @@ static int object_constraint_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
/* if we're not handling the object we're copying from, copy all constraints over */
if (obact != ob) {
- copy_constraints(&ob->constraints, &obact->constraints, TRUE);
+ BKE_copy_constraints(&ob->constraints, &obact->constraints, TRUE);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
CTX_DATA_END;
/* force depsgraph to get recalculated since new relationships added */
- DAG_scene_sort(bmain, scene); /* sort order of objects */
+ DAG_relations_tag_update(bmain);
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_ADDED, NULL);
@@ -1607,7 +1615,6 @@ static short get_new_constraint_target(bContext *C, int con_type, Object **tar_o
static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase *list, int type, short setTarget)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
bPoseChannel *pchan;
bConstraint *con;
@@ -1642,9 +1649,9 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase
/* create a new constraint of the type requried, and add it to the active/given constraints list */
if (pchan)
- con = add_pose_constraint(ob, pchan, NULL, type);
+ con = BKE_add_pose_constraint(ob, pchan, NULL, type);
else
- con = add_ob_constraint(ob, NULL, type);
+ con = BKE_add_ob_constraint(ob, NULL, type);
/* get the first selected object/bone, and make that the target
* - apart from the buttons-window add buttons, we shouldn't add in this way
@@ -1701,7 +1708,7 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase
/* force depsgraph to get recalculated since new relationships added */
- DAG_scene_sort(bmain, scene); /* sort order of objects */
+ DAG_relations_tag_update(bmain);
if ((ob->type == OB_ARMATURE) && (pchan)) {
ob->pose->flag |= POSE_RECALC; /* sort pose channels */
@@ -1843,7 +1850,7 @@ void POSE_OT_constraint_add_with_targets(wmOperatorType *ot)
// TODO: should these be here, or back in editors/armature/poseobject.c again?
/* present menu with options + validation for targets to use */
-static int pose_ik_add_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt))
+static int pose_ik_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
bPoseChannel *pchan = BKE_pose_channel_active(ob);
@@ -1870,7 +1877,7 @@ static int pose_ik_add_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt))
}
/* prepare popup menu to choose targetting options */
- pup = uiPupMenuBegin(C, "Add IK", ICON_NONE);
+ pup = uiPupMenuBegin(C, IFACE_("Add IK"), ICON_NONE);
layout = uiPupMenuLayout(pup);
/* the type of targets we'll set determines the menu entries to show... */
@@ -1879,14 +1886,14 @@ static int pose_ik_add_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt))
* - the only thing that matters is that we want a target...
*/
if (tar_pchan)
- uiItemBooleanO(layout, "To Active Bone", ICON_NONE, "POSE_OT_ik_add", "with_targets", 1);
+ uiItemBooleanO(layout, IFACE_("To Active Bone"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 1);
else
- uiItemBooleanO(layout, "To Active Object", ICON_NONE, "POSE_OT_ik_add", "with_targets", 1);
+ uiItemBooleanO(layout, IFACE_("To Active Object"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 1);
}
else {
/* we have a choice of adding to a new empty, or not setting any target (targetless IK) */
- uiItemBooleanO(layout, "To New Empty Object", ICON_NONE, "POSE_OT_ik_add", "with_targets", 1);
- uiItemBooleanO(layout, "Without Targets", ICON_NONE, "POSE_OT_ik_add", "with_targets", 0);
+ uiItemBooleanO(layout, IFACE_("To New Empty Object"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 1);
+ uiItemBooleanO(layout, IFACE_("Without Targets"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 0);
}
/* finish building the menu, and process it (should result in calling self again) */
@@ -1940,7 +1947,7 @@ static int pose_ik_clear_exec(bContext *C, wmOperator *UNUSED(op))
for (con = pchan->constraints.first; con; con = next) {
next = con->next;
if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
- remove_constraint(&pchan->constraints, con);
+ BKE_remove_constraint(&pchan->constraints, con);
}
}
pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_TARGET);
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index d39e34824b9..12400209866 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -150,7 +150,7 @@ static int object_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op))
}
if (changed) {
DAG_id_type_tag(bmain, ID_OB);
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
@@ -207,7 +207,7 @@ static int object_hide_view_set_exec(bContext *C, wmOperator *op)
if (changed) {
DAG_id_type_tag(bmain, ID_OB);
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
@@ -312,29 +312,26 @@ void OBJECT_OT_hide_render_set(wmOperatorType *ot)
/* ******************* toggle editmode operator ***************** */
-void ED_object_exit_editmode(bContext *C, int flag)
+/**
+ * Load EditMode data back into the object,
+ * optionally freeing the editmode data.
+ */
+static bool ED_object_editmode_load_ex(Object *obedit, const bool freedata)
{
- /* Note! only in exceptional cases should 'EM_DO_UNDO' NOT be in the flag */
+ if (obedit == NULL) {
+ return false;
+ }
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- int freedata = flag & EM_FREEDATA;
-
- if (obedit == NULL) return;
-
- if (flag & EM_WAITCURSOR) waitcursor(1);
if (obedit->type == OB_MESH) {
Mesh *me = obedit->data;
-
-// if (EM_texFaceCheck())
-
+
if (me->edit_btmesh->bm->totvert > MESH_MAX_VERTS) {
error("Too many vertices");
- return;
+ return false;
}
-
+
EDBM_mesh_load(obedit);
-
+
if (freedata) {
EDBM_mesh_free(me->edit_btmesh);
MEM_freeN(me->edit_btmesh);
@@ -367,6 +364,29 @@ void ED_object_exit_editmode(bContext *C, int flag)
if (freedata) free_editMball(obedit);
}
+ return true;
+}
+
+bool ED_object_editmode_load(Object *obedit)
+{
+ return ED_object_editmode_load_ex(obedit, false);
+}
+
+void ED_object_editmode_exit(bContext *C, int flag)
+{
+ /* Note! only in exceptional cases should 'EM_DO_UNDO' NOT be in the flag */
+ /* Note! if 'EM_FREEDATA' isn't in the flag, use ED_object_editmode_load directly */
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ const bool freedata = (flag & EM_FREEDATA) != 0;
+
+ if (flag & EM_WAITCURSOR) waitcursor(1);
+
+ if (ED_object_editmode_load_ex(obedit, freedata) == false) {
+ if (flag & EM_WAITCURSOR) waitcursor(0);
+ return;
+ }
+
/* freedata only 0 now on file saves and render */
if (freedata) {
ListBase pidlist;
@@ -376,7 +396,7 @@ void ED_object_exit_editmode(bContext *C, int flag)
scene->obedit = NULL; // XXX for context
/* flag object caches as outdated */
- BKE_ptcache_ids_from_object(&pidlist, obedit, NULL, 0);
+ BKE_ptcache_ids_from_object(&pidlist, obedit, scene, 0);
for (pid = pidlist.first; pid; pid = pid->next) {
if (pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */
pid->cache->flag |= PTCACHE_OUTDATED;
@@ -390,17 +410,17 @@ void ED_object_exit_editmode(bContext *C, int flag)
if (flag & EM_DO_UNDO)
ED_undo_push(C, "Editmode");
-
- if (flag & EM_WAITCURSOR) waitcursor(0);
-
+
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
obedit->mode &= ~OB_MODE_EDIT;
}
+
+ if (flag & EM_WAITCURSOR) waitcursor(0);
}
-void ED_object_enter_editmode(bContext *C, int flag)
+void ED_object_editmode_enter(bContext *C, int flag)
{
Scene *scene = CTX_data_scene(C);
Base *base = NULL;
@@ -429,6 +449,10 @@ void ED_object_enter_editmode(bContext *C, int flag)
ob = base->object;
+ /* this checks actual object->data, for cases when other scenes have it in editmode context */
+ if ( BKE_object_is_in_editmode(ob) )
+ return;
+
if (BKE_object_obdata_is_libdata(ob)) {
error_libdata();
return;
@@ -533,9 +557,9 @@ static int editmode_toggle_exec(bContext *C, wmOperator *UNUSED(op))
ToolSettings *toolsettings = CTX_data_tool_settings(C);
if (!CTX_data_edit_object(C))
- ED_object_enter_editmode(C, EM_WAITCURSOR);
+ ED_object_editmode_enter(C, EM_WAITCURSOR);
else
- ED_object_exit_editmode(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR); /* had EM_DO_UNDO but op flag calls undo too [#24685] */
+ 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);
@@ -585,7 +609,7 @@ static int posemode_exec(bContext *C, wmOperator *UNUSED(op))
if (base->object->type == OB_ARMATURE) {
if (base->object == CTX_data_edit_object(C)) {
- ED_object_exit_editmode(C, EM_FREEDATA | EM_DO_UNDO);
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_DO_UNDO);
ED_armature_enter_posemode(C, base);
}
else if (base->object->mode & OB_MODE_POSE)
@@ -767,7 +791,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
Base *base;
Curve *cu, *cu1;
Nurb *nu;
- int do_scene_sort = FALSE;
+ bool do_depgraph_update = false;
if (scene->id.lib) return;
@@ -794,7 +818,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
for (base = FIRSTBASE; base; base = base->next) {
if (base != BASACT) {
if (TESTBASELIB(v3d, base)) {
- base->object->recalc |= OB_RECALC_OB;
+ DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
if (event == 1) { /* loc */
copy_v3_v3(base->object->loc, ob->loc);
@@ -893,7 +917,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
BLI_strncpy(cu1->family, cu->family, sizeof(cu1->family));
- base->object->recalc |= OB_RECALC_DATA;
+ DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
}
}
else if (event == 19) { /* bevel settings */
@@ -909,7 +933,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
cu1->ext1 = cu->ext1;
cu1->ext2 = cu->ext2;
- base->object->recalc |= OB_RECALC_DATA;
+ DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
}
}
else if (event == 25) { /* curve resolution */
@@ -928,7 +952,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
nu = nu->next;
}
- base->object->recalc |= OB_RECALC_DATA;
+ DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
}
}
else if (event == 21) {
@@ -944,15 +968,15 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
}
modifier_copyData(md, tmd);
- base->object->recalc |= OB_RECALC_DATA;
+ DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
}
}
}
else if (event == 22) {
/* Copy the constraint channels over */
- copy_constraints(&base->object->constraints, &ob->constraints, TRUE);
+ BKE_copy_constraints(&base->object->constraints, &ob->constraints, TRUE);
- do_scene_sort = TRUE;
+ do_depgraph_update = true;
}
else if (event == 23) {
base->object->softflag = ob->softflag;
@@ -1004,13 +1028,11 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
}
}
- if (do_scene_sort)
- DAG_scene_sort(bmain, scene);
-
- DAG_ids_flush_update(bmain, 0);
+ if (do_depgraph_update)
+ DAG_relations_tag_update(bmain);
}
-static void UNUSED_FUNCTION(copy_attr_menu) (Main * bmain, Scene * scene, View3D * v3d)
+static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, View3D *v3d)
{
Object *ob;
short event;
@@ -1130,7 +1152,7 @@ void ED_objects_recalculate_paths(bContext *C, Scene *scene)
/* show popup to determine settings */
-static int object_calculate_paths_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int object_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Object *ob = CTX_data_active_object(C);
@@ -1147,7 +1169,7 @@ static int object_calculate_paths_invoke(bContext *C, wmOperator *op, wmEvent *U
/* show popup dialog to allow editing of range... */
/* FIXME: hardcoded dimensions here are just arbitrary */
- return WM_operator_props_dialog_popup(C, op, 200, 200);
+ return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 10 * UI_UNIT_Y);
}
/* Calculate/recalculate whole paths (avs.path_sf to avs.path_ef) */
@@ -1356,7 +1378,7 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot)
/* ********************** */
-static void UNUSED_FUNCTION(image_aspect) (Scene * scene, View3D * v3d)
+static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d)
{
/* all selected objects with an image map: scale in image aspect */
Base *base;
@@ -1672,10 +1694,6 @@ static EnumPropertyItem game_properties_copy_operations[] = {
{0, NULL, 0, NULL, NULL}
};
-static EnumPropertyItem gameprops_items[] = {
- {0, NULL, 0, NULL, NULL}
-};
-
static EnumPropertyItem *gameprops_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
{
Object *ob = ED_object_active_context(C);
@@ -1685,7 +1703,7 @@ static EnumPropertyItem *gameprops_itemf(bContext *C, PointerRNA *UNUSED(ptr), P
int a, totitem = 0;
if (!ob)
- return gameprops_items;
+ return DummyRNA_NULL_items;
for (a = 1, prop = ob->prop.first; prop; prop = prop->next, a++) {
tmp.value = a;
@@ -1756,7 +1774,7 @@ void OBJECT_OT_game_property_copy(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_enum(ot->srna, "operation", game_properties_copy_operations, 3, "Operation", "");
- prop = RNA_def_enum(ot->srna, "property", gameprops_items, 0, "Property", "Properties to copy");
+ prop = RNA_def_enum(ot->srna, "property", DummyRNA_NULL_items, 0, "Property", "Properties to copy");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
RNA_def_enum_funcs(prop, gameprops_itemf);
ot->prop = prop;
@@ -1864,9 +1882,7 @@ static int game_physics_copy_exec(bContext *C, wmOperator *UNUSED(op))
ob_iter->max_vel = ob->max_vel;
ob_iter->obstacleRad = ob->obstacleRad;
ob_iter->mass = ob->mass;
- ob_iter->anisotropicFriction[0] = ob->anisotropicFriction[0];
- ob_iter->anisotropicFriction[1] = ob->anisotropicFriction[1];
- ob_iter->anisotropicFriction[2] = ob->anisotropicFriction[2];
+ copy_v3_v3(ob_iter->anisotropicFriction, ob->anisotropicFriction);
ob_iter->collision_boundtype = ob->collision_boundtype;
ob_iter->margin = ob->margin;
ob_iter->bsoft = copy_bulletsoftbody(ob->bsoft);
@@ -1874,6 +1890,9 @@ static int game_physics_copy_exec(bContext *C, wmOperator *UNUSED(op))
ob_iter->restrictflag |= OB_RESTRICT_RENDER;
else
ob_iter->restrictflag &= ~OB_RESTRICT_RENDER;
+
+ ob_iter->col_group = ob->col_group;
+ ob_iter->col_mask = ob->col_mask;
}
}
CTX_DATA_END;
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index a3bf27a19d6..3112bb21091 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -137,7 +137,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_WARNING, "Skipped some groups because of cycle detected");
}
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -197,7 +197,7 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op)
if (!ok) BKE_report(op->reports, RPT_ERROR, "Active object contains no groups");
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -229,7 +229,7 @@ static int group_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op))
}
CTX_DATA_END;
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -269,7 +269,7 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -311,15 +311,15 @@ static int group_create_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "name", name);
- group = add_group(name);
+ group = add_group(bmain, name);
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
add_to_group(group, base->object, scene, base);
}
CTX_DATA_END;
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -348,12 +348,13 @@ static int group_add_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_context(C);
+ Main *bmain = CTX_data_main(C);
Group *group;
if (ob == NULL)
return OPERATOR_CANCELLED;
- group = add_group("Group");
+ group = add_group(bmain, "Group");
add_to_group(group, ob, scene, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index caeff1e82a7..43736909c40 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -386,6 +386,31 @@ static void select_editcurve_hook(Object *obedit, HookModifierData *hmd)
}
}
+static void object_hook_from_context(bContext *C, PointerRNA *ptr, const int num,
+ Object **r_ob, HookModifierData **r_hmd)
+{
+ Object *ob;
+ HookModifierData *hmd;
+
+ if (ptr->data) { /* if modifier context is available, use that */
+ ob = ptr->id.data;
+ hmd = ptr->data;
+ }
+ else { /* use the provided property */
+ ob = CTX_data_edit_object(C);
+ hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
+ }
+
+ if (ob && hmd && (hmd->modifier.type == eModifierType_Hook)) {
+ *r_ob = ob;
+ *r_hmd = hmd;
+ }
+ else {
+ *r_ob = NULL;
+ *r_hmd = NULL;
+ }
+}
+
static void object_hook_select(Object *ob, HookModifierData *hmd)
{
if (hmd->indexar == NULL)
@@ -491,7 +516,7 @@ static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob
mul_serie_m4(hmd->parentinv, ob->imat, obedit->obmat, NULL,
NULL, NULL, NULL, NULL, NULL);
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
return TRUE;
}
@@ -533,7 +558,7 @@ static int object_add_hook_selob_exec(bContext *C, wmOperator *op)
}
}
-void OBJECT_OT_hook_add_selobj(wmOperatorType *ot)
+void OBJECT_OT_hook_add_selob(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Hook to Selected Object";
@@ -567,7 +592,7 @@ static int object_add_hook_newob_exec(bContext *C, wmOperator *op)
}
}
-void OBJECT_OT_hook_add_newobj(wmOperatorType *ot)
+void OBJECT_OT_hook_add_newob(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Hook to New Object";
@@ -663,16 +688,9 @@ static int object_hook_reset_exec(bContext *C, wmOperator *op)
int num = RNA_enum_get(op->ptr, "modifier");
Object *ob = NULL;
HookModifierData *hmd = NULL;
-
- if (ptr.data) { /* if modifier context is available, use that */
- ob = ptr.id.data;
- hmd = ptr.data;
- }
- else { /* use the provided property */
- ob = CTX_data_edit_object(C);
- hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
- }
- if (!ob || !hmd) {
+
+ object_hook_from_context(C, &ptr, num, &ob, &hmd);
+ if (hmd == NULL) {
BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
return OPERATOR_CANCELLED;
}
@@ -732,15 +750,8 @@ static int object_hook_recenter_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
float bmat[3][3], imat[3][3];
- if (ptr.data) { /* if modifier context is available, use that */
- ob = ptr.id.data;
- hmd = ptr.data;
- }
- else { /* use the provided property */
- ob = CTX_data_edit_object(C);
- hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
- }
- if (!ob || !hmd) {
+ object_hook_from_context(C, &ptr, num, &ob, &hmd);
+ if (hmd == NULL) {
BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
return OPERATOR_CANCELLED;
}
@@ -790,15 +801,8 @@ static int object_hook_assign_exec(bContext *C, wmOperator *op)
char name[MAX_NAME];
int *indexar, tot;
- if (ptr.data) { /* if modifier context is available, use that */
- ob = ptr.id.data;
- hmd = ptr.data;
- }
- else { /* use the provided property */
- ob = CTX_data_edit_object(C);
- hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
- }
- if (!ob || !hmd) {
+ object_hook_from_context(C, &ptr, num, &ob, &hmd);
+ if (hmd == NULL) {
BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
return OPERATOR_CANCELLED;
}
@@ -852,15 +856,8 @@ static int object_hook_select_exec(bContext *C, wmOperator *op)
Object *ob = NULL;
HookModifierData *hmd = NULL;
- if (ptr.data) { /* if modifier context is available, use that */
- ob = ptr.id.data;
- hmd = ptr.data;
- }
- else { /* use the provided property */
- ob = CTX_data_edit_object(C);
- hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
- }
- if (!ob || !hmd) {
+ object_hook_from_context(C, &ptr, num, &ob, &hmd);
+ if (hmd == NULL) {
BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 0be9c92897e..e138d2fe24a 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -40,11 +40,11 @@ struct Mesh;
struct HookModifierData;
/* add hook menu */
-enum {
+enum eObject_Hook_Add_Mode {
OBJECT_ADDHOOK_NEWOB = 1,
OBJECT_ADDHOOK_SELOB,
OBJECT_ADDHOOK_SELOB_BONE
-} eObject_Hook_Add_Mode;
+};
/* internal exports only */
@@ -113,6 +113,7 @@ void OBJECT_OT_metaball_add(struct wmOperatorType *ot);
void OBJECT_OT_text_add(struct wmOperatorType *ot);
void OBJECT_OT_armature_add(struct wmOperatorType *ot);
void OBJECT_OT_empty_add(struct wmOperatorType *ot);
+void OBJECT_OT_drop_named_image(struct wmOperatorType *ot);
void OBJECT_OT_lamp_add(struct wmOperatorType *ot);
void OBJECT_OT_effector_add(struct wmOperatorType *ot);
void OBJECT_OT_camera_add(struct wmOperatorType *ot);
@@ -127,8 +128,8 @@ void OBJECT_OT_join_shapes(struct wmOperatorType *ot);
void OBJECT_OT_convert(struct wmOperatorType *ot);
/* object_hook.c */
-void OBJECT_OT_hook_add_selobj(struct wmOperatorType *ot);
-void OBJECT_OT_hook_add_newobj(struct wmOperatorType *ot);
+void OBJECT_OT_hook_add_selob(struct wmOperatorType *ot);
+void OBJECT_OT_hook_add_newob(struct wmOperatorType *ot);
void OBJECT_OT_hook_remove(struct wmOperatorType *ot);
void OBJECT_OT_hook_select(struct wmOperatorType *ot);
void OBJECT_OT_hook_assign(struct wmOperatorType *ot);
@@ -137,6 +138,7 @@ void OBJECT_OT_hook_recenter(struct wmOperatorType *ot);
/* object_lattice.c */
void LATTICE_OT_select_all(struct wmOperatorType *ot);
+void LATTICE_OT_select_ungrouped(struct wmOperatorType *ot);
void LATTICE_OT_make_regular(struct wmOperatorType *ot);
void LATTICE_OT_flip(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/object/object_lattice.c
index 4aa2e825954..9d3b2b7272d 100644
--- a/source/blender/editors/object/object_lattice.c
+++ b/source/blender/editors/object/object_lattice.c
@@ -52,7 +52,8 @@
#include "BKE_depsgraph.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
-#include "BKE_mesh.h"
+#include "BKE_deform.h"
+#include "BKE_report.h"
#include "ED_lattice.h"
#include "ED_object.h"
@@ -77,7 +78,7 @@ void free_editLatt(Object *ob)
if (editlt->def)
MEM_freeN(editlt->def);
if (editlt->dvert)
- free_dverts(editlt->dvert, editlt->pntsu * editlt->pntsv * editlt->pntsw);
+ BKE_defvert_array_free(editlt->dvert, editlt->pntsu * editlt->pntsv * editlt->pntsw);
MEM_freeN(editlt);
MEM_freeN(lt->editlatt);
@@ -104,7 +105,7 @@ void make_editLatt(Object *obedit)
if (lt->dvert) {
int tot = lt->pntsu * lt->pntsv * lt->pntsw;
lt->editlatt->latt->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
- copy_dverts(lt->editlatt->latt->dvert, lt->dvert, tot);
+ BKE_defvert_array_copy(lt->editlatt->latt->dvert, lt->dvert, tot);
}
if (lt->key) lt->editlatt->shapenr = obedit->shapenr;
@@ -156,7 +157,7 @@ void load_editLatt(Object *obedit)
}
if (lt->dvert) {
- free_dverts(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
+ BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
lt->dvert = NULL;
}
@@ -164,7 +165,7 @@ void load_editLatt(Object *obedit)
tot = lt->pntsu * lt->pntsv * lt->pntsw;
lt->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
- copy_dverts(lt->dvert, editlt->dvert, tot);
+ BKE_defvert_array_copy(lt->dvert, editlt->dvert, tot);
}
}
@@ -255,6 +256,58 @@ void LATTICE_OT_select_all(wmOperatorType *ot)
WM_operator_properties_select_all(ot);
}
+/************************** Select Ungrouped Verts Operator *************************/
+
+static int lattice_select_ungrouped_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
+ MDeformVert *dv;
+ BPoint *bp;
+ int a, tot;
+
+ if (obedit->defbase.first == NULL || lt->dvert == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No weights/vertex groups on object");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (!RNA_boolean_get(op->ptr, "extend")) {
+ ED_setflagsLatt(obedit, 0);
+ }
+
+ dv = lt->dvert;
+ tot = lt->pntsu * lt->pntsv * lt->pntsw;
+
+ for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) {
+ if (bp->hide == 0) {
+ if (dv->dw == NULL) {
+ bp->f1 |= SELECT;
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
+ return OPERATOR_FINISHED;
+}
+
+void LATTICE_OT_select_ungrouped(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Ungrouped";
+ ot->idname = "LATTICE_OT_select_ungrouped";
+ ot->description = "Select vertices without a group";
+
+ /* api callbacks */
+ ot->exec = lattice_select_ungrouped_exec;
+ ot->poll = ED_operator_editlattice;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
+}
+
/************************** Make Regular Operator *************************/
static int make_regular_poll(bContext *C)
@@ -585,7 +638,7 @@ static BPoint *findnearestLattvert(ViewContext *vc, const int mval[2], int sel)
return data.bp;
}
-int mouse_lattice(bContext *C, const int mval[2], int extend, int deselect, int toggle)
+bool mouse_lattice(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
{
ViewContext vc;
BPoint *bp = NULL;
@@ -610,10 +663,10 @@ int mouse_lattice(bContext *C, const int mval[2], int extend, int deselect, int
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/******************************** Undo *************************/
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 7d3d6861418..2239148ca1c 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -151,10 +151,10 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc
ob->pd = object_add_collision_fields(0);
ob->pd->deflect = 1;
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
}
else if (type == eModifierType_Surface)
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
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);
@@ -198,7 +198,7 @@ static int object_has_modifier(const Object *ob, const ModifierData *exclude,
* If the callback ever returns TRUE, iteration will stop and the
* function value will be TRUE. Otherwise the function returns FALSE.
*/
-int ED_object_iter_other(Main *bmain, Object *orig_ob, int include_orig,
+int ED_object_iter_other(Main *bmain, Object *orig_ob, const bool include_orig,
int (*callback)(Object *ob, void *callback_data),
void *callback_data)
{
@@ -330,7 +330,7 @@ static int object_modifier_remove(Main *bmain, Object *ob, ModifierData *md,
return 1;
}
-int ED_object_modifier_remove(ReportList *reports, Main *bmain, Scene *scene, Object *ob, ModifierData *md)
+int ED_object_modifier_remove(ReportList *reports, Main *bmain, Object *ob, ModifierData *md)
{
int sort_depsgraph = 0;
int ok;
@@ -343,15 +343,12 @@ int ED_object_modifier_remove(ReportList *reports, Main *bmain, Scene *scene, Ob
}
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
- /* sorting has to be done after the update so that dynamic systems can react properly */
- if (sort_depsgraph)
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
return 1;
}
-void ED_object_modifier_clear(Main *bmain, Scene *scene, Object *ob)
+void ED_object_modifier_clear(Main *bmain, Object *ob)
{
ModifierData *md = ob->modifiers.first;
int sort_depsgraph = 0;
@@ -370,10 +367,7 @@ void ED_object_modifier_clear(Main *bmain, Scene *scene, Object *ob)
}
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
- /* sorting has to be done after the update so that dynamic systems can react properly */
- if (sort_depsgraph)
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
}
int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md)
@@ -391,7 +385,7 @@ int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md
}
BLI_remlink(&ob->modifiers, md);
- BLI_insertlink(&ob->modifiers, md->prev->prev, md);
+ BLI_insertlinkbefore(&ob->modifiers, md->prev, md);
}
return 1;
@@ -412,7 +406,7 @@ int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData *
}
BLI_remlink(&ob->modifiers, md);
- BLI_insertlink(&ob->modifiers, md->next, md);
+ BLI_insertlinkafter(&ob->modifiers, md->next, md);
}
return 1;
@@ -522,7 +516,7 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
}
}
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
return 1;
}
@@ -728,7 +722,7 @@ int ED_object_modifier_copy(ReportList *UNUSED(reports), Object *ob, ModifierDat
nmd = modifier_new(md->type);
modifier_copyData(md, nmd);
- BLI_insertlink(&ob->modifiers, md, nmd);
+ BLI_insertlinkafter(&ob->modifiers, md, nmd);
modifier_unique_name(&ob->modifiers, nmd);
return 1;
@@ -884,7 +878,7 @@ static int modifier_remove_exec(bContext *C, wmOperator *op)
ModifierData *md = edit_modifier_property_get(op, ob, 0);
int mode_orig = ob ? ob->mode : 0;
- if (!ob || !md || !ED_object_modifier_remove(op->reports, bmain, scene, ob, md))
+ if (!ob || !md || !ED_object_modifier_remove(op->reports, bmain, ob, md))
return OPERATOR_CANCELLED;
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
@@ -898,7 +892,7 @@ static int modifier_remove_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int modifier_remove_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_modifier_invoke_properties(C, op))
return modifier_remove_exec(C, op);
@@ -937,7 +931,7 @@ static int modifier_move_up_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int modifier_move_up_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_modifier_invoke_properties(C, op))
return modifier_move_up_exec(C, op);
@@ -976,7 +970,7 @@ static int modifier_move_down_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int modifier_move_down_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_modifier_invoke_properties(C, op))
return modifier_move_down_exec(C, op);
@@ -1018,7 +1012,7 @@ static int modifier_apply_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int modifier_apply_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_modifier_invoke_properties(C, op))
return modifier_apply_exec(C, op);
@@ -1067,7 +1061,7 @@ static int modifier_convert_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int modifier_convert_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int modifier_convert_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_modifier_invoke_properties(C, op))
return modifier_convert_exec(C, op);
@@ -1106,7 +1100,7 @@ static int modifier_copy_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int modifier_copy_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_modifier_invoke_properties(C, op))
return modifier_copy_exec(C, op);
@@ -1155,7 +1149,7 @@ static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_modifier_invoke_properties(C, op))
return multires_higher_levels_delete_exec(C, op);
@@ -1196,11 +1190,16 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ if (ob->mode & OB_MODE_SCULPT) {
+ /* ensure that grid paint mask layer is created */
+ ED_sculpt_mask_layers_ensure(ob, mmd);
+ }
return OPERATOR_FINISHED;
}
-static int multires_subdivide_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int multires_subdivide_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_modifier_invoke_properties(C, op))
return multires_subdivide_exec(C, op);
@@ -1264,7 +1263,7 @@ static int multires_reshape_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int multires_reshape_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int multires_reshape_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_modifier_invoke_properties(C, op))
return multires_reshape_exec(C, op);
@@ -1315,7 +1314,7 @@ static int multires_external_save_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int multires_external_save_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int multires_external_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Object *ob = ED_object_active_context(C);
MultiresModifierData *mmd;
@@ -1411,7 +1410,7 @@ static int multires_base_apply_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int multires_base_apply_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int multires_base_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_modifier_invoke_properties(C, op))
return multires_base_apply_exec(C, op);
@@ -1755,7 +1754,7 @@ static Object *modifier_skin_armature_create(struct Scene *scene,
arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature");
mvert_skin = CustomData_get_layer(&me->vdata, CD_MVERT_SKIN);
- create_vert_edge_map(&emap, &emap_mem,
+ BKE_mesh_vert_edge_map_create(&emap, &emap_mem,
me->medge, me->totvert, me->totedge);
edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited");
@@ -1826,7 +1825,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op)
arm_md->object = arm_ob;
arm_md->deformflag = ARM_DEF_VGROUP | ARM_DEF_QUATERNION;
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
@@ -1835,7 +1834,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int skin_armature_create_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int skin_armature_create_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_modifier_invoke_properties(C, op))
return skin_armature_create_exec(C, op);
@@ -1928,7 +1927,7 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int meshdeform_bind_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int meshdeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_modifier_invoke_properties(C, op))
return meshdeform_bind_exec(C, op);
@@ -1976,7 +1975,7 @@ static int explode_refresh_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int explode_refresh_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int explode_refresh_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_modifier_invoke_properties(C, op))
return explode_refresh_exec(C, op);
@@ -2192,7 +2191,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int ocean_bake_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int ocean_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_modifier_invoke_properties(C, op))
return ocean_bake_exec(C, op);
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index d19277d20a2..594dfd6e271 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -114,6 +114,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_text_add);
WM_operatortype_append(OBJECT_OT_armature_add);
WM_operatortype_append(OBJECT_OT_empty_add);
+ WM_operatortype_append(OBJECT_OT_drop_named_image);
WM_operatortype_append(OBJECT_OT_lamp_add);
WM_operatortype_append(OBJECT_OT_camera_add);
WM_operatortype_append(OBJECT_OT_speaker_add);
@@ -210,6 +211,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_shape_key_move);
WM_operatortype_append(LATTICE_OT_select_all);
+ WM_operatortype_append(LATTICE_OT_select_ungrouped);
WM_operatortype_append(LATTICE_OT_make_regular);
WM_operatortype_append(LATTICE_OT_flip);
@@ -217,8 +219,8 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_group_link);
WM_operatortype_append(OBJECT_OT_group_remove);
- WM_operatortype_append(OBJECT_OT_hook_add_selobj);
- WM_operatortype_append(OBJECT_OT_hook_add_newobj);
+ WM_operatortype_append(OBJECT_OT_hook_add_selob);
+ WM_operatortype_append(OBJECT_OT_hook_add_newob);
WM_operatortype_append(OBJECT_OT_hook_remove);
WM_operatortype_append(OBJECT_OT_hook_select);
WM_operatortype_append(OBJECT_OT_hook_assign);
@@ -252,15 +254,6 @@ void ED_operatormacros_object(void)
RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
}
- /* XXX */
- ot = WM_operatortype_append_macro("OBJECT_OT_add_named_cursor", "Add Named At Cursor",
- "Add named object at cursor", OPTYPE_UNDO | OPTYPE_REGISTER);
- if (ot) {
- RNA_def_string(ot->srna, "name", "Cube", MAX_ID_NAME - 2, "Name", "Object name to add");
-
- WM_operatortype_macro_define(ot, "VIEW3D_OT_cursor3d");
- WM_operatortype_macro_define(ot, "OBJECT_OT_add_named");
- }
}
static int object_mode_poll(bContext *C)
@@ -372,7 +365,7 @@ void ED_keymap_object(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_delete", XKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "use_global", TRUE);
- WM_keymap_add_item(keymap, "OBJECT_OT_delete", DELKEY, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_delete", DELKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "use_global", FALSE);
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_delete", DELKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "use_global", TRUE);
@@ -403,6 +396,12 @@ void ED_keymap_object(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove_all", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL | KM_ALT, 0);
WM_keymap_verify_item(keymap, "GROUP_OT_objects_add_active", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove_active", GKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0);
+
+ kmi = WM_keymap_add_item(keymap, "RIGIDBODY_OT_objects_add", RKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_enum_set(kmi->ptr, "type", 0); /* active */
+ kmi = WM_keymap_add_item(keymap, "RIGIDBODY_OT_objects_add", RKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
+ RNA_enum_set(kmi->ptr, "type", 1); /* passive */
+ WM_keymap_add_item(keymap, "RIGIDBODY_OT_objects_remove", RKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
WM_keymap_add_menu(keymap, "VIEW3D_MT_object_specials", WKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 0988a196fb1..34a6d359f6b 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -35,6 +35,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
#include "DNA_mesh_types.h"
#include "DNA_constraint_types.h"
#include "DNA_group_types.h"
@@ -55,6 +56,8 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "BKE_action.h"
#include "BKE_animsys.h"
#include "BKE_armature.h"
@@ -212,7 +215,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
}
}
- if (v4 || !((v1 && v2 == 0 && v3 == 0) || (v1 && v2 && v3)) ) {
+ 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;
}
@@ -220,7 +223,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
if (ob != obedit) {
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
par = obedit->parent;
while (par) {
@@ -257,7 +260,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT, NULL);
@@ -283,7 +286,7 @@ void OBJECT_OT_vertex_parent_set(wmOperatorType *ot)
/********************** Make Proxy Operator *************************/
/* set the object to proxify */
-static int make_proxy_invoke(bContext *C, wmOperator *op, wmEvent *evt)
+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);
@@ -296,12 +299,12 @@ static int make_proxy_invoke(bContext *C, wmOperator *op, wmEvent *evt)
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);
- WM_enum_search_invoke(C, op, evt);
+ WM_enum_search_invoke(C, op, event);
return OPERATOR_CANCELLED;
}
else if (ob->id.lib) {
- uiPopupMenu *pup = uiPupMenuBegin(C, "OK?", ICON_QUESTION);
+ uiPopupMenu *pup = uiPupMenuBegin(C, IFACE_("OK?"), ICON_QUESTION);
uiLayout *layout = uiPupMenuLayout(pup);
/* create operator menu item with relevant properties filled in */
@@ -354,14 +357,14 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
/* remove base, leave user count of object, it gets linked in BKE_object_make_proxy */
if (gob == NULL) {
- BLI_remlink(&scene->base, oldbase);
+ 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_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
DAG_id_tag_update(&newob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, newob);
}
@@ -509,14 +512,13 @@ void ED_object_parent_clear(Object *ob, int type)
break;
}
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
/* note, poll should check for editable scene */
static int parent_clear_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
int type = RNA_enum_get(op->ptr, "type");
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
@@ -525,8 +527,7 @@ static int parent_clear_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- DAG_scene_sort(bmain, scene);
- DAG_ids_flush_update(bmain, 0);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
return OPERATOR_FINISHED;
@@ -578,6 +579,7 @@ EnumPropertyItem prop_make_parent_types[] = {
{PAR_ARMATURE_AUTO, "ARMATURE_AUTO", 0, " With Automatic Weights", ""},
{PAR_ARMATURE_ENVELOPE, "ARMATURE_ENVELOPE", 0, " With Envelope Weights", ""},
{PAR_BONE, "BONE", 0, "Bone", ""},
+ {PAR_BONE_RELATIVE, "BONE_RELATIVE", 0, "Bone Relative", ""},
{PAR_CURVE, "CURVE", 0, "Curve Deform", ""},
{PAR_FOLLOW, "FOLLOW", 0, "Follow Path", ""},
{PAR_PATH_CONST, "PATH_CONST", 0, "Path Constraint", ""},
@@ -593,7 +595,7 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
bPoseChannel *pchan = NULL;
int pararm = ELEM4(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
- par->recalc |= OB_RECALC_OB;
+ DAG_id_tag_update(&par->id, OB_RECALC_OB);
/* preconditions */
if (partype == PAR_FOLLOW || partype == PAR_PATH_CONST) {
@@ -606,8 +608,10 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
cu->flag |= CU_PATH | CU_FOLLOW;
BKE_displist_make_curveTypes(scene, par, 0); /* force creation of path data */
}
- else cu->flag |= CU_FOLLOW;
-
+ else {
+ cu->flag |= CU_FOLLOW;
+ }
+
/* if follow, add F-Curve for ctime (i.e. "eval_time") so that path-follow works */
if (partype == PAR_FOLLOW) {
/* get or create F-Curve */
@@ -624,7 +628,7 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
partype = PAR_OBJECT;
}
}
- else if (partype == PAR_BONE) {
+ else if (ELEM(partype, PAR_BONE, PAR_BONE_RELATIVE)) {
pchan = BKE_pose_channel_active(par);
if (pchan == NULL) {
@@ -705,8 +709,16 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
}
}
}
- else if (partype == PAR_BONE)
+ else if (partype == PAR_BONE) {
+ ob->partype = PARBONE; /* note, dna define, not operator property */
+ if (pchan->bone)
+ pchan->bone->flag &= ~BONE_RELATIVE_PARENTING;
+ }
+ else if (partype == PAR_BONE_RELATIVE) {
ob->partype = PARBONE; /* note, dna define, not operator property */
+ if (pchan->bone)
+ pchan->bone->flag |= BONE_RELATIVE_PARENTING;
+ }
else
ob->partype = PAROBJECT; /* note, dna define, not operator property */
@@ -716,12 +728,12 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
bFollowPathConstraint *data;
float cmat[4][4], vec[3];
- con = add_ob_constraint(ob, "AutoPath", CONSTRAINT_TYPE_FOLLOWPATH);
+ con = BKE_add_ob_constraint(ob, "AutoPath", CONSTRAINT_TYPE_FOLLOWPATH);
data = con->data;
data->tar = par;
- get_constraint_target_matrix(scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra);
+ BKE_get_constraint_target_matrix(scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra);
sub_v3_v3v3(vec, ob->obmat[3], cmat[3]);
ob->loc[0] = vec[0];
@@ -750,7 +762,7 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
invert_m4_m4(ob->parentinv, workob.obmat);
}
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
}
}
@@ -779,8 +791,7 @@ static int parent_set_exec(bContext *C, wmOperator *op)
if (!ok)
return OPERATOR_CANCELLED;
- DAG_scene_sort(bmain, scene);
- DAG_ids_flush_update(bmain, 0);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
@@ -788,10 +799,10 @@ static int parent_set_exec(bContext *C, wmOperator *op)
}
-static int parent_set_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
+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, "Set Parent To", ICON_NONE);
+ uiPopupMenu *pup = uiPupMenuBegin(C, IFACE_("Set Parent To"), ICON_NONE);
uiLayout *layout = uiPupMenuLayout(pup);
wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_parent_set", TRUE);
@@ -800,11 +811,12 @@ static int parent_set_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSE
#if 0
uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_OBJECT);
#else
- opptr = uiItemFullO_ptr(layout, ot, "Object", ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ opptr = uiItemFullO_ptr(layout, ot, IFACE_("Object"), ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "type", PAR_OBJECT);
RNA_boolean_set(&opptr, "keep_transform", FALSE);
- opptr = uiItemFullO_ptr(layout, ot, "Object (Keep Transform)", ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ opptr = uiItemFullO_ptr(layout, ot, IFACE_("Object (Keep Transform)"), ICON_NONE, NULL, WM_OP_EXEC_DEFAULT,
+ UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "type", PAR_OBJECT);
RNA_boolean_set(&opptr, "keep_transform", TRUE);
#endif
@@ -815,6 +827,7 @@ static int parent_set_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSE
uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_ENVELOPE);
uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_AUTO);
uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_BONE);
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_BONE_RELATIVE);
}
else if (ob->type == OB_CURVE) {
uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_CURVE);
@@ -830,20 +843,20 @@ static int parent_set_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSE
return OPERATOR_CANCELLED;
}
-static int parent_set_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
+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");
/* Only show XMirror for PAR_ARMATURE_ENVELOPE and PAR_ARMATURE_AUTO! */
- if (strcmp(prop_id, "xmirror") == 0) {
+ if (STREQ(prop_id, "xmirror")) {
if (ELEM(type, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO))
- return TRUE;
+ return true;
else
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
static void parent_set_ui(bContext *C, wmOperator *op)
@@ -889,7 +902,7 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
Object *par = ED_object_active_context(C);
- par->recalc |= OB_RECALC_OB;
+ DAG_id_tag_update(&par->id, OB_RECALC_OB);
/* context iterator */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
@@ -904,7 +917,7 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op)
memset(ob->loc, 0, 3 * sizeof(float));
/* set recalc flags */
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
/* set parenting type for object - object only... */
ob->parent = par;
@@ -914,8 +927,7 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- DAG_scene_sort(bmain, CTX_data_scene(C));
- DAG_ids_flush_update(bmain, 0);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
return OPERATOR_FINISHED;
@@ -941,7 +953,6 @@ void OBJECT_OT_parent_no_inverse_set(wmOperatorType *ot)
static int object_slow_parent_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
@@ -951,13 +962,12 @@ static int object_slow_parent_clear_exec(bContext *C, wmOperator *UNUSED(op))
ob->partype -= PARSLOW;
BKE_object_where_is_calc(scene, ob);
ob->partype |= PARSLOW;
- ob->recalc |= OB_RECALC_OB;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB);
}
}
}
CTX_DATA_END;
- DAG_ids_flush_update(bmain, 0);
WM_event_add_notifier(C, NC_SCENE, scene);
return OPERATOR_FINISHED;
@@ -984,7 +994,6 @@ void OBJECT_OT_slow_parent_clear(wmOperatorType *ot)
static int object_slow_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
@@ -992,12 +1001,11 @@ static int object_slow_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
if (ob->parent)
ob->partype |= PARSLOW;
- ob->recalc |= OB_RECALC_OB;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB);
}
CTX_DATA_END;
- DAG_ids_flush_update(bmain, 0);
WM_event_add_notifier(C, NC_SCENE, scene);
return OPERATOR_FINISHED;
@@ -1032,7 +1040,6 @@ static EnumPropertyItem prop_clear_track_types[] = {
static int object_track_clear_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
int type = RNA_enum_get(op->ptr, "type");
if (CTX_data_edit_object(C)) {
@@ -1045,13 +1052,13 @@ static int object_track_clear_exec(bContext *C, wmOperator *op)
/* remove track-object for old track */
ob->track = NULL;
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ 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 (ELEM3(con->type, CONSTRAINT_TYPE_TRACKTO, CONSTRAINT_TYPE_LOCKTRACK, CONSTRAINT_TYPE_DAMPTRACK))
- remove_constraint(&ob->constraints, con);
+ BKE_remove_constraint(&ob->constraints, con);
}
if (type == 1)
@@ -1059,8 +1066,7 @@ static int object_track_clear_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- DAG_ids_flush_update(bmain, 0);
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
return OPERATOR_FINISHED;
@@ -1069,7 +1075,7 @@ static int object_track_clear_exec(bContext *C, wmOperator *op)
void OBJECT_OT_track_clear(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Clear track";
+ ot->name = "Clear Track";
ot->description = "Clear tracking constraint or flag from object";
ot->idname = "OBJECT_OT_track_clear";
@@ -1097,7 +1103,6 @@ static EnumPropertyItem prop_make_track_types[] = {
static int track_set_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
Object *obact = ED_object_active_context(C);
int type = RNA_enum_get(op->ptr, "type");
@@ -1109,11 +1114,11 @@ static int track_set_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
if (ob != obact) {
- con = add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_DAMPTRACK);
+ con = BKE_add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_DAMPTRACK);
data = con->data;
data->tar = obact;
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* Lamp, Camera and Speaker track differently by default */
if (ob->type == OB_LAMP || ob->type == OB_CAMERA || ob->type == OB_SPEAKER)
@@ -1129,11 +1134,11 @@ static int track_set_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
if (ob != obact) {
- con = add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_TRACKTO);
+ con = BKE_add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_TRACKTO);
data = con->data;
data->tar = obact;
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* Lamp, Camera and Speaker track differently by default */
if (ob->type == OB_LAMP || ob->type == OB_CAMERA || ob->type == OB_SPEAKER) {
@@ -1151,11 +1156,11 @@ static int track_set_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
if (ob != obact) {
- con = add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_LOCKTRACK);
+ con = BKE_add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_LOCKTRACK);
data = con->data;
data->tar = obact;
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* Lamp, Camera and Speaker track differently by default */
if (ob->type == OB_LAMP || ob->type == OB_CAMERA || ob->type == OB_SPEAKER) {
@@ -1167,8 +1172,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
}
- DAG_scene_sort(bmain, scene);
- DAG_ids_flush_update(bmain, 0);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
return OPERATOR_FINISHED;
@@ -1225,7 +1229,7 @@ static unsigned int move_to_layer_init(bContext *C, wmOperator *op)
return lay;
}
-static int move_to_layer_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int move_to_layer_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
View3D *v3d = CTX_wm_view3d(C);
if (v3d && v3d->localvd) {
@@ -1283,7 +1287,7 @@ static int move_to_layer_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
return OPERATOR_FINISHED;
}
@@ -1346,7 +1350,6 @@ Base *ED_object_scene_link(Scene *scene, Object *ob)
static int make_links_scene_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
Scene *scene_to = BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene"));
if (scene_to == NULL) {
@@ -1370,8 +1373,6 @@ static int make_links_scene_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- DAG_ids_flush_update(bmain, 0);
-
/* redraw the 3D view because the object center points are colored differently */
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
@@ -1462,7 +1463,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
/* if amount of material indices changed: */
test_object_materials(ob_dst->data);
- ob_dst->recalc |= OB_RECALC_DATA;
+ DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
break;
case MAKE_LINKS_MATERIALS:
/* new approach, using functions from kernel */
@@ -1501,7 +1502,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
break;
case MAKE_LINKS_MODIFIERS:
BKE_object_link_modifiers(ob_dst, ob_src);
- ob_dst->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
break;
case MAKE_LINKS_FONTS:
{
@@ -1521,7 +1522,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
cu_dst->vfontbi = cu_src->vfontbi;
id_us_plus((ID *)cu_dst->vfontbi);
- ob_dst->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
break;
}
}
@@ -1540,10 +1541,10 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
}
}
- DAG_scene_sort(bmain, scene);
-
- DAG_ids_flush_update(bmain, 0);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
+ WM_event_add_notifier(C, NC_OBJECT, NULL);
+
return OPERATOR_FINISHED;
}
@@ -1692,7 +1693,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, int flag)
id = ob->data;
if (id && id->us > 1 && id->lib == NULL) {
- ob->recalc = OB_RECALC_DATA;
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
BKE_copy_animdata_id_action(id);
@@ -1728,7 +1729,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, int flag)
ob->data = BKE_lattice_copy(ob->data);
break;
case OB_ARMATURE:
- ob->recalc |= OB_RECALC_DATA;
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
ob->data = BKE_armature_copy(ob->data);
BKE_pose_rebuild(ob, ob->data);
break;
@@ -1764,7 +1765,7 @@ static void single_object_action_users(Scene *scene, int flag)
for (base = FIRSTBASE; base; base = base->next) {
ob = base->object;
if (ob->id.lib == NULL && (flag == 0 || (base->flag & SELECT)) ) {
- ob->recalc = OB_RECALC_DATA;
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
BKE_copy_animdata_id_action(&ob->id);
}
}
@@ -1930,11 +1931,11 @@ static void make_local_makelocalmaterial(Material *ma)
AnimData *adt;
int b;
- id_make_local(&ma->id, 0);
+ 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, 0);
+ id_make_local(&ma->mtex[b]->tex->id, false);
adt = BKE_animdata_from_id(&ma->id);
if (adt) BKE_animdata_make_local(adt);
@@ -1960,7 +1961,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
int a, b, mode = RNA_enum_get(op->ptr, "type");
if (mode == MAKE_LOCAL_ALL) {
- BKE_library_make_local(bmain, NULL, 0); /* NULL is all libs */
+ BKE_library_make_local(bmain, NULL, false); /* NULL is all libs */
WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_FINISHED;
}
@@ -1970,7 +1971,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
if (ob->id.lib)
- id_make_local(&ob->id, 0);
+ id_make_local(&ob->id, false);
}
CTX_DATA_END;
@@ -1988,7 +1989,7 @@ 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, 0);
+ id_make_local(id, false);
adt = BKE_animdata_from_id(id);
if (adt) BKE_animdata_make_local(adt);
@@ -2004,7 +2005,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
}
for (psys = ob->particlesystem.first; psys; psys = psys->next)
- id_make_local(&psys->part->id, 0);
+ id_make_local(&psys->part->id, false);
adt = BKE_animdata_from_id(&ob->id);
if (adt) BKE_animdata_make_local(adt);
@@ -2019,7 +2020,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
for (b = 0; b < MAX_MTEX; b++)
if (la->mtex[b] && la->mtex[b]->tex)
- id_make_local(&la->mtex[b]->tex->id, 0);
+ id_make_local(&la->mtex[b]->tex->id, false);
}
else {
for (a = 0; a < ob->totcol; a++) {
@@ -2132,9 +2133,8 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "animation", 0, "Object Animation", "Make animation data local to each object");
}
-static int drop_named_material_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Main *bmain = CTX_data_main(C);
Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
Material *ma;
char name[MAX_ID_NAME - 2];
@@ -2146,7 +2146,6 @@ static int drop_named_material_invoke(bContext *C, wmOperator *op, wmEvent *even
assign_material(base->object, ma, 1, BKE_MAT_ASSIGN_USERPREF);
- DAG_ids_flush_update(bmain, 0);
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);
@@ -2168,7 +2167,7 @@ void OBJECT_OT_drop_named_material(wmOperatorType *ot)
ot->poll = ED_operator_objectmode;
/* flags */
- ot->flag = OPTYPE_UNDO;
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
/* properties */
RNA_def_string(ot->srna, "name", "Material", MAX_ID_NAME - 2, "Name", "Material name to assign");
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 2aa737d204d..b7303b2af51 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -42,6 +42,7 @@
#include "DNA_property_types.h"
#include "DNA_scene_types.h"
#include "DNA_armature_types.h"
+#include "DNA_lamp_types.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
@@ -49,6 +50,8 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "BKE_context.h"
#include "BKE_group.h"
#include "BKE_main.h"
@@ -436,7 +439,7 @@ static int object_select_linked_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
else if (nr == OBJECT_SELECT_LINKED_OBDATA) {
- if (ob->data == 0)
+ if (ob->data == NULL)
return OPERATOR_CANCELLED;
changed = object_select_all_by_obdata(C, ob->data);
@@ -525,6 +528,8 @@ static EnumPropertyItem prop_select_grouped_types[] = {
{10, "COLOR", 0, "Color", "Object Color"},
{11, "PROPERTIES", 0, "Properties", "Game Properties"},
{12, "KEYINGSET", 0, "Keying Set", "Objects included in active Keying Set"},
+ {13, "LAMP_TYPE", 0, "Lamp Type", "Matching lamp types"},
+ {14, "PASS_INDEX", 0, "Pass Index", "Matching object pass index"},
{0, NULL, 0, NULL, NULL}
};
@@ -603,7 +608,7 @@ static short select_grouped_group(bContext *C, Object *ob) /* Select objects in
}
/* build the menu. */
- pup = uiPupMenuBegin(C, "Select Group", ICON_NONE);
+ pup = uiPupMenuBegin(C, IFACE_("Select Group"), ICON_NONE);
layout = uiPupMenuLayout(pup);
for (i = 0; i < group_count; i++) {
@@ -656,7 +661,39 @@ static short select_grouped_siblings(bContext *C, Object *ob)
CTX_DATA_END;
return changed;
}
+static short select_similar_lamps(bContext *C, Object *ob)
+{
+ Lamp *la = ob->data;
+
+ short changed = 0;
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
+ {
+ if (base->object->type == OB_LAMP) {
+ Lamp *la_test = base->object->data;
+ if ((la->type == la_test->type) && !(base->flag & SELECT)) {
+ ED_base_object_select(base, BA_SELECT);
+ changed = 1;
+ }
+ }
+ }
+ CTX_DATA_END;
+ return changed;
+}
+static short select_similar_pass_index(bContext *C, Object *ob)
+{
+ char changed = 0;
+
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
+ {
+ if ((base->object->index == ob->index) && !(base->flag & SELECT)) {
+ ED_base_object_select(base, BA_SELECT);
+ changed = 1;
+ }
+ }
+ CTX_DATA_END;
+ return changed;
+}
static short select_grouped_type(bContext *C, Object *ob)
{
short changed = 0;
@@ -803,7 +840,12 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No active object");
return OPERATOR_CANCELLED;
}
-
+
+ if (nr == 13 && ob->type != OB_LAMP) {
+ BKE_report(op->reports, RPT_ERROR, "Active object must be a lamp");
+ return OPERATOR_CANCELLED;
+ }
+
if (nr == 1) changed |= select_grouped_children(C, ob, 1);
else if (nr == 2) changed |= select_grouped_children(C, ob, 0);
else if (nr == 3) changed |= select_grouped_parent(C);
@@ -816,7 +858,9 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
else if (nr == 10) changed |= select_grouped_color(C, ob);
else if (nr == 11) changed |= select_grouped_gameprops(C, ob);
else if (nr == 12) changed |= select_grouped_keyingset(C, ob);
-
+ else if (nr == 13) changed |= select_similar_lamps(C, ob);
+ else if (nr == 14) changed |= select_similar_pass_index(C, ob);
+
if (changed) {
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
return OPERATOR_FINISHED;
@@ -850,13 +894,13 @@ void OBJECT_OT_select_grouped(wmOperatorType *ot)
static int object_select_by_layer_exec(bContext *C, wmOperator *op)
{
unsigned int layernum;
- short extend, match;
+ bool extend, match;
extend = RNA_boolean_get(op->ptr, "extend");
layernum = RNA_int_get(op->ptr, "layers");
match = RNA_enum_get(op->ptr, "match");
- if (extend == 0) {
+ if (extend == false) {
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
ED_base_object_select(base, BA_DESELECT);
@@ -866,12 +910,12 @@ static int object_select_by_layer_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
- int ok = 0;
+ bool ok = false;
- if (match == 1) /* exact */
+ if (match == true) /* exact */
ok = (base->lay == (1 << (layernum - 1)));
else /* shared layers */
- ok = (base->lay & (1 << (layernum - 1)));
+ ok = (base->lay & (1 << (layernum - 1))) != 0;
if (ok)
ED_base_object_select(base, BA_SELECT);
@@ -1028,7 +1072,7 @@ void OBJECT_OT_select_same_group(wmOperatorType *ot)
static int object_select_mirror_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- short extend;
+ bool extend;
extend = RNA_boolean_get(op->ptr, "extend");
@@ -1049,7 +1093,7 @@ static int object_select_mirror_exec(bContext *C, wmOperator *op)
}
}
- if (extend == 0) ED_base_object_select(primbase, BA_DESELECT);
+ if (extend == false) ED_base_object_select(primbase, BA_DESELECT);
}
CTX_DATA_END;
@@ -1084,11 +1128,11 @@ void OBJECT_OT_select_mirror(wmOperatorType *ot)
static int object_select_random_exec(bContext *C, wmOperator *op)
{
float percent;
- short extend;
+ bool extend;
extend = RNA_boolean_get(op->ptr, "extend");
- if (extend == 0) {
+ if (extend == false) {
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
ED_base_object_select(base, BA_DESELECT);
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 900bf57b509..80d494a6a07 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -57,6 +57,7 @@
#include "BKE_tessmesh.h"
#include "BKE_multires.h"
#include "BKE_armature.h"
+#include "BKE_lattice.h"
#include "RNA_define.h"
#include "RNA_access.h"
@@ -66,6 +67,7 @@
#include "ED_armature.h"
#include "ED_keyframing.h"
+#include "ED_mball.h"
#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_view3d.h"
@@ -211,7 +213,6 @@ static void object_clear_scale(Object *ob)
static int object_clear_transform_generic_exec(bContext *C, wmOperator *op,
void (*clear_func)(Object *), const char default_ksName[])
{
- Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
KeyingSet *ks;
@@ -242,8 +243,6 @@ static int object_clear_transform_generic_exec(bContext *C, wmOperator *op,
CTX_DATA_END;
/* this is needed so children are also updated */
- DAG_ids_flush_update(bmain, 0);
-
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
return OPERATOR_FINISHED;
@@ -316,7 +315,6 @@ void OBJECT_OT_scale_clear(wmOperatorType *ot)
static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
float *v1, *v3;
float mat[3][3];
@@ -336,8 +334,6 @@ static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op))
}
CTX_DATA_END;
- DAG_ids_flush_update(bmain, 0);
-
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
return OPERATOR_FINISHED;
@@ -406,6 +402,12 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo
change = 0;
}
}
+ else if (ob->type == OB_MBALL) {
+ if (ID_REAL_USERS(ob->data) > 1) {
+ BKE_report(reports, RPT_ERROR, "Cannot apply to a multi user metaball, doing nothing");
+ change = 0;
+ }
+ }
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
Curve *cu;
@@ -416,7 +418,7 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo
cu = ob->data;
- if (!(cu->flag & CU_3D) && (apply_rot || apply_loc)) {
+ if (((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) && (apply_rot || apply_loc)) {
BKE_report(reports, RPT_ERROR,
"Neither rotation nor location could be applied to a 2D curve, doing nothing");
change = 0;
@@ -447,7 +449,7 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo
float tmat[3][3], timat[3][3];
/* simple rotation matrix */
- BKE_object_rot_to_mat3(ob, rsmat);
+ BKE_object_rot_to_mat3(ob, rsmat, TRUE);
/* correct for scale, note mul_m3_m3m3 has swapped args! */
BKE_object_scale_to_mat3(ob, tmat);
@@ -515,6 +517,10 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo
bp++;
}
}
+ else if (ob->type == OB_MBALL) {
+ MetaBall *mb = ob->data;
+ ED_mball_transform(mb, (float *)mat);
+ }
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
Curve *cu = ob->data;
@@ -699,9 +705,11 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
}
else {
if (around == V3D_CENTROID) {
- const float total_div = 1.0f / (float)em->bm->totvert;
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- madd_v3_v3fl(cent, eve->co, total_div);
+ if (em->bm->totvert) {
+ const float total_div = 1.0f / (float)em->bm->totvert;
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ madd_v3_v3fl(cent, eve->co, total_div);
+ }
}
}
else {
@@ -787,8 +795,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
else if (centermode == ORIGIN_TO_CENTER_OF_MASS) { BKE_mesh_center_centroid(me, cent); }
- else if (around == V3D_CENTROID) { BKE_mesh_center_median(me, cent); }
- else { BKE_mesh_center_bounds(me, cent); }
+ else if (around == V3D_CENTROID) { BKE_mesh_center_median(me, cent); }
+ else { BKE_mesh_center_bounds(me, cent); }
negate_v3_v3(cent_neg, cent);
BKE_mesh_translate(me, cent_neg, 1);
@@ -800,9 +808,9 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
Curve *cu = ob->data;
- if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
+ if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
else if (around == V3D_CENTROID) { BKE_curve_center_median(cu, cent); }
- else { BKE_curve_center_bounds(cu, cent); }
+ else { BKE_curve_center_bounds(cu, cent); }
/* don't allow Z change if curve is 2D */
if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D))
@@ -863,7 +871,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
/* Function to recenter armatures in editarmature.c
* Bone + object locations are handled there.
*/
- docenter_armature(scene, ob, cursor, centermode, around);
+ ED_armature_origin_set(scene, ob, cursor, centermode, around);
tot_change++;
arm->id.flag |= LIB_DOIT;
@@ -881,9 +889,9 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
else if (ob->type == OB_MBALL) {
MetaBall *mb = ob->data;
- if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
+ if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
else if (around == V3D_CENTROID) { BKE_mball_center_median(mb, cent); }
- else { BKE_mball_center_bounds(mb, cent); }
+ else { BKE_mball_center_bounds(mb, cent); }
negate_v3_v3(cent_neg, cent);
BKE_mball_translate(mb, cent_neg);
@@ -899,6 +907,20 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
break;
}
}
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = ob->data;
+
+ if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
+ else if (around == V3D_CENTROID) { BKE_lattice_center_median(lt, cent); }
+ else { BKE_lattice_center_bounds(lt, cent); }
+
+ negate_v3_v3(cent_neg, cent);
+ BKE_lattice_translate(lt, cent_neg, 1);
+
+ tot_change++;
+ lt->id.flag |= LIB_DOIT;
+ do_inverse_offset = TRUE;
+ }
/* offset other selected objects */
if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) {
@@ -963,7 +985,6 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(&tob->id, OB_RECALC_OB | OB_RECALC_DATA);
if (tot_change) {
- DAG_ids_flush_update(bmain, 0);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
}
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 1b135c0686e..5abbb7124c0 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -65,6 +65,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -81,13 +82,14 @@ 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 int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, const short use_vert_sel);
static int vertex_group_use_vert_sel(Object *ob)
{
if (ob->mode == OB_MODE_EDIT) {
return TRUE;
}
- else if (ob->type == OB_MESH && ((Mesh *)ob->data)->editflag & ME_EDIT_VERT_SEL) {
+ else if (ob->type == OB_MESH && ((Mesh *)ob->data)->editflag & ME_EDIT_PAINT_VERT_SEL) {
return TRUE;
}
else {
@@ -182,6 +184,29 @@ int ED_vgroup_data_create(ID *id)
}
}
+/**
+ * Removes out of range MDeformWeights
+ */
+void ED_vgroup_data_clamp_range(ID *id, const int total)
+{
+ MDeformVert **dvert_arr;
+ int dvert_tot;
+
+ if (ED_vgroup_give_parray(id, &dvert_arr, &dvert_tot, false)) {
+ int i;
+ for (i = 0; i < dvert_tot; i++) {
+ MDeformVert *dv = dvert_arr[i];
+ int j;
+ for (j = 0; j < dv->totweight; j++) {
+ if (dv->dw[j].def_nr >= total) {
+ defvert_remove_group(dv, &dv->dw[j]);
+ j--;
+ }
+ }
+ }
+ }
+}
+
static int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, const short use_vert_sel)
{
*dvert_tot = 0;
@@ -400,26 +425,34 @@ typedef enum WT_ReplaceMode {
} 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"},
+ {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"},
+ {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"},
+ {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}
};
-/*copy weight*/
+/* Copy weight.*/
static void vgroup_transfer_weight(float *r_weight_dst, const float weight_src, const WT_ReplaceMode replace_mode)
{
switch (replace_mode) {
@@ -439,7 +472,9 @@ static void vgroup_transfer_weight(float *r_weight_dst, const float weight_src,
}
}
-/* could be exposed externally */
+/* 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 int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGroup *dg_src, Scene *scene,
WT_Method method, WT_ReplaceMode replace_mode, wmOperator *op)
{
@@ -457,53 +492,52 @@ static int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGrou
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);
- /* create new and overwrite vertex group on destination without data */
+ /* Ensure vertex group on target.*/
if (!defgroup_find_name(ob_dst, dg_src->name)) {
- ED_vgroup_delete(ob_dst, defgroup_find_name(ob_dst, dg_src->name));
ED_vgroup_add_name(ob_dst, dg_src->name);
}
- /* get destination deformgroup */
+ /* Get destination deformgroup.*/
dg_dst = defgroup_find_name(ob_dst, dg_src->name);
- /* get meshes */
+ /* Get meshes.*/
dmesh_src = mesh_get_derived_deform(scene, ob_src, CD_MASK_BAREMESH);
me_dst = ob_dst->data;
me_src = ob_src->data;
- /* sanity check */
+ /* Sanity check.*/
if (!me_src->dvert) {
BKE_report(op->reports, RPT_ERROR, "Transfer failed (source mesh does not have any vertex groups)");
return 0;
}
- /* create data in memory when nothing there */
+ /* Create data in memory when nothing there.*/
if (!me_dst->dvert) ED_vgroup_data_create(ob_dst->data);
- /* get vertex group arrays */
+ /* Get vertex group arrays.*/
ED_vgroup_give_parray(ob_src->data, &dv_array_src, &dv_tot_src, FALSE);
ED_vgroup_give_parray(ob_dst->data, &dv_array_dst, &dv_tot_dst, use_vert_sel);
- /* get indexes of vertex groups */
+ /* 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 */
+ /* Get vertices.*/
mv_dst = me_dst->mvert;
mv_src = dmesh_src->getVertArray(dmesh_src);
- /* prepare transformation matrix */
+ /* Prepare transformation matrix.*/
invert_m4_m4(ob_src->imat, ob_src->obmat);
mult_m4_m4m4(tmp_mat, ob_src->imat, ob_dst->obmat);
- /* clear weights */
+ /* 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 */
+ /* Remove vertex from group.*/
if (dw_dst) defvert_remove_group(*dv_dst, dw_dst);
}
}
@@ -511,7 +545,7 @@ static int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGrou
switch (method) {
case WT_BY_INDEX:
- /* check if indices are matching, delete and return if not */
+ /* 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)
{
@@ -523,14 +557,17 @@ static int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGrou
return 0;
}
- /* 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++) {
+ /* 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 */
+ /* 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);
@@ -540,29 +577,30 @@ static int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGrou
break;
case WT_BY_NEAREST_VERTEX:
- /* make node tree */
+ /* Make node tree.*/
bvhtree_from_mesh_verts(&tree_mesh_vertices_src, dmesh_src, FLT_EPSILON, 2, 6);
- /* loop trough vertices */
+ /* 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 */
+ /* Reset nearest.*/
nearest.dist = FLT_MAX;
- /* with current binary tree its marginally faster to start searching at the top, as opposed to previous search. */
+ /* It is faster to start searching at the top of the tree instead of previous search result.*/
nearest.index = -1;
- /* transform into target space */
+ /* Transform into target space.*/
mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co);
- /* node tree accelerated search for closest vetex */
+ /* 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. Existing target weights are overwritten prior to this in relevant cases. */
+ /* 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);
@@ -570,105 +608,108 @@ static int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGrou
}
}
- /* free memory */
+ /* Free memory.*/
free_bvhtree_from_mesh(&tree_mesh_vertices_src);
break;
case WT_BY_NEAREST_FACE:
- /* get faces */
+ /* Get faces.*/
DM_ensure_tessface(dmesh_src);
mface_src = dmesh_src->getTessFaceArray(dmesh_src);
- /* make node tree */
+ /* Make node tree.*/
bvhtree_from_mesh_faces(&tree_mesh_faces_src, dmesh_src, FLT_EPSILON, 2, 6);
- /* loop through the vertices */
+ /* 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 */
+ /* Reset nearest.*/
nearest.dist = FLT_MAX;
- /* with current binary tree its marginally faster to start searching at the top, as opposed to previous search. */
+ /* It is faster to start searching at the top of the tree instead of previous search result.*/
nearest.index = -1;
- /* transform into target space */
+ /* Transform into target space.*/
mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co);
- /* node tree accelerated search for closest face */
+ /* 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 */
+ /* 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*/
+ /* Interpolate weights over face.*/
f_index = mf->v4 ? 3 : 2;
if (f_index == 3) {
- interp_weights_face_v3(tmp_weight, mv_src[mf->v1].co, mv_src[mf->v2].co, mv_src[mf->v3].co, mv_src[mf->v4].co, tmp_co);
+ interp_weights_face_v3(tmp_weight, mv_src[mf->v1].co, mv_src[mf->v2].co,
+ mv_src[mf->v3].co, mv_src[mf->v4].co, tmp_co);
}
else {
- interp_weights_face_v3(tmp_weight, mv_src[mf->v1].co, mv_src[mf->v2].co, mv_src[mf->v3].co, NULL, tmp_co);
+ interp_weights_face_v3(tmp_weight, mv_src[mf->v1].co, mv_src[mf->v2].co,
+ mv_src[mf->v3].co, NULL, tmp_co);
}
- /* get weights from face*/
+ /* Get weights from face.*/
weight = 0;
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. Existing target weights are overwritten prior to this in relevant cases. */
+ /* 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) {
dw_dst = defvert_verify_index(*dv_dst, index_dst);
vgroup_transfer_weight(&dw_dst->weight, weight, replace_mode);
}
}
- /* free memory */
+ /* Free memory.*/
free_bvhtree_from_mesh(&tree_mesh_faces_src);
break;
case WT_BY_NEAREST_VERTEX_IN_FACE:
- /* get faces */
+ /* Get faces.*/
DM_ensure_tessface(dmesh_src);
mface_src = dmesh_src->getTessFaceArray(dmesh_src);
- /* make node tree */
+ /* Make node tree.*/
bvhtree_from_mesh_faces(&tree_mesh_faces_src, dmesh_src, FLT_EPSILON, 2, 6);
- /* loop through the vertices */
+ /* 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 */
+ /* Reset nearest.*/
nearest.dist = FLT_MAX;
- /* With current binary tree its marginally faster to start searching at the top, as opposed to previous search. */
+ /* It is faster to start searching at the top of the tree instead of previous search result.*/
nearest.index = -1;
- /* transform into target space */
+ /* Transform into target space.*/
mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co);
- /* node tree accelerated search for closest face */
+ /* 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 */
+ /* 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 */
+ /* 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;
@@ -680,7 +721,8 @@ static int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGrou
}
}
- /* copy weight that are not NULL including weight value 0. Existing target weights are overwritten prior to this in relevant cases. */
+ /* 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);
@@ -688,7 +730,7 @@ static int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGrou
}
}
- /* free memory */
+ /* Free memory.*/
free_bvhtree_from_mesh(&tree_mesh_faces_src);
break;
@@ -697,7 +739,7 @@ static int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGrou
break;
}
- /*free memory*/
+ /* 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);
@@ -995,7 +1037,7 @@ static void vgroup_duplicate(Object *ob)
BLI_snprintf(name, sizeof(name), "%s_copy", dg->name);
}
else {
- BLI_snprintf(name, sizeof(name), "%s", dg->name);
+ BLI_strncpy(name, dg->name, sizeof(name));
}
cdg = defgroup_duplicate(dg);
@@ -1394,7 +1436,7 @@ static void vgroup_fix(Scene *scene, Object *ob, float distToBe, float strength,
Mesh *me = ob->data;
MVert *mvert = me->mvert;
int *verts = NULL;
- if (!(me->editflag & ME_EDIT_VERT_SEL))
+ if (!(me->editflag & ME_EDIT_PAINT_VERT_SEL))
return;
for (i = 0; i < me->totvert && mvert; i++, mvert++) {
if (mvert->flag & SELECT) {
@@ -1516,16 +1558,30 @@ static void vgroup_normalize_all(Object *ob, int lock_active)
}
}
+enum {
+ VGROUP_TOGGLE,
+ VGROUP_LOCK,
+ VGROUP_UNLOCK,
+ VGROUP_INVERT
+};
+
+static EnumPropertyItem vgroup_lock_actions[] = {
+ {VGROUP_TOGGLE, "TOGGLE", 0, "Toggle", "Unlock all vertex groups if there is at least one locked group, lock all in other case"},
+ {VGROUP_LOCK, "LOCK", 0, "Lock", "Lock all vertex groups"},
+ {VGROUP_UNLOCK, "UNLOCK", 0, "Unlock", "Unlock all vertex groups"},
+ {VGROUP_INVERT, "INVERT", 0, "Invert", "Invert the lock state of all vertex groups"},
+ {0, NULL, 0, NULL, NULL}
+};
static void vgroup_lock_all(Object *ob, int action)
{
bDeformGroup *dg;
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
+ if (action == VGROUP_TOGGLE) {
+ action = VGROUP_LOCK;
for (dg = ob->defbase.first; dg; dg = dg->next) {
if (dg->flag & DG_LOCK_WEIGHT) {
- action = SEL_DESELECT;
+ action = VGROUP_UNLOCK;
break;
}
}
@@ -1533,13 +1589,13 @@ static void vgroup_lock_all(Object *ob, int action)
for (dg = ob->defbase.first; dg; dg = dg->next) {
switch (action) {
- case SEL_SELECT:
+ case VGROUP_LOCK:
dg->flag |= DG_LOCK_WEIGHT;
break;
- case SEL_DESELECT:
+ case VGROUP_UNLOCK:
dg->flag &= ~DG_LOCK_WEIGHT;
break;
- case SEL_INVERT:
+ case VGROUP_INVERT:
dg->flag ^= DG_LOCK_WEIGHT;
break;
}
@@ -2041,7 +2097,7 @@ void ED_vgroup_mirror(Object *ob, const short mirror_weights, const short flip_v
/* object mode / weight paint */
MVert *mv, *mv_mirr;
int vidx, vidx_mirr;
- const int use_vert_sel = (me->editflag & ME_EDIT_VERT_SEL) != 0;
+ const int use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
if (me->dvert == NULL) {
goto cleanup;
@@ -2544,7 +2600,7 @@ static int vertex_group_poll(bContext *C)
return (ob && !ob->id.lib && OB_TYPE_SUPPORT_VGROUP(ob->type) && data && !data->lib);
}
-static int UNUSED_FUNCTION(vertex_group_poll_edit) (bContext * C)
+static int UNUSED_FUNCTION(vertex_group_poll_edit) (bContext *C)
{
Object *ob = ED_object_context(C);
ID *data = (ob) ? ob->data : NULL;
@@ -2695,7 +2751,7 @@ void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot)
/* identifiers */
ot->name = "Remove from Vertex Group";
ot->idname = "OBJECT_OT_vertex_group_remove_from";
- ot->description = "Remove the selected vertices from the active vertex group";
+ ot->description = "Remove the selected vertices from active or all vertex group(s)";
/* api callbacks */
ot->poll = vertex_group_poll_edit_or_wpaint_vert_select;
@@ -2963,7 +3019,7 @@ void OBJECT_OT_vertex_group_lock(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_select_all(ot);
+ RNA_def_enum(ot->srna, "action", vgroup_lock_actions, VGROUP_TOGGLE, "Action", "Lock action to execute on vertex groups");
}
static int vertex_group_invert_exec(bContext *C, wmOperator *op)
@@ -3097,7 +3153,7 @@ void OBJECT_OT_vertex_group_clean(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, 1.0, "Limit", "Remove weights under this limit", 0.001f, 0.99f);
+ RNA_def_float(ot->srna, "limit", 0.0f, 0.0f, 1.0, "Limit", "Remove weights under this limit", 0.0f, 0.99f);
RNA_def_boolean(ot->srna, "all_groups", FALSE, "All Groups", "Clean all vertex groups");
RNA_def_boolean(ot->srna, "keep_single", FALSE, "Keep Single",
"Keep verts assigned to at least one group when cleaning");
@@ -3274,7 +3330,7 @@ static int vertex_group_transfer_weight_exec(bContext *C, wmOperator *op)
WT_Method method = RNA_enum_get(op->ptr, "WT_method");
WT_ReplaceMode replace_mode = RNA_enum_get(op->ptr, "WT_replace_mode");
- /* Macro to loop through selected objects and perform operation depending on function, option and method */
+ /* Macro to loop through selected objects and perform operation depending on function, option and method.*/
CTX_DATA_BEGIN (C, Object *, ob_slc, selected_editable_objects)
{
@@ -3282,8 +3338,7 @@ static int vertex_group_transfer_weight_exec(bContext *C, wmOperator *op)
switch (vertex_group_mode) {
case WT_REPLACE_ACTIVE_VERTEX_GROUP:
- if (!ed_vgroup_transfer_weight(ob_act, ob_slc,
- BLI_findlink(&ob_slc->defbase, ob_slc->actdef - 1),
+ if (!ed_vgroup_transfer_weight(ob_act, ob_slc, BLI_findlink(&ob_slc->defbase, ob_slc->actdef - 1),
scene, method, replace_mode, op))
{
fail++;
@@ -3292,9 +3347,7 @@ static int vertex_group_transfer_weight_exec(bContext *C, wmOperator *op)
case WT_REPLACE_ALL_VERTEX_GROUPS:
for (dg_src = ob_slc->defbase.first; dg_src; dg_src = dg_src->next) {
- if (!ed_vgroup_transfer_weight(ob_act, ob_slc,
- dg_src, scene, method, replace_mode, op))
- {
+ if (!ed_vgroup_transfer_weight(ob_act, ob_slc, dg_src, scene, method, replace_mode, op)) {
fail++;
}
}
@@ -3307,7 +3360,7 @@ static int vertex_group_transfer_weight_exec(bContext *C, wmOperator *op)
}
}
- /* Event notifiers for correct display of data */
+ /* Event notifiers for correct display of data.*/
DAG_id_tag_update(&ob_slc->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_slc);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob_slc->data);
@@ -3325,28 +3378,24 @@ static int vertex_group_transfer_weight_exec(bContext *C, wmOperator *op)
/* transfers weight from active to selected */
void OBJECT_OT_vertex_group_transfer_weight(wmOperatorType *ot)
{
- /* identifiers */
+ /* 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 */
+ /* API callbacks.*/
ot->poll = vertex_group_poll;
ot->exec = vertex_group_transfer_weight_exec;
- /* flags */
+ /* Flags.*/
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
+ /* Properties.*/
ot->prop = RNA_def_enum(ot->srna, "WT_vertex_group_mode", WT_vertex_group_mode_item, 1, "Group", "");
ot->prop = RNA_def_enum(ot->srna, "WT_method", WT_method_item, 3, "Method", "");
ot->prop = RNA_def_enum(ot->srna, "WT_replace_mode", WT_replace_mode_item, 1, "Replace", "");
}
-static EnumPropertyItem vgroup_items[] = {
- {0, NULL, 0, NULL, NULL}
-};
-
static int set_active_group_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
@@ -3370,7 +3419,7 @@ static EnumPropertyItem *vgroup_itemf(bContext *C, PointerRNA *UNUSED(ptr), Prop
int a, totitem = 0;
if (!ob)
- return vgroup_items;
+ return DummyRNA_NULL_items;
for (a = 0, def = ob->defbase.first; def; def = def->next, a++) {
tmp.value = a;
@@ -3404,7 +3453,7 @@ void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_enum(ot->srna, "group", vgroup_items, 0, "Group", "Vertex group to set as active");
+ prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "Vertex group to set as active");
RNA_def_enum_funcs(prop, vgroup_itemf);
ot->prop = prop;
}
diff --git a/source/blender/editors/physics/CMakeLists.txt b/source/blender/editors/physics/CMakeLists.txt
index da12a26e747..29d8aec4224 100644
--- a/source/blender/editors/physics/CMakeLists.txt
+++ b/source/blender/editors/physics/CMakeLists.txt
@@ -43,6 +43,9 @@ set(SRC
physics_fluid.c
physics_ops.c
physics_pointcache.c
+ rigidbody_constraint.c
+ rigidbody_object.c
+ rigidbody_world.c
physics_intern.h
)
@@ -59,4 +62,11 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_BULLET)
+ list(APPEND INC
+ ../../../../intern/rigidbody
+ )
+ add_definitions(-DWITH_BULLET)
+endif()
+
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 fffe05d6a0d..7916ea24bde 100644
--- a/source/blender/editors/physics/SConscript
+++ b/source/blender/editors/physics/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
@@ -7,6 +33,7 @@ incs = '../include ../../blenfont ../../blenlib ../../blenkernel ../../makesdna
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
incs += ' ../../gpu ../../blenloader ../../bmesh'
incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern'
+incs += ' #/intern/rigidbody'
defs = []
diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c
index c51b3ca4c43..aa4652af0ba 100644
--- a/source/blender/editors/physics/dynamicpaint_ops.c
+++ b/source/blender/editors/physics/dynamicpaint_ops.c
@@ -172,8 +172,8 @@ static int type_toggle_exec(bContext *C, wmOperator *op)
/* update dependency */
DAG_id_tag_update(&cObject->id, OB_RECALC_DATA);
+ DAG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, cObject);
- DAG_scene_sort(CTX_data_main(C), scene);
return OPERATOR_FINISHED;
}
@@ -202,7 +202,6 @@ void DPAINT_OT_type_toggle(wmOperatorType *ot)
static int output_toggle_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
- Scene *scene = CTX_data_scene(C);
DynamicPaintSurface *surface;
DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
int output = RNA_enum_get(op->ptr, "output"); /* currently only 1/0 */
@@ -223,9 +222,9 @@ static int output_toggle_exec(bContext *C, wmOperator *op)
/* Vertex Color Layer */
if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
if (!exists)
- ED_mesh_color_add(C, scene, ob, ob->data, name, 1);
+ ED_mesh_color_add(ob->data, name, true);
else
- ED_mesh_color_remove_named(C, ob, ob->data, name);
+ ED_mesh_color_remove_named(ob->data, name);
}
/* Vertex Weight Layer */
else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
@@ -304,7 +303,9 @@ static int dynamicPaint_bakeImageSequence(bContext *C, DynamicPaintSurface *surf
if (blender_test_break()) return 0;
/* Update progress bar cursor */
- WM_cursor_time(win, (int)progress);
+ if (!G.background) {
+ WM_cursor_time(win, (int)progress);
+ }
/* calculate a frame */
scene->r.cfra = (int)frame;
@@ -346,6 +347,7 @@ static int dynamicPaint_bakeImageSequence(bContext *C, DynamicPaintSurface *surf
*/
static int dynamicPaint_initBake(struct bContext *C, struct wmOperator *op)
{
+ wmWindow *win = CTX_wm_window(C);
DynamicPaintModifierData *pmd = NULL;
DynamicPaintCanvasSettings *canvas;
Object *ob = ED_object_context(C);
@@ -379,7 +381,9 @@ static int dynamicPaint_initBake(struct bContext *C, struct wmOperator *op)
status = dynamicPaint_bakeImageSequence(C, surface, ob);
/* Clear bake */
canvas->flags &= ~MOD_DPAINT_BAKING;
- WM_cursor_restore(CTX_wm_window(C));
+ if (!G.background) {
+ WM_cursor_restore(win);
+ }
dynamicPaint_freeSurfaceData(surface);
/* Bake was successful:
diff --git a/source/blender/editors/physics/particle_boids.c b/source/blender/editors/physics/particle_boids.c
index dc309ec3c31..8a5f623c533 100644
--- a/source/blender/editors/physics/particle_boids.c
+++ b/source/blender/editors/physics/particle_boids.c
@@ -100,7 +100,6 @@ void BOID_OT_rule_add(wmOperatorType *ot)
static int rule_del_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
ParticleSettings *part = ptr.data;
BoidRule *rule;
@@ -123,7 +122,7 @@ static int rule_del_exec(bContext *C, wmOperator *UNUSED(op))
if (rule)
rule->flag |= BOIDRULE_CURRENT;
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
return OPERATOR_FINISHED;
@@ -158,7 +157,7 @@ static int rule_move_up_exec(bContext *C, wmOperator *UNUSED(op))
for (rule = state->rules.first; rule; rule=rule->next) {
if (rule->flag & BOIDRULE_CURRENT && rule->prev) {
BLI_remlink(&state->rules, rule);
- BLI_insertlink(&state->rules, rule->prev->prev, rule);
+ BLI_insertlinkbefore(&state->rules, rule->prev, rule);
DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
break;
@@ -194,7 +193,7 @@ static int rule_move_down_exec(bContext *C, wmOperator *UNUSED(op))
for (rule = state->rules.first; rule; rule=rule->next) {
if (rule->flag & BOIDRULE_CURRENT && rule->next) {
BLI_remlink(&state->rules, rule);
- BLI_insertlink(&state->rules, rule->next, rule);
+ BLI_insertlinkafter(&state->rules, rule->next, rule);
DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
break;
@@ -254,7 +253,6 @@ void BOID_OT_state_add(wmOperatorType *ot)
static int state_del_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
ParticleSettings *part = ptr.data;
BoidState *state;
@@ -280,7 +278,7 @@ static int state_del_exec(bContext *C, wmOperator *UNUSED(op))
state->flag |= BOIDSTATE_CURRENT;
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
return OPERATOR_FINISHED;
@@ -316,7 +314,7 @@ static int state_move_up_exec(bContext *C, wmOperator *UNUSED(op))
for (state = boids->states.first; state; state=state->next) {
if (state->flag & BOIDSTATE_CURRENT && state->prev) {
BLI_remlink(&boids->states, state);
- BLI_insertlink(&boids->states, state->prev->prev, state);
+ BLI_insertlinkbefore(&boids->states, state->prev, state);
break;
}
}
@@ -351,7 +349,7 @@ static int state_move_down_exec(bContext *C, wmOperator *UNUSED(op))
for (state = boids->states.first; state; state=state->next) {
if (state->flag & BOIDSTATE_CURRENT && state->next) {
BLI_remlink(&boids->states, state);
- BLI_insertlink(&boids->states, state->next, state);
+ BLI_insertlinkafter(&boids->states, state->next, state);
DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
break;
}
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 6a56a5fdb33..e972b7d6620 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -53,10 +53,9 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_depsgraph.h"
-
#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_object.h"
#include "BKE_mesh.h"
@@ -193,6 +192,16 @@ ParticleEditSettings *PE_settings(Scene *scene)
return scene->toolsettings ? &scene->toolsettings->particle : NULL;
}
+static float pe_brush_size_get(const Scene *UNUSED(scene), ParticleBrushData *brush)
+{
+ // here we can enable unified brush size, needs more work...
+ // UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+ // float size = (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size;
+
+ return brush->size * U.pixelsize;
+}
+
+
/* always gets at least the first particlesystem even if PSYS_CURRENT flag is not set
*
* note: this function runs on poll, therefor it can runs many times a second
@@ -412,7 +421,7 @@ static int key_test_depth(PEData *data, const float co[3], const int screen_co[2
/* used to calculate here but all callers have the screen_co already, so pass as arg */
#if 0
if (ED_view3d_project_int_global(data->vc.ar, co, screen_co,
- V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN) != V3D_PROJ_RET_OK)
+ V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) != V3D_PROJ_RET_OK)
{
return 0;
}
@@ -421,15 +430,6 @@ static int key_test_depth(PEData *data, const float co[3], const int screen_co[2
gluProject(co[0], co[1], co[2], data->mats.modelview, data->mats.projection,
(GLint *)data->mats.viewport, &ux, &uy, &uz);
-#if 0 /* works well but too slow on some systems [#23118] */
- screen_co[0] += (short)data->vc.ar->winrct.xmin;
- screen_co[1] += (short)data->vc.ar->winrct.ymin;
-
- /* PE_set_view3d_data calls this. no need to call here */
- /* view3d_validate_backbuf(&data->vc); */
- glReadPixels(screen_co[0], screen_co[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
-#else /* faster to use depths, these are calculated in PE_set_view3d_data */
-
/* check if screen_co is within bounds because brush_cut uses out of screen coords */
if (screen_co[0] >= 0 && screen_co[0] < vd->w && screen_co[1] >= 0 && screen_co[1] < vd->h) {
BLI_assert(vd && vd->depths);
@@ -438,7 +438,6 @@ static int key_test_depth(PEData *data, const float co[3], const int screen_co[2
}
else
return 0;
-#endif
if ((float)uz - 0.00001f > depth)
return 0;
@@ -1103,7 +1102,7 @@ static void recalc_emitter_field(Object *ob, ParticleSystem *psys)
mul_v3_fl(vec, 0.25);
}
else
- mul_v3_fl(vec, 0.3333f);
+ mul_v3_fl(vec, 1.0f / 3.0f);
normalize_v3(nor);
@@ -1404,7 +1403,7 @@ void PARTICLE_OT_select_all(wmOperatorType *ot)
/************************ pick select operator ************************/
-int PE_mouse_particles(bContext *C, const int mval[2], int extend, int deselect, int toggle)
+int PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
{
PEData data;
Scene *scene= CTX_data_scene(C);
@@ -1546,7 +1545,7 @@ static int select_linked_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int select_linked_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
RNA_int_set_array(op->ptr, "location", event->mval);
return select_linked_exec(C, op);
@@ -1585,7 +1584,7 @@ void PE_deselect_all_visible(PTCacheEdit *edit)
}
}
-int PE_border_select(bContext *C, rcti *rect, int select, int extend)
+int PE_border_select(bContext *C, rcti *rect, bool select, bool extend)
{
Scene *scene= CTX_data_scene(C);
Object *ob= CTX_data_active_object(C);
@@ -1637,7 +1636,7 @@ int PE_circle_select(bContext *C, int selecting, const int mval[2], float rad)
/************************ lasso select operator ************************/
-int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, short extend, short select)
+int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool extend, bool select)
{
Scene *scene= CTX_data_scene(C);
Object *ob= CTX_data_active_object(C);
@@ -1995,7 +1994,7 @@ static int rekey_exec(bContext *C, wmOperator *op)
PE_set_data(C, &data);
data.dval= 1.0f / (float)(data.totrekey-1);
- data.totrekey= RNA_int_get(op->ptr, "keys");
+ data.totrekey= RNA_int_get(op->ptr, "keys_number");
foreach_selected_point(&data, rekey_particle);
@@ -2022,7 +2021,7 @@ void PARTICLE_OT_rekey(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
/* properties */
- RNA_def_int(ot->srna, "keys", 2, 2, INT_MAX, "Number of Keys", "", 2, 100);
+ RNA_def_int(ot->srna, "keys_number", 2, 2, INT_MAX, "Number of Keys", "", 2, 100);
}
static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float path_time)
@@ -2500,7 +2499,8 @@ void PARTICLE_OT_weight_set(wmOperatorType *ot)
static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata))
{
- ParticleEditSettings *pset= PE_settings(CTX_data_scene(C));
+ Scene *scene = CTX_data_scene(C);
+ ParticleEditSettings *pset= PE_settings(scene);
ParticleBrushData *brush;
if (pset->brushtype < 0)
@@ -2516,7 +2516,7 @@ static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata)
glColor4ub(255, 255, 255, 128);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- glutil_draw_lined_arc(0.0, M_PI*2.0, brush->size, 40);
+ glutil_draw_lined_arc(0.0, M_PI*2.0, pe_brush_size_get(scene, brush), 40);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
@@ -2802,7 +2802,7 @@ static void brush_cut(PEData *data, int pa_index)
if (edit->points[pa_index].flag & PEP_HIDE)
return;
- if (ED_view3d_project_int_global(ar, key->co, screen_co, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK)
+ if (ED_view3d_project_int_global(ar, key->co, screen_co, V3D_PROJ_TEST_CLIP_NEAR) != V3D_PROJ_RET_OK)
return;
rad2= data->rad * data->rad;
@@ -2827,7 +2827,7 @@ static void brush_cut(PEData *data, int pa_index)
/* calculate path time closest to root that was inside the circle */
for (k=1, key++; k<=keys; k++, key++) {
- if ((ED_view3d_project_int_global(ar, key->co, screen_co, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) ||
+ if ((ED_view3d_project_int_global(ar, key->co, screen_co, V3D_PROJ_TEST_CLIP_NEAR) != V3D_PROJ_RET_OK) ||
key_test_depth(data, key->co, screen_co) == 0)
{
x0 = (float)screen_co[0];
@@ -3244,7 +3244,7 @@ static int brush_add(PEData *data, short number)
ParticleEditSettings *pset= PE_settings(scene);
int i, k, n= 0, totpart= psys->totpart;
float mco[2];
- short dmx= 0, dmy= 0;
+ float dmx, dmy;
float co1[3], co2[3], min_d, imat[4][4];
float framestep, timestep;
short size= pset->brush[PE_BRUSH_ADD].size;
@@ -3272,12 +3272,19 @@ static int brush_add(PEData *data, short number)
for (i=0; i<number; i++) {
if (number>1) {
- dmx=dmy=size;
- while (dmx*dmx+dmy*dmy>size2) {
- dmx=(short)((2.0f*BLI_frand()-1.0f)*size);
- dmy=(short)((2.0f*BLI_frand()-1.0f)*size);
+ dmx = size;
+ dmy = size;
+
+ /* rejection sampling to get points in circle */
+ while (dmx*dmx + dmy*dmy > size2) {
+ dmx= (2.0f*BLI_frand() - 1.0f)*size;
+ dmy= (2.0f*BLI_frand() - 1.0f)*size;
}
}
+ else {
+ dmx = 0.0f;
+ dmy = 0.0f;
+ }
mco[0] = data->mval[0] + dmx;
mco[1] = data->mval[1] + dmy;
@@ -3297,8 +3304,8 @@ static int brush_add(PEData *data, short number)
int newtotpart=totpart+n;
float hairmat[4][4], cur_co[3];
KDTree *tree=0;
- ParticleData *pa, *new_pars= MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new");
- PTCacheEditPoint *point, *new_points= MEM_callocN(newtotpart*sizeof(PTCacheEditPoint), "PTCacheEditPoint array new");
+ ParticleData *pa, *new_pars = MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new");
+ PTCacheEditPoint *point, *new_points = MEM_callocN(newtotpart*sizeof(PTCacheEditPoint), "PTCacheEditPoint array new");
PTCacheEditKey *key;
HairKey *hkey;
@@ -3333,8 +3340,8 @@ static int brush_add(PEData *data, short number)
edit->totpoint= psys->totpart= newtotpart;
/* create new elements */
- pa= psys->particles + totpart;
- point= edit->points + totpart;
+ pa = psys->particles + totpart;
+ point = edit->points + totpart;
for (i=totpart; i<newtotpart; i++, pa++, point++) {
memcpy(pa, add_pars + i - totpart, sizeof(ParticleData));
@@ -3380,8 +3387,14 @@ static int brush_add(PEData *data, short number)
weight[w] = 0.0f;
}
- for (w=0; w<maxw; w++)
- weight[w] /= totw;
+ if (totw > 0.0f) {
+ for (w=0; w<maxw; w++)
+ weight[w] /= totw;
+ }
+ else {
+ for (w=0; w<maxw; w++)
+ weight[w] = 1.0f/maxw;
+ }
ppa= psys->particles+ptn[0].index;
@@ -3393,7 +3406,7 @@ static int brush_add(PEData *data, short number)
psys_get_particle_on_path(&sim, ptn[0].index, key3, 0);
mul_v3_fl(key3[0].co, weight[0]);
- /* TODO: interpolatint the weight would be nicer */
+ /* TODO: interpolating the weight would be nicer */
thkey->weight= (ppa->hair+MIN2(k, ppa->totkey-1))->weight;
if (maxw>1) {
@@ -3453,6 +3466,7 @@ typedef struct BrushEdit {
int first;
int lastmouse[2];
+ float zfac;
/* optional cached view settings to avoid setting on every mousemove */
PEData data;
@@ -3466,11 +3480,15 @@ static int brush_edit_init(bContext *C, wmOperator *op)
PTCacheEdit *edit= PE_get_current(scene, ob);
ARegion *ar= CTX_wm_region(C);
BrushEdit *bedit;
-
+ float min[3], max[3];
+
if (pset->brushtype < 0)
return 0;
- initgrabz(ar->regiondata, ob->obmat[3][0], ob->obmat[3][1], ob->obmat[3][2]);
+ /* set the 'distance factor' for grabbing (used in comb etc) */
+ INIT_MINMAX(min, max);
+ PE_minmax(scene, min, max);
+ mid_v3_v3v3(min, min, max);
bedit= MEM_callocN(sizeof(BrushEdit), "BrushEdit");
bedit->first= 1;
@@ -3480,6 +3498,8 @@ static int brush_edit_init(bContext *C, wmOperator *op)
bedit->ob= ob;
bedit->edit= edit;
+ bedit->zfac = ED_view3d_calc_zfac(ar->regiondata, min, NULL);
+
/* cache view depths and settings for re-use */
PE_set_view3d_data(C, &bedit->data);
@@ -3535,7 +3555,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
selected= (short)count_selected_keys(scene, edit);
dmax = max_ff(fabsf(dx), fabsf(dy));
- tot_steps = dmax/(0.2f * brush->size) + 1;
+ tot_steps = dmax/(0.2f * pe_brush_size_get(scene, brush)) + 1;
dx /= (float)tot_steps;
dy /= (float)tot_steps;
@@ -3549,7 +3569,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
{
const float mval_f[2] = {dx, dy};
data.mval= mval;
- data.rad= (float)brush->size;
+ data.rad= pe_brush_size_get(scene, brush);
data.combfac= (brush->strength - 0.5f) * 2.0f;
if (data.combfac < 0.0f)
@@ -3559,7 +3579,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
invert_m4_m4(ob->imat, ob->obmat);
- ED_view3d_win_to_delta(ar, mval_f, vec);
+ ED_view3d_win_to_delta(ar, mval_f, vec, bedit->zfac);
data.dvec= vec;
foreach_mouse_hit_key(&data, brush_comb, selected);
@@ -3569,7 +3589,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
{
if (edit->psys && edit->pathcache) {
data.mval= mval;
- data.rad= (float)brush->size;
+ data.rad= pe_brush_size_get(scene, brush);
data.cutfac= brush->strength;
if (selected)
@@ -3590,7 +3610,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
{
data.mval= mval;
- data.rad= (float)brush->size;
+ data.rad= pe_brush_size_get(scene, brush);
data.growfac= brush->strength / 50.0f;
if (brush->invert ^ flip)
@@ -3609,7 +3629,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
if (edit->psys) {
data.dm= psmd->dm;
data.mval= mval;
- data.rad= (float)brush->size;
+ data.rad= pe_brush_size_get(scene, brush);
data.select= selected;
data.pufffac= (brush->strength - 0.5f) * 2.0f;
@@ -3642,7 +3662,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
case PE_BRUSH_SMOOTH:
{
data.mval= mval;
- data.rad= (float)brush->size;
+ data.rad= pe_brush_size_get(scene, brush);
data.vec[0] = data.vec[1] = data.vec[2] = 0.0f;
data.tot= 0;
@@ -3665,7 +3685,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
if (edit->psys) {
data.dm= psmd->dm;
data.mval= mval;
- data.rad= (float)brush->size;
+ data.rad= pe_brush_size_get(scene, brush);
data.weightfac = brush->strength; /* note that this will never be zero */
@@ -3729,7 +3749,7 @@ static int brush_edit_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static void brush_edit_apply_event(bContext *C, wmOperator *op, wmEvent *event)
+static void brush_edit_apply_event(bContext *C, wmOperator *op, const wmEvent *event)
{
PointerRNA itemptr;
float mouse[2];
@@ -3746,7 +3766,7 @@ static void brush_edit_apply_event(bContext *C, wmOperator *op, wmEvent *event)
brush_edit_apply(C, op, &itemptr);
}
-static int brush_edit_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int brush_edit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (!brush_edit_init(C, op))
return OPERATOR_CANCELLED;
@@ -3758,7 +3778,7 @@ static int brush_edit_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static int brush_edit_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int brush_edit_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
switch (event->type) {
case LEFTMOUSE:
@@ -4123,7 +4143,7 @@ int PE_minmax(Scene *scene, float min[3], float max[3])
BKE_object_minmax(ob, min, max, TRUE);
ok= 1;
}
-
+
return ok;
}
@@ -4132,8 +4152,8 @@ int PE_minmax(Scene *scene, float min[3], float max[3])
/* initialize needed data for bake edit */
static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
{
- PTCacheEdit *edit= (psys)? psys->edit : cache->edit;
- ParticleSystemModifierData *psmd= (psys)? psys_get_modifier(ob, psys): NULL;
+ PTCacheEdit *edit;
+ ParticleSystemModifierData *psmd = (psys) ? psys_get_modifier(ob, psys) : NULL;
POINT_P; KEY_K;
ParticleData *pa = NULL;
HairKey *hkey;
@@ -4149,6 +4169,8 @@ static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache,
if (psys == NULL && (cache && cache->mem_cache.first == NULL))
return;
+ edit = (psys) ? psys->edit : cache->edit;
+
if (!edit) {
totpoint = psys ? psys->totpart : (int)((PTCacheMem *)cache->mem_cache.first)->totpoint;
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 221aad2161c..5fd2a0806e9 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -49,6 +49,7 @@
#include "BKE_main.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
+#include "BKE_report.h"
#include "RNA_access.h"
@@ -150,7 +151,6 @@ static int psys_poll(bContext *C)
static int new_particle_settings_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
Main *bmain= CTX_data_main(C);
ParticleSystem *psys;
ParticleSettings *part = NULL;
@@ -176,7 +176,7 @@ static int new_particle_settings_exec(bContext *C, wmOperator *UNUSED(op))
psys_check_boid_data(psys);
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
@@ -204,7 +204,6 @@ void PARTICLE_OT_new(wmOperatorType *ot)
static int new_particle_target_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
Object *ob = ptr.id.data;
@@ -225,7 +224,7 @@ static int new_particle_target_exec(bContext *C, wmOperator *UNUSED(op))
BLI_addtail(&psys->targets, pt);
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
@@ -250,7 +249,6 @@ void PARTICLE_OT_new_target(wmOperatorType *ot)
static int remove_particle_target_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
Object *ob = ptr.id.data;
@@ -274,7 +272,7 @@ static int remove_particle_target_exec(bContext *C, wmOperator *UNUSED(op))
if (pt)
pt->flag |= PTARGET_CURRENT;
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
@@ -312,7 +310,7 @@ static int target_move_up_exec(bContext *C, wmOperator *UNUSED(op))
for (; pt; pt=pt->next) {
if (pt->flag & PTARGET_CURRENT && pt->prev) {
BLI_remlink(&psys->targets, pt);
- BLI_insertlink(&psys->targets, pt->prev->prev, pt);
+ BLI_insertlinkbefore(&psys->targets, pt->prev, pt);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
@@ -350,7 +348,7 @@ static int target_move_down_exec(bContext *C, wmOperator *UNUSED(op))
for (; pt; pt=pt->next) {
if (pt->flag & PTARGET_CURRENT && pt->next) {
BLI_remlink(&psys->targets, pt);
- BLI_insertlink(&psys->targets, pt->next, pt);
+ BLI_insertlinkafter(&psys->targets, pt->next, pt);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
@@ -389,7 +387,7 @@ static int dupliob_move_up_exec(bContext *C, wmOperator *UNUSED(op))
for (dw=part->dupliweights.first; dw; dw=dw->next) {
if (dw->flag & PART_DUPLIW_CURRENT && dw->prev) {
BLI_remlink(&part->dupliweights, dw);
- BLI_insertlink(&part->dupliweights, dw->prev->prev, dw);
+ BLI_insertlinkbefore(&part->dupliweights, dw->prev, dw);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
break;
@@ -511,7 +509,7 @@ static int dupliob_move_down_exec(bContext *C, wmOperator *UNUSED(op))
for (dw=part->dupliweights.first; dw; dw=dw->next) {
if (dw->flag & PART_DUPLIW_CURRENT && dw->next) {
BLI_remlink(&part->dupliweights, dw);
- BLI_insertlink(&part->dupliweights, dw->next, dw);
+ BLI_insertlinkafter(&part->dupliweights, dw->next, dw);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
break;
@@ -625,7 +623,7 @@ 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 void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
+static int connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
{
ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
ParticleData *pa;
@@ -642,8 +640,8 @@ static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
float hairmat[4][4], imat[4][4];
float v[4][3], vec[3];
- if (!psys || !psys->part || psys->part->type != PART_HAIR)
- return;
+ if (!psys || !psys->part || psys->part->type != PART_HAIR || !psmd->dm)
+ return FALSE;
edit= psys->edit;
point= edit ? edit->points : NULL;
@@ -724,6 +722,8 @@ static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
psys->flag &= ~PSYS_GLOBAL_HAIR;
PE_update_object(scene, ob, 0);
+
+ return TRUE;
}
static int connect_hair_exec(bContext *C, wmOperator *op)
@@ -733,18 +733,24 @@ static int connect_hair_exec(bContext *C, wmOperator *op)
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= NULL;
int all = RNA_boolean_get(op->ptr, "all");
+ int any_connected = FALSE;
if (!ob)
return OPERATOR_CANCELLED;
if (all) {
for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- connect_hair(scene, ob, psys);
+ any_connected |= connect_hair(scene, ob, psys);
}
}
else {
psys = ptr.data;
- connect_hair(scene, ob, psys);
+ any_connected |= connect_hair(scene, ob, psys);
+ }
+
+ if (!any_connected) {
+ BKE_report(op->reports, RPT_ERROR, "Can't disconnect hair if particle system modifier is disabled");
+ return OPERATOR_CANCELLED;
}
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index 5304c64c2a9..df723b06259 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -127,7 +127,7 @@ static float get_fluid_size_m(Scene *scene, Object *domainob, FluidsimSettings *
float longest_axis;
BKE_object_dimensions_get(domainob, dim);
- longest_axis = MAX3(dim[0], dim[1], dim[2]);
+ longest_axis = max_fff(dim[0], dim[1], dim[2]);
return longest_axis * scene->unit.scale_length;
}
@@ -142,7 +142,7 @@ static int fluid_is_animated_mesh(FluidsimSettings *fss)
#if 0
/* helper function */
-void fluidsimGetGeometryObjFilename(Object *ob, char *dst) { //, char *srcname)
+void fluidsimGetGeometryObjFilename(Object *ob, char *dst) //, char *srcname)
{
//BLI_snprintf(dst, FILE_MAXFILE, "%s_cfgdata_%s.bobj.gz", srcname, ob->id.name);
BLI_snprintf(dst, FILE_MAXFILE, "fluidcfgdata_%s.bobj.gz", ob->id.name);
@@ -237,7 +237,7 @@ static void init_time(FluidsimSettings *domainSettings, FluidAnimChannels *chann
{
int i;
- channels->timeAtFrame = MEM_callocN((channels->length+1)*sizeof(float), "timeAtFrame channel");
+ channels->timeAtFrame = MEM_callocN((channels->length + 1) * sizeof(float), "timeAtFrame channel");
channels->timeAtFrame[0] = channels->timeAtFrame[1] = domainSettings->animStart; // start at index 1
@@ -267,7 +267,7 @@ static void set_vertex_channel(float *channel, float time, struct Scene *scene,
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
float *verts;
int *tris=NULL, numVerts=0, numTris=0;
- int modifierIndex = modifiers_indexInObject(ob, (ModifierData *)fluidmd);
+ int modifierIndex = BLI_findindex(&ob->modifiers, fluidmd);
int framesize = (3*fobj->numVerts) + 1;
int j;
@@ -388,7 +388,7 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid
if (fluid_is_animated_mesh(fluidmd->fss)) {
float *verts=NULL;
- int *tris=NULL, modifierIndex = modifiers_indexInObject(ob, (ModifierData *)fluidmd);
+ int *tris=NULL, modifierIndex = BLI_findindex(&ob->modifiers, (ModifierData *)fluidmd);
initElbeemMesh(scene, ob, &fobj->numVerts, &verts, &fobj->numTris, &tris, 0, modifierIndex);
fobj->VertexCache = MEM_callocN(length *((fobj->numVerts*CHANNEL_VEC)+1) * sizeof(float), "fluidobject VertexCache");
@@ -491,7 +491,7 @@ static void export_fluid_objects(ListBase *fobjects, Scene *scene, int length)
for (fobj=fobjects->first; fobj; fobj=fobj->next) {
Object *ob = fobj->object;
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
- int modifierIndex = modifiers_indexInObject(ob, (ModifierData *)fluidmd);
+ int modifierIndex = BLI_findindex(&ob->modifiers, fluidmd);
float *verts=NULL;
int *tris=NULL;
@@ -679,18 +679,15 @@ static int fluid_init_filepaths(Object *fsDomain, char *targetDir, char *targetF
if (fileCfg) {
dirExist = 1; fclose(fileCfg);
// remove cfg dummy from directory test
- BLI_delete(targetFile, 0, 0);
+ BLI_delete(targetFile, false, false);
}
if (targetDir[0] == '\0' || (!dirExist)) {
- char blendDir[FILE_MAX];
char blendFile[FILE_MAX];
// invalid dir, reset to current/previous
- BLI_strncpy(blendDir, G.main->name, FILE_MAX);
- BLI_splitdirstring(blendDir, blendFile);
+ BLI_split_file_part(G.main->name, blendFile, sizeof(blendFile));
BLI_replace_extension(blendFile, FILE_MAX, ""); /* strip .blend */
-
BLI_snprintf(newSurfdataPath, FILE_MAX, "//fluidsimdata/%s_%s_", blendFile, fsDomain->id.name);
BLI_snprintf(debugStrBuffer, 256, "fluidsimBake::error - warning resetting output dir to '%s'\n", newSurfdataPath);
@@ -852,9 +849,9 @@ static void fluidsim_delete_until_lastframe(FluidsimSettings *fss, const char *r
curFrame++;
if ((exists = BLI_exists(targetFile))) {
- BLI_delete(targetFile, 0, 0);
- BLI_delete(targetFileVel, 0, 0);
- BLI_delete(previewFile, 0, 0);
+ BLI_delete(targetFile, false, false);
+ BLI_delete(targetFileVel, false, false);
+ BLI_delete(previewFile, false, false);
}
} while (exists);
@@ -1130,7 +1127,7 @@ static int fluidsimBake(bContext *UNUSED(C), ReportList *UNUSED(reports), Object
/***************************** Operators ******************************/
-static int fluid_bake_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int fluid_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
/* only one bake job at a time */
if (WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_SIM_FLUID))
diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h
index 75779cf6102..77ce5a334e6 100644
--- a/source/blender/editors/physics/physics_intern.h
+++ b/source/blender/editors/physics/physics_intern.h
@@ -105,5 +105,23 @@ void PTCACHE_OT_bake_from_cache(struct wmOperatorType *ot);
void PTCACHE_OT_add(struct wmOperatorType *ot);
void PTCACHE_OT_remove(struct wmOperatorType *ot);
-#endif /* __PHYSICS_INTERN_H__ */
+/* rigidbody_object.c */
+void RIGIDBODY_OT_object_add(struct wmOperatorType *ot);
+void RIGIDBODY_OT_object_remove(struct wmOperatorType *ot);
+
+void RIGIDBODY_OT_objects_add(struct wmOperatorType *ot);
+void RIGIDBODY_OT_objects_remove(struct wmOperatorType *ot);
+
+void RIGIDBODY_OT_shape_change(struct wmOperatorType *ot);
+void RIGIDBODY_OT_mass_calculate(struct wmOperatorType *ot);
+/* rigidbody_constraint.c */
+void RIGIDBODY_OT_constraint_add(struct wmOperatorType *ot);
+void RIGIDBODY_OT_constraint_remove(struct wmOperatorType *ot);
+
+/*rigidbody_world.c */
+void RIGIDBODY_OT_world_add(struct wmOperatorType *ot);
+void RIGIDBODY_OT_world_remove(struct wmOperatorType *ot);
+void RIGIDBODY_OT_world_export(struct wmOperatorType *ot);
+
+#endif /* __PHYSICS_INTERN_H__ */
diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c
index fb99d296a54..2ede7047b74 100644
--- a/source/blender/editors/physics/physics_ops.c
+++ b/source/blender/editors/physics/physics_ops.c
@@ -27,9 +27,9 @@
* \ingroup edphys
*/
-
#include <stdlib.h>
+#include "BLI_utildefines.h"
#include "RNA_access.h"
@@ -39,8 +39,6 @@
#include "ED_physics.h"
#include "ED_object.h"
-#include "BLI_utildefines.h"
-
#include "physics_intern.h" // own include
@@ -86,6 +84,22 @@ static void operatortypes_particle(void)
WM_operatortype_append(PARTICLE_OT_dupliob_remove);
WM_operatortype_append(PARTICLE_OT_dupliob_move_up);
WM_operatortype_append(PARTICLE_OT_dupliob_move_down);
+
+ WM_operatortype_append(RIGIDBODY_OT_object_add);
+ WM_operatortype_append(RIGIDBODY_OT_object_remove);
+
+ WM_operatortype_append(RIGIDBODY_OT_objects_add);
+ WM_operatortype_append(RIGIDBODY_OT_objects_remove);
+
+ WM_operatortype_append(RIGIDBODY_OT_shape_change);
+ WM_operatortype_append(RIGIDBODY_OT_mass_calculate);
+
+ WM_operatortype_append(RIGIDBODY_OT_constraint_add);
+ WM_operatortype_append(RIGIDBODY_OT_constraint_remove);
+
+ WM_operatortype_append(RIGIDBODY_OT_world_add);
+ WM_operatortype_append(RIGIDBODY_OT_world_remove);
+// WM_operatortype_append(RIGIDBODY_OT_world_export);
}
static void keymap_particle(wmKeyConfig *keyconf)
diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c
index bbce94b6215..b9742c9968f 100644
--- a/source/blender/editors/physics/physics_pointcache.c
+++ b/source/blender/editors/physics/physics_pointcache.c
@@ -90,6 +90,20 @@ static void bake_console_progress_end(void *UNUSED(arg))
printf("\rbake: done!\n");
}
+static void ptcache_free_bake(PointCache *cache)
+{
+ if (cache->edit) {
+ if (!cache->edit->edited || 1) {// XXX okee("Lose changes done in particle mode?")) {
+ PE_free_ptcache_edit(cache->edit);
+ cache->edit = NULL;
+ cache->flag &= ~PTCACHE_BAKED;
+ }
+ }
+ else {
+ cache->flag &= ~PTCACHE_BAKED;
+ }
+}
+
static int ptcache_bake_all_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -139,7 +153,7 @@ static int ptcache_free_bake_all_exec(bContext *C, wmOperator *UNUSED(op))
BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
for (pid=pidlist.first; pid; pid=pid->next) {
- pid->cache->flag &= ~PTCACHE_BAKED;
+ ptcache_free_bake(pid->cache);
}
BLI_freelistN(&pidlist);
@@ -241,15 +255,7 @@ static int ptcache_free_bake_exec(bContext *C, wmOperator *UNUSED(op))
PointCache *cache= ptr.data;
Object *ob= ptr.id.data;
- if (cache->edit) {
- if (!cache->edit->edited || 1) {// XXX okee("Lose changes done in particle mode?")) {
- PE_free_ptcache_edit(cache->edit);
- cache->edit = NULL;
- cache->flag &= ~PTCACHE_BAKED;
- }
- }
- else
- cache->flag &= ~PTCACHE_BAKED;
+ ptcache_free_bake(cache);
WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
new file mode 100644
index 00000000000..b3f92d3de46
--- /dev/null
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -0,0 +1,199 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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): Sergej Reich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file rigidbody_constraint.c
+ * \ingroup editor_physics
+ * \brief Rigid Body constraint editing operators
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_group_types.h"
+#include "DNA_object_types.h"
+#include "DNA_rigidbody_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.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"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_physics.h"
+#include "ED_screen.h"
+
+#include "physics_intern.h"
+
+/* ********************************************** */
+/* Helper API's for RigidBody Constraint Editing */
+
+static int ED_operator_rigidbody_con_active_poll(bContext *C)
+{
+ if (ED_operator_object_active_editable(C)) {
+ Object *ob = CTX_data_active_object(C);
+ return (ob && ob->rigidbody_constraint);
+ }
+ else
+ return 0;
+}
+
+
+void ED_rigidbody_con_add(wmOperator *op, Scene *scene, Object *ob, int type)
+{
+ RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
+
+ /* check that object doesn't already have a constraint */
+ if (ob->rigidbody_constraint) {
+ BKE_reportf(op->reports, RPT_INFO, "Object '%s' already has a Rigid Body Constraint", ob->id.name + 2);
+ return;
+ }
+ /* create constraint group if it doesn't already exits */
+ if (rbw->constraints == NULL) {
+ rbw->constraints = add_group(G.main, "RigidBodyConstraints");
+ }
+ /* make rigidbody constraint settings */
+ ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, type);
+ ob->rigidbody_constraint->flag |= RBC_FLAG_NEEDS_VALIDATE;
+
+ /* add constraint to rigid body constraint group */
+ add_to_group(rbw->constraints, ob, scene, NULL);
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+}
+
+void ED_rigidbody_con_remove(Scene *scene, Object *ob)
+{
+ RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
+
+ BKE_rigidbody_remove_constraint(scene, ob);
+ if (rbw)
+ rem_from_group(rbw->constraints, ob, scene, NULL);
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+}
+
+/* ********************************************** */
+/* Active Object Add/Remove Operators */
+
+/* ************ Add Rigid Body Constraint ************** */
+
+static int rigidbody_con_add_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
+ Object *ob = (scene) ? OBACT : NULL;
+ int type = RNA_enum_get(op->ptr, "type");
+
+ /* sanity checks */
+ if (ELEM(NULL, scene, rbw)) {
+ BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to add Rigid Body Constraint to");
+ return OPERATOR_CANCELLED;
+ }
+ /* apply to active object */
+ ED_rigidbody_con_add(op, scene, ob, type);
+
+ /* send updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void RIGIDBODY_OT_constraint_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_constraint_add";
+ ot->name = "Add Rigid Body Constraint";
+ ot->description = "Add Rigid Body Constraint to active object";
+
+ /* callbacks */
+ ot->exec = rigidbody_con_add_exec;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_con_type_items, RBC_TYPE_FIXED, "Rigid Body Constraint Type", "");
+}
+
+/* ************ Remove Rigid Body Constraint ************** */
+
+static int rigidbody_con_remove_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = (scene) ? OBACT : NULL;
+
+ /* sanity checks */
+ if (scene == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* apply to active object */
+ if (ELEM(NULL, ob, ob->rigidbody_constraint)) {
+ BKE_report(op->reports, RPT_ERROR, "Object has no Rigid Body Constraint to remove");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ ED_rigidbody_con_remove(scene, ob);
+ }
+
+ /* send updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void RIGIDBODY_OT_constraint_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_constraint_remove";
+ ot->name = "Remove Rigid Body Constraint";
+ ot->description = "Remove Rigid Body Constraint from Object";
+
+ /* callbacks */
+ ot->exec = rigidbody_con_remove_exec;
+ ot->poll = ED_operator_rigidbody_con_active_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
new file mode 100644
index 00000000000..9c03c6173a5
--- /dev/null
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -0,0 +1,625 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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): Joshua Leung, Sergej Reich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file rigidbody_object.c
+ * \ingroup editor_physics
+ * \brief Rigid Body object editing operators
+ */
+
+#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 "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"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_physics.h"
+#include "ED_screen.h"
+
+#include "physics_intern.h"
+
+/* ********************************************** */
+/* Helper API's for RigidBody Objects Editing */
+
+static int ED_operator_rigidbody_active_poll(bContext *C)
+{
+ if (ED_operator_object_active_editable(C)) {
+ Object *ob = CTX_data_active_object(C);
+ return (ob && ob->rigidbody_object);
+ }
+ else
+ return 0;
+}
+
+static int ED_operator_rigidbody_add_poll(bContext *C)
+{
+ if (ED_operator_object_active_editable(C)) {
+ Object *ob = CTX_data_active_object(C);
+ return (ob && ob->type == OB_MESH);
+ }
+ else
+ return 0;
+}
+
+/* ----------------- */
+
+void ED_rigidbody_ob_add(wmOperator *op, Scene *scene, Object *ob, int type)
+{
+ RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
+
+ if (ob->type != OB_MESH) {
+ BKE_report(op->reports, RPT_ERROR, "Can't add Rigid Body to non mesh object");
+ return;
+ }
+ if (((Mesh *)ob->data)->totpoly == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Can't create Rigid Body from mesh with no polygons");
+ return;
+ }
+
+ /* Add rigid body world and group if they don't exist for convenience */
+ if (rbw == NULL) {
+ rbw = BKE_rigidbody_create_world(scene);
+ BKE_rigidbody_validate_sim_world(scene, rbw, false);
+ scene->rigidbody_world = rbw;
+ }
+ if (rbw->group == NULL) {
+ rbw->group = add_group(G.main, "RigidBodyWorld");
+ }
+
+ /* make rigidbody object settings */
+ if (ob->rigidbody_object == NULL) {
+ ob->rigidbody_object = BKE_rigidbody_create_object(scene, ob, type);
+ }
+ ob->rigidbody_object->type = type;
+ ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE;
+
+ /* add object to rigid body group */
+ add_to_group(rbw->group, ob, scene, NULL);
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+}
+
+void ED_rigidbody_ob_remove(Scene *scene, Object *ob)
+{
+ RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
+
+ BKE_rigidbody_remove_object(scene, ob);
+ if (rbw)
+ rem_from_group(rbw->group, ob, scene, NULL);
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+}
+
+/* ********************************************** */
+/* Active Object Add/Remove Operators */
+
+/* ************ Add Rigid Body ************** */
+
+static int rigidbody_ob_add_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = (scene) ? OBACT : NULL;
+ int type = RNA_enum_get(op->ptr, "type");
+
+ /* apply to active object */
+ ED_rigidbody_ob_add(op, scene, ob, type);
+
+ /* send updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void RIGIDBODY_OT_object_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_object_add";
+ ot->name = "Add Rigid Body";
+ ot->description = "Add active object as Rigid Body";
+
+ /* callbacks */
+ ot->exec = rigidbody_ob_add_exec;
+ ot->poll = ED_operator_rigidbody_add_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_ob_type_items, RBO_TYPE_ACTIVE, "Rigid Body Type", "");
+}
+
+/* ************ Remove Rigid Body ************** */
+
+static int rigidbody_ob_remove_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = (scene) ? OBACT : NULL;
+
+ /* sanity checks */
+ if (scene == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* apply to active object */
+ if (ELEM(NULL, ob, ob->rigidbody_object)) {
+ BKE_report(op->reports, RPT_ERROR, "Object has no Rigid Body settings to remove");
+ return OPERATOR_CANCELLED;
+ }
+ else
+ ED_rigidbody_ob_remove(scene, ob);
+
+ /* send updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void RIGIDBODY_OT_object_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_object_remove";
+ ot->name = "Remove Rigid Body";
+ ot->description = "Remove Rigid Body settings from Object";
+
+ /* callbacks */
+ ot->exec = rigidbody_ob_remove_exec;
+ ot->poll = ED_operator_rigidbody_active_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ********************************************** */
+/* Selected Object Add/Remove Operators */
+
+/* ************ Add Rigid Bodies ************** */
+
+static int rigidbody_obs_add_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ int type = RNA_enum_get(op->ptr, "type");
+
+ /* sanity check */
+ if (scene == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No Scene to add Rigid Bodies to");
+ return OPERATOR_CANCELLED;
+ }
+ /* create rigid body objects and add them to the world's group */
+ CTX_DATA_BEGIN(C, Object *, ob, selected_objects) {
+ ED_rigidbody_ob_add(op, scene, ob, type);
+ }
+ CTX_DATA_END;
+
+ /* send updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void RIGIDBODY_OT_objects_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_objects_add";
+ ot->name = "Add Rigid Bodies";
+ ot->description = "Add selected objects as Rigid Bodies";
+
+ /* callbacks */
+ ot->exec = rigidbody_obs_add_exec;
+ ot->poll = ED_operator_rigidbody_add_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_ob_type_items, RBO_TYPE_ACTIVE, "Rigid Body Type", "");
+}
+
+/* ************ Remove Rigid Bodies ************** */
+
+static int rigidbody_obs_remove_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+
+ /* sanity checks */
+ if (scene == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* apply this to all selected objects... */
+ CTX_DATA_BEGIN(C, Object *, ob, selected_objects)
+ {
+ if (ob->rigidbody_object) {
+ ED_rigidbody_ob_remove(scene, ob);
+ }
+ }
+ CTX_DATA_END;
+
+ /* send updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void RIGIDBODY_OT_objects_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_objects_remove";
+ ot->name = "Remove Rigid Bodies";
+ ot->description = "Remove selected objects from Rigid Body simulation";
+
+ /* callbacks */
+ ot->exec = rigidbody_obs_remove_exec;
+ ot->poll = ED_operator_rigidbody_active_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ********************************************** */
+/* Utility Operators */
+
+/* ************ Change Collision Shapes ************** */
+
+static int rigidbody_obs_shape_change_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ int shape = RNA_enum_get(op->ptr, "type");
+
+ /* sanity checks */
+ if (scene == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* apply this to all selected objects... */
+ CTX_DATA_BEGIN(C, Object *, ob, selected_objects)
+ {
+ if (ob->rigidbody_object) {
+ PointerRNA ptr;
+
+ /* use RNA-system to change the property and perform all necessary changes */
+ RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr);
+ RNA_enum_set(&ptr, "collision_shape", shape);
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ }
+ }
+ CTX_DATA_END;
+
+ /* send updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void RIGIDBODY_OT_shape_change(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_shape_change";
+ ot->name = "Change Collision Shape";
+ ot->description = "Change collision shapes for selected Rigid Body Objects";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = rigidbody_obs_shape_change_exec;
+ ot->poll = ED_operator_rigidbody_active_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_ob_shape_items, RB_SHAPE_TRIMESH, "Rigid Body Shape", "");
+}
+
+/* ************ Calculate Mass ************** */
+
+/* Entry in material density table */
+typedef struct rbMaterialDensityItem {
+ const char *name; /* Name of material */
+ float density; /* Density (kg/m^3) */
+} rbMaterialDensityItem;
+
+/* Preset density values for materials (kg/m^3)
+ * Selected values obtained from:
+ * 1) http://www.jaredzone.info/2010/09/densities.html
+ * 2) http://www.avlandesign.com/density_construction.htm
+ * 3) http://www.avlandesign.com/density_metal.htm
+ */
+static rbMaterialDensityItem RB_MATERIAL_DENSITY_TABLE[] = {
+ {N_("Air"), 1.0f}, /* not quite; adapted from 1.43 for oxygen for use as default */
+ {N_("Acrylic"), 1400.0f},
+ {N_("Asphalt (Crushed)"), 721.0f},
+ {N_("Bark"), 240.0f},
+ {N_("Beans (Cocoa)"), 593.0f},
+ {N_("Beans (Soy)"), 721.0f},
+ {N_("Brick (Pressed)"), 2400.0f},
+ {N_("Brick (Common)"), 2000.0f},
+ {N_("Brick (Soft)"), 1600.0f},
+ {N_("Brass"), 8216.0f},
+ {N_("Bronze"), 8860.0f},
+ {N_("Carbon (Solid)"), 2146.0f},
+ {N_("Cardboard"), 689.0f},
+ {N_("Cast Iron"), 7150.0f},
+ /* {N_("Cement"), 1442.0f}, */
+ {N_("Chalk (Solid)"), 2499.0f},
+ /* {N_("Coffee (Fresh/Roast)"), ~500}, */
+ {N_("Concrete"), 2320.0f},
+ {N_("Charcoal"), 208.0f},
+ {N_("Cork"), 240.0f},
+ {N_("Copper"), 8933.0f},
+ {N_("Garbage"), 481.0f},
+ {N_("Glass (Broken)"), 1940.0f},
+ {N_("Glass (Solid)"), 2190.0f},
+ {N_("Gold"), 19282.0f},
+ {N_("Granite (Broken)"), 1650.0f},
+ {N_("Granite (Solid)"), 2691.0f},
+ {N_("Gravel"), 2780.0f},
+ {N_("Ice (Crushed)"), 593.0f},
+ {N_("Ice (Solid)"), 919.0f},
+ {N_("Iron"), 7874.0f},
+ {N_("Lead"), 11342.0f},
+ {N_("Limestone (Broken)"), 1554.0f},
+ {N_("Limestone (Solid)"), 2611.0f},
+ {N_("Marble (Broken)"), 1570.0f},
+ {N_("Marble (Solid)"), 2563.0f},
+ {N_("Paper"), 1201.0f},
+ {N_("Peanuts (Shelled)"), 641.0f},
+ {N_("Peanuts (Not Shelled)"), 272.0f},
+ {N_("Plaster"), 849.0f},
+ {N_("Plastic"), 1200.0f},
+ {N_("Polystyrene"), 1050.0f},
+ {N_("Rubber"), 1522.0f},
+ {N_("Silver"), 10501.0f},
+ {N_("Steel"), 7860.0f},
+ {N_("Stone"), 2515.0f},
+ {N_("Stone (Crushed)"), 1602.0f},
+ {N_("Timber"), 610.0f}
+};
+static const int NUM_RB_MATERIAL_PRESETS = sizeof(RB_MATERIAL_DENSITY_TABLE) / sizeof(rbMaterialDensityItem);
+
+
+/* dynamically generate list of items
+ * - Although there is a runtime cost, this has a lower maintenance cost
+ * in the long run than other two-list solutions...
+ */
+static EnumPropertyItem *rigidbody_materials_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
+{
+ EnumPropertyItem item_tmp = {0};
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+ int i = 0;
+
+ /* add each preset to the list */
+ for (i = 0; i < NUM_RB_MATERIAL_PRESETS; i++) {
+ rbMaterialDensityItem *preset = &RB_MATERIAL_DENSITY_TABLE[i];
+
+ item_tmp.identifier = preset->name;
+ item_tmp.name = IFACE_(preset->name);
+ item_tmp.value = i;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
+
+ /* add special "custom" entry to the end of the list */
+ {
+ item_tmp.identifier = "Custom";
+ item_tmp.name = IFACE_("Custom");
+ item_tmp.value = -1;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *free = 1;
+
+ return item;
+}
+
+/* ------------------------------------------ */
+
+/* helper function to calculate volume of rigidbody object */
+// TODO: allow a parameter to specify method used to calculate this?
+static float calc_rigidbody_ob_volume(Object *ob)
+{
+ RigidBodyOb *rbo = ob->rigidbody_object;
+
+ float size[3] = {1.0f, 1.0f, 1.0f};
+ float radius = 1.0f;
+ float height = 1.0f;
+
+ float volume = 0.0f;
+
+ /* if automatically determining dimensions, use the Object's boundbox
+ * - assume that all quadrics are standing upright on local z-axis
+ * - assume even distribution of mass around the Object's pivot
+ * (i.e. Object pivot is centralised in boundbox)
+ * - boundbox gives full width
+ */
+ // XXX: all dimensions are auto-determined now... later can add stored settings for this
+ BKE_object_dimensions_get(ob, size);
+
+ if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
+ /* take radius as largest x/y dimension, and height as z-dimension */
+ radius = MAX2(size[0], size[1]) * 0.5f;
+ height = size[2];
+ }
+ else if (rbo->shape == RB_SHAPE_SPHERE) {
+ /* take radius to the the largest dimension to try and encompass everything */
+ radius = max_fff(size[0], size[1], size[2]) * 0.5f;
+ }
+
+ /* calculate volume as appropriate */
+ switch (rbo->shape) {
+ case RB_SHAPE_BOX:
+ volume = size[0] * size[1] * size[2];
+ break;
+
+ case RB_SHAPE_SPHERE:
+ volume = 4.0f / 3.0f * (float)M_PI * radius * radius * radius;
+ break;
+
+ /* for now, assume that capsule is close enough to a cylinder... */
+ case RB_SHAPE_CAPSULE:
+ case RB_SHAPE_CYLINDER:
+ volume = (float)M_PI * radius * radius * height;
+ break;
+
+ case RB_SHAPE_CONE:
+ volume = (float)M_PI / 3.0f * radius * radius * height;
+ break;
+
+ /* for now, all mesh shapes are just treated as boxes...
+ * NOTE: this may overestimate the volume, but other methods are overkill
+ */
+ case RB_SHAPE_CONVEXH:
+ case RB_SHAPE_TRIMESH:
+ volume = size[0] * size[1] * size[2];
+ break;
+
+#if 0 // XXX: not defined yet
+ case RB_SHAPE_COMPOUND:
+ volume = 0.0f;
+ break;
+#endif
+ }
+
+ /* return the volume calculated */
+ return volume;
+}
+
+/* ------------------------------------------ */
+
+static int rigidbody_obs_calc_mass_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ int material = RNA_enum_get(op->ptr, "material");
+ float density;
+
+ /* sanity checks */
+ if (scene == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* get density (kg/m^3) to apply */
+ if (material >= 0) {
+ /* get density from table, and store in props for later repeating */
+ if (material >= NUM_RB_MATERIAL_PRESETS)
+ material = 0;
+
+ density = RB_MATERIAL_DENSITY_TABLE[material].density;
+ RNA_float_set(op->ptr, "density", density);
+ }
+ else {
+ /* custom - grab from whatever value is set */
+ density = RNA_float_get(op->ptr, "density");
+ }
+
+ /* apply this to all selected objects (with rigidbodies)... */
+ CTX_DATA_BEGIN(C, Object *, ob, selected_objects)
+ {
+ if (ob->rigidbody_object) {
+ PointerRNA ptr;
+
+ float volume; /* m^3 */
+ float mass; /* kg */
+
+ /* mass is calculated from the approximate volume of the object,
+ * and the density of the material we're simulating
+ */
+ volume = calc_rigidbody_ob_volume(ob);
+ mass = volume * density;
+
+ /* use RNA-system to change the property and perform all necessary changes */
+ RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr);
+ RNA_float_set(&ptr, "mass", mass);
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ }
+ }
+ CTX_DATA_END;
+
+ /* send updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void RIGIDBODY_OT_mass_calculate(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_mass_calculate";
+ ot->name = "Calculate Mass";
+ ot->description = "Automatically calculate mass values for Rigid Body Objects based on volume";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke; // XXX
+ ot->exec = rigidbody_obs_calc_mass_exec;
+ ot->poll = ED_operator_rigidbody_active_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = prop = RNA_def_enum(ot->srna, "material",
+ DummyRNA_DEFAULT_items, 0,
+ "Material Preset",
+ "Type of material that objects are made of (determines material density)");
+ RNA_def_enum_funcs(prop, rigidbody_materials_itemf);
+
+ RNA_def_float(ot->srna, "density", 1.0, FLT_MIN, FLT_MAX,
+ "Density",
+ "Custom density value (kg/m^3) to use instead of material preset",
+ 1.0f, 2500.0f);
+}
+
+/* ********************************************** */
diff --git a/source/blender/editors/physics/rigidbody_world.c b/source/blender/editors/physics/rigidbody_world.c
new file mode 100644
index 00000000000..b7430cb8a95
--- /dev/null
+++ b/source/blender/editors/physics/rigidbody_world.c
@@ -0,0 +1,210 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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): Joshua Leung, Sergej Reich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file rigidbody_world.c
+ * \ingroup editor_physics
+ * \brief Rigid Body world editing operators
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "DNA_object_types.h"
+#include "DNA_rigidbody_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+
+#ifdef WITH_BULLET
+# include "RBI_api.h"
+#endif
+
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_group.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+#include "BKE_rigidbody.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_physics.h"
+#include "ED_screen.h"
+
+#include "physics_intern.h"
+
+/* ********************************************** */
+/* API */
+
+/* check if there is an active rigid body world */
+static int ED_rigidbody_world_active_poll(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ return (scene && scene->rigidbody_world);
+}
+static int ED_rigidbody_world_add_poll(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ return (scene && scene->rigidbody_world == NULL);
+}
+
+/* ********************************************** */
+/* OPERATORS - Management */
+
+/* ********** Add RigidBody World **************** */
+
+static int rigidbody_world_add_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ RigidBodyWorld *rbw;
+
+ rbw = BKE_rigidbody_create_world(scene);
+// BKE_rigidbody_validate_sim_world(scene, rbw, false);
+ scene->rigidbody_world = rbw;
+
+ return OPERATOR_FINISHED;
+}
+
+void RIGIDBODY_OT_world_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_world_add";
+ ot->name = "Add Rigid Body World";
+ ot->description = "Add Rigid Body simulation world to the current scene";
+
+ /* callbacks */
+ ot->exec = rigidbody_world_add_exec;
+ ot->poll = ED_rigidbody_world_add_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ********** Remove RigidBody World ************* */
+
+static int rigidbody_world_remove_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ RigidBodyWorld *rbw = scene->rigidbody_world;
+
+ /* sanity checks */
+ if (ELEM(NULL, scene, rbw)) {
+ BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to remove");
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_rigidbody_free_world(rbw);
+ scene->rigidbody_world = NULL;
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void RIGIDBODY_OT_world_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_world_remove";
+ ot->name = "Remove Rigid Body World";
+ ot->description = "Remove Rigid Body simulation world from the current scene";
+
+ /* callbacks */
+ ot->exec = rigidbody_world_remove_exec;
+ ot->poll = ED_rigidbody_world_active_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ********************************************** */
+/* UTILITY OPERATORS */
+
+/* ********** Export RigidBody World ************* */
+
+static int rigidbody_world_export_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ RigidBodyWorld *rbw = scene->rigidbody_world;
+ char path[FILE_MAX];
+
+ /* sanity checks */
+ if ELEM(NULL, scene, rbw) {
+ BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to export");
+ return OPERATOR_CANCELLED;
+ }
+ if (rbw->physics_world == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Rigid Body World has no associated physics data to export");
+ return OPERATOR_CANCELLED;
+ }
+
+ RNA_string_get(op->ptr, "filepath", path);
+#ifdef WITH_BULLET
+ RB_dworld_export(rbw->physics_world, path);
+#endif
+ return OPERATOR_FINISHED;
+}
+
+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));
+
+ if (RNA_struct_property_is_set(op->ptr, "filepath"))
+ return rigidbody_world_export_exec(C, op);
+
+ // TODO: use the actual rigidbody world's name + .bullet instead of this temp crap
+ RNA_string_set(op->ptr, "filepath", "rigidbodyworld_export.bullet");
+ WM_event_add_fileselect(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void RIGIDBODY_OT_world_export(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->idname = "RIGIDBODY_OT_world_export";
+ ot->name = "Export Rigid Body World";
+ ot->description = "Export Rigid Body world to simulator's own fileformat (i.e. '.bullet' for Bullet Physics)";
+
+ /* callbacks */
+ ot->invoke = rigidbody_world_export_invoke;
+ ot->exec = rigidbody_world_export_exec;
+ ot->poll = ED_rigidbody_world_active_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_filesel(ot, FOLDERFILE, FILE_SPECIAL, FILE_SAVE, FILE_RELPATH, FILE_DEFAULTDISPLAY);
+}
diff --git a/source/blender/editors/render/CMakeLists.txt b/source/blender/editors/render/CMakeLists.txt
index 3c5fd0b4ef7..b858d715cfe 100644
--- a/source/blender/editors/render/CMakeLists.txt
+++ b/source/blender/editors/render/CMakeLists.txt
@@ -68,4 +68,11 @@ if(WITH_HEADLESS)
add_definitions(-DWITH_HEADLESS)
endif()
+if(WITH_FREESTYLE)
+ list(APPEND INC
+ ../../freestyle
+ )
+ add_definitions(-DWITH_FREESTYLE)
+endif()
+
blender_add_lib(bf_editor_render "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/render/SConscript b/source/blender/editors/render/SConscript
index 0b19ecdab8e..25af8080d51 100644
--- a/source/blender/editors/render/SConscript
+++ b/source/blender/editors/render/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
@@ -7,7 +33,7 @@ incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
incs += ' ../../gpu'
incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern'
-incs += ' ../../blenloader ../../bmesh'
+incs += ' ../../blenloader ../../bmesh ../../blenfont'
if env['OURPLATFORM'] == 'linux':
cflags='-pthread'
@@ -16,6 +42,9 @@ if env['OURPLATFORM'] == 'linux':
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
+if env['WITH_BF_FREESTYLE']:
+ incs += ' ../../freestyle'
+ env.Append(CFLAGS=['-DWITH_FREESTYLE'])
if env['WITH_BF_QUICKTIME']:
incs += ' ../../quicktime'
diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h
index 18ba2b5abf9..88c00601933 100644
--- a/source/blender/editors/render/render_intern.h
+++ b/source/blender/editors/render/render_intern.h
@@ -54,6 +54,25 @@ 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);
+#ifdef WITH_FREESTYLE
+void SCENE_OT_freestyle_module_add(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_module_remove(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_module_move(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_lineset_add(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_lineset_copy(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_lineset_paste(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_lineset_remove(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_lineset_move(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_linestyle_new(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_color_modifier_add(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_alpha_modifier_add(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_thickness_modifier_add(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_geometry_modifier_add(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_modifier_remove(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_modifier_move(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_modifier_copy(struct wmOperatorType *ot);
+#endif
+
void TEXTURE_OT_slot_copy(struct wmOperatorType *ot);
void TEXTURE_OT_slot_paste(struct wmOperatorType *ot);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index f8154f4abda..1268d577f44 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -39,6 +39,8 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "DNA_scene_types.h"
#include "BKE_blender.h"
@@ -73,6 +75,7 @@
#include "render_intern.h"
/* Render Callbacks */
+static int render_break(void *rjv);
/* called inside thread! */
void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volatile rcti *renrect)
@@ -210,7 +213,7 @@ static int screen_render_exec(bContext *C, wmOperator *op)
lay = (v3d) ? v3d->lay : scene->lay;
G.is_break = FALSE;
- RE_test_break_cb(re, NULL, (int (*)(void *))blender_test_break);
+ RE_test_break_cb(re, NULL, render_break);
ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
@@ -280,38 +283,39 @@ static void make_renderinfo_string(RenderStats *rs, Scene *scene, char *str)
megs_peak_memory = (peak_memory) / (1024.0 * 1024.0);
if (scene->lay & 0xFF000000)
- spos += sprintf(spos, "Localview | ");
+ spos += sprintf(spos, IFACE_("Localview | "));
else if (scene->r.scemode & R_SINGLE_LAYER)
- spos += sprintf(spos, "Single Layer | ");
+ spos += sprintf(spos, IFACE_("Single Layer | "));
- spos += sprintf(spos, "Frame:%d ", (scene->r.cfra));
+ spos += sprintf(spos, IFACE_("Frame:%d "), (scene->r.cfra));
if (rs->statstr) {
spos += sprintf(spos, "| %s ", rs->statstr);
}
else {
- if (rs->totvert) spos += sprintf(spos, "Ve:%d ", rs->totvert);
- if (rs->totface) spos += sprintf(spos, "Fa:%d ", rs->totface);
- if (rs->tothalo) spos += sprintf(spos, "Ha:%d ", rs->tothalo);
- if (rs->totstrand) spos += sprintf(spos, "St:%d ", rs->totstrand);
- if (rs->totlamp) spos += sprintf(spos, "La:%d ", rs->totlamp);
+ if (rs->totvert) spos += sprintf(spos, IFACE_("Ve:%d "), rs->totvert);
+ if (rs->totface) spos += sprintf(spos, IFACE_("Fa:%d "), rs->totface);
+ if (rs->tothalo) spos += sprintf(spos, IFACE_("Ha:%d "), rs->tothalo);
+ if (rs->totstrand) spos += sprintf(spos, IFACE_("St:%d "), rs->totstrand);
+ if (rs->totlamp) spos += sprintf(spos, IFACE_("La:%d "), rs->totlamp);
if (rs->mem_peak == 0.0f)
- spos += sprintf(spos, "Mem:%.2fM (%.2fM, peak %.2fM) ", megs_used_memory, mmap_used_memory, megs_peak_memory);
+ spos += sprintf(spos, IFACE_("Mem:%.2fM (%.2fM, Peak %.2fM) "),
+ megs_used_memory, mmap_used_memory, megs_peak_memory);
else
- spos += sprintf(spos, "Mem:%.2fM, Peak: %.2fM ", rs->mem_used, rs->mem_peak);
+ spos += sprintf(spos, IFACE_("Mem:%.2fM, Peak: %.2fM "), rs->mem_used, rs->mem_peak);
if (rs->curfield)
- spos += sprintf(spos, "Field %d ", rs->curfield);
+ spos += sprintf(spos, IFACE_("Field %d "), rs->curfield);
if (rs->curblur)
- spos += sprintf(spos, "Blur %d ", rs->curblur);
+ spos += sprintf(spos, IFACE_("Blur %d "), rs->curblur);
}
BLI_timestr(rs->lastframetime, info_time_str);
- spos += sprintf(spos, "Time:%s ", info_time_str);
+ spos += sprintf(spos, IFACE_("Time:%s "), info_time_str);
if (rs->curfsa)
- spos += sprintf(spos, "| Full Sample %d ", rs->curfsa);
+ spos += sprintf(spos, IFACE_("| Full Sample %d "), rs->curfsa);
if (rs->infostr && rs->infostr[0])
spos += sprintf(spos, "| %s ", rs->infostr);
@@ -443,6 +447,15 @@ static int render_breakjob(void *rjv)
return 0;
}
+/* for exec() when there is no render job
+ * note: this wont check for the escape key being pressed, but doing so isnt threadsafe */
+static int render_break(void *UNUSED(rjv))
+{
+ if (G.is_break)
+ return 1;
+ return 0;
+}
+
/* runs in thread, no cursor setting here works. careful with notifiers too (malloc conflicts) */
/* maybe need a way to get job send notifer? */
static void render_drawlock(void *UNUSED(rjv), int lock)
@@ -452,7 +465,7 @@ static void render_drawlock(void *UNUSED(rjv), int lock)
}
/* catch esc */
-static int screen_render_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int screen_render_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
Scene *scene = (Scene *) op->customdata;
@@ -471,7 +484,7 @@ static int screen_render_modal(bContext *C, wmOperator *op, wmEvent *event)
}
/* using context, starts job */
-static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
/* new render clears all callbacks */
Main *mainp;
@@ -529,7 +542,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
BKE_sequencer_cache_cleanup();
/* get editmode results */
- ED_object_exit_editmode(C, 0); /* 0 = does not exit editmode */
+ ED_object_editmode_load(CTX_data_edit_object(C));
// store spare
// get view3d layer, local layer, make this nice api call to render
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 73f8abdf15f..f47d737beca 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -43,6 +43,7 @@
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
+#include "DNA_world_types.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -192,7 +193,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
}
if ((scene->r.mode & R_OSA) == 0) {
- ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE, FALSE);
+ ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE);
GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, rr->rectf);
}
else {
@@ -206,7 +207,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
BLI_jitter_init(jit_ofs[0], scene->r.osa);
/* first sample buffer, also initializes 'rv3d->persmat' */
- ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE, FALSE);
+ ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE);
GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, accum_buffer);
/* skip the first sample */
@@ -216,7 +217,7 @@ 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, TRUE, FALSE);
+ ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, TRUE);
GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, accum_tmp);
add_vn_vn(accum_buffer, accum_tmp, sizex * sizey * sizeof(float));
}
@@ -232,7 +233,8 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
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_rectfloat, OB_SOLID, TRUE, FALSE, err_out);
+ ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey,
+ IB_rectfloat, OB_SOLID, FALSE, TRUE, R_ALPHAPREMUL, err_out);
camera = scene->camera;
if (ibuf_view) {
@@ -243,7 +245,13 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
fprintf(stderr, "%s: failed to get buffer, %s\n", __func__, err_out);
}
}
-
+
+ if (scene->r.alphamode == R_ADDSKY) {
+ float sky_color[3];
+ ED_view3d_offscreen_sky_color_get(scene, sky_color);
+ IMB_alpha_under_color_float(rr->rectf, sizex, sizey, sky_color);
+ }
+
/* note on color management:
*
* OpenGL renders into sRGB colors, but render buffers are expected to be
@@ -256,7 +264,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
/* sequencer has got tricker ocnversion happened above */
IMB_buffer_float_from_float(rr->rectf, rr->rectf,
- 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, FALSE,
+ 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, TRUE,
oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex);
}
@@ -281,7 +289,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
IMB_color_to_bw(ibuf);
}
- BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, scene->r.im_format.imtype, scene->r.scemode & R_EXTENSION, FALSE);
+ BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, 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);
@@ -505,7 +513,7 @@ static int 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.imtype, scene->r.scemode & R_EXTENSION, TRUE);
+ BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, TRUE);
if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) {
printf("skipping existing frame \"%s\"\n", name);
@@ -630,7 +638,7 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op)
}
-static int screen_opengl_render_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int screen_opengl_render_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
OGLRender *oglrender = op->customdata;
int anim = RNA_boolean_get(op->ptr, "animation");
@@ -669,7 +677,7 @@ static int screen_opengl_render_modal(bContext *C, wmOperator *op, wmEvent *even
return OPERATOR_RUNNING_MODAL;
}
-static int screen_opengl_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int screen_opengl_render_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
OGLRender *oglrender;
int anim = RNA_boolean_get(op->ptr, "animation");
diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c
index c9e6dc90515..7c52b7d0d39 100644
--- a/source/blender/editors/render/render_ops.c
+++ b/source/blender/editors/render/render_ops.c
@@ -27,14 +27,14 @@
* \ingroup edrend
*/
-
#include <stdlib.h>
-
-#include "WM_api.h"
+#include "BLI_utildefines.h"
#include "ED_render.h"
+#include "WM_api.h"
+
#include "render_intern.h" // own include
#if (defined(WITH_QUICKTIME) && !defined(USE_QTKIT))
@@ -62,6 +62,25 @@ void ED_operatortypes_render(void)
WM_operatortype_append(SCENE_OT_render_layer_add);
WM_operatortype_append(SCENE_OT_render_layer_remove);
+#ifdef WITH_FREESTYLE
+ WM_operatortype_append(SCENE_OT_freestyle_module_add);
+ WM_operatortype_append(SCENE_OT_freestyle_module_remove);
+ WM_operatortype_append(SCENE_OT_freestyle_module_move);
+ WM_operatortype_append(SCENE_OT_freestyle_lineset_add);
+ WM_operatortype_append(SCENE_OT_freestyle_lineset_copy);
+ WM_operatortype_append(SCENE_OT_freestyle_lineset_paste);
+ WM_operatortype_append(SCENE_OT_freestyle_lineset_remove);
+ WM_operatortype_append(SCENE_OT_freestyle_lineset_move);
+ WM_operatortype_append(SCENE_OT_freestyle_linestyle_new);
+ WM_operatortype_append(SCENE_OT_freestyle_color_modifier_add);
+ WM_operatortype_append(SCENE_OT_freestyle_alpha_modifier_add);
+ WM_operatortype_append(SCENE_OT_freestyle_thickness_modifier_add);
+ WM_operatortype_append(SCENE_OT_freestyle_geometry_modifier_add);
+ WM_operatortype_append(SCENE_OT_freestyle_modifier_remove);
+ WM_operatortype_append(SCENE_OT_freestyle_modifier_move);
+ WM_operatortype_append(SCENE_OT_freestyle_modifier_copy);
+#endif
+
#if (defined(WITH_QUICKTIME) && !defined(USE_QTKIT))
WM_operatortype_append(SCENE_OT_render_data_set_quicktime_codec);
#endif
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index a864fe306b3..b851dc3be94 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -84,6 +84,8 @@
#include "IMB_imbuf_types.h"
#include "IMB_colormanagement.h"
+#include "GPU_extensions.h"
+
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -95,6 +97,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_datafiles.h"
#include "ED_render.h"
#include "ED_view3d.h"
@@ -107,7 +110,7 @@ ImBuf *get_brush_icon(Brush *brush)
static const int flags = IB_rect | IB_multilayer | IB_metadata;
char path[FILE_MAX];
- char *folder;
+ const char *folder;
if (!(brush->icon_imbuf)) {
if (brush->flag & BRUSH_CUSTOM_ICON) {
@@ -166,7 +169,8 @@ typedef struct ShaderPreview {
int sizex, sizey;
unsigned int *pr_rect;
int pr_method;
-
+
+ Main *pr_main;
} ShaderPreview;
typedef struct IconPreviewSize {
@@ -184,31 +188,44 @@ typedef struct IconPreview {
/* *************************** Preview for buttons *********************** */
-static Main *pr_main = NULL;
+static Main *G_pr_main = NULL;
+static Main *G_pr_main_cycles = NULL;
-void ED_preview_init_dbase(void)
-{
#ifndef WITH_HEADLESS
- BlendFileData *bfd;
- extern int datatoc_preview_blend_size;
- extern char datatoc_preview_blend[];
+static Main *load_main_from_memory(const void *blend, int blend_size)
+{
const int fileflags = G.fileflags;
-
+ Main *bmain = NULL;
+ BlendFileData *bfd;
+
G.fileflags |= G_FILE_NO_UI;
- bfd = BLO_read_from_memory(datatoc_preview_blend, datatoc_preview_blend_size, NULL);
+ bfd = BLO_read_from_memory(blend, blend_size, NULL);
if (bfd) {
- pr_main = bfd->main;
-
+ bmain = bfd->main;
+
MEM_freeN(bfd);
}
G.fileflags = fileflags;
+
+ return bmain;
+}
+#endif
+
+void ED_preview_init_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);
#endif
}
void ED_preview_free_dbase(void)
{
- if (pr_main)
- free_main(pr_main);
+ if (G_pr_main)
+ free_main(G_pr_main);
+
+ if (G_pr_main_cycles)
+ free_main(G_pr_main_cycles);
}
static int preview_mat_has_sss(Material *mat, bNodeTree *ntree)
@@ -237,7 +254,7 @@ static int preview_mat_has_sss(Material *mat, bNodeTree *ntree)
return 0;
}
-static Scene *preview_get_scene(void)
+static Scene *preview_get_scene(Main *pr_main)
{
if (pr_main == NULL) return NULL;
@@ -251,8 +268,9 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
{
Scene *sce;
Base *base;
+ Main *pr_main = sp->pr_main;
- sce = preview_get_scene();
+ sce = preview_get_scene(pr_main);
if (sce) {
/* this flag tells render to not execute depsgraph or ipos etc */
@@ -280,18 +298,23 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
sce->r.tiley = sce->r.ysch / 4;
}
- /* exception: don't apply render part of display transform for texture previews or icons */
- if ((id && sp->pr_method == PR_ICON_RENDER) || id_type == ID_TE) {
- BKE_scene_disable_color_management(sce);
- }
-
if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO)
sce->r.alphamode = R_ALPHAPREMUL;
else
sce->r.alphamode = R_ADDSKY;
sce->r.cfra = scene->r.cfra;
- BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine));
+
+ if (id_type == ID_TE && sp->pr_method == PR_ICON_RENDER) {
+ /* force blender internal for texture icons render,
+ * seems commonly used render engines does not support
+ * such kind of rendering
+ */
+ BLI_strncpy(sce->r.engine, "BLENDER_RENDER", sizeof(sce->r.engine));
+ }
+ else {
+ BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine));
+ }
if (id_type == ID_MA) {
Material *mat = NULL, *origmat = (Material *)id;
@@ -302,50 +325,56 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
sp->matcopy = mat;
BLI_addtail(&pr_main->mat, mat);
- init_render_material(mat, 0, NULL); /* call that retrieves mode_l */
- end_render_material(mat);
-
- /* un-useful option */
- if (sp->pr_method == PR_ICON_RENDER)
- mat->shade_flag &= ~MA_OBCOLOR;
-
- /* turn on raytracing if needed */
- if (mat->mode_l & MA_RAYMIRROR)
- sce->r.mode |= R_RAYTRACE;
- if (mat->material_type == MA_TYPE_VOLUME)
- sce->r.mode |= R_RAYTRACE;
- if ((mat->mode_l & MA_RAYTRANSP) && (mat->mode_l & MA_TRANSP))
- sce->r.mode |= R_RAYTRACE;
- if (preview_mat_has_sss(mat, NULL))
- sce->r.mode |= R_SSS;
-
- /* turn off fake shadows if needed */
- /* this only works in a specific case where the preview.blend contains
- * an object starting with 'c' which has a material linked to it (not the obdata)
- * and that material has a fake shadow texture in the active texture slot */
- for (base = sce->base.first; base; base = base->next) {
- if (base->object->id.name[2] == 'c') {
- Material *shadmat = give_current_material(base->object, base->object->actcol);
- if (shadmat) {
- if (mat->mode & MA_SHADBUF) shadmat->septex = 0;
- else shadmat->septex |= 1;
+ if (!BKE_scene_use_new_shading_nodes(scene)) {
+ init_render_material(mat, 0, NULL); /* call that retrieves mode_l */
+ end_render_material(mat);
+
+ /* un-useful option */
+ if (sp->pr_method == PR_ICON_RENDER)
+ mat->shade_flag &= ~MA_OBCOLOR;
+
+ /* turn on raytracing if needed */
+ if (mat->mode_l & MA_RAYMIRROR)
+ sce->r.mode |= R_RAYTRACE;
+ if (mat->material_type == MA_TYPE_VOLUME)
+ sce->r.mode |= R_RAYTRACE;
+ if ((mat->mode_l & MA_RAYTRANSP) && (mat->mode_l & MA_TRANSP))
+ sce->r.mode |= R_RAYTRACE;
+ if (preview_mat_has_sss(mat, NULL))
+ sce->r.mode |= R_SSS;
+
+ /* turn off fake shadows if needed */
+ /* this only works in a specific case where the preview.blend contains
+ * an object starting with 'c' which has a material linked to it (not the obdata)
+ * and that material has a fake shadow texture in the active texture slot */
+ for (base = sce->base.first; base; base = base->next) {
+ if (base->object->id.name[2] == 'c') {
+ Material *shadmat = give_current_material(base->object, base->object->actcol);
+ if (shadmat) {
+ if (mat->mode & MA_SHADBUF) shadmat->septex = 0;
+ else shadmat->septex |= 1;
+ }
}
}
- }
-
- /* turn off bounce lights for volume,
- * doesn't make much visual difference and slows it down too */
- if (mat->material_type == MA_TYPE_VOLUME) {
- for (base = sce->base.first; base; base = base->next) {
- if (base->object->type == OB_LAMP) {
- /* if doesn't match 'Lamp.002' --> main key light */
- if (strcmp(base->object->id.name + 2, "Lamp.002") != 0) {
- base->object->restrictflag |= OB_RESTRICT_RENDER;
+
+ /* turn off bounce lights for volume,
+ * doesn't make much visual difference and slows it down too */
+ if (mat->material_type == MA_TYPE_VOLUME) {
+ for (base = sce->base.first; base; base = base->next) {
+ if (base->object->type == OB_LAMP) {
+ /* if doesn't match 'Lamp.002' --> main key light */
+ if (strcmp(base->object->id.name + 2, "Lamp.002") != 0) {
+ base->object->restrictflag |= OB_RESTRICT_RENDER;
+ }
}
}
}
}
-
+ else {
+ /* use current scene world to light sphere */
+ if (mat->pr_type == MA_SPHERE_A)
+ sce->world = scene->world;
+ }
if (sp->pr_method == PR_ICON_RENDER) {
if (mat->material_type == MA_TYPE_HALO) {
@@ -359,8 +388,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
sce->lay = 1 << mat->pr_type;
if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
- ntreeInitPreview(mat->nodetree, sp->sizex, sp->sizey);
- ntreeInitPreview(origmat->nodetree, sp->sizex, sp->sizey);
+ BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, TRUE);
+ BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, TRUE);
}
}
}
@@ -406,15 +435,16 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
if (tex && sp->slot)
mat->mtex[0]->which_output = sp->slot->which_output;
-
+
+ mat->mtex[0]->mapto &= ~MAP_ALPHA;
+ mat->alpha = 1.0f;
+
/* show alpha in this case */
if (tex == NULL || (tex->flag & TEX_PRV_ALPHA)) {
- mat->mtex[0]->mapto |= MAP_ALPHA;
- mat->alpha = 0.0f;
- }
- else {
- mat->mtex[0]->mapto &= ~MAP_ALPHA;
- mat->alpha = 1.0f;
+ if (!(tex && tex->type == TEX_IMAGE && (tex->imaflag & (TEX_USEALPHA | TEX_CALCALPHA)) == 0)) {
+ mat->mtex[0]->mapto |= MAP_ALPHA;
+ mat->alpha = 0.0f;
+ }
}
}
}
@@ -422,8 +452,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
- ntreeInitPreview(origtex->nodetree, sp->sizex, sp->sizey);
- ntreeInitPreview(tex->nodetree, sp->sizex, sp->sizey);
+ BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, TRUE);
+ BKE_node_preview_init_tree(tex->nodetree, sp->sizex, sp->sizey, TRUE);
}
}
else if (id_type == ID_LA) {
@@ -435,19 +465,21 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
sp->lampcopy = la;
BLI_addtail(&pr_main->lamp, la);
}
-
- if (la && la->type == LA_SUN && (la->sun_effect_type & LA_SUN_EFFECT_SKY)) {
- sce->lay = 1 << MA_ATMOS;
- sce->world = scene->world;
- sce->camera = (Object *)BLI_findstring(&pr_main->object, "CameraAtmo", offsetof(ID, name) + 2);
- }
- else {
- sce->lay = 1 << MA_LAMP;
- sce->world = NULL;
- sce->camera = (Object *)BLI_findstring(&pr_main->object, "Camera", offsetof(ID, name) + 2);
+
+ sce->lay = 1 << MA_LAMP;
+
+ if (!BKE_scene_use_new_shading_nodes(scene)) {
+ if (la && la->type == LA_SUN && (la->sun_effect_type & LA_SUN_EFFECT_SKY)) {
+ sce->lay = 1 << MA_ATMOS;
+ sce->world = scene->world;
+ sce->camera = (Object *)BLI_findstring(&pr_main->object, "CameraAtmo", offsetof(ID, name) + 2);
+ }
+ else {
+ sce->world = NULL;
+ sce->camera = (Object *)BLI_findstring(&pr_main->object, "Camera", offsetof(ID, name) + 2);
+ }
}
- sce->r.mode &= ~R_SHADOW;
-
+
for (base = sce->base.first; base; base = base->next) {
if (base->object->id.name[2] == 'p') {
if (base->object->type == OB_LAMP)
@@ -457,8 +489,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
if (la && la->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
- ntreeInitPreview(origla->nodetree, sp->sizex, sp->sizey);
- ntreeInitPreview(la->nodetree, sp->sizex, sp->sizey);
+ BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, TRUE);
+ BKE_node_preview_init_tree(la->nodetree, sp->sizex, sp->sizey, TRUE);
}
}
else if (id_type == ID_WO) {
@@ -475,8 +507,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
- ntreeInitPreview(wrld->nodetree, sp->sizex, sp->sizey);
- ntreeInitPreview(origwrld->nodetree, sp->sizex, sp->sizey);
+ BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, TRUE);
+ BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, TRUE);
}
}
@@ -488,24 +520,15 @@ 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 */
-static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int first, rcti *rect, rcti *newrect)
+static int ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, rcti *newrect)
{
Render *re;
RenderResult rres;
char name[32];
- int do_gamma_correct = FALSE, do_predivide = FALSE;
int offx = 0;
int newx = BLI_rcti_size_x(rect);
int newy = BLI_rcti_size_y(rect);
- if (id && GS(id->name) != ID_TE) {
- /* exception: don't color manage texture previews - show the raw values */
- if (sce) {
- do_gamma_correct = TRUE;
- do_predivide = sce->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE;
- }
- }
-
if (!split || first) sprintf(name, "Preview %p", (void *)sa);
else sprintf(name, "SecondPreview %p", (void *)sa);
@@ -520,8 +543,10 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int
}
}
+ /* test if something rendered ok */
re = RE_GetRender(name);
RE_AcquireResultImage(re, &rres);
+ RE_ReleaseResultImage(re);
if (rres.rectf) {
@@ -531,40 +556,20 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int
newrect->ymax = max_ii(newrect->ymax, rect->ymin + rres.recty);
if (rres.rectx && rres.recty) {
- /* temporary conversion to byte for drawing */
+ 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;
- int dither = 0;
- unsigned char *rect_byte;
-
- rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect");
-
- if (do_gamma_correct) {
- IMB_display_buffer_transform_apply(rect_byte, rres.rectf, rres.rectx, rres.recty, 4,
- &sce->view_settings, &sce->display_settings, do_predivide);
-
- }
- else {
- /* OCIO_TODO: currently seems an exception for textures (came fro mlegacish time),
- * but is it indeed expected behavior, or textures should be
- * color managed as well?
- */
- IMB_buffer_byte_from_float(rect_byte, rres.rectf,
- 4, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, do_predivide,
- rres.rectx, rres.recty, rres.rectx, rres.rectx);
- }
-
+
+ RE_ResultGet32(re, (unsigned int *)rect_byte);
glaDrawPixelsSafe(fx, fy, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect_byte);
-
+
MEM_freeN(rect_byte);
+
+ return 1;
}
-
- RE_ReleaseResultImage(re);
- return 1;
}
}
- RE_ReleaseResultImage(re);
return 0;
}
@@ -572,7 +577,6 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
{
if (idp) {
ScrArea *sa = CTX_wm_area(C);
- Scene *sce = CTX_data_scene(C);
ID *id = (ID *)idp;
ID *parent = (ID *)parentp;
MTex *slot = (MTex *)slotp;
@@ -588,11 +592,11 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r
newrect.ymax = rect->ymin;
if (parent) {
- ok = ed_preview_draw_rect(sa, sce, id, 1, 1, rect, &newrect);
- ok &= ed_preview_draw_rect(sa, sce, parent, 1, 0, rect, &newrect);
+ ok = ed_preview_draw_rect(sa, 1, 1, rect, &newrect);
+ ok &= ed_preview_draw_rect(sa, 1, 0, rect, &newrect);
}
else
- ok = ed_preview_draw_rect(sa, sce, id, 0, 0, rect, &newrect);
+ ok = ed_preview_draw_rect(sa, 0, 0, rect, &newrect);
if (ok)
*rect = newrect;
@@ -670,16 +674,19 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
short idtype = GS(id->name);
char name[32];
int sizex;
+ Main *pr_main = sp->pr_main;
/* in case of split preview, use border render */
if (split) {
if (first) sizex = sp->sizex / 2;
else sizex = sp->sizex - sp->sizex / 2;
}
- else sizex = sp->sizex;
-
+ else {
+ sizex = sp->sizex;
+ }
+
/* we have to set preview variables first */
- sce = preview_get_scene();
+ sce = preview_get_scene(pr_main);
if (sce) {
sce->r.xsch = sizex;
sce->r.ysch = sp->sizey;
@@ -743,7 +750,7 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
else {
/* validate owner */
//if (ri->rect == NULL)
- // ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
+ // ri->rect= MEM_mallocN(sizeof(int) * ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
//RE_ResultGet32(re, ri->rect);
}
@@ -780,6 +787,7 @@ static void shader_preview_startjob(void *customdata, short *stop, short *do_upd
static void shader_preview_free(void *customdata)
{
ShaderPreview *sp = customdata;
+ Main *pr_main = sp->pr_main;
if (sp->matcopy) {
struct IDProperty *properties;
@@ -917,7 +925,7 @@ static void icon_preview_startjob(void *customdata, short *stop, short *do_updat
ShaderPreview *sp = customdata;
ID *id = sp->id;
short idtype = GS(id->name);
-
+
if (idtype == ID_IM) {
Image *ima = (Image *)id;
ImBuf *ibuf = NULL;
@@ -935,8 +943,10 @@ static void icon_preview_startjob(void *customdata, short *stop, short *do_updat
* 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)
+ 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);
@@ -1028,6 +1038,7 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short
sp->pr_method = PR_ICON_RENDER;
sp->pr_rect = cur_size->rect;
sp->id = ip->id;
+ sp->pr_main = G_pr_main;
common_preview_startjob(sp, stop, do_update, progress);
shader_preview_free(sp);
@@ -1040,8 +1051,27 @@ static void icon_preview_endjob(void *customdata)
{
IconPreview *ip = customdata;
- if (ip->id && GS(ip->id->name) == ID_BR)
- WM_main_add_notifier(NC_BRUSH | NA_EDITED, ip->id);
+ if (ip->id) {
+
+ if (GS(ip->id->name) == ID_BR)
+ WM_main_add_notifier(NC_BRUSH | NA_EDITED, ip->id);
+#if 0
+ if (GS(ip->id->name) == ID_MA) {
+ Material *ma = (Material *)ip->id;
+ PreviewImage *prv_img = ma->preview;
+ int i;
+
+ /* signal to gpu texture */
+ for (i = 0; i < NUM_ICON_SIZES; ++i) {
+ if (prv_img->gputexture[i]) {
+ GPU_texture_free(prv_img->gputexture[i]);
+ prv_img->gputexture[i] = NULL;
+ WM_main_add_notifier(NC_MATERIAL|ND_SHADING_DRAW, ip->id);
+ }
+ }
+ }
+#endif
+ }
}
static void icon_preview_free(void *customdata)
@@ -1077,7 +1107,7 @@ void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *r
/* setup job */
WM_jobs_customdata_set(wm_job, ip, icon_preview_free);
- WM_jobs_timer(wm_job, 0.25, NC_MATERIAL, NC_MATERIAL);
+ WM_jobs_timer(wm_job, 0.1, NC_MATERIAL, NC_MATERIAL);
WM_jobs_callbacks(wm_job, icon_preview_startjob_all_sizes, NULL, NULL, icon_preview_endjob);
WM_jobs_start(CTX_wm_manager(C), wm_job);
@@ -1088,13 +1118,18 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M
Object *ob = CTX_data_active_object(C);
wmJob *wm_job;
ShaderPreview *sp;
+ Scene *scene = CTX_data_scene(C);
+
+ /* node previews not supported for cycles */
+ if (BKE_scene_use_new_shading_nodes(scene) && method == PR_NODE_RENDER)
+ return;
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");
/* customdata for preview thread */
- sp->scene = CTX_data_scene(C);
+ sp->scene = scene;
sp->owner = owner;
sp->sizex = sizex;
sp->sizey = sizey;
@@ -1102,6 +1137,14 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M
sp->id = id;
sp->parent = parent;
sp->slot = slot;
+
+ /* hardcoded preview .blend for cycles/internal, this should be solved
+ * once with custom preview .blend path for external engines */
+ if (BKE_scene_use_new_shading_nodes(scene))
+ sp->pr_main = G_pr_main_cycles;
+ else
+ sp->pr_main = G_pr_main;
+
if (ob && ob->totcol) copy_v4_v4(sp->col, ob->col);
else sp->col[0] = sp->col[1] = sp->col[2] = sp->col[3] = 1.0f;
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index eef5e705ce7..d1254a7cb78 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -51,10 +51,12 @@
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
#include "BKE_font.h"
+#include "BKE_freestyle.h"
#include "BKE_global.h"
#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_library.h"
+#include "BKE_linestyle.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_node.h"
@@ -69,7 +71,12 @@
#include "GPU_material.h"
+#ifdef WITH_FREESTYLE
+# include "FRS_freestyle.h"
+#endif
+
#include "RNA_access.h"
+#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -367,6 +374,7 @@ static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
+ Main *bmain = CTX_data_main(C);
PointerRNA ptr, idptr;
PropertyRNA *prop;
@@ -375,10 +383,10 @@ static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
ma = BKE_material_copy(ma);
}
else {
- ma = BKE_material_add("Material");
+ ma = BKE_material_add(bmain, "Material");
if (BKE_scene_use_new_shading_nodes(scene)) {
- ED_node_shader_default(scene, &ma->id);
+ ED_node_shader_default(C, &ma->id);
ma->use_nodes = TRUE;
}
}
@@ -420,6 +428,7 @@ void MATERIAL_OT_new(wmOperatorType *ot)
static int new_texture_exec(bContext *C, wmOperator *UNUSED(op))
{
Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
+ Main *bmain = CTX_data_main(C);
PointerRNA ptr, idptr;
PropertyRNA *prop;
@@ -427,7 +436,7 @@ static int new_texture_exec(bContext *C, wmOperator *UNUSED(op))
if (tex)
tex = BKE_texture_copy(tex);
else
- tex = add_texture("Texture");
+ tex = add_texture(bmain, "Texture");
/* hook into UI */
uiIDContextProperty(C, &ptr, &prop);
@@ -467,6 +476,7 @@ static int new_world_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
+ Main *bmain = CTX_data_main(C);
PointerRNA ptr, idptr;
PropertyRNA *prop;
@@ -475,10 +485,10 @@ static int new_world_exec(bContext *C, wmOperator *UNUSED(op))
wo = BKE_world_copy(wo);
}
else {
- wo = add_world("World");
+ wo = add_world(bmain, "World");
if (BKE_scene_use_new_shading_nodes(scene)) {
- ED_node_shader_default(scene, &wo->id);
+ ED_node_shader_default(C, &wo->id);
wo->use_nodes = TRUE;
}
}
@@ -570,6 +580,624 @@ void SCENE_OT_render_layer_remove(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+#ifdef WITH_FREESTYLE
+
+static int freestyle_module_add_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+
+ BKE_freestyle_module_add(&srl->freestyleConfig);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_module_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Freestyle Module";
+ ot->idname = "SCENE_OT_freestyle_module_add";
+ ot->description = "Add a style module into the list of modules";
+
+ /* api callbacks */
+ ot->exec = freestyle_module_add_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int freestyle_module_remove_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
+ FreestyleModuleConfig *module = ptr.data;
+
+ BKE_freestyle_module_delete(&srl->freestyleConfig, module);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_module_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Freestyle Module";
+ ot->idname = "SCENE_OT_freestyle_module_remove";
+ ot->description = "Remove the style module from the stack";
+
+ /* api callbacks */
+ ot->exec = freestyle_module_remove_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int freestyle_module_move_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
+ FreestyleModuleConfig *module = ptr.data;
+ int dir = RNA_enum_get(op->ptr, "direction");
+
+ if (dir == 1) {
+ BKE_freestyle_module_move_up(&srl->freestyleConfig, module);
+ }
+ else {
+ BKE_freestyle_module_move_down(&srl->freestyleConfig, module);
+ }
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_module_move(wmOperatorType *ot)
+{
+ static EnumPropertyItem direction_items[] = {
+ {1, "UP", 0, "Up", ""},
+ {-1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Move Freestyle Module";
+ ot->idname = "SCENE_OT_freestyle_module_move";
+ ot->description = "Change the position of the style module within in the list of style modules";
+
+ /* api callbacks */
+ ot->exec = freestyle_module_move_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to move, UP or DOWN");
+}
+
+static int freestyle_lineset_add_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+
+ BKE_freestyle_lineset_add(&srl->freestyleConfig);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_lineset_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Line Set";
+ ot->idname = "SCENE_OT_freestyle_lineset_add";
+ ot->description = "Add a line set into the list of line sets";
+
+ /* api callbacks */
+ ot->exec = freestyle_lineset_add_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int freestyle_active_lineset_poll(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+
+ return BKE_freestyle_lineset_get_active(&srl->freestyleConfig) != NULL;
+}
+
+static int freestyle_lineset_copy_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+
+ FRS_copy_active_lineset(&srl->freestyleConfig);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_lineset_copy(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Copy Line Set";
+ ot->idname = "SCENE_OT_freestyle_lineset_copy";
+ ot->description = "Copy the active line set to a buffer";
+
+ /* api callbacks */
+ ot->exec = freestyle_lineset_copy_exec;
+ ot->poll = freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int freestyle_lineset_paste_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+
+ FRS_paste_active_lineset(&srl->freestyleConfig);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_lineset_paste(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Paste Line Set";
+ ot->idname = "SCENE_OT_freestyle_lineset_paste";
+ ot->description = "Paste the buffer content to the active line set";
+
+ /* api callbacks */
+ ot->exec = freestyle_lineset_paste_exec;
+ ot->poll = freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int freestyle_lineset_remove_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+
+ FRS_delete_active_lineset(&srl->freestyleConfig);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_lineset_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Line Set";
+ ot->idname = "SCENE_OT_freestyle_lineset_remove";
+ ot->description = "Remove the active line set from the list of line sets";
+
+ /* api callbacks */
+ ot->exec = freestyle_lineset_remove_exec;
+ ot->poll = freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int freestyle_lineset_move_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, scene->r.actlay);
+ int dir = RNA_enum_get(op->ptr, "direction");
+
+ if (dir == 1) {
+ FRS_move_active_lineset_up(&srl->freestyleConfig);
+ }
+ else {
+ FRS_move_active_lineset_down(&srl->freestyleConfig);
+ }
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_lineset_move(wmOperatorType *ot)
+{
+ static EnumPropertyItem direction_items[] = {
+ {1, "UP", 0, "Up", ""},
+ {-1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Move Line Set";
+ ot->idname = "SCENE_OT_freestyle_lineset_move";
+ ot->description = "Change the position of the active line set within the list of line sets";
+
+ /* api callbacks */
+ ot->exec = freestyle_lineset_move_exec;
+ ot->poll = freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to move, UP or DOWN");
+}
+
+static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op)
+{
+ 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);
+
+ if (!lineset) {
+ BKE_report(op->reports, RPT_ERROR, "No active lineset to add a new line style to");
+ return OPERATOR_CANCELLED;
+ }
+ lineset->linestyle->id.us--;
+ lineset->linestyle = BKE_copy_linestyle(lineset->linestyle);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_linestyle_new(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "New Line Style";
+ ot->idname = "SCENE_OT_freestyle_linestyle_new";
+ ot->description = "Create a new line style, reusable by multiple line sets";
+
+ /* api callbacks */
+ ot->exec = freestyle_linestyle_new_exec;
+ ot->poll = freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int freestyle_color_modifier_add_exec(bContext *C, wmOperator *op)
+{
+ 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);
+ int type = RNA_enum_get(op->ptr, "type");
+
+ if (!lineset) {
+ BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to");
+ return OPERATOR_CANCELLED;
+ }
+ if (BKE_add_linestyle_color_modifier(lineset->linestyle, type) == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unknown line color modifier type.");
+ return OPERATOR_CANCELLED;
+ }
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_color_modifier_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Line Color Modifier";
+ ot->idname = "SCENE_OT_freestyle_color_modifier_add";
+ ot->description = "Add a line color modifier to the line style associated with the active lineset";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = freestyle_color_modifier_add_exec;
+ ot->poll = freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", linestyle_color_modifier_type_items, 0, "Type", "");
+}
+
+static int freestyle_alpha_modifier_add_exec(bContext *C, wmOperator *op)
+{
+ 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);
+ int type = RNA_enum_get(op->ptr, "type");
+
+ if (!lineset) {
+ BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to");
+ return OPERATOR_CANCELLED;
+ }
+ if (BKE_add_linestyle_alpha_modifier(lineset->linestyle, type) == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unknown alpha transparency modifier type");
+ return OPERATOR_CANCELLED;
+ }
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_alpha_modifier_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Alpha Transparency Modifier";
+ ot->idname = "SCENE_OT_freestyle_alpha_modifier_add";
+ ot->description = "Add an alpha transparency modifier to the line style associated with the active lineset";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = freestyle_alpha_modifier_add_exec;
+ ot->poll = freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", linestyle_alpha_modifier_type_items, 0, "Type", "");
+}
+
+static int freestyle_thickness_modifier_add_exec(bContext *C, wmOperator *op)
+{
+ 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);
+ int type = RNA_enum_get(op->ptr, "type");
+
+ if (!lineset) {
+ BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to");
+ return OPERATOR_CANCELLED;
+ }
+ if (BKE_add_linestyle_thickness_modifier(lineset->linestyle, type) == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unknown line thickness modifier type");
+ return OPERATOR_CANCELLED;
+ }
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_thickness_modifier_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Line Thickness Modifier";
+ ot->idname = "SCENE_OT_freestyle_thickness_modifier_add";
+ ot->description = "Add a line thickness modifier to the line style associated with the active lineset";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = freestyle_thickness_modifier_add_exec;
+ ot->poll = freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", linestyle_thickness_modifier_type_items, 0, "Type", "");
+}
+
+static int freestyle_geometry_modifier_add_exec(bContext *C, wmOperator *op)
+{
+ 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);
+ int type = RNA_enum_get(op->ptr, "type");
+
+ if (!lineset) {
+ BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to");
+ return OPERATOR_CANCELLED;
+ }
+ if (BKE_add_linestyle_geometry_modifier(lineset->linestyle, type) == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unknown stroke geometry modifier type");
+ return OPERATOR_CANCELLED;
+ }
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_geometry_modifier_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Stroke Geometry Modifier";
+ ot->idname = "SCENE_OT_freestyle_geometry_modifier_add";
+ ot->description = "Add a stroke geometry modifier to the line style associated with the active lineset";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = freestyle_geometry_modifier_add_exec;
+ ot->poll = freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", linestyle_geometry_modifier_type_items, 0, "Type", "");
+}
+
+static int freestyle_get_modifier_type(PointerRNA *ptr)
+{
+ if (RNA_struct_is_a(ptr->type, &RNA_LineStyleColorModifier))
+ return LS_MODIFIER_TYPE_COLOR;
+ else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleAlphaModifier))
+ return LS_MODIFIER_TYPE_ALPHA;
+ else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleThicknessModifier))
+ return LS_MODIFIER_TYPE_THICKNESS;
+ else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleGeometryModifier))
+ return LS_MODIFIER_TYPE_GEOMETRY;
+ return -1;
+}
+
+static int freestyle_modifier_remove_exec(bContext *C, wmOperator *op)
+{
+ 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);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
+ LineStyleModifier *modifier = ptr.data;
+
+ if (!lineset) {
+ BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style the modifier belongs to");
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (freestyle_get_modifier_type(&ptr)) {
+ case LS_MODIFIER_TYPE_COLOR:
+ BKE_remove_linestyle_color_modifier(lineset->linestyle, modifier);
+ break;
+ case LS_MODIFIER_TYPE_ALPHA:
+ BKE_remove_linestyle_alpha_modifier(lineset->linestyle, modifier);
+ break;
+ case LS_MODIFIER_TYPE_THICKNESS:
+ BKE_remove_linestyle_thickness_modifier(lineset->linestyle, modifier);
+ break;
+ case LS_MODIFIER_TYPE_GEOMETRY:
+ BKE_remove_linestyle_geometry_modifier(lineset->linestyle, modifier);
+ break;
+ default:
+ BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
+ return OPERATOR_CANCELLED;
+ }
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_modifier_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Modifier";
+ ot->idname = "SCENE_OT_freestyle_modifier_remove";
+ ot->description = "Remove the modifier from the list of modifiers";
+
+ /* api callbacks */
+ ot->exec = freestyle_modifier_remove_exec;
+ ot->poll = freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op)
+{
+ 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);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
+ LineStyleModifier *modifier = ptr.data;
+
+ if (!lineset) {
+ BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style the modifier belongs to");
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (freestyle_get_modifier_type(&ptr)) {
+ case LS_MODIFIER_TYPE_COLOR:
+ BKE_copy_linestyle_color_modifier(lineset->linestyle, modifier);
+ break;
+ case LS_MODIFIER_TYPE_ALPHA:
+ BKE_copy_linestyle_alpha_modifier(lineset->linestyle, modifier);
+ break;
+ case LS_MODIFIER_TYPE_THICKNESS:
+ BKE_copy_linestyle_thickness_modifier(lineset->linestyle, modifier);
+ break;
+ case LS_MODIFIER_TYPE_GEOMETRY:
+ BKE_copy_linestyle_geometry_modifier(lineset->linestyle, modifier);
+ break;
+ default:
+ BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
+ return OPERATOR_CANCELLED;
+ }
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_modifier_copy(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Copy Modifier";
+ ot->idname = "SCENE_OT_freestyle_modifier_copy";
+ ot->description = "Duplicate the modifier within the list of modifiers";
+
+ /* api callbacks */
+ ot->exec = freestyle_modifier_copy_exec;
+ ot->poll = freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int freestyle_modifier_move_exec(bContext *C, wmOperator *op)
+{
+ 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);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier);
+ LineStyleModifier *modifier = ptr.data;
+ int dir = RNA_enum_get(op->ptr, "direction");
+
+ if (!lineset) {
+ BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style the modifier belongs to");
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (freestyle_get_modifier_type(&ptr)) {
+ case LS_MODIFIER_TYPE_COLOR:
+ BKE_move_linestyle_color_modifier(lineset->linestyle, modifier, dir);
+ break;
+ case LS_MODIFIER_TYPE_ALPHA:
+ BKE_move_linestyle_alpha_modifier(lineset->linestyle, modifier, dir);
+ break;
+ case LS_MODIFIER_TYPE_THICKNESS:
+ BKE_move_linestyle_thickness_modifier(lineset->linestyle, modifier, dir);
+ break;
+ case LS_MODIFIER_TYPE_GEOMETRY:
+ BKE_move_linestyle_geometry_modifier(lineset->linestyle, modifier, dir);
+ break;
+ default:
+ BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier");
+ return OPERATOR_CANCELLED;
+ }
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_modifier_move(wmOperatorType *ot)
+{
+ static EnumPropertyItem direction_items[] = {
+ {1, "UP", 0, "Up", ""},
+ {-1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Move Modifier";
+ ot->idname = "SCENE_OT_freestyle_modifier_move";
+ ot->description = "Move the modifier within the list of modifiers";
+
+ /* api callbacks */
+ ot->exec = freestyle_modifier_move_exec;
+ ot->poll = freestyle_active_lineset_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to move, UP or DOWN");
+}
+
+#endif /* WITH_FREESTYLE */
+
static int texture_slot_move(bContext *C, wmOperator *op)
{
ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
@@ -688,7 +1316,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, imtype);
+ BKE_add_image_extension(path, &scene->r.im_format);
}
WM_cursor_wait(1);
@@ -702,7 +1330,7 @@ static int envmap_save_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int envmap_save_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int envmap_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
//Scene *scene= CTX_data_scene(C);
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index 1ed1cbb2c6b..d29c711cad0 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -33,6 +33,7 @@
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -46,6 +47,7 @@
#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_main.h"
@@ -56,6 +58,7 @@
#include "BKE_world.h"
#include "GPU_material.h"
+#include "GPU_buffers.h"
#include "RE_engine.h"
#include "RE_pipeline.h"
@@ -232,6 +235,9 @@ static int nodes_use_material(bNodeTree *ntree, Material *ma)
static void material_changed(Main *bmain, Material *ma)
{
Material *parent;
+ Object *ob;
+ Scene *scene;
+ int texture_draw = FALSE;
/* icons */
BKE_icon_changed(BKE_icon_getid(&ma->id));
@@ -254,6 +260,33 @@ static void material_changed(Main *bmain, Material *ma)
if (parent->gpumaterial.first)
GPU_material_free(parent);
}
+
+ /* find if we have a scene with textured display */
+ for (scene = bmain->scene.first; scene; scene = scene->id.next) {
+ if (scene->customdata_mask & CD_MASK_MTFACE) {
+ texture_draw = TRUE;
+ break;
+ }
+ }
+
+ /* find textured objects */
+ if (texture_draw && !(U.gameflags & USER_DISABLE_VBO)) {
+ for (ob = bmain->object.first; ob; ob = ob->id.next) {
+ DerivedMesh *dm = ob->derivedFinal;
+ Material ***material = give_matarar(ob);
+ short a, *totmaterial = give_totcolp(ob);
+
+ if (dm && totmaterial && material) {
+ for (a = 0; a < *totmaterial; a++) {
+ if ((*material)[a] == ma) {
+ GPU_drawobject_free(dm);
+ break;
+ }
+ }
+ }
+ }
+ }
+
}
static void lamp_changed(Main *bmain, Lamp *la)
@@ -277,28 +310,33 @@ static void lamp_changed(Main *bmain, Lamp *la)
GPU_material_free(&defmaterial);
}
+static int material_uses_texture(Material *ma, Tex *tex)
+{
+ if (mtex_use_tex(ma->mtex, MAX_MTEX, tex))
+ return TRUE;
+ else if (ma->use_nodes && ma->nodetree && nodes_use_tex(ma->nodetree, tex))
+ return TRUE;
+
+ return FALSE;
+}
+
static void texture_changed(Main *bmain, Tex *tex)
{
Material *ma;
Lamp *la;
World *wo;
Scene *scene;
+ Object *ob;
bNode *node;
+ int texture_draw = FALSE;
/* icons */
BKE_icon_changed(BKE_icon_getid(&tex->id));
/* find materials */
for (ma = bmain->mat.first; ma; ma = ma->id.next) {
- if (mtex_use_tex(ma->mtex, MAX_MTEX, tex)) {
- /* pass */
- }
- else if (ma->use_nodes && ma->nodetree && nodes_use_tex(ma->nodetree, tex)) {
- /* pass */
- }
- else {
+ if (!material_uses_texture(ma, tex))
continue;
- }
BKE_icon_changed(BKE_icon_getid(&ma->id));
@@ -339,7 +377,33 @@ static void texture_changed(Main *bmain, Tex *tex)
if (scene->use_nodes && scene->nodetree) {
for (node = scene->nodetree->nodes.first; node; node = node->next) {
if (node->id == &tex->id)
- ED_node_changed_update(&scene->id, node);
+ ED_node_tag_update_id(&scene->id);
+ }
+ }
+
+ if (scene->customdata_mask & CD_MASK_MTFACE)
+ texture_draw = TRUE;
+ }
+
+ /* find textured objects */
+ if (texture_draw && !(U.gameflags & USER_DISABLE_VBO)) {
+ for (ob = bmain->object.first; ob; ob = ob->id.next) {
+ DerivedMesh *dm = ob->derivedFinal;
+ Material ***material = give_matarar(ob);
+ short a, *totmaterial = give_totcolp(ob);
+
+ if (dm && totmaterial && material) {
+ for (a = 0; a < *totmaterial; a++) {
+ if (ob->matbits && ob->matbits[a])
+ ma = ob->mat[a];
+ else
+ ma = (*material)[a];
+
+ if (ma && material_uses_texture(ma, tex)) {
+ GPU_drawobject_free(dm);
+ break;
+ }
+ }
}
}
}
diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c
index 5ec7f4d05b6..186d0d20623 100644
--- a/source/blender/editors/render/render_view.c
+++ b/source/blender/editors/render/render_view.c
@@ -35,6 +35,7 @@
#include "BLI_utildefines.h"
#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
#include "BKE_blender.h"
#include "BKE_context.h"
@@ -151,9 +152,10 @@ void render_view_open(bContext *C, int mx, int my)
if (sizex < 320) sizex = 320;
if (sizey < 256) sizey = 256;
- /* XXX some magic to calculate postition */
- rect.xmin = mx + win->posx - sizex / 2;
- rect.ymin = my + win->posy - sizey / 2;
+ /* some magic to calculate postition */
+ /* pixelsize: mouse coords are in U.pixelsize units :/ */
+ rect.xmin = (mx / U.pixelsize) + win->posx - sizex / 2;
+ rect.ymin = (my / U.pixelsize) + win->posy - sizey / 2;
rect.xmax = rect.xmin + sizex;
rect.ymax = rect.ymin + sizey;
@@ -273,7 +275,7 @@ void RENDER_OT_view_cancel(struct wmOperatorType *ot)
/************************* show render viewer *****************/
-static int render_view_show_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int render_view_show_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
wmWindow *wincur = CTX_wm_window(C);
@@ -287,7 +289,10 @@ static int render_view_show_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent
/* is there another window showing result? */
for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) {
- if (win->screen->temp || (win == winshow && winshow != wincur)) {
+ bScreen *sc = win->screen;
+ if ((sc->temp && ((ScrArea *)sc->areabase.first)->spacetype == SPACE_IMAGE) ||
+ (win == winshow && winshow != wincur))
+ {
wm_window_raise(win);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/screen/SConscript b/source/blender/editors/screen/SConscript
index 0e894a13d28..c0a14ce5377 100644
--- a/source/blender/editors/screen/SConscript
+++ b/source/blender/editors/screen/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index f30e0abb4f3..2d6e8d0ada0 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -67,6 +67,8 @@
#include "screen_intern.h"
+extern void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); /* xxx temp */
+
/* general area and region code */
static void region_draw_emboss(ARegion *ar, rcti *scirct)
@@ -235,8 +237,8 @@ static void region_draw_azone_icon(AZone *az)
static void draw_azone_plus(float x1, float y1, float x2, float y2)
{
- float width = 2.0f;
- float pad = 4.0f;
+ float width = 0.1f * U.widget_unit;
+ float pad = 0.2f * U.widget_unit;
glRectf((x1 + x2 - width) * 0.5f, y1 + pad, (x1 + x2 + width) * 0.5f, y2 - pad);
glRectf(x1 + pad, (y1 + y2 - width) * 0.5f, (x1 + x2 - width) * 0.5f, (y1 + y2 + width) * 0.5f);
@@ -245,8 +247,6 @@ static void draw_azone_plus(float x1, float y1, float x2, float y2)
static void region_draw_azone_tab_plus(AZone *az)
{
- extern void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); /* xxx temp */
-
glEnable(GL_BLEND);
/* add code to draw region hidden as 'too small' */
@@ -321,8 +321,6 @@ static void region_draw_azone_tab(AZone *az)
static void region_draw_azone_tria(AZone *az)
{
- extern void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); /* xxx temp */
-
glEnable(GL_BLEND);
//UI_GetThemeColor3fv(TH_HEADER, col);
glColor4f(0.0f, 0.0f, 0.0f, 0.35f);
@@ -395,47 +393,14 @@ void ED_area_overdraw(bContext *C)
}
-/* get scissor rect, checking overlapping regions */
-void region_scissor_winrct(ARegion *ar, rcti *winrct)
-{
- *winrct = ar->winrct;
-
- if (ELEM(ar->alignment, RGN_OVERLAP_LEFT, RGN_OVERLAP_RIGHT))
- return;
-
- while (ar->prev) {
- ar = ar->prev;
-
- if (BLI_rcti_isect(winrct, &ar->winrct, NULL)) {
- if (ar->flag & RGN_FLAG_HIDDEN) {
- /* pass */
- }
- else if (ar->alignment & RGN_SPLIT_PREV) {
- /* pass */
- }
- else if (ar->alignment == RGN_OVERLAP_LEFT) {
- winrct->xmin = ar->winrct.xmax + 1;
- }
- else if (ar->alignment == RGN_OVERLAP_RIGHT) {
- winrct->xmax = ar->winrct.xmin - 1;
- }
- else break;
- }
- }
-}
-
/* only exported for WM */
/* makes region ready for drawing, sets pixelspace */
void ED_region_set(const bContext *C, ARegion *ar)
{
wmWindow *win = CTX_wm_window(C);
ScrArea *sa = CTX_wm_area(C);
- rcti winrct;
-
- /* checks other overlapping regions */
- region_scissor_winrct(ar, &winrct);
- ar->drawrct = winrct;
+ ar->drawrct = ar->winrct;
/* note; this sets state, so we can use wmOrtho and friends */
wmSubWindowScissorSet(win, ar->swinid, &ar->drawrct);
@@ -452,24 +417,20 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
wmWindow *win = CTX_wm_window(C);
ScrArea *sa = CTX_wm_area(C);
ARegionType *at = ar->type;
- rcti winrct;
/* see BKE_spacedata_draw_locks() */
if (at->do_lock)
return;
- /* checks other overlapping regions */
- region_scissor_winrct(ar, &winrct);
-
/* if no partial draw rect set, full rect */
if (ar->drawrct.xmin == ar->drawrct.xmax)
- ar->drawrct = winrct;
+ ar->drawrct = ar->winrct;
else {
/* extra clip for safety (intersect the rects, could use API func) */
- ar->drawrct.xmin = max_ii(winrct.xmin, ar->drawrct.xmin);
- ar->drawrct.ymin = max_ii(winrct.ymin, ar->drawrct.ymin);
- ar->drawrct.xmax = min_ii(winrct.xmax, ar->drawrct.xmax);
- ar->drawrct.ymax = min_ii(winrct.ymax, ar->drawrct.ymax);
+ ar->drawrct.xmin = max_ii(ar->winrct.xmin, ar->drawrct.xmin);
+ ar->drawrct.ymin = max_ii(ar->winrct.ymin, ar->drawrct.ymin);
+ ar->drawrct.xmax = min_ii(ar->winrct.xmax, ar->drawrct.xmax);
+ ar->drawrct.ymax = min_ii(ar->winrct.ymax, ar->drawrct.ymax);
}
/* note; this sets state, so we can use wmOrtho and friends */
@@ -483,7 +444,7 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
glClear(GL_COLOR_BUFFER_BIT);
UI_ThemeColor(TH_TEXT);
- BLF_draw_default(20, 8, 0.0f, ar->headerstr, BLF_DRAW_STR_DUMMY_MAX);
+ BLF_draw_default(UI_UNIT_X, 0.4f * UI_UNIT_Y, 0.0f, ar->headerstr, BLF_DRAW_STR_DUMMY_MAX);
}
else if (at->draw) {
at->draw(C, ar);
@@ -500,7 +461,7 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
uiFreeInactiveBlocks(C, &ar->uiblocks);
if (sa)
- region_draw_emboss(ar, &winrct);
+ region_draw_emboss(ar, &ar->winrct);
}
/* **********************************
@@ -611,8 +572,8 @@ static void area_azone_initialize(bScreen *screen, ScrArea *sa)
az = (AZone *)MEM_callocN(sizeof(AZone), "actionzone");
BLI_addtail(&(sa->actionzones), az);
az->type = AZONE_AREA;
- az->x1 = sa->totrct.xmin - 1;
- az->y1 = sa->totrct.ymin - 1;
+ az->x1 = sa->totrct.xmin;
+ az->y1 = sa->totrct.ymin;
az->x2 = sa->totrct.xmin + (AZONESPOT - 1);
az->y2 = sa->totrct.ymin + (AZONESPOT - 1);
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
@@ -627,8 +588,8 @@ static void area_azone_initialize(bScreen *screen, ScrArea *sa)
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
}
-#define AZONEPAD_EDGE 4
-#define AZONEPAD_ICON 9
+#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)
{
switch (az->edge) {
@@ -636,22 +597,22 @@ static void region_azone_edge(AZone *az, ARegion *ar)
az->x1 = ar->winrct.xmin;
az->y1 = ar->winrct.ymax - AZONEPAD_EDGE;
az->x2 = ar->winrct.xmax;
- az->y2 = ar->winrct.ymax;
+ az->y2 = ar->winrct.ymax + AZONEPAD_EDGE;
break;
case AE_BOTTOM_TO_TOPLEFT:
az->x1 = ar->winrct.xmin;
az->y1 = ar->winrct.ymin + AZONEPAD_EDGE;
az->x2 = ar->winrct.xmax;
- az->y2 = ar->winrct.ymin;
+ az->y2 = ar->winrct.ymin - AZONEPAD_EDGE;
break;
case AE_LEFT_TO_TOPRIGHT:
- az->x1 = ar->winrct.xmin;
+ az->x1 = ar->winrct.xmin - AZONEPAD_EDGE;
az->y1 = ar->winrct.ymin;
az->x2 = ar->winrct.xmin + AZONEPAD_EDGE;
az->y2 = ar->winrct.ymax;
break;
case AE_RIGHT_TO_TOPLEFT:
- az->x1 = ar->winrct.xmax;
+ az->x1 = ar->winrct.xmax + AZONEPAD_EDGE;
az->y1 = ar->winrct.ymin;
az->x2 = ar->winrct.xmax - AZONEPAD_EDGE;
az->y2 = ar->winrct.ymax;
@@ -720,8 +681,8 @@ static void region_azone_icon(ScrArea *sa, AZone *az, ARegion *ar)
}
}
-#define AZONEPAD_TAB_PLUSW 14
-#define AZONEPAD_TAB_PLUSH 14
+#define AZONEPAD_TAB_PLUSW (0.7f * U.widget_unit)
+#define AZONEPAD_TAB_PLUSH (0.7f * U.widget_unit)
/* region already made zero sized, in shape of edge */
static void region_azone_tab_plus(ScrArea *sa, AZone *az, ARegion *ar)
@@ -736,28 +697,28 @@ 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;
- az->x1 = ar->winrct.xmax - 2.5 * AZONEPAD_TAB_PLUSW;
+ az->x1 = ar->winrct.xmax - 2.5f * AZONEPAD_TAB_PLUSW;
az->y1 = ar->winrct.ymax - add;
- az->x2 = ar->winrct.xmax - 1.5 * AZONEPAD_TAB_PLUSW;
+ az->x2 = ar->winrct.xmax - 1.5f * AZONEPAD_TAB_PLUSW;
az->y2 = ar->winrct.ymax - add + AZONEPAD_TAB_PLUSH;
break;
case AE_BOTTOM_TO_TOPLEFT:
- az->x1 = ar->winrct.xmax - 2.5 * AZONEPAD_TAB_PLUSW;
+ az->x1 = ar->winrct.xmax - 2.5f * AZONEPAD_TAB_PLUSW;
az->y1 = ar->winrct.ymin - AZONEPAD_TAB_PLUSH;
- az->x2 = ar->winrct.xmax - 1.5 * AZONEPAD_TAB_PLUSW;
+ az->x2 = ar->winrct.xmax - 1.5f * AZONEPAD_TAB_PLUSW;
az->y2 = ar->winrct.ymin;
break;
case AE_LEFT_TO_TOPRIGHT:
az->x1 = ar->winrct.xmin - AZONEPAD_TAB_PLUSH;
- az->y1 = ar->winrct.ymax - 2.5 * AZONEPAD_TAB_PLUSW;
+ az->y1 = ar->winrct.ymax - 2.5f * AZONEPAD_TAB_PLUSW;
az->x2 = ar->winrct.xmin;
- az->y2 = ar->winrct.ymax - 1.5 * AZONEPAD_TAB_PLUSW;
+ az->y2 = ar->winrct.ymax - 1.5f * AZONEPAD_TAB_PLUSW;
break;
case AE_RIGHT_TO_TOPLEFT:
az->x1 = ar->winrct.xmax - 1;
- az->y1 = ar->winrct.ymax - 2.5 * AZONEPAD_TAB_PLUSW;
+ az->y1 = ar->winrct.ymax - 2.5f * AZONEPAD_TAB_PLUSW;
az->x2 = ar->winrct.xmax - 1 + AZONEPAD_TAB_PLUSH;
- az->y2 = ar->winrct.ymax - 1.5 * AZONEPAD_TAB_PLUSW;
+ az->y2 = ar->winrct.ymax - 1.5f * AZONEPAD_TAB_PLUSW;
break;
}
/* rect needed for mouse pointer test */
@@ -765,8 +726,8 @@ static void region_azone_tab_plus(ScrArea *sa, AZone *az, ARegion *ar)
}
-#define AZONEPAD_TABW 18
-#define AZONEPAD_TABH 7
+#define AZONEPAD_TABW (0.9f * U.widget_unit)
+#define AZONEPAD_TABH (0.35f * U.widget_unit)
/* region already made zero sized, in shape of edge */
static void region_azone_tab(ScrArea *sa, AZone *az, ARegion *ar)
@@ -809,8 +770,8 @@ static void region_azone_tab(ScrArea *sa, AZone *az, ARegion *ar)
BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2);
}
-#define AZONEPAD_TRIAW 16
-#define AZONEPAD_TRIAH 9
+#define AZONEPAD_TRIAW (0.8f * U.widget_unit)
+#define AZONEPAD_TRIAH (0.45f * U.widget_unit)
/* region already made zero sized, in shape of edge */
@@ -892,9 +853,9 @@ static void region_azone_add(ScrArea *sa, ARegion *ar, int alignment)
region_azone_initialize(sa, ar, AE_BOTTOM_TO_TOPLEFT);
else if (alignment == RGN_ALIGN_BOTTOM)
region_azone_initialize(sa, ar, AE_TOP_TO_BOTTOMRIGHT);
- else if (ELEM(alignment, RGN_ALIGN_RIGHT, RGN_OVERLAP_RIGHT))
+ else if (alignment == RGN_ALIGN_RIGHT)
region_azone_initialize(sa, ar, AE_LEFT_TO_TOPRIGHT);
- else if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_OVERLAP_LEFT))
+ else if (alignment == RGN_ALIGN_LEFT)
region_azone_initialize(sa, ar, AE_RIGHT_TO_TOPLEFT);
}
@@ -909,7 +870,58 @@ static int rct_fits(rcti *rect, char dir, int size)
}
}
-static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int quad)
+/* *************************************************************** */
+
+/* ar should be overlapping */
+/* function checks if some overlapping region was defined before - on same place */
+static void region_overlap_fix(ScrArea *sa, ARegion *ar)
+{
+ ARegion *ar1 = ar->prev;
+
+ /* find overlapping previous region on same place */
+ while (ar1) {
+ if (ar1->overlap) {
+ if ((ar1->alignment & RGN_SPLIT_PREV) == 0)
+ if (BLI_rcti_isect(&ar1->winrct, &ar->winrct, NULL))
+ break;
+ }
+ ar1 = ar1->prev;
+ }
+
+ /* translate or close */
+ if (ar1) {
+ int align1 = ar1->alignment & ~RGN_SPLIT_PREV;
+
+ if (align1 == RGN_ALIGN_LEFT) {
+ if (ar->winrct.xmax + ar1->winx > sa->winx - U.widget_unit)
+ ar->flag |= RGN_FLAG_TOO_SMALL;
+ else
+ BLI_rcti_translate(&ar->winrct, ar1->winx, 0);
+ }
+ else if (align1 == RGN_ALIGN_RIGHT) {
+ if (ar->winrct.xmin - ar1->winx < U.widget_unit)
+ ar->flag |= RGN_FLAG_TOO_SMALL;
+ else
+ BLI_rcti_translate(&ar->winrct, -ar1->winx, 0);
+ }
+ }
+
+
+
+}
+
+/* overlapping regions only in the following restricted cases */
+static int region_is_overlap(wmWindow *win, ScrArea *sa, ARegion *ar)
+{
+ if (U.uiflag2 & USER_REGION_OVERLAP)
+ if (WM_is_draw_triple(win))
+ if (ELEM4(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_SEQ, SPACE_CLIP))
+ if (ELEM3(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS))
+ return 1;
+ return 0;
+}
+
+static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti *remainder, int quad)
{
rcti *remainder_prev = remainder;
int prefsizex, prefsizey;
@@ -928,22 +940,26 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int
alignment = ar->alignment & ~RGN_SPLIT_PREV;
+ /* set here, assuming userpref switching forces to call this again */
+ ar->overlap = region_is_overlap(win, sa, ar);
+
/* clear state flags first */
ar->flag &= ~RGN_FLAG_TOO_SMALL;
/* user errors */
if (ar->next == NULL && alignment != RGN_ALIGN_QSPLIT)
alignment = RGN_ALIGN_NONE;
- /* prefsize, for header we stick to exception */
- prefsizex = ar->sizex ? ar->sizex : ar->type->prefsizex;
+ /* prefsize, for header we stick to exception (prevent dpi rounding error) */
+ prefsizex = UI_DPI_FAC * (ar->sizex > 1 ? ar->sizex + 0.5f : ar->type->prefsizex);
+
if (ar->regiontype == RGN_TYPE_HEADER) {
- prefsizey = ar->type->prefsizey;
+ prefsizey = ED_area_headersize();
}
else if (ar->regiontype == RGN_TYPE_UI && sa->spacetype == SPACE_FILE) {
prefsizey = UI_UNIT_Y * 2 + (UI_UNIT_Y / 2);
}
else {
- prefsizey = ar->sizey ? ar->sizey : ar->type->prefsizey;
+ prefsizey = UI_DPI_FAC * (ar->sizey > 1 ? ar->sizey + 0.5f : ar->type->prefsizey);
}
@@ -985,7 +1001,7 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int
}
}
}
- else if (ELEM4(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT, RGN_OVERLAP_LEFT, RGN_OVERLAP_RIGHT)) {
+ else if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
if (rct_fits(remainder, 'h', prefsizex) < 0) {
ar->flag |= RGN_FLAG_TOO_SMALL;
@@ -998,14 +1014,14 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int
ar->winrct = *remainder;
- if (ELEM(alignment, RGN_ALIGN_RIGHT, RGN_OVERLAP_RIGHT)) {
+ if (alignment == RGN_ALIGN_RIGHT) {
ar->winrct.xmin = ar->winrct.xmax - prefsizex + 1;
- if (alignment == RGN_ALIGN_RIGHT)
+ if (ar->overlap == 0)
remainder->xmax = ar->winrct.xmin - 1;
}
else {
ar->winrct.xmax = ar->winrct.xmin + prefsizex - 1;
- if (alignment == RGN_ALIGN_LEFT)
+ if (ar->overlap == 0)
remainder->xmin = ar->winrct.xmax + 1;
}
}
@@ -1053,7 +1069,9 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int
if (G.debug & G_DEBUG)
printf("region quadsplit failed\n");
}
- else quad = 1;
+ else {
+ quad = 1;
+ }
}
if (quad) {
if (quad == 1) { /* left bottom */
@@ -1082,6 +1100,15 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int
ar->winx = BLI_rcti_size_x(&ar->winrct) + 1;
ar->winy = BLI_rcti_size_y(&ar->winrct) + 1;
+ /* if region opened normally, we store this for hide/reveal usage */
+ /* prevent rounding errors for UI_DPI_FAC mult and divide */
+ if (ar->winx > 1) ar->sizex = (ar->winx + 0.5f) / UI_DPI_FAC;
+ if (ar->winy > 1) ar->sizey = (ar->winy + 0.5f) / UI_DPI_FAC;
+
+ /* exception for multiple overlapping regions on same spot */
+ if (ar->overlap)
+ region_overlap_fix(sa, ar);
+
/* set winrect for azones */
if (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) {
ar->winrct = *remainder;
@@ -1090,9 +1117,9 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int
ar->winrct.ymin = ar->winrct.ymax;
else if (alignment == RGN_ALIGN_BOTTOM)
ar->winrct.ymax = ar->winrct.ymin;
- else if (ELEM(alignment, RGN_ALIGN_RIGHT, RGN_OVERLAP_RIGHT))
+ else if (alignment == RGN_ALIGN_RIGHT)
ar->winrct.xmin = ar->winrct.xmax;
- else if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_OVERLAP_LEFT))
+ else if (alignment == RGN_ALIGN_LEFT)
ar->winrct.xmax = ar->winrct.xmin;
else /* prevent winrct to be valid */
ar->winrct.xmax = ar->winrct.xmin;
@@ -1121,12 +1148,12 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int
region_azone_add(sa, ar, alignment);
}
- region_rect_recursive(sa, ar->next, remainder, quad);
+ region_rect_recursive(win, sa, ar->next, remainder, quad);
}
static void area_calc_totrct(ScrArea *sa, int sizex, int sizey)
{
- short rt = 0; // CLAMPIS(G.debug_value, 0, 16);
+ short rt = U.pixelsize > 1.0f ? 1 : 0;
if (sa->v1->vec.x > 0) sa->totrct.xmin = sa->v1->vec.x + 1 + rt;
else sa->totrct.xmin = sa->v1->vec.x;
@@ -1229,14 +1256,14 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
ar->type = BKE_regiontype_from_id(sa->type, ar->regiontype);
/* area sizes */
- area_calc_totrct(sa, win->sizex, win->sizey);
+ area_calc_totrct(sa, WM_window_pixels_x(win), WM_window_pixels_y(win));
/* clear all azones, add the area triange widgets */
area_azone_initialize(win->screen, sa);
/* region rect sizes */
rect = sa->totrct;
- region_rect_recursive(sa, sa->regionbase.first, &rect, 0);
+ region_rect_recursive(win, sa, sa->regionbase.first, &rect, 0);
/* default area handlers */
ed_default_handlers(wm, sa, &sa->handlers, sa->type->keymapflag);
@@ -1273,22 +1300,38 @@ void ED_region_init(bContext *C, ARegion *ar)
ar->winx = BLI_rcti_size_x(&ar->winrct) + 1;
ar->winy = BLI_rcti_size_y(&ar->winrct) + 1;
+ /* v2d mask is used to subtract scrollbars from a 2d view. Needs initialize here. */
+ BLI_rcti_init(&ar->v2d.mask, 0, ar->winx - 1, 0, ar->winy -1);
+
/* UI convention */
wmOrtho2(-0.01f, ar->winx - 0.01f, -0.01f, ar->winy - 0.01f);
glLoadIdentity();
}
-void ED_region_toggle_hidden(bContext *C, ARegion *ar)
+/* for quick toggle, can skip fades */
+void region_toggle_hidden(bContext *C, ARegion *ar, int do_fade)
{
ScrArea *sa = CTX_wm_area(C);
-
+
ar->flag ^= RGN_FLAG_HIDDEN;
+
+ if (do_fade && ar->overlap) {
+ /* starts a timer, and in end calls the stuff below itself (region_sblend_invoke()) */
+ region_blend_start(C, sa, ar);
+ }
+ else {
+ if (ar->flag & RGN_FLAG_HIDDEN)
+ WM_event_remove_handlers(C, &ar->handlers);
+
+ ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
+ ED_area_tag_redraw(sa);
+ }
+}
- if (ar->flag & RGN_FLAG_HIDDEN)
- WM_event_remove_handlers(C, &ar->handlers);
-
- ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
- ED_area_tag_redraw(sa);
+/* exported to all editors, uses fading default */
+void ED_region_toggle_hidden(bContext *C, ARegion *ar)
+{
+ region_toggle_hidden(C, ar, 1);
}
/* sa2 to sa1, we swap spaces for fullscreen to keep all allocated data */
@@ -1441,7 +1484,7 @@ void ED_area_prevspace(bContext *C, ScrArea *sa)
{
SpaceLink *sl = (sa) ? sa->spacedata.first : CTX_wm_space_data(C);
- if (sl->next) {
+ if (sl && sl->next) {
/* workaround for case of double prevspace, render window
* with a file browser on top of it */
if (sl->next->spacetype == SPACE_FILE && sl->next->next)
@@ -1515,22 +1558,22 @@ int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco)
{
ScrArea *sa = CTX_wm_area(C);
uiBut *but;
- int xco = 8;
+ int xco = 0.4 * U.widget_unit;
but = uiDefIconTextButC(block, ICONTEXTROW, 0, ICON_VIEW3D,
- editortype_pup(), xco, yco, UI_UNIT_X + 10, UI_UNIT_Y,
+ editortype_pup(), xco, yco, 1.5 * U.widget_unit, U.widget_unit,
&(sa->butspacetype), 1.0, SPACEICONMAX, 0, 0,
TIP_("Display current editor type (click for a menu of available types)"));
uiButSetFunc(but, spacefunc, NULL, NULL);
uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
- return xco + UI_UNIT_X + 14;
+ return xco + 1.7 * U.widget_unit;
}
int ED_area_header_standardbuttons(const bContext *C, uiBlock *block, int yco)
{
ScrArea *sa = CTX_wm_area(C);
- int xco = 8;
+ int xco = 0.4 * U.widget_unit;
uiBut *but;
if (!sa->full)
@@ -1541,23 +1584,23 @@ int ED_area_header_standardbuttons(const bContext *C, uiBlock *block, int yco)
if (sa->flag & HEADER_NO_PULLDOWN) {
but = uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, 0,
ICON_DISCLOSURE_TRI_RIGHT,
- xco, yco, UI_UNIT_X, UI_UNIT_Y - 2,
+ xco, yco, U.widget_unit, U.widget_unit * 0.9f,
&(sa->flag), 0, 0, 0, 0,
- "Show pulldown menus");
+ TIP_("Show pulldown menus"));
}
else {
but = uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, 0,
ICON_DISCLOSURE_TRI_DOWN,
- xco, yco, UI_UNIT_X, UI_UNIT_Y - 2,
+ xco, yco, U.widget_unit, U.widget_unit * 0.9f,
&(sa->flag), 0, 0, 0, 0,
- "Hide pulldown menus");
+ TIP_("Hide pulldown menus"));
}
uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
uiBlockSetEmboss(block, UI_EMBOSS);
- return xco + UI_UNIT_X;
+ return xco + U.widget_unit;
}
/************************ standard UI regions ************************/
@@ -1565,127 +1608,164 @@ int ED_area_header_standardbuttons(const bContext *C, uiBlock *block, int yco)
void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *context, int contextnr)
{
ScrArea *sa = CTX_wm_area(C);
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_GetStyleDraw();
uiBlock *block;
PanelType *pt;
Panel *panel;
View2D *v2d = &ar->v2d;
View2DScrollers *scrollers;
int x, y, xco, yco, w, em, triangle, open, newcontext = 0;
+ int redo;
+ int scroll;
if (contextnr >= 0)
newcontext = UI_view2d_tab_set(v2d, contextnr);
-
+
+ /* before setting the view */
if (vertical) {
- w = BLI_rctf_size_x(&v2d->cur);
- em = (ar->type->prefsizex) ? UI_UNIT_Y / 2 : UI_UNIT_Y;
+ /* only allow scrolling in vertical direction */
+ v2d->keepofs |= V2D_LOCKOFS_X | V2D_KEEPOFS_Y;
+ v2d->keepofs &= ~(V2D_LOCKOFS_Y | V2D_KEEPOFS_X);
+ v2d->scroll &= ~(V2D_SCROLL_BOTTOM);
+ v2d->scroll |= (V2D_SCROLL_RIGHT);
}
else {
- w = UI_PANEL_WIDTH;
- em = (ar->type->prefsizex) ? UI_UNIT_Y / 2 : UI_UNIT_Y;
+ /* for now, allow scrolling in both directions (since layouts are optimized for vertical,
+ * they often don't fit in horizontal layout)
+ */
+ v2d->keepofs &= ~(V2D_LOCKOFS_X | V2D_LOCKOFS_Y | V2D_KEEPOFS_X | V2D_KEEPOFS_Y);
+ v2d->scroll |= (V2D_SCROLL_BOTTOM);
+ v2d->scroll &= ~(V2D_SCROLL_RIGHT);
}
- /* create panels */
- uiBeginPanels(C, ar);
+ scroll = v2d->scroll;
+
+ /* sortof hack - but we cannot predict the height of panels, until it's being generated */
+ /* the layout engine works with fixed width (from v2d->cur), which is being set at end of the loop */
+ /* in case scroller settings (hide flags) differ from previous, the whole loop gets done again */
+ for (redo = 2; redo > 0; redo--) {
+
+ if (vertical) {
+ w = BLI_rctf_size_x(&v2d->cur);
+ em = (ar->type->prefsizex) ? UI_UNIT_Y / 2 : UI_UNIT_Y;
+ }
+ else {
+ w = UI_PANEL_WIDTH;
+ em = (ar->type->prefsizex) ? UI_UNIT_Y / 2 : UI_UNIT_Y;
+ }
+
+ /* create panels */
+ uiBeginPanels(C, ar);
- /* set view2d view matrix for scrolling (without scrollers) */
- UI_view2d_view_ortho(v2d);
+ /* set view2d view matrix - uiBeginBlock() stores it */
+ UI_view2d_view_ortho(v2d);
- for (pt = ar->type->paneltypes.first; pt; pt = pt->next) {
- /* verify context */
- if (context)
- if (pt->context[0] && strcmp(context, pt->context) != 0)
- continue;
+ for (pt = ar->type->paneltypes.first; pt; pt = pt->next) {
+ /* verify context */
+ if (context)
+ if (pt->context[0] && strcmp(context, pt->context) != 0)
+ continue;
- /* draw panel */
- if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
- block = uiBeginBlock(C, ar, pt->idname, UI_EMBOSS);
- panel = uiBeginPanel(sa, ar, block, pt, &open);
+ /* draw panel */
+ if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
+ block = uiBeginBlock(C, ar, pt->idname, UI_EMBOSS);
+ panel = uiBeginPanel(sa, ar, block, pt, &open);
- /* bad fixed values */
- triangle = (int)(UI_UNIT_Y * 1.1f);
+ /* bad fixed values */
+ triangle = (int)(UI_UNIT_Y * 1.1f);
- if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
- /* for enabled buttons */
- panel->layout = uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
- triangle, UI_UNIT_Y + style->panelspace + 2, UI_UNIT_Y, 1, style);
+ if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
+ /* for enabled buttons */
+ panel->layout = uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
+ triangle, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, style);
- pt->draw_header(C, panel);
+ pt->draw_header(C, panel);
- uiBlockLayoutResolve(block, &xco, &yco);
- panel->labelofs = xco - triangle;
- panel->layout = NULL;
- }
- else {
- panel->labelofs = 0;
- }
+ uiBlockLayoutResolve(block, &xco, &yco);
+ panel->labelofs = xco - triangle;
+ panel->layout = NULL;
+ }
+ else {
+ panel->labelofs = 0;
+ }
- if (open) {
- short panelContext;
-
- /* panel context can either be toolbar region or normal panels region */
- if (ar->regiontype == RGN_TYPE_TOOLS)
- panelContext = UI_LAYOUT_TOOLBAR;
- else
- panelContext = UI_LAYOUT_PANEL;
-
- panel->layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, panelContext,
- style->panelspace, 0, w - 2 * style->panelspace, em, style);
+ if (open) {
+ short panelContext;
+
+ /* panel context can either be toolbar region or normal panels region */
+ if (ar->regiontype == RGN_TYPE_TOOLS)
+ panelContext = UI_LAYOUT_TOOLBAR;
+ else
+ panelContext = UI_LAYOUT_PANEL;
+
+ panel->layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, panelContext,
+ style->panelspace, 0, w - 2 * style->panelspace, em, style);
- pt->draw(C, panel);
+ pt->draw(C, panel);
- uiBlockLayoutResolve(block, &xco, &yco);
- panel->layout = NULL;
+ uiBlockLayoutResolve(block, &xco, &yco);
+ panel->layout = NULL;
- yco -= 2 * style->panelspace;
- uiEndPanel(block, w, -yco);
- }
- else {
- yco = 0;
- uiEndPanel(block, w, 0);
+ yco -= 2 * style->panelspace;
+ uiEndPanel(block, w, -yco);
+ }
+ else {
+ yco = 0;
+ uiEndPanel(block, w, 0);
+ }
+
+ uiEndBlock(C, block);
}
+ }
- uiEndBlock(C, block);
+ /* align panels and return size */
+ uiEndPanels(C, ar, &x, &y);
+
+ /* before setting the view */
+ if (vertical) {
+ /* we always keep the scroll offset - so the total view gets increased with the scrolled away part */
+ if (v2d->cur.ymax < - 0.001f)
+ y = min_ii(y, v2d->cur.ymin);
+
+ y = -y;
+ }
+ else {
+ /* don't jump back when panels close or hide */
+ if (!newcontext)
+ x = max_ii(x, v2d->cur.xmax);
+ y = -y;
+ }
+
+ /* this also changes the 'cur' */
+ UI_view2d_totRect_set(v2d, x, y);
+
+ if (scroll != v2d->scroll) {
+ /* Note: this code scales fine, but because of rounding differences, positions of elements
+ * flip +1 or -1 pixel compared to redoing the entire layout again.
+ * Leaving in commented code for future tests */
+ /* uiScalePanels(ar, BLI_rctf_size_x(&v2d->cur));
+ break; */
+ }
+ else {
+ break;
}
}
-
- /* align panels and return size */
- uiEndPanels(C, ar, &x, &y);
-
- /* clear */
- UI_ThemeClearColor((ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
- /* before setting the view */
- if (vertical) {
- /* only allow scrolling in vertical direction */
- v2d->keepofs |= V2D_LOCKOFS_X | V2D_KEEPOFS_Y;
- v2d->keepofs &= ~(V2D_LOCKOFS_Y | V2D_KEEPOFS_X);
- v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
- v2d->scroll &= ~V2D_SCROLL_VERTICAL_HIDE;
-
- /* ensure tot is set correctly, to keep views on bottons, with sliders */
- y = min_ii(y, v2d->cur.ymin);
- y = -y;
+
+ /* clear */
+ if (ar->overlap) {
+ /* view should be in pixelspace */
+ 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));
+ glDisable(GL_BLEND);
}
else {
- /* for now, allow scrolling in both directions (since layouts are optimized for vertical,
- * they often don't fit in horizontal layout)
- */
- v2d->keepofs &= ~(V2D_LOCKOFS_X | V2D_LOCKOFS_Y | V2D_KEEPOFS_X | V2D_KEEPOFS_Y);
- //v2d->keepofs |= V2D_LOCKOFS_Y|V2D_KEEPOFS_X;
- //v2d->keepofs &= ~(V2D_LOCKOFS_X|V2D_KEEPOFS_Y);
- v2d->scroll |= V2D_SCROLL_VERTICAL_HIDE;
- v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_HIDE;
-
- /* don't jump back when panels close or hide */
- if (!newcontext)
- x = max_ii(x, v2d->cur.xmax);
- y = -y;
+ UI_ThemeClearColor((ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK);
+ glClear(GL_COLOR_BUFFER_BIT);
}
-
- /* +V2D_SCROLL_HEIGHT is workaround to set the actual height */
- UI_view2d_totRect_set(v2d, x + V2D_SCROLL_WIDTH, y + V2D_SCROLL_HEIGHT);
+
/* set the view */
UI_view2d_view_ortho(v2d);
@@ -1705,17 +1785,6 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
void ED_region_panels_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
-
- /* XXX quick hacks for files saved with 2.5 already (i.e. the builtin defaults file)
- * scrollbars for button regions */
- ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
- ar->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
- ar->v2d.scroll &= ~V2D_SCROLL_VERTICAL_HIDE;
- ar->v2d.keepzoom |= V2D_KEEPZOOM;
-
- /* correctly initialized User-Prefs? */
- if (!(ar->v2d.align & V2D_ALIGN_NO_POS_Y))
- ar->v2d.flag &= ~V2D_IS_INITIALISED;
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy);
@@ -1725,7 +1794,7 @@ void ED_region_panels_init(wmWindowManager *wm, ARegion *ar)
void ED_region_header(const bContext *C, ARegion *ar)
{
- uiStyle *style = UI_GetStyle();
+ uiStyle *style = UI_GetStyleDraw();
uiBlock *block;
uiLayout *layout;
HeaderType *ht;
@@ -1740,8 +1809,8 @@ void ED_region_header(const bContext *C, ARegion *ar)
/* set view2d view matrix for scrolling (without scrollers) */
UI_view2d_view_ortho(&ar->v2d);
- xco = maxco = 8;
- yco = headery - 4;
+ xco = maxco = 0.4f * UI_UNIT_X;
+ yco = headery - floor(0.2f * UI_UNIT_Y);
/* draw all headers types */
for (ht = ar->type->headertypes.first; ht; ht = ht->next) {
@@ -1778,35 +1847,30 @@ void ED_region_header(const bContext *C, ARegion *ar)
void ED_region_header_init(ARegion *ar)
{
+ ar->v2d.flag &= ~V2D_IS_INITIALISED;
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
}
/* UI_UNIT_Y is defined as U variable now, depending dpi */
int ED_area_headersize(void)
{
- return UI_UNIT_Y + 6;
+ return (int)(1.3f * UI_UNIT_Y);
}
void ED_region_info_draw(ARegion *ar, const char *text, int block, float alpha)
{
- const int header_height = 18;
- uiStyle *style = UI_GetStyle();
+ const int header_height = UI_UNIT_Y;
+ uiStyle *style = UI_GetStyleDraw();
int fontid = style->widget.uifont_id;
rcti rect;
- BLF_size(fontid, 11.0f, 72);
-
/* background box */
- rect = ar->winrct;
- rect.xmin = 0;
+ ED_region_visible_rect(ar, &rect);
rect.ymin = BLI_rcti_size_y(&ar->winrct) - header_height;
- if (block) {
- rect.xmax = BLI_rcti_size_x(&ar->winrct);
- }
- else {
- rect.xmax = rect.xmin + BLF_width(fontid, text) + 24;
- }
+ /* box fill entire width or just around text */
+ if (!block)
+ rect.xmax = min_ii(rect.xmax, rect.xmin + BLF_width(fontid, text) + 1.2f * U.widget_unit);
rect.ymax = BLI_rcti_size_y(&ar->winrct);
@@ -1818,8 +1882,13 @@ void ED_region_info_draw(ARegion *ar, const char *text, int block, float alpha)
/* text */
UI_ThemeColor(TH_TEXT_HI);
- BLF_position(fontid, 12, rect.ymin + 5, 0.0f);
+ BLF_clipping(fontid, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ BLF_enable(fontid, BLF_CLIPPING);
+ BLF_position(fontid, rect.xmin + 0.6f * U.widget_unit, rect.ymin + 0.3f * U.widget_unit, 0.0f);
+
BLF_draw(fontid, text, BLF_DRAW_STR_DUMMY_MAX);
+
+ BLF_disable(fontid, BLF_CLIPPING);
}
void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
@@ -1881,3 +1950,34 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
}
glEnd();
}
+
+/* If the area has overlapping regions, it returns visible rect for Region *ar */
+/* rect gets returned in local region coordinates */
+void ED_region_visible_rect(ARegion *ar, rcti *rect)
+{
+ ARegion *arn = ar;
+
+ /* allow function to be called without area */
+ while (arn->prev)
+ arn = arn->prev;
+
+ *rect = ar->winrct;
+
+ /* check if a region overlaps with the current one */
+ for (; arn; arn = arn->next) {
+ if (ar != arn && arn->overlap) {
+ if (BLI_rcti_isect(rect, &arn->winrct, NULL)) {
+
+ /* overlap left, also check 1 pixel offset (2 regions on one side) */
+ if (ABS(rect->xmin - arn->winrct.xmin) < 2)
+ rect->xmin = arn->winrct.xmax;
+
+ /* overlap right */
+ if (ABS(rect->xmax - arn->winrct.xmax) < 2)
+ rect->xmax = arn->winrct.xmin;
+ }
+ }
+ }
+ BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->winrct.ymin);
+}
+
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index ce2d045dc80..8501b53afae 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -33,16 +33,17 @@
#include "MEM_guardedalloc.h"
+#include "DNA_userdef_types.h"
#include "DNA_vec_types.h"
#include "BLI_rect.h"
#include "BLI_utildefines.h"
-
-#include "BKE_colortools.h"
-
#include "BLI_math.h"
#include "BLI_threads.h"
+#include "BKE_blender.h"
+#include "BKE_colortools.h"
+
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -54,7 +55,7 @@
/* ******************************************** */
/* defined in BIF_gl.h */
-GLubyte stipple_halftone[128] = {
+const GLubyte stipple_halftone[128] = {
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
@@ -81,7 +82,7 @@ GLubyte stipple_halftone[128] = {
* 00000000 */
-GLubyte stipple_quarttone[128] = {
+const GLubyte stipple_quarttone[128] = {
136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
@@ -92,7 +93,7 @@ GLubyte stipple_quarttone[128] = {
136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0};
-GLubyte stipple_diag_stripes_pos[128] = {
+const GLubyte stipple_diag_stripes_pos[128] = {
0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
@@ -111,7 +112,7 @@ GLubyte stipple_diag_stripes_pos[128] = {
0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f};
-GLubyte stipple_diag_stripes_neg[128] = {
+const GLubyte stipple_diag_stripes_neg[128] = {
0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
@@ -292,7 +293,10 @@ void setlinestyle(int nr)
else {
glEnable(GL_LINE_STIPPLE);
- glLineStipple(nr, 0xAAAA);
+ if (U.pixelsize > 1.0f)
+ glLineStipple(nr, 0xCCCC);
+ else
+ glLineStipple(nr, 0xAAAA);
}
}
@@ -478,7 +482,7 @@ static int get_cached_work_texture(int *w_r, int *h_r)
return texid;
}
-void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, void *rect, float scaleX, float scaleY)
+void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect, float scaleX, float scaleY)
{
unsigned char *uc_rect = (unsigned char *) rect;
float *f_rect = (float *)rect;
@@ -499,6 +503,7 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
/* don't want nasty border artifacts */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, zoomfilter);
#ifdef __APPLE__
/* workaround for os x 10.5/10.6 driver bug: http://lists.apple.com/archives/Mac-opengl/2008/Jul/msg00117.html */
@@ -556,10 +561,10 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f((float)(0 + offset_left) / tex_w, (float)(0 + offset_bot) / tex_h);
- glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * xzoom);
+ glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * yzoom);
glTexCoord2f((float)(subpart_w - offset_right) / tex_w, (float)(0 + offset_bot) / tex_h);
- glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)offset_bot * xzoom);
+ glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)offset_bot * yzoom);
glTexCoord2f((float)(subpart_w - offset_right) / tex_w, (float)(subpart_h - offset_top) / tex_h);
glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
@@ -581,9 +586,9 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format,
#endif
}
-void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, void *rect)
+void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect)
{
- glaDrawPixelsTexScaled(x, y, img_w, img_h, format, rect, 1.0f, 1.0f);
+ glaDrawPixelsTexScaled(x, y, img_w, img_h, format, zoomfilter, rect, 1.0f, 1.0f);
}
void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect)
@@ -665,6 +670,22 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo
}
}
+/* uses either DrawPixelsSafe or DrawPixelsTex, based on user defined maximum */
+void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect)
+{
+ if (U.image_gpubuffer_limit) {
+ /* Megapixels, use float math to prevent overflow */
+ float img_size = ((float)img_w * (float)img_h) / (1024.0f * 1024.0f);
+
+ if (U.image_gpubuffer_limit > (int)img_size) {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glaDrawPixelsTex(x, y, img_w, img_h, format, zoomfilter, rect);
+ return;
+ }
+ }
+ glaDrawPixelsSafe(x, y, img_w, img_h, img_w, GL_RGBA, format, rect);
+}
+
/* 2D Drawing Assistance */
void glaDefine2DArea(rcti *screen_rect)
@@ -803,7 +824,9 @@ void bglBegin(int mode)
pointhack = floor(value[0] + 0.5f);
if (pointhack > 4) pointhack = 4;
}
- else glBegin(mode);
+ else {
+ glBegin(mode);
+ }
}
}
@@ -831,7 +854,9 @@ void bglVertex3fv(const float vec[3])
glRasterPos3fv(vec);
glBitmap(pointhack, pointhack, (float)pointhack / 2.0f, (float)pointhack / 2.0f, 0.0, 0.0, Squaredot);
}
- else glVertex3fv(vec);
+ else {
+ glVertex3fv(vec);
+ }
break;
}
}
@@ -844,7 +869,9 @@ void bglVertex3f(float x, float y, float z)
glRasterPos3f(x, y, z);
glBitmap(pointhack, pointhack, (float)pointhack / 2.0f, (float)pointhack / 2.0f, 0.0, 0.0, Squaredot);
}
- else glVertex3f(x, y, z);
+ else {
+ glVertex3f(x, y, z);
+ }
break;
}
}
@@ -857,7 +884,9 @@ void bglVertex2fv(const float vec[2])
glRasterPos2fv(vec);
glBitmap(pointhack, pointhack, (float)pointhack / 2, pointhack / 2, 0.0, 0.0, Squaredot);
}
- else glVertex2fv(vec);
+ else {
+ glVertex2fv(vec);
+ }
break;
}
}
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 60aad14efcf..bf458290b09 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -194,7 +194,9 @@ void removenotused_scrverts(bScreen *sc)
BLI_remlink(&sc->vertbase, sv);
MEM_freeN(sv);
}
- else sv->flag = 0;
+ else {
+ sv->flag = 0;
+ }
sv = svn;
}
}
@@ -250,7 +252,9 @@ void removenotused_scredges(bScreen *sc)
BLI_remlink(&sc->edgebase, se);
MEM_freeN(se);
}
- else se->flag = 0;
+ else {
+ se->flag = 0;
+ }
se = sen;
}
}
@@ -263,6 +267,9 @@ int scredge_is_horizontal(ScrEdge *se)
ScrEdge *screen_find_active_scredge(bScreen *sc, int mx, int my)
{
ScrEdge *se;
+ int safety = U.widget_unit / 10;
+
+ if (safety < 2) safety = 2;
for (se = sc->edgebase.first; se; se = se->next) {
if (scredge_is_horizontal(se)) {
@@ -270,7 +277,7 @@ ScrEdge *screen_find_active_scredge(bScreen *sc, int mx, int my)
min = MIN2(se->v1->vec.x, se->v2->vec.x);
max = MAX2(se->v1->vec.x, se->v2->vec.x);
- if (abs(my - se->v1->vec.y) <= 2 && mx >= min && mx <= max)
+ if (abs(my - se->v1->vec.y) <= safety && mx >= min && mx <= max)
return se;
}
else {
@@ -278,7 +285,7 @@ ScrEdge *screen_find_active_scredge(bScreen *sc, int mx, int my)
min = MIN2(se->v1->vec.y, se->v2->vec.y);
max = MAX2(se->v1->vec.y, se->v2->vec.y);
- if (abs(mx - se->v1->vec.x) <= 2 && my >= min && my <= max)
+ if (abs(mx - se->v1->vec.x) <= safety && my >= min && my <= max)
return se;
}
}
@@ -428,9 +435,9 @@ bScreen *ED_screen_add(wmWindow *win, Scene *scene, const char *name)
sc->winid = win->winid;
sv1 = screen_addvert(sc, 0, 0);
- sv2 = screen_addvert(sc, 0, win->sizey - 1);
- sv3 = screen_addvert(sc, win->sizex - 1, win->sizey - 1);
- sv4 = screen_addvert(sc, win->sizex - 1, 0);
+ sv2 = screen_addvert(sc, 0, WM_window_pixels_y(win) - 1);
+ sv3 = screen_addvert(sc, WM_window_pixels_x(win) - 1, WM_window_pixels_y(win) - 1);
+ sv4 = screen_addvert(sc, WM_window_pixels_x(win) - 1, 0);
screen_addedge(sc, sv1, sv2);
screen_addedge(sc, sv2, sv3);
@@ -628,7 +635,7 @@ static void screen_test_scale(bScreen *sc, int winsizex, int winsizey)
float facx, facy, tempf, min[2], max[2];
/* calculate size */
- min[0] = min[1] = 10000.0f;
+ min[0] = min[1] = 20000.0f;
max[0] = max[1] = 0.0f;
for (sv = sc->vertbase.first; sv; sv = sv->next) {
@@ -676,7 +683,7 @@ static void screen_test_scale(bScreen *sc, int winsizex, int winsizey)
/* make each window at least ED_area_headersize() high */
for (sa = sc->areabase.first; sa; sa = sa->next) {
- int headery = ED_area_headersize() + 1;
+ int headery = ED_area_headersize() + U.pixelsize;
if (sa->v1->vec.y + headery > sa->v2->vec.y) {
/* lower edge */
@@ -907,18 +914,18 @@ static void drawscredge_area(ScrArea *sa, int sizex, int sizey, int center)
short y1 = sa->v1->vec.y;
short x2 = sa->v3->vec.x;
short y2 = sa->v3->vec.y;
- short a, rt;
-
- rt = 0; // CLAMPIS(G.debug_value, 0, 16);
if (center == 0) {
- cpack(0x505050);
- for (a = -rt; a <= rt; a++)
- if (a != 0)
- drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2, a);
+ if (U.pixelsize > 1.0f) {
+
+ glColor3ub(0x50, 0x50, 0x50);
+ glLineWidth(1.5f * U.pixelsize);
+ drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2, 0);
+ glLineWidth(1.0f);
+ }
}
else {
- cpack(0x0);
+ glColor3ub(0, 0, 0);
drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2, 0);
}
}
@@ -1002,10 +1009,10 @@ void ED_screen_draw(wmWindow *win)
if (sa->flag & AREA_FLAG_DRAWJOINFROM) sa1 = sa;
if (sa->flag & AREA_FLAG_DRAWJOINTO) sa2 = sa;
if (sa->flag & (AREA_FLAG_DRAWSPLIT_H | AREA_FLAG_DRAWSPLIT_V)) sa3 = sa;
- drawscredge_area(sa, win->sizex, win->sizey, 0);
+ drawscredge_area(sa, WM_window_pixels_x(win), WM_window_pixels_y(win), 0);
}
for (sa = win->screen->areabase.first; sa; sa = sa->next)
- drawscredge_area(sa, win->sizex, win->sizey, 1);
+ drawscredge_area(sa, WM_window_pixels_x(win), WM_window_pixels_y(win), 1);
/* blended join arrow */
if (sa1 && sa2) {
@@ -1078,20 +1085,20 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
rcti winrct;
winrct.xmin = 0;
- winrct.xmax = win->sizex - 1;
+ winrct.xmax = WM_window_pixels_x(win) - 1;
winrct.ymin = 0;
- winrct.ymax = win->sizey - 1;
+ winrct.ymax = WM_window_pixels_y(win) - 1;
+
+ /* header size depends on DPI, let's verify */
+ screen_refresh_headersizes();
- screen_test_scale(win->screen, win->sizex, win->sizey);
+ screen_test_scale(win->screen, WM_window_pixels_x(win), WM_window_pixels_y(win));
if (win->screen->mainwin == 0)
win->screen->mainwin = wm_subwindow_open(win, &winrct);
else
wm_subwindow_position(win, win->screen->mainwin, &winrct);
- /* header size depends on DPI, let's verify */
- screen_refresh_headersizes();
-
for (sa = win->screen->areabase.first; sa; sa = sa->next) {
/* set spacetype and region callbacks, calls init() */
/* sets subwindows for regions, adds handlers */
@@ -1130,8 +1137,12 @@ void ED_screens_initialize(wmWindowManager *wm)
void ED_region_exit(bContext *C, ARegion *ar)
{
+ wmWindowManager *wm = CTX_wm_manager(C);
ARegion *prevar = CTX_wm_region(C);
+ if (ar->type && ar->type->exit)
+ ar->type->exit(wm, ar);
+
CTX_wm_region_set(C, ar);
WM_event_remove_handlers(C, &ar->handlers);
if (ar->swinid)
@@ -1142,23 +1153,20 @@ void ED_region_exit(bContext *C, ARegion *ar)
MEM_freeN(ar->headerstr);
ar->headerstr = NULL;
+ if (ar->regiontimer)
+ WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), ar->regiontimer);
+
CTX_wm_region_set(C, prevar);
}
void ED_area_exit(bContext *C, ScrArea *sa)
{
+ wmWindowManager *wm = CTX_wm_manager(C);
ScrArea *prevsa = CTX_wm_area(C);
ARegion *ar;
- if (sa->spacetype == SPACE_FILE) {
- SpaceLink *sl = sa->spacedata.first;
- if (sl && sl->spacetype == SPACE_FILE) {
- ED_fileselect_exit(C, (SpaceFile *)sl);
- }
- }
- else if (sa->spacetype == SPACE_VIEW3D) {
- ED_render_engine_area_exit(sa);
- }
+ if (sa->type && sa->type->exit)
+ sa->type->exit(wm, sa);
CTX_wm_area_set(C, sa);
for (ar = sa->regionbase.first; ar; ar = ar->next)
@@ -1262,9 +1270,12 @@ void ED_screen_set_subwinactive(bContext *C, wmEvent *event)
break;
}
if (sa) {
+ /* make overlap active when mouse over */
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (BLI_rcti_isect_pt_v(&ar->winrct, &event->x))
+ if (BLI_rcti_isect_pt_v(&ar->winrct, &event->x)) {
scr->subwinactive = ar->swinid;
+ break;
+ }
}
}
else
@@ -1293,6 +1304,7 @@ void ED_screen_set_subwinactive(bContext *C, wmEvent *event)
screen_cursor_set(win, event);
}
else {
+ /* notifier invokes freeing the buttons... causing a bit too much redraws */
if (oldswin != scr->subwinactive) {
region_cursor_set(win, scr->subwinactive, TRUE);
WM_event_add_notifier(C, NC_SCREEN | ND_SUBWINACTIVE, scr);
@@ -1327,13 +1339,14 @@ int ED_screen_area_active(const bContext *C)
/* Do NOT call in area/region queues! */
void 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 = CTX_data_main(C)->screen.first; id; id = id->next)
+ for (id = bmain->screen.first; id; id = id->next)
if (sc == (bScreen *)id)
break;
if (id == NULL)
@@ -1345,7 +1358,7 @@ void ED_screen_set(bContext *C, bScreen *sc)
if (sc->full) { /* find associated full */
bScreen *sc1;
- for (sc1 = CTX_data_main(C)->screen.first; sc1; sc1 = sc1->id.next) {
+ for (sc1 = bmain->screen.first; sc1; sc1 = sc1->id.next) {
ScrArea *sa = sc1->areabase.first;
if (sa->full == sc) {
sc = sc1;
@@ -1445,7 +1458,7 @@ void ED_screen_set_scene(bContext *C, bScreen *screen, Scene *scene)
return;
if (ed_screen_used(CTX_wm_manager(C), screen))
- ED_object_exit_editmode(C, EM_FREEDATA | EM_DO_UNDO);
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_DO_UNDO);
for (sc = CTX_data_main(C)->screen.first; sc; sc = sc->id.next) {
if ((U.flag & USER_SCENEGLOBAL) || sc == screen) {
diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h
index 86d99777e98..b811fc46188 100644
--- a/source/blender/editors/screen/screen_intern.h
+++ b/source/blender/editors/screen/screen_intern.h
@@ -35,10 +35,11 @@
struct wmWindow;
struct Scene;
-#define AZONESPOT 12
+#define AZONESPOT (0.6f * U.widget_unit)
/* area.c */
void area_copy_data(ScrArea *sa1, ScrArea *sa2, int swap_space);
+void region_toggle_hidden(bContext *C, ARegion *ar, int do_fade);
/* screen_edit.c */
ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2);
@@ -57,12 +58,16 @@ ScrEdge *screen_find_active_scredge(bScreen *sc, int mx, int my);
struct AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2]);
/* screen_context.c */
-int ed_screen_context(const bContext *C, const char *member, bContextDataResult *result);
+int ed_screen_context(const bContext *C, const char *member, bContextDataResult *result);
extern const char *screen_context_dir[]; /* doc access */
/* screendump.c */
-void SCREEN_OT_screenshot(struct wmOperatorType *ot);
-void SCREEN_OT_screencast(struct wmOperatorType *ot);
+void SCREEN_OT_screenshot(struct wmOperatorType *ot);
+void SCREEN_OT_screencast(struct wmOperatorType *ot);
+
+/* screen_ops.c */
+void region_blend_start(struct bContext *C, struct ScrArea *sa, struct ARegion *ar);
+
#endif /* __SCREEN_INTERN_H__ */
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 67d4af916aa..d5d5add215c 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -47,6 +47,7 @@
#include "DNA_meta_types.h"
#include "DNA_mesh_types.h"
#include "DNA_mask_types.h"
+#include "DNA_node_types.h"
#include "DNA_userdef_types.h"
#include "BKE_context.h"
@@ -54,6 +55,7 @@
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
+#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -140,9 +142,11 @@ static int screen_active_editable(bContext *C)
/* when mouse is over area-edge */
int ED_operator_screen_mainwinactive(bContext *C)
{
+ bScreen *screen;
if (CTX_wm_window(C) == NULL) return 0;
- if (CTX_wm_screen(C) == NULL) return 0;
- if (CTX_wm_screen(C)->subwinactive != CTX_wm_screen(C)->mainwin) return 0;
+ screen = CTX_wm_screen(C);
+ if (screen == NULL) return 0;
+ if (screen->subwinactive != screen->mainwin) return 0;
return 1;
}
@@ -204,7 +208,7 @@ int ED_operator_animview_active(bContext *C)
return TRUE;
}
- CTX_wm_operator_poll_msg_set(C, "expected an timeline/animation area to be active");
+ CTX_wm_operator_poll_msg_set(C, "expected a timeline/animation area to be active");
return 0;
}
@@ -358,7 +362,7 @@ int ED_operator_editarmature(bContext *C)
/**
* \brief check for pose mode (no mixed modes)
*
- * We wan't to enable most pose operations in weight paint mode,
+ * We want to enable most pose operations in weight paint mode,
* when it comes to transforming bones, but managing bomes layers/groups
* can be left for pose mode only. (not weight paint mode)
*/
@@ -642,7 +646,7 @@ static void actionzone_apply(bContext *C, wmOperator *op, int type)
wm_event_add(win, &event);
}
-static int actionzone_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
AZone *az = is_in_area_actionzone(CTX_wm_area(C), &event->x);
sActionzoneData *sad;
@@ -672,7 +676,7 @@ static int actionzone_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
-static int actionzone_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
sActionzoneData *sad = op->customdata;
int deltax, deltay;
@@ -727,7 +731,7 @@ static int actionzone_cancel(bContext *UNUSED(C), wmOperator *op)
static void SCREEN_OT_actionzone(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Handle area action zones";
+ ot->name = "Handle Area Action Zones";
ot->description = "Handle area action zones for mouse actions/gestures";
ot->idname = "SCREEN_OT_actionzone";
@@ -767,7 +771,7 @@ typedef struct sAreaSwapData {
ScrArea *sa1, *sa2;
} sAreaSwapData;
-static int area_swap_init(wmOperator *op, wmEvent *event)
+static int area_swap_init(wmOperator *op, const wmEvent *event)
{
sAreaSwapData *sd = NULL;
sActionzoneData *sad = event->customdata;
@@ -798,7 +802,7 @@ static int area_swap_cancel(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int area_swap_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int area_swap_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (!area_swap_init(op, event))
@@ -812,7 +816,7 @@ static int area_swap_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
-static int area_swap_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int area_swap_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
sActionzoneData *sad = op->customdata;
@@ -849,7 +853,7 @@ static int area_swap_modal(bContext *C, wmOperator *op, wmEvent *event)
static void SCREEN_OT_area_swap(wmOperatorType *ot)
{
- ot->name = "Swap areas";
+ ot->name = "Swap Areas";
ot->description = "Swap selected areas screen positions";
ot->idname = "SCREEN_OT_area_swap";
@@ -864,7 +868,7 @@ static void SCREEN_OT_area_swap(wmOperatorType *ot)
/* *********** Duplicate area as new window operator ****************** */
/* operator callback */
-static int area_dupli_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
wmWindow *newwin, *win;
bScreen *newsc, *sc;
@@ -965,7 +969,7 @@ typedef struct sAreaMoveData {
static void area_move_set_limits(bScreen *sc, int dir, int *bigger, int *smaller)
{
ScrArea *sa;
- int areaminy = ED_area_headersize() + 1;
+ int areaminy = ED_area_headersize() + U.pixelsize; // pixelsize is used as area divider
/* we check all areas and test for free space with MINSIZE */
*bigger = *smaller = 100000;
@@ -975,18 +979,18 @@ static void area_move_set_limits(bScreen *sc, int dir, int *bigger, int *smaller
int y1 = sa->v2->vec.y - sa->v1->vec.y - areaminy;
/* if top or down edge selected, test height */
- if (sa->v1->flag && sa->v4->flag)
+ if (sa->v1->editflag && sa->v4->editflag)
*bigger = min_ii(*bigger, y1);
- else if (sa->v2->flag && sa->v3->flag)
+ else if (sa->v2->editflag && sa->v3->editflag)
*smaller = min_ii(*smaller, y1);
}
else {
int x1 = sa->v4->vec.x - sa->v1->vec.x - AREAMINX;
/* if left or right edge selected, test width */
- if (sa->v1->flag && sa->v2->flag)
+ if (sa->v1->editflag && sa->v2->editflag)
*bigger = min_ii(*bigger, x1);
- else if (sa->v3->flag && sa->v4->flag)
+ else if (sa->v3->editflag && sa->v4->editflag)
*smaller = min_ii(*smaller, x1);
}
}
@@ -999,6 +1003,7 @@ static int area_move_init(bContext *C, wmOperator *op)
bScreen *sc = CTX_wm_screen(C);
ScrEdge *actedge;
sAreaMoveData *md;
+ ScrVert *v1;
int x, y;
/* required properties */
@@ -1017,7 +1022,9 @@ static int area_move_init(bContext *C, wmOperator *op)
else md->origval = actedge->v1->vec.x;
select_connected_scredge(sc, actedge);
- /* now all vertices with 'flag==1' are the ones that can be moved. */
+ /* now all vertices with 'flag==1' are the ones that can be moved. Move this to editflag */
+ for (v1 = sc->vertbase.first; v1; v1 = v1->next)
+ v1->editflag = v1->flag;
area_move_set_limits(sc, md->dir, &md->bigger, &md->smaller);
@@ -1036,27 +1043,27 @@ static void area_move_apply_do(bContext *C, int origval, int delta, int dir, int
delta = CLAMPIS(delta, -smaller, bigger);
for (v1 = sc->vertbase.first; v1; v1 = v1->next) {
- if (v1->flag) {
+ if (v1->editflag) {
/* that way a nice AREAGRID */
- if ((dir == 'v') && v1->vec.x > 0 && v1->vec.x < win->sizex - 1) {
+ if ((dir == 'v') && v1->vec.x > 0 && v1->vec.x < WM_window_pixels_x(win) - 1) {
v1->vec.x = origval + delta;
if (delta != bigger && delta != -smaller) v1->vec.x -= (v1->vec.x % AREAGRID);
}
- if ((dir == 'h') && v1->vec.y > 0 && v1->vec.y < win->sizey - 1) {
+ if ((dir == 'h') && v1->vec.y > 0 && v1->vec.y < WM_window_pixels_y(win) - 1) {
v1->vec.y = origval + delta;
v1->vec.y += AREAGRID - 1;
v1->vec.y -= (v1->vec.y % AREAGRID);
/* prevent too small top header */
- if (v1->vec.y > win->sizey - areaminy)
- v1->vec.y = win->sizey - areaminy;
+ if (v1->vec.y > WM_window_pixels_y(win) - areaminy)
+ v1->vec.y = WM_window_pixels_y(win) - areaminy;
}
}
}
for (sa = sc->areabase.first; sa; sa = sa->next) {
- if (sa->v1->flag || sa->v2->flag || sa->v3->flag || sa->v4->flag)
+ if (sa->v1->editflag || sa->v2->editflag || sa->v3->editflag || sa->v4->editflag)
ED_area_tag_redraw(sa);
}
@@ -1095,7 +1102,7 @@ static int area_move_exec(bContext *C, wmOperator *op)
}
/* interaction callback */
-static int area_move_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int area_move_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
RNA_int_set(op->ptr, "x", event->x);
RNA_int_set(op->ptr, "y", event->y);
@@ -1120,7 +1127,7 @@ static int area_move_cancel(bContext *C, wmOperator *op)
}
/* modal callback for while moving edges */
-static int area_move_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int area_move_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
sAreaMoveData *md = op->customdata;
int delta, x, y;
@@ -1164,7 +1171,7 @@ static int area_move_modal(bContext *C, wmOperator *op, wmEvent *event)
static void SCREEN_OT_area_move(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Move area edges";
+ ot->name = "Move Area Edges";
ot->description = "Move selected area edges";
ot->idname = "SCREEN_OT_area_move";
@@ -1334,10 +1341,10 @@ static int area_split_apply(bContext *C, wmOperator *op)
/* select newly created edge, prepare for moving edge */
for (sv = sc->vertbase.first; sv; sv = sv->next)
- sv->flag = 0;
+ sv->editflag = 0;
- sd->nedge->v1->flag = 1;
- sd->nedge->v2->flag = 1;
+ sd->nedge->v1->editflag = 1;
+ sd->nedge->v2->editflag = 1;
if (dir == 'h') sd->origval = sd->nedge->v1->vec.y;
else sd->origval = sd->nedge->v1->vec.x;
@@ -1377,7 +1384,7 @@ static void area_split_exit(bContext *C, wmOperator *op)
/* UI callback, adds new handler */
-static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
sAreaSplitData *sd;
int dir;
@@ -1509,7 +1516,7 @@ static int area_split_cancel(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int area_split_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
sAreaSplitData *sd = (sAreaSplitData *)op->customdata;
float fac;
@@ -1692,7 +1699,7 @@ static int area_max_regionsize(ScrArea *sa, ARegion *scalear, AZEdge edge)
return dist;
}
-static int region_scale_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int region_scale_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
sActionzoneData *sad = event->customdata;
AZone *az;
@@ -1720,9 +1727,9 @@ static int region_scale_invoke(bContext *C, wmOperator *op, wmEvent *event)
/* if not set we do now, otherwise it uses type */
if (rmd->ar->sizex == 0)
- rmd->ar->sizex = rmd->ar->type->prefsizex;
+ rmd->ar->sizex = rmd->ar->winx;
if (rmd->ar->sizey == 0)
- rmd->ar->sizey = rmd->ar->type->prefsizey;
+ rmd->ar->sizey = rmd->ar->winy;
/* now copy to regionmovedata */
if (rmd->edge == AE_LEFT_TO_TOPRIGHT || rmd->edge == AE_RIGHT_TO_TOPLEFT) {
@@ -1734,7 +1741,7 @@ static int region_scale_invoke(bContext *C, wmOperator *op, wmEvent *event)
/* limit headers to standard height for now */
if (rmd->ar->regiontype == RGN_TYPE_HEADER)
- maxsize = rmd->ar->type->prefsizey;
+ maxsize = ED_area_headersize();
else
maxsize = 1000;
@@ -1754,7 +1761,7 @@ static int region_scale_get_maxsize(RegionMoveData *rmd)
int maxsize = 0;
if (rmd->edge == AE_LEFT_TO_TOPRIGHT || rmd->edge == AE_RIGHT_TO_TOPLEFT) {
- return rmd->sa->winx - UI_UNIT_X;
+ return (int) ( (rmd->sa->winx / UI_DPI_FAC) - UI_UNIT_X);
}
if (rmd->ar->regiontype == RGN_TYPE_TOOL_PROPS) {
@@ -1786,11 +1793,11 @@ static void region_scale_validate_size(RegionMoveData *rmd)
static void region_scale_toggle_hidden(bContext *C, RegionMoveData *rmd)
{
- ED_region_toggle_hidden(C, rmd->ar);
+ region_toggle_hidden(C, rmd->ar, 0);
region_scale_validate_size(rmd);
}
-static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
RegionMoveData *rmd = op->customdata;
int delta;
@@ -1803,6 +1810,9 @@ static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event)
delta = event->x - rmd->origx;
if (rmd->edge == AE_LEFT_TO_TOPRIGHT) delta = -delta;
+ /* region sizes now get multiplied */
+ delta /= UI_DPI_FAC;
+
rmd->ar->sizex = rmd->origval + delta;
CLAMP(rmd->ar->sizex, 0, rmd->maxsize);
@@ -1819,6 +1829,9 @@ static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event)
delta = event->y - rmd->origy;
if (rmd->edge == AE_BOTTOM_TO_TOPLEFT) delta = -delta;
+ /* region sizes now get multiplied */
+ delta /= UI_DPI_FAC;
+
rmd->ar->sizey = rmd->origval + delta;
CLAMP(rmd->ar->sizey, 0, rmd->maxsize);
@@ -2307,7 +2320,7 @@ static int area_join_exec(bContext *C, wmOperator *op)
}
/* interaction callback */
-static int area_join_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int area_join_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (event->type == EVT_ACTIONZONE_AREA) {
@@ -2363,7 +2376,7 @@ static int area_join_cancel(bContext *C, wmOperator *op)
}
/* modal callback while selecting area (space) that will be removed */
-static int area_join_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
bScreen *sc = CTX_wm_screen(C);
sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
@@ -2479,7 +2492,7 @@ static void SCREEN_OT_area_join(wmOperatorType *ot)
/* ******************************* */
-static int screen_area_options_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
uiPopupMenu *pup;
uiLayout *layout;
@@ -2557,7 +2570,7 @@ static int spacedata_cleanup(bContext *C, wmOperator *op)
static void SCREEN_OT_spacedata_cleanup(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Clean-up space-data";
+ ot->name = "Clean-up Space-data";
ot->description = "Remove unused settings for invisible editors";
ot->idname = "SCREEN_OT_spacedata_cleanup";
@@ -2593,7 +2606,7 @@ static void SCREEN_OT_repeat_last(wmOperatorType *ot)
}
-static int repeat_history_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int repeat_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
wmWindowManager *wm = CTX_wm_manager(C);
wmOperator *lastop;
@@ -2650,7 +2663,7 @@ static void SCREEN_OT_repeat_history(wmOperatorType *ot)
/* ********************** redo operator ***************************** */
-static int redo_last_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
+static int redo_last_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
wmOperator *lastop = WM_operator_last_redo(C);
@@ -2797,7 +2810,6 @@ static void SCREEN_OT_region_quadview(wmOperatorType *ot)
}
-
/* ************** region flip operator ***************************** */
/* flip a region alignment */
@@ -2948,12 +2960,12 @@ void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UN
}
}
-static int header_toolbox_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
+static int header_toolbox_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
uiPopupMenu *pup;
uiLayout *layout;
- pup = uiPupMenuBegin(C, N_("Header"), ICON_NONE);
+ pup = uiPupMenuBegin(C, IFACE_("Header"), ICON_NONE);
layout = uiPupMenuLayout(pup);
ED_screens_header_tools_menu_create(C, layout, NULL);
@@ -3061,7 +3073,7 @@ static int match_region_with_redraws(int spacetype, int regiontype, int redraws)
return 0;
}
-static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
bScreen *screen = CTX_wm_screen(C);
@@ -3358,7 +3370,7 @@ static int border_select_do(bContext *C, wmOperator *op)
static void SCREEN_OT_border_select(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Border select";
+ ot->name = "Border Select";
ot->idname = "SCREEN_OT_border_select";
/* api callbacks */
@@ -3411,17 +3423,19 @@ static void SCREEN_OT_back_to_previous(struct wmOperatorType *ot)
/* *********** show user pref window ****** */
-static int userpref_show_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int userpref_show_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
+ wmWindow *win = CTX_wm_window(C);
rcti rect;
int sizex, sizey;
- sizex = 800;
- sizey = 480;
+ sizex = 800 * UI_DPI_WINDOW_FAC;
+ sizey = 480 * UI_DPI_WINDOW_FAC;
/* some magic to calculate postition */
- rect.xmin = event->x + CTX_wm_window(C)->posx - sizex / 2;
- rect.ymin = event->y + CTX_wm_window(C)->posy - sizey / 2;
+ /* pixelsize: mouse coords are in U.pixelsize units :/ */
+ rect.xmin = (event->x / U.pixelsize) + win->posx - sizex / 2;
+ rect.ymin = (event->y / U.pixelsize) + win->posy - sizey / 2;
rect.xmax = rect.xmin + sizex;
rect.ymax = rect.ymin + sizey;
@@ -3435,8 +3449,8 @@ static int userpref_show_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *ev
static void SCREEN_OT_userpref_show(struct wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Show/Hide User Preferences";
- ot->description = "Show/hide user preferences";
+ ot->name = "Show User Preferences";
+ ot->description = "Show user preferences";
ot->idname = "SCREEN_OT_userpref_show";
/* api callbacks */
@@ -3506,7 +3520,7 @@ static int scene_new_exec(bContext *C, wmOperator *op)
int type = RNA_enum_get(op->ptr, "type");
if (type == SCE_COPY_NEW) {
- newscene = BKE_scene_add("Scene");
+ newscene = BKE_scene_add(bmain, "Scene");
}
else { /* different kinds of copying */
newscene = BKE_scene_copy(scene, type);
@@ -3583,6 +3597,149 @@ static void SCENE_OT_delete(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/* ***************** region alpha blending ***************** */
+
+/* implementation note: a disappearing region needs at least 1 last draw with 100% backbuffer
+ * texture over it- then triple buffer will clear it entirely.
+ * This because flag RGN_HIDDEN is set in end - region doesnt draw at all then */
+
+typedef struct RegionAlphaInfo {
+ ScrArea *sa;
+ ARegion *ar, *child_ar; /* other region */
+ int hidden;
+} RegionAlphaInfo;
+
+#define TIMEOUT 0.2f
+#define TIMESTEP 0.04f
+
+float ED_region_blend_factor(ARegion *ar)
+{
+ /* check parent too */
+ if (ar->regiontimer == NULL && (ar->alignment & RGN_SPLIT_PREV) && ar->prev) {
+ ar = ar->prev;
+ }
+
+ if (ar->regiontimer) {
+ RegionAlphaInfo *rgi = ar->regiontimer->customdata;
+ float alpha;
+
+ alpha = (float)ar->regiontimer->duration / TIMEOUT;
+ /* makes sure the blend out works 100% - without area redraws */
+ if (rgi->hidden) alpha = 0.9f - TIMESTEP - alpha;
+
+ CLAMP(alpha, 0.0f, 1.0f);
+ return alpha;
+ }
+ return 1.0f;
+}
+
+/* assumes region has running region-blend timer */
+static void region_blend_end(bContext *C, ARegion *ar, int is_running)
+{
+ RegionAlphaInfo *rgi = ar->regiontimer->customdata;
+
+ /* always send redraw */
+ ED_region_tag_redraw(ar);
+ if (rgi->child_ar)
+ ED_region_tag_redraw(rgi->child_ar);
+
+ /* if running timer was hiding, the flag toggle went wrong */
+ if (is_running) {
+ if (rgi->hidden)
+ rgi->ar->flag &= ~RGN_FLAG_HIDDEN;
+ }
+ else {
+ if (rgi->hidden) {
+ rgi->ar->flag |= rgi->hidden;
+ ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), rgi->sa);
+ }
+ /* area decoration needs redraw in end */
+ ED_area_tag_redraw(rgi->sa);
+ }
+ WM_event_remove_timer(CTX_wm_manager(C), NULL, ar->regiontimer); /* frees rgi */
+ ar->regiontimer = NULL;
+
+}
+/* assumes that *ar itself is not a splitted version from previous region */
+void region_blend_start(bContext *C, ScrArea *sa, ARegion *ar)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+ RegionAlphaInfo *rgi;
+
+ /* end running timer */
+ if (ar->regiontimer) {
+
+ region_blend_end(C, ar, 1);
+ }
+ rgi = MEM_callocN(sizeof(RegionAlphaInfo), "RegionAlphaInfo");
+
+ rgi->hidden = ar->flag & RGN_FLAG_HIDDEN;
+ rgi->sa = sa;
+ rgi->ar = ar;
+ ar->flag &= ~RGN_FLAG_HIDDEN;
+
+ /* blend in, reinitialize regions because it got unhidden */
+ if (rgi->hidden == 0)
+ ED_area_initialize(wm, win, sa);
+ else
+ WM_event_remove_handlers(C, &ar->handlers);
+
+ if (ar->next) {
+ if (ar->next->alignment & RGN_SPLIT_PREV) {
+ rgi->child_ar = ar->next;
+ }
+ }
+
+ /* new timer */
+ ar->regiontimer = WM_event_add_timer(wm, win, TIMERREGION, TIMESTEP);
+ ar->regiontimer->customdata = rgi;
+
+}
+
+/* timer runs in win->handlers, so it cannot use context to find area/region */
+static int region_blend_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ RegionAlphaInfo *rgi;
+ wmTimer *timer = event->customdata;
+
+ /* event type is TIMERREGION, but we better check */
+ if (event->type != TIMERREGION || timer == NULL)
+ return OPERATOR_PASS_THROUGH;
+
+ rgi = timer->customdata;
+
+ /* always send redraws */
+ ED_region_tag_redraw(rgi->ar);
+ if (rgi->child_ar)
+ ED_region_tag_redraw(rgi->child_ar);
+
+ /* end timer? */
+ if (rgi->ar->regiontimer->duration > (double)TIMEOUT) {
+ region_blend_end(C, rgi->ar, 0);
+ return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
+ }
+
+ return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
+}
+
+static void SCREEN_OT_region_blend(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Region Alpha";
+ ot->idname = "SCREEN_OT_region_blend";
+ ot->description = "Blend in and out overlapping region";
+
+ /* api callbacks */
+ ot->invoke = region_blend_invoke;
+
+ /* flags */
+ ot->flag = 0;
+
+ /* properties */
+}
+
+
/* **************** Assigning operatortypes to global list, adding handlers **************** */
@@ -3615,6 +3772,7 @@ void ED_operatortypes_screen(void)
WM_operatortype_append(SCREEN_OT_screenshot);
WM_operatortype_append(SCREEN_OT_screencast);
WM_operatortype_append(SCREEN_OT_userpref_show);
+ WM_operatortype_append(SCREEN_OT_region_blend);
/*frame changes*/
WM_operatortype_append(SCREEN_OT_frame_offset);
@@ -3664,7 +3822,7 @@ static void keymap_modal_set(wmKeyConfig *keyconf)
}
-static int open_file_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
+static int open_file_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_PATH) {
if (drag->icon == ICON_FILE_BLEND)
@@ -3717,6 +3875,7 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
/* standard timers */
WM_keymap_add_item(keymap, "SCREEN_OT_animation_step", TIMER0, KM_ANY, KM_ANY, 0);
+ WM_keymap_add_item(keymap, "SCREEN_OT_region_blend", TIMERREGION, KM_ANY, KM_ANY, 0);
RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", 1);
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index ca85daadf3b..20edd3d32e7 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -86,8 +86,8 @@ static unsigned int *screenshot(bContext *C, int *dumpsx, int *dumpsy)
x = 0;
y = 0;
- *dumpsx = win->sizex;
- *dumpsy = win->sizey;
+ *dumpsx = WM_window_pixels_x(win);
+ *dumpsy = WM_window_pixels_y(win);
if (*dumpsx && *dumpsy) {
@@ -204,7 +204,7 @@ static int screenshot_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int screenshot_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int screenshot_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (screenshot_data_create(C, op)) {
if (RNA_struct_property_is_set(op->ptr, "filepath"))
@@ -223,7 +223,7 @@ static int screenshot_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)
static int screenshot_check(bContext *UNUSED(C), wmOperator *op)
{
ScreenshotData *scd = op->customdata;
- return WM_operator_filesel_ensure_ext_imtype(op, scd->im_format.imtype);
+ return WM_operator_filesel_ensure_ext_imtype(op, &scd->im_format);
}
static int screenshot_cancel(bContext *UNUSED(C), wmOperator *op)
@@ -232,11 +232,11 @@ static int screenshot_cancel(bContext *UNUSED(C), wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int screenshot_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
+static bool screenshot_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
{
const char *prop_id = RNA_property_identifier(prop);
- return !(strcmp(prop_id, "filepath") == 0);
+ return !(STREQ(prop_id, "filepath"));
}
static void screenshot_draw(bContext *UNUSED(C), wmOperator *op)
@@ -272,7 +272,8 @@ void SCREEN_OT_screenshot(wmOperatorType *ot)
WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE, FILE_SPECIAL, FILE_SAVE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
- RNA_def_boolean(ot->srna, "full", 1, "Full Screen", "Screenshot the whole Blender window");
+ RNA_def_boolean(ot->srna, "full", 1, "Full Screen",
+ "Capture the whole window (otherwise only capture the active area)");
}
/* *************** screenshot movie job ************************* */
@@ -361,7 +362,7 @@ 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.imtype, rd.scemode & R_EXTENSION, TRUE);
+ BKE_makepicstring(name, rd.pic, sj->bmain->name, rd.cfra, &rd.im_format, rd.scemode & R_EXTENSION, TRUE);
ibuf->rect = sj->dumprect;
ok = BKE_imbuf_write(ibuf, name, &rd.im_format);
@@ -448,17 +449,25 @@ static void screenshot_endjob(void *sjv)
static int screencast_exec(bContext *C, wmOperator *op)
{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
bScreen *screen = CTX_wm_screen(C);
- wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), screen, "Screencast", 0, WM_JOB_TYPE_SCREENCAST);
- ScreenshotJob *sj = MEM_callocN(sizeof(ScreenshotJob), "screenshot job");
+ wmJob *wm_job;
+ ScreenshotJob *sj;
+ /* if called again, stop the running job */
+ if (WM_jobs_test(wm, screen, WM_JOB_TYPE_SCREENCAST))
+ WM_jobs_stop(wm, screen, screenshot_startjob);
+
+ wm_job = WM_jobs_get(wm, win, screen, "Screencast", 0, WM_JOB_TYPE_SCREENCAST);
+ sj = MEM_callocN(sizeof(ScreenshotJob), "screenshot job");
+
/* setup sj */
if (RNA_boolean_get(op->ptr, "full")) {
- wmWindow *win = CTX_wm_window(C);
sj->x = 0;
sj->y = 0;
- sj->dumpsx = win->sizex;
- sj->dumpsy = win->sizey;
+ sj->dumpsx = WM_window_pixels_x(win);
+ sj->dumpsy = WM_window_pixels_y(win);
}
else {
ScrArea *curarea = CTX_wm_area(C);
@@ -469,7 +478,7 @@ static int screencast_exec(bContext *C, wmOperator *op)
}
sj->bmain = CTX_data_main(C);
sj->scene = CTX_data_scene(C);
- sj->wm = CTX_wm_manager(C);
+ sj->wm = wm;
BKE_reports_init(&sj->reports, RPT_PRINT);
@@ -500,5 +509,6 @@ void SCREEN_OT_screencast(wmOperatorType *ot)
ot->flag = 0;
RNA_def_property(ot->srna, "filepath", PROP_STRING, PROP_FILEPATH);
- RNA_def_boolean(ot->srna, "full", 1, "Full Screen", "Screencast the whole Blender window");
+ RNA_def_boolean(ot->srna, "full", 1, "Full Screen",
+ "Capture the whole window (otherwise only capture the active area)");
}
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index ae72dce1415..0899fb97a2a 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../uvedit
../../blenkernel
../../blenlib
+ ../../blenfont
../../blenloader
../../bmesh
../../gpu
@@ -42,6 +43,8 @@ set(SRC
paint_cursor.c
paint_hide.c
paint_image.c
+ paint_image_2d.c
+ paint_image_proj.c
paint_mask.c
paint_ops.c
paint_stroke.c
@@ -56,4 +59,8 @@ set(SRC
sculpt_intern.h
)
+if(WITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
+endif()
+
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 21439e6c6b2..d10666de637 100644
--- a/source/blender/editors/sculpt_paint/SConscript
+++ b/source/blender/editors/sculpt_paint/SConscript
@@ -1,11 +1,37 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
defs = []
-incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs = '../include ../../blenlib ../../blenfont ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
incs += ' ../../render/extern/include'
incs += ' ../../gpu ../../makesrna ../../blenloader ../../bmesh ../uvedit'
@@ -21,4 +47,7 @@ if env['OURPLATFORM'] == 'linuxcross':
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
+if env['WITH_BF_INTERNATIONAL']:
+ defs.append('WITH_INTERNATIONAL')
+
env.BlenderLib ( 'bf_editors_sculpt_paint', sources, Split(incs), defines=defs, libtype=['core'], priority=[40] )
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 5e23a144408..8d9cbbbcf11 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -43,6 +43,7 @@
#include "BKE_brush.h"
#include "BKE_context.h"
+#include "BKE_image.h"
#include "BKE_paint.h"
#include "WM_api.h"
@@ -116,7 +117,7 @@ static void make_snap(Snapshot *snap, Brush *brush, ViewContext *vc)
snap->winy = vc->ar->winy;
}
-static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc)
+static int load_tex(Brush *br, ViewContext *vc)
{
static GLuint overlay_texture = 0;
static int init = 0;
@@ -130,10 +131,6 @@ static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc)
int size;
int j;
int refresh;
-
-#ifndef _OPENMP
- (void)sd; /* quied unused warning */
-#endif
if (br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED && !br->mtex.tex) return 0;
@@ -147,6 +144,8 @@ static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc)
!same_snap(&snap, br, vc);
if (refresh) {
+ struct ImagePool *pool = NULL;
+
if (br->mtex.tex && br->mtex.tex->preview)
tex_changed_timestamp = br->mtex.tex->preview->changed_timestamp[0];
@@ -186,7 +185,10 @@ static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc)
buffer = MEM_mallocN(sizeof(GLubyte) * size * size, "load_tex");
- #pragma omp parallel for schedule(static) if (sd->flags & SCULPT_USE_OPENMP)
+ if (br->mtex.tex)
+ pool = BKE_image_pool_new();
+
+ #pragma omp parallel for schedule(static)
for (j = 0; j < size; j++) {
int i;
float y;
@@ -205,14 +207,14 @@ static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc)
x = (float)i / size;
y = (float)j / size;
- x -= 0.5f;
- y -= 0.5f;
-
if (br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED) {
x *= vc->ar->winx / radius;
y *= vc->ar->winy / radius;
}
else {
+ x -= 0.5f;
+ y -= 0.5f;
+
x *= 2;
y *= 2;
}
@@ -236,7 +238,7 @@ static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc)
x += br->mtex.ofs[0];
y += br->mtex.ofs[1];
- avg = br->mtex.tex ? paint_get_tex_pixel(br, x, y) : 1;
+ avg = br->mtex.tex ? paint_get_tex_pixel(br, x, y, pool) : 1;
avg += br->texture_sample_bias;
@@ -251,6 +253,9 @@ static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc)
}
}
+ if (pool)
+ BKE_image_pool_free(pool);
+
if (!overlay_texture)
glGenTextures(1, &overlay_texture);
}
@@ -340,14 +345,14 @@ static int sculpt_get_brush_geometry(bContext *C, ViewContext *vc,
{
Scene *scene = CTX_data_scene(C);
Paint *paint = paint_get_active_from_context(C);
- float window[2];
+ float mouse[2];
int hit;
- window[0] = x + vc->ar->winrct.xmin;
- window[1] = y + vc->ar->winrct.ymin;
+ mouse[0] = x;
+ mouse[1] = y;
if (vc->obact->sculpt && vc->obact->sculpt->pbvh &&
- sculpt_stroke_get_location(C, location, window))
+ sculpt_stroke_get_location(C, location, mouse))
{
Brush *brush = paint_brush(paint);
*pixel_radius =
@@ -376,7 +381,7 @@ static int sculpt_get_brush_geometry(bContext *C, ViewContext *vc,
/* Draw an overlay that shows what effect the brush's texture will
* have on brush strength */
/* TODO: sculpt only for now */
-static void paint_draw_alpha_overlay(Sculpt *sd, Brush *brush,
+static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
ViewContext *vc, int x, int y)
{
rctf quad;
@@ -401,7 +406,7 @@ static void paint_draw_alpha_overlay(Sculpt *sd, Brush *brush,
GL_VIEWPORT_BIT |
GL_TEXTURE_BIT);
- if (load_tex(sd, brush, vc)) {
+ if (load_tex(brush, vc)) {
glEnable(GL_BLEND);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@@ -415,25 +420,23 @@ static void paint_draw_alpha_overlay(Sculpt *sd, Brush *brush,
if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) {
/* brush rotation */
glTranslatef(0.5, 0.5, 0);
- glRotatef((double)RAD2DEGF((brush->flag & BRUSH_RAKE) ?
- sd->last_angle : sd->special_rotation),
+ glRotatef((double)RAD2DEGF(ups->brush_rotation),
0.0, 0.0, 1.0);
glTranslatef(-0.5f, -0.5f, 0);
/* scale based on tablet pressure */
- if (sd->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) {
+ if (ups->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) {
glTranslatef(0.5f, 0.5f, 0);
- glScalef(1.0f / sd->pressure_value, 1.0f / sd->pressure_value, 1);
+ glScalef(1.0f / ups->pressure_value, 1.0f / ups->pressure_value, 1);
glTranslatef(-0.5f, -0.5f, 0);
}
- if (sd->draw_anchored) {
- const float *aim = sd->anchored_initial_mouse;
- const rcti *win = &vc->ar->winrct;
- quad.xmin = aim[0] - sd->anchored_size - win->xmin;
- quad.ymin = aim[1] - sd->anchored_size - win->ymin;
- quad.xmax = aim[0] + sd->anchored_size - win->xmin;
- quad.ymax = aim[1] + sd->anchored_size - win->ymin;
+ if (ups->draw_anchored) {
+ const float *aim = ups->anchored_initial_mouse;
+ quad.xmin = aim[0] - ups->anchored_size;
+ quad.ymin = aim[1] - ups->anchored_size;
+ quad.xmax = aim[0] + ups->anchored_size;
+ quad.ymax = aim[1] + ups->anchored_size;
}
else {
const int radius = BKE_brush_size_get(vc->scene, brush);
@@ -476,7 +479,7 @@ static void paint_draw_alpha_overlay(Sculpt *sd, Brush *brush,
/* Special actions taken when paint cursor goes over mesh */
/* TODO: sculpt only for now */
-static void paint_cursor_on_hit(Sculpt *sd, Brush *brush, ViewContext *vc,
+static void paint_cursor_on_hit(UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc,
const float location[3])
{
float unprojected_radius, projected_radius;
@@ -484,8 +487,8 @@ static void paint_cursor_on_hit(Sculpt *sd, Brush *brush, ViewContext *vc,
/* update the brush's cached 3D radius */
if (!BKE_brush_use_locked_size(vc->scene, brush)) {
/* get 2D brush radius */
- if (sd->draw_anchored)
- projected_radius = sd->anchored_size;
+ if (ups->draw_anchored)
+ projected_radius = ups->anchored_size;
else {
if (brush->flag & BRUSH_ANCHORED)
projected_radius = 8;
@@ -498,8 +501,8 @@ static void paint_cursor_on_hit(Sculpt *sd, Brush *brush, ViewContext *vc,
projected_radius);
/* scale 3D brush radius by pressure */
- if (sd->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush))
- unprojected_radius *= sd->pressure_value;
+ if (ups->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush))
+ unprojected_radius *= ups->pressure_value;
/* set cached value in either Brush or UnifiedPaintSettings */
BKE_brush_unprojected_radius_set(vc->scene, brush, unprojected_radius);
@@ -509,6 +512,7 @@ static void paint_cursor_on_hit(Sculpt *sd, Brush *brush, ViewContext *vc,
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 = paint_get_active_from_context(C);
Brush *brush = paint_brush(paint);
ViewContext vc;
@@ -531,39 +535,22 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
* mouse over too, not just during a stroke */
view3d_set_viewcontext(C, &vc);
+ if (brush->flag & BRUSH_RAKE)
+ /* here, translation contains the mouse coordinates. */
+ paint_calculate_rake_rotation(ups, translation);
+
+ /* draw overlay */
+ paint_draw_alpha_overlay(ups, brush, &vc, x, y);
+
/* TODO: as sculpt and other paint modes are unified, this
* special mode of drawing will go away */
if (vc.obact->sculpt) {
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
float location[3];
int pixel_radius, hit;
- /* this is probably here so that rake takes into
- * account the brush movements before the stroke
- * starts, but this doesn't really belong in draw code
- * TODO) */
- {
- const float u = 0.5f;
- const float v = 1 - u;
- const float r = 20;
-
- const float dx = sd->last_x - x;
- const float dy = sd->last_y - y;
-
- if (dx * dx + dy * dy >= r * r) {
- sd->last_angle = atan2(dx, dy);
-
- sd->last_x = u * sd->last_x + v * x;
- sd->last_y = u * sd->last_y + v * y;
- }
- }
-
/* test if brush is over the mesh */
hit = sculpt_get_brush_geometry(C, &vc, x, y, &pixel_radius, location);
- /* draw overlay */
- paint_draw_alpha_overlay(sd, brush, &vc, x, y);
-
if (BKE_brush_use_locked_size(scene, brush))
BKE_brush_size_set(scene, brush, pixel_radius);
@@ -581,12 +568,12 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* only do if brush is over the mesh */
if (hit)
- paint_cursor_on_hit(sd, brush, &vc, location);
+ paint_cursor_on_hit(ups, brush, &vc, location);
- if (sd->draw_anchored) {
- final_radius = sd->anchored_size;
- translation[0] = sd->anchored_initial_mouse[0] - vc.ar->winrct.xmin;
- translation[1] = sd->anchored_initial_mouse[1] - vc.ar->winrct.ymin;
+ if (ups->draw_anchored) {
+ final_radius = ups->anchored_size;
+ translation[0] = ups->anchored_initial_mouse[0];
+ translation[1] = ups->anchored_initial_mouse[1];
}
}
@@ -599,6 +586,14 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* draw brush outline */
glTranslatef(translation[0], translation[1], 0);
+
+ /* draw an inner brush */
+ if (ups->draw_pressure && BKE_brush_use_size_pressure(scene, brush)) {
+ /* inner at full alpha */
+ glutil_draw_lined_arc(0.0, M_PI * 2.0, final_radius * ups->pressure_value, 40);
+ /* outer at half alpha */
+ glColor4f(outline_col[0], outline_col[1], outline_col[2], outline_alpha * 0.5f);
+ }
glutil_draw_lined_arc(0.0, M_PI * 2.0, final_radius, 40);
glTranslatef(-translation[0], -translation[1], 0);
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index bdd73cd6db3..14eb358f20f 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -37,7 +37,6 @@
#include "BLI_bitmap.h"
#include "BLI_listbase.h"
#include "BLI_math_vector.h"
-#include "BLI_pbvh.h"
#include "BLI_utildefines.h"
#include "DNA_mesh_types.h"
@@ -45,6 +44,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "BKE_pbvh.h"
#include "BKE_ccg.h"
#include "BKE_context.h"
#include "BKE_DerivedMesh.h"
@@ -112,8 +112,8 @@ static void partialvis_update_mesh(Object *ob,
int *vert_indices;
int any_changed = 0, any_visible = 0, totvert, i;
- BLI_pbvh_node_num_verts(pbvh, node, NULL, &totvert);
- BLI_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
+ BKE_pbvh_node_num_verts(pbvh, node, NULL, &totvert);
+ BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
paint_mask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK);
sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
@@ -136,8 +136,8 @@ static void partialvis_update_mesh(Object *ob,
}
if (any_changed) {
- BLI_pbvh_node_mark_rebuild_draw(node);
- BLI_pbvh_node_fully_hidden_set(node, !any_visible);
+ BKE_pbvh_node_mark_rebuild_draw(node);
+ BKE_pbvh_node_fully_hidden_set(node, !any_visible);
}
}
@@ -157,11 +157,11 @@ static void partialvis_update_grids(Object *ob,
int *grid_indices, totgrid, any_changed, i;
/* get PBVH data */
- BLI_pbvh_node_get_grids(pbvh, node,
+ BKE_pbvh_node_get_grids(pbvh, node,
&grid_indices, &totgrid, NULL, NULL,
&grids, NULL);
- grid_hidden = BLI_pbvh_grid_hidden(pbvh);
- BLI_pbvh_get_grid_key(pbvh, &key);
+ grid_hidden = BKE_pbvh_grid_hidden(pbvh);
+ BKE_pbvh_get_grid_key(pbvh, &key);
sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
@@ -226,12 +226,81 @@ static void partialvis_update_grids(Object *ob,
/* mark updates if anything was hidden/shown */
if (any_changed) {
- BLI_pbvh_node_mark_rebuild_draw(node);
- BLI_pbvh_node_fully_hidden_set(node, !any_visible);
+ BKE_pbvh_node_mark_rebuild_draw(node);
+ BKE_pbvh_node_fully_hidden_set(node, !any_visible);
multires_mark_as_modified(ob, MULTIRES_HIDDEN_MODIFIED);
}
}
+static void partialvis_update_bmesh_verts(BMesh *bm,
+ GHash *verts,
+ PartialVisAction action,
+ PartialVisArea area,
+ float planes[4][4],
+ int *any_changed,
+ int *any_visible)
+{
+ GHashIterator gh_iter;
+
+ GHASH_ITER (gh_iter, verts) {
+ BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ float *vmask = CustomData_bmesh_get(&bm->vdata,
+ v->head.data,
+ CD_PAINT_MASK);
+
+ /* hide vertex if in the hide volume */
+ if (is_effected(area, planes, v->co, *vmask)) {
+ if (action == PARTIALVIS_HIDE)
+ BM_elem_flag_enable(v, BM_ELEM_HIDDEN);
+ else
+ BM_elem_flag_disable(v, BM_ELEM_HIDDEN);
+ (*any_changed) = TRUE;
+ }
+
+ if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN))
+ (*any_visible) = TRUE;
+ }
+}
+
+static void partialvis_update_bmesh(Object *ob,
+ PBVH *pbvh,
+ PBVHNode *node,
+ PartialVisAction action,
+ PartialVisArea area,
+ float planes[4][4])
+{
+ BMesh *bm;
+ GHash *unique, *other;
+ int any_changed = 0, any_visible = 0;
+
+ bm = BKE_pbvh_get_bmesh(pbvh);
+ unique = BKE_pbvh_bmesh_node_unique_verts(node);
+ other = BKE_pbvh_bmesh_node_other_verts(node);
+
+ sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
+
+ partialvis_update_bmesh_verts(bm,
+ unique,
+ action,
+ area,
+ planes,
+ &any_changed,
+ &any_visible);
+
+ partialvis_update_bmesh_verts(bm,
+ other,
+ action,
+ area,
+ planes,
+ &any_changed,
+ &any_visible);
+
+ if (any_changed) {
+ BKE_pbvh_node_mark_rebuild_draw(node);
+ BKE_pbvh_node_fully_hidden_set(node, !any_visible);
+ }
+}
+
static void rect_from_props(rcti *rect, PointerRNA *ptr)
{
rect->xmin = RNA_int_get(ptr, "xmin");
@@ -265,22 +334,22 @@ static void get_pbvh_nodes(PBVH *pbvh,
float clip_planes[4][4],
PartialVisArea mode)
{
- BLI_pbvh_SearchCallback cb = NULL;
+ BKE_pbvh_SearchCallback cb = NULL;
/* select search callback */
switch (mode) {
case PARTIALVIS_INSIDE:
- cb = BLI_pbvh_node_planes_contain_AABB;
+ cb = BKE_pbvh_node_planes_contain_AABB;
break;
case PARTIALVIS_OUTSIDE:
- cb = BLI_pbvh_node_planes_exclude_AABB;
+ cb = BKE_pbvh_node_planes_exclude_AABB;
break;
case PARTIALVIS_ALL:
case PARTIALVIS_MASKED:
break;
}
- BLI_pbvh_search_gather(pbvh, cb, clip_planes, nodes, totnode);
+ BKE_pbvh_search_gather(pbvh, cb, clip_planes, nodes, totnode);
}
static int hide_show_exec(bContext *C, wmOperator *op)
@@ -310,7 +379,7 @@ static int hide_show_exec(bContext *C, wmOperator *op)
ob->sculpt->pbvh = pbvh;
get_pbvh_nodes(pbvh, &nodes, &totnode, clip_planes, area);
- pbvh_type = BLI_pbvh_type(pbvh);
+ pbvh_type = BKE_pbvh_type(pbvh);
/* start undo */
switch (action) {
@@ -330,6 +399,9 @@ static int hide_show_exec(bContext *C, wmOperator *op)
case PBVH_GRIDS:
partialvis_update_grids(ob, pbvh, nodes[i], action, area, clip_planes);
break;
+ case PBVH_BMESH:
+ partialvis_update_bmesh(ob, pbvh, nodes[i], action, area, clip_planes);
+ break;
}
}
@@ -352,7 +424,7 @@ static int hide_show_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int hide_show_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int hide_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
PartialVisArea area = RNA_enum_get(op->ptr, "area");
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index b704414c321..4f935ebdd8c 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -42,7 +42,6 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
-#include "BLI_dynstr.h"
#include "BLI_linklist.h"
#include "BLI_memarena.h"
#include "BLI_threads.h"
@@ -54,13 +53,9 @@
#include "IMB_imbuf_types.h"
#include "DNA_brush_types.h"
-#include "DNA_camera_types.h"
#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_texture_types.h"
#include "BKE_camera.h"
#include "BKE_context.h"
@@ -77,8 +72,7 @@
#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_scene.h"
-#include "BKE_global.h"
-#include "BKE_deform.h"
+#include "BKE_colortools.h"
#include "BKE_tessmesh.h"
@@ -102,304 +96,13 @@
#include "RNA_enum_types.h"
#include "GPU_draw.h"
-#include "GPU_extensions.h"
#include "IMB_colormanagement.h"
#include "paint_intern.h"
-/* Defines and Structs */
-/* FTOCHAR as inline function */
-BLI_INLINE unsigned char f_to_char(const float val)
-{
- return FTOCHAR(val);
-}
-
-
-#define IMAPAINT_CHAR_TO_FLOAT(c) ((c) / 255.0f)
-
-#define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { \
- (c)[0] = f_to_char((f)[0]); \
- (c)[1] = f_to_char((f)[1]); \
- (c)[2] = f_to_char((f)[2]); \
-} (void)0
-#define IMAPAINT_FLOAT_RGBA_TO_CHAR(c, f) { \
- (c)[0] = f_to_char((f)[0]); \
- (c)[1] = f_to_char((f)[1]); \
- (c)[2] = f_to_char((f)[2]); \
- (c)[3] = f_to_char((f)[3]); \
-} (void)0
-#define IMAPAINT_CHAR_RGB_TO_FLOAT(f, c) { \
- (f)[0] = IMAPAINT_CHAR_TO_FLOAT((c)[0]); \
- (f)[1] = IMAPAINT_CHAR_TO_FLOAT((c)[1]); \
- (f)[2] = IMAPAINT_CHAR_TO_FLOAT((c)[2]); \
-} (void)0
-#define IMAPAINT_CHAR_RGBA_TO_FLOAT(f, c) { \
- (f)[0] = IMAPAINT_CHAR_TO_FLOAT((c)[0]); \
- (f)[1] = IMAPAINT_CHAR_TO_FLOAT((c)[1]); \
- (f)[2] = IMAPAINT_CHAR_TO_FLOAT((c)[2]); \
- (f)[3] = IMAPAINT_CHAR_TO_FLOAT((c)[3]); \
-} (void)0
-
-#define IMAPAINT_FLOAT_RGB_COPY(a, b) copy_v3_v3(a, b)
-
#define IMAPAINT_TILE_BITS 6
#define IMAPAINT_TILE_SIZE (1 << IMAPAINT_TILE_BITS)
-#define IMAPAINT_TILE_NUMBER(size) (((size) + IMAPAINT_TILE_SIZE - 1) >> IMAPAINT_TILE_BITS)
-
-static void imapaint_image_update(Scene *scene, SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint);
-
-
-typedef struct ImagePaintState {
- SpaceImage *sima;
- View2D *v2d;
- Scene *scene;
- bScreen *screen;
-
- Brush *brush;
- short tool, blend;
- Image *image;
- ImBuf *canvas;
- ImBuf *clonecanvas;
- char *warnpackedfile;
- char *warnmultifile;
-
- /* viewport texture paint only, but _not_ project paint */
- Object *ob;
- int faceindex;
- float uv[2];
- int do_facesel;
-
- DerivedMesh *dm;
- int dm_totface;
- int dm_release;
-
- MFace *dm_mface;
- MTFace *dm_mtface;
-} ImagePaintState;
-
-typedef struct ImagePaintPartialRedraw {
- int x1, y1, x2, y2; /* XXX, could use 'rcti' */
- int enabled;
-} ImagePaintPartialRedraw;
-
-typedef struct ImagePaintRegion {
- int destx, desty;
- int srcx, srcy;
- int width, height;
-} ImagePaintRegion;
-
-/* ProjectionPaint defines */
-
-/* approx the number of buckets to have under the brush,
- * used with the brush size to set the ps->buckets_x and ps->buckets_y value.
- *
- * When 3 - a brush should have ~9 buckets under it at once
- * ...this helps for threading while painting as well as
- * avoiding initializing pixels that wont touch the brush */
-#define PROJ_BUCKET_BRUSH_DIV 4
-
-#define PROJ_BUCKET_RECT_MIN 4
-#define PROJ_BUCKET_RECT_MAX 256
-
-#define PROJ_BOUNDBOX_DIV 8
-#define PROJ_BOUNDBOX_SQUARED (PROJ_BOUNDBOX_DIV * PROJ_BOUNDBOX_DIV)
-
-//#define PROJ_DEBUG_PAINT 1
-//#define PROJ_DEBUG_NOSEAMBLEED 1
-//#define PROJ_DEBUG_PRINT_CLIP 1
-#define PROJ_DEBUG_WINCLIP 1
-
-/* 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)
-
-#define PROJ_SRC_VIEW 1
-#define PROJ_SRC_IMAGE_CAM 2
-#define PROJ_SRC_IMAGE_VIEW 3
-
-#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)
-
-/* used for testing doubles, if a point is on a line etc */
-#define PROJ_GEOM_TOLERANCE 0.00075f
-
-/* vert flags */
-#define PROJ_VERT_CULL 1
-
-/* This is mainly a convenience struct used so we can keep an array of images we use
- * Thir imbufs, etc, in 1 array, When using threads this array is copied for each thread
- * because 'partRedrawRect' and 'touch' values would not be thread safe */
-typedef struct ProjPaintImage {
- Image *ima;
- ImBuf *ibuf;
- ImagePaintPartialRedraw *partRedrawRect;
- void **undoRect; /* only used to build undo tiles after painting */
- int touch;
-} ProjPaintImage;
-
-/* Main projection painting struct passed to all projection painting functions */
-typedef struct ProjPaintState {
- View3D *v3d;
- RegionView3D *rv3d;
- ARegion *ar;
- Scene *scene;
- int source; /* PROJ_SRC_**** */
-
- Brush *brush;
- short tool, blend;
- Object *ob;
- /* 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;
-
- /* projection painting only */
- MemArena *arena_mt[BLENDER_MAX_THREADS]; /* for multithreading, the first item is sometimes used for non threaded cases too */
- LinkNode **bucketRect; /* screen sized 2D array, each pixel has a linked list of ProjPixel's */
- 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*/
- 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 */
- float screen_height;
- int winx, winy; /* from the carea or from the projection render */
-
- /* options for projection painting */
- int do_layer_clone;
- int do_layer_stencil;
- int do_layer_stencil_inv;
-
- short do_occlude; /* Use raytraced occlusion? - ortherwise will paint right through to the back*/
- short do_backfacecull; /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */
- short do_mask_normal; /* mask out pixels based on their normals */
- short do_new_shading_nodes; /* cache BKE_scene_use_new_shading_nodes value */
- float normal_angle; /* what angle to mask at*/
- float normal_angle_inner;
- float normal_angle_range; /* difference between normal_angle and normal_angle_inner, for easy access */
-
- short is_ortho;
- short is_airbrush; /* only to avoid using (ps.brush->flag & BRUSH_AIRBRUSH) */
- short is_texbrush; /* only to avoid running */
-#ifndef PROJ_DEBUG_NOSEAMBLEED
- float seam_bleed_px;
-#endif
- /* clone vars */
- float cloneOffset[2];
-
- float projectMat[4][4]; /* Projection matrix, use for getting screen coords */
- 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;
-
- /* reproject vars */
- Image *reproject_image;
- ImBuf *reproject_ibuf;
-
-
- /* threads */
- int thread_tot;
- int bucketMin[2];
- int bucketMax[2];
- int context_bucket_x, context_bucket_y; /* must lock threads while accessing these */
-} ProjPaintState;
-
-typedef union pixelPointer {
- float *f_pt; /* float buffer */
- unsigned int *uint_pt; /* 2 ways to access a char buffer */
- unsigned char *ch_pt;
-} PixelPointer;
-
-typedef union pixelStore {
- unsigned char ch[4];
- unsigned int uint;
- float f[4];
-} PixelStore;
-
-typedef struct ProjPixel {
- float projCoSS[2]; /* the floating point screen projection of this pixel */
-
- /* 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_max */
- unsigned short mask_max;
-
- /* for various reasons we may want to mask out painting onto this pixel */
- unsigned short mask;
-
- short x_px, y_px;
-
- PixelStore origColor;
- PixelStore newColor;
- PixelPointer pixel;
-
- short image_index; /* if anyone wants to paint onto more then 32768 images they can bite me */
- unsigned char bb_cell_index;
-} ProjPixel;
-
-typedef struct ProjPixelClone {
- struct ProjPixel __pp;
- PixelStore clonepx;
-} ProjPixelClone;
-
-/* blur, store surrounding colors */
-#define PROJ_PIXEL_SOFTEN_TOT 4
-/* blur picking offset (in screenspace) */
-#define PROJ_PIXEL_SOFTEN_OFS_PX 1.0f
-
-static const float proj_pixel_soften_v2[PROJ_PIXEL_SOFTEN_TOT][2] = {
- {-PROJ_PIXEL_SOFTEN_OFS_PX, 0.0f},
- { 0.0f, -PROJ_PIXEL_SOFTEN_OFS_PX},
- { 0.0f, PROJ_PIXEL_SOFTEN_OFS_PX},
- { PROJ_PIXEL_SOFTEN_OFS_PX, 0.0f},
-};
-
-/* Finish projection painting structs */
typedef struct UndoImageTile {
struct UndoImageTile *next, *prev;
@@ -418,8 +121,21 @@ typedef struct UndoImageTile {
char gen_type;
} UndoImageTile;
+/* this is a static resource for non-globality,
+ * Maybe it should be exposed as part of the
+ * paint operation, but for now just give a public interface */
static ImagePaintPartialRedraw imapaintpartial = {0, 0, 0, 0, 0};
+ImagePaintPartialRedraw *get_imapaintpartial(void)
+{
+ return &imapaintpartial;
+}
+
+void set_imapaintpartial(struct ImagePaintPartialRedraw *ippr)
+{
+ imapaintpartial = *ippr;
+}
+
/* UNDO */
static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, int restore)
@@ -440,7 +156,7 @@ static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, int
tile->y * IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
}
-static void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile)
+void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile)
{
ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
UndoImageTile *tile;
@@ -479,7 +195,7 @@ static void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int
return tile->rect.pt;
}
-static void image_undo_restore(bContext *C, ListBase *lb)
+void image_undo_restore(bContext *C, ListBase *lb)
{
Main *bmain = CTX_data_main(C);
Image *ima = NULL;
@@ -488,7 +204,7 @@ static void image_undo_restore(bContext *C, ListBase *lb)
tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32,
IB_rectfloat | IB_rect);
-
+
for (tile = lb->first; tile; tile = tile->next) {
short use_float;
@@ -545,7 +261,7 @@ static void image_undo_restore(bContext *C, ListBase *lb)
IMB_freeImBuf(tmpibuf);
}
-static void image_undo_free(ListBase *lb)
+void image_undo_free(ListBase *lb)
{
UndoImageTile *tile;
@@ -553,3807 +269,14 @@ static void image_undo_free(ListBase *lb)
MEM_freeN(tile->rect.pt);
}
-/* get active image for face depending on old/new shading system */
-
-static Image *imapaint_face_image(const ImagePaintState *s, int face_index)
-{
- Image *ima;
-
- if (BKE_scene_use_new_shading_nodes(s->scene)) {
- MFace *mf = &s->dm_mface[face_index];
- ED_object_get_active_image(s->ob, mf->mat_nr + 1, &ima, NULL, NULL);
- }
- else {
- MTFace *tf = &s->dm_mtface[face_index];
- ima = tf->tpage;
- }
-
- return ima;
-}
-
-static Image *project_paint_face_image(const ProjPaintState *ps, MTFace *dm_mtface, int face_index)
-{
- Image *ima;
-
- if (ps->do_new_shading_nodes) { /* cached BKE_scene_use_new_shading_nodes result */
- MFace *mf = ps->dm_mface + face_index;
- ED_object_get_active_image(ps->ob, mf->mat_nr + 1, &ima, NULL, NULL);
- }
- else {
- ima = dm_mtface[face_index].tpage;
- }
-
- return ima;
-}
-
-/* fast projection bucket array lookup, use the safe version for bound checking */
-static int project_bucket_offset(const ProjPaintState *ps, const float projCoSS[2])
-{
- /* If we were not dealing with screenspace 2D coords we could simple do...
- * ps->bucketRect[x + (y*ps->buckets_y)] */
-
- /* please explain?
- * projCoSS[0] - ps->screenMin[0] : zero origin
- * ... / ps->screen_width : range from 0.0 to 1.0
- * ... * ps->buckets_x : use as a bucket index
- *
- * Second multiplication does similar but for vertical offset
- */
- return ( (int)(((projCoSS[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x)) +
- (((int)(((projCoSS[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y)) * ps->buckets_x);
-}
-
-static int project_bucket_offset_safe(const ProjPaintState *ps, const float projCoSS[2])
-{
- int bucket_index = project_bucket_offset(ps, projCoSS);
-
- if (bucket_index < 0 || bucket_index >= ps->buckets_x * ps->buckets_y) {
- return -1;
- }
- else {
- return bucket_index;
- }
-}
-
-/* still use 2D X,Y space but this works for verts transformed by a perspective matrix, using their 4th component as a weight */
-static void barycentric_weights_v2_persp(const float v1[4], const float v2[4], const float v3[4], const float co[2], float w[3])
-{
- float wtot_inv, 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];
- wtot = w[0] + w[1] + w[2];
-
- if (wtot != 0.0f) {
- wtot_inv = 1.0f / wtot;
-
- w[0] = w[0] * wtot_inv;
- w[1] = w[1] * wtot_inv;
- w[2] = w[2] * wtot_inv;
- }
- else /* dummy values for zero area face */
- w[0] = w[1] = w[2] = 1.0f / 3.0f;
-}
-
-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])
-{
- float wtot_inv, wtot;
- float w_tmp[3];
-
- barycentric_weights_v2_persp(v1, v2, v3, pt, w);
- /* for the depth we need the weights to match what
- * barycentric_weights_v2 would return, in this case its easiest just to
- * undo the 4th axis division and make it unit-sum
- *
- * don't call barycentric_weights_v2() because our callers expect 'w'
- * to be weighted from the perspective */
- w_tmp[0] = w[0] * v1[3];
- w_tmp[1] = w[1] * v2[3];
- w_tmp[2] = w[2] * v3[3];
-
- wtot = w_tmp[0] + w_tmp[1] + w_tmp[2];
-
- if (wtot != 0.0f) {
- wtot_inv = 1.0f / wtot;
-
- w_tmp[0] = w_tmp[0] * wtot_inv;
- w_tmp[1] = w_tmp[1] * wtot_inv;
- w_tmp[2] = w_tmp[2] * wtot_inv;
- }
- else /* dummy values for zero area face */
- w_tmp[0] = w_tmp[1] = w_tmp[2] = 1.0f / 3.0f;
- /* done mimicing barycentric_weights_v2() */
-
- return (v1[2] * w_tmp[0]) + (v2[2] * w_tmp[1]) + (v3[2] * w_tmp[2]);
-}
-
-
-/* Return the top-most face index that the screen space coord 'pt' touches (or -1) */
-static int project_paint_PickFace(const ProjPaintState *ps, float pt[2], float w[3], int *side)
-{
- LinkNode *node;
- float w_tmp[3];
- float *v1, *v2, *v3, *v4;
- int bucket_index;
- int face_index;
- int best_side = -1;
- int best_face_index = -1;
- float z_depth_best = FLT_MAX, z_depth;
- MFace *mf;
-
- bucket_index = project_bucket_offset_safe(ps, pt);
- if (bucket_index == -1)
- return -1;
-
-
-
- /* 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 (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
- face_index = GET_INT_FROM_POINTER(node->link);
- mf = ps->dm_mface + face_index;
-
- 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 (z_depth < z_depth_best) {
- best_face_index = face_index;
- best_side = 0;
- 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 */
-}
-
-/* Converts a uv coord into a pixel location wrapping if the uv is outside 0-1 range */
-static void uvco_to_wrapped_pxco(float uv[2], int ibuf_x, int ibuf_y, float *x, float *y)
-{
- /* use */
- *x = (float)fmodf(uv[0], 1.0f);
- *y = (float)fmodf(uv[1], 1.0f);
-
- if (*x < 0.0f) *x += 1.0f;
- if (*y < 0.0f) *y += 1.0f;
-
- *x = *x * ibuf_x - 0.5f;
- *y = *y * ibuf_y - 0.5f;
-}
-
-/* Set the top-most face color that the screen space coord 'pt' touches (or return 0 if none touch) */
-static int project_paint_PickColor(const ProjPaintState *ps, float pt[2], float *rgba_fp, unsigned char *rgba, const int interp)
-{
- float w[3], uv[2];
- int side;
- int face_index;
- MTFace *tf;
- Image *ima;
- ImBuf *ibuf;
- int xi, yi;
-
-
- face_index = project_paint_PickFace(ps, pt, w, &side);
-
- if (face_index == -1)
- return 0;
-
- tf = ps->dm_mtface + face_index;
-
- 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);
- }
-
- ima = project_paint_face_image(ps, ps->dm_mtface, face_index);
- ibuf = ima->ibufs.first; /* we must have got the imbuf before getting here */
- if (!ibuf) return 0;
-
- if (interp) {
- float x, y;
- uvco_to_wrapped_pxco(uv, ibuf->x, ibuf->y, &x, &y);
-
- if (ibuf->rect_float) {
- if (rgba_fp) {
- bilinear_interpolation_color_wrap(ibuf, NULL, rgba_fp, x, y);
- }
- else {
- float rgba_tmp_f[4];
- bilinear_interpolation_color_wrap(ibuf, NULL, rgba_tmp_f, x, y);
- IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, rgba_tmp_f);
- }
- }
- else {
- if (rgba) {
- bilinear_interpolation_color_wrap(ibuf, rgba, NULL, x, y);
- }
- else {
- unsigned char rgba_tmp[4];
- bilinear_interpolation_color_wrap(ibuf, rgba_tmp, NULL, x, y);
- IMAPAINT_CHAR_RGBA_TO_FLOAT(rgba_fp, rgba_tmp);
- }
- }
- }
- else {
- //xi = (int)((uv[0]*ibuf->x) + 0.5f);
- //yi = (int)((uv[1]*ibuf->y) + 0.5f);
- //if (xi < 0 || xi >= ibuf->x || yi < 0 || yi >= ibuf->y) return 0;
-
- /* wrap */
- xi = ((int)(uv[0] * ibuf->x)) % ibuf->x;
- if (xi < 0) xi += ibuf->x;
- yi = ((int)(uv[1] * ibuf->y)) % ibuf->y;
- if (yi < 0) yi += ibuf->y;
-
-
- if (rgba) {
- if (ibuf->rect_float) {
- float *rgba_tmp_fp = ibuf->rect_float + (xi + yi * ibuf->x * 4);
- IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, rgba_tmp_fp);
- }
- else {
- *((unsigned int *)rgba) = *(unsigned int *)(((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4));
- }
- }
-
- if (rgba_fp) {
- if (ibuf->rect_float) {
- copy_v4_v4(rgba_fp, (ibuf->rect_float + ((xi + yi * ibuf->x) * 4)));
- }
- else {
- char *tmp_ch = ((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4);
- IMAPAINT_CHAR_RGBA_TO_FLOAT(rgba_fp, tmp_ch);
- }
- }
- }
- 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(float pt[3], float v1[4], float v2[4], float v3[4], float w[3], int is_ortho)
-{
- /* if all are behind us, return false */
- if (v1[2] > pt[2] && v2[2] > pt[2] && v3[2] > pt[2])
- return 0;
-
- /* do a 2D point in try intersection */
- if (!isect_point_tri_v2(pt, v1, v2, v3))
- return 0; /* we know there is */
-
-
- /* From here on we know there IS an intersection */
- /* if ALL of the verts are infront of us then we know it intersects ? */
- if (v1[2] < pt[2] && v2[2] < pt[2] && v3[2] < pt[2]) {
- return 1;
- }
- else {
- /* we intersect? - find the exact depth at the point of intersection */
- /* Is this point is occluded by another face? */
- if (is_ortho) {
- if (VecZDepthOrtho(pt, v1, v2, v3, w) < pt[2]) return 2;
- }
- else {
- if (VecZDepthPersp(pt, v1, v2, v3, w) < pt[2]) return 2;
- }
- }
- return -1;
-}
-
-
-static int project_paint_occlude_ptv_clip(const ProjPaintState *ps, const MFace *mf,
- float pt[3], float v1[4], float v2[4], float v3[4],
- const int side)
-{
- float w[3], wco[3];
- int ret = project_paint_occlude_ptv(pt, v1, v2, v3, w, ps->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);
- }
-
- /* 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);
-
- if (!ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) {
- return 1;
- }
-
- return -1;
-}
-
-
-/* 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 dosn't need to be correct in relation to X and Y coords (this is the case in perspective view) */
-static int project_bucket_point_occluded(const ProjPaintState *ps, LinkNode *bucketFace, const int orig_face, 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;
-
- /* 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);
- }
- 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 */
- return 1;
- }
- }
- }
- return 0;
-}
-
-/* basic line intersection, could move to math_geom.c, 2 points with a horiz line
- * 1 for an intersection, 2 if the first point is aligned, 3 if the second point is aligned */
-#define ISECT_TRUE 1
-#define ISECT_TRUE_P1 2
-#define ISECT_TRUE_P2 3
-static int line_isect_y(const float p1[2], const float p2[2], const float y_level, float *x_isect)
-{
- float y_diff;
-
- if (y_level == p1[1]) { /* are we touching the first point? - no interpolation needed */
- *x_isect = p1[0];
- return ISECT_TRUE_P1;
- }
- if (y_level == p2[1]) { /* are we touching the second point? - no interpolation needed */
- *x_isect = p2[0];
- return ISECT_TRUE_P2;
- }
-
- y_diff = fabsf(p1[1] - p2[1]); /* yuck, horizontal line, we cant do much here */
-
- if (y_diff < 0.000001f) {
- *x_isect = (p1[0] + p2[0]) * 0.5f;
- return ISECT_TRUE;
- }
-
- 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]);*/
- 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]);*/
- return ISECT_TRUE;
- }
- else {
- return 0;
- }
-}
-
-static int line_isect_x(const float p1[2], const float p2[2], const float x_level, float *y_isect)
-{
- float x_diff;
-
- if (x_level == p1[0]) { /* are we touching the first point? - no interpolation needed */
- *y_isect = p1[1];
- return ISECT_TRUE_P1;
- }
- if (x_level == p2[0]) { /* are we touching the second point? - no interpolation needed */
- *y_isect = p2[1];
- return ISECT_TRUE_P2;
- }
-
- x_diff = fabsf(p1[0] - p2[0]); /* yuck, horizontal line, we cant do much here */
-
- if (x_diff < 0.000001f) { /* yuck, vertical line, we cant do much here */
- *y_isect = (p1[0] + p2[0]) * 0.5f;
- return ISECT_TRUE;
- }
-
- 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]);*/
- 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]);*/
- return ISECT_TRUE;
- }
- else {
- return 0;
- }
-}
-
-/* simple func use for comparing UV locations to check if there are seams.
- * Its possible this gives incorrect results, when the UVs for 1 face go into the next
- * tile, but do not do this for the adjacent face, it could return a false positive.
- * This is so unlikely that Id not worry about it. */
-#ifndef PROJ_DEBUG_NOSEAMBLEED
-static int cmp_uv(const float vec2a[2], const float vec2b[2])
-{
- /* if the UV's are not between 0.0 and 1.0 */
- float xa = (float)fmodf(vec2a[0], 1.0f);
- float ya = (float)fmodf(vec2a[1], 1.0f);
-
- float xb = (float)fmodf(vec2b[0], 1.0f);
- float yb = (float)fmodf(vec2b[1], 1.0f);
-
- if (xa < 0.0f) xa += 1.0f;
- if (ya < 0.0f) ya += 1.0f;
-
- if (xb < 0.0f) xb += 1.0f;
- if (yb < 0.0f) yb += 1.0f;
-
- return ((fabsf(xa - xb) < PROJ_GEOM_TOLERANCE) && (fabsf(ya - yb) < PROJ_GEOM_TOLERANCE)) ? 1 : 0;
-}
-#endif
-
-/* set min_px and max_px to the image space bounds of the UV coords
- * return zero if there is no area in the returned rectangle */
-#ifndef PROJ_DEBUG_NOSEAMBLEED
-static int pixel_bounds_uv(
- const float uv1[2], const float uv2[2], const float uv3[2], const float uv4[2],
- rcti *bounds_px,
- const int ibuf_x, const int ibuf_y,
- int is_quad
- )
-{
- 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);
-
- bounds_px->xmin = (int)(ibuf_x * min_uv[0]);
- bounds_px->ymin = (int)(ibuf_y * min_uv[1]);
-
- bounds_px->xmax = (int)(ibuf_x * max_uv[0]) + 1;
- bounds_px->ymax = (int)(ibuf_y * max_uv[1]) + 1;
-
- /*printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]);*/
-
- /* face uses no UV area when quantized to pixels? */
- return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1;
-}
-#endif
-
-static int pixel_bounds_array(float (*uv)[2], rcti *bounds_px, const int ibuf_x, const int ibuf_y, int tot)
-{
- float min_uv[2], max_uv[2]; /* UV bounds */
-
- if (tot == 0) {
- return 0;
- }
-
- INIT_MINMAX2(min_uv, max_uv);
-
- while (tot--) {
- minmax_v2v2_v2(min_uv, max_uv, (*uv));
- uv++;
- }
-
- bounds_px->xmin = (int)(ibuf_x * min_uv[0]);
- bounds_px->ymin = (int)(ibuf_y * min_uv[1]);
-
- bounds_px->xmax = (int)(ibuf_x * max_uv[0]) + 1;
- bounds_px->ymax = (int)(ibuf_y * max_uv[1]) + 1;
-
- /*printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]);*/
-
- /* face uses no UV area when quantized to pixels? */
- return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1;
-}
-
-#ifndef PROJ_DEBUG_NOSEAMBLEED
-
-/* This function returns 1 if this face has a seam along the 2 face-vert indices
- * 'orig_i1_fidx' and 'orig_i2_fidx' */
-static int 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)
-{
- 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);
-
- if (face_index != orig_face) {
- mf = ps->dm_mface + face_index;
- /* 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) */
- if (mf->v1 == i1) i1_fidx = 0;
- else if (mf->v2 == i1) i1_fidx = 1;
- else if (mf->v3 == i1) i1_fidx = 2;
- else if (mf->v4 && mf->v4 == i1) i1_fidx = 3;
-
- if (mf->v1 == i2) i2_fidx = 0;
- else if (mf->v2 == i2) i2_fidx = 1;
- else if (mf->v3 == i2) i2_fidx = 2;
- else if (mf->v4 && mf->v4 == i2) i2_fidx = 3;
-
- /* Only need to check if 'i2_fidx' is valid because we know i1_fidx is the same vert on both faces */
- if (i2_fidx != -1) {
- Image *tpage = project_paint_face_image(ps, ps->dm_mtface, face_index);
- Image *orig_tpage = project_paint_face_image(ps, ps->dm_mtface, orig_face);
-
- /* 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;
- *orig_fidx = (i1_fidx < i2_fidx) ? i1_fidx : i2_fidx;
-
- /* 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]) )
- {
- // printf("SEAM (NONE)\n");
- return 0;
-
- }
- else {
- // printf("SEAM (UV GAP)\n");
- return 1;
- }
- }
- }
- }
- // printf("SEAM (NO FACE)\n");
- *other_face = -1;
- return 1;
-}
-
-/* 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 int is_quad)
-{
- 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 ibuf_inv[2];
-
- ibuf_inv[0] = 1.0f / (float)ibuf_x;
- ibuf_inv[1] = 1.0f / (float)ibuf_y;
-
- /* make UV's in pixel space so we can */
- puv[0][0] = orig_uv[0][0] * ibuf_x;
- puv[0][1] = orig_uv[0][1] * ibuf_y;
-
- puv[1][0] = orig_uv[1][0] * ibuf_x;
- puv[1][1] = orig_uv[1][1] * ibuf_y;
-
- 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]);
- 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);
- }
-
- /* TODO - angle_normalized_v2v2(...) * (M_PI/180.0f)
- * This is incorrect. Its already given radians but without it wont work.
- * need to look into a fix - campbell */
- if (is_quad) {
- a1 = shell_angle_to_dist(angle_normalized_v2v2(dir4, dir1) * ((float)M_PI / 180.0f));
- a2 = shell_angle_to_dist(angle_normalized_v2v2(dir1, dir2) * ((float)M_PI / 180.0f));
- a3 = shell_angle_to_dist(angle_normalized_v2v2(dir2, dir3) * ((float)M_PI / 180.0f));
- a4 = shell_angle_to_dist(angle_normalized_v2v2(dir3, dir4) * ((float)M_PI / 180.0f));
- }
- else {
- a1 = shell_angle_to_dist(angle_normalized_v2v2(dir3, dir1) * ((float)M_PI / 180.0f));
- a2 = shell_angle_to_dist(angle_normalized_v2v2(dir1, dir2) * ((float)M_PI / 180.0f));
- a3 = shell_angle_to_dist(angle_normalized_v2v2(dir2, dir3) * ((float)M_PI / 180.0f));
- }
-
- 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);
- }
- 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);
- }
-}
-
-/*
- * Be tricky with flags, first 4 bits are PROJ_FACE_SEAM1 to 4, last 4 bits are PROJ_FACE_NOSEAM1 to 4
- * 1<<i - where i is (0-3)
- *
- * 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)
-{
- int other_face, other_fidx; /* vars for the other face, we also set its flag */
- int fidx1 = is_quad ? 3 : 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 */
-
- 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 (other_face != -1)
- ps->faceSeamFlags[other_face] |= 1 << other_fidx;
- }
- else {
- ps->faceSeamFlags[face_index] |= 16 << fidx1;
- if (other_face != -1)
- ps->faceSeamFlags[other_face] |= 16 << other_fidx; /* second 4 bits for disabled */
- }
- }
-
- fidx2 = fidx1;
- } while (fidx1--);
-}
-#endif // PROJ_DEBUG_NOSEAMBLEED
-
-
-/* Converts a UV location to a 3D screenspace location
- * Takes a 'uv' and 3 UV coords, and sets the values of pixelScreenCo
- *
- * This is used for finding a pixels location in screenspace for painting */
-static void screen_px_from_ortho(
- float uv[2],
- float v1co[3], float v2co[3], float v3co[3], /* Screenspace coords */
- float uv1co[2], float uv2co[2], float uv3co[2],
- float pixelScreenCo[4],
- float w[3])
-{
- barycentric_weights_v2(uv1co, uv2co, uv3co, uv, w);
- interp_v3_v3v3v3(pixelScreenCo, v1co, v2co, v3co, w);
-}
-
-/* same as screen_px_from_ortho except we need to take into account
- * the perspective W coord for each vert */
-static void screen_px_from_persp(
- float uv[2],
- float v1co[4], float v2co[4], float v3co[4], /* screenspace coords */
- float uv1co[2], float uv2co[2], float uv3co[2],
- float pixelScreenCo[4],
- float w[3])
-{
-
- float wtot_inv, wtot;
- barycentric_weights_v2(uv1co, uv2co, uv3co, uv, w);
-
- /* re-weight from the 4th coord of each screen vert */
- w[0] *= v1co[3];
- w[1] *= v2co[3];
- w[2] *= v3co[3];
-
- wtot = w[0] + w[1] + w[2];
-
- if (wtot > 0.0f) {
- wtot_inv = 1.0f / wtot;
- w[0] *= wtot_inv;
- w[1] *= wtot_inv;
- w[2] *= wtot_inv;
- }
- else {
- w[0] = w[1] = w[2] = 1.0f / 3.0f; /* dummy values for zero area face */
- }
- /* done re-weighting */
-
- interp_v3_v3v3v3(pixelScreenCo, v1co, v2co, v3co, w);
-}
-
-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])
-{
- float *uvCo1, *uvCo2, *uvCo3;
- float uv_other[2], x, y;
-
- 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];
- }
-
- interp_v2_v2v2v2(uv_other, uvCo1, uvCo2, uvCo3, (float *)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);
- }
- else { /* from char to float */
- bilinear_interpolation_color_wrap(ibuf_other, rgba_ub, NULL, x, y);
- }
-
-}
-
-/* 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 float w[3])
-{
- float mask;
-
- /* Image Mask */
- if (ps->do_layer_stencil) {
- /* another UV maps image is masking this one's */
- ImBuf *ibuf_other;
- Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_stencil, face_index);
- const MTFace *tf_other = ps->dm_mtface_stencil + face_index;
-
- if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
- /* 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);
-
- if (ibuf_other->rect_float) { /* from float to float */
- mask = ((rgba_f[0] + rgba_f[1] + rgba_f[2]) / 3.0f) * rgba_f[3];
- }
- else { /* from char to float */
- mask = ((rgba_ub[0] + rgba_ub[1] + rgba_ub[2]) / (256 * 3.0f)) * (rgba_ub[3] / 256.0f);
- }
-
- BKE_image_release_ibuf(other_tpage, ibuf_other, NULL);
-
- if (!ps->do_layer_stencil_inv) /* matching the gimps layer mask black/white rules, white==full opacity */
- mask = (1.0f - mask);
-
- if (mask == 0.0f) {
- return 0.0f;
- }
- }
- else {
- return 0.0f;
- }
- }
- else {
- mask = 1.0f;
- }
-
- /* calculate mask */
- if (ps->do_mask_normal) {
- MFace *mf = &ps->dm_mface[face_index];
- float no[3], angle;
- if (mf->flag & ME_SMOOTH) {
- 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;
- }
-
- 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];
- no[2] = w[0] * no1[2] + w[1] * no2[2] + w[2] * no3[2];
- normalize_v3(no);
- }
- else {
- /* 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);
-#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));
-#endif
- }
-
- /* now we can use the normal as a mask */
- if (ps->is_ortho) {
- angle = angle_normalized_v3v3((float *)ps->viewDir, no);
- }
- else {
- /* Annoying but for the perspective view we need to get the pixels location in 3D space :/ */
- float viewDirPersp[3];
- 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;
- }
-
- /* 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);
-
- angle = angle_normalized_v3v3(viewDirPersp, no);
- }
-
- if (angle >= ps->normal_angle) {
- return 0.0f; /* outsize the normal limit*/
- }
- else if (angle > ps->normal_angle_inner) {
- mask *= (ps->normal_angle - angle) / ps->normal_angle_range;
- } /* otherwise no mask normal is needed, were within the limit */
- }
-
- /* This only works when the opacity dosnt change while painting, stylus pressure messes with this
- * so don't use it. */
- // if (ps->is_airbrush == 0) mask *= BKE_brush_alpha_get(ps->brush);
-
- return mask;
-}
-
-static int project_paint_pixel_sizeof(const short tool)
-{
- if ((tool == PAINT_TOOL_CLONE) || (tool == PAINT_TOOL_SMEAR)) {
- return sizeof(ProjPixelClone);
- }
- else {
- return sizeof(ProjPixel);
- }
-}
-
-/* run this function when we know a bucket's, face's pixel can be initialized,
- * return the ProjPixel which is added to 'ps->bucketRect[bucket_index]' */
-static ProjPixel *project_paint_uvpixel_init(
- const ProjPaintState *ps,
- MemArena *arena,
- const ImBuf *ibuf,
- short x_px, short y_px,
- const float mask,
- const int face_index,
- const int image_index,
- const float pixelScreenCo[4],
- const int side,
- const float w[3])
-{
- ProjPixel *projPixel;
-
- /* wrap pixel location */
- x_px = x_px % ibuf->x;
- if (x_px < 0) x_px += ibuf->x;
- y_px = y_px % ibuf->y;
- if (y_px < 0) y_px += ibuf->y;
-
- BLI_assert(ps->pixel_sizeof == project_paint_pixel_sizeof(ps->tool));
- projPixel = (ProjPixel *)BLI_memarena_alloc(arena, ps->pixel_sizeof);
- //memset(projPixel, 0, size);
-
- if (ibuf->rect_float) {
- projPixel->pixel.f_pt = ibuf->rect_float + ((x_px + y_px * ibuf->x) * 4);
- projPixel->origColor.f[0] = projPixel->newColor.f[0] = projPixel->pixel.f_pt[0];
- projPixel->origColor.f[1] = projPixel->newColor.f[1] = projPixel->pixel.f_pt[1];
- projPixel->origColor.f[2] = projPixel->newColor.f[2] = projPixel->pixel.f_pt[2];
- projPixel->origColor.f[3] = projPixel->newColor.f[3] = projPixel->pixel.f_pt[3];
- }
- else {
- projPixel->pixel.ch_pt = ((unsigned char *)ibuf->rect + ((x_px + y_px * ibuf->x) * 4));
- projPixel->origColor.uint = projPixel->newColor.uint = *projPixel->pixel.uint_pt;
- }
-
- /* screenspace unclamped, we could keep its z and w values but don't need them at the moment */
- copy_v2_v2(projPixel->projCoSS, pixelScreenCo);
-
- projPixel->x_px = x_px;
- projPixel->y_px = y_px;
-
- projPixel->mask = (unsigned short)(mask * 65535);
- projPixel->mask_max = 0;
-
- /* which bounding box cell are we in?, needed for undo */
- projPixel->bb_cell_index = ((int)(((float)x_px / (float)ibuf->x) * PROJ_BOUNDBOX_DIV)) +
- ((int)(((float)y_px / (float)ibuf->y) * PROJ_BOUNDBOX_DIV)) * PROJ_BOUNDBOX_DIV;
-
- /* done with view3d_project_float inline */
- if (ps->tool == PAINT_TOOL_CLONE) {
- if (ps->dm_mtface_clone) {
- ImBuf *ibuf_other;
- Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_clone, face_index);
- const MTFace *tf_other = ps->dm_mtface_clone + face_index;
-
- if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
- /* 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);
- }
- else { /* from char to float */
- unsigned char rgba_ub[4];
- project_face_pixel(tf_other, ibuf_other, w, side, rgba_ub, NULL);
- IMAPAINT_CHAR_RGBA_TO_FLOAT(((ProjPixelClone *)projPixel)->clonepx.f, rgba_ub);
- }
- }
- else {
- if (ibuf_other->rect_float) { /* float to char */
- float rgba[4];
- project_face_pixel(tf_other, ibuf_other, w, side, NULL, rgba);
- IMAPAINT_FLOAT_RGBA_TO_CHAR(((ProjPixelClone *)projPixel)->clonepx.ch, rgba);
- }
- else { /* char to char */
- project_face_pixel(tf_other, ibuf_other, w, side, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL);
- }
- }
-
- BKE_image_release_ibuf(other_tpage, ibuf_other, NULL);
- }
- else {
- if (ibuf->rect_float) {
- ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0;
- }
- else {
- ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0;
- }
- }
-
- }
- else {
- float co[2];
- sub_v2_v2v2(co, projPixel->projCoSS, (float *)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(...) */
- if (ibuf->rect_float) {
- if (!project_paint_PickColor(ps, co, ((ProjPixelClone *)projPixel)->clonepx.f, NULL, 1)) {
- ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0; /* zero alpha - ignore */
- }
- }
- else {
- if (!project_paint_PickColor(ps, co, NULL, ((ProjPixelClone *)projPixel)->clonepx.ch, 1)) {
- ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0; /* zero alpha - ignore */
- }
- }
- }
- }
-
-#ifdef PROJ_DEBUG_PAINT
- if (ibuf->rect_float) projPixel->pixel.f_pt[0] = 0;
- else projPixel->pixel.ch_pt[0] = 0;
-#endif
- projPixel->image_index = image_index;
-
- return projPixel;
-}
-
-static int line_clip_rect2f(
- 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) {
- /* is the line out of range on its Y axis? */
- if (l1[1] < rect->ymin || l1[1] > rect->ymax) {
- return 0;
- }
- /* line is out of range on its X axis */
- if ((l1[0] < rect->xmin && l2[0] < rect->xmin) || (l1[0] > rect->xmax && l2[0] > rect->xmax)) {
- return 0;
- }
-
-
- if (fabsf(l1[0] - l2[0]) < PROJ_GEOM_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);
- return 1;
- }
- else {
- return 0;
- }
- }
-
- copy_v2_v2(l1_clip, l1);
- copy_v2_v2(l2_clip, l2);
- CLAMP(l1_clip[0], rect->xmin, rect->xmax);
- CLAMP(l2_clip[0], rect->xmin, rect->xmax);
- return 1;
- }
- else if (fabsf(l1[0] - l2[0]) < PROJ_GEOM_TOLERANCE) {
- /* is the line out of range on its X axis? */
- if (l1[0] < rect->xmin || l1[0] > rect->xmax) {
- return 0;
- }
-
- /* line is out of range on its Y axis */
- if ((l1[1] < rect->ymin && l2[1] < rect->ymin) || (l1[1] > rect->ymax && l2[1] > rect->ymax)) {
- return 0;
- }
-
- if (fabsf(l1[1] - l2[1]) < PROJ_GEOM_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);
- return 1;
- }
- else {
- return 0;
- }
- }
-
- copy_v2_v2(l1_clip, l1);
- copy_v2_v2(l2_clip, l2);
- CLAMP(l1_clip[1], rect->ymin, rect->ymax);
- CLAMP(l2_clip[1], rect->ymin, rect->ymax);
- return 1;
- }
- else {
- float isect;
- short ok1 = 0;
- short ok2 = 0;
-
- /* Done with vertical lines */
-
- /* are either of the points inside the rectangle ? */
- if (BLI_rctf_isect_pt_v(rect, l1)) {
- copy_v2_v2(l1_clip, l1);
- ok1 = 1;
- }
-
- if (BLI_rctf_isect_pt_v(rect, l2)) {
- copy_v2_v2(l2_clip, l2);
- ok2 = 1;
- }
-
- /* line inside rect */
- if (ok1 && ok2) return 1;
-
- /* top/bottom */
- if (line_isect_y(l1, l2, rect->ymin, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) {
- if (l1[1] < l2[1]) { /* line 1 is outside */
- l1_clip[0] = isect;
- l1_clip[1] = rect->ymin;
- ok1 = 1;
- }
- else {
- l2_clip[0] = isect;
- l2_clip[1] = rect->ymin;
- ok2 = 2;
- }
- }
-
- if (ok1 && ok2) return 1;
-
- if (line_isect_y(l1, l2, rect->ymax, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) {
- if (l1[1] > l2[1]) { /* line 1 is outside */
- l1_clip[0] = isect;
- l1_clip[1] = rect->ymax;
- ok1 = 1;
- }
- else {
- l2_clip[0] = isect;
- l2_clip[1] = rect->ymax;
- ok2 = 2;
- }
- }
-
- if (ok1 && ok2) return 1;
-
- /* left/right */
- if (line_isect_x(l1, l2, rect->xmin, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) {
- if (l1[0] < l2[0]) { /* line 1 is outside */
- l1_clip[0] = rect->xmin;
- l1_clip[1] = isect;
- ok1 = 1;
- }
- else {
- l2_clip[0] = rect->xmin;
- l2_clip[1] = isect;
- ok2 = 2;
- }
- }
-
- if (ok1 && ok2) return 1;
-
- if (line_isect_x(l1, l2, rect->xmax, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) {
- if (l1[0] > l2[0]) { /* line 1 is outside */
- l1_clip[0] = rect->xmax;
- l1_clip[1] = isect;
- ok1 = 1;
- }
- else {
- l2_clip[0] = rect->xmax;
- l2_clip[1] = isect;
- ok2 = 2;
- }
- }
-
- if (ok1 && ok2) {
- return 1;
- }
- else {
- return 0;
- }
- }
-}
-
-
-
-/* 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 */
-#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]) / 4.0f;
- cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1] + origCos[3][1]) / 4.0f;
- cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2] + origCos[3][2]) / 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)
-{
- float cent[3];
- cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0]) / 3.0f;
- cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1]) / 3.0f;
- cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2]) / 3.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);
-
- mul_v3_fl(insetCos[0], inset);
- mul_v3_fl(insetCos[1], inset);
- mul_v3_fl(insetCos[2], inset);
-
- add_v3_v3(insetCos[0], cent);
- add_v3_v3(insetCos[1], cent);
- add_v3_v3(insetCos[2], cent);
-}
-#endif //PROJ_DEBUG_NOSEAMBLEED
-
-static float len_squared_v2v2_alt(const float *v1, const float v2_1, const float v2_2)
-{
- float x, y;
-
- x = v1[0] - v2_1;
- y = v1[1] - v2_2;
- return x * x + y * y;
-}
-
-/* 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 int project_bucket_isect_circle(const float cent[2], const float radius_squared, rctf *bucket_bounds)
-{
-
- /* Would normally to a simple intersection test, however we know the bounds of these 2 already intersect
- * so we only need to test if the center is inside the vertical or horizontal bounds on either axis,
- * this is even less work then an intersection test
- */
-#if 0
- if (BLI_rctf_isect_pt_v(bucket_bounds, cent))
- return 1;
-#endif
-
- if ((bucket_bounds->xmin <= cent[0] && bucket_bounds->xmax >= cent[0]) ||
- (bucket_bounds->ymin <= cent[1] && bucket_bounds->ymax >= cent[1]))
- {
- return 1;
- }
-
- /* out of bounds left */
- if (cent[0] < bucket_bounds->xmin) {
- /* lower left out of radius test */
- if (cent[1] < bucket_bounds->ymin) {
- return (len_squared_v2v2_alt(cent, bucket_bounds->xmin, bucket_bounds->ymin) < radius_squared) ? 1 : 0;
- }
- /* top left test */
- else if (cent[1] > bucket_bounds->ymax) {
- return (len_squared_v2v2_alt(cent, bucket_bounds->xmin, bucket_bounds->ymax) < radius_squared) ? 1 : 0;
- }
- }
- else if (cent[0] > bucket_bounds->xmax) {
- /* lower right out of radius test */
- if (cent[1] < bucket_bounds->ymin) {
- return (len_squared_v2v2_alt(cent, bucket_bounds->xmax, bucket_bounds->ymin) < radius_squared) ? 1 : 0;
- }
- /* top right test */
- else if (cent[1] > bucket_bounds->ymax) {
- return (len_squared_v2v2_alt(cent, bucket_bounds->xmax, bucket_bounds->ymax) < radius_squared) ? 1 : 0;
- }
- }
-
- return 0;
-}
-
-
-
-/* Note for rect_to_uvspace_ortho() and rect_to_uvspace_persp()
- * in ortho view this function gives good results when bucket_bounds are outside the triangle
- * however in some cases, perspective view will mess up with faces that have minimal screenspace area
- * (viewed from the side)
- *
- * for this reason its not reliable in this case so we'll use the Simple Barycentric'
- * funcs that only account for points inside the triangle.
- * however switching back to this for ortho is always an option */
-
-static void rect_to_uvspace_ortho(
- rctf *bucket_bounds,
- float *v1coSS, float *v2coSS, float *v3coSS,
- float *uv1co, float *uv2co, float *uv3co,
- float bucket_bounds_uv[4][2],
- const int flip)
-{
- float uv[2];
- float w[3];
-
- /* get the UV space bounding box */
- uv[0] = bucket_bounds->xmax;
- uv[1] = bucket_bounds->ymin;
- barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
- interp_v2_v2v2v2(bucket_bounds_uv[flip ? 3 : 0], uv1co, uv2co, uv3co, w);
-
- //uv[0] = bucket_bounds->xmax; // set above
- uv[1] = bucket_bounds->ymax;
- barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
- interp_v2_v2v2v2(bucket_bounds_uv[flip ? 2 : 1], uv1co, uv2co, uv3co, w);
-
- uv[0] = bucket_bounds->xmin;
- //uv[1] = bucket_bounds->ymax; // set above
- barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
- interp_v2_v2v2v2(bucket_bounds_uv[flip ? 1 : 2], uv1co, uv2co, uv3co, w);
-
- //uv[0] = bucket_bounds->xmin; // set above
- uv[1] = bucket_bounds->ymin;
- barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
- interp_v2_v2v2v2(bucket_bounds_uv[flip ? 0 : 3], uv1co, uv2co, uv3co, w);
-}
-
-/* same as above but use barycentric_weights_v2_persp */
-static void rect_to_uvspace_persp(
- rctf *bucket_bounds,
- float *v1coSS, float *v2coSS, float *v3coSS,
- float *uv1co, float *uv2co, float *uv3co,
- float bucket_bounds_uv[4][2],
- const int flip
- )
-{
- float uv[2];
- float w[3];
-
- /* get the UV space bounding box */
- uv[0] = bucket_bounds->xmax;
- uv[1] = bucket_bounds->ymin;
- barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
- interp_v2_v2v2v2(bucket_bounds_uv[flip ? 3 : 0], uv1co, uv2co, uv3co, w);
-
- //uv[0] = bucket_bounds->xmax; // set above
- uv[1] = bucket_bounds->ymax;
- barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
- interp_v2_v2v2v2(bucket_bounds_uv[flip ? 2 : 1], uv1co, uv2co, uv3co, w);
-
- uv[0] = bucket_bounds->xmin;
- //uv[1] = bucket_bounds->ymax; // set above
- barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
- interp_v2_v2v2v2(bucket_bounds_uv[flip ? 1 : 2], uv1co, uv2co, uv3co, w);
-
- //uv[0] = bucket_bounds->xmin; // set above
- uv[1] = bucket_bounds->ymin;
- barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
- interp_v2_v2v2v2(bucket_bounds_uv[flip ? 0 : 3], uv1co, uv2co, uv3co, w);
-}
-
-/* This works as we need it to but we can save a few steps and not use it */
-
-#if 0
-static float angle_2d_clockwise(const float p1[2], const float p2[2], const float p3[2])
-{
- float v1[2], v2[2];
-
- 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]);
-}
-#endif
-
-#define ISECT_1 (1)
-#define ISECT_2 (1 << 1)
-#define ISECT_3 (1 << 2)
-#define ISECT_4 (1 << 3)
-#define ISECT_ALL3 ((1 << 3) - 1)
-#define ISECT_ALL4 ((1 << 4) - 1)
-
-/* limit must be a fraction over 1.0f */
-static int IsectPT2Df_limit(float pt[2], float v1[2], float v2[2], float v3[2], float limit)
-{
- return ((area_tri_v2(pt, v1, v2) + area_tri_v2(pt, v2, v3) + area_tri_v2(pt, v3, v1)) / (area_tri_v2(v1, v2, v3))) < limit;
-}
-
-/* Clip the face by a bucket and set the uv-space bucket_bounds_uv
- * so we have the clipped UV's to do pixel intersection tests with
- * */
-static int float_z_sort_flip(const void *p1, const void *p2)
-{
- return (((float *)p1)[2] < ((float *)p2)[2] ? 1 : -1);
-}
-
-static int float_z_sort(const void *p1, const void *p2)
-{
- return (((float *)p1)[2] < ((float *)p2)[2] ? -1 : 1);
-}
-
-static void project_bucket_clip_face(
- const int is_ortho,
- rctf *bucket_bounds,
- float *v1coSS, float *v2coSS, float *v3coSS,
- float *uv1co, float *uv2co, float *uv3co,
- float bucket_bounds_uv[8][2],
- int *tot)
-{
- 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));
-
- float bucket_bounds_ss[4][2];
-
- /* get the UV space bounding box */
- inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v1coSS);
- inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v2coSS) << 1;
- inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v3coSS) << 2;
-
- if (inside_bucket_flag == ISECT_ALL3) {
- /* all screenspace points are inside the bucket bounding box, this means we don't need to clip and can simply return the UVs */
- if (flip) { /* facing the back? */
- copy_v2_v2(bucket_bounds_uv[0], uv3co);
- copy_v2_v2(bucket_bounds_uv[1], uv2co);
- copy_v2_v2(bucket_bounds_uv[2], uv1co);
- }
- else {
- 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;
- }
-
- /* get the UV space bounding box */
- /* use IsectPT2Df_limit here so we catch points are are touching the tri edge (or a small fraction over) */
- bucket_bounds_ss[0][0] = bucket_bounds->xmax;
- bucket_bounds_ss[0][1] = bucket_bounds->ymin;
- inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[0], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_1 : 0);
-
- bucket_bounds_ss[1][0] = bucket_bounds->xmax;
- bucket_bounds_ss[1][1] = bucket_bounds->ymax;
- inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[1], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_2 : 0);
-
- bucket_bounds_ss[2][0] = bucket_bounds->xmin;
- bucket_bounds_ss[2][1] = bucket_bounds->ymax;
- inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[2], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_3 : 0);
-
- bucket_bounds_ss[3][0] = bucket_bounds->xmin;
- 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);
-
- 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);
-
- *tot = 4;
- return;
- }
- else {
- /* The Complicated Case!
- *
- * The 2 cases above are where the face is inside the bucket or the bucket is inside the face.
- *
- * we need to make a convex polyline from the intersection between the screenspace face
- * and the bucket bounds.
- *
- * There are a number of ways this could be done, currently it just collects all intersecting verts,
- * and line intersections, then sorts them clockwise, this is a lot easier then evaluating the geometry to
- * do a correct clipping on both shapes. */
-
-
- /* add a bunch of points, we know must make up the convex hull which is the clipped rect and triangle */
-
-
-
- /* Maximum possible 6 intersections when using a rectangle and triangle */
- float isectVCosSS[8][3]; /* The 3rd float is used to store angle for qsort(), NOT as a Z location */
- float v1_clipSS[2], v2_clipSS[2];
- float w[3];
-
- /* calc center */
- float cent[2] = {0.0f, 0.0f};
- /*float up[2] = {0.0f, 1.0f};*/
- int i;
- short doubles;
-
- (*tot) = 0;
-
- if (inside_face_flag & ISECT_1) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[0]); (*tot)++; }
- if (inside_face_flag & ISECT_2) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[1]); (*tot)++; }
- if (inside_face_flag & ISECT_3) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[2]); (*tot)++; }
- if (inside_face_flag & ISECT_4) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[3]); (*tot)++; }
-
- if (inside_bucket_flag & ISECT_1) { copy_v2_v2(isectVCosSS[*tot], v1coSS); (*tot)++; }
- if (inside_bucket_flag & ISECT_2) { copy_v2_v2(isectVCosSS[*tot], v2coSS); (*tot)++; }
- 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 ((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 ((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 ((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)++; }
- }
- }
-
-
- if ((*tot) < 3) { /* no intersections to speak of */
- *tot = 0;
- return;
- }
-
- /* now we have all points we need, collect their angles and sort them clockwise */
-
- for (i = 0; i < (*tot); i++) {
- cent[0] += isectVCosSS[i][0];
- cent[1] += isectVCosSS[i][1];
- }
- cent[0] = cent[0] / (float)(*tot);
- cent[1] = cent[1] / (float)(*tot);
-
-
-
- /* Collect angles for every point around the center point */
-
-
-#if 0 /* uses a few more cycles then the above loop */
- for (i = 0; i < (*tot); i++) {
- isectVCosSS[i][2] = angle_2d_clockwise(up, cent, isectVCosSS[i]);
- }
-#endif
-
- v1_clipSS[0] = cent[0]; /* Abuse this var for the loop below */
- v1_clipSS[1] = cent[1] + 1.0f;
-
- 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]);
- }
-
- 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_GEOM_TOLERANCE &&
- fabsf(isectVCosSS[0][1] - isectVCosSS[(*tot) - 1][1]) < PROJ_GEOM_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_GEOM_TOLERANCE &&
- fabsf(isectVCosSS[i - 1][1] - isectVCosSS[i][1]) < PROJ_GEOM_TOLERANCE)
- {
- int j;
- for (j = i + 1; j < (*tot); j++) {
- isectVCosSS[j - 1][0] = isectVCosSS[j][0];
- isectVCosSS[j - 1][1] = isectVCosSS[j][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;
- }
-
-
- if (is_ortho) {
- for (i = 0; i < (*tot); i++) {
- barycentric_weights_v2(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w);
- interp_v2_v2v2v2(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w);
- }
- }
- else {
- for (i = 0; i < (*tot); i++) {
- barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w);
- interp_v2_v2v2v2(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w);
- }
- }
- }
-
-#ifdef PROJ_DEBUG_PRINT_CLIP
- /* include this at the bottom of the above function to debug the output */
-
- {
- /* If there are ever any problems, */
- float test_uv[4][2];
- 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)], ", uv1co[0], uv1co[1], uv2co[0], uv2co[1], uv3co[0], uv3co[1]);
-
- printf("[");
- for (i = 0; i < (*tot); i++) {
- printf("(%f, %f),", bucket_bounds_uv[i][0], bucket_bounds_uv[i][1]);
- }
- printf("]),\\\n");
- }
-#endif
-}
-
-/*
- * # This script creates faces in a blender scene from printed data above.
- *
- * project_ls = [
- * ...(output from above block)...
- * ]
- *
- * from Blender import Scene, Mesh, Window, sys, Mathutils
- *
- * import bpy
- *
- * V = Mathutils.Vector
- *
- * def main():
- * sce = bpy.data.scenes.active
- *
- * for item in project_ls:
- * bb = item[0]
- * uv = item[1]
- * poly = item[2]
- *
- * me = bpy.data.meshes.new()
- * ob = sce.objects.new(me)
- *
- * me.verts.extend([V(bb[0]).xyz, V(bb[1]).xyz, V(bb[2]).xyz, V(bb[3]).xyz])
- * me.faces.extend([(0,1,2,3),])
- * me.verts.extend([V(uv[0]).xyz, V(uv[1]).xyz, V(uv[2]).xyz])
- * me.faces.extend([(4,5,6),])
- *
- * vs = [V(p).xyz for p in poly]
- * print len(vs)
- * l = len(me.verts)
- * me.verts.extend(vs)
- *
- * i = l
- * while i < len(me.verts):
- * ii = i + 1
- * if ii == len(me.verts):
- * ii = l
- * me.edges.extend([i, ii])
- * i += 1
- *
- * if __name__ == '__main__':
- * main()
- */
-
-
-#undef ISECT_1
-#undef ISECT_2
-#undef ISECT_3
-#undef ISECT_4
-#undef ISECT_ALL3
-#undef ISECT_ALL4
-
-
-/* checks if pt is inside a convex 2D polyline, the polyline must be ordered rotating clockwise
- * otherwise it would have to test for mixed (line_point_side_v2 > 0.0f) cases */
-static int IsectPoly2Df(const float pt[2], float uv[][2], const int tot)
-{
- int i;
- if (line_point_side_v2(uv[tot - 1], uv[0], pt) < 0.0f)
- return 0;
-
- for (i = 1; i < tot; i++) {
- if (line_point_side_v2(uv[i - 1], uv[i], pt) < 0.0f)
- return 0;
-
- }
-
- return 1;
-}
-static int 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);
-
- for (i = 1; i < tot; i++) {
- if ((line_point_side_v2(uv[i - 1], uv[i], pt) > 0.0f) != side)
- return 0;
-
- }
-
- 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, const ImBuf *ibuf, const short clamp_u, const short clamp_v)
-{
- /* Projection vars, to get the 3D locations into screen space */
- MemArena *arena = ps->arena_mt[thread_index];
- LinkNode **bucketPixelNodes = ps->bucketRect + bucket_index;
- LinkNode *bucketFaceNodes = ps->bucketFaces[bucket_index];
-
- const MFace *mf = ps->dm_mface + face_index;
- const MTFace *tf = ps->dm_mtface + face_index;
-
- /* UV/pixel seeking data */
- int x; /* Image X-Pixel */
- int y; /* Image Y-Pixel */
- 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 */
-
- float *vCo[4]; /* 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 pixelScreenCo[4];
-
- 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 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 short is_ortho = ps->is_ortho;
- const short do_backfacecull = ps->do_backfacecull;
- const short 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;
-
-
- /* Use tf_uv_pxoffset instead of tf->uv so we can offset the UV half a pixel
- * this is done so we can avoid offsetting all the pixels by 0.5 which causes
- * problems when wrapping negative coords */
- xhalfpx = (0.5f + (PROJ_GEOM_TOLERANCE / 3.0f)) / ibuf_xf;
- yhalfpx = (0.5f + (PROJ_GEOM_TOLERANCE / 4.0f)) / ibuf_yf;
-
- /* Note about (PROJ_GEOM_TOLERANCE/x) above...
- * Needed to add this offset since UV coords are often quads aligned to pixels.
- * In this case pixels can be exactly between 2 triangles causing nasty
- * artifacts.
- *
- * This workaround can be removed and painting will still work on most cases
- * 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;
-
- tf_uv_pxoffset[2][0] = tf->uv[2][0] - xhalfpx;
- tf_uv_pxoffset[2][1] = tf->uv[2][1] - yhalfpx;
-
- if (mf->v4) {
- vCo[3] = ps->dm_mvert[mf->v4].co;
-
- 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];
-
- v1coSS = ps->screenCoords[(*(&mf->v1 + i1))];
- v2coSS = ps->screenCoords[(*(&mf->v1 + i2))];
- v3coSS = ps->screenCoords[(*(&mf->v1 + i3))];
-
- /* This funtion gives is a concave polyline in UV space from the clipped quad and tri*/
- project_bucket_clip_face(
- is_ortho, bucket_bounds,
- v1coSS, v2coSS, v3coSS,
- uv1co, uv2co, uv3co,
- uv_clip, &uv_clip_tot
- );
-
- /* sometimes this happens, better just allow for 8 intersectiosn even though there should be max 6 */
-#if 0
- if (uv_clip_tot > 6) {
- printf("this should never happen! %d\n", uv_clip_tot);
- }
-#endif
-
- if (pixel_bounds_array(uv_clip, &bounds_px, ibuf->x, ibuf->y, uv_clip_tot)) {
-
- if (clamp_u) {
- CLAMP(bounds_px.xmin, 0, ibuf->x);
- CLAMP(bounds_px.xmax, 0, ibuf->x);
- }
-
- if (clamp_v) {
- CLAMP(bounds_px.ymin, 0, ibuf->y);
- CLAMP(bounds_px.ymax, 0, ibuf->y);
- }
-
- /* clip face and */
-
- has_isect = 0;
- for (y = bounds_px.ymin; y < bounds_px.ymax; y++) {
- //uv[1] = (((float)y) + 0.5f) / (float)ibuf->y;
- uv[1] = (float)y / ibuf_yf; /* use pixel offset UV coords instead */
-
- has_x_isect = 0;
- for (x = bounds_px.xmin; x < bounds_px.xmax; x++) {
- //uv[0] = (((float)x) + 0.5f) / ibuf->x;
- uv[0] = (float)x / ibuf_xf; /* use pixel offset UV coords instead */
-
- /* Note about IsectPoly2Df_twoside, checking the face or uv flipping doesnt work,
- * could check the poly direction but better to do this */
- if ((do_backfacecull == TRUE && IsectPoly2Df(uv, uv_clip, uv_clip_tot)) ||
- (do_backfacecull == FALSE && IsectPoly2Df_twoside(uv, uv_clip, uv_clip_tot)))
- {
-
- has_x_isect = has_isect = 1;
-
- if (is_ortho) screen_px_from_ortho(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
- else screen_px_from_persp(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
-
- /* a pity we need to get the worldspace pixel location here */
- if (do_clip) {
- 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);
- if (ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) {
- continue; /* Watch out that no code below this needs to run */
- }
- }
-
- /* 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 ((ps->do_occlude == FALSE) ||
- !project_bucket_point_occluded(ps, bucketFaceNodes, face_index, pixelScreenCo))
- {
-
- mask = project_paint_uvpixel_mask(ps, face_index, side, w);
-
- if (mask > 0.0f) {
- BLI_linklist_prepend_arena(
- bucketPixelNodes,
- project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, side, w),
- arena
- );
- }
- }
-
- }
-//#if 0
- else if (has_x_isect) {
- /* assuming the face is not a bow-tie - we know we cant intersect again on the X */
- break;
- }
-//#endif
- }
-
-
-#if 0 /* TODO - investigate why this dosnt work sometimes! it should! */
- /* no intersection for this entire row, after some intersection above means we can quit now */
- if (has_x_isect == 0 && has_isect) {
- break;
- }
-#endif
- }
- }
- } while (side--);
-
-
-
-#ifndef PROJ_DEBUG_NOSEAMBLEED
- if (ps->seam_bleed_px > 0.0f) {
- int face_seam_flag;
-
- if (ps->thread_tot > 1)
- BLI_lock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
-
- face_seam_flag = ps->faceSeamFlags[face_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)
- {
- 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);
- }
-
- if ((face_seam_flag & (PROJ_FACE_SEAM1 | PROJ_FACE_SEAM2 | PROJ_FACE_SEAM3 | PROJ_FACE_SEAM4)) == 0) {
-
- if (ps->thread_tot > 1)
- BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
-
- }
- else {
- /* 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 *vCoSS[4]; /* 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;
-
-
- 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);
-
- /* ps->faceSeamUVs cant be modified when threading, now this is done we can unlock */
- if (ps->thread_tot > 1)
- 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];
-
- /* 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);
- }
- else {
- if (mf->v4) scale_quad(insetCos, vCo, PROJ_FACE_SCALE_SEAM);
- else 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) */
-
- 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]))
- {
-
- 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;
- }
-
- 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[2], outset_uv[fidx1], outset_uv[fidx2], fac2);
- interp_v2_v2v2(seam_subsection[3], outset_uv[fidx1], outset_uv[fidx2], fac1);
-
- /* if the bucket_clip_edges values Z values was kept we could avoid this
- * Inset needs to be added so occlusion tests wont hit adjacent faces */
- interp_v3_v3v3(edge_verts_inset_clip[0], insetCos[fidx1], insetCos[fidx2], fac1);
- 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, 1)) {
- /* bounds between the seam rect and the uvspace bucket pixels */
-
- has_isect = 0;
- for (y = bounds_px.ymin; y < bounds_px.ymax; y++) {
- // uv[1] = (((float)y) + 0.5f) / (float)ibuf->y;
- uv[1] = (float)y / ibuf_yf; /* use offset uvs instead */
-
- has_x_isect = 0;
- for (x = bounds_px.xmin; x < bounds_px.xmax; x++) {
- //uv[0] = (((float)x) + 0.5f) / (float)ibuf->x;
- 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])) {
- float fac;
-
- /* We need to find the closest point along the face edge,
- * getting the screen_px_from_*** wont work because our actual location
- * is not relevant, since we are outside the face, Use VecLerpf to find
- * our location on the side of the face's UV */
-#if 0
- if (is_ortho) screen_px_from_ortho(ps, uv, v1co, v2co, v3co, uv1co, uv2co, uv3co, pixelScreenCo);
- else screen_px_from_persp(ps, uv, v1co, v2co, v3co, uv1co, uv2co, uv3co, pixelScreenCo);
-#endif
-
- /* 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); }
-
- if (!is_ortho) {
- pixelScreenCo[3] = 1.0f;
- mul_m4_v4((float(*)[4])ps->projectMat, pixelScreenCo); /* cast because of const */
- pixelScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * pixelScreenCo[0] / pixelScreenCo[3];
- pixelScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * pixelScreenCo[1] / pixelScreenCo[3];
- pixelScreenCo[2] = pixelScreenCo[2] / pixelScreenCo[3]; /* Use the depth for bucket point occlusion */
- }
-
- if ((ps->do_occlude == FALSE) ||
- !project_bucket_point_occluded(ps, bucketFaceNodes, face_index, pixelScreenCo))
- {
- /* Only bother calculating the weights if we intersect */
- if (ps->do_mask_normal || ps->dm_mtface_clone) {
-#if 1
- /* 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 */
-
- /* 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;
- }
-#endif
- }
-
- /* a pity we need to get the worldspace pixel location here */
- if (do_clip) {
- 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);
-
- if (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);
-
- if (mask > 0.0f) {
- BLI_linklist_prepend_arena(
- bucketPixelNodes,
- project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, side, w),
- arena
- );
- }
-
- }
- }
- else if (has_x_isect) {
- /* assuming the face is not a bow-tie - we know we cant intersect again on the X */
- break;
- }
- }
-
-#if 0 /* TODO - investigate why this dosnt work sometimes! it should! */
- /* no intersection for this entire row, after some intersection above means we can quit now */
- if (has_x_isect == 0 && has_isect) {
- break;
- }
-#endif
- }
- }
- }
- }
- }
- }
- }
-#endif // PROJ_DEBUG_NOSEAMBLEED
-}
-
-
-/* takes floating point screenspace min/max and returns int min/max to be used as indices for ps->bucketRect, ps->bucketFlags */
-static void project_paint_bucket_bounds(const ProjPaintState *ps, const float min[2], const float max[2], int bucketMin[2], int bucketMax[2])
-{
- /* divide by bucketWidth & bucketHeight so the bounds are offset in bucket grid units */
- /* XXX: the offset of 0.5 is always truncated to zero and the offset of 1.5f is always truncated to 1, is this really correct?? - jwilkins */
- bucketMin[0] = (int)((int)(((float)(min[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 0.5f); /* these offsets of 0.5 and 1.5 seem odd but they are correct */
- bucketMin[1] = (int)((int)(((float)(min[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 0.5f);
-
- bucketMax[0] = (int)((int)(((float)(max[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 1.5f);
- bucketMax[1] = (int)((int)(((float)(max[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 1.5f);
-
- /* in case the rect is outside the mesh 2d bounds */
- CLAMP(bucketMin[0], 0, ps->buckets_x);
- CLAMP(bucketMin[1], 0, ps->buckets_y);
-
- CLAMP(bucketMax[0], 0, ps->buckets_x);
- CLAMP(bucketMax[1], 0, ps->buckets_y);
-}
-
-/* set bucket_bounds to a screen space-aligned floating point bound-box */
-static void project_bucket_bounds(const ProjPaintState *ps, const int bucket_x, const int bucket_y, rctf *bucket_bounds)
-{
- bucket_bounds->xmin = ps->screenMin[0] + ((bucket_x) * (ps->screen_width / ps->buckets_x)); /* left */
- bucket_bounds->xmax = ps->screenMin[0] + ((bucket_x + 1) * (ps->screen_width / ps->buckets_x)); /* right */
-
- bucket_bounds->ymin = ps->screenMin[1] + ((bucket_y) * (ps->screen_height / ps->buckets_y)); /* bottom */
- bucket_bounds->ymax = ps->screenMin[1] + ((bucket_y + 1) * (ps->screen_height / ps->buckets_y)); /* top */
-}
-
-/* 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)
-{
- LinkNode *node;
- int face_index, image_index = 0;
- ImBuf *ibuf = NULL;
- Image *tpage_last = NULL, *tpage;
- Image *ima = NULL;
-
- if (ps->image_tot == 1) {
- /* Simple loop, no context switching */
- ibuf = ps->projImages[0].ibuf;
- ima = ps->projImages[0].ima;
-
- for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
- project_paint_face_init(ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0, bucket_bounds, ibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V);
- }
- }
- 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);
-
- /* Image context switching */
- tpage = project_paint_face_image(ps, ps->dm_mtface, face_index);
- if (tpage_last != tpage) {
- tpage_last = tpage;
-
- for (image_index = 0; image_index < ps->image_tot; image_index++) {
- if (ps->projImages[image_index].ima == tpage_last) {
- ibuf = ps->projImages[image_index].ibuf;
- ima = ps->projImages[image_index].ima;
- break;
- }
- }
- }
- /* context switching done */
-
- project_paint_face_init(ps, thread_index, bucket_index, face_index, image_index, bucket_bounds, ibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V);
- }
- }
-
- ps->bucketFlags[bucket_index] |= PROJ_BUCKET_INIT;
-}
-
-
-/* We want to know if a bucket and a face overlap in screen-space
- *
- * Note, if this ever returns false positives its not that bad, since a face in the bounding area will have its pixels
- * calculated when it might not be needed later, (at the moment at least)
- * obviously it shouldn't have bugs though */
-
-static int project_bucket_face_isect(ProjPaintState *ps, int bucket_x, int bucket_y, const MFace *mf)
-{
- /* TODO - replace this with a tricker method that uses sideofline for all screenCoords's edges against the closest bucket corner */
- rctf bucket_bounds;
- float p1[2], p2[2], p3[2], p4[2];
- float *v, *v1, *v2, *v3, *v4 = NULL;
- 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;
- do {
- v = ps->screenCoords[(*(&mf->v1 + 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];
- }
-
- 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;
- }
- }
-
- return 0;
-}
-
-/* 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)
-{
- float min[2], max[2], *vCoSS;
- int bucketMin[2], bucketMax[2]; /* for ps->bucketRect indexing */
- int fidx, bucket_x, bucket_y;
- int has_x_isect = -1, has_isect = 0; /* for early loop exit */
- MemArena *arena = ps->arena_mt[0]; /* just use the first thread arena since threading has not started yet */
-
- INIT_MINMAX2(min, max);
-
- fidx = mf->v4 ? 3 : 2;
- do {
- vCoSS = ps->screenCoords[*(&mf->v1 + fidx)];
- minmax_v2v2_v2(min, max, vCoSS);
- } while (fidx--);
-
- project_paint_bucket_bounds(ps, min, max, bucketMin, bucketMax);
-
- 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)) {
- 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 */
- arena
- );
-
- has_x_isect = has_isect = 1;
- }
- else if (has_x_isect) {
- /* assuming the face is not a bow-tie - we know we cant intersect again on the X */
- break;
- }
- }
-
- /* no intersection for this entire row, after some intersection above means we can quit now */
- if (has_x_isect == 0 && has_isect) {
- break;
- }
- }
-
-#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 */
- }
-#endif
-}
-
-static int project_paint_view_clip(View3D *v3d, RegionView3D *rv3d, float *clipsta, float *clipend)
-{
- int orth = ED_view3d_clip_range_get(v3d, rv3d, clipsta, clipend);
-
- if (orth) { /* only needed for ortho */
- float fac = 2.0f / ((*clipend) - (*clipsta));
- *clipsta *= fac;
- *clipend *= fac;
- }
-
- return orth;
-}
-
-/* run once per stroke before projection painting */
-static void project_paint_begin(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;
-
- /* Face vars */
- MFace *mf;
- MTFace *tf;
-
- int a, i; /* generic looping vars */
- int image_index = -1, face_index;
- 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);
-
- /* ---- end defines ---- */
-
- if (ps->source == PROJ_SRC_VIEW)
- ED_view3d_clipping_local(ps->rv3d, ps->ob->obmat); /* faster clipping lookups */
-
- /* 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->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->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;
- }
-
- ps->dm_mvert = ps->dm->getVertArray(ps->dm);
- ps->dm_mface = ps->dm->getTessFaceArray(ps->dm);
- ps->dm_mtface = ps->dm->getTessFaceDataArray(ps->dm, CD_MTFACE);
-
- ps->dm_totvert = ps->dm->getNumVerts(ps->dm);
- ps->dm_totface = ps->dm->getNumTessFaces(ps->dm);
-
- /* use clone mtface? */
-
-
- /* Note, use the original mesh for getting the clone and mask layer index
- * this avoids re-generating the derived mesh just to get the new index */
- if (ps->do_layer_clone) {
- //int layer_num = CustomData_get_clone_layer(&ps->dm->faceData, CD_MTFACE);
- int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->fdata, CD_MTFACE);
- if (layer_num != -1)
- ps->dm_mtface_clone = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
-
- if (ps->dm_mtface_clone == NULL || ps->dm_mtface_clone == ps->dm_mtface) {
- ps->do_layer_clone = FALSE;
- ps->dm_mtface_clone = NULL;
- printf("ACK!\n");
- }
- }
-
- if (ps->do_layer_stencil) {
- //int layer_num = CustomData_get_stencil_layer(&ps->dm->faceData, CD_MTFACE);
- int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->fdata, CD_MTFACE);
- if (layer_num != -1)
- ps->dm_mtface_stencil = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
-
- if (ps->dm_mtface_stencil == NULL || ps->dm_mtface_stencil == ps->dm_mtface) {
- ps->do_layer_stencil = FALSE;
- ps->dm_mtface_stencil = NULL;
- }
- }
-
- /* 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);
- /* 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);
-#endif
- }
-
- ps->viewDir[0] = 0.0f;
- ps->viewDir[1] = 0.0f;
- ps->viewDir[2] = 1.0f;
-
- {
- float viewmat[4][4];
- float viewinv[4][4];
-
- invert_m4_m4(ps->ob->imat, ps->ob->obmat);
-
- if (ps->source == PROJ_SRC_VIEW) {
- /* normal drawing */
- ps->winx = ps->ar->winx;
- ps->winy = ps->ar->winy;
-
- copy_m4_m4(viewmat, ps->rv3d->viewmat);
- copy_m4_m4(viewinv, ps->rv3d->viewinv);
-
- ED_view3d_ob_project_mat_get(ps->rv3d, ps->ob, ps->projectMat);
-
- ps->is_ortho = project_paint_view_clip(ps->v3d, ps->rv3d, &ps->clipsta, &ps->clipend);
- }
- else {
- /* re-projection */
- float winmat[4][4];
- float vmat[4][4];
-
- ps->winx = ps->reproject_ibuf->x;
- ps->winy = ps->reproject_ibuf->y;
-
- 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);
-
- float *array = (float *)IDP_Array(view_data);
-
- /* 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;
-
- 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;
- }
-
- /* same as #ED_view3d_ob_project_mat_get */
- mult_m4_m4m4(vmat, viewmat, ps->ob->obmat);
- mult_m4_m4m4(ps->projectMat, winmat, vmat);
- }
-
-
- /* 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);
-
- /* 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]);
- }
-
- /* calculate vert screen coords
- * run this early so we can calculate the x/y resolution of our bucket rect */
- INIT_MINMAX2(ps->screenMin, ps->screenMax);
-
- ps->screenCoords = MEM_mallocN(sizeof(float) * ps->dm_totvert * 4, "ProjectPaint ScreenVerts");
- projScreenCo = *ps->screenCoords;
-
- if (ps->is_ortho) {
- for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++, projScreenCo += 4) {
- mul_v3_m4v3(projScreenCo, ps->projectMat, mv->co);
-
- /* screen space, not clamped */
- projScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projScreenCo[0];
- projScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projScreenCo[1];
- minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo);
- }
- }
- else {
- for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++, projScreenCo += 4) {
- copy_v3_v3(projScreenCo, mv->co);
- projScreenCo[3] = 1.0f;
-
- mul_m4_v4(ps->projectMat, projScreenCo);
-
- if (projScreenCo[3] > ps->clipsta) {
- /* screen space, not clamped */
- projScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projScreenCo[0] / projScreenCo[3];
- projScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projScreenCo[1] / projScreenCo[3];
- projScreenCo[2] = projScreenCo[2] / projScreenCo[3]; /* Use the depth for bucket point occlusion */
- minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo);
- }
- else {
- /* TODO - deal with cases where 1 side of a face goes behind the view ?
- *
- * After some research this is actually very tricky, only option is to
- * clip the derived mesh before painting, which is a Pain */
- projScreenCo[0] = FLT_MAX;
- }
- }
- }
-
- /* 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
- * - a single screen aligned quad */
- projMargin = (ps->screenMax[0] - ps->screenMin[0]) * 0.000001f;
- ps->screenMax[0] += projMargin;
- ps->screenMin[0] -= projMargin;
- projMargin = (ps->screenMax[1] - ps->screenMin[1]) * 0.000001f;
- ps->screenMax[1] += projMargin;
- ps->screenMin[1] -= projMargin;
-
- if (ps->source == PROJ_SRC_VIEW) {
-#ifdef PROJ_DEBUG_WINCLIP
- CLAMP(ps->screenMin[0], (float)(-diameter), (float)(ps->winx + diameter));
- CLAMP(ps->screenMax[0], (float)(-diameter), (float)(ps->winx + diameter));
-
- CLAMP(ps->screenMin[1], (float)(-diameter), (float)(ps->winy + diameter));
- CLAMP(ps->screenMax[1], (float)(-diameter), (float)(ps->winy + diameter));
-#endif
- }
- else { /* 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));
-
- /* printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y); */
-
- /* 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
- 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->faceSeamUVs = MEM_mallocN(sizeof(float) * ps->dm_totface * 8, "paint-faceSeamUVs");
- }
-#endif
-
- /* Thread stuff
- *
- * very small brushes run a lot slower multithreaded since the advantage with
- * threads is being able to fill in multiple buckets at once.
- * Only use threads for bigger brushes. */
-
- if (ps->scene->r.mode & R_FIXED_THREADS) {
- ps->thread_tot = ps->scene->r.threads;
- }
- else {
- ps->thread_tot = BLI_system_thread_count();
- }
- for (a = 0; a < ps->thread_tot; a++) {
- ps->arena_mt[a] = BLI_memarena_new(1 << 16, "project paint arena");
- }
-
- arena = ps->arena_mt[0];
-
- if (ps->do_backfacecull && ps->do_mask_normal) {
- float viewDirPersp[3];
-
- 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 (ps->is_ortho) {
- if (angle_normalized_v3v3(ps->viewDir, no) >= ps->normal_angle) { /* 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 */
- 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++) {
-
-#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);
- }
- }
-#endif
-
- tpage = project_paint_face_image(ps, ps->dm_mtface, face_index);
-
- if (tpage && ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_MASK) == 0 || mf->flag & ME_FACE_SEL)) {
-
- float *v1coSS, *v2coSS, *v3coSS, *v4coSS = NULL;
-
- 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))
- {
- 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;
- }
-
-#endif //PROJ_DEBUG_WINCLIP
-
-
- 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;
- }
- }
- else {
- if (line_point_side_v2(v1coSS, v2coSS, v3coSS) < 0.0f) {
- continue;
- }
-
- }
- }
-
- if (tpage_last != tpage) {
-
- image_index = BLI_linklist_index(image_LinkList, tpage);
-
- if (image_index == -1 && BKE_image_has_ibuf(tpage, NULL)) { /* MemArena dosnt have an append func */
- BLI_linklist_append(&image_LinkList, tpage);
- image_index = ps->image_tot;
- ps->image_tot++;
- }
-
- tpage_last = tpage;
- }
-
- 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);
- }
- }
- }
-
- /* 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++) {
- projIma->ima = node->link;
- projIma->touch = 0;
- projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL);
- projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
- memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
- }
-
- /* we have built the array, discard the linked list */
- BLI_linklist_free(image_LinkList, NULL);
-}
-
-static void project_paint_begin_clone(ProjPaintState *ps, int mouse[2])
-{
- /* setup clone offset */
- if (ps->tool == PAINT_TOOL_CLONE) {
- float projCo[4];
- copy_v3_v3(projCo, give_cursor(ps->scene, ps->v3d));
- mul_m4_v3(ps->ob->imat, projCo);
-
- projCo[3] = 1.0f;
- mul_m4_v4(ps->projectMat, projCo);
- ps->cloneOffset[0] = mouse[0] - ((float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projCo[0] / projCo[3]);
- ps->cloneOffset[1] = mouse[1] - ((float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projCo[1] / projCo[3]);
- }
-}
-
-static void project_paint_end(ProjPaintState *ps)
-{
- int a;
- ProjPaintImage *projIma;
-
- /* build undo data from original pixel colors */
- if (U.uiflag & USER_GLOBALUNDO) {
- ProjPixel *projPixel;
- ImBuf *tmpibuf = NULL, *tmpibuf_float = NULL;
- LinkNode *pixel_node;
- void *tilerect;
- MemArena *arena = ps->arena_mt[0]; /* threaded arena re-used for non threaded case */
-
- int bucket_tot = (ps->buckets_x * ps->buckets_y); /* we could get an X/Y but easier to loop through all possible buckets */
- int bucket_index;
- int tile_index;
- int x_round, y_round;
- int x_tile, y_tile;
- int is_float = -1;
-
- /* context */
- ProjPaintImage *last_projIma;
- int last_image_index = -1;
- int last_tile_width = 0;
-
- for (a = 0, last_projIma = ps->projImages; a < ps->image_tot; a++, last_projIma++) {
- int size = sizeof(void **) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->y);
- last_projIma->undoRect = (void **) BLI_memarena_alloc(arena, size);
- memset(last_projIma->undoRect, 0, size);
- last_projIma->ibuf->userflags |= IB_BITMAPDIRTY;
- }
-
- for (bucket_index = 0; bucket_index < bucket_tot; bucket_index++) {
- /* loop through all pixels */
- for (pixel_node = ps->bucketRect[bucket_index]; pixel_node; pixel_node = pixel_node->next) {
-
- /* ok we have a pixel, was it modified? */
- projPixel = (ProjPixel *)pixel_node->link;
-
- if (last_image_index != projPixel->image_index) {
- /* set the context */
- last_image_index = projPixel->image_index;
- last_projIma = ps->projImages + last_image_index;
- last_tile_width = IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x);
- is_float = last_projIma->ibuf->rect_float ? 1 : 0;
- }
-
-
- if ((is_float == 0 && projPixel->origColor.uint != *projPixel->pixel.uint_pt) ||
- (is_float == 1 &&
- (projPixel->origColor.f[0] != projPixel->pixel.f_pt[0] ||
- projPixel->origColor.f[1] != projPixel->pixel.f_pt[1] ||
- projPixel->origColor.f[2] != projPixel->pixel.f_pt[2] ||
- projPixel->origColor.f[3] != projPixel->pixel.f_pt[3]))
- )
- {
-
- x_tile = projPixel->x_px >> IMAPAINT_TILE_BITS;
- y_tile = projPixel->y_px >> IMAPAINT_TILE_BITS;
-
- x_round = x_tile * IMAPAINT_TILE_SIZE;
- y_round = y_tile * IMAPAINT_TILE_SIZE;
-
- tile_index = x_tile + y_tile * last_tile_width;
-
- if (last_projIma->undoRect[tile_index] == NULL) {
- /* add the undo tile from the modified image, then write the original colors back into it */
- tilerect = last_projIma->undoRect[tile_index] = image_undo_push_tile(last_projIma->ima, last_projIma->ibuf, is_float ? (&tmpibuf_float) : (&tmpibuf), x_tile, y_tile);
- }
- else {
- tilerect = last_projIma->undoRect[tile_index];
- }
-
- /* This is a BIT ODD, but overwrite the undo tiles image info with this pixels original color
- * because allocating the tiles along the way slows down painting */
-
- if (is_float) {
- float *rgba_fp = (float *)tilerect + (((projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE)) * 4;
- copy_v4_v4(rgba_fp, projPixel->origColor.f);
- }
- else {
- ((unsigned int *)tilerect)[(projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE] = projPixel->origColor.uint;
- }
- }
- }
- }
-
- if (tmpibuf) IMB_freeImBuf(tmpibuf);
- if (tmpibuf_float) IMB_freeImBuf(tmpibuf_float);
- }
- /* done calculating undo data */
-
- /* 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);
- }
-
- BKE_image_release_ibuf(ps->reproject_image, ps->reproject_ibuf, NULL);
-
- MEM_freeN(ps->screenCoords);
- MEM_freeN(ps->bucketRect);
- MEM_freeN(ps->bucketFaces);
- MEM_freeN(ps->bucketFlags);
-
-#ifndef PROJ_DEBUG_NOSEAMBLEED
- if (ps->seam_bleed_px > 0.0f) {
- MEM_freeN(ps->vertFaces);
- MEM_freeN(ps->faceSeamFlags);
- MEM_freeN(ps->faceSeamUVs);
- }
-#endif
-
- if (ps->vertFlags) MEM_freeN(ps->vertFlags);
-
- 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
- }
-
- if (ps->dm_release)
- ps->dm->release(ps->dm);
-}
-
-/* 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;
-
- pr++;
- }
-}
-
-
-static int partial_redraw_array_merge(ImagePaintPartialRedraw *pr, ImagePaintPartialRedraw *pr_other, int tot)
-{
- int touch = 0;
- while (tot--) {
- pr->x1 = min_ii(pr->x1, pr_other->x1);
- pr->y1 = min_ii(pr->y1, pr_other->y1);
-
- pr->x2 = max_ii(pr->x2, pr_other->x2);
- pr->y2 = max_ii(pr->y2, pr_other->y2);
-
- if (pr->x2 != -1)
- touch = 1;
-
- pr++; pr_other++;
- }
-
- return touch;
-}
-
-/* Loop over all images on this mesh and update any we have touched */
-static int project_image_refresh_tagged(ProjPaintState *ps)
-{
- ImagePaintPartialRedraw *pr;
- ProjPaintImage *projIma;
- int a, i;
- int redraw = 0;
-
-
- for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) {
- if (projIma->touch) {
- /* look over each bound cell */
- for (i = 0; i < PROJ_BOUNDBOX_SQUARED; i++) {
- pr = &(projIma->partRedrawRect[i]);
- if (pr->x2 != -1) { /* TODO - use 'enabled' ? */
- imapaintpartial = *pr;
- imapaint_image_update(NULL, NULL, projIma->ima, projIma->ibuf, 1); /*last 1 is for texpaint*/
- redraw = 1;
- }
- }
-
- projIma->touch = 0; /* clear for reuse */
- }
- }
-
- return redraw;
-}
-
-/* run this per painting onto each mouse location */
-static int project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2])
-{
- if (ps->source == PROJ_SRC_VIEW) {
- float min_brush[2], max_brush[2];
- const float radius = (float)BKE_brush_size_get(ps->scene, ps->brush);
-
- /* so we don't have a bucket bounds that is way too small to paint into */
- // if (radius < 1.0f) radius = 1.0f; // this doesn't work yet :/
-
- min_brush[0] = mval_f[0] - radius;
- min_brush[1] = mval_f[1] - radius;
-
- max_brush[0] = mval_f[0] + radius;
- max_brush[1] = mval_f[1] + radius;
-
- /* offset to make this a valid bucket index */
- project_paint_bucket_bounds(ps, min_brush, max_brush, ps->bucketMin, ps->bucketMax);
-
- /* mouse outside the model areas? */
- if (ps->bucketMin[0] == ps->bucketMax[0] || ps->bucketMin[1] == ps->bucketMax[1]) {
- return 0;
- }
-
- ps->context_bucket_x = ps->bucketMin[0];
- ps->context_bucket_y = ps->bucketMin[1];
- }
- else { /* reproject: PROJ_SRC_* */
- ps->bucketMin[0] = 0;
- ps->bucketMin[1] = 0;
-
- ps->bucketMax[0] = ps->buckets_x;
- ps->bucketMax[1] = ps->buckets_y;
-
- ps->context_bucket_x = 0;
- ps->context_bucket_y = 0;
- }
- return 1;
-}
-
-
-static int project_bucket_iter_next(ProjPaintState *ps, int *bucket_index, rctf *bucket_bounds, const float mval[2])
-{
- const int diameter = 2 * BKE_brush_size_get(ps->scene, ps->brush);
-
- if (ps->thread_tot > 1)
- BLI_lock_thread(LOCK_CUSTOM1);
-
- //printf("%d %d\n", ps->context_bucket_x, ps->context_bucket_y);
-
- for (; ps->context_bucket_y < ps->bucketMax[1]; ps->context_bucket_y++) {
- for (; ps->context_bucket_x < ps->bucketMax[0]; ps->context_bucket_x++) {
-
- /* use bucket_bounds for project_bucket_isect_circle and project_bucket_init*/
- project_bucket_bounds(ps, ps->context_bucket_x, ps->context_bucket_y, bucket_bounds);
-
- if ((ps->source != PROJ_SRC_VIEW) ||
- project_bucket_isect_circle(mval, (float)(diameter * diameter), bucket_bounds))
- {
- *bucket_index = ps->context_bucket_x + (ps->context_bucket_y * ps->buckets_x);
- ps->context_bucket_x++;
-
- if (ps->thread_tot > 1)
- BLI_unlock_thread(LOCK_CUSTOM1);
-
- return 1;
- }
- }
- ps->context_bucket_x = ps->bucketMin[0];
- }
-
- if (ps->thread_tot > 1)
- BLI_unlock_thread(LOCK_CUSTOM1);
- return 0;
-}
-
-/* Each thread gets one of these, also used as an argument to pass to project_paint_op */
-typedef struct ProjectHandle {
- /* args */
- ProjPaintState *ps;
- float prevmval[2];
- float mval[2];
-
- /* annoying but we need to have image bounds per thread, then merge into ps->projectPartialRedraws */
- ProjPaintImage *projImages; /* array of partial redraws */
-
- /* thread settings */
- int thread_index;
-} ProjectHandle;
-
-static void blend_color_mix(unsigned char cp[4], const unsigned char cp1[4], const unsigned char cp2[4], const int fac)
-{
- /* this and other blending modes previously used >>8 instead of /255. both
- * are not equivalent (>>8 is /256), and the former results in rounding
- * errors that can turn colors black fast after repeated blending */
- const int mfac = 255 - fac;
-
- cp[0] = (mfac * cp1[0] + fac * cp2[0]) / 255;
- cp[1] = (mfac * cp1[1] + fac * cp2[1]) / 255;
- cp[2] = (mfac * cp1[2] + fac * cp2[2]) / 255;
- cp[3] = (mfac * cp1[3] + fac * cp2[3]) / 255;
-}
-
-static void blend_color_mix_float(float cp[4], const float cp1[4], const float cp2[4], const float fac)
-{
- const float mfac = 1.0f - fac;
- cp[0] = mfac * cp1[0] + fac * cp2[0];
- cp[1] = mfac * cp1[1] + fac * cp2[1];
- cp[2] = mfac * cp1[2] + fac * cp2[2];
- cp[3] = mfac * cp1[3] + fac * cp2[3];
-}
-
-static void blend_color_mix_accum(unsigned char cp[4], const unsigned char cp1[4], const unsigned char cp2[4], const int fac)
-{
- /* this and other blending modes previously used >>8 instead of /255. both
- * are not equivalent (>>8 is /256), and the former results in rounding
- * errors that can turn colors black fast after repeated blending */
- const int mfac = 255 - fac;
- const int alpha = cp1[3] + ((fac * cp2[3]) / 255);
-
- cp[0] = (mfac * cp1[0] + fac * cp2[0]) / 255;
- cp[1] = (mfac * cp1[1] + fac * cp2[1]) / 255;
- cp[2] = (mfac * cp1[2] + fac * cp2[2]) / 255;
- cp[3] = alpha > 255 ? 255 : alpha;
-}
-static void blend_color_mix_accum_float(float cp[4], const float cp1[4], const unsigned char cp2[4], const float fac)
-{
- const float mfac = 1.0f - fac;
- const float alpha = cp1[3] + (fac * (cp2[3] / 255.0f));
-
- cp[0] = (mfac * cp1[0] + (fac * (cp2[0] / 255.0f)));
- cp[1] = (mfac * cp1[1] + (fac * (cp2[1] / 255.0f)));
- cp[2] = (mfac * cp1[2] + (fac * (cp2[2] / 255.0f)));
- cp[3] = alpha > 1.0f ? 1.0f : alpha;
-}
-
-
-static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask)
-{
- if (ps->is_airbrush == 0 && mask < 1.0f) {
- projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, ((ProjPixelClone *)projPixel)->clonepx.uint, (int)(alpha * 255), ps->blend);
- blend_color_mix(projPixel->pixel.ch_pt, projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask * 255));
- }
- else {
- *projPixel->pixel.uint_pt = IMB_blend_color(*projPixel->pixel.uint_pt, ((ProjPixelClone *)projPixel)->clonepx.uint, (int)(alpha * mask * 255), ps->blend);
- }
-}
-
-static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask)
-{
- if (ps->is_airbrush == 0 && mask < 1.0f) {
- IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, ((ProjPixelClone *)projPixel)->clonepx.f, alpha, ps->blend);
- blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f, projPixel->newColor.f, mask);
- }
- else {
- IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.f, alpha * mask, ps->blend);
- }
-}
-
-/* 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
- * really that important to be correct as it is with clone and painting
- */
-static void do_projectpaint_smear(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, MemArena *smearArena, LinkNode **smearPixels, float co[2])
-{
- unsigned char rgba_ub[4];
-
- if (project_paint_PickColor(ps, co, NULL, rgba_ub, 1) == 0)
- return;
- /* ((ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*projPixel->pixel.uint_pt, *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend); */
- blend_color_mix(((ProjPixelClone *)projPixel)->clonepx.ch, projPixel->pixel.ch_pt, rgba_ub, (int)(alpha * mask * 255));
- BLI_linklist_prepend_arena(smearPixels, (void *)projPixel, smearArena);
-}
-
-static void do_projectpaint_smear_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, MemArena *smearArena, LinkNode **smearPixels_f, float co[2])
-{
- float rgba[4];
-
- if (project_paint_PickColor(ps, co, rgba, NULL, 1) == 0)
- return;
-
- /* (ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*((unsigned int *)rgba_smear), *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend); */
- blend_color_mix_float(((ProjPixelClone *)projPixel)->clonepx.f, projPixel->pixel.f_pt, rgba, alpha * mask);
- BLI_linklist_prepend_arena(smearPixels_f, (void *)projPixel, smearArena);
-}
-
-/* do_projectpaint_soften for float & byte
- */
-static float inv_pow2(float f)
-{
- f = 1.0f - f;
- f = f * f;
- return 1.0f - f;
-}
-
-static void do_projectpaint_soften_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, MemArena *softenArena, LinkNode **softenPixels)
-{
- unsigned int accum_tot = 0;
- unsigned int i;
-
- float *rgba = projPixel->newColor.f;
-
- /* sigh, alpha values tend to need to be a _lot_ stronger with blur */
- mask = inv_pow2(mask);
- alpha = inv_pow2(alpha);
-
- /* rather then painting, accumulate surrounding colors */
- zero_v4(rgba);
-
- for (i = 0; i < PROJ_PIXEL_SOFTEN_TOT; i++) {
- float co_ofs[2];
- float rgba_tmp[4];
- sub_v2_v2v2(co_ofs, projPixel->projCoSS, proj_pixel_soften_v2[i]);
- if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, TRUE)) {
- add_v4_v4(rgba, rgba_tmp);
- accum_tot++;
- }
- }
-
- if (LIKELY(accum_tot != 0)) {
- mul_v4_fl(rgba, 1.0f / (float)accum_tot);
- blend_color_mix_float(rgba, projPixel->pixel.f_pt, rgba, alpha);
- if (mask < 1.0f) blend_color_mix_float(rgba, projPixel->origColor.f, rgba, mask);
- BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena);
- }
-}
-
-static void do_projectpaint_soften(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, MemArena *softenArena, LinkNode **softenPixels)
-{
- unsigned int accum_tot = 0;
- unsigned int i;
-
- float rgba[4]; /* convert to byte after */
-
- /* sigh, alpha values tend to need to be a _lot_ stronger with blur */
- mask = inv_pow2(mask);
- alpha = inv_pow2(alpha);
-
- /* rather then painting, accumulate surrounding colors */
- zero_v4(rgba);
-
- for (i = 0; i < PROJ_PIXEL_SOFTEN_TOT; i++) {
- float co_ofs[2];
- float rgba_tmp[4];
- sub_v2_v2v2(co_ofs, projPixel->projCoSS, proj_pixel_soften_v2[i]);
- if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, TRUE)) {
- add_v4_v4(rgba, rgba_tmp);
- accum_tot++;
- }
- }
-
- if (LIKELY(accum_tot != 0)) {
- unsigned char *rgba_ub = projPixel->newColor.ch;
-
- mul_v4_fl(rgba, 1.0f / (float)accum_tot);
- IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba_ub, rgba);
-
- blend_color_mix(rgba_ub, projPixel->pixel.ch_pt, rgba_ub, (int)(alpha * 255));
- if (mask != 1.0f) blend_color_mix(rgba_ub, projPixel->origColor.ch, rgba_ub, (int)(mask * 255));
- BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena);
- }
-}
-
-BLI_INLINE void rgba_float_to_uchar__mul_v3(unsigned char rgba_ub[4], const float rgba[4], const float rgb[3])
-{
- rgba_ub[0] = f_to_char(rgba[0] * rgb[0]);
- rgba_ub[1] = f_to_char(rgba[1] * rgb[1]);
- rgba_ub[2] = f_to_char(rgba[2] * rgb[2]);
- rgba_ub[3] = f_to_char(rgba[3]);
-}
-
-static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, const float rgba[4], float alpha, float mask)
-{
- unsigned char rgba_ub[4];
-
- if (ps->is_texbrush) {
- rgba_float_to_uchar__mul_v3(rgba_ub, rgba, ps->brush->rgb);
- }
- else {
- IMAPAINT_FLOAT_RGB_TO_CHAR(rgba_ub, ps->brush->rgb);
- rgba_ub[3] = 255;
- }
-
- if (ps->is_airbrush == 0 && mask < 1.0f) {
- projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, *((unsigned int *)rgba_ub), (int)(alpha * 255), ps->blend);
- blend_color_mix(projPixel->pixel.ch_pt, projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask * 255));
- }
- else {
- *projPixel->pixel.uint_pt = IMB_blend_color(*projPixel->pixel.uint_pt, *((unsigned int *)rgba_ub), (int)(alpha * mask * 255), ps->blend);
- }
-}
-
-static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, float rgba[4], float alpha, float mask, int use_color_correction)
-{
- if (ps->is_texbrush) {
- /* rgba already holds a texture result here from higher level function */
- if (use_color_correction) {
- float rgba_br[3];
- srgb_to_linearrgb_v3_v3(rgba_br, ps->brush->rgb);
- mul_v3_v3(rgba, rgba_br);
- }
- else {
- mul_v3_v3(rgba, ps->brush->rgb);
- }
- }
- else {
- if (use_color_correction) {
- srgb_to_linearrgb_v3_v3(rgba, ps->brush->rgb);
- }
- else {
- copy_v3_v3(rgba, ps->brush->rgb);
- }
- rgba[3] = 1.0;
- }
-
- if (ps->is_airbrush == 0 && mask < 1.0f) {
- IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, rgba, alpha, ps->blend);
- blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f, projPixel->newColor.f, mask);
- }
- else {
- IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, rgba, alpha * mask, ps->blend);
- }
-}
-
-
-
-/* run this for single and multithreaded painting */
-static void *do_projectpaint_thread(void *ph_v)
-{
- /* First unpack args from the struct */
- ProjPaintState *ps = ((ProjectHandle *)ph_v)->ps;
- ProjPaintImage *projImages = ((ProjectHandle *)ph_v)->projImages;
- const float *lastpos = ((ProjectHandle *)ph_v)->prevmval;
- const float *pos = ((ProjectHandle *)ph_v)->mval;
- const int thread_index = ((ProjectHandle *)ph_v)->thread_index;
- /* Done with args from ProjectHandle */
-
- LinkNode *node;
- ProjPixel *projPixel;
-
- int last_index = -1;
- ProjPaintImage *last_projIma = NULL;
- ImagePaintPartialRedraw *last_partial_redraw_cell;
-
- float rgba[4], alpha, dist_nosqrt, dist;
-
- float falloff;
- int bucket_index;
- int is_floatbuf = 0;
- int use_color_correction = FALSE;
- const short tool = ps->tool;
- rctf bucket_bounds;
-
- /* for smear only */
- float pos_ofs[2] = {0};
- float co[2];
- float mask = 1.0f; /* airbrush wont use mask */
- unsigned short mask_short;
- const float radius = (float)BKE_brush_size_get(ps->scene, ps->brush);
- const float radius_squared = radius * radius; /* avoid a square root with every dist comparison */
-
- short lock_alpha = ELEM(ps->brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ? 0 : ps->brush->flag & BRUSH_LOCK_ALPHA;
-
- LinkNode *smearPixels = NULL;
- LinkNode *smearPixels_f = NULL;
- MemArena *smearArena = NULL; /* mem arena for this brush projection only */
-
- LinkNode *softenPixels = NULL;
- LinkNode *softenPixels_f = NULL;
- MemArena *softenArena = NULL; /* mem arena for this brush projection only */
-
- if (tool == PAINT_TOOL_SMEAR) {
- pos_ofs[0] = pos[0] - lastpos[0];
- pos_ofs[1] = pos[1] - lastpos[1];
-
- smearArena = BLI_memarena_new(1 << 16, "paint smear arena");
- }
- else if (tool == PAINT_TOOL_SOFTEN) {
- softenArena = BLI_memarena_new(1 << 16, "paint soften arena");
- }
-
- /* printf("brush bounds %d %d %d %d\n", bucketMin[0], bucketMin[1], bucketMax[0], bucketMax[1]); */
-
- while (project_bucket_iter_next(ps, &bucket_index, &bucket_bounds, pos)) {
-
- /* Check this bucket and its faces are initialized */
- if (ps->bucketFlags[bucket_index] == PROJ_BUCKET_NULL) {
- /* No pixels initialized */
- project_bucket_init(ps, thread_index, bucket_index, &bucket_bounds);
- }
-
- if (ps->source != PROJ_SRC_VIEW) {
-
- /* Re-Projection, simple, no brushes! */
-
- for (node = ps->bucketRect[bucket_index]; node; node = node->next) {
- projPixel = (ProjPixel *)node->link;
-
- /* copy of code below */
- if (last_index != projPixel->image_index) {
- last_index = projPixel->image_index;
- last_projIma = projImages + last_index;
-
- last_projIma->touch = 1;
- is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0;
- use_color_correction = TRUE;
- }
- /* end copy */
-
- if (is_floatbuf) {
- /* re-project buffer is assumed byte - TODO, allow float */
- bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL,
- projPixel->projCoSS[0], projPixel->projCoSS[1]);
- if (projPixel->newColor.ch[3]) {
- mask = ((float)projPixel->mask) / 65535.0f;
- blend_color_mix_accum_float(projPixel->pixel.f_pt, projPixel->origColor.f,
- projPixel->newColor.ch, (mask * (projPixel->newColor.ch[3] / 255.0f)));
- }
- }
- else {
- /* re-project buffer is assumed byte - TODO, allow float */
- bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL,
- projPixel->projCoSS[0], projPixel->projCoSS[1]);
- if (projPixel->newColor.ch[3]) {
- mask = ((float)projPixel->mask) / 65535.0f;
- blend_color_mix_accum(projPixel->pixel.ch_pt, projPixel->origColor.ch,
- projPixel->newColor.ch, (int)(mask * projPixel->newColor.ch[3]));
- }
- }
- }
- }
- else {
- /* Normal brush painting */
-
- for (node = ps->bucketRect[bucket_index]; node; node = node->next) {
-
- projPixel = (ProjPixel *)node->link;
-
- dist_nosqrt = len_squared_v2v2(projPixel->projCoSS, pos);
-
- /*if (dist < radius) {*/ /* correct but uses a sqrtf */
- if (dist_nosqrt <= radius_squared) {
- dist = sqrtf(dist_nosqrt);
-
- falloff = BKE_brush_curve_strength_clamp(ps->brush, dist, radius);
-
- if (falloff > 0.0f) {
- if (ps->is_texbrush) {
- /* note, for clone and smear, we only use the alpha, could be a special function */
- BKE_brush_sample_tex(ps->scene, ps->brush, projPixel->projCoSS, rgba, thread_index);
- alpha = rgba[3];
- }
- else {
- alpha = 1.0f;
- }
-
- if (ps->is_airbrush) {
- /* for an aurbrush there is no real mask, so just multiply the alpha by it */
- alpha *= falloff * BKE_brush_alpha_get(ps->scene, ps->brush);
- mask = ((float)projPixel->mask) / 65535.0f;
- }
- else {
- /* This brush dosnt accumulate so add some curve to the brushes falloff */
- falloff = 1.0f - falloff;
- falloff = 1.0f - (falloff * falloff);
-
- mask_short = (unsigned short)(projPixel->mask * (BKE_brush_alpha_get(ps->scene, ps->brush) * falloff));
- if (mask_short > projPixel->mask_max) {
- mask = ((float)mask_short) / 65535.0f;
- projPixel->mask_max = mask_short;
- }
- else {
- /*mask = ((float)projPixel->mask_max)/65535.0f;*/
-
- /* Go onto the next pixel */
- continue;
- }
- }
-
- if (alpha > 0.0f) {
-
- /* copy of code above */
- if (last_index != projPixel->image_index) {
- last_index = projPixel->image_index;
- last_projIma = projImages + last_index;
-
- last_projIma->touch = 1;
- is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0;
- use_color_correction = TRUE;
- }
- /* end copy */
-
- 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);
-
-
- switch (tool) {
- case PAINT_TOOL_CLONE:
- if (is_floatbuf) {
- if (((ProjPixelClone *)projPixel)->clonepx.f[3]) {
- do_projectpaint_clone_f(ps, projPixel, alpha, mask); /* rgba isn't used for cloning, only alpha */
- }
- }
- else {
- if (((ProjPixelClone *)projPixel)->clonepx.ch[3]) {
- do_projectpaint_clone(ps, projPixel, alpha, mask); /* rgba isn't used for cloning, only alpha */
- }
- }
- break;
- case PAINT_TOOL_SMEAR:
- sub_v2_v2v2(co, projPixel->projCoSS, pos_ofs);
-
- if (is_floatbuf) do_projectpaint_smear_f(ps, projPixel, alpha, mask, smearArena, &smearPixels_f, co);
- else do_projectpaint_smear(ps, projPixel, alpha, mask, smearArena, &smearPixels, co);
- break;
- case PAINT_TOOL_SOFTEN:
- if (is_floatbuf) do_projectpaint_soften_f(ps, projPixel, alpha, mask, softenArena, &softenPixels_f);
- else do_projectpaint_soften(ps, projPixel, alpha, mask, softenArena, &softenPixels);
- break;
- default:
- if (is_floatbuf) do_projectpaint_draw_f(ps, projPixel, rgba, alpha, mask, use_color_correction);
- else do_projectpaint_draw(ps, projPixel, rgba, alpha, mask);
- break;
- }
- }
-
- if (lock_alpha) {
- if (is_floatbuf) projPixel->pixel.f_pt[3] = projPixel->origColor.f[3];
- else projPixel->pixel.ch_pt[3] = projPixel->origColor.ch[3];
- }
-
- /* done painting */
- }
- }
- }
- }
- }
-
-
- if (tool == PAINT_TOOL_SMEAR) {
-
- for (node = smearPixels; node; node = node->next) { /* this wont run for a float image */
- projPixel = node->link;
- *projPixel->pixel.uint_pt = ((ProjPixelClone *)projPixel)->clonepx.uint;
- }
-
- for (node = smearPixels_f; node; node = node->next) {
- projPixel = node->link;
- copy_v4_v4(projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.f);
- }
-
- BLI_memarena_free(smearArena);
- }
- else if (tool == PAINT_TOOL_SOFTEN) {
-
- for (node = softenPixels; node; node = node->next) { /* this wont run for a float image */
- projPixel = node->link;
- *projPixel->pixel.uint_pt = projPixel->newColor.uint;
- }
-
- for (node = softenPixels_f; node; node = node->next) {
- projPixel = node->link;
- copy_v4_v4(projPixel->pixel.f_pt, projPixel->newColor.f);
- }
-
- BLI_memarena_free(softenArena);
- }
-
- return NULL;
-}
-
-static int project_paint_op(void *state, ImBuf *UNUSED(ibufb), const float lastpos[2], const float pos[2])
-{
- /* First unpack args from the struct */
- ProjPaintState *ps = (ProjPaintState *)state;
- int touch_any = 0;
-
- ProjectHandle handles[BLENDER_MAX_THREADS];
- ListBase threads;
- int a, i;
-
- if (!project_bucket_iter_init(ps, pos)) {
- return 0;
- }
-
- if (ps->thread_tot > 1)
- BLI_init_threads(&threads, do_projectpaint_thread, ps->thread_tot);
-
- /* get the threads running */
- for (a = 0; a < ps->thread_tot; a++) {
-
- /* set defaults in handles */
- //memset(&handles[a], 0, sizeof(BakeShade));
-
- handles[a].ps = ps;
- copy_v2_v2(handles[a].mval, pos);
- copy_v2_v2(handles[a].prevmval, lastpos);
-
- /* thread specific */
- handles[a].thread_index = a;
-
- handles[a].projImages = (ProjPaintImage *)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);
- memcpy(handles[a].projImages[i].partRedrawRect, ps->projImages[i].partRedrawRect, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
- }
-
- if (ps->thread_tot > 1)
- BLI_insert_thread(&threads, &handles[a]);
- }
-
- if (ps->thread_tot > 1) /* wait for everything to be done */
- BLI_end_threads(&threads);
- else
- do_projectpaint_thread(&handles[0]);
-
-
- /* move threaded bounds back into ps->projectPartialRedraws */
- for (i = 0; i < ps->image_tot; i++) {
- int touch = 0;
- for (a = 0; a < ps->thread_tot; a++) {
- touch |= partial_redraw_array_merge(ps->projImages[i].partRedrawRect, handles[a].projImages[i].partRedrawRect, PROJ_BOUNDBOX_SQUARED);
- }
-
- if (touch) {
- ps->projImages[i].touch = 1;
- touch_any = 1;
- }
- }
-
- return touch_any;
-}
-
-
-static int project_paint_sub_stroke(ProjPaintState *ps, BrushPainter *painter, const int UNUSED(prevmval_i[2]), const int mval_i[2], double time, float pressure)
-{
-
- /* Use mouse coords as floats for projection painting */
- float pos[2];
-
- pos[0] = (float)(mval_i[0]);
- pos[1] = (float)(mval_i[1]);
-
- // we may want to use this later
- // BKE_brush_painter_require_imbuf(painter, ((ibuf->rect_float)? 1: 0), 0, 0);
-
- if (BKE_brush_painter_paint(painter, project_paint_op, pos, time, pressure, ps, 0)) {
- return 1;
- }
- else return 0;
-}
-
-
-static int project_paint_stroke(ProjPaintState *ps, BrushPainter *painter, const int prevmval_i[2], const int mval_i[2], double time, float pressure)
-{
- int a, redraw;
-
- for (a = 0; a < ps->image_tot; a++)
- partial_redraw_array_init(ps->projImages[a].partRedrawRect);
-
- redraw = project_paint_sub_stroke(ps, painter, prevmval_i, mval_i, time, pressure);
-
- if (project_image_refresh_tagged(ps))
- return redraw;
-
- return 0;
-}
-
/* Imagepaint Partial Redraw & Dirty Region */
-static void imapaint_clear_partial_redraw(void)
+void imapaint_clear_partial_redraw(void)
{
memset(&imapaintpartial, 0, sizeof(imapaintpartial));
}
-static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h)
+void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h)
{
ImBuf *tmpibuf = NULL;
int srcx = 0, srcy = 0, origx;
@@ -4392,16 +315,13 @@ static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w,
IMB_freeImBuf(tmpibuf);
}
-static void imapaint_image_update(Scene *scene, SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint)
+void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint)
{
- if (scene) {
- IMB_partial_display_buffer_update(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect, ibuf->x, 0, 0,
- &scene->view_settings, &scene->display_settings,
- imapaintpartial.x1, imapaintpartial.y1,
- imapaintpartial.x2, imapaintpartial.y2, FALSE);
- }
- else {
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ if (imapaintpartial.x1 != imapaintpartial.x2 &&
+ imapaintpartial.y1 != imapaintpartial.y2)
+ {
+ IMB_partial_display_buffer_update_delayed(ibuf, imapaintpartial.x1, imapaintpartial.y1,
+ imapaintpartial.x2, imapaintpartial.y2);
}
if (ibuf->mipmap[0])
@@ -4416,446 +336,6 @@ static void imapaint_image_update(Scene *scene, SpaceImage *sima, Image *image,
}
}
-/* Image Paint Operations */
-
-/* keep these functions in sync */
-static void imapaint_ibuf_rgb_get(ImBuf *ibuf, int x, int y, const short is_torus, float r_rgb[3])
-{
- 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) {
- float *rrgbf = ibuf->rect_float + (ibuf->x * y + x) * 4;
- IMAPAINT_FLOAT_RGB_COPY(r_rgb, rrgbf);
- }
- else {
- char *rrgb = (char *)ibuf->rect + (ibuf->x * y + x) * 4;
- IMAPAINT_CHAR_RGB_TO_FLOAT(r_rgb, rrgb);
- }
-}
-static void imapaint_ibuf_rgb_set(ImBuf *ibuf, int x, int y, const short is_torus, const float rgb[3])
-{
- 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) {
- float *rrgbf = ibuf->rect_float + (ibuf->x * y + x) * 4;
- IMAPAINT_FLOAT_RGB_COPY(rrgbf, rgb);
- }
- else {
- char *rrgb = (char *)ibuf->rect + (ibuf->x * y + x) * 4;
- IMAPAINT_FLOAT_RGB_TO_CHAR(rrgb, rgb);
- }
-}
-
-static int imapaint_ibuf_add_if(ImBuf *ibuf, unsigned int x, unsigned int y, float *outrgb, short torus)
-{
- float inrgb[3];
-
- // XXX: signed unsigned mismatch
- if ((x >= (unsigned int)(ibuf->x)) || (y >= (unsigned int)(ibuf->y))) {
- if (torus) imapaint_ibuf_rgb_get(ibuf, x, y, 1, inrgb);
- else return 0;
- }
- else {
- imapaint_ibuf_rgb_get(ibuf, x, y, 0, inrgb);
- }
-
- outrgb[0] += inrgb[0];
- outrgb[1] += inrgb[1];
- outrgb[2] += inrgb[2];
-
- return 1;
-}
-
-static void imapaint_lift_soften(ImBuf *ibuf, ImBuf *ibufb, int *pos, const short is_torus)
-{
- int x, y, count, xi, yi, xo, yo;
- int out_off[2], in_off[2], dim[2];
- float outrgb[3];
-
- dim[0] = ibufb->x;
- dim[1] = ibufb->y;
- in_off[0] = pos[0];
- in_off[1] = pos[1];
- out_off[0] = out_off[1] = 0;
-
- if (!is_torus) {
- IMB_rectclip(ibuf, ibufb, &in_off[0], &in_off[1], &out_off[0],
- &out_off[1], &dim[0], &dim[1]);
-
- if ((dim[0] == 0) || (dim[1] == 0))
- return;
- }
-
- for (y = 0; y < dim[1]; y++) {
- for (x = 0; x < dim[0]; x++) {
- /* get input pixel */
- xi = in_off[0] + x;
- yi = in_off[1] + y;
-
- count = 1;
- imapaint_ibuf_rgb_get(ibuf, xi, yi, is_torus, outrgb);
-
- count += imapaint_ibuf_add_if(ibuf, xi - 1, yi - 1, outrgb, is_torus);
- count += imapaint_ibuf_add_if(ibuf, xi - 1, yi, outrgb, is_torus);
- count += imapaint_ibuf_add_if(ibuf, xi - 1, yi + 1, outrgb, is_torus);
-
- count += imapaint_ibuf_add_if(ibuf, xi, yi - 1, outrgb, is_torus);
- count += imapaint_ibuf_add_if(ibuf, xi, yi + 1, outrgb, is_torus);
-
- count += imapaint_ibuf_add_if(ibuf, xi + 1, yi - 1, outrgb, is_torus);
- count += imapaint_ibuf_add_if(ibuf, xi + 1, yi, outrgb, is_torus);
- count += imapaint_ibuf_add_if(ibuf, xi + 1, yi + 1, outrgb, is_torus);
-
- mul_v3_fl(outrgb, 1.0f / (float)count);
-
- /* write into brush buffer */
- xo = out_off[0] + x;
- yo = out_off[1] + y;
- imapaint_ibuf_rgb_set(ibufb, xo, yo, 0, outrgb);
- }
- }
-}
-
-static void imapaint_set_region(ImagePaintRegion *region, int destx, int desty, int srcx, int srcy, int width, int height)
-{
- region->destx = destx;
- region->desty = desty;
- region->srcx = srcx;
- region->srcy = srcy;
- region->width = width;
- region->height = height;
-}
-
-static int imapaint_torus_split_region(ImagePaintRegion region[4], ImBuf *dbuf, ImBuf *sbuf)
-{
- int destx = region->destx;
- int desty = region->desty;
- int srcx = region->srcx;
- int srcy = region->srcy;
- int width = region->width;
- int height = region->height;
- 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;
-
- /* clip width of blending area to destination imbuf, to avoid writing the
- * same pixel twice */
- origw = w = (width > dbuf->x) ? dbuf->x : width;
- origh = h = (height > dbuf->y) ? dbuf->y : height;
-
- /* clip within image */
- IMB_rectclip(dbuf, sbuf, &destx, &desty, &srcx, &srcy, &w, &h);
- imapaint_set_region(&region[tot++], destx, desty, srcx, srcy, w, h);
-
- /* do 3 other rects if needed */
- if (w < origw)
- imapaint_set_region(&region[tot++], (destx + w) % dbuf->x, desty, (srcx + w) % sbuf->x, srcy, origw - w, h);
- if (h < origh)
- imapaint_set_region(&region[tot++], destx, (desty + h) % dbuf->y, srcx, (srcy + h) % sbuf->y, w, origh - h);
- if ((w < origw) && (h < origh))
- imapaint_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 imapaint_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos)
-{
- ImagePaintRegion region[4];
- int a, tot;
-
- imapaint_set_region(region, 0, 0, pos[0], pos[1], ibufb->x, ibufb->y);
- tot = imapaint_torus_split_region(region, ibufb, ibuf);
-
- for (a = 0; a < tot; a++)
- IMB_rectblend(ibufb, ibuf, region[a].destx, region[a].desty,
- region[a].srcx, region[a].srcy,
- region[a].width, region[a].height, IMB_BLEND_COPY_RGB);
-}
-
-static ImBuf *imapaint_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos)
-{
- /* note: allocImbuf returns zero'd memory, so regions outside image will
- * have zero alpha, and hence not be blended onto the image */
- int w = ibufb->x, h = ibufb->y, destx = 0, desty = 0, srcx = pos[0], srcy = pos[1];
- ImBuf *clonebuf = IMB_allocImBuf(w, h, ibufb->planes, ibufb->flags);
-
- IMB_rectclip(clonebuf, ibuf, &destx, &desty, &srcx, &srcy, &w, &h);
- IMB_rectblend(clonebuf, ibuf, destx, desty, srcx, srcy, w, h,
- IMB_BLEND_COPY_RGB);
- IMB_rectblend(clonebuf, ibufb, destx, desty, destx, desty, w, h,
- IMB_BLEND_COPY_ALPHA);
-
- return clonebuf;
-}
-
-static void imapaint_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);
-}
-
-/* dosnt run for projection painting
- * only the old style painting in the 3d view */
-static int imapaint_paint_op(void *state, ImBuf *ibufb, const float lastpos[2], const float pos[2])
-{
- ImagePaintState *s = ((ImagePaintState *)state);
- ImBuf *clonebuf = NULL, *frombuf;
- ImagePaintRegion region[4];
- short torus = s->brush->flag & BRUSH_TORUS;
- short blend = s->blend;
- float *offset = s->brush->clone.offset;
- float liftpos[2];
- int bpos[2], blastpos[2], bliftpos[2];
- int a, tot;
-
- imapaint_convert_brushco(ibufb, pos, bpos);
-
- /* lift from canvas */
- if (s->tool == PAINT_TOOL_SOFTEN) {
- imapaint_lift_soften(s->canvas, ibufb, bpos, torus);
- }
- else if (s->tool == PAINT_TOOL_SMEAR) {
- if (lastpos[0] == pos[0] && lastpos[1] == pos[1])
- return 0;
-
- imapaint_convert_brushco(ibufb, lastpos, blastpos);
- imapaint_lift_smear(s->canvas, ibufb, blastpos);
- }
- else if (s->tool == PAINT_TOOL_CLONE && s->clonecanvas) {
- liftpos[0] = pos[0] - offset[0] * s->canvas->x;
- liftpos[1] = pos[1] - offset[1] * s->canvas->y;
-
- imapaint_convert_brushco(ibufb, liftpos, bliftpos);
- clonebuf = imapaint_lift_clone(s->clonecanvas, ibufb, bliftpos);
- }
-
- frombuf = (clonebuf) ? clonebuf : ibufb;
-
- if (torus) {
- imapaint_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
- tot = imapaint_torus_split_region(region, s->canvas, frombuf);
- }
- else {
- imapaint_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
- tot = 1;
- }
-
- /* blend into canvas */
- for (a = 0; a < tot; a++) {
- imapaint_dirty_region(s->image, s->canvas,
- region[a].destx, region[a].desty,
- region[a].width, region[a].height);
-
- IMB_rectblend(s->canvas, frombuf,
- region[a].destx, region[a].desty,
- region[a].srcx, region[a].srcy,
- region[a].width, region[a].height, blend);
- }
-
- if (clonebuf) IMB_freeImBuf(clonebuf);
-
- return 1;
-}
-
-/* 3D TexturePaint */
-
-static int texpaint_break_stroke(float *prevuv, float *fwuv, float *bkuv, float *uv)
-{
- float d1[2], d2[2];
- float mismatch = len_v2v2(fwuv, uv);
- float len1 = len_v2v2(prevuv, fwuv);
- float len2 = len_v2v2(bkuv, uv);
-
- sub_v2_v2v2(d1, fwuv, prevuv);
- sub_v2_v2v2(d2, uv, bkuv);
-
- return ((dot_v2v2(d1, d2) < 0.0f) || (mismatch > MAX2(len1, len2) * 2));
-}
-
-/* ImagePaint Common */
-
-static int imapaint_canvas_set(ImagePaintState *s, Image *ima)
-{
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL);
-
- /* verify that we can paint and set canvas */
- if (ima == NULL) {
- return 0;
- }
- else if (ima->packedfile && ima->rr) {
- s->warnpackedfile = ima->id.name + 2;
- return 0;
- }
- else if (ibuf && ibuf->channels != 4) {
- s->warnmultifile = ima->id.name + 2;
- return 0;
- }
- else if (!ibuf || !(ibuf->rect || ibuf->rect_float))
- return 0;
-
- s->image = ima;
- s->canvas = ibuf;
-
- /* set clone canvas */
- if (s->tool == PAINT_TOOL_CLONE) {
- ima = s->brush->clone.image;
- ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL);
-
- if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- return 0;
- }
-
- s->clonecanvas = ibuf;
-
- /* temporarily add float rect for cloning */
- if (s->canvas->rect_float && !s->clonecanvas->rect_float) {
- IMB_float_from_rect(s->clonecanvas);
- }
- else if (!s->canvas->rect_float && !s->clonecanvas->rect)
- IMB_rect_from_float(s->clonecanvas);
- }
-
- return 1;
-}
-
-static void imapaint_canvas_free(ImagePaintState *s)
-{
- BKE_image_release_ibuf(s->image, s->canvas, NULL);
- BKE_image_release_ibuf(s->brush->clone.image, s->clonecanvas, NULL);
-}
-
-static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, Image *image, short texpaint, float *uv, double time, int update, float pressure)
-{
- ImBuf *ibuf = BKE_image_acquire_ibuf(image, s->sima ? &s->sima->iuser : NULL, NULL);
- float pos[2];
- int is_data;
-
- if (!ibuf)
- return 0;
-
- is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA;
-
- pos[0] = uv[0] * ibuf->x;
- pos[1] = uv[1] * ibuf->y;
-
- BKE_brush_painter_require_imbuf(painter, ((ibuf->rect_float) ? 1 : 0), 0, 0);
-
- /* OCIO_TODO: float buffers are now always linear, so always use color correction
- * this should probably be changed when texture painting color space is supported
- */
- if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, is_data == FALSE)) {
- if (update)
- imapaint_image_update(s->scene, s->sima, image, ibuf, texpaint);
- BKE_image_release_ibuf(image, ibuf, NULL);
- return 1;
- }
- else {
- BKE_image_release_ibuf(image, ibuf, NULL);
- return 0;
- }
-}
-
-static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPainter *painter, short texpaint, const int prevmval[2], const int mval[2], double time, float pressure)
-{
- Image *newimage = NULL;
- float fwuv[2], bkuv[2], newuv[2];
- unsigned int newfaceindex;
- int breakstroke = 0, redraw = 0;
-
- if (texpaint) {
- /* pick new face and image */
- if (imapaint_pick_face(vc, mval, &newfaceindex, s->dm_totface) &&
- ((s->do_facesel == FALSE) || (s->dm_mface[newfaceindex].flag & ME_FACE_SEL)))
- {
- ImBuf *ibuf;
-
- newimage = imapaint_face_image(s, newfaceindex);
- ibuf = BKE_image_acquire_ibuf(newimage, s->sima ? &s->sima->iuser : NULL, NULL);
-
- if (ibuf && ibuf->rect)
- imapaint_pick_uv(s->scene, s->ob, newfaceindex, mval, newuv);
- else {
- newimage = NULL;
- newuv[0] = newuv[1] = 0.0f;
- }
-
- BKE_image_release_ibuf(newimage, ibuf, NULL);
- }
- else
- newuv[0] = newuv[1] = 0.0f;
-
- /* see if stroke is broken, and if so finish painting in old position */
- if (s->image) {
- imapaint_pick_uv(s->scene, s->ob, s->faceindex, mval, fwuv);
- imapaint_pick_uv(s->scene, s->ob, newfaceindex, prevmval, bkuv);
-
- if (newimage == s->image)
- breakstroke = texpaint_break_stroke(s->uv, fwuv, bkuv, newuv);
- else
- breakstroke = 1;
- }
- else
- fwuv[0] = fwuv[1] = 0.0f;
-
- if (breakstroke) {
- imapaint_pick_uv(s->scene, s->ob, s->faceindex, mval, fwuv);
- redraw |= imapaint_paint_sub_stroke(s, painter, s->image, texpaint,
- fwuv, time, 1, pressure);
- imapaint_clear_partial_redraw();
- BKE_brush_painter_break_stroke(painter);
- }
-
- /* set new canvas */
- if (newimage && (newimage != s->image))
- if (!imapaint_canvas_set(s, newimage))
- newimage = NULL;
-
- /* paint in new image */
- if (newimage) {
- if (breakstroke)
- redraw |= imapaint_paint_sub_stroke(s, painter, newimage,
- texpaint, bkuv, time, 0, pressure);
- redraw |= imapaint_paint_sub_stroke(s, painter, newimage, texpaint,
- newuv, time, 1, pressure);
- }
-
- /* update state */
- s->image = newimage;
- s->faceindex = newfaceindex;
- s->uv[0] = newuv[0];
- s->uv[1] = newuv[1];
- }
- else {
- UI_view2d_region_to_view(s->v2d, mval[0], mval[1], &newuv[0], &newuv[1]);
- redraw |= imapaint_paint_sub_stroke(s, painter, s->image, texpaint, newuv,
- time, 1, pressure);
- }
-
- if (redraw)
- imapaint_clear_partial_redraw();
-
- return redraw;
-}
-
/************************ image paint poll ************************/
static Brush *image_paint_brush(bContext *C)
@@ -4866,16 +346,6 @@ static Brush *image_paint_brush(bContext *C)
return paint_brush(&settings->imapaint.paint);
}
-static Brush *uv_sculpt_brush(bContext *C)
-{
- Scene *scene = CTX_data_scene(C);
- ToolSettings *settings = scene->toolsettings;
-
- if (!settings->uvsculpt)
- return NULL;
- return paint_brush(&settings->uvsculpt->paint);
-}
-
static int image_paint_poll(bContext *C)
{
Object *obact = CTX_data_active_object(C);
@@ -4901,38 +371,6 @@ static int image_paint_poll(bContext *C)
return 0;
}
-static int uv_sculpt_brush_poll(bContext *C)
-{
- BMEditMesh *em;
- int ret;
- Object *obedit = CTX_data_edit_object(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- Scene *scene = CTX_data_scene(C);
- ToolSettings *toolsettings = scene->toolsettings;
-
- if (!uv_sculpt_brush(C) || !obedit || obedit->type != OB_MESH)
- return 0;
-
- em = BMEdit_FromObject(obedit);
- ret = EDBM_mtexpoly_check(em);
-
- if (ret && sima) {
- ARegion *ar = CTX_wm_region(C);
- if ((toolsettings->use_uv_sculpt) && ar->regiontype == RGN_TYPE_WINDOW)
- return 1;
- }
-
- return 0;
-}
-
-static int image_paint_3d_poll(bContext *C)
-{
- if (CTX_wm_region_view3d(C))
- return image_paint_poll(C);
-
- return 0;
-}
-
static int image_paint_2d_clone_poll(bContext *C)
{
Brush *brush = image_paint_brush(C);
@@ -4946,476 +384,240 @@ static int image_paint_2d_clone_poll(bContext *C)
}
/************************ paint operator ************************/
-
-typedef enum PaintMode {
+typedef enum TexPaintMode {
PAINT_MODE_2D,
- PAINT_MODE_3D,
PAINT_MODE_3D_PROJECT
-} PaintMode;
+} TexPaintMode;
typedef struct PaintOperation {
- PaintMode mode;
+ TexPaintMode mode;
- BrushPainter *painter;
- ImagePaintState s;
- ProjPaintState ps;
+ void *custom_paint;
- int first;
int prevmouse[2];
- float prev_pressure; /* need this since we don't get tablet events for pressure change */
- int orig_brush_size;
double starttime;
ViewContext vc;
- wmTimer *timer;
-
- short restore_projection;
} PaintOperation;
-static void paint_redraw(bContext *C, ImagePaintState *s, int texpaint, int final)
-{
- if (final) {
- if (s->image && !(texpaint || (s->sima && s->sima->lock)))
- GPU_free_image(s->image);
-
- /* compositor listener deals with updating */
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, s->image);
- }
- else {
- if (!s->sima || !s->sima->lock)
- ED_region_tag_redraw(CTX_wm_region(C));
- else
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, s->image);
- }
-}
-
-/* initialize project paint settings from context */
-static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps)
+void paint_brush_init_tex(Brush *brush)
{
- Scene *scene = CTX_data_scene(C);
- ToolSettings *settings = scene->toolsettings;
- Brush *brush = paint_brush(&settings->imapaint.paint);
-
- /* brush */
- ps->brush = brush;
- ps->tool = brush->imagepaint_tool;
- ps->blend = brush->blend;
-
- /* sizeof ProjPixel, since we alloc this a _lot_ */
- ps->pixel_sizeof = project_paint_pixel_sizeof(ps->tool);
- BLI_assert(ps->pixel_sizeof >= sizeof(ProjPixel));
-
- ps->is_airbrush = (brush->flag & BRUSH_AIRBRUSH) ? 1 : 0;
- ps->is_texbrush = (brush->mtex.tex) ? 1 : 0;
-
-
- /* these can be NULL */
- ps->v3d = CTX_wm_view3d(C);
- ps->rv3d = CTX_wm_region_view3d(C);
- ps->ar = CTX_wm_region(C);
-
- ps->scene = scene;
- ps->ob = ob; /* allow override of active object */
-
- /* setup projection painting data */
- ps->do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? 0 : 1;
- ps->do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? 0 : 1;
- ps->do_mask_normal = (settings->imapaint.flag & IMAGEPAINT_PROJECT_FLAT) ? 0 : 1;
- ps->do_new_shading_nodes = BKE_scene_use_new_shading_nodes(scene); /* only cache the value */
-
- if (ps->tool == PAINT_TOOL_CLONE)
- ps->do_layer_clone = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE);
-
- ps->do_layer_stencil = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) ? 1 : 0;
- ps->do_layer_stencil_inv = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) ? 1 : 0;
-
-
-#ifndef PROJ_DEBUG_NOSEAMBLEED
- ps->seam_bleed_px = settings->imapaint.seam_bleed; /* pixel num to bleed */
-#endif
-
- if (ps->do_mask_normal) {
- ps->normal_angle_inner = settings->imapaint.normal_angle;
- ps->normal_angle = (ps->normal_angle_inner + 90.0f) * 0.5f;
- }
- else {
- ps->normal_angle_inner = ps->normal_angle = settings->imapaint.normal_angle;
+ /* init mtex nodes */
+ if (brush) {
+ MTex *mtex = &brush->mtex;
+ if (mtex->tex && mtex->tex->nodetree)
+ ntreeTexBeginExecTree(mtex->tex->nodetree); /* has internal flag to detect it only does it once */
}
-
- ps->normal_angle_inner *= (float)(M_PI_2 / 90);
- ps->normal_angle *= (float)(M_PI_2 / 90);
- ps->normal_angle_range = ps->normal_angle - ps->normal_angle_inner;
-
- if (ps->normal_angle_range <= 0.0f)
- ps->do_mask_normal = FALSE; /* no need to do blending */
}
-static void paint_brush_init_tex(Brush *brush)
+void paint_brush_exit_tex(Brush *brush)
{
- /* init mtex nodes */
if (brush) {
MTex *mtex = &brush->mtex;
if (mtex->tex && mtex->tex->nodetree)
- ntreeTexBeginExecTree(mtex->tex->nodetree, 1); /* has internal flag to detect it only does it once */
+ ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
}
-
}
-static int texture_paint_init(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- ToolSettings *settings = scene->toolsettings;
- Brush *brush = paint_brush(&settings->imapaint.paint);
- PaintOperation *pop = MEM_callocN(sizeof(PaintOperation), "PaintOperation"); /* caller frees */
- pop->first = 1;
- op->customdata = pop;
-
- /* initialize from context */
- if (CTX_wm_region_view3d(C)) {
- pop->mode = PAINT_MODE_3D;
-
- if (!(settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE))
- pop->mode = PAINT_MODE_3D_PROJECT;
- else
- view3d_set_viewcontext(C, &pop->vc);
+static void paint_redraw(const bContext *C, PaintOperation *pop, int final)
+{
+ if (pop->mode == PAINT_MODE_2D) {
+ paint_2d_redraw(C, pop->custom_paint, final);
}
else {
- pop->s.sima = CTX_wm_space_image(C);
- pop->s.v2d = &CTX_wm_region(C)->v2d;
- }
-
- pop->s.scene = scene;
- pop->s.screen = CTX_wm_screen(C);
-
- pop->s.brush = brush;
- pop->s.tool = brush->imagepaint_tool;
- if (pop->mode == PAINT_MODE_3D && (pop->s.tool == PAINT_TOOL_CLONE))
- pop->s.tool = PAINT_TOOL_DRAW;
- pop->s.blend = brush->blend;
- pop->orig_brush_size = BKE_brush_size_get(scene, brush);
-
- if (pop->mode != PAINT_MODE_2D) {
- Object *ob = OBACT;
- Mesh *me = BKE_mesh_from_object(ob);
-
- if (!me) {
- return 0;
- }
-
- pop->s.ob = ob;
- pop->s.do_facesel = (me->editflag & ME_EDIT_PAINT_MASK) != 0;
-
- /* for non prohect paint we need */
- /* fill in derived mesh */
- if (ob->derivedFinal && CustomData_has_layer(&ob->derivedFinal->faceData, CD_MTFACE)) {
- pop->s.dm = ob->derivedFinal;
- pop->s.dm_release = FALSE;
+ if (final) {
+ /* compositor listener deals with updating */
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, NULL);
}
else {
- pop->s.dm = mesh_get_derived_final(pop->s.scene, ob, pop->s.scene->customdata_mask | CD_MASK_MTFACE);
- pop->s.dm_release = TRUE;
+ ED_region_tag_redraw(CTX_wm_region(C));
}
+ }
+}
- if (!CustomData_has_layer(&pop->s.dm->faceData, CD_MTFACE)) {
+static PaintOperation * texture_paint_init(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *settings = scene->toolsettings;
+ PaintOperation *pop = MEM_callocN(sizeof(PaintOperation), "PaintOperation"); /* caller frees */
+ int mode = RNA_enum_get(op->ptr, "mode");
+ view3d_set_viewcontext(C, &pop->vc);
- if (pop->s.dm_release)
- pop->s.dm->release(pop->s.dm);
+ /* TODO Should avoid putting this here. Instead, last position should be requested
+ * from stroke system. */
+ pop->prevmouse[0] = event->mval[0];
+ pop->prevmouse[1] = event->mval[1];
- pop->s.dm = NULL;
- return 0;
- }
- pop->s.dm_mface = pop->s.dm->getTessFaceArray(pop->s.dm);
- pop->s.dm_mtface = pop->s.dm->getTessFaceDataArray(pop->s.dm, CD_MTFACE);
- pop->s.dm_totface = pop->s.dm->getNumTessFaces(pop->s.dm);
+ /* initialize from context */
+ if (CTX_wm_region_view3d(C)) {
+ pop->mode = PAINT_MODE_3D_PROJECT;
+ pop->custom_paint = paint_proj_new_stroke(C, OBACT, pop->prevmouse, mode);
}
else {
- pop->s.image = pop->s.sima->image;
-
- if (!imapaint_canvas_set(&pop->s, pop->s.image)) {
- if (pop->s.warnmultifile)
- BKE_report(op->reports, RPT_WARNING, "Image requires 4 color channels to paint");
- if (pop->s.warnpackedfile)
- BKE_report(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted");
-
- return 0;
- }
+ pop->mode = PAINT_MODE_2D;
+ pop->custom_paint = paint_2d_new_stroke(C, op);
}
-
- paint_brush_init_tex(pop->s.brush);
-
- /* note, if we have no UVs on the derived mesh, then we must return here */
- if (pop->mode == PAINT_MODE_3D_PROJECT) {
-
- /* initialize all data from the context */
- project_state_init(C, OBACT, &pop->ps);
-
- paint_brush_init_tex(pop->ps.brush);
-
- pop->ps.source = PROJ_SRC_VIEW;
-
- if (pop->ps.ob == NULL || !(pop->ps.ob->lay & pop->ps.v3d->lay))
- return 0;
- /* Don't allow brush size below 2 */
- if (BKE_brush_size_get(scene, brush) < 2)
- BKE_brush_size_set(scene, brush, 2);
-
- /* allocate and initialize spatial data structures */
- project_paint_begin(&pop->ps);
-
- if (pop->ps.dm == NULL)
- return 0;
+ if (!pop->custom_paint) {
+ MEM_freeN(pop);
+ return NULL;
}
-
+
settings->imapaint.flag |= IMAGEPAINT_DRAWING;
undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
image_undo_restore, image_undo_free);
- /* create painter */
- pop->painter = BKE_brush_painter_new(scene, pop->s.brush);
+ {
+ UnifiedPaintSettings *ups = &settings->unified_paint_settings;
+ ups->draw_pressure = true;
+ }
- return 1;
+ return pop;
}
-static void paint_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
+static void paint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
{
- PaintOperation *pop = op->customdata;
- float time, mousef[2];
+ PaintOperation *pop = paint_stroke_mode_data(stroke);
+ Scene *scene = CTX_data_scene(C);
+ Brush *brush = paint_brush(&scene->toolsettings->imapaint.paint);
+
+ /* initial brush values. Maybe it should be considered moving these to stroke system */
+ float startsize = BKE_brush_size_get(scene, brush);
+ float startalpha = BKE_brush_alpha_get(scene, brush);
+
+ float mousef[2];
float pressure;
- int mouse[2], redraw;
+ int mouse[2], redraw, eraser;
RNA_float_get_array(itemptr, "mouse", mousef);
mouse[0] = (int)(mousef[0]);
mouse[1] = (int)(mousef[1]);
- time = RNA_float_get(itemptr, "time");
pressure = RNA_float_get(itemptr, "pressure");
+ eraser = RNA_boolean_get(itemptr, "pen_flip");
- if (pop->first)
- project_paint_begin_clone(&pop->ps, mouse);
-
- if (pop->mode == PAINT_MODE_3D)
- view3d_operator_needs_opengl(C);
+ if (BKE_brush_use_alpha_pressure(scene, brush))
+ BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * pressure));
+ if (BKE_brush_use_size_pressure(scene, brush))
+ BKE_brush_size_set(scene, brush, max_ff(1.0f, startsize * pressure));
if (pop->mode == PAINT_MODE_3D_PROJECT) {
- redraw = project_paint_stroke(&pop->ps, pop->painter, pop->prevmouse, mouse, time, pressure);
- pop->prevmouse[0] = mouse[0];
- pop->prevmouse[1] = mouse[1];
-
+ redraw = paint_proj_stroke(C, pop->custom_paint, pop->prevmouse, mouse);
}
else {
- redraw = imapaint_paint_stroke(&pop->vc, &pop->s, pop->painter, pop->mode == PAINT_MODE_3D, pop->prevmouse, mouse, time, pressure);
- pop->prevmouse[0] = mouse[0];
- pop->prevmouse[1] = mouse[1];
+ redraw = paint_2d_stroke(pop->custom_paint, pop->prevmouse, mouse, eraser);
}
- if (redraw)
- paint_redraw(C, &pop->s, pop->mode == PAINT_MODE_3D, 0);
+ pop->prevmouse[0] = mouse[0];
+ pop->prevmouse[1] = mouse[1];
- pop->first = 0;
-}
+ /* restore brush values */
+ BKE_brush_alpha_set(scene, brush, startalpha);
+ BKE_brush_size_set(scene, brush, startsize);
+
+
+ if (redraw)
+ paint_redraw(C, pop, 0);
-static void paint_brush_exit_tex(Brush *brush)
-{
- if (brush) {
- MTex *mtex = &brush->mtex;
- if (mtex->tex && mtex->tex->nodetree)
- ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1);
- }
}
-static void paint_exit(bContext *C, wmOperator *op)
+static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
{
Scene *scene = CTX_data_scene(C);
ToolSettings *settings = scene->toolsettings;
- PaintOperation *pop = op->customdata;
-
- if (pop->timer)
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), pop->timer);
+ PaintOperation *pop = paint_stroke_mode_data(stroke);
- if (pop->restore_projection)
- settings->imapaint.flag &= ~IMAGEPAINT_PROJECT_DISABLE;
+ paint_redraw(C, pop, 1);
- paint_brush_exit_tex(pop->s.brush);
-
settings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
- imapaint_canvas_free(&pop->s);
- BKE_brush_painter_free(pop->painter);
if (pop->mode == PAINT_MODE_3D_PROJECT) {
- BKE_brush_size_set(scene, pop->ps.brush, pop->orig_brush_size);
- paint_brush_exit_tex(pop->ps.brush);
-
- project_paint_end(&pop->ps);
+ paint_proj_stroke_done(pop->custom_paint);
}
else {
- /* non projection 3d paint, could move into own function of more needs adding */
- if (pop->s.dm_release)
- pop->s.dm->release(pop->s.dm);
+ paint_2d_stroke_done(pop->custom_paint);
}
-
- paint_redraw(C, &pop->s, pop->mode == PAINT_MODE_3D, 1);
+
undo_paint_push_end(UNDO_PAINT_IMAGE);
-
+
+ /* duplicate warning, see texpaint_init
if (pop->s.warnmultifile)
BKE_reportf(op->reports, RPT_WARNING, "Image requires 4 color channels to paint: %s", pop->s.warnmultifile);
if (pop->s.warnpackedfile)
BKE_reportf(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted: %s", pop->s.warnpackedfile);
-
+ */
MEM_freeN(pop);
-}
-
-static int paint_exec(bContext *C, wmOperator *op)
-{
- if (!texture_paint_init(C, op)) {
- MEM_freeN(op->customdata);
- return OPERATOR_CANCELLED;
- }
- RNA_BEGIN (op->ptr, itemptr, "stroke")
{
- paint_apply(C, op, &itemptr);
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+ ups->draw_pressure = false;
}
- RNA_END;
-
- paint_exit(C, op);
-
- return OPERATOR_FINISHED;
}
-static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event)
+static int paint_stroke_test_start(bContext *UNUSED(C), wmOperator *UNUSED(op), const float UNUSED(mouse[2]))
{
- const Scene *scene = CTX_data_scene(C);
- PaintOperation *pop = op->customdata;
- wmTabletData *wmtab;
- PointerRNA itemptr;
- float pressure, mousef[2];
- double time;
- int tablet;
-
- time = PIL_check_seconds_timer();
-
- tablet = 0;
- pop->s.blend = pop->s.brush->blend;
-
- if (event->custom == EVT_DATA_TABLET) {
- wmtab = event->customdata;
-
- tablet = (wmtab->Active != EVT_TABLET_NONE);
- pressure = wmtab->Pressure;
- if (wmtab->Active == EVT_TABLET_ERASER)
- pop->s.blend = IMB_BLEND_ERASE_ALPHA;
- }
- else { /* otherwise airbrush becomes 1.0 pressure instantly */
- pressure = pop->prev_pressure ? pop->prev_pressure : 1.0f;
- }
-
- if (pop->first) {
- pop->prevmouse[0] = event->mval[0];
- pop->prevmouse[1] = event->mval[1];
- pop->starttime = time;
-
- /* special exception here for too high pressure values on first touch in
- * windows for some tablets, then we just skip first touch .. */
- if (tablet && (pressure >= 0.99f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || BKE_brush_use_alpha_pressure(scene, pop->s.brush) || BKE_brush_use_size_pressure(scene, pop->s.brush)))
- return;
-
- /* This can be removed once fixed properly in
- * BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user)
- * at zero pressure we should do nothing 1/2^12 is 0.0002 which is the sensitivity of the most sensitive pen tablet available */
- if (tablet && (pressure < 0.0002f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || BKE_brush_use_alpha_pressure(scene, pop->s.brush) || BKE_brush_use_size_pressure(scene, pop->s.brush)))
- return;
-
- }
-
- /* fill in stroke */
- RNA_collection_add(op->ptr, "stroke", &itemptr);
-
- mousef[0] = (float)(event->mval[0]);
- mousef[1] = (float)(event->mval[1]);
- RNA_float_set_array(&itemptr, "mouse", mousef);
- RNA_float_set(&itemptr, "time", (float)(time - pop->starttime));
- RNA_float_set(&itemptr, "pressure", pressure);
-
- /* apply */
- paint_apply(C, op, &itemptr);
-
- pop->prev_pressure = pressure;
+ return true;
}
-static int paint_invoke(bContext *C, wmOperator *op, wmEvent *event)
+
+static int paint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
PaintOperation *pop;
+ struct PaintStroke *stroke;
+ int retval;
- if (!texture_paint_init(C, op)) {
- MEM_freeN(op->customdata);
+ if (!(pop = texture_paint_init(C, op, event))) {
return OPERATOR_CANCELLED;
}
-
- paint_apply_event(C, op, event);
- pop = op->customdata;
+ stroke = op->customdata = paint_stroke_new(C, NULL, paint_stroke_test_start,
+ paint_stroke_update_step,
+ paint_stroke_done, event->type);
+ paint_stroke_set_mode_data(stroke, pop);
+ /* add modal handler */
WM_event_add_modal_handler(C, op);
- if (pop->s.brush->flag & BRUSH_AIRBRUSH)
- pop->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
+ retval = op->type->modal(C, op, event);
+ OPERATOR_RETVAL_CHECK(retval);
+ BLI_assert(retval == OPERATOR_RUNNING_MODAL);
return OPERATOR_RUNNING_MODAL;
}
-static int paint_modal(bContext *C, wmOperator *op, wmEvent *event)
-{
- PaintOperation *pop = op->customdata;
-
- switch (event->type) {
- case LEFTMOUSE:
- case MIDDLEMOUSE:
- case RIGHTMOUSE: // XXX hardcoded
- paint_exit(C, op);
- return OPERATOR_FINISHED;
- case MOUSEMOVE:
- case INBETWEEN_MOUSEMOVE:
- paint_apply_event(C, op, event);
- break;
- case TIMER:
- if (event->customdata == pop->timer)
- paint_apply_event(C, op, event);
- break;
- }
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static int paint_cancel(bContext *C, wmOperator *op)
-{
- paint_exit(C, op);
-
- return OPERATOR_CANCELLED;
-}
void PAINT_OT_image_paint(wmOperatorType *ot)
{
+ static EnumPropertyItem stroke_mode_items[] = {
+ {BRUSH_STROKE_NORMAL, "NORMAL", 0, "Normal", "Apply brush normally"},
+ {BRUSH_STROKE_INVERT, "INVERT", 0, "Invert", "Invert action of brush for duration of stroke"},
+ {0}
+ };
+
/* identifiers */
ot->name = "Image Paint";
ot->idname = "PAINT_OT_image_paint";
ot->description = "Paint a stroke into the image";
-
+
/* api callbacks */
- ot->exec = paint_exec;
ot->invoke = paint_invoke;
- ot->modal = paint_modal;
- ot->cancel = paint_cancel;
+ ot->modal = paint_stroke_modal;
+ /* ot->exec = paint_exec; <-- needs stroke property */
ot->poll = image_paint_poll;
+ ot->cancel = paint_stroke_cancel;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ RNA_def_enum(ot->srna, "mode", stroke_mode_items, BRUSH_STROKE_NORMAL,
+ "Paint Stroke Mode",
+ "Action taken when a paint stroke is made");
- /* properties */
RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
}
-static int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
+
+int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
@@ -5437,7 +639,7 @@ static int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
/************************ cursor drawing *******************************/
-static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata))
+void brush_drawcursor_texpaint_uvsculpt(bContext *C, int x, int y, void *UNUSED(customdata))
{
#define PX_SIZE_FADE_MAX 12.0f
#define PX_SIZE_FADE_MIN 4.0f
@@ -5482,6 +684,16 @@ static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata)
glColor4f(brush->add_col[0], brush->add_col[1], brush->add_col[2], alpha);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
+ {
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+ /* hrmf, duplicate paint_draw_cursor logic here */
+ if (ups->draw_pressure && BKE_brush_use_size_pressure(scene, brush)) {
+ /* inner at full alpha */
+ glutil_draw_lined_arc(0, (float)(M_PI * 2.0), size * ups->pressure_value, 40);
+ /* outer at half alpha */
+ glColor4f(brush->add_col[0], brush->add_col[1], brush->add_col[2], alpha * 0.5f);
+ }
+ }
glutil_draw_lined_arc(0, (float)(M_PI * 2.0), size, 40);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
@@ -5503,7 +715,8 @@ static void toggle_paint_cursor(bContext *C, int enable)
settings->imapaint.paintcursor = NULL;
}
else if (enable)
- settings->imapaint.paintcursor = WM_paint_cursor_activate(wm, image_paint_poll, brush_drawcursor, NULL);
+ settings->imapaint.paintcursor =
+ WM_paint_cursor_activate(wm, image_paint_poll, brush_drawcursor_texpaint_uvsculpt, NULL);
}
/* enable the paint cursor if it isn't already.
@@ -5530,32 +743,11 @@ void ED_space_image_paint_update(wmWindowManager *wm, ToolSettings *settings)
if (!imapaint->paintcursor) {
imapaint->paintcursor =
WM_paint_cursor_activate(wm, image_paint_poll,
- brush_drawcursor, NULL);
+ brush_drawcursor_texpaint_uvsculpt, NULL);
}
}
}
-
-void ED_space_image_uv_sculpt_update(wmWindowManager *wm, ToolSettings *settings)
-{
- if (settings->use_uv_sculpt) {
- if (!settings->uvsculpt) {
- settings->uvsculpt = MEM_callocN(sizeof(*settings->uvsculpt), "UV Smooth paint");
- settings->uv_sculpt_tool = UV_SCULPT_TOOL_GRAB;
- settings->uv_sculpt_settings = UV_SCULPT_LOCK_BORDERS | UV_SCULPT_ALL_ISLANDS;
- settings->uv_relax_method = UV_SCULPT_TOOL_RELAX_LAPLACIAN;
- }
-
- BKE_paint_init(&settings->uvsculpt->paint, PAINT_CURSOR_SCULPT);
-
- WM_paint_cursor_activate(wm, uv_sculpt_brush_poll,
- brush_drawcursor, NULL);
- }
- else {
- if (settings->uvsculpt)
- settings->uvsculpt->paint.flags &= ~PAINT_SHOW_BRUSH;
- }
-}
/************************ grab clone operator ************************/
typedef struct GrabClone {
@@ -5580,7 +772,7 @@ static int grab_clone_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int grab_clone_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int grab_clone_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Brush *brush = image_paint_brush(C);
GrabClone *cmv;
@@ -5596,7 +788,7 @@ static int grab_clone_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static int grab_clone_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int grab_clone_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
Brush *brush = image_paint_brush(C);
ARegion *ar = CTX_wm_region(C);
@@ -5671,7 +863,7 @@ static int sample_color_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int sample_color_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
RNA_int_set_array(op->ptr, "location", event->mval);
sample_color_exec(C, op);
@@ -5681,7 +873,7 @@ static int sample_color_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static int sample_color_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
switch (event->type) {
case LEFTMOUSE:
@@ -5705,7 +897,7 @@ static int image_paint_sample_color_poll(bContext *C)
if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) {
Mesh *me = BKE_mesh_from_object(obact);
if (me) {
- return !(me->editflag & ME_EDIT_PAINT_MASK);
+ return !(me->editflag & ME_EDIT_PAINT_FACE_SEL);
}
}
}
@@ -5736,57 +928,6 @@ void PAINT_OT_sample_color(wmOperatorType *ot)
RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "Cursor location in region coordinates", 0, 16384);
}
-/******************** set clone cursor operator ********************/
-
-static int set_clone_cursor_exec(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- float *cursor = give_cursor(scene, v3d);
-
- RNA_float_get_array(op->ptr, "location", cursor);
-
- ED_area_tag_redraw(CTX_wm_area(C));
-
- return OPERATOR_FINISHED;
-}
-
-static int set_clone_cursor_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- ARegion *ar = CTX_wm_region(C);
- float location[3];
-
- view3d_operator_needs_opengl(C);
-
- if (!ED_view3d_autodist(scene, ar, v3d, event->mval, location))
- return OPERATOR_CANCELLED;
-
- RNA_float_set_array(op->ptr, "location", location);
-
- return set_clone_cursor_exec(C, op);
-}
-
-void PAINT_OT_clone_cursor_set(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Set Clone Cursor";
- ot->idname = "PAINT_OT_clone_cursor_set";
- ot->description = "Set the location of the clone cursor";
-
- /* api callbacks */
- ot->exec = set_clone_cursor_exec;
- ot->invoke = set_clone_cursor_invoke;
- ot->poll = image_paint_3d_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_float_vector(ot->srna, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location", "Cursor location in world space coordinates", -10000.0f, 10000.0f);
-}
-
/******************** texture paint toggle operator ********************/
static int texture_paint_toggle_poll(bContext *C)
@@ -5880,11 +1021,6 @@ int image_texture_paint_poll(bContext *C)
return (texture_paint_poll(C) || image_paint_poll(C));
}
-int uv_sculpt_poll(bContext *C)
-{
- return uv_sculpt_brush_poll(C);
-}
-
int facemask_paint_poll(bContext *C)
{
return paint_facesel_test(CTX_data_active_object(C));
@@ -5899,201 +1035,4 @@ int mask_paint_poll(bContext *C)
{
return paint_facesel_test(CTX_data_active_object(C)) || paint_vertsel_test(CTX_data_active_object(C));
}
-/* use project paint to re-apply an image */
-static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
-{
- Image *image = BLI_findlink(&CTX_data_main(C)->image, RNA_enum_get(op->ptr, "image"));
- Scene *scene = CTX_data_scene(C);
- ProjPaintState ps = {NULL};
- int orig_brush_size;
- IDProperty *idgroup;
- IDProperty *view_data = NULL;
-
- project_state_init(C, OBACT, &ps);
-
- if (ps.ob == NULL || ps.ob->type != OB_MESH) {
- BKE_report(op->reports, RPT_ERROR, "No active mesh object");
- return OPERATOR_CANCELLED;
- }
-
- if (image == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Image could not be found");
- return OPERATOR_CANCELLED;
- }
-
- ps.reproject_image = image;
- ps.reproject_ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
-
- if (ps.reproject_ibuf == NULL || ps.reproject_ibuf->rect == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Image data could not be found");
- return OPERATOR_CANCELLED;
- }
-
- idgroup = IDP_GetProperties(&image->id, 0);
-
- if (idgroup) {
- view_data = IDP_GetPropertyTypeFromGroup(idgroup, PROJ_VIEW_DATA_ID, IDP_ARRAY);
-
- /* type check to make sure its ok */
- if (view_data->len != PROJ_VIEW_DATA_SIZE || view_data->subtype != IDP_FLOAT) {
- BKE_report(op->reports, RPT_ERROR, "Image project data invalid");
- return OPERATOR_CANCELLED;
- }
- }
-
- if (view_data) {
- /* image has stored view projection info */
- ps.source = PROJ_SRC_IMAGE_VIEW;
- }
- else {
- ps.source = PROJ_SRC_IMAGE_CAM;
-
- if (scene->camera == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active camera set");
- return OPERATOR_CANCELLED;
- }
- }
-
- /* override */
- ps.is_texbrush = 0;
- ps.is_airbrush = 1;
- orig_brush_size = BKE_brush_size_get(scene, ps.brush);
- BKE_brush_size_set(scene, ps.brush, 32); /* cover the whole image */
-
- ps.tool = PAINT_TOOL_DRAW; /* so pixels are initialized with minimal info */
-
- scene->toolsettings->imapaint.flag |= IMAGEPAINT_DRAWING;
-
- undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
- image_undo_restore, image_undo_free);
-
- /* allocate and initialize spatial data structures */
- project_paint_begin(&ps);
-
- if (ps.dm == NULL) {
- BKE_brush_size_set(scene, ps.brush, orig_brush_size);
- return OPERATOR_CANCELLED;
- }
- else {
- float pos[2] = {0.0, 0.0};
- float lastpos[2] = {0.0, 0.0};
- int a;
-
- for (a = 0; a < ps.image_tot; a++)
- partial_redraw_array_init(ps.projImages[a].partRedrawRect);
-
- project_paint_op(&ps, NULL, lastpos, pos);
-
- project_image_refresh_tagged(&ps);
-
- for (a = 0; a < ps.image_tot; a++) {
- GPU_free_image(ps.projImages[a].ima);
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ps.projImages[a].ima);
- }
- }
- project_paint_end(&ps);
-
- scene->toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
- BKE_brush_size_set(scene, ps.brush, orig_brush_size);
-
- return OPERATOR_FINISHED;
-}
-
-void PAINT_OT_project_image(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Project Image";
- ot->idname = "PAINT_OT_project_image";
- ot->description = "Project an edited render from the active camera back onto the object";
-
- /* api callbacks */
- ot->invoke = WM_enum_search_invoke;
- ot->exec = texture_paint_camera_project_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- prop = RNA_def_enum(ot->srna, "image", DummyRNA_NULL_items, 0, "Image", "");
- RNA_def_enum_funcs(prop, RNA_image_itemf);
- ot->prop = prop;
-}
-
-static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
-{
- Image *image;
- ImBuf *ibuf;
- char filename[FILE_MAX];
-
- Scene *scene = CTX_data_scene(C);
- ToolSettings *settings = scene->toolsettings;
- int w = settings->imapaint.screen_grab_size[0];
- int h = settings->imapaint.screen_grab_size[1];
- int maxsize;
- char err_out[256] = "unknown";
-
- RNA_string_get(op->ptr, "filepath", filename);
-
- glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
-
- if (w > maxsize) w = maxsize;
- if (h > maxsize) h = maxsize;
-
- ibuf = ED_view3d_draw_offscreen_imbuf(CTX_data_scene(C), CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, FALSE, FALSE, 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 */
- BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer: %s", err_out);
- return OPERATOR_CANCELLED;
- }
-
- image = BKE_image_add_from_imbuf(ibuf);
-
- if (image) {
- /* now for the trickyness. store the view projection here!
- * re-projection will reuse this */
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
-
- IDPropertyTemplate val;
- IDProperty *idgroup = IDP_GetProperties(&image->id, 1);
- IDProperty *view_data;
- int orth;
- float *array;
-
- val.array.len = PROJ_VIEW_DATA_SIZE;
- val.array.type = IDP_FLOAT;
- view_data = IDP_New(IDP_ARRAY, &val, PROJ_VIEW_DATA_ID);
-
- array = (float *)IDP_Array(view_data);
- 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);
- orth = project_paint_view_clip(v3d, rv3d, &array[0], &array[1]);
- array[2] = orth ? 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 */
-
- IDP_AddToGroup(idgroup, view_data);
-
- rename_id(&image->id, "image_view");
- }
-
- return OPERATOR_FINISHED;
-}
-
-void PAINT_OT_image_from_view(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Image from View";
- ot->idname = "PAINT_OT_image_from_view";
- ot->description = "Make an image from the current 3D view for re-projection";
-
- /* api callbacks */
- ot->exec = texture_paint_image_from_view_exec;
- ot->poll = ED_operator_region_view3d_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER;
-
- RNA_def_string_file_name(ot->srna, "filepath", "", FILE_MAX, "File Path", "Name of the file");
-}
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
new file mode 100644
index 00000000000..90a2c8037c4
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -0,0 +1,824 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 blender/editors/sculpt_paint/paint_image_2d.c
+ * \ingroup bke
+ */
+//#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+#include "BKE_brush.h"
+#include "BKE_main.h"
+#include "BKE_image.h"
+#include "BKE_paint.h"
+#include "BKE_report.h"
+
+#include "ED_screen.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_colormanagement.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_view2d.h"
+
+#include "RE_shader_ext.h"
+
+#include "GPU_draw.h"
+
+#include "paint_intern.h"
+
+/* Brush Painting for 2D image editor */
+
+/* Defines and Structs */
+/* FTOCHAR as inline function */
+BLI_INLINE unsigned char f_to_char(const float val)
+{
+ return FTOCHAR(val);
+}
+#define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { \
+ (c)[0] = f_to_char((f)[0]); \
+ (c)[1] = f_to_char((f)[1]); \
+ (c)[2] = f_to_char((f)[2]); \
+} (void)0
+
+#define IMAPAINT_CHAR_RGB_TO_FLOAT(f, c) { \
+ (f)[0] = IMAPAINT_CHAR_TO_FLOAT((c)[0]); \
+ (f)[1] = IMAPAINT_CHAR_TO_FLOAT((c)[1]); \
+ (f)[2] = IMAPAINT_CHAR_TO_FLOAT((c)[2]); \
+} (void)0
+
+#define IMAPAINT_FLOAT_RGB_COPY(a, b) copy_v3_v3(a, b)
+
+typedef struct BrushPainterCache {
+ short enabled;
+
+ int size; /* size override, if 0 uses 2*BKE_brush_size_get(brush) */
+ short flt; /* need float imbuf? */
+ short texonly; /* no alpha, color or fallof, only texture in imbuf */
+
+ int lastsize;
+ float lastalpha;
+ float lastjitter;
+ float last_rotation;
+
+ ImBuf *ibuf;
+ ImBuf *texibuf;
+ ImBuf *maskibuf;
+} BrushPainterCache;
+
+typedef struct BrushPainter {
+ Scene *scene;
+ Brush *brush;
+
+ float lastpaintpos[2]; /* position of last paint op */
+ float startpaintpos[2]; /* position of first paint */
+
+ short firsttouch; /* first paint op */
+
+ BrushPainterCache cache;
+} BrushPainter;
+
+typedef struct ImagePaintRegion {
+ int destx, desty;
+ int srcx, srcy;
+ int width, height;
+} ImagePaintRegion;
+
+typedef struct ImagePaintState {
+ BrushPainter *painter;
+ SpaceImage *sima;
+ View2D *v2d;
+ Scene *scene;
+ bScreen *screen;
+
+ Brush *brush;
+ short tool, blend;
+ Image *image;
+ ImBuf *canvas;
+ ImBuf *clonecanvas;
+ char *warnpackedfile;
+ char *warnmultifile;
+
+ /* viewport texture paint only, but _not_ project paint */
+ Object *ob;
+ int faceindex;
+ float uv[2];
+ int do_facesel;
+} ImagePaintState;
+
+
+static BrushPainter *brush_painter_2d_new(Scene *scene, Brush *brush)
+{
+ BrushPainter *painter = MEM_callocN(sizeof(BrushPainter), "BrushPainter");
+
+ painter->brush = brush;
+ painter->scene = scene;
+ painter->firsttouch = 1;
+ painter->cache.lastsize = -1; /* force ibuf create in refresh */
+
+ return painter;
+}
+
+
+static void brush_painter_2d_require_imbuf(BrushPainter *painter, short flt, short texonly, int size)
+{
+ if ((painter->cache.flt != flt) || (painter->cache.size != size) ||
+ ((painter->cache.texonly != texonly) && texonly))
+ {
+ if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
+ if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
+ painter->cache.ibuf = painter->cache.maskibuf = NULL;
+ painter->cache.lastsize = -1; /* force ibuf create in refresh */
+ }
+
+ if (painter->cache.flt != flt) {
+ if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
+ painter->cache.texibuf = NULL;
+ painter->cache.lastsize = -1; /* force ibuf create in refresh */
+ }
+
+ painter->cache.size = size;
+ painter->cache.flt = flt;
+ painter->cache.texonly = texonly;
+ painter->cache.enabled = 1;
+}
+
+static void brush_painter_2d_free(BrushPainter *painter)
+{
+ if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
+ if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
+ if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
+ MEM_freeN(painter);
+}
+
+static void brush_painter_2d_do_partial(BrushPainter *painter, ImBuf *oldtexibuf,
+ int x, int y, int w, int h, int xt, int yt,
+ const float pos[2])
+{
+ Scene *scene = painter->scene;
+ Brush *brush = painter->brush;
+ ImBuf *ibuf, *maskibuf, *texibuf;
+ float *bf, *mf, *tf, *otf = NULL, xoff, yoff, xy[2], rgba[4];
+ unsigned char *b, *m, *t, *ot = NULL;
+ int dotexold, origx = x, origy = y;
+ const int radius = BKE_brush_size_get(painter->scene, brush);
+
+ xoff = -radius + 0.5f;
+ yoff = -radius + 0.5f;
+ xoff += (int)pos[0] - (int)painter->startpaintpos[0];
+ yoff += (int)pos[1] - (int)painter->startpaintpos[1];
+
+ ibuf = painter->cache.ibuf;
+ texibuf = painter->cache.texibuf;
+ maskibuf = painter->cache.maskibuf;
+
+ dotexold = (oldtexibuf != NULL);
+
+ /* not sure if it's actually needed or it's a mistake in coords/sizes
+ * calculation in brush_painter_fixed_tex_partial_update(), but without this
+ * limitation memory gets corrupted at fast strokes with quite big spacing (sergey) */
+ w = min_ii(w, ibuf->x);
+ h = min_ii(h, ibuf->y);
+
+ if (painter->cache.flt) {
+ for (; y < h; y++) {
+ bf = ibuf->rect_float + (y * ibuf->x + origx) * 4;
+ tf = texibuf->rect_float + (y * texibuf->x + origx) * 4;
+ mf = maskibuf->rect_float + (y * maskibuf->x + origx) * 4;
+
+ if (dotexold)
+ otf = oldtexibuf->rect_float + ((y - origy + yt) * oldtexibuf->x + xt) * 4;
+
+ for (x = origx; x < w; x++, bf += 4, mf += 4, tf += 4) {
+ if (dotexold) {
+ copy_v4_v4(tf, otf);
+ otf += 4;
+ }
+ else {
+ xy[0] = x + xoff;
+ xy[1] = y + yoff;
+
+ BKE_brush_sample_tex_2D(scene, brush, xy, tf);
+ }
+
+ bf[0] = tf[0] * mf[0];
+ bf[1] = tf[1] * mf[1];
+ bf[2] = tf[2] * mf[2];
+ bf[3] = tf[3] * mf[3];
+ }
+ }
+ }
+ else {
+ for (; y < h; y++) {
+ b = (unsigned char *)ibuf->rect + (y * ibuf->x + origx) * 4;
+ t = (unsigned char *)texibuf->rect + (y * texibuf->x + origx) * 4;
+ m = (unsigned char *)maskibuf->rect + (y * maskibuf->x + origx) * 4;
+
+ if (dotexold)
+ ot = (unsigned char *)oldtexibuf->rect + ((y - origy + yt) * oldtexibuf->x + xt) * 4;
+
+ for (x = origx; x < w; x++, b += 4, m += 4, t += 4) {
+ if (dotexold) {
+ t[0] = ot[0];
+ t[1] = ot[1];
+ t[2] = ot[2];
+ t[3] = ot[3];
+ ot += 4;
+ }
+ else {
+ xy[0] = x + xoff;
+ xy[1] = y + yoff;
+
+ BKE_brush_sample_tex_2D(scene, brush, xy, rgba);
+ rgba_float_to_uchar(t, rgba);
+ }
+
+ b[0] = t[0] * m[0] / 255;
+ b[1] = t[1] * m[1] / 255;
+ b[2] = t[2] * m[2] / 255;
+ b[3] = t[3] * m[3] / 255;
+ }
+ }
+ }
+}
+
+static void brush_painter_2d_tiled_tex_partial_update(BrushPainter *painter, const float pos[2])
+{
+ const Scene *scene = painter->scene;
+ Brush *brush = painter->brush;
+ BrushPainterCache *cache = &painter->cache;
+ ImBuf *oldtexibuf, *ibuf;
+ int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
+ const int diameter = 2 * BKE_brush_size_get(scene, brush);
+
+ imbflag = (cache->flt) ? IB_rectfloat : IB_rect;
+ if (!cache->ibuf)
+ cache->ibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
+ ibuf = cache->ibuf;
+
+ oldtexibuf = cache->texibuf;
+ cache->texibuf = IMB_allocImBuf(diameter, diameter, 32, imbflag);
+ if (oldtexibuf) {
+ srcx = srcy = 0;
+ destx = (int)painter->lastpaintpos[0] - (int)pos[0];
+ desty = (int)painter->lastpaintpos[1] - (int)pos[1];
+ w = oldtexibuf->x;
+ h = oldtexibuf->y;
+
+ IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h);
+ }
+ else {
+ srcx = srcy = 0;
+ destx = desty = 0;
+ w = h = 0;
+ }
+
+ x1 = destx;
+ y1 = desty;
+ x2 = destx + w;
+ y2 = desty + h;
+
+ /* blend existing texture in new position */
+ if ((x1 < x2) && (y1 < y2))
+ brush_painter_2d_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos);
+
+ if (oldtexibuf)
+ IMB_freeImBuf(oldtexibuf);
+
+ /* sample texture in new areas */
+ if ((0 < x1) && (0 < ibuf->y))
+ brush_painter_2d_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos);
+ if ((x2 < ibuf->x) && (0 < ibuf->y))
+ brush_painter_2d_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos);
+ if ((x1 < x2) && (0 < y1))
+ brush_painter_2d_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos);
+ if ((x1 < x2) && (y2 < ibuf->y))
+ brush_painter_2d_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos);
+}
+
+static void brush_painter_2d_refresh_cache(BrushPainter *painter, const float pos[2], int use_color_correction)
+{
+ const Scene *scene = painter->scene;
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+ Brush *brush = painter->brush;
+ BrushPainterCache *cache = &painter->cache;
+ MTex *mtex = &brush->mtex;
+ int size;
+ short flt;
+ const int diameter = 2 * BKE_brush_size_get(scene, brush);
+ const float alpha = BKE_brush_alpha_get(scene, brush);
+ const bool do_tiled = ELEM(brush->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_3D);
+ float rotation = -mtex->rot;
+
+ if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
+ rotation += ups->brush_rotation;
+ }
+
+ if (diameter != cache->lastsize ||
+ alpha != cache->lastalpha ||
+ brush->jitter != cache->lastjitter ||
+ rotation != cache->last_rotation)
+ {
+ if (cache->ibuf) {
+ IMB_freeImBuf(cache->ibuf);
+ cache->ibuf = NULL;
+ }
+ if (cache->maskibuf) {
+ IMB_freeImBuf(cache->maskibuf);
+ cache->maskibuf = NULL;
+ }
+
+ flt = cache->flt;
+ size = (cache->size) ? cache->size : diameter;
+
+ if (do_tiled) {
+ BKE_brush_imbuf_new(scene, brush, flt, 3, size, &cache->maskibuf, use_color_correction);
+ brush_painter_2d_tiled_tex_partial_update(painter, pos);
+ }
+ else
+ BKE_brush_imbuf_new(scene, brush, flt, 2, size, &cache->ibuf, use_color_correction);
+
+ cache->lastsize = diameter;
+ cache->lastalpha = alpha;
+ cache->lastjitter = brush->jitter;
+ cache->last_rotation = rotation;
+ }
+ else if (do_tiled && mtex && mtex->tex) {
+ int dx = (int)painter->lastpaintpos[0] - (int)pos[0];
+ int dy = (int)painter->lastpaintpos[1] - (int)pos[1];
+
+ if ((dx != 0) || (dy != 0))
+ brush_painter_2d_tiled_tex_partial_update(painter, pos);
+ }
+}
+
+/* keep these functions in sync */
+static void paint_2d_ibuf_rgb_get(ImBuf *ibuf, int x, int y, const short is_torus, float r_rgb[3])
+{
+ 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) {
+ float *rrgbf = ibuf->rect_float + (ibuf->x * y + x) * 4;
+ IMAPAINT_FLOAT_RGB_COPY(r_rgb, rrgbf);
+ }
+ else {
+ char *rrgb = (char *)ibuf->rect + (ibuf->x * y + x) * 4;
+ IMAPAINT_CHAR_RGB_TO_FLOAT(r_rgb, rrgb);
+ }
+}
+static void paint_2d_ibuf_rgb_set(ImBuf *ibuf, int x, int y, const short is_torus, const float rgb[3])
+{
+ 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) {
+ float *rrgbf = ibuf->rect_float + (ibuf->x * y + x) * 4;
+ IMAPAINT_FLOAT_RGB_COPY(rrgbf, rgb);
+ }
+ else {
+ char *rrgb = (char *)ibuf->rect + (ibuf->x * y + x) * 4;
+ IMAPAINT_FLOAT_RGB_TO_CHAR(rrgb, rgb);
+ }
+}
+
+static int paint_2d_ibuf_add_if(ImBuf *ibuf, unsigned int x, unsigned int y, float *outrgb, short torus)
+{
+ float inrgb[3];
+
+ // 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);
+ }
+
+ outrgb[0] += inrgb[0];
+ outrgb[1] += inrgb[1];
+ outrgb[2] += inrgb[2];
+
+ return 1;
+}
+
+static void paint_2d_lift_soften(ImBuf *ibuf, ImBuf *ibufb, int *pos, const short is_torus)
+{
+ int x, y, count, xi, yi, xo, yo;
+ int out_off[2], in_off[2], dim[2];
+ float outrgb[3];
+
+ dim[0] = ibufb->x;
+ dim[1] = ibufb->y;
+ in_off[0] = pos[0];
+ in_off[1] = pos[1];
+ out_off[0] = out_off[1] = 0;
+
+ if (!is_torus) {
+ IMB_rectclip(ibuf, ibufb, &in_off[0], &in_off[1], &out_off[0],
+ &out_off[1], &dim[0], &dim[1]);
+
+ if ((dim[0] == 0) || (dim[1] == 0))
+ return;
+ }
+
+ for (y = 0; y < dim[1]; y++) {
+ for (x = 0; x < dim[0]; x++) {
+ /* get input pixel */
+ xi = in_off[0] + x;
+ yi = in_off[1] + y;
+
+ count = 1;
+ paint_2d_ibuf_rgb_get(ibuf, xi, yi, is_torus, outrgb);
+
+ count += paint_2d_ibuf_add_if(ibuf, xi - 1, yi - 1, outrgb, is_torus);
+ count += paint_2d_ibuf_add_if(ibuf, xi - 1, yi, outrgb, is_torus);
+ count += paint_2d_ibuf_add_if(ibuf, xi - 1, yi + 1, outrgb, is_torus);
+
+ count += paint_2d_ibuf_add_if(ibuf, xi, yi - 1, outrgb, is_torus);
+ count += paint_2d_ibuf_add_if(ibuf, xi, yi + 1, outrgb, is_torus);
+
+ count += paint_2d_ibuf_add_if(ibuf, xi + 1, yi - 1, outrgb, is_torus);
+ count += paint_2d_ibuf_add_if(ibuf, xi + 1, yi, outrgb, is_torus);
+ count += paint_2d_ibuf_add_if(ibuf, xi + 1, yi + 1, outrgb, is_torus);
+
+ mul_v3_fl(outrgb, 1.0f / (float)count);
+
+ /* write into brush buffer */
+ xo = out_off[0] + x;
+ yo = out_off[1] + y;
+ paint_2d_ibuf_rgb_set(ibufb, xo, yo, 0, outrgb);
+ }
+ }
+}
+
+static void paint_2d_set_region(ImagePaintRegion *region, int destx, int desty, int srcx, int srcy, int width, int height)
+{
+ region->destx = destx;
+ region->desty = desty;
+ region->srcx = srcx;
+ region->srcy = srcy;
+ region->width = width;
+ region->height = height;
+}
+
+static int paint_2d_torus_split_region(ImagePaintRegion region[4], ImBuf *dbuf, ImBuf *sbuf)
+{
+ int destx = region->destx;
+ int desty = region->desty;
+ int srcx = region->srcx;
+ int srcy = region->srcy;
+ int width = region->width;
+ int height = region->height;
+ 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;
+
+ /* clip width of blending area to destination imbuf, to avoid writing the
+ * same pixel twice */
+ origw = w = (width > dbuf->x) ? dbuf->x : width;
+ origh = h = (height > dbuf->y) ? dbuf->y : height;
+
+ /* clip within image */
+ IMB_rectclip(dbuf, sbuf, &destx, &desty, &srcx, &srcy, &w, &h);
+ paint_2d_set_region(&region[tot++], destx, desty, srcx, srcy, w, h);
+
+ /* do 3 other rects if needed */
+ if (w < origw)
+ paint_2d_set_region(&region[tot++], (destx + w) % dbuf->x, desty, (srcx + w) % sbuf->x, srcy, origw - w, h);
+ if (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))
+ 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)
+{
+ 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);
+
+ for (a = 0; a < tot; a++)
+ IMB_rectblend(ibufb, ibuf, region[a].destx, region[a].desty,
+ region[a].srcx, region[a].srcy,
+ region[a].width, region[a].height, IMB_BLEND_COPY_RGB);
+}
+
+static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos)
+{
+ /* note: allocImbuf returns zero'd memory, so regions outside image will
+ * have zero alpha, and hence not be blended onto the image */
+ int w = ibufb->x, h = ibufb->y, destx = 0, desty = 0, srcx = pos[0], srcy = pos[1];
+ ImBuf *clonebuf = IMB_allocImBuf(w, h, ibufb->planes, ibufb->flags);
+
+ IMB_rectclip(clonebuf, ibuf, &destx, &desty, &srcx, &srcy, &w, &h);
+ IMB_rectblend(clonebuf, ibuf, destx, desty, srcx, srcy, w, h,
+ IMB_BLEND_COPY_RGB);
+ IMB_rectblend(clonebuf, ibufb, destx, desty, destx, desty, w, h,
+ IMB_BLEND_COPY_ALPHA);
+
+ return clonebuf;
+}
+
+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);
+}
+
+static int paint_2d_op(void *state, ImBuf *ibufb, const float lastpos[2], const float pos[2])
+{
+ ImagePaintState *s = ((ImagePaintState *)state);
+ ImBuf *clonebuf = NULL, *frombuf;
+ ImagePaintRegion region[4];
+ short torus = s->brush->flag & BRUSH_TORUS;
+ short blend = s->blend;
+ float *offset = s->brush->clone.offset;
+ float liftpos[2];
+ int bpos[2], blastpos[2], bliftpos[2];
+ int a, tot;
+
+ paint_2d_convert_brushco(ibufb, pos, bpos);
+
+ /* lift from canvas */
+ if (s->tool == PAINT_TOOL_SOFTEN) {
+ paint_2d_lift_soften(s->canvas, ibufb, bpos, torus);
+ }
+ 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);
+ }
+ else if (s->tool == PAINT_TOOL_CLONE && s->clonecanvas) {
+ liftpos[0] = pos[0] - offset[0] * s->canvas->x;
+ liftpos[1] = pos[1] - offset[1] * s->canvas->y;
+
+ paint_2d_convert_brushco(ibufb, liftpos, bliftpos);
+ clonebuf = paint_2d_lift_clone(s->clonecanvas, ibufb, bliftpos);
+ }
+
+ frombuf = (clonebuf) ? clonebuf : ibufb;
+
+ if (torus) {
+ 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);
+ }
+ else {
+ paint_2d_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
+ tot = 1;
+ }
+
+ /* blend into canvas */
+ for (a = 0; a < tot; a++) {
+ imapaint_dirty_region(s->image, s->canvas,
+ region[a].destx, region[a].desty,
+ region[a].width, region[a].height);
+
+ IMB_rectblend(s->canvas, frombuf,
+ region[a].destx, region[a].desty,
+ region[a].srcx, region[a].srcy,
+ region[a].width, region[a].height, blend);
+ }
+
+ if (clonebuf) IMB_freeImBuf(clonebuf);
+
+ return 1;
+}
+
+
+static int paint_2d_canvas_set(ImagePaintState *s, Image *ima)
+{
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL);
+
+ /* verify that we can paint and set canvas */
+ if (ima == NULL) {
+ return 0;
+ }
+ else if (ima->packedfile && ima->rr) {
+ s->warnpackedfile = ima->id.name + 2;
+ return 0;
+ }
+ else if (ibuf && ibuf->channels != 4) {
+ s->warnmultifile = ima->id.name + 2;
+ return 0;
+ }
+ else if (!ibuf || !(ibuf->rect || ibuf->rect_float))
+ return 0;
+
+ s->image = ima;
+ s->canvas = ibuf;
+
+ /* set clone canvas */
+ if (s->tool == PAINT_TOOL_CLONE) {
+ ima = s->brush->clone.image;
+ ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL);
+
+ if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_release_ibuf(s->image, s->canvas, NULL);
+ return 0;
+ }
+
+ s->clonecanvas = ibuf;
+
+ /* temporarily add float rect for cloning */
+ if (s->canvas->rect_float && !s->clonecanvas->rect_float) {
+ IMB_float_from_rect(s->clonecanvas);
+ }
+ else if (!s->canvas->rect_float && !s->clonecanvas->rect)
+ IMB_rect_from_float(s->clonecanvas);
+ }
+
+ return 1;
+}
+
+static void paint_2d_canvas_free(ImagePaintState *s)
+{
+ BKE_image_release_ibuf(s->image, s->canvas, NULL);
+ BKE_image_release_ibuf(s->brush->clone.image, s->clonecanvas, NULL);
+}
+
+int paint_2d_stroke(void *ps, const int prev_mval[2], const int mval[2], int eraser)
+{
+ float newuv[2], olduv[2];
+ int redraw = 0;
+ ImagePaintState *s = ps;
+ BrushPainter *painter = s->painter;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(s->image, s->sima ? &s->sima->iuser : NULL, NULL);
+ const bool is_data = (ibuf && ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA);
+
+ if (!ibuf)
+ return 0;
+
+ s->blend = s->brush->blend;
+ if (eraser)
+ s->blend = IMB_BLEND_ERASE_ALPHA;
+
+ UI_view2d_region_to_view(s->v2d, mval[0], mval[1], &newuv[0], &newuv[1]);
+ UI_view2d_region_to_view(s->v2d, prev_mval[0], prev_mval[1], &olduv[0], &olduv[1]);
+
+ newuv[0] *= ibuf->x;
+ newuv[1] *= ibuf->y;
+
+ olduv[0] *= ibuf->x;
+ olduv[1] *= ibuf->y;
+
+ if (painter->firsttouch) {
+ /* paint exactly once on first touch */
+ painter->startpaintpos[0] = newuv[0];
+ painter->startpaintpos[1] = newuv[1];
+
+ painter->firsttouch = 0;
+ copy_v2_v2(painter->lastpaintpos, newuv);
+ }
+ else {
+ copy_v2_v2(painter->lastpaintpos, olduv);
+ }
+ /* OCIO_TODO: float buffers are now always linear, so always use color correction
+ * this should probably be changed when texture painting color space is supported
+ */
+ brush_painter_2d_require_imbuf(painter, ((ibuf->rect_float) ? 1 : 0), 0, 0);
+
+ if (painter->cache.enabled)
+ brush_painter_2d_refresh_cache(painter, newuv, is_data == false);
+
+ if (paint_2d_op(s, painter->cache.ibuf, olduv, newuv)) {
+ imapaint_image_update(s->sima, s->image, ibuf, false);
+ BKE_image_release_ibuf(s->image, ibuf, NULL);
+ redraw |= 1;
+ }
+ else {
+ BKE_image_release_ibuf(s->image, ibuf, NULL);
+ }
+
+ if (redraw)
+ imapaint_clear_partial_redraw();
+
+ return redraw;
+}
+
+void *paint_2d_new_stroke(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *settings = scene->toolsettings;
+ Brush *brush = paint_brush(&settings->imapaint.paint);
+
+ ImagePaintState *s = MEM_callocN(sizeof(ImagePaintState), "ImagePaintState");
+
+ s->sima = CTX_wm_space_image(C);
+ s->v2d = &CTX_wm_region(C)->v2d;
+ s->scene = scene;
+ s->screen = CTX_wm_screen(C);
+
+ s->brush = brush;
+ s->tool = brush->imagepaint_tool;
+ s->blend = brush->blend;
+
+ s->image = s->sima->image;
+
+ if (!paint_2d_canvas_set(s, s->image)) {
+ if (s->warnmultifile)
+ BKE_report(op->reports, RPT_WARNING, "Image requires 4 color channels to paint");
+ if (s->warnpackedfile)
+ BKE_report(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted");
+
+ MEM_freeN(s);
+ return NULL;
+ }
+
+ paint_brush_init_tex(s->brush);
+
+ /* create painter */
+ s->painter = brush_painter_2d_new(scene, s->brush);
+
+ return s;
+}
+
+void paint_2d_redraw (const bContext *C, void *ps, int final)
+{
+ ImagePaintState *s = ps;
+
+ if (final) {
+ if (s->image && !(s->sima && s->sima->lock))
+ GPU_free_image(s->image);
+
+ /* compositor listener deals with updating */
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, s->image);
+ }
+ else {
+ if (!s->sima || !s->sima->lock)
+ ED_region_tag_redraw(CTX_wm_region(C));
+ else
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, s->image);
+ }
+}
+
+void paint_2d_stroke_done(void *ps)
+{
+ ImagePaintState *s = ps;
+
+ paint_2d_canvas_free(s);
+ brush_painter_2d_free(s->painter);
+ paint_brush_exit_tex(s->brush);
+
+ MEM_freeN(s);
+}
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
new file mode 100644
index 00000000000..7a0f7b817b3
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -0,0 +1,4465 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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: some of this file.
+ *
+ * Contributor(s): Jens Ole Wund (bjornmose), Campbell Barton (ideasman42)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/sculpt_paint/paint_image_proj.c
+ * \ingroup edsculpt
+ * \brief Functions to paint images in 2D and 3D.
+ */
+
+#include <float.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#ifdef WIN32
+# include "BLI_winstuff.h"
+#endif
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_linklist.h"
+#include "BLI_memarena.h"
+#include "BLI_threads.h"
+#include "BLI_utildefines.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_camera.h"
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_idprop.h"
+#include "BKE_brush.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_report.h"
+#include "BKE_scene.h"
+#include "BKE_colortools.h"
+
+#include "BKE_tessmesh.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_view2d.h"
+
+#include "ED_image.h"
+#include "ED_screen.h"
+#include "ED_sculpt.h"
+#include "ED_uvedit.h"
+#include "ED_view3d.h"
+#include "ED_mesh.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "GPU_draw.h"
+
+#include "IMB_colormanagement.h"
+
+#include "paint_intern.h"
+
+/* Defines and Structs */
+/* FTOCHAR as inline function */
+BLI_INLINE unsigned char f_to_char(const float val)
+{
+ return FTOCHAR(val);
+}
+
+#define IMAPAINT_FLOAT_RGBA_TO_CHAR(c, f) { \
+ (c)[0] = f_to_char((f)[0]); \
+ (c)[1] = f_to_char((f)[1]); \
+ (c)[2] = f_to_char((f)[2]); \
+ (c)[3] = f_to_char((f)[3]); \
+} (void)0
+
+#define IMAPAINT_CHAR_RGBA_TO_FLOAT(f, c) { \
+ (f)[0] = IMAPAINT_CHAR_TO_FLOAT((c)[0]); \
+ (f)[1] = IMAPAINT_CHAR_TO_FLOAT((c)[1]); \
+ (f)[2] = IMAPAINT_CHAR_TO_FLOAT((c)[2]); \
+ (f)[3] = IMAPAINT_CHAR_TO_FLOAT((c)[3]); \
+} (void)0
+
+#define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { \
+ (c)[0] = f_to_char((f)[0]); \
+ (c)[1] = f_to_char((f)[1]); \
+ (c)[2] = f_to_char((f)[2]); \
+} (void)0
+
+/* ProjectionPaint defines */
+
+/* approx the number of buckets to have under the brush,
+ * used with the brush size to set the ps->buckets_x and ps->buckets_y value.
+ *
+ * When 3 - a brush should have ~9 buckets under it at once
+ * ...this helps for threading while painting as well as
+ * avoiding initializing pixels that wont touch the brush */
+#define PROJ_BUCKET_BRUSH_DIV 4
+
+#define PROJ_BUCKET_RECT_MIN 4
+#define PROJ_BUCKET_RECT_MAX 256
+
+#define PROJ_BOUNDBOX_DIV 8
+#define PROJ_BOUNDBOX_SQUARED (PROJ_BOUNDBOX_DIV * PROJ_BOUNDBOX_DIV)
+
+//#define PROJ_DEBUG_PAINT 1
+//#define PROJ_DEBUG_NOSEAMBLEED 1
+//#define PROJ_DEBUG_PRINT_CLIP 1
+#define PROJ_DEBUG_WINCLIP 1
+
+/* 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)
+
+#define PROJ_SRC_VIEW 1
+#define PROJ_SRC_IMAGE_CAM 2
+#define PROJ_SRC_IMAGE_VIEW 3
+
+#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)
+
+/* used for testing doubles, if a point is on a line etc */
+#define PROJ_GEOM_TOLERANCE 0.00075f
+
+/* vert flags */
+#define PROJ_VERT_CULL 1
+
+/* This is mainly a convenience struct used so we can keep an array of images we use
+ * Thir imbufs, etc, in 1 array, When using threads this array is copied for each thread
+ * because 'partRedrawRect' and 'touch' values would not be thread safe */
+typedef struct ProjPaintImage {
+ Image *ima;
+ ImBuf *ibuf;
+ ImagePaintPartialRedraw *partRedrawRect;
+ void **undoRect; /* only used to build undo tiles after painting */
+ int touch;
+} ProjPaintImage;
+
+/* Main projection painting struct passed to all projection painting functions */
+typedef struct ProjPaintState {
+ View3D *v3d;
+ RegionView3D *rv3d;
+ ARegion *ar;
+ Scene *scene;
+ int source; /* PROJ_SRC_**** */
+
+ Brush *brush;
+ short tool, blend, mode;
+ int orig_brush_size;
+ Object *ob;
+ /* 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;
+
+ /* projection painting only */
+ MemArena *arena_mt[BLENDER_MAX_THREADS]; /* for multithreading, the first item is sometimes used for non threaded cases too */
+ LinkNode **bucketRect; /* screen sized 2D array, each pixel has a linked list of ProjPixel's */
+ 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*/
+ 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 */
+ float screen_height;
+ int winx, winy; /* from the carea or from the projection render */
+
+ /* options for projection painting */
+ int do_layer_clone;
+ int do_layer_stencil;
+ int do_layer_stencil_inv;
+
+ short do_occlude; /* Use raytraced occlusion? - ortherwise will paint right through to the back*/
+ short do_backfacecull; /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */
+ short do_mask_normal; /* mask out pixels based on their normals */
+ short do_new_shading_nodes; /* cache BKE_scene_use_new_shading_nodes value */
+ float normal_angle; /* what angle to mask at*/
+ float normal_angle_inner;
+ float normal_angle_range; /* difference between normal_angle and normal_angle_inner, for easy access */
+
+ short is_ortho;
+ bool do_masking; /* use masking during painting. Some operations such as airbrush may disable */
+ short is_texbrush; /* only to avoid running */
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+ float seam_bleed_px;
+#endif
+ /* clone vars */
+ float cloneOffset[2];
+
+ float projectMat[4][4]; /* Projection matrix, use for getting screen coords */
+ 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;
+
+ /* reproject vars */
+ Image *reproject_image;
+ ImBuf *reproject_ibuf;
+
+
+ /* threads */
+ int thread_tot;
+ int bucketMin[2];
+ int bucketMax[2];
+ int context_bucket_x, context_bucket_y; /* must lock threads while accessing these */
+} ProjPaintState;
+
+typedef union pixelPointer {
+ float *f_pt; /* float buffer */
+ unsigned int *uint_pt; /* 2 ways to access a char buffer */
+ unsigned char *ch_pt;
+} PixelPointer;
+
+typedef union pixelStore {
+ unsigned char ch[4];
+ unsigned int uint;
+ float f[4];
+} PixelStore;
+
+typedef struct ProjPixel {
+ float projCoSS[2]; /* the floating point screen projection of this pixel */
+ float worldCoSS[3];
+ /* 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_max */
+ unsigned short mask_max;
+
+ /* for various reasons we may want to mask out painting onto this pixel */
+ unsigned short mask;
+
+ short x_px, y_px;
+
+ PixelStore origColor;
+ PixelStore newColor;
+ PixelPointer pixel;
+
+ short image_index; /* if anyone wants to paint onto more then 32768 images they can bite me */
+ unsigned char bb_cell_index;
+} ProjPixel;
+
+typedef struct ProjPixelClone {
+ struct ProjPixel __pp;
+ PixelStore clonepx;
+} ProjPixelClone;
+
+/* blur, store surrounding colors */
+#define PROJ_PIXEL_SOFTEN_TOT 4
+/* blur picking offset (in screenspace) */
+#define PROJ_PIXEL_SOFTEN_OFS_PX 1.0f
+
+static const float proj_pixel_soften_v2[PROJ_PIXEL_SOFTEN_TOT][2] = {
+ {-PROJ_PIXEL_SOFTEN_OFS_PX, 0.0f},
+ { 0.0f, -PROJ_PIXEL_SOFTEN_OFS_PX},
+ { 0.0f, PROJ_PIXEL_SOFTEN_OFS_PX},
+ { PROJ_PIXEL_SOFTEN_OFS_PX, 0.0f},
+};
+
+/* Finish projection painting structs */
+
+static Image *project_paint_face_image(const ProjPaintState *ps, MTFace *dm_mtface, int face_index)
+{
+ Image *ima;
+
+ if (ps->do_new_shading_nodes) { /* cached BKE_scene_use_new_shading_nodes result */
+ MFace *mf = ps->dm_mface + face_index;
+ ED_object_get_active_image(ps->ob, mf->mat_nr + 1, &ima, NULL, NULL);
+ }
+ else {
+ ima = dm_mtface[face_index].tpage;
+ }
+
+ return ima;
+}
+
+/* fast projection bucket array lookup, use the safe version for bound checking */
+static int project_bucket_offset(const ProjPaintState *ps, const float projCoSS[2])
+{
+ /* If we were not dealing with screenspace 2D coords we could simple do...
+ * ps->bucketRect[x + (y*ps->buckets_y)] */
+
+ /* please explain?
+ * projCoSS[0] - ps->screenMin[0] : zero origin
+ * ... / ps->screen_width : range from 0.0 to 1.0
+ * ... * ps->buckets_x : use as a bucket index
+ *
+ * Second multiplication does similar but for vertical offset
+ */
+ return ( (int)(((projCoSS[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x)) +
+ (((int)(((projCoSS[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y)) * ps->buckets_x);
+}
+
+static int project_bucket_offset_safe(const ProjPaintState *ps, const float projCoSS[2])
+{
+ int bucket_index = project_bucket_offset(ps, projCoSS);
+
+ if (bucket_index < 0 || bucket_index >= ps->buckets_x * ps->buckets_y) {
+ return -1;
+ }
+ else {
+ return bucket_index;
+ }
+}
+
+/* still use 2D X,Y space but this works for verts transformed by a perspective matrix, using their 4th component as a weight */
+static void barycentric_weights_v2_persp(const float v1[4], const float v2[4], const float v3[4], const float co[2], float w[3])
+{
+ float wtot_inv, 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];
+ wtot = w[0] + w[1] + w[2];
+
+ if (wtot != 0.0f) {
+ wtot_inv = 1.0f / wtot;
+
+ w[0] = w[0] * wtot_inv;
+ w[1] = w[1] * wtot_inv;
+ w[2] = w[2] * wtot_inv;
+ }
+ else /* dummy values for zero area face */
+ w[0] = w[1] = w[2] = 1.0f / 3.0f;
+}
+
+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])
+{
+ float wtot_inv, wtot;
+ float w_tmp[3];
+
+ barycentric_weights_v2_persp(v1, v2, v3, pt, w);
+ /* for the depth we need the weights to match what
+ * barycentric_weights_v2 would return, in this case its easiest just to
+ * undo the 4th axis division and make it unit-sum
+ *
+ * don't call barycentric_weights_v2() because our callers expect 'w'
+ * to be weighted from the perspective */
+ w_tmp[0] = w[0] * v1[3];
+ w_tmp[1] = w[1] * v2[3];
+ w_tmp[2] = w[2] * v3[3];
+
+ wtot = w_tmp[0] + w_tmp[1] + w_tmp[2];
+
+ if (wtot != 0.0f) {
+ wtot_inv = 1.0f / wtot;
+
+ w_tmp[0] = w_tmp[0] * wtot_inv;
+ w_tmp[1] = w_tmp[1] * wtot_inv;
+ w_tmp[2] = w_tmp[2] * wtot_inv;
+ }
+ else /* dummy values for zero area face */
+ w_tmp[0] = w_tmp[1] = w_tmp[2] = 1.0f / 3.0f;
+ /* done mimicing barycentric_weights_v2() */
+
+ return (v1[2] * w_tmp[0]) + (v2[2] * w_tmp[1]) + (v3[2] * w_tmp[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)
+{
+ LinkNode *node;
+ float w_tmp[3];
+ float *v1, *v2, *v3, *v4;
+ int bucket_index;
+ int face_index;
+ int best_side = -1;
+ int best_face_index = -1;
+ float z_depth_best = FLT_MAX, z_depth;
+ MFace *mf;
+
+ bucket_index = project_bucket_offset_safe(ps, pt);
+ if (bucket_index == -1)
+ return -1;
+
+
+
+ /* 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 (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
+ face_index = GET_INT_FROM_POINTER(node->link);
+ mf = ps->dm_mface + face_index;
+
+ 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 (z_depth < z_depth_best) {
+ best_face_index = face_index;
+ best_side = 0;
+ 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 */
+}
+
+/* Converts a uv coord into a pixel location wrapping if the uv is outside 0-1 range */
+static void uvco_to_wrapped_pxco(float uv[2], int ibuf_x, int ibuf_y, float *x, float *y)
+{
+ /* use */
+ *x = (float)fmodf(uv[0], 1.0f);
+ *y = (float)fmodf(uv[1], 1.0f);
+
+ if (*x < 0.0f) *x += 1.0f;
+ if (*y < 0.0f) *y += 1.0f;
+
+ *x = *x * ibuf_x - 0.5f;
+ *y = *y * ibuf_y - 0.5f;
+}
+
+/* Set the top-most face color that the screen space coord 'pt' touches (or return 0 if none touch) */
+static int project_paint_PickColor(const ProjPaintState *ps, const float pt[2],
+ float *rgba_fp, unsigned char *rgba, const int interp)
+{
+ float w[3], uv[2];
+ int side;
+ int face_index;
+ MTFace *tf;
+ Image *ima;
+ ImBuf *ibuf;
+ int xi, yi;
+
+
+ face_index = project_paint_PickFace(ps, pt, w, &side);
+
+ if (face_index == -1)
+ return 0;
+
+ tf = ps->dm_mtface + face_index;
+
+ 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);
+ }
+
+ ima = project_paint_face_image(ps, ps->dm_mtface, face_index);
+ ibuf = ima->ibufs.first; /* we must have got the imbuf before getting here */
+ if (!ibuf) return 0;
+
+ if (interp) {
+ float x, y;
+ uvco_to_wrapped_pxco(uv, ibuf->x, ibuf->y, &x, &y);
+
+ if (ibuf->rect_float) {
+ if (rgba_fp) {
+ bilinear_interpolation_color_wrap(ibuf, NULL, rgba_fp, x, y);
+ }
+ else {
+ float rgba_tmp_f[4];
+ bilinear_interpolation_color_wrap(ibuf, NULL, rgba_tmp_f, x, y);
+ IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, rgba_tmp_f);
+ }
+ }
+ else {
+ if (rgba) {
+ bilinear_interpolation_color_wrap(ibuf, rgba, NULL, x, y);
+ }
+ else {
+ unsigned char rgba_tmp[4];
+ bilinear_interpolation_color_wrap(ibuf, rgba_tmp, NULL, x, y);
+ IMAPAINT_CHAR_RGBA_TO_FLOAT(rgba_fp, rgba_tmp);
+ }
+ }
+ }
+ else {
+ //xi = (int)((uv[0]*ibuf->x) + 0.5f);
+ //yi = (int)((uv[1]*ibuf->y) + 0.5f);
+ //if (xi < 0 || xi >= ibuf->x || yi < 0 || yi >= ibuf->y) return 0;
+
+ /* wrap */
+ xi = ((int)(uv[0] * ibuf->x)) % ibuf->x;
+ if (xi < 0) xi += ibuf->x;
+ yi = ((int)(uv[1] * ibuf->y)) % ibuf->y;
+ if (yi < 0) yi += ibuf->y;
+
+
+ if (rgba) {
+ if (ibuf->rect_float) {
+ float *rgba_tmp_fp = ibuf->rect_float + (xi + yi * ibuf->x * 4);
+ IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, rgba_tmp_fp);
+ }
+ else {
+ *((unsigned int *)rgba) = *(unsigned int *)(((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4));
+ }
+ }
+
+ if (rgba_fp) {
+ if (ibuf->rect_float) {
+ copy_v4_v4(rgba_fp, (ibuf->rect_float + ((xi + yi * ibuf->x) * 4)));
+ }
+ else {
+ char *tmp_ch = ((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4);
+ IMAPAINT_CHAR_RGBA_TO_FLOAT(rgba_fp, tmp_ch);
+ }
+ }
+ }
+ 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(float pt[3], float v1[4], float v2[4], float v3[4], float w[3], int is_ortho)
+{
+ /* if all are behind us, return false */
+ if (v1[2] > pt[2] && v2[2] > pt[2] && v3[2] > pt[2])
+ return 0;
+
+ /* do a 2D point in try intersection */
+ if (!isect_point_tri_v2(pt, v1, v2, v3))
+ return 0; /* we know there is */
+
+
+ /* From here on we know there IS an intersection */
+ /* if ALL of the verts are infront of us then we know it intersects ? */
+ if (v1[2] < pt[2] && v2[2] < pt[2] && v3[2] < pt[2]) {
+ return 1;
+ }
+ else {
+ /* we intersect? - find the exact depth at the point of intersection */
+ /* Is this point is occluded by another face? */
+ if (is_ortho) {
+ if (VecZDepthOrtho(pt, v1, v2, v3, w) < pt[2]) return 2;
+ }
+ else {
+ if (VecZDepthPersp(pt, v1, v2, v3, w) < pt[2]) return 2;
+ }
+ }
+ return -1;
+}
+
+
+static int project_paint_occlude_ptv_clip(const ProjPaintState *ps, const MFace *mf,
+ float pt[3], float v1[4], float v2[4], float v3[4],
+ const int side)
+{
+ float w[3], wco[3];
+ int ret = project_paint_occlude_ptv(pt, v1, v2, v3, w, ps->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);
+ }
+
+ /* 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);
+
+ if (!ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) {
+ return 1;
+ }
+
+ return -1;
+}
+
+
+/* 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 int project_bucket_point_occluded(const ProjPaintState *ps, LinkNode *bucketFace, const int orig_face, 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;
+
+ /* 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);
+ }
+ 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 */
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/* basic line intersection, could move to math_geom.c, 2 points with a horiz line
+ * 1 for an intersection, 2 if the first point is aligned, 3 if the second point is aligned */
+#define ISECT_TRUE 1
+#define ISECT_TRUE_P1 2
+#define ISECT_TRUE_P2 3
+static int line_isect_y(const float p1[2], const float p2[2], const float y_level, float *x_isect)
+{
+ float y_diff;
+
+ if (y_level == p1[1]) { /* are we touching the first point? - no interpolation needed */
+ *x_isect = p1[0];
+ return ISECT_TRUE_P1;
+ }
+ if (y_level == p2[1]) { /* are we touching the second point? - no interpolation needed */
+ *x_isect = p2[0];
+ return ISECT_TRUE_P2;
+ }
+
+ y_diff = fabsf(p1[1] - p2[1]); /* yuck, horizontal line, we cant do much here */
+
+ if (y_diff < 0.000001f) {
+ *x_isect = (p1[0] + p2[0]) * 0.5f;
+ return ISECT_TRUE;
+ }
+
+ 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]);*/
+ 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]);*/
+ return ISECT_TRUE;
+ }
+ else {
+ return 0;
+ }
+}
+
+static int line_isect_x(const float p1[2], const float p2[2], const float x_level, float *y_isect)
+{
+ float x_diff;
+
+ if (x_level == p1[0]) { /* are we touching the first point? - no interpolation needed */
+ *y_isect = p1[1];
+ return ISECT_TRUE_P1;
+ }
+ if (x_level == p2[0]) { /* are we touching the second point? - no interpolation needed */
+ *y_isect = p2[1];
+ return ISECT_TRUE_P2;
+ }
+
+ x_diff = fabsf(p1[0] - p2[0]); /* yuck, horizontal line, we cant do much here */
+
+ if (x_diff < 0.000001f) { /* yuck, vertical line, we cant do much here */
+ *y_isect = (p1[0] + p2[0]) * 0.5f;
+ return ISECT_TRUE;
+ }
+
+ 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]);*/
+ 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]);*/
+ return ISECT_TRUE;
+ }
+ else {
+ return 0;
+ }
+}
+
+/* simple func use for comparing UV locations to check if there are seams.
+ * Its possible this gives incorrect results, when the UVs for 1 face go into the next
+ * tile, but do not do this for the adjacent face, it could return a false positive.
+ * This is so unlikely that Id not worry about it. */
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+static int cmp_uv(const float vec2a[2], const float vec2b[2])
+{
+ /* if the UV's are not between 0.0 and 1.0 */
+ float xa = (float)fmodf(vec2a[0], 1.0f);
+ float ya = (float)fmodf(vec2a[1], 1.0f);
+
+ float xb = (float)fmodf(vec2b[0], 1.0f);
+ float yb = (float)fmodf(vec2b[1], 1.0f);
+
+ if (xa < 0.0f) xa += 1.0f;
+ if (ya < 0.0f) ya += 1.0f;
+
+ if (xb < 0.0f) xb += 1.0f;
+ if (yb < 0.0f) yb += 1.0f;
+
+ return ((fabsf(xa - xb) < PROJ_GEOM_TOLERANCE) && (fabsf(ya - yb) < PROJ_GEOM_TOLERANCE)) ? 1 : 0;
+}
+#endif
+
+/* set min_px and max_px to the image space bounds of the UV coords
+ * return zero if there is no area in the returned rectangle */
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+static int pixel_bounds_uv(
+ const float uv1[2], const float uv2[2], const float uv3[2], const float uv4[2],
+ rcti *bounds_px,
+ const int ibuf_x, const int ibuf_y,
+ int is_quad
+ )
+{
+ 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);
+
+ bounds_px->xmin = (int)(ibuf_x * min_uv[0]);
+ bounds_px->ymin = (int)(ibuf_y * min_uv[1]);
+
+ bounds_px->xmax = (int)(ibuf_x * max_uv[0]) + 1;
+ bounds_px->ymax = (int)(ibuf_y * max_uv[1]) + 1;
+
+ /*printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]);*/
+
+ /* face uses no UV area when quantized to pixels? */
+ return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1;
+}
+#endif
+
+static int pixel_bounds_array(float (*uv)[2], rcti *bounds_px, const int ibuf_x, const int ibuf_y, int tot)
+{
+ float min_uv[2], max_uv[2]; /* UV bounds */
+
+ if (tot == 0) {
+ return 0;
+ }
+
+ INIT_MINMAX2(min_uv, max_uv);
+
+ while (tot--) {
+ minmax_v2v2_v2(min_uv, max_uv, (*uv));
+ uv++;
+ }
+
+ bounds_px->xmin = (int)(ibuf_x * min_uv[0]);
+ bounds_px->ymin = (int)(ibuf_y * min_uv[1]);
+
+ bounds_px->xmax = (int)(ibuf_x * max_uv[0]) + 1;
+ bounds_px->ymax = (int)(ibuf_y * max_uv[1]) + 1;
+
+ /*printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]);*/
+
+ /* face uses no UV area when quantized to pixels? */
+ return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1;
+}
+
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+
+/* This function returns 1 if this face has a seam along the 2 face-vert indices
+ * 'orig_i1_fidx' and 'orig_i2_fidx' */
+static int 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)
+{
+ 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);
+
+ if (face_index != orig_face) {
+ mf = ps->dm_mface + face_index;
+ /* 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) */
+ if (mf->v1 == i1) i1_fidx = 0;
+ else if (mf->v2 == i1) i1_fidx = 1;
+ else if (mf->v3 == i1) i1_fidx = 2;
+ else if (mf->v4 && mf->v4 == i1) i1_fidx = 3;
+
+ if (mf->v1 == i2) i2_fidx = 0;
+ else if (mf->v2 == i2) i2_fidx = 1;
+ else if (mf->v3 == i2) i2_fidx = 2;
+ else if (mf->v4 && mf->v4 == i2) i2_fidx = 3;
+
+ /* Only need to check if 'i2_fidx' is valid because we know i1_fidx is the same vert on both faces */
+ if (i2_fidx != -1) {
+ Image *tpage = project_paint_face_image(ps, ps->dm_mtface, face_index);
+ Image *orig_tpage = project_paint_face_image(ps, ps->dm_mtface, orig_face);
+
+ /* 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;
+ *orig_fidx = (i1_fidx < i2_fidx) ? i1_fidx : i2_fidx;
+
+ /* 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]) )
+ {
+ // printf("SEAM (NONE)\n");
+ return 0;
+
+ }
+ else {
+ // printf("SEAM (UV GAP)\n");
+ return 1;
+ }
+ }
+ }
+ }
+ // printf("SEAM (NO FACE)\n");
+ *other_face = -1;
+ return 1;
+}
+
+/* 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 int is_quad)
+{
+ 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 ibuf_inv[2];
+
+ ibuf_inv[0] = 1.0f / (float)ibuf_x;
+ ibuf_inv[1] = 1.0f / (float)ibuf_y;
+
+ /* make UV's in pixel space so we can */
+ puv[0][0] = orig_uv[0][0] * ibuf_x;
+ puv[0][1] = orig_uv[0][1] * ibuf_y;
+
+ puv[1][0] = orig_uv[1][0] * ibuf_x;
+ puv[1][1] = orig_uv[1][1] * ibuf_y;
+
+ 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]);
+ 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);
+ }
+
+ /* TODO - angle_normalized_v2v2(...) * (M_PI/180.0f)
+ * This is incorrect. Its already given radians but without it wont work.
+ * need to look into a fix - campbell */
+ if (is_quad) {
+ a1 = shell_angle_to_dist(angle_normalized_v2v2(dir4, dir1) * ((float)M_PI / 180.0f));
+ a2 = shell_angle_to_dist(angle_normalized_v2v2(dir1, dir2) * ((float)M_PI / 180.0f));
+ a3 = shell_angle_to_dist(angle_normalized_v2v2(dir2, dir3) * ((float)M_PI / 180.0f));
+ a4 = shell_angle_to_dist(angle_normalized_v2v2(dir3, dir4) * ((float)M_PI / 180.0f));
+ }
+ else {
+ a1 = shell_angle_to_dist(angle_normalized_v2v2(dir3, dir1) * ((float)M_PI / 180.0f));
+ a2 = shell_angle_to_dist(angle_normalized_v2v2(dir1, dir2) * ((float)M_PI / 180.0f));
+ a3 = shell_angle_to_dist(angle_normalized_v2v2(dir2, dir3) * ((float)M_PI / 180.0f));
+ }
+
+ 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);
+ }
+ 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);
+ }
+}
+
+/*
+ * Be tricky with flags, first 4 bits are PROJ_FACE_SEAM1 to 4, last 4 bits are PROJ_FACE_NOSEAM1 to 4
+ * 1<<i - where i is (0-3)
+ *
+ * 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)
+{
+ int other_face, other_fidx; /* vars for the other face, we also set its flag */
+ int fidx1 = is_quad ? 3 : 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 */
+
+ 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 (other_face != -1)
+ ps->faceSeamFlags[other_face] |= 1 << other_fidx;
+ }
+ else {
+ ps->faceSeamFlags[face_index] |= 16 << fidx1;
+ if (other_face != -1)
+ ps->faceSeamFlags[other_face] |= 16 << other_fidx; /* second 4 bits for disabled */
+ }
+ }
+
+ fidx2 = fidx1;
+ } while (fidx1--);
+}
+#endif // PROJ_DEBUG_NOSEAMBLEED
+
+
+/* Converts a UV location to a 3D screenspace location
+ * Takes a 'uv' and 3 UV coords, and sets the values of pixelScreenCo
+ *
+ * This is used for finding a pixels location in screenspace for painting */
+static void screen_px_from_ortho(
+ float uv[2],
+ float v1co[3], float v2co[3], float v3co[3], /* Screenspace coords */
+ float uv1co[2], float uv2co[2], float uv3co[2],
+ float pixelScreenCo[4],
+ float w[3])
+{
+ barycentric_weights_v2(uv1co, uv2co, uv3co, uv, w);
+ interp_v3_v3v3v3(pixelScreenCo, v1co, v2co, v3co, w);
+}
+
+/* same as screen_px_from_ortho except we need to take into account
+ * the perspective W coord for each vert */
+static void screen_px_from_persp(
+ float uv[2],
+ float v1co[4], float v2co[4], float v3co[4], /* screenspace coords */
+ float uv1co[2], float uv2co[2], float uv3co[2],
+ float pixelScreenCo[4],
+ float w[3])
+{
+
+ float wtot_inv, wtot;
+ barycentric_weights_v2(uv1co, uv2co, uv3co, uv, w);
+
+ /* re-weight from the 4th coord of each screen vert */
+ w[0] *= v1co[3];
+ w[1] *= v2co[3];
+ w[2] *= v3co[3];
+
+ wtot = w[0] + w[1] + w[2];
+
+ if (wtot > 0.0f) {
+ wtot_inv = 1.0f / wtot;
+ w[0] *= wtot_inv;
+ w[1] *= wtot_inv;
+ w[2] *= wtot_inv;
+ }
+ else {
+ w[0] = w[1] = w[2] = 1.0f / 3.0f; /* dummy values for zero area face */
+ }
+ /* done re-weighting */
+
+ interp_v3_v3v3v3(pixelScreenCo, v1co, v2co, v3co, w);
+}
+
+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])
+{
+ float *uvCo1, *uvCo2, *uvCo3;
+ float uv_other[2], x, y;
+
+ 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];
+ }
+
+ interp_v2_v2v2v2(uv_other, uvCo1, uvCo2, uvCo3, (float *)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);
+ }
+ else { /* from char to float */
+ bilinear_interpolation_color_wrap(ibuf_other, rgba_ub, NULL, x, y);
+ }
+
+}
+
+/* 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 float w[3])
+{
+ float mask;
+
+ /* Image Mask */
+ if (ps->do_layer_stencil) {
+ /* another UV maps image is masking this one's */
+ ImBuf *ibuf_other;
+ Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_stencil, face_index);
+ const MTFace *tf_other = ps->dm_mtface_stencil + face_index;
+
+ if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
+ /* 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);
+
+ if (ibuf_other->rect_float) { /* from float to float */
+ mask = ((rgba_f[0] + rgba_f[1] + rgba_f[2]) / 3.0f) * rgba_f[3];
+ }
+ else { /* from char to float */
+ mask = ((rgba_ub[0] + rgba_ub[1] + rgba_ub[2]) / (256 * 3.0f)) * (rgba_ub[3] / 256.0f);
+ }
+
+ BKE_image_release_ibuf(other_tpage, ibuf_other, NULL);
+
+ if (!ps->do_layer_stencil_inv) /* matching the gimps layer mask black/white rules, white==full opacity */
+ mask = (1.0f - mask);
+
+ if (mask == 0.0f) {
+ return 0.0f;
+ }
+ }
+ else {
+ return 0.0f;
+ }
+ }
+ else {
+ mask = 1.0f;
+ }
+
+ /* calculate mask */
+ if (ps->do_mask_normal) {
+ MFace *mf = &ps->dm_mface[face_index];
+ float no[3], angle;
+ if (mf->flag & ME_SMOOTH) {
+ 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;
+ }
+
+ 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];
+ no[2] = w[0] * no1[2] + w[1] * no2[2] + w[2] * no3[2];
+ normalize_v3(no);
+ }
+ else {
+ /* 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);
+#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));
+#endif
+ }
+
+ /* now we can use the normal as a mask */
+ if (ps->is_ortho) {
+ angle = angle_normalized_v3v3((float *)ps->viewDir, no);
+ }
+ else {
+ /* Annoying but for the perspective view we need to get the pixels location in 3D space :/ */
+ float viewDirPersp[3];
+ 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;
+ }
+
+ /* 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);
+
+ angle = angle_normalized_v3v3(viewDirPersp, no);
+ }
+
+ if (angle >= ps->normal_angle) {
+ return 0.0f; /* outsize the normal limit*/
+ }
+ else if (angle > ps->normal_angle_inner) {
+ mask *= (ps->normal_angle - angle) / ps->normal_angle_range;
+ } /* otherwise no mask normal is needed, were within the limit */
+ }
+
+ /* This only works when the opacity dosnt change while painting, stylus pressure messes with this
+ * so don't use it. */
+ // if (ps->is_airbrush == 0) mask *= BKE_brush_alpha_get(ps->brush);
+
+ return mask;
+}
+
+static int project_paint_pixel_sizeof(const short tool)
+{
+ if ((tool == PAINT_TOOL_CLONE) || (tool == PAINT_TOOL_SMEAR)) {
+ return sizeof(ProjPixelClone);
+ }
+ else {
+ return sizeof(ProjPixel);
+ }
+}
+
+
+/* run this function when we know a bucket's, face's pixel can be initialized,
+ * return the ProjPixel which is added to 'ps->bucketRect[bucket_index]' */
+static ProjPixel *project_paint_uvpixel_init(
+ const ProjPaintState *ps,
+ MemArena *arena,
+ const ImBuf *ibuf,
+ short x_px, short y_px,
+ const float mask,
+ const int face_index,
+ const int image_index,
+ const float pixelScreenCo[4],
+ const float world_spaceCo[3],
+ const int side,
+ const float w[3])
+{
+ ProjPixel *projPixel;
+
+ /* wrap pixel location */
+ x_px = x_px % ibuf->x;
+ if (x_px < 0) x_px += ibuf->x;
+ y_px = y_px % ibuf->y;
+ if (y_px < 0) y_px += ibuf->y;
+
+ BLI_assert(ps->pixel_sizeof == project_paint_pixel_sizeof(ps->tool));
+ projPixel = (ProjPixel *)BLI_memarena_alloc(arena, ps->pixel_sizeof);
+ //memset(projPixel, 0, size);
+
+ if (ibuf->rect_float) {
+ projPixel->pixel.f_pt = ibuf->rect_float + ((x_px + y_px * ibuf->x) * 4);
+ projPixel->origColor.f[0] = projPixel->newColor.f[0] = projPixel->pixel.f_pt[0];
+ projPixel->origColor.f[1] = projPixel->newColor.f[1] = projPixel->pixel.f_pt[1];
+ projPixel->origColor.f[2] = projPixel->newColor.f[2] = projPixel->pixel.f_pt[2];
+ projPixel->origColor.f[3] = projPixel->newColor.f[3] = projPixel->pixel.f_pt[3];
+ }
+ else {
+ projPixel->pixel.ch_pt = ((unsigned char *)ibuf->rect + ((x_px + y_px * ibuf->x) * 4));
+ projPixel->origColor.uint = projPixel->newColor.uint = *projPixel->pixel.uint_pt;
+ }
+
+ /* screenspace unclamped, we could keep its z and w values but don't need them at the moment */
+ if (ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) {
+ copy_v3_v3(projPixel->worldCoSS, world_spaceCo);
+ }
+
+ copy_v2_v2(projPixel->projCoSS, pixelScreenCo);
+
+ projPixel->x_px = x_px;
+ projPixel->y_px = y_px;
+
+ projPixel->mask = (unsigned short)(mask * 65535);
+ projPixel->mask_max = 0;
+
+ /* which bounding box cell are we in?, needed for undo */
+ projPixel->bb_cell_index = ((int)(((float)x_px / (float)ibuf->x) * PROJ_BOUNDBOX_DIV)) +
+ ((int)(((float)y_px / (float)ibuf->y) * PROJ_BOUNDBOX_DIV)) * PROJ_BOUNDBOX_DIV;
+
+ /* done with view3d_project_float inline */
+ if (ps->tool == PAINT_TOOL_CLONE) {
+ if (ps->dm_mtface_clone) {
+ ImBuf *ibuf_other;
+ Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_clone, face_index);
+ const MTFace *tf_other = ps->dm_mtface_clone + face_index;
+
+ if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
+ /* 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);
+ }
+ 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);
+ srgb_to_linearrgb_uchar4(rgba, rgba_ub);
+ straight_to_premul_v4_v4(((ProjPixelClone *)projPixel)->clonepx.f, rgba);
+ }
+ }
+ else {
+ if (ibuf_other->rect_float) { /* float to char */
+ float rgba[4];
+ project_face_pixel(tf_other, ibuf_other, w, side, NULL, rgba);
+ premul_to_straight_v4(rgba);
+ linearrgb_to_srgb_uchar3(((ProjPixelClone *)projPixel)->clonepx.ch, rgba);
+ }
+ else { /* char to char */
+ project_face_pixel(tf_other, ibuf_other, w, side, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL);
+ }
+ }
+
+ BKE_image_release_ibuf(other_tpage, ibuf_other, NULL);
+ }
+ else {
+ if (ibuf->rect_float) {
+ ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0;
+ }
+ else {
+ ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0;
+ }
+ }
+
+ }
+ else {
+ float co[2];
+ sub_v2_v2v2(co, projPixel->projCoSS, (float *)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(...) */
+ if (ibuf->rect_float) {
+ if (!project_paint_PickColor(ps, co, ((ProjPixelClone *)projPixel)->clonepx.f, NULL, 1)) {
+ ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0; /* zero alpha - ignore */
+ }
+ }
+ else {
+ if (!project_paint_PickColor(ps, co, NULL, ((ProjPixelClone *)projPixel)->clonepx.ch, 1)) {
+ ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0; /* zero alpha - ignore */
+ }
+ }
+ }
+ }
+
+#ifdef PROJ_DEBUG_PAINT
+ if (ibuf->rect_float) projPixel->pixel.f_pt[0] = 0;
+ else projPixel->pixel.ch_pt[0] = 0;
+#endif
+ projPixel->image_index = image_index;
+
+ return projPixel;
+}
+
+static int line_clip_rect2f(
+ 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) {
+ /* is the line out of range on its Y axis? */
+ if (l1[1] < rect->ymin || l1[1] > rect->ymax) {
+ return 0;
+ }
+ /* line is out of range on its X axis */
+ if ((l1[0] < rect->xmin && l2[0] < rect->xmin) || (l1[0] > rect->xmax && l2[0] > rect->xmax)) {
+ return 0;
+ }
+
+
+ if (fabsf(l1[0] - l2[0]) < PROJ_GEOM_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);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+ }
+
+ copy_v2_v2(l1_clip, l1);
+ copy_v2_v2(l2_clip, l2);
+ CLAMP(l1_clip[0], rect->xmin, rect->xmax);
+ CLAMP(l2_clip[0], rect->xmin, rect->xmax);
+ return 1;
+ }
+ else if (fabsf(l1[0] - l2[0]) < PROJ_GEOM_TOLERANCE) {
+ /* is the line out of range on its X axis? */
+ if (l1[0] < rect->xmin || l1[0] > rect->xmax) {
+ return 0;
+ }
+
+ /* line is out of range on its Y axis */
+ if ((l1[1] < rect->ymin && l2[1] < rect->ymin) || (l1[1] > rect->ymax && l2[1] > rect->ymax)) {
+ return 0;
+ }
+
+ if (fabsf(l1[1] - l2[1]) < PROJ_GEOM_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);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+ }
+
+ copy_v2_v2(l1_clip, l1);
+ copy_v2_v2(l2_clip, l2);
+ CLAMP(l1_clip[1], rect->ymin, rect->ymax);
+ CLAMP(l2_clip[1], rect->ymin, rect->ymax);
+ return 1;
+ }
+ else {
+ float isect;
+ short ok1 = 0;
+ short ok2 = 0;
+
+ /* Done with vertical lines */
+
+ /* are either of the points inside the rectangle ? */
+ if (BLI_rctf_isect_pt_v(rect, l1)) {
+ copy_v2_v2(l1_clip, l1);
+ ok1 = 1;
+ }
+
+ if (BLI_rctf_isect_pt_v(rect, l2)) {
+ copy_v2_v2(l2_clip, l2);
+ ok2 = 1;
+ }
+
+ /* line inside rect */
+ if (ok1 && ok2) return 1;
+
+ /* top/bottom */
+ if (line_isect_y(l1, l2, rect->ymin, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) {
+ if (l1[1] < l2[1]) { /* line 1 is outside */
+ l1_clip[0] = isect;
+ l1_clip[1] = rect->ymin;
+ ok1 = 1;
+ }
+ else {
+ l2_clip[0] = isect;
+ l2_clip[1] = rect->ymin;
+ ok2 = 2;
+ }
+ }
+
+ if (ok1 && ok2) return 1;
+
+ if (line_isect_y(l1, l2, rect->ymax, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) {
+ if (l1[1] > l2[1]) { /* line 1 is outside */
+ l1_clip[0] = isect;
+ l1_clip[1] = rect->ymax;
+ ok1 = 1;
+ }
+ else {
+ l2_clip[0] = isect;
+ l2_clip[1] = rect->ymax;
+ ok2 = 2;
+ }
+ }
+
+ if (ok1 && ok2) return 1;
+
+ /* left/right */
+ if (line_isect_x(l1, l2, rect->xmin, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) {
+ if (l1[0] < l2[0]) { /* line 1 is outside */
+ l1_clip[0] = rect->xmin;
+ l1_clip[1] = isect;
+ ok1 = 1;
+ }
+ else {
+ l2_clip[0] = rect->xmin;
+ l2_clip[1] = isect;
+ ok2 = 2;
+ }
+ }
+
+ if (ok1 && ok2) return 1;
+
+ if (line_isect_x(l1, l2, rect->xmax, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) {
+ if (l1[0] > l2[0]) { /* line 1 is outside */
+ l1_clip[0] = rect->xmax;
+ l1_clip[1] = isect;
+ ok1 = 1;
+ }
+ else {
+ l2_clip[0] = rect->xmax;
+ l2_clip[1] = isect;
+ ok2 = 2;
+ }
+ }
+
+ if (ok1 && ok2) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+ }
+}
+
+
+
+/* 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 */
+#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]) / 4.0f;
+ cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1] + origCos[3][1]) / 4.0f;
+ cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2] + origCos[3][2]) / 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)
+{
+ float cent[3];
+ cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0]) / 3.0f;
+ cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1]) / 3.0f;
+ cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2]) / 3.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);
+
+ mul_v3_fl(insetCos[0], inset);
+ mul_v3_fl(insetCos[1], inset);
+ mul_v3_fl(insetCos[2], inset);
+
+ add_v3_v3(insetCos[0], cent);
+ add_v3_v3(insetCos[1], cent);
+ add_v3_v3(insetCos[2], cent);
+}
+#endif //PROJ_DEBUG_NOSEAMBLEED
+
+static float len_squared_v2v2_alt(const float *v1, const float v2_1, const float v2_2)
+{
+ float x, y;
+
+ x = v1[0] - v2_1;
+ y = v1[1] - v2_2;
+ return x * x + y * y;
+}
+
+/* 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 int project_bucket_isect_circle(const float cent[2], const float radius_squared, rctf *bucket_bounds)
+{
+
+ /* Would normally to a simple intersection test, however we know the bounds of these 2 already intersect
+ * so we only need to test if the center is inside the vertical or horizontal bounds on either axis,
+ * this is even less work then an intersection test
+ */
+#if 0
+ if (BLI_rctf_isect_pt_v(bucket_bounds, cent))
+ return 1;
+#endif
+
+ if ((bucket_bounds->xmin <= cent[0] && bucket_bounds->xmax >= cent[0]) ||
+ (bucket_bounds->ymin <= cent[1] && bucket_bounds->ymax >= cent[1]))
+ {
+ return 1;
+ }
+
+ /* out of bounds left */
+ if (cent[0] < bucket_bounds->xmin) {
+ /* lower left out of radius test */
+ if (cent[1] < bucket_bounds->ymin) {
+ return (len_squared_v2v2_alt(cent, bucket_bounds->xmin, bucket_bounds->ymin) < radius_squared) ? 1 : 0;
+ }
+ /* top left test */
+ else if (cent[1] > bucket_bounds->ymax) {
+ return (len_squared_v2v2_alt(cent, bucket_bounds->xmin, bucket_bounds->ymax) < radius_squared) ? 1 : 0;
+ }
+ }
+ else if (cent[0] > bucket_bounds->xmax) {
+ /* lower right out of radius test */
+ if (cent[1] < bucket_bounds->ymin) {
+ return (len_squared_v2v2_alt(cent, bucket_bounds->xmax, bucket_bounds->ymin) < radius_squared) ? 1 : 0;
+ }
+ /* top right test */
+ else if (cent[1] > bucket_bounds->ymax) {
+ return (len_squared_v2v2_alt(cent, bucket_bounds->xmax, bucket_bounds->ymax) < radius_squared) ? 1 : 0;
+ }
+ }
+
+ return 0;
+}
+
+
+
+/* Note for rect_to_uvspace_ortho() and rect_to_uvspace_persp()
+ * in ortho view this function gives good results when bucket_bounds are outside the triangle
+ * however in some cases, perspective view will mess up with faces that have minimal screenspace area
+ * (viewed from the side)
+ *
+ * for this reason its not reliable in this case so we'll use the Simple Barycentric'
+ * funcs that only account for points inside the triangle.
+ * however switching back to this for ortho is always an option */
+
+static void rect_to_uvspace_ortho(
+ rctf *bucket_bounds,
+ float *v1coSS, float *v2coSS, float *v3coSS,
+ float *uv1co, float *uv2co, float *uv3co,
+ float bucket_bounds_uv[4][2],
+ const int flip)
+{
+ float uv[2];
+ float w[3];
+
+ /* get the UV space bounding box */
+ uv[0] = bucket_bounds->xmax;
+ uv[1] = bucket_bounds->ymin;
+ barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
+ interp_v2_v2v2v2(bucket_bounds_uv[flip ? 3 : 0], uv1co, uv2co, uv3co, w);
+
+ //uv[0] = bucket_bounds->xmax; // set above
+ uv[1] = bucket_bounds->ymax;
+ barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
+ interp_v2_v2v2v2(bucket_bounds_uv[flip ? 2 : 1], uv1co, uv2co, uv3co, w);
+
+ uv[0] = bucket_bounds->xmin;
+ //uv[1] = bucket_bounds->ymax; // set above
+ barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
+ interp_v2_v2v2v2(bucket_bounds_uv[flip ? 1 : 2], uv1co, uv2co, uv3co, w);
+
+ //uv[0] = bucket_bounds->xmin; // set above
+ uv[1] = bucket_bounds->ymin;
+ barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
+ interp_v2_v2v2v2(bucket_bounds_uv[flip ? 0 : 3], uv1co, uv2co, uv3co, w);
+}
+
+/* same as above but use barycentric_weights_v2_persp */
+static void rect_to_uvspace_persp(
+ rctf *bucket_bounds,
+ float *v1coSS, float *v2coSS, float *v3coSS,
+ float *uv1co, float *uv2co, float *uv3co,
+ float bucket_bounds_uv[4][2],
+ const int flip
+ )
+{
+ float uv[2];
+ float w[3];
+
+ /* get the UV space bounding box */
+ uv[0] = bucket_bounds->xmax;
+ uv[1] = bucket_bounds->ymin;
+ barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
+ interp_v2_v2v2v2(bucket_bounds_uv[flip ? 3 : 0], uv1co, uv2co, uv3co, w);
+
+ //uv[0] = bucket_bounds->xmax; // set above
+ uv[1] = bucket_bounds->ymax;
+ barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
+ interp_v2_v2v2v2(bucket_bounds_uv[flip ? 2 : 1], uv1co, uv2co, uv3co, w);
+
+ uv[0] = bucket_bounds->xmin;
+ //uv[1] = bucket_bounds->ymax; // set above
+ barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
+ interp_v2_v2v2v2(bucket_bounds_uv[flip ? 1 : 2], uv1co, uv2co, uv3co, w);
+
+ //uv[0] = bucket_bounds->xmin; // set above
+ uv[1] = bucket_bounds->ymin;
+ barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
+ interp_v2_v2v2v2(bucket_bounds_uv[flip ? 0 : 3], uv1co, uv2co, uv3co, w);
+}
+
+/* This works as we need it to but we can save a few steps and not use it */
+
+#if 0
+static float angle_2d_clockwise(const float p1[2], const float p2[2], const float p3[2])
+{
+ float v1[2], v2[2];
+
+ 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]);
+}
+#endif
+
+#define ISECT_1 (1)
+#define ISECT_2 (1 << 1)
+#define ISECT_3 (1 << 2)
+#define ISECT_4 (1 << 3)
+#define ISECT_ALL3 ((1 << 3) - 1)
+#define ISECT_ALL4 ((1 << 4) - 1)
+
+/* limit must be a fraction over 1.0f */
+static int IsectPT2Df_limit(float pt[2], float v1[2], float v2[2], float v3[2], float limit)
+{
+ return ((area_tri_v2(pt, v1, v2) + area_tri_v2(pt, v2, v3) + area_tri_v2(pt, v3, v1)) / (area_tri_v2(v1, v2, v3))) < limit;
+}
+
+/* Clip the face by a bucket and set the uv-space bucket_bounds_uv
+ * so we have the clipped UV's to do pixel intersection tests with
+ * */
+static int float_z_sort_flip(const void *p1, const void *p2)
+{
+ return (((float *)p1)[2] < ((float *)p2)[2] ? 1 : -1);
+}
+
+static int float_z_sort(const void *p1, const void *p2)
+{
+ return (((float *)p1)[2] < ((float *)p2)[2] ? -1 : 1);
+}
+
+static void project_bucket_clip_face(
+ const int is_ortho,
+ rctf *bucket_bounds,
+ float *v1coSS, float *v2coSS, float *v3coSS,
+ float *uv1co, float *uv2co, float *uv3co,
+ float bucket_bounds_uv[8][2],
+ int *tot)
+{
+ 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));
+
+ float bucket_bounds_ss[4][2];
+
+ /* get the UV space bounding box */
+ inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v1coSS);
+ inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v2coSS) << 1;
+ inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v3coSS) << 2;
+
+ if (inside_bucket_flag == ISECT_ALL3) {
+ /* all screenspace points are inside the bucket bounding box, this means we don't need to clip and can simply return the UVs */
+ if (flip) { /* facing the back? */
+ copy_v2_v2(bucket_bounds_uv[0], uv3co);
+ copy_v2_v2(bucket_bounds_uv[1], uv2co);
+ copy_v2_v2(bucket_bounds_uv[2], uv1co);
+ }
+ else {
+ 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;
+ }
+
+ /* get the UV space bounding box */
+ /* use IsectPT2Df_limit here so we catch points are are touching the tri edge (or a small fraction over) */
+ bucket_bounds_ss[0][0] = bucket_bounds->xmax;
+ bucket_bounds_ss[0][1] = bucket_bounds->ymin;
+ inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[0], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_1 : 0);
+
+ bucket_bounds_ss[1][0] = bucket_bounds->xmax;
+ bucket_bounds_ss[1][1] = bucket_bounds->ymax;
+ inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[1], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_2 : 0);
+
+ bucket_bounds_ss[2][0] = bucket_bounds->xmin;
+ bucket_bounds_ss[2][1] = bucket_bounds->ymax;
+ inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[2], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_3 : 0);
+
+ bucket_bounds_ss[3][0] = bucket_bounds->xmin;
+ 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);
+
+ 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);
+
+ *tot = 4;
+ return;
+ }
+ else {
+ /* The Complicated Case!
+ *
+ * The 2 cases above are where the face is inside the bucket or the bucket is inside the face.
+ *
+ * we need to make a convex polyline from the intersection between the screenspace face
+ * and the bucket bounds.
+ *
+ * There are a number of ways this could be done, currently it just collects all intersecting verts,
+ * and line intersections, then sorts them clockwise, this is a lot easier then evaluating the geometry to
+ * do a correct clipping on both shapes. */
+
+
+ /* add a bunch of points, we know must make up the convex hull which is the clipped rect and triangle */
+
+
+
+ /* Maximum possible 6 intersections when using a rectangle and triangle */
+ float isectVCosSS[8][3]; /* The 3rd float is used to store angle for qsort(), NOT as a Z location */
+ float v1_clipSS[2], v2_clipSS[2];
+ float w[3];
+
+ /* calc center */
+ float cent[2] = {0.0f, 0.0f};
+ /*float up[2] = {0.0f, 1.0f};*/
+ int i;
+ short doubles;
+
+ (*tot) = 0;
+
+ if (inside_face_flag & ISECT_1) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[0]); (*tot)++; }
+ if (inside_face_flag & ISECT_2) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[1]); (*tot)++; }
+ if (inside_face_flag & ISECT_3) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[2]); (*tot)++; }
+ if (inside_face_flag & ISECT_4) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[3]); (*tot)++; }
+
+ if (inside_bucket_flag & ISECT_1) { copy_v2_v2(isectVCosSS[*tot], v1coSS); (*tot)++; }
+ if (inside_bucket_flag & ISECT_2) { copy_v2_v2(isectVCosSS[*tot], v2coSS); (*tot)++; }
+ 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 ((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 ((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 ((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)++; }
+ }
+ }
+
+
+ if ((*tot) < 3) { /* no intersections to speak of */
+ *tot = 0;
+ return;
+ }
+
+ /* now we have all points we need, collect their angles and sort them clockwise */
+
+ for (i = 0; i < (*tot); i++) {
+ cent[0] += isectVCosSS[i][0];
+ cent[1] += isectVCosSS[i][1];
+ }
+ cent[0] = cent[0] / (float)(*tot);
+ cent[1] = cent[1] / (float)(*tot);
+
+
+
+ /* Collect angles for every point around the center point */
+
+
+#if 0 /* uses a few more cycles then the above loop */
+ for (i = 0; i < (*tot); i++) {
+ isectVCosSS[i][2] = angle_2d_clockwise(up, cent, isectVCosSS[i]);
+ }
+#endif
+
+ v1_clipSS[0] = cent[0]; /* Abuse this var for the loop below */
+ v1_clipSS[1] = cent[1] + 1.0f;
+
+ 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]);
+ }
+
+ 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_GEOM_TOLERANCE &&
+ fabsf(isectVCosSS[0][1] - isectVCosSS[(*tot) - 1][1]) < PROJ_GEOM_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_GEOM_TOLERANCE &&
+ fabsf(isectVCosSS[i - 1][1] - isectVCosSS[i][1]) < PROJ_GEOM_TOLERANCE)
+ {
+ int j;
+ for (j = i + 1; j < (*tot); j++) {
+ isectVCosSS[j - 1][0] = isectVCosSS[j][0];
+ isectVCosSS[j - 1][1] = isectVCosSS[j][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;
+ }
+
+
+ if (is_ortho) {
+ for (i = 0; i < (*tot); i++) {
+ barycentric_weights_v2(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w);
+ interp_v2_v2v2v2(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w);
+ }
+ }
+ else {
+ for (i = 0; i < (*tot); i++) {
+ barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w);
+ interp_v2_v2v2v2(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w);
+ }
+ }
+ }
+
+#ifdef PROJ_DEBUG_PRINT_CLIP
+ /* include this at the bottom of the above function to debug the output */
+
+ {
+ /* If there are ever any problems, */
+ float test_uv[4][2];
+ 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)], ", uv1co[0], uv1co[1], uv2co[0], uv2co[1], uv3co[0], uv3co[1]);
+
+ printf("[");
+ for (i = 0; i < (*tot); i++) {
+ printf("(%f, %f),", bucket_bounds_uv[i][0], bucket_bounds_uv[i][1]);
+ }
+ printf("]),\\\n");
+ }
+#endif
+}
+
+/*
+ * # This script creates faces in a blender scene from printed data above.
+ *
+ * project_ls = [
+ * ...(output from above block)...
+ * ]
+ *
+ * from Blender import Scene, Mesh, Window, sys, Mathutils
+ *
+ * import bpy
+ *
+ * V = Mathutils.Vector
+ *
+ * def main():
+ * sce = bpy.data.scenes.active
+ *
+ * for item in project_ls:
+ * bb = item[0]
+ * uv = item[1]
+ * poly = item[2]
+ *
+ * me = bpy.data.meshes.new()
+ * ob = sce.objects.new(me)
+ *
+ * me.verts.extend([V(bb[0]).xyz, V(bb[1]).xyz, V(bb[2]).xyz, V(bb[3]).xyz])
+ * me.faces.extend([(0,1,2,3),])
+ * me.verts.extend([V(uv[0]).xyz, V(uv[1]).xyz, V(uv[2]).xyz])
+ * me.faces.extend([(4,5,6),])
+ *
+ * vs = [V(p).xyz for p in poly]
+ * print len(vs)
+ * l = len(me.verts)
+ * me.verts.extend(vs)
+ *
+ * i = l
+ * while i < len(me.verts):
+ * ii = i + 1
+ * if ii == len(me.verts):
+ * ii = l
+ * me.edges.extend([i, ii])
+ * i += 1
+ *
+ * if __name__ == '__main__':
+ * main()
+ */
+
+
+#undef ISECT_1
+#undef ISECT_2
+#undef ISECT_3
+#undef ISECT_4
+#undef ISECT_ALL3
+#undef ISECT_ALL4
+
+
+/* checks if pt is inside a convex 2D polyline, the polyline must be ordered rotating clockwise
+ * otherwise it would have to test for mixed (line_point_side_v2 > 0.0f) cases */
+static int IsectPoly2Df(const float pt[2], float uv[][2], const int tot)
+{
+ int i;
+ if (line_point_side_v2(uv[tot - 1], uv[0], pt) < 0.0f)
+ return 0;
+
+ for (i = 1; i < tot; i++) {
+ if (line_point_side_v2(uv[i - 1], uv[i], pt) < 0.0f)
+ return 0;
+
+ }
+
+ return 1;
+}
+static int 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);
+
+ for (i = 1; i < tot; i++) {
+ if ((line_point_side_v2(uv[i - 1], uv[i], pt) > 0.0f) != side)
+ return 0;
+
+ }
+
+ 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, const ImBuf *ibuf, const short clamp_u, const short clamp_v)
+{
+ /* Projection vars, to get the 3D locations into screen space */
+ MemArena *arena = ps->arena_mt[thread_index];
+ LinkNode **bucketPixelNodes = ps->bucketRect + bucket_index;
+ LinkNode *bucketFaceNodes = ps->bucketFaces[bucket_index];
+
+ const MFace *mf = ps->dm_mface + face_index;
+ const MTFace *tf = ps->dm_mtface + face_index;
+
+ /* UV/pixel seeking data */
+ int x; /* Image X-Pixel */
+ int y; /* Image Y-Pixel */
+ 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 */
+
+ float *vCo[4]; /* 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 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 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 short is_ortho = ps->is_ortho;
+ const short do_backfacecull = ps->do_backfacecull;
+ const short 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;
+
+
+ /* Use tf_uv_pxoffset instead of tf->uv so we can offset the UV half a pixel
+ * this is done so we can avoid offsetting all the pixels by 0.5 which causes
+ * problems when wrapping negative coords */
+ xhalfpx = (0.5f + (PROJ_GEOM_TOLERANCE / 3.0f)) / ibuf_xf;
+ yhalfpx = (0.5f + (PROJ_GEOM_TOLERANCE / 4.0f)) / ibuf_yf;
+
+ /* Note about (PROJ_GEOM_TOLERANCE/x) above...
+ * Needed to add this offset since UV coords are often quads aligned to pixels.
+ * In this case pixels can be exactly between 2 triangles causing nasty
+ * artifacts.
+ *
+ * This workaround can be removed and painting will still work on most cases
+ * 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;
+
+ tf_uv_pxoffset[2][0] = tf->uv[2][0] - xhalfpx;
+ tf_uv_pxoffset[2][1] = tf->uv[2][1] - yhalfpx;
+
+ if (mf->v4) {
+ vCo[3] = ps->dm_mvert[mf->v4].co;
+
+ 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];
+
+ v1coSS = ps->screenCoords[(*(&mf->v1 + i1))];
+ v2coSS = ps->screenCoords[(*(&mf->v1 + i2))];
+ v3coSS = ps->screenCoords[(*(&mf->v1 + i3))];
+
+ /* This funtion gives is a concave polyline in UV space from the clipped quad and tri*/
+ project_bucket_clip_face(
+ is_ortho, bucket_bounds,
+ v1coSS, v2coSS, v3coSS,
+ uv1co, uv2co, uv3co,
+ uv_clip, &uv_clip_tot
+ );
+
+ /* sometimes this happens, better just allow for 8 intersectiosn even though there should be max 6 */
+#if 0
+ if (uv_clip_tot > 6) {
+ printf("this should never happen! %d\n", uv_clip_tot);
+ }
+#endif
+
+ if (pixel_bounds_array(uv_clip, &bounds_px, ibuf->x, ibuf->y, uv_clip_tot)) {
+
+ if (clamp_u) {
+ CLAMP(bounds_px.xmin, 0, ibuf->x);
+ CLAMP(bounds_px.xmax, 0, ibuf->x);
+ }
+
+ if (clamp_v) {
+ CLAMP(bounds_px.ymin, 0, ibuf->y);
+ CLAMP(bounds_px.ymax, 0, ibuf->y);
+ }
+
+ /* clip face and */
+
+ has_isect = 0;
+ for (y = bounds_px.ymin; y < bounds_px.ymax; y++) {
+ //uv[1] = (((float)y) + 0.5f) / (float)ibuf->y;
+ uv[1] = (float)y / ibuf_yf; /* use pixel offset UV coords instead */
+
+ has_x_isect = 0;
+ for (x = bounds_px.xmin; x < bounds_px.xmax; x++) {
+ //uv[0] = (((float)x) + 0.5f) / ibuf->x;
+ uv[0] = (float)x / ibuf_xf; /* use pixel offset UV coords instead */
+
+ /* Note about IsectPoly2Df_twoside, checking the face or uv flipping doesnt work,
+ * could check the poly direction but better to do this */
+ if ((do_backfacecull == TRUE && IsectPoly2Df(uv, uv_clip, uv_clip_tot)) ||
+ (do_backfacecull == FALSE && IsectPoly2Df_twoside(uv, uv_clip, uv_clip_tot)))
+ {
+
+ has_x_isect = has_isect = 1;
+
+ if (is_ortho) screen_px_from_ortho(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
+ else screen_px_from_persp(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
+
+ /* 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);
+ if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) {
+ continue; /* Watch out that no code below this needs to run */
+ }
+ }
+
+ /* 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 ((ps->do_occlude == FALSE) ||
+ !project_bucket_point_occluded(ps, bucketFaceNodes, face_index, pixelScreenCo))
+ {
+ mask = project_paint_uvpixel_mask(ps, face_index, side, w);
+
+ if (mask > 0.0f) {
+ BLI_linklist_prepend_arena(
+ bucketPixelNodes,
+ project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index,
+ image_index, pixelScreenCo, wco, side, w),
+ arena
+ );
+ }
+ }
+
+ }
+//#if 0
+ else if (has_x_isect) {
+ /* assuming the face is not a bow-tie - we know we cant intersect again on the X */
+ break;
+ }
+//#endif
+ }
+
+
+#if 0 /* TODO - investigate why this dosnt work sometimes! it should! */
+ /* no intersection for this entire row, after some intersection above means we can quit now */
+ if (has_x_isect == 0 && has_isect) {
+ break;
+ }
+#endif
+ }
+ }
+ } while (side--);
+
+
+
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+ if (ps->seam_bleed_px > 0.0f) {
+ int face_seam_flag;
+
+ if (ps->thread_tot > 1)
+ BLI_lock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
+
+ face_seam_flag = ps->faceSeamFlags[face_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)
+ {
+ 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);
+ }
+
+ if ((face_seam_flag & (PROJ_FACE_SEAM1 | PROJ_FACE_SEAM2 | PROJ_FACE_SEAM3 | PROJ_FACE_SEAM4)) == 0) {
+
+ if (ps->thread_tot > 1)
+ BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
+
+ }
+ else {
+ /* 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 *vCoSS[4]; /* 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;
+
+
+ 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);
+
+ /* ps->faceSeamUVs cant be modified when threading, now this is done we can unlock */
+ if (ps->thread_tot > 1)
+ 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];
+
+ /* 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);
+ }
+ else {
+ if (mf->v4) scale_quad(insetCos, vCo, PROJ_FACE_SCALE_SEAM);
+ else 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) */
+
+ 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]))
+ {
+
+ 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;
+ }
+
+ 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[2], outset_uv[fidx1], outset_uv[fidx2], fac2);
+ interp_v2_v2v2(seam_subsection[3], outset_uv[fidx1], outset_uv[fidx2], fac1);
+
+ /* if the bucket_clip_edges values Z values was kept we could avoid this
+ * Inset needs to be added so occlusion tests wont hit adjacent faces */
+ interp_v3_v3v3(edge_verts_inset_clip[0], insetCos[fidx1], insetCos[fidx2], fac1);
+ 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, 1)) {
+ /* bounds between the seam rect and the uvspace bucket pixels */
+
+ has_isect = 0;
+ for (y = bounds_px.ymin; y < bounds_px.ymax; y++) {
+ // uv[1] = (((float)y) + 0.5f) / (float)ibuf->y;
+ uv[1] = (float)y / ibuf_yf; /* use offset uvs instead */
+
+ has_x_isect = 0;
+ for (x = bounds_px.xmin; x < bounds_px.xmax; x++) {
+ //uv[0] = (((float)x) + 0.5f) / (float)ibuf->x;
+ 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])) {
+ float fac;
+
+ /* We need to find the closest point along the face edge,
+ * getting the screen_px_from_*** wont work because our actual location
+ * is not relevant, since we are outside the face, Use VecLerpf to find
+ * our location on the side of the face's UV */
+#if 0
+ if (is_ortho) screen_px_from_ortho(ps, uv, v1co, v2co, v3co, uv1co, uv2co, uv3co, pixelScreenCo);
+ else screen_px_from_persp(ps, uv, v1co, v2co, v3co, uv1co, uv2co, uv3co, pixelScreenCo);
+#endif
+
+ /* 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); }
+
+ if (!is_ortho) {
+ pixelScreenCo[3] = 1.0f;
+ mul_m4_v4((float(*)[4])ps->projectMat, pixelScreenCo); /* cast because of const */
+ pixelScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * pixelScreenCo[0] / pixelScreenCo[3];
+ pixelScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * pixelScreenCo[1] / pixelScreenCo[3];
+ pixelScreenCo[2] = pixelScreenCo[2] / pixelScreenCo[3]; /* Use the depth for bucket point occlusion */
+ }
+
+ if ((ps->do_occlude == FALSE) ||
+ !project_bucket_point_occluded(ps, bucketFaceNodes, face_index, pixelScreenCo))
+ {
+ /* Only bother calculating the weights if we intersect */
+ if (ps->do_mask_normal || ps->dm_mtface_clone) {
+#if 1
+ /* 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 */
+
+ /* 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;
+ }
+#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);
+
+ 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);
+
+ if (mask > 0.0f) {
+ BLI_linklist_prepend_arena(
+ bucketPixelNodes,
+ project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, wco, side, w),
+ arena
+ );
+ }
+
+ }
+ }
+ else if (has_x_isect) {
+ /* assuming the face is not a bow-tie - we know we cant intersect again on the X */
+ break;
+ }
+ }
+
+#if 0 /* TODO - investigate why this dosnt work sometimes! it should! */
+ /* no intersection for this entire row, after some intersection above means we can quit now */
+ if (has_x_isect == 0 && has_isect) {
+ break;
+ }
+#endif
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+#endif // PROJ_DEBUG_NOSEAMBLEED
+}
+
+
+/* takes floating point screenspace min/max and returns int min/max to be used as indices for ps->bucketRect, ps->bucketFlags */
+static void project_paint_bucket_bounds(const ProjPaintState *ps, const float min[2], const float max[2], int bucketMin[2], int bucketMax[2])
+{
+ /* divide by bucketWidth & bucketHeight so the bounds are offset in bucket grid units */
+ /* XXX: the offset of 0.5 is always truncated to zero and the offset of 1.5f is always truncated to 1, is this really correct?? - jwilkins */
+ bucketMin[0] = (int)((int)(((float)(min[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 0.5f); /* these offsets of 0.5 and 1.5 seem odd but they are correct */
+ bucketMin[1] = (int)((int)(((float)(min[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 0.5f);
+
+ bucketMax[0] = (int)((int)(((float)(max[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 1.5f);
+ bucketMax[1] = (int)((int)(((float)(max[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 1.5f);
+
+ /* in case the rect is outside the mesh 2d bounds */
+ CLAMP(bucketMin[0], 0, ps->buckets_x);
+ CLAMP(bucketMin[1], 0, ps->buckets_y);
+
+ CLAMP(bucketMax[0], 0, ps->buckets_x);
+ CLAMP(bucketMax[1], 0, ps->buckets_y);
+}
+
+/* set bucket_bounds to a screen space-aligned floating point bound-box */
+static void project_bucket_bounds(const ProjPaintState *ps, const int bucket_x, const int bucket_y, rctf *bucket_bounds)
+{
+ bucket_bounds->xmin = ps->screenMin[0] + ((bucket_x) * (ps->screen_width / ps->buckets_x)); /* left */
+ bucket_bounds->xmax = ps->screenMin[0] + ((bucket_x + 1) * (ps->screen_width / ps->buckets_x)); /* right */
+
+ bucket_bounds->ymin = ps->screenMin[1] + ((bucket_y) * (ps->screen_height / ps->buckets_y)); /* bottom */
+ bucket_bounds->ymax = ps->screenMin[1] + ((bucket_y + 1) * (ps->screen_height / ps->buckets_y)); /* top */
+}
+
+/* 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)
+{
+ LinkNode *node;
+ int face_index, image_index = 0;
+ ImBuf *ibuf = NULL;
+ Image *tpage_last = NULL, *tpage;
+ Image *ima = NULL;
+
+ if (ps->image_tot == 1) {
+ /* Simple loop, no context switching */
+ ibuf = ps->projImages[0].ibuf;
+ ima = ps->projImages[0].ima;
+
+ for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
+ project_paint_face_init(ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0, bucket_bounds, ibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V);
+ }
+ }
+ 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);
+
+ /* Image context switching */
+ tpage = project_paint_face_image(ps, ps->dm_mtface, face_index);
+ if (tpage_last != tpage) {
+ tpage_last = tpage;
+
+ for (image_index = 0; image_index < ps->image_tot; image_index++) {
+ if (ps->projImages[image_index].ima == tpage_last) {
+ ibuf = ps->projImages[image_index].ibuf;
+ ima = ps->projImages[image_index].ima;
+ break;
+ }
+ }
+ }
+ /* context switching done */
+
+ project_paint_face_init(ps, thread_index, bucket_index, face_index, image_index, bucket_bounds, ibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V);
+ }
+ }
+
+ ps->bucketFlags[bucket_index] |= PROJ_BUCKET_INIT;
+}
+
+
+/* We want to know if a bucket and a face overlap in screen-space
+ *
+ * Note, if this ever returns false positives its not that bad, since a face in the bounding area will have its pixels
+ * calculated when it might not be needed later, (at the moment at least)
+ * obviously it shouldn't have bugs though */
+
+static int project_bucket_face_isect(ProjPaintState *ps, int bucket_x, int bucket_y, const MFace *mf)
+{
+ /* TODO - replace this with a tricker method that uses sideofline for all screenCoords's edges against the closest bucket corner */
+ rctf bucket_bounds;
+ float p1[2], p2[2], p3[2], p4[2];
+ float *v, *v1, *v2, *v3, *v4 = NULL;
+ 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;
+ do {
+ v = ps->screenCoords[(*(&mf->v1 + 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];
+ }
+
+ 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;
+ }
+ }
+
+ return 0;
+}
+
+/* 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)
+{
+ float min[2], max[2], *vCoSS;
+ int bucketMin[2], bucketMax[2]; /* for ps->bucketRect indexing */
+ int fidx, bucket_x, bucket_y;
+ int has_x_isect = -1, has_isect = 0; /* for early loop exit */
+ MemArena *arena = ps->arena_mt[0]; /* just use the first thread arena since threading has not started yet */
+
+ INIT_MINMAX2(min, max);
+
+ fidx = mf->v4 ? 3 : 2;
+ do {
+ vCoSS = ps->screenCoords[*(&mf->v1 + fidx)];
+ minmax_v2v2_v2(min, max, vCoSS);
+ } while (fidx--);
+
+ project_paint_bucket_bounds(ps, min, max, bucketMin, bucketMax);
+
+ 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)) {
+ 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 */
+ arena
+ );
+
+ has_x_isect = has_isect = 1;
+ }
+ else if (has_x_isect) {
+ /* assuming the face is not a bow-tie - we know we cant intersect again on the X */
+ break;
+ }
+ }
+
+ /* no intersection for this entire row, after some intersection above means we can quit now */
+ if (has_x_isect == 0 && has_isect) {
+ break;
+ }
+ }
+
+#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 */
+ }
+#endif
+}
+
+/* run once per stroke before projection painting */
+static void project_paint_begin(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;
+
+ /* Face vars */
+ MFace *mf;
+ MTFace *tf;
+
+ int a, i; /* generic looping vars */
+ int image_index = -1, face_index;
+ 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);
+
+ /* ---- end defines ---- */
+
+ if (ps->source == PROJ_SRC_VIEW)
+ ED_view3d_clipping_local(ps->rv3d, ps->ob->obmat); /* faster clipping lookups */
+
+ /* 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->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->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;
+ }
+
+ ps->dm_mvert = ps->dm->getVertArray(ps->dm);
+ ps->dm_mface = ps->dm->getTessFaceArray(ps->dm);
+ ps->dm_mtface = ps->dm->getTessFaceDataArray(ps->dm, CD_MTFACE);
+
+ ps->dm_totvert = ps->dm->getNumVerts(ps->dm);
+ ps->dm_totface = ps->dm->getNumTessFaces(ps->dm);
+
+ /* use clone mtface? */
+
+
+ /* Note, use the original mesh for getting the clone and mask layer index
+ * this avoids re-generating the derived mesh just to get the new index */
+ if (ps->do_layer_clone) {
+ //int layer_num = CustomData_get_clone_layer(&ps->dm->faceData, CD_MTFACE);
+ int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->fdata, CD_MTFACE);
+ if (layer_num != -1)
+ ps->dm_mtface_clone = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
+
+ if (ps->dm_mtface_clone == NULL || ps->dm_mtface_clone == ps->dm_mtface) {
+ ps->do_layer_clone = FALSE;
+ ps->dm_mtface_clone = NULL;
+ printf("ACK!\n");
+ }
+ }
+
+ if (ps->do_layer_stencil) {
+ //int layer_num = CustomData_get_stencil_layer(&ps->dm->faceData, CD_MTFACE);
+ int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->fdata, CD_MTFACE);
+ if (layer_num != -1)
+ ps->dm_mtface_stencil = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
+
+ if (ps->dm_mtface_stencil == NULL || ps->dm_mtface_stencil == ps->dm_mtface) {
+ ps->do_layer_stencil = FALSE;
+ ps->dm_mtface_stencil = NULL;
+ }
+ }
+
+ /* 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);
+ /* 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);
+#endif
+ }
+
+ ps->viewDir[0] = 0.0f;
+ ps->viewDir[1] = 0.0f;
+ ps->viewDir[2] = 1.0f;
+
+ {
+ float viewmat[4][4];
+ float viewinv[4][4];
+
+ invert_m4_m4(ps->ob->imat, ps->ob->obmat);
+
+ if (ps->source == PROJ_SRC_VIEW) {
+ /* normal drawing */
+ ps->winx = ps->ar->winx;
+ ps->winy = ps->ar->winy;
+
+ copy_m4_m4(viewmat, ps->rv3d->viewmat);
+ copy_m4_m4(viewinv, ps->rv3d->viewinv);
+
+ ED_view3d_ob_project_mat_get(ps->rv3d, ps->ob, ps->projectMat);
+
+ 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];
+
+ ps->winx = ps->reproject_ibuf->x;
+ ps->winy = ps->reproject_ibuf->y;
+
+ 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);
+
+ float *array = (float *)IDP_Array(view_data);
+
+ /* 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;
+
+ 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;
+ }
+
+ /* same as #ED_view3d_ob_project_mat_get */
+ mult_m4_m4m4(vmat, viewmat, ps->ob->obmat);
+ mult_m4_m4m4(ps->projectMat, winmat, vmat);
+ }
+
+
+ /* 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);
+
+ /* 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]);
+ }
+
+ /* calculate vert screen coords
+ * run this early so we can calculate the x/y resolution of our bucket rect */
+ INIT_MINMAX2(ps->screenMin, ps->screenMax);
+
+ ps->screenCoords = MEM_mallocN(sizeof(float) * ps->dm_totvert * 4, "ProjectPaint ScreenVerts");
+ projScreenCo = *ps->screenCoords;
+
+ if (ps->is_ortho) {
+ for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++, projScreenCo += 4) {
+ mul_v3_m4v3(projScreenCo, ps->projectMat, mv->co);
+
+ /* screen space, not clamped */
+ projScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projScreenCo[0];
+ projScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projScreenCo[1];
+ minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo);
+ }
+ }
+ else {
+ for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++, projScreenCo += 4) {
+ copy_v3_v3(projScreenCo, mv->co);
+ projScreenCo[3] = 1.0f;
+
+ mul_m4_v4(ps->projectMat, projScreenCo);
+
+ if (projScreenCo[3] > ps->clipsta) {
+ /* screen space, not clamped */
+ projScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projScreenCo[0] / projScreenCo[3];
+ projScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projScreenCo[1] / projScreenCo[3];
+ projScreenCo[2] = projScreenCo[2] / projScreenCo[3]; /* Use the depth for bucket point occlusion */
+ minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo);
+ }
+ else {
+ /* TODO - deal with cases where 1 side of a face goes behind the view ?
+ *
+ * After some research this is actually very tricky, only option is to
+ * clip the derived mesh before painting, which is a Pain */
+ projScreenCo[0] = FLT_MAX;
+ }
+ }
+ }
+
+ /* 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
+ * - a single screen aligned quad */
+ projMargin = (ps->screenMax[0] - ps->screenMin[0]) * 0.000001f;
+ ps->screenMax[0] += projMargin;
+ ps->screenMin[0] -= projMargin;
+ projMargin = (ps->screenMax[1] - ps->screenMin[1]) * 0.000001f;
+ ps->screenMax[1] += projMargin;
+ ps->screenMin[1] -= projMargin;
+
+ if (ps->source == PROJ_SRC_VIEW) {
+#ifdef PROJ_DEBUG_WINCLIP
+ CLAMP(ps->screenMin[0], (float)(-diameter), (float)(ps->winx + diameter));
+ CLAMP(ps->screenMax[0], (float)(-diameter), (float)(ps->winx + diameter));
+
+ CLAMP(ps->screenMin[1], (float)(-diameter), (float)(ps->winy + diameter));
+ CLAMP(ps->screenMax[1], (float)(-diameter), (float)(ps->winy + diameter));
+#endif
+ }
+ else { /* 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));
+
+ /* printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y); */
+
+ /* 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
+ 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->faceSeamUVs = MEM_mallocN(sizeof(float) * ps->dm_totface * 8, "paint-faceSeamUVs");
+ }
+#endif
+
+ /* Thread stuff
+ *
+ * very small brushes run a lot slower multithreaded since the advantage with
+ * threads is being able to fill in multiple buckets at once.
+ * Only use threads for bigger brushes. */
+
+ if (ps->scene->r.mode & R_FIXED_THREADS) {
+ ps->thread_tot = ps->scene->r.threads;
+ }
+ else {
+ ps->thread_tot = BLI_system_thread_count();
+ }
+ for (a = 0; a < ps->thread_tot; a++) {
+ ps->arena_mt[a] = BLI_memarena_new(1 << 16, "project paint arena");
+ }
+
+ arena = ps->arena_mt[0];
+
+ if (ps->do_backfacecull && ps->do_mask_normal) {
+ float viewDirPersp[3];
+
+ 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 (ps->is_ortho) {
+ if (angle_normalized_v3v3(ps->viewDir, no) >= ps->normal_angle) { /* 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 */
+ 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++) {
+
+#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);
+ }
+ }
+#endif
+
+ tpage = project_paint_face_image(ps, ps->dm_mtface, face_index);
+
+ if (tpage && ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) == 0 || mf->flag & ME_FACE_SEL)) {
+
+ float *v1coSS, *v2coSS, *v3coSS, *v4coSS = NULL;
+
+ 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))
+ {
+ 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;
+ }
+
+#endif //PROJ_DEBUG_WINCLIP
+
+
+ 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;
+ }
+ }
+ else {
+ if (line_point_side_v2(v1coSS, v2coSS, v3coSS) < 0.0f) {
+ continue;
+ }
+
+ }
+ }
+
+ if (tpage_last != tpage) {
+
+ image_index = BLI_linklist_index(image_LinkList, tpage);
+
+ if (image_index == -1 && BKE_image_has_ibuf(tpage, NULL)) { /* MemArena dosnt have an append func */
+ BLI_linklist_append(&image_LinkList, tpage);
+ image_index = ps->image_tot;
+ ps->image_tot++;
+ }
+
+ tpage_last = tpage;
+ }
+
+ 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);
+ }
+ }
+ }
+
+ /* 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++) {
+ projIma->ima = node->link;
+ projIma->touch = 0;
+ projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL);
+ projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ }
+
+ /* we have built the array, discard the linked list */
+ BLI_linklist_free(image_LinkList, NULL);
+}
+
+static void paint_proj_begin_clone(ProjPaintState *ps, const int mouse[2])
+{
+ /* setup clone offset */
+ if (ps->tool == PAINT_TOOL_CLONE) {
+ float projCo[4];
+ copy_v3_v3(projCo, give_cursor(ps->scene, ps->v3d));
+ mul_m4_v3(ps->ob->imat, projCo);
+
+ projCo[3] = 1.0f;
+ mul_m4_v4(ps->projectMat, projCo);
+ ps->cloneOffset[0] = mouse[0] - ((float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projCo[0] / projCo[3]);
+ ps->cloneOffset[1] = mouse[1] - ((float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projCo[1] / projCo[3]);
+ }
+}
+
+static void project_paint_end(ProjPaintState *ps)
+{
+ int a;
+ ProjPaintImage *projIma;
+
+ /* build undo data from original pixel colors */
+ if (U.uiflag & USER_GLOBALUNDO) {
+ ProjPixel *projPixel;
+ ImBuf *tmpibuf = NULL, *tmpibuf_float = NULL;
+ LinkNode *pixel_node;
+ void *tilerect;
+ MemArena *arena = ps->arena_mt[0]; /* threaded arena re-used for non threaded case */
+
+ int bucket_tot = (ps->buckets_x * ps->buckets_y); /* we could get an X/Y but easier to loop through all possible buckets */
+ int bucket_index;
+ int tile_index;
+ int x_round, y_round;
+ int x_tile, y_tile;
+ int is_float = -1;
+
+ /* context */
+ ProjPaintImage *last_projIma;
+ int last_image_index = -1;
+ int last_tile_width = 0;
+
+ for (a = 0, last_projIma = ps->projImages; a < ps->image_tot; a++, last_projIma++) {
+ int size = sizeof(void **) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->y);
+ last_projIma->undoRect = (void **) BLI_memarena_alloc(arena, size);
+ memset(last_projIma->undoRect, 0, size);
+ last_projIma->ibuf->userflags |= IB_BITMAPDIRTY;
+ }
+
+ for (bucket_index = 0; bucket_index < bucket_tot; bucket_index++) {
+ /* loop through all pixels */
+ for (pixel_node = ps->bucketRect[bucket_index]; pixel_node; pixel_node = pixel_node->next) {
+
+ /* ok we have a pixel, was it modified? */
+ projPixel = (ProjPixel *)pixel_node->link;
+
+ if (last_image_index != projPixel->image_index) {
+ /* set the context */
+ last_image_index = projPixel->image_index;
+ last_projIma = ps->projImages + last_image_index;
+ last_tile_width = IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x);
+ is_float = last_projIma->ibuf->rect_float ? 1 : 0;
+ }
+
+
+ if ((is_float == 0 && projPixel->origColor.uint != *projPixel->pixel.uint_pt) ||
+ (is_float == 1 &&
+ (projPixel->origColor.f[0] != projPixel->pixel.f_pt[0] ||
+ projPixel->origColor.f[1] != projPixel->pixel.f_pt[1] ||
+ projPixel->origColor.f[2] != projPixel->pixel.f_pt[2] ||
+ projPixel->origColor.f[3] != projPixel->pixel.f_pt[3]))
+ )
+ {
+
+ x_tile = projPixel->x_px >> IMAPAINT_TILE_BITS;
+ y_tile = projPixel->y_px >> IMAPAINT_TILE_BITS;
+
+ x_round = x_tile * IMAPAINT_TILE_SIZE;
+ y_round = y_tile * IMAPAINT_TILE_SIZE;
+
+ tile_index = x_tile + y_tile * last_tile_width;
+
+ if (last_projIma->undoRect[tile_index] == NULL) {
+ /* add the undo tile from the modified image, then write the original colors back into it */
+ tilerect = last_projIma->undoRect[tile_index] = image_undo_push_tile(last_projIma->ima, last_projIma->ibuf, is_float ? (&tmpibuf_float) : (&tmpibuf), x_tile, y_tile);
+ }
+ else {
+ tilerect = last_projIma->undoRect[tile_index];
+ }
+
+ /* This is a BIT ODD, but overwrite the undo tiles image info with this pixels original color
+ * because allocating the tiles along the way slows down painting */
+
+ if (is_float) {
+ float *rgba_fp = (float *)tilerect + (((projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE)) * 4;
+ copy_v4_v4(rgba_fp, projPixel->origColor.f);
+ }
+ else {
+ ((unsigned int *)tilerect)[(projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE] = projPixel->origColor.uint;
+ }
+ }
+ }
+ }
+
+ if (tmpibuf) IMB_freeImBuf(tmpibuf);
+ if (tmpibuf_float) IMB_freeImBuf(tmpibuf_float);
+ }
+ /* done calculating undo data */
+
+ /* 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);
+ }
+
+ BKE_image_release_ibuf(ps->reproject_image, ps->reproject_ibuf, NULL);
+
+ MEM_freeN(ps->screenCoords);
+ MEM_freeN(ps->bucketRect);
+ MEM_freeN(ps->bucketFaces);
+ MEM_freeN(ps->bucketFlags);
+
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+ if (ps->seam_bleed_px > 0.0f) {
+ MEM_freeN(ps->vertFaces);
+ MEM_freeN(ps->faceSeamFlags);
+ MEM_freeN(ps->faceSeamUVs);
+ }
+#endif
+
+ if (ps->vertFlags) MEM_freeN(ps->vertFlags);
+
+ 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
+ }
+
+ if (ps->dm_release)
+ ps->dm->release(ps->dm);
+}
+
+/* 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;
+
+ pr++;
+ }
+}
+
+
+static int partial_redraw_array_merge(ImagePaintPartialRedraw *pr, ImagePaintPartialRedraw *pr_other, int tot)
+{
+ int touch = 0;
+ while (tot--) {
+ pr->x1 = min_ii(pr->x1, pr_other->x1);
+ pr->y1 = min_ii(pr->y1, pr_other->y1);
+
+ pr->x2 = max_ii(pr->x2, pr_other->x2);
+ pr->y2 = max_ii(pr->y2, pr_other->y2);
+
+ if (pr->x2 != -1)
+ touch = 1;
+
+ pr++; pr_other++;
+ }
+
+ return touch;
+}
+
+/* Loop over all images on this mesh and update any we have touched */
+static int project_image_refresh_tagged(ProjPaintState *ps)
+{
+ ImagePaintPartialRedraw *pr;
+ ProjPaintImage *projIma;
+ int a, i;
+ int redraw = 0;
+
+
+ for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) {
+ if (projIma->touch) {
+ /* look over each bound cell */
+ for (i = 0; i < PROJ_BOUNDBOX_SQUARED; i++) {
+ pr = &(projIma->partRedrawRect[i]);
+ if (pr->x2 != -1) { /* TODO - use 'enabled' ? */
+ set_imapaintpartial(pr);
+ imapaint_image_update(NULL, projIma->ima, projIma->ibuf, true);
+ redraw = 1;
+ }
+ }
+
+ projIma->touch = 0; /* clear for reuse */
+ }
+ }
+
+ return redraw;
+}
+
+/* run this per painting onto each mouse location */
+static int project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2])
+{
+ if (ps->source == PROJ_SRC_VIEW) {
+ float min_brush[2], max_brush[2];
+ const float radius = (float)BKE_brush_size_get(ps->scene, ps->brush);
+
+ /* so we don't have a bucket bounds that is way too small to paint into */
+ // if (radius < 1.0f) radius = 1.0f; // this doesn't work yet :/
+
+ min_brush[0] = mval_f[0] - radius;
+ min_brush[1] = mval_f[1] - radius;
+
+ max_brush[0] = mval_f[0] + radius;
+ max_brush[1] = mval_f[1] + radius;
+
+ /* offset to make this a valid bucket index */
+ project_paint_bucket_bounds(ps, min_brush, max_brush, ps->bucketMin, ps->bucketMax);
+
+ /* mouse outside the model areas? */
+ if (ps->bucketMin[0] == ps->bucketMax[0] || ps->bucketMin[1] == ps->bucketMax[1]) {
+ return 0;
+ }
+
+ ps->context_bucket_x = ps->bucketMin[0];
+ ps->context_bucket_y = ps->bucketMin[1];
+ }
+ else { /* reproject: PROJ_SRC_* */
+ ps->bucketMin[0] = 0;
+ ps->bucketMin[1] = 0;
+
+ ps->bucketMax[0] = ps->buckets_x;
+ ps->bucketMax[1] = ps->buckets_y;
+
+ ps->context_bucket_x = 0;
+ ps->context_bucket_y = 0;
+ }
+ return 1;
+}
+
+
+static int project_bucket_iter_next(ProjPaintState *ps, int *bucket_index, rctf *bucket_bounds, const float mval[2])
+{
+ const int diameter = 2 * BKE_brush_size_get(ps->scene, ps->brush);
+
+ if (ps->thread_tot > 1)
+ BLI_lock_thread(LOCK_CUSTOM1);
+
+ //printf("%d %d\n", ps->context_bucket_x, ps->context_bucket_y);
+
+ for (; ps->context_bucket_y < ps->bucketMax[1]; ps->context_bucket_y++) {
+ for (; ps->context_bucket_x < ps->bucketMax[0]; ps->context_bucket_x++) {
+
+ /* use bucket_bounds for project_bucket_isect_circle and project_bucket_init*/
+ project_bucket_bounds(ps, ps->context_bucket_x, ps->context_bucket_y, bucket_bounds);
+
+ if ((ps->source != PROJ_SRC_VIEW) ||
+ project_bucket_isect_circle(mval, (float)(diameter * diameter), bucket_bounds))
+ {
+ *bucket_index = ps->context_bucket_x + (ps->context_bucket_y * ps->buckets_x);
+ ps->context_bucket_x++;
+
+ if (ps->thread_tot > 1)
+ BLI_unlock_thread(LOCK_CUSTOM1);
+
+ return 1;
+ }
+ }
+ ps->context_bucket_x = ps->bucketMin[0];
+ }
+
+ if (ps->thread_tot > 1)
+ BLI_unlock_thread(LOCK_CUSTOM1);
+ return 0;
+}
+
+/* Each thread gets one of these, also used as an argument to pass to project_paint_op */
+typedef struct ProjectHandle {
+ /* args */
+ ProjPaintState *ps;
+ float prevmval[2];
+ float mval[2];
+
+ /* annoying but we need to have image bounds per thread, then merge into ps->projectPartialRedraws */
+ ProjPaintImage *projImages; /* array of partial redraws */
+
+ /* thread settings */
+ int thread_index;
+
+ struct ImagePool *pool;
+} ProjectHandle;
+
+static void blend_color_mix(unsigned char cp[4], const unsigned char cp1[4], const unsigned char cp2[4], const int fac)
+{
+ /* this and other blending modes previously used >>8 instead of /255. both
+ * are not equivalent (>>8 is /256), and the former results in rounding
+ * errors that can turn colors black fast after repeated blending */
+ const int mfac = 255 - fac;
+
+ cp[0] = (mfac * cp1[0] + fac * cp2[0]) / 255;
+ cp[1] = (mfac * cp1[1] + fac * cp2[1]) / 255;
+ cp[2] = (mfac * cp1[2] + fac * cp2[2]) / 255;
+ cp[3] = (mfac * cp1[3] + fac * cp2[3]) / 255;
+}
+
+static void blend_color_mix_float(float cp[4], const float cp1[4], const float cp2[4], const float fac)
+{
+ const float mfac = 1.0f - fac;
+ cp[0] = mfac * cp1[0] + fac * cp2[0];
+ cp[1] = mfac * cp1[1] + fac * cp2[1];
+ cp[2] = mfac * cp1[2] + fac * cp2[2];
+ cp[3] = mfac * cp1[3] + fac * cp2[3];
+}
+
+static void blend_color_mix_accum(unsigned char cp[4], const unsigned char cp1[4], const unsigned char cp2[4], const int fac)
+{
+ /* this and other blending modes previously used >>8 instead of /255. both
+ * are not equivalent (>>8 is /256), and the former results in rounding
+ * errors that can turn colors black fast after repeated blending */
+ const int mfac = 255 - fac;
+ const int alpha = cp1[3] + ((fac * cp2[3]) / 255);
+
+ cp[0] = (mfac * cp1[0] + fac * cp2[0]) / 255;
+ cp[1] = (mfac * cp1[1] + fac * cp2[1]) / 255;
+ cp[2] = (mfac * cp1[2] + fac * cp2[2]) / 255;
+ cp[3] = alpha > 255 ? 255 : alpha;
+}
+static void blend_color_mix_accum_float(float cp[4], const float cp1[4], const unsigned char cp2[4], const float fac)
+{
+ const float mfac = 1.0f - fac;
+ const float alpha = cp1[3] + (fac * (cp2[3] / 255.0f));
+
+ cp[0] = (mfac * cp1[0] + (fac * (cp2[0] / 255.0f)));
+ cp[1] = (mfac * cp1[1] + (fac * (cp2[1] / 255.0f)));
+ cp[2] = (mfac * cp1[2] + (fac * (cp2[2] / 255.0f)));
+ cp[3] = alpha > 1.0f ? 1.0f : alpha;
+}
+
+
+static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask)
+{
+ if (ps->do_masking && mask < 1.0f) {
+ projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, ((ProjPixelClone *)projPixel)->clonepx.uint, (int)(alpha * 255), ps->blend);
+ blend_color_mix(projPixel->pixel.ch_pt, projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask * 255));
+ }
+ else {
+ *projPixel->pixel.uint_pt = IMB_blend_color(*projPixel->pixel.uint_pt, ((ProjPixelClone *)projPixel)->clonepx.uint, (int)(alpha * mask * 255), ps->blend);
+ }
+}
+
+static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask)
+{
+ if (ps->do_masking && mask < 1.0f) {
+ IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, ((ProjPixelClone *)projPixel)->clonepx.f, alpha, ps->blend);
+ blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f, projPixel->newColor.f, mask);
+ }
+ else {
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.f, alpha * mask, ps->blend);
+ }
+}
+
+/* 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
+ * really that important to be correct as it is with clone and painting
+ */
+static void do_projectpaint_smear(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask,
+ MemArena *smearArena, LinkNode **smearPixels, const float co[2])
+{
+ unsigned char rgba_ub[4];
+
+ if (project_paint_PickColor(ps, co, NULL, rgba_ub, 1) == 0)
+ return;
+ /* ((ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*projPixel->pixel.uint_pt, *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend); */
+ blend_color_mix(((ProjPixelClone *)projPixel)->clonepx.ch, projPixel->pixel.ch_pt, rgba_ub, (int)(alpha * mask * 255));
+ BLI_linklist_prepend_arena(smearPixels, (void *)projPixel, smearArena);
+}
+
+static void do_projectpaint_smear_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask,
+ MemArena *smearArena, LinkNode **smearPixels_f, const float co[2])
+{
+ float rgba[4];
+
+ if (project_paint_PickColor(ps, co, rgba, NULL, 1) == 0)
+ return;
+
+ /* (ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*((unsigned int *)rgba_smear), *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend); */
+ blend_color_mix_float(((ProjPixelClone *)projPixel)->clonepx.f, projPixel->pixel.f_pt, rgba, alpha * mask);
+ BLI_linklist_prepend_arena(smearPixels_f, (void *)projPixel, smearArena);
+}
+
+/* do_projectpaint_soften for float & byte
+ */
+static float inv_pow2(float f)
+{
+ f = 1.0f - f;
+ f = f * f;
+ return 1.0f - f;
+}
+
+static void do_projectpaint_soften_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask,
+ MemArena *softenArena, LinkNode **softenPixels)
+{
+ unsigned int accum_tot = 0;
+ unsigned int i;
+
+ float *rgba = projPixel->newColor.f;
+
+ /* sigh, alpha values tend to need to be a _lot_ stronger with blur */
+ mask = inv_pow2(mask);
+ alpha = inv_pow2(alpha);
+
+ /* rather then painting, accumulate surrounding colors */
+ zero_v4(rgba);
+
+ for (i = 0; i < PROJ_PIXEL_SOFTEN_TOT; i++) {
+ float co_ofs[2];
+ float rgba_tmp[4];
+ sub_v2_v2v2(co_ofs, projPixel->projCoSS, proj_pixel_soften_v2[i]);
+ if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, TRUE)) {
+ add_v4_v4(rgba, rgba_tmp);
+ accum_tot++;
+ }
+ }
+
+ if (LIKELY(accum_tot != 0)) {
+ mul_v4_fl(rgba, 1.0f / (float)accum_tot);
+ blend_color_mix_float(rgba, projPixel->pixel.f_pt, rgba, alpha);
+ if (mask < 1.0f) blend_color_mix_float(rgba, projPixel->origColor.f, rgba, mask);
+ BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena);
+ }
+}
+
+static void do_projectpaint_soften(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask,
+ MemArena *softenArena, LinkNode **softenPixels)
+{
+ unsigned int accum_tot = 0;
+ unsigned int i;
+
+ float rgba[4]; /* convert to byte after */
+
+ /* sigh, alpha values tend to need to be a _lot_ stronger with blur */
+ mask = inv_pow2(mask);
+ alpha = inv_pow2(alpha);
+
+ /* rather then painting, accumulate surrounding colors */
+ zero_v4(rgba);
+
+ for (i = 0; i < PROJ_PIXEL_SOFTEN_TOT; i++) {
+ float co_ofs[2];
+ float rgba_tmp[4];
+ sub_v2_v2v2(co_ofs, projPixel->projCoSS, proj_pixel_soften_v2[i]);
+ if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, TRUE)) {
+ add_v4_v4(rgba, rgba_tmp);
+ accum_tot++;
+ }
+ }
+
+ if (LIKELY(accum_tot != 0)) {
+ unsigned char *rgba_ub = projPixel->newColor.ch;
+
+ mul_v4_fl(rgba, 1.0f / (float)accum_tot);
+ IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba_ub, rgba);
+
+ blend_color_mix(rgba_ub, projPixel->pixel.ch_pt, rgba_ub, (int)(alpha * 255));
+ if (mask != 1.0f) blend_color_mix(rgba_ub, projPixel->origColor.ch, rgba_ub, (int)(mask * 255));
+ BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena);
+ }
+}
+
+BLI_INLINE void rgba_float_to_uchar__mul_v3(unsigned char rgba_ub[4], const float rgba[4], const float rgb[3])
+{
+ rgba_ub[0] = f_to_char(rgba[0] * rgb[0]);
+ rgba_ub[1] = f_to_char(rgba[1] * rgb[1]);
+ rgba_ub[2] = f_to_char(rgba[2] * rgb[2]);
+ rgba_ub[3] = f_to_char(rgba[3]);
+}
+
+static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, const float rgba[4], float alpha, float mask)
+{
+ unsigned char rgba_ub[4];
+
+ if (ps->is_texbrush) {
+ rgba_float_to_uchar__mul_v3(rgba_ub, rgba, ps->brush->rgb);
+ }
+ else {
+ IMAPAINT_FLOAT_RGB_TO_CHAR(rgba_ub, ps->brush->rgb);
+ rgba_ub[3] = 255;
+ }
+
+ if (ps->do_masking && mask < 1.0f) {
+ projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, *((unsigned int *)rgba_ub), (int)(alpha * 255), ps->blend);
+ blend_color_mix(projPixel->pixel.ch_pt, projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask * 255));
+ }
+ else {
+ *projPixel->pixel.uint_pt = IMB_blend_color(*projPixel->pixel.uint_pt, *((unsigned int *)rgba_ub), (int)(alpha * mask * 255), ps->blend);
+ }
+}
+
+static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, float rgba[4], float alpha, float mask)
+{
+ if (ps->is_texbrush) {
+ /* rgba already holds a texture result here from higher level function */
+ float rgba_br[3];
+ srgb_to_linearrgb_v3_v3(rgba_br, ps->brush->rgb);
+ mul_v3_v3(rgba, rgba_br);
+ }
+ else {
+ srgb_to_linearrgb_v3_v3(rgba, ps->brush->rgb);
+ rgba[3] = 1.0;
+ }
+
+ if (ps->do_masking && mask < 1.0f) {
+ IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, rgba, alpha, ps->blend);
+ blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f, projPixel->newColor.f, mask);
+ }
+ else {
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, rgba, alpha * mask, ps->blend);
+ }
+}
+
+
+
+/* run this for single and multithreaded painting */
+static void *do_projectpaint_thread(void *ph_v)
+{
+ /* First unpack args from the struct */
+ ProjPaintState *ps = ((ProjectHandle *)ph_v)->ps;
+ ProjPaintImage *projImages = ((ProjectHandle *)ph_v)->projImages;
+ const float *lastpos = ((ProjectHandle *)ph_v)->prevmval;
+ const float *pos = ((ProjectHandle *)ph_v)->mval;
+ const int thread_index = ((ProjectHandle *)ph_v)->thread_index;
+ struct ImagePool *pool = ((ProjectHandle *)ph_v)->pool;
+ /* Done with args from ProjectHandle */
+
+ LinkNode *node;
+ ProjPixel *projPixel;
+ Brush *brush = ps->brush;
+
+ int last_index = -1;
+ ProjPaintImage *last_projIma = NULL;
+ ImagePaintPartialRedraw *last_partial_redraw_cell;
+
+ float rgba[4], alpha, dist_nosqrt, dist;
+
+ float falloff;
+ int bucket_index;
+ int is_floatbuf = 0;
+ const short tool = ps->tool;
+ rctf bucket_bounds;
+
+ /* for smear only */
+ float pos_ofs[2] = {0};
+ float co[2];
+ float mask = 1.0f; /* airbrush wont use mask */
+ unsigned short mask_short;
+ const float radius = (float)BKE_brush_size_get(ps->scene, brush);
+ const float radius_squared = radius * 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;
+
+ LinkNode *smearPixels = NULL;
+ LinkNode *smearPixels_f = NULL;
+ MemArena *smearArena = NULL; /* mem arena for this brush projection only */
+
+ LinkNode *softenPixels = NULL;
+ LinkNode *softenPixels_f = NULL;
+ MemArena *softenArena = NULL; /* mem arena for this brush projection only */
+
+ if (tool == PAINT_TOOL_SMEAR) {
+ pos_ofs[0] = pos[0] - lastpos[0];
+ pos_ofs[1] = pos[1] - lastpos[1];
+
+ smearArena = BLI_memarena_new(1 << 16, "paint smear arena");
+ }
+ else if (tool == PAINT_TOOL_SOFTEN) {
+ softenArena = BLI_memarena_new(1 << 16, "paint soften arena");
+ }
+
+ /* printf("brush bounds %d %d %d %d\n", bucketMin[0], bucketMin[1], bucketMax[0], bucketMax[1]); */
+
+ while (project_bucket_iter_next(ps, &bucket_index, &bucket_bounds, pos)) {
+
+ /* Check this bucket and its faces are initialized */
+ if (ps->bucketFlags[bucket_index] == PROJ_BUCKET_NULL) {
+ /* No pixels initialized */
+ project_bucket_init(ps, thread_index, bucket_index, &bucket_bounds);
+ }
+
+ if (ps->source != PROJ_SRC_VIEW) {
+
+ /* Re-Projection, simple, no brushes! */
+
+ for (node = ps->bucketRect[bucket_index]; node; node = node->next) {
+ projPixel = (ProjPixel *)node->link;
+
+ /* copy of code below */
+ if (last_index != projPixel->image_index) {
+ last_index = projPixel->image_index;
+ last_projIma = projImages + last_index;
+
+ last_projIma->touch = 1;
+ is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0;
+ }
+ /* end copy */
+
+ if (is_floatbuf) {
+ /* re-project buffer is assumed byte - TODO, allow float */
+ bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL,
+ projPixel->projCoSS[0], projPixel->projCoSS[1]);
+ if (projPixel->newColor.ch[3]) {
+ mask = ((float)projPixel->mask) / 65535.0f;
+ blend_color_mix_accum_float(projPixel->pixel.f_pt, projPixel->origColor.f,
+ projPixel->newColor.ch, (mask * (projPixel->newColor.ch[3] / 255.0f)));
+ }
+ }
+ else {
+ /* re-project buffer is assumed byte - TODO, allow float */
+ bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL,
+ projPixel->projCoSS[0], projPixel->projCoSS[1]);
+ if (projPixel->newColor.ch[3]) {
+ mask = ((float)projPixel->mask) / 65535.0f;
+ blend_color_mix_accum(projPixel->pixel.ch_pt, projPixel->origColor.ch,
+ projPixel->newColor.ch, (int)(mask * projPixel->newColor.ch[3]));
+ }
+ }
+ }
+ }
+ else {
+ /* Normal brush painting */
+
+ for (node = ps->bucketRect[bucket_index]; node; node = node->next) {
+
+ projPixel = (ProjPixel *)node->link;
+
+ dist_nosqrt = len_squared_v2v2(projPixel->projCoSS, pos);
+
+ /*if (dist < radius) {*/ /* correct but uses a sqrtf */
+ if (dist_nosqrt <= radius_squared) {
+ float samplecos[3];
+ dist = sqrtf(dist_nosqrt);
+
+ falloff = BKE_brush_curve_strength_clamp(ps->brush, dist, radius);
+
+ if (ps->is_texbrush) {
+ MTex *mtex = &brush->mtex;
+ /* taking 3d copy to account for 3D mapping too. It gets concatenated during sampling */
+ if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
+ copy_v3_v3(samplecos, projPixel->worldCoSS);
+ }
+ else {
+ copy_v2_v2(samplecos, projPixel->projCoSS);
+ samplecos[2] = 0.0f;
+ }
+ }
+
+ if (falloff > 0.0f) {
+ if (ps->is_texbrush) {
+ /* note, for clone and smear, we only use the alpha, could be a special function */
+ BKE_brush_sample_tex_3D(ps->scene, brush, samplecos, rgba, thread_index, pool);
+ alpha = rgba[3];
+ }
+ else {
+ alpha = 1.0f;
+ }
+
+ if (!ps->do_masking) {
+ /* for an aurbrush there is no real mask, so just multiply the alpha by it */
+ alpha *= falloff * BKE_brush_alpha_get(ps->scene, brush);
+ mask = ((float)projPixel->mask) / 65535.0f;
+ }
+ else {
+ /* This brush dosnt accumulate so add some curve to the brushes falloff */
+ falloff = 1.0f - falloff;
+ falloff = 1.0f - (falloff * falloff);
+
+ mask_short = (unsigned short)(projPixel->mask * (BKE_brush_alpha_get(ps->scene, brush) * falloff));
+ if (mask_short > projPixel->mask_max) {
+ mask = ((float)mask_short) / 65535.0f;
+ projPixel->mask_max = mask_short;
+ }
+ else {
+ /*mask = ((float)projPixel->mask_max)/65535.0f;*/
+
+ /* Go onto the next pixel */
+ continue;
+ }
+ }
+
+ if (alpha > 0.0f) {
+
+ /* copy of code above */
+ if (last_index != projPixel->image_index) {
+ last_index = projPixel->image_index;
+ last_projIma = projImages + last_index;
+
+ last_projIma->touch = 1;
+ is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0;
+ }
+ /* end copy */
+
+ 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);
+
+
+ switch (tool) {
+ case PAINT_TOOL_CLONE:
+ if (is_floatbuf) {
+ if (((ProjPixelClone *)projPixel)->clonepx.f[3]) {
+ do_projectpaint_clone_f(ps, projPixel, alpha, mask); /* rgba isn't used for cloning, only alpha */
+ }
+ }
+ else {
+ if (((ProjPixelClone *)projPixel)->clonepx.ch[3]) {
+ do_projectpaint_clone(ps, projPixel, alpha, mask); /* rgba isn't used for cloning, only alpha */
+ }
+ }
+ break;
+ case PAINT_TOOL_SMEAR:
+ sub_v2_v2v2(co, projPixel->projCoSS, pos_ofs);
+
+ if (is_floatbuf) do_projectpaint_smear_f(ps, projPixel, alpha, mask, smearArena, &smearPixels_f, co);
+ else do_projectpaint_smear(ps, projPixel, alpha, mask, smearArena, &smearPixels, co);
+ break;
+ case PAINT_TOOL_SOFTEN:
+ if (is_floatbuf) do_projectpaint_soften_f(ps, projPixel, alpha, mask, softenArena, &softenPixels_f);
+ else do_projectpaint_soften(ps, projPixel, alpha, mask, softenArena, &softenPixels);
+ break;
+ default:
+ if (is_floatbuf) do_projectpaint_draw_f(ps, projPixel, rgba, alpha, mask);
+ else do_projectpaint_draw(ps, projPixel, rgba, alpha, mask);
+ break;
+ }
+ }
+
+ if (lock_alpha) {
+ if (is_floatbuf) projPixel->pixel.f_pt[3] = projPixel->origColor.f[3];
+ else projPixel->pixel.ch_pt[3] = projPixel->origColor.ch[3];
+ }
+
+ /* done painting */
+ }
+ }
+ }
+ }
+ }
+
+
+ if (tool == PAINT_TOOL_SMEAR) {
+
+ for (node = smearPixels; node; node = node->next) { /* this wont run for a float image */
+ projPixel = node->link;
+ *projPixel->pixel.uint_pt = ((ProjPixelClone *)projPixel)->clonepx.uint;
+ }
+
+ for (node = smearPixels_f; node; node = node->next) {
+ projPixel = node->link;
+ copy_v4_v4(projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.f);
+ }
+
+ BLI_memarena_free(smearArena);
+ }
+ else if (tool == PAINT_TOOL_SOFTEN) {
+
+ for (node = softenPixels; node; node = node->next) { /* this wont run for a float image */
+ projPixel = node->link;
+ *projPixel->pixel.uint_pt = projPixel->newColor.uint;
+ }
+
+ for (node = softenPixels_f; node; node = node->next) {
+ projPixel = node->link;
+ copy_v4_v4(projPixel->pixel.f_pt, projPixel->newColor.f);
+ }
+
+ BLI_memarena_free(softenArena);
+ }
+
+ return NULL;
+}
+
+static int project_paint_op(void *state, const float lastpos[2], const float pos[2])
+{
+ /* First unpack args from the struct */
+ ProjPaintState *ps = (ProjPaintState *)state;
+ int touch_any = 0;
+
+ ProjectHandle handles[BLENDER_MAX_THREADS];
+ ListBase threads;
+ int a, i;
+
+ struct ImagePool *pool;
+
+ if (!project_bucket_iter_init(ps, pos)) {
+ return 0;
+ }
+
+ if (ps->thread_tot > 1)
+ BLI_init_threads(&threads, do_projectpaint_thread, ps->thread_tot);
+
+ pool = BKE_image_pool_new();
+
+ /* get the threads running */
+ for (a = 0; a < ps->thread_tot; a++) {
+
+ /* set defaults in handles */
+ //memset(&handles[a], 0, sizeof(BakeShade));
+
+ handles[a].ps = ps;
+ copy_v2_v2(handles[a].mval, pos);
+ copy_v2_v2(handles[a].prevmval, lastpos);
+
+ /* thread specific */
+ handles[a].thread_index = a;
+
+ handles[a].projImages = (ProjPaintImage *)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);
+ memcpy(handles[a].projImages[i].partRedrawRect, ps->projImages[i].partRedrawRect, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ }
+
+ handles[a].pool = pool;
+
+ if (ps->thread_tot > 1)
+ BLI_insert_thread(&threads, &handles[a]);
+ }
+
+ if (ps->thread_tot > 1) /* wait for everything to be done */
+ BLI_end_threads(&threads);
+ else
+ do_projectpaint_thread(&handles[0]);
+
+
+ BKE_image_pool_free(pool);
+
+ /* move threaded bounds back into ps->projectPartialRedraws */
+ for (i = 0; i < ps->image_tot; i++) {
+ int touch = 0;
+ for (a = 0; a < ps->thread_tot; a++) {
+ touch |= partial_redraw_array_merge(ps->projImages[i].partRedrawRect, handles[a].projImages[i].partRedrawRect, PROJ_BOUNDBOX_SQUARED);
+ }
+
+ if (touch) {
+ ps->projImages[i].touch = 1;
+ touch_any = 1;
+ }
+ }
+
+ return touch_any;
+}
+
+
+int paint_proj_stroke(bContext *C, void *pps, const int prevmval_i[2], const int mval_i[2])
+{
+ ProjPaintState *ps = pps;
+ int a, redraw;
+ float pos[2], prev_pos[2];
+
+ pos[0] = (float)(mval_i[0]);
+ pos[1] = (float)(mval_i[1]);
+
+ prev_pos[0] = (float)(prevmval_i[0]);
+ prev_pos[1] = (float)(prevmval_i[1]);
+
+ /* clone gets special treatment here to avoid going through image initialization */
+ if (ps->tool == PAINT_TOOL_CLONE && ps->mode == BRUSH_STROKE_INVERT) {
+ Scene *scene = ps->scene;
+ View3D *v3d = ps->v3d;
+ float *cursor = give_cursor(scene, v3d);
+
+ view3d_operator_needs_opengl(C);
+
+ if (!ED_view3d_autodist(scene, ps->ar, v3d, mval_i, cursor, false))
+ return 0;
+
+ ED_region_tag_redraw(ps->ar);
+
+ return 0;
+ }
+
+ for (a = 0; a < ps->image_tot; a++)
+ partial_redraw_array_init(ps->projImages[a].partRedrawRect);
+
+ redraw = project_paint_op(ps, prev_pos, pos) ? 1 : 0;
+
+ if (project_image_refresh_tagged(ps))
+ return redraw;
+
+ return 0;
+}
+
+
+/* initialize project paint settings from context */
+static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int mode)
+{
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *settings = scene->toolsettings;
+
+ /* brush */
+ ps->mode = mode;
+ ps->brush = paint_brush(&settings->imapaint.paint);
+ if (ps->brush) {
+ Brush *brush = ps->brush;
+ ps->tool = brush->imagepaint_tool;
+ ps->blend = brush->blend;
+
+ /* disable for 3d mapping also because painting on mirrored mesh can create "stripes" */
+ ps->do_masking = (brush->flag & BRUSH_AIRBRUSH || brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW ||
+ brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) ? false : true;
+ ps->is_texbrush = (brush->mtex.tex && brush->imagepaint_tool == PAINT_TOOL_DRAW) ? 1 : 0;
+ }
+ else {
+ /* brush may be NULL*/
+ ps->do_masking = false;
+ ps->is_texbrush = false;
+ }
+
+ /* sizeof(ProjPixel), since we alloc this a _lot_ */
+ ps->pixel_sizeof = project_paint_pixel_sizeof(ps->tool);
+ BLI_assert(ps->pixel_sizeof >= sizeof(ProjPixel));
+
+ /* these can be NULL */
+ ps->v3d = CTX_wm_view3d(C);
+ ps->rv3d = CTX_wm_region_view3d(C);
+ ps->ar = CTX_wm_region(C);
+
+ ps->scene = scene;
+ ps->ob = ob; /* allow override of active object */
+
+ /* setup projection painting data */
+ ps->do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? 0 : 1;
+ ps->do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? 0 : 1;
+ ps->do_mask_normal = (settings->imapaint.flag & IMAGEPAINT_PROJECT_FLAT) ? 0 : 1;
+ ps->do_new_shading_nodes = BKE_scene_use_new_shading_nodes(scene); /* only cache the value */
+
+ if (ps->tool == PAINT_TOOL_CLONE)
+ ps->do_layer_clone = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE);
+
+ ps->do_layer_stencil = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) ? 1 : 0;
+ ps->do_layer_stencil_inv = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) ? 1 : 0;
+
+
+#ifndef PROJ_DEBUG_NOSEAMBLEED
+ ps->seam_bleed_px = settings->imapaint.seam_bleed; /* pixel num to bleed */
+#endif
+
+ if (ps->do_mask_normal) {
+ ps->normal_angle_inner = settings->imapaint.normal_angle;
+ ps->normal_angle = (ps->normal_angle_inner + 90.0f) * 0.5f;
+ }
+ else {
+ ps->normal_angle_inner = ps->normal_angle = settings->imapaint.normal_angle;
+ }
+
+ ps->normal_angle_inner *= (float)(M_PI_2 / 90);
+ ps->normal_angle *= (float)(M_PI_2 / 90);
+ ps->normal_angle_range = ps->normal_angle - ps->normal_angle_inner;
+
+ if (ps->normal_angle_range <= 0.0f)
+ ps->do_mask_normal = FALSE; /* no need to do blending */
+
+ return;
+}
+
+void *paint_proj_new_stroke(bContext *C, Object *ob, const int mouse[2], int mode)
+{
+ ProjPaintState *ps = MEM_callocN(sizeof(ProjPaintState), "ProjectionPaintState");
+ project_state_init(C, ob, ps, mode);
+
+ if (ps->tool == PAINT_TOOL_CLONE && mode == BRUSH_STROKE_INVERT) {
+ view3d_operator_needs_opengl(C);
+ return ps;
+ }
+
+ /* needed so multiple threads don't try to initialize the brush at once (can leak memory) */
+ curvemapping_initialize(ps->brush->curve);
+
+ paint_brush_init_tex(ps->brush);
+
+ ps->source = PROJ_SRC_VIEW;
+
+ if (ps->ob == NULL || !(ps->ob->lay & ps->v3d->lay)) {
+ MEM_freeN(ps);
+ return NULL;
+ }
+
+ ps->orig_brush_size = BKE_brush_size_get(ps->scene, ps->brush);
+
+ /* 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);
+
+ /* allocate and initialize spatial data structures */
+ project_paint_begin(ps);
+
+ if (ps->dm == NULL) {
+ MEM_freeN(ps);
+ return NULL;
+ }
+
+ paint_proj_begin_clone(ps, mouse);
+
+ return ps;
+}
+
+void paint_proj_stroke_done(void *pps)
+{
+ ProjPaintState *ps = pps;
+ if (ps->tool == PAINT_TOOL_CLONE && ps->mode == BRUSH_STROKE_INVERT) {
+ MEM_freeN(ps);
+ return;
+ }
+ BKE_brush_size_set(ps->scene, ps->brush, ps->orig_brush_size);
+
+ paint_brush_exit_tex(ps->brush);
+
+ project_paint_end(ps);
+ MEM_freeN(ps);
+}
+/* use project paint to re-apply an image */
+static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
+{
+ Image *image = BLI_findlink(&CTX_data_main(C)->image, RNA_enum_get(op->ptr, "image"));
+ Scene *scene = CTX_data_scene(C);
+ ProjPaintState ps = {NULL};
+ int orig_brush_size;
+ IDProperty *idgroup;
+ IDProperty *view_data = NULL;
+
+ project_state_init(C, OBACT, &ps, BRUSH_STROKE_NORMAL);
+
+ if (ps.ob == NULL || ps.ob->type != OB_MESH) {
+ BKE_report(op->reports, RPT_ERROR, "No active mesh object");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (image == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Image could not be found");
+ return OPERATOR_CANCELLED;
+ }
+
+ ps.reproject_image = image;
+ ps.reproject_ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
+
+ if (ps.reproject_ibuf == NULL || ps.reproject_ibuf->rect == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Image data could not be found");
+ return OPERATOR_CANCELLED;
+ }
+
+ idgroup = IDP_GetProperties(&image->id, 0);
+
+ if (idgroup) {
+ view_data = IDP_GetPropertyTypeFromGroup(idgroup, PROJ_VIEW_DATA_ID, IDP_ARRAY);
+
+ /* type check to make sure its ok */
+ if (view_data->len != PROJ_VIEW_DATA_SIZE || view_data->subtype != IDP_FLOAT) {
+ BKE_report(op->reports, RPT_ERROR, "Image project data invalid");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ if (view_data) {
+ /* image has stored view projection info */
+ ps.source = PROJ_SRC_IMAGE_VIEW;
+ }
+ else {
+ ps.source = PROJ_SRC_IMAGE_CAM;
+
+ if (scene->camera == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active camera set");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ /* override */
+ ps.is_texbrush = 0;
+ 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 */
+
+ ps.tool = PAINT_TOOL_DRAW; /* so pixels are initialized with minimal info */
+
+ scene->toolsettings->imapaint.flag |= IMAGEPAINT_DRAWING;
+
+ undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
+ image_undo_restore, image_undo_free);
+
+ /* allocate and initialize spatial data structures */
+ project_paint_begin(&ps);
+
+ if (ps.dm == NULL) {
+ BKE_brush_size_set(scene, ps.brush, orig_brush_size);
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ float pos[2] = {0.0, 0.0};
+ float lastpos[2] = {0.0, 0.0};
+ int a;
+
+ for (a = 0; a < ps.image_tot; a++)
+ partial_redraw_array_init(ps.projImages[a].partRedrawRect);
+
+ project_paint_op(&ps, lastpos, pos);
+
+ project_image_refresh_tagged(&ps);
+
+ for (a = 0; a < ps.image_tot; a++) {
+ GPU_free_image(ps.projImages[a].ima);
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ps.projImages[a].ima);
+ }
+ }
+
+ project_paint_end(&ps);
+
+ scene->toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
+ BKE_brush_size_set(scene, ps.brush, orig_brush_size);
+
+ return OPERATOR_FINISHED;
+}
+
+void PAINT_OT_project_image(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Project Image";
+ ot->idname = "PAINT_OT_project_image";
+ ot->description = "Project an edited render from the active camera back onto the object";
+
+ /* api callbacks */
+ ot->invoke = WM_enum_search_invoke;
+ ot->exec = texture_paint_camera_project_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_enum(ot->srna, "image", DummyRNA_NULL_items, 0, "Image", "");
+ RNA_def_enum_funcs(prop, RNA_image_itemf);
+ ot->prop = prop;
+}
+
+static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
+{
+ Image *image;
+ ImBuf *ibuf;
+ char filename[FILE_MAX];
+
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *settings = scene->toolsettings;
+ int w = settings->imapaint.screen_grab_size[0];
+ int h = settings->imapaint.screen_grab_size[1];
+ int maxsize;
+ char err_out[256] = "unknown";
+
+ RNA_string_get(op->ptr, "filepath", filename);
+
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
+
+ if (w > maxsize) w = maxsize;
+ if (h > maxsize) h = maxsize;
+
+ ibuf = ED_view3d_draw_offscreen_imbuf(CTX_data_scene(C), CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, FALSE, R_ALPHAPREMUL, 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 */
+ BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer: %s", err_out);
+ return OPERATOR_CANCELLED;
+ }
+
+ image = BKE_image_add_from_imbuf(ibuf);
+
+ if (image) {
+ /* now for the trickyness. store the view projection here!
+ * re-projection will reuse this */
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+
+ IDPropertyTemplate val;
+ IDProperty *idgroup = IDP_GetProperties(&image->id, 1);
+ IDProperty *view_data;
+ bool is_ortho;
+ float *array;
+
+ val.array.len = PROJ_VIEW_DATA_SIZE;
+ val.array.type = IDP_FLOAT;
+ view_data = IDP_New(IDP_ARRAY, &val, PROJ_VIEW_DATA_ID);
+
+ array = (float *)IDP_Array(view_data);
+ 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 */
+
+ IDP_AddToGroup(idgroup, view_data);
+
+ rename_id(&image->id, "image_view");
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void PAINT_OT_image_from_view(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Image from View";
+ ot->idname = "PAINT_OT_image_from_view";
+ ot->description = "Make an image from the current 3D view for re-projection";
+
+ /* api callbacks */
+ ot->exec = texture_paint_image_from_view_exec;
+ ot->poll = ED_operator_region_view3d_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
+
+ RNA_def_string_file_name(ot->srna, "filepath", "", FILE_MAX, "File Path", "Name of the file");
+}
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 162e2fa15d6..a15795dc2da 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -36,6 +36,7 @@ struct ARegion;
struct bContext;
struct bglMats;
struct Brush;
+struct ImagePool;
struct ListBase;
struct Mesh;
struct Object;
@@ -49,6 +50,8 @@ struct ViewContext;
struct wmEvent;
struct wmOperator;
struct wmOperatorType;
+struct ImagePaintState;
+enum PaintMode;
/* paint_stroke.c */
typedef int (*StrokeGetLocation)(struct bContext *C, float location[3], const float mouse[2]);
@@ -61,10 +64,14 @@ struct PaintStroke *paint_stroke_new(struct bContext *C,
StrokeUpdateStep update_step, StrokeDone done, int event_type);
void paint_stroke_data_free(struct wmOperator *op);
-int paint_space_stroke_enabled(struct Brush *br);
+bool paint_space_stroke_enabled(struct Brush *br, enum PaintMode mode);
+bool paint_supports_dynamic_size(struct Brush *br, enum PaintMode mode);
+bool paint_supports_dynamic_tex_coords(struct Brush *br, enum PaintMode mode);
+bool paint_supports_smooth_stroke(struct Brush *br, enum PaintMode mode);
+bool paint_supports_jitter(enum PaintMode mode);
struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf);
-int paint_stroke_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
+int paint_stroke_modal(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
int paint_stroke_exec(struct bContext *C, struct wmOperator *op);
int paint_stroke_cancel(struct bContext *C, struct wmOperator *op);
struct ViewContext *paint_stroke_view_context(struct PaintStroke *stroke);
@@ -89,22 +96,58 @@ void PAINT_OT_weight_from_bones(struct wmOperatorType *ot);
void PAINT_OT_weight_sample(struct wmOperatorType *ot);
void PAINT_OT_weight_sample_group(struct wmOperatorType *ot);
+enum {
+ WPAINT_GRADIENT_TYPE_LINEAR,
+ WPAINT_GRADIENT_TYPE_RADIAL
+};
+void PAINT_OT_weight_gradient(struct wmOperatorType *ot);
+
void PAINT_OT_vertex_paint_toggle(struct wmOperatorType *ot);
void PAINT_OT_vertex_paint(struct wmOperatorType *ot);
unsigned int vpaint_get_current_col(struct VPaint *vp);
/* paint_image.c */
+typedef struct ImagePaintPartialRedraw {
+ int x1, y1, x2, y2; /* XXX, could use 'rcti' */
+ int enabled;
+} ImagePaintPartialRedraw;
+
+#define IMAPAINT_TILE_BITS 6
+#define IMAPAINT_TILE_SIZE (1 << IMAPAINT_TILE_BITS)
+#define IMAPAINT_TILE_NUMBER(size) (((size) + IMAPAINT_TILE_SIZE - 1) >> IMAPAINT_TILE_BITS)
+
+#define IMAPAINT_CHAR_TO_FLOAT(c) ((c) / 255.0f)
+
int image_texture_paint_poll(struct bContext *C);
+void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile);
+void image_undo_restore(struct bContext *C, struct ListBase *lb);
+void image_undo_free(struct ListBase *lb);
+void imapaint_image_update(struct SpaceImage *sima, struct Image *image, struct ImBuf *ibuf, short texpaint);
+struct ImagePaintPartialRedraw *get_imapaintpartial(void);
+void set_imapaintpartial(struct ImagePaintPartialRedraw * ippr);
+void imapaint_clear_partial_redraw(void);
+void imapaint_dirty_region(struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h);
+int get_imapaint_zoom(struct bContext *C, float *zoomx, float *zoomy);
+void *paint_2d_new_stroke(struct bContext *, struct wmOperator *);
+void paint_2d_redraw(const bContext *C, void *ps, int final);
+void paint_2d_stroke_done(void *ps);
+int paint_2d_stroke(void *ps, const int prev_mval[2], const int mval[2], int eraser);
+void *paint_proj_new_stroke(struct bContext *C, struct Object *ob, const int mouse[2], int mode);
+int paint_proj_stroke(struct bContext *C, void *ps, const int prevmval_i[2], const int mval_i[2]);
+void paint_proj_stroke_done(void *ps);
+void paint_brush_init_tex(struct Brush *brush);
+void paint_brush_exit_tex(struct Brush *brush);
-void PAINT_OT_image_paint(struct wmOperatorType *ot);
void PAINT_OT_grab_clone(struct wmOperatorType *ot);
void PAINT_OT_sample_color(struct wmOperatorType *ot);
-void PAINT_OT_clone_cursor_set(struct wmOperatorType *ot);
void PAINT_OT_texture_paint_toggle(struct wmOperatorType *ot);
void PAINT_OT_project_image(struct wmOperatorType *ot);
void PAINT_OT_image_from_view(struct wmOperatorType *ot);
+/* new texture painting */
+void PAINT_OT_image_paint(struct wmOperatorType *ot);
+
/* uv sculpting */
int uv_sculpt_poll(struct bContext *C);
@@ -133,9 +176,10 @@ void paint_calc_redraw_planes(float planes[4][4],
void projectf(struct bglMats *mats, const float v[3], float p[2]);
float paint_calc_object_space_radius(struct ViewContext *vc, const float center[3], float pixel_radius);
-float paint_get_tex_pixel(struct Brush *br, float u, float v);
+float paint_get_tex_pixel(struct Brush *br, float u, float v, struct ImagePool *pool);
int imapaint_pick_face(struct ViewContext *vc, const int mval[2], unsigned int *index, unsigned int totface);
void imapaint_pick_uv(struct Scene *scene, struct Object *ob, unsigned int faceindex, const int xy[2], float uv[2]);
+void brush_drawcursor_texpaint_uvsculpt(struct bContext *C, int x, int y, void *customdata);
void paint_sample_color(const struct bContext *C, struct ARegion *ar, int x, int y);
void BRUSH_OT_curve_preset(struct wmOperatorType *ot);
@@ -143,12 +187,11 @@ void BRUSH_OT_curve_preset(struct wmOperatorType *ot);
void PAINT_OT_face_select_linked(struct wmOperatorType *ot);
void PAINT_OT_face_select_linked_pick(struct wmOperatorType *ot);
void PAINT_OT_face_select_all(struct wmOperatorType *ot);
-void PAINT_OT_face_select_inverse(struct wmOperatorType *ot);
void PAINT_OT_face_select_hide(struct wmOperatorType *ot);
void PAINT_OT_face_select_reveal(struct wmOperatorType *ot);
void PAINT_OT_vert_select_all(struct wmOperatorType *ot);
-void PAINT_OT_vert_select_inverse(struct wmOperatorType *ot);
+void PAINT_OT_vert_select_ungrouped(struct wmOperatorType *ot);
int vert_paint_poll(struct bContext *C);
int mask_paint_poll(struct bContext *C);
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index 697d7c63d1f..e0b3905b30f 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -38,8 +38,8 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "BLI_pbvh.h"
-
+#include "BLI_utildefines.h"
+#include "BKE_pbvh.h"
#include "BKE_ccg.h"
#include "BKE_context.h"
#include "BKE_DerivedMesh.h"
@@ -97,7 +97,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
pbvh = dm->getPBVH(ob, dm);
ob->sculpt->pbvh = pbvh;
- BLI_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
+ BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
sculpt_undo_push_begin("Mask flood fill");
@@ -106,12 +106,12 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
sculpt_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK);
- BLI_pbvh_vertex_iter_begin(pbvh, nodes[i], vi, PBVH_ITER_UNIQUE) {
+ BKE_pbvh_vertex_iter_begin(pbvh, nodes[i], vi, PBVH_ITER_UNIQUE) {
mask_flood_fill_set_elem(vi.mask, mode, value);
- } BLI_pbvh_vertex_iter_end;
+ } BKE_pbvh_vertex_iter_end;
- BLI_pbvh_node_mark_update(nodes[i]);
- if (BLI_pbvh_type(pbvh) == PBVH_GRIDS)
+ BKE_pbvh_node_mark_update(nodes[i]);
+ if (BKE_pbvh_type(pbvh) == PBVH_GRIDS)
multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
}
@@ -128,13 +128,14 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
void PAINT_OT_mask_flood_fill(struct wmOperatorType *ot)
{
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, "VALUE", 0, "Value", "Set mask to the level specified by the 'value' property"},
{PAINT_MASK_INVERT, "INVERT", 0, "Invert", "Invert the mask"},
{0}};
/* identifiers */
ot->name = "Mask Flood Fill";
ot->idname = "PAINT_OT_mask_flood_fill";
+ ot->description = "Fill the whole mask with a given value, or invert its values";
/* api callbacks */
ot->exec = mask_flood_fill_exec;
@@ -144,5 +145,6 @@ void PAINT_OT_mask_flood_fill(struct wmOperatorType *ot)
/* rna */
RNA_def_enum(ot->srna, "mode", mode_items, PAINT_MASK_FLOOD_VALUE, "Mode", NULL);
- RNA_def_float(ot->srna, "value", 0, 0, 1, "Value", "Mask level to use when mode is \"Value\"; zero means no masking and one is fully masked", 0, 1);
+ RNA_def_float(ot->srna, "value", 0, 0, 1, "Value",
+ "Mask level to use when mode is 'Value'; zero means no masking and one is fully masked", 0, 1);
}
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index 40dcb92f087..120d0a3b10a 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -62,11 +62,12 @@ static int brush_add_exec(bContext *C, wmOperator *UNUSED(op))
/*int type = RNA_enum_get(op->ptr, "type");*/
Paint *paint = paint_get_active_from_context(C);
struct Brush *br = paint_brush(paint);
+ Main *bmain = CTX_data_main(C);
if (br)
br = BKE_brush_copy(br);
else
- br = BKE_brush_add("Brush");
+ br = BKE_brush_add(bmain, "Brush");
paint_brush_set(paint, br);
@@ -272,7 +273,7 @@ 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(tool_name);
+ brush = BKE_brush_add(bmain, tool_name);
brush_tool_set(brush, tool_offset, tool);
brush->ob_mode = ob_mode;
brush->toggle_brush = brush_orig;
@@ -466,7 +467,6 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(PAINT_OT_image_paint);
WM_operatortype_append(PAINT_OT_sample_color);
WM_operatortype_append(PAINT_OT_grab_clone);
- WM_operatortype_append(PAINT_OT_clone_cursor_set);
WM_operatortype_append(PAINT_OT_project_image);
WM_operatortype_append(PAINT_OT_image_from_view);
@@ -475,6 +475,7 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(PAINT_OT_weight_paint);
WM_operatortype_append(PAINT_OT_weight_set);
WM_operatortype_append(PAINT_OT_weight_from_bones);
+ WM_operatortype_append(PAINT_OT_weight_gradient);
WM_operatortype_append(PAINT_OT_weight_sample);
WM_operatortype_append(PAINT_OT_weight_sample_group);
@@ -483,7 +484,7 @@ void ED_operatortypes_paint(void)
/* vertex selection */
WM_operatortype_append(PAINT_OT_vert_select_all);
- WM_operatortype_append(PAINT_OT_vert_select_inverse);
+ WM_operatortype_append(PAINT_OT_vert_select_ungrouped);
/* vertex */
WM_operatortype_append(PAINT_OT_vertex_paint_toggle);
@@ -494,7 +495,6 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(PAINT_OT_face_select_linked);
WM_operatortype_append(PAINT_OT_face_select_linked_pick);
WM_operatortype_append(PAINT_OT_face_select_all);
- WM_operatortype_append(PAINT_OT_face_select_inverse);
WM_operatortype_append(PAINT_OT_face_select_hide);
WM_operatortype_append(PAINT_OT_face_select_reveal);
@@ -533,7 +533,7 @@ static void ed_keymap_paint_brush_size(wmKeyMap *keymap, const char *UNUSED(path
typedef enum {
RC_COLOR = 1,
RC_ROTATION = 2,
- RC_ZOOM = 4,
+ RC_ZOOM = 4
} RCFlags;
static void set_brush_rc_path(PointerRNA *ptr, const char *brush_path,
@@ -647,6 +647,17 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "PAINT_OT_mask_flood_fill", IKEY, KM_PRESS, KM_CTRL, 0);
RNA_enum_set(kmi->ptr, "mode", PAINT_MASK_INVERT);
+ /* Toggle dynamic topology */
+ WM_keymap_add_item(keymap, "SCULPT_OT_dynamic_topology_toggle", DKEY, KM_PRESS, KM_CTRL, 0);
+
+ /* Dynamic-topology detail size
+ *
+ * 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");
+
/* multires switch */
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_subdivision_set", PAGEUPKEY, KM_PRESS, 0, 0);
RNA_int_set(kmi->ptr, "level", 1);
@@ -669,6 +680,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
keymap_brush_select(keymap, OB_MODE_SCULPT, SCULPT_TOOL_FLATTEN, TKEY, KM_SHIFT);
keymap_brush_select(keymap, OB_MODE_SCULPT, SCULPT_TOOL_CLAY, CKEY, 0);
keymap_brush_select(keymap, OB_MODE_SCULPT, SCULPT_TOOL_CREASE, CKEY, KM_SHIFT);
+ keymap_brush_select(keymap, OB_MODE_SCULPT, SCULPT_TOOL_SNAKE_HOOK, KKEY, 0);
kmi = keymap_brush_select(keymap, OB_MODE_SCULPT, SCULPT_TOOL_MASK, MKEY, 0);
RNA_boolean_set(kmi->ptr, "toggle", 1);
RNA_boolean_set(kmi->ptr, "create_missing", 1);
@@ -695,11 +707,17 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
ed_keymap_paint_brush_switch(keymap, "vertex_paint");
ed_keymap_paint_brush_size(keymap, "tool_settings.vertex_paint.brush.size");
- ed_keymap_paint_brush_radial_control(keymap, "vertex_paint", RC_COLOR);
+ ed_keymap_paint_brush_radial_control(keymap, "vertex_paint", RC_COLOR | RC_ROTATION);
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", MKEY, KM_PRESS, 0, 0); /* mask toggle */
RNA_string_set(kmi->ptr, "data_path", "vertex_paint_object.data.use_paint_mask");
+ 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");
+
/* Weight Paint mode */
keymap = WM_keymap_find(keyconf, "Weight Paint", 0, 0);
keymap->poll = weight_paint_mode_poll;
@@ -707,8 +725,11 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "PAINT_OT_weight_paint", LEFTMOUSE, KM_PRESS, 0, 0);
/* these keys are from 2.4x but could be changed */
- WM_keymap_verify_item(keymap, "PAINT_OT_weight_sample", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
- WM_keymap_verify_item(keymap, "PAINT_OT_weight_sample_group", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_verify_item(keymap, "PAINT_OT_weight_sample", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_verify_item(keymap, "PAINT_OT_weight_sample_group", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0);
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_weight_gradient", LEFTMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "type", WPAINT_GRADIENT_TYPE_LINEAR);
+ RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_weight_gradient", LEFTMOUSE, KM_PRESS, KM_ALT | KM_CTRL, 0)->ptr, "type", WPAINT_GRADIENT_TYPE_RADIAL);
WM_keymap_add_item(keymap,
"PAINT_OT_weight_set", KKEY, KM_PRESS, KM_SHIFT, 0);
@@ -726,12 +747,15 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "PAINT_OT_weight_from_bones", WKEY, KM_PRESS, 0, 0);
-
+ 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.weight_paint.brush.use_smooth_stroke");
+
/*Weight paint's Vertex Selection Mode */
keymap = WM_keymap_find(keyconf, "Weight Paint Vertex Selection", 0, 0);
keymap->poll = vert_paint_poll;
WM_keymap_add_item(keymap, "PAINT_OT_vert_select_all", AKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "PAINT_OT_vert_select_inverse", IKEY, KM_PRESS, KM_CTRL, 0);
+ kmi = WM_keymap_add_item(keymap, "PAINT_OT_vert_select_all", IKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_enum_set(kmi->ptr, "action", SEL_INVERT);
WM_keymap_add_item(keymap, "VIEW3D_OT_select_border", BKEY, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "deselect", FALSE);
@@ -743,24 +767,31 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
keymap = WM_keymap_find(keyconf, "Image Paint", 0, 0);
keymap->poll = image_texture_paint_poll;
- WM_keymap_add_item(keymap, "PAINT_OT_image_paint", LEFTMOUSE, KM_PRESS, 0, 0);
+ RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_image_paint", LEFTMOUSE, KM_PRESS, 0, 0)->ptr, "mode", BRUSH_STROKE_NORMAL);
+ RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_image_paint", LEFTMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "mode", BRUSH_STROKE_INVERT);
WM_keymap_add_item(keymap, "PAINT_OT_grab_clone", RIGHTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "PAINT_OT_sample_color", RIGHTMOUSE, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "PAINT_OT_clone_cursor_set", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
ed_keymap_paint_brush_switch(keymap, "image_paint");
ed_keymap_paint_brush_size(keymap, "tool_settings.image_paint.brush.size");
- ed_keymap_paint_brush_radial_control(keymap, "image_paint", RC_COLOR | RC_ZOOM);
+ ed_keymap_paint_brush_radial_control(keymap, "image_paint", RC_COLOR | RC_ZOOM | RC_ROTATION);
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", MKEY, KM_PRESS, 0, 0); /* mask toggle */
RNA_string_set(kmi->ptr, "data_path", "image_paint_object.data.use_paint_mask");
+ 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");
+
/* face-mask mode */
keymap = WM_keymap_find(keyconf, "Face Mask", 0, 0);
keymap->poll = facemask_paint_poll;
WM_keymap_add_item(keymap, "PAINT_OT_face_select_all", AKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "PAINT_OT_face_select_inverse", IKEY, KM_PRESS, KM_CTRL, 0);
+ kmi = WM_keymap_add_item(keymap, "PAINT_OT_face_select_all", IKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_enum_set(kmi->ptr, "action", SEL_INVERT);
kmi = WM_keymap_add_item(keymap, "PAINT_OT_face_select_hide", HKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "unselected", FALSE);
kmi = WM_keymap_add_item(keymap, "PAINT_OT_face_select_hide", HKEY, KM_PRESS, KM_SHIFT, 0);
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 9ebeb61a7bb..8c5552f48bc 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -35,6 +35,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLI_rand.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -91,6 +92,12 @@ typedef struct PaintStroke {
/* event that started stroke, for modal() return */
int event_type;
+ bool brush_init;
+ float initial_mouse[2];
+ float cached_pressure;
+
+ float zoom_2d;
+
StrokeGetLocation get_location;
StrokeTestStart test_start;
StrokeUpdateStep update_step;
@@ -104,29 +111,27 @@ static void paint_draw_smooth_stroke(bContext *C, int x, int y, void *customdata
Brush *brush = paint_brush(paint);
PaintStroke *stroke = customdata;
- glColor4ubv(paint->paint_cursor_col);
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
-
if (stroke && brush && (brush->flag & BRUSH_SMOOTH_STROKE)) {
- ARegion *ar = CTX_wm_region(C);
- sdrawline(x, y, (int)stroke->last_mouse_position[0] - ar->winrct.xmin,
- (int)stroke->last_mouse_position[1] - ar->winrct.ymin);
+ glColor4ubv(paint->paint_cursor_col);
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+
+ sdrawline(x, y, (int)stroke->last_mouse_position[0],
+ (int)stroke->last_mouse_position[1]);
+ glDisable(GL_BLEND);
+ glDisable(GL_LINE_SMOOTH);
}
-
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
}
/* if this is a tablet event, return tablet pressure and set *pen_flip
* to 1 if the eraser tool is being used, 0 otherwise */
-static float event_tablet_data(wmEvent *event, int *pen_flip)
+static float event_tablet_data(const wmEvent *event, int *pen_flip)
{
int erasor = 0;
float pressure = 1;
- if (event->custom == EVT_DATA_TABLET) {
- wmTabletData *wmtab = event->customdata;
+ if (event->tablet_data) {
+ wmTabletData *wmtab = event->tablet_data;
erasor = (wmtab->Active == EVT_TABLET_ERASER);
pressure = (wmtab->Active != EVT_TABLET_NONE) ? wmtab->Pressure : 1;
@@ -138,11 +143,105 @@ static float event_tablet_data(wmEvent *event, int *pen_flip)
return pressure;
}
+
+/* Initialize the stroke cache variants from operator properties */
+static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
+ struct PaintStroke *stroke,
+ const float mouse[2], float pressure)
+{
+ Scene *scene = CTX_data_scene(C);
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+
+ /* 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.
+ * 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, mode) || !stroke->brush_init) {
+ copy_v2_v2(stroke->initial_mouse, mouse);
+ copy_v2_v2(ups->tex_mouse, mouse);
+ stroke->cached_pressure = pressure;
+ }
+
+ /* Truly temporary data that isn't stored in properties */
+
+ ups->draw_pressure = TRUE;
+ ups->pressure_value = stroke->cached_pressure;
+
+ ups->pixel_radius = BKE_brush_size_get(scene, brush);
+
+ if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, mode)) {
+ ups->pixel_radius *= stroke->cached_pressure;
+ }
+
+ if (!(brush->flag & BRUSH_ANCHORED ||
+ ELEM4(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK,
+ SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE)))
+ {
+ copy_v2_v2(ups->tex_mouse, mouse);
+
+ if ((brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) &&
+ (brush->flag & BRUSH_RANDOM_ROTATION) &&
+ !(brush->flag & BRUSH_RAKE))
+ {
+ ups->brush_rotation = 2.0f * (float)M_PI * BLI_frand();
+ }
+ }
+
+ if (brush->flag & BRUSH_ANCHORED) {
+ bool hit = false;
+ float halfway[2];
+
+ const float dx = mouse[0] - stroke->initial_mouse[0];
+ const float dy = mouse[1] - stroke->initial_mouse[1];
+
+ ups->anchored_size = ups->pixel_radius = sqrt(dx * dx + dy * dy);
+
+ ups->brush_rotation = atan2(dx, dy) + M_PI;
+
+ if (brush->flag & BRUSH_EDGE_TO_EDGE) {
+ float out[3];
+
+ halfway[0] = dx * 0.5f + stroke->initial_mouse[0];
+ halfway[1] = dy * 0.5f + stroke->initial_mouse[1];
+
+ if (stroke->get_location) {
+ if (stroke->get_location(C, out, halfway)) {
+ hit = true;
+ }
+ }
+ else {
+ hit = true;
+ }
+ }
+ if (hit) {
+ copy_v2_v2(ups->anchored_initial_mouse, halfway);
+ copy_v2_v2(ups->tex_mouse, halfway);
+ ups->anchored_size /= 2.0f;
+ ups->pixel_radius /= 2.0f;
+ }
+ else
+ copy_v2_v2(ups->anchored_initial_mouse, stroke->initial_mouse);
+
+ ups->draw_anchored = 1;
+ }
+ else if (brush->flag & BRUSH_RAKE) {
+ if (!stroke->brush_init)
+ copy_v2_v2(ups->last_rake, mouse);
+ else
+ paint_calculate_rake_rotation(ups, mouse);
+ }
+
+ stroke->brush_init = TRUE;
+}
+
+
/* Put the location of the next stroke dot into the stroke RNA and apply it to the mesh */
-static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *event, const float mouse_in[2])
+static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const wmEvent *event, const float mouse_in[2])
{
Scene *scene = CTX_data_scene(C);
Paint *paint = paint_get_active_from_context(C);
+ PaintMode mode = paintmode_get_active_from_context(C);
Brush *brush = paint_brush(paint);
PaintStroke *stroke = op->customdata;
float mouse_out[2];
@@ -154,19 +253,45 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *ev
/* see if tablet affects event */
pressure = event_tablet_data(event, &pen_flip);
+/* the following code is adapted from texture paint. It may not be needed but leaving here
+ * just in case for reference (code in texpaint removed as part of refactoring).
+ * It's strange that only texpaint had these guards. */
+#if 0
+ /* special exception here for too high pressure values on first touch in
+ * windows for some tablets, then we just skip first touch .. */
+ if (tablet && (pressure >= 0.99f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || BKE_brush_use_alpha_pressure(scene, pop->s.brush) || BKE_brush_use_size_pressure(scene, pop->s.brush)))
+ return;
+
+ /* This can be removed once fixed properly in
+ * BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user)
+ * at zero pressure we should do nothing 1/2^12 is 0.0002 which is the sensitivity of the most sensitive pen tablet available */
+ if (tablet && (pressure < 0.0002f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || BKE_brush_use_alpha_pressure(scene, pop->s.brush) || BKE_brush_use_size_pressure(scene, pop->s.brush)))
+ return;
+#endif
+
+ /* copy last position -before- jittering, or space fill code
+ * will create too many dabs */
+ copy_v2_v2(stroke->last_mouse_position, mouse_in);
+
+ paint_brush_update(C, brush, mode, stroke, mouse_in, pressure);
+
/* TODO: as sculpt and other paint modes are unified, this
* separation will go away */
- if (stroke->vc.obact->sculpt) {
+ if (paint_supports_jitter(mode)) {
float delta[2];
+ float factor = stroke->zoom_2d;
+
+ if (brush->flag & BRUSH_JITTER_PRESSURE)
+ factor *= pressure;
BKE_brush_jitter_pos(scene, brush, mouse_in, mouse_out);
/* XXX: meh, this is round about because
* BKE_brush_jitter_pos isn't written in the best way to
* be reused here */
- if (brush->flag & BRUSH_JITTER_PRESSURE) {
+ if (factor != 1.0f) {
sub_v2_v2v2(delta, mouse_out, mouse_in);
- mul_v2_fl(delta, pressure);
+ mul_v2_fl(delta, factor);
add_v2_v2v2(mouse_out, mouse_in, delta);
}
}
@@ -188,34 +313,25 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *ev
RNA_boolean_set(&itemptr, "pen_flip", pen_flip);
RNA_float_set(&itemptr, "pressure", pressure);
- copy_v2_v2(stroke->last_mouse_position, mouse_out);
-
stroke->update_step(C, stroke, &itemptr);
}
/* Returns zero if no sculpt changes should be made, non-zero otherwise */
static int paint_smooth_stroke(PaintStroke *stroke, float output[2],
- const PaintSample *sample)
+ const PaintSample *sample, PaintMode mode)
{
output[0] = sample->mouse[0];
output[1] = sample->mouse[1];
- if ((stroke->brush->flag & BRUSH_SMOOTH_STROKE) &&
- !ELEM4(stroke->brush->sculpt_tool,
- SCULPT_TOOL_GRAB,
- SCULPT_TOOL_THUMB,
- SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_SNAKE_HOOK) &&
- !(stroke->brush->flag & BRUSH_ANCHORED) &&
- !(stroke->brush->flag & BRUSH_RESTORE_MESH))
- {
+ if (paint_supports_smooth_stroke(stroke->brush, mode)) {
+ float radius = stroke->brush->smooth_stroke_radius * stroke->zoom_2d;
float u = stroke->brush->smooth_stroke_factor, v = 1.0f - u;
float dx = stroke->last_mouse_position[0] - sample->mouse[0];
float dy = stroke->last_mouse_position[1] - sample->mouse[1];
/* If the mouse is moving within the radius of the last move,
* don't update the mouse position. This allows sharp turns. */
- if (dx * dx + dy * dy < stroke->brush->smooth_stroke_radius * stroke->brush->smooth_stroke_radius)
+ if (dx * dx + dy * dy < radius * radius)
return 0;
output[0] = sample->mouse[0] * v + stroke->last_mouse_position[0] * u;
@@ -227,12 +343,14 @@ static int paint_smooth_stroke(PaintStroke *stroke, float output[2],
/* For brushes with stroke spacing enabled, moves mouse in steps
* towards the final mouse location. */
-static int paint_space_stroke(bContext *C, wmOperator *op, wmEvent *event, const float final_mouse[2])
+static int paint_space_stroke(bContext *C, wmOperator *op, const wmEvent *event, const float final_mouse[2])
{
PaintStroke *stroke = op->customdata;
+ PaintMode mode = paintmode_get_active_from_context(C);
+
int cnt = 0;
- if (paint_space_stroke_enabled(stroke->brush)) {
+ if (paint_space_stroke_enabled(stroke->brush, mode)) {
float mouse[2];
float vec[2];
float length, scale;
@@ -246,17 +364,28 @@ static int paint_space_stroke(bContext *C, wmOperator *op, wmEvent *event, const
const Scene *scene = CTX_data_scene(C);
int steps;
int i;
- float pressure = 1.0f;
+ float size_pressure = 1.0f;
+ float pressure = event_tablet_data(event, NULL);
/* XXX mysterious :) what has 'use size' do with this here... if you don't check for it, pressure fails */
if (BKE_brush_use_size_pressure(scene, stroke->brush))
- pressure = event_tablet_data(event, NULL);
+ size_pressure = pressure;
- if (pressure > FLT_EPSILON) {
+ if (size_pressure > FLT_EPSILON) {
/* brushes can have a minimum size of 1.0 but with pressure it can be smaller then a pixel
* causing very high step sizes, hanging blender [#32381] */
- const float size_clamp = max_ff(1.0f, BKE_brush_size_get(scene, stroke->brush) * pressure);
- scale = (size_clamp * stroke->brush->spacing / 50.0f) / length;
+ const float size_clamp = max_ff(1.0f, BKE_brush_size_get(scene, stroke->brush) * size_pressure);
+ float spacing = stroke->brush->spacing;
+
+ /* stroke system is used for 2d paint too, so we need to account for
+ * the fact that brush can be scaled there. */
+
+ if (stroke->brush->flag & BRUSH_SPACING_PRESSURE)
+ spacing = max_ff(1.0f, spacing * (1.5f - pressure));
+
+ spacing *= stroke->zoom_2d;
+
+ scale = (size_clamp * spacing / 50.0f) / length;
if (scale > FLT_EPSILON) {
mul_v2_fl(vec, scale);
@@ -286,7 +415,8 @@ PaintStroke *paint_stroke_new(bContext *C,
stroke->brush = paint_brush(paint_get_active_from_context(C));
view3d_set_viewcontext(C, &stroke->vc);
- view3d_get_transformation(stroke->vc.ar, stroke->vc.rv3d, stroke->vc.obact, &stroke->mats);
+ if (stroke->vc.v3d)
+ view3d_get_transformation(stroke->vc.ar, stroke->vc.rv3d, stroke->vc.obact, &stroke->mats);
stroke->get_location = get_location;
stroke->test_start = test_start;
@@ -324,11 +454,77 @@ static void stroke_done(struct bContext *C, struct wmOperator *op)
}
/* Returns zero if the stroke dots should not be spaced, non-zero otherwise */
-int paint_space_stroke_enabled(Brush *br)
+bool paint_space_stroke_enabled(Brush *br, PaintMode mode)
{
- return (br->flag & BRUSH_SPACE) &&
- !(br->flag & BRUSH_ANCHORED) &&
- !ELEM4(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_SNAKE_HOOK);
+ return (br->flag & BRUSH_SPACE) && paint_supports_dynamic_size(br, mode);
+}
+
+/* return true if the brush size can change during paint (normally used for pressure) */
+bool paint_supports_dynamic_size(Brush *br, PaintMode mode)
+{
+ if (br->flag & BRUSH_ANCHORED)
+ return false;
+
+ switch (mode) {
+ case PAINT_SCULPT:
+ if (ELEM4(br->sculpt_tool,
+ SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_THUMB,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_SNAKE_HOOK))
+ {
+ return false;
+ }
+ default:
+ ;
+ }
+ return true;
+}
+
+bool paint_supports_smooth_stroke(Brush *br, PaintMode mode)
+{
+ if (!(br->flag & BRUSH_SMOOTH_STROKE) ||
+ (br->flag & BRUSH_ANCHORED) ||
+ (br->flag & BRUSH_RESTORE_MESH))
+ {
+ return false;
+ }
+
+ switch (mode) {
+ case PAINT_SCULPT:
+ if (ELEM4(br->sculpt_tool,
+ SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_THUMB,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_SNAKE_HOOK))
+ {
+ return false;
+ }
+ default:
+ ;
+ }
+ return true;
+}
+
+/* return true if the brush size can change during paint (normally used for pressure) */
+bool paint_supports_dynamic_tex_coords(Brush *br, PaintMode mode)
+{
+ if (br->flag & BRUSH_ANCHORED)
+ return false;
+
+ switch (mode) {
+ case PAINT_SCULPT:
+ if (ELEM4(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_SNAKE_HOOK))
+ return false;
+ default:
+ ;
+ }
+ return true;
+}
+
+bool paint_supports_jitter(PaintMode mode)
+{
+ return ELEM3(mode, PAINT_SCULPT, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D);
}
#define PAINT_STROKE_MODAL_CANCEL 1
@@ -395,17 +591,22 @@ static void paint_stroke_sample_average(const PaintStroke *stroke,
/*printf("avg=(%f, %f), num=%d\n", average->mouse[0], average->mouse[1], stroke->num_samples);*/
}
-int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
+int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
Paint *p = paint_get_active_from_context(C);
+ PaintMode mode = paintmode_get_active_from_context(C);
PaintStroke *stroke = op->customdata;
PaintSample sample_average;
float mouse[2];
int first = 0;
+ float zoomx, zoomy;
- paint_stroke_add_sample(p, stroke, event->x, event->y);
+ paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1]);
paint_stroke_sample_average(stroke, &sample_average);
+ get_imapaint_zoom(C, &zoomx, &zoomy);
+ stroke->zoom_2d = max_ff(zoomx, zoomy);
+
/* let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously!
* this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it
* since the 2D deltas are zero -- code in this file needs to be updated to use the
@@ -416,6 +617,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
if (!stroke->stroke_started) {
copy_v2_v2(stroke->last_mouse_position, sample_average.mouse);
stroke->stroke_started = stroke->test_start(C, op, sample_average.mouse);
+ BLI_assert((stroke->stroke_started & ~1) == 0); /* 0/1 */
if (stroke->stroke_started) {
stroke->smooth_stroke_cursor =
@@ -446,8 +648,8 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
(event->type == TIMER && (event->customdata == stroke->timer)) )
{
if (stroke->stroke_started) {
- if (paint_smooth_stroke(stroke, mouse, &sample_average)) {
- if (paint_space_stroke_enabled(stroke->brush)) {
+ if (paint_smooth_stroke(stroke, mouse, &sample_average, mode)) {
+ if (paint_space_stroke_enabled(stroke->brush, mode)) {
if (!paint_space_stroke(C, op, event, mouse)) {
//ED_region_tag_redraw(ar);
}
@@ -466,7 +668,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
* instead of waiting till we have moved the space distance */
if (first &&
stroke->stroke_started &&
- paint_space_stroke_enabled(stroke->brush) &&
+ paint_space_stroke_enabled(stroke->brush, mode) &&
!(stroke->brush->flag & BRUSH_ANCHORED) &&
!(stroke->brush->flag & BRUSH_SMOOTH_STROKE))
{
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index e7d13bd080d..5e88c7b5730 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -47,6 +47,7 @@
#include "BKE_context.h"
#include "BKE_DerivedMesh.h"
#include "BKE_paint.h"
+#include "BKE_report.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -160,12 +161,12 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3],
Object *ob = vc->obact;
float delta[3], scale, loc[3];
const float mval_f[2] = {pixel_radius, 0.0f};
+ float zfac;
mul_v3_m4v3(loc, ob->obmat, center);
- initgrabz(vc->rv3d, loc[0], loc[1], loc[2]);
-
- ED_view3d_win_to_delta(vc->ar, mval_f, delta);
+ zfac = ED_view3d_calc_zfac(vc->rv3d, loc, NULL);
+ ED_view3d_win_to_delta(vc->ar, mval_f, delta, zfac);
scale = fabsf(mat4_to_scale(ob->obmat));
scale = (scale == 0.0f) ? 1.0f : scale;
@@ -173,13 +174,13 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3],
return len_v3(delta) / scale;
}
-float paint_get_tex_pixel(Brush *br, float u, float v)
+float paint_get_tex_pixel(Brush *br, float u, float v, struct ImagePool *pool)
{
TexResult texres = {0};
float co[3] = {u, v, 0.0f};
int hasrgb;
- hasrgb = multitex_ext(br->mtex.tex, co, NULL, NULL, 0, &texres);
+ hasrgb = multitex_ext(br->mtex.tex, co, NULL, NULL, 0, &texres, pool);
if (hasrgb & TEX_RGB)
texres.tin = rgb_to_grayscale(&texres.tr) * texres.ta;
@@ -414,7 +415,7 @@ void PAINT_OT_face_select_linked(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int paint_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int paint_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int mode = RNA_boolean_get(op->ptr, "extend") ? 1 : 0;
paintface_select_linked(C, CTX_data_active_object(C), event->mval, mode);
@@ -448,7 +449,7 @@ static int face_select_all_exec(bContext *C, wmOperator *op)
void PAINT_OT_face_select_all(wmOperatorType *ot)
{
- ot->name = "Face Selection";
+ ot->name = "(De)select All";
ot->description = "Change selection for all faces";
ot->idname = "PAINT_OT_face_select_all";
@@ -472,7 +473,7 @@ static int vert_select_all_exec(bContext *C, wmOperator *op)
void PAINT_OT_vert_select_all(wmOperatorType *ot)
{
- ot->name = "Vertex Selection";
+ ot->name = "(De)select All";
ot->description = "Change selection for all vertices";
ot->idname = "PAINT_OT_vert_select_all";
@@ -484,44 +485,37 @@ void PAINT_OT_vert_select_all(wmOperatorType *ot)
WM_operator_properties_select_all(ot);
}
-static int vert_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = CTX_data_active_object(C);
- paintvert_deselect_all_visible(ob, SEL_INVERT, TRUE);
- ED_region_tag_redraw(CTX_wm_region(C));
- return OPERATOR_FINISHED;
-}
-void PAINT_OT_vert_select_inverse(wmOperatorType *ot)
+static int vert_select_ungrouped_exec(bContext *C, wmOperator *op)
{
- ot->name = "Vertex Select Invert";
- ot->description = "Invert selection of vertices";
- ot->idname = "PAINT_OT_vert_select_inverse";
+ Object *ob = CTX_data_active_object(C);
+ Mesh *me = ob->data;
- ot->exec = vert_select_inverse_exec;
- ot->poll = vert_paint_poll;
+ if ((ob->defbase.first == NULL) || (me->dvert == NULL)) {
+ BKE_report(op->reports, RPT_ERROR, "No weights/vertex groups on object");
+ return OPERATOR_CANCELLED;
+ }
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-static int face_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = CTX_data_active_object(C);
- paintface_deselect_all_visible(ob, SEL_INVERT, TRUE);
+ paintvert_select_ungrouped(ob, RNA_boolean_get(op->ptr, "extend"), TRUE);
ED_region_tag_redraw(CTX_wm_region(C));
return OPERATOR_FINISHED;
}
-
-void PAINT_OT_face_select_inverse(wmOperatorType *ot)
+void PAINT_OT_vert_select_ungrouped(wmOperatorType *ot)
{
- ot->name = "Face Select Invert";
- ot->description = "Invert selection of faces";
- ot->idname = "PAINT_OT_face_select_inverse";
+ /* identifiers */
+ ot->name = "Select Ungrouped";
+ ot->idname = "PAINT_OT_vert_select_ungrouped";
+ ot->description = "Select vertices without a group";
- ot->exec = face_select_inverse_exec;
- ot->poll = facemask_paint_poll;
+ /* api callbacks */
+ ot->exec = vert_select_ungrouped_exec;
+ ot->poll = vert_paint_poll;
+ /* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
static int face_select_hide_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 90ca1a6b18a..197231124fc 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -43,6 +43,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_math_color.h"
#include "BLI_memarena.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
@@ -224,7 +225,7 @@ static void do_shared_vertex_tesscol(Mesh *me)
{
/* if no mcol: do not do */
/* if tface: only the involved faces, otherwise all */
- const int use_face_sel = (me->editflag & ME_EDIT_PAINT_MASK);
+ const int use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL);
MFace *mface;
int a;
short *scolmain, *scol;
@@ -284,7 +285,7 @@ static void do_shared_vertex_tesscol(Mesh *me)
static void do_shared_vertexcol(Mesh *me, int do_tessface)
{
- const int use_face_sel = (me->editflag & ME_EDIT_PAINT_MASK);
+ const int use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL);
MPoly *mp;
float (*scol)[4];
int i, j, has_shared = 0;
@@ -292,7 +293,7 @@ static void do_shared_vertexcol(Mesh *me, int do_tessface)
/* if no mloopcol: do not do */
/* if mtexpoly: only the involved faces, otherwise all */
- if (me->mloopcol == 0 || me->totvert == 0 || me->totpoly == 0) return;
+ if (me->mloopcol == NULL || me->totvert == 0 || me->totpoly == 0) return;
scol = MEM_callocN(sizeof(float) * me->totvert * 5, "scol");
@@ -346,14 +347,14 @@ static void make_vertexcol(Object *ob) /* single ob */
if (me->edit_btmesh) return;
/* copies from shadedisplist to mcol */
- if (!me->mloopcol) {
+ 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);
}
- mesh_update_customdata_pointers(me, TRUE);
+ BKE_mesh_update_customdata_pointers(me, true);
}
update_tessface_data(ob, me);
@@ -372,42 +373,49 @@ static int wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active)
bDeformGroup *defgroup = BLI_findlink(&ob->defbase, vgroup_active);
if (defgroup) {
- bDeformGroup *curdef;
int mirrdef;
char name[MAXBONENAME];
flip_side_name(name, defgroup->name, FALSE);
-
- if (strcmp(name, defgroup->name) != 0) {
- for (curdef = ob->defbase.first, mirrdef = 0; curdef; curdef = curdef->next, mirrdef++) {
- if (!strcmp(curdef->name, name)) {
- break;
- }
- }
-
- if (curdef == NULL) {
- int olddef = ob->actdef; /* tsk, ED_vgroup_add sets the active defgroup */
- curdef = ED_vgroup_add_name(ob, name);
- ob->actdef = olddef;
- }
-
- /* curdef should never be NULL unless this is
- * a lamp and ED_vgroup_add_name fails */
- if (curdef) {
- return mirrdef;
+ mirrdef = defgroup_name_index(ob, name);
+ if (mirrdef == -1) {
+ int olddef = ob->actdef; /* tsk, ED_vgroup_add sets the active defgroup */
+ if (ED_vgroup_add_name(ob, name)) {
+ mirrdef = BLI_countlist(&ob->defbase) - 1;
}
+ ob->actdef = olddef;
}
+
+ /* curdef should never be NULL unless this is
+ * a lamp and ED_vgroup_add_name fails */
+ return mirrdef;
}
return -1;
}
-static void copy_vpaint_prev(VPaint *vp, unsigned int *lcol, int tot)
+static void free_vpaint_prev(VPaint *vp)
{
if (vp->vpaint_prev) {
MEM_freeN(vp->vpaint_prev);
vp->vpaint_prev = NULL;
+ vp->tot = 0;
}
+}
+
+static void free_wpaint_prev(VPaint *vp)
+{
+ if (vp->wpaint_prev) {
+ BKE_defvert_array_free(vp->wpaint_prev, vp->tot);
+ vp->wpaint_prev = NULL;
+ vp->tot = 0;
+ }
+}
+
+static void copy_vpaint_prev(VPaint *vp, unsigned int *lcol, int tot)
+{
+ free_vpaint_prev(vp);
+
vp->tot = tot;
if (lcol == NULL || tot == 0) return;
@@ -419,20 +427,16 @@ static void copy_vpaint_prev(VPaint *vp, unsigned int *lcol, int tot)
static void copy_wpaint_prev(VPaint *wp, MDeformVert *dverts, int dcount)
{
- if (wp->wpaint_prev) {
- free_dverts(wp->wpaint_prev, wp->tot);
- wp->wpaint_prev = NULL;
- }
+ free_wpaint_prev(wp);
if (dverts && dcount) {
wp->wpaint_prev = MEM_mallocN(sizeof(MDeformVert) * dcount, "wpaint prev");
wp->tot = dcount;
- copy_dverts(wp->wpaint_prev, dverts, dcount);
+ BKE_defvert_array_copy(wp->wpaint_prev, dverts, dcount);
}
}
-
void vpaint_fill(Object *ob, unsigned int paintcol)
{
Mesh *me;
@@ -447,7 +451,7 @@ void vpaint_fill(Object *ob, unsigned int paintcol)
if (!me->mloopcol) return; /* possible we can't make mcol's */
- selected = (me->editflag & ME_EDIT_PAINT_MASK);
+ selected = (me->editflag & ME_EDIT_PAINT_FACE_SEL);
mp = me->mpoly;
for (i = 0; i < me->totpoly; i++, mp++) {
@@ -657,11 +661,11 @@ BLI_INLINE unsigned int mcol_sub(unsigned int col1, unsigned int col2, int fac)
cp = (unsigned char *)&col;
temp = cp1[0] - ((fac * cp2[0]) / 255);
- cp1[0] = (temp < 0) ? 0 : temp;
+ cp[0] = (temp < 0) ? 0 : temp;
temp = cp1[1] - ((fac * cp2[1]) / 255);
- cp1[1] = (temp < 0) ? 0 : temp;
+ cp[1] = (temp < 0) ? 0 : temp;
temp = cp1[2] - ((fac * cp2[2]) / 255);
- cp1[2] = (temp < 0) ? 0 : temp;
+ cp[2] = (temp < 0) ? 0 : temp;
cp[3] = 255;
return col;
@@ -851,46 +855,58 @@ static int sample_backbuf_area(ViewContext *vc, int *indexar, int totface, int x
}
/* whats _dl mean? */
-static float calc_vp_strength_dl(VPaint *vp, ViewContext *vc, const float vert_nor[3],
- const float mval[2], const float brush_size_pressure)
+static float calc_vp_strength_col_dl(VPaint *vp, ViewContext *vc, const float co[3],
+ const float mval[2], const float brush_size_pressure, float rgba[4])
{
- float vertco[2];
+ float co_ss[2]; /* screenspace */
- if (ED_view3d_project_float_global(vc->ar, vert_nor, vertco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_float_object(vc->ar,
+ co, co_ss,
+ V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
+ {
float delta[2];
float dist_squared;
- sub_v2_v2v2(delta, mval, vertco);
+ sub_v2_v2v2(delta, mval, co_ss);
dist_squared = dot_v2v2(delta, delta); /* len squared */
if (dist_squared <= brush_size_pressure * brush_size_pressure) {
Brush *brush = paint_brush(&vp->paint);
const float dist = sqrtf(dist_squared);
+ if (brush->mtex.tex && rgba) {
+ if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) {
+ BKE_brush_sample_tex_3D(vc->scene, brush, co, rgba, 0, NULL);
+ }
+ else {
+ const float co_ss_3d[3] = {co_ss[0], co_ss[1], 0.0f}; /* we need a 3rd empty value */
+ BKE_brush_sample_tex_3D(vc->scene, brush, co_ss_3d, rgba, 0, NULL);
+ }
+ }
return BKE_brush_curve_strength_clamp(brush, dist, brush_size_pressure);
}
}
-
+ if (rgba)
+ zero_v4(rgba);
return 0.0f;
}
-static float calc_vp_alpha_dl(VPaint *vp, ViewContext *vc,
- float vpimat[3][3], const float *vert_nor,
+static float calc_vp_alpha_col_dl(VPaint *vp, ViewContext *vc,
+ float vpimat[3][3], const DMCoNo *v_co_no,
const float mval[2],
- const float brush_size_pressure, const float brush_alpha_pressure)
+ const float brush_size_pressure, const float brush_alpha_pressure, float rgba[4])
{
- float strength = calc_vp_strength_dl(vp, vc, vert_nor, mval, brush_size_pressure);
+ float strength = calc_vp_strength_col_dl(vp, vc, v_co_no->co, mval, brush_size_pressure, rgba);
if (strength > 0.0f) {
float alpha = brush_alpha_pressure * strength;
if (vp->flag & VP_NORMALS) {
float dvec[3];
- const float *no = vert_nor + 3;
/* transpose ! */
- dvec[2] = dot_v3v3(vpimat[2], no);
+ dvec[2] = dot_v3v3(vpimat[2], v_co_no->no);
if (dvec[2] > 0.0f) {
- dvec[0] = dot_v3v3(vpimat[0], no);
- dvec[1] = dot_v3v3(vpimat[1], no);
+ dvec[0] = dot_v3v3(vpimat[0], v_co_no->no);
+ dvec[1] = dot_v3v3(vpimat[1], v_co_no->no);
alpha *= dvec[2] / len_v3(dvec);
}
@@ -908,7 +924,8 @@ static float calc_vp_alpha_dl(VPaint *vp, ViewContext *vc,
BLI_INLINE float wval_blend(const float weight, const float paintval, const float alpha)
{
- return (paintval * alpha) + (weight * (1.0f - alpha));
+ const float talpha = min_ff(alpha, 1.0f); /* blending with values over 1 doesn't make sense */
+ return (paintval * talpha) + (weight * (1.0f - talpha));
}
BLI_INLINE float wval_add(const float weight, const float paintval, const float alpha)
{
@@ -1009,7 +1026,7 @@ static float wpaint_blend(VPaint *wp, float weight, float weight_prev,
/* sets wp->weight to the closest weight value to vertex */
/* note: we cant sample frontbuf, weight colors are interpolated too unpredictable */
-static int weight_sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewContext vc;
Mesh *me;
@@ -1019,22 +1036,23 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
me = BKE_mesh_from_object(vc.obact);
if (me && me->dvert && vc.v3d && vc.rv3d) {
- const int use_vert_sel = (me->editflag & ME_EDIT_VERT_SEL) != 0;
+ const int use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
int v_idx_best = -1;
unsigned int index;
view3d_operator_needs_opengl(C);
+ ED_view3d_init_mats_rv3d(vc.obact, vc.rv3d);
if (use_vert_sel) {
- if (ED_mesh_pick_vert(C, me, event->mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE)) {
+ if (ED_mesh_pick_vert(C, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE, TRUE)) {
v_idx_best = index;
}
}
else {
- if (ED_mesh_pick_face_vert(C, me, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
+ if (ED_mesh_pick_face_vert(C, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
v_idx_best = index;
}
- else if (ED_mesh_pick_face(C, me, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
+ else if (ED_mesh_pick_face(C, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
/* this relies on knowning the internal worksings of ED_mesh_pick_face_vert() */
BKE_report(op->reports, RPT_WARNING, "The modifier used does not support deformed locations");
}
@@ -1104,7 +1122,7 @@ static EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, PointerRNA
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_VERT_SEL) != 0;
+ const int use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
int *groups = MEM_callocN(defbase_tot * sizeof(int), "groups");
int found = FALSE;
unsigned int index;
@@ -1113,15 +1131,16 @@ static EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, PointerRNA
win->eventstate->y - vc.ar->winrct.ymin};
view3d_operator_needs_opengl(C);
+ ED_view3d_init_mats_rv3d(vc.obact, vc.rv3d);
if (use_vert_sel) {
- if (ED_mesh_pick_vert(C, me, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE)) {
+ if (ED_mesh_pick_vert(C, vc.obact, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE, TRUE)) {
MDeformVert *dvert = &me->dvert[index];
found |= weight_paint_sample_enum_itemf__helper(dvert, defbase_tot, groups);
}
}
else {
- if (ED_mesh_pick_face(C, me, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
+ if (ED_mesh_pick_face(C, vc.obact, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
MPoly *mp = &me->mpoly[index];
unsigned int fidx = mp->totloop - 1;
@@ -1459,7 +1478,7 @@ static void enforce_locks(MDeformVert *odv, MDeformVert *ndv,
MDeformWeight *ndw;
MDeformWeight *odw;
- float changed_sum = 0.0f;
+ // float changed_sum = 0.0f; // UNUSED
char *change_status;
@@ -1488,7 +1507,7 @@ static void enforce_locks(MDeformVert *odv, MDeformVert *ndv,
}
else if (ndw->weight != odw->weight) { /* changed groups are handled here */
totchange += ndw->weight - odw->weight;
- changed_sum += ndw->weight;
+ // changed_sum += ndw->weight; // UNUSED
change_status[i] = 2; /* was altered already */
total_changed++;
} /* unchanged, unlocked bone groups are handled here */
@@ -1994,6 +2013,13 @@ static int set_wpaint(bContext *C, wmOperator *UNUSED(op)) /* toggle */
else {
mesh_octree_table(NULL, NULL, NULL, 'e');
mesh_mirrtopo_table(NULL, 'e');
+
+ if (me->editflag & ME_EDIT_PAINT_VERT_SEL) {
+ BKE_mesh_flush_select_from_verts(me);
+ }
+ else if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
+ BKE_mesh_flush_select_from_polys(me);
+ }
}
WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
@@ -2038,34 +2064,30 @@ struct WPaintData {
int *indexar;
int vgroup_active;
int vgroup_mirror;
- float *vertexcosnos;
+ DMCoNo *vertexcosnos;
float wpimat[3][3];
-
+
/* variables for auto normalize */
const char *vgroup_validmap; /* stores if vgroups tie to deforming bones or not */
const char *lock_flags;
int defbase_tot;
};
-static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNUSED(mouse[2]))
+/* ensure we have data on wpaint start, add if needed */
+static int wpaint_ensure_data(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- struct PaintStroke *stroke = op->customdata;
- ToolSettings *ts = scene->toolsettings;
- VPaint *wp = ts->wpaint;
Object *ob = CTX_data_active_object(C);
- struct WPaintData *wpd;
- Mesh *me;
+ Mesh *me = BKE_mesh_from_object(ob);
- float mat[4][4], imat[4][4];
-
if (scene->obedit) {
return FALSE;
}
-
- me = BKE_mesh_from_object(ob);
- if (me == NULL || me->totpoly == 0) return OPERATOR_PASS_THROUGH;
-
+
+ if (me == NULL || me->totpoly == 0) {
+ return FALSE;
+ }
+
/* if nothing was added yet, we make dverts and a vertex deform group */
if (!me->dvert) {
ED_vgroup_data_create(&me->id);
@@ -2104,6 +2126,25 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNU
return FALSE;
}
+ return TRUE;
+}
+
+static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNUSED(mouse[2]))
+{
+ Scene *scene = CTX_data_scene(C);
+ struct PaintStroke *stroke = op->customdata;
+ ToolSettings *ts = scene->toolsettings;
+ VPaint *wp = ts->wpaint;
+ Object *ob = CTX_data_active_object(C);
+ Mesh *me = BKE_mesh_from_object(ob);
+ struct WPaintData *wpd;
+
+ float mat[4][4], imat[4][4];
+
+ if (wpaint_ensure_data(C, op) == FALSE) {
+ return FALSE;
+ }
+
{
/* check if we are attempting to paint onto a locked vertex group,
* and other options disallow it from doing anything useful */
@@ -2145,6 +2186,11 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNU
if (me->editflag & ME_EDIT_MIRROR_X) {
wpd->vgroup_mirror = wpaint_mirror_vgroup_ensure(ob, wpd->vgroup_active);
}
+
+ {
+ UnifiedPaintSettings *ups = &ts->unified_paint_settings;
+ ups->draw_pressure = true;
+ }
return TRUE;
}
@@ -2166,7 +2212,15 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
unsigned int index, totindex;
float alpha;
float mval[2];
- int use_vert_sel;
+ bool use_vert_sel;
+ bool use_face_sel;
+ bool use_depth;
+
+ MDeformWeight *(*dw_func)(MDeformVert *, const int) =
+ (brush->vertexpaint_tool == PAINT_BLEND_BLUR) ?
+ ((wp->flag & VP_ONLYVGROUP) ?
+ (MDeformWeight *(*)(MDeformVert *, const int))defvert_find_index :
+ defvert_verify_index) : NULL;
const float pressure = RNA_float_get(itemptr, "pressure");
const float brush_size_pressure = BKE_brush_size_get(scene, brush) * (BKE_brush_use_size_pressure(scene, brush) ? pressure : 1.0f);
@@ -2183,23 +2237,19 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
ED_region_tag_redraw(CTX_wm_region(C));
return;
}
-
+
vc = &wpd->vc;
ob = vc->obact;
me = ob->data;
indexar = wpd->indexar;
view3d_operator_needs_opengl(C);
-
+ ED_view3d_init_mats_rv3d(ob, vc->rv3d);
+
/* load projection matrix */
mult_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat);
RNA_float_get_array(itemptr, "mouse", mval);
- mval[0] -= vc->ar->winrct.xmin;
- mval[1] -= vc->ar->winrct.ymin;
-
-
-
/* *** setup WeightPaintInfo - pass onto do_weight_paint_vertex *** */
wpi.defbase_tot = wpd->defbase_tot;
@@ -2223,32 +2273,39 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
swap_m4m4(wpd->vc.rv3d->persmat, mat);
- use_vert_sel = (me->editflag & ME_EDIT_VERT_SEL) != 0;
+ use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+ use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ use_depth = (vc->v3d->flag & V3D_ZBUF_SELECT);
/* which faces are involved */
- if (wp->flag & VP_AREA) {
- /* Ugly hack, to avoid drawing vertex index when getting the face index buffer - campbell */
- me->editflag &= ~ME_EDIT_VERT_SEL;
- totindex = sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size_pressure);
- me->editflag |= use_vert_sel ? ME_EDIT_VERT_SEL : 0;
- }
- else {
- indexar[0] = view3d_sample_backbuf(vc, mval[0], mval[1]);
- if (indexar[0]) totindex = 1;
- else totindex = 0;
- }
+ if (use_depth) {
+ if (wp->flag & VP_AREA) {
+ /* Ugly hack, to avoid drawing vertex index when getting the face index buffer - campbell */
+ me->editflag &= ~ME_EDIT_PAINT_VERT_SEL;
+ totindex = sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size_pressure);
+ me->editflag |= use_vert_sel ? ME_EDIT_PAINT_VERT_SEL : 0;
+ }
+ else {
+ indexar[0] = view3d_sample_backbuf(vc, mval[0], mval[1]);
+ if (indexar[0]) totindex = 1;
+ else totindex = 0;
+ }
- if ((me->editflag & ME_EDIT_PAINT_MASK) && me->mpoly) {
- for (index = 0; index < totindex; index++) {
- if (indexar[index] && indexar[index] <= me->totpoly) {
- MPoly *mpoly = ((MPoly *)me->mpoly) + (indexar[index] - 1);
-
- if ((mpoly->flag & ME_FACE_SEL) == 0) {
- indexar[index] = 0;
+ if (use_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);
+
+ if ((mpoly->flag & ME_FACE_SEL) == 0) {
+ indexar[index] = 0;
+ }
}
}
}
}
+ else {
+ indexar = NULL;
+ }
/* make sure each vertex gets treated only once */
/* and calculate filter weight */
@@ -2257,80 +2314,126 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
paintweight = 0.0f;
else
paintweight = BKE_brush_weight_get(scene, brush);
-
- for (index = 0; index < totindex; index++) {
- if (indexar[index] && indexar[index] <= me->totpoly) {
- MPoly *mpoly = me->mpoly + (indexar[index] - 1);
- MLoop *ml = me->mloop + mpoly->loopstart;
- int i;
- if (use_vert_sel) {
- for (i = 0; i < mpoly->totloop; i++, ml++) {
- me->dvert[ml->v].flag = (me->mvert[ml->v].flag & SELECT);
+#define WP_BLUR_ACCUM(v_idx_var) \
+ { \
+ const unsigned int vidx = v_idx_var; \
+ const float fac = calc_vp_strength_col_dl(wp, vc, wpd->vertexcosnos[vidx].co, mval, brush_size_pressure, NULL); \
+ if (fac > 0.0f) { \
+ MDeformWeight *dw = dw_func(&me->dvert[vidx], wpi.vgroup_active); \
+ paintweight += dw ? (dw->weight * fac) : 0.0f; \
+ totw += fac; \
+ } \
+ } (void)0
+
+
+ if (use_depth) {
+ for (index = 0; index < totindex; index++) {
+ if (indexar[index] && indexar[index] <= me->totpoly) {
+ MPoly *mpoly = me->mpoly + (indexar[index] - 1);
+ MLoop *ml = me->mloop + mpoly->loopstart;
+ int i;
+
+ if (use_vert_sel) {
+ for (i = 0; i < mpoly->totloop; i++, ml++) {
+ me->dvert[ml->v].flag = (me->mvert[ml->v].flag & SELECT);
+ }
}
- }
- else {
- for (i = 0; i < mpoly->totloop; i++, ml++) {
- me->dvert[ml->v].flag = 1;
+ else {
+ for (i = 0; i < mpoly->totloop; i++, ml++) {
+ me->dvert[ml->v].flag = 1;
+ }
}
- }
-
- if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
- MDeformWeight *dw, *(*dw_func)(MDeformVert *, const int);
-
- if (wp->flag & VP_ONLYVGROUP)
- dw_func = (MDeformWeight *(*)(MDeformVert *, const int))defvert_find_index;
- else
- dw_func = defvert_verify_index;
-
- ml = me->mloop + mpoly->loopstart;
- for (i = 0; i < mpoly->totloop; i++, ml++) {
- unsigned int vidx = ml->v;
- const float fac = calc_vp_strength_dl(wp, vc, wpd->vertexcosnos + 6 * vidx, mval, brush_size_pressure);
- if (fac > 0.0f) {
- dw = dw_func(&me->dvert[vidx], wpi.vgroup_active);
- paintweight += dw ? (dw->weight * fac) : 0.0f;
- totw += fac;
+
+ if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
+ ml = me->mloop + mpoly->loopstart;
+ for (i = 0; i < mpoly->totloop; i++, ml++) {
+ WP_BLUR_ACCUM(ml->v);
}
}
}
}
}
-
+ else {
+ const unsigned int totvert = me->totvert;
+ unsigned int i;
+
+ /* in the case of face selection we need to flush */
+ if (use_vert_sel || use_face_sel) {
+ for (i = 0; i < totvert; i++) {
+ me->dvert[i].flag = me->mvert[i].flag & SELECT;
+ }
+ }
+ else {
+ for (i = 0; i < totvert; i++) {
+ me->dvert[i].flag = SELECT;
+ }
+ }
+
+ if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
+ for (i = 0; i < totvert; i++) {
+ WP_BLUR_ACCUM(i);
+ }
+ }
+ }
+
+#undef WP_BLUR_ACCUM
+
+
if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
paintweight /= totw;
}
- for (index = 0; index < totindex; index++) {
+#define WP_PAINT(v_idx_var) \
+ { \
+ unsigned int vidx = v_idx_var; \
+ if (me->dvert[vidx].flag) { \
+ alpha = calc_vp_alpha_col_dl(wp, vc, wpd->wpimat, &wpd->vertexcosnos[vidx], \
+ mval, brush_size_pressure, brush_alpha_pressure, NULL); \
+ if (alpha) { \
+ do_weight_paint_vertex(wp, ob, &wpi, vidx, alpha, paintweight); \
+ } \
+ me->dvert[vidx].flag = 0; \
+ } \
+ } (void)0
+
+ if (use_depth) {
+ for (index = 0; index < totindex; index++) {
- if (indexar[index] && indexar[index] <= me->totpoly) {
- MPoly *mpoly = me->mpoly + (indexar[index] - 1);
- MLoop *ml = me->mloop + mpoly->loopstart;
- int i;
-
- for (i = 0; i < mpoly->totloop; i++, ml++) {
- unsigned int vidx = ml->v;
-
- if (me->dvert[vidx].flag) {
- alpha = calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos + 6 * vidx,
- mval, brush_size_pressure, brush_alpha_pressure);
- if (alpha) {
- do_weight_paint_vertex(wp, ob, &wpi, vidx, alpha, paintweight);
- }
- me->dvert[vidx].flag = 0;
+ if (indexar[index] && indexar[index] <= me->totpoly) {
+ MPoly *mpoly = me->mpoly + (indexar[index] - 1);
+ MLoop *ml = me->mloop + mpoly->loopstart;
+ int i;
+
+ for (i = 0; i < mpoly->totloop; i++, ml++) {
+ WP_PAINT(ml->v);
}
}
}
}
+ else {
+ const unsigned int totvert = me->totvert;
+ unsigned int i;
+
+ for (i = 0; i < totvert; i++) {
+ WP_PAINT(i);
+ }
+ }
+#undef WP_PAINT
/* *** free wpi members */
MEM_freeN((void *)wpi.defbase_sel);
- /* *** don't freeing wpi members */
+ /* *** done freeing wpi members */
swap_m4m4(vc->rv3d->persmat, mat);
-
+
+ {
+ UnifiedPaintSettings *ups = &ts->unified_paint_settings;
+ ups->pressure_value = pressure;
+ }
+
DAG_id_tag_update(ob->data, 0);
ED_region_tag_redraw(vc->ar);
}
@@ -2371,14 +2474,19 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
}
}
}
-
+
+ {
+ UnifiedPaintSettings *ups = &ts->unified_paint_settings;
+ ups->draw_pressure = false;
+ }
+
DAG_id_tag_update(ob->data, 0);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
}
-static int wpaint_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int wpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int retval;
@@ -2424,7 +2532,7 @@ void PAINT_OT_weight_paint(wmOperatorType *ot)
RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
}
-static int weight_paint_set_exec(bContext *C, wmOperator *UNUSED(op))
+static int weight_paint_set_exec(bContext *C, wmOperator *op)
{
struct Scene *scene = CTX_data_scene(C);
Object *obact = CTX_data_active_object(C);
@@ -2432,6 +2540,10 @@ static int weight_paint_set_exec(bContext *C, wmOperator *UNUSED(op))
Brush *brush = paint_brush(&ts->wpaint->paint);
float vgroup_weight = BKE_brush_weight_get(scene, brush);
+ if (wpaint_ensure_data(C, op) == FALSE) {
+ return OPERATOR_CANCELLED;
+ }
+
wpaint_fill(scene->toolsettings->wpaint, obact, vgroup_weight);
ED_region_tag_redraw(CTX_wm_region(C)); /* XXX - should redraw all 3D views */
return OPERATOR_FINISHED;
@@ -2477,6 +2589,10 @@ static int set_vpaint(bContext *C, wmOperator *op) /* toggle */
if (ob->mode & OB_MODE_VERTEX_PAINT) {
ob->mode &= ~OB_MODE_VERTEX_PAINT;
+
+ if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
+ BKE_mesh_flush_select_from_polys(me);
+ }
}
else {
ob->mode |= OB_MODE_VERTEX_PAINT;
@@ -2492,9 +2608,8 @@ static int set_vpaint(bContext *C, wmOperator *op) /* toggle */
BKE_paint_init(&vp->paint, PAINT_CURSOR_VERTEX_PAINT);
}
- if (me)
- /* update modifier stack for mapping requirements */
- DAG_id_tag_update(&me->id, 0);
+ /* update modifier stack for mapping requirements */
+ DAG_id_tag_update(&me->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
@@ -2548,7 +2663,7 @@ typedef struct VPaintData {
ViewContext vc;
unsigned int paintcol;
int *indexar;
- float *vertexcosnos;
+ DMCoNo *vertexcosnos;
float vpimat[3][3];
/* modify 'me->mcol' directly, since the derived mesh is drawing from this array,
@@ -2558,6 +2673,8 @@ typedef struct VPaintData {
/* mpoly -> mface mapping */
MemArena *polyfacemap_arena;
ListBase *polyfacemap;
+
+ bool is_texbrush;
} VPaintData;
static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me)
@@ -2594,6 +2711,7 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const fl
ToolSettings *ts = CTX_data_tool_settings(C);
struct PaintStroke *stroke = op->customdata;
VPaint *vp = ts->vpaint;
+ Brush *brush = paint_brush(&vp->paint);
struct VPaintData *vpd;
Object *ob = CTX_data_active_object(C);
Mesh *me;
@@ -2623,6 +2741,8 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const fl
vpd->indexar = get_indexarray(me);
vpd->paintcol = vpaint_get_current_col(vp);
+ vpd->is_texbrush = !(brush->vertexpaint_tool == PAINT_BLEND_BLUR) &&
+ brush->mtex.tex;
/* are we painting onto a modified mesh?,
* if not we can skip face map trickyness */
@@ -2644,16 +2764,20 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const fl
invert_m4_m4(imat, mat);
copy_m3_m4(vpd->vpimat, imat);
+ {
+ UnifiedPaintSettings *ups = &ts->unified_paint_settings;
+ ups->draw_pressure = true;
+ }
+
return 1;
}
-static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Object *ob,
+static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Mesh *me,
const unsigned int index, const float mval[2],
const float brush_size_pressure, const float brush_alpha_pressure)
{
ViewContext *vc = &vpd->vc;
Brush *brush = paint_brush(&vp->paint);
- Mesh *me = BKE_mesh_from_object(ob);
MPoly *mpoly = &me->mpoly[index];
MFace *mf;
MCol *mc;
@@ -2695,12 +2819,24 @@ static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Object *ob,
ml = me->mloop + mpoly->loopstart;
for (i = 0; i < mpoly->totloop; i++, ml++) {
- alpha = calc_vp_alpha_dl(vp, vc, vpd->vpimat,
- vpd->vertexcosnos + 6 * ml->v, mval,
- brush_size_pressure, brush_alpha_pressure);
+ float rgba[4];
+ unsigned int paintcol;
+ alpha = calc_vp_alpha_col_dl(vp, vc, vpd->vpimat,
+ &vpd->vertexcosnos[ml->v], mval,
+ brush_size_pressure, brush_alpha_pressure, rgba);
+
+ if (vpd->is_texbrush) {
+ float rgba_br[3];
+ rgb_uchar_to_float(rgba_br, (const unsigned char *)&vpd->paintcol);
+ mul_v3_v3(rgba_br, rgba);
+ rgb_float_to_uchar((unsigned char *)&paintcol, rgba_br);
+ }
+ else
+ paintcol = vpd->paintcol;
+
if (alpha > 0.0f) {
const int alpha_i = (int)(alpha * 255.0f);
- lcol[i] = vpaint_blend(vp, lcol[i], lcolorig[i], vpd->paintcol, alpha_i, brush_alpha_pressure_i);
+ lcol[i] = vpaint_blend(vp, lcol[i], lcolorig[i], paintcol, alpha_i, brush_alpha_pressure_i);
}
}
@@ -2754,14 +2890,11 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
RNA_float_get_array(itemptr, "mouse", mval);
view3d_operator_needs_opengl(C);
-
+ ED_view3d_init_mats_rv3d(ob, vc->rv3d);
+
/* load projection matrix */
mult_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat);
- mval[0] -= vc->ar->winrct.xmin;
- mval[1] -= vc->ar->winrct.ymin;
-
-
/* which faces are involved */
if (vp->flag & VP_AREA) {
totindex = sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size_pressure);
@@ -2772,7 +2905,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
else totindex = 0;
}
- if ((me->editflag & ME_EDIT_PAINT_MASK) && me->mpoly) {
+ 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);
@@ -2787,7 +2920,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
for (index = 0; index < totindex; index++) {
if (indexar[index] && indexar[index] <= me->totpoly) {
- vpaint_paint_poly(vp, vpd, ob, indexar[index] - 1, mval, brush_size_pressure, brush_alpha_pressure);
+ vpaint_paint_poly(vp, vpd, me, indexar[index] - 1, mval, brush_size_pressure, brush_alpha_pressure);
}
}
@@ -2799,6 +2932,11 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
do_shared_vertexcol(me, do_tessface);
}
+ {
+ UnifiedPaintSettings *ups = &ts->unified_paint_settings;
+ ups->pressure_value = pressure;
+ }
+
ED_region_tag_redraw(vc->ar);
if (vpd->use_fast_update == FALSE) {
@@ -2830,12 +2968,17 @@ static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
BLI_memarena_free(vpd->polyfacemap_arena);
}
+ {
+ UnifiedPaintSettings *ups = &ts->unified_paint_settings;
+ ups->draw_pressure = false;
+ }
+
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
MEM_freeN(vpd);
}
-static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int retval;
@@ -2929,3 +3072,275 @@ void PAINT_OT_weight_from_bones(wmOperatorType *ot)
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "Method to use for assigning weights");
}
+
+/* *** VGroups Gradient *** */
+typedef struct DMGradient_vertStore {
+ float sco[2];
+ float weight_orig;
+ enum {
+ VGRAD_STORE_NOP = 0,
+ VGRAD_STORE_DW_EXIST = (1 << 0)
+ } flag;
+} DMGradient_vertStore;
+
+typedef struct DMGradient_userData {
+ struct ARegion *ar;
+ Scene *scene;
+ Mesh *me;
+ Brush *brush;
+ const float *sco_start; /* [2] */
+ const float *sco_end; /* [2] */
+ float sco_line_div; /* store (1.0f / len_v2v2(sco_start, sco_end)) */
+ int def_nr;
+ short is_init;
+ DMGradient_vertStore *vert_cache;
+
+ /* options */
+ short use_select;
+ short type;
+ float weightpaint;
+} DMGradient_userData;
+
+static void gradientVert__mapFunc(void *userData, int index, const float co[3],
+ const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+{
+ DMGradient_userData *grad_data = userData;
+ Mesh *me = grad_data->me;
+
+ if (grad_data->use_select == FALSE || (me->mvert[index].flag & SELECT)) {
+ DMGradient_vertStore *vs = &grad_data->vert_cache[index];
+
+ /* run first pass only, could be split into its own mapFunc
+ * the screen coords of the verts need to be cached because
+ * updating the mesh may move them about (entering feedback loop) */
+ if (grad_data->is_init) {
+ if (ED_view3d_project_float_object(grad_data->ar,
+ co, vs->sco,
+ V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
+ {
+ /* ok */
+ MDeformVert *dv = &me->dvert[index];
+ MDeformWeight *dw;
+ dw = defvert_find_index(dv, grad_data->def_nr);
+ if (dw) {
+ vs->weight_orig = dw->weight;
+ vs->flag = VGRAD_STORE_DW_EXIST;
+ }
+ else {
+ vs->weight_orig = 0.0f;
+ vs->flag = VGRAD_STORE_NOP;
+ }
+ }
+ else {
+ /* no go */
+ copy_v2_fl(vs->sco, FLT_MAX);
+ }
+ }
+ /* end init */
+
+ if (vs->sco[0] != FLT_MAX) {
+ float alpha;
+
+ if (grad_data->type == WPAINT_GRADIENT_TYPE_LINEAR) {
+ alpha = line_point_factor_v2(vs->sco, grad_data->sco_start, grad_data->sco_end);
+ }
+ else {
+ BLI_assert(grad_data->type == WPAINT_GRADIENT_TYPE_RADIAL);
+ alpha = len_v2v2(grad_data->sco_start, vs->sco) * grad_data->sco_line_div;
+ }
+ /* no need to clamp 'alpha' yet */
+
+ /* adjust weight */
+ alpha = BKE_brush_curve_strength_clamp(grad_data->brush, alpha, 1.0f);
+
+ if (alpha != 0.0f) {
+ MDeformVert *dv = &me->dvert[index];
+ MDeformWeight *dw = defvert_verify_index(dv, grad_data->def_nr);
+ // dw->weight = alpha; // testing
+ int tool = grad_data->brush->vertexpaint_tool;
+ float testw;
+
+ /* init if we just added */
+ testw = wpaint_blend_tool(tool, vs->weight_orig, grad_data->weightpaint, alpha * grad_data->brush->alpha);
+ CLAMP(testw, 0.0f, 1.0f);
+ dw->weight = testw;
+ }
+ else {
+ MDeformVert *dv = &me->dvert[index];
+ if (vs->flag & VGRAD_STORE_DW_EXIST) {
+ /* normally we NULL check, but in this case we know it exists */
+ MDeformWeight *dw = defvert_find_index(dv, grad_data->def_nr);
+ dw->weight = vs->weight_orig;
+ }
+ else {
+ /* wasn't originally existing, remove */
+ MDeformWeight *dw = defvert_find_index(dv, grad_data->def_nr);
+ if (dw) {
+ defvert_remove_group(dv, dw);
+ }
+ }
+ }
+ }
+ }
+}
+
+static int paint_weight_gradient_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int ret = WM_gesture_straightline_modal(C, op, event);
+
+ if (ret & OPERATOR_RUNNING_MODAL) {
+ if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { /* XXX, hardcoded */
+ /* generally crap! redo! */
+ WM_gesture_straightline_cancel(C, op);
+ ret &= ~OPERATOR_RUNNING_MODAL;
+ ret |= OPERATOR_FINISHED;
+ }
+ }
+
+ if (ret & OPERATOR_CANCELLED) {
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ VPaint *wp = ts->wpaint;
+ Object *ob = CTX_data_active_object(C);
+ Mesh *me = ob->data;
+ if (wp->wpaint_prev) {
+ BKE_defvert_array_free_elems(me->dvert, me->totvert);
+ BKE_defvert_array_copy(me->dvert, wp->wpaint_prev, me->totvert);
+ free_wpaint_prev(wp);
+ }
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ else if (ret & OPERATOR_FINISHED) {
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ VPaint *wp = ts->wpaint;
+ free_wpaint_prev(wp);
+ }
+
+ return ret;
+}
+
+static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
+{
+ wmGesture *gesture = op->customdata;
+ DMGradient_vertStore *vert_cache;
+ struct ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ Mesh *me = ob->data;
+ int x_start = RNA_int_get(op->ptr, "xstart");
+ int y_start = RNA_int_get(op->ptr, "ystart");
+ int x_end = RNA_int_get(op->ptr, "xend");
+ int y_end = RNA_int_get(op->ptr, "yend");
+ float sco_start[2] = {x_start, y_start};
+ float sco_end[2] = {x_end, y_end};
+ const bool is_interactive = (gesture != NULL);
+ DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
+
+ DMGradient_userData data = {0};
+
+ if (is_interactive) {
+ if (gesture->userdata == NULL) {
+ VPaint *wp = scene->toolsettings->wpaint;
+
+ gesture->userdata = MEM_mallocN(sizeof(DMGradient_vertStore) * me->totvert, __func__);
+ data.is_init = true;
+
+ copy_wpaint_prev(wp, me->dvert, me->totvert);
+
+ /* on init only, convert face -> vert sel */
+ if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
+ BKE_mesh_flush_select_from_polys(me);
+ }
+ }
+
+ vert_cache = gesture->userdata;
+ }
+ else {
+ data.is_init = true;
+ vert_cache = MEM_mallocN(sizeof(DMGradient_vertStore) * me->totvert, __func__);
+ }
+
+ data.ar = ar;
+ data.scene = scene;
+ data.me = ob->data;
+ data.sco_start = sco_start;
+ data.sco_end = sco_end;
+ data.sco_line_div = 1.0f / len_v2v2(sco_start, sco_end);
+ data.def_nr = ob->actdef - 1;
+ data.use_select = (me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL));
+ data.vert_cache = vert_cache;
+ data.type = RNA_enum_get(op->ptr, "type");
+
+ {
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ VPaint *wp = ts->wpaint;
+ struct Brush *brush = paint_brush(&wp->paint);
+ data.brush = brush;
+ data.weightpaint = BKE_brush_weight_get(scene, brush);
+ }
+
+ dm->foreachMappedVert(dm, gradientVert__mapFunc, &data);
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ if (is_interactive == false) {
+ MEM_freeN(vert_cache);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static int paint_weight_gradient_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int ret;
+
+ if (wpaint_ensure_data(C, op) == FALSE) {
+ return OPERATOR_CANCELLED;
+ }
+
+ ret = WM_gesture_straightline_invoke(C, op, event);
+ if (ret & OPERATOR_RUNNING_MODAL) {
+ struct ARegion *ar = CTX_wm_region(C);
+ if (ar->regiontype == RGN_TYPE_WINDOW) {
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS) { /* TODO, hardcoded, extend WM_gesture_straightline_ */
+ wmGesture *gesture = op->customdata;
+ gesture->mode = 1;
+ }
+ }
+ }
+ return ret;
+}
+
+void PAINT_OT_weight_gradient(wmOperatorType *ot)
+{
+ /* defined in DNA_space_types.h */
+ static EnumPropertyItem gradient_types[] = {
+ {WPAINT_GRADIENT_TYPE_LINEAR, "LINEAR", 0, "Linear", ""},
+ {WPAINT_GRADIENT_TYPE_RADIAL, "RADIAL", 0, "Radial", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Weight Gradient";
+ ot->idname = "PAINT_OT_weight_gradient";
+ ot->description = "Sample a line and show it in Scope panels";
+
+ /* api callbacks */
+ ot->invoke = paint_weight_gradient_invoke;
+ ot->modal = paint_weight_gradient_modal;
+ ot->exec = paint_weight_gradient_exec;
+ ot->poll = weight_paint_poll;
+ ot->cancel = WM_gesture_straightline_cancel;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_enum(ot->srna, "type", gradient_types, 0, "Type", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT);
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index e2ed7776b7e..51500ab8e1c 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -40,10 +40,11 @@
#include "BLI_utildefines.h"
#include "BLI_dynstr.h"
#include "BLI_ghash.h"
-#include "BLI_pbvh.h"
#include "BLI_threads.h"
#include "BLI_rand.h"
+#include "BLF_translation.h"
+
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_node_types.h"
@@ -51,11 +52,13 @@
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
+#include "BKE_pbvh.h"
#include "BKE_brush.h"
#include "BKE_ccg.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#include "BKE_image.h"
#include "BKE_key.h"
#include "BKE_library.h"
#include "BKE_mesh.h"
@@ -65,6 +68,7 @@
#include "BKE_report.h"
#include "BKE_lattice.h" /* for armature_deform_verts */
#include "BKE_node.h"
+#include "BKE_object.h"
#include "BKE_subsurf.h"
#include "BIF_glutil.h"
@@ -86,6 +90,8 @@
#include "GPU_buffers.h"
+#include "bmesh.h"
+
#include <math.h>
#include <stdlib.h>
#include <string.h>
@@ -98,8 +104,13 @@ void ED_sculpt_force_update(bContext *C)
{
Object *ob = CTX_data_active_object(C);
- if (ob && (ob->mode & OB_MODE_SCULPT))
+ if (ob && (ob->mode & OB_MODE_SCULPT)) {
multires_force_update(ob);
+
+ /* Set reorder=false so that saving the file doesn't reorder
+ * the BMesh's elements */
+ sculptsession_bm_to_me(ob, FALSE);
+ }
}
float *ED_sculpt_get_last_stroke(struct Object *ob)
@@ -129,6 +140,11 @@ MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob)
Mesh *me = (Mesh *)ob->data;
ModifierData *md;
+ if (ob->sculpt && ob->sculpt->bm) {
+ /* can't combine multires and dynamic topology */
+ return NULL;
+ }
+
if (!CustomData_get_layer(&me->ldata, CD_MDISPS)) {
/* multires can't work without displacement layer */
return NULL;
@@ -172,7 +188,8 @@ static int sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
Mesh *me = (Mesh *)ob->data;
MultiresModifierData *mmd = sculpt_multires_active(scene, ob);
- if (mmd) return 0;
+ if (mmd || ob->sculpt->bm)
+ return 0;
/* 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)
@@ -228,7 +245,6 @@ typedef struct StrokeCache {
float pressure;
float mouse[2];
float bstrength;
- float tex_mouse[2];
/* The rest is temporary storage that isn't saved as a property */
@@ -242,8 +258,8 @@ typedef struct StrokeCache {
Brush *brush;
float (*face_norms)[3]; /* Copy of the mesh faces' normals */
- float special_rotation; /* Texture rotation (radians) for anchored and rake modes */
- int pixel_radius, previous_pixel_radius;
+
+ float special_rotation;
float grab_delta[3], grab_delta_symmetry[3];
float old_grab_location[3], orig_grab_location[3];
@@ -267,8 +283,8 @@ typedef struct StrokeCache {
int radial_symmetry_pass;
float symm_rot_mat[4][4];
float symm_rot_mat_inv[4][4];
- float last_rake[2]; /* Last location of updating rake rotation */
int original;
+ float anchored_location[3];
float vertex_rotation;
@@ -281,12 +297,129 @@ typedef struct StrokeCache {
rcti previous_r; /* previous redraw rectangle */
} StrokeCache;
+/************** Access to original unmodified vertex data *************/
+
+typedef struct {
+ BMLog *bm_log;
+
+ SculptUndoNode *unode;
+ float (*coords)[3];
+ short (*normals)[3];
+ float *vmasks;
+
+ /* Original coordinate, normal, and mask */
+ const float *co;
+ float mask;
+ short no[3];
+} SculptOrigVertData;
+
+
+/* Initialize a SculptOrigVertData for accessing original vertex data;
+ * handles BMesh, mesh, and multires */
+static void sculpt_orig_vert_data_unode_init(SculptOrigVertData *data,
+ Object *ob,
+ SculptUndoNode *unode)
+{
+ SculptSession *ss = ob->sculpt;
+ BMesh *bm = ss->bm;
+
+ memset(data, 0, sizeof(*data));
+ data->unode = unode;
+
+ if (bm) {
+ data->bm_log = ss->bm_log;
+ }
+ else {
+ data->coords = data->unode->co;
+ data->normals = data->unode->no;
+ data->vmasks = data->unode->mask;
+ }
+}
+
+/* Initialize a SculptOrigVertData for accessing original vertex data;
+ * handles BMesh, mesh, and multires */
+static void sculpt_orig_vert_data_init(SculptOrigVertData *data,
+ Object *ob,
+ PBVHNode *node)
+{
+ SculptUndoNode *unode;
+ unode = sculpt_undo_push_node(ob, node, SCULPT_UNDO_COORDS);
+ sculpt_orig_vert_data_unode_init(data, ob, unode);
+}
+
+/* Update a SculptOrigVertData for a particular vertex from the PBVH
+ * iterator */
+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];
+ }
+ else {
+ orig_data->co = BM_log_original_vert_co(orig_data->bm_log, iter->bm_vert);
+ }
+
+ if (orig_data->normals) {
+ copy_v3_v3_short(orig_data->no, orig_data->normals[iter->i]);
+ }
+ else {
+ /* TODO: log doesn't store normals yet */
+ normal_float_to_short_v3(orig_data->no, iter->bm_vert->no);
+ }
+ }
+ else if (orig_data->unode->type == SCULPT_UNDO_MASK) {
+ if (orig_data->vmasks) {
+ orig_data->mask = orig_data->vmasks[iter->i];
+ }
+ else {
+ orig_data->mask = BM_log_original_mask(orig_data->bm_log, iter->bm_vert);
+ }
+ }
+}
+
+/**********************************************************************/
+
+/* Returns true if the stroke will use dynamic topology, false
+ otherwise.
+
+ 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)
+{
+ return ((BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) &&
+
+ (!ss->cache || (!ss->cache->alt_smooth)) &&
+
+ /* Requires mesh restore, which doesn't work with
+ * dynamic-topology */
+ !(brush->flag & BRUSH_ANCHORED) &&
+ !(brush->flag & BRUSH_RESTORE_MESH) &&
+
+ (!ELEM6(brush->sculpt_tool,
+ /* These brushes, as currently coded, cannot
+ * support dynamic topology */
+ SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_THUMB,
+ SCULPT_TOOL_LAYER,
+
+ /* These brushes could handle dynamic topology,
+ * but user feedback indicates it's better not
+ * to */
+ SCULPT_TOOL_SMOOTH,
+ SCULPT_TOOL_MASK)));
+}
/*** paint mesh ***/
-static void paint_mesh_restore_co(Sculpt *sd, SculptSession *ss)
+static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
{
+ SculptSession *ss = ob->sculpt;
StrokeCache *cache = ss->cache;
+ const Brush *brush = paint_brush(&sd->paint);
int i;
PBVHNode **nodes;
@@ -296,31 +429,47 @@ static void paint_mesh_restore_co(Sculpt *sd, SculptSession *ss)
(void)sd; /* quied unused warning */
#endif
- BLI_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
- #pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+ /* Disable OpenMP when dynamic-topology is enabled. Otherwise, new
+ * entries might be inserted by sculpt_undo_push_node() into the
+ * GHash used internally by BM_log_original_vert_co() by a
+ * different thread. [#33787] */
+ #pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP && !ss->bm)
for (n = 0; n < totnode; n++) {
SculptUndoNode *unode;
-
- unode = sculpt_undo_get_node(nodes[n]);
+ SculptUndoType type = (brush->sculpt_tool == SCULPT_TOOL_MASK ?
+ SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS);
+
+ if (ss->bm) {
+ unode = sculpt_undo_push_node(ob, nodes[n], type);
+ }
+ else {
+ unode = sculpt_undo_get_node(nodes[n]);
+ }
if (unode) {
PBVHVertexIter vd;
+ SculptOrigVertData orig_data;
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ sculpt_orig_vert_data_unode_init(&orig_data, ob, unode);
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (unode->type == SCULPT_UNDO_COORDS) {
- copy_v3_v3(vd.co, unode->co[vd.i]);
- if (vd.no) copy_v3_v3_short(vd.no, unode->no[vd.i]);
- else normal_short_to_float_v3(vd.fno, unode->no[vd.i]);
+ sculpt_orig_vert_data_update(&orig_data, &vd);
+
+ if (orig_data.unode->type == SCULPT_UNDO_COORDS) {
+ copy_v3_v3(vd.co, orig_data.co);
+ if (vd.no) copy_v3_v3_short(vd.no, orig_data.no);
+ else normal_short_to_float_v3(vd.fno, orig_data.no);
}
- else if (unode->type == SCULPT_UNDO_MASK) {
- *vd.mask = unode->mask[vd.i];
+ else if (orig_data.unode->type == SCULPT_UNDO_MASK) {
+ *vd.mask = orig_data.mask;
}
if (vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
- BLI_pbvh_node_mark_update(nodes[n]);
+ BKE_pbvh_node_mark_update(nodes[n]);
}
}
@@ -347,7 +496,7 @@ static int sculpt_get_redraw_rect(ARegion *ar, RegionView3D *rv3d,
if (!pbvh)
return 0;
- BLI_pbvh_redraw_BB(pbvh, bb_min, bb_max);
+ BKE_pbvh_redraw_BB(pbvh, bb_min, bb_max);
/* convert 3D bounding box to screen space */
if (!paint_convert_bb_to_rect(rect,
@@ -387,7 +536,7 @@ void sculpt_get_redraw_planes(float planes[4][4], ARegion *ar,
/* clear redraw flag from nodes */
if (pbvh)
- BLI_pbvh_update(pbvh, PBVH_UpdateRedraw, NULL);
+ BKE_pbvh_update(pbvh, PBVH_UpdateRedraw, NULL);
}
/************************ Brush Testing *******************/
@@ -396,20 +545,42 @@ typedef struct SculptBrushTest {
float radius_squared;
float location[3];
float dist;
+
+ /* View3d clipping - only set rv3d for clipping */
+ RegionView3D *clip_rv3d;
} SculptBrushTest;
static void sculpt_brush_test_init(SculptSession *ss, SculptBrushTest *test)
{
+ RegionView3D *rv3d = ss->cache->vc->rv3d;
+
test->radius_squared = ss->cache->radius_squared;
copy_v3_v3(test->location, ss->cache->location);
test->dist = 0.0f; /* just for initialize */
+
+
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ test->clip_rv3d = rv3d;
+ }
+ else {
+ test->clip_rv3d = NULL;
+ }
}
-static int sculpt_brush_test(SculptBrushTest *test, float co[3])
+BLI_INLINE bool sculpt_brush_test_clipping(SculptBrushTest *test, const float co[3])
+{
+ RegionView3D *rv3d = test->clip_rv3d;
+ return (rv3d && (ED_view3d_clipping_test(rv3d, co, true)));
+}
+
+static int sculpt_brush_test(SculptBrushTest *test, const float co[3])
{
float distsq = len_squared_v3v3(co, test->location);
if (distsq <= test->radius_squared) {
+ if (sculpt_brush_test_clipping(test, co)) {
+ return 0;
+ }
test->dist = sqrt(distsq);
return 1;
}
@@ -418,11 +589,14 @@ static int sculpt_brush_test(SculptBrushTest *test, float co[3])
}
}
-static int sculpt_brush_test_sq(SculptBrushTest *test, float co[3])
+static int sculpt_brush_test_sq(SculptBrushTest *test, const float co[3])
{
float distsq = len_squared_v3v3(co, test->location);
if (distsq <= test->radius_squared) {
+ if (sculpt_brush_test_clipping(test, co)) {
+ return 0;
+ }
test->dist = distsq;
return 1;
}
@@ -433,6 +607,9 @@ static int sculpt_brush_test_sq(SculptBrushTest *test, float co[3])
static int sculpt_brush_test_fast(SculptBrushTest *test, float co[3])
{
+ if (sculpt_brush_test_clipping(test, co)) {
+ return 0;
+ }
return len_squared_v3v3(co, test->location) <= test->radius_squared;
}
@@ -441,6 +618,10 @@ static int sculpt_brush_test_cube(SculptBrushTest *test, float co[3], float loca
float side = M_SQRT1_2;
float local_co[3];
+ if (sculpt_brush_test_clipping(test, co)) {
+ return 0;
+ }
+
mul_v3_m4v3(local_co, local, co);
local_co[0] = fabs(local_co[0]);
@@ -510,7 +691,6 @@ static int sculpt_brush_test_cyl(SculptBrushTest *test, float co[3], float locat
/* ===== Sculpting =====
*
*/
-
static float overlapped_curve(Brush *br, float x)
{
@@ -734,32 +914,30 @@ static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather)
}
/* Return a multiplier for brush strength on a particular vertex. */
-static float tex_strength(SculptSession *ss, Brush *br, float point[3],
+static float tex_strength(SculptSession *ss, Brush *br,
+ const float point[3],
const float len,
const float sculpt_normal[3],
const short vno[3],
const float fno[3],
const float mask)
{
+ const Scene *scene = ss->cache->vc->scene;
MTex *mtex = &br->mtex;
float avg = 1;
+ float rgba[4];
if (!mtex->tex) {
avg = 1;
}
else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
- float jnk;
-
/* Get strength by feeding the vertex
* location directly into a texture */
- externtex(mtex, point, &avg,
- &jnk, &jnk, &jnk, &jnk, 0);
+ avg = BKE_brush_sample_tex_3D(scene, br, point, rgba, 0, ss->tex_pool);
}
else if (ss->texcache) {
- float rotation = -mtex->rot;
float symm_point[3], point_2d[2];
float x = 0.0f, y = 0.0f; /* Quite warnings */
- float radius = 1.0f; /* Quite warnings */
/* if the active area is being applied for symmetry, flip it
* across the symmetry axis and rotate it back to the original
@@ -773,77 +951,33 @@ static float tex_strength(SculptSession *ss, Brush *br, float point[3],
ED_view3d_project_float_v2_m4(ss->cache->vc->ar, symm_point, point_2d, ss->cache->projection_mat);
- if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
- /* keep coordinates relative to mouse */
-
- rotation += ss->cache->special_rotation;
-
- point_2d[0] -= ss->cache->tex_mouse[0];
- point_2d[1] -= ss->cache->tex_mouse[1];
-
- /* use pressure adjusted size for fixed mode */
- radius = ss->cache->pixel_radius;
-
- x = point_2d[0] + ss->cache->vc->ar->winrct.xmin;
- y = point_2d[1] + ss->cache->vc->ar->winrct.ymin;
- }
- else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) {
- /* leave the coordinates relative to the screen */
-
- /* use unadjusted size for tiled mode */
- radius = BKE_brush_size_get(ss->cache->vc->scene, br);
-
- x = point_2d[0];
- y = point_2d[1];
- }
- else if (mtex->brush_map_mode == MTEX_MAP_MODE_AREA) {
+ /* still no symmetry supported for other paint modes.
+ * Sculpt does it DIY */
+ if (mtex->brush_map_mode == MTEX_MAP_MODE_AREA) {
/* Similar to fixed mode, but projects from brush angle
* rather than view direction */
- /* Rotation is handled by the brush_local_mat */
- rotation = 0;
-
mul_m4_v3(ss->cache->brush_local_mat, symm_point);
x = symm_point[0];
y = symm_point[1];
- }
- if (mtex->brush_map_mode != MTEX_MAP_MODE_AREA) {
- x /= ss->cache->vc->ar->winx;
- y /= ss->cache->vc->ar->winy;
+ x *= br->mtex.size[0];
+ y *= br->mtex.size[1];
- if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) {
- x -= 0.5f;
- y -= 0.5f;
- }
-
- x *= ss->cache->vc->ar->winx / radius;
- y *= ss->cache->vc->ar->winy / radius;
- }
+ x += br->mtex.ofs[0];
+ y += br->mtex.ofs[1];
- /* it is probably worth optimizing for those cases where
- * the texture is not rotated by skipping the calls to
- * atan2, sqrtf, sin, and cos. */
- if (rotation > 0.001f || rotation < -0.001f) {
- const float angle = atan2f(y, x) + rotation;
- const float flen = sqrtf(x * x + y * y);
+ avg = paint_get_tex_pixel(br, x, y, ss->tex_pool);
- x = flen * cosf(angle);
- y = flen * sinf(angle);
+ avg += br->texture_sample_bias;
+ }
+ else {
+ const float point_3d[3] = {point_2d[0], point_2d[1], 0.0f};
+ avg = BKE_brush_sample_tex_3D(scene, br, point_3d, rgba, 0, ss->tex_pool);
}
-
- x *= br->mtex.size[0];
- y *= br->mtex.size[1];
-
- x += br->mtex.ofs[0];
- y += br->mtex.ofs[1];
-
- avg = paint_get_tex_pixel(br, x, y);
}
- avg += br->texture_sample_bias;
-
/* Falloff curve */
avg *= BKE_brush_curve_strength(br, len, ss->cache->radius);
@@ -871,9 +1005,9 @@ static int sculpt_search_sphere_cb(PBVHNode *node, void *data_v)
int i;
if (data->original)
- BLI_pbvh_node_get_original_BB(node, bb_min, bb_max);
+ BKE_pbvh_node_get_original_BB(node, bb_min, bb_max);
else
- BLI_pbvh_node_get_BB(node, bb_min, bb_max);
+ BKE_pbvh_node_get_BB(node, bb_min, bb_max);
for (i = 0; i < 3; ++i) {
if (bb_min[i] > center[i])
@@ -926,6 +1060,11 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod
original = (paint_brush(&sd->paint)->sculpt_tool == SCULPT_TOOL_GRAB ?
TRUE : ss->cache->original);
+ /* In general the original coords are not available with dynamic
+ * topology */
+ if (ss->bm)
+ original = FALSE;
+
(void)sd; /* unused w/o openmp */
zero_v3(an);
@@ -942,7 +1081,7 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod
sculpt_brush_test_init(ss, &test);
if (original) {
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ 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];
@@ -951,10 +1090,10 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod
add_norm_if(ss->cache->view_normal, private_an, private_out_flip, fno);
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
else {
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_fast(&test, vd.co)) {
if (vd.no) {
@@ -968,7 +1107,7 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod
}
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
#pragma omp critical
@@ -1049,11 +1188,12 @@ static void calc_local_y(ViewContext *vc, const float center[3], float y[3])
{
Object *ob = vc->obact;
float loc[3], mval_f[2] = {0.0f, 1.0f};
+ float zfac;
mul_v3_m4v3(loc, ob->imat, center);
- initgrabz(vc->rv3d, loc[0], loc[1], loc[2]);
+ zfac = ED_view3d_calc_zfac(vc->rv3d, loc, NULL);
- ED_view3d_win_to_delta(vc->ar, mval_f, y);
+ ED_view3d_win_to_delta(vc->ar, mval_f, y, zfac);
normalize_v3(y);
add_v3_v3(y, ob->loc);
@@ -1210,6 +1350,71 @@ static float neighbor_average_mask(SculptSession *ss, unsigned vert)
return vmask[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);
+
+ zero_v3(avg);
+
+ /* Don't modify corner vertices */
+ if (vfcount > 1) {
+ BMIter liter;
+ BMLoop *l;
+ 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};
+
+ 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);
+ total++;
+ }
+ }
+ }
+
+ if (total > 0) {
+ mul_v3_fl(avg, 1.0f / total);
+ return;
+ }
+ }
+
+ copy_v3_v3(avg, v->co);
+}
+
+/* Same logic as neighbor_average_mask(), but for bmesh rather than mesh */
+static float bmesh_neighbor_average_mask(BMesh *bm, BMVert *v)
+{
+ BMIter liter;
+ BMLoop *l;
+ float avg = 0;
+ 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};
+
+ for (i = 0; i < 3; i++) {
+ BMVert *v2 = adj_v[i];
+ float *vmask = CustomData_bmesh_get(&bm->vdata,
+ v2->head.data,
+ CD_PAINT_MASK);
+ avg += (*vmask);
+ total++;
+ }
+ }
+
+ if (total > 0) {
+ return avg / (float)total;
+ }
+ else {
+ float *vmask = CustomData_bmesh_get(&bm->vdata,
+ v->head.data,
+ CD_PAINT_MASK);
+ return (*vmask);
+ }
+}
+
static void do_mesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node, float bstrength, int smooth_mask)
{
Brush *brush = paint_brush(&sd->paint);
@@ -1220,7 +1425,7 @@ static void do_mesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node,
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test(&test, vd.co)) {
const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist,
@@ -1248,7 +1453,48 @@ static void do_mesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node,
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
+}
+
+static void do_bmesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node, float bstrength, int smooth_mask)
+{
+ Brush *brush = paint_brush(&sd->paint);
+ PBVHVertexIter vd;
+ SculptBrushTest test;
+
+ CLAMP(bstrength, 0.0f, 1.0f);
+
+ sculpt_brush_test_init(ss, &test);
+
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+ {
+ if (sculpt_brush_test(&test, vd.co)) {
+ const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist,
+ ss->cache->view_normal, 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;
+ val *= fade * bstrength;
+ *vd.mask += val;
+ CLAMP(*vd.mask, 0, 1);
+ }
+ else {
+ float avg[3], val[3];
+
+ bmesh_neighbor_average(avg, vd.bm_vert);
+ sub_v3_v3v3(val, avg, vd.co);
+ mul_v3_fl(val, fade);
+
+ add_v3_v3(val, vd.co);
+
+ sculpt_clip(sd, ss, vd.co, val);
+ }
+
+ if (vd.mvert)
+ vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+ }
+ }
+ BKE_pbvh_vertex_iter_end;
}
static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node,
@@ -1269,9 +1515,9 @@ static void do_multires_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *no
CLAMP(bstrength, 0.0f, 1.0f);
- BLI_pbvh_node_get_grids(ss->pbvh, node, &grid_indices, &totgrid,
+ BKE_pbvh_node_get_grids(ss->pbvh, node, &grid_indices, &totgrid,
NULL, &gridsize, &griddata, &gridadj);
- BLI_pbvh_get_grid_key(ss->pbvh, &key);
+ BKE_pbvh_get_grid_key(ss->pbvh, &key);
thread_num = 0;
#ifdef _OPENMP
@@ -1405,7 +1651,7 @@ static void smooth(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode,
SculptSession *ss = ob->sculpt;
const int max_iterations = 4;
const float fract = 1.0f / max_iterations;
- PBVHType type = BLI_pbvh_type(ss->pbvh);
+ PBVHType type = BKE_pbvh_type(ss->pbvh);
int iteration, n, count;
float last;
@@ -1433,6 +1679,9 @@ static void smooth(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode,
do_mesh_smooth_brush(sd, ss, nodes[n], strength,
smooth_mask);
break;
+ case PBVH_BMESH:
+ do_bmesh_smooth_brush(sd, ss, nodes[n], strength, smooth_mask);
+ break;
}
}
@@ -1462,7 +1711,7 @@ static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test(&test, vd.co)) {
float fade = tex_strength(ss, brush, vd.co, test.dist,
@@ -1474,7 +1723,7 @@ static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot
if (vd.mvert)
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
}
@@ -1514,11 +1763,11 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test(&test, vd.co)) {
/* offset vertex */
@@ -1532,7 +1781,7 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -1570,11 +1819,11 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test(&test, vd.co)) {
/* offset vertex */
@@ -1597,7 +1846,7 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -1614,11 +1863,11 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test(&test, vd.co)) {
float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist,
@@ -1633,7 +1882,7 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -1659,25 +1908,26 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
- SculptUndoNode *unode;
SculptBrushTest test;
- float (*origco)[3];
- short (*origno)[3];
+ SculptOrigVertData orig_data;
float (*proxy)[3];
- unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
- origco = unode->co;
- origno = unode->no;
+ sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]);
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test(&test, origco[vd.i])) {
- const float fade = bstrength * tex_strength(ss, brush, origco[vd.i], test.dist,
- ss->cache->sculpt_normal_symm, origno[vd.i],
+ sculpt_orig_vert_data_update(&orig_data, &vd);
+
+ if (sculpt_brush_test(&test, orig_data.co)) {
+ const float fade = bstrength * tex_strength(ss, brush,
+ orig_data.co,
+ test.dist,
+ ss->cache->sculpt_normal_symm,
+ orig_data.no,
NULL, vd.mask ? *vd.mask : 0.0f);
mul_v3_v3fl(proxy[vd.i], grab_delta, fade);
@@ -1686,7 +1936,7 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -1710,11 +1960,11 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test(&test, vd.co)) {
const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist,
@@ -1727,7 +1977,7 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -1759,11 +2009,11 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test(&test, vd.co)) {
const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist,
@@ -1776,7 +2026,7 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -1797,26 +2047,27 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
- SculptUndoNode *unode;
SculptBrushTest test;
- float (*origco)[3];
- short (*origno)[3];
+ SculptOrigVertData orig_data;
float (*proxy)[3];
- unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
- origco = unode->co;
- origno = unode->no;
+ sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]);
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test(&test, origco[vd.i])) {
- const float fade = bstrength * tex_strength(ss, brush, origco[vd.i], test.dist,
+ sculpt_orig_vert_data_update(&orig_data, &vd);
+
+ if (sculpt_brush_test(&test, orig_data.co)) {
+ const float fade = bstrength * tex_strength(ss, brush,
+ orig_data.co,
+ test.dist,
ss->cache->sculpt_normal_symm,
- origno[vd.i], NULL, vd.mask ? *vd.mask : 0.0f);
+ orig_data.no,
+ NULL, vd.mask ? *vd.mask : 0.0f);
mul_v3_v3fl(proxy[vd.i], cono, fade);
@@ -1824,7 +2075,7 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -1850,36 +2101,37 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
- SculptUndoNode *unode;
SculptBrushTest test;
- float (*origco)[3];
- short (*origno)[3];
+ SculptOrigVertData orig_data;
float (*proxy)[3];
- unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
- origco = unode->co;
- origno = unode->no;
+ sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]);
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test(&test, origco[vd.i])) {
- const float fade = bstrength * tex_strength(ss, brush, origco[vd.i], test.dist,
+ sculpt_orig_vert_data_update(&orig_data, &vd);
+
+ if (sculpt_brush_test(&test, orig_data.co)) {
+ const float fade = bstrength * tex_strength(ss, brush,
+ orig_data.co,
+ test.dist,
ss->cache->sculpt_normal_symm,
- origno[vd.i], NULL, vd.mask ? *vd.mask : 0.0f);
+ orig_data.no,
+ NULL, vd.mask ? *vd.mask : 0.0f);
- mul_v3_m4v3(proxy[vd.i], m, origco[vd.i]);
- sub_v3_v3(proxy[vd.i], origco[vd.i]);
+ mul_v3_m4v3(proxy[vd.i], m, orig_data.co);
+ sub_v3_v3(proxy[vd.i], orig_data.co);
mul_v3_fl(proxy[vd.i], fade);
if (vd.mvert)
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -1901,25 +2153,25 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
- SculptUndoNode *unode;
- float (*origco)[3], *layer_disp;
+ SculptOrigVertData orig_data;
+ float *layer_disp;
/* XXX: layer brush needs conversion to proxy but its more complicated */
- /* proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; */
+ /* proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co; */
- unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
- origco = unode->co;
- if (!unode->layer_disp) {
- #pragma omp critical
- unode->layer_disp = MEM_callocN(sizeof(float) * unode->totvert, "layer disp");
- }
-
- layer_disp = unode->layer_disp;
+ sculpt_orig_vert_data_init(&orig_data, ob, nodes[n]);
+ #pragma omp critical
+ {
+ layer_disp = BKE_pbvh_node_layer_disp_get(ss->pbvh, nodes[n]);
+ }
+
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (sculpt_brush_test(&test, origco[vd.i])) {
+ sculpt_orig_vert_data_update(&orig_data, &vd);
+
+ if (sculpt_brush_test(&test, orig_data.co)) {
const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist,
ss->cache->sculpt_normal_symm,
vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f);
@@ -1941,7 +2193,7 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
add_v3_v3(val, ss->layer_co[index]);
}
else {
- add_v3_v3(val, origco[vd.i]);
+ add_v3_v3(val, orig_data.co);
}
sculpt_clip(sd, ss, vd.co, val);
@@ -1950,7 +2202,7 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -1967,11 +2219,11 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test(&test, vd.co)) {
const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist,
@@ -1989,7 +2241,7 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -2015,25 +2267,25 @@ static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
sculpt_brush_test_init(ss, &test);
- if (ss->cache->original) {
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ 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])) {
add_v3_v3(private_fc, unode->co[vd.i]);
private_count++;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
else {
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_fast(&test, vd.co)) {
add_v3_v3(private_fc, vd.co);
private_count++;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
#pragma omp critical
@@ -2082,8 +2334,8 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob,
unode = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS);
sculpt_brush_test_init(ss, &test);
- if (ss->cache->original) {
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ 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 */
@@ -2097,10 +2349,10 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob,
private_count++;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
else {
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_fast(&test, vd.co)) {
/* for area normal */
@@ -2119,7 +2371,7 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob,
private_count++;
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
#pragma omp critical
@@ -2301,11 +2553,11 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
if (sculpt_brush_test_sq(&test, vd.co)) {
float intr[3];
@@ -2326,7 +2578,7 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
}
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -2373,11 +2625,11 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ 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)) {
@@ -2401,7 +2653,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
}
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -2475,11 +2727,11 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ 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)) {
@@ -2503,7 +2755,7 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
}
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -2539,11 +2791,11 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ 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)) {
@@ -2567,7 +2819,7 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
}
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -2603,11 +2855,11 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
SculptBrushTest test;
float (*proxy)[3];
- proxy = BLI_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
+ proxy = BKE_pbvh_node_add_proxy(ss->pbvh, nodes[n])->co;
sculpt_brush_test_init(ss, &test);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ 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)) {
@@ -2631,7 +2883,7 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
}
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
}
@@ -2688,6 +2940,65 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
BKE_key_convert_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)
+{
+ SculptSession *ss = ob->sculpt;
+ SculptSearchSphereData data;
+ PBVHNode **nodes = NULL;
+ float radius;
+ int n, totnode;
+
+ /* Build a list of all nodes that are potentially within the
+ * brush's area of influence */
+ data.ss = ss;
+ data.sd = sd;
+
+ radius = ss->cache->radius * 1.25f;
+
+ data.radius_squared = radius * radius;
+ data.original = ELEM4(brush->sculpt_tool,
+ SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_THUMB,
+ SCULPT_TOOL_LAYER);
+
+ BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
+
+ /* Only act if some verts are inside the brush area */
+ if (totnode) {
+ PBVHTopologyUpdateMode mode = PBVH_Subdivide;
+
+ if ((sd->flags & SCULPT_DYNTOPO_COLLAPSE) ||
+ (brush->sculpt_tool == SCULPT_TOOL_SIMPLIFY))
+ {
+ mode |= PBVH_Collapse;
+ }
+
+ for (n = 0; n < totnode; n++) {
+ sculpt_undo_push_node(ob, nodes[n],
+ brush->sculpt_tool == SCULPT_TOOL_MASK ?
+ SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS);
+ BKE_pbvh_node_mark_update(nodes[n]);
+
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ BKE_pbvh_node_mark_topology_update(nodes[n]);
+ BKE_pbvh_bmesh_node_save_orig(nodes[n]);
+ }
+ }
+
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ BKE_pbvh_bmesh_update_topology(ss->pbvh, mode,
+ ss->cache->location,
+ ss->cache->radius);
+ }
+
+ MEM_freeN(nodes);
+ }
+}
+
static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
{
SculptSession *ss = ob->sculpt;
@@ -2704,7 +3015,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
SCULPT_TOOL_ROTATE,
SCULPT_TOOL_THUMB,
SCULPT_TOOL_LAYER);
- BLI_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
+ BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
/* Only act if some verts are inside the brush area */
if (totnode) {
@@ -2713,7 +3024,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
sculpt_undo_push_node(ob, nodes[n],
brush->sculpt_tool == SCULPT_TOOL_MASK ?
SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS);
- BLI_pbvh_node_mark_update(nodes[n]);
+ BKE_pbvh_node_mark_update(nodes[n]);
}
if (brush_needs_sculpt_normal(brush))
@@ -2821,7 +3132,7 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
PBVHNode **nodes;
int totnode, n;
- BLI_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode);
+ BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode);
if (!ELEM(brush->sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_LAYER)) {
/* these brushes start from original coordinates */
@@ -2833,20 +3144,27 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
PBVHVertexIter vd;
PBVHProxyNode *proxies;
int proxy_count;
- float (*orco)[3];
+ float (*orco)[3] = NULL;
- if (use_orco)
+ if (use_orco && !ss->bm)
orco = sculpt_undo_push_node(ob, nodes[n], SCULPT_UNDO_COORDS)->co;
- BLI_pbvh_node_get_proxies(nodes[n], &proxies, &proxy_count);
+ BKE_pbvh_node_get_proxies(nodes[n], &proxies, &proxy_count);
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
float val[3];
int p;
- if (use_orco)
- copy_v3_v3(val, orco[vd.i]);
+ if (use_orco) {
+ if (ss->bm) {
+ copy_v3_v3(val,
+ BM_log_original_vert_co(ss->bm_log,
+ vd.bm_vert));
+ }
+ else
+ copy_v3_v3(val, orco[vd.i]);
+ }
else
copy_v3_v3(val, vd.co);
@@ -2858,9 +3176,9 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
if (ss->modifiers_active)
sculpt_flush_pbvhvert_deform(ob, &vd);
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
- BLI_pbvh_node_free_proxies(nodes[n]);
+ BKE_pbvh_node_free_proxies(nodes[n]);
}
}
@@ -2877,7 +3195,7 @@ static void sculpt_update_keyblock(Object *ob)
/* Keyblock update happens after handling deformation caused by modifiers,
* so ss->orig_cos would be updated with new stroke */
if (ss->orig_cos) vertCos = ss->orig_cos;
- else vertCos = BLI_pbvh_get_vertCos(ss->pbvh);
+ else vertCos = BKE_pbvh_get_vertCos(ss->pbvh);
if (vertCos) {
sculpt_vertcos_to_key(ob, ss->kb, vertCos);
@@ -2905,13 +3223,13 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob)
if (ss->kb)
vertCos = MEM_callocN(sizeof(*vertCos) * me->totvert, "flushStrokeDeofrm keyVerts");
- BLI_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
- BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE)
{
sculpt_flush_pbvhvert_deform(ob, &vd);
@@ -2920,7 +3238,7 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob)
copy_v3_v3(vertCos[index], ss->orig_cos[index]);
}
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
if (vertCos) {
@@ -2978,7 +3296,10 @@ static void calc_brushdata_symm(Sculpt *sd, StrokeCache *cache, const char symm,
mul_m4_v3(cache->symm_rot_mat, cache->grab_delta_symmetry);
}
+typedef void (*BrushActionFunc)(Sculpt *sd, Object *ob, Brush *brush);
+
static void do_radial_symmetry(Sculpt *sd, Object *ob, Brush *brush,
+ BrushActionFunc action,
const char symm, const int axis,
const float feather)
{
@@ -2989,7 +3310,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);
- do_brush_action(sd, ob, brush);
+ action(sd, ob, brush);
}
}
@@ -3006,7 +3327,8 @@ static void sculpt_fix_noise_tear(Sculpt *sd, Object *ob)
multires_stitch_grids(ob);
}
-static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob)
+static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob,
+ BrushActionFunc action)
{
Brush *brush = paint_brush(&sd->paint);
SculptSession *ss = ob->sculpt;
@@ -3017,7 +3339,6 @@ static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob)
float feather = calc_symmetry_feather(sd, ss->cache);
cache->bstrength = brush_strength(sd, cache, feather);
-
cache->symmetry = symm;
/* symm is a bit combination of XYZ - 1 is mirror X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
@@ -3027,23 +3348,13 @@ static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob)
cache->radial_symmetry_pass = 0;
calc_brushdata_symm(sd, cache, i, 0, 0, feather);
- do_brush_action(sd, ob, brush);
+ action(sd, ob, brush);
- do_radial_symmetry(sd, ob, brush, i, 'X', feather);
- do_radial_symmetry(sd, ob, brush, i, 'Y', feather);
- do_radial_symmetry(sd, ob, brush, i, 'Z', feather);
+ 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);
}
}
-
- sculpt_combine_proxies(sd, ob);
-
- /* hack to fix noise texture tearing mesh */
- sculpt_fix_noise_tear(sd, ob);
-
- if (ss->modifiers_active)
- sculpt_flush_stroke_deform(sd, ob);
-
- cache->first_time = 0;
}
static void sculpt_update_tex(const Scene *scene, Sculpt *sd, SculptSession *ss)
@@ -3056,11 +3367,17 @@ static void sculpt_update_tex(const Scene *scene, Sculpt *sd, SculptSession *ss)
ss->texcache = NULL;
}
+ if (ss->tex_pool) {
+ BKE_image_pool_free(ss->tex_pool);
+ ss->tex_pool = NULL;
+ }
+
/* Need to allocate a bigger buffer for bigger brush size */
ss->texcache_side = 2 * radius;
if (!ss->texcache || ss->texcache_side > ss->texcache_actual) {
ss->texcache = BKE_brush_gen_texture_cache(brush, radius);
ss->texcache_actual = ss->texcache_side;
+ ss->tex_pool = BKE_image_pool_new();
}
}
@@ -3142,22 +3459,24 @@ void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
ss->orig_cos = (ss->kb) ? BKE_key_convert_to_vertcos(ob, ss->kb) : mesh_getVertexCos(me, NULL);
crazyspace_build_sculpt(scene, ob, &ss->deform_imats, &ss->deform_cos);
- BLI_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos);
+ BKE_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos);
for (a = 0; a < me->totvert; ++a) {
invert_m3(ss->deform_imats[a]);
}
}
}
- else free_sculptsession_deformMats(ss);
+ else {
+ free_sculptsession_deformMats(ss);
+ }
/* if pbvh is deformed, key block is already applied to it */
- if (ss->kb && !BLI_pbvh_isDeformed(ss->pbvh)) {
+ if (ss->kb && !BKE_pbvh_isDeformed(ss->pbvh)) {
float (*vertCos)[3] = BKE_key_convert_to_vertcos(ob, ss->kb);
if (vertCos) {
/* apply shape keys coordinates to PBVH */
- BLI_pbvh_apply_vertCos(ss->pbvh, vertCos);
+ BKE_pbvh_apply_vertCos(ss->pbvh, vertCos);
MEM_freeN(vertCos);
}
}
@@ -3220,6 +3539,8 @@ static const char *sculpt_tool_name(Sculpt *sd)
return "Rotate Brush";
case SCULPT_TOOL_MASK:
return "Mask Brush";
+ case SCULPT_TOOL_SIMPLIFY:
+ return "Simplify Brush";
}
return "Sculpting";
@@ -3291,7 +3612,7 @@ static void sculpt_omp_start(Sculpt *sd, SculptSession *ss)
if (ss->multires) {
int i, gridsize, array_mem_size;
- BLI_pbvh_node_get_grids(ss->pbvh, NULL, NULL, NULL, NULL,
+ BKE_pbvh_node_get_grids(ss->pbvh, NULL, NULL, NULL, NULL,
&gridsize, NULL, NULL);
array_mem_size = cache->num_threads * sizeof(void *);
@@ -3336,30 +3657,32 @@ static void sculpt_omp_done(SculptSession *ss)
static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSession *ss, wmOperator *op, const float mouse[2])
{
StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
+ UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
Brush *brush = paint_brush(&sd->paint);
ViewContext *vc = paint_stroke_view_context(op->customdata);
Object *ob = CTX_data_active_object(C);
+ float rot[3][3], scale[3], loc[3];
int i;
int mode;
ss->cache = cache;
/* Set scaling adjustment */
- ss->cache->scale[0] = 1.0f / ob->size[0];
- ss->cache->scale[1] = 1.0f / ob->size[1];
- ss->cache->scale[2] = 1.0f / ob->size[2];
+ cache->scale[0] = 1.0f / ob->size[0];
+ cache->scale[1] = 1.0f / ob->size[1];
+ cache->scale[2] = 1.0f / ob->size[2];
- ss->cache->plane_trim_squared = brush->plane_trim * brush->plane_trim;
+ cache->plane_trim_squared = brush->plane_trim * brush->plane_trim;
- ss->cache->flag = 0;
+ cache->flag = 0;
sculpt_init_mirror_clipping(ob, ss);
/* Initial mouse location */
if (mouse)
- copy_v2_v2(ss->cache->initial_mouse, mouse);
+ copy_v2_v2(cache->initial_mouse, mouse);
else
- zero_v2(ss->cache->initial_mouse);
+ zero_v2(cache->initial_mouse);
mode = RNA_enum_get(op->ptr, "mode");
cache->invert = mode == BRUSH_STROKE_INVERT;
@@ -3371,7 +3694,7 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
else brush->flag &= ~BRUSH_INVERTED;
/* Alt-Smooth */
- if (ss->cache->alt_smooth) {
+ if (cache->alt_smooth) {
if (brush->sculpt_tool == SCULPT_TOOL_MASK) {
cache->saved_mask_brush_tool = brush->mask_tool;
brush->mask_tool = BRUSH_MASK_SMOOTH;
@@ -3392,7 +3715,7 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
}
copy_v2_v2(cache->mouse, cache->initial_mouse);
- copy_v2_v2(cache->tex_mouse, cache->initial_mouse);
+ copy_v2_v2(ups->tex_mouse, cache->initial_mouse);
/* Truly temporary data that isn't stored in properties */
@@ -3403,16 +3726,25 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
/* cache projection matrix */
ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat);
+ mat4_to_loc_rot_size(loc, rot, scale, ob->obmat);
+ /* transposing an orthonormal matrix inverts */
+ transpose_m3(rot);
ED_view3d_global_to_vector(cache->vc->rv3d, cache->vc->rv3d->twmat[3], cache->true_view_normal);
+ /* This takes care of rotated mesh. Instead of rotating every normal, we inverse rotate view normal. */
+ mul_m3_v3(rot, cache->true_view_normal);
/* Initialize layer brush displacements and persistent coords */
if (brush->sculpt_tool == SCULPT_TOOL_LAYER) {
- /* not supported yet for multires */
- if (!ss->multires && !ss->layer_co && (brush->flag & BRUSH_PERSISTENT)) {
+ /* not supported yet for multires or dynamic topology */
+ if (!ss->multires && !ss->bm && !ss->layer_co &&
+ (brush->flag & BRUSH_PERSISTENT))
+ {
if (!ss->layer_co)
ss->layer_co = MEM_mallocN(sizeof(float) * 3 * ss->totvert,
"sculpt mesh vertices copy");
- if (ss->deform_cos) memcpy(ss->layer_co, ss->deform_cos, ss->totvert);
+ if (ss->deform_cos) {
+ memcpy(ss->layer_co, ss->deform_cos, ss->totvert);
+ }
else {
for (i = 0; i < ss->totvert; ++i) {
copy_v3_v3(ss->layer_co[i], ss->mvert[i].co);
@@ -3443,8 +3775,6 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
}
}
- cache->special_rotation = (brush->flag & BRUSH_RAKE) ? sd->last_angle : 0;
-
cache->first_time = 1;
cache->vertex_rotation = 0;
@@ -3452,13 +3782,13 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
sculpt_omp_start(sd, ss);
}
-static void sculpt_update_brush_delta(Sculpt *sd, Object *ob, Brush *brush)
+static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Brush *brush)
{
SculptSession *ss = ob->sculpt;
StrokeCache *cache = ss->cache;
float mouse[2] = {
- cache->mouse[0] - cache->vc->ar->winrct.xmin,
- cache->mouse[1] - cache->vc->ar->winrct.ymin
+ cache->mouse[0],
+ cache->mouse[1]
};
int tool = brush->sculpt_tool;
@@ -3478,8 +3808,6 @@ static void sculpt_update_brush_delta(Sculpt *sd, Object *ob, Brush *brush)
/* compute 3d coordinate at same z from original location + mouse */
mul_v3_m4v3(loc, ob->obmat, cache->orig_grab_location);
- initgrabz(cache->vc->rv3d, loc[0], loc[1], loc[2]);
-
ED_view3d_win_to_3d(cache->vc->ar, loc, mouse, grab_location);
/* compute delta to move verts by */
@@ -3517,17 +3845,17 @@ static void sculpt_update_brush_delta(Sculpt *sd, Object *ob, Brush *brush)
copy_v3_v3(cache->old_grab_location, grab_location);
if (tool == SCULPT_TOOL_GRAB)
- copy_v3_v3(sd->anchored_location, cache->true_location);
+ copy_v3_v3(cache->anchored_location, cache->true_location);
else if (tool == SCULPT_TOOL_THUMB)
- copy_v3_v3(sd->anchored_location, cache->orig_grab_location);
+ copy_v3_v3(cache->anchored_location, cache->orig_grab_location);
if (ELEM(tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB)) {
/* location stays the same for finding vertices in brush radius */
copy_v3_v3(cache->true_location, cache->orig_grab_location);
- sd->draw_anchored = 1;
- copy_v2_v2(sd->anchored_initial_mouse, cache->initial_mouse);
- sd->anchored_size = cache->pixel_radius;
+ ups->draw_anchored = 1;
+ copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse);
+ ups->anchored_size = ups->pixel_radius;
}
}
}
@@ -3538,6 +3866,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob,
PointerRNA *ptr)
{
Scene *scene = CTX_data_scene(C);
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
SculptSession *ss = ob->sculpt;
StrokeCache *cache = ss->cache;
Brush *brush = paint_brush(&sd->paint);
@@ -3561,17 +3890,11 @@ 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_space_stroke_enabled(brush) || cache->first_time)
+ if (paint_supports_dynamic_size(brush, PAINT_SCULPT) || cache->first_time) {
cache->pressure = RNA_float_get(ptr, "pressure");
+ }
/* Truly temporary data that isn't stored in properties */
-
- sd->draw_pressure = 1;
- sd->pressure_value = cache->pressure;
-
- cache->previous_pixel_radius = cache->pixel_radius;
- cache->pixel_radius = BKE_brush_size_get(scene, brush);
-
if (cache->first_time) {
if (!BKE_brush_use_locked_size(scene, brush)) {
cache->initial_radius = paint_calc_object_space_radius(cache->vc,
@@ -3584,89 +3907,37 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob,
}
}
- if (BKE_brush_use_size_pressure(scene, brush)) {
- cache->pixel_radius *= cache->pressure;
+ if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, PAINT_SCULPT)) {
cache->radius = cache->initial_radius * cache->pressure;
}
- else
+ else {
cache->radius = cache->initial_radius;
+ }
cache->radius_squared = cache->radius * cache->radius;
- if (!(brush->flag & BRUSH_ANCHORED ||
- ELEM4(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK,
- SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE)))
- {
- copy_v2_v2(cache->tex_mouse, cache->mouse);
-
- if ((brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) &&
- (brush->flag & BRUSH_RANDOM_ROTATION) &&
- !(brush->flag & BRUSH_RAKE))
- {
- cache->special_rotation = 2.0f * (float)M_PI * BLI_frand();
- }
- }
-
if (brush->flag & BRUSH_ANCHORED) {
- int hit = 0;
-
- const float dx = cache->mouse[0] - cache->initial_mouse[0];
- const float dy = cache->mouse[1] - cache->initial_mouse[1];
-
- sd->anchored_size = cache->pixel_radius = sqrt(dx * dx + dy * dy);
-
- cache->special_rotation = atan2(dx, dy) + M_PI;
-
if (brush->flag & BRUSH_EDGE_TO_EDGE) {
float halfway[2];
float out[3];
-
- halfway[0] = dx * 0.5f + cache->initial_mouse[0];
- halfway[1] = dy * 0.5f + cache->initial_mouse[1];
+ halfway[0] = 0.5f * (cache->mouse[0] + cache->initial_mouse[0]);
+ halfway[1] = 0.5f * (cache->mouse[1] + cache->initial_mouse[1]);
if (sculpt_stroke_get_location(C, out, halfway)) {
- copy_v3_v3(sd->anchored_location, out);
- copy_v2_v2(sd->anchored_initial_mouse, halfway);
- copy_v2_v2(cache->tex_mouse, halfway);
- copy_v3_v3(cache->true_location, sd->anchored_location);
- sd->anchored_size /= 2.0f;
- cache->pixel_radius /= 2.0f;
- hit = 1;
+ copy_v3_v3(cache->anchored_location, out);
+ copy_v3_v3(cache->true_location, cache->anchored_location);
}
}
- if (!hit)
- copy_v2_v2(sd->anchored_initial_mouse, cache->initial_mouse);
-
cache->radius = paint_calc_object_space_radius(paint_stroke_view_context(stroke),
cache->true_location,
- cache->pixel_radius);
+ ups->pixel_radius);
cache->radius_squared = cache->radius * cache->radius;
- copy_v3_v3(sd->anchored_location, cache->true_location);
-
- sd->draw_anchored = 1;
- }
- else if (brush->flag & BRUSH_RAKE) {
- const float u = 0.5f;
- const float v = 1 - u;
- const float r = 20;
-
- const float dx = cache->last_rake[0] - cache->mouse[0];
- const float dy = cache->last_rake[1] - cache->mouse[1];
-
- if (cache->first_time) {
- copy_v2_v2(cache->last_rake, cache->mouse);
- }
- else if (dx * dx + dy * dy >= r * r) {
- cache->special_rotation = atan2(dx, dy);
-
- cache->last_rake[0] = u * cache->last_rake[0] + v * cache->mouse[0];
- cache->last_rake[1] = u * cache->last_rake[1] + v * cache->mouse[1];
- }
+ copy_v3_v3(cache->anchored_location, cache->true_location);
}
- sculpt_update_brush_delta(sd, ob, brush);
+ sculpt_update_brush_delta(ups, ob, brush);
if (brush->sculpt_tool == SCULPT_TOOL_ROTATE) {
const float dx = cache->mouse[0] - cache->initial_mouse[0];
@@ -3674,16 +3945,16 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob,
cache->vertex_rotation = -atan2f(dx, dy) * cache->bstrength;
- sd->draw_anchored = 1;
- copy_v2_v2(sd->anchored_initial_mouse, cache->initial_mouse);
- copy_v3_v3(sd->anchored_location, cache->true_location);
- sd->anchored_size = cache->pixel_radius;
+ ups->draw_anchored = 1;
+ copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse);
+ copy_v3_v3(cache->anchored_location, cache->true_location);
+ ups->anchored_size = ups->pixel_radius;
}
- sd->special_rotation = cache->special_rotation;
+ cache->special_rotation = ups->brush_rotation;
}
-/* Returns true iff any of the smoothing modes are active (currently
+/* Returns true if any of the smoothing modes are active (currently
* one of smooth brush, autosmooth, mask smooth, or shift-key
* smooth) */
static int sculpt_any_smooth_mode(const Brush *brush,
@@ -3721,17 +3992,26 @@ typedef struct {
static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
{
- if (BLI_pbvh_node_get_tmin(node) < *tmin) {
+ if (BKE_pbvh_node_get_tmin(node) < *tmin) {
SculptRaycastData *srd = data_v;
float (*origco)[3] = NULL;
+ int use_origco = FALSE;
if (srd->original && srd->ss->cache) {
- /* intersect with coordinates from before we started stroke */
- SculptUndoNode *unode = sculpt_undo_get_node(node);
- origco = (unode) ? unode->co : NULL;
+ if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) {
+ use_origco = TRUE;
+ }
+ else {
+ /* intersect with coordinates from before we started stroke */
+ SculptUndoNode *unode = sculpt_undo_get_node(node);
+ origco = (unode) ? unode->co : NULL;
+ use_origco = origco ? TRUE : FALSE;
+ }
}
- if (BLI_pbvh_node_raycast(srd->ss->pbvh, node, origco, srd->ray_start, srd->ray_normal, &srd->dist)) {
+ if (BKE_pbvh_node_raycast(srd->ss->pbvh, node, origco, use_origco,
+ srd->ray_start, srd->ray_normal, &srd->dist))
+ {
srd->hit = 1;
*tmin = srd->dist;
}
@@ -3750,7 +4030,6 @@ int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
StrokeCache *cache;
float ray_start[3], ray_end[3], ray_normal[3], dist;
float obimat[4][4];
- float mval[2];
SculptRaycastData srd;
view3d_set_viewcontext(C, &vc);
@@ -3761,11 +4040,8 @@ int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
sculpt_stroke_modifiers_check(C, ob);
- mval[0] = mouse[0] - vc.ar->winrct.xmin;
- mval[1] = mouse[1] - vc.ar->winrct.ymin;
-
/* TODO: what if the segment is totally clipped? (return == 0) */
- ED_view3d_win_to_segment_clip(vc.ar, vc.v3d, mval, ray_start, ray_end);
+ ED_view3d_win_to_segment_clip(vc.ar, vc.v3d, mouse, ray_start, ray_end);
invert_m4_m4(obimat, ob->obmat);
mul_m4_v3(obimat, ray_start);
@@ -3780,7 +4056,7 @@ int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
srd.dist = dist;
srd.hit = 0;
srd.original = (cache) ? cache->original : 0;
- BLI_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd,
+ BKE_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd,
ray_start, ray_normal, srd.original);
copy_v3_v3(out, ray_normal);
@@ -3797,7 +4073,7 @@ static void sculpt_brush_init_tex(const Scene *scene, Sculpt *sd, SculptSession
/* init mtex nodes */
if (mtex->tex && mtex->tex->nodetree)
- ntreeTexBeginExecTree(mtex->tex->nodetree, 1); /* has internal flag to detect it only does it once */
+ ntreeTexBeginExecTree(mtex->tex->nodetree); /* has internal flag to detect it only does it once */
/* TODO: Shouldn't really have to do this at the start of every
* stroke, but sculpt would need some sort of notification when
@@ -3829,8 +4105,9 @@ static int sculpt_brush_stroke_init(bContext *C, wmOperator *op)
return 1;
}
-static void sculpt_restore_mesh(Sculpt *sd, SculptSession *ss)
+static void sculpt_restore_mesh(Sculpt *sd, Object *ob)
{
+ SculptSession *ss = ob->sculpt;
Brush *brush = paint_brush(&sd->paint);
/* Restore the mesh before continuing with anchored stroke */
@@ -3839,7 +4116,18 @@ static void sculpt_restore_mesh(Sculpt *sd, SculptSession *ss)
BKE_brush_use_size_pressure(ss->cache->vc->scene, brush)) ||
(brush->flag & BRUSH_RESTORE_MESH))
{
- paint_mesh_restore_co(sd, ss);
+ paint_mesh_restore_co(sd, ob);
+ }
+}
+
+/* Copy the PBVH bounding box into the object's bounding box */
+static void sculpt_update_object_bounding_box(Object *ob)
+{
+ if (ob->bb) {
+ float bb_min[3], bb_max[3];
+
+ BKE_pbvh_bounding_box(ob->sculpt->pbvh, bb_min, bb_max);
+ BKE_boundbox_init_from_minmax(ob->bb, bb_min, bb_max);
}
}
@@ -3862,7 +4150,12 @@ static void sculpt_flush_update(bContext *C)
else {
rcti r;
- BLI_pbvh_update(ss->pbvh, PBVH_UpdateBB, NULL);
+ BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB, NULL);
+ /* Update the object's bounding box too so that the object
+ * doesn't get incorrectly clipped during drawing in
+ * draw_mesh_object(). [#33790] */
+ sculpt_update_object_bounding_box(ob);
+
if (sculpt_get_redraw_rect(ar, CTX_wm_region_view3d(C), ob, &r)) {
if (ss->cache)
ss->cache->previous_r = r;
@@ -3914,14 +4207,37 @@ static int sculpt_stroke_test_start(bContext *C, struct wmOperator *op,
static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
{
+ UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
+ const Brush *brush = paint_brush(&sd->paint);
sculpt_stroke_modifiers_check(C, ob);
sculpt_update_cache_variants(C, sd, ob, stroke, itemptr);
- sculpt_restore_mesh(sd, ss);
- do_symmetrical_brush_actions(sd, ob);
+ sculpt_restore_mesh(sd, ob);
+
+ BKE_pbvh_bmesh_detail_size_set(ss->pbvh,
+ (ss->cache->radius /
+ (float)ups->pixel_radius) *
+ (float)sd->detail_size);
+
+ if (sculpt_stroke_dynamic_topology(ss, brush)) {
+ do_symmetrical_brush_actions(sd, ob, sculpt_topology_update);
+ }
+
+ if (paint_brush(&sd->paint)->sculpt_tool != SCULPT_TOOL_SIMPLIFY)
+ do_symmetrical_brush_actions(sd, ob, do_brush_action);
+
+ sculpt_combine_proxies(sd, ob);
+
+ /* hack to fix noise texture tearing mesh */
+ sculpt_fix_noise_tear(sd, ob);
+
+ if (ss->modifiers_active)
+ sculpt_flush_stroke_deform(sd, ob);
+
+ ss->cache->first_time = FALSE;
/* Cleanup */
sculpt_flush_update(C);
@@ -3933,11 +4249,12 @@ static void sculpt_brush_exit_tex(Sculpt *sd)
MTex *mtex = &brush->mtex;
if (mtex->tex && mtex->tex->nodetree)
- ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1);
+ ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
}
static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(stroke))
{
+ UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
@@ -3945,9 +4262,8 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
sculpt_omp_done(ss);
/* reset values used to draw brush after completing the stroke */
- sd->draw_anchored = 0;
- sd->draw_pressure = 0;
- sd->special_rotation = 0;
+ ups->draw_anchored = 0;
+ ups->draw_pressure = 0;
/* Finished */
if (ss->cache) {
@@ -3980,7 +4296,10 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
sculpt_undo_push_end();
- BLI_pbvh_update(ss->pbvh, PBVH_UpdateOriginalBB, NULL);
+ BKE_pbvh_update(ss->pbvh, PBVH_UpdateOriginalBB, NULL);
+
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH)
+ BKE_pbvh_bmesh_after_stroke(ss->pbvh);
/* optimization: if there is locked key and active modifiers present in */
/* the stack, keyblock is updating at each step. otherwise we could update */
@@ -3999,7 +4318,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
sculpt_brush_exit_tex(sd);
}
-static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
struct PaintStroke *stroke;
int ignore_background_click;
@@ -4016,8 +4335,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *even
op->customdata = stroke;
/* For tablet rotation */
- ignore_background_click = RNA_boolean_get(op->ptr,
- "ignore_background_click");
+ ignore_background_click = RNA_boolean_get(op->ptr, "ignore_background_click");
if (ignore_background_click && !over_mesh(C, op, event->x, event->y)) {
paint_stroke_data_free(op);
@@ -4055,7 +4373,7 @@ static int sculpt_brush_stroke_cancel(bContext *C, wmOperator *op)
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
if (ss->cache) {
- paint_mesh_restore_co(sd, ss);
+ paint_mesh_restore_co(sd, ob);
}
paint_stroke_cancel(C, op);
@@ -4096,8 +4414,7 @@ static void SCULPT_OT_brush_stroke(wmOperatorType *ot)
/* properties */
- RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement,
- "Stroke", "");
+ RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
RNA_def_enum(ot->srna, "mode", stroke_mode_items, BRUSH_STROKE_NORMAL,
"Sculpt Stroke Mode",
@@ -4137,6 +4454,265 @@ static void SCULPT_OT_set_persistent_base(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/************************** Dynamic Topology **************************/
+
+static void sculpt_dynamic_topology_triangulate(BMesh *bm)
+{
+ BM_mesh_triangulate(bm, false, false, NULL, NULL);
+}
+
+void sculpt_pbvh_clear(Object *ob)
+{
+ SculptSession *ss = ob->sculpt;
+ DerivedMesh *dm = ob->derivedFinal;
+
+ /* Clear out any existing DM and PBVH */
+ if (ss->pbvh)
+ BKE_pbvh_free(ss->pbvh);
+ ss->pbvh = NULL;
+ if (dm)
+ dm->getPBVH(NULL, dm);
+ BKE_object_free_display(ob);
+}
+
+void sculpt_update_after_dynamic_topology_toggle(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ Sculpt *sd = scene->toolsettings->sculpt;
+
+ /* Create the PBVH */
+ sculpt_update_mesh_elements(scene, sd, ob, FALSE, FALSE);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+}
+
+void sculpt_dynamic_topology_enable(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ Mesh *me = ob->data;
+
+ sculpt_pbvh_clear(ob);
+
+ ss->bm_smooth_shading = (scene->toolsettings->sculpt->flags &
+ SCULPT_DYNTOPO_SMOOTH_SHADING);
+
+ /* Create triangles-only BMesh */
+ ss->bm = BM_mesh_create(&bm_mesh_allocsize_default);
+
+ BM_mesh_bm_from_me(ss->bm, me, TRUE, ob->shapenr);
+ BM_mesh_normals_update(ss->bm, false);
+ sculpt_dynamic_topology_triangulate(ss->bm);
+ BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK);
+ BM_mesh_normals_update(ss->bm, TRUE);
+
+ /* Enable dynamic topology */
+ me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
+
+ /* Enable logging for undo/redo */
+ ss->bm_log = BM_log_create(ss->bm);
+
+ /* Refresh */
+ sculpt_update_after_dynamic_topology_toggle(C);
+}
+
+/* Free the sculpt BMesh and BMLog
+ *
+ * If 'unode' is given, the BMesh's data is copied out to the unode
+ * before the BMesh is deleted so that it can be restored from */
+void sculpt_dynamic_topology_disable(bContext *C,
+ SculptUndoNode *unode)
+{
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+ Mesh *me = ob->data;
+
+ sculpt_pbvh_clear(ob);
+
+ if (unode) {
+ /* Free all existing custom data */
+ CustomData_free(&me->vdata, me->totvert);
+ CustomData_free(&me->edata, me->totedge);
+ CustomData_free(&me->fdata, me->totface);
+ CustomData_free(&me->ldata, me->totloop);
+ CustomData_free(&me->pdata, me->totpoly);
+
+ /* Copy over stored custom data */
+ me->totvert = unode->bm_enter_totvert;
+ me->totloop = unode->bm_enter_totloop;
+ me->totpoly = unode->bm_enter_totpoly;
+ me->totedge = unode->bm_enter_totedge;
+ me->totface = 0;
+ CustomData_copy(&unode->bm_enter_vdata, &me->vdata, CD_MASK_MESH,
+ CD_DUPLICATE, unode->bm_enter_totvert);
+ CustomData_copy(&unode->bm_enter_edata, &me->edata, CD_MASK_MESH,
+ CD_DUPLICATE, unode->bm_enter_totedge);
+ CustomData_copy(&unode->bm_enter_ldata, &me->ldata, CD_MASK_MESH,
+ CD_DUPLICATE, unode->bm_enter_totloop);
+ CustomData_copy(&unode->bm_enter_pdata, &me->pdata, CD_MASK_MESH,
+ CD_DUPLICATE, unode->bm_enter_totpoly);
+
+ BKE_mesh_update_customdata_pointers(me, false);
+ }
+ else {
+ sculptsession_bm_to_me(ob, TRUE);
+ }
+
+ BM_mesh_free(ss->bm);
+
+ /* Clear data */
+ me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY;
+ ss->bm = NULL;
+ BM_log_free(ss->bm_log);
+ ss->bm_log = NULL;
+
+ /* Refresh */
+ sculpt_update_after_dynamic_topology_toggle(C);
+}
+
+static int sculpt_dynamic_topology_toggle_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = CTX_data_active_object(C);
+ SculptSession *ss = ob->sculpt;
+
+ if (ss->bm) {
+ sculpt_undo_push_begin("Dynamic topology disable");
+ sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_END);
+ sculpt_dynamic_topology_disable(C, NULL);
+ }
+ else {
+ sculpt_undo_push_begin("Dynamic topology enable");
+ sculpt_dynamic_topology_enable(C);
+ sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
+ }
+ sculpt_undo_push_end();
+
+ return OPERATOR_FINISHED;
+}
+
+static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ Object *ob = CTX_data_active_object(C);
+ Mesh *me = ob->data;
+ SculptSession *ss = ob->sculpt;
+ const char *msg = TIP_("Dynamic-topology sculpting will not preserve vertex colors, UVs, or other customdata");
+
+ if (!ss->bm) {
+ int i;
+
+ for (i = 0; i < CD_NUMTYPES; i++) {
+ if (!ELEM7(i, CD_MVERT, CD_MEDGE, CD_MFACE, CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX) &&
+ (CustomData_has_layer(&me->vdata, i) ||
+ CustomData_has_layer(&me->edata, i) ||
+ CustomData_has_layer(&me->fdata, i)))
+ {
+ /* The mesh has customdata that will be lost, let the user confirm this is OK */
+ return WM_operator_confirm_message(C, op, msg);
+ }
+ }
+ }
+
+ return sculpt_dynamic_topology_toggle_exec(C, op);
+}
+
+static void SCULPT_OT_dynamic_topology_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Dynamic Topology Toggle";
+ ot->idname = "SCULPT_OT_dynamic_topology_toggle";
+ ot->description = "Dynamic topology alters the mesh topology while sculpting";
+
+ /* api callbacks */
+ ot->invoke = sculpt_dynamic_topology_toggle_invoke;
+ ot->exec = sculpt_dynamic_topology_toggle_exec;
+ ot->poll = sculpt_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/************************* SCULPT_OT_optimize *************************/
+
+static int sculpt_optimize_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = CTX_data_active_object(C);
+
+ sculpt_pbvh_clear(ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int sculpt_and_dynamic_topology_poll(bContext *C)
+{
+ Object *ob = CTX_data_active_object(C);
+
+ return sculpt_mode_poll(C) && ob->sculpt->bm;
+}
+
+/* The BVH gets less optimal more quickly with dynamic topology than
+ * regular sculpting. There is no doubt more clever stuff we can do to
+ * optimize it on the fly, but for now this gives the user a nicer way
+ * to recalculate it than toggling modes. */
+static void SCULPT_OT_optimize(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Optimize";
+ ot->idname = "SCULPT_OT_optimize";
+ ot->description = "Recalculate the sculpt BVH to improve performance";
+
+ /* api callbacks */
+ ot->exec = sculpt_optimize_exec;
+ ot->poll = sculpt_and_dynamic_topology_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/********************* Dynamic topology symmetrize ********************/
+
+static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = CTX_data_active_object(C);
+ const Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ SculptSession *ss = ob->sculpt;
+
+ /* To simplify undo for symmetrize, all BMesh elements are logged
+ * as deleted, then after symmetrize operation all BMesh elements
+ * are logged as added (as opposed to attempting to store just the
+ * parts that symmetrize modifies) */
+ sculpt_undo_push_begin("Dynamic topology symmetrize");
+ sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_SYMMETRIZE);
+ BM_log_before_all_removed(ss->bm, ss->bm_log);
+
+ /* Symmetrize and re-triangulate */
+ BMO_op_callf(ss->bm, BMO_FLAG_DEFAULTS,
+ "symmetrize input=%avef direction=%i",
+ sd->symmetrize_direction);
+ sculpt_dynamic_topology_triangulate(ss->bm);
+
+ /* Finish undo */
+ BM_log_all_added(ss->bm, ss->bm_log);
+ sculpt_undo_push_end();
+
+ /* Redraw */
+ sculpt_pbvh_clear(ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static void SCULPT_OT_symmetrize(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Symmetrize";
+ ot->idname = "SCULPT_OT_symmetrize";
+ ot->description = "Symmetrize the topology modifications";
+
+ /* api callbacks */
+ ot->exec = sculpt_symmetrize_exec;
+ ot->poll = sculpt_and_dynamic_topology_poll;
+}
+
/**** Toggle operator for turning sculpt mode on or off ****/
static void sculpt_init_session(Scene *scene, Object *ob)
@@ -4222,6 +4798,7 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op))
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = CTX_data_tool_settings(C);
Object *ob = CTX_data_active_object(C);
+ Mesh *me = ob->data;
MultiresModifierData *mmd = sculpt_multires_active(scene, ob);
int flush_recalc = 0;
@@ -4234,9 +4811,16 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op))
if (mmd)
multires_force_update(ob);
- if (flush_recalc)
+ if (flush_recalc || (ob->sculpt && ob->sculpt->bm))
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
+ /* Dynamic topology must be disabled before exiting sculpt
+ * mode to ensure the undo stack stays in a consistent
+ * state */
+ sculpt_dynamic_topology_toggle_exec(C, NULL);
+ }
+
/* Leave sculptmode */
ob->mode &= ~OB_MODE_SCULPT;
@@ -4246,6 +4830,12 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op))
/* Enter sculptmode */
ob->mode |= OB_MODE_SCULPT;
+ /* Remove dynamic-topology flag; this will be enabled if the
+ * file was saved with dynamic topology on, but we don't
+ * automatically re-enter dynamic-topology mode when loading a
+ * file. */
+ me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY;
+
if (flush_recalc)
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -4257,6 +4847,9 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op))
ts->sculpt->flags |= SCULPT_SYMM_X;
}
+ if (!ts->sculpt->detail_size)
+ ts->sculpt->detail_size = 30;
+
/* Create sculpt mode session data */
if (ob->sculpt)
free_sculptsession(ob);
@@ -4271,7 +4864,7 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op))
}
BKE_paint_init(&ts->sculpt->paint, PAINT_CURSOR_SCULPT);
-
+
paint_cursor_start(C, sculpt_poll);
}
@@ -4299,4 +4892,7 @@ void ED_operatortypes_sculpt(void)
WM_operatortype_append(SCULPT_OT_brush_stroke);
WM_operatortype_append(SCULPT_OT_sculptmode_toggle);
WM_operatortype_append(SCULPT_OT_set_persistent_base);
+ WM_operatortype_append(SCULPT_OT_dynamic_topology_toggle);
+ WM_operatortype_append(SCULPT_OT_optimize);
+ WM_operatortype_append(SCULPT_OT_symmetrize);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index acb906e4a91..82a07c9e3be 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -38,7 +38,7 @@
#include "DNA_key_types.h"
#include "BLI_bitmap.h"
-#include "BLI_pbvh.h"
+#include "BKE_pbvh.h"
struct bContext;
struct Brush;
@@ -49,6 +49,7 @@ struct Object;
struct Scene;
struct Sculpt;
struct SculptStroke;
+struct SculptUndoNode;
/* Interface */
struct MultiresModifierData *sculpt_multires_active(struct Scene *scene, struct Object *ob);
@@ -61,18 +62,25 @@ int sculpt_poll(struct bContext *C);
void sculpt_update_mesh_elements(struct Scene *scene, struct Sculpt *sd, struct Object *ob,
int need_pmap, int need_mask);
-/* Deformed mesh sculpt */
-void free_sculptsession_deformMats(struct SculptSession *ss);
-
/* Stroke */
int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2]);
+/* Dynamic topology */
+void sculpt_pbvh_clear(Object *ob);
+void sculpt_update_after_dynamic_topology_toggle(bContext *C);
+void sculpt_dynamic_topology_enable(struct bContext *C);
+void sculpt_dynamic_topology_disable(struct bContext *C,
+ struct SculptUndoNode *unode);
+
/* Undo */
typedef enum {
SCULPT_UNDO_COORDS,
SCULPT_UNDO_HIDDEN,
- SCULPT_UNDO_MASK
+ SCULPT_UNDO_MASK,
+ SCULPT_UNDO_DYNTOPO_BEGIN,
+ SCULPT_UNDO_DYNTOPO_END,
+ SCULPT_UNDO_DYNTOPO_SYMMETRIZE,
} SculptUndoType;
typedef struct SculptUndoNode {
@@ -101,8 +109,17 @@ typedef struct SculptUndoNode {
int *grids; /* to restore into right location */
BLI_bitmap *grid_hidden;
- /* layer brush */
- float *layer_disp;
+ /* bmesh */
+ struct BMLogEntry *bm_entry;
+ int applied;
+ CustomData bm_enter_vdata;
+ CustomData bm_enter_edata;
+ CustomData bm_enter_ldata;
+ CustomData bm_enter_pdata;
+ int bm_enter_totvert;
+ int bm_enter_totedge;
+ int bm_enter_totloop;
+ int bm_enter_totpoly;
/* shape keys */
char shapeName[sizeof(((KeyBlock *)0))->name];
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 1b3fd24ae22..2cc09ea2aa9 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -65,6 +65,7 @@
#include "GPU_buffers.h"
#include "ED_sculpt.h"
+#include "bmesh.h"
#include "paint_intern.h"
#include "sculpt_intern.h"
@@ -72,10 +73,10 @@
static void update_cb(PBVHNode *node, void *rebuild)
{
- BLI_pbvh_node_mark_update(node);
+ BKE_pbvh_node_mark_update(node);
if (*((int *)rebuild))
- BLI_pbvh_node_mark_rebuild_draw(node);
- BLI_pbvh_node_fully_hidden_set(node, 0);
+ BKE_pbvh_node_mark_rebuild_draw(node);
+ BKE_pbvh_node_fully_hidden_set(node, 0);
}
static void sculpt_undo_restore_deformed(const SculptSession *ss,
@@ -130,7 +131,9 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo
vertCos = BKE_key_convert_to_vertcos(ob, ss->kb);
for (i = 0; i < unode->totvert; i++) {
- if (ss->modifiers_active) sculpt_undo_restore_deformed(ss, unode, i, index[i], vertCos[index[i]]);
+ if (ss->modifiers_active) {
+ sculpt_undo_restore_deformed(ss, unode, i, index[i], vertCos[index[i]]);
+ }
else {
if (unode->orig_co) swap_v3_v3(vertCos[index[i]], unode->orig_co[i]);
else swap_v3_v3(vertCos[index[i]], unode->co[i]);
@@ -142,13 +145,15 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo
/* pbvh uses it's own mvert array, so coords should be */
/* propagated to pbvh here */
- BLI_pbvh_apply_vertCos(ss->pbvh, vertCos);
+ BKE_pbvh_apply_vertCos(ss->pbvh, vertCos);
MEM_freeN(vertCos);
}
else {
for (i = 0; i < unode->totvert; i++) {
- if (ss->modifiers_active) sculpt_undo_restore_deformed(ss, unode, i, index[i], mvert[index[i]].co);
+ if (ss->modifiers_active) {
+ sculpt_undo_restore_deformed(ss, unode, i, index[i], mvert[index[i]].co);
+ }
else {
if (unode->orig_co) swap_v3_v3(mvert[index[i]].co, unode->orig_co[i]);
else swap_v3_v3(mvert[index[i]].co, unode->co[i]);
@@ -261,6 +266,111 @@ static int sculpt_undo_restore_mask(bContext *C, DerivedMesh *dm, SculptUndoNode
return 1;
}
+static void sculpt_undo_bmesh_restore_generic(SculptUndoNode *unode,
+ Object *ob,
+ SculptSession *ss)
+{
+ if (unode->applied) {
+ BM_log_undo(ss->bm, ss->bm_log);
+ unode->applied = FALSE;
+ }
+ else {
+ BM_log_redo(ss->bm, ss->bm_log);
+ unode->applied = TRUE;
+ }
+
+ /* A bit lame, but for now just recreate the PBVH. The alternative
+ * is to store changes to the PBVH in the undo stack. */
+ sculpt_pbvh_clear(ob);
+}
+
+/* Create empty sculpt BMesh and enable logging */
+static void sculpt_undo_bmesh_enable(Object *ob,
+ SculptUndoNode *unode)
+{
+ SculptSession *ss = ob->sculpt;
+ Mesh *me = ob->data;
+
+ sculpt_pbvh_clear(ob);
+
+ /* Create empty BMesh and enable logging */
+ ss->bm = BM_mesh_create(&bm_mesh_allocsize_default);
+ BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK);
+ me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
+
+ /* Restore the BMLog using saved entries */
+ ss->bm_log = BM_log_from_existing_entries_create(ss->bm,
+ unode->bm_entry);
+}
+
+static void sculpt_undo_bmesh_restore_begin(bContext *C,
+ SculptUndoNode *unode,
+ Object *ob,
+ SculptSession *ss)
+{
+ if (unode->applied) {
+ sculpt_dynamic_topology_disable(C, unode);
+ unode->applied = FALSE;
+ }
+ else {
+ sculpt_undo_bmesh_enable(ob, unode);
+
+ /* Restore the mesh from the first log entry */
+ BM_log_redo(ss->bm, ss->bm_log);
+
+ unode->applied = TRUE;
+ }
+}
+
+static void sculpt_undo_bmesh_restore_end(bContext *C,
+ SculptUndoNode *unode,
+ Object *ob,
+ SculptSession *ss)
+{
+ if (unode->applied) {
+ sculpt_undo_bmesh_enable(ob, unode);
+
+ /* Restore the mesh from the last log entry */
+ BM_log_undo(ss->bm, ss->bm_log);
+
+ unode->applied = FALSE;
+ }
+ else {
+ /* Disable dynamic topology sculpting */
+ sculpt_dynamic_topology_disable(C, NULL);
+ unode->applied = TRUE;
+ }
+}
+
+/* Handle all dynamic-topology updates
+ *
+ * Returns TRUE if this was a dynamic-topology undo step, otherwise
+ * returns FALSE to indicate the non-dyntopo code should run. */
+static int sculpt_undo_bmesh_restore(bContext *C,
+ SculptUndoNode *unode,
+ Object *ob,
+ SculptSession *ss)
+{
+ switch (unode->type) {
+ case SCULPT_UNDO_DYNTOPO_BEGIN:
+ sculpt_undo_bmesh_restore_begin(C, unode, ob, ss);
+ return TRUE;
+
+ case SCULPT_UNDO_DYNTOPO_END:
+ sculpt_undo_bmesh_restore_end(C, unode, ob, ss);
+ return TRUE;
+
+ default:
+ if (ss->bm_log) {
+ sculpt_undo_bmesh_restore_generic(unode, ob, ss);
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
static void sculpt_undo_restore(bContext *C, ListBase *lb)
{
Scene *scene = CTX_data_scene(C);
@@ -269,7 +379,6 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
DerivedMesh *dm;
SculptSession *ss = ob->sculpt;
SculptUndoNode *unode;
- MultiresModifierData *mmd;
int update = FALSE, rebuild = FALSE;
int need_mask = FALSE;
@@ -289,6 +398,9 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
/* call _after_ sculpt_update_mesh_elements() which may update 'ob->derivedFinal' */
dm = mesh_get_derived_final(scene, ob, 0);
+ if (lb->first && sculpt_undo_bmesh_restore(C, lb->first, ob, ss))
+ return;
+
for (unode = lb->first; unode; unode = unode->next) {
if (!(strcmp(unode->idname, ob->id.name) == 0))
continue;
@@ -306,9 +418,6 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
continue;
}
}
- else {
- continue;
- }
switch (unode->type) {
case SCULPT_UNDO_COORDS:
@@ -323,6 +432,12 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
if (sculpt_undo_restore_mask(C, dm, unode))
update = TRUE;
break;
+
+ case SCULPT_UNDO_DYNTOPO_BEGIN:
+ case SCULPT_UNDO_DYNTOPO_END:
+ case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
+ BLI_assert(!"Dynamic topology should've already been handled");
+ break;
}
}
@@ -331,10 +446,10 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
/* we update all nodes still, should be more clever, but also
* needs to work correct when exiting/entering sculpt mode and
* the nodes get recreated, though in that case it could do all */
- BLI_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, &rebuild);
- BLI_pbvh_update(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw, NULL);
+ BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, &rebuild);
+ BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw, NULL);
- if ((mmd = sculpt_multires_active(scene, ob))) {
+ if (sculpt_multires_active(scene, ob)) {
if (rebuild)
multires_mark_as_modified(ob, MULTIRES_HIDDEN_MODIFIED);
else
@@ -374,8 +489,6 @@ static void sculpt_undo_free(ListBase *lb)
MEM_freeN(unode->index);
if (unode->grids)
MEM_freeN(unode->grids);
- if (unode->layer_disp)
- MEM_freeN(unode->layer_disp);
if (unode->orig_co)
MEM_freeN(unode->orig_co);
if (unode->vert_hidden)
@@ -389,6 +502,17 @@ static void sculpt_undo_free(ListBase *lb)
}
if (unode->mask)
MEM_freeN(unode->mask);
+ if (unode->bm_entry) {
+ BM_log_entry_drop(unode->bm_entry);
+ }
+ if (unode->bm_enter_totvert)
+ CustomData_free(&unode->bm_enter_vdata, unode->bm_enter_totvert);
+ if (unode->bm_enter_totedge)
+ CustomData_free(&unode->bm_enter_edata, unode->bm_enter_totedge);
+ if (unode->bm_enter_totloop)
+ CustomData_free(&unode->bm_enter_ldata, unode->bm_enter_totloop);
+ if (unode->bm_enter_totpoly)
+ CustomData_free(&unode->bm_enter_pdata, unode->bm_enter_totpoly);
}
}
@@ -410,9 +534,9 @@ static void sculpt_undo_alloc_and_store_hidden(PBVH *pbvh,
BLI_bitmap *grid_hidden;
int i, *grid_indices, totgrid;
- grid_hidden = BLI_pbvh_grid_hidden(pbvh);
+ grid_hidden = BKE_pbvh_grid_hidden(pbvh);
- BLI_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid,
+ BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid,
NULL, NULL, NULL, NULL);
unode->grid_hidden = MEM_mapallocN(sizeof(BLI_bitmap) * totgrid,
@@ -439,11 +563,15 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node,
unode->type = type;
unode->node = node;
- BLI_pbvh_node_num_verts(ss->pbvh, node, &totvert, &allvert);
- BLI_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
- &maxgrid, &gridsize, NULL, NULL);
+ 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);
- unode->totvert = totvert;
+ unode->totvert = totvert;
+ }
+ else
+ maxgrid = 0;
/* we will use this while sculpting, is mapalloc slow to access then? */
@@ -468,6 +596,11 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node,
unode->mask = MEM_mapallocN(sizeof(float) * allvert, "SculptUndoNode.mask");
undo_paint_push_count_alloc(UNDO_PAINT_MESH, (sizeof(float) * sizeof(int)) * allvert);
break;
+ case SCULPT_UNDO_DYNTOPO_BEGIN:
+ case SCULPT_UNDO_DYNTOPO_END:
+ case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
+ BLI_assert(!"Dynamic topology should've already been handled");
+ break;
}
BLI_addtail(lb, unode);
@@ -496,7 +629,7 @@ static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
SculptSession *ss = ob->sculpt;
PBVHVertexIter vd;
- BLI_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
{
copy_v3_v3(unode->co[vd.i], vd.co);
if (vd.no) copy_v3_v3_short(unode->no[vd.i], vd.no);
@@ -505,7 +638,7 @@ static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
if (ss->modifiers_active)
copy_v3_v3(unode->orig_co[vd.i], ss->orig_cos[unode->index[vd.i]]);
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
}
static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode)
@@ -521,8 +654,8 @@ static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode)
int *vert_indices, allvert;
int i;
- BLI_pbvh_node_num_verts(pbvh, node, NULL, &allvert);
- BLI_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
+ BKE_pbvh_node_num_verts(pbvh, node, NULL, &allvert);
+ BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
for (i = 0; i < allvert; i++) {
BLI_BITMAP_MODIFY(unode->vert_hidden, i,
mvert[vert_indices[i]].flag & ME_HIDE);
@@ -535,11 +668,85 @@ static void sculpt_undo_store_mask(Object *ob, SculptUndoNode *unode)
SculptSession *ss = ob->sculpt;
PBVHVertexIter vd;
- BLI_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
{
unode->mask[vd.i] = *vd.mask;
}
- BLI_pbvh_vertex_iter_end;
+ BKE_pbvh_vertex_iter_end;
+}
+
+static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
+ PBVHNode *node,
+ SculptUndoType type)
+{
+ ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_MESH);
+ SculptUndoNode *unode = lb->first;
+ SculptSession *ss = ob->sculpt;
+ PBVHVertexIter vd;
+
+ if (!lb->first) {
+ unode = MEM_callocN(sizeof(*unode), AT);
+
+ BLI_strncpy(unode->idname, ob->id.name, sizeof(unode->idname));
+ unode->type = type;
+ unode->applied = TRUE;
+
+ if (type == SCULPT_UNDO_DYNTOPO_END) {
+ unode->bm_entry = BM_log_entry_add(ss->bm_log);
+ BM_log_before_all_removed(ss->bm, ss->bm_log);
+ }
+ else if (type == SCULPT_UNDO_DYNTOPO_BEGIN) {
+ Mesh *me = ob->data;
+
+ /* Store a copy of the mesh's current vertices, loops, and
+ * polys. A full copy like this is needed because entering
+ * dynamic-topology immediately does topological edits
+ * (converting polys to triangles) that the BMLog can't
+ * fully restore from */
+ CustomData_copy(&me->vdata, &unode->bm_enter_vdata, CD_MASK_MESH,
+ CD_DUPLICATE, me->totvert);
+ CustomData_copy(&me->edata, &unode->bm_enter_edata, CD_MASK_MESH,
+ CD_DUPLICATE, me->totedge);
+ CustomData_copy(&me->ldata, &unode->bm_enter_ldata, CD_MASK_MESH,
+ CD_DUPLICATE, me->totloop);
+ CustomData_copy(&me->pdata, &unode->bm_enter_pdata, CD_MASK_MESH,
+ CD_DUPLICATE, me->totpoly);
+ unode->bm_enter_totvert = me->totvert;
+ unode->bm_enter_totedge = me->totedge;
+ unode->bm_enter_totloop = me->totloop;
+ unode->bm_enter_totpoly = me->totpoly;
+
+ unode->bm_entry = BM_log_entry_add(ss->bm_log);
+ BM_log_all_added(ss->bm, ss->bm_log);
+ }
+ else {
+ unode->bm_entry = BM_log_entry_add(ss->bm_log);
+ }
+
+ BLI_addtail(lb, unode);
+ }
+
+ if (node) {
+ switch (type) {
+ case SCULPT_UNDO_COORDS:
+ case SCULPT_UNDO_HIDDEN:
+ case SCULPT_UNDO_MASK:
+ /* Before any vertex values get modified, ensure their
+ * original positions are logged */
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL) {
+ BM_log_vert_before_modified(ss->bm, ss->bm_log, vd.bm_vert);
+ }
+ BKE_pbvh_vertex_iter_end;
+ break;
+
+ case SCULPT_UNDO_DYNTOPO_BEGIN:
+ case SCULPT_UNDO_DYNTOPO_END:
+ case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
+ break;
+ }
+ }
+
+ return unode;
}
SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
@@ -551,7 +758,18 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
/* list is manipulated by multiple threads, so we lock */
BLI_lock_thread(LOCK_CUSTOM1);
- if ((unode = sculpt_undo_get_node(node))) {
+ if (ss->bm ||
+ ELEM(type,
+ SCULPT_UNDO_DYNTOPO_BEGIN,
+ SCULPT_UNDO_DYNTOPO_END))
+ {
+ /* Dynamic topology stores only one undo node per stroke,
+ * regardless of the number of PBVH nodes modified */
+ unode = sculpt_undo_bmesh_push(ob, node, type);
+ BLI_unlock_thread(LOCK_CUSTOM1);
+ return unode;
+ }
+ else if ((unode = sculpt_undo_get_node(node))) {
BLI_unlock_thread(LOCK_CUSTOM1);
return unode;
}
@@ -564,14 +782,14 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
if (unode->grids) {
int totgrid, *grids;
- BLI_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
+ BKE_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
NULL, NULL, NULL, NULL);
memcpy(unode->grids, grids, sizeof(int) * totgrid);
}
else {
int *vert_indices, allvert;
- BLI_pbvh_node_num_verts(ss->pbvh, node, NULL, &allvert);
- BLI_pbvh_node_get_verts(ss->pbvh, node, &vert_indices, NULL);
+ 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);
}
@@ -585,6 +803,11 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
case SCULPT_UNDO_MASK:
sculpt_undo_store_mask(ob, unode);
break;
+ case SCULPT_UNDO_DYNTOPO_BEGIN:
+ case SCULPT_UNDO_DYNTOPO_END:
+ case SCULPT_UNDO_DYNTOPO_SYMMETRIZE:
+ BLI_assert(!"Dynamic topology should've already been handled");
+ break;
}
/* store active shape key */
@@ -612,10 +835,8 @@ void sculpt_undo_push_end(void)
unode->no = NULL;
}
- if (unode->layer_disp) {
- MEM_freeN(unode->layer_disp);
- unode->layer_disp = NULL;
- }
+ if (unode->node)
+ BKE_pbvh_node_layer_disp_free(unode->node);
}
undo_paint_push_end(UNDO_PAINT_MESH);
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index 0bcccd9479c..7cdfb6d22b2 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -144,6 +144,69 @@ typedef struct UvSculptData {
char invert;
} UvSculptData;
+
+static Brush *uv_sculpt_brush(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *settings = scene->toolsettings;
+
+ if (!settings->uvsculpt)
+ return NULL;
+ return paint_brush(&settings->uvsculpt->paint);
+}
+
+
+static int uv_sculpt_brush_poll(bContext *C)
+{
+ BMEditMesh *em;
+ int ret;
+ Object *obedit = CTX_data_edit_object(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *toolsettings = scene->toolsettings;
+
+ if (!uv_sculpt_brush(C) || !obedit || obedit->type != OB_MESH)
+ return 0;
+
+ em = BMEdit_FromObject(obedit);
+ ret = EDBM_mtexpoly_check(em);
+
+ if (ret && sima) {
+ ARegion *ar = CTX_wm_region(C);
+ if ((toolsettings->use_uv_sculpt) && ar->regiontype == RGN_TYPE_WINDOW)
+ return 1;
+ }
+
+ return 0;
+}
+
+
+void ED_space_image_uv_sculpt_update(wmWindowManager *wm, ToolSettings *settings)
+{
+ if (settings->use_uv_sculpt) {
+ if (!settings->uvsculpt) {
+ settings->uvsculpt = MEM_callocN(sizeof(*settings->uvsculpt), "UV Smooth paint");
+ settings->uv_sculpt_tool = UV_SCULPT_TOOL_GRAB;
+ settings->uv_sculpt_settings = UV_SCULPT_LOCK_BORDERS | UV_SCULPT_ALL_ISLANDS;
+ settings->uv_relax_method = UV_SCULPT_TOOL_RELAX_LAPLACIAN;
+ }
+
+ BKE_paint_init(&settings->uvsculpt->paint, PAINT_CURSOR_SCULPT);
+
+ WM_paint_cursor_activate(wm, uv_sculpt_brush_poll,
+ brush_drawcursor_texpaint_uvsculpt, NULL);
+ }
+ else {
+ if (settings->uvsculpt)
+ settings->uvsculpt->paint.flags &= ~PAINT_SHOW_BRUSH;
+ }
+}
+
+int uv_sculpt_poll(bContext *C)
+{
+ return uv_sculpt_brush_poll(C);
+}
+
/*********** Improved Laplacian Relaxation Operator ************************/
/* original code by Raul Fernandez Hernandez "farsthary" *
* adapted to uv smoothing by Antony Riakiatakis *
@@ -294,7 +357,7 @@ static void laplacian_relaxation_iteration_uv(BMEditMesh *em, UvSculptData *scul
}
-static void uv_sculpt_stroke_apply(bContext *C, wmOperator *op, wmEvent *event, Object *obedit)
+static void uv_sculpt_stroke_apply(bContext *C, wmOperator *op, const wmEvent *event, Object *obedit)
{
float co[2], radius, radius_root;
Scene *scene = CTX_data_scene(C);
@@ -464,7 +527,7 @@ static int uv_edge_compare(const void *a, const void *b)
}
-static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, wmEvent *event)
+static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
@@ -649,7 +712,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, wmEvent
return NULL;
}
/* fill the edges with data */
- for (i = 0; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) {
+ for (i = 0; BLI_ghashIterator_notDone(ghi); BLI_ghashIterator_step(ghi)) {
data->uvedges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(ghi));
}
data->totalUvEdges = BLI_ghash_size(edgeHash);
@@ -731,7 +794,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, wmEvent
return op->customdata;
}
-static int uv_sculpt_stroke_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int uv_sculpt_stroke_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
UvSculptData *data;
Object *obedit = CTX_data_edit_object(C);
@@ -754,7 +817,7 @@ static int uv_sculpt_stroke_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
-static int uv_sculpt_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int uv_sculpt_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
UvSculptData *data = (UvSculptData *)op->customdata;
Object *obedit = CTX_data_edit_object(C);
diff --git a/source/blender/editors/sound/SConscript b/source/blender/editors/sound/SConscript
index e17bccdadd9..1eaf9c2e945 100644
--- a/source/blender/editors/sound/SConscript
+++ b/source/blender/editors/sound/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index aaa1328f9f6..0cb0a3d6e5c 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -160,7 +160,7 @@ static int sound_open_exec(bContext *UNUSED(C), wmOperator *op)
#endif
-static int sound_open_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int sound_open_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (RNA_struct_property_is_set(op->ptr, "filepath"))
return sound_open_exec(C, op);
@@ -221,7 +221,7 @@ static int sound_update_animation_flags_exec(bContext *C, wmOperator *UNUSED(op)
Sequence *seq;
Scene *scene = CTX_data_scene(C);
struct FCurve *fcu;
- char driven;
+ bool driven;
SEQ_BEGIN(scene->ed, seq)
{
@@ -264,7 +264,7 @@ static void SOUND_OT_update_animation_flags(wmOperatorType *ot)
*/
/* identifiers */
- ot->name = "Update animation";
+ ot->name = "Update Animation";
ot->description = "Update animation flags";
ot->idname = "SOUND_OT_update_animation_flags";
@@ -300,7 +300,7 @@ static int sound_bake_animation_exec(bContext *C, wmOperator *UNUSED(op))
static void SOUND_OT_bake_animation(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Update animation cache";
+ ot->name = "Update Animation Cache";
ot->description = "Update the audio animation cache";
ot->idname = "SOUND_OT_bake_animation";
@@ -439,7 +439,7 @@ static int sound_mixdown_check(bContext *UNUSED(C), wmOperator *op)
#endif // WITH_AUDASPACE
-static int sound_mixdown_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int sound_mixdown_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (RNA_struct_property_is_set(op->ptr, "filepath"))
return sound_mixdown_exec(C, op);
@@ -449,7 +449,7 @@ static int sound_mixdown_invoke(bContext *C, wmOperator *op, wmEvent *event)
#ifdef WITH_AUDASPACE
-static int sound_mixdown_draw_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
+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 ||
@@ -747,7 +747,7 @@ static int sound_unpack_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int sound_unpack_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int sound_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Editing *ed = CTX_data_scene(C)->ed;
bSound *sound;
diff --git a/source/blender/editors/space_action/SConscript b/source/blender/editors/space_action/SConscript
index 0fee8ff68ab..abaf6154a42 100644
--- a/source/blender/editors/space_action/SConscript
+++ b/source/blender/editors/space_action/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 9bd7d2a44ca..4b1954c8889 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -82,13 +82,7 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* Update max-extent of channels here (taking into account scrollers):
- * - this is done to allow the channel list to be scrollable, but must be done here
- * to avoid regenerating the list again and/or also because channels list is drawn first
- * - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
- * start of list offset, and the second is as a correction for the scrollers.
- */
- height = ((items * ACHANNEL_STEP) + (ACHANNEL_HEIGHT * 2));
+ height = ((items * ACHANNEL_STEP) + (ACHANNEL_HEIGHT));
if (height > BLI_rcti_size_y(&v2d->mask)) {
/* don't use totrect set, as the width stays the same
* (NOTE: this is ok here, the configuration is pretty straightforward)
@@ -199,13 +193,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- /* Update max-extent of channels here (taking into account scrollers):
- * - this is done to allow the channel list to be scrollable, but must be done here
- * to avoid regenerating the list again and/or also because channels list is drawn first
- * - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
- * start of list offset, and the second is as a correction for the scrollers.
- */
- height = ((items * ACHANNEL_STEP) + (ACHANNEL_HEIGHT * 2));
+ height = ((items * ACHANNEL_STEP) + (ACHANNEL_HEIGHT));
/* don't use totrect set, as the width stays the same
* (NOTE: this is ok here, the configuration is pretty straightforward)
*/
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index a80d425b90a..803e7b71c77 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -53,6 +53,7 @@
#include "BKE_action.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_nla.h"
#include "BKE_context.h"
#include "BKE_report.h"
@@ -104,8 +105,10 @@ static int act_new_exec(bContext *C, wmOperator *UNUSED(op))
action = BKE_action_copy(oldact);
}
else {
+ Main *bmain = CTX_data_main(C);
+
/* just make a new (empty) action */
- action = add_empty_action("Action");
+ action = add_empty_action(bmain, "Action");
}
/* when creating new ID blocks, use is already 1 (fake user),
@@ -739,7 +742,7 @@ static int actkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-static int actkeys_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int actkeys_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
actkeys_duplicate_exec(C, op);
diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h
index 10085d8a149..8f39a38157a 100644
--- a/source/blender/editors/space_action/action_intern.h
+++ b/source/blender/editors/space_action/action_intern.h
@@ -60,19 +60,19 @@ void ACTION_OT_select_leftright(struct wmOperatorType *ot);
void ACTION_OT_clickselect(struct wmOperatorType *ot);
/* defines for left-right select tool */
-enum {
+enum eActKeys_LeftRightSelect_Mode {
ACTKEYS_LRSEL_TEST = 0,
ACTKEYS_LRSEL_LEFT,
ACTKEYS_LRSEL_RIGHT
-} eActKeys_LeftRightSelect_Mode;
+};
/* defines for column-select mode */
-enum {
+enum eActKeys_ColumnSelect_Mode {
ACTKEYS_COLUMNSEL_KEYS = 0,
ACTKEYS_COLUMNSEL_CFRA,
ACTKEYS_COLUMNSEL_MARKERS_COLUMN,
ACTKEYS_COLUMNSEL_MARKERS_BETWEEN,
-} eActKeys_ColumnSelect_Mode;
+};
/* ***************************************** */
/* action_edit.c */
@@ -107,22 +107,22 @@ void ACTION_OT_markers_make_local(struct wmOperatorType *ot);
/* defines for snap keyframes
* NOTE: keep in sync with eEditKeyframes_Snap (in ED_keyframes_edit.h)
*/
-enum {
+enum eActKeys_Snap_Mode {
ACTKEYS_SNAP_CFRA = 1,
ACTKEYS_SNAP_NEAREST_FRAME,
ACTKEYS_SNAP_NEAREST_SECOND,
ACTKEYS_SNAP_NEAREST_MARKER,
-} eActKeys_Snap_Mode;
+};
/* defines for mirror keyframes
* NOTE: keep in sync with eEditKeyframes_Mirror (in ED_keyframes_edit.h)
*/
-enum {
+enum eActKeys_Mirror_Mode {
ACTKEYS_MIRROR_CFRA = 1,
ACTKEYS_MIRROR_YAXIS,
ACTKEYS_MIRROR_XAXIS,
ACTKEYS_MIRROR_MARKER,
-} eActKeys_Mirror_Mode;
+};
/* ***************************************** */
/* action_ops.c */
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index d0f76c21019..b6d2d31f0ad 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -259,12 +259,35 @@ static void borderselect_action(bAnimContext *ac, rcti rect, short mode, short s
!((ymax < rectf.ymin) || (ymin > rectf.ymax)))
{
/* loop over data selecting */
- if (ale->type == ANIMTYPE_GPLAYER)
- ED_gplayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode);
- else if (ale->type == ANIMTYPE_MASKLAYER)
- ED_masklayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode);
- else
- ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
+ switch (ale->type) {
+ case ANIMTYPE_GPDATABLOCK:
+ {
+ bGPdata *gpd = ale->data;
+ bGPDlayer *gpl;
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ ED_gplayer_frames_select_border(gpl, rectf.xmin, rectf.xmax, selectmode);
+ }
+ break;
+ }
+ case ANIMTYPE_GPLAYER:
+ ED_gplayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode);
+ break;
+ case ANIMTYPE_MASKDATABLOCK:
+ {
+ Mask *mask = ale->data;
+ MaskLayer *masklay;
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ ED_masklayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode);
+ }
+ break;
+ }
+ case ANIMTYPE_MASKLAYER:
+ ED_masklayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode);
+ break;
+ default:
+ ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
+ break;
+ }
}
/* set minimum extent to be the maximum of the next channel */
@@ -849,7 +872,7 @@ static int actkeys_select_leftright_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int actkeys_select_leftright_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int actkeys_select_leftright_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
bAnimContext ac;
short leftright = RNA_enum_get(op->ptr, "mode");
@@ -944,6 +967,7 @@ static void actkeys_mselect_single(bAnimContext *ac, bAnimListElem *ale, short s
else if (ale->type == ANIMTYPE_MASKLAYER)
ED_mask_select_frame(ale->data, selx, select_mode);
}
+ BLI_freelistN(&anim_data);
}
else {
ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
@@ -1199,7 +1223,7 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
}
/* handle clicking */
-static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
bAnimContext ac;
/* ARegion *ar; */ /* UNUSED */
@@ -1240,16 +1264,17 @@ void ACTION_OT_clickselect(wmOperatorType *ot)
ot->idname = "ACTION_OT_clickselect";
ot->description = "Select keyframes by clicking on them";
- /* api callbacks - absolutely no exec() this yet... */
+ /* callbacks */
ot->invoke = actkeys_clickselect_invoke;
ot->poll = ED_operator_action_active;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_UNDO;
/* properties */
prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
prop = RNA_def_boolean(ot->srna, "column", 0, "Column Select", ""); // ALTKEY
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index c5f3ccee101..e0ca589c1fb 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -219,6 +219,9 @@ static void action_channel_area_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
+ /* ensure the 2d view sync works - main region has bottom scroller */
+ ar->v2d.scroll = V2D_SCROLL_BOTTOM;
+
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
/* own keymap */
@@ -231,7 +234,6 @@ static void action_channel_area_draw(const bContext *C, ARegion *ar)
/* draw entirely, view changes should be handled here */
bAnimContext ac;
View2D *v2d = &ar->v2d;
- View2DScrollers *scrollers;
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
@@ -247,10 +249,7 @@ static void action_channel_area_draw(const bContext *C, ARegion *ar)
/* reset view matrix */
UI_view2d_view_restore(C);
- /* scrollers */
- scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
+ /* no scrollers here */
}
diff --git a/source/blender/editors/space_api/SConscript b/source/blender/editors/space_api/SConscript
index 9b818b074ba..a07be054011 100644
--- a/source/blender/editors/space_api/SConscript
+++ b/source/blender/editors/space_api/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/space_buttons/CMakeLists.txt b/source/blender/editors/space_buttons/CMakeLists.txt
index 7233d4623d1..10080c62594 100644
--- a/source/blender/editors/space_buttons/CMakeLists.txt
+++ b/source/blender/editors/space_buttons/CMakeLists.txt
@@ -48,4 +48,8 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_FREESTYLE)
+ add_definitions(-DWITH_FREESTYLE)
+endif()
+
blender_add_lib(bf_editor_space_buttons "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_buttons/SConscript b/source/blender/editors/space_buttons/SConscript
index 92579b6dedf..1f7939598c8 100644
--- a/source/blender/editors/space_buttons/SConscript
+++ b/source/blender/editors/space_buttons/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
@@ -12,4 +38,7 @@ defs = []
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
+if env['WITH_BF_FREESTYLE']:
+ defs.append('WITH_FREESTYLE')
+
env.BlenderLib ( 'bf_editors_space_buttons', sources, Split(incs), defs, libtype=['core'], priority=[120] )
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 2a5b64cd6ed..95d43fd334e 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -36,6 +36,8 @@
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "DNA_armature_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
@@ -538,6 +540,7 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma
switch (mainb) {
case BCONTEXT_SCENE:
case BCONTEXT_RENDER:
+ case BCONTEXT_RENDER_LAYER:
found = buttons_context_path_scene(path);
break;
case BCONTEXT_WORLD:
@@ -1028,7 +1031,8 @@ void buttons_context_draw(const bContext *C, uiLayout *layout)
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, 0, 0, 0, 0, "Follow context or keep fixed datablock displayed");
+ but = uiDefIconButBitC(block, ICONTOG, SB_PIN_CONTEXT, 0, ICON_UNPINNED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &sbuts->flag,
+ 0, 0, 0, 0, IFACE_("Follow context or keep fixed datablock displayed"));
uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
uiButSetFunc(but, pin_cb, NULL, NULL);
@@ -1043,7 +1047,7 @@ void buttons_context_draw(const bContext *C, uiLayout *layout)
name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL);
if (name) {
- if (!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE) && ptr->type == &RNA_Scene)
+ if (!ELEM3(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE, BCONTEXT_RENDER_LAYER) && ptr->type == &RNA_Scene)
uiItemLDrag(row, ptr, "", icon); /* save some space */
else
uiItemLDrag(row, ptr, name, icon);
@@ -1068,7 +1072,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, "Context");
+ strcpy(pt->label, N_("Context")); /* XXX C panels are not available through RNA (bpy.types)! */
pt->draw = buttons_panel_context;
pt->flag = PNL_NO_HEADER;
BLI_addtail(&art->paneltypes, pt);
diff --git a/source/blender/editors/space_buttons/buttons_header.c b/source/blender/editors/space_buttons/buttons_header.c
index ebba7d92819..19bfe05e8a4 100644
--- a/source/blender/editors/space_buttons/buttons_header.c
+++ b/source/blender/editors/space_buttons/buttons_header.c
@@ -97,14 +97,15 @@ static void do_buttons_buttons(bContext *C, void *UNUSED(arg), int event)
sbuts->mainbuser = sbuts->mainb;
}
-#define BUT_UNIT_X (UI_UNIT_X + 2)
+#define BUT_UNIT_X (UI_UNIT_X + 2 * U.pixelsize)
void buttons_header_buttons(const bContext *C, ARegion *ar)
{
SpaceButs *sbuts = CTX_wm_space_buts(C);
uiBlock *block;
uiBut *but;
- int xco, yco = 2;
+ int headery = ED_area_headersize();
+ int xco, yco = 0.5f * (headery - UI_UNIT_Y);
buttons_context_compute(C, sbuts);
@@ -128,6 +129,7 @@ void buttons_header_buttons(const bContext *C, ARegion *ar)
} (void)0
BUTTON_HEADER_CTX(BCONTEXT_RENDER, ICON_SCENE, N_("Render"));
+ BUTTON_HEADER_CTX(BCONTEXT_RENDER_LAYER, ICON_RENDERLAYERS, N_("Render Layers"));
BUTTON_HEADER_CTX(BCONTEXT_SCENE, ICON_SCENE_DATA, N_("Scene"));
BUTTON_HEADER_CTX(BCONTEXT_WORLD, ICON_WORLD, N_("World"));
BUTTON_HEADER_CTX(BCONTEXT_OBJECT, ICON_OBJECT_DATA, N_("Object"));
diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c
index d40426a5bc9..dcc61cfa544 100644
--- a/source/blender/editors/space_buttons/buttons_ops.c
+++ b/source/blender/editors/space_buttons/buttons_ops.c
@@ -35,10 +35,12 @@
#include "DNA_userdef_types.h"
+#include "BLI_utildefines.h"
#include "BLI_fileops.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
-#include "BLI_utildefines.h"
+
+#include "BLF_translation.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -60,7 +62,7 @@
/********************** toolbox operator *********************/
-static int toolbox_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
+static int toolbox_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
bScreen *sc = CTX_wm_screen(C);
SpaceButs *sbuts = CTX_wm_space_buts(C);
@@ -70,7 +72,7 @@ static int toolbox_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(e
RNA_pointer_create(&sc->id, &RNA_SpaceProperties, sbuts, &ptr);
- pup = uiPupMenuBegin(C, "Align", ICON_NONE);
+ pup = uiPupMenuBegin(C, IFACE_("Align"), ICON_NONE);
layout = uiPupMenuLayout(pup);
uiItemsEnumR(layout, &ptr, "align");
uiPupMenuEnd(C, pup);
@@ -111,19 +113,28 @@ static int file_browse_exec(bContext *C, wmOperator *op)
/* add slash for directories, important for some properties */
if (RNA_property_subtype(fbo->prop) == PROP_DIRPATH) {
- char name[FILE_MAX];
-
+ int is_relative = RNA_boolean_get(op->ptr, "relative_path");
id = fbo->ptr.id.data;
BLI_strncpy(path, str, FILE_MAX);
BLI_path_abs(path, id ? ID_BLEND_PATH(G.main, id) : G.main->name);
if (BLI_is_dir(path)) {
- str = MEM_reallocN(str, strlen(str) + 2);
+ if (is_relative) {
+ BLI_strncpy(path, str, FILE_MAX);
+ BLI_path_rel(path, G.main->name);
+ str = MEM_reallocN(str, strlen(path) + 2);
+ BLI_strncpy(str, path, FILE_MAX);
+ }
+ else {
+ str = MEM_reallocN(str, strlen(str) + 2);
+ }
BLI_add_slash(str);
}
- else
- BLI_splitdirstring(str, name);
+ else {
+ char * const lslash = (char *)BLI_last_slash(str);
+ if (lslash) lslash[1] = '\0';
+ }
}
RNA_property_string_set(&fbo->ptr, fbo->prop, str);
@@ -154,7 +165,7 @@ static int file_browse_cancel(bContext *UNUSED(C), wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int file_browse_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
PointerRNA ptr;
PropertyRNA *prop;
@@ -179,7 +190,7 @@ static int file_browse_invoke(bContext *C, wmOperator *op, wmEvent *event)
PointerRNA props_ptr;
if (event->alt) {
- char *lslash = BLI_last_slash(str);
+ char *lslash = (char *)BLI_last_slash(str);
if (lslash)
*lslash = '\0';
}
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index abfefba02b9..b108f9fa4b5 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -37,6 +37,8 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "DNA_brush_types.h"
#include "DNA_ID.h"
#include "DNA_lamp_types.h"
@@ -116,10 +118,10 @@ static void buttons_texture_users_find_nodetree(ListBase *users, ID *id,
if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
PointerRNA ptr;
/* PropertyRNA *prop; */ /* UNUSED */
-
+
RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
/* prop = RNA_struct_find_property(&ptr, "texture"); */ /* UNUSED */
-
+
buttons_texture_user_node_add(users, id, ntree, node,
category, RNA_struct_ui_icon(ptr.type), node->name);
}
@@ -358,7 +360,17 @@ static void template_texture_user_menu(bContext *C, uiLayout *layout, void *UNUS
}
/* create button */
- BLI_snprintf(name, UI_MAX_NAME_STR, " %s", user->name);
+ if (user->prop) {
+ PointerRNA texptr = RNA_property_pointer_get(&user->ptr, user->prop);
+ Tex *tex = texptr.data;
+
+ if (tex)
+ BLI_snprintf(name, UI_MAX_NAME_STR, " %s - %s", user->name, tex->id.name + 2);
+ else
+ BLI_snprintf(name, UI_MAX_NAME_STR, " %s", user->name);
+ }
+ 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,
NULL, 0.0, 0.0, 0.0, 0.0, "");
@@ -387,12 +399,12 @@ void uiTemplateTextureUser(uiLayout *layout, bContext *C)
user = ct->user;
if (!user) {
- uiItemL(layout, "No textures in context.", ICON_NONE);
+ uiItemL(layout, IFACE_("No textures in context"), ICON_NONE);
return;
}
/* create button */
- BLI_snprintf(name, UI_MAX_NAME_STR, "%s", user->name);
+ BLI_strncpy(name, user->name, UI_MAX_NAME_STR);
if (user->icon) {
but = uiDefIconTextMenuBut(block, template_texture_user_menu, NULL,
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index c98d213e949..6367ca893d1 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -155,6 +155,8 @@ static void buttons_main_area_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, vertical, "scene", sbuts->mainb);
else if (sbuts->mainb == BCONTEXT_RENDER)
ED_region_panels(C, ar, vertical, "render", sbuts->mainb);
+ else if (sbuts->mainb == BCONTEXT_RENDER_LAYER)
+ ED_region_panels(C, ar, vertical, "render_layer", sbuts->mainb);
else if (sbuts->mainb == BCONTEXT_WORLD)
ED_region_panels(C, ar, vertical, "world", sbuts->mainb);
else if (sbuts->mainb == BCONTEXT_OBJECT)
@@ -239,6 +241,7 @@ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn)
switch (wmn->data) {
case ND_RENDER_OPTIONS:
buttons_area_redraw(sa, BCONTEXT_RENDER);
+ buttons_area_redraw(sa, BCONTEXT_RENDER_LAYER);
break;
case ND_FRAME:
/* any buttons area can have animated properties so redraw all */
@@ -375,6 +378,12 @@ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn)
ED_area_tag_redraw(sa);
sbuts->preview = 1;
break;
+#ifdef WITH_FREESTYLE
+ case NC_LINESTYLE:
+ ED_area_tag_redraw(sa);
+ sbuts->preview = 1;
+ break;
+#endif
}
if (wmn->data == ND_KEYS)
diff --git a/source/blender/editors/space_clip/CMakeLists.txt b/source/blender/editors/space_clip/CMakeLists.txt
index 75e3d8d5685..e09a8b41262 100644
--- a/source/blender/editors/space_clip/CMakeLists.txt
+++ b/source/blender/editors/space_clip/CMakeLists.txt
@@ -57,4 +57,8 @@ set(SRC
clip_intern.h
)
+if(WITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
+endif()
+
blender_add_lib(bf_editor_space_clip "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_clip/SConscript b/source/blender/editors/space_clip/SConscript
index c9c82aea68e..840a3b49f2b 100644
--- a/source/blender/editors/space_clip/SConscript
+++ b/source/blender/editors/space_clip/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
@@ -6,4 +32,10 @@ defs = []
incs = '../include ../../blenkernel ../../blenloader ../../blenfont ../../blenlib ../../imbuf ../../makesdna'
incs += ' ../../makesrna ../../windowmanager #/intern/guardedalloc #/extern/glew/include ../../gpu'
+if env['WITH_BF_INTERNATIONAL']:
+ defs.append('WITH_INTERNATIONAL')
+
+if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
+ incs += ' ' + env['BF_PTHREADS_INC']
+
env.BlenderLib ( 'bf_editors_space_clip', sources, Split(incs), defs, libtype=['core'], priority=[95] )
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index 969b0e25928..9409ce42d3a 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -43,6 +43,8 @@
#include "BLI_listbase.h"
#include "BLI_rect.h"
+#include "BLF_translation.h"
+
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_screen.h"
@@ -78,6 +80,7 @@ void ED_clip_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype clip panel gpencil");
strcpy(pt->idname, "CLIP_PT_gpencil");
strcpy(pt->label, "Grease Pencil");
+ pt->draw_header = gpencil_panel_standard_header;
pt->draw = gpencil_panel_standard;
pt->flag |= PNL_DEFAULT_CLOSED;
pt->poll = clip_grease_pencil_panel_poll;
@@ -123,7 +126,7 @@ void uiTemplateMovieClip(uiLayout *layout, bContext *C, PointerRNA *ptr, const c
row = uiLayoutRow(layout, FALSE);
block = uiLayoutGetBlock(row);
- uiDefBut(block, LABEL, 0, "File Path:", 0, 19, 145, 19, NULL, 0, 0, 0, 0, "");
+ uiDefBut(block, LABEL, 0, IFACE_("File Path:"), 0, 19, 145, 19, NULL, 0, 0, 0, 0, "");
row = uiLayoutRow(layout, FALSE);
split = uiLayoutSplit(row, 0.0f, FALSE);
@@ -166,16 +169,16 @@ void uiTemplateTrack(uiLayout *layout, PointerRNA *ptr, const char *propname)
scopesptr = RNA_property_pointer_get(ptr, prop);
scopes = (MovieClipScopes *)scopesptr.data;
- rect.xmin = 0; rect.xmax = 200;
- rect.ymin = 0; rect.ymax = 120;
+ rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X;
+ rect.ymin = 0; rect.ymax = 6.0f * UI_UNIT_Y;
block = uiLayoutAbsoluteBlock(layout);
scopes->track_preview_height =
- (scopes->track_preview_height <= UI_UNIT_Y) ? UI_UNIT_Y : scopes->track_preview_height;
+ (scopes->track_preview_height <= 20) ? 20 : scopes->track_preview_height;
uiDefBut(block, TRACKPREVIEW, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect),
- scopes->track_preview_height, scopes, 0, 0, 0, 0, "");
+ scopes->track_preview_height * UI_DPI_FAC, scopes, 0, 0, 0, 0, "");
}
/********************* Marker Template ************************/
@@ -386,11 +389,11 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P
block = uiLayoutGetBlock(layout);
if (cb->marker_flag & MARKER_DISABLED)
- tip = "Marker is disabled at current frame";
+ tip = TIP_("Marker is disabled at current frame");
else
- tip = "Marker is enabled at current frame";
+ tip = TIP_("Marker is enabled at current frame");
- bt = uiDefIconButBitI(block, TOGN, MARKER_DISABLED, 0, ICON_RESTRICT_VIEW_OFF, 0, 0, 20, 20,
+ bt = uiDefIconButBitI(block, TOGN, 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);
}
@@ -404,7 +407,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, "Track is locked", 0, 0, 300, 19, NULL, 0, 0, 0, 0, "");
+ uiDefBut(block, LABEL, 0, IFACE_("Track is locked"), 0, 0, UI_UNIT_X * 15.0f, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
return;
}
@@ -433,12 +436,12 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P
uiBlockSetNFunc(block, marker_update_cb, cb, NULL);
if (cb->marker_flag & MARKER_DISABLED)
- tip = "Marker is disabled at current frame";
+ tip = TIP_("Marker is disabled at current frame");
else
- tip = "Marker is enabled at current frame";
+ tip = TIP_("Marker is enabled at current frame");
- uiDefButBitI(block, OPTIONN, MARKER_DISABLED, B_MARKER_FLAG, "Enabled", 10, 190, 145, 19, &cb->marker_flag,
- 0, 0, 0, 0, tip);
+ uiDefButBitI(block, OPTIONN, MARKER_DISABLED, B_MARKER_FLAG, IFACE_("Enabled"), 10, 190, 145, 19,
+ &cb->marker_flag, 0, 0, 0, 0, tip);
col = uiLayoutColumn(layout, TRUE);
uiLayoutSetActive(col, (cb->marker_flag & MARKER_DISABLED) == 0);
@@ -446,33 +449,34 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P
block = uiLayoutAbsoluteBlock(col);
uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, 0, "Position:", 0, 190, 300, 19, NULL, 0, 0, 0, 0, "");
- uiDefButF(block, NUM, B_MARKER_POS, "X:", 10, 171, 145, 19, &cb->marker_pos[0],
- -10 * width, 10.0 * width, step, digits, "X-position of marker at frame in screen coordinates");
- uiDefButF(block, NUM, B_MARKER_POS, "Y:", 165, 171, 145, 19, &cb->marker_pos[1],
- -10 * height, 10.0 * height, step, digits, "Y-position of marker at frame in screen coordinates");
-
- uiDefBut(block, LABEL, 0, "Offset:", 0, 152, 300, 19, NULL, 0, 0, 0, 0, "");
- uiDefButF(block, NUM, B_MARKER_OFFSET, "X:", 10, 133, 145, 19, &cb->track_offset[0],
- -10 * width, 10.0 * width, step, digits, "X-offset to parenting point");
- uiDefButF(block, NUM, B_MARKER_OFFSET, "Y:", 165, 133, 145, 19, &cb->track_offset[1],
- -10 * height, 10.0 * height, step, digits, "Y-offset to parenting point");
-
- uiDefBut(block, LABEL, 0, "Pattern Area:", 0, 114, 300, 19, NULL, 0, 0, 0, 0, "");
- uiDefButF(block, NUM, B_MARKER_PAT_DIM, "Width:", 10, 95, 300, 19, &cb->marker_pat[0], 3.0f,
- 10.0 * width, step, digits, "Width of marker's pattern in screen coordinates");
- uiDefButF(block, NUM, B_MARKER_PAT_DIM, "Height:", 10, 76, 300, 19, &cb->marker_pat[1], 3.0f,
- 10.0 * height, step, digits, "Height of marker's pattern in screen coordinates");
-
- uiDefBut(block, LABEL, 0, "Search Area:", 0, 57, 300, 19, NULL, 0, 0, 0, 0, "");
- uiDefButF(block, NUM, B_MARKER_SEARCH_POS, "X:", 10, 38, 145, 19, &cb->marker_search_pos[0],
- -width, width, step, digits, "X-position of search at frame relative to marker's position");
- uiDefButF(block, NUM, B_MARKER_SEARCH_POS, "Y:", 165, 38, 145, 19, &cb->marker_search_pos[1],
- -height, height, step, digits, "X-position of search at frame relative to marker's position");
- uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, "Width:", 10, 19, 300, 19, &cb->marker_search[0], 3.0f,
- 10.0 * width, step, digits, "Width of marker's search in screen soordinates");
- uiDefButF(block, NUM, B_MARKER_SEARCH_DIM, "Height:", 10, 0, 300, 19, &cb->marker_search[1], 3.0f,
- 10.0 * height, step, digits, "Height of marker's search in screen soordinates");
+ uiDefBut(block, LABEL, 0, IFACE_("Position:"), 0, 190, 300, 19, NULL, 0, 0, 0, 0, "");
+ uiDefButF(block, NUM, B_MARKER_POS, IFACE_("X:"), 10, 171, 145, 19, &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:"), 165, 171, 145, 19, &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, 152, 300, 19, NULL, 0, 0, 0, 0, "");
+ uiDefButF(block, NUM, B_MARKER_OFFSET, IFACE_("X:"), 10, 133, 145, 19, &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:"), 165, 133, 145, 19, &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, 114, 300, 19, NULL, 0, 0, 0, 0, "");
+ uiDefButF(block, NUM, B_MARKER_PAT_DIM, IFACE_("Width:"), 10, 95, 300, 19, &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:"), 10, 76, 300, 19, &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, 57, 300, 19, NULL, 0, 0, 0, 0, "");
+ uiDefButF(block, NUM, B_MARKER_SEARCH_POS, IFACE_("X:"), 10, 38, 145, 19, &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:"), 165, 38, 145, 19, &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:"), 10, 19, 300, 19, &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:"), 10, 0, 300, 19, &cb->marker_search[1], 3.0f,
+ 10.0 * height, step, digits, TIP_("Height of marker's search in screen coordinates"));
uiBlockEndAlign(block);
}
diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c
index cc1b8d444bc..b1be9217819 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_draw.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c
@@ -145,6 +145,31 @@ static void draw_keyframe_shape(float x, float y, float xscale, float yscale, sh
glPopMatrix();
}
+static void clip_draw_dopesheet_background(ARegion *ar, MovieClip *clip)
+{
+ View2D *v2d = &ar->v2d;
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
+ MovieTrackingDopesheetCoverageSegment *coverage_segment;
+
+ for (coverage_segment = dopesheet->coverage_segments.first;
+ coverage_segment;
+ coverage_segment = coverage_segment->next)
+ {
+ if (coverage_segment->coverage < TRACKING_COVERAGE_OK) {
+ int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, coverage_segment->start_frame);
+ int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, coverage_segment->end_frame);
+
+ if (coverage_segment->coverage == TRACKING_COVERAGE_BAD)
+ glColor4f(1.0f, 0.0f, 0.0f, 0.07f);
+ else
+ glColor4f(1.0f, 1.0f, 0.0f, 0.07f);
+
+ glRectf(start_frame, v2d->cur.ymin, end_frame, v2d->cur.ymax);
+ }
+ }
+}
+
void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
{
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -159,7 +184,7 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
MovieTrackingDopesheetChannel *channel;
float y, xscale, yscale;
float strip[4], selected_strip[4];
- float height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT * 2);
+ float height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT);
/* don't use totrect set, as the width stays the same
* (NOTE: this is ok here, the configuration is pretty straightforward)
@@ -179,6 +204,8 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
glEnable(GL_BLEND);
+ clip_draw_dopesheet_background(ar, clip);
+
for (channel = dopesheet->channels.first; channel; channel = channel->next) {
float yminc = (float) (y - CHANNEL_HEIGHT_HALF);
float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF);
@@ -272,7 +299,7 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
tracking = &clip->tracking;
dopesheet = &tracking->dopesheet;
- height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT * 2);
+ height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT);
if (height > BLI_rcti_size_y(&v2d->mask)) {
/* don't use totrect set, as the width stays the same
diff --git a/source/blender/editors/space_clip/clip_dopesheet_ops.c b/source/blender/editors/space_clip/clip_dopesheet_ops.c
index 09f6271b6ef..e5cd7247c43 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_ops.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_ops.c
@@ -59,12 +59,11 @@
#include "clip_intern.h" // own include
-#if 0
-static int ED_space_clip_dopesheet_poll(bContext *C)
+static int space_clip_dopesheet_poll(bContext *C)
{
- SpaceClip *sc = CTX_wm_space_clip(C);
+ if (ED_space_clip_tracking_poll(C)) {
+ SpaceClip *sc = CTX_wm_space_clip(C);
- if (sc && sc->clip) {
if (sc->view == SC_VIEW_DOPESHEET) {
ARegion *ar = CTX_wm_region(C);
@@ -74,7 +73,6 @@ static int ED_space_clip_dopesheet_poll(bContext *C)
return FALSE;
}
-#endif
/********************** select channel operator *********************/
@@ -129,7 +127,7 @@ static int dopesheet_select_channel_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int dopesheet_select_channel_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int dopesheet_select_channel_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
float location[2];
@@ -161,3 +159,54 @@ void CLIP_OT_dopesheet_select_channel(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", 0,
"Extend", "Extend selection rather than clearing the existing selection");
}
+
+/********************** View All operator *********************/
+
+static int dopesheet_view_all_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ ARegion *ar = CTX_wm_region(C);
+ View2D *v2d = &ar->v2d;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
+ MovieTrackingDopesheetChannel *channel;
+ int frame_min = INT_MAX, frame_max = INT_MIN;
+
+ for (channel = dopesheet->channels.first; channel; channel = channel->next) {
+ frame_min = min_ii(frame_min, channel->segments[0]);
+ frame_max = max_ii(frame_max, channel->segments[channel->tot_segment]);
+ }
+
+ if (frame_min < frame_max) {
+ float extra;
+
+ v2d->cur.xmin = frame_min;
+ v2d->cur.xmax = frame_max;
+
+ /* we need an extra "buffer" factor on either side so that the endpoints are visible */
+ extra = 0.01f * BLI_rctf_size_x(&v2d->cur);
+ v2d->cur.xmin -= extra;
+ v2d->cur.xmax += extra;
+
+ ED_region_tag_redraw(ar);
+ }
+
+
+ return OPERATOR_FINISHED;
+}
+
+void CLIP_OT_dopesheet_view_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "View All";
+ ot->description = "Reset viewable area to show full keyframe range";
+ ot->idname = "CLIP_OT_dopesheet_view_all";
+
+ /* api callbacks */
+ ot->exec = dopesheet_view_all_exec;
+ ot->poll = space_clip_dopesheet_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index 9cf389c4508..2d3dc9127c3 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -103,11 +103,11 @@ static void draw_keyframe(int frame, int cfra, int sfra, float framelen, int wid
if (width == 1) {
glBegin(GL_LINES);
glVertex2i(x, 0);
- glVertex2i(x, height);
+ glVertex2i(x, height * UI_DPI_FAC);
glEnd();
}
else {
- glRecti(x, 0, x + width, height);
+ glRecti(x, 0, x + width, height * UI_DPI_FAC);
}
}
@@ -125,7 +125,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
/* cache background */
glColor4ub(128, 128, 255, 64);
- glRecti(0, 0, ar->winx, 8);
+ glRecti(0, 0, ar->winx, 8 * UI_DPI_FAC);
/* cached segments -- could be usefu lto debug caching strategies */
BKE_movieclip_get_cache_segments(clip, &sc->user, &totseg, &points);
@@ -138,7 +138,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
x1 = (points[a * 2] - sfra) / (efra - sfra + 1) * ar->winx;
x2 = (points[a * 2 + 1] - sfra + 1) / (efra - sfra + 1) * ar->winx;
- glRecti(x1, 0, x2, 8);
+ glRecti(x1, 0, x2, 8 * UI_DPI_FAC);
}
}
@@ -175,7 +175,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
else
glColor4ub(255, 255, 0, 96);
- glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 4);
+ glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 4 * UI_DPI_FAC);
}
}
}
@@ -203,7 +203,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
}
if (!ok)
- glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 8);
+ glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 8 * UI_DPI_FAC);
}
}
@@ -213,9 +213,9 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
x = (sc->user.framenr - sfra) / (efra - sfra + 1) * ar->winx;
UI_ThemeColor(TH_CFRAME);
- glRecti(x, 0, x + ceilf(framelen), 8);
+ glRecti(x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC);
- clip_draw_curfra_label(sc->user.framenr, x, 8.0f);
+ clip_draw_curfra_label(sc->user.framenr, x, 8.0f * UI_DPI_FAC);
/* solver keyframes */
glColor4ub(175, 255, 0, 255);
@@ -269,8 +269,18 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar,
if (display_buffer) {
int need_fallback = 1;
+ /* checkerboard for case alpha */
+ if (ibuf->planes == 32) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ fdrawcheckerboard(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y);
+ }
+
if (ED_space_clip_texture_buffer_supported(sc)) {
if (ED_space_clip_load_movieclip_buffer(sc, ibuf, display_buffer)) {
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+
glPushMatrix();
glTranslatef(x, y, 0.0f);
glScalef(zoomx, zoomy, 1.0f);
@@ -296,11 +306,14 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar,
/* set zoom */
glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y);
- glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
+ glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer);
/* reset zoom */
glPixelZoom(1.0f, 1.0f);
}
+
+ if (ibuf->planes == 32)
+ glDisable(GL_BLEND);
}
IMB_display_buffer_release(cache_handle);
@@ -796,11 +809,11 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
dy = 6.0f / height / sc->zoom;
side = get_shortest_pattern_side(marker);
- patdx = min_ff(dx * 2.0f / 3.0f, side / 6.0f);
- patdy = min_ff(dy * 2.0f / 3.0f, side * width / height / 6.0f);
+ patdx = min_ff(dx * 2.0f / 3.0f, side / 6.0f) * UI_DPI_FAC;
+ patdy = min_ff(dy * 2.0f / 3.0f, side * width / height / 6.0f) * UI_DPI_FAC;
- searchdx = min_ff(dx, (marker->search_max[0] - marker->search_min[0]) / 6.0f);
- searchdy = min_ff(dy, (marker->search_max[1] - marker->search_min[1]) / 6.0f);
+ searchdx = min_ff(dx, (marker->search_max[0] - marker->search_min[0]) / 6.0f) * UI_DPI_FAC;
+ searchdy = min_ff(dy, (marker->search_max[1] - marker->search_min[1]) / 6.0f) * UI_DPI_FAC;
px[0] = 1.0f / sc->zoom / width / sc->scale;
px[1] = 1.0f / sc->zoom / height / sc->scale;
@@ -944,7 +957,7 @@ static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
if (state[0])
BLI_snprintf(str, sizeof(str), "%s: %s", track->name, state);
else
- BLI_snprintf(str, sizeof(str), "%s", track->name);
+ BLI_strncpy(str, track->name, sizeof(str));
BLF_position(fontid, pos[0], pos[1], 0.0f);
BLF_draw(fontid, str, sizeof(str));
@@ -1471,6 +1484,8 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
if (ibuf) {
draw_movieclip_buffer(C, sc, ar, ibuf, width, height, zoomx, zoomy);
IMB_freeImBuf(ibuf);
+
+ clip_start_prefetch_job(C);
}
else {
ED_region_grid_draw(ar, zoomx, zoomy);
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index 1a62af39600..6d9c5b4ba46 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -30,22 +30,35 @@
*/
#include <stddef.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <fcntl.h>
-#include "MEM_guardedalloc.h"
+#ifndef WIN32
+# include <unistd.h>
+#else
+# include <io.h>
+#endif
-#include "BKE_main.h"
-#include "BKE_mask.h"
-#include "BKE_movieclip.h"
-#include "BKE_context.h"
-#include "BKE_tracking.h"
+#include "MEM_guardedalloc.h"
#include "DNA_mask_types.h"
#include "DNA_object_types.h" /* SELECT */
#include "BLI_utildefines.h"
+#include "BLI_fileops.h"
#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_rect.h"
+#include "BLI_threads.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"
@@ -81,7 +94,7 @@ int ED_space_clip_view_clip_poll(bContext *C)
{
SpaceClip *sc = CTX_wm_space_clip(C);
- if (sc && sc->clip) {
+ if (sc) {
return sc->view == SC_VIEW_CLIP;
}
@@ -524,8 +537,7 @@ void ED_space_clip_set_clip(bContext *C, bScreen *screen, SpaceClip *sc, MovieCl
old_clip = sc->clip;
sc->clip = clip;
- if (sc->clip && sc->clip->id.us == 0)
- sc->clip->id.us = 1;
+ id_us_ensure_real((ID *)sc->clip);
if (screen && sc->view == SC_VIEW_CLIP) {
ScrArea *area;
@@ -561,9 +573,7 @@ void ED_space_clip_set_mask(bContext *C, SpaceClip *sc, Mask *mask)
{
sc->mask_info.mask = mask;
- if (sc->mask_info.mask && sc->mask_info.mask->id.us == 0) {
- sc->mask_info.mask->id.us = 1;
- }
+ id_us_ensure_real((ID *)sc->mask_info.mask);
if (C) {
WM_event_add_notifier(C, NC_MASK | NA_SELECTED, mask);
@@ -619,8 +629,10 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf, const unsign
context->last_texture = glaGetOneInteger(GL_TEXTURE_2D);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
/* image texture need to be rebinded if displaying another image buffer
- * assuming displaying happens of footage frames only on which painting doesn't heppen.
+ * assuming displaying happens of footage frames only on which painting doesn't happen.
* so not changed image buffer pointer means unchanged image content */
need_rebind |= context->texture_ibuf != ibuf;
need_rebind |= context->display_buffer != display_buffer;
@@ -724,3 +736,380 @@ void ED_space_clip_free_texture_buffer(SpaceClip *sc)
MEM_freeN(context);
}
}
+
+/* ******** pre-fetching functions ******** */
+
+typedef struct PrefetchJob {
+ MovieClip *clip;
+ int start_frame, end_frame;
+ short render_size, render_flag;
+} PrefetchJob;
+
+typedef struct PrefetchQueue {
+ int current_frame, start_frame, end_frame;
+ short render_size, render_flag;
+
+ SpinLock spin;
+
+ short *stop;
+ short *do_update;
+ float *progress;
+} PrefetchQueue;
+
+typedef struct PrefetchThread {
+ MovieClip *clip;
+ PrefetchQueue *queue;
+} PrefetchThread;
+
+/* check whether pre-fetching is allowed */
+static bool check_prefetch_allowed(void)
+{
+ wmWindowManager *wm;
+
+ /* if there's any job started, better to leave all CPU and
+ * HDD bandwidth to it
+ *
+ * also, display transform could be needed during playback,
+ * so better to avoid prefetching in this case and reserve
+ * all the power for display transform
+ */
+ for (wm = G.main->wm.first; wm; wm = wm->id.next) {
+ if (WM_jobs_has_running_except(wm, WM_JOB_TYPE_CLIP_PREFETCH))
+ return false;
+
+ if (ED_screen_animation_playing(wm))
+ return false;
+ }
+
+ return true;
+}
+
+/* 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)
+{
+ MovieClipUser user = {0};
+ char name[FILE_MAX];
+ size_t size;
+ int file;
+ unsigned char *mem;
+
+ user.framenr = current_frame;
+ user.render_size = render_size;
+ user.render_flag = render_flag;
+
+ BKE_movieclip_filename_for_frame(clip, &user, name);
+
+ file = open(name, O_BINARY | O_RDONLY, 0);
+ if (file < 0) {
+ return NULL;
+ }
+
+ size = BLI_file_descriptor_size(file);
+ if (size < 1) {
+ close(file);
+ return NULL;
+ }
+
+ mem = MEM_mallocN(size, "movieclip prefetch memory file");
+
+ if (read(file, mem, size) != size) {
+ close(file);
+ MEM_freeN(mem);
+ return NULL;
+ }
+
+ *size_r = size;
+
+ close(file);
+
+ return mem;
+}
+
+/* find first uncached frame within prefetching frame range */
+static int prefetch_find_uncached_frame(MovieClip *clip, int from_frame, int end_frame,
+ short render_size, short render_flag)
+{
+ int current_frame;
+
+ for (current_frame = from_frame; current_frame <= end_frame; current_frame++) {
+ MovieClipUser user = {0};
+
+ user.framenr = current_frame;
+ user.render_size = render_size;
+ user.render_flag = render_flag;
+
+ if (!BKE_movieclip_has_cached_frame(clip, &user))
+ break;
+ }
+
+ return current_frame;
+}
+
+/* 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)
+{
+ unsigned char *mem = NULL;
+
+ BLI_spin_lock(&queue->spin);
+ if (!*queue->stop && queue->current_frame <= queue->end_frame && check_prefetch_allowed()) {
+ int current_frame;
+ current_frame = prefetch_find_uncached_frame(clip, queue->current_frame + 1, queue->end_frame,
+ queue->render_size, queue->render_flag);
+
+ if (current_frame <= queue->end_frame) {
+ mem = prefetch_read_file_to_memory(clip, current_frame, queue->render_size,
+ queue->render_flag, size_r);
+
+ *current_frame_r = current_frame;
+
+ queue->current_frame = current_frame;
+
+ *queue->do_update = 1;
+ *queue->progress = (float)(queue->current_frame - queue->start_frame) /
+ (queue->end_frame - queue->start_frame);
+ }
+ }
+ BLI_spin_unlock(&queue->spin);
+
+ return mem;
+}
+
+static void *do_prefetch_thread(void *data_v)
+{
+ PrefetchThread *data = (PrefetchThread *) data_v;
+ unsigned char *mem;
+ size_t size;
+ int current_frame;
+
+ while ((mem = prefetch_thread_next_frame(data->queue, data->clip, &size, &current_frame))) {
+ ImBuf *ibuf;
+ MovieClipUser user = {0};
+ int flag = IB_rect | IB_alphamode_detect;
+ int result;
+
+ user.framenr = current_frame;
+ user.render_size = data->queue->render_size;
+ user.render_flag = data->queue->render_flag;
+
+ ibuf = IMB_ibImageFromMemory(mem, size, flag, NULL, "prefetch frame");
+
+ result = BKE_movieclip_put_frame_if_possible(data->clip, &user, ibuf);
+
+ IMB_freeImBuf(ibuf);
+
+ MEM_freeN(mem);
+
+ if (!result) {
+ /* no more space in the cache, stop reading frames */
+ *data->queue->stop = 1;
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+static void start_prefetch_threads(MovieClip *clip, int start_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--;
+
+ /* initialize queue */
+ BLI_spin_init(&queue.spin);
+
+ queue.current_frame = start_frame;
+ queue.start_frame = start_frame;
+ queue.end_frame = end_frame;
+ queue.render_size = render_size;
+ queue.render_flag = render_flag;
+
+ queue.stop = stop;
+ 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);
+
+ 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);
+ }
+
+ /* run the threads */
+ if (tot_thread > 1)
+ BLI_end_threads(&threads);
+ else
+ do_prefetch_thread(handles);
+
+ MEM_freeN(handles);
+}
+
+static void do_prefetch_movie(MovieClip *clip, int start_frame, int end_frame, short render_size,
+ short render_flag, short *stop, short *do_update, float *progress)
+{
+ int current_frame;
+
+ for (current_frame = start_frame; current_frame <= end_frame; current_frame++) {
+ MovieClipUser user = {0};
+ ImBuf *ibuf;
+
+ if (!check_prefetch_allowed() || *stop)
+ break;
+
+ user.framenr = current_frame;
+ user.render_size = render_size;
+ user.render_flag = render_flag;
+
+ if (!BKE_movieclip_has_cached_frame(clip, &user)) {
+ ibuf = BKE_movieclip_anim_ibuf_for_frame(clip, &user);
+
+ if (ibuf) {
+ int result;
+
+ result = BKE_movieclip_put_frame_if_possible(clip, &user, ibuf);
+
+ if (!result) {
+ /* no more space in the cache, we could stop prefetching here */
+ *stop = 1;
+ }
+
+ IMB_freeImBuf(ibuf);
+ }
+ else {
+ /* error reading frame, fair enough stop attempting further reading */
+ *stop = 1;
+ }
+ }
+
+ *do_update = 1;
+ *progress = (float)(current_frame - start_frame) / (end_frame - start_frame);
+ }
+}
+
+static void prefetch_startjob(void *pjv, short *stop, short *do_update, float *progress)
+{
+ PrefetchJob *pj = pjv;
+
+ if (pj->clip->source == MCLIP_SRC_SEQUENCE) {
+ /* read sequence files in multiple threads */
+ start_prefetch_threads(pj->clip, pj->start_frame, pj->end_frame,
+ pj->render_size, pj->render_flag,
+ stop, do_update, progress);
+ }
+ else if (pj->clip->source == MCLIP_SRC_MOVIE) {
+ /* read movie in a single thread */
+ do_prefetch_movie(pj->clip, pj->start_frame, pj->end_frame,
+ pj->render_size, pj->render_flag,
+ stop, do_update, progress);
+ }
+ else {
+ BLI_assert(!"Unknown movie clip source when prefetching frames");
+ }
+}
+
+static void prefetch_freejob(void *pjv)
+{
+ PrefetchJob *pj = pjv;
+
+ MEM_freeN(pj);
+}
+
+static int prefetch_get_final_frame(const bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ int end_frame;
+
+ /* check whether all the frames from prefetch range are cached */
+ end_frame = EFRA;
+
+ if (clip->len)
+ end_frame = min_ii(end_frame, clip->len);
+
+ return end_frame;
+}
+
+/* returns true if early out is possible */
+static bool prefetch_check_early_out(const bContext *C)
+{
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+ int first_uncached_frame, end_frame;
+ int clip_len;
+
+ if (clip->prefetch_ok)
+ return true;
+
+ clip_len = BKE_movieclip_get_duration(clip);
+
+ /* check whether all the frames from prefetch range are cached */
+ end_frame = prefetch_get_final_frame(C);
+
+ first_uncached_frame =
+ prefetch_find_uncached_frame(clip, sc->user.framenr, end_frame,
+ sc->user.render_size, sc->user.render_flag);
+
+ if (first_uncached_frame > end_frame || first_uncached_frame == clip_len)
+ return true;
+
+ return false;
+}
+
+void clip_start_prefetch_job(const bContext *C)
+{
+ wmJob *wm_job;
+ PrefetchJob *pj;
+ SpaceClip *sc = CTX_wm_space_clip(C);
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+
+ if (prefetch_check_early_out(C))
+ return;
+
+ wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), CTX_wm_area(C), "Prefetching",
+ WM_JOB_PROGRESS, WM_JOB_TYPE_CLIP_PREFETCH);
+
+ if (WM_jobs_is_running(wm_job)) {
+ /* if job is already running, it'll call clip editor redraw when
+ * it's finished, so cache line is nicely updated
+ * this will also trigger call of this function, which will ensure
+ * all needed frames are prefetched
+ */
+ return;
+ }
+
+ clip->prefetch_ok = true;
+
+ /* create new job */
+ pj = MEM_callocN(sizeof(PrefetchJob), "prefetch job");
+ pj->clip = ED_space_clip_get_clip(sc);
+ pj->start_frame = sc->user.framenr;
+ pj->end_frame = prefetch_get_final_frame(C);
+ pj->render_size = sc->user.render_size;
+ pj->render_flag = sc->user.render_flag;
+
+ WM_jobs_customdata_set(wm_job, pj, prefetch_freejob);
+ WM_jobs_timer(wm_job, 0.2, NC_MOVIECLIP, 0);
+ WM_jobs_callbacks(wm_job, prefetch_startjob, NULL, NULL, NULL);
+
+ /* and finally start the job */
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+}
diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c
index fa235bd2997..edc6ac1ecf7 100644
--- a/source/blender/editors/space_clip/clip_graph_ops.c
+++ b/source/blender/editors/space_clip/clip_graph_ops.c
@@ -276,7 +276,7 @@ static int select_exec(bContext *C, wmOperator *op)
return mouse_select(C, co, extend);
}
-static int select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
float co[2];
diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h
index d33f77c1064..99222ec63ac 100644
--- a/source/blender/editors/space_clip/clip_intern.h
+++ b/source/blender/editors/space_clip/clip_intern.h
@@ -43,10 +43,10 @@ struct SpaceClip;
struct wmOperatorType;
/* channel heights */
-#define CHANNEL_FIRST -UI_UNIT_Y
-#define CHANNEL_HEIGHT UI_UNIT_Y
-#define CHANNEL_HEIGHT_HALF (UI_UNIT_Y / 2.0f)
-#define CHANNEL_SKIP 2
+#define CHANNEL_FIRST (-0.8f * U.widget_unit)
+#define CHANNEL_HEIGHT (0.8f * U.widget_unit)
+#define CHANNEL_HEIGHT_HALF (0.4f * U.widget_unit)
+#define CHANNEL_SKIP (0.1f * U.widget_unit)
#define CHANNEL_STEP (CHANNEL_HEIGHT + CHANNEL_SKIP)
#define CHANNEL_PAD 4
@@ -54,7 +54,7 @@ struct wmOperatorType;
/* extra padding for lengths (to go under scrollers) */
#define EXTRA_SCROLL_PAD 100.0f
-#define STRIP_HEIGHT_HALF 5
+#define STRIP_HEIGHT_HALF (0.25f * UI_UNIT_Y)
/* internal exports only */
@@ -67,12 +67,16 @@ void clip_draw_dopesheet_channels(const struct bContext *C, struct ARegion *ar);
/* clip_dopesheet_ops.c */
void CLIP_OT_dopesheet_select_channel(struct wmOperatorType *ot);
+void CLIP_OT_dopesheet_view_all(struct wmOperatorType *ot);
/* clip_draw.c */
void clip_draw_main(const struct bContext *C, struct SpaceClip *sc, struct ARegion *ar);
void clip_draw_grease_pencil(struct bContext *C, int onlyv2d);
void clip_draw_curfra_label(const int framenr, const float x, const float y);
+/* clip_editor.c */
+void clip_start_prefetch_job(const struct bContext *C);
+
/* clip_graph_draw.c */
void clip_draw_graph(struct SpaceClip *sc, struct ARegion *ar, struct Scene *scene);
@@ -133,7 +137,7 @@ void clip_draw_cfra(struct SpaceClip *sc, struct ARegion *ar, struct Scene *scen
void clip_draw_sfra_efra(struct View2D *v2d, struct Scene *scene);
/* tracking_ops.c */
-struct MovieTrackingTrack *tracking_marker_check_slide(struct bContext *C, struct wmEvent *event,
+struct MovieTrackingTrack *tracking_marker_check_slide(struct bContext *C, const struct wmEvent *event,
int *area_r, int *action_r, int *corner_r);
void CLIP_OT_add_marker(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index 4e53f34359e..8e03691e64f 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -30,16 +30,26 @@
*/
#include <errno.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#ifndef WIN32
+# include <unistd.h>
+#else
+# include <io.h>
+#endif
#include "MEM_guardedalloc.h"
#include "DNA_userdef_types.h"
#include "DNA_scene_types.h" /* min/max frames */
-#include "BLI_path_util.h"
#include "BLI_utildefines.h"
+#include "BLI_fileops.h"
+#include "BLI_path_util.h"
#include "BLI_math.h"
#include "BLI_rect.h"
+#include "BLI_threads.h"
#include "BLF_translation.h"
@@ -113,7 +123,7 @@ static void sclip_zoom_set_factor(const bContext *C, float zoomfac, float locati
sclip_zoom_set(C, sc->zoom * zoomfac, location);
}
-static void sclip_zoom_set_factor_exec(bContext *C, wmEvent *event, float factor)
+static void sclip_zoom_set_factor_exec(bContext *C, const wmEvent *event, float factor)
{
ARegion *ar = CTX_wm_region(C);
@@ -160,6 +170,7 @@ static int open_exec(bContext *C, wmOperator *op)
{
SpaceClip *sc = CTX_wm_space_clip(C);
bScreen *screen = CTX_wm_screen(C);
+ Main *bmain = CTX_data_main(C);
PropertyPointerRNA *pprop;
PointerRNA idptr;
MovieClip *clip = NULL;
@@ -191,7 +202,7 @@ static int open_exec(bContext *C, wmOperator *op)
errno = 0;
- clip = BKE_movieclip_file_add(str);
+ clip = BKE_movieclip_file_add(bmain, str);
if (!clip) {
if (op->customdata)
@@ -229,7 +240,7 @@ static int open_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int open_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
SpaceClip *sc = CTX_wm_space_clip(C);
char path[FILE_MAX];
@@ -317,7 +328,7 @@ typedef struct ViewPanData {
float *vec;
} ViewPanData;
-static void view_pan_init(bContext *C, wmOperator *op, wmEvent *event)
+static void view_pan_init(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
ViewPanData *vpd;
@@ -376,14 +387,14 @@ static int view_pan_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int view_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (event->type == MOUSEPAN) {
SpaceClip *sc = CTX_wm_space_clip(C);
float offset[2];
- offset[0] = (event->x - event->prevx) / sc->zoom;
- offset[1] = (event->y - event->prevy) / sc->zoom;
+ offset[0] = (event->prevx - event->x) / sc->zoom;
+ offset[1] = (event->prevy - event->y) / sc->zoom;
RNA_float_set_array(op->ptr, "offset", offset);
@@ -398,7 +409,7 @@ static int view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
}
-static int view_pan_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
ViewPanData *vpd = op->customdata;
@@ -470,7 +481,7 @@ typedef struct ViewZoomData {
float location[2];
} ViewZoomData;
-static void view_zoom_init(bContext *C, wmOperator *op, wmEvent *event)
+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);
@@ -513,12 +524,12 @@ static int view_zoom_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int view_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (event->type == MOUSEZOOM) {
+ if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
float delta, factor;
- delta = event->x - event->prevx + event->y - event->prevy;
+ delta = event->prevx - event->x + event->prevy - event->y;
if (U.uiflag & USER_ZOOM_INVERT)
delta *= -1;
@@ -537,7 +548,7 @@ static int view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
}
-static int view_zoom_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int view_zoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewZoomData *vpd = op->customdata;
float delta, factor;
@@ -610,7 +621,7 @@ static int view_zoom_in_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int view_zoom_in_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int view_zoom_in_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
ARegion *ar = CTX_wm_region(C);
@@ -653,7 +664,7 @@ static int view_zoom_out_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int view_zoom_out_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int view_zoom_out_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
ARegion *ar = CTX_wm_region(C);
@@ -843,7 +854,7 @@ static int change_frame_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int frame_from_event(bContext *C, wmEvent *event)
+static int frame_from_event(bContext *C, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
@@ -865,7 +876,7 @@ static int frame_from_event(bContext *C, wmEvent *event)
return framenr;
}
-static int change_frame_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
@@ -884,7 +895,7 @@ static int change_frame_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static int change_frame_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
switch (event->type) {
case ESCKEY:
@@ -908,7 +919,7 @@ static int change_frame_modal(bContext *C, wmOperator *op, wmEvent *event)
void CLIP_OT_change_frame(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Change frame";
+ ot->name = "Change Frame";
ot->idname = "CLIP_OT_change_frame";
ot->description = "Interactively change the current frame number";
@@ -970,46 +981,39 @@ static int proxy_bitflag_to_array(int size_flag, int build_sizes[4], int undisto
return build_count;
}
-/* only this runs inside thread */
-static void proxy_startjob(void *pjv, short *stop, short *do_update, float *progress)
+/* simple case for movies -- handle frame-by-frame, do threading within single frame */
+static void do_movie_proxy(void *pjv, int *UNUSED(build_sizes), int UNUSED(build_count),
+ int *build_undistort_sizes, int build_undistort_count,
+ short *stop, short *do_update, float *progress)
{
ProxyJob *pj = pjv;
Scene *scene = pj->scene;
MovieClip *clip = pj->clip;
struct MovieDistortion *distortion = NULL;
- short size_flag;
int cfra, sfra = SFRA, efra = EFRA;
- int build_sizes[4], build_count = 0;
- int build_undistort_sizes[4], build_undistort_count = 0;
- size_flag = clip->proxy.build_size_flag;
-
- build_count = proxy_bitflag_to_array(size_flag, build_sizes, 0);
- build_undistort_count = proxy_bitflag_to_array(size_flag, build_undistort_sizes, 1);
-
- if (clip->source == MCLIP_SRC_MOVIE) {
- if (pj->index_context)
- IMB_anim_index_rebuild(pj->index_context, stop, do_update, progress);
+ if (pj->index_context)
+ IMB_anim_index_rebuild(pj->index_context, stop, do_update, progress);
- if (!build_undistort_count) {
- if (*stop)
- pj->stop = 1;
+ if (!build_undistort_count) {
+ if (*stop)
+ pj->stop = 1;
- return;
- }
- else {
- sfra = 1;
- efra = IMB_anim_get_duration(clip->anim, IMB_TC_NONE);
- }
+ return;
}
+ else {
+ sfra = 1;
+ efra = IMB_anim_get_duration(clip->anim, IMB_TC_NONE);
+ }
+
+ if (build_undistort_count) {
+ int threads = BLI_system_thread_count();
- if (build_undistort_count)
distortion = BKE_tracking_distortion_new();
+ BKE_tracking_distortion_set_threads(distortion, threads);
+ }
for (cfra = sfra; cfra <= efra; cfra++) {
- if (clip->source != MCLIP_SRC_MOVIE)
- BKE_movieclip_build_proxy_frame(clip, pj->clip_flag, NULL, cfra, build_sizes, build_count, 0);
-
BKE_movieclip_build_proxy_frame(clip, pj->clip_flag, distortion, cfra,
build_undistort_sizes, build_undistort_count, 1);
@@ -1027,6 +1031,196 @@ static void proxy_startjob(void *pjv, short *stop, short *do_update, float *prog
pj->stop = 1;
}
+/* *****
+ * special case for sequences -- handle different frames in different threads,
+ * loading from disk happens in critical section, decoding frame happens from
+ * thread for maximal speed
+ */
+
+typedef struct ProxyQueue {
+ int cfra;
+ int sfra;
+ int efra;
+ SpinLock spin;
+
+ short *stop;
+ short *do_update;
+ float *progress;
+} ProxyQueue;
+
+typedef struct ProxyThread {
+ MovieClip *clip;
+ ProxyQueue *queue;
+
+ struct MovieDistortion *distortion;
+
+ int *build_sizes, build_count;
+ int *build_undistort_sizes, build_undistort_count;
+} ProxyThread;
+
+static unsigned char *proxy_thread_next_frame(ProxyQueue *queue, MovieClip *clip, size_t *size_r, int *cfra_r)
+{
+ unsigned char *mem = NULL;
+
+ BLI_spin_lock(&queue->spin);
+ if (!*queue->stop && queue->cfra <= queue->efra) {
+ MovieClipUser user = {0};
+ char name[FILE_MAX];
+ size_t size;
+ int file;
+
+ user.framenr = queue->cfra;
+
+ BKE_movieclip_filename_for_frame(clip, &user, name);
+
+ file = open(name, O_BINARY | O_RDONLY, 0);
+ if (file < 0) {
+ BLI_spin_unlock(&queue->spin);
+ return NULL;
+ }
+
+ size = BLI_file_descriptor_size(file);
+ if (size < 1) {
+ close(file);
+ BLI_spin_unlock(&queue->spin);
+ return NULL;
+ }
+
+ mem = MEM_mallocN(size, "movieclip proxy memory file");
+
+ if (read(file, mem, size) != size) {
+ close(file);
+ BLI_spin_unlock(&queue->spin);
+ MEM_freeN(mem);
+ return NULL;
+ }
+
+ *size_r = size;
+ *cfra_r = queue->cfra;
+
+ queue->cfra++;
+ close(file);
+
+ *queue->do_update = 1;
+ *queue->progress = (float)(queue->cfra - queue->sfra) / (queue->efra - queue->sfra);
+ }
+ BLI_spin_unlock(&queue->spin);
+
+ return mem;
+}
+
+static void *do_proxy_thread(void *data_v)
+{
+ ProxyThread *data = (ProxyThread *) data_v;
+ unsigned char *mem;
+ size_t size;
+ int cfra;
+
+ while ((mem = proxy_thread_next_frame(data->queue, data->clip, &size, &cfra))) {
+ ImBuf *ibuf;
+
+ ibuf = IMB_ibImageFromMemory(mem, size, IB_rect | IB_multilayer | IB_alphamode_detect, NULL, "proxy frame");
+
+ BKE_movieclip_build_proxy_frame_for_ibuf(data->clip, ibuf, NULL, cfra,
+ data->build_sizes, data->build_count, FALSE);
+
+ BKE_movieclip_build_proxy_frame_for_ibuf(data->clip, ibuf, data->distortion, cfra,
+ data->build_undistort_sizes, data->build_undistort_count, TRUE);
+
+ IMB_freeImBuf(ibuf);
+
+ MEM_freeN(mem);
+ }
+
+ return NULL;
+}
+
+static void do_sequence_proxy(void *pjv, int *build_sizes, int build_count,
+ int *build_undistort_sizes, int build_undistort_count,
+ short *stop, short *do_update, float *progress)
+{
+ ProxyJob *pj = pjv;
+ MovieClip *clip = pj->clip;
+ Scene *scene = pj->scene;
+ int sfra = SFRA, efra = EFRA;
+ ProxyThread *handles;
+ ListBase threads;
+ int i, tot_thread = BLI_system_thread_count();
+ ProxyQueue queue;
+
+ BLI_spin_init(&queue.spin);
+
+ queue.cfra = sfra;
+ queue.sfra = sfra;
+ queue.efra = efra;
+ queue.stop = stop;
+ 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);
+
+ 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;
+
+ handle->build_undistort_count = build_undistort_count;
+ handle->build_undistort_sizes = build_undistort_sizes;
+
+ if (build_undistort_count)
+ handle->distortion = BKE_tracking_distortion_new();
+
+ if (tot_thread > 1)
+ BLI_insert_thread(&threads, handle);
+ }
+
+ if (tot_thread > 1)
+ BLI_end_threads(&threads);
+ else
+ do_proxy_thread(handles);
+
+ MEM_freeN(handles);
+
+ if (build_undistort_count) {
+ for (i = 0; i < tot_thread; i++) {
+ ProxyThread *handle = &handles[i];
+
+ BKE_tracking_distortion_free(handle->distortion);
+ }
+ }
+}
+
+static void proxy_startjob(void *pjv, short *stop, short *do_update, float *progress)
+{
+ ProxyJob *pj = pjv;
+ MovieClip *clip = pj->clip;
+
+ short size_flag;
+ int build_sizes[4], build_count = 0;
+ int build_undistort_sizes[4], build_undistort_count = 0;
+
+ size_flag = clip->proxy.build_size_flag;
+
+ build_count = proxy_bitflag_to_array(size_flag, build_sizes, 0);
+ build_undistort_count = proxy_bitflag_to_array(size_flag, build_undistort_sizes, 1);
+
+ if (clip->source == MCLIP_SRC_MOVIE) {
+ do_movie_proxy(pjv, build_sizes, build_count, build_undistort_sizes,
+ build_undistort_count, stop, do_update, progress);
+ }
+ else {
+ do_sequence_proxy(pjv, build_sizes, build_count, build_undistort_sizes,
+ build_undistort_count, stop, do_update, progress);
+ }
+}
+
static void proxy_endjob(void *pjv)
{
ProxyJob *pj = pjv;
@@ -1133,7 +1327,7 @@ void CLIP_OT_mode_set(wmOperatorType *ot)
* that explains the negative signs in the code below
*/
-static int clip_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int clip_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
if (event->type != NDOF_MOTION)
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/space_clip/clip_toolbar.c b/source/blender/editors/space_clip/clip_toolbar.c
index 1bdf5214192..10175d07300 100644
--- a/source/blender/editors/space_clip/clip_toolbar.c
+++ b/source/blender/editors/space_clip/clip_toolbar.c
@@ -38,15 +38,19 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "BKE_context.h"
#include "BKE_screen.h"
-#include "ED_screen.h"
-#include "ED_util.h"
+#include "RNA_access.h"
#include "WM_types.h"
#include "WM_api.h"
+#include "ED_screen.h"
+#include "ED_util.h"
+
#include "UI_interface.h"
#include "UI_resources.h"
@@ -197,16 +201,16 @@ static void clip_panel_operator_redo_header(const bContext *C, Panel *pa)
wmOperator *op = WM_operator_last_redo(C);
if (op)
- BLI_strncpy(pa->drawname, op->type->name, sizeof(pa->drawname));
+ BLI_strncpy(pa->drawname, RNA_struct_ui_name(op->type->srna), sizeof(pa->drawname));
else
- BLI_strncpy(pa->drawname, "Operator", sizeof(pa->drawname));
+ BLI_strncpy(pa->drawname, IFACE_("Operator"), sizeof(pa->drawname));
}
static void clip_panel_operator_redo_operator(const bContext *C, Panel *pa, wmOperator *op)
{
if (op->type->flag & OPTYPE_MACRO) {
for (op = op->macro.first; op; op = op->next) {
- uiItemL(pa->layout, op->type->name, ICON_NONE);
+ uiItemL(pa->layout, RNA_struct_ui_name(op->type->srna), ICON_NONE);
clip_panel_operator_redo_operator(C, pa, op);
}
}
@@ -219,23 +223,32 @@ static void clip_panel_operator_redo_operator(const bContext *C, Panel *pa, wmOp
static void clip_panel_operator_redo(const bContext *C, Panel *pa)
{
wmOperator *op = WM_operator_last_redo(C);
- uiBlock *block;
+ ARegion *ar;
+ ARegion *ar1;
if (op == NULL)
return;
- if (WM_operator_poll((bContext *)C, op->type) == 0)
- return;
+ /* keep in sync with logic in ED_undo_operator_repeat() */
+ ar = CTX_wm_region(C);
+ ar1 = BKE_area_find_region_type(CTX_wm_area(C), RGN_TYPE_WINDOW);
+ if (ar1)
+ CTX_wm_region_set((bContext *)C, ar1);
- block = uiLayoutGetBlock(pa->layout);
+ if (WM_operator_poll((bContext *)C, op->type)) {
+ uiBlock *block = uiLayoutGetBlock(pa->layout);
- if (!WM_operator_check_ui_enabled(C, op->type->name))
- uiLayoutSetEnabled(pa->layout, FALSE);
+ if (!WM_operator_check_ui_enabled(C, op->type->name))
+ 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);
+ /* note, blockfunc is a default but->func, use Handle func to allow button callbacks too */
+ uiBlockSetHandleFunc(block, ED_undo_operator_repeat_cb_evt, op);
+
+ clip_panel_operator_redo_operator(C, pa, op);
+ }
- clip_panel_operator_redo_operator(C, pa, op);
+ /* set region back */
+ CTX_wm_region_set((bContext *)C, ar);
}
void ED_clip_tool_props_register(ARegionType *art)
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 77e2a1bb3d3..ced19020034 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -236,6 +236,16 @@ static void clip_stabilization_tag_refresh(ScrArea *sa)
}
}
+static void clip_prefetch_tag_refresh(ScrArea *sa)
+{
+ SpaceClip *sc = (SpaceClip *) sa->spacedata.first;
+ MovieClip *clip = ED_space_clip_get_clip(sc);
+
+ if (clip) {
+ clip->prefetch_ok = FALSE;
+ }
+}
+
/* ******************** default callbacks for clip space ***************** */
static SpaceLink *clip_new(const bContext *C)
@@ -246,7 +256,7 @@ static SpaceLink *clip_new(const bContext *C)
sc = MEM_callocN(sizeof(SpaceClip), "initclip");
sc->spacetype = SPACE_CLIP;
sc->flag = SC_SHOW_MARKER_PATTERN | SC_SHOW_TRACK_PATH | SC_MANUAL_CALIBRATION |
- SC_SHOW_GRAPH_TRACKS | SC_SHOW_GRAPH_FRAMES;
+ SC_SHOW_GRAPH_TRACKS | SC_SHOW_GRAPH_FRAMES | SC_SHOW_GPENCIL;
sc->zoom = 1.0f;
sc->path_length = 20;
sc->scopes.track_preview_height = 120;
@@ -351,6 +361,7 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn)
switch (wmn->data) {
case ND_FRAME:
clip_scopes_tag_refresh(sa);
+ clip_prefetch_tag_refresh(sa);
/* no break! */
case ND_FRAME_RANGE:
@@ -359,11 +370,19 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn)
}
break;
case NC_MOVIECLIP:
+ if (wmn->data == 0 && wmn->action == 0) {
+ /* a nit funky, happens from prefetch job to update
+ * cache line and job progress
+ */
+ ED_area_tag_redraw(sa);
+ }
+
switch (wmn->data) {
case ND_DISPLAY:
case ND_SELECT:
clip_scopes_tag_refresh(sa);
ED_area_tag_redraw(sa);
+ clip_prefetch_tag_refresh(sa);
break;
}
switch (wmn->action) {
@@ -407,6 +426,7 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn)
case NC_SCREEN:
switch (wmn->data) {
case ND_ANIMPLAY:
+ clip_prefetch_tag_refresh(sa);
ED_area_tag_redraw(sa);
break;
}
@@ -415,6 +435,7 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn)
if (wmn->data == ND_SPACE_CLIP) {
clip_scopes_tag_refresh(sa);
clip_stabilization_tag_refresh(sa);
+ clip_prefetch_tag_refresh(sa);
ED_area_tag_redraw(sa);
}
break;
@@ -424,6 +445,10 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn)
ED_area_tag_redraw(sa);
}
break;
+ case NC_WM:
+ if (wmn->data == ND_FILEREAD)
+ clip_prefetch_tag_refresh(sa);
+ break;
}
}
@@ -534,6 +559,7 @@ static void clip_operatortypes(void)
/* ** clip_dopesheet_ops.c ** */
WM_operatortype_append(CLIP_OT_dopesheet_select_channel);
+ WM_operatortype_append(CLIP_OT_dopesheet_view_all);
}
static void clip_keymap(struct wmKeyConfig *keyconf)
@@ -587,14 +613,20 @@ static void clip_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "CLIP_OT_view_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "CLIP_OT_view_zoom", MOUSEZOOM, 0, 0, 0);
+ WM_keymap_add_item(keymap, "CLIP_OT_view_zoom", MOUSEPAN, 0, KM_CTRL, 0);
WM_keymap_add_item(keymap, "CLIP_OT_view_zoom_in", WHEELINMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "CLIP_OT_view_zoom_out", WHEELOUTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "CLIP_OT_view_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "CLIP_OT_view_zoom_out", PADMINUS, KM_PRESS, 0, 0);
+ /* ctrl now works as well, shift + numpad works as arrow keys on Windows */
+ RNA_float_set(WM_keymap_add_item(keymap, "CLIP_OT_view_zoom_ratio", PAD8, KM_PRESS, KM_CTRL, 0)->ptr, "ratio", 8.0f);
+ RNA_float_set(WM_keymap_add_item(keymap, "CLIP_OT_view_zoom_ratio", PAD4, KM_PRESS, KM_CTRL, 0)->ptr, "ratio", 4.0f);
+ RNA_float_set(WM_keymap_add_item(keymap, "CLIP_OT_view_zoom_ratio", PAD2, KM_PRESS, KM_CTRL, 0)->ptr, "ratio", 2.0f);
RNA_float_set(WM_keymap_add_item(keymap, "CLIP_OT_view_zoom_ratio", PAD8, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 8.0f);
RNA_float_set(WM_keymap_add_item(keymap, "CLIP_OT_view_zoom_ratio", PAD4, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 4.0f);
RNA_float_set(WM_keymap_add_item(keymap, "CLIP_OT_view_zoom_ratio", PAD2, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 2.0f);
+
RNA_float_set(WM_keymap_add_item(keymap, "CLIP_OT_view_zoom_ratio", PAD1, KM_PRESS, 0, 0)->ptr, "ratio", 1.0f);
RNA_float_set(WM_keymap_add_item(keymap, "CLIP_OT_view_zoom_ratio", PAD2, KM_PRESS, 0, 0)->ptr, "ratio", 0.5f);
RNA_float_set(WM_keymap_add_item(keymap, "CLIP_OT_view_zoom_ratio", PAD4, KM_PRESS, 0, 0)->ptr, "ratio", 0.25f);
@@ -762,6 +794,8 @@ static void clip_keymap(struct wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "CLIP_OT_dopesheet_select_channel", ACTIONMOUSE, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "extend", TRUE); /* toggle */
+
+ WM_keymap_add_item(keymap, "CLIP_OT_dopesheet_view_all", HOMEKEY, KM_PRESS, 0, 0);
}
const char *clip_context_dir[] = {"edit_movieclip", "edit_mask", NULL};
@@ -790,7 +824,7 @@ static int clip_context(const bContext *C, const char *member, bContextDataResul
}
/* dropboxes */
-static int clip_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
+static int clip_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_PATH)
if (ELEM3(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_BLANK)) /* rule might not work? */
@@ -1146,14 +1180,18 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar)
}
- /* Grease Pencil */
- clip_draw_grease_pencil((bContext *)C, 1);
+ if (sc->flag & SC_SHOW_GPENCIL) {
+ /* Grease Pencil */
+ clip_draw_grease_pencil((bContext *)C, TRUE);
+ }
/* reset view matrix */
UI_view2d_view_restore(C);
- /* draw Grease Pencil - screen space only */
- clip_draw_grease_pencil((bContext *)C, 0);
+ if (sc->flag & SC_SHOW_GPENCIL) {
+ /* draw Grease Pencil - screen space only */
+ clip_draw_grease_pencil((bContext *)C, FALSE);
+ }
}
static void clip_main_area_listener(ARegion *ar, wmNotifier *wmn)
@@ -1181,6 +1219,9 @@ static void clip_preview_area_init(wmWindowManager *wm, ARegion *ar)
keymap = WM_keymap_find(wm->defaultconf, "Clip Graph Editor", SPACE_CLIP, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+
+ keymap = WM_keymap_find(wm->defaultconf, "Clip Dopesheet Editor", SPACE_CLIP, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
static void graph_area_draw(const bContext *C, ARegion *ar)
@@ -1272,6 +1313,9 @@ static void clip_channels_area_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
+ /* ensure the 2d view sync works - main region has bottom scroller */
+ ar->v2d.scroll = V2D_SCROLL_BOTTOM;
+
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
keymap = WM_keymap_find(wm->defaultconf, "Clip Dopesheet Editor", SPACE_CLIP, 0);
@@ -1283,7 +1327,6 @@ static void clip_channels_area_draw(const bContext *C, ARegion *ar)
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
View2D *v2d = &ar->v2d;
- View2DScrollers *scrollers;
if (clip)
BKE_tracking_dopesheet_update(&clip->tracking);
@@ -1299,11 +1342,6 @@ static void clip_channels_area_draw(const bContext *C, ARegion *ar)
/* reset view matrix */
UI_view2d_view_restore(C);
-
- /* scrollers */
- scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
}
static void clip_channels_area_listener(ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index a29524de36d..a51315d9a16 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -124,7 +124,7 @@ static int add_marker_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int add_marker_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int add_marker_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
ARegion *ar = CTX_wm_region(C);
@@ -282,7 +282,7 @@ static void slide_marker_tilt_slider(MovieTrackingMarker *marker, float slider[2
}
static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTrack *track,
- MovieTrackingMarker *marker, wmEvent *event,
+ MovieTrackingMarker *marker, const wmEvent *event,
int area, int corner, int action, int width, int height)
{
SlideMarkerData *data = MEM_callocN(sizeof(SlideMarkerData), "slide marker data");
@@ -524,7 +524,7 @@ static void show_cursor(bContext *C)
WM_cursor_set(win, CURSOR_STD);
}
-MovieTrackingTrack *tracking_marker_check_slide(bContext *C, wmEvent *event, int *area_r, int *action_r, int *corner_r)
+MovieTrackingTrack *tracking_marker_check_slide(bContext *C, const wmEvent *event, int *area_r, int *action_r, int *corner_r)
{
SpaceClip *sc = CTX_wm_space_clip(C);
ARegion *ar = CTX_wm_region(C);
@@ -623,7 +623,7 @@ MovieTrackingTrack *tracking_marker_check_slide(bContext *C, wmEvent *event, int
return NULL;
}
-static void *slide_marker_customdata(bContext *C, wmEvent *event)
+static void *slide_marker_customdata(bContext *C, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
ARegion *ar = CTX_wm_region(C);
@@ -652,7 +652,7 @@ static void *slide_marker_customdata(bContext *C, wmEvent *event)
return customdata;
}
-static int slide_marker_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int slide_marker_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SlideMarkerData *slidedata = slide_marker_customdata(C, event);
@@ -703,7 +703,7 @@ static void free_slide_data(SlideMarkerData *data)
MEM_freeN(data);
}
-static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int slide_marker_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
ARegion *ar = CTX_wm_region(C);
@@ -1105,7 +1105,7 @@ static void track_markers_startjob(void *tmv, short *stop, short *do_update, flo
{
TrackMarkersJob *tmj = (TrackMarkersJob *)tmv;
int framenr = tmj->sfra;
- //double t = PIL_check_seconds_timer();
+ // double t = PIL_check_seconds_timer();
while (framenr != tmj->efra) {
if (tmj->delay > 0) {
@@ -1141,7 +1141,7 @@ static void track_markers_startjob(void *tmv, short *stop, short *do_update, flo
break;
}
- //printf("Tracking time: %lf\n", PIL_check_seconds_timer()-t);
+ // printf("Tracking time: %lf\n", PIL_check_seconds_timer()-t);
}
static void track_markers_updatejob(void *tmv)
@@ -1228,7 +1228,7 @@ static int track_markers_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int track_markers_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int track_markers_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
TrackMarkersJob *tmj;
ScrArea *sa = CTX_wm_area(C);
@@ -1286,7 +1286,7 @@ static int track_markers_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(eve
return OPERATOR_RUNNING_MODAL;
}
-static int track_markers_modal(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int track_markers_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
/* no running tracking, remove handler and pass through */
if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_wm_area(C), WM_JOB_TYPE_ANY))
@@ -1457,7 +1457,7 @@ static int solve_camera_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int solve_camera_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int solve_camera_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
SolveCameraJob *scj;
ScrArea *sa = CTX_wm_area(C);
@@ -1507,7 +1507,7 @@ static int solve_camera_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even
return OPERATOR_RUNNING_MODAL;
}
-static int solve_camera_modal(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int solve_camera_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
/* no running solver, remove handler and pass through */
if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_wm_area(C), WM_JOB_TYPE_ANY))
@@ -1801,7 +1801,7 @@ static void object_solver_inverted_matrix(Scene *scene, Object *ob, float invmat
int found = FALSE;
for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
if (!cti)
continue;
@@ -1832,7 +1832,7 @@ static Object *object_solver_camera(Scene *scene, Object *ob)
bConstraint *con;
for (con = ob->constraints.first; con; con = con->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
if (!cti)
continue;
@@ -2025,7 +2025,7 @@ static void set_axis(Scene *scene, Object *ob, MovieClip *clip, MovieTrackingOb
if (!flip) {
float lmat[4][4], ilmat[4][4], rmat[3][3];
- BKE_object_rot_to_mat3(ob, rmat);
+ BKE_object_rot_to_mat3(ob, rmat, TRUE);
invert_m3(rmat);
mul_m4_m4m3(mat, mat, rmat);
@@ -2334,7 +2334,7 @@ static int set_scale_exec(bContext *C, wmOperator *op)
return do_set_scale(C, op, 0);
}
-static int set_scale_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int set_scale_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -2390,7 +2390,7 @@ static int set_solution_scale_exec(bContext *C, wmOperator *op)
return do_set_scale(C, op, 1);
}
-static int set_solution_scale_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int set_solution_scale_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -2892,7 +2892,7 @@ void CLIP_OT_set_solver_keyframe(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_enum(ot->srna, "keyframe", keyframe_items, 0, "Keyframe", "keyframe to set");
+ RNA_def_enum(ot->srna, "keyframe", keyframe_items, 0, "Keyframe", "Keyframe to set");
}
/********************** track copy color operator *********************/
@@ -3258,7 +3258,7 @@ static int clean_tracks_exec(bContext *C, wmOperator *op)
next = track->next;
if ((track->flag & TRACK_HIDDEN) == 0 && (track->flag & TRACK_LOCKED) == 0) {
- int ok = 1;
+ bool ok;
ok = (is_track_clean(track, frames, action == TRACKING_CLEAN_DELETE_SEGMENT)) &&
(error == 0.0f || (track->flag & TRACK_HAS_BUNDLE) == 0 || track->error < error);
@@ -3295,7 +3295,7 @@ static int clean_tracks_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int clean_tracks_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int clean_tracks_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c
index b8e162bfb17..b03209173d8 100644
--- a/source/blender/editors/space_clip/tracking_select.c
+++ b/source/blender/editors/space_clip/tracking_select.c
@@ -123,10 +123,10 @@ static int track_mouse_area(const bContext *C, float co[2], MovieTrackingTrack *
BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max);
- epsx = MIN4(pat_min[0] - marker->search_min[0], marker->search_max[0] - pat_max[0],
- fabsf(pat_min[0]), fabsf(pat_max[0])) / 2;
- epsy = MIN4(pat_min[1] - marker->search_min[1], marker->search_max[1] - pat_max[1],
- fabsf(pat_min[1]), fabsf(pat_max[1])) / 2;
+ epsx = min_ffff(pat_min[0] - marker->search_min[0], marker->search_max[0] - pat_max[0],
+ fabsf(pat_min[0]), fabsf(pat_max[0])) / 2;
+ epsy = min_ffff(pat_min[1] - marker->search_min[1], marker->search_max[1] - pat_max[1],
+ fabsf(pat_min[1]), fabsf(pat_max[1])) / 2;
epsx = max_ff(epsx, 2.0f / width);
epsy = max_ff(epsy, 2.0f / height);
@@ -166,7 +166,7 @@ static float dist_to_rect(float co[2], float pos[2], float min[2], float max[2])
d3 = dist_squared_to_line_segment_v2(p, v3, v4);
d4 = dist_squared_to_line_segment_v2(p, v4, v1);
- return sqrtf(MIN4(d1, d2, d3, d4));
+ return sqrtf(min_ffff(d1, d2, d3, d4));
}
static float dist_to_crns(float co[2], float pos[2], float crns[4][2])
@@ -181,7 +181,7 @@ static float dist_to_crns(float co[2], float pos[2], float crns[4][2])
d3 = dist_squared_to_line_segment_v2(p, v3, v4);
d4 = dist_squared_to_line_segment_v2(p, v4, v1);
- return sqrtf(MIN4(d1, d2, d3, d4));
+ return sqrtf(min_ffff(d1, d2, d3, d4));
}
static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbase, float co[2])
@@ -210,7 +210,7 @@ static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbas
d3 = dist_to_rect(co, marker->pos, marker->search_min, marker->search_max);
/* choose minimal distance. useful for cases of overlapped markers. */
- dist = MIN3(d1, d2, d3);
+ dist = min_fff(d1, d2, d3);
if (track == NULL || dist < mindist) {
track = cur;
@@ -268,6 +268,17 @@ static int mouse_select(bContext *C, float co[2], int extend)
return OPERATOR_FINISHED;
}
+static int select_poll(bContext *C)
+{
+ SpaceClip *sc = CTX_wm_space_clip(C);
+
+ if (sc) {
+ return sc->clip && sc->view == SC_VIEW_CLIP;
+ }
+
+ return FALSE;
+}
+
static int select_exec(bContext *C, wmOperator *op)
{
float co[2];
@@ -279,7 +290,7 @@ static int select_exec(bContext *C, wmOperator *op)
return mouse_select(C, co, extend);
}
-static int select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceClip *sc = CTX_wm_space_clip(C);
ARegion *ar = CTX_wm_region(C);
@@ -317,8 +328,7 @@ void CLIP_OT_select(wmOperatorType *ot)
/* api callbacks */
ot->exec = select_exec;
ot->invoke = select_invoke;
- //ot->poll = ED_space_clip_tracking_poll; // so mask view can Ctrl+RMB markers
- ot->poll = ED_space_clip_view_clip_poll;
+ ot->poll = select_poll;
/* flags */
ot->flag = OPTYPE_UNDO;
diff --git a/source/blender/editors/space_console/SConscript b/source/blender/editors/space_console/SConscript
index f246f08d7ac..3e2c9d6dfdf 100644
--- a/source/blender/editors/space_console/SConscript
+++ b/source/blender/editors/space_console/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c
index a215b476094..cb191d0b15e 100644
--- a/source/blender/editors/space_console/console_draw.c
+++ b/source/blender/editors/space_console/console_draw.c
@@ -50,7 +50,9 @@
#include "ED_datafiles.h"
#include "ED_types.h"
+#include "UI_interface.h"
#include "UI_resources.h"
+#include "UI_view2d.h"
#include "console_intern.h"
@@ -79,9 +81,9 @@ typedef struct ConsoleDrawContext {
int cwidth;
int lheight;
int console_width;
- int winx;
int ymin, ymax;
#if 0 /* used by textview, may use later */
+ int winx;
int *xy; // [2]
int *sel; // [2]
int *pos_pick; /* bottom of view == 0, top of file == combine chars, end of line is lower then start. */
@@ -111,15 +113,12 @@ void console_scrollback_prompt_end(struct SpaceConsole *sc, ConsoleLine *cl_dumm
}
#define CONSOLE_DRAW_MARGIN 4
-#define CONSOLE_DRAW_SCROLL 16
-
-
/* console textview callbacks */
static int console_textview_begin(TextViewContext *tvc)
{
SpaceConsole *sc = (SpaceConsole *)tvc->arg1;
- tvc->lheight = sc->lheight;
+ tvc->lheight = sc->lheight * UI_DPI_FAC;
tvc->sel_start = sc->sel_start;
tvc->sel_end = sc->sel_end;
@@ -151,6 +150,26 @@ static int console_textview_line_get(struct TextViewContext *tvc, const char **l
return 1;
}
+static void console_cursor_wrap_offset(const char *str, int width, int *row, int *column, const char *end)
+{
+ int col;
+
+ for (; *str; str += BLI_str_utf8_size_safe(str)) {
+ col = BLI_str_utf8_char_width_safe(str);
+
+ if (*column + col > width) {
+ (*row)++;
+ *column = 0;
+ }
+
+ if (end && str >= end)
+ break;
+
+ *column += col;
+ }
+ return;
+}
+
static int console_textview_line_color(struct TextViewContext *tvc, unsigned char fg[3], unsigned char UNUSED(bg[3]))
{
ConsoleLine *cl_iter = (ConsoleLine *)tvc->iter;
@@ -159,24 +178,18 @@ static int console_textview_line_color(struct TextViewContext *tvc, unsigned cha
if (tvc->iter_index == 0) {
const SpaceConsole *sc = (SpaceConsole *)tvc->arg1;
const ConsoleLine *cl = (ConsoleLine *)sc->history.last;
- const int prompt_len = strlen(sc->prompt);
- const int cursor_loc = cl->cursor + prompt_len;
- const int line_len = cl->len + prompt_len;
+ int offl = 0, offc = 0;
int xy[2] = {CONSOLE_DRAW_MARGIN, CONSOLE_DRAW_MARGIN};
int pen[2];
xy[1] += tvc->lheight / 6;
- /* account for wrapping */
- if (line_len < tvc->console_width) {
- /* simple case, no wrapping */
- pen[0] = tvc->cwidth * cursor_loc;
- pen[1] = -2;
- }
- else {
- /* wrap */
- pen[0] = tvc->cwidth * (cursor_loc % tvc->console_width);
- pen[1] = -2 + (((line_len / tvc->console_width) - (cursor_loc / tvc->console_width)) * tvc->lheight);
- }
+ console_cursor_wrap_offset(sc->prompt, tvc->console_width, &offl, &offc, NULL);
+ console_cursor_wrap_offset(cl->line, tvc->console_width, &offl, &offc, cl->line + cl->cursor);
+ pen[0] = tvc->cwidth * offc;
+ pen[1] = -2 - tvc->lheight * offl;
+
+ console_cursor_wrap_offset(cl->line + cl->cursor, tvc->console_width, &offl, &offc, NULL);
+ pen[1] += tvc->lheight * offl;
/* cursor */
UI_GetThemeColor3ubv(TH_CONSOLE_CURSOR, fg);
@@ -194,8 +207,13 @@ static int console_textview_line_color(struct TextViewContext *tvc, unsigned cha
return TVC_LINE_FG;
}
+static void console_textview_const_colors(TextViewContext *UNUSED(tvc), unsigned char bg_sel[4])
+{
+ UI_GetThemeColor4ubv(TH_CONSOLE_SELECT, bg_sel);
+}
-static int console_textview_main__internal(struct SpaceConsole *sc, ARegion *ar, int draw, int mval[2], void **mouse_pick, int *pos_pick)
+static int console_textview_main__internal(struct SpaceConsole *sc, ARegion *ar, int draw,
+ int mval[2], void **mouse_pick, int *pos_pick)
{
ConsoleLine cl_dummy = {NULL};
int ret = 0;
@@ -210,6 +228,7 @@ static int console_textview_main__internal(struct SpaceConsole *sc, ARegion *ar,
tvc.step = console_textview_step;
tvc.line_get = console_textview_line_get;
tvc.line_color = console_textview_line_color;
+ tvc.const_colors = console_textview_const_colors;
tvc.arg1 = sc;
tvc.arg2 = NULL;
@@ -217,10 +236,10 @@ static int console_textview_main__internal(struct SpaceConsole *sc, ARegion *ar,
/* view */
tvc.sel_start = sc->sel_start;
tvc.sel_end = sc->sel_end;
- tvc.lheight = sc->lheight;
+ tvc.lheight = sc->lheight * UI_DPI_FAC;
tvc.ymin = v2d->cur.ymin;
tvc.ymax = v2d->cur.ymax;
- tvc.winx = ar->winx;
+ tvc.winx = ar->winx - V2D_SCROLL_WIDTH;
console_scrollback_prompt_begin(sc, &cl_dummy);
ret = textview_draw(&tvc, draw, mval, mouse_pick, pos_pick);
@@ -242,13 +261,13 @@ int console_textview_height(struct SpaceConsole *sc, ARegion *ar)
return console_textview_main__internal(sc, ar, 0, mval, NULL, NULL);
}
-int console_char_pick(struct SpaceConsole *sc, ARegion *ar, int mval[2])
+int console_char_pick(struct SpaceConsole *sc, ARegion *ar, const int mval[2])
{
int pos_pick = 0;
void *mouse_pick = NULL;
int mval_clamp[2];
- mval_clamp[0] = CLAMPIS(mval[0], CONSOLE_DRAW_MARGIN, ar->winx - (CONSOLE_DRAW_SCROLL + CONSOLE_DRAW_MARGIN));
+ mval_clamp[0] = CLAMPIS(mval[0], CONSOLE_DRAW_MARGIN, ar->winx - CONSOLE_DRAW_MARGIN);
mval_clamp[1] = CLAMPIS(mval[1], CONSOLE_DRAW_MARGIN, ar->winy - CONSOLE_DRAW_MARGIN);
console_textview_main__internal(sc, ar, 0, mval_clamp, &mouse_pick, &pos_pick);
diff --git a/source/blender/editors/space_console/console_intern.h b/source/blender/editors/space_console/console_intern.h
index 3d30dcad710..00f1f8c21c9 100644
--- a/source/blender/editors/space_console/console_intern.h
+++ b/source/blender/editors/space_console/console_intern.h
@@ -37,7 +37,7 @@ struct bContext;
/* console_draw.c */
void console_textview_main(struct SpaceConsole *sc, struct ARegion *ar);
int console_textview_height(struct SpaceConsole *sc, struct ARegion *ar); /* needed to calculate the scrollbar */
-int console_char_pick(struct SpaceConsole *sc, struct ARegion *ar, int mval[2]);
+int console_char_pick(struct SpaceConsole *sc, struct ARegion *ar, const int mval[2]);
void console_scrollback_prompt_begin(struct SpaceConsole *sc, ConsoleLine *cl_dummy);
void console_scrollback_prompt_end(struct SpaceConsole *sc, ConsoleLine *cl_dummy);
@@ -45,8 +45,8 @@ void console_scrollback_prompt_end(struct SpaceConsole *sc, ConsoleLine *cl_dumm
/* console_ops.c */
void console_history_free(SpaceConsole *sc, ConsoleLine *cl);
void console_scrollback_free(SpaceConsole *sc, ConsoleLine *cl);
-ConsoleLine *console_history_add_str(struct SpaceConsole *sc, char *str, int own);
-ConsoleLine *console_scrollback_add_str(struct SpaceConsole *sc, char *str, int own);
+ConsoleLine *console_history_add_str(struct SpaceConsole *sc, char *str, bool own);
+ConsoleLine *console_scrollback_add_str(struct SpaceConsole *sc, char *str, bool own);
ConsoleLine *console_history_verify(const struct bContext *C);
diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c
index 36716aeab95..74f776549e9 100644
--- a/source/blender/editors/space_console/console_ops.c
+++ b/source/blender/editors/space_console/console_ops.c
@@ -34,11 +34,12 @@
#include "DNA_userdef_types.h"
+#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BLI_string_cursor_utf8.h"
+#include "BLI_string_utf8.h"
#include "BLI_string.h"
#include "BLI_dynstr.h"
-#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BKE_context.h"
@@ -115,7 +116,7 @@ static ConsoleLine *console_history_find(SpaceConsole *sc, const char *str, Cons
}
/* return 0 if no change made, clamps the range */
-static int console_line_cursor_set(ConsoleLine *cl, int cursor)
+static bool console_line_cursor_set(ConsoleLine *cl, int cursor)
{
int cursor_new;
@@ -124,11 +125,11 @@ static int console_line_cursor_set(ConsoleLine *cl, int cursor)
else cursor_new = cursor;
if (cursor_new == cl->cursor) {
- return FALSE;
+ return false;
}
cl->cursor = cursor_new;
- return TRUE;
+ return true;
}
#if 0 // XXX unused
@@ -187,7 +188,7 @@ static ConsoleLine *console_scrollback_add(const bContext *C, ConsoleLine *from)
}
#endif
-static ConsoleLine *console_lb_add_str__internal(ListBase *lb, char *str, int own)
+static ConsoleLine *console_lb_add_str__internal(ListBase *lb, char *str, bool own)
{
ConsoleLine *ci = MEM_callocN(sizeof(ConsoleLine), "ConsoleLine Add");
if (own) ci->line = str;
@@ -198,11 +199,11 @@ static ConsoleLine *console_lb_add_str__internal(ListBase *lb, char *str, int ow
BLI_addtail(lb, ci);
return ci;
}
-ConsoleLine *console_history_add_str(SpaceConsole *sc, char *str, int own)
+ConsoleLine *console_history_add_str(SpaceConsole *sc, char *str, bool own)
{
return console_lb_add_str__internal(&sc->history, str, own);
}
-ConsoleLine *console_scrollback_add_str(SpaceConsole *sc, char *str, int own)
+ConsoleLine *console_scrollback_add_str(SpaceConsole *sc, char *str, bool own)
{
ConsoleLine *ci = console_lb_add_str__internal(&sc->scrollback, str, own);
console_select_offset(sc, ci->len + 1);
@@ -275,7 +276,7 @@ static int console_move_exec(bContext *C, wmOperator *op)
ConsoleLine *ci = console_history_verify(C);
int type = RNA_enum_get(op->ptr, "type");
- int done = FALSE;
+ bool done = false;
int pos;
switch (type) {
@@ -283,28 +284,28 @@ static int console_move_exec(bContext *C, wmOperator *op)
pos = ci->cursor;
BLI_str_cursor_step_utf8(ci->line, ci->len,
&pos, STRCUR_DIR_PREV,
- STRCUR_JUMP_ALL);
+ STRCUR_JUMP_ALL, true);
done = console_line_cursor_set(ci, pos);
break;
case LINE_END:
pos = ci->cursor;
BLI_str_cursor_step_utf8(ci->line, ci->len,
&pos, STRCUR_DIR_NEXT,
- STRCUR_JUMP_ALL);
+ STRCUR_JUMP_ALL, true);
done = console_line_cursor_set(ci, pos);
break;
case PREV_CHAR:
pos = ci->cursor;
BLI_str_cursor_step_utf8(ci->line, ci->len,
&pos, STRCUR_DIR_PREV,
- STRCUR_JUMP_NONE);
+ STRCUR_JUMP_NONE, true);
done = console_line_cursor_set(ci, pos);
break;
case NEXT_CHAR:
pos = ci->cursor;
BLI_str_cursor_step_utf8(ci->line, ci->len,
&pos, STRCUR_DIR_NEXT,
- STRCUR_JUMP_NONE);
+ STRCUR_JUMP_NONE, true);
done = console_line_cursor_set(ci, pos);
break;
@@ -314,14 +315,14 @@ static int console_move_exec(bContext *C, wmOperator *op)
pos = ci->cursor;
BLI_str_cursor_step_utf8(ci->line, ci->len,
&pos, STRCUR_DIR_PREV,
- STRCUR_JUMP_DELIM);
+ STRCUR_JUMP_DELIM, true);
done = console_line_cursor_set(ci, pos);
break;
case NEXT_WORD:
pos = ci->cursor;
BLI_str_cursor_step_utf8(ci->line, ci->len,
&pos, STRCUR_DIR_NEXT,
- STRCUR_JUMP_DELIM);
+ STRCUR_JUMP_DELIM, true);
done = console_line_cursor_set(ci, pos);
break;
}
@@ -389,19 +390,30 @@ static int console_insert_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int console_insert_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int console_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
// if (!RNA_struct_property_is_set(op->ptr, "text")) { /* always set from keymap XXX */
if (!RNA_string_length(op->ptr, "text")) {
- /* if alt/ctrl/super are pressed pass through */
- if (event->ctrl || event->oskey) {
+ /* if alt/ctrl/super are pressed pass through except for utf8 character event
+ * (when input method are used for utf8 inputs, the user may assign key event
+ * including alt/ctrl/super like ctrl+m to commit utf8 string. in such case,
+ * the modifiers in the utf8 character event make no sense.) */
+ if ((event->ctrl || event->oskey) && !event->utf8_buf[0]) {
return OPERATOR_PASS_THROUGH;
}
else {
- char str[2];
- str[0] = event->ascii;
- str[1] = '\0';
-
+ char str[BLI_UTF8_MAX + 1];
+ size_t len;
+
+ if (event->utf8_buf[0]) {
+ len = BLI_str_utf8_size_safe(event->utf8_buf);
+ memcpy(str, event->utf8_buf, len);
+ }
+ else {
+ /* in theory, ghost can set value to extended ascii here */
+ len = BLI_str_utf8_from_unicode(event->ascii, str);
+ }
+ str[len] = '\0';
RNA_string_set(op->ptr, "text", str);
}
}
@@ -550,7 +562,7 @@ static int console_delete_exec(bContext *C, wmOperator *op)
pos = ci->cursor;
BLI_str_cursor_step_utf8(ci->line, ci->len,
&pos, STRCUR_DIR_NEXT,
- (type == DEL_NEXT_CHAR) ? STRCUR_JUMP_NONE : STRCUR_JUMP_DELIM);
+ (type == DEL_NEXT_CHAR) ? STRCUR_JUMP_NONE : STRCUR_JUMP_DELIM, true);
stride = pos - ci->cursor;
if (stride) {
memmove(ci->line + ci->cursor, ci->line + ci->cursor + stride, (ci->len - ci->cursor) + 1);
@@ -566,7 +578,7 @@ static int console_delete_exec(bContext *C, wmOperator *op)
pos = ci->cursor;
BLI_str_cursor_step_utf8(ci->line, ci->len,
&pos, STRCUR_DIR_PREV,
- (type == DEL_PREV_CHAR) ? STRCUR_JUMP_NONE : STRCUR_JUMP_DELIM);
+ (type == DEL_PREV_CHAR) ? STRCUR_JUMP_NONE : STRCUR_JUMP_DELIM, true);
stride = ci->cursor - pos;
if (stride) {
ci->cursor -= stride; /* same as above */
@@ -1030,7 +1042,7 @@ static void console_cursor_set_to_pos(SpaceConsole *sc, ARegion *ar, SetConsoleC
}
}
-static void console_modal_select_apply(bContext *C, wmOperator *op, wmEvent *event)
+static void console_modal_select_apply(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceConsole *sc = CTX_wm_space_console(C);
ARegion *ar = CTX_wm_region(C);
@@ -1068,7 +1080,7 @@ static void console_cursor_set_exit(bContext *UNUSED(C), wmOperator *op)
MEM_freeN(scu);
}
-static int console_modal_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int console_modal_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceConsole *sc = CTX_wm_space_console(C);
// ARegion *ar = CTX_wm_region(C);
@@ -1089,7 +1101,7 @@ static int console_modal_select_invoke(bContext *C, wmOperator *op, wmEvent *eve
return OPERATOR_RUNNING_MODAL;
}
-static int console_modal_select(bContext *C, wmOperator *op, wmEvent *event)
+static int console_modal_select(bContext *C, wmOperator *op, const wmEvent *event)
{
switch (event->type) {
case LEFTMOUSE:
diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c
index be8febdab23..4243ae4e2df 100644
--- a/source/blender/editors/space_console/space_console.c
+++ b/source/blender/editors/space_console/space_console.c
@@ -160,7 +160,7 @@ static void console_main_area_init(wmWindowManager *wm, ARegion *ar)
/* ************* dropboxes ************* */
-static int id_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
+static int id_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
// SpaceConsole *sc = CTX_wm_space_console(C);
if (drag->type == WM_DRAG_ID)
@@ -174,12 +174,12 @@ static void id_drop_copy(wmDrag *drag, wmDropBox *drop)
ID *id = drag->poin;
/* copy drag path to properties */
- text = RNA_path_from_ID_python(id);
+ text = RNA_path_full_ID_py(id);
RNA_string_set(drop->ptr, "text", text);
MEM_freeN(text);
}
-static int path_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
+static int path_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
// SpaceConsole *sc = CTX_wm_space_console(C);
if (drag->type == WM_DRAG_PATH)
diff --git a/source/blender/editors/space_file/CMakeLists.txt b/source/blender/editors/space_file/CMakeLists.txt
index 98e147413ff..b30f008e1bf 100644
--- a/source/blender/editors/space_file/CMakeLists.txt
+++ b/source/blender/editors/space_file/CMakeLists.txt
@@ -82,4 +82,8 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_FREESTYLE)
+ add_definitions(-DWITH_FREESTYLE)
+endif()
+
blender_add_lib(bf_editor_space_file "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_file/SConscript b/source/blender/editors/space_file/SConscript
index b387d489805..6459f880bc4 100644
--- a/source/blender/editors/space_file/SConscript
+++ b/source/blender/editors/space_file/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
@@ -22,6 +48,9 @@ if env['WITH_BF_TIFF']:
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
+if env['WITH_BF_FREESTYLE']:
+ defs.append('WITH_FREESTYLE')
+
if env['OURPLATFORM'] == 'linux':
cflags='-pthread'
incs += ' ../../../extern/binreloc/include'
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index fb438ae45fb..5b6b8656072 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_dynstr.h"
+#include "BLI_fileops_types.h"
#ifdef WIN32
# include "BLI_winstuff.h"
@@ -55,6 +56,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
#include "RNA_access.h"
@@ -321,8 +323,7 @@ void file_calc_previews(const bContext *C, ARegion *ar)
View2D *v2d = &ar->v2d;
ED_fileselect_init_layout(sfile, ar);
- /* +SCROLL_HEIGHT is bad hack to work around issue in UI_view2d_totRect_set */
- UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height + V2D_SCROLL_HEIGHT);
+ 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, short dropshadow)
@@ -336,7 +337,9 @@ static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int
float scale;
int ex, ey;
- if ( (imb->x > layout->prv_w) || (imb->y > layout->prv_h) ) {
+ 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;
@@ -349,10 +352,11 @@ static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int
}
}
else {
- scaledx = (float)imb->x;
- scaledy = (float)imb->y;
- scale = 1.0;
+ scaledx = (float)imb->x * UI_DPI_FAC;
+ scaledy = (float)imb->y * UI_DPI_FAC;
+ scale = UI_DPI_FAC;
}
+
ex = (int)scaledx;
ey = (int)scaledy;
fx = ((float)layout->prv_w - (float)ex) / 2.0f;
@@ -372,7 +376,7 @@ static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int
/* the image */
glColor4f(1.0, 1.0, 1.0, 1.0);
- glaDrawPixelsTexScaled((float)xco, (float)yco, imb->x, imb->y, GL_UNSIGNED_BYTE, imb->rect, scale, scale);
+ glaDrawPixelsTexScaled((float)xco, (float)yco, imb->x, imb->y, GL_UNSIGNED_BYTE, GL_NEAREST, imb->rect, scale, scale);
/* border */
if (dropshadow) {
@@ -394,6 +398,7 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
char newname[FILE_MAX + 12];
char orgname[FILE_MAX + 12];
char filename[FILE_MAX + 12];
+ wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C);
ARegion *ar = CTX_wm_region(C);
@@ -405,7 +410,7 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
if (!BLI_exists(newname)) {
BLI_rename(orgname, newname);
/* to make sure we show what is on disk */
- ED_fileselect_clear(C, sfile);
+ ED_fileselect_clear(wm, sfile);
}
ED_region_tag_redraw(ar);
@@ -462,7 +467,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
int i;
short is_icon;
short align;
-
+ int column_space = 0.6f * UI_UNIT_X;
numfiles = filelist_numfiles(files);
@@ -493,7 +498,7 @@ void file_draw_list(const bContext *C, ARegion *ar)
for (i = offset; (i < numfiles) && (i < offset + numfiles_layout); i++) {
ED_fileselect_layout_tilepos(layout, i, &sx, &sy);
- sx += (int)(v2d->tot.xmin + 2.0f);
+ sx += (int)(v2d->tot.xmin + 0.1f * UI_UNIT_X);
sy = (int)(v2d->tot.ymax - sy);
file = filelist_file(files, i);
@@ -522,13 +527,13 @@ void file_draw_list(const bContext *C, ARegion *ar)
}
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);
- sx += ICON_DEFAULT_WIDTH_SCALE + 4;
+ 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 - 3,
+ 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 */
@@ -544,39 +549,39 @@ void file_draw_list(const bContext *C, ARegion *ar)
}
if (params->display == FILE_SHORTDISPLAY) {
- sx += (int)layout->column_widths[COLUMN_NAME] + 12;
+ 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] + 12;
+ sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
}
}
else if (params->display == FILE_LONGDISPLAY) {
- sx += (int)layout->column_widths[COLUMN_NAME] + 12;
+ 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] + 12;
+ 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] + 12;
+ 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] + 12;
+ 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] + 12;
+ 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] + 12;
+ 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] + 12;
+ 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] + 12;
+ sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
}
}
}
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index 763b18788de..f705831c715 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -28,6 +28,9 @@
* \ingroup spfile
*/
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_fileops_types.h"
#include "BKE_context.h"
#include "BKE_screen.h"
@@ -35,9 +38,6 @@
#include "BKE_report.h"
#include "BKE_main.h"
-#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
-
#ifdef WIN32
# include "BLI_winstuff.h"
#endif
@@ -228,7 +228,7 @@ static FileSelect file_select(bContext *C, const rcti *rect, FileSelType select,
return retval;
}
-static int file_border_select_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int file_border_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceFile *sfile = CTX_wm_space_file(C);
@@ -311,7 +311,7 @@ void FILE_OT_select_border(wmOperatorType *ot)
WM_operator_properties_gesture_border(ot, 1);
}
-static int file_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceFile *sfile = CTX_wm_space_file(C);
@@ -585,7 +585,7 @@ int file_highlight_set(SpaceFile *sfile, ARegion *ar, int mx, int my)
return (params->active_file != origfile);
}
-static int file_highlight_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int file_highlight_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceFile *sfile = CTX_wm_space_file(C);
@@ -612,12 +612,13 @@ void FILE_OT_highlight(struct wmOperatorType *ot)
int file_cancel_exec(bContext *C, wmOperator *UNUSED(unused))
{
+ wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
wmOperator *op = sfile->op;
sfile->op = NULL;
- WM_event_fileselect_event(C, op, EVT_FILESELECT_CANCEL);
+ WM_event_fileselect_event(wm, op, EVT_FILESELECT_CANCEL);
return OPERATOR_FINISHED;
}
@@ -780,6 +781,7 @@ int file_draw_check_exists(SpaceFile *sfile)
/* 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);
char filepath[FILE_MAX];
@@ -811,7 +813,7 @@ int file_exec(bContext *C, wmOperator *exec_op)
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);
- WM_event_fileselect_event(C, op, EVT_FILESELECT_EXEC);
+ WM_event_fileselect_event(wm, op, EVT_FILESELECT_EXEC);
}
@@ -871,10 +873,11 @@ void FILE_OT_parent(struct wmOperatorType *ot)
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();
- ED_fileselect_clear(C, sfile);
+ ED_fileselect_clear(wm, sfile);
/* refresh system directory menu */
fsmenu_refresh_system_category(fsmenu);
@@ -950,7 +953,7 @@ int file_next_exec(bContext *C, wmOperator *UNUSED(unused))
/* only meant for timer usage */
-static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
ScrArea *sa = CTX_wm_area(C);
SpaceFile *sfile = CTX_wm_space_file(C);
@@ -1088,6 +1091,7 @@ int file_directory_new_exec(bContext *C, wmOperator *op)
char path[FILE_MAX];
int generate_name = 1;
+ wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
if (!sfile->params) {
@@ -1126,7 +1130,7 @@ 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(C, sfile);
+ ED_fileselect_clear(wm, sfile);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
return OPERATOR_FINISHED;
@@ -1179,11 +1183,10 @@ static void file_expand_directory(bContext *C)
get_default_root(sfile->params->dir);
}
/* change "C:" --> "C:\", [#28102] */
- else if ( (isalpha(sfile->params->dir[0]) &&
- (sfile->params->dir[1] == ':')) &&
- (sfile->params->dir[2] == '\0')
-
- ) {
+ else if ((isalpha(sfile->params->dir[0]) &&
+ (sfile->params->dir[1] == ':')) &&
+ (sfile->params->dir[2] == '\0'))
+ {
sfile->params->dir[2] = '\\';
sfile->params->dir[3] = '\0';
}
@@ -1191,7 +1194,7 @@ static void file_expand_directory(bContext *C)
}
}
-static int file_directory_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int file_directory_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
SpaceFile *sfile = CTX_wm_space_file(C);
@@ -1229,7 +1232,6 @@ int file_directory_exec(bContext *C, wmOperator *UNUSED(unused))
}
BLI_cleanup_dir(G.main->name, sfile->params->dir);
- BLI_add_slash(sfile->params->dir);
file_change_dir(C, 1);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
@@ -1293,11 +1295,12 @@ void FILE_OT_refresh(struct wmOperatorType *ot)
static int file_hidedot_exec(bContext *C, wmOperator *UNUSED(unused))
{
+ wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
if (sfile->params) {
sfile->params->flag ^= FILE_HIDE_DOT;
- ED_fileselect_clear(C, sfile);
+ ED_fileselect_clear(wm, sfile);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
@@ -1479,14 +1482,15 @@ static int file_delete_poll(bContext *C)
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;
file = filelist_file(sfile->files, sfile->params->active_file);
BLI_make_file_string(G.main->name, str, sfile->params->dir, file->relname);
- BLI_delete(str, 0, 0);
- ED_fileselect_clear(C, sfile);
+ BLI_delete(str, false, false);
+ ED_fileselect_clear(wm, 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 a159c88221e..9a7f528be78 100644
--- a/source/blender/editors/space_file/file_panels.c
+++ b/source/blender/editors/space_file/file_panels.c
@@ -190,12 +190,12 @@ static void file_panel_operator_header(const bContext *C, Panel *pa)
BLI_strncpy(pa->drawname, RNA_struct_ui_name(op->type->srna), sizeof(pa->drawname));
}
-static int file_panel_check_prop(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
+static bool file_panel_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")
);
}
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index a49b75477e4..f1e707f8802 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -48,6 +48,7 @@
#include "BLI_linklist.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLI_fileops_types.h"
#ifdef WIN32
# include "BLI_winstuff.h"
@@ -545,8 +546,6 @@ FileList *filelist_new(short type)
void filelist_free(struct FileList *filelist)
{
- int i;
-
if (!filelist) {
printf("Attempting to delete empty filelist.\n");
return;
@@ -557,23 +556,8 @@ void filelist_free(struct FileList *filelist)
filelist->fidx = NULL;
}
- for (i = 0; i < filelist->numfiles; ++i) {
- if (filelist->filelist[i].image) {
- IMB_freeImBuf(filelist->filelist[i].image);
- }
- filelist->filelist[i].image = NULL;
- if (filelist->filelist[i].relname)
- MEM_freeN(filelist->filelist[i].relname);
- if (filelist->filelist[i].path)
- MEM_freeN(filelist->filelist[i].path);
- filelist->filelist[i].relname = NULL;
- if (filelist->filelist[i].string)
- MEM_freeN(filelist->filelist[i].string);
- filelist->filelist[i].string = NULL;
- }
-
+ BLI_free_filelist(filelist->filelist, filelist->numfiles);
filelist->numfiles = 0;
- free(filelist->filelist);
filelist->filelist = NULL;
filelist->filter = 0;
filelist->filter_glob[0] = '\0';
@@ -874,18 +858,14 @@ static void filelist_setfiletypes(struct FileList *filelist)
static void filelist_read_dir(struct FileList *filelist)
{
- char wdir[FILE_MAX] = "";
if (!filelist) return;
filelist->fidx = NULL;
filelist->filelist = NULL;
- BLI_current_working_dir(wdir, sizeof(wdir)); /* backup cwd to restore after */
-
BLI_cleanup_dir(G.main->name, filelist->dir);
filelist->numfiles = BLI_dir_contents(filelist->dir, &(filelist->filelist));
- if (!chdir(wdir)) {} /* fix warning about not checking return value */
filelist_setfiletypes(filelist);
filelist_filter(filelist);
}
@@ -1033,7 +1013,7 @@ static int groupname_to_code(const char *group)
char *lslash;
BLI_strncpy(buf, group, sizeof(buf));
- lslash = BLI_last_slash(buf);
+ lslash = (char *)BLI_last_slash(buf);
if (lslash)
lslash[0] = '\0';
@@ -1162,7 +1142,11 @@ void filelist_from_main(struct FileList *filelist)
if (filelist->dir[0] == 0) {
/* make directories */
+#ifdef WITH_FREESTYLE
+ filelist->numfiles = 25;
+#else
filelist->numfiles = 24;
+#endif
filelist->filelist = (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry));
for (a = 0; a < filelist->numfiles; a++) {
@@ -1193,6 +1177,9 @@ void filelist_from_main(struct FileList *filelist)
filelist->filelist[21].relname = BLI_strdup("Action");
filelist->filelist[22].relname = BLI_strdup("NodeTree");
filelist->filelist[23].relname = BLI_strdup("Speaker");
+#ifdef WITH_FREESTYLE
+ filelist->filelist[24].relname = BLI_strdup("FreestyleLineStyle");
+#endif
filelist_sort(filelist, FILE_SORT_ALPHA);
}
else {
@@ -1357,7 +1344,7 @@ static void thumbnails_free(void *tjv)
}
-void thumbnails_start(struct FileList *filelist, const struct bContext *C)
+void thumbnails_start(FileList *filelist, const bContext *C)
{
wmJob *wm_job;
ThumbnailJob *tj;
@@ -1369,7 +1356,7 @@ void thumbnails_start(struct FileList *filelist, const struct bContext *C)
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(struct FileImage), "loadimage");
+ 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;
@@ -1391,12 +1378,12 @@ void thumbnails_start(struct FileList *filelist, const struct bContext *C)
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
-void thumbnails_stop(struct FileList *filelist, const struct bContext *C)
+void thumbnails_stop(wmWindowManager *wm, FileList *filelist)
{
- WM_jobs_kill(CTX_wm_manager(C), filelist, NULL);
+ WM_jobs_kill(wm, filelist, NULL);
}
-int thumbnails_running(struct FileList *filelist, const struct bContext *C)
+int thumbnails_running(wmWindowManager *wm, FileList *filelist)
{
- return WM_jobs_test(CTX_wm_manager(C), filelist, WM_JOB_TYPE_FILESEL_THUMBNAIL);
+ return WM_jobs_test(wm, filelist, WM_JOB_TYPE_FILESEL_THUMBNAIL);
}
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
index 32a31c51229..d093d427eae 100644
--- a/source/blender/editors/space_file/filelist.h
+++ b/source/blender/editors/space_file/filelist.h
@@ -37,15 +37,16 @@
extern "C" {
#endif
+struct BlendHandle;
struct FileList;
+struct FileSelection;
struct FolderList;
-struct direntry;
-struct BlendHandle;
-struct Scene;
struct Main;
-struct rcti;
struct ReportList;
-struct FileSelection;
+struct Scene;
+struct direntry;
+struct rcti;
+struct wmWindowManager;
typedef enum FileSelType {
FILE_SEL_REMOVE = 0,
@@ -99,9 +100,9 @@ void folderlist_popdir(struct ListBase *folderlist, char *dir);
void folderlist_pushdir(struct ListBase *folderlist, const char *dir);
int folderlist_clear_next(struct SpaceFile *sfile);
-void thumbnails_stop(struct FileList *filelist, const struct bContext *C);
void thumbnails_start(struct FileList *filelist, const struct bContext *C);
-int thumbnails_running(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);
#ifdef __cplusplus
}
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 778a3f4df3e..b8db7dc97b7 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -58,6 +58,7 @@
#include "BLI_linklist.h"
#include "BLI_dynstr.h"
#include "BLI_utildefines.h"
+#include "BLI_fileops_types.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -95,7 +96,7 @@ FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile)
}
/**
- * \note RNA_struct_property_is_set_ex is used here because we wan't
+ * \note RNA_struct_property_is_set_ex is used here because we want
* the previously used settings to be used here rather then overriding them */
short ED_fileselect_set_params(SpaceFile *sfile)
{
@@ -244,9 +245,11 @@ short ED_fileselect_set_params(SpaceFile *sfile)
params->display = FILE_SHORTDISPLAY;
params->filter = 0;
params->filter_glob[0] = '\0';
- params->sort = FILE_SORT_ALPHA;
}
+ /* operator has no setting for this */
+ params->sort = FILE_SORT_ALPHA;
+
/* initialize the list with previous folders */
if (!sfile->folders_prev)
@@ -498,12 +501,12 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
layout->textheight = textheight;
if (params->display == FILE_IMGDISPLAY) {
- layout->prv_w = 96;
- layout->prv_h = 96;
- layout->tile_border_x = 6;
- layout->tile_border_y = 6;
- layout->prv_border_x = 6;
- layout->prv_border_y = 6;
+ layout->prv_w = 4.8f * UI_UNIT_X;
+ layout->prv_h = 4.8f * 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;
+ layout->prv_border_y = 0.3f * UI_UNIT_Y;
layout->tile_w = layout->prv_w + 2 * layout->prv_border_x;
layout->tile_h = layout->prv_h + 2 * layout->prv_border_y + textheight;
layout->width = (int)(BLI_rctf_size_x(&v2d->cur) - 2 * layout->tile_border_x);
@@ -518,10 +521,13 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
layout->flag = FILE_LAYOUT_VER;
}
else {
+ int column_space = 0.6f * UI_UNIT_X;
+ int column_icon_space = 0.2f * UI_UNIT_X;
+
layout->prv_w = 0;
layout->prv_h = 0;
- layout->tile_border_x = 8;
- layout->tile_border_y = 2;
+ layout->tile_border_x = 0.4f * UI_UNIT_X;
+ layout->tile_border_y = 0.1f * UI_UNIT_Y;
layout->prv_border_x = 0;
layout->prv_border_y = 0;
layout->tile_h = textheight * 3 / 2;
@@ -531,22 +537,22 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
column_widths(sfile->files, layout);
if (params->display == FILE_SHORTDISPLAY) {
- maxlen = ICON_DEFAULT_WIDTH_SCALE + 4 +
- (int)layout->column_widths[COLUMN_NAME] + 12 +
- (int)layout->column_widths[COLUMN_SIZE] + 12;
+ maxlen = ICON_DEFAULT_WIDTH_SCALE + column_icon_space +
+ (int)layout->column_widths[COLUMN_NAME] + column_space +
+ (int)layout->column_widths[COLUMN_SIZE] + column_space;
}
else {
- maxlen = ICON_DEFAULT_WIDTH_SCALE + 4 +
- (int)layout->column_widths[COLUMN_NAME] + 12 +
+ maxlen = ICON_DEFAULT_WIDTH_SCALE + column_icon_space +
+ (int)layout->column_widths[COLUMN_NAME] + column_space +
#ifndef WIN32
- (int)layout->column_widths[COLUMN_MODE1] + 12 +
- (int)layout->column_widths[COLUMN_MODE2] + 12 +
- (int)layout->column_widths[COLUMN_MODE3] + 12 +
- (int)layout->column_widths[COLUMN_OWNER] + 12 +
+ (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] + 12 +
- (int)layout->column_widths[COLUMN_TIME] + 12 +
- (int)layout->column_widths[COLUMN_SIZE] + 12;
+ (int)layout->column_widths[COLUMN_DATE] + column_space +
+ (int)layout->column_widths[COLUMN_TIME] + column_space +
+ (int)layout->column_widths[COLUMN_SIZE] + column_space;
}
layout->tile_w = maxlen;
@@ -572,13 +578,14 @@ FileLayout *ED_fileselect_get_layout(struct SpaceFile *sfile, ARegion *ar)
void file_change_dir(bContext *C, int checkdir)
{
+ wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
if (sfile->params) {
- ED_fileselect_clear(C, sfile);
+ ED_fileselect_clear(wm, sfile);
- if (checkdir && BLI_is_dir(sfile->params->dir) == 0) {
+ if (checkdir && !BLI_is_dir(sfile->params->dir)) {
BLI_strncpy(sfile->params->dir, filelist_dir(sfile->files), sizeof(sfile->params->dir));
/* could return but just refresh the current dir */
}
@@ -685,24 +692,24 @@ void autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v))
}
}
-void ED_fileselect_clear(struct bContext *C, struct SpaceFile *sfile)
+void ED_fileselect_clear(struct wmWindowManager *wm, struct SpaceFile *sfile)
{
/* only NULL in rare cases - [#29734] */
if (sfile->files) {
- thumbnails_stop(sfile->files, C);
+ thumbnails_stop(wm, sfile->files);
filelist_freelib(sfile->files);
filelist_free(sfile->files);
}
sfile->params->active_file = -1;
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
+ WM_main_add_notifier(NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
-void ED_fileselect_exit(struct bContext *C, struct SpaceFile *sfile)
+void ED_fileselect_exit(struct wmWindowManager *wm, struct SpaceFile *sfile)
{
if (!sfile) return;
if (sfile->op) {
- WM_event_fileselect_event(C, sfile->op, EVT_FILESELECT_EXTERNAL_CANCEL);
+ WM_event_fileselect_event(wm, sfile->op, EVT_FILESELECT_EXTERNAL_CANCEL);
sfile->op = NULL;
}
@@ -710,7 +717,7 @@ void ED_fileselect_exit(struct bContext *C, struct SpaceFile *sfile)
folderlist_free(sfile->folders_next);
if (sfile->files) {
- ED_fileselect_clear(C, sfile);
+ ED_fileselect_clear(wm, sfile);
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 a5647c06b92..04c68e5ea68 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -281,14 +281,14 @@ void fsmenu_write_file(struct FSMenu *fsmenu, const char *filename)
void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filename)
{
- char line[256];
+ char line[FILE_MAXDIR];
FSMenuCategory category = FS_CATEGORY_BOOKMARKS;
FILE *fp;
fp = BLI_fopen(filename, "r");
if (!fp) return;
- while (fgets(line, 256, fp) != NULL) { /* read a line */
+ while (fgets(line, sizeof(line), fp) != NULL) { /* read a line */
if (strncmp(line, "[Bookmarks]", 11) == 0) {
category = FS_CATEGORY_BOOKMARKS;
}
@@ -318,7 +318,7 @@ void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filename)
void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
{
- char line[256];
+ char line[FILE_MAXDIR];
#ifdef WIN32
/* Add the drive names to the listing */
{
@@ -350,7 +350,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
#else
#ifdef __APPLE__
{
-#if (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4)
+#if (MAC_OS_X_VERSION_MIN_REQUIRED <= 1040)
OSErr err = noErr;
int i;
const char *home;
@@ -376,25 +376,25 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
* TODO : replace hardcoded paths with proper BLI_get_folder calls */
home = getenv("HOME");
if (read_bookmarks && home) {
- BLI_snprintf(line, 256, "%s/", home);
+ BLI_snprintf(line, sizeof(line), "%s/", home);
fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
- BLI_snprintf(line, 256, "%s/Desktop/", home);
+ BLI_snprintf(line, sizeof(line), "%s/Desktop/", home);
if (BLI_exists(line)) {
fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
}
- BLI_snprintf(line, 256, "%s/Documents/", home);
+ BLI_snprintf(line, sizeof(line), "%s/Documents/", home);
if (BLI_exists(line)) {
fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
}
- BLI_snprintf(line, 256, "%s/Pictures/", home);
+ BLI_snprintf(line, sizeof(line), "%s/Pictures/", home);
if (BLI_exists(line)) {
fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
}
- BLI_snprintf(line, 256, "%s/Music/", home);
+ BLI_snprintf(line, sizeof(line), "%s/Music/", home);
if (BLI_exists(line)) {
fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
}
- BLI_snprintf(line, 256, "%s/Movies/", home);
+ BLI_snprintf(line, sizeof(line), "%s/Movies/", home);
if (BLI_exists(line)) {
fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
}
@@ -427,7 +427,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
pathString = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle);
- if (!CFStringGetCString(pathString, line, 256, kCFStringEncodingASCII))
+ if (!CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingASCII))
continue;
fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, line, FS_INSERT_SORTED);
@@ -480,7 +480,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
pathString = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle);
- if (!CFStringGetCString(pathString, line, 256, kCFStringEncodingASCII))
+ if (!CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingASCII))
continue;
fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
@@ -499,9 +499,9 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
const char *home = getenv("HOME");
if (read_bookmarks && home) {
- BLI_snprintf(line, FILE_MAXDIR, "%s/", home);
+ BLI_snprintf(line, sizeof(line), "%s/", home);
fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
- BLI_snprintf(line, FILE_MAXDIR, "%s/Desktop/", home);
+ BLI_snprintf(line, sizeof(line), "%s/Desktop/", home);
if (BLI_exists(line)) {
fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED);
}
@@ -527,7 +527,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
len = strlen(mnt->mnt_dir);
if (len && mnt->mnt_dir[len - 1] != '/') {
- BLI_snprintf(line, FILE_MAXDIR, "%s/", mnt->mnt_dir);
+ BLI_snprintf(line, sizeof(line), "%s/", mnt->mnt_dir);
fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, line, FS_INSERT_SORTED);
}
else {
diff --git a/source/blender/editors/space_file/fsmenu.h b/source/blender/editors/space_file/fsmenu.h
index 1b69eb09fce..eea7e0e3837 100644
--- a/source/blender/editors/space_file/fsmenu.h
+++ b/source/blender/editors/space_file/fsmenu.h
@@ -64,7 +64,7 @@ char *fsmenu_get_entry(struct FSMenu *fsmenu, FSMenuCategory category, int index
/** Inserts a new fsmenu entry with the given \a path.
* Duplicate entries are not added.
- * \param sorted Should entry be inserted in sorted order?
+ * \param flag Options for inserting the entry.
*/
void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const char *path, const FSMenuInsert flag);
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index be037a0d5ba..698c355fad3 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -28,13 +28,9 @@
* \ingroup spfile
*/
-
#include <string.h>
#include <stdio.h>
-
-#include "RNA_access.h"
-
#include "MEM_guardedalloc.h"
#include "BIF_gl.h"
@@ -45,11 +41,17 @@
#include "BLI_math.h"
#include "BLI_rand.h"
#include "BLI_utildefines.h"
+#include "BLI_fileops_types.h"
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_global.h"
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
#include "ED_space_api.h"
#include "ED_screen.h"
#include "ED_fileselect.h"
@@ -57,9 +59,6 @@
#include "IMB_imbuf_types.h"
#include "IMB_thumbs.h"
-#include "WM_api.h"
-#include "WM_types.h"
-
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -147,7 +146,7 @@ static void file_free(SpaceLink *sl)
/* spacetype; init callback, area size changes, screen set, etc */
-static void file_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
+static void file_init(wmWindowManager *UNUSED(wm), ScrArea *sa)
{
SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
//printf("file_init\n");
@@ -158,6 +157,12 @@ static void file_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
if (sfile->layout) sfile->layout->dirty = TRUE;
}
+static void file_exit(wmWindowManager *wm, ScrArea *sa)
+{
+ SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
+
+ ED_fileselect_exit(wm, sfile);
+}
static SpaceLink *file_duplicate(SpaceLink *sl)
{
@@ -187,6 +192,7 @@ static SpaceLink *file_duplicate(SpaceLink *sl)
static void file_refresh(const bContext *C, ScrArea *UNUSED(sa))
{
+ wmWindowManager *wm = CTX_wm_manager(C);
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_params(sfile);
@@ -202,7 +208,7 @@ static void file_refresh(const bContext *C, ScrArea *UNUSED(sa))
filelist_setfilter_types(sfile->files, params->filter_glob);
if (filelist_empty(sfile->files)) {
- thumbnails_stop(sfile->files, C);
+ thumbnails_stop(wm, sfile->files);
filelist_readdir(sfile->files);
if (params->sort != FILE_SORT_NONE) {
filelist_sort(sfile->files, params->sort);
@@ -214,7 +220,7 @@ static void file_refresh(const bContext *C, ScrArea *UNUSED(sa))
}
else {
if (params->sort != FILE_SORT_NONE) {
- thumbnails_stop(sfile->files, C);
+ thumbnails_stop(wm, sfile->files);
filelist_sort(sfile->files, params->sort);
if (params->display == FILE_IMGDISPLAY) {
thumbnails_start(sfile->files, C);
@@ -222,14 +228,14 @@ static void file_refresh(const bContext *C, ScrArea *UNUSED(sa))
}
else {
if (params->display == FILE_IMGDISPLAY) {
- if (!thumbnails_running(sfile->files, C)) {
+ 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(sfile->files, C);
+ thumbnails_stop(wm, sfile->files);
}
filelist_filter(sfile->files);
}
@@ -478,6 +484,7 @@ static void file_channel_area_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
+ ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
ED_region_panels_init(wm, ar);
/* own keymaps */
@@ -533,7 +540,7 @@ static void file_ui_area_draw(const bContext *C, ARegion *ar)
{
float col[3];
/* clear */
- UI_GetThemeColor3fv(TH_PANEL, col);
+ UI_GetThemeColor3fv(TH_BACK, col);
glClearColor(col[0], col[1], col[2], 0.0);
glClear(GL_COLOR_BUFFER_BIT);
@@ -576,6 +583,7 @@ void ED_spacetype_file(void)
st->new = file_new;
st->free = file_free;
st->init = file_init;
+ st->exit = file_exit;
st->duplicate = file_duplicate;
st->refresh = file_refresh;
st->listener = file_listener;
@@ -628,7 +636,7 @@ void ED_spacetype_file(void)
void ED_file_init(void)
{
- char *cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL);
+ const char * const cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL);
fsmenu_read_system(fsmenu_get(), TRUE);
diff --git a/source/blender/editors/space_graph/SConscript b/source/blender/editors/space_graph/SConscript
index 83239a5480a..84ac27a8962 100644
--- a/source/blender/editors/space_graph/SConscript
+++ b/source/blender/editors/space_graph/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index 483348db18e..f1501857b13 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -383,10 +383,7 @@ static void do_graph_region_driver_buttons(bContext *C, void *UNUSED(arg), int e
case B_IPO_DEPCHANGE:
{
/* rebuild depsgraph for the new deps */
- DAG_scene_sort(bmain, scene);
-
- /* force an update of depsgraph */
- DAG_ids_flush_update(bmain, 0);
+ DAG_relations_tag_update(bmain);
}
break;
}
@@ -464,6 +461,7 @@ static void graph_panel_driverVar__singleProp(uiLayout *layout, ID *id, DriverVa
/* Target ID */
row = uiLayoutRow(layout, FALSE);
+ uiLayoutSetRedAlert(row, ((dtar->flag & DTAR_FLAG_INVALID) && !dtar->id));
uiTemplateAnyID(row, &dtar_ptr, "id", "id_type", IFACE_("Prop:"));
/* Target Property */
@@ -473,8 +471,9 @@ static void graph_panel_driverVar__singleProp(uiLayout *layout, ID *id, DriverVa
/* get pointer for resolving the property selected */
RNA_id_pointer_create(dtar->id, &root_ptr);
- col = uiLayoutColumn(layout, TRUE);
/* rna path */
+ col = uiLayoutColumn(layout, TRUE);
+ uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID));
uiTemplatePathBuilder(col, &dtar_ptr, "data_path", &root_ptr, IFACE_("Path"));
}
}
@@ -495,21 +494,23 @@ static void graph_panel_driverVar__rotDiff(uiLayout *layout, ID *id, DriverVar *
/* Bone 1 */
col = uiLayoutColumn(layout, TRUE);
+ uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
uiTemplateAnyID(col, &dtar_ptr, "id", "id_type", IFACE_("Bone 1:"));
-
+
if (dtar->id && ob1->pose) {
PointerRNA tar_ptr;
-
+
RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr);
uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA);
}
col = uiLayoutColumn(layout, TRUE);
+ uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
uiTemplateAnyID(col, &dtar2_ptr, "id", "id_type", IFACE_("Bone 2:"));
if (dtar2->id && ob2->pose) {
PointerRNA tar_ptr;
-
+
RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr);
uiItemPointerR(col, &dtar2_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA);
}
@@ -518,7 +519,7 @@ static void graph_panel_driverVar__rotDiff(uiLayout *layout, ID *id, DriverVar *
/* settings for 'location difference' driver variable type */
static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar *dvar)
{
- DriverTarget *dtar = &dvar->targets[0];
+ DriverTarget *dtar = &dvar->targets[0];
DriverTarget *dtar2 = &dvar->targets[1];
Object *ob1 = (Object *)dtar->id;
Object *ob2 = (Object *)dtar2->id;
@@ -526,32 +527,36 @@ static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar *
uiLayout *col;
/* initialize RNA pointer to the target */
- RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
+ RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr);
/* Bone 1 */
col = uiLayoutColumn(layout, TRUE);
+ uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
uiTemplateAnyID(col, &dtar_ptr, "id", "id_type", IFACE_("Ob/Bone 1:"));
if (dtar->id && ob1->pose) {
PointerRNA tar_ptr;
-
+
RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr);
uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA);
}
-
+
+ uiLayoutSetRedAlert(col, false); /* we can clear it again now - it's only needed when creating the ID/Bone fields */
uiItemR(col, &dtar_ptr, "transform_space", 0, NULL, ICON_NONE);
col = uiLayoutColumn(layout, TRUE);
+ uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
uiTemplateAnyID(col, &dtar2_ptr, "id", "id_type", IFACE_("Ob/Bone 2:"));
if (dtar2->id && ob2->pose) {
PointerRNA tar_ptr;
-
+
RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr);
uiItemPointerR(col, &dtar2_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA);
}
+ uiLayoutSetRedAlert(col, false); /* we can clear it again now - it's only needed when creating the ID/Bone fields */
uiItemR(col, &dtar2_ptr, "transform_space", 0, NULL, ICON_NONE);
}
@@ -568,11 +573,12 @@ static void graph_panel_driverVar__transChan(uiLayout *layout, ID *id, DriverVar
/* properties */
col = uiLayoutColumn(layout, TRUE);
+ uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
uiTemplateAnyID(col, &dtar_ptr, "id", "id_type", IFACE_("Ob/Bone:"));
if (dtar->id && ob->pose) {
PointerRNA tar_ptr;
-
+
RNA_pointer_create(dtar->id, &RNA_Pose, ob->pose, &tar_ptr);
uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA);
}
@@ -626,7 +632,7 @@ static void graph_panel_drivers(const bContext *C, Panel *pa)
if (driver->type == DRIVER_TYPE_PYTHON) {
/* expression */
uiItemR(col, &driver_ptr, "expression", 0, IFACE_("Expr"), ICON_NONE);
-
+
/* errors? */
if (driver->flag & DRIVER_FLAG_INVALID)
uiItemL(col, IFACE_("ERROR: Invalid Python expression"), ICON_ERROR);
@@ -671,19 +677,19 @@ static void graph_panel_drivers(const bContext *C, Panel *pa)
box = uiLayoutBox(col);
/* first row context info for driver */
RNA_pointer_create(ale->id, &RNA_DriverVariable, dvar, &dvar_ptr);
-
+
row = uiLayoutRow(box, FALSE);
block = uiLayoutGetBlock(row);
/* variable name */
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,
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);
-
+
/* variable type */
row = uiLayoutRow(box, FALSE);
uiItemR(row, &dvar_ptr, "type", 0, "", ICON_NONE);
@@ -724,7 +730,7 @@ static void graph_panel_drivers(const bContext *C, Panel *pa)
else {
BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", dvar->curval);
}
-
+
uiItemL(row, valBuf, ICON_NONE);
}
}
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index f665b979559..bdf93b98f22 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -516,7 +516,7 @@ 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;
+ samplefreq = dx / (U.v2d_min_gridsize * U.pixelsize);
if (samplefreq < 0.00001f) samplefreq = 0.00001f;
@@ -712,7 +712,7 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
v1[1] = prevbezt->vec[1][1];
v2[0] = prevbezt->vec[2][0];
v2[1] = prevbezt->vec[2][1];
-
+
v3[0] = bezt->vec[0][0];
v3[1] = bezt->vec[0][1];
v4[0] = bezt->vec[1][0];
@@ -772,6 +772,111 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
glEnd();
}
+/* Debugging -------------------------------- */
+
+/* Draw indicators which show the value calculated from the driver,
+ * and how this is mapped to the value that comes out of it. This
+ * is handy for helping users better understand how to interpret
+ * the graphs, and also facilitates debugging.
+ */
+static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
+{
+ ChannelDriver *driver = fcu->driver;
+ View2D *v2d = &ac->ar->v2d;
+ float unitfac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, false);
+
+ /* for now, only show when debugging driver... */
+ //if ((driver->flag & DRIVER_FLAG_SHOWDEBUG) == 0)
+ // return;
+
+ /* No curve to modify/visualise the result?
+ * => We still want to show the 1-1 default...
+ */
+ if ((fcu->totvert == 0) && (fcu->modifiers.first == NULL)) {
+ float t;
+
+ /* draw with thin dotted lines in style of what curve would have been */
+ glColor3fv(fcu->color);
+
+ setlinestyle(20);
+ glLineWidth(2.0f);
+
+ /* draw 1-1 line, stretching just past the screen limits
+ * 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);
+
+ t = v2d->cur.xmax;
+ glVertex2f(t, t * unitfac);
+ glEnd();
+
+ /* cleanup line drawing */
+ setlinestyle(0);
+ glLineWidth(1.0f);
+ }
+
+ /* draw driver only if actually functional */
+ if ((driver->flag & DRIVER_FLAG_INVALID) == 0) {
+ /* grab "coordinates" for driver outputs */
+ float x = driver->curval;
+ float y = fcu->curval * unitfac;
+
+ /* only draw indicators if the point is in range*/
+ if (x >= v2d->cur.xmin) {
+ float co[2];
+
+ /* draw dotted lines leading towards this point from both axes ....... */
+ glColor3f(0.9f, 0.9f, 0.9f);
+ setlinestyle(5);
+
+ glBegin(GL_LINES);
+ /* x-axis lookup */
+ co[0] = x;
+
+ if (y >= v2d->cur.ymin) {
+ co[1] = v2d->cur.ymin - 1.0f;
+ glVertex2fv(co);
+
+ co[1] = y;
+ glVertex2fv(co);
+ }
+
+ /* y-axis lookup */
+ co[1] = y;
+
+ co[0] = v2d->cur.xmin - 1.0f;
+ glVertex2fv(co);
+
+ co[0] = x;
+ glVertex2fv(co);
+ glEnd();
+
+ setlinestyle(0);
+
+ /* x marks the spot .................................................... */
+ /* -> outer frame */
+ glColor3f(0.9f, 0.9f, 0.9f);
+ glPointSize(7.0);
+
+ glBegin(GL_POINTS);
+ glVertex2f(x, y);
+ glEnd();
+
+ /* inner frame */
+ glColor3f(0.9f, 0.0f, 0.0f);
+ glPointSize(3.0);
+
+ glBegin(GL_POINTS);
+ glVertex2f(x, y);
+ glEnd();
+
+ glPointSize(1.0f);
+ }
+ }
+}
+
/* Public Curve-Drawing API ---------------- */
/* Draw the 'ghost' F-Curves (i.e. snapshots of the curve)
@@ -934,6 +1039,11 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
}
}
+ /* 3) draw driver debugging stuff */
+ if ((ac->datatype == ANIMCONT_DRIVERS) && (fcu->flag & FCURVE_ACTIVE)) {
+ graph_draw_driver_debug(ac, ale->id, fcu);
+ }
+
/* undo mapping of keyframes for drawing if scaled F-Curve */
if (adt)
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 21b0ed99f0b..a51fef6c692 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -217,7 +217,6 @@ void GRAPH_OT_previewrange_set(wmOperatorType *ot)
static int graphkeys_viewall(bContext *C, const short do_sel_only, const short include_handles)
{
bAnimContext ac;
- float extra;
rctf cur_new;
/* get editor data */
@@ -230,13 +229,7 @@ static int graphkeys_viewall(bContext *C, const short do_sel_only, const short i
&cur_new.ymin, &cur_new.ymax,
do_sel_only, include_handles);
- extra = 0.1f * BLI_rctf_size_x(&cur_new);
- cur_new.xmin -= extra;
- cur_new.xmax += extra;
-
- extra = 0.1f * BLI_rctf_size_y(&cur_new);
- cur_new.ymin -= extra;
- cur_new.ymax += extra;
+ BLI_rctf_scale(&cur_new, 1.1f);
UI_view2d_smooth_view(C, ac.ar, &cur_new);
@@ -616,7 +609,7 @@ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int graphkeys_click_insert_invoke(bContext *C, wmOperator *op, wmEvent *evt)
+static int graphkeys_click_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
bAnimContext ac;
ARegion *ar;
@@ -632,8 +625,8 @@ static int graphkeys_click_insert_invoke(bContext *C, wmOperator *op, wmEvent *e
ar = ac.ar;
v2d = &ar->v2d;
- mval[0] = (evt->x - ar->winrct.xmin);
- mval[1] = (evt->y - ar->winrct.ymin);
+ mval[0] = (event->x - ar->winrct.xmin);
+ mval[1] = (event->y - ar->winrct.ymin);
UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
@@ -842,7 +835,7 @@ static int graphkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-static int graphkeys_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int graphkeys_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
graphkeys_duplicate_exec(C, op);
@@ -1197,7 +1190,7 @@ static int graphkeys_sound_bake_exec(bContext *UNUSED(C), wmOperator *op)
#endif //WITH_AUDASPACE
-static int graphkeys_sound_bake_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int graphkeys_sound_bake_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
bAnimContext ac;
@@ -2139,7 +2132,7 @@ void GRAPH_OT_smooth(wmOperatorType *ot)
/* ******************** Add F-Modifier Operator *********************** */
/* present a special customised popup menu for this, with some filtering */
-static int graph_fmodifier_add_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int graph_fmodifier_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
wmOperatorType *ot = WM_operatortype_find("GRAPH_OT_fmodifier_add", 1);
uiPopupMenu *pup;
@@ -2203,8 +2196,9 @@ static int graph_fmodifier_add_exec(bContext *C, wmOperator *op)
/* add F-Modifier of specified type to active F-Curve, and make it the active one */
fcm = add_fmodifier(&fcu->modifiers, type);
- if (fcm)
+ if (fcm) {
set_active_fmodifier(&fcu->modifiers, fcm);
+ }
else {
BKE_report(op->reports, RPT_ERROR, "Modifier could not be added (see console for details)");
break;
diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h
index b2dbf764c1d..8dc5e9a441d 100644
--- a/source/blender/editors/space_graph/graph_intern.h
+++ b/source/blender/editors/space_graph/graph_intern.h
@@ -69,19 +69,19 @@ void GRAPH_OT_select_leftright(struct wmOperatorType *ot);
void GRAPH_OT_clickselect(struct wmOperatorType *ot);
/* defines for left-right select tool */
-enum {
+enum eGraphKeys_LeftRightSelect_Mode {
GRAPHKEYS_LRSEL_TEST = 0,
GRAPHKEYS_LRSEL_LEFT,
GRAPHKEYS_LRSEL_RIGHT
-} eGraphKeys_LeftRightSelect_Mode;
+};
/* defines for column-select mode */
-enum {
+enum eGraphKeys_ColumnSelect_Mode {
GRAPHKEYS_COLUMNSEL_KEYS = 0,
GRAPHKEYS_COLUMNSEL_CFRA,
GRAPHKEYS_COLUMNSEL_MARKERS_COLUMN,
GRAPHKEYS_COLUMNSEL_MARKERS_BETWEEN,
-} eGraphKeys_ColumnSelect_Mode;
+};
/* ***************************************** */
/* graph_edit.c */
@@ -119,25 +119,25 @@ void GRAPH_OT_mirror(struct wmOperatorType *ot);
/* defines for snap keyframes
* NOTE: keep in sync with eEditKeyframes_Snap (in ED_keyframes_edit.h)
*/
-enum {
+enum eGraphKeys_Snap_Mode {
GRAPHKEYS_SNAP_CFRA = 1,
GRAPHKEYS_SNAP_NEAREST_FRAME,
GRAPHKEYS_SNAP_NEAREST_SECOND,
GRAPHKEYS_SNAP_NEAREST_MARKER,
GRAPHKEYS_SNAP_HORIZONTAL,
GRAPHKEYS_SNAP_VALUE,
-} eGraphKeys_Snap_Mode;
+};
/* defines for mirror keyframes
* NOTE: keep in sync with eEditKeyframes_Mirror (in ED_keyframes_edit.h)
*/
-enum {
+enum eGraphKeys_Mirror_Mode {
GRAPHKEYS_MIRROR_CFRA = 1,
GRAPHKEYS_MIRROR_YAXIS,
GRAPHKEYS_MIRROR_XAXIS,
GRAPHKEYS_MIRROR_MARKER,
GRAPHKEYS_MIRROR_VALUE,
-} eGraphKeys_Mirror_Mode;
+};
/* ----------- */
diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c
index 54b417e740a..acb9e42d91b 100644
--- a/source/blender/editors/space_graph/graph_ops.c
+++ b/source/blender/editors/space_graph/graph_ops.c
@@ -109,7 +109,7 @@ static int graphview_cursor_exec(bContext *C, wmOperator *op)
/* ... */
/* set the operator properties from the initial event */
-static void graphview_cursor_setprops(bContext *C, wmOperator *op, wmEvent *event)
+static void graphview_cursor_setprops(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
float viewx, viewy;
@@ -128,7 +128,7 @@ static void graphview_cursor_setprops(bContext *C, wmOperator *op, wmEvent *even
}
/* Modal Operator init */
-static int graphview_cursor_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int graphview_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
/* 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
@@ -145,7 +145,7 @@ static int graphview_cursor_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
/* Modal event handling of cursor changing */
-static int graphview_cursor_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int graphview_cursor_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
/* execute the events */
switch (event->type) {
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 978b3224850..cbec3072c44 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -815,7 +815,7 @@ static int graphkeys_select_leftright_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int graphkeys_select_leftright_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int graphkeys_select_leftright_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
bAnimContext ac;
short leftright = RNA_enum_get(op->ptr, "mode");
@@ -1297,7 +1297,7 @@ static void graphkeys_mselect_column(bAnimContext *ac, const int mval[2], short
/* ------------------- */
/* handle clicking */
-static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
bAnimContext ac;
short selectmode;
@@ -1342,10 +1342,13 @@ void GRAPH_OT_clickselect(wmOperatorType *ot)
ot->idname = "GRAPH_OT_clickselect";
ot->description = "Select keyframes by clicking on them";
- /* api callbacks */
+ /* callbacks */
ot->invoke = graphkeys_clickselect_invoke;
ot->poll = graphop_visible_keyframes_poll;
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
/* properties */
prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index fa7c6bd472a..734c0e6c479 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -309,6 +309,12 @@ static void graph_channel_area_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
+ /* make sure we keep the hide flags */
+ ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
+ ar->v2d.scroll &= ~(V2D_SCROLL_LEFT | V2D_SCROLL_TOP); /* prevent any noise of past */
+ ar->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
+ ar->v2d.scroll |= V2D_SCROLL_VERTICAL_HIDE;
+
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
/* own keymap */
diff --git a/source/blender/editors/space_image/SConscript b/source/blender/editors/space_image/SConscript
index 737da4aac74..68f747270a3 100644
--- a/source/blender/editors/space_image/SConscript
+++ b/source/blender/editors/space_image/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
@@ -18,7 +44,7 @@ if env['WITH_BF_OPENJPEG']:
if env['WITH_BF_TIFF']:
defs.append('WITH_TIFF')
if env['WITH_BF_CINEON']:
- defs.append('WITH_CINEON')
+ defs.append('WITH_CINEON')
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 0a3db59096a..70001b59528 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -73,51 +73,55 @@
/* proto */
-static void image_info(Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf, char *str)
+static void image_info(Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf, char *str, size_t len)
{
- int ofs = 0;
+ size_t ofs = 0;
str[0] = 0;
-
- if (ima == NULL) return;
+ if (ima == NULL)
+ return;
if (ibuf == NULL) {
- ofs += sprintf(str, "%s", IFACE_("Can't Load Image"));
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Can't Load Image"), len - ofs);
}
else {
if (ima->source == IMA_SRC_MOVIE) {
- ofs += sprintf(str, "%s", IFACE_("Movie"));
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Movie"), len - ofs);
if (ima->anim)
- ofs += sprintf(str + ofs, IFACE_("%d frs"), IMB_anim_get_duration(ima->anim, IMB_TC_RECORD_RUN));
+ ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(" %d frs"),
+ IMB_anim_get_duration(ima->anim, IMB_TC_RECORD_RUN));
+ }
+ else {
+ ofs += BLI_strncpy_rlen(str, IFACE_("Image"), len - ofs);
}
- else
- ofs += sprintf(str, "%s", IFACE_("Image"));
- ofs += sprintf(str + ofs, ": %s %d x %d,", IFACE_("size"), ibuf->x, ibuf->y);
+ ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(": size %d x %d,"), ibuf->x, ibuf->y);
if (ibuf->rect_float) {
if (ibuf->channels != 4) {
- ofs += sprintf(str + ofs, "%d %s", ibuf->channels, IFACE_("float channel(s)"));
+ ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_("%d float channel(s)"), ibuf->channels);
}
else if (ibuf->planes == R_IMF_PLANES_RGBA)
- ofs += sprintf(str + ofs, "%s", IFACE_(" RGBA float"));
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA float"), len - ofs);
else
- ofs += sprintf(str + ofs, "%s", IFACE_(" RGB float"));
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB float"), len - ofs);
}
else {
if (ibuf->planes == R_IMF_PLANES_RGBA)
- ofs += sprintf(str + ofs, "%s", IFACE_(" RGBA byte"));
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA byte"), len - ofs);
else
- ofs += sprintf(str + ofs, "%s", IFACE_(" RGB byte"));
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB byte"), len - ofs);
}
if (ibuf->zbuf || ibuf->zbuf_float)
- ofs += sprintf(str + ofs, "%s", IFACE_(" + Z"));
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" + Z"), len - ofs);
if (ima->source == IMA_SRC_SEQUENCE) {
- char *file = BLI_last_slash(ibuf->name);
- if (file == NULL) file = ibuf->name;
- else file++;
- ofs += sprintf(str + ofs, ", %s", file);
+ const char *file = BLI_last_slash(ibuf->name);
+ if (file == NULL)
+ file = ibuf->name;
+ else
+ file++;
+ ofs += BLI_snprintf(str + ofs, len - ofs, ", %s", file);
}
}
@@ -125,10 +129,8 @@ static void image_info(Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf,
if (ima->source == IMA_SRC_SEQUENCE) {
/* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */
const int framenr = BKE_image_user_frame_get(iuser, CFRA, 0, NULL);
- ofs += sprintf(str + ofs, IFACE_(", Frame: %d"), framenr);
+ ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(", Frame: %d"), framenr);
}
-
- (void)ofs;
}
/* gets active viewer user */
@@ -219,7 +221,7 @@ static void preview_cb(ScrArea *sa, struct uiBlock *block)
BLI_rcti_translate(disprect, -curarea->winrct.xmin, -curarea->winrct.ymin);
calc_image_view(sima, 'p');
-// printf("winrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
+// printf("winrct %d %d %d %d\n", disprect->xmin, disprect->ymin, disprect->xmax, disprect->ymax);
/* map to image space coordinates */
mval[0] = disprect->xmin; mval[1] = disprect->ymin;
areamouseco_to_ipoco(v2d, mval, &dispf.xmin, &dispf.ymin);
@@ -236,7 +238,7 @@ static void preview_cb(ScrArea *sa, struct uiBlock *block)
CLAMP(disprect->xmax, 0, winx);
CLAMP(disprect->ymin, 0, winy);
CLAMP(disprect->ymax, 0, winy);
-// printf("drawrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
+// printf("drawrct %d %d %d %d\n", disprect->xmin, disprect->ymin, disprect->xmax, disprect->ymax);
}
@@ -498,17 +500,17 @@ static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, RenderResult *rr,
}
/* decrease, increase arrows */
- but = uiDefIconBut(block, BUT, 0, ICON_TRIA_LEFT, 0, 0, 17, 20, NULL, 0, 0, 0, 0, TIP_("Previous Layer"));
+ 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, 18, 20, NULL, 0, 0, 0, 0, TIP_("Next Layer"));
+ 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);
uiblock_layer_pass_buttons(row, rr, iuser, 230 * dpi_fac, render_slot);
/* decrease, increase arrows */
- but = uiDefIconBut(block, BUT, 0, ICON_TRIA_LEFT, 0, 0, 17, 20, NULL, 0, 0, 0, 0, TIP_("Previous Pass"));
+ 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, 18, 20, NULL, 0, 0, 0, 0, TIP_("Next Pass"));
+ 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);
uiBlockEndAlign(block);
@@ -539,16 +541,17 @@ static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *userptr, int compact)
{
+#define MAX_INFO_LEN 128
+
PropertyRNA *prop;
PointerRNA imaptr;
RNAUpdateCb *cb;
Image *ima;
ImageUser *iuser;
- ImBuf *ibuf;
Scene *scene = CTX_data_scene(C);
uiLayout *row, *split, *col;
uiBlock *block;
- char str[128];
+ char str[MAX_INFO_LEN];
void *lock;
@@ -591,8 +594,8 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);
if (ima->source == IMA_SRC_VIEWER) {
- ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
- image_info(scene, iuser, ima, ibuf, str);
+ 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, ima->id.name + 2, ICON_NONE);
@@ -661,8 +664,8 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
}
else if (ima->source != IMA_SRC_GENERATED) {
if (compact == 0) {
- ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
- image_info(scene, iuser, ima, ibuf, str);
+ 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);
}
@@ -674,6 +677,24 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
if (ima->source != IMA_SRC_GENERATED) {
if (compact == 0) { /* background image view doesnt need these */
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
+ int has_alpha = TRUE;
+
+ if (ibuf) {
+ int imtype = BKE_ftype_to_imtype(ibuf->ftype);
+ char valid_channels = BKE_imtype_valid_channels(imtype);
+
+ has_alpha = valid_channels & IMA_CHAN_FLAG_ALPHA;
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+
+ if (has_alpha) {
+ col = uiLayoutColumn(layout, FALSE);
+ uiItemR(col, &imaptr, "use_alpha", 0, NULL, ICON_NONE);
+ uiItemR(col, &imaptr, "alpha_mode", 0, "Alpha", ICON_NONE);
+ }
+
uiItemS(layout);
split = uiLayoutSplit(layout, 0.0f, FALSE);
@@ -694,10 +715,6 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
row = uiLayoutRow(col, FALSE);
uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_fields"));
uiItemR(row, &imaptr, "field_order", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
-
- row = uiLayoutRow(layout, FALSE);
- uiItemR(row, &imaptr, "use_premultiply", 0, NULL, ICON_NONE);
- uiItemR(row, &imaptr, "use_color_unpremultiply", 0, NULL, ICON_NONE);
}
}
@@ -736,6 +753,8 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
}
MEM_freeN(cb);
+
+#undef MAX_INFO_LEN
}
void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_management)
@@ -770,6 +789,8 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man
R_IMF_CHAN_DEPTH_32)) == 0)
{
row = uiLayoutRow(col, FALSE);
+
+ uiItemL(row, IFACE_("Color Depth:"), ICON_NONE);
uiItemR(row, imfptr, "color_depth", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
}
@@ -796,6 +817,8 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man
}
if (imf->imtype == R_IMF_IMTYPE_JP2) {
+ uiItemR(col, imfptr, "jpeg2k_codec", 0, NULL, ICON_NONE);
+
row = uiLayoutRow(col, FALSE);
uiItemR(row, imfptr, "use_jpeg2k_cinema_preset", 0, NULL, ICON_NONE);
uiItemR(row, imfptr, "use_jpeg2k_cinema_48", 0, NULL, ICON_NONE);
@@ -858,6 +881,7 @@ void image_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype image panel gpencil");
strcpy(pt->idname, "IMAGE_PT_gpencil");
strcpy(pt->label, "Grease Pencil");
+ pt->draw_header = gpencil_panel_standard_header;
pt->draw = gpencil_panel_standard;
BLI_addtail(&art->paneltypes, pt);
}
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index d565e6f9e9a..f27a99ac44b 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -75,13 +75,15 @@
#include "WM_types.h"
#include "RE_pipeline.h"
+#include "RE_engine.h"
#include "image_intern.h"
-static void draw_render_info(Scene *scene, Image *ima, ARegion *ar)
+static void draw_render_info(Scene *scene, Image *ima, ARegion *ar, float zoomx, float zoomy)
{
RenderResult *rr;
-
+ Render *re = RE_GetRender(scene->id.name);
+
rr = BKE_image_acquire_renderresult(scene, ima);
if (rr && rr->text) {
@@ -89,11 +91,78 @@ static void draw_render_info(Scene *scene, Image *ima, ARegion *ar)
}
BKE_image_release_renderresult(scene, ima);
+
+ if (re) {
+ int total_tiles;
+ rcti *tiles;
+
+ RE_engine_get_current_tiles(re, &total_tiles, &tiles);
+
+ if (total_tiles) {
+ int i, x, y;
+ rcti *tile;
+
+ /* find window pixel coordinates of origin */
+ UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y);
+
+ glPushMatrix();
+ 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),
+ 0.0f);
+ }
+
+ UI_ThemeColor(TH_FACE_SELECT);
+
+ for (i = 0, tile = tiles; i < total_tiles; i++, tile++) {
+ float delta_x = 4.0f * UI_DPI_FAC / zoomx;
+ float delta_y = 4.0f * UI_DPI_FAC / zoomy;
+
+ delta_x = min_ff(delta_x, tile->xmax - tile->xmin);
+ delta_y = min_ff(delta_y, tile->ymax - tile->ymin);
+
+ /* left bottom corner */
+ glBegin(GL_LINE_STRIP);
+ glVertex2f(tile->xmin, tile->ymin + delta_y);
+ glVertex2f(tile->xmin, tile->ymin);
+ glVertex2f(tile->xmin + delta_x, tile->ymin);
+ glEnd();
+
+ /* left top corner */
+ glBegin(GL_LINE_STRIP);
+ glVertex2f(tile->xmin, tile->ymax - delta_y);
+ glVertex2f(tile->xmin, tile->ymax);
+ glVertex2f(tile->xmin + delta_x, tile->ymax);
+ glEnd();
+
+ /* right bottom corner */
+ glBegin(GL_LINE_STRIP);
+ glVertex2f(tile->xmax - delta_x, tile->ymin);
+ glVertex2f(tile->xmax, tile->ymin);
+ glVertex2f(tile->xmax, tile->ymin + delta_y);
+ glEnd();
+
+ /* right top corner */
+ glBegin(GL_LINE_STRIP);
+ glVertex2f(tile->xmax - delta_x, tile->ymax);
+ glVertex2f(tile->xmax, tile->ymax);
+ glVertex2f(tile->xmax, tile->ymax - delta_y);
+ glEnd();
+ }
+
+ MEM_freeN(tiles);
+
+ glPopMatrix();
+ }
+ }
}
/* used by node view too */
void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_default_view, int channels, int x, int y,
- const unsigned char cp[4], const float fp[4], int *zp, float *zpf)
+ const unsigned char cp[4], const float fp[4], const float linearcol[4], int *zp, float *zpf)
{
char str[256];
float dx = 6;
@@ -116,29 +185,28 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
/* noisy, high contrast make impossible to read if lower alpha is used. */
glColor4ub(0, 0, 0, 190);
- glRecti(0.0, 0.0, BLI_rcti_size_x(&ar->winrct) + 1, 20);
+ glRecti(0.0, 0.0, BLI_rcti_size_x(&ar->winrct) + 1, UI_UNIT_Y);
glDisable(GL_BLEND);
- BLF_size(blf_mono_font, 11, 72);
+ BLF_size(blf_mono_font, 11 * U.pixelsize, U.dpi);
glColor3ub(255, 255, 255);
BLI_snprintf(str, sizeof(str), "X:%-4d Y:%-4d |", x, y);
- // UI_DrawString(6, 6, str); // works ok but fixed width is nicer.
- BLF_position(blf_mono_font, dx, 6, 0);
+ BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_Y, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str);
if (zp) {
glColor3ub(255, 255, 255);
BLI_snprintf(str, sizeof(str), " Z:%-.4f |", 0.5f + 0.5f * (((float)*zp) / (float)0x7fffffff));
- BLF_position(blf_mono_font, dx, 6, 0);
+ BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str);
}
if (zpf) {
glColor3ub(255, 255, 255);
BLI_snprintf(str, sizeof(str), " Z:%-.3f |", *zpf);
- BLF_position(blf_mono_font, dx, 6, 0);
+ BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str);
}
@@ -146,34 +214,34 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
if (channels >= 3) {
glColor3ubv(red);
if (fp)
- BLI_snprintf(str, sizeof(str), " R:%-.4f", fp[0]);
+ BLI_snprintf(str, sizeof(str), " R:%-.5f", fp[0]);
else if (cp)
BLI_snprintf(str, sizeof(str), " R:%-3d", cp[0]);
else
BLI_snprintf(str, sizeof(str), " R:-");
- BLF_position(blf_mono_font, dx, 6, 0);
+ BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str);
glColor3ubv(green);
if (fp)
- BLI_snprintf(str, sizeof(str), " G:%-.4f", fp[1]);
+ BLI_snprintf(str, sizeof(str), " G:%-.5f", fp[1]);
else if (cp)
BLI_snprintf(str, sizeof(str), " G:%-3d", cp[1]);
else
BLI_snprintf(str, sizeof(str), " G:-");
- BLF_position(blf_mono_font, dx, 6, 0);
+ BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str);
glColor3ubv(blue);
if (fp)
- BLI_snprintf(str, sizeof(str), " B:%-.4f", fp[2]);
+ BLI_snprintf(str, sizeof(str), " B:%-.5f", fp[2]);
else if (cp)
BLI_snprintf(str, sizeof(str), " B:%-3d", cp[2]);
else
BLI_snprintf(str, sizeof(str), " B:-");
- BLF_position(blf_mono_font, dx, 6, 0);
+ BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str);
@@ -185,21 +253,29 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
BLI_snprintf(str, sizeof(str), " A:%-3d", cp[3]);
else
BLI_snprintf(str, sizeof(str), "- ");
- BLF_position(blf_mono_font, dx, 6, 0);
+ BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str);
}
- if (color_manage && channels == 4) {
- float pixel[4];
+ if (color_manage) {
+ float rgba[4];
+
+ copy_v3_v3(rgba, linearcol);
+ if (channels == 3)
+ rgba[3] = 1.0f;
+ else
+ rgba[3] = linearcol[3];
+
+ (void)color_manage;
if (use_default_view)
- IMB_colormanagement_pixel_to_display_space_v4(pixel, fp, NULL, &scene->display_settings);
+ IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, NULL, &scene->display_settings);
else
- IMB_colormanagement_pixel_to_display_space_v4(pixel, fp, &scene->view_settings, &scene->display_settings);
+ IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, &scene->view_settings, &scene->display_settings);
- BLI_snprintf(str, sizeof(str), " | CM R:%-.4f G:%-.4f B:%-.4f", pixel[0], pixel[1], pixel[2]);
- BLF_position(blf_mono_font, dx, 6, 0);
+ BLI_snprintf(str, sizeof(str), " | CM R:%-.4f G:%-.4f B:%-.4f", rgba[0], rgba[1], rgba[2]);
+ BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str);
}
@@ -219,26 +295,11 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
col[3] = 1.0f;
}
else if (channels == 3) {
- if (fp) {
- copy_v3_v3(col, fp);
- }
- else if (cp) {
- rgb_uchar_to_float(col, cp);
- }
- else {
- zero_v3(col);
- }
+ copy_v3_v3(col, linearcol);
col[3] = 1.0f;
}
else if (channels == 4) {
- if (fp)
- copy_v4_v4(col, fp);
- else if (cp) {
- rgba_uchar_to_float(col, cp);
- }
- else {
- zero_v4(col);
- }
+ copy_v4_v4(col, linearcol);
}
else {
BLI_assert(0);
@@ -257,24 +318,24 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
glDisable(GL_BLEND);
glColor3fv(finalcol);
- dx += 5;
+ dx += 0.25f * UI_UNIT_X;
glBegin(GL_QUADS);
- glVertex2f(dx, 3);
- glVertex2f(dx, 17);
- glVertex2f(dx + 30, 17);
- glVertex2f(dx + 30, 3);
+ glVertex2f(dx, 0.15f * UI_UNIT_Y);
+ glVertex2f(dx, 0.85f * UI_UNIT_Y);
+ glVertex2f(dx + 1.5f * UI_UNIT_X, 0.85 * UI_UNIT_Y);
+ glVertex2f(dx + 1.5f * UI_UNIT_X, 0.15f * UI_UNIT_Y);
glEnd();
/* draw outline */
glColor3ub(128, 128, 128);
glBegin(GL_LINE_LOOP);
- glVertex2f(dx, 3);
- glVertex2f(dx, 17);
- glVertex2f(dx + 30, 17);
- glVertex2f(dx + 30, 3);
+ glVertex2f(dx, 0.15f * UI_UNIT_Y);
+ glVertex2f(dx, 0.85f * UI_UNIT_Y);
+ glVertex2f(dx + 1.5f * UI_UNIT_X, 0.85f * UI_UNIT_Y);
+ glVertex2f(dx + 1.5f * UI_UNIT_X, 0.15f * UI_UNIT_Y);
glEnd();
- dx += 35;
+ dx += 1.75f * UI_UNIT_X;
glColor3ub(255, 255, 255);
if (channels == 1) {
@@ -288,12 +349,12 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
}
BLI_snprintf(str, sizeof(str), "V:%-.4f", val);
- BLF_position(blf_mono_font, dx, 6, 0);
+ BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str);
BLI_snprintf(str, sizeof(str), " L:%-.4f", lum);
- BLF_position(blf_mono_font, dx, 6, 0);
+ BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str);
}
@@ -308,22 +369,22 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def
}
BLI_snprintf(str, sizeof(str), "H:%-.4f", hue);
- BLF_position(blf_mono_font, dx, 6, 0);
+ BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str);
BLI_snprintf(str, sizeof(str), " S:%-.4f", sat);
- BLF_position(blf_mono_font, dx, 6, 0);
+ BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str);
BLI_snprintf(str, sizeof(str), " V:%-.4f", val);
- BLF_position(blf_mono_font, dx, 6, 0);
+ BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str);
BLI_snprintf(str, sizeof(str), " L:%-.4f", lum);
- BLF_position(blf_mono_font, dx, 6, 0);
+ BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str);
}
@@ -356,11 +417,11 @@ static void sima_draw_alpha_pixelsf(float x1, float y1, int rectx, int recty, fl
MEM_freeN(trectf);
/* ogl trick below is slower... (on ATI 9600) */
// glColorMask(1, 0, 0, 0);
-// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf+3);
+// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf + 3);
// glColorMask(0, 1, 0, 0);
-// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf+2);
+// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf + 2);
// glColorMask(0, 0, 1, 0);
-// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf+1);
+// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf + 1);
// glColorMask(1, 1, 1, 1);
}
@@ -423,6 +484,8 @@ static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar,
/* set zoom */
glPixelZoom(zoomx, zoomy);
+ glaDefine2DArea(&ar->winrct);
+
/* find window pixel coordinates of origin */
UI_view2d_to_region_no_clip(&ar->v2d, fx, fy, &x, &y);
@@ -446,20 +509,16 @@ static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar,
void *cache_handle;
if (sima->flag & SI_USE_ALPHA) {
- fdrawcheckerboard(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy);
-
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ fdrawcheckerboard(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy);
}
display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
if (display_buffer)
- glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
-#if 0
- else
- glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_FLOAT, ibuf->rect_float);
-#endif
+ glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer);
IMB_display_buffer_release(cache_handle);
@@ -518,8 +577,8 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene,
sima->curtile = ima->xrep * ima->yrep - 1;
/* retrieve part of image buffer */
- dx = ibuf->x / ima->xrep;
- dy = ibuf->y / ima->yrep;
+ dx = max_ii(ibuf->x / ima->xrep, 1);
+ dy = max_ii(ibuf->y / ima->yrep, 1);
sx = (sima->curtile % ima->xrep) * dx;
sy = (sima->curtile / ima->xrep) * dy;
rect = get_part_from_buffer((unsigned int *)display_buffer, ibuf->x, sx, sy, sx + dx, sy + dy);
@@ -762,7 +821,7 @@ void draw_image_main(const bContext *C, ARegion *ar)
show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT);
if (show_viewer) {
- /* use locked draw for drawing viewer image buffer since the conpositor
+ /* use locked draw for drawing viewer image buffer since the compositor
* is running in separated thread and compositor could free this buffers.
* other images are not modifying in such a way so they does not require
* lock (sergey)
@@ -786,7 +845,6 @@ void draw_image_main(const bContext *C, ARegion *ar)
if (sima->mode == SI_MODE_PAINT)
draw_image_paint_helpers(C, ar, scene, zoomx, zoomy);
-
/* XXX integrate this code */
#if 0
if (ibuf) {
@@ -812,5 +870,5 @@ void draw_image_main(const bContext *C, ARegion *ar)
/* render info */
if (ima && show_render)
- draw_render_info(scene, ima, ar);
+ draw_render_info(scene, ima, ar, zoomx, zoomy);
}
diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c
index c4e2230e7a7..34207e16f1c 100644
--- a/source/blender/editors/space_image/image_edit.c
+++ b/source/blender/editors/space_image/image_edit.c
@@ -40,6 +40,7 @@
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_tessmesh.h"
+#include "BKE_library.h"
#include "IMB_imbuf_types.h"
@@ -78,8 +79,7 @@ void ED_space_image_set(SpaceImage *sima, Scene *scene, Object *obedit, Image *i
if (sima->image)
BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE);
- if (sima->image && ID_REAL_USERS(sima->image) <= 0)
- sima->image->id.us = max_ii(sima->image->id.us, 0) + 1;
+ id_us_ensure_real((ID *)sima->image);
if (obedit)
WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
@@ -97,8 +97,7 @@ void ED_space_image_set_mask(bContext *C, SpaceImage *sima, Mask *mask)
sima->mask_info.mask = mask;
/* weak, but same as image/space */
- if (sima->mask_info.mask && ID_REAL_USERS(sima->mask_info.mask) <= 0)
- sima->mask_info.mask->id.us = max_ii(sima->mask_info.mask->id.us, 0) + 1;
+ id_us_ensure_real((ID *)sima->mask_info.mask);
if (C) {
WM_event_add_notifier(C, NC_MASK | NA_SELECTED, mask);
@@ -194,9 +193,7 @@ void ED_space_image_get_size_fl(SpaceImage *sima, float size[2])
void ED_space_image_get_aspect(SpaceImage *sima, float *aspx, float *aspy)
{
Image *ima = sima->image;
- if ((ima == NULL) || (ima->type == IMA_TYPE_R_RESULT) || (ima->type == IMA_TYPE_COMPOSITE) ||
- (ima->aspx == 0.0f || ima->aspy == 0.0f))
- {
+ if ((ima == NULL) || (ima->aspx == 0.0f || ima->aspy == 0.0f)) {
*aspx = *aspy = 1.0;
}
else {
diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h
index f86e59c41a8..5184b1e1a73 100644
--- a/source/blender/editors/space_image/image_intern.h
+++ b/source/blender/editors/space_image/image_intern.h
@@ -87,8 +87,6 @@ void IMAGE_OT_sample(struct wmOperatorType *ot);
void IMAGE_OT_sample_line(struct wmOperatorType *ot);
void IMAGE_OT_curves_point_set(struct wmOperatorType *ot);
-void IMAGE_OT_record_composite(struct wmOperatorType *ot);
-
/* image_panels.c */
struct ImageUser *ntree_get_active_iuser(struct bNodeTree *ntree);
void image_buttons_register(struct ARegionType *art);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 0d0fdc6be1c..7e0767bfcfb 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -162,7 +162,7 @@ static int space_image_file_exists_poll(bContext *C)
if (BLI_exists(name) == FALSE) {
CTX_wm_operator_poll_msg_set(C, "image file not found");
}
- else if (BLI_file_is_writable(name) == FALSE) {
+ else if (!BLI_file_is_writable(name)) {
CTX_wm_operator_poll_msg_set(C, "image path can't be written to");
}
else {
@@ -238,7 +238,7 @@ typedef struct ViewPanData {
int event_type;
} ViewPanData;
-static void image_view_pan_init(bContext *C, wmOperator *op, wmEvent *event)
+static void image_view_pan_init(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceImage *sima = CTX_wm_space_image(C);
ViewPanData *vpd;
@@ -293,14 +293,14 @@ static int image_view_pan_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int image_view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int image_view_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (event->type == MOUSEPAN) {
SpaceImage *sima = CTX_wm_space_image(C);
float offset[2];
- offset[0] = (event->x - event->prevx) / sima->zoom;
- offset[1] = (event->y - event->prevy) / sima->zoom;
+ offset[0] = (event->prevx - event->x) / sima->zoom;
+ offset[1] = (event->prevy - event->y) / sima->zoom;
RNA_float_set_array(op->ptr, "offset", offset);
image_view_pan_exec(C, op);
@@ -312,7 +312,7 @@ static int image_view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
}
-static int image_view_pan_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int image_view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceImage *sima = CTX_wm_space_image(C);
ViewPanData *vpd = op->customdata;
@@ -383,7 +383,7 @@ typedef struct ViewZoomData {
ARegion *ar;
} ViewZoomData;
-static void image_view_zoom_init(bContext *C, wmOperator *op, wmEvent *event)
+static void image_view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceImage *sima = CTX_wm_space_image(C);
ARegion *ar = CTX_wm_region(C);
@@ -455,16 +455,16 @@ enum {
VIEW_CONFIRM
};
-static int image_view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int image_view_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (event->type == MOUSEZOOM) {
+ if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
SpaceImage *sima = CTX_wm_space_image(C);
ARegion *ar = CTX_wm_region(C);
float delta, factor, location[2];
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
- delta = event->x - event->prevx + event->y - event->prevy;
+ delta = event->prevx - event->x + event->prevy - event->y;
if (U.uiflag & USER_ZOOM_INVERT)
delta *= -1;
@@ -525,7 +525,7 @@ static void image_zoom_apply(ViewZoomData *vpd, wmOperator *op, const int x, con
ED_region_tag_redraw(vpd->ar);
}
-static int image_view_zoom_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int image_view_zoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewZoomData *vpd = op->customdata;
short event_code = VIEW_PASS;
@@ -589,7 +589,7 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot)
* that explains the negative signs in the code below
*/
-static int image_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int image_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
if (event->type != NDOF_MOTION)
return OPERATOR_CANCELLED;
@@ -773,7 +773,7 @@ static int image_view_zoom_in_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int image_view_zoom_in_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int image_view_zoom_in_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
float location[2];
@@ -815,7 +815,7 @@ static int image_view_zoom_out_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int image_view_zoom_out_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int image_view_zoom_out_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
float location[2];
@@ -978,7 +978,7 @@ static int image_open_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int image_open_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int image_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
SpaceImage *sima = CTX_wm_space_image(C); /* XXX other space types can call */
char *path = U.textudir;
@@ -1084,7 +1084,7 @@ void IMAGE_OT_match_movie_length(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Match Movie Length";
- ot->description = "Set image's users length to the one of this video";
+ ot->description = "Set image's user's length to the one of this video";
ot->idname = "IMAGE_OT_match_movie_length";
/* api callbacks */
@@ -1109,6 +1109,11 @@ static int image_replace_exec(bContext *C, wmOperator *op)
/* we cant do much if the str is longer then FILE_MAX :/ */
BLI_strncpy(sima->image->name, str, sizeof(sima->image->name));
+ if (sima->image->source == IMA_SRC_GENERATED) {
+ sima->image->source = IMA_SRC_FILE;
+ BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_SRC_CHANGE);
+ }
+
if (BLI_testextensie_array(str, imb_ext_movie))
sima->image->source = IMA_SRC_MOVIE;
else
@@ -1123,7 +1128,7 @@ static int image_replace_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int image_replace_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int image_replace_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
SpaceImage *sima = CTX_wm_space_image(C);
@@ -1217,7 +1222,7 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima,
simopts->im_format.imtype = R_IMF_IMTYPE_PNG;
}
else {
- simopts->im_format.imtype = BKE_ftype_to_imtype(ibuf->ftype);
+ BKE_imbuf_to_image_format(&simopts->im_format, ibuf);
}
//simopts->subimtype = scene->r.subimtype; /* XXX - this is lame, we need to make these available too! */
simopts->im_format.quality = ibuf->ftype & 0xff;
@@ -1434,10 +1439,10 @@ static int image_save_as_exec(bContext *C, wmOperator *op)
static int image_save_as_check(bContext *UNUSED(C), wmOperator *op)
{
ImageFormatData *imf = op->customdata;
- return WM_operator_filesel_ensure_ext_imtype(op, imf->imtype);
+ return WM_operator_filesel_ensure_ext_imtype(op, imf);
}
-static int image_save_as_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
SpaceImage *sima = CTX_wm_space_image(C);
Image *ima = ED_space_image(sima);
@@ -1478,15 +1483,15 @@ static int image_save_as_cancel(bContext *UNUSED(C), wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int image_save_as_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop)
+static bool image_save_as_draw_check_prop(PointerRNA *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") ||
/* when saving a copy, relative path has no effect */
- ((strcmp(prop_id, "relative_path") == 0) && RNA_boolean_get(ptr, "copy"))
+ ((STREQ(prop_id, "relative_path")) && RNA_boolean_get(ptr, "copy"))
);
}
@@ -1559,6 +1564,7 @@ static int image_save_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
SaveImageOptions simopts;
+ save_image_options_defaults(&simopts);
if (save_image_options_init(&simopts, sima, scene, FALSE) == 0)
return OPERATOR_CANCELLED;
save_image_options_from_op(&simopts, op);
@@ -1597,7 +1603,7 @@ static int image_save_sequence_exec(bContext *C, wmOperator *op)
SpaceImage *sima = CTX_wm_space_image(C);
ImBuf *ibuf;
int tot = 0;
- char di[FILE_MAX], fi[FILE_MAX];
+ char di[FILE_MAX];
if (sima->image == NULL)
return OPERATOR_CANCELLED;
@@ -1626,10 +1632,8 @@ static int image_save_sequence_exec(bContext *C, wmOperator *op)
for (ibuf = sima->image->ibufs.first; ibuf; ibuf = ibuf->next)
if (ibuf->userflags & IB_BITMAPDIRTY)
break;
-
- BLI_strncpy(di, ibuf->name, FILE_MAX);
- BLI_splitdirstring(di, fi);
-
+
+ BLI_split_dir_part(ibuf->name, di, sizeof(di));
BKE_reportf(op->reports, RPT_INFO, "%d image(s) will be saved in %s", tot, di);
for (ibuf = sima->image->ibufs.first; ibuf; ibuf = ibuf->next) {
@@ -1710,6 +1714,7 @@ static int image_new_exec(bContext *C, wmOperator *op)
Scene *scene;
Object *obedit;
Image *ima;
+ Main *bmain;
PointerRNA ptr, idptr;
PropertyRNA *prop;
char name[MAX_ID_NAME - 2];
@@ -1720,6 +1725,7 @@ static int image_new_exec(bContext *C, wmOperator *op)
sima = CTX_wm_space_image(C);
scene = CTX_data_scene(C);
obedit = CTX_data_edit_object(C);
+ bmain = CTX_data_main(C);
RNA_string_get(op->ptr, "name", name);
width = RNA_int_get(op->ptr, "width");
@@ -1729,15 +1735,10 @@ static int image_new_exec(bContext *C, wmOperator *op)
RNA_float_get_array(op->ptr, "color", color);
alpha = RNA_boolean_get(op->ptr, "alpha");
- if (!floatbuf) {
- /* OCIO_TODO: perhaps we need to convert to display space, not just to sRGB */
- linearrgb_to_srgb_v3_v3(color, color);
- }
-
if (!alpha)
color[3] = 1.0f;
- ima = BKE_image_add_generated(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);
if (!ima)
return OPERATOR_CANCELLED;
@@ -1772,9 +1773,9 @@ 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 */
-static int image_new_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int image_new_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- return WM_operator_props_dialog_popup(C, op, 300, 100);
+ return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, 5 * UI_UNIT_Y);
}
@@ -1800,6 +1801,7 @@ void IMAGE_OT_new(wmOperatorType *ot)
RNA_def_int(ot->srna, "width", 1024, 1, INT_MAX, "Width", "Image width", 1, 16384);
RNA_def_int(ot->srna, "height", 1024, 1, INT_MAX, "Height", "Image height", 1, 16384);
prop = RNA_def_float_color(ot->srna, "color", 4, NULL, 0.0f, FLT_MAX, "Color", "Default fill color", 0.0f, 1.0f);
+ RNA_def_property_subtype(prop, PROP_COLOR_GAMMA);
RNA_def_property_float_array_default(prop, default_color);
RNA_def_boolean(ot->srna, "alpha", 1, "Alpha", "Create an image with an alpha channel");
RNA_def_enum(ot->srna, "generated_type", image_generated_type_items, IMA_GENTYPE_BLANK,
@@ -1941,7 +1943,7 @@ static int image_pack_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int image_pack_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int image_pack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Image *ima = CTX_data_edit_image(C);
ImBuf *ibuf;
@@ -1955,9 +1957,10 @@ static int image_pack_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)
ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
if (!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) {
- pup = uiPupMenuBegin(C, "OK", ICON_QUESTION);
+ pup = uiPupMenuBegin(C, IFACE_("OK"), ICON_QUESTION);
layout = uiPupMenuLayout(pup);
- uiItemBooleanO(layout, "Can't pack edited image from disk. Pack as internal PNG?", ICON_NONE, op->idname, "as_png", 1);
+ uiItemBooleanO(layout, IFACE_("Can't pack edited image from disk, pack as internal PNG?"), ICON_NONE,
+ op->idname, "as_png", 1);
uiPupMenuEnd(C, pup);
BKE_image_release_ibuf(ima, ibuf, NULL);
@@ -2024,7 +2027,7 @@ static int image_unpack_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int image_unpack_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Image *ima = CTX_data_edit_image(C);
@@ -2076,6 +2079,7 @@ typedef struct ImageSampleInfo {
unsigned char col[4];
float colf[4];
+ float linearcol[4];
int z;
float zf;
@@ -2096,7 +2100,7 @@ static void image_sample_draw(const bContext *C, ARegion *ar, void *arg_info)
Scene *scene = CTX_data_scene(C);
ED_image_draw_info(scene, ar, info->color_manage, info->use_default_view, info->channels,
- info->x, info->y, info->colp, info->colfp, info->zp, info->zfp);
+ info->x, info->y, info->colp, info->colfp, info->linearcol, info->zp, info->zfp);
}
}
@@ -2140,7 +2144,7 @@ int ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], floa
return ret;
}
-static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event)
+static void image_sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceImage *sima = CTX_wm_space_image(C);
ARegion *ar = CTX_wm_region(C);
@@ -2195,7 +2199,10 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event)
info->colf[3] = (float)cp[3] / 255.0f;
info->colfp = info->colf;
- info->color_manage = FALSE;
+ copy_v4_v4(info->linearcol, info->colf);
+ IMB_colormanagement_colorspace_to_scene_linear_v4(info->linearcol, false, ibuf->rect_colorspace);
+
+ info->color_manage = TRUE;
}
if (ibuf->rect_float) {
fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
@@ -2206,6 +2213,8 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event)
info->colf[3] = fp[3];
info->colfp = info->colf;
+ copy_v4_v4(info->linearcol, info->colf);
+
info->color_manage = TRUE;
}
@@ -2266,7 +2275,7 @@ static void image_sample_exit(bContext *C, wmOperator *op)
MEM_freeN(info);
}
-static int image_sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int image_sample_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceImage *sima = CTX_wm_space_image(C);
ARegion *ar = CTX_wm_region(C);
@@ -2287,7 +2296,7 @@ static int image_sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static int image_sample_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int image_sample_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
switch (event->type) {
case LEFTMOUSE:
@@ -2373,7 +2382,7 @@ static int image_sample_line_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int image_sample_line_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int image_sample_line_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceImage *sima = CTX_wm_space_image(C);
@@ -2434,6 +2443,7 @@ void IMAGE_OT_curves_point_set(wmOperatorType *ot)
RNA_def_enum(ot->srna, "point", point_items, 0, "Point", "Set black point or white point for curves");
}
+#if 0 /* Not ported to 2.5x yet */
/******************** record composite operator *********************/
typedef struct RecordCompositeData {
@@ -2527,7 +2537,7 @@ static int image_record_composite_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int image_record_composite_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int image_record_composite_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
RecordCompositeData *rcd;
@@ -2544,7 +2554,7 @@ static int image_record_composite_invoke(bContext *C, wmOperator *op, wmEvent *U
return OPERATOR_RUNNING_MODAL;
}
-static int image_record_composite_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int image_record_composite_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
RecordCompositeData *rcd = op->customdata;
@@ -2585,6 +2595,8 @@ void IMAGE_OT_record_composite(wmOperatorType *ot)
ot->poll = space_image_buffer_exists_poll;
}
+#endif
+
/********************* cycle render slot operator *********************/
static int image_cycle_render_slot_poll(bContext *C)
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index ea696772957..761becdbf8e 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -38,6 +38,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_threads.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
@@ -151,6 +152,7 @@ static SpaceLink *image_new(const bContext *UNUSED(C))
simage->spacetype = SPACE_IMAGE;
simage->zoom = 1.0f;
simage->lock = TRUE;
+ simage->flag = SI_SHOW_GPENCIL | SI_USE_ALPHA;
simage->iuser.ok = TRUE;
simage->iuser.fie_ima = 2;
@@ -251,8 +253,6 @@ static void image_operatortypes(void)
WM_operatortype_append(IMAGE_OT_sample_line);
WM_operatortype_append(IMAGE_OT_curves_point_set);
- WM_operatortype_append(IMAGE_OT_record_composite);
-
WM_operatortype_append(IMAGE_OT_properties);
WM_operatortype_append(IMAGE_OT_scopes);
}
@@ -291,10 +291,16 @@ static void image_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_out", PADMINUS, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom", MOUSEZOOM, 0, 0, 0);
+ WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom", MOUSEPAN, 0, KM_CTRL, 0);
+ /* ctrl now works as well, shift + numpad works as arrow keys on Windows */
+ RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD8, KM_PRESS, KM_CTRL, 0)->ptr, "ratio", 8.0f);
+ RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD4, KM_PRESS, KM_CTRL, 0)->ptr, "ratio", 4.0f);
+ RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD2, KM_PRESS, KM_CTRL, 0)->ptr, "ratio", 2.0f);
RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD8, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 8.0f);
RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD4, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 4.0f);
RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD2, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 2.0f);
+
RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD1, KM_PRESS, 0, 0)->ptr, "ratio", 1.0f);
RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD2, KM_PRESS, 0, 0)->ptr, "ratio", 0.5f);
RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD4, KM_PRESS, 0, 0)->ptr, "ratio", 0.25f);
@@ -331,7 +337,7 @@ static void image_keymap(struct wmKeyConfig *keyconf)
}
/* dropboxes */
-static int image_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
+static int image_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_PATH)
if (ELEM3(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_BLANK)) /* rule might not work? */
@@ -669,22 +675,41 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
- /* Grease Pencil too (in addition to UV's) */
- draw_image_grease_pencil((bContext *)C, 1);
+ if (sima->flag & SI_SHOW_GPENCIL) {
+ /* Grease Pencil too (in addition to UV's) */
+ draw_image_grease_pencil((bContext *)C, TRUE);
+ }
/* sample line */
draw_image_sample_line(sima);
UI_view2d_view_restore(C);
- /* draw Grease Pencil - screen space only */
- draw_image_grease_pencil((bContext *)C, 0);
+ if (sima->flag & SI_SHOW_GPENCIL) {
+ /* draw Grease Pencil - screen space only */
+ draw_image_grease_pencil((bContext *)C, FALSE);
+ }
if (mask) {
- int width, height;
+ Image *image = ED_space_image(sima);
+ int width, height, show_viewer;
float aspx, aspy;
+
+ show_viewer = (image && image->source == IMA_SRC_VIEWER);
+
+ if (show_viewer) {
+ /* ED_space_image_get* will acquire image buffer which requires
+ * lock here by the same reason why lock is needed in draw_image_main
+ */
+ BLI_lock_thread(LOCK_DRAW_IMAGE);
+ }
+
ED_space_image_get_size(sima, &width, &height);
ED_space_image_get_aspect(sima, &aspx, &aspy);
+
+ if (show_viewer)
+ BLI_unlock_thread(LOCK_DRAW_IMAGE);
+
ED_mask_draw_region(mask, ar,
sima->mask_info.draw_flag, sima->mask_info.draw_type,
width, height,
@@ -723,6 +748,7 @@ static void image_buttons_area_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
+ ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
ED_region_panels_init(wm, ar);
keymap = WM_keymap_find(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
@@ -762,6 +788,7 @@ static void image_scope_area_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
+ ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
ED_region_panels_init(wm, ar);
keymap = WM_keymap_find(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
diff --git a/source/blender/editors/space_info/SConscript b/source/blender/editors/space_info/SConscript
index e4746aefa0c..bacc28161d3 100644
--- a/source/blender/editors/space_info/SConscript
+++ b/source/blender/editors/space_info/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/space_info/info_draw.c b/source/blender/editors/space_info/info_draw.c
index 5830c4574df..a748c303b5d 100644
--- a/source/blender/editors/space_info/info_draw.c
+++ b/source/blender/editors/space_info/info_draw.c
@@ -56,6 +56,8 @@
#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"
@@ -139,7 +141,7 @@ static int report_textview_begin(TextViewContext *tvc)
// SpaceConsole *sc = (SpaceConsole *)tvc->arg1;
ReportList *reports = (ReportList *)tvc->arg2;
- tvc->lheight = 14; //sc->lheight;
+ tvc->lheight = 14 * UI_DPI_FAC; //sc->lheight;
tvc->sel_start = 0;
tvc->sel_end = 0;
@@ -249,7 +251,8 @@ static int report_textview_line_color(struct TextViewContext *tvc, unsigned char
#undef USE_INFO_NEWLINE
-static int info_textview_main__internal(struct SpaceInfo *sinfo, ARegion *ar, ReportList *reports, int draw, int mval[2], void **mouse_pick, int *pos_pick)
+static int info_textview_main__internal(struct SpaceInfo *sinfo, ARegion *ar, ReportList *reports,
+ int draw, int mval[2], void **mouse_pick, int *pos_pick)
{
int ret = 0;
@@ -262,6 +265,7 @@ static int info_textview_main__internal(struct SpaceInfo *sinfo, ARegion *ar, Re
tvc.step = report_textview_step;
tvc.line_get = report_textview_line_get;
tvc.line_color = report_textview_line_color;
+ tvc.const_colors = NULL;
tvc.arg1 = sinfo;
tvc.arg2 = reports;
@@ -269,10 +273,10 @@ static int info_textview_main__internal(struct SpaceInfo *sinfo, ARegion *ar, Re
/* view */
tvc.sel_start = 0;
tvc.sel_end = 0;
- tvc.lheight = 14; //sc->lheight;
+ tvc.lheight = 14 * UI_DPI_FAC; //sc->lheight;
tvc.ymin = v2d->cur.ymin;
tvc.ymax = v2d->cur.ymax;
- tvc.winx = ar->winx;
+ tvc.winx = ar->winx - V2D_SCROLL_WIDTH;
ret = textview_draw(&tvc, draw, mval, mouse_pick, pos_pick);
diff --git a/source/blender/editors/space_info/info_intern.h b/source/blender/editors/space_info/info_intern.h
index 80018e849d3..b5426fe15e1 100644
--- a/source/blender/editors/space_info/info_intern.h
+++ b/source/blender/editors/space_info/info_intern.h
@@ -39,11 +39,16 @@ struct ReportList;
void FILE_OT_pack_all(struct wmOperatorType *ot);
void FILE_OT_unpack_all(struct wmOperatorType *ot);
+void FILE_OT_unpack_item(struct wmOperatorType *ot);
+void FILE_OT_pack_libraries(struct wmOperatorType *ot);
+void FILE_OT_unpack_libraries(struct wmOperatorType *ot);
+
void FILE_OT_make_paths_relative(struct wmOperatorType *ot);
void FILE_OT_make_paths_absolute(struct wmOperatorType *ot);
void FILE_OT_report_missing_files(struct wmOperatorType *ot);
void FILE_OT_find_missing_files(struct wmOperatorType *ot);
+
void INFO_OT_reports_display_update(struct wmOperatorType *ot);
/* info_draw.c */
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
index 48b5eaf7b44..c68473820e3 100644
--- a/source/blender/editors/space_info/info_ops.c
+++ b/source/blender/editors/space_info/info_ops.c
@@ -40,15 +40,19 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLI_bpath.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
+#include "BKE_bpath.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_image.h"
+#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_packedFile.h"
#include "BKE_report.h"
+#include "BKE_screen.h"
#include "WM_api.h"
@@ -66,24 +70,79 @@
#include "info_intern.h"
+/********************* pack blend file libararies operator *********************/
+
+static int pack_libraries_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+
+ packLibraries(bmain, op->reports);
+
+ return OPERATOR_FINISHED;
+}
+
+void FILE_OT_pack_libraries(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Pack Blender Libraries";
+ ot->idname = "FILE_OT_pack_libraries";
+ ot->description = "Pack all used Blender library files into the current .blend";
+
+ /* api callbacks */
+ ot->exec = pack_libraries_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int unpack_libraries_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+
+ unpackLibraries(bmain, op->reports);
+
+ return OPERATOR_FINISHED;
+}
+
+static int unpack_libraries_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ return WM_operator_confirm_message(C, op, "Unpack Blender Libraries - creates directories, all new paths should work");
+}
+
+void FILE_OT_unpack_libraries(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Unpack Blender Libraries";
+ ot->idname = "FILE_OT_unpack_libraries";
+ ot->description = "Unpack all used Blender library files from this .blend file";
+
+ /* api callbacks */
+ ot->invoke = unpack_libraries_invoke;
+ ot->exec = unpack_libraries_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
/********************* pack all operator *********************/
static int pack_all_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
-
+
packAll(bmain, op->reports);
G.fileflags |= G_AUTOPACK;
-
+
return OPERATOR_FINISHED;
}
-static int pack_all_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int pack_all_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Main *bmain = CTX_data_main(C);
Image *ima;
ImBuf *ibuf;
-
+
// first check for dirty images
for (ima = bmain->image.first; ima; ima = ima->id.next) {
if (ima->ibufs.first) { /* XXX FIX */
@@ -93,16 +152,16 @@ static int pack_all_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
BKE_image_release_ibuf(ima, ibuf, NULL);
break;
}
-
+
BKE_image_release_ibuf(ima, ibuf, NULL);
}
}
-
+
if (ima) {
uiPupMenuOkee(C, "FILE_OT_pack_all", "Some images are painted on. These changes will be lost. Continue?");
return OPERATOR_CANCELLED;
}
-
+
return pack_all_exec(C, op);
}
@@ -116,11 +175,12 @@ void FILE_OT_pack_all(wmOperatorType *ot)
/* api callbacks */
ot->exec = pack_all_exec;
ot->invoke = pack_all_invoke;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
/********************* unpack all operator *********************/
static const EnumPropertyItem unpack_all_method_items[] = {
@@ -143,7 +203,7 @@ static int unpack_all_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int unpack_all_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int unpack_all_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Main *bmain = CTX_data_main(C);
uiPopupMenu *pup;
@@ -160,9 +220,9 @@ static int unpack_all_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)
}
if (count == 1)
- strcpy(title, "Unpack 1 file");
+ strcpy(title, IFACE_("Unpack 1 File"));
else
- BLI_snprintf(title, sizeof(title), "Unpack %d files", count);
+ BLI_snprintf(title, sizeof(title), IFACE_("Unpack %d Files"), count);
pup = uiPupMenuBegin(C, title, ICON_NONE);
layout = uiPupMenuLayout(pup);
@@ -193,6 +253,78 @@ void FILE_OT_unpack_all(wmOperatorType *ot)
RNA_def_enum(ot->srna, "method", unpack_all_method_items, PF_USE_LOCAL, "Method", "How to unpack");
}
+/********************* unpack single item operator *********************/
+
+static const EnumPropertyItem unpack_item_method_items[] = {
+ {PF_USE_LOCAL, "USE_LOCAL", 0, "Use file from current directory (create when necessary)", ""},
+ {PF_WRITE_LOCAL, "WRITE_LOCAL", 0, "Write file to current directory (overwrite existing file)", ""},
+ {PF_USE_ORIGINAL, "USE_ORIGINAL", 0, "Use file in original location (create when necessary)", ""},
+ {PF_WRITE_ORIGINAL, "WRITE_ORIGINAL", 0, "Write file to original location (overwrite existing file)", ""},
+ /* {PF_ASK, "ASK", 0, "Ask for each file", ""}, */
+ {0, NULL, 0, NULL, NULL}};
+
+
+static int unpack_item_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ ID *id;
+ char idname[MAX_ID_NAME - 2];
+ int type = RNA_int_get(op->ptr, "id_type");
+ int method = RNA_enum_get(op->ptr, "method");
+
+ RNA_string_get(op->ptr, "id_name", idname);
+ id = BKE_libblock_find_name(type, idname);
+
+ if (id == NULL) {
+ BKE_report(op->reports, RPT_WARNING, "No packed file");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (method != PF_KEEP)
+ BKE_unpack_id(bmain, id, op->reports, method); /* XXX PF_ASK can't work here */
+
+ G.fileflags &= ~G_AUTOPACK;
+
+ return OPERATOR_FINISHED;
+}
+
+static int unpack_item_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ uiPopupMenu *pup;
+ uiLayout *layout;
+
+ pup = uiPupMenuBegin(C, IFACE_("Unpack"), ICON_NONE);
+ layout = uiPupMenuLayout(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);
+
+ return OPERATOR_CANCELLED;
+}
+
+void FILE_OT_unpack_item(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Unpack Item";
+ ot->idname = "FILE_OT_unpack_item";
+ ot->description = "Unpack this file to an external file";
+
+ /* api callbacks */
+ ot->exec = unpack_item_exec;
+ ot->invoke = unpack_item_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "method", unpack_item_method_items, PF_USE_LOCAL, "Method", "How to unpack");
+ RNA_def_string(ot->srna, "id_name", "", BKE_ST_MAXNAME, "ID name", "Name of ID block to unpack");
+ RNA_def_int(ot->srna, "id_type", ID_IM, 0, INT_MAX, "ID Type", "Identifier type of ID block", 0, INT_MAX);
+}
+
+
/********************* make paths relative operator *********************/
static int make_paths_relative_exec(bContext *C, wmOperator *op)
@@ -204,7 +336,7 @@ static int make_paths_relative_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BLI_bpath_relative_convert(bmain, bmain->name, op->reports);
+ BKE_bpath_relative_convert(bmain, bmain->name, op->reports);
/* redraw everything so any changed paths register */
WM_main_add_notifier(NC_WINDOW, NULL);
@@ -237,7 +369,7 @@ static int make_paths_absolute_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BLI_bpath_absolute_convert(bmain, bmain->name, op->reports);
+ BKE_bpath_absolute_convert(bmain, bmain->name, op->reports);
/* redraw everything so any changed paths register */
WM_main_add_notifier(NC_WINDOW, NULL);
@@ -266,7 +398,7 @@ static int report_missing_files_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
/* run the missing file check */
- BLI_bpath_missing_files_check(bmain, op->reports);
+ BKE_bpath_missing_files_check(bmain, op->reports);
return OPERATOR_FINISHED;
}
@@ -291,13 +423,13 @@ static int find_missing_files_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
const char *searchpath = RNA_string_get_alloc(op->ptr, "filepath", NULL, 0);
- BLI_bpath_missing_files_find(bmain, searchpath, op->reports);
+ BKE_bpath_missing_files_find(bmain, searchpath, op->reports);
MEM_freeN((void *)searchpath);
return OPERATOR_FINISHED;
}
-static int find_missing_files_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int find_missing_files_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
/* XXX file open button text "Find Missing Files" */
WM_event_add_fileselect(C, op);
@@ -337,7 +469,7 @@ void FILE_OT_find_missing_files(wmOperatorType *ot)
#define ERROR_TIMEOUT 10.0f
#define ERROR_COLOR_TIMEOUT 6.0f
#define COLLAPSE_TIMEOUT 0.25f
-static int update_reports_display_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int update_reports_display_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
wmWindowManager *wm = CTX_wm_manager(C);
ReportList *reports = CTX_wm_reports(C);
diff --git a/source/blender/editors/space_info/info_report.c b/source/blender/editors/space_info/info_report.c
index 049a50f89fc..b096b8f3e2b 100644
--- a/source/blender/editors/space_info/info_report.c
+++ b/source/blender/editors/space_info/info_report.c
@@ -62,7 +62,7 @@ int info_report_mask(SpaceInfo *UNUSED(sinfo))
return report_mask;
#endif
- return RPT_DEBUG_ALL | RPT_INFO_ALL | RPT_OPERATOR_ALL | RPT_WARNING_ALL | RPT_ERROR_ALL;
+ return RPT_DEBUG_ALL | RPT_INFO_ALL | RPT_OPERATOR_ALL | RPT_PROPERTY_ALL | RPT_WARNING_ALL | RPT_ERROR_ALL;
}
// TODO, get this working again!
@@ -77,7 +77,10 @@ static int report_replay_exec(bContext *C, wmOperator *UNUSED(op))
sc->type = CONSOLE_TYPE_PYTHON;
for (report = reports->list.last; report; report = report->prev) {
- if ((report->type & report_mask) && (report->type & RPT_OPERATOR_ALL) && (report->flag & SELECT)) {
+ if ((report->type & report_mask) &&
+ (report->type & RPT_OPERATOR_ALL | RPT_PROPERTY_ALL) &&
+ (report->flag & SELECT))
+ {
console_history_add_str(sc, report->message, 0);
WM_operator_name_call(C, "CONSOLE_OT_execute", WM_OP_EXEC_DEFAULT, NULL);
@@ -124,7 +127,7 @@ static int select_report_pick_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int select_report_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int select_report_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceInfo *sinfo = CTX_wm_space_info(C);
ARegion *ar = CTX_wm_region(C);
@@ -145,7 +148,7 @@ static int select_report_pick_invoke(bContext *C, wmOperator *op, wmEvent *event
void INFO_OT_select_pick(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Select report";
+ ot->name = "Select Report";
ot->description = "Select reports by index";
ot->idname = "INFO_OT_select_pick";
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 5e5e0c87feb..b2e9427c799 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -38,8 +38,12 @@
#include "DNA_meta_types.h"
#include "DNA_scene_types.h"
+#include "BLI_math.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "BKE_anim.h"
#include "BKE_blender.h"
#include "BKE_curve.h"
@@ -47,6 +51,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_key.h"
#include "BKE_mesh.h"
+#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_tessmesh.h"
@@ -54,6 +59,7 @@
#include "ED_armature.h"
#include "ED_mesh.h"
+#define MAX_INFO_LEN 512
typedef struct SceneStats {
int totvert, totvertsel;
@@ -62,9 +68,9 @@ typedef struct SceneStats {
int totbone, totbonesel;
int totobj, totobjsel;
int totlamp, totlampsel;
- int tottri, totmesh, totcurve;
+ int tottri, totmesh;
- char infostr[512];
+ char infostr[MAX_INFO_LEN];
} SceneStats;
static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
@@ -74,7 +80,7 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
{
/* we assume derivedmesh is already built, this strictly does stats now. */
DerivedMesh *dm = ob->derivedFinal;
- int totvert, totedge, totface;
+ int totvert, totedge, totface, totloop;
stats->totmesh += totob;
@@ -82,10 +88,12 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
totvert = dm->getNumVerts(dm);
totedge = dm->getNumEdges(dm);
totface = dm->getNumPolys(dm);
+ totloop = dm->getNumLoops(dm);
stats->totvert += totvert * totob;
stats->totedge += totedge * totob;
stats->totface += totface * totob;
+ stats->tottri += poly_to_tri_count(totface, totloop) * totob;
if (sel) {
stats->totvertsel += totvert;
@@ -103,40 +111,23 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
case OB_SURF:
case OB_CURVE:
case OB_FONT:
- {
- int tot = 0, totf = 0;
-
- stats->totcurve += totob;
-
- if (ob->disp.first)
- BKE_displist_count(&ob->disp, &tot, &totf);
-
- tot *= totob;
- totf *= totob;
-
- stats->totvert += tot;
- stats->totface += totf;
-
- if (sel) {
- stats->totvertsel += tot;
- stats->totfacesel += totf;
- }
- break;
- }
case OB_MBALL:
{
- int tot = 0, totf = 0;
+ int totv = 0, totf = 0, tottri = 0;
- BKE_displist_count(&ob->disp, &tot, &totf);
+ if (ob->disp.first)
+ BKE_displist_count(&ob->disp, &totv, &totf, &tottri);
- tot *= totob;
- totf *= totob;
+ totv *= totob;
+ totf *= totob;
+ tottri *= totob;
- stats->totvert += tot;
+ stats->totvert += totv;
stats->totface += totf;
+ stats->tottri += tottri;
if (sel) {
- stats->totvertsel += tot;
+ stats->totvertsel += totv;
stats->totfacesel += totf;
}
break;
@@ -179,8 +170,11 @@ static void stats_object_edit(Object *obedit, SceneStats *stats)
if (ebo->flag & BONE_SELECTED) stats->totbonesel++;
/* if this is a connected child and it's parent is being moved, remove our root */
- if ((ebo->flag & BONE_CONNECTED) && (ebo->flag & BONE_ROOTSEL) && ebo->parent && (ebo->parent->flag & BONE_TIPSEL))
+ if ((ebo->flag & BONE_CONNECTED) && (ebo->flag & BONE_ROOTSEL) &&
+ ebo->parent && (ebo->parent->flag & BONE_TIPSEL))
+ {
stats->totvertsel--;
+ }
stats->totvert += 2;
}
@@ -260,6 +254,12 @@ static void stats_object_pose(Object *ob, SceneStats *stats)
}
}
+static void stats_object_sculpt_dynamic_topology(Object *ob, SceneStats *stats)
+{
+ stats->totvert = ob->sculpt->bm->totvert;
+ stats->tottri = ob->sculpt->bm->totface;
+}
+
static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
{
if (base->flag & SELECT) stats->totobjsel++;
@@ -319,6 +319,12 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
}
}
+static int stats_is_object_dynamic_topology_sculpt(Object *ob)
+{
+ return (ob && (ob->mode & OB_MODE_SCULPT) &&
+ ob->sculpt && ob->sculpt->bm);
+}
+
/* Statistics displayed in info header. Called regularly on scene changes. */
static void stats_update(Scene *scene)
{
@@ -334,6 +340,10 @@ static void stats_update(Scene *scene)
/* Pose Mode */
stats_object_pose(ob, &stats);
}
+ else if (stats_is_object_dynamic_topology_sculpt(ob)) {
+ /* Dynamic-topology sculpt mode */
+ stats_object_sculpt_dynamic_topology(ob, &stats);
+ }
else {
/* Objects */
for (base = scene->base.first; base; base = base->next)
@@ -349,54 +359,70 @@ static void stats_update(Scene *scene)
static void stats_string(Scene *scene)
{
+#define MAX_INFO_MEM_LEN 64
SceneStats *stats = scene->stats;
Object *ob = (scene->basact) ? scene->basact->object : NULL;
uintptr_t mem_in_use, mmap_in_use;
- char memstr[64];
+ char memstr[MAX_INFO_MEM_LEN];
char *s;
+ size_t ofs = 0;
mem_in_use = MEM_get_memory_in_use();
mmap_in_use = MEM_get_mapped_memory_in_use();
/* get memory statistics */
- s = memstr + sprintf(memstr, " | Mem:%.2fM", (double)((mem_in_use - mmap_in_use) >> 10) / 1024.0);
+ s = memstr;
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" | Mem:%.2fM"),
+ (double)((mem_in_use - mmap_in_use) >> 10) / 1024.0);
if (mmap_in_use)
- sprintf(s, " (%.2fM)", (double)((mmap_in_use) >> 10) / 1024.0);
+ BLI_snprintf(s + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%.2fM)"), (double)((mmap_in_use) >> 10) / 1024.0);
s = stats->infostr;
-
- s += sprintf(s, "%s | ", versionstr);
+ ofs = 0;
+
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, "%s | ", versionstr);
if (scene->obedit) {
if (BKE_keyblock_from_object(scene->obedit))
- s += sprintf(s, "(Key) ");
+ ofs += BLI_strncpy_rlen(s + ofs, IFACE_("(Key) "), MAX_INFO_LEN - ofs);
if (scene->obedit->type == OB_MESH) {
- s += sprintf(s, "Verts:%d/%d | Edges:%d/%d | Faces:%d/%d | Tris:%d",
- stats->totvertsel, stats->totvert, stats->totedgesel, stats->totedge, stats->totfacesel, stats->totface, stats->tottri);
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs,
+ IFACE_("Verts:%d/%d | Edges:%d/%d | Faces:%d/%d | Tris:%d"),
+ stats->totvertsel, stats->totvert, stats->totedgesel, stats->totedge,
+ stats->totfacesel, stats->totface, stats->tottri);
}
else if (scene->obedit->type == OB_ARMATURE) {
- s += sprintf(s, "Verts:%d/%d | Bones:%d/%d", stats->totvertsel, stats->totvert, stats->totbonesel, stats->totbone);
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%d/%d | Bones:%d/%d"), stats->totvertsel,
+ stats->totvert, stats->totbonesel, stats->totbone);
}
else {
- s += sprintf(s, "Verts:%d/%d", stats->totvertsel, stats->totvert);
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%d/%d"), stats->totvertsel, stats->totvert);
}
- strcat(s, memstr);
+ ofs += BLI_strncpy_rlen(s + ofs, memstr, MAX_INFO_LEN - ofs);
}
else if (ob && (ob->mode & OB_MODE_POSE)) {
- s += sprintf(s, "Bones:%d/%d %s",
- stats->totbonesel, stats->totbone, memstr);
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Bones:%d/%d %s"),
+ stats->totbonesel, stats->totbone, memstr);
+ }
+ else if (stats_is_object_dynamic_topology_sculpt(ob)) {
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%d | Tris:%d"), stats->totvert, stats->tottri);
}
else {
- s += sprintf(s, "Verts:%d | Faces:%d | Objects:%d/%d | Lamps:%d/%d%s",
- stats->totvert, stats->totface, stats->totobjsel, stats->totobj, stats->totlampsel, stats->totlamp, memstr);
+ ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs,
+ IFACE_("Verts:%d | Faces:%d | Tris:%d | Objects:%d/%d | Lamps:%d/%d%s"), stats->totvert,
+ stats->totface, stats->tottri, stats->totobjsel, stats->totobj, stats->totlampsel,
+ stats->totlamp, memstr);
}
if (ob)
- sprintf(s, " | %s", ob->id.name + 2);
+ BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, " | %s", ob->id.name + 2);
+#undef MAX_INFO_MEM_LEN
}
+#undef MAX_INFO_LEN
+
void ED_info_stats_clear(Scene *scene)
{
if (scene->stats) {
@@ -413,4 +439,3 @@ const char *ED_info_stats_string(Scene *scene)
return scene->stats->infostr;
}
-
diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c
index cba0a808d63..1577ac338e7 100644
--- a/source/blender/editors/space_info/space_info.c
+++ b/source/blender/editors/space_info/space_info.c
@@ -178,7 +178,11 @@ static void info_main_area_draw(const bContext *C, ARegion *ar)
static void info_operatortypes(void)
{
WM_operatortype_append(FILE_OT_pack_all);
+ WM_operatortype_append(FILE_OT_pack_libraries);
WM_operatortype_append(FILE_OT_unpack_all);
+ WM_operatortype_append(FILE_OT_unpack_item);
+ WM_operatortype_append(FILE_OT_unpack_libraries);
+
WM_operatortype_append(FILE_OT_make_paths_relative);
WM_operatortype_append(FILE_OT_make_paths_absolute);
WM_operatortype_append(FILE_OT_report_missing_files);
@@ -272,7 +276,7 @@ static void info_header_listener(ARegion *ar, wmNotifier *wmn)
static void recent_files_menu_draw(const bContext *UNUSED(C), Menu *menu)
{
struct RecentFile *recent;
- char file [FILE_MAX];
+ char file[FILE_MAX];
uiLayout *layout = menu->layout;
uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
if (G.recent_files.first) {
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index f454b1dbe7d..e53cbdd04af 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -31,21 +31,27 @@
#include <limits.h>
#include <assert.h>
+#include "MEM_guardedalloc.h"
+
#include "BLF_api.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLI_string_utf8.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "BKE_text.h"
+
#include "ED_datafiles.h"
#include "textview.h"
static void console_font_begin(TextViewContext *sc)
{
- BLF_size(blf_mono_font, sc->lheight - 2, 72);
+ /* 0.875 is based on: 16 pixels lines get 14 pixel text */
+ BLF_size(blf_mono_font, 0.875 * sc->lheight, 72);
}
typedef struct ConsoleDrawContext {
@@ -61,57 +67,95 @@ typedef struct ConsoleDrawContext {
int draw;
} ConsoleDrawContext;
-static void console_draw_sel(int sel[2], int xy[2], int str_len_draw, int cwidth, int lheight)
+BLI_INLINE void console_step_sel(ConsoleDrawContext *cdc, const int step)
+{
+ cdc->sel[0] += step;
+ cdc->sel[1] += step;
+}
+
+static void console_draw_sel(const char *str, const int sel[2], const int xy[2], const int str_len_draw,
+ int cwidth, int lheight, const unsigned char bg_sel[4])
{
if (sel[0] <= str_len_draw && sel[1] >= 0) {
- int sta = max_ii(sel[0], 0);
- int end = min_ii(sel[1], str_len_draw);
+ const int sta = txt_utf8_offset_to_column(str, max_ii(sel[0], 0));
+ const int end = txt_utf8_offset_to_column(str, min_ii(sel[1], str_len_draw));
- glEnable(GL_POLYGON_STIPPLE);
- glPolygonStipple(stipple_halftone);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColor4ub(255, 255, 255, 96);
+ glColor4ubv(bg_sel);
glRecti(xy[0] + (cwidth * sta), xy[1] - 2 + lheight, xy[0] + (cwidth * end), xy[1] - 2);
- glDisable(GL_POLYGON_STIPPLE);
glDisable(GL_BLEND);
}
}
+/* warning: allocated memory for 'offsets' must be freed by caller */
+static int console_wrap_offsets(const char *str, int len, int width, int *lines, int **offsets)
+{
+ int i, end; /* column */
+ int j; /* mem */
+
+ *lines = 1;
+
+ *offsets = MEM_callocN(sizeof(**offsets) * (len * BLI_UTF8_WIDTH_MAX / MAX2(1, width - (BLI_UTF8_WIDTH_MAX - 1)) + 1),
+ "console_wrap_offsets");
+ (*offsets)[0] = 0;
+
+ for (i = 0, end = width, j = 0; j < len && str[j]; j += BLI_str_utf8_size_safe(str + j)) {
+ int columns = BLI_str_utf8_char_width_safe(str + j);
+
+ if (i + columns > end) {
+ (*offsets)[*lines] = j;
+ (*lines)++;
+
+ end = i + width;
+ }
+ i += columns;
+ }
+ return j; /* return actual length */
+}
/* return 0 if the last line is off the screen
* should be able to use this for any string type */
-static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str_len, unsigned char *fg, unsigned char *bg)
+static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str_len,
+ const unsigned char fg[3], const unsigned char bg[3], const unsigned char bg_sel[4])
{
-#define STEP_SEL(value) cdc->sel[0] += (value); cdc->sel[1] += (value)
int rct_ofs = cdc->lheight / 4;
- int tot_lines = (str_len / cdc->console_width) + 1; /* total number of lines for wrapping */
- int y_next = (str_len > cdc->console_width) ? cdc->xy[1] + cdc->lheight * tot_lines : cdc->xy[1] + cdc->lheight;
+ int tot_lines; /* total number of lines for wrapping */
+ int *offsets; /* offsets of line beginnings for wrapping */
+ int y_next;
const int mono = blf_mono_font;
+ str_len = console_wrap_offsets(str, str_len, cdc->console_width, &tot_lines, &offsets);
+ y_next = cdc->xy[1] + cdc->lheight * tot_lines;
+
/* just advance the height */
if (cdc->draw == 0) {
- if (cdc->pos_pick && (cdc->mval[1] != INT_MAX)) {
- if (cdc->xy[1] <= cdc->mval[1]) {
- if ((y_next >= cdc->mval[1])) {
- int ofs = (int)floor(((float)cdc->mval[0] / (float)cdc->cwidth));
-
- /* wrap */
- if (str_len > cdc->console_width)
- ofs += (cdc->console_width * ((int)((((float)(y_next - cdc->mval[1]) / (float)(y_next - cdc->xy[1])) * tot_lines))));
-
- CLAMP(ofs, 0, str_len);
- *cdc->pos_pick += str_len - ofs;
+ if (cdc->pos_pick && cdc->mval[1] != INT_MAX && cdc->xy[1] <= cdc->mval[1]) {
+ if (y_next >= cdc->mval[1]) {
+ int ofs = 0;
+
+ /* wrap */
+ if (tot_lines > 1) {
+ int iofs = (int)((float)(y_next - cdc->mval[1]) / cdc->lheight);
+ ofs += offsets[MIN2(iofs, tot_lines - 1)];
}
- else
- *cdc->pos_pick += str_len + 1;
+
+ /* last part */
+ ofs += txt_utf8_column_to_offset(str + ofs,
+ (int)floor((float)cdc->mval[0] / cdc->cwidth));
+
+ CLAMP(ofs, 0, str_len);
+ *cdc->pos_pick += str_len - ofs;
}
+ else
+ *cdc->pos_pick += str_len + 1;
}
cdc->xy[1] = y_next;
+ MEM_freeN(offsets);
return 1;
}
else if (y_next - cdc->lheight < cdc->ymin) {
@@ -120,15 +164,18 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
/* adjust selection even if not drawing */
if (cdc->sel[0] != cdc->sel[1]) {
- STEP_SEL(-(str_len + 1));
+ console_step_sel(cdc, -(str_len + 1));
}
+ MEM_freeN(offsets);
return 1;
}
if (tot_lines > 1) { /* wrap? */
- const int initial_offset = ((tot_lines - 1) * cdc->console_width);
- const char *line_stride = str + initial_offset; /* advance to the last line and draw it first */
+ const int initial_offset = offsets[tot_lines - 1];
+ size_t len = str_len - initial_offset;
+ const char *s = str + initial_offset;
+ int i;
int sel_orig[2];
copy_v2_v2_int(sel_orig, cdc->sel);
@@ -146,40 +193,42 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
/* last part needs no clipping */
BLF_position(mono, cdc->xy[0], cdc->xy[1], 0);
- BLF_draw(mono, line_stride, str_len - initial_offset);
+ BLF_draw_mono(mono, s, len, cdc->cwidth);
if (cdc->sel[0] != cdc->sel[1]) {
- STEP_SEL(-initial_offset);
+ console_step_sel(cdc, -initial_offset);
// glColor4ub(255, 0, 0, 96); // debug
- console_draw_sel(cdc->sel, cdc->xy, str_len % cdc->console_width, cdc->cwidth, cdc->lheight);
- STEP_SEL(cdc->console_width);
+ console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel);
glColor3ubv(fg);
}
cdc->xy[1] += cdc->lheight;
- line_stride -= cdc->console_width;
-
- for (; line_stride >= str; line_stride -= cdc->console_width) {
+ for (i = tot_lines - 1; i > 0; i--) {
+ len = offsets[i] - offsets[i - 1];
+ s = str + offsets[i - 1];
+
BLF_position(mono, cdc->xy[0], cdc->xy[1], 0);
- BLF_draw(mono, line_stride, cdc->console_width);
+ BLF_draw_mono(mono, s, len, cdc->cwidth);
if (cdc->sel[0] != cdc->sel[1]) {
+ console_step_sel(cdc, len);
// glColor4ub(0, 255, 0, 96); // debug
- console_draw_sel(cdc->sel, cdc->xy, cdc->console_width, cdc->cwidth, cdc->lheight);
- STEP_SEL(cdc->console_width);
+ console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel);
glColor3ubv(fg);
}
cdc->xy[1] += cdc->lheight;
/* check if were out of view bounds */
- if (cdc->xy[1] > cdc->ymax)
+ if (cdc->xy[1] > cdc->ymax) {
+ MEM_freeN(offsets);
return 0;
+ }
}
copy_v2_v2_int(cdc->sel, sel_orig);
- STEP_SEL(-(str_len + 1));
+ console_step_sel(cdc, -(str_len + 1));
}
else { /* simple, no wrap */
@@ -191,7 +240,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
glColor3ubv(fg);
BLF_position(mono, cdc->xy[0], cdc->xy[1], 0);
- BLF_draw(mono, str, str_len);
+ BLF_draw_mono(mono, str, str_len, cdc->cwidth);
if (cdc->sel[0] != cdc->sel[1]) {
int isel[2];
@@ -200,24 +249,25 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
isel[1] = str_len - cdc->sel[0];
// glColor4ub(255, 255, 0, 96); // debug
- console_draw_sel(isel, cdc->xy, str_len, cdc->cwidth, cdc->lheight);
- STEP_SEL(-(str_len + 1));
+ console_draw_sel(str, isel, cdc->xy, str_len, cdc->cwidth, cdc->lheight, bg_sel);
+ console_step_sel(cdc, -(str_len + 1));
}
cdc->xy[1] += cdc->lheight;
- if (cdc->xy[1] > cdc->ymax)
+ if (cdc->xy[1] > cdc->ymax) {
+ MEM_freeN(offsets);
return 0;
+ }
}
+ MEM_freeN(offsets);
return 1;
-#undef STEP_SEL
}
#define CONSOLE_DRAW_MARGIN 4
-#define CONSOLE_DRAW_SCROLL 16
-int textview_draw(TextViewContext *tvc, int draw, int mval[2], void **mouse_pick, int *pos_pick)
+int textview_draw(TextViewContext *tvc, const int draw, int mval[2], void **mouse_pick, int *pos_pick)
{
ConsoleDrawContext cdc = {0};
@@ -241,9 +291,10 @@ int textview_draw(TextViewContext *tvc, int draw, int mval[2], void **mouse_pick
cdc.cwidth = (int)BLF_fixed_width(mono);
assert(cdc.cwidth > 0);
cdc.lheight = tvc->lheight;
- cdc.console_width = (tvc->winx - (CONSOLE_DRAW_SCROLL + CONSOLE_DRAW_MARGIN * 2) ) / cdc.cwidth;
+ /* note, scroll bar must be already subtracted () */
+ cdc.console_width = (tvc->winx - (CONSOLE_DRAW_MARGIN * 2) ) / cdc.cwidth;
CLAMP(cdc.console_width, 1, INT_MAX); /* avoid divide by zero on small windows */
- cdc.winx = tvc->winx - (CONSOLE_DRAW_MARGIN + CONSOLE_DRAW_SCROLL);
+ cdc.winx = tvc->winx - CONSOLE_DRAW_MARGIN;
cdc.ymin = tvc->ymin;
cdc.ymax = tvc->ymax;
cdc.xy = xy;
@@ -263,6 +314,11 @@ int textview_draw(TextViewContext *tvc, int draw, int mval[2], void **mouse_pick
}
if (tvc->begin(tvc)) {
+ unsigned char bg_sel[4] = {0};
+
+ if (draw && tvc->const_colors) {
+ tvc->const_colors(tvc, bg_sel);
+ }
do {
const char *ext_line;
@@ -276,7 +332,11 @@ int textview_draw(TextViewContext *tvc, int draw, int mval[2], void **mouse_pick
tvc->line_get(tvc, &ext_line, &ext_len);
- if (!console_draw_string(&cdc, ext_line, ext_len, (color_flag & TVC_LINE_FG) ? fg : NULL, (color_flag & TVC_LINE_BG) ? bg : NULL)) {
+ if (!console_draw_string(&cdc, ext_line, ext_len,
+ (color_flag & TVC_LINE_FG) ? fg : NULL,
+ (color_flag & TVC_LINE_BG) ? bg : NULL,
+ bg_sel))
+ {
/* when drawing, if we pass v2d->cur.ymax, then quit */
if (draw) {
break; /* past the y limits */
diff --git a/source/blender/editors/space_info/textview.h b/source/blender/editors/space_info/textview.h
index 33fbe556245..653c9b83a50 100644
--- a/source/blender/editors/space_info/textview.h
+++ b/source/blender/editors/space_info/textview.h
@@ -46,6 +46,7 @@ typedef struct TextViewContext {
int (*step)(struct TextViewContext *tvc);
int (*line_get)(struct TextViewContext *tvc, const char **, int *);
int (*line_color)(struct TextViewContext *tvc, unsigned char fg[3], unsigned char bg[3]);
+ void (*const_colors)(struct TextViewContext *tvc, unsigned char bg_sel[4]); /* constant theme colors */
void *iter;
int iter_index;
int iter_char; /* char intex, used for multi-line report display */
@@ -54,7 +55,7 @@ typedef struct TextViewContext {
} TextViewContext;
-int textview_draw(struct TextViewContext *tvc, int draw, int mval[2], void **mouse_pick, int *pos_pick);
+int textview_draw(struct TextViewContext *tvc, const int draw, int mval[2], void **mouse_pick, int *pos_pick);
#define TVC_LINE_FG (1<<0)
#define TVC_LINE_BG (1<<1)
diff --git a/source/blender/editors/space_logic/SConscript b/source/blender/editors/space_logic/SConscript
index e63d88ea5de..e5a19b7f30b 100644
--- a/source/blender/editors/space_logic/SConscript
+++ b/source/blender/editors/space_logic/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/space_logic/logic_buttons.c b/source/blender/editors/space_logic/logic_buttons.c
index e898a1baf74..a55da0e3b2c 100644
--- a/source/blender/editors/space_logic/logic_buttons.c
+++ b/source/blender/editors/space_logic/logic_buttons.c
@@ -145,7 +145,7 @@ void LOGIC_OT_links_cut(wmOperatorType *ot)
{
PropertyRNA *prop;
- ot->name = "Cut links";
+ ot->name = "Cut Links";
ot->idname = "LOGIC_OT_links_cut";
ot->description = "Remove logic brick connections";
diff --git a/source/blender/editors/space_logic/logic_ops.c b/source/blender/editors/space_logic/logic_ops.c
index 74be7c46d26..5f2ecbf1b2b 100644
--- a/source/blender/editors/space_logic/logic_ops.c
+++ b/source/blender/editors/space_logic/logic_ops.c
@@ -54,6 +54,8 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "UI_view2d.h"
+
#include "logic_intern.h"
// temporary new includes for texface functions
@@ -120,7 +122,7 @@ static Object *edit_object_property_get(bContext *C, wmOperator *op)
/* if ob_name is valid try to find the object with this name
* otherwise gets the active object */
- if (BLI_strnlen(ob_name, MAX_NAME) > 0)
+ if (*ob_name)
ob = BLI_findstring(&(CTX_data_main(C)->object), ob_name, offsetof(ID, name) + 2);
else
ob = ED_object_active_context(C);
@@ -248,7 +250,7 @@ static int sensor_remove_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int sensor_remove_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int sensor_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_sensor_invoke_properties(C, op))
return sensor_remove_exec(C, op);
@@ -293,12 +295,13 @@ static int sensor_add_exec(bContext *C, wmOperator *op)
prop = RNA_struct_find_property(&sens_ptr, "type");
RNA_string_get(op->ptr, "name", name);
- if (BLI_strnlen(name, MAX_NAME) < 1) {
+ if (*name) {
+ BLI_strncpy(sens->name, name, sizeof(sens->name));
+ }
+ else {
RNA_property_enum_name(C, &sens_ptr, prop, RNA_property_enum_get(&sens_ptr, prop), &sens_name);
BLI_strncpy(sens->name, sens_name, sizeof(sens->name));
}
- else
- BLI_strncpy(sens->name, name, sizeof(sens->name));
make_unique_prop_names(C, sens->name);
ob->scaflag |= OB_SHOWSENS;
@@ -328,8 +331,10 @@ static void LOGIC_OT_sensor_add(wmOperatorType *ot)
/* properties */
ot->prop = prop = RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, SENS_ALWAYS, "Type", "Type of sensor to add");
RNA_def_enum_funcs(prop, rna_Sensor_type_itemf);
- RNA_def_string(ot->srna, "name", "", MAX_NAME, "Name", "Name of the Sensor to add");
- RNA_def_string(ot->srna, "object", "", MAX_NAME, "Object", "Name of the Object to add the Sensor to");
+ prop = RNA_def_string(ot->srna, "name", "", MAX_NAME, "Name", "Name of the Sensor to add");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_string(ot->srna, "object", "", MAX_NAME, "Object", "Name of the Object to add the Sensor to");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ************* Add/Remove Controller Operator ************* */
@@ -351,7 +356,7 @@ static int controller_remove_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int controller_remove_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int controller_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_controller_invoke_properties(C, op))
return controller_remove_exec(C, op);
@@ -397,12 +402,13 @@ static int controller_add_exec(bContext *C, wmOperator *op)
prop = RNA_struct_find_property(&cont_ptr, "type");
RNA_string_get(op->ptr, "name", name);
- if (BLI_strnlen(name, MAX_NAME) < 1) {
+ if (*name) {
+ BLI_strncpy(cont->name, name, sizeof(cont->name));
+ }
+ else {
RNA_property_enum_name(C, &cont_ptr, prop, RNA_property_enum_get(&cont_ptr, prop), &cont_name);
BLI_strncpy(cont->name, cont_name, sizeof(cont->name));
}
- else
- BLI_strncpy(cont->name, name, sizeof(cont->name));
make_unique_prop_names(C, cont->name);
/* set the controller state mask from the current object state.
@@ -427,6 +433,8 @@ static int controller_add_exec(bContext *C, wmOperator *op)
static void LOGIC_OT_controller_add(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Add Controller";
ot->description = "Add a controller to the active object";
@@ -442,8 +450,10 @@ static void LOGIC_OT_controller_add(wmOperatorType *ot)
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", controller_type_items, CONT_LOGIC_AND, "Type", "Type of controller to add");
- RNA_def_string(ot->srna, "name", "", MAX_NAME, "Name", "Name of the Controller to add");
- RNA_def_string(ot->srna, "object", "", MAX_NAME, "Object", "Name of the Object to add the Controller to");
+ prop = RNA_def_string(ot->srna, "name", "", MAX_NAME, "Name", "Name of the Controller to add");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_string(ot->srna, "object", "", MAX_NAME, "Object", "Name of the Object to add the Controller to");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ************* Add/Remove Actuator Operator ************* */
@@ -465,7 +475,7 @@ static int actuator_remove_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int actuator_remove_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int actuator_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_actuator_invoke_properties(C, op))
return actuator_remove_exec(C, op);
@@ -510,12 +520,13 @@ static int actuator_add_exec(bContext *C, wmOperator *op)
prop = RNA_struct_find_property(&act_ptr, "type");
RNA_string_get(op->ptr, "name", name);
- if (BLI_strnlen(name, MAX_NAME) < 1) {
+ if (*name) {
+ BLI_strncpy(act->name, name, sizeof(act->name));
+ }
+ else {
RNA_property_enum_name(C, &act_ptr, prop, RNA_property_enum_get(&act_ptr, prop), &act_name);
BLI_strncpy(act->name, act_name, sizeof(act->name));
}
- else
- BLI_strncpy(act->name, name, sizeof(act->name));
make_unique_prop_names(C, act->name);
ob->scaflag |= OB_SHOWACT;
@@ -545,8 +556,10 @@ static void LOGIC_OT_actuator_add(wmOperatorType *ot)
/* properties */
ot->prop = prop = RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, CONT_LOGIC_AND, "Type", "Type of actuator to add");
RNA_def_enum_funcs(prop, rna_Actuator_type_itemf);
- RNA_def_string(ot->srna, "name", "", MAX_NAME, "Name", "Name of the Actuator to add");
- RNA_def_string(ot->srna, "object", "", MAX_NAME, "Object", "Name of the Object to add the Actuator to");
+ prop = RNA_def_string(ot->srna, "name", "", MAX_NAME, "Name", "Name of the Actuator to add");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_string(ot->srna, "object", "", MAX_NAME, "Object", "Name of the Object to add the Actuator to");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ************* Move Logic Bricks Operator ************* */
@@ -573,7 +586,7 @@ static int sensor_move_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int sensor_move_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int sensor_move_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_sensor_invoke_properties(C, op)) {
return sensor_move_exec(C, op);
@@ -618,7 +631,7 @@ static int controller_move_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int controller_move_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int controller_move_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_controller_invoke_properties(C, op)) {
return controller_move_exec(C, op);
@@ -663,7 +676,7 @@ static int actuator_move_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int actuator_move_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int actuator_move_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (edit_actuator_invoke_properties(C, op)) {
return actuator_move_exec(C, op);
@@ -701,7 +714,7 @@ static int texface_convert_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-static int texface_convert_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int texface_convert_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
return texface_convert_exec(C, op);
}
@@ -723,6 +736,39 @@ static void LOGIC_OT_texface_convert(wmOperatorType *ot)
}
+/* ************************ view ********************* */
+
+static int logic_view_all_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ ARegion *ar = CTX_wm_region(C);
+ rctf cur_new = ar->v2d.tot;
+ float aspect = BLI_rctf_size_y(&ar->v2d.cur) / BLI_rctf_size_x(&ar->v2d.cur);
+
+ /* force the view2d code to zoom to width, not height */
+ cur_new.ymin = cur_new.ymax - BLI_rctf_size_x(&cur_new) * aspect;
+
+ UI_view2d_smooth_view(C, ar, &cur_new);
+
+ return OPERATOR_FINISHED;
+}
+
+static void LOGIC_OT_view_all(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "View All";
+ ot->idname = "LOGIC_OT_view_all";
+ ot->description = "Resize view so you can see all logic bricks";
+
+ /* api callbacks */
+ ot->exec = logic_view_all_exec;
+ ot->poll = ED_operator_logic_active;
+
+ /* flags */
+ ot->flag = 0;
+}
+
+/* ************************* */
+
void ED_operatortypes_logic(void)
{
WM_operatortype_append(LOGIC_OT_sensor_remove);
@@ -735,4 +781,5 @@ void ED_operatortypes_logic(void)
WM_operatortype_append(LOGIC_OT_actuator_add);
WM_operatortype_append(LOGIC_OT_actuator_move);
WM_operatortype_append(LOGIC_OT_texface_convert);
+ WM_operatortype_append(LOGIC_OT_view_all);
}
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index 5a8a7cef119..816ad9960df 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -1006,7 +1006,7 @@ static void draw_sensor_actuator(uiLayout *layout, PointerRNA *ptr)
static void draw_sensor_armature(uiLayout *layout, PointerRNA *ptr)
{
- bSensor *sens = (bSensor*)ptr->data;
+ bSensor *sens = (bSensor *)ptr->data;
bArmatureSensor *as = (bArmatureSensor *) sens->data;
Object *ob = (Object *)ptr->id.data;
PointerRNA pose_ptr, pchan_ptr;
@@ -1476,7 +1476,7 @@ static void draw_actuator_action(uiLayout *layout, PointerRNA *ptr)
static void draw_actuator_armature(uiLayout *layout, PointerRNA *ptr)
{
- bActuator *act = (bActuator*)ptr->data;
+ bActuator *act = (bActuator *)ptr->data;
bArmatureActuator *aa = (bArmatureActuator *) act->data;
Object *ob = (Object *)ptr->id.data;
bConstraint *constraint = NULL;
@@ -1860,6 +1860,25 @@ static void draw_actuator_motion(uiLayout *layout, PointerRNA *ptr)
uiItemR(col, ptr, "integral_coefficient", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
uiItemR(col, ptr, "derivate_coefficient", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
break;
+ case ACT_OBJECT_CHARACTER:
+ split = uiLayoutSplit(layout, 0.9, FALSE);
+ row = uiLayoutRow(split, FALSE);
+ uiItemR(row, ptr, "offset_location", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(split, TRUE);
+ uiItemR(row, ptr, "use_local_location", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
+ uiItemR(row, ptr, "use_add_character_location", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
+
+ split = uiLayoutSplit(layout, 0.9, FALSE);
+ row = uiLayoutRow(split, FALSE);
+ uiItemR(row, ptr, "offset_rotation", 0, NULL, ICON_NONE);
+ uiItemR(split, ptr, "use_local_rotation", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
+
+ split = uiLayoutSplit(layout, 0.9, FALSE);
+ row = uiLayoutRow(split, FALSE);
+ split = uiLayoutSplit(row, 0.7, FALSE);
+ uiItemL(split, "", ICON_NONE); /*Just use this for some spacing */
+ uiItemR(split, ptr, "use_character_jump", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
+ break;
}
}
@@ -2226,6 +2245,7 @@ void logic_buttons(bContext *C, ARegion *ar)
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);
/* loop over all objects and set visible/linked flags for the logic bricks */
for (a=0; a<count; a++) {
@@ -2270,11 +2290,11 @@ void logic_buttons(bContext *C, ARegion *ar)
/* ****************** Controllers ****************** */
- xco= 420; yco= -10; width= 300;
+ 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, UI_GetStyle());
row = uiLayoutRow(layout, TRUE);
- uiDefBlockBut(block, controller_menu, NULL, IFACE_("Controllers"), xco-10, yco, 300, UI_UNIT_Y, ""); /* replace this with uiLayout stuff later */
+ uiDefBlockBut(block, controller_menu, NULL, IFACE_("Controllers"), xco - U.widget_unit / 2, yco, width, UI_UNIT_Y, ""); /* replace this with uiLayout stuff later */
uiItemR(row, &logic_ptr, "show_controllers_selected_objects", 0, IFACE_("Sel"), ICON_NONE);
uiItemR(row, &logic_ptr, "show_controllers_active_object", 0, IFACE_("Act"), ICON_NONE);
@@ -2301,7 +2321,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-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide controllers"));
+ 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"));
RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
uiLayoutSetContextPointer(row, "object", &object_ptr);
@@ -2377,11 +2397,11 @@ void logic_buttons(bContext *C, ARegion *ar)
/* ****************** Sensors ****************** */
- xco= 10; yco= -10; width= 340;
+ 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, UI_GetStyle());
row = uiLayoutRow(layout, TRUE);
- uiDefBlockBut(block, sensor_menu, NULL, IFACE_("Sensors"), xco-10, yco, 300, UI_UNIT_Y, ""); /* replace this with uiLayout stuff later */
+ 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 */
uiItemR(row, &logic_ptr, "show_sensors_selected_objects", 0, IFACE_("Sel"), ICON_NONE);
uiItemR(row, &logic_ptr, "show_sensors_active_object", 0, IFACE_("Act"), ICON_NONE);
@@ -2398,7 +2418,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-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide sensors"));
+ 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"));
RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
uiLayoutSetContextPointer(row, "object", &object_ptr);
@@ -2446,11 +2466,11 @@ void logic_buttons(bContext *C, ARegion *ar)
/* ****************** Actuators ****************** */
- xco= 800; yco= -10; width= 340;
+ 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, UI_GetStyle());
row = uiLayoutRow(layout, TRUE);
- uiDefBlockBut(block, actuator_menu, NULL, IFACE_("Actuators"), xco-10, yco, 300, UI_UNIT_Y, ""); /* replace this with uiLayout stuff later */
+ 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 */
uiItemR(row, &logic_ptr, "show_actuators_selected_objects", 0, IFACE_("Sel"), ICON_NONE);
uiItemR(row, &logic_ptr, "show_actuators_active_object", 0, IFACE_("Act"), ICON_NONE);
@@ -2469,7 +2489,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-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide actuators"));
+ 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"));
RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
uiLayoutSetContextPointer(row, "object", &object_ptr);
@@ -2516,7 +2536,7 @@ void logic_buttons(bContext *C, ARegion *ar)
uiBlockLayoutResolve(block, NULL, &yco); /* stores final height in yco */
height = MIN2(height, yco);
- UI_view2d_totRect_set(&ar->v2d, 1150, height);
+ UI_view2d_totRect_set(&ar->v2d, 57.5f * U.widget_unit, height - U.widget_unit);
/* set the view */
UI_view2d_view_ortho(&ar->v2d);
diff --git a/source/blender/editors/space_logic/space_logic.c b/source/blender/editors/space_logic/space_logic.c
index 4cd53215697..3f3c81f2bfa 100644
--- a/source/blender/editors/space_logic/space_logic.c
+++ b/source/blender/editors/space_logic/space_logic.c
@@ -148,7 +148,7 @@ static SpaceLink *logic_new(const bContext *C)
/* not spacelink itself */
static void logic_free(SpaceLink *UNUSED(sl))
{
-// Spacelogic *slogic= (SpaceLogic*) sl;
+// Spacelogic *slogic= (SpaceLogic *) sl;
// if (slogic->gpd)
// XXX BKE_gpencil_free(slogic->gpd);
@@ -183,7 +183,7 @@ static void logic_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "LOGIC_OT_links_cut", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_menu(keymap, "LOGIC_MT_logicbricks_add", AKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_add_item(keymap, "VIEW2D_OT_reset", HOMEKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "LOGIC_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
}
diff --git a/source/blender/editors/space_nla/SConscript b/source/blender/editors/space_nla/SConscript
index ee010e6856f..18c6392eee9 100644
--- a/source/blender/editors/space_nla/SConscript
+++ b/source/blender/editors/space_nla/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index d75946c4317..b26d1662f6c 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -131,7 +131,6 @@ static int nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA
case ANIMTYPE_SCENE: /* Top-Level Widgets doubling up as datablocks */
case ANIMTYPE_OBJECT:
- case ANIMTYPE_FILLACTD: /* Action Expander */
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
@@ -142,19 +141,32 @@ static int nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA
case ANIMTYPE_DSPART:
case ANIMTYPE_DSMBALL:
case ANIMTYPE_DSARM:
+ case ANIMTYPE_DSMESH:
+ case ANIMTYPE_DSTEX:
+ case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
/* for these channels, we only do AnimData */
- if (ale->id && ale->adt) {
- if (adt_ptr) {
- /* AnimData pointer */
- RNA_pointer_create(ale->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...
- */
- found = -1;
+ if (ale->adt && adt_ptr) {
+ ID *id;
+
+ if ((ale->data == NULL) || (ale->type == ANIMTYPE_OBJECT)) {
+ /* ale->data is not an ID block! */
+ id = ale->id;
}
+ else {
+ /* ale->data is always the proper ID block we need, but ale->id may not be (i.e. for textures) */
+ id = (ID *)ale->data;
+ }
+
+ /* AnimData pointer */
+ 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...
+ */
+ found = -1;
}
}
break;
@@ -247,6 +259,28 @@ static void nla_panel_animdata(const bContext *C, Panel *pa)
block = uiLayoutGetBlock(layout);
uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
+ /* AnimData Source Properties ----------------------------------- */
+
+ /* icon + id-block name of block where AnimData came from to prevent
+ * accidentally changing the properties of the wrong action
+ */
+ if (adt_ptr.id.data) {
+ ID *id = adt_ptr.id.data;
+ PointerRNA id_ptr;
+
+ RNA_id_pointer_create(id, &id_ptr);
+
+ /* ID-block name > AnimData */
+ row = uiLayoutRow(layout, TRUE);
+ uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
+
+ uiItemL(row, id->name + 2, RNA_struct_ui_icon(id_ptr.type)); /* id-block (src) */
+ uiItemL(row, "", VICO_SMALL_TRI_RIGHT_VEC); /* expander */
+ uiItemL(row, IFACE_("Animation Data"), ICON_ANIM_DATA); /* animdata */
+
+ uiItemS(layout);
+ }
+
/* Active Action Properties ------------------------------------- */
/* action */
row = uiLayoutRow(layout, TRUE);
@@ -308,7 +342,7 @@ static void nla_panel_properties(const bContext *C, Panel *pa)
/* strip extents */
column = uiLayoutColumn(layout, TRUE);
- uiItemL(column, "Strip Extents:", ICON_NONE);
+ uiItemL(column, IFACE_("Strip Extents:"), ICON_NONE);
uiItemR(column, &strip_ptr, "frame_start", 0, NULL, ICON_NONE);
uiItemR(column, &strip_ptr, "frame_end", 0, NULL, ICON_NONE);
@@ -343,7 +377,7 @@ static void nla_panel_properties(const bContext *C, Panel *pa)
/* settings */
column = uiLayoutColumn(layout, TRUE);
uiLayoutSetActive(column, !(RNA_boolean_get(&strip_ptr, "use_animated_influence") || RNA_boolean_get(&strip_ptr, "use_animated_time")));
- uiItemL(column, "Playback Settings:", ICON_NONE);
+ uiItemL(column, IFACE_("Playback Settings:"), ICON_NONE);
uiItemR(column, &strip_ptr, "mute", 0, NULL, ICON_NONE);
uiItemR(column, &strip_ptr, "use_reverse", 0, NULL, ICON_NONE);
}
@@ -373,15 +407,15 @@ static void nla_panel_actclip(const bContext *C, Panel *pa)
/* action extents */
// XXX custom names were used here (to avoid the prefixes)... probably not necessary in future?
column = uiLayoutColumn(layout, TRUE);
- uiItemL(column, "Action Extents:", ICON_NONE);
- uiItemR(column, &strip_ptr, "action_frame_start", 0, "Start Frame", ICON_NONE);
- uiItemR(column, &strip_ptr, "action_frame_end", 0, "End Frame", ICON_NONE);
+ uiItemL(column, IFACE_("Action Extents:"), ICON_NONE);
+ uiItemR(column, &strip_ptr, "action_frame_start", 0, IFACE_("Start Frame"), ICON_NONE);
+ uiItemR(column, &strip_ptr, "action_frame_end", 0, IFACE_("End Frame"), ICON_NONE);
uiItemO(column, NULL, ICON_NONE, "NLA_OT_action_sync_length");
/* action usage */
column = uiLayoutColumn(layout, TRUE);
uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "use_animated_time") == FALSE);
- uiItemL(column, "Playback Settings:", ICON_NONE);
+ uiItemL(column, IFACE_("Playback Settings:"), ICON_NONE);
uiItemR(column, &strip_ptr, "scale", 0, NULL, ICON_NONE);
uiItemR(column, &strip_ptr, "repeat", 0, NULL, ICON_NONE);
}
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index 95e75d0e4fc..97a1c583e36 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -48,6 +48,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_screen.h"
+#include "BKE_report.h"
#include "ED_anim_api.h"
#include "ED_keyframes_edit.h"
@@ -140,7 +141,7 @@ static int mouse_nla_channels(bAnimContext *ac, float x, int channel_index, shor
}
else {
Base *b;
-
+
/* deselect all */
/* TODO: should this deselect all other types of channels too? */
for (b = sce->base.first; b; b = b->next) {
@@ -178,6 +179,7 @@ static int mouse_nla_channels(bAnimContext *ac, float x, int channel_index, shor
case ANIMTYPE_DSMESH:
case ANIMTYPE_DSTEX:
case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
/* sanity checking... */
@@ -265,6 +267,7 @@ static int mouse_nla_channels(bAnimContext *ac, float x, int channel_index, shor
{
AnimData *adt = BKE_animdata_from_id(ale->id);
+ /* button area... */
if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) {
if (nlaedit_is_tweakmode_on(ac) == 0) {
/* 'push-down' action - only usable when not in TweakMode */
@@ -280,6 +283,30 @@ static int mouse_nla_channels(bAnimContext *ac, float x, int channel_index, shor
/* changes to NLA-Action occurred */
notifierFlags |= ND_NLA_ACTCHANGE;
}
+ /* OR rest of name... */
+ else {
+ /* NOTE: rest of NLA-Action name doubles for operating on the AnimData block
+ * - this is useful when there's no clear divider, and makes more sense in
+ * the case of users trying to use this to change actions
+ */
+
+ /* select/deselect */
+ if (selectmode == SELECT_INVERT) {
+ /* inverse selection status of this AnimData block only */
+ adt->flag ^= ADT_UI_SELECTED;
+ }
+ else {
+ /* select AnimData block by itself */
+ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+ adt->flag |= ADT_UI_SELECTED;
+ }
+
+ /* set active? */
+ if (adt->flag & ADT_UI_SELECTED)
+ adt->flag |= ADT_UI_ACTIVE;
+
+ notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
+ }
}
break;
@@ -298,7 +325,7 @@ static int mouse_nla_channels(bAnimContext *ac, float x, int channel_index, shor
/* ------------------- */
/* handle clicking */
-static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
bAnimContext ac;
SpaceNla *snla;
@@ -355,7 +382,7 @@ void NLA_OT_channels_click(wmOperatorType *ot)
ot->poll = ED_operator_nla_active;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_UNDO;
/* props */
prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
@@ -368,24 +395,18 @@ void NLA_OT_channels_click(wmOperatorType *ot)
/* ******************** Add Tracks Operator ***************************** */
/* Add NLA Tracks to the same AnimData block as a selected track, or above the selected tracks */
-static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op)
+/* helper - add NLA Tracks alongside existing ones */
+static bool nlaedit_add_tracks_existing(bAnimContext *ac, bool above_sel)
{
- bAnimContext ac;
-
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
-
AnimData *lastAdt = NULL;
- short above_sel = RNA_boolean_get(op->ptr, "above_selected");
+ bool added = false;
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get a list of the AnimData blocks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+ /* get a list of the (selected) NLA Tracks being shown in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* add tracks... */
for (ale = anim_data.first; ale; ale = ale->next) {
@@ -399,11 +420,13 @@ static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op)
if (above_sel) {
/* just add a new one above this one */
add_nlatrack(adt, nlt);
+ added = true;
}
else if ((lastAdt == NULL) || (adt != lastAdt)) {
/* add one track to the top of the owning AnimData's stack, then don't add anymore to this stack */
add_nlatrack(adt, NULL);
lastAdt = adt;
+ added = true;
}
}
}
@@ -411,17 +434,80 @@ static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op)
/* free temp data */
BLI_freelistN(&anim_data);
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+ return added;
+}
+
+/* helper - add NLA Tracks to empty (and selected) AnimData blocks */
+static bool nlaedit_add_tracks_empty(bAnimContext *ac)
+{
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ bool added = false;
- /* done */
- return OPERATOR_FINISHED;
+ /* get a list of the selected AnimData blocks in the NLA */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+
+ /* check if selected AnimData blocks are empty, and add tracks if so... */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ale->adt;
+
+ /* sanity check */
+ BLI_assert(adt->flag & ADT_UI_SELECTED);
+
+ /* ensure it is empty */
+ if (adt->nla_tracks.first == NULL) {
+ /* add new track to this AnimData block then */
+ add_nlatrack(adt, NULL);
+ added = true;
+ }
+ }
+
+ /* cleanup */
+ BLI_freelistN(&anim_data);
+
+ return added;
+}
+
+/* ----- */
+
+static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ bool above_sel = RNA_boolean_get(op->ptr, "above_selected");
+ bool op_done = false;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* perform adding in two passes - existing first so that we don't double up for empty */
+ op_done |= nlaedit_add_tracks_existing(&ac, above_sel);
+ op_done |= nlaedit_add_tracks_empty(&ac);
+
+ /* done? */
+ if (op_done) {
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+ }
+ else {
+ /* failed to add any tracks */
+ BKE_report(op->reports, RPT_WARNING,
+ "Select an existing NLA Track or an empty action line first");
+
+ /* not done */
+ return OPERATOR_CANCELLED;
+ }
}
void NLA_OT_tracks_add(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Add Track(s)";
+ ot->name = "Add Tracks";
ot->idname = "NLA_OT_tracks_add";
ot->description = "Add NLA-Tracks above/after the selected tracks";
@@ -482,11 +568,11 @@ static int nlaedit_delete_tracks_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-void NLA_OT_delete_tracks(wmOperatorType *ot)
+void NLA_OT_tracks_delete(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Delete Tracks";
- ot->idname = "NLA_OT_delete_tracks";
+ ot->idname = "NLA_OT_tracks_delete";
ot->description = "Delete selected NLA-Tracks and the strips they contain";
/* api callbacks */
@@ -498,3 +584,59 @@ void NLA_OT_delete_tracks(wmOperatorType *ot)
}
/* *********************************************** */
+/* AnimData Related Operators */
+
+/* ******************** Include Objects Operator ***************************** */
+/* Include selected objects in NLA Editor, by giving them AnimData blocks
+ * NOTE: This doesn't help for non-object AnimData, where we do not have any effective
+ * selection mechanism in place. Unfortunately, this means that non-object AnimData
+ * once again becomes a second-class citizen here. However, at least for the most
+ * common use case, we now have a nice shortcut again.
+ */
+
+static int nlaedit_objects_add_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ bAnimContext ac;
+ SpaceNla *snla;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* ensure that filters are set so that the effect will be immediately visible */
+ snla = (SpaceNla *)ac.sl;
+ if (snla && snla->ads) {
+ snla->ads->filterflag &= ~ADS_FILTER_NLA_NOACT;
+ }
+
+ /* operate on selected objects... */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
+ {
+ /* ensure that object has AnimData... that's all */
+ BKE_id_add_animdata(&ob->id);
+ }
+ CTX_DATA_END;
+
+ /* set notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+
+ /* done */
+ return OPERATOR_FINISHED;
+}
+
+void NLA_OT_selected_objects_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Include Selected Objects";
+ ot->idname = "NLA_OT_selected_objects_add";
+ ot->description = "Make selected objects appear in NLA Editor by adding Animation Data";
+
+ /* api callbacks */
+ ot->exec = nlaedit_objects_add_exec;
+ ot->poll = nlaop_poll_tweakmode_off;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* *********************************************** */
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index fd999bf2476..56f2ec9ebe1 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -632,7 +632,7 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View
for (ale = anim_data->first; ale; ale = ale->next) {
const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla));
const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla));
- const float ydatac = (float)(y - 7);
+ const float ydatac = (float)(y - 0.35f * U.widget_unit);
/* check if visible */
if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
@@ -695,11 +695,8 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View
special = ICON_ACTION;
- if (act)
- BLI_snprintf(name, sizeof(name), "%s", act->id.name + 2);
- else
- BLI_strncpy(name, "<No Action>", sizeof(name));
-
+ BLI_strncpy(name, act ? act->id.name + 2 : "<No Action>", sizeof(name));
+
/* draw manually still */
do_draw = TRUE;
}
@@ -716,7 +713,7 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View
if (ale->id) {
/* special exception for textures */
if (GS(ale->id->name) == ID_TE) {
- offset = 14;
+ offset = 0.7f * U.widget_unit;
indent = 1;
}
/* special exception for nodetrees */
@@ -727,7 +724,7 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View
case NTREE_SHADER:
{
/* same as for textures */
- offset = 14;
+ offset = 0.7f * U.widget_unit;
indent = 1;
}
break;
@@ -735,19 +732,19 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View
case NTREE_TEXTURE:
{
/* even more */
- offset = 21;
+ offset = U.widget_unit;
indent = 1;
}
break;
default:
/* normal will do */
- offset = 14;
+ offset = 0.7f * U.widget_unit;
break;
}
}
else {
- offset = 14;
+ offset = 0.7f * U.widget_unit;
}
}
else {
@@ -759,7 +756,6 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View
glEnable(GL_BLEND);
/* draw backing strip behind channel name */
- // FIXME: hardcoded colors!!!
if (group == 5) {
float color[4];
@@ -779,7 +775,7 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View
glColor4f(color[0], color[1], color[2], alpha);
}
- offset += 7 * indent;
+ offset += 0.35f * U.widget_unit * indent;
/* only on top two corners, to show that this channel sits on top of the preceding ones */
uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
@@ -797,7 +793,7 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View
UI_ThemeColorShade(TH_HEADER, ((nonSolo == 0) ? 20 : -20));
indent += group;
- offset += 7 * indent;
+ offset += 0.35f * U.widget_unit * indent;
glBegin(GL_QUADS);
glVertex2f(x + offset, yminc);
glVertex2f(x + offset, ymaxc);
@@ -809,14 +805,14 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View
/* draw expand/collapse triangle */
if (expand > 0) {
UI_icon_draw(x + offset, ydatac, expand);
- offset += 17;
+ offset += 0.85f * U.widget_unit;
}
/* draw special icon indicating certain data-types */
if (special > -1) {
/* for normal channels */
UI_icon_draw(x + offset, ydatac, special);
- offset += 17;
+ offset += 0.85f * U.widget_unit;
}
glDisable(GL_BLEND);
@@ -837,19 +833,19 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View
/* draw protect 'lock' */
if (protect > -1) {
- offset = 16;
+ offset = 0.8f * U.widget_unit;
UI_icon_draw((float)(v2d->cur.xmax - offset), ydatac, protect);
}
/* draw mute 'eye' */
if (mute > -1) {
- offset += 16;
+ offset += 0.8f * U.widget_unit;
UI_icon_draw((float)(v2d->cur.xmax - offset), ydatac, mute);
}
/* draw NLA-action line 'status-icons' - only when there's an action */
if ((ale->type == ANIMTYPE_NLAACTION) && (ale->data)) {
- offset += 16;
+ offset += 0.8f * U.widget_unit;
/* now draw some indicator icons */
if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
@@ -862,7 +858,7 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View
fdrawline((float)(v2d->cur.xmax - offset), yminc,
(float)(v2d->cur.xmax - offset), ymaxc);
- offset += 16;
+ offset += 0.8f * U.widget_unit;
/* 'tweaking action' indicator - not a button */
UI_icon_draw((float)(v2d->cur.xmax - offset), ydatac, ICON_EDIT);
@@ -870,11 +866,11 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View
else {
/* XXX firstly draw a little rect to help identify that it's different from the toggles */
glBegin(GL_LINE_LOOP);
- glVertex2f((float)v2d->cur.xmax - offset - 1, y - 7);
- glVertex2f((float)v2d->cur.xmax - offset - 1, y + 9);
- glVertex2f((float)v2d->cur.xmax - 1, y + 9);
- glVertex2f((float)v2d->cur.xmax - 1, y - 7);
- glEnd(); // GL_LINES
+ glVertex2f((float)v2d->cur.xmax - offset - 1, y - 0.35f * U.widget_unit);
+ glVertex2f((float)v2d->cur.xmax - offset - 1, y + 0.45f * U.widget_unit);
+ glVertex2f((float)v2d->cur.xmax - 1, y + 0.45f * U.widget_unit);
+ glVertex2f((float)v2d->cur.xmax - 1, y - 0.35f * U.widget_unit);
+ glEnd();
/* 'push down' icon for normal active-actions */
UI_icon_draw((float)v2d->cur.xmax - offset, ydatac, ICON_FREEZE);
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index 3740c3fae5e..17d403789cf 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -44,6 +44,8 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "BKE_action.h"
#include "BKE_fcurve.h"
#include "BKE_nla.h"
@@ -198,7 +200,7 @@ static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *op)
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt = ale->data;
- /* try entering tweakmode if valid */
+ /* to be sure, just exit tweakmode... */
BKE_nla_tweakmode_exit(adt);
}
@@ -889,7 +891,7 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
-static int nlaedit_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int nlaedit_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
nlaedit_duplicate_exec(C, op);
@@ -1625,7 +1627,7 @@ void NLA_OT_action_sync_length(wmOperatorType *ot)
/* api callbacks */
ot->exec = nlaedit_sync_actlen_exec;
- ot->poll = ED_operator_nla_active; // XXX: is this satisfactory... probably requires a check for active strip...
+ ot->poll = nlaop_poll_tweakmode_off;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1799,7 +1801,7 @@ void NLA_OT_clear_scale(wmOperatorType *ot)
/* defines for snap keyframes tool */
static EnumPropertyItem prop_nlaedit_snap_types[] = {
- {NLAEDIT_SNAP_CFRA, "CFRA", 0, "Current frame", ""},
+ {NLAEDIT_SNAP_CFRA, "CFRA", 0, "Current Frame", ""},
{NLAEDIT_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame", ""}, // XXX as single entry?
{NLAEDIT_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Nearest Second", ""}, // XXX as single entry?
{NLAEDIT_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker", ""},
@@ -1945,13 +1947,13 @@ void NLA_OT_snap(wmOperatorType *ot)
/* ******************** Add F-Modifier Operator *********************** */
/* present a special customised popup menu for this, with some filtering */
-static int nla_fmodifier_add_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
+static int nla_fmodifier_add_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
uiPopupMenu *pup;
uiLayout *layout;
int i;
- pup = uiPupMenuBegin(C, "Add F-Modifier", ICON_NONE);
+ pup = uiPupMenuBegin(C, IFACE_("Add F-Modifier"), ICON_NONE);
layout = uiPupMenuLayout(pup);
/* start from 1 to skip the 'Invalid' modifier type */
@@ -2019,8 +2021,9 @@ static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
/* add F-Modifier of specified type to selected, and make it the active one */
fcm = add_fmodifier(&strip->modifiers, type);
- if (fcm)
+ if (fcm) {
set_active_fmodifier(&strip->modifiers, fcm);
+ }
else {
BKE_reportf(op->reports, RPT_ERROR,
"Modifier could not be added to (%s : %s) (see console for details)",
@@ -2099,8 +2102,10 @@ static int nla_fmodifier_copy_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No F-Modifiers available to be copied");
return OPERATOR_CANCELLED;
}
- else
+ else {
+ /* no updates needed - copy is non-destructive operation */
return OPERATOR_FINISHED;
+ }
}
void NLA_OT_fmodifier_copy(wmOperatorType *ot)
@@ -2154,8 +2159,6 @@ static int nla_fmodifier_paste_exec(bContext *C, wmOperator *op)
/* successful or not? */
if (ok) {
- /* set notifier that things have changed */
- /* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h
index 398d2d5f1f4..98c66d70a75 100644
--- a/source/blender/editors/space_nla/nla_intern.h
+++ b/source/blender/editors/space_nla/nla_intern.h
@@ -54,12 +54,12 @@ void draw_nla_channel_list(bContext *C, bAnimContext *ac, ARegion *ar);
/* nla_select.c */
/* defines for left-right select tool */
-enum {
+enum eNlaEdit_LeftRightSelect_Mode {
NLAEDIT_LRSEL_TEST = -1,
NLAEDIT_LRSEL_NONE,
NLAEDIT_LRSEL_LEFT,
NLAEDIT_LRSEL_RIGHT
-} eNlaEdit_LeftRightSelect_Mode;
+};
/* --- */
@@ -73,12 +73,12 @@ void NLA_OT_click_select(wmOperatorType *ot);
/* defines for snap strips
*/
-enum {
+enum eNlaEdit_Snap_Mode {
NLAEDIT_SNAP_CFRA = 1,
NLAEDIT_SNAP_NEAREST_FRAME,
NLAEDIT_SNAP_NEAREST_SECOND,
NLAEDIT_SNAP_NEAREST_MARKER
-} eNlaEdit_Snap_Mode;
+};
/* --- */
@@ -125,7 +125,9 @@ void NLA_OT_fmodifier_paste(wmOperatorType *ot);
void NLA_OT_channels_click(wmOperatorType *ot);
void NLA_OT_tracks_add(wmOperatorType *ot);
-void NLA_OT_delete_tracks(wmOperatorType *ot);
+void NLA_OT_tracks_delete(wmOperatorType *ot);
+
+void NLA_OT_selected_objects_add(wmOperatorType *ot);
/* **************************************** */
/* nla_ops.c */
diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c
index 54ade829c0d..fb0f11ffd87 100644
--- a/source/blender/editors/space_nla/nla_ops.c
+++ b/source/blender/editors/space_nla/nla_ops.c
@@ -120,7 +120,9 @@ void nla_operatortypes(void)
WM_operatortype_append(NLA_OT_channels_click);
WM_operatortype_append(NLA_OT_tracks_add);
- WM_operatortype_append(NLA_OT_delete_tracks);
+ WM_operatortype_append(NLA_OT_tracks_delete);
+
+ WM_operatortype_append(NLA_OT_selected_objects_add);
/* select */
WM_operatortype_append(NLA_OT_click_select);
@@ -188,8 +190,8 @@ static void nla_keymap_channels(wmKeyMap *keymap)
RNA_boolean_set(kmi->ptr, "above_selected", TRUE);
/* delete tracks */
- WM_keymap_add_item(keymap, "NLA_OT_delete_tracks", XKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "NLA_OT_delete_tracks", DELKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "NLA_OT_tracks_delete", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "NLA_OT_tracks_delete", DELKEY, KM_PRESS, 0, 0);
}
static void nla_keymap_main(wmKeyConfig *keyconf, wmKeyMap *keymap)
diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c
index 97553b7aa56..3e414233add 100644
--- a/source/blender/editors/space_nla/nla_select.c
+++ b/source/blender/editors/space_nla/nla_select.c
@@ -451,7 +451,7 @@ static int nlaedit_select_leftright_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int nlaedit_select_leftright_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int nlaedit_select_leftright_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
bAnimContext ac;
short leftright = RNA_enum_get(op->ptr, "mode");
@@ -613,7 +613,7 @@ static void mouse_nla_strips(bContext *C, bAnimContext *ac, const int mval[2], s
/* ------------------- */
/* handle clicking */
-static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
bAnimContext ac;
/* Scene *scene; */ /* UNUSED */
@@ -660,7 +660,7 @@ void NLA_OT_click_select(wmOperatorType *ot)
ot->poll = ED_operator_nla_active;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_UNDO;
/* properties */
prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt
index 996c6fb530f..3803f899ccc 100644
--- a/source/blender/editors/space_node/CMakeLists.txt
+++ b/source/blender/editors/space_node/CMakeLists.txt
@@ -52,6 +52,7 @@ set(SRC
node_relationships.c
node_select.c
node_templates.c
+ node_toolbar.c
node_view.c
space_node.c
diff --git a/source/blender/editors/space_node/SConscript b/source/blender/editors/space_node/SConscript
index 7e311b1329d..70837fa766a 100644
--- a/source/blender/editors/space_node/SConscript
+++ b/source/blender/editors/space_node/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 381393eb725..a413eb47140 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -43,18 +43,23 @@
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BKE_scene.h"
#include "BKE_tracking.h"
#include "BLF_api.h"
#include "BLF_translation.h"
+#include "NOD_texture.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "BLF_translation.h"
#include "MEM_guardedalloc.h"
#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "ED_node.h"
@@ -68,190 +73,136 @@
#include "IMB_imbuf_types.h"
#include "node_intern.h" /* own include */
+#include "NOD_composite.h"
+#include "NOD_shader.h"
+#include "NOD_texture.h"
-/* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */
+/* ****************** MENU FUNCTIONS ***************** */
-static void node_sync_cb(bContext *UNUSED(C), void *snode_v, void *node_v)
+static void node_add_menu_class(bContext *C, uiLayout *layout, void *arg_nodeclass)
{
- SpaceNode *snode = snode_v;
+ Scene *scene = CTX_data_scene(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree;
+ int nodeclass = GET_INT_FROM_POINTER(arg_nodeclass);
+ int event, compatibility = 0;
- if (snode->treetype == NTREE_SHADER) {
- nodeShaderSynchronizeID(node_v, 1);
- // allqueue(REDRAWBUTSSHADING, 0);
+ ntree = snode->nodetree;
+
+ if (!ntree) {
+ uiItemS(layout);
+ return;
}
-}
-static void node_socket_button_label(const bContext *UNUSED(C), uiBlock *block,
- bNodeTree *UNUSED(ntree), bNode *UNUSED(node), bNodeSocket *sock,
- const char *UNUSED(name), int x, int y, int width)
-{
- uiDefBut(block, LABEL, 0, IFACE_(sock->name), x, y, width, NODE_DY, NULL, 0, 0, 0, 0, "");
-}
-
-static void node_socket_button_default(const bContext *C, uiBlock *block,
- bNodeTree *ntree, bNode *node, bNodeSocket *sock,
- const char *name, int x, int y, int width)
-{
- if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
- node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
- else {
+ if (ntree->type == NTREE_SHADER) {
+ if (BKE_scene_use_new_shading_nodes(scene))
+ compatibility = NODE_NEW_SHADING;
+ else
+ compatibility = NODE_OLD_SHADING;
+ }
+
+ if (nodeclass == NODE_CLASS_GROUP) {
+ Main *bmain = CTX_data_main(C);
+ bNodeTree *ngroup;
+ const char *ngroup_type, *node_type;
PointerRNA ptr;
- uiBut *bt;
-
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
- bt = uiDefButR(block, NUM, B_NODE_EXEC, IFACE_(name),
- x, y + 1, width, NODE_DY - 2,
- &ptr, "default_value", 0, 0, 0, -1, -1, NULL);
- if (node)
- uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
+ NODE_TYPES_BEGIN(ntype)
+ if (ntype->nclass != nodeclass || !ntype->ui_name)
+ continue;
+ if (!ntype->poll(ntype, ntree))
+ continue;
+
+ switch (ntree->type) {
+ case NTREE_COMPOSIT:
+ ngroup_type = "CompositorNodeTree";
+ node_type = "CompositorNodeGroup";
+ break;
+ case NTREE_SHADER:
+ ngroup_type = "ShaderNodeTree";
+ node_type = "ShaderNodeGroup";
+ break;
+ case NTREE_TEXTURE:
+ ngroup_type = "TextureNodeTree";
+ node_type = "TextureNodeGroup";
+ break;
+ }
+
+ ptr = uiItemFullO(layout, "NODE_OT_group_make", "New Group", ntype->ui_icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_string_set(&ptr, "node_type", node_type);
+
+ uiItemS(layout);
+
+ for (ngroup = bmain->nodetree.first, event = 0; ngroup; ngroup = ngroup->id.next, ++event) {
+ /* only use group trees of the right type */
+ if (STRNEQ(ngroup->idname, ngroup_type))
+ continue;
+ if (!nodeGroupPoll(ntree, ngroup))
+ continue;
+
+ ptr = uiItemFullO(layout, "NODE_OT_add_group_node", ngroup->id.name + 2, ntype->ui_icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_string_set(&ptr, "type", ntype->idname);
+ RNA_string_set(&ptr, "grouptree", ngroup->id.name + 2);
+ }
+ NODE_TYPES_END
+ }
+ else if (nodeclass == NODE_DYNAMIC) {
+ /* disabled */
}
-}
-
-static void node_socket_button_string(const bContext *C, uiBlock *block,
- bNodeTree *ntree, bNode *node, bNodeSocket *sock,
- const char *name, int x, int y, int width)
-{
- if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
- node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
else {
PointerRNA ptr;
- uiBut *bt;
-
- SpaceNode *snode = CTX_wm_space_node(C);
- const char *ui_name = IFACE_(name);
- float slen;
-
- UI_ThemeColor(TH_TEXT);
- slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect_sqrt;
- while (slen > (width * 0.5f) && *ui_name) {
- ui_name = BLI_str_find_next_char_utf8(ui_name, NULL);
- slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect_sqrt;
- }
-
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
-
- if (name[0] == '\0')
- slen = 0.0;
-
- bt = uiDefButR(block, TEX, B_NODE_EXEC, "",
- x, y + 1, width - slen, NODE_DY - 2,
- &ptr, "default_value", 0, 0, 0, -1, -1, "");
- if (node)
- uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
- if (slen > 0.0f)
- uiDefBut(block, LABEL, 0, IFACE_(name), x + (width - slen), y + 2, slen, NODE_DY - 2, NULL, 0, 0, 0, 0, "");
+ NODE_TYPES_BEGIN(ntype)
+ if (ntype->nclass != nodeclass || !ntype->ui_name)
+ continue;
+ if (!ntype->poll(ntype, ntree))
+ continue;
+ if (compatibility && (ntype->compatibility & compatibility) == 0)
+ continue;
+
+ ptr = uiItemFullO(layout, "NODE_OT_add_node", IFACE_(ntype->ui_name), ntype->ui_icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_string_set(&ptr, "type", ntype->idname);
+ NODE_TYPES_END
}
}
-typedef struct SocketComponentMenuArgs {
- PointerRNA ptr;
- int x, y, width;
- uiButHandleFunc cb;
- void *arg1, *arg2;
-} SocketComponentMenuArgs;
-/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
-static uiBlock *socket_component_menu(bContext *C, ARegion *ar, void *args_v)
+static void node_add_menu_foreach_class_cb(void *calldata, int nclass, const char *name)
{
- SocketComponentMenuArgs *args = (SocketComponentMenuArgs *)args_v;
- uiBlock *block;
- uiLayout *layout;
-
- block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
- uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN);
-
- layout = uiLayoutColumn(uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
- args->x, args->y + 2, args->width, NODE_DY, UI_GetStyle()), FALSE);
-
- uiItemR(layout, &args->ptr, "default_value", UI_ITEM_R_EXPAND, "", ICON_NONE);
-
- return block;
+ uiLayout *layout = calldata;
+ uiItemMenuF(layout, IFACE_(name), 0, node_add_menu_class, SET_INT_IN_POINTER(nclass));
}
-static void node_socket_button_components(const bContext *C, uiBlock *block,
- bNodeTree *ntree, bNode *node, bNodeSocket *sock,
- const char *name, int x, int y, int width)
+
+static void node_add_menu_default(const bContext *C, uiLayout *layout, bNodeTree *ntree)
{
- if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
- node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
- else {
- PointerRNA ptr;
- SocketComponentMenuArgs *args;
-
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
-
- args = MEM_callocN(sizeof(SocketComponentMenuArgs), "SocketComponentMenuArgs");
-
- args->ptr = ptr;
- args->x = x;
- args->y = y;
- args->width = width;
- args->cb = node_sync_cb;
- args->arg1 = CTX_wm_space_node(C);
- args->arg2 = node;
-
- uiDefBlockButN(block, socket_component_menu, args, IFACE_(name), x, y + 1, width, NODE_DY - 2, "");
- }
+ Scene *scene = CTX_data_scene(C);
+
+ if (ntree->typeinfo->foreach_nodeclass)
+ ntree->typeinfo->foreach_nodeclass(scene, layout, node_add_menu_foreach_class_cb);
}
-static void node_socket_button_color(const bContext *C, uiBlock *block,
- bNodeTree *ntree, bNode *node, bNodeSocket *sock,
- const char *name, int x, int y, int width)
+/* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */
+
+static void node_socket_button_label(bContext *UNUSED(C), uiLayout *layout, PointerRNA *ptr, PointerRNA *UNUSED(node_ptr))
{
- if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
- node_socket_button_label(C, block, ntree, node, sock, IFACE_(name), x, y, width);
- else {
- PointerRNA ptr;
- uiBut *bt;
- int labelw = width - 40;
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
-
- bt = uiDefButR(block, COLOR, B_NODE_EXEC, "",
- x, y + 2, (labelw > 0 ? 40 : width), NODE_DY - 2,
- &ptr, "default_value", 0, 0, 0, -1, -1, NULL);
- if (node)
- uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
-
- if (name[0] != '\0' && labelw > 0)
- uiDefBut(block, LABEL, 0, IFACE_(name), x + 40, y + 2, labelw, NODE_DY - 2, NULL, 0, 0, 0, 0, "");
- }
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ uiItemL(layout, sock->name, 0);
}
-/* standard draw function, display the default input value */
-static void node_draw_input_default(const bContext *C, uiBlock *block,
- bNodeTree *ntree, bNode *node, bNodeSocket *sock,
- const char *name, int x, int y, int width)
+static void node_draw_input_default(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, int linked)
{
- bNodeSocketType *stype = ntreeGetSocketType(sock->type);
- if (stype->buttonfunc)
- stype->buttonfunc(C, block, ntree, node, sock, name, x, y, width);
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ if (linked || (sock->flag & SOCK_HIDE_VALUE))
+ node_socket_button_label(C, layout, ptr, node_ptr);
else
- node_socket_button_label(C, block, ntree, node, sock, IFACE_(name), x, y, width);
+ sock->typeinfo->draw(C, layout, ptr, node_ptr);
}
-static void node_draw_output_default(const bContext *C, uiBlock *block,
- bNodeTree *UNUSED(ntree), bNode *node, bNodeSocket *sock,
- const char *name, int UNUSED(x), int UNUSED(y), int UNUSED(width))
+static void node_draw_output_default(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, int UNUSED(linked))
{
- SpaceNode *snode = CTX_wm_space_node(C);
- const char *ui_name = IFACE_(name);
- float slen;
-
- UI_ThemeColor(TH_TEXT);
- slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect_sqrt;
- while (slen > node->width && *ui_name) {
- ui_name = BLI_str_find_next_char_utf8(ui_name, NULL);
- slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect_sqrt;
- }
-
- if (*ui_name) {
- uiDefBut(block, LABEL, 0, ui_name,
- (int)(sock->locx - slen), (int)(sock->locy - 9.0f),
- (short)slen, (short)NODE_DY,
- NULL, 0, 0, 0, 0, "");
- }
+ node_socket_button_label(C, layout, ptr, node_ptr);
}
+
/* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */
#if 0 /* UNUSED */
@@ -298,25 +249,23 @@ static void node_draw_socket_new(bNodeSocket *sock, float size)
static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
+ bNode *node = ptr->data;
+ /* first output stores value */
+ bNodeSocket *output = node->outputs.first;
PointerRNA sockptr;
- PropertyRNA *prop;
-
- /* first socket stores value */
- prop = RNA_struct_find_property(ptr, "outputs");
- RNA_property_collection_lookup_int(ptr, prop, 0, &sockptr);
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr);
uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE);
}
static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ bNode *node = ptr->data;
+ /* first output stores value */
+ bNodeSocket *output = node->outputs.first;
PointerRNA sockptr;
- PropertyRNA *prop;
-
- /* first socket stores value */
- prop = RNA_struct_find_property(ptr, "outputs");
- RNA_property_collection_lookup_int(ptr, prop, 0, &sockptr);
+ uiLayout *col;
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr);
col = uiLayoutColumn(layout, FALSE);
uiTemplateColorPicker(col, &sockptr, "default_value", 1, 0, 0, 0);
@@ -400,14 +349,15 @@ static void node_buts_curvecol(uiLayout *layout, bContext *UNUSED(C), PointerRNA
static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree*)ptr->id.data;
- bNode *node = (bNode*)ptr->data;
- bNodeSocket *sock = node->outputs.first; /* first socket stores normal */
+ bNode *node = ptr->data;
+ /* first output stores normal */
+ bNodeSocket *output = node->outputs.first;
PointerRNA sockptr;
-
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &sockptr);
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr);
+
uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE);
}
+
#if 0 /* not used in 2.5x yet */
static void node_browse_tex_cb(bContext *C, void *ntree_v, void *node_v)
{
@@ -492,427 +442,6 @@ static int node_resize_area_default(bNode *node, int x, int y)
/* ****************** BUTTON CALLBACKS FOR COMMON NODES ***************** */
-/* width of socket columns in group display */
-#define NODE_GROUP_FRAME 120
-
-/* based on settings in node, sets drawing rect info. each redraw! */
-/* note: this assumes only 1 group at a time is drawn (linked data) */
-/* in node->totr the entire boundbox for the group is stored */
-static void node_update_group(const bContext *C, bNodeTree *ntree, bNode *gnode)
-{
- if (!(gnode->flag & NODE_GROUP_EDIT)) {
- node_update_default(C, ntree, gnode);
- }
- else {
- bNodeTree *ngroup = (bNodeTree *)gnode->id;
- bNode *node;
- bNodeSocket *sock, *gsock;
- float locx, locy;
- rctf *rect = &gnode->totr;
- const float dpi_fac = UI_DPI_ICON_FAC;
- const float node_group_frame = NODE_GROUP_FRAME * dpi_fac;
- const float group_header = 26 * dpi_fac;
- int counter;
- int dy;
-
- /* get "global" coords */
- nodeToView(gnode, 0.0f, 0.0f, &locx, &locy);
-
- /* center them, is a bit of abuse of locx and locy though */
- node_update_nodetree(C, ngroup, locx, locy);
-
- rect->xmin = rect->xmax = locx;
- rect->ymin = rect->ymax = locy;
-
- counter = 1;
- for (node = ngroup->nodes.first; node; node = node->next) {
- if (counter) {
- *rect = node->totr;
- counter = 0;
- }
- else
- BLI_rctf_union(rect, &node->totr);
- }
-
- /* add some room for links to group sockets */
- rect->xmin -= 4 * NODE_DY;
- rect->xmax += 4 * NODE_DY;
- rect->ymin -= NODE_DY;
- rect->ymax += NODE_DY;
-
- /* input sockets */
- dy = BLI_rctf_cent_y(rect) + (NODE_DY * (BLI_countlist(&gnode->inputs) - 1));
- gsock = ngroup->inputs.first;
- sock = gnode->inputs.first;
- while (gsock || sock) {
- while (sock && !sock->groupsock) {
- sock->locx = rect->xmin - node_group_frame;
- sock->locy = dy;
-
- /* prevent long socket lists from growing out of the group box */
- if (dy - 3 * NODE_DYS < rect->ymin)
- rect->ymin = dy - 3 * NODE_DYS;
- if (dy + 3 * NODE_DYS > rect->ymax)
- rect->ymax = dy + 3 * NODE_DYS;
- dy -= 2 * NODE_DY;
-
- sock = sock->next;
- }
- while (gsock && (!sock || sock->groupsock != gsock)) {
- gsock->locx = rect->xmin;
- gsock->locy = dy;
-
- /* prevent long socket lists from growing out of the group box */
- if (dy - 3 * NODE_DYS < rect->ymin)
- rect->ymin = dy - 3 * NODE_DYS;
- if (dy + 3 * NODE_DYS > rect->ymax)
- rect->ymax = dy + 3 * NODE_DYS;
- dy -= 2 * NODE_DY;
-
- gsock = gsock->next;
- }
- while (sock && gsock && sock->groupsock == gsock) {
- gsock->locx = rect->xmin;
- sock->locx = rect->xmin - node_group_frame;
- sock->locy = gsock->locy = dy;
-
- /* prevent long socket lists from growing out of the group box */
- if (dy - 3 * NODE_DYS < rect->ymin)
- rect->ymin = dy - 3 * NODE_DYS;
- if (dy + 3 * NODE_DYS > rect->ymax)
- rect->ymax = dy + 3 * NODE_DYS;
- dy -= 2 * NODE_DY;
-
- sock = sock->next;
- gsock = gsock->next;
- }
- }
-
- /* output sockets */
- dy = BLI_rctf_cent_y(rect) + (NODE_DY * (BLI_countlist(&gnode->outputs) - 1));
- gsock = ngroup->outputs.first;
- sock = gnode->outputs.first;
- while (gsock || sock) {
- while (sock && !sock->groupsock) {
- sock->locx = rect->xmax + node_group_frame;
- sock->locy = dy - NODE_DYS;
-
- /* prevent long socket lists from growing out of the group box */
- if (dy - 3 * NODE_DYS < rect->ymin)
- rect->ymin = dy - 3 * NODE_DYS;
- if (dy + 3 * NODE_DYS > rect->ymax)
- rect->ymax = dy + 3 * NODE_DYS;
- dy -= 2 * NODE_DY;
-
- sock = sock->next;
- }
- while (gsock && (!sock || sock->groupsock != gsock)) {
- gsock->locx = rect->xmax;
- gsock->locy = dy - NODE_DYS;
-
- /* prevent long socket lists from growing out of the group box */
- if (dy - 3 * NODE_DYS < rect->ymin)
- rect->ymin = dy - 3 * NODE_DYS;
- if (dy + 3 * NODE_DYS > rect->ymax)
- rect->ymax = dy + 3 * NODE_DYS;
- dy -= 2 * NODE_DY;
-
- gsock = gsock->next;
- }
- while (sock && gsock && sock->groupsock == gsock) {
- gsock->locx = rect->xmax;
- sock->locx = rect->xmax + node_group_frame;
- sock->locy = gsock->locy = dy - NODE_DYS;
-
- /* prevent long socket lists from growing out of the group box */
- if (dy - 3 * NODE_DYS < rect->ymin)
- rect->ymin = dy - 3 * NODE_DYS;
- if (dy + 3 * NODE_DYS > rect->ymax)
- rect->ymax = dy + 3 * NODE_DYS;
- dy -= 2 * NODE_DY;
-
- sock = sock->next;
- gsock = gsock->next;
- }
- }
-
- /* Set the block bounds to clip mouse events from underlying nodes.
- * Add margin for header and input/output columns.
- */
- uiExplicitBoundsBlock(gnode->block,
- rect->xmin - node_group_frame,
- rect->ymin,
- rect->xmax + node_group_frame,
- rect->ymax + group_header);
- }
-}
-
-static void update_group_input_cb(bContext *UNUSED(C), void *UNUSED(snode_v), void *ngroup_v)
-{
- bNodeTree *ngroup = (bNodeTree *)ngroup_v;
-
- ngroup->update |= NTREE_UPDATE_GROUP_IN;
- ntreeUpdateTree(ngroup);
-}
-
-static void update_group_output_cb(bContext *UNUSED(C), void *UNUSED(snode_v), void *ngroup_v)
-{
- bNodeTree *ngroup = (bNodeTree *)ngroup_v;
-
- ngroup->update |= NTREE_UPDATE_GROUP_OUT;
- ntreeUpdateTree(ngroup);
-}
-
-static void draw_group_socket_name(SpaceNode *snode, bNode *gnode, bNodeSocket *sock,
- int in_out, float xoffset, float yoffset, short width, short height)
-{
- if (sock->flag & SOCK_DYNAMIC) {
- bNodeTree *ngroup = (bNodeTree *)gnode->id;
- uiBut *but;
- but = uiDefBut(gnode->block, TEX, 0, "",
- sock->locx + xoffset, sock->locy + 1 + yoffset, width, height,
- sock->name, 0, sizeof(sock->name), 0, 0, "");
- if (in_out == SOCK_IN)
- uiButSetFunc(but, update_group_input_cb, snode, ngroup);
- else
- uiButSetFunc(but, update_group_output_cb, snode, ngroup);
- }
- else {
- const char *ui_name = IFACE_(sock->name);
- uiDefBut(gnode->block, LABEL, 0, ui_name,
- sock->locx + xoffset, sock->locy + 1 + yoffset, width, height,
- NULL, 0, 0, 0, 0, "");
- }
-}
-
-static void draw_group_socket(const bContext *C, SpaceNode *snode, bNodeTree *ntree, bNode *gnode,
- bNodeSocket *sock, bNodeSocket *gsock, int index, int in_out)
-{
- const float dpi_fac = UI_DPI_ICON_FAC;
- bNodeTree *ngroup = (bNodeTree *)gnode->id;
- bNodeSocketType *stype = ntreeGetSocketType(gsock ? gsock->type : sock->type);
- uiBut *bt;
- float offset;
- int draw_value;
- const float node_group_frame = NODE_GROUP_FRAME * dpi_fac;
- const float socket_size = NODE_SOCKSIZE * dpi_fac;
- const float arrowbutw = 0.8f * UI_UNIT_X;
- const short co_text_w = 72 * dpi_fac;
- const float co_margin = 6.0f * dpi_fac;
- /* layout stuff for buttons on group left frame */
- const float colw = 0.6f * node_group_frame;
- const float col1 = co_margin - node_group_frame;
- const float col2 = col1 + colw + co_margin;
- const float col3 = -arrowbutw - co_margin;
- /* layout stuff for buttons on group right frame */
- const float cor1 = co_margin;
- const float cor2 = cor1 + arrowbutw;
- const float cor3 = cor2 + arrowbutw + co_margin;
-
- /* node and group socket circles */
- if (sock)
- node_socket_circle_draw(ntree, sock, socket_size, sock->flag & SELECT);
- if (gsock)
- node_socket_circle_draw(ngroup, gsock, socket_size, gsock->flag & SELECT);
-
- /* socket name */
- offset = (in_out == SOCK_IN ? col1 : cor3);
- if (!gsock)
- offset += (in_out == SOCK_IN ? node_group_frame : -node_group_frame);
-
- /* draw both name and value button if:
- * 1) input: not internal
- * 2) output: (node type uses const outputs) and (group output is unlinked)
- */
- draw_value = 0;
- switch (in_out) {
- case SOCK_IN:
- draw_value = !(gsock && (gsock->flag & SOCK_INTERNAL));
- break;
- case SOCK_OUT:
- if (gnode->typeinfo->flag & NODE_CONST_OUTPUT)
- draw_value = !(gsock && gsock->link);
- break;
- }
- if (draw_value) {
- /* both name and value buttons */
- if (gsock) {
- draw_group_socket_name(snode, gnode, gsock, in_out, offset, 0, co_text_w, NODE_DY);
- if (stype->buttonfunc)
- stype->buttonfunc(C, gnode->block, ngroup, NULL, gsock, "",
- gsock->locx + offset, gsock->locy - NODE_DY, colw);
- }
- else {
- draw_group_socket_name(snode, gnode, sock, in_out, offset, 0, co_text_w, NODE_DY);
- if (stype->buttonfunc)
- stype->buttonfunc(C, gnode->block, ngroup, NULL, sock, "",
- sock->locx + offset, sock->locy - NODE_DY, colw);
- }
- }
- else {
- /* only name, no value button */
- if (gsock)
- draw_group_socket_name(snode, gnode, gsock, in_out, offset, -NODE_DYS, co_text_w, NODE_DY);
- else
- draw_group_socket_name(snode, gnode, sock, in_out, offset, -NODE_DYS, co_text_w, NODE_DY);
- }
-
- if (gsock && (gsock->flag & SOCK_DYNAMIC)) {
- /* up/down buttons */
- offset = (in_out == SOCK_IN ? col2 : cor2);
- uiBlockSetDirection(gnode->block, UI_TOP);
- uiBlockBeginAlign(gnode->block);
- bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_up", 0, ICON_TRIA_UP,
- gsock->locx + offset, gsock->locy, arrowbutw, arrowbutw, "");
- if (!gsock->prev || !(gsock->prev->flag & SOCK_DYNAMIC))
- uiButSetFlag(bt, UI_BUT_DISABLED);
- RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
- RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", in_out);
- bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_down", 0, ICON_TRIA_DOWN,
- gsock->locx + offset, gsock->locy - arrowbutw, arrowbutw, arrowbutw, "");
- if (!gsock->next || !(gsock->next->flag & SOCK_DYNAMIC))
- uiButSetFlag(bt, UI_BUT_DISABLED);
- RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
- RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", in_out);
- uiBlockEndAlign(gnode->block);
- uiBlockSetDirection(gnode->block, 0);
-
- /* remove button */
- offset = (in_out == SOCK_IN ? col3 : cor1);
- uiBlockSetEmboss(gnode->block, UI_EMBOSSN);
- bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_remove", 0, ICON_X,
- gsock->locx + offset, gsock->locy - 0.5f * arrowbutw, arrowbutw, arrowbutw, "");
- RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
- RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", in_out);
- uiBlockSetEmboss(gnode->block, UI_EMBOSS);
- }
-}
-
-/* groups are, on creation, centered around 0,0 */
-static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *gnode)
-{
- if (!(gnode->flag & NODE_GROUP_EDIT)) {
- node_draw_default(C, ar, snode, ntree, gnode);
- }
- else {
- bNodeTree *ngroup = (bNodeTree *)gnode->id;
- bNodeSocket *sock, *gsock;
- uiLayout *layout;
- PointerRNA ptr;
- rctf rect = gnode->totr;
- const float dpi_fac = UI_DPI_ICON_FAC;
- const float node_group_frame = NODE_GROUP_FRAME * dpi_fac;
- const float group_header = 26 * dpi_fac;
-
- int index;
-
- /* backdrop header */
- glEnable(GL_BLEND);
- uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
- UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
- uiDrawBox(GL_POLYGON,
- rect.xmin - node_group_frame, rect.ymax,
- rect.xmax + node_group_frame, rect.ymax + group_header, BASIS_RAD);
-
- /* backdrop body */
- UI_ThemeColorShadeAlpha(TH_BACK, -8, -70);
- uiSetRoundBox(UI_CNR_NONE);
- uiDrawBox(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, BASIS_RAD);
-
- /* input column */
- UI_ThemeColorShadeAlpha(TH_BACK, 10, -50);
- uiSetRoundBox(UI_CNR_BOTTOM_LEFT);
- uiDrawBox(GL_POLYGON, rect.xmin - node_group_frame, rect.ymin, rect.xmin, rect.ymax, BASIS_RAD);
-
- /* output column */
- UI_ThemeColorShadeAlpha(TH_BACK, 10, -50);
- uiSetRoundBox(UI_CNR_BOTTOM_RIGHT);
- uiDrawBox(GL_POLYGON, rect.xmax, rect.ymin, rect.xmax + node_group_frame, rect.ymax, BASIS_RAD);
-
- /* input column separator */
- glColor4ub(200, 200, 200, 140);
- glBegin(GL_LINES);
- glVertex2f(rect.xmin, rect.ymin);
- glVertex2f(rect.xmin, rect.ymax);
- glEnd();
-
- /* output column separator */
- glColor4ub(200, 200, 200, 140);
- glBegin(GL_LINES);
- glVertex2f(rect.xmax, rect.ymin);
- glVertex2f(rect.xmax, rect.ymax);
- glEnd();
-
- /* group node outline */
- uiSetRoundBox(UI_CNR_ALL);
- glColor4ub(200, 200, 200, 140);
- glEnable(GL_LINE_SMOOTH);
- uiDrawBox(GL_LINE_LOOP,
- rect.xmin - node_group_frame, rect.ymin,
- rect.xmax + node_group_frame, rect.ymax + group_header, BASIS_RAD);
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
-
- /* backdrop title */
- UI_ThemeColor(TH_TEXT_HI);
-
- layout = uiBlockLayout(gnode->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
- (int)(rect.xmin + NODE_MARGIN_X), (int)(rect.ymax + (group_header - (2.5f * dpi_fac))),
- min_ii((int)(BLI_rctf_size_x(&rect) - 18.0f), node_group_frame + 20), group_header, UI_GetStyle());
- RNA_pointer_create(&ntree->id, &RNA_Node, gnode, &ptr);
- uiTemplateIDBrowse(layout, (bContext *)C, &ptr, "node_tree", NULL, NULL, NULL);
- uiBlockLayoutResolve(gnode->block, NULL, NULL);
-
- /* draw the internal tree nodes and links */
- node_draw_nodetree(C, ar, snode, ngroup);
-
- /* group sockets */
- gsock = ngroup->inputs.first;
- sock = gnode->inputs.first;
- index = 0;
- while (gsock || sock) {
- while (sock && !sock->groupsock) {
- draw_group_socket(C, snode, ntree, gnode, sock, NULL, index, SOCK_IN);
- sock = sock->next;
- }
- while (gsock && (!sock || sock->groupsock != gsock)) {
- draw_group_socket(C, snode, ntree, gnode, NULL, gsock, index, SOCK_IN);
- gsock = gsock->next;
- index++;
- }
- while (sock && gsock && sock->groupsock == gsock) {
- draw_group_socket(C, snode, ntree, gnode, sock, gsock, index, SOCK_IN);
- sock = sock->next;
- gsock = gsock->next;
- index++;
- }
- }
- gsock = ngroup->outputs.first;
- sock = gnode->outputs.first;
- index = 0;
- while (gsock || sock) {
- while (sock && !sock->groupsock) {
- draw_group_socket(C, snode, ntree, gnode, sock, NULL, index, SOCK_OUT);
- sock = sock->next;
- }
- while (gsock && (!sock || sock->groupsock != gsock)) {
- draw_group_socket(C, snode, ntree, gnode, NULL, gsock, index, SOCK_OUT);
- gsock = gsock->next;
- index++;
- }
- while (sock && gsock && sock->groupsock == gsock) {
- draw_group_socket(C, snode, ntree, gnode, sock, gsock, index, SOCK_OUT);
- sock = sock->next;
- gsock = gsock->next;
- index++;
- }
- }
-
- uiEndBlock(C, gnode->block);
- uiDrawBlock(C, gnode->block);
- gnode->block = NULL;
- }
-}
static void node_uifunc_group(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
@@ -925,7 +454,7 @@ static void node_uifunc_group(uiLayout *layout, bContext *C, PointerRNA *ptr)
*/
static void node_update_frame(const bContext *UNUSED(C), bNodeTree *ntree, bNode *node)
{
- const float margin = 30.0f;
+ const float margin = 1.5f * U.widget_unit;
NodeFrame *data = (NodeFrame *)node->storage;
int bbinit;
bNode *tnode;
@@ -933,8 +462,8 @@ static void node_update_frame(const bContext *UNUSED(C), bNodeTree *ntree, bNode
float xmax, ymax;
/* init rect from current frame size */
- nodeToView(node, node->offsetx, node->offsety, &rect.xmin, &rect.ymax);
- nodeToView(node, node->offsetx + node->width, node->offsety - node->height, &rect.xmax, &rect.ymin);
+ node_to_view(node, node->offsetx, node->offsety, &rect.xmin, &rect.ymax);
+ node_to_view(node, node->offsetx + node->width, node->offsety - node->height, &rect.xmax, &rect.ymin);
/* frame can be resized manually only if shrinking is disabled or no children are attached */
data->flag |= NODE_FRAME_RESIZEABLE;
@@ -963,8 +492,8 @@ static void node_update_frame(const bContext *UNUSED(C), bNodeTree *ntree, bNode
}
/* now adjust the frame size from view-space bounding box */
- nodeFromView(node, rect.xmin, rect.ymax, &node->offsetx, &node->offsety);
- nodeFromView(node, rect.xmax, rect.ymin, &xmax, &ymax);
+ node_from_view(node, rect.xmin, rect.ymax, &node->offsetx, &node->offsety);
+ node_from_view(node, rect.xmax, rect.ymin, &xmax, &ymax);
node->width = xmax - node->offsetx;
node->height = -ymax + node->offsety;
@@ -1004,7 +533,8 @@ static void node_draw_frame_label(bNode *node, const float aspect)
BLF_disable(fontid, BLF_ASPECT);
}
-static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *UNUSED(ntree), bNode *node)
+static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode,
+ bNodeTree *UNUSED(ntree), bNode *node, bNodeInstanceKey UNUSED(key))
{
rctf *rct = &node->totr;
int color_id = node_get_colorid(node);
@@ -1101,7 +631,7 @@ static void node_update_reroute(const bContext *UNUSED(C), bNodeTree *UNUSED(ntr
float size = NODE_REROUTE_SIZE;
/* get "global" coords */
- nodeToView(node, 0.0f, 0.0f, &locx, &locy);
+ node_to_view(node, 0.0f, 0.0f, &locx, &locy);
/* reroute node has exactly one input and one output, both in the same place */
nsock = node->outputs.first;
@@ -1119,19 +649,22 @@ static void node_update_reroute(const bContext *UNUSED(C), bNodeTree *UNUSED(ntr
node->totr.ymin = locy - size;
}
-static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode), bNodeTree *ntree, bNode *node)
+static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode),
+ bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key))
{
bNodeSocket *sock;
-#if 0 /* UNUSED */
+ char showname[128]; /* 128 used below */
rctf *rct = &node->totr;
+
+#if 0 /* UNUSED */
float size = NODE_REROUTE_SIZE;
#endif
float socket_size = NODE_SOCKSIZE;
/* skip if out of view */
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) {
-
+ node->totr.ymax < ar->v2d.cur.ymin || node->totr.ymin > ar->v2d.cur.ymax)
+ {
uiEndBlock(C, node->block);
node->block = NULL;
return;
@@ -1164,11 +697,20 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
}
#endif
+ if (node->label[0] != '\0') {
+ /* draw title (node label) */
+ BLI_strncpy(showname, node->label, sizeof(showname));
+ uiDefBut(node->block, LABEL, 0, showname,
+ (int)(rct->xmin - NODE_DYS), (int)(rct->ymax),
+ (short)512, (short)NODE_DY,
+ NULL, 0, 0, 0, 0, NULL);
+ }
+
/* only draw input socket. as they all are placed on the same position.
* highlight also if node itself is selected, since we don't display the node body separately!
*/
for (sock = node->inputs.first; sock; sock = sock->next) {
- node_socket_circle_draw(ntree, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT));
+ node_socket_circle_draw(C, ntree, node, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT));
}
uiEndBlock(C, node->block);
@@ -1195,8 +737,6 @@ static void node_common_set_butfunc(bNodeType *ntype)
switch (ntype->type) {
case NODE_GROUP:
ntype->uifunc = node_uifunc_group;
- ntype->drawfunc = node_draw_group;
- ntype->drawupdatefunc = node_update_group;
break;
case NODE_FRAME:
ntype->drawfunc = node_draw_frame;
@@ -1286,11 +826,11 @@ static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), Poin
uiItemR(row, ptr, "scale", 0, "", ICON_NONE);
row = uiLayoutRow(layout, TRUE);
- uiItemR(row, ptr, "use_min", 0, "Min", ICON_NONE);
+ uiItemR(row, ptr, "use_min", 0, IFACE_("Min"), ICON_NONE);
uiItemR(row, ptr, "min", 0, "", ICON_NONE);
row = uiLayoutRow(layout, TRUE);
- uiItemR(row, ptr, "use_max", 0, "Max", ICON_NONE);
+ uiItemR(row, ptr, "use_max", 0, IFACE_("Max"), ICON_NONE);
uiItemR(row, ptr, "max", 0, "", ICON_NONE);
}
@@ -1481,8 +1021,6 @@ static void node_shader_buts_script_details(uiLayout *layout, bContext *C, Point
static void node_shader_set_butfunc(bNodeType *ntype)
{
switch (ntype->type) {
- /* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */
-
case SH_NODE_MATERIAL:
case SH_NODE_MATERIAL_EXT:
ntype->uifunc = node_shader_buts_material;
@@ -1598,12 +1136,15 @@ static void node_composit_buts_image_details(uiLayout *layout, bContext *C, Poin
node_composit_buts_image(layout, C, ptr);
+ uiItemR(layout, ptr, "use_straight_alpha_output", 0, NULL, 0);
+
if (!node->id)
return;
imaptr = RNA_pointer_get(ptr, "image");
uiTemplateColorspaceSettings(layout, &imaptr, "colorspace_settings");
+ uiItemR(layout, &imaptr, "alpha_mode", 0, NULL, 0);
}
static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -1624,7 +1165,7 @@ static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, Point
if (!node->id) return;
col = uiLayoutColumn(layout, FALSE);
- row = uiLayoutRow(col, FALSE);
+ row = uiLayoutRow(col, TRUE);
uiItemR(row, ptr, "layer", 0, "", ICON_NONE);
prop = RNA_struct_find_property(ptr, "layer");
@@ -1933,9 +1474,9 @@ static void node_composit_buts_hue_sat(uiLayout *layout, bContext *UNUSED(C), Po
static void node_composit_buts_dilateerode(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiItemR(layout, ptr, "type", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE);
- switch (RNA_enum_get(ptr, "type")) {
+ switch (RNA_enum_get(ptr, "mode")) {
case CMP_NODE_DILATEERODE_DISTANCE_THRESH:
uiItemR(layout, ptr, "edge", 0, NULL, ICON_NONE);
break;
@@ -1973,7 +1514,7 @@ static void node_composit_buts_distance_matte(uiLayout *layout, bContext *UNUSED
uiLayout *col, *row;
col = uiLayoutColumn(layout, TRUE);
-
+
uiItemL(layout, IFACE_("Color Space:"), ICON_NONE);
row = uiLayoutRow(layout, FALSE);
uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
@@ -2079,20 +1620,17 @@ static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), Po
}
/* draw function for file output node sockets, displays only sub-path and format, no value button */
-static void node_draw_input_file_output(const bContext *C, uiBlock *block,
- bNodeTree *ntree, bNode *node, bNodeSocket *sock,
- const char *UNUSED(name), int x, int y, int width)
+static void node_draw_input_file_output(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, int UNUSED(linked))
{
- uiLayout *layout, *row;
- PointerRNA nodeptr, inputptr, imfptr;
+ bNodeTree *ntree = ptr->id.data;
+ bNodeSocket *sock = ptr->data;
+ uiLayout *row;
+ PointerRNA inputptr, imfptr;
int imtype;
- int rx, ry;
- RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
- layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, x, y + NODE_DY, width, 20, UI_GetStyle());
row = uiLayoutRow(layout, FALSE);
- imfptr = RNA_pointer_get(&nodeptr, "format");
+ imfptr = RNA_pointer_get(node_ptr, "format");
imtype = RNA_enum_get(&imfptr, "file_format");
if (imtype == R_IMF_IMTYPE_MULTILAYER) {
NodeImageMultiFileSocket *input = sock->storage;
@@ -2104,6 +1642,7 @@ static void node_draw_input_file_output(const bContext *C, uiBlock *block,
NodeImageMultiFileSocket *input = sock->storage;
PropertyRNA *imtype_prop;
const char *imtype_name;
+ uiBlock *block;
RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotFile, input, &inputptr);
uiItemL(row, input->path, ICON_NONE);
@@ -2114,12 +1653,11 @@ static void node_draw_input_file_output(const bContext *C, uiBlock *block,
imtype_prop = RNA_struct_find_property(&imfptr, "file_format");
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);
uiItemL(row, imtype_name, ICON_NONE);
uiBlockSetEmboss(block, UI_EMBOSSN);
}
-
- uiBlockLayoutResolve(block, &rx, &ry);
}
static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
@@ -2153,12 +1691,12 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C
active_index = RNA_int_get(ptr, "active_input_index");
/* using different collection properties if multilayer format is enabled */
if (multilayer) {
- uiTemplateList(col, C, ptr, "layer_slots", ptr, "active_input_index", NULL, 0, 0, 0);
+ uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "layer_slots", ptr, "active_input_index", 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, ptr, "file_slots", ptr, "active_input_index", NULL, 0, 0, 0);
+ uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "file_slots", ptr, "active_input_index", 0, 0, 0);
RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "file_slots"),
active_index, &active_input_ptr);
}
@@ -2369,6 +1907,12 @@ static void node_composit_buts_stabilize2d(uiLayout *layout, bContext *C, Pointe
uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
}
+static void node_composit_buts_translate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "use_relative", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "wrap_axis", 0, NULL, ICON_NONE);
+}
+
static void node_composit_buts_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
@@ -2638,10 +2182,21 @@ static void node_composit_buts_ellipsemask(uiLayout *layout, bContext *UNUSED(C)
uiItemR(layout, ptr, "mask_type", 0, NULL, ICON_NONE);
}
+static void node_composit_buts_composite(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "use_alpha", 0, NULL, ICON_NONE);
+}
+
+static void node_composit_buts_viewer(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "use_alpha", 0, NULL, ICON_NONE);
+}
+
static void node_composit_buts_viewer_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *col;
+ uiItemR(layout, ptr, "use_alpha", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "tile_order", 0, NULL, ICON_NONE);
if (RNA_enum_get(ptr, "tile_order") == 0) {
col = uiLayoutColumn(layout, TRUE);
@@ -2751,8 +2306,6 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN
static void node_composit_set_butfunc(bNodeType *ntype)
{
switch (ntype->type) {
- /* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */
-
case CMP_NODE_IMAGE:
ntype->uifunc = node_composit_buts_image;
ntype->uifuncbut = node_composit_buts_image_details;
@@ -2921,6 +2474,9 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_TRANSFORM:
ntype->uifunc = node_composit_buts_transform;
break;
+ case CMP_NODE_TRANSLATE:
+ ntype->uifunc = node_composit_buts_translate;
+ break;
case CMP_NODE_MOVIEDISTORTION:
ntype->uifunc = node_composit_buts_moviedistortion;
break;
@@ -2946,10 +2502,13 @@ static void node_composit_set_butfunc(bNodeType *ntype)
ntype->uifunc = node_composit_buts_bokehblur;
break;
case CMP_NODE_VIEWER:
- ntype->uifunc = NULL;
+ ntype->uifunc = node_composit_buts_viewer;
ntype->uifuncbut = node_composit_buts_viewer_but;
ntype->uibackdropfunc = node_composit_backdrop_viewer;
break;
+ case CMP_NODE_COMPOSITE:
+ ntype->uifunc = node_composit_buts_composite;
+ break;
case CMP_NODE_MASK:
ntype->uifunc = node_composit_buts_mask;
break;
@@ -2962,8 +2521,6 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_TRACKPOS:
ntype->uifunc = node_composit_buts_trackpos;
break;
- default:
- ntype->uifunc = NULL;
}
}
@@ -3122,81 +2679,223 @@ static void node_texture_set_butfunc(bNodeType *ntype)
/* ******* init draw callbacks for all tree types, only called in usiblender.c, once ************* */
+static void node_property_update_default(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ bNodeTree *ntree = ptr->id.data;
+ ED_node_tag_update_nodetree(bmain, ntree);
+}
+
+static void node_socket_template_properties_update(bNodeType *ntype, bNodeSocketTemplate *stemp)
+{
+ StructRNA *srna = ntype->ext.srna;
+ PropertyRNA *prop = RNA_struct_type_find_property(srna, stemp->identifier);
+
+ if (prop)
+ RNA_def_property_update_runtime(prop, node_property_update_default);
+}
+
+static void node_template_properties_update(bNodeType *ntype)
+{
+ bNodeSocketTemplate *stemp;
+
+ if (ntype->inputs) {
+ for (stemp = ntype->inputs; stemp->type >= 0; ++stemp)
+ node_socket_template_properties_update(ntype, stemp);
+ }
+ if (ntype->outputs) {
+ for (stemp = ntype->outputs; stemp->type >= 0; ++stemp)
+ node_socket_template_properties_update(ntype, stemp);
+ }
+}
+
+static void node_socket_undefined_draw(bContext *UNUSED(C), uiLayout *layout, PointerRNA *UNUSED(ptr), PointerRNA *UNUSED(node_ptr))
+{
+ uiItemL(layout, "Undefined Socket Type", ICON_ERROR);
+}
+
+static void node_socket_undefined_draw_color(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PointerRNA *UNUSED(node_ptr), float *r_color)
+{
+ r_color[0] = 1.0f;
+ r_color[1] = 0.0f;
+ r_color[2] = 0.0f;
+ r_color[3] = 1.0f;
+}
+
+static void node_socket_undefined_interface_draw(bContext *UNUSED(C), uiLayout *layout, PointerRNA *UNUSED(ptr))
+{
+ uiItemL(layout, "Undefined Socket Type", ICON_ERROR);
+}
+
+static void node_socket_undefined_interface_draw_color(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), float *r_color)
+{
+ r_color[0] = 1.0f;
+ r_color[1] = 0.0f;
+ r_color[2] = 0.0f;
+ r_color[3] = 1.0f;
+}
+
void ED_node_init_butfuncs(void)
{
- bNodeTreeType *treetype;
- bNodeType *ntype;
- bNodeSocketType *stype;
- int i;
+ /* Fallback types for undefined tree, nodes, sockets
+ * Defined in blenkernel, but not registered in type hashes.
+ */
+ /*extern bNodeTreeType NodeTreeTypeUndefined;*/
+ extern bNodeType NodeTypeUndefined;
+ extern bNodeSocketType NodeSocketTypeUndefined;
+
+ /* default ui functions */
+ NodeTypeUndefined.drawfunc = node_draw_default;
+ NodeTypeUndefined.drawupdatefunc = node_update_default;
+ NodeTypeUndefined.select_area_func = node_select_area_default;
+ NodeTypeUndefined.tweak_area_func = node_tweak_area_default;
+ NodeTypeUndefined.uifunc = NULL;
+ NodeTypeUndefined.uifuncbut = NULL;
+ NodeTypeUndefined.drawinputfunc = node_draw_input_default;
+ NodeTypeUndefined.drawoutputfunc = node_draw_output_default;
+ NodeTypeUndefined.resize_area_func = node_resize_area_default;
+
+ NodeSocketTypeUndefined.draw = node_socket_undefined_draw;
+ NodeSocketTypeUndefined.draw_color = node_socket_undefined_draw_color;
+ NodeSocketTypeUndefined.interface_draw = node_socket_undefined_interface_draw;
+ NodeSocketTypeUndefined.interface_draw_color = node_socket_undefined_interface_draw_color;
/* node type ui functions */
- for (i = 0; i < NUM_NTREE_TYPES; ++i) {
- treetype = ntreeGetType(i);
- if (treetype) {
- for (ntype = treetype->node_types.first; ntype; ntype = ntype->next) {
- /* default ui functions */
- ntype->drawfunc = node_draw_default;
- ntype->drawupdatefunc = node_update_default;
- ntype->select_area_func = node_select_area_default;
- ntype->tweak_area_func = node_tweak_area_default;
- ntype->uifunc = NULL;
- ntype->uifuncbut = NULL;
- ntype->drawinputfunc = node_draw_input_default;
- ntype->drawoutputfunc = node_draw_output_default;
- ntype->resize_area_func = node_resize_area_default;
-
- node_common_set_butfunc(ntype);
-
- switch (i) {
- case NTREE_COMPOSIT:
- node_composit_set_butfunc(ntype);
- break;
- case NTREE_SHADER:
- node_shader_set_butfunc(ntype);
- break;
- case NTREE_TEXTURE:
- node_texture_set_butfunc(ntype);
- break;
- }
- }
- }
- }
+ NODE_TYPES_BEGIN(ntype)
+ /* default ui functions */
+ ntype->drawfunc = node_draw_default;
+ ntype->drawupdatefunc = node_update_default;
+ ntype->select_area_func = node_select_area_default;
+ ntype->tweak_area_func = node_tweak_area_default;
+ ntype->uifunc = NULL;
+ ntype->uifuncbut = NULL;
+ ntype->drawinputfunc = node_draw_input_default;
+ ntype->drawoutputfunc = node_draw_output_default;
+ ntype->resize_area_func = node_resize_area_default;
+
+ node_common_set_butfunc(ntype);
+
+ node_composit_set_butfunc(ntype);
+ node_shader_set_butfunc(ntype);
+ node_texture_set_butfunc(ntype);
+
+ /* define update callbacks for socket properties */
+ node_template_properties_update(ntype);
+ NODE_TYPES_END
- /* socket type ui functions */
- for (i = 0; i < NUM_SOCKET_TYPES; ++i) {
- stype = ntreeGetSocketType(i);
- if (stype) {
- switch (stype->type) {
- case SOCK_FLOAT:
- case SOCK_INT:
- case SOCK_BOOLEAN:
- stype->buttonfunc = node_socket_button_default;
- break;
- case SOCK_STRING:
- stype->buttonfunc = node_socket_button_string;
- break;
- case SOCK_VECTOR:
- stype->buttonfunc = node_socket_button_components;
- break;
- case SOCK_RGBA:
- stype->buttonfunc = node_socket_button_color;
- break;
- case SOCK_SHADER:
- stype->buttonfunc = node_socket_button_label;
- break;
- default:
- stype->buttonfunc = NULL;
- }
+ /* tree type icons */
+ ntreeType_Composite->ui_icon = ICON_RENDERLAYERS;
+ ntreeType_Composite->draw_add_menu = node_add_menu_default;
+ ntreeType_Shader->ui_icon = ICON_MATERIAL;
+ ntreeType_Shader->draw_add_menu = node_add_menu_default;
+ ntreeType_Texture->ui_icon = ICON_TEXTURE;
+ ntreeType_Texture->draw_add_menu = node_add_menu_default;
+}
+
+void ED_init_custom_node_type(bNodeType *ntype)
+{
+ /* default ui functions */
+ ntype->drawfunc = node_draw_default;
+ ntype->drawupdatefunc = node_update_default;
+ ntype->drawinputfunc = node_draw_input_default;
+ ntype->drawoutputfunc = node_draw_output_default;
+ ntype->resize_area_func = node_resize_area_default;
+ ntype->select_area_func = node_select_area_default;
+ ntype->tweak_area_func = node_tweak_area_default;
+}
+
+void ED_init_custom_node_socket_type(bNodeSocketType *stype)
+{
+ /* default ui functions */
+ stype->draw = node_socket_button_label;
+}
+
+/* maps standard socket integer type to a color */
+static const float std_node_socket_colors[][4] = {
+ {0.63, 0.63, 0.63, 1.0}, /* SOCK_FLOAT */
+ {0.39, 0.39, 0.78, 1.0}, /* SOCK_VECTOR */
+ {0.78, 0.78, 0.16, 1.0}, /* SOCK_RGBA */
+ {0.39, 0.78, 0.39, 1.0}, /* SOCK_SHADER */
+ {0.70, 0.65, 0.19, 1.0}, /* SOCK_BOOLEAN */
+ {0.0, 0.0, 0.0, 1.0}, /*__SOCK_MESH (deprecated) */
+ {0.06, 0.52, 0.15, 1.0}, /* SOCK_INT */
+ {1.0, 1.0, 1.0, 1.0}, /* SOCK_STRING */
+};
+
+/* common color callbacks for standard types */
+static void std_node_socket_draw_color(bContext *UNUSED(C), PointerRNA *ptr, PointerRNA *UNUSED(node_ptr), float *r_color)
+{
+ bNodeSocket *sock = ptr->data;
+ int type = sock->typeinfo->type;
+ copy_v4_v4(r_color, std_node_socket_colors[type]);
+}
+static void std_node_socket_interface_draw_color(bContext *UNUSED(C), PointerRNA *ptr, float *r_color)
+{
+ bNodeSocket *sock = ptr->data;
+ int type = sock->typeinfo->type;
+ copy_v4_v4(r_color, std_node_socket_colors[type]);
+}
+
+static void std_node_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr)
+{
+ bNodeSocket *sock = ptr->data;
+ int type = sock->typeinfo->type;
+ /*int subtype = sock->typeinfo->subtype;*/
+
+ switch (type) {
+ case SOCK_FLOAT:
+ case SOCK_INT:
+ case SOCK_BOOLEAN:
+ uiItemR(layout, ptr, "default_value", 0, sock->name, 0);
+ break;
+ case SOCK_VECTOR:
+ uiTemplateComponentMenu(layout, ptr, "default_value", sock->name);
+ break;
+ case SOCK_RGBA: {
+ uiLayout *row = uiLayoutRow(layout, false);
+ uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
+ /* draw the socket name right of the actual button */
+ uiItemR(row, ptr, "default_value", 0, "", 0);
+ uiItemL(row, sock->name, 0);
+ break;
+ }
+ case SOCK_STRING: {
+ uiLayout *row = uiLayoutRow(layout, true);
+ /* draw the socket name right of the actual button */
+ uiItemR(row, ptr, "default_value", 0, "", 0);
+ uiItemL(row, sock->name, 0);
+ break;
}
+
+ default:
+ node_socket_button_label(C, layout, ptr, node_ptr);
+ break;
}
}
+void ED_init_standard_node_socket_type(bNodeSocketType *stype)
+{
+ stype->draw = std_node_socket_draw;
+ stype->draw_color = std_node_socket_draw_color;
+ stype->interface_draw_color = std_node_socket_interface_draw_color;
+}
+
+static void node_socket_virtual_draw_color(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PointerRNA *UNUSED(node_ptr), float *r_color)
+{
+ /* alpha = 0, empty circle */
+ zero_v4(r_color);
+}
+
+void ED_init_node_socket_type_virtual(bNodeSocketType *stype)
+{
+ stype->draw = node_socket_button_label;
+ stype->draw_color = node_socket_virtual_draw_color;
+}
+
/* ************** Generic drawing ************** */
void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
{
-
- if ((snode->flag & SNODE_BACKDRAW) && snode->treetype == NTREE_COMPOSIT) {
+ if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) {
Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
void *lock;
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
@@ -3265,15 +2964,15 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPixelZoom(snode->zoom, snode->zoom);
- glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
+ glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer);
glPixelZoom(1.0f, 1.0f);
glDisable(GL_BLEND);
}
else {
glPixelZoom(snode->zoom, snode->zoom);
-
- glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
+
+ glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer);
glPixelZoom(1.0f, 1.0f);
}
@@ -3284,6 +2983,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
/** @note draw selected info on backdrop */
if (snode->edittree) {
bNode *node = snode->edittree->nodes.first;
+ rctf *viewer_border = &snode->edittree->viewer_border;
while (node) {
if (node->flag & NODE_SELECT) {
if (node->typeinfo->uibackdropfunc) {
@@ -3292,6 +2992,23 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
}
node = node->next;
}
+
+ if ((snode->edittree->flag & NTREE_VIEWER_BORDER) &&
+ viewer_border->xmin < viewer_border->xmax &&
+ viewer_border->ymin < viewer_border->ymax)
+ {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ setlinestyle(3);
+ cpack(0x4040FF);
+
+ glRectf(x + snode->zoom * viewer_border->xmin * ibuf->x,
+ y + snode->zoom * viewer_border->ymin * ibuf->y,
+ x + snode->zoom * viewer_border->xmax * ibuf->x,
+ y + snode->zoom * viewer_border->ymax * ibuf->y);
+
+ setlinestyle(0);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
}
glMatrixMode(GL_PROJECTION);
@@ -3304,57 +3021,6 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
}
}
-#if 0
-/* note: needs to be userpref or opengl profile option */
-static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode)
-{
-
- draw_nodespace_grid(snode);
-
- if (snode->flag & SNODE_BACKDRAW) {
- Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
- if (ibuf) {
- int x, y;
- float zoom = 1.0;
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
-
- glaDefine2DArea(&sa->winrct);
-
- if (ibuf->x > sa->winx || ibuf->y > sa->winy) {
- float zoomx, zoomy;
- zoomx = (float)sa->winx / ibuf->x;
- zoomy = (float)sa->winy / ibuf->y;
- zoom = min_ff(zoomx, zoomy);
- }
-
- x = (sa->winx - zoom * ibuf->x) / 2 + snode->xof;
- y = (sa->winy - zoom * ibuf->y) / 2 + snode->yof;
-
- glPixelZoom(zoom, zoom);
-
- glColor4f(1.0, 1.0, 1.0, 1.0);
- if (ibuf->rect)
- glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect);
- else if (ibuf->channels == 4)
- glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_FLOAT, ibuf->rect_float);
-
- glPixelZoom(1.0, 1.0);
-
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
- }
-}
-#endif
/* if v2d not NULL, it clips and returns 0 if not visible */
int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol)
@@ -3417,10 +3083,10 @@ int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, floa
vec[2][0] = vec[3][0] - dist;
vec[2][1] = vec[3][1];
}
- if (v2d && MIN4(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > v2d->cur.xmax) {
+ if (v2d && min_ffff(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > v2d->cur.xmax) {
/* clipped */
}
- else if (v2d && MAX4(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) < v2d->cur.xmin) {
+ else if (v2d && max_ffff(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) < v2d->cur.xmin) {
/* clipped */
}
else {
@@ -3532,7 +3198,7 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
glDisable(GL_LINE_SMOOTH);
/* restore previuos linewidth */
- glLineWidth(linew);
+ glLineWidth(1.0f);
}
}
@@ -3618,7 +3284,7 @@ void node_draw_link_straight(View2D *v2d, SpaceNode *snode, bNodeLink *link,
glDisable(GL_LINE_SMOOTH);
/* restore previuos linewidth */
- glLineWidth(linew);
+ glLineWidth(1.0f);
}
#endif
@@ -3637,18 +3303,13 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
do_triple = TRUE;
}
else {
- int cycle = 0;
-
/* going to give issues once... */
if (link->tosock->flag & SOCK_UNAVAIL)
return;
if (link->fromsock->flag & SOCK_UNAVAIL)
return;
- /* check cyclic */
- if (link->fromnode && link->tonode)
- cycle = (link->fromnode->level < link->tonode->level || link->tonode->level == 0xFFF);
- if (!cycle && (link->flag & NODE_LINK_VALID)) {
+ if (link->flag & NODE_LINK_VALID) {
/* special indicated link, on drop-node */
if (link->flag & NODE_LINKFLAG_HILITE) {
th_col1 = th_col2 = TH_ACTIVE;
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index 96ac716f383..fb9e1221c38 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -62,58 +62,63 @@
#include "node_intern.h" /* own include */
-/* can be called from menus too, but they should do own undopush and redraws */
-bNode *node_add_node(SpaceNode *snode, Main *bmain, Scene *scene,
- bNodeTemplate *ntemp, float locx, float locy)
+/* XXX Does some additional initialization on top of nodeAddNode
+ * Can be used with both custom and static nodes, if idname==NULL the static int type will be used instead.
+ * Can be called from menus too, but they should do own undopush and redraws.
+ */
+bNode *node_add_node(const bContext *C, const char *idname, int type, float locx, float locy)
{
- bNode *node = NULL, *gnode;
-
+ SpaceNode *snode = CTX_wm_space_node(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ bNode *node = NULL;
+
node_deselect_all(snode);
-
- node = nodeAddNode(snode->edittree, ntemp);
-
+
+ if (idname)
+ node = nodeAddNode(C, snode->edittree, idname);
+ else
+ node = nodeAddStaticNode(C, snode->edittree, type);
+ BLI_assert(node && node->typeinfo);
+
/* generics */
- if (node) {
- node_select(node);
-
- gnode = node_tree_get_editgroup(snode->nodetree);
- // arbitrary y offset of 60 so its visible
- if (gnode) {
- nodeFromView(gnode, locx, locy + 60.0f, &node->locx, &node->locy);
- }
- else {
- node->locx = locx;
- node->locy = locy + 60.0f;
+ node->locx = locx;
+ node->locy = locy + 60.0f; // arbitrary.. so its visible, (0,0) is top of node
+ nodeSetSelected(node, TRUE);
+
+ /* node location is mapped */
+ locx /= UI_DPI_FAC;
+ locy /= UI_DPI_FAC;
+
+ node->locx = locx;
+ node->locy = locy + 60.0f;
+
+ ntreeUpdateTree(snode->edittree);
+ ED_node_set_active(bmain, snode->edittree, node);
+
+ if (snode->nodetree->type == NTREE_COMPOSIT) {
+ if (ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE)) {
+ node->id = &scene->id;
}
-
- ntreeUpdateTree(snode->edittree);
- ED_node_set_active(bmain, snode->edittree, node);
-
- if (snode->nodetree->type == NTREE_COMPOSIT) {
- if (ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE)) {
- node->id = &scene->id;
- }
- else if (ELEM3(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_MOVIEDISTORTION, CMP_NODE_STABILIZE2D)) {
- node->id = (ID *)scene->clip;
- }
-
- ntreeCompositForceHidden(snode->edittree, scene);
+ else if (ELEM3(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_MOVIEDISTORTION, CMP_NODE_STABILIZE2D)) {
+ node->id = (ID *)scene->clip;
}
-
- if (node->id)
- id_us_plus(node->id);
-
-
- if (snode->flag & SNODE_USE_HIDDEN_PREVIEW)
- node->flag &= ~NODE_PREVIEW;
-
- snode_update(snode, node);
+
+ ntreeCompositForceHidden(snode->edittree, scene);
}
-
+
+ if (node->id)
+ id_us_plus(node->id);
+
+ if (snode->flag & SNODE_USE_HIDDEN_PREVIEW)
+ node->flag &= ~NODE_PREVIEW;
+
+ snode_update(snode, node);
+
if (snode->nodetree->type == NTREE_TEXTURE) {
ntreeTexCheckCyclics(snode->edittree);
}
-
+
return node;
}
@@ -179,9 +184,7 @@ static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, bNodeSocketLi
/* create the reroute node for this cursock */
if (!reroute_node) {
- bNodeTemplate ntemp;
- ntemp.type = NODE_REROUTE;
- reroute_node = nodeAddNode(ntree, &ntemp);
+ reroute_node = nodeAddStaticNode(C, ntree, NODE_REROUTE);
/* add a single link to/from the reroute node to replace multiple links */
if (in_out == SOCK_OUT) {
@@ -203,24 +206,17 @@ static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, bNodeSocketLi
}
add_v2_v2(insert_point, socklink->point);
- ++num_links;
+ num_links++;
}
socklink = socklink->next;
}
if (num_links > 0) {
- bNode *gnode = node_tree_get_editgroup(snode->nodetree);
-
/* average cut point from shared links */
mul_v2_fl(insert_point, 1.0f / num_links);
- if (gnode) {
- nodeFromView(gnode, insert_point[0], insert_point[1], &reroute_node->locx, &reroute_node->locy);
- }
- else {
- reroute_node->locx = insert_point[0];
- reroute_node->locy = insert_point[1];
- }
+ reroute_node->locx = insert_point[0];
+ reroute_node->locy = insert_point[1];
}
return socklink;
@@ -262,6 +258,8 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
output_links.first = output_links.last = NULL;
input_links.first = input_links.last = NULL;
for (link = ntree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
if (add_reroute_intersect_check(link, mcoords, i, insert_point)) {
add_reroute_insert_socket_link(&output_links, link->fromsock, link, insert_point);
add_reroute_insert_socket_link(&input_links, link->tosock, link, insert_point);
@@ -301,8 +299,9 @@ void NODE_OT_add_reroute(wmOperatorType *ot)
{
PropertyRNA *prop;
- ot->name = "Add reroute";
+ ot->name = "Add Reroute";
ot->idname = "NODE_OT_add_reroute";
+ ot->description = "Add a reroute node";
ot->invoke = WM_gesture_lines_invoke;
ot->modal = WM_gesture_lines_modal;
@@ -325,12 +324,10 @@ void NODE_OT_add_reroute(wmOperatorType *ot)
static int node_add_file_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
Image *ima = NULL;
- bNodeTemplate ntemp;
+ int type = 0;
/* check input variables */
if (RNA_struct_property_is_set(op->ptr, "filepath")) {
@@ -362,48 +359,47 @@ static int node_add_file_exec(bContext *C, wmOperator *op)
switch (snode->nodetree->type) {
case NTREE_SHADER:
- ntemp.type = SH_NODE_TEX_IMAGE;
+ type = SH_NODE_TEX_IMAGE;
break;
case NTREE_TEXTURE:
- ntemp.type = TEX_NODE_IMAGE;
+ type = TEX_NODE_IMAGE;
break;
case NTREE_COMPOSIT:
- ntemp.type = CMP_NODE_IMAGE;
+ type = CMP_NODE_IMAGE;
break;
default:
return OPERATOR_CANCELLED;
}
-
+
ED_preview_kill_jobs(C);
-
- node = node_add_node(snode, bmain, scene, &ntemp, snode->cursor[0], snode->cursor[1]);
-
+
+ node = node_add_node(C, NULL, type, snode->cursor[0], snode->cursor[1]);
+
if (!node) {
BKE_report(op->reports, RPT_WARNING, "Could not add an image node");
return OPERATOR_CANCELLED;
}
-
+
node->id = (ID *)ima;
- id_us_plus(node->id);
-
+
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);
-
+
return OPERATOR_FINISHED;
}
-static int node_add_file_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int node_add_file_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
-
+
/* convert mouse coordinates to v2d space */
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
&snode->cursor[0], &snode->cursor[1]);
-
+
if (RNA_struct_property_is_set(op->ptr, "filepath") || RNA_struct_property_is_set(op->ptr, "name"))
return node_add_file_exec(C, op);
else
@@ -430,33 +426,35 @@ void NODE_OT_add_file(wmOperatorType *ot)
RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Datablock name to assign");
}
-
/********************** New node tree operator *********************/
static int new_node_tree_exec(bContext *C, wmOperator *op)
{
- SpaceNode *snode;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ Main *bmain = CTX_data_main(C);
bNodeTree *ntree;
PointerRNA ptr, idptr;
PropertyRNA *prop;
- int treetype;
+ const char *idname;
char treename[MAX_ID_NAME - 2] = "NodeTree";
-
- /* retrieve state */
- snode = CTX_wm_space_node(C);
-
- if (RNA_struct_property_is_set(op->ptr, "type"))
- treetype = RNA_enum_get(op->ptr, "type");
- else
- treetype = snode->treetype;
-
+
+ if (RNA_struct_property_is_set(op->ptr, "type")) {
+ prop = RNA_struct_find_property(op->ptr, "type");
+ RNA_property_enum_identifier(C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &idname);
+ }
+ else if (snode)
+ idname = snode->tree_idname;
+
if (RNA_struct_property_is_set(op->ptr, "name"))
RNA_string_get(op->ptr, "name", treename);
-
- ntree = ntreeAddTree(treename, treetype, 0);
- if (!ntree)
+
+ if (!ntreeTypeFind(idname)) {
+ BKE_reportf(op->reports, RPT_ERROR, "Node tree type %s undefined", idname);
return OPERATOR_CANCELLED;
-
+ }
+
+ ntree = ntreeAddTree(bmain, treename, idname);
+
/* hook into UI */
uiIDContextProperty(C, &ptr, &prop);
@@ -470,29 +468,36 @@ static int new_node_tree_exec(bContext *C, wmOperator *op)
RNA_property_update(C, &ptr, prop);
}
else if (snode) {
- Scene *scene = CTX_data_scene(C);
snode->nodetree = ntree;
-
- ED_node_tree_update(snode, scene);
+
+ ED_node_tree_update(C);
}
-
+
return OPERATOR_FINISHED;
}
+static EnumPropertyItem *new_node_tree_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
+{
+ return rna_node_tree_type_itemf(NULL, NULL, free);
+}
+
void NODE_OT_new_node_tree(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "New Node Tree";
ot->idname = "NODE_OT_new_node_tree";
ot->description = "Create a new node tree";
-
+
/* api callbacks */
ot->exec = new_node_tree_exec;
- ot->poll = ED_operator_node_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "type", nodetree_type_items, NTREE_COMPOSIT, "Tree Type", "");
+
+ prop = RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, 0, "Tree Type", "");
+ RNA_def_enum_funcs(prop, new_node_tree_type_itemf);
RNA_def_string(ot->srna, "name", "NodeTree", MAX_ID_NAME - 2, "Name", "");
}
+
diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c
index da077d93641..efdb7c0d85d 100644
--- a/source/blender/editors/space_node/node_buttons.c
+++ b/source/blender/editors/space_node/node_buttons.c
@@ -160,6 +160,86 @@ static void node_sockets_panel(const bContext *C, Panel *pa)
}
}
+static int node_tree_interface_poll(const bContext *C, PanelType *UNUSED(pt))
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+
+ return (snode && snode->edittree && (snode->edittree->inputs.first || snode->edittree->outputs.first));
+}
+
+static int node_tree_find_active_socket(bNodeTree *ntree, bNodeSocket **r_sock, int *r_in_out)
+{
+ bNodeSocket *sock;
+ for (sock = ntree->inputs.first; sock; sock = sock->next) {
+ if (sock->flag & SELECT) {
+ *r_sock = sock;
+ *r_in_out = SOCK_IN;
+ return TRUE;
+ }
+ }
+ for (sock = ntree->outputs.first; sock; sock = sock->next) {
+ if (sock->flag & SELECT) {
+ *r_sock = sock;
+ *r_in_out = SOCK_OUT;
+ return TRUE;
+ }
+ }
+
+ *r_sock = NULL;
+ *r_in_out = 0;
+ return FALSE;
+}
+
+static void node_tree_interface_panel(const bContext *C, Panel *pa)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = (snode) ? snode->edittree : NULL;
+ bNodeSocket *sock;
+ int in_out;
+ uiLayout *layout = pa->layout, *row, *split, *col;
+ PointerRNA ptr, sockptr, opptr;
+
+ if (!ntree)
+ return;
+
+ RNA_id_pointer_create((ID *)ntree, &ptr);
+
+ node_tree_find_active_socket(ntree, &sock, &in_out);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, sock, &sockptr);
+
+ row = uiLayoutRow(layout, FALSE);
+
+ split = uiLayoutRow(row, TRUE);
+ col = uiLayoutColumn(split, TRUE);
+ uiItemL(col, "Inputs:", ICON_NONE);
+ uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "", &ptr, "inputs", &ptr, "active_input", 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, "Outputs:", ICON_NONE);
+ uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "", &ptr, "outputs", &ptr, "active_output", 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);
+
+ col = uiLayoutColumn(row, TRUE);
+ opptr = uiItemFullO(col, "NODE_OT_tree_socket_move", "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_enum_set(&opptr, "direction", 1);
+ opptr = uiItemFullO(col, "NODE_OT_tree_socket_move", "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_enum_set(&opptr, "direction", 2);
+
+ if (sock) {
+ row = uiLayoutRow(layout, TRUE);
+ uiItemR(row, &sockptr, "name", 0, NULL, ICON_NONE);
+ uiItemO(row, "", ICON_X, "NODE_OT_tree_socket_remove");
+
+ if (sock->typeinfo->interface_draw) {
+ uiItemS(layout);
+ sock->typeinfo->interface_draw((bContext *)C, layout, &sockptr);
+ }
+ }
+}
+
/* ******************* node buttons registration ************** */
void node_buttons_register(ARegionType *art)
@@ -180,10 +260,18 @@ void node_buttons_register(ARegionType *art)
pt->poll = node_sockets_poll;
pt->flag |= PNL_DEFAULT_CLOSED;
BLI_addtail(&art->paneltypes, pt);
-
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype node panel tree interface");
+ strcpy(pt->idname, "NODE_PT_node_tree_interface");
+ strcpy(pt->label, "Interface");
+ 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, "Grease Pencil");
+ pt->draw_header = gpencil_panel_standard_header;
pt->draw = gpencil_panel_standard;
pt->poll = active_nodetree_poll;
BLI_addtail(&art->paneltypes, pt);
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 72461cfb2a8..f1915a82f69 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -29,10 +29,14 @@
* \brief higher level node drawing for the node editor.
*/
+#include "DNA_lamp_types.h"
#include "DNA_node_types.h"
+#include "DNA_material_types.h"
#include "DNA_object_types.h"
-#include "DNA_space_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_world_types.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
@@ -44,6 +48,8 @@
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BLF_api.h"
+
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -52,6 +58,7 @@
#include "ED_node.h"
#include "ED_gpencil.h"
+#include "ED_screen.h"
#include "ED_space_api.h"
#include "UI_resources.h"
@@ -65,25 +72,49 @@
/* XXX interface.h */
extern void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select);
-/* XXX update functions for node editor are a mess, needs a clear concept */
-void ED_node_tree_update(SpaceNode *snode, Scene *scene)
+void ED_node_tree_update(const bContext *C)
{
- snode_set_context(snode, scene);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ snode_set_context(C);
if (snode->nodetree && snode->nodetree->id.us == 0)
snode->nodetree->id.us = 1;
}
-void ED_node_changed_update(ID *id, bNode *node)
+/* id is supposed to contain a node tree */
+static bNodeTree *node_tree_from_ID(ID *id)
{
- bNodeTree *nodetree, *edittree;
- int treetype;
-
- node_tree_from_ID(id, &nodetree, &edittree, &treetype);
+ if (id) {
+ short idtype = GS(id->name);
+
+ switch (idtype) {
+ case ID_NT:
+ return (bNodeTree *)id;
+ case ID_MA:
+ return ((Material *)id)->nodetree;
+ case ID_LA:
+ return ((Lamp *)id)->nodetree;
+ case ID_WO:
+ return ((World *)id)->nodetree;
+ case ID_SCE:
+ return ((Scene *)id)->nodetree;
+ case ID_TE:
+ return ((Tex *)id)->nodetree;
+ }
+ }
+
+ return NULL;
+}
- if (treetype == NTREE_SHADER) {
+void ED_node_tag_update_id(ID *id)
+{
+ bNodeTree *ntree = node_tree_from_ID(id);
+ if (id == NULL)
+ return;
+
+ if (ntree->type == NTREE_SHADER) {
DAG_id_tag_update(id, 0);
-
+
if (GS(id->name) == ID_MA)
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, id);
else if (GS(id->name) == ID_LA)
@@ -91,18 +122,10 @@ void ED_node_changed_update(ID *id, bNode *node)
else if (GS(id->name) == ID_WO)
WM_main_add_notifier(NC_WORLD | ND_WORLD_DRAW, id);
}
- else if (treetype == NTREE_COMPOSIT) {
- if (node)
- nodeUpdate(edittree, node);
- /* don't use NodeTagIDChanged, it gives far too many recomposites for image, scene layers, ... */
-
- node = node_tree_get_editgroup(nodetree);
- if (node)
- nodeUpdateID(nodetree, node->id);
-
+ else if (ntree->type == NTREE_COMPOSIT) {
WM_main_add_notifier(NC_SCENE | ND_NODES, id);
}
- else if (treetype == NTREE_TEXTURE) {
+ else if (ntree->type == NTREE_TEXTURE) {
DAG_id_tag_update(id, 0);
WM_main_add_notifier(NC_TEXTURE | ND_NODES, id);
}
@@ -123,25 +146,17 @@ static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup)
return 0;
}
-typedef struct NodeUpdateCalldata {
- bNodeTree *ntree;
- bNode *node;
-} NodeUpdateCalldata;
-static void node_generic_update_cb(void *calldata, ID *owner_id, bNodeTree *ntree)
-{
- NodeUpdateCalldata *cd = (NodeUpdateCalldata *)calldata;
- /* check if nodetree uses the group stored in calldata */
- if (has_nodetree(ntree, cd->ntree))
- ED_node_changed_update(owner_id, cd->node);
-}
-void ED_node_generic_update(Main *bmain, bNodeTree *ntree, bNode *node)
+void ED_node_tag_update_nodetree(Main *bmain, bNodeTree *ntree)
{
- bNodeTreeType *tti = ntreeGetType(ntree->type);
- NodeUpdateCalldata cd;
- cd.ntree = ntree;
- cd.node = node;
+ if (!ntree)
+ return;
+
/* look through all datablocks, to support groups */
- tti->foreach_nodetree(bmain, &cd, node_generic_update_cb);
+ FOREACH_NODETREE(bmain, tntree, id) {
+ /* check if nodetree uses the group */
+ if (has_nodetree(tntree, ntree))
+ ED_node_tag_update_id(id);
+ } FOREACH_NODETREE_END
if (ntree->type == NTREE_TEXTURE)
ntreeTexCheckCyclics(ntree);
@@ -251,12 +266,12 @@ void ED_node_sort(bNodeTree *ntree)
}
-static void do_node_internal_buttons(bContext *C, void *node_v, int event)
+static void do_node_internal_buttons(bContext *C, void *UNUSED(node_v), int event)
{
if (event == B_NODE_EXEC) {
SpaceNode *snode = CTX_wm_space_node(C);
if (snode && snode->id)
- ED_node_changed_update(snode->id, node_v);
+ ED_node_tag_update_id(snode->id);
}
}
@@ -278,18 +293,35 @@ static void node_uiblocks_init(const bContext *C, bNodeTree *ntree)
}
}
+void node_to_view(struct bNode *node, float x, float y, float *rx, float *ry)
+{
+ nodeToView(node, x, y, rx, ry);
+ *rx *= UI_DPI_FAC;
+ *ry *= UI_DPI_FAC;
+}
+
+void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry)
+{
+ x /= UI_DPI_FAC;
+ y /= UI_DPI_FAC;
+ nodeFromView(node, x, y, rx, ry);
+}
+
+
/* based on settings in node, sets drawing rect info. each redraw! */
static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
{
- uiLayout *layout;
- PointerRNA ptr;
+ uiLayout *layout, *row;
+ PointerRNA nodeptr, sockptr;
bNodeSocket *nsock;
float locx, locy;
float dy;
int buty;
+ RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
+
/* get "global" coords */
- nodeToView(node, 0.0f, 0.0f, &locx, &locy);
+ node_to_view(node, 0.0f, 0.0f, &locx, &locy);
dy = locy;
/* header */
@@ -298,90 +330,126 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
/* little bit space in top */
if (node->outputs.first)
dy -= NODE_DYS / 2;
-
+
/* output sockets */
for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
- if (!nodeSocketIsHidden(nsock)) {
- nsock->locx = locx + node->width;
- nsock->locy = dy - NODE_DYS;
- dy -= NODE_DY;
- }
+ if (nodeSocketIsHidden(nsock))
+ continue;
+
+ 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, UI_GetStyle());
+ /* context pointers for current node and socket */
+ uiLayoutSetContextPointer(layout, "node", &nodeptr);
+ uiLayoutSetContextPointer(layout, "socket", &sockptr);
+
+ /* align output buttons to the right */
+ row = uiLayoutRow(layout, 1);
+ uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
+
+ node->typeinfo->drawoutputfunc((bContext *)C, row, &sockptr, &nodeptr, (nsock->flag & SOCK_IN_USE));
+
+ uiBlockEndAlign(node->block);
+ uiBlockLayoutResolve(node->block, NULL, &buty);
+
+ /* ensure minimum socket height in case layout is empty */
+ buty = MIN2(buty, dy - NODE_DY);
+
+ nsock->locx = locx + NODE_WIDTH(node);
+ /* place the socket circle in the middle of the layout */
+ nsock->locy = 0.5f * (dy + buty);
+
+ dy = buty;
+ if (nsock->next)
+ dy -= NODE_SOCKDY;
}
node->prvr.xmin = locx + NODE_DYS;
- node->prvr.xmax = locx + node->width - NODE_DYS;
+ node->prvr.xmax = locx + NODE_WIDTH(node) - NODE_DYS;
/* preview rect? */
if (node->flag & NODE_PREVIEW) {
- if (node->preview && node->preview->rect) {
- float aspect = 1.0f;
-
- if (node->preview && node->preview->xsize && node->preview->ysize)
- aspect = (float)node->preview->ysize / (float)node->preview->xsize;
+ float aspect = 1.0f;
+
+ if (node->preview_xsize && node->preview_ysize)
+ aspect = (float)node->preview_ysize / (float)node->preview_xsize;
+
+ dy -= NODE_DYS / 2;
+ node->prvr.ymax = dy;
+
+ if (aspect <= 1.0f)
+ node->prvr.ymin = dy - aspect * (NODE_WIDTH(node) - NODE_DY);
+ else {
+ /* width correction of image */
+ /* XXX huh? (ton) */
+ float dx = (NODE_WIDTH(node) - NODE_DYS) - (NODE_WIDTH(node) - NODE_DYS) / aspect;
- dy -= NODE_DYS / 2;
- node->prvr.ymax = dy;
+ node->prvr.ymin = dy - (NODE_WIDTH(node) - NODE_DY);
- if (aspect <= 1.0f)
- node->prvr.ymin = dy - aspect * (node->width - NODE_DY);
- else {
- /* width correction of image */
- float dx = (node->width - NODE_DYS) - (node->width - NODE_DYS) / aspect;
-
- node->prvr.ymin = dy - (node->width - NODE_DY);
-
- node->prvr.xmin += 0.5f * dx;
- node->prvr.xmax -= 0.5f * dx;
- }
-
- dy = node->prvr.ymin - NODE_DYS / 2;
-
- /* make sure that maximums are bigger or equal to minimums */
- if (node->prvr.xmax < node->prvr.xmin) SWAP(float, node->prvr.xmax, node->prvr.xmin);
- if (node->prvr.ymax < node->prvr.ymin) SWAP(float, node->prvr.ymax, node->prvr.ymin);
- }
- else {
- float oldh = BLI_rctf_size_y(&node->prvr);
- if (oldh == 0.0f)
- oldh = 0.6f * node->width - NODE_DY;
- dy -= NODE_DYS / 2;
- node->prvr.ymax = dy;
- node->prvr.ymin = dy - oldh;
- dy = node->prvr.ymin - NODE_DYS / 2;
+ node->prvr.xmin += 0.5f * dx;
+ node->prvr.xmax -= 0.5f * dx;
}
+
+ dy = node->prvr.ymin - NODE_DYS / 2;
+
+ /* make sure that maximums are bigger or equal to minimums */
+ if (node->prvr.xmax < node->prvr.xmin) SWAP(float, node->prvr.xmax, node->prvr.xmin);
+ if (node->prvr.ymax < node->prvr.ymin) SWAP(float, node->prvr.ymax, node->prvr.ymin);
}
/* buttons rect? */
- if ((node->flag & NODE_OPTIONS) && node->typeinfo->uifunc) {
+ /* TODO: NODE_OPTION shall be cleaned up */
+ if (/*(node->flag & NODE_OPTIONS) && */node->typeinfo->uifunc) {
dy -= NODE_DYS / 2;
/* set this for uifunc() that don't use layout engine yet */
node->butr.xmin = 0;
- node->butr.xmax = node->width - 2 * NODE_DYS;
+ node->butr.xmax = NODE_WIDTH(node) - 2 * NODE_DYS;
node->butr.ymin = 0;
node->butr.ymax = 0;
- RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
-
+
layout = uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
- locx + NODE_DYS, dy, node->butr.xmax, NODE_DY, UI_GetStyle());
- uiLayoutSetContextPointer(layout, "node", &ptr);
+ locx + NODE_DYS, dy, node->butr.xmax, 0, UI_GetStyle());
+ uiLayoutSetContextPointer(layout, "node", &nodeptr);
- node->typeinfo->uifunc(layout, (bContext *)C, &ptr);
+ node->typeinfo->uifunc(layout, (bContext *)C, &nodeptr);
uiBlockEndAlign(node->block);
uiBlockLayoutResolve(node->block, NULL, &buty);
-
+
dy = buty - NODE_DYS / 2;
}
/* input sockets */
for (nsock = node->inputs.first; nsock; nsock = nsock->next) {
- if (!nodeSocketIsHidden(nsock)) {
- nsock->locx = locx;
- nsock->locy = dy - NODE_DYS;
- dy -= NODE_DY;
- }
+ if (nodeSocketIsHidden(nsock))
+ continue;
+
+ 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, UI_GetStyle());
+ /* context pointers for current node and socket */
+ uiLayoutSetContextPointer(layout, "node", &nodeptr);
+ uiLayoutSetContextPointer(layout, "socket", &sockptr);
+
+ node->typeinfo->drawinputfunc((bContext *)C, layout, &sockptr, &nodeptr, (nsock->flag & SOCK_IN_USE));
+
+ uiBlockEndAlign(node->block);
+ uiBlockLayoutResolve(node->block, NULL, &buty);
+
+ /* ensure minimum socket height in case layout is empty */
+ buty = MIN2(buty, dy - NODE_DY);
+
+ nsock->locx = locx;
+ /* place the socket circle in the middle of the layout */
+ nsock->locy = 0.5f * (dy + buty);
+
+ dy = buty;
+ if (nsock->next)
+ dy -= NODE_SOCKDY;
}
/* little bit space in end */
@@ -389,7 +457,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
dy -= NODE_DYS / 2;
node->totr.xmin = locx;
- node->totr.xmax = locx + node->width;
+ node->totr.xmax = locx + NODE_WIDTH(node);
node->totr.ymax = locy;
node->totr.ymin = min_ff(dy, locy - 2 * NODE_DY);
@@ -412,7 +480,7 @@ static void node_update_hidden(bNode *node)
int totin = 0, totout = 0, tot;
/* get "global" coords */
- nodeToView(node, 0.0f, 0.0f, &locx, &locy);
+ node_to_view(node, 0.0f, 0.0f, &locx, &locy);
/* calculate minimal radius */
for (nsock = node->inputs.first; nsock; nsock = nsock->next)
@@ -437,8 +505,8 @@ static void node_update_hidden(bNode *node)
for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
if (!nodeSocketIsHidden(nsock)) {
- nsock->locx = node->totr.xmax - hiddenrad + (float)sin(rad) * hiddenrad;
- nsock->locy = node->totr.ymin + hiddenrad + (float)cos(rad) * hiddenrad;
+ nsock->locx = node->totr.xmax - hiddenrad + sinf(rad) * hiddenrad;
+ nsock->locy = node->totr.ymin + hiddenrad + cosf(rad) * hiddenrad;
rad += drad;
}
}
@@ -448,8 +516,8 @@ static void node_update_hidden(bNode *node)
for (nsock = node->inputs.first; nsock; nsock = nsock->next) {
if (!nodeSocketIsHidden(nsock)) {
- nsock->locx = node->totr.xmin + hiddenrad + (float)sin(rad) * hiddenrad;
- nsock->locy = node->totr.ymin + hiddenrad + (float)cos(rad) * hiddenrad;
+ nsock->locx = node->totr.xmin + hiddenrad + sinf(rad) * hiddenrad;
+ nsock->locy = node->totr.ymin + hiddenrad + cosf(rad) * hiddenrad;
rad += drad;
}
}
@@ -484,21 +552,19 @@ int node_tweak_area_default(bNode *node, int x, int y)
int node_get_colorid(bNode *node)
{
- if (node->typeinfo->nclass == NODE_CLASS_INPUT)
- return TH_NODE_IN_OUT;
- if (node->typeinfo->nclass == NODE_CLASS_OUTPUT) {
- if (node->flag & NODE_DO_OUTPUT)
- return TH_NODE_IN_OUT;
- else
- return TH_NODE;
+ switch (node->typeinfo->nclass) {
+ case NODE_CLASS_INPUT: return TH_NODE_IN_OUT;
+ case NODE_CLASS_OUTPUT: return (node->flag & NODE_DO_OUTPUT) ? TH_NODE_IN_OUT : TH_NODE;
+ case NODE_CLASS_CONVERTOR: return TH_NODE_CONVERTOR;
+ case NODE_CLASS_OP_COLOR:
+ case NODE_CLASS_OP_VECTOR:
+ case NODE_CLASS_OP_FILTER: return TH_NODE_OPERATOR;
+ case NODE_CLASS_GROUP: return TH_NODE_GROUP;
+ case NODE_CLASS_INTERFACE: return TH_NODE_INTERFACE;
+ case NODE_CLASS_MATTE: return TH_NODE_MATTE;
+ case NODE_CLASS_DISTORT: return TH_NODE_DISTORT;
+ default: return TH_NODE;
}
- if (node->typeinfo->nclass == NODE_CLASS_CONVERTOR)
- return TH_NODE_CONVERTOR;
- if (ELEM3(node->typeinfo->nclass, NODE_CLASS_OP_COLOR, NODE_CLASS_OP_VECTOR, NODE_CLASS_OP_FILTER))
- return TH_NODE_OPERATOR;
- if (node->typeinfo->nclass == NODE_CLASS_GROUP)
- return TH_NODE_GROUP;
- return TH_NODE;
}
/* note: in cmp_util.c is similar code, for node_compo_pass_on()
@@ -519,7 +585,7 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node)
}
/* this might have some more generic use */
-static void node_circle_draw(float x, float y, float size, char *col, int highlight)
+static void node_circle_draw(float x, float y, float size, float *col, int highlight)
{
/* 16 values of sin function */
static float si[16] = {
@@ -537,12 +603,14 @@ static void node_circle_draw(float x, float y, float size, char *col, int highli
};
int a;
- glColor3ub(col[0], col[1], col[2]);
+ glColor4fv(col);
+ glEnable(GL_BLEND);
glBegin(GL_POLYGON);
for (a = 0; a < 16; a++)
glVertex2f(x + size * si[a], y + size * co[a]);
glEnd();
+ glDisable(GL_BLEND);
if (highlight) {
UI_ThemeColor(TH_TEXT_HI);
@@ -562,66 +630,93 @@ static void node_circle_draw(float x, float y, float size, char *col, int highli
glLineWidth(1.0f);
}
-void node_socket_circle_draw(bNodeTree *UNUSED(ntree), bNodeSocket *sock, float size, int highlight)
+void node_socket_circle_draw(const bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *sock, float size, int highlight)
{
- bNodeSocketType *stype = ntreeGetSocketType(sock->type);
- node_circle_draw(sock->locx, sock->locy, size, stype->ui_color, highlight);
+ PointerRNA ptr, node_ptr;
+ float color[4];
+
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
+ sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color);
+ node_circle_draw(sock->locx, sock->locy, size, color, highlight);
}
/* ************** Socket callbacks *********** */
-/* not a callback */
-static void node_draw_preview(bNodePreview *preview, rctf *prv)
+static void node_draw_preview_background(float tile, rctf *rect)
{
- float xscale = BLI_rctf_size_x(prv) / ((float)preview->xsize);
- float yscale = BLI_rctf_size_y(prv) / ((float)preview->ysize);
- float tile = BLI_rctf_size_x(prv) / 10.0f;
float x, y;
/* draw checkerboard backdrop to show alpha */
glColor3ub(120, 120, 120);
- glRectf(prv->xmin, prv->ymin, prv->xmax, prv->ymax);
+ glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
glColor3ub(160, 160, 160);
- for (y = prv->ymin; y < prv->ymax; y += tile * 2) {
- for (x = prv->xmin; x < prv->xmax; x += tile * 2) {
+ for (y = rect->ymin; y < rect->ymax; y += tile * 2) {
+ for (x = rect->xmin; x < rect->xmax; x += tile * 2) {
float tilex = tile, tiley = tile;
- if (x + tile > prv->xmax)
- tilex = prv->xmax - x;
- if (y + tile > prv->ymax)
- tiley = prv->ymax - y;
+ if (x + tile > rect->xmax)
+ tilex = rect->xmax - x;
+ if (y + tile > rect->ymax)
+ tiley = rect->ymax - y;
glRectf(x, y, x + tilex, y + tiley);
}
}
- for (y = prv->ymin + tile; y < prv->ymax; y += tile * 2) {
- for (x = prv->xmin + tile; x < prv->xmax; x += tile * 2) {
+ for (y = rect->ymin + tile; y < rect->ymax; y += tile * 2) {
+ for (x = rect->xmin + tile; x < rect->xmax; x += tile * 2) {
float tilex = tile, tiley = tile;
- if (x + tile > prv->xmax)
- tilex = prv->xmax - x;
- if (y + tile > prv->ymax)
- tiley = prv->ymax - y;
+ if (x + tile > rect->xmax)
+ tilex = rect->xmax - x;
+ if (y + tile > rect->ymax)
+ tiley = rect->ymax - y;
glRectf(x, y, x + tilex, y + tiley);
}
}
-
- glPixelZoom(xscale, yscale);
+}
+/* not a callback */
+static void node_draw_preview(bNodePreview *preview, rctf *prv)
+{
+ float xrect = BLI_rctf_size_x(prv);
+ float yrect = BLI_rctf_size_y(prv);
+ float xscale = xrect / ((float)preview->xsize);
+ float yscale = yrect / ((float)preview->ysize);
+ float scale;
+ rctf draw_rect;
+
+ /* uniform scale and offset */
+ draw_rect = *prv;
+ if (xscale < yscale) {
+ float offset = 0.5f * (yrect - ((float)preview->ysize) * xscale);
+ draw_rect.ymin += offset;
+ draw_rect.ymax -= offset;
+ scale = xscale;
+ }
+ else {
+ float offset = 0.5f * (xrect - ((float)preview->xsize) * yscale);
+ draw_rect.xmin += offset;
+ draw_rect.xmax -= offset;
+ scale = yscale;
+ }
+
+ node_draw_preview_background(BLI_rctf_size_x(prv) / 10.0f, &draw_rect);
+
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* premul graphics */
glColor4f(1.0, 1.0, 1.0, 1.0);
- glaDrawPixelsTex(prv->xmin, prv->ymin, preview->xsize, preview->ysize, GL_UNSIGNED_BYTE, preview->rect);
+ glPixelZoom(scale, scale);
+ glaDrawPixelsTex(draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect);
+ glPixelZoom(1.0f, 1.0f);
glDisable(GL_BLEND);
- glPixelZoom(1.0f, 1.0f);
UI_ThemeColorShadeAlpha(TH_BACK, -15, +100);
- fdrawbox(prv->xmin, prv->ymin, prv->xmax, prv->ymax);
-
+ fdrawbox(draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax);
}
/* common handle function for operator buttons that need to select the node first */
@@ -654,8 +749,9 @@ void node_draw_shadow(SpaceNode *snode, bNode *node, float radius, float alpha)
}
}
-static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node)
+static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
{
+ bNodeInstanceHash *previews = CTX_data_pointer_get(C, "node_previews").data;
bNodeSocket *sock;
rctf *rct = &node->totr;
float iconofs;
@@ -665,9 +761,9 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
char showname[128]; /* 128 used below */
View2D *v2d = &ar->v2d;
- /* hurmf... another candidate for callback, have to see how this works first */
- if (node->id && node->block && snode->treetype == NTREE_SHADER)
- nodeShaderSynchronizeID(node, 0);
+ /* XXX hack: copy values from linked ID data where displayed as sockets */
+ if (node->block)
+ nodeSynchronizeID(node, false);
/* skip if out of view */
if (BLI_rctf_isect(&node->totr, &ar->v2d.cur, NULL) == FALSE) {
@@ -687,6 +783,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
if (node->flag & NODE_MUTED)
UI_ThemeColorBlend(color_id, TH_REDALERT, 0.5f);
+
#ifdef WITH_COMPOSITOR
if (ntree->type == NTREE_COMPOSIT && (snode->flag & SNODE_SHOW_HIGHLIGHT)) {
@@ -700,7 +797,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
uiRoundBox(rct->xmin, rct->ymax - NODE_DY, rct->xmax, rct->ymax, BASIS_RAD);
/* show/hide icons */
- iconofs = rct->xmax - 7.0f;
+ iconofs = rct->xmax - 0.35f * U.widget_unit;
/* preview */
if (node->typeinfo->flag & NODE_PREVIEW) {
@@ -742,13 +839,13 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
/* 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, "",
- rct->xmin + 10.0f - but_size / 2, rct->ymax - NODE_DY / 2.0f - but_size / 2,
+ 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);
/* custom draw function for this button */
- UI_DrawTriIcon(rct->xmin + 10.0f, rct->ymax - NODE_DY / 2.0f, 'v');
+ UI_DrawTriIcon(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 */
@@ -765,12 +862,14 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
// BLI_snprintf(showname, sizeof(showname), "[%s]", showname); /* XXX - don't print into self! */
uiDefBut(node->block, LABEL, 0, showname,
- (int)(rct->xmin + (NODE_MARGIN_X / snode->aspect_sqrt)), (int)(rct->ymax - NODE_DY),
+ (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, "");
/* body */
- if (node->flag & NODE_CUSTOM_COLOR)
+ if (!nodeIsRegistered(node))
+ UI_ThemeColor4(TH_REDALERT); /* use warning color to indicate undefined types */
+ else if (node->flag & NODE_CUSTOM_COLOR)
glColor3fv(node->color);
else
UI_ThemeColor4(TH_NODE);
@@ -781,6 +880,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
/* outline active and selected emphasis */
if (node->flag & SELECT) {
+
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
@@ -788,6 +888,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40);
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);
@@ -805,11 +906,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
if (nodeSocketIsHidden(sock))
continue;
- node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE, sock->flag & SELECT);
-
- node->typeinfo->drawinputfunc(C, node->block, ntree, node, sock, IFACE_(sock->name),
- sock->locx + (NODE_DYS / snode->aspect_sqrt), sock->locy - NODE_DYS,
- node->width - NODE_DY);
+ node_socket_circle_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT);
}
/* socket outputs */
@@ -817,17 +914,14 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
if (nodeSocketIsHidden(sock))
continue;
- node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE, sock->flag & SELECT);
-
- node->typeinfo->drawoutputfunc(C, node->block, ntree, node, sock, IFACE_(sock->name),
- sock->locx - node->width + (NODE_DYS / snode->aspect_sqrt), sock->locy - NODE_DYS,
- node->width - NODE_DY);
+ node_socket_circle_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT);
}
/* preview */
if (node->flag & NODE_PREVIEW) {
- if (node->preview && node->preview->rect && !BLI_rctf_is_empty(&node->prvr))
- node_draw_preview(node->preview, &node->prvr);
+ bNodePreview *preview = previews ? BKE_node_instance_hash_lookup(previews, key) : NULL;
+ if (preview && preview->rect && !BLI_rctf_is_empty(&node->prvr))
+ node_draw_preview(preview, &node->prvr);
}
UI_ThemeClearColor(color_id);
@@ -837,13 +931,13 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
node->block = NULL;
}
-static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node)
+static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key))
{
bNodeSocket *sock;
rctf *rct = &node->totr;
float dx, centy = BLI_rctf_cent_y(rct);
float hiddenrad = BLI_rctf_size_y(rct) / 2.0f;
- float socket_size = NODE_SOCKSIZE * UI_DPI_ICON_FAC;
+ float socket_size = NODE_SOCKSIZE;
int color_id = node_get_colorid(node);
char showname[128]; /* 128 is used below */
@@ -881,7 +975,19 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
}
-
+
+ /* custom color inline */
+ if (node->flag & NODE_CUSTOM_COLOR) {
+ glEnable(GL_BLEND);
+ glEnable(GL_LINE_SMOOTH);
+
+ glColor3fv(node->color);
+ uiDrawBox(GL_LINE_LOOP, rct->xmin + 1, rct->ymin + 1, rct->xmax -1, rct->ymax - 1, hiddenrad);
+
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
+ }
+
/* title */
if (node->flag & SELECT)
UI_ThemeColor(TH_SELECT);
@@ -920,7 +1026,7 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
// BLI_snprintf(showname, sizeof(showname), "[%s]", showname); /* XXX - don't print into self! */
uiDefBut(node->block, LABEL, 0, showname,
- (int)(rct->xmin + (NODE_MARGIN_X / snode->aspect_sqrt)), (int)(centy - 10),
+ (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, "");
}
@@ -939,12 +1045,12 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
/* sockets */
for (sock = node->inputs.first; sock; sock = sock->next) {
if (!nodeSocketIsHidden(sock))
- node_socket_circle_draw(snode->nodetree, sock, socket_size, sock->flag & SELECT);
+ node_socket_circle_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT);
}
for (sock = node->outputs.first; sock; sock = sock->next) {
if (!nodeSocketIsHidden(sock))
- node_socket_circle_draw(snode->nodetree, sock, socket_size, sock->flag & SELECT);
+ node_socket_circle_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT);
}
uiEndBlock(C, node->block);
@@ -991,12 +1097,12 @@ void node_set_cursor(wmWindow *win, SpaceNode *snode)
WM_cursor_set(win, cursor);
}
-void node_draw_default(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node)
+void node_draw_default(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
{
if (node->flag & NODE_HIDDEN)
- node_draw_hidden(C, ar, snode, ntree, node);
+ node_draw_hidden(C, ar, snode, ntree, node, key);
else
- node_draw_basis(C, ar, snode, ntree, node);
+ node_draw_basis(C, ar, snode, ntree, node, key);
}
static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
@@ -1005,32 +1111,25 @@ static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
node->typeinfo->drawupdatefunc(C, ntree, node);
}
-void node_update_nodetree(const bContext *C, bNodeTree *ntree, float offsetx, float offsety)
+void node_update_nodetree(const bContext *C, bNodeTree *ntree)
{
bNode *node;
/* update nodes front to back, so children sizes get updated before parents */
for (node = ntree->nodes.last; node; node = node->prev) {
- /* XXX little hack */
- node->locx += offsetx;
- node->locy += offsety;
-
node_update(C, ntree, node);
-
- node->locx -= offsetx;
- node->locy -= offsety;
}
}
-static void node_draw(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node)
+static void node_draw(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
{
if (node->typeinfo->drawfunc)
- node->typeinfo->drawfunc(C, ar, snode, ntree, node);
+ node->typeinfo->drawfunc(C, ar, snode, ntree, node, key);
}
#define USE_DRAW_TOT_UPDATE
-void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree)
+void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNodeInstanceKey parent_key)
{
bNode *node;
bNodeLink *link;
@@ -1046,6 +1145,7 @@ void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeT
/* draw background nodes, last nodes in front */
for (a = 0, node = ntree->nodes.first; node; node = node->next, a++) {
+ bNodeInstanceKey key;
#ifdef USE_DRAW_TOT_UPDATE
/* unrelated to background nodes, update the v2d->tot,
@@ -1055,117 +1155,200 @@ void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeT
if (!(node->flag & NODE_BACKGROUND))
continue;
+
+ key = BKE_node_instance_key(parent_key, ntree, node);
node->nr = a; /* index of node in list, used for exec event code */
- node_draw(C, ar, snode, ntree, node);
+ node_draw(C, ar, snode, ntree, node, key);
}
/* node lines */
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
- for (link = ntree->links.first; link; link = link->next)
- node_draw_link(&ar->v2d, snode, link);
+ for (link = ntree->links.first; link; link = link->next) {
+ if (!nodeLinkIsHidden(link))
+ node_draw_link(&ar->v2d, snode, link);
+ }
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
/* draw foreground nodes, last nodes in front */
for (a = 0, node = ntree->nodes.first; node; node = node->next, a++) {
+ bNodeInstanceKey key;
if (node->flag & NODE_BACKGROUND)
continue;
+
+ key = BKE_node_instance_key(parent_key, ntree, node);
node->nr = a; /* index of node in list, used for exec event code */
- node_draw(C, ar, snode, ntree, node);
+ node_draw(C, ar, snode, ntree, node, key);
}
}
-void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d)
+/* draw tree path info in lower left corner */
+static void draw_tree_path(SpaceNode *snode)
+{
+ char info[256];
+
+ ED_node_tree_path_get_fixedbuf(snode, info, sizeof(info));
+
+ UI_ThemeColor(TH_TEXT_HI);
+ BLF_draw_default(30, 30, 0.0f, info, sizeof(info));
+}
+
+static void snode_setup_v2d(SpaceNode *snode, ARegion *ar, float centerx, float centery)
+{
+ View2D *v2d = &ar->v2d;
+
+ /* shift view to node tree center */
+ UI_view2d_setcenter(v2d, centerx, centery);
+ UI_view2d_view_ortho(v2d);
+
+ /* aspect+font, set each time */
+ snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)ar->winx;
+ // XXX snode->curfont = uiSetCurFont_ext(snode->aspect);
+}
+
+static void draw_nodetree(const bContext *C, ARegion *ar, bNodeTree *ntree, bNodeInstanceKey parent_key)
{
- View2DScrollers *scrollers;
SpaceNode *snode = CTX_wm_space_node(C);
- bNodeLinkDrag *nldrag;
- LinkData *linkdata;
+ node_uiblocks_init(C, ntree);
+
+#ifdef WITH_COMPOSITOR
+ if (ntree->type == NTREE_COMPOSIT) {
+ COM_startReadHighlights();
+ }
+#endif
+
+ node_update_nodetree(C, ntree);
+ node_draw_nodetree(C, ar, snode, ntree, parent_key);
+}
+
+/* shade the parent node group and add a uiBlock to clip mouse events */
+static void draw_group_overlay(const bContext *C, ARegion *ar)
+{
+ View2D *v2d = &ar->v2d;
+ rctf rect = v2d->cur;
+ uiBlock *block;
+
+ /* shade node groups to separate them visually */
+ UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
+ glEnable(GL_BLEND);
+ uiSetRoundBox(0);
+ uiDrawBox(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);
+}
+
+void drawnodespace(const bContext *C, ARegion *ar)
+{
+ View2DScrollers *scrollers;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ View2D *v2d = &ar->v2d;
+
UI_ThemeClearColor(TH_BACK);
glClear(GL_COLOR_BUFFER_BIT);
UI_view2d_view_ortho(v2d);
-
- //uiFreeBlocksWin(&sa->uiblocks, sa->win);
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
/* only set once */
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_MAP1_VERTEX_3);
-
- /* aspect+font, set each time */
- snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)ar->winx;
- snode->aspect_sqrt = sqrtf(snode->aspect);
- // XXX snode->curfont = uiSetCurFont_ext(snode->aspect);
-
- /* grid */
- UI_view2d_multi_grid_draw(v2d, 25.0f, 5, 2);
-
- /* backdrop */
- draw_nodespace_back_pix(C, ar, snode);
/* nodes */
- snode_set_context(snode, CTX_data_scene(C));
-
- if (snode->nodetree) {
- bNode *node;
- /* void** highlights = 0; */ /* UNUSED */
+ snode_set_context(C);
+
+ /* draw parent node trees */
+ if (snode->treepath.last) {
+ static const int max_depth = 2;
+ bNodeTreePath *path;
+ int depth, curdepth;
+ float center[2];
+ bNodeTree *ntree;
+ bNodeLinkDrag *nldrag;
+ LinkData *linkdata;
- node_uiblocks_init(C, snode->nodetree);
+ /* current View2D center, will be set temporarily for parent node trees */
+ UI_view2d_getcenter(v2d, &center[0], &center[1]);
- /* uiBlocks must be initialized in drawing order for correct event clipping.
- * Node group internal blocks added after the main group block.
- */
- for (node = snode->nodetree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_GROUP_EDIT)
- node_uiblocks_init(C, (bNodeTree *)node->id);
+ /* store new view center in current edittree */
+ if (snode->edittree)
+ copy_v2_v2(snode->edittree->view_center, center);
+
+ depth = 0;
+ path = snode->treepath.last;
+ while (path->prev && depth < max_depth) {
+ path = path->prev;
+ ++depth;
+ }
+ /* parent node trees in the background */
+ for (curdepth = depth; curdepth >= 0; path = path->next, --curdepth) {
+ ntree = path->nodetree;
+
+ if (ntree) {
+ snode_setup_v2d(snode, ar, ntree->view_center[0], ntree->view_center[1]);
+
+ if (curdepth == 0) {
+ /* grid, uses theme color based on node path depth */
+ UI_view2d_multi_grid_draw(v2d, (depth > 0 ? TH_NODE_GROUP : TH_BACK), U.widget_unit, 5, 2);
+
+ /* backdrop */
+ draw_nodespace_back_pix(C, ar, snode);
+ }
+
+ draw_nodetree(C, ar, ntree, path->parent_key);
+
+ if (curdepth > 0)
+ draw_group_overlay(C, ar);
+ }
}
- node_update_nodetree(C, snode->nodetree, 0.0f, 0.0f);
-
-#ifdef WITH_COMPOSITOR
- if (snode->nodetree->type == NTREE_COMPOSIT) {
- COM_startReadHighlights();
+ /* reset View2D */
+ UI_view2d_setcenter(v2d, center[0], center[1]);
+
+ /* temporary links */
+ glEnable(GL_BLEND);
+ glEnable(GL_LINE_SMOOTH);
+ for (nldrag = snode->linkdrag.first; nldrag; nldrag = nldrag->next) {
+ for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next)
+ node_draw_link(v2d, snode, (bNodeLink *)linkdata->data);
}
-#endif
-
- node_draw_nodetree(C, ar, snode, snode->nodetree);
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
- #if 0
- /* active group */
- for (node = snode->nodetree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_GROUP_EDIT)
- node_draw_group(C, ar, snode, snode->nodetree, node);
+ if (snode->flag & SNODE_SHOW_GPENCIL) {
+ /* draw grease-pencil ('canvas' strokes) */
+ draw_gpencil_view2d(C, TRUE);
}
- #endif
}
-
- /* temporary links */
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
- for (nldrag = snode->linkdrag.first; nldrag; nldrag = nldrag->next) {
- for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
- node_draw_link(&ar->v2d, snode, (bNodeLink *)linkdata->data);
- }
+ else {
+ /* default grid */
+ UI_view2d_multi_grid_draw(v2d, TH_BACK, U.widget_unit, 5, 2);
+
+ /* backdrop */
+ draw_nodespace_back_pix(C, ar, snode);
}
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
- /* draw grease-pencil ('canvas' strokes) */
- if (snode->nodetree)
- draw_gpencil_view2d(C, 1);
-
/* reset view matrix */
UI_view2d_view_restore(C);
- /* draw grease-pencil (screen strokes, and also paintbuffer) */
- if (snode->nodetree)
- draw_gpencil_view2d(C, 0);
+ if (snode->treepath.last) {
+ if (snode->flag & SNODE_SHOW_GPENCIL) {
+ /* draw grease-pencil (screen strokes, and also paintbuffer) */
+ draw_gpencil_view2d(C, FALSE);
+ }
+ }
+
+ /* tree path info */
+ draw_tree_path(snode);
/* scrollers */
scrollers = UI_view2d_scrollers_calc(C, v2d, 10, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index f757345bdcb..c74c160080c 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -31,6 +31,8 @@
#include "MEM_guardedalloc.h"
+#include "DNA_action_types.h"
+#include "DNA_anim_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
@@ -65,6 +67,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -73,12 +76,25 @@
#include "GPU_material.h"
+#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"
+
#define USE_ESC_COMPO
/* ***************** composite job manager ********************** */
+enum {
+ COM_RECALC_COMPOSITE = 1,
+ COM_RECALC_VIEWER = 2
+};
+
typedef struct CompoJob {
Scene *scene;
bNodeTree *ntree;
@@ -87,8 +103,55 @@ typedef struct CompoJob {
short *do_update;
float *progress;
short need_sync;
+ int recalc_flags;
} CompoJob;
+static void compo_tag_output_nodes(bNodeTree *nodetree, int recalc_flags)
+{
+ bNode *node;
+
+ for (node = nodetree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_COMPOSITE) {
+ if (recalc_flags & COM_RECALC_COMPOSITE)
+ node->flag |= NODE_DO_OUTPUT_RECALC;
+ }
+ else if (node->type == CMP_NODE_VIEWER) {
+ if (recalc_flags & COM_RECALC_VIEWER)
+ node->flag |= NODE_DO_OUTPUT_RECALC;
+ }
+ else if (node->type == NODE_GROUP) {
+ if (node->id)
+ compo_tag_output_nodes((bNodeTree *)node->id, recalc_flags);
+ }
+ }
+}
+
+static int compo_get_recalc_flags(const bContext *C)
+{
+ bScreen *sc = CTX_wm_screen(C);
+ ScrArea *sa;
+ int recalc_flags = 0;
+
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ if (sa->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = sa->spacedata.first;
+ if (sima->image) {
+ if (sima->image->type == IMA_TYPE_R_RESULT)
+ recalc_flags |= COM_RECALC_COMPOSITE;
+ else if (sima->image->type == IMA_TYPE_COMPOSITE)
+ recalc_flags |= COM_RECALC_VIEWER;
+ }
+ }
+ else if (sa->spacetype == SPACE_NODE) {
+ SpaceNode *snode = sa->spacedata.first;
+ if (snode->flag & SNODE_BACKDRAW)
+ recalc_flags |= COM_RECALC_VIEWER;
+ }
+ }
+
+ return recalc_flags;
+}
+
/* called by compo, only to check job 'stop' value */
static int compo_breakjob(void *cjv)
{
@@ -137,6 +200,9 @@ static void compo_initjob(void *cjv)
CompoJob *cj = cjv;
cj->localtree = ntreeLocalize(cj->ntree);
+
+ if (cj->recalc_flags)
+ compo_tag_output_nodes(cj->localtree, cj->recalc_flags);
}
/* called before redraw notifiers, it moves finished previews over */
@@ -223,6 +289,7 @@ void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene
/* customdata for preview thread */
cj->scene = CTX_data_scene(C);
cj->ntree = nodetree;
+ cj->recalc_flags = compo_get_recalc_flags(C);
/* setup job */
WM_jobs_customdata_set(wm_job, cj, compo_freejob);
@@ -239,27 +306,12 @@ int composite_node_active(bContext *C)
{
if (ED_operator_node_active(C)) {
SpaceNode *snode = CTX_wm_space_node(C);
- if (snode->treetype == NTREE_COMPOSIT)
+ if (ED_node_is_compositor(snode))
return 1;
}
return 0;
}
-/* also checks for edited groups */
-bNode *editnode_get_active(bNodeTree *ntree)
-{
- bNode *node;
-
- /* check for edited group */
- for (node = ntree->nodes.first; node; node = node->next)
- if (nodeGroupEditGet(node))
- break;
- if (node)
- return nodeGetActive((bNodeTree *)node->id);
- else
- return nodeGetActive(ntree);
-}
-
static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup)
{
bNode *node;
@@ -275,20 +327,16 @@ static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup)
return 0;
}
-static void snode_dag_update_group(void *calldata, ID *owner_id, bNodeTree *ntree)
-{
- if (has_nodetree(ntree, calldata))
- DAG_id_tag_update(owner_id, 0);
-}
-
void snode_dag_update(bContext *C, SpaceNode *snode)
{
Main *bmain = CTX_data_main(C);
/* for groups, update all ID's using this */
if (snode->edittree != snode->nodetree) {
- bNodeTreeType *tti = ntreeGetType(snode->edittree->type);
- tti->foreach_nodetree(bmain, snode->edittree, snode_dag_update_group);
+ FOREACH_NODETREE(bmain, tntree, id) {
+ if (has_nodetree(tntree, snode->edittree))
+ DAG_id_tag_update(id, 0);
+ } FOREACH_NODETREE_END
}
DAG_id_tag_update(snode->id, 0);
@@ -298,37 +346,49 @@ void snode_notify(bContext *C, SpaceNode *snode)
{
WM_event_add_notifier(C, NC_NODE | NA_EDITED, NULL);
- if (snode->treetype == NTREE_SHADER)
+ if (ED_node_is_shader(snode))
WM_event_add_notifier(C, NC_MATERIAL | ND_NODES, snode->id);
- else if (snode->treetype == NTREE_COMPOSIT)
+ else if (ED_node_is_compositor(snode))
WM_event_add_notifier(C, NC_SCENE | ND_NODES, snode->id);
- else if (snode->treetype == NTREE_TEXTURE)
+ else if (ED_node_is_texture(snode))
WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, snode->id);
}
-bNode *node_tree_get_editgroup(bNodeTree *nodetree)
+void ED_node_set_tree_type(SpaceNode *snode, bNodeTreeType *typeinfo)
{
- bNode *gnode;
-
- /* get the groupnode */
- for (gnode = nodetree->nodes.first; gnode; gnode = gnode->next)
- if (nodeGroupEditGet(gnode))
- break;
- return gnode;
+ if (typeinfo)
+ BLI_strncpy(snode->tree_idname, typeinfo->idname, sizeof(snode->tree_idname));
+ else
+ snode->tree_idname[0] = '\0';
+}
+
+int ED_node_is_compositor(struct SpaceNode *snode)
+{
+ return STREQ(snode->tree_idname, ntreeType_Composite->idname);
+}
+
+int ED_node_is_shader(struct SpaceNode *snode)
+{
+ return STREQ(snode->tree_idname, ntreeType_Shader->idname);
+}
+
+int ED_node_is_texture(struct SpaceNode *snode)
+{
+ return STREQ(snode->tree_idname, ntreeType_Texture->idname);
}
/* assumes nothing being done in ntree yet, sets the default in/out node */
/* called from shading buttons or header */
-void ED_node_shader_default(Scene *scene, ID *id)
+void ED_node_shader_default(const bContext *C, ID *id)
{
+ Scene *scene = CTX_data_scene(C);
bNode *in, *out;
bNodeSocket *fromsock, *tosock, *sock;
bNodeTree *ntree;
- bNodeTemplate ntemp;
int output_type, shader_type;
- float color[3], strength = 1.0f;
+ float color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }, strength = 1.0f;
- ntree = ntreeAddTree("Shader Nodetree", NTREE_SHADER, 0);
+ ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
switch (GS(id->name)) {
case ID_MA:
@@ -381,12 +441,10 @@ void ED_node_shader_default(Scene *scene, ID *id)
return;
}
- ntemp.type = output_type;
- out = nodeAddNode(ntree, &ntemp);
+ out = nodeAddStaticNode(C, ntree, output_type);
out->locx = 300.0f; out->locy = 300.0f;
- ntemp.type = shader_type;
- in = nodeAddNode(ntree, &ntemp);
+ in = nodeAddStaticNode(C, ntree, shader_type);
in->locx = 10.0f; in->locy = 300.0f;
nodeSetActive(ntree, in);
@@ -397,12 +455,16 @@ void ED_node_shader_default(Scene *scene, ID *id)
/* default values */
if (BKE_scene_use_new_shading_nodes(scene)) {
+ PointerRNA sockptr;
sock = in->inputs.first;
- copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, color);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr);
+
+ RNA_float_set_array(&sockptr, "default_value", color);
if (strength != 0.0f) {
sock = in->inputs.last;
- ((bNodeSocketValueFloat *)sock->default_value)->value = strength;
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr);
+ RNA_float_set(&sockptr, "default_value", strength);
}
}
@@ -411,11 +473,10 @@ void ED_node_shader_default(Scene *scene, ID *id)
/* assumes nothing being done in ntree yet, sets the default in/out node */
/* called from shading buttons or header */
-void ED_node_composit_default(Scene *sce)
+void ED_node_composit_default(const bContext *C, struct Scene *sce)
{
bNode *in, *out;
bNodeSocket *fromsock, *tosock;
- bNodeTemplate ntemp;
/* but lets check it anyway */
if (sce->nodetree) {
@@ -424,20 +485,18 @@ void ED_node_composit_default(Scene *sce)
return;
}
- sce->nodetree = ntreeAddTree("Compositing Nodetree", NTREE_COMPOSIT, 0);
-
+ sce->nodetree = ntreeAddTree(NULL, "Compositing Nodetree", ntreeType_Composite->idname);
+
sce->nodetree->chunksize = 256;
sce->nodetree->edit_quality = NTREE_QUALITY_HIGH;
sce->nodetree->render_quality = NTREE_QUALITY_HIGH;
- ntemp.type = CMP_NODE_COMPOSITE;
- out = nodeAddNode(sce->nodetree, &ntemp);
+ out = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_COMPOSITE);
out->locx = 300.0f; out->locy = 400.0f;
out->id = &sce->id;
id_us_plus(out->id);
- ntemp.type = CMP_NODE_R_LAYERS;
- in = nodeAddNode(sce->nodetree, &ntemp);
+ in = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_R_LAYERS);
in->locx = 10.0f; in->locy = 400.0f;
in->id = &sce->id;
id_us_plus(in->id);
@@ -455,11 +514,10 @@ void ED_node_composit_default(Scene *sce)
/* assumes nothing being done in ntree yet, sets the default in/out node */
/* called from shading buttons or header */
-void ED_node_texture_default(Tex *tx)
+void ED_node_texture_default(const bContext *C, Tex *tx)
{
bNode *in, *out;
bNodeSocket *fromsock, *tosock;
- bNodeTemplate ntemp;
/* but lets check it anyway */
if (tx->nodetree) {
@@ -468,14 +526,12 @@ void ED_node_texture_default(Tex *tx)
return;
}
- tx->nodetree = ntreeAddTree("Texture Nodetree", NTREE_TEXTURE, 0);
+ tx->nodetree = ntreeAddTree(NULL, "Texture Nodetree", ntreeType_Texture->idname);
- ntemp.type = TEX_NODE_OUTPUT;
- out = nodeAddNode(tx->nodetree, &ntemp);
+ out = nodeAddStaticNode(C, tx->nodetree, TEX_NODE_OUTPUT);
out->locx = 300.0f; out->locy = 300.0f;
- ntemp.type = TEX_NODE_CHECKER;
- in = nodeAddNode(tx->nodetree, &ntemp);
+ in = nodeAddStaticNode(C, tx->nodetree, TEX_NODE_CHECKER);
in->locx = 10.0f; in->locy = 300.0f;
nodeSetActive(tx->nodetree, in);
@@ -486,156 +542,74 @@ void ED_node_texture_default(Tex *tx)
ntreeUpdateTree(tx->nodetree);
}
-/* id is supposed to contain a node tree */
-void node_tree_from_ID(ID *id, bNodeTree **ntree, bNodeTree **edittree, int *treetype)
+/* Here we set the active tree(s), even called for each redraw now, so keep it fast :) */
+void snode_set_context(const bContext *C)
{
- if (id) {
- bNode *node = NULL;
- short idtype = GS(id->name);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTreeType *treetype = ntreeTypeFind(snode->tree_idname);
+ bNodeTree *ntree = snode->nodetree;
+ ID *id = snode->id, *from = snode->from;
- if (idtype == ID_NT) {
- *ntree = (bNodeTree *)id;
- if (treetype) *treetype = (*ntree)->type;
- }
- else if (idtype == ID_MA) {
- *ntree = ((Material *)id)->nodetree;
- if (treetype) *treetype = NTREE_SHADER;
- }
- else if (idtype == ID_LA) {
- *ntree = ((Lamp *)id)->nodetree;
- if (treetype) *treetype = NTREE_SHADER;
- }
- else if (idtype == ID_WO) {
- *ntree = ((World *)id)->nodetree;
- if (treetype) *treetype = NTREE_SHADER;
- }
- else if (idtype == ID_SCE) {
- *ntree = ((Scene *)id)->nodetree;
- if (treetype) *treetype = NTREE_COMPOSIT;
- }
- else if (idtype == ID_TE) {
- *ntree = ((Tex *)id)->nodetree;
- if (treetype) *treetype = NTREE_TEXTURE;
- }
- else {
- if (treetype) *treetype = 0;
- return;
- }
+ /* we use this to signal warnings, when node shaders are drawn in wrong render engine */
+ if (BKE_scene_use_new_shading_nodes(CTX_data_scene(C)))
+ snode->flag |= SNODE_NEW_SHADERS;
+ else
+ snode->flag &= ~SNODE_NEW_SHADERS;
+
+ /* check the tree type */
+ if (!treetype ||
+ (treetype->poll && !treetype->poll(C, treetype)))
+ {
+ /* invalid tree type, disable */
+ snode->tree_idname[0] = '\0';
+ ED_node_tree_start(snode, NULL, NULL, NULL);
+ return;
+ }
+
+ if (snode->nodetree && strcmp(snode->nodetree->idname, snode->tree_idname) != 0) {
+ /* current tree does not match selected type, clear tree path */
+ ntree = NULL;
+ id = NULL;
+ from = NULL;
+ }
- /* find editable group */
- if (edittree) {
- if (*ntree)
- for (node = (*ntree)->nodes.first; node; node = node->next)
- if (nodeGroupEditGet(node))
- break;
+ if (!(snode->flag & SNODE_PIN) || ntree == NULL) {
+ if (treetype->get_from_context) {
+ /* reset and update from context */
+ ntree = NULL;
+ id = NULL;
+ from = NULL;
- if (node && node->id)
- *edittree = (bNodeTree *)node->id;
- else
- *edittree = *ntree;
+ treetype->get_from_context(C, treetype, &ntree, &id, &from);
}
}
- else {
- *ntree = NULL;
- *edittree = NULL;
- if (treetype) *treetype = 0;
+
+ if (snode->nodetree != ntree || snode->id != id || snode->from != from) {
+ ED_node_tree_start(snode, ntree, id, from);
}
}
-/* Here we set the active tree(s), even called for each redraw now, so keep it fast :) */
-void snode_set_context(SpaceNode *snode, Scene *scene)
+void snode_update(SpaceNode *snode, bNode *node)
{
- Object *ob = OBACT;
+ bNodeTreePath *path;
- snode->id = snode->from = NULL;
+ /* XXX this only updates nodes in the current node space tree path.
+ * The function supposedly should update any potential group node linking to changed tree,
+ * this really requires a working depsgraph ...
+ */
- if (snode->treetype == NTREE_SHADER) {
- /* need active object, or we allow pinning... */
- if (snode->shaderfrom == SNODE_SHADER_OBJECT) {
- if (ob) {
- if (ob->type == OB_LAMP) {
- snode->from = &ob->id;
- snode->id = ob->data;
- }
- else {
- Material *ma = give_current_material(ob, ob->actcol);
- if (ma) {
- snode->from = &ob->id;
- snode->id = &ma->id;
- }
- }
- }
- }
- else { /* SNODE_SHADER_WORLD */
- if (scene->world) {
- snode->from = NULL;
- snode->id = &scene->world->id;
- }
+ /* update all edited group nodes */
+ path = snode->treepath.last;
+ if (path) {
+ bNodeTree *ngroup = path->nodetree;
+ for (path = path->prev; path; path = path->prev) {
+ nodeUpdateID(path->nodetree, (ID *)ngroup);
+ ngroup = path->nodetree;
}
}
- else if (snode->treetype == NTREE_COMPOSIT) {
- snode->id = &scene->id;
-
- /* update output sockets based on available layers */
- ntreeCompositForceHidden(scene->nodetree, scene);
- }
- else if (snode->treetype == NTREE_TEXTURE) {
- Tex *tx = NULL;
-
- if (snode->texfrom == SNODE_TEX_OBJECT) {
- if (ob) {
- tx = give_current_object_texture(ob);
- if (ob->type == OB_LAMP)
- snode->from = (ID *)ob->data;
- else
- snode->from = (ID *)give_current_material(ob, ob->actcol);
-
- /* from is not set fully for material nodes, should be ID + Node then */
- snode->id = &tx->id;
- }
- }
- else if (snode->texfrom == SNODE_TEX_WORLD) {
- tx = give_current_world_texture(scene->world);
- snode->from = (ID *)scene->world;
- snode->id = &tx->id;
- }
- else {
- struct Brush *brush = NULL;
-
- if (ob && (ob->mode & OB_MODE_SCULPT))
- brush = paint_brush(&scene->toolsettings->sculpt->paint);
- else
- brush = paint_brush(&scene->toolsettings->imapaint.paint);
-
- if (brush) {
- snode->from = (ID *)brush;
- tx = give_current_brush_texture(brush);
- snode->id = &tx->id;
- }
- }
- }
- else {
- if (snode->nodetree && snode->nodetree->type == snode->treetype)
- snode->id = &snode->nodetree->id;
- else
- snode->id = NULL;
- }
-
- node_tree_from_ID(snode->id, &snode->nodetree, &snode->edittree, NULL);
-}
-
-void snode_update(SpaceNode *snode, bNode *node)
-{
- bNode *gnode;
-
if (node)
nodeUpdate(snode->edittree, node);
-
- /* if inside group, tag entire group */
- gnode = node_tree_get_editgroup(snode->nodetree);
- if (gnode)
- nodeUpdateID(snode->nodetree, gnode->id);
}
void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
@@ -646,6 +620,19 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
if (node->type != NODE_GROUP) {
int was_output = (node->flag & NODE_DO_OUTPUT);
+ int do_update = 0;
+
+ /* generic node group output: set node as active output */
+ if (node->type == NODE_GROUP_OUTPUT) {
+ bNode *tnode;
+ for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
+ if (tnode->type == NODE_GROUP_OUTPUT)
+ tnode->flag &= ~NODE_DO_OUTPUT;
+
+ node->flag |= NODE_DO_OUTPUT;
+ if (!was_output)
+ do_update = 1;
+ }
/* tree specific activate calls */
if (ntree->type == NTREE_SHADER) {
@@ -662,8 +649,10 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
node->flag |= NODE_DO_OUTPUT;
if (was_output == 0)
- ED_node_generic_update(bmain, ntree, node);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
+ else if (do_update)
+ ED_node_tag_update_nodetree(bmain, ntree);
/* if active texture changed, free glsl materials */
if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
@@ -690,7 +679,7 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
node->flag |= NODE_DO_OUTPUT;
if (was_output == 0)
- ED_node_generic_update(bmain, ntree, node);
+ ED_node_tag_update_nodetree(bmain, ntree);
/* addnode() doesnt link this yet... */
node->id = (ID *)BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
@@ -715,9 +704,11 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
tnode->flag &= ~NODE_DO_OUTPUT;
node->flag |= NODE_DO_OUTPUT;
- ED_node_generic_update(bmain, ntree, node);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
}
+ else if (do_update)
+ ED_node_tag_update_nodetree(bmain, ntree);
}
else if (ntree->type == NTREE_TEXTURE) {
// XXX
@@ -754,7 +745,7 @@ static void edit_node_properties(wmOperatorType *ot)
/* XXX could node be a context pointer? */
RNA_def_string(ot->srna, "node", "", MAX_NAME, "Node", "");
RNA_def_int(ot->srna, "socket", 0, 0, MAX_SOCKET, "Socket", "", 0, MAX_SOCKET);
- RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Side", "");
+ RNA_def_enum(ot->srna, "in_out", node_socket_in_out_items, SOCK_IN, "Socket Side", "");
}
static int edit_node_invoke_properties(bContext *C, wmOperator *op)
@@ -829,7 +820,7 @@ typedef struct NodeSizeWidget {
int directions;
} NodeSizeWidget;
-static void node_resize_init(bContext *C, wmOperator *op, wmEvent *UNUSED(event), bNode *node, int dir)
+static void node_resize_init(bContext *C, wmOperator *op, const wmEvent *UNUSED(event), bNode *node, int dir)
{
SpaceNode *snode = CTX_wm_space_node(C);
@@ -862,11 +853,11 @@ static void node_resize_exit(bContext *C, wmOperator *op, int UNUSED(cancel))
op->customdata = NULL;
}
-static int node_resize_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceNode *snode = CTX_wm_space_node(C);
ARegion *ar = CTX_wm_region(C);
- bNode *node = editnode_get_active(snode->edittree);
+ bNode *node = nodeGetActive(snode->edittree);
NodeSizeWidget *nsw = op->customdata;
float mx, my, dx, dy;
@@ -874,8 +865,8 @@ static int node_resize_modal(bContext *C, wmOperator *op, wmEvent *event)
case MOUSEMOVE:
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &mx, &my);
- dx = mx - nsw->mxstart;
- dy = my - nsw->mystart;
+ dx = (mx - nsw->mxstart) / UI_DPI_FAC;
+ dy = (my - nsw->mystart) / UI_DPI_FAC;
if (node) {
if (node->flag & NODE_HIDDEN) {
@@ -894,8 +885,8 @@ static int node_resize_modal(bContext *C, wmOperator *op, wmEvent *event)
}
}
else {
- float widthmin = UI_DPI_FAC * node->typeinfo->minwidth;
- float widthmax = UI_DPI_FAC * node->typeinfo->maxwidth;
+ float widthmin = node->typeinfo->minwidth;
+ float widthmax = node->typeinfo->maxwidth;
if (nsw->directions & NODE_RESIZE_RIGHT) {
node->width = nsw->oldwidth + dx;
CLAMP(node->width, widthmin, widthmax);
@@ -965,11 +956,11 @@ static int node_resize_modal(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static int node_resize_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int node_resize_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceNode *snode = CTX_wm_space_node(C);
ARegion *ar = CTX_wm_region(C);
- bNode *node = editnode_get_active(snode->edittree);
+ bNode *node = nodeGetActive(snode->edittree);
int dir;
if (node) {
@@ -1048,33 +1039,6 @@ void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
}
}
-/* return 0, nothing done */
-static int UNUSED_FUNCTION(node_mouse_groupheader) (SpaceNode * snode)
-{
- bNode *gnode;
- float mx = 0, my = 0;
-// XXX int mval[2];
-
- gnode = node_tree_get_editgroup(snode->nodetree);
- if (gnode == NULL) return 0;
-
-// XXX getmouseco_areawin(mval);
-// XXX areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
-
- /* click in header or outside? */
- if (BLI_rctf_isect_pt(&gnode->totr, mx, my) == 0) {
- rctf rect = gnode->totr;
-
- rect.ymax += NODE_DY;
- if (BLI_rctf_isect_pt(&rect, mx, my) == 0)
- snode_make_group_editable(snode, NULL); /* toggles, so exits editmode */
-// else
-// XXX transform_nodes(snode->nodetree, 'g', "Move group");
-
- return 1;
- }
- return 0;
-}
/* checks snode->mouse position, and returns found node/socket */
/* type is SOCK_IN and/or SOCK_OUT */
@@ -1135,32 +1099,6 @@ int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **so
}
}
- /* check group sockets
- * NB: using ngroup->outputs as input sockets and vice versa here!
- */
- if (in_out & SOCK_IN) {
- for (sock = snode->edittree->outputs.first; sock; sock = sock->next) {
- if (!nodeSocketIsHidden(sock)) {
- if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) {
- *nodep = NULL; /* NULL node pointer indicates group socket */
- *sockp = sock;
- return 1;
- }
- }
- }
- }
- if (in_out & SOCK_OUT) {
- for (sock = snode->edittree->inputs.first; sock; sock = sock->next) {
- if (!nodeSocketIsHidden(sock)) {
- if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) {
- *nodep = NULL; /* NULL node pointer indicates group socket */
- *sockp = sock;
- return 1;
- }
- }
- }
- }
-
return 0;
}
@@ -1207,7 +1145,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
* but operators and readfile.c do. */
id_us_plus(newnode->id);
/* to ensure redraws or rerenders happen */
- ED_node_changed_update(snode->id, newnode);
+ ED_node_tag_update_id(snode->id);
}
}
@@ -1268,9 +1206,9 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
/* has been set during copy above */
newnode = node->new_node;
- node_deselect(node);
+ nodeSetSelected(node, FALSE);
node->flag &= ~NODE_ACTIVE;
- node_select(newnode);
+ nodeSetSelected(newnode, TRUE);
}
/* make sure we don't copy new nodes again! */
@@ -1304,6 +1242,8 @@ void NODE_OT_duplicate(wmOperatorType *ot)
}
int ED_node_select_check(ListBase *lb)
+
+
{
bNode *node;
@@ -1448,6 +1388,7 @@ void NODE_OT_render_changed(wmOperatorType *ot)
ot->flag = 0;
}
+
/* ****************** Hide operator *********************** */
static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
@@ -1743,7 +1684,7 @@ static int node_delete_reconnect_exec(bContext *C, wmOperator *UNUSED(op))
void NODE_OT_delete_reconnect(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Delete with reconnect";
+ ot->name = "Delete with Reconnect";
ot->description = "Delete nodes; will reconnect nodes as if deletion was muted";
ot->idname = "NODE_OT_delete_reconnect";
@@ -1954,8 +1895,6 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
- bNode *gnode = node_tree_get_editgroup(snode->nodetree);
- float gnode_x = 0.0f, gnode_y = 0.0f;
bNode *node;
bNodeLink *link, *newlink;
@@ -1965,10 +1904,6 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
BKE_node_clipboard_clear();
BKE_node_clipboard_init(ntree);
- /* get group node offset */
- if (gnode)
- nodeToView(gnode, 0.0f, 0.0f, &gnode_x, &gnode_y);
-
for (node = ntree->nodes.first; node; node = node->next) {
if (node->flag & SELECT) {
bNode *new_node;
@@ -1991,12 +1926,6 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
nodeDetachNode(new_node);
}
}
-
- /* transform to basic view space. child node location is relative to parent */
- if (!new_node->parent) {
- new_node->locx += gnode_x;
- new_node->locy += gnode_y;
- }
}
}
@@ -2025,7 +1954,7 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
void NODE_OT_clipboard_copy(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Copy to clipboard";
+ ot->name = "Copy to Clipboard";
ot->description = "Copies selected nodes to the clipboard";
ot->idname = "NODE_OT_clipboard_copy";
@@ -2043,8 +1972,6 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
- bNode *gnode = node_tree_get_editgroup(snode->nodetree);
- float gnode_center[2];
const ListBase *clipboard_nodes_lb;
const ListBase *clipboard_links_lb;
bNode *node;
@@ -2078,14 +2005,6 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
/* deselect old nodes */
node_deselect_all(snode);
- /* get group node offset */
- if (gnode) {
- nodeToView(gnode, 0.0f, 0.0f, &gnode_center[0], &gnode_center[1]);
- }
- else {
- zero_v2(gnode_center);
- }
-
/* calculate "barycenter" for placing on mouse cursor */
zero_v2(center);
for (node = clipboard_nodes_lb->first, num_nodes = 0; node; node = node->next, num_nodes++) {
@@ -2102,7 +2021,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
id_us_plus(node->id);
/* pasted nodes are selected */
- node_select(new_node);
+ nodeSetSelected(new_node, TRUE);
}
/* reparent copied nodes */
@@ -2110,13 +2029,6 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
bNode *new_node = node->new_node;
if (new_node->parent)
new_node->parent = new_node->parent->new_node;
-
-
- /* place nodes around the mouse cursor. child nodes locations are relative to parent */
- if (!new_node->parent) {
- new_node->locx += snode->cursor[0] - center[0] - gnode_center[0];
- new_node->locy += snode->cursor[1] - center[1] - gnode_center[1];
- }
}
for (link = clipboard_links_lb->first; link; link = link->next) {
@@ -2132,7 +2044,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int node_clipboard_paste_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int node_clipboard_paste_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
@@ -2146,7 +2058,7 @@ static int node_clipboard_paste_invoke(bContext *C, wmOperator *op, wmEvent *eve
void NODE_OT_clipboard_paste(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Paste from clipboard";
+ ot->name = "Paste from Clipboard";
ot->description = "Pastes nodes from the clipboard to the active node tree";
ot->idname = "NODE_OT_clipboard_paste";
@@ -2159,15 +2071,195 @@ void NODE_OT_clipboard_paste(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ********************** Shader Script Update ******************/
+/********************** Add interface socket operator *********************/
-typedef struct ScriptUpdateData {
- RenderEngine *engine;
- RenderEngineType *type;
+static bNodeSocket *ntree_get_active_interface_socket(ListBase *lb)
+{
+ bNodeSocket *sock;
+ for (sock = lb->first; sock; sock = sock->next)
+ if (sock->flag & SELECT)
+ return sock;
+ return NULL;
+}
- Text *text;
- int found;
-} ScriptUpdateData;
+static int ntree_socket_add_exec(bContext *C, wmOperator *op)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ int in_out = RNA_enum_get(op->ptr, "in_out");
+ PointerRNA ntree_ptr;
+ bNodeSocket *sock, *tsock, *active_sock;
+ const char *default_name;
+
+ RNA_id_pointer_create((ID *)ntree, &ntree_ptr);
+
+ if (in_out == SOCK_IN) {
+ active_sock = ntree_get_active_interface_socket(&ntree->inputs);
+ default_name = "Input";
+ }
+ else {
+ active_sock = ntree_get_active_interface_socket(&ntree->outputs);
+ default_name = "Output";
+ }
+
+ if (active_sock) {
+ /* insert a copy of the active socket right after it */
+ sock = ntreeInsertSocketInterface(ntree, in_out, active_sock->idname, active_sock->next, active_sock->name);
+ /* XXX this only works for actual sockets, not interface templates! */
+ /*nodeSocketCopyValue(sock, &ntree_ptr, active_sock, &ntree_ptr);*/
+ }
+ else {
+ /* XXX TODO define default socket type for a tree! */
+ sock = ntreeAddSocketInterface(ntree, in_out, "NodeSocketFloat", default_name);
+ }
+
+ /* deactivate sockets (has to check both lists) */
+ for (tsock = ntree->inputs.first; tsock; tsock = tsock->next)
+ tsock->flag &= ~SELECT;
+ for (tsock = ntree->outputs.first; tsock; tsock = tsock->next)
+ tsock->flag &= ~SELECT;
+ /* make the new socket active */
+ sock->flag |= SELECT;
+
+ ntreeUpdateTree(ntree);
+
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_tree_socket_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Node Tree Interface Socket";
+ ot->description = "Add an input or output socket to the current node tree";
+ ot->idname = "NODE_OT_tree_socket_add";
+
+ /* api callbacks */
+ ot->exec = ntree_socket_add_exec;
+ ot->poll = ED_operator_node_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "in_out", node_socket_in_out_items, SOCK_IN, "Socket Type", "");
+}
+
+/********************** Remove interface socket operator *********************/
+
+static int ntree_socket_remove_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNodeSocket *iosock, *active_sock;
+
+ iosock = ntree_get_active_interface_socket(&ntree->inputs);
+ if (!iosock)
+ iosock = ntree_get_active_interface_socket(&ntree->outputs);
+ if (!iosock)
+ return OPERATOR_CANCELLED;
+
+ /* preferably next socket becomes active, otherwise try previous socket */
+ active_sock = (iosock->next ? iosock->next : iosock->prev);
+ ntreeRemoveSocketInterface(ntree, iosock);
+
+ /* set active socket */
+ if (active_sock)
+ active_sock->flag |= SELECT;
+
+ ntreeUpdateTree(ntree);
+
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_tree_socket_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Node Tree Interface Socket";
+ ot->description = "Remove an input or output socket to the current node tree";
+ ot->idname = "NODE_OT_tree_socket_remove";
+
+ /* api callbacks */
+ ot->exec = ntree_socket_remove_exec;
+ ot->poll = ED_operator_node_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/********************** Move interface socket operator *********************/
+
+static EnumPropertyItem move_direction_items[] = {
+ { 1, "UP", 0, "Up", "" },
+ { 2, "DOWN", 0, "Down", "" },
+ { 0, NULL, 0, NULL, NULL },
+};
+
+static int ntree_socket_move_exec(bContext *C, wmOperator *op)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ int direction = RNA_enum_get(op->ptr, "direction");
+ bNodeSocket *iosock;
+ ListBase *lb;
+
+ lb = &ntree->inputs;
+ iosock = ntree_get_active_interface_socket(lb);
+ if (!iosock) {
+ lb = &ntree->outputs;
+ iosock = ntree_get_active_interface_socket(lb);
+ }
+ if (!iosock)
+ return OPERATOR_CANCELLED;
+
+ switch (direction) {
+ case 1: { /* up */
+ bNodeSocket *before = iosock->prev;
+ BLI_remlink(lb, iosock);
+ if (before)
+ BLI_insertlinkbefore(lb, before, iosock);
+ else
+ BLI_addhead(lb, iosock);
+ break;
+ }
+ case 2: { /* down */
+ bNodeSocket *after = iosock->next;
+ BLI_remlink(lb, iosock);
+ if (after)
+ BLI_insertlinkafter(lb, after, iosock);
+ else
+ BLI_addtail(lb, iosock);
+ break;
+ }
+ }
+
+ ntreeUpdateTree(ntree);
+
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_tree_socket_move(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Move Node Tree Socket";
+ ot->description = "Move a socket up or down in the current node tree's sockets stack";
+ ot->idname = "NODE_OT_tree_socket_move";
+
+ /* api callbacks */
+ ot->exec = ntree_socket_move_exec;
+ ot->poll = ED_operator_node_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "direction", move_direction_items, 1, "Direction", "");
+}
+
+/* ********************** Shader Script Update ******************/
static int node_shader_script_update_poll(bContext *C)
{
@@ -2200,64 +2292,79 @@ static int node_shader_script_update_poll(bContext *C)
return 0;
}
-static void node_shader_script_update_text(void *data_, ID *UNUSED(id), bNodeTree *ntree)
+/* recursively check for script nodes in groups using this text and update */
+static int node_shader_script_update_text_recursive(RenderEngine *engine, RenderEngineType *type, bNodeTree *ntree, Text *text)
{
- ScriptUpdateData *data = (ScriptUpdateData *)data_;
+ int found = FALSE;
bNode *node;
-
+
+ ntree->done = TRUE;
+
/* update each script that is using this text datablock */
for (node = ntree->nodes.first; node; node = node->next) {
if (node->type == NODE_GROUP) {
- node_shader_script_update_text(data_, NULL, (bNodeTree *)node->id);
+ bNodeTree *ngroup = (bNodeTree *)node->id;
+ if (ngroup && !ngroup->done)
+ found |= node_shader_script_update_text_recursive(engine, type, ngroup, text);
}
- else if (node->type == SH_NODE_SCRIPT && node->id == &data->text->id) {
- data->type->update_script_node(data->engine, ntree, node);
- data->found = TRUE;
+ else if (node->type == SH_NODE_SCRIPT && node->id == &text->id) {
+ type->update_script_node(engine, ntree, node);
+ found = TRUE;
}
}
+
+ return found;
}
static int node_shader_script_update_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- ScriptUpdateData data;
PointerRNA nodeptr = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript);
+ RenderEngine *engine;
+ RenderEngineType *type;
+ int found = FALSE;
/* setup render engine */
- data.type = RE_engines_find(scene->r.engine);
- data.engine = RE_engine_create(data.type);
- data.engine->reports = op->reports;
- data.text = NULL;
- data.found = FALSE;
+ type = RE_engines_find(scene->r.engine);
+ engine = RE_engine_create(type);
+ engine->reports = op->reports;
if (nodeptr.data) {
/* update single node */
bNodeTree *ntree = nodeptr.id.data;
bNode *node = nodeptr.data;
- data.type->update_script_node(data.engine, ntree, node);
+ type->update_script_node(engine, ntree, node);
- data.found = TRUE;
+ found = TRUE;
}
else {
/* update all nodes using text datablock */
- data.text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
-
- if (data.text) {
- bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER);
-
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(bmain, &data, node_shader_script_update_text);
+ Text *text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
+
+ if (text) {
+ /* clear flags for recursion check */
+ FOREACH_NODETREE(bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER)
+ ntree->done = FALSE;
+ } FOREACH_NODETREE_END
+
+ FOREACH_NODETREE(bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ if (!ntree->done)
+ found |= node_shader_script_update_text_recursive(engine, type, ntree, text);
+ }
+ } FOREACH_NODETREE_END
- if (!data.found)
+ if (!found)
BKE_report(op->reports, RPT_INFO, "Text not used by any node, no update done");
}
}
- RE_engine_free(data.engine);
+ RE_engine_free(engine);
- return (data.found)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
+ return (found)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
}
void NODE_OT_shader_script_update(wmOperatorType *ot)
@@ -2275,3 +2382,105 @@ void NODE_OT_shader_script_update(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/* ********************** Viewer border ******************/
+
+static void viewer_border_corner_to_backdrop(SpaceNode *snode, ARegion *ar, int x, int y,
+ int backdrop_width, int backdrop_height,
+ float *fx, float *fy)
+{
+ float bufx, bufy;
+
+ bufx = backdrop_width * snode->zoom;
+ bufy = backdrop_height * snode->zoom;
+
+ *fx = (bufx > 0.0f ? ((float) x - 0.5f * ar->winx - snode->xof) / bufx + 0.5f : 0.0f);
+ *fy = (bufy > 0.0f ? ((float) y - 0.5f * ar->winy - snode->yof) / bufy + 0.5f : 0.0f);
+}
+
+static int viewer_border_exec(bContext *C, wmOperator *op)
+{
+ Image *ima;
+ void *lock;
+ ImBuf *ibuf;
+
+ ED_preview_kill_jobs(C);
+
+ ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+
+ if (ibuf) {
+ ARegion *ar = CTX_wm_region(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *btree = snode->edittree;
+ rcti rect;
+ rctf rectf;
+
+ /* get border from operator */
+ WM_operator_properties_border_to_rcti(op, &rect);
+
+ /* convert border to unified space within backdrop image */
+ viewer_border_corner_to_backdrop(snode, ar, rect.xmin, rect.ymin, ibuf->x, ibuf->y,
+ &rectf.xmin, &rectf.ymin);
+
+ viewer_border_corner_to_backdrop(snode, ar, rect.xmax, rect.ymax, ibuf->x, ibuf->y,
+ &rectf.xmax, &rectf.ymax);
+
+ /* clamp coordinates */
+ rectf.xmin = max_ff(rectf.xmin, 0.0f);
+ rectf.ymin = max_ff(rectf.ymin, 0.0f);
+ rectf.xmax = min_ff(rectf.xmax, 1.0f);
+ rectf.ymax = min_ff(rectf.ymax, 1.0f);
+
+ if (rectf.xmin < rectf.xmax && rectf.ymin < rectf.ymax) {
+ btree->viewer_border = rectf;
+
+ if (rectf.xmin == 0.0f && rectf.ymin == 0.0f &&
+ rectf.xmax == 1.0f && rectf.ymax == 1.0f)
+ {
+ btree->flag &= ~NTREE_VIEWER_BORDER;
+ }
+ else {
+ if (ibuf->rect)
+ memset(ibuf->rect, 0, 4 * ibuf->x * ibuf->y);
+
+ if (ibuf->rect_float)
+ memset(ibuf->rect_float, 0, 4 * ibuf->x * ibuf->y * sizeof(float));
+
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+
+ btree->flag |= NTREE_VIEWER_BORDER;
+ }
+
+ snode_notify(C, snode);
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+ }
+ else {
+ btree->flag &= ~NTREE_VIEWER_BORDER;
+ }
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_viewer_border(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Viewer Border";
+ ot->description = "Set the boundaries for viewer operations";
+ ot->idname = "NODE_OT_viewer_border";
+
+ /* api callbacks */
+ ot->invoke = WM_border_select_invoke;
+ ot->exec = viewer_border_exec;
+ ot->modal = WM_border_select_modal;
+ ot->cancel = WM_border_select_cancel;
+ ot->poll = composite_node_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_gesture_border(ot, TRUE);
+}
diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c
index 4dd9c89375d..30ba4108143 100644
--- a/source/blender/editors/space_node/node_group.c
+++ b/source/blender/editors/space_node/node_group.c
@@ -42,6 +42,8 @@
#include "BLI_rect.h"
#include "BLI_math.h"
+#include "BLF_translation.h"
+
#include "BKE_action.h"
#include "BKE_animsys.h"
#include "BKE_context.h"
@@ -64,85 +66,132 @@
#include "UI_resources.h"
#include "node_intern.h" /* own include */
+#include "NOD_common.h"
#include "NOD_socket.h"
-static EnumPropertyItem socket_in_out_items[] = {
- { SOCK_IN, "SOCK_IN", 0, "Input", "" },
- { SOCK_OUT, "SOCK_OUT", 0, "Output", "" },
- { 0, NULL, 0, NULL, NULL },
-};
-
-/* ***************** Edit Group operator ************* */
-
-void snode_make_group_editable(SpaceNode *snode, bNode *gnode)
+/* define common group node operator properties */
+static void node_group_operator_properties(wmOperatorType *ot)
{
- bNode *node;
-
- /* make sure nothing has group editing on */
- for (node = snode->nodetree->nodes.first; node; node = node->next) {
- nodeGroupEditClear(node);
+ /* NB: not using an enum here, because that it would have to use an item callback and thus require
+ * copying of identifier strings anyway. node_type is not a user option, just a way of allowing
+ * node group operators to work on different types of group nodes.
+ */
+ RNA_def_string(ot->srna, "node_type", "", 0, "Node Type", "Group node type the operator works on");
+}
- /* while we're here, clear texture active */
- if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
- /* this is not 100% sure to be reliable, see comment on the flag */
- node->flag &= ~NODE_ACTIVE_TEXTURE;
- }
+/* Internal poll functions so group node operators can work with different group node types.
+ * This checks the operator node type property and looks up the respective types.
+ * If this function returns FALSE the operator should return PASS_THROUGH to allow other variants.
+ */
+static int node_group_operator_check_type(bContext *C, wmOperator *op, char **r_node_idname, char **r_ntree_idname)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ PropertyRNA *ntype_prop = RNA_struct_find_property(op->ptr, "node_type");
+ char *node_idname, *ntree_idname;
+ bNodeType *ntype;
+ bNodeTreeType *ntreetype;
+
+ if (!RNA_property_is_set(op->ptr, ntype_prop)) {
+ BKE_report(op->reports, RPT_ERROR, "Group node type not set");
+ return FALSE;
}
-
- if (gnode == NULL) {
- /* with NULL argument we do a toggle */
- if (snode->edittree == snode->nodetree)
- gnode = nodeGetActive(snode->nodetree);
+
+ node_idname = RNA_property_string_get_alloc(op->ptr, ntype_prop, NULL, 0, NULL);
+ ntype = nodeTypeFind(node_idname);
+ if (!ntype) {
+ BKE_reportf(op->reports, RPT_ERROR, "Group node type %s undefined", node_idname);
+ MEM_freeN(node_idname);
+ return FALSE;
}
-
- if (gnode) {
- snode->edittree = nodeGroupEditSet(gnode, 1);
-
- /* deselect all other nodes, so we can also do grabbing of entire subtree */
- for (node = snode->nodetree->nodes.first; node; node = node->next) {
- node_deselect(node);
-
- if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
- /* this is not 100% sure to be reliable, see comment on the flag */
- node->flag &= ~NODE_ACTIVE_TEXTURE;
- }
- }
- node_select(gnode);
+
+ if (!ntype->poll(ntype, ntree)) {
+ MEM_freeN(node_idname);
+ return FALSE;
+ }
+
+ ntree_idname = BLI_strdup(ntype->group_tree_idname);
+ ntreetype = ntreeTypeFind(ntree_idname);
+ if (!ntreetype) {
+ BKE_reportf(op->reports, RPT_ERROR, "Group node tree type %s undefined", ntree_idname);
+ MEM_freeN(node_idname);
+ MEM_freeN(ntree_idname);
+ return FALSE;
}
+
+ if (r_node_idname)
+ *r_node_idname = node_idname;
+ else
+ MEM_freeN(node_idname);
+
+ if (r_ntree_idname)
+ *r_ntree_idname = ntree_idname;
else
- snode->edittree = snode->nodetree;
+ MEM_freeN(ntree_idname);
+
+ return TRUE;
}
-static int node_group_edit_exec(bContext *C, wmOperator *UNUSED(op))
+static bNode *node_group_get_active(bContext *C, const char *node_idname)
{
SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node = nodeGetActive(snode->edittree);
+
+ if (node && STREQ(node->idname, node_idname))
+ return node;
+ else
+ return NULL;
+}
- ED_preview_kill_jobs(C);
+/* ***************** Edit Group operator ************* */
- if (snode->nodetree == snode->edittree) {
- bNode *gnode = nodeGetActive(snode->edittree);
- snode_make_group_editable(snode, gnode);
+static int node_group_edit_exec(bContext *C, wmOperator *op)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ char *node_idname;
+ bNode *gnode;
+ int exit = RNA_boolean_get(op->ptr, "exit");
+
+ ED_preview_kill_jobs(C);
+
+ if (!node_group_operator_check_type(C, op, &node_idname, NULL))
+ return OPERATOR_PASS_THROUGH;
+
+ gnode = node_group_get_active(C, node_idname);
+ MEM_freeN(node_idname);
+
+ if (gnode && !exit) {
+ bNodeTree *ngroup = (bNodeTree *)gnode->id;
+
+ if (ngroup) {
+ if (ngroup->id.lib)
+ ntreeMakeLocal(ngroup);
+
+ ED_node_tree_push(snode, ngroup, gnode);
+ }
}
else
- snode_make_group_editable(snode, NULL);
-
+ ED_node_tree_pop(snode);
+
WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL);
-
+
return OPERATOR_FINISHED;
}
-static int node_group_edit_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int node_group_edit_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ char *node_idname;
bNode *gnode;
-
- /* XXX callback? */
- if (snode->nodetree == snode->edittree) {
- gnode = nodeGetActive(snode->edittree);
- if (gnode && gnode->id && GS(gnode->id->name) == ID_NT && gnode->id->lib) {
- uiPupMenuOkee(C, op->type->idname, "Make group local?");
- return OPERATOR_CANCELLED;
- }
+
+ if (!node_group_operator_check_type(C, op, &node_idname, NULL))
+ return OPERATOR_PASS_THROUGH;
+
+ gnode = node_group_get_active(C, node_idname);
+ MEM_freeN(node_idname);
+
+ if (gnode && gnode->id && gnode->id->lib) {
+ WM_operator_confirm_message(C, op, "Make group local?");
+ return OPERATOR_CANCELLED;
}
return node_group_edit_exec(C, op);
@@ -154,258 +203,17 @@ void NODE_OT_group_edit(wmOperatorType *ot)
ot->name = "Edit Group";
ot->description = "Edit node group";
ot->idname = "NODE_OT_group_edit";
-
+
/* api callbacks */
ot->invoke = node_group_edit_invoke;
ot->exec = node_group_edit_exec;
ot->poll = ED_operator_node_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* ***************** Add Group Socket operator ************* */
-
-static int node_group_socket_add_exec(bContext *C, wmOperator *op)
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- int in_out = -1;
- char name[MAX_NAME] = "";
- int type = SOCK_FLOAT;
- bNodeTree *ngroup = snode->edittree;
- /* bNodeSocket *sock; */ /* UNUSED */
-
- ED_preview_kill_jobs(C);
-
- if (RNA_struct_property_is_set(op->ptr, "name"))
- RNA_string_get(op->ptr, "name", name);
-
- if (RNA_struct_property_is_set(op->ptr, "type"))
- type = RNA_enum_get(op->ptr, "type");
-
- if (RNA_struct_property_is_set(op->ptr, "in_out"))
- in_out = RNA_enum_get(op->ptr, "in_out");
- else
- return OPERATOR_CANCELLED;
-
- /* using placeholder subtype first */
- /* sock = */ /* UNUSED */ node_group_add_socket(ngroup, name, type, in_out);
-
- ntreeUpdateTree(ngroup);
-
- snode_notify(C, snode);
-
- return OPERATOR_FINISHED;
-}
-
-void NODE_OT_group_socket_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Group Socket";
- ot->description = "Add node group socket";
- ot->idname = "NODE_OT_group_socket_add";
-
- /* api callbacks */
- ot->exec = node_group_socket_add_exec;
- ot->poll = ED_operator_node_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
- RNA_def_string(ot->srna, "name", "", MAX_NAME, "Name", "Group socket name");
- RNA_def_enum(ot->srna, "type", node_socket_type_items, SOCK_FLOAT, "Type", "Type of the group socket");
-}
-
-/* ***************** Remove Group Socket operator ************* */
-
-static int node_group_socket_remove_exec(bContext *C, wmOperator *op)
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- int index = -1;
- int in_out = -1;
- bNodeTree *ngroup = snode->edittree;
- bNodeSocket *sock;
-
- ED_preview_kill_jobs(C);
-
- if (RNA_struct_property_is_set(op->ptr, "index"))
- index = RNA_int_get(op->ptr, "index");
- else
- return OPERATOR_CANCELLED;
-
- if (RNA_struct_property_is_set(op->ptr, "in_out"))
- in_out = RNA_enum_get(op->ptr, "in_out");
- else
- return OPERATOR_CANCELLED;
-
- sock = (bNodeSocket *)BLI_findlink(in_out == SOCK_IN ? &ngroup->inputs : &ngroup->outputs, index);
- if (sock) {
- node_group_remove_socket(ngroup, sock, in_out);
- ntreeUpdateTree(ngroup);
-
- snode_notify(C, snode);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void NODE_OT_group_socket_remove(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Remove Group Socket";
- ot->description = "Remove a node group socket";
- ot->idname = "NODE_OT_group_socket_remove";
-
- /* api callbacks */
- ot->exec = node_group_socket_remove_exec;
- ot->poll = ED_operator_node_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
- RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
-}
-
-/* ***************** Move Group Socket Up operator ************* */
-
-static int node_group_socket_move_up_exec(bContext *C, wmOperator *op)
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- int index = -1;
- int in_out = -1;
- bNodeTree *ngroup = snode->edittree;
- bNodeSocket *sock, *prev;
-
- ED_preview_kill_jobs(C);
-
- if (RNA_struct_property_is_set(op->ptr, "index"))
- index = RNA_int_get(op->ptr, "index");
- else
- return OPERATOR_CANCELLED;
-
- if (RNA_struct_property_is_set(op->ptr, "in_out"))
- in_out = RNA_enum_get(op->ptr, "in_out");
- else
- return OPERATOR_CANCELLED;
-
- /* swap */
- if (in_out == SOCK_IN) {
- sock = (bNodeSocket *)BLI_findlink(&ngroup->inputs, index);
- prev = sock->prev;
- /* can't move up the first socket */
- if (!prev)
- return OPERATOR_CANCELLED;
- BLI_remlink(&ngroup->inputs, sock);
- BLI_insertlinkbefore(&ngroup->inputs, prev, sock);
-
- ngroup->update |= NTREE_UPDATE_GROUP_IN;
- }
- else if (in_out == SOCK_OUT) {
- sock = (bNodeSocket *)BLI_findlink(&ngroup->outputs, index);
- prev = sock->prev;
- /* can't move up the first socket */
- if (!prev)
- return OPERATOR_CANCELLED;
- BLI_remlink(&ngroup->outputs, sock);
- BLI_insertlinkbefore(&ngroup->outputs, prev, sock);
-
- ngroup->update |= NTREE_UPDATE_GROUP_OUT;
- }
- ntreeUpdateTree(ngroup);
-
- snode_notify(C, snode);
-
- return OPERATOR_FINISHED;
-}
-
-void NODE_OT_group_socket_move_up(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Move Group Socket Up";
- ot->description = "Move up node group socket";
- ot->idname = "NODE_OT_group_socket_move_up";
-
- /* api callbacks */
- ot->exec = node_group_socket_move_up_exec;
- ot->poll = ED_operator_node_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
- RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
-}
-
-/* ***************** Move Group Socket Up operator ************* */
-
-static int node_group_socket_move_down_exec(bContext *C, wmOperator *op)
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- int index = -1;
- int in_out = -1;
- bNodeTree *ngroup = snode->edittree;
- bNodeSocket *sock, *next;
-
- ED_preview_kill_jobs(C);
-
- if (RNA_struct_property_is_set(op->ptr, "index"))
- index = RNA_int_get(op->ptr, "index");
- else
- return OPERATOR_CANCELLED;
-
- if (RNA_struct_property_is_set(op->ptr, "in_out"))
- in_out = RNA_enum_get(op->ptr, "in_out");
- else
- return OPERATOR_CANCELLED;
-
- /* swap */
- if (in_out == SOCK_IN) {
- sock = (bNodeSocket *)BLI_findlink(&ngroup->inputs, index);
- next = sock->next;
- /* can't move down the last socket */
- if (!next)
- return OPERATOR_CANCELLED;
- BLI_remlink(&ngroup->inputs, sock);
- BLI_insertlinkafter(&ngroup->inputs, next, sock);
-
- ngroup->update |= NTREE_UPDATE_GROUP_IN;
- }
- else if (in_out == SOCK_OUT) {
- sock = (bNodeSocket *)BLI_findlink(&ngroup->outputs, index);
- next = sock->next;
- /* can't move down the last socket */
- if (!next)
- return OPERATOR_CANCELLED;
- BLI_remlink(&ngroup->outputs, sock);
- BLI_insertlinkafter(&ngroup->outputs, next, sock);
-
- ngroup->update |= NTREE_UPDATE_GROUP_OUT;
- }
- ntreeUpdateTree(ngroup);
-
- snode_notify(C, snode);
-
- return OPERATOR_FINISHED;
-}
-
-void NODE_OT_group_socket_move_down(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Move Group Socket Down";
- ot->description = "Move down node group socket";
- ot->idname = "NODE_OT_group_socket_move_down";
-
- /* api callbacks */
- ot->exec = node_group_socket_move_down_exec;
- ot->poll = ED_operator_node_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
- RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
+
+ node_group_operator_properties(ot);
+ RNA_def_boolean(ot->srna, "exit", FALSE, "Exit", "");
}
/* ******************** Ungroup operator ********************** */
@@ -413,178 +221,185 @@ void NODE_OT_group_socket_move_down(wmOperatorType *ot)
/* returns 1 if its OK */
static int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
{
- bNodeLink *link, *linkn;
- bNode *node, *nextn;
+ bNodeLink *link, *linkn, *tlink;
+ bNode *node, *nextnode;
bNodeTree *ngroup, *wgroup;
ListBase anim_basepaths = {NULL, NULL};
-
+
ngroup = (bNodeTree *)gnode->id;
- if (ngroup == NULL) return 0;
-
+
/* clear new pointers, set in copytree */
for (node = ntree->nodes.first; node; node = node->next)
node->new_node = NULL;
-
+
/* wgroup is a temporary copy of the NodeTree we're merging in
* - all of wgroup's nodes are transferred across to their new home
* - ngroup (i.e. the source NodeTree) is left unscathed
* - temp copy. don't change ID usercount
*/
wgroup = ntreeCopyTree_ex(ngroup, FALSE);
-
- /* add the nodes into the ntree */
- for (node = wgroup->nodes.first; node; node = nextn) {
- nextn = node->next;
-
- /* keep track of this node's RNA "base" path (the part of the path identifying the node)
+
+ /* Add the nodes into the ntree */
+ for (node = wgroup->nodes.first; node; node = nextnode) {
+ nextnode = node->next;
+
+ /* Remove interface nodes.
+ * This also removes remaining links to and from interface nodes.
+ */
+ if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
+ nodeFreeNode(wgroup, node);
+ continue;
+ }
+
+ /* keep track of this node's RNA "base" path (the part of the path identifying the node)
* if the old nodetree has animation data which potentially covers this node
*/
if (wgroup->adt) {
PointerRNA ptr;
char *path;
-
+
RNA_pointer_create(&wgroup->id, &RNA_Node, node, &ptr);
path = RNA_path_from_ID_to_struct(&ptr);
-
+
if (path)
BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
}
-
+
/* migrate node */
BLI_remlink(&wgroup->nodes, node);
BLI_addtail(&ntree->nodes, node);
-
- /* ensure unique node name in the nodee tree */
+
+ /* ensure unique node name in the node tree */
nodeUniqueName(ntree, node);
-
- node->locx += gnode->locx;
- node->locy += gnode->locy;
-
- node->flag |= NODE_SELECT;
- }
-
- /* restore external links to and from the gnode */
- for (link = ntree->links.first; link; link = link->next) {
- if (link->fromnode == gnode) {
- if (link->fromsock->groupsock) {
- bNodeSocket *gsock = link->fromsock->groupsock;
- if (gsock->link) {
- if (gsock->link->fromnode) {
- /* NB: using the new internal copies here! the groupsock pointer still maps to the old tree */
- link->fromnode = (gsock->link->fromnode ? gsock->link->fromnode->new_node : NULL);
- link->fromsock = gsock->link->fromsock->new_sock;
- }
- else {
- /* group output directly maps to group input */
- bNodeSocket *insock = node_group_find_input(gnode, gsock->link->fromsock);
- if (insock->link) {
- link->fromnode = insock->link->fromnode;
- link->fromsock = insock->link->fromsock;
- }
- }
- }
- else {
- /* copy the default input value from the group socket default to the external socket */
- node_socket_convert_default_value(link->tosock->type, link->tosock->default_value, gsock->type, gsock->default_value);
- }
- }
- }
- }
- /* remove internal output links, these are not used anymore */
- for (link = wgroup->links.first; link; link = linkn) {
- linkn = link->next;
- if (!link->tonode)
- nodeRemLink(wgroup, link);
- }
- /* restore links from internal nodes */
- for (link = wgroup->links.first; link; link = linkn) {
- linkn = link->next;
- /* indicates link to group input */
- if (!link->fromnode) {
- /* NB: can't use find_group_node_input here,
- * because gnode sockets still point to the old tree!
- */
- bNodeSocket *insock;
- for (insock = gnode->inputs.first; insock; insock = insock->next)
- if (insock->groupsock->new_sock == link->fromsock)
- break;
- if (insock->link) {
- link->fromnode = insock->link->fromnode;
- link->fromsock = insock->link->fromsock;
- }
- else {
- /* copy the default input value from the group node socket default to the internal socket */
- node_socket_convert_default_value(link->tosock->type, link->tosock->default_value, insock->type, insock->default_value);
- nodeRemLink(wgroup, link);
- }
+
+ if (!node->parent) {
+ node->locx += gnode->locx;
+ node->locy += gnode->locy;
}
+
+ node->flag |= NODE_SELECT;
}
-
- /* add internal links to the ntree */
+
+ /* Add internal links to the ntree */
for (link = wgroup->links.first; link; link = linkn) {
linkn = link->next;
BLI_remlink(&wgroup->links, link);
BLI_addtail(&ntree->links, link);
}
-
+
/* and copy across the animation,
* note that the animation data's action can be NULL here */
if (wgroup->adt) {
LinkData *ld, *ldn = NULL;
bAction *waction;
-
+
/* firstly, wgroup needs to temporary dummy action that can be destroyed, as it shares copies */
waction = wgroup->adt->action = BKE_action_copy(wgroup->adt->action);
-
+
/* now perform the moving */
BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->id, &anim_basepaths);
-
+
/* paths + their wrappers need to be freed */
for (ld = anim_basepaths.first; ld; ld = ldn) {
ldn = ld->next;
-
+
MEM_freeN(ld->data);
BLI_freelinkN(&anim_basepaths, ld);
}
-
+
/* free temp action too */
if (waction) {
BKE_libblock_free(&G.main->action, waction);
}
}
-
- /* delete the group instance. this also removes old input links! */
- nodeFreeNode(ntree, gnode);
-
+
/* free the group tree (takes care of user count) */
BKE_libblock_free(&G.main->nodetree, wgroup);
-
+
+ /* restore external links to and from the gnode */
+ /* note: the nodes have been copied to intermediate wgroup first (so need to use new_node),
+ * then transferred to ntree (new_node pointers remain valid).
+ */
+
+ /* input links */
+ for (link = ngroup->links.first; link; link = link->next) {
+ if (link->fromnode->type == NODE_GROUP_INPUT) {
+ const char *identifier = link->fromsock->identifier;
+ int num_external_links = 0;
+
+ /* find external links to this input */
+ for (tlink = ntree->links.first; tlink; tlink = tlink->next) {
+ if (tlink->tonode == gnode && STREQ(tlink->tosock->identifier, identifier)) {
+ nodeAddLink(ntree, tlink->fromnode, tlink->fromsock, link->tonode->new_node, link->tosock->new_sock);
+ ++num_external_links;
+ }
+ }
+
+ /* if group output is not externally linked,
+ * convert the constant input value to ensure somewhat consistent behavior */
+ if (num_external_links == 0) {
+ bNodeSocket *sock = node_group_find_input_socket(gnode, identifier);
+ BLI_assert(sock);
+
+ /* XXX TODO nodeSocketCopy(ntree, link->tosock->new_sock, link->tonode->new_node, ntree, sock, gnode);*/
+ }
+ }
+ }
+
+ /* output links */
+ for (link = ntree->links.first; link; link = link->next) {
+ if (link->fromnode == gnode) {
+ const char *identifier = link->fromsock->identifier;
+ int num_internal_links = 0;
+
+ /* find internal links to this output */
+ for (tlink = ngroup->links.first; tlink; tlink = tlink->next) {
+ /* only use active output node */
+ if (tlink->tonode->type == NODE_GROUP_OUTPUT && (tlink->tonode->flag & NODE_DO_OUTPUT)) {
+ if (STREQ(tlink->tosock->identifier, identifier)) {
+ nodeAddLink(ntree, tlink->fromnode->new_node, tlink->fromsock->new_sock, link->tonode, link->tosock);
+ ++num_internal_links;
+ }
+ }
+ }
+
+ /* if group output is not internally linked,
+ * convert the constant output value to ensure somewhat consistent behavior */
+ if (num_internal_links == 0) {
+ bNodeSocket *sock = node_group_find_output_socket(gnode, identifier);
+ BLI_assert(sock);
+
+ /* XXX TODO nodeSocketCopy(ntree, link->tosock, link->tonode, ntree, sock, gnode); */
+ }
+ }
+ }
+
+ /* delete the group instance */
+ nodeFreeNode(ntree, gnode);
+
ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
-
+
return 1;
}
+
static int node_group_ungroup_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
+ char *node_idname;
bNode *gnode;
ED_preview_kill_jobs(C);
- /* are we inside of a group? */
- gnode = node_tree_get_editgroup(snode->nodetree);
- if (gnode)
- snode_make_group_editable(snode, NULL);
-
- gnode = nodeGetActive(snode->edittree);
- if (gnode == NULL)
+ if (!node_group_operator_check_type(C, op, &node_idname, NULL))
+ return OPERATOR_PASS_THROUGH;
+
+ gnode = node_group_get_active(C, node_idname);
+ MEM_freeN(node_idname);
+ if (!gnode)
return OPERATOR_CANCELLED;
-
- if (gnode->type != NODE_GROUP) {
- BKE_report(op->reports, RPT_WARNING, "Not a group");
- return OPERATOR_CANCELLED;
- }
- else if (node_group_ungroup(snode->nodetree, gnode)) {
+
+ if (gnode->id && node_group_ungroup(snode->edittree, gnode)) {
ntreeUpdateTree(snode->nodetree);
}
else {
@@ -604,91 +419,92 @@ void NODE_OT_group_ungroup(wmOperatorType *ot)
ot->name = "Ungroup";
ot->description = "Ungroup selected nodes";
ot->idname = "NODE_OT_group_ungroup";
-
+
/* api callbacks */
ot->exec = node_group_ungroup_exec;
ot->poll = ED_operator_node_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ node_group_operator_properties(ot);
}
/* ******************** Separate operator ********************** */
/* returns 1 if its OK */
-static int node_group_separate_selected(bNodeTree *ntree, bNode *gnode, int make_copy)
+static int node_group_separate_selected(bNodeTree *ntree, bNodeTree *ngroup, float offx, float offy, int make_copy)
{
bNodeLink *link, *link_next;
bNode *node, *node_next, *newnode;
- bNodeTree *ngroup;
ListBase anim_basepaths = {NULL, NULL};
-
- ngroup = (bNodeTree *)gnode->id;
- if (ngroup == NULL) return 0;
-
+
/* deselect all nodes in the target tree */
for (node = ntree->nodes.first; node; node = node->next)
- node_deselect(node);
-
+ nodeSetSelected(node, FALSE);
+
/* clear new pointers, set in nodeCopyNode */
for (node = ngroup->nodes.first; node; node = node->next)
node->new_node = NULL;
-
+
/* add selected nodes into the ntree */
for (node = ngroup->nodes.first; node; node = node_next) {
node_next = node->next;
- if (node->flag & NODE_SELECT) {
-
- if (make_copy) {
- /* make a copy */
- newnode = nodeCopyNode(ngroup, node);
- }
- else {
- /* use the existing node */
- newnode = node;
- }
-
- /* keep track of this node's RNA "base" path (the part of the path identifying the node)
- * if the old nodetree has animation data which potentially covers this node
- */
- if (ngroup->adt) {
- PointerRNA ptr;
- char *path;
-
- RNA_pointer_create(&ngroup->id, &RNA_Node, newnode, &ptr);
- path = RNA_path_from_ID_to_struct(&ptr);
-
- if (path)
- BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
- }
-
- /* ensure valid parent pointers, detach if parent stays inside the group */
- if (newnode->parent && !(newnode->parent->flag & NODE_SELECT))
- nodeDetachNode(newnode);
-
- /* migrate node */
- BLI_remlink(&ngroup->nodes, newnode);
- BLI_addtail(&ntree->nodes, newnode);
+ if (!(node->flag & NODE_SELECT))
+ continue;
+
+ /* ignore interface nodes */
+ if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
+ nodeSetSelected(node, FALSE);
+ continue;
+ }
+
+ if (make_copy) {
+ /* make a copy */
+ newnode = nodeCopyNode(ngroup, node);
+ }
+ else {
+ /* use the existing node */
+ newnode = node;
+ }
+
+ /* keep track of this node's RNA "base" path (the part of the path identifying the node)
+ * if the old nodetree has animation data which potentially covers this node
+ */
+ if (ngroup->adt) {
+ PointerRNA ptr;
+ char *path;
- /* ensure unique node name in the node tree */
- nodeUniqueName(ntree, newnode);
+ RNA_pointer_create(&ngroup->id, &RNA_Node, newnode, &ptr);
+ path = RNA_path_from_ID_to_struct(&ptr);
- newnode->locx += gnode->locx;
- newnode->locy += gnode->locy;
+ if (path)
+ BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
}
- else {
- /* ensure valid parent pointers, detach if child stays inside the group */
- if (node->parent && (node->parent->flag & NODE_SELECT))
- nodeDetachNode(node);
+
+ /* ensure valid parent pointers, detach if parent stays inside the group */
+ if (newnode->parent && !(newnode->parent->flag & NODE_SELECT))
+ nodeDetachNode(newnode);
+
+ /* migrate node */
+ BLI_remlink(&ngroup->nodes, newnode);
+ BLI_addtail(&ntree->nodes, newnode);
+
+ /* ensure unique node name in the node tree */
+ nodeUniqueName(ntree, newnode);
+
+ if (!newnode->parent) {
+ newnode->locx += offx;
+ newnode->locy += offy;
}
}
-
+
/* 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));
link_next = link->next;
-
+
if (make_copy) {
/* make a copy of internal links */
if (fromselect && toselect)
@@ -705,28 +521,28 @@ static int node_group_separate_selected(bNodeTree *ntree, bNode *gnode, int make
}
}
}
-
+
/* and copy across the animation,
* note that the animation data's action can be NULL here */
if (ngroup->adt) {
LinkData *ld, *ldn = NULL;
-
+
/* now perform the moving */
BKE_animdata_separate_by_basepath(&ngroup->id, &ntree->id, &anim_basepaths);
-
+
/* paths + their wrappers need to be freed */
for (ld = anim_basepaths.first; ld; ld = ldn) {
ldn = ld->next;
-
+
MEM_freeN(ld->data);
BLI_freelinkN(&anim_basepaths, ld);
}
}
-
+
ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
if (!make_copy)
ngroup->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
-
+
return 1;
}
@@ -736,7 +552,7 @@ typedef enum eNodeGroupSeparateType {
} eNodeGroupSeparateType;
/* Operator Property */
-EnumPropertyItem node_group_separate_types[] = {
+static EnumPropertyItem node_group_separate_types[] = {
{NODE_GS_COPY, "COPY", 0, "Copy", "Copy to parent node tree, keep group intact"},
{NODE_GS_MOVE, "MOVE", 0, "Move", "Move to parent node tree, remove from group"},
{0, NULL, 0, NULL, NULL}
@@ -745,56 +561,64 @@ EnumPropertyItem node_group_separate_types[] = {
static int node_group_separate_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
- bNode *gnode;
+ bNodeTree *ngroup, *nparent;
int type = RNA_enum_get(op->ptr, "type");
+ float offx, offy;
ED_preview_kill_jobs(C);
/* are we inside of a group? */
- gnode = node_tree_get_editgroup(snode->nodetree);
- if (!gnode) {
+ ngroup = snode->edittree;
+ nparent = ED_node_tree_get(snode, 1);
+ if (!nparent) {
BKE_report(op->reports, RPT_WARNING, "Not inside node group");
return OPERATOR_CANCELLED;
}
-
+ /* get node tree offset */
+ snode_group_offset(snode, &offx, &offy);
+
switch (type) {
case NODE_GS_COPY:
- if (!node_group_separate_selected(snode->nodetree, gnode, 1)) {
+ if (!node_group_separate_selected(nparent, ngroup, offx, offy, 1)) {
BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
return OPERATOR_CANCELLED;
}
break;
case NODE_GS_MOVE:
- if (!node_group_separate_selected(snode->nodetree, gnode, 0)) {
+ if (!node_group_separate_selected(nparent, ngroup, offx, offy, 0)) {
BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
return OPERATOR_CANCELLED;
}
break;
}
-
+
/* switch to parent tree */
- snode_make_group_editable(snode, NULL);
-
+ ED_node_tree_pop(snode);
+
ntreeUpdateTree(snode->nodetree);
-
+
snode_notify(C, snode);
snode_dag_update(C, snode);
return OPERATOR_FINISHED;
}
-static int node_group_separate_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
+static int node_group_separate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- uiPopupMenu *pup = uiPupMenuBegin(C, "Separate", ICON_NONE);
- uiLayout *layout = uiPupMenuLayout(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);
-
- return OPERATOR_CANCELLED;
+ if (!node_group_operator_check_type(C, op, NULL, NULL))
+ return OPERATOR_PASS_THROUGH;
+ else {
+ uiPopupMenu *pup = uiPupMenuBegin(C, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Separate"), ICON_NONE);
+ uiLayout *layout = uiPupMenuLayout(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);
+
+ return OPERATOR_CANCELLED;
+ }
}
void NODE_OT_group_separate(wmOperatorType *ot)
@@ -803,158 +627,193 @@ void NODE_OT_group_separate(wmOperatorType *ot)
ot->name = "Separate";
ot->description = "Separate selected nodes from the node group";
ot->idname = "NODE_OT_group_separate";
-
+
/* api callbacks */
ot->invoke = node_group_separate_invoke;
ot->exec = node_group_separate_exec;
ot->poll = ED_operator_node_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
+ node_group_operator_properties(ot);
RNA_def_enum(ot->srna, "type", node_group_separate_types, NODE_GS_COPY, "Type", "");
}
/* ****************** Make Group operator ******************* */
-static int node_group_make_test(bNodeTree *ntree, bNode *gnode)
+static bool node_group_make_use_node(bNode *node, bNode *gnode)
{
+ return (node != gnode &&
+ !ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT) &&
+ (node->flag & NODE_SELECT));
+}
+
+static bool node_group_make_test_selected(bNodeTree *ntree, bNode *gnode, const char *ntree_idname, struct ReportList *reports)
+{
+ bNodeTree *ngroup;
bNode *node;
bNodeLink *link;
- int totnode = 0;
-
- /* is there something to group? also do some clearing */
+ int ok = true;
+
+ /* make a local pseudo node tree to pass to the node poll functions */
+ ngroup = ntreeAddTree(NULL, "Pseudo Node Group", ntree_idname);
+
+ /* check poll functions for selected nodes */
for (node = ntree->nodes.first; node; node = node->next) {
- if (node == gnode)
- continue;
-
- if (node->flag & NODE_SELECT) {
- /* no groups in groups */
- if (node->type == NODE_GROUP)
- return 0;
- totnode++;
+ if (node_group_make_use_node(node, gnode)) {
+ if (node->typeinfo->poll_instance && !node->typeinfo->poll_instance(node, ngroup)) {
+ BKE_reportf(reports, RPT_WARNING, "Can not add node '%s' in a group", node->name);
+ ok = false;
+ break;
+ }
}
node->done = 0;
}
- if (totnode == 0) return 0;
-
+
+ /* free local pseudo node tree again */
+ ntreeFreeTree(ngroup);
+ MEM_freeN(ngroup);
+ if (!ok)
+ return false;
+
/* check if all connections are OK, no unselected node has both
* inputs and outputs to a selection */
for (link = ntree->links.first; link; link = link->next) {
- if (link->fromnode && link->tonode && link->fromnode->flag & NODE_SELECT && link->fromnode != gnode)
+ if (node_group_make_use_node(link->fromnode, gnode))
link->tonode->done |= 1;
- if (link->fromnode && link->tonode && link->tonode->flag & NODE_SELECT && link->tonode != gnode)
+ if (node_group_make_use_node(link->tonode, gnode))
link->fromnode->done |= 2;
}
-
for (node = ntree->nodes.first; node; node = node->next) {
- if (node == gnode)
- continue;
- if ((node->flag & NODE_SELECT) == 0)
- if (node->done == 3)
- break;
+ if (!(node->flag & NODE_SELECT) &&
+ node != gnode &&
+ node->done == 3)
+ {
+ return false;
+ }
}
- if (node)
- return 0;
-
- return 1;
+ return true;
}
-
-static void node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min, float *max)
+static int node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min, float *max)
{
bNode *node;
+ float loc[2];
+ int totselect = 0;
+
INIT_MINMAX2(min, max);
for (node = ntree->nodes.first; node; node = node->next) {
- if (node == gnode)
- continue;
- if (node->flag & NODE_SELECT) {
- minmax_v2v2_v2(min, max, &node->locx);
+ if (node_group_make_use_node(node, gnode)) {
+ nodeToView(node, 0.0f, 0.0f, &loc[0], &loc[1]);
+ minmax_v2v2_v2(min, max, loc);
+ ++totselect;
}
}
+
+ /* sane min/max if no selected nodes */
+ if (totselect == 0) {
+ min[0] = min[1] = max[0] = max[1] = 0.0f;
+ }
+
+ return totselect;
}
-static int node_group_make_insert_selected(bNodeTree *ntree, bNode *gnode)
+static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, bNode *gnode)
{
bNodeTree *ngroup = (bNodeTree *)gnode->id;
bNodeLink *link, *linkn;
bNode *node, *nextn;
- bNodeSocket *gsock, *sock;
+ bNodeSocket *sock;
ListBase anim_basepaths = {NULL, NULL};
- float min[2], max[2];
-
+ float min[2], max[2], center[2];
+ int totselect;
+ int expose_all = FALSE;
+ bNode *input_node, *output_node;
+
+ /* XXX rough guess, not nice but we don't have access to UI constants here ... */
+ static const float offsetx = 200;
+ static const float offsety = 0.0f;
+
/* deselect all nodes in the target tree */
for (node = ngroup->nodes.first; node; node = node->next)
- node_deselect(node);
-
- node_get_selected_minmax(ntree, gnode, min, max);
-
+ nodeSetSelected(node, FALSE);
+
+ totselect = node_get_selected_minmax(ntree, gnode, min, max);
+ add_v2_v2v2(center, min, max);
+ mul_v2_fl(center, 0.5f);
+
+ /* auto-add interface for "solo" nodes */
+ if (totselect == 1)
+ expose_all = TRUE;
+
/* move nodes over */
for (node = ntree->nodes.first; node; node = nextn) {
nextn = node->next;
- if (node == gnode)
- continue;
- if (node->flag & NODE_SELECT) {
- /* keep track of this node's RNA "base" path (the part of the pat identifying the node)
+ if (node_group_make_use_node(node, gnode)) {
+ /* keep track of this node's RNA "base" path (the part of the pat identifying the node)
* if the old nodetree has animation data which potentially covers this node
*/
if (ntree->adt) {
PointerRNA ptr;
char *path;
-
+
RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
path = RNA_path_from_ID_to_struct(&ptr);
-
+
if (path)
BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
}
-
+
/* ensure valid parent pointers, detach if parent stays outside the group */
if (node->parent && !(node->parent->flag & NODE_SELECT))
nodeDetachNode(node);
-
+
/* change node-collection membership */
BLI_remlink(&ntree->nodes, node);
BLI_addtail(&ngroup->nodes, node);
-
+
/* ensure unique node name in the ngroup */
nodeUniqueName(ngroup, node);
-
- node->locx -= 0.5f * (min[0] + max[0]);
- node->locy -= 0.5f * (min[1] + max[1]);
- }
- else {
- /* if the parent is to be inserted but not the child, detach properly */
- if (node->parent && (node->parent->flag & NODE_SELECT))
- nodeDetachNode(node);
}
}
-
+
/* move animation data over */
if (ntree->adt) {
LinkData *ld, *ldn = NULL;
-
+
BKE_animdata_separate_by_basepath(&ntree->id, &ngroup->id, &anim_basepaths);
-
+
/* paths + their wrappers need to be freed */
for (ld = anim_basepaths.first; ld; ld = ldn) {
ldn = ld->next;
-
+
MEM_freeN(ld->data);
BLI_freelinkN(&anim_basepaths, ld);
}
}
-
+
/* node groups don't use internal cached data */
ntreeFreeCache(ngroup);
-
+
+ /* create input node */
+ input_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_INPUT);
+ input_node->locx = min[0] - center[0] - offsetx;
+ input_node->locy = -offsety;
+
+ /* create output node */
+ output_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_OUTPUT);
+ output_node->locx = max[0] - center[0] + offsetx;
+ output_node->locy = -offsety;
+
/* relink external sockets */
for (link = ntree->links.first; link; link = linkn) {
- int fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT) && link->fromnode != gnode);
- int toselect = (link->tonode && (link->tonode->flag & NODE_SELECT) && link->tonode != gnode);
+ int fromselect = node_group_make_use_node(link->fromnode, gnode);
+ int toselect = node_group_make_use_node(link->tonode, gnode);
+
linkn = link->next;
-
+
if ((fromselect && link->tonode == gnode) || (toselect && link->fromnode == gnode)) {
/* remove all links to/from the gnode.
* this can remove link information, but there's no general way to preserve it.
@@ -966,58 +825,94 @@ static int node_group_make_insert_selected(bNodeTree *ntree, bNode *gnode)
BLI_addtail(&ngroup->links, link);
}
else if (toselect) {
- gsock = node_group_expose_socket(ngroup, link->tosock, SOCK_IN);
- link->tosock->link = nodeAddLink(ngroup, NULL, gsock, link->tonode, link->tosock);
- link->tosock = node_group_add_extern_socket(ntree, &gnode->inputs, SOCK_IN, gsock);
+ bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, link->tonode, link->tosock);
+ bNodeSocket *input_sock;
+
+ /* update the group node and interface node sockets,
+ * so the new interface socket can be linked.
+ */
+ node_group_verify(ntree, gnode, (ID *)ngroup);
+ node_group_input_verify(ngroup, input_node, (ID *)ngroup);
+
+ /* create new internal link */
+ input_sock = node_group_input_find_socket(input_node, iosock->identifier);
+ nodeAddLink(ngroup, input_node, input_sock, link->tonode, link->tosock);
+
+ /* redirect external link */
link->tonode = gnode;
+ link->tosock = node_group_find_input_socket(gnode, iosock->identifier);
}
else if (fromselect) {
- /* search for existing group node socket */
- for (gsock = ngroup->outputs.first; gsock; gsock = gsock->next)
- if (gsock->link && gsock->link->fromsock == link->fromsock)
- break;
- if (!gsock) {
- gsock = node_group_expose_socket(ngroup, link->fromsock, SOCK_OUT);
- gsock->link = nodeAddLink(ngroup, link->fromnode, link->fromsock, NULL, gsock);
- link->fromsock = node_group_add_extern_socket(ntree, &gnode->outputs, SOCK_OUT, gsock);
- }
- else
- link->fromsock = node_group_find_output(gnode, gsock);
+ bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, link->fromnode, link->fromsock);
+ bNodeSocket *output_sock;
+
+ /* update the group node and interface node sockets,
+ * so the new interface socket can be linked.
+ */
+ node_group_verify(ntree, gnode, (ID *)ngroup);
+ node_group_output_verify(ngroup, output_node, (ID *)ngroup);
+
+ /* create new internal link */
+ output_sock = node_group_output_find_socket(output_node, iosock->identifier);
+ nodeAddLink(ngroup, link->fromnode, link->fromsock, output_node, output_sock);
+
+ /* redirect external link */
link->fromnode = gnode;
+ link->fromsock = node_group_find_output_socket(gnode, iosock->identifier);
}
}
- /* auto-add interface for "solo" nodes */
- node = ((bNodeTree *)gnode->id)->nodes.first;
- if (node && !node->next) {
- for (sock = node->inputs.first; sock; sock = sock->next) {
- int skip = FALSE;
-
- for (link = ((bNodeTree *)gnode->id)->links.first; link; link = link->next)
- if (link->tosock == sock)
- skip = TRUE;
-
- if (skip == TRUE)
- continue;
-
- gsock = node_group_expose_socket(ngroup, sock, SOCK_IN);
- node_group_add_extern_socket(ntree, &gnode->inputs, SOCK_IN, gsock);
- nodeAddLink(ngroup, NULL, gsock, node, sock);
+ /* move nodes in the group to the center */
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node_group_make_use_node(node, gnode) && !node->parent) {
+ node->locx -= center[0];
+ node->locy -= center[1];
}
-
- for (sock = node->outputs.first; sock; sock = sock->next) {
- int skip = FALSE;
-
- for (link = ((bNodeTree *)gnode->id)->links.first; link; link = link->next)
- if (link->fromsock == sock)
- skip = TRUE;
-
- if (skip == TRUE)
- continue;
-
- gsock = node_group_expose_socket(ngroup, sock, SOCK_OUT);
- node_group_add_extern_socket(ntree, &gnode->outputs, SOCK_OUT, gsock);
- nodeAddLink(ngroup, NULL, gsock, node, sock);
+ }
+
+ /* expose all unlinked sockets too */
+ if (expose_all) {
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node_group_make_use_node(node, gnode)) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ bNodeSocket *iosock, *input_sock;
+ int skip = FALSE;
+ for (link = ngroup->links.first; link; link = link->next) {
+ if (link->tosock == sock) {
+ skip = TRUE;
+ break;
+ }
+ }
+ if (skip)
+ continue;
+
+ iosock = ntreeAddSocketInterfaceFromSocket(ngroup, node, sock);
+
+ node_group_input_verify(ngroup, input_node, (ID *)ngroup);
+
+ /* create new internal link */
+ input_sock = node_group_input_find_socket(input_node, iosock->identifier);
+ nodeAddLink(ngroup, input_node, input_sock, node, sock);
+ }
+
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ bNodeSocket *iosock, *output_sock;
+ int skip = FALSE;
+ for (link = ngroup->links.first; link; link = link->next)
+ if (link->fromsock == sock)
+ skip = TRUE;
+ if (skip)
+ continue;
+
+ iosock = ntreeAddSocketInterfaceFromSocket(ngroup, node, sock);
+
+ node_group_output_verify(ngroup, output_node, (ID *)ngroup);
+
+ /* create new internal link */
+ output_sock = node_group_output_find_socket(output_node, iosock->identifier);
+ nodeAddLink(ngroup, node, sock, output_node, output_sock);
+ }
+ }
}
}
@@ -1025,30 +920,32 @@ static int node_group_make_insert_selected(bNodeTree *ntree, bNode *gnode)
ngroup->update |= NTREE_UPDATE | NTREE_UPDATE_LINKS;
/* update of the tree containing the group instance node */
ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
-
- return 1;
}
-static bNode *node_group_make_from_selected(bNodeTree *ntree)
+static bNode *node_group_make_from_selected(const bContext *C, bNodeTree *ntree, const char *ntype, const char *ntreetype)
{
+ Main *bmain = CTX_data_main(C);
bNode *gnode;
bNodeTree *ngroup;
float min[2], max[2];
- bNodeTemplate ntemp;
-
- node_get_selected_minmax(ntree, NULL, min, max);
-
+ int totselect;
+
+ totselect = node_get_selected_minmax(ntree, NULL, min, max);
+ /* don't make empty group */
+ if (totselect == 0)
+ return NULL;
+
/* new nodetree */
- ngroup = ntreeAddTree("NodeGroup", ntree->type, NODE_GROUP);
-
+ ngroup = ntreeAddTree(bmain, "NodeGroup", ntreetype);
+
/* make group node */
- ntemp.type = NODE_GROUP;
- ntemp.ngroup = ngroup;
- gnode = nodeAddNode(ntree, &ntemp);
+ gnode = nodeAddNode(C, ntree, ntype);
+ gnode->id = (ID *)ngroup;
+
gnode->locx = 0.5f * (min[0] + max[0]);
gnode->locy = 0.5f * (min[1] + max[1]);
-
- node_group_make_insert_selected(ntree, gnode);
+
+ node_group_make_insert_selected(C, ntree, gnode);
/* update of the tree containing the group instance node */
ntree->update |= NTREE_UPDATE_NODES;
@@ -1056,120 +953,116 @@ static bNode *node_group_make_from_selected(bNodeTree *ntree)
return gnode;
}
-typedef enum eNodeGroupMakeType {
- NODE_GM_NEW,
- NODE_GM_INSERT
-} eNodeGroupMakeType;
-
-/* Operator Property */
-EnumPropertyItem node_group_make_types[] = {
- {NODE_GM_NEW, "NEW", 0, "New", "Create a new node group from selected nodes"},
- {NODE_GM_INSERT, "INSERT", 0, "Insert", "Insert into active node group"},
- {0, NULL, 0, NULL, NULL}
-};
-
static int node_group_make_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ char *node_idname, *ntree_idname;
+ bNodeTree *ngroup;
bNode *gnode;
- int type = RNA_enum_get(op->ptr, "type");
-
- if (snode->edittree != snode->nodetree) {
- BKE_report(op->reports, RPT_WARNING, "Cannot add a new group in a group");
- return OPERATOR_CANCELLED;
- }
-
- /* for time being... is too complex to handle */
- if (snode->treetype == NTREE_COMPOSIT) {
- for (gnode = snode->nodetree->nodes.first; gnode; gnode = gnode->next) {
- if (gnode->flag & SELECT)
- if (gnode->type == CMP_NODE_R_LAYERS)
- break;
- }
-
- if (gnode) {
- BKE_report(op->reports, RPT_WARNING, "Cannot add a Render Layers node in a group");
- return OPERATOR_CANCELLED;
- }
- }
-
+
ED_preview_kill_jobs(C);
-
- switch (type) {
- case NODE_GM_NEW:
- if (node_group_make_test(snode->nodetree, NULL)) {
- gnode = node_group_make_from_selected(snode->nodetree);
- }
- else {
- BKE_report(op->reports, RPT_WARNING, "Cannot make group");
- return OPERATOR_CANCELLED;
- }
- break;
- case NODE_GM_INSERT:
- gnode = nodeGetActive(snode->nodetree);
- if (!gnode || gnode->type != NODE_GROUP) {
- BKE_report(op->reports, RPT_WARNING, "No active group node");
- return OPERATOR_CANCELLED;
- }
- if (node_group_make_test(snode->nodetree, gnode)) {
- node_group_make_insert_selected(snode->nodetree, gnode);
- }
- else {
- BKE_report(op->reports, RPT_WARNING, "Cannot insert into group");
- return OPERATOR_CANCELLED;
- }
- break;
+
+ if (!node_group_operator_check_type(C, op, &node_idname, &ntree_idname))
+ return OPERATOR_PASS_THROUGH;
+
+ if (!node_group_make_test_selected(ntree, NULL, ntree_idname, op->reports)) {
+ MEM_freeN(node_idname);
+ MEM_freeN(ntree_idname);
+ return OPERATOR_CANCELLED;
}
-
+
+ gnode = node_group_make_from_selected(C, ntree, node_idname, ntree_idname);
+ MEM_freeN(node_idname);
+ MEM_freeN(ntree_idname);
+
if (gnode) {
- nodeSetActive(snode->nodetree, gnode);
- snode_make_group_editable(snode, gnode);
+ ngroup = (bNodeTree *)gnode->id;
+
+ nodeSetActive(ntree, gnode);
+ if (ngroup) {
+ ED_node_tree_push(snode, ngroup, gnode);
+ ntreeUpdateTree(ngroup);
+ }
}
-
- if (gnode)
- ntreeUpdateTree((bNodeTree *)gnode->id);
- ntreeUpdateTree(snode->nodetree);
+
+ ntreeUpdateTree(ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
-
+
return OPERATOR_FINISHED;
}
-static int node_group_make_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *act = nodeGetActive(snode->edittree);
- uiPopupMenu *pup = uiPupMenuBegin(C, "Make Group", ICON_NONE);
- uiLayout *layout = uiPupMenuLayout(pup);
-
- uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
- uiItemEnumO(layout, "NODE_OT_group_make", NULL, 0, "type", NODE_GM_NEW);
-
- /* if active node is a group, add insert option */
- if (act && act->type == NODE_GROUP) {
- uiItemEnumO(layout, "NODE_OT_group_make", NULL, 0, "type", NODE_GM_INSERT);
- }
-
- uiPupMenuEnd(C, pup);
-
- return OPERATOR_CANCELLED;
-}
-
void NODE_OT_group_make(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Group";
+ ot->name = "Make Group";
ot->description = "Make group from selected nodes";
ot->idname = "NODE_OT_group_make";
-
+
/* api callbacks */
- ot->invoke = node_group_make_invoke;
ot->exec = node_group_make_exec;
ot->poll = ED_operator_node_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ node_group_operator_properties(ot);
+}
+
+/* ****************** Group Insert operator ******************* */
+
+static int node_group_insert_exec(bContext *C, wmOperator *op)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNodeTree *ngroup;
+ char *node_idname;
+ bNode *gnode;
+
+ ED_preview_kill_jobs(C);
+
+ if (!node_group_operator_check_type(C, op, &node_idname, NULL))
+ return OPERATOR_PASS_THROUGH;
+
+ gnode = node_group_get_active(C, node_idname);
+ MEM_freeN(node_idname);
+
+ if (!gnode || !gnode->id)
+ return OPERATOR_CANCELLED;
+
+ ngroup = (bNodeTree *)gnode->id;
+ if (!node_group_make_test_selected(ntree, gnode, ngroup->idname, op->reports))
+ return OPERATOR_CANCELLED;
+
+ node_group_make_insert_selected(C, ntree, gnode);
+
+ nodeSetActive(ntree, gnode);
+ ED_node_tree_push(snode, ngroup, gnode);
+ ntreeUpdateTree(ngroup);
+
+ ntreeUpdateTree(ntree);
+
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
+
+ return OPERATOR_FINISHED;
+}
- RNA_def_enum(ot->srna, "type", node_group_make_types, NODE_GM_NEW, "Type", "");
+void NODE_OT_group_insert(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Group Insert";
+ ot->description = "Insert selected nodes into a node group";
+ ot->idname = "NODE_OT_group_insert";
+
+ /* api callbacks */
+ ot->exec = node_group_insert_exec;
+ ot->poll = ED_operator_node_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ node_group_operator_properties(ot);
}
diff --git a/source/blender/editors/space_node/node_header.c b/source/blender/editors/space_node/node_header.c
index e82917feb21..175bbce756e 100644
--- a/source/blender/editors/space_node/node_header.c
+++ b/source/blender/editors/space_node/node_header.c
@@ -58,186 +58,21 @@
/* ************************ add menu *********************** */
-static void do_node_add(bContext *C, bNodeTemplate *ntemp)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar;
- bNode *node, *node_new;
-
- /* get location to add node at mouse */
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- wmWindow *win = CTX_wm_window(C);
- int x = win->eventstate->x - ar->winrct.xmin;
- int y = win->eventstate->y - ar->winrct.ymin;
-
- if (y < 60) y += 60;
- UI_view2d_region_to_view(&ar->v2d, x, y, &snode->cursor[0], &snode->cursor[1]);
- }
- }
-
- /* store selection in temp test flag */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_SELECT) node->flag |= NODE_TEST;
- else node->flag &= ~NODE_TEST;
- }
-
- node_new = node_add_node(snode, bmain, scene, ntemp, snode->cursor[0], snode->cursor[1]);
-
- /* select previous selection before autoconnect */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_TEST) node->flag |= NODE_SELECT;
- }
-
- /* deselect after autoconnection */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_TEST) node->flag &= ~NODE_SELECT;
- }
-
- /* once this is called from an operator, this should be removed */
- if (node_new) {
- char undostr[BKE_UNDO_STR_MAX];
- BLI_snprintf(undostr, sizeof(undostr), "Add Node %s", nodeLabel(node_new));
- BKE_write_undo(C, undostr);
- }
-
- snode_notify(C, snode);
- snode_dag_update(C, snode);
-}
-
-static void do_node_add_static(bContext *C, void *UNUSED(arg), int event)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- bNodeTemplate ntemp;
-
- ntemp.type = event;
- ntemp.main = bmain;
- ntemp.scene = scene;
-
- do_node_add(C, &ntemp);
-}
-
-static void do_node_add_group(bContext *C, void *UNUSED(arg), int event)
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- bNodeTemplate ntemp;
-
- if (event >= 0) {
- ntemp.ngroup = BLI_findlink(&G.main->nodetree, event);
- ntemp.type = ntemp.ngroup->nodetype;
- }
- else {
- ntemp.type = -event;
- switch (ntemp.type) {
- case NODE_GROUP:
- ntemp.ngroup = ntreeAddTree("Group", snode->treetype, ntemp.type);
- break;
- default:
- ntemp.ngroup = NULL;
- }
- }
- if (!ntemp.ngroup)
- return;
-
- ntemp.main = bmain;
- ntemp.scene = scene;
-
- do_node_add(C, &ntemp);
-}
-
-static int node_tree_has_type(int treetype, int nodetype)
-{
- bNodeTreeType *ttype = ntreeGetType(treetype);
- bNodeType *ntype;
- for (ntype = ttype->node_types.first; ntype; ntype = ntype->next) {
- if (ntype->type == nodetype)
- return 1;
- }
- return 0;
-}
-
-static void node_add_menu(bContext *C, uiLayout *layout, void *arg_nodeclass)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree;
- int nodeclass = GET_INT_FROM_POINTER(arg_nodeclass);
- int event, compatibility = 0;
-
- ntree = snode->nodetree;
-
- if (!ntree) {
- uiItemS(layout);
- return;
- }
-
- if (ntree->type == NTREE_SHADER) {
- if (BKE_scene_use_new_shading_nodes(scene))
- compatibility = NODE_NEW_SHADING;
- else
- compatibility = NODE_OLD_SHADING;
- }
-
- if (nodeclass == NODE_CLASS_GROUP) {
- bNodeTree *ngroup;
-
- uiLayoutSetFunc(layout, do_node_add_group, NULL);
-
- /* XXX hack: negative numbers used for empty group types */
- if (node_tree_has_type(ntree->type, NODE_GROUP))
- uiItemV(layout, IFACE_("New Group"), 0, -NODE_GROUP);
- uiItemS(layout);
-
- for (ngroup = bmain->nodetree.first, event = 0; ngroup; ngroup = ngroup->id.next, ++event) {
- /* only use group trees */
- if (ngroup->type == ntree->type && ngroup->nodetype == NODE_GROUP) {
- uiItemV(layout, ngroup->id.name + 2, 0, event);
- }
- }
- }
- else {
- bNodeType *ntype;
-
- uiLayoutSetFunc(layout, do_node_add_static, NULL);
-
- for (ntype = ntreeGetType(ntree->type)->node_types.first; ntype; ntype = ntype->next) {
- if (ntype->nclass == nodeclass && ntype->name) {
- if (!compatibility || (ntype->compatibility & compatibility)) {
- uiItemV(layout, IFACE_(ntype->name), 0, ntype->type);
- }
- }
- }
- }
-}
-
-static void node_menu_add_foreach_cb(void *calldata, int nclass, const char *name)
-{
- uiLayout *layout = calldata;
- uiItemMenuF(layout, IFACE_(name), 0, node_add_menu, SET_INT_IN_POINTER(nclass));
-}
-
static void node_menu_add(const bContext *C, Menu *menu)
{
- Scene *scene = CTX_data_scene(C);
SpaceNode *snode = CTX_wm_space_node(C);
uiLayout *layout = menu->layout;
- bNodeTreeType *ntreetype = ntreeGetType(snode->treetype);
+ bNodeTree *ntree = snode->edittree;
- if (!snode->nodetree)
+ if (!ntree || !ntree->typeinfo || !ntree->typeinfo->draw_add_menu) {
uiLayoutSetActive(layout, FALSE);
-
+ return;
+ }
+
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
- uiItemO(layout, "Search ...", 0, "NODE_OT_add_search");
+ uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Search ..."), 0, "NODE_OT_add_search");
- if (ntreetype && ntreetype->foreach_nodeclass)
- ntreetype->foreach_nodeclass(scene, layout, node_menu_add_foreach_cb);
+ ntree->typeinfo->draw_add_menu(C, layout, ntree);
}
void node_menus_register(void)
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 45509e02226..2f6090d67ce 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -32,6 +32,7 @@
#define __NODE_INTERN_H__
#include <stddef.h> /* for size_t */
+#include "BKE_node.h"
#include "UI_interface.h"
/* internal exports only */
@@ -43,11 +44,11 @@ struct bContext;
struct wmWindow;
struct wmWindowManager;
struct wmEvent;
-struct bNodeTemplate;
struct bNode;
struct bNodeSocket;
struct bNodeLink;
struct Main;
+struct wmKeyConfig;
/* temp data to pass on to modal */
typedef struct bNodeLinkDrag {
@@ -63,36 +64,47 @@ typedef struct bNodeLinkDrag {
/* space_node.c */
ARegion *node_has_buttons_region(ScrArea *sa);
+ARegion *node_has_tools_region(ScrArea *sa);
+
+void snode_group_offset(struct SpaceNode *snode, float *x, float *y); /* transform between View2Ds in the tree path */
/* node_header.c */
void node_menus_register(void);
/* node_draw.c */
int node_get_colorid(struct bNode *node);
-void node_socket_circle_draw(struct bNodeTree *ntree, struct bNodeSocket *sock, float size, int highlight);
+void node_socket_circle_draw(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node,
+ struct bNodeSocket *sock, float size, int highlight);
int node_get_resize_cursor(int directions);
void node_draw_shadow(struct SpaceNode *snode, struct bNode *node, float radius, float alpha);
-void node_draw_default(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node);
+void node_draw_default(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode,
+ struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key);
void node_update_default(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node);
int node_select_area_default(struct bNode *node, int x, int y);
int node_tweak_area_default(struct bNode *node, int x, int y);
-void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree, float offsetx, float offsety);
-void node_draw_nodetree(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree);
-void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d);
+void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree);
+void node_draw_nodetree(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode,
+ struct bNodeTree *ntree, bNodeInstanceKey parent_key);
+void drawnodespace(const bContext *C, ARegion *ar);
void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode);
+ /* DPI scaled coords */
+void node_to_view(struct bNode *node, float x, float y, float *rx, float *ry);
+void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry);
/* node_buttons.c */
void node_buttons_register(struct ARegionType *art);
void NODE_OT_properties(struct wmOperatorType *ot);
+/* node_toolbar.c */
+void node_toolbar_register(struct ARegionType *art);
+void NODE_OT_toolbar(struct wmOperatorType *ot);
+
/* node_ops.c */
void node_operatortypes(void);
-void node_keymap(wmKeyConfig *keyconf);
+void node_keymap(struct wmKeyConfig *keyconf);
/* node_select.c */
-void node_select(struct bNode *node);
-void node_deselect(struct bNode *node);
void node_deselect_all(struct SpaceNode *snode);
void node_socket_select(struct bNode *node, struct bNodeSocket *sock);
void node_socket_deselect(struct bNode *node, struct bNodeSocket *sock, int deselect_node);
@@ -103,14 +115,14 @@ int node_select_same_type_np(struct SpaceNode *snode, int dir);
void node_select_single(struct bContext *C, struct bNode *node);
void NODE_OT_select(struct wmOperatorType *ot);
-void NODE_OT_select_all(wmOperatorType *ot);
-void NODE_OT_select_linked_to(wmOperatorType *ot);
-void NODE_OT_select_linked_from(wmOperatorType *ot);
+void NODE_OT_select_all(struct wmOperatorType *ot);
+void NODE_OT_select_linked_to(struct wmOperatorType *ot);
+void NODE_OT_select_linked_from(struct wmOperatorType *ot);
void NODE_OT_select_border(struct wmOperatorType *ot);
void NODE_OT_select_lasso(struct wmOperatorType *ot);
void NODE_OT_select_same_type(struct wmOperatorType *ot);
-void NODE_OT_select_same_type_next(wmOperatorType *ot);
-void NODE_OT_select_same_type_prev(wmOperatorType *ot);
+void NODE_OT_select_same_type_next(struct wmOperatorType *ot);
+void NODE_OT_select_same_type_prev(struct wmOperatorType *ot);
/* node_view.c */
void NODE_OT_view_all(struct wmOperatorType *ot);
@@ -118,24 +130,26 @@ void NODE_OT_view_selected(struct wmOperatorType *ot);
void NODE_OT_backimage_move(struct wmOperatorType *ot);
void NODE_OT_backimage_zoom(struct wmOperatorType *ot);
-void NODE_OT_backimage_sample(wmOperatorType *ot);
+void NODE_OT_backimage_sample(struct wmOperatorType *ot);
/* drawnode.c */
-void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link);
-void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3);
-int node_link_bezier_points(View2D * v2d, SpaceNode * snode, bNodeLink * link, float coord_array[][2], int resol);
+void node_draw_link(struct View2D *v2d, struct SpaceNode *snode, struct bNodeLink *link);
+void node_draw_link_bezier(struct View2D *v2d, struct SpaceNode *snode, struct bNodeLink *link, int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3);
+int node_link_bezier_points(struct View2D * v2d, struct SpaceNode * snode, struct bNodeLink * link, float coord_array[][2], int resol);
// void node_draw_link_straight(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3 );
-void draw_nodespace_back_pix(const struct bContext *C, ARegion *ar, SpaceNode *snode);
+void draw_nodespace_back_pix(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode);
/* node_add.c */
-bNode *node_add_node(struct SpaceNode *snode, struct Main *bmain, struct Scene *scene,
- struct bNodeTemplate *ntemp, float locx, float locy);
+bNode *node_add_node(const struct bContext *C, const char *idname, int type, float locx, float locy);
void NODE_OT_add_reroute(struct wmOperatorType *ot);
+void NODE_OT_add_file(struct wmOperatorType *ot);
+void NODE_OT_new_node_tree(struct wmOperatorType *ot);
/* node_group.c */
void NODE_OT_group_make(struct wmOperatorType *ot);
+void NODE_OT_group_insert(struct wmOperatorType *ot);
void NODE_OT_group_ungroup(struct wmOperatorType *ot);
void NODE_OT_group_separate(struct wmOperatorType *ot);
void NODE_OT_group_edit(struct wmOperatorType *ot);
@@ -145,11 +159,6 @@ void NODE_OT_group_socket_move_up(struct wmOperatorType *ot);
void NODE_OT_group_socket_move_down(struct wmOperatorType *ot);
-/* note_add.c */
-void NODE_OT_add_file(struct wmOperatorType *ot);
-void NODE_OT_new_node_tree(struct wmOperatorType *ot);
-
-
/* node_relationships.c */
void NODE_OT_link(struct wmOperatorType *ot);
void NODE_OT_link_make(struct wmOperatorType *ot);
@@ -166,11 +175,9 @@ void NODE_OT_show_cyclic_dependencies(struct wmOperatorType *ot);
void NODE_OT_link_viewer(struct wmOperatorType *ot);
/* node_edit.c */
-void node_tree_from_ID(ID *id, bNodeTree **ntree, bNodeTree **edittree, int *treetype);
-void snode_notify(bContext *C, SpaceNode *snode);
-void snode_dag_update(bContext *C, SpaceNode *snode);
-void snode_set_context(SpaceNode *snode, Scene *scene);
-void snode_make_group_editable(SpaceNode *snode, bNode *gnode);
+void snode_notify(struct bContext *C, struct SpaceNode *snode);
+void snode_dag_update(struct bContext *C, struct SpaceNode *snode);
+void snode_set_context(const struct bContext *C);
bNode *node_tree_get_editgroup(bNodeTree *ntree);
void snode_update(struct SpaceNode *snode, struct bNode *node);
@@ -179,7 +186,7 @@ int composite_node_active(struct bContext *C);
int node_has_hidden_sockets(bNode *node);
void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set);
-int node_render_changed_exec(bContext *, wmOperator *);
+int node_render_changed_exec(bContext *, struct wmOperator *);
int node_find_indicated_socket(struct SpaceNode *snode, struct bNode **nodep, struct bNodeSocket **sockp, int in_out);
void NODE_OT_duplicate(struct wmOperatorType *ot);
@@ -206,23 +213,31 @@ void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot);
void NODE_OT_clipboard_copy(struct wmOperatorType *ot);
void NODE_OT_clipboard_paste(struct wmOperatorType *ot);
+void NODE_OT_tree_socket_add(struct wmOperatorType *ot);
+void NODE_OT_tree_socket_remove(struct wmOperatorType *ot);
+void NODE_OT_tree_socket_move(struct wmOperatorType *ot);
+
void NODE_OT_shader_script_update(struct wmOperatorType *ot);
+void NODE_OT_viewer_border(struct wmOperatorType *ot);
+
extern const char *node_context_dir[];
// XXXXXX
-// XXX from BSE_node.h
-#define HIDDEN_RAD 15.0f
-#define BASIS_RAD 8.0f
+// nodes draw without dpi - the view zoom is flexible
+#define HIDDEN_RAD (0.75f * U.widget_unit)
+#define BASIS_RAD (0.4f * U.widget_unit)
#define NODE_DYS (U.widget_unit / 2)
#define NODE_DY U.widget_unit
-#define NODE_MARGIN_X 15
-#define NODE_SOCKSIZE 5
+#define NODE_SOCKDY (0.08f * U.widget_unit)
+#define NODE_WIDTH(node) (node->width * 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
// XXX button events (butspace)
-enum {
+enum eNodeSpace_ButEvents {
B_NOP = 0,
B_REDR = 1,
B_NODE_USEMAT,
@@ -239,6 +254,6 @@ enum {
B_MATPRV,
B_NODE_LOADIMAGE,
B_NODE_SETIMAGE,
-} eNodeSpace_ButEvents;
+};
#endif /* __NODE_INTERN_H__ */
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c
index 64e5f67a348..1e4e02b6ae1 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.c
@@ -49,6 +49,7 @@
void node_operatortypes(void)
{
WM_operatortype_append(NODE_OT_properties);
+ WM_operatortype_append(NODE_OT_toolbar);
WM_operatortype_append(NODE_OT_select);
WM_operatortype_append(NODE_OT_select_all);
@@ -83,13 +84,10 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_add_reroute);
WM_operatortype_append(NODE_OT_group_make);
+ WM_operatortype_append(NODE_OT_group_insert);
WM_operatortype_append(NODE_OT_group_ungroup);
WM_operatortype_append(NODE_OT_group_separate);
WM_operatortype_append(NODE_OT_group_edit);
- WM_operatortype_append(NODE_OT_group_socket_add);
- WM_operatortype_append(NODE_OT_group_socket_remove);
- WM_operatortype_append(NODE_OT_group_socket_move_up);
- WM_operatortype_append(NODE_OT_group_socket_move_down);
WM_operatortype_append(NODE_OT_link_viewer);
@@ -119,6 +117,12 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_clipboard_paste);
WM_operatortype_append(NODE_OT_shader_script_update);
+
+ WM_operatortype_append(NODE_OT_viewer_border);
+
+ WM_operatortype_append(NODE_OT_tree_socket_add);
+ WM_operatortype_append(NODE_OT_tree_socket_remove);
+ WM_operatortype_append(NODE_OT_tree_socket_move);
}
void ED_operatormacros_node(void)
@@ -195,6 +199,29 @@ static void node_select_keymap(wmKeyMap *keymap, int extend)
}
}
+/* register group operators for a specific group node type */
+static void node_group_operators(wmKeyMap *keymap, const char *node_type)
+{
+ wmKeyMapItem *kmi;
+
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_group_make", GKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_string_set(kmi->ptr, "node_type", node_type);
+
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_group_ungroup", GKEY, KM_PRESS, KM_ALT, 0);
+ RNA_string_set(kmi->ptr, "node_type", node_type);
+
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_group_separate", PKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "node_type", node_type);
+
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "node_type", node_type);
+ RNA_boolean_set(kmi->ptr, "exit", FALSE);
+
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_string_set(kmi->ptr, "node_type", node_type);
+ RNA_boolean_set(kmi->ptr, "exit", TRUE);
+}
+
void node_keymap(struct wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
@@ -204,6 +231,7 @@ void node_keymap(struct wmKeyConfig *keyconf)
keymap = WM_keymap_find(keyconf, "Node Generic", SPACE_NODE, 0);
WM_keymap_add_item(keymap, "NODE_OT_properties", NKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "NODE_OT_toolbar", TKEY, KM_PRESS, 0, 0);
/* Main Area only ----------------- */
keymap = WM_keymap_find(keyconf, "Node Editor", SPACE_NODE, 0);
@@ -226,9 +254,18 @@ void node_keymap(struct wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "deselect", TRUE);
/* each of these falls through if not handled... */
- WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "detach", FALSE);
+ RNA_boolean_set(kmi->ptr, "expose", FALSE);
kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "detach", TRUE);
+ RNA_boolean_set(kmi->ptr, "expose", FALSE);
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "detach", FALSE);
+ RNA_boolean_set(kmi->ptr, "expose", TRUE);
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "detach", TRUE);
+ RNA_boolean_set(kmi->ptr, "expose", TRUE);
WM_keymap_add_item(keymap, "NODE_OT_resize", LEFTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NODE_OT_add_reroute", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
@@ -284,11 +321,10 @@ void node_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "NODE_OT_select_same_type_next", RIGHTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "NODE_OT_select_same_type_prev", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_add_item(keymap, "NODE_OT_group_make", GKEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_add_item(keymap, "NODE_OT_group_ungroup", GKEY, KM_PRESS, KM_ALT, 0);
- WM_keymap_add_item(keymap, "NODE_OT_group_separate", PKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, 0, 0);
-
+ node_group_operators(keymap, "ShaderNodeGroup");
+ node_group_operators(keymap, "CompositorNodeGroup");
+ node_group_operators(keymap, "TextureNodeGroup");
+
WM_keymap_add_item(keymap, "NODE_OT_read_renderlayers", RKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "NODE_OT_read_fullsamplelayers", RKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "NODE_OT_render_changed", ZKEY, KM_PRESS, 0, 0);
@@ -296,5 +332,7 @@ void node_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "NODE_OT_clipboard_copy", CKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "NODE_OT_clipboard_paste", VKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "NODE_OT_viewer_border", BKEY, KM_PRESS, KM_CTRL, 0);
+
transform_keymap_for_space(keyconf, keymap, SPACE_NODE);
}
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index 7fa48c48ad6..8ff964aa932 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -54,6 +54,7 @@
#include "UI_view2d.h"
#include "node_intern.h" /* own include */
+#include "NOD_common.h"
/* ****************** Add *********************** */
@@ -107,7 +108,7 @@ static bNodeSocket *best_socket_output(bNodeTree *ntree, bNode *node, bNodeSocke
/* check for same types */
if (sock->type == sock_target->type) {
- if (strcmp(sock->name, sock_target->name) == 0)
+ if (STREQ(sock->name, sock_target->name))
return sock;
}
}
@@ -323,13 +324,8 @@ static int node_link_viewer(const bContext *C, bNode *tonode)
if (sock) {
/* add a new viewer if none exists yet */
if (!node) {
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- bNodeTemplate ntemp;
-
- ntemp.type = CMP_NODE_VIEWER;
/* XXX location is a quick hack, just place it next to the linked socket */
- node = node_add_node(snode, bmain, scene, &ntemp, sock->locx + 100, sock->locy);
+ node = node_add_node(C, NULL, CMP_NODE_VIEWER, sock->locx + 100, sock->locy);
if (!node)
return OPERATOR_CANCELLED;
@@ -364,7 +360,7 @@ static int node_active_link_viewer(bContext *C, wmOperator *UNUSED(op))
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
- node = editnode_get_active(snode->edittree);
+ node = nodeGetActive(snode->edittree);
if (!node)
return OPERATOR_CANCELLED;
@@ -434,21 +430,9 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeSocket *tsock, bNodeL
}
}
-static int outside_group_rect(SpaceNode *snode)
-{
- bNode *gnode = node_tree_get_editgroup(snode->nodetree);
- if (gnode) {
- return (snode->cursor[0] < gnode->totr.xmin ||
- snode->cursor[0] >= gnode->totr.xmax ||
- snode->cursor[1] < gnode->totr.ymin ||
- snode->cursor[1] >= gnode->totr.ymax);
- }
- return 0;
-}
-
/* loop that adds a nodelink, called by function below */
/* in_out = starting socket */
-static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceNode *snode = CTX_wm_space_node(C);
ARegion *ar = CTX_wm_region(C);
@@ -459,55 +443,41 @@ static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event)
bNodeLink *link;
LinkData *linkdata;
int in_out;
+ int expose;
in_out = nldrag->in_out;
-
+
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
&snode->cursor[0], &snode->cursor[1]);
+ expose = RNA_boolean_get(op->ptr, "expose");
+
switch (event->type) {
case MOUSEMOVE:
-
+
if (in_out == SOCK_OUT) {
if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_IN)) {
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
-
+
/* skip if this is already the target socket */
if (link->tosock == tsock)
continue;
/* skip if socket is on the same node as the fromsock */
if (tnode && link->fromnode == tnode)
continue;
-
+
/* attach links to the socket */
link->tonode = tnode;
link->tosock = tsock;
- /* add it to the node tree temporarily */
- if (BLI_findindex(&ntree->links, link) < 0)
- BLI_addtail(&ntree->links, link);
-
- ntree->update |= NTREE_UPDATE_LINKS;
}
- ntreeUpdateTree(ntree);
}
else {
- int do_update = FALSE;
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
-
- if (link->tonode || link->tosock) {
- BLI_remlink(&ntree->links, link);
- link->prev = link->next = NULL;
- link->tonode = NULL;
- link->tosock = NULL;
-
- ntree->update |= NTREE_UPDATE_LINKS;
- do_update = TRUE;
- }
- }
- if (do_update) {
- ntreeUpdateTree(ntree);
+
+ link->tonode = NULL;
+ link->tosock = NULL;
}
}
}
@@ -515,108 +485,126 @@ static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event)
if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_OUT)) {
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
-
+
/* skip if this is already the target socket */
if (link->fromsock == tsock)
continue;
/* skip if socket is on the same node as the fromsock */
if (tnode && link->tonode == tnode)
continue;
-
+
/* attach links to the socket */
link->fromnode = tnode;
link->fromsock = tsock;
- /* add it to the node tree temporarily */
- if (BLI_findindex(&ntree->links, link) < 0)
- BLI_addtail(&ntree->links, link);
-
- ntree->update |= NTREE_UPDATE_LINKS;
}
- ntreeUpdateTree(ntree);
}
else {
- int do_update = FALSE;
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
-
- if (link->fromnode || link->fromsock) {
- BLI_remlink(&ntree->links, link);
- link->prev = link->next = NULL;
- link->fromnode = NULL;
- link->fromsock = NULL;
-
- ntree->update |= NTREE_UPDATE_LINKS;
- do_update = TRUE;
- }
- }
- if (do_update) {
- ntreeUpdateTree(ntree);
+
+ link->fromnode = NULL;
+ link->fromsock = NULL;
}
}
}
-
+
ED_region_tag_redraw(ar);
break;
-
+
case LEFTMOUSE:
case RIGHTMOUSE:
case MIDDLEMOUSE:
{
+ /* XXX expose + detach could have some ugly corner cases and is not great.
+ * The first link will define the exposed socket type, which is arbitrary.
+ * Some of the resulting links may turn out to be invalid.
+ */
+ bNode *ionode = NULL;
+ bNodeSocket *iosock = NULL, *gsock;
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
-
+
if (link->tosock && link->fromsock) {
- /* send changed events for original tonode and new */
- if (link->tonode)
- snode_update(snode, link->tonode);
-
+ /* add link to the node tree */
+ BLI_addtail(&ntree->links, link);
+
+ ntree->update |= NTREE_UPDATE_LINKS;
+
+ /* tag tonode for update */
+ link->tonode->update |= NODE_UPDATE;
+
/* we might need to remove a link */
if (in_out == SOCK_OUT)
node_remove_extra_links(snode, link->tosock, link);
-
- /* when linking to group outputs, update the socket type */
- /* XXX this should all be part of a generic update system */
- if (!link->tonode) {
- if (link->tosock->type != link->fromsock->type)
- nodeSocketSetType(link->tosock, link->fromsock->type);
- }
}
- else if (outside_group_rect(snode) && (link->tonode || link->fromnode)) {
- /* automatically add new group socket */
- if (link->tonode && link->tosock) {
- link->fromsock = node_group_expose_socket(ntree, link->tosock, SOCK_IN);
- link->fromnode = NULL;
- if (BLI_findindex(&ntree->links, link) < 0)
- BLI_addtail(&ntree->links, link);
-
+ else if (expose) {
+ if (link->tosock) {
+ if (!ionode) {
+ ionode = nodeAddStaticNode(C, snode->edittree, NODE_GROUP_INPUT);
+ gsock = ntreeAddSocketInterfaceFromSocket(snode->edittree, link->tonode, link->tosock);
+ node_group_input_verify(snode->edittree, ionode, (ID *)snode->edittree);
+ iosock = node_group_input_find_socket(ionode, gsock->identifier);
+
+ {
+ /* place the node at the mouse pointer */
+ float sockx = 42.0f + 3 * HIDDEN_RAD; /* XXX totally arbitrary initial hidden node size ... */
+ float socky = -HIDDEN_RAD;
+
+ ionode->locx = snode->cursor[0] - sockx;
+ ionode->locy = snode->cursor[1] - socky;
+ }
+ }
+ link->fromnode = ionode;
+ link->fromsock = iosock;
+
+ BLI_addtail(&ntree->links, link);
+
ntree->update |= NTREE_UPDATE_GROUP_IN | NTREE_UPDATE_LINKS;
}
- else if (link->fromnode && link->fromsock) {
- link->tosock = node_group_expose_socket(ntree, link->fromsock, SOCK_OUT);
- link->tonode = NULL;
- if (BLI_findindex(&ntree->links, link) < 0)
- BLI_addtail(&ntree->links, link);
-
+ else if (link->fromsock) {
+ if (!ionode) {
+ ionode = nodeAddStaticNode(C, snode->edittree, NODE_GROUP_OUTPUT);
+ gsock = ntreeAddSocketInterfaceFromSocket(snode->edittree, link->fromnode, link->fromsock);
+ node_group_output_verify(snode->edittree, ionode, (ID *)snode->edittree);
+ iosock = node_group_output_find_socket(ionode, gsock->identifier);
+
+ {
+ /* place the node at the mouse pointer */
+ float sockx = 0;
+ float socky = -HIDDEN_RAD;
+
+ ionode->locx = snode->cursor[0] - sockx;
+ ionode->locy = snode->cursor[1] - socky;
+ }
+ }
+ link->tonode = ionode;
+ link->tosock = iosock;
+
+ BLI_addtail(&ntree->links, link);
+
ntree->update |= NTREE_UPDATE_GROUP_OUT | NTREE_UPDATE_LINKS;
}
+ else {
+ nodeRemLink(snode->edittree, link);
+ }
}
else
nodeRemLink(ntree, link);
}
-
+
ntreeUpdateTree(ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
-
+
BLI_remlink(&snode->linkdrag, nldrag);
/* links->data pointers are either held by the tree or freed already */
BLI_freelistN(&nldrag->links);
MEM_freeN(nldrag);
-
+
return OPERATOR_FINISHED;
}
}
-
+
return OPERATOR_RUNNING_MODAL;
}
@@ -646,6 +634,8 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
*oplink = *link;
oplink->next = oplink->prev = NULL;
+ oplink->flag |= NODE_LINK_VALID;
+
BLI_addtail(&nldrag->links, linkdata);
nodeRemLink(snode->edittree, link);
}
@@ -659,6 +649,8 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
oplink->fromnode = node;
oplink->fromsock = sock;
+ oplink->flag |= NODE_LINK_VALID;
+
BLI_addtail(&nldrag->links, linkdata);
}
}
@@ -678,9 +670,11 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
*oplink = *link;
oplink->next = oplink->prev = NULL;
+ oplink->flag |= NODE_LINK_VALID;
+
BLI_addtail(&nldrag->links, linkdata);
nodeRemLink(snode->edittree, link);
-
+
/* send changed event to original link->tonode */
if (node)
snode_update(snode, node);
@@ -695,6 +689,8 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
oplink->tonode = node;
oplink->tosock = sock;
+ oplink->flag |= NODE_LINK_VALID;
+
BLI_addtail(&nldrag->links, linkdata);
}
}
@@ -702,7 +698,7 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
return nldrag;
}
-static int node_link_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceNode *snode = CTX_wm_space_node(C);
ARegion *ar = CTX_wm_region(C);
@@ -760,6 +756,7 @@ void NODE_OT_link(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
RNA_def_boolean(ot->srna, "detach", FALSE, "Detach", "Detach and redirect existing links");
+ RNA_def_boolean(ot->srna, "expose", FALSE, "Expose", "Expose the socket as an interface node");
}
/* ********************** Make Link operator ***************** */
@@ -840,9 +837,13 @@ static int cut_links_exec(bContext *C, wmOperator *op)
if (i > 1) {
int found = FALSE;
bNodeLink *link, *next;
-
+
+ ED_preview_kill_jobs(C);
+
for (link = snode->edittree->links.first; link; link = next) {
next = link->next;
+ if (nodeLinkIsHidden(link))
+ continue;
if (cut_links_intersect(link, mcoords, i)) {
@@ -876,7 +877,7 @@ void NODE_OT_links_cut(wmOperatorType *ot)
{
PropertyRNA *prop;
- ot->name = "Cut links";
+ ot->name = "Cut Links";
ot->idname = "NODE_OT_links_cut";
ot->description = "Use the mouse to cut (remove) some links";
@@ -1073,11 +1074,8 @@ static void node_join_attach_recursive(bNode *node, bNode *frame)
static int node_join_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceNode *snode = CTX_wm_space_node(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
bNodeTree *ntree = snode->edittree;
bNode *node, *frame;
- bNodeTemplate ntemp;
/* XXX save selection: node_add_node call below sets the new frame as single active+selected node */
for (node = ntree->nodes.first; node; node = node->next) {
@@ -1087,10 +1085,7 @@ static int node_join_exec(bContext *C, wmOperator *UNUSED(op))
node->flag &= ~NODE_TEST;
}
- ntemp.main = bmain;
- ntemp.scene = scene;
- ntemp.type = NODE_FRAME;
- frame = node_add_node(snode, bmain, scene, &ntemp, 0.0f, 0.0f);
+ frame = node_add_node(C, NULL, NODE_FRAME, 0.0f, 0.0f);
/* reset tags */
for (node = ntree->nodes.first; node; node = node->next)
@@ -1181,7 +1176,7 @@ static int node_attach_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-static int node_attach_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int node_attach_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
@@ -1308,6 +1303,9 @@ static SpaceNode *ed_node_link_conditions(ScrArea *sa, bNode **select)
/* test node for links */
for (link = snode->edittree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
+
if (link->tonode == *select || link->fromnode == *select)
return NULL;
}
@@ -1348,7 +1346,9 @@ void ED_node_link_intersect_test(ScrArea *sa, int test)
/* we only tag a single link for intersect now */
/* idea; use header dist when more? */
for (link = snode->edittree->links.first; link; link = link->next) {
-
+ if (nodeLinkIsHidden(link))
+ continue;
+
if (cut_links_intersect(link, mcoords, 5)) { /* intersect code wants edges */
if (selink)
break;
@@ -1413,11 +1413,12 @@ void ED_node_link_insert(ScrArea *sa)
link->tonode = select;
link->tosock = socket_best_match(&select->inputs);
+ node_remove_extra_links(snode, link->tosock, link);
link->flag &= ~NODE_LINKFLAG_HILITE;
nodeAddLink(snode->edittree, select, socket_best_match(&select->outputs), node, sockto);
ntreeUpdateTree(snode->edittree); /* needed for pointers */
snode_update(snode, select);
- ED_node_changed_update(snode->id, 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 a3efa15c54a..faebeabdbba 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -30,14 +30,14 @@
#include "DNA_node_types.h"
-#include "BKE_context.h"
-#include "BKE_main.h"
-#include "BKE_node.h"
-
#include "BLI_rect.h"
#include "BLI_lasso.h"
#include "BLI_utildefines.h"
+#include "BKE_context.h"
+#include "BKE_main.h"
+#include "BKE_node.h"
+
#include "ED_node.h" /* own include */
#include "ED_screen.h"
#include "ED_types.h"
@@ -82,30 +82,9 @@ static bNode *node_under_mouse_tweak(bNodeTree *ntree, int mx, int my)
return NULL;
}
-void node_select(bNode *node)
-{
- node->flag |= SELECT;
-}
-
-void node_deselect(bNode *node)
-{
- bNodeSocket *sock;
-
- node->flag &= ~SELECT;
-
- /* deselect sockets too */
- for (sock = node->inputs.first; sock; sock = sock->next)
- sock->flag &= ~SELECT;
- for (sock = node->outputs.first; sock; sock = sock->next)
- sock->flag &= ~SELECT;
-}
-
static void node_toggle(bNode *node)
{
- if (node->flag & SELECT)
- node_deselect(node);
- else
- node_select(node);
+ nodeSetSelected(node, !(node->flag & SELECT));
}
void node_socket_select(bNode *node, bNodeSocket *sock)
@@ -157,7 +136,7 @@ void node_deselect_all(SpaceNode *snode)
bNode *node;
for (node = snode->edittree->nodes.first; node; node = node->next)
- node_deselect(node);
+ nodeSetSelected(node, FALSE);
}
void node_deselect_all_input_sockets(SpaceNode *snode, int deselect_nodes)
@@ -189,9 +168,6 @@ void node_deselect_all_input_sockets(SpaceNode *snode, int deselect_nodes)
node->flag &= ~SELECT;
}
}
-
- for (sock = snode->edittree->outputs.first; sock; sock = sock->next)
- sock->flag &= ~SELECT;
}
void node_deselect_all_output_sockets(SpaceNode *snode, int deselect_nodes)
@@ -223,9 +199,6 @@ void node_deselect_all_output_sockets(SpaceNode *snode, int deselect_nodes)
node->flag &= ~SELECT;
}
}
-
- for (sock = snode->edittree->inputs.first; sock; sock = sock->next)
- sock->flag &= ~SELECT;
}
/* return 1 if we need redraw otherwise zero. */
@@ -249,12 +222,12 @@ int node_select_same_type(SpaceNode *snode)
if (p->type != nac->type && p->flag & SELECT) {
/* if it's selected but different type, unselect */
redraw = 1;
- node_deselect(p);
+ nodeSetSelected(p, FALSE);
}
else if (p->type == nac->type && (!(p->flag & SELECT))) {
/* if it's the same type and is not selected, select! */
redraw = 1;
- node_select(p);
+ nodeSetSelected(p, TRUE);
}
}
return(redraw);
@@ -296,8 +269,8 @@ int node_select_same_type_np(SpaceNode *snode, int dir)
if (p) {
for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next)
if (tnode != p)
- node_deselect(tnode);
- node_select(p);
+ nodeSetSelected(tnode, FALSE);
+ nodeSetSelected(p, TRUE);
return(1);
}
return(0);
@@ -311,8 +284,8 @@ void node_select_single(bContext *C, bNode *node)
for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next)
if (tnode != node)
- node_deselect(tnode);
- node_select(node);
+ nodeSetSelected(tnode, FALSE);
+ nodeSetSelected(node, TRUE);
ED_node_set_active(bmain, snode->edittree, node);
@@ -386,9 +359,10 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i
node = node_under_mouse_select(snode->edittree, mx, my);
if (node) {
- for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next)
- node_deselect(tnode);
- node_select(node);
+ for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
+ nodeSetSelected(tnode, false);
+ }
+ nodeSetSelected(node, TRUE);
ED_node_set_active(bmain, snode->edittree, node);
selected = 1;
}
@@ -429,7 +403,7 @@ static int node_select_exec(bContext *C, wmOperator *op)
}
}
-static int node_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int node_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
RNA_int_set(op->ptr, "mouse_x", event->mval[0]);
RNA_int_set(op->ptr, "mouse_y", event->mval[1]);
@@ -477,13 +451,10 @@ static int node_borderselect_exec(bContext *C, wmOperator *op)
for (node = snode->edittree->nodes.first; node; node = node->next) {
if (BLI_rctf_isect(&rectf, &node->totr, NULL)) {
- if (gesture_mode == GESTURE_MODAL_SELECT)
- node_select(node);
- else
- node_deselect(node);
+ nodeSetSelected(node, (gesture_mode == GESTURE_MODAL_SELECT));
}
else if (!extend) {
- node_deselect(node);
+ nodeSetSelected(node, FALSE);
}
}
@@ -494,7 +465,7 @@ static int node_borderselect_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int node_border_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int node_border_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int tweak = RNA_boolean_get(op->ptr, "tweak");
@@ -566,11 +537,7 @@ static int do_lasso_select_node(bContext *C, const int mcords[][2], short moves,
if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) &&
BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], INT_MAX))
{
- if (select)
- node_select(node);
- else
- node_deselect(node);
-
+ nodeSetSelected(node, select);
change = TRUE;
}
}
@@ -642,13 +609,13 @@ static int node_select_all_exec(bContext *C, wmOperator *op)
for (node = node_lb->first; node; node = node->next) {
switch (action) {
case SEL_SELECT:
- node_select(node);
+ nodeSetSelected(node, TRUE);
break;
case SEL_DESELECT:
- node_deselect(node);
+ nodeSetSelected(node, FALSE);
break;
case SEL_INVERT:
- ((node->flag & SELECT) ? node_deselect : node_select)(node);
+ nodeSetSelected(node, !(node->flag & SELECT));
break;
}
}
@@ -688,13 +655,15 @@ static int node_select_linked_to_exec(bContext *C, wmOperator *UNUSED(op))
node->flag &= ~NODE_TEST;
for (link = snode->edittree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
if (link->fromnode && link->tonode && (link->fromnode->flag & NODE_SELECT))
link->tonode->flag |= NODE_TEST;
}
for (node = snode->edittree->nodes.first; node; node = node->next) {
if (node->flag & NODE_TEST)
- node_select(node);
+ nodeSetSelected(node, TRUE);
}
ED_node_sort(snode->edittree);
@@ -730,13 +699,15 @@ static int node_select_linked_from_exec(bContext *C, wmOperator *UNUSED(op))
node->flag &= ~NODE_TEST;
for (link = snode->edittree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
if (link->fromnode && link->tonode && (link->tonode->flag & NODE_SELECT))
link->fromnode->flag |= NODE_TEST;
}
for (node = snode->edittree->nodes.first; node; node = node->next) {
if (node->flag & NODE_TEST)
- node_select(node);
+ nodeSetSelected(node, TRUE);
}
ED_node_sort(snode->edittree);
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index 23f4e948794..527defb1f07 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -30,6 +30,7 @@
#include "DNA_node_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
@@ -52,6 +53,8 @@
#include "ED_util.h"
+#include "node_intern.h"
+
/************************* Node Socket Manipulation **************************/
static void node_tag_recursive(bNode *node)
@@ -127,7 +130,7 @@ static void node_socket_disconnect(Main *bmain, bNodeTree *ntree, bNode *node_to
nodeUpdate(ntree, node_to);
ntreeUpdateTree(ntree);
- ED_node_generic_update(bmain, ntree, node_to);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
/* remove all nodes connected to this socket, if they aren't connected to other nodes */
@@ -142,11 +145,11 @@ static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bN
nodeUpdate(ntree, node_to);
ntreeUpdateTree(ntree);
- ED_node_generic_update(bmain, ntree, node_to);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
/* add new node connected to this socket, or replace an existing one */
-static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, bNodeTemplate *ntemp, int sock_num)
+static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, int type, bNodeTree *ngroup, int sock_num)
{
bNode *node_from;
bNodeSocket *sock_from_tmp;
@@ -160,24 +163,30 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
/* find existing node that we can use */
for (node_from = ntree->nodes.first; node_from; node_from = node_from->next)
- if (node_from->type == ntemp->type)
+ if (node_from->type == type)
break;
if (node_from)
if (!(node_from->inputs.first == NULL && !(node_from->typeinfo->flag & NODE_OPTIONS)))
node_from = NULL;
- if (node_prev && node_prev->type == ntemp->type &&
- (ntemp->type != NODE_GROUP || node_prev->id == &ntemp->ngroup->id))
+ /* XXX how can this be done nicely? bNodeTemplate is removed, it doesn't work for generic custom nodes */
+ if (node_prev && node_prev->type == type &&
+ (type != NODE_GROUP || node_prev->id == &ngroup->id))
{
/* keep the previous node if it's the same type */
node_from = node_prev;
}
else if (!node_from) {
- node_from = nodeAddNode(ntree, ntemp);
+ node_from = nodeAddStaticNode(C, ntree, type);
node_from->locx = node_to->locx - (node_from->typeinfo->width + 50);
node_from->locy = node_to->locy;
-
+
+ /* XXX bad, should be dispatched to generic operator or something ... */
+ if (type == NODE_GROUP) {
+ node_from->id = (ID *)ngroup;
+ }
+
if (node_from->id)
id_us_plus(node_from->id);
}
@@ -198,7 +207,7 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
if (nodeCountSocketLinks(ntree, sock_from) >= sock_from->limit)
continue;
- if (strcmp(sock_prev->name, sock_from->name) == 0 && sock_prev->type == sock_from->type) {
+ if (STREQ(sock_prev->name, sock_from->name) && sock_prev->type == sock_from->type) {
bNodeLink *link = sock_prev->link;
if (link && link->fromnode) {
@@ -206,9 +215,11 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
nodeRemLink(ntree, link);
}
- node_socket_free_default_value(sock_from->type, sock_from->default_value);
- sock_from->default_value = node_socket_make_default_value(sock_from->type);
- node_socket_copy_default_value(sock_from->type, sock_from->default_value, sock_prev->default_value);
+#if 0 /* XXX TODO */
+ node_socket_free_default_value(sock_from->typeinfo, sock_from->default_value);
+ sock_from->default_value = node_socket_make_default_value(sock_from->typeinfo);
+ node_socket_copy_default_value(sock_from->typeinfo, sock_from->default_value, sock_prev->default_value);
+#endif
}
}
}
@@ -228,7 +239,7 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
nodeUpdate(ntree, node_to);
ntreeUpdateTree(ntree);
- ED_node_generic_update(bmain, ntree, node_to);
+ ED_node_tag_update_nodetree(CTX_data_main(C), ntree);
}
/****************************** Node Link Menu *******************************/
@@ -259,19 +270,13 @@ static void ui_node_link(bContext *C, void *arg_p, void *event_p)
bNodeSocket *sock_to = arg->sock;
bNodeTree *ntree = arg->ntree;
int event = GET_INT_FROM_POINTER(event_p);
- bNodeTemplate ntemp;
-
- ntemp.type = arg->type;
- ntemp.ngroup = arg->ngroup;
- ntemp.scene = CTX_data_scene(C);
- ntemp.main = CTX_data_main(C);
if (event == UI_NODE_LINK_DISCONNECT)
node_socket_disconnect(bmain, ntree, node_to, sock_to);
else if (event == UI_NODE_LINK_REMOVE)
node_socket_remove(bmain, ntree, node_to, sock_to);
else
- node_socket_add_replace(bmain, ntree, node_to, sock_to, &ntemp, arg->output);
+ node_socket_add_replace(C, ntree, node_to, sock_to, arg->type, arg->ngroup, arg->output);
ED_undo_push(C, "Node input modify");
}
@@ -286,10 +291,10 @@ static void ui_node_sock_name(bNodeSocket *sock, char name[UI_MAX_NAME_STR])
if (node->id)
BLI_strncpy(node_name, node->id->name + 2, UI_MAX_NAME_STR);
else
- BLI_strncpy(node_name, N_("Group"), UI_MAX_NAME_STR);
+ BLI_strncpy(node_name, N_(node->typeinfo->ui_name), UI_MAX_NAME_STR);
}
else
- BLI_strncpy(node_name, node->typeinfo->name, UI_MAX_NAME_STR);
+ BLI_strncpy(node_name, node->typeinfo->ui_name, UI_MAX_NAME_STR);
if (node->inputs.first == NULL &&
node->outputs.first != node->outputs.last)
@@ -313,19 +318,16 @@ static int ui_compatible_sockets(int typeA, int typeB)
static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
{
- Main *bmain = arg->bmain;
bNodeTree *ntree = arg->ntree;
bNodeSocket *sock = arg->sock;
uiLayout *layout = arg->layout;
uiLayout *column = NULL;
uiBlock *block = uiLayoutGetBlock(layout);
uiBut *but;
- bNodeType *ntype;
- bNodeTree *ngroup;
NodeLinkArg *argN;
int first = 1;
int compatibility = 0;
-
+
if (ntree->type == NTREE_SHADER) {
if (BKE_scene_use_new_shading_nodes(arg->scene))
compatibility = NODE_NEW_SHADING;
@@ -333,114 +335,58 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
compatibility = NODE_OLD_SHADING;
}
- if (nclass == NODE_CLASS_GROUP) {
- for (ngroup = bmain->nodetree.first; ngroup; ngroup = ngroup->id.next) {
- bNodeSocket *gsock;
- char name[UI_MAX_NAME_STR];
- int i, j, num = 0;
-
- if (ngroup->type != ntree->type)
+ NODE_TYPES_BEGIN(ntype)
+ bNodeSocketTemplate *stemp;
+ char name[UI_MAX_NAME_STR];
+ int i, j, num = 0;
+
+ if (compatibility && !(ntype->compatibility & compatibility))
+ continue;
+
+ if (ntype->nclass != nclass)
+ continue;
+
+ for (i = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++)
+ if (ui_compatible_sockets(stemp->type, sock->type))
+ num++;
+
+ for (i = 0, j = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++) {
+ if (!ui_compatible_sockets(stemp->type, sock->type))
continue;
-
- for (gsock = ngroup->inputs.first; gsock; gsock = gsock->next)
- if (ui_compatible_sockets(gsock->type, sock->type))
- num++;
-
- for (i = 0, j = 0, gsock = ngroup->outputs.first; gsock; gsock = gsock->next, i++) {
- if (!ui_compatible_sockets(gsock->type, sock->type))
- continue;
-
- if (first) {
- column = uiLayoutColumn(layout, FALSE);
- uiBlockSetCurLayout(block, column);
-
- uiItemL(column, IFACE_(cname), ICON_NODE);
- but = block->buttons.last;
- but->flag = UI_TEXT_LEFT;
-
- first = 0;
- }
-
- if (num > 1) {
- if (j == 0) {
- uiItemL(column, ngroup->id.name + 2, ICON_NODE);
- but = block->buttons.last;
- but->flag = UI_TEXT_LEFT;
- }
-
- BLI_snprintf(name, UI_MAX_NAME_STR, " %s", gsock->name);
- j++;
- }
- else
- BLI_strncpy(name, ngroup->id.name + 2, UI_MAX_NAME_STR);
-
- but = uiDefBut(block, BUT, 0, ngroup->id.name + 2, 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->type = NODE_GROUP;
- argN->ngroup = ngroup;
- argN->output = i;
- uiButSetNFunc(but, ui_node_link, argN, NULL);
+
+ if (first) {
+ column = uiLayoutColumn(layout, 0);
+ uiBlockSetCurLayout(block, column);
+
+ uiItemL(column, IFACE_(cname), ICON_NODE);
+ but = block->buttons.last;
+ but->flag = UI_TEXT_LEFT;
+
+ first = 0;
}
- }
- }
- else {
- bNodeTreeType *ttype = ntreeGetType(ntree->type);
-
- for (ntype = ttype->node_types.first; ntype; ntype = ntype->next) {
- bNodeSocketTemplate *stemp;
- char name[UI_MAX_NAME_STR];
- int i, j, num = 0;
-
- if (compatibility && !(ntype->compatibility & compatibility))
- continue;
-
- if (ntype->nclass != nclass)
- continue;
-
- for (i = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++)
- if (ui_compatible_sockets(stemp->type, sock->type))
- num++;
-
- for (i = 0, j = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++) {
- if (!ui_compatible_sockets(stemp->type, sock->type))
- continue;
-
- if (first) {
- column = uiLayoutColumn(layout, FALSE);
- uiBlockSetCurLayout(block, column);
-
- uiItemL(column, IFACE_(cname), ICON_NODE);
+
+ if (num > 1) {
+ if (j == 0) {
+ uiItemL(column, IFACE_(ntype->ui_name), ICON_NODE);
but = block->buttons.last;
but->flag = UI_TEXT_LEFT;
-
- first = 0;
}
-
- if (num > 1) {
- if (j == 0) {
- uiItemL(column, IFACE_(ntype->name), ICON_NODE);
- but = block->buttons.last;
- but->flag = UI_TEXT_LEFT;
- }
-
- BLI_snprintf(name, UI_MAX_NAME_STR, " %s", IFACE_(stemp->name));
- j++;
- }
- else
- BLI_strncpy(name, IFACE_(ntype->name), UI_MAX_NAME_STR);
-
- but = uiDefBut(block, BUT, 0, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input"));
-
- argN = MEM_dupallocN(arg);
- argN->type = ntype->type;
- argN->output = i;
- uiButSetNFunc(but, ui_node_link, argN, NULL);
+
+ BLI_snprintf(name, UI_MAX_NAME_STR, " %s", IFACE_(stemp->name));
+ j++;
}
+ else
+ BLI_strncpy(name, IFACE_(ntype->ui_name), UI_MAX_NAME_STR);
+
+ but = uiDefBut(block, BUT, 0, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
+ NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input"));
+
+ argN = MEM_dupallocN(arg);
+ argN->type = ntype->type;
+ argN->output = i;
+ uiButSetNFunc(but, ui_node_link, argN, NULL);
}
- }
+ NODE_TYPES_END
}
static void node_menu_column_foreach_cb(void *calldata, int nclass, const char *name)
@@ -460,7 +406,7 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_
uiLayout *split, *column;
NodeLinkArg *arg = (NodeLinkArg *)but->func_argN;
bNodeSocket *sock = arg->sock;
- bNodeTreeType *ntreetype = ntreeGetType(arg->ntree->type);
+ bNodeTreeType *ntreetype = arg->ntree->typeinfo;
uiBlockSetCurLayout(block, layout);
split = uiLayoutSplit(layout, 0.0f, FALSE);
@@ -554,7 +500,7 @@ static void ui_node_draw_node(uiLayout *layout, bContext *C, bNodeTree *ntree, b
static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth)
{
- PointerRNA inputptr;
+ PointerRNA inputptr, nodeptr;
uiBlock *block = uiLayoutGetBlock(layout);
uiBut *bt;
uiLayout *split, *row, *col;
@@ -576,6 +522,7 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
/* socket RNA pointer */
RNA_pointer_create(&ntree->id, &RNA_NodeSocket, input, &inputptr);
+ RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
/* indented label */
memset(label, ' ', indent);
@@ -624,16 +571,25 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
}
else {
/* input not linked, show value */
- if (input->type != SOCK_SHADER && !(input->flag & SOCK_HIDE_VALUE)) {
- if (input->type == SOCK_VECTOR) {
+ if (!(input->flag & SOCK_HIDE_VALUE)) {
+ switch (input->type) {
+ case SOCK_FLOAT:
+ case SOCK_INT:
+ case SOCK_BOOLEAN:
+ case SOCK_RGBA:
+ case SOCK_STRING:
+ row = uiLayoutRow(split, TRUE);
+ uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE);
+ break;
+ case SOCK_VECTOR:
row = uiLayoutRow(split, FALSE);
col = uiLayoutColumn(row, FALSE);
-
uiItemR(col, &inputptr, "default_value", 0, "", ICON_NONE);
- }
- else {
- row = uiLayoutRow(split, TRUE);
- uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE);
+ break;
+
+ default:
+ row = uiLayoutRow(split, FALSE);
+ break;
}
}
else
diff --git a/source/blender/editors/space_node/node_toolbar.c b/source/blender/editors/space_node/node_toolbar.c
new file mode 100644
index 00000000000..86da4009b17
--- /dev/null
+++ b/source/blender/editors/space_node/node_toolbar.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.
+ *
+ * The Original Code is Copyright (C) 2012 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_node/node_toolbar.c
+ * \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 */
+
+
+/* ******************* node toolbar registration ************** */
+
+void node_toolbar_register(ARegionType *UNUSED(art))
+{
+}
+
+/* ********** operator to open/close toolshelf region */
+
+static int node_toolbar(bContext *C, wmOperator *UNUSED(op))
+{
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = node_has_tools_region(sa);
+
+ if (ar)
+ ED_region_toggle_hidden(C, ar);
+
+ return OPERATOR_FINISHED;
+}
+
+/* non-standard poll operator which doesn't care if there are any nodes */
+static int node_toolbar_poll(bContext *C)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ return (sa && (sa->spacetype == SPACE_NODE));
+}
+
+void NODE_OT_toolbar(wmOperatorType *ot)
+{
+ ot->name = "Tool Shelf";
+ ot->description = "Toggles tool shelf display";
+ ot->idname = "NODE_OT_toolbar";
+
+ ot->exec = node_toolbar;
+ ot->poll = node_toolbar_poll;
+
+ /* flags */
+ ot->flag = 0;
+}
diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index f386657c460..293913dff11 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -56,10 +56,12 @@
#include "MEM_guardedalloc.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "node_intern.h" /* own include */
+#include "NOD_composite.h"
/* **************** View All Operator ************** */
@@ -69,12 +71,15 @@ static int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar, cons
bNode *node;
rctf cur_new;
float oldwidth, oldheight, width, height;
+ float oldasp, asp;
int tot = 0;
int has_frame = FALSE;
oldwidth = BLI_rctf_size_x(&ar->v2d.cur);
oldheight = BLI_rctf_size_y(&ar->v2d.cur);
+ oldasp = oldwidth / oldheight;
+
BLI_rctf_init_minmax(&cur_new);
if (snode->edittree) {
@@ -93,6 +98,7 @@ static int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar, cons
if (tot) {
width = BLI_rctf_size_x(&cur_new);
height = BLI_rctf_size_y(&cur_new);
+ asp = width / height;
/* for single non-frame nodes, don't zoom in, just pan view,
* but do allow zooming out, this allows for big nodes to be zoomed out */
@@ -104,18 +110,19 @@ static int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar, cons
BLI_rctf_resize(&cur_new, oldwidth, oldheight);
}
else {
- if (width > height) {
- float newheight;
- newheight = oldheight * width / oldwidth;
- cur_new.ymin = cur_new.ymin - newheight / 4;
- cur_new.ymax = cur_new.ymax + newheight / 4;
+ if (oldasp < asp) {
+ const float height_new = width / oldasp;
+ cur_new.ymin = cur_new.ymin - height_new / 2.0f;
+ cur_new.ymax = cur_new.ymax + height_new / 2.0f;
}
else {
- float newwidth;
- newwidth = oldwidth * height / oldheight;
- cur_new.xmin = cur_new.xmin - newwidth / 4;
- cur_new.xmax = cur_new.xmax + newwidth / 4;
+ const float width_new = height * oldasp;
+ cur_new.xmin = cur_new.xmin - width_new / 2.0f;
+ cur_new.xmax = cur_new.xmax + width_new / 2.0f;
}
+
+ /* add some padding */
+ BLI_rctf_scale(&cur_new, 1.1f);
}
UI_view2d_smooth_view(C, ar, &cur_new);
@@ -191,7 +198,7 @@ typedef struct NodeViewMove {
int xmin, ymin, xmax, ymax;
} NodeViewMove;
-static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceNode *snode = CTX_wm_space_node(C);
ARegion *ar = CTX_wm_region(C);
@@ -226,7 +233,7 @@ static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceNode *snode = CTX_wm_space_node(C);
ARegion *ar = CTX_wm_region(C);
@@ -330,6 +337,7 @@ typedef struct ImageSampleInfo {
unsigned char col[4];
float colf[4];
+ float linearcol[4];
int z;
float zf;
@@ -348,7 +356,7 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
if (info->draw) {
ED_image_draw_info(scene, ar, info->color_manage, FALSE, info->channels,
- info->x, info->y, info->col, info->colf,
+ info->x, info->y, info->col, info->colf, info->linearcol,
info->zp, info->zfp);
}
}
@@ -363,7 +371,7 @@ int ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float
float fx, fy, bufx, bufy;
int ret = FALSE;
- if (snode->treetype != NTREE_COMPOSIT || (snode->flag & SNODE_BACKDRAW) == 0) {
+ if (STREQ(snode->tree_idname, ntreeType_Composite->idname) || (snode->flag & SNODE_BACKDRAW) == 0) {
/* use viewer image for color sampling only if we're in compositor tree
* with backdrop enabled
*/
@@ -408,7 +416,7 @@ int ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float
return ret;
}
-static void sample_apply(bContext *C, wmOperator *op, wmEvent *event)
+static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceNode *snode = CTX_wm_space_node(C);
ARegion *ar = CTX_wm_region(C);
@@ -464,7 +472,10 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event)
info->colf[2] = (float)cp[2] / 255.0f;
info->colf[3] = (float)cp[3] / 255.0f;
- info->color_manage = FALSE;
+ copy_v4_v4(info->linearcol, info->colf);
+ IMB_colormanagement_colorspace_to_scene_linear_v4(info->linearcol, false, ibuf->rect_colorspace);
+
+ info->color_manage = TRUE;
}
if (ibuf->rect_float) {
fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
@@ -508,13 +519,13 @@ static void sample_exit(bContext *C, wmOperator *op)
MEM_freeN(info);
}
-static int sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int sample_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceNode *snode = CTX_wm_space_node(C);
ARegion *ar = CTX_wm_region(C);
ImageSampleInfo *info;
- if (snode->treetype != NTREE_COMPOSIT || !(snode->flag & SNODE_BACKDRAW))
+ if (!ED_node_is_compositor(snode) || !(snode->flag & SNODE_BACKDRAW))
return OPERATOR_CANCELLED;
info = MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo");
@@ -529,7 +540,7 @@ static int sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static int sample_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int sample_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
switch (event->type) {
case LEFTMOUSE:
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index f7e0d51ea03..2075cc055e1 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -45,10 +45,10 @@
#include "BKE_node.h"
#include "ED_space_api.h"
+#include "ED_node.h"
#include "ED_render.h"
#include "ED_screen.h"
#include "ED_node.h"
-
#include "WM_api.h"
#include "WM_types.h"
@@ -59,6 +59,168 @@
#include "node_intern.h" /* own include */
+
+/* ******************** tree path ********************* */
+
+void ED_node_tree_start(SpaceNode *snode, bNodeTree *ntree, ID *id, ID *from)
+{
+ bNodeTreePath *path, *path_next;
+ for (path = snode->treepath.first; path; path = path_next) {
+ path_next = path->next;
+ MEM_freeN(path);
+ }
+ snode->treepath.first = snode->treepath.last = NULL;
+
+ if (ntree) {
+ path = MEM_callocN(sizeof(bNodeTreePath), "node tree path");
+ path->nodetree = ntree;
+ path->parent_key = NODE_INSTANCE_KEY_BASE;
+ if (id)
+ BLI_strncpy(path->node_name, id->name + 2, sizeof(path->node_name));
+ BLI_addtail(&snode->treepath, path);
+ }
+
+ /* update current tree */
+ snode->nodetree = snode->edittree = ntree;
+ snode->id = id;
+ snode->from = from;
+
+ /* listener updates the View2D center from edittree */
+ WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
+}
+
+void ED_node_tree_push(SpaceNode *snode, bNodeTree *ntree, bNode *gnode)
+{
+ bNodeTreePath *path = MEM_callocN(sizeof(bNodeTreePath), "node tree path");
+ bNodeTreePath *prev_path = snode->treepath.last;
+ path->nodetree = ntree;
+ if (gnode) {
+ if (prev_path)
+ path->parent_key = BKE_node_instance_key(prev_path->parent_key, prev_path->nodetree, gnode);
+ else
+ path->parent_key = NODE_INSTANCE_KEY_BASE;
+
+ BLI_strncpy(path->node_name, gnode->name, sizeof(path->node_name));
+ }
+ else
+ path->parent_key = NODE_INSTANCE_KEY_BASE;
+
+ BLI_addtail(&snode->treepath, path);
+
+ /* update current tree */
+ snode->edittree = ntree;
+
+ /* listener updates the View2D center from edittree */
+ WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
+}
+
+void ED_node_tree_pop(SpaceNode *snode)
+{
+ bNodeTreePath *path = snode->treepath.last;
+
+ /* don't remove root */
+ if (path == snode->treepath.first)
+ return;
+
+ BLI_remlink(&snode->treepath, path);
+ MEM_freeN(path);
+
+ /* update current tree */
+ path = snode->treepath.last;
+ snode->edittree = path->nodetree;
+
+ /* listener updates the View2D center from edittree */
+ WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
+}
+
+int ED_node_tree_depth(SpaceNode *snode)
+{
+ return BLI_countlist(&snode->treepath);
+}
+
+bNodeTree *ED_node_tree_get(SpaceNode *snode, int level)
+{
+ bNodeTreePath *path;
+ int i;
+ for (path = snode->treepath.last, i = 0; path; path = path->prev, ++i) {
+ if (i == level)
+ return path->nodetree;
+ }
+ return NULL;
+}
+
+int ED_node_tree_path_length(SpaceNode *snode)
+{
+ bNodeTreePath *path;
+ int length = 0;
+ int i;
+ for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
+ length += strlen(path->node_name);
+ if (i > 0)
+ length += 1; /* for separator char */
+ }
+ return length;
+}
+
+void ED_node_tree_path_get(SpaceNode *snode, char *value)
+{
+ bNodeTreePath *path;
+ int i;
+
+ value[0] = '\0';
+ for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
+ if (i == 0) {
+ strcpy(value, path->node_name);
+ value += strlen(path->node_name);
+ }
+ else {
+ sprintf(value, "/%s", path->node_name);
+ value += strlen(path->node_name) + 1;
+ }
+ }
+}
+
+void ED_node_tree_path_get_fixedbuf(SpaceNode *snode, char *value, int max_length)
+{
+ bNodeTreePath *path;
+ int size, i;
+
+ 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);
+ }
+ else {
+ BLI_snprintf(value, max_length, "/%s", path->node_name);
+ size = strlen(path->node_name) + 1;
+ }
+ max_length -= size;
+ if (max_length <= 0)
+ break;
+ value += size;
+ }
+}
+
+void snode_group_offset(SpaceNode *snode, float *x, float *y)
+{
+ bNodeTreePath *path = snode->treepath.last;
+ float cx, cy;
+
+ if (path) {
+ cx = path->nodetree->view_center[0];
+ cy = path->nodetree->view_center[1];
+
+ if (path->prev) {
+ *x = cx - path->prev->nodetree->view_center[0];
+ *y = cy - path->prev->nodetree->view_center[1];
+ return;
+ }
+ }
+
+ *x = *y = 0.0f;
+}
+
/* ******************** manage regions ********************* */
ARegion *node_has_buttons_region(ScrArea *sa)
@@ -85,6 +247,30 @@ ARegion *node_has_buttons_region(ScrArea *sa)
return arnew;
}
+ARegion *node_has_tools_region(ScrArea *sa)
+{
+ ARegion *ar, *arnew;
+
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOLS);
+ if (ar) return ar;
+
+ /* add subdiv level; after header */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+
+ /* is error! */
+ if (ar == NULL) return NULL;
+
+ arnew = MEM_callocN(sizeof(ARegion), "node tools");
+
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype = RGN_TYPE_TOOLS;
+ arnew->alignment = RGN_ALIGN_LEFT;
+
+ arnew->flag = RGN_FLAG_HIDDEN;
+
+ return arnew;
+}
+
/* ******************** default callbacks for node space ***************** */
static SpaceLink *node_new(const bContext *UNUSED(C))
@@ -95,9 +281,17 @@ static SpaceLink *node_new(const bContext *UNUSED(C))
snode = MEM_callocN(sizeof(SpaceNode), "initnode");
snode->spacetype = SPACE_NODE;
+ snode->flag = SNODE_SHOW_GPENCIL | SNODE_USE_ALPHA;
+
/* backdrop */
snode->zoom = 1.0f;
+ /* select the first tree type for valid type */
+ NODE_TREE_TYPES_BEGIN(treetype)
+ strcpy(snode->tree_idname, treetype->idname);
+ break;
+ NODE_TREE_TYPES_END
+
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for node");
@@ -118,15 +312,12 @@ static SpaceLink *node_new(const bContext *UNUSED(C))
BLI_addtail(&snode->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
- ar->v2d.tot.xmin = -256.0f;
- ar->v2d.tot.ymin = -256.0f;
- ar->v2d.tot.xmax = 768.0f;
- ar->v2d.tot.ymax = 768.0f;
+ ar->v2d.tot.xmin = -12.8f * U.widget_unit;
+ ar->v2d.tot.ymin = -12.8f * U.widget_unit;
+ ar->v2d.tot.xmax = 38.4f * U.widget_unit;
+ ar->v2d.tot.ymax = 38.4f * U.widget_unit;
- ar->v2d.cur.xmin = -256.0f;
- ar->v2d.cur.ymin = -256.0f;
- ar->v2d.cur.xmax = 768.0f;
- ar->v2d.cur.ymax = 768.0f;
+ ar->v2d.cur = ar->v2d.tot;
ar->v2d.min[0] = 1.0f;
ar->v2d.min[1] = 1.0f;
@@ -144,10 +335,15 @@ static SpaceLink *node_new(const bContext *UNUSED(C))
return (SpaceLink *)snode;
}
-/* not spacelink itself */
-static void node_free(SpaceLink *UNUSED(sl))
+static void node_free(SpaceLink *sl)
{
+ SpaceNode *snode = (SpaceNode *)sl;
+ bNodeTreePath *path, *path_next;
+ for (path = snode->treepath.first; path; path = path_next) {
+ path_next = path->next;
+ MEM_freeN(path);
+ }
}
@@ -161,14 +357,21 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
{
/* note, ED_area_tag_refresh will re-execute compositor */
SpaceNode *snode = sa->spacedata.first;
- int type = snode->treetype;
short shader_type = snode->shaderfrom;
/* preview renders */
switch (wmn->category) {
case NC_SCENE:
switch (wmn->data) {
- case ND_NODES:
+ case ND_NODES: {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ /* shift view to node tree center */
+ if (ar && snode->edittree)
+ UI_view2d_setcenter(&ar->v2d, snode->edittree->view_center[0], snode->edittree->view_center[1]);
+
+ ED_area_tag_refresh(sa);
+ break;
+ }
case ND_FRAME:
ED_area_tag_refresh(sa);
break;
@@ -176,7 +379,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
ED_area_tag_redraw(sa);
break;
case ND_TRANSFORM_DONE:
- if (type == NTREE_COMPOSIT) {
+ if (ED_node_is_compositor(snode)) {
if (snode->flag & SNODE_AUTO_RENDER) {
snode->recalc = 1;
ED_area_tag_refresh(sa);
@@ -188,7 +391,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
/* future: add ID checks? */
case NC_MATERIAL:
- if (type == NTREE_SHADER) {
+ if (ED_node_is_shader(snode)) {
if (wmn->data == ND_SHADING)
ED_area_tag_refresh(sa);
else if (wmn->data == ND_SHADING_DRAW)
@@ -201,18 +404,18 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
}
break;
case NC_TEXTURE:
- if (type == NTREE_SHADER || type == NTREE_TEXTURE) {
+ if (ED_node_is_shader(snode) || ED_node_is_texture(snode)) {
if (wmn->data == ND_NODES)
ED_area_tag_refresh(sa);
}
break;
case NC_WORLD:
- if (type == NTREE_SHADER && shader_type == SNODE_SHADER_WORLD) {
+ if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_WORLD) {
ED_area_tag_refresh(sa);
}
break;
case NC_OBJECT:
- if (type == NTREE_SHADER) {
+ if (ED_node_is_shader(snode)) {
if (wmn->data == ND_OB_SHADING)
ED_area_tag_refresh(sa);
}
@@ -238,7 +441,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
break;
case NC_MASK:
if (wmn->action == NA_EDITED) {
- if (type == NTREE_COMPOSIT) {
+ if (snode->nodetree && snode->nodetree->type == NTREE_COMPOSIT) {
ED_area_tag_refresh(sa);
}
}
@@ -246,7 +449,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
case NC_IMAGE:
if (wmn->action == NA_EDITED) {
- if (type == NTREE_COMPOSIT) {
+ if (ED_node_is_compositor(snode)) {
/* note that nodeUpdateID is already called by BKE_image_signal() on all
* scenes so really this is just to know if the images is used in the compo else
* painting on images could become very slow when the compositor is open. */
@@ -258,7 +461,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
case NC_MOVIECLIP:
if (wmn->action == NA_EDITED) {
- if (type == NTREE_COMPOSIT) {
+ if (ED_node_is_compositor(snode)) {
if (nodeUpdateID(snode->nodetree, wmn->reference))
ED_area_tag_refresh(sa);
}
@@ -271,11 +474,13 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
{
/* default now: refresh node is starting preview */
SpaceNode *snode = sa->spacedata.first;
-
- snode_set_context(snode, CTX_data_scene(C));
+
+ ED_preview_kill_jobs(C);
+
+ snode_set_context(C);
if (snode->nodetree) {
- if (snode->treetype == NTREE_SHADER) {
+ if (snode->nodetree->type == NTREE_SHADER) {
if (GS(snode->id->name) == ID_MA) {
Material *ma = (Material *)snode->id;
if (ma->use_nodes)
@@ -292,7 +497,7 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
}
}
- else if (snode->treetype == NTREE_COMPOSIT) {
+ else if (snode->nodetree->type == NTREE_COMPOSIT) {
Scene *scene = (Scene *)snode->id;
if (scene->use_nodes) {
/* recalc is set on 3d view changes for auto compo */
@@ -305,7 +510,7 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
}
}
}
- else if (snode->treetype == NTREE_TEXTURE) {
+ else if (snode->nodetree->type == NTREE_TEXTURE) {
Tex *tex = (Tex *)snode->id;
if (tex->use_nodes) {
ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
@@ -316,11 +521,14 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
static SpaceLink *node_duplicate(SpaceLink *sl)
{
- SpaceNode *snoden = MEM_dupallocN(sl);
+ SpaceNode *snode = (SpaceNode *)sl;
+ SpaceNode *snoden = MEM_dupallocN(snode);
/* clear or remove stuff from old */
snoden->nodetree = NULL;
snoden->linkdrag.first = snoden->linkdrag.last = NULL;
+
+ BLI_duplicatelist(&snoden->treepath, &snode->treepath);
return (SpaceLink *)snoden;
}
@@ -342,6 +550,22 @@ static void node_buttons_area_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, 1, NULL, -1);
}
+/* add handlers, stuff you only do once or on area/region changes */
+static void node_toolbar_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ wmKeyMap *keymap;
+
+ ED_region_panels_init(wm, ar);
+
+ keymap = WM_keymap_find(wm->defaultconf, "Node Generic", SPACE_NODE, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+}
+
+static void node_toolbar_area_draw(const bContext *C, ARegion *ar)
+{
+ ED_region_panels(C, ar, 1, NULL, -1);
+}
+
static void node_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
{
SpaceNode *snode = sa->spacedata.first;
@@ -376,15 +600,13 @@ static void node_main_area_init(wmWindowManager *wm, ARegion *ar)
static void node_main_area_draw(const bContext *C, ARegion *ar)
{
- View2D *v2d = &ar->v2d;
-
- drawnodespace(C, ar, v2d);
+ drawnodespace(C, ar);
}
/* ************* dropboxes ************* */
-static int node_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
+static int node_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
ID *id = (ID *)drag->poin;
@@ -430,11 +652,8 @@ static void node_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
static void node_header_area_draw(const bContext *C, ARegion *ar)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- Scene *scene = CTX_data_scene(C);
-
/* find and set the context */
- snode_set_context(snode, scene);
+ snode_set_context(C);
ED_region_header(C, ar);
}
@@ -459,6 +678,7 @@ static void node_region_listener(ARegion *ar, wmNotifier *wmn)
case NC_SCENE:
case NC_MATERIAL:
case NC_TEXTURE:
+ case NC_WORLD:
case NC_NODE:
ED_region_tag_redraw(ar);
break;
@@ -509,6 +729,14 @@ static int node_context(const bContext *C, const char *member, bContextDataResul
CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
return 1;
}
+ else if (CTX_data_equals(member, "node_previews")) {
+ if (snode->nodetree) {
+ CTX_data_pointer_set(result, &snode->nodetree->id, &RNA_NodeInstanceHash, snode->nodetree->previews);
+ }
+
+ CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
+ return 1;
+ }
return 0;
}
@@ -570,6 +798,19 @@ void ED_spacetype_node(void)
node_buttons_register(art);
+ /* regions: toolbar */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region");
+ art->regionid = RGN_TYPE_TOOLS;
+ art->prefsizex = 160; /* XXX */
+ art->prefsizey = 50; /* XXX */
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
+ art->listener = node_region_listener;
+ art->init = node_toolbar_area_init;
+ art->draw = node_toolbar_area_draw;
+ BLI_addhead(&st->regiontypes, art);
+
+ node_toolbar_register(art);
+
BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_outliner/SConscript b/source/blender/editors/space_outliner/SConscript
index a6f2e3c2a5d..1bb71941a43 100644
--- a/source/blender/editors/space_outliner/SConscript
+++ b/source/blender/editors/space_outliner/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index d37cb4be8fa..26a0d0a2fa8 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -41,6 +41,8 @@
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
+#include "BLF_translation.h"
+
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_depsgraph.h"
@@ -50,6 +52,7 @@
#include "BKE_modifier.h"
#include "BKE_report.h"
#include "BKE_scene.h"
+#include "BKE_object.h"
#include "ED_armature.h"
#include "ED_object.h"
@@ -129,11 +132,66 @@ static void outliner_rna_width(SpaceOops *soops, ListBase *lb, int *w, int start
/* ****************************************************** */
+static void restrictbutton_recursive_ebone(bContext *C, EditBone *ebone_parent, int flag, bool set_flag)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ bArmature *arm = obedit->data;
+ EditBone *ebone;
+
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (ED_armature_ebone_is_child_recursive(ebone_parent, ebone)) {
+ if (set_flag) {
+ ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ ebone->flag |= flag;
+ }
+ else {
+ ebone->flag &= ~flag;
+ }
+ }
+ }
+}
+
+static void restrictbutton_recursive_bone(bContext *C, bArmature *arm, Bone *bone_parent, int flag, bool set_flag)
+{
+ Bone *bone;
+ for (bone = bone_parent->childbase.first; bone; bone = bone->next) {
+ if (set_flag) {
+ bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ bone->flag |= flag;
+ }
+ else {
+ bone->flag &= ~flag;
+ }
+ restrictbutton_recursive_bone(C, arm, bone, flag, set_flag);
+ }
+
+}
+
+static void restrictbutton_recursive_child(bContext *C, Scene *scene, Object *ob_parent, char flag,
+ bool state, bool deselect)
+{
+ 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);
+ }
+ }
+ else {
+ ob->restrictflag &= ~flag;
+ }
+ }
+ }
+}
+
static void restrictbutton_view_cb(bContext *C, void *poin, void *poin2)
{
Scene *scene = (Scene *)poin;
Object *ob = (Object *)poin2;
-
+
if (!common_restrict_check(C, ob)) return;
/* deselect objects that are invisible */
@@ -142,6 +200,12 @@ static void restrictbutton_view_cb(bContext *C, void *poin, void *poin2)
* so have to do loop to find it. */
ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT);
}
+
+ if (CTX_wm_window(C)->eventstate->ctrl) {
+ restrictbutton_recursive_child(C, scene, ob, OB_RESTRICT_VIEW,
+ (ob->restrictflag & OB_RESTRICT_VIEW) != 0, true);
+ }
+
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
@@ -159,12 +223,25 @@ static void restrictbutton_sel_cb(bContext *C, void *poin, void *poin2)
* so have to do loop to find it. */
ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT);
}
+
+ if (CTX_wm_window(C)->eventstate->ctrl) {
+ restrictbutton_recursive_child(C, scene, ob, OB_RESTRICT_SELECT,
+ (ob->restrictflag & OB_RESTRICT_SELECT) != 0, true);
+ }
+
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
-static void restrictbutton_rend_cb(bContext *C, void *poin, void *UNUSED(poin2))
+static void restrictbutton_rend_cb(bContext *C, void *poin, void *poin2)
{
+ Object *ob = (Object *)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);
+ }
+
WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, poin);
}
@@ -182,19 +259,59 @@ static void restrictbutton_modifier_cb(bContext *C, void *UNUSED(poin), void *po
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
}
-static void restrictbutton_bone_cb(bContext *C, void *UNUSED(poin), void *poin2)
+static void restrictbutton_bone_visibility_cb(bContext *C, void *poin, void *poin2)
{
+ bArmature *arm = (bArmature *)poin;
Bone *bone = (Bone *)poin2;
if (bone && (bone->flag & BONE_HIDDEN_P))
bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+
+ if (CTX_wm_window(C)->eventstate->ctrl) {
+ restrictbutton_recursive_bone(C, arm, bone, BONE_HIDDEN_P, (bone->flag & BONE_HIDDEN_P) != 0);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+}
+
+static void restrictbutton_bone_select_cb(bContext *C, void *poin, void *poin2)
+{
+ bArmature *arm = (bArmature *)poin;
+ Bone *bone = (Bone *)poin2;
+ if (bone && (bone->flag & BONE_UNSELECTABLE))
+ bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+
+ if (CTX_wm_window(C)->eventstate->ctrl) {
+ restrictbutton_recursive_bone(C, arm, bone, BONE_UNSELECTABLE, (bone->flag & BONE_UNSELECTABLE) != 0);
+ }
+
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
}
-static void restrictbutton_ebone_cb(bContext *C, void *UNUSED(poin), void *poin2)
+static void restrictbutton_ebone_select_cb(bContext *C, void *UNUSED(poin), void *poin2)
{
EditBone *ebone = (EditBone *)poin2;
- if (ebone && (ebone->flag & BONE_HIDDEN_A))
+
+ if (ebone->flag & BONE_UNSELECTABLE) {
ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+
+ if (CTX_wm_window(C)->eventstate->ctrl) {
+ restrictbutton_recursive_ebone(C, ebone, BONE_UNSELECTABLE, (ebone->flag & BONE_UNSELECTABLE) != 0);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+}
+
+static void restrictbutton_ebone_visibility_cb(bContext *C, void *UNUSED(poin), void *poin2)
+{
+ EditBone *ebone = (EditBone *)poin2;
+ if (ebone->flag & BONE_HIDDEN_A) {
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+
+ if (CTX_wm_window(C)->eventstate->ctrl) {
+ restrictbutton_recursive_ebone(C, ebone, BONE_HIDDEN_A, (ebone->flag & BONE_HIDDEN_A) != 0);
+ }
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
}
@@ -238,7 +355,7 @@ static int group_select_flag(Group *gr)
}
void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag)
-{
+{
Scene *scene = (Scene *)poin;
GroupObject *gob;
Group *gr = (Group *)poin2;
@@ -297,7 +414,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
TreeElement *te = outliner_find_tse(soops, tselem);
if (tselem->type == 0) {
- test_idbutton(tselem->id->name + 2); // library.c, unique name and alpha sort
+ test_idbutton(tselem->id->name); // library.c, unique name and alpha sort
switch (GS(tselem->id->name)) {
case ID_MA:
@@ -332,7 +449,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
defgroup_unique_name(te->directdata, (Object *)tselem->id); // id = object
break;
case TSE_NLA_ACTION:
- test_idbutton(tselem->id->name + 2);
+ test_idbutton(tselem->id->name);
break;
case TSE_EBONE:
{
@@ -389,7 +506,8 @@ 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, "Group", '.', offsetof(bActionGroup, name), sizeof(grp->name));
+ BLI_uniquename(&ob->pose->agroups, grp, "Group", '.', offsetof(bActionGroup, name),
+ sizeof(grp->name));
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
}
break;
@@ -421,18 +539,21 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
uiBlockSetEmboss(block, UI_EMBOSSN);
bt = uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_VIEW_OFF,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X - 1, UI_UNIT_Y - 1,
- &ptr, "hide", -1, 0, 0, -1, -1, NULL);
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &ptr, "hide", -1, 0, 0, -1, -1,
+ TIP_("Restrict viewport visibility (Ctrl - Recursive)"));
uiButSetFunc(bt, restrictbutton_view_cb, scene, ob);
bt = uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_SELECT_OFF,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X - 1, UI_UNIT_Y - 1,
- &ptr, "hide_select", -1, 0, 0, -1, -1, NULL);
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &ptr, "hide_select", -1, 0, 0, -1, -1,
+ TIP_("Restrict viewport selection (Ctrl - Recursive)"));
uiButSetFunc(bt, restrictbutton_sel_cb, scene, ob);
bt = uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_RENDER_OFF,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X - 1, UI_UNIT_Y - 1,
- &ptr, "hide_render", -1, 0, 0, -1, -1, NULL);
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &ptr, "hide_render", -1, 0, 0, -1, -1,
+ TIP_("Restrict rendering (Ctrl - Recursive)"));
uiButSetFunc(bt, restrictbutton_rend_cb, scene, ob);
uiBlockSetEmboss(block, UI_EMBOSS);
@@ -445,15 +566,21 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
uiBlockSetEmboss(block, UI_EMBOSSN);
restrict_bool = group_restrict_flag(gr, OB_RESTRICT_VIEW);
- bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF, (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X - 1, UI_UNIT_Y - 1, NULL, 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
+ bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)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);
restrict_bool = group_restrict_flag(gr, OB_RESTRICT_SELECT);
- bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF, (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X - 1, UI_UNIT_Y - 1, NULL, 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
+ bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)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);
restrict_bool = group_restrict_flag(gr, OB_RESTRICT_RENDER);
- bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF, (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X - 1, UI_UNIT_Y - 1, NULL, 0, 0, 0, 0, "Restrict/Allow renderability");
+ bt = uiDefIconBut(block, ICONTOG, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)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);
uiBlockSetEmboss(block, UI_EMBOSS);
@@ -463,7 +590,8 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
uiBlockSetEmboss(block, UI_EMBOSSN);
bt = uiDefIconButBitI(block, ICONTOGN, SCE_LAY_DISABLE, 0, ICON_CHECKBOX_HLT - 1,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X - 1, UI_UNIT_Y - 1, te->directdata, 0, 0, 0, 0, "Render this RenderLayer");
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)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);
uiBlockSetEmboss(block, UI_EMBOSS);
@@ -476,13 +604,18 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
bt = uiDefIconButBitI(block, ICONTOG, passflag, 0, ICON_CHECKBOX_HLT - 1,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X - 1, UI_UNIT_Y - 1, layflag, 0, 0, 0, 0, "Render this Pass");
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)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);
layflag++; /* is lay_xor */
- if (ELEM8(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))
+ if (ELEM8(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,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X - 1, UI_UNIT_Y - 1, layflag, 0, 0, 0, 0, "Exclude this Pass from Combined");
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)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);
uiBlockSetEmboss(block, UI_EMBOSS);
@@ -493,37 +626,49 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
uiBlockSetEmboss(block, UI_EMBOSSN);
bt = uiDefIconButBitI(block, ICONTOGN, eModifierMode_Realtime, 0, ICON_RESTRICT_VIEW_OFF,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X - 1, UI_UNIT_Y - 1, &(md->mode), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)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);
bt = uiDefIconButBitI(block, ICONTOGN, eModifierMode_Render, 0, ICON_RESTRICT_RENDER_OFF,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X - 1, UI_UNIT_Y - 1, &(md->mode), 0, 0, 0, 0, "Restrict/Allow renderability");
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)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);
}
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,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X - 1, UI_UNIT_Y - 1, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
- uiButSetFunc(bt, restrictbutton_bone_cb, NULL, bone);
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)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);
bt = uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X - 1, UI_UNIT_Y - 1, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
- uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL);
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)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);
}
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,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X - 1, UI_UNIT_Y - 1, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
- uiButSetFunc(bt, restrictbutton_ebone_cb, NULL, ebone);
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)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);
bt = uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
- (int)ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X - 1, UI_UNIT_Y - 1, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View");
- uiButSetFunc(bt, restrictbutton_ebone_cb, NULL, NULL);
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)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);
}
}
@@ -535,7 +680,7 @@ static void outliner_draw_rnacols(ARegion *ar, int sizex)
{
View2D *v2d = &ar->v2d;
- float miny = v2d->cur.ymin - V2D_SCROLL_HEIGHT;
+ float miny = v2d->cur.ymin;
if (miny < v2d->tot.ymin) miny = v2d->tot.ymin;
UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
@@ -553,7 +698,7 @@ static void outliner_draw_rnacols(ARegion *ar, int sizex)
}
static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, int sizex, ListBase *lb)
-{
+{
TreeElement *te;
TreeStoreElem *tselem;
PointerRNA *ptr;
@@ -568,14 +713,17 @@ static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, Spa
ptr = &te->rnaptr;
prop = te->directdata;
- if (!(RNA_property_type(prop) == PROP_POINTER && (TSELEM_OPEN(tselem, soops))) )
- uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, sizex, (int)te->ys, OL_RNA_COL_SIZEX, UI_UNIT_Y - 1);
+ if (!(RNA_property_type(prop) == PROP_POINTER && (TSELEM_OPEN(tselem, soops)))) {
+ uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, sizex, (int)te->ys, OL_RNA_COL_SIZEX,
+ UI_UNIT_Y - 1);
+ }
}
else if (tselem->type == TSE_RNA_ARRAY_ELEM) {
ptr = &te->rnaptr;
prop = te->directdata;
- uiDefAutoButR(block, ptr, prop, te->index, "", ICON_NONE, sizex, (int)te->ys, OL_RNA_COL_SIZEX, UI_UNIT_Y - 1);
+ uiDefAutoButR(block, ptr, prop, te->index, "", ICON_NONE, sizex, (int)te->ys, OL_RNA_COL_SIZEX,
+ UI_UNIT_Y - 1);
}
}
@@ -597,7 +745,7 @@ static void operator_search_cb(const struct bContext *UNUSED(C), void *UNUSED(ar
{
GHashIterator *iter = WM_operatortype_iter();
- for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
+ for (; BLI_ghashIterator_notDone(iter); BLI_ghashIterator_step(iter)) {
wmOperatorType *ot = BLI_ghashIterator_getValue(iter);
if (BLI_strcasestr(ot->idname, str)) {
@@ -788,7 +936,8 @@ static void outliner_draw_keymapbuts(uiBlock *block, ARegion *ar, SpaceOops *soo
/* pass */
}
else {
- uiDefBlockBut(block, operator_search_menu, kmi, "", xstart, (int)te->ys + 1, butw1, UI_UNIT_Y - 1, "Assign new Operator");
+ uiDefBlockBut(block, operator_search_menu, kmi, "", xstart, (int)te->ys + 1, butw1, UI_UNIT_Y - 1,
+ TIP_("Assign new Operator"));
}
xstart += butw1 + 10;
@@ -796,43 +945,58 @@ static void outliner_draw_keymapbuts(uiBlock *block, ARegion *ar, SpaceOops *soo
kmi->maptype = keymap_menu_type(kmi->type);
str = keymap_type_menu();
- but = uiDefButS(block, MENU, 0, str, xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->maptype, 0, 0, 0, 0, "Event type");
+ but = uiDefButS(block, MENU, 0, str, xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->maptype,
+ 0, 0, 0, 0, TIP_("Event type"));
uiButSetFunc(but, keymap_type_cb, kmi, NULL);
xstart += butw2 + 5;
/* edit actual event */
switch (kmi->maptype) {
case OL_KM_KEYBOARD:
- uiDefKeyevtButS(block, 0, "", xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->type, "Key code");
+ uiDefKeyevtButS(block, 0, "", xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->type,
+ TIP_("Key code"));
xstart += butw2 + 5;
break;
case OL_KM_MOUSE:
str = keymap_mouse_menu();
- uiDefButS(block, MENU, 0, str, xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->type, 0, 0, 0, 0, "Mouse button");
+ uiDefButS(block, MENU, 0, str, xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->type,
+ 0, 0, 0, 0, TIP_("Mouse button"));
xstart += butw2 + 5;
break;
case OL_KM_TWEAK:
str = keymap_tweak_menu();
- uiDefButS(block, MENU, 0, str, xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->type, 0, 0, 0, 0, "Tweak gesture");
+ uiDefButS(block, MENU, 0, str, xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->type,
+ 0, 0, 0, 0, TIP_("Tweak gesture"));
xstart += butw2 + 5;
str = keymap_tweak_dir_menu();
- uiDefButS(block, MENU, 0, str, xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->val, 0, 0, 0, 0, "Tweak gesture direction");
+ uiDefButS(block, MENU, 0, str, xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->val,
+ 0, 0, 0, 0, TIP_("Tweak gesture direction"));
xstart += butw2 + 5;
break;
}
/* modifiers */
- uiDefButS(block, OPTION, 0, "Shift", xstart, (int)te->ys + 1, butw3 + 5, UI_UNIT_Y - 1, &kmi->shift, 0, 0, 0, 0, "Modifier"); xstart += butw3 + 5;
- uiDefButS(block, OPTION, 0, "Ctrl", xstart, (int)te->ys + 1, butw3, UI_UNIT_Y - 1, &kmi->ctrl, 0, 0, 0, 0, "Modifier"); xstart += butw3;
- uiDefButS(block, OPTION, 0, "Alt", xstart, (int)te->ys + 1, butw3, UI_UNIT_Y - 1, &kmi->alt, 0, 0, 0, 0, "Modifier"); xstart += butw3;
- uiDefButS(block, OPTION, 0, "OS", xstart, (int)te->ys + 1, butw3, UI_UNIT_Y - 1, &kmi->oskey, 0, 0, 0, 0, "Modifier"); xstart += butw3;
- xstart += 5;
- uiDefKeyevtButS(block, 0, "", xstart, (int)te->ys + 1, butw3, UI_UNIT_Y - 1, &kmi->keymodifier, "Key Modifier code");
+ uiDefButS(block, OPTION, 0, IFACE_("Shift"), xstart, (int)te->ys + 1, butw3 + 5, UI_UNIT_Y - 1,
+ &kmi->shift, 0, 0, 0, 0, TIP_("Modifier"));
+ xstart += butw3 + 5;
+ uiDefButS(block, OPTION, 0, IFACE_("Ctrl"), xstart, (int)te->ys + 1, butw3, UI_UNIT_Y - 1, &kmi->ctrl,
+ 0, 0, 0, 0, TIP_("Modifier"));
+ xstart += butw3;
+ uiDefButS(block, OPTION, 0, IFACE_("Alt"), xstart, (int)te->ys + 1, butw3, UI_UNIT_Y - 1, &kmi->alt,
+ 0, 0, 0, 0, TIP_("Modifier"));
+ xstart += butw3;
+ uiDefButS(block, OPTION, 0, IFACE_("OS"), xstart, (int)te->ys + 1, butw3, UI_UNIT_Y - 1, &kmi->oskey,
+ 0, 0, 0, 0, TIP_("Modifier"));
+ xstart += butw3 + 5;
+ uiDefKeyevtButS(block, 0, "", xstart, (int)te->ys + 1, butw3, UI_UNIT_Y - 1, &kmi->keymodifier,
+ TIP_("Key Modifier code"));
xstart += butw3 + 5;
/* rna property */
if (kmi->ptr && kmi->ptr->data) {
- uiDefBut(block, LABEL, 0, "(RNA property)", xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->oskey, 0, 0, 0, 0, ""); xstart += butw2;
+ uiDefBut(block, LABEL, 0, IFACE_("(RNA property)"), xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1,
+ NULL, 0, 0, 0, 0, "");
+ xstart += butw2;
}
(void)xstart;
@@ -860,7 +1024,8 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Spa
/* If we add support to rename Sequence.
* need change this.
*/
- if (tselem->type == TSE_POSE_BASE) continue; // prevent crash when trying to rename 'pose' entry of armature
+ // prevent crash when trying to rename 'pose' entry of armature
+ if (tselem->type == TSE_POSE_BASE) continue;
if (tselem->type == TSE_EBONE) len = sizeof(((EditBone *) 0)->name);
else if (tselem->type == TSE_MODIFIER) len = sizeof(((ModifierData *) 0)->name);
@@ -873,7 +1038,8 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Spa
spx = te->xs + 2 * UI_UNIT_X - 4;
if (spx + dx + 10 > ar->v2d.cur.xmax) dx = ar->v2d.cur.xmax - spx - 10;
- bt = uiDefBut(block, TEX, OL_NAMEBUTTON, "", spx, (int)te->ys, dx + 10, UI_UNIT_Y - 1, (void *)te->name, 1.0, (float)len, 0, 0, "");
+ bt = uiDefBut(block, TEX, OL_NAMEBUTTON, "", spx, (int)te->ys, dx + 10, UI_UNIT_Y - 1, (void *)te->name,
+ 1.0, (float)len, 0, 0, "");
uiButSetRenameFunc(bt, namebutton_cb, tselem);
/* returns false if button got removed */
@@ -893,7 +1059,7 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Spa
struct DrawIconArg {
uiBlock *block;
ID *id;
- int xmax, x, y;
+ float xmax, x, y, xb, yb;
float alpha;
};
@@ -902,13 +1068,12 @@ static void tselem_draw_icon_uibut(struct DrawIconArg *arg, int icon)
/* restrict column clip... it has been coded by simply overdrawing, doesnt work for buttons */
if (arg->x >= arg->xmax) {
glEnable(GL_BLEND);
- UI_icon_draw_aspect(arg->x, arg->y, icon, 1.0f, arg->alpha);
+ UI_icon_draw_aspect(arg->x, arg->y, icon, 1.0f / UI_DPI_FAC, arg->alpha);
glDisable(GL_BLEND);
}
else {
- /* XXX investigate: button placement of icons is way different than UI_icon_draw? */
- float ufac = UI_UNIT_X / 20.0f;
- uiBut *but = uiDefIconBut(arg->block, LABEL, 0, icon, arg->x - 3.0f * ufac, arg->y, UI_UNIT_X - 4.0f * ufac, UI_UNIT_Y - 4.0f * ufac, NULL, 0.0, 0.0, 1.0, arg->alpha, (arg->id && arg->id->lib) ? arg->id->lib->name : "");
+ uiBut *but = uiDefIconBut(arg->block, 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);
@@ -916,18 +1081,28 @@ static void tselem_draw_icon_uibut(struct DrawIconArg *arg, int icon)
}
-static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te, float alpha)
+static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te,
+ float alpha)
{
struct DrawIconArg arg;
+ float aspect;
+
+ /* icons tiny bit away from text */
+ x -= 0.15f * UI_UNIT_Y;
/* make function calls a bit compacter */
arg.block = block;
arg.id = tselem->id;
arg.xmax = xmax;
- arg.x = x;
- arg.y = y;
+ arg.xb = x; /* for ui buttons */
+ arg.yb = y;
arg.alpha = alpha;
+ /* placement of icons, copied from interface_widgets.c */
+ aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT;
+ arg.x = x = x + 4.0f * aspect;
+ arg.y = y = y + 0.1f * UI_UNIT_Y;
+
if (tselem->type) {
switch (tselem->type) {
case TSE_ANIM_DATA:
@@ -989,6 +1164,7 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
case eModifierType_Array:
UI_icon_draw(x, y, ICON_MOD_ARRAY); break;
case eModifierType_UVProject:
+ case eModifierType_UVWarp: /* TODO, get own icon */
UI_icon_draw(x, y, ICON_MOD_UVPROJECT); break;
case eModifierType_Displace:
UI_icon_draw(x, y, ICON_MOD_DISPLACE); break;
@@ -1040,7 +1216,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
UI_icon_draw(x, y, ICON_MOD_SKIN); break;
case eModifierType_Triangulate:
UI_icon_draw(x, y, ICON_MOD_TRIANGULATE); break;
-
+ case eModifierType_MeshCache:
+ UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */
/* Default */
case eModifierType_None:
case eModifierType_ShapeKey:
@@ -1190,7 +1367,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
}
}
-static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, SpaceOops *soops, ListBase *lb, int level, int xmax, int *offsx, int ys)
+static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, SpaceOops *soops, ListBase *lb, int level,
+ int xmax, int *offsx, int ys)
{
TreeElement *te;
TreeStoreElem *tselem;
@@ -1209,22 +1387,30 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Spa
/* active blocks get white circle */
if (tselem->type == 0) {
- if (te->idcode == ID_OB) active = (OBACT == (Object *)tselem->id);
- else if (scene->obedit && scene->obedit->data == tselem->id) active = 1; // XXX use context?
- else active = tree_element_active(C, scene, soops, te, 0);
+ if (te->idcode == ID_OB) {
+ active = (OBACT == (Object *)tselem->id);
+ }
+ else if (scene->obedit && scene->obedit->data == tselem->id) {
+ active = 1; // XXX use context?
+ }
+ else {
+ active = tree_element_active(C, scene, soops, te, 0);
+ }
}
- else active = tree_element_type_active(NULL, scene, soops, te, tselem, 0);
-
+ else {
+ active = tree_element_type_active(NULL, scene, soops, te, tselem, 0, false);
+ }
+
if (active) {
float ufac = UI_UNIT_X / 20.0f;
uiSetRoundBox(UI_CNR_ALL);
glColor4ub(255, 255, 255, 100);
- uiRoundBox((float) *offsx - 0.5f * ufac,
- (float)ys - 1.0f * ufac,
- (float)*offsx + UI_UNIT_Y - 3.0f * ufac,
- (float)ys + UI_UNIT_Y - 3.0f * ufac,
- (float)UI_UNIT_Y / 2.0f - 2.0f * ufac);
+ 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);
glEnable(GL_BLEND); /* roundbox disables */
}
@@ -1259,7 +1445,8 @@ 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)
+static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops,
+ TreeElement *te, int startx, int *starty)
{
TreeElement *ten;
TreeStoreElem *tselem;
@@ -1270,6 +1457,7 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
if (*starty + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && *starty <= ar->v2d.cur.ymax) {
int xmax = ar->v2d.cur.xmax;
+ unsigned char alpha = 128;
/* icons can be ui buts, we don't want it to overlap with restrict */
if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0)
@@ -1286,16 +1474,17 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
{
char col[4];
UI_GetThemeColorType4ubv(TH_MATCH, SPACE_OUTLINER, col);
- col[3] = 100;
+ col[3] = alpha;
glColor4ubv((GLubyte *)col);
glRecti(startx, *starty + 1, ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
}
/* colors for active/selected data */
if (tselem->type == 0) {
+
if (te->idcode == ID_SCE) {
if (tselem->id == (ID *)scene) {
- glColor4ub(255, 255, 255, 100);
+ glColor4ub(255, 255, 255, alpha);
active = 2;
}
}
@@ -1304,7 +1493,7 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
if (group_select_flag(gr)) {
char col[4];
UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col);
- col[3] = 100;
+ col[3] = alpha;
glColor4ubv((GLubyte *)col);
active = 2;
@@ -1322,14 +1511,14 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
if (ob == OBACT) {
if (ob->flag & SELECT) {
UI_GetThemeColorType4ubv(TH_ACTIVE, SPACE_VIEW3D, col);
- col[3] = 100;
+ col[3] = alpha;
}
active = 1; /* means it draws white text */
}
else if (ob->flag & SELECT) {
UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col);
- col[3] = 100;
+ col[3] = alpha;
}
glColor4ubv((GLubyte *)col);
@@ -1337,29 +1526,29 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
}
else if (scene->obedit && scene->obedit->data == tselem->id) {
- glColor4ub(255, 255, 255, 100);
+ glColor4ub(255, 255, 255, alpha);
active = 2;
}
else {
if (tree_element_active(C, scene, soops, te, 0)) {
- glColor4ub(220, 220, 255, 100);
+ glColor4ub(220, 220, 255, alpha);
active = 2;
}
}
}
else {
- if (tree_element_type_active(NULL, scene, soops, te, tselem, 0) ) active = 2;
- glColor4ub(220, 220, 255, 100);
+ if (tree_element_type_active(NULL, scene, soops, te, tselem, 0, false) ) active = 2;
+ glColor4ub(220, 220, 255, alpha);
}
/* active circle */
if (active) {
uiSetRoundBox(UI_CNR_ALL);
- uiRoundBox((float)startx + UI_UNIT_Y - 1.5f * ufac,
- (float)*starty + 2.0f * ufac,
- (float)startx + 2.0f * UI_UNIT_Y - 4.0f * ufac,
+ 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 - 2.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
@@ -1384,8 +1573,8 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
/* datatype icon */
if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM))) {
- // icons a bit higher
- tselem_draw_icon(block, xmax, (float)startx + offsx - 0.5f * ufac, (float)*starty + 2.0f * ufac, tselem, te, 1.0f);
+
+ tselem_draw_icon(block, xmax, (float)startx + offsx, (float)*starty, tselem, te, 1.0f);
offsx += UI_UNIT_X;
}
@@ -1425,12 +1614,15 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
/* divider */
UI_ThemeColorShade(TH_BACK, -40);
- glRecti(tempx - 10, *starty + 4, tempx - 8, *starty + UI_UNIT_Y - 4);
+ glRecti(tempx - 10.0f * ufac,
+ *starty + 4.0f * ufac,
+ tempx - 8.0f * ufac,
+ *starty + UI_UNIT_Y - 4.0f * ufac);
glEnable(GL_BLEND);
glPixelTransferf(GL_ALPHA_SCALE, 0.5);
- outliner_draw_iconrow(C, block, scene, soops, &te->subtree, 0, xmax, &tempx, *starty + 2);
+ outliner_draw_iconrow(C, block, scene, soops, &te->subtree, 0, xmax, &tempx, *starty);
glPixelTransferf(GL_ALPHA_SCALE, 1.0);
glDisable(GL_BLEND);
@@ -1502,13 +1694,13 @@ static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *
/* selection status */
if (TSELEM_OPEN(tselem, soops))
if (tselem->type == TSE_RNA_STRUCT)
- glRecti(0, *starty + 1, (int)ar->v2d.cur.xmax + V2D_SCROLL_WIDTH, *starty + UI_UNIT_Y - 1);
+ glRecti(0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
*starty -= UI_UNIT_Y;
if (TSELEM_OPEN(tselem, soops)) {
outliner_draw_struct_marks(ar, soops, &te->subtree, starty);
if (tselem->type == TSE_RNA_STRUCT)
- fdrawline(0, (float)*starty + UI_UNIT_Y, ar->v2d.cur.xmax + V2D_SCROLL_WIDTH, (float)*starty + UI_UNIT_Y);
+ fdrawline(0, (float)*starty + UI_UNIT_Y, ar->v2d.cur.xmax, (float)*starty + UI_UNIT_Y);
}
}
}
@@ -1577,7 +1769,7 @@ static void outliner_back(ARegion *ar)
ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET;
while (ystart + 2 * UI_UNIT_Y > ar->v2d.cur.ymin) {
- glRecti(0, ystart, (int)ar->v2d.cur.xmax + V2D_SCROLL_WIDTH, ystart + UI_UNIT_Y);
+ glRecti(0, ystart, (int)ar->v2d.cur.xmax, ystart + UI_UNIT_Y);
ystart -= 2 * UI_UNIT_Y;
}
}
@@ -1588,10 +1780,8 @@ static void outliner_draw_restrictcols(ARegion *ar)
/* background underneath */
UI_ThemeColor(TH_BACK);
- glRecti((int)ar->v2d.cur.xmax - OL_TOGW,
- (int)ar->v2d.cur.ymin - V2D_SCROLL_HEIGHT - 1,
- (int)ar->v2d.cur.xmax + V2D_SCROLL_WIDTH,
- (int)ar->v2d.cur.ymax);
+ glRecti((int)(ar->v2d.cur.xmax - OL_TOGW),
+ (int)(ar->v2d.cur.ymin - 1), (int)ar->v2d.cur.xmax, (int)ar->v2d.cur.ymax);
UI_ThemeColorShade(TH_BACK, 6);
ystart = (int)ar->v2d.tot.ymax;
@@ -1605,38 +1795,38 @@ static void outliner_draw_restrictcols(ARegion *ar)
UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
/* view */
- fdrawline(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX,
- ar->v2d.cur.ymax,
- ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX,
- ar->v2d.cur.ymin - V2D_SCROLL_HEIGHT);
+ sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ (int)ar->v2d.cur.ymax,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ (int)ar->v2d.cur.ymin);
/* render */
- fdrawline(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX,
- ar->v2d.cur.ymax,
- ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX,
- ar->v2d.cur.ymin - V2D_SCROLL_HEIGHT);
+ sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
+ (int)ar->v2d.cur.ymax,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
+ (int)ar->v2d.cur.ymin);
/* render */
- fdrawline(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX,
- ar->v2d.cur.ymax,
- ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX,
- ar->v2d.cur.ymin - V2D_SCROLL_HEIGHT);
+ sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
+ (int)ar->v2d.cur.ymax,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
+ (int)ar->v2d.cur.ymin);
}
/* ****************************************************** */
/* Main Entrypoint - Draw contents of Outliner editor */
-
+
void draw_outliner(const bContext *C)
{
- Main *mainvar = CTX_data_main(C);
+ Main *mainvar = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
View2D *v2d = &ar->v2d;
SpaceOops *soops = CTX_wm_space_outliner(C);
uiBlock *block;
int sizey = 0, sizex = 0, sizex_rna = 0;
-
- outliner_build_tree(mainvar, scene, soops); // always
+
+ outliner_build_tree(mainvar, scene, soops); // always
/* get extents of data */
outliner_height(soops, &soops->tree, &sizey);
@@ -1647,7 +1837,7 @@ void draw_outliner(const bContext *C)
* (OL_RNA_COL_X), whichever is wider...
* - column 2 is fixed at OL_RNA_COL_SIZEX
*
- * (*) XXX max width for now is a fixed factor of UI_UNIT_X*(max_indention+100)
+ * (*) XXX max width for now is a fixed factor of (UI_UNIT_X * (max_indention + 100))
*/
/* get actual width of column 1 */
@@ -1655,25 +1845,25 @@ void draw_outliner(const bContext *C)
sizex_rna = max_ii(OL_RNA_COLX, sizex_rna + OL_RNA_COL_SPACEX);
/* get width of data (for setting 'tot' rect, this is column 1 + column 2 + a bit extra) */
- if (soops->outlinevis == SO_KEYMAP)
- sizex = sizex_rna + OL_RNA_COL_SIZEX * 3 + 50; // XXX this is only really a quick hack to make this wide enough...
+ if (soops->outlinevis == SO_KEYMAP)
+ // XXX this is only really a quick hack to make this wide enough...
+ sizex = sizex_rna + OL_RNA_COL_SIZEX * 3 + 50;
else
sizex = sizex_rna + OL_RNA_COL_SIZEX + 50;
}
else {
/* width must take into account restriction columns (if visible) so that entries will still be visible */
//outliner_width(soops, &soops->tree, &sizex);
- outliner_rna_width(soops, &soops->tree, &sizex, 0); // XXX should use outliner_width instead when te->xend will be set correctly...
+ // XXX should use outliner_width instead when te->xend will be set correctly...
+ outliner_rna_width(soops, &soops->tree, &sizex, 0);
/* constant offset for restriction columns */
// XXX this isn't that great yet...
if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0)
sizex += OL_TOGW * 3;
+
}
- /* tweak to display last line (when list bigger than window) */
- sizey += V2D_SCROLL_HEIGHT;
-
/* adds vertical offset */
sizey += OL_Y_OFFSET;
@@ -1709,7 +1899,7 @@ void draw_outliner(const bContext *C)
uiEndBlock(C, block);
uiDrawBlock(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 d11a8ed6369..1e67e099508 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -146,7 +146,7 @@ static int do_outliner_item_openclose(bContext *C, SpaceOops *soops, TreeElement
}
/* event can enterkey, then it opens/closes */
-static int outliner_item_openclose(bContext *C, wmOperator *op, wmEvent *event)
+static int outliner_item_openclose(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
@@ -183,8 +183,8 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot)
static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem, ReportList *reports)
{
- /* can't rename rna datablocks entries */
- if (ELEM3(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
+ /* can't rename rna datablocks entries or listbases */
+ if (ELEM4(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE)) {
/* do nothing */;
}
else if (ELEM10(tselem->type, TSE_ANIM_DATA, TSE_NLA, TSE_DEFGROUP_BASE, TSE_CONSTRAINT_BASE, TSE_MODIFIER_BASE,
@@ -222,12 +222,12 @@ static int do_outliner_item_rename(bContext *C, ARegion *ar, SpaceOops *soops, T
if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
TreeStoreElem *tselem = TREESTORE(te);
- /* name and first icon */
- if (mval[0] > te->xs + UI_UNIT_X && mval[0] < te->xend) {
-
+ /* click on name */
+ if (mval[0] > te->xs + UI_UNIT_X * 2 && mval[0] < te->xend) {
do_item_rename(ar, te, tselem, reports);
+ return 1;
}
- return 1;
+ return 0;
}
for (te = te->subtree.first; te; te = te->next) {
@@ -236,20 +236,24 @@ static int do_outliner_item_rename(bContext *C, ARegion *ar, SpaceOops *soops, T
return 0;
}
-static int outliner_item_rename(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int outliner_item_rename(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
TreeElement *te;
float fmval[2];
+ bool change = false;
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], fmval, fmval + 1);
for (te = soops->tree.first; te; te = te->next) {
- if (do_outliner_item_rename(C, ar, soops, te, fmval)) break;
+ if (do_outliner_item_rename(C, ar, soops, te, fmval)) {
+ change = true;
+ break;
+ }
}
- return OPERATOR_FINISHED;
+ return change ? OPERATOR_FINISHED : OPERATOR_PASS_THROUGH;
}
@@ -890,9 +894,13 @@ static void tree_element_show_hierarchy(Scene *scene, SpaceOops *soops, ListBase
else tselem->flag |= TSE_CLOSED;
}
}
- else tselem->flag |= TSE_CLOSED;
-
- if (TSELEM_OPEN(tselem, soops)) tree_element_show_hierarchy(scene, soops, &te->subtree);
+ else {
+ tselem->flag |= TSE_CLOSED;
+ }
+
+ if (TSELEM_OPEN(tselem, soops)) {
+ tree_element_show_hierarchy(scene, soops, &te->subtree);
+ }
}
}
@@ -1309,8 +1317,8 @@ static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBa
* 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);
+ break;
}
- break;
case KEYINGSET_EDITMODE_REMOVE:
{
/* find the relevant path, then remove it from the KeyingSet */
@@ -1322,8 +1330,8 @@ static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBa
ks->active_path = 0;
}
+ break;
}
- break;
}
/* free path, since it had to be generated */
@@ -1432,8 +1440,7 @@ static int parent_drop_exec(bContext *C, wmOperator *op)
ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, FALSE, FALSE);
- DAG_scene_sort(bmain, scene);
- DAG_ids_flush_update(bmain, 0);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
@@ -1441,7 +1448,7 @@ static int parent_drop_exec(bContext *C, wmOperator *op)
}
/* Used for drag and drop parenting */
-TreeElement *outliner_dropzone_parent(bContext *C, wmEvent *event, TreeElement *te, float *fmval)
+TreeElement *outliner_dropzone_parent(bContext *C, const wmEvent *event, TreeElement *te, const float fmval[2])
{
SpaceOops *soops = CTX_wm_space_outliner(C);
TreeStoreElem *tselem = TREESTORE(te);
@@ -1470,7 +1477,7 @@ TreeElement *outliner_dropzone_parent(bContext *C, wmEvent *event, TreeElement *
return NULL;
}
-static int parent_drop_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Object *par = NULL;
Object *ob = NULL;
@@ -1522,8 +1529,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, wmEvent *event)
if ((par->type != OB_ARMATURE) && (par->type != OB_CURVE) && (par->type != OB_LATTICE)) {
if (ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, FALSE, FALSE)) {
- DAG_scene_sort(bmain, scene);
- DAG_ids_flush_update(bmain, 0);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
}
@@ -1637,7 +1643,7 @@ void OUTLINER_OT_parent_drop(wmOperatorType *ot)
ot->poll = ED_operator_outliner_active;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
/* properties */
RNA_def_string(ot->srna, "child", "Object", MAX_ID_NAME, "Child", "Child Object");
@@ -1645,7 +1651,7 @@ void OUTLINER_OT_parent_drop(wmOperatorType *ot)
RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
}
-int outliner_dropzone_parent_clear(bContext *C, wmEvent *event, TreeElement *te, float *fmval)
+int outliner_dropzone_parent_clear(bContext *C, const wmEvent *event, TreeElement *te, const float fmval[2])
{
SpaceOops *soops = CTX_wm_space_outliner(C);
TreeStoreElem *tselem = TREESTORE(te);
@@ -1683,7 +1689,7 @@ int outliner_dropzone_parent_clear(bContext *C, wmEvent *event, TreeElement *te,
return 0;
}
-static int parent_clear_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int parent_clear_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Main *bmain = CTX_data_main(C);
Scene *scene = NULL;
@@ -1706,8 +1712,7 @@ static int parent_clear_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even
ED_object_parent_clear(ob, RNA_enum_get(op->ptr, "type"));
- DAG_scene_sort(bmain, scene);
- DAG_ids_flush_update(bmain, 0);
+ DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
return OPERATOR_FINISHED;
@@ -1726,14 +1731,14 @@ void OUTLINER_OT_parent_clear(wmOperatorType *ot)
ot->poll = ED_operator_outliner_active;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
/* properties */
RNA_def_string(ot->srna, "dragged_obj", "Object", MAX_ID_NAME, "Child", "Child Object");
RNA_def_enum(ot->srna, "type", prop_clear_parent_types, 0, "Type", "");
}
-TreeElement *outliner_dropzone_scene(bContext *C, wmEvent *UNUSED(event), TreeElement *te, float *fmval)
+TreeElement *outliner_dropzone_scene(bContext *C, const wmEvent *UNUSED(event), TreeElement *te, const float fmval[2])
{
SpaceOops *soops = CTX_wm_space_outliner(C);
TreeStoreElem *tselem = TREESTORE(te);
@@ -1749,7 +1754,7 @@ TreeElement *outliner_dropzone_scene(bContext *C, wmEvent *UNUSED(event), TreeEl
return NULL;
}
-static int scene_drop_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Scene *scene = NULL;
Object *ob = NULL;
@@ -1795,8 +1800,7 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, wmEvent *event)
ED_base_object_select(base, BA_SELECT);
}
- DAG_scene_sort(bmain, scene);
- DAG_ids_flush_update(bmain, 0);
+ DAG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
@@ -1819,16 +1823,15 @@ void OUTLINER_OT_scene_drop(wmOperatorType *ot)
ot->poll = ED_operator_outliner_active;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
/* properties */
RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", "Target Object");
RNA_def_string(ot->srna, "scene", "Scene", MAX_ID_NAME, "Scene", "Target Scene");
}
-static int material_drop_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int material_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Main *bmain = CTX_data_main(C);
Material *ma = NULL;
Object *ob = NULL;
SpaceOops *soops = CTX_wm_space_outliner(C);
@@ -1860,7 +1863,6 @@ static int material_drop_invoke(bContext *C, wmOperator *op, wmEvent *event)
assign_material(ob, ma, ob->totcol + 1, BKE_MAT_ASSIGN_USERPREF);
- DAG_ids_flush_update(bmain, 0);
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);
@@ -1883,7 +1885,7 @@ void OUTLINER_OT_material_drop(wmOperatorType *ot)
ot->poll = ED_operator_outliner_active;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
/* properties */
RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", "Target Object");
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 65de2a27568..a918357ced2 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -103,6 +103,7 @@ typedef struct TreeElement {
#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
@@ -115,8 +116,8 @@ typedef struct TreeElement {
/* size constants */
#define OL_Y_OFFSET 2
-#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 3)
-#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 2)
+#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 3.0f)
+#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 2.0f)
#define OL_TOG_RESTRICT_RENDERX UI_UNIT_X
#define OL_TOGW OL_TOG_RESTRICT_VIEWX
@@ -164,8 +165,9 @@ void draw_outliner(const struct bContext *C);
void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag);
/* outliner_select.c -------------------------------------------- */
-int tree_element_type_active(struct bContext *C, struct Scene *scene, struct SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, int set);
+int tree_element_type_active(struct bContext *C, struct Scene *scene, struct SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, int set, bool recursive);
int tree_element_active(struct bContext *C, struct Scene *scene, SpaceOops *soops, TreeElement *te, int set);
+int outliner_item_do_activate(struct bContext *C, int x, int y, bool extend, bool recursive);
/* outliner_edit.c ---------------------------------------------- */
@@ -188,9 +190,9 @@ 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_parent(struct bContext *C, struct wmEvent *event, struct TreeElement *te, float *fmval);
-int outliner_dropzone_parent_clear(struct bContext *C, struct wmEvent *event, struct TreeElement *te, float *fmval);
-TreeElement *outliner_dropzone_scene(struct bContext *C, struct wmEvent *event, struct TreeElement *te, float *fmval);
+TreeElement *outliner_dropzone_parent(struct bContext *C, const struct wmEvent *event, struct TreeElement *te, const float fmval[2]);
+int outliner_dropzone_parent_clear(struct bContext *C, const struct wmEvent *event, struct TreeElement *te, const float fmval[2]);
+TreeElement *outliner_dropzone_scene(struct bContext *C, const struct wmEvent *event, struct TreeElement *te, const float fmval[2]);
/* ...................................................... */
void OUTLINER_OT_item_activate(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index 1dd043409a5..b9e3942a7ce 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -30,12 +30,12 @@
#include "DNA_space_types.h"
-#include "WM_api.h"
-#include "WM_types.h"
+#include "BLI_utildefines.h"
#include "RNA_access.h"
-#include "BLI_utildefines.h"
+#include "WM_api.h"
+#include "WM_types.h"
#include "outliner_intern.h"
@@ -88,10 +88,22 @@ void outliner_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "OUTLINER_OT_item_rename", LEFTMOUSE, KM_DBL_CLICK, 0, 0);
kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, 0, 0);
+ RNA_boolean_set(kmi->ptr, "recursive", FALSE);
RNA_boolean_set(kmi->ptr, "extend", FALSE);
+
kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "recursive", FALSE);
+ RNA_boolean_set(kmi->ptr, "extend", TRUE);
+
+ kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "recursive", TRUE);
+ RNA_boolean_set(kmi->ptr, "extend", FALSE);
+
+ kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, KM_CTRL | KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "recursive", TRUE);
RNA_boolean_set(kmi->ptr, "extend", TRUE);
+
WM_keymap_add_item(keymap, "OUTLINER_OT_select_border", BKEY, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_openclose", RETKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 0b585e1272b..29f1b3fb5a3 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -47,8 +47,11 @@
#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
#include "BKE_scene.h"
#include "BKE_sequencer.h"
+#include "BKE_armature.h"
#include "ED_armature.h"
#include "ED_object.h"
@@ -140,7 +143,50 @@ static int tree_element_active_renderlayer(bContext *C, TreeElement *te, TreeSto
return 0;
}
-static int tree_element_set_active_object(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set)
+/**
+ * Select object tree:
+ * CTRL+LMB: Select/Deselect object and all cildren
+ * CTRL+SHIFT+LMB: Add/Remove object and all children
+ */
+static void do_outliner_object_select_recursive(Scene *scene, Object *ob_parent, bool select)
+{
+ Base *base;
+
+ for (base = FIRSTBASE; base; base = base->next) {
+ Object *ob = base->object;
+ if ((((ob->restrictflag & OB_RESTRICT_VIEW) == 0) && BKE_object_is_child_recursive(ob_parent, ob))) {
+ ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT);
+ }
+ }
+}
+
+static void do_outliner_bone_select_recursive(bArmature *arm, Bone *bone_parent, bool select)
+{
+ Bone *bone;
+ for (bone = bone_parent->childbase.first; bone; bone = bone->next) {
+ if (select && PBONE_SELECTABLE(arm, bone))
+ bone->flag |= BONE_SELECTED;
+ else
+ bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ do_outliner_bone_select_recursive(arm, bone, select);
+ }
+}
+
+static void do_outliner_ebone_select_recursive(bArmature *arm, EditBone *ebone_parent, bool select)
+{
+ EditBone *ebone;
+ for (ebone = ebone_parent->next; ebone; ebone = ebone->next) {
+ if (ED_armature_ebone_is_child_recursive(ebone_parent, ebone)) {
+ if (select && EBONE_SELECTABLE(arm, ebone))
+ ebone->flag |= BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL;
+ else
+ ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ }
+ }
+}
+
+static int tree_element_set_active_object(bContext *C, Scene *scene, SpaceOops *soops,
+ TreeElement *te, int set, bool recursive)
{
TreeStoreElem *tselem = TREESTORE(te);
Scene *sce;
@@ -148,7 +194,9 @@ static int tree_element_set_active_object(bContext *C, Scene *scene, SpaceOops
Object *ob = NULL;
/* if id is not object, we search back */
- if (te->idcode == ID_OB) ob = (Object *)tselem->id;
+ if (te->idcode == ID_OB) {
+ ob = (Object *)tselem->id;
+ }
else {
ob = (Object *)outliner_search_back(soops, te, ID_OB);
if (ob == OBACT) return 0;
@@ -176,6 +224,12 @@ static int tree_element_set_active_object(bContext *C, Scene *scene, SpaceOops
BKE_scene_base_deselect_all(scene);
ED_base_object_select(base, BA_SELECT);
}
+
+ if (recursive) {
+ /* Recursive select/deselect for Object hierarchies */
+ do_outliner_object_select_recursive(scene, ob, (ob->flag & SELECT) != 0);
+ }
+
if (C) {
ED_base_object_activate(C, base); /* adds notifier */
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -183,7 +237,7 @@ static int tree_element_set_active_object(bContext *C, Scene *scene, SpaceOops
}
if (ob != scene->obedit)
- ED_object_exit_editmode(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
return 1;
}
@@ -312,7 +366,9 @@ static int tree_element_active_lamp(bContext *UNUSED(C), Scene *scene, SpaceOops
if (set) {
// XXX extern_set_butspace(F5KEY, 0);
}
- else return 1;
+ else {
+ return 1;
+ }
return 0;
}
@@ -336,7 +392,8 @@ static int tree_element_active_world(bContext *C, Scene *scene, SpaceOops *soops
tep = te->parent;
if (tep) {
tselem = TREESTORE(tep);
- sce = (Scene *)tselem->id;
+ if (tselem->type == 0)
+ sce = (Scene *)tselem->id;
}
if (set) { // make new scene active
@@ -394,7 +451,7 @@ static int tree_element_active_posegroup(bContext *C, Scene *scene, TreeElement
return 0;
}
-static int tree_element_active_posechannel(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set)
+static int tree_element_active_posechannel(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set, bool recursive)
{
Object *ob = (Object *)tselem->id;
bArmature *arm = ob->data;
@@ -403,9 +460,13 @@ static int tree_element_active_posechannel(bContext *C, Scene *scene, TreeElemen
if (set) {
if (!(pchan->bone->flag & BONE_HIDDEN_P)) {
- if (set == 2) ED_pose_deselectall(ob, 2); // 2 = clear active tag
- else ED_pose_deselectall(ob, 0); // 0 = deselect
-
+ if (set != 2) {
+ 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);
+ }
+
if (set == 2 && (pchan->bone->flag & BONE_SELECTED)) {
pchan->bone->flag &= ~BONE_SELECTED;
}
@@ -413,7 +474,12 @@ static int tree_element_active_posechannel(bContext *C, Scene *scene, TreeElemen
pchan->bone->flag |= BONE_SELECTED;
arm->act_bone = pchan->bone;
}
-
+
+ if (recursive) {
+ /* Recursive select/deselect */
+ do_outliner_bone_select_recursive(arm, pchan->bone, (pchan->bone->flag & BONE_SELECTED) != 0);
+ }
+
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, ob);
}
@@ -426,7 +492,7 @@ static int tree_element_active_posechannel(bContext *C, Scene *scene, TreeElemen
return 0;
}
-static int tree_element_active_bone(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set)
+static int tree_element_active_bone(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set, bool recursive)
{
bArmature *arm = (bArmature *)tselem->id;
Bone *bone = te->directdata;
@@ -435,8 +501,12 @@ static int tree_element_active_bone(bContext *C, Scene *scene, TreeElement *te,
if (!(bone->flag & BONE_HIDDEN_P)) {
Object *ob = OBACT;
if (ob) {
- if (set == 2) ED_pose_deselectall(ob, 2); // 2 is clear active tag
- else ED_pose_deselectall(ob, 0);
+ if (set != 2) {
+ 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);
+ }
}
if (set == 2 && (bone->flag & BONE_SELECTED)) {
@@ -446,6 +516,12 @@ static int tree_element_active_bone(bContext *C, Scene *scene, TreeElement *te,
bone->flag |= BONE_SELECTED;
arm->act_bone = bone;
}
+
+ if (recursive) {
+ /* Recursive select/deselect */
+ do_outliner_bone_select_recursive(arm, bone, (bone->flag & BONE_SELECTED) != 0);
+ }
+
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, ob);
}
@@ -478,35 +554,42 @@ static void tree_element_active_ebone__sel(bContext *C, Scene *scene, bArmature
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, scene->obedit);
}
-static int tree_element_active_ebone(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tselem), int set)
+static int tree_element_active_ebone(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tselem), int set, bool recursive)
{
bArmature *arm = scene->obedit->data;
EditBone *ebone = te->directdata;
-
- if (set == 1) {
- if (!(ebone->flag & BONE_HIDDEN_A)) {
- ED_armature_deselect_all(scene->obedit, 0); // deselect
- tree_element_active_ebone__sel(C, scene, arm, ebone, TRUE);
- return 1;
- }
- }
- else if (set == 2) {
- if (!(ebone->flag & BONE_HIDDEN_A)) {
- if (!(ebone->flag & BONE_SELECTED)) {
+ int status = 0;
+ if (set) {
+ if (set == 1) {
+ if (!(ebone->flag & BONE_HIDDEN_A)) {
+ ED_armature_deselect_all(scene->obedit, 0); // deselect
tree_element_active_ebone__sel(C, scene, arm, ebone, TRUE);
- return 1;
+ status = 1;
}
- else {
- /* entirely selected, so de-select */
- tree_element_active_ebone__sel(C, scene, arm, ebone, FALSE);
- return 0;
+ }
+ else if (set == 2) {
+ if (!(ebone->flag & BONE_HIDDEN_A)) {
+ if (!(ebone->flag & BONE_SELECTED)) {
+ tree_element_active_ebone__sel(C, scene, arm, ebone, TRUE);
+ status = 1;
+ }
+ else {
+ /* entirely selected, so de-select */
+ tree_element_active_ebone__sel(C, scene, arm, ebone, FALSE);
+ status = 0;
+ }
}
}
+
+ if (recursive) {
+ /* Recursive select/deselect */
+ do_outliner_ebone_select_recursive(arm, ebone, (ebone->flag & BONE_SELECTED) != 0);
+ }
}
else if (ebone->flag & BONE_SELECTED) {
- return 1;
+ status = 1;
}
- return 0;
+ return status;
}
static int tree_element_active_modifier(bContext *C, TreeElement *UNUSED(te), TreeStoreElem *tselem, int set)
@@ -560,7 +643,7 @@ static int tree_element_active_pose(bContext *C, Scene *scene, TreeElement *UNUS
if (set) {
if (scene->obedit)
- ED_object_exit_editmode(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
if (ob->mode & OB_MODE_POSE)
ED_armature_exit_posemode(C, base);
@@ -674,19 +757,19 @@ int tree_element_active(bContext *C, Scene *scene, SpaceOops *soops, TreeElement
/* generic call for non-id data to make/check active in UI */
/* Context can be NULL when set==0 */
int tree_element_type_active(bContext *C, Scene *scene, SpaceOops *soops,
- TreeElement *te, TreeStoreElem *tselem, int set)
+ TreeElement *te, TreeStoreElem *tselem, int set, bool recursive)
{
switch (tselem->type) {
case TSE_DEFGROUP:
return tree_element_active_defgroup(C, scene, te, tselem, set);
case TSE_BONE:
- return tree_element_active_bone(C, scene, te, tselem, set);
+ return tree_element_active_bone(C, scene, te, tselem, set, recursive);
case TSE_EBONE:
- return tree_element_active_ebone(C, scene, te, tselem, set);
+ return tree_element_active_ebone(C, scene, te, tselem, set, recursive);
case TSE_MODIFIER:
return tree_element_active_modifier(C, te, tselem, set);
case TSE_LINKED_OB:
- if (set) tree_element_set_active_object(C, scene, soops, te, set);
+ if (set) tree_element_set_active_object(C, scene, soops, te, set, FALSE);
else if (tselem->id == (ID *)OBACT) return 1;
break;
case TSE_LINKED_PSYS:
@@ -694,7 +777,7 @@ int tree_element_type_active(bContext *C, Scene *scene, SpaceOops *soops,
case TSE_POSE_BASE:
return tree_element_active_pose(C, scene, te, tselem, set);
case TSE_POSE_CHANNEL:
- return tree_element_active_posechannel(C, scene, te, tselem, set);
+ return tree_element_active_posechannel(C, scene, te, tselem, set, recursive);
case TSE_CONSTRAINT:
return tree_element_active_constraint(C, te, tselem, set);
case TSE_R_LAYER:
@@ -715,7 +798,7 @@ int tree_element_type_active(bContext *C, Scene *scene, SpaceOops *soops,
/* ================================================ */
static int do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops,
- TreeElement *te, int extend, const float mval[2])
+ TreeElement *te, bool extend, bool recursive, const float mval[2])
{
if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
@@ -747,7 +830,9 @@ static int do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, Spa
/* always makes active object */
if (tselem->type != TSE_SEQUENCE && tselem->type != TSE_SEQ_STRIP && tselem->type != TSE_SEQUENCE_DUP)
- tree_element_set_active_object(C, scene, soops, te, 1 + (extend != 0 && tselem->type == 0));
+ tree_element_set_active_object(C, scene, soops, te,
+ 1 + (extend != 0 && tselem->type == 0),
+ recursive && tselem->type == 0 );
if (tselem->type == 0) { // the lib blocks
/* editmode? */
@@ -790,31 +875,31 @@ static int do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, Spa
else { // rest of types
tree_element_active(C, scene, soops, te, 1);
}
-
+
+ }
+ else {
+ tree_element_type_active(C, scene, soops, te, tselem, 1 + (extend != 0), recursive);
}
- else tree_element_type_active(C, scene, soops, te, tselem, 1 + (extend != 0));
return 1;
}
}
for (te = te->subtree.first; te; te = te->next) {
- if (do_outliner_item_activate(C, scene, ar, soops, te, extend, mval)) return 1;
+ if (do_outliner_item_activate(C, scene, ar, soops, te, extend, recursive, mval)) return 1;
}
return 0;
}
-/* event can enterkey, then it opens/closes */
-static int outliner_item_activate(bContext *C, wmOperator *op, wmEvent *event)
+int outliner_item_do_activate(bContext *C, int x, int y, bool extend, bool recursive)
{
Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
TreeElement *te;
float fmval[2];
- int extend = RNA_boolean_get(op->ptr, "extend");
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], fmval, fmval + 1);
+ UI_view2d_region_to_view(&ar->v2d, x, y, fmval, fmval + 1);
if (!ELEM3(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF, SO_KEYMAP) &&
!(soops->flag & SO_HIDE_RESTRICTCOLS) &&
@@ -824,7 +909,7 @@ static int outliner_item_activate(bContext *C, wmOperator *op, wmEvent *event)
}
for (te = soops->tree.first; te; te = te->next) {
- if (do_outliner_item_activate(C, scene, ar, soops, te, extend, fmval)) break;
+ if (do_outliner_item_activate(C, scene, ar, soops, te, extend, recursive, fmval)) break;
}
if (te) {
@@ -854,6 +939,16 @@ static int outliner_item_activate(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_FINISHED;
}
+/* event can enterkey, then it opens/closes */
+static int outliner_item_activate(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+ bool recursive = RNA_boolean_get(op->ptr, "recursive");
+ int x = event->mval[0];
+ int y = event->mval[1];
+ return outliner_item_do_activate(C, x, y, extend, recursive);
+}
+
void OUTLINER_OT_item_activate(wmOperatorType *ot)
{
ot->name = "Activate Item";
@@ -864,7 +959,8 @@ void OUTLINER_OT_item_activate(wmOperatorType *ot)
ot->poll = ED_operator_outliner_active;
- RNA_def_boolean(ot->srna, "extend", 1, "Extend", "Extend selection for activation");
+ RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection for activation");
+ RNA_def_boolean(ot->srna, "recursive", false, "Recursive", "Select Objects and their children");
}
/* ****************************************************** */
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 3b83279e09d..9b9e7bef42c 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -75,6 +75,7 @@
#include "outliner_intern.h"
+
/* ****************************************************** */
/* ************ SELECTION OPERATIONS ********* */
@@ -190,8 +191,10 @@ static void unlink_texture_cb(bContext *UNUSED(C), Scene *UNUSED(scene), TreeEle
World *wrld = (World *)tsep->id;
mtex = wrld->mtex;
}
- else return;
-
+ else {
+ return;
+ }
+
for (a = 0; a < MAX_MTEX; a++) {
if (a == te->index && mtex[a]) {
if (mtex[a]->tex) {
@@ -264,6 +267,17 @@ static void object_select_cb(bContext *UNUSED(C), Scene *scene, TreeElement *te,
}
}
+static void object_select_hierarchy_cb(bContext *C, Scene *UNUSED(scene), TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep), TreeStoreElem *UNUSED(tselem))
+{
+ /* From where do i get the x,y coordinate of the mouse event ? */
+ wmWindow *win = CTX_wm_window(C);
+ int x = win->eventstate->mval[0];
+ int y = win->eventstate->mval[1];
+ outliner_item_do_activate(C, x, y, true, true);
+}
+
+
static void object_deselect_cb(bContext *UNUSED(C), Scene *scene, TreeElement *te,
TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem)
{
@@ -286,7 +300,7 @@ static void object_delete_cb(bContext *C, Scene *scene, TreeElement *te,
if (base) {
// check also library later
if (scene->obedit == base->object)
- ED_object_exit_editmode(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
ED_base_object_free_and_unlink(CTX_data_main(C), scene, base);
te->directdata = NULL;
@@ -300,7 +314,7 @@ static void id_local_cb(bContext *C, Scene *UNUSED(scene), TreeElement *UNUSED(t
if (tselem->id->lib && (tselem->id->flag & LIB_EXTERN)) {
/* if the ID type has no special local function,
* just clear the lib */
- if (id_make_local(tselem->id, FALSE) == FALSE) {
+ if (id_make_local(tselem->id, false) == false) {
Main *bmain = CTX_data_main(C);
id_clear_lib_data(bmain, tselem->id);
}
@@ -389,7 +403,7 @@ static void group_linkobs2scene_cb(bContext *UNUSED(C), Scene *scene, TreeElemen
/* link to scene */
base = MEM_callocN(sizeof(Base), "add_base");
BLI_addhead(&scene->base, base);
- base->lay = (1 << 20) - 1; /*v3d->lay;*/ /* would be nice to use the 3d layer but the include's not here */
+ base->lay = gob->ob->lay;
gob->ob->flag |= SELECT;
base->flag = gob->ob->flag;
base->object = gob->ob;
@@ -526,9 +540,9 @@ static void sequence_cb(int event, TreeElement *te, TreeStoreElem *tselem, void
Sequence *seq = (Sequence *)te->directdata;
if (event == 1) {
Scene *scene = (Scene *)scene_ptr;
- Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
if (BLI_findindex(ed->seqbasep, seq) != -1) {
- ED_sequencer_select_sequence_single(scene, seq, TRUE);
+ ED_sequencer_select_sequence_single(scene, seq, true);
}
}
@@ -569,15 +583,29 @@ static void outliner_do_data_operation(SpaceOops *soops, int type, int event, Li
/* **************************************** */
+enum {
+ OL_OP_ENDMARKER = 0,
+ OL_OP_SELECT,
+ OL_OP_DESELECT,
+ OL_OP_SELECT_HIERARCHY,
+ OL_OP_DELETE,
+ OL_OP_LOCALIZED, /* disabled, see below */
+ OL_OP_TOGVIS,
+ OL_OP_TOGSEL,
+ OL_OP_TOGREN,
+ OL_OP_RENAME
+};
+
static EnumPropertyItem prop_object_op_types[] = {
- {1, "SELECT", 0, "Select", ""},
- {2, "DESELECT", 0, "Deselect", ""},
- {4, "DELETE", 0, "Delete", ""},
- {6, "TOGVIS", 0, "Toggle Visible", ""},
- {7, "TOGSEL", 0, "Toggle Selectable", ""},
- {8, "TOGREN", 0, "Toggle Renderable", ""},
- {9, "RENAME", 0, "Rename", ""},
- {0, NULL, 0, NULL, NULL}
+ {OL_OP_SELECT, "SELECT", 0, "Select", ""},
+ {OL_OP_DESELECT, "DESELECT", 0, "Deselect", ""},
+ {OL_OP_SELECT_HIERARCHY, "SELECT_HIERARCHY", 0, "Select Hierarchy", ""},
+ {OL_OP_DELETE, "DELETE", 0, "Delete", ""},
+ {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}
};
static int outliner_object_operation_exec(bContext *C, wmOperator *op)
@@ -594,7 +622,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
event = RNA_enum_get(op->ptr, "type");
- if (event == 1) {
+ if (event == OL_OP_SELECT) {
Scene *sce = scene; // to be able to delete, scenes are set...
outliner_do_object_operation(C, scene, soops, &soops->tree, object_select_cb);
if (scene != sce) {
@@ -604,12 +632,21 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
str = "Select Objects";
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
- else if (event == 2) {
+ else if (event == OL_OP_SELECT_HIERARCHY) {
+ Scene *sce = scene; // to be able to delete, scenes are set...
+ outliner_do_object_operation(C, scene, soops, &soops->tree, object_select_hierarchy_cb);
+ if (scene != sce) {
+ ED_screen_set_scene(C, CTX_wm_screen(C), sce);
+ }
+ str = "Select Object Hierarchy";
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ }
+ else if (event == OL_OP_DESELECT) {
outliner_do_object_operation(C, scene, soops, &soops->tree, object_deselect_cb);
str = "Deselect Objects";
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
- else if (event == 4) {
+ else if (event == OL_OP_DELETE) {
outliner_do_object_operation(C, scene, soops, &soops->tree, object_delete_cb);
/* XXX: tree management normally happens from draw_outliner(), but when
@@ -619,30 +656,30 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
* cleanup tree here to prevent such cases. */
outliner_cleanup_tree(soops);
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
str = "Delete Objects";
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
}
- else if (event == 5) { /* disabled, see above enum (ton) */
+ 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";
}
- else if (event == 6) {
+ else if (event == OL_OP_TOGVIS) {
outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_visibility_cb);
str = "Toggle Visibility";
WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene);
}
- else if (event == 7) {
+ else if (event == OL_OP_TOGSEL) {
outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_selectability_cb);
str = "Toggle Selectability";
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
- else if (event == 8) {
+ else if (event == OL_OP_TOGREN) {
outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_renderability_cb);
str = "Toggle Renderability";
WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, scene);
}
- else if (event == 9) {
+ else if (event == OL_OP_RENAME) {
outliner_do_object_operation(C, scene, soops, &soops->tree, item_rename_cb);
str = "Rename Object";
}
@@ -712,10 +749,8 @@ static int outliner_group_operation_exec(bContext *C, wmOperator *op)
if (event == 3) { /* instance */
- Main *bmain = CTX_data_main(C);
-
/* works without this except if you try render right after, see: 22027 */
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(CTX_data_main(C));
}
ED_undo_push(C, prop_group_op_types[event].name);
@@ -764,7 +799,7 @@ static EnumPropertyItem prop_id_op_types[] = {
{OUTLINER_IDOP_LOCAL, "LOCAL", 0, "Make Local", ""},
{OUTLINER_IDOP_SINGLE, "SINGLE", 0, "Make Single User", ""},
{OUTLINER_IDOP_FAKE_ADD, "ADD_FAKE", 0, "Add Fake User",
- "Ensure datablock gets saved even if it isn't in use (e.g. for motion and material libraries)"},
+ "Ensure datablock gets saved even if it isn't in use (e.g. for motion and material libraries)"},
{OUTLINER_IDOP_FAKE_CLEAR, "CLEAR_FAKE", 0, "Clear Fake User", ""},
{OUTLINER_IDOP_RENAME, "RENAME", 0, "Rename", ""},
{OUTLINER_IDOP_SELECT_LINKED, "SELECT_LINKED", 0, "Select Linked", ""},
@@ -1110,14 +1145,8 @@ static int outliner_animdata_operation_exec(bContext *C, wmOperator *op)
/* update dependencies */
if (updateDeps) {
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
-
/* rebuild depsgraph for the new deps */
- DAG_scene_sort(bmain, scene);
-
- /* force an update of depsgraph */
- DAG_ids_flush_update(bmain, 0);
+ DAG_relations_tag_update(CTX_data_main(C));
}
return OPERATOR_FINISHED;
@@ -1237,7 +1266,7 @@ void OUTLINER_OT_data_operation(wmOperatorType *ot)
static int do_outliner_operation_event(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops,
- TreeElement *te, wmEvent *event, const float mval[2])
+ TreeElement *te, const wmEvent *event, const float mval[2])
{
ReportList *reports = CTX_wm_reports(C); // XXX...
@@ -1267,7 +1296,9 @@ static int do_outliner_operation_event(bContext *C, Scene *scene, ARegion *ar, S
WM_operator_name_call(C, "OUTLINER_OT_object_operation", WM_OP_INVOKE_REGION_WIN, NULL);
}
else if (idlevel) {
- if (idlevel == -1 || datalevel) BKE_report(reports, RPT_WARNING, "Mixed selection");
+ if (idlevel == -1 || datalevel) {
+ BKE_report(reports, RPT_WARNING, "Mixed selection");
+ }
else {
if (idlevel == ID_GR)
WM_operator_name_call(C, "OUTLINER_OT_group_operation", WM_OP_INVOKE_REGION_WIN, NULL);
@@ -1276,7 +1307,9 @@ static int do_outliner_operation_event(bContext *C, Scene *scene, ARegion *ar, S
}
}
else if (datalevel) {
- if (datalevel == -1) BKE_report(reports, RPT_WARNING, "Mixed selection");
+ if (datalevel == -1) {
+ BKE_report(reports, RPT_WARNING, "Mixed selection");
+ }
else {
if (datalevel == TSE_ANIM_DATA)
WM_operator_name_call(C, "OUTLINER_OT_animdata_operation", WM_OP_INVOKE_REGION_WIN, NULL);
@@ -1303,7 +1336,7 @@ static int do_outliner_operation_event(bContext *C, Scene *scene, ARegion *ar, S
}
-static int outliner_operation(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int outliner_operation(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index e6910280da4..19bc1db2b5d 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -64,10 +64,14 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLF_translation.h"
+
#include "BKE_fcurve.h"
#include "BKE_main.h"
+#include "BKE_library.h"
#include "BKE_modifier.h"
#include "BKE_sequencer.h"
+#include "BKE_idcode.h"
#include "ED_armature.h"
#include "ED_screen.h"
@@ -320,7 +324,7 @@ static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, Sc
* in order to not overflow short tselem->nr */
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_COMBINED));
- te->name = "Combined";
+ te->name = IFACE_("Combined");
te->directdata = &srl->passflag;
/* save cpu cycles, but we add the first to invoke an open/close triangle */
@@ -329,71 +333,71 @@ static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, Sc
return;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_Z));
- te->name = "Z";
+ te->name = IFACE_("Z");
te->directdata = &srl->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_VECTOR));
- te->name = "Vector";
+ te->name = IFACE_("Vector");
te->directdata = &srl->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_NORMAL));
- te->name = "Normal";
+ te->name = IFACE_("Normal");
te->directdata = &srl->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_UV));
- te->name = "UV";
+ te->name = IFACE_("UV");
te->directdata = &srl->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_MIST));
- te->name = "Mist";
+ te->name = IFACE_("Mist");
te->directdata = &srl->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_INDEXOB));
- te->name = "Index Object";
+ te->name = IFACE_("Index Object");
te->directdata = &srl->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_INDEXMA));
- te->name = "Index Material";
+ te->name = IFACE_("Index Material");
te->directdata = &srl->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_RGBA));
- te->name = "Color";
+ te->name = IFACE_("Color");
te->directdata = &srl->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_DIFFUSE));
- te->name = "Diffuse";
+ te->name = IFACE_("Diffuse");
te->directdata = &srl->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_SPEC));
- te->name = "Specular";
+ te->name = IFACE_("Specular");
te->directdata = &srl->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_SHADOW));
- te->name = "Shadow";
+ te->name = IFACE_("Shadow");
te->directdata = &srl->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_AO));
- te->name = "AO";
+ te->name = IFACE_("AO");
te->directdata = &srl->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_REFLECT));
- te->name = "Reflection";
+ te->name = IFACE_("Reflection");
te->directdata = &srl->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_REFRACT));
- te->name = "Refraction";
+ te->name = IFACE_("Refraction");
te->directdata = &srl->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_INDIRECT));
- te->name = "Indirect";
+ te->name = IFACE_("Indirect");
te->directdata = &srl->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_ENVIRONMENT));
- te->name = "Environment";
+ te->name = IFACE_("Environment");
te->directdata = &srl->passflag;
te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_EMIT));
- te->name = "Emit";
+ te->name = IFACE_("Emit");
te->directdata = &srl->passflag;
}
@@ -405,7 +409,7 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s
TreeElement *tenla = outliner_add_element(soops, lb, sce, te, TSE_R_LAYER_BASE, 0);
int a;
- tenla->name = "RenderLayers";
+ tenla->name = IFACE_("RenderLayers");
for (a = 0, srl = sce->r.layers.first; srl; srl = srl->next, a++) {
TreeElement *tenlay = outliner_add_element(soops, &tenla->subtree, sce, te, TSE_R_LAYER, a);
tenlay->name = srl->name;
@@ -447,7 +451,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
TreeElement *ten;
TreeElement *tenla = outliner_add_element(soops, &te->subtree, ob, te, TSE_POSE_BASE, 0);
- tenla->name = "Pose";
+ tenla->name = IFACE_("Pose");
/* channels undefined in editmode, but we want the 'tenla' pose icon itself */
if ((arm->edbo == NULL) && (ob->mode & OB_MODE_POSE)) {
@@ -466,7 +470,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
TreeElement *tenla1 = outliner_add_element(soops, &ten->subtree, ob, ten, TSE_CONSTRAINT_BASE, 0);
//char *str;
- tenla1->name = "Constraints";
+ tenla1->name = IFACE_("Constraints");
for (con = pchan->constraints.first; con; con = con->next, const_index++) {
ten1 = outliner_add_element(soops, &tenla1->subtree, ob, tenla1, TSE_CONSTRAINT, const_index);
#if 0 /* disabled as it needs to be reworked for recoded constraints system */
@@ -506,7 +510,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
TreeElement *tenla = outliner_add_element(soops, &te->subtree, ob, te, TSE_POSEGRP_BASE, 0);
int a = 0;
- tenla->name = "Bone Groups";
+ tenla->name = IFACE_("Bone Groups");
for (agrp = ob->pose->agroups.first; agrp; agrp = agrp->next, a++) {
ten = outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_POSEGRP, a);
ten->name = agrp->name;
@@ -525,7 +529,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
TreeElement *tenla = outliner_add_element(soops, &te->subtree, ob, te, TSE_CONSTRAINT_BASE, 0);
//char *str;
- tenla->name = "Constraints";
+ tenla->name = IFACE_("Constraints");
for (con = ob->constraints.first, a = 0; con; con = con->next, a++) {
ten = outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_CONSTRAINT, a);
#if 0 /* disabled due to constraints system targets recode... code here needs review */
@@ -545,7 +549,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
TreeElement *temod = outliner_add_element(soops, &te->subtree, ob, te, TSE_MODIFIER_BASE, 0);
int index;
- temod->name = "Modifiers";
+ temod->name = IFACE_("Modifiers");
for (index = 0, md = ob->modifiers.first; md; index++, md = md->next) {
TreeElement *te = outliner_add_element(soops, &temod->subtree, ob, temod, TSE_MODIFIER, index);
te->name = md->name;
@@ -580,7 +584,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
TreeElement *ten;
TreeElement *tenla = outliner_add_element(soops, &te->subtree, ob, te, TSE_DEFGROUP_BASE, 0);
- tenla->name = "Vertex Groups";
+ tenla->name = IFACE_("Vertex Groups");
for (defgroup = ob->defbase.first, a = 0; defgroup; defgroup = defgroup->next, a++) {
ten = outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_DEFGROUP, a);
ten->name = defgroup->name;
@@ -593,6 +597,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
outliner_add_element(soops, &te->subtree, ob->dup_group, te, 0, 0);
}
+
// can be inlined if necessary
static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, ID *id)
{
@@ -785,6 +790,7 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
}
// TODO: this function needs to be split up! It's getting a bit too large...
+// Note: "ID" is not always a real ID
static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *idv,
TreeElement *parent, short type, short index)
{
@@ -798,7 +804,13 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
if (!id) id = ((PointerRNA *)idv)->data;
}
- if (id == NULL) return NULL;
+ /* One exception */
+ if (type == TSE_ID_BASE) {
+ /* pass */
+ }
+ else if (id == NULL) {
+ return NULL;
+ }
te = MEM_callocN(sizeof(TreeElement), "tree elem");
/* add to the visual tree */
@@ -822,21 +834,31 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
else if (type == TSE_ANIM_DATA) {
/* pass */
}
+ else if (type == TSE_ID_BASE) {
+ /* pass */
+ }
else {
- te->name = id->name + 2; // default, can be overridden by Library or non-ID data
+ /* do here too, for blend file viewer, own ID_LI then shows file name */
+ if (GS(id->name) == ID_LI)
+ te->name = ((Library *)id)->name;
+ else
+ te->name = id->name + 2; // default, can be overridden by Library or non-ID data
te->idcode = GS(id->name);
}
if (type == 0) {
+ TreeStoreElem *tsepar = parent ? TREESTORE(parent) : NULL;
+
/* ID datablock */
- outliner_add_id_contents(soops, te, tselem, id);
+ if (tsepar == NULL || tsepar->type != TSE_ID_BASE)
+ outliner_add_id_contents(soops, te, tselem, id);
}
else if (type == TSE_ANIM_DATA) {
IdAdtTemplate *iat = (IdAdtTemplate *)idv;
AnimData *adt = (AnimData *)iat->adt;
/* this element's info */
- te->name = "Animation";
+ te->name = IFACE_("Animation");
te->directdata = adt;
/* Action */
@@ -848,7 +870,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
ID *lastadded = NULL;
FCurve *fcu;
- ted->name = "Drivers";
+ ted->name = IFACE_("Drivers");
for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
if (fcu->driver && fcu->driver->variables.first) {
@@ -877,7 +899,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
NlaTrack *nlt;
int a = 0;
- tenla->name = "NLA Tracks";
+ tenla->name = IFACE_("NLA Tracks");
for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
TreeElement *tenlt = outliner_add_element(soops, &tenla->subtree, nlt, tenla, TSE_NLA_TRACK, a);
@@ -931,7 +953,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
if (strip->dir)
te->name = strip->dir;
else
- te->name = "Strip None";
+ te->name = IFACE_("Strip None");
te->directdata = strip;
}
else if (type == TSE_SEQUENCE_DUP) {
@@ -950,7 +972,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
/* we do lazy build, for speed and to avoid infinite recusion */
if (ptr->data == NULL) {
- te->name = "(empty)";
+ te->name = IFACE_("(empty)");
}
else if (type == TSE_RNA_STRUCT) {
/* struct */
@@ -1076,7 +1098,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
ten->directdata = kmi;
if (kmi->propvalue) {
- ten->name = "Modal map, not yet";
+ ten->name = IFACE_("Modal map, not yet");
}
else {
WM_operator_py_idname(opname, ot->idname);
@@ -1194,8 +1216,8 @@ typedef struct tTreeSort {
short idcode;
} tTreeSort;
-/* alphabetical comparator */
-static int treesort_alpha(const void *v1, const void *v2)
+/* alphabetical comparator, tryping to put objects first */
+static int treesort_alpha_ob(const void *v1, const void *v2)
{
const tTreeSort *x1 = v1, *x2 = v2;
int comp;
@@ -1216,6 +1238,20 @@ static int treesort_alpha(const void *v1, const void *v2)
return 0;
}
+/* alphabetical comparator */
+static int treesort_alpha(const void *v1, const void *v2)
+{
+ const tTreeSort *x1 = v1, *x2 = v2;
+ int comp;
+
+ comp = strcmp(x1->name, x2->name);
+
+ if (comp > 0) return 1;
+ else if (comp < 0) return -1;
+ return 0;
+}
+
+
/* this is nice option for later? doesnt look too useful... */
#if 0
static int treesort_obtype_alpha(const void *v1, const void *v2)
@@ -1223,19 +1259,23 @@ static int treesort_obtype_alpha(const void *v1, const void *v2)
const tTreeSort *x1 = v1, *x2 = v2;
/* first put objects last (hierarchy) */
- if (x1->idcode == ID_OB && x2->idcode != ID_OB) return 1;
- else if (x2->idcode == ID_OB && x1->idcode != ID_OB) return -1;
+ if (x1->idcode == ID_OB && x2->idcode != ID_OB) {
+ return 1;
+ }
+ else if (x2->idcode == ID_OB && x1->idcode != ID_OB) {
+ return -1;
+ }
else {
/* 2nd we check ob type */
if (x1->idcode == ID_OB && x2->idcode == ID_OB) {
- if (((Object *)x1->id)->type > ((Object *)x2->id)->type) return 1;
+ if (((Object *)x1->id)->type > ((Object *)x2->id)->type) return 1;
else if (((Object *)x1->id)->type > ((Object *)x2->id)->type) return -1;
else return 0;
}
else {
int comp = strcmp(x1->name, x2->name);
- if (comp > 0) return 1;
+ if (comp > 0) return 1;
else if (comp < 0) return -1;
return 0;
}
@@ -1254,8 +1294,8 @@ static void outliner_sort(SpaceOops *soops, ListBase *lb)
if (te == NULL) return;
tselem = TREESTORE(te);
- /* sorting rules; only object lists or deformgroups */
- if ((tselem->type == TSE_DEFGROUP) || (tselem->type == 0 && te->idcode == ID_OB)) {
+ /* sorting rules; only object lists, ID lists, or deformgroups */
+ if ( ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) || (tselem->type == 0 && te->idcode == ID_OB)) {
/* count first */
for (te = lb->first; te; te = te->next) totelem++;
@@ -1270,15 +1310,27 @@ static void outliner_sort(SpaceOops *soops, ListBase *lb)
tp->te = te;
tp->name = te->name;
tp->idcode = te->idcode;
- if (tselem->type && tselem->type != TSE_DEFGROUP) tp->idcode = 0; // don't sort this
+
+ if (tselem->type && tselem->type != TSE_DEFGROUP)
+ tp->idcode = 0; // don't sort this
+ if (tselem->type == TSE_ID_BASE)
+ tp->idcode = 1; // do sort this
+
tp->id = tselem->id;
}
- /* keep beginning of list */
- for (tp = tear, skip = 0; skip < totelem; skip++, tp++)
- if (tp->idcode) break;
- if (skip < totelem)
- qsort(tear + skip, totelem - skip, sizeof(tTreeSort), treesort_alpha);
+ /* just sort alphabetically */
+ if (tear->idcode == 1) {
+ qsort(tear, totelem, sizeof(tTreeSort), treesort_alpha);
+ }
+ else {
+ /* keep beginning of list */
+ for (tp = tear, skip = 0; skip < totelem; skip++, tp++)
+ if (tp->idcode) break;
+
+ if (skip < totelem)
+ qsort(tear + skip, totelem - skip, sizeof(tTreeSort), treesort_alpha_ob);
+ }
lb->first = lb->last = NULL;
tp = tear;
@@ -1384,6 +1436,42 @@ static int outliner_filter_tree(SpaceOops *soops, ListBase *lb)
return (lb->first != NULL);
}
+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 */
@@ -1418,17 +1506,31 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
if (soops->outlinevis == SO_LIBRARIES) {
Library *lib;
+ /* current file first - mainvar provides tselem with unique pointer - not used */
+ ten = outliner_add_element(soops, &soops->tree, mainvar, NULL, TSE_ID_BASE, 0);
+ ten->name = IFACE_("Current File");
+
+ tselem = TREESTORE(ten);
+ if (!tselem->used)
+ tselem->flag &= ~TSE_CLOSED;
+
+ outliner_add_library_contents(mainvar, soops, ten, NULL);
+
for (lib = mainvar->library.first; lib; lib = lib->id.next) {
ten = outliner_add_element(soops, &soops->tree, lib, NULL, 0, 0);
lib->id.newid = (ID *)ten;
+
+ outliner_add_library_contents(mainvar, soops, ten, lib);
+
}
/* make hierarchy */
ten = soops->tree.first;
+ ten = ten->next; /* first one is main */
while (ten) {
TreeElement *nten = ten->next, *par;
tselem = TREESTORE(ten);
lib = (Library *)tselem->id;
- if (lib->parent) {
+ if (lib && lib->parent) {
BLI_remlink(&soops->tree, ten);
par = (TreeElement *)lib->parent->id.newid;
BLI_addtail(&par->subtree, ten);
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index ecc09a35670..3849aaf78c1 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -67,6 +67,17 @@ static void outliner_main_area_init(wmWindowManager *wm, ARegion *ar)
ListBase *lb;
wmKeyMap *keymap;
+ /* make sure we keep the hide flags */
+ ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
+ ar->v2d.scroll &= ~(V2D_SCROLL_LEFT | V2D_SCROLL_TOP); /* prevent any noise of past */
+ ar->v2d.scroll |= V2D_SCROLL_HORIZONTAL_HIDE;
+ ar->v2d.scroll |= V2D_SCROLL_VERTICAL_HIDE;
+
+ ar->v2d.align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
+ ar->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
+ ar->v2d.keeptot = V2D_KEEPTOT_STRICT;
+ ar->v2d.minzoom = ar->v2d.maxzoom = 1.0f;
+
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
/* own keymap */
@@ -79,7 +90,7 @@ static void outliner_main_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_dropbox_handler(&ar->handlers, lb);
}
-static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
+static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
@@ -124,7 +135,7 @@ static void outliner_parent_drop_copy(wmDrag *drag, wmDropBox *drop)
RNA_string_set(drop->ptr, "child", id->name + 2);
}
-static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, wmEvent *event)
+static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
@@ -165,7 +176,7 @@ static void outliner_parent_clear_copy(wmDrag *drag, wmDropBox *drop)
RNA_enum_set(drop->ptr, "type", 0);
}
-static int outliner_scene_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
+static int outliner_scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
@@ -194,7 +205,7 @@ static void outliner_scene_drop_copy(wmDrag *drag, wmDropBox *drop)
RNA_string_set(drop->ptr, "object", id->name + 2);
}
-static int outliner_material_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
+static int outliner_material_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
@@ -305,6 +316,10 @@ static void outliner_main_area_listener(ARegion *ar, wmNotifier *wmn)
/* all modifier actions now */
ED_region_tag_redraw(ar);
break;
+ default:
+ /* Trigger update for NC_OBJECT itself */
+ ED_region_tag_redraw(ar);
+ break;
}
break;
case NC_GROUP:
@@ -410,12 +425,6 @@ static SpaceLink *outliner_new(const bContext *UNUSED(C))
BLI_addtail(&soutliner->regionbase, ar);
ar->regiontype = RGN_TYPE_WINDOW;
- ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM_O);
- ar->v2d.align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
- ar->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
- ar->v2d.keeptot = V2D_KEEPTOT_STRICT;
- ar->v2d.minzoom = ar->v2d.maxzoom = 1.0f;
-
return (SpaceLink *)soutliner;
}
diff --git a/source/blender/editors/space_script/SConscript b/source/blender/editors/space_script/SConscript
index c30e204f6f4..eff603a3e2d 100644
--- a/source/blender/editors/space_script/SConscript
+++ b/source/blender/editors/space_script/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/space_script/script_edit.c b/source/blender/editors/space_script/script_edit.c
index 4e6783e1862..96008004ee4 100644
--- a/source/blender/editors/space_script/script_edit.c
+++ b/source/blender/editors/space_script/script_edit.c
@@ -71,7 +71,7 @@ static int run_pyfile_exec(bContext *C, wmOperator *op)
void SCRIPT_OT_python_file_run(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Run python file";
+ ot->name = "Run Python File";
ot->description = "Run Python file";
ot->idname = "SCRIPT_OT_python_file_run";
ot->flag = OPTYPE_UNDO;
diff --git a/source/blender/editors/space_sequencer/SConscript b/source/blender/editors/space_sequencer/SConscript
index bc72786fc5f..060c7892bd1 100644
--- a/source/blender/editors/space_sequencer/SConscript
+++ b/source/blender/editors/space_sequencer/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 8155f9d645e..571779a7524 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -49,6 +49,8 @@
#include "DNA_mask_types.h"
#include "DNA_userdef_types.h"
+#include "BLF_translation.h"
+
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_library.h"
@@ -124,23 +126,50 @@ static void sequencer_generic_invoke_path__internal(bContext *C, wmOperator *op,
}
}
-static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, wmEvent *event, int flag)
+static int sequencer_generic_invoke_xy_guess_channel(bContext *C, int type)
{
- View2D *v2d = UI_view2d_fromcontext(C);
-
- float mval_v2d[2];
+ Sequence *tgt = NULL;
+ Sequence *seq;
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, TRUE);
+ int cfra = (int) CFRA;
+ int proximity = INT_MAX;
+
+ if (!ed || !ed->seqbasep) {
+ return 1;
+ }
+
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if ((type == -1 || seq->type == type) &&
+ (seq->enddisp < cfra) &&
+ (cfra - seq->enddisp < proximity))
+ {
+ tgt = seq;
+ proximity = cfra - seq->enddisp;
+ }
+ }
- UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mval_v2d[0], &mval_v2d[1]);
+ if (tgt) {
+ return tgt->machine;
+ }
+ return 1;
+}
+static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, int flag, int type)
+{
+ Scene *scene = CTX_data_scene(C);
+
+ int cfra = (int) CFRA;
+
/* effect strips don't need a channel initialized from the mouse */
if (!(flag & SEQPROP_NOCHAN)) {
- RNA_int_set(op->ptr, "channel", (int)mval_v2d[1] + 0.5f);
+ RNA_int_set(op->ptr, "channel", sequencer_generic_invoke_xy_guess_channel(C, type));
}
- RNA_int_set(op->ptr, "frame_start", (int)mval_v2d[0]);
+ RNA_int_set(op->ptr, "frame_start", cfra);
if ((flag & SEQPROP_ENDFRAME) && RNA_struct_property_is_set(op->ptr, "frame_end") == 0)
- RNA_int_set(op->ptr, "frame_end", (int)mval_v2d[0] + 25); // XXX arbitary but ok for now.
+ RNA_int_set(op->ptr, "frame_end", cfra + 25); // XXX arbitary but ok for now.
if (!(flag & SEQPROP_NOPATHS)) {
sequencer_generic_invoke_path__internal(C, op, "filepath");
@@ -265,7 +294,7 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
}
-static int sequencer_add_scene_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int sequencer_add_scene_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (!ED_operator_sequencer_active(C)) {
BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
@@ -275,7 +304,7 @@ static int sequencer_add_scene_strip_invoke(bContext *C, wmOperator *op, wmEvent
if (!RNA_struct_property_is_set(op->ptr, "scene"))
return WM_enum_search_invoke(C, op, event);
- sequencer_generic_invoke_xy__internal(C, op, event, 0);
+ sequencer_generic_invoke_xy__internal(C, op, 0, SEQ_TYPE_SCENE);
return sequencer_add_scene_strip_exec(C, op);
// needs a menu
// return WM_menu_invoke(C, op, event);
@@ -363,7 +392,7 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int sequencer_add_movieclip_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int sequencer_add_movieclip_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (!ED_operator_sequencer_active(C)) {
BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
@@ -373,7 +402,7 @@ static int sequencer_add_movieclip_strip_invoke(bContext *C, wmOperator *op, wmE
if (!RNA_struct_property_is_set(op->ptr, "clip"))
return WM_enum_search_invoke(C, op, event);
- sequencer_generic_invoke_xy__internal(C, op, event, 0);
+ sequencer_generic_invoke_xy__internal(C, op, 0, SEQ_TYPE_MOVIECLIP);
return sequencer_add_movieclip_strip_exec(C, op);
// needs a menu
// return WM_menu_invoke(C, op, event);
@@ -400,6 +429,7 @@ void SEQUENCER_OT_movieclip_strip_add(struct wmOperatorType *ot)
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
prop = RNA_def_enum(ot->srna, "clip", DummyRNA_NULL_items, 0, "Clip", "");
RNA_def_enum_funcs(prop, RNA_movieclip_itemf);
+ RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_MOVIECLIP);
ot->prop = prop;
}
@@ -459,7 +489,7 @@ static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int sequencer_add_mask_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int sequencer_add_mask_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (!ED_operator_sequencer_active(C)) {
BKE_report(op->reports, RPT_ERROR, "Sequencer area not active");
@@ -469,7 +499,7 @@ static int sequencer_add_mask_strip_invoke(bContext *C, wmOperator *op, wmEvent
if (!RNA_struct_property_is_set(op->ptr, "mask"))
return WM_enum_search_invoke(C, op, event);
- sequencer_generic_invoke_xy__internal(C, op, event, 0);
+ sequencer_generic_invoke_xy__internal(C, op, 0, SEQ_TYPE_MASK);
return sequencer_add_mask_strip_exec(C, op);
// needs a menu
// return WM_menu_invoke(C, op, event);
@@ -572,7 +602,7 @@ static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
}
-static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (!ED_operator_sequencer_active(C)) {
@@ -584,11 +614,11 @@ static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, wmEvent
if ((RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) ||
RNA_struct_property_is_set(op->ptr, "filepath"))
{
- sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_NOPATHS);
+ sequencer_generic_invoke_xy__internal(C, op, SEQPROP_NOPATHS, SEQ_TYPE_MOVIE);
return sequencer_add_movie_strip_exec(C, op);
}
- sequencer_generic_invoke_xy__internal(C, op, event, 0);
+ sequencer_generic_invoke_xy__internal(C, op, 0, SEQ_TYPE_MOVIE);
WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
@@ -627,7 +657,7 @@ static int sequencer_add_sound_strip_exec(bContext *C, wmOperator *op)
return sequencer_add_generic_strip_exec(C, op, BKE_sequencer_add_sound_strip);
}
-static int sequencer_add_sound_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int sequencer_add_sound_strip_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (!ED_operator_sequencer_active(C)) {
@@ -639,11 +669,11 @@ static int sequencer_add_sound_strip_invoke(bContext *C, wmOperator *op, wmEvent
if ((RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) ||
RNA_struct_property_is_set(op->ptr, "filepath"))
{
- sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_NOPATHS);
+ sequencer_generic_invoke_xy__internal(C, op, SEQPROP_NOPATHS, SEQ_TYPE_SOUND_RAM);
return sequencer_add_sound_strip_exec(C, op);
}
- sequencer_generic_invoke_xy__internal(C, op, event, 0);
+ sequencer_generic_invoke_xy__internal(C, op, 0, SEQ_TYPE_SOUND_RAM);
WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
@@ -739,7 +769,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (!ED_operator_sequencer_active(C)) {
@@ -750,11 +780,11 @@ static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, wmEvent
/* 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, event, SEQPROP_ENDFRAME | SEQPROP_NOPATHS);
+ sequencer_generic_invoke_xy__internal(C, op, SEQPROP_ENDFRAME | SEQPROP_NOPATHS, SEQ_TYPE_IMAGE);
return sequencer_add_image_strip_exec(C, op);
}
- sequencer_generic_invoke_xy__internal(C, op, event, SEQPROP_ENDFRAME);
+ sequencer_generic_invoke_xy__internal(C, op, SEQPROP_ENDFRAME, SEQ_TYPE_IMAGE);
WM_event_add_fileselect(C, op);
return OPERATOR_RUNNING_MODAL;
@@ -859,9 +889,9 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
* the other strips. */
if (!RNA_struct_property_is_set(op->ptr, "channel")) {
if (seq->seq1) {
- int chan = MAX3(seq->seq1 ? seq->seq1->machine : 0,
- seq->seq2 ? seq->seq2->machine : 0,
- seq->seq3 ? seq->seq3->machine : 0);
+ int chan = max_iii(seq->seq1 ? seq->seq1->machine : 0,
+ seq->seq2 ? seq->seq2->machine : 0,
+ seq->seq3 ? seq->seq3->machine : 0);
if (chan < MAXSEQ)
seq->machine = chan;
}
@@ -871,7 +901,7 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
if (BKE_sequence_test_overlap(ed->seqbasep, seq)) BKE_sequence_base_shuffle(ed->seqbasep, seq, scene);
}
- BKE_sequencer_update_changed_seq_and_deps(scene, seq, 1, 1); /* runs calc_sequence */
+ BKE_sequencer_update_changed_seq_and_deps(scene, seq, 1, 1); /* runs BKE_sequence_calc */
/* not sure if this is needed with update_changed_seq_and_deps.
@@ -891,7 +921,7 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
/* add color */
-static int sequencer_add_effect_strip_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int sequencer_add_effect_strip_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
short is_type_set = RNA_struct_property_is_set(op->ptr, "type");
int type = -1;
@@ -914,7 +944,7 @@ static int sequencer_add_effect_strip_invoke(bContext *C, wmOperator *op, wmEven
}
}
- sequencer_generic_invoke_xy__internal(C, op, event, prop_flag);
+ sequencer_generic_invoke_xy__internal(C, op, prop_flag, type);
return sequencer_add_effect_strip_exec(C, op);
}
diff --git a/source/blender/editors/space_sequencer/sequencer_buttons.c b/source/blender/editors/space_sequencer/sequencer_buttons.c
index 7dbcabedccc..21128408a97 100644
--- a/source/blender/editors/space_sequencer/sequencer_buttons.c
+++ b/source/blender/editors/space_sequencer/sequencer_buttons.c
@@ -41,6 +41,7 @@
#include "ED_screen.h"
#include "ED_gpencil.h"
+#include "ED_sequencer.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -51,6 +52,14 @@
/* **************************** buttons ********************************* */
+static int sequencer_grease_pencil_panel_poll(const bContext *C, PanelType *UNUSED(pt))
+{
+ SpaceSeq *sseq = CTX_wm_space_seq(C);
+
+ /* don't show the gpencil if we are not showing the image */
+ return ED_space_sequencer_check_show_imbuf(sseq);
+}
+
void sequencer_buttons_register(ARegionType *art)
{
PanelType *pt;
@@ -58,7 +67,9 @@ void sequencer_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype sequencer panel gpencil");
strcpy(pt->idname, "SEQUENCER_PT_gpencil");
strcpy(pt->label, N_("Grease Pencil"));
+ pt->draw_header = gpencil_panel_standard_header;
pt->draw = gpencil_panel_standard;
+ pt->poll = sequencer_grease_pencil_panel_poll;
BLI_addtail(&art->paneltypes, pt);
}
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 1a84efa0b50..7ebe04f666b 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -62,6 +62,7 @@
#include "ED_gpencil.h"
#include "ED_markers.h"
#include "ED_mask.h"
+#include "ED_sequencer.h"
#include "ED_types.h"
#include "ED_space_api.h"
@@ -812,7 +813,9 @@ static void UNUSED_FUNCTION(set_special_seq_update) (int val)
if (val) {
// XXX special_seq_update = find_nearest_seq(&x);
}
- else special_seq_update = NULL;
+ else {
+ special_seq_update = NULL;
+ }
}
ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int cfra, int frame_ofs)
@@ -921,12 +924,20 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
GLuint last_texid;
unsigned char *display_buffer;
void *cache_handle = NULL;
+ const int is_imbuf = ED_space_sequencer_check_show_imbuf(sseq);
- if (G.is_rendering == 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
* needed to make so sequencer's rendering doesn't conflict with compositor
*/
WM_jobs_kill_type(CTX_wm_manager(C), WM_JOB_TYPE_COMPOSITE);
+
+ if ((scene->r.seq_flag & R_SEQ_GL_PREV) == 0) {
+ /* in case of final rendering used for preview, kill all previews,
+ * otherwise threading conflict will happen in rendering module
+ */
+ WM_jobs_kill_type(CTX_wm_manager(C), WM_JOB_TYPE_RENDER_PREVIEW);
+ }
}
render_size = sseq->render_size;
@@ -1049,6 +1060,12 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
+
+ if (sseq->flag & SEQ_USE_ALPHA) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
glBegin(GL_QUADS);
if (draw_overlay) {
@@ -1080,6 +1097,8 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
glEnd();
glBindTexture(GL_TEXTURE_2D, last_texid);
glDisable(GL_TEXTURE_2D);
+ if (sseq->flag & SEQ_USE_ALPHA)
+ glDisable(GL_BLEND);
glDeleteTextures(1, &texid);
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
@@ -1125,8 +1144,12 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
setlinestyle(0);
}
- /* draw grease-pencil (image aligned) */
- draw_gpencil_2dimage(C);
+ if (sseq->flag & SEQ_SHOW_GPENCIL) {
+ if (is_imbuf) {
+ /* draw grease-pencil (image aligned) */
+ draw_gpencil_2dimage(C);
+ }
+ }
if (!scope)
IMB_freeImBuf(ibuf);
@@ -1134,9 +1157,12 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
/* ortho at pixel level */
UI_view2d_view_restore(C);
- /* draw grease-pencil (screen aligned) */
- draw_gpencil_view2d(C, 0);
-
+ if (sseq->flag & SEQ_SHOW_GPENCIL) {
+ if (is_imbuf) {
+ /* draw grease-pencil (screen aligned) */
+ draw_gpencil_view2d(C, 0);
+ }
+ }
/* NOTE: sequencer mask editing isnt finished, the draw code is working but editing not,
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index e7f77db3b9e..f0ed8d4107d 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -496,6 +496,13 @@ int ED_space_sequencer_maskedit_poll(bContext *C)
return FALSE;
}
+/* are we displaying the seq output (not channels or histogram)*/
+int ED_space_sequencer_check_show_imbuf(SpaceSeq *sseq)
+{
+ return (ELEM(sseq->view, SEQ_VIEW_PREVIEW, 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);
@@ -513,7 +520,7 @@ int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequen
return 0;
}
if ((seq != activeseq) && (seq != seq2)) {
- if (seq2 == NULL) seq2 = seq;
+ if (seq2 == NULL) seq2 = seq;
else if (seq1 == NULL) seq1 = seq;
else if (seq3 == NULL) seq3 = seq;
else {
@@ -810,18 +817,23 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
/* like duplicate, but only duplicate and cut overlapping strips,
- * strips to the left of the cutframe are ignored and strips to the right are moved into the new list */
-static int cut_seq_list(Scene *scene, ListBase *old, ListBase *new, int cutframe,
+ * strips to the left of the cutframe are ignored and strips to the right
+ * are moved to the end of slist
+ * we have to work on the same slist (not using a seperate list), since
+ * otherwise dupli_seq can't check for duplicate names properly and
+ * may generate strips with the same name (which will mess up animdata)
+ */
+
+static int cut_seq_list(Scene *scene, ListBase *slist, int cutframe,
Sequence * (*cut_seq)(Scene *, Sequence *, int))
{
- int did_something = FALSE;
Sequence *seq, *seq_next_iter;
+ Sequence *seq_first_new = NULL;
- seq = old->first;
-
- while (seq) {
+ seq = slist->first;
+
+ while (seq && seq != seq_first_new) {
seq_next_iter = seq->next; /* we need this because we may remove seq */
-
seq->tmp = NULL;
if (seq->flag & SELECT) {
if (cutframe > seq->startdisp &&
@@ -829,22 +841,29 @@ static int cut_seq_list(Scene *scene, ListBase *old, ListBase *new, int cutframe
{
Sequence *seqn = cut_seq(scene, seq, cutframe);
if (seqn) {
- BLI_addtail(new, seqn);
+ BLI_addtail(slist, seqn);
+ if (seq_first_new == NULL) {
+ seq_first_new = seqn;
+ }
}
- did_something = TRUE;
}
else if (seq->enddisp <= cutframe) {
/* do nothing */
}
else if (seq->startdisp >= cutframe) {
- /* move into new list */
- BLI_remlink(old, seq);
- BLI_addtail(new, seq);
+ /* move to tail */
+ BLI_remlink(slist, seq);
+ BLI_addtail(slist, seq);
+
+ if (seq_first_new == NULL) {
+ seq_first_new = seq;
+ }
}
}
seq = seq_next_iter;
}
- return did_something;
+
+ return (seq_first_new != NULL);
}
static int insert_gap(Scene *scene, int gap, int cfra)
@@ -870,7 +889,7 @@ static int insert_gap(Scene *scene, int gap, int cfra)
return done;
}
-static void UNUSED_FUNCTION(touch_seq_files) (Scene * scene)
+static void UNUSED_FUNCTION(touch_seq_files) (Scene *scene)
{
Sequence *seq;
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
@@ -918,7 +937,7 @@ static void set_filter_seq(Scene *scene)
if (seq->type == SEQ_TYPE_MOVIE) {
seq->flag |= SEQ_FILTERY;
reload_sequence_new_file(scene, seq, FALSE);
- calc_sequence(scene, seq);
+ BKE_sequence_calc(scene, seq);
}
}
@@ -927,7 +946,7 @@ static void set_filter_seq(Scene *scene)
}
#endif
-static void UNUSED_FUNCTION(seq_remap_paths) (Scene * scene)
+static void UNUSED_FUNCTION(seq_remap_paths) (Scene *scene)
{
Sequence *seq, *last_seq = BKE_sequencer_active_get(scene);
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
@@ -969,7 +988,7 @@ static void UNUSED_FUNCTION(seq_remap_paths) (Scene * scene)
}
-static void UNUSED_FUNCTION(no_gaps) (Scene * scene)
+static void UNUSED_FUNCTION(no_gaps) (Scene *scene)
{
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
int cfra, first = 0, done;
@@ -1102,7 +1121,7 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int sequencer_snap_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int sequencer_snap_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Scene *scene = CTX_data_scene(C);
@@ -1117,7 +1136,7 @@ static int sequencer_snap_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(ev
void SEQUENCER_OT_snap(struct wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Snap strips";
+ ot->name = "Snap Strips";
ot->idname = "SEQUENCER_OT_snap";
ot->description = "Frame where selected strips will be snapped";
@@ -1481,25 +1500,21 @@ static int sequencer_cut_exec(bContext *C, wmOperator *op)
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
int cut_side, cut_hard, cut_frame;
- ListBase newlist;
int changed;
cut_frame = RNA_int_get(op->ptr, "frame");
cut_hard = RNA_enum_get(op->ptr, "type");
cut_side = RNA_enum_get(op->ptr, "side");
- newlist.first = newlist.last = NULL;
-
if (cut_hard == SEQ_CUT_HARD) {
- changed = cut_seq_list(scene, ed->seqbasep, &newlist, cut_frame, cut_seq_hard);
+ changed = cut_seq_list(scene, ed->seqbasep, cut_frame, cut_seq_hard);
}
else {
- changed = cut_seq_list(scene, ed->seqbasep, &newlist, cut_frame, cut_seq_soft);
+ changed = cut_seq_list(scene, ed->seqbasep, cut_frame, cut_seq_soft);
}
- if (newlist.first) { /* got new strips ? */
+ if (changed) { /* got new strips ? */
Sequence *seq;
- BLI_movelisttolist(ed->seqbasep, &newlist);
if (cut_side != SEQ_SIDE_BOTH) {
SEQP_BEGIN (ed, seq)
@@ -1531,7 +1546,7 @@ static int sequencer_cut_exec(bContext *C, wmOperator *op)
}
-static int sequencer_cut_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int sequencer_cut_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
View2D *v2d = UI_view2d_fromcontext(C);
@@ -1680,7 +1695,7 @@ static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-static int sequencer_delete_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int sequencer_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
@@ -1899,6 +1914,9 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
for (seq = ed->seqbasep->first; seq; seq = seq->next)
BKE_sequence_calc(scene, seq);
+ if (BKE_sequence_test_overlap(ed->seqbasep, ms->parseq))
+ BKE_sequence_base_shuffle(ed->seqbasep, ms->parseq, scene);
+
BKE_sequencer_active_set(scene, ms->parseq);
ms->parseq->flag |= SELECT;
@@ -2453,9 +2471,15 @@ void SEQUENCER_OT_strip_jump(wmOperatorType *ot)
static void swap_sequence(Scene *scene, Sequence *seqa, Sequence *seqb)
{
int gap = seqb->startdisp - seqa->enddisp;
- seqb->start = (seqb->start - seqb->startdisp) + seqa->startdisp;
+ int seq_a_start;
+ int seq_b_start;
+
+ seq_b_start = (seqb->start - seqb->startdisp) + seqa->startdisp;
+ BKE_sequence_translate(scene, seqb, seq_b_start - seqb->start);
BKE_sequence_calc(scene, seqb);
- seqa->start = (seqa->start - seqa->startdisp) + seqb->enddisp + gap;
+
+ seq_a_start = (seqa->start - seqa->startdisp) + seqb->enddisp + gap;
+ BKE_sequence_translate(scene, seqa, seq_a_start - seqa->start);
BKE_sequence_calc(scene, seqa);
}
@@ -3081,7 +3105,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int sequencer_change_path_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int sequencer_change_path_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Scene *scene = CTX_data_scene(C);
Sequence *seq = BKE_sequencer_active_get(scene);
diff --git a/source/blender/editors/space_sequencer/sequencer_modifier.c b/source/blender/editors/space_sequencer/sequencer_modifier.c
index a4a485b34c6..51df21e509a 100644
--- a/source/blender/editors/space_sequencer/sequencer_modifier.c
+++ b/source/blender/editors/space_sequencer/sequencer_modifier.c
@@ -180,13 +180,13 @@ static int strip_modifier_move_exec(bContext *C, wmOperator *op)
if (direction == SEQ_MODIFIER_MOVE_UP) {
if (smd->prev) {
BLI_remlink(&seq->modifiers, smd);
- BLI_insertlink(&seq->modifiers, smd->prev->prev, smd);
+ BLI_insertlinkbefore(&seq->modifiers, smd->prev, smd);
}
}
else if (direction == SEQ_MODIFIER_MOVE_DOWN) {
if (smd->next) {
BLI_remlink(&seq->modifiers, smd);
- BLI_insertlink(&seq->modifiers, smd->next, smd);
+ BLI_insertlinkafter(&seq->modifiers, smd->next, smd);
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index 192f45ac918..254d15341cd 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -162,7 +162,7 @@ void select_surround_from_last(Scene *scene)
}
#endif
-void ED_sequencer_select_sequence_single(Scene * scene, Sequence * seq, int deselect_all)
+void ED_sequencer_select_sequence_single(Scene *scene, Sequence *seq, bool deselect_all)
{
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
@@ -315,15 +315,15 @@ void SEQUENCER_OT_select_inverse(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int sequencer_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
View2D *v2d = UI_view2d_fromcontext(C);
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
- short extend = RNA_boolean_get(op->ptr, "extend");
- short linked_handle = RNA_boolean_get(op->ptr, "linked_handle");
- short left_right = RNA_boolean_get(op->ptr, "left_right");
- short linked_time = RNA_boolean_get(op->ptr, "linked_time");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool linked_handle = RNA_boolean_get(op->ptr, "linked_handle");
+ const bool linked_time = RNA_boolean_get(op->ptr, "linked_time");
+ bool left_right = RNA_boolean_get(op->ptr, "left_right");
Sequence *seq, *neighbor, *act_orig;
int hand, sel_side;
@@ -552,8 +552,6 @@ void SEQUENCER_OT_select(wmOperatorType *ot)
}
-
-
/* run recursively to select linked */
static int select_more_less_seq__internal(Scene *scene, int sel, int linked)
{
@@ -670,12 +668,12 @@ void SEQUENCER_OT_select_less(wmOperatorType *ot)
/* select pick linked operator (uses the mouse) */
-static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
View2D *v2d = UI_view2d_fromcontext(C);
- short extend = RNA_boolean_get(op->ptr, "extend");
+ bool extend = RNA_boolean_get(op->ptr, "extend");
Sequence *mouse_seq;
int selected, hand;
@@ -704,7 +702,7 @@ static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEv
void SEQUENCER_OT_select_linked_pick(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Select pick linked";
+ ot->name = "Select Pick Linked";
ot->idname = "SEQUENCER_OT_select_linked_pick";
ot->description = "Select a chain of linked strips nearest to the mouse pointer";
@@ -739,7 +737,7 @@ static int sequencer_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
void SEQUENCER_OT_select_linked(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Select linked";
+ ot->name = "Select Linked";
ot->idname = "SEQUENCER_OT_select_linked";
ot->description = "Select all strips adjacent to the current selection";
diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c
index 92b17393114..68428cd890f 100644
--- a/source/blender/editors/space_sequencer/sequencer_view.c
+++ b/source/blender/editors/space_sequencer/sequencer_view.c
@@ -31,6 +31,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "DNA_scene_types.h"
@@ -66,6 +67,7 @@ typedef struct ImageSampleInfo {
unsigned char col[4];
float colf[4];
+ float linearcol[4];
unsigned char *colp;
float *colfp;
@@ -81,11 +83,12 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
if (info->draw) {
ED_image_draw_info(scene, ar, info->color_manage, FALSE, info->channels,
- info->x, info->y, info->colp, info->colfp, NULL, NULL);
+ info->x, info->y, info->colp, info->colfp,
+ info->linearcol, NULL, NULL);
}
}
-static void sample_apply(bContext *C, wmOperator *op, wmEvent *event)
+static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
@@ -134,7 +137,10 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event)
info->colf[3] = (float)cp[3] / 255.0f;
info->colfp = info->colf;
- info->color_manage = FALSE;
+ copy_v4_v4(info->linearcol, info->colf);
+ IMB_colormanagement_colorspace_to_scene_linear_v4(info->linearcol, false, ibuf->rect_colorspace);
+
+ info->color_manage = TRUE;
}
if (ibuf->rect_float) {
fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
@@ -168,7 +174,7 @@ static void sample_exit(bContext *C, wmOperator *op)
MEM_freeN(info);
}
-static int sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int sample_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceSeq *sseq = CTX_wm_space_seq(C);
@@ -189,7 +195,7 @@ static int sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static int sample_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int sample_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
switch (event->type) {
case LEFTMOUSE:
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index e8d47016608..ffe89407715 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -120,6 +120,8 @@ static SpaceLink *sequencer_new(const bContext *C)
sseq->chanshown = 0;
sseq->view = SEQ_VIEW_SEQUENCE;
sseq->mainb = SEQ_DRAW_IMG_IMBUF;
+ sseq->flag = SEQ_SHOW_GPENCIL | SEQ_USE_ALPHA;
+
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for sequencer");
@@ -371,7 +373,7 @@ static void sequencer_main_area_draw(const bContext *C, ARegion *ar)
/* ************* dropboxes ************* */
-static int image_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
+static int image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
@@ -385,7 +387,7 @@ static int image_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
return 0;
}
-static int movie_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
+static int movie_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
@@ -398,7 +400,7 @@ static int movie_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
return 0;
}
-static int sound_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
+static int sound_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
diff --git a/source/blender/editors/space_text/CMakeLists.txt b/source/blender/editors/space_text/CMakeLists.txt
index 9cc407f0604..1a6b8eaa753 100644
--- a/source/blender/editors/space_text/CMakeLists.txt
+++ b/source/blender/editors/space_text/CMakeLists.txt
@@ -36,11 +36,16 @@ set(INC_SYS
set(SRC
space_text.c
+ text_autocomplete.c
text_draw.c
+ text_format.c
+ text_format_lua.c
+ text_format_osl.c
+ text_format_py.c
text_header.c
text_ops.c
- text_python.c
+ text_format.h
text_intern.h
)
diff --git a/source/blender/editors/space_text/SConscript b/source/blender/editors/space_text/SConscript
index 373564520c8..4b6d9fbd693 100644
--- a/source/blender/editors/space_text/SConscript
+++ b/source/blender/editors/space_text/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index d74e32620af..58e45bc766f 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -30,17 +30,12 @@
#include <string.h>
-#include <stdio.h>
#include "DNA_text_types.h"
-#include "DNA_object_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLI_rand.h"
-#include "BLI_utildefines.h"
#include "BKE_context.h"
#include "BKE_screen.h"
@@ -61,7 +56,8 @@
#include "RNA_access.h"
-#include "text_intern.h" // own include
+#include "text_format.h"
+#include "text_intern.h" /* own include */
/* ******************** default callbacks for text space ***************** */
@@ -227,6 +223,8 @@ static void text_operatortypes(void)
WM_operatortype_append(TEXT_OT_to_3d_object);
WM_operatortype_append(TEXT_OT_resolve_conflict);
+
+ WM_operatortype_append(TEXT_OT_autocomplete);
}
static void text_keymap(struct wmKeyConfig *keyconf)
@@ -234,6 +232,12 @@ static void text_keymap(struct wmKeyConfig *keyconf)
wmKeyMap *keymap;
wmKeyMapItem *kmi;
+ keymap = WM_keymap_find(keyconf, "Text Generic", SPACE_TEXT, 0);
+ WM_keymap_add_item(keymap, "TEXT_OT_properties", FKEY, KM_PRESS, KM_CTRL, 0);
+#ifdef __APPLE__
+ WM_keymap_add_item(keymap, "TEXT_OT_properties", FKEY, KM_PRESS, KM_OSKEY, 0);
+#endif
+
keymap = WM_keymap_find(keyconf, "Text", SPACE_TEXT, 0);
#ifdef __APPLE__
@@ -258,7 +262,6 @@ static void text_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "TEXT_OT_cut", XKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_item(keymap, "TEXT_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_item(keymap, "TEXT_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0);
- WM_keymap_add_item(keymap, "TEXT_OT_properties", FKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_item(keymap, "TEXT_OT_find_set_selected", EKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_item(keymap, "TEXT_OT_find", GKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_item(keymap, "TEXT_OT_select_all", AKEY, KM_PRESS, KM_OSKEY, 0);
@@ -280,7 +283,7 @@ static void text_keymap(struct wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_cycle_int", PADMINUS, KM_PRESS, KM_CTRL, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.font_size");
RNA_boolean_set(kmi->ptr, "reverse", TRUE);
-
+
WM_keymap_add_item(keymap, "TEXT_OT_new", NKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "TEXT_OT_open", OKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "TEXT_OT_reload", RKEY, KM_PRESS, KM_ALT, 0);
@@ -307,7 +310,6 @@ static void text_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "TEXT_OT_jump", JKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "TEXT_OT_find", GKEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_add_item(keymap, "TEXT_OT_properties", FKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "TEXT_OT_replace", HKEY, KM_PRESS, KM_CTRL, 0);
kmi = WM_keymap_add_item(keymap, "TEXT_OT_to_3d_object", MKEY, KM_PRESS, KM_ALT, 0);
@@ -379,6 +381,8 @@ static void text_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "TEXT_OT_line_break", PADENTER, KM_PRESS, 0, 0);
WM_keymap_add_menu(keymap, "TEXT_MT_toolbox", RIGHTMOUSE, KM_PRESS, KM_ANY, 0);
+
+ WM_keymap_add_item(keymap, "TEXT_OT_autocomplete", SPACEKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "TEXT_OT_line_number", KM_TEXTINPUT, KM_ANY, KM_ANY, 0);
WM_keymap_add_item(keymap, "TEXT_OT_insert", KM_TEXTINPUT, KM_ANY, KM_ANY, 0); // last!
@@ -413,6 +417,8 @@ static void text_main_area_init(wmWindowManager *wm, ARegion *ar)
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
/* own keymap */
+ keymap = WM_keymap_find(wm->defaultconf, "Text Generic", SPACE_TEXT, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
keymap = WM_keymap_find(wm->defaultconf, "Text", SPACE_TEXT, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
@@ -452,7 +458,7 @@ static void text_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar))
/* ************* dropboxes ************* */
-static int text_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
+static int text_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_PATH)
if (ELEM(drag->icon, ICON_FILE_SCRIPT, ICON_FILE_BLANK)) /* rule might not work? */
@@ -496,7 +502,15 @@ static void text_header_area_draw(const bContext *C, ARegion *ar)
/* add handlers, stuff you only do once or on area/region changes */
static void text_properties_area_init(wmWindowManager *wm, ARegion *ar)
{
+ wmKeyMap *keymap;
+
+ ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
ED_region_panels_init(wm, ar);
+
+ /* own keymaps */
+ keymap = WM_keymap_find(wm->defaultconf, "Text Generic", SPACE_TEXT, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+
}
static void text_properties_area_draw(const bContext *C, ARegion *ar)
@@ -556,5 +570,10 @@ void ED_spacetype_text(void)
BLI_addhead(&st->regiontypes, art);
BKE_spacetype_register(st);
+
+ /* register formatters */
+ ED_text_format_register_py();
+ ED_text_format_register_osl();
+ ED_text_format_register_lua();
}
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
new file mode 100644
index 00000000000..838ffb948b1
--- /dev/null
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -0,0 +1,557 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 blender/editors/space_text/text_autocomplete.c
+ * \ingroup sptext
+ */
+
+#include <ctype.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_text_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+
+#include "BKE_context.h"
+#include "BKE_text.h"
+#include "BKE_screen.h"
+#include "BKE_suggestions.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "UI_interface.h"
+
+#include "text_format.h"
+#include "text_intern.h" /* own include */
+
+
+/* -------------------------------------------------------------------- */
+/* Public API */
+
+int text_do_suggest_select(SpaceText *st, ARegion *ar)
+{
+ SuggItem *item, *first, *last /* , *sel */ /* UNUSED */;
+ TextLine *tmp;
+ int l, x, y, w, h, i;
+ int tgti, *top;
+ int mval[2] = {0, 0};
+
+ if (!st || !st->text) return 0;
+ if (!texttool_text_is_active(st->text)) return 0;
+
+ first = texttool_suggest_first();
+ last = texttool_suggest_last();
+ /* sel = texttool_suggest_selected(); */ /* UNUSED */
+ top = texttool_suggest_top();
+
+ if (!last || !first)
+ return 0;
+
+ /* Count the visible lines to the cursor */
+ for (tmp = st->text->curl, l = -st->top; tmp; tmp = tmp->prev, l++) ;
+ if (l < 0) return 0;
+
+ text_update_character_width(st);
+
+ if (st->showlinenrs) {
+ x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET + TEXTXLOC - 4;
+ }
+ else {
+ x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET - 4;
+ }
+ y = ar->winy - st->lheight_dpi * l - 2;
+
+ w = SUGG_LIST_WIDTH * st->cwidth + U.widget_unit;
+ h = SUGG_LIST_SIZE * st->lheight_dpi + 0.4f * U.widget_unit;
+
+ // XXX getmouseco_areawin(mval);
+
+ if (mval[0] < x || x + w < mval[0] || mval[1] < y - h || y < mval[1])
+ return 0;
+
+ /* Work out which of the items is at the top of the visible list */
+ for (i = 0, item = first; i < *top && item->next; i++, item = item->next) ;
+
+ /* Work out the target item index in the visible list */
+ tgti = (y - mval[1] - 4) / st->lheight_dpi;
+ if (tgti < 0 || tgti > SUGG_LIST_SIZE)
+ return 1;
+
+ for (i = tgti; i > 0 && item->next; i--, item = item->next) ;
+ if (item)
+ texttool_suggest_select(item);
+ return 1;
+}
+
+void text_pop_suggest_list(void)
+{
+ SuggItem *item, *sel;
+ int *top, i;
+
+ item = texttool_suggest_first();
+ sel = texttool_suggest_selected();
+ top = texttool_suggest_top();
+
+ i = 0;
+ while (item && item != sel) {
+ item = item->next;
+ i++;
+ }
+ if (i > *top + SUGG_LIST_SIZE - 1)
+ *top = i - SUGG_LIST_SIZE + 1;
+ else if (i < *top)
+ *top = i;
+}
+
+/* -------------------------------------------------------------------- */
+/* Private API */
+
+static void text_autocomplete_free(bContext *C, wmOperator *op);
+
+static GHash *text_autocomplete_build(Text *text)
+{
+ GHash *gh;
+ int seek_len = 0;
+ const char *seek;
+ texttool_text_clear();
+
+ texttool_text_set_active(text);
+
+ /* first get the word we're at */
+ {
+ const int i = text_find_identifier_start(text->curl->line, text->curc);
+ seek_len = text->curc - i;
+ seek = text->curl->line + i;
+
+ // BLI_strncpy(seek, seek_ptr, seek_len);
+ }
+
+ /* now walk over entire doc and suggest words */
+ {
+ TextLine *linep;
+
+ gh = BLI_ghash_str_new(__func__);
+
+ for (linep = text->lines.first; linep; linep = linep->next) {
+ size_t i_start = 0;
+ size_t i_end = 0;
+ size_t i_pos = 0;
+
+ while (i_start < linep->len) {
+ /* seek identifier beginning */
+ i_pos = i_start;
+ while ((i_start < linep->len) &&
+ (!text_check_identifier_nodigit_unicode(BLI_str_utf8_as_unicode_and_size_safe(&linep->line[i_start], &i_pos))))
+ {
+ i_start = i_pos;
+ }
+ i_pos = i_end = i_start;
+ while ((i_end < linep->len) &&
+ (text_check_identifier_unicode(BLI_str_utf8_as_unicode_and_size_safe(&linep->line[i_end], &i_pos))))
+ {
+ i_end = i_pos;
+ }
+
+ if ((i_start != i_end) &&
+ /* check we're at the beginning of a line or that the previous char is not an identifier
+ * this prevents digits from being added */
+ ((i_start < 1) || !text_check_identifier_unicode(BLI_str_utf8_as_unicode(&linep->line[i_start - 1]))))
+ {
+ char *str_sub = &linep->line[i_start];
+ const int choice_len = i_end - i_start;
+
+ if ((choice_len > seek_len) &&
+ (seek_len == 0 || strncmp(seek, str_sub, seek_len) == 0) &&
+ (seek != str_sub))
+ {
+ // printf("Adding: %s\n", s);
+ char str_sub_last = str_sub[choice_len];
+ str_sub[choice_len] = '\0';
+ if (!BLI_ghash_lookup(gh, str_sub)) {
+ char *str_dup = BLI_strdupn(str_sub, choice_len);
+ BLI_ghash_insert(gh, str_dup, str_dup); /* A 'set' would make more sense here */
+ }
+ str_sub[choice_len] = str_sub_last;
+ }
+ }
+ if (i_end != i_start) {
+ i_start = i_end;
+ }
+ else {
+ /* highly unlikely, but prevent eternal loop */
+ i_start++;
+ }
+ }
+ }
+
+ {
+ GHashIterator *iter = BLI_ghashIterator_new(gh);
+
+ /* get the formatter for highlighting */
+ TextFormatType *tft;
+ tft = ED_text_format_get(text);
+
+ for (; BLI_ghashIterator_notDone(iter); BLI_ghashIterator_step(iter)) {
+ const char *s = BLI_ghashIterator_getValue(iter);
+ texttool_suggest_add(s, tft->format_identifier(s));
+ }
+ BLI_ghashIterator_free(iter);
+
+ }
+ }
+
+ texttool_suggest_prefix(seek, seek_len);
+
+ return gh;
+}
+
+/* -- */
+
+static void get_suggest_prefix(Text *text, int offset)
+{
+ int i, len;
+ char *line;
+
+ if (!text) return;
+ if (!texttool_text_is_active(text)) return;
+
+ line = text->curl->line;
+ i = text_find_identifier_start(line, text->curc + offset);
+ len = text->curc - i + offset;
+ texttool_suggest_prefix(line + i, len);
+}
+
+static void confirm_suggestion(Text *text)
+{
+ SuggItem *sel;
+ int i, over = 0;
+ const char *line;
+
+ if (!text) return;
+ if (!texttool_text_is_active(text)) return;
+
+ sel = texttool_suggest_selected();
+ if (!sel) return;
+
+ line = text->curl->line;
+ i = text_find_identifier_start(line, text->curc /* - skipleft */);
+ over = text->curc - i;
+
+// for (i = 0; i < skipleft; i++)
+// txt_move_left(text, 0);
+ for (i = 0; i < over; i++)
+ txt_move_left(text, 1);
+
+ txt_insert_buf(text, sel->name);
+
+// for (i = 0; i < skipleft; i++)
+// txt_move_right(text, 0);
+
+ texttool_text_clear();
+}
+
+/* -- */
+
+
+static int text_autocomplete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ SpaceText *st = CTX_wm_space_text(C);
+ Text *text = CTX_data_edit_text(C);
+
+ st->doplugins = TRUE;
+ op->customdata = text_autocomplete_build(text);
+
+ if (texttool_suggest_first()) {
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ if (texttool_suggest_first() == texttool_suggest_last()) {
+ confirm_suggestion(st->text);
+ text_update_line_edited(st->text->curl);
+ text_autocomplete_free(C, op);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+ else {
+ text_autocomplete_free(C, op);
+ return OPERATOR_CANCELLED;
+ }
+}
+
+static int doc_scroll = 0;
+
+static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ SpaceText *st = CTX_wm_space_text(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+
+ int draw = 0, tools = 0, swallow = 0, scroll = 1;
+ Text *text = CTX_data_edit_text(C);
+ int retval = OPERATOR_RUNNING_MODAL;
+
+ (void)text;
+
+ if (st->doplugins && texttool_text_is_active(st->text)) {
+ if (texttool_suggest_first()) tools |= TOOL_SUGG_LIST;
+ if (texttool_docs_get()) tools |= TOOL_DOCUMENT;
+ }
+
+ switch (event->type) {
+ case LEFTMOUSE:
+ if (event->val == KM_PRESS) {
+ if (text_do_suggest_select(st, ar))
+ swallow = 1;
+ else {
+ if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
+ if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
+ retval = OPERATOR_FINISHED;
+ }
+ draw = 1;
+ }
+ break;
+ case MIDDLEMOUSE:
+ if (event->val == KM_PRESS) {
+ if (text_do_suggest_select(st, ar)) {
+ confirm_suggestion(st->text);
+ text_update_line_edited(st->text->curl);
+ swallow = 1;
+ }
+ else {
+ if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
+ if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
+ retval = OPERATOR_FINISHED;
+ }
+ draw = 1;
+ }
+ break;
+ case ESCKEY:
+ if (event->val == KM_PRESS) {
+ draw = swallow = 1;
+ if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
+ else if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
+ else draw = swallow = 0;
+ retval = OPERATOR_CANCELLED;
+ }
+ break;
+ case RETKEY:
+ if (event->val == KM_PRESS) {
+ if (tools & TOOL_SUGG_LIST) {
+ confirm_suggestion(st->text);
+ text_update_line_edited(st->text->curl);
+ swallow = 1;
+ draw = 1;
+ }
+ if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
+ retval = OPERATOR_FINISHED;
+ }
+ break;
+ case LEFTARROWKEY:
+ case BACKSPACEKEY:
+ if (event->val == KM_PRESS) {
+ if (tools & TOOL_SUGG_LIST) {
+ if (event->ctrl) {
+ texttool_suggest_clear();
+ retval = OPERATOR_CANCELLED;
+ }
+ else {
+ /* Work out which char we are about to delete/pass */
+ if (st->text->curl && st->text->curc > 0) {
+ char ch = st->text->curl->line[st->text->curc - 1];
+ if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
+ get_suggest_prefix(st->text, -1);
+ text_pop_suggest_list();
+ }
+ else {
+ texttool_suggest_clear();
+ retval = OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ texttool_suggest_clear();
+ retval = OPERATOR_CANCELLED;
+ }
+ }
+ }
+ if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
+ }
+ break;
+ case RIGHTARROWKEY:
+ if (event->val == KM_PRESS) {
+ if (tools & TOOL_SUGG_LIST) {
+ if (event->ctrl) {
+ texttool_suggest_clear();
+ retval = OPERATOR_CANCELLED;
+ }
+ else {
+ /* Work out which char we are about to pass */
+ if (st->text->curl && st->text->curc < st->text->curl->len) {
+ char ch = st->text->curl->line[st->text->curc + 1];
+ if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
+ get_suggest_prefix(st->text, 1);
+ text_pop_suggest_list();
+ }
+ else {
+ texttool_suggest_clear();
+ retval = OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ texttool_suggest_clear();
+ retval = OPERATOR_CANCELLED;
+ }
+ }
+ }
+ if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
+ }
+ break;
+ case PAGEDOWNKEY:
+ scroll = SUGG_LIST_SIZE - 1;
+ case WHEELDOWNMOUSE:
+ case DOWNARROWKEY:
+ if (event->val == KM_PRESS) {
+ if (tools & TOOL_DOCUMENT) {
+ doc_scroll++;
+ swallow = 1;
+ draw = 1;
+ }
+ else if (tools & TOOL_SUGG_LIST) {
+ SuggItem *sel = texttool_suggest_selected();
+ if (!sel) {
+ texttool_suggest_select(texttool_suggest_first());
+ }
+ else {
+ while (sel && sel != texttool_suggest_last() && sel->next && scroll--) {
+ texttool_suggest_select(sel->next);
+ sel = sel->next;
+ }
+ }
+ text_pop_suggest_list();
+ swallow = 1;
+ draw = 1;
+ }
+ }
+ break;
+ case PAGEUPKEY:
+ scroll = SUGG_LIST_SIZE - 1;
+ case WHEELUPMOUSE:
+ case UPARROWKEY:
+ if (event->val == KM_PRESS) {
+ if (tools & TOOL_DOCUMENT) {
+ if (doc_scroll > 0) doc_scroll--;
+ swallow = 1;
+ draw = 1;
+ }
+ else if (tools & TOOL_SUGG_LIST) {
+ SuggItem *sel = texttool_suggest_selected();
+ while (sel && sel != texttool_suggest_first() && sel->prev && scroll--) {
+ texttool_suggest_select(sel->prev);
+ sel = sel->prev;
+ }
+ text_pop_suggest_list();
+ swallow = 1;
+ draw = 1;
+ }
+ }
+ break;
+ case RIGHTSHIFTKEY:
+ case LEFTSHIFTKEY:
+ break;
+#if 0
+ default:
+ if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(), draw = 1;
+ if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
+#endif
+ }
+
+ if (draw) {
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+// if (swallow) {
+// retval = OPERATOR_RUNNING_MODAL;
+// }
+
+ if (texttool_suggest_first()) {
+ if (retval != OPERATOR_RUNNING_MODAL) {
+ text_autocomplete_free(C, op);
+ }
+ return retval;
+ }
+ else {
+ text_autocomplete_free(C, op);
+ return OPERATOR_FINISHED;
+ }
+}
+
+static void text_autocomplete_free(bContext *C, wmOperator *op)
+{
+ GHash *gh = op->customdata;
+ if (gh) {
+ BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
+ op->customdata = NULL;
+ }
+
+ /* other stuff */
+ {
+ SpaceText *st = CTX_wm_space_text(C);
+ st->doplugins = FALSE;
+ texttool_text_clear();
+ }
+}
+
+static int text_autocomplete_cancel(bContext *C, wmOperator *op)
+{
+ text_autocomplete_free(C, op);
+ return OPERATOR_CANCELLED;
+}
+
+void TEXT_OT_autocomplete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Text Auto Complete";
+ ot->description = "Show a list of used text in the open document";
+ ot->idname = "TEXT_OT_autocomplete";
+
+ /* api callbacks */
+ ot->invoke = text_autocomplete_invoke;
+ ot->cancel = text_autocomplete_cancel;
+ ot->modal = text_autocomplete_modal;
+ ot->poll = text_space_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_BLOCKING;
+}
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 46ab2d9e688..95fd7fce878 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -29,10 +29,6 @@
*/
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
#include "MEM_guardedalloc.h"
@@ -40,12 +36,10 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#include "BLI_utildefines.h"
#include "DNA_text_types.h"
#include "DNA_space_types.h"
#include "DNA_screen_types.h"
-#include "DNA_userdef_types.h"
#include "BKE_context.h"
#include "BKE_suggestions.h"
@@ -53,11 +47,12 @@
#include "BIF_gl.h"
-#include "ED_datafiles.h"
#include "UI_interface.h"
#include "UI_resources.h"
+#include "UI_view2d.h"
#include "text_intern.h"
+#include "text_format.h"
/******************** text font drawing ******************/
// XXX, fixme
@@ -65,388 +60,40 @@
static void text_font_begin(SpaceText *st)
{
- BLF_size(mono, st->lheight, 72);
+ BLF_size(mono, st->lheight_dpi, 72);
}
static void text_font_end(SpaceText *UNUSED(st))
{
}
-static int text_font_draw(SpaceText *UNUSED(st), int x, int y, const char *str)
+static int text_font_draw(SpaceText *st, int x, int y, const char *str)
{
+ int columns;
+
BLF_position(mono, x, y, 0);
- BLF_draw(mono, str, BLF_DRAW_STR_DUMMY_MAX);
+ columns = BLF_draw_mono(mono, str, BLF_DRAW_STR_DUMMY_MAX, st->cwidth);
- return BLF_width(mono, str);
+ return st->cwidth * columns;
}
static int text_font_draw_character(SpaceText *st, int x, int y, char c)
{
- char str[2];
- str[0] = c;
- str[1] = '\0';
-
BLF_position(mono, x, y, 0);
- BLF_draw(mono, str, 1);
+ BLF_draw(mono, &c, 1);
return st->cwidth;
}
static int text_font_draw_character_utf8(SpaceText *st, int x, int y, const char *c)
{
- char str[BLI_UTF8_MAX + 1];
- size_t len = BLI_str_utf8_size_safe(c);
- memcpy(str, c, len);
- str[len] = '\0';
+ int columns;
+ const size_t len = BLI_str_utf8_size_safe(c);
BLF_position(mono, x, y, 0);
- BLF_draw(mono, str, len);
+ columns = BLF_draw_mono(mono, c, len, st->cwidth);
- return st->cwidth;
-}
-
-/****************** flatten string **********************/
-
-static void flatten_string_append(FlattenString *fs, const char *c, int accum, int len)
-{
- int i;
-
- if (fs->pos + len > fs->len) {
- char *nbuf; int *naccum;
- fs->len *= 2;
-
- nbuf = MEM_callocN(sizeof(*fs->buf) * fs->len, "fs->buf");
- naccum = MEM_callocN(sizeof(*fs->accum) * fs->len, "fs->accum");
-
- memcpy(nbuf, fs->buf, fs->pos * sizeof(*fs->buf));
- memcpy(naccum, fs->accum, fs->pos * sizeof(*fs->accum));
-
- if (fs->buf != fs->fixedbuf) {
- MEM_freeN(fs->buf);
- MEM_freeN(fs->accum);
- }
-
- fs->buf = nbuf;
- fs->accum = naccum;
- }
-
- for (i = 0; i < len; i++) {
- fs->buf[fs->pos + i] = c[i];
- fs->accum[fs->pos + i] = accum;
- }
-
- fs->pos += len;
-}
-
-int flatten_string(SpaceText *st, FlattenString *fs, const char *in)
-{
- int r, i, total = 0;
-
- memset(fs, 0, sizeof(FlattenString));
- fs->buf = fs->fixedbuf;
- fs->accum = fs->fixedaccum;
- fs->len = sizeof(fs->fixedbuf);
-
- for (r = 0, i = 0; *in; r++) {
- if (*in == '\t') {
- i = st->tabnumber - (total % st->tabnumber);
- total += i;
-
- while (i--)
- flatten_string_append(fs, " ", r, 1);
-
- in++;
- }
- else {
- size_t len = BLI_str_utf8_size_safe(in);
- flatten_string_append(fs, in, r, len);
- in += len;
- total++;
- }
- }
-
- flatten_string_append(fs, "\0", r, 1);
-
- return total;
-}
-
-void flatten_string_free(FlattenString *fs)
-{
- if (fs->buf != fs->fixedbuf)
- MEM_freeN(fs->buf);
- if (fs->accum != fs->fixedaccum)
- MEM_freeN(fs->accum);
-}
-
-/* Checks the specified source string for a Python built-in function name. This
- * name must start at the beginning of the source string and must be followed by
- * a non-identifier (see text_check_identifier(char)) or null character.
- *
- * If a built-in function is found, the length of the matching name is returned.
- * Otherwise, -1 is returned.
- *
- * See:
- * http://docs.python.org/py3k/reference/lexical_analysis.html#keywords
- */
-
-static int find_builtinfunc(char *string)
-{
- int a, i;
- const char *builtinfuncs[] = {
- /* "False", "None", "True", */ /* see find_bool() */
- "and", "as", "assert", "break",
- "class", "continue", "def", "del", "elif", "else", "except",
- "finally", "for", "from", "global", "if", "import", "in",
- "is", "lambda", "nonlocal", "not", "or", "pass", "raise",
- "return", "try", "while", "with", "yield",
- };
-
- for (a = 0; a < sizeof(builtinfuncs) / sizeof(builtinfuncs[0]); a++) {
- i = 0;
- while (1) {
- /* If we hit the end of a keyword... (eg. "def") */
- if (builtinfuncs[a][i] == '\0') {
- /* If we still have identifier chars in the source (eg. "definate") */
- if (text_check_identifier(string[i]))
- i = -1; /* No match */
- break; /* Next keyword if no match, otherwise we're done */
-
- /* If chars mismatch, move on to next keyword */
- }
- else if (string[i] != builtinfuncs[a][i]) {
- i = -1;
- break; /* Break inner loop, start next keyword */
- }
- i++;
- }
- if (i > 0) break; /* If we have a match, we're done */
- }
- return i;
-}
-
-/* Checks the specified source string for a Python special name. This name must
- * start at the beginning of the source string and must be followed by a non-
- * identifier (see text_check_identifier(char)) or null character.
- *
- * If a special name is found, the length of the matching name is returned.
- * Otherwise, -1 is returned. */
-
-static int find_specialvar(char *string)
-{
- int i = 0;
- /* Check for "def" */
- if (string[0] == 'd' && string[1] == 'e' && string[2] == 'f')
- i = 3;
- /* Check for "class" */
- else if (string[0] == 'c' && string[1] == 'l' && string[2] == 'a' && string[3] == 's' && string[4] == 's')
- i = 5;
- /* If next source char is an identifier (eg. 'i' in "definate") no match */
- if (i == 0 || text_check_identifier(string[i]))
- return -1;
- return i;
-}
-
-static int find_decorator(char *string)
-{
- if (string[0] == '@') {
- int i = 1;
- while (text_check_identifier(string[i])) {
- i++;
- }
- return i;
- }
- return -1;
-}
-
-static int find_bool(char *string)
-{
- int i = 0;
- /* Check for "False" */
- if (string[0] == 'F' && string[1] == 'a' && string[2] == 'l' && string[3] == 's' && string[4] == 'e')
- i = 5;
- /* Check for "True" */
- else if (string[0] == 'T' && string[1] == 'r' && string[2] == 'u' && string[3] == 'e')
- i = 4;
- /* Check for "None" */
- else if (string[0] == 'N' && string[1] == 'o' && string[2] == 'n' && string[3] == 'e')
- i = 4;
- /* If next source char is an identifier (eg. 'i' in "definate") no match */
- if (i == 0 || text_check_identifier(string[i]))
- return -1;
- return i;
-}
-
-/* Ensures the format string for the given line is long enough, reallocating
- * as needed. Allocation is done here, alone, to ensure consistency. */
-static int text_check_format_len(TextLine *line, unsigned int len)
-{
- if (line->format) {
- if (strlen(line->format) < len) {
- MEM_freeN(line->format);
- line->format = MEM_mallocN(len + 2, "SyntaxFormat");
- if (!line->format) return 0;
- }
- }
- else {
- line->format = MEM_mallocN(len + 2, "SyntaxFormat");
- if (!line->format) return 0;
- }
-
- return 1;
-}
-
-/* Formats the specified line. If do_next is set, the process will move on to
- * the succeeding line if it is affected (eg. multiline strings). Format strings
- * may contain any of the following characters:
- * '_' Whitespace
- * '#' Comment text
- * '!' Punctuation and other symbols
- * 'n' Numerals
- * 'l' String letters
- * 'v' Special variables (class, def)
- * 'b' Built-in names (print, for, etc.)
- * 'q' Other text (identifiers, etc.)
- * It is terminated with a null-terminator '\0' followed by a continuation
- * flag indicating whether the line is part of a multi-line string. */
-
-static void txt_format_line(SpaceText *st, TextLine *line, int do_next)
-{
- FlattenString fs;
- char *str, *fmt, orig, cont, find, prev = ' ';
- int len, i;
-
- /* Get continuation from previous line */
- if (line->prev && line->prev->format != NULL) {
- fmt = line->prev->format;
- cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
- }
- else cont = 0;
-
- /* Get original continuation from this line */
- if (line->format != NULL) {
- fmt = line->format;
- orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
- }
- else orig = 0xFF;
-
- len = flatten_string(st, &fs, line->line);
- str = fs.buf;
- if (!text_check_format_len(line, len)) {
- flatten_string_free(&fs);
- return;
- }
- fmt = line->format;
-
- while (*str) {
- /* Handle escape sequences by skipping both \ and next char */
- if (*str == '\\') {
- *fmt = prev; fmt++; str++;
- if (*str == '\0') break;
- *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str);
- continue;
- }
- /* Handle continuations */
- else if (cont) {
- /* Triple strings ("""...""" or '''...''') */
- if (cont & TXT_TRISTR) {
- find = (cont & TXT_DBLQUOTSTR) ? '"' : '\'';
- if (*str == find && *(str + 1) == find && *(str + 2) == find) {
- *fmt = 'l'; fmt++; str++;
- *fmt = 'l'; fmt++; str++;
- cont = 0;
- }
- /* Handle other strings */
- }
- else {
- find = (cont & TXT_DBLQUOTSTR) ? '"' : '\'';
- if (*str == find) cont = 0;
- }
-
- *fmt = 'l';
- str += BLI_str_utf8_size_safe(str) - 1;
- }
- /* Not in a string... */
- else {
- /* Deal with comments first */
- if (prev == '#' || *str == '#') {
- *fmt = '#';
- str += BLI_str_utf8_size_safe(str) - 1;
- }
- else if (*str == '"' || *str == '\'') {
- /* Strings */
- find = *str;
- cont = (*str == '"') ? TXT_DBLQUOTSTR : TXT_SNGQUOTSTR;
- if (*(str + 1) == find && *(str + 2) == find) {
- *fmt = 'l'; fmt++; str++;
- *fmt = 'l'; fmt++; str++;
- cont |= TXT_TRISTR;
- }
- *fmt = 'l';
- }
- /* Whitespace (all ws. has been converted to spaces) */
- else if (*str == ' ')
- *fmt = '_';
- /* Numbers (digits not part of an identifier and periods followed by digits) */
- else if ((prev != 'q' && text_check_digit(*str)) || (*str == '.' && text_check_digit(*(str + 1))))
- *fmt = 'n';
- /* Booleans */
- else if (prev != 'q' && (i = find_bool(str)) != -1)
- if (i > 0) {
- while (i > 1) {
- *fmt = 'n'; fmt++; str++;
- i--;
- }
- *fmt = 'n';
- }
- else {
- str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = 'q';
- }
- /* Punctuation */
- else if (text_check_delim(*str))
- *fmt = '!';
- /* Identifiers and other text (no previous ws. or delims. so text continues) */
- else if (prev == 'q') {
- str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = 'q';
- }
- /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
- else {
- /* Special vars(v) or built-in keywords(b) */
- if ((i = find_specialvar(str)) != -1)
- prev = 'v';
- else if ((i = find_builtinfunc(str)) != -1)
- prev = 'b';
- else if ((i = find_decorator(str)) != -1)
- prev = 'v'; /* could have a new color for this */
- if (i > 0) {
- while (i > 1) {
- *fmt = prev; fmt++; str++;
- i--;
- }
- *fmt = prev;
- }
- else {
- str += BLI_str_utf8_size_safe(str) - 1;
- *fmt = 'q';
- }
- }
- }
- prev = *fmt;
- fmt++;
- str++;
- }
-
- /* Terminate and add continuation char */
- *fmt = '\0'; fmt++;
- *fmt = cont;
-
- /* If continuation has changed and we're allowed, process the next line */
- if (cont != orig && do_next && line->next) {
- txt_format_line(st, line->next, do_next);
- }
-
- flatten_string_free(&fs);
+ return st->cwidth * columns;
}
#if 0
@@ -466,27 +113,33 @@ static void txt_format_text(SpaceText *st)
static void format_draw_color(char formatchar)
{
switch (formatchar) {
- case '_': /* Whitespace */
+ case FMT_TYPE_WHITESPACE:
break;
- case '!': /* Symbols */
- UI_ThemeColorBlend(TH_TEXT, TH_BACK, 0.5f);
+ case FMT_TYPE_SYMBOL:
+ UI_ThemeColor(TH_SYNTAX_S);
break;
- case '#': /* Comments */
+ case FMT_TYPE_COMMENT:
UI_ThemeColor(TH_SYNTAX_C);
break;
- case 'n': /* Numerals */
+ case FMT_TYPE_NUMERAL:
UI_ThemeColor(TH_SYNTAX_N);
break;
- case 'l': /* Strings */
+ case FMT_TYPE_STRING:
UI_ThemeColor(TH_SYNTAX_L);
break;
- case 'v': /* Specials: class, def */
+ case FMT_TYPE_DIRECTIVE:
+ UI_ThemeColor(TH_SYNTAX_D);
+ break;
+ case FMT_TYPE_SPECIAL:
UI_ThemeColor(TH_SYNTAX_V);
break;
- case 'b': /* Keywords: for, print, etc. */
+ case FMT_TYPE_RESERVED:
+ UI_ThemeColor(TH_SYNTAX_R);
+ break;
+ case FMT_TYPE_KEYWORD:
UI_ThemeColor(TH_SYNTAX_B);
break;
- case 'q': /* Other text (identifiers) */
+ case FMT_TYPE_DEFAULT:
default:
UI_ThemeColor(TH_TEXT);
break;
@@ -568,7 +221,7 @@ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *
}
max = wrap_width(st, ar);
- cursin = txt_utf8_offset_to_index(linein->line, cursin);
+ cursin = txt_utf8_offset_to_column(linein->line, cursin);
while (linep) {
start = 0;
@@ -577,6 +230,7 @@ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *
*offc = 0;
for (i = 0, j = 0; linep->line[j]; j += BLI_str_utf8_size_safe(linep->line + j)) {
int chars;
+ int columns = BLI_str_utf8_char_width_safe(linep->line + j); /* = 1 for tab */
/* Mimic replacement of tabs */
ch = linep->line[j];
@@ -590,7 +244,9 @@ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *
}
while (chars--) {
- if (i - start >= max) {
+ if (i + columns - start > max) {
+ end = MIN2(end, i);
+
if (chop && linep == linein && i >= cursin) {
if (i == cursin) {
(*offl)++;
@@ -613,7 +269,7 @@ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *
if (linep == linein && i >= cursin)
return;
}
- i++;
+ i += columns;
}
}
if (linep == linein) break;
@@ -638,9 +294,10 @@ void wrap_offset_in_line(SpaceText *st, ARegion *ar, TextLine *linein, int cursi
end = max;
chop = 1;
*offc = 0;
- cursin = txt_utf8_offset_to_index(linein->line, cursin);
+ cursin = txt_utf8_offset_to_column(linein->line, cursin);
for (i = 0, j = 0; linein->line[j]; j += BLI_str_utf8_size_safe(linein->line + j)) {
+ int columns = BLI_str_utf8_char_width_safe(linein->line + j); /* = 1 for tab */
/* Mimic replacement of tabs */
ch = linein->line[j];
@@ -653,7 +310,9 @@ void wrap_offset_in_line(SpaceText *st, ARegion *ar, TextLine *linein, int cursi
chars = 1;
while (chars--) {
- if (i - start >= max) {
+ if (i + columns - start > max) {
+ end = MIN2(end, i);
+
if (chop && i >= cursin) {
if (i == cursin) {
(*offl)++;
@@ -676,7 +335,7 @@ void wrap_offset_in_line(SpaceText *st, ARegion *ar, TextLine *linein, int cursi
if (i >= cursin)
return;
}
- i++;
+ i += columns;
}
}
}
@@ -689,25 +348,37 @@ int text_get_char_pos(SpaceText *st, const char *line, int cur)
if (line[i] == '\t')
a += st->tabnumber - a % st->tabnumber;
else
- a++;
+ a += BLI_str_utf8_char_width_safe(line + i);
}
return a;
}
-static const char *txt_utf8_get_nth(const char *str, int n)
+static const char *txt_utf8_forward_columns(const char *str, int columns, int *padding)
{
- int pos = 0;
- while (str[pos] && n--) {
- pos += BLI_str_utf8_size_safe(str + pos);
+ int col;
+ const char *p = str;
+ while (*p) {
+ col = BLI_str_utf8_char_width(p);
+ if (columns - col < 0)
+ break;
+ columns -= col;
+ p += BLI_str_utf8_size_safe(p);
+ if (columns == 0)
+ break;
}
- return str + pos;
+ if (padding)
+ *padding = *p ? columns : 0;
+ return p;
}
static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w, const char *format, int skip)
{
FlattenString fs;
- int basex, i, a, start, end, max, lines; /* view */
+ int basex, lines;
+ int i, wrap, end, max, columns, padding; /* column */
+ int a, fstart, fpos; /* utf8 chars */
int mi, ma, mstart, mend; /* mem */
+ char fmt_prev = 0xff;
flatten_string(st, &fs, str);
str = fs.buf;
@@ -716,41 +387,49 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
basex = x;
lines = 1;
- start = 0; mstart = 0;
- end = max; mend = txt_utf8_get_nth(str, max) - str;
+ fpos = fstart = 0; mstart = 0;
+ mend = txt_utf8_forward_columns(str, max, &padding) - str;
+ end = wrap = max - padding;
- for (i = 0, mi = 0; str[mi]; i++, mi += BLI_str_utf8_size_safe(str + mi)) {
- if (i - start >= max) {
+ for (i = 0, mi = 0; str[mi]; i += columns, mi += BLI_str_utf8_size_safe(str + mi)) {
+ columns = BLI_str_utf8_char_width_safe(str + mi);
+ if (i + columns > end) {
/* skip hidden part of line */
if (skip) {
skip--;
- start = end; mstart = mend;
- end += max; mend = txt_utf8_get_nth(str + mend, max) - str;
+ fstart = fpos; mstart = mend;
+ mend = txt_utf8_forward_columns(str + mend, max, &padding) - str;
+ end = (wrap += max - padding);
continue;
}
/* Draw the visible portion of text on the overshot line */
- for (a = start, ma = mstart; a < end; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
- if (st->showsyntax && format) format_draw_color(format[a]);
+ for (a = fstart, ma = mstart; ma < mend; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
+ if (st->showsyntax && format) {
+ if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
+ }
x += text_font_draw_character_utf8(st, x, y, str + ma);
+ fpos++;
}
- y -= st->lheight + TXT_LINE_SPACING;
+ y -= st->lheight_dpi + TXT_LINE_SPACING;
x = basex;
lines++;
- start = end; mstart = mend;
- end += max; mend = txt_utf8_get_nth(str + mend, max) - str;
+ fstart = fpos; mstart = mend;
+ mend = txt_utf8_forward_columns(str + mend, max, &padding) - str;
+ end = (wrap += max - padding);
if (y <= 0) break;
}
else if (str[mi] == ' ' || str[mi] == '-') {
- end = i + 1; mend = mi + 1;
+ wrap = i + 1; mend = mi + 1;
}
}
/* Draw the remaining text */
- for (a = start, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
- if (st->showsyntax && format)
- format_draw_color(format[a]);
+ for (a = fstart, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
+ if (st->showsyntax && format) {
+ if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
+ }
x += text_font_draw_character_utf8(st, x, y, str + ma);
}
@@ -760,50 +439,55 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w
return lines;
}
-static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int draw, int x, int y, const char *format)
+static void text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int x, int y, const char *format)
{
FlattenString fs;
- int *acc, r = 0;
- const char *in;
+ int columns, size, n, w = 0, padding, amount = 0;
+ const char *in = NULL;
+
+ for (n = flatten_string(st, &fs, str), str = fs.buf; n > 0; n--) {
+ columns = BLI_str_utf8_char_width_safe(str);
+ size = BLI_str_utf8_size_safe(str);
+
+ if (!in) {
+ if (w >= cshift) {
+ padding = w - cshift;
+ in = str;
+ }
+ else if (format)
+ format++;
+ }
+ if (in) {
+ if (maxwidth && w + columns > cshift + maxwidth)
+ break;
+ amount++;
+ }
- int w = flatten_string(st, &fs, str);
- if (w < cshift) {
+ w += columns;
+ str += size;
+ }
+ if (!in) {
flatten_string_free(&fs);
- return 0; /* String is shorter than shift */
+ return; /* String is shorter than shift or ends with a padding */
}
-
- in = txt_utf8_get_nth(fs.buf, cshift);
- acc = fs.accum + cshift;
- w = w - cshift;
- if (draw) {
- int amount = maxwidth ? MIN2(w, maxwidth) : w;
-
- if (st->showsyntax && format) {
- int a, str_shift = 0;
- format = format + cshift;
+ x += st->cwidth * padding;
- for (a = 0; a < amount; a++) {
- format_draw_color(format[a]);
- x += text_font_draw_character_utf8(st, x, y, in + str_shift);
- str_shift += BLI_str_utf8_size_safe(in + str_shift);
- }
+ if (st->showsyntax && format) {
+ int a, str_shift = 0;
+ char fmt_prev = 0xff;
+
+ for (a = 0; a < amount; a++) {
+ if (format[a] != fmt_prev) format_draw_color(fmt_prev = format[a]);
+ x += text_font_draw_character_utf8(st, x, y, in + str_shift);
+ str_shift += BLI_str_utf8_size_safe(in + str_shift);
}
- else text_font_draw(st, x, y, in);
}
else {
- while (w-- && *acc++ < maxwidth)
- r += st->cwidth;
+ text_font_draw(st, x, y, in);
}
flatten_string_free(&fs);
-
- if (cshift && r == 0)
- return 0;
- else if (st->showlinenrs)
- return r + TXT_OFFSET + TEXTXLOC;
- else
- return r + TXT_OFFSET;
}
/************************ cache utilities *****************************/
@@ -852,7 +536,7 @@ static void text_update_drawcache(SpaceText *st, ARegion *ar)
full_update |= drawcache->wordwrap != st->wordwrap; /* word-wrapping option was toggled */
full_update |= drawcache->showlinenrs != st->showlinenrs; /* word-wrapping option was toggled */
full_update |= drawcache->tabnumber != st->tabnumber; /* word-wrapping option was toggled */
- full_update |= drawcache->lheight != st->lheight; /* 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 */
@@ -928,7 +612,7 @@ static void text_update_drawcache(SpaceText *st, ARegion *ar)
/* store settings */
drawcache->winx = ar->winx;
drawcache->wordwrap = st->wordwrap;
- drawcache->lheight = st->lheight;
+ drawcache->lheight = st->lheight_dpi;
drawcache->cwidth = st->cwidth;
drawcache->showlinenrs = st->showlinenrs;
drawcache->tabnumber = st->tabnumber;
@@ -1017,25 +701,29 @@ int text_get_visible_lines(SpaceText *st, ARegion *ar, const char *str)
start = 0;
end = max;
for (i = 0, j = 0; str[j]; j += BLI_str_utf8_size_safe(str + j)) {
+ int columns = BLI_str_utf8_char_width_safe(str + j); /* = 1 for tab */
+
/* Mimic replacement of tabs */
ch = str[j];
if (ch == '\t') {
chars = st->tabnumber - i % st->tabnumber;
ch = ' ';
}
- else chars = 1;
+ else {
+ chars = 1;
+ }
while (chars--) {
- if (i - start >= max) {
+ if (i + columns - start > max) {
lines++;
- start = end;
+ start = MIN2(end, i);
end += max;
}
else if (ch == ' ' || ch == '-') {
end = i + 1;
}
- i++;
+ i += columns;
}
}
@@ -1057,7 +745,9 @@ int text_get_span_wrap(SpaceText *st, ARegion *ar, TextLine *from, TextLine *to)
return ret;
}
- else return txt_get_span(from, to);
+ else {
+ return txt_get_span(from, to);
+ }
}
int text_get_total_lines(SpaceText *st, ARegion *ar)
@@ -1085,12 +775,12 @@ static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll, rcti *back)
blank_lines = st->viewlines / 2;
/* nicer code: use scroll rect for entire bar */
- back->xmin = ar->winx - 18;
+ back->xmin = ar->winx - (V2D_SCROLL_WIDTH + 1);
back->xmax = ar->winx;
back->ymin = 0;
back->ymax = ar->winy;
- scroll->xmin = ar->winx - 17;
+ scroll->xmin = ar->winx - V2D_SCROLL_WIDTH;
scroll->xmax = ar->winx - 5;
scroll->ymin = 4;
scroll->ymax = 4 + pix_available;
@@ -1237,9 +927,9 @@ static void draw_documentation(SpaceText *st, ARegion *ar)
x += SUGG_LIST_WIDTH * st->cwidth + 50;
}
- /* top = */ /* UNUSED */ y = ar->winy - st->lheight * l - 2;
+ /* top = */ /* UNUSED */ y = ar->winy - st->lheight_dpi * l - 2;
boxw = DOC_WIDTH * st->cwidth + 20;
- boxh = (DOC_HEIGHT + 1) * st->lheight;
+ boxh = (DOC_HEIGHT + 1) * (st->lheight_dpi + TXT_LINE_SPACING);
/* Draw panel */
UI_ThemeColor(TH_BACK);
@@ -1271,8 +961,8 @@ static void draw_documentation(SpaceText *st, ARegion *ar)
else if (*p == '\n') {
buf[i] = '\0';
if (lines >= 0) {
- y -= st->lheight;
- text_draw(st, buf, 0, 0, 1, x + 4, y - 3, NULL);
+ y -= st->lheight_dpi;
+ text_draw(st, buf, 0, 0, x + 4, y - 3, NULL);
}
i = 0; br = DOC_WIDTH; lines++;
}
@@ -1280,8 +970,8 @@ static void draw_documentation(SpaceText *st, ARegion *ar)
if (i == DOC_WIDTH) { /* Reached the width, go to last break and wrap there */
buf[br] = '\0';
if (lines >= 0) {
- y -= st->lheight;
- text_draw(st, buf, 0, 0, 1, x + 4, y - 3, NULL);
+ y -= st->lheight_dpi;
+ text_draw(st, buf, 0, 0, x + 4, y - 3, NULL);
}
p -= i - br - 1; /* Rewind pointer to last break */
i = 0; br = DOC_WIDTH; lines++;
@@ -1300,11 +990,13 @@ static void draw_documentation(SpaceText *st, ARegion *ar)
static void draw_suggestion_list(SpaceText *st, ARegion *ar)
{
SuggItem *item, *first, *last, *sel;
- TextLine *tmp;
- char str[SUGG_LIST_WIDTH + 1];
- int w, boxw = 0, boxh, i, l, x, y, b, *top;
+ char str[SUGG_LIST_WIDTH * BLI_UTF8_MAX + 1];
+ int offl, offc, vcurl, vcurc;
+ int w, boxw = 0, boxh, i, x, y, *top;
+ const int lheight = st->lheight_dpi + TXT_LINE_SPACING;
+ const int margin_x = 2;
- if (!st || !st->text) return;
+ if (!st->text) return;
if (!texttool_text_is_active(st->text)) return;
first = texttool_suggest_first();
@@ -1316,54 +1008,51 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar)
sel = texttool_suggest_selected();
top = texttool_suggest_top();
- /* Count the visible lines to the cursor */
- for (tmp = st->text->curl, l = -st->top; tmp; tmp = tmp->prev, l++) ;
- if (l < 0) return;
-
- if (st->showlinenrs) {
- x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET + TEXTXLOC - 4;
- }
- else {
- x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET - 4;
- }
- y = ar->winy - st->lheight * l - 2;
+ wrap_offset(st, ar, st->text->curl, st->text->curc, &offl, &offc);
+ vcurl = txt_get_span(st->text->lines.first, st->text->curl) - st->top + offl;
+ vcurc = text_get_char_pos(st, st->text->curl->line, st->text->curc) - st->left + offc;
+
+ x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
+ x += vcurc * st->cwidth - 4;
+ y = ar->winy - (vcurl + 1) * lheight - 2;
+
+ /* offset back so the start of the text lines up with the suggestions,
+ * not essential but makes suggestions easier to follow */
+ x -= st->cwidth * (st->text->curc - text_find_identifier_start(st->text->curl->line, st->text->curc));
boxw = SUGG_LIST_WIDTH * st->cwidth + 20;
- boxh = SUGG_LIST_SIZE * st->lheight + 8;
+ boxh = SUGG_LIST_SIZE * lheight + 8;
+ if (x + boxw > ar->winx)
+ x = MAX2(0, ar->winx - boxw);
+
+ /* not needed but stands out nicer */
+ uiDrawBoxShadow(220, x, y - boxh, x + boxw, y);
+
UI_ThemeColor(TH_SHADE1);
glRecti(x - 1, y + 1, x + boxw + 1, y - boxh - 1);
- UI_ThemeColor(TH_BACK);
+ UI_ThemeColorShade(TH_BACK, 16);
glRecti(x, y, x + boxw, y - boxh);
/* Set the top 'item' of the visible list */
for (i = 0, item = first; i < *top && item->next; i++, item = item->next) ;
for (i = 0; i < SUGG_LIST_SIZE && item; i++, item = item->next) {
+ int len = txt_utf8_forward_columns(item->name, SUGG_LIST_WIDTH, NULL) - item->name;
- y -= st->lheight;
+ y -= lheight;
- BLI_strncpy(str, item->name, SUGG_LIST_WIDTH);
+ BLI_strncpy(str, item->name, len + 1);
- w = BLF_width(mono, str);
+ w = st->cwidth * text_get_char_pos(st, str, len);
if (item == sel) {
UI_ThemeColor(TH_SHADE2);
- glRecti(x + 16, y - 3, x + 16 + w, y + st->lheight - 3);
- }
- b = 1; /* b=1 color block, text is default. b=0 no block, color text */
- switch (item->type) {
- case 'k': UI_ThemeColor(TH_SYNTAX_B); b = 0; break;
- case 'm': UI_ThemeColor(TH_TEXT); break;
- case 'f': UI_ThemeColor(TH_SYNTAX_L); break;
- case 'v': UI_ThemeColor(TH_SYNTAX_N); break;
- case '?': UI_ThemeColor(TH_TEXT); b = 0; break;
+ glRecti(x + margin_x, y - 3, x + margin_x + w, y + lheight - 3);
}
- if (b) {
- glRecti(x + 8, y + 2, x + 11, y + 5);
- UI_ThemeColor(TH_TEXT);
- }
- text_draw(st, str, 0, 0, 1, x + 16, y - 1, NULL);
+
+ format_draw_color(item->type);
+ text_draw(st, str, 0, 0, x + margin_x, y - 1, NULL);
if (item == last) break;
}
@@ -1376,7 +1065,7 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
Text *text = st->text;
int vcurl, vcurc, vsell, vselc, hidden = 0;
int x, y, w, i;
- int lheight = st->lheight + TXT_LINE_SPACING;
+ const int lheight = st->lheight_dpi + TXT_LINE_SPACING;
/* Draw the selection */
if (text->curl != text->sell || text->curc != text->selc) {
@@ -1394,14 +1083,14 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
UI_ThemeColor(TH_SHADE2);
x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
- y = ar->winy - 2;
+ y = ar->winy;
if (vcurl == vsell) {
y -= vcurl * lheight;
if (vcurc < vselc)
- glRecti(x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - lheight + TXT_LINE_SPACING);
+ glRecti(x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - lheight);
else
- glRecti(x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - lheight + TXT_LINE_SPACING);
+ glRecti(x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - lheight);
}
else {
int froml, fromc, tol, toc;
@@ -1420,7 +1109,7 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
for (i = froml + 1; i < tol; i++)
glRecti(x - 4, y, ar->winx, y - lheight), y -= lheight;
- glRecti(x - 4, y, x + toc * st->cwidth, y - lheight + TXT_LINE_SPACING); y -= lheight;
+ glRecti(x - 4, y, x + toc * st->cwidth, y - lheight); y -= lheight;
}
}
else {
@@ -1445,11 +1134,11 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
wrap_offset_in_line(st, ar, text->sell, text->selc, &offl, &offc);
y1 = ar->winy - 2 - (vsell - offl) * lheight;
- y2 = y1 - lheight * visible_lines + 1;
+ y2 = y1 - (lheight * visible_lines + TXT_LINE_SPACING);
}
else {
y1 = ar->winy - 2 - vsell * lheight;
- y2 = y1 - lheight + 1;
+ y2 = y1 - (lheight + TXT_LINE_SPACING);
}
if (!(y1 < 0 || y2 > ar->winy)) { /* check we need to draw */
@@ -1469,7 +1158,7 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
/* Draw the cursor itself (we draw the sel. cursor as this is the leading edge) */
x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
x += vselc * st->cwidth;
- y = ar->winy - 2 - vsell * lheight;
+ y = ar->winy - vsell * lheight;
if (st->overwrite) {
char ch = text->sell->line[text->selc];
@@ -1483,7 +1172,7 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
}
else {
UI_ThemeColor(TH_HILITE);
- glRecti(x - 1, y, x + 1, y - lheight + TXT_LINE_SPACING);
+ glRecti(x - 1, y, x + 1, y - lheight);
}
}
}
@@ -1517,7 +1206,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
stack = 0;
/* Don't highlight backets if syntax HL is off or bracket in string or comment. */
- if (!linep->format || linep->format[fc] == 'l' || linep->format[fc] == '#')
+ if (!linep->format || linep->format[fc] == FMT_TYPE_STRING || linep->format[fc] == FMT_TYPE_COMMENT)
return;
if (b > 0) {
@@ -1526,7 +1215,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
c += BLI_str_utf8_size_safe(linep->line + c);
while (linep) {
while (c < linep->len) {
- if (linep->format && linep->format[fc] != 'l' && linep->format[fc] != '#') {
+ if (linep->format && linep->format[fc] != FMT_TYPE_STRING && linep->format[fc] != FMT_TYPE_COMMENT) {
b = text_check_bracket(linep->line[c]);
if (b == find) {
if (stack == 0) {
@@ -1555,7 +1244,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
if (c > 0) c -= linep->line + c - BLI_str_prev_char_utf8(linep->line + c);
while (linep) {
while (fc >= 0) {
- if (linep->format && linep->format[fc] != 'l' && linep->format[fc] != '#') {
+ if (linep->format && linep->format[fc] != FMT_TYPE_STRING && linep->format[fc] != FMT_TYPE_COMMENT) {
b = text_check_bracket(linep->line[c]);
if (b == find) {
if (stack == 0) {
@@ -1588,7 +1277,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
UI_ThemeColor(TH_HILITE);
x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
- y = ar->winy - st->lheight;
+ y = ar->winy - st->lheight_dpi;
/* draw opening bracket */
ch = startl->line[startc];
@@ -1598,8 +1287,8 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
if (viewc >= 0) {
viewl = txt_get_span(text->lines.first, startl) - st->top + offl;
- text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * (st->lheight + TXT_LINE_SPACING), ch);
- text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * (st->lheight + TXT_LINE_SPACING), ch);
+ text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
+ text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
}
/* draw closing bracket */
@@ -1610,8 +1299,8 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
if (viewc >= 0) {
viewl = txt_get_span(text->lines.first, endl) - st->top + offl;
- text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * (st->lheight + TXT_LINE_SPACING), ch);
- text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * (st->lheight + TXT_LINE_SPACING), ch);
+ text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
+ text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * (st->lheight_dpi + TXT_LINE_SPACING), ch);
}
}
@@ -1620,6 +1309,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
void draw_text_main(SpaceText *st, ARegion *ar)
{
Text *text = st->text;
+ TextFormatType *tft;
TextLine *tmp;
rcti scroll, back;
char linenr[12];
@@ -1627,7 +1317,10 @@ void draw_text_main(SpaceText *st, ARegion *ar)
int wraplinecount = 0, wrap_skip = 0;
int margin_column_x;
- if (st->lheight) st->viewlines = (int)ar->winy / (st->lheight + TXT_LINE_SPACING);
+ /* dpi controlled line height and font size */
+ st->lheight_dpi = (U.widget_unit * st->lheight) / 20;
+
+ if (st->lheight_dpi) st->viewlines = (int)ar->winy / (st->lheight_dpi + TXT_LINE_SPACING);
else st->viewlines = 0;
/* if no text, nothing to do */
@@ -1644,11 +1337,12 @@ void draw_text_main(SpaceText *st, ARegion *ar)
calc_text_rcts(st, ar, &scroll, &back); /* scroll will hold the entire bar size */
/* update syntax formatting if needed */
+ tft = ED_text_format_get(text);
tmp = text->lines.first;
lineno = 0;
for (i = 0; i < st->top && tmp; i++) {
if (st->showsyntax && !tmp->format)
- txt_format_line(st, tmp, 0);
+ tft->format_line(st, tmp, 0);
if (st->wordwrap) {
int lines = text_get_visible_lines_no(st, lineno);
@@ -1686,7 +1380,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
st->linenrs_tot = 0; /* not used */
x = TXT_OFFSET;
}
- y = ar->winy - st->lheight;
+ y = ar->winy - st->lheight_dpi;
winx = ar->winx - TXT_SCROLL_WIDTH;
/* draw cursor */
@@ -1697,7 +1391,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
for (i = 0; y > 0 && i < st->viewlines && tmp; i++, tmp = tmp->next) {
if (st->showsyntax && !tmp->format)
- txt_format_line(st, tmp, 0);
+ tft->format_line(st, tmp, 0);
if (st->showlinenrs && !wrap_skip) {
/* draw line number */
@@ -1716,12 +1410,12 @@ void draw_text_main(SpaceText *st, ARegion *ar)
if (st->wordwrap) {
/* draw word wrapped text */
int lines = text_draw_wrapped(st, tmp->line, x, y, winx - x, tmp->format, wrap_skip);
- y -= lines * (st->lheight + TXT_LINE_SPACING);
+ y -= lines * (st->lheight_dpi + TXT_LINE_SPACING);
}
else {
/* draw unwrapped text */
- text_draw(st, tmp->line, st->left, ar->winx / st->cwidth, 1, x, y, tmp->format);
- y -= st->lheight + TXT_LINE_SPACING;
+ text_draw(st, tmp->line, st->left, ar->winx / st->cwidth, x, y, tmp->format);
+ y -= st->lheight_dpi + TXT_LINE_SPACING;
}
wrap_skip = 0;
@@ -1777,8 +1471,6 @@ void text_scroll_to_cursor(SpaceText *st, ScrArea *sa)
winx = ar->winx;
break;
}
-
- winx -= TXT_SCROLL_WIDTH;
text_update_character_width(st);
@@ -1796,10 +1488,11 @@ void text_scroll_to_cursor(SpaceText *st, ScrArea *sa)
st->left = 0;
}
else {
- x = text_draw(st, text->sell->line, st->left, text->selc, 0, 0, 0, NULL);
+ 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 = text->curc - 0.5 * winx / st->cwidth;
+ if (x <= 0 || x > winx)
+ st->left += (x - winx / 2) / st->cwidth;
}
if (st->top < 0) st->top = 0;
diff --git a/source/blender/editors/space_text/text_format.c b/source/blender/editors/space_text/text_format.c
new file mode 100644
index 00000000000..b29c6420d60
--- /dev/null
+++ b/source/blender/editors/space_text/text_format.c
@@ -0,0 +1,227 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 blender/editors/space_text/text_format.c
+ * \ingroup sptext
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_text_types.h"
+#include "DNA_space_types.h"
+
+#include "text_format.h"
+
+
+/****************** flatten string **********************/
+
+static void flatten_string_append(FlattenString *fs, const char *c, int accum, int len)
+{
+ int i;
+
+ if (fs->pos + len > fs->len) {
+ char *nbuf; int *naccum;
+ fs->len *= 2;
+
+ nbuf = MEM_callocN(sizeof(*fs->buf) * fs->len, "fs->buf");
+ naccum = MEM_callocN(sizeof(*fs->accum) * fs->len, "fs->accum");
+
+ memcpy(nbuf, fs->buf, fs->pos * sizeof(*fs->buf));
+ memcpy(naccum, fs->accum, fs->pos * sizeof(*fs->accum));
+
+ if (fs->buf != fs->fixedbuf) {
+ MEM_freeN(fs->buf);
+ MEM_freeN(fs->accum);
+ }
+
+ fs->buf = nbuf;
+ fs->accum = naccum;
+ }
+
+ for (i = 0; i < len; i++) {
+ fs->buf[fs->pos + i] = c[i];
+ fs->accum[fs->pos + i] = accum;
+ }
+
+ fs->pos += len;
+}
+
+int flatten_string(SpaceText *st, FlattenString *fs, const char *in)
+{
+ int r, i, total = 0;
+
+ memset(fs, 0, sizeof(FlattenString));
+ fs->buf = fs->fixedbuf;
+ fs->accum = fs->fixedaccum;
+ fs->len = sizeof(fs->fixedbuf);
+
+ for (r = 0, i = 0; *in; r++) {
+ if (*in == '\t') {
+ i = st->tabnumber - (total % st->tabnumber);
+ total += i;
+
+ while (i--)
+ flatten_string_append(fs, " ", r, 1);
+
+ in++;
+ }
+ else {
+ size_t len = BLI_str_utf8_size_safe(in);
+ flatten_string_append(fs, in, r, len);
+ in += len;
+ total++;
+ }
+ }
+
+ flatten_string_append(fs, "\0", r, 1);
+
+ return total;
+}
+
+void flatten_string_free(FlattenString *fs)
+{
+ if (fs->buf != fs->fixedbuf)
+ MEM_freeN(fs->buf);
+ if (fs->accum != fs->fixedaccum)
+ MEM_freeN(fs->accum);
+}
+
+/* takes a string within fs->buf and returns its length */
+int flatten_string_strlen(FlattenString *fs, const char *str)
+{
+ const int len = (fs->pos - (int)(str - fs->buf)) - 1;
+ BLI_assert(strlen(str) == len);
+ return len;
+}
+
+/* Ensures the format string for the given line is long enough, reallocating
+ * as needed. Allocation is done here, alone, to ensure consistency. */
+int text_check_format_len(TextLine *line, unsigned int len)
+{
+ if (line->format) {
+ if (strlen(line->format) < len) {
+ MEM_freeN(line->format);
+ line->format = MEM_mallocN(len + 2, "SyntaxFormat");
+ if (!line->format) return 0;
+ }
+ }
+ else {
+ line->format = MEM_mallocN(len + 2, "SyntaxFormat");
+ if (!line->format) return 0;
+ }
+
+ return 1;
+}
+
+/**
+ * Fill the string with formatting constant,
+ * advancing \a str_p and \a fmt_p
+ *
+ * \param len length in bytes of \a fmt_p to fill.
+ */
+void text_format_fill(const char **str_p, char **fmt_p, const char type, const int len)
+{
+ const char *str = *str_p;
+ char *fmt = *fmt_p;
+ int i = 0;
+
+ while (i < len) {
+ const int size = BLI_str_utf8_size_safe(str);
+ *fmt++ = type;
+
+ str += size;
+ i += 1;
+ }
+
+ str--;
+ fmt--;
+
+ BLI_assert(*str != '\0');
+
+ *str_p = str;
+ *fmt_p = fmt;
+}
+/**
+ * ascii version of #text_format_fill,
+ * use when we no the text being stepped over is ascii (as is the case for most keywords)
+ */
+void text_format_fill_ascii(const char **str_p, char **fmt_p, const char type, const int len)
+{
+ const char *str = *str_p;
+ char *fmt = *fmt_p;
+
+ memset(fmt, type, len);
+
+ str += len - 1;
+ fmt += len - 1;
+
+ BLI_assert(*str != '\0');
+
+ *str_p = str;
+ *fmt_p = fmt;
+}
+
+/* *** Registration *** */
+static ListBase tft_lb = {NULL, NULL};
+void ED_text_format_register(TextFormatType *tft)
+{
+ BLI_addtail(&tft_lb, tft);
+}
+
+TextFormatType *ED_text_format_get(Text *text)
+{
+ TextFormatType *tft;
+
+ if (text) {
+ const char *text_ext = strchr(text->id.name + 2, '.');
+ if (text_ext) {
+ text_ext++; /* skip the '.' */
+ /* Check all text formats in the static list */
+ for (tft = tft_lb.first; tft; tft = tft->next) {
+ /* All formats should have an ext, but just in case */
+ const char **ext;
+ for (ext = tft->ext; *ext; ext++) {
+ /* If extension matches text name, return the matching tft */
+ if (BLI_strcasecmp(text_ext, *ext) == 0) {
+ return tft;
+ }
+ }
+ }
+ }
+
+ /* If we make it here we never found an extension that worked - return
+ * the "default" text format */
+ return tft_lb.first;
+ }
+ else {
+ /* Return the "default" text format */
+ return tft_lb.first;
+ }
+}
diff --git a/source/blender/editors/space_text/text_format.h b/source/blender/editors/space_text/text_format.h
new file mode 100644
index 00000000000..808311cbb62
--- /dev/null
+++ b/source/blender/editors/space_text/text_format.h
@@ -0,0 +1,109 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_text/text_format.h
+ * \ingroup sptext
+ */
+
+#ifndef __TEXT_FORMAT_H__
+#define __TEXT_FORMAT_H__
+
+/* *** Flatten String *** */
+typedef struct FlattenString {
+ char fixedbuf[256];
+ int fixedaccum[256];
+
+ char *buf;
+ int *accum;
+ int pos, len;
+} FlattenString;
+
+/* format continuation flags (stored just after the NULL terminator) */
+enum {
+ FMT_CONT_NOP = 0, /* no continuation */
+ FMT_CONT_QUOTESINGLE = (1 << 0), /* single quotes */
+ FMT_CONT_QUOTEDOUBLE = (1 << 1), /* double quotes */
+ FMT_CONT_TRIPLE = (1 << 2), /* triplets of quotes: """ or ''' */
+ FMT_CONT_QUOTESINGLE_TRIPLE = (FMT_CONT_TRIPLE | FMT_CONT_QUOTESINGLE),
+ FMT_CONT_QUOTEDOUBLE_TRIPLE = (FMT_CONT_TRIPLE | FMT_CONT_QUOTEDOUBLE),
+ FMT_CONT_COMMENT_C = (1 << 3) /* multi-line comments, OSL only (C style) */
+};
+#define FMT_CONT_ALL \
+ (FMT_CONT_QUOTESINGLE | FMT_CONT_QUOTEDOUBLE | FMT_CONT_TRIPLE | FMT_CONT_COMMENT_C)
+
+int flatten_string(struct SpaceText *st, FlattenString *fs, const char *in);
+void flatten_string_free(FlattenString *fs);
+int flatten_string_strlen(FlattenString *fs, const char *str);
+
+int text_check_format_len(TextLine *line, unsigned int len);
+void text_format_fill(const char **str_p, char **fmt_p, const char type, const int len);
+void text_format_fill_ascii(const char **str_p, char **fmt_p, const char type, const int len);
+
+/* *** Generalize Formatting *** */
+typedef struct TextFormatType {
+ struct TextFormatType *next, *prev;
+
+ char (*format_identifier)(const char *string);
+
+ /* Formats the specified line. If do_next is set, the process will move on to
+ * the succeeding line if it is affected (eg. multiline strings). Format strings
+ * may contain any of the following characters:
+ *
+ * It is terminated with a null-terminator '\0' followed by a continuation
+ * flag indicating whether the line is part of a multi-line string.
+ *
+ * See: FMT_TYPE_ enums below
+ */
+ void (*format_line)(SpaceText *st, TextLine *line, int do_next);
+
+ const char **ext; /* NULL terminated extensions */
+} TextFormatType;
+
+enum {
+ FMT_TYPE_WHITESPACE = '_', /* Whitespace */
+ FMT_TYPE_COMMENT = '#', /* Comment text */
+ FMT_TYPE_SYMBOL = '!', /* Punctuation and other symbols */
+ FMT_TYPE_NUMERAL = 'n', /* Numerals */
+ FMT_TYPE_STRING = 'l', /* String letters */
+ FMT_TYPE_DIRECTIVE = 'd', /* Decorator / Preprocessor directive */
+ FMT_TYPE_SPECIAL = 'v', /* Special variables (class, def) */
+ FMT_TYPE_RESERVED = 'r', /* Reserved keywords currently not in use, but still prohibited (OSL -> switch e.g.) */
+ FMT_TYPE_KEYWORD = 'b', /* Built-in names (return, for, etc.) */
+ FMT_TYPE_DEFAULT = 'q', /* Regular text (identifiers, etc.) */
+};
+
+TextFormatType *ED_text_format_get(Text *text);
+void ED_text_format_register(TextFormatType *tft);
+
+/* formatters */
+void ED_text_format_register_py(void);
+void ED_text_format_register_osl(void);
+void ED_text_format_register_lua(void);
+
+#define STR_LITERAL_STARTSWITH(str, str_literal, len_var) \
+ (strncmp(str, str_literal, len_var = (sizeof(str_literal) - 1)) == 0)
+
+#endif /* __TEXT_FORMAT_H__ */
diff --git a/source/blender/editors/space_text/text_format_lua.c b/source/blender/editors/space_text/text_format_lua.c
new file mode 100644
index 00000000000..9972c570db7
--- /dev/null
+++ b/source/blender/editors/space_text/text_format_lua.c
@@ -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
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 blender/editors/space_text/text_format_lua.c
+ * \ingroup sptext
+ */
+
+#include <string.h>
+
+#include "BLI_blenlib.h"
+
+#include "DNA_text_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_text.h"
+
+#include "text_format.h"
+
+/* *** Lua Keywords (for format_line) *** */
+
+/* Checks the specified source string for a Lua keyword (minus boolean & 'nil').
+ * This name must start at the beginning of the source string and must be
+ * followed by a non-identifier (see text_check_identifier(char)) or null char.
+ *
+ * If a keyword is found, the length of the matching word is returned.
+ * Otherwise, -1 is returned.
+ *
+ * See:
+ * http://www.lua.org/manual/5.1/manual.html#2.1
+ */
+
+static int txtfmt_lua_find_keyword(const char *string)
+{
+ int i, len;
+
+ if (STR_LITERAL_STARTSWITH(string, "and", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "do", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "elseif", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "end", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "function", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "in", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "local", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "not", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "or", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "repeat", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "then", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "until", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
+}
+
+/* Checks the specified source string for a Lua special name/function. This
+ * name must start at the beginning of the source string and must be followed
+ * by a non-identifier (see text_check_identifier(char)) or null character.
+ *
+ * If a special name is found, the length of the matching name is returned.
+ * Otherwise, -1 is returned.
+ *
+ * See:
+ * http://www.lua.org/manual/5.1/manual.html#5.1
+ */
+
+static int txtfmt_lua_find_specialvar(const char *string)
+{
+ int i, len;
+
+ if (STR_LITERAL_STARTSWITH(string, "assert", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "collectgarbage", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "dofile", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "error", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "_G", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "getfenv", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "getmetatable", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "__index", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "ipairs", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "load", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "loadfile", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "loadstring", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "next", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pairs", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pcall", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "print", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rawequal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rawget", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "rawset", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "select", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "setfenv", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "setmetatable", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tonumber", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "tostring", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "type", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "unpack", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "_VERSION", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "xpcall", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
+}
+
+static int txtfmt_lua_find_bool(const char *string)
+{
+ int i, len;
+
+ if (STR_LITERAL_STARTSWITH(string, "nil", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
+}
+
+static char txtfmt_lua_format_identifier(const char *str)
+{
+ char fmt;
+ if ((txtfmt_lua_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL;
+ else if ((txtfmt_lua_find_keyword(str)) != -1) fmt = FMT_TYPE_KEYWORD;
+ else fmt = FMT_TYPE_DEFAULT;
+ return fmt;
+}
+
+static void txtfmt_lua_format_line(SpaceText *st, TextLine *line, const int do_next)
+{
+ FlattenString fs;
+ const char *str;
+ char *fmt;
+ char cont_orig, cont, find, prev = ' ';
+ int len, i;
+
+ /* Get continuation from previous line */
+ if (line->prev && line->prev->format != NULL) {
+ fmt = line->prev->format;
+ cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont) == cont);
+ }
+ else {
+ cont = FMT_CONT_NOP;
+ }
+
+ /* Get original continuation from this line */
+ if (line->format != NULL) {
+ fmt = line->format;
+ cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
+ }
+ else {
+ cont_orig = 0xFF;
+ }
+
+ len = flatten_string(st, &fs, line->line);
+ str = fs.buf;
+ if (!text_check_format_len(line, len)) {
+ flatten_string_free(&fs);
+ return;
+ }
+ fmt = line->format;
+
+ while (*str) {
+ /* Handle escape sequences by skipping both \ and next char */
+ if (*str == '\\') {
+ *fmt = prev; fmt++; str++;
+ if (*str == '\0') break;
+ *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str);
+ continue;
+ }
+ /* Handle continuations */
+ else if (cont) {
+ /* Multi-line comments */
+ if (cont & FMT_CONT_COMMENT_C) {
+ if (*str == ']' && *(str + 1) == ']') {
+ *fmt = FMT_TYPE_COMMENT; fmt++; str++;
+ *fmt = FMT_TYPE_COMMENT;
+ cont = FMT_CONT_NOP;
+ }
+ else {
+ *fmt = FMT_TYPE_COMMENT;
+ }
+ /* Handle other comments */
+ }
+ else {
+ find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
+ if (*str == find) cont = 0;
+ *fmt = FMT_TYPE_STRING;
+ }
+
+ str += BLI_str_utf8_size_safe(str) - 1;
+ }
+ /* Not in a string... */
+ else {
+ /* Multi-line comments */
+ if (*str == '-' && *(str + 1) == '-' &&
+ *(str + 2) == '[' && *(str + 3) == '[')
+ {
+ cont = FMT_CONT_COMMENT_C;
+ *fmt = FMT_TYPE_COMMENT; fmt++; str++;
+ *fmt = FMT_TYPE_COMMENT; fmt++; str++;
+ *fmt = FMT_TYPE_COMMENT; fmt++; str++;
+ *fmt = FMT_TYPE_COMMENT;
+ }
+ /* Single line comment */
+ else if (*str == '-' && *(str + 1) == '-') {
+ text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format));
+ }
+ else if (*str == '"' || *str == '\'') {
+ /* Strings */
+ find = *str;
+ cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
+ *fmt = FMT_TYPE_STRING;
+ }
+ /* Whitespace (all ws. has been converted to spaces) */
+ else if (*str == ' ') {
+ *fmt = FMT_TYPE_WHITESPACE;
+ }
+ /* Numbers (digits not part of an identifier and periods followed by digits) */
+ else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
+ (*str == '.' && text_check_digit(*(str + 1))))
+ {
+ *fmt = FMT_TYPE_NUMERAL;
+ }
+ /* Booleans */
+ else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_lua_find_bool(str)) != -1) {
+ if (i > 0) {
+ text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i);
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ /* Punctuation */
+ else if ((*str != '#') && text_check_delim(*str)) {
+ *fmt = FMT_TYPE_SYMBOL;
+ }
+ /* Identifiers and other text (no previous ws. or delims. so text continues) */
+ else if (prev == FMT_TYPE_DEFAULT) {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
+ else {
+ /* Special vars(v) or built-in keywords(b) */
+ /* keep in sync with 'txtfmt_osl_format_identifier()' */
+ if ((i = txtfmt_lua_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL;
+ else if ((i = txtfmt_lua_find_keyword(str)) != -1) prev = FMT_TYPE_KEYWORD;
+
+ if (i > 0) {
+ text_format_fill_ascii(&str, &fmt, prev, i);
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ }
+ prev = *fmt; fmt++; str++;
+ }
+
+ /* Terminate and add continuation char */
+ *fmt = '\0'; fmt++;
+ *fmt = cont;
+
+ /* If continuation has changed and we're allowed, process the next line */
+ if (cont != cont_orig && do_next && line->next) {
+ txtfmt_lua_format_line(st, line->next, do_next);
+ }
+
+ flatten_string_free(&fs);
+}
+
+void ED_text_format_register_lua(void)
+{
+ static TextFormatType tft = {NULL};
+ static const char *ext[] = {"lua", NULL};
+
+ tft.format_identifier = txtfmt_lua_format_identifier;
+ tft.format_line = txtfmt_lua_format_line;
+ tft.ext = ext;
+
+ ED_text_format_register(&tft);
+}
diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c
new file mode 100644
index 00000000000..a4322fb310e
--- /dev/null
+++ b/source/blender/editors/space_text/text_format_osl.c
@@ -0,0 +1,336 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 blender/editors/space_text/text_format_osl.c
+ * \ingroup sptext
+ */
+
+#include <string.h>
+
+#include "BLI_blenlib.h"
+
+#include "DNA_text_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_text.h"
+
+#include "text_format.h"
+
+/* *** Local Functions (for format_line) *** */
+
+static int txtfmt_osl_find_builtinfunc(const char *string)
+{
+ int i, len;
+ /* list is from
+ * https://github.com/imageworks/OpenShadingLanguage/raw/master/src/doc/osl-languagespec.pdf
+ */
+ if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "closure", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "color", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "continue", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "do", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "emit", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "float", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "illuminance", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "illuminate", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "int", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "matrix", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "normal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "output", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "point", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "public", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "string", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "struct", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "vector", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "void", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
+}
+
+static int txtfmt_osl_find_reserved(const char *string)
+{
+ int i, len;
+ /* list is from...
+ * https://github.com/imageworks/OpenShadingLanguage/raw/master/src/doc/osl-languagespec.pdf
+ */
+ if (STR_LITERAL_STARTSWITH(string, "bool", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "case", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "catch", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "char", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "const", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "delete", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "default", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "double", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "enum", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "extern", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "friend", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "goto", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "inline", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "long", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "new", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "operator", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "private", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "protected", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "short", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "signed", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "sizeof", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "static", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "switch", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "template", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "this", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "throw", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "try", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "typedef", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "uniform", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "union", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "unsigned", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "varying", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "virtual", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "volatile", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
+}
+
+/* Checks the specified source string for a OSL special name. This name must
+ * start at the beginning of the source string and must be followed by a non-
+ * identifier (see text_check_identifier(char)) or null character.
+ *
+ * If a special name is found, the length of the matching name is returned.
+ * Otherwise, -1 is returned. */
+
+static int txtfmt_osl_find_specialvar(const char *string)
+{
+ int i, len;
+
+ /* OSL shader types */
+ if (STR_LITERAL_STARTSWITH(string, "shader", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "surface", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "volume", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "displacement", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
+}
+
+/* matches py 'txtfmt_osl_find_decorator' */
+static int txtfmt_osl_find_preprocessor(const char *string)
+{
+ if (string[0] == '#') {
+ int i = 1;
+ /* Whitespace is ok '# foo' */
+ while (text_check_whitespace(string[i])) {
+ i++;
+ }
+ while (text_check_identifier(string[i])) {
+ i++;
+ }
+ return i;
+ }
+ return -1;
+}
+
+static char txtfmt_osl_format_identifier(const char *str)
+{
+ char fmt;
+ if ((txtfmt_osl_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL;
+ else if ((txtfmt_osl_find_builtinfunc(str)) != -1) fmt = FMT_TYPE_KEYWORD;
+ else if ((txtfmt_osl_find_reserved(str)) != -1) fmt = FMT_TYPE_RESERVED;
+ else if ((txtfmt_osl_find_preprocessor(str)) != -1) fmt = FMT_TYPE_DIRECTIVE;
+ else fmt = FMT_TYPE_DEFAULT;
+ return fmt;
+}
+
+static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_next)
+{
+ FlattenString fs;
+ const char *str;
+ char *fmt;
+ char cont_orig, cont, find, prev = ' ';
+ int len, i;
+
+ /* Get continuation from previous line */
+ if (line->prev && line->prev->format != NULL) {
+ fmt = line->prev->format;
+ cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont) == cont);
+ }
+ else {
+ cont = FMT_CONT_NOP;
+ }
+
+ /* Get original continuation from this line */
+ if (line->format != NULL) {
+ fmt = line->format;
+ cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
+ }
+ else {
+ cont_orig = 0xFF;
+ }
+
+ len = flatten_string(st, &fs, line->line);
+ str = fs.buf;
+ if (!text_check_format_len(line, len)) {
+ flatten_string_free(&fs);
+ return;
+ }
+ fmt = line->format;
+
+ while (*str) {
+ /* Handle escape sequences by skipping both \ and next char */
+ if (*str == '\\') {
+ *fmt = prev; fmt++; str++;
+ if (*str == '\0') break;
+ *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str);
+ continue;
+ }
+ /* Handle continuations */
+ else if (cont) {
+ /* C-Style comments */
+ if (cont & FMT_CONT_COMMENT_C) {
+ if (*str == '*' && *(str + 1) == '/') {
+ *fmt = FMT_TYPE_COMMENT; fmt++; str++;
+ *fmt = FMT_TYPE_COMMENT;
+ cont = FMT_CONT_NOP;
+ }
+ else {
+ *fmt = FMT_TYPE_COMMENT;
+ }
+ /* Handle other comments */
+ }
+ else {
+ find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
+ if (*str == find) cont = 0;
+ *fmt = FMT_TYPE_STRING;
+ }
+
+ str += BLI_str_utf8_size_safe(str) - 1;
+ }
+ /* Not in a string... */
+ else {
+ /* Deal with comments first */
+ if (*str == '/' && *(str + 1) == '/') {
+ /* fill the remaining line */
+ text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format));
+ }
+ /* C-Style (multi-line) comments */
+ else if (*str == '/' && *(str + 1) == '*') {
+ cont = FMT_CONT_COMMENT_C;
+ *fmt = FMT_TYPE_COMMENT; fmt++; str++;
+ *fmt = FMT_TYPE_COMMENT;
+ }
+ else if (*str == '"' || *str == '\'') {
+ /* Strings */
+ find = *str;
+ cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
+ *fmt = FMT_TYPE_STRING;
+ }
+ /* Whitespace (all ws. has been converted to spaces) */
+ else if (*str == ' ') {
+ *fmt = FMT_TYPE_WHITESPACE;
+ }
+ /* Numbers (digits not part of an identifier and periods followed by digits) */
+ else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
+ (*str == '.' && text_check_digit(*(str + 1))))
+ {
+ *fmt = FMT_TYPE_NUMERAL;
+ }
+ /* Punctuation */
+ else if ((*str != '#') && text_check_delim(*str)) {
+ *fmt = FMT_TYPE_SYMBOL;
+ }
+ /* Identifiers and other text (no previous ws. or delims. so text continues) */
+ else if (prev == FMT_TYPE_DEFAULT) {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
+ else {
+ /* Special vars(v) or built-in keywords(b) */
+ /* keep in sync with 'txtfmt_osl_format_identifier()' */
+ if ((i = txtfmt_osl_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL;
+ else if ((i = txtfmt_osl_find_builtinfunc(str)) != -1) prev = FMT_TYPE_KEYWORD;
+ else if ((i = txtfmt_osl_find_reserved(str)) != -1) prev = FMT_TYPE_RESERVED;
+ else if ((i = txtfmt_osl_find_preprocessor(str)) != -1) prev = FMT_TYPE_DIRECTIVE;
+
+ if (i > 0) {
+ if (prev == FMT_TYPE_DIRECTIVE) { /* can contain utf8 */
+ text_format_fill(&str, &fmt, prev, i);
+ }
+ else {
+ text_format_fill_ascii(&str, &fmt, prev, i);
+ }
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ }
+ prev = *fmt; fmt++; str++;
+ }
+
+ /* Terminate and add continuation char */
+ *fmt = '\0'; fmt++;
+ *fmt = cont;
+
+ /* If continuation has changed and we're allowed, process the next line */
+ if (cont != cont_orig && do_next && line->next) {
+ txtfmt_osl_format_line(st, line->next, do_next);
+ }
+
+ flatten_string_free(&fs);
+}
+
+void ED_text_format_register_osl(void)
+{
+ static TextFormatType tft = {NULL};
+ static const char *ext[] = {"osl", NULL};
+
+ tft.format_identifier = txtfmt_osl_format_identifier;
+ tft.format_line = txtfmt_osl_format_line;
+ tft.ext = ext;
+
+ ED_text_format_register(&tft);
+}
diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c
new file mode 100644
index 00000000000..a401e5dcdac
--- /dev/null
+++ b/source/blender/editors/space_text/text_format_py.c
@@ -0,0 +1,325 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 blender/editors/space_text/text_format_py.c
+ * \ingroup sptext
+ */
+
+#include <string.h>
+
+#include "BLI_blenlib.h"
+
+#include "DNA_text_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_text.h"
+
+#include "text_format.h"
+
+/* *** Local Functions (for format_line) *** */
+
+/* Checks the specified source string for a Python built-in function name. This
+ * name must start at the beginning of the source string and must be followed by
+ * a non-identifier (see text_check_identifier(char)) or null character.
+ *
+ * If a built-in function is found, the length of the matching name is returned.
+ * Otherwise, -1 is returned.
+ *
+ * See:
+ * http://docs.python.org/py3k/reference/lexical_analysis.html#keywords
+ */
+
+static int txtfmt_py_find_builtinfunc(const char *string)
+{
+ int i, len;
+ /* list is from...
+ * ", ".join(['"%s"' % kw
+ * for kw in __import__("keyword").kwlist
+ * if kw not in {"False", "None", "True", "def", "class"}])
+ *
+ * ... and for this code:
+ * print("\n".join(['else if (STR_LITERAL_STARTSWITH(string, "%s", len)) i = len;' % kw
+ * for kw in __import__("keyword").kwlist
+ * if kw not in {"False", "None", "True", "def", "class"}]))
+ */
+
+ if (STR_LITERAL_STARTSWITH(string, "and", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "as", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "assert", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "continue", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "del", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "elif", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "except", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "finally", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "from", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "global", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "import", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "in", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "is", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "lambda", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "nonlocal", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "not", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "or", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "pass", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "raise", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "return", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "try", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "with", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "yield", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
+}
+
+/* Checks the specified source string for a Python special name. This name must
+ * start at the beginning of the source string and must be followed by a non-
+ * identifier (see text_check_identifier(char)) or null character.
+ *
+ * If a special name is found, the length of the matching name is returned.
+ * Otherwise, -1 is returned. */
+
+static int txtfmt_py_find_specialvar(const char *string)
+{
+ int i, len;
+
+ if (STR_LITERAL_STARTSWITH(string, "def", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "class", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "definate") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
+}
+
+static int txtfmt_py_find_decorator(const char *string)
+{
+ if (string[0] == '@') {
+ int i = 1;
+ /* Whitespace is ok '@ foo' */
+ while (text_check_whitespace(string[i])) {
+ i++;
+ }
+ while (text_check_identifier(string[i])) {
+ i++;
+ }
+ return i;
+ }
+ return -1;
+}
+
+static int txtfmt_py_find_bool(const char *string)
+{
+ int i, len;
+
+ if (STR_LITERAL_STARTSWITH(string, "None", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "True", len)) i = len;
+ else if (STR_LITERAL_STARTSWITH(string, "False", len)) i = len;
+ else i = 0;
+
+ /* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */
+ if (i == 0 || text_check_identifier(string[i]))
+ return -1;
+ return i;
+}
+
+static char txtfmt_py_format_identifier(const char *str)
+{
+ char fmt;
+ if ((txtfmt_py_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL;
+ else if ((txtfmt_py_find_builtinfunc(str)) != -1) fmt = FMT_TYPE_KEYWORD;
+ else if ((txtfmt_py_find_decorator(str)) != -1) fmt = FMT_TYPE_RESERVED;
+ else fmt = FMT_TYPE_DEFAULT;
+ return fmt;
+}
+
+static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_next)
+{
+ FlattenString fs;
+ const char *str;
+ char *fmt;
+ char cont_orig, cont, find, prev = ' ';
+ int len, i;
+
+ /* Get continuation from previous line */
+ if (line->prev && line->prev->format != NULL) {
+ fmt = line->prev->format;
+ cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont) == cont);
+ }
+ else {
+ cont = FMT_CONT_NOP;
+ }
+
+ /* Get original continuation from this line */
+ if (line->format != NULL) {
+ fmt = line->format;
+ cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
+ BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
+ }
+ else {
+ cont_orig = 0xFF;
+ }
+
+ len = flatten_string(st, &fs, line->line);
+ str = fs.buf;
+ if (!text_check_format_len(line, len)) {
+ flatten_string_free(&fs);
+ return;
+ }
+ fmt = line->format;
+
+ while (*str) {
+ /* Handle escape sequences by skipping both \ and next char */
+ if (*str == '\\') {
+ *fmt = prev; fmt++; str++;
+ if (*str == '\0') break;
+ *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str);
+ continue;
+ }
+ /* Handle continuations */
+ else if (cont) {
+ /* Triple strings ("""...""" or '''...''') */
+ if (cont & FMT_CONT_TRIPLE) {
+ find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
+ if (*str == find && *(str + 1) == find && *(str + 2) == find) {
+ *fmt = FMT_TYPE_STRING; fmt++; str++;
+ *fmt = FMT_TYPE_STRING; fmt++; str++;
+ cont = FMT_CONT_NOP;
+ }
+ /* Handle other strings */
+ }
+ else {
+ find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
+ if (*str == find) cont = FMT_CONT_NOP;
+ }
+
+ *fmt = FMT_TYPE_STRING;
+ str += BLI_str_utf8_size_safe(str) - 1;
+ }
+ /* Not in a string... */
+ else {
+ /* Deal with comments first */
+ if (*str == '#') {
+ /* fill the remaining line */
+ text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format));
+ }
+ else if (*str == '"' || *str == '\'') {
+ /* Strings */
+ find = *str;
+ cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
+ if (*(str + 1) == find && *(str + 2) == find) {
+ *fmt = FMT_TYPE_STRING; fmt++; str++;
+ *fmt = FMT_TYPE_STRING; fmt++; str++;
+ cont |= FMT_CONT_TRIPLE;
+ }
+ *fmt = FMT_TYPE_STRING;
+ }
+ /* Whitespace (all ws. has been converted to spaces) */
+ else if (*str == ' ') {
+ *fmt = FMT_TYPE_WHITESPACE;
+ }
+ /* Numbers (digits not part of an identifier and periods followed by digits) */
+ else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
+ (*str == '.' && text_check_digit(*(str + 1))))
+ {
+ *fmt = FMT_TYPE_NUMERAL;
+ }
+ /* Booleans */
+ else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_py_find_bool(str)) != -1) {
+ if (i > 0) {
+ text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i);
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ /* Punctuation */
+ else if ((*str != '@') && text_check_delim(*str)) {
+ *fmt = FMT_TYPE_SYMBOL;
+ }
+ /* Identifiers and other text (no previous ws. or delims. so text continues) */
+ else if (prev == FMT_TYPE_DEFAULT) {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
+ else {
+ /* Special vars(v) or built-in keywords(b) */
+ /* keep in sync with 'txtfmt_py_format_identifier()' */
+ if ((i = txtfmt_py_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL;
+ else if ((i = txtfmt_py_find_builtinfunc(str)) != -1) prev = FMT_TYPE_KEYWORD;
+ else if ((i = txtfmt_py_find_decorator(str)) != -1) prev = FMT_TYPE_DIRECTIVE;
+
+ if (i > 0) {
+ if (prev == FMT_TYPE_DIRECTIVE) { /* can contain utf8 */
+ text_format_fill(&str, &fmt, prev, i);
+ }
+ else {
+ text_format_fill_ascii(&str, &fmt, prev, i);
+ }
+ }
+ else {
+ str += BLI_str_utf8_size_safe(str) - 1;
+ *fmt = FMT_TYPE_DEFAULT;
+ }
+ }
+ }
+ prev = *fmt; fmt++; str++;
+ }
+
+ /* Terminate and add continuation char */
+ *fmt = '\0'; fmt++;
+ *fmt = cont;
+
+ /* If continuation has changed and we're allowed, process the next line */
+ if (cont != cont_orig && do_next && line->next) {
+ txtfmt_py_format_line(st, line->next, do_next);
+ }
+
+ flatten_string_free(&fs);
+}
+
+void ED_text_format_register_py(void)
+{
+ static TextFormatType tft = {NULL};
+ static const char *ext[] = {"py", NULL};
+
+ tft.format_identifier = txtfmt_py_format_identifier;
+ tft.format_line = txtfmt_py_format_line;
+ tft.ext = ext;
+
+ ED_text_format_register(&tft);
+}
diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c
index 7dc3ec1ac60..605a08e587a 100644
--- a/source/blender/editors/space_text/text_header.c
+++ b/source/blender/editors/space_text/text_header.c
@@ -29,20 +29,11 @@
*/
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
/* file time checking */
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
#ifndef _WIN32
-# include <unistd.h>
#else
-# include <io.h>
-# include "BLI_winstuff.h"
#endif
#include "DNA_windowmanager_types.h"
@@ -50,7 +41,8 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
+
+#include "BLF_translation.h"
#include "BKE_context.h"
#include "BKE_screen.h"
@@ -130,7 +122,7 @@ void TEXT_OT_properties(wmOperatorType *ot)
uiPopupMenu *pup;
if (text) {
- pup = uiPupMenuBegin(C, "Text", ICON_NONE);
+ pup = uiPupMenuBegin(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");
@@ -144,7 +136,7 @@ void TEXT_OT_properties(wmOperatorType *ot)
uiPupMenuEnd(C, pup);
}
else {
- pup = uiPupMenuBegin(C, "File", ICON_NONE);
+ pup = uiPupMenuBegin(C, IFACE_("File"), ICON_NONE);
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new");
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open");
uiPupMenuEnd(C, pup);
@@ -156,7 +148,7 @@ void TEXT_OT_properties(wmOperatorType *ot)
uiPopupMenu *pup;
- pup = uiPupMenuBegin(C, "Edit", ICON_NONE);
+ pup = uiPupMenuBegin(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");
@@ -169,7 +161,7 @@ void TEXT_OT_properties(wmOperatorType *ot)
uiPopupMenu *pup;
if (text) {
- pup = uiPupMenuBegin(C, "Text", ICON_NONE);
+ pup = uiPupMenuBegin(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");
@@ -178,7 +170,7 @@ void TEXT_OT_properties(wmOperatorType *ot)
uiPupMenuEnd(C, pup);
}
else {
- pup = uiPupMenuBegin(C, "File", ICON_NONE);
+ pup = uiPupMenuBegin(C, IFACE_("File"), ICON_NONE);
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_new");
uiItemO(layout, NULL, ICON_NONE, "TEXT_OT_open");
uiPupMenuEnd(C, pup);
@@ -190,11 +182,14 @@ void TEXT_OT_properties(wmOperatorType *ot)
uiPopupMenu *pup;
- pup = uiPupMenuBegin(C, "Text", ICON_NONE);
- uiItemEnumO(layout, "TEXT_OT_move", "Top of File", 0, "type", FILE_TOP);
- uiItemEnumO(layout, "TEXT_OT_move", "Bottom of File", 0, "type", FILE_BOTTOM);
- uiItemEnumO(layout, "TEXT_OT_move", "Page Up", 0, "type", PREV_PAGE);
- uiItemEnumO(layout, "TEXT_OT_move", "Page Down", 0, "type", NEXT_PAGE);
+ pup = uiPupMenuBegin(C, IFACE_("Text"), ICON_NONE);
+ uiItemEnumO(layout, "TEXT_OT_move", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Top of File"),
+ 0, "type", FILE_TOP);
+ uiItemEnumO(layout, "TEXT_OT_move", CTX_IFACE_(BLF_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"),
+ 0, "type", NEXT_PAGE);
uiPupMenuEnd(C, pup);
}
#endif
diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h
index ea61644cee9..799bc49b624 100644
--- a/source/blender/editors/space_text/text_intern.h
+++ b/source/blender/editors/space_text/text_intern.h
@@ -54,12 +54,11 @@ void text_scroll_to_cursor(struct SpaceText *st, struct ScrArea *sa);
void text_update_cursor_moved(struct bContext *C);
/* TXT_OFFSET used to be 35 when the scrollbar was on the left... */
-#define TXT_OFFSET 15
-#define TXT_SCROLL_WIDTH 20
-#define TXT_SCROLL_SPACE 2
-#define TXT_LINE_SPACING 4 /* space between lines */
-
-#define TEXTXLOC (st->cwidth * st->linenrs_tot)
+#define TXT_OFFSET ((int)(0.75f * U.widget_unit))
+#define TXT_SCROLL_WIDTH U.widget_unit
+#define TXT_SCROLL_SPACE ((int)(0.1f * U.widget_unit))
+#define TXT_LINE_SPACING ((int)(0.2f * U.widget_unit)) /* space between lines */
+#define TEXTXLOC (st->cwidth * st->linenrs_tot)
#define SUGG_LIST_SIZE 7
#define SUGG_LIST_WIDTH 20
@@ -69,18 +68,6 @@ void text_update_cursor_moved(struct bContext *C);
#define TOOL_SUGG_LIST 0x01
#define TOOL_DOCUMENT 0x02
-typedef struct FlattenString {
- char fixedbuf[256];
- int fixedaccum[256];
-
- char *buf;
- int *accum;
- int pos, len;
-} FlattenString;
-
-int flatten_string(struct SpaceText *st, FlattenString *fs, const char *in);
-void flatten_string_free(FlattenString *fs);
-
int wrap_width(struct SpaceText *st, struct ARegion *ar);
void wrap_offset(struct SpaceText *st, struct ARegion *ar, struct TextLine *linein, int cursin, int *offl, int *offc);
void wrap_offset_in_line(struct SpaceText *st, struct ARegion *ar, struct TextLine *linep, int cursin, int *offl, int *offc);
@@ -156,6 +143,11 @@ void TEXT_OT_to_3d_object(struct wmOperatorType *ot);
void TEXT_OT_resolve_conflict(struct wmOperatorType *ot);
+int text_space_edit_poll(struct bContext *C);
+
+/* text_autocomplete.c */
+void TEXT_OT_autocomplete(struct wmOperatorType *ot);
+
/* space_text.c */
extern const char *text_context_dir[]; /* doc access */
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 5b7f92739ed..cdbb3e7c600 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -30,19 +30,14 @@
*/
-#include <stdlib.h>
#include <string.h>
-#include <ctype.h> /* ispunct */
-#include <sys/stat.h>
#include <errno.h>
#include "MEM_guardedalloc.h"
#include "DNA_text_types.h"
-#include "DNA_userdef_types.h"
#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
#include "BLF_translation.h"
@@ -72,11 +67,12 @@
#endif
#include "text_intern.h"
+#include "text_format.h"
/************************ poll ***************************/
-BLI_INLINE int text_pixel_x_to_index(SpaceText *st, const int x)
+BLI_INLINE int text_pixel_x_to_column(SpaceText *st, const int x)
{
/* add half the char width so mouse cursor selection is inbetween letters */
return (x + (st->cwidth / 2)) / st->cwidth;
@@ -102,7 +98,7 @@ static int text_edit_poll(bContext *C)
return 1;
}
-static int text_space_edit_poll(bContext *C)
+int text_space_edit_poll(bContext *C)
{
SpaceText *st = CTX_wm_space_text(C);
Text *text = CTX_data_edit_text(C);
@@ -165,11 +161,12 @@ void text_update_edited(Text *text)
static int text_new_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceText *st = CTX_wm_space_text(C);
+ Main *bmain = CTX_data_main(C);
Text *text;
PointerRNA ptr, idptr;
PropertyRNA *prop;
- text = BKE_text_add("Text");
+ text = BKE_text_add(bmain, "Text");
/* hook into UI */
uiIDContextProperty(C, &ptr, &prop);
@@ -230,6 +227,7 @@ static int text_open_cancel(bContext *UNUSED(C), wmOperator *op)
static int text_open_exec(bContext *C, wmOperator *op)
{
SpaceText *st = CTX_wm_space_text(C);
+ Main *bmain = CTX_data_main(C);
Text *text;
PropertyPointerRNA *pprop;
PointerRNA idptr;
@@ -238,7 +236,7 @@ static int text_open_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "filepath", str);
- text = BKE_text_load(str, G.main->name);
+ text = BKE_text_load(bmain, str, G.main->name);
if (!text) {
if (op->customdata) MEM_freeN(op->customdata);
@@ -280,7 +278,7 @@ static int text_open_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int text_open_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int text_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Text *text = CTX_data_edit_text(C);
char *path = (text && text->name) ? text->name : G.main->name;
@@ -541,7 +539,7 @@ static int text_save_as_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int text_save_as_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int text_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Text *text = CTX_data_edit_text(C);
char *str;
@@ -1013,7 +1011,7 @@ static int text_line_break_exec(bContext *C, wmOperator *UNUSED(op))
text_drawcache_tag_update(st, 0);
// double check tabs/spaces before splitting the line
- curts = setcurr_tab_spaces(text, space);
+ curts = txt_setcurr_tab_spaces(text, space);
txt_split_curline(text);
for (a = 0; a < curts; a++) {
@@ -1131,21 +1129,20 @@ static int text_convert_whitespace_exec(bContext *C, wmOperator *op)
TextLine *tmp;
FlattenString fs;
size_t a, j;
- char *text_check_line, *new_line;
+ char *new_line;
int extra, number; //unknown for now
int type = RNA_enum_get(op->ptr, "type");
-
- tmp = text->lines.first;
-
+
/* first convert to all space, this make it a lot easier to convert to tabs
* because there is no mixtures of ' ' && '\t' */
- while (tmp) {
- text_check_line = tmp->line;
+ for (tmp = text->lines.first; tmp; tmp = tmp->next) {
+ const char *text_check_line = tmp->line;
+ const int text_check_line_len = tmp->len;
number = flatten_string(st, &fs, text_check_line) + 1;
flatten_string_free(&fs);
new_line = MEM_callocN(number, "Converted_Line");
j = 0;
- for (a = 0; a < strlen(text_check_line); a++) { //foreach char in line
+ for (a = 0; a < text_check_line_len; a++) { //foreach char in line
if (text_check_line[a] == '\t') { //checking for tabs
//get the number of spaces this tabs is showing
//i don't like doing it this way but will look into it later
@@ -1175,20 +1172,19 @@ static int text_convert_whitespace_exec(bContext *C, wmOperator *op)
tmp->line = new_line;
tmp->len = strlen(new_line);
tmp->format = NULL;
- tmp = tmp->next;
}
if (type == TO_TABS) { // Converting to tabs
//start over from the beginning
- tmp = text->lines.first;
- while (tmp) {
- text_check_line = tmp->line;
+ for (tmp = text->lines.first; tmp; tmp = tmp->next) {
+ const char *text_check_line = tmp->line;
+ const int text_check_line_len = tmp->len;
extra = 0;
- for (a = 0; a < strlen(text_check_line); a++) {
+ for (a = 0; a < text_check_line_len; a++) {
number = 0;
for (j = 0; j < (size_t)st->tabnumber; j++) {
- if ((a + j) <= strlen(text_check_line)) { //check to make sure we are not pass the end of the line
+ if ((a + j) <= text_check_line_len) { //check to make sure we are not pass the end of the line
if (text_check_line[a + j] != ' ') {
number = 1;
}
@@ -1201,12 +1197,12 @@ static int text_convert_whitespace_exec(bContext *C, wmOperator *op)
}
if (extra > 0) { //got tabs make malloc and do what you have to do
- new_line = MEM_callocN(strlen(text_check_line) - (((st->tabnumber * extra) - extra) - 1), "Converted_Line");
+ new_line = MEM_callocN(text_check_line_len - (((st->tabnumber * extra) - extra) - 1), "Converted_Line");
extra = 0; //reuse vars
- for (a = 0; a < strlen(text_check_line); a++) {
+ for (a = 0; a < text_check_line_len; a++) {
number = 0;
for (j = 0; j < (size_t)st->tabnumber; j++) {
- if ((a + j) <= strlen(text_check_line)) { //check to make sure we are not pass the end of the line
+ if ((a + j) <= text_check_line_len) { //check to make sure we are not pass the end of the line
if (text_check_line[a + j] != ' ') {
number = 1;
}
@@ -1233,7 +1229,6 @@ static int text_convert_whitespace_exec(bContext *C, wmOperator *op)
tmp->len = strlen(new_line);
tmp->format = NULL;
}
- tmp = tmp->next;
}
}
@@ -1317,9 +1312,11 @@ void TEXT_OT_select_line(wmOperatorType *ot)
static int text_select_word_exec(bContext *C, wmOperator *UNUSED(op))
{
Text *text = CTX_data_edit_text(C);
+ /* don't advance cursor before stepping */
+ const bool use_init_step = false;
- txt_jump_left(text, 0);
- txt_jump_right(text, 1);
+ txt_jump_left(text, false, use_init_step);
+ txt_jump_right(text, true, use_init_step);
text_update_cursor_moved(C);
WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
@@ -1410,25 +1407,31 @@ static int text_get_cursor_rel(SpaceText *st, ARegion *ar, TextLine *linein, int
for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe(linein->line + j)) {
int chars;
+ int columns = BLI_str_utf8_char_width_safe(linein->line + j); /* = 1 for tab */
+
/* Mimic replacement of tabs */
ch = linein->line[j];
if (ch == '\t') {
chars = st->tabnumber - i % st->tabnumber;
ch = ' ';
}
- else chars = 1;
+ else {
+ chars = 1;
+ }
while (chars--) {
- if (rell == 0 && i - start == relc) {
+ if (rell == 0 && i - start <= relc && i + columns - start > relc) {
/* current position could be wrapped to next line */
/* this should be checked when end of current line would be reached */
selc = j;
found = 1;
}
- else if (i - end == relc) {
+ else if (i - end <= relc && i + columns - end > relc) {
curs = j;
}
- if (i - start >= max) {
+ if (i + columns - start > max) {
+ end = MIN2(end, i);
+
if (found) {
/* exact cursor position was found, check if it's */
/* still on needed line (hasn't been wrapped) */
@@ -1444,7 +1447,7 @@ static int text_get_cursor_rel(SpaceText *st, ARegion *ar, TextLine *linein, int
chop = 1;
rell--;
- if (rell == 0 && i - start >= relc) {
+ if (rell == 0 && i + columns - start > relc) {
selc = curs;
loop = 0;
break;
@@ -1461,7 +1464,7 @@ static int text_get_cursor_rel(SpaceText *st, ARegion *ar, TextLine *linein, int
break;
}
- if (rell == 0 && i - start >= relc) {
+ if (rell == 0 && i + columns - start > relc) {
selc = curs;
loop = 0;
break;
@@ -1470,7 +1473,7 @@ static int text_get_cursor_rel(SpaceText *st, ARegion *ar, TextLine *linein, int
endj = j;
chop = 0;
}
- i++;
+ i += columns;
}
}
@@ -1588,20 +1591,26 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel)
for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) {
int chars;
+ int columns = BLI_str_utf8_char_width_safe((*linep)->line + j); /* = 1 for tab */
+
/* Mimic replacement of tabs */
ch = (*linep)->line[j];
if (ch == '\t') {
chars = st->tabnumber - i % st->tabnumber;
ch = ' ';
}
- else chars = 1;
+ else {
+ chars = 1;
+ }
while (chars--) {
- if (i - start >= max) {
+ if (i + columns - start > max) {
+ end = MIN2(end, i);
+
*charp = endj;
if (j >= oldc) {
- if (ch == '\0') *charp = txt_utf8_index_to_offset((*linep)->line, start);
+ if (ch == '\0') *charp = txt_utf8_column_to_offset((*linep)->line, start);
loop = 0;
break;
}
@@ -1614,7 +1623,7 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel)
}
else if (ch == ' ' || ch == '-' || ch == '\0') {
if (j >= oldc) {
- *charp = txt_utf8_index_to_offset((*linep)->line, start);
+ *charp = txt_utf8_column_to_offset((*linep)->line, start);
loop = 0;
break;
}
@@ -1623,7 +1632,7 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel)
endj = j + 1;
chop = 0;
}
- i++;
+ i += columns;
}
}
@@ -1654,16 +1663,22 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel)
for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) {
int chars;
+ int columns = BLI_str_utf8_char_width_safe((*linep)->line + j); /* = 1 for tab */
+
/* Mimic replacement of tabs */
ch = (*linep)->line[j];
if (ch == '\t') {
chars = st->tabnumber - i % st->tabnumber;
ch = ' ';
}
- else chars = 1;
+ else {
+ chars = 1;
+ }
while (chars--) {
- if (i - start >= max) {
+ if (i + columns - start > max) {
+ end = MIN2(end, i);
+
if (chop) endj = BLI_str_prev_char_utf8((*linep)->line + j) - (*linep)->line;
if (endj >= oldc) {
@@ -1687,7 +1702,7 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel)
endj = j;
chop = 0;
}
- i++;
+ i += columns;
}
}
@@ -1719,7 +1734,9 @@ static void txt_wrap_move_up(SpaceText *st, ARegion *ar, short sel)
visible_lines = text_get_visible_lines(st, ar, (*linep)->line);
*charp = text_get_cursor_rel(st, ar, *linep, visible_lines - 1, col);
}
- else *charp = 0;
+ else {
+ *charp = 0;
+ }
}
if (!sel) txt_pop_sel(text);
@@ -1748,7 +1765,9 @@ static void txt_wrap_move_down(SpaceText *st, ARegion *ar, short sel)
*linep = (*linep)->next;
*charp = text_get_cursor_rel(st, ar, *linep, 0, col);
}
- else *charp = (*linep)->len;
+ else {
+ *charp = (*linep)->len;
+ }
}
if (!sel) txt_pop_sel(text);
@@ -1821,11 +1840,11 @@ static int text_move_cursor(bContext *C, int type, int select)
break;
case PREV_WORD:
- txt_jump_left(text, select);
+ txt_jump_left(text, select, true);
break;
case NEXT_WORD:
- txt_jump_right(text, select);
+ txt_jump_right(text, select, true);
break;
case PREV_CHAR:
@@ -1930,14 +1949,16 @@ static int text_jump_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int text_jump_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int text_jump_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- return WM_operator_props_dialog_popup(C, op, 200, 100);
+ return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 5 * UI_UNIT_Y);
}
void TEXT_OT_jump(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Jump";
ot->idname = "TEXT_OT_jump";
@@ -1949,7 +1970,8 @@ void TEXT_OT_jump(wmOperatorType *ot)
ot->poll = text_edit_poll;
/* properties */
- RNA_def_int(ot->srna, "line", 1, 1, INT_MAX, "Line", "Line number to jump to", 1, 10000);
+ 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);
}
/******************* delete operator **********************/
@@ -2085,7 +2107,7 @@ static int text_scroll_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static void text_scroll_apply(bContext *C, wmOperator *op, wmEvent *event)
+static void text_scroll_apply(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceText *st = CTX_wm_space_text(C);
ARegion *ar = CTX_wm_region(C);
@@ -2106,10 +2128,10 @@ static void text_scroll_apply(bContext *C, wmOperator *op, wmEvent *event)
if (!tsc->scrollbar) {
txtdelta[0] = -tsc->delta[0] / st->cwidth;
- txtdelta[1] = tsc->delta[1] / (st->lheight + TXT_LINE_SPACING);
+ txtdelta[1] = tsc->delta[1] / (st->lheight_dpi + TXT_LINE_SPACING);
tsc->delta[0] %= st->cwidth;
- tsc->delta[1] %= (st->lheight + TXT_LINE_SPACING);
+ tsc->delta[1] %= (st->lheight_dpi + TXT_LINE_SPACING);
}
else {
txtdelta[1] = -tsc->delta[1] * st->pix_per_line;
@@ -2142,7 +2164,7 @@ static void scroll_exit(bContext *C, wmOperator *op)
MEM_freeN(op->customdata);
}
-static int text_scroll_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int text_scroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
TextScroll *tsc = op->customdata;
SpaceText *st = CTX_wm_space_text(C);
@@ -2182,7 +2204,7 @@ static int text_scroll_cancel(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int text_scroll_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int text_scroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceText *st = CTX_wm_space_text(C);
TextScroll *tsc;
@@ -2204,7 +2226,7 @@ static int text_scroll_invoke(bContext *C, wmOperator *op, wmEvent *event)
tsc->old[1] = event->y;
/* Sensitivity of scroll set to 4pix per line/char */
tsc->delta[0] = (event->x - event->prevx) * st->cwidth / 4;
- tsc->delta[1] = (event->y - event->prevy) * st->lheight / 4;
+ tsc->delta[1] = (event->y - event->prevy) * st->lheight_dpi / 4;
tsc->first = 0;
tsc->scrollbar = 0;
text_scroll_apply(C, op, event);
@@ -2259,7 +2281,7 @@ static int text_region_scroll_poll(bContext *C)
return 1;
}
-static int text_scroll_bar_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int text_scroll_bar_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceText *st = CTX_wm_space_text(C);
ARegion *ar = CTX_wm_region(C);
@@ -2342,7 +2364,7 @@ typedef struct SetSelection {
short old[2];
} SetSelection;
-static int flatten_len(SpaceText *st, const char *str)
+static int flatten_width(SpaceText *st, const char *str)
{
int i, total = 0;
@@ -2350,20 +2372,30 @@ static int flatten_len(SpaceText *st, const char *str)
if (str[i] == '\t') {
total += st->tabnumber - total % st->tabnumber;
}
- else total++;
+ else {
+ total += BLI_str_utf8_char_width_safe(str + i);
+ }
}
return total;
}
-static int flatten_index_to_offset(SpaceText *st, const char *str, int index)
+static int flatten_column_to_offset(SpaceText *st, const char *str, int index)
{
- int i, j;
- for (i = 0, j = 0; i < index; j += BLI_str_utf8_size_safe(str + j))
+ int i = 0, j = 0, col;
+
+ while (*(str + j)) {
if (str[j] == '\t')
- i += st->tabnumber - i % st->tabnumber;
+ col = st->tabnumber - i % st->tabnumber;
else
- i++;
+ col = BLI_str_utf8_char_width_safe(str + j);
+
+ if (i + col > index)
+ break;
+
+ i += col;
+ j += BLI_str_utf8_size_safe(str + j);
+ }
return j;
}
@@ -2390,7 +2422,7 @@ static TextLine *get_first_visible_line(SpaceText *st, ARegion *ar, int *y)
static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, int y, int sel)
{
Text *text = st->text;
- int max = wrap_width(st, ar); /* view */
+ int max = wrap_width(st, ar); /* column */
int charp = -1; /* mem */
int loop = 1, found = 0; /* flags */
char ch;
@@ -2399,12 +2431,13 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
TextLine *linep = get_first_visible_line(st, ar, &y);
while (loop && linep) {
- int i = 0, start = 0, end = max; /* view */
+ int i = 0, start = 0, end = max; /* column */
int j = 0, curs = 0, endj = 0; /* mem */
int chop = 1; /* flags */
for (; loop; j += BLI_str_utf8_size_safe(linep->line + j)) {
int chars;
+ int columns = BLI_str_utf8_char_width_safe(linep->line + j); /* = 1 for tab */
/* Mimic replacement of tabs */
ch = linep->line[j];
@@ -2412,7 +2445,9 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
chars = st->tabnumber - i % st->tabnumber;
ch = ' ';
}
- else chars = 1;
+ else {
+ chars = 1;
+ }
while (chars--) {
/* Gone too far, go back to last wrap point */
@@ -2422,17 +2457,19 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
break;
/* Exactly at the cursor */
}
- else if (y == 0 && i - start == x) {
+ else if (y == 0 && i - start <= x && i + columns - start > x) {
/* current position could be wrapped to next line */
/* this should be checked when end of current line would be reached */
charp = curs = j;
found = 1;
/* Prepare curs for next wrap */
}
- else if (i - end == x) {
+ else if (i - end <= x && i + columns - end > x) {
curs = j;
}
- if (i - start >= max) {
+ if (i + columns - start > max) {
+ end = MIN2(end, i);
+
if (found) {
/* exact cursor position was found, check if it's */
/* still on needed line (hasn't been wrapped) */
@@ -2449,7 +2486,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
y--;
chop = 1;
- if (y == 0 && i - start >= x) {
+ if (y == 0 && i + columns - start > x) {
charp = curs;
loop = 0;
break;
@@ -2461,7 +2498,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
break;
}
- if (y == 0 && i - start >= x) {
+ if (y == 0 && i + columns - start > x) {
charp = curs;
loop = 0;
break;
@@ -2470,7 +2507,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
endj = j;
chop = 0;
}
- i++;
+ i += columns;
}
if (ch == '\0') break;
@@ -2503,13 +2540,13 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, int
{
Text *text = st->text;
text_update_character_width(st);
- y = (ar->winy - 2 - y) / (st->lheight + TXT_LINE_SPACING);
+ y = (ar->winy - 2 - y) / (st->lheight_dpi + TXT_LINE_SPACING);
if (st->showlinenrs) x -= TXT_OFFSET + TEXTXLOC;
else x -= TXT_OFFSET;
if (x < 0) x = 0;
- x = text_pixel_x_to_index(st, x) + st->left;
+ x = text_pixel_x_to_column(st, x) + st->left;
if (st->wordwrap) {
text_cursor_set_to_pos_wrapped(st, ar, x, y, sel);
@@ -2532,14 +2569,14 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, int
}
- w = flatten_len(st, (*linep)->line);
- if (x < w) *charp = flatten_index_to_offset(st, (*linep)->line, x);
+ w = flatten_width(st, (*linep)->line);
+ if (x < w) *charp = flatten_column_to_offset(st, (*linep)->line, x);
else *charp = (*linep)->len;
}
if (!sel) txt_pop_sel(text);
}
-static void text_cursor_set_apply(bContext *C, wmOperator *op, wmEvent *event)
+static void text_cursor_set_apply(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceText *st = CTX_wm_space_text(C);
ARegion *ar = CTX_wm_region(C);
@@ -2594,7 +2631,7 @@ static void text_cursor_set_exit(bContext *C, wmOperator *op)
MEM_freeN(ssel);
}
-static int text_set_selection_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int text_set_selection_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceText *st = CTX_wm_space_text(C);
SetSelection *ssel;
@@ -2619,7 +2656,7 @@ static int text_set_selection_invoke(bContext *C, wmOperator *op, wmEvent *event
return OPERATOR_RUNNING_MODAL;
}
-static int text_set_selection_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int text_set_selection_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
switch (event->type) {
case LEFTMOUSE:
@@ -2675,7 +2712,7 @@ static int text_cursor_set_exec(bContext *C, wmOperator *op)
return OPERATOR_PASS_THROUGH;
}
-static int text_cursor_set_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int text_cursor_set_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceText *st = CTX_wm_space_text(C);
@@ -2707,7 +2744,7 @@ void TEXT_OT_cursor_set(wmOperatorType *ot)
/******************* line number operator **********************/
-static int text_line_number_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int text_line_number_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
SpaceText *st = CTX_wm_space_text(C);
Text *text = CTX_data_edit_text(C);
@@ -2797,7 +2834,7 @@ static int text_insert_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int text_insert_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int text_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int ret;
@@ -3100,7 +3137,7 @@ static int text_resolve_conflict_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int text_resolve_conflict_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int text_resolve_conflict_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Text *text = CTX_data_edit_text(C);
uiPopupMenu *pup;
@@ -3110,27 +3147,31 @@ static int text_resolve_conflict_invoke(bContext *C, wmOperator *op, wmEvent *UN
case 1:
if (text->flags & TXT_ISDIRTY) {
/* modified locally and externally, ahhh. offer more possibilites. */
- pup = uiPupMenuBegin(C, "File Modified Outside and Inside Blender", ICON_NONE);
+ pup = uiPupMenuBegin(C, IFACE_("File Modified Outside and Inside Blender"), ICON_NONE);
layout = uiPupMenuLayout(pup);
- uiItemEnumO_ptr(layout, op->type, "Reload from disk (ignore local changes)", 0, "resolution", RESOLVE_RELOAD);
- uiItemEnumO_ptr(layout, op->type, "Save to disk (ignore outside changes)", 0, "resolution", RESOLVE_SAVE);
- uiItemEnumO_ptr(layout, op->type, "Make text internal (separate copy)", 0, "resolution", RESOLVE_MAKE_INTERNAL);
+ 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);
}
else {
- pup = uiPupMenuBegin(C, "File Modified Outside Blender", ICON_NONE);
+ pup = uiPupMenuBegin(C, IFACE_("File Modified Outside Blender"), ICON_NONE);
layout = uiPupMenuLayout(pup);
- uiItemEnumO_ptr(layout, op->type, "Reload from disk", 0, "resolution", RESOLVE_RELOAD);
- uiItemEnumO_ptr(layout, op->type, "Make text internal (separate copy)", 0, "resolution", RESOLVE_MAKE_INTERNAL);
- uiItemEnumO_ptr(layout, op->type, "Ignore", 0, "resolution", RESOLVE_IGNORE);
+ 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);
}
break;
case 2:
- pup = uiPupMenuBegin(C, "File Deleted Outside Blender", ICON_NONE);
+ pup = uiPupMenuBegin(C, IFACE_("File Deleted Outside Blender"), ICON_NONE);
layout = uiPupMenuLayout(pup);
- uiItemEnumO_ptr(layout, op->type, "Make text internal", 0, "resolution", RESOLVE_MAKE_INTERNAL);
- uiItemEnumO_ptr(layout, op->type, "Recreate file", 0, "resolution", RESOLVE_SAVE);
+ 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);
break;
}
diff --git a/source/blender/editors/space_text/text_python.c b/source/blender/editors/space_text/text_python.c
deleted file mode 100644
index 4c9b4b900cc..00000000000
--- a/source/blender/editors/space_text/text_python.c
+++ /dev/null
@@ -1,361 +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.
- * All rights reserved.
- *
- *
- * Contributor(s): Blender Foundation
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/space_text/text_python.c
- * \ingroup sptext
- */
-
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
-#include "DNA_text_types.h"
-
-#include "BKE_suggestions.h"
-#include "BKE_text.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
-
-#include "WM_types.h"
-
-#include "text_intern.h"
-
-int text_do_suggest_select(SpaceText *st, ARegion *ar)
-{
- SuggItem *item, *first, *last /* , *sel */ /* UNUSED */;
- TextLine *tmp;
- int l, x, y, w, h, i;
- int tgti, *top;
- int mval[2] = {0, 0};
-
- if (!st || !st->text) return 0;
- if (!texttool_text_is_active(st->text)) return 0;
-
- first = texttool_suggest_first();
- last = texttool_suggest_last();
- /* sel = texttool_suggest_selected(); */ /* UNUSED */
- top = texttool_suggest_top();
-
- if (!last || !first)
- return 0;
-
- /* Count the visible lines to the cursor */
- for (tmp = st->text->curl, l = -st->top; tmp; tmp = tmp->prev, l++) ;
- if (l < 0) return 0;
-
- text_update_character_width(st);
-
- if (st->showlinenrs) {
- x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET + TEXTXLOC - 4;
- }
- else {
- x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET - 4;
- }
- y = ar->winy - st->lheight * l - 2;
-
- w = SUGG_LIST_WIDTH * st->cwidth + 20;
- h = SUGG_LIST_SIZE * st->lheight + 8;
-
- // XXX getmouseco_areawin(mval);
-
- if (mval[0] < x || x + w < mval[0] || mval[1] < y - h || y < mval[1])
- return 0;
-
- /* Work out which of the items is at the top of the visible list */
- for (i = 0, item = first; i < *top && item->next; i++, item = item->next) ;
-
- /* Work out the target item index in the visible list */
- tgti = (y - mval[1] - 4) / st->lheight;
- if (tgti < 0 || tgti > SUGG_LIST_SIZE)
- return 1;
-
- for (i = tgti; i > 0 && item->next; i--, item = item->next) ;
- if (item)
- texttool_suggest_select(item);
- return 1;
-}
-
-void text_pop_suggest_list(void)
-{
- SuggItem *item, *sel;
- int *top, i;
-
- item = texttool_suggest_first();
- sel = texttool_suggest_selected();
- top = texttool_suggest_top();
-
- i = 0;
- while (item && item != sel) {
- item = item->next;
- i++;
- }
- if (i > *top + SUGG_LIST_SIZE - 1)
- *top = i - SUGG_LIST_SIZE + 1;
- else if (i < *top)
- *top = i;
-}
-
-static void get_suggest_prefix(Text *text, int offset)
-{
- int i, len;
- char *line, tmp[256];
-
- if (!text) return;
- if (!texttool_text_is_active(text)) return;
-
- line = text->curl->line;
- for (i = text->curc - 1 + offset; i >= 0; i--)
- if (!text_check_identifier(line[i]))
- break;
- i++;
- len = text->curc - i + offset;
- if (len > 255) {
- printf("Suggestion prefix too long\n");
- len = 255;
- }
- BLI_strncpy(tmp, line + i, len);
- tmp[len] = '\0';
- texttool_suggest_prefix(tmp);
-}
-
-static void confirm_suggestion(Text *text, int skipleft)
-{
- SuggItem *sel;
- int i, over = 0;
- char *line;
-
- if (!text) return;
- if (!texttool_text_is_active(text)) return;
-
- sel = texttool_suggest_selected();
- if (!sel) return;
-
- line = text->curl->line;
- i = text->curc - skipleft - 1;
- while (i >= 0) {
- if (!text_check_identifier(line[i]))
- break;
- over++;
- i--;
- }
-
- for (i = 0; i < skipleft; i++)
- txt_move_left(text, 0);
- for (i = 0; i < over; i++)
- txt_move_left(text, 1);
-
- txt_insert_buf(text, sel->name);
-
- for (i = 0; i < skipleft; i++)
- txt_move_right(text, 0);
-
- texttool_text_clear();
-}
-
-// XXX
-#define LR_SHIFTKEY 0
-#define LR_ALTKEY 0
-#define LR_CTRLKEY 0
-
-// XXX
-static int doc_scroll = 0;
-
-static short UNUSED_FUNCTION(do_texttools) (SpaceText * st, char ascii, unsigned short evnt, short val)
-{
- ARegion *ar = NULL; // XXX
- int qual = 0; // XXX
- int draw = 0, tools = 0, swallow = 0, scroll = 1;
- if (!texttool_text_is_active(st->text)) return 0;
- if (!st->text || st->text->id.lib) return 0;
-
- if (st->doplugins && texttool_text_is_active(st->text)) {
- if (texttool_suggest_first()) tools |= TOOL_SUGG_LIST;
- if (texttool_docs_get()) tools |= TOOL_DOCUMENT;
- }
-
- if (ascii) {
- if (tools & TOOL_SUGG_LIST) {
- if ((ascii != '_' && ascii != '*' && ispunct(ascii)) || text_check_whitespace(ascii)) {
- confirm_suggestion(st->text, 0);
- text_update_line_edited(st->text->curl);
- }
- else if ((st->overwrite && txt_replace_char(st->text, ascii)) || txt_add_char(st->text, ascii)) {
- get_suggest_prefix(st->text, 0);
- text_pop_suggest_list();
- swallow = 1;
- draw = 1;
- }
- }
- if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
-
- }
- else if (val == 1 && evnt) {
- switch (evnt) {
- case LEFTMOUSE:
- if (text_do_suggest_select(st, ar))
- swallow = 1;
- else {
- if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
- if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
- }
- draw = 1;
- break;
- case MIDDLEMOUSE:
- if (text_do_suggest_select(st, ar)) {
- confirm_suggestion(st->text, 0);
- text_update_line_edited(st->text->curl);
- swallow = 1;
- }
- else {
- if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
- if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
- }
- draw = 1;
- break;
- case ESCKEY:
- draw = swallow = 1;
- if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
- else if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
- else draw = swallow = 0;
- break;
- case RETKEY:
- if (tools & TOOL_SUGG_LIST) {
- confirm_suggestion(st->text, 0);
- text_update_line_edited(st->text->curl);
- swallow = 1;
- draw = 1;
- }
- if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
- break;
- case LEFTARROWKEY:
- case BACKSPACEKEY:
- if (tools & TOOL_SUGG_LIST) {
- if (qual)
- texttool_suggest_clear();
- else {
- /* Work out which char we are about to delete/pass */
- if (st->text->curl && st->text->curc > 0) {
- char ch = st->text->curl->line[st->text->curc - 1];
- if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
- get_suggest_prefix(st->text, -1);
- text_pop_suggest_list();
- }
- else
- texttool_suggest_clear();
- }
- else
- texttool_suggest_clear();
- }
- }
- if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
- break;
- case RIGHTARROWKEY:
- if (tools & TOOL_SUGG_LIST) {
- if (qual)
- texttool_suggest_clear();
- else {
- /* Work out which char we are about to pass */
- if (st->text->curl && st->text->curc < st->text->curl->len) {
- char ch = st->text->curl->line[st->text->curc + 1];
- if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
- get_suggest_prefix(st->text, 1);
- text_pop_suggest_list();
- }
- else
- texttool_suggest_clear();
- }
- else
- texttool_suggest_clear();
- }
- }
- if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
- break;
- case PAGEDOWNKEY:
- scroll = SUGG_LIST_SIZE - 1;
- case WHEELDOWNMOUSE:
- case DOWNARROWKEY:
- if (tools & TOOL_DOCUMENT) {
- doc_scroll++;
- swallow = 1;
- draw = 1;
- break;
- }
- else if (tools & TOOL_SUGG_LIST) {
- SuggItem *sel = texttool_suggest_selected();
- if (!sel) {
- texttool_suggest_select(texttool_suggest_first());
- }
- else {
- while (sel && sel != texttool_suggest_last() && sel->next && scroll--) {
- texttool_suggest_select(sel->next);
- sel = sel->next;
- }
- }
- text_pop_suggest_list();
- swallow = 1;
- draw = 1;
- break;
- }
- case PAGEUPKEY:
- scroll = SUGG_LIST_SIZE - 1;
- case WHEELUPMOUSE:
- case UPARROWKEY:
- if (tools & TOOL_DOCUMENT) {
- if (doc_scroll > 0) doc_scroll--;
- swallow = 1;
- draw = 1;
- break;
- }
- else if (tools & TOOL_SUGG_LIST) {
- SuggItem *sel = texttool_suggest_selected();
- while (sel && sel != texttool_suggest_first() && sel->prev && scroll--) {
- texttool_suggest_select(sel->prev);
- sel = sel->prev;
- }
- text_pop_suggest_list();
- swallow = 1;
- draw = 1;
- break;
- }
- case RIGHTSHIFTKEY:
- case LEFTSHIFTKEY:
- break;
- default:
- if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(), draw = 1;
- if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
- }
- }
-
- if (draw) {
- // XXX redraw_alltext();
- }
-
- return swallow;
-}
diff --git a/source/blender/editors/space_time/SConscript b/source/blender/editors/space_time/SConscript
index c08339ba692..32f02bff008 100644
--- a/source/blender/editors/space_time/SConscript
+++ b/source/blender/editors/space_time/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c
index 13c1938d77c..e5bd9e62c74 100644
--- a/source/blender/editors/space_time/space_time.c
+++ b/source/blender/editors/space_time/space_time.c
@@ -92,7 +92,7 @@ static void time_draw_sfra_efra(Scene *scene, View2D *v2d)
#define CACHE_DRAW_HEIGHT 3.0f
-static void time_draw_cache(SpaceTime *stime, Object *ob)
+static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
{
PTCacheID *pid;
ListBase pidlist;
@@ -102,7 +102,7 @@ static void time_draw_cache(SpaceTime *stime, Object *ob)
if (!(stime->cache_display & TIME_CACHE_DISPLAY) || (!ob))
return;
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
+ BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0);
/* iterate over pointcaches on the active object,
* add spacetimecache and vertex array for each */
@@ -128,6 +128,9 @@ static void time_draw_cache(SpaceTime *stime, Object *ob)
case PTCACHE_TYPE_DYNAMICPAINT:
if (!(stime->cache_display & TIME_CACHE_DYNAMICPAINT)) continue;
break;
+ case PTCACHE_TYPE_RIGIDBODY:
+ if (!(stime->cache_display & TIME_CACHE_RIGIDBODY)) continue;
+ break;
}
if (pid->cache->cached_frames == NULL)
@@ -193,6 +196,10 @@ static void time_draw_cache(SpaceTime *stime, Object *ob)
col[0] = 1.0; col[1] = 0.1; col[2] = 0.75;
col[3] = 0.1;
break;
+ case PTCACHE_TYPE_RIGIDBODY:
+ col[0] = 1.0; col[1] = 0.6; col[2] = 0.0;
+ col[3] = 0.1;
+ break;
default:
BLI_assert(0);
col[0] = 1.0; col[1] = 0.0; col[2] = 1.0;
@@ -499,7 +506,7 @@ static void time_main_area_draw(const bContext *C, ARegion *ar)
draw_markers_time(C, 0);
/* caches */
- time_draw_cache(stime, obact);
+ time_draw_cache(stime, obact, scene);
/* reset view matrix */
UI_view2d_view_restore(C);
@@ -648,6 +655,7 @@ static void time_init(wmWindowManager *UNUSED(wm), ScrArea *sa)
stime->cache_display |= TIME_CACHE_DISPLAY;
stime->cache_display |= (TIME_CACHE_SOFTBODY | TIME_CACHE_PARTICLES);
stime->cache_display |= (TIME_CACHE_CLOTH | TIME_CACHE_SMOKE | TIME_CACHE_DYNAMICPAINT);
+ stime->cache_display |= TIME_CACHE_RIGIDBODY;
}
static SpaceLink *time_duplicate(SpaceLink *sl)
diff --git a/source/blender/editors/space_userpref/SConscript b/source/blender/editors/space_userpref/SConscript
index 5c52e6f4c41..d5aa9304364 100644
--- a/source/blender/editors/space_userpref/SConscript
+++ b/source/blender/editors/space_userpref/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c
index 1ea3876f5cc..5ebbebec35b 100644
--- a/source/blender/editors/space_userpref/space_userpref.c
+++ b/source/blender/editors/space_userpref/space_userpref.c
@@ -105,14 +105,16 @@ static SpaceLink *userpref_duplicate(SpaceLink *sl)
/* add handlers, stuff you only do once or on area/region changes */
static void userpref_main_area_init(wmWindowManager *wm, ARegion *ar)
{
+ /* do not use here, the properties changed in userprefs do a system-wide refresh, then scroller jumps back */
+ /* ar->v2d.flag &= ~V2D_IS_INITIALISED; */
+
+ ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
+
ED_region_panels_init(wm, ar);
}
static void userpref_main_area_draw(const bContext *C, ARegion *ar)
{
- /* this solves "vibrating UI" bug #25422 */
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy);
-
ED_region_panels(C, ar, 1, NULL, -1);
}
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index 35dd88c3209..a04371a5ed9 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -54,6 +54,7 @@ set(SRC
view3d_iterators.c
view3d_ops.c
view3d_project.c
+ view3d_ruler.c
view3d_select.c
view3d_snap.c
view3d_toolbar.c
@@ -75,4 +76,8 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_FREESTYLE)
+ add_definitions(-DWITH_FREESTYLE)
+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 ffe35019960..b775c5bba59 100644
--- a/source/blender/editors/space_view3d/SConscript
+++ b/source/blender/editors/space_view3d/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
@@ -19,4 +45,7 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', '
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
+if env['WITH_BF_FREESTYLE']:
+ defs.append('WITH_FREESTYLE')
+
env.BlenderLib ( 'bf_editors_space_view3d', sources, Split(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 0649edc1ac4..57864854734 100644
--- a/source/blender/editors/space_view3d/drawanimviz.c
+++ b/source/blender/editors/space_view3d/drawanimviz.c
@@ -139,35 +139,38 @@ void draw_motion_path_instance(Scene *scene,
short sel = (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT);
float intensity; /* how faint */
+ int frame = sfra + i;
+ int blend_base = (abs(frame - CFRA) == 1) ? TH_CFRAME : TH_BACK; /* "bleed" cframe color to ease color blending */
+
/* set color
* - more intense for active/selected bones, less intense for unselected bones
* - black for before current frame, green for current frame, blue for after current frame
* - intensity decreases as distance from current frame increases
*/
#define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max - min)) + min)
- if ((sfra + i) < CFRA) {
+ if (frame < CFRA) {
/* black - before cfra */
if (sel) {
- // intensity = 0.5f;
+ /* intensity = 0.5f; */
intensity = SET_INTENSITY(sfra, i, CFRA, 0.25f, 0.75f);
}
else {
- //intensity = 0.8f;
+ /* intensity = 0.8f; */
intensity = SET_INTENSITY(sfra, i, CFRA, 0.68f, 0.92f);
}
- UI_ThemeColorBlend(TH_WIRE, TH_BACK, intensity);
+ UI_ThemeColorBlend(TH_WIRE, blend_base, intensity);
}
- else if ((sfra + i) > CFRA) {
+ else if (frame > CFRA) {
/* blue - after cfra */
if (sel) {
- //intensity = 0.5f;
+ /* intensity = 0.5f; */
intensity = SET_INTENSITY(CFRA, i, efra, 0.25f, 0.75f);
}
else {
- //intensity = 0.8f;
+ /* intensity = 0.8f; */
intensity = SET_INTENSITY(CFRA, i, efra, 0.68f, 0.92f);
}
- UI_ThemeColorBlend(TH_BONE_POSE, TH_BACK, intensity);
+ UI_ThemeColorBlend(TH_BONE_POSE, blend_base, intensity);
}
else {
/* green - on cfra */
@@ -232,21 +235,22 @@ void draw_motion_path_instance(Scene *scene,
col[3] = 255;
for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize) {
+ int frame = sfra + i;
char numstr[32];
float co[3];
/* only draw framenum if several consecutive highlighted points don't occur on same point */
if (i == 0) {
- sprintf(numstr, "%d", (i + sfra));
+ sprintf(numstr, " %d", frame);
mul_v3_m4v3(co, ob->imat, mpv->co);
view3d_cached_text_draw_add(co, numstr, 0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col);
}
- else if ((i > stepsize) && (i < len - stepsize)) {
+ else if ((i >= stepsize) && (i < len - stepsize)) {
bMotionPathVert *mpvP = (mpv - stepsize);
bMotionPathVert *mpvN = (mpv + stepsize);
if ((equals_v3v3(mpv->co, mpvP->co) == 0) || (equals_v3v3(mpv->co, mpvN->co) == 0)) {
- sprintf(numstr, "%d", (sfra + i));
+ sprintf(numstr, " %d", frame);
mul_v3_m4v3(co, ob->imat, mpv->co);
view3d_cached_text_draw_add(co, numstr, 0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col);
}
@@ -286,12 +290,13 @@ void draw_motion_path_instance(Scene *scene,
UI_GetThemeColor3ubv(TH_VERTEX_SELECT, col);
col[3] = 255;
- glPointSize(4.0f); // XXX perhaps a bit too big
+ glPointSize(4.0f);
glColor3ubv(col);
glBegin(GL_POINTS);
for (i = 0, mpv = mpv_start; i < len; i++, mpv++) {
- float mframe = (float)(sfra + i);
+ int frame = sfra + i;
+ float mframe = (float)(frame);
if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe))
glVertex3fv(mpv->co);
@@ -309,7 +314,7 @@ void draw_motion_path_instance(Scene *scene,
if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) {
char numstr[32];
- sprintf(numstr, "%d", (sfra + i));
+ sprintf(numstr, " %d", (sfra + i));
mul_v3_m4v3(co, ob->imat, mpv->co);
view3d_cached_text_draw_add(co, numstr, 0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col);
}
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index f37437b159d..cb685b59b64 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -144,7 +144,7 @@ static void cp_shade_color3ub(unsigned char cp[3], const int offset)
}
/* This function sets the gl-color for coloring a certain bone (based on bcolor) */
-static short set_pchan_glColor(short colCode, int boneflag, short constflag)
+static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
{
switch (colCode) {
case PCHAN_COLOR_NORMAL:
@@ -184,7 +184,7 @@ static short set_pchan_glColor(short colCode, int boneflag, short constflag)
}
}
- return 1;
+ return true;
}
break;
@@ -196,7 +196,7 @@ static short set_pchan_glColor(short colCode, int boneflag, short constflag)
else
UI_ThemeColor(TH_BONE_SOLID);
- return 1;
+ return true;
}
break;
@@ -208,7 +208,7 @@ static short set_pchan_glColor(short colCode, int boneflag, short constflag)
else if (constflag & PCHAN_HAS_SPLINEIK) glColor4ub(200, 255, 0, 80);
else if (constflag & PCHAN_HAS_CONST) glColor4ub(0, 255, 120, 80);
- return 1;
+ return true;
}
else
return 0;
@@ -238,7 +238,7 @@ static short set_pchan_glColor(short colCode, int boneflag, short constflag)
else UI_ThemeColor(TH_BONE_SOLID);
}
- return 1;
+ return true;
}
break;
case PCHAN_COLOR_SPHEREBONE_END:
@@ -288,12 +288,12 @@ static short set_pchan_glColor(short colCode, int boneflag, short constflag)
UI_ThemeColorShade(TH_BACK, -30);
}
- return 1;
+ return true;
}
break;
}
- return 0;
+ return false;
}
static void set_ebone_glColor(const unsigned int boneflag)
@@ -1660,7 +1660,7 @@ static void bone_matrix_translate_y(float mat[4][4], float y)
/* assumes object is Armature with pose */
static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
const short dt, const unsigned char ob_wire_col[4],
- const short do_const_color, const short is_outline)
+ const bool do_const_color, const bool is_outline)
{
RegionView3D *rv3d = ar->regiondata;
Object *ob = base->object;
@@ -1670,7 +1670,8 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
GLfloat tmp;
float smat[4][4], imat[4][4], bmat[4][4];
int index = -1;
- short do_dashed = 3, draw_wire = FALSE;
+ short do_dashed = 3;
+ bool draw_wire = false;
int flag;
/* being set below */
@@ -1736,7 +1737,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
((G.f & G_PICKSEL) == 0 || (bone->flag & BONE_UNSELECTABLE) == 0))
{
if (bone->layer & arm->layer) {
- int use_custom = (pchan->custom) && !(arm->flag & ARM_NO_CUSTOM);
+ const bool use_custom = (pchan->custom) && !(arm->flag & ARM_NO_CUSTOM);
glPushMatrix();
if (use_custom && pchan->custom_tx) {
@@ -1767,7 +1768,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
if (use_custom) {
/* if drawwire, don't try to draw in solid */
if (pchan->bone->flag & BONE_DRAWWIRE) {
- draw_wire = 1;
+ draw_wire = true;
}
else {
draw_custom_bone(scene, v3d, rv3d, pchan->custom,
@@ -1801,7 +1802,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
/* very very confusing... but in object mode, solid draw, we cannot do glLoadName yet,
* stick bones and/or wire custom-shapes are drawn in next loop
*/
- if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) == 0 && (draw_wire == 0)) {
+ if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) == 0 && (draw_wire == false)) {
/* object tag, for bordersel optim */
glLoadName(index & 0xFFFF);
index = -1;
@@ -1810,7 +1811,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
/* draw custom bone shapes as wireframes */
if (!(arm->flag & ARM_NO_CUSTOM) &&
- ((draw_wire) || (dt <= OB_WIRE)) )
+ (draw_wire || (dt <= OB_WIRE)) )
{
if (arm->flag & ARM_POSEMODE)
index = base->selcol;
@@ -2384,7 +2385,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base
BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
BKE_pose_where_is(scene, ob);
- draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, TRUE, FALSE);
+ draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false);
}
glDisable(GL_BLEND);
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
@@ -2466,7 +2467,7 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *
BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
BKE_pose_where_is(scene, ob);
- draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, TRUE, FALSE);
+ draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false);
}
glDisable(GL_BLEND);
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
@@ -2539,7 +2540,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
if (CFRA != cfrao) {
BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
BKE_pose_where_is(scene, ob);
- draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, TRUE, FALSE);
+ draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false);
}
}
@@ -2554,7 +2555,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
if (CFRA != cfrao) {
BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
BKE_pose_where_is(scene, ob);
- draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, TRUE, FALSE);
+ draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false);
}
}
}
@@ -2579,16 +2580,16 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
/* called from drawobject.c, return 1 if nothing was drawn
* (ob_wire_col == NULL) when drawing ghost */
-int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
- const short dt, const short dflag, const unsigned char ob_wire_col[4],
- const short is_outline)
+bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
+ const short dt, const short dflag, const unsigned char ob_wire_col[4],
+ const bool is_outline)
{
Object *ob = base->object;
bArmature *arm = ob->data;
- int retval = 0;
+ bool retval = false;
if (v3d->flag2 & V3D_RENDER_OVERRIDE)
- return 1;
+ return true;
if (dt > OB_WIRE && !ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
/* we use color for solid lighting */
@@ -2652,7 +2653,7 @@ int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
UI_ThemeColor(TH_WIRE); /* restore, for extra draw stuff */
}
else {
- retval = 1;
+ retval = true;
}
}
/* restore */
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index 0ecde350b00..b13f395b80b 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -236,31 +236,32 @@ static struct TextureDrawState {
Object *ob;
int is_lit, is_tex;
int color_profile;
+ bool use_backface_culling;
unsigned char obcol[4];
-} Gtexdraw = {NULL, 0, 0, 0, {0, 0, 0, 0}};
+} Gtexdraw = {NULL, 0, 0, 0, false, {0, 0, 0, 0}};
-static int set_draw_settings_cached(int clearcache, MTFace *texface, Material *ma, struct TextureDrawState gtexdraw)
+static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *ma, struct TextureDrawState gtexdraw)
{
static Material *c_ma;
static int c_textured;
static MTFace c_texface;
static int c_backculled;
- static int c_badtex;
+ static bool c_badtex;
static int c_lit;
static int c_has_texface;
Object *litob = NULL; /* to get mode to turn off mipmap in painting mode */
- int backculled = GEMAT_BACKCULL;
+ int backculled = GEMAT_BACKCULL || gtexdraw.use_backface_culling;
int alphablend = 0;
int textured = 0;
int lit = 0;
int has_texface = texface != NULL;
- int need_set_tpage = FALSE;
+ bool need_set_tpage = false;
if (clearcache) {
c_textured = c_lit = c_backculled = -1;
memset(&c_texface, 0, sizeof(MTFace));
- c_badtex = 0;
+ c_badtex = false;
c_has_texface = -1;
}
else {
@@ -274,7 +275,7 @@ static int set_draw_settings_cached(int clearcache, MTFace *texface, Material *m
if (ma) {
alphablend = ma->game.alpha_blend;
if (ma->mode & MA_SHLESS) lit = 0;
- backculled = ma->game.flag & GEMAT_BACKCULL;
+ backculled = (ma->game.flag & GEMAT_BACKCULL) || gtexdraw.use_backface_culling;
}
if (texface) {
@@ -306,7 +307,7 @@ static int set_draw_settings_cached(int clearcache, MTFace *texface, Material *m
}
else {
GPU_set_tpage(NULL, 0, 0);
- c_badtex = 0;
+ c_badtex = false;
}
c_textured = textured;
c_has_texface = has_texface;
@@ -344,7 +345,7 @@ static int set_draw_settings_cached(int clearcache, MTFace *texface, Material *m
static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
{
unsigned char obcol[4];
- int is_tex, solidtex;
+ bool is_tex, solidtex;
Mesh *me = ob->data;
/* XXX scene->obedit warning */
@@ -352,40 +353,35 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
/* texture draw is abused for mask selection mode, do this so wire draw
* with face selection in weight paint is not lit. */
if ((v3d->drawtype <= OB_WIRE) && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT))) {
- solidtex = FALSE;
+ solidtex = false;
Gtexdraw.is_lit = 0;
}
else if (v3d->drawtype == OB_SOLID || ((ob->mode & OB_MODE_EDIT) && v3d->drawtype != OB_TEXTURE)) {
/* draw with default lights in solid draw mode and edit mode */
- solidtex = TRUE;
+ solidtex = true;
Gtexdraw.is_lit = -1;
}
else {
/* draw with lights in the scene otherwise */
- solidtex = FALSE;
+ solidtex = false;
Gtexdraw.is_lit = GPU_scene_object_lights(scene, ob, v3d->lay, rv3d->viewmat, !rv3d->is_persp);
}
rgba_float_to_uchar(obcol, ob->col);
- if (solidtex || v3d->drawtype == OB_TEXTURE) is_tex = 1;
- else is_tex = 0;
+ if (solidtex || v3d->drawtype == OB_TEXTURE) is_tex = true;
+ else is_tex = false;
Gtexdraw.ob = ob;
Gtexdraw.is_tex = is_tex;
Gtexdraw.color_profile = BKE_scene_check_color_management_enabled(scene);
+ Gtexdraw.use_backface_culling = (v3d->flag2 & V3D_BACKFACE_CULLING) != 0;
memcpy(Gtexdraw.obcol, obcol, sizeof(obcol));
set_draw_settings_cached(1, NULL, NULL, Gtexdraw);
glShadeModel(GL_SMOOTH);
- if (v3d->flag2 & V3D_BACKFACE_CULLING) {
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
- }
- else {
- glDisable(GL_CULL_FACE);
- }
+ glCullFace(GL_BACK);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, (me->flag & ME_TWOSIDED) ? GL_TRUE : GL_FALSE);
}
@@ -396,6 +392,7 @@ static void draw_textured_end(void)
glShadeModel(GL_FLAT);
glDisable(GL_CULL_FACE);
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
/* XXX, bad patch - GPU_default_lights() calls
* glLightfv(GL_POSITION, ...) which
@@ -415,14 +412,14 @@ static void draw_textured_end(void)
static DMDrawOption draw_tface__set_draw_legacy(MTFace *tface, int has_mcol, int matnr)
{
Material *ma = give_current_material(Gtexdraw.ob, matnr + 1);
- int validtexture = 0;
+ bool invalidtexture = false;
if (ma && (ma->game.flag & GEMAT_INVISIBLE))
return DM_DRAW_OPTION_SKIP;
- validtexture = set_draw_settings_cached(0, tface, ma, Gtexdraw);
+ invalidtexture = set_draw_settings_cached(0, tface, ma, Gtexdraw);
- if (tface && validtexture) {
+ if (tface && invalidtexture) {
glColor3ub(0xFF, 0x00, 0xFF);
return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
}
@@ -431,7 +428,9 @@ static DMDrawOption draw_tface__set_draw_legacy(MTFace *tface, int has_mcol, int
return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
}
else if (!has_mcol) {
- if (tface) glColor3f(1.0, 1.0, 1.0);
+ if (tface) {
+ glColor3f(1.0, 1.0, 1.0);
+ }
else {
if (ma) {
float col[3];
@@ -440,7 +439,9 @@ static DMDrawOption draw_tface__set_draw_legacy(MTFace *tface, int has_mcol, int
glColor3fv(col);
}
- else glColor3f(1.0, 1.0, 1.0);
+ else {
+ glColor3f(1.0, 1.0, 1.0);
+ }
}
return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
}
@@ -457,25 +458,17 @@ static DMDrawOption draw_mcol__set_draw_legacy(MTFace *UNUSED(tface), int has_mc
return DM_DRAW_OPTION_NO_MCOL;
}
-static DMDrawOption draw_tface__set_draw(MTFace *tface, int has_mcol, int matnr)
+static DMDrawOption draw_tface__set_draw(MTFace *tface, int UNUSED(has_mcol), int matnr)
{
Material *ma = give_current_material(Gtexdraw.ob, matnr + 1);
if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return 0;
- if (tface && set_draw_settings_cached(0, tface, ma, Gtexdraw)) {
- return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
- }
- else if (tface && (tface->mode & TF_OBCOL)) {
- return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
- }
- else if (!has_mcol) {
- /* XXX: this return value looks wrong (and doesn't match comment) */
- return DM_DRAW_OPTION_NORMAL; /* Don't set color */
- }
- else {
- return DM_DRAW_OPTION_NORMAL; /* Set color from mcol */
- }
+ if (tface)
+ set_draw_settings_cached(0, tface, 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)
@@ -517,11 +510,11 @@ static void update_tface_color_layer(DerivedMesh *dm)
finalCol[i * 4 + j].r = 255;
}
}
- else if (tface && (tface->mode & TF_OBCOL)) {
+ else if (ma && (ma->shade_flag & MA_OBCOLOR)) {
for (j = 0; j < 4; j++) {
- finalCol[i * 4 + j].b = FTOCHAR(Gtexdraw.obcol[0]);
- finalCol[i * 4 + j].g = FTOCHAR(Gtexdraw.obcol[1]);
- finalCol[i * 4 + j].r = FTOCHAR(Gtexdraw.obcol[2]);
+ finalCol[i * 4 + j].b = Gtexdraw.obcol[0];
+ finalCol[i * 4 + j].g = Gtexdraw.obcol[1];
+ finalCol[i * 4 + j].r = Gtexdraw.obcol[2];
}
}
else if (!mcol) {
@@ -874,7 +867,7 @@ static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs)
if (ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node)) {
/* get openl texture */
int mipmap = 1;
- int bindcode = (ima) ? GPU_verify_image(ima, iuser, 0, 0, mipmap, FALSE) : 0;
+ int bindcode = (ima) ? GPU_verify_image(ima, iuser, 0, 0, mipmap, false) : 0;
float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
if (bindcode) {
@@ -947,7 +940,8 @@ static int tex_mat_set_face_editmesh_cb(void *userData, int index)
void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
Object *ob, DerivedMesh *dm, const int draw_flags)
{
- if ((!BKE_scene_use_new_shading_nodes(scene)) || (draw_flags & DRAW_MODIFIERS_PREVIEW)) {
+ /* if not cycles, or preview-modifiers, or drawing matcaps */
+ if ((!BKE_scene_use_new_shading_nodes(scene)) || (draw_flags & DRAW_MODIFIERS_PREVIEW) || (v3d->flag2 & V3D_SHOW_SOLID_MATCAP)) {
draw_mesh_textured_old(scene, v3d, rv3d, ob, dm, draw_flags);
return;
}
@@ -1026,10 +1020,10 @@ void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
{
DMSetDrawOptions facemask = NULL;
Mesh *me = ob->data;
- const short do_light = (v3d->drawtype >= OB_SOLID);
+ const bool do_light = (v3d->drawtype >= OB_SOLID);
/* hide faces in face select mode */
- if (draw_flags & DRAW_FACE_SELECT)
+ if (me->editflag & (ME_EDIT_PAINT_VERT_SEL | ME_EDIT_PAINT_FACE_SEL))
facemask = wpaint__setSolidDrawOptions_facemask;
if (ob->mode & OB_MODE_WEIGHT_PAINT) {
@@ -1076,13 +1070,19 @@ void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
if (draw_flags & DRAW_FACE_SELECT) {
draw_mesh_face_select(rv3d, me, dm);
}
- else if ((do_light == FALSE) || (ob->dtx & OB_DRAWWIRE)) {
+ else if ((do_light == false) || (ob->dtx & OB_DRAWWIRE)) {
+ const int use_depth = (v3d->flag & V3D_ZBUF_SELECT) || !(ob->mode & OB_MODE_WEIGHT_PAINT);
/* weight paint in solid mode, special case. focus on making the weights clear
* rather than the shading, this is also forced in wire view */
- bglPolygonOffset(rv3d->dist, 1.0);
- glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */
+ if (use_depth) {
+ bglPolygonOffset(rv3d->dist, 1.0);
+ glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */
+ }
+ else {
+ glDisable(GL_DEPTH_TEST);
+ }
glEnable(GL_BLEND);
glColor4ub(255, 255, 255, 96);
@@ -1091,8 +1091,14 @@ void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
dm->drawEdges(dm, 1, 1);
- bglPolygonOffset(rv3d->dist, 0.0);
- glDepthMask(1);
+ if (use_depth) {
+ bglPolygonOffset(rv3d->dist, 0.0);
+ glDepthMask(1);
+ }
+ else {
+ glEnable(GL_DEPTH_TEST);
+ }
+
glDisable(GL_LINE_STIPPLE);
glDisable(GL_BLEND);
}
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 055afda189f..8eae1571933 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -88,6 +88,7 @@
#include "ED_types.h"
#include "UI_resources.h"
+#include "UI_interface_icons.h"
#include "WM_api.h"
#include "BLF_api.h"
@@ -101,7 +102,7 @@ typedef enum eWireDrawMode {
} eWireDrawMode;
typedef struct drawDMVerts_userData {
- BMEditMesh *em; /* BMESH BRANCH ONLY */
+ BMEditMesh *em;
int sel;
BMVert *eve_act;
@@ -119,17 +120,21 @@ typedef struct drawDMVerts_userData {
} drawDMVerts_userData;
typedef struct drawDMEdgesSel_userData {
- BMEditMesh *em; /* BMESH BRANCH ONLY */
+ BMEditMesh *em;
unsigned char *baseCol, *selCol, *actCol;
BMEdge *eed_act;
} drawDMEdgesSel_userData;
typedef struct drawDMFacesSel_userData {
+#ifdef WITH_FREESTYLE
+ unsigned char *cols[4];
+#else
unsigned char *cols[3];
+#endif
- DerivedMesh *dm; /* BMESH BRANCH ONLY */
- BMEditMesh *em; /* BMESH BRANCH ONLY */
+ DerivedMesh *dm;
+ BMEditMesh *em;
BMFace *efa_act;
int *orig_index_mf_to_mpoly;
@@ -168,70 +173,83 @@ static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], con
}
/* this condition has been made more complex since editmode can draw textures */
-static int check_object_draw_texture(Scene *scene, View3D *v3d, int drawtype)
+static bool check_object_draw_texture(Scene *scene, View3D *v3d, int drawtype)
{
/* texture and material draw modes */
- if (ELEM(v3d->drawtype, OB_TEXTURE, OB_MATERIAL) && drawtype > OB_SOLID)
- return TRUE;
+ if (ELEM(v3d->drawtype, OB_TEXTURE, OB_MATERIAL) && drawtype > OB_SOLID) {
+ return true;
+ }
/* textured solid */
- if (v3d->drawtype == OB_SOLID && (v3d->flag2 & V3D_SOLID_TEX) && !BKE_scene_use_new_shading_nodes(scene))
- return TRUE;
+ if ((v3d->drawtype == OB_SOLID) &&
+ (v3d->flag2 & V3D_SOLID_TEX) &&
+ (BKE_scene_use_new_shading_nodes(scene) == false))
+ {
+ return true;
+ }
- return FALSE;
+ if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) {
+ return true;
+ }
+
+ return false;
}
-static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
+static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
{
if ((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0)
- return 0;
+ return false;
if (G.f & G_BACKBUFSEL)
- return 0;
+ return false;
if ((vd->flag & V3D_ZBUF_SELECT) == 0)
- return 1;
+ return true;
/* if its drawing textures with zbuf sel, then don't draw dots */
if (dt == OB_TEXTURE && vd->drawtype == OB_TEXTURE)
- return 0;
+ return false;
if ((vd->drawtype >= OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX))
- return 0;
+ return false;
- return 1;
+ return true;
}
/* ************************ */
/* check for glsl drawing */
-int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const short dt)
+bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt)
{
if (!GPU_glsl_support())
- return 0;
+ return false;
if (G.f & G_PICKSEL)
- return 0;
+ return false;
if (!check_object_draw_texture(scene, v3d, dt))
- return 0;
+ return false;
if (ob == OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
- return 0;
+ return false;
+
+ if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP)
+ return true;
+
if (BKE_scene_use_new_shading_nodes(scene))
- return 0;
+ return false;
return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID);
}
-static int check_alpha_pass(Base *base)
+static bool check_alpha_pass(Base *base)
{
if (base->flag & OB_FROMDUPLI)
- return 0;
+ return false;
if (G.f & G_PICKSEL)
- return 0;
+ return false;
if (base->object->mode & OB_MODE_ALL_PAINT)
- return 0;
+ return false;
return (base->object->dtx & OB_DRAWTRANSP);
}
@@ -589,32 +607,44 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char
glScalef(scale * sca_x, scale * sca_y, 1.0f);
if (ibuf && ibuf->rect) {
+ const bool use_clip = (U.glalphaclip != 1.0f);
/* Setup GL params */
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ if (use_clip) {
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GREATER, U.glalphaclip);
+ }
+
/* Use the object color and alpha */
glColor4fv(ob->col);
/* Draw the Image on the screen */
- glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, ibuf->rect);
+ glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect);
glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
glDisable(GL_BLEND);
+
+ if (use_clip) {
+ glDisable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GREATER, 0.0f);
+ }
}
if ((dflag & DRAW_CONSTCOLOR) == 0) {
glColor3ubv(ob_wire_col);
-
- /* Calculate the outline vertex positions */
- glBegin(GL_LINE_LOOP);
- glVertex2f(ofs_x, ofs_y);
- glVertex2f(ofs_x + ima_x, ofs_y);
- glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
- glVertex2f(ofs_x, ofs_y + ima_y);
- glEnd();
}
+ /* Calculate the outline vertex positions */
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(ofs_x, ofs_y);
+ glVertex2f(ofs_x + ima_x, ofs_y);
+ glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
+ glVertex2f(ofs_x, ofs_y + ima_y);
+ glEnd();
+
+
/* Reset GL settings */
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
@@ -739,7 +769,7 @@ void view3d_cached_text_draw_add(const float co[3],
memcpy(++vos, str, alloc_len);
}
-void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[4][4])
+void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, float mat[4][4])
{
RegionView3D *rv3d = ar->regiondata;
ListBase *strings = &CachedText[CachedTextLevel - 1];
@@ -755,7 +785,7 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, floa
(vos->flag & V3D_CACHE_TEXT_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob,
(vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0,
vos->vec, vos->sco,
- V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_OK)
+ V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
{
tot++;
}
@@ -793,17 +823,6 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, floa
}
for (vos = strings->first; vos; vos = vos->next) {
- /* too slow, reading opengl info while drawing is very bad,
- * better to see if we can use the zbuffer while in pixel space - campbell */
-#if 0
- if (v3d->zbuf && (vos->flag & V3D_CACHE_TEXT_ZBUF)) {
- gluProject(vos->vec[0], vos->vec[1], vos->vec[2], mats.modelview, mats.projection, (GLint *)mats.viewport, &ux, &uy, &uz);
- glReadPixels(ar->winrct.xmin + vos->mval[0] + vos->xoffs, ar->winrct.ymin + vos->mval[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
-
- if (uz > depth)
- continue;
- }
-#endif
if (vos->sco[0] != IS_CLIPPED) {
const char *str = (char *)(vos + 1);
@@ -1077,7 +1096,7 @@ static void draw_transp_spot_volume(Lamp *la, float x, float z)
}
static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
- const short dt, const short dflag, const unsigned char ob_wire_col[4])
+ const char dt, const short dflag, const unsigned char ob_wire_col[4])
{
Object *ob = base->object;
const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]);
@@ -1090,13 +1109,13 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
unsigned char col[4];
/* cone can't be drawn for duplicated lamps, because duplilist would be freed to */
/* the moment of view3d_draw_transp() call */
- const short is_view = (rv3d->persp == RV3D_CAMOB && v3d->camera == base->object);
- const short drawcone = ((dt > OB_WIRE) &&
- !(G.f & G_PICKSEL) &&
- (la->type == LA_SPOT) &&
- (la->mode & LA_SHOW_CONE) &&
- !(base->flag & OB_FROMDUPLI) &&
- !is_view);
+ const bool is_view = (rv3d->persp == RV3D_CAMOB && v3d->camera == base->object);
+ const bool drawcone = ((dt > OB_WIRE) &&
+ !(G.f & G_PICKSEL) &&
+ (la->type == LA_SPOT) &&
+ (la->mode & LA_SHOW_CONE) &&
+ !(base->flag & OB_FROMDUPLI) &&
+ !is_view);
if (drawcone && !v3d->transp) {
/* in this case we need to draw delayed */
@@ -1286,6 +1305,13 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
glVertex3fv(vvec_clip);
glEnd();
}
+ /* Else, draw spot direction (using distance as end limit, same as for Area lamp). */
+ else {
+ glBegin(GL_LINE_STRIP);
+ glVertex3f(0.0, 0.0, -circrad);
+ glVertex3f(0.0, 0.0, -la->dist);
+ glEnd();
+ }
}
else if (ELEM(la->type, LA_HEMI, LA_SUN)) {
@@ -1355,7 +1381,7 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
setlinestyle(0);
- if ((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == FALSE)) {
+ if ((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == false)) {
drawshadbuflimits(la, ob->obmat);
}
@@ -1387,20 +1413,22 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
}
}
-static void draw_limit_line(float sta, float end, unsigned int col)
+static void draw_limit_line(float sta, float end, const short dflag, unsigned int col)
{
glBegin(GL_LINES);
glVertex3f(0.0, 0.0, -sta);
glVertex3f(0.0, 0.0, -end);
glEnd();
- glPointSize(3.0);
- glBegin(GL_POINTS);
- cpack(col);
- glVertex3f(0.0, 0.0, -sta);
- glVertex3f(0.0, 0.0, -end);
- glEnd();
- glPointSize(1.0);
+ if (!(dflag & DRAW_PICKING)) {
+ glPointSize(3.0);
+ glBegin(GL_POINTS);
+ cpack(col);
+ glVertex3f(0.0, 0.0, -sta);
+ glVertex3f(0.0, 0.0, -end);
+ glEnd();
+ glPointSize(1.0);
+ }
}
@@ -1418,7 +1446,7 @@ static void draw_focus_cross(float dist, float size)
#ifdef VIEW3D_CAMERA_BORDER_HACK
unsigned char view3d_camera_border_hack_col[3];
-short view3d_camera_border_hack_test = FALSE;
+bool view3d_camera_border_hack_test = false;
#endif
/* ****************** draw clip data *************** */
@@ -1449,7 +1477,7 @@ static void draw_bundle_sphere(void)
static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D *v3d,
MovieClip *clip, MovieTrackingObject *tracking_object,
const short dflag, const unsigned char ob_wire_col[4],
- int *global_track_index, int draw_selected)
+ int *global_track_index, bool draw_selected)
{
MovieTracking *tracking = &clip->tracking;
MovieTrackingTrack *track;
@@ -1604,7 +1632,7 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D
static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d, MovieClip *clip,
const short dflag, const unsigned char ob_wire_col[4],
- int draw_selected)
+ const bool draw_selected)
{
MovieTracking *tracking = &clip->tracking;
MovieTrackingObject *tracking_object;
@@ -1653,13 +1681,13 @@ 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 short is_view = (rv3d->persp == RV3D_CAMOB && ob == v3d->camera);
+ const bool is_view = (rv3d->persp == RV3D_CAMOB && ob == v3d->camera);
MovieClip *clip = BKE_object_movieclip_get(scene, base->object, 0);
/* draw data for movie clip set as active for scene */
if (clip) {
- draw_viewport_reconstruction(scene, base, v3d, clip, dflag, ob_wire_col, FALSE);
- draw_viewport_reconstruction(scene, base, v3d, clip, dflag, ob_wire_col, TRUE);
+ draw_viewport_reconstruction(scene, base, v3d, clip, dflag, ob_wire_col, false);
+ draw_viewport_reconstruction(scene, base, v3d, clip, dflag, ob_wire_col, true);
}
#ifdef VIEW3D_CAMERA_BORDER_HACK
@@ -1674,7 +1702,7 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
glGetFloatv(GL_CURRENT_COLOR, col);
rgb_float_to_uchar(view3d_camera_border_hack_col, col);
}
- view3d_camera_border_hack_test = TRUE;
+ view3d_camera_border_hack_test = true;
return;
}
#endif
@@ -1741,10 +1769,9 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
glEnd();
}
- if (dflag == 0) {
- if (cam->flag & (CAM_SHOWLIMITS + CAM_SHOWMIST)) {
+ if ((dflag & DRAW_SCENESET) == 0) {
+ if (cam->flag & (CAM_SHOWLIMITS | CAM_SHOWMIST)) {
float nobmat[4][4];
- World *wrld;
/* draw in normalized object matrix space */
copy_m4_m4(nobmat, ob->obmat);
@@ -1755,15 +1782,17 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
glMultMatrixf(nobmat);
if (cam->flag & CAM_SHOWLIMITS) {
- draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
+ draw_limit_line(cam->clipsta, cam->clipend, dflag, 0x77FFFF);
/* qdn: was yafray only, now also enabled for Blender to be used with defocus composite node */
draw_focus_cross(BKE_camera_object_dof_distance(ob), cam->drawsize);
}
- wrld = scene->world;
- if (cam->flag & CAM_SHOWMIST)
- if (wrld) draw_limit_line(wrld->miststa, wrld->miststa + wrld->mistdist, 0xFFFFFF);
-
+ if (cam->flag & CAM_SHOWMIST) {
+ World *world = scene->world;
+ if (world) {
+ draw_limit_line(world->miststa, world->miststa + world->mistdist, dflag, 0xFFFFFF);
+ }
+ }
glPopMatrix();
}
}
@@ -1842,13 +1871,13 @@ static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
bglEnd();
}
-static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
+static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int actdef_wcol)
{
int index = ((w * lt->pntsv + v) * lt->pntsu) + u;
- if (use_wcol) {
+ if (actdef_wcol) {
float col[3];
- MDeformWeight *mdw = defvert_find_index(lt->dvert + index, use_wcol - 1);
+ MDeformWeight *mdw = defvert_find_index(lt->dvert + index, actdef_wcol - 1);
weight_to_rgb(col, mdw ? mdw->weight : 0.0f);
glColor3fv(col);
@@ -1869,7 +1898,8 @@ static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
Lattice *lt = ob->data;
DispList *dl;
int u, v, w;
- int use_wcol = FALSE, is_edit = (lt->editlatt != NULL);
+ int actdef_wcol = 0;
+ const bool is_edit = (lt->editlatt != NULL);
/* now we default make displist, this will modifiers work for non animated case */
if (ob->disp.first == NULL)
@@ -1882,7 +1912,7 @@ static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
cpack(0x004000);
if (ob->defbase.first && lt->dvert) {
- use_wcol = ob->actdef;
+ actdef_wcol = ob->actdef;
glShadeModel(GL_SMOOTH);
}
}
@@ -1896,16 +1926,16 @@ static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
int uxt = (u == 0 || u == lt->pntsu - 1);
if (w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
- drawlattice__point(lt, dl, u, v, w - 1, use_wcol);
- drawlattice__point(lt, dl, u, v, w, use_wcol);
+ drawlattice__point(lt, dl, u, v, w - 1, actdef_wcol);
+ drawlattice__point(lt, dl, u, v, w, actdef_wcol);
}
if (v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
- drawlattice__point(lt, dl, u, v - 1, w, use_wcol);
- drawlattice__point(lt, dl, u, v, w, use_wcol);
+ drawlattice__point(lt, dl, u, v - 1, w, actdef_wcol);
+ drawlattice__point(lt, dl, u, v, w, actdef_wcol);
}
if (u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
- drawlattice__point(lt, dl, u - 1, v, w, use_wcol);
- drawlattice__point(lt, dl, u, v, w, use_wcol);
+ drawlattice__point(lt, dl, u - 1, v, w, actdef_wcol);
+ drawlattice__point(lt, dl, u, v, w, actdef_wcol);
}
}
}
@@ -1913,7 +1943,7 @@ static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
glEnd();
/* restoration for weight colors */
- if (use_wcol)
+ if (actdef_wcol)
glShadeModel(GL_FLAT);
if (is_edit) {
@@ -2280,6 +2310,44 @@ static void draw_dm_edges_sharp(BMEditMesh *em, DerivedMesh *dm)
dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, em);
}
+#ifdef WITH_FREESTYLE
+
+static int draw_dm_test_freestyle_edge_mark(BMEditMesh *em, BMEdge *eed)
+{
+ FreestyleEdge *fed = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_FREESTYLE_EDGE);
+ if (!fed)
+ return 0;
+ return (fed->flag & FREESTYLE_EDGE_MARK) != 0;
+}
+
+/* Draw only Freestyle feature edges */
+static DMDrawOption draw_dm_edges_freestyle__setDrawOptions(void *userData, int index)
+{
+ BMEdge *eed = EDBM_edge_at_index(userData, index);
+
+ if (!eed)
+ return DM_DRAW_OPTION_SKIP;
+
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && draw_dm_test_freestyle_edge_mark(userData, eed))
+ return DM_DRAW_OPTION_NORMAL;
+ else
+ return DM_DRAW_OPTION_SKIP;
+}
+
+static void draw_dm_edges_freestyle(BMEditMesh *em, DerivedMesh *dm)
+{
+ dm->drawMappedEdges(dm, draw_dm_edges_freestyle__setDrawOptions, em);
+}
+
+static int draw_dm_test_freestyle_face_mark(BMEditMesh *em, BMFace *efa)
+{
+ FreestyleFace *ffa = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_FREESTYLE_FACE);
+ if (!ffa)
+ return 0;
+ return (ffa->flag & FREESTYLE_FACE_MARK) != 0;
+}
+
+#endif
/* Draw faces with color set based on selection
* return 2 for the active face so it renders with stipple enabled */
@@ -2298,7 +2366,11 @@ static DMDrawOption draw_dm_faces_sel__setDrawOptions(void *userData, int index)
return DM_DRAW_OPTION_STIPPLE;
}
else {
+#ifdef WITH_FREESTYLE
+ col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : draw_dm_test_freestyle_face_mark(data->em, efa) ? 3 : 0];
+#else
col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
+#endif
if (col[3] == 0)
return DM_DRAW_OPTION_SKIP;
glColor4ubv(col);
@@ -2329,8 +2401,13 @@ static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int
if (efa == data->efa_act || next_efa == data->efa_act)
return 0;
+#ifdef WITH_FREESTYLE
+ col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : draw_dm_test_freestyle_face_mark(data->em, efa) ? 3 : 0];
+ next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT) ? 1 : draw_dm_test_freestyle_face_mark(data->em, efa) ? 3 : 0];
+#else
col = data->cols[BM_elem_flag_test(efa, BM_ELEM_SELECT) ? 1 : 0];
next_col = data->cols[BM_elem_flag_test(next_efa, BM_ELEM_SELECT) ? 1 : 0];
+#endif
if (col[3] == 0 || next_col[3] == 0)
return 0;
@@ -2339,8 +2416,13 @@ static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int
}
/* also draws the active face */
+#ifdef WITH_FREESTYLE
+static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
+ unsigned char *selCol, unsigned char *actCol, unsigned char *markCol, BMFace *efa_act)
+#else
static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol,
unsigned char *selCol, unsigned char *actCol, BMFace *efa_act)
+#endif
{
drawDMFacesSel_userData data;
data.dm = dm;
@@ -2348,11 +2430,14 @@ static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *ba
data.em = em;
data.cols[1] = selCol;
data.cols[2] = actCol;
+#ifdef WITH_FREESTYLE
+ data.cols[3] = markCol;
+#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) {
+ 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;
}
@@ -2584,10 +2669,10 @@ static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitS
/* make the precision of the display value proportionate to the gridsize */
- if (grid < 0.01f) conv_float = "%.6g";
- else if (grid < 0.1f) conv_float = "%.5g";
- else if (grid < 1.0f) conv_float = "%.4g";
- else if (grid < 10.0f) conv_float = "%.3g";
+ if (grid <= 0.01f) conv_float = "%.6g";
+ else if (grid <= 0.1f) conv_float = "%.5g";
+ else if (grid <= 1.0f) conv_float = "%.4g";
+ else if (grid <= 10.0f) conv_float = "%.3g";
else conv_float = "%.2g";
if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
@@ -2615,7 +2700,7 @@ static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitS
if (unit->system) {
bUnit_AsString(numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3,
- unit->system, B_UNIT_LENGTH, do_split, FALSE);
+ unit->system, B_UNIT_LENGTH, do_split, false);
}
else {
sprintf(numstr, conv_float, len_v3v3(v1, v2));
@@ -2632,16 +2717,21 @@ static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitS
BMFace *f;
int n;
-#define DRAW_EM_MEASURE_STATS_FACEAREA() \
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { \
- mul_v3_fl(vmid, 1.0f / (float)n); \
- if (unit->system) \
- bUnit_AsString(numstr, sizeof(numstr), \
- (double)(area * unit->scale_length), \
- 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); \
- else \
- BLI_snprintf(numstr, sizeof(numstr), conv_float, area); \
- view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col); \
+#define DRAW_EM_MEASURE_STATS_FACEAREA() \
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { \
+ mul_v3_fl(vmid, 1.0f / (float)n); \
+ if (unit->system) { \
+ bUnit_AsString(numstr, sizeof(numstr), \
+ (double)(area * unit->scale_length * unit->scale_length), \
+ 3, unit->system, B_UNIT_AREA, do_split, false); \
+ view3d_cached_text_draw_add(vmid, numstr, 0, \
+ /* Metric system uses unicode "squared" sign! */ \
+ txt_flag ^ V3D_CACHE_TEXT_ASCII, col); \
+ } \
+ else { \
+ BLI_snprintf(numstr, sizeof(numstr), conv_float, area); \
+ view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col); \
+ } \
} (void)0
UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
@@ -2694,7 +2784,7 @@ static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitS
if (is_face_sel || do_moving) {
BMIter liter;
BMLoop *loop;
- int is_first = TRUE;
+ 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))) {
@@ -2710,7 +2800,7 @@ static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitS
mul_mat3_m4_v3(ob->obmat, v1);
mul_mat3_m4_v3(ob->obmat, v2);
}
- is_first = FALSE;
+ is_first = false;
}
if (do_global) {
@@ -2813,11 +2903,11 @@ static DMDrawOption draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
}
static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
- Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, const short dt)
+ Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, const char dt)
{
Mesh *me = ob->data;
- BMFace *efa_act = BM_active_face_get(em->bm, FALSE, FALSE); /* annoying but active faces is stored differently */
+ BMFace *efa_act = BM_active_face_get(em->bm, false, false); /* annoying but active faces is stored differently */
BMEdge *eed_act = NULL;
BMVert *eve_act = NULL;
@@ -2838,7 +2928,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
}
}
- EDBM_index_arrays_init(em, 1, 1, 1);
+ EDBM_index_arrays_ensure(em, BM_VERT | BM_EDGE | BM_FACE);
if (dt > OB_WIRE) {
if (check_object_draw_texture(scene, v3d, dt)) {
@@ -2885,10 +2975,16 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
if (me->drawflag & ME_DRAWFACES) { /* transp faces */
unsigned char col1[4], col2[4], col3[4];
+#ifdef WITH_FREESTYLE
+ unsigned char col4[4];
+#endif
UI_GetThemeColor4ubv(TH_FACE, col1);
UI_GetThemeColor4ubv(TH_FACE_SELECT, col2);
UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
+#ifdef WITH_FREESTYLE
+ UI_GetThemeColor4ubv(TH_FREESTYLE_FACE_MARK, col4);
+#endif
glEnable(GL_BLEND);
glDepthMask(0); /* disable write in zbuffer, needed for nice transp */
@@ -2897,7 +2993,14 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
if (check_object_draw_texture(scene, v3d, dt))
col1[3] = 0;
+#ifdef WITH_FREESTYLE
+ if (!(me->drawflag & ME_DRAW_FREESTYLE_FACE) || !CustomData_has_layer(&em->bm->pdata, CD_FREESTYLE_FACE))
+ col4[3] = 0;
+
+ draw_dm_faces_sel(em, cageDM, col1, col2, col3, col4, efa_act);
+#else
draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act);
+#endif
glDisable(GL_BLEND);
glDepthMask(1); /* restore write in zbuffer */
@@ -2906,14 +3009,19 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
/* 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
* */
- unsigned char col1[4], col2[4], col3[4];
- col1[3] = col2[3] = 0; /* don't draw */
+ /* 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 */
UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3);
glEnable(GL_BLEND);
glDepthMask(0); /* disable write in zbuffer, needed for nice transp */
+#ifdef WITH_FREESTYLE
+ draw_dm_faces_sel(em, cageDM, col1, col2, col3, col4, efa_act);
+#else
draw_dm_faces_sel(em, cageDM, col1, col2, col3, efa_act);
+#endif
glDisable(GL_BLEND);
glDepthMask(1); /* restore write in zbuffer */
@@ -2949,6 +3057,18 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
glLineWidth(1);
}
+#ifdef WITH_FREESTYLE
+ if (me->drawflag & ME_DRAW_FREESTYLE_EDGE && CustomData_has_layer(&em->bm->edata, CD_FREESTYLE_EDGE)) {
+ UI_ThemeColor(TH_FREESTYLE_EDGE_MARK);
+ glLineWidth(2);
+
+ draw_dm_edges_freestyle(em, cageDM);
+
+ glColor3ub(0,0,0);
+ glLineWidth(1);
+ }
+#endif
+
if (me->drawflag & ME_DRAWCREASES && CustomData_has_layer(&em->bm->edata, CD_CREASE)) {
draw_dm_creases(em, cageDM);
}
@@ -2989,16 +3109,14 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d,
bglPolygonOffset(rv3d->dist, 0.0);
GPU_disable_material();
}
-
- EDBM_index_arrays_free(em);
}
/* Mesh drawing routines */
static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
{
- if ((v3d->transp == FALSE) && /* not when we draw the transparent pass */
- (ob->mode & OB_MODE_ALL_PAINT) == FALSE) /* not when painting (its distracting) - campbell */
+ if ((v3d->transp == false) && /* not when we draw the transparent pass */
+ (ob->mode & OB_MODE_ALL_PAINT) == false) /* not when painting (its distracting) - campbell */
{
glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
glDepthMask(0);
@@ -3021,7 +3139,7 @@ static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
}
static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
- const short dt, const unsigned char ob_wire_col[4], const short dflag)
+ const char dt, const unsigned char ob_wire_col[4], const short dflag)
{
Object *ob = base->object;
Mesh *me = ob->data;
@@ -3230,7 +3348,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), me->drawflag & ME_ALLEDGES);
+ dm->drawEdges(dm, (dt == OB_WIRE || totface == 0), (ob->dtx & OB_DRAW_ALL_EDGES));
if (dt != OB_WIRE && (draw_wire == OBDRAW_WIRE_ON_DEPTH)) {
glDepthMask(1);
@@ -3239,11 +3357,15 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
}
if (is_obact && paint_vertsel_test(ob)) {
-
+ const int use_depth = (v3d->flag & V3D_ZBUF_SELECT);
glColor3f(0.0f, 0.0f, 0.0f);
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
-
+
+ if (!use_depth) glDisable(GL_DEPTH_TEST);
+ else bglPolygonOffset(rv3d->dist, 1.0);
drawSelectedVertices(dm, ob->data);
+ if (!use_depth) glEnable(GL_DEPTH_TEST);
+ else bglPolygonOffset(rv3d->dist, 0.0);
glPointSize(1.0f);
}
@@ -3251,14 +3373,15 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
}
/* returns 1 if nothing was drawn, for detecting to draw an object center */
-static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
- const short dt, const unsigned char ob_wire_col[4], const short dflag)
+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)
{
Object *ob = base->object;
Object *obedit = scene->obedit;
Mesh *me = ob->data;
BMEditMesh *em = me->edit_btmesh;
- int do_alpha_after = FALSE, drawlinked = 0, retval = 0, glsl, check_alpha, i;
+ int i;
+ bool do_alpha_after = false, drawlinked = false, retval = false;
/* If we are drawing shadows and any of the materials don't cast a shadow,
* then don't draw the object */
@@ -3266,7 +3389,7 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
for (i = 0; i < ob->totcol; ++i) {
Material *ma = give_current_material(ob, i);
if (ma && !(ma->mode & MA_SHADBUF)) {
- return 1;
+ return true;
}
}
}
@@ -3274,7 +3397,7 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
if (obedit && ob != obedit && ob->data == obedit->data) {
if (BKE_key_from_object(ob) || BKE_key_from_object(obedit)) {}
else if (ob->modifiers.first || obedit->modifiers.first) {}
- else drawlinked = 1;
+ else drawlinked = true;
}
/* backface culling */
@@ -3293,7 +3416,7 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
scene->customdata_mask);
if (dt > OB_WIRE) {
- glsl = draw_glsl_material(scene, ob, v3d, dt);
+ const bool glsl = draw_glsl_material(scene, ob, v3d, dt);
GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
}
@@ -3308,8 +3431,8 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
else {
/* ob->bb was set by derived mesh system, do NULL check just to be sure */
if (me->totpoly <= 4 || (!ob->bb || ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb))) {
- glsl = draw_glsl_material(scene, ob, v3d, dt);
- check_alpha = check_alpha_pass(base);
+ const bool glsl = draw_glsl_material(scene, ob, v3d, dt);
+ const bool check_alpha = check_alpha_pass(base);
if (dt == OB_SOLID || glsl) {
GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
@@ -3320,7 +3443,7 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
GPU_end_object_materials();
- if (me->totvert == 0) retval = 1;
+ if (me->totvert == 0) retval = true;
}
}
@@ -3350,11 +3473,11 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
/* ************** DRAW DISPLIST ****************** */
-static int draw_index_wire = 1;
-static int index3_nors_incr = 1;
+static bool draw_index_wire = true;
+static bool index3_nors_incr = true;
/* returns 1 when nothing was drawn */
-static int drawDispListwire(ListBase *dlbase)
+static bool drawDispListwire(ListBase *dlbase)
{
DispList *dl;
int parts, nr;
@@ -3416,7 +3539,7 @@ static int drawDispListwire(ListBase *dlbase)
#if 0
/* (ton) this code crashes for me when resolv is 86 or higher... no clue */
- glVertexPointer(3, GL_FLOAT, sizeof(float) * 3 * dl->nr, data + 3*nr);
+ glVertexPointer(3, GL_FLOAT, sizeof(float) * 3 * dl->nr, data + 3 * nr);
if (dl->flag & DL_CYCL_V)
glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
else
@@ -3444,11 +3567,11 @@ static int drawDispListwire(ListBase *dlbase)
glDisableClientState(GL_VERTEX_ARRAY);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- return 0;
+ return false;
}
static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
- const unsigned char ob_wire_col[4], int use_glsl)
+ const unsigned char ob_wire_col[4], const bool use_glsl)
{
DispList *dl;
GPUVertexAttribs gattribs;
@@ -3573,14 +3696,14 @@ static void drawCurveDMWired(Object *ob)
dm->drawEdges(dm, 1, 0);
}
-/* return 1 when nothing was drawn */
-static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const short dt)
+/* return true when nothing was drawn */
+static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt)
{
Object *ob = base->object;
DerivedMesh *dm = ob->derivedFinal;
if (!dm) {
- return 1;
+ return true;
}
if (dt > OB_WIRE && dm->getNumTessFaces(dm)) {
@@ -3602,15 +3725,15 @@ static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, B
drawCurveDMWired(ob);
}
- return 0;
+ return false;
}
/**
* Only called by #drawDispList
* \return 1 when nothing was drawn
*/
-static int drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
- const short dt, const short dflag, const unsigned char ob_wire_col[4])
+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])
{
Object *ob = base->object;
ListBase *lb = NULL;
@@ -3619,8 +3742,8 @@ static int drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d
const short render_only = (v3d->flag2 & V3D_RENDER_OVERRIDE);
const short solid = (dt > OB_WIRE);
- if (drawCurveDerivedMesh(scene, v3d, rv3d, base, dt) == 0) {
- return FALSE;
+ if (drawCurveDerivedMesh(scene, v3d, rv3d, base, dt) == false) {
+ return false;
}
switch (ob->type) {
@@ -3633,45 +3756,45 @@ static int drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d
if (solid) {
dl = lb->first;
if (dl == NULL) {
- return TRUE;
+ return true;
}
if (dl->nors == NULL) BKE_displist_normals_add(lb);
- index3_nors_incr = 0;
+ index3_nors_incr = false;
- if (BKE_displist_has_faces(lb) == 0) {
+ if (BKE_displist_has_faces(lb) == false) {
if (!render_only) {
- draw_index_wire = 0;
+ draw_index_wire = false;
drawDispListwire(lb);
- draw_index_wire = 1;
+ draw_index_wire = true;
}
}
else {
if (draw_glsl_material(scene, ob, v3d, dt)) {
GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
- drawDispListsolid(lb, ob, dflag, ob_wire_col, TRUE);
+ drawDispListsolid(lb, ob, dflag, ob_wire_col, true);
GPU_end_object_materials();
}
else {
GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
- drawDispListsolid(lb, ob, dflag, ob_wire_col, FALSE);
+ drawDispListsolid(lb, ob, dflag, ob_wire_col, false);
GPU_end_object_materials();
}
if (cu->editnurb && cu->bevobj == NULL && cu->taperobj == NULL && cu->ext1 == 0.0f && cu->ext2 == 0.0f) {
cpack(0);
- draw_index_wire = 0;
+ draw_index_wire = false;
drawDispListwire(lb);
- draw_index_wire = 1;
+ draw_index_wire = true;
}
}
- index3_nors_incr = 1;
+ index3_nors_incr = true;
}
else {
if (!render_only || (render_only && BKE_displist_has_faces(lb))) {
int retval;
- draw_index_wire = 0;
+ draw_index_wire = false;
retval = drawDispListwire(lb);
- draw_index_wire = 1;
+ draw_index_wire = true;
return retval;
}
}
@@ -3683,19 +3806,19 @@ static int drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d
if (solid) {
dl = lb->first;
if (dl == NULL) {
- return TRUE;
+ return true;
}
if (dl->nors == NULL) BKE_displist_normals_add(lb);
if (draw_glsl_material(scene, ob, v3d, dt)) {
GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
- drawDispListsolid(lb, ob, dflag, ob_wire_col, TRUE);
+ drawDispListsolid(lb, ob, dflag, ob_wire_col, true);
GPU_end_object_materials();
}
else {
GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
- drawDispListsolid(lb, ob, dflag, ob_wire_col, FALSE);
+ drawDispListsolid(lb, ob, dflag, ob_wire_col, false);
GPU_end_object_materials();
}
}
@@ -3709,19 +3832,19 @@ static int drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d
lb = &ob->disp;
if (lb->first == NULL) BKE_displist_make_mball(scene, ob);
if (lb->first == NULL) {
- return TRUE;
+ return true;
}
if (solid) {
if (draw_glsl_material(scene, ob, v3d, dt)) {
GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
- drawDispListsolid(lb, ob, dflag, ob_wire_col, TRUE);
+ drawDispListsolid(lb, ob, dflag, ob_wire_col, true);
GPU_end_object_materials();
}
else {
GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
- drawDispListsolid(lb, ob, dflag, ob_wire_col, FALSE);
+ drawDispListsolid(lb, ob, dflag, ob_wire_col, false);
GPU_end_object_materials();
}
}
@@ -3735,16 +3858,16 @@ static int drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d
return FALSE;
}
-static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
- const short dt, const short dflag, const unsigned char ob_wire_col[4])
+static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
+ const char dt, const short dflag, const unsigned char ob_wire_col[4])
{
- int retval;
+ bool retval;
/* backface culling */
if (v3d->flag2 & V3D_BACKFACE_CULLING) {
/* not all displists use same in/out normal direction convention */
glEnable(GL_CULL_FACE);
- glCullFace((base->object->type == OB_MBALL) ? GL_BACK : GL_FRONT);
+ glCullFace((base->object->type == OB_MBALL || base->object->derivedFinal) ? GL_BACK : GL_FRONT);
}
retval = drawDispList_nobackface(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
@@ -3850,7 +3973,9 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix
if (draw_as == PART_DRAW_AXIS) {
copy_v3_v3(vec2, state->co);
}
- else sub_v3_v3v3(vec2, state->co, vec);
+ else {
+ sub_v3_v3v3(vec2, state->co, vec);
+ }
add_v3_v3(vec, state->co);
copy_v3_v3(pdd->vd, vec); pdd->vd += 3;
@@ -3862,7 +3987,9 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix
if (draw_as == PART_DRAW_AXIS) {
copy_v3_v3(vec2, state->co);
}
- else sub_v3_v3v3(vec2, state->co, vec);
+ else {
+ sub_v3_v3v3(vec2, state->co, vec);
+ }
add_v3_v3(vec, state->co);
@@ -4659,9 +4786,11 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
if (!(point->flag & PEP_HIDE))
totkeys += point->totkey;
- if (edit->points && !(edit->points->keys->flag & PEK_USE_WCO))
- pd = pdata = MEM_callocN(totkeys * 3 * sizeof(float), "particle edit point data");
- cd = cdata = MEM_callocN(totkeys * (timed ? 4 : 3) * sizeof(float), "particle edit color data");
+ if (totkeys) {
+ if (edit->points && !(edit->points->keys->flag & PEK_USE_WCO))
+ pd = pdata = MEM_callocN(totkeys * 3 * sizeof(float), "particle edit point data");
+ cd = cdata = MEM_callocN(totkeys * (timed ? 4 : 3) * sizeof(float), "particle edit color data");
+ }
for (i = 0, point = edit->points; i < totpoint; i++, point++) {
if (point->flag & PEP_HIDE)
@@ -4898,9 +5027,9 @@ static void ob_draw_RE_motion(float com[3], float rotscale[3][3], float itw, flo
glEnd();
}
-/*place to add drawers */
+/* place to add drawers */
-static void tekenhandlesN(Nurb *nu, short sel, short hide_handles)
+static void drawhandlesN(Nurb *nu, short sel, short hide_handles)
{
BezTriple *bezt;
float *fp;
@@ -4960,7 +5089,7 @@ static void tekenhandlesN(Nurb *nu, short sel, short hide_handles)
glEnd();
}
-static void tekenhandlesN_active(Nurb *nu)
+static void drawhandlesN_active(Nurb *nu)
{
BezTriple *bezt;
float *fp;
@@ -4995,7 +5124,7 @@ static void tekenhandlesN_active(Nurb *nu)
glLineWidth(1);
}
-static void tekenvertsN(Nurb *nu, short sel, short hide_handles, void *lastsel)
+static void drawvertsN(Nurb *nu, short sel, short hide_handles, void *lastsel)
{
BezTriple *bezt;
BPoint *bp;
@@ -5251,7 +5380,7 @@ static void draw_editnurb(Object *ob, Nurb *nurb, int sel)
}
static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb,
- const short dt, const short dflag, const unsigned char ob_wire_col[4])
+ const char dt, const short dflag, const unsigned char ob_wire_col[4])
{
ToolSettings *ts = scene->toolsettings;
Object *ob = base->object;
@@ -5275,8 +5404,8 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
for (nu = nurb; nu; nu = nu->next) {
if (nu->type == CU_BEZIER) {
if (index == cu->actnu && !hide_handles)
- tekenhandlesN_active(nu);
- tekenhandlesN(nu, 0, hide_handles);
+ drawhandlesN_active(nu);
+ drawhandlesN(nu, 0, hide_handles);
}
index++;
}
@@ -5285,8 +5414,8 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
/* selected handles */
for (nu = nurb; nu; nu = nu->next) {
if (nu->type == CU_BEZIER && (cu->drawflag & CU_HIDE_HANDLES) == 0)
- tekenhandlesN(nu, 1, hide_handles);
- tekenvertsN(nu, 0, hide_handles, NULL);
+ drawhandlesN(nu, 1, hide_handles);
+ drawvertsN(nu, 0, hide_handles, NULL);
}
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
@@ -5337,7 +5466,7 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
for (nu = nurb; nu; nu = nu->next) {
- tekenvertsN(nu, 1, hide_handles, cu->lastsel);
+ drawvertsN(nu, 1, hide_handles, cu->lastsel);
}
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
@@ -5399,43 +5528,10 @@ static void draw_empty_cone(float size)
gluDeleteQuadric(qobj);
}
-/* draw points on curve speed handles */
-#if 0 /* XXX old animation system stuff */
-static void curve_draw_speed(Scene *scene, Object *ob)
-{
- Curve *cu = ob->data;
- IpoCurve *icu;
- BezTriple *bezt;
- float loc[4], dir[3];
- int a;
-
- if (cu->ipo == NULL)
- return;
-
- icu = cu->ipo->curve.first;
- if (icu == NULL || icu->totvert < 2)
- return;
-
- glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
- bglBegin(GL_POINTS);
-
- for (a = 0, bezt = icu->bezt; a < icu->totvert; a++, bezt++) {
- if (where_on_path(ob, bezt->vec[1][1], loc, dir)) {
- UI_ThemeColor((bezt->f2 & SELECT) && ob == OBACT ? TH_VERTEX_SELECT : TH_VERTEX);
- bglVertex3fv(loc);
- }
- }
-
- glPointSize(1.0);
- bglEnd();
-}
-#endif /* XXX old animation system stuff */
-
-
-static void draw_textcurs(float textcurs[4][2])
+static void draw_textcurs(RegionView3D *rv3d, float textcurs[4][2])
{
cpack(0);
-
+ bglPolygonOffset(rv3d->dist, -1.0);
set_inverted_drawing(1);
glBegin(GL_QUADS);
glVertex2fv(textcurs[0]);
@@ -5444,6 +5540,7 @@ static void draw_textcurs(float textcurs[4][2])
glVertex2fv(textcurs[3]);
glEnd();
set_inverted_drawing(0);
+ bglPolygonOffset(rv3d->dist, 0.0);
}
static void drawspiral(const float cent[3], float rad, float tmat[4][4], int start)
@@ -5451,11 +5548,11 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta
float vec[3], vx[3], vy[3];
const float tot_inv = (1.0f / (float)CIRCLE_RESOL);
int a;
- char inverse = FALSE;
+ bool inverse = false;
float x, y, fac;
if (start < 0) {
- inverse = TRUE;
+ inverse = true;
start = -start;
}
@@ -5534,7 +5631,7 @@ static void drawcircle_size(float size)
}
-/* needs fixing if non-identity matrice used */
+/* needs fixing if non-identity matrix used */
static void drawtube(const float vec[3], float radius, float height, float tmat[4][4])
{
float cur[3];
@@ -5556,7 +5653,8 @@ static void drawtube(const float vec[3], float radius, float height, float tmat[
glVertex3f(cur[0], cur[1] - radius, cur[2]);
glEnd();
}
-/* needs fixing if non-identity matrice used */
+
+/* needs fixing if non-identity matrix used */
static void drawcone(const float vec[3], float radius, float height, float tmat[4][4])
{
float cur[3];
@@ -5577,9 +5675,10 @@ static void drawcone(const float vec[3], float radius, float height, float tmat[
glVertex3f(cur[0], cur[1] - radius, cur[2]);
glEnd();
}
-/* return TRUE if nothing was drawn */
-static int drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
- const short dt, const short dflag, const unsigned char ob_wire_col[4])
+
+/* return true if nothing was drawn */
+static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
+ const char dt, const short dflag, const unsigned char ob_wire_col[4])
{
Object *ob = base->object;
MetaBall *mb;
@@ -5607,11 +5706,11 @@ static int drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
}
if (ml == NULL) {
- return TRUE;
+ return true;
}
if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
- return FALSE;
+ return false;
}
invert_m4_m4(imat, rv3d->viewmatob);
@@ -5625,7 +5724,6 @@ static int drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
}
while (ml) {
-
/* draw radius */
if (mb->editelems) {
if ((dflag & DRAW_CONSTCOLOR) == 0) {
@@ -5656,7 +5754,7 @@ static int drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
ml = ml->next;
}
- return FALSE;
+ return false;
}
static void draw_forcefield(Object *ob, RegionView3D *rv3d,
@@ -5910,6 +6008,15 @@ static void draw_bb_quadric(BoundBox *bb, char type)
glScalef(radius, radius, 2.0f * size[2]);
gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
}
+ else if (type == OB_BOUND_CAPSULE) {
+ float radius = size[0] > size[1] ? size[0] : size[1];
+ float length = size[2] > radius ? 2.0f * (size[2] - radius) : 0.0f;
+ glTranslatef(cent[0], cent[1], cent[2] - length * 0.5f);
+ gluCylinder(qobj, radius, radius, length, 8, 1);
+ gluSphere(qobj, radius, 8, 4);
+ glTranslatef(0.0, 0.0, length);
+ gluSphere(qobj, radius, 8, 4);
+ }
glPopMatrix();
gluDeleteQuadric(qobj);
@@ -5966,8 +6073,10 @@ static void drawtexspace(Object *ob)
copy_v3_v3(size, mb->size);
copy_v3_v3(loc, mb->loc);
}
- else return;
-
+ else {
+ return;
+ }
+
vec[0][0] = vec[1][0] = vec[2][0] = vec[3][0] = loc[0] - size[0];
vec[4][0] = vec[5][0] = vec[6][0] = vec[7][0] = loc[0] + size[0];
@@ -5997,24 +6106,24 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
Curve *cu = ob->data;
DerivedMesh *dm = ob->derivedFinal;
- int hasfaces = 0;
+ bool has_faces = false;
if (dm) {
- hasfaces = dm->getNumTessFaces(dm);
+ has_faces = dm->getNumTessFaces(dm);
}
else {
- hasfaces = BKE_displist_has_faces(&ob->disp);
+ has_faces = BKE_displist_has_faces(&ob->disp);
}
- if (hasfaces && ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
- draw_index_wire = 0;
+ if (has_faces && ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
+ draw_index_wire = false;
if (dm) {
draw_mesh_object_outline(v3d, ob, dm);
}
else {
drawDispListwire(&ob->disp);
}
- draw_index_wire = 1;
+ draw_index_wire = true;
}
}
else if (ob->type == OB_MBALL) {
@@ -6025,7 +6134,7 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
}
else if (ob->type == OB_ARMATURE) {
if (!(ob->mode & OB_MODE_POSE && base == scene->basact))
- draw_armature(scene, v3d, ar, base, OB_WIRE, FALSE, ob_wire_col, TRUE);
+ draw_armature(scene, v3d, ar, base, OB_WIRE, 0, ob_wire_col, true);
}
glLineWidth(1.0);
@@ -6050,7 +6159,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign
Curve *cu = ob->data;
if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
if (ob->type == OB_CURVE)
- draw_index_wire = 0;
+ draw_index_wire = false;
if (ob->derivedFinal) {
drawCurveDMWired(ob);
@@ -6060,7 +6169,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign
}
if (ob->type == OB_CURVE)
- draw_index_wire = 1;
+ draw_index_wire = true;
}
}
else if (ob->type == OB_MBALL) {
@@ -6212,6 +6321,34 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_
r_ob_wire_col[3] = 255;
}
+static void draw_object_matcap_check(Scene *scene, View3D *v3d, Object *ob)
+{
+ /* fixed rule, active object draws as matcap */
+ if (ob == OBACT) {
+ if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))
+ return;
+
+ if (v3d->defmaterial == NULL) {
+ extern Material defmaterial;
+
+ v3d->defmaterial = MEM_mallocN(sizeof(Material), "matcap material");
+ *(v3d->defmaterial) = defmaterial;
+ v3d->defmaterial->gpumaterial.first = v3d->defmaterial->gpumaterial.last = NULL;
+ v3d->defmaterial->preview = NULL;
+ }
+ /* first time users */
+ if (v3d->matcap_icon == 0)
+ v3d->matcap_icon = ICON_MATCAP_01;
+
+ if (v3d->defmaterial->preview == NULL)
+ v3d->defmaterial->preview = UI_icon_to_preview(v3d->matcap_icon);
+
+ /* signal to all material checks, gets cleared below */
+ v3d->flag2 |= V3D_SHOW_SOLID_MATCAP;
+ }
+
+}
+
/**
* main object drawing function, draws in selection
* \param dflag (draw flag) can be DRAW_PICKING and/or DRAW_CONSTCOLOR, DRAW_SCENESET
@@ -6228,7 +6365,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
unsigned char _ob_wire_col[4]; /* dont initialize this */
unsigned char *ob_wire_col = NULL; /* dont initialize this, use NULL crashes as a way to find invalid use */
int i, selstart, selend, empty_object = 0;
- short dt, dtx, zbufoff = 0;
+ short dtx;
+ char dt;
+ short zbufoff = 0;
const short is_obact = (ob == OBACT);
/* only once set now, will be removed too, should become a global standard */
@@ -6299,6 +6438,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
dt = MIN2(dt, ob->dt);
if (v3d->zbuf == 0 && dt > OB_WIRE) dt = OB_WIRE;
dtx = 0;
+
+ /* matcap check */
+ if (dt == OB_SOLID && (v3d->flag2 & V3D_SOLID_MATCAP))
+ draw_object_matcap_check(scene, v3d, ob);
/* faceselect exception: also draw solid when (dt == wire), except in editmode */
if (is_obact && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) {
@@ -6364,7 +6507,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
case OB_FONT:
cu = ob->data;
if (cu->editfont) {
- draw_textcurs(cu->editfont->textcurs);
+ draw_textcurs(rv3d, cu->editfont->textcurs);
if (cu->flag & CU_FAST) {
cpack(0xFFFFFF);
@@ -6530,7 +6673,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
else {
if (dt > OB_WIRE)
GPU_enable_material(0, NULL); /* we use default material */
- empty_object = draw_armature(scene, v3d, ar, base, dt, dflag, ob_wire_col, FALSE);
+ empty_object = draw_armature(scene, v3d, ar, base, dt, dflag, ob_wire_col, false);
if (dt > OB_WIRE)
GPU_disable_material();
}
@@ -6742,7 +6885,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
}
if (ob->gameflag & OB_BOUNDS) {
- if (ob->boundtype != ob->collision_boundtype || (dtx & OB_BOUNDBOX) == 0) {
+ if (ob->boundtype != ob->collision_boundtype || (dtx & OB_DRAWBOUNDOX) == 0) {
setlinestyle(2);
draw_bounding_volume(scene, ob, ob->collision_boundtype);
@@ -6756,7 +6899,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if (dtx & OB_AXIS) {
drawaxes(1.0f, OB_ARROWS);
}
- if (dtx & OB_BOUNDBOX) {
+ if (dtx & OB_DRAWBOUNDOX) {
draw_bounding_volume(scene, ob, ob->boundtype);
}
if (dtx & OB_TEXSPACE) {
@@ -6799,7 +6942,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
/* return warning, this is cached text draw */
invert_m4_m4(ob->imat, ob->obmat);
view3d_cached_text_draw_end(v3d, ar, 1, NULL);
-
+ /* return warning, clear temp flag */
+ v3d->flag2 &= ~V3D_SHOW_SOLID_MATCAP;
+
glLoadMatrixf(rv3d->viewmat);
if (zbufoff) {
@@ -6873,10 +7018,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
UI_make_axis_color(col1, col2, 'Z');
glColor3ubv(col2);
- cob = constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
+ cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
for (curcon = list->first; curcon; curcon = curcon->next) {
- bConstraintTypeInfo *cti = constraint_get_typeinfo(curcon);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(curcon);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -6930,7 +7075,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
}
}
- constraints_clear_evalob(cob);
+ BKE_constraints_clear_evalob(cob);
}
}
@@ -7091,14 +7236,28 @@ static DMDrawOption bbs_mesh_solid_hide2__setDrawOpts(void *userData, int index)
return DM_DRAW_OPTION_SKIP;
}
}
-static void bbs_mesh_solid(Scene *scene, Object *ob)
+
+static void bbs_mesh_solid_verts(Scene *scene, Object *ob)
+{
+ Mesh *me = ob->data;
+ DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
+ glColor3ub(0, 0, 0);
+
+ dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, GPU_enable_material, NULL, me, 0);
+
+ bbs_obmode_mesh_verts(ob, dm, 1);
+ bm_vertoffs = me->totvert + 1;
+ dm->release(dm);
+}
+
+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;
glColor3ub(0, 0, 0);
- if ((me->editflag & ME_EDIT_PAINT_MASK))
+ if ((me->editflag & ME_EDIT_PAINT_FACE_SEL))
dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts, GPU_enable_material, NULL, me, 0);
else
dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, GPU_enable_material, NULL, me, 0);
@@ -7123,7 +7282,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
DerivedMesh *dm = editbmesh_get_derived_cage(scene, ob, em, CD_MASK_BAREMESH);
- EDBM_index_arrays_init(em, 1, 1, 1);
+ EDBM_index_arrays_ensure(em, BM_VERT | BM_EDGE | BM_FACE);
bbs_mesh_solid_EM(em, scene, v3d, ob, dm, ts->selectmode & SCE_SELECT_FACE);
if (ts->selectmode & SCE_SELECT_FACE)
@@ -7149,27 +7308,17 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
bglPolygonOffset(rv3d->dist, 0.0);
dm->release(dm);
-
- EDBM_index_arrays_free(em);
}
else {
Mesh *me = ob->data;
- if ((me->editflag & ME_EDIT_VERT_SEL) &&
+ if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) &&
/* currently vertex select only supports weight paint */
(ob->mode & OB_MODE_WEIGHT_PAINT))
{
- DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
- glColor3ub(0, 0, 0);
-
- dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, GPU_enable_material, NULL, me, 0);
-
-
- bbs_obmode_mesh_verts(ob, dm, 1);
- bm_vertoffs = me->totvert + 1;
- dm->release(dm);
+ bbs_mesh_solid_verts(scene, ob);
}
else {
- bbs_mesh_solid(scene, ob);
+ bbs_mesh_solid_faces(scene, ob);
}
}
break;
@@ -7235,7 +7384,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r
if (dm) dm->release(dm);
}
-void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const short dt, int outline)
+void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const char dt, int outline)
{
if (ob == NULL)
return;
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index ebb48960b80..3933d8e4753 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -38,6 +38,7 @@
#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_blenlib.h"
@@ -73,61 +74,18 @@
#include "ED_mesh.h"
-
#include "BLF_api.h"
-
#include "view3d_intern.h" // own include
+struct GPUTexture;
-#ifdef _WIN32
-#include <time.h>
-#include <stdio.h>
-#include <conio.h>
-#include <windows.h>
-
-static LARGE_INTEGER liFrequency;
-static LARGE_INTEGER liStartTime;
-static LARGE_INTEGER liCurrentTime;
+// #define DEBUG_DRAW_TIME
-static void tstart(void)
-{
- QueryPerformanceFrequency(&liFrequency);
- QueryPerformanceCounter(&liStartTime);
-}
-static void tend(void)
-{
- QueryPerformanceCounter(&liCurrentTime);
-}
-static double tval(void)
-{
- return ((double)( (liCurrentTime.QuadPart - liStartTime.QuadPart) * (double)1000.0 / (double)liFrequency.QuadPart));
-}
-#else
-#include <sys/time.h>
-static struct timeval _tstart, _tend;
-static struct timezone tz;
-static void tstart(void)
-{
- gettimeofday(&_tstart, &tz);
-}
-static void tend(void)
-{
- gettimeofday(&_tend, &tz);
-}
- #if 0
-static double tval()
-{
- double t1, t2;
- t1 = ( double ) _tstart.tv_sec * 1000 + ( double ) _tstart.tv_usec / (1000);
- t2 = ( double ) _tend.tv_sec * 1000 + ( double ) _tend.tv_usec / (1000);
- return t2 - t1;
-}
- #endif
+#ifdef DEBUG_DRAW_TIME
+# include "PIL_time.h"
#endif
-struct GPUTexture;
-
static int intersect_edges(float *points, float a, float b, float c, float d, float edges[12][2][3])
{
int i;
@@ -147,7 +105,7 @@ static int intersect_edges(float *points, float a, float b, float c, float d, fl
return numpoints;
}
-static int convex(const float p0[3], const float up[3], const float a[3], const float b[3])
+static bool convex(const float p0[3], const float up[3], const float a[3], const float b[3])
{
/* Vec3 va = a-p0, vb = b-p0; */
float va[3], vb[3], tmp[3];
@@ -274,7 +232,10 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
return;
}
- tstart();
+#ifdef DEBUG_DRAW_TIME
+ TIMEIT_START(draw);
+#endif
+
/* generate flame spectrum texture */
#define SPEC_WIDTH 256
#define FIRE_THRESH 7
@@ -448,8 +409,8 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
* inserting previously found vertex into the plane equation */
/* d0 = (viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]); */ /* UNUSED */
- ds = (ABS(viewnormal[0]) * size[0] + ABS(viewnormal[1]) * size[1] + ABS(viewnormal[2]) * size[2]);
- dd = MAX3(sds->global_size[0], sds->global_size[1], sds->global_size[2]) / 128.f;
+ ds = (fabsf(viewnormal[0]) * size[0] + fabsf(viewnormal[1]) * size[1] + fabsf(viewnormal[2]) * size[2]);
+ dd = max_fff(sds->global_size[0], sds->global_size[1], sds->global_size[2]) / 128.f;
n = 0;
good_index = i;
@@ -521,8 +482,10 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
n++;
}
- tend();
- // printf ( "Draw Time: %f\n",(float) tval() );
+#ifdef DEBUG_DRAW_TIME
+ printf("Draw Time: %f\n", (float)TIMEIT_VALUE(draw));
+ TIMEIT_END(draw);
+#endif
if (tex_shadow)
GPU_texture_unbind(tex_shadow);
@@ -569,7 +532,7 @@ void draw_smoke_velocity(SmokeDomainSettings *domain, Object *ob)
float min[3];
float *cell_size = domain->cell_size;
- float step_size = ((float)MAX3(base_res[0], base_res[1], base_res[2])) / 16.f;
+ float step_size = ((float)max_iii(base_res[0], base_res[1], base_res[2])) / 16.f;
float vf = domain->scale / 16.f * 2.f; /* velocity factor */
glLineWidth(1.0f);
@@ -623,7 +586,7 @@ void draw_smoke_heat(SmokeDomainSettings *domain, Object *ob)
float min[3];
float *cell_size = domain->cell_size;
- float step_size = ((float)MAX3(base_res[0], base_res[1], base_res[2])) / 16.f;
+ float step_size = ((float)max_iii(base_res[0], base_res[1], base_res[2])) / 16.f;
float vf = domain->scale / 16.f * 2.f; /* velocity factor */
/* set first position so that it doesn't jump when domain moves */
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 1c31cd23e33..ef16090c39d 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -32,6 +32,7 @@
#include <string.h>
#include <stdio.h>
+#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -42,16 +43,20 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
-#include "BKE_object.h"
#include "BKE_context.h"
+#include "BKE_icons.h"
+#include "BKE_object.h"
#include "BKE_screen.h"
+#include "ED_render.h"
#include "ED_space_api.h"
#include "ED_screen.h"
#include "ED_object.h"
-#include "BIF_gl.h"
+#include "GPU_extensions.h"
+#include "GPU_material.h"
+#include "BIF_gl.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -117,7 +122,7 @@ ARegion *view3d_has_tools_region(ScrArea *sa)
BLI_insertlinkafter(&sa->regionbase, arhead, artool);
artool->regiontype = RGN_TYPE_TOOLS;
- artool->alignment = RGN_ALIGN_LEFT; //RGN_OVERLAP_LEFT;
+ artool->alignment = RGN_ALIGN_LEFT;
artool->flag = RGN_FLAG_HIDDEN;
}
@@ -143,7 +148,7 @@ RegionView3D *ED_view3d_context_rv3d(bContext *C)
if (rv3d == NULL) {
ScrArea *sa = CTX_wm_area(C);
if (sa && sa->spacetype == SPACE_VIEW3D) {
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ ARegion *ar = BKE_area_find_region_active_win(sa);
if (ar) {
rv3d = ar->regiondata;
}
@@ -154,12 +159,12 @@ RegionView3D *ED_view3d_context_rv3d(bContext *C)
/* ideally would return an rv3d but in some cases the region is needed too
* so return that, the caller can then access the ar->regiondata */
-int ED_view3d_context_user_region(bContext *C, View3D **v3d_r, ARegion **ar_r)
+bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_ar)
{
ScrArea *sa = CTX_wm_area(C);
- *v3d_r = NULL;
- *ar_r = NULL;
+ *r_v3d = NULL;
+ *r_ar = NULL;
if (sa && sa->spacetype == SPACE_VIEW3D) {
ARegion *ar = CTX_wm_region(C);
@@ -168,9 +173,9 @@ int ED_view3d_context_user_region(bContext *C, View3D **v3d_r, ARegion **ar_r)
if (ar) {
RegionView3D *rv3d = ar->regiondata;
if (rv3d && rv3d->viewlock == 0) {
- *v3d_r = v3d;
- *ar_r = ar;
- return 1;
+ *r_v3d = v3d;
+ *r_ar = ar;
+ return true;
}
else {
ARegion *ar_unlock_user = NULL;
@@ -191,21 +196,21 @@ int ED_view3d_context_user_region(bContext *C, View3D **v3d_r, ARegion **ar_r)
/* camera/perspective view get priority when the active region is locked */
if (ar_unlock_user) {
- *v3d_r = v3d;
- *ar_r = ar_unlock_user;
- return 1;
+ *r_v3d = v3d;
+ *r_ar = ar_unlock_user;
+ return true;
}
if (ar_unlock) {
- *v3d_r = v3d;
- *ar_r = ar_unlock;
- return 1;
+ *r_v3d = v3d;
+ *r_ar = ar_unlock;
+ return true;
}
}
}
}
- return 0;
+ return false;
}
/* Most of the time this isn't needed since you could assume the view matrix was
@@ -261,14 +266,11 @@ static SpaceLink *view3d_new(const bContext *C)
v3d->gridlines = 16;
v3d->gridsubdiv = 10;
v3d->drawtype = OB_SOLID;
+
+ v3d->gridflag = V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_FLOOR;
- v3d->gridflag |= V3D_SHOW_X;
- v3d->gridflag |= V3D_SHOW_Y;
- v3d->gridflag |= V3D_SHOW_FLOOR;
- v3d->gridflag &= ~V3D_SHOW_Z;
-
- v3d->flag |= V3D_SELECT_OUTLINE;
- v3d->flag2 |= V3D_SHOW_RECONSTRUCTION;
+ v3d->flag = V3D_SELECT_OUTLINE;
+ v3d->flag2 = V3D_SHOW_RECONSTRUCTION | V3D_SHOW_GPENCIL;
v3d->lens = 35.0f;
v3d->near = 0.01f;
@@ -338,11 +340,19 @@ static void view3d_free(SpaceLink *sl)
if (vd->localvd) MEM_freeN(vd->localvd);
if (vd->properties_storage) MEM_freeN(vd->properties_storage);
+
+ /* matcap material, its preview rect gets freed via icons */
+ if (vd->defmaterial) {
+ if (vd->defmaterial->gpumaterial.first)
+ GPU_material_free(vd->defmaterial);
+ BKE_previewimg_free(&vd->defmaterial->preview);
+ MEM_freeN(vd->defmaterial);
+ }
}
/* spacetype; init callback */
-static void view3d_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
+static void view3d_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
{
}
@@ -368,6 +378,8 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
/* copy or clear inside new stuff */
+ v3dn->defmaterial = NULL;
+
BLI_duplicatelist(&v3dn->bgpicbase, &v3do->bgpicbase);
v3dn->properties_storage = NULL;
@@ -459,7 +471,22 @@ static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar)
}
-static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
+static void view3d_main_area_exit(wmWindowManager *UNUSED(wm), ARegion *ar)
+{
+ RegionView3D *rv3d = ar->regiondata;
+
+ if (rv3d->render_engine) {
+ RE_engine_free(rv3d->render_engine);
+ rv3d->render_engine = NULL;
+ }
+
+ if (rv3d->gpuoffscreen) {
+ GPU_offscreen_free(rv3d->gpuoffscreen);
+ rv3d->gpuoffscreen = 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;
@@ -469,7 +496,17 @@ static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSE
return 0;
}
-static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
+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;
+ if (GS(id->name) == ID_GR)
+ return 1;
+ }
+ return 0;
+}
+
+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;
@@ -479,7 +516,7 @@ static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUS
return 0;
}
-static int view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
+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;
@@ -493,34 +530,50 @@ static int view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUS
return 0;
}
-
-static int view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
+static int view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
- if (ED_view3d_give_base_under_cursor(C, event->mval) ) {
- return 0;
+ if (event->ctrl)
+ return false;
+
+ if (!ED_view3d_give_base_under_cursor(C, event->mval)) {
+ return view3d_ima_drop_poll(C, drag, event);
}
- return view3d_ima_drop_poll(C, drag, event);
+ return 0;
}
-static int view3d_ima_ob_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
+static int view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
- if (ED_view3d_give_base_under_cursor(C, event->mval) ) {
+ Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
+
+ /* either holding and ctrl and no object, or dropping to empty */
+ if ((event->ctrl && !base) || (base && base->object->type == OB_EMPTY))
+ return view3d_ima_drop_poll(C, drag, event);
+
+ return 0;
+}
+
+static int view3d_ima_mesh_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
+{
+ Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
+
+ if (base && base->object->type == OB_MESH)
return view3d_ima_drop_poll(C, drag, event);
- }
return 0;
}
static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
{
ID *id = (ID *)drag->poin;
- PointerRNA ptr;
- /* need to put name in sub-operator in macro */
- ptr = RNA_pointer_get(drop->ptr, "OBJECT_OT_add_named");
- if (ptr.data)
- RNA_string_set(&ptr, "name", id->name + 2);
- else
- RNA_string_set(drop->ptr, "name", id->name + 2);
+ RNA_string_set(drop->ptr, "name", id->name + 2);
+}
+
+static void view3d_group_drop_copy(wmDrag *drag, wmDropBox *drop)
+{
+ ID *id = (ID *)drag->poin;
+
+ drop->opcontext = WM_OP_EXEC_DEFAULT;
+ RNA_string_set(drop->ptr, "name", id->name + 2);
}
static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop)
@@ -546,10 +599,12 @@ static void view3d_dropboxes(void)
{
ListBase *lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
- WM_dropbox_add(lb, "OBJECT_OT_add_named_cursor", view3d_ob_drop_poll, view3d_ob_drop_copy);
+ WM_dropbox_add(lb, "OBJECT_OT_add_named", view3d_ob_drop_poll, view3d_ob_drop_copy);
WM_dropbox_add(lb, "OBJECT_OT_drop_named_material", view3d_mat_drop_poll, view3d_id_drop_copy);
- WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_ob_drop_poll, view3d_id_path_drop_copy);
+ WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_mesh_drop_poll, view3d_id_path_drop_copy);
+ WM_dropbox_add(lb, "OBJECT_OT_drop_named_image", view3d_ima_empty_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
+ WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy);
}
@@ -574,6 +629,13 @@ static void view3d_main_area_free(ARegion *ar)
if (rv3d->depths->depths) MEM_freeN(rv3d->depths->depths);
MEM_freeN(rv3d->depths);
}
+ if (rv3d->sms) {
+ MEM_freeN(rv3d->sms);
+ }
+ if (rv3d->gpuoffscreen) {
+ GPU_offscreen_free(rv3d->gpuoffscreen);
+ }
+
MEM_freeN(rv3d);
ar->regiondata = NULL;
}
@@ -592,6 +654,7 @@ static void *view3d_main_area_duplicate(void *poin)
new->clipbb = MEM_dupallocN(rv3d->clipbb);
new->depths = NULL;
+ new->gpuoffscreen = NULL;
new->ri = NULL;
new->render_engine = NULL;
new->gpd = NULL;
@@ -635,8 +698,7 @@ static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, Scene *scene
static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
{
- bScreen *sc;
-
+
/* context changes */
switch (wmn->category) {
case NC_ANIMATION:
@@ -659,7 +721,8 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
case NC_SCENE:
switch (wmn->data) {
case ND_LAYER_CONTENT:
- view3d_recalc_used_layers(ar, wmn, wmn->reference);
+ if (wmn->reference)
+ view3d_recalc_used_layers(ar, wmn, wmn->reference);
ED_region_tag_redraw(ar);
break;
case ND_FRAME:
@@ -787,8 +850,10 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
case ND_SCREENSET:
/* screen was changed, need to update used layers due to NC_SCENE|ND_LAYER_CONTENT */
/* updates used layers only for View3D in active screen */
- sc = wmn->reference;
- view3d_recalc_used_layers(ar, wmn, sc->scene);
+ if (wmn->reference) {
+ bScreen *sc = wmn->reference;
+ view3d_recalc_used_layers(ar, wmn, sc->scene);
+ }
ED_region_tag_redraw(ar);
break;
}
@@ -1173,6 +1238,7 @@ void ED_spacetype_view3d(void)
art->keymapflag = ED_KEYMAP_GPENCIL;
art->draw = view3d_main_area_draw;
art->init = view3d_main_area_init;
+ art->exit = view3d_main_area_exit;
art->free = view3d_main_area_free;
art->duplicate = view3d_main_area_duplicate;
art->listener = view3d_main_area_listener;
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index bf14d915412..533bb30d8d1 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -158,7 +158,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
TransformProperties *tfp;
float median[NBR_TRANSFORM_PROPERTIES], ve_median[NBR_TRANSFORM_PROPERTIES];
int tot, totedgedata, totcurvedata, totlattdata, totskinradius, totcurvebweight;
- int meshdata = FALSE;
+ bool has_meshdata = false;
char defstr[320];
PointerRNA data_ptr;
@@ -179,34 +179,52 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
BMEdge *eed;
BMIter iter;
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- MVertSkin *vs;
-
- evedef = eve;
- tot++;
- add_v3_v3(&median[LOC_X], eve->co);
-
- vs = (MVertSkin *)CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MVERT_SKIN);
- if (vs) {
- add_v2_v2(&median[M_SKIN_X], vs->radius); /* Third val not used currently. */
- totskinradius++;
+ 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_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
+ const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
+
+ if (bm->totvertsel) {
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ evedef = eve;
+ tot++;
+ add_v3_v3(&median[LOC_X], eve->co);
+
+ /* TODO cd_vert_bweight_offset */
+ (void)cd_vert_bweight_offset;
+
+ if (cd_vert_skin_offset != -1) {
+ 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++;
+ }
}
}
}
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- float *f;
+ 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);
+ }
- totedgedata++;
- f = (float *)CustomData_bmesh_get(&bm->edata, eed->head.data, CD_CREASE);
- median[M_CREASE] += f ? *f : 0.0f;
+ if (cd_edge_crease_offset != -1) {
+ median[M_CREASE] += BM_ELEM_CD_GET_FLOAT(eed, cd_edge_crease_offset);
+ }
- f = (float *)CustomData_bmesh_get(&bm->edata, eed->head.data, CD_BWEIGHT);
- median[M_WEIGHT] += f ? *f : 0.0f;
+ totedgedata++;
+ }
+ }
}
}
+ else {
+ totedgedata = bm->totedgesel;
+ }
/* check for defgroups */
if (evedef)
@@ -235,7 +253,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
}
}
- meshdata = totedgedata || totskinradius;
+ has_meshdata = (totedgedata || totskinradius);
}
else if (ob->type == OB_CURVE || ob->type == OB_SURF) {
Curve *cu = ob->data;
@@ -342,7 +360,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
if (v3d->flag & V3D_GLOBAL_STATS)
mul_m4_v3(ob->obmat, &median[LOC_X]);
- if (meshdata) {
+ if (has_meshdata) {
if (totedgedata) {
median[M_CREASE] /= (float)totedgedata;
median[M_WEIGHT] /= (float)totedgedata;
@@ -365,7 +383,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
if (block) { /* buttons */
uiBut *but;
int yi = 200;
- const int buth = 20 * UI_DPI_ICON_FAC;
+ const int buth = 20 * UI_DPI_FAC;
const int but_margin = 2;
const char *c;
@@ -385,41 +403,43 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
uiBlockBeginAlign(block);
/* Should be no need to translate these. */
- but = uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "X:", 0, yi -= buth, 200, buth,
+ but = uiDefButF(block, 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, "Y:", 0, yi -= buth, 200, buth,
+ but = uiDefButF(block, 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, "Z:", 0, yi -= buth, 200, buth,
+ but = uiDefButF(block, 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);
if (totcurvebweight == tot) {
- uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "W:", 0, yi -= buth, 200, buth,
+ uiDefButF(block, 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"),
0, yi -= buth + but_margin, 100, buth,
- &v3d->flag, 0, 0, 0, 0, "Displays global values");
+ &v3d->flag, 0, 0, 0, 0, TIP_("Displays global values"));
uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, IFACE_("Local"),
100, yi, 100, buth,
- &v3d->flag, 0, 0, 0, 0, "Displays local values");
+ &v3d->flag, 0, 0, 0, 0, TIP_("Displays local values"));
uiBlockEndAlign(block);
/* Meshes... */
- if (meshdata) {
+ 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, 3, TIP_("Weight used by SubSurf modifier"));
+ totedgedata == 1 ? IFACE_("Crease:") : IFACE_("Mean Crease:"),
+ 0, yi -= buth + but_margin, 200, buth,
+ &(tfp->ve_median[M_CREASE]), 0.0, 1.0, 1, 3, TIP_("Weight used by SubSurf modifier"));
+ /* customdata layer added on demand */
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN,
- totedgedata == 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, 3, TIP_("Weight used by Bevel modifier"));
+ totedgedata == 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, 3, TIP_("Weight used by Bevel modifier"));
}
if (totskinradius) {
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN,
@@ -434,12 +454,12 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
}
/* Curve... */
else if (totcurvedata == 1) {
- uiDefButR(block, NUM, 0, "Weight", 0, yi -= buth + but_margin, 200, buth,
+ uiDefButR(block, NUM, 0, IFACE_("Weight"), 0, yi -= buth + but_margin, 200, buth,
&data_ptr, "weight_softbody", 0, 0.0, 1.0, 1, 3, NULL);
- uiDefButR(block, NUM, 0, "Radius", 0, yi -= buth + but_margin, 200, buth,
+ uiDefButR(block, NUM, 0, IFACE_("Radius"), 0, yi -= buth + but_margin, 200, buth,
&data_ptr, "radius", 0, 0.0, 100.0, 1, 3, NULL);
- uiDefButR(block, NUM, 0, "Tilt", 0, yi -= buth + but_margin, 200, buth,
- &data_ptr, "tilt", 0, -M_PI * 2.0, M_PI * 2.0, 1, 3, NULL);
+ uiDefButR(block, NUM, 0, IFACE_("Tilt"), 0, yi -= buth + but_margin, 200, buth,
+ &data_ptr, "tilt", 0, -FLT_MAX, FLT_MAX, 1, 3, NULL);
}
else if (totcurvedata > 1) {
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Weight:"),
@@ -450,13 +470,13 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
&(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:"),
0, yi -= buth + but_margin, 200, buth,
- &(tfp->ve_median[C_TILT]), -M_PI * 2.0, M_PI * 2.0, 1, 3,
+ &(tfp->ve_median[C_TILT]), -FLT_MAX, FLT_MAX, 1, 3,
TIP_("Tilt of curve control points"));
uiButSetUnitType(but, PROP_UNIT_ROTATION);
}
/* Lattice... */
else if (totlattdata == 1) {
- uiDefButR(block, NUM, 0, "Weight", 0, yi -= buth + but_margin, 200, buth,
+ uiDefButR(block, NUM, 0, IFACE_("Weight"), 0, yi -= buth + but_margin, 200, buth,
&data_ptr, "weight_softbody", 0, 0.0, 1.0, 1, 3, NULL);
}
else if (totlattdata > 1) {
@@ -502,91 +522,87 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
}
if (median[M_CREASE] != 0.0f) {
- BMEdge *eed;
+ 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 (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 *crease = (float *)CustomData_bmesh_get(&bm->edata, eed->head.data, CD_CREASE);
- if (crease) {
- *crease = sca;
- }
+ 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 = (float *)CustomData_bmesh_get(&bm->edata, eed->head.data, CD_CREASE);
- if (crease) {
- *crease *= sca;
- CLAMP(*crease, 0.0f, 1.0f);
- }
+ float *crease = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_crease_offset);
+ *crease *= sca;
+ CLAMP(*crease, 0.0f, 1.0f);
}
}
}
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 = (float *)CustomData_bmesh_get(&bm->edata, eed->head.data, CD_CREASE);
- if (crease) {
- *crease = 1.0f + ((1.0f - *crease) * sca);
- CLAMP(*crease, 0.0f, 1.0f);
- }
+ 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) {
- BMEdge *eed;
+ 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 (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 = (float *)CustomData_bmesh_get(&bm->edata, eed->head.data, CD_BWEIGHT);
- if (bweight) {
- *bweight = sca;
- }
+ float *bweight = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_bweight_offset);
+ *bweight = 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 *bweight = (float *)CustomData_bmesh_get(&bm->edata, eed->head.data, CD_BWEIGHT);
- if (bweight) {
- *bweight *= sca;
- CLAMP(*bweight, 0.0f, 1.0f);
- }
+ float *bweight = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_bweight_offset);
+ *bweight *= sca;
+ CLAMP(*bweight, 0.0f, 1.0f);
}
}
}
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 = (float *)CustomData_bmesh_get(&bm->edata, eed->head.data, CD_BWEIGHT);
- if (bweight) {
- *bweight = 1.0f + ((1.0f - *bweight) * sca);
- CLAMP(*bweight, 0.0f, 1.0f);
- }
+ 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 (median[M_SKIN_X] != 0.0f) {
- BMVert *eve;
+ 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);
+
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 = (MVertSkin *)CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MVERT_SKIN);
- if (vs)
- vs->radius[0] = sca;
+ MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset);
+ vs->radius[0] = sca;
}
}
}
@@ -594,23 +610,25 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
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)) {
- MVertSkin *vs = (MVertSkin *)CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MVERT_SKIN);
- if (vs)
- vs->radius[0] *= sca;
+ MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset);
+ vs->radius[0] *= sca;
}
}
}
}
if (median[M_SKIN_Y] != 0.0f) {
- BMVert *eve;
+ 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 (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 = (MVertSkin *)CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MVERT_SKIN);
- if (vs)
- vs->radius[1] = sca;
+ MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset);
+ vs->radius[1] = sca;
}
}
}
@@ -618,14 +636,12 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
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 = (MVertSkin *)CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MVERT_SKIN);
- if (vs)
- vs->radius[1] *= sca;
+ MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset);
+ vs->radius[1] *= sca;
}
}
}
}
- EDBM_mesh_normals_update(em);
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
Curve *cu = ob->data;
@@ -792,8 +808,8 @@ static void editvert_mirror_update(Object *ob, BMVert *eve, int def_nr, int inde
if (def_nr == -1) {
/* all vgroups, add groups where neded */
int flip_map_len;
- int *flip_map = defgroup_flip_map(ob, &flip_map_len, TRUE);
- defvert_sync_mapped(dvert_dst, dvert_src, flip_map, flip_map_len, TRUE);
+ int *flip_map = defgroup_flip_map(ob, &flip_map_len, true);
+ defvert_sync_mapped(dvert_dst, dvert_src, flip_map, flip_map_len, true);
MEM_freeN(flip_map);
}
else {
@@ -1253,19 +1269,20 @@ void view3d_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel object");
strcpy(pt->idname, "VIEW3D_PT_object");
- strcpy(pt->label, "Transform");
+ strcpy(pt->label, N_("Transform")); /* XXX C panels not available through RNA (bpy.types)! */
pt->draw = view3d_panel_object;
BLI_addtail(&art->paneltypes, pt);
pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel gpencil");
strcpy(pt->idname, "VIEW3D_PT_gpencil");
- strcpy(pt->label, "Grease Pencil");
+ strcpy(pt->label, N_("Grease Pencil")); /* XXX C panels are not available through RNA (bpy.types)! */
+ pt->draw_header = gpencil_panel_standard_header;
pt->draw = 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, "Vertex Groups");
+ strcpy(pt->label, N_("Vertex Groups")); /* XXX C panels are not available through RNA (bpy.types)! */
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_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index a2e16efadd4..66047b6e8f4 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -75,7 +75,9 @@
#include "BIF_glutil.h"
#include "WM_api.h"
+
#include "BLF_api.h"
+#include "BLF_translation.h"
#include "ED_armature.h"
#include "ED_keyframing.h"
@@ -217,25 +219,22 @@ void ED_view3d_clipping_enable(void)
}
}
-static int view3d_clipping_test(const float vec[3], float clip[6][4])
+static bool view3d_clipping_test(const float co[3], float clip[6][4])
{
- float view[3];
- copy_v3_v3(view, vec);
-
- if (0.0f < clip[0][3] + dot_v3v3(view, clip[0]))
- if (0.0f < clip[1][3] + dot_v3v3(view, clip[1]))
- if (0.0f < clip[2][3] + dot_v3v3(view, clip[2]))
- if (0.0f < clip[3][3] + dot_v3v3(view, clip[3]))
- return 0;
+ if (0.0f < clip[0][3] + dot_v3v3(co, clip[0]))
+ if (0.0f < clip[1][3] + dot_v3v3(co, clip[1]))
+ if (0.0f < clip[2][3] + dot_v3v3(co, clip[2]))
+ if (0.0f < clip[3][3] + dot_v3v3(co, clip[3]))
+ return false;
- return 1;
+ return true;
}
/* for 'local' ED_view3d_clipping_local must run first
* then all comparisons can be done in localspace */
-int ED_view3d_clipping_test(RegionView3D *rv3d, const float vec[3], const int is_local)
+bool ED_view3d_clipping_test(RegionView3D *rv3d, const float co[3], const bool is_local)
{
- return view3d_clipping_test(vec, is_local ? rv3d->clip_local : rv3d->clip);
+ return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip);
}
/* ********* end custom clipping *********** */
@@ -315,7 +314,7 @@ static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **
UI_ThemeColor(TH_GRID);
if (unit->system) {
- /* Use GRID_MIN_PX*2 for units because very very small grid
+ /* Use GRID_MIN_PX * 2 for units because very very small grid
* items are less useful when dealing with units */
void *usys;
int len, i;
@@ -345,7 +344,7 @@ static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **
CLAMP(blend_fac, 0.3f, 1.0f);
- UI_ThemeColorBlend(TH_BACK, TH_GRID, blend_fac);
+ UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, blend_fac);
drawgrid_draw(ar, wx, wy, x, y, dx_scalar);
}
@@ -374,15 +373,15 @@ static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **
}
}
else { /* start blending out */
- UI_ThemeColorBlend(TH_BACK, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
+ UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
drawgrid_draw(ar, wx, wy, x, y, dx);
UI_ThemeColor(TH_GRID);
drawgrid_draw(ar, wx, wy, x, y, sublines * dx);
}
}
- else { /* start blending out (GRID_MIN_PX < dx < (GRID_MIN_PX*10)) */
- UI_ThemeColorBlend(TH_BACK, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
+ else { /* start blending out (GRID_MIN_PX < dx < (GRID_MIN_PX * 10)) */
+ UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
drawgrid_draw(ar, wx, wy, x, y, dx);
UI_ThemeColor(TH_GRID);
@@ -401,21 +400,21 @@ static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **
drawgrid_draw(ar, wx, wy, x, y, dx);
}
else {
- UI_ThemeColorBlend(TH_BACK, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
+ UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
drawgrid_draw(ar, wx, wy, x, y, dx);
UI_ThemeColor(TH_GRID);
drawgrid_draw(ar, wx, wy, x, y, dx * sublines);
}
}
else {
- UI_ThemeColorBlend(TH_BACK, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
+ UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
drawgrid_draw(ar, wx, wy, x, y, dx);
UI_ThemeColor(TH_GRID);
drawgrid_draw(ar, wx, wy, x, y, dx * sublines);
}
}
else {
- UI_ThemeColorBlend(TH_BACK, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
+ UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
drawgrid_draw(ar, wx, wy, x, y, dx);
UI_ThemeColor(TH_GRID);
drawgrid_draw(ar, wx, wy, x, y, dx * sublines);
@@ -563,41 +562,49 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit)
if (v3d->zbuf && scene->obedit) glDepthMask(1);
}
+
static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d)
{
int co[2];
/* we don't want the clipping for cursor */
if (ED_view3d_project_int_global(ar, give_cursor(scene, v3d), co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ const float f5 = 0.25f * U.widget_unit;
+ const float f10 = 0.5f * U.widget_unit;
+ const float f20 = U.widget_unit;
+
setlinestyle(0);
cpack(0xFF);
- circ((float)co[0], (float)co[1], 10.0);
- setlinestyle(4);
+ circ((float)co[0], (float)co[1], f10);
+ setlinestyle(4);
cpack(0xFFFFFF);
- circ((float)co[0], (float)co[1], 10.0);
+ circ((float)co[0], (float)co[1], f10);
setlinestyle(0);
cpack(0x0);
- sdrawline(co[0] - 20, co[1], co[0] - 5, co[1]);
- sdrawline(co[0] + 5, co[1], co[0] + 20, co[1]);
- sdrawline(co[0], co[1] - 20, co[0], co[1] - 5);
- sdrawline(co[0], co[1] + 5, co[0], co[1] + 20);
+ sdrawline(co[0] - f20, co[1], co[0] - f5, co[1]);
+ sdrawline(co[0] + f5, co[1], co[0] + f20, co[1]);
+ sdrawline(co[0], co[1] - f20, co[0], co[1] - f5);
+ sdrawline(co[0], co[1] + f5, co[0], co[1] + f20);
}
}
/* Draw a live substitute of the view icon, which is always shown
* colors copied from transform_manipulator.c, we should keep these matching. */
-static void draw_view_axis(RegionView3D *rv3d)
+static void draw_view_axis(RegionView3D *rv3d, rcti *rect)
{
const float k = U.rvisize; /* axis size */
const float toll = 0.5; /* used to see when view is quasi-orthogonal */
- const float start = k + 1.0f; /* axis center in screen coordinates, x=y */
+ float startx = k + 1.0f; /* axis center in screen coordinates, x=y */
+ float starty = k + 1.0f;
float ydisp = 0.0; /* vertical displacement to allow obj info text */
- int bright = 25 * (float)U.rvibright + 5; /* axis alpha (rvibright has range 0-10) */
-
+ int bright = - 20 * (10 - U.rvibright); /* axis alpha offset (rvibright has range 0-10) */
float vec[3];
float dx, dy;
+ startx += rect->xmin;
+ starty += rect->ymin;
+
/* thickness of lines is proportional to k */
glLineWidth(2);
@@ -613,12 +620,12 @@ static void draw_view_axis(RegionView3D *rv3d)
UI_ThemeColorShadeAlpha(TH_AXIS_X, 0, bright);
glBegin(GL_LINES);
- glVertex2f(start, start + ydisp);
- glVertex2f(start + dx, start + dy + ydisp);
+ glVertex2f(startx, starty + ydisp);
+ glVertex2f(startx + dx, starty + dy + ydisp);
glEnd();
if (fabsf(dx) > toll || fabsf(dy) > toll) {
- BLF_draw_default_ascii(start + dx + 2, start + dy + ydisp + 2, 0.0f, "x", 1);
+ BLF_draw_default_ascii(startx + dx + 2, starty + dy + ydisp + 2, 0.0f, "x", 1);
}
/* BLF_draw_default disables blending */
@@ -633,12 +640,12 @@ static void draw_view_axis(RegionView3D *rv3d)
UI_ThemeColorShadeAlpha(TH_AXIS_Y, 0, bright);
glBegin(GL_LINES);
- glVertex2f(start, start + ydisp);
- glVertex2f(start + dx, start + dy + ydisp);
+ glVertex2f(startx, starty + ydisp);
+ glVertex2f(startx + dx, starty + dy + ydisp);
glEnd();
if (fabsf(dx) > toll || fabsf(dy) > toll) {
- BLF_draw_default_ascii(start + dx + 2, start + dy + ydisp + 2, 0.0f, "y", 1);
+ BLF_draw_default_ascii(startx + dx + 2, starty + dy + ydisp + 2, 0.0f, "y", 1);
}
glEnable(GL_BLEND);
@@ -652,12 +659,12 @@ static void draw_view_axis(RegionView3D *rv3d)
UI_ThemeColorShadeAlpha(TH_AXIS_Z, 0, bright);
glBegin(GL_LINES);
- glVertex2f(start, start + ydisp);
- glVertex2f(start + dx, start + dy + ydisp);
+ glVertex2f(startx, starty + ydisp);
+ glVertex2f(startx + dx, starty + dy + ydisp);
glEnd();
if (fabsf(dx) > toll || fabsf(dy) > toll) {
- BLF_draw_default_ascii(start + dx + 2, start + dy + ydisp + 2, 0.0f, "z", 1);
+ BLF_draw_default_ascii(startx + dx + 2, starty + dy + ydisp + 2, 0.0f, "z", 1);
}
/* restore line-width */
@@ -770,7 +777,7 @@ static void draw_rotation_guide(RegionView3D *rv3d)
glDepthMask(1);
}
-static void draw_view_icon(RegionView3D *rv3d)
+static void draw_view_icon(RegionView3D *rv3d, rcti *rect)
{
BIFIconID icon;
@@ -785,7 +792,7 @@ static void draw_view_icon(RegionView3D *rv3d)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- UI_icon_draw(5.0, 5.0, icon);
+ UI_icon_draw(5.0 + rect->xmin, 5.0 + rect->ymin, icon);
glDisable(GL_BLEND);
}
@@ -796,28 +803,28 @@ static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
switch (rv3d->view) {
case RV3D_VIEW_FRONT:
- if (rv3d->persp == RV3D_ORTHO) name = "Front Ortho";
- else name = "Front Persp";
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Front Ortho");
+ else name = IFACE_("Front Persp");
break;
case RV3D_VIEW_BACK:
- if (rv3d->persp == RV3D_ORTHO) name = "Back Ortho";
- else name = "Back Persp";
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Back Ortho");
+ else name = IFACE_("Back Persp");
break;
case RV3D_VIEW_TOP:
- if (rv3d->persp == RV3D_ORTHO) name = "Top Ortho";
- else name = "Top Persp";
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Top Ortho");
+ else name = IFACE_("Top Persp");
break;
case RV3D_VIEW_BOTTOM:
- if (rv3d->persp == RV3D_ORTHO) name = "Bottom Ortho";
- else name = "Bottom Persp";
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Bottom Ortho");
+ else name = IFACE_("Bottom Persp");
break;
case RV3D_VIEW_RIGHT:
- if (rv3d->persp == RV3D_ORTHO) name = "Right Ortho";
- else name = "Right Persp";
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Right Ortho");
+ else name = IFACE_("Right Persp");
break;
case RV3D_VIEW_LEFT:
- if (rv3d->persp == RV3D_ORTHO) name = "Left Ortho";
- else name = "Left Persp";
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Left Ortho");
+ else name = IFACE_("Left Persp");
break;
default:
@@ -825,14 +832,14 @@ 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) ? "Camera Persp" : "Camera Ortho";
+ name = (cam->type != CAM_ORTHO) ? IFACE_("Camera Persp") : IFACE_("Camera Ortho");
}
else {
- name = "Object as Camera";
+ name = IFACE_("Object as Camera");
}
}
else {
- name = (rv3d->persp == RV3D_ORTHO) ? "User Ortho" : "User Persp";
+ name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Ortho") : IFACE_("User Persp");
}
break;
}
@@ -840,30 +847,39 @@ static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
return name;
}
-static void draw_viewport_name(ARegion *ar, View3D *v3d)
+static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect)
{
RegionView3D *rv3d = ar->regiondata;
const char *name = view3d_get_name(v3d, rv3d);
+ /* XXX 24 may be a bit small for unicode languages (Chinese in utf-8...) */
+#ifdef WITH_INTERNATIONAL
+ char tmpstr[32];
+#else
char tmpstr[24];
-
+#endif
+
if (v3d->localvd) {
- BLI_snprintf(tmpstr, sizeof(tmpstr), "%s (Local)", name);
+ BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name);
name = tmpstr;
}
if (name) {
UI_ThemeColor(TH_TEXT_HI);
- BLF_draw_default_ascii(22, ar->winy - 17, 0.0f, name, sizeof(tmpstr));
+#ifdef WITH_INTERNATIONAL
+ BLF_draw_default(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr));
+#else
+ BLF_draw_default_ascii(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr));
+#endif
}
}
/* draw info beside axes in bottom left-corner:
* framenum, object name, bone name (if available), marker name (if available)
*/
-static void draw_selected_name(Scene *scene, Object *ob)
+static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
{
char info[256], *markern;
- short offset = 30;
+ short offset = 1.5f * UI_UNIT_X + rect->xmin;
/* get name of marker on current frame (if available) */
markern = BKE_scene_find_marker_name(scene, CFRA);
@@ -910,7 +926,7 @@ static void draw_selected_name(Scene *scene, Object *ob)
if (kb) {
BLI_snprintf(shapes, sizeof(shapes), ": %s ", kb->name);
if (ob->shapeflag == OB_SHAPE_LOCK) {
- strcat(shapes, " (Pinned)");
+ strcat(shapes, IFACE_(" (Pinned)"));
}
}
}
@@ -929,7 +945,7 @@ static void draw_selected_name(Scene *scene, Object *ob)
}
/* color depends on whether there is a keyframe */
- if (id_frame_has_keyframe((ID *)ob, /*BKE_scene_frame_get(scene)*/ (float)(CFRA), ANIMFILTER_KEYS_LOCAL))
+ if (id_frame_has_keyframe((ID *)ob, /* BKE_scene_frame_get(scene) */ (float)(CFRA), ANIMFILTER_KEYS_LOCAL))
UI_ThemeColor(TH_VERTEX_SELECT);
else
UI_ThemeColor(TH_TEXT_HI);
@@ -946,13 +962,13 @@ static void draw_selected_name(Scene *scene, Object *ob)
}
if (U.uiflag & USER_SHOW_ROTVIEWICON)
- offset = 14 + (U.rvisize * 2);
+ offset = U.widget_unit + (U.rvisize * 2) + rect->xmin;
- BLF_draw_default(offset, 10, 0.0f, info, sizeof(info));
+ 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 *viewborder_r, short no_shift, short no_zoom)
+ rctf *r_viewborder, const bool no_shift, const bool no_zoom)
{
CameraParams params;
rctf rect_view, rect_camera;
@@ -976,25 +992,25 @@ static void view3d_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionV
rect_camera = params.viewplane;
/* get camera border within viewport */
- viewborder_r->xmin = ((rect_camera.xmin - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx;
- viewborder_r->xmax = ((rect_camera.xmax - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx;
- viewborder_r->ymin = ((rect_camera.ymin - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy;
- viewborder_r->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy;
+ r_viewborder->xmin = ((rect_camera.xmin - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx;
+ r_viewborder->xmax = ((rect_camera.xmax - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx;
+ r_viewborder->ymin = ((rect_camera.ymin - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy;
+ 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 size_r[2])
+void ED_view3d_calc_camera_border_size(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, float r_size[2])
{
rctf viewborder;
- view3d_camera_border(scene, ar, v3d, rv3d, &viewborder, TRUE, TRUE);
- size_r[0] = BLI_rctf_size_x(&viewborder);
- size_r[1] = BLI_rctf_size_y(&viewborder);
+ view3d_camera_border(scene, ar, v3d, rv3d, &viewborder, true, true);
+ r_size[0] = BLI_rctf_size_x(&viewborder);
+ r_size[1] = BLI_rctf_size_y(&viewborder);
}
void ED_view3d_calc_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d,
- rctf *viewborder_r, short no_shift)
+ rctf *r_viewborder, const bool no_shift)
{
- view3d_camera_border(scene, ar, v3d, rv3d, viewborder_r, no_shift, FALSE);
+ view3d_camera_border(scene, ar, v3d, rv3d, r_viewborder, no_shift, false);
}
static void drawviewborder_grid3(float x1, float x2, float y1, float y2, float fac)
@@ -1083,7 +1099,7 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
if (v3d->camera->type == OB_CAMERA)
ca = v3d->camera->data;
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, FALSE);
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false);
/* the offsets */
x1 = viewborder.xmin;
y1 = viewborder.ymin;
@@ -1134,10 +1150,10 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
glRectf(x1i, y1i, x2i, y2i);
#ifdef VIEW3D_CAMERA_BORDER_HACK
- if (view3d_camera_border_hack_test == TRUE) {
+ if (view3d_camera_border_hack_test == true) {
glColor3ubv(view3d_camera_border_hack_col);
glRectf(x1i + 1, y1i + 1, x2i - 1, y2i - 1);
- view3d_camera_border_hack_test = FALSE;
+ view3d_camera_border_hack_test = false;
}
#endif
@@ -1289,7 +1305,6 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
RegionView3D *rv3d = ar->regiondata;
struct Base *base = scene->basact;
int multisample_enabled;
- rcti winrct;
BLI_assert(ar->regiontype == RGN_TYPE_WINDOW);
@@ -1298,11 +1313,6 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
{
/* do nothing */
}
- else if ((base && (base->object->mode & OB_MODE_TEXTURE_PAINT)) &&
- scene->toolsettings && (scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE))
- {
- /* do nothing */
- }
else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) &&
v3d->drawtype > OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT))
{
@@ -1338,8 +1348,35 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
if (multisample_enabled)
glDisable(GL_MULTISAMPLE_ARB);
- region_scissor_winrct(ar, &winrct);
- glScissor(winrct.xmin, winrct.ymin, BLI_rcti_size_x(&winrct), BLI_rcti_size_y(&winrct));
+ if (U.ogl_multisamples != USER_MULTISAMPLE_NONE) {
+ /* for multisample we use an offscreen FBO. multisample drawing can fail
+ * with color coded selection drawing, and reading back depths from such
+ * a buffer can also cause a few seconds freeze on OS X / NVidia. */
+ int w = BLI_rcti_size_x(&ar->winrct);
+ int h = BLI_rcti_size_y(&ar->winrct);
+ char error[256];
+
+ if (rv3d->gpuoffscreen) {
+ if (GPU_offscreen_width(rv3d->gpuoffscreen) != w ||
+ GPU_offscreen_height(rv3d->gpuoffscreen) != h)
+ {
+ GPU_offscreen_free(rv3d->gpuoffscreen);
+ rv3d->gpuoffscreen = NULL;
+ }
+ }
+
+ if (!rv3d->gpuoffscreen) {
+ rv3d->gpuoffscreen = GPU_offscreen_create(w, h, error);
+
+ if (!rv3d->gpuoffscreen)
+ fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error);
+ }
+ }
+
+ if (rv3d->gpuoffscreen)
+ GPU_offscreen_bind(rv3d->gpuoffscreen);
+ 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);
if (v3d->zbuf) {
@@ -1358,9 +1395,13 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
if (base && (base->lay & v3d->lay))
draw_object_backbufsel(scene, v3d, rv3d, base->object);
+
+ if (rv3d->gpuoffscreen)
+ GPU_offscreen_unbind(rv3d->gpuoffscreen);
+ else
+ ar->swap = 0; /* mark invalid backbuf for wm draw */
v3d->flag &= ~V3D_INVALID_BACKBUF;
- ar->swap = 0; /* mark invalid backbuf for wm draw */
G.f &= ~G_BACKBUFSEL;
v3d->zbuf = FALSE;
@@ -1377,6 +1418,28 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
}
+void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data)
+{
+ RegionView3D *rv3d = ar->regiondata;
+
+ if (rv3d->gpuoffscreen) {
+ GPU_offscreen_bind(rv3d->gpuoffscreen);
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ glReadPixels(x, y, w, h, format, type, data);
+ GPU_offscreen_unbind(rv3d->gpuoffscreen);
+ }
+ else {
+ glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
+ }
+}
+
+/* XXX depth reading exception, for code not using gpu offscreen */
+static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data)
+{
+
+ glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
+}
+
void view3d_validate_backbuf(ViewContext *vc)
{
if (vc->v3d->flag & V3D_INVALID_BACKBUF)
@@ -1392,12 +1455,9 @@ unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y)
return 0;
}
- x += vc->ar->winrct.xmin;
- y += vc->ar->winrct.ymin;
-
view3d_validate_backbuf(vc);
- glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
+ view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
glReadBuffer(GL_BACK);
if (ENDIAN_ORDER == B_ENDIAN) {
@@ -1428,8 +1488,8 @@ ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax,
view3d_validate_backbuf(vc);
- glReadPixels(vc->ar->winrct.xmin + xminc,
- vc->ar->winrct.ymin + yminc,
+ view3d_opengl_read_pixels(vc->ar,
+ xminc, yminc,
(xmaxc - xminc + 1),
(ymaxc - yminc + 1),
GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
@@ -1537,7 +1597,7 @@ exit:
/* ************************************************************* */
static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
- const short do_foreground, const short do_camera_frame)
+ const bool do_foreground, const bool do_camera_frame)
{
RegionView3D *rv3d = ar->regiondata;
BGpic *bgpic;
@@ -1556,7 +1616,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
float fac, asp, zoomx, zoomy;
float x1, y1, x2, y2;
- ImBuf *ibuf = NULL, *freeibuf;
+ ImBuf *ibuf = NULL, *freeibuf, *releaseibuf;
Image *ima;
MovieClip *clip;
@@ -1566,6 +1626,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
continue;
freeibuf = NULL;
+ releaseibuf = NULL;
if (bgpic->source == V3D_BGPIC_IMAGE) {
ima = bgpic->ima;
if (ima == NULL)
@@ -1576,7 +1637,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
}
else {
ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, NULL);
- freeibuf = ibuf;
+ releaseibuf = ibuf;
}
image_aspect[0] = ima->aspx;
@@ -1591,7 +1652,9 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
if (scene->camera)
clip = BKE_object_movieclip_get(scene, scene->camera, 1);
}
- else clip = bgpic->clip;
+ else {
+ clip = bgpic->clip;
+ }
if (clip == NULL)
continue;
@@ -1619,6 +1682,8 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) { /* invalid image format */
if (freeibuf)
IMB_freeImBuf(freeibuf);
+ if (releaseibuf)
+ BKE_image_release_ibuf(ima, releaseibuf, NULL);
continue;
}
@@ -1630,7 +1695,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
if (do_camera_frame) {
rctf vb;
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, FALSE);
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, false);
x1 = vb.xmin;
y1 = vb.ymin;
x2 = vb.xmax;
@@ -1691,10 +1756,12 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
float tvec[3];
float sco[2];
const float mval_f[2] = {1.0f, 0.0f};
+ const float co_zero[3] = {0};
+ float zfac;
/* calc window coord */
- initgrabz(rv3d, 0.0, 0.0, 0.0);
- ED_view3d_win_to_delta(ar, mval_f, tvec);
+ zfac = ED_view3d_calc_zfac(rv3d, co_zero, NULL);
+ ED_view3d_win_to_delta(ar, mval_f, tvec, zfac);
fac = max_ff(fabsf(tvec[0]), max_ff(fabsf(tvec[1]), fabsf(tvec[2]))); /* largest abs axis */
fac = 1.0f / fac;
@@ -1714,6 +1781,8 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
if (x2 < 0 || y2 < 0 || x1 > ar->winx || y1 > ar->winy) {
if (freeibuf)
IMB_freeImBuf(freeibuf);
+ if (releaseibuf)
+ BKE_image_release_ibuf(ima, releaseibuf, NULL);
continue;
}
@@ -1757,7 +1826,12 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
glPixelZoom(zoomx, zoomy);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f - bgpic->blend);
- glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect);
+
+ /* could not use glaDrawPixelsAuto because it could fallback to
+ * glaDrawPixelsSafe in some cases, which will end up in misssing
+ * alpha transparency for the background image (sergey)
+ */
+ glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect);
glPixelZoom(1.0, 1.0);
glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
@@ -1772,15 +1846,16 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
glDepthMask(1);
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
- if (freeibuf) {
+ if (freeibuf)
IMB_freeImBuf(freeibuf);
- }
+ if (releaseibuf)
+ BKE_image_release_ibuf(ima, releaseibuf, NULL);
}
}
}
static void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d,
- const short do_foreground, const short do_camera_frame)
+ const bool do_foreground, const bool do_camera_frame)
{
RegionView3D *rv3d = ar->regiondata;
@@ -1921,12 +1996,13 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas
BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */
GLuint displist = 0;
short transflag, use_displist = -1; /* -1 is initialize */
- char dt, dtx;
+ char dt;
+ short dtx;
if (base->object->restrictflag & OB_RESTRICT_VIEW) return;
tbase.flag = OB_FROMDUPLI | base->flag;
- lb = object_duplilist(scene, base->object, FALSE);
+ lb = object_duplilist(scene, base->object, false);
// BLI_sortlist(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */
dob = dupli_step(lb->first);
@@ -1956,7 +2032,7 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas
/* generate displist, test for new object */
if (dob_prev && dob_prev->ob != dob->ob) {
- if (use_displist == TRUE)
+ if (use_displist == true)
glDeleteLists(displist, 1);
use_displist = -1;
@@ -1977,11 +2053,11 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas
(dob->type == OB_DUPLIGROUP && dob->animated) ||
!(bb_tmp = BKE_object_boundbox_get(dob->ob)))
{
- // printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name+2);
- use_displist = FALSE;
+ // printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name + 2);
+ use_displist = false;
}
else {
- // printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name+2);
+ // printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name + 2);
bb = *bb_tmp; /* must make a copy */
/* disable boundbox check for list creation */
@@ -1994,7 +2070,7 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas
draw_object(scene, ar, v3d, &tbase, DRAW_CONSTCOLOR);
glEndList();
- use_displist = TRUE;
+ use_displist = true;
BKE_object_boundbox_flag(dob->ob, OB_BB_DISABLED, 0);
}
}
@@ -2035,6 +2111,7 @@ static void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *bas
draw_dupli_objects_color(scene, ar, v3d, base, color);
}
+/* XXX warning, not using gpu offscreen here */
void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect)
{
int x, y, w, h;
@@ -2061,7 +2138,7 @@ void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect)
MEM_freeN(d->depths);
d->depths = NULL;
- d->damaged = FALSE;
+ d->damaged = false;
}
else if (d->w != w ||
d->h != h ||
@@ -2080,13 +2157,14 @@ void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect)
d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset");
- d->damaged = TRUE;
+ d->damaged = true;
}
if (d->damaged) {
- glReadPixels(ar->winrct.xmin + d->x, ar->winrct.ymin + d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
+ /* XXX using special function here, it doesn't use the gpu offscreen system */
+ view3d_opengl_read_Z_pixels(ar, d->x, d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
- d->damaged = FALSE;
+ d->damaged = false;
}
}
@@ -2108,16 +2186,14 @@ void ED_view3d_depth_update(ARegion *ar)
if (d->depths)
MEM_freeN(d->depths);
d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths");
- d->damaged = 1;
+ d->damaged = true;
}
if (d->damaged) {
- glReadPixels(ar->winrct.xmin, ar->winrct.ymin, d->w, d->h,
- GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
-
+ view3d_opengl_read_pixels(ar, 0, 0, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
- d->damaged = 0;
+ d->damaged = false;
}
}
}
@@ -2165,13 +2241,15 @@ void draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d)
v3d->zbuf = TRUE;
glEnable(GL_DEPTH_TEST);
- draw_gpencil_view3d(scene, v3d, ar, 1);
+ if (v3d->flag2 & V3D_SHOW_GPENCIL) {
+ draw_gpencil_view3d(scene, v3d, ar, true);
+ }
v3d->zbuf = zbuf;
}
-void draw_depth(Scene *scene, ARegion *ar, View3D *v3d, int (*func)(void *))
+void draw_depth(Scene *scene, ARegion *ar, View3D *v3d, int (*func)(void *), bool alphaoverride)
{
RegionView3D *rv3d = ar->regiondata;
Base *base;
@@ -2183,7 +2261,7 @@ void draw_depth(Scene *scene, ARegion *ar, View3D *v3d, int (*func)(void *))
/* Setting these temporarily is not nice */
v3d->flag &= ~V3D_SELECT_OUTLINE;
- U.glalphaclip = 0.5; /* not that nice but means we wont zoom into billboards */
+ U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */
U.obcenter_dia = 0;
setwinmatrixview3d(ar, v3d, NULL);
@@ -2346,7 +2424,7 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
if (ob->transflag & OB_DUPLI) {
DupliObject *dob;
- ListBase *lb = object_duplilist(scene, ob, FALSE);
+ ListBase *lb = object_duplilist(scene, ob, false);
for (dob = lb->first; dob; dob = dob->next)
if (dob->ob->type == OB_LAMP)
@@ -2385,7 +2463,7 @@ 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);
GPU_lamp_shadow_buffer_unbind(shadow->lamp);
v3d->drawtype = drawtype;
@@ -2532,13 +2610,11 @@ void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d)
/* 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],
- int do_bgpic, int colormanage_background)
+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)
{
RegionView3D *rv3d = ar->regiondata;
Base *base;
- float backcol[3];
int bwinx, bwiny;
rcti brect;
@@ -2566,34 +2642,7 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
* warning! can be slow so only free animated images - campbell */
GPU_free_images_anim();
- /* set background color, fallback on the view background color
- * (if active clip is set but frame is failed to load fallback to horizon color as background) */
- if (scene->world) {
- /* NOTE: currently OpenGL is supposed to always work in sRGB space and do not
- * apply any tonemaps since it's really tricky to support for all features (GLSL, textures, etc)
- * but due to compatibility issues background is being affected display transform, so we can
- * emulate behavior of disabled color management
- * but this function is also used for sequencer's scene strips which shouldn't be affected by
- * tonemaps now and should be purely sRGB, that's why we've got this colormanage_background
- * we can drop this flag in cost of some compatibility loss -- background wouldn't be
- * color managed in 3d viewport
- * same goes to opengl rendering, where color profile should be applied as very final step
- */
-
- if (colormanage_background) {
- IMB_colormanagement_pixel_to_display_space_v3(backcol, &scene->world->horr, &scene->view_settings,
- &scene->display_settings);
- }
- else {
- linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr);
- }
-
- glClearColor(backcol[0], backcol[1], backcol[2], 0.0);
- }
- else {
- UI_ThemeClearColor(TH_BACK);
- }
-
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -2613,7 +2662,7 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
/* important to do before clipping */
if (do_bgpic) {
- view3d_draw_bgpic_test(scene, ar, v3d, FALSE, FALSE);
+ view3d_draw_bgpic_test(scene, ar, v3d, false, false);
}
if (rv3d->rflag & RV3D_CLIPPING)
@@ -2645,9 +2694,11 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
}
/* must be before xray draw which clears the depth buffer */
- if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
- draw_gpencil_view3d(scene, v3d, ar, 1);
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+ if (v3d->flag2 & V3D_SHOW_GPENCIL) {
+ if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
+ draw_gpencil_view3d(scene, v3d, ar, true);
+ if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+ }
/* transp and X-ray afterdraw stuff */
if (v3d->afterdraw_transp.first) view3d_draw_transp(scene, ar, v3d);
@@ -2659,7 +2710,7 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
/* important to do after clipping */
if (do_bgpic) {
- view3d_draw_bgpic_test(scene, ar, v3d, TRUE, FALSE);
+ view3d_draw_bgpic_test(scene, ar, v3d, true, false);
}
/* cleanup */
@@ -2671,8 +2722,11 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
/* draw grease-pencil stuff */
ED_region_pixelspace(ar);
- /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
- draw_gpencil_view3d(scene, v3d, ar, 0);
+
+ if (v3d->flag2 & V3D_SHOW_GPENCIL) {
+ /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
+ draw_gpencil_view3d(scene, v3d, ar, false);
+ }
/* freeing the images again here could be done after the operator runs, leaving for now */
GPU_free_images_anim();
@@ -2690,10 +2744,30 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
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);
+}
+
+static void offscreen_imbuf_add_sky(ImBuf *ibuf, Scene *scene)
+{
+ float sky_color[3];
+
+ ED_view3d_offscreen_sky_color_get(scene, sky_color);
+
+ if (ibuf->rect_float)
+ IMB_alpha_under_color_float(ibuf->rect_float, ibuf->x, ibuf->y, sky_color);
+ else
+ IMB_alpha_under_color_byte((unsigned char *) ibuf->rect, ibuf->x, ibuf->y, 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, int draw_background,
- int colormanage_background, char err_out[256])
+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])
{
RegionView3D *rv3d = ar->regiondata;
ImBuf *ibuf;
@@ -2720,10 +2794,10 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar,
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, colormanage_background);
+ ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, params.winmat, draw_background);
}
else {
- ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background, colormanage_background);
+ ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background);
}
/* read in pixels & stamp */
@@ -2734,6 +2808,9 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar,
else if (ibuf->rect)
GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect);
+ if (alpha_mode == R_ADDSKY)
+ offscreen_imbuf_add_sky(ibuf, scene);
+
/* unbind */
GPU_offscreen_unbind(ofs);
GPU_offscreen_free(ofs);
@@ -2747,9 +2824,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar,
}
/* 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, int draw_background,
- int colormanage_background, char err_out[256])
+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])
{
View3D v3d = {NULL};
ARegion ar = {NULL};
@@ -2765,6 +2841,9 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int w
v3d.drawtype = drawtype;
v3d.flag2 = V3D_RENDER_OVERRIDE;
+ if (use_solid_tex)
+ v3d.flag2 |= V3D_SOLID_TEX;
+
rv3d.persp = RV3D_CAMOB;
copy_m4_m4(rv3d.viewinv, v3d.camera->obmat);
@@ -2789,7 +2868,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, colormanage_background, err_out);
+ draw_background, alpha_mode, err_out);
// seq_view3d_cb(scene, cfra, render_size, seqrectx, seqrecty);
}
@@ -2798,7 +2877,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int w
/* NOTE: the info that this uses is updated in ED_refresh_viewport_fps(),
* which currently gets called during SCREEN_OT_animation_step.
*/
-static void draw_viewport_fps(Scene *scene, ARegion *ar)
+static void draw_viewport_fps(Scene *scene, rcti *rect)
{
ScreenFrameRateInfo *fpsi = scene->fps_info;
float fps;
@@ -2836,19 +2915,23 @@ static void draw_viewport_fps(Scene *scene, ARegion *ar)
/* is this more then half a frame behind? */
if (fps + 0.5f < (float)(FPS)) {
UI_ThemeColor(TH_REDALERT);
- BLI_snprintf(printable, sizeof(printable), "fps: %.2f", fps);
+ BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps);
}
else {
UI_ThemeColor(TH_TEXT_HI);
- BLI_snprintf(printable, sizeof(printable), "fps: %i", (int)(fps + 0.5f));
+ BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f));
}
-
- BLF_draw_default_ascii(22, ar->winy - 17, 0.0f, printable, sizeof(printable));
+
+#ifdef WITH_INTERNATIONAL
+ BLF_draw_default(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable));
+#else
+ BLF_draw_default_ascii(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable));
+#endif
}
static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const char **grid_unit);
-static int view3d_main_area_do_render_draw(const bContext *C)
+static bool view3d_main_area_do_render_draw(const bContext *C)
{
Scene *scene = CTX_data_scene(C);
RenderEngineType *type = RE_engines_find(scene->r.engine);
@@ -2856,7 +2939,7 @@ static int view3d_main_area_do_render_draw(const bContext *C)
return (type && type->view_update && type->view_draw);
}
-static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar, int draw_border)
+static bool view3d_main_area_draw_engine(const bContext *C, ARegion *ar, const bool draw_border)
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -2871,9 +2954,9 @@ static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar, int draw
type = RE_engines_find(scene->r.engine);
if (!(type->view_update && type->view_draw))
- return 0;
+ return false;
- engine = RE_engine_create(type);
+ engine = RE_engine_create_ex(type, true);
engine->tile_x = scene->r.tilex;
engine->tile_y = scene->r.tiley;
@@ -2895,7 +2978,7 @@ static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar, int draw
rcti cliprct;
if (rv3d->persp == RV3D_CAMOB) {
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, FALSE);
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false);
cliprct.xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder);
cliprct.ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder);
@@ -2923,15 +3006,16 @@ static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar, int draw
glGetIntegerv(GL_SCISSOR_BOX, scissor);
glScissor(cliprct.xmin, cliprct.ymin, BLI_rcti_size_x(&cliprct), BLI_rcti_size_y(&cliprct));
}
- else
- return 0;
+ else {
+ return false;
+ }
}
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (v3d->flag & V3D_DISPBGPICS)
- view3d_draw_bgpic(scene, ar, v3d, FALSE, TRUE);
+ view3d_draw_bgpic(scene, ar, v3d, false, true);
else
fdrawcheckerboard(0, 0, ar->winx, ar->winy);
@@ -2940,14 +3024,14 @@ static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar, int draw
type->view_draw(rv3d->render_engine, C);
if (v3d->flag & V3D_DISPBGPICS)
- view3d_draw_bgpic(scene, ar, v3d, TRUE, TRUE);
+ view3d_draw_bgpic(scene, ar, v3d, true, true);
if (draw_border) {
/* restore scissor as it was before */
glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
}
- return 1;
+ return true;
}
static void view3d_main_area_draw_engine_info(RegionView3D *rv3d, ARegion *ar)
@@ -2958,6 +3042,177 @@ static void view3d_main_area_draw_engine_info(RegionView3D *rv3d, ARegion *ar)
ED_region_info_draw(ar, rv3d->render_engine->text, 1, 0.25);
}
+/*
+ * Function to clear the view
+ */
+static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar)
+{
+ /* clear background */
+ if (scene->world && (v3d->flag2 & V3D_RENDER_OVERRIDE)) { /* clear with solid color */
+ if (scene->world->skytype & WO_SKYBLEND) { /* blend sky */
+ int x, y;
+ float col_hor[3];
+ float col_zen[3];
+
+#define VIEWGRAD_RES_X 16
+#define VIEWGRAD_RES_Y 16
+
+ GLubyte grid_col[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][4];
+ static float grid_pos[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][3];
+ static GLushort indices[VIEWGRAD_RES_X - 1][VIEWGRAD_RES_X - 1][4];
+ static bool buf_calculated = false;
+
+ IMB_colormanagement_pixel_to_display_space_v3(col_hor, &scene->world->horr, &scene->view_settings,
+ &scene->display_settings);
+ IMB_colormanagement_pixel_to_display_space_v3(col_zen, &scene->world->zenr, &scene->view_settings,
+ &scene->display_settings);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glShadeModel(GL_SMOOTH);
+
+ /* calculate buffers the first time only */
+ if (!buf_calculated) {
+ for (x = 0; x < VIEWGRAD_RES_X; x++) {
+ for (y = 0; y < VIEWGRAD_RES_Y; y++) {
+ const float xf = (float)x / (float)(VIEWGRAD_RES_X - 1);
+ const float yf = (float)y / (float)(VIEWGRAD_RES_Y - 1);
+
+ /* -1..1 range */
+ grid_pos[x][y][0] = (xf - 0.5f) * 2.0f;
+ grid_pos[x][y][1] = (yf - 0.5f) * 2.0f;
+ grid_pos[x][y][2] = 1.0;
+ }
+ }
+
+ for (x = 0; x < VIEWGRAD_RES_X - 1; x++) {
+ for (y = 0; y < VIEWGRAD_RES_Y - 1; y++) {
+ indices[x][y][0] = x * VIEWGRAD_RES_X + y;
+ indices[x][y][1] = x * VIEWGRAD_RES_X + y + 1;
+ indices[x][y][2] = (x + 1) * VIEWGRAD_RES_X + y + 1;
+ indices[x][y][3] = (x + 1) * VIEWGRAD_RES_X + y;
+ }
+ }
+
+ buf_calculated = true;
+ }
+
+ for (x = 0; x < VIEWGRAD_RES_X; x++) {
+ for (y = 0; y < VIEWGRAD_RES_Y; y++) {
+ const float xf = (float)x / (float)(VIEWGRAD_RES_X - 1);
+ const float yf = (float)y / (float)(VIEWGRAD_RES_Y - 1);
+ const float mval[2] = {xf * (float)ar->winx, yf * ar->winy};
+ const float z_up[3] = {0.0f, 0.0f, 1.0f};
+ float out[3];
+ GLubyte *col_ub = grid_col[x][y];
+
+ float col_fac;
+ float col_fl[3];
+
+ ED_view3d_win_to_vector(ar, mval, out);
+
+ if (scene->world->skytype & WO_SKYPAPER) {
+ if (scene->world->skytype & WO_SKYREAL) {
+ col_fac = fabsf(((float)y / (float)VIEWGRAD_RES_Y) - 0.5f) * 2.0f;
+ }
+ else {
+ col_fac = (float)y / (float)VIEWGRAD_RES_Y;
+ }
+ }
+ else {
+ if (scene->world->skytype & WO_SKYREAL) {
+ col_fac = fabsf((angle_normalized_v3v3(z_up, out) / (float)M_PI) - 0.5f) * 2.0f;
+ }
+ else {
+ col_fac = 1.0f - (angle_normalized_v3v3(z_up, out) / (float)M_PI);
+ }
+ }
+
+ interp_v3_v3v3(col_fl, col_hor, col_zen, col_fac);
+
+ rgb_float_to_uchar(col_ub, col_fl);
+ col_ub[3] = 0;
+ }
+ }
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, grid_pos);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 0, grid_col);
+
+ glDrawElements(GL_QUADS, (VIEWGRAD_RES_X - 1) * (VIEWGRAD_RES_Y - 1) * 4, GL_UNSIGNED_SHORT, indices);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+
+ glDepthFunc(GL_LEQUAL);
+ glDisable(GL_DEPTH_TEST);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ glShadeModel(GL_FLAT);
+
+#undef VIEWGRAD_RES_X
+#undef VIEWGRAD_RES_Y
+ }
+ else { /* solid sky */
+ float col_hor[3];
+ IMB_colormanagement_pixel_to_display_space_v3(col_hor, &scene->world->horr, &scene->view_settings,
+ &scene->display_settings);
+
+ glClearColor(col_hor[0], col_hor[1], col_hor[2], 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+ }
+ else {
+ if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+ glShadeModel(GL_SMOOTH);
+ glBegin(GL_QUADS);
+ UI_ThemeColor(TH_LOW_GRAD);
+ glVertex3f(-1.0, -1.0, 1.0);
+ glVertex3f(1.0, -1.0, 1.0);
+ UI_ThemeColor(TH_HIGH_GRAD);
+ glVertex3f(1.0, 1.0, 1.0);
+ glVertex3f(-1.0, 1.0, 1.0);
+ glEnd();
+ glShadeModel(GL_FLAT);
+
+ glDepthFunc(GL_LEQUAL);
+ glDisable(GL_DEPTH_TEST);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
+ else {
+ UI_ThemeClearColor(TH_HIGH_GRAD);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+ }
+}
+
/* warning: this function has duplicate drawing in ED_view3d_draw_offscreen() */
static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const char **grid_unit)
{
@@ -2965,7 +3220,6 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
Base *base;
- float backcol[3];
unsigned int lay_used;
/* shadow buffers, before we setup matrices */
@@ -2978,21 +3232,12 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const
GPU_default_lights();
}
- /* clear background */
- if ((v3d->flag2 & V3D_RENDER_OVERRIDE) && scene->world) {
- IMB_colormanagement_pixel_to_display_space_v3(backcol, &scene->world->horr, &scene->view_settings,
- &scene->display_settings);
-
- glClearColor(backcol[0], backcol[1], backcol[2], 0.0);
- }
- else
- UI_ThemeClearColor(TH_BACK);
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
/* setup view matrices */
view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL);
+ /* clear the background */
+ view3d_main_area_clear(scene, v3d, ar);
+
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
if (rv3d->rflag & RV3D_CLIPPING)
@@ -3008,7 +3253,6 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const
/* enables anti-aliasing for 3D view drawing */
if (U.ogl_multisamples != USER_MULTISAMPLE_NONE) {
- // if (!(U.gameflags & USER_DISABLE_AA))
glEnable(GL_MULTISAMPLE_ARB);
}
@@ -3041,7 +3285,7 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const
}
}
- view3d_draw_bgpic_test(scene, ar, v3d, FALSE, TRUE);
+ view3d_draw_bgpic_test(scene, ar, v3d, false, true);
if (rv3d->rflag & RV3D_CLIPPING)
ED_view3d_clipping_set(rv3d);
@@ -3102,10 +3346,10 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const
// REEB_draw();
- if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
+ if (v3d->flag2 & V3D_SHOW_GPENCIL) {
/* must be before xray draw which clears the depth buffer */
if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
- draw_gpencil_view3d(scene, v3d, ar, 1);
+ draw_gpencil_view3d(scene, v3d, ar, true);
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
}
@@ -3120,13 +3364,12 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const
ED_view3d_clipping_disable();
/* important to do after clipping */
- view3d_draw_bgpic_test(scene, ar, v3d, TRUE, TRUE);
+ view3d_draw_bgpic_test(scene, ar, v3d, true, true);
BIF_draw_manipulator(C);
/* Disable back anti-aliasing */
if (U.ogl_multisamples != USER_MULTISAMPLE_NONE) {
- // if (!(U.gameflags & USER_DISABLE_AA))
glDisable(GL_MULTISAMPLE_ARB);
}
@@ -3152,6 +3395,10 @@ static void view3d_main_area_draw_info(const bContext *C, ARegion *ar, const cha
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ rcti rect;
+
+ /* local coordinate visible rect inside region, to accomodate overlapping ui */
+ ED_region_visible_rect(ar, &rect);
if (rv3d->persp == RV3D_CAMOB) {
drawviewborder(scene, ar, v3d);
@@ -3168,23 +3415,24 @@ static void view3d_main_area_draw_info(const bContext *C, ARegion *ar, const cha
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
+ if (v3d->flag2 & V3D_SHOW_GPENCIL) {
+ /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
+ draw_gpencil_view3d(scene, v3d, ar, false);
+ }
+
if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
Object *ob;
- /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
- // if (v3d->flag2 & V3D_DISPGP)
- draw_gpencil_view3d(scene, v3d, ar, 0);
-
drawcursor(scene, ar, v3d);
if (U.uiflag & USER_SHOW_ROTVIEWICON)
- draw_view_axis(rv3d);
+ draw_view_axis(rv3d, &rect);
else
- draw_view_icon(rv3d);
+ draw_view_icon(rv3d, &rect);
ob = OBACT;
if (U.uiflag & USER_DRAWVIEWINFO)
- draw_selected_name(scene, ob);
+ draw_selected_name(scene, ob, &rect);
}
if (rv3d->render_engine) {
@@ -3194,10 +3442,10 @@ static void view3d_main_area_draw_info(const bContext *C, ARegion *ar, const cha
if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_playing(wm)) {
- draw_viewport_fps(scene, ar);
+ draw_viewport_fps(scene, &rect);
}
else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
- draw_viewport_name(ar, v3d);
+ draw_viewport_name(ar, v3d, &rect);
}
if (grid_unit) { /* draw below the viewport name */
@@ -3208,7 +3456,8 @@ static void view3d_main_area_draw_info(const bContext *C, ARegion *ar, const cha
BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
}
- BLF_draw_default_ascii(22, ar->winy - (USER_SHOW_VIEWPORTNAME ? 40 : 20), 0.0f,
+ BLF_draw_default_ascii(rect.xmin + U.widget_unit,
+ rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f,
numstr[0] ? numstr : grid_unit, sizeof(numstr));
}
}
@@ -3220,12 +3469,12 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar)
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
const char *grid_unit = NULL;
- int draw_border = FALSE;
+ bool draw_border = false;
if (rv3d->persp == RV3D_CAMOB)
- draw_border = scene->r.mode & R_BORDER;
+ draw_border = (scene->r.mode & R_BORDER) != 0;
else
- draw_border = v3d->flag2 & V3D_RENDER_BORDER;
+ draw_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0;
/* draw viewport using opengl */
if (v3d->drawtype != OB_RENDER || !view3d_main_area_do_render_draw(C) || draw_border) {
@@ -3290,14 +3539,14 @@ static void bl_debug_draw(void)
if (_bl_debug_draw_quads_tot) {
int i;
cpack(0x00FF0000);
- glBegin(GL_LINE_LOOP);
for (i = 0; i < _bl_debug_draw_quads_tot; i ++) {
+ glBegin(GL_LINE_LOOP);
glVertex3fv(_bl_debug_draw_quads[i][0]);
glVertex3fv(_bl_debug_draw_quads[i][1]);
glVertex3fv(_bl_debug_draw_quads[i][2]);
glVertex3fv(_bl_debug_draw_quads[i][3]);
+ glEnd();
}
- glEnd();
}
if (_bl_debug_draw_edges_tot) {
int i;
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 3050b7efad2..9d9dd0535ff 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -83,9 +83,12 @@
#include "view3d_intern.h" /* own include */
+/* for ndof prints */
+// #define DEBUG_NDOF_MOTION
+
/* ********************** view3d_edit: view manipulations ********************* */
-int ED_view3d_camera_lock_check(View3D *v3d, RegionView3D *rv3d)
+bool ED_view3d_camera_lock_check(View3D *v3d, RegionView3D *rv3d)
{
return ((v3d->camera) &&
(v3d->camera->id.lib == NULL) &&
@@ -102,8 +105,8 @@ void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d)
}
}
-/* return TRUE if the camera is moved */
-int ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d)
+/* 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)) {
ObjectTfmProtectedChannels obtfm;
@@ -127,7 +130,7 @@ int ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d)
mult_m4_m4m4(parent_mat, diff_mat, root_parent->obmat);
BKE_object_tfm_protected_backup(root_parent, &obtfm);
- BKE_object_apply_mat4(root_parent, parent_mat, TRUE, FALSE);
+ BKE_object_apply_mat4(root_parent, parent_mat, true, false);
BKE_object_tfm_protected_restore(root_parent, &obtfm, root_parent->protectflag);
ob_update = v3d->camera;
@@ -146,10 +149,10 @@ int ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d)
WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, v3d->camera);
}
- return TRUE;
+ return true;
}
else {
- return FALSE;
+ return false;
}
}
@@ -306,7 +309,7 @@ void view3d_boxview_copy(ScrArea *sa, ARegion *ar)
}
/* 'clip' is used to know if our clip setting has changed */
-void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, short do_clip)
+void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip)
{
ARegion *ar_sync = NULL;
RegionView3D *rv3d = ar->regiondata;
@@ -320,7 +323,7 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, short do_clip)
viewlock = 0;
else if ((viewlock & RV3D_BOXVIEW) == 0) {
viewlock &= ~RV3D_BOXCLIP;
- do_clip = TRUE;
+ do_clip = true;
}
for (; ar; ar = ar->prev) {
@@ -364,11 +367,12 @@ typedef struct ViewOpsData {
float mousevec[3]; /* dolly only */
float reverse, dist0, camzoom0;
float grid, far;
- short axis_snap; /* view rotate only */
+ bool axis_snap; /* view rotate only */
+ float zfac;
/* use for orbit selection and auto-dist */
float ofs[3], dyn_ofs[3];
- short use_dyn_ofs;
+ bool use_dyn_ofs;
int origx, origy, oldx, oldy;
int origkey; /* the key that triggered the operator */
@@ -404,7 +408,7 @@ static void calctrackballvec(const rcti *rect, int mx, int my, float vec[3])
}
-static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event)
+static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *event)
{
static float lastofs[3] = {0, 0, 0};
RegionView3D *rv3d;
@@ -428,19 +432,33 @@ static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event)
vod->origx = vod->oldx = event->x;
vod->origy = vod->oldy = event->y;
vod->origkey = event->type; /* the key that triggered the operator. */
- vod->use_dyn_ofs = (U.uiflag & USER_ORBIT_SELECTION) ? 1 : 0;
+ vod->use_dyn_ofs = (U.uiflag & USER_ORBIT_SELECTION) != 0;
copy_v3_v3(vod->ofs, rv3d->ofs);
if (vod->use_dyn_ofs) {
- /* If there's no selection, lastofs is unmodified and last value since static */
- calculateTransformCenter(C, V3D_CENTROID, lastofs, NULL);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = OBACT;
+
+ if (ob && ob->mode & OB_MODE_ALL_PAINT) {
+ /* transformation is disabled for painting modes, which will make it
+ * so previous offset is used. This is annoying when you open file
+ * saved with active object in painting mode
+ */
+ copy_v3_v3(lastofs, ob->obmat[3]);
+ }
+ else {
+ /* If there's no selection, lastofs is unmodified and last value since static */
+ calculateTransformCenter(C, V3D_CENTROID, lastofs, NULL);
+ }
+
negate_v3_v3(vod->dyn_ofs, lastofs);
}
else if (U.uiflag & USER_ZBUF_ORBIT) {
+ Scene *scene = CTX_data_scene(C);
view3d_operator_needs_opengl(C); /* needed for zbuf drawing */
- if ((vod->use_dyn_ofs = ED_view3d_autodist(CTX_data_scene(C), vod->ar, vod->v3d, event->mval, vod->dyn_ofs))) {
+ if ((vod->use_dyn_ofs = ED_view3d_autodist(scene, vod->ar, vod->v3d, event->mval, vod->dyn_ofs, true))) {
if (rv3d->is_persp) {
float my_origin[3]; /* original G.vd->ofs */
float my_pivot[3]; /* view */
@@ -488,7 +506,11 @@ static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event)
calctrackballvec(&vod->ar->winrct, event->x, event->y, vod->trackvec);
- initgrabz(rv3d, -rv3d->ofs[0], -rv3d->ofs[1], -rv3d->ofs[2]);
+ {
+ float tvec[3];
+ negate_v3_v3(tvec, rv3d->ofs);
+ vod->zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL);
+ }
vod->reverse = 1.0f;
if (rv3d->persmat[2][1] < 0.0f)
@@ -820,7 +842,7 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y)
ED_region_tag_redraw(vod->ar);
}
-static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod = op->customdata;
short event_code = VIEW_PASS;
@@ -835,11 +857,11 @@ static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event)
event_code = VIEW_CONFIRM;
break;
case VIEWROT_MODAL_AXIS_SNAP_ENABLE:
- vod->axis_snap = TRUE;
+ vod->axis_snap = true;
event_code = VIEW_APPLY;
break;
case VIEWROT_MODAL_AXIS_SNAP_DISABLE:
- vod->axis_snap = FALSE;
+ vod->axis_snap = false;
event_code = VIEW_APPLY;
break;
case VIEWROT_MODAL_SWITCH_ZOOM:
@@ -869,7 +891,7 @@ static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
RegionView3D *rv3d;
@@ -908,7 +930,12 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
if (event->type == MOUSEPAN) {
- viewrotate_apply(vod, event->prevx, event->prevy);
+ /* 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(rv3d);
viewops_data_free(C, op);
@@ -958,7 +985,7 @@ static int viewrotate_cancel(bContext *C, wmOperator *op)
void VIEW3D_OT_rotate(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Rotate view";
+ ot->name = "Rotate View";
ot->description = "Rotate the view";
ot->idname = "VIEW3D_OT_rotate";
@@ -975,12 +1002,12 @@ void VIEW3D_OT_rotate(wmOperatorType *ot)
/* NDOF utility functions
* (should these functions live in this file?)
*/
-float ndof_to_axis_angle(struct wmNDOFMotionData *ndof, float axis[3])
+float ndof_to_axis_angle(const struct wmNDOFMotionData *ndof, float axis[3])
{
return ndof->dt * normalize_v3_v3(axis, ndof->rvec);
}
-void ndof_to_quat(struct wmNDOFMotionData *ndof, float q[4])
+void ndof_to_quat(const struct wmNDOFMotionData *ndof, float q[4])
{
float axis[3];
float angle;
@@ -989,23 +1016,104 @@ void ndof_to_quat(struct wmNDOFMotionData *ndof, float q[4])
axis_angle_to_quat(q, axis, angle);
}
+static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof, RegionView3D *rv3d, const float view_inv[4],
+ const float rot_sensitivity, const float dt,
+ /* optional, can be NULL*/
+ ViewOpsData *vod)
+{
+ if (U.ndof_flag & NDOF_TURNTABLE) {
+
+ /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */
+ float angle, rot[4];
+ float xvec[3] = {1, 0, 0};
+
+ /* Determine the direction of the x vector (for rotating up and down) */
+ mul_qt_v3(view_inv, xvec);
+
+ /* Perform the up/down rotation */
+ angle = rot_sensitivity * dt * ndof->rx;
+ if (U.ndof_flag & NDOF_TILT_INVERT_AXIS)
+ angle = -angle;
+ rot[0] = cosf(angle);
+ mul_v3_v3fl(rot + 1, xvec, sin(angle));
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
+
+ /* Perform the orbital rotation */
+ angle = rot_sensitivity * dt * ndof->ry;
+ if (U.ndof_flag & NDOF_ROTATE_INVERT_AXIS)
+ angle = -angle;
+
+ /* update the onscreen doo-dad */
+ rv3d->rot_angle = angle;
+ rv3d->rot_axis[0] = 0;
+ rv3d->rot_axis[1] = 0;
+ rv3d->rot_axis[2] = 1;
+
+ rot[0] = cosf(angle);
+ rot[1] = rot[2] = 0.0;
+ rot[3] = sinf(angle);
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
+
+ }
+ else {
+ float rot[4];
+ float axis[3];
+ float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis);
+
+ if (U.ndof_flag & NDOF_ROLL_INVERT_AXIS) axis[2] = -axis[2];
+ if (U.ndof_flag & NDOF_TILT_INVERT_AXIS) axis[0] = -axis[0];
+ if (U.ndof_flag & NDOF_ROTATE_INVERT_AXIS) axis[1] = -axis[1];
+
+
+ /* transform rotation axis from view to world coordinates */
+ mul_qt_v3(view_inv, axis);
+
+ /* update the onscreen doo-dad */
+ rv3d->rot_angle = angle;
+ copy_v3_v3(rv3d->rot_axis, axis);
+
+ axis_angle_to_quat(rot, axis, angle);
+
+ /* apply rotation */
+ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
+ }
+
+ /* rotate around custom center */
+ if (vod && vod->use_dyn_ofs) {
+ float q1[4];
+
+ /* compute the post multiplication quat, to rotate the offset correctly */
+ conjugate_qt_qt(q1, vod->oldquat);
+ mul_qt_qtqt(q1, q1, rv3d->viewquat);
+
+ conjugate_qt(q1); /* conj == inv for unit quat */
+ copy_v3_v3(rv3d->ofs, vod->ofs);
+ sub_v3_v3(rv3d->ofs, vod->dyn_ofs);
+ mul_qt_v3(q1, rv3d->ofs);
+ add_v3_v3(rv3d->ofs, vod->dyn_ofs);
+ }
+}
+
/* -- "orbit" navigation (trackball/turntable)
* -- zooming
* -- panning in rotationally-locked views
*/
-static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewOpsData *vod = op->customdata;
if (event->type != NDOF_MOTION)
return OPERATOR_CANCELLED;
else {
View3D *v3d = CTX_wm_view3d(C);
+ ViewOpsData *vod;
RegionView3D *rv3d = CTX_wm_region_view3d(C);
wmNDOFMotionData *ndof = (wmNDOFMotionData *) event->customdata;
ED_view3d_camera_lock_init(v3d, rv3d);
+ viewops_data_create(C, op, event);
+ vod = op->customdata;
+
rv3d->rot_angle = 0.f; /* off by default, until changed later this function */
if (ndof->progress != P_FINISHING) {
@@ -1022,11 +1130,10 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event)
float view_inv[4];
invert_qt_qt(view_inv, rv3d->viewquat);
- /* #define DEBUG_NDOF_MOTION */
- #ifdef DEBUG_NDOF_MOTION
+#ifdef DEBUG_NDOF_MOTION
printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f delivered to 3D view\n",
ndof->tx, ndof->ty, ndof->tz, ndof->rx, ndof->ry, ndof->rz, ndof->dt);
- #endif
+#endif
if (rv3d->viewlock == RV3D_LOCKED) {
/* rotation not allowed -- explore panning options instead */
@@ -1042,89 +1149,109 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
if (has_rotation) {
-
rv3d->view = RV3D_VIEW_USER;
+ view3d_ndof_orbit(ndof, rv3d, view_inv, rot_sensitivity, dt, vod);
+ }
+ }
- if (U.ndof_flag & NDOF_TURNTABLE) {
-
- /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */
- float angle, rot[4];
- float xvec[3] = {1, 0, 0};
-
- /* Determine the direction of the x vector (for rotating up and down) */
- mul_qt_v3(view_inv, xvec);
-
- /* Perform the up/down rotation */
- angle = rot_sensitivity * dt * ndof->rx;
- if (U.ndof_flag & NDOF_TILT_INVERT_AXIS)
- angle = -angle;
- rot[0] = cos(angle);
- mul_v3_v3fl(rot + 1, xvec, sin(angle));
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
-
- /* Perform the orbital rotation */
- angle = rot_sensitivity * dt * ndof->ry;
- if (U.ndof_flag & NDOF_ROTATE_INVERT_AXIS)
- angle = -angle;
-
- /* update the onscreen doo-dad */
- rv3d->rot_angle = angle;
- rv3d->rot_axis[0] = 0;
- rv3d->rot_axis[1] = 0;
- rv3d->rot_axis[2] = 1;
-
- rot[0] = cos(angle);
- rot[1] = rot[2] = 0.0;
- rot[3] = sin(angle);
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
-
- }
- else {
- float rot[4];
- float axis[3];
- float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis);
+ viewops_data_free(C, op);
+
+ ED_view3d_camera_lock_sync(v3d, rv3d);
+
+ ED_region_tag_redraw(CTX_wm_region(C));
- if (U.ndof_flag & NDOF_ROLL_INVERT_AXIS)
- axis[2] = -axis[2];
+ return OPERATOR_FINISHED;
+ }
+}
- if (U.ndof_flag & NDOF_TILT_INVERT_AXIS)
- axis[0] = -axis[0];
+void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "NDOF Orbit View";
+ ot->description = "Explore every angle of an object using the 3D mouse";
+ ot->idname = "VIEW3D_OT_ndof_orbit";
- if (U.ndof_flag & NDOF_ROTATE_INVERT_AXIS)
- axis[1] = -axis[1];
-
+ /* api callbacks */
+ ot->invoke = ndof_orbit_invoke;
+ ot->poll = ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag = 0;
+}
+
+
+static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+
+ if (event->type != NDOF_MOTION)
+ return OPERATOR_CANCELLED;
+ else {
+ ViewOpsData *vod;
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ wmNDOFMotionData *ndof = (wmNDOFMotionData *) event->customdata;
- /* transform rotation axis from view to world coordinates */
- mul_qt_v3(view_inv, axis);
+ ED_view3d_camera_lock_init(v3d, rv3d);
- /* update the onscreen doo-dad */
- rv3d->rot_angle = angle;
- copy_v3_v3(rv3d->rot_axis, axis);
+ rv3d->rot_angle = 0.f; /* off by default, until changed later this function */
- axis_angle_to_quat(rot, axis, angle);
+ viewops_data_create(C, op, event);
+ vod = op->customdata;
- /* apply rotation */
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
-
- }
-
- /* rotate around custom center */
- if (vod && vod->use_dyn_ofs) {
- float q1[4];
-
- /* compute the post multiplication quat, to rotate the offset correctly */
- conjugate_qt_qt(q1, vod->oldquat);
- mul_qt_qtqt(q1, q1, rv3d->viewquat);
-
- conjugate_qt(q1); /* conj == inv for unit quat */
- copy_v3_v3(rv3d->ofs, vod->ofs);
- sub_v3_v3(rv3d->ofs, vod->dyn_ofs);
- mul_qt_v3(q1, rv3d->ofs);
- add_v3_v3(rv3d->ofs, vod->dyn_ofs);
- }
+ if (ndof->progress != P_FINISHING) {
+ const float dt = ndof->dt;
+
+ /* tune these until everything feels right */
+ const float rot_sensitivity = 1.f;
+
+ const float zoom_sensitivity = 1.f;
+
+ const float pan_sensitivity = 1.f;
+ const int has_rotation = rv3d->viewlock != RV3D_LOCKED && !is_zero_v3(ndof->rvec);
+
+ float view_inv[4];
+ invert_qt_qt(view_inv, rv3d->viewquat);
+
+#ifdef DEBUG_NDOF_MOTION
+ printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f delivered to 3D view\n",
+ ndof->tx, ndof->ty, ndof->tz, ndof->rx, ndof->ry, ndof->rz, ndof->dt);
+#endif
+
+ if (ndof->tz) {
+ /* Zoom!
+ * velocity should be proportional to the linear velocity attained by rotational motion of same strength
+ * [got that?]
+ * proportional to arclength = radius * angle
+ */
+ float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tz;
+
+ if (U.ndof_flag & NDOF_ZOOM_INVERT)
+ zoom_distance = -zoom_distance;
+
+ rv3d->dist += zoom_distance;
+ }
+
+ if (rv3d->viewlock == RV3D_LOCKED) {
+ /* rotation not allowed -- explore panning options instead */
+ float pan_vec[3] = {ndof->tx, ndof->ty, 0.0f};
+ mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt);
+
+ /* transform motion from view to world coordinates */
+ invert_qt_qt(view_inv, rv3d->viewquat);
+ mul_qt_v3(view_inv, pan_vec);
+
+ /* move center of view opposite of hand motion (this is camera mode, not object mode) */
+ sub_v3_v3(rv3d->ofs, pan_vec);
+ }
+
+ if (has_rotation) {
+ rv3d->view = RV3D_VIEW_USER;
+ view3d_ndof_orbit(ndof, rv3d, view_inv, rot_sensitivity, dt, vod);
}
}
+ viewops_data_free(C, op);
+
ED_view3d_camera_lock_sync(v3d, rv3d);
ED_region_tag_redraw(CTX_wm_region(C));
@@ -1133,15 +1260,15 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
}
-void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot)
+void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot)
{
/* identifiers */
- ot->name = "NDOF Orbit View";
+ ot->name = "NDOF Orbit View with Zoom";
ot->description = "Explore every angle of an object using the 3D mouse";
- ot->idname = "VIEW3D_OT_ndof_orbit";
+ ot->idname = "VIEW3D_OT_ndof_orbit_zoom";
/* api callbacks */
- ot->invoke = ndof_orbit_invoke;
+ ot->invoke = ndof_orbit_zoom_invoke;
ot->poll = ED_operator_view3d_active;
/* flags */
@@ -1151,7 +1278,7 @@ void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot)
/* -- "pan" navigation
* -- zoom or dolly?
*/
-static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
if (event->type != NDOF_MOTION)
return OPERATOR_CANCELLED;
@@ -1184,8 +1311,7 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt);
#else /* ------------------------------------------------------- dolly with Z */
- float speed = 10.f; /* blender units per second */
- /* ^^ this is ok for default cube scene, but should scale with.. something */
+ float speed = rv3d->dist; /* uses distance from pivot to define dolly */
/* tune these until everything feels right */
const float forward_sensitivity = 1.f;
@@ -1246,10 +1372,11 @@ void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot)
/*
* this is basically just the pan only code + the rotate only code crammed into one function that does both
*/
-static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int ndof_all_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (event->type != NDOF_MOTION)
+ if (event->type != NDOF_MOTION) {
return OPERATOR_CANCELLED;
+ }
else {
ViewOpsData *vod;
@@ -1269,23 +1396,14 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
const float dt = ndof->dt;
float view_inv[4];
- float speed = 10.f; /* blender units per second */
- /* ^^ this is ok for default cube scene, but should scale with.. something */
+ float speed = rv3d->dist; /* uses distance from pivot to define dolly */
/* tune these until everything feels right */
const float forward_sensitivity = 1.f;
const float vertical_sensitivity = 0.4f;
const float lateral_sensitivity = 0.6f;
-
float pan_vec[3];
const float rot_sensitivity = 1.f;
-#if 0
- const float zoom_sensitivity = 1.f;
- const float pan_sensitivity = 1.f;
- float rot[4];
- float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis);
- float axis[3];
-#endif
/* inverse view */
invert_qt_qt(view_inv, rv3d->viewquat);
@@ -1312,89 +1430,16 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
/* move center of view opposite of hand motion (this is camera mode, not object mode) */
sub_v3_v3(rv3d->ofs, pan_vec);
-
- if (U.ndof_flag & NDOF_TURNTABLE) {
- /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */
- float angle, rot[4];
- float xvec[3] = {1, 0, 0};
-
- /* Determine the direction of the x vector (for rotating up and down) */
- mul_qt_v3(view_inv, xvec);
-
- /* Perform the up/down rotation */
- angle = rot_sensitivity * dt * ndof->rx;
- if (U.ndof_flag & NDOF_TILT_INVERT_AXIS)
- angle = -angle;
- rot[0] = cos(angle);
- mul_v3_v3fl(rot + 1, xvec, sin(angle));
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
-
- /* Perform the orbital rotation */
- angle = rot_sensitivity * dt * ndof->ry;
- if (U.ndof_flag & NDOF_ROTATE_INVERT_AXIS)
- angle = -angle;
-
- /* update the onscreen doo-dad */
- rv3d->rot_angle = angle;
- rv3d->rot_axis[0] = 0;
- rv3d->rot_axis[1] = 0;
- rv3d->rot_axis[2] = 1;
-
- rot[0] = cos(angle);
- rot[1] = rot[2] = 0.0;
- rot[3] = sin(angle);
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
-
- }
- else {
-
- float rot[4];
- float axis[3];
- float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis);
-
- if (U.ndof_flag & NDOF_ROLL_INVERT_AXIS)
- axis[2] = -axis[2];
-
- if (U.ndof_flag & NDOF_TILT_INVERT_AXIS)
- axis[0] = -axis[0];
-
- if (U.ndof_flag & NDOF_ROTATE_INVERT_AXIS)
- axis[1] = -axis[1];
-
- /* transform rotation axis from view to world coordinates */
- mul_qt_v3(view_inv, axis);
-
- /* update the onscreen doo-dad */
- rv3d->rot_angle = angle;
- copy_v3_v3(rv3d->rot_axis, axis);
-
- axis_angle_to_quat(rot, axis, angle);
-
- /* apply rotation */
- mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot);
-
- }
-
- /* rotate around custom center */
- if (vod && vod->use_dyn_ofs) {
- float q1[4];
-
- /* compute the post multiplication quat, to rotate the offset correctly */
- conjugate_qt_qt(q1, vod->oldquat);
- mul_qt_qtqt(q1, q1, rv3d->viewquat);
-
- conjugate_qt(q1); /* conj == inv for unit quat */
- copy_v3_v3(rv3d->ofs, vod->ofs);
- sub_v3_v3(rv3d->ofs, vod->dyn_ofs);
- mul_qt_v3(q1, rv3d->ofs);
- add_v3_v3(rv3d->ofs, vod->dyn_ofs);
- }
+ view3d_ndof_orbit(ndof, rv3d, view_inv, rot_sensitivity, dt, vod);
}
+
+ viewops_data_free(C, op);
+
ED_view3d_camera_lock_sync(v3d, rv3d);
ED_region_tag_redraw(CTX_wm_region(C));
- viewops_data_free(C, op);
+
return OPERATOR_FINISHED;
}
}
@@ -1402,7 +1447,7 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
void VIEW3D_OT_ndof_all(struct wmOperatorType *ot)
{
/* identifiers */
- ot->name = "NDOF move View";
+ ot->name = "NDOF Move View";
ot->description = "Position your viewpoint with the 3D mouse";
ot->idname = "VIEW3D_OT_ndof_all";
@@ -1469,7 +1514,7 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y)
mval_f[0] = x - vod->oldx;
mval_f[1] = y - vod->oldy;
- ED_view3d_win_to_delta(vod->ar, mval_f, dvec);
+ ED_view3d_win_to_delta(vod->ar, mval_f, dvec, vod->zfac);
add_v3_v3(vod->rv3d->ofs, dvec);
@@ -1486,7 +1531,7 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y)
}
-static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod = op->customdata;
@@ -1529,7 +1574,7 @@ static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static int viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
@@ -1538,7 +1583,8 @@ static int viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event)
vod = op->customdata;
if (event->type == MOUSEPAN) {
- viewmove_apply(vod, event->prevx, event->prevy);
+ /* invert it, trackpad scroll follows same principle as 2d windows this way */
+ viewmove_apply(vod, 2 * event->x - event->prevx, 2 * event->y - event->prevy);
ED_view3d_depth_tag_update(vod->rv3d);
viewops_data_free(C, op);
@@ -1564,7 +1610,7 @@ void VIEW3D_OT_move(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Move view";
+ ot->name = "Move View";
ot->description = "Move the view";
ot->idname = "VIEW3D_OT_move";
@@ -1625,15 +1671,16 @@ static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my)
float tpos[3];
float mval_f[2];
float new_dist;
+ float zfac;
negate_v3_v3(tpos, rv3d->ofs);
- /* Project cursor position into 3D space */
- initgrabz(rv3d, tpos[0], tpos[1], tpos[2]);
-
mval_f[0] = (float)(((mx - ar->winrct.xmin) * 2) - ar->winx) / 2.0f;
mval_f[1] = (float)(((my - ar->winrct.ymin) * 2) - ar->winy) / 2.0f;
- ED_view3d_win_to_delta(ar, mval_f, dvec);
+
+ /* Project cursor position into 3D space */
+ zfac = ED_view3d_calc_zfac(rv3d, tpos, NULL);
+ ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
/* Calculate view target position for dolly */
add_v3_v3v3(tvec, tpos, dvec);
@@ -1657,7 +1704,7 @@ static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my)
static void viewzoom_apply(ViewOpsData *vod, const int x, const int y, const short viewzoom, const short zoom_invert)
{
float zfac = 1.0;
- short use_cam_zoom;
+ bool use_cam_zoom;
use_cam_zoom = (vod->rv3d->persp == RV3D_CAMOB) && !(vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d));
@@ -1748,7 +1795,7 @@ static void viewzoom_apply(ViewOpsData *vod, const int x, const int y, const sho
}
-static int viewzoom_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod = op->customdata;
short event_code = VIEW_PASS;
@@ -1799,9 +1846,9 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
RegionView3D *rv3d;
ScrArea *sa;
ARegion *ar;
- short use_cam_zoom;
+ bool use_cam_zoom;
- int delta = RNA_int_get(op->ptr, "delta");
+ const int delta = RNA_int_get(op->ptr, "delta");
int mx, my;
if (op->customdata) {
@@ -1893,7 +1940,7 @@ void viewdolly_modal_keymap(wmKeyConfig *keyconf)
}
/* viewdolly_invoke() copied this function, changes here may apply there */
-static int viewzoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
@@ -1911,17 +1958,16 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
viewzoom_exec(C, op);
}
else {
- if (event->type == MOUSEZOOM) {
- /* Bypass Zoom invert flag for track pads (pass FALSE always) */
+ if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
if (U.uiflag & USER_ZOOM_HORIZ) {
vod->origx = vod->oldx = event->x;
- viewzoom_apply(vod, event->prevx, event->prevy, USER_ZOOM_DOLLY, (U.uiflag & USER_ZOOM_INVERT) == 0);
+ viewzoom_apply(vod, event->prevx, event->prevy, USER_ZOOM_DOLLY, (U.uiflag & USER_ZOOM_INVERT) != 0);
}
else {
/* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
vod->origy = vod->oldy = vod->origy + event->x - event->prevx;
- viewzoom_apply(vod, event->prevx, event->prevy, USER_ZOOM_DOLLY, (U.uiflag & USER_ZOOM_INVERT) == 0);
+ viewzoom_apply(vod, event->prevx, event->prevy, USER_ZOOM_DOLLY, (U.uiflag & USER_ZOOM_INVERT) != 0);
}
ED_view3d_depth_tag_update(vod->rv3d);
@@ -2014,7 +2060,7 @@ static void viewdolly_apply(ViewOpsData *vod, int x, int y, const short zoom_inv
}
-static int viewdolly_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod = op->customdata;
short event_code = VIEW_PASS;
@@ -2063,7 +2109,7 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
ARegion *ar;
float mousevec[3];
- int delta = RNA_int_get(op->ptr, "delta");
+ const int delta = RNA_int_get(op->ptr, "delta");
if (op->customdata) {
ViewOpsData *vod = op->customdata;
@@ -2106,7 +2152,7 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
}
/* copied from viewzoom_invoke(), changes here may apply there */
-static int viewdolly_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
@@ -2131,7 +2177,7 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
if (event->type == MOUSEZOOM) {
- /* Bypass Zoom invert flag for track pads (pass FALSE always) */
+ /* Bypass Zoom invert flag for track pads (pass false always) */
if (U.uiflag & USER_ZOOM_HORIZ) {
vod->origx = vod->oldx = event->x;
@@ -2187,7 +2233,7 @@ static int viewdolly_cancel(bContext *C, wmOperator *op)
void VIEW3D_OT_dolly(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Dolly view";
+ ot->name = "Dolly View";
ot->description = "Dolly in/out in the view";
ot->idname = "VIEW3D_OT_dolly";
@@ -2208,7 +2254,7 @@ void VIEW3D_OT_dolly(wmOperatorType *ot)
static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar,
const float min[3], const float max[3],
- int ok_dist)
+ bool ok_dist)
{
RegionView3D *rv3d = ar->regiondata;
float afm[3];
@@ -2219,7 +2265,7 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar,
float new_dist;
sub_v3_v3v3(afm, max, min);
- size = MAX3(afm[0], afm[1], afm[2]);
+ size = max_fff(afm[0], afm[1], afm[2]);
if (ok_dist) {
/* fix up zoom distance if needed */
@@ -2247,7 +2293,7 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar,
else { /* ortho */
if (size < 0.0001f) {
/* bounding box was a single point so do not zoom */
- ok_dist = 0;
+ ok_dist = false;
}
else {
/* adjust zoom so it looks nicer */
@@ -2282,7 +2328,7 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar,
/* same as view3d_from_minmax but for all regions (except cameras) */
static void view3d_from_minmax_multi(bContext *C, View3D *v3d,
const float min[3], const float max[3],
- const int ok_dist)
+ const bool ok_dist)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar;
@@ -2305,14 +2351,14 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in
Scene *scene = CTX_data_scene(C);
Base *base;
float *curs;
- const short use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions");
- const short skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) ||
- /* any one of the regions may be locked */
- (use_all_regions && v3d->flag2 & V3D_LOCK_CAMERA));
- int center = RNA_boolean_get(op->ptr, "center");
+ const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions");
+ const bool skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) ||
+ /* any one of the regions may be locked */
+ (use_all_regions && v3d->flag2 & V3D_LOCK_CAMERA));
+ const bool center = RNA_boolean_get(op->ptr, "center");
float min[3], max[3];
- int ok = 1, onedone = FALSE;
+ bool change = false;
if (center) {
/* in 2.4x this also move the cursor to (0, 0, 0) (with shift+c). */
@@ -2327,16 +2373,16 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in
for (base = scene->base.first; base; base = base->next) {
if (BASE_VISIBLE(v3d, base)) {
- onedone = TRUE;
+ change = true;
if (skip_camera && base->object == v3d->camera) {
continue;
}
- BKE_object_minmax(base->object, min, max, FALSE);
+ BKE_object_minmax(base->object, min, max, false);
}
}
- if (!onedone) {
+ if (!change) {
ED_region_tag_redraw(ar);
/* TODO - should this be cancel?
* I think no, because we always move the cursor, with or without
@@ -2348,15 +2394,11 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in
return OPERATOR_FINISHED;
}
- if (ok == 0) {
- return OPERATOR_FINISHED;
- }
-
if (use_all_regions) {
- view3d_from_minmax_multi(C, v3d, min, max, TRUE);
+ view3d_from_minmax_multi(C, v3d, min, max, true);
}
else {
- view3d_from_minmax(C, v3d, ar, min, max, TRUE);
+ view3d_from_minmax(C, v3d, ar, min, max, true);
}
return OPERATOR_FINISHED;
@@ -2393,11 +2435,11 @@ static int viewselected_exec(bContext *C, wmOperator *op)
Object *ob = OBACT;
Object *obedit = CTX_data_edit_object(C);
float min[3], max[3];
- int ok = 0, ok_dist = 1;
- const short use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions");
- const short skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) ||
- /* any one of the regions may be locked */
- (use_all_regions && v3d->flag2 & V3D_LOCK_CAMERA));
+ bool ok = false, ok_dist = true;
+ const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions");
+ const bool skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) ||
+ /* any one of the regions may be locked */
+ (use_all_regions && v3d->flag2 & V3D_LOCK_CAMERA));
INIT_MINMAX(min, max);
@@ -2460,8 +2502,8 @@ static int viewselected_exec(bContext *C, wmOperator *op)
}
/* account for duplis */
- if (BKE_object_minmax_dupli(scene, base->object, min, max, FALSE) == 0)
- BKE_object_minmax(base->object, min, max, FALSE); /* use if duplis not found */
+ if (BKE_object_minmax_dupli(scene, base->object, min, max, false) == 0)
+ BKE_object_minmax(base->object, min, max, false); /* use if duplis not found */
ok = 1;
}
@@ -2681,7 +2723,7 @@ static int render_border_exec(bContext *C, wmOperator *op)
rcti rect;
rctf vb, border;
- int camera_only = RNA_boolean_get(op->ptr, "camera_only");
+ const bool camera_only = RNA_boolean_get(op->ptr, "camera_only");
if (camera_only && rv3d->persp != RV3D_CAMOB)
return OPERATOR_PASS_THROUGH;
@@ -2692,7 +2734,7 @@ static int render_border_exec(bContext *C, wmOperator *op)
/* calculate range */
if (rv3d->persp == RV3D_CAMOB) {
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, FALSE);
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, false);
}
else {
vb.xmin = 0;
@@ -2851,7 +2893,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
/* Get Z Depths, needed for perspective, nice for ortho */
bgl_get_mats(&mats);
- draw_depth(scene, ar, v3d, NULL);
+ draw_depth(scene, ar, v3d, NULL, true);
{
/* avoid allocating the whole depth buffer */
@@ -2918,14 +2960,20 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
}
else {
float mval_f[2];
+ float zfac;
+
/* We cant use the depth, fallback to the old way that dosnt set the center depth */
copy_v3_v3(new_ofs, rv3d->ofs);
- initgrabz(rv3d, -new_ofs[0], -new_ofs[1], -new_ofs[2]);
+ {
+ float tvec[3];
+ negate_v3_v3(tvec, new_ofs);
+ zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL);
+ }
mval_f[0] = (rect.xmin + rect.xmax - vb[0]) / 2.0f;
mval_f[1] = (rect.ymin + rect.ymax - vb[1]) / 2.0f;
- ED_view3d_win_to_delta(ar, mval_f, dvec);
+ ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
/* center the view to the center of the rectangle */
sub_v3_v3(new_ofs, dvec);
}
@@ -2958,7 +3006,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int view3d_zoom_border_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int view3d_zoom_border_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
@@ -2989,7 +3037,7 @@ void VIEW3D_OT_zoom_border(wmOperatorType *ot)
ot->flag = 0;
/* rna */
- WM_operator_properties_gesture_border(ot, FALSE);
+ WM_operator_properties_gesture_border(ot, false);
}
/* sets the view to 1:1 camera/render-pixel */
@@ -3055,7 +3103,7 @@ static EnumPropertyItem prop_view_items[] = {
static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar,
float q1, float q2, float q3, float q4,
- short view, int perspo, int align_active)
+ short view, int perspo, bool align_active)
{
RegionView3D *rv3d = ar->regiondata; /* no NULL check is needed, poll checks */
float new_quat[4];
@@ -3069,14 +3117,14 @@ static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar,
Object *obact = CTX_data_active_object(C);
if (obact == NULL) {
/* no active object, ignore this option */
- align_active = FALSE;
+ align_active = false;
}
else {
float obact_quat[4];
float twmat[3][3];
/* same as transform manipulator when normal is set */
- ED_getTransformOrientationMatrix(C, twmat, FALSE);
+ ED_getTransformOrientationMatrix(C, twmat, false);
mat3_to_quat(obact_quat, twmat);
invert_qt(obact_quat);
@@ -3086,7 +3134,7 @@ static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar,
}
}
- if (align_active == FALSE) {
+ if (align_active == false) {
/* normal operation */
if (rv3d->viewlock) {
/* only pass on if */
@@ -3135,7 +3183,8 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
RegionView3D *rv3d;
Scene *scene = CTX_data_scene(C);
static int perspo = RV3D_PERSP;
- int viewnum, align_active, nextperspo;
+ int viewnum, nextperspo;
+ bool align_active;
/* no NULL check is needed, poll checks */
ED_view3d_context_user_region(C, &v3d, &ar);
@@ -3146,7 +3195,7 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
/* set this to zero, gets handled in axis_set_view */
if (rv3d->viewlock)
- align_active = 0;
+ align_active = false;
/* Use this to test if we started out with a camera */
@@ -3269,7 +3318,7 @@ void VIEW3D_OT_viewnumpad(wmOperatorType *ot)
PropertyRNA *prop;
/* identifiers */
- ot->name = "View numpad";
+ ot->name = "View Numpad";
ot->description = "Use a preset viewpoint";
ot->idname = "VIEW3D_OT_viewnumpad";
@@ -3376,16 +3425,19 @@ static int viewpan_exec(bContext *C, wmOperator *op)
ARegion *ar = CTX_wm_region(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
float vec[3];
+ const float co_zero[3] = {0.0f};
float mval_f[2] = {0.0f, 0.0f};
+ float zfac;
int pandir;
pandir = RNA_enum_get(op->ptr, "type");
- initgrabz(rv3d, 0.0, 0.0, 0.0);
- if (pandir == V3D_VIEW_PANRIGHT) { mval_f[0] = -32.0f; ED_view3d_win_to_delta(ar, mval_f, vec); }
- else if (pandir == V3D_VIEW_PANLEFT) { mval_f[0] = 32.0f; ED_view3d_win_to_delta(ar, mval_f, vec); }
- else if (pandir == V3D_VIEW_PANUP) { mval_f[1] = -25.0f; ED_view3d_win_to_delta(ar, mval_f, vec); }
- else if (pandir == V3D_VIEW_PANDOWN) { mval_f[1] = 25.0f; ED_view3d_win_to_delta(ar, mval_f, vec); }
+ zfac = ED_view3d_calc_zfac(rv3d, co_zero, NULL);
+ if (pandir == V3D_VIEW_PANRIGHT) { mval_f[0] = -32.0f; }
+ else if (pandir == V3D_VIEW_PANLEFT) { mval_f[0] = 32.0f; }
+ else if (pandir == V3D_VIEW_PANUP) { mval_f[1] = -25.0f; }
+ else if (pandir == V3D_VIEW_PANDOWN) { mval_f[1] = 25.0f; }
+ ED_view3d_win_to_delta(ar, mval_f, vec, zfac);
add_v3_v3(rv3d->ofs, vec);
if (rv3d->viewlock & RV3D_BOXVIEW)
@@ -3467,7 +3519,7 @@ static int background_image_add_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-static int background_image_add_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
View3D *v3d = CTX_wm_view3d(C);
Image *ima = NULL;
@@ -3506,7 +3558,9 @@ static int background_image_add_invoke(bContext *C, wmOperator *op, wmEvent *UNU
void VIEW3D_OT_background_image_add(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Add Background Image";
+ /* note: having key shortcut here is bad practice,
+ * but for now keep because this displays when dragging an image over the 3D viewport */
+ ot->name = "Add Background Image (Ctrl for Empty Object)";
ot->description = "Add a new background image";
ot->idname = "VIEW3D_OT_background_image_add";
@@ -3528,7 +3582,7 @@ void VIEW3D_OT_background_image_add(wmOperatorType *ot)
static int background_image_remove_exec(bContext *C, wmOperator *op)
{
View3D *v3d = CTX_wm_view3d(C);
- int index = RNA_int_get(op->ptr, "index");
+ const int index = RNA_int_get(op->ptr, "index");
BGpic *bgpic_rem = BLI_findlink(&v3d->bgpicbase, index);
if (bgpic_rem) {
@@ -3620,7 +3674,7 @@ static int view3d_clipping_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int view3d_clipping_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int view3d_clipping_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
ARegion *ar = CTX_wm_region(C);
@@ -3663,61 +3717,71 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot)
/* ***************** 3d cursor cursor op ******************* */
-/* mx my in region coords */
-static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+/* cursor position in vec, result in vec, mval in region coords */
+/* note: cannot use event->mval here (called by object_add() */
+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);
- float *fp = NULL;
float mval_fl[2];
- int flip;
- fp = give_cursor(scene, v3d);
-
- flip = initgrabz(rv3d, fp[0], fp[1], fp[2]);
+ float zfac;
+ bool flip;
+
+ zfac = ED_view3d_calc_zfac(rv3d, fp, &flip);
/* reset the depth based on the view offset (we _know_ the offset is infront of us) */
if (flip) {
negate_v3_v3(fp, rv3d->ofs);
/* re initialize, no need to check flip again */
- /* flip = */ initgrabz(rv3d, fp[0], fp[1], fp[2]);
+ zfac = ED_view3d_calc_zfac(rv3d, fp, NULL /* &flip */ );
}
if (ED_view3d_project_float_global(ar, fp, mval_fl, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- short depth_used = FALSE;
+ bool depth_used = false;
if (U.uiflag & USER_ZBUF_CURSOR) { /* maybe this should be accessed some other way */
view3d_operator_needs_opengl(C);
- if (ED_view3d_autodist(scene, ar, v3d, event->mval, fp))
- depth_used = TRUE;
+ if (ED_view3d_autodist(scene, ar, v3d, mval, fp, true))
+ depth_used = true;
}
- if (depth_used == FALSE) {
+ if (depth_used == false) {
float dvec[3];
- VECSUB2D(mval_fl, mval_fl, event->mval);
- ED_view3d_win_to_delta(ar, mval_fl, dvec);
+ VECSUB2D(mval_fl, mval_fl, mval);
+ ED_view3d_win_to_delta(ar, mval_fl, dvec, zfac);
sub_v3_v3(fp, dvec);
}
}
else {
- const float dx = ((float)(event->mval[0] - (ar->winx / 2))) * rv3d->zfac / (ar->winx / 2);
- const float dy = ((float)(event->mval[1] - (ar->winy / 2))) * rv3d->zfac / (ar->winy / 2);
+ const float dx = ((float)(mval[0] - (ar->winx / 2))) * zfac / (ar->winx / 2);
+ const float dy = ((float)(mval[1] - (ar->winy / 2))) * zfac / (ar->winy / 2);
const float fz = (rv3d->persmat[0][3] * fp[0] +
rv3d->persmat[1][3] * fp[1] +
rv3d->persmat[2][3] * fp[2] +
- rv3d->persmat[3][3]) / rv3d->zfac;
+ rv3d->persmat[3][3]) / zfac;
fp[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy + rv3d->persinv[2][0] * fz) - rv3d->ofs[0];
fp[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy + rv3d->persinv[2][1] * fz) - rv3d->ofs[1];
fp[2] = (rv3d->persinv[0][2] * dx + rv3d->persinv[1][2] * dy + rv3d->persinv[2][2] * fz) - rv3d->ofs[2];
}
+}
+
+static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ float *fp = give_cursor(scene, v3d);
+
+ ED_view3d_cursor3d_position(C, fp, event->mval);
+
if (v3d && v3d->localvd)
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
else
WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
-
+
return OPERATOR_FINISHED;
}
@@ -3744,7 +3808,7 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot)
/* ***************** manipulator op ******************* */
-static int manipulator_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
View3D *v3d = CTX_wm_view3d(C);
@@ -3780,7 +3844,7 @@ void VIEW3D_OT_manipulator(wmOperatorType *ot)
Transform_Properties(ot, P_CONSTRAINT);
}
-static int enable_manipulator_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int enable_manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
View3D *v3d = CTX_wm_view3d(C);
@@ -3851,7 +3915,7 @@ static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int marg
}
/* XXX todo Zooms in on a border drawn by the user */
-int ED_view3d_autodist(Scene *scene, ARegion *ar, View3D *v3d, const int mval[2], float mouse_worldloc[3])
+bool ED_view3d_autodist(Scene *scene, ARegion *ar, View3D *v3d, const int mval[2], float mouse_worldloc[3], bool alphaoverride)
{
bglMats mats; /* ZBuffer depth vars */
float depth_close = FLT_MAX;
@@ -3859,12 +3923,12 @@ int ED_view3d_autodist(Scene *scene, ARegion *ar, View3D *v3d, const int mval[2]
/* Get Z Depths, needed for perspective, nice for ortho */
bgl_get_mats(&mats);
- draw_depth(scene, ar, v3d, NULL);
+ draw_depth(scene, ar, v3d, NULL, alphaoverride);
depth_close = view_autodist_depth_margin(ar, mval, 4);
if (depth_close == FLT_MAX)
- return 0;
+ return false;
cent[0] = (double)mval[0];
cent[1] = (double)mval[1];
@@ -3872,33 +3936,31 @@ int ED_view3d_autodist(Scene *scene, ARegion *ar, View3D *v3d, const int mval[2]
if (!gluUnProject(cent[0], cent[1], depth_close,
mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2]))
{
- return 0;
+ return false;
}
mouse_worldloc[0] = (float)p[0];
mouse_worldloc[1] = (float)p[1];
mouse_worldloc[2] = (float)p[2];
- return 1;
+ return true;
}
-int ED_view3d_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode)
+void ED_view3d_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode)
{
/* Get Z Depths, needed for perspective, nice for ortho */
switch (mode) {
case 0:
- draw_depth(scene, ar, v3d, NULL);
+ draw_depth(scene, ar, v3d, NULL, true);
break;
case 1:
draw_depth_gpencil(scene, ar, v3d);
break;
}
-
- return 1;
}
-/* no 4x4 sampling, run view_autodist_init first */
-int ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_worldloc[3],
- int margin, float *force_depth)
+/* no 4x4 sampling, run #ED_view3d_autodist_init first */
+bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_worldloc[3],
+ int margin, float *force_depth)
{
bglMats mats; /* ZBuffer depth vars, could cache? */
float depth;
@@ -3911,7 +3973,7 @@ int ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_worldl
depth = view_autodist_depth_margin(ar, mval, margin);
if (depth == FLT_MAX)
- return 0;
+ return false;
cent[0] = (double)mval[0];
cent[1] = (double)mval[1];
@@ -3921,23 +3983,23 @@ int ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_worldl
if (!gluUnProject(cent[0], cent[1], depth,
mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2]))
{
- return 0;
+ return false;
}
mouse_worldloc[0] = (float)p[0];
mouse_worldloc[1] = (float)p[1];
mouse_worldloc[2] = (float)p[2];
- return 1;
+ return true;
}
-int ED_view3d_autodist_depth(ARegion *ar, const int mval[2], int margin, float *depth)
+bool ED_view3d_autodist_depth(ARegion *ar, const int mval[2], int margin, float *depth)
{
*depth = view_autodist_depth_margin(ar, mval, margin);
- return (*depth == FLT_MAX) ? 0 : 1;
+ return (*depth != FLT_MAX);
}
-static int depth_segment_cb(int x, int y, void *userData)
+static bool depth_segment_cb(int x, int y, void *userData)
{
struct { ARegion *ar; int margin; float depth; } *data = userData;
int mval[2];
@@ -3957,8 +4019,8 @@ static int depth_segment_cb(int x, int y, void *userData)
}
}
-int ED_view3d_autodist_depth_seg(ARegion *ar, const int mval_sta[2], const int mval_end[2],
- int margin, float *depth)
+bool ED_view3d_autodist_depth_seg(ARegion *ar, const int mval_sta[2], const int mval_end[2],
+ int margin, float *depth)
{
struct { ARegion *ar; int margin; float depth; } data = {NULL};
int p1[2];
@@ -3975,7 +4037,7 @@ int ED_view3d_autodist_depth_seg(ARegion *ar, const int mval_sta[2], const int m
*depth = data.depth;
- return (*depth == FLT_MAX) ? 0 : 1;
+ return (*depth != FLT_MAX);
}
/* problem - ofs[3] can be on same location as camera itself.
@@ -4089,7 +4151,7 @@ void ED_view3d_to_object(Object *ob, const float ofs[3], const float quat[4], co
{
float mat[4][4];
ED_view3d_to_m4(mat, ofs, quat, dist);
- BKE_object_apply_mat4(ob, mat, TRUE, TRUE);
+ BKE_object_apply_mat4(ob, mat, true, true);
}
BGpic *ED_view3D_background_image_new(View3D *v3d)
@@ -4132,6 +4194,6 @@ void ED_view3D_lock_clear(View3D *v3d)
{
v3d->ob_centre = NULL;
v3d->ob_centre_bone[0] = '\0';
- v3d->ob_centre_cursor = FALSE;
+ v3d->ob_centre_cursor = false;
v3d->flag2 &= ~V3D_LOCK_CAMERA;
}
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index cddfae53f6f..2cedf7da725 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -76,10 +76,23 @@ enum {
FLY_MODAL_PRECISION_ENABLE,
FLY_MODAL_PRECISION_DISABLE,
FLY_MODAL_FREELOOK_ENABLE,
- FLY_MODAL_FREELOOK_DISABLE
-
+ FLY_MODAL_FREELOOK_DISABLE,
+ FLY_MODAL_SPEED, /* mousepan typically */
};
+/* relative view axis locking - xlock, zlock */
+typedef enum eFlyPanState {
+ /* disabled */
+ FLY_AXISLOCK_STATE_OFF = 0,
+
+ /* enabled but not checking because mouse hasn't moved outside the margin since locking was checked an not needed
+ * when the mouse moves, locking is set to 2 so checks are done. */
+ FLY_AXISLOCK_STATE_IDLE = 1,
+
+ /* mouse moved and checking needed, if no view altering is done its changed back to #FLY_AXISLOCK_STATE_IDLE */
+ FLY_AXISLOCK_STATE_ACTIVE = 2
+} eFlyPanState;
+
/* called in transform_ops.c, on each regeneration of keymaps */
void fly_modal_keymap(wmKeyConfig *keyconf)
{
@@ -132,6 +145,8 @@ void fly_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, KM_ANY, 0, FLY_MODAL_ACCELERATE);
WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_ANY, 0, FLY_MODAL_DECELERATE);
+ WM_modalkeymap_add_item(keymap, MOUSEPAN, 0, 0, 0, FLY_MODAL_SPEED);
+
WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_PRESS, KM_ANY, 0, FLY_MODAL_PAN_ENABLE);
/* XXX - Bug in the event system, middle mouse release doesnt work */
WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, FLY_MODAL_PAN_DISABLE);
@@ -167,11 +182,11 @@ typedef struct FlyInfo {
wmTimer *timer; /* needed for redraws */
short state;
- short redraw;
- unsigned char use_precision;
+ bool redraw;
+ bool use_precision;
/* if the user presses shift they can look about
* without moving the direction there looking */
- unsigned char use_freelook;
+ bool use_freelook;
int mval[2]; /* latest 2D mouse values */
wmNDOFMotionData *ndof; /* latest 3D mouse values */
@@ -179,14 +194,9 @@ typedef struct FlyInfo {
/* fly state state */
float speed; /* the speed the view is moving per redraw */
short axis; /* Axis index to move along by default Z to move along the view */
- short pan_view; /* when true, pan the view instead of rotating */
-
- /* relative view axis locking - xlock, zlock
- * 0) disabled
- * 1) enabled but not checking because mouse hasn't moved outside the margin since locking was checked an not needed
- * when the mouse moves, locking is set to 2 so checks are done.
- * 2) mouse moved and checking needed, if no view altering is done its changed back to 1 */
- short xlock, zlock;
+ bool pan_view; /* when true, pan the view instead of rotating */
+
+ eFlyPanState xlock, zlock;
float xlock_momentum, zlock_momentum; /* nicer dynamics */
float grid; /* world scale 1.0 default */
@@ -205,7 +215,7 @@ typedef struct FlyInfo {
/* are we flying an ortho camera in perspective view,
* which was originall in ortho view?
* could probably figure it out but better be explicit */
- short is_ortho_cam;
+ bool is_ortho_cam;
void *obtfm; /* backup the objects transform */
/* compare between last state */
@@ -269,7 +279,7 @@ static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar),
#define FLY_CANCEL 1
#define FLY_CONFIRM 2
-static int initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *event)
+static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
float upvec[3]; /* tmp */
@@ -291,30 +301,30 @@ static int initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *event
if (fly->rv3d->persp == RV3D_CAMOB && fly->v3d->camera->id.lib) {
BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library");
- return FALSE;
+ return false;
}
if (fly->v3d->ob_centre) {
BKE_report(op->reports, RPT_ERROR, "Cannot fly when the view is locked to an object");
- return FALSE;
+ return false;
}
if (fly->rv3d->persp == RV3D_CAMOB && fly->v3d->camera->constraints.first) {
BKE_report(op->reports, RPT_ERROR, "Cannot fly an object with constraints");
- return FALSE;
+ return false;
}
fly->state = FLY_RUNNING;
fly->speed = 0.0f;
fly->axis = 2;
- fly->pan_view = FALSE;
- fly->xlock = FALSE;
- fly->zlock = FALSE;
+ fly->pan_view = false;
+ fly->xlock = FLY_AXISLOCK_STATE_OFF;
+ fly->zlock = FLY_AXISLOCK_STATE_OFF;
fly->xlock_momentum = 0.0f;
fly->zlock_momentum = 0.0f;
fly->grid = 1.0f;
- fly->use_precision = FALSE;
- fly->use_freelook = FALSE;
+ fly->use_precision = false;
+ fly->use_freelook = false;
#ifdef NDOF_FLY_DRAW_TOOMUCH
fly->redraw = 1;
@@ -339,7 +349,7 @@ static int initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *event
copy_m3_m4(mat, fly->rv3d->viewinv);
mul_m3_v3(mat, upvec);
if (fabsf(upvec[2]) < 0.1f) {
- fly->zlock = 1;
+ fly->zlock = FLY_AXISLOCK_STATE_IDLE;
}
upvec[0] = 0;
upvec[1] = 0;
@@ -351,10 +361,10 @@ static int initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *event
/* check for flying ortho camera - which we cant support well
* we _could_ also check for an ortho camera but this is easier */
if ((fly->rv3d->persp == RV3D_CAMOB) &&
- (fly->rv3d->is_persp == FALSE))
+ (fly->rv3d->is_persp == false))
{
((Camera *)fly->v3d->camera->data)->type = CAM_PERSP;
- fly->is_ortho_cam = TRUE;
+ fly->is_ortho_cam = true;
}
if (fly->rv3d->persp == RV3D_CAMOB) {
@@ -483,7 +493,7 @@ static int flyEnd(bContext *C, FlyInfo *fly)
return OPERATOR_CANCELLED;
}
-static void flyEvent(FlyInfo *fly, wmEvent *event)
+static void flyEvent(FlyInfo *fly, const wmEvent *event)
{
if (event->type == TIMER && event->customdata == fly->timer) {
fly->redraw = 1;
@@ -544,7 +554,22 @@ static void flyEvent(FlyInfo *fly, wmEvent *event)
case FLY_MODAL_CONFIRM:
fly->state = FLY_CONFIRM;
break;
-
+
+ /* speed adjusting with mousepan (trackpad) */
+ case FLY_MODAL_SPEED:
+ {
+ float fac = 0.02f * (event->prevy - event->y);
+
+ /* allowing to brake immediate */
+ if (fac > 0.0f && fly->speed < 0.0f)
+ fly->speed = 0.0f;
+ else if (fac < 0.0f && fly->speed > 0.0f)
+ fly->speed = 0.0f;
+ else
+ fly->speed += fly->grid * fac;
+
+ break;
+ }
case FLY_MODAL_ACCELERATE:
{
double time_currwheel;
@@ -583,11 +608,11 @@ static void flyEvent(FlyInfo *fly, wmEvent *event)
break;
}
case FLY_MODAL_PAN_ENABLE:
- fly->pan_view = TRUE;
+ fly->pan_view = true;
break;
case FLY_MODAL_PAN_DISABLE:
//XXX2.5 WM_cursor_warp(CTX_wm_window(C), cent_orig[0], cent_orig[1]);
- fly->pan_view = FALSE;
+ fly->pan_view = false;
break;
/* implement WASD keys,
@@ -659,40 +684,41 @@ static void flyEvent(FlyInfo *fly, wmEvent *event)
break;
case FLY_MODAL_AXIS_LOCK_X:
- if (fly->xlock)
- fly->xlock = 0;
+ if (fly->xlock != FLY_AXISLOCK_STATE_OFF)
+ fly->xlock = FLY_AXISLOCK_STATE_OFF;
else {
- fly->xlock = 2;
+ fly->xlock = FLY_AXISLOCK_STATE_ACTIVE;
fly->xlock_momentum = 0.0;
}
break;
case FLY_MODAL_AXIS_LOCK_Z:
- if (fly->zlock)
- fly->zlock = 0;
+ if (fly->zlock != FLY_AXISLOCK_STATE_OFF)
+ fly->zlock = FLY_AXISLOCK_STATE_OFF;
else {
- fly->zlock = 2;
+ fly->zlock = FLY_AXISLOCK_STATE_ACTIVE;
fly->zlock_momentum = 0.0;
}
break;
case FLY_MODAL_PRECISION_ENABLE:
- fly->use_precision = TRUE;
+ fly->use_precision = true;
break;
case FLY_MODAL_PRECISION_DISABLE:
- fly->use_precision = FALSE;
+ fly->use_precision = false;
break;
case FLY_MODAL_FREELOOK_ENABLE:
- fly->use_freelook = TRUE;
+ fly->use_freelook = true;
break;
case FLY_MODAL_FREELOOK_DISABLE:
- fly->use_freelook = FALSE;
+ fly->use_freelook = false;
break;
}
}
}
-static void move_camera(bContext *C, RegionView3D *rv3d, FlyInfo *fly, int orientationChanged, int positionChanged)
+static void flyMoveCamera(bContext *C, RegionView3D *rv3d, FlyInfo *fly,
+ const bool do_rotate, const bool do_translate)
{
/* we are in camera view so apply the view ofs and quat to the view matrix and set the camera to the view */
@@ -715,7 +741,7 @@ static void move_camera(bContext *C, RegionView3D *rv3d, FlyInfo *fly, int orien
ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
mult_m4_m4m4(diff_mat, view_mat, prev_view_imat);
mult_m4_m4m4(parent_mat, diff_mat, fly->root_parent->obmat);
- BKE_object_apply_mat4(fly->root_parent, parent_mat, TRUE, FALSE);
+ BKE_object_apply_mat4(fly->root_parent, parent_mat, true, false);
// BKE_object_where_is_calc(scene, fly->root_parent);
@@ -730,7 +756,7 @@ static void move_camera(bContext *C, RegionView3D *rv3d, FlyInfo *fly, int orien
else {
float view_mat[4][4];
ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
- BKE_object_apply_mat4(v3d->camera, view_mat, TRUE, FALSE);
+ BKE_object_apply_mat4(v3d->camera, view_mat, true, false);
id_key = &v3d->camera->id;
}
@@ -746,11 +772,11 @@ static void move_camera(bContext *C, RegionView3D *rv3d, FlyInfo *fly, int orien
* 2) on each subsequent frame
* TODO: need to check in future that frame changed before doing this
*/
- if (orientationChanged) {
+ if (do_rotate) {
KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID);
ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
}
- if (positionChanged) {
+ if (do_translate) {
KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID);
ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
}
@@ -816,7 +842,7 @@ static int flyApply(bContext *C, FlyInfo *fly)
/* scale the mouse movement by this value - scales mouse movement to the view size
- * moffset[0]/(ar->winx-xmargin*2) - window size minus margin (same for y)
+ * moffset[0] / (ar->winx-xmargin * 2) - window size minus margin (same for y)
*
* the mouse moves isn't linear */
@@ -833,7 +859,8 @@ static int flyApply(bContext *C, FlyInfo *fly)
/* Should we redraw? */
if ((fly->speed != 0.0f) ||
moffset[0] || moffset[1] ||
- fly->zlock || fly->xlock ||
+ (fly->zlock != FLY_AXISLOCK_STATE_OFF) ||
+ (fly->xlock != FLY_AXISLOCK_STATE_OFF) ||
dvec[0] || dvec[1] || dvec[2])
{
float dvec_tmp[3];
@@ -858,7 +885,7 @@ static int flyApply(bContext *C, FlyInfo *fly)
copy_m3_m4(mat, rv3d->viewinv);
- if (fly->pan_view == TRUE) {
+ if (fly->pan_view == true) {
/* pan only */
dvec_tmp[0] = -moffset[0];
dvec_tmp[1] = -moffset[1];
@@ -886,10 +913,10 @@ static int flyApply(bContext *C, FlyInfo *fly)
axis_angle_to_quat(tmp_quat, upvec, (float)moffset[1] * time_redraw * -FLY_ROTATE_FAC);
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
- if (fly->xlock)
- fly->xlock = 2; /* check for rotation */
- if (fly->zlock)
- fly->zlock = 2;
+ if (fly->xlock != FLY_AXISLOCK_STATE_OFF)
+ fly->xlock = FLY_AXISLOCK_STATE_ACTIVE; /* check for rotation */
+ if (fly->zlock != FLY_AXISLOCK_STATE_OFF)
+ fly->zlock = FLY_AXISLOCK_STATE_ACTIVE;
fly->xlock_momentum = 0.0f;
}
@@ -922,13 +949,13 @@ static int flyApply(bContext *C, FlyInfo *fly)
axis_angle_to_quat(tmp_quat, upvec, (float)moffset[0] * time_redraw * FLY_ROTATE_FAC);
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
- if (fly->xlock)
- fly->xlock = 2; /* check for rotation */
- if (fly->zlock)
- fly->zlock = 2;
+ if (fly->xlock != FLY_AXISLOCK_STATE_OFF)
+ fly->xlock = FLY_AXISLOCK_STATE_ACTIVE; /* check for rotation */
+ if (fly->zlock != FLY_AXISLOCK_STATE_OFF)
+ fly->zlock = FLY_AXISLOCK_STATE_ACTIVE;
}
- if (fly->zlock == 2) {
+ if (fly->zlock == FLY_AXISLOCK_STATE_ACTIVE) {
upvec[0] = 1.0f;
upvec[1] = 0.0f;
upvec[2] = 0.0f;
@@ -950,12 +977,13 @@ static int flyApply(bContext *C, FlyInfo *fly)
fly->zlock_momentum += FLY_ZUP_CORRECT_ACCEL;
}
else {
- fly->zlock = 1; /* don't check until the view rotates again */
+ fly->zlock = FLY_AXISLOCK_STATE_IDLE; /* don't check until the view rotates again */
fly->zlock_momentum = 0.0f;
}
}
- if (fly->xlock == 2 && moffset[1] == 0) { /* only apply xcorrect when mouse isn't applying x rot */
+ /* only apply xcorrect when mouse isn't applying x rot */
+ if (fly->xlock == FLY_AXISLOCK_STATE_ACTIVE && moffset[1] == 0) {
upvec[0] = 0;
upvec[1] = 0;
upvec[2] = 1;
@@ -977,7 +1005,7 @@ static int flyApply(bContext *C, FlyInfo *fly)
fly->xlock_momentum += 0.05f;
}
else {
- fly->xlock = 1; /* see above */
+ fly->xlock = FLY_AXISLOCK_STATE_IDLE; /* see above */
fly->xlock_momentum = 0.0f;
}
}
@@ -1017,8 +1045,13 @@ static int flyApply(bContext *C, FlyInfo *fly)
add_v3_v3(rv3d->ofs, dvec);
- if (rv3d->persp == RV3D_CAMOB)
- move_camera(C, rv3d, fly, (fly->xlock || fly->zlock || moffset[0] || moffset[1]), fly->speed);
+ if (rv3d->persp == RV3D_CAMOB) {
+ const bool do_rotate = ((fly->xlock != FLY_AXISLOCK_STATE_OFF) ||
+ (fly->zlock != FLY_AXISLOCK_STATE_OFF) ||
+ ((moffset[0] || moffset[1]) && !fly->pan_view));
+ const bool do_translate = (fly->speed != 0.0f || fly->pan_view);
+ flyMoveCamera(C, rv3d, fly, do_rotate, do_translate);
+ }
}
else {
@@ -1041,19 +1074,19 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly)
const int flag = U.ndof_flag;
#if 0
- int shouldRotate = (flag & NDOF_SHOULD_ROTATE) && (fly->pan_view == FALSE),
- shouldTranslate = (flag & (NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM));
+ bool do_rotate = (flag & NDOF_SHOULD_ROTATE) && (fly->pan_view == false);
+ bool do_translate = (flag & (NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM));
#endif
- int shouldRotate = (fly->pan_view == FALSE);
- int shouldTranslate = TRUE;
+ bool do_rotate = (fly->pan_view == false);
+ bool do_translate = true;
float view_inv[4];
invert_qt_qt(view_inv, rv3d->viewquat);
rv3d->rot_angle = 0.0f; /* disable onscreen rotation doo-dad */
- if (shouldTranslate) {
+ if (do_translate) {
const float forward_sensitivity = 1.0f;
const float vertical_sensitivity = 0.4f;
const float lateral_sensitivity = 0.6f;
@@ -1089,14 +1122,14 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly)
if (!is_zero_v3(trans)) {
/* move center of view opposite of hand motion (this is camera mode, not object mode) */
sub_v3_v3(rv3d->ofs, trans);
- shouldTranslate = TRUE;
+ do_translate = true;
}
else {
- shouldTranslate = FALSE;
+ do_translate = false;
}
}
- if (shouldRotate) {
+ if (do_rotate) {
const float turn_sensitivity = 1.0f;
float rotation[4];
@@ -1104,7 +1137,7 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly)
float angle = turn_sensitivity * ndof_to_axis_angle(ndof, axis);
if (fabsf(angle) > 0.0001f) {
- shouldRotate = TRUE;
+ do_rotate = true;
if (fly->use_precision)
angle *= 0.2f;
@@ -1146,22 +1179,22 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly)
rv3d->view = RV3D_VIEW_USER;
}
else {
- shouldRotate = FALSE;
+ do_rotate = false;
}
}
- if (shouldTranslate || shouldRotate) {
- fly->redraw = TRUE;
+ if (do_translate || do_rotate) {
+ fly->redraw = true;
if (rv3d->persp == RV3D_CAMOB) {
- move_camera(C, rv3d, fly, shouldRotate, shouldTranslate);
+ flyMoveCamera(C, rv3d, fly, do_rotate, do_translate);
}
}
return OPERATOR_FINISHED;
}
-static int fly_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int fly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
FlyInfo *fly;
@@ -1173,7 +1206,7 @@ static int fly_invoke(bContext *C, wmOperator *op, wmEvent *event)
op->customdata = fly;
- if (initFlyInfo(C, fly, op, event) == FALSE) {
+ if (initFlyInfo(C, fly, op, event) == false) {
MEM_freeN(op->customdata);
return OPERATOR_CANCELLED;
}
@@ -1196,10 +1229,10 @@ static int fly_cancel(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int fly_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int fly_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
int exit_code;
- short do_draw = FALSE;
+ bool do_draw = false;
FlyInfo *fly = op->customdata;
RegionView3D *rv3d = fly->rv3d;
Object *fly_object = fly->root_parent ? fly->root_parent : fly->v3d->camera;
@@ -1222,7 +1255,7 @@ static int fly_modal(bContext *C, wmOperator *op, wmEvent *event)
exit_code = flyEnd(C, fly);
if (exit_code != OPERATOR_RUNNING_MODAL)
- do_draw = TRUE;
+ do_draw = true;
if (do_draw) {
if (rv3d->persp == RV3D_CAMOB) {
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 79bf003a563..854bd9f6cf8 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -28,7 +28,6 @@
* \ingroup spview3d
*/
-
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
@@ -37,8 +36,6 @@
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
-#include "RNA_access.h"
-
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
@@ -57,18 +54,19 @@
#include "BKE_screen.h"
#include "BKE_tessmesh.h"
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
#include "ED_mesh.h"
#include "ED_util.h"
#include "ED_screen.h"
#include "ED_transform.h"
#include "ED_types.h"
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
#include "UI_interface.h"
#include "UI_resources.h"
@@ -149,7 +147,7 @@ static int view3d_layers_exec(bContext *C, wmOperator *op)
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = sa->spacedata.first;
int nr = RNA_int_get(op->ptr, "nr");
- int toggle = RNA_boolean_get(op->ptr, "toggle");
+ const bool toggle = RNA_boolean_get(op->ptr, "toggle");
if (nr < 0)
return OPERATOR_CANCELLED;
@@ -200,7 +198,7 @@ static int view3d_layers_exec(bContext *C, wmOperator *op)
if (v3d->scenelock) handle_view3d_lock(C);
- DAG_on_visible_update(CTX_data_main(C), FALSE);
+ DAG_on_visible_update(CTX_data_main(C), false);
ED_area_tag_redraw(sa);
@@ -209,7 +207,7 @@ static int view3d_layers_exec(bContext *C, wmOperator *op)
/* applies shift and alt, lazy coding or ok? :) */
/* the local per-keymap-entry keymap will solve it */
-static int view3d_layers_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int view3d_layers_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (event->ctrl || event->oskey)
return OPERATOR_PASS_THROUGH;
@@ -217,10 +215,10 @@ static int view3d_layers_invoke(bContext *C, wmOperator *op, wmEvent *event)
if (event->shift)
RNA_boolean_set(op->ptr, "extend", TRUE);
else
- RNA_boolean_set(op->ptr, "extend", FALSE);
+ RNA_boolean_set(op->ptr, "extend", false);
if (event->alt) {
- int nr = RNA_int_get(op->ptr, "nr") + 10;
+ const int nr = RNA_int_get(op->ptr, "nr") + 10;
RNA_int_set(op->ptr, "nr", nr);
}
view3d_layers_exec(C, op);
@@ -400,13 +398,13 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C)
block = uiLayoutGetBlock(row);
uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL,
0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0,
- "Vertex select - Shift-Click for multiple modes");
+ TIP_("Vertex select - Shift-Click for multiple modes"));
uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL,
0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0,
- "Edge select - Shift-Click for multiple modes, Ctrl-Click expands selection");
+ TIP_("Edge select - Shift-Click for multiple modes, Ctrl-Click expands selection"));
uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL,
0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0,
- "Face select - Shift-Click for multiple modes, Ctrl-Click expands selection");
+ TIP_("Face select - Shift-Click for multiple modes, Ctrl-Click expands selection"));
}
}
@@ -453,6 +451,13 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
uiItemR(layout, &v3dptr, "viewport_shade", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
if (obedit == NULL && is_paint) {
+
+ if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ /* Only for Weight Paint. makes no sense in other paint modes. */
+ row = uiLayoutRow(layout, TRUE);
+ uiItemR(row, &v3dptr, "pivot_point", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ }
+
/* Manipulators aren't used in paint modes */
if (!ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_PARTICLE_EDIT)) {
/* masks aren't used for sculpt and particle painting */
@@ -476,7 +481,9 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
uiItemR(row, &v3dptr, "pivot_point", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
/* pose/object only however we want to allow in weight paint mode too
- * so don't be totally strict and just check not-editmode for now */
+ * so don't be totally strict and just check not-editmode for now
+ * XXX We never get here when we are in Weight Paint mode
+ */
if (obedit == NULL) {
uiItemR(row, &v3dptr, "use_pivot_point_align", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
}
@@ -487,11 +494,17 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
block = uiLayoutGetBlock(row);
if (v3d->twflag & V3D_USE_MANIPULATOR) {
- but = uiDefIconButBitC(block, TOG, V3D_MANIP_TRANSLATE, B_MAN_TRANS, ICON_MAN_TRANS, 0, 0, UI_UNIT_X, UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0, TIP_("Translate manipulator - Shift-Click for multiple modes"));
+ but = uiDefIconButBitC(block, TOG, V3D_MANIP_TRANSLATE, B_MAN_TRANS, ICON_MAN_TRANS,
+ 0, 0, UI_UNIT_X, UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0,
+ TIP_("Translate manipulator - Shift-Click for multiple modes"));
uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
- but = uiDefIconButBitC(block, TOG, V3D_MANIP_ROTATE, B_MAN_ROT, ICON_MAN_ROT, 0, 0, UI_UNIT_X, UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0, TIP_("Rotate manipulator - Shift-Click for multiple modes"));
+ but = uiDefIconButBitC(block, TOG, V3D_MANIP_ROTATE, B_MAN_ROT, ICON_MAN_ROT,
+ 0, 0, UI_UNIT_X, UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0,
+ TIP_("Rotate manipulator - Shift-Click for multiple modes"));
uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
- but = uiDefIconButBitC(block, TOG, V3D_MANIP_SCALE, B_MAN_SCALE, ICON_MAN_SCALE, 0, 0, UI_UNIT_X, UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0, TIP_("Scale manipulator - Shift-Click for multiple modes"));
+ but = uiDefIconButBitC(block, TOG, V3D_MANIP_SCALE, B_MAN_SCALE, ICON_MAN_SCALE,
+ 0, 0, UI_UNIT_X, UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0,
+ TIP_("Scale manipulator - Shift-Click for multiple modes"));
uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
}
@@ -500,7 +513,8 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
}
str_menu = BIF_menustringTransformOrientation(C, "Orientation");
- but = uiDefButC(block, MENU, B_MAN_MODE, str_menu, 0, 0, 70 * dpi_fac, UI_UNIT_Y, &v3d->twmode, 0, 0, 0, 0, TIP_("Transform Orientation"));
+ but = uiDefButC(block, MENU, B_MAN_MODE, str_menu, 0, 0, 70 * dpi_fac, UI_UNIT_Y, &v3d->twmode, 0, 0, 0, 0,
+ TIP_("Transform Orientation"));
uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
MEM_freeN((void *)str_menu);
}
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index f8a7cdde8a5..11cd0fdb1d7 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -77,6 +77,7 @@ void VIEW3D_OT_zoom_camera_1_to_1(struct wmOperatorType *ot);
void VIEW3D_OT_move(struct wmOperatorType *ot);
void VIEW3D_OT_rotate(struct wmOperatorType *ot);
void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot);
+void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot);
void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot);
void VIEW3D_OT_ndof_all(struct wmOperatorType *ot);
void VIEW3D_OT_view_all(struct wmOperatorType *ot);
@@ -100,13 +101,16 @@ void VIEW3D_OT_clear_render_border(struct wmOperatorType *ot);
void VIEW3D_OT_zoom_border(struct wmOperatorType *ot);
void view3d_boxview_copy(ScrArea *sa, ARegion *ar);
-void ndof_to_quat(struct wmNDOFMotionData *ndof, float q[4]);
-float ndof_to_axis_angle(struct wmNDOFMotionData *ndof, float axis[3]);
+void ndof_to_quat(const struct wmNDOFMotionData *ndof, float q[4]);
+float ndof_to_axis_angle(const struct wmNDOFMotionData *ndof, float axis[3]);
/* view3d_fly.c */
void view3d_keymap(struct wmKeyConfig *keyconf);
void VIEW3D_OT_fly(struct wmOperatorType *ot);
+/* view3d_ruler.c */
+void VIEW3D_OT_ruler(struct wmOperatorType *ot);
+
/* drawanim.c */
void draw_motion_paths_init(View3D *v3d, struct ARegion *ar);
void draw_motion_path_instance(Scene *scene,
@@ -118,14 +122,14 @@ void draw_motion_paths_cleanup(View3D *v3d);
/* drawobject.c */
void draw_object(Scene *scene, struct ARegion *ar, View3D *v3d, Base *base, const short dflag);
-int draw_glsl_material(Scene *scene, struct Object *ob, View3D *v3d, const short dt);
-void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const short dt, int outline);
+bool draw_glsl_material(Scene *scene, struct Object *ob, View3D *v3d, const char dt);
+void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline);
void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob);
void drawaxes(float size, char drawtype);
void view3d_cached_text_draw_begin(void);
void view3d_cached_text_draw_add(const float co[3], const char *str, short xoffs, short flag, const unsigned char col[4]);
-void view3d_cached_text_draw_end(View3D * v3d, ARegion * ar, int depth_write, float mat[4][4]);
+void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, float mat[4][4]);
enum {
V3D_CACHE_TEXT_ZBUF = (1 << 0),
@@ -136,9 +140,9 @@ enum {
};
/* drawarmature.c */
-int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
- const short dt, const short dflag, const unsigned char ob_wire_col[4],
- const short is_outline);
+bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
+ const short dt, const short dflag, const unsigned char ob_wire_col[4],
+ const bool is_outline);
/* drawmesh.c */
void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
@@ -148,7 +152,7 @@ void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
/* view3d_draw.c */
void view3d_main_area_draw(const struct bContext *C, struct ARegion *ar);
-void draw_depth(Scene *scene, struct ARegion *ar, View3D *v3d, int (*func)(void *));
+void draw_depth(Scene *scene, struct ARegion *ar, View3D *v3d, int (*func)(void *), bool alphaoverride);
void draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d);
void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag);
@@ -172,7 +176,7 @@ void VIEW3D_OT_localview(struct wmOperatorType *ot);
void VIEW3D_OT_game_start(struct wmOperatorType *ot);
-int ED_view3d_boundbox_clip(RegionView3D * rv3d, float obmat[4][4], struct BoundBox *bb);
+bool ED_view3d_boundbox_clip(RegionView3D *rv3d, float obmat[4][4], const struct BoundBox *bb);
void view3d_smooth_view(struct bContext *C, struct View3D *v3d, struct ARegion *ar, struct Object *, struct Object *,
float *ofs, float *quat, float *dist, float *lens);
@@ -196,7 +200,7 @@ void view3d_toolshelf_register(struct ARegionType *art);
void view3d_tool_props_register(struct ARegionType *art);
/* view3d_snap.c */
-int ED_view3d_minmax_verts(struct Object *obedit, float min[3], float max[3]);
+bool ED_view3d_minmax_verts(struct Object *obedit, float min[3], float max[3]);
void VIEW3D_OT_snap_selected_to_grid(struct wmOperatorType *ot);
void VIEW3D_OT_snap_selected_to_cursor(struct wmOperatorType *ot);
@@ -235,7 +239,7 @@ void draw_smoke_heat(struct SmokeDomainSettings *domain, struct Object *ob);
#define VIEW3D_CAMERA_BORDER_HACK
#ifdef VIEW3D_CAMERA_BORDER_HACK
extern unsigned char view3d_camera_border_hack_col[3];
-extern short view3d_camera_border_hack_test;
+extern bool view3d_camera_border_hack_test;
#endif
#endif /* __VIEW3D_INTERN_H__ */
diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c
index 37607729d0d..81e890c37ee 100644
--- a/source/blender/editors/space_view3d/view3d_iterators.c
+++ b/source/blender/editors/space_view3d/view3d_iterators.c
@@ -27,6 +27,7 @@
#include "DNA_curve_types.h"
#include "DNA_lattice_types.h"
#include "DNA_meta_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_armature_types.h"
#include "DNA_object_types.h"
@@ -47,6 +48,12 @@
#include "ED_object.h"
#include "ED_view3d.h"
+typedef struct foreachScreenObjectVert_userData {
+ void (*func)(void *userData, MVert *mv, const float screen_co_b[2], int index);
+ void *userData;
+ ViewContext vc;
+ eV3DProjTest clip_flag;
+} foreachScreenObjectVert_userData;
typedef struct foreachScreenVert_userData {
void (*func)(void *userData, BMVert *eve, const float screen_co_b[2], int index);
@@ -79,6 +86,46 @@ typedef struct foreachScreenFace_userData {
/* ------------------------------------------------------------------------ */
+
+static void meshobject_foreachScreenVert__mapFunc(void *userData, int index, const float co[3],
+ const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+{
+ foreachScreenObjectVert_userData *data = userData;
+ struct MVert *mv = &((Mesh *)(data->vc.obact->data))->mvert[index];
+
+ if (!(mv->flag & ME_HIDE)) {
+ float screen_co[2];
+
+ if (ED_view3d_project_float_object(data->vc.ar, co, screen_co, data->clip_flag) != V3D_PROJ_RET_OK) {
+ return;
+ }
+
+ data->func(data->userData, mv, screen_co, index);
+ }
+}
+
+void meshobject_foreachScreenVert(
+ ViewContext *vc,
+ void (*func)(void *userData, MVert *eve, const float screen_co[2], int index),
+ void *userData, eV3DProjTest clip_flag)
+{
+ foreachScreenObjectVert_userData data;
+ DerivedMesh *dm = mesh_get_derived_deform(vc->scene, vc->obact, CD_MASK_BAREMESH);
+
+ data.vc = *vc;
+ data.func = func;
+ data.userData = userData;
+ data.clip_flag = clip_flag;
+
+ if (clip_flag & V3D_PROJ_TEST_CLIP_BB) {
+ ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
+ }
+
+ dm->foreachMappedVert(dm, meshobject_foreachScreenVert__mapFunc, &data);
+
+ dm->release(dm);
+}
+
static void mesh_foreachScreenVert__mapFunc(void *userData, int index, const float co[3],
const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
{
@@ -113,9 +160,8 @@ void mesh_foreachScreenVert(
ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
}
- EDBM_index_arrays_init(vc->em, 1, 0, 0);
+ EDBM_index_arrays_ensure(vc->em, BM_VERT);
dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
- EDBM_index_arrays_free(vc->em);
dm->release(dm);
}
@@ -172,9 +218,8 @@ void mesh_foreachScreenEdge(
ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */
}
- EDBM_index_arrays_init(vc->em, 0, 1, 0);
+ EDBM_index_arrays_ensure(vc->em, BM_EDGE);
dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
- EDBM_index_arrays_free(vc->em);
dm->release(dm);
}
@@ -209,9 +254,8 @@ void mesh_foreachScreenFace(
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- EDBM_index_arrays_init(vc->em, 0, 0, 1);
+ EDBM_index_arrays_ensure(vc->em, BM_FACE);
dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
- EDBM_index_arrays_free(vc->em);
dm->release(dm);
}
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 6105b5e4eb5..e567ebda4b7 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -43,15 +43,84 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BKE_blender.h"
+#include "BKE_context.h"
+#include "BKE_main.h"
+
#include "RNA_access.h"
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_screen.h"
#include "ED_transform.h"
#include "view3d_intern.h"
+/* ************************** copy paste ***************************** */
+
+static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
+{
+ char str[FILE_MAX];
+
+ BKE_copybuffer_begin();
+
+ /* context, selection, could be generalized */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
+ {
+ BKE_copybuffer_tag_ID(&ob->id);
+
+ }
+ CTX_DATA_END;
+
+ BLI_make_file_string("/", str, BLI_temporary_dir(), "copybuffer.blend");
+ BKE_copybuffer_save(str, op->reports);
+
+ return OPERATOR_FINISHED;
+}
+
+static void VIEW3D_OT_copybuffer(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name = "Copy Selection to Buffer";
+ ot->idname = "VIEW3D_OT_copybuffer";
+ ot->description = "Selected objects are saved in a temp file";
+
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = view3d_copybuffer_exec;
+ ot->poll = ED_operator_view3d_active;
+}
+
+static int view3d_pastebuffer_exec(bContext *C, wmOperator *op)
+{
+ char str[FILE_MAX];
+
+ BLI_make_file_string("/", str, BLI_temporary_dir(), "copybuffer.blend");
+ BKE_copybuffer_paste(C, str, op->reports);
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static void VIEW3D_OT_pastebuffer(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name = "Paste Selection from Buffer";
+ ot->idname = "VIEW3D_OT_pastebuffer";
+ ot->description = "Contents of copy buffer gets pasted";
+
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = view3d_pastebuffer_exec;
+ ot->poll = ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
/* ************************** registration **********************************/
@@ -62,6 +131,7 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_zoom);
WM_operatortype_append(VIEW3D_OT_zoom_camera_1_to_1);
WM_operatortype_append(VIEW3D_OT_dolly);
+ WM_operatortype_append(VIEW3D_OT_ndof_orbit_zoom);
WM_operatortype_append(VIEW3D_OT_ndof_orbit);
WM_operatortype_append(VIEW3D_OT_ndof_pan);
WM_operatortype_append(VIEW3D_OT_ndof_all);
@@ -96,7 +166,10 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_localview);
WM_operatortype_append(VIEW3D_OT_game_start);
WM_operatortype_append(VIEW3D_OT_fly);
+ WM_operatortype_append(VIEW3D_OT_ruler);
WM_operatortype_append(VIEW3D_OT_layers);
+ WM_operatortype_append(VIEW3D_OT_copybuffer);
+ WM_operatortype_append(VIEW3D_OT_pastebuffer);
WM_operatortype_append(VIEW3D_OT_properties);
WM_operatortype_append(VIEW3D_OT_toolshelf);
@@ -117,13 +190,13 @@ void view3d_keymap(wmKeyConfig *keyconf)
wmKeyMapItem *kmi;
keymap = WM_keymap_find(keyconf, "3D View Generic", SPACE_VIEW3D, 0);
-
+
WM_keymap_add_item(keymap, "VIEW3D_OT_properties", NKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_toolshelf", TKEY, KM_PRESS, 0, 0);
/* only for region 3D window */
keymap = WM_keymap_find(keyconf, "3D View", SPACE_VIEW3D, 0);
-
+
kmi = WM_keymap_verify_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_ANY, 0);
RNA_boolean_set(kmi->ptr, "release_confirm", TRUE);
/*
@@ -149,10 +222,11 @@ void view3d_keymap(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "VIEW3D_OT_smoothview", TIMER1, KM_ANY, KM_ANY, 0);
- WM_keymap_add_item(keymap, "VIEW3D_OT_rotate", MOUSEPAN, 0, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_rotate", MOUSEPAN, 0, 0, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_rotate", MOUSEROTATE, 0, 0, 0);
- WM_keymap_add_item(keymap, "VIEW3D_OT_move", MOUSEPAN, 0, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_move", MOUSEPAN, 0, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", MOUSEZOOM, 0, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", MOUSEPAN, 0, KM_CTRL, 0);
/*numpad +/-*/
RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", PADPLUSKEY, KM_PRESS, 0, 0)->ptr, "delta", 1);
@@ -170,6 +244,8 @@ void view3d_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "VIEW3D_OT_view_center_camera", HOMEKEY, KM_PRESS, 0, 0); /* only with camera view */
+ WM_keymap_add_item(keymap, "VIEW3D_OT_view_center_cursor", HOMEKEY, KM_PRESS, KM_ALT, 0);
+
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "center", FALSE); /* only without camera view */
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", HOMEKEY, KM_PRESS, KM_CTRL, 0);
@@ -226,11 +302,16 @@ void view3d_keymap(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD7, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_BOTTOM);
RNA_boolean_set(kmi->ptr, "align_active", TRUE);
+
+ WM_keymap_add_item(keymap, "VIEW3D_OT_localview", PADSLASHKEY, KM_PRESS, 0, 0);
+ /* NDOF: begin */
+ /* note: positioned here so keymaps show keyboard keys if assigned */
/* 3D mouse */
+ WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit_zoom", NDOF_MOTION, 0, 0, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit", NDOF_MOTION, 0, KM_CTRL, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_pan", NDOF_MOTION, 0, KM_SHIFT, 0);
- WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_all", NDOF_MOTION, 0, 0, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_all", NDOF_MOTION, 0, KM_CTRL | KM_SHIFT, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BACK, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BACK);
@@ -238,7 +319,7 @@ void view3d_keymap(wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_RIGHT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_RIGHT);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_TOP);
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BOTTOM, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BOTTOM);
-
+
/* 3D mouse align */
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_FRONT);
@@ -249,9 +330,9 @@ void view3d_keymap(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_TOP);
RNA_boolean_set(kmi->ptr, "align_active", TRUE);
-
- WM_keymap_add_item(keymap, "VIEW3D_OT_localview", PADSLASHKEY, KM_PRESS, 0, 0);
+ /* NDOF: end */
+
/* layers, shift + alt are properties set in invoke() */
RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", ACCENTGRAVEKEY, KM_PRESS, 0, 0)->ptr, "nr", 0);
RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", ONEKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 1);
@@ -359,6 +440,13 @@ void view3d_keymap(wmKeyConfig *keyconf)
WM_keymap_add_menu(keymap, "VIEW3D_MT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
+#ifdef __APPLE__
+ WM_keymap_add_item(keymap, "VIEW3D_OT_copybuffer", CKEY, KM_PRESS, KM_OSKEY, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_pastebuffer", VKEY, KM_PRESS, KM_OSKEY, 0);
+#endif
+ WM_keymap_add_item(keymap, "VIEW3D_OT_copybuffer", CKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "VIEW3D_OT_pastebuffer", VKEY, KM_PRESS, KM_CTRL, 0);
+
/* context ops */
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");
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index 34b983f83df..7d728234c92 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -43,6 +43,7 @@
#include "ED_view3d.h" /* own include */
#define BL_NEAR_CLIP 0.001
+#define BL_ZERO_CLIP 0.001
/* Non Clipping Projection Functions
* ********************************* */
@@ -72,7 +73,7 @@ void ED_view3d_project_float_v2_m4(const ARegion *ar, const float co[3], float r
/**
* \note use #ED_view3d_ob_project_mat_get to get projecting mat
*/
-void ED_view3d_project_float_v3_m4(ARegion *ar, const float vec[3], float r_co[3], float mat[4][4])
+void ED_view3d_project_float_v3_m4(const ARegion *ar, const float vec[3], float r_co[3], float mat[4][4])
{
float vec4[4];
@@ -96,7 +97,7 @@ void ED_view3d_project_float_v3_m4(ARegion *ar, const float vec[3], float r_co[3
/* Clipping Projection Functions
* ***************************** */
-eV3DProjStatus ED_view3d_project_base(struct ARegion *ar, struct Base *base)
+eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct Base *base)
{
eV3DProjStatus ret = ED_view3d_project_short_global(ar, base->object->obmat[3], &base->sx, V3D_PROJ_TEST_CLIP_DEFAULT);
@@ -109,14 +110,14 @@ eV3DProjStatus ED_view3d_project_base(struct ARegion *ar, struct Base *base)
}
/* perspmat is typically...
- * - 'rv3d->perspmat', is_local == FALSE
- * - 'rv3d->perspmatob', is_local == TRUE
+ * - 'rv3d->perspmat', is_local == false
+ * - 'rv3d->persmatob', is_local == true
*/
-static eV3DProjStatus ed_view3d_project__internal(ARegion *ar,
- float perspmat[4][4], const int is_local, /* normally hidden */
+static eV3DProjStatus ed_view3d_project__internal(const ARegion *ar,
+ float perspmat[4][4], const bool is_local, /* normally hidden */
const float co[3], float r_co[2], const eV3DProjTest flag)
{
- float fx, fy, vec4[4];
+ float vec4[4];
/* check for bad flags */
BLI_assert((flag & V3D_PROJ_TEST_ALL) == flag);
@@ -134,30 +135,43 @@ static eV3DProjStatus ed_view3d_project__internal(ARegion *ar,
vec4[3] = 1.0;
mul_m4_v4(perspmat, vec4);
- if (vec4[3] > (float)BL_NEAR_CLIP) {
- fx = ((float)ar->winx / 2.0f) * (1.0f + vec4[0] / vec4[3]);
- if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fx > 0 && fx < ar->winx)) {
- fy = ((float)ar->winy / 2.0f) * (1.0f + vec4[1] / vec4[3]);
- if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fy > 0.0f && fy < (float)ar->winy)) {
- r_co[0] = (short)floor(fx);
- r_co[1] = (short)floor(fy);
+
+
+ if (((flag & V3D_PROJ_TEST_CLIP_ZERO) == 0) || (fabsf(vec4[3]) > (float)BL_ZERO_CLIP)) {
+ if (((flag & V3D_PROJ_TEST_CLIP_NEAR) == 0) || (vec4[3] > (float)BL_NEAR_CLIP)) {
+ const float scalar = (vec4[3] != 0.0f) ? (1.0f / vec4[3]): 0.0f;
+ const float fx = ((float)ar->winx / 2.0f) * (1.0f + (vec4[0] * scalar));
+ if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fx > 0.0f && fx < (float)ar->winx)) {
+ const float fy = ((float)ar->winy / 2.0f) * (1.0f + (vec4[1] * scalar));
+ if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fy > 0.0f && fy < (float)ar->winy)) {
+ r_co[0] = floorf(fx);
+ r_co[1] = floorf(fy);
+
+ /* check if the point is behind the view, we need to flip in this case */
+ if (UNLIKELY((flag & V3D_PROJ_TEST_CLIP_NEAR) == 0) && (vec4[3] < 0.0f)) {
+ negate_v2(r_co);
+ }
+ }
+ else {
+ return V3D_PROJ_RET_CLIP_WIN;
+ }
}
else {
return V3D_PROJ_RET_CLIP_WIN;
}
}
else {
- return V3D_PROJ_RET_CLIP_WIN;
+ return V3D_PROJ_RET_CLIP_NEAR;
}
}
else {
- return V3D_PROJ_RET_CLIP_NEAR;
+ return V3D_PROJ_RET_CLIP_ZERO;
}
return V3D_PROJ_RET_OK;
}
-eV3DProjStatus ED_view3d_project_short_ex(ARegion *ar, float perspmat[4][4], const int is_local,
+eV3DProjStatus ED_view3d_project_short_ex(const ARegion *ar, float perspmat[4][4], const bool is_local,
const float co[3], short r_co[2], const eV3DProjTest flag)
{
float tvec[2];
@@ -166,8 +180,8 @@ eV3DProjStatus ED_view3d_project_short_ex(ARegion *ar, float perspmat[4][4], con
if ((tvec[0] > -32700.0f && tvec[0] < 32700.0f) &&
(tvec[1] > -32700.0f && tvec[1] < 32700.0f))
{
- r_co[0] = (short)floor(tvec[0]);
- r_co[1] = (short)floor(tvec[1]);
+ r_co[0] = (short)floorf(tvec[0]);
+ r_co[1] = (short)floorf(tvec[1]);
}
else {
ret = V3D_PROJ_RET_OVERFLOW;
@@ -176,7 +190,7 @@ eV3DProjStatus ED_view3d_project_short_ex(ARegion *ar, float perspmat[4][4], con
return ret;
}
-eV3DProjStatus ED_view3d_project_int_ex(ARegion *ar, float perspmat[4][4], const int is_local,
+eV3DProjStatus ED_view3d_project_int_ex(const ARegion *ar, float perspmat[4][4], const bool is_local,
const float co[3], int r_co[2], const eV3DProjTest flag)
{
float tvec[2];
@@ -185,8 +199,8 @@ eV3DProjStatus ED_view3d_project_int_ex(ARegion *ar, float perspmat[4][4], const
if ((tvec[0] > -2140000000.0f && tvec[0] < 2140000000.0f) &&
(tvec[1] > -2140000000.0f && tvec[1] < 2140000000.0f))
{
- r_co[0] = (int)floor(tvec[0]);
- r_co[1] = (int)floor(tvec[1]);
+ r_co[0] = (int)floorf(tvec[0]);
+ r_co[1] = (int)floorf(tvec[1]);
}
else {
ret = V3D_PROJ_RET_OVERFLOW;
@@ -195,7 +209,7 @@ eV3DProjStatus ED_view3d_project_int_ex(ARegion *ar, float perspmat[4][4], const
return ret;
}
-eV3DProjStatus ED_view3d_project_float_ex(ARegion *ar, float perspmat[4][4], const int is_local,
+eV3DProjStatus ED_view3d_project_float_ex(const ARegion *ar, float perspmat[4][4], const bool is_local,
const float co[3], float r_co[2], const eV3DProjTest flag)
{
float tvec[2];
@@ -214,42 +228,42 @@ eV3DProjStatus ED_view3d_project_float_ex(ARegion *ar, float perspmat[4][4], con
}
/* --- short --- */
-eV3DProjStatus ED_view3d_project_short_global(ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag)
+eV3DProjStatus ED_view3d_project_short_global(const ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag)
{
RegionView3D *rv3d = ar->regiondata;
- return ED_view3d_project_short_ex(ar, rv3d->persmat, FALSE, co, r_co, flag);
+ return ED_view3d_project_short_ex(ar, rv3d->persmat, false, co, r_co, flag);
}
/* object space, use ED_view3d_init_mats_rv3d before calling */
-eV3DProjStatus ED_view3d_project_short_object(ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag)
+eV3DProjStatus ED_view3d_project_short_object(const ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag)
{
RegionView3D *rv3d = ar->regiondata;
- return ED_view3d_project_short_ex(ar, rv3d->persmatob, TRUE, co, r_co, flag);
+ return ED_view3d_project_short_ex(ar, rv3d->persmatob, true, co, r_co, flag);
}
/* --- int --- */
-eV3DProjStatus ED_view3d_project_int_global(ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag)
+eV3DProjStatus ED_view3d_project_int_global(const ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag)
{
RegionView3D *rv3d = ar->regiondata;
- return ED_view3d_project_int_ex(ar, rv3d->persmat, FALSE, co, r_co, flag);
+ return ED_view3d_project_int_ex(ar, rv3d->persmat, false, co, r_co, flag);
}
/* object space, use ED_view3d_init_mats_rv3d before calling */
-eV3DProjStatus ED_view3d_project_int_object(ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag)
+eV3DProjStatus ED_view3d_project_int_object(const ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag)
{
RegionView3D *rv3d = ar->regiondata;
- return ED_view3d_project_int_ex(ar, rv3d->persmatob, TRUE, co, r_co, flag);
+ return ED_view3d_project_int_ex(ar, rv3d->persmatob, true, co, r_co, flag);
}
/* --- float --- */
-eV3DProjStatus ED_view3d_project_float_global(ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag)
+eV3DProjStatus ED_view3d_project_float_global(const ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag)
{
RegionView3D *rv3d = ar->regiondata;
- return ED_view3d_project_float_ex(ar, rv3d->persmat, FALSE, co, r_co, flag);
+ return ED_view3d_project_float_ex(ar, rv3d->persmat, false, co, r_co, flag);
}
/* object space, use ED_view3d_init_mats_rv3d before calling */
-eV3DProjStatus ED_view3d_project_float_object(ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag)
+eV3DProjStatus ED_view3d_project_float_object(const ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag)
{
RegionView3D *rv3d = ar->regiondata;
- return ED_view3d_project_float_ex(ar, rv3d->persmatob, TRUE, co, r_co, flag);
+ return ED_view3d_project_float_ex(ar, rv3d->persmatob, true, co, r_co, flag);
}
@@ -257,28 +271,30 @@ eV3DProjStatus ED_view3d_project_float_object(ARegion *ar, const float co[3], fl
/* More Generic Window/Ray/Vector projection functions
* *************************************************** */
-/* odd function, need to document better */
-int initgrabz(RegionView3D *rv3d, float x, float y, float z)
+/**
+ * Caculate a depth value from \a co, use with #ED_view3d_win_to_delta
+ */
+float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3], bool *r_flip)
{
- int flip = FALSE;
- if (rv3d == NULL) return flip;
- rv3d->zfac = rv3d->persmat[0][3] * x + rv3d->persmat[1][3] * y + rv3d->persmat[2][3] * z + rv3d->persmat[3][3];
- if (rv3d->zfac < 0.0f)
- flip = TRUE;
+ float zfac = mul_project_m4_v3_zfac((float (*)[4])rv3d->persmat, co);
+
+ if (r_flip) {
+ *r_flip = (zfac < 0.0f);
+ }
+
/* if x,y,z is exactly the viewport offset, zfac is 0 and we don't want that
- * (accounting for near zero values)
- */
- if (rv3d->zfac < 1.e-6f && rv3d->zfac > -1.e-6f) rv3d->zfac = 1.0f;
+ * (accounting for near zero values) */
+ if (zfac < 1.e-6f && zfac > -1.e-6f) {
+ zfac = 1.0f;
+ }
/* Negative zfac means x, y, z was behind the camera (in perspective).
- * This gives flipped directions, so revert back to ok default case.
- */
- /* NOTE: I've changed this to flip zfac to be positive again for now so that GPencil draws ok
- * Aligorith, 2009Aug31 */
- //if (rv3d->zfac < 0.0f) rv3d->zfac = 1.0f;
- if (rv3d->zfac < 0.0f) rv3d->zfac = -rv3d->zfac;
-
- return flip;
+ * This gives flipped directions, so revert back to ok default case. */
+ if (zfac < 0.0f) {
+ zfac = -zfac;
+ }
+
+ return zfac;
}
/**
@@ -292,7 +308,7 @@ int initgrabz(RegionView3D *rv3d, float x, float y, float z)
* \param ray_start The world-space starting point of the segment.
* \param ray_normal The normalized world-space direction of towards mval.
*/
-void ED_view3d_win_to_ray(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_normal[3])
+void ED_view3d_win_to_ray(const ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_normal[3])
{
float ray_end[3];
@@ -308,7 +324,7 @@ void ED_view3d_win_to_ray(ARegion *ar, View3D *v3d, const float mval[2], float r
* \param coord The world-space location.
* \param vec The resulting normalized vector.
*/
-void ED_view3d_global_to_vector(RegionView3D *rv3d, const float coord[3], float vec[3])
+void ED_view3d_global_to_vector(const RegionView3D *rv3d, const float coord[3], float vec[3])
{
if (rv3d->is_persp) {
float p1[4], p2[4];
@@ -317,11 +333,11 @@ void ED_view3d_global_to_vector(RegionView3D *rv3d, const float coord[3], float
p1[3] = 1.0f;
copy_v3_v3(p2, p1);
p2[3] = 1.0f;
- mul_m4_v4(rv3d->viewmat, p2);
+ mul_m4_v4((float (*)[4])rv3d->viewmat, p2);
mul_v3_fl(p2, 2.0f);
- mul_m4_v4(rv3d->viewinv, p2);
+ mul_m4_v4((float (*)[4])rv3d->viewinv, p2);
sub_v3_v3v3(vec, p1, p2);
}
@@ -338,7 +354,7 @@ void ED_view3d_global_to_vector(RegionView3D *rv3d, const float coord[3], float
* \param mval The area relative location (such as event->mval converted to floats).
* \param out The resulting world-space location.
*/
-void ED_view3d_win_to_3d(ARegion *ar, const float depth_pt[3], const float mval[2], float out[3])
+void ED_view3d_win_to_3d(const ARegion *ar, const float depth_pt[3], const float mval[2], float out[3])
{
RegionView3D *rv3d = ar->regiondata;
@@ -351,7 +367,7 @@ void ED_view3d_win_to_3d(ARegion *ar, const float depth_pt[3], const float mval[
ED_view3d_win_to_vector(ar, mval, mousevec);
add_v3_v3v3(line_end, line_sta, mousevec);
- if (isect_line_plane_v3(out, line_sta, line_end, depth_pt, rv3d->viewinv[2], TRUE) == 0) {
+ if (isect_line_plane_v3(out, line_sta, line_end, depth_pt, rv3d->viewinv[2], true) == 0) {
/* highly unlikely to ever happen, mouse vec paralelle with view plane */
zero_v3(out);
}
@@ -370,19 +386,19 @@ void ED_view3d_win_to_3d(ARegion *ar, const float depth_pt[3], const float mval[
/**
* Calculate a 3d difference vector from 2d window offset.
- * note that initgrabz() must be called first to determine
+ * note that ED_view3d_calc_zfac() must be called first to determine
* the depth used to calculate the delta.
* \param ar The region (used for the window width and height).
* \param mval The area relative 2d difference (such as event->mval[0] - other_x).
* \param out The resulting world-space delta.
*/
-void ED_view3d_win_to_delta(ARegion *ar, const float mval[2], float out[3])
+void ED_view3d_win_to_delta(const ARegion *ar, const float mval[2], float out[3], const float zfac)
{
RegionView3D *rv3d = ar->regiondata;
float dx, dy;
- dx = 2.0f * mval[0] * rv3d->zfac / ar->winx;
- dy = 2.0f * mval[1] * rv3d->zfac / ar->winy;
+ dx = 2.0f * mval[0] * zfac / ar->winx;
+ dy = 2.0f * mval[1] * zfac / ar->winy;
out[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy);
out[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy);
@@ -394,7 +410,7 @@ void ED_view3d_win_to_delta(ARegion *ar, const float mval[2], float out[3])
* This direction vector starts and the view in the direction of the 2d window coordinates.
* In orthographic view all window coordinates yield the same vector.
*
- * \note doesn't rely on initgrabz
+ * \note doesn't rely on ED_view3d_calc_zfac
* for perspective view, get the vector direction to
* the mouse cursor as a normalized vector.
*
@@ -402,7 +418,7 @@ void ED_view3d_win_to_delta(ARegion *ar, const float mval[2], float out[3])
* \param mval The area relative 2d location (such as event->mval converted to floats).
* \param out The resulting normalized world-space direction vector.
*/
-void ED_view3d_win_to_vector(ARegion *ar, const float mval[2], float out[3])
+void ED_view3d_win_to_vector(const ARegion *ar, const float mval[2], float out[3])
{
RegionView3D *rv3d = ar->regiondata;
@@ -419,7 +435,8 @@ void ED_view3d_win_to_vector(ARegion *ar, const float mval[2], float out[3])
normalize_v3(out);
}
-void ED_view3d_win_to_segment(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3])
+void ED_view3d_win_to_segment(const ARegion *ar, View3D *v3d, const float mval[2],
+ float ray_start[3], float ray_end[3])
{
RegionView3D *rv3d = ar->regiondata;
@@ -456,9 +473,10 @@ void ED_view3d_win_to_segment(ARegion *ar, View3D *v3d, const float mval[2], flo
* \param mval The area relative 2d location (such as event->mval, converted into float[2]).
* \param ray_start The world-space starting point of the segment.
* \param ray_end The world-space end point of the segment.
- * \return success, FALSE if the segment is totally clipped.
+ * \return success, false if the segment is totally clipped.
*/
-int ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3])
+bool ED_view3d_win_to_segment_clip(const ARegion *ar, View3D *v3d, const float mval[2],
+ float ray_start[3], float ray_end[3])
{
RegionView3D *rv3d = ar->regiondata;
ED_view3d_win_to_segment(ar, v3d, mval, ray_start, ray_end);
@@ -466,14 +484,14 @@ int ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2],
/* clipping */
if (rv3d->rflag & RV3D_CLIPPING) {
/* if the ray is totally clipped,
- * restore the original values but return FALSE
+ * restore the original values but return false
* caller can choose what to do */
float tray_start[3] = {UNPACK3(ray_start)};
float tray_end[3] = {UNPACK3(ray_end)};
int a;
for (a = 0; a < 4; a++) {
- if (clip_line_plane(tray_start, tray_end, rv3d->clip[a]) == FALSE) {
- return FALSE;
+ if (clip_line_plane(tray_start, tray_end, rv3d->clip[a]) == false) {
+ return false;
}
}
@@ -482,19 +500,19 @@ int ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2],
copy_v3_v3(ray_end, tray_end);
}
- return TRUE;
+ return true;
}
/* Utility functions for projection
* ******************************** */
-void ED_view3d_ob_project_mat_get(RegionView3D *rv3d, Object *ob, float pmat[4][4])
+void ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, Object *ob, float pmat[4][4])
{
float vmat[4][4];
- mult_m4_m4m4(vmat, rv3d->viewmat, ob->obmat);
- mult_m4_m4m4(pmat, rv3d->winmat, vmat);
+ mult_m4_m4m4(vmat, (float (*)[4])rv3d->viewmat, ob->obmat);
+ mult_m4_m4m4(pmat, (float (*)[4])rv3d->winmat, vmat);
}
/**
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
new file mode 100644
index 00000000000..d6cc218e266
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -0,0 +1,939 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_view3d/view3d_ruler.c
+ * \ingroup spview3d
+ */
+
+/* defines VIEW3D_OT_ruler modal operator */
+
+#include "DNA_scene_types.h"
+#include "DNA_gpencil_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+#include "BKE_gpencil.h"
+
+#include "BIF_gl.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_space_api.h"
+
+#include "BLF_api.h"
+#include "BIF_glutil.h"
+
+#include "UI_resources.h"
+#include "UI_interface.h"
+
+#include "view3d_intern.h" /* own include */
+
+
+/* -------------------------------------------------------------------- */
+/* Snapping (could be own function) */
+/* NOTE - this is not very nice use of transform snapping */
+#include "ED_transform.h"
+#include "../transform/transform.h"
+
+static bool ED_view3d_snap_co(bContext *C, float r_co[3], const float co_ss[2],
+ bool use_vert, bool use_edge, bool use_face)
+{
+ TransInfo t = {0};
+ int dist = 12; /* snap dist */
+ float r_no_dummy[3];
+ bool ret = false;
+ char backup_snap_mode;
+ Base *backup_baseact;
+
+ t.scene = CTX_data_scene(C);
+ t.view = CTX_wm_view3d(C);
+ t.ar = CTX_wm_region(C);
+ t.obedit = CTX_data_edit_object(C);
+
+ backup_snap_mode = t.scene->toolsettings->snap_mode;
+ backup_baseact = t.scene->basact;
+ t.scene->basact = NULL;
+
+ /* try snap edge, then face if it fails */
+ if (use_vert) {
+ t.scene->toolsettings->snap_mode = SCE_SNAP_MODE_VERTEX;
+ ret = snapObjectsTransform(&t, co_ss, &dist, r_co, r_no_dummy, SNAP_ALL);
+ }
+ if (use_edge && (ret == false)) {
+ t.scene->toolsettings->snap_mode = SCE_SNAP_MODE_EDGE;
+ ret = snapObjectsTransform(&t, co_ss, &dist, r_co, r_no_dummy, SNAP_ALL);
+ }
+ if (use_face && (ret == false)) {
+ t.scene->toolsettings->snap_mode = SCE_SNAP_MODE_FACE;
+ ret = snapObjectsTransform(&t, co_ss, &dist, r_co, r_no_dummy, SNAP_ALL);
+ }
+
+ t.scene->toolsettings->snap_mode = backup_snap_mode;
+ t.scene->basact = backup_baseact;
+
+ return ret;
+}
+/* done snapping */
+
+
+/* -------------------------------------------------------------------- */
+/* Ruler Item (we can have many) */
+enum {
+ RULERITEM_USE_ANGLE = (1 << 0), /* use protractor */
+ RULERITEM_USE_RAYCAST = (1 << 1)
+};
+
+enum {
+ RULERITEM_DIRECTION_IN = 0,
+ RULERITEM_DIRECTION_OUT
+};
+
+#define RULER_PICK_DIST 75.0f
+#define RULER_PICK_DIST_SQ (RULER_PICK_DIST * RULER_PICK_DIST)
+
+typedef struct RulerItem {
+ struct RulerItem *next, *prev;
+
+ /* worldspace coords, middle being optional */
+ float co[3][3];
+
+ /* selected coord */
+ char co_index; /* 0 -> 2*/
+
+ int flag;
+ int raycast_dir; /* RULER_DIRECTION_* */
+} RulerItem;
+
+enum {
+ RULER_STATE_NORMAL = 0,
+ RULER_STATE_DRAG
+};
+
+
+/* -------------------------------------------------------------------- */
+/* Ruler Info (one per session) */
+
+typedef struct RulerInfo {
+ ListBase items;
+ int item_active;
+ int flag;
+ int snap_flag;
+ int state;
+
+ /* --- */
+ ARegion *ar;
+ void *draw_handle_pixel;
+} RulerInfo;
+
+/* -------------------------------------------------------------------- */
+/* local functions */
+static RulerItem *ruler_item_add(RulerInfo *ruler_info)
+{
+ RulerItem *ruler_item = MEM_callocN(sizeof(RulerItem), "RulerItem");
+ BLI_addtail(&ruler_info->items, ruler_item);
+ return ruler_item;
+}
+
+static void ruler_item_remove(RulerInfo *ruler_info, RulerItem *ruler_item)
+{
+ BLI_remlink(&ruler_info->items, ruler_item);
+ MEM_freeN(ruler_item);
+}
+
+static RulerItem *ruler_item_active_get(RulerInfo *ruler_info)
+{
+ return BLI_findlink(&ruler_info->items, ruler_info->item_active);
+}
+
+static void ruler_item_active_set(RulerInfo *ruler_info, RulerItem *ruler_item)
+{
+ ruler_info->item_active = BLI_findindex(&ruler_info->items, ruler_item);
+}
+
+static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit,
+ char *numstr, size_t numstr_size, int prec)
+{
+ const int do_split = unit->flag & USER_UNIT_OPT_SPLIT;
+
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ const float ruler_angle = angle_v3v3v3(ruler_item->co[0],
+ ruler_item->co[1],
+ ruler_item->co[2]);
+
+ if (unit->system == USER_UNIT_NONE) {
+ BLI_snprintf(numstr, numstr_size, "%.*f°", prec, RAD2DEGF(ruler_angle));
+ }
+ else {
+ bUnit_AsString(numstr, numstr_size,
+ (double)ruler_angle,
+ prec, unit->system, B_UNIT_ROTATION, do_split, false);
+ }
+ }
+ else {
+ const float ruler_len = len_v3v3(ruler_item->co[0],
+ ruler_item->co[2]);
+
+ if (unit->system == USER_UNIT_NONE) {
+ BLI_snprintf(numstr, numstr_size, "%.*f", prec, ruler_len);
+ }
+ else {
+ bUnit_AsString(numstr, numstr_size,
+ (double)(ruler_len * unit->scale_length),
+ prec, unit->system, B_UNIT_LENGTH, do_split, false);
+ }
+ }
+
+}
+
+static bool view3d_ruler_pick(RulerInfo *ruler_info, const float mval[2],
+ RulerItem **r_ruler_item, int *r_co_index)
+{
+ ARegion *ar = ruler_info->ar;
+ RulerItem *ruler_item;
+
+ float dist_best = RULER_PICK_DIST_SQ;
+ RulerItem *ruler_item_best = NULL;
+ int co_index_best = -1;
+
+ for (ruler_item = ruler_info->items.first; ruler_item; ruler_item = ruler_item->next) {
+ float co_ss[3][2];
+ float dist;
+ int j;
+
+ /* should these be checked? - ok for now not to */
+ for (j = 0; j < 3; j++) {
+ ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP);
+ }
+
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ dist = min_ff(dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[1]),
+ dist_squared_to_line_segment_v2(mval, co_ss[1], co_ss[2]));
+ if (dist < dist_best) {
+ dist_best = dist;
+ ruler_item_best = ruler_item;
+
+ {
+ float dist_points[3] = {len_squared_v2v2(co_ss[0], mval),
+ len_squared_v2v2(co_ss[1], mval),
+ len_squared_v2v2(co_ss[2], mval)};
+ if (min_fff(UNPACK3(dist_points)) < RULER_PICK_DIST_SQ) {
+ co_index_best = min_axis_v3(dist_points);
+ }
+ else {
+ co_index_best = -1;
+ }
+ }
+ }
+ }
+ else {
+ dist = dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[2]);
+ if (dist < dist_best) {
+ dist_best = dist;
+ ruler_item_best = ruler_item;
+
+ {
+ float dist_points[2] = {len_squared_v2v2(co_ss[0], mval),
+ len_squared_v2v2(co_ss[2], mval)};
+ if (min_ff(UNPACK2(dist_points)) < RULER_PICK_DIST_SQ) {
+ co_index_best = (dist_points[0] < dist_points[1]) ? 0 : 2;
+ }
+ else {
+ co_index_best = -1;
+ }
+ }
+ }
+ }
+ }
+
+ if (ruler_item_best) {
+ *r_ruler_item = ruler_item_best;
+ *r_co_index = co_index_best;
+ return true;
+ }
+ else {
+ *r_ruler_item = NULL;
+ *r_co_index = -1;
+ return false;
+ }
+}
+
+#define RULER_ID "RulerData3D"
+static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info)
+{
+ Scene *scene = CTX_data_scene(C);
+ bGPDlayer *gpl;
+ bGPDframe *gpf;
+ bGPDstroke *gps;
+ RulerItem *ruler_item;
+ const char *ruler_name = RULER_ID;
+ bool change = false;
+
+ if (scene->gpd == NULL) {
+ scene->gpd = gpencil_data_addnew("GPencil");
+ }
+
+ gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
+ if (gpl == NULL) {
+ gpl = gpencil_layer_addnew(scene->gpd, ruler_name, false);
+ gpl->thickness = 1;
+ gpl->flag |= GP_LAYER_HIDE;
+ }
+
+ gpf = gpencil_layer_getframe(gpl, CFRA, true);
+ free_gpencil_strokes(gpf);
+
+ for (ruler_item = ruler_info->items.first; ruler_item; ruler_item = ruler_item->next) {
+ bGPDspoint *pt;
+ int j;
+
+ /* allocate memory for a new stroke */
+ gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ gps->totpoints = 3;
+ pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ for (j = 0; j < 3; j++) {
+ copy_v3_v3(&pt->x, ruler_item->co[j]);
+ pt->pressure = 1.0f;
+ pt++;
+ }
+ }
+ else {
+ gps->totpoints = 2;
+ pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ for (j = 0; j < 3; j += 2) {
+ copy_v3_v3(&pt->x, ruler_item->co[j]);
+ pt->pressure = 1.0f;
+ pt++;
+ }
+ }
+ gps->flag = GP_STROKE_3DSPACE;
+ BLI_addtail(&gpf->strokes, gps);
+ change = true;
+ }
+
+ return change;
+}
+
+static bool view3d_ruler_from_gpencil(bContext *C, RulerInfo *ruler_info)
+{
+ Scene *scene = CTX_data_scene(C);
+ bool change = false;
+
+ if (scene->gpd) {
+ bGPDlayer *gpl;
+ const char *ruler_name = RULER_ID;
+ gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
+ if (gpl) {
+ bGPDframe *gpf;
+ gpf = gpencil_layer_getframe(gpl, CFRA, false);
+ if (gpf) {
+ bGPDstroke *gps;
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ bGPDspoint *pt = gps->points;
+ int j;
+ if (gps->totpoints == 3) {
+ RulerItem *ruler_item = ruler_item_add(ruler_info);
+ for (j = 0; j < 3; j++) {
+ copy_v3_v3(ruler_item->co[j], &pt->x);
+ pt++;
+ }
+ ruler_item->flag |= RULERITEM_USE_ANGLE;
+ change = true;
+ }
+ else if (gps->totpoints == 2) {
+ RulerItem *ruler_item = ruler_item_add(ruler_info);
+ for (j = 0; j < 3; j += 2) {
+ copy_v3_v3(ruler_item->co[j], &pt->x);
+ pt++;
+ }
+ change = true;
+ }
+ }
+ }
+ }
+ }
+
+ return change;
+}
+
+/* -------------------------------------------------------------------- */
+/* local callbacks */
+
+static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *arg)
+{
+ Scene *scene = CTX_data_scene(C);
+ UnitSettings *unit = &scene->unit;
+ RulerItem *ruler_item;
+ RulerInfo *ruler_info = arg;
+ RegionView3D *rv3d = ruler_info->ar->regiondata;
+// ARegion *ar = ruler_info->ar;
+ const float cap_size = 4.0f;
+ const float bg_margin = 4.0f * U.pixelsize;
+ const float bg_radius = 4.0f * U.pixelsize;
+ const float arc_size = 64.0f * U.pixelsize;
+#define ARC_STEPS 24
+ const int arc_steps = ARC_STEPS;
+ int i;
+ //unsigned int color_act = 0x666600;
+ unsigned int color_act = 0xffffff;
+ unsigned int color_base = 0x0;
+ unsigned char color_back[4] = {0xff, 0xff, 0xff, 0x80};
+ unsigned char color_text[3];
+ unsigned char color_wire[3];
+
+ /* anti-aliased lines for more consistent appearance */
+ glEnable(GL_LINE_SMOOTH);
+
+ BLF_enable(blf_mono_font, BLF_ROTATION);
+ BLF_size(blf_mono_font, 14 * U.pixelsize, U.dpi);
+ BLF_rotation(blf_mono_font, 0.0f);
+
+ UI_GetThemeColor3ubv(TH_TEXT, color_text);
+ UI_GetThemeColor3ubv(TH_WIRE, color_wire);
+
+ for (ruler_item = ruler_info->items.first, i = 0; ruler_item; ruler_item = ruler_item->next, i++) {
+ const bool is_act = (i == ruler_info->item_active);
+ float dir_ruler[2];
+ float co_ss[3][2];
+ int j;
+
+ /* should these be checked? - ok for now not to */
+ for (j = 0; j < 3; j++) {
+ ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP);
+ }
+
+ glEnable(GL_BLEND);
+
+ cpack(is_act ? color_act : color_base);
+
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ glBegin(GL_LINE_STRIP);
+ for (j = 0; j < 3; j++) {
+ glVertex2fv(co_ss[j]);
+ }
+ glEnd();
+ cpack(0xaaaaaa);
+ setlinestyle(3);
+ glBegin(GL_LINE_STRIP);
+ for (j = 0; j < 3; j++) {
+ glVertex2fv(co_ss[j]);
+ }
+ glEnd();
+ setlinestyle(0);
+
+ /* arc */
+ {
+ float dir_tmp[3];
+ float co_tmp[3];
+ float arc_ss_coords[ARC_STEPS + 1][2];
+
+ float dir_a[3];
+ float dir_b[3];
+ float quat[4];
+ float axis[3];
+ float angle;
+ const float px_scale = (ED_view3d_pixel_size(rv3d, ruler_item->co[1]) *
+ min_fff(arc_size,
+ len_v2v2(co_ss[0], co_ss[1]) / 2.0f,
+ len_v2v2(co_ss[2], co_ss[1]) / 2.0f));
+
+ sub_v3_v3v3(dir_a, ruler_item->co[0], ruler_item->co[1]);
+ sub_v3_v3v3(dir_b, ruler_item->co[2], ruler_item->co[1]);
+ normalize_v3(dir_a);
+ normalize_v3(dir_b);
+
+ cross_v3_v3v3(axis, dir_a, dir_b);
+ angle = angle_normalized_v3v3(dir_a, dir_b);
+
+ axis_angle_to_quat(quat, axis, angle / arc_steps);
+
+ copy_v3_v3(dir_tmp, dir_a);
+
+ glColor3ubv(color_wire);
+
+ for (j = 0; j <= arc_steps; j++) {
+ madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale);
+ ED_view3d_project_float_global(ar, co_tmp, arc_ss_coords[j], V3D_PROJ_TEST_NOP);
+ mul_qt_v3(quat, dir_tmp);
+ }
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 0, arc_ss_coords);
+ glDrawArrays(GL_LINE_STRIP, 0, arc_steps + 1);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ }
+
+ /* text */
+ {
+ char numstr[256];
+ float numstr_size[2];
+ float pos[2];
+ const int prec = 2; /* XXX, todo, make optional */
+
+ ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
+
+ BLF_width_and_height(blf_mono_font, numstr, &numstr_size[0], &numstr_size[1]);
+
+ pos[0] = co_ss[1][0] + (cap_size * 2.0f);
+ pos[1] = co_ss[1][1] - (numstr_size[1] / 2.0f);
+
+ /* 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);
+ /* draw text */
+ glColor3ubv(color_text);
+ BLF_position(blf_mono_font, pos[0], pos[1], 0.0f);
+ BLF_rotation(blf_mono_font, 0.0f);
+ BLF_draw(blf_mono_font, numstr, sizeof(numstr));
+ }
+
+ /* capping */
+ {
+ float rot_90_vec_a[2];
+ float rot_90_vec_b[2];
+ float cap[2];
+
+ sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[1]);
+ rot_90_vec_a[0] = -dir_ruler[1];
+ rot_90_vec_a[1] = dir_ruler[0];
+ normalize_v2(rot_90_vec_a);
+
+ sub_v2_v2v2(dir_ruler, co_ss[1], co_ss[2]);
+ rot_90_vec_b[0] = -dir_ruler[1];
+ rot_90_vec_b[1] = dir_ruler[0];
+ normalize_v2(rot_90_vec_b);
+
+ glEnable(GL_BLEND);
+
+ glColor3ubv(color_wire);
+
+ glBegin(GL_LINES);
+
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size);
+ glVertex2fv(cap);
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size);
+ glVertex2fv(cap);
+
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size);
+ glVertex2fv(cap);
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size);
+ glVertex2fv(cap);
+
+ /* angle vertex */
+ glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
+ glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
+ glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
+ glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
+ glEnd();
+
+ glDisable(GL_BLEND);
+ }
+ }
+ else {
+ glBegin(GL_LINE_STRIP);
+ for (j = 0; j < 3; j += 2) {
+ glVertex2fv(co_ss[j]);
+ }
+ glEnd();
+ cpack(0xaaaaaa);
+ setlinestyle(3);
+ glBegin(GL_LINE_STRIP);
+ for (j = 0; j < 3; j += 2) {
+ glVertex2fv(co_ss[j]);
+ }
+ glEnd();
+ setlinestyle(0);
+
+ sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]);
+
+ /* text */
+ {
+ char numstr[256];
+ float numstr_size[2];
+ const int prec = 6; /* XXX, todo, make optional */
+ float pos[2];
+
+ ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
+
+ BLF_width_and_height(blf_mono_font, numstr, &numstr_size[0], &numstr_size[1]);
+
+ mid_v2_v2v2(pos, co_ss[0], co_ss[2]);
+
+ /* center text */
+ pos[0] -= numstr_size[0] / 2.0f;
+ pos[1] -= numstr_size[1] / 2.0f;
+
+ /* 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);
+ /* draw text */
+ glColor3ubv(color_text);
+ BLF_position(blf_mono_font, pos[0], pos[1], 0.0f);
+ BLF_draw(blf_mono_font, numstr, sizeof(numstr));
+ }
+
+ /* capping */
+ {
+ float rot_90_vec[2] = {-dir_ruler[1], dir_ruler[0]};
+ float cap[2];
+
+ normalize_v2(rot_90_vec);
+
+ glEnable(GL_BLEND);
+ glColor3ubv(color_wire);
+
+ glBegin(GL_LINES);
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size);
+ glVertex2fv(cap);
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size);
+ glVertex2fv(cap);
+
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size);
+ glVertex2fv(cap);
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size);
+ glVertex2fv(cap);
+ glEnd();
+
+ glDisable(GL_BLEND);
+ }
+ }
+ }
+
+ glDisable(GL_LINE_SMOOTH);
+
+ BLF_disable(blf_mono_font, BLF_ROTATION);
+
+#undef ARC_STEPS
+}
+
+/* free, use for both cancel and finish */
+static void view3d_ruler_end(const struct bContext *UNUSED(C), RulerInfo *ruler_info)
+{
+ ED_region_draw_cb_exit(ruler_info->ar->type, ruler_info->draw_handle_pixel);
+}
+
+static void view3d_ruler_free(RulerInfo *ruler_info)
+{
+ BLI_freelistN(&ruler_info->items);
+ MEM_freeN(ruler_info);
+}
+
+static void view3d_ruler_item_project(RulerInfo *ruler_info, float r_co[3],
+ const int xy[2])
+{
+ view3d_get_view_aligned_coordinate(ruler_info->ar, r_co, xy, true);
+}
+
+/* use for mousemove events */
+static bool view3d_ruler_item_mousemove(bContext *C, RulerInfo *ruler_info, const int mval[2], const bool do_snap)
+{
+ RulerItem *ruler_item = ruler_item_active_get(ruler_info);
+
+ if (ruler_item) {
+ float *co = ruler_item->co[ruler_item->co_index];
+ view3d_ruler_item_project(ruler_info, co, mval);
+ if (do_snap) {
+ const float mval_fl[2] = {UNPACK2(mval)};
+ ED_view3d_snap_co(C, co, mval_fl, true, true, true);
+ }
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+static void view3d_ruler_header_update(ScrArea *sa)
+{
+ const char *text = "Ctrl+LMB: Add, "
+ "Del: Remove, "
+ "Ctrl+Drag: Snap, "
+ "Ctrl+C: Copy Value, "
+ "Enter: Store, "
+ "Esc: Cancel";
+
+ ED_area_headerprint(sa, text);
+}
+
+/* -------------------------------------------------------------------- */
+/* Operator callbacks */
+
+static int view3d_ruler_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ RulerInfo *ruler_info;
+
+ ruler_info = MEM_callocN(sizeof(RulerInfo), "RulerInfo");
+
+ if (view3d_ruler_from_gpencil(C, ruler_info)) {
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ }
+
+ op->customdata = ruler_info;
+
+ 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);
+
+ WM_cursor_modal(win, BC_CROSSCURSOR);
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int view3d_ruler_cancel(bContext *C, wmOperator *op)
+{
+ RulerInfo *ruler_info = op->customdata;
+
+ view3d_ruler_end(C, ruler_info);
+ view3d_ruler_free(ruler_info);
+ op->customdata = NULL;
+
+ return OPERATOR_CANCELLED;
+}
+
+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;
+ ARegion *ar = ruler_info->ar;
+ RegionView3D *rv3d = ar->regiondata;
+
+ (void)C;
+
+ switch (event->type) {
+ case LEFTMOUSE:
+ if (event->val == KM_RELEASE) {
+ if (ruler_info->state == RULER_STATE_DRAG) {
+ /* rubber-band angle removal */
+ RulerItem *ruler_item = ruler_item_active_get(ruler_info);
+ if (ruler_item && (ruler_item->co_index == 1) && (ruler_item->flag & RULERITEM_USE_ANGLE)) {
+ if (!BLI_rcti_isect_pt_v(&ar->winrct, &event->x)) {
+ ruler_item->flag &= ~RULERITEM_USE_ANGLE;
+ do_draw = true;
+ }
+ }
+ ruler_info->state = RULER_STATE_NORMAL;
+ }
+ }
+ else {
+ if (ruler_info->state == RULER_STATE_NORMAL) {
+
+ if (event->ctrl ||
+ /* weak - but user friendly */
+ (ruler_info->items.first == NULL))
+ {
+ /* Create new line */
+ RulerItem *ruler_item;
+ /* check if we want to drag an existing point or add a new one */
+ ruler_info->state = RULER_STATE_DRAG;
+
+ ruler_item = ruler_item_add(ruler_info);
+ ruler_item_active_set(ruler_info, ruler_item);
+
+ negate_v3_v3(ruler_item->co[0], rv3d->ofs);
+ view3d_ruler_item_project(ruler_info, ruler_item->co[0], event->mval);
+
+ /* snap the first point added, not essential but handy */
+ {
+ ruler_item->co_index = 0;
+ view3d_ruler_item_mousemove(C, ruler_info, event->mval, true);
+ }
+
+ copy_v3_v3(ruler_item->co[2], ruler_item->co[0]);
+ ruler_item->co_index = 2;
+
+ do_draw = true;
+ }
+ else {
+ float mval_fl[2] = {UNPACK2(event->mval)};
+ RulerItem *ruler_item_pick;
+ int co_index;
+
+ /* select and drag */
+ if (view3d_ruler_pick(ruler_info, mval_fl, &ruler_item_pick, &co_index)) {
+ if (co_index == -1) {
+ if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) {
+ /* Add Center Point */
+ ruler_item_active_set(ruler_info, ruler_item_pick);
+ ruler_item_pick->flag |= RULERITEM_USE_ANGLE;
+ ruler_item_pick->co_index = 1;
+ ruler_info->state = RULER_STATE_DRAG;
+
+ /* find the factor */
+ {
+ float co_ss[2][2];
+ float fac;
+
+ ED_view3d_project_float_global(ar, ruler_item_pick->co[0], co_ss[0], V3D_PROJ_TEST_NOP);
+ ED_view3d_project_float_global(ar, ruler_item_pick->co[2], co_ss[1], V3D_PROJ_TEST_NOP);
+
+ fac = line_point_factor_v2(mval_fl, co_ss[0], co_ss[1]);
+ CLAMP(fac, 0.0f, 1.0f);
+
+ interp_v3_v3v3(ruler_item_pick->co[1],
+ ruler_item_pick->co[0],
+ ruler_item_pick->co[2], fac);
+ }
+
+ /* update the new location */
+ view3d_ruler_item_mousemove(C, ruler_info, event->mval, event->ctrl != 0);
+ do_draw = true;
+ }
+ }
+ else {
+ ruler_item_active_set(ruler_info, ruler_item_pick);
+ ruler_item_pick->co_index = co_index;
+ ruler_info->state = RULER_STATE_DRAG;
+ do_draw = true;
+ }
+ }
+ else {
+ exit_code = OPERATOR_PASS_THROUGH;
+ }
+
+ }
+ }
+ }
+ break;
+ case CKEY:
+ {
+ if (event->ctrl) {
+ RulerItem *ruler_item = ruler_item_active_get(ruler_info);
+ if (ruler_item) {
+ const int prec = 8;
+ char numstr[256];
+ Scene *scene = CTX_data_scene(C);
+ UnitSettings *unit = &scene->unit;
+
+ ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
+ WM_clipboard_text_set((void *) numstr, false);
+ }
+ }
+ }
+ case RIGHTCTRLKEY:
+ case LEFTCTRLKEY:
+ {
+ WM_event_add_mousemove(C);
+ break;
+ }
+ case MOUSEMOVE:
+ {
+ if (ruler_info->state == RULER_STATE_DRAG) {
+ if (view3d_ruler_item_mousemove(C, ruler_info, event->mval, event->ctrl != 0)) {
+ do_draw = true;
+ }
+ }
+ break;
+ }
+ case ESCKEY:
+ {
+ do_draw = true;
+ exit_code = OPERATOR_CANCELLED;
+ break;
+ }
+ case RETKEY:
+ {
+ view3d_ruler_to_gpencil(C, ruler_info);
+ do_draw = true;
+ exit_code = OPERATOR_FINISHED;
+ break;
+ }
+ case DELKEY:
+ {
+ if (event->val == KM_PRESS) {
+ if (ruler_info->state == RULER_STATE_NORMAL) {
+ RulerItem *ruler_item = ruler_item_active_get(ruler_info);
+ if (ruler_item) {
+ ruler_item_remove(ruler_info, ruler_item);
+ ruler_info->item_active = -1;
+ do_draw = true;
+ }
+ }
+ }
+ break;
+ }
+ default:
+ exit_code = OPERATOR_PASS_THROUGH;
+ break;
+
+ }
+
+ if (do_draw) {
+ ScrArea *sa = CTX_wm_area(C);
+
+ view3d_ruler_header_update(sa);
+
+ /* all 3d views draw rulers */
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ }
+
+ if (ELEM(exit_code, OPERATOR_FINISHED, OPERATOR_CANCELLED)) {
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *sa = CTX_wm_area(C);
+
+ WM_cursor_restore(win);
+
+ view3d_ruler_end(C, ruler_info);
+ view3d_ruler_free(ruler_info);
+ op->customdata = NULL;
+
+ ED_area_headerprint(sa, NULL);
+ }
+
+ return exit_code;
+}
+
+void VIEW3D_OT_ruler(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Ruler/Protractor";
+ ot->description = "Interactive ruler";
+ ot->idname = "VIEW3D_OT_ruler";
+
+ /* api callbacks */
+ ot->invoke = view3d_ruler_invoke;
+ ot->cancel = view3d_ruler_cancel;
+ ot->modal = view3d_ruler_modal;
+ ot->poll = ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag = 0;
+}
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index cffa53b5dfb..a84075fb60e 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -70,6 +70,7 @@
#include "BKE_paint.h"
#include "BKE_tessmesh.h"
#include "BKE_tracking.h"
+#include "BKE_utildefines.h"
#include "BIF_gl.h"
@@ -107,35 +108,35 @@ void view3d_set_viewcontext(bContext *C, ViewContext *vc)
vc->obedit = CTX_data_edit_object(C);
}
-int view3d_get_view_aligned_coordinate(ViewContext *vc, float fp[3], const int mval[2], const short do_fallback)
+/**
+ * Re-project \a fp so it stays on the same view-plane but is under \a mval (normally the cursor location).
+ */
+bool view3d_get_view_aligned_coordinate(ARegion *ar, float fp[3], const int mval[2], const bool do_fallback)
{
+ RegionView3D *rv3d = ar->regiondata;
float dvec[3];
int mval_cpy[2];
eV3DProjStatus ret;
- mval_cpy[0] = mval[0];
- mval_cpy[1] = mval[1];
-
- ret = ED_view3d_project_int_global(vc->ar, fp, mval_cpy, V3D_PROJ_TEST_NOP);
-
- initgrabz(vc->rv3d, fp[0], fp[1], fp[2]);
+ ret = ED_view3d_project_int_global(ar, fp, mval_cpy, V3D_PROJ_TEST_NOP);
if (ret == V3D_PROJ_RET_OK) {
const float mval_f[2] = {(float)(mval_cpy[0] - mval[0]),
(float)(mval_cpy[1] - mval[1])};
- ED_view3d_win_to_delta(vc->ar, mval_f, dvec);
+ const float zfac = ED_view3d_calc_zfac(rv3d, fp, NULL);
+ ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
sub_v3_v3(fp, dvec);
- return TRUE;
+ return true;
}
else {
/* fallback to the view center */
if (do_fallback) {
- negate_v3_v3(fp, vc->rv3d->ofs);
- return view3d_get_view_aligned_coordinate(vc, fp, mval, FALSE);
+ negate_v3_v3(fp, rv3d->ofs);
+ return view3d_get_view_aligned_coordinate(ar, fp, mval, false);
}
else {
- return FALSE;
+ return false;
}
}
}
@@ -176,10 +177,9 @@ static void edbm_backbuf_check_and_select_verts(BMEditMesh *em, int select)
{
BMVert *eve;
BMIter iter;
- int index = bm_wireoffs;
+ unsigned int index = bm_wireoffs;
- eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
- for (; eve; eve = BM_iter_step(&iter), index++) {
+ for (eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL); eve; eve = BM_iter_step(&iter), index++) {
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
if (EDBM_backbuf_check(index)) {
BM_vert_select_set(em->bm, eve, select);
@@ -208,7 +208,7 @@ static void edbm_backbuf_check_and_select_faces(BMEditMesh *em, int select)
{
BMFace *efa;
BMIter iter;
- int index = 1;
+ unsigned int index = 1;
efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL);
for (; efa; efa = BM_iter_step(&iter), index++) {
@@ -225,11 +225,11 @@ static void edbm_backbuf_check_and_select_faces(BMEditMesh *em, int select)
static void edbm_backbuf_check_and_select_verts_obmode(Mesh *me, int select)
{
MVert *mv = me->mvert;
- int a;
+ unsigned int index;
if (mv) {
- for (a = 1; a <= me->totvert; a++, mv++) {
- if (EDBM_backbuf_check(a)) {
+ for (index = 1; index <= me->totvert; index++, mv++) {
+ if (EDBM_backbuf_check(index)) {
if (!(mv->flag & ME_HIDE)) {
mv->flag = select ? (mv->flag | SELECT) : (mv->flag & ~SELECT);
}
@@ -242,11 +242,11 @@ static void edbm_backbuf_check_and_select_verts_obmode(Mesh *me, int select)
static void edbm_backbuf_check_and_select_tfaces(Mesh *me, int select)
{
MPoly *mpoly = me->mpoly;
- int a;
+ unsigned int index;
if (mpoly) {
- for (a = 1; a <= me->totpoly; a++, mpoly++) {
- if (EDBM_backbuf_check(a)) {
+ for (index = 1; index <= me->totpoly; index++, mpoly++) {
+ if (EDBM_backbuf_check(index)) {
mpoly->flag = select ? (mpoly->flag | ME_FACE_SEL) : (mpoly->flag & ~ME_FACE_SEL);
}
}
@@ -262,17 +262,17 @@ typedef struct LassoSelectUserData {
rctf _rect_fl;
const int (*mcords)[2];
int moves;
- int select;
+ bool select;
/* runtime */
int pass;
- int is_done;
- int is_change;
+ bool is_done;
+ bool is_change;
} LassoSelectUserData;
static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data,
ViewContext *vc, const rcti *rect, const int (*mcords)[2],
- const int moves, const int select)
+ const int moves, const bool select)
{
r_data->vc = vc;
@@ -286,8 +286,8 @@ static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data,
/* runtime */
r_data->pass = 0;
- r_data->is_done = FALSE;
- r_data->is_change = FALSE;
+ r_data->is_done = false;
+ r_data->is_change = false;
}
static int view3d_selectable_data(bContext *C)
@@ -356,7 +356,7 @@ static void do_lasso_select_pose__doSelectBone(void *userData, struct bPoseChann
bArmature *arm = data->vc->obact->data;
if (PBONE_SELECTABLE(arm, pchan->bone)) {
- int is_point_done = FALSE;
+ bool is_point_done = false;
int points_proj_tot = 0;
const int x0 = screen_co_a[0];
@@ -370,7 +370,7 @@ static void do_lasso_select_pose__doSelectBone(void *userData, struct bPoseChann
if (BLI_rcti_isect_pt(data->rect, x0, y0) &&
BLI_lasso_is_point_inside(data->mcords, data->moves, x0, y0, INT_MAX))
{
- is_point_done = TRUE;
+ is_point_done = true;
}
}
@@ -380,23 +380,23 @@ static void do_lasso_select_pose__doSelectBone(void *userData, struct bPoseChann
if (BLI_rcti_isect_pt(data->rect, x1, y1) &&
BLI_lasso_is_point_inside(data->mcords, data->moves, x1, y1, INT_MAX))
{
- is_point_done = TRUE;
+ is_point_done = true;
}
}
/* if one of points selected, we skip the bone itself */
- if ((is_point_done == TRUE) ||
- ((is_point_done == FALSE) && (points_proj_tot == 2) &&
+ if ((is_point_done == true) ||
+ ((is_point_done == false) && (points_proj_tot == 2) &&
BLI_lasso_is_edge_inside(data->mcords, data->moves, x0, y0, x1, y1, INT_MAX)))
{
if (data->select) pchan->bone->flag |= BONE_SELECTED;
else pchan->bone->flag &= ~BONE_SELECTED;
- data->is_change = TRUE;
+ data->is_change = true;
}
data->is_change |= is_point_done;
}
}
-static void do_lasso_select_pose(ViewContext *vc, Object *ob, const int mcords[][2], short moves, short select)
+static void do_lasso_select_pose(ViewContext *vc, Object *ob, const int mcords[][2], short moves, bool select)
{
ViewContext vc_tmp;
LassoSelectUserData data;
@@ -437,11 +437,11 @@ static void object_deselect_all_visible(Scene *scene, View3D *v3d)
}
}
-static void do_lasso_select_objects(ViewContext *vc, const int mcords[][2], const short moves, short extend, short select)
+static void do_lasso_select_objects(ViewContext *vc, const int mcords[][2], const short moves, bool extend, bool select)
{
Base *base;
- if (extend == 0 && select)
+ if (extend == false && select)
object_deselect_all_visible(vc->scene, vc->v3d);
for (base = vc->scene->base.first; base; base = base->next) {
@@ -486,7 +486,7 @@ static void do_lasso_select_mesh__doSelectEdge(void *userData, BMEdge *eed, cons
BLI_lasso_is_point_inside(data->mcords, data->moves, x1, y1, IS_CLIPPED))
{
BM_edge_select_set(data->vc->em->bm, eed, data->select);
- data->is_done = TRUE;
+ data->is_done = true;
}
}
else {
@@ -507,7 +507,7 @@ static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, cons
}
}
-static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short moves, short extend, short select)
+static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
{
LassoSelectUserData data;
ToolSettings *ts = vc->scene->toolsettings;
@@ -521,7 +521,7 @@ static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short m
view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
- if (extend == 0 && select)
+ if (extend == false && select)
EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT);
/* for non zbuf projections, don't change the GL state */
@@ -541,11 +541,11 @@ static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short m
if (ts->selectmode & SCE_SELECT_EDGE) {
/* Does both bbsel and non-bbsel versions (need screen cos for both) */
data.pass = 0;
- mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_NOP);
+ mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
- if (data.is_done == 0) {
+ if (data.is_done == false) {
data.pass = 1;
- mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_NOP);
+ mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
}
}
@@ -595,7 +595,7 @@ static void do_lasso_select_curve__doSelect(void *userData, Nurb *UNUSED(nu), BP
}
}
-static void do_lasso_select_curve(ViewContext *vc, const int mcords[][2], short moves, short extend, short select)
+static void do_lasso_select_curve(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
{
LassoSelectUserData data;
rcti rect;
@@ -604,7 +604,7 @@ static void do_lasso_select_curve(ViewContext *vc, const int mcords[][2], short
view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
- if (extend == 0 && select)
+ if (extend == false && select)
CU_deselect_all(vc->obedit);
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
@@ -616,11 +616,12 @@ static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const
LassoSelectUserData *data = userData;
if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)) {
+ BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED))
+ {
bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
}
}
-static void do_lasso_select_lattice(ViewContext *vc, const int mcords[][2], short moves, short extend, short select)
+static void do_lasso_select_lattice(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
{
LassoSelectUserData data;
rcti rect;
@@ -629,7 +630,7 @@ static void do_lasso_select_lattice(ViewContext *vc, const int mcords[][2], shor
view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
- if (extend == 0 && select)
+ if (extend == false && select)
ED_setflagsLatt(vc->obedit, 0);
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
@@ -642,7 +643,7 @@ static void do_lasso_select_armature__doSelectBone(void *userData, struct EditBo
bArmature *arm = data->vc->obedit->data;
if (EBONE_SELECTABLE(arm, ebone)) {
- int is_point_done = FALSE;
+ bool is_point_done = false;
int points_proj_tot = 0;
const int x0 = screen_co_a[0];
@@ -656,7 +657,7 @@ static void do_lasso_select_armature__doSelectBone(void *userData, struct EditBo
if (BLI_rcti_isect_pt(data->rect, x0, y0) &&
BLI_lasso_is_point_inside(data->mcords, data->moves, x0, y0, INT_MAX))
{
- is_point_done = TRUE;
+ is_point_done = true;
if (data->select) ebone->flag |= BONE_ROOTSEL;
else ebone->flag &= ~BONE_ROOTSEL;
}
@@ -668,26 +669,26 @@ static void do_lasso_select_armature__doSelectBone(void *userData, struct EditBo
if (BLI_rcti_isect_pt(data->rect, x1, y1) &&
BLI_lasso_is_point_inside(data->mcords, data->moves, x1, y1, INT_MAX))
{
- is_point_done = TRUE;
+ is_point_done = true;
if (data->select) ebone->flag |= BONE_TIPSEL;
else ebone->flag &= ~BONE_TIPSEL;
}
}
/* if one of points selected, we skip the bone itself */
- if ((is_point_done == FALSE) && (points_proj_tot == 2) &&
+ if ((is_point_done == false) && (points_proj_tot == 2) &&
BLI_lasso_is_edge_inside(data->mcords, data->moves, x0, y0, x1, y1, INT_MAX))
{
if (data->select) ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
else ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- data->is_change = TRUE;
+ data->is_change = true;
}
data->is_change |= is_point_done;
}
}
-static void do_lasso_select_armature(ViewContext *vc, const int mcords[][2], short moves, short extend, short select)
+static void do_lasso_select_armature(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
{
LassoSelectUserData data;
rcti rect;
@@ -698,7 +699,7 @@ static void do_lasso_select_armature(ViewContext *vc, const int mcords[][2], sho
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- if (extend == 0 && select)
+ if (extend == false && select)
ED_armature_deselect_all_visible(vc->obedit);
armature_foreachScreenBone(vc, do_lasso_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
@@ -716,21 +717,22 @@ static void do_lasso_select_mball__doSelectElem(void *userData, struct MetaElem
LassoSelectUserData *data = userData;
if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], INT_MAX)) {
+ BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], INT_MAX))
+ {
if (data->select) ml->flag |= SELECT;
else ml->flag &= ~SELECT;
- data->is_change = TRUE;
+ data->is_change = true;
}
}
-static void do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short moves, short extend, short select)
+static void do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
{
LassoSelectUserData data;
rcti rect;
MetaBall *mb = (MetaBall *)vc->obedit->data;
- if (extend == 0 && select)
- BKE_mball_deselect_all(mb);
+ if (extend == false && select)
+ BKE_mball_deselect_all(mb);
BLI_lasso_boundbox(&rect, mcords, moves);
@@ -741,67 +743,19 @@ static void do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short m
mball_foreachScreenElem(vc, do_lasso_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
-static int do_paintvert_box_select(ViewContext *vc, rcti *rect, int select, int extend)
+static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
{
- 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;
-
- me = vc->obact->data;
-
- if (me == NULL || me->totvert == 0 || sx * sy <= 0)
- return OPERATOR_CANCELLED;
-
- selar = MEM_callocN(me->totvert + 1, "selar");
-
- if (extend == 0 && select)
- paintvert_deselect_all_visible(vc->obact, SEL_DESELECT, FALSE);
-
- view3d_validate_backbuf(vc);
-
- ibuf = IMB_allocImBuf(sx, sy, 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);
-
- a = sx * sy;
- while (a--) {
- if (*rt) {
- index = WM_framebuffer_to_index(*rt);
- if (index <= me->totvert) selar[index] = 1;
- }
- rt++;
- }
+ LassoSelectUserData *data = userData;
- mvert = me->mvert;
- for (a = 1; a <= me->totvert; a++, mvert++) {
- if (selar[a]) {
- if ((mvert->flag & ME_HIDE) == 0) {
- if (select) mvert->flag |= SELECT;
- else mvert->flag &= ~SELECT;
- }
- }
+ if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
+ BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED))
+ {
+ BKE_BIT_TEST_SET(mv->flag, data->select, SELECT);
}
-
- IMB_freeImBuf(ibuf);
- MEM_freeN(selar);
-
-#ifdef __APPLE__
- glReadBuffer(GL_BACK);
-#endif
-
- paintvert_flush_flags(vc->obact);
-
- return OPERATOR_FINISHED;
}
-
-static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, short extend, short select)
+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);
Object *ob = vc->obact;
Mesh *me = ob ? ob->data : NULL;
rcti rect;
@@ -809,20 +763,34 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh
if (me == NULL || me->totvert == 0)
return;
- if (extend == 0 && select)
- paintvert_deselect_all_visible(ob, SEL_DESELECT, FALSE); /* flush selection at the end */
- bm_vertoffs = me->totvert + 1; /* max index array */
+ if (extend == false && select)
+ paintvert_deselect_all_visible(ob, SEL_DESELECT, false); /* flush selection at the end */
BLI_lasso_boundbox(&rect, mcords, moves);
- EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- edbm_backbuf_check_and_select_verts_obmode(me, select);
+ if (use_zbuf) {
+ bm_vertoffs = me->totvert + 1; /* max index array */
+
+ EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- EDBM_backbuf_free();
+ edbm_backbuf_check_and_select_verts_obmode(me, select);
+
+ EDBM_backbuf_free();
+ }
+ else {
+ LassoSelectUserData data;
+
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
+
+ ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
+
+ meshobject_foreachScreenVert(vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ }
paintvert_flush_flags(ob);
}
-static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], short moves, short extend, short select)
+static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select)
{
Object *ob = vc->obact;
Mesh *me = ob ? ob->data : NULL;
@@ -831,8 +799,8 @@ static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], sh
if (me == NULL || me->totpoly == 0)
return;
- if (extend == 0 && select)
- paintface_deselect_all_visible(ob, SEL_DESELECT, FALSE); /* flush selection at the end */
+ if (extend == false && select)
+ paintface_deselect_all_visible(ob, SEL_DESELECT, false); /* flush selection at the end */
bm_vertoffs = me->totpoly + 1; /* max index array */
@@ -879,7 +847,7 @@ static void do_lasso_select_node(int mcords[][2], short moves, short select)
static void view3d_lasso_select(bContext *C, ViewContext *vc,
const int mcords[][2], short moves,
- short extend, short select)
+ bool extend, bool select)
{
Object *ob = CTX_data_active_object(C);
@@ -934,7 +902,7 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
if (mcords) {
- short extend, select;
+ bool extend, select;
view3d_operator_needs_opengl(C);
/* setup view context for argument to callbacks */
@@ -1063,9 +1031,9 @@ static EnumPropertyItem *object_select_menu_enum_itemf(bContext *C, PointerRNA *
static int object_select_menu_exec(bContext *C, wmOperator *op)
{
- int name_index = RNA_enum_get(op->ptr, "name");
- short toggle = RNA_boolean_get(op->ptr, "toggle");
- short changed = 0;
+ const int name_index = RNA_enum_get(op->ptr, "name");
+ const bool toggle = RNA_boolean_get(op->ptr, "toggle");
+ bool change = false;
const char *name = object_mouse_select_menu_data[name_index].idname;
if (!toggle) {
@@ -1073,7 +1041,7 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
{
if (base->flag & SELECT) {
ED_base_object_select(base, BA_DESELECT);
- changed = 1;
+ change = true;
}
}
CTX_DATA_END;
@@ -1082,10 +1050,10 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
/* this is a bit dodjy, there should only be ONE object with this name, but library objects can mess this up */
- if (strcmp(name, base->object->id.name + 2) == 0) {
+ if (STREQ(name, base->object->id.name + 2)) {
ED_base_object_activate(C, base);
ED_base_object_select(base, BA_SELECT);
- changed = 1;
+ change = true;
}
}
CTX_DATA_END;
@@ -1094,7 +1062,7 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data));
/* undo? */
- if (changed) {
+ if (change) {
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
return OPERATOR_FINISHED;
}
@@ -1144,12 +1112,12 @@ static void deselectall_except(Scene *scene, Base *b) /* deselect all except b
static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int *buffer, int hits, const int mval[2], short toggle)
{
short baseCount = 0;
- short ok;
+ bool ok;
LinkNode *linklist = NULL;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
- ok = FALSE;
+ ok = false;
/* two selection methods, the CTRL select uses max dist of 15 */
if (buffer) {
@@ -1157,7 +1125,7 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int
for (a = 0; a < hits; a++) {
/* index was converted */
if (base->selcol == buffer[(4 * a) + 3])
- ok = TRUE;
+ ok = true;
}
}
else {
@@ -1166,7 +1134,7 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int
temp = abs(base->sx - mval[0]) + abs(base->sy - mval[1]);
if (temp < dist)
- ok = TRUE;
+ ok = true;
}
if (ok) {
@@ -1217,31 +1185,42 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int
}
}
+static bool selectbuffer_has_bones(const unsigned int *buffer, const unsigned int hits)
+{
+ unsigned int i;
+ for (i = 0; i < hits; i++) {
+ if (buffer[(4 * i) + 3] & 0xFFFF0000) {
+ return true;
+ }
+ }
+ return false;
+}
+
/* 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])
{
rcti rect;
int offs;
- short a, hits15, hits9 = 0, hits5 = 0;
- short has_bones15 = 0, has_bones9 = 0, has_bones5 = 0;
+ short hits15, hits9 = 0, hits5 = 0;
+ bool has_bones15 = false, has_bones9 = false, has_bones5 = false;
BLI_rcti_init(&rect, mval[0] - 14, mval[0] + 14, mval[1] - 14, mval[1] + 14);
hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
if (hits15 > 0) {
- for (a = 0; a < hits15; a++) if (buffer[4 * a + 3] & 0xFFFF0000) has_bones15 = 1;
+ has_bones15 = selectbuffer_has_bones(buffer, hits15);
offs = 4 * hits15;
BLI_rcti_init(&rect, mval[0] - 9, mval[0] + 9, mval[1] - 9, mval[1] + 9);
hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect);
if (hits9 > 0) {
- for (a = 0; a < hits9; a++) if (buffer[offs + 4 * a + 3] & 0xFFFF0000) has_bones9 = 1;
+ has_bones9 = selectbuffer_has_bones(buffer + offs, hits9);
offs += 4 * hits9;
BLI_rcti_init(&rect, mval[0] - 5, mval[0] + 5, mval[1] - 5, mval[1] + 5);
hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect);
if (hits5 > 0) {
- for (a = 0; a < hits5; a++) if (buffer[offs + 4 * a + 3] & 0xFFFF0000) has_bones5 = 1;
+ has_bones5 = selectbuffer_has_bones(buffer + offs, hits5);
}
}
@@ -1276,20 +1255,22 @@ static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buff
}
/* returns basact */
-static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int hits, const int mval[2], Base *startbase, int has_bones)
+static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int hits, const int mval[2],
+ Base *startbase, bool has_bones)
{
Scene *scene = vc->scene;
View3D *v3d = vc->v3d;
Base *base, *basact = NULL;
static int lastmval[2] = {-100, -100};
- int a, do_nearest = FALSE;
+ int a;
+ bool do_nearest = false;
/* define if we use solid nearest select or not */
if (v3d->drawtype > OB_WIRE) {
- do_nearest = TRUE;
+ do_nearest = true;
if (ABS(mval[0] - lastmval[0]) < 3 && ABS(mval[1] - lastmval[1]) < 3) {
if (!has_bones) /* hrms, if theres bones we always do nearest */
- do_nearest = FALSE;
+ do_nearest = false;
}
}
lastmval[0] = mval[0]; lastmval[1] = mval[1];
@@ -1383,10 +1364,7 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
hits = mixed_bones_object_selectbuffer(&vc, buffer, mval);
if (hits > 0) {
- int a, has_bones = 0;
-
- for (a = 0; a < hits; a++) if (buffer[4 * a + 3] & 0xFFFF0000) has_bones = 1;
-
+ const bool has_bones = selectbuffer_has_bones(buffer, hits);
basact = mouse_select_eval_buffer(&vc, buffer, hits, mval, vc.scene->base.first, has_bones);
}
@@ -1413,16 +1391,15 @@ static void deselect_all_tracks(MovieTracking *tracking)
}
/* mval is region coords */
-static int mouse_select(bContext *C, const int mval[2], short extend, short deselect, short toggle, short obcenter, short enumerate)
+static bool mouse_select(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, bool obcenter, short enumerate)
{
ViewContext vc;
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
Base *base, *startbase = NULL, *basact = NULL, *oldbasact = NULL;
- int a;
float dist = 100.0f;
- int retval = 0;
+ int retval = false;
short hits;
const float mval_fl[2] = {(float)mval[0], (float)mval[1]};
@@ -1448,7 +1425,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese
if (BASE_SELECTABLE(v3d, base)) {
float screen_co[2];
if (ED_view3d_project_float_global(ar, base->object->obmat[3], screen_co,
- V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_OK)
+ V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
{
float dist_temp = len_manhattan_v2v2(mval_fl, screen_co);
if (base == BASACT) dist_temp += 10.0f;
@@ -1473,10 +1450,8 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese
hits = mixed_bones_object_selectbuffer(&vc, buffer, mval);
if (hits > 0) {
- int has_bones = 0;
-
/* note: bundles are handling in the same way as bones */
- for (a = 0; a < hits; a++) if (buffer[4 * a + 3] & 0xFFFF0000) has_bones = 1;
+ const bool has_bones = selectbuffer_has_bones(buffer, hits);
/* note; shift+alt goes to group-flush-selecting */
if (has_bones == 0 && enumerate) {
@@ -1502,7 +1477,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese
}
/* index of bundle is 1<<16-based. if there's no "bone" index
- * in height word, this buffer value belongs to camera,. not to bundle */
+ * in height word, this buffer value belongs to camera. not to bundle */
if (buffer[4 * i + 3] & 0xFFFF0000) {
MovieClip *clip = BKE_object_movieclip_get(scene, basact->object, 0);
MovieTracking *tracking = &clip->tracking;
@@ -1529,7 +1504,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese
basact->flag |= SELECT;
basact->object->flag = basact->flag;
- retval = 1;
+ retval = true;
WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, track);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -1553,7 +1528,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese
basact->flag |= SELECT;
basact->object->flag = basact->flag;
- retval = 1;
+ retval = true;
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, basact->object);
@@ -1573,7 +1548,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese
/* so, do we have something selected? */
if (basact) {
- retval = 1;
+ retval = true;
if (vc.obedit) {
/* only do select */
@@ -1628,8 +1603,8 @@ typedef struct BoxSelectUserData {
/* runtime */
int pass;
- int is_done;
- int is_change;
+ bool is_done;
+ bool is_change;
} BoxSelectUserData;
static void view3d_userdata_boxselect_init(BoxSelectUserData *r_data,
@@ -1645,29 +1620,108 @@ static void view3d_userdata_boxselect_init(BoxSelectUserData *r_data,
/* runtime */
r_data->pass = 0;
- r_data->is_done = FALSE;
- r_data->is_change = FALSE;
+ r_data->is_done = false;
+ r_data->is_change = false;
}
-int edge_inside_circle(const float cent[2], float radius, const float screen_co_a[2], const float screen_co_b[2])
+bool edge_inside_circle(const float cent[2], float radius, const float screen_co_a[2], const float screen_co_b[2])
{
int radius_squared = radius * radius;
/* check points in circle itself */
if (len_squared_v2v2(cent, screen_co_a) <= radius_squared) {
- return TRUE;
+ return true;
}
if (len_squared_v2v2(cent, screen_co_b) <= radius_squared) {
- return TRUE;
+ return true;
}
else {
/* pointdistline */
if (dist_squared_to_line_segment_v2(cent, screen_co_a, screen_co_b) < (float)radius_squared) {
- return TRUE;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
+{
+ BoxSelectUserData *data = userData;
+
+ if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) {
+ BKE_BIT_TEST_SET(mv->flag, data->select, SELECT);
+ }
+}
+static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
+{
+ const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT);
+ 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;
+
+ me = vc->obact->data;
+
+ if (me == NULL || me->totvert == 0 || sx * sy <= 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);
+
+ ibuf = IMB_allocImBuf(sx, sy, 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);
+
+ a = sx * sy;
+ while (a--) {
+ if (*rt) {
+ index = WM_framebuffer_to_index(*rt);
+ if (index <= me->totvert) selar[index] = 1;
+ }
+ rt++;
}
+
+ mvert = me->mvert;
+ for (a = 1; a <= me->totvert; a++, mvert++) {
+ if (selar[a]) {
+ if ((mvert->flag & ME_HIDE) == 0) {
+ if (select) mvert->flag |= SELECT;
+ else mvert->flag &= ~SELECT;
+ }
+ }
+ }
+
+ IMB_freeImBuf(ibuf);
+ MEM_freeN(selar);
+
+#ifdef __APPLE__
+ glReadBuffer(GL_BACK);
+#endif
}
+ else {
+ BoxSelectUserData data;
+
+ view3d_userdata_boxselect_init(&data, vc, rect, select);
- return FALSE;
+ ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
+
+ meshobject_foreachScreenVert(vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+ }
+
+ paintvert_flush_flags(vc->obact);
+
+ return OPERATOR_FINISHED;
}
static void do_nurbs_box_select__doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
@@ -1702,13 +1756,13 @@ static void do_nurbs_box_select__doSelect(void *userData, Nurb *UNUSED(nu), BPoi
}
}
}
-static int do_nurbs_box_select(ViewContext *vc, rcti *rect, int select, int extend)
+static int do_nurbs_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
{
BoxSelectUserData data;
view3d_userdata_boxselect_init(&data, vc, rect, select);
- if (extend == 0 && select)
+ if (extend == false && select)
CU_deselect_all(vc->obedit);
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
@@ -1725,13 +1779,13 @@ static void do_lattice_box_select__doSelect(void *userData, BPoint *bp, const fl
bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
}
}
-static int do_lattice_box_select(ViewContext *vc, rcti *rect, int select, int extend)
+static int do_lattice_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
{
BoxSelectUserData data;
view3d_userdata_boxselect_init(&data, vc, rect, select);
- if (extend == 0 && select)
+ if (extend == false && select)
ED_setflagsLatt(vc->obedit, 0);
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
@@ -1756,7 +1810,7 @@ static void do_mesh_box_select__doSelectEdge(void *userData, BMEdge *eed, const
if (data->pass == 0) {
if (edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b)) {
BM_edge_select_set(data->vc->em->bm, eed, data->select);
- data->is_done = TRUE;
+ data->is_done = true;
}
}
else {
@@ -1774,7 +1828,7 @@ static void do_mesh_box_select__doSelectFace(void *userData, BMFace *efa, const
BM_face_select_set(data->vc->em->bm, efa, data->select);
}
}
-static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int extend)
+static int do_mesh_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
{
BoxSelectUserData data;
ToolSettings *ts = vc->scene->toolsettings;
@@ -1782,7 +1836,7 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int exten
view3d_userdata_boxselect_init(&data, vc, rect, select);
- if (extend == 0 && select)
+ if (extend == false && select)
EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT);
/* for non zbuf projections, don't change the GL state */
@@ -1803,11 +1857,11 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int exten
/* Does both bbsel and non-bbsel versions (need screen cos for both) */
data.pass = 0;
- mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_NOP);
+ mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
if (data.is_done == 0) {
data.pass = 1;
- mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_NOP);
+ mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
}
}
@@ -1827,7 +1881,7 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int exten
return OPERATOR_FINISHED;
}
-static int do_meta_box_select(ViewContext *vc, rcti *rect, int select, int extend)
+static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
{
MetaBall *mb = (MetaBall *)vc->obedit->data;
MetaElem *ml;
@@ -1838,7 +1892,7 @@ static int do_meta_box_select(ViewContext *vc, rcti *rect, int select, int exten
hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect);
- if (extend == 0 && select)
+ if (extend == false && select)
BKE_mball_deselect_all(mb);
for (ml = mb->editelems->first; ml; ml = ml->next) {
@@ -1861,7 +1915,7 @@ static int do_meta_box_select(ViewContext *vc, rcti *rect, int select, int exten
return OPERATOR_FINISHED;
}
-static int do_armature_box_select(ViewContext *vc, rcti *rect, short select, short extend)
+static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
{
bArmature *arm = vc->obedit->data;
EditBone *ebone;
@@ -1876,7 +1930,7 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, short select, sho
for (ebone = arm->edbo->first; ebone; ebone = ebone->next)
ebone->flag &= ~BONE_DONE;
- if (extend == 0 && select)
+ if (extend == false && select)
ED_armature_deselect_all_visible(vc->obedit);
/* first we only check points inside the border */
@@ -1931,7 +1985,7 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, short select, sho
return OPERATOR_CANCELLED;
}
-static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, int select, int extend)
+static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, bool select, bool extend)
{
Bone *bone;
Object *ob = vc->obact;
@@ -1947,7 +2001,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, i
else
bone_only = 0;
- if (extend == 0 && select) {
+ if (extend == false && select) {
if (bone_only) {
CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
{
@@ -2039,8 +2093,8 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
{
ViewContext vc;
rcti rect;
- short extend;
- short select;
+ bool extend;
+ bool select;
int ret = OPERATOR_CANCELLED;
@@ -2135,18 +2189,21 @@ void VIEW3D_OT_select_border(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO;
/* rna */
- WM_operator_properties_gesture_border(ot, TRUE);
+ WM_operator_properties_gesture_border(ot, true);
}
/* mouse selection in weight paint */
/* gets called via generic mouse select operator */
-static int mouse_weight_paint_vertex_select(bContext *C, const int mval[2], short extend, short deselect, short toggle, Object *obact)
+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);
+
Mesh *me = obact->data; /* already checked for NULL */
unsigned int index = 0;
MVert *mv;
- if (ED_mesh_pick_vert(C, me, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE)) {
+ if (ED_mesh_pick_vert(C, obact, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE, use_zbuf)) {
mv = &me->mvert[index];
if (extend) {
mv->flag |= SELECT;
@@ -2158,30 +2215,30 @@ static int mouse_weight_paint_vertex_select(bContext *C, const int mval[2], shor
mv->flag ^= SELECT;
}
else {
- paintvert_deselect_all_visible(obact, SEL_DESELECT, FALSE);
+ paintvert_deselect_all_visible(obact, SEL_DESELECT, false);
mv->flag |= SELECT;
}
paintvert_flush_flags(obact);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* ****** Mouse Select ****** */
-static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int view3d_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Object *obedit = CTX_data_edit_object(C);
Object *obact = CTX_data_active_object(C);
- short extend = RNA_boolean_get(op->ptr, "extend");
- short deselect = RNA_boolean_get(op->ptr, "deselect");
- short toggle = RNA_boolean_get(op->ptr, "toggle");
- short center = RNA_boolean_get(op->ptr, "center");
- short enumerate = RNA_boolean_get(op->ptr, "enumerate");
- short object = RNA_boolean_get(op->ptr, "object");
- int retval = 0;
+ 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 center = RNA_boolean_get(op->ptr, "center");
+ bool enumerate = RNA_boolean_get(op->ptr, "enumerate");
+ bool object = RNA_boolean_get(op->ptr, "object");
+ bool retval = false;
view3d_operator_needs_opengl(C);
@@ -2192,10 +2249,10 @@ static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
/* ack, this is incorrect but to do this correctly we would need an
* alternative editmode/objectmode keymap, this copies the functionality
* from 2.4x where Ctrl+Select in editmode does object select only */
- center = FALSE;
+ center = false;
}
- if (obedit && object == FALSE) {
+ if (obedit && object == false) {
if (obedit->type == OB_MESH)
retval = EDBM_select_pick(C, event->mval, extend, deselect, toggle);
else if (obedit->type == OB_ARMATURE)
@@ -2262,7 +2319,7 @@ typedef struct CircleSelectUserData {
float radius_squared;
/* runtime */
- int is_change;
+ bool is_change;
} CircleSelectUserData;
static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data,
@@ -2278,7 +2335,7 @@ static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data,
r_data->radius_squared = rad * rad;
/* runtime */
- r_data->is_change = FALSE;
+ r_data->is_change = false;
}
static void mesh_circle_doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index))
@@ -2333,7 +2390,7 @@ static void mesh_circle_select(ViewContext *vc, int select, const int mval[2], f
edbm_backbuf_check_and_select_edges(vc->em, select == LEFTMOUSE);
}
else {
- mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_NOP);
+ mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
}
}
@@ -2366,22 +2423,39 @@ static void paint_facesel_circle_select(ViewContext *vc, int select, const int m
}
}
+static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
+{
+ CircleSelectUserData *data = userData;
+ if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
+ BKE_BIT_TEST_SET(mv->flag, data->select, SELECT);
+ }
+}
static void paint_vertsel_circle_select(ViewContext *vc, int select, const int mval[2], float rad)
{
+ const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT);
Object *ob = vc->obact;
- Mesh *me = ob ? ob->data : NULL;
+ Mesh *me = ob->data;
/* int bbsel; */ /* UNUSED */
/* CircleSelectUserData data = {NULL}; */ /* UNUSED */
- if (me) {
+
+ if (use_zbuf) {
bm_vertoffs = me->totvert + 1; /* max index array */
/* bbsel = */ /* UNUSED */ EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
edbm_backbuf_check_and_select_verts_obmode(me, select == LEFTMOUSE);
EDBM_backbuf_free();
+ }
+ else {
+ CircleSelectUserData data;
+
+ ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */
- paintvert_flush_flags(ob);
+ view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
+ meshobject_foreachScreenVert(vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
+
+ paintvert_flush_flags(ob);
}
@@ -2468,14 +2542,14 @@ static void do_circle_select_pose__doSelectBone(void *userData, struct bPoseChan
bArmature *arm = data->vc->obact->data;
if (PBONE_SELECTABLE(arm, pchan->bone)) {
- int is_point_done = FALSE;
+ bool is_point_done = false;
int points_proj_tot = 0;
/* project head location to screenspace */
if (screen_co_a[0] != IS_CLIPPED) {
points_proj_tot++;
if (pchan_circle_doSelectJoint(data, pchan, screen_co_a)) {
- is_point_done = TRUE;
+ is_point_done = true;
}
}
@@ -2483,7 +2557,7 @@ static void do_circle_select_pose__doSelectBone(void *userData, struct bPoseChan
if (screen_co_b[0] != IS_CLIPPED) {
points_proj_tot++;
if (pchan_circle_doSelectJoint(data, pchan, screen_co_a)) {
- is_point_done = TRUE;
+ is_point_done = true;
}
}
@@ -2494,12 +2568,12 @@ static void do_circle_select_pose__doSelectBone(void *userData, struct bPoseChan
/* only if the endpoints didn't get selected, deal with the middle of the bone too
* It works nicer to only do this if the head or tail are not in the circle,
* otherwise there is no way to circle select joints alone */
- if ((is_point_done == FALSE) && (points_proj_tot == 2) &&
+ if ((is_point_done == false) && (points_proj_tot == 2) &&
edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b))
{
if (data->select) pchan->bone->flag |= BONE_SELECTED;
else pchan->bone->flag &= ~BONE_SELECTED;
- data->is_change = TRUE;
+ data->is_change = true;
}
data->is_change |= is_point_done;
@@ -2554,22 +2628,22 @@ static void do_circle_select_armature__doSelectBone(void *userData, struct EditB
bArmature *arm = data->vc->obedit->data;
if (EBONE_SELECTABLE(arm, ebone)) {
- int is_point_done = FALSE;
+ bool is_point_done = false;
int points_proj_tot = 0;
/* project head location to screenspace */
if (screen_co_a[0] != IS_CLIPPED) {
points_proj_tot++;
- if (armature_circle_doSelectJoint(data, ebone, screen_co_a, TRUE)) {
- is_point_done = TRUE;
+ if (armature_circle_doSelectJoint(data, ebone, screen_co_a, true)) {
+ is_point_done = true;
}
}
/* project tail location to screenspace */
if (screen_co_b[0] != IS_CLIPPED) {
points_proj_tot++;
- if (armature_circle_doSelectJoint(data, ebone, screen_co_b, FALSE)) {
- is_point_done = TRUE;
+ if (armature_circle_doSelectJoint(data, ebone, screen_co_b, false)) {
+ is_point_done = true;
}
}
@@ -2580,12 +2654,12 @@ static void do_circle_select_armature__doSelectBone(void *userData, struct EditB
/* only if the endpoints didn't get selected, deal with the middle of the bone too
* It works nicer to only do this if the head or tail are not in the circle,
* otherwise there is no way to circle select joints alone */
- if ((is_point_done == FALSE) && (points_proj_tot == 2) &&
+ if ((is_point_done == false) && (points_proj_tot == 2) &&
edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b))
{
if (data->select) ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
else ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- data->is_change = TRUE;
+ data->is_change = true;
}
data->is_change |= is_point_done;
@@ -2616,7 +2690,7 @@ static void do_circle_select_mball__doSelectElem(void *userData, struct MetaElem
if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
if (data->select) ml->flag |= SELECT;
else ml->flag &= ~SELECT;
- data->is_change = TRUE;
+ data->is_change = true;
}
}
static void mball_circle_select(ViewContext *vc, int select, const int mval[2], float rad)
@@ -2656,12 +2730,12 @@ static void obedit_circle_select(ViewContext *vc, short select, const int mval[2
}
}
-static int object_circle_select(ViewContext *vc, int select, const int mval[2], float rad)
+static bool object_circle_select(ViewContext *vc, int select, const int mval[2], float rad)
{
Scene *scene = vc->scene;
const float radius_squared = rad * rad;
const float mval_fl[2] = {mval[0], mval[1]};
- int is_change = FALSE;
+ bool is_change = false;
int select_flag = select ? SELECT : 0;
Base *base;
@@ -2670,11 +2744,11 @@ static int object_circle_select(ViewContext *vc, int select, const int mval[2],
if (BASE_SELECTABLE(vc->v3d, base) && ((base->flag & SELECT) != select_flag)) {
float screen_co[2];
if (ED_view3d_project_float_global(vc->ar, base->object->obmat[3], screen_co,
- V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_OK)
+ V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
{
if (len_squared_v2v2(mval_fl, screen_co) <= radius_squared) {
ED_base_object_select(base, select);
- is_change = TRUE;
+ is_change = true;
}
}
}
@@ -2688,8 +2762,8 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *obact = CTX_data_active_object(C);
- int radius = RNA_int_get(op->ptr, "radius");
- int gesture_mode = RNA_int_get(op->ptr, "gesture_mode");
+ const int radius = RNA_int_get(op->ptr, "radius");
+ const int gesture_mode = RNA_int_get(op->ptr, "gesture_mode");
int select;
const int mval[2] = {RNA_int_get(op->ptr, "x"),
RNA_int_get(op->ptr, "y")};
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index 7f1bbb22f24..eb32baf4c3f 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -101,7 +101,7 @@ static void special_transvert_update(Object *obedit)
if (obedit->type == OB_MESH) {
BMEditMesh *em = BMEdit_FromObject(obedit);
- BM_mesh_normals_update(em->bm, TRUE); /* does face centers too */
+ BM_mesh_normals_update(em->bm, true); /* does face centers too */
}
else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
Curve *cu = obedit->data;
@@ -340,9 +340,8 @@ static void make_trans_verts(Object *obedit, float min[3], float max[3], int mod
}
if (transvmain && em->derivedCage) {
- EDBM_index_arrays_init(em, 1, 0, 0);
+ EDBM_index_arrays_ensure(em, BM_VERT);
em->derivedCage->foreachMappedVert(em->derivedCage, set_mapped_co, userdata);
- EDBM_index_arrays_free(em);
}
}
else if (obedit->type == OB_ARMATURE) {
@@ -533,7 +532,6 @@ static void make_trans_verts(Object *obedit, float min[3], float max[3], int mod
static int snap_sel_to_grid(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
Object *obedit = CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
RegionView3D *rv3d = CTX_wm_region_data(C);
@@ -624,8 +622,6 @@ static int snap_sel_to_grid(bContext *C, wmOperator *UNUSED(op))
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
else {
- ob->recalc |= OB_RECALC_OB;
-
vec[0] = -ob->obmat[3][0] + gridf * floorf(0.5f + ob->obmat[3][0] / gridf);
vec[1] = -ob->obmat[3][1] + gridf * floorf(0.5f + ob->obmat[3][1] / gridf);
vec[2] = -ob->obmat[3][2] + gridf * floorf(0.5f + ob->obmat[3][2] / gridf);
@@ -645,12 +641,13 @@ static int snap_sel_to_grid(bContext *C, wmOperator *UNUSED(op))
/* auto-keyframing */
ED_autokeyframe_object(C, scene, ob, ks);
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB);
}
}
CTX_DATA_END;
}
- DAG_ids_flush_update(bmain, 0);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
return OPERATOR_FINISHED;
@@ -675,7 +672,6 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
static int snap_sel_to_curs(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
Object *obedit = CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -749,8 +745,6 @@ static int snap_sel_to_curs(bContext *C, wmOperator *UNUSED(op))
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
else {
- ob->recalc |= OB_RECALC_OB;
-
vec[0] = -ob->obmat[3][0] + curs[0];
vec[1] = -ob->obmat[3][1] + curs[1];
vec[2] = -ob->obmat[3][2] + curs[2];
@@ -770,12 +764,13 @@ static int snap_sel_to_curs(bContext *C, wmOperator *UNUSED(op))
/* auto-keyframing */
ED_autokeyframe_object(C, scene, ob, ks);
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB);
}
}
CTX_DATA_END;
}
- DAG_ids_flush_update(bmain, 0);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
return OPERATOR_FINISHED;
@@ -1080,7 +1075,7 @@ void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot)
/* **************************************************** */
-int ED_view3d_minmax_verts(Object *obedit, float min[3], float max[3])
+bool ED_view3d_minmax_verts(Object *obedit, float min[3], float max[3])
{
TransVert *tv;
float centroid[3], vec[3], bmat[3][3];
@@ -1090,7 +1085,7 @@ int ED_view3d_minmax_verts(Object *obedit, float min[3], float max[3])
if (ELEM5(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE))
make_trans_verts(obedit, bmat[0], bmat[1], TM_ALL_JOINTS);
- if (tottrans == 0) return 0;
+ if (tottrans == 0) return false;
copy_m3_m4(bmat, obedit->obmat);
@@ -1106,5 +1101,5 @@ int ED_view3d_minmax_verts(Object *obedit, float min[3], float max[3])
MEM_freeN(transvmain);
transvmain = NULL;
- return 1;
+ return true;
}
diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c
index bfeb56036e6..d3bf8a30792 100644
--- a/source/blender/editors/space_view3d/view3d_toolbar.c
+++ b/source/blender/editors/space_view3d/view3d_toolbar.c
@@ -101,22 +101,33 @@ static void view3d_panel_operator_redo_operator(const bContext *C, Panel *pa, wm
static void view3d_panel_operator_redo(const bContext *C, Panel *pa)
{
wmOperator *op = WM_operator_last_redo(C);
- uiBlock *block;
-
- if (op == NULL)
- return;
- if (WM_operator_poll((bContext *)C, op->type) == 0)
+ ARegion *ar;
+ ARegion *ar1;
+
+ if (op == NULL) {
return;
-
- block = uiLayoutGetBlock(pa->layout);
-
- if (!WM_operator_check_ui_enabled(C, op->type->name))
- 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);
-
- view3d_panel_operator_redo_operator(C, pa, op);
+ /* keep in sync with logic in ED_undo_operator_repeat() */
+ ar = CTX_wm_region(C);
+ ar1 = BKE_area_find_region_active_win(CTX_wm_area(C));
+ if (ar1)
+ CTX_wm_region_set((bContext *)C, ar1);
+
+ if (WM_operator_poll((bContext *)C, op->type)) {
+ uiBlock *block = uiLayoutGetBlock(pa->layout);
+
+ if (!WM_operator_check_ui_enabled(C, op->type->name))
+ 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);
+
+ view3d_panel_operator_redo_operator(C, pa, op);
+ }
+
+ /* set region back */
+ CTX_wm_region_set((bContext *)C, ar);
}
/* ******************* */
@@ -145,7 +156,7 @@ static void operator_search_cb(const struct bContext *C, void *UNUSED(arg), cons
{
GHashIterator *iter = WM_operatortype_iter();
- for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
+ for (; BLI_ghashIterator_notDone(iter); BLI_ghashIterator_step(iter)) {
wmOperatorType *ot = BLI_ghashIterator_getValue(iter);
if (BLI_strcasestr(ot->name, str)) {
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 5a7edfe4140..b227d32d987 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -111,17 +111,43 @@ float *give_cursor(Scene *scene, View3D *v3d)
/* ****************** smooth view operator ****************** */
/* This operator is one of the 'timer refresh' ones like animation playback */
+struct SmoothView3DState {
+ float dist;
+ float lens;
+ float quat[4];
+ float ofs[3];
+};
+
struct SmoothView3DStore {
- float orig_dist, new_dist;
- float orig_lens, new_lens;
- float orig_quat[4], new_quat[4];
- float orig_ofs[3], new_ofs[3];
-
- int to_camera, orig_view;
-
+ /* source*/
+ struct SmoothView3DState src; /* source */
+ struct SmoothView3DState dst; /* destination */
+ struct SmoothView3DState org; /* original */
+
+ bool to_camera;
+ char org_view;
+
double time_allowed;
};
+static void view3d_smooth_view_state_backup(struct SmoothView3DState *sms_state,
+ const View3D *v3d, const RegionView3D *rv3d)
+{
+ copy_v3_v3(sms_state->ofs, rv3d->ofs);
+ copy_qt_qt(sms_state->quat, rv3d->viewquat);
+ sms_state->dist = rv3d->dist;
+ sms_state->lens = v3d->lens;
+}
+
+static void view3d_smooth_view_state_restore(const struct SmoothView3DState *sms_state,
+ View3D *v3d, RegionView3D *rv3d)
+{
+ copy_v3_v3(rv3d->ofs, sms_state->ofs);
+ copy_qt_qt(rv3d->viewquat, sms_state->quat);
+ rv3d->dist = sms_state->dist;
+ v3d->lens = sms_state->lens;
+}
+
/* will start timer if appropriate */
/* the arguments are the desired situation */
void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera, Object *camera,
@@ -132,15 +158,22 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera
ScrArea *sa = CTX_wm_area(C);
RegionView3D *rv3d = ar->regiondata;
- struct SmoothView3DStore sms = {0};
- short ok = FALSE;
+ struct SmoothView3DStore sms = {{0}};
+ bool ok = false;
/* initialize sms */
- copy_v3_v3(sms.new_ofs, rv3d->ofs);
- copy_qt_qt(sms.new_quat, rv3d->viewquat);
- sms.new_dist = rv3d->dist;
- sms.new_lens = v3d->lens;
- sms.to_camera = FALSE;
+ view3d_smooth_view_state_backup(&sms.dst, v3d, rv3d);
+ view3d_smooth_view_state_backup(&sms.src, v3d, rv3d);
+ /* 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.to_camera = false; */ /* initizlized to zero anyway */
/* note on camera locking, this is a little confusing but works ok.
* we may be changing the view 'as if' there is no active camera, but in fact
@@ -155,50 +188,43 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera
}
/* store the options we want to end with */
- if (ofs) copy_v3_v3(sms.new_ofs, ofs);
- if (quat) copy_qt_qt(sms.new_quat, quat);
- if (dist) sms.new_dist = *dist;
- if (lens) sms.new_lens = *lens;
+ if (ofs) copy_v3_v3(sms.dst.ofs, ofs);
+ if (quat) copy_qt_qt(sms.dst.quat, quat);
+ if (dist) sms.dst.dist = *dist;
+ if (lens) sms.dst.lens = *lens;
if (camera) {
- sms.new_dist = ED_view3d_offset_distance(camera->obmat, ofs, VIEW3D_DIST_FALLBACK);
- ED_view3d_from_object(camera, sms.new_ofs, sms.new_quat, &sms.new_dist, &sms.new_lens);
- sms.to_camera = TRUE; /* restore view3d values in end */
+ sms.dst.dist = ED_view3d_offset_distance(camera->obmat, ofs, VIEW3D_DIST_FALLBACK);
+ ED_view3d_from_object(camera, sms.dst.ofs, sms.dst.quat, &sms.dst.dist, &sms.dst.lens);
+ sms.to_camera = true; /* restore view3d values in end */
}
if (C && U.smooth_viewtx) {
- int changed = FALSE; /* zero means no difference */
+ bool changed = false; /* zero means no difference */
if (oldcamera != camera)
- changed = TRUE;
- else if (sms.new_dist != rv3d->dist)
- changed = TRUE;
- else if (sms.new_lens != v3d->lens)
- changed = TRUE;
- else if (!equals_v3v3(sms.new_ofs, rv3d->ofs))
- changed = TRUE;
- else if (!equals_v4v4(sms.new_quat, rv3d->viewquat))
- changed = TRUE;
+ changed = true;
+ else if (sms.dst.dist != rv3d->dist)
+ changed = true;
+ else if (sms.dst.lens != v3d->lens)
+ changed = true;
+ else if (!equals_v3v3(sms.dst.ofs, rv3d->ofs))
+ changed = true;
+ else if (!equals_v4v4(sms.dst.quat, rv3d->viewquat))
+ changed = true;
/* The new view is different from the old one
* so animate the view */
if (changed) {
-
/* original values */
if (oldcamera) {
- sms.orig_dist = ED_view3d_offset_distance(oldcamera->obmat, rv3d->ofs, 0.0f);
- ED_view3d_from_object(oldcamera, sms.orig_ofs, sms.orig_quat, &sms.orig_dist, &sms.orig_lens);
- }
- else {
- copy_v3_v3(sms.orig_ofs, rv3d->ofs);
- copy_qt_qt(sms.orig_quat, rv3d->viewquat);
- sms.orig_dist = rv3d->dist;
- sms.orig_lens = v3d->lens;
+ sms.src.dist = ED_view3d_offset_distance(oldcamera->obmat, rv3d->ofs, 0.0f);
+ /* this */
+ ED_view3d_from_object(oldcamera, sms.src.ofs, sms.src.quat, &sms.src.dist, &sms.src.lens);
}
/* grid draw as floor */
if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
/* use existing if exists, means multiple calls to smooth view wont loose the original 'view' setting */
- sms.orig_view = rv3d->sms ? rv3d->sms->orig_view : rv3d->view;
rv3d->view = RV3D_VIEW_USER;
}
@@ -212,8 +238,8 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera
float vec1[3] = {0, 0, 1}, vec2[3] = {0, 0, 1};
float q1[4], q2[4];
- invert_qt_qt(q1, sms.new_quat);
- invert_qt_qt(q2, sms.orig_quat);
+ invert_qt_qt(q1, sms.dst.quat);
+ invert_qt_qt(q2, sms.src.quat);
mul_qt_v3(q1, vec1);
mul_qt_v3(q2, vec2);
@@ -223,43 +249,52 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera
}
/* ensure it shows correct */
- if (sms.to_camera) rv3d->persp = RV3D_PERSP;
+ if (sms.to_camera) {
+ rv3d->persp = RV3D_PERSP;
+ }
rv3d->rflag |= RV3D_NAVIGATING;
+ /* not essential but in some cases the caller will tag the area for redraw,
+ * and in that case we can get a ficker of the 'org' user view but we want to see 'src' */
+ view3d_smooth_view_state_restore(&sms.src, v3d, rv3d);
+
/* keep track of running timer! */
- if (rv3d->sms == NULL)
+ if (rv3d->sms == NULL) {
rv3d->sms = MEM_mallocN(sizeof(struct SmoothView3DStore), "smoothview v3d");
+ }
*rv3d->sms = sms;
- if (rv3d->smooth_timer)
+ if (rv3d->smooth_timer) {
WM_event_remove_timer(wm, win, rv3d->smooth_timer);
+ }
/* TIMER1 is hardcoded in keymap */
rv3d->smooth_timer = WM_event_add_timer(wm, win, TIMER1, 1.0 / 100.0); /* max 30 frs/sec */
-
- ok = TRUE;
+
+ ok = true;
}
}
/* if we get here nothing happens */
- if (ok == FALSE) {
- if (sms.to_camera == FALSE) {
- copy_v3_v3(rv3d->ofs, sms.new_ofs);
- copy_qt_qt(rv3d->viewquat, sms.new_quat);
- rv3d->dist = sms.new_dist;
- v3d->lens = sms.new_lens;
+ if (ok == false) {
+ if (sms.to_camera == false) {
+ copy_v3_v3(rv3d->ofs, sms.dst.ofs);
+ copy_qt_qt(rv3d->viewquat, sms.dst.quat);
+ rv3d->dist = sms.dst.dist;
+ v3d->lens = sms.dst.lens;
ED_view3d_camera_lock_sync(v3d, rv3d);
}
- if (rv3d->viewlock & RV3D_BOXVIEW)
+ if (rv3d->viewlock & RV3D_BOXVIEW) {
view3d_boxview_copy(sa, ar);
+ }
ED_region_tag_redraw(ar);
}
}
/* only meant for timer usage */
-static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
@@ -281,22 +316,16 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent
/* if we went to camera, store the original */
if (sms->to_camera) {
rv3d->persp = RV3D_CAMOB;
- copy_v3_v3(rv3d->ofs, sms->orig_ofs);
- copy_qt_qt(rv3d->viewquat, sms->orig_quat);
- rv3d->dist = sms->orig_dist;
- v3d->lens = sms->orig_lens;
+ view3d_smooth_view_state_restore(&sms->org, v3d, rv3d);
}
else {
- copy_v3_v3(rv3d->ofs, sms->new_ofs);
- copy_qt_qt(rv3d->viewquat, sms->new_quat);
- rv3d->dist = sms->new_dist;
- v3d->lens = sms->new_lens;
+ view3d_smooth_view_state_restore(&sms->dst, v3d, rv3d);
ED_view3d_camera_lock_sync(v3d, rv3d);
}
if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
- rv3d->view = sms->orig_view;
+ rv3d->view = sms->org_view;
}
MEM_freeN(rv3d->sms);
@@ -312,11 +341,11 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent
step_inv = 1.0f - step;
- interp_v3_v3v3(rv3d->ofs, sms->orig_ofs, sms->new_ofs, step);
- interp_qt_qtqt(rv3d->viewquat, sms->orig_quat, sms->new_quat, step);
+ interp_v3_v3v3(rv3d->ofs, sms->src.ofs, sms->dst.ofs, step);
+ interp_qt_qtqt(rv3d->viewquat, sms->src.quat, sms->dst.quat, step);
- rv3d->dist = sms->new_dist * step + sms->orig_dist * step_inv;
- v3d->lens = sms->new_lens * step + sms->orig_lens * step_inv;
+ rv3d->dist = sms->dst.dist * step + sms->src.dist * step_inv;
+ v3d->lens = sms->dst.lens * step + sms->src.lens * step_inv;
ED_view3d_camera_lock_sync(v3d, rv3d);
}
@@ -325,12 +354,16 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent
view3d_boxview_copy(CTX_wm_area(C), CTX_wm_region(C));
/* note: this doesn't work right because the v3d->lens is now used in ortho mode r51636,
- * when switching camera in quad-view the other ortho views would zoom & reset. */
-#if 0
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
-#else
- ED_region_tag_redraw(CTX_wm_region(C));
-#endif
+ * when switching camera in quad-view the other ortho views would zoom & reset.
+ *
+ * For now only redraw all regions when smoothview finishes.
+ */
+ if (step >= 1.0f) {
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
+ }
+ else {
+ ED_region_tag_redraw(CTX_wm_region(C));
+ }
return OPERATOR_FINISHED;
}
@@ -427,7 +460,7 @@ static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *UNUSED(o
/* only touch location */
BKE_object_tfm_protected_backup(camera_ob, &obtfm);
- BKE_object_apply_mat4(camera_ob, obmat_new, TRUE, TRUE);
+ BKE_object_apply_mat4(camera_ob, obmat_new, true, true);
BKE_object_tfm_protected_restore(camera_ob, &obtfm, OB_LOCK_SCALE | OB_LOCK_ROT4D);
/* notifiers */
@@ -446,7 +479,7 @@ static int view3d_camera_to_view_selected_poll(bContext *C)
if (v3d && v3d->camera && v3d->camera->id.lib == NULL) {
RegionView3D *rv3d = CTX_wm_region_view3d(C);
if (rv3d) {
- if (rv3d->is_persp == FALSE) {
+ if (rv3d->is_persp == false) {
CTX_wm_operator_poll_msg_set(C, "Only valid for a perspective camera view");
}
else if (!rv3d->viewlock) {
@@ -579,7 +612,7 @@ void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], bglMats *mats, co
}
-int ED_view3d_boundbox_clip(RegionView3D *rv3d, float obmat[4][4], BoundBox *bb)
+bool ED_view3d_boundbox_clip(RegionView3D *rv3d, float obmat[4][4], const BoundBox *bb)
{
/* return 1: draw */
@@ -587,8 +620,8 @@ int ED_view3d_boundbox_clip(RegionView3D *rv3d, float obmat[4][4], BoundBox *bb)
float vec[4], min, max;
int a, flag = -1, fl;
- if (bb == NULL) return 1;
- if (bb->flag & OB_BB_DISABLED) return 1;
+ if (bb == NULL) return true;
+ if (bb->flag & OB_BB_DISABLED) return true;
mult_m4_m4m4(mat, rv3d->persmat, obmat);
@@ -608,10 +641,10 @@ int ED_view3d_boundbox_clip(RegionView3D *rv3d, float obmat[4][4], BoundBox *bb)
if (vec[2] > max) fl += 32;
flag &= fl;
- if (flag == 0) return 1;
+ if (flag == 0) return true;
}
- return 0;
+ return false;
}
float ED_view3d_depth_read_cached(ViewContext *vc, int x, int y)
@@ -630,26 +663,33 @@ float ED_view3d_depth_read_cached(ViewContext *vc, int x, int y)
void ED_view3d_depth_tag_update(RegionView3D *rv3d)
{
if (rv3d->depths)
- rv3d->depths->damaged = 1;
+ rv3d->depths->damaged = true;
}
/* copies logic of get_view3d_viewplane(), keep in sync */
-int ED_view3d_clip_range_get(View3D *v3d, RegionView3D *rv3d, float *clipsta, float *clipend)
+bool ED_view3d_clip_range_get(View3D *v3d, RegionView3D *rv3d, float *r_clipsta, float *r_clipend,
+ const bool use_ortho_factor)
{
CameraParams params;
BKE_camera_params_init(&params);
BKE_camera_params_from_view3d(&params, v3d, rv3d);
- if (clipsta) *clipsta = params.clipsta;
- if (clipend) *clipend = params.clipend;
+ if (use_ortho_factor && params.is_ortho) {
+ const float fac = 2.0f / (params.clipend - params.clipsta);
+ params.clipsta *= fac;
+ params.clipend *= fac;
+ }
+
+ if (r_clipsta) *r_clipsta = params.clipsta;
+ if (r_clipend) *r_clipend = params.clipend;
return params.is_ortho;
}
/* also exposed in previewrender.c */
-int ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winx, int winy,
- rctf *viewplane, float *clipsta, float *clipend)
+bool ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winx, int winy,
+ rctf *r_viewplane, float *r_clipsta, float *r_clipend)
{
CameraParams params;
@@ -657,9 +697,9 @@ int ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winx, int winy,
BKE_camera_params_from_view3d(&params, v3d, rv3d);
BKE_camera_params_compute_viewplane(&params, winx, winy, 1.0f, 1.0f);
- if (viewplane) *viewplane = params.viewplane;
- if (clipsta) *clipsta = params.clipsta;
- if (clipend) *clipend = params.clipend;
+ if (r_viewplane) *r_viewplane = params.viewplane;
+ if (r_clipsta) *r_clipsta = params.clipsta;
+ if (r_clipend) *r_clipend = params.clipend;
return params.is_ortho;
}
@@ -758,7 +798,7 @@ static void obmat_to_viewmat(View3D *v3d, RegionView3D *rv3d, Object *ob, short
#define QUATSET(a, b, c, d, e) { a[0] = b; a[1] = c; a[2] = d; a[3] = e; } (void)0
-int ED_view3d_lock(RegionView3D *rv3d)
+bool ED_view3d_lock(RegionView3D *rv3d)
{
switch (rv3d->view) {
case RV3D_VIEW_BOTTOM:
@@ -785,10 +825,10 @@ int ED_view3d_lock(RegionView3D *rv3d)
QUATSET(rv3d->viewquat, 0.5, -0.5, -0.5, -0.5);
break;
default:
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
/* don't set windows active in here, is used by renderwin too */
@@ -830,7 +870,9 @@ void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d)
copy_v3_v3(vec, give_cursor(scene, v3d));
translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
}
- else translate_m4(rv3d->viewmat, rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2]);
+ else {
+ translate_m4(rv3d->viewmat, rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2]);
+ }
}
}
@@ -846,7 +888,8 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
ARegion *ar = vc->ar;
rctf rect;
short code, hits;
- char dt, dtx;
+ char dt;
+ short dtx;
G.f |= G_PICKSEL;
@@ -908,7 +951,7 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
Base tbase;
tbase.flag = OB_FROMDUPLI;
- lb = object_duplilist(scene, base->object, FALSE);
+ lb = object_duplilist(scene, base->object, false);
for (dob = lb->first; dob; dob = dob->next) {
tbase.object = dob->ob;
@@ -932,7 +975,7 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
}
}
}
- v3d->xray = FALSE; /* restore */
+ v3d->xray = false; /* restore */
}
glPopName(); /* see above (pushname) */
@@ -1030,14 +1073,14 @@ int ED_view3d_scene_layer_set(int lay, const int *values, int *active)
return lay;
}
-static int view3d_localview_init(Main *bmain, Scene *scene, ScrArea *sa, ReportList *reports)
+static bool view3d_localview_init(Main *bmain, Scene *scene, ScrArea *sa, ReportList *reports)
{
View3D *v3d = sa->spacedata.first;
Base *base;
float min[3], max[3], box[3];
float size = 0.0f, size_persp = 0.0f, size_ortho = 0.0f;
unsigned int locallay;
- int ok = FALSE;
+ bool ok = false;
if (v3d->localvd) {
return ok;
@@ -1049,13 +1092,13 @@ static int view3d_localview_init(Main *bmain, Scene *scene, ScrArea *sa, ReportL
if (locallay == 0) {
BKE_report(reports, RPT_ERROR, "No more than 8 local views");
- ok = FALSE;
+ ok = false;
}
else {
if (scene->obedit) {
- BKE_object_minmax(scene->obedit, min, max, FALSE);
+ BKE_object_minmax(scene->obedit, min, max, false);
- ok = TRUE;
+ ok = true;
BASACT->lay |= locallay;
scene->obedit->lay = BASACT->lay;
@@ -1063,18 +1106,16 @@ static int view3d_localview_init(Main *bmain, Scene *scene, ScrArea *sa, ReportL
else {
for (base = FIRSTBASE; base; base = base->next) {
if (TESTBASE(v3d, base)) {
- BKE_object_minmax(base->object, min, max, FALSE);
+ BKE_object_minmax(base->object, min, max, false);
base->lay |= locallay;
base->object->lay = base->lay;
- ok = TRUE;
+ ok = true;
}
}
}
-
- box[0] = (max[0] - min[0]);
- box[1] = (max[1] - min[1]);
- box[2] = (max[2] - min[2]);
- size = MAX3(box[0], box[1], box[2]);
+
+ 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);
@@ -1084,7 +1125,7 @@ static int view3d_localview_init(Main *bmain, Scene *scene, ScrArea *sa, ReportL
size_ortho = ED_view3d_radius_to_ortho_dist(v3d->lens, size / 2.0f) * VIEW3D_MARGIN;
}
- if (ok == TRUE) {
+ if (ok == true) {
ARegion *ar;
v3d->localvd = MEM_mallocN(sizeof(View3D), "localview");
@@ -1179,7 +1220,7 @@ static void restore_localviewdata(ScrArea *sa, int free)
}
}
-static int view3d_localview_exit(Main *bmain, Scene *scene, ScrArea *sa)
+static bool view3d_localview_exit(Main *bmain, Scene *scene, ScrArea *sa)
{
View3D *v3d = sa->spacedata.first;
struct Base *base;
@@ -1206,12 +1247,12 @@ static int view3d_localview_exit(Main *bmain, Scene *scene, ScrArea *sa)
}
}
- DAG_on_visible_update(bmain, FALSE);
+ DAG_on_visible_update(bmain, false);
- return TRUE;
+ return true;
}
else {
- return FALSE;
+ return false;
}
}
@@ -1221,7 +1262,7 @@ static int localview_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = CTX_wm_view3d(C);
- int change;
+ bool change;
if (v3d->localvd) {
change = view3d_localview_exit(bmain, scene, sa);
@@ -1362,7 +1403,7 @@ static int game_engine_poll(bContext *C)
return 1;
}
-int ED_view3d_context_activate(bContext *C)
+bool ED_view3d_context_activate(bContext *C)
{
bScreen *sc = CTX_wm_screen(C);
ScrArea *sa = CTX_wm_area(C);
@@ -1375,20 +1416,20 @@ int ED_view3d_context_activate(bContext *C)
break;
if (!sa)
- return 0;
+ return false;
for (ar = sa->regionbase.first; ar; ar = ar->next)
if (ar->regiontype == RGN_TYPE_WINDOW)
break;
if (!ar)
- return 0;
+ return false;
/* bad context switch .. */
CTX_wm_area_set(C, sa);
CTX_wm_region_set(C, ar);
- return 1;
+ return true;
}
static int game_engine_exec(bContext *C, wmOperator *op)
@@ -1425,7 +1466,7 @@ static int game_engine_exec(bContext *C, wmOperator *op)
{
/* Letterbox */
rctf cam_framef;
- ED_view3d_calc_camera_border(startscene, ar, CTX_wm_view3d(C), rv3d, &cam_framef, FALSE);
+ ED_view3d_calc_camera_border(startscene, ar, CTX_wm_view3d(C), rv3d, &cam_framef, false);
cam_frame.xmin = cam_framef.xmin + ar->winrct.xmin;
cam_frame.xmax = cam_framef.xmax + ar->winrct.xmin;
cam_frame.ymin = cam_framef.ymin + ar->winrct.ymin;
@@ -1526,11 +1567,7 @@ static void UNUSED_FUNCTION(view3d_align_axis_to_vector)(View3D *v3d, RegionView
float ED_view3d_pixel_size(RegionView3D *rv3d, const float co[3])
{
- return (rv3d->persmat[3][3] + (
- rv3d->persmat[0][3] * co[0] +
- rv3d->persmat[1][3] * co[1] +
- rv3d->persmat[2][3] * co[2])
- ) * rv3d->pixsize;
+ return mul_project_m4_v3_zfac(rv3d->persmat, co) * rv3d->pixsize * U.pixelsize;
}
float ED_view3d_radius_to_persp_dist(const float angle, const float radius)
diff --git a/source/blender/editors/transform/SConscript b/source/blender/editors/transform/SConscript
index 9cf36a2d970..d579fd73db3 100644
--- a/source/blender/editors/transform/SConscript
+++ b/source/blender/editors/transform/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index d877d506e3e..64e49abd761 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -52,12 +52,14 @@
#include "DNA_movieclip_types.h"
#include "DNA_scene_types.h" /* PET modes */
-#include "RNA_access.h"
-
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
-
-#include "BLF_api.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_linklist.h"
+#include "BLI_smallhash.h"
#include "BKE_nla.h"
#include "BKE_bmesh.h"
@@ -69,6 +71,9 @@
#include "BKE_unit.h"
#include "BKE_mask.h"
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
#include "ED_image.h"
#include "ED_keyframing.h"
#include "ED_screen.h"
@@ -79,25 +84,38 @@
#include "ED_clip.h"
#include "ED_mask.h"
-#include "UI_view2d.h"
#include "WM_types.h"
#include "WM_api.h"
-#include "BLI_math.h"
-#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
-#include "BLI_ghash.h"
-#include "BLI_linklist.h"
-#include "BLI_smallhash.h"
-#include "BLI_array.h"
-
+#include "UI_view2d.h"
#include "UI_interface_icons.h"
#include "UI_resources.h"
+#include "RNA_access.h"
+
+#include "BLF_api.h"
+#include "BLF_translation.h"
+
#include "transform.h"
+#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 drawEdgeSlide(const struct bContext *C, TransInfo *t);
+static void drawVertSlide(const struct bContext *C, TransInfo *t);
+
+static bool transdata_check_local_center(TransInfo *t)
+{
+ return ((t->around == V3D_LOCAL) && (
+ (t->flag & (T_OBJECT | T_POSE)) ||
+ (t->obedit && t->obedit->type == OB_MESH && (t->settings->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_FACE))) ||
+ (t->obedit && t->obedit->type == OB_ARMATURE) ||
+ (t->spacetype == SPACE_IPO))
+ );
+}
/* ************************** SPACE DEPENDANT CODE **************************** */
@@ -167,7 +185,7 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy)
{
if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) {
const float mval_f[2] = {(float)dx, (float)dy};
- ED_view3d_win_to_delta(t->ar, mval_f, r_vec);
+ ED_view3d_win_to_delta(t->ar, mval_f, r_vec, t->zfac);
}
else if (t->spacetype == SPACE_IMAGE) {
float aspx, aspy;
@@ -223,11 +241,11 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy)
}
}
-void projectIntView(TransInfo *t, const float vec[3], int adr[2])
+void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DProjTest flag)
{
if (t->spacetype == SPACE_VIEW3D) {
if (t->ar->regiontype == RGN_TYPE_WINDOW) {
- if (ED_view3d_project_int_global(t->ar, vec, adr, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) {
+ if (ED_view3d_project_int_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) {
adr[0] = (int)2140000000.0f; /* this is what was done in 2.64, perhaps we can be smarter? */
adr[1] = (int)2140000000.0f;
}
@@ -345,14 +363,19 @@ void projectIntView(TransInfo *t, const float vec[3], int adr[2])
UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], vec[1], adr, adr + 1);
}
}
+void projectIntView(TransInfo *t, const float vec[3], int adr[2])
+{
+ projectIntViewEx(t, vec, adr, V3D_PROJ_TEST_NOP);
+}
-void projectFloatView(TransInfo *t, const float vec[3], float adr[2])
+void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV3DProjTest flag)
{
switch (t->spacetype) {
case SPACE_VIEW3D:
{
if (t->ar->regiontype == RGN_TYPE_WINDOW) {
- if (ED_view3d_project_float_global(t->ar, vec, adr, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) {
+ /* allow points behind the view [#33643] */
+ if (ED_view3d_project_float_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) {
/* XXX, 2.64 and prior did this, weak! */
adr[0] = t->ar->winx / 2.0f;
adr[1] = t->ar->winy / 2.0f;
@@ -376,6 +399,10 @@ void projectFloatView(TransInfo *t, const float vec[3], float adr[2])
zero_v2(adr);
}
+void projectFloatView(TransInfo *t, const float vec[3], float adr[2])
+{
+ projectFloatViewEx(t, vec, adr, V3D_PROJ_TEST_NOP);
+}
void applyAspectRatio(TransInfo *t, float vec[2])
{
@@ -461,7 +488,10 @@ static void viewRedrawForce(const bContext *C, TransInfo *t)
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
else
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
+
+ if (t->mode == TFM_EDGE_SLIDE && (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT))
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+
/* for realtime animation record - send notifiers recognised by animation editors */
// XXX: is this notifier a lame duck?
if ((t->animtimer) && IS_AUTOKEY_ON(t->scene))
@@ -685,6 +715,9 @@ static void view_editmove(unsigned short UNUSED(event))
#define TFM_MODAL_EDGESLIDE_UP 24
#define TFM_MODAL_EDGESLIDE_DOWN 25
+/* for analog input, like trackpad */
+#define TFM_MODAL_PROPSIZE 26
+
/* called in transform_ops.c, on each regeneration of keymaps */
wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
{
@@ -714,6 +747,7 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
{TFM_MODAL_AUTOIK_LEN_DEC, "AUTOIK_CHAIN_LEN_DOWN", 0, "Decrease Max AutoIK Chain Length", ""},
{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", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -749,6 +783,7 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, 0, 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, MOUSEPAN, 0, 0, 0, TFM_MODAL_PROPSIZE);
WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_ALT, 0, TFM_MODAL_EDGESLIDE_UP);
WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, KM_ALT, 0, TFM_MODAL_EDGESLIDE_DOWN);
@@ -766,22 +801,29 @@ 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);
- char msg1[] = "along _";
- char msg2[] = "along %s _";
- char msg3[] = "locking %s _";
+ const char *msg1 = "", *msg2 = "", *msg3 = "";
char axis;
/* Initialize */
switch (key_type) {
case XKEY:
+ msg1 = IFACE_("along X");
+ msg2 = IFACE_("along %s X");
+ msg3 = IFACE_("locking %s X");
axis = 'X';
constraint_axis = CON_AXIS0;
break;
case YKEY:
+ msg1 = IFACE_("along Y");
+ msg2 = IFACE_("along %s Y");
+ msg3 = IFACE_("locking %s Y");
axis = 'Y';
constraint_axis = CON_AXIS1;
break;
case ZKEY:
+ msg1 = IFACE_("along Z");
+ msg2 = IFACE_("along %s Z");
+ msg3 = IFACE_("locking %s Z");
axis = 'Z';
constraint_axis = CON_AXIS2;
break;
@@ -789,9 +831,6 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm
/* Invalid key */
return;
}
- msg1[sizeof(msg1) - 2] = axis;
- msg2[sizeof(msg2) - 2] = axis;
- msg3[sizeof(msg3) - 2] = axis;
constraint_plane = ((CON_AXIS0 | CON_AXIS1 | CON_AXIS2) & (~constraint_axis));
if (edit_2d && (key_type != ZKEY)) {
@@ -827,7 +866,7 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm
}
}
-int transformEvent(TransInfo *t, wmEvent *event)
+int transformEvent(TransInfo *t, const wmEvent *event)
{
float mati[3][3] = MAT3_UNITY;
char cmode = constraintModeToChar(t);
@@ -866,19 +905,56 @@ int transformEvent(TransInfo *t, wmEvent *event)
break;
case TFM_MODAL_TRANSLATE:
/* only switch when... */
- if (ELEM3(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL) ) {
+ if (ELEM5(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
+ if (t->mode == TFM_EDGE_SLIDE) {
+ freeEdgeSlideVerts(t);
+ }
+ else if (t->mode == TFM_VERT_SLIDE) {
+ freeVertSlideVerts(t);
+ }
resetTransRestrictions(t);
restoreTransObjects(t);
initTranslation(t);
initSnapping(t, NULL); // need to reinit after mode change
t->redraw |= TREDRAW_HARD;
+ WM_event_add_mousemove(t->context);
}
- else if (t->mode == TFM_TRANSLATION) {
- if (t->options & (CTX_MOVIECLIP | CTX_MASK)) {
- restoreTransObjects(t);
+ else if (t->mode == TFM_SEQ_SLIDE) {
+ t->flag ^= T_ALT_TRANSFORM;
+ t->redraw |= TREDRAW_HARD;
+ }
+ else {
+ if (t->obedit && t->obedit->type == OB_MESH) {
+ if ((t->mode == TFM_TRANSLATION) && (t->spacetype == SPACE_VIEW3D)) {
+ resetTransRestrictions(t);
+ restoreTransObjects(t);
- t->flag ^= T_ALT_TRANSFORM;
- t->redraw |= TREDRAW_HARD;
+ /* first try edge slide */
+ initEdgeSlide(t);
+ /* if that fails, do vertex slide */
+ if (t->state == TRANS_CANCEL) {
+ t->state = TRANS_STARTING;
+ initVertSlide(t);
+ }
+ /* vert slide can fail on unconnected vertices (rare but possible) */
+ if (t->state == TRANS_CANCEL) {
+ t->state = TRANS_STARTING;
+ resetTransRestrictions(t);
+ restoreTransObjects(t);
+ initTranslation(t);
+ }
+ initSnapping(t, NULL); // need to reinit after mode change
+ t->redraw |= TREDRAW_HARD;
+ WM_event_add_mousemove(t->context);
+ }
+ }
+ else if (t->options & (CTX_MOVIECLIP | CTX_MASK)) {
+ if (t->mode == TFM_TRANSLATION) {
+ restoreTransObjects(t);
+
+ t->flag ^= T_ALT_TRANSFORM;
+ t->redraw |= TREDRAW_HARD;
+ }
}
}
break;
@@ -911,6 +987,10 @@ int transformEvent(TransInfo *t, wmEvent *event)
initSnapping(t, NULL); // need to reinit after mode change
t->redraw |= TREDRAW_HARD;
}
+ else if (t->mode == TFM_SHRINKFATTEN) {
+ t->flag ^= T_ALT_TRANSFORM;
+ t->redraw |= TREDRAW_HARD;
+ }
else if (t->mode == TFM_RESIZE) {
if (t->options & CTX_MOVIECLIP) {
restoreTransObjects(t);
@@ -940,10 +1020,10 @@ int transformEvent(TransInfo *t, wmEvent *event)
}
else {
if (t->flag & T_2D_EDIT) {
- setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS0), "along X");
+ setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS0), IFACE_("along X"));
}
else {
- setUserConstraint(t, t->current_orientation, (CON_AXIS0), "along %s X");
+ setUserConstraint(t, t->current_orientation, (CON_AXIS0), IFACE_("along %s X"));
}
}
t->redraw |= TREDRAW_HARD;
@@ -956,10 +1036,10 @@ int transformEvent(TransInfo *t, wmEvent *event)
}
else {
if (t->flag & T_2D_EDIT) {
- setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS1), "along Y");
+ setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS1), IFACE_("along Y"));
}
else {
- setUserConstraint(t, t->current_orientation, (CON_AXIS1), "along %s Y");
+ setUserConstraint(t, t->current_orientation, (CON_AXIS1), IFACE_("along %s Y"));
}
}
t->redraw |= TREDRAW_HARD;
@@ -971,7 +1051,7 @@ int transformEvent(TransInfo *t, wmEvent *event)
stopConstraint(t);
}
else {
- setUserConstraint(t, t->current_orientation, (CON_AXIS2), "along %s Z");
+ setUserConstraint(t, t->current_orientation, (CON_AXIS2), IFACE_("along %s Z"));
}
t->redraw |= TREDRAW_HARD;
}
@@ -982,7 +1062,7 @@ int transformEvent(TransInfo *t, wmEvent *event)
stopConstraint(t);
}
else {
- setUserConstraint(t, t->current_orientation, (CON_AXIS1 | CON_AXIS2), "locking %s X");
+ setUserConstraint(t, t->current_orientation, (CON_AXIS1 | CON_AXIS2), IFACE_("locking %s X"));
}
t->redraw |= TREDRAW_HARD;
}
@@ -993,7 +1073,7 @@ int transformEvent(TransInfo *t, wmEvent *event)
stopConstraint(t);
}
else {
- setUserConstraint(t, t->current_orientation, (CON_AXIS0 | CON_AXIS2), "locking %s Y");
+ setUserConstraint(t, t->current_orientation, (CON_AXIS0 | CON_AXIS2), IFACE_("locking %s Y"));
}
t->redraw |= TREDRAW_HARD;
}
@@ -1004,7 +1084,7 @@ int transformEvent(TransInfo *t, wmEvent *event)
stopConstraint(t);
}
else {
- setUserConstraint(t, t->current_orientation, (CON_AXIS0 | CON_AXIS1), "locking %s Z");
+ setUserConstraint(t, t->current_orientation, (CON_AXIS0 | CON_AXIS1), IFACE_("locking %s Z"));
}
t->redraw |= TREDRAW_HARD;
}
@@ -1023,6 +1103,19 @@ int transformEvent(TransInfo *t, wmEvent *event)
removeSnapPoint(t);
t->redraw |= TREDRAW_HARD;
break;
+
+ case TFM_MODAL_PROPSIZE:
+ /* MOUSEPAN usage... */
+ if (t->flag & T_PROP_EDIT) {
+ float fac = 1.0f + 0.005f *(event->y - event->prevy);
+ t->prop_size *= fac;
+ if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO)
+ t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far);
+ calculatePropRatio(t);
+ }
+ t->redraw |= TREDRAW_HARD;
+ break;
+
case TFM_MODAL_PROPSIZE_UP:
if (t->flag & T_PROP_EDIT) {
t->prop_size *= 1.1f;
@@ -1096,7 +1189,7 @@ int transformEvent(TransInfo *t, wmEvent *event)
/* exception for switching to dolly, or trackball, in camera view */
if (t->flag & T_CAMERA) {
if (t->mode == TFM_TRANSLATION)
- setLocalConstraint(t, (CON_AXIS2), "along local Z");
+ setLocalConstraint(t, (CON_AXIS2), IFACE_("along local Z"));
else if (t->mode == TFM_ROTATION) {
restoreTransObjects(t);
initTrackball(t);
@@ -1207,7 +1300,9 @@ int transformEvent(TransInfo *t, wmEvent *event)
if (t->flag & T_AUTOIK) {
transform_autoik_update(t, 1);
}
- else view_editmove(event->type);
+ else {
+ view_editmove(event->type);
+ }
t->redraw = 1;
break;
case PADMINUS:
@@ -1222,7 +1317,9 @@ int transformEvent(TransInfo *t, wmEvent *event)
if (t->flag & T_AUTOIK) {
transform_autoik_update(t, -1);
}
- else view_editmove(event->type);
+ else {
+ view_editmove(event->type);
+ }
t->redraw = 1;
break;
case LEFTALTKEY:
@@ -1460,7 +1557,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
if (ob) mul_m4_v3(ob->obmat, vecrot);
}
- projectFloatView(t, vecrot, cent); // no overflow in extreme cases
+ projectFloatViewEx(t, vecrot, cent, V3D_PROJ_TEST_CLIP_ZERO);
glPushMatrix();
@@ -1499,7 +1596,6 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
glTranslatef(mval[0], mval[1], 0);
glLineWidth(3.0);
- glBegin(GL_LINES);
drawArrow(UP, 5, 10, 5);
drawArrow(DOWN, 5, 10, 5);
glLineWidth(1.0);
@@ -1579,26 +1675,36 @@ static void drawTransformView(const struct bContext *C, ARegion *UNUSED(ar), voi
drawConstraint(t);
drawPropCircle(C, t);
drawSnapping(C, t);
- drawNonPropEdge(C, t);
+
+ /* edge slide, vert slide */
+ drawEdgeSlide(C, t);
+ drawVertSlide(C, t);
}
/* just draw a little warning message in the top-right corner of the viewport to warn that autokeying is enabled */
static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar)
{
- const char printable[] = "Auto Keying On";
+ rcti rect;
+ const char *printable = IFACE_("Auto Keying On");
float printable_size[2];
int xco, yco;
+ ED_region_visible_rect(ar, &rect);
+
BLF_width_and_height_default(printable, &printable_size[0], &printable_size[1]);
- xco = ar->winx - (int)printable_size[0] - 10;
- yco = ar->winy - (int)printable_size[1] - 10;
+ xco = rect.xmax - (int)printable_size[0] - 10;
+ yco = rect.ymax - (int)printable_size[1] - 10;
/* warning text (to clarify meaning of overlays)
* - original color was red to match the icon, but that clashes badly with a less nasty border
*/
UI_ThemeColorShade(TH_TEXT_HI, -50);
+#ifdef WITH_INTERNATIONAL
+ BLF_draw_default(xco, ar->winy - 17, 0.0f, printable, sizeof(printable));
+#else
BLF_draw_default_ascii(xco, ar->winy - 17, 0.0f, printable, sizeof(printable));
+#endif
/* autokey recording icon... */
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -1754,7 +1860,7 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
}
/* note: caller needs to free 't' on a 0 return */
-int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int mode)
+int initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event, int mode)
{
int options = 0;
PropertyRNA *prop;
@@ -1855,6 +1961,8 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int
}
+ t->keymap = WM_keymap_active(CTX_wm_manager(C), op->type->modalkeymap);
+
initSnapping(t, op); // Initialize snapping data AFTER mode flags
/* EVIL! posemode code can switch translation to rotate when 1 bone is selected. will be removed (ton) */
@@ -1925,6 +2033,9 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int
case TFM_EDGE_SLIDE:
initEdgeSlide(t);
break;
+ case TFM_VERT_SLIDE:
+ initVertSlide(t);
+ break;
case TFM_BONE_ROLL:
initBoneRoll(t);
break;
@@ -2056,12 +2167,6 @@ void transformApply(bContext *C, TransInfo *t)
t->state = TRANS_CONFIRM;
}
- if (BKE_ptcache_get_continue_physics()) {
- // TRANSFORM_FIX_ME
- //do_screenhandlers(G.curscreen);
- t->redraw |= TREDRAW_HARD;
- }
-
t->context = NULL;
}
@@ -2254,8 +2359,8 @@ static void protectedQuaternionBits(short protectflag, float *quat, float *oldqu
static void constraintTransLim(TransInfo *t, TransData *td)
{
if (td->con) {
- bConstraintTypeInfo *ctiLoc = get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT);
- bConstraintTypeInfo *ctiDist = get_constraint_typeinfo(CONSTRAINT_TYPE_DISTLIMIT);
+ bConstraintTypeInfo *ctiLoc = BKE_get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT);
+ bConstraintTypeInfo *ctiDist = BKE_get_constraint_typeinfo(CONSTRAINT_TYPE_DISTLIMIT);
bConstraintOb cob = {NULL};
bConstraint *con;
@@ -2274,7 +2379,7 @@ static void constraintTransLim(TransInfo *t, TransData *td)
ListBase targets = {NULL, NULL};
/* only consider constraint if enabled */
- if (con->flag & CONSTRAINT_DISABLE) continue;
+ if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) continue;
if (con->enforce == 0.0f) continue;
/* only use it if it's tagged for this purpose (and the right type) */
@@ -2305,7 +2410,7 @@ static void constraintTransLim(TransInfo *t, TransData *td)
}
/* get constraint targets if needed */
- get_constraint_targets_for_solving(con, &cob, &targets, ctime);
+ BKE_get_constraint_targets_for_solving(con, &cob, &targets, ctime);
/* do constraint */
cti->evaluate_constraint(con, &cob, &targets);
@@ -2357,7 +2462,7 @@ static void constraintob_from_transdata(bConstraintOb *cob, TransData *td)
static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
{
if (td->con) {
- bConstraintTypeInfo *cti = get_constraint_typeinfo(CONSTRAINT_TYPE_ROTLIMIT);
+ bConstraintTypeInfo *cti = BKE_get_constraint_typeinfo(CONSTRAINT_TYPE_ROTLIMIT);
bConstraintOb cob;
bConstraint *con;
int do_limit = FALSE;
@@ -2365,7 +2470,7 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
/* Evaluate valid constraints */
for (con = td->con; con; con = con->next) {
/* only consider constraint if enabled */
- if (con->flag & CONSTRAINT_DISABLE) continue;
+ if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) continue;
if (con->enforce == 0.0f) continue;
/* we're only interested in Limit-Rotation constraints */
@@ -2424,7 +2529,7 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
static void constraintSizeLim(TransInfo *t, TransData *td)
{
if (td->con && td->ext) {
- bConstraintTypeInfo *cti = get_constraint_typeinfo(CONSTRAINT_TYPE_SIZELIMIT);
+ bConstraintTypeInfo *cti = BKE_get_constraint_typeinfo(CONSTRAINT_TYPE_SIZELIMIT);
bConstraintOb cob = {NULL};
bConstraint *con;
float size_sign[3], size_abs[3];
@@ -2455,7 +2560,7 @@ static void constraintSizeLim(TransInfo *t, TransData *td)
/* Evaluate valid constraints */
for (con = td->con; con; con = con->next) {
/* only consider constraint if enabled */
- if (con->flag & CONSTRAINT_DISABLE) continue;
+ if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) continue;
if (con->enforce == 0.0f) continue;
/* we're only interested in Limit-Scale constraints */
@@ -2555,11 +2660,12 @@ void initWarp(TransInfo *t)
mid_v3_v3v3(t->center, min, max);
- if (max[0] == min[0]) max[0] += 0.1f; /* not optimal, but flipping is better than invalid garbage (i.e. division by zero!) */
+ if (max[0] == min[0])
+ max[0] += 0.1f; /* not optimal, but flipping is better than invalid garbage (i.e. division by zero!) */
t->val = (max[0] - min[0]) / 2.0f; /* t->val is X dimension projected boundbox */
}
-int handleEventWarp(TransInfo *t, wmEvent *event)
+int handleEventWarp(TransInfo *t, const wmEvent *event)
{
int status = 0;
@@ -2579,9 +2685,10 @@ int handleEventWarp(TransInfo *t, wmEvent *event)
int Warp(TransInfo *t, const int UNUSED(mval[2]))
{
TransData *td = t->data;
- float vec[3], circumfac, dist, phi0, co, si, *curs, cursor[3], gcursor[3];
+ float vec[3], circumfac, dist, phi0, co, si, cursor[3], gcursor[3];
+ const float *curs;
int i;
- char str[50];
+ char str[MAX_INFO_LEN];
curs = give_cursor(t->scene, t->view);
/*
@@ -2616,13 +2723,13 @@ int Warp(TransInfo *t, const int UNUSED(mval[2]))
outputNumInput(&(t->num), c);
- sprintf(str, "Warp: %s", c);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Warp: %s"), c);
circumfac = DEG2RADF(circumfac);
}
else {
/* default header print */
- sprintf(str, "Warp: %.3f", RAD2DEGF(circumfac));
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Warp: %.3f"), RAD2DEGF(circumfac));
}
t->values[0] = circumfac;
@@ -2699,7 +2806,7 @@ void initShear(TransInfo *t)
t->flag |= T_NO_CONSTRAINT;
}
-int handleEventShear(TransInfo *t, wmEvent *event)
+int handleEventShear(TransInfo *t, const wmEvent *event)
{
int status = 0;
@@ -2716,6 +2823,18 @@ int handleEventShear(TransInfo *t, wmEvent *event)
status = 1;
}
+ else if (event->type == XKEY && event->val == KM_PRESS) {
+ initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE);
+ t->customData = NULL;
+
+ status = 1;
+ }
+ else if (event->type == YKEY && event->val == KM_PRESS) {
+ initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE);
+ t->customData = (void *)1;
+
+ status = 1;
+ }
return status;
}
@@ -2728,7 +2847,7 @@ int Shear(TransInfo *t, const int UNUSED(mval[2]))
float smat[3][3], tmat[3][3], totmat[3][3], persmat[3][3], persinv[3][3];
float value;
int i;
- char str[50];
+ char str[MAX_INFO_LEN];
copy_m3_m4(persmat, t->viewmat);
invert_m3_m3(persinv, persmat);
@@ -2745,11 +2864,11 @@ int Shear(TransInfo *t, const int UNUSED(mval[2]))
outputNumInput(&(t->num), c);
- sprintf(str, "Shear: %s %s", c, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shear: %s %s"), c, t->proptext);
}
else {
/* default header print */
- sprintf(str, "Shear: %.3f %s", value, t->proptext);
+ 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;
@@ -2825,10 +2944,11 @@ void initResize(TransInfo *t)
t->num.increment = t->snap[1];
}
+/* We assume str is MAX_INFO_LEN long. */
static void headerResize(TransInfo *t, float vec[3], char *str)
{
char tvec[NUM_STR_REP_LEN * 3];
- char *spos = str;
+ size_t ofs = 0;
if (hasNumInput(&t->num)) {
outputNumInput(&(t->num), tvec);
}
@@ -2837,37 +2957,36 @@ static void headerResize(TransInfo *t, float vec[3], char *str)
BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]);
BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]);
}
-
+
if (t->con.mode & CON_APPLY) {
switch (t->num.idx_max) {
case 0:
- spos += sprintf(spos, "Scale: %s%s %s", &tvec[0], t->con.text, t->proptext);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Scale: %s%s %s"),
+ &tvec[0], t->con.text, t->proptext);
break;
case 1:
- spos += sprintf(spos, "Scale: %s : %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN],
- t->con.text, t->proptext);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Scale: %s : %s%s %s"),
+ &tvec[0], &tvec[NUM_STR_REP_LEN], t->con.text, t->proptext);
break;
case 2:
- spos += sprintf(spos, "Scale: %s : %s : %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN],
- &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Scale: %s : %s : %s%s %s"), &tvec[0],
+ &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext);
}
}
else {
if (t->flag & T_2D_EDIT) {
- spos += sprintf(spos, "Scale X: %s Y: %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN],
- t->con.text, t->proptext);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Scale X: %s Y: %s%s %s"),
+ &tvec[0], &tvec[NUM_STR_REP_LEN], t->con.text, t->proptext);
}
else {
- spos += sprintf(spos, "Scale X: %s Y: %s Z: %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN],
- &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Scale X: %s Y: %s Z: %s%s %s"),
+ &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext);
}
}
-
+
if (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) {
- spos += sprintf(spos, " Proportional size: %.2f", t->prop_size);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
}
-
- (void)spos;
}
/* FLT_EPSILON is too small [#29633], 0.0000001f starts to flip */
@@ -2920,12 +3039,7 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3])
}
/* local constraint shouldn't alter center */
- if ((t->around == V3D_LOCAL) &&
- ( (t->flag & (T_OBJECT | T_POSE)) ||
- ((t->flag & T_EDIT) && (t->settings->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_FACE))) ||
- (t->obedit && t->obedit->type == OB_ARMATURE))
- )
- {
+ if (transdata_check_local_center(t)) {
copy_v3_v3(center, td->center);
}
else if (t->options & CTX_MOVIECLIP) {
@@ -3007,7 +3121,7 @@ int Resize(TransInfo *t, const int mval[2])
float size[3], mat[3][3];
float ratio;
int i;
- char str[200];
+ char str[MAX_INFO_LEN];
/* for manipulator, center handle, the scaling can't be done relative to center */
if ((t->flag & T_USES_MANIPULATOR) && t->con.mode == 0) {
@@ -3112,7 +3226,7 @@ int SkinResize(TransInfo *t, const int UNUSED(mval[2]))
float size[3], mat[3][3];
float ratio;
int i;
- char str[200];
+ char str[MAX_INFO_LEN];
ratio = t->values[0];
size[0] = size[1] = size[2] = ratio;
@@ -3206,7 +3320,7 @@ int ToSphere(TransInfo *t, const int UNUSED(mval[2]))
float vec[3];
float ratio, radius;
int i;
- char str[64];
+ char str[MAX_INFO_LEN];
TransData *td = t->data;
ratio = t->values[0];
@@ -3228,11 +3342,11 @@ int ToSphere(TransInfo *t, const int UNUSED(mval[2]))
outputNumInput(&(t->num), c);
- sprintf(str, "To Sphere: %s %s", c, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("To Sphere: %s %s"), c, t->proptext);
}
else {
/* default header print */
- sprintf(str, "To Sphere: %.4f %s", ratio, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("To Sphere: %.4f %s"), ratio, t->proptext);
}
@@ -3302,20 +3416,16 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
{
float vec[3], totmat[3][3], smat[3][3];
float eul[3], fmat[3][3], quat[4];
- float *center = t->center;
+ const float *center;
/* local constraint shouldn't alter center */
- if (around == V3D_LOCAL) {
- if ( (t->flag & (T_OBJECT | T_POSE)) ||
- (t->settings->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_FACE)) ||
- (t->obedit && t->obedit->type == OB_ARMATURE))
- {
- center = td->center;
- }
-
- if (t->options & CTX_MOVIECLIP) {
- center = td->center;
- }
+ if (transdata_check_local_center(t) ||
+ ((around == V3D_LOCAL) && (t->options & CTX_MOVIECLIP)))
+ {
+ center = td->center;
+ }
+ else {
+ center = t->center;
}
if (t->flag & T_POINTS) {
@@ -3425,7 +3535,8 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat);
/* this function works on end result */
- protectedAxisAngleBits(td->protectflag, td->ext->rotAxis, td->ext->rotAngle, td->ext->irotAxis, td->ext->irotAngle);
+ protectedAxisAngleBits(td->protectflag, td->ext->rotAxis, td->ext->rotAngle, td->ext->irotAxis,
+ td->ext->irotAngle);
}
else {
float eulmat[3][3];
@@ -3472,12 +3583,15 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
if ((t->flag & T_V3D_ALIGN) == 0) { // align mode doesn't rotate objects itself
/* euler or quaternion? */
if ((td->ext->rotOrder == ROT_MODE_QUAT) || (td->flag & TD_USEQUAT)) {
- mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL);
- mat3_to_quat(quat, fmat); // Actual transform
-
- mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat);
- /* this function works on end result */
- protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
+ /* can be called for texture space translate for example, then opt out */
+ if (td->ext->quat) {
+ mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL);
+ mat3_to_quat(quat, fmat); // Actual transform
+
+ mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat);
+ /* this function works on end result */
+ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat);
+ }
}
else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
/* calculate effect based on quats */
@@ -3492,7 +3606,8 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat);
/* this function works on end result */
- protectedAxisAngleBits(td->protectflag, td->ext->rotAxis, td->ext->rotAngle, td->ext->irotAxis, td->ext->irotAngle);
+ protectedAxisAngleBits(td->protectflag, td->ext->rotAxis, td->ext->rotAngle, td->ext->irotAxis,
+ td->ext->irotAngle);
}
else {
float obmat[3][3];
@@ -3551,14 +3666,15 @@ static void applyRotation(TransInfo *t, float angle, float axis[3])
int Rotation(TransInfo *t, const int UNUSED(mval[2]))
{
- char str[128], *spos = str;
-
+ char str[MAX_INFO_LEN];
+ size_t ofs = 0;
+
float final;
final = t->values[0];
-
+
snapGrid(t, &final);
-
+
if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
t->con.applyRot(t, NULL, t->axis, NULL);
}
@@ -3566,9 +3682,9 @@ int Rotation(TransInfo *t, const int UNUSED(mval[2]))
/* reset axis if constraint is not set */
copy_v3_v3(t->axis, t->axis_orig);
}
-
+
applySnapping(t, &final);
-
+
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@@ -3576,19 +3692,19 @@ int Rotation(TransInfo *t, const int UNUSED(mval[2]))
outputNumInput(&(t->num), c);
- spos += sprintf(spos, "Rot: %s %s %s", &c[0], t->con.text, t->proptext);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext);
/* Clamp between -180 and 180 */
final = angle_wrap_rad(DEG2RADF(final));
}
else {
- spos += sprintf(spos, "Rot: %.2f%s %s", RAD2DEGF(final), t->con.text, t->proptext);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Rot: %.2f%s %s"),
+ RAD2DEGF(final), t->con.text, t->proptext);
}
if (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) {
- spos += sprintf(spos, " Proportional size: %.2f", t->prop_size);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
}
- (void)spos;
t->values[0] = final;
@@ -3653,7 +3769,8 @@ static void applyTrackball(TransInfo *t, float axis1[3], float axis2[3], float a
int Trackball(TransInfo *t, const int UNUSED(mval[2]))
{
- char str[128], *spos = str;
+ char str[MAX_INFO_LEN];
+ size_t ofs = 0;
float axis1[3], axis2[3];
float mat[3][3], totmat[3][3], smat[3][3];
float phi[2];
@@ -3675,19 +3792,20 @@ int Trackball(TransInfo *t, const int UNUSED(mval[2]))
outputNumInput(&(t->num), c);
- spos += sprintf(spos, "Trackball: %s %s %s", &c[0], &c[NUM_STR_REP_LEN], t->proptext);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Trackball: %s %s %s"),
+ &c[0], &c[NUM_STR_REP_LEN], t->proptext);
phi[0] = DEG2RADF(phi[0]);
phi[1] = DEG2RADF(phi[1]);
}
else {
- spos += sprintf(spos, "Trackball: %.2f %.2f %s", RAD2DEGF(phi[0]), RAD2DEGF(phi[1]), t->proptext);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Trackball: %.2f %.2f %s"),
+ RAD2DEGF(phi[0]), RAD2DEGF(phi[1]), t->proptext);
}
if (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) {
- spos += sprintf(spos, " Proportional size: %.2f", t->prop_size);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
}
- (void)spos;
vec_rot_to_mat3(smat, axis1, phi[0]);
vec_rot_to_mat3(totmat, axis2, phi[1]);
@@ -3751,9 +3869,10 @@ void initTranslation(TransInfo *t)
t->num.increment = t->snap[1];
}
+/* We assume str is MAX_INFO_LEN long. */
static void headerTranslation(TransInfo *t, float vec[3], char *str)
{
- char *spos = str;
+ size_t ofs = 0;
char tvec[NUM_STR_REP_LEN * 3];
char distvec[NUM_STR_REP_LEN];
char autoik[NUM_STR_REP_LEN];
@@ -3774,29 +3893,30 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str)
int i, do_split = t->scene->unit.flag & USER_UNIT_OPT_SPLIT ? 1 : 0;
for (i = 0; i < 3; i++) {
- bUnit_AsString(&tvec[i * NUM_STR_REP_LEN], NUM_STR_REP_LEN, dvec[i] * t->scene->unit.scale_length,
+ bUnit_AsString(&tvec[NUM_STR_REP_LEN * i], NUM_STR_REP_LEN, dvec[i] * t->scene->unit.scale_length,
4, t->scene->unit.system, B_UNIT_LENGTH, do_split, 1);
}
}
else {
- sprintf(&tvec[0], "%.4f", dvec[0]);
- sprintf(&tvec[NUM_STR_REP_LEN], "%.4f", dvec[1]);
- sprintf(&tvec[NUM_STR_REP_LEN * 2], "%.4f", dvec[2]);
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", dvec[0]);
+ BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", dvec[1]);
+ BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", dvec[2]);
}
}
if (!(t->flag & T_2D_EDIT) && t->scene->unit.system)
- bUnit_AsString(distvec, sizeof(distvec), dist * t->scene->unit.scale_length, 4, t->scene->unit.system, B_UNIT_LENGTH, t->scene->unit.flag & USER_UNIT_OPT_SPLIT, 0);
+ bUnit_AsString(distvec, sizeof(distvec), dist * t->scene->unit.scale_length, 4, t->scene->unit.system,
+ B_UNIT_LENGTH, t->scene->unit.flag & USER_UNIT_OPT_SPLIT, 0);
else if (dist > 1e10f || dist < -1e10f) /* prevent string buffer overflow */
- sprintf(distvec, "%.4e", dist);
+ BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4e", dist);
else
- sprintf(distvec, "%.4f", dist);
+ BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4f", dist);
if (t->flag & T_AUTOIK) {
short chainlen = t->settings->autoik_chainlen;
if (chainlen)
- sprintf(autoik, "AutoIK-Len: %d", chainlen);
+ BLI_snprintf(autoik, NUM_STR_REP_LEN, IFACE_("AutoIK-Len: %d"), chainlen);
else
autoik[0] = '\0';
}
@@ -3806,32 +3926,34 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str)
if (t->con.mode & CON_APPLY) {
switch (t->num.idx_max) {
case 0:
- spos += sprintf(spos, "D: %s (%s)%s %s %s", &tvec[0], distvec, t->con.text, t->proptext, &autoik[0]);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "D: %s (%s)%s %s %s",
+ &tvec[0], distvec, t->con.text, t->proptext, autoik);
break;
case 1:
- spos += sprintf(spos, "D: %s D: %s (%s)%s %s %s", &tvec[0], &tvec[NUM_STR_REP_LEN],
- distvec, t->con.text, t->proptext, &autoik[0]);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "D: %s D: %s (%s)%s %s %s",
+ &tvec[0], &tvec[NUM_STR_REP_LEN], distvec, t->con.text, t->proptext, autoik);
break;
case 2:
- spos += sprintf(spos, "D: %s D: %s D: %s (%s)%s %s %s", &tvec[0], &tvec[NUM_STR_REP_LEN],
- &tvec[NUM_STR_REP_LEN * 2], distvec, t->con.text, t->proptext, &autoik[0]);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "D: %s D: %s D: %s (%s)%s %s %s",
+ &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], distvec,
+ t->con.text, t->proptext, autoik);
}
}
else {
if (t->flag & T_2D_EDIT) {
- spos += sprintf(spos, "Dx: %s Dy: %s (%s)%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN],
- distvec, t->con.text, t->proptext);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "Dx: %s Dy: %s (%s)%s %s",
+ &tvec[0], &tvec[NUM_STR_REP_LEN], distvec, t->con.text, t->proptext);
}
else {
- spos += sprintf(spos, "Dx: %s Dy: %s Dz: %s (%s)%s %s %s", &tvec[0], &tvec[NUM_STR_REP_LEN],
- &tvec[NUM_STR_REP_LEN * 2], distvec, t->con.text, t->proptext, &autoik[0]);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "Dx: %s Dy: %s Dz: %s (%s)%s %s %s",
+ &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], distvec, t->con.text,
+ t->proptext, autoik);
}
}
-
+
if (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) {
- spos += sprintf(spos, " Proportional size: %.2f", t->prop_size);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size);
}
- (void)spos;
}
static void applyTranslation(TransInfo *t, float vec[3])
@@ -3903,7 +4025,7 @@ static void applyTranslation(TransInfo *t, float vec[3])
/* uses t->vec to store actual translation in */
int Translation(TransInfo *t, const int UNUSED(mval[2]))
{
- char str[250];
+ char str[MAX_INFO_LEN];
if (t->con.mode & CON_APPLY) {
float pvec[3] = {0.0f, 0.0f, 0.0f};
@@ -3979,7 +4101,8 @@ int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
{
float distance;
int i;
- char str[64];
+ char str[MAX_INFO_LEN];
+ size_t ofs = 0;
TransData *td = t->data;
distance = -t->values[0];
@@ -3989,17 +4112,32 @@ int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
applyNumInput(&t->num, &distance);
/* header print for NumInput */
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Shrink/Fatten:"), MAX_INFO_LEN - ofs);
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
-
outputNumInput(&(t->num), c);
-
- sprintf(str, "Shrink/Fatten: %s %s", c, t->proptext);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, " %s", c);
}
else {
/* default header print */
- sprintf(str, "Shrink/Fatten: %.4f %s", distance, t->proptext);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, " %.4f", distance);
+ }
+
+ if (t->proptext[0]) {
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, " %s", t->proptext);
}
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, ", (");
+
+ {
+ 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);
+ }
+ }
+ BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" or Alt) Even Thickness %s"),
+ (t->flag & T_ALT_TRANSFORM) ? IFACE_("ON") : IFACE_("OFF"));
+ /* done with header string */
+
t->values[0] = -distance;
@@ -4053,7 +4191,7 @@ int Tilt(TransInfo *t, const int UNUSED(mval[2]))
{
TransData *td = t->data;
int i;
- char str[50];
+ char str[MAX_INFO_LEN];
float final;
@@ -4068,7 +4206,7 @@ int Tilt(TransInfo *t, const int UNUSED(mval[2]))
outputNumInput(&(t->num), c);
- sprintf(str, "Tilt: %s° %s", &c[0], t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Tilt: %s° %s"), &c[0], t->proptext);
final = DEG2RADF(final);
@@ -4076,7 +4214,7 @@ int Tilt(TransInfo *t, const int UNUSED(mval[2]))
t->values[0] = final;
}
else {
- sprintf(str, "Tilt: %.2f° %s", RAD2DEGF(final), t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Tilt: %.2f° %s"), RAD2DEGF(final), t->proptext);
}
for (i = 0; i < t->total; i++, td++) {
@@ -4127,7 +4265,7 @@ int CurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
TransData *td = t->data;
float ratio;
int i;
- char str[50];
+ char str[MAX_INFO_LEN];
ratio = t->values[0];
@@ -4140,10 +4278,10 @@ int CurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c);
- sprintf(str, "Shrink/Fatten: %s", c);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shrink/Fatten: %s"), c);
}
else {
- sprintf(str, "Shrink/Fatten: %3f", ratio);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shrink/Fatten: %3f"), ratio);
}
for (i = 0; i < t->total; i++, td++) {
@@ -4195,7 +4333,7 @@ int MaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
TransData *td;
float ratio;
int i, initial_feather = FALSE;
- char str[50];
+ char str[MAX_INFO_LEN];
ratio = t->values[0];
@@ -4208,10 +4346,10 @@ int MaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c);
- sprintf(str, "Feather Shrink/Fatten: %s", c);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Feather Shrink/Fatten: %s"), c);
}
else {
- sprintf(str, "Feather Shrink/Fatten: %3f", ratio);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Feather Shrink/Fatten: %3f"), ratio);
}
/* detect if no points have feather yet */
@@ -4281,7 +4419,7 @@ int PushPull(TransInfo *t, const int UNUSED(mval[2]))
float vec[3], axis[3];
float distance;
int i;
- char str[128];
+ char str[MAX_INFO_LEN];
TransData *td = t->data;
distance = t->values[0];
@@ -4296,11 +4434,11 @@ int PushPull(TransInfo *t, const int UNUSED(mval[2]))
outputNumInput(&(t->num), c);
- sprintf(str, "Push/Pull: %s%s %s", c, t->con.text, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Push/Pull: %s%s %s"), c, t->con.text, t->proptext);
}
else {
/* default header print */
- sprintf(str, "Push/Pull: %.4f%s %s", distance, t->con.text, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Push/Pull: %.4f%s %s"), distance, t->con.text, t->proptext);
}
t->values[0] = distance;
@@ -4376,7 +4514,7 @@ void initBevel(TransInfo *t)
}
}
-int handleEventBevel(TransInfo *t, wmEvent *event)
+int handleEventBevel(TransInfo *t, const wmEvent *event)
{
if (event->val == KM_PRESS) {
if (!G.editBMesh) return 0;
@@ -4413,11 +4551,11 @@ int Bevel(TransInfo *t, const int UNUSED(mval[2]))
{
float distance, d;
int i;
- char str[128];
+ char str[MAX_INFO_LEN];
const char *mode;
TransData *td = t->data;
- mode = (G.editBMesh->options & BME_BEVEL_VERT) ? "verts only" : "normal";
+ mode = (G.editBMesh->options & BME_BEVEL_VERT) ? IFACE_("verts only") : IFACE_("normal");
distance = t->values[0] / 4; /* 4 just seemed a nice value to me, nothing special */
distance = fabs(distance);
@@ -4432,11 +4570,11 @@ int Bevel(TransInfo *t, const int UNUSED(mval[2]))
outputNumInput(&(t->num), c);
- sprintf(str, "Bevel - Dist: %s, Mode: %s (MMB to toggle))", c, mode);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel - Dist: %s, Mode: %s (MMB to toggle))"), c, mode);
}
else {
/* default header print */
- sprintf(str, "Bevel - Dist: %.4f, Mode: %s (MMB to toggle))", distance, mode);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel - Dist: %.4f, Mode: %s (MMB to toggle))"), distance, mode);
}
if (distance < 0) distance = -distance;
@@ -4482,7 +4620,7 @@ int BevelWeight(TransInfo *t, const int UNUSED(mval[2]))
TransData *td = t->data;
float weight;
int i;
- char str[50];
+ char str[MAX_INFO_LEN];
weight = t->values[0];
@@ -4500,16 +4638,16 @@ int BevelWeight(TransInfo *t, const int UNUSED(mval[2]))
outputNumInput(&(t->num), c);
if (weight >= 0.0f)
- sprintf(str, "Bevel Weight: +%s %s", c, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel Weight: +%s %s"), c, t->proptext);
else
- sprintf(str, "Bevel Weight: %s %s", c, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel Weight: %s %s"), c, t->proptext);
}
else {
/* default header print */
if (weight >= 0.0f)
- sprintf(str, "Bevel Weight: +%.3f %s", weight, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel Weight: +%.3f %s"), weight, t->proptext);
else
- sprintf(str, "Bevel Weight: %.3f %s", weight, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel Weight: %.3f %s"), weight, t->proptext);
}
for (i = 0; i < t->total; i++, td++) {
@@ -4555,7 +4693,7 @@ int Crease(TransInfo *t, const int UNUSED(mval[2]))
TransData *td = t->data;
float crease;
int i;
- char str[50];
+ char str[MAX_INFO_LEN];
crease = t->values[0];
@@ -4573,16 +4711,16 @@ int Crease(TransInfo *t, const int UNUSED(mval[2]))
outputNumInput(&(t->num), c);
if (crease >= 0.0f)
- sprintf(str, "Crease: +%s %s", c, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Crease: +%s %s"), c, t->proptext);
else
- sprintf(str, "Crease: %s %s", c, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Crease: %s %s"), c, t->proptext);
}
else {
/* default header print */
if (crease >= 0.0f)
- sprintf(str, "Crease: +%.3f %s", crease, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Crease: +%.3f %s"), crease, t->proptext);
else
- sprintf(str, "Crease: %.3f %s", crease, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Crease: %.3f %s"), crease, t->proptext);
}
for (i = 0; i < t->total; i++, td++) {
@@ -4626,6 +4764,7 @@ void initBoneSize(TransInfo *t)
t->num.increment = t->snap[1];
}
+/* We assume str is MAX_INFO_LEN long. */
static void headerBoneSize(TransInfo *t, float vec[3], char *str)
{
char tvec[NUM_STR_REP_LEN * 3];
@@ -4633,22 +4772,22 @@ static void headerBoneSize(TransInfo *t, float vec[3], char *str)
outputNumInput(&(t->num), tvec);
}
else {
- sprintf(&tvec[0], "%.4f", vec[0]);
- sprintf(&tvec[NUM_STR_REP_LEN], "%.4f", vec[1]);
- sprintf(&tvec[NUM_STR_REP_LEN * 2], "%.4f", vec[2]);
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]);
+ BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]);
+ BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]);
}
/* hmm... perhaps the y-axis values don't need to be shown? */
if (t->con.mode & CON_APPLY) {
if (t->num.idx_max == 0)
- sprintf(str, "ScaleB: %s%s %s", &tvec[0], t->con.text, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("ScaleB: %s%s %s"), &tvec[0], t->con.text, t->proptext);
else
- sprintf(str, "ScaleB: %s : %s : %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2],
- t->con.text, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("ScaleB: %s : %s : %s%s %s"),
+ &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext);
}
else {
- sprintf(str, "ScaleB X: %s Y: %s Z: %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2],
- t->con.text, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("ScaleB X: %s Y: %s Z: %s%s %s"),
+ &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext);
}
}
@@ -4678,7 +4817,7 @@ int BoneSize(TransInfo *t, const int mval[2])
float size[3], mat[3][3];
float ratio;
int i;
- char str[60];
+ char str[MAX_INFO_LEN];
// TRANSFORM_FIX_ME MOVE TO MOUSE INPUT
/* for manipulator, center handle, the scaling can't be done relative to center */
@@ -4751,7 +4890,7 @@ int BoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
TransData *td = t->data;
float ratio;
int i;
- char str[50];
+ char str[MAX_INFO_LEN];
ratio = t->values[0];
@@ -4764,10 +4903,10 @@ int BoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
char c[NUM_STR_REP_LEN];
outputNumInput(&(t->num), c);
- sprintf(str, "Envelope: %s", c);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Envelope: %s"), c);
}
else {
- sprintf(str, "Envelope: %3f", ratio);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Envelope: %3f"), ratio);
}
for (i = 0; i < t->total; i++, td++) {
@@ -4797,96 +4936,200 @@ int BoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
static BMEdge *get_other_edge(BMVert *v, BMEdge *e)
{
BMIter iter;
- BMEdge *e2;
+ BMEdge *e_iter;
- BM_ITER_ELEM (e2, &iter, v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e2, BM_ELEM_SELECT) && e2 != e)
- return e2;
+ BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT) && e_iter != e) {
+ return e_iter;
+ }
}
return NULL;
}
+static void len_v3_ensure(float v[3], const float length)
+{
+ normalize_v3(v);
+ mul_v3_fl(v, length);
+}
+
+/**
+ * Find the closest point on the ngon on the opposite side.
+ * used to set the edge slide distance for ngons.
+ */
+static bool bm_loop_calc_opposite_co(BMLoop *l_tmp,
+ const float plane_no[3],
+ float r_co[3])
+{
+ /* skip adjacent edges */
+ BMLoop *l_first = l_tmp->next;
+ BMLoop *l_last = l_tmp->prev;
+ BMLoop *l_iter;
+ float dist = FLT_MAX;
+
+ l_iter = l_first;
+ do {
+ float tvec[3];
+ if (isect_line_plane_v3(tvec,
+ l_iter->v->co, l_iter->next->v->co,
+ l_tmp->v->co, plane_no, false))
+ {
+ const float fac = line_point_factor_v3(tvec, l_iter->v->co, l_iter->next->v->co);
+ /* allow some overlap to avoid missing the intersection because of float precision */
+ if ((fac > -FLT_EPSILON) && (fac < 1.0f + FLT_EPSILON)) {
+ /* likelyhood of multiple intersections per ngon is quite low,
+ * it would have to loop back on its self, but better support it
+ * so check for the closest opposite edge */
+ const float tdist = len_v3v3(l_tmp->v->co, tvec);
+ if (tdist < dist) {
+ copy_v3_v3(r_co, tvec);
+ dist = tdist;
+ }
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_last);
+
+ return (dist != FLT_MAX);
+}
+
+/**
+ * Given 2 edges and a loop, step over the loops
+ * and calculate a direction to slide along.
+ *
+ * \param r_slide_vec the direction to slide,
+ * the length of the vector defines the slide distance.
+ */
static BMLoop *get_next_loop(BMVert *v, BMLoop *l,
- BMEdge *olde, BMEdge *nexte, float vec[3])
+ BMEdge *e_prev, BMEdge *e_next, float r_slide_vec[3])
{
- BMLoop *firstl;
- float a[3] = {0.0f, 0.0f, 0.0f}, n[3] = {0.0f, 0.0f, 0.0f};
+ BMLoop *l_first;
+ float vec_accum[3] = {0.0f, 0.0f, 0.0f};
+ float vec_accum_len = 0.0f;
int i = 0;
- firstl = l;
+ BLI_assert(BM_edge_share_vert(e_prev, e_next) == v);
+
+ l_first = l;
do {
l = BM_face_other_edge_loop(l->f, l->e, v);
if (l->radial_next == l)
return NULL;
- if (l->e == nexte) {
+ if (l->e == e_next) {
if (i) {
- mul_v3_fl(a, 1.0f / (float)i);
+ len_v3_ensure(vec_accum, vec_accum_len / (float)i);
}
else {
- float f1[3], f2[3], f3[3];
+ /* When there is no edge to slide along,
+ * we must slide along the vector defined by the face we're attach to */
+ BMLoop *l_tmp = BM_face_vert_share_loop(l_first->f, v);
- sub_v3_v3v3(f1, BM_edge_other_vert(olde, v)->co, v->co);
- sub_v3_v3v3(f2, BM_edge_other_vert(nexte, v)->co, v->co);
+ BLI_assert(ELEM(l_tmp->e, e_prev, e_next) && ELEM(l_tmp->prev->e, e_prev, e_next));
- cross_v3_v3v3(f3, f1, l->f->no);
- cross_v3_v3v3(a, f2, l->f->no);
- mul_v3_fl(a, -1.0f);
+ if (l_tmp->f->len == 4) {
+ /* we could use code below, but in this case
+ * sliding diagonally across the quad works well */
+ sub_v3_v3v3(vec_accum, l_tmp->next->next->v->co, v->co);
+ }
+ else {
+ float tdir[3];
+ BM_loop_calc_face_direction(l_tmp, tdir);
+ cross_v3_v3v3(vec_accum, l_tmp->f->no, tdir);
+#if 0
+ /* rough guess, we can do better! */
+ len_v3_ensure(vec_accum, (BM_edge_calc_length(e_prev) + BM_edge_calc_length(e_next)) / 2.0f);
+#else
+ /* be clever, check the opposite ngon edge to slide into.
+ * this gives best results */
+ {
+ float tvec[3];
+ float dist;
+
+ if (bm_loop_calc_opposite_co(l_tmp, tdir, tvec)) {
+ dist = len_v3v3(l_tmp->v->co, tvec);
+ }
+ else {
+ dist = (BM_edge_calc_length(e_prev) + BM_edge_calc_length(e_next)) / 2.0f;
+ }
- mid_v3_v3v3(a, a, f3);
+ len_v3_ensure(vec_accum, dist);
+ }
+#endif
+ }
}
-
- copy_v3_v3(vec, a);
+
+ copy_v3_v3(r_slide_vec, vec_accum);
return l;
}
else {
- sub_v3_v3v3(n, BM_edge_other_vert(l->e, v)->co, v->co);
- add_v3_v3v3(a, a, n);
+ /* accumulate the normalized edge vector,
+ * normalize so some edges don't skew the result */
+ float tvec[3];
+ sub_v3_v3v3(tvec, BM_edge_other_vert(l->e, v)->co, v->co);
+ vec_accum_len += normalize_v3(tvec);
+ add_v3_v3(vec_accum, tvec);
i += 1;
}
- if (BM_face_other_edge_loop(l->f, l->e, v)->e == nexte) {
- if (i)
- mul_v3_fl(a, 1.0f / (float)i);
-
- copy_v3_v3(vec, a);
+ if (BM_face_other_edge_loop(l->f, l->e, v)->e == e_next) {
+ if (i) {
+ len_v3_ensure(vec_accum, vec_accum_len / (float)i);
+ }
+
+ copy_v3_v3(r_slide_vec, vec_accum);
return BM_face_other_edge_loop(l->f, l->e, v);
}
+ BLI_assert(l != l->radial_next);
l = l->radial_next;
- } while (l != firstl);
+ } while (l != l_first);
- if (i)
- mul_v3_fl(a, 1.0f / (float)i);
+ if (i) {
+ len_v3_ensure(vec_accum, vec_accum_len / (float)i);
+ }
- copy_v3_v3(vec, a);
+ copy_v3_v3(r_slide_vec, vec_accum);
return NULL;
}
-static void calcNonProportionalEdgeSlide(TransInfo *t, SlideData *sld, const float mval[2])
+static void calcNonProportionalEdgeSlide(TransInfo *t, EdgeSlideData *sld, const float mval[2])
{
- TransDataSlideVert *sv = sld->sv;
+ TransDataEdgeSlideVert *sv = sld->sv;
if (sld->totsv > 0) {
+ ARegion *ar = t->ar;
+ RegionView3D *rv3d = NULL;
+ float projectMat[4][4];
+
int i = 0;
- float v_proj[3];
+ float v_proj[2];
float dist = 0;
float min_dist = FLT_MAX;
+ if (t->spacetype == SPACE_VIEW3D) {
+ /* background mode support */
+ 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);
+ }
+
for (i = 0; i < sld->totsv; i++, sv++) {
/* Set length */
sv->edge_len = len_v3v3(sv->upvec, sv->downvec);
- mul_v3_m4v3(v_proj, t->obedit->obmat, sv->v->co);
- if (ED_view3d_project_float_global(t->ar, v_proj, v_proj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- dist = len_squared_v2v2(mval, v_proj);
- if (dist < min_dist) {
- min_dist = dist;
- sld->curr_sv_index = i;
- }
+ ED_view3d_project_float_v2_m4(ar, sv->v->co, v_proj, projectMat);
+ dist = len_squared_v2v2(mval, v_proj);
+ if (dist < min_dist) {
+ min_dist = dist;
+ sld->curr_sv_index = i;
}
}
}
@@ -4895,17 +5138,18 @@ static void calcNonProportionalEdgeSlide(TransInfo *t, SlideData *sld, const flo
}
}
-static int createSlideVerts(TransInfo *t)
+static int createEdgeSlideVerts(TransInfo *t)
{
BMEditMesh *em = BMEdit_FromObject(t->obedit);
BMesh *bm = em->bm;
BMIter iter;
BMEdge *e, *e1;
- BMVert *v, *v2, *first;
- TransDataSlideVert *sv_array;
- BMBVHTree *btree = BMBVH_NewBVH(em, BMBVH_RESPECT_HIDDEN, NULL, NULL);
+ BMVert *v, *v2;
+ TransDataEdgeSlideVert *sv_array;
+ int sv_tot;
+ BMBVHTree *btree;
SmallHash table;
- SlideData *sld = MEM_callocN(sizeof(*sld), "sld");
+ EdgeSlideData *sld = MEM_callocN(sizeof(*sld), "sld");
View3D *v3d = NULL;
RegionView3D *rv3d = NULL;
ARegion *ar = t->ar;
@@ -4915,6 +5159,7 @@ static int createSlideVerts(TransInfo *t)
float vec[3], vec2[3] /*, lastvec[3], size, dis=0.0, z */ /* UNUSED */;
float 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 */
@@ -4922,6 +5167,15 @@ static int createSlideVerts(TransInfo *t)
rv3d = t->ar ? t->ar->regiondata : NULL;
}
+ use_btree_disp = (v3d && t->obedit->dt > OB_WIRE && v3d->drawtype > OB_WIRE);
+
+ if (use_btree_disp) {
+ btree = BMBVH_NewBVH(em, BMBVH_RESPECT_HIDDEN, NULL, NULL);
+ }
+ else {
+ btree = NULL;
+ }
+
sld->is_proportional = TRUE;
sld->curr_sv_index = 0;
sld->flipped_vtx = FALSE;
@@ -4955,7 +5209,8 @@ static int createSlideVerts(TransInfo *t)
if (numsel == 0 || numsel > 2) {
MEM_freeN(sld);
- BMBVH_FreeBVH(btree);
+ if (btree)
+ BMBVH_FreeBVH(btree);
return 0; /* invalid edge selection */
}
}
@@ -4965,7 +5220,8 @@ static int createSlideVerts(TransInfo *t)
if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
if (!BM_edge_is_manifold(e)) {
MEM_freeN(sld);
- BMBVH_FreeBVH(btree);
+ if (btree)
+ BMBVH_FreeBVH(btree);
return 0; /* can only handle exactly 2 faces around each edge */
}
}
@@ -4985,16 +5241,18 @@ static int createSlideVerts(TransInfo *t)
if (!j) {
MEM_freeN(sld);
- BMBVH_FreeBVH(btree);
+ if (btree)
+ BMBVH_FreeBVH(btree);
return 0;
}
- sv_array = MEM_callocN(sizeof(TransDataSlideVert) * j, "sv_array");
+ sv_tot = j;
+ sv_array = MEM_callocN(sizeof(TransDataEdgeSlideVert) * sv_tot, "sv_array");
loop_nr = 0;
- j = 0;
while (1) {
BMLoop *l, *l1, *l2;
+ BMVert *v_first;
v = NULL;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
@@ -5009,7 +5267,7 @@ static int createSlideVerts(TransInfo *t)
if (!v->e)
continue;
- first = v;
+ v_first = v;
/*walk along the edge loop*/
e = v->e;
@@ -5029,7 +5287,7 @@ static int createSlideVerts(TransInfo *t)
break;
v = BM_edge_other_vert(e, v);
- } while (e != first->e);
+ } while (e != v_first->e);
BM_elem_flag_disable(v, BM_ELEM_TAG);
@@ -5049,10 +5307,13 @@ static int createSlideVerts(TransInfo *t)
}
/*iterate over the loop*/
- first = v;
+ v_first = v;
do {
- TransDataSlideVert *sv = sv_array + j;
+ TransDataEdgeSlideVert *sv;
+ /* XXX, 'sv' will initialize multiple times, this is suspicious. see [#34024] */
+ BLI_assert(BLI_smallhash_haskey(&table, (uintptr_t)v) != false);
+ sv = sv_array + GET_INT_FROM_POINTER(BLI_smallhash_lookup(&table, (uintptr_t)v));
sv->v = v;
sv->origvert = *v;
sv->loop_nr = loop_nr;
@@ -5074,9 +5335,8 @@ static int createSlideVerts(TransInfo *t)
e1 = e;
e = get_other_edge(v, e);
if (!e) {
- //v2=v, v = BM_edge_other_vert(l1->e, v);
-
- sv = sv_array + j + 1;
+ BLI_assert(BLI_smallhash_haskey(&table, (uintptr_t)v) != false);
+ sv = sv_array + GET_INT_FROM_POINTER(BLI_smallhash_lookup(&table, (uintptr_t)v));
sv->v = v;
sv->origvert = *v;
sv->loop_nr = loop_nr;
@@ -5093,19 +5353,22 @@ static int createSlideVerts(TransInfo *t)
BM_elem_flag_disable(v, BM_ELEM_TAG);
BM_elem_flag_disable(v2, BM_ELEM_TAG);
-
- j += 2;
+
break;
}
l1 = get_next_loop(v, l1, e1, e, vec);
l2 = l2 ? get_next_loop(v, l2, e1, e, vec2) : NULL;
- j += 1;
+ if (UNLIKELY(l1 == NULL && l2 != NULL)) {
+ l1 = l2;
+ l2 = NULL;
+ swap_v3_v3(vec, vec2);
+ }
BM_elem_flag_disable(v, BM_ELEM_TAG);
BM_elem_flag_disable(v2, BM_ELEM_TAG);
- } while (e != first->e && l1);
+ } while (e != v_first->e && l1);
loop_nr++;
}
@@ -5113,7 +5376,7 @@ static int createSlideVerts(TransInfo *t)
/* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */
sld->sv = sv_array;
- sld->totsv = j;
+ 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 */
@@ -5140,12 +5403,11 @@ static int createSlideVerts(TransInfo *t)
continue;
/* This test is only relevant if object is not wire-drawn! See [#32068]. */
- if (v3d && t->obedit->dt > OB_WIRE && v3d->drawtype > OB_WIRE &&
- !BMBVH_EdgeVisible(btree, e2, ar, v3d, t->obedit))
- {
+ if (use_btree_disp && !BMBVH_EdgeVisible(btree, e2, ar, v3d, t->obedit)) {
continue;
}
+ BLI_assert(BLI_smallhash_haskey(&table, (uintptr_t)v) != false);
j = GET_INT_FROM_POINTER(BLI_smallhash_lookup(&table, (uintptr_t)v));
if (sv_array[j].down) {
@@ -5216,14 +5478,14 @@ static int createSlideVerts(TransInfo *t)
if (dot_v3v3(loop_dir[l_nr], dir) < 0.0f) {
swap_v3_v3(sv_array->upvec, sv_array->downvec);
SWAP(BMVert, sv_array->vup, sv_array->vdown);
- SWAP(BMVert*, sv_array->up, sv_array->down);
+ SWAP(BMVert *, sv_array->up, sv_array->down);
}
}
if (rv3d)
calcNonProportionalEdgeSlide(t, sld, mval);
- sld->origfaces_init = TRUE;
+ sld->origfaces_init = true;
sld->em = em;
/*zero out start*/
@@ -5244,17 +5506,22 @@ static int createSlideVerts(TransInfo *t)
t->customData = sld;
BLI_smallhash_release(&table);
- BMBVH_FreeBVH(btree);
+ if (btree) {
+ BMBVH_FreeBVH(btree);
+ }
MEM_freeN(loop_dir);
MEM_freeN(loop_maxdist);
-
+
+ /* arrays are dirty from copying faces: EDBM_index_arrays_free */
+ EDBM_update_generic(em, FALSE, TRUE);
+
return 1;
}
-void projectSVData(TransInfo *t, int final)
+void projectEdgeSlideData(TransInfo *t, bool is_final)
{
- SlideData *sld = t->customData;
- TransDataSlideVert *sv;
+ EdgeSlideData *sld = t->customData;
+ TransDataEdgeSlideVert *sv;
BMEditMesh *em = sld->em;
SmallHash visit;
int i;
@@ -5356,7 +5623,8 @@ void projectSVData(TransInfo *t, int final)
f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)e_sel->l->f);
}
else if (BM_vert_in_face(e_sel->l->radial_next->f, sv->down)) {
- f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)e_sel->l->radial_next->f);
+ f_copy_flip = BLI_smallhash_lookup(&sld->origfaces,
+ (uintptr_t)e_sel->l->radial_next->f);
}
}
@@ -5365,7 +5633,8 @@ void projectSVData(TransInfo *t, int final)
f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)e_sel->l->f);
}
else if (BM_vert_in_face(e_sel->l->radial_next->f, sv->up)) {
- f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)e_sel->l->radial_next->f);
+ f_copy_flip = BLI_smallhash_lookup(&sld->origfaces,
+ (uintptr_t)e_sel->l->radial_next->f);
}
}
@@ -5373,7 +5642,7 @@ void projectSVData(TransInfo *t, int final)
}
}
-
+
if (!affected)
continue;
@@ -5381,7 +5650,7 @@ void projectSVData(TransInfo *t, int final)
* 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 (final) {
+ 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);
@@ -5405,7 +5674,7 @@ void projectSVData(TransInfo *t, int final)
BLI_smallhash_release(&visit);
}
-void freeSlideTempFaces(SlideData *sld)
+void freeEdgeSlideTempFaces(EdgeSlideData *sld)
{
if (sld->origfaces_init) {
SmallHashIter hiter;
@@ -5418,18 +5687,21 @@ void freeSlideTempFaces(SlideData *sld)
BLI_smallhash_release(&sld->origfaces);
- sld->origfaces_init = FALSE;
+ sld->origfaces_init = false;
+
+ /* arrays are dirty from removing faces: EDBM_index_arrays_free */
+ EDBM_update_generic(sld->em, FALSE, TRUE);
}
}
-void freeSlideVerts(TransInfo *t)
+void freeEdgeSlideVerts(TransInfo *t)
{
- SlideData *sld = t->customData;
+ EdgeSlideData *sld = t->customData;
#if 0 /*BMESH_TODO*/
if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
- TransDataSlideVert *sv;
+ TransDataEdgeSlideVert *sv;
LinkNode *look = sld->vertlist;
GHash *vertgh = sld->vhash;
while (look) {
@@ -5446,7 +5718,7 @@ void freeSlideVerts(TransInfo *t)
if (!sld)
return;
- freeSlideTempFaces(sld);
+ freeEdgeSlideTempFaces(sld);
bmesh_edit_end(sld->em->bm, BMO_OP_FLAG_UNTAN_MULTIRES);
@@ -5462,13 +5734,13 @@ void freeSlideVerts(TransInfo *t)
void initEdgeSlide(TransInfo *t)
{
- SlideData *sld;
+ EdgeSlideData *sld;
t->mode = TFM_EDGE_SLIDE;
t->transform = EdgeSlide;
t->handleEvent = handleEventEdgeSlide;
- if (!createSlideVerts(t)) {
+ if (!createEdgeSlideVerts(t)) {
t->state = TRANS_CANCEL;
return;
}
@@ -5478,11 +5750,11 @@ void initEdgeSlide(TransInfo *t)
if (!sld)
return;
- t->customFree = freeSlideVerts;
+ t->customFree = freeEdgeSlideVerts;
/* set custom point first if you want value to be initialized by init */
setCustomPoints(t, &t->mouse, sld->end, sld->start);
- initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO);
+ initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO_FLIP);
t->idx_max = 0;
t->num.idx_max = 0;
@@ -5495,10 +5767,10 @@ void initEdgeSlide(TransInfo *t)
t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
}
-int handleEventEdgeSlide(struct TransInfo *t, struct wmEvent *event)
+int handleEventEdgeSlide(struct TransInfo *t, const struct wmEvent *event)
{
if (t->mode == TFM_EDGE_SLIDE) {
- SlideData *sld = t->customData;
+ EdgeSlideData *sld = t->customData;
if (sld) {
switch (event->type) {
@@ -5541,17 +5813,17 @@ int handleEventEdgeSlide(struct TransInfo *t, struct wmEvent *event)
return 0;
}
-void drawNonPropEdge(const struct bContext *C, TransInfo *t)
+void drawEdgeSlide(const struct bContext *C, TransInfo *t)
{
if (t->mode == TFM_EDGE_SLIDE) {
- SlideData *sld = (SlideData *)t->customData;
+ EdgeSlideData *sld = (EdgeSlideData *)t->customData;
/* Non-Prop mode */
if (sld && sld->is_proportional == FALSE) {
View3D *v3d = CTX_wm_view3d(C);
float marker[3];
float v1[3], v2[3];
float interp_v;
- TransDataSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
+ TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f;
const float guide_size = ctrl_size - 0.5f;
const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f;
@@ -5617,8 +5889,8 @@ void drawNonPropEdge(const struct bContext *C, TransInfo *t)
static int doEdgeSlide(TransInfo *t, float perc)
{
- SlideData *sld = t->customData;
- TransDataSlideVert *svlist = sld->sv, *sv;
+ EdgeSlideData *sld = t->customData;
+ TransDataEdgeSlideVert *svlist = sld->sv, *sv;
int i;
sld->perc = perc;
@@ -5648,7 +5920,7 @@ static int doEdgeSlide(TransInfo *t, float perc)
* \note len_v3v3(curr_sv->upvec, curr_sv->downvec)
* is the same as the distance between the original vert locations, same goes for the lines below.
*/
- TransDataSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
+ TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
const float curr_length_perc = curr_sv->edge_len * (((sld->flipped_vtx ? perc : -perc) + 1.0f) / 2.0f);
float down_co[3];
@@ -5671,18 +5943,21 @@ static int doEdgeSlide(TransInfo *t, float perc)
}
}
- projectSVData(t, 0);
+ projectEdgeSlideData(t, 0);
return 1;
}
int EdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
{
- char str[128];
+ char str[MAX_INFO_LEN];
float final;
- SlideData *sld = t->customData;
- int flipped = sld->flipped_vtx;
- int is_proportional = sld->is_proportional;
+ EdgeSlideData *sld = t->customData;
+ bool flipped = sld->flipped_vtx;
+ bool is_proportional = sld->is_proportional;
+
+ const char *on_str = IFACE_("ON");
+ const char *off_str = IFACE_("OFF");
final = t->values[0];
@@ -5698,12 +5973,12 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
outputNumInput(&(t->num), c);
- BLI_snprintf(str, sizeof(str), "Edge Slide: %s (E)ven: %s, (F)lipped: %s",
- &c[0], !is_proportional ? "ON" : "OFF", flipped ? "ON" : "OFF");
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %s (E)ven: %s, (F)lipped: %s"),
+ &c[0], !is_proportional ? on_str : off_str, flipped ? on_str : off_str);
}
else {
- BLI_snprintf(str, sizeof(str), "Edge Slide: %.2f (E)ven: %s, (F)lipped: %s",
- final, !is_proportional ? "ON" : "OFF", flipped ? "ON" : "OFF");
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %.4f (E)ven: %s, (F)lipped: %s"),
+ final, !is_proportional ? on_str : off_str, flipped ? on_str : off_str);
}
CLAMP(final, -1.0f, 1.0f);
@@ -5711,10 +5986,524 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
t->values[0] = final;
/*do stuff here*/
- if (t->customData)
+ if (t->customData) {
doEdgeSlide(t, final);
+ }
+ else {
+ BLI_strncpy(str, IFACE_("Invalid Edge Selection"), MAX_INFO_LEN);
+ t->state = TRANS_CANCEL;
+ }
+
+ recalcData(t);
+
+ ED_area_headerprint(t->sa, str);
+
+ return 1;
+}
+
+
+/* ******************** Vert Slide *************** */
+static void calcVertSlideCustomPoints(struct TransInfo *t)
+{
+ VertSlideData *sld = t->customData;
+ TransDataVertSlideVert *sv = &sld->sv[sld->curr_sv_index];
+ float *co_orig = sv->co_orig_2d;
+ float *co_curr = sv->co_link_orig_2d[sv->co_link_curr];
+ const int start[2] = {co_orig[0], co_orig[1]};
+ const int end[2] = {co_curr[0], co_curr[1]};
+
+ if (sld->flipped_vtx && sld->is_proportional == false) {
+ setCustomPoints(t, &t->mouse, start, end);
+ }
+ else {
+ setCustomPoints(t, &t->mouse, end, start);
+ }
+}
+
+/**
+ * Run once when initializing vert slide to find the reference edge
+ */
+static void calcVertSlideMouseActiveVert(struct TransInfo *t, const int mval[2])
+{
+ VertSlideData *sld = t->customData;
+ float mval_fl[2] = {UNPACK2(mval)};
+ TransDataVertSlideVert *sv;
+
+ /* set the vertex to use as a reference for the mouse direction 'curr_sv_index' */
+ float dist = 0.0f;
+ float min_dist = FLT_MAX;
+ int i;
+
+ for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) {
+ dist = len_squared_v2v2(mval_fl, sv->co_orig_2d);
+ if (dist < min_dist) {
+ min_dist = dist;
+ 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 dir[2];
+ 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);
+
+ for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) {
+ if (sv->co_link_tot > 1) {
+ float dir_dot_best = -FLT_MAX;
+ int co_link_curr_best = -1;
+ int j;
+
+ for (j = 0; j < sv->co_link_tot; j++) {
+ float tdir[2];
+ 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);
+ if (dir_dot > dir_dot_best) {
+ dir_dot_best = dir_dot;
+ co_link_curr_best = j;
+ }
+ }
+
+ if (co_link_curr_best != -1) {
+ sv->co_link_curr = co_link_curr_best;
+ }
+ }
+ }
+}
+
+static int createVertSlideVerts(TransInfo *t)
+{
+ BMEditMesh *em = BMEdit_FromObject(t->obedit);
+ BMesh *bm = em->bm;
+ BMIter iter;
+ BMIter eiter;
+ BMEdge *e;
+ 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;
+ }
+
+ 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 {
- strcpy(str, "Invalid Edge Selection");
+ 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;
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT) && v->e) {
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ ok = true;
+ break;
+ }
+ }
+ }
+
+ if (ok) {
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ j += 1;
+ }
+ else {
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ }
+ }
+
+ if (!j) {
+ MEM_freeN(sld);
+ return 0;
+ }
+
+ sv_array = MEM_callocN(sizeof(TransDataVertSlideVert) * j, "sv_array");
+
+ j = 0;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ int k;
+ sv_array[j].v = v;
+ copy_v3_v3(sv_array[j].co_orig_3d, v->co);
+
+ k = 0;
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ k++;
+ }
+ }
+
+ 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;
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ 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++;
+ }
+ }
+
+ sld->sv = sv_array;
+ sld->totsv = j;
+
+ sld->em = em;
+
+ sld->perc = 0.0f;
+
+ t->customData = sld;
+
+ if (rv3d) {
+ calcVertSlideMouseActiveVert(t, t->mval);
+ calcVertSlideMouseActiveEdges(t, t->mval);
+ }
+
+ return 1;
+}
+
+void freeVertSlideVerts(TransInfo *t)
+{
+ VertSlideData *sld = t->customData;
+
+ if (!sld)
+ return;
+
+
+ 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);
+ }
+ }
+
+ MEM_freeN(sld->sv);
+ MEM_freeN(sld);
+
+ t->customData = NULL;
+
+ recalcData(t);
+}
+
+void initVertSlide(TransInfo *t)
+{
+ VertSlideData *sld;
+
+ t->mode = TFM_VERT_SLIDE;
+ t->transform = VertSlide;
+ t->handleEvent = handleEventVertSlide;
+
+ if (!createVertSlideVerts(t)) {
+ t->state = TRANS_CANCEL;
+ return;
+ }
+
+ sld = t->customData;
+
+ if (!sld)
+ return;
+
+ t->customFree = freeVertSlideVerts;
+
+ /* set custom point first if you want value to be initialized by init */
+ calcVertSlideCustomPoints(t);
+ initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO);
+
+ 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;
+
+ t->num.increment = t->snap[1];
+
+ t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
+}
+
+int handleEventVertSlide(struct TransInfo *t, const struct wmEvent *event)
+{
+ if (t->mode == TFM_VERT_SLIDE) {
+ VertSlideData *sld = t->customData;
+
+ if (sld) {
+ switch (event->type) {
+ case EKEY:
+ if (event->val == KM_PRESS) {
+ sld->is_proportional = !sld->is_proportional;
+ if (sld->flipped_vtx) {
+ calcVertSlideCustomPoints(t);
+ }
+ return 1;
+ }
+ break;
+ case FKEY:
+ {
+ if (event->val == KM_PRESS) {
+ sld->flipped_vtx = !sld->flipped_vtx;
+ calcVertSlideCustomPoints(t);
+ return 1;
+ }
+ break;
+ }
+ case CKEY:
+ {
+ /* use like a modifier key */
+ if (event->val == KM_PRESS) {
+ t->flag ^= T_ALT_TRANSFORM;
+ calcVertSlideCustomPoints(t);
+ return 1;
+ }
+ 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;
+ }
+ }
+ }
+#endif
+ case MOUSEMOVE:
+ {
+ /* don't recalculat the best edge */
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+ if (is_clamp) {
+ calcVertSlideMouseActiveEdges(t, event->mval);
+ }
+ calcVertSlideCustomPoints(t);
+ }
+ default:
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+static void drawVertSlide(const struct bContext *C, TransInfo *t)
+{
+ if (t->mode == TFM_VERT_SLIDE) {
+ VertSlideData *sld = (VertSlideData *)t->customData;
+ /* Non-Prop mode */
+ if (sld) {
+ View3D *v3d = CTX_wm_view3d(C);
+ 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 = -30;
+ const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
+ int i;
+
+ if (v3d && v3d->zbuf)
+ glDisable(GL_DEPTH_TEST);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT | GL_POINT_BIT);
+ glPushMatrix();
+
+ glMultMatrixf(t->obedit->obmat);
+
+ glLineWidth(line_size);
+ UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+ glBegin(GL_LINES);
+ if (is_clamp) {
+ sv = sld->sv;
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ glVertex3fv(sv->co_orig_3d);
+ glVertex3fv(sv->co_link_orig_3d[sv->co_link_curr]);
+ }
+ }
+ else {
+ sv = sld->sv;
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ float a[3], b[3];
+ sub_v3_v3v3(a, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d);
+ mul_v3_fl(a, 100.0f);
+ negate_v3_v3(b, a);
+ add_v3_v3(a, sv->co_orig_3d);
+ add_v3_v3(b, sv->co_orig_3d);
+
+ glVertex3fv(a);
+ glVertex3fv(b);
+ }
+ }
+ bglEnd();
+
+ glPointSize(ctrl_size);
+
+ bglBegin(GL_POINTS);
+ bglVertex3fv((sld->flipped_vtx && sld->is_proportional == FALSE) ?
+ curr_sv->co_link_orig_3d[curr_sv->co_link_curr] :
+ curr_sv->co_orig_3d);
+ bglEnd();
+
+ glPopMatrix();
+ glPopAttrib();
+
+ glDisable(GL_BLEND);
+
+ if (v3d && v3d->zbuf)
+ glEnable(GL_DEPTH_TEST);
+ }
+ }
+}
+
+static int doVertSlide(TransInfo *t, float perc)
+{
+ VertSlideData *sld = t->customData;
+ TransDataVertSlideVert *svlist = sld->sv, *sv;
+ int i;
+
+ sld->perc = perc;
+ sv = svlist;
+
+ if (sld->is_proportional == TRUE) {
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ interp_v3_v3v3(sv->v->co, sv->co_orig_3d, sv->co_link_orig_3d[sv->co_link_curr], perc);
+ }
+ }
+ else {
+ TransDataVertSlideVert *sv_curr = &sld->sv[sld->curr_sv_index];
+ const float edge_len_curr = len_v3v3(sv_curr->co_orig_3d, sv_curr->co_link_orig_3d[sv_curr->co_link_curr]);
+ const float tperc = perc * edge_len_curr;
+
+ for (i = 0; i < sld->totsv; i++, sv++) {
+ float edge_len;
+ float dir[3];
+
+ sub_v3_v3v3(dir, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d);
+ edge_len = normalize_v3(dir);
+
+ if (edge_len > FLT_EPSILON) {
+ if (sld->flipped_vtx) {
+ madd_v3_v3v3fl(sv->v->co, sv->co_link_orig_3d[sv->co_link_curr], dir, -tperc);
+ }
+ else {
+ madd_v3_v3v3fl(sv->v->co, sv->co_orig_3d, dir, tperc);
+ }
+ }
+ else {
+ copy_v3_v3(sv->v->co, sv->co_orig_3d);
+ }
+ }
+ }
+
+ return 1;
+}
+
+int VertSlide(TransInfo *t, const int UNUSED(mval[2]))
+{
+ char str[MAX_INFO_LEN];
+ size_t ofs = 0;
+ float final;
+ VertSlideData *sld = t->customData;
+ const bool flipped = sld->flipped_vtx;
+ const 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));
+
+ const char *on_str = IFACE_("ON");
+ const char *off_str = IFACE_("OFF");
+
+ final = t->values[0];
+
+ snapGrid(t, &final);
+
+ /* only do this so out of range values are not displayed */
+ if (is_constrained) {
+ CLAMP(final, 0.0f, 1.0f);
+ }
+
+ /* header string */
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Vert Slide: "), MAX_INFO_LEN - ofs);
+ if (hasNumInput(&t->num)) {
+ char c[NUM_STR_REP_LEN];
+ applyNumInput(&t->num, &final);
+ outputNumInput(&(t->num), c);
+ ofs += BLI_strncpy_rlen(str + ofs, &c[0], MAX_INFO_LEN - ofs);
+ }
+ else {
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "%.4f ", final);
+ }
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(E)ven: %s, "), !is_proportional ? on_str : off_str);
+ if (!is_proportional) {
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(F)lipped: %s, "), flipped ? on_str : off_str);
+ }
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Alt or (C)lamp: %s"), is_clamp ? on_str : off_str);
+ /* done with header string */
+
+ /*do stuff here*/
+ if (t->customData) {
+ doVertSlide(t, final);
+ }
+ else {
+ BLI_strncpy(str, IFACE_("Invalid Vert Selection"), MAX_INFO_LEN);
t->state = TRANS_CANCEL;
}
@@ -5725,6 +6514,7 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
return 1;
}
+
/* ******************** EditBone roll *************** */
void initBoneRoll(TransInfo *t)
@@ -5749,7 +6539,7 @@ int BoneRoll(TransInfo *t, const int UNUSED(mval[2]))
{
TransData *td = t->data;
int i;
- char str[50];
+ char str[MAX_INFO_LEN];
float final;
@@ -5764,12 +6554,12 @@ int BoneRoll(TransInfo *t, const int UNUSED(mval[2]))
outputNumInput(&(t->num), c);
- sprintf(str, "Roll: %s", &c[0]);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Roll: %s"), &c[0]);
final = DEG2RADF(final);
}
else {
- sprintf(str, "Roll: %.2f", RAD2DEGF(final));
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Roll: %.2f"), RAD2DEGF(final));
}
/* set roll values */
@@ -5811,7 +6601,7 @@ int BakeTime(TransInfo *t, const int mval[2])
TransData *td = t->data;
float time;
int i;
- char str[50];
+ char str[MAX_INFO_LEN];
float fac = 0.1f;
@@ -5835,16 +6625,16 @@ int BakeTime(TransInfo *t, const int mval[2])
outputNumInput(&(t->num), c);
if (time >= 0.0f)
- sprintf(str, "Time: +%s %s", c, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Time: +%s %s"), c, t->proptext);
else
- sprintf(str, "Time: %s %s", c, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Time: %s %s"), c, t->proptext);
}
else {
/* default header print */
if (time >= 0.0f)
- sprintf(str, "Time: +%.3f %s", time, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Time: +%.3f %s"), time, t->proptext);
else
- sprintf(str, "Time: %.3f %s", time, t->proptext);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Time: %.3f %s"), time, t->proptext);
}
for (i = 0; i < t->total; i++, td++) {
@@ -5886,7 +6676,7 @@ int Mirror(TransInfo *t, const int UNUSED(mval[2]))
TransData *td;
float size[3], mat[3][3];
int i;
- char str[200];
+ char str[MAX_INFO_LEN];
/*
* OPTIMIZATION:
@@ -5904,7 +6694,7 @@ int Mirror(TransInfo *t, const int UNUSED(mval[2]))
t->con.applySize(t, NULL, mat);
}
- sprintf(str, "Mirror%s", t->con.text);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Mirror%s"), t->con.text);
for (i = 0, td = t->data; i < t->total; i++, td++) {
if (td->flag & TD_NOACTION)
@@ -5938,9 +6728,9 @@ int Mirror(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
if (t->flag & T_2D_EDIT)
- ED_area_headerprint(t->sa, "Select a mirror axis (X, Y)");
+ ED_area_headerprint(t->sa, IFACE_("Select a mirror axis (X, Y)"));
else
- ED_area_headerprint(t->sa, "Select a mirror axis (X, Y, Z)");
+ ED_area_headerprint(t->sa, IFACE_("Select a mirror axis (X, Y, Z)"));
}
return 1;
@@ -5997,7 +6787,7 @@ int Align(TransInfo *t, const int UNUSED(mval[2]))
recalcData(t);
- ED_area_headerprint(t->sa, "Align");
+ ED_area_headerprint(t->sa, IFACE_("Align"));
return 1;
}
@@ -6021,18 +6811,29 @@ void initSeqSlide(TransInfo *t)
t->num.increment = t->snap[1];
}
+/* We assume str is MAX_INFO_LEN long. */
static void headerSeqSlide(TransInfo *t, float val[2], char *str)
{
char tvec[NUM_STR_REP_LEN * 3];
+ size_t ofs = 0;
if (hasNumInput(&t->num)) {
outputNumInput(&(t->num), tvec);
}
else {
- sprintf(&tvec[0], "%.0f, %.0f", val[0], val[1]);
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.0f, %.0f", val[0], val[1]);
}
- sprintf(str, "Sequence Slide: %s%s", &tvec[0], t->con.text);
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text);
+
+ {
+ 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 += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" or Alt) Expand to fit %s"),
+ (t->flag & T_ALT_TRANSFORM) ? IFACE_("ON") : IFACE_("OFF"));
}
static void applySeqSlide(TransInfo *t, float val[2])
@@ -6060,7 +6861,7 @@ static void applySeqSlide(TransInfo *t, float val[2])
int SeqSlide(TransInfo *t, const int UNUSED(mval[2]))
{
- char str[200];
+ char str[MAX_INFO_LEN];
if (t->con.mode & CON_APPLY) {
float pvec[3] = {0.0f, 0.0f, 0.0f};
@@ -6176,7 +6977,11 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, TransData2D *td2d,
#if 0 /* 'do_time' disabled for now */
const Scene *scene = t->scene;
- const short do_time = 0; //getAnimEdit_DrawTime(t); // NOTE: this works, but may be confusing behavior given the option's label, hence disabled
+#if 0 /* NOTE: this works, but may be confusing behavior given the option's label, hence disabled */
+ const short do_time = getAnimEdit_DrawTime(t);
+#else
+ const short do_time = 0;
+#endif
const double secf = FPS;
#endif
double val;
@@ -6264,6 +7069,7 @@ void initTimeTranslate(TransInfo *t)
t->num.increment = t->snap[1];
}
+/* We assume str is MAX_INFO_LEN long. */
static void headerTimeTranslate(TransInfo *t, char *str)
{
char tvec[NUM_STR_REP_LEN * 3];
@@ -6292,12 +7098,12 @@ static void headerTimeTranslate(TransInfo *t, char *str)
}
if (autosnap == SACTSNAP_FRAME)
- sprintf(&tvec[0], "%d.00 (%.4f)", (int)val, val);
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%d.00 (%.4f)", (int)val, val);
else
- sprintf(&tvec[0], "%.4f", val);
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val);
}
- sprintf(str, "DeltaX: %s", &tvec[0]);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("DeltaX: %s"), &tvec[0]);
}
static void applyTimeTranslate(TransInfo *t, float UNUSED(sval))
@@ -6361,7 +7167,7 @@ int TimeTranslate(TransInfo *t, const int mval[2])
{
View2D *v2d = (View2D *)t->view;
float cval[2], sval[2];
- char str[200];
+ 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]);
@@ -6419,6 +7225,7 @@ void initTimeSlide(TransInfo *t)
t->num.increment = t->snap[1];
}
+/* We assume str is MAX_INFO_LEN long. */
static void headerTimeSlide(TransInfo *t, float sval, char *str)
{
char tvec[NUM_STR_REP_LEN * 3];
@@ -6435,10 +7242,10 @@ static void headerTimeSlide(TransInfo *t, float sval, char *str)
val = 2.0f * (cval - sval) / (maxx - minx);
CLAMP(val, -1.0f, 1.0f);
- sprintf(&tvec[0], "%.4f", val);
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val);
}
- sprintf(str, "TimeSlide: %s", &tvec[0]);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("TimeSlide: %s"), &tvec[0]);
}
static void applyTimeSlide(TransInfo *t, float sval)
@@ -6494,7 +7301,7 @@ int TimeSlide(TransInfo *t, const int mval[2])
float cval[2], sval[2];
float minx = *((float *)(t->customData));
float maxx = *((float *)(t->customData) + 1);
- char str[200];
+ char str[MAX_INFO_LEN];
/* calculate mouse co-ordinates */
UI_view2d_region_to_view(v2d, mval[0], mval[1], &cval[0], &cval[1]);
@@ -6561,6 +7368,7 @@ void initTimeScale(TransInfo *t)
t->num.increment = t->snap[1];
}
+/* We assume str is MAX_INFO_LEN long. */
static void headerTimeScale(TransInfo *t, char *str)
{
char tvec[NUM_STR_REP_LEN * 3];
@@ -6568,9 +7376,9 @@ static void headerTimeScale(TransInfo *t, char *str)
if (hasNumInput(&t->num))
outputNumInput(&(t->num), tvec);
else
- sprintf(&tvec[0], "%.4f", t->values[0]);
+ BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", t->values[0]);
- sprintf(str, "ScaleX: %s", &tvec[0]);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("ScaleX: %s"), &tvec[0]);
}
static void applyTimeScale(TransInfo *t)
@@ -6615,7 +7423,7 @@ static void applyTimeScale(TransInfo *t)
int TimeScale(TransInfo *t, const int UNUSED(mval[2]))
{
- char str[200];
+ char str[MAX_INFO_LEN];
/* handle numeric-input stuff */
t->vec[0] = t->values[0];
@@ -6639,3 +7447,12 @@ void BIF_TransformSetUndo(const char *UNUSED(str))
// TRANSFORM_FIX_ME
//Trans.undostr = str;
}
+
+
+/* TODO, move to: transform_queries.c */
+bool checkUseLocalCenter_GraphEdit(TransInfo *t)
+{
+ return ((t->around == V3D_LOCAL) && !ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE));
+}
+
+#undef MAX_INFO_LEN
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 08fe1e7676b..a551ef5008e 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -35,6 +35,7 @@
#include "ED_transform.h"
#include "ED_numinput.h"
+#include "ED_view3d.h"
#include "DNA_listBase.h"
@@ -52,12 +53,7 @@ struct Object;
struct View3D;
struct ScrArea;
struct Scene;
-struct bPose;
struct bConstraint;
-struct BezTriple;
-struct wmOperatorType;
-struct wmOperator;
-struct wmWindowManager;
struct wmKeyMap;
struct wmKeyConfig;
struct bContext;
@@ -65,7 +61,6 @@ struct wmEvent;
struct wmTimer;
struct ARegion;
struct ReportList;
-struct SmallHash;
typedef struct TransSnapPoint {
struct TransSnapPoint *next, *prev;
@@ -108,15 +103,15 @@ typedef struct TransCon {
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 */
- void (*drawExtra)(struct TransInfo *);
+ void (*drawExtra)(struct TransInfo *t);
/* For constraints that needs to draw differently from the other
* uses this instead of the generic draw function */
- void (*applyVec)(struct TransInfo *, struct TransData *, float *, float *, float *);
+ void (*applyVec)(struct TransInfo *t, struct TransData *td, const float in[3], float out[3], float pvec[3]);
/* Apply function pointer for linear vectorial transformation */
/* The last three parameters are pointers to the in/out/printable vectors */
- void (*applySize)(struct TransInfo *, struct TransData *, float [3][3]);
+ void (*applySize)(struct TransInfo *t, struct TransData *td, float smat[3][3]);
/* Apply function pointer for size transformation */
- void (*applyRot)(struct TransInfo *, struct TransData *, float [3], float *);
+ void (*applyRot)(struct TransInfo *t, struct TransData *td, float vec[3], float *angle);
/* Apply function pointer for rotation transformation */
} TransCon;
@@ -143,6 +138,7 @@ typedef struct TransDataExtension {
* namely when a bone is in "NoLocal" or "Hinge" mode)... */
float r_smtx[3][3]; /* Invers of previous one. */
int rotOrder; /* rotation mode, as defined in eRotationModes (DNA_action_types.h) */
+ float oloc[3], orot[3], oquat[4], orotAxis[3], orotAngle; /* Original object transformation used for rigid bodies */
} TransDataExtension;
typedef struct TransData2D {
@@ -188,7 +184,7 @@ typedef struct TransDataNla {
struct LinkNode;
struct GHash;
-typedef struct TransDataSlideVert {
+typedef struct TransDataEdgeSlideVert {
struct BMVert vup, vdown;
struct BMVert origvert;
@@ -201,10 +197,10 @@ typedef struct TransDataSlideVert {
float upvec[3], downvec[3];
int loop_nr;
-} TransDataSlideVert;
+} TransDataEdgeSlideVert;
-typedef struct SlideData {
- TransDataSlideVert *sv;
+typedef struct EdgeSlideData {
+ TransDataEdgeSlideVert *sv;
int totsv;
struct SmallHash vhash;
@@ -214,15 +210,40 @@ typedef struct SlideData {
struct BMEditMesh *em;
/* flag that is set when origfaces is initialized */
- int origfaces_init;
+ bool origfaces_init;
float perc;
- int is_proportional;
- int flipped_vtx;
+ bool is_proportional;
+ bool flipped_vtx;
int curr_sv_index;
-} SlideData;
+} EdgeSlideData;
+
+
+typedef struct TransDataVertSlideVert {
+ BMVert *v;
+ float co_orig_3d[3];
+ float co_orig_2d[2];
+ float (*co_link_orig_3d)[3];
+ float (*co_link_orig_2d)[2];
+ int co_link_tot;
+ int co_link_curr;
+} TransDataVertSlideVert;
+
+typedef struct VertSlideData {
+ TransDataVertSlideVert *sv;
+ int totsv;
+
+ struct BMEditMesh *em;
+
+ float perc;
+
+ bool is_proportional;
+ bool flipped_vtx;
+
+ int curr_sv_index;
+} VertSlideData;
typedef struct TransData {
float dist; /* Distance needed to affect element (for Proportionnal Editing) */
@@ -246,8 +267,8 @@ typedef struct TransData {
} TransData;
typedef struct MouseInput {
- void (*apply)(struct TransInfo *, struct MouseInput *, const int [2], float [3]);
- void (*post)(struct TransInfo *, float [3]);
+ void (*apply)(struct TransInfo *t, struct MouseInput *mi, const int mval[2], float output[3]);
+ void (*post)(struct TransInfo *t, float values[3]);
int imval[2]; /* initial mouse position */
char precision;
@@ -267,7 +288,7 @@ typedef struct TransInfo {
float fac; /* factor for distance based transform */
int (*transform)(struct TransInfo *, const int *);
/* transform function pointer */
- int (*handleEvent)(struct TransInfo *, struct wmEvent *);
+ int (*handleEvent)(struct TransInfo *, const struct wmEvent *);
/* event handler function pointer RETURN 1 if redraw is needed */
int total; /* total number of transformed data */
TransData *data; /* transformed data (array) */
@@ -331,7 +352,9 @@ typedef struct TransInfo {
struct Scene *scene;
struct ToolSettings *settings;
struct wmTimer *animtimer;
+ struct wmKeyMap *keymap; /* so we can do lookups for header text */
int mval[2]; /* current mouse position */
+ float zfac; /* use for 3d view */
struct Object *obedit;
void *draw_handle_apply;
void *draw_handle_view;
@@ -452,26 +475,28 @@ typedef struct TransInfo {
#define POINT_INIT 4
#define MULTI_POINTS 8
-int initTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op, struct wmEvent *event, int mode);
+int initTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op, const struct wmEvent *event, int mode);
void saveTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op);
-int transformEvent(TransInfo *t, struct wmEvent *event);
+int transformEvent(TransInfo *t, const struct wmEvent *event);
void transformApply(struct bContext *C, TransInfo *t);
int transformEnd(struct bContext *C, TransInfo *t);
void setTransformViewMatrices(TransInfo *t);
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]);
+void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV3DProjTest flag);
void projectFloatView(TransInfo *t, const float vec[3], float adr[2]);
void applyAspectRatio(TransInfo *t, float *vec);
void removeAspectRatio(TransInfo *t, float *vec);
void initWarp(TransInfo *t);
-int handleEventWarp(TransInfo *t, struct wmEvent *event);
+int handleEventWarp(TransInfo *t, const struct wmEvent *event);
int Warp(TransInfo *t, const int mval[2]);
void initShear(TransInfo *t);
-int handleEventShear(TransInfo *t, struct wmEvent *event);
+int handleEventShear(TransInfo *t, const struct wmEvent *event);
int Shear(TransInfo *t, const int mval[2]);
void initResize(TransInfo *t);
@@ -508,7 +533,7 @@ void initPushPull(TransInfo *t);
int PushPull(TransInfo *t, const int mval[2]);
void initBevel(TransInfo *t);
-int handleEventBevel(TransInfo *t, struct wmEvent *event);
+int handleEventBevel(TransInfo *t, const struct wmEvent *event);
int Bevel(TransInfo *t, const int mval[2]);
void initBevelWeight(TransInfo *t);
@@ -527,9 +552,13 @@ void initBoneRoll(TransInfo *t);
int BoneRoll(TransInfo *t, const int mval[2]);
void initEdgeSlide(TransInfo *t);
-int handleEventEdgeSlide(TransInfo *t, struct wmEvent *event);
+int handleEventEdgeSlide(TransInfo *t, const struct wmEvent *event);
int EdgeSlide(TransInfo *t, const int mval[2]);
+void initVertSlide(TransInfo *t);
+int handleEventVertSlide(TransInfo *t, const struct wmEvent *event);
+int VertSlide(TransInfo *t, const int mval[2]);
+
void initTimeTranslate(TransInfo *t);
int TimeTranslate(TransInfo *t, const int mval[2]);
@@ -630,7 +659,7 @@ void initSnapping(struct TransInfo *t, struct wmOperator *op);
void applyProject(TransInfo *t);
void applySnapping(TransInfo *t, float *vec);
void resetSnapping(TransInfo *t);
-int handleSnapping(TransInfo *t, struct wmEvent *event);
+int handleSnapping(TransInfo *t, const struct wmEvent *event);
void drawSnapping(const struct bContext *C, TransInfo *t);
int usingSnappingNormal(TransInfo *t);
int validSnappingNormal(TransInfo *t);
@@ -653,27 +682,26 @@ typedef enum {
INPUT_HORIZONTAL_ABSOLUTE,
INPUT_VERTICAL_RATIO,
INPUT_VERTICAL_ABSOLUTE,
- INPUT_CUSTOM_RATIO
+ INPUT_CUSTOM_RATIO,
+ INPUT_CUSTOM_RATIO_FLIP
} MouseInputMode;
-void initMouseInput(TransInfo *t, MouseInput *mi, int center[2], int mval[2]);
+void initMouseInput(TransInfo *t, MouseInput *mi, const int center[2], const int mval[2]);
void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode);
-int handleMouseInput(struct TransInfo *t, struct MouseInput *mi, struct wmEvent *event);
+int handleMouseInput(struct TransInfo *t, struct MouseInput *mi, const struct wmEvent *event);
void applyMouseInput(struct TransInfo *t, struct MouseInput *mi, const int mval[2], float output[3]);
-void setCustomPoints(TransInfo *t, MouseInput *mi, int start[2], int end[2]);
-void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *, float [3]));
+void setCustomPoints(TransInfo *t, MouseInput *mi, const int start[2], const int end[2]);
+void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3]));
/*********************** Generics ********************************/
-int initTransInfo(struct bContext *C, TransInfo *t, struct wmOperator *op, struct wmEvent *event);
+int initTransInfo(struct bContext *C, TransInfo *t, struct wmOperator *op, const struct wmEvent *event);
void postTrans (struct bContext *C, TransInfo *t);
void resetTransRestrictions(TransInfo *t);
void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis, short options);
-void drawNonPropEdge(const struct bContext *C, TransInfo *t);
-
/* DRAWLINE options flags */
#define DRAWLIGHT 1
@@ -715,8 +743,14 @@ void applyTransformOrientation(const struct bContext *C, float mat[3][3], char *
int getTransformOrientation(const struct bContext *C, float normal[3], float plane[3], int activeOnly);
-void freeSlideTempFaces(SlideData *sld);
-void freeSlideVerts(TransInfo *t);
-void projectSVData(TransInfo *t, int final);
+void freeEdgeSlideTempFaces(EdgeSlideData *sld);
+void freeEdgeSlideVerts(TransInfo *t);
+void projectEdgeSlideData(TransInfo *t, bool is_final);
+
+void freeVertSlideVerts(TransInfo *t);
+
+
+/* TODO. transform_queries.c */
+bool checkUseLocalCenter_GraphEdit(TransInfo *t);
#endif
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 947bdf53bee..f3026205ea2 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -29,19 +29,17 @@
* \ingroup edtransform
*/
-
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#ifndef WIN32
-#include <unistd.h>
+# include <unistd.h>
#else
-#include <io.h>
+# include <io.h>
#endif
-
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -53,13 +51,15 @@
#include "BKE_context.h"
-#include "ED_image.h"
-#include "ED_view3d.h"
-
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"
+#include "ED_image.h"
+#include "ED_view3d.h"
+
+#include "BLF_translation.h"
+
#include "UI_resources.h"
#include "transform.h"
@@ -200,13 +200,14 @@ static void viewAxisCorrectCenter(TransInfo *t, float t_con_center[3])
}
}
-static void axisProjection(TransInfo *t, float axis[3], float in[3], float out[3])
+static void axisProjection(TransInfo *t, const float axis[3], const float in[3], float out[3])
{
float norm[3], vec[3], factor, angle;
float t_con_center[3];
- if (in[0] == 0.0f && in[1] == 0.0f && in[2] == 0.0f)
+ if (is_zero_v3(in)) {
return;
+ }
copy_v3_v3(t_con_center, t->con.center);
@@ -278,7 +279,7 @@ static void axisProjection(TransInfo *t, float axis[3], float in[3], float out[3
}
}
-static void planeProjection(TransInfo *t, float in[3], float out[3])
+static void planeProjection(TransInfo *t, const float in[3], float out[3])
{
float vec[3], factor, norm[3];
@@ -308,7 +309,7 @@ static void planeProjection(TransInfo *t, float in[3], float out[3])
*
*/
-static void applyAxisConstraintVec(TransInfo *t, TransData *td, float in[3], float out[3], float pvec[3])
+static void applyAxisConstraintVec(TransInfo *t, TransData *td, const float in[3], float out[3], float pvec[3])
{
copy_v3_v3(out, in);
if (!td && t->con.mode & CON_APPLY) {
@@ -351,7 +352,7 @@ static void applyAxisConstraintVec(TransInfo *t, TransData *td, float in[3], flo
* Further down, that vector is mapped to each data's space.
*/
-static void applyObjectConstraintVec(TransInfo *t, TransData *td, float in[3], float out[3], float pvec[3])
+static void applyObjectConstraintVec(TransInfo *t, TransData *td, const float in[3], float out[3], float pvec[3])
{
copy_v3_v3(out, in);
if (t->con.mode & CON_APPLY) {
@@ -597,24 +598,24 @@ void setUserConstraint(TransInfo *t, short orientation, int mode, const char fte
case V3D_MANIP_GLOBAL:
{
float mtx[3][3] = MAT3_UNITY;
- BLI_snprintf(text, sizeof(text), ftext, "global");
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("global"));
setConstraint(t, mtx, mode, text);
}
break;
case V3D_MANIP_LOCAL:
- BLI_snprintf(text, sizeof(text), ftext, "local");
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("local"));
setLocalConstraint(t, mode, text);
break;
case V3D_MANIP_NORMAL:
- BLI_snprintf(text, sizeof(text), ftext, "normal");
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("normal"));
setConstraint(t, t->spacemtx, mode, text);
break;
case V3D_MANIP_VIEW:
- BLI_snprintf(text, sizeof(text), ftext, "view");
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("view"));
setConstraint(t, t->spacemtx, mode, text);
break;
case V3D_MANIP_GIMBAL:
- BLI_snprintf(text, sizeof(text), ftext, "gimbal");
+ BLI_snprintf(text, sizeof(text), ftext, IFACE_("gimbal"));
setConstraint(t, t->spacemtx, mode, text);
break;
default: /* V3D_MANIP_CUSTOM */
@@ -864,11 +865,11 @@ static void setNearestAxis2d(TransInfo *t)
/* no correction needed... just use whichever one is lower */
if (abs(t->mval[0] - t->con.imval[0]) < abs(t->mval[1] - t->con.imval[1]) ) {
t->con.mode |= CON_AXIS1;
- BLI_snprintf(t->con.text, sizeof(t->con.text), " along Y axis");
+ BLI_strncpy(t->con.text, IFACE_(" along Y axis"), sizeof(t->con.text));
}
else {
t->con.mode |= CON_AXIS0;
- BLI_snprintf(t->con.text, sizeof(t->con.text), " along X axis");
+ BLI_strncpy(t->con.text, IFACE_(" along X axis"), sizeof(t->con.text));
}
}
@@ -889,9 +890,9 @@ static void setNearestAxis3d(TransInfo *t)
* and to overflow the short integers.
* The formula used is a bit stupid, just a simplification of the subtraction
* of two 2D points 30 pixels apart (that's the last factor in the formula) after
- * projecting them with window_to_3d_delta and then get the length of that vector.
+ * projecting them with ED_view3d_win_to_delta and then get the length of that vector.
*/
- zfac = t->persmat[0][3] * t->center[0] + t->persmat[1][3] * t->center[1] + t->persmat[2][3] * t->center[2] + t->persmat[3][3];
+ zfac = mul_project_m4_v3_zfac(t->persmat, t->center);
zfac = len_v3(t->persinv[0]) * 2.0f / t->ar->winx * zfac * 30.0f;
for (i = 0; i < 3; i++) {
@@ -919,31 +920,31 @@ static void setNearestAxis3d(TransInfo *t)
if (len[0] <= len[1] && len[0] <= len[2]) {
if (t->modifiers & MOD_CONSTRAINT_PLANE) {
t->con.mode |= (CON_AXIS1 | CON_AXIS2);
- BLI_snprintf(t->con.text, sizeof(t->con.text), " locking %s X axis", t->spacename);
+ BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s X axis"), t->spacename);
}
else {
t->con.mode |= CON_AXIS0;
- BLI_snprintf(t->con.text, sizeof(t->con.text), " along %s X axis", t->spacename);
+ BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s X axis"), t->spacename);
}
}
else if (len[1] <= len[0] && len[1] <= len[2]) {
if (t->modifiers & MOD_CONSTRAINT_PLANE) {
t->con.mode |= (CON_AXIS0 | CON_AXIS2);
- BLI_snprintf(t->con.text, sizeof(t->con.text), " locking %s Y axis", t->spacename);
+ BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s Y axis"), t->spacename);
}
else {
t->con.mode |= CON_AXIS1;
- BLI_snprintf(t->con.text, sizeof(t->con.text), " along %s Y axis", t->spacename);
+ BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s Y axis"), t->spacename);
}
}
else if (len[2] <= len[1] && len[2] <= len[0]) {
if (t->modifiers & MOD_CONSTRAINT_PLANE) {
t->con.mode |= (CON_AXIS0 | CON_AXIS1);
- BLI_snprintf(t->con.text, sizeof(t->con.text), " locking %s Z axis", t->spacename);
+ BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s Z axis"), t->spacename);
}
else {
t->con.mode |= CON_AXIS2;
- BLI_snprintf(t->con.text, sizeof(t->con.text), " along %s Z axis", t->spacename);
+ BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s Z axis"), t->spacename);
}
}
}
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 884ec03cc62..cf960c953c3 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -85,6 +85,7 @@
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_report.h"
+#include "BKE_rigidbody.h"
#include "BKE_scene.h"
#include "BKE_sequencer.h"
#include "BKE_tessmesh.h"
@@ -113,6 +114,7 @@
#include "WM_types.h"
#include "UI_view2d.h"
+#include "UI_interface.h"
#include "RNA_access.h"
@@ -121,35 +123,30 @@
#include "BLO_sys_types.h" // for intptr_t support
+
/* local function prototype - for Object/Bone Constraints */
static short constraints_list_needinv(TransInfo *t, ListBase *list);
/* ************************** Functions *************************** */
-static int trans_data_compare_dist(const void *A, const void *B)
+static int trans_data_compare_dist(const void *a, const void *b)
{
- const TransData *td_A = (const TransData*)A;
- const TransData *td_B = (const TransData*)B;
+ const TransData *td_a = (const TransData *)a;
+ const TransData *td_b = (const TransData *)b;
- if (td_A->dist < td_B->dist)
- return -1;
- else if (td_A->dist > td_B->dist)
- return 1;
-
- return 0;
+ if (td_a->dist < td_b->dist) return -1;
+ else if (td_a->dist > td_b->dist) return 1;
+ else return 0;
}
-static int trans_data_compare_rdist(const void *A, const void *B)
+static int trans_data_compare_rdist(const void *a, const void *b)
{
- const TransData *td_A = (const TransData*)A;
- const TransData *td_B = (const TransData*)B;
+ const TransData *td_a = (const TransData *)a;
+ const TransData *td_b = (const TransData *)b;
- if (td_A->rdist < td_B->rdist)
- return -1;
- else if (td_A->rdist > td_B->rdist)
- return 1;
-
- return 0;
+ if (td_a->rdist < td_b->rdist) return -1;
+ else if (td_a->rdist > td_b->rdist) return 1;
+ else return 0;
}
void sort_trans_data_dist(TransInfo *t)
@@ -226,7 +223,9 @@ static void set_prop_dist(TransInfo *t, short with_dist)
tob->rdist = dist;
}
}
- else break; // by definition transdata has selected items in beginning
+ else {
+ break; /* by definition transdata has selected items in beginning */
+ }
}
if (with_dist) {
tob->dist = tob->rdist;
@@ -271,7 +270,7 @@ static void createTransTexspace(TransInfo *t)
copy_m3_m4(td->mtx, ob->obmat);
copy_m3_m4(td->axismtx, ob->obmat);
normalize_m3(td->axismtx);
- invert_m3_m3(td->smtx, td->mtx);
+ pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
if (BKE_object_obdata_texspace_get(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
ob->dtx |= OB_TEXSPACE;
@@ -294,6 +293,7 @@ static void createTransEdge(TransInfo *t)
float mtx[3][3], smtx[3][3];
int count = 0, countsel = 0;
int propmode = t->flag & T_PROP_EDIT;
+ 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)) {
@@ -315,10 +315,24 @@ static void createTransEdge(TransInfo *t)
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransCrease");
copy_m3_m4(mtx, t->obedit->obmat);
- invert_m3_m3(smtx, mtx);
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
+
+ /* create data we need */
+ if (t->mode == TFM_BWEIGHT) {
+ BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(t->obedit), ME_CDFLAG_EDGE_BWEIGHT);
+ cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT);
+ }
+ else { //if (t->mode == TFM_CREASE) {
+ BLI_assert(t->mode == TFM_CREASE);
+ BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(t->obedit), ME_CDFLAG_EDGE_CREASE);
+ cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE);
+ }
+
+ 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)) {
+ float *fl_ptr;
/* need to set center for center calculations */
mid_v3_v3v3(td->center, eed->v1->co, eed->v2->co);
@@ -332,17 +346,10 @@ static void createTransEdge(TransInfo *t)
copy_m3_m3(td->mtx, mtx);
td->ext = NULL;
- if (t->mode == TFM_BWEIGHT) {
- float *bweight = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_BWEIGHT);
- td->val = bweight;
- td->ival = bweight ? *bweight : 1.0f;
- }
- else {
- float *crease = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE);
- BLI_assert(t->mode == TFM_CREASE);
- td->val = crease;
- td->ival = crease ? *crease : 0.0f;
- }
+
+ fl_ptr = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_float_offset);
+ td->val = fl_ptr;
+ td->ival = *fl_ptr;
td++;
}
@@ -552,7 +559,7 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr
invert_m3_m3(td->ext->r_smtx, td->ext->r_mtx);
}
- invert_m3_m3(td->smtx, td->mtx);
+ pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
/* exceptional case: rotate the pose bone which also applies transformation
* when a parentless bone has BONE_NO_LOCAL_LOCATION [] */
@@ -604,7 +611,7 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr
/* only object matrix correction */
copy_m3_m3(td->mtx, omat);
- invert_m3_m3(td->smtx, td->mtx);
+ pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON);
}
}
@@ -834,7 +841,7 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan)
}
}
- con = add_pose_constraint(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC);
+ con = BKE_add_pose_constraint(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC);
pchan->constflag |= (PCHAN_HAS_IK | PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
data = con->data;
if (targetless) {
@@ -1053,7 +1060,7 @@ static void createTransArmatureVerts(TransInfo *t)
if (!t->total) return;
copy_m3_m4(mtx, t->obedit->obmat);
- invert_m3_m3(smtx, mtx);
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransEditBone");
@@ -1221,7 +1228,7 @@ static void createTransMBallVerts(TransInfo *t)
tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "MetaElement_TransExtension");
copy_m3_m4(mtx, t->obedit->obmat);
- invert_m3_m3(smtx, mtx);
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
for (ml = mb->editelems->first; ml; ml = ml->next) {
if (propmode || (ml->flag & SELECT)) {
@@ -1286,7 +1293,7 @@ static void calc_distanceCurveVerts(TransData *head, TransData *tail)
}
}
else {
- td->dist = MAXFLOAT;
+ td->dist = FLT_MAX;
td->flag |= TD_NOTCONNECTED;
}
}
@@ -1378,7 +1385,7 @@ static void createTransCurveVerts(TransInfo *t)
t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Curve EditMode)");
copy_m3_m4(mtx, t->obedit->obmat);
- invert_m3_m3(smtx, mtx);
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
td = t->data;
for (nu = nurbs->first; nu; nu = nu->next) {
@@ -1569,7 +1576,7 @@ static void createTransLatticeVerts(TransInfo *t)
t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Lattice EditMode)");
copy_m3_m4(mtx, t->obedit->obmat);
- invert_m3_m3(smtx, mtx);
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
td = t->data;
bp = latt->def;
@@ -1852,7 +1859,7 @@ static void editmesh_set_connectivity_distance(BMEditMesh *em, float mtx[3][3],
}
/* loop-in-a-loop I know, but we need it! (ton) */
-static void get_face_center(float cent_r[3], BMVert *eve)
+static void get_face_center(float r_cent[3], BMVert *eve)
{
BMFace *efa;
@@ -1860,20 +1867,20 @@ static void get_face_center(float cent_r[3], BMVert *eve)
BM_ITER_ELEM (efa, &iter, eve, BM_FACES_OF_VERT) {
if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- BM_face_calc_center_mean(efa, cent_r);
+ BM_face_calc_center_mean(efa, r_cent);
break;
}
}
}
-static void get_edge_center(float cent_r[3], BMVert *eve)
+static void get_edge_center(float r_cent[3], BMVert *eve)
{
BMEdge *eed;
BMIter iter;
BM_ITER_ELEM (eed, &iter, eve, BM_EDGES_OF_VERT) {
if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
- mid_v3_v3v3(cent_r, eed->v1->co, eed->v2->co);
+ mid_v3_v3v3(r_cent, eed->v1->co, eed->v2->co);
break;
}
}
@@ -1912,8 +1919,8 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx
td->val = NULL;
td->extra = NULL;
if (t->mode == TFM_BWEIGHT) {
- td->val = bweight;
- td->ival = bweight ? *(bweight) : 1.0f;
+ td->val = bweight;
+ td->ival = *bweight;
}
else if (t->mode == TFM_SKIN_RESIZE) {
MVertSkin *vs = CustomData_bmesh_get(&em->bm->vdata,
@@ -1927,7 +1934,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(eve);
+ tx->isize[0] = BM_vert_calc_shell_factor_ex(eve, BM_ELEM_SELECT);
}
}
@@ -1949,6 +1956,7 @@ static void createTransEditVerts(TransInfo *t)
int mirror = 0;
char *selstate = NULL;
short selectmode = ts->selectmode;
+ int cd_vert_bweight_offset = -1;
if (t->flag & T_MIRROR) {
EDBM_verts_mirror_cache_begin(em, TRUE);
@@ -2030,6 +2038,10 @@ static void createTransEditVerts(TransInfo *t)
}
}
+ if (t->mode == TFM_BWEIGHT) {
+ BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(t->obedit), ME_CDFLAG_VERT_BWEIGHT);
+ cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
+ }
if (propmode) {
t->total = count;
@@ -2038,7 +2050,9 @@ static void createTransEditVerts(TransInfo *t)
if (propmode & T_PROP_CONNECTED)
dists = MEM_mallocN(em->bm->totvert * sizeof(float), "scratch nears");
}
- else t->total = countsel;
+ else {
+ t->total = countsel;
+ }
tob = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Mesh EditMode)");
if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) {
@@ -2051,7 +2065,9 @@ static void createTransEditVerts(TransInfo *t)
}
copy_m3_m4(mtx, t->obedit->obmat);
- invert_m3_m3(smtx, mtx);
+ /* we use a pseudoinverse so that when one of the axes is scaled to 0,
+ * matrix inversion still works and we can still moving along the other */
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
if (propmode & T_PROP_CONNECTED) {
editmesh_set_connectivity_distance(em, mtx, dists);
@@ -2094,11 +2110,10 @@ static void createTransEditVerts(TransInfo *t)
}
}
- eve = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL);
- for (a = 0; eve; eve = BM_iter_step(&iter), a++) {
+ BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
if (propmode || selstate[a]) {
- float *bweight = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_BWEIGHT);
+ float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL;
VertsToTransData(t, tob, tx, em, eve, bweight);
if (tx)
@@ -2116,7 +2131,7 @@ static void createTransEditVerts(TransInfo *t)
}
else {
tob->flag |= TD_NOTCONNECTED;
- tob->dist = MAXFLOAT;
+ tob->dist = FLT_MAX;
}
}
@@ -2195,7 +2210,12 @@ void flushTransNodes(TransInfo *t)
/* flush to 2d vector from internally used 3d vector */
for (a = 0, td = t->data, td2d = t->data2d; a < t->total; a++, td++, td2d++) {
bNode *node = td->extra;
- add_v2_v2v2(&node->locx, td2d->loc, td2d->ih1);
+ float vec[2];
+
+ /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */
+ add_v2_v2v2(vec, td2d->loc, td2d->ih1);
+ node->locx = vec[0] / UI_DPI_FAC;
+ node->locy = vec[1] / UI_DPI_FAC;
}
/* handle intersection with noodles */
@@ -2347,7 +2367,7 @@ static void UVsToTransData(SpaceImage *sima, TransData *td, TransData2D *td2d, f
td->dist = 0.0;
}
else {
- td->dist = MAXFLOAT;
+ td->dist = FLT_MAX;
}
unit_m3(td->mtx);
unit_m3(td->smtx);
@@ -2627,6 +2647,14 @@ static void createTransNlaData(bContext *C, TransInfo *t)
/* stop if trying to build list if nothing selected */
if (count == 0) {
+ /* clear temp metas that may have been created but aren't needed now
+ * because they fell on the wrong side of CFRA
+ */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ NlaTrack *nlt = (NlaTrack *)ale->data;
+ BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
+ }
+
/* cleanup temp list */
BLI_freelistN(&anim_data);
return;
@@ -2671,14 +2699,14 @@ static void createTransNlaData(bContext *C, TransInfo *t)
tdn->oldTrack = tdn->nlt = nlt;
tdn->strip = strip;
tdn->trackIndex = BLI_findindex(&adt->nla_tracks, nlt);
-
+
yval = (float)(tdn->trackIndex * NLACHANNEL_STEP(snla));
-
+
tdn->h1[0] = strip->start;
tdn->h1[1] = yval;
tdn->h2[0] = strip->end;
tdn->h2[1] = yval;
-
+
center[0] = (float)CFRA;
center[1] = yval;
center[2] = 0.0f;
@@ -3476,7 +3504,7 @@ static void bezt_to_transdata(TransData *td, TransData2D *td2d, AnimData *adt, B
td->dist = 0.0f;
}
else
- td->dist = MAXFLOAT;
+ td->dist = FLT_MAX;
if (ishandle)
td->flag |= TD_NOTIMESNAP;
@@ -3507,7 +3535,9 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
int count = 0, i;
float cfra;
float mtx[3][3], smtx[3][3];
- const short use_handle = !(sipo->flag & SIPO_NOHANDLES);
+ const bool use_handle = !(sipo->flag & SIPO_NOHANDLES);
+ const bool use_local_center = checkUseLocalCenter_GraphEdit(t);
+ const short anim_map_flag = ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS;
/* determine what type of data we are operating on */
if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -3558,7 +3588,9 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
if (ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE)) {
/* for 'normal' pivots - just include anything that is selected.
* this works a bit differently in translation modes */
- if (sel2) count++;
+ if (sel2) {
+ count++;
+ }
else {
if (sel1) count++;
if (sel3) count++;
@@ -3639,7 +3671,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
if (fcu->bezt == NULL)
continue;
- ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data, ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS);
+ ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data, anim_map_flag);
/* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse (if applicable) */
for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
@@ -3674,7 +3706,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
}
/* only include main vert if selected */
- if (sel2 && (sipo->around != V3D_LOCAL || ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE))) {
+ if (sel2 && (use_local_center == false)) {
/* move handles relative to center */
if (ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE)) {
@@ -3710,6 +3742,13 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
/* Sets handles based on the selection */
testhandles_fcurve(fcu, use_handle);
+
+ /* even though transform values are written back right after during transform,
+ * using individual center's with rotation means the center point wont
+ * be touched again see: [#34303] */
+ if (use_local_center) {
+ ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data, anim_map_flag | ANIM_UNITCONV_RESTORE);
+ }
}
/* cleanup temp list */
@@ -4082,7 +4121,7 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count
/* Meta's can only directly be moved between channels since they
* don't have their start and length set directly (children affect that)
* since this Meta is nested we don't need any of its data in fact.
- * calc_sequence() will update its settings when run on the toplevel meta */
+ * BKE_sequence_calc() will update its settings when run on the toplevel meta */
*flag = 0;
*count = 0;
*recursive = TRUE;
@@ -4260,8 +4299,8 @@ static void freeSeqData(TransInfo *t)
{
int overlap = 0;
+ seq_prev = NULL;
for (a = 0; a < t->total; a++, td++) {
- seq_prev = NULL;
seq = ((TransDataSeq *)td->extra)->seq;
if ((seq != seq_prev) && (seq->depth == 0) && (seq->flag & SEQ_OVERLAP)) {
overlap = 1;
@@ -4527,6 +4566,27 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
short constinv;
short skip_invert = 0;
+ if (t->mode != TFM_DUMMY && ob->rigidbody_object) {
+ float rot[3][3], scale[3];
+
+ /* save original object transform */
+ copy_v3_v3(td->ext->oloc, ob->loc);
+
+ if (ob->rotmode > 0) {
+ copy_v3_v3(td->ext->orot, ob->rot);
+ }
+ else if (ob->rotmode == ROT_MODE_AXISANGLE) {
+ td->ext->orotAngle = ob->rotAngle;
+ copy_v3_v3(td->ext->orotAxis, ob->rotAxis);
+ }
+ else {
+ copy_qt_qt(td->ext->oquat, ob->quat);
+ }
+ /* update object's loc/rot to get current rigid body transform */
+ mat4_to_loc_rot_size(ob->loc, rot, scale, ob->obmat);
+ BKE_object_mat3_to_rot(ob, rot, FALSE);
+ }
+
/* axismtx has the real orientation */
copy_m3_m4(td->axismtx, ob->obmat);
normalize_m3(td->axismtx);
@@ -4689,6 +4749,7 @@ 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 */
+ DAG_scene_relations_update(G.main, t->scene);
DAG_scene_flush_update(G.main, t->scene, -1, 0);
/* and we store them temporal in base (only used for transform code) */
@@ -4766,6 +4827,7 @@ 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);
DAG_scene_flush_update(G.main, t->scene, -1, 0);
/* and we store them temporal in base (only used for transform code) */
@@ -5080,25 +5142,25 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
if (canceled == 0) {
/* we need to delete the temporary faces before automerging */
if (t->mode == TFM_EDGE_SLIDE) {
- SlideData *sld = t->customData;
+ EdgeSlideData *sld = t->customData;
/* handle multires re-projection, done
* on transform completion since it's
* really slow -joeedh */
- projectSVData(t, TRUE);
+ projectEdgeSlideData(t, TRUE);
/* free temporary faces to avoid automerging and deleting
* during cleanup - psy-fi */
- freeSlideTempFaces(sld);
+ freeEdgeSlideTempFaces(sld);
}
- EDBM_automerge(t->scene, t->obedit, 1);
+ EDBM_automerge(t->scene, t->obedit, TRUE);
}
else {
if (t->mode == TFM_EDGE_SLIDE) {
- SlideData *sld = t->customData;
+ EdgeSlideData *sld = t->customData;
sld->perc = 0.0;
- projectSVData(t, FALSE);
+ projectEdgeSlideData(t, FALSE);
}
}
}
@@ -5480,6 +5542,9 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
if (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)
recalcObPaths = 1;
}
+ /* restore rigid body transform */
+ if (ob->rigidbody_object && canceled)
+ BKE_rigidbody_aftertrans_update(ob, td->ext->oloc, td->ext->orot, td->ext->oquat, td->ext->orotAxis, td->ext->orotAngle);
}
/* recalculate motion paths for objects (if necessary)
@@ -5592,7 +5657,8 @@ static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node)
/* hold original location */
float locxy[2] = {BLI_rctf_cent_x(&node->totr),
BLI_rctf_cent_y(&node->totr)};
-
+ float nodeloc[2];
+
copy_v2_v2(td2d->loc, locxy);
td2d->loc[2] = 0.0f;
td2d->loc2d = td2d->loc; /* current location */
@@ -5617,7 +5683,10 @@ static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node)
unit_m3(td->mtx);
unit_m3(td->smtx);
- sub_v2_v2v2(td2d->ih1, &node->locx, locxy);
+ /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */
+ nodeloc[0] = UI_DPI_FAC * node->locx;
+ nodeloc[1] = UI_DPI_FAC * node->locy;
+ sub_v2_v2v2(td2d->ih1, nodeloc, locxy);
td->extra = node;
}
@@ -5673,10 +5742,10 @@ static void createTransNodeData(bContext *UNUSED(C), TransInfo *t)
/* * motion tracking * */
-enum {
+enum transDataTracking_Mode {
transDataTracking_ModeTracks = 0,
- transDataTracking_ModeCurves = 1,
-} transDataTracking_Mode;
+ transDataTracking_ModeCurves = 1
+};
typedef struct TransDataTracking {
int mode, flag;
@@ -6531,7 +6600,7 @@ void createTransData(bContext *C, TransInfo *t)
sort_trans_data_dist(t);
}
}
- else if (ob && (ob->mode & (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT))) {
+ else if (ob && (ob->mode & (OB_MODE_ALL_PAINT))) {
/* sculpt mode and project paint have own undo stack
* transform ops redo clears sculpt/project undo stack.
*
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 615bb786071..2a3b0bc8726 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -56,11 +56,15 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "RNA_access.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "BIK_api.h"
+
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_armature.h"
@@ -128,6 +132,7 @@ void getViewVector(TransInfo *t, float coord[3], float vec[3])
/* ************************** GENERICS **************************** */
+
static void clipMirrorModifier(TransInfo *t, Object *ob)
{
ModifierData *md = ob->modifiers.first;
@@ -375,6 +380,8 @@ static void recalcData_graphedit(TransInfo *t)
bAnimListElem *ale;
int dosort = 0;
+
+ const bool use_local_center = checkUseLocalCenter_GraphEdit(t);
/* initialize relevant anim-context 'context' data from TransInfo data */
@@ -403,9 +410,10 @@ static void recalcData_graphedit(TransInfo *t)
/* ignore unselected fcurves */
if (!fcu_test_selected(fcu))
continue;
-
- // fixme: only do this for selected verts...
- ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data, ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS | ANIM_UNITCONV_RESTORE);
+
+ ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data,
+ ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS | ANIM_UNITCONV_RESTORE |
+ (use_local_center ? ANIM_UNITCONV_SKIPKNOTS : 0));
/* watch it: if the time is wrong: do not correct handles yet */
@@ -548,13 +556,20 @@ static void recalcData_nla(TransInfo *t)
break;
}
- /* use RNA to write the values... */
- // TODO: do we need to write in 2 passes to make sure that no truncation goes on?
+ /* Use RNA to write the values to ensure that constraints on these are obeyed
+ * (e.g. for transition strips, the values are taken from the neighbours)
+ *
+ * NOTE: we write these twice to avoid truncation errors which can arise when
+ * moving the strips a large distance using numeric input [#33852]
+ */
RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
+ RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
+ RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
+
/* flush transforms to child strips (since this should be a meta) */
BKE_nlameta_flush_transforms(strip);
@@ -796,6 +811,7 @@ static void recalcData_view3d(TransInfo *t)
if (td->extra) {
float vec[3], up_axis[3];
float qrot[4];
+ float roll;
ebo = td->extra;
copy_v3_v3(up_axis, td->axismtx[2]);
@@ -810,7 +826,9 @@ static void recalcData_view3d(TransInfo *t)
mul_m3_v3(t->mat, up_axis);
}
- ebo->roll = ED_rollBoneToVector(ebo, up_axis, FALSE);
+ /* roll has a tendency to flip in certain orientations - [#34283], [#33974] */
+ roll = ED_rollBoneToVector(ebo, up_axis, false);
+ ebo->roll = angle_compat_rad(roll, ebo->roll);
}
}
}
@@ -847,6 +865,8 @@ static void recalcData_view3d(TransInfo *t)
/* old optimize trick... this enforces to bypass the depgraph */
if (!(arm->flag & ARM_DELAYDEFORM)) {
DAG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */
+ /* transformation of pose may affect IK tree, make sure it is rebuilt */
+ BIK_clear_data(ob->pose);
}
else
BKE_pose_where_is(t->scene, ob);
@@ -992,7 +1012,7 @@ void resetTransRestrictions(TransInfo *t)
}
/* the *op can be NULL */
-int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
+int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event)
{
Scene *sce = CTX_data_scene(C);
ToolSettings *ts = CTX_data_tool_settings(C);
@@ -1445,7 +1465,7 @@ void calculateCenter2D(TransInfo *t)
void calculateCenterCursor(TransInfo *t)
{
- float *cursor;
+ const float *cursor;
cursor = give_cursor(t->scene, t->view);
copy_v3_v3(t->center, cursor);
@@ -1529,13 +1549,6 @@ void calculateCenterMedian(TransInfo *t)
total++;
}
}
- else {
- /*
- * All the selected elements are at the head of the array
- * which means we can stop when it finds unselected data
- */
- break;
- }
}
if (i)
mul_v3_fl(partial, 1.0f / total);
@@ -1555,13 +1568,6 @@ void calculateCenterBound(TransInfo *t)
if (!(t->data[i].flag & TD_NOCENTER))
minmax_v3v3_v3(min, max, t->data[i].center);
}
- else {
- /*
- * All the selected elements are at the head of the array
- * which means we can stop when it finds unselected data
- */
- break;
- }
}
else {
copy_v3_v3(max, t->data[i].center);
@@ -1663,7 +1669,7 @@ void calculateCenter(TransInfo *t)
projectIntView(t, axis, t->center2d);
- /* rotate only needs correct 2d center, grab needs initgrabz() value */
+ /* 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);
@@ -1673,18 +1679,16 @@ void calculateCenter(TransInfo *t)
}
if (t->spacetype == SPACE_VIEW3D) {
- /* initgrabz() defines a factor for perspective depth correction, used in window_to_3d_delta() */
+ /* ED_view3d_calc_zfac() defines a factor for perspective depth correction, used in ED_view3d_win_to_delta() */
+ float vec[3];
if (t->flag & (T_EDIT | T_POSE)) {
Object *ob = t->obedit ? t->obedit : t->poseobj;
- float vec[3];
-
- copy_v3_v3(vec, t->center);
- mul_m4_v3(ob->obmat, vec);
- initgrabz(t->ar->regiondata, vec[0], vec[1], vec[2]);
+ mul_v3_m4v3(vec, ob->obmat, t->center);
}
else {
- initgrabz(t->ar->regiondata, t->center[0], t->center[1], t->center[2]);
+ copy_v3_v3(vec, t->center);
}
+ t->zfac = ED_view3d_calc_zfac(t->ar->regiondata, vec, NULL);
}
}
@@ -1764,25 +1768,25 @@ void calculatePropRatio(TransInfo *t)
}
switch (t->prop_mode) {
case PROP_SHARP:
- strcpy(t->proptext, "(Sharp)");
+ strcpy(t->proptext, IFACE_("(Sharp)"));
break;
case PROP_SMOOTH:
- strcpy(t->proptext, "(Smooth)");
+ strcpy(t->proptext, IFACE_("(Smooth)"));
break;
case PROP_ROOT:
- strcpy(t->proptext, "(Root)");
+ strcpy(t->proptext, IFACE_("(Root)"));
break;
case PROP_LIN:
- strcpy(t->proptext, "(Linear)");
+ strcpy(t->proptext, IFACE_("(Linear)"));
break;
case PROP_CONST:
- strcpy(t->proptext, "(Constant)");
+ strcpy(t->proptext, IFACE_("(Constant)"));
break;
case PROP_SPHERE:
- strcpy(t->proptext, "(Sphere)");
+ strcpy(t->proptext, IFACE_("(Sphere)"));
break;
case PROP_RANDOM:
- strcpy(t->proptext, "(Random)");
+ strcpy(t->proptext, IFACE_("(Random)"));
break;
default:
t->proptext[0] = '\0';
diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c
index 7e05fdae364..4943a3a2fe7 100644
--- a/source/blender/editors/transform/transform_input.c
+++ b/source/blender/editors/transform/transform_input.c
@@ -164,7 +164,7 @@ static void InputVerticalAbsolute(TransInfo *t, MouseInput *mi, const int mval[2
output[0] = dot_v3v3(t->viewinv[1], vec) * 2.0f;
}
-void setCustomPoints(TransInfo *UNUSED(t), MouseInput *mi, int start[2], int end[2])
+void setCustomPoints(TransInfo *UNUSED(t), MouseInput *mi, const int start[2], const int end[2])
{
int *data;
@@ -180,7 +180,7 @@ void setCustomPoints(TransInfo *UNUSED(t), MouseInput *mi, int start[2], int end
data[3] = end[1];
}
-static void InputCustomRatio(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2], float output[3])
+static void InputCustomRatioFlip(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2], float output[3])
{
double length;
double distance;
@@ -213,6 +213,12 @@ static void InputCustomRatio(TransInfo *UNUSED(t), MouseInput *mi, const int mva
}
}
+static void InputCustomRatio(TransInfo *t, MouseInput *mi, const int mval[2], float output[3])
+{
+ InputCustomRatioFlip(t, mi, mval, output);
+ output[0] = -output[0];
+}
+
static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2], float output[3])
{
double dx2 = mval[0] - mi->center[0];
@@ -232,7 +238,7 @@ static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2],
double deler = (((dx1 * dx1 + dy1 * dy1) +
(dx2 * dx2 + dy2 * dy2) -
(dx3 * dx3 + dy3 * dy3)) / (2.0 * ((A * B) ? (A * B) : 1.0)));
- /* ((A*B)?(A*B):1.0) this takes care of potential divide by zero errors */
+ /* ((A * B) ? (A * B) : 1.0) this takes care of potential divide by zero errors */
float dphi;
@@ -275,7 +281,7 @@ static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2],
output[0] = *angle;
}
-void initMouseInput(TransInfo *UNUSED(t), MouseInput *mi, int center[2], int mval[2])
+void initMouseInput(TransInfo *UNUSED(t), MouseInput *mi, const int center[2], const int mval[2])
{
mi->factor = 0;
mi->precision = 0;
@@ -301,15 +307,8 @@ static void calcSpringFactor(MouseInput *mi)
void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
{
- /* may have been allocated previously */
- /* TODO, holding R-key can cause mem leak, but this causes [#28903]
- * disable for now. */
-#if 0
- if (mi->data) {
- MEM_freeN(mi->data);
- mi->data = NULL;
- }
-#endif
+ /* incase we allocate a new value */
+ void *mi_data_prev = mi->data;
switch (mode) {
case INPUT_VECTOR:
@@ -358,17 +357,27 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
mi->apply = InputCustomRatio;
t->helpline = HLP_NONE;
break;
+ case INPUT_CUSTOM_RATIO_FLIP:
+ mi->apply = InputCustomRatioFlip;
+ t->helpline = HLP_NONE;
+ break;
case INPUT_NONE:
default:
mi->apply = NULL;
break;
}
+ /* if we've allocated new data, free the old data
+ * less hassle then checking before every alloc above */
+ if (mi_data_prev && (mi_data_prev != mi->data)) {
+ MEM_freeN(mi_data_prev);
+ }
+
/* bootstrap mouse input with initial values */
applyMouseInput(t, mi, mi->imval, t->values);
}
-void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *, float[3]))
+void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3]))
{
mi->post = post;
}
@@ -384,7 +393,7 @@ void applyMouseInput(TransInfo *t, MouseInput *mi, const int mval[2], float outp
}
}
-int handleMouseInput(TransInfo *t, MouseInput *mi, wmEvent *event)
+int handleMouseInput(TransInfo *t, MouseInput *mi, const wmEvent *event)
{
int redraw = TREDRAW_NOTHING;
@@ -397,12 +406,13 @@ int handleMouseInput(TransInfo *t, MouseInput *mi, wmEvent *event)
* store the mouse position where the normal movement ended */
copy_v2_v2_int(mi->precision_mval, event->mval);
mi->precision = 1;
+ redraw = TREDRAW_HARD;
}
- else {
+ else if (event->val == KM_RELEASE) {
t->modifiers &= ~MOD_PRECISION;
mi->precision = 0;
+ redraw = TREDRAW_HARD;
}
- redraw = TREDRAW_HARD;
break;
}
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index 757fdfa2445..bea1f9da057 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -148,10 +148,8 @@ static void stats_pose(Scene *scene, RegionView3D *rv3d, bPoseChannel *pchan)
Bone *bone = pchan->bone;
if (bone) {
- if (bone->flag & BONE_TRANSFORM) {
- calc_tw_center(scene, pchan->pose_head);
- protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag);
- }
+ calc_tw_center(scene, pchan->pose_head);
+ protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag);
}
}
@@ -361,18 +359,35 @@ int calc_manipulator_stats(const bContext *C)
else if (obedit->type == OB_ARMATURE) {
bArmature *arm = obedit->data;
EditBone *ebo;
- for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
- if (EBONE_VISIBLE(arm, ebo)) {
- if (ebo->flag & BONE_TIPSEL) {
- calc_tw_center(scene, ebo->tail);
- totsel++;
- }
- if (ebo->flag & BONE_ROOTSEL) {
- calc_tw_center(scene, ebo->head);
- totsel++;
- }
- if (ebo->flag & BONE_SELECTED) {
- stats_editbone(rv3d, ebo);
+
+ if ((v3d->around == V3D_ACTIVE) && (ebo = arm->act_edbone)) {
+ /* doesn't check selection or visibility intentionally */
+ if (ebo->flag & BONE_TIPSEL) {
+ calc_tw_center(scene, ebo->tail);
+ totsel++;
+ }
+ if ((ebo->flag & BONE_ROOTSEL) ||
+ ((ebo->flag & BONE_TIPSEL) == FALSE)) /* ensure we get at least one point */
+ {
+ calc_tw_center(scene, ebo->head);
+ totsel++;
+ }
+ stats_editbone(rv3d, ebo);
+ }
+ else {
+ for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ if (EBONE_VISIBLE(arm, ebo)) {
+ if (ebo->flag & BONE_TIPSEL) {
+ calc_tw_center(scene, ebo->tail);
+ totsel++;
+ }
+ if (ebo->flag & BONE_ROOTSEL) {
+ calc_tw_center(scene, ebo->head);
+ totsel++;
+ }
+ if (ebo->flag & BONE_SELECTED) {
+ stats_editbone(rv3d, ebo);
+ }
}
}
}
@@ -480,17 +495,35 @@ int calc_manipulator_stats(const bContext *C)
else if (ob && (ob->mode & OB_MODE_POSE)) {
bPoseChannel *pchan;
int mode = TFM_ROTATION; // mislead counting bones... bah. We don't know the manipulator mode, could be mixed
+ int ok = FALSE;
if ((ob->lay & v3d->lay) == 0) return 0;
- totsel = count_set_pose_transflags(&mode, 0, ob);
-
- if (totsel) {
- /* use channels to get stats */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if ((v3d->around == V3D_ACTIVE) && (pchan = BKE_pose_channel_active(ob))) {
+ /* doesn't check selection or visibility intentionally */
+ Bone *bone = pchan->bone;
+ if (bone) {
stats_pose(scene, rv3d, pchan);
+ totsel = 1;
+ ok = TRUE;
+ }
+ }
+ else {
+ totsel = count_set_pose_transflags(&mode, 0, ob);
+
+ if (totsel) {
+ /* use channels to get stats */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ Bone *bone = pchan->bone;
+ if (bone && (bone->flag & BONE_TRANSFORM)) {
+ stats_pose(scene, rv3d, pchan);
+ }
+ }
+ ok = TRUE;
}
+ }
+ if (ok) {
mul_v3_fl(scene->twcent, 1.0f / (float)totsel); // centroid!
mul_m4_v3(ob->obmat, scene->twcent);
mul_m4_v3(ob->obmat, scene->twmin);
@@ -552,8 +585,9 @@ int calc_manipulator_stats(const bContext *C)
switch (v3d->twmode) {
case V3D_MANIP_GLOBAL:
+ {
break; /* nothing to do */
-
+ }
case V3D_MANIP_GIMBAL:
{
float mat[3][3];
@@ -562,28 +596,43 @@ int calc_manipulator_stats(const bContext *C)
break;
}
/* if not gimbal, fall through to normal */
+ /* pass through */
}
case V3D_MANIP_NORMAL:
+ {
if (obedit || ob->mode & OB_MODE_POSE) {
float mat[3][3];
ED_getTransformOrientationMatrix(C, mat, (v3d->around == V3D_ACTIVE));
copy_m4_m3(rv3d->twmat, mat);
break;
}
- /* no break we define 'normal' as 'local' in Object mode */
+ /* no break we define 'normal' as 'local' in Object mode */
+ /* pass through */
+ }
case V3D_MANIP_LOCAL:
+ {
+ if (ob->mode & OB_MODE_POSE) {
+ /* each bone moves on its own local axis, but to avoid confusion,
+ * use the active pones axis for display [#33575], this works as expected on a single bone
+ * 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));
+ copy_m4_m3(rv3d->twmat, mat);
+ break;
+ }
copy_m4_m4(rv3d->twmat, ob->obmat);
normalize_m4(rv3d->twmat);
break;
-
+ }
case V3D_MANIP_VIEW:
{
float mat[3][3];
copy_m3_m4(mat, rv3d->viewinv);
normalize_m3(mat);
copy_m4_m3(rv3d->twmat, mat);
+ break;
}
- break;
default: /* V3D_MANIP_CUSTOM */
{
float mat[3][3];
@@ -685,8 +734,8 @@ static void partial_doughnut(float radring, float radhole, int start, int end, i
float cos_phi, sin_phi, dist;
phi += side_delta;
- cos_phi = (float)cos(phi);
- sin_phi = (float)sin(phi);
+ cos_phi = cosf(phi);
+ sin_phi = sinf(phi);
dist = radhole + radring * cos_phi;
glVertex3f(cos_theta1 * dist, -sin_theta1 * dist, radring * sin_phi);
@@ -700,8 +749,8 @@ static void partial_doughnut(float radring, float radhole, int start, int end, i
float cos_phi, sin_phi, dist;
phi += side_delta;
- cos_phi = (float)cos(phi);
- sin_phi = (float)sin(phi);
+ cos_phi = cosf(phi);
+ sin_phi = sinf(phi);
dist = radhole + radring * cos_phi;
glVertex3f(cos_theta1 * dist, -sin_theta1 * dist, radring * sin_phi);
@@ -792,37 +841,89 @@ static void manipulator_setcolor(View3D *v3d, char axis, int colcode, unsigned c
glColor4ubv(col);
}
-/* viewmatrix should have been set OK, also no shademode! */
-static void draw_manipulator_axes(View3D *v3d, RegionView3D *rv3d, int colcode, int flagx, int flagy, int flagz)
+static void axis_sort_v3(const float axis_values[3], int r_axis_order[3])
{
+ float v[3];
+ copy_v3_v3(v, axis_values);
- /* axes */
- if (flagx) {
- manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->twangle[0]));
- if (flagx & MAN_SCALE_X) glLoadName(MAN_SCALE_X);
- else if (flagx & MAN_TRANS_X) glLoadName(MAN_TRANS_X);
- glBegin(GL_LINES);
- glVertex3f(0.2f, 0.0f, 0.0f);
- glVertex3f(1.0f, 0.0f, 0.0f);
- glEnd();
+#define SWAP_AXIS(a, b) { \
+ SWAP(float, v[a], v[b]); \
+ SWAP(int, r_axis_order[a], r_axis_order[b]); \
+} (void)0
+
+ if (v[0] < v[1]) {
+ if (v[2] < v[0]) { SWAP_AXIS(0, 2); }
}
- if (flagy) {
- if (flagy & MAN_SCALE_Y) glLoadName(MAN_SCALE_Y);
- else if (flagy & MAN_TRANS_Y) glLoadName(MAN_TRANS_Y);
- manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->twangle[1]));
- glBegin(GL_LINES);
- glVertex3f(0.0f, 0.2f, 0.0f);
- glVertex3f(0.0f, 1.0f, 0.0f);
- glEnd();
+ else {
+ if (v[1] < v[2]) { SWAP_AXIS(0, 1); }
+ else { SWAP_AXIS(0, 2); }
+ }
+ if (v[2] < v[1]) { SWAP_AXIS(1, 2); }
+
+#undef SWAP_AXIS
+}
+static void manipulator_axis_order(RegionView3D *rv3d, int r_axis_order[3])
+{
+ float axis_values[3];
+ float vec[3];
+
+ ED_view3d_global_to_vector(rv3d, rv3d->twmat[3], vec);
+
+ axis_values[0] = -dot_v3v3(rv3d->twmat[0], vec);
+ axis_values[1] = -dot_v3v3(rv3d->twmat[1], vec);
+ axis_values[2] = -dot_v3v3(rv3d->twmat[2], vec);
+
+ axis_sort_v3(axis_values, r_axis_order);
+}
+
+/* viewmatrix should have been set OK, also no shademode! */
+static void draw_manipulator_axes_single(View3D *v3d, RegionView3D *rv3d, int colcode,
+ int flagx, int flagy, int flagz, int axis)
+{
+ switch (axis) {
+ case 0:
+ /* axes */
+ if (flagx) {
+ manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->twangle[0]));
+ if (flagx & MAN_SCALE_X) glLoadName(MAN_SCALE_X);
+ else if (flagx & MAN_TRANS_X) glLoadName(MAN_TRANS_X);
+ glBegin(GL_LINES);
+ glVertex3f(0.2f, 0.0f, 0.0f);
+ glVertex3f(1.0f, 0.0f, 0.0f);
+ glEnd();
+ }
+ break;
+ case 1:
+ if (flagy) {
+ if (flagy & MAN_SCALE_Y) glLoadName(MAN_SCALE_Y);
+ else if (flagy & MAN_TRANS_Y) glLoadName(MAN_TRANS_Y);
+ manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->twangle[1]));
+ glBegin(GL_LINES);
+ glVertex3f(0.0f, 0.2f, 0.0f);
+ glVertex3f(0.0f, 1.0f, 0.0f);
+ glEnd();
+ }
+ break;
+ case 2:
+ if (flagz) {
+ if (flagz & MAN_SCALE_Z) glLoadName(MAN_SCALE_Z);
+ else if (flagz & MAN_TRANS_Z) glLoadName(MAN_TRANS_Z);
+ manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->twangle[2]));
+ glBegin(GL_LINES);
+ glVertex3f(0.0f, 0.0f, 0.2f);
+ glVertex3f(0.0f, 0.0f, 1.0f);
+ glEnd();
+ }
+ break;
}
- if (flagz) {
- if (flagz & MAN_SCALE_Z) glLoadName(MAN_SCALE_Z);
- else if (flagz & MAN_TRANS_Z) glLoadName(MAN_TRANS_Z);
- manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->twangle[2]));
- glBegin(GL_LINES);
- glVertex3f(0.0f, 0.0f, 0.2f);
- glVertex3f(0.0f, 0.0f, 1.0f);
- glEnd();
+}
+static void draw_manipulator_axes(View3D *v3d, RegionView3D *rv3d, int colcode,
+ int flagx, int flagy, int flagz,
+ const int axis_order[3])
+{
+ int i;
+ for (i = 0; i < 3; i++) {
+ draw_manipulator_axes_single(v3d, rv3d, colcode, flagx, flagy, flagz, axis_order[i]);
}
}
@@ -1165,10 +1266,14 @@ static void draw_manipulator_scale(View3D *v3d, RegionView3D *rv3d, int moving,
{
float cywid = 0.25f * 0.01f * (float)U.tw_handlesize;
float cusize = cywid * 0.75f, dz;
+ int axis_order[3] = {2, 0, 1};
+ int i;
/* when called while moving in mixed mode, do not draw when... */
if ((drawflags & MAN_SCALE_C) == 0) return;
+ manipulator_axis_order(rv3d, axis_order);
+
glDisable(GL_DEPTH_TEST);
/* not in combo mode */
@@ -1188,7 +1293,9 @@ static void draw_manipulator_scale(View3D *v3d, RegionView3D *rv3d, int moving,
dz = 1.0;
}
- else dz = 1.0f - 4.0f * cusize;
+ else {
+ dz = 1.0f - 4.0f * cusize;
+ }
if (moving) {
float matt[4][4];
@@ -1206,28 +1313,41 @@ static void draw_manipulator_scale(View3D *v3d, RegionView3D *rv3d, int moving,
/* axis */
/* in combo mode, this is always drawn as first type */
- draw_manipulator_axes(v3d, rv3d, colcode, drawflags & MAN_SCALE_X, drawflags & MAN_SCALE_Y, drawflags & MAN_SCALE_Z);
-
- /* Z cube */
- glTranslatef(0.0, 0.0, dz);
- if (drawflags & MAN_SCALE_Z) {
- if (G.f & G_PICKSEL) glLoadName(MAN_SCALE_Z);
- manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->twangle[2]));
- drawsolidcube(cusize);
- }
- /* X cube */
- glTranslatef(dz, 0.0, -dz);
- if (drawflags & MAN_SCALE_X) {
- if (G.f & G_PICKSEL) glLoadName(MAN_SCALE_X);
- manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->twangle[0]));
- drawsolidcube(cusize);
- }
- /* Y cube */
- glTranslatef(-dz, dz, 0.0);
- if (drawflags & MAN_SCALE_Y) {
- if (G.f & G_PICKSEL) glLoadName(MAN_SCALE_Y);
- manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->twangle[1]));
- drawsolidcube(cusize);
+ draw_manipulator_axes(v3d, rv3d, colcode,
+ drawflags & MAN_SCALE_X, drawflags & MAN_SCALE_Y, drawflags & MAN_SCALE_Z,
+ axis_order);
+
+
+ for (i = 0; i < 3; i++) {
+ switch (axis_order[i]) {
+ case 0: /* X cube */
+ if (drawflags & MAN_SCALE_X) {
+ glTranslatef(dz, 0.0, 0.0);
+ if (G.f & G_PICKSEL) glLoadName(MAN_SCALE_X);
+ manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->twangle[0]));
+ drawsolidcube(cusize);
+ glTranslatef(-dz, 0.0, 0.0);
+ }
+ break;
+ case 1: /* Y cube */
+ if (drawflags & MAN_SCALE_Y) {
+ glTranslatef(0.0, dz, 0.0);
+ if (G.f & G_PICKSEL) glLoadName(MAN_SCALE_Y);
+ manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->twangle[1]));
+ drawsolidcube(cusize);
+ glTranslatef(0.0, -dz, 0.0);
+ }
+ break;
+ case 2: /* Z cube */
+ if (drawflags & MAN_SCALE_Z) {
+ glTranslatef(0.0, 0.0, dz);
+ if (G.f & G_PICKSEL) glLoadName(MAN_SCALE_Z);
+ manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->twangle[2]));
+ drawsolidcube(cusize);
+ glTranslatef(0.0, 0.0, -dz);
+ }
+ break;
+ }
}
/* if shiftkey, center point as last, for selectbuffer order */
@@ -1284,16 +1404,17 @@ static void draw_manipulator_translate(View3D *v3d, RegionView3D *rv3d, int UNUS
float cywid = 0.25f * cylen, dz, size;
float unitmat[4][4];
int shift = 0; // XXX
+ int axis_order[3] = {0, 1, 2};
+ int i;
/* when called while moving in mixed mode, do not draw when... */
if ((drawflags & MAN_TRANS_C) == 0) return;
+ manipulator_axis_order(rv3d, axis_order);
+
// XXX if (moving) glTranslatef(t->vec[0], t->vec[1], t->vec[2]);
glDisable(GL_DEPTH_TEST);
- qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_FILL);
-
/* center circle, do not add to selection when shift is pressed (planar constraint) */
if ((G.f & G_PICKSEL) && shift == 0) glLoadName(MAN_TRANS_C);
@@ -1311,8 +1432,11 @@ static void draw_manipulator_translate(View3D *v3d, RegionView3D *rv3d, int UNUS
glLoadName(-1);
// translate drawn as last, only axis when no combo with scale, or for ghosting
- if ((combo & V3D_MANIP_SCALE) == 0 || colcode == MAN_GHOST)
- draw_manipulator_axes(v3d, rv3d, colcode, drawflags & MAN_TRANS_X, drawflags & MAN_TRANS_Y, drawflags & MAN_TRANS_Z);
+ if ((combo & V3D_MANIP_SCALE) == 0 || colcode == MAN_GHOST) {
+ draw_manipulator_axes(v3d, rv3d, colcode,
+ drawflags & MAN_TRANS_X, drawflags & MAN_TRANS_Y, drawflags & MAN_TRANS_Z,
+ axis_order);
+ }
/* offset in combo mode, for rotate a bit more */
@@ -1320,29 +1444,43 @@ static void draw_manipulator_translate(View3D *v3d, RegionView3D *rv3d, int UNUS
else if (combo & (V3D_MANIP_SCALE)) dz = 1.0f + 0.5f * cylen;
else dz = 1.0f;
- /* Z Cone */
- glTranslatef(0.0, 0.0, dz);
- if (drawflags & MAN_TRANS_Z) {
- if (G.f & G_PICKSEL) glLoadName(MAN_TRANS_Z);
- manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->twangle[2]));
- draw_cone(qobj, cylen, cywid);
- }
- /* X Cone */
- glTranslatef(dz, 0.0, -dz);
- if (drawflags & MAN_TRANS_X) {
- if (G.f & G_PICKSEL) glLoadName(MAN_TRANS_X);
- glRotatef(90.0, 0.0, 1.0, 0.0);
- manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->twangle[0]));
- draw_cone(qobj, cylen, cywid);
- glRotatef(-90.0, 0.0, 1.0, 0.0);
- }
- /* Y Cone */
- glTranslatef(-dz, dz, 0.0);
- if (drawflags & MAN_TRANS_Y) {
- if (G.f & G_PICKSEL) glLoadName(MAN_TRANS_Y);
- glRotatef(-90.0, 1.0, 0.0, 0.0);
- manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->twangle[1]));
- draw_cone(qobj, cylen, cywid);
+ qobj = gluNewQuadric();
+ gluQuadricDrawStyle(qobj, GLU_FILL);
+
+ for (i = 0; i < 3; i++) {
+ switch (axis_order[i]) {
+ case 0: /* Z Cone */
+ if (drawflags & MAN_TRANS_Z) {
+ glTranslatef(0.0, 0.0, dz);
+ if (G.f & G_PICKSEL) glLoadName(MAN_TRANS_Z);
+ manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->twangle[2]));
+ draw_cone(qobj, cylen, cywid);
+ glTranslatef(0.0, 0.0, -dz);
+ }
+ break;
+ case 1: /* X Cone */
+ if (drawflags & MAN_TRANS_X) {
+ glTranslatef(dz, 0.0, 0.0);
+ if (G.f & G_PICKSEL) glLoadName(MAN_TRANS_X);
+ glRotatef(90.0, 0.0, 1.0, 0.0);
+ manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->twangle[0]));
+ draw_cone(qobj, cylen, cywid);
+ glRotatef(-90.0, 0.0, 1.0, 0.0);
+ glTranslatef(-dz, 0.0, 0.0);
+ }
+ break;
+ case 2: /* Y Cone */
+ if (drawflags & MAN_TRANS_Y) {
+ glTranslatef(0.0, dz, 0.0);
+ if (G.f & G_PICKSEL) glLoadName(MAN_TRANS_Y);
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->twangle[1]));
+ draw_cone(qobj, cylen, cywid);
+ glRotatef(90.0, 1.0, 0.0, 0.0);
+ glTranslatef(0.0, -dz, 0.0);
+ }
+ break;
+ }
}
gluDeleteQuadric(qobj);
@@ -1358,10 +1496,13 @@ static void draw_manipulator_rotate_cyl(View3D *v3d, RegionView3D *rv3d, int mov
float size;
float cylen = 0.01f * (float)U.tw_handlesize;
float cywid = 0.25f * cylen;
-
+ 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;
+ manipulator_axis_order(rv3d, axis_order);
+
/* prepare for screen aligned draw */
glPushMatrix();
size = screen_aligned(rv3d, rv3d->twmat);
@@ -1412,36 +1553,50 @@ static void draw_manipulator_rotate_cyl(View3D *v3d, RegionView3D *rv3d, int mov
if ((G.f & G_PICKSEL) == 0) {
// only draw axis when combo didn't draw scale axes
- if ((combo & V3D_MANIP_SCALE) == 0)
- draw_manipulator_axes(v3d, rv3d, colcode, drawflags & MAN_ROT_X, drawflags & MAN_ROT_Y, drawflags & MAN_ROT_Z);
+ if ((combo & V3D_MANIP_SCALE) == 0) {
+ draw_manipulator_axes(v3d, rv3d, colcode,
+ drawflags & MAN_ROT_X, drawflags & MAN_ROT_Y, drawflags & MAN_ROT_Z,
+ axis_order);
+ }
/* only has to be set when not in picking */
gluQuadricDrawStyle(qobj, GLU_FILL);
}
- /* Z cyl */
- glTranslatef(0.0, 0.0, 1.0);
- if (drawflags & MAN_ROT_Z) {
- if (G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
- manipulator_setcolor(v3d, 'Z', colcode, 255);
- draw_cylinder(qobj, cylen, cywid);
- }
- /* X cyl */
- glTranslatef(1.0, 0.0, -1.0);
- if (drawflags & MAN_ROT_X) {
- if (G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
- glRotatef(90.0, 0.0, 1.0, 0.0);
- manipulator_setcolor(v3d, 'X', colcode, 255);
- draw_cylinder(qobj, cylen, cywid);
- glRotatef(-90.0, 0.0, 1.0, 0.0);
- }
- /* Y cylinder */
- glTranslatef(-1.0, 1.0, 0.0);
- if (drawflags & MAN_ROT_Y) {
- if (G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
- glRotatef(-90.0, 1.0, 0.0, 0.0);
- manipulator_setcolor(v3d, 'Y', colcode, 255);
- draw_cylinder(qobj, cylen, cywid);
+ for (i = 0; i < 3; i++) {
+ switch (axis_order[i]) {
+ case 0: /* X cylinder */
+ if (drawflags & MAN_ROT_X) {
+ glTranslatef(1.0, 0.0, 0.0);
+ if (G.f & G_PICKSEL) glLoadName(MAN_ROT_X);
+ glRotatef(90.0, 0.0, 1.0, 0.0);
+ manipulator_setcolor(v3d, 'X', colcode, 255);
+ draw_cylinder(qobj, cylen, cywid);
+ glRotatef(-90.0, 0.0, 1.0, 0.0);
+ glTranslatef(-1.0, 0.0, 0.0);
+ }
+ break;
+ case 1: /* Y cylinder */
+ if (drawflags & MAN_ROT_Y) {
+ glTranslatef(0.0, 1.0, 0.0);
+ if (G.f & G_PICKSEL) glLoadName(MAN_ROT_Y);
+ glRotatef(-90.0, 1.0, 0.0, 0.0);
+ manipulator_setcolor(v3d, 'Y', colcode, 255);
+ draw_cylinder(qobj, cylen, cywid);
+ glRotatef(90.0, 1.0, 0.0, 0.0);
+ glTranslatef(0.0, -1.0, 0.0);
+ }
+ break;
+ case 2: /* Z cylinder */
+ if (drawflags & MAN_ROT_Z) {
+ glTranslatef(0.0, 0.0, 1.0);
+ if (G.f & G_PICKSEL) glLoadName(MAN_ROT_Z);
+ manipulator_setcolor(v3d, 'Z', colcode, 255);
+ draw_cylinder(qobj, cylen, cywid);
+ glTranslatef(0.0, 0.0, -1.0);
+ }
+ break;
+ }
}
/* restore */
@@ -1586,8 +1741,12 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl
dep = buffer[4 * a + 1];
val = buffer[4 * a + 3];
- if (val == MAN_TRANS_C) return MAN_TRANS_C;
- else if (val == MAN_SCALE_C) return MAN_SCALE_C;
+ if (val == MAN_TRANS_C) {
+ return MAN_TRANS_C;
+ }
+ else if (val == MAN_SCALE_C) {
+ return MAN_SCALE_C;
+ }
else {
if (val & MAN_ROT_C) {
if (minvalrot == 0 || dep < mindeprot) {
@@ -1614,7 +1773,7 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl
/* return 0; nothing happened */
-int BIF_do_manipulator(bContext *C, struct wmEvent *event, wmOperator *op)
+int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op)
{
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = sa->spacedata.first;
@@ -1702,8 +1861,15 @@ int BIF_do_manipulator(bContext *C, struct wmEvent *event, wmOperator *op)
//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 */
- WM_operator_name_call(C, "TRANSFORM_OT_trackball", WM_OP_INVOKE_DEFAULT, op->ptr);
- //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_trackball", 0), event, op->ptr, NULL, FALSE);
+ /* Do not pass op->ptr!!! trackball has no "constraint" properties!
+ * See [#34621], it's a miracle it did not cause more problems!!! */
+ /* However, we need to copy the "release_confirm" property... */
+ PointerRNA props_ptr;
+ WM_operator_properties_create(&props_ptr, "TRANSFORM_OT_trackball");
+ RNA_boolean_set(&props_ptr, "release_confirm", RNA_boolean_get(op->ptr, "release_confirm"));
+
+ WM_operator_name_call(C, "TRANSFORM_OT_trackball", WM_OP_INVOKE_DEFAULT, &props_ptr);
+ //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_trackball", 0), event, NULL, NULL, FALSE);
}
else if (drawflags & MAN_ROT_C) {
switch (drawflags) {
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 916cf540589..60b0c655691 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -24,24 +24,25 @@
* \ingroup edtransform
*/
-
#include "MEM_guardedalloc.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "RNA_access.h"
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_armature.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"
@@ -73,6 +74,7 @@ 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";
@@ -90,6 +92,7 @@ static void TRANSFORM_OT_tilt(struct wmOperatorType *ot);
static void TRANSFORM_OT_trackball(struct wmOperatorType *ot);
static void TRANSFORM_OT_mirror(struct wmOperatorType *ot);
static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot);
+static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot);
static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot);
static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot);
static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot);
@@ -109,6 +112,7 @@ static TransformModeItem transform_modes[] =
{OP_TRACKBALL, TFM_TRACKBALL, TRANSFORM_OT_trackball},
{OP_MIRROR, TFM_MIRROR, TRANSFORM_OT_mirror},
{OP_EDGE_SLIDE, TFM_EDGE_SLIDE, TRANSFORM_OT_edge_slide},
+ {OP_VERT_SLIDE, TFM_VERT_SLIDE, TRANSFORM_OT_vert_slide},
{OP_EDGE_CREASE, TFM_CREASE, TRANSFORM_OT_edge_crease},
{OP_EDGE_BWEIGHT, TFM_BWEIGHT, TRANSFORM_OT_edge_bevelweight},
{OP_SEQ_SLIDE, TFM_SEQ_SLIDE, TRANSFORM_OT_seq_slide},
@@ -150,38 +154,6 @@ EnumPropertyItem transform_mode_types[] =
{0, NULL, 0, NULL, NULL}
};
-static int snap_type_exec(bContext *C, wmOperator *op)
-{
- ToolSettings *ts = CTX_data_tool_settings(C);
-
- ts->snap_mode = RNA_enum_get(op->ptr, "type");
-
- WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
-
- return OPERATOR_FINISHED;
-}
-
-static void TRANSFORM_OT_snap_type(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Snap Type";
- ot->description = "Set the snap element type";
- ot->idname = "TRANSFORM_OT_snap_type";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = snap_type_exec;
-
- ot->poll = ED_operator_areaactive;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* props */
- ot->prop = RNA_def_enum(ot->srna, "type", snap_element_items, 0, "Type", "Set the snap element type");
-
-}
-
static int select_orientation_exec(bContext *C, wmOperator *op)
{
int orientation = RNA_enum_get(op->ptr, "orientation");
@@ -193,12 +165,12 @@ static int select_orientation_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int select_orientation_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
+static int select_orientation_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
uiPopupMenu *pup;
uiLayout *layout;
- pup = uiPupMenuBegin(C, "Orientation", ICON_NONE);
+ pup = uiPupMenuBegin(C, IFACE_("Orientation"), ICON_NONE);
layout = uiPupMenuLayout(pup);
uiItemsEnumO(layout, "TRANSFORM_OT_select_orientation", "orientation");
uiPupMenuEnd(C, pup);
@@ -240,7 +212,7 @@ static int delete_orientation_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-static int delete_orientation_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int delete_orientation_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
return delete_orientation_exec(C, op);
}
@@ -296,7 +268,7 @@ static int create_orientation_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int create_orientation_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int create_orientation_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
return create_orientation_exec(C, op);
}
@@ -328,7 +300,7 @@ static void transformops_exit(bContext *C, wmOperator *op)
G.moving = 0;
}
-static int transformops_data(bContext *C, wmOperator *op, wmEvent *event)
+static int transformops_data(bContext *C, wmOperator *op, const wmEvent *event)
{
int retval = 1;
if (op->customdata == NULL) {
@@ -362,7 +334,7 @@ static int transformops_data(bContext *C, wmOperator *op, wmEvent *event)
return retval; /* return 0 on error */
}
-static int transform_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
int exit_code;
@@ -429,7 +401,7 @@ static int transform_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int transform_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int transform_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (!transformops_data(C, op, event)) {
G.moving = 0;
@@ -458,7 +430,6 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
/* Make this not hidden when there's a nice axis selection widget */
RNA_def_property_flag(prop, PROP_HIDDEN);
RNA_def_property_ui_text(prop, "Axis", "The axis around which the transformation occurs");
-
}
if (flags & P_CONSTRAINT) {
@@ -466,8 +437,6 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
prop = RNA_def_property(ot->srna, "constraint_orientation", PROP_ENUM, PROP_NONE);
RNA_def_property_ui_text(prop, "Orientation", "Transformation orientation");
RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
-
-
}
if (flags & P_MIRROR) {
@@ -585,6 +554,8 @@ 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";
@@ -598,7 +569,9 @@ static void TRANSFORM_OT_trackball(struct wmOperatorType *ot)
ot->cancel = transform_cancel;
ot->poll = ED_operator_screenactive;
- RNA_def_float_vector(ot->srna, "value", 2, VecOne, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX);
+ /* 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);
Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP);
}
@@ -793,6 +766,26 @@ static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot)
Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
}
+static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Vertex Slide";
+ ot->description = "Slide a vertex along a mesh";
+ ot->idname = OP_VERT_SLIDE;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* api callbacks */
+ ot->invoke = transform_invoke;
+ ot->exec = transform_exec;
+ ot->modal = transform_modal;
+ ot->cancel = transform_cancel;
+ ot->poll = ED_operator_editmesh;
+
+ RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
+
+ Transform_Properties(ot, P_MIRROR | P_SNAP);
+}
+
static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot)
{
/* identifiers */
@@ -848,7 +841,7 @@ static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot)
ot->cancel = transform_cancel;
ot->poll = ED_operator_sequencer_active;
- RNA_def_float_vector(ot->srna, "value", 2, VecOne, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX);
+ RNA_def_float_vector_xyz(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX);
Transform_Properties(ot, P_SNAP);
}
@@ -891,8 +884,6 @@ void transform_operatortypes(void)
WM_operatortype_append(TRANSFORM_OT_select_orientation);
WM_operatortype_append(TRANSFORM_OT_create_orientation);
WM_operatortype_append(TRANSFORM_OT_delete_orientation);
-
- WM_operatortype_append(TRANSFORM_OT_snap_type);
}
void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spaceid)
@@ -939,7 +930,9 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac
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");
- WM_keymap_add_item(keymap, "TRANSFORM_OT_snap_type", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+ 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_element");
+
kmi = WM_keymap_add_item(keymap, OP_TRANSLATION, TKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "texture_space", TRUE);
@@ -1032,6 +1025,9 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac
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_uv_element");
break;
case SPACE_CLIP:
WM_keymap_add_item(keymap, OP_TRANSLATION, GKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index d758a15f50c..b12c0906fa0 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -43,6 +43,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_curve.h"
#include "BKE_context.h"
@@ -88,7 +89,7 @@ static TransformOrientation *findOrientationName(ListBase *lb, const char *name)
return NULL;
}
-static int uniqueOrientationNameCheck(void *arg, const char *name)
+static bool uniqueOrientationNameCheck(void *arg, const char *name)
{
return findOrientationName((ListBase *)arg, name) != NULL;
}
@@ -408,14 +409,16 @@ const char *BIF_menustringTransformOrientation(const bContext *C, const char *ti
int i = V3D_MANIP_CUSTOM;
char *str_menu, *p;
const int elem_size = MAX_NAME + 4;
+ size_t str_menu_size;
title = IFACE_(title);
- str_menu = MEM_callocN(strlen(menu) + strlen(title) + 1 + elem_size * BIF_countTransformOrientation(C), "UserTransSpace from matrix");
+ str_menu_size = strlen(menu) + strlen(title) + 1 + (elem_size * BIF_countTransformOrientation(C));
+ str_menu = MEM_callocN(str_menu_size, "UserTransSpace from matrix");
+
p = str_menu;
-
- p += sprintf(str_menu, "%s", title);
- p += sprintf(p, "%s", menu);
+ p += BLI_strncpy_rlen(p, title, str_menu_size);
+ p += BLI_strncpy_rlen(p, menu, str_menu_size - (p - str_menu));
for (ts = transform_spaces->first; ts; ts = ts->next) {
p += sprintf(p, "|%s %%x%d", ts->name, i++);
@@ -437,7 +440,7 @@ int BIF_countTransformOrientation(const bContext *C)
return count;
}
-void applyTransformOrientation(const bContext *C, float mat[3][3], char *name)
+void applyTransformOrientation(const bContext *C, float mat[3][3], char name[MAX_NAME])
{
TransformOrientation *ts;
View3D *v3d = CTX_wm_view3d(C);
@@ -448,8 +451,9 @@ void applyTransformOrientation(const bContext *C, float mat[3][3], char *name)
for (i = 0, ts = CTX_data_scene(C)->transform_spaces.first; ts; ts = ts->next, i++) {
if (selected_index == i) {
- if (name)
- strcpy(name, ts->name);
+ if (name) {
+ BLI_strncpy(name, ts->name, MAX_NAME);
+ }
copy_m3_m3(mat, ts->mat);
break;
@@ -491,25 +495,25 @@ void initTransformOrientation(bContext *C, TransInfo *t)
switch (t->current_orientation) {
case V3D_MANIP_GLOBAL:
unit_m3(t->spacemtx);
- strcpy(t->spacename, "global");
+ strcpy(t->spacename, IFACE_("global"));
break;
case V3D_MANIP_GIMBAL:
unit_m3(t->spacemtx);
if (gimbal_axis(ob, t->spacemtx)) {
- strcpy(t->spacename, "gimbal");
+ strcpy(t->spacename, IFACE_("gimbal"));
break;
}
/* no gimbal fallthrough to normal */
case V3D_MANIP_NORMAL:
if (obedit || (ob && ob->mode & OB_MODE_POSE)) {
- strcpy(t->spacename, "normal");
+ strcpy(t->spacename, IFACE_("normal"));
ED_getTransformOrientationMatrix(C, t->spacemtx, (v3d->around == V3D_ACTIVE));
break;
}
/* no break we define 'normal' as 'local' in Object mode */
case V3D_MANIP_LOCAL:
- strcpy(t->spacename, "local");
+ strcpy(t->spacename, IFACE_("local"));
if (ob) {
copy_m3_m4(t->spacemtx, ob->obmat);
@@ -526,7 +530,7 @@ void initTransformOrientation(bContext *C, TransInfo *t)
RegionView3D *rv3d = t->ar->regiondata;
float mat[3][3];
- strcpy(t->spacename, "view");
+ strcpy(t->spacename, IFACE_("view"));
copy_m3_m4(mat, rv3d->viewinv);
normalize_m3(mat);
copy_m3_m3(t->spacemtx, mat);
@@ -737,7 +741,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
}
}
- if (normal[0] != 0 || normal[1] != 0 || normal[2] != 0) {
+ if (!is_zero_v3(normal)) {
result = ORIENTATION_NORMAL;
}
}
@@ -760,29 +764,45 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
else if (obedit->type == OB_ARMATURE) {
bArmature *arm = obedit->data;
EditBone *ebone;
+ int ok = FALSE;
- for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
- if (arm->layer & ebone->layer) {
- if (ebone->flag & BONE_SELECTED) {
- float tmat[3][3];
- float vec[3];
- sub_v3_v3v3(vec, ebone->tail, ebone->head);
- normalize_v3(vec);
- add_v3_v3(normal, vec);
-
- vec_roll_to_mat3(vec, ebone->roll, tmat);
- add_v3_v3(plane, tmat[2]);
+ /* grr. but better then duplicate code */
+#define EBONE_CALC_NORMAL_PLANE { \
+ float tmat[3][3]; \
+ float vec[3]; \
+ sub_v3_v3v3(vec, ebone->tail, ebone->head); \
+ normalize_v3(vec); \
+ add_v3_v3(normal, vec); \
+ \
+ vec_roll_to_mat3(vec, ebone->roll, tmat); \
+ add_v3_v3(plane, tmat[2]); \
+ } (void)0
+
+
+ if (activeOnly && (ebone = arm->act_edbone)) {
+ EBONE_CALC_NORMAL_PLANE;
+ ok = TRUE;
+ }
+ else {
+ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+ if (arm->layer & ebone->layer) {
+ if (ebone->flag & BONE_SELECTED) {
+ EBONE_CALC_NORMAL_PLANE;
+ ok = TRUE;
+ }
}
}
}
- normalize_v3(normal);
- normalize_v3(plane);
+ if (ok) {
+ normalize_v3(normal);
+ normalize_v3(plane);
- if (plane[0] != 0 || plane[1] != 0 || plane[2] != 0) {
- result = ORIENTATION_EDGE;
+ if (!is_zero_v3(plane)) {
+ result = ORIENTATION_EDGE;
+ }
}
-
+#undef EBONE_CALC_NORMAL_PLANE
}
/* Vectors from edges don't need the special transpose inverse multiplication */
@@ -798,19 +818,32 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
else if (ob && (ob->mode & OB_MODE_POSE)) {
bArmature *arm = ob->data;
bPoseChannel *pchan;
- int totsel;
-
- totsel = count_bone_select(arm, &arm->bonebase, 1);
- if (totsel) {
- float imat[3][3], mat[3][3];
-
- /* use channels to get stats */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) {
- add_v3_v3(normal, pchan->pose_mat[2]);
- add_v3_v3(plane, pchan->pose_mat[1]);
+ float imat[3][3], mat[3][3];
+ int ok = FALSE;
+
+ if (activeOnly && (pchan = BKE_pose_channel_active(ob))) {
+ add_v3_v3(normal, pchan->pose_mat[2]);
+ add_v3_v3(plane, pchan->pose_mat[1]);
+ ok = TRUE;
+ }
+ else {
+ int totsel;
+
+ totsel = count_bone_select(arm, &arm->bonebase, 1);
+ if (totsel) {
+ /* use channels to get stats */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) {
+ add_v3_v3(normal, pchan->pose_mat[2]);
+ add_v3_v3(plane, pchan->pose_mat[1]);
+ }
}
+ ok = TRUE;
}
+ }
+
+ /* use for both active & all */
+ if (ok) {
negate_v3(plane);
/* we need the transpose of the inverse for a normal... */
@@ -851,7 +884,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
return result;
}
-void ED_getTransformOrientationMatrix(const bContext *C, float orientation_mat[3][3], int activeOnly)
+void ED_getTransformOrientationMatrix(const bContext *C, float orientation_mat[3][3], const bool activeOnly)
{
float normal[3] = {0.0, 0.0, 0.0};
float plane[3] = {0.0, 0.0, 0.0};
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 9de9c96f2ec..c92cd77449e 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -47,8 +47,6 @@
#include "DNA_view3d_types.h"
#include "DNA_windowmanager_types.h"
-#include "RNA_access.h"
-
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -62,6 +60,10 @@
#include "BKE_tessmesh.h"
#include "BKE_mesh.h"
+#include "RNA_access.h"
+
+#include "WM_types.h"
+
#include "ED_armature.h"
#include "ED_image.h"
#include "ED_mesh.h"
@@ -69,8 +71,6 @@
#include "ED_uvedit.h"
#include "ED_view3d.h"
-#include "WM_types.h"
-
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -103,7 +103,7 @@ static float ResizeBetween(TransInfo *t, float p1[3], float p2[3]);
/****************** IMPLEMENTATIONS *********************/
-static int snapNodeTest(View2D *v2d, bNode *node, SnapMode mode);
+static bool snapNodeTest(View2D *v2d, bNode *node, SnapMode mode);
static NodeBorder snapNodeBorder(int snap_node_mode);
#if 0
@@ -260,7 +260,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
}
}
-int handleSnapping(TransInfo *t, wmEvent *event)
+int handleSnapping(TransInfo *t, const wmEvent *event)
{
int status = 0;
@@ -303,6 +303,9 @@ void applyProject(TransInfo *t)
if (td->flag & TD_SKIP)
continue;
+
+ if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f))
+ continue;
copy_v3_v3(iloc, td->loc);
if (t->flag & (T_EDIT | T_POSE)) {
@@ -804,7 +807,7 @@ static float ResizeBetween(TransInfo *t, float p1[3], float p2[3])
/********************** CALC **************************/
-static void UNUSED_FUNCTION(CalcSnapGrid) (TransInfo * t, float *UNUSED(vec))
+static void UNUSED_FUNCTION(CalcSnapGrid) (TransInfo *t, float *UNUSED(vec))
{
snapGridAction(t, t->tsnap.snapPoint, BIG_GEARS);
}
@@ -815,7 +818,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
float loc[3];
float no[3];
float mval[2];
- int found = 0;
+ bool found = false;
int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
mval[0] = t->mval[0];
@@ -898,7 +901,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
no[0] = 0.0;
no[1] = 0.0;
no[2] = 1.0;
- found = 1;
+ found = true;
}
BLI_freelistN(&depth_peels);
@@ -907,7 +910,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
found = snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.modeSelect);
}
- if (found == 1) {
+ if (found == true) {
float tangent[3];
sub_v3_v3v3(tangent, loc, t->tsnap.snapPoint);
@@ -1141,13 +1144,13 @@ static void TargetSnapClosest(TransInfo *t)
}
}
-static int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], short v2no[3], float obmat[4][4], float timat[3][3],
- const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2],
- float r_loc[3], float r_no[3], int *r_dist, float *r_depth)
+static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], short v2no[3], float obmat[4][4], float timat[3][3],
+ const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2],
+ float r_loc[3], float r_no[3], int *r_dist, float *r_depth)
{
float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3];
int result;
- int retval = 0;
+ bool retval = false;
copy_v3_v3(ray_end, ray_normal_local);
mul_v3_fl(ray_end, 2000);
@@ -1203,7 +1206,7 @@ static int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], sh
float n1[3], n2[3];
*r_depth = new_depth;
- retval = 1;
+ retval = true;
sub_v3_v3v3(edge_loc, v1co, v2co);
sub_v3_v3v3(vec, intersect, v2co);
@@ -1228,11 +1231,11 @@ static int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], sh
return retval;
}
-static int snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4], float timat[3][3],
- const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2],
- float r_loc[3], float r_no[3], int *r_dist, float *r_depth)
+static bool snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4], float timat[3][3],
+ const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2],
+ float r_loc[3], float r_no[3], int *r_dist, float *r_depth)
{
- int retval = 0;
+ bool retval = false;
float dvec[3];
sub_v3_v3v3(dvec, vco, ray_start_local);
@@ -1259,7 +1262,7 @@ static int snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4]
if (new_dist <= *r_dist && new_depth < *r_depth) {
*r_depth = new_depth;
- retval = 1;
+ retval = true;
copy_v3_v3(r_loc, location);
@@ -1276,13 +1279,13 @@ static int snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4]
return retval;
}
-static int snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4],
- const float ray_start[3], const float ray_normal[3], const float mval[2],
- float r_loc[3], float *UNUSED(r_no), int *r_dist, float *r_depth)
+static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4],
+ const float ray_start[3], const float ray_normal[3], const float mval[2],
+ float r_loc[3], float *UNUSED(r_no), int *r_dist, float *r_depth)
{
float imat[4][4];
float ray_start_local[3], ray_normal_local[3];
- int retval = 0;
+ bool retval = false;
invert_m4_m4(imat, obmat);
@@ -1339,11 +1342,11 @@ static int snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm
return retval;
}
-static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, BMEditMesh *em, float obmat[4][4],
- const float ray_start[3], const float ray_normal[3], const float mval[2],
- float r_loc[3], float r_no[3], int *r_dist, float *r_depth)
+static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, BMEditMesh *em, float obmat[4][4],
+ const float ray_start[3], const float ray_normal[3], const float mval[2],
+ float r_loc[3], float r_no[3], int *r_dist, float *r_depth)
{
- int retval = 0;
+ bool retval = false;
int totvert = dm->getNumVerts(dm);
int totface = dm->getNumTessFaces(dm);
@@ -1417,7 +1420,7 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh
if (em != NULL) {
index_array = dm->getVertDataArray(dm, CD_ORIGINDEX);
- EDBM_index_arrays_init(em, 1, 0, 0);
+ EDBM_index_arrays_ensure(em, BM_VERT);
}
for (i = 0; i < totvert; i++) {
@@ -1452,9 +1455,6 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh
}
}
- if (em != NULL) {
- EDBM_index_arrays_free(em);
- }
break;
}
case SCE_SNAP_MODE_EDGE:
@@ -1468,7 +1468,7 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh
if (em != NULL) {
index_array = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
- EDBM_index_arrays_init(em, 0, 1, 0);
+ EDBM_index_arrays_ensure(em, BM_EDGE);
}
for (i = 0; i < totedge; i++) {
@@ -1505,9 +1505,6 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh
}
}
- if (em != NULL) {
- EDBM_index_arrays_free(em);
- }
break;
}
}
@@ -1517,12 +1514,12 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh
return retval;
}
-static int snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obmat[4][4],
- const float ray_start[3], const float ray_normal[3], const float mval[2],
- float r_loc[3], float r_no[3], int *r_dist, float *r_depth)
+static bool snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obmat[4][4],
+ const float ray_start[3], const float ray_normal[3], const float mval[2],
+ float r_loc[3], float r_no[3], int *r_dist, float *r_depth)
{
ToolSettings *ts = scene->toolsettings;
- int retval = 0;
+ bool retval = false;
if (ob->type == OB_MESH) {
BMEditMesh *em;
@@ -1549,12 +1546,12 @@ static int snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, flo
return retval;
}
-static int snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, const float mval[2],
- int *r_dist, float r_loc[3], float r_no[3], SnapMode mode)
+static bool snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, const float mval[2],
+ int *r_dist, float r_loc[3], float r_no[3], SnapMode mode)
{
Base *base;
- float depth = FLT_MAX;
- int retval = 0;
+ float depth = (FLT_MAX / 2.0f); /* use half of flt-max so we can scale up without an exception */
+ bool retval = false;
float ray_start[3], ray_normal[3];
ED_view3d_win_to_ray(ar, v3d, mval, ray_start, ray_normal);
@@ -1605,12 +1602,12 @@ static int snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, c
return retval;
}
-int snapObjectsTransform(TransInfo *t, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode)
+bool snapObjectsTransform(TransInfo *t, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode)
{
return snapObjects(t->scene, t->view, t->ar, t->obedit, mval, r_dist, r_loc, r_no, mode);
}
-int snapObjectsContext(bContext *C, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode)
+bool snapObjectsContext(bContext *C, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode)
{
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = sa->spacedata.first;
@@ -1670,11 +1667,11 @@ static void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float n
peel->flag = 0;
}
-static int 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)
+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)
{
- int retval = 0;
+ bool retval = false;
int totvert = dm->getNumVerts(dm);
int totface = dm->getNumTessFaces(dm);
@@ -1779,10 +1776,11 @@ static int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[4][4],
return retval;
}
-static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, ListBase *depth_peels, const float mval[2], SnapMode mode)
+static bool peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit,
+ ListBase *depth_peels, const float mval[2], SnapMode mode)
{
Base *base;
- int retval = 0;
+ bool retval = false;
float ray_start[3], ray_normal[3];
ED_view3d_win_to_ray(ar, v3d, mval, ray_start, ray_normal);
@@ -1801,7 +1799,7 @@ static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, L
if (dob->type == OB_MESH) {
BMEditMesh *em;
DerivedMesh *dm = NULL;
- int val;
+ bool val;
if (dob != obedit) {
dm = mesh_get_derived_final(scene, dob, CD_MASK_BAREMESH);
@@ -1825,7 +1823,7 @@ static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, L
}
if (ob->type == OB_MESH) {
- int val = 0;
+ bool val = false;
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);
@@ -1853,12 +1851,12 @@ static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, L
return retval;
}
-int peelObjectsTransForm(TransInfo *t, ListBase *depth_peels, const float mval[2], SnapMode mode)
+bool peelObjectsTransForm(TransInfo *t, ListBase *depth_peels, const float mval[2], SnapMode mode)
{
return peelObjects(t->scene, t->view, t->ar, t->obedit, depth_peels, mval, mode);
}
-int peelObjectsContext(bContext *C, ListBase *depth_peels, const float mval[2], SnapMode mode)
+bool peelObjectsContext(bContext *C, ListBase *depth_peels, const float mval[2], SnapMode mode)
{
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = sa->spacedata.first;
@@ -1868,7 +1866,7 @@ int peelObjectsContext(bContext *C, ListBase *depth_peels, const float mval[2],
/******************** NODES ***********************************/
-static int snapNodeTest(View2D *v2d, bNode *node, SnapMode mode)
+static bool snapNodeTest(View2D *v2d, bNode *node, SnapMode mode)
{
/* node is use for snapping only if a) snap mode matches and b) node is inside the view */
return ((mode == SNAP_NOT_SELECTED && !(node->flag & NODE_SELECT)) ||
@@ -1890,12 +1888,12 @@ static NodeBorder snapNodeBorder(int snap_node_mode)
return 0;
}
-static int snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNode *node, const int mval[2],
- float r_loc[2], int *r_dist, char *r_node_border)
+static bool snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNode *node, const int mval[2],
+ float r_loc[2], int *r_dist, char *r_node_border)
{
View2D *v2d = &ar->v2d;
NodeBorder border = snapNodeBorder(ts->snap_node_mode);
- int retval = 0;
+ bool retval = false;
rcti totr;
int new_dist;
@@ -1908,7 +1906,7 @@ static int snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNo
UI_view2d_region_to_view(v2d, totr.xmin, mval[1], &r_loc[0], &r_loc[1]);
*r_dist = new_dist;
*r_node_border = NODE_LEFT;
- retval = 1;
+ retval = true;
}
}
@@ -1918,7 +1916,7 @@ static int snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNo
UI_view2d_region_to_view(v2d, totr.xmax, mval[1], &r_loc[0], &r_loc[1]);
*r_dist = new_dist;
*r_node_border = NODE_RIGHT;
- retval = 1;
+ retval = true;
}
}
@@ -1928,7 +1926,7 @@ static int snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNo
UI_view2d_region_to_view(v2d, mval[0], totr.ymin, &r_loc[0], &r_loc[1]);
*r_dist = new_dist;
*r_node_border = NODE_BOTTOM;
- retval = 1;
+ retval = true;
}
}
@@ -1938,19 +1936,19 @@ static int snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNo
UI_view2d_region_to_view(v2d, mval[0], totr.ymax, &r_loc[0], &r_loc[1]);
*r_dist = new_dist;
*r_node_border = NODE_TOP;
- retval = 1;
+ retval = true;
}
}
return retval;
}
-static int snapNodes(ToolSettings *ts, SpaceNode *snode, ARegion *ar, const int mval[2],
+static bool snapNodes(ToolSettings *ts, SpaceNode *snode, ARegion *ar, const int mval[2],
int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode)
{
bNodeTree *ntree = snode->edittree;
bNode *node;
- int retval = 0;
+ bool retval = false;
*r_node_border = 0;
@@ -1962,12 +1960,12 @@ static int snapNodes(ToolSettings *ts, SpaceNode *snode, ARegion *ar, const int
return retval;
}
-int snapNodesTransform(TransInfo *t, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode)
+bool snapNodesTransform(TransInfo *t, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode)
{
return snapNodes(t->settings, t->sa->spacedata.first, t->ar, mval, r_dist, r_loc, r_node_border, mode);
}
-int snapNodesContext(bContext *C, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode)
+bool snapNodesContext(bContext *C, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode)
{
Scene *scene = CTX_data_scene(C);
return snapNodes(scene->toolsettings, CTX_wm_space_node(C), CTX_wm_region(C), mval, r_dist, r_loc, r_node_border, mode);
diff --git a/source/blender/editors/util/SConscript b/source/blender/editors/util/SConscript
index 74879e54850..1c1a8e46dd7 100644
--- a/source/blender/editors/util/SConscript
+++ b/source/blender/editors/util/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.c')
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 23d6b0a075e..73062c57526 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -42,6 +42,8 @@
#include "BLI_blenlib.h"
+#include "BLF_translation.h"
+
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -174,10 +176,10 @@ 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, "Unpack file", ICON_NONE);
+ pup = uiPupMenuBegin(C, IFACE_("Unpack File"), ICON_NONE);
layout = uiPupMenuLayout(pup);
- strcpy(line, "Remove Pack");
+ strcpy(line, IFACE_("Remove Pack"));
props_ptr = uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&props_ptr, "method", PF_REMOVE);
RNA_string_set(&props_ptr, "id", id_name);
@@ -185,20 +187,19 @@ void unpack_menu(bContext *C, const char *opname, const char *id_name, const cha
if (G.relbase_valid) {
char local_name[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX];
- BLI_strncpy(local_name, abs_name, sizeof(local_name));
- BLI_splitdirstring(local_name, fi);
+ 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) {
switch (checkPackedFile(local_name, pf)) {
case PF_NOFILE:
- BLI_snprintf(line, sizeof(line), "Create %s", local_name);
+ BLI_snprintf(line, sizeof(line), IFACE_("Create %s"), local_name);
props_ptr = uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&props_ptr, "method", PF_WRITE_LOCAL);
RNA_string_set(&props_ptr, "id", id_name);
break;
case PF_EQUAL:
- BLI_snprintf(line, sizeof(line), "Use %s (identical)", local_name);
+ BLI_snprintf(line, sizeof(line), IFACE_("Use %s (identical)"), local_name);
//uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_LOCAL);
props_ptr = uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&props_ptr, "method", PF_USE_LOCAL);
@@ -206,13 +207,13 @@ void unpack_menu(bContext *C, const char *opname, const char *id_name, const cha
break;
case PF_DIFFERS:
- BLI_snprintf(line, sizeof(line), "Use %s (differs)", local_name);
+ BLI_snprintf(line, sizeof(line), IFACE_("Use %s (differs)"), local_name);
//uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_LOCAL);
props_ptr = uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&props_ptr, "method", PF_USE_LOCAL);
RNA_string_set(&props_ptr, "id", id_name);
- BLI_snprintf(line, sizeof(line), "Overwrite %s", local_name);
+ BLI_snprintf(line, sizeof(line), IFACE_("Overwrite %s"), local_name);
//uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_WRITE_LOCAL);
props_ptr = uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&props_ptr, "method", PF_WRITE_LOCAL);
@@ -224,27 +225,27 @@ void unpack_menu(bContext *C, const char *opname, const char *id_name, const cha
switch (checkPackedFile(abs_name, pf)) {
case PF_NOFILE:
- BLI_snprintf(line, sizeof(line), "Create %s", abs_name);
+ BLI_snprintf(line, sizeof(line), IFACE_("Create %s"), abs_name);
//uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_WRITE_ORIGINAL);
props_ptr = uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&props_ptr, "method", PF_WRITE_ORIGINAL);
RNA_string_set(&props_ptr, "id", id_name);
break;
case PF_EQUAL:
- BLI_snprintf(line, sizeof(line), "Use %s (identical)", abs_name);
+ BLI_snprintf(line, sizeof(line), IFACE_("Use %s (identical)"), abs_name);
//uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_ORIGINAL);
props_ptr = uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&props_ptr, "method", PF_USE_ORIGINAL);
RNA_string_set(&props_ptr, "id", id_name);
break;
case PF_DIFFERS:
- BLI_snprintf(line, sizeof(line), "Use %s (differs)", abs_name);
+ BLI_snprintf(line, sizeof(line), IFACE_("Use %s (differs)"), abs_name);
//uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_ORIGINAL);
props_ptr = uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&props_ptr, "method", PF_USE_ORIGINAL);
RNA_string_set(&props_ptr, "id", id_name);
- BLI_snprintf(line, sizeof(line), "Overwrite %s", abs_name);
+ BLI_snprintf(line, sizeof(line), IFACE_("Overwrite %s"), abs_name);
//uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_WRITE_ORIGINAL);
props_ptr = uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&props_ptr, "method", PF_WRITE_ORIGINAL);
diff --git a/source/blender/editors/util/editmode_undo.c b/source/blender/editors/util/editmode_undo.c
index c8c26ed771d..7f4e05ddefa 100644
--- a/source/blender/editors/util/editmode_undo.c
+++ b/source/blender/editors/util/editmode_undo.c
@@ -246,7 +246,9 @@ void undo_editmode_step(bContext *C, int step)
}
else if (step == 1) {
- if (curundo == NULL || curundo->prev == NULL) error("No more steps to undo");
+ if (curundo == NULL || curundo->prev == NULL) {
+ error("No more steps to undo");
+ }
else {
if (G.debug & G_DEBUG) printf("undo %s\n", curundo->name);
curundo = curundo->prev;
@@ -256,7 +258,9 @@ void undo_editmode_step(bContext *C, int step)
else {
/* curundo has to remain current situation! */
- if (curundo == NULL || curundo->next == NULL) error("No more steps to redo");
+ if (curundo == NULL || curundo->next == NULL) {
+ error("No more steps to redo");
+ }
else {
undo_restore(curundo->next, curundo->getdata(C), obedit->data);
curundo = curundo->next;
diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c
index 0ec16ead35d..98a1b54c452 100644
--- a/source/blender/editors/util/numinput.c
+++ b/source/blender/editors/util/numinput.c
@@ -163,7 +163,7 @@ void applyNumInput(NumInput *n, float *vec)
}
}
-char handleNumInput(NumInput *n, wmEvent *event)
+char handleNumInput(NumInput *n, const wmEvent *event)
{
float Val = 0;
short idx = n->idx, idx_max = n->idx_max;
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index 1753a564a3c..fc603f7a593 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -83,8 +83,8 @@ void ED_undo_push(bContext *C, const char *str)
Object *obact = CTX_data_active_object(C);
if (G.debug & G_DEBUG)
- printf("undo push %s\n", str);
-
+ printf("%s: %s\n", __func__, str);
+
if (obedit) {
if (U.undosteps == 0) return;
@@ -162,15 +162,18 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
}
}
else {
- int do_glob_undo = FALSE;
-
+ /* Note: we used to do a fall-through here where if the
+ * mode-specific undo system had no more steps to undo (or
+ * redo), the global undo would run.
+ *
+ * That was inconsistent with editmode, and also makes for
+ * unecessarily tricky interaction with the other undo
+ * systems. */
if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) {
- if (!ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname))
- do_glob_undo = TRUE;
+ ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname);
}
else if (obact && obact->mode & OB_MODE_SCULPT) {
- if (!ED_undo_paint_step(C, UNDO_PAINT_MESH, step, undoname))
- do_glob_undo = TRUE;
+ ED_undo_paint_step(C, UNDO_PAINT_MESH, step, undoname);
}
else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
if (step == 1)
@@ -178,24 +181,17 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
else
PE_redo(CTX_data_scene(C));
}
- else {
- do_glob_undo = TRUE;
- }
-
- if (do_glob_undo) {
- if (U.uiflag & USER_GLOBALUNDO) {
- // note python defines not valid here anymore.
- //#ifdef WITH_PYTHON
- // XXX BPY_scripts_clear_pyobjects();
- //#endif
- if (undoname)
- BKE_undo_name(C, undoname);
- else
- BKE_undo_step(C, step);
+ else if (U.uiflag & USER_GLOBALUNDO) {
+ // note python defines not valid here anymore.
+ //#ifdef WITH_PYTHON
+ // XXX BPY_scripts_clear_pyobjects();
+ //#endif
+ if (undoname)
+ BKE_undo_name(C, undoname);
+ else
+ BKE_undo_step(C, step);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
- }
-
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, CTX_data_scene(C));
}
}
@@ -343,8 +339,9 @@ int ED_undo_operator_repeat(bContext *C, struct wmOperator *op)
wmWindowManager *wm = CTX_wm_manager(C);
struct Scene *scene = CTX_data_scene(C);
+ /* keep in sync with logic in view3d_panel_operator_redo() */
ARegion *ar = CTX_wm_region(C);
- ARegion *ar1 = BKE_area_find_region_type(CTX_wm_area(C), RGN_TYPE_WINDOW);
+ ARegion *ar1 = BKE_area_find_region_active_win(CTX_wm_area(C));
if (ar1)
CTX_wm_region_set(C, ar1);
@@ -478,7 +475,7 @@ static EnumPropertyItem *rna_undo_itemf(bContext *C, int undosys, int *totitem)
}
-static int undo_history_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int undo_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
int undosys, totitem = 0;
diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt
index 1c69e569aa6..695a7cdd0f6 100644
--- a/source/blender/editors/uvedit/CMakeLists.txt
+++ b/source/blender/editors/uvedit/CMakeLists.txt
@@ -22,6 +22,7 @@ set(INC
../include
../../blenkernel
../../blenlib
+ ../../blenfont
../../blenloader
../../bmesh
../../makesdna
@@ -47,4 +48,8 @@ set(SRC
uvedit_parametrizer.h
)
+if(WITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
+endif()
+
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 d236b18a8fd..dfa15d2de4f 100644
--- a/source/blender/editors/uvedit/SConscript
+++ b/source/blender/editors/uvedit/SConscript
@@ -1,10 +1,41 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
+defs = []
+
sources = env.Glob('*.c')
-incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs = '../include ../../blenlib ../../blenfont ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
incs += ' ../../bmesh ../../makesrna #/intern/opennl/extern ../../gpu ../../blenloader'
-env.BlenderLib ( 'bf_editors_uvedit', sources, Split(incs), [], libtype=['core'], priority=[45] )
+if env['WITH_BF_INTERNATIONAL']:
+ defs.append('WITH_INTERNATIONAL')
+
+env.BlenderLib ( 'bf_editors_uvedit', sources, Split(incs), defs, libtype=['core'], priority=[45] )
diff --git a/source/blender/editors/uvedit/uvedit_buttons.c b/source/blender/editors/uvedit/uvedit_buttons.c
index 1c32c01b8f0..5c188628978 100644
--- a/source/blender/editors/uvedit/uvedit_buttons.c
+++ b/source/blender/editors/uvedit/uvedit_buttons.c
@@ -43,6 +43,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_mesh.h"
@@ -152,8 +154,10 @@ static void uvedit_vertex_buttons(const bContext *C, uiBlock *block)
}
uiBlockBeginAlign(block);
- uiDefButF(block, NUM, B_UVEDIT_VERTEX, "X:", 10, 10, 145, 19, &uvedit_old_center[0], -10 * imx, 10.0 * imx, step, digits, "");
- uiDefButF(block, NUM, B_UVEDIT_VERTEX, "Y:", 165, 10, 145, 19, &uvedit_old_center[1], -10 * imy, 10.0 * imy, step, digits, "");
+ uiDefButF(block, NUM, B_UVEDIT_VERTEX, IFACE_("X:"), 10, 10, 145, 19, &uvedit_old_center[0],
+ -10 * imx, 10.0 * imx, step, digits, "");
+ uiDefButF(block, NUM, B_UVEDIT_VERTEX, IFACE_("Y:"), 165, 10, 145, 19, &uvedit_old_center[1],
+ -10 * imy, 10.0 * imy, step, digits, "");
uiBlockEndAlign(block);
}
}
@@ -214,7 +218,7 @@ void ED_uvedit_buttons_register(ARegionType *art)
pt = MEM_callocN(sizeof(PanelType), "spacetype image panel uv");
strcpy(pt->idname, "IMAGE_PT_uv");
- strcpy(pt->label, "UV Vertex");
+ strcpy(pt->label, N_("UV Vertex")); /* XXX C panels are not available through RNA (bpy.types)! */
pt->draw = image_panel_uv;
pt->poll = image_panel_uv_poll;
BLI_addtail(&art->paneltypes, pt);
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index 9c2c300c530..ba4879b38ca 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -50,6 +50,7 @@
#include "BKE_tessmesh.h"
#include "BLI_array.h"
+#include "BLI_buffer.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -60,48 +61,49 @@
#include "ED_uvedit.h"
#include "UI_resources.h"
+#include "UI_interface.h"
+#include "UI_view2d.h"
#include "uvedit_intern.h"
void draw_image_cursor(SpaceImage *sima, ARegion *ar)
{
- float zoomx, zoomy, w, h;
- int width, height;
+ float zoom[2], x_fac, y_fac;
- ED_space_image_get_size(sima, &width, &height);
- ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
+ UI_view2d_getscale_inverse(&ar->v2d, &zoom[0], &zoom[1]);
- w = zoomx * width / 256.0f;
- h = zoomy * height / 256.0f;
+ mul_v2_fl(zoom, 256.0f * UI_DPI_FAC);
+ x_fac = zoom[0];
+ y_fac = zoom[1];
cpack(0xFFFFFF);
glTranslatef(sima->cursor[0], sima->cursor[1], 0.0);
- fdrawline(-0.05f / w, 0, 0, 0.05f / h);
- fdrawline(0, 0.05f / h, 0.05f / w, 0.0f);
- fdrawline(0.05f / w, 0.0f, 0.0f, -0.05f / h);
- fdrawline(0.0f, -0.05f / h, -0.05f / w, 0.0f);
+ 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);
+ fdrawline(0.0f, -0.05f * y_fac, -0.05f * x_fac, 0.0f);
setlinestyle(4);
cpack(0xFF);
- fdrawline(-0.05f / w, 0.0f, 0.0f, 0.05f / h);
- fdrawline(0.0f, 0.05f / h, 0.05f / w, 0.0f);
- fdrawline(0.05f / w, 0.0f, 0.0f, -0.05f / h);
- fdrawline(0.0f, -0.05f / h, -0.05f / w, 0.0f);
+ fdrawline(-0.05f * x_fac, 0.0f, 0.0f, 0.05f * y_fac);
+ fdrawline(0.0f, 0.05f * y_fac, 0.05f * x_fac, 0.0f);
+ fdrawline(0.05f * x_fac, 0.0f, 0.0f, -0.05f * y_fac);
+ fdrawline(0.0f, -0.05f * y_fac, -0.05f * x_fac, 0.0f);
setlinestyle(0.0f);
cpack(0x0);
- fdrawline(-0.020f / w, 0.0f, -0.1f / w, 0.0f);
- fdrawline(0.1f / w, 0.0f, 0.020f / w, 0.0f);
- fdrawline(0.0f, -0.020f / h, 0.0f, -0.1f / h);
- fdrawline(0.0f, 0.1f / h, 0.0f, 0.020f / h);
+ fdrawline(-0.020f * x_fac, 0.0f, -0.1f * x_fac, 0.0f);
+ fdrawline(0.1f * x_fac, 0.0f, 0.020f * x_fac, 0.0f);
+ fdrawline(0.0f, -0.020f * y_fac, 0.0f, -0.1f * y_fac);
+ fdrawline(0.0f, 0.1f * y_fac, 0.0f, 0.020f * y_fac);
setlinestyle(1);
cpack(0xFFFFFF);
- fdrawline(-0.020f / w, 0.0f, -0.1f / w, 0.0f);
- fdrawline(0.1f / w, 0.0f, 0.020f / w, 0.0f);
- fdrawline(0.0f, -0.020f / h, 0.0f, -0.1f / h);
- fdrawline(0.0f, 0.1f / h, 0.0f, 0.020f / h);
+ fdrawline(-0.020f * x_fac, 0.0f, -0.1f * x_fac, 0.0f);
+ fdrawline(0.1f * x_fac, 0.0f, 0.020f * x_fac, 0.0f);
+ fdrawline(0.0f, -0.020f * y_fac, 0.0f, -0.1f * y_fac);
+ fdrawline(0.0f, 0.1f * y_fac, 0.0f, 0.020f * y_fac);
glTranslatef(-sima->cursor[0], -sima->cursor[1], 0.0);
setlinestyle(0);
@@ -133,14 +135,15 @@ static void draw_uvs_shadow(Object *obedit)
BMIter iter, liter;
MLoopUV *luv;
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
/* draws the gray mesh when painting */
glColor3ub(112, 112, 112);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
glBegin(GL_LINE_LOOP);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
-
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
glVertex2fv(luv->uv);
}
glEnd();
@@ -169,10 +172,14 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
MTexPoly *tf;
MLoopUV *luv;
Image *ima = sima->image;
- BLI_array_declare(tf_uv);
- BLI_array_declare(tf_uvorig);
- float aspx, aspy, col[4], (*tf_uv)[2] = NULL, (*tf_uvorig)[2] = NULL;
- int i, j, nverts;
+ float aspx, aspy, col[4];
+ int i;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
+
+ BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_buffer_declare_static(vec2f, tf_uvorig_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
ED_space_image_get_uv_aspect(sima, &aspx, &aspy);
@@ -182,27 +189,20 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
float totarea = 0.0f, totuvarea = 0.0f, areadiff, uvarea, area;
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
-
- BLI_array_empty(tf_uv);
- BLI_array_empty(tf_uvorig);
- BLI_array_grow_items(tf_uv, efa->len);
- BLI_array_grow_items(tf_uvorig, efa->len);
-
- i = 0;
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ const int efa_len = efa->len;
+ float (*tf_uv)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, efa_len);
+ float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uvorig_buf, vec2f, efa_len);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
+ BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
copy_v2_v2(tf_uvorig[i], luv->uv);
-
- i++;
}
uv_poly_copy_aspect(tf_uvorig, tf_uv, aspx, aspy, efa->len);
totarea += BM_face_calc_area(efa);
- //totuvarea += tf_area(tf, efa->v4!=0);
- totuvarea += uv_poly_area(tf_uv, efa->len);
+ totuvarea += area_poly_v2(efa->len, tf_uv);
if (uvedit_face_visible_test(scene, ima, efa, tf)) {
BM_elem_flag_enable(efa, BM_ELEM_TAG);
@@ -222,7 +222,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
glBegin(GL_POLYGON);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
glVertex2fv(luv->uv);
}
glEnd();
@@ -232,26 +232,20 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
else {
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- area = BM_face_calc_area(efa) / totarea;
+ const int efa_len = efa->len;
+ float (*tf_uv)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, efa_len);
+ float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uvorig_buf, vec2f, efa_len);
- BLI_array_empty(tf_uv);
- BLI_array_empty(tf_uvorig);
- BLI_array_grow_items(tf_uv, efa->len);
- BLI_array_grow_items(tf_uvorig, efa->len);
-
- i = 0;
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ area = BM_face_calc_area(efa) / totarea;
+ BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
copy_v2_v2(tf_uvorig[i], luv->uv);
-
- i++;
}
uv_poly_copy_aspect(tf_uvorig, tf_uv, aspx, aspy, efa->len);
- //uvarea = tf_area(tf, efa->v4!=0) / totuvarea;
- uvarea = uv_poly_area(tf_uv, efa->len) / totuvarea;
+ uvarea = area_poly_v2(efa->len, tf_uv) / totuvarea;
if (area < FLT_EPSILON || uvarea < FLT_EPSILON)
areadiff = 1.0f;
@@ -265,7 +259,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
glBegin(GL_POLYGON);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
glVertex2fv(luv->uv);
}
glEnd();
@@ -276,68 +270,60 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
}
case SI_UVDT_STRETCH_ANGLE:
{
- float *uvang = NULL;
- float *ang = NULL;
- float (*av)[3] = NULL; /* use for 2d and 3d angle vectors */
- float (*auv)[2] = NULL;
float a;
- BLI_array_declare(uvang);
- BLI_array_declare(ang);
- BLI_array_declare(av);
- BLI_array_declare(auv);
+ BLI_buffer_declare_static(float, uvang_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_buffer_declare_static(float, ang_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_buffer_declare_static(vec3f, av_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_buffer_declare_static(vec2f, auv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
- col[3] = 0.5; /* hard coded alpha, not that nice */
+ col[3] = 0.5f; /* hard coded alpha, not that nice */
glShadeModel(GL_SMOOTH);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (uvedit_face_visible_test(scene, ima, efa, tf)) {
- nverts = efa->len;
+ const int efa_len = efa->len;
+ float (*tf_uv)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, efa_len);
+ float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uvorig_buf, vec2f, efa_len);
+ float *uvang = BLI_buffer_resize_data(&uvang_buf, float, efa_len);
+ float *ang = BLI_buffer_resize_data(&ang_buf, float, efa_len);
+ float (*av)[3] = (float (*)[3])BLI_buffer_resize_data(&av_buf, vec3f, efa_len);
+ float (*auv)[2] = (float (*)[2])BLI_buffer_resize_data(&auv_buf, vec2f, efa_len);
+ int j;
+
BM_elem_flag_enable(efa, BM_ELEM_TAG);
- BLI_array_empty(tf_uv);
- BLI_array_empty(tf_uvorig);
- BLI_array_empty(uvang);
- BLI_array_empty(ang);
- BLI_array_empty(av);
- BLI_array_empty(auv);
- BLI_array_grow_items(tf_uv, nverts);
- BLI_array_grow_items(tf_uvorig, nverts);
- BLI_array_grow_items(uvang, nverts);
- BLI_array_grow_items(ang, nverts);
- BLI_array_grow_items(av, nverts);
- BLI_array_grow_items(auv, nverts);
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
copy_v2_v2(tf_uvorig[i], luv->uv);
}
- uv_poly_copy_aspect(tf_uvorig, tf_uv, aspx, aspy, nverts);
+ uv_poly_copy_aspect(tf_uvorig, tf_uv, aspx, aspy, efa_len);
- j = nverts - 1;
+ j = efa_len - 1;
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
sub_v2_v2v2(auv[i], tf_uv[j], tf_uv[i]); normalize_v2(auv[i]);
sub_v3_v3v3(av[i], l->prev->v->co, l->v->co); normalize_v3(av[i]);
j = i;
}
- for (i = 0; i < nverts; i++) {
+ for (i = 0; i < efa_len; i++) {
#if 0
/* Simple but slow, better reuse normalized vectors
* (Not ported to bmesh, copied for reference) */
uvang1 = RAD2DEG(angle_v2v2v2(tf_uv[3], tf_uv[0], tf_uv[1]));
ang1 = RAD2DEG(angle_v3v3v3(efa->v4->co, efa->v1->co, efa->v2->co));
#endif
- uvang[i] = angle_normalized_v2v2(auv[i], auv[(i + 1) % nverts]);
- ang[i] = angle_normalized_v3v3(av[i], av[(i + 1) % nverts]);
+ uvang[i] = angle_normalized_v2v2(auv[i], auv[(i + 1) % efa_len]);
+ ang[i] = angle_normalized_v3v3(av[i], av[(i + 1) % efa_len]);
}
glBegin(GL_POLYGON);
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ 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));
glColor3fv(col);
@@ -352,19 +338,19 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
}
}
- glShadeModel(GL_FLAT);
+ BLI_buffer_free(&uvang_buf);
+ BLI_buffer_free(&ang_buf);
+ BLI_buffer_free(&av_buf);
+ BLI_buffer_free(&auv_buf);
- BLI_array_free(uvang);
- BLI_array_free(ang);
- BLI_array_free(av);
- BLI_array_free(auv);
+ glShadeModel(GL_FLAT);
break;
}
}
- BLI_array_free(tf_uv);
- BLI_array_free(tf_uvorig);
+ BLI_buffer_free(&tf_uv_buf);
+ BLI_buffer_free(&tf_uvorig_buf);
}
static void draw_uvs_other(Scene *scene, Object *obedit, Image *curimage)
@@ -453,6 +439,9 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
int drawfaces, interpedges;
Image *ima = sima->image;
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
+
activetf = EDBM_mtexpoly_active_get(em, &efa_act, FALSE, FALSE); /* will be set to NULL if hidden */
activef = BM_active_face_get(bm, FALSE, FALSE);
ts = scene->toolsettings;
@@ -502,7 +491,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glEnable(GL_BLEND);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (uvedit_face_visible_test(scene, ima, efa, tf)) {
BM_elem_flag_enable(efa, BM_ELEM_TAG);
@@ -515,7 +504,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glBegin(GL_POLYGON);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
glVertex2fv(luv->uv);
}
glEnd();
@@ -532,7 +521,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
/* would be nice to do this within a draw loop but most below are optional, so it would involve too many checks */
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (uvedit_face_visible_test(scene, ima, efa, tf)) {
BM_elem_flag_enable(efa, BM_ELEM_TAG);
@@ -549,7 +538,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
/* 3. draw active face stippled */
if (activef) {
- tf = CustomData_bmesh_get(&bm->pdata, activef->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(activef, cd_poly_tex_offset);
if (uvedit_face_visible_test(scene, ima, activef, tf)) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -560,7 +549,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glBegin(GL_POLYGON);
BM_ITER_ELEM (l, &liter, activef, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
glVertex2fv(luv->uv);
}
glEnd();
@@ -583,14 +572,14 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
- tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (tf) {
cpack(0x111111);
glBegin(GL_LINE_LOOP);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
glVertex2fv(luv->uv);
}
glEnd();
@@ -600,20 +589,11 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glBegin(GL_LINE_LOOP);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
glVertex2fv(luv->uv);
}
glEnd();
-#if 0
- glBegin(GL_LINE_STRIP);
- luv = CustomData_bmesh_get(&bm->ldata, efa->lbase->head.data, CD_MLOOPUV);
- glVertex2fv(luv->uv);
- luv = CustomData_bmesh_get(&bm->ldata, efa->lbase->next->head.data, CD_MLOOPUV);
- glVertex2fv(luv->uv);
- glEnd();
-#endif
-
setlinestyle(0);
}
}
@@ -629,7 +609,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glBegin(GL_LINE_LOOP);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
glVertex2fv(luv->uv);
}
glEnd();
@@ -645,7 +625,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glBegin(GL_LINE_LOOP);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
glVertex2fv(luv->uv);
}
glEnd();
@@ -671,7 +651,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
sel = (uvedit_uv_select_test(em, scene, l) ? 1 : 0);
glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2);
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
glVertex2fv(luv->uv);
}
glEnd();
@@ -691,9 +671,9 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2);
lastsel = sel;
}
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
glVertex2fv(luv->uv);
- luv = CustomData_bmesh_get(&bm->ldata, l->next->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
glVertex2fv(luv->uv);
}
glEnd();
@@ -708,7 +688,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glBegin(GL_LINE_LOOP);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
glVertex2fv(luv->uv);
}
glEnd();
@@ -776,7 +756,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (!uvedit_uv_select_test(em, scene, l))
bglVertex2fv(luv->uv);
}
@@ -794,7 +774,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (luv->flag & MLOOPUV_PINNED)
bglVertex2fv(luv->uv);
@@ -812,7 +792,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (uvedit_uv_select_test(em, scene, l))
bglVertex2fv(luv->uv);
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index b42875f20c2..d1893d639bb 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -50,8 +50,7 @@ struct BMVert;
int uvedit_face_visible_nolocal(struct Scene *scene, struct BMFace *efa);
/* geometric utilities */
-float uv_poly_area(float uv[][2], int len);
-void uv_poly_copy_aspect(float uv_orig [][2], float uv[][2], float aspx, float aspy, int len);
+void uv_poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len);
void uv_poly_center(struct BMEditMesh *em, struct BMFace *f, float r_cent[2]);
/* find nearest */
@@ -60,7 +59,7 @@ typedef struct NearestHit {
struct BMFace *efa;
struct MTexPoly *tf;
struct BMLoop *l, *nextl;
- struct MLoopUV *luv, *nextluv;
+ struct MLoopUV *luv, *luv_next;
int lindex; //index of loop within face
int vert1, vert2; //index in mesh of edge vertices
} NearestHit;
@@ -73,13 +72,14 @@ 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 */
void UV_OT_average_islands_scale(struct wmOperatorType *ot);
void UV_OT_cube_project(struct wmOperatorType *ot);
void UV_OT_cylinder_project(struct wmOperatorType *ot);
-void UV_OT_from_view(struct wmOperatorType *ot);
+void UV_OT_project_from_view(struct wmOperatorType *ot);
void UV_OT_minimize_stretch(struct wmOperatorType *ot);
void UV_OT_pack_islands(struct wmOperatorType *ot);
void UV_OT_reset(struct wmOperatorType *ot);
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index a384c777aab..a3a1e6534bf 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -113,7 +113,7 @@ static int ED_operator_uvedit_can_uv_sculpt(struct bContext *C)
return ED_space_image_show_uvedit(sima, obedit) && !(toolsettings->use_uv_sculpt);
}
-static int UNUSED_FUNCTION(ED_operator_uvmap_mesh) (bContext * C)
+static int UNUSED_FUNCTION(ED_operator_uvmap_mesh) (bContext *C)
{
Object *ob = CTX_data_active_object(C);
@@ -159,7 +159,7 @@ void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *i
if (node && is_image_texture_node(node)) {
node->id = &ima->id;
- ED_node_generic_update(bmain, ma->nodetree, node);
+ ED_node_tag_update_nodetree(bmain, ma->nodetree);
}
}
@@ -199,6 +199,8 @@ void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *im
else {
BMFace *efa;
+ int cd_poly_tex_offset;
+
/* old shading system, assign image to selected faces */
#ifdef USE_SWITCH_ASPECT
float prev_aspect[2], fprev_aspect;
@@ -220,9 +222,11 @@ void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *im
update = 1;
}
+ cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
+
/* now assign to all visible faces */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (uvedit_face_visible_test(scene, previma, efa, tf) &&
(selected == TRUE || uvedit_face_select_test(scene, em, efa)))
@@ -243,7 +247,7 @@ void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *im
BMLoop *l;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->uv[0] *= fprev_aspect;
luv->uv[0] /= faspect;
@@ -274,6 +278,7 @@ static int uvedit_set_tile(Object *obedit, Image *ima, int curtile)
BMFace *efa;
BMIter iter;
MTexPoly *tf;
+ int cd_poly_tex_offset;
/* verify if we have something to do */
if (!ima || !ED_uvedit_test(obedit))
@@ -288,10 +293,12 @@ static int uvedit_set_tile(Object *obedit, Image *ima, int curtile)
em = BMEdit_FromObject(obedit);
+ cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
+
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT))
tf->tile = curtile; /* set tile index */
}
@@ -344,15 +351,18 @@ int uvedit_face_select_test(Scene *scene, BMEditMesh *em, BMFace *efa)
{
ToolSettings *ts = scene->toolsettings;
- if (ts->uv_flag & UV_SYNC_SELECTION)
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
return (BM_elem_flag_test(efa, BM_ELEM_SELECT));
+ }
else {
BMLoop *l;
MLoopUV *luv;
BMIter liter;
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */
+
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (!(luv->flag & MLOOPUV_VERTSEL))
return 0;
}
@@ -376,8 +386,10 @@ int uvedit_face_select_enable(Scene *scene, BMEditMesh *em, BMFace *efa, const s
MLoopUV *luv;
BMIter liter;
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */
+
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag |= MLOOPUV_VERTSEL;
}
@@ -399,8 +411,10 @@ int uvedit_face_select_disable(Scene *scene, BMEditMesh *em, BMFace *efa)
MLoopUV *luv;
BMIter liter;
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */
+
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag &= ~MLOOPUV_VERTSEL;
}
@@ -503,7 +517,9 @@ int uvedit_uv_select_test(BMEditMesh *em, Scene *scene, BMLoop *l)
return BM_elem_flag_test(l->v, BM_ELEM_SELECT);
}
else {
- MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */
+
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
return luv->flag & MLOOPUV_VERTSEL;
}
@@ -524,7 +540,8 @@ void uvedit_uv_select_enable(BMEditMesh *em, Scene *scene, BMLoop *l, const shor
}
}
else {
- MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag |= MLOOPUV_VERTSEL;
}
@@ -541,7 +558,8 @@ void uvedit_uv_select_disable(BMEditMesh *em, Scene *scene, BMLoop *l)
BM_vert_select_set(em->bm, l->v, FALSE);
}
else {
- MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag &= ~MLOOPUV_VERTSEL;
}
@@ -565,29 +583,18 @@ void uv_poly_center(BMEditMesh *em, BMFace *f, float r_cent[2])
MLoopUV *luv;
BMIter liter;
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */
+
zero_v2(r_cent);
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
add_v2_v2(r_cent, luv->uv);
}
mul_v2_fl(r_cent, 1.0f / (float)f->len);
}
-float uv_poly_area(float uv[][2], int len)
-{
- //BMESH_TODO: make this not suck
- //maybe use scanfill? I dunno.
-
- if (len >= 4)
- return area_tri_v2(uv[0], uv[1], uv[2]) + area_tri_v2(uv[0], uv[2], uv[3]);
- else
- return area_tri_v2(uv[0], uv[1], uv[2]);
-
- return 1.0;
-}
-
void uv_poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len)
{
int i;
@@ -607,17 +614,20 @@ int ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float r_min[2], f
MLoopUV *luv;
int sel;
+ 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);
+
INIT_MINMAX2(r_min, r_max);
sel = 0;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_uv_select_test(em, scene, l)) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
minmax_v2v2_v2(r_min, r_max, luv->uv);
sel = 1;
}
@@ -637,14 +647,17 @@ static int ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[2
MLoopUV *luv;
unsigned int sel = 0;
+ 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);
+
zero_v2(co);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (uvedit_uv_select_test(em, scene, l)) {
add_v2_v2(co, luv->uv);
sel++;
@@ -685,26 +698,29 @@ void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MLoopUV *luv, *nextluv;
+ MLoopUV *luv, *luv_next;
float mindist_squared, dist_squared;
int i;
+ 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);
+
mindist_squared = 1e10f;
memset(hit, 0, sizeof(*hit));
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
i = 0;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- nextluv = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
- dist_squared = dist_squared_to_line_segment_v2(co, luv->uv, nextluv->uv);
+ dist_squared = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv);
if (dist_squared < mindist_squared) {
hit->tf = tf;
@@ -713,7 +729,7 @@ void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float
hit->l = l;
hit->nextl = l->next;
hit->luv = luv;
- hit->nextluv = nextluv;
+ hit->luv_next = luv_next;
hit->lindex = i;
hit->vert1 = BM_elem_index_get(hit->l->v);
hit->vert2 = BM_elem_index_get(hit->l->next->v);
@@ -733,16 +749,18 @@ static void find_nearest_uv_face(Scene *scene, Image *ima, BMEditMesh *em, const
BMIter iter;
float mindist, dist, cent[2];
+ const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
+
mindist = 1e10f;
memset(hit, 0, sizeof(*hit));
/*this will fill in hit.vert1 and hit.vert2*/
uv_find_nearest_edge(scene, ima, em, co, hit);
hit->l = hit->nextl = NULL;
- hit->luv = hit->nextluv = NULL;
+ hit->luv = hit->luv_next = NULL;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
@@ -766,6 +784,7 @@ static int nearest_uv_between(BMEditMesh *em, BMFace *efa, int UNUSED(nverts), i
BMIter iter;
float m[2], v1[2], v2[2], c1, c2, *uv1 = NULL, /* *uv2, */ /* UNUSED */ *uv3 = NULL;
int id1, id2, i;
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
id1 = (id + efa->len - 1) % efa->len;
id2 = (id + efa->len + 1) % efa->len;
@@ -774,7 +793,7 @@ static int nearest_uv_between(BMEditMesh *em, BMFace *efa, int UNUSED(nverts), i
i = 0;
BM_ITER_ELEM (l, &iter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (i == id1) {
uv1 = luv->uv;
@@ -816,10 +835,13 @@ void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em,
float mindist, dist;
int i;
+ 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);
+
/*this will fill in hit.vert1 and hit.vert2*/
uv_find_nearest_edge(scene, ima, em, co, hit);
hit->l = hit->nextl = NULL;
- hit->luv = hit->nextluv = NULL;
+ hit->luv = hit->luv_next = NULL;
mindist = 1e10f;
memset(hit, 0, sizeof(*hit));
@@ -827,13 +849,13 @@ void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em,
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
i = 0;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (penalty && uvedit_uv_select_test(em, scene, l))
dist = fabsf(co[0] - luv->uv[0]) + penalty[0] + fabsf(co[1] - luv->uv[1]) + penalty[1];
@@ -852,7 +874,7 @@ void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em,
hit->l = l;
hit->nextl = l->next;
hit->luv = luv;
- hit->nextluv = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV);
+ hit->luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
hit->tf = tf;
hit->efa = efa;
hit->lindex = i;
@@ -875,16 +897,19 @@ int ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, const float c
float mindist, dist;
int found = FALSE;
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+ const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
+
mindist = 1e10f;
copy_v2_v2(r_uv, co);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
dist = fabsf(co[0] - luv->uv[0]) + fabsf(co[1] - luv->uv[1]);
if (dist <= mindist) {
@@ -988,7 +1013,7 @@ static int select_edgeloop_uv_edge_tag_faces(BMEditMesh *em, UvMapVert *first1,
}
static int select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestHit *hit,
- float limit[2], const short extend)
+ float limit[2], const bool extend)
{
BMFace *efa;
BMIter iter, liter;
@@ -998,9 +1023,11 @@ static int select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestHit
UvMapVert *iterv1, *iterv2;
int a, looking, nverts, starttotf, select;
+ const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
+
/* setup */
- EDBM_index_arrays_init(em, 0, 0, 1);
- vmap = EDBM_uv_vert_map_create(em, 0, 0, limit);
+ EDBM_index_arrays_ensure(em, BM_FACE);
+ vmap = EDBM_uv_vert_map_create(em, 0, limit);
BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
@@ -1031,7 +1058,7 @@ static int select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestHit
/* find correct valence edges which are not tagged yet, but connect to tagged one */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!BM_elem_flag_test(efa, BM_ELEM_TAG) && uvedit_face_visible_test(scene, ima, efa, tf)) {
nverts = efa->len;
@@ -1091,14 +1118,13 @@ static int select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestHit
/* cleanup */
EDBM_uv_vert_map_free(vmap);
- EDBM_index_arrays_free(em);
return (select) ? 1 : -1;
}
/*********************** linked select ***********************/
-static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float limit[2], NearestHit *hit, int extend)
+static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float limit[2], NearestHit *hit, bool extend)
{
BMFace *efa;
BMLoop *l;
@@ -1111,8 +1137,11 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float
unsigned int a;
char *flag;
- EDBM_index_arrays_init(em, 0, 0, 1); /* we can use this too */
- vmap = EDBM_uv_vert_map_create(em, 1, 1, limit);
+ 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);
+
+ EDBM_index_arrays_ensure(em, BM_FACE); /* we can use this too */
+ vmap = EDBM_uv_vert_map_create(em, 1, limit);
if (vmap == NULL)
return;
@@ -1122,11 +1151,11 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float
if (!hit) {
BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ 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 = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (luv->flag & MLOOPUV_VERTSEL) {
stack[stacksize] = a;
@@ -1200,7 +1229,7 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float
a = 0;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (flag[a])
luv->flag |= MLOOPUV_VERTSEL;
@@ -1219,7 +1248,7 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (luv->flag & MLOOPUV_VERTSEL)
break;
@@ -1240,7 +1269,7 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag &= ~MLOOPUV_VERTSEL;
}
@@ -1257,7 +1286,7 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag |= MLOOPUV_VERTSEL;
}
@@ -1270,7 +1299,6 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float
MEM_freeN(stack);
MEM_freeN(flag);
EDBM_uv_vert_map_free(vmap);
- EDBM_index_arrays_free(em);
}
/* WATCH IT: this returns first selected UV,
@@ -1280,14 +1308,17 @@ static float *uv_sel_co_from_eve(Scene *scene, Image *ima, BMEditMesh *em, BMVer
BMIter liter;
BMLoop *l;
+ 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);
+
BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) {
- MTexPoly *tf = CustomData_bmesh_get(&em->bm->pdata, l->f->head.data, CD_MTEXPOLY);
+ MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(l->f, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, l->f, tf))
continue;
if (uvedit_uv_select_test(em, scene, l)) {
- MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
return luv->uv;
}
}
@@ -1299,17 +1330,18 @@ static float *uv_sel_co_from_eve(Scene *scene, Image *ima, BMEditMesh *em, BMVer
static void weld_align_uv(bContext *C, int tool)
{
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BMEdit_FromObject(obedit);
SpaceImage *sima;
Scene *scene;
- Object *obedit;
Image *ima;
- BMEditMesh *em;
MTexPoly *tf;
float cent[2], min[2], max[2];
-
+
+ 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);
+
scene = CTX_data_scene(C);
- obedit = CTX_data_edit_object(C);
- em = BMEdit_FromObject(obedit);
ima = CTX_data_edit_image(C);
sima = CTX_wm_space_image(C);
@@ -1321,14 +1353,14 @@ static void weld_align_uv(bContext *C, int tool)
BMLoop *l;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_uv_select_test(em, scene, l)) {
- MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
minmax_v2v2_v2(min, max, luv->uv);
}
}
@@ -1345,13 +1377,13 @@ static void weld_align_uv(bContext *C, int tool)
BMLoop *l;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_uv_select_test(em, scene, l)) {
- MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->uv[0] = cent[0];
}
@@ -1365,13 +1397,13 @@ static void weld_align_uv(bContext *C, int tool)
BMLoop *l;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_uv_select_test(em, scene, l)) {
- MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->uv[1] = cent[1];
}
@@ -1394,7 +1426,7 @@ static void weld_align_uv(bContext *C, int tool)
/* tag verts with a selected UV */
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) {
- tf = CustomData_bmesh_get(&em->bm->pdata, l->f->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(l->f, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, l->f, tf))
continue;
@@ -1484,13 +1516,13 @@ static void weld_align_uv(bContext *C, int tool)
/* go over all verts except for endpoints */
for (i = 0; i < BLI_array_count(eve_line); i++) {
BM_ITER_ELEM (l, &liter, eve_line[i], BM_LOOPS_OF_VERT) {
- tf = CustomData_bmesh_get(&em->bm->pdata, l->f->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(l->f, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, l->f, tf))
continue;
if (uvedit_uv_select_test(em, scene, l)) {
- MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
/* Projection of point (x, y) over line (x1, y1, x2, y2) along X axis:
* new_y = (y2 - y1) / (x2 - x1) * (x - x1) + y1
* Maybe this should be a BLI func? Or is it already existing?
@@ -1550,7 +1582,7 @@ static void UV_OT_align(wmOperatorType *ot)
/* api callbacks */
ot->exec = align_exec;
- ot->poll = ED_operator_image_active; /* requires space image */;
+ ot->poll = ED_operator_uvedit; /* requires space image */;
/* properties */
RNA_def_enum(ot->srna, "axis", axis_items, 'a', "Axis", "Axis to align UV locations on");
@@ -1569,9 +1601,9 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
SpaceImage *sima;
Scene *scene;
- Object *obedit;
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BMEdit_FromObject(obedit);
Image *ima;
- BMEditMesh *em;
MTexPoly *tf;
int uv_a_index;
int uv_b_index;
@@ -1582,10 +1614,11 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
BMFace *efa;
BMLoop *l;
+ 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);
+
sima = CTX_wm_space_image(C);
scene = CTX_data_scene(C);
- obedit = CTX_data_edit_object(C);
- em = BMEdit_FromObject(obedit);
ima = CTX_data_edit_image(C);
if (use_unselected == FALSE) {
@@ -1596,13 +1629,13 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
/* TODO, use qsort as with MESH_OT_remove_doubles, this isn't optimal */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_uv_select_test(em, scene, l)) {
- MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
UVvert vert;
vert.uv_loop = luv;
vert.weld = FALSE;
@@ -1659,12 +1692,12 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
BLI_array_declare(loop_arr_unselected);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (uvedit_uv_select_test(em, scene, l)) {
BLI_array_append(loop_arr, luv);
}
@@ -1753,6 +1786,9 @@ static void select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int act
MTexPoly *tf;
MLoopUV *luv;
+ 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 (ts->uv_flag & UV_SYNC_SELECTION) {
switch (action) {
@@ -1775,13 +1811,13 @@ static void select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int act
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (luv->flag & MLOOPUV_VERTSEL) {
action = SEL_DESELECT;
@@ -1793,13 +1829,13 @@ static void select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int act
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
switch (action) {
case SEL_SELECT:
@@ -1873,7 +1909,7 @@ static int sticky_select(float *limit, int hitv[4], int v, float *hituv[4], floa
return 0;
}
-static int mouse_select(bContext *C, const float co[2], int extend, int loop)
+static int mouse_select(bContext *C, const float co[2], bool extend, bool loop)
{
SpaceImage *sima = CTX_wm_space_image(C);
Scene *scene = CTX_data_scene(C);
@@ -1894,6 +1930,9 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop)
BLI_array_declare(hituv);
float penalty[2];
+ 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);
+
/* notice 'limit' is the same no matter the zoom level, since this is like
* remove doubles and could annoying if it joined points when zoomed out.
* 'penalty' is in screen pixel space otherwise zooming in on a uv-vert and
@@ -1972,7 +2011,7 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop)
hitv[hit.lindex] = hit.vert1;
hitv[(hit.lindex + 1) % hit.efa->len] = hit.vert2;
hituv[hit.lindex] = hit.luv->uv;
- hituv[(hit.lindex + 1) % hit.efa->len] = hit.nextluv->uv;
+ hituv[(hit.lindex + 1) % hit.efa->len] = hit.luv_next->uv;
hitlen = hit.efa->len;
}
@@ -1994,7 +2033,7 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop)
BLI_array_grow_items(hituv, hit.efa->len);
i = 0;
BM_ITER_ELEM (l, &liter, hit.efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
hituv[i] = luv->uv;
hitv[i] = BM_elem_index_get(l->v);
i++;
@@ -2080,12 +2119,12 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop)
/* deselect */
if (select == 0) {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (sticky_select(limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen))
uvedit_uv_select_disable(em, scene, l);
}
@@ -2095,12 +2134,12 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop)
/* select */
else {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (sticky_select(limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen))
uvedit_uv_select_enable(em, scene, l, FALSE);
}
@@ -2132,13 +2171,13 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop)
/* select sticky uvs */
if (sticky != SI_STICKY_DISABLE) {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (sticky == SI_STICKY_DISABLE) continue;
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (sticky_select(limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen))
uvedit_uv_select_enable(em, scene, l, FALSE);
@@ -2188,16 +2227,16 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop)
static int select_exec(bContext *C, wmOperator *op)
{
float co[2];
- int extend, loop;
+ bool extend, loop;
RNA_float_get_array(op->ptr, "location", co);
extend = RNA_boolean_get(op->ptr, "extend");
- loop = 0;
+ loop = false;
return mouse_select(C, co, extend, loop);
}
-static int select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
float co[2];
@@ -2219,7 +2258,7 @@ static void UV_OT_select(wmOperatorType *ot)
/* api callbacks */
ot->exec = select_exec;
ot->invoke = select_invoke;
- ot->poll = ED_operator_image_active; /* requires space image */;
+ ot->poll = ED_operator_uvedit; /* requires space image */;
/* properties */
RNA_def_boolean(ot->srna, "extend", 0,
@@ -2233,16 +2272,16 @@ static void UV_OT_select(wmOperatorType *ot)
static int select_loop_exec(bContext *C, wmOperator *op)
{
float co[2];
- int extend, loop;
+ bool extend, loop;
RNA_float_get_array(op->ptr, "location", co);
extend = RNA_boolean_get(op->ptr, "extend");
- loop = 1;
+ loop = true;
return mouse_select(C, co, extend, loop);
}
-static int select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
float co[2];
@@ -2264,7 +2303,7 @@ static void UV_OT_select_loop(wmOperatorType *ot)
/* api callbacks */
ot->exec = select_loop_exec;
ot->invoke = select_loop_invoke;
- ot->poll = ED_operator_image_active; /* requires space image */;
+ ot->poll = ED_operator_uvedit; /* requires space image */;
/* properties */
RNA_def_boolean(ot->srna, "extend", 0,
@@ -2275,7 +2314,7 @@ static void UV_OT_select_loop(wmOperatorType *ot)
/* ******************** linked select operator **************** */
-static int select_linked_internal(bContext *C, wmOperator *op, wmEvent *event, int pick)
+static int select_linked_internal(bContext *C, wmOperator *op, const wmEvent *event, int pick)
{
SpaceImage *sima = CTX_wm_space_image(C);
Scene *scene = CTX_data_scene(C);
@@ -2338,14 +2377,14 @@ static void UV_OT_select_linked(wmOperatorType *ot)
/* api callbacks */
ot->exec = select_linked_exec;
- ot->poll = ED_operator_image_active; /* requires space image */
+ ot->poll = ED_operator_uvedit; /* requires space image */
/* properties */
RNA_def_boolean(ot->srna, "extend", 0,
"Extend", "Extend selection rather than clearing the existing selection");
}
-static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
return select_linked_internal(C, op, event, 1);
}
@@ -2366,7 +2405,7 @@ static void UV_OT_select_linked_pick(wmOperatorType *ot)
/* api callbacks */
ot->invoke = select_linked_pick_invoke;
ot->exec = select_linked_pick_exec;
- ot->poll = ED_operator_image_active; /* requires space image */;
+ ot->poll = ED_operator_uvedit; /* requires space image */;
/* properties */
RNA_def_boolean(ot->srna, "extend", 0,
@@ -2395,23 +2434,27 @@ static int select_split_exec(bContext *C, wmOperator *op)
MLoopUV *luv;
short change = FALSE;
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
+
if (ts->uv_flag & UV_SYNC_SELECTION) {
BKE_report(op->reports, RPT_ERROR, "Cannot split selection when sync selection is enabled");
return OPERATOR_CANCELLED;
}
+
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
int is_sel = FALSE;
int is_unsel = FALSE;
- tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
/* are we all selected? */
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (luv->flag & MLOOPUV_VERTSEL) {
is_sel = TRUE;
@@ -2428,7 +2471,7 @@ static int select_split_exec(bContext *C, wmOperator *op)
if (is_sel && is_unsel) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag &= ~MLOOPUV_VERTSEL;
}
@@ -2474,6 +2517,9 @@ static int unlink_selection_exec(bContext *C, wmOperator *op)
MTexPoly *tf;
MLoopUV *luv;
+ 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 (ts->uv_flag & UV_SYNC_SELECTION) {
BKE_report(op->reports, RPT_ERROR, "Cannot unlink selection when sync selection is enabled");
return OPERATOR_CANCELLED;
@@ -2482,12 +2528,12 @@ static int unlink_selection_exec(bContext *C, wmOperator *op)
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
int desel = 0;
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (!(luv->flag & MLOOPUV_VERTSEL)) {
desel = 1;
@@ -2497,7 +2543,7 @@ static int unlink_selection_exec(bContext *C, wmOperator *op)
if (desel) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag &= ~MLOOPUV_VERTSEL;
}
}
@@ -2584,7 +2630,7 @@ static void uv_faces_do_sticky(SpaceImage *sima, Scene *scene, Object *obedit, s
/* now select tagged verts */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
+ /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) {
@@ -2608,8 +2654,8 @@ static void uv_faces_do_sticky(SpaceImage *sima, Scene *scene, Object *obedit, s
uvedit_pixel_to_float(sima, limit, 0.05);
- EDBM_index_arrays_init(em, 0, 0, 1);
- vmap = EDBM_uv_vert_map_create(em, 0, 0, limit);
+ EDBM_index_arrays_ensure(em, BM_FACE);
+ vmap = EDBM_uv_vert_map_create(em, 0, limit);
/* verts are numbered above in make_uv_vert_map_EM, make sure this stays true! */
if (vmap == NULL) {
@@ -2619,7 +2665,7 @@ static void uv_faces_do_sticky(SpaceImage *sima, Scene *scene, Object *obedit, s
efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL);
for (efa_index = 0; efa; efa = BM_iter_step(&iter), efa_index++) {
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
- /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
+ /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (select)
@@ -2648,7 +2694,7 @@ static void uv_faces_do_sticky(SpaceImage *sima, Scene *scene, Object *obedit, s
if (efa_index != vlist_iter->f) {
BMLoop *l_other;
efa_vlist = EDBM_face_at_index(em, vlist_iter->f);
- /* tf_vlist = CustomData_bmesh_get(&em->bm->pdata, efa_vlist->head.data, CD_MTEXPOLY); */ /* UNUSED */
+ /* tf_vlist = BM_ELEM_CD_GET_VOID_P(efa_vlist, cd_poly_tex_offset); */ /* UNUSED */
l_other = BM_iter_at_index(em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->tfindex);
@@ -2662,7 +2708,6 @@ static void uv_faces_do_sticky(SpaceImage *sima, Scene *scene, Object *obedit, s
}
}
}
- EDBM_index_arrays_free(em);
EDBM_uv_vert_map_free(vmap);
}
@@ -2701,6 +2746,9 @@ static int border_select_exec(bContext *C, wmOperator *op)
(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);
+
/* get rectangle from operator */
WM_operator_properties_border_to_rcti(op, &rect);
@@ -2726,7 +2774,7 @@ static int border_select_exec(bContext *C, wmOperator *op)
/* assume not touched */
BM_elem_flag_disable(efa, BM_ELEM_TAG);
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (uvedit_face_visible_test(scene, ima, efa, tf)) {
uv_poly_center(em, efa, cent);
if (BLI_rctf_isect_pt_v(&rectf, cent)) {
@@ -2746,11 +2794,11 @@ static int border_select_exec(bContext *C, wmOperator *op)
change = 1;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (!pinned || (ts->uv_flag & UV_SYNC_SELECTION) ) {
@@ -2794,7 +2842,7 @@ static void UV_OT_select_border(wmOperatorType *ot)
ot->invoke = WM_border_select_invoke;
ot->exec = border_select_exec;
ot->modal = WM_border_select_modal;
- ot->poll = ED_operator_image_active; /* requires space image */;
+ ot->poll = ED_operator_uvedit; /* requires space image */;
ot->cancel = WM_border_select_cancel;
/* flags */
@@ -2850,6 +2898,8 @@ static int circle_select_exec(bContext *C, wmOperator *op)
(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);
+
/* get operator properties */
select = (gesture_mode == GESTURE_MODAL_SELECT);
x = RNA_int_get(op->ptr, "x");
@@ -2890,7 +2940,7 @@ static int circle_select_exec(bContext *C, wmOperator *op)
else {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
change |= select_uv_inside_ellipse(em, scene, select, offset, ellipse, l, luv);
}
}
@@ -2916,7 +2966,7 @@ static void UV_OT_circle_select(wmOperatorType *ot)
ot->invoke = WM_gesture_circle_invoke;
ot->modal = WM_gesture_circle_modal;
ot->exec = circle_select_exec;
- ot->poll = ED_operator_image_active; /* requires space image */;
+ ot->poll = ED_operator_uvedit; /* requires space image */;
ot->cancel = WM_gesture_circle_cancel;
/* flags */
@@ -2945,6 +2995,9 @@ static int do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mov
(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);
+
BMIter iter, liter;
BMFace *efa;
@@ -2980,11 +3033,11 @@ static int do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mov
}
else { /* Vert Sel */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ 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) {
if ((select) != (uvedit_uv_select_test(em, scene, l))) {
- MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
UI_view2d_view_to_region(&ar->v2d, luv->uv[0], luv->uv[1], &screen_uv[0], &screen_uv[1]);
if (BLI_rcti_isect_pt_v(&rect, screen_uv) &&
BLI_lasso_is_point_inside(mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED))
@@ -3042,7 +3095,7 @@ static void UV_OT_select_lasso(wmOperatorType *ot)
ot->invoke = WM_gesture_lasso_invoke;
ot->modal = WM_gesture_lasso_modal;
ot->exec = uv_lasso_select_exec;
- ot->poll = ED_operator_image_active;
+ ot->poll = ED_operator_uvedit;
ot->cancel = WM_gesture_lasso_cancel;
/* flags */
@@ -3117,7 +3170,7 @@ static void UV_OT_snap_cursor(wmOperatorType *ot)
/* api callbacks */
ot->exec = snap_cursor_exec;
- ot->poll = ED_operator_image_active; /* requires space image */;
+ ot->poll = ED_operator_uvedit; /* requires space image */;
/* properties */
RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UVs to");
@@ -3135,14 +3188,17 @@ static int snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, SpaceIma
MLoopUV *luv;
short change = 0;
+ 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);
+
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tface = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tface))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_uv_select_test(em, scene, l)) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
copy_v2_v2(luv->uv, sima->cursor);
change = 1;
}
@@ -3162,11 +3218,13 @@ static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obe
MTexPoly *tface;
MLoopUV *luv;
short change = FALSE;
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
/* index every vert that has a selected UV using it, but only once so as to
* get unique indices and to count how much to malloc */
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- tface = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_MTEXPOLY);
+ tface = BM_ELEM_CD_GET_VOID_P(f, cd_poly_tex_offset);
if (uvedit_face_visible_test(scene, ima, f, tface)) {
BM_elem_flag_enable(f, BM_ELEM_TAG);
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
@@ -3189,15 +3247,14 @@ static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obe
if (BM_elem_flag_test(lsub->f, BM_ELEM_TAG) && /* face: visible */
!BM_elem_flag_test(lsub, BM_ELEM_TAG)) /* loop: unselected */
{
-
- luv = CustomData_bmesh_get(&bm->ldata, lsub->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(lsub, cd_loop_uv_offset);
add_v2_v2(uv, luv->uv);
uv_tot++;
}
}
if (uv_tot) {
- luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
mul_v2_v2fl(luv->uv, uv, 1.0f / (float)uv_tot);
change = TRUE;
}
@@ -3222,18 +3279,21 @@ static int snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit)
float w, h;
short change = 0;
+ 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);
+
ED_space_image_get_size(sima, &width, &height);
w = (float)width;
h = (float)height;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tface = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tface))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_uv_select_test(em, scene, l)) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
snap_uv_to_pixel(luv->uv, w, h);
}
}
@@ -3290,7 +3350,7 @@ static void UV_OT_snap_selected(wmOperatorType *ot)
/* api callbacks */
ot->exec = snap_selection_exec;
- ot->poll = ED_operator_image_active; /* requires space image */;
+ ot->poll = ED_operator_uvedit; /* requires space image */;
/* properties */
RNA_def_enum(ot->srna, "target", target_items, 0, "Target", "Target to snap the selected UVs to");
@@ -3311,13 +3371,16 @@ static int pin_exec(bContext *C, wmOperator *op)
MLoopUV *luv;
int clear = RNA_boolean_get(op->ptr, "clear");
+ 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);
+
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tface = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tface))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (!clear) {
if (uvedit_uv_select_test(em, scene, l))
@@ -3365,13 +3428,16 @@ static int select_pinned_exec(bContext *C, wmOperator *UNUSED(op))
MTexPoly *tface;
MLoopUV *luv;
+ 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);
+
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tface = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tface))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (luv->flag & MLOOPUV_PINNED)
uvedit_uv_select_enable(em, scene, l, FALSE);
@@ -3403,15 +3469,17 @@ static void UV_OT_select_pinned(wmOperatorType *ot)
#define UV_SEL_TEST(luv, bool_test) ((((luv)->flag & MLOOPUV_VERTSEL) == MLOOPUV_VERTSEL) == bool_test)
/* is every UV vert selected or unselected depending on bool_test */
-static int bm_face_is_all_uv_sel(BMesh *bm, BMFace *f, int bool_test)
+static int bm_face_is_all_uv_sel(BMFace *f, bool select_test,
+ const int cd_loop_uv_offset)
{
BMLoop *l_iter;
BMLoop *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
- MLoopUV *luv = CustomData_bmesh_get(&bm->ldata, l_iter->head.data, CD_MLOOPUV);
- if (!UV_SEL_TEST(luv, bool_test)) {
+
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
+ if (!UV_SEL_TEST(luv, select_test)) {
return FALSE;
}
} while ((l_iter = l_iter->next) != l_first);
@@ -3435,6 +3503,9 @@ static int hide_exec(bContext *C, wmOperator *op)
Image *ima = sima ? sima->image : NULL;
const int use_face_center = (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);
+
if (ts->uv_flag & UV_SYNC_SELECTION) {
EDBM_mesh_hide(em, swap);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
@@ -3445,14 +3516,14 @@ static int hide_exec(bContext *C, wmOperator *op)
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
int hide = 0;
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+ tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf)) {
continue;
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (UV_SEL_TEST(luv, !swap)) {
hide = 1;
@@ -3466,15 +3537,15 @@ static int hide_exec(bContext *C, wmOperator *op)
if (use_face_center) {
if (em->selectmode == SCE_SELECT_FACE) {
/* check that every UV is selected */
- if (bm_face_is_all_uv_sel(em->bm, efa, TRUE) == !swap) {
+ if (bm_face_is_all_uv_sel(efa, true, cd_loop_uv_offset) == !swap) {
BM_face_select_set(em->bm, efa, FALSE);
}
uvedit_face_select_disable(scene, em, efa);
}
else {
- if (bm_face_is_all_uv_sel(em->bm, efa, TRUE) == !swap) {
+ if (bm_face_is_all_uv_sel(efa, true, cd_loop_uv_offset) == !swap) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (UV_SEL_TEST(luv, !swap)) {
BM_vert_select_set(em->bm, l->v, FALSE);
}
@@ -3485,14 +3556,14 @@ static int hide_exec(bContext *C, wmOperator *op)
}
else if (em->selectmode == SCE_SELECT_FACE) {
/* check if a UV is de-selected */
- if (bm_face_is_all_uv_sel(em->bm, efa, FALSE) != !swap) {
+ if (bm_face_is_all_uv_sel(efa, false, cd_loop_uv_offset) != !swap) {
BM_face_select_set(em->bm, efa, FALSE);
uvedit_face_select_disable(scene, em, efa);
}
}
else {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (UV_SEL_TEST(luv, !swap)) {
BM_vert_select_set(em->bm, l->v, FALSE);
if (!swap) luv->flag &= ~MLOOPUV_VERTSEL;
@@ -3546,6 +3617,8 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE);
const int stickymode = sima ? (sima->sticky != SI_STICKY_DISABLE) : 1;
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
/* note on tagging, selecting faces needs to be delayed so it doesn't select the verts and
* confuse our checks on selected verts. */
@@ -3562,7 +3635,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
BM_elem_flag_disable(efa, BM_ELEM_TAG);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag |= MLOOPUV_VERTSEL;
}
/* BM_face_select_set(em->bm, efa, TRUE); */
@@ -3583,7 +3656,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
if (!totsel) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag |= MLOOPUV_VERTSEL;
}
/* BM_face_select_set(em->bm, efa, TRUE); */
@@ -3598,7 +3671,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag |= MLOOPUV_VERTSEL;
}
}
@@ -3614,7 +3687,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
BM_elem_flag_disable(efa, BM_ELEM_TAG);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag |= MLOOPUV_VERTSEL;
}
/* BM_face_select_set(em->bm, efa, TRUE); */
@@ -3628,7 +3701,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag |= MLOOPUV_VERTSEL;
}
}
@@ -3675,7 +3748,7 @@ static int set_2d_cursor_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int set_2d_cursor_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int set_2d_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
float location[2];
@@ -3696,7 +3769,7 @@ static void UV_OT_cursor_set(wmOperatorType *ot)
/* api callbacks */
ot->exec = set_2d_cursor_exec;
ot->invoke = set_2d_cursor_invoke;
- ot->poll = ED_operator_image_active; /* requires space image */;
+ ot->poll = ED_operator_uvedit; /* requires space image */;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -3726,7 +3799,7 @@ static int set_tile_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int set_tile_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int set_tile_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceImage *sima = CTX_wm_space_image(C);
Image *ima = CTX_data_edit_image(C);
@@ -3795,8 +3868,8 @@ static int seams_from_islands_exec(bContext *C, wmOperator *op)
}
/* This code sets editvert->tmp.l to the index. This will be useful later on. */
- EDBM_index_arrays_init(em, 0, 0, 1);
- vmap = EDBM_uv_vert_map_create(em, 0, 0, limit);
+ EDBM_index_arrays_ensure(em, BM_FACE);
+ vmap = EDBM_uv_vert_map_create(em, 0, limit);
BM_ITER_MESH (editedge, &iter, bm, BM_EDGES_OF_MESH) {
/* flags to determine if we uv is separated from first editface match */
@@ -3875,7 +3948,6 @@ static int seams_from_islands_exec(bContext *C, wmOperator *op)
me->drawflag |= ME_DRAWSEAMS;
EDBM_uv_vert_map_free(vmap);
- EDBM_index_arrays_free(em);
DAG_id_tag_update(&me->id, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
@@ -3981,7 +4053,7 @@ void ED_operatortypes_uvedit(void)
WM_operatortype_append(UV_OT_average_islands_scale);
WM_operatortype_append(UV_OT_cube_project);
WM_operatortype_append(UV_OT_cylinder_project);
- WM_operatortype_append(UV_OT_from_view);
+ WM_operatortype_append(UV_OT_project_from_view);
WM_operatortype_append(UV_OT_minimize_stretch);
WM_operatortype_append(UV_OT_pack_islands);
WM_operatortype_append(UV_OT_reset);
diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index 8703234122a..bf5fc9a3021 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -60,6 +60,7 @@
{ /*printf("Assertion %s:%d\n", __FILE__, __LINE__); abort();*/ } (void)0
#define param_warning(message) \
{ /*printf("Warning %s:%d: %s\n", __FILE__, __LINE__, message);*/ } (void)0
+#if 0
#define param_test_equals_ptr(str, a, b) \
if (a != b) \
{ /*printf("Equals %s => %p != %p\n", str, a, b);*/ } (void)0
@@ -67,6 +68,7 @@
if (a != b) \
{ /*printf("Equals %s => %d != %d\n", str, a, b);*/ } (void)0
#endif
+#endif
typedef enum PBool {
P_TRUE = 1,
P_FALSE = 0
@@ -707,7 +709,7 @@ static void p_face_restore_uvs(PFace *f)
static PVert *p_vert_add(PHandle *handle, PHashKey key, const float co[3], PEdge *e)
{
- PVert *v = (PVert *)BLI_memarena_alloc(handle->arena, sizeof *v);
+ PVert *v = (PVert *)BLI_memarena_alloc(handle->arena, sizeof(*v));
copy_v3_v3(v->co, co);
v->u.key = key;
v->edge = e;
@@ -730,7 +732,7 @@ static PVert *p_vert_lookup(PHandle *handle, PHashKey key, const float co[3], PE
static PVert *p_vert_copy(PChart *chart, PVert *v)
{
- PVert *nv = (PVert *)BLI_memarena_alloc(chart->handle->arena, sizeof *nv);
+ PVert *nv = (PVert *)BLI_memarena_alloc(chart->handle->arena, sizeof(*nv));
copy_v3_v3(nv->co, v->co);
nv->uv[0] = v->uv[0];
@@ -784,7 +786,7 @@ static int p_face_exists(ParamHandle *phandle, ParamKey *pvkeys, int i1, int i2,
static PChart *p_chart_new(PHandle *handle)
{
- PChart *chart = (PChart *)MEM_callocN(sizeof *chart, "PChart");
+ PChart *chart = (PChart *)MEM_callocN(sizeof(*chart), "PChart");
chart->handle = handle;
return chart;
@@ -902,7 +904,7 @@ static PBool p_edge_connect_pair(PHandle *handle, PEdge *e, PEdge ***stack, PBoo
static int p_connect_pairs(PHandle *handle, PBool impl)
{
- PEdge **stackbase = MEM_mallocN(sizeof *stackbase * phash_size(handle->hash_faces), "Pstackbase");
+ PEdge **stackbase = MEM_mallocN(sizeof(*stackbase) * phash_size(handle->hash_faces), "Pstackbase");
PEdge **stack = stackbase;
PFace *f, *first;
PEdge *e, *e1, *e2;
@@ -997,7 +999,7 @@ static void p_split_vert(PChart *chart, PEdge *e)
static PChart **p_split_charts(PHandle *handle, PChart *chart, int ncharts)
{
- PChart **charts = MEM_mallocN(sizeof *charts * ncharts, "PCharts"), *nchart;
+ PChart **charts = MEM_mallocN(sizeof(*charts) * ncharts, "PCharts"), *nchart;
PFace *f, *nextf;
int i;
@@ -1039,12 +1041,12 @@ static PFace *p_face_add(PHandle *handle)
PEdge *e1, *e2, *e3;
/* allocate */
- f = (PFace *)BLI_memarena_alloc(handle->arena, sizeof *f);
+ f = (PFace *)BLI_memarena_alloc(handle->arena, sizeof(*f));
f->flag = 0; /* init ! */
- e1 = (PEdge *)BLI_memarena_alloc(handle->arena, sizeof *e1);
- e2 = (PEdge *)BLI_memarena_alloc(handle->arena, sizeof *e2);
- e3 = (PEdge *)BLI_memarena_alloc(handle->arena, sizeof *e3);
+ e1 = (PEdge *)BLI_memarena_alloc(handle->arena, sizeof(*e1));
+ e2 = (PEdge *)BLI_memarena_alloc(handle->arena, sizeof(*e2));
+ e3 = (PEdge *)BLI_memarena_alloc(handle->arena, sizeof(*e3));
/* set up edges */
f->edge = e1;
@@ -1057,7 +1059,7 @@ static PFace *p_face_add(PHandle *handle)
e1->pair = NULL;
e2->pair = NULL;
e3->pair = NULL;
-
+
e1->flag = 0;
e2->flag = 0;
e3->flag = 0;
@@ -3047,6 +3049,8 @@ static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
PVert *v, *pin1 = chart->u.lscm.pin1, *pin2 = chart->u.lscm.pin2;
PFace *f;
float *alpha = chart->u.lscm.abf_alpha;
+ float area_pinned_up, area_pinned_down;
+ bool flip_faces;
int row;
nlMakeCurrent(chart->u.lscm.context);
@@ -3085,6 +3089,26 @@ static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
}
}
+ /* detect up direction based on pinned vertices */
+ area_pinned_up = 0.0f;
+ area_pinned_down = 0.0f;
+
+ for (f = chart->faces; f; f = f->nextlink) {
+ PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
+ PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
+
+ if ((v1->flag & PVERT_PIN) && (v2->flag & PVERT_PIN) && (v3->flag & PVERT_PIN)) {
+ float area = p_face_uv_area_signed(f);
+
+ if (area > 0.0f)
+ area_pinned_up += area;
+ else
+ area_pinned_down -= area;
+ }
+ }
+
+ flip_faces = (area_pinned_down > area_pinned_up);
+
/* construct matrix */
nlBegin(NL_MATRIX);
@@ -3105,11 +3129,17 @@ static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
else
p_face_angles(f, &a1, &a2, &a3);
+ if (flip_faces) {
+ SWAP(float, a2, a3);
+ SWAP(PEdge *, e2, e3);
+ SWAP(PVert *, v2, v3);
+ }
+
sina1 = sin(a1);
sina2 = sin(a2);
sina3 = sin(a3);
- sinmax = MAX3(sina1, sina2, sina3);
+ sinmax = max_fff(sina1, sina2, sina3);
/* shift vertices to find most stable order */
if (sina3 != sinmax) {
@@ -3644,7 +3674,7 @@ static PBool p_triangle_inside(SmoothTriangle *t, float co[2])
static SmoothNode *p_node_new(MemArena *arena, SmoothTriangle **tri, int ntri, float *bmin, float *bmax, int depth)
{
- SmoothNode *node = BLI_memarena_alloc(arena, sizeof *node);
+ SmoothNode *node = BLI_memarena_alloc(arena, sizeof(*node));
int axis, i, t1size = 0, t2size = 0;
float split, /* mi, */ /* UNUSED */ mx;
SmoothTriangle **t1, **t2, *t;
@@ -4084,7 +4114,7 @@ static void p_smooth(PChart *chart)
ParamHandle *param_construct_begin(void)
{
- PHandle *handle = MEM_callocN(sizeof *handle, "PHandle");
+ PHandle *handle = MEM_callocN(sizeof(*handle), "PHandle");
handle->construction_chart = p_chart_new(handle);
handle->state = PHANDLE_STATE_ALLOCATED;
handle->arena = BLI_memarena_new((1 << 16), "param construct arena");
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index 4ca642690c4..4c56a016176 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -41,6 +41,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
+#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLI_math.h"
#include "BLI_math_vector.h"
@@ -72,7 +73,7 @@
/* ********************** smart stitch operator *********************** */
-/* object that stores display data for previewing before accepting stitching */
+/* object that stores display data for previewing before confirming stitching */
typedef struct StitchPreviewer {
/* here we'll store the preview triangle indices of the mesh */
float *preview_polys;
@@ -87,7 +88,7 @@ typedef struct StitchPreviewer {
unsigned int num_stitchable;
unsigned int num_unstitchable;
unsigned int preview_uvs;
- /* ...and here we'll store the triangles*/
+ /* ...and here we'll store the static island triangles*/
float *static_tris;
unsigned int num_static_tris;
} StitchPreviewer;
@@ -100,11 +101,13 @@ struct IslandStitchData;
typedef struct IslandStitchData {
/* rotation can be used only for edges, for vertices there is no such notion */
float rotation;
+ float rotation_neg;
float translation[2];
/* Used for rotation, the island will rotate around this point */
float medianPoint[2];
int numOfElements;
int num_rot_elements;
+ int num_rot_elements_neg;
/* flag to remember if island has been added for preview */
char addedForPreview;
/* flag an island to be considered for determining static island */
@@ -124,14 +127,19 @@ typedef struct UvEdge {
unsigned int uv1;
unsigned int uv2;
/* general use flag (Used to check if edge is boundary here, and propagates to adjacency elements) */
- char flag;
- /* element that guarantees element->face has the face on element->tfindex and element->tfindex+1 is the second uv */
+ unsigned char flag;
+ /* element that guarantees element->face has the edge on element->tfindex and element->tfindex+1 is the second uv */
UvElement *element;
+ /* next uv edge with the same exact vertices as this one.. Calculated at startup to save time */
+ struct UvEdge *next;
+ /* point to first of common edges. Needed for iteration */
+ struct UvEdge *first;
} UvEdge;
/* stitch state object */
typedef struct StitchState {
+ float aspect;
/* use limit flag */
char use_limit;
/* limit to operator, same as original operator */
@@ -156,19 +164,26 @@ typedef struct StitchState {
float *normals;
/* edge storage */
UvEdge *edges;
+ /* hash for quick lookup of edges */
+ GHash *edge_hash;
/* count of separate uvs and edges */
- int total_boundary_edges;
+ int total_separate_edges;
int total_separate_uvs;
/* hold selection related information */
- UvElement **selection_stack;
+ void **selection_stack;
int selection_size;
/* island that stays in place */
int static_island;
/* store number of primitives per face so that we can allocate the active island buffer later */
unsigned int *tris_per_island;
+ /* vert or edge mode used for stitching */
+ char mode;
+ /* handle for drawing */
void *draw_handle;
+ /* preview data */
+ StitchPreviewer *stitch_preview;
} StitchState;
typedef struct PreviewPosition {
@@ -176,7 +191,7 @@ typedef struct PreviewPosition {
int polycount_position;
} PreviewPosition;
/*
- * defines for UvElement flags
+ * defines for UvElement/UcEdge flags
*/
#define STITCH_SELECTED 1
#define STITCH_STITCHABLE 2
@@ -186,83 +201,79 @@ typedef struct PreviewPosition {
#define STITCH_NO_PREVIEW -1
-/* previewer stuff (see uvedit_intern.h for more info) */
-static StitchPreviewer *_stitch_preview;
+enum StitchModes {
+ STITCH_VERT,
+ STITCH_EDGE
+};
/* constructor */
static StitchPreviewer *stitch_preview_init(void)
{
- _stitch_preview = MEM_mallocN(sizeof(StitchPreviewer), "stitch_previewer");
- _stitch_preview->preview_polys = NULL;
- _stitch_preview->preview_stitchable = NULL;
- _stitch_preview->preview_unstitchable = NULL;
- _stitch_preview->uvs_per_polygon = NULL;
+ StitchPreviewer *stitch_preview;
- _stitch_preview->preview_uvs = 0;
- _stitch_preview->num_polys = 0;
- _stitch_preview->num_stitchable = 0;
- _stitch_preview->num_unstitchable = 0;
+ stitch_preview = MEM_mallocN(sizeof(StitchPreviewer), "stitch_previewer");
+ stitch_preview->preview_polys = NULL;
+ stitch_preview->preview_stitchable = NULL;
+ stitch_preview->preview_unstitchable = NULL;
+ stitch_preview->uvs_per_polygon = NULL;
- _stitch_preview->static_tris = NULL;
+ stitch_preview->preview_uvs = 0;
+ stitch_preview->num_polys = 0;
+ stitch_preview->num_stitchable = 0;
+ stitch_preview->num_unstitchable = 0;
- _stitch_preview->num_static_tris = 0;
+ stitch_preview->static_tris = NULL;
- return _stitch_preview;
+ stitch_preview->num_static_tris = 0;
+
+ return stitch_preview;
}
/* destructor...yeah this should be C++ :) */
-static void stitch_preview_delete(void)
+static void stitch_preview_delete(StitchPreviewer *stitch_preview)
{
- if (_stitch_preview) {
- if (_stitch_preview->preview_polys) {
- MEM_freeN(_stitch_preview->preview_polys);
- _stitch_preview->preview_polys = NULL;
+ if (stitch_preview) {
+ if (stitch_preview->preview_polys) {
+ MEM_freeN(stitch_preview->preview_polys);
+ stitch_preview->preview_polys = NULL;
}
- if (_stitch_preview->uvs_per_polygon) {
- MEM_freeN(_stitch_preview->uvs_per_polygon);
- _stitch_preview->uvs_per_polygon = NULL;
+ if (stitch_preview->uvs_per_polygon) {
+ MEM_freeN(stitch_preview->uvs_per_polygon);
+ stitch_preview->uvs_per_polygon = NULL;
}
- if (_stitch_preview->preview_stitchable) {
- MEM_freeN(_stitch_preview->preview_stitchable);
- _stitch_preview->preview_stitchable = NULL;
+ if (stitch_preview->preview_stitchable) {
+ MEM_freeN(stitch_preview->preview_stitchable);
+ stitch_preview->preview_stitchable = NULL;
}
- if (_stitch_preview->preview_unstitchable) {
- MEM_freeN(_stitch_preview->preview_unstitchable);
- _stitch_preview->preview_unstitchable = NULL;
+ if (stitch_preview->preview_unstitchable) {
+ MEM_freeN(stitch_preview->preview_unstitchable);
+ stitch_preview->preview_unstitchable = NULL;
}
- if (_stitch_preview->static_tris) {
- MEM_freeN(_stitch_preview->static_tris);
- _stitch_preview->static_tris = NULL;
+ if (stitch_preview->static_tris) {
+ MEM_freeN(stitch_preview->static_tris);
+ stitch_preview->static_tris = NULL;
}
-
- MEM_freeN(_stitch_preview);
- _stitch_preview = NULL;
+ MEM_freeN(stitch_preview);
}
}
-
-/* "getter method" */
-static StitchPreviewer *uv_get_stitch_previewer(void)
-{
- return _stitch_preview;
-}
-
#define HEADER_LENGTH 256
/* This function updates the header of the UV editor when the stitch tool updates its settings */
-static void stitch_update_header(StitchState *stitch_state, bContext *C)
+static void stitch_update_header(StitchState *state, bContext *C)
{
- static char str[] = "(S)nap %s, (M)idpoints %s, (L)imit %.2f (Alt Wheel adjust) %s, Switch (I)sland, shift select vertices";
+ static char str[] = "Mode(TAB) %s, (S)nap %s, (M)idpoints %s, (L)imit %.2f (Alt Wheel adjust) %s, Switch (I)sland, shift select vertices";
char msg[HEADER_LENGTH];
ScrArea *sa = CTX_wm_area(C);
if (sa) {
BLI_snprintf(msg, HEADER_LENGTH, str,
- stitch_state->snap_islands ? "On" : "Off",
- stitch_state->midpoints ? "On" : "Off",
- stitch_state->limit_dist,
- stitch_state->use_limit ? "On" : "Off");
+ state->mode == STITCH_VERT ? "Vertex" : "Edge",
+ state->snap_islands ? "On" : "Off",
+ state->midpoints ? "On" : "Off",
+ state->limit_dist,
+ state->use_limit ? "On" : "Off");
ED_area_headerprint(sa, msg);
}
@@ -278,44 +289,42 @@ static int getNumOfIslandUvs(UvElementMap *elementMap, int island)
}
}
-static void stitch_uv_rotate(float rotation, float medianPoint[2], float uv[2])
+static void stitch_uv_rotate(float mat[2][2], float medianPoint[2], float uv[2], float aspect)
{
float uv_rotation_result[2];
- uv[0] -= medianPoint[0];
- uv[1] -= medianPoint[1];
+ uv[1] /= aspect;
- uv_rotation_result[0] = cosf(rotation) * uv[0] - sinf(rotation) * uv[1];
- uv_rotation_result[1] = sinf(rotation) * uv[0] + cosf(rotation) * uv[1];
+ sub_v2_v2(uv, medianPoint);
+ mul_v2_m2v2(uv_rotation_result, mat, uv);
+ add_v2_v2v2(uv, uv_rotation_result, medianPoint);
- uv[0] = uv_rotation_result[0] + medianPoint[0];
- uv[1] = uv_rotation_result[1] + medianPoint[1];
+ uv[1] *= aspect;
}
+/* check if two uvelements are stitchable. This should only operate on -different- separate UvElements */
static int stitch_check_uvs_stitchable(UvElement *element, UvElement *element_iter, StitchState *state)
{
float limit;
- int do_limit;
if (element_iter == element) {
return 0;
}
limit = state->limit_dist;
- do_limit = state->use_limit;
- if (do_limit) {
- MLoopUV *luv_orig, *luv_iter;
- BMLoop *l_orig, *l_iter;
+ if (state->use_limit) {
+ MLoopUV *luv, *luv_iter;
+ BMLoop *l;
- l_orig = element->l;
- luv_orig = CustomData_bmesh_get(&state->em->bm->ldata, l_orig->head.data, CD_MLOOPUV);
- l_iter = element_iter->l;
- luv_iter = CustomData_bmesh_get(&state->em->bm->ldata, l_iter->head.data, CD_MLOOPUV);
+ l = element->l;
+ luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+ l = element_iter->l;
+ luv_iter = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
- if (fabsf(luv_orig->uv[0] - luv_iter->uv[0]) < limit &&
- fabsf(luv_orig->uv[1] - luv_iter->uv[1]) < limit)
+ if (fabsf(luv->uv[0] - luv_iter->uv[0]) < limit &&
+ fabsf(luv->uv[1] - luv_iter->uv[1]) < limit)
{
return 1;
}
@@ -328,6 +337,46 @@ static int stitch_check_uvs_stitchable(UvElement *element, UvElement *element_it
}
}
+static int stitch_check_edges_stitchable(UvEdge *edge, UvEdge *edge_iter, StitchState *state)
+{
+ float limit;
+
+ if (edge_iter == edge) {
+ return 0;
+ }
+
+ limit = state->limit_dist;
+
+ if (state->use_limit) {
+ BMLoop *l;
+ MLoopUV *luv_orig1, *luv_iter1;
+ MLoopUV *luv_orig2, *luv_iter2;
+
+ l = state->uvs[edge->uv1]->l;
+ luv_orig1 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+ l = state->uvs[edge_iter->uv1]->l;
+ luv_iter1 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ l = state->uvs[edge->uv2]->l;
+ luv_orig2 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+ l = state->uvs[edge_iter->uv2]->l;
+ luv_iter2 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ if (fabsf(luv_orig1->uv[0] - luv_iter1->uv[0]) < limit &&
+ fabsf(luv_orig1->uv[1] - luv_iter1->uv[1]) < limit &&
+ fabsf(luv_orig2->uv[0] - luv_iter2->uv[0]) < limit &&
+ fabsf(luv_orig2->uv[1] - luv_iter2->uv[1]) < limit)
+ {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+ }
+ else {
+ return 1;
+ }
+}
static int stitch_check_uvs_state_stitchable(UvElement *element, UvElement *element_iter, StitchState *state)
{
@@ -341,6 +390,17 @@ static int stitch_check_uvs_state_stitchable(UvElement *element, UvElement *elem
}
+static int stitch_check_edges_state_stitchable(UvEdge *edge, UvEdge *edge_iter, StitchState *state)
+{
+ if ((state->snap_islands && edge->element->island == edge_iter->element->island) ||
+ (!state->midpoints && edge->element->island == edge_iter->element->island))
+ {
+ return 0;
+ }
+
+ return stitch_check_edges_stitchable(edge, edge_iter, state);
+}
+
/* calculate snapping for islands */
static void stitch_calculate_island_snapping(StitchState *state, PreviewPosition *preview_position, StitchPreviewer *preview, IslandStitchData *island_stitch_data, int final)
{
@@ -350,15 +410,40 @@ static void stitch_calculate_island_snapping(StitchState *state, PreviewPosition
for (i = 0; i < state->element_map->totalIslands; i++) {
if (island_stitch_data[i].addedForPreview) {
int numOfIslandUVs = 0, j;
+ int totelem = island_stitch_data[i].num_rot_elements_neg + island_stitch_data[i].num_rot_elements;
+ float rotation;
+ float rotation_mat[2][2];
/* check to avoid divide by 0 */
- if (island_stitch_data[i].num_rot_elements > 0) {
+ if (island_stitch_data[i].num_rot_elements > 1)
island_stitch_data[i].rotation /= island_stitch_data[i].num_rot_elements;
+
+ if (island_stitch_data[i].num_rot_elements_neg > 1)
+ island_stitch_data[i].rotation_neg /= island_stitch_data[i].num_rot_elements_neg;
+
+ if (island_stitch_data[i].numOfElements > 1) {
island_stitch_data[i].medianPoint[0] /= island_stitch_data[i].numOfElements;
island_stitch_data[i].medianPoint[1] /= island_stitch_data[i].numOfElements;
+
+ island_stitch_data[i].translation[0] /= island_stitch_data[i].numOfElements;
+ island_stitch_data[i].translation[1] /= island_stitch_data[i].numOfElements;
+ }
+
+ island_stitch_data[i].medianPoint[1] /= state->aspect;
+ if ((island_stitch_data[i].rotation + island_stitch_data[i].rotation_neg < (float)M_PI_2) ||
+ island_stitch_data[i].num_rot_elements == 0 || island_stitch_data[i].num_rot_elements_neg == 0)
+ {
+ rotation = (island_stitch_data[i].rotation * island_stitch_data[i].num_rot_elements -
+ island_stitch_data[i].rotation_neg *
+ island_stitch_data[i].num_rot_elements_neg) / totelem;
}
- island_stitch_data[i].translation[0] /= island_stitch_data[i].numOfElements;
- island_stitch_data[i].translation[1] /= island_stitch_data[i].numOfElements;
+ else {
+ rotation = (island_stitch_data[i].rotation * island_stitch_data[i].num_rot_elements +
+ (2.0f * (float)M_PI - island_stitch_data[i].rotation_neg) *
+ island_stitch_data[i].num_rot_elements_neg) / totelem;
+ }
+
+ rotate_m2(rotation_mat, rotation);
numOfIslandUVs = getNumOfIslandUvs(state->element_map, i);
element = &state->element_map->buf[state->element_map->islandIndices[i]];
for (j = 0; j < numOfIslandUVs; j++, element++) {
@@ -372,16 +457,17 @@ static void stitch_calculate_island_snapping(StitchState *state, PreviewPosition
if (final) {
- stitch_uv_rotate(island_stitch_data[i].rotation, island_stitch_data[i].medianPoint, luv->uv);
+ stitch_uv_rotate(rotation_mat, island_stitch_data[i].medianPoint, luv->uv, state->aspect);
add_v2_v2(luv->uv, island_stitch_data[i].translation);
}
else {
- int face_preview_pos = preview_position[BM_elem_index_get(element->face)].data_position;
- stitch_uv_rotate(island_stitch_data[i].rotation, island_stitch_data[i].medianPoint,
- preview->preview_polys + face_preview_pos + 2 * element->tfindex);
+ int face_preview_pos = preview_position[BM_elem_index_get(element->l->f)].data_position;
+
+ stitch_uv_rotate(rotation_mat, island_stitch_data[i].medianPoint,
+ preview->preview_polys + face_preview_pos + 2 * element->tfindex, state->aspect);
add_v2_v2(preview->preview_polys + face_preview_pos + 2 * element->tfindex,
island_stitch_data[i].translation);
@@ -404,39 +490,48 @@ static void stitch_island_calculate_edge_rotation(UvEdge *edge, StitchState *sta
int index1, index2;
float rotation;
MLoopUV *luv1, *luv2;
- BMLoop *l1, *l2;
element1 = state->uvs[edge->uv1];
element2 = state->uvs[edge->uv2];
- l1 = element1->l;
- luv1 = CustomData_bmesh_get(&state->em->bm->ldata, l1->head.data, CD_MLOOPUV);
- l2 = element2->l;
- luv2 = CustomData_bmesh_get(&state->em->bm->ldata, l2->head.data, CD_MLOOPUV);
-
- index1 = uvfinal_map[element1 - state->element_map->buf];
- index2 = uvfinal_map[element2 - state->element_map->buf];
+ luv1 = CustomData_bmesh_get(&state->em->bm->ldata, element1->l->head.data, CD_MLOOPUV);
+ luv2 = CustomData_bmesh_get(&state->em->bm->ldata, element2->l->head.data, CD_MLOOPUV);
+ if (state->mode == STITCH_VERT) {
+ index1 = uvfinal_map[element1 - state->element_map->buf];
+ index2 = uvfinal_map[element2 - state->element_map->buf];
+ }
+ else {
+ index1 = edge->uv1;
+ index2 = edge->uv2;
+ }
/* the idea here is to take the directions of the edges and find the rotation between final and initial
* direction. This, using inner and outer vector products, gives the angle. Directions are differences so... */
uv1[0] = luv2->uv[0] - luv1->uv[0];
uv1[1] = luv2->uv[1] - luv1->uv[1];
+ uv1[1] /= state->aspect;
+
uv2[0] = uv_average[index2].uv[0] - uv_average[index1].uv[0];
uv2[1] = uv_average[index2].uv[1] - uv_average[index1].uv[1];
+ uv2[1] /= state->aspect;
+
normalize_v2(uv1);
normalize_v2(uv2);
- edgecos = uv1[0] * uv2[0] + uv1[1] * uv2[1];
- edgesin = uv1[0] * uv2[1] - uv2[0] * uv1[1];
-
- rotation = (edgesin > 0.0f) ?
- +acosf(max_ff(-1.0f, min_ff(1.0f, edgecos))) :
- -acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
+ edgecos = dot_v2v2(uv1, uv2);
+ edgesin = cross_v2v2(uv1, uv2);
+ rotation = acosf(max_ff(-1.0f, min_ff(1.0f, edgecos)));
- island_stitch_data[element1->island].num_rot_elements++;
- island_stitch_data[element1->island].rotation += rotation;
+ if (edgesin > 0.0f) {
+ island_stitch_data[element1->island].num_rot_elements++;
+ island_stitch_data[element1->island].rotation += rotation;
+ }
+ else {
+ island_stitch_data[element1->island].num_rot_elements_neg++;
+ island_stitch_data[element1->island].rotation_neg += rotation;
+ }
}
@@ -445,7 +540,8 @@ static void stitch_island_calculate_vert_rotation(UvElement *element, StitchStat
float edgecos = 1.0f, edgesin = 0.0f;
int index;
UvElement *element_iter;
- float rotation = 0;
+ float rotation = 0, rotation_neg = 0;
+ int rot_elem = 0, rot_elem_neg = 0;
BMLoop *l;
if (element->island == state->static_island && !state->midpoints)
@@ -461,7 +557,10 @@ static void stitch_island_calculate_vert_rotation(UvElement *element, StitchStat
if (element_iter->separate && stitch_check_uvs_state_stitchable(element, element_iter, state)) {
int index_tmp1, index_tmp2;
float normal[2];
- /* easily possible*/
+
+ /* only calculate rotation against static island uv verts */
+ if (!state->midpoints && element_iter->island != state->static_island)
+ continue;
index_tmp1 = element_iter - state->element_map->buf;
index_tmp1 = state->map[index_tmp1];
@@ -471,45 +570,136 @@ static void stitch_island_calculate_vert_rotation(UvElement *element, StitchStat
negate_v2_v2(normal, state->normals + index_tmp2 * 2);
edgecos = dot_v2v2(normal, state->normals + index_tmp1 * 2);
edgesin = cross_v2v2(normal, state->normals + index_tmp1 * 2);
- rotation += (edgesin > 0.0f) ? acosf(edgecos) : -acosf(edgecos);
+ if (edgesin > 0.0f) {
+ 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)));
+ rot_elem_neg++;
+ }
}
}
- if (state->midpoints)
+ if (state->midpoints) {
rotation /= 2.0f;
- island_stitch_data[element->island].num_rot_elements++;
+ rotation_neg /= 2.0f;
+ }
+ island_stitch_data[element->island].num_rot_elements += rot_elem;
island_stitch_data[element->island].rotation += rotation;
+ island_stitch_data[element->island].num_rot_elements_neg += rot_elem_neg;
+ island_stitch_data[element->island].rotation_neg += rotation_neg;
}
-static void stitch_state_delete(StitchState *stitch_state)
+static void state_delete(StitchState *state)
{
- if (stitch_state) {
- if (stitch_state->element_map) {
- EDBM_uv_element_map_free(stitch_state->element_map);
+ if (state) {
+ if (state->element_map) {
+ EDBM_uv_element_map_free(state->element_map);
}
- if (stitch_state->uvs) {
- MEM_freeN(stitch_state->uvs);
+ if (state->uvs) {
+ MEM_freeN(state->uvs);
}
- if (stitch_state->selection_stack) {
- MEM_freeN(stitch_state->selection_stack);
+ if (state->selection_stack) {
+ MEM_freeN(state->selection_stack);
}
- if (stitch_state->tris_per_island) {
- MEM_freeN(stitch_state->tris_per_island);
+ if (state->tris_per_island) {
+ MEM_freeN(state->tris_per_island);
}
- if (stitch_state->map) {
- MEM_freeN(stitch_state->map);
+ if (state->map) {
+ MEM_freeN(state->map);
}
- if (stitch_state->normals) {
- MEM_freeN(stitch_state->normals);
+ if (state->normals) {
+ MEM_freeN(state->normals);
}
- if (stitch_state->edges) {
- MEM_freeN(stitch_state->edges);
+ if (state->edges) {
+ MEM_freeN(state->edges);
}
- MEM_freeN(stitch_state);
+ if (state->stitch_preview) {
+ stitch_preview_delete(state->stitch_preview);
+ }
+ if (state->edge_hash) {
+ BLI_ghash_free(state->edge_hash, NULL, NULL);
+ }
+ MEM_freeN(state);
}
}
+static void stitch_uv_edge_generate_linked_edges(GHash *edge_hash, StitchState *state)
+{
+ UvEdge *edges = state->edges;
+ int *map = state->map;
+ UvElementMap *element_map = state->element_map;
+ UvElement *first_element = element_map->buf;
+ int i;
+
+ for (i = 0; i < state->total_separate_edges; i++) {
+ UvEdge *edge = edges + i;
+
+ if (edge->first)
+ continue;
+
+ /* only boundary edges can be stitched. Yes. Sorry about that :p */
+ if (edge->flag & STITCH_BOUNDARY) {
+ UvElement *element1 = state->uvs[edge->uv1];
+ UvElement *element2 = state->uvs[edge->uv2];
+
+ /* Now iterate through all faces and try to find edges sharing the same vertices */
+ UvElement *iter1 = element_map->vert[BM_elem_index_get(element1->l->v)];
+ UvEdge *last_set = edge;
+ int elemindex2 = BM_elem_index_get(element2->l->v);
+
+ edge->first = edge;
+
+ for (; iter1; iter1 = iter1->next) {
+ UvElement *iter2 = NULL;
+
+ /* check to see if other vertex of edge belongs to same vertex as */
+ if (BM_elem_index_get(iter1->l->next->v) == elemindex2)
+ iter2 = ED_uv_element_get(element_map, iter1->l->f, iter1->l->next);
+ else if (BM_elem_index_get(iter1->l->prev->v) == elemindex2)
+ iter2 = ED_uv_element_get(element_map, iter1->l->f, iter1->l->prev);
+
+ if (iter2) {
+ int index1 = map[iter1 - first_element];
+ int index2 = map[iter2 - first_element];
+
+ /* make certain we do not have the same edge! */
+ if (state->uvs[index2] != element2 && state->uvs[index1] != element1) {
+ UvEdge edgetmp;
+ UvEdge *edge2;
+
+
+ /* make sure the indices are well behaved */
+ if (index1 < index2) {
+ edgetmp.uv1 = index1;
+ edgetmp.uv2 = index2;
+ }
+ else {
+ edgetmp.uv1 = index2;
+ edgetmp.uv2 = index1;
+ }
+
+ /* get the edge from the hash */
+ edge2 = BLI_ghash_lookup(edge_hash, &edgetmp);
+
+ /* here I am taking care of non manifold case, assuming more than two matching edges.
+ * I am not too sure we want this though */
+ last_set->next = edge2;
+ last_set = edge2;
+ /* set first, similarly to uv elements. Now we can iterate among common edges easily */
+ edge2->first = edge;
+ }
+ }
+ }
+ }
+ else {
+ /* so stitchability code works */
+ edge->first = edge;
+ }
+ }
+}
/* checks for remote uvs that may be stitched with a certain uv, flags them if stitchable. */
@@ -526,9 +716,6 @@ static void determine_uv_stitchability(UvElement *element, StitchState *state, I
for (; element_iter; element_iter = element_iter->next) {
if (element_iter->separate) {
- if (element_iter == element) {
- continue;
- }
if (stitch_check_uvs_stitchable(element, element_iter, state)) {
island_stitch_data[element_iter->island].stitchableCandidate = 1;
island_stitch_data[element->island].stitchableCandidate = 1;
@@ -538,6 +725,19 @@ static void determine_uv_stitchability(UvElement *element, StitchState *state, I
}
}
+static void determine_uv_edge_stitchability(UvEdge *edge, StitchState *state, IslandStitchData *island_stitch_data)
+{
+ UvEdge *edge_iter = edge->first;
+
+ for (; edge_iter; edge_iter = edge_iter->next) {
+ if (stitch_check_edges_stitchable(edge, edge_iter, state)) {
+ island_stitch_data[edge_iter->element->island].stitchableCandidate = 1;
+ island_stitch_data[edge->element->island].stitchableCandidate = 1;
+ edge->flag |= STITCH_STITCHABLE_CANDIDATE;
+ }
+ }
+}
+
/* set preview buffer position of UV face in editface->tmp.l */
static void stitch_set_face_preview_buffer_position(BMFace *efa, StitchPreviewer *preview, PreviewPosition *preview_position)
@@ -555,7 +755,7 @@ static void stitch_set_face_preview_buffer_position(BMFace *efa, StitchPreviewer
/* setup face preview for all coincident uvs and their faces */
static void stitch_setup_face_preview_for_uv_group(UvElement *element, StitchState *state, IslandStitchData *island_stitch_data,
PreviewPosition *preview_position) {
- StitchPreviewer *preview = uv_get_stitch_previewer();
+ StitchPreviewer *preview = state->stitch_preview;
/* static island does not change so returning immediately */
if (state->snap_islands && !state->midpoints && state->static_island == element->island)
@@ -566,17 +766,17 @@ static void stitch_setup_face_preview_for_uv_group(UvElement *element, StitchSta
}
do {
- stitch_set_face_preview_buffer_position(element->face, preview, preview_position);
+ stitch_set_face_preview_buffer_position(element->l->f, preview, preview_position);
element = element->next;
} while (element && !element->separate);
}
/* checks if uvs are indeed stitchable and registers so that they can be shown in preview */
-static void stitch_validate_stichability(UvElement *element, StitchState *state, IslandStitchData *island_stitch_data,
+static void stitch_validate_uv_stichability(UvElement *element, StitchState *state, IslandStitchData *island_stitch_data,
PreviewPosition *preview_position) {
UvElement *element_iter;
- StitchPreviewer *preview;
+ StitchPreviewer *preview = state->stitch_preview;
int vert_index;
BMLoop *l;
@@ -584,7 +784,6 @@ static void stitch_validate_stichability(UvElement *element, StitchState *state,
vert_index = BM_elem_index_get(l->v);
- preview = uv_get_stitch_previewer();
element_iter = state->element_map->vert[vert_index];
for (; element_iter; element_iter = element_iter->next) {
@@ -608,6 +807,72 @@ static void stitch_validate_stichability(UvElement *element, StitchState *state,
}
}
+
+static void stitch_validate_edge_stichability(UvEdge *edge, StitchState *state, IslandStitchData *island_stitch_data,
+ PreviewPosition *preview_position) {
+ UvEdge *edge_iter = edge->first;
+ StitchPreviewer *preview = state->stitch_preview;
+
+ for (; edge_iter; edge_iter = edge_iter->next) {
+ if (edge_iter == edge)
+ continue;
+ if (stitch_check_edges_state_stitchable(edge, edge_iter, state)) {
+ if ((edge_iter->element->island == state->static_island) || (edge->element->island == state->static_island)) {
+ edge->flag |= STITCH_STITCHABLE;
+ preview->num_stitchable++;
+ stitch_setup_face_preview_for_uv_group(state->uvs[edge->uv1], state, island_stitch_data, preview_position);
+ stitch_setup_face_preview_for_uv_group(state->uvs[edge->uv2], state, island_stitch_data, preview_position);
+ return;
+ }
+ }
+ }
+
+ /* this can happen if the uvs to be stitched are not on a stitchable island */
+ if (!(edge->flag & STITCH_STITCHABLE)) {
+ preview->num_unstitchable++;
+ }
+}
+
+
+static void stitch_propagate_uv_final_position(UvElement *element, int index, PreviewPosition *preview_position, UVVertAverage *final_position, StitchState *state, char final, Scene *scene)
+{
+ StitchPreviewer *preview = state->stitch_preview;
+
+ if (element->flag & STITCH_STITCHABLE) {
+ UvElement *element_iter = element;
+ /* propagate to coincident uvs */
+ do {
+ BMLoop *l;
+ MLoopUV *luv;
+
+ l = element_iter->l;
+ luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ element_iter->flag |= STITCH_PROCESSED;
+ /* either flush to preview or to the MTFace, if final */
+ if (final) {
+ copy_v2_v2(luv->uv, final_position[index].uv);
+
+ uvedit_uv_select_enable(state->em, scene, l, FALSE);
+ }
+ else {
+ int face_preview_pos = preview_position[BM_elem_index_get(element_iter->l->f)].data_position;
+ if (face_preview_pos != STITCH_NO_PREVIEW) {
+ copy_v2_v2(preview->preview_polys + face_preview_pos + 2 * element_iter->tfindex,
+ final_position[index].uv);
+ }
+ }
+
+ /* end of calculations, keep only the selection flag */
+ if ( (!state->snap_islands) || ((!state->midpoints) && (element_iter->island == state->static_island))) {
+ element_iter->flag &= STITCH_SELECTED;
+ }
+
+ element_iter = element_iter->next;
+ } while (element_iter && !element_iter->separate);
+ }
+}
+
/* main processing function. It calculates preview and final positions. */
static int stitch_process_data(StitchState *state, Scene *scene, int final)
{
@@ -617,16 +882,17 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
int previous_island = state->static_island;
BMFace *efa;
BMIter iter;
- UVVertAverage *final_position;
+ UVVertAverage *final_position = NULL;
+
char stitch_midpoints = state->midpoints;
/* used to map uv indices to uvaverage indices for selection */
- unsigned int *uvfinal_map;
+ unsigned int *uvfinal_map = NULL;
/* per face preview position in preview buffer */
- PreviewPosition *preview_position;
+ PreviewPosition *preview_position = NULL;
/* cleanup previous preview */
- stitch_preview_delete();
- preview = stitch_preview_init();
+ stitch_preview_delete(state->stitch_preview);
+ preview = state->stitch_preview = stitch_preview_init();
if (preview == NULL)
return 0;
@@ -649,8 +915,14 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
*****************************************/
for (i = 0; i < state->selection_size; i++) {
- UvElement *element = state->selection_stack[i];
- determine_uv_stitchability(element, state, island_stitch_data);
+ if (state->mode == STITCH_VERT) {
+ UvElement *element = (UvElement *)state->selection_stack[i];
+ determine_uv_stitchability(element, state, island_stitch_data);
+ }
+ else {
+ UvEdge *edge = (UvEdge *)state->selection_stack[i];
+ determine_uv_edge_stitchability(edge, state, island_stitch_data);
+ }
}
/* set static island to one that is added for preview */
@@ -664,14 +936,26 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
}
for (i = 0; i < state->selection_size; i++) {
- UvElement *element = state->selection_stack[i];
- if (element->flag & STITCH_STITCHABLE_CANDIDATE) {
- element->flag &= ~STITCH_STITCHABLE_CANDIDATE;
- stitch_validate_stichability(element, state, island_stitch_data, preview_position);
+ if (state->mode == STITCH_VERT) {
+ UvElement *element = (UvElement *)state->selection_stack[i];
+ if (element->flag & STITCH_STITCHABLE_CANDIDATE) {
+ element->flag &= ~STITCH_STITCHABLE_CANDIDATE;
+ stitch_validate_uv_stichability(element, state, island_stitch_data, preview_position);
+ }
+ else {
+ /* add to preview for unstitchable */
+ preview->num_unstitchable++;
+ }
}
else {
- /* add to preview for unstitchable */
- preview->num_unstitchable++;
+ UvEdge *edge = (UvEdge *)state->selection_stack[i];
+ if (edge->flag & STITCH_STITCHABLE_CANDIDATE) {
+ edge->flag &= ~STITCH_STITCHABLE_CANDIDATE;
+ stitch_validate_edge_stichability(edge, state, island_stitch_data, preview_position);
+ }
+ else {
+ preview->num_unstitchable++;
+ }
}
}
@@ -686,7 +970,7 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
numOfIslandUVs = getNumOfIslandUvs(state->element_map, i);
element = &state->element_map->buf[state->element_map->islandIndices[i]];
for (j = 0; j < numOfIslandUVs; j++, element++) {
- stitch_set_face_preview_buffer_position(element->face, preview, preview_position);
+ stitch_set_face_preview_buffer_position(element->l->f, preview, preview_position);
}
}
}
@@ -701,11 +985,12 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
MLoopUV *luv;
unsigned int buffer_index = 0;
int stitchBufferIndex = 0, unstitchBufferIndex = 0;
+ int preview_size = (state->mode == STITCH_VERT) ? 2 : 4;
/* initialize the preview buffers */
preview->preview_polys = (float *)MEM_mallocN(preview->preview_uvs * sizeof(float) * 2, "tri_uv_stitch_prev");
preview->uvs_per_polygon = MEM_mallocN(preview->num_polys * sizeof(*preview->uvs_per_polygon), "tri_uv_stitch_prev");
- preview->preview_stitchable = (float *)MEM_mallocN(preview->num_stitchable * sizeof(float) * 2, "stitch_preview_stichable_data");
- preview->preview_unstitchable = (float *)MEM_mallocN(preview->num_unstitchable * sizeof(float) * 2, "stitch_preview_unstichable_data");
+ preview->preview_stitchable = (float *)MEM_mallocN(preview->num_stitchable * sizeof(float) * preview_size, "stitch_preview_stichable_data");
+ preview->preview_unstitchable = (float *)MEM_mallocN(preview->num_unstitchable * sizeof(float) * preview_size, "stitch_preview_unstichable_data");
preview->static_tris = (float *)MEM_mallocN(state->tris_per_island[state->static_island] * sizeof(float) * 6, "static_island_preview_tris");
@@ -715,7 +1000,7 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
return 0;
}
- /* copy data from MTFaces to the preview display buffers */
+ /* copy data from MLoopUVs to the preview display buffers */
BM_ITER_MESH (efa, &iter, state->em->bm, BM_FACES_OF_MESH) {
/* just to test if face was added for processing. uvs of inselected vertices will return NULL */
UvElement *element = ED_uv_element_get(state->element_map, efa, BM_FACE_FIRST_LOOP(efa));
@@ -757,22 +1042,56 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
}
/* fill the appropriate preview buffers */
- for (i = 0; i < state->total_separate_uvs; i++) {
- UvElement *element = (UvElement *)state->uvs[i];
- if (element->flag & STITCH_STITCHABLE) {
- l = element->l;
- luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if (state->mode == STITCH_VERT) {
+ for (i = 0; i < state->total_separate_uvs; i++) {
+ UvElement *element = (UvElement *)state->uvs[i];
+ if (element->flag & STITCH_STITCHABLE) {
+ l = element->l;
+ luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
- copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 2], luv->uv);
+ copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 2], luv->uv);
- stitchBufferIndex++;
+ stitchBufferIndex++;
+ }
+ else if (element->flag & STITCH_SELECTED) {
+ l = element->l;
+ luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 2], luv->uv);
+ unstitchBufferIndex++;
+ }
}
- else if (element->flag & STITCH_SELECTED) {
- l = element->l;
- luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+ }
+ else {
+ for (i = 0; i < state->total_separate_edges; i++) {
+ UvEdge *edge = state->edges + i;
+ UvElement *element1 = state->uvs[edge->uv1];
+ UvElement *element2 = state->uvs[edge->uv2];
+
+ if (edge->flag & STITCH_STITCHABLE) {
+ l = element1->l;
+ luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+ copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4], luv->uv);
- copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 2], luv->uv);
- unstitchBufferIndex++;
+ l = element2->l;
+ luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+ copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4 + 2], luv->uv);
+
+ stitchBufferIndex++;
+ BLI_assert(stitchBufferIndex <= preview->num_stitchable);
+ }
+ else if (edge->flag & STITCH_SELECTED) {
+ l = element1->l;
+ luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+ copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4], luv->uv);
+
+ l = element2->l;
+ luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+ copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4 + 2], luv->uv);
+
+ unstitchBufferIndex++;
+ BLI_assert(unstitchBufferIndex <= preview->num_unstitchable);
+ }
}
}
}
@@ -781,51 +1100,111 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
* Here we calculate the final coordinates of the uvs *
******************************************************/
- final_position = MEM_callocN(state->selection_size * sizeof(*final_position), "stitch_uv_average");
- uvfinal_map = MEM_mallocN(state->element_map->totalUVs * sizeof(*uvfinal_map), "stitch_uv_final_map");
+ if (state->mode == STITCH_VERT) {
+ final_position = MEM_callocN(state->selection_size * sizeof(*final_position), "stitch_uv_average");
+ uvfinal_map = MEM_mallocN(state->element_map->totalUVs * sizeof(*uvfinal_map), "stitch_uv_final_map");
+ }
+ else {
+ final_position = MEM_callocN(state->total_separate_uvs * sizeof(*final_position), "stitch_uv_average");
+ }
/* first pass, calculate final position for stitchable uvs of the static island */
for (i = 0; i < state->selection_size; i++) {
- UvElement *element = state->selection_stack[i];
- if (element->flag & STITCH_STITCHABLE) {
- BMLoop *l;
- MLoopUV *luv;
- UvElement *element_iter;
+ if (state->mode == STITCH_VERT) {
+ UvElement *element = state->selection_stack[i];
- l = element->l;
- luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if (element->flag & STITCH_STITCHABLE) {
+ BMLoop *l;
+ MLoopUV *luv;
+ UvElement *element_iter;
+ l = element->l;
+ luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
- uvfinal_map[element - state->element_map->buf] = i;
+ uvfinal_map[element - state->element_map->buf] = i;
- copy_v2_v2(final_position[i].uv, luv->uv);
- final_position[i].count = 1;
+ copy_v2_v2(final_position[i].uv, luv->uv);
+ final_position[i].count = 1;
- if (state->snap_islands && element->island == state->static_island && !stitch_midpoints)
- continue;
+ if (state->snap_islands && element->island == state->static_island && !stitch_midpoints)
+ continue;
+
+ element_iter = state->element_map->vert[BM_elem_index_get(l->v)];
+
+ for ( ; element_iter; element_iter = element_iter->next) {
+ if (element_iter->separate) {
+ if (stitch_check_uvs_state_stitchable(element, element_iter, state)) {
+ l = element_iter->l;
+ luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if (stitch_midpoints) {
+ add_v2_v2(final_position[i].uv, luv->uv);
+ final_position[i].count++;
+ }
+ else if (element_iter->island == state->static_island) {
+ /* if multiple uvs on the static island exist,
+ * last checked remains. to disambiguate we need to limit or use
+ * edge stitch */
+ copy_v2_v2(final_position[i].uv, luv->uv);
+ }
+ }
+ }
+ }
+ }
+ if (stitch_midpoints) {
+ final_position[i].uv[0] /= final_position[i].count;
+ final_position[i].uv[1] /= final_position[i].count;
+ }
+ }
+ else {
+ UvEdge *edge = state->selection_stack[i];
- element_iter = state->element_map->vert[BM_elem_index_get(l->v)];
+ if (edge->flag & STITCH_STITCHABLE) {
+ MLoopUV *luv2, *luv1;
+ BMLoop *l;
+ UvEdge *edge_iter;
+
+ l = state->uvs[edge->uv1]->l;
+ luv1 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+ l = state->uvs[edge->uv2]->l;
+ luv2 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+ copy_v2_v2(final_position[edge->uv1].uv, luv1->uv);
+ copy_v2_v2(final_position[edge->uv2].uv, luv2->uv);
+ final_position[edge->uv1].count = 1;
+ final_position[edge->uv2].count = 1;
+
+ state->uvs[edge->uv1]->flag |= STITCH_STITCHABLE;
+ state->uvs[edge->uv2]->flag |= STITCH_STITCHABLE;
+
+ if (state->snap_islands && edge->element->island == state->static_island && !stitch_midpoints)
+ continue;
+
+ for (edge_iter = edge->first; edge_iter; edge_iter = edge_iter->next) {
+ if (stitch_check_edges_state_stitchable (edge, edge_iter, state)) {
+ l = state->uvs[edge_iter->uv1]->l;
+ luv1 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+ l = state->uvs[edge_iter->uv2]->l;
+ luv2 = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
- for ( ; element_iter; element_iter = element_iter->next) {
- if (element_iter->separate) {
- if (stitch_check_uvs_state_stitchable(element, element_iter, state)) {
- l = element_iter->l;
- luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
if (stitch_midpoints) {
- add_v2_v2(final_position[i].uv, luv->uv);
- final_position[i].count++;
+ add_v2_v2(final_position[edge->uv1].uv, luv1->uv);
+ final_position[edge->uv1].count++;
+ add_v2_v2(final_position[edge->uv2].uv, luv2->uv);
+ final_position[edge->uv2].count++;
}
- else if (element_iter->island == state->static_island) {
- /* if multiple uvs on the static island exist,
- * last checked remains. to disambiguate we need to limit or use
- * edge stitch */
- copy_v2_v2(final_position[i].uv, luv->uv);
+ else if (edge_iter->element->island == state->static_island) {
+ copy_v2_v2(final_position[edge->uv1].uv, luv1->uv);
+ copy_v2_v2(final_position[edge->uv2].uv, luv2->uv);
}
}
}
}
}
- if (stitch_midpoints) {
+ }
+
+ /* take mean position here. For edge case, this can't be done inside the loop for shared uvverts */
+ if (state->mode == STITCH_EDGE && stitch_midpoints) {
+ for (i = 0; i < state->total_separate_uvs; i++) {
final_position[i].uv[0] /= final_position[i].count;
final_position[i].uv[1] /= final_position[i].count;
}
@@ -833,89 +1212,110 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
/* second pass, calculate island rotation and translation before modifying any uvs */
if (state->snap_islands) {
- for (i = 0; i < state->selection_size; i++) {
- UvElement *element = state->selection_stack[i];
- if (element->flag & STITCH_STITCHABLE) {
- BMLoop *l;
- MLoopUV *luv;
+ if (state->mode == STITCH_VERT) {
+ for (i = 0; i < state->selection_size; i++) {
+ UvElement *element = state->selection_stack[i];
- l = element->l;
- luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+ if (element->flag & STITCH_STITCHABLE) {
+ BMLoop *l;
+ MLoopUV *luv;
- /* accumulate each islands' translation from stitchable elements. it is important to do here
- * because in final pass MTFaces get modified and result is zero. */
- island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - luv->uv[0];
- island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - luv->uv[1];
- island_stitch_data[element->island].medianPoint[0] += luv->uv[0];
- island_stitch_data[element->island].medianPoint[1] += luv->uv[1];
- island_stitch_data[element->island].numOfElements++;
- }
- }
+ l = element->l;
+ luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
- /* only calculate rotation when an edge has been fully selected */
- for (i = 0; i < state->total_boundary_edges; i++) {
- UvEdge *edge = state->edges + i;
- if ((state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) && (state->uvs[edge->uv2]->flag & STITCH_STITCHABLE)) {
- stitch_island_calculate_edge_rotation(edge, state, final_position, uvfinal_map, island_stitch_data);
- island_stitch_data[state->uvs[edge->uv1]->island].use_edge_rotation = TRUE;
+ /* accumulate each islands' translation from stitchable elements. it is important to do here
+ * because in final pass MTFaces get modified and result is zero. */
+ island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - luv->uv[0];
+ island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - luv->uv[1];
+ island_stitch_data[element->island].medianPoint[0] += luv->uv[0];
+ island_stitch_data[element->island].medianPoint[1] += luv->uv[1];
+ island_stitch_data[element->island].numOfElements++;
+ }
}
- }
- /* clear seams of stitched edges */
- if (final && state->clear_seams) {
- for (i = 0; i < state->total_boundary_edges; i++) {
+ /* only calculate rotation when an edge has been fully selected */
+ for (i = 0; i < state->total_separate_edges; i++) {
UvEdge *edge = state->edges + i;
- if ((state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) && (state->uvs[edge->uv2]->flag & STITCH_STITCHABLE))
- BM_elem_flag_disable(edge->element->l->e, BM_ELEM_SEAM);
+ if ((edge->flag & STITCH_BOUNDARY) && (state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) && (state->uvs[edge->uv2]->flag & STITCH_STITCHABLE)) {
+ stitch_island_calculate_edge_rotation(edge, state, final_position, uvfinal_map, island_stitch_data);
+ island_stitch_data[state->uvs[edge->uv1]->island].use_edge_rotation = TRUE;
+ }
}
- }
- for (i = 0; i < state->selection_size; i++) {
- UvElement *element = state->selection_stack[i];
- if (!island_stitch_data[element->island].use_edge_rotation) {
- if (element->flag & STITCH_STITCHABLE) {
- stitch_island_calculate_vert_rotation(element, state, island_stitch_data);
+ /* clear seams of stitched edges */
+ if (final && state->clear_seams) {
+ for (i = 0; i < state->total_separate_edges; i++) {
+ UvEdge *edge = state->edges + i;
+ if ((state->uvs[edge->uv1]->flag & STITCH_STITCHABLE) && (state->uvs[edge->uv2]->flag & STITCH_STITCHABLE))
+ BM_elem_flag_disable(edge->element->l->e, BM_ELEM_SEAM);
+ }
+ }
+
+ for (i = 0; i < state->selection_size; i++) {
+ UvElement *element = state->selection_stack[i];
+ if (!island_stitch_data[element->island].use_edge_rotation) {
+ if (element->flag & STITCH_STITCHABLE) {
+ stitch_island_calculate_vert_rotation(element, state, island_stitch_data);
+ }
}
}
}
+ else {
+ for (i = 0; i < state->total_separate_uvs; i++) {
+ UvElement *element = state->uvs[i];
- }
+ if (element->flag & STITCH_STITCHABLE) {
+ BMLoop *l;
+ MLoopUV *luv;
- /* third pass, propagate changes to coincident uvs */
- for (i = 0; i < state->selection_size; i++) {
- UvElement *element = state->selection_stack[i];
- if (element->flag & STITCH_STITCHABLE) {
- UvElement *element_iter = element;
- /* propagate to coincident uvs */
- do {
- BMLoop *l;
- MLoopUV *luv;
+ l = element->l;
+ luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
- l = element_iter->l;
- luv = CustomData_bmesh_get(&state->em->bm->ldata, l->head.data, CD_MLOOPUV);
+ /* accumulate each islands' translation from stitchable elements. it is important to do here
+ * because in final pass MTFaces get modified and result is zero. */
+ island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - luv->uv[0];
+ island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - luv->uv[1];
+ island_stitch_data[element->island].medianPoint[0] += luv->uv[0];
+ island_stitch_data[element->island].medianPoint[1] += luv->uv[1];
+ island_stitch_data[element->island].numOfElements++;
+ }
+ }
- element_iter->flag |= STITCH_PROCESSED;
- /* either flush to preview or to the MTFace, if final */
- if (final) {
- copy_v2_v2(luv->uv, final_position[i].uv);
+ for (i = 0; i < state->selection_size; i++) {
+ UvEdge *edge = state->selection_stack[i];
- uvedit_uv_select_enable(state->em, scene, l, FALSE);
+ if (edge->flag & STITCH_STITCHABLE) {
+ stitch_island_calculate_edge_rotation(edge, state, final_position, NULL, island_stitch_data);
+ island_stitch_data[state->uvs[edge->uv1]->island].use_edge_rotation = TRUE;
}
- else {
- int face_preview_pos = preview_position[BM_elem_index_get(element_iter->face)].data_position;
- if (face_preview_pos != STITCH_NO_PREVIEW) {
- copy_v2_v2(preview->preview_polys + face_preview_pos + 2 * element_iter->tfindex,
- final_position[i].uv);
+ }
+
+ /* clear seams of stitched edges */
+ if (final && state->clear_seams) {
+ for (i = 0; i < state->selection_size; i++) {
+ UvEdge *edge = state->selection_stack[i];
+ if (edge->flag & STITCH_STITCHABLE) {
+ BM_elem_flag_disable(edge->element->l->e, BM_ELEM_SEAM);
}
}
+ }
+ }
+ }
- /* end of calculations, keep only the selection flag */
- if ( (!state->snap_islands) || ((!stitch_midpoints) && (element_iter->island == state->static_island))) {
- element_iter->flag &= STITCH_SELECTED;
- }
+ /* third pass, propagate changes to coincident uvs */
+ for (i = 0; i < state->selection_size; i++) {
+ if (state->mode == STITCH_VERT) {
+ UvElement *element = state->selection_stack[i];
+
+ stitch_propagate_uv_final_position (element, i, preview_position, final_position, state, final, scene);
+ }
+ else {
+ UvEdge *edge = state->selection_stack[i];
+
+ stitch_propagate_uv_final_position (state->uvs[edge->uv1], edge->uv1, preview_position, final_position, state, final, scene);
+ stitch_propagate_uv_final_position (state->uvs[edge->uv2], edge->uv2, preview_position, final_position, state, final, scene);
- element_iter = element_iter->next;
- } while (element_iter && !element_iter->separate);
+ edge->flag &= (STITCH_SELECTED | STITCH_BOUNDARY);
}
}
@@ -925,7 +1325,9 @@ static int stitch_process_data(StitchState *state, Scene *scene, int final)
}
MEM_freeN(final_position);
- MEM_freeN(uvfinal_map);
+ if (state->mode == STITCH_VERT) {
+ MEM_freeN(uvfinal_map);
+ }
MEM_freeN(island_stitch_data);
MEM_freeN(preview_position);
@@ -937,8 +1339,8 @@ static unsigned int uv_edge_hash(const void *key)
{
UvEdge *edge = (UvEdge *)key;
return
- BLI_ghashutil_inthash(SET_INT_IN_POINTER(edge->uv2)) +
- BLI_ghashutil_inthash(SET_INT_IN_POINTER(edge->uv1));
+ BLI_ghashutil_inthash(SET_INT_IN_POINTER(edge->uv2)) +
+ BLI_ghashutil_inthash(SET_INT_IN_POINTER(edge->uv1));
}
static int uv_edge_compare(const void *a, const void *b)
@@ -952,13 +1354,41 @@ static int uv_edge_compare(const void *a, const void *b)
return 1;
}
+/* select all common edges */
+static void stitch_select_edge(UvEdge *edge, StitchState *state, int always_select)
+{
+ UvEdge *eiter;
+ UvEdge **selection_stack = (UvEdge **)state->selection_stack;
+
+ for (eiter = edge->first; eiter; eiter = eiter->next) {
+ if (eiter->flag & STITCH_SELECTED) {
+ int i;
+ if (always_select)
+ continue;
+
+ eiter->flag &= ~STITCH_SELECTED;
+ for (i = 0; i < state->selection_size; i++) {
+ if (selection_stack[i] == eiter) {
+ (state->selection_size)--;
+ selection_stack[i] = selection_stack[state->selection_size];
+ break;
+ }
+ }
+ }
+ else {
+ eiter->flag |= STITCH_SELECTED;
+ selection_stack[state->selection_size++] = eiter;
+ }
+ }
+}
+
/* Select all common uvs */
static void stitch_select_uv(UvElement *element, StitchState *state, int always_select)
{
BMLoop *l;
UvElement *element_iter;
- UvElement **selection_stack = state->selection_stack;
+ UvElement **selection_stack = (UvElement **)state->selection_stack;
l = element->l;
@@ -989,33 +1419,86 @@ static void stitch_select_uv(UvElement *element, StitchState *state, int always_
}
}
-static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *normal)
+static void stitch_switch_selection_mode(StitchState *state)
+{
+ void **old_selection_stack = state->selection_stack;
+ int old_selection_size = state->selection_size;
+ state->selection_size = 0;
+
+ if (state->mode == STITCH_VERT) {
+ int i;
+ state->selection_stack = MEM_mallocN(state->total_separate_edges * sizeof(*state->selection_stack),
+ "stitch_new_edge_selection_stack");
+
+ /* check if both elements of an edge are selected */
+ for (i = 0; i < state->total_separate_edges; i++) {
+ UvEdge *edge = state->edges + i;
+ UvElement *element1 = state->uvs[edge->uv1];
+ UvElement *element2 = state->uvs[edge->uv2];
+
+ if ((element1->flag & STITCH_SELECTED) && (element2->flag & STITCH_SELECTED))
+ stitch_select_edge(edge, state, TRUE);
+ }
+
+ /* unselect selected uvelements */
+ for (i = 0; i < old_selection_size; i++) {
+ UvElement *element = old_selection_stack[i];
+
+ element->flag &= ~STITCH_SELECTED;
+ }
+ state->mode = STITCH_EDGE;
+ }
+ else {
+ int i;
+ state->selection_stack = MEM_mallocN(state->total_separate_uvs * sizeof(*state->selection_stack),
+ "stitch_new_vert_selection_stack");
+
+ for (i = 0; i < old_selection_size; i++) {
+ UvEdge *edge = old_selection_stack[i];
+ UvElement *element1 = state->uvs[edge->uv1];
+ UvElement *element2 = state->uvs[edge->uv2];
+
+ stitch_select_uv(element1, state, TRUE);
+ stitch_select_uv(element2, state, TRUE);
+
+ edge->flag &= ~STITCH_SELECTED;
+ }
+ state->mode = STITCH_VERT;
+ }
+ MEM_freeN(old_selection_stack);
+}
+
+static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *normal, float aspect)
{
BMLoop *l1 = edge->element->l;
- BMLoop *l2 = l1->next;
MLoopUV *luv1, *luv2;
float tangent[2];
luv1 = CustomData_bmesh_get(&em->bm->ldata, l1->head.data, CD_MLOOPUV);
- luv2 = CustomData_bmesh_get(&em->bm->ldata, l2->head.data, CD_MLOOPUV);
+ luv2 = CustomData_bmesh_get(&em->bm->ldata, l1->next->head.data, CD_MLOOPUV);
sub_v2_v2v2(tangent, luv2->uv, luv1->uv);
+ tangent[1] /= aspect;
+
normal[0] = tangent[1];
normal[1] = -tangent[0];
normalize_v2(normal);
}
-static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *UNUSED(arg))
+static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
{
int i, index = 0;
float pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
- StitchPreviewer *stitch_preview = uv_get_stitch_previewer();
+ StitchState *state = (StitchState *)arg;
+ StitchPreviewer *stitch_preview = state->stitch_preview;
glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
+ glPointSize(pointsize * 2.0f);
+
glEnable(GL_BLEND);
UI_ThemeColor4(TH_STITCH_PREVIEW_ACTIVE);
@@ -1031,35 +1514,68 @@ static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *UN
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
UI_ThemeColor4(TH_STITCH_PREVIEW_EDGE);
glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]);
+ #if 0
+ glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
+ UI_ThemeColor4(TH_STITCH_PREVIEW_VERT);
+ glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]);
+ #endif
index += stitch_preview->uvs_per_polygon[i];
}
- glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
-#if 0
- UI_ThemeColor4(TH_STITCH_PREVIEW_VERT);
- glDrawArrays(GL_TRIANGLES, 0, stitch_preview->num_tris * 3);
-#endif
glDisable(GL_BLEND);
/* draw vert preview */
- glPointSize(pointsize * 2.0f);
- UI_ThemeColor4(TH_STITCH_PREVIEW_STITCHABLE);
- glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_stitchable);
- glDrawArrays(GL_POINTS, 0, stitch_preview->num_stitchable);
+ if (state->mode == STITCH_VERT) {
+ UI_ThemeColor4(TH_STITCH_PREVIEW_STITCHABLE);
+ glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_stitchable);
+ glDrawArrays(GL_POINTS, 0, stitch_preview->num_stitchable);
+
+ UI_ThemeColor4(TH_STITCH_PREVIEW_UNSTITCHABLE);
+ glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_unstitchable);
+ glDrawArrays(GL_POINTS, 0, stitch_preview->num_unstitchable);
+ }
+ else {
+ UI_ThemeColor4(TH_STITCH_PREVIEW_STITCHABLE);
+ glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_stitchable);
+ glDrawArrays(GL_LINES, 0, 2 * stitch_preview->num_stitchable);
- UI_ThemeColor4(TH_STITCH_PREVIEW_UNSTITCHABLE);
- glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_unstitchable);
- glDrawArrays(GL_POINTS, 0, stitch_preview->num_unstitchable);
+ UI_ThemeColor4(TH_STITCH_PREVIEW_UNSTITCHABLE);
+ glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_unstitchable);
+ glDrawArrays(GL_LINES, 0, 2 * stitch_preview->num_unstitchable);
+ }
glPopClientAttrib();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glPointSize(1.0);
+}
+
+static UvEdge *uv_edge_get (BMLoop *l, StitchState *state)
+{
+ UvEdge tmp_edge;
+
+ UvElement *element1 = ED_uv_element_get(state->element_map, l->f, l);
+ UvElement *element2 = ED_uv_element_get(state->element_map, l->f, l->next);
+
+ int uv1 = state->map[element1 - state->element_map->buf];
+ int uv2 = state->map[element2 - state->element_map->buf];
+
+ if (uv1 < uv2) {
+ tmp_edge.uv1 = uv1;
+ tmp_edge.uv2 = uv2;
+ }
+ else {
+ tmp_edge.uv1 = uv2;
+ tmp_edge.uv2 = uv1;
+ }
+
+ return BLI_ghash_lookup(state->edge_hash, &tmp_edge);
}
static int stitch_init(bContext *C, wmOperator *op)
{
/* for fast edge lookup... */
- GHash *edgeHash;
+ GHash *edge_hash;
/* ...and actual edge storage */
UvEdge *edges;
int total_edges;
@@ -1076,7 +1592,7 @@ static int stitch_init(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = scene->toolsettings;
ARegion *ar = CTX_wm_region(C);
-
+ float aspx, aspy;
Object *obedit = CTX_data_edit_object(C);
if (!ar)
@@ -1097,21 +1613,44 @@ static int stitch_init(bContext *C, wmOperator *op)
state->static_island = RNA_int_get(op->ptr, "static_island");
state->midpoints = RNA_boolean_get(op->ptr, "midpoint_snap");
state->clear_seams = RNA_boolean_get(op->ptr, "clear_seams");
- state->draw_handle = ED_region_draw_cb_activate(ar->type, stitch_draw, NULL, REGION_DRAW_POST_VIEW);
+ if (RNA_struct_property_is_set(op->ptr, "mode")) {
+ state->mode = RNA_enum_get(op->ptr, "mode");
+ }
+ else {
+ if (ts->uv_flag & UV_SYNC_SELECTION) {
+ if (ts->selectmode & SCE_SELECT_VERTEX)
+ state->mode = STITCH_VERT;
+ else
+ state->mode = STITCH_EDGE;
+ }
+ else {
+ if (ts->uv_selectmode & UV_SELECT_VERTEX) {
+ state->mode = STITCH_VERT;
+ }
+ else {
+ state->mode = STITCH_EDGE;
+ }
+ }
+ }
+
+ state->draw_handle = ED_region_draw_cb_activate(ar->type, stitch_draw, state, REGION_DRAW_POST_VIEW);
/* in uv synch selection, all uv's are visible */
if (ts->uv_flag & UV_SYNC_SELECTION) {
- state->element_map = EDBM_uv_element_map_create(state->em, 0, 1);
+ state->element_map = EDBM_uv_element_map_create(state->em, FALSE, TRUE);
}
else {
- state->element_map = EDBM_uv_element_map_create(state->em, 1, 1);
+ state->element_map = EDBM_uv_element_map_create(state->em, TRUE, TRUE);
}
if (!state->element_map) {
- stitch_state_delete(state);
+ state_delete(state);
return 0;
}
+ uvedit_get_aspect(scene, obedit, em, &aspx, &aspy);
+ state->aspect = aspx / aspy;
+
/* Entirely possible if redoing last operator that static island is bigger than total number of islands.
- * This ensures we get no hang in the island checking code in stitch_process_data. */
+ * This ensures we get no hang in the island checking code in stitch_stitch_process_data. */
state->static_island %= state->element_map->totalIslands;
/* Count 'unique' uvs */
@@ -1121,22 +1660,21 @@ static int stitch_init(bContext *C, wmOperator *op)
}
}
+ /* explicitly set preview to NULL, to avoid deleting an invalid pointer on stitch_process_data */
+ state->stitch_preview = NULL;
/* Allocate the unique uv buffers */
state->uvs = MEM_mallocN(sizeof(*state->uvs) * counter, "uv_stitch_unique_uvs");
/* internal uvs need no normals but it is hard and slow to keep a map of
* normals only for boundary uvs, so allocating for all uvs */
state->normals = MEM_callocN(sizeof(*state->normals) * counter * 2, "uv_stitch_normals");
state->total_separate_uvs = counter;
- /* we can at most have totalUVs edges or uvs selected. Actually they are less, considering we store only
- * unique uvs for processing but I am accounting for all bizarre cases, especially for edges, this way */
- state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * counter, "uv_stitch_selection_stack");
state->map = map = MEM_mallocN(sizeof(*map) * state->element_map->totalUVs, "uv_stitch_unique_map");
/* Allocate the edge stack */
- edgeHash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "stitch_edge_hash");
+ edge_hash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "stitch_edge_hash");
all_edges = MEM_mallocN(sizeof(*all_edges) * state->element_map->totalUVs, "stitch_all_edges");
- if (!state->selection_stack || !state->uvs || !map || !edgeHash || !all_edges) {
- stitch_state_delete(state);
+ if (!state->uvs || !map || !edge_hash || !all_edges) {
+ state_delete(state);
return 0;
}
@@ -1169,6 +1707,8 @@ static int stitch_init(bContext *C, wmOperator *op)
offset1 = map[itmp1];
offset2 = map[itmp2];
+ all_edges[counter].next = NULL;
+ all_edges[counter].first = NULL;
all_edges[counter].flag = 0;
all_edges[counter].element = element;
/* using an order policy, sort uvs according to address space. This avoids
@@ -1182,12 +1722,12 @@ static int stitch_init(bContext *C, wmOperator *op)
all_edges[counter].uv2 = offset1;
}
- if (BLI_ghash_haskey(edgeHash, &all_edges[counter])) {
- char *flag = BLI_ghash_lookup(edgeHash, &all_edges[counter]);
- *flag = 0;
+ if (BLI_ghash_haskey(edge_hash, &all_edges[counter])) {
+ UvEdge *edge = BLI_ghash_lookup(edge_hash, &all_edges[counter]);
+ edge->flag = 0;
}
else {
- BLI_ghash_insert(edgeHash, &all_edges[counter], &(all_edges[counter].flag));
+ BLI_ghash_insert(edge_hash, &all_edges[counter], &all_edges[counter]);
all_edges[counter].flag = STITCH_BOUNDARY;
}
counter++;
@@ -1195,55 +1735,56 @@ static int stitch_init(bContext *C, wmOperator *op)
}
- ghi = BLI_ghashIterator_new(edgeHash);
- total_edges = 0;
- /* fill the edges with data */
- for (; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) {
- UvEdge *edge = ((UvEdge *)BLI_ghashIterator_getKey(ghi));
- if (edge->flag & STITCH_BOUNDARY) {
- total_edges++;
- }
- }
+ ghi = BLI_ghashIterator_new(edge_hash);
+ total_edges = BLI_ghash_size(edge_hash);
state->edges = edges = MEM_mallocN(sizeof(*edges) * total_edges, "stitch_edges");
- if (!ghi || !edges) {
- MEM_freeN(all_edges);
- stitch_state_delete(state);
+
+ /* 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;
}
- state->total_boundary_edges = total_edges;
+ state->total_separate_edges = total_edges;
/* fill the edges with data */
- for (i = 0, BLI_ghashIterator_init(ghi, edgeHash); !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) {
- UvEdge *edge = ((UvEdge *)BLI_ghashIterator_getKey(ghi));
- if (edge->flag & STITCH_BOUNDARY) {
- edges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(ghi));
- }
+ for (i = 0, BLI_ghashIterator_init(ghi, edge_hash); BLI_ghashIterator_notDone(ghi); BLI_ghashIterator_step(ghi)) {
+ edges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(ghi));
}
/* cleanup temporary stuff */
BLI_ghashIterator_free(ghi);
MEM_freeN(all_edges);
- /* refill hash with new pointers to cleanup duplicates */
- BLI_ghash_free(edgeHash, NULL, NULL);
+ BLI_ghash_free(edge_hash, NULL, NULL);
+
+ /* refill an edge hash to create edge connnectivity data */
+ state->edge_hash = edge_hash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "stitch_edge_hash");
+ for (i = 0; i < total_edges; i++) {
+ BLI_ghash_insert(edge_hash, edges + i, edges + i);
+ }
+ stitch_uv_edge_generate_linked_edges(edge_hash, state);
/***** calculate 2D normals for boundary uvs *****/
/* we use boundary edges to calculate 2D normals.
* to disambiguate the direction of the normal, we also need
* a point "inside" the island, that can be provided by
- * the opposite uv for a quad, or the next uv for a triangle. */
+ * the winding of the polygon (assuming counter-clockwise flow). */
for (i = 0; i < total_edges; i++) {
+ UvEdge *edge = edges + i;
float normal[2];
- stitch_calculate_edge_normal(em, edges + i, normal);
+ if (edge->flag & STITCH_BOUNDARY) {
+ stitch_calculate_edge_normal(em, edge, normal, state->aspect);
- add_v2_v2(state->normals + edges[i].uv1 * 2, normal);
- add_v2_v2(state->normals + edges[i].uv2 * 2, normal);
+ add_v2_v2(state->normals + edge->uv1 * 2, normal);
+ add_v2_v2(state->normals + edge->uv2 * 2, normal);
- normalize_v2(state->normals + edges[i].uv1 * 2);
- normalize_v2(state->normals + edges[i].uv2 * 2);
+ normalize_v2(state->normals + edge->uv1 * 2);
+ normalize_v2(state->normals + edge->uv2 * 2);
+ }
}
@@ -1255,31 +1796,89 @@ static int stitch_init(bContext *C, wmOperator *op)
if (RNA_struct_property_is_set(op->ptr, "selection")) {
int faceIndex, elementIndex;
UvElement *element;
+ enum StitchModes stored_mode = RNA_enum_get(op->ptr, "stored_mode");
- EDBM_index_arrays_init(em, 0, 0, 1);
+ EDBM_index_arrays_ensure(em, BM_FACE);
- RNA_BEGIN (op->ptr, itemptr, "selection")
- {
- faceIndex = RNA_int_get(&itemptr, "face_index");
- elementIndex = RNA_int_get(&itemptr, "element_index");
- efa = EDBM_face_at_index(em, faceIndex);
- element = ED_uv_element_get(state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
- stitch_select_uv(element, state, 1);
+ if (stored_mode == STITCH_VERT) {
+ state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * state->total_separate_uvs, "uv_stitch_selection_stack");
+
+ RNA_BEGIN (op->ptr, itemptr, "selection")
+ {
+ faceIndex = RNA_int_get(&itemptr, "face_index");
+ elementIndex = RNA_int_get(&itemptr, "element_index");
+ efa = EDBM_face_at_index(em, faceIndex);
+ element = ED_uv_element_get(state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
+ stitch_select_uv(element, state, 1);
+ }
+ RNA_END;
}
- RNA_END;
+ else {
+ state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * state->total_separate_edges, "uv_stitch_selection_stack");
+
+ RNA_BEGIN (op->ptr, itemptr, "selection")
+ {
+ UvEdge tmp_edge, *edge;
+ int uv1, uv2;
+ faceIndex = RNA_int_get(&itemptr, "face_index");
+ elementIndex = RNA_int_get(&itemptr, "element_index");
+ efa = EDBM_face_at_index(em, faceIndex);
+ element = ED_uv_element_get(state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, elementIndex));
+ uv1 = map[element - state->element_map->buf];
+
+ element = ED_uv_element_get(state->element_map, efa, BM_iter_at_index(NULL, BM_LOOPS_OF_FACE, efa, (elementIndex + 1) % efa->len));
+ uv2 = map[element - state->element_map->buf];
+
+ if (uv1 < uv2) {
+ tmp_edge.uv1 = uv1;
+ tmp_edge.uv2 = uv2;
+ }
+ else {
+ tmp_edge.uv1 = uv2;
+ tmp_edge.uv2 = uv1;
+ }
- EDBM_index_arrays_free(em);
+ edge = BLI_ghash_lookup(edge_hash, &tmp_edge);
+
+ stitch_select_edge(edge, state, TRUE);
+ }
+ RNA_END;
+ }
+ /* if user has switched the operator mode after operation, we need to convert
+ * the stored format */
+ if (state->mode != stored_mode) {
+ state->mode = stored_mode;
+ stitch_switch_selection_mode(state);
+ }
/* Clear the selection */
RNA_collection_clear(op->ptr, "selection");
}
else {
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
- if (uvedit_uv_select_test(em, scene, l)) {
- UvElement *element = ED_uv_element_get(state->element_map, efa, l);
- if (element) {
- stitch_select_uv(element, state, 1);
+ if (state->mode == STITCH_VERT) {
+ state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * state->total_separate_uvs, "uv_stitch_selection_stack");
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
+ if (uvedit_uv_select_test(em, scene, l)) {
+ UvElement *element = ED_uv_element_get(state->element_map, efa, l);
+ if (element) {
+ stitch_select_uv(element, state, 1);
+ }
+ }
+ }
+ }
+ }
+ else {
+ state->selection_stack = MEM_mallocN(sizeof(*state->selection_stack) * state->total_separate_edges, "uv_stitch_selection_stack");
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
+ if (uvedit_edge_select_test(em, scene, l)) {
+ UvEdge *edge = uv_edge_get(l, state);
+ if (edge) {
+ stitch_select_edge(edge, state, TRUE);
+ }
}
}
}
@@ -1302,8 +1901,9 @@ static int stitch_init(bContext *C, wmOperator *op)
}
}
- if (!stitch_process_data(state, scene, 0)) {
- stitch_state_delete(state);
+ if (!stitch_process_data(state, scene, FALSE)) {
+
+ state_delete(state);
return 0;
}
@@ -1311,7 +1911,7 @@ static int stitch_init(bContext *C, wmOperator *op)
return 1;
}
-static int stitch_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int stitch_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Object *obedit = CTX_data_edit_object(C);
if (!stitch_init(C, op))
@@ -1324,7 +1924,7 @@ static int stitch_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
static void stitch_exit(bContext *C, wmOperator *op, int finished)
{
- StitchState *stitch_state;
+ StitchState *state;
Scene *scene;
SpaceImage *sima;
ScrArea *sa = CTX_wm_area(C);
@@ -1334,45 +1934,48 @@ static void stitch_exit(bContext *C, wmOperator *op, int finished)
obedit = CTX_data_edit_object(C);
sima = CTX_wm_space_image(C);
- stitch_state = (StitchState *)op->customdata;
+ state = (StitchState *)op->customdata;
if (finished) {
int i;
- RNA_float_set(op->ptr, "limit", stitch_state->limit_dist);
- RNA_boolean_set(op->ptr, "use_limit", stitch_state->use_limit);
- RNA_boolean_set(op->ptr, "snap_islands", stitch_state->snap_islands);
- RNA_int_set(op->ptr, "static_island", stitch_state->static_island);
- RNA_boolean_set(op->ptr, "midpoint_snap", stitch_state->midpoints);
+ RNA_float_set(op->ptr, "limit", state->limit_dist);
+ RNA_boolean_set(op->ptr, "use_limit", state->use_limit);
+ RNA_boolean_set(op->ptr, "snap_islands", state->snap_islands);
+ RNA_int_set(op->ptr, "static_island", state->static_island);
+ RNA_boolean_set(op->ptr, "midpoint_snap", state->midpoints);
+ RNA_enum_set(op->ptr, "mode", state->mode);
+ RNA_enum_set(op->ptr, "stored_mode", state->mode);
/* Store selection for re-execution of stitch */
- for (i = 0; i < stitch_state->selection_size; i++) {
+ for (i = 0; i < state->selection_size; i++) {
+ UvElement *element;
PointerRNA itemptr;
- UvElement *element = stitch_state->selection_stack[i];
-
+ if (state->mode == STITCH_VERT) {
+ element = state->selection_stack[i];
+ }
+ else {
+ element = ((UvEdge *)state->selection_stack[i])->element;
+ }
RNA_collection_add(op->ptr, "selection", &itemptr);
- RNA_int_set(&itemptr, "face_index", BM_elem_index_get(element->face));
-
+ RNA_int_set(&itemptr, "face_index", BM_elem_index_get(element->l->f));
RNA_int_set(&itemptr, "element_index", element->tfindex);
}
-
uvedit_live_unwrap_update(sima, scene, obedit);
}
if (sa)
ED_area_headerprint(sa, NULL);
- ED_region_draw_cb_exit(CTX_wm_region(C)->type, stitch_state->draw_handle);
+ ED_region_draw_cb_exit(CTX_wm_region(C)->type, state->draw_handle);
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- stitch_state_delete(stitch_state);
+ state_delete(state);
op->customdata = NULL;
-
- stitch_preview_delete();
}
@@ -1398,7 +2001,7 @@ static int stitch_exec(bContext *C, wmOperator *op)
}
}
-static void stitch_select(bContext *C, Scene *scene, wmEvent *event, StitchState *stitch_state)
+static void stitch_select(bContext *C, Scene *scene, const wmEvent *event, StitchState *state)
{
/* add uv under mouse to processed uv's */
float co[2];
@@ -1407,42 +2010,53 @@ static void stitch_select(bContext *C, Scene *scene, wmEvent *event, StitchState
Image *ima = CTX_data_edit_image(C);
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
- uv_find_nearest_vert(scene, ima, stitch_state->em, co, NULL, &hit);
- if (hit.efa) {
- /* Add vertex to selection, deselect all common uv's of vert other
- * than selected and update the preview. This behavior was decided so that
- * you can do stuff like deselect the opposite stitchable vertex and the initial still gets deselected */
+ if (state->mode == STITCH_VERT) {
+ uv_find_nearest_vert(scene, ima, state->em, co, NULL, &hit);
- /* This works due to setting of tmp in find nearest uv vert */
- UvElement *element = ED_uv_element_get(stitch_state->element_map, hit.efa, hit.l);
- stitch_select_uv(element, stitch_state, 0);
+ if (hit.efa) {
+ /* Add vertex to selection, deselect all common uv's of vert other
+ * than selected and update the preview. This behavior was decided so that
+ * you can do stuff like deselect the opposite stitchable vertex and the initial still gets deselected */
+ /* This works due to setting of tmp in find nearest uv vert */
+ UvElement *element = ED_uv_element_get(state->element_map, hit.efa, hit.l);
+ stitch_select_uv(element, state, FALSE);
+
+ }
+ }
+ else {
+ uv_find_nearest_edge(scene, ima, state->em, co, &hit);
+
+ if (hit.efa) {
+ UvEdge *edge = uv_edge_get(hit.l, state);
+ stitch_select_edge(edge, state, FALSE);
+ }
}
}
-static int stitch_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- StitchState *stitch_state;
+ StitchState *state;
Scene *scene = CTX_data_scene(C);
- stitch_state = (StitchState *)op->customdata;
+ state = (StitchState *)op->customdata;
switch (event->type) {
case MIDDLEMOUSE:
return OPERATOR_PASS_THROUGH;
- /* Cancel */
+ /* Cancel */
case ESCKEY:
return stitch_cancel(C, op);
case LEFTMOUSE:
if (event->shift && (U.flag & USER_LMOUSESELECT)) {
- if (event->val == KM_RELEASE) {
- stitch_select(C, scene, event, stitch_state);
+ if (event->val == KM_PRESS) {
+ stitch_select(C, scene, event, state);
- if (!stitch_process_data(stitch_state, scene, 0)) {
+ if (!stitch_process_data(state, scene, FALSE)) {
return stitch_cancel(C, op);
}
}
@@ -1451,7 +2065,7 @@ static int stitch_modal(bContext *C, wmOperator *op, wmEvent *event)
case PADENTER:
case RETKEY:
if (event->val == KM_PRESS) {
- if (stitch_process_data(stitch_state, scene, 1)) {
+ if (stitch_process_data(state, scene, TRUE)) {
stitch_exit(C, op, 1);
return OPERATOR_FINISHED;
}
@@ -1462,12 +2076,12 @@ static int stitch_modal(bContext *C, wmOperator *op, wmEvent *event)
else {
return OPERATOR_PASS_THROUGH;
}
- /* Increase limit */
+ /* Increase limit */
case PADPLUSKEY:
case WHEELUPMOUSE:
if (event->val == KM_PRESS && event->alt) {
- stitch_state->limit_dist += 0.01f;
- if (!stitch_process_data(stitch_state, scene, 0)) {
+ state->limit_dist += 0.01f;
+ if (!stitch_process_data(state, scene, FALSE)) {
return stitch_cancel(C, op);
}
break;
@@ -1475,13 +2089,13 @@ static int stitch_modal(bContext *C, wmOperator *op, wmEvent *event)
else {
return OPERATOR_PASS_THROUGH;
}
- /* Decrease limit */
+ /* Decrease limit */
case PADMINUS:
case WHEELDOWNMOUSE:
if (event->val == KM_PRESS && event->alt) {
- stitch_state->limit_dist -= 0.01f;
- stitch_state->limit_dist = MAX2(0.01f, stitch_state->limit_dist);
- if (!stitch_process_data(stitch_state, scene, 0)) {
+ state->limit_dist -= 0.01f;
+ state->limit_dist = MAX2(0.01f, state->limit_dist);
+ if (!stitch_process_data(state, scene, FALSE)) {
return stitch_cancel(C, op);
}
break;
@@ -1490,11 +2104,11 @@ static int stitch_modal(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_PASS_THROUGH;
}
- /* Use Limit (Default off)*/
+ /* Use Limit (Default off)*/
case LKEY:
if (event->val == KM_PRESS) {
- stitch_state->use_limit = !stitch_state->use_limit;
- if (!stitch_process_data(stitch_state, scene, 0)) {
+ state->use_limit = !state->use_limit;
+ if (!stitch_process_data(state, scene, FALSE)) {
return stitch_cancel(C, op);
}
break;
@@ -1503,10 +2117,10 @@ static int stitch_modal(bContext *C, wmOperator *op, wmEvent *event)
case IKEY:
if (event->val == KM_PRESS) {
- stitch_state->static_island++;
- stitch_state->static_island %= stitch_state->element_map->totalIslands;
+ state->static_island++;
+ state->static_island %= state->element_map->totalIslands;
- if (!stitch_process_data(stitch_state, scene, 0)) {
+ if (!stitch_process_data(state, scene, FALSE)) {
return stitch_cancel(C, op);
}
break;
@@ -1515,33 +2129,33 @@ static int stitch_modal(bContext *C, wmOperator *op, wmEvent *event)
case MKEY:
if (event->val == KM_PRESS) {
- stitch_state->midpoints = !stitch_state->midpoints;
- if (!stitch_process_data(stitch_state, scene, 0)) {
+ state->midpoints = !state->midpoints;
+ if (!stitch_process_data(state, scene, FALSE)) {
return stitch_cancel(C, op);
}
}
break;
- /* Select geometry*/
+ /* Select geometry*/
case RIGHTMOUSE:
if (!event->shift) {
return stitch_cancel(C, op);
}
- if (event->val == KM_RELEASE && !(U.flag & USER_LMOUSESELECT)) {
- stitch_select(C, scene, event, stitch_state);
+ if (event->val == KM_PRESS && !(U.flag & USER_LMOUSESELECT)) {
+ stitch_select(C, scene, event, state);
- if (!stitch_process_data(stitch_state, scene, 0)) {
+ if (!stitch_process_data(state, scene, FALSE)) {
return stitch_cancel(C, op);
}
break;
}
return OPERATOR_RUNNING_MODAL;
- /* snap islands on/off */
+ /* snap islands on/off */
case SKEY:
if (event->val == KM_PRESS) {
- stitch_state->snap_islands = !stitch_state->snap_islands;
- if (!stitch_process_data(stitch_state, scene, 0)) {
+ state->snap_islands = !state->snap_islands;
+ if (!stitch_process_data(state, scene, FALSE)) {
return stitch_cancel(C, op);
}
break;
@@ -1550,12 +2164,23 @@ static int stitch_modal(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
+ /* switch between edge/vertex mode */
+ case TABKEY:
+ if (event->val == KM_PRESS) {
+ stitch_switch_selection_mode(state);
+
+ if (!stitch_process_data(state, scene, FALSE)) {
+ return stitch_cancel(C, op);
+ }
+ }
+ break;
+
default:
return OPERATOR_RUNNING_MODAL;
}
/* if updated settings, renew feedback message */
- stitch_update_header(stitch_state, C);
+ stitch_update_header(state, C);
ED_region_tag_redraw(CTX_wm_region(C));
return OPERATOR_RUNNING_MODAL;
}
@@ -1564,6 +2189,12 @@ void UV_OT_stitch(wmOperatorType *ot)
{
PropertyRNA *prop;
+ static EnumPropertyItem stitch_modes[] = {
+ {STITCH_VERT, "VERTEX", 0, "Vertex", ""},
+ {STITCH_EDGE, "EDGE", 0, "Edge", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
/* identifiers */
ot->name = "Stitch";
ot->description = "Stitch selected UV vertices by proximity";
@@ -1590,6 +2221,11 @@ void UV_OT_stitch(wmOperatorType *ot)
"UVs are stitched at midpoint instead of at static island");
RNA_def_boolean(ot->srna, "clear_seams", 1, "Clear Seams",
"Clear seams of stitched edges");
+ RNA_def_enum(ot->srna, "mode", stitch_modes, STITCH_VERT, "Operation Mode",
+ "Use vertex or edge stitching");
+ prop = RNA_def_enum(ot->srna, "stored_mode", stitch_modes, STITCH_VERT, "Stored Operation Mode",
+ "Use vertex or edge stitching");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
prop = RNA_def_collection_runtime(ot->srna, "selection", &RNA_SelectedUvElement, "Selection", "");
/* Selection should not be editable or viewed in toolbar */
RNA_def_property_flag(prop, PROP_HIDDEN);
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index b50b8d466f1..b80862d4db5 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -87,6 +87,24 @@
#include "uvedit_intern.h"
#include "uvedit_parametrizer.h"
+static void modifier_unwrap_state(Object *obedit, Scene *scene, short *use_subsurf)
+{
+ ModifierData *md;
+ short subsurf = scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF;
+
+ md = obedit->modifiers.first;
+
+ /* subsurf will take the modifier settings only if modifier is first or right after mirror */
+ if (subsurf) {
+ if (md && md->type == eModifierType_Subsurf)
+ subsurf = TRUE;
+ else
+ subsurf = FALSE;
+ }
+
+ *use_subsurf = subsurf;
+}
+
static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit)
{
Main *bmain = CTX_data_main(C);
@@ -103,7 +121,7 @@ static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit)
return 1;
if (em && em->bm->totface && !CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY))
- ED_mesh_uv_texture_add(C, obedit->data, NULL, TRUE);
+ ED_mesh_uv_texture_add(obedit->data, NULL, true);
if (!ED_uvedit_test(obedit))
return 0;
@@ -143,13 +161,16 @@ static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit)
/****************** Parametrizer Conversion ***************/
-static int uvedit_have_selection(Scene *scene, BMEditMesh *em, short implicit)
+static bool uvedit_have_selection(Scene *scene, BMEditMesh *em, bool implicit)
{
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
- MLoopUV *luv;
+ if (!CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV)) {
+ return (em->bm->totfacesel != 0);
+ }
+
/* verify if we have any selected uv's before unwrapping,
* so we can cancel the operator early */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
@@ -157,14 +178,10 @@ static int uvedit_have_selection(Scene *scene, BMEditMesh *em, short implicit)
if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
continue;
}
- else if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) || !BM_elem_flag_test(efa, BM_ELEM_SELECT))
+ else if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
- if (!luv)
- return 1;
-
if (uvedit_uv_select_test(em, scene, l))
break;
}
@@ -172,13 +189,13 @@ static int uvedit_have_selection(Scene *scene, BMEditMesh *em, short implicit)
if (implicit && !l)
continue;
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-static void ED_uvedit_get_aspect(Scene *scene, Object *ob, BMEditMesh *em, float *aspx, float *aspy)
+void uvedit_get_aspect(Scene *scene, Object *ob, BMEditMesh *em, float *aspx, float *aspy)
{
int sloppy = TRUE;
int selected = FALSE;
@@ -208,6 +225,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh
short implicit, short fill, short sel,
short correct_aspect)
{
+ BMesh *bm = em->bm;
ScanFillContext sf_ctx;
ParamHandle *handle;
BMFace *efa;
@@ -215,12 +233,15 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh
BMEdge *eed;
BMIter iter, liter;
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
handle = param_construct_begin();
+
if (correct_aspect) {
float aspx, aspy;
- ED_uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
+ uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
if (aspx != aspy)
param_aspect_ratio(handle, aspx, aspy);
@@ -266,7 +287,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh
* about which split is best for unwrapping than scanfill */
i = 0;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
vkeys[i] = (ParamKey)BM_elem_index_get(l->v);
co[i] = l->v->co;
uv[i] = luv->uv;
@@ -314,7 +335,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh
ls[2] = sf_tri->v3->tmp.p;
for (i = 0; i < 3; i++) {
- MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, ls[i]->head.data, CD_MLOOPUV);
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(ls[i], cd_loop_uv_offset);
vkeys[i] = (ParamKey)BM_elem_index_get(ls[i]->v);
co[i] = ls[i]->v->co;
uv[i] = luv->uv;
@@ -346,7 +367,8 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh
}
-static void texface_from_original_index(BMFace *efa, int index, float **uv, ParamBool *pin, ParamBool *select, Scene *scene, BMEditMesh *em)
+static void texface_from_original_index(BMFace *efa, int index, float **uv, ParamBool *pin, ParamBool *select,
+ Scene *scene, BMEditMesh *em, const int cd_loop_uv_offset)
{
BMLoop *l;
BMIter liter;
@@ -361,10 +383,11 @@ static void texface_from_original_index(BMFace *efa, int index, float **uv, Para
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_elem_index_get(l->v) == index) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
*uv = luv->uv;
*pin = (luv->flag & MLOOPUV_PINNED) ? 1 : 0;
*select = (uvedit_uv_select_test(em, scene, l) != 0);
+ break;
}
}
}
@@ -379,6 +402,9 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
MEdge *edge;
int i;
+ /* pointers to modifier data for unwrap control */
+ ModifierData *md;
+ SubsurfModifierData *smd_real;
/* modifier initialization data, will control what type of subdivision will happen*/
SubsurfModifierData smd = {{0}};
/* Used to hold subsurfed Mesh */
@@ -397,20 +423,25 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
/* similar to the above, we need a way to map edges to their original ones */
BMEdge **edgeMap;
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
handle = param_construct_begin();
if (correct_aspect) {
float aspx, aspy;
- ED_uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
+ uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
if (aspx != aspy)
param_aspect_ratio(handle, aspx, aspy);
}
/* number of subdivisions to perform */
- smd.levels = scene->toolsettings->uv_subsurf_level;
- smd.subdivType = ME_CC_SUBSURF;
+ md = ob->modifiers.first;
+ smd_real = (SubsurfModifierData *)md;
+
+ smd.levels = smd_real->levels;
+ smd.subdivType = smd_real->subdivType;
initialDerived = CDDM_from_editbmesh(em, FALSE, FALSE);
derivedMesh = subsurf_make_derived_from_derived(initialDerived, &smd,
@@ -434,7 +465,7 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
faceMap = MEM_mallocN(numOfFaces * sizeof(BMFace *), "unwrap_edit_face_map");
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
- EDBM_index_arrays_init(em, 0, 1, 1);
+ EDBM_index_arrays_ensure(em, BM_EDGE | BM_FACE);
/* map subsurfed faces to original editFaces */
for (i = 0; i < numOfFaces; i++)
@@ -445,12 +476,10 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
/* map subsurfed edges to original editEdges */
for (i = 0; i < numOfEdges; i++) {
/* not all edges correspond to an old edge */
- edgeMap[i] = (origEdgeIndices[i] != -1) ?
+ edgeMap[i] = (origEdgeIndices[i] != ORIGINDEX_NONE) ?
EDBM_edge_at_index(em, origEdgeIndices[i]) : NULL;
}
- EDBM_index_arrays_free(em);
-
/* Prepare and feed faces to the solver */
for (i = 0; i < numOfFaces; i++) {
ParamKey key, vkeys[4];
@@ -484,10 +513,10 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
/* This is where all the magic is done. If the vertex exists in the, we pass the original uv pointer to the solver, thus
* flushing the solution to the edit mesh. */
- texface_from_original_index(origFace, origVertIndices[face->v1], &uv[0], &pin[0], &select[0], scene, em);
- texface_from_original_index(origFace, origVertIndices[face->v2], &uv[1], &pin[1], &select[1], scene, em);
- texface_from_original_index(origFace, origVertIndices[face->v3], &uv[2], &pin[2], &select[2], scene, em);
- texface_from_original_index(origFace, origVertIndices[face->v4], &uv[3], &pin[3], &select[3], scene, em);
+ texface_from_original_index(origFace, origVertIndices[face->v1], &uv[0], &pin[0], &select[0], scene, em, cd_loop_uv_offset);
+ texface_from_original_index(origFace, origVertIndices[face->v2], &uv[1], &pin[1], &select[1], scene, em, cd_loop_uv_offset);
+ texface_from_original_index(origFace, origVertIndices[face->v3], &uv[2], &pin[2], &select[2], scene, em, cd_loop_uv_offset);
+ texface_from_original_index(origFace, origVertIndices[face->v4], &uv[3], &pin[3], &select[3], scene, em, cd_loop_uv_offset);
param_face_add(handle, key, 4, vkeys, co, uv, pin, select);
}
@@ -525,17 +554,17 @@ typedef struct MinStretch {
wmTimer *timer;
} MinStretch;
-static int minimize_stretch_init(bContext *C, wmOperator *op)
+static bool minimize_stretch_init(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
MinStretch *ms;
int fill_holes = RNA_boolean_get(op->ptr, "fill_holes");
- short implicit = 1;
+ bool implicit = true;
if (!uvedit_have_selection(scene, em, implicit)) {
- return 0;
+ return false;
}
ms = MEM_callocN(sizeof(MinStretch), "MinStretch");
@@ -554,7 +583,7 @@ static int minimize_stretch_init(bContext *C, wmOperator *op)
op->customdata = ms;
- return 1;
+ return true;
}
static void minimize_stretch_iteration(bContext *C, wmOperator *op, int interactive)
@@ -574,7 +603,7 @@ static void minimize_stretch_iteration(bContext *C, wmOperator *op, int interact
param_flush(ms->handle);
if (sa) {
- BLI_snprintf(str, sizeof(str), "Minimize Stretch. Blend %.2f", ms->blend);
+ BLI_snprintf(str, sizeof(str), "Minimize Stretch. Blend %.2f (Press + and -, or scroll wheel to set)", ms->blend);
ED_area_headerprint(sa, str);
}
@@ -625,7 +654,7 @@ static int minimize_stretch_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int minimize_stretch_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int minimize_stretch_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
MinStretch *ms;
@@ -641,7 +670,7 @@ static int minimize_stretch_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(
return OPERATOR_RUNNING_MODAL;
}
-static int minimize_stretch_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int minimize_stretch_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
MinStretch *ms = op->customdata;
@@ -657,20 +686,24 @@ static int minimize_stretch_modal(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_FINISHED;
case PADPLUSKEY:
case WHEELUPMOUSE:
- if (ms->blend < 0.95f) {
- ms->blend += 0.1f;
- ms->lasttime = 0.0f;
- RNA_float_set(op->ptr, "blend", ms->blend);
- minimize_stretch_iteration(C, op, 1);
+ if (event->val == KM_PRESS) {
+ if (ms->blend < 0.95f) {
+ ms->blend += 0.1f;
+ ms->lasttime = 0.0f;
+ RNA_float_set(op->ptr, "blend", ms->blend);
+ minimize_stretch_iteration(C, op, 1);
+ }
}
break;
case PADMINUS:
case WHEELDOWNMOUSE:
- if (ms->blend > 0.05f) {
- ms->blend -= 0.1f;
- ms->lasttime = 0.0f;
- RNA_float_set(op->ptr, "blend", ms->blend);
- minimize_stretch_iteration(C, op, 1);
+ if (event->val == KM_PRESS) {
+ if (ms->blend > 0.05f) {
+ ms->blend -= 0.1f;
+ ms->lasttime = 0.0f;
+ RNA_float_set(op->ptr, "blend", ms->blend);
+ minimize_stretch_iteration(C, op, 1);
+ }
}
break;
case TIMER:
@@ -728,7 +761,7 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
ParamHandle *handle;
- short implicit = 1;
+ bool implicit = true;
if (!uvedit_have_selection(scene, em, implicit)) {
return OPERATOR_CANCELLED;
@@ -775,7 +808,7 @@ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
ParamHandle *handle;
- short implicit = 1;
+ bool implicit = true;
if (!uvedit_have_selection(scene, em, implicit)) {
return OPERATOR_CANCELLED;
@@ -815,16 +848,18 @@ void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit)
BMEditMesh *em = BMEdit_FromObject(obedit);
short abf = scene->toolsettings->unwrapper == 0;
short fillholes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES;
- short use_subsurf = scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF;
+ short use_subsurf;
+
+ modifier_unwrap_state(obedit, scene, &use_subsurf);
if (!ED_uvedit_test(obedit)) {
return;
}
if (use_subsurf)
- liveHandle = construct_param_handle_subsurfed(scene, obedit, em, fillholes, 0, 1);
+ liveHandle = construct_param_handle_subsurfed(scene, obedit, em, fillholes, FALSE, TRUE);
else
- liveHandle = construct_param_handle(scene, obedit, em, 0, fillholes, 0, 1);
+ liveHandle = construct_param_handle(scene, obedit, em, FALSE, fillholes, FALSE, TRUE);
param_lscm_begin(liveHandle, PARAM_TRUE, abf);
}
@@ -871,16 +906,18 @@ void ED_uvedit_live_unwrap(Scene *scene, Object *obedit)
static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result,
Object *ob, BMEditMesh *em)
{
- BMFace *efa;
- BMLoop *l;
- BMIter iter, liter;
- float min[3], max[3], *cursx;
int around = (v3d) ? v3d->around : V3D_CENTER;
/* only operates on the edit object - this is all that's needed now */
switch (around) {
case V3D_CENTER: /* bounding box center */
+ {
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+ float min[3], max[3];
+
INIT_MINMAX(min, max);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
@@ -892,17 +929,18 @@ static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result,
}
mid_v3_v3v3(result, min, max);
break;
-
+ }
case V3D_CURSOR: /* cursor center */
- cursx = give_cursor(scene, v3d);
+ {
+ const float *curs = give_cursor(scene, v3d);
/* shift to objects world */
- sub_v3_v3v3(result, cursx, ob->obmat[3]);
+ sub_v3_v3v3(result, curs, ob->obmat[3]);
break;
-
+ }
case V3D_LOCAL: /* object center */
case V3D_CENTROID: /* multiple objects centers, only one object here*/
default:
- result[0] = result[1] = result[2] = 0.0;
+ zero_v3(result);
break;
}
}
@@ -938,18 +976,18 @@ static void uv_map_rotation_matrix(float result[4][4], RegionView3D *rv3d, Objec
/* this is "kanonen gegen spatzen", a few plus minus 1 will do here */
/* i wanted to keep the reason here, so we're rotating*/
sideangle = (float)M_PI * (sideangledeg + 180.0f) / 180.0f;
- rotside[0][0] = (float)cos(sideangle);
- rotside[0][1] = -(float)sin(sideangle);
- rotside[1][0] = (float)sin(sideangle);
- rotside[1][1] = (float)cos(sideangle);
- rotside[2][2] = 1.0f;
+ rotside[0][0] = cosf(sideangle);
+ rotside[0][1] = -sinf(sideangle);
+ rotside[1][0] = sinf(sideangle);
+ rotside[1][1] = cosf(sideangle);
+ rotside[2][2] = 1.0f;
upangle = (float)M_PI * upangledeg / 180.0f;
- rotup[1][1] = (float)cos(upangle) / radius;
- rotup[1][2] = -(float)sin(upangle) / radius;
- rotup[2][1] = (float)sin(upangle) / radius;
- rotup[2][2] = (float)cos(upangle) / radius;
- rotup[0][0] = (float)1.0f / radius;
+ rotup[1][1] = cosf(upangle) / radius;
+ rotup[1][2] = -sinf(upangle) / radius;
+ rotup[2][1] = sinf(upangle) / radius;
+ rotup[2][2] = cosf(upangle) / radius;
+ rotup[0][0] = 1.0f / radius;
/* calculate transforms*/
mul_serie_m4(result, rotup, rotside, viewmatrix, rotobj, NULL, NULL, NULL, NULL);
@@ -1020,7 +1058,9 @@ static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em)
BMFace *efa;
float scale, aspx, aspy;
- ED_uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ uvedit_get_aspect(scene, ob, em, &aspx, &aspy);
if (aspx == aspy)
return;
@@ -1029,11 +1069,11 @@ static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em)
scale = aspy / aspx;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT) || BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
+ if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->uv[0] = ((luv->uv[0] - 0.5f) * scale) + 0.5f;
}
}
@@ -1042,11 +1082,11 @@ static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em)
scale = aspx / aspy;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_SELECT) || BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
+ if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->uv[1] = ((luv->uv[1] - 0.5f) * scale) + 0.5f;
}
}
@@ -1076,6 +1116,8 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper
int clip_to_bounds = RNA_boolean_get(op->ptr, "clip_to_bounds");
int scale_to_bounds = RNA_boolean_get(op->ptr, "scale_to_bounds");
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
/* correct for image aspect ratio */
if (correct_aspect)
correct_uv_aspect(scene, ob, em);
@@ -1088,7 +1130,7 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
minmax_v2v2_v2(min, max, luv->uv);
}
}
@@ -1107,7 +1149,7 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ 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;
@@ -1121,7 +1163,7 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
CLAMP(luv->uv[0], 0.0f, 1.0f);
CLAMP(luv->uv[1], 0.0f, 1.0f);
}
@@ -1139,12 +1181,14 @@ void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel)
const short fill_holes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES;
const short correct_aspect = !(scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT);
- const short use_subsurf = scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF;
+ short use_subsurf;
+
+ modifier_unwrap_state(obedit, scene, &use_subsurf);
if (use_subsurf)
handle = construct_param_handle_subsurfed(scene, obedit, em, fill_holes, sel, correct_aspect);
else
- handle = construct_param_handle(scene, obedit, em, 0, fill_holes, sel, correct_aspect);
+ handle = construct_param_handle(scene, obedit, em, FALSE, fill_holes, sel, correct_aspect);
param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0);
param_lscm_solve(handle);
@@ -1167,9 +1211,9 @@ static int unwrap_exec(bContext *C, wmOperator *op)
int fill_holes = RNA_boolean_get(op->ptr, "fill_holes");
int correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect");
int use_subsurf = RNA_boolean_get(op->ptr, "use_subsurf_data");
- int subsurf_level = RNA_int_get(op->ptr, "uv_subsurf_level");
+ short use_subsurf_final;
float obsize[3];
- short implicit = 0;
+ bool implicit = false;
if (!uvedit_have_selection(scene, em, implicit)) {
return OPERATOR_CANCELLED;
@@ -1197,8 +1241,6 @@ static int unwrap_exec(bContext *C, wmOperator *op)
else
RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
- scene->toolsettings->uv_subsurf_level = subsurf_level;
-
if (fill_holes) scene->toolsettings->uvcalc_flag |= UVCALC_FILLHOLES;
else scene->toolsettings->uvcalc_flag &= ~UVCALC_FILLHOLES;
@@ -1208,6 +1250,12 @@ static int unwrap_exec(bContext *C, wmOperator *op)
if (use_subsurf) scene->toolsettings->uvcalc_flag |= UVCALC_USESUBSURF;
else scene->toolsettings->uvcalc_flag &= ~UVCALC_USESUBSURF;
+ /* double up the check here but better keep ED_unwrap_lscm interface simple and not
+ * pass operator for warning append */
+ modifier_unwrap_state(obedit, scene, &use_subsurf_final);
+ if (use_subsurf != use_subsurf_final)
+ BKE_report(op->reports, RPT_INFO, "Subsurf modifier needs to be first to work with unwrap");
+
/* execute unwrap */
ED_unwrap_lscm(scene, obedit, TRUE);
@@ -1242,10 +1290,8 @@ void UV_OT_unwrap(wmOperatorType *ot)
"Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry");
RNA_def_boolean(ot->srna, "correct_aspect", 1, "Correct Aspect",
"Map UVs taking image aspect ratio into account");
- RNA_def_boolean(ot->srna, "use_subsurf_data", 0, "Use Subsurf Data",
+ RNA_def_boolean(ot->srna, "use_subsurf_data", 0, "Use Subsurf Modifier",
"Map UVs taking vertex position after subsurf into account");
- RNA_def_int(ot->srna, "uv_subsurf_level", 1, 1, 6, "Subsurf Target",
- "Number of times to subdivide before calculating UVs", 1, 6);
RNA_def_float_factor(ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
}
@@ -1265,11 +1311,15 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
MLoopUV *luv;
float rotmat[4][4];
+ 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(&em->bm->ldata, CD_MLOOPUV);
+
/* establish the camera object, so we can default to view mapping if anything is wrong with it */
if ((rv3d->persp == RV3D_CAMOB) && (v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
camera = v3d->camera->data;
@@ -1283,7 +1333,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
BLI_uvproject_from_view_ortho(luv->uv, l->v->co, rotmat);
}
}
@@ -1297,7 +1347,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
BLI_uvproject_from_camera(luv->uv, l->v->co, uci);
}
}
@@ -1313,7 +1363,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
BLI_uvproject_from_view(luv->uv, l->v->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
}
}
@@ -1337,7 +1387,7 @@ static int uv_from_view_poll(bContext *C)
return (rv3d != NULL);
}
-void UV_OT_from_view(wmOperatorType *ot)
+void UV_OT_project_from_view(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Project From View";
@@ -1417,11 +1467,11 @@ static void uv_map_mirror(BMEditMesh *em, BMFace *efa, MTexPoly *UNUSED(tf))
float dx;
int i, mi;
- i = 0;
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
+
+ BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
uvs[i] = luv->uv;
- i++;
}
mi = 0;
@@ -1449,11 +1499,15 @@ static int sphere_project_exec(bContext *C, wmOperator *op)
MLoopUV *luv;
float center[3], rotmat[4][4];
+ 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(&em->bm->ldata, CD_MLOOPUV);
+
uv_map_transform(C, op, center, rotmat);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
@@ -1461,7 +1515,7 @@ static int sphere_project_exec(bContext *C, wmOperator *op)
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
uv_sphere_project(luv->uv, l->v->co, center, rotmat);
}
@@ -1524,24 +1578,28 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
MLoopUV *luv;
float center[3], rotmat[4][4];
+ 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(&em->bm->ldata, CD_MLOOPUV);
+
uv_map_transform(C, op, center, rotmat);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
if (!BM_elem_flag_test(efa, BM_ELEM_SELECT))
continue;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
uv_cylinder_project(luv->uv, l->v->co, center, rotmat);
}
+ tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
uv_map_mirror(em, efa, tf);
}
@@ -1586,11 +1644,15 @@ static int cube_project_exec(bContext *C, wmOperator *op)
float cube_size, *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(&em->bm->ldata, CD_MLOOPUV);
+
loc = obedit->obmat[3];
cube_size = RNA_float_get(op->ptr, "cube_size");
@@ -1608,7 +1670,7 @@ static int cube_project_exec(bContext *C, wmOperator *op)
dx = dy = 0;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
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]);
diff --git a/source/blender/freestyle/CMakeLists.txt b/source/blender/freestyle/CMakeLists.txt
new file mode 100644
index 00000000000..71bdb6aaf9e
--- /dev/null
+++ b/source/blender/freestyle/CMakeLists.txt
@@ -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.
+#
+# 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 *****
+
+file(GLOB_RECURSE SRC *.cpp *.h)
+
+set(INC
+ ../blenkernel ../blenloader ../blenlib ../imbuf ../makesdna ../makesrna
+ ../python ../python/intern ../render/extern/include ../render/intern/include
+ ../../../extern/glew/include ../../../intern/guardedalloc ../freestyle
+)
+
+set(INC_SYS
+ ${PYTHON_INCLUDE_DIRS}
+ ${PNG_INC}
+)
+
+add_definitions(-DWITH_FREESTYLE)
+
+if(WIN32)
+ set(INC_SYS ${INC_SYS} ${PTHREADS_INC})
+endif(WIN32)
+
+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
new file mode 100644
index 00000000000..1759d394664
--- /dev/null
+++ b/source/blender/freestyle/FRS_freestyle.h
@@ -0,0 +1,74 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FRS_FREESTYLE_H__
+#define __FRS_FREESTYLE_H__
+
+/** \file blender/freestyle/FRS_freestyle.h
+ * \ingroup freestyle
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "DNA_listBase.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_context.h"
+
+struct Render;
+
+extern Scene *freestyle_scene;
+extern float freestyle_viewpoint[3];
+extern float freestyle_mv[4][4];
+extern float freestyle_proj[4][4];
+extern int freestyle_viewport[4];
+
+/* Rendering */
+void FRS_initialize(void);
+void FRS_set_context(bContext *C);
+void FRS_read_file(bContext *C);
+int FRS_is_freestyle_enabled(struct SceneRenderLayer *srl);
+void FRS_init_stroke_rendering(struct Render *re);
+struct Render *FRS_do_stroke_rendering(struct Render *re, struct SceneRenderLayer *srl);
+void FRS_finish_stroke_rendering(struct Render *re);
+void FRS_composite_result(struct Render *re, struct SceneRenderLayer *srl, struct Render *freestyle_render);
+void FRS_exit(void);
+
+/* FreestyleConfig.linesets */
+void FRS_copy_active_lineset(FreestyleConfig *config);
+void FRS_paste_active_lineset(FreestyleConfig *config);
+void FRS_delete_active_lineset(FreestyleConfig *config);
+void FRS_move_active_lineset_up(FreestyleConfig *config);
+void FRS_move_active_lineset_down(FreestyleConfig *config);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __FRS_FREESTYLE_H__
diff --git a/source/blender/freestyle/SConscript b/source/blender/freestyle/SConscript
new file mode 100644
index 00000000000..d5ccf12d2db
--- /dev/null
+++ b/source/blender/freestyle/SConscript
@@ -0,0 +1,75 @@
+#!/usr/bin/python
+import sys
+Import ('env')
+
+sources = []
+defs = ['WITH_FREESTYLE']
+incs = ''
+
+incs += '../blenkernel ../blenloader ../blenlib ../imbuf ../makesdna ../makesrna'
+incs += ' ../python ../python/intern ../render/extern/include ../render/intern/include'
+incs += ' #/extern/glew/include #/intern/guardedalloc ../freestyle'
+incs += ' ' + env['BF_PYTHON_INC']
+incs += ' ' + env['BF_PNG_INC']
+
+if env['OURPLATFORM'] == 'linux2':
+ cflags='-pthread'
+ incs += ' ../../../extern/binreloc/include'
+
+if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
+ incs += ' ' + env['BF_PTHREADS_INC']
+
+########################################################
+# folders sources
+########################################################
+
+# system
+prefix = 'intern/system'
+system_sources = env.Glob(prefix + '/*.cpp')
+
+# image
+prefix = 'intern/image'
+image_sources = env.Glob(prefix + '/*.cpp')
+
+# geometry
+prefix = 'intern/geometry'
+geometry_sources = env.Glob(prefix + '/*.cpp')
+
+# scene_graph
+prefix = 'intern/scene_graph'
+scene_graph_sources = env.Glob(prefix + '/*.cpp')
+
+# winged_edge
+prefix = 'intern/winged_edge'
+winged_edge_sources = env.Glob(prefix + '/*.cpp')
+
+# view_map
+prefix = 'intern/view_map'
+view_map_sources = env.Glob(prefix + '/*.cpp')
+
+# stroke
+prefix = 'intern/stroke'
+stroke_sources = env.Glob(prefix + '/*.cpp')
+
+# application
+prefix = 'intern/application'
+application_sources = env.Glob(prefix + '/*.cpp')
+
+# blender_interface
+prefix = 'intern/blender_interface'
+interface_sources = env.Glob(prefix + '/*.cpp')
+
+# Python
+prefix = 'intern/python'
+python_sources = env.Glob(prefix + '/*.cpp') + \
+ env.Glob(prefix + '/*/*.cpp') + \
+ env.Glob(prefix + '/*/*/*.cpp') + \
+ env.Glob(prefix + '/*/*/*/*.cpp')
+
+sources = system_sources + image_sources + geometry_sources + scene_graph_sources + \
+ winged_edge_sources + view_map_sources + stroke_sources + \
+ application_sources + interface_sources + python_sources
+
+env.BlenderLib(libname="bf_freestyle", sources=sources, includes=Split(incs),
+ defines=defs, libtype=['core'], priority = [370] # bf_python is 361
+)
diff --git a/source/blender/freestyle/intern/application/AppCanvas.cpp b/source/blender/freestyle/intern/application/AppCanvas.cpp
new file mode 100644
index 00000000000..d2dc14b1c19
--- /dev/null
+++ b/source/blender/freestyle/intern/application/AppCanvas.cpp
@@ -0,0 +1,218 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/application/AppCanvas.cpp
+ * \ingroup freestyle
+ */
+
+#include "Controller.h"
+#include "AppView.h"
+#include "../image/Image.h"
+#include "../system/TimeStamp.h"
+#include "../stroke/StrokeRenderer.h"
+#include "AppCanvas.h"
+#include "AppConfig.h"
+#include "../stroke/StyleModule.h"
+
+#include "../system/StringUtils.h"
+
+AppCanvas::AppCanvas()
+:Canvas()
+{
+ _pViewer = 0;
+ _MapsPath = StringUtils::toAscii(Config::Path::getInstance()->getMapsDir()).c_str();
+}
+
+AppCanvas::AppCanvas(AppView *iViewer)
+:Canvas()
+{
+ _pViewer = iViewer;
+}
+
+AppCanvas::AppCanvas(const AppCanvas& iBrother)
+:Canvas(iBrother)
+{
+ _pViewer = iBrother._pViewer;
+}
+
+AppCanvas::~AppCanvas()
+{
+ _pViewer = 0;
+}
+
+void AppCanvas::setViewer(AppView *iViewer)
+{
+ _pViewer = iViewer;
+}
+
+int AppCanvas::width() const
+{
+ return _pViewer->width();
+}
+
+int AppCanvas::height() const
+{
+ return _pViewer->height();
+}
+
+BBox<Vec2i> AppCanvas::border() const
+{
+ return _pViewer->border();
+}
+
+float AppCanvas::thickness() const
+{
+ return _pViewer->thickness();
+}
+
+BBox<Vec3r> AppCanvas::scene3DBBox() const
+{
+ return _pViewer->scene3DBBox();
+}
+
+void AppCanvas::preDraw()
+{
+ Canvas::preDraw();
+}
+
+void AppCanvas::init()
+{
+#if 0
+ static bool firsttime = true;
+ if (firsttime) {
+ _Renderer = new BlenderStrokeRenderer;
+ if(!StrokeRenderer::loadTextures()) {
+ cerr << "unable to load stroke textures" << endl;
+ return;
+ }
+ }
+#endif
+}
+
+void AppCanvas::postDraw()
+{
+ for (unsigned int i = 0; i < _StyleModules.size(); i++) {
+ if (!_StyleModules[i]->getDisplayed() || !_Layers[i])
+ continue;
+ _Layers[i]->ScaleThickness(thickness());
+ }
+ Canvas::postDraw();
+}
+
+void AppCanvas::Erase()
+{
+ Canvas::Erase();
+}
+
+// Abstract
+
+void AppCanvas::readColorPixels(int x, int y, int w, int h, RGBImage& oImage) const
+{
+ float *rgb = new float[3 * w * h];
+ memset(rgb, 0, sizeof(float) * 3 * w * h);
+ int xsch = width();
+ int ysch = height();
+ if (_pass_diffuse.buf) {
+ int xmin = border().getMin().x();
+ int ymin = border().getMin().y();
+ int xmax = border().getMax().x();
+ int ymax = border().getMax().y();
+ int rectx = _pass_z.width;
+ int recty = _pass_z.height;
+ float xfac = ((float)rectx) / ((float)(xmax - xmin));
+ float yfac = ((float)recty) / ((float)(ymax - ymin));
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("readColorPixels %d x %d @ (%d, %d) in %d x %d [%d x %d] -- %d x %d @ %d%%\n", w, h, x, y,
+ xsch, ysch, xmax - xmin, ymax - ymin, rectx, recty, (int)(xfac * 100.0f));
+ }
+#endif
+ int ii, jj;
+ for (int j = 0; j < h; j++) {
+ jj = (int)((y - ymin + j) * yfac);
+ if (jj < 0 || jj >= recty)
+ continue;
+ for (int i = 0; i < w; i++) {
+ ii = (int)((x - xmin + i) * xfac);
+ if (ii < 0 || ii >= rectx)
+ continue;
+ memcpy(rgb + (w * j + i) * 3, _pass_diffuse.buf + (rectx * jj + ii) * 3, sizeof(float) * 3);
+ }
+ }
+ }
+ oImage.setArray(rgb, xsch, ysch, w, h, x, y, false);
+}
+
+void AppCanvas::readDepthPixels(int x, int y, int w, int h, GrayImage& oImage) const
+{
+ float *z = new float[w * h];
+ memset(z, 0, sizeof(float) * w * h);
+ int xsch = width();
+ int ysch = height();
+ if (_pass_z.buf) {
+ int xmin = border().getMin().x();
+ int ymin = border().getMin().y();
+ int xmax = border().getMax().x();
+ int ymax = border().getMax().y();
+ int rectx = _pass_z.width;
+ int recty = _pass_z.height;
+ float xfac = ((float)rectx) / ((float)(xmax - xmin));
+ float yfac = ((float)recty) / ((float)(ymax - ymin));
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("readDepthPixels %d x %d @ (%d, %d) in %d x %d [%d x %d] -- %d x %d @ %d%%\n", w, h, x, y,
+ xsch, ysch, xmax - xmin, ymax - ymin, rectx, recty, (int)(xfac * 100.0f));
+ }
+#endif
+ int ii, jj;
+ for (int j = 0; j < h; j++) {
+ jj = (int)((y - ymin + j) * yfac);
+ if (jj < 0 || jj >= recty)
+ continue;
+ for (int i = 0; i < w; i++) {
+ ii = (int)((x - xmin + i) * xfac);
+ if (ii < 0 || ii >= rectx)
+ continue;
+ z[w * j + i] = _pass_z.buf[rectx * jj + ii];
+ }
+ }
+ }
+ oImage.setArray(z, xsch, ysch, w, h, x, y, false);
+}
+
+void AppCanvas::RenderStroke(Stroke *iStroke)
+{
+ if (_basic)
+ iStroke->RenderBasic(_Renderer);
+ else
+ iStroke->Render(_Renderer);
+}
+
+
+void AppCanvas::update()
+{
+}
diff --git a/source/blender/freestyle/intern/application/AppCanvas.h b/source/blender/freestyle/intern/application/AppCanvas.h
new file mode 100644
index 00000000000..a839c1efe0d
--- /dev/null
+++ b/source/blender/freestyle/intern/application/AppCanvas.h
@@ -0,0 +1,101 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __APPCANVAS_H__
+#define __APPCANVAS_H__
+
+/** \file blender/freestyle/intern/application/AppCanvas.h
+ * \ingroup freestyle
+ */
+
+#include "../stroke/Canvas.h"
+#include "AppView.h"
+
+class AppCanvas : public Canvas
+{
+public:
+ AppCanvas();
+ AppCanvas(AppView *iViewer);
+ AppCanvas(const AppCanvas& iBrother);
+ virtual ~AppCanvas();
+
+ /*! operations that need to be done before a draw */
+ virtual void preDraw();
+
+ /*! operations that need to be done after a draw */
+ virtual void postDraw();
+
+ /*! Erases the layers and clears the canvas */
+ virtual void Erase();
+
+ /* init the canvas */
+ virtual void init();
+
+ /*! Reads a pixel area from the canvas */
+ virtual void readColorPixels(int x, int y, int w, int h, RGBImage& oImage) const;
+ /*! Reads a depth pixel area from the canvas */
+ virtual void readDepthPixels(int x, int y, int w, int h, GrayImage& oImage) const;
+
+ virtual BBox<Vec3r> scene3DBBox() const;
+
+ /* abstract */
+ virtual void RenderStroke(Stroke *);
+ virtual void update();
+
+
+ /*! accessors */
+ virtual int width() const;
+ virtual int height() const;
+ virtual BBox<Vec2i> border() const;
+ virtual float thickness() const;
+
+ AppView *_pViewer;
+ inline const AppView * viewer() const {return _pViewer;}
+
+ /*! modifiers */
+ void setViewer(AppView *iViewer);
+
+ /* soc */
+ void setPassDiffuse(float *buf, int width, int height) {
+ _pass_diffuse.buf = buf;
+ _pass_diffuse.width = width;
+ _pass_diffuse.height = height;
+ }
+ void setPassZ(float *buf, int width, int height) {
+ _pass_z.buf = buf;
+ _pass_z.width = width;
+ _pass_z.height = height;
+ }
+
+private:
+ struct {
+ float *buf;
+ int width, height;
+ } _pass_diffuse, _pass_z;
+};
+
+#endif // __APPCANVAS_H__
diff --git a/source/blender/freestyle/intern/application/AppConfig.cpp b/source/blender/freestyle/intern/application/AppConfig.cpp
new file mode 100644
index 00000000000..2500c9c68ee
--- /dev/null
+++ b/source/blender/freestyle/intern/application/AppConfig.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/application/AppConfig.cpp
+ * \ingroup freestyle
+ */
+
+#include "AppConfig.h"
+#include <iostream>
+
+#include "../system/StringUtils.h"
+
+using namespace std;
+
+extern "C" {
+#include "BLI_path_util.h"
+}
+
+namespace Config {
+
+Path *Path::_pInstance = 0;
+Path::Path()
+{
+ // get the root directory
+ // soc
+ setRootDir(BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, NULL));
+
+ _pInstance = this;
+}
+
+void Path::setRootDir(const string& iRootDir)
+{
+ _ProjectDir = iRootDir + string(DIR_SEP.c_str()) + "freestyle";
+ _ModelsPath = "";
+ _PatternsPath = _ProjectDir + string(DIR_SEP.c_str()) + "data" + string(DIR_SEP.c_str()) + "textures" +
+ string(DIR_SEP.c_str()) + "variation_patterns" + string(DIR_SEP.c_str());
+ _BrushesPath = _ProjectDir + string(DIR_SEP.c_str()) + "data" + string(DIR_SEP.c_str()) + "textures" +
+ string(DIR_SEP.c_str()) + "brushes" + string(DIR_SEP.c_str());
+ _PythonPath = _ProjectDir + string(DIR_SEP.c_str()) + "style_modules" + string(DIR_SEP.c_str());
+ if (getenv("PYTHONPATH")) {
+ _PythonPath += string(PATH_SEP.c_str()) + string(getenv("PYTHONPATH"));
+ }
+ _EnvMapDir = _ProjectDir + string(DIR_SEP.c_str()) + "data" + string(DIR_SEP.c_str()) + "env_map" +
+ string(DIR_SEP.c_str());
+ _MapsDir = _ProjectDir + string(DIR_SEP.c_str()) + "data" + string(DIR_SEP.c_str()) + "maps" +
+ string(DIR_SEP.c_str());
+}
+
+void Path::setHomeDir(const string& iHomeDir)
+{
+ _HomeDir = iHomeDir;
+}
+
+Path::~Path()
+{
+ _pInstance = 0;
+}
+
+Path *Path::getInstance()
+{
+ return _pInstance;
+}
+
+string Path::getEnvVar(const string& iEnvVarName)
+{
+ string value;
+ if (!getenv(StringUtils::toAscii(iEnvVarName).c_str())) {
+ cerr << "Warning: You may want to set the $" <<
+ StringUtils::toAscii(iEnvVarName) <<
+ " environment variable to use Freestyle." << endl <<
+ " Otherwise, the current directory will be used instead." << endl;
+ value = ".";
+ }
+ else {
+ value = getenv(StringUtils::toAscii(iEnvVarName).c_str());
+ }
+ return value;
+}
+
+} // End of namepace Config
diff --git a/source/blender/freestyle/intern/application/AppConfig.h b/source/blender/freestyle/intern/application/AppConfig.h
new file mode 100644
index 00000000000..54dde44df7c
--- /dev/null
+++ b/source/blender/freestyle/intern/application/AppConfig.h
@@ -0,0 +1,108 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __APP_CONFIG_H__
+#define __APP_CONFIG_H__
+
+/** \file blender/freestyle/intern/application/AppConfig.h
+ * \ingroup freestyle
+ * \brief Configuration file
+ * \author Emmanuel Turquin
+ * \date 26/02/2003
+ */
+
+#include <string>
+#include "../system/FreestyleConfig.h"
+#include "../system/Precision.h"
+
+using namespace std;
+
+namespace Config {
+
+class Path {
+protected:
+ static Path * _pInstance;
+ string _ProjectDir;
+ string _ModelsPath;
+ string _PatternsPath;
+ string _BrushesPath;
+ string _PythonPath;
+ string _EnvMapDir;
+ string _MapsDir;
+ string _HomeDir;
+
+public:
+ Path();
+ virtual ~Path();
+ static Path *getInstance();
+
+ void setRootDir(const string& iRootDir);
+ void setHomeDir(const string& iHomeDir);
+
+ const string& getProjectDir() const {return _ProjectDir;}
+ const string& getModelsPath() const {return _ModelsPath;}
+ const string& getPatternsPath() const {return _PatternsPath;}
+ const string& getBrushesPath() const {return _BrushesPath;}
+ const string& getPythonPath() const {return _PythonPath;}
+ const string& getEnvMapDir() const {return _EnvMapDir;}
+ const string& getMapsDir() const {return _MapsDir;}
+ const string& getHomeDir() const {return _HomeDir;}
+
+ static string getEnvVar(const string& iEnvVarName);
+};
+
+//
+// Configuration, default values
+//
+//////////////////////////////////////////////////////////////
+
+// Application
+static const string APPLICATION_NAME("APPNAME");
+static const string APPLICATION_VERSION("APPVERSION");
+
+// ViewMap
+static const string VIEWMAP_EXTENSION("vm");
+static const string VIEWMAP_MAGIC("ViewMap File");
+static const string VIEWMAP_VERSION("1.9");
+
+// Style modules
+static const string STYLE_MODULE_EXTENSION("py");
+static const string STYLE_MODULES_LIST_EXTENSION("sml");
+
+// Options
+static const string OPTIONS_DIR("." + APPLICATION_NAME);
+static const string OPTIONS_FILE("options.xml");
+static const string OPTIONS_CURRENT_DIRS_FILE("current_dirs.xml");
+static const string OPTIONS_QGLVIEWER_FILE("qglviewer.xml");
+
+// Default options
+static const real DEFAULT_SPHERE_RADIUS = 1.0;
+static const real DEFAULT_DKR_EPSILON = 0.0;
+
+} // End of namepace Config
+
+#endif // __APP_CONFIG_H__
diff --git a/source/blender/freestyle/intern/application/AppView.cpp b/source/blender/freestyle/intern/application/AppView.cpp
new file mode 100644
index 00000000000..cd38fa0ae0c
--- /dev/null
+++ b/source/blender/freestyle/intern/application/AppView.cpp
@@ -0,0 +1,198 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/application/AppView.cpp
+ * \ingroup freestyle
+ */
+
+/* This header file needs to be included first, in order to avoid a
+ compilation with MinGW (see the commit log of revision 28253) */
+extern "C" {
+#include "BLI_jitter.h"
+}
+
+#include <iostream>
+
+#include "Controller.h"
+#include "AppConfig.h"
+#include "AppView.h"
+#include "../view_map/Silhouette.h"
+#include "../view_map/ViewMap.h"
+#include "../scene_graph/LineRep.h"
+#include "../scene_graph/NodeLight.h"
+#include "../scene_graph/NodeShape.h"
+#include "../scene_graph/VertexRep.h"
+#include "../stroke/Canvas.h"
+#include "../system/StringUtils.h"
+
+extern "C" {
+#include "BLI_blenlib.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#if 1 // FRS_antialiasing
+# include "BKE_global.h"
+# include "DNA_scene_types.h"
+#endif
+
+#include "FRS_freestyle.h"
+}
+
+AppView::AppView(const char *iName)
+{
+ _Fovy = DEG2RADF(30.0f);
+ _ModelRootNode = new NodeDrawingStyle;
+ _SilhouetteRootNode = new NodeDrawingStyle;
+ _DebugRootNode = new NodeDrawingStyle;
+
+ _RootNode.AddChild(_ModelRootNode);
+ _SilhouetteRootNode->setStyle(DrawingStyle::LINES);
+ _SilhouetteRootNode->setLightingEnabled(false);
+ _SilhouetteRootNode->setLineWidth(2.0f);
+ _SilhouetteRootNode->setPointSize(3.0f);
+
+ _RootNode.AddChild(_SilhouetteRootNode);
+
+ _DebugRootNode->setStyle(DrawingStyle::LINES);
+ _DebugRootNode->setLightingEnabled(false);
+ _DebugRootNode->setLineWidth(1.0f);
+
+ _RootNode.AddChild(_DebugRootNode);
+
+ _minBBox = std::min(std::min(_ModelRootNode->bbox().getMin()[0], _ModelRootNode->bbox().getMin()[1]),
+ _ModelRootNode->bbox().getMin()[2]);
+ _maxBBox = std::max(std::max(_ModelRootNode->bbox().getMax()[0], _ModelRootNode->bbox().getMax()[1]),
+ _ModelRootNode->bbox().getMax()[2]);
+
+ _maxAbs = std::max(rabs(_minBBox), rabs(_maxBBox));
+ _minAbs = std::min(rabs(_minBBox), rabs(_maxBBox));
+
+ _p2DSelectionNode = new NodeDrawingStyle;
+ _p2DSelectionNode->setLightingEnabled(false);
+ _p2DSelectionNode->setStyle(DrawingStyle::LINES);
+ _p2DSelectionNode->setLineWidth(5.0f);
+
+ _p2DNode.AddChild(_p2DSelectionNode);
+
+ NodeLight *light = new NodeLight;
+ _Light.AddChild(light);
+}
+
+AppView::~AppView()
+{
+ /*int ref =*/ /* UNUSED */ _RootNode.destroy();
+
+ _Light.destroy();
+ /*ref =*/ /* UNUSED */ _p2DNode.destroy();
+}
+
+real AppView::distanceToSceneCenter()
+{
+ BBox<Vec3r> bbox = _ModelRootNode->bbox();
+
+ Vec3r v(freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]);
+ v -= 0.5 * (bbox.getMin() + bbox.getMax());
+
+ return v.norm();
+}
+
+real AppView::znear()
+{
+ BBox<Vec3r> bbox = _ModelRootNode->bbox();
+ Vec3r u = bbox.getMin();
+ Vec3r v = bbox.getMax();
+ Vec3r cameraCenter(freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]);
+
+ Vec3r w1(u[0], u[1], u[2]);
+ Vec3r w2(v[0], u[1], u[2]);
+ Vec3r w3(u[0], v[1], u[2]);
+ Vec3r w4(v[0], v[1], u[2]);
+ Vec3r w5(u[0], u[1], v[2]);
+ Vec3r w6(v[0], u[1], v[2]);
+ Vec3r w7(u[0], v[1], v[2]);
+ Vec3r w8(v[0], v[1], v[2]);
+
+ real _znear = std::min((w1 - cameraCenter).norm(),
+ std::min((w2 - cameraCenter).norm(),
+ std::min((w3 - cameraCenter).norm(),
+ std::min((w4 - cameraCenter).norm(),
+ std::min((w5 - cameraCenter).norm(),
+ std::min((w6 - cameraCenter).norm(),
+ std::min((w7 - cameraCenter).norm(),
+ (w8 - cameraCenter).norm()
+ )
+ )
+ )
+ )
+ )
+ )
+ );
+
+ return std::max(_znear, 0.001);
+}
+
+real AppView::zfar()
+{
+ BBox<Vec3r> bbox = _ModelRootNode->bbox();
+ Vec3r u = bbox.getMin();
+ Vec3r v = bbox.getMax();
+ Vec3r cameraCenter(freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]);
+
+ Vec3r w1(u[0], u[1], u[2]);
+ Vec3r w2(v[0], u[1], u[2]);
+ Vec3r w3(u[0], v[1], u[2]);
+ Vec3r w4(v[0], v[1], u[2]);
+ Vec3r w5(u[0], u[1], v[2]);
+ Vec3r w6(v[0], u[1], v[2]);
+ Vec3r w7(u[0], v[1], v[2]);
+ Vec3r w8(v[0], v[1], v[2]);
+
+ real _zfar = std::max((w1 - cameraCenter).norm(),
+ std::max((w2 - cameraCenter).norm(),
+ std::max((w3 - cameraCenter).norm(),
+ std::max((w4 - cameraCenter).norm(),
+ std::max((w5 - cameraCenter).norm(),
+ std::max((w6 - cameraCenter).norm(),
+ std::max((w7 - cameraCenter).norm(),
+ (w8 - cameraCenter).norm()
+ )
+ )
+ )
+ )
+ )
+ )
+ );
+
+ return _zfar;
+}
+
+real AppView::GetFocalLength()
+{
+ real Near = std::max(0.1, (real)(-2.0f * _maxAbs + distanceToSceneCenter()));
+ return Near;
+}
diff --git a/source/blender/freestyle/intern/application/AppView.h b/source/blender/freestyle/intern/application/AppView.h
new file mode 100644
index 00000000000..0aa3f8a4005
--- /dev/null
+++ b/source/blender/freestyle/intern/application/AppView.h
@@ -0,0 +1,238 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __APPVIEW_H__
+#define __APPVIEW_H__
+
+/** \file blender/freestyle/intern/application/AppView.h
+ * \ingroup freestyle
+ */
+
+#include "AppConfig.h"
+#include "../geometry/Geom.h"
+#include "../geometry/BBox.h"
+#include "../scene_graph/NodeDrawingStyle.h"
+#include "../system/Precision.h"
+
+using namespace Geometry;
+
+class AppView
+{
+public:
+ AppView(const char *iName = 0);
+ virtual ~AppView();
+
+public:
+ //inherited
+ inline unsigned int width() {return _width;}
+ inline unsigned int height() {return _height;}
+ inline BBox<Vec2i> border() {return _border;}
+ inline float thickness() {return _thickness;}
+ inline void setWidth(unsigned int width) {_width = width;}
+ inline void setHeight(unsigned int height) {_height = height;}
+ inline void setBorder(int xmin, int ymin, int xmax, int ymax) {
+ _border = BBox<Vec2i>(Vec2i(xmin, ymin), Vec2i(xmax, ymax));
+ }
+ inline void setThickness(float thickness) {_thickness = thickness;}
+
+protected:
+ unsigned int _width, _height;
+ BBox<Vec2i> _border;
+ float _thickness;
+
+public:
+ /*! Sets the model to draw in the viewer
+ * iModel
+ * The Root Node of the model
+ */
+ inline void setModel(NodeGroup *iModel)
+ {
+ if (0 != _ModelRootNode->numberOfChildren()) {
+ _ModelRootNode->DetachChildren();
+ _ModelRootNode->clearBBox();
+ }
+
+ AddModel(iModel);
+ }
+
+ /*! Adds a model for displaying in the viewer */
+ inline void AddModel(NodeGroup *iModel)
+ {
+ _ModelRootNode->AddChild(iModel);
+ _ModelRootNode->UpdateBBox();
+
+ _minBBox = std::min(std::min(_ModelRootNode->bbox().getMin()[0], _ModelRootNode->bbox().getMin()[1]),
+ _ModelRootNode->bbox().getMin()[2]);
+ _maxBBox = std::max(std::max(_ModelRootNode->bbox().getMax()[0], _ModelRootNode->bbox().getMax()[1]),
+ _ModelRootNode->bbox().getMax()[2]);
+
+ _maxAbs = std::max(rabs(_minBBox), rabs(_maxBBox));
+ _minAbs = std::min(rabs(_minBBox), rabs(_maxBBox));
+ }
+
+ inline void AddSilhouette(NodeGroup *iSilhouette)
+ {
+ _SilhouetteRootNode->AddChild(iSilhouette);
+ }
+
+ inline void Add2DSilhouette(NodeGroup *iSilhouette)
+ {
+ //_pFENode->AddChild(iSilhouette);
+ }
+
+ inline void Add2DVisibleSilhouette(NodeGroup *iVSilhouette)
+ {
+ //_pVisibleSilhouetteNode->AddChild(iVSilhouette);
+ }
+
+ inline void setDebug(NodeGroup *iDebug)
+ {
+ if (0 != _DebugRootNode->numberOfChildren()) {
+ _DebugRootNode->DetachChildren();
+ _DebugRootNode->clearBBox();
+ }
+
+ AddDebug(iDebug);
+ }
+
+ inline void AddDebug(NodeGroup *iDebug)
+ {
+ _DebugRootNode->AddChild(iDebug);
+ }
+
+ inline void DetachModel(Node *iModel)
+ {
+ _ModelRootNode->DetachChild(iModel);
+ _ModelRootNode->UpdateBBox();
+
+ _minBBox = std::min(std::min(_ModelRootNode->bbox().getMin()[0], _ModelRootNode->bbox().getMin()[1]),
+ _ModelRootNode->bbox().getMin()[2]);
+ _maxBBox = std::max(std::max(_ModelRootNode->bbox().getMax()[0], _ModelRootNode->bbox().getMax()[1]),
+ _ModelRootNode->bbox().getMax()[2]);
+
+ _maxAbs = std::max(rabs(_minBBox), rabs(_maxBBox));
+ _minAbs = std::min(rabs(_minBBox), rabs(_maxBBox));
+ }
+
+ inline void DetachModel()
+ {
+ _ModelRootNode->DetachChildren();
+ _ModelRootNode->clearBBox();
+
+#if 0
+ // 2D Scene
+ _p2DNode.DetachChildren();
+ _pFENode->DetachChildren();
+ _pVisibleSilhouetteNode->DetachChildren();
+#endif
+ }
+
+ inline void DetachSilhouette()
+ {
+ _SilhouetteRootNode->DetachChildren();
+#if 0
+ _pFENode->DetachChildren();
+ _pVisibleSilhouetteNode->DetachChildren();
+#endif
+ _p2DSelectionNode->destroy();
+ }
+
+ inline void DetachVisibleSilhouette()
+ {
+ //_pVisibleSilhouetteNode->DetachChildren();
+ _p2DSelectionNode->destroy();
+ }
+
+ inline void DetachDebug()
+ {
+ _DebugRootNode->DetachChildren();
+ }
+
+ real distanceToSceneCenter();
+ real GetFocalLength();
+
+ inline real GetAspect() const
+ {
+ return ((real)_width / (real)_height);
+ }
+
+ void setHorizontalFov(float hfov)
+ {
+ _Fovy = 2.0 * atan (tan(hfov / 2.0) / GetAspect());
+ }
+
+ inline real GetFovyRadian() const
+ {
+ return _Fovy;
+ }
+
+ inline real GetFovyDegrees() const
+ {
+ return _Fovy * 180.0 / M_PI; // TODO Use RAD2DEG here too?
+ }
+
+ BBox<Vec3r> scene3DBBox() const {return _ModelRootNode->bbox();}
+
+ real znear();
+ real zfar();
+
+public:
+ /*! Core scene drawing */
+ void DrawScene(SceneVisitor *iRenderer);
+
+ /*! 2D Scene Drawing */
+ void Draw2DScene(SceneVisitor *iRenderer);
+
+protected:
+ /*! fabs or abs */
+ inline int rabs(int x) {return abs(x);}
+ inline real rabs(real x) {return fabs(x);}
+
+protected:
+ float _Fovy;
+
+ //The root node container
+ NodeGroup _RootNode;
+ NodeDrawingStyle *_ModelRootNode;
+ NodeDrawingStyle *_SilhouetteRootNode;
+ NodeDrawingStyle *_DebugRootNode;
+
+ NodeGroup _Light;
+
+ real _minBBox;
+ real _maxBBox;
+ real _maxAbs;
+ real _minAbs;
+
+ // 2D Scene
+ bool _Draw2DScene;
+ bool _Draw3DScene;
+ NodeGroup _p2DNode;
+ NodeDrawingStyle *_p2DSelectionNode;
+};
+
+#endif // __APPVIEW_H__
diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp
new file mode 100644
index 00000000000..bc847bb6114
--- /dev/null
+++ b/source/blender/freestyle/intern/application/Controller.cpp
@@ -0,0 +1,1052 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/application/Controller.cpp
+ * \ingroup freestyle
+ */
+
+#include <string>
+#include <fstream>
+#include <float.h>
+
+#include "AppView.h"
+#include "AppCanvas.h"
+#include "AppConfig.h"
+#include "Controller.h"
+
+#include "../image/Image.h"
+
+#include "../scene_graph/NodeDrawingStyle.h"
+#include "../scene_graph/NodeShape.h"
+#include "../scene_graph/NodeTransform.h"
+#include "../scene_graph/ScenePrettyPrinter.h"
+#include "../scene_graph/VertexRep.h"
+
+#include "../stroke/PSStrokeRenderer.h"
+#include "../stroke/TextStrokeRenderer.h"
+#include "../stroke/StrokeTesselator.h"
+#include "../stroke/StyleModule.h"
+
+#include "../system/StringUtils.h"
+#include "../system/PythonInterpreter.h"
+
+#include "../view_map/SteerableViewMap.h"
+#include "../view_map/ViewMap.h"
+#include "../view_map/ViewMapIO.h"
+#include "../view_map/ViewMapTesselator.h"
+
+#include "../winged_edge/Curvature.h"
+#include "../winged_edge/WEdge.h"
+#include "../winged_edge/WingedEdgeBuilder.h"
+#include "../winged_edge/WXEdgeBuilder.h"
+
+#include "../blender_interface/BlenderFileLoader.h"
+#include "../blender_interface/BlenderStrokeRenderer.h"
+#include "../blender_interface/BlenderStyleModule.h"
+
+#include "BKE_global.h"
+
+// XXX Not inside an "extern C" block???
+#include "DNA_freestyle_types.h"
+
+// XXX Are those "ifdef __cplusplus" useful here?
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "FRS_freestyle.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+Controller::Controller()
+{
+ const string sep(Config::DIR_SEP.c_str());
+#if 0
+ const string filename = Config::Path::getInstance()->getHomeDir() + sep + Config::OPTIONS_DIR + sep +
+ Config::OPTIONS_CURRENT_DIRS_FILE;
+ _current_dirs = new ConfigIO(filename, Config::APPLICATION_NAME + "CurrentDirs", true);
+#endif
+
+ _RootNode = new NodeGroup;
+ _RootNode->addRef();
+
+ _SilhouetteNode = NULL;
+#if 0
+ _ProjectedSilhouette = NULL;
+ _VisibleProjectedSilhouette = NULL;
+#endif
+
+ _DebugNode = new NodeGroup;
+ _DebugNode->addRef();
+
+ _winged_edge = NULL;
+
+ _pView = NULL;
+ _pRenderMonitor = NULL;
+
+ _edgeTesselationNature = (Nature::SILHOUETTE | Nature::BORDER | Nature::CREASE);
+
+ _ProgressBar = new ProgressBar;
+ _SceneNumFaces = 0;
+ _minEdgeSize = DBL_MAX;
+ _EPSILON = 1.0e-6;
+ _bboxDiag = 0;
+
+ _ViewMap = 0;
+
+ _Canvas = 0;
+
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_adaptive_traditional;
+ //_VisibilityAlgo = ViewMapBuilder::ray_casting;
+
+ _Canvas = new AppCanvas;
+
+ _inter = new PythonInterpreter();
+ _EnableQI = true;
+ _EnableFaceSmoothness = false;
+ _ComputeRidges = true;
+ _ComputeSteerableViewMap = false;
+ _ComputeSuggestive = true;
+ _ComputeMaterialBoundaries = true;
+ _sphereRadius = 1.0;
+ _creaseAngle = 134.43;
+
+ init_options();
+}
+
+Controller::~Controller()
+{
+ if (NULL != _RootNode) {
+ int ref = _RootNode->destroy();
+ if (0 == ref)
+ delete _RootNode;
+ }
+
+ if (NULL != _SilhouetteNode) {
+ int ref = _SilhouetteNode->destroy();
+ if (0 == ref)
+ delete _SilhouetteNode;
+ }
+
+ if (NULL != _DebugNode) {
+ int ref = _DebugNode->destroy();
+ if (0 == ref)
+ delete _DebugNode;
+ }
+
+ if (_winged_edge) {
+ delete _winged_edge;
+ _winged_edge = NULL;
+ }
+
+ if (0 != _ViewMap) {
+ delete _ViewMap;
+ _ViewMap = 0;
+ }
+
+ if (0 != _Canvas) {
+ delete _Canvas;
+ _Canvas = 0;
+ }
+
+ if (_inter) {
+ delete _inter;
+ _inter = NULL;
+ }
+
+ //delete _current_dirs;
+}
+
+void Controller::setView(AppView *iView)
+{
+ if (NULL == iView)
+ return;
+
+ _pView = iView;
+ _Canvas->setViewer(_pView);
+}
+
+void Controller::setRenderMonitor(RenderMonitor *iRenderMonitor)
+{
+ _pRenderMonitor = iRenderMonitor;
+}
+
+void Controller::setPassDiffuse(float *buf, int width, int height)
+{
+ AppCanvas *app_canvas = dynamic_cast<AppCanvas *>(_Canvas);
+ assert(app_canvas != 0);
+ app_canvas->setPassDiffuse(buf, width, height);
+}
+
+void Controller::setPassZ(float *buf, int width, int height)
+{
+ AppCanvas *app_canvas = dynamic_cast<AppCanvas *>(_Canvas);
+ assert(app_canvas != 0);
+ app_canvas->setPassZ(buf, width, height);
+}
+
+void Controller::setContext(bContext *C)
+{
+ PythonInterpreter *py_inter = dynamic_cast<PythonInterpreter*>(_inter);
+ assert(py_inter != 0);
+ py_inter->setContext(C);
+}
+
+int Controller::LoadMesh(Render *re, SceneRenderLayer *srl)
+{
+ BlenderFileLoader loader(re, srl);
+
+ loader.setRenderMonitor(_pRenderMonitor);
+
+ _Chrono.start();
+
+ NodeGroup *blenderScene = loader.Load();
+
+ if (blenderScene == NULL) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Cannot load scene" << endl;
+ }
+ return 1;
+ }
+
+ if (blenderScene->numberOfChildren() < 1) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Empty scene" << endl;
+ }
+ blenderScene->destroy();
+ delete blenderScene;
+ return 1;
+ }
+
+ real duration = _Chrono.stop();
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Scene loaded" << endl;
+ printf("Mesh cleaning : %lf\n", duration);
+ }
+ _SceneNumFaces += loader.numFacesRead();
+
+ if (loader.minEdgeSize() < _minEdgeSize) {
+ _minEdgeSize = loader.minEdgeSize();
+ }
+
+#if 0 // DEBUG
+ ScenePrettyPrinter spp;
+ blenderScene->accept(spp);
+#endif
+
+ _RootNode->AddChild(blenderScene);
+ _RootNode->UpdateBBox(); // FIXME: Correct that by making a Renderer to compute the bbox
+
+ _pView->setModel(_RootNode);
+ //_pView->FitBBox();
+
+ if (_pRenderMonitor->testBreak())
+ return 0;
+
+ _Chrono.start();
+
+ WXEdgeBuilder wx_builder;
+ wx_builder.setRenderMonitor(_pRenderMonitor);
+ blenderScene->accept(wx_builder);
+ _winged_edge = wx_builder.getWingedEdge();
+
+ duration = _Chrono.stop();
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("WEdge building : %lf\n", duration);
+ }
+
+#if 0
+ _pView->setDebug(_DebugNode);
+
+ // delete stuff
+ if (0 != ws_builder) {
+ delete ws_builder;
+ ws_builder = 0;
+ }
+
+ soc QFileInfo qfi(iFileName);
+ soc string basename((const char*)qfi.fileName().toAscii().data());
+ char cleaned[FILE_MAX];
+ BLI_strncpy(cleaned, iFileName, FILE_MAX);
+ BLI_cleanup_file(NULL, cleaned);
+ string basename = StringUtils::toAscii(string(cleaned));
+#endif
+
+ _ListOfModels.push_back("Blender_models");
+
+ _bboxDiag = (_RootNode->bbox().getMax() - _RootNode->bbox().getMin()).norm();
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Triangles nb : " << _SceneNumFaces << endl;
+ cout << "Bounding Box : " << _bboxDiag << endl;
+ }
+
+ ClearRootNode();
+
+ return 0;
+}
+
+void Controller::CloseFile()
+{
+ WShape::setCurrentId(0);
+ _ListOfModels.clear();
+
+ // We deallocate the memory:
+ ClearRootNode();
+ DeleteWingedEdge();
+ DeleteViewMap();
+
+ // clears the canvas
+ _Canvas->Clear();
+
+ // soc: reset passes
+ setPassDiffuse(NULL, 0, 0);
+ setPassZ(NULL, 0, 0);
+}
+
+void Controller::ClearRootNode()
+{
+ _pView->DetachModel();
+ if (NULL != _RootNode) {
+ int ref = _RootNode->destroy();
+ if (0 == ref)
+ _RootNode->addRef();
+ _RootNode->clearBBox();
+ }
+}
+
+void Controller::DeleteWingedEdge()
+{
+ if (_winged_edge) {
+ delete _winged_edge;
+ _winged_edge = NULL;
+ }
+
+ // clears the grid
+ _Grid.clear();
+ _SceneNumFaces = 0;
+ _minEdgeSize = DBL_MAX;
+}
+
+void Controller::DeleteViewMap()
+{
+ _pView->DetachSilhouette();
+ if (NULL != _SilhouetteNode) {
+ int ref = _SilhouetteNode->destroy();
+ if (0 == ref) {
+ delete _SilhouetteNode;
+ _SilhouetteNode = NULL;
+ }
+ }
+
+#if 0
+ if (NULL != _ProjectedSilhouette) {
+ int ref = _ProjectedSilhouette->destroy();
+ if (0 == ref) {
+ delete _ProjectedSilhouette;
+ _ProjectedSilhouette = NULL;
+ }
+ }
+ if (NULL != _VisibleProjectedSilhouette) {
+ int ref = _VisibleProjectedSilhouette->destroy();
+ if (0 == ref) {
+ delete _VisibleProjectedSilhouette;
+ _VisibleProjectedSilhouette = NULL;
+ }
+ }
+#endif
+
+ _pView->DetachDebug();
+ if (NULL != _DebugNode) {
+ int ref = _DebugNode->destroy();
+ if (0 == ref)
+ _DebugNode->addRef();
+ }
+
+ if (NULL != _ViewMap) {
+ delete _ViewMap;
+ _ViewMap = NULL;
+ }
+}
+
+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
+
+ // retrieve the 3D viewpoint and transformations information
+ //----------------------------------------------------------
+ // Save the viewpoint context at the view level in order
+ // to be able to restore it later:
+
+ // 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]);
+
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "mv" << endl;
+ }
+#endif
+ real mv[4][4];
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ mv[i][j] = freestyle_mv[i][j];
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << mv[i][j] << " ";
+ }
+#endif
+ }
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << endl;
+ }
+#endif
+ }
+
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "\nproj" << endl;
+ }
+#endif
+ real proj[4][4];
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ proj[i][j] = freestyle_proj[i][j];
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << proj[i][j] << " ";
+ }
+#endif
+ }
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << endl;
+ }
+#endif
+ }
+
+ int viewport[4];
+ for (int i = 0; i < 4; i++)
+ viewport[i] = freestyle_viewport[i];
+
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "\nfocal:" << _pView->GetFocalLength() << endl << endl;
+ }
+#endif
+
+ // Flag the WXEdge structure for silhouette edge detection:
+ //----------------------------------------------------------
+
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "\n=== Detecting silhouette edges ===" << endl;
+ }
+ _Chrono.start();
+
+ edgeDetector.setViewpoint(Vec3r(vp));
+ edgeDetector.enableOrthographicProjection(proj[3][3] != 0.0);
+ edgeDetector.enableRidgesAndValleysFlag(_ComputeRidges);
+ edgeDetector.enableSuggestiveContours(_ComputeSuggestive);
+ edgeDetector.enableMaterialBoundaries(_ComputeMaterialBoundaries);
+ edgeDetector.enableFaceSmoothness(_EnableFaceSmoothness);
+ edgeDetector.setCreaseAngle(_creaseAngle);
+ edgeDetector.setSphereRadius(_sphereRadius);
+ edgeDetector.setSuggestiveContourKrDerivativeEpsilon(_suggestiveContourKrDerivativeEpsilon);
+ edgeDetector.setRenderMonitor(_pRenderMonitor);
+ edgeDetector.processShapes(*_winged_edge);
+
+ real duration = _Chrono.stop();
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("Feature lines : %lf\n", duration);
+ }
+
+ if (_pRenderMonitor->testBreak())
+ return;
+
+ // Builds the view map structure from the flagged WSEdge structure:
+ //----------------------------------------------------------
+ ViewMapBuilder vmBuilder;
+ vmBuilder.setEnableQI(_EnableQI);
+ vmBuilder.setViewpoint(Vec3r(vp));
+ vmBuilder.setTransform(mv, proj, viewport, _pView->GetFocalLength(), _pView->GetAspect(), _pView->GetFovyRadian());
+ vmBuilder.setFrustum(_pView->znear(), _pView->zfar());
+ vmBuilder.setGrid(&_Grid);
+ vmBuilder.setRenderMonitor(_pRenderMonitor);
+
+ // Builds a tesselated form of the silhouette for display purpose:
+ //---------------------------------------------------------------
+ ViewMapTesselator3D sTesselator3d;
+#if 0
+ ViewMapTesselator2D sTesselator2d;
+ sTesselator2d.setNature(_edgeTesselationNature);
+#endif
+ sTesselator3d.setNature(_edgeTesselationNature);
+
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "\n=== Building the view map ===" << endl;
+ }
+ _Chrono.start();
+ // Build View Map
+ _ViewMap = vmBuilder.BuildViewMap(*_winged_edge, _VisibilityAlgo, _EPSILON, _RootNode->bbox(), _SceneNumFaces);
+ _ViewMap->setScene3dBBox(_RootNode->bbox());
+
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("ViewMap edge count : %i\n", _ViewMap->viewedges_size());
+ }
+
+ // Tesselate the 3D edges:
+ _SilhouetteNode = sTesselator3d.Tesselate(_ViewMap);
+ _SilhouetteNode->addRef();
+
+ // Tesselate 2D edges
+#if 0
+ _ProjectedSilhouette = sTesselator2d.Tesselate(_ViewMap);
+ _ProjectedSilhouette->addRef();
+#endif
+
+ duration = _Chrono.stop();
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("ViewMap building : %lf\n", duration);
+ }
+
+ _pView->AddSilhouette(_SilhouetteNode);
+#if 0
+ _pView->AddSilhouette(_WRoot);
+ _pView->Add2DSilhouette(_ProjectedSilhouette);
+ _pView->Add2DVisibleSilhouette(_VisibleProjectedSilhouette);
+#endif
+ _pView->AddDebug(_DebugNode);
+
+ // Draw the steerable density map:
+ //--------------------------------
+ if (_ComputeSteerableViewMap) {
+ ComputeSteerableViewMap();
+ }
+ // Reset Style modules modification flags
+ resetModified(true);
+
+ DeleteWingedEdge();
+}
+
+void Controller::ComputeSteerableViewMap()
+{
+#if 0 //soc
+ if ((!_Canvas) || (!_ViewMap))
+ return;
+
+ // Build 4 nodes containing the edges in the 4 directions
+ NodeGroup *ng[Canvas::NB_STEERABLE_VIEWMAP];
+ unsigned i;
+ real c = 32.0f/255.0f; // see SteerableViewMap::readSteerableViewMapPixel() for information about this 32.
+ for (i = 0; i < Canvas::NB_STEERABLE_VIEWMAP; ++i) {
+ ng[i] = new NodeGroup;
+ }
+ NodeShape *completeNS = new NodeShape;
+ completeNS->material().setDiffuse(c,c,c,1);
+ ng[Canvas::NB_STEERABLE_VIEWMAP-1]->AddChild(completeNS);
+ SteerableViewMap * svm = _Canvas->getSteerableViewMap();
+ svm->Reset();
+
+ ViewMap::fedges_container& fedges = _ViewMap->FEdges();
+ LineRep * fRep;
+ NodeShape *ns;
+ for (ViewMap::fedges_container::iterator f = fedges.begin(), fend = fedges.end();
+ f != fend;
+ ++f)
+ {
+ if ((*f)->viewedge()->qi() != 0)
+ continue;
+ fRep = new LineRep((*f)->vertexA()->point2d(), (*f)->vertexB()->point2d());
+ completeNS->AddRep(fRep); // add to the complete map anyway
+ double *oweights = svm->AddFEdge(*f);
+ for (i = 0; i < (Canvas::NB_STEERABLE_VIEWMAP - 1); ++i) {
+ ns = new NodeShape;
+ double wc = oweights[i]*c;
+ if (oweights[i] == 0)
+ continue;
+ ns->material().setDiffuse(wc, wc, wc, 1);
+ ns->AddRep(fRep);
+ ng[i]->AddChild(ns);
+ }
+ }
+
+ GrayImage *img[Canvas::NB_STEERABLE_VIEWMAP];
+ //#ifdef WIN32
+ QGLBasicWidget offscreenBuffer(_pView, "SteerableViewMap", _pView->width(), _pView->height());
+ QPixmap pm;
+ QImage qimg;
+ for (i = 0; i < Canvas::NB_STEERABLE_VIEWMAP; ++i) {
+ offscreenBuffer.AddNode(ng[i]);
+#if 0
+ img[i] = new GrayImage(_pView->width(), _pView->height());
+ offscreenBuffer.readPixels(0,0,_pView->width(), _pView->height(), img[i]->getArray());
+#endif
+ pm = offscreenBuffer.renderPixmap(_pView->width(), _pView->height());
+
+ if (pm.isNull()) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "BuildViewMap Warning: couldn't render the steerable ViewMap" << endl;
+ }
+ }
+ //pm.save(QString("steerable") + QString::number(i) + QString(".bmp"), "BMP");
+ // FIXME!! Lost of time !
+ qimg = pm.toImage();
+ // FIXME !! again!
+ img[i] = new GrayImage(_pView->width(), _pView->height());
+ for (unsigned int y = 0; y < img[i]->height(); ++y) {
+ for(unsigned int x = 0; x < img[i]->width(); ++x) {
+ //img[i]->setPixel(x, y, (float)qGray(qimg.pixel(x, y)) / 255.0f);
+ img[i]->setPixel(x, y, (float)qGray(qimg.pixel(x, y)));
+ //float c = qGray(qimg.pixel(x, y));
+ //img[i]->setPixel(x, y, qGray(qimg.pixel(x, y)));
+ }
+ }
+ offscreenBuffer.DetachNode(ng[i]);
+ ng[i]->destroy();
+ delete ng[i];
+ // check
+#if 0
+ qimg = QImage(_pView->width(), _pView->height(), 32);
+ for (unsigned int y = 0; y < img[i]->height(); ++y) {
+ for(unsigned int x = 0; x < img[i]->width(); ++x) {
+ float v = img[i]->pixel(x, y);
+ qimg.setPixel(x, y, qRgb(v, v, v));
+ }
+ }
+ qimg.save(QString("newsteerable") + QString::number(i) + QString(".bmp"), "BMP");
+#endif
+ }
+
+
+ svm->buildImagesPyramids(img, false, 0, 1.0f);
+#endif
+}
+
+void Controller::saveSteerableViewMapImages()
+{
+ SteerableViewMap * svm = _Canvas->getSteerableViewMap();
+ if (!svm) {
+ cerr << "the Steerable ViewMap has not been computed yet" << endl;
+ return;
+ }
+ svm->saveSteerableViewMap();
+}
+
+void Controller::toggleVisibilityAlgo()
+{
+ if (_VisibilityAlgo == ViewMapBuilder::ray_casting) {
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_fast;
+ }
+ else if (_VisibilityAlgo == ViewMapBuilder::ray_casting_fast) {
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_very_fast;
+ }
+ else {
+ _VisibilityAlgo = ViewMapBuilder::ray_casting;
+ }
+}
+
+void Controller::setVisibilityAlgo(int algo)
+{
+ switch (algo) {
+ case FREESTYLE_ALGO_REGULAR:
+ _VisibilityAlgo = ViewMapBuilder::ray_casting;
+ break;
+ case FREESTYLE_ALGO_FAST:
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_fast;
+ break;
+ case FREESTYLE_ALGO_VERYFAST:
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_very_fast;
+ break;
+ case FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL:
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_culled_adaptive_traditional;
+ break;
+ case FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL:
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_adaptive_traditional;
+ break;
+ case FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE:
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_culled_adaptive_cumulative;
+ break;
+ case FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE:
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_adaptive_cumulative;
+ break;
+ }
+}
+
+int Controller::getVisibilityAlgo()
+{
+ switch (_VisibilityAlgo) {
+ case ViewMapBuilder::ray_casting:
+ return FREESTYLE_ALGO_REGULAR;
+ case ViewMapBuilder::ray_casting_fast:
+ return FREESTYLE_ALGO_FAST;
+ case ViewMapBuilder::ray_casting_very_fast:
+ return FREESTYLE_ALGO_VERYFAST;
+ case ViewMapBuilder::ray_casting_culled_adaptive_traditional:
+ return FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL;
+ case ViewMapBuilder::ray_casting_adaptive_traditional:
+ return FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL;
+ case ViewMapBuilder::ray_casting_culled_adaptive_cumulative:
+ return FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE;
+ case ViewMapBuilder::ray_casting_adaptive_cumulative:
+ return FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE;
+ }
+
+ // ray_casting_adaptive_traditional is the most exact replacement
+ // for legacy code
+ return FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL;
+}
+
+void Controller::setQuantitativeInvisibility(bool iBool)
+{
+ _EnableQI = iBool;
+}
+
+bool Controller::getQuantitativeInvisibility() const
+{
+ return _EnableQI;
+}
+
+void Controller::setFaceSmoothness(bool iBool)
+{
+ _EnableFaceSmoothness = iBool;
+}
+
+bool Controller::getFaceSmoothness() const
+{
+ return _EnableFaceSmoothness;
+}
+
+void Controller::setComputeRidgesAndValleysFlag(bool iBool)
+{
+ _ComputeRidges = iBool;
+}
+
+bool Controller::getComputeRidgesAndValleysFlag() const
+{
+ return _ComputeRidges;
+}
+
+void Controller::setComputeSuggestiveContoursFlag(bool b)
+{
+ _ComputeSuggestive = b;
+}
+
+bool Controller::getComputeSuggestiveContoursFlag() const
+{
+ return _ComputeSuggestive;
+}
+
+void Controller::setComputeMaterialBoundariesFlag(bool b)
+{
+ _ComputeMaterialBoundaries = b;
+}
+
+bool Controller::getComputeMaterialBoundariesFlag() const
+{
+ return _ComputeMaterialBoundaries;
+}
+
+void Controller::setComputeSteerableViewMapFlag(bool iBool)
+{
+ _ComputeSteerableViewMap = iBool;
+}
+
+bool Controller::getComputeSteerableViewMapFlag() const
+{
+ return _ComputeSteerableViewMap;
+}
+
+void Controller::DrawStrokes()
+{
+ if (_ViewMap == 0)
+ return;
+
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "\n=== Stroke drawing ===" << endl;
+ }
+ _Chrono.start();
+ _Canvas->Draw();
+ real d = _Chrono.stop();
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Strokes generation : " << d << endl;
+ cout << "Stroke count : " << _Canvas->stroke_count << endl;
+ }
+ resetModified();
+ DeleteViewMap();
+}
+
+void Controller::ResetRenderCount()
+{
+ _render_count = 0;
+}
+
+Render *Controller::RenderStrokes(Render *re)
+{
+ _Chrono.start();
+ BlenderStrokeRenderer *blenderRenderer = new BlenderStrokeRenderer(re, ++_render_count);
+ _Canvas->Render(blenderRenderer);
+ real d = _Chrono.stop();
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Temporary scene generation: " << d << endl;
+ }
+ _Chrono.start();
+ Render *freestyle_render = blenderRenderer->RenderScene(re);
+ d = _Chrono.stop();
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Stroke rendering : " << d << endl;
+ }
+ delete blenderRenderer;
+
+ return freestyle_render;
+}
+
+void Controller::InsertStyleModule(unsigned index, const char *iFileName)
+{
+ if (!BLI_testextensie(iFileName, ".py")) {
+ cerr << "Error: Cannot load \"" << StringUtils::toAscii(string(iFileName)) << "\", unknown extension" << endl;
+ return;
+ }
+
+ StyleModule *sm = new StyleModule(iFileName, _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)
+{
+ //_pStyleWindow->Add(iFileName);
+}
+
+void Controller::RemoveStyleModule(unsigned index)
+{
+ _Canvas->RemoveStyleModule(index);
+}
+
+void Controller::Clear()
+{
+ _Canvas->Clear();
+}
+
+void Controller::ReloadStyleModule(unsigned index, const char * iFileName)
+{
+ StyleModule *sm = new StyleModule(iFileName, _inter);
+ _Canvas->ReplaceStyleModule(index, sm);
+}
+
+void Controller::SwapStyleModules(unsigned i1, unsigned i2)
+{
+ _Canvas->SwapStyleModules(i1, i2);
+}
+
+void Controller::toggleLayer(unsigned index, bool iDisplay)
+{
+ _Canvas->setVisible(index, iDisplay);
+}
+
+void Controller::setModified(unsigned index, bool iMod)
+{
+ //_pStyleWindow->setModified(index, iMod);
+ _Canvas->setModified(index, iMod);
+ updateCausalStyleModules(index + 1);
+}
+
+void Controller::updateCausalStyleModules(unsigned index)
+{
+ vector<unsigned> vec;
+ _Canvas->causalStyleModules(vec, index);
+ for (vector<unsigned>::const_iterator it = vec.begin(); it != vec.end(); it++) {
+ //_pStyleWindow->setModified(*it, true);
+ _Canvas->setModified(*it, true);
+ }
+}
+
+void Controller::resetModified(bool iMod)
+{
+ //_pStyleWindow->resetModified(iMod);
+ _Canvas->resetModified(iMod);
+}
+
+NodeGroup * Controller::BuildRep(vector<ViewEdge*>::iterator vedges_begin, vector<ViewEdge*>::iterator vedges_end)
+{
+ ViewMapTesselator2D tesselator2D;
+ FrsMaterial mat;
+ mat.setDiffuse(1, 1, 0.3, 1);
+ tesselator2D.setFrsMaterial(mat);
+
+ return (tesselator2D.Tesselate(vedges_begin, vedges_end));
+}
+
+void Controller::toggleEdgeTesselationNature(Nature::EdgeNature iNature)
+{
+ _edgeTesselationNature ^= (iNature);
+ ComputeViewMap();
+}
+
+void Controller::setModelsDir(const string& dir)
+{
+ //_current_dirs->setValue("models/dir", dir);
+}
+
+string Controller::getModelsDir() const
+{
+ string dir = ".";
+ //_current_dirs->getValue("models/dir", dir);
+ return dir;
+}
+
+void Controller::setModulesDir(const string& dir)
+{
+ //_current_dirs->setValue("modules/dir", dir);
+}
+
+string Controller::getModulesDir() const
+{
+ string dir = ".";
+ //_current_dirs->getValue("modules/dir", dir);
+ return dir;
+}
+
+void Controller::resetInterpreter()
+{
+ if (_inter)
+ _inter->reset();
+}
+
+
+void Controller::displayDensityCurves(int x, int y)
+{
+ SteerableViewMap * svm = _Canvas->getSteerableViewMap();
+ if (!svm)
+ return;
+
+ unsigned int i, j;
+ typedef vector<Vec3r> densityCurve;
+ vector<densityCurve> curves(svm->getNumberOfOrientations() + 1);
+ vector<densityCurve> curvesDirection(svm->getNumberOfPyramidLevels());
+
+ // collect the curves values
+ unsigned nbCurves = svm->getNumberOfOrientations() + 1;
+ unsigned nbPoints = svm->getNumberOfPyramidLevels();
+ if (!nbPoints)
+ return;
+
+ // build the density/nbLevels curves for each orientation
+ for (i = 0; i < nbCurves; ++i) {
+ for (j = 0; j < nbPoints; ++j) {
+ curves[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(i, j, x, y), 0));
+ }
+ }
+ // build the density/nbOrientations curves for each level
+ for (i = 0; i < nbPoints; ++i) {
+ for (j = 0; j < nbCurves; ++j) {
+ curvesDirection[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(j, i, x, y), 0));
+ }
+ }
+
+ // display the curves
+#if 0
+ for (i = 0; i < nbCurves; ++i)
+ _pDensityCurvesWindow->setOrientationCurve(i, Vec2d(0, 0), Vec2d(nbPoints, 1), curves[i], "scale", "density");
+ for (i = 1; i <= 8; ++i)
+ _pDensityCurvesWindow->setLevelCurve(i, Vec2d(0, 0), Vec2d(nbCurves, 1), curvesDirection[i],
+ "orientation", "density");
+ _pDensityCurvesWindow->show();
+#endif
+}
+
+void Controller::init_options()
+{
+ // from AppOptionsWindow.cpp
+ // Default init options
+
+ Config::Path * cpath = Config::Path::getInstance();
+
+ // Directories
+ ViewMapIO::Options::setModelsPath(StringUtils::toAscii(cpath->getModelsPath()));
+ PythonInterpreter::Options::setPythonPath(StringUtils::toAscii(cpath->getPythonPath()));
+ TextureManager::Options::setPatternsPath(StringUtils::toAscii(cpath->getPatternsPath()));
+ TextureManager::Options::setBrushesPath(StringUtils::toAscii(cpath->getModelsPath()));
+
+ // ViewMap Format
+ ViewMapIO::Options::rmFlags(ViewMapIO::Options::FLOAT_VECTORS);
+ ViewMapIO::Options::rmFlags(ViewMapIO::Options::NO_OCCLUDERS);
+ setComputeSteerableViewMapFlag(false);
+
+ // Visibility
+ setQuantitativeInvisibility(true);
+
+ // soc: initialize canvas
+ _Canvas->init();
+
+ // soc: initialize passes
+ setPassDiffuse(NULL, 0, 0);
+ setPassZ(NULL, 0, 0);
+}
diff --git a/source/blender/freestyle/intern/application/Controller.h b/source/blender/freestyle/intern/application/Controller.h
new file mode 100644
index 00000000000..b89470e417f
--- /dev/null
+++ b/source/blender/freestyle/intern/application/Controller.h
@@ -0,0 +1,257 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __CONTROLLER_H__
+#define __CONTROLLER_H__
+
+/** \file blender/freestyle/intern/application/Controller.h
+ * \ingroup freestyle
+ * \brief The spinal tap of the system.
+ * \author Stephane Grabli
+ * \date 01/07/2002
+ */
+
+#include <string>
+
+//#include "ConfigIO.h"
+#include "../geometry/FastGrid.h"
+#include "../system/Interpreter.h"
+#include "../system/ProgressBar.h"
+#include "../system/Precision.h"
+#include "../system/RenderMonitor.h"
+#include "../system/TimeUtils.h"
+#include "../view_map/FEdgeXDetector.h"
+#include "../view_map/ViewMapBuilder.h"
+
+class AppView;
+class NodeGroup;
+class WShape;
+class SShape;
+class ViewMap;
+class ViewEdge;
+class AppCanvas;
+class InteractiveShader;
+class Shader;
+class StrokeRenderer;
+
+// XXX Are those "ifdef __cplusplus" useful here?
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "render_types.h"
+#include "DNA_scene_types.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+class Controller
+{
+public:
+ Controller();
+ ~Controller();
+
+ void setView(AppView *iView);
+ void setRenderMonitor(RenderMonitor *iRenderMonitor);
+ void setPassDiffuse(float *buf, int width, int height);
+ void setPassZ(float *buf, int width, int height);
+ void setContext(bContext *C);
+
+ //soc
+ void init_options();
+
+ int LoadMesh(Render *re, SceneRenderLayer *srl);
+ int Load3DSFile(const char *iFileName);
+ void CloseFile();
+ void ComputeViewMap();
+ void ComputeSteerableViewMap();
+ void saveSteerableViewMapImages();
+ void toggleEdgeTesselationNature(Nature::EdgeNature iNature);
+ void DrawStrokes();
+ void ResetRenderCount();
+ Render *RenderStrokes(Render *re);
+ void SwapStyleModules(unsigned i1, unsigned i2);
+ void InsertStyleModule(unsigned index, const char *iFileName);
+ void InsertStyleModule(unsigned index, const char *iName, struct Text *iText);
+ void AddStyleModule(const char *iFileName);
+ void RemoveStyleModule(unsigned index);
+ void ReloadStyleModule(unsigned index, const char * iFileName);
+ void Clear();
+ void ClearRootNode();
+ void DeleteWingedEdge();
+ void DeleteViewMap();
+ void toggleLayer(unsigned index, bool iDisplay);
+ void setModified(unsigned index, bool iMod);
+ void resetModified(bool iMod=false);
+ void updateCausalStyleModules(unsigned index);
+ void displayDensityCurves(int x, int y);
+
+ ViewEdge *SelectViewEdge(real x, real y);
+ FEdge *SelectFEdge(real x, real y);
+ NodeGroup *BuildRep(vector<ViewEdge*>::iterator vedges_begin, vector<ViewEdge*>::iterator vedges_end) ;
+
+#if 0
+ NodeGroup *debugNode() {return _DebugNode;}
+ AppView *view() {return _pView;}
+ NodeGroup *debugScene() {return _DebugNode;}
+ Grid& grid() {return _Grid;}
+#endif
+
+ void toggleVisibilityAlgo();
+ void setVisibilityAlgo(int algo);
+ int getVisibilityAlgo();
+
+ void setQuantitativeInvisibility(bool iBool); // if true, we compute quantitativeInvisibility
+ bool getQuantitativeInvisibility() const;
+ void setFaceSmoothness(bool iBool);
+ bool getFaceSmoothness() const;
+
+ void setComputeRidgesAndValleysFlag(bool b);
+ bool getComputeRidgesAndValleysFlag() const;
+ void setComputeSuggestiveContoursFlag(bool b);
+ bool getComputeSuggestiveContoursFlag() const;
+ void setComputeMaterialBoundariesFlag(bool b);
+ bool getComputeMaterialBoundariesFlag() const;
+
+ 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 setModelsDir(const string& dir);
+ string getModelsDir() const;
+ void setModulesDir(const string& dir);
+ string getModulesDir() const;
+
+ void resetInterpreter();
+
+public:
+ // Viewmap data structure
+ ViewMap *_ViewMap;
+
+ // Canvas
+ AppCanvas *_Canvas;
+
+private:
+ // Main Window:
+ //AppMainWindow *_pMainWindow;
+
+ // List of models currently loaded
+ vector<string> _ListOfModels;
+
+ // Current directories
+ //ConfigIO* _current_dirs;
+
+ //View
+ // 3D
+ AppView *_pView;
+
+ // 2D
+#if 0
+ Viewer2DWindow *_pView2DWindow;
+ Viewer2D *_pView2D;
+#endif
+
+ RenderMonitor *_pRenderMonitor;
+
+ //Model
+ // Drawing Structure
+ NodeGroup *_RootNode;
+
+ // Winged-Edge structure
+ WingedEdge *_winged_edge;
+
+ // Silhouette structure:
+#if 0
+ std::vector<SShape*> _SShapes;
+ NodeGroup *_SRoot;
+#endif
+
+ // Silhouette
+ NodeGroup *_SilhouetteNode;
+ NodeGroup *_ProjectedSilhouette;
+ NodeGroup *_VisibleProjectedSilhouette;
+
+ // more Debug info
+ NodeGroup *_DebugNode;
+
+ // debug
+ //NodeUser<ViewMap> *_ViewMapNode; // FIXME
+
+ // Chronometer:
+ Chronometer _Chrono;
+
+ // Progress Bar
+ ProgressBar *_ProgressBar;
+
+ // edges tesselation nature
+ int _edgeTesselationNature;
+
+ FastGrid _Grid;
+ //HashGrid _Grid;
+
+ unsigned int _SceneNumFaces;
+ real _minEdgeSize;
+ real _EPSILON;
+ real _bboxDiag;
+
+ int _render_count;
+
+ //AppStyleWindow *_pStyleWindow;
+ //AppOptionsWindow *_pOptionsWindow;
+ //AppDensityCurvesWindow *_pDensityCurvesWindow;
+
+ ViewMapBuilder::visibility_algo _VisibilityAlgo;
+
+ // Script Interpreter
+ Interpreter *_inter;
+
+ string _help_index;
+ string _browser_cmd;
+
+ bool _EnableQI;
+ bool _EnableFaceSmoothness;
+ bool _ComputeRidges;
+ bool _ComputeSuggestive;
+ bool _ComputeMaterialBoundaries;
+ real _creaseAngle;
+ real _sphereRadius;
+ real _suggestiveContourKrDerivativeEpsilon;
+
+ bool _ComputeSteerableViewMap;
+
+ FEdgeXDetector edgeDetector;
+};
+
+extern Controller *g_pController;
+
+#endif // __CONTROLLER_H__
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
new file mode 100644
index 00000000000..860c7f5610d
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
@@ -0,0 +1,765 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
+ * \ingroup freestyle
+ */
+
+#include <assert.h>
+
+#include "BlenderFileLoader.h"
+
+#include "BKE_global.h"
+
+BlenderFileLoader::BlenderFileLoader(Render *re, SceneRenderLayer *srl)
+{
+ _re = re;
+ _srl = srl;
+ _Scene = NULL;
+ _numFacesRead = 0;
+ _minEdgeSize = DBL_MAX;
+ _smooth = (srl->freestyleConfig.flags & FREESTYLE_FACE_SMOOTHNESS_FLAG) != 0;
+}
+
+BlenderFileLoader::~BlenderFileLoader()
+{
+ _Scene = NULL;
+}
+
+NodeGroup *BlenderFileLoader::Load()
+{
+ ObjectInstanceRen *obi;
+
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "\n=== Importing triangular meshes into Blender ===" << endl;
+ }
+
+ // creation of the scene root node
+ _Scene = new NodeGroup;
+
+ _viewplane_left = _re->viewplane.xmin;
+ _viewplane_right = _re->viewplane.xmax;
+ _viewplane_bottom = _re->viewplane.ymin;
+ _viewplane_top = _re->viewplane.ymax;
+ _z_near = -_re->clipsta;
+ _z_far = -_re->clipend;
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Frustum: l " << _viewplane_left << " r " << _viewplane_right
+ << " b " << _viewplane_bottom << " t " << _viewplane_top
+ << " n " << _z_near << " f " << _z_far << endl;
+ }
+#endif
+
+ int id = 0;
+ for (obi = (ObjectInstanceRen *)_re->instancetable.first; obi; obi = obi->next) {
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ break;
+ if (!(obi->lay & _srl->lay))
+ continue;
+ char *name = obi->ob->id.name;
+ //printf("%c%c:%s\n", name[0], name[1], name+2);
+ //print_m4("obi->mat", obi->mat);
+
+ if (obi->obr->totvlak > 0) {
+ insertShapeNode(obi, ++id);
+ }
+ else if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Warning: " << (name + 2) << " is not a vlak-based object (ignored)" << endl;
+ }
+ }
+
+ // Return the built scene.
+ return _Scene;
+}
+
+#define CLIPPED_BY_NEAR -1
+#define NOT_CLIPPED 0
+#define CLIPPED_BY_FAR 1
+
+// check if each vertex of a triangle (V1, V2, V3) is clipped by the near/far plane
+// and calculate the number of triangles to be generated by clipping
+int BlenderFileLoader::countClippedFaces(float v1[3], float v2[3], float v3[3], int clip[3])
+{
+ float *v[3];
+ int numClipped, sum, numTris = 0;
+
+ v[0] = v1;
+ v[1] = v2;
+ v[2] = v3;
+ numClipped = sum = 0;
+ for (int i = 0; i < 3; i++) {
+ if (v[i][2] > _z_near) {
+ clip[i] = CLIPPED_BY_NEAR;
+ numClipped++;
+ }
+ else if (v[i][2] < _z_far) {
+ clip[i] = CLIPPED_BY_FAR;
+ numClipped++;
+ }
+ else {
+ clip[i] = NOT_CLIPPED;
+ }
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("%d %s\n", i, (clip[i] == NOT_CLIPPED) ? "not" : (clip[i] == CLIPPED_BY_NEAR) ? "near" : "far");
+ }
+#endif
+ sum += clip[i];
+ }
+ switch (numClipped) {
+ case 0:
+ numTris = 1; // triangle
+ break;
+ case 1:
+ numTris = 2; // tetragon
+ break;
+ case 2:
+ if (sum == 0)
+ numTris = 3; // pentagon
+ else
+ numTris = 1; // triangle
+ break;
+ case 3:
+ if (sum == 3 || sum == -3)
+ numTris = 0;
+ else
+ numTris = 2; // tetragon
+ break;
+ }
+ return numTris;
+}
+
+// find the intersection point C between the line segment from V1 to V2 and
+// a clipping plane at depth Z (i.e., the Z component of C is known, while
+// the X and Y components are unknown).
+void BlenderFileLoader::clipLine(float v1[3], float v2[3], float c[3], float z)
+{
+ // Order v1 and v2 by Z values to make sure that clipLine(P, Q, c, z)
+ // and clipLine(Q, P, c, z) gives exactly the same numerical result.
+ float *p, *q;
+ if (v1[2] < v2[2]) {
+ p = v1;
+ q = v2;
+ }
+ else {
+ p = v2;
+ q = v1;
+ }
+ double d[3];
+ for (int i = 0; i < 3; i++)
+ d[i] = q[i] - p[i];
+ double t = (z - p[2]) / d[2];
+ c[0] = p[0] + t * d[0];
+ c[1] = p[1] + t * d[1];
+ c[2] = z;
+}
+
+// clip the triangle (V1, V2, V3) by the near and far clipping plane and
+// obtain a set of vertices after the clipping. The number of vertices
+// is at most 5.
+void BlenderFileLoader::clipTriangle(int numTris, float triCoords[][3], float v1[3], float v2[3], float v3[3],
+ float triNormals[][3], float n1[3], float n2[3], float n3[3],
+ bool edgeMarks[], bool em1, bool em2, bool em3, int clip[3])
+{
+ float *v[3], *n[3];
+ bool em[3];
+ int i, j, k;
+
+ v[0] = v1; n[0] = n1;
+ v[1] = v2; n[1] = n2;
+ v[2] = v3; n[2] = n3;
+ em[0] = em1; /* edge mark of the edge between v1 and v2 */
+ em[1] = em2; /* edge mark of the edge between v2 and v3 */
+ em[2] = em3; /* edge mark of the edge between v3 and v1 */
+ k = 0;
+ for (i = 0; i < 3; i++) {
+ j = (i + 1) % 3;
+ if (clip[i] == NOT_CLIPPED) {
+ copy_v3_v3(triCoords[k], v[i]);
+ copy_v3_v3(triNormals[k], n[i]);
+ edgeMarks[k] = em[i];
+ k++;
+ if (clip[j] != NOT_CLIPPED) {
+ clipLine(v[i], v[j], triCoords[k], (clip[j] == CLIPPED_BY_NEAR) ? _z_near : _z_far);
+ copy_v3_v3(triNormals[k], n[j]);
+ edgeMarks[k] = false;
+ k++;
+ }
+ }
+ else if (clip[i] != clip[j]) {
+ if (clip[j] == NOT_CLIPPED) {
+ clipLine(v[i], v[j], triCoords[k], (clip[i] == CLIPPED_BY_NEAR) ? _z_near : _z_far);
+ copy_v3_v3(triNormals[k], n[i]);
+ edgeMarks[k] = em[i];
+ k++;
+ }
+ else {
+ clipLine(v[i], v[j], triCoords[k], (clip[i] == CLIPPED_BY_NEAR) ? _z_near : _z_far);
+ copy_v3_v3(triNormals[k], n[i]);
+ edgeMarks[k] = em[i];
+ k++;
+ clipLine(v[i], v[j], triCoords[k], (clip[j] == CLIPPED_BY_NEAR) ? _z_near : _z_far);
+ copy_v3_v3(triNormals[k], n[j]);
+ edgeMarks[k] = false;
+ k++;
+ }
+ }
+ }
+ assert(k == 2 + numTris);
+}
+
+void BlenderFileLoader::addTriangle(struct LoaderState *ls, float v1[3], float v2[3], float v3[3],
+ float n1[3], float n2[3], float n3[3],
+ bool fm, bool em1, bool em2, bool em3)
+{
+ float *fv[3], *fn[3], len;
+ unsigned int i, j;
+ IndexedFaceSet::FaceEdgeMark marks = 0;
+
+ // initialize the bounding box by the first vertex
+ if (ls->currentIndex == 0) {
+ copy_v3_v3(ls->minBBox, v1);
+ copy_v3_v3(ls->maxBBox, v1);
+ }
+
+ fv[0] = v1; fn[0] = n1;
+ fv[1] = v2; fn[1] = n2;
+ fv[2] = v3; fn[2] = n3;
+ for (i = 0; i < 3; i++) {
+
+ copy_v3_v3(ls->pv, fv[i]);
+ copy_v3_v3(ls->pn, fn[i]);
+
+ // update the bounding box
+ for (j = 0; j < 3; j++) {
+ if (ls->minBBox[j] > ls->pv[j])
+ ls->minBBox[j] = ls->pv[j];
+
+ if (ls->maxBBox[j] < ls->pv[j])
+ ls->maxBBox[j] = ls->pv[j];
+ }
+
+ len = len_v3v3(fv[i], fv[(i + 1) % 3]);
+ if (_minEdgeSize > len)
+ _minEdgeSize = len;
+
+ *ls->pvi = ls->currentIndex;
+ *ls->pni = ls->currentIndex;
+ *ls->pmi = ls->currentMIndex;
+
+ ls->currentIndex += 3;
+ ls->pv += 3;
+ ls->pn += 3;
+
+ ls->pvi++;
+ ls->pni++;
+ ls->pmi++;
+ }
+
+ if (fm)
+ marks |= IndexedFaceSet::FACE_MARK;
+ if (em1)
+ marks |= IndexedFaceSet::EDGE_MARK_V1V2;
+ if (em2)
+ marks |= IndexedFaceSet::EDGE_MARK_V2V3;
+ if (em3)
+ marks |= IndexedFaceSet::EDGE_MARK_V3V1;
+ *(ls->pm++) = marks;
+}
+
+// With A, B and P indicating the three vertices of a given triangle, returns:
+// 1 if points A and B are in the same position in the 3D space;
+// 2 if the distance between point P and line segment AB is zero; and
+// zero otherwise.
+int BlenderFileLoader::testDegenerateTriangle(float v1[3], float v2[3], float v3[3])
+{
+#if 0
+ float area = area_tri_v3(v1, v2, v3);
+ bool verbose = (area < 1.0e-6);
+#endif
+
+ if (equals_v3v3(v1, v2) || equals_v3v3(v2, v3) || equals_v3v3(v1, v3)) {
+#if 0
+ if (verbose && G.debug & G_DEBUG_FREESTYLE) {
+ printf("BlenderFileLoader::testDegenerateTriangle = 1\n");
+ }
+#endif
+ return 1;
+ }
+ if (dist_to_line_segment_v3(v1, v2, v3) < 1.0e-6 ||
+ dist_to_line_segment_v3(v2, v1, v3) < 1.0e-6 ||
+ dist_to_line_segment_v3(v3, v1, v2) < 1.0e-6)
+ {
+#if 0
+ if (verbose && G.debug & G_DEBUG_FREESTYLE) {
+ printf("BlenderFileLoader::testDegenerateTriangle = 2\n");
+ }
+#endif
+ return 2;
+ }
+#if 0
+ if (verbose && G.debug & G_DEBUG_FREESTYLE) {
+ printf("BlenderFileLoader::testDegenerateTriangle = 0\n");
+ }
+#endif
+ return 0;
+}
+
+// Checks if edge rotation (if necessary) can prevent the given quad from
+// being decomposed into a degenerate triangle
+bool BlenderFileLoader::testEdgeRotation(float v1[3], float v2[3], float v3[3], float v4[3])
+{
+ if (testDegenerateTriangle(v1, v2, v3) == 2 || testDegenerateTriangle(v1, v3, v4) == 2) {
+ if (testDegenerateTriangle(v1, v2, v4) == 2 || testDegenerateTriangle(v2, v3, v4) == 2) {
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("BlenderFileLoader::testEdgeRotation: edge rotation is unsuccessful.\n");
+ }
+#endif
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+
+void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id)
+{
+ ObjectRen *obr = obi->obr;
+ char *name = obi->ob->id.name + 2;
+
+ // We parse vlak nodes and count the number of faces after the clipping by
+ // the near and far view planes is applied (Note: mesh vertices are in the
+ // camera coordinate system).
+ VlakRen *vlr = NULL;
+ unsigned numFaces = 0;
+ float v1[3], v2[3], v3[3], v4[3];
+ float n1[3], n2[3], n3[3], n4[3], facenormal[3];
+ int clip_1[3], clip_2[3];
+ int wire_material = 0;
+ for (int a = 0; a < obr->totvlak; a++) {
+ if ((a & 255) == 0)
+ vlr = obr->vlaknodes[a>>8].vlak;
+ else
+ vlr++;
+ if (vlr->mat->material_type == MA_TYPE_WIRE) {
+ wire_material = 1;
+ continue;
+ }
+ copy_v3_v3(v1, vlr->v1->co);
+ copy_v3_v3(v2, vlr->v2->co);
+ copy_v3_v3(v3, vlr->v3->co);
+ if (vlr->v4)
+ copy_v3_v3(v4, vlr->v4->co);
+ if (obi->flag & R_TRANSFORMED) {
+ mul_m4_v3(obi->mat, v1);
+ mul_m4_v3(obi->mat, v2);
+ mul_m4_v3(obi->mat, v3);
+ if (vlr->v4)
+ mul_m4_v3(obi->mat, v4);
+ }
+#if 0
+ print_v3("v1", v1);
+ print_v3("v2", v2);
+ print_v3("v3", v3);
+ if (vlr->v4)
+ print_v3("v4", v4);
+#endif
+ if (!vlr->v4 || !testEdgeRotation(v1, v2, v3, v4)) {
+ numFaces += countClippedFaces(v1, v2, v3, clip_1);
+ if (vlr->v4)
+ numFaces += countClippedFaces(v1, v3, v4, clip_2);
+ }
+ else {
+ numFaces += countClippedFaces(v1, v2, v4, clip_1);
+ numFaces += countClippedFaces(v2, v3, v4, clip_2);
+ }
+ }
+ if (wire_material) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Warning: Object " << name << " has wire materials (ignored)" << endl;
+ }
+ }
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "numFaces " << numFaces << endl;
+ }
+#endif
+ if (numFaces == 0)
+ return;
+
+ // We allocate memory for the meshes to be imported
+ NodeTransform *currentMesh = new NodeTransform;
+ NodeShape *shape = new NodeShape;
+
+ unsigned vSize = 3 * 3 * numFaces;
+ float *vertices = new float[vSize];
+ unsigned nSize = vSize;
+ float *normals = new float[nSize];
+ unsigned *numVertexPerFaces = new unsigned[numFaces];
+ vector<FrsMaterial> meshFrsMaterials;
+
+ IndexedFaceSet::TRIANGLES_STYLE *faceStyle = new IndexedFaceSet::TRIANGLES_STYLE[numFaces];
+ unsigned i;
+ for (i = 0; i <numFaces; i++) {
+ faceStyle[i] = IndexedFaceSet::TRIANGLES;
+ numVertexPerFaces[i] = 3;
+ }
+
+ IndexedFaceSet::FaceEdgeMark *faceEdgeMarks = new IndexedFaceSet::FaceEdgeMark[numFaces];
+
+ unsigned viSize = 3 * numFaces;
+ unsigned *VIndices = new unsigned[viSize];
+ unsigned niSize = viSize;
+ unsigned *NIndices = new unsigned[niSize];
+ unsigned *MIndices = new unsigned[viSize]; // Material Indices
+
+ struct LoaderState ls;
+ ls.pv = vertices;
+ ls.pn = normals;
+ ls.pm = faceEdgeMarks;
+ ls.pvi = VIndices;
+ ls.pni = NIndices;
+ ls.pmi = MIndices;
+ ls.currentIndex = 0;
+ ls.currentMIndex = 0;
+
+ FrsMaterial tmpMat;
+
+ // We parse the vlak nodes again and import meshes while applying the clipping
+ // by the near and far view planes.
+ int p;
+ for (p = 0; p < obr->totvlak; ++p) { // we parse the faces of the mesh
+#if 0
+ Lib3dsFace *f = &mesh->faceL[p];
+ Lib3dsMaterial *mat = NULL;
+#endif
+ if ((p & 255) == 0)
+ vlr = obr->vlaknodes[p>>8].vlak;
+ else
+ vlr++;
+ if (vlr->mat->material_type == MA_TYPE_WIRE)
+ continue;
+ copy_v3_v3(v1, vlr->v1->co);
+ copy_v3_v3(v2, vlr->v2->co);
+ copy_v3_v3(v3, vlr->v3->co);
+ if (vlr->v4)
+ copy_v3_v3(v4, vlr->v4->co);
+ if (obi->flag & R_TRANSFORMED) {
+ mul_m4_v3(obi->mat, v1);
+ mul_m4_v3(obi->mat, v2);
+ mul_m4_v3(obi->mat, v3);
+ if (vlr->v4)
+ mul_m4_v3(obi->mat, v4);
+ }
+ if (_smooth && (vlr->flag & R_SMOOTH)) {
+ copy_v3_v3(n1, vlr->v1->n);
+ copy_v3_v3(n2, vlr->v2->n);
+ copy_v3_v3(n3, vlr->v3->n);
+ if (vlr->v4)
+ copy_v3_v3(n4, vlr->v4->n);
+ if (obi->flag & R_TRANSFORMED) {
+ mul_m3_v3(obi->nmat, n1);
+ mul_m3_v3(obi->nmat, n2);
+ mul_m3_v3(obi->nmat, n3);
+ normalize_v3(n1);
+ normalize_v3(n2);
+ normalize_v3(n3);
+ if (vlr->v4) {
+ mul_m3_v3(obi->nmat, n4);
+ normalize_v3(n4);
+ }
+ }
+ }
+ else {
+ RE_vlakren_get_normal(_re, obi, vlr, facenormal);
+ copy_v3_v3(n1, facenormal);
+ copy_v3_v3(n2, facenormal);
+ copy_v3_v3(n3, facenormal);
+ if (vlr->v4)
+ copy_v3_v3(n4, facenormal);
+ }
+
+ unsigned int numTris_1, numTris_2;
+ bool edge_rotation;
+ if (!vlr->v4 || !testEdgeRotation(v1, v2, v3, v4)) {
+ numTris_1 = countClippedFaces(v1, v2, v3, clip_1);
+ numTris_2 = (!vlr->v4) ? 0 : countClippedFaces(v1, v3, v4, clip_2);
+ edge_rotation = false;
+ }
+ else {
+ numTris_1 = countClippedFaces(v1, v2, v4, clip_1);
+ numTris_2 = countClippedFaces(v2, v3, v4, clip_2);
+ edge_rotation = true;
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("BlenderFileLoader::insertShapeNode: edge rotation is performed.\n");
+ }
+ }
+ if (numTris_1 == 0 && numTris_2 == 0)
+ continue;
+ bool fm, em1, em2, em3, em4;
+ fm = (vlr->freestyle_face_mark) != 0;
+ em1 = (vlr->freestyle_edge_mark & R_EDGE_V1V2) != 0;
+ em2 = (vlr->freestyle_edge_mark & R_EDGE_V2V3) != 0;
+ if (!vlr->v4) {
+ em3 = (vlr->freestyle_edge_mark & R_EDGE_V3V1) != 0;
+ em4 = false;
+ }
+ else {
+ em3 = (vlr->freestyle_edge_mark & R_EDGE_V3V4) != 0;
+ em4 = (vlr->freestyle_edge_mark & R_EDGE_V4V1) != 0;
+ }
+
+ Material *mat = vlr->mat;
+ if (mat) {
+ tmpMat.setDiffuse(mat->r, mat->g, mat->b, mat->alpha);
+ tmpMat.setSpecular(mat->specr, mat->specg, mat->specb, mat->spectra);
+ float s = 1.0 * (mat->har + 1) / 4 ; // in Blender: [1;511] => in OpenGL: [0;128]
+ if (s > 128.f)
+ s = 128.f;
+ tmpMat.setShininess(s);
+ }
+
+ if (meshFrsMaterials.empty()) {
+ meshFrsMaterials.push_back(tmpMat);
+ shape->setFrsMaterial(tmpMat);
+ }
+ else {
+ // find if the material is aleady in the list
+ unsigned int i = 0;
+ bool found = false;
+
+ for (vector<FrsMaterial>::iterator it = meshFrsMaterials.begin(), itend = meshFrsMaterials.end();
+ it != itend;
+ it++, i++)
+ {
+ if (*it == tmpMat) {
+ ls.currentMIndex = i;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ meshFrsMaterials.push_back(tmpMat);
+ ls.currentMIndex = meshFrsMaterials.size() - 1;
+ }
+ }
+
+ float triCoords[5][3], triNormals[5][3];
+ bool edgeMarks[5]; // edgeMarks[i] is for the edge between i-th and (i+1)-th vertices
+
+ if (numTris_1 > 0) {
+ if (!edge_rotation) {
+ clipTriangle(numTris_1, triCoords, v1, v2, v3, triNormals, n1, n2, n3,
+ edgeMarks, em1, em2, (!vlr->v4) ? em3 : false, clip_1);
+ }
+ else {
+ clipTriangle(numTris_1, triCoords, v1, v2, v4, triNormals, n1, n2, n4,
+ edgeMarks, em1, false, em4, clip_1);
+ }
+ for (i = 0; i < numTris_1; i++) {
+ addTriangle(&ls, triCoords[0], triCoords[i + 1], triCoords[i + 2],
+ triNormals[0], triNormals[i + 1], triNormals[i + 2],
+ fm, (i == 0) ? edgeMarks[0] : false, edgeMarks[i + 1],
+ (i == numTris_1 - 1) ? edgeMarks[i + 2] : false);
+ _numFacesRead++;
+ }
+ }
+
+ if (numTris_2 > 0) {
+ if (!edge_rotation) {
+ clipTriangle(numTris_2, triCoords, v1, v3, v4, triNormals, n1, n3, n4,
+ edgeMarks, false, em3, em4, clip_2);
+ }
+ else {
+ clipTriangle(numTris_2, triCoords, v2, v3, v4, triNormals, n2, n3, n4,
+ edgeMarks, em2, em3, false, clip_2);
+ }
+ for (i = 0; i < numTris_2; i++) {
+ addTriangle(&ls, triCoords[0], triCoords[i + 1], triCoords[i + 2],
+ triNormals[0], triNormals[i + 1], triNormals[i + 2],
+ fm, (i == 0) ? edgeMarks[0] : false, edgeMarks[i + 1],
+ (i == numTris_2 - 1) ? edgeMarks[i + 2] : false);
+ _numFacesRead++;
+ }
+ }
+ }
+
+ // 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;
+ unsigned int cvSize;
+ unsigned int *cleanVIndices = NULL;
+
+ GeomCleaner::CleanIndexedVertexArray(vertices, vSize, VIndices, viSize, &cleanVertices, &cvSize, &cleanVIndices);
+
+ real *cleanNormals = NULL;
+ unsigned int cnSize;
+ unsigned int *cleanNIndices = NULL;
+
+ GeomCleaner::CleanIndexedVertexArray(normals, nSize, NIndices, niSize, &cleanNormals, &cnSize, &cleanNIndices);
+
+ // format materials array
+ FrsMaterial **marray = new FrsMaterial *[meshFrsMaterials.size()];
+ unsigned int mindex = 0;
+ for (vector<FrsMaterial>::iterator m = meshFrsMaterials.begin(), mend = meshFrsMaterials.end(); m != mend; ++m) {
+ marray[mindex] = new FrsMaterial(*m);
+ ++mindex;
+ }
+
+ // deallocates memory:
+ delete [] vertices;
+ delete [] normals;
+ delete [] VIndices;
+ delete [] NIndices;
+
+ // Fix for degenerated triangles
+ // A degenerate triangle is a triangle such that
+ // 1) A and B are in the same position in the 3D space; or
+ // 2) the distance between point P and line segment AB is zero.
+ // Only those degenerate triangles in the second form are resolved here
+ // by adding a small offset to P, whereas those in the first form are
+ // addressed later in WShape::MakeFace().
+ vector<detri_t> detriList;
+ Vec3r zero(0.0, 0.0, 0.0);
+ unsigned vi0, vi1, vi2;
+ for (i = 0; i < viSize; i += 3) {
+ detri_t detri;
+ vi0 = cleanVIndices[i];
+ vi1 = cleanVIndices[i + 1];
+ vi2 = cleanVIndices[i + 2];
+ Vec3r v0(cleanVertices[vi0], cleanVertices[vi0 + 1], cleanVertices[vi0 + 2]);
+ Vec3r v1(cleanVertices[vi1], cleanVertices[vi1 + 1], cleanVertices[vi1 + 2]);
+ Vec3r v2(cleanVertices[vi2], cleanVertices[vi2 + 1], cleanVertices[vi2 + 2]);
+ if (v0 == v1 || v0 == v2 || v1 == v2) {
+ continue; // do nothing for now
+ }
+ else if (GeomUtils::distPointSegment<Vec3r>(v0, v1, v2) < 1.0e-6) {
+ detri.viP = vi0;
+ detri.viA = vi1;
+ detri.viB = vi2;
+ }
+ else if (GeomUtils::distPointSegment<Vec3r>(v1, v0, v2) < 1.0e-6) {
+ detri.viP = vi1;
+ detri.viA = vi0;
+ detri.viB = vi2;
+ }
+ else if (GeomUtils::distPointSegment<Vec3r>(v2, v0, v1) < 1.0e-6) {
+ detri.viP = vi2;
+ detri.viA = vi0;
+ detri.viB = vi1;
+ }
+ else {
+ continue;
+ }
+
+ detri.v = zero;
+ detri.n = 0;
+ for (unsigned int j = 0; j < viSize; j += 3) {
+ if (i == j)
+ continue;
+ vi0 = cleanVIndices[j];
+ vi1 = cleanVIndices[j + 1];
+ vi2 = cleanVIndices[j + 2];
+ Vec3r v0(cleanVertices[vi0], cleanVertices[vi0 + 1], cleanVertices[vi0 + 2]);
+ Vec3r v1(cleanVertices[vi1], cleanVertices[vi1 + 1], cleanVertices[vi1 + 2]);
+ Vec3r v2(cleanVertices[vi2], cleanVertices[vi2 + 1], cleanVertices[vi2 + 2]);
+ if (detri.viP == vi0 && (detri.viA == vi1 || detri.viB == vi1)) {
+ detri.v += (v2 - v0);
+ detri.n++;
+ }
+ else if (detri.viP == vi0 && (detri.viA == vi2 || detri.viB == vi2)) {
+ detri.v += (v1 - v0);
+ detri.n++;
+ }
+ else if (detri.viP == vi1 && (detri.viA == vi0 || detri.viB == vi0)) {
+ detri.v += (v2 - v1);
+ detri.n++;
+ }
+ else if (detri.viP == vi1 && (detri.viA == vi2 || detri.viB == vi2)) {
+ detri.v += (v0 - v1);
+ detri.n++;
+ }
+ else if (detri.viP == vi2 && (detri.viA == vi0 || detri.viB == vi0)) {
+ detri.v += (v1 - v2);
+ detri.n++;
+ }
+ else if (detri.viP == vi2 && (detri.viA == vi1 || detri.viB == vi1)) {
+ detri.v += (v0 - v2);
+ detri.n++;
+ }
+ }
+ if (detri.n > 0) {
+ detri.v.normalizeSafe();
+ }
+ detriList.push_back(detri);
+ }
+
+ if (detriList.size() > 0) {
+ vector<detri_t>::iterator v;
+ 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 + 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] += 1.0e-5 * detri.v.y();
+ cleanVertices[detri.viP + 2] += 1.0e-5 * detri.v.z();
+ }
+ }
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("Warning: Object %s contains %lu degenerated triangle%s (strokes may be incorrect)\n",
+ name, detriList.size(), (detriList.size() > 1) ? "s" : "");
+ }
+ }
+
+ // Create the IndexedFaceSet with the retrieved attributes
+ IndexedFaceSet *rep;
+ rep = new IndexedFaceSet(cleanVertices, cvSize, cleanNormals, cnSize, marray, meshFrsMaterials.size(), 0, 0,
+ numFaces, numVertexPerFaces, faceStyle, faceEdgeMarks, cleanVIndices, viSize,
+ cleanNIndices, niSize, MIndices, viSize, 0, 0, 0);
+ // sets the id of the rep
+ rep->setId(Id(id, 0));
+ rep->setName(obi->ob->id.name + 2);
+
+ const BBox<Vec3r> bbox = BBox<Vec3r>(Vec3r(ls.minBBox[0], ls.minBBox[1], ls.minBBox[2]),
+ Vec3r(ls.maxBBox[0], ls.maxBBox[1], ls.maxBBox[2]));
+ rep->setBBox(bbox);
+ shape->AddRep(rep);
+
+ Matrix44r meshMat = Matrix44r::identity();
+ currentMesh->setMatrix(meshMat);
+ currentMesh->Translate(0, 0, 0);
+
+ currentMesh->AddChild(shape);
+ _Scene->AddChild(currentMesh);
+}
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h
new file mode 100644
index 00000000000..1637a136a8a
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLENDER_FILE_LOADER_H__
+#define __BLENDER_FILE_LOADER_H__
+
+/** \file blender/freestyle/intern/blender_interface/BlenderFileLoader.h
+ * \ingroup freestyle
+ */
+
+#include <string.h>
+#include <float.h>
+
+#include "../geometry/BBox.h"
+#include "../geometry/Geom.h"
+#include "../geometry/GeomCleaner.h"
+#include "../geometry/GeomUtils.h"
+#include "../scene_graph/IndexedFaceSet.h"
+#include "../scene_graph/NodeGroup.h"
+#include "../scene_graph/NodeTransform.h"
+#include "../scene_graph/NodeShape.h"
+#include "../system/FreestyleConfig.h"
+#include "../system/RenderMonitor.h"
+
+// XXX Are those "ifdef __cplusplus" useful here?
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "DNA_material_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+
+#include "renderdatabase.h"
+#include "render_types.h"
+
+#include "BKE_mesh.h"
+#include "BKE_scene.h"
+
+#include "BLI_math.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+
+class NodeGroup;
+
+struct LoaderState {
+ float *pv;
+ float *pn;
+ IndexedFaceSet::FaceEdgeMark *pm;
+ unsigned *pvi;
+ unsigned *pni;
+ unsigned *pmi;
+ unsigned currentIndex;
+ unsigned currentMIndex;
+ float minBBox[3];
+ float maxBBox[3];
+};
+
+class LIB_SCENE_GRAPH_EXPORT BlenderFileLoader
+{
+public:
+ /*! Builds a MaxFileLoader */
+ BlenderFileLoader(Render *re, SceneRenderLayer *srl);
+ virtual ~BlenderFileLoader();
+
+ /*! Loads the 3D scene and returns a pointer to the scene root node */
+ NodeGroup * Load();
+
+ /*! Gets the number of read faces */
+ inline unsigned int numFacesRead() {return _numFacesRead;}
+
+ /*! Gets the smallest edge size read */
+ inline real minEdgeSize() {return _minEdgeSize;}
+
+ /*! Modifiers */
+ inline void setRenderMonitor(RenderMonitor *iRenderMonitor) {_pRenderMonitor = iRenderMonitor;}
+
+protected:
+ void insertShapeNode(ObjectInstanceRen *obi, int id);
+ int testDegenerateTriangle(float v1[3], float v2[3], float v3[3]);
+ bool testEdgeRotation(float v1[3], float v2[3], float v3[3], float v4[3]);
+ int countClippedFaces(float v1[3], float v2[3], float v3[3], int clip[3]);
+ void clipLine(float v1[3], float v2[3], float c[3], float z);
+ void clipTriangle(int numTris, float triCoords[][3], float v1[3], float v2[3], float v3[3],
+ float triNormals[][3], float n1[3], float n2[3], float n3[3],
+ bool edgeMarks[5], bool em1, bool em2, bool em3, int clip[3]);
+ void addTriangle(struct LoaderState *ls, float v1[3], float v2[3], float v3[3],
+ float n1[3], float n2[3], float n3[3], bool fm, bool em1, bool em2, bool em3);
+
+protected:
+ struct detri_t {
+ unsigned viA, viB, viP; // 0 <= viA, viB, viP < viSize
+ Vec3r v;
+ unsigned n;
+ };
+ Render *_re;
+ SceneRenderLayer *_srl;
+ NodeGroup *_Scene;
+ unsigned _numFacesRead;
+ real _minEdgeSize;
+ bool _smooth; /* if true, face smoothness is taken into account */
+ float _viewplane_left;
+ float _viewplane_right;
+ float _viewplane_bottom;
+ float _viewplane_top;
+ float _z_near, _z_far;
+
+ RenderMonitor *_pRenderMonitor;
+};
+
+#endif // __BLENDER_FILE_LOADER_H__
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
new file mode 100644
index 00000000000..cab6ebff4f2
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -0,0 +1,519 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+ * \ingroup freestyle
+ */
+
+#include "BlenderStrokeRenderer.h"
+#include "BlenderTextureManager.h"
+
+#include "../application/AppConfig.h"
+#include "../stroke/Canvas.h"
+
+#include "BKE_global.h"
+
+// XXX Are those "ifdef __cplusplus" useful here?
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_camera_types.h"
+#include "DNA_customdata_types.h"
+#include "DNA_listBase.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_library.h" /* free_libblock */
+#include "BKE_main.h" /* struct Main */
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_scene.h"
+
+#include "RE_pipeline.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : StrokeRenderer()
+{
+ // TEMPORARY - need a texture manager
+ _textureManager = new BlenderTextureManager;
+ _textureManager->load();
+
+ // for stroke mesh generation
+ _width = re->winx;
+ _height = re->winy;
+
+ //Scene.New("FreestyleStrokes")
+ old_scene = re->scene;
+
+ char name[22];
+ BLI_snprintf(name, sizeof(name), "FRS%d_%s", render_count, re->scene->id.name + 2);
+ freestyle_scene = BKE_scene_add(G.main, name);
+ freestyle_scene->r.cfra = old_scene->r.cfra;
+ freestyle_scene->r.mode = old_scene->r.mode &
+ ~(R_EDGE_FRS | R_SHADOW | R_SSS | R_PANORAMA | R_ENVMAP | R_MBLUR | R_BORDER);
+ freestyle_scene->r.xsch = re->rectx; // old_scene->r.xsch
+ freestyle_scene->r.ysch = re->recty; // old_scene->r.ysch
+ freestyle_scene->r.xasp = 1.0f; // old_scene->r.xasp;
+ freestyle_scene->r.yasp = 1.0f; // old_scene->r.yasp;
+ freestyle_scene->r.tilex = old_scene->r.tilex;
+ freestyle_scene->r.tiley = old_scene->r.tiley;
+ freestyle_scene->r.size = 100; // old_scene->r.size
+ freestyle_scene->r.maximsize = old_scene->r.maximsize;
+ 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);
+ 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;
+ freestyle_scene->r.border.ymin = old_scene->r.border.ymin;
+ freestyle_scene->r.border.xmax = old_scene->r.border.xmax;
+ freestyle_scene->r.border.ymax = old_scene->r.border.ymax;
+ strcpy(freestyle_scene->r.pic, old_scene->r.pic);
+ freestyle_scene->r.safety.xmin = old_scene->r.safety.xmin;
+ freestyle_scene->r.safety.ymin = old_scene->r.safety.ymin;
+ freestyle_scene->r.safety.xmax = old_scene->r.safety.xmax;
+ freestyle_scene->r.safety.ymax = old_scene->r.safety.ymax;
+ freestyle_scene->r.osa = old_scene->r.osa;
+ freestyle_scene->r.filtertype = old_scene->r.filtertype;
+ freestyle_scene->r.gauss = old_scene->r.gauss;
+ freestyle_scene->r.dither_intensity = old_scene->r.dither_intensity;
+ BLI_strncpy(freestyle_scene->r.engine, old_scene->r.engine, sizeof(freestyle_scene->r.engine));
+ freestyle_scene->r.im_format.planes = R_IMF_PLANES_RGBA;
+ freestyle_scene->r.im_format.imtype = R_IMF_IMTYPE_PNG;
+ BKE_scene_disable_color_management(freestyle_scene);
+
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("%s: %d threads\n", __func__, freestyle_scene->r.threads);
+ }
+
+ // Render layer
+ SceneRenderLayer *srl = (SceneRenderLayer *)freestyle_scene->r.layers.first;
+ srl->layflag = SCE_LAY_SOLID | SCE_LAY_ZTRA;
+
+ BKE_scene_set_background(G.main, freestyle_scene);
+
+ // Camera
+ Object *object_camera = BKE_object_add(freestyle_scene, OB_CAMERA);
+
+ Camera *camera = (Camera *)object_camera->data;
+ camera->type = CAM_ORTHO;
+ camera->ortho_scale = max(re->rectx, re->recty);
+ camera->clipsta = 0.1f;
+ camera->clipend = 100.0f;
+
+ _z_delta = 0.00001f;
+ _z = camera->clipsta + _z_delta;
+
+ // test
+ //_z = 999.90f; _z_delta = 0.01f;
+
+ object_camera->loc[0] = re->disprect.xmin + 0.5f * re->rectx;
+ object_camera->loc[1] = re->disprect.ymin + 0.5f * re->recty;
+ object_camera->loc[2] = 1.0f;
+
+ freestyle_scene->camera = object_camera;
+
+ // Material
+ material = BKE_material_add(G.main, "stroke_material");
+ material->mode |= MA_VERTEXCOLP;
+ material->mode |= MA_TRANSP;
+ material->mode |= MA_SHLESS;
+ material->vcol_alpha = 1;
+
+ // Reset serial mesh ID (used for BlenderStrokeRenderer::NewMesh())
+ _mesh_id = 0xffffffff;
+}
+
+BlenderStrokeRenderer::~BlenderStrokeRenderer()
+{
+ if (0 != _textureManager) {
+ delete _textureManager;
+ _textureManager = NULL;
+ }
+
+ // The freestyle_scene object is not released here. Instead,
+ // the scene is released in free_all_freestyle_renders() in
+ // source/blender/render/intern/source/pipeline.c, after the
+ // compositor has finished.
+
+ // release objects and data blocks
+ for (Base *b = (Base *)freestyle_scene->base.first; b; b = b->next) {
+ Object *ob = b->object;
+ void *data = ob->data;
+ char *name = ob->id.name;
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "removing " << name[0] << name[1] << ":" << (name+2) << endl;
+ }
+#endif
+ switch (ob->type) {
+ case OB_MESH:
+ BKE_libblock_free(&G.main->object, ob);
+ BKE_libblock_free(&G.main->mesh, data);
+ break;
+ case OB_CAMERA:
+ BKE_libblock_free(&G.main->object, ob);
+ BKE_libblock_free(&G.main->camera, data);
+ freestyle_scene->camera = NULL;
+ break;
+ default:
+ cerr << "Warning: unexpected object in the scene: " << name[0] << name[1] << ":" << (name + 2) << endl;
+ }
+ }
+ BLI_freelistN(&freestyle_scene->base);
+
+ // release material
+ BKE_libblock_free(&G.main->mat, material);
+
+ BKE_scene_set_background(G.main, old_scene);
+}
+
+float BlenderStrokeRenderer::get_stroke_vertex_z(void) const
+{
+ float z = _z;
+ BlenderStrokeRenderer *self = const_cast<BlenderStrokeRenderer *>(this);
+ if (!(_z < _z_delta * 100000.0f))
+ self->_z_delta *= 10.0f;
+ self->_z += _z_delta;
+ return -z;
+}
+
+unsigned int BlenderStrokeRenderer::get_stroke_mesh_id(void) const
+{
+ unsigned mesh_id = _mesh_id;
+ BlenderStrokeRenderer *self = const_cast<BlenderStrokeRenderer *>(this);
+ self->_mesh_id--;
+ return mesh_id;
+}
+
+void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
+{
+ RenderStrokeRepBasic(iStrokeRep);
+}
+
+void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
+{
+ ////////////////////
+ // Build up scene
+ ////////////////////
+
+ vector<Strip*>& strips = iStrokeRep->getStrips();
+ Strip::vertex_container::iterator v[3];
+ StrokeVertexRep *svRep[3];
+ /* Vec3r color[3]; */ /* UNUSED */
+ unsigned int vertex_index, edge_index, loop_index;
+ Vec2r p;
+
+ for (vector<Strip*>::iterator s = strips.begin(), send = strips.end(); s != send; ++s) {
+ Strip::vertex_container& strip_vertices = (*s)->vertices();
+ int strip_vertex_count = (*s)->sizeStrip();
+ int xl, xu, yl, yu, n, visible_faces, visible_segments;
+ bool visible;
+
+ // iterate over all vertices and count visible faces and strip segments
+ // (note: a strip segment is a series of visible faces, while two strip
+ // segments are separated by one or more invisible faces)
+ v[0] = strip_vertices.begin();
+ v[1] = v[0] + 1;
+ v[2] = v[0] + 2;
+ visible_faces = visible_segments = 0;
+ visible = false;
+ for (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]);
+ xl = xu = yl = yu = 0;
+ for (int j = 0; j < 3; j++) {
+ p = svRep[j]->point2d();
+ if (p[0] < 0.0)
+ xl++;
+ else if (p[0] > _width)
+ xu++;
+ if (p[1] < 0.0)
+ yl++;
+ else if (p[1] > _height)
+ yu++;
+ }
+ if (xl == 3 || xu == 3 || yl == 3 || yu == 3) {
+ visible = false;
+ }
+ else {
+ visible_faces++;
+ if (!visible)
+ visible_segments++;
+ visible = true;
+ }
+ }
+ if (visible_faces == 0)
+ continue;
+
+ //me = Mesh.New()
+#if 0
+ Object *object_mesh = BKE_object_add(freestyle_scene, OB_MESH);
+#else
+ Object *object_mesh = NewMesh();
+#endif
+ Mesh *mesh = (Mesh *)object_mesh->data;
+#if 0
+ MEM_freeN(mesh->bb);
+ mesh->bb = NULL;
+ mesh->id.us = 0;
+#endif
+#if 1
+ //me.materials = [mat]
+ mesh->mat = (Material **)MEM_mallocN(1 * sizeof(Material *), "MaterialList");
+ mesh->mat[0] = material;
+ mesh->totcol = 1;
+ test_object_materials((ID *)mesh);
+#else
+ assign_material(object_mesh, material, object_mesh->totcol + 1);
+ object_mesh->actcol = object_mesh->totcol;
+#endif
+
+ // vertices allocation
+ mesh->totvert = visible_faces + visible_segments * 2;
+ mesh->mvert = (MVert *)CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CALLOC, NULL, mesh->totvert);
+
+ // edges allocation
+ mesh->totedge = visible_faces * 2 + visible_segments;
+ mesh->medge = (MEdge *)CustomData_add_layer(&mesh->edata, CD_MEDGE, CD_CALLOC, NULL, mesh->totedge);
+
+ // faces allocation
+ mesh->totpoly = visible_faces;
+ mesh->mpoly = (MPoly *)CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CALLOC, NULL, mesh->totpoly);
+
+ // loops allocation
+ mesh->totloop = visible_faces * 3;
+ mesh->mloop = (MLoop *)CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, NULL, mesh->totloop);
+
+ // colors allocation
+ mesh->mloopcol = (MLoopCol *)CustomData_add_layer(&mesh->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, mesh->totloop);
+
+ ////////////////////
+ // Data copy
+ ////////////////////
+
+ MVert *vertices = mesh->mvert;
+ MEdge *edges = mesh->medge;
+ MPoly *polys = mesh->mpoly;
+ MLoop *loops = mesh->mloop;
+ MLoopCol *colors = mesh->mloopcol;
+
+ v[0] = strip_vertices.begin();
+ v[1] = v[0] + 1;
+ v[2] = v[0] + 2;
+
+ vertex_index = edge_index = loop_index = 0;
+ visible = false;
+
+ // Note: Mesh generation in the following loop assumes stroke strips
+ // to be triangle strips.
+ for (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]);
+ xl = xu = yl = yu = 0;
+ for (int j = 0; j < 3; j++) {
+ p = svRep[j]->point2d();
+ if (p[0] < 0.0)
+ xl++;
+ else if (p[0] > _width)
+ xu++;
+ if (p[1] < 0.0)
+ yl++;
+ else if (p[1] > _height)
+ yu++;
+ }
+ if (xl == 3 || xu == 3 || yl == 3 || yu == 3) {
+ 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;
+ ++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;
+ ++vertex_index;
+
+ // first edge
+ edges->v1 = vertex_index - 2;
+ edges->v2 = vertex_index - 1;
+ ++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;
+ ++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;
+
+ // loops
+ if (n % 2 == 0) {
+ 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;
+ }
+ else {
+ 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;
+ }
+ loops += 3;
+ loop_index += 3;
+
+ // colors
+ if (n % 2 == 0) {
+ 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());
+ }
+ 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[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());
+ }
+ colors += 3;
+ }
+ } // loop over strip vertices
+#if 0
+ BKE_mesh_validate(mesh, TRUE);
+#endif
+ } // loop over strips
+}
+
+// A replacement of BKE_object_add() for better performance.
+Object *BlenderStrokeRenderer::NewMesh() const
+{
+ Object *ob;
+ Base *base;
+ char name[MAX_ID_NAME];
+ unsigned int mesh_id = get_stroke_mesh_id();
+
+ BLI_snprintf(name, MAX_ID_NAME, "0%08xOB", mesh_id);
+ ob = BKE_object_add_only_object(G.main, OB_MESH, name);
+ BLI_snprintf(name, MAX_ID_NAME, "0%08xME", mesh_id);
+ ob->data = BKE_mesh_add(G.main, name);
+ ob->lay = 1;
+
+ base = BKE_scene_base_add(freestyle_scene, ob);
+#if 0
+ BKE_scene_base_deselect_all(scene);
+ BKE_scene_base_select(scene, base);
+#else
+ (void)base;
+#endif
+ ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+
+ return ob;
+}
+
+Render *BlenderStrokeRenderer::RenderScene(Render *re)
+{
+ Camera *camera = (Camera *)freestyle_scene->camera->data;
+ if (camera->clipend < _z)
+ camera->clipend = _z + _z_delta * 100.0f;
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "clipsta " << camera->clipsta << ", clipend " << camera->clipend << endl;
+ }
+#endif
+
+ Render *freestyle_render = RE_NewRender(freestyle_scene->id.name);
+
+ RE_RenderFreestyleStrokes(freestyle_render, G.main, freestyle_scene);
+ return freestyle_render;
+}
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
new file mode 100644
index 00000000000..fa6e83b853f
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
@@ -0,0 +1,78 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLENDER_STROKE_RENDERER_H__
+#define __BLENDER_STROKE_RENDERER_H__
+
+/** \file blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
+ * \ingroup freestyle
+ */
+
+#include "../stroke/StrokeRenderer.h"
+#include "../system/FreestyleConfig.h"
+
+// XXX Are those "ifdef __cplusplus" useful here?
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "DNA_material_types.h"
+#include "DNA_scene_types.h"
+
+#include "render_types.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+class LIB_STROKE_EXPORT BlenderStrokeRenderer : public StrokeRenderer
+{
+public:
+ BlenderStrokeRenderer(Render *re, int render_count);
+ virtual ~BlenderStrokeRenderer();
+
+ /*! Renders a stroke rep */
+ virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const;
+ virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const;
+
+ Object *NewMesh() const;
+
+ Render *RenderScene(Render *re);
+
+protected:
+ Scene *old_scene;
+ Scene *freestyle_scene;
+ Material *material;
+ float _width, _height;
+ float _z, _z_delta;
+ unsigned int _mesh_id;
+
+ float get_stroke_vertex_z(void) const;
+ unsigned int get_stroke_mesh_id(void) const;
+};
+
+#endif // __BLENDER_STROKE_RENDERER_H__
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h
new file mode 100644
index 00000000000..51eaf4fe504
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h
@@ -0,0 +1,74 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLENDERSTYLEMODULE_H__
+#define __BLENDERSTYLEMODULE_H__
+
+/** \file blender/freestyle/intern/blender_interface/BlenderStyleModule.h
+ * \ingroup freestyle
+ */
+
+#include "../stroke/StyleModule.h"
+#include "../system/PythonInterpreter.h"
+
+extern "C" {
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_text.h"
+}
+
+class BlenderStyleModule : public StyleModule
+{
+public:
+ BlenderStyleModule(struct Text *text, const string &name, Interpreter *inter) : StyleModule(name, inter)
+ {
+ _text = text;
+ }
+
+ virtual ~BlenderStyleModule()
+ {
+ }
+
+ virtual void close()
+ {
+ BKE_text_unlink(G.main, _text);
+ BKE_libblock_free(&G.main->text, _text);
+ }
+
+protected:
+ virtual int interpret()
+ {
+ PythonInterpreter *py_inter = dynamic_cast<PythonInterpreter*>(_inter);
+ assert(py_inter != 0);
+ return py_inter->interpretText(_text, getFileName());
+ }
+
+private:
+ struct Text *_text;
+};
+
+#endif // __BLENDERSTYLEMODULE_H__
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.cpp b/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.cpp
new file mode 100644
index 00000000000..aa8f8809cea
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/blender_interface/BlenderTextureManager.cpp
+ * \ingroup freestyle
+ */
+
+#include "BlenderTextureManager.h"
+
+#include "BKE_global.h"
+
+BlenderTextureManager::BlenderTextureManager()
+: TextureManager()
+{
+ //_brushes_path = Config::getInstance()...
+}
+
+BlenderTextureManager::~BlenderTextureManager()
+{
+}
+
+void BlenderTextureManager::loadStandardBrushes()
+{
+#if 0
+ getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::HUMID_MEDIUM);
+ getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::HUMID_MEDIUM);
+ getBrushTextureIndex(TEXTURES_DIR "/brushes/oil.bmp", Stroke::HUMID_MEDIUM);
+ getBrushTextureIndex(TEXTURES_DIR "/brushes/oilnoblend.bmp", Stroke::HUMID_MEDIUM);
+ getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::DRY_MEDIUM);
+ getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::DRY_MEDIUM);
+ getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueDryBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
+ getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
+ _defaultTextureId = getBrushTextureIndex("smoothAlpha.bmp", Stroke::OPAQUE_MEDIUM);
+#endif
+}
+
+unsigned int BlenderTextureManager::loadBrush(string sname, Stroke::MediumType mediumType)
+{
+#if 0
+ GLuint texId;
+ glGenTextures(1, &texId);
+ bool found = false;
+ vector<string> pathnames;
+ string path; //soc
+ StringUtils::getPathName(TextureManager::Options::getBrushesPath(), sname, pathnames);
+ for (vector<string>::const_iterator j = pathnames.begin(); j != pathnames.end(); j++) {
+ path = j->c_str();
+ //soc if (QFile::exists(path)) {
+ if (BLI_exists( const_cast<char *>(path.c_str()))) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return 0;
+ // Brush texture
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Loading brush texture..." << endl;
+ }
+ switch (mediumType) {
+ case Stroke::DRY_MEDIUM:
+ //soc prepareTextureLuminance((const char*)path.toAscii(), texId);
+ prepareTextureLuminance(StringUtils::toAscii(path), texId);
+ break;
+ case Stroke::HUMID_MEDIUM:
+ case Stroke::OPAQUE_MEDIUM:
+ default:
+ //soc prepareTextureAlpha((const char*)path.toAscii(), texId);
+ prepareTextureAlpha(StringUtils::toAscii(path), texId);
+ break;
+ }
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Done." << endl << endl;
+ }
+
+ return texId;
+#else
+ return 0;
+#endif
+}
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.h b/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.h
new file mode 100644
index 00000000000..bd6f377b1eb
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLENDERTEXTUREMANAGER_H__
+#define __BLENDERTEXTUREMANAGER_H__
+
+/** \file blender/freestyle/intern/blender_interface/BlenderTextureManager.h
+ * \ingroup freestyle
+ */
+
+# include "../stroke/StrokeRenderer.h"
+# include "../stroke/StrokeRep.h"
+# include "../system/FreestyleConfig.h"
+
+/*! Class to load textures */
+class LIB_RENDERING_EXPORT BlenderTextureManager : public TextureManager
+{
+public:
+ BlenderTextureManager();
+ virtual ~BlenderTextureManager();
+
+protected:
+ virtual unsigned int loadBrush(string fileName, Stroke::MediumType=Stroke::OPAQUE_MEDIUM);
+
+protected:
+ virtual void loadStandardBrushes();
+};
+
+#endif // __BLENDERTEXTUREMANAGER_H__
diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
new file mode 100644
index 00000000000..50547c00dd4
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
+ * \ingroup freestyle
+ */
+
+#include <iostream>
+#include <map>
+#include <set>
+
+#include "../application/AppCanvas.h"
+#include "../application/AppConfig.h"
+#include "../application/AppView.h"
+#include "../application/Controller.h"
+
+using namespace std;
+
+extern "C" {
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_camera_types.h"
+#include "DNA_freestyle_types.h"
+#include "DNA_group_types.h"
+#include "DNA_text_types.h"
+
+#include "BKE_freestyle.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_linestyle.h"
+#include "BKE_main.h"
+#include "BKE_text.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_callbacks.h"
+
+#include "BPY_extern.h"
+
+#include "renderpipeline.h"
+#include "pixelblending.h"
+
+#include "FRS_freestyle.h"
+
+#define DEFAULT_SPHERE_RADIUS 1.0f
+#define DEFAULT_DKR_EPSILON 0.0f
+
+// Freestyle configuration
+static short freestyle_is_initialized = 0;
+static Config::Path *pathconfig = NULL;
+static Controller *controller = NULL;
+static AppView *view = NULL;
+
+// line set buffer for copy & paste
+static FreestyleLineSet lineset_buffer;
+static bool lineset_copied = false;
+
+// camera information
+float freestyle_viewpoint[3];
+float freestyle_mv[4][4];
+float freestyle_proj[4][4];
+int freestyle_viewport[4];
+
+// current scene
+Scene *freestyle_scene;
+
+static string default_module_path;
+
+static void load_post_callback(struct Main *main, struct ID *id, void *arg)
+{
+ lineset_copied = false;
+}
+
+static bCallbackFuncStore load_post_callback_funcstore = {
+ NULL, NULL, /* next, prev */
+ load_post_callback, /* func */
+ NULL, /* arg */
+ 0 /* alloc */
+};
+
+//=======================================================
+// Initialization
+//=======================================================
+
+void FRS_initialize()
+{
+ if (freestyle_is_initialized)
+ return;
+
+ pathconfig = new Config::Path;
+ controller = new Controller();
+ view = new AppView;
+ controller->setView(view);
+ controller->Clear();
+ freestyle_scene = NULL;
+ lineset_copied = false;
+
+ default_module_path = pathconfig->getProjectDir() + Config::DIR_SEP + "style_modules" +
+ Config::DIR_SEP + "contour.py";
+
+ BLI_callback_add(&load_post_callback_funcstore, BLI_CB_EVT_LOAD_POST);
+
+ freestyle_is_initialized = 1;
+}
+
+void FRS_set_context(bContext *C)
+{
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "FRS_set_context: context 0x" << C << " scene 0x" << CTX_data_scene(C) << endl;
+ }
+ controller->setContext(C);
+}
+
+void FRS_exit()
+{
+ delete pathconfig;
+ delete controller;
+ delete view;
+}
+
+//=======================================================
+// Rendering
+//=======================================================
+
+static void init_view(Render *re)
+{
+ int width = re->winx;
+ int height = re->winy;
+ int xmin = re->disprect.xmin;
+ int ymin = re->disprect.ymin;
+ int xmax = re->disprect.xmax;
+ int ymax = re->disprect.ymax;
+
+ float thickness = 1.0f;
+ switch (re->r.line_thickness_mode) {
+ case R_LINE_THICKNESS_ABSOLUTE:
+ thickness = re->r.unit_line_thickness * (re->r.size / 100.f);
+ break;
+ case R_LINE_THICKNESS_RELATIVE:
+ thickness = height / 480.f;
+ break;
+ }
+
+ freestyle_viewport[0] = freestyle_viewport[1] = 0;
+ freestyle_viewport[2] = width;
+ freestyle_viewport[3] = height;
+
+ view->setWidth(width);
+ view->setHeight(height);
+ view->setBorder(xmin, ymin, xmax, ymax);
+ view->setThickness(thickness);
+
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "\n=== Dimensions of the 2D image coordinate system ===" << endl;
+ cout << "Width : " << width << endl;
+ cout << "Height : " << height << endl;
+ if (re->r.mode & R_BORDER)
+ cout << "Border : (" << xmin << ", " << ymin << ") - (" << xmax << ", " << ymax << ")" << endl;
+ cout << "Unit line thickness : " << thickness << " pixel(s)" << endl;
+ }
+}
+
+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.
+
+ freestyle_viewpoint[0] = 0.0;
+ freestyle_viewpoint[1] = 0.0;
+ freestyle_viewpoint[2] = 0.0;
+
+ unit_m4(freestyle_mv);
+
+ copy_m4_m4(freestyle_proj, re->winmat);
+
+#if 0
+ print_m4("mv", freestyle_mv);
+ print_m4("proj", freestyle_proj);
+#endif
+}
+
+static char *escape_quotes(char *name)
+{
+ char *s = (char *)MEM_mallocN(strlen(name) * 2 + 1, "escape_quotes");
+ char *p = s;
+ while (*name) {
+ if (*name == '\'')
+ *(p++) = '\\';
+ *(p++) = *(name++);
+ }
+ *p = '\0';
+ return s;
+}
+
+static Text *create_lineset_handler(char *layer_name, char *lineset_name)
+{
+ char *s1 = escape_quotes(layer_name);
+ char *s2 = escape_quotes(lineset_name);
+ Text *text = BKE_text_add(G.main, 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");
+ MEM_freeN(s1);
+ MEM_freeN(s2);
+ return text;
+}
+
+struct edge_type_condition
+{
+ int edge_type, value;
+};
+
+// examines the conditions and returns true if the target edge type needs to be computed
+static bool test_edge_type_conditions(struct edge_type_condition *conditions,
+ int num_edge_types, bool logical_and, int target, bool distinct)
+{
+ int target_condition = 0;
+ int num_non_target_positive_conditions = 0;
+ int num_non_target_negative_conditions = 0;
+
+ for (int i = 0; i < num_edge_types; i++) {
+ if (conditions[i].edge_type == target)
+ target_condition = conditions[i].value;
+ else if (conditions[i].value > 0)
+ ++num_non_target_positive_conditions;
+ else if (conditions[i].value < 0)
+ ++num_non_target_negative_conditions;
+ }
+ if (distinct) {
+ // In this case, the 'target' edge type is assumed to appear on distinct edge
+ // of its own and never together with other edge types.
+ if (logical_and) {
+ if (num_non_target_positive_conditions > 0)
+ return false;
+ if (target_condition > 0)
+ return true;
+ if (target_condition < 0)
+ return false;
+ if (num_non_target_negative_conditions > 0)
+ return true;
+ }
+ else {
+ if (target_condition > 0)
+ return true;
+ if (num_non_target_negative_conditions > 0)
+ return true;
+ if (target_condition < 0)
+ return false;
+ if (num_non_target_positive_conditions > 0)
+ return false;
+ }
+ }
+ else {
+ // In this case, the 'target' edge type may appear together with other edge types.
+ if (target_condition > 0)
+ return true;
+ if (target_condition < 0)
+ return true;
+ if (logical_and) {
+ if (num_non_target_positive_conditions > 0)
+ return false;
+ if (num_non_target_negative_conditions > 0)
+ return true;
+ }
+ else {
+ if (num_non_target_negative_conditions > 0)
+ return true;
+ if (num_non_target_positive_conditions > 0)
+ return false;
+ }
+ }
+ return true;
+}
+
+static void prepare(Render *re, SceneRenderLayer *srl)
+{
+ // load mesh
+ re->i.infostr = "Freestyle: Mesh loading";
+ re->stats_draw(re->sdh, &re->i);
+ re->i.infostr = NULL;
+ if (controller->LoadMesh(re, srl)) // returns if scene cannot be loaded or if empty
+ return;
+ if (re->test_break(re->tbh))
+ return;
+
+ // add style modules
+ FreestyleConfig *config = &srl->freestyleConfig;
+
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "\n=== Rendering options ===" << endl;
+ }
+ int layer_count = 0;
+
+ switch (config->mode) {
+ case FREESTYLE_CONTROL_SCRIPT_MODE:
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Modules :" << endl;
+ }
+ for (FreestyleModuleConfig *module_conf = (FreestyleModuleConfig *)config->modules.first;
+ module_conf;
+ module_conf = module_conf->next)
+ {
+ if (module_conf->is_displayed) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << " " << layer_count + 1 << ": " << module_conf->module_path << endl;
+ }
+ controller->InsertStyleModule(layer_count, module_conf->module_path);
+ controller->toggleLayer(layer_count, true);
+ layer_count++;
+ }
+ }
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << endl;
+ }
+ controller->setComputeRidgesAndValleysFlag((config->flags & FREESTYLE_RIDGES_AND_VALLEYS_FLAG) ? true : false);
+ controller->setComputeSuggestiveContoursFlag((config->flags & FREESTYLE_SUGGESTIVE_CONTOURS_FLAG) ? true : false);
+ controller->setComputeMaterialBoundariesFlag((config->flags & FREESTYLE_MATERIAL_BOUNDARIES_FLAG) ? true : false);
+ break;
+ case FREESTYLE_CONTROL_EDITOR_MODE:
+ int use_ridges_and_valleys = 0;
+ int use_suggestive_contours = 0;
+ int use_material_boundaries = 0;
+ struct edge_type_condition conditions[] = {
+ {FREESTYLE_FE_SILHOUETTE, 0},
+ {FREESTYLE_FE_BORDER, 0},
+ {FREESTYLE_FE_CREASE, 0},
+ {FREESTYLE_FE_RIDGE_VALLEY, 0},
+ {FREESTYLE_FE_SUGGESTIVE_CONTOUR, 0},
+ {FREESTYLE_FE_MATERIAL_BOUNDARY, 0},
+ {FREESTYLE_FE_CONTOUR, 0},
+ {FREESTYLE_FE_EXTERNAL_CONTOUR, 0},
+ {FREESTYLE_FE_EDGE_MARK, 0}
+ };
+ int num_edge_types = sizeof(conditions) / sizeof(struct edge_type_condition);
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Linesets:" << endl;
+ }
+ for (FreestyleLineSet *lineset = (FreestyleLineSet *)config->linesets.first;
+ lineset;
+ lineset = lineset->next)
+ {
+ if (lineset->flags & FREESTYLE_LINESET_ENABLED) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << " " << layer_count+1 << ": " << lineset->name << " - " <<
+ lineset->linestyle->id.name + 2 << endl;
+ }
+ Text *text = create_lineset_handler(srl->name, lineset->name);
+ controller->InsertStyleModule(layer_count, lineset->name, text);
+ controller->toggleLayer(layer_count, true);
+ if (!(lineset->selection & FREESTYLE_SEL_EDGE_TYPES) || !lineset->edge_types) {
+ ++use_ridges_and_valleys;
+ ++use_suggestive_contours;
+ ++use_material_boundaries;
+ }
+ else {
+ // conditions for feature edge selection by edge types
+ for (int i = 0; i < num_edge_types; i++) {
+ if (!(lineset->edge_types & conditions[i].edge_type))
+ conditions[i].value = 0; // no condition specified
+ else if (!(lineset->exclude_edge_types & conditions[i].edge_type))
+ conditions[i].value = 1; // condition: X
+ else
+ conditions[i].value = -1; // condition: NOT X
+ }
+ // logical operator for the selection conditions
+ bool logical_and = ((lineset->flags & FREESTYLE_LINESET_FE_AND) != 0);
+ // negation operator
+ if (lineset->flags & FREESTYLE_LINESET_FE_NOT) {
+ // convert an Exclusive condition into an Inclusive equivalent using De Morgan's laws:
+ // NOT (X OR Y) --> (NOT X) AND (NOT Y)
+ // NOT (X AND Y) --> (NOT X) OR (NOT Y)
+ for (int i = 0; i < num_edge_types; i++)
+ conditions[i].value *= -1;
+ logical_and = !logical_and;
+ }
+ if (test_edge_type_conditions(conditions, num_edge_types, logical_and,
+ FREESTYLE_FE_RIDGE_VALLEY, true))
+ {
+ ++use_ridges_and_valleys;
+ }
+ if (test_edge_type_conditions(conditions, num_edge_types, logical_and,
+ FREESTYLE_FE_SUGGESTIVE_CONTOUR, true))
+ {
+ ++use_suggestive_contours;
+ }
+ if (test_edge_type_conditions(conditions, num_edge_types, logical_and,
+ FREESTYLE_FE_MATERIAL_BOUNDARY, true))
+ {
+ ++use_material_boundaries;
+ }
+ }
+ layer_count++;
+ }
+ }
+ controller->setComputeRidgesAndValleysFlag(use_ridges_and_valleys > 0);
+ controller->setComputeSuggestiveContoursFlag(use_suggestive_contours > 0);
+ controller->setComputeMaterialBoundariesFlag(use_material_boundaries > 0);
+ break;
+ }
+
+ // set parameters
+ if (config->flags & FREESTYLE_ADVANCED_OPTIONS_FLAG) {
+ controller->setSphereRadius(config->sphere_radius);
+ controller->setSuggestiveContourKrDerivativeEpsilon(config->dkr_epsilon);
+ }
+ else {
+ controller->setSphereRadius(DEFAULT_SPHERE_RADIUS);
+ controller->setSuggestiveContourKrDerivativeEpsilon(DEFAULT_DKR_EPSILON);
+ }
+ controller->setFaceSmoothness((config->flags & FREESTYLE_FACE_SMOOTHNESS_FLAG) ? true : false);
+ controller->setCreaseAngle(RAD2DEGF(config->crease_angle));
+ controller->setVisibilityAlgo((config->flags & FREESTYLE_CULLING) ?
+ FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE :
+ FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE);
+
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Crease angle : " << controller->getCreaseAngle() << endl;
+ cout << "Sphere radius : " << controller->getSphereRadius() << endl;
+ cout << "Face smoothness : " << (controller->getFaceSmoothness() ? "enabled" : "disabled") << endl;
+ cout << "Redges and valleys : " << (controller->getComputeRidgesAndValleysFlag() ? "enabled" : "disabled") <<
+ endl;
+ cout << "Suggestive contours : " <<
+ (controller->getComputeSuggestiveContoursFlag() ? "enabled" : "disabled") << endl;
+ cout << "Suggestive contour Kr derivative epsilon : " <<
+ controller->getSuggestiveContourKrDerivativeEpsilon() << endl;
+ cout << "Material boundaries : " <<
+ (controller->getComputeMaterialBoundariesFlag() ? "enabled" : "disabled") << endl;
+ cout << endl;
+ }
+
+ // set diffuse and z depth passes
+ RenderLayer *rl = RE_GetRenderLayer(re->result, srl->name);
+ bool diffuse = false, z = false;
+ for (RenderPass *rpass = (RenderPass *)rl->passes.first; rpass; rpass = rpass->next) {
+ switch (rpass->passtype) {
+ case SCE_PASS_DIFFUSE:
+ controller->setPassDiffuse(rpass->rect, rpass->rectx, rpass->recty);
+ diffuse = true;
+ break;
+ case SCE_PASS_Z:
+ controller->setPassZ(rpass->rect, rpass->rectx, rpass->recty);
+ z = true;
+ break;
+ }
+ }
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Passes :" << endl;
+ cout << " Diffuse = " << (diffuse ? "enabled" : "disabled") << endl;
+ cout << " Z = " << (z ? "enabled" : "disabled") << endl;
+ }
+
+ // compute view map
+ re->i.infostr = "Freestyle: View map creation";
+ re->stats_draw(re->sdh, &re->i);
+ re->i.infostr = NULL;
+ controller->ComputeViewMap();
+}
+
+void FRS_composite_result(Render *re, SceneRenderLayer *srl, Render *freestyle_render)
+{
+ RenderLayer *rl;
+ float *src, *dest, *pixSrc, *pixDest;
+ int x, y, rectx, recty;
+
+ if (freestyle_render == NULL || freestyle_render->result == NULL)
+ return;
+
+ rl = render_get_active_layer( freestyle_render, freestyle_render->result );
+ if (!rl || rl->rectf == NULL) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Cannot find Freestyle result image" << endl;
+ }
+ return;
+ }
+ src = rl->rectf;
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "src: " << rl->rectx << " x " << rl->recty << endl;
+ }
+#endif
+
+ rl = RE_GetRenderLayer(re->result, srl->name);
+ if (!rl || rl->rectf == NULL) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "No layer to composite to" << endl;
+ }
+ return;
+ }
+ dest = rl->rectf;
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "dest: " << rl->rectx << " x " << rl->recty << endl;
+ }
+#endif
+
+ rectx = re->rectx;
+ recty = re->recty;
+ for (y = 0; y < recty; y++) {
+ for (x = 0; x < rectx; x++) {
+ pixSrc = src + 4 * (rectx * y + x);
+ if (pixSrc[3] > 0.0) {
+ pixDest = dest + 4 * (rectx * y + x);
+ addAlphaOverFloat(pixDest, pixSrc);
+ }
+ }
+ }
+}
+
+static int displayed_layer_count(SceneRenderLayer *srl)
+{
+ int count = 0;
+
+ switch (srl->freestyleConfig.mode) {
+ case FREESTYLE_CONTROL_SCRIPT_MODE:
+ for (FreestyleModuleConfig *module = (FreestyleModuleConfig *)srl->freestyleConfig.modules.first;
+ module;
+ module = module->next)
+ {
+ if (module->is_displayed)
+ count++;
+ }
+ break;
+ case FREESTYLE_CONTROL_EDITOR_MODE:
+ for (FreestyleLineSet *lineset = (FreestyleLineSet *)srl->freestyleConfig.linesets.first;
+ lineset;
+ lineset = lineset->next)
+ {
+ if (lineset->flags & FREESTYLE_LINESET_ENABLED)
+ count++;
+ }
+ break;
+ }
+ return count;
+}
+
+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)
+{
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << endl;
+ cout << "#===============================================================" << endl;
+ cout << "# Freestyle" << endl;
+ cout << "#===============================================================" << endl;
+ }
+
+ init_view(re);
+ init_camera(re);
+
+ controller->ResetRenderCount();
+}
+
+Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl)
+{
+ Render *freestyle_render = NULL;
+
+ RenderMonitor monitor(re);
+ controller->setRenderMonitor(&monitor);
+
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << endl;
+ cout << "----------------------------------------------------------" << endl;
+ cout << "| " << (re->scene->id.name + 2) << "|" << srl->name << endl;
+ cout << "----------------------------------------------------------" << endl;
+ }
+
+ // prepare Freestyle:
+ // - load mesh
+ // - add style modules
+ // - set parameters
+ // - compute view map
+ prepare(re, srl);
+
+ if (re->test_break(re->tbh)) {
+ controller->CloseFile();
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Break" << endl;
+ }
+ return NULL;
+ }
+
+ // render and composite Freestyle result
+ if (controller->_ViewMap) {
+ // render strokes
+ re->i.infostr = "Freestyle: Stroke rendering";
+ re->stats_draw(re->sdh, &re->i);
+ re->i.infostr = NULL;
+ freestyle_scene = re->scene;
+ controller->DrawStrokes();
+ freestyle_render = controller->RenderStrokes(re);
+ controller->CloseFile();
+ freestyle_scene = NULL;
+
+ // composite result
+ FRS_composite_result(re, srl, freestyle_render);
+ RE_FreeRenderResult(freestyle_render->result);
+ freestyle_render->result = NULL;
+ }
+
+ return freestyle_render;
+}
+
+void FRS_finish_stroke_rendering(Render *re)
+{
+ // clear canvas
+ controller->Clear();
+}
+
+//=======================================================
+// Freestyle Panel Configuration
+//=======================================================
+
+void FRS_copy_active_lineset(FreestyleConfig *config)
+{
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
+
+ if (lineset) {
+ lineset_buffer.linestyle = lineset->linestyle;
+ lineset_buffer.flags = lineset->flags;
+ lineset_buffer.selection = lineset->selection;
+ lineset_buffer.qi = lineset->qi;
+ lineset_buffer.qi_start = lineset->qi_start;
+ lineset_buffer.qi_end = lineset->qi_end;
+ lineset_buffer.edge_types = lineset->edge_types;
+ lineset_buffer.exclude_edge_types = lineset->exclude_edge_types;
+ lineset_buffer.group = lineset->group;
+ strcpy(lineset_buffer.name, lineset->name);
+ lineset_copied = true;
+ }
+}
+
+void FRS_paste_active_lineset(FreestyleConfig *config)
+{
+ if (!lineset_copied)
+ return;
+
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
+
+ if (lineset) {
+ lineset->linestyle->id.us--;
+ lineset->linestyle = lineset_buffer.linestyle;
+ lineset->linestyle->id.us++;
+ lineset->flags = lineset_buffer.flags;
+ lineset->selection = lineset_buffer.selection;
+ lineset->qi = lineset_buffer.qi;
+ lineset->qi_start = lineset_buffer.qi_start;
+ lineset->qi_end = lineset_buffer.qi_end;
+ lineset->edge_types = lineset_buffer.edge_types;
+ lineset->exclude_edge_types = lineset_buffer.exclude_edge_types;
+ if (lineset->group) {
+ lineset->group->id.us--;
+ lineset->group = NULL;
+ }
+ if (lineset_buffer.group) {
+ lineset->group = lineset_buffer.group;
+ lineset->group->id.us++;
+ }
+ strcpy(lineset->name, lineset_buffer.name);
+ BKE_freestyle_lineset_unique_name(config, lineset);
+ lineset->flags |= FREESTYLE_LINESET_CURRENT;
+ }
+}
+
+void FRS_delete_active_lineset(FreestyleConfig *config)
+{
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
+
+ if (lineset) {
+ if (lineset->group) {
+ lineset->group->id.us--;
+ lineset->group = NULL;
+ }
+ lineset->linestyle->id.us--;
+ lineset->linestyle = NULL;
+ BLI_remlink(&config->linesets, lineset);
+ MEM_freeN(lineset);
+ BKE_freestyle_lineset_set_active_index(config, 0);
+ }
+}
+
+void FRS_move_active_lineset_up(FreestyleConfig *config)
+{
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
+
+ if (lineset) {
+ BLI_remlink(&config->linesets, lineset);
+ BLI_insertlinkbefore(&config->linesets, lineset->prev, lineset);
+ }
+}
+
+void FRS_move_active_lineset_down(FreestyleConfig *config)
+{
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
+
+ if (lineset) {
+ BLI_remlink(&config->linesets, lineset);
+ BLI_insertlinkafter(&config->linesets, lineset->next, lineset);
+ }
+}
+
+} // extern "C"
diff --git a/source/blender/freestyle/intern/geometry/BBox.h b/source/blender/freestyle/intern/geometry/BBox.h
new file mode 100644
index 00000000000..b13960a4d2e
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/BBox.h
@@ -0,0 +1,154 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BBOX_H__
+#define __BBOX_H__
+
+/** \file blender/freestyle/intern/geometry/BBox.h
+ * \ingroup freestyle
+ * \brief A class to hold a bounding box
+ * \author Stephane Grabli
+ * \date 22/05/2003
+ */
+
+template <class Point>
+class BBox
+{
+public:
+ inline BBox()
+ {
+ _empty = true;
+ }
+
+ template <class T>
+ inline BBox(const T& min_in, const T& max_in) : _min(min_in), _max(max_in)
+ {
+ _empty = false;
+ }
+
+ template <class T>
+ inline BBox(const BBox<T>& b) : _min(b.getMin()), _max(b.getMax())
+ {
+ _empty = false;
+ }
+
+ template <class T>
+ inline void extendToContain(const T& p)
+ {
+ if (_empty) {
+ _min = p;
+ _max = p;
+ _empty = false;
+ return;
+ }
+ for (unsigned int i = 0; i < Point::dim(); i++) {
+ if (p[i] < _min[i])
+ _min[i] = p[i];
+ else if (p[i] > _max[i])
+ _max[i] = p[i];
+ }
+ _empty = false;
+ }
+
+ inline void clear()
+ {
+ _empty = true;
+ }
+
+ inline bool empty() const
+ {
+ return _empty;
+ }
+
+ inline const Point& getMin() const
+ {
+ return _min;
+ }
+
+ inline const Point& getMax() const
+ {
+ return _max;
+ }
+
+ inline BBox<Point>& operator=(const BBox<Point>& b)
+ {
+ _min = b.getMin();
+ _max = b.getMax();
+ _empty = false;
+ return *this;
+ }
+
+ inline BBox<Point>& operator+=(const BBox<Point>& b)
+ {
+ if (_empty) {
+ _min = b.getMin();
+ _max = b.getMax();
+ _empty = false;
+ }
+ else {
+ for (unsigned int i = 0; i < Point::dim(); i++) {
+ if (b.getMin()[i] < _min[i])
+ _min[i] = b.getMin()[i];
+ if (b.getMax()[i] > _max[i])
+ _max[i] = b.getMax()[i];
+ }
+ }
+ return *this;
+ }
+
+ inline bool inside(const Point& p)
+ {
+ if (empty())
+ return false;
+ for (unsigned int i = 0; i < Point::dim(); i++) {
+ if ((_min[i]>p[i]) || (_max[i]<p[i]))
+ return false;
+ }
+ return true;
+ }
+
+private:
+ Point _min;
+ Point _max;
+ bool _empty;
+};
+
+template <class Point>
+BBox<Point>& operator+(const BBox<Point> &b1, const BBox<Point> &b2)
+{
+ Point new_min;
+ Point new_max;
+
+ for (unsigned int i = 0; i < Point::dim(); i++) {
+ new_min[i] = b1.getMin()[i] < b2.getMin()[i] ? b1.getMin()[i] : b2.getMin()[i];
+ new_max[i] = b1.getMax()[i] > b2.getMax()[i] ? b1.getMax()[i] : b2.getMax()[i];
+ }
+
+ return BBox<Point>(new_min, new_max);
+}
+
+#endif // __BBOX_H__
diff --git a/source/blender/freestyle/intern/geometry/Bezier.cpp b/source/blender/freestyle/intern/geometry/Bezier.cpp
new file mode 100644
index 00000000000..b332553f0b4
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Bezier.cpp
@@ -0,0 +1,127 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/geometry/Bezier.cpp
+ * \ingroup freestyle
+ * \brief Class to define a Bezier curve of order 4.
+ * \author Stephane Grabli
+ * \date 04/06/2003
+ */
+
+#include "Bezier.h"
+#include "FitCurve.h"
+
+using namespace std;
+
+BezierCurveSegment::BezierCurveSegment()
+{
+}
+
+BezierCurveSegment::~BezierCurveSegment()
+{
+}
+
+void BezierCurveSegment::AddControlPoint(const Vec2d& iPoint)
+{
+ _ControlPolygon.push_back(iPoint);
+ if (_ControlPolygon.size() == 4)
+ Build();
+}
+
+void BezierCurveSegment::Build()
+{
+ if (_ControlPolygon.size() != 4)
+ return;
+
+ // Compute the rightmost part of the matrix:
+ vector<Vec2d>::const_iterator p0, p1, p2, p3;
+ p0 = _ControlPolygon.begin();
+ p1 = p0;
+ ++p1;
+ p2 = p1;
+ ++p2;
+ p3 = p2;
+ ++p3;
+ float x[4], y[4];
+
+ x[0] = -p0->x() + 3 * p1->x() - 3 * p2->x() + p3->x();
+ x[1] = 3 * p0->x() - 6 * p1->x() + 3 * p2->x();
+ x[2] = -3 * p0->x() + 3 * p1->x();
+ x[3] = p0->x();
+
+ y[0] = -p0->y() + 3 * p1->y() - 3 * p2->y() + p3->y();
+ y[1] = 3 * p0->y() - 6 * p1->y() + 3 * p2->y();
+ y[2] = -3 * p0->y() + 3 * p1->y();
+ y[3] = p0->y();
+
+ int nvertices = 12;
+ float increment = 1.0 / (float)nvertices;
+ float t = 0.0f;
+ for (int i = 0; i <= nvertices; ++i) {
+ _Vertices.push_back(Vec2d((x[3] + t * (x[2] + t * (x[1] + t * x[0]))),
+ (y[3] + t * (y[2] + t * (y[1] + t * y[0])))));
+ t += increment;
+ }
+}
+
+BezierCurve::BezierCurve()
+{
+ _currentSegment = new BezierCurveSegment;
+}
+
+BezierCurve::BezierCurve(vector<Vec2d>& iPoints, double error)
+{
+ FitCurveWrapper fitcurve;
+ _currentSegment = new BezierCurveSegment;
+ vector<Vec2d> curve;
+
+ fitcurve.FitCurve(iPoints, curve, error);
+ int i = 0;
+ vector<Vec2d>::iterator v, vend;
+ for (v = curve.begin(), vend = curve.end(); v != vend; ++v) {
+ if ((i == 0) || (i % 4 != 0))
+ AddControlPoint(*v);
+ ++i;
+ }
+}
+
+BezierCurve::~BezierCurve()
+{
+ if (_currentSegment)
+ delete _currentSegment;
+}
+
+void BezierCurve::AddControlPoint(const Vec2d& iPoint)
+{
+ _ControlPolygon.push_back(iPoint);
+ _currentSegment->AddControlPoint(iPoint);
+ if (_currentSegment->size() == 4) {
+ _Segments.push_back(_currentSegment);
+ _currentSegment = new BezierCurveSegment;
+ _currentSegment->AddControlPoint(iPoint);
+ }
+}
diff --git a/source/blender/freestyle/intern/geometry/Bezier.h b/source/blender/freestyle/intern/geometry/Bezier.h
new file mode 100644
index 00000000000..51f32e9e0b3
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Bezier.h
@@ -0,0 +1,96 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BEZIER_H__
+#define __BEZIER_H__
+
+/** \file blender/freestyle/intern/geometry/Bezier.h
+ * \ingroup freestyle
+ * \brief Class to define a Bezier curve of order 4.
+ * \author Stephane Grabli
+ * \date 04/06/2003
+ */
+
+#include <vector>
+
+#include "Geom.h"
+
+#include "../system/FreestyleConfig.h"
+
+using namespace Geometry;
+
+class LIB_GEOMETRY_EXPORT BezierCurveSegment
+{
+private:
+ std::vector<Vec2d> _ControlPolygon;
+ std::vector<Vec2d> _Vertices;
+
+public:
+ BezierCurveSegment();
+ virtual ~BezierCurveSegment();
+
+ void AddControlPoint(const Vec2d& iPoint);
+ void Build();
+
+ inline int size() const
+ {
+ return _ControlPolygon.size();
+ }
+
+ inline std::vector<Vec2d>& vertices()
+ {
+ return _Vertices;
+ }
+};
+
+
+class LIB_GEOMETRY_EXPORT BezierCurve
+{
+private:
+ std::vector<Vec2d> _ControlPolygon;
+ std::vector<BezierCurveSegment*> _Segments;
+ BezierCurveSegment *_currentSegment;
+
+public:
+ BezierCurve();
+ BezierCurve(std::vector<Vec2d>& iPoints, double error=4.0);
+ virtual ~BezierCurve();
+
+ void AddControlPoint(const Vec2d& iPoint);
+
+ std::vector<Vec2d>& controlPolygon()
+ {
+ return _ControlPolygon;
+ }
+
+ std::vector<BezierCurveSegment*>& segments()
+ {
+ return _Segments;
+ }
+};
+
+#endif // __BEZIER_H__
diff --git a/source/blender/freestyle/intern/geometry/FastGrid.cpp b/source/blender/freestyle/intern/geometry/FastGrid.cpp
new file mode 100644
index 00000000000..37871eadcec
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/FastGrid.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/geometry/FastGrid.cpp
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the bounding box of the scene
+ * \author Stephane Grabli
+ * \date 30/07/2002
+ */
+
+#include "FastGrid.h"
+
+#include "BKE_global.h"
+
+void FastGrid::clear()
+{
+ if (!_cells)
+ return;
+
+ for (unsigned int i = 0; i < _cells_size; i++) {
+ if (_cells[i])
+ delete _cells[i];
+ }
+ delete[] _cells;
+ _cells = NULL;
+ _cells_size = 0;
+
+ Grid::clear();
+}
+
+void FastGrid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb)
+{
+ Grid::configure(orig, size, nb);
+ _cells_size = _cells_nb[0] * _cells_nb[1] * _cells_nb[2];
+ _cells = new Cell *[_cells_size];
+ memset(_cells, 0, _cells_size * sizeof(*_cells));
+}
+
+Cell *FastGrid::getCell(const Vec3u& p)
+{
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << _cells << " " << p << " " << _cells_nb[0] << "-" << _cells_nb[1] << "-" << _cells_nb[2]
+ << " " << _cells_size << endl;
+ }
+#endif
+ assert(_cells || ("_cells is a null pointer"));
+ assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]) < _cells_size);
+ assert(p[0] < _cells_nb[0]);
+ assert(p[1] < _cells_nb[1]);
+ assert(p[2] < _cells_nb[2]);
+ return _cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]];
+}
+
+void FastGrid::fillCell(const Vec3u& p, Cell& cell)
+{
+ assert(_cells || ("_cells is a null pointer"));
+ assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]) < _cells_size);
+ assert(p[0] < _cells_nb[0]);
+ assert(p[1] < _cells_nb[1]);
+ assert(p[2] < _cells_nb[2]);
+ _cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]] = &cell;
+}
diff --git a/source/blender/freestyle/intern/geometry/FastGrid.h b/source/blender/freestyle/intern/geometry/FastGrid.h
new file mode 100644
index 00000000000..cf5f911497a
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/FastGrid.h
@@ -0,0 +1,86 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FASTGRID_H__
+#define __FASTGRID_H__
+
+/** \file blender/freestyle/intern/geometry/FastGrid.h
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the bounding box of the scene
+ * \author Stephane Grabli
+ * \date 30/07/2002
+ */
+
+#include <cassert>
+
+#include "Grid.h"
+
+/*! Class to define a regular grid used for ray casting computations
+ * We don't use a hashtable here. The grid is explicitly stored for faster computations.
+ * However, this might result in significant increase in memory usage (compared to the regular grid)
+ */
+class LIB_GEOMETRY_EXPORT FastGrid : public Grid
+{
+public:
+ FastGrid() : Grid()
+ {
+ _cells = NULL;
+ _cells_size = 0;
+ }
+
+ virtual ~FastGrid()
+ {
+ clear();
+ }
+
+ /*! clears the grid
+ * Deletes all the cells, clears the hashtable, resets size, size of cell, number of cells.
+ */
+ virtual void clear();
+
+ /*! Sets the different parameters of the grid
+ * orig
+ * The grid origin
+ * size
+ * The grid's dimensions
+ * nb
+ * The number of cells of the grid
+ */
+ virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
+
+ /*! returns the cell whose coordinates are pased as argument */
+ Cell *getCell(const Vec3u& p);
+
+ /*! Fills the case p with the cell iCell */
+ virtual void fillCell(const Vec3u& p, Cell& cell);
+
+protected:
+ Cell **_cells;
+ unsigned _cells_size;
+};
+
+#endif // __FASTGRID_H__
diff --git a/source/blender/freestyle/intern/geometry/FitCurve.cpp b/source/blender/freestyle/intern/geometry/FitCurve.cpp
new file mode 100644
index 00000000000..73816cc687f
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/FitCurve.cpp
@@ -0,0 +1,600 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/geometry/FitCurve.cpp
+ * \ingroup freestyle
+ * \brief An Algorithm for Automatically Fitting Digitized Curves by Philip J. Schneider,
+ * \brief from "Graphics Gems", Academic Press, 1990
+ * \author Stephane Grabli
+ * \date 06/06/2003
+ */
+
+#include <cstdlib> // for malloc and free
+#include <stdio.h>
+#include <math.h>
+
+#include "FitCurve.h"
+
+using namespace std;
+
+typedef Vector2 *BezierCurve;
+
+// XXX Do we need "#ifdef __cplusplus" at all here???
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Forward declarations */
+static double *Reparameterize(Vector2 *d, int first, int last, double *u, BezierCurve bezCurve);
+static double NewtonRaphsonRootFind(BezierCurve Q, Vector2 P, double u);
+static Vector2 BezierII(int degree, Vector2 *V, double t);
+static double B0(double u);
+static double B1(double u);
+static double B2(double u);
+static double B3(double u);
+static Vector2 ComputeLeftTangent(Vector2 *d, int end);
+static double ComputeMaxError(Vector2 *d, int first, int last, BezierCurve bezCurve, double *u, int *splitPoint);
+static double *ChordLengthParameterize(Vector2 *d, int first, int last);
+static BezierCurve GenerateBezier(Vector2 *d, int first, int last, double *uPrime, Vector2 tHat1, Vector2 tHat2);
+static Vector2 V2AddII(Vector2 a, Vector2 b);
+static Vector2 V2ScaleIII(Vector2 v, double s);
+static Vector2 V2SubII(Vector2 a, Vector2 b);
+
+#define MAXPOINTS 1000 /* The most points you can have */
+
+/* returns squared length of input vector */
+static double V2SquaredLength(Vector2 *a)
+{
+ return (((*a)[0] * (*a)[0]) + ((*a)[1] * (*a)[1]));
+}
+
+/* returns length of input vector */
+static double V2Length(Vector2 *a)
+{
+ return (sqrt(V2SquaredLength(a)));
+}
+
+static Vector2 *V2Scale(Vector2 *v, double newlen)
+{
+ double len = V2Length(v);
+ if (len != 0.0) {
+ (*v)[0] *= newlen / len;
+ (*v)[1] *= newlen / len;
+ }
+ return v;
+}
+
+/* return the dot product of vectors a and b */
+static double V2Dot(Vector2 *a, Vector2 *b)
+{
+ return (((*a)[0] * (*b)[0]) + ((*a)[1] * (*b)[1]));
+}
+
+/* return the distance between two points */
+static double V2DistanceBetween2Points(Vector2 *a, Vector2 *b)
+{
+ double dx = (*a)[0] - (*b)[0];
+ double dy = (*a)[1] - (*b)[1];
+ return (sqrt((dx * dx) + (dy * dy)));
+}
+
+/* return vector sum c = a+b */
+static Vector2 *V2Add(Vector2 *a, Vector2 *b, Vector2 *c)
+{
+ (*c)[0] = (*a)[0] + (*b)[0];
+ (*c)[1] = (*a)[1] + (*b)[1];
+ return c;
+}
+
+/* normalizes the input vector and returns it */
+static Vector2 *V2Normalize(Vector2 *v)
+{
+ double len = V2Length(v);
+ if (len != 0.0) {
+ (*v)[0] /= len;
+ (*v)[1] /= len;
+ }
+ return v;
+}
+
+/* negates the input vector and returns it */
+static Vector2 *V2Negate(Vector2 *v)
+{
+ (*v)[0] = -(*v)[0];
+ (*v)[1] = -(*v)[1];
+ return v;
+}
+
+/* GenerateBezier:
+ * Use least-squares method to find Bezier control points for region.
+ * Vector2 *d; Array of digitized points
+ * int first, last; Indices defining region
+ * double *uPrime; Parameter values for region
+ * Vector2 tHat1, tHat2; Unit tangents at endpoints
+ */
+static BezierCurve GenerateBezier(Vector2 *d, int first, int last, double *uPrime, Vector2 tHat1, Vector2 tHat2)
+{
+ int i;
+ Vector2 A[MAXPOINTS][2]; /* Precomputed rhs for eqn */
+ int nPts; /* Number of pts in sub-curve */
+ double C[2][2]; /* Matrix C */
+ double X[2]; /* Matrix X */
+ double det_C0_C1; /* Determinants of matrices */
+ double det_C0_X;
+ double det_X_C1;
+ double alpha_l; /* Alpha values, left and right */
+ double alpha_r;
+ Vector2 tmp; /* Utility variable */
+ BezierCurve bezCurve; /* RETURN bezier curve ctl pts */
+
+ bezCurve = (Vector2 *)malloc(4 * sizeof(Vector2));
+ nPts = last - first + 1;
+
+ /* Compute the A's */
+ for (i = 0; i < nPts; i++) {
+ Vector2 v1, v2;
+ v1 = tHat1;
+ v2 = tHat2;
+ V2Scale(&v1, B1(uPrime[i]));
+ V2Scale(&v2, B2(uPrime[i]));
+ A[i][0] = v1;
+ A[i][1] = v2;
+ }
+
+ /* Create the C and X matrices */
+ C[0][0] = 0.0;
+ C[0][1] = 0.0;
+ C[1][0] = 0.0;
+ C[1][1] = 0.0;
+ X[0] = 0.0;
+ X[1] = 0.0;
+ for (i = 0; i < nPts; i++) {
+ C[0][0] += V2Dot(&A[i][0], &A[i][0]);
+ C[0][1] += V2Dot(&A[i][0], &A[i][1]);
+// C[1][0] += V2Dot(&A[i][0], &A[i][1]);
+ C[1][0] = C[0][1];
+ C[1][1] += V2Dot(&A[i][1], &A[i][1]);
+
+ tmp = V2SubII(d[first + i],
+ V2AddII(V2ScaleIII(d[first], B0(uPrime[i])),
+ V2AddII(V2ScaleIII(d[first], B1(uPrime[i])),
+ V2AddII(V2ScaleIII(d[last], B2(uPrime[i])),
+ V2ScaleIII(d[last], B3(uPrime[i]))
+ )
+ )
+ )
+ );
+
+ X[0] += V2Dot(&((A[i])[0]), &tmp);
+ X[1] += V2Dot(&((A[i])[1]), &tmp);
+ }
+
+ /* Compute the determinants of C and X */
+ det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1];
+ det_C0_X = C[0][0] * X[1] - C[0][1] * X[0];
+ det_X_C1 = X[0] * C[1][1] - X[1] * C[0][1];
+
+ /* Finally, derive alpha values */
+ if (det_C0_C1 == 0.0) {
+ det_C0_C1 = (C[0][0] * C[1][1]) * 10.0e-12;
+ }
+ alpha_l = det_X_C1 / det_C0_C1;
+ alpha_r = det_C0_X / det_C0_C1;
+
+
+ /* If alpha negative, use the Wu/Barsky heuristic (see text) (if alpha is 0, you get coincident control points
+ * that lead to divide by zero in any subsequent NewtonRaphsonRootFind() call).
+ */
+ if (alpha_l < 1.0e-6 || alpha_r < 1.0e-6) {
+ double dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0;
+
+ bezCurve[0] = d[first];
+ bezCurve[3] = d[last];
+ V2Add(&(bezCurve[0]), V2Scale(&(tHat1), dist), &(bezCurve[1]));
+ V2Add(&(bezCurve[3]), V2Scale(&(tHat2), dist), &(bezCurve[2]));
+ return bezCurve;
+ }
+
+ /* First and last control points of the Bezier curve are positioned exactly at the first and last data points
+ * Control points 1 and 2 are positioned an alpha distance out on the tangent vectors, left and right, respectively
+ */
+ bezCurve[0] = d[first];
+ bezCurve[3] = d[last];
+ V2Add(&bezCurve[0], V2Scale(&tHat1, alpha_l), &bezCurve[1]);
+ V2Add(&bezCurve[3], V2Scale(&tHat2, alpha_r), &bezCurve[2]);
+ return (bezCurve);
+}
+
+/*
+ * Reparameterize:
+ * Given set of points and their parameterization, try to find a better parameterization.
+ * Vector2 *d; Array of digitized points
+ * int first, last; Indices defining region
+ * double *u; Current parameter values
+ * BezierCurve bezCurve; Current fitted curve
+ */
+static double *Reparameterize(Vector2 *d, int first, int last, double *u, BezierCurve bezCurve)
+{
+ int nPts = last - first + 1;
+ int i;
+ double *uPrime; /* New parameter values */
+
+ uPrime = (double *)malloc(nPts * sizeof(double));
+ for (i = first; i <= last; i++) {
+ uPrime[i - first] = NewtonRaphsonRootFind(bezCurve, d[i], u[i - first]);
+ }
+ return (uPrime);
+}
+
+/*
+ * NewtonRaphsonRootFind:
+ * Use Newton-Raphson iteration to find better root.
+ * BezierCurve Q; Current fitted curve
+ * Vector2 P; Digitized point
+ * double u; Parameter value for "P"
+ */
+static double NewtonRaphsonRootFind(BezierCurve Q, Vector2 P, double u)
+{
+ double numerator, denominator;
+ Vector2 Q1[3], Q2[2]; /* Q' and Q'' */
+ Vector2 Q_u, Q1_u, Q2_u; /* u evaluated at Q, Q', & Q'' */
+ double uPrime; /* Improved u */
+ int i;
+
+ /* Compute Q(u) */
+ Q_u = BezierII(3, Q, u);
+
+ /* Generate control vertices for Q' */
+ for (i = 0; i <= 2; i++) {
+ Q1[i][0] = (Q[i + 1][0] - Q[i][0]) * 3.0;
+ Q1[i][1] = (Q[i + 1][1] - Q[i][1]) * 3.0;
+ }
+
+ /* Generate control vertices for Q'' */
+ for (i = 0; i <= 1; i++) {
+ Q2[i][0] = (Q1[i + 1][0] - Q1[i][0]) * 2.0;
+ Q2[i][1] = (Q1[i + 1][1] - Q1[i][1]) * 2.0;
+ }
+
+ /* Compute Q'(u) and Q''(u) */
+ Q1_u = BezierII(2, Q1, u);
+ Q2_u = BezierII(1, Q2, u);
+
+ /* Compute f(u)/f'(u) */
+ numerator = (Q_u[0] - P[0]) * (Q1_u[0]) + (Q_u[1] - P[1]) * (Q1_u[1]);
+ denominator = (Q1_u[0]) * (Q1_u[0]) + (Q1_u[1]) * (Q1_u[1]) +
+ (Q_u[0] - P[0]) * (Q2_u[0]) + (Q_u[1] - P[1]) * (Q2_u[1]);
+
+ /* u = u - f(u)/f'(u) */
+ if (denominator == 0) // FIXME
+ return u;
+ uPrime = u - (numerator / denominator);
+ return uPrime;
+}
+
+/*
+ * Bezier:
+ * Evaluate a Bezier curve at a particular parameter value
+ * int degree; The degree of the bezier curve
+ * Vector2 *V; Array of control points
+ * double t; Parametric value to find point for
+ */
+static Vector2 BezierII(int degree, Vector2 *V, double t)
+{
+ int i, j;
+ Vector2 Q; /* Point on curve at parameter t */
+ Vector2 *Vtemp; /* Local copy of control points */
+
+ /* Copy array */
+ Vtemp = (Vector2 *)malloc((unsigned)((degree + 1) * sizeof(Vector2)));
+ for (i = 0; i <= degree; i++) {
+ Vtemp[i] = V[i];
+ }
+
+ /* Triangle computation */
+ for (i = 1; i <= degree; i++) {
+ for (j = 0; j <= degree - i; j++) {
+ Vtemp[j][0] = (1.0 - t) * Vtemp[j][0] + t * Vtemp[j + 1][0];
+ Vtemp[j][1] = (1.0 - t) * Vtemp[j][1] + t * Vtemp[j + 1][1];
+ }
+ }
+
+ Q = Vtemp[0];
+ free((void *)Vtemp);
+ return Q;
+}
+
+/*
+ * B0, B1, B2, B3:
+ * Bezier multipliers
+ */
+static double B0(double u)
+{
+ double tmp = 1.0 - u;
+ return (tmp * tmp * tmp);
+}
+
+
+static double B1(double u)
+{
+ double tmp = 1.0 - u;
+ return (3 * u * (tmp * tmp));
+}
+
+static double B2(double u)
+{
+ double tmp = 1.0 - u;
+ return (3 * u * u * tmp);
+}
+
+static double B3(double u)
+{
+ return (u * u * u);
+}
+
+/*
+ * ComputeLeftTangent, ComputeRightTangent, ComputeCenterTangent:
+ * Approximate unit tangents at endpoints and "center" of digitized curve
+ */
+/* Vector2 *d; Digitized points
+ * int end; Index to "left" end of region
+ */
+static Vector2 ComputeLeftTangent(Vector2 *d, int end)
+{
+ Vector2 tHat1;
+ tHat1 = V2SubII(d[end + 1], d[end]);
+ tHat1 = *V2Normalize(&tHat1);
+ return tHat1;
+}
+
+/* Vector2 *d; Digitized points
+ * int end; Index to "right" end of region
+ */
+static Vector2 ComputeRightTangent(Vector2 *d, int end)
+{
+ Vector2 tHat2;
+ tHat2 = V2SubII(d[end - 1], d[end]);
+ tHat2 = *V2Normalize(&tHat2);
+ return tHat2;
+}
+
+/* Vector2 *d; Digitized points
+ * int end; Index to point inside region
+ */
+static Vector2 ComputeCenterTangent(Vector2 *d, int center)
+{
+ Vector2 V1, V2, tHatCenter;
+
+ V1 = V2SubII(d[center - 1], d[center]);
+ V2 = V2SubII(d[center], d[center + 1]);
+ tHatCenter[0] = (V1[0] + V2[0]) / 2.0;
+ tHatCenter[1] = (V1[1] + V2[1]) / 2.0;
+ tHatCenter = *V2Normalize(&tHatCenter);
+ return tHatCenter;
+}
+
+/*
+ * ChordLengthParameterize:
+ * Assign parameter values to digitized points using relative distances between points.
+ * Vector2 *d; Array of digitized points
+ * int first, last; Indices defining region
+ */
+static double *ChordLengthParameterize(Vector2 *d, int first, int last)
+{
+ int i;
+ double *u; /* Parameterization */
+
+ u = (double *)malloc((unsigned)(last - first + 1) * sizeof(double));
+
+ u[0] = 0.0;
+ for (i = first + 1; i <= last; i++) {
+ u[i - first] = u[i - first - 1] + V2DistanceBetween2Points(&d[i], &d[i - 1]);
+ }
+
+ for (i = first + 1; i <= last; i++) {
+ u[i - first] = u[i - first] / u[last - first];
+ }
+
+ return u;
+}
+
+
+
+
+/*
+ * ComputeMaxError :
+ * Find the maximum squared distance of digitized points to fitted curve.
+ * Vector2 *d; Array of digitized points
+ * int first, last; Indices defining region
+ * BezierCurve bezCurve; Fitted Bezier curve
+ * double *u; Parameterization of points
+ * int *splitPoint; Point of maximum error
+ */
+static double ComputeMaxError(Vector2 *d, int first, int last, BezierCurve bezCurve, double *u, int *splitPoint)
+{
+ int i;
+ double maxDist; /* Maximum error */
+ double dist; /* Current error */
+ Vector2 P; /* Point on curve */
+ Vector2 v; /* Vector from point to curve */
+
+ *splitPoint = (last - first + 1) / 2;
+ maxDist = 0.0;
+ for (i = first + 1; i < last; i++) {
+ P = BezierII(3, bezCurve, u[i - first]);
+ v = V2SubII(P, d[i]);
+ dist = V2SquaredLength(&v);
+ if (dist >= maxDist) {
+ maxDist = dist;
+ *splitPoint = i;
+ }
+ }
+ return maxDist;
+}
+
+static Vector2 V2AddII(Vector2 a, Vector2 b)
+{
+ Vector2 c;
+ c[0] = a[0] + b[0];
+ c[1] = a[1] + b[1];
+ return c;
+}
+
+static Vector2 V2ScaleIII(Vector2 v, double s)
+{
+ Vector2 result;
+ result[0] = v[0] * s;
+ result[1] = v[1] * s;
+ return result;
+}
+
+static Vector2 V2SubII(Vector2 a, Vector2 b)
+{
+ Vector2 c;
+ c[0] = a[0] - b[0];
+ c[1] = a[1] - b[1];
+ return c;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+
+//------------------------- WRAPPER -----------------------------//
+
+FitCurveWrapper::FitCurveWrapper()
+{
+}
+
+FitCurveWrapper::~FitCurveWrapper()
+{
+ _vertices.clear();
+}
+
+void FitCurveWrapper::DrawBezierCurve(int n, Vector2 *curve)
+{
+ for (int i = 0; i < n + 1; ++i)
+ _vertices.push_back(curve[i]);
+}
+
+void FitCurveWrapper::FitCurve(vector<Vec2d>& data, vector<Vec2d>& oCurve, double error)
+{
+ int size = data.size();
+ Vector2 *d = new Vector2[size];
+ for (int i = 0; i < size; ++i) {
+ d[i][0] = data[i][0];
+ d[i][1] = data[i][1];
+ }
+
+ FitCurve(d, size, error);
+
+ // copy results
+ for (vector<Vector2>::iterator v = _vertices.begin(), vend = _vertices.end(); v != vend; ++v) {
+ oCurve.push_back(Vec2d(v->x(), v->y())) ;
+ }
+}
+
+void FitCurveWrapper::FitCurve(Vector2 *d, int nPts, double error)
+{
+ Vector2 tHat1, tHat2; /* Unit tangent vectors at endpoints */
+
+ tHat1 = ComputeLeftTangent(d, 0);
+ tHat2 = ComputeRightTangent(d, nPts - 1);
+ FitCubic(d, 0, nPts - 1, tHat1, tHat2, error);
+}
+
+void FitCurveWrapper::FitCubic(Vector2 *d, int first, int last, Vector2 tHat1, Vector2 tHat2, double error)
+{
+ BezierCurve bezCurve; /* Control points of fitted Bezier curve */
+ double *u; /* Parameter values for point */
+ double *uPrime; /* Improved parameter values */
+ double maxError; /* Maximum fitting error */
+ int splitPoint; /* Point to split point set at */
+ int nPts; /* Number of points in subset */
+ double iterationError; /* Error below which you try iterating */
+ int maxIterations = 4; /* Max times to try iterating */
+ Vector2 tHatCenter; /* Unit tangent vector at splitPoint */
+ int i;
+
+ iterationError = error * error;
+ nPts = last - first + 1;
+
+ /* Use heuristic if region only has two points in it */
+ if (nPts == 2) {
+ double dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0;
+
+ bezCurve = (Vector2 *)malloc(4 * sizeof(Vector2));
+ bezCurve[0] = d[first];
+ bezCurve[3] = d[last];
+ V2Add(&bezCurve[0], V2Scale(&tHat1, dist), &bezCurve[1]);
+ V2Add(&bezCurve[3], V2Scale(&tHat2, dist), &bezCurve[2]);
+ DrawBezierCurve(3, bezCurve);
+ free((void *)bezCurve);
+ return;
+ }
+
+ /* Parameterize points, and attempt to fit curve */
+ u = ChordLengthParameterize(d, first, last);
+ bezCurve = GenerateBezier(d, first, last, u, tHat1, tHat2);
+
+ /* Find max deviation of points to fitted curve */
+ maxError = ComputeMaxError(d, first, last, bezCurve, u, &splitPoint);
+ if (maxError < error) {
+ DrawBezierCurve(3, bezCurve);
+ free((void *)u);
+ free((void *)bezCurve);
+ return;
+ }
+
+ /* If error not too large, try some reparameterization and iteration */
+ if (maxError < iterationError) {
+ for (i = 0; i < maxIterations; i++) {
+ uPrime = Reparameterize(d, first, last, u, bezCurve);
+ bezCurve = GenerateBezier(d, first, last, uPrime, tHat1, tHat2);
+ maxError = ComputeMaxError(d, first, last,
+ bezCurve, uPrime, &splitPoint);
+ if (maxError < error) {
+ DrawBezierCurve(3, bezCurve);
+ free((void *)u);
+ free((void *)bezCurve);
+ return;
+ }
+ free((void *)u);
+ u = uPrime;
+ }
+ }
+
+ /* Fitting failed -- split at max error point and fit recursively */
+ free((void *)u);
+ free((void *)bezCurve);
+ tHatCenter = ComputeCenterTangent(d, splitPoint);
+ FitCubic(d, first, splitPoint, tHat1, tHatCenter, error);
+ V2Negate(&tHatCenter);
+ FitCubic(d, splitPoint, last, tHatCenter, tHat2, error);
+}
diff --git a/source/blender/freestyle/intern/geometry/FitCurve.h b/source/blender/freestyle/intern/geometry/FitCurve.h
new file mode 100644
index 00000000000..0a80c2f28f9
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/FitCurve.h
@@ -0,0 +1,125 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FITCURVE_H__
+#define __FITCURVE_H__
+
+/** \file blender/freestyle/intern/geometry/FitCurve.h
+ * \ingroup freestyle
+ * \brief An Algorithm for Automatically Fitting Digitized Curves by Philip J. Schneider,
+ * \brief from "Graphics Gems", Academic Press, 1990
+ * \author Stephane Grabli
+ * \date 06/06/2003
+ */
+
+#include <vector>
+
+#include "Geom.h"
+
+#include "../system/FreestyleConfig.h"
+
+using namespace Geometry;
+
+/* 2d point */
+typedef struct Point2Struct
+{
+ double coordinates[2];
+
+ Point2Struct()
+ {
+ coordinates[0] = 0;
+ coordinates[1] = 0;
+ }
+
+ inline double operator[](const int i) const
+ {
+ return coordinates[i];
+ }
+
+ inline double& operator[](const int i)
+ {
+ return coordinates[i];
+ }
+
+ inline double x() const
+ {
+ return coordinates[0];
+ }
+
+ inline double y() const
+ {
+ return coordinates[1];
+ }
+} Point2;
+
+typedef Point2 Vector2;
+
+
+class LIB_GEOMETRY_EXPORT FitCurveWrapper
+{
+private:
+ std::vector<Vector2> _vertices;
+
+public:
+ FitCurveWrapper();
+ ~FitCurveWrapper();
+
+ /*! Fits a set of 2D data points to a set of Bezier Curve segments
+ * data
+ * Input data points
+ * oCurve
+ * Control points of the sets of bezier curve segments.
+ * Each segment is made of 4 points (polynomial degree of curve = 3)
+ * error
+ * max error tolerance between resulting curve and input data
+ */
+ void FitCurve(std::vector<Vec2d>& data, std::vector<Vec2d>& oCurve, double error);
+
+protected:
+ /* Vec2d *d; Array of digitized points
+ * int nPts; Number of digitized points
+ * double error; User-defined error squared
+ */
+ void FitCurve(Vector2 *d, int nPts, double error);
+
+ /*! Draws a Bezier curve segment
+ * n
+ * degree of curve (=3)
+ * curve
+ * bezier segments control points
+ */
+ void DrawBezierCurve(int n, Vector2 *curve);
+
+ /* Vec2d *d; Array of digitized points
+ * int first, last; Indices of first and last pts in region
+ * Vec2d tHat1, tHat2; Unit tangent vectors at endpoints
+ * double error; User-defined error squared
+ */
+ void FitCubic(Vector2 *d, int first, int last, Vector2 tHat1, Vector2 tHat2, double error);
+};
+
+#endif // __FITCURVE_H__
diff --git a/source/blender/freestyle/intern/geometry/Geom.h b/source/blender/freestyle/intern/geometry/Geom.h
new file mode 100644
index 00000000000..f241346ec85
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Geom.h
@@ -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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __GEOM_H__
+#define __GEOM_H__
+
+/** \file blender/freestyle/intern/geometry/Geom.h
+ * \ingroup freestyle
+ * \brief Vectors and Matrices (useful type definitions)
+ * \author Sylvain Paris
+ * \author Emmanuel Turquin
+ * \author Stephane Grabli
+ * \date 20/05/2003
+ */
+
+#include "VecMat.h"
+
+#include "../system/Precision.h"
+
+namespace Geometry {
+
+typedef VecMat::Vec2<unsigned> Vec2u;
+typedef VecMat::Vec2<int> Vec2i;
+typedef VecMat::Vec2<float> Vec2f;
+typedef VecMat::Vec2<double> Vec2d;
+typedef VecMat::Vec2<real> Vec2r;
+
+typedef VecMat::Vec3<unsigned> Vec3u;
+typedef VecMat::Vec3<int> Vec3i;
+typedef VecMat::Vec3<float> Vec3f;
+typedef VecMat::Vec3<double> Vec3d;
+typedef VecMat::Vec3<real> Vec3r;
+
+typedef VecMat::HVec3<unsigned> HVec3u;
+typedef VecMat::HVec3<int> HVec3i;
+typedef VecMat::HVec3<float> HVec3f;
+typedef VecMat::HVec3<double> HVec3d;
+typedef VecMat::HVec3<real> HVec3r;
+
+typedef VecMat::SquareMatrix<unsigned, 2> Matrix22u;
+typedef VecMat::SquareMatrix<int, 2> Matrix22i;
+typedef VecMat::SquareMatrix<float, 2> Matrix22f;
+typedef VecMat::SquareMatrix<double, 2> Matrix22d;
+typedef VecMat::SquareMatrix<real, 2> Matrix22r;
+
+typedef VecMat::SquareMatrix<unsigned, 3> Matrix33u;
+typedef VecMat::SquareMatrix<int, 3> Matrix33i;
+typedef VecMat::SquareMatrix<float, 3> Matrix33f;
+typedef VecMat::SquareMatrix<double, 3> Matrix33d;
+typedef VecMat::SquareMatrix<real, 3> Matrix33r;
+
+typedef VecMat::SquareMatrix<unsigned, 4> Matrix44u;
+typedef VecMat::SquareMatrix<int, 4> Matrix44i;
+typedef VecMat::SquareMatrix<float, 4> Matrix44f;
+typedef VecMat::SquareMatrix<double, 4> Matrix44d;
+typedef VecMat::SquareMatrix<real, 4> Matrix44r;
+
+} // end of namespace Geometry
+
+#endif // __GEOM_H__
diff --git a/source/blender/freestyle/intern/geometry/GeomCleaner.cpp b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp
new file mode 100644
index 00000000000..dc9618a1a45
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp
@@ -0,0 +1,240 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/geometry/GeomCleaner.cpp
+ * \ingroup freestyle
+ * \brief Class to define a cleaner of geometry providing a set of useful tools
+ * \author Stephane Grabli
+ * \date 04/03/2002
+ */
+
+#if 0
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+// hash_map is not part of the C++ standard anymore;
+// hash_map.h has been kept though for backward compatibility
+# include <hash_map.h>
+#else
+# include <hash_map>
+#endif
+#endif
+
+#include <stdio.h>
+#include <list>
+#include <map>
+
+#include "GeomCleaner.h"
+
+#include "../system/TimeUtils.h"
+
+#include "BKE_global.h"
+
+using namespace std;
+
+
+void GeomCleaner::SortIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
+ unsigned iISize, real **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));
+ }
+
+ // q-sort
+ indexedVertices.sort();
+
+ // build the indices mapping array:
+ unsigned *mapIndices = new unsigned[iVSize / 3];
+ *oVertices = new real[iVSize];
+ list<IndexedVertex>::iterator iv;
+ unsigned newIndex = 0;
+ unsigned vIndex = 0;
+ for (iv = indexedVertices.begin(); iv != indexedVertices.end(); iv++) {
+ // Build the final results:
+ (*oVertices)[vIndex] = iv->x();
+ (*oVertices)[vIndex + 1] = iv->y();
+ (*oVertices)[vIndex + 2] = iv->z();
+
+ mapIndices[iv->index()] = newIndex;
+ newIndex++;
+ vIndex += 3;
+ }
+
+ // Build the final index array:
+ *oIndices = new unsigned[iISize];
+ for (i = 0; i < iISize; i++) {
+ (*oIndices)[i] = 3 * mapIndices[iIndices[i] / 3];
+ }
+
+ delete [] mapIndices;
+}
+
+void GeomCleaner::CompressIndexedVertexArray(const real *iVertices, unsigned iVSize, const unsigned *iIndices,
+ unsigned iISize, real **oVertices, unsigned *oVSize, unsigned **oIndices)
+{
+ // First, we build a list of IndexVertex:
+ vector<Vec3r> vertices;
+ unsigned i;
+ for (i = 0; i < iVSize; i += 3) {
+ vertices.push_back(Vec3r(iVertices[i], iVertices[i + 1], iVertices[i + 2]));
+ }
+
+ unsigned *mapVertex = new unsigned[iVSize];
+ vector<Vec3r>::iterator v = vertices.begin();
+
+ vector<Vec3r> compressedVertices;
+ Vec3r previous = *v;
+ mapVertex[0] = 0;
+ compressedVertices.push_back(vertices.front());
+
+ v++;
+ Vec3r current;
+ i = 1;
+ for (; v != vertices.end(); v++) {
+ current = *v;
+ if (current == previous)
+ mapVertex[i] = compressedVertices.size() - 1;
+ else {
+ compressedVertices.push_back(current);
+ mapVertex[i] = compressedVertices.size() - 1;
+ }
+ previous = current;
+ i++;
+ }
+
+ // Builds the resulting vertex array:
+ *oVSize = 3 * compressedVertices.size();
+ *oVertices = new real[*oVSize];
+ i = 0;
+ for (v = compressedVertices.begin(); v != compressedVertices.end(); v++) {
+ (*oVertices)[i] = (*v)[0];
+ (*oVertices)[i + 1] = (*v)[1];
+ (*oVertices)[i + 2] = (*v)[2];
+ i += 3;
+ }
+
+ // Map the index array:
+ *oIndices = new unsigned[iISize];
+ for (i = 0; i < iISize; i++) {
+ (*oIndices)[i] = 3 * mapVertex[iIndices[i] / 3];
+ }
+
+ delete [] mapVertex;
+}
+
+void GeomCleaner::SortAndCompressIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
+ unsigned iISize, real **oVertices, unsigned *oVSize,
+ unsigned **oIndices)
+{
+ // tmp arrays used to store the sorted data:
+ real *tmpVertices;
+ unsigned *tmpIndices;
+
+ Chronometer chrono;
+ // Sort data
+ chrono.start();
+ GeomCleaner::SortIndexedVertexArray(iVertices, iVSize, iIndices, iISize, &tmpVertices, &tmpIndices);
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("Sorting: %lf\n", chrono.stop());
+ }
+
+ // compress data
+ chrono.start();
+ GeomCleaner::CompressIndexedVertexArray(tmpVertices, iVSize, tmpIndices, iISize, oVertices, oVSize, oIndices);
+ real duration = chrono.stop();
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("Merging: %lf\n", duration);
+ }
+
+ // deallocates memory:
+ delete [] tmpVertices;
+ delete [] tmpIndices;
+}
+
+/*! Defines a hash table used for searching the Cells */
+struct GeomCleanerHasher {
+#define _MUL 950706376UL
+#define _MOD 2147483647UL
+ inline size_t operator() (const Vec3r& p) const
+ {
+ size_t res = ((unsigned long) (p[0] * _MUL)) % _MOD;
+ res = ((res + (unsigned long) (p[1]) * _MUL)) % _MOD;
+ return ((res +(unsigned long) (p[2]) * _MUL)) % _MOD;
+ }
+#undef _MUL
+#undef _MOD
+};
+
+void GeomCleaner::CleanIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
+ unsigned iISize, real **oVertices, unsigned *oVSize, unsigned **oIndices)
+{
+ typedef map<Vec3r, unsigned> cleanHashTable;
+ vector<Vec3r> vertices;
+ unsigned i;
+ for (i = 0; i < iVSize; i += 3)
+ vertices.push_back(Vec3r(iVertices[i], iVertices[i + 1], iVertices[i + 2]));
+
+ cleanHashTable ht;
+ vector<unsigned> newIndices;
+ vector<Vec3r> newVertices;
+
+ // elimination of needless points
+ unsigned currentIndex = 0;
+ vector<Vec3r>::const_iterator v = vertices.begin();
+ vector<Vec3r>::const_iterator end = vertices.end();
+ cleanHashTable::const_iterator found;
+ for (; v != end; v++) {
+ found = ht.find(*v);
+ if (found != ht.end()) {
+ // The vertex is already in the new array.
+ newIndices.push_back((*found).second);
+ }
+ else {
+ newVertices.push_back(*v);
+ newIndices.push_back(currentIndex);
+ ht[*v] = currentIndex;
+ currentIndex++;
+ }
+ }
+
+ // creation of oVertices array:
+ *oVSize = 3 * newVertices.size();
+ *oVertices = new real[*oVSize];
+ currentIndex = 0;
+ end = newVertices.end();
+ for (v = newVertices.begin(); v != end ; v++) {
+ (*oVertices)[currentIndex++] = (*v)[0];
+ (*oVertices)[currentIndex++] = (*v)[1];
+ (*oVertices)[currentIndex++] = (*v)[2];
+ }
+
+ // map new indices:
+ *oIndices = new unsigned[iISize];
+ for (i = 0; i < iISize; i++)
+ (*oIndices)[i] = 3 * newIndices[iIndices[i] / 3];
+}
diff --git a/source/blender/freestyle/intern/geometry/GeomCleaner.h b/source/blender/freestyle/intern/geometry/GeomCleaner.h
new file mode 100644
index 00000000000..334145f3bcd
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/GeomCleaner.h
@@ -0,0 +1,227 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __GEOMCLEANER_H__
+#define __GEOMCLEANER_H__
+
+/** \file blender/freestyle/intern/geometry/GeomCleaner.h
+ * \ingroup freestyle
+ * \brief Class to define a cleaner of geometry providing a set of useful tools
+ * \author Stephane Grabli
+ * \date 04/03/2002
+ */
+
+#include "Geom.h"
+
+#include "../system/FreestyleConfig.h"
+
+using namespace Geometry;
+
+class LIB_GEOMETRY_EXPORT GeomCleaner
+{
+public:
+ inline GeomCleaner() {}
+ inline ~GeomCleaner() {}
+
+ /*! Sorts an array of Indexed vertices
+ * iVertices
+ * Array of vertices to sort. It is organized as a float series of vertex coordinates: XYZXYZXYZ...
+ * iVSize
+ * The size of iVertices array.
+ * iIndices
+ * The array containing the vertex indices (used to refer to the vertex coordinates in an indexed face). Each
+ * element is an unsignedeger multiple of 3.
+ * iISize
+ * The size of iIndices array
+ * oVertices
+ * Output of sorted vertices. A vertex v1 precedes another one v2 in this array if v1.x<v2.x,
+ * or v1.x=v2.x && v1.y < v2.y or v1.x=v2.y && v1.y=v2.y && v1.z < v2.z.
+ * The array is organized as a 3-float serie giving the vertices coordinates: XYZXYZXYZ...
+ * oIndices
+ * 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);
+
+ /*! Compress a SORTED indexed vertex array by eliminating multiple appearing occurences of a single vertex.
+ * iVertices
+ * The SORTED vertex array to compress. It is organized as a float series of vertex coordinates: XYZXYZXYZ...
+ * iVSize
+ * The size of iVertices array.
+ * iIndices
+ * The array containing the vertex indices (used to refer to the vertex coordinates in an indexed face).
+ * Each element is an unsignedeger multiple of 3.
+ * iISize
+ * The size of iIndices array
+ * oVertices
+ * The vertex array, result of the compression.
+ * The array is organized as a 3-float serie giving the vertices coordinates: XYZXYZXYZ...
+ * oVSize
+ * The size of oVertices.
+ * 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);
+
+ /*! Sorts and compress an array of indexed vertices.
+ * iVertices
+ * The vertex array to sort then compress. It is organized as a float series of
+ * vertex coordinates: XYZXYZXYZ...
+ * iVSize
+ * The size of iVertices array.
+ * iIndices
+ * The array containing the vertex indices (used to refer to the vertex coordinates in an indexed face).
+ * Each element is an unsignedeger multiple of 3.
+ * iISize
+ * The size of iIndices array
+ * oVertices
+ * The vertex array, result of the sorting-compression.
+ * The array is organized as a 3-float serie giving the vertices coordinates: XYZXYZXYZ...
+ * oVSize
+ * The size of oVertices.
+ * oIndices
+ * 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 **oIndices);
+
+ /*! Cleans an indexed vertex array. (Identical to SortAndCompress except that we use here a hash table
+ * to create the new array.)
+ * iVertices
+ * The vertex array to sort then compress. It is organized as a float series of
+ * vertex coordinates: XYZXYZXYZ...
+ * iVSize
+ * The size of iVertices array.
+ * iIndices
+ * The array containing the vertex indices (used to refer to the vertex coordinates in an indexed face).
+ * Each element is an unsignedeger multiple of 3.
+ * iISize
+ * The size of iIndices array
+ * oVertices
+ * The vertex array, result of the sorting-compression.
+ * The array is organized as a 3-float serie giving the vertices coordinates: XYZXYZXYZ...
+ * oVSize
+ * The size of oVertices.
+ * oIndices
+ * 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);
+};
+
+
+/*! Binary operators */
+//inline bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2);
+
+/*! Class Indexed Vertex. Used to represent an indexed vertex by storing the vertex coordinates as well as its index */
+class IndexedVertex
+{
+private:
+ Vec3r _Vector;
+ unsigned _index;
+
+public:
+ inline IndexedVertex() {}
+
+ inline IndexedVertex(Vec3r iVector, unsigned iIndex)
+ {
+ _Vector = iVector;
+ _index = iIndex;
+ }
+
+ /*! accessors */
+ inline const Vec3r& vector() const
+ {
+ return _Vector;
+ }
+
+ inline unsigned index()
+ {
+ return _index;
+ }
+
+ inline real x()
+ {
+ return _Vector[0];
+ }
+
+ inline real y()
+ {
+ return _Vector[1];
+ }
+
+ inline real z()
+ {
+ return _Vector[2];
+ }
+
+ /*! modifiers */
+ inline void setVector(const Vec3r& iVector)
+ {
+ _Vector = iVector;
+ }
+
+ inline void setIndex(unsigned iIndex)
+ {
+ _index = iIndex;
+ }
+
+ /*! operators */
+ IndexedVertex& operator=(const IndexedVertex& iv)
+ {
+ _Vector = iv._Vector;
+ _index = iv._index;
+ return *this;
+ }
+
+ inline real operator[](const unsigned i)
+ {
+ return _Vector[i];
+ }
+
+ //friend inline bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2);
+ inline bool operator<(const IndexedVertex& v) const
+ {
+ return (_Vector < v._Vector);
+ }
+
+ inline bool operator==(const IndexedVertex& v)
+ {
+ return (_Vector == v._Vector);
+ }
+};
+
+#if 0
+bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2)
+{
+ return iv1.operator<(iv2);
+}
+#endif
+
+#endif // __GEOMCLEANER_H__
diff --git a/source/blender/freestyle/intern/geometry/GeomUtils.cpp b/source/blender/freestyle/intern/geometry/GeomUtils.cpp
new file mode 100644
index 00000000000..8d6317c9b07
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/GeomUtils.cpp
@@ -0,0 +1,783 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/geometry/GeomUtils.cpp
+ * \ingroup freestyle
+ * \brief Various tools for geometry
+ * \author Stephane Grabli
+ * \date 12/04/2002
+ */
+
+#include "GeomUtils.h"
+
+namespace GeomUtils {
+
+// This internal procedure is defined below.
+bool intersect2dSegPoly(Vec2r *seg, Vec2r *poly, unsigned n);
+
+bool intersect2dSeg2dArea(const Vec2r& min, const Vec2r& max, const Vec2r& A, const Vec2r& B)
+{
+ Vec2r seg[2];
+ seg[0] = A;
+ seg[1] = B;
+
+ Vec2r poly[5];
+ poly[0][0] = min[0];
+ poly[0][1] = min[1];
+ poly[1][0] = max[0];
+ poly[1][1] = min[1];
+ poly[2][0] = max[0];
+ poly[2][1] = max[1];
+ poly[3][0] = min[0];
+ poly[3][1] = max[1];
+ poly[4][0] = min[0];
+ poly[4][1] = min[1];
+
+ return intersect2dSegPoly(seg, poly, 4);
+}
+
+bool include2dSeg2dArea(const Vec2r& min, const Vec2r& max, const Vec2r& A, const Vec2r& B)
+{
+ if ((((max[0] > A[0]) && (A[0] > min[0])) && ((max[0] > B[0]) && (B[0] > min[0]))) &&
+ (((max[1] > A[1]) && (A[1] > min[1])) && ((max[1] > B[1]) && (B[1] > min[1]))))
+ {
+ return true;
+ }
+ return false;
+}
+
+intersection_test intersect2dSeg2dSeg(const Vec2r& p1, const Vec2r& p2, const Vec2r& p3, const Vec2r& p4, Vec2r& res)
+{
+ real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
+ real r1, r2, r3, r4; // 'Sign' values
+ real denom, num; // Intermediate values
+
+ // Compute a1, b1, c1, where line joining points p1 and p2 is "a1 x + b1 y + c1 = 0".
+ a1 = p2[1] - p1[1];
+ b1 = p1[0] - p2[0];
+ c1 = p2[0] * p1[1] - p1[0] * p2[1];
+
+ // Compute r3 and r4.
+ r3 = a1 * p3[0] + b1 * p3[1] + c1;
+ r4 = a1 * p4[0] + b1 * p4[1] + c1;
+
+ // Check signs of r3 and r4. If both point 3 and point 4 lie on same side of line 1,
+ // the line segments do not intersect.
+ if ( r3 != 0 && r4 != 0 && r3 * r4 > 0.0)
+ return (DONT_INTERSECT);
+
+ // Compute a2, b2, c2
+ a2 = p4[1] - p3[1];
+ b2 = p3[0] - p4[0];
+ c2 = p4[0] * p3[1] - p3[0] * p4[1];
+
+ // Compute r1 and r2
+ r1 = a2 * p1[0] + b2 * p1[1] + c2;
+ r2 = a2 * p2[0] + b2 * p2[1] + c2;
+
+ // Check signs of r1 and r2. If both point 1 and point 2 lie on same side of second line segment,
+ // the line segments do not intersect.
+ if (r1 != 0 && r2 != 0 && r1 * r2 > 0.0)
+ return (DONT_INTERSECT);
+
+ // Line segments intersect: compute intersection point.
+ denom = a1 * b2 - a2 * b1;
+ if (fabs(denom) < M_EPSILON)
+ return (COLINEAR);
+
+ num = b1 * c2 - b2 * c1;
+ res[0] = num / denom;
+
+ num = a2 * c1 - a1 * c2;
+ res[1] = num / denom;
+
+ return (DO_INTERSECT);
+}
+
+intersection_test intersect2dLine2dLine(const Vec2r& p1, const Vec2r& p2, const Vec2r& p3, const Vec2r& p4, Vec2r& res)
+{
+ real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
+ real denom, num; // Intermediate values
+
+ // Compute a1, b1, c1, where line joining points p1 and p2 is "a1 x + b1 y + c1 = 0".
+ a1 = p2[1] - p1[1];
+ b1 = p1[0] - p2[0];
+ c1 = p2[0] * p1[1] - p1[0] * p2[1];
+
+ // Compute a2, b2, c2
+ a2 = p4[1] - p3[1];
+ b2 = p3[0] - p4[0];
+ c2 = p4[0] * p3[1] - p3[0] * p4[1];
+
+ // Line segments intersect: compute intersection point.
+ denom = a1 * b2 - a2 * b1;
+ if (fabs(denom) < M_EPSILON)
+ return (COLINEAR);
+
+ num = b1 * c2 - b2 * c1;
+ res[0] = num / denom;
+
+ num = a2 * c1 - a1 * c2;
+ res[1] = num / denom;
+
+ return (DO_INTERSECT);
+}
+
+intersection_test intersect2dSeg2dSegParametric(const Vec2r& p1, const Vec2r& p2, const Vec2r& p3, const Vec2r& p4,
+ real& t, real& u, real epsilon)
+{
+ real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
+ real r1, r2, r3, r4; // 'Sign' values
+ real denom, num; // Intermediate values
+
+ // Compute a1, b1, c1, where line joining points p1 and p2 is "a1 x + b1 y + c1 = 0".
+ a1 = p2[1] - p1[1];
+ b1 = p1[0] - p2[0];
+ c1 = p2[0] * p1[1] - p1[0] * p2[1];
+
+ // Compute r3 and r4.
+ r3 = a1 * p3[0] + b1 * p3[1] + c1;
+ r4 = a1 * p4[0] + b1 * p4[1] + c1;
+
+ // Check signs of r3 and r4. If both point 3 and point 4 lie on same side of line 1,
+ // the line segments do not intersect.
+ if (r3 != 0 && r4 != 0 && r3 * r4 > 0.0)
+ return (DONT_INTERSECT);
+
+ // Compute a2, b2, c2
+ a2 = p4[1] - p3[1];
+ b2 = p3[0] - p4[0];
+ c2 = p4[0] * p3[1] - p3[0] * p4[1];
+
+ // Compute r1 and r2
+ r1 = a2 * p1[0] + b2 * p1[1] + c2;
+ r2 = a2 * p2[0] + b2 * p2[1] + c2;
+
+ // Check signs of r1 and r2. If both point 1 and point 2 lie on same side of second line segment,
+ // the line segments do not intersect.
+ if (r1 != 0 && r2 != 0 && r1 * r2 > 0.0)
+ return (DONT_INTERSECT);
+
+ // Line segments intersect: compute intersection point.
+ denom = a1 * b2 - a2 * b1;
+ if (fabs(denom) < epsilon)
+ return (COLINEAR);
+
+ real d1, e1;
+
+ d1 = p1[1] - p3[1];
+ e1 = p1[0] - p3[0];
+
+ num = -b2 * d1 - a2 * e1;
+ t = num / denom;
+
+ num = -b1 * d1 - a1 * e1;
+ u = num / denom;
+
+ return (DO_INTERSECT);
+}
+
+// AABB-triangle overlap test code by Tomas Akenine-Möller
+// Function: int triBoxOverlap(real boxcenter[3], real boxhalfsize[3],real triverts[3][3]);
+// History:
+// 2001-03-05: released the code in its first version
+// 2001-06-18: changed the order of the tests, faster
+//
+// Acknowledgement: Many thanks to Pierre Terdiman for suggestions and discussions on how to optimize code.
+// Thanks to David Hunt for finding a ">="-bug!
+
+#define X 0
+#define Y 1
+#define Z 2
+
+#define FINDMINMAX(x0, x1, x2, min, max) \
+ { \
+ min = max = x0; \
+ if (x1 < min) \
+ min = x1; \
+ if (x1 > max) \
+ max = x1; \
+ if (x2 < min) \
+ min = x2; \
+ if (x2 > max) \
+ max = x2; \
+ } (void)0
+
+//======================== X-tests ========================//
+#define AXISTEST_X01(a, b, fa, fb) \
+ { \
+ p0 = a * v0[Y] - b * v0[Z]; \
+ p2 = a * v2[Y] - b * v2[Z]; \
+ if (p0 < p2) { \
+ min = p0; \
+ max = p2; \
+ } \
+ else { \
+ min = p2; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
+ if (min > rad || max < -rad) \
+ return 0; \
+ } (void)0
+
+#define AXISTEST_X2(a, b, fa, fb) \
+ { \
+ p0 = a * v0[Y] - b * v0[Z]; \
+ p1 = a * v1[Y] - b * v1[Z]; \
+ if (p0 < p1) { \
+ min = p0; \
+ max = p1; \
+ } \
+ else { \
+ min = p1; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
+ if (min > rad || max < -rad) \
+ return 0; \
+ } (void)0
+
+//======================== Y-tests ========================//
+#define AXISTEST_Y02(a, b, fa, fb) \
+ { \
+ p0 = -a * v0[X] + b * v0[Z]; \
+ p2 = -a * v2[X] + b * v2[Z]; \
+ if (p0 < p2) { \
+ min = p0; \
+ max = p2; \
+ } \
+ else { \
+ min = p2; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
+ if (min > rad || max < -rad) \
+ return 0; \
+ } (void)0
+
+#define AXISTEST_Y1(a, b, fa, fb) \
+ { \
+ p0 = -a * v0[X] + b * v0[Z]; \
+ p1 = -a * v1[X] + b * v1[Z]; \
+ if (p0 < p1) { \
+ min = p0; \
+ max = p1; \
+ } \
+ else { \
+ min = p1; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
+ if (min > rad || max < -rad) \
+ return 0; \
+ } (void)0
+
+//======================== Z-tests ========================//
+#define AXISTEST_Z12(a, b, fa, fb) \
+ { \
+ p1 = a * v1[X] - b * v1[Y]; \
+ p2 = a * v2[X] - b * v2[Y]; \
+ if (p2 < p1) { \
+ min = p2; \
+ max = p1; \
+ } \
+ else { \
+ min = p1; \
+ max = p2; \
+ } \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
+ if (min > rad || max < -rad) \
+ return 0; \
+ } (void)0
+
+#define AXISTEST_Z0(a, b, fa, fb) \
+ { \
+ p0 = a * v0[X] - b * v0[Y]; \
+ p1 = a * v1[X] - b * v1[Y]; \
+ if (p0 < p1) { \
+ min = p0; \
+ max = p1; \
+ } \
+ else { \
+ min = p1; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
+ if (min > rad || max < -rad) \
+ return 0; \
+ } (void)0
+
+// This internal procedure is defined below.
+bool overlapPlaneBox(Vec3r& normal, real d, Vec3r& maxbox);
+
+// Use separating axis theorem to test overlap between triangle and box need to test for overlap in these directions:
+// 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle we do not even need to test these)
+// 2) normal of the triangle
+// 3) crossproduct(edge from tri, {x,y,z}-directin) this gives 3x3=9 more tests
+bool overlapTriangleBox(Vec3r& boxcenter, Vec3r& boxhalfsize, Vec3r triverts[3])
+{
+ Vec3r v0, v1, v2, normal, e0, e1, e2;
+ real min, max, d, p0, p1, p2, rad, fex, fey, fez;
+
+ // This is the fastest branch on Sun
+ // move everything so that the boxcenter is in (0, 0, 0)
+ v0 = triverts[0] - boxcenter;
+ v1 = triverts[1] - boxcenter;
+ v2 = triverts[2] - boxcenter;
+
+ // compute triangle edges
+ e0 = v1 - v0;
+ e1 = v2 - v1;
+ e2 = v0 - v2;
+
+ // Bullet 3:
+ // Do the 9 tests first (this was faster)
+ fex = fabs(e0[X]);
+ fey = fabs(e0[Y]);
+ fez = fabs(e0[Z]);
+ AXISTEST_X01(e0[Z], e0[Y], fez, fey);
+ AXISTEST_Y02(e0[Z], e0[X], fez, fex);
+ AXISTEST_Z12(e0[Y], e0[X], fey, fex);
+
+ fex = fabs(e1[X]);
+ fey = fabs(e1[Y]);
+ fez = fabs(e1[Z]);
+ AXISTEST_X01(e1[Z], e1[Y], fez, fey);
+ AXISTEST_Y02(e1[Z], e1[X], fez, fex);
+ AXISTEST_Z0(e1[Y], e1[X], fey, fex);
+
+ fex = fabs(e2[X]);
+ fey = fabs(e2[Y]);
+ fez = fabs(e2[Z]);
+ AXISTEST_X2(e2[Z], e2[Y], fez, fey);
+ AXISTEST_Y1(e2[Z], e2[X], fez, fex);
+ AXISTEST_Z12(e2[Y], e2[X], fey, fex);
+
+ // Bullet 1:
+ // first test overlap in the {x,y,z}-directions
+ // find min, max of the triangle each direction, and test for overlap in that direction -- this is equivalent
+ // to testing a minimal AABB around the triangle against the AABB
+
+ // test in X-direction
+ FINDMINMAX(v0[X], v1[X], v2[X], min, max);
+ if (min > boxhalfsize[X] || max < -boxhalfsize[X])
+ return false;
+
+ // test in Y-direction
+ FINDMINMAX(v0[Y], v1[Y], v2[Y], min, max);
+ if (min > boxhalfsize[Y] || max < -boxhalfsize[Y])
+ return false;
+
+ // test in Z-direction
+ FINDMINMAX(v0[Z], v1[Z], v2[Z], min, max);
+ if (min > boxhalfsize[Z] || max < -boxhalfsize[Z])
+ return false;
+
+ // Bullet 2:
+ // test if the box intersects the plane of the triangle
+ // compute plane equation of triangle: normal * x + d = 0
+ normal = e0 ^ e1;
+ d = -(normal * v0); // plane eq: normal.x + d = 0
+ if (!overlapPlaneBox(normal, d, boxhalfsize))
+ return false;
+
+ return true; // box and triangle overlaps
+}
+
+// Fast, Minimum Storage Ray-Triangle Intersection
+//
+// Tomas Möller
+// Prosolvia Clarus AB
+// Sweden
+// tompa@clarus.se
+//
+// Ben Trumbore
+// Cornell University
+// Ithaca, New York
+// wbt@graphics.cornell.edu
+bool intersectRayTriangle(const Vec3r& orig, const Vec3r& dir, const Vec3r& v0, const Vec3r& v1, const Vec3r& v2,
+ real& t, real& u, real& v, const real epsilon)
+{
+ Vec3r edge1, edge2, tvec, pvec, qvec;
+ real det, inv_det;
+
+ // find vectors for two edges sharing v0
+ edge1 = v1 - v0;
+ edge2 = v2 - v0;
+
+ // begin calculating determinant - also used to calculate U parameter
+ pvec = dir ^ edge2;
+
+ // if determinant is near zero, ray lies in plane of triangle
+ det = edge1 * pvec;
+
+ // calculate distance from v0 to ray origin
+ tvec = orig - v0;
+ inv_det = 1.0 / det;
+
+ qvec = tvec ^ edge1;
+
+ if (det > epsilon) {
+ u = tvec * pvec;
+ if (u < 0.0 || u > det)
+ return false;
+
+ // calculate V parameter and test bounds
+ v = dir * qvec;
+ if (v < 0.0 || u + v > det)
+ return false;
+ }
+ else if (det < -epsilon) {
+ // calculate U parameter and test bounds
+ u = tvec * pvec;
+ if (u > 0.0 || u < det)
+ return false;
+
+ // calculate V parameter and test bounds
+ v = dir * qvec;
+ if (v > 0.0 || u + v < det)
+ return false;
+ }
+ else {
+ return false; // ray is parallell to the plane of the triangle
+ }
+
+ u *= inv_det;
+ v *= inv_det;
+ t = (edge2 * qvec) * inv_det;
+
+ return true;
+}
+
+// Intersection between plane and ray, adapted from Graphics Gems, Didier Badouel
+intersection_test intersectRayPlane(const Vec3r& orig, const Vec3r& dir, const Vec3r& norm, const real d,
+ real& t, const real epsilon)
+{
+ real denom = norm * dir;
+
+ if (fabs(denom) <= epsilon) { // plane and ray are parallel
+ if (fabs((norm * orig) + d) <= epsilon)
+ return COINCIDENT; // plane and ray are coincident
+ else
+ return COLINEAR;
+ }
+
+ t = -(d + (norm * orig)) / denom;
+
+ if (t < 0.0f)
+ return DONT_INTERSECT;
+
+ return DO_INTERSECT;
+}
+
+bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
+ const Vec3r& boxMin, const Vec3r& boxMax, // the bbox
+ 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)
+{
+ float tymin, tymax, tzmin, tzmax;
+ Vec3r inv_direction(1.0 / dir[0], 1.0 / dir[1], 1.0 / dir[2]);
+ int sign[3];
+ sign[0] = (inv_direction.x() < 0);
+ sign[1] = (inv_direction.y() < 0);
+ sign[2] = (inv_direction.z() < 0);
+
+ Vec3r bounds[2];
+ bounds[0] = boxMin;
+ bounds[1] = boxMax;
+
+ tmin = (bounds[sign[0]].x() - orig.x()) * inv_direction.x();
+ tmax = (bounds[1 - sign[0]].x() - orig.x()) * inv_direction.x();
+ tymin = (bounds[sign[1]].y() - orig.y()) * inv_direction.y();
+ tymax = (bounds[1 - sign[1]].y() - orig.y()) * inv_direction.y();
+ if ((tmin > tymax) || (tymin > tmax))
+ return false;
+ if (tymin > tmin)
+ tmin = tymin;
+ if (tymax < tmax)
+ tmax = tymax;
+ tzmin = (bounds[sign[2]].z() - orig.z()) * inv_direction.z();
+ tzmax = (bounds[1 - sign[2]].z() - orig.z()) * inv_direction.z();
+ if ((tmin > tzmax) || (tzmin > tmax))
+ return false;
+ if (tzmin > tmin)
+ tmin = tzmin;
+ if (tzmax < tmax)
+ tmax = tzmax;
+ return ((tmin < t1) && (tmax > t0));
+}
+
+// Checks whether 3D points p lies inside or outside of the triangle ABC
+bool includePointTriangle(const Vec3r& P, const Vec3r& A, const Vec3r& B, const Vec3r& C)
+{
+ Vec3r AB(B - A);
+ Vec3r BC(C - B);
+ Vec3r CA(A - C);
+ Vec3r AP(P - A);
+ Vec3r BP(P - B);
+ Vec3r CP(P - C);
+
+ Vec3r N(AB ^ BC); // triangle's normal
+
+ N.normalize();
+
+ Vec3r J(AB ^ AP), K(BC ^ BP), L(CA ^ CP);
+ J.normalize();
+ K.normalize();
+ L.normalize();
+
+ if (J * N < 0)
+ return false; // on the right of AB
+
+ if (K * N < 0)
+ return false; // on the right of BC
+
+ if (L * N < 0)
+ return false; // on the right of CA
+
+ return true;
+}
+
+void transformVertex(const Vec3r& vert, const Matrix44r& matrix, Vec3r& res)
+{
+ HVec3r hvert(vert), res_tmp;
+ real scale;
+ for (unsigned int j = 0; j < 4; j++) {
+ scale = hvert[j];
+ for (unsigned int i = 0; i < 4; i++)
+ res_tmp[i] += matrix(i, j) * scale;
+ }
+
+ res[0] = res_tmp.x();
+ res[1] = res_tmp.y();
+ res[2] = res_tmp.z();
+}
+
+void transformVertices(const vector<Vec3r>& vertices, const Matrix44r& trans, vector<Vec3r>& res)
+{
+ for (vector<Vec3r>::const_iterator v = vertices.begin(); v != vertices.end(); v++) {
+ Vec3r *res_tmp = new Vec3r;
+ transformVertex(*v, trans, *res_tmp);
+ res.push_back(*res_tmp);
+ }
+}
+
+Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v)
+{
+ Vec3r res;
+ for (unsigned int i = 0; i < 3; i++) {
+ res[i] = 0;
+ for (unsigned int j = 0; j < 3; j++)
+ res[i] += mat(i, j) * v[j];
+ }
+ res.normalize();
+ return res;
+}
+
+// This internal procedure is defined below.
+void fromCoordAToCoordB(const Vec3r& p, Vec3r& q, const real transform[4][4]);
+
+void fromWorldToCamera(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4])
+{
+ fromCoordAToCoordB(p, q, model_view_matrix);
+}
+
+void fromCameraToRetina(const Vec3r& p, Vec3r& q, const real projection_matrix[4][4])
+{
+ fromCoordAToCoordB(p, q, projection_matrix);
+}
+
+void fromRetinaToImage(const Vec3r& p, Vec3r& q, const int viewport[4])
+{
+ // winX:
+ q[0] = viewport[0] + viewport[2] * (p[0] + 1.0) / 2.0;
+
+ // winY:
+ q[1] = viewport[1] + viewport[3] * (p[1] + 1.0) / 2.0;
+
+ // winZ:
+ q[2] = (p[2] + 1.0) / 2.0;
+}
+
+void fromWorldToImage(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4],
+ const real projection_matrix[4][4], const int viewport[4])
+{
+ Vec3r p1, p2;
+ fromWorldToCamera(p, p1, model_view_matrix);
+ fromCameraToRetina(p1, p2, projection_matrix);
+ fromRetinaToImage(p2, q, viewport);
+ q[2] = p1[2];
+}
+
+void fromWorldToImage(const Vec3r& p, Vec3r& q, const real transform[4][4], const int viewport[4])
+{
+ fromCoordAToCoordB(p, q, transform);
+
+ // winX:
+ q[0] = viewport[0] + viewport[2] * (q[0] + 1.0) / 2.0;
+
+ //winY:
+ q[1] = viewport[1] + viewport[3] * (q[1] + 1.0) / 2.0;
+}
+
+void fromImageToRetina(const Vec3r& p, Vec3r& q, const int viewport[4])
+{
+ q = p;
+ q[0] = 2.0 * (q[0] - viewport[0]) / viewport[2] - 1.0;
+ q[1] = 2.0 * (q[1] - viewport[1]) / viewport[3] - 1.0;
+}
+
+void fromRetinaToCamera(const Vec3r& p, Vec3r& q, real focal, const real projection_matrix[4][4])
+{
+ if (projection_matrix[3][3] == 0.0) { // perspective
+ q[0] = (-p[0] * focal) / projection_matrix[0][0];
+ q[1] = (-p[1] * focal) / projection_matrix[1][1];
+ q[2] = focal;
+ }
+ else { // orthogonal
+ q[0] = p[0] / projection_matrix[0][0];
+ q[1] = p[1] / projection_matrix[1][1];
+ q[2] = focal;
+ }
+}
+
+void fromCameraToWorld(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4])
+{
+ real translation[3] = {
+ model_view_matrix[0][3],
+ model_view_matrix[1][3],
+ model_view_matrix[2][3]
+ };
+ for (unsigned short i = 0; i < 3; i++) {
+ q[i] = 0.0;
+ for (unsigned short j = 0; j < 3; j++)
+ q[i] += model_view_matrix[j][i] * (p[j] - translation[j]);
+ }
+}
+
+
+//
+// Internal code
+//
+/////////////////////////////////////////////////////////////////////////////
+
+// Copyright 2001, softSurfer (www.softsurfer.com)
+// This code may be freely used and modified for any purpose providing that this copyright notice is included with it.
+// SoftSurfer makes no warranty for this code, and cannot be held liable for any real or imagined damage resulting
+// from its use.
+// Users of this code must verify correctness for their application.
+
+#define PERP(u, v) ((u)[0] * (v)[1] - (u)[1] * (v)[0]) // 2D perp product
+
+inline bool intersect2dSegPoly(Vec2r *seg, Vec2r *poly, unsigned n)
+{
+ if (seg[0] == seg[1])
+ return false;
+
+ real tE = 0; // the maximum entering segment parameter
+ real tL = 1; // the minimum leaving segment parameter
+ real t, N, D; // intersect parameter t = N / D
+ Vec2r dseg = seg[1] - seg[0]; // the segment direction vector
+ Vec2r e; // edge vector
+
+ for (unsigned int i = 0; i < n; i++) { // process polygon edge poly[i]poly[i+1]
+ e = poly[i + 1] - poly[i];
+ N = PERP(e, seg[0] - poly[i]);
+ D = -PERP(e, dseg);
+ if (fabs(D) < M_EPSILON) {
+ if (N < 0)
+ return false;
+ else
+ continue;
+ }
+
+ t = N / D;
+ if (D < 0) { // segment seg is entering across this edge
+ if (t > tE) { // new max tE
+ tE = t;
+ if (tE > tL) // seg enters after leaving polygon
+ return false;
+ }
+ }
+ else { // segment seg is leaving across this edge
+ if (t < tL) { // new min tL
+ tL = t;
+ if (tL < tE) // seg leaves before entering polygon
+ return false;
+ }
+ }
+ }
+
+ // tE <= tL implies that there is a valid intersection subsegment
+ return true;
+}
+
+inline bool overlapPlaneBox(Vec3r& normal, real d, Vec3r& maxbox)
+{
+ Vec3r vmin, vmax;
+
+ for (unsigned int q = X; q <= Z; q++) {
+ if (normal[q] > 0.0f) {
+ vmin[q] = -maxbox[q];
+ vmax[q] = maxbox[q];
+ }
+ else {
+ vmin[q] = maxbox[q];
+ vmax[q] = -maxbox[q];
+ }
+ }
+ if ((normal * vmin) + d > 0.0f)
+ return false;
+ if ((normal * vmax) + d >= 0.0f)
+ return true;
+ return false;
+}
+
+inline void fromCoordAToCoordB(const Vec3r&p, Vec3r& q, const real transform[4][4])
+{
+ HVec3r hp(p);
+ HVec3r hq(0, 0, 0, 0);
+
+ for (unsigned int i = 0; i < 4; i++) {
+ for (unsigned int j = 0; j < 4; j++) {
+ hq[i] += transform[i][j] * hp[j];
+ }
+ }
+
+ if (hq[3] == 0) {
+ q = p;
+ return;
+ }
+
+ for (unsigned int k = 0; k < 3; k++)
+ q[k] = hq[k] / hq[3];
+}
+
+} // end of namespace GeomUtils
diff --git a/source/blender/freestyle/intern/geometry/GeomUtils.h b/source/blender/freestyle/intern/geometry/GeomUtils.h
new file mode 100644
index 00000000000..be20873e73b
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/GeomUtils.h
@@ -0,0 +1,277 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __GEOMUTILS_H__
+#define __GEOMUTILS_H__
+
+/** \file blender/freestyle/intern/geometry/GeomUtils.h
+ * \ingroup freestyle
+ * \brief Various tools for geometry
+ * \author Stephane Grabli
+ * \date 12/04/2002
+ */
+
+#include <vector>
+
+#include "Geom.h"
+
+#include "../system/FreestyleConfig.h"
+
+using namespace std;
+using namespace Geometry;
+
+namespace GeomUtils {
+
+//
+// Templated procedures
+//
+/////////////////////////////////////////////////////////////////////////////
+
+/*! Computes the distance from a point P to a segment AB */
+template<class T>
+real distPointSegment(const T& P, const T& A, const T& B)
+{
+ T AB, AP, BP;
+ AB = B - A;
+ AP = P - A;
+ BP = P - B;
+
+ real c1(AB * AP);
+ if (c1 <= 0)
+ return AP.norm();
+
+ real c2(AB * AB);
+ if (c2 <= c1)
+ return BP.norm();
+
+ real b = c1 / c2;
+ T Pb, PPb;
+ Pb = A + b * AB;
+ PPb = P - Pb;
+
+ return PPb.norm();
+}
+
+//
+// Non-templated procedures
+//
+/////////////////////////////////////////////////////////////////////////////
+typedef enum {
+ DONT_INTERSECT,
+ DO_INTERSECT,
+ COLINEAR,
+ COINCIDENT,
+} intersection_test;
+
+LIB_GEOMETRY_EXPORT
+intersection_test intersect2dSeg2dSeg(const Vec2r& p1, const Vec2r& p2, // first segment
+ const Vec2r& p3, const Vec2r& p4, // second segment
+ Vec2r& res); // found intersection point
+
+LIB_GEOMETRY_EXPORT
+intersection_test intersect2dLine2dLine(const Vec2r& p1, const Vec2r& p2, // first segment
+ const Vec2r& p3, const Vec2r& p4, // second segment
+ Vec2r& res); // found intersection point
+
+LIB_GEOMETRY_EXPORT
+intersection_test intersect2dSeg2dSegParametric(const Vec2r& p1, const Vec2r& p2, // first segment
+ const Vec2r& p3, const Vec2r& p4, // second segment
+ real& t, // I = P1 + t * P1P2)
+ real& u, // I = P3 + u * P3P4
+ real epsilon = M_EPSILON);
+
+/*! check whether a 2D segment intersect a 2D region or not */
+LIB_GEOMETRY_EXPORT
+bool intersect2dSeg2dArea(const Vec2r& min, const Vec2r& max, const Vec2r& A, const Vec2r& B);
+
+/*! check whether a 2D segment is included in a 2D region or not */
+LIB_GEOMETRY_EXPORT
+bool include2dSeg2dArea(const Vec2r& min, const Vec2r& max, const Vec2r& A, const Vec2r& B);
+
+/*! Box-triangle overlap test, adapted from Tomas Akenine-Möller code */
+LIB_GEOMETRY_EXPORT
+bool overlapTriangleBox(Vec3r& boxcenter, Vec3r& boxhalfsize, Vec3r triverts[3]);
+
+/*! Fast, Minimum Storage Ray-Triangle Intersection, adapted from Tomas Möller and Ben Trumbore code. */
+LIB_GEOMETRY_EXPORT
+bool intersectRayTriangle(const Vec3r& orig, const Vec3r& dir, const Vec3r& v0, const Vec3r& v1, const Vec3r& v2,
+ real& t, // I = orig + t * dir
+ real& u, real& v, // I = (1 - u - v) * v0 + u * v1 + v * v2
+ const real epsilon = M_EPSILON); // the epsilon to use
+
+/*! Intersection between plane and ray adapted from Graphics Gems, Didier Badouel */
+LIB_GEOMETRY_EXPORT
+intersection_test intersectRayPlane(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
+ // plane's normal and offset (plane = { P / P.N + d = 0 })
+ const Vec3r& norm, const real d,
+ real& t, // I = orig + t * dir
+ const real epsilon = M_EPSILON); // the epsilon to use
+
+/*! Intersection Ray-Bounding box (axis aligned).
+ * Adapted from Williams et al, "An Efficient Robust Ray-Box Intersection Algorithm", JGT 10:1 (2005), pp. 49-54.
+ */
+LIB_GEOMETRY_EXPORT
+bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
+ const Vec3r& boxMin, const Vec3r& boxMax, // the bbox
+ // the interval in which at least on of the intersections must happen
+ real t0, real t1,
+ real& tmin, // Imin = orig + tmin * dir is the first intersection
+ real& tmax, // Imax = orig + tmax * dir is the second intersection
+ real epsilon = M_EPSILON); // the epsilon to use
+
+/*! Checks whether 3D point P lies inside or outside of the triangle ABC */
+LIB_GEOMETRY_EXPORT
+bool includePointTriangle(const Vec3r& P, const Vec3r& A, const Vec3r& B, const Vec3r& C);
+
+LIB_GEOMETRY_EXPORT
+void transformVertex(const Vec3r& vert, const Matrix44r& matrix, Vec3r& res);
+
+LIB_GEOMETRY_EXPORT
+void transformVertices(const vector<Vec3r>& vertices, const Matrix44r& trans, vector<Vec3r>& res);
+
+LIB_GEOMETRY_EXPORT
+Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v);
+
+//
+// Coordinates systems changing procedures
+//
+/////////////////////////////////////////////////////////////////////////////
+
+/*! From world to image
+ * p
+ * point's coordinates expressed in world coordinates system
+ * q
+ * vector in which the result will be stored
+ * model_view_matrix
+ * The model view matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ * projection_matrix
+ * The projection matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ * viewport
+ * The viewport: x,y coordinates followed by width and height (OpenGL like viewport)
+ */
+LIB_GEOMETRY_EXPORT
+void fromWorldToImage(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4], const real projection_matrix[4][4],
+ const int viewport[4]);
+
+/*! From world to image
+ * p
+ * point's coordinates expressed in world coordinates system
+ * q
+ * vector in which the result will be stored
+ * transform
+ * The transformation matrix (gathering model view and projection),
+ * expressed in line major order (OpenGL matrices are column major ordered)
+ * viewport
+ * The viewport: x,y coordinates followed by width and height (OpenGL like viewport)
+ */
+LIB_GEOMETRY_EXPORT
+void fromWorldToImage(const Vec3r& p, Vec3r& q, const real transform[4][4], const int viewport[4]);
+
+/*! Projects from world coordinates to camera coordinates
+ * Returns the point's coordinates expressed in the camera's
+ * coordinates system.
+ * p
+ * point's coordinates expressed in world coordinates system
+ * q
+ * vector in which the result will be stored
+ * model_view_matrix
+ * The model view matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ */
+LIB_GEOMETRY_EXPORT
+void fromWorldToCamera(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4]);
+
+/*! Projects from World Coordinates to retina coordinates
+ * Returns the point's coordinates expressed in Retina system.
+ * p
+ * point's coordinates expressed in camera system
+ * q
+ * vector in which the result will be stored
+ * projection_matrix
+ * The projection matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ */
+LIB_GEOMETRY_EXPORT
+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.
+ * p
+ * point's coordinates expressed in retina system
+ * q
+ * vector in which the result will be stored
+ * viewport
+ * The viewport: x,y coordinates followed by width and height (OpenGL like viewport).
+ */
+LIB_GEOMETRY_EXPORT
+void fromRetinaToImage(const Vec3r& p, Vec3r& q, const int viewport[4]);
+
+/*! From image to retina
+ * p
+ * point's coordinates expressed in image system
+ * q
+ * vector in which the result will be stored
+ * viewport
+ * The viewport: x,y coordinates followed by width and height (OpenGL like viewport).
+ */
+LIB_GEOMETRY_EXPORT
+void fromImageToRetina(const Vec3r& p, Vec3r& q, const int viewport[4]);
+
+/*! computes the coordinates of q in the camera coordinates system,
+ * using the known z coordinates of the 3D point.
+ * That means that this method does not inverse any matrices,
+ * it only computes X and Y from x,y and Z)
+ * p
+ * point's coordinates expressed in retina system
+ * q
+ * vector in which the result will be stored
+ * projection_matrix
+ * The projection matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ */
+LIB_GEOMETRY_EXPORT
+void fromRetinaToCamera(const Vec3r& p, Vec3r& q, real z, const real projection_matrix[4][4]);
+
+/*! Projects from camera coordinates to world coordinates
+ * Returns the point's coordinates expressed in the world's
+ * coordinates system.
+ * p
+ * point's coordinates expressed in the camera coordinates system
+ * q
+ * vector in which the result will be stored
+ * model_view_matrix
+ * The model view matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ */
+LIB_GEOMETRY_EXPORT
+void fromCameraToWorld(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4]);
+
+} // end of namespace GeomUtils
+
+#endif // __GEOMUTILS_H__
diff --git a/source/blender/freestyle/intern/geometry/Grid.cpp b/source/blender/freestyle/intern/geometry/Grid.cpp
new file mode 100644
index 00000000000..0b798c5abb8
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Grid.cpp
@@ -0,0 +1,391 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/geometry/Grid.cpp
+ * \ingroup freestyle
+ * \brief Base class to define a cell grid surrounding the bounding box of the scene
+ * \author Stephane Grabli
+ * \date 30/07/2002
+ */
+
+#include <cassert>
+#include <stdexcept>
+
+#include "BBox.h"
+#include "Grid.h"
+
+// Grid Visitors
+/////////////////
+void allOccludersGridVisitor::examineOccluder(Polygon3r *occ)
+{
+ occluders_.push_back(occ);
+}
+
+static bool inBox(const Vec3r& inter, const Vec3r& box_min, const Vec3r& box_max)
+{
+ if (((inter.x() >= box_min.x()) && (inter.x() < box_max.x())) &&
+ ((inter.y() >= box_min.y()) && (inter.y() < box_max.y())) &&
+ ((inter.z() >= box_min.z()) && (inter.z() < box_max.z())))
+ {
+ return true;
+ }
+ return false;
+}
+
+void firstIntersectionGridVisitor::examineOccluder(Polygon3r *occ)
+{
+ // check whether the edge and the polygon plane are coincident:
+ //-------------------------------------------------------------
+ //first let us compute the plane equation.
+ Vec3r v1(((occ)->getVertices())[0]);
+ Vec3d normal((occ)->getNormal());
+ //soc unused - double d = -(v1 * normal);
+
+ double tmp_u, tmp_v, tmp_t;
+ if ((occ)->rayIntersect(ray_org_, ray_dir_, tmp_t, tmp_u, tmp_v)) {
+ if (fabs(ray_dir_ * normal) > 0.0001) {
+ // Check whether the intersection is in the cell:
+ if (inBox(ray_org_ + tmp_t * ray_dir_ / ray_dir_.norm(), current_cell_->getOrigin(),
+ current_cell_->getOrigin() + cell_size_))
+ {
+#if 0
+ Vec3d bboxdiag(_scene3d->bbox().getMax() - _scene3d->bbox().getMin());
+ if ((t > 1.0e-06 * (min(min(bboxdiag.x(), bboxdiag.y()), bboxdiag.z()))) && (t < raylength)) {
+#else
+ if (tmp_t < t_) {
+#endif
+ occluder_ = occ;
+ u_ = tmp_u;
+ v_ = tmp_v;
+ t_ = tmp_t;
+ }
+ }
+ else {
+ occ->userdata2 = 0;
+ }
+ }
+ }
+}
+
+bool firstIntersectionGridVisitor::stop()
+{
+ if (occluder_)
+ return true;
+ return false;
+}
+
+// Grid
+/////////////////
+void Grid::clear()
+{
+ if (_occluders.size() != 0) {
+ for (OccludersSet::iterator it = _occluders.begin(); it != _occluders.end(); it++) {
+ delete (*it);
+ }
+ _occluders.clear();
+ }
+
+ _size = Vec3r(0, 0, 0);
+ _cell_size = Vec3r(0, 0, 0);
+ _orig = Vec3r(0, 0, 0);
+ _cells_nb = Vec3u(0, 0, 0);
+ //_ray_occluders.clear();
+}
+
+void Grid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb)
+{
+ _orig = orig;
+ Vec3r tmpSize = size;
+ // Compute the volume of the desired grid
+ real grid_vol = size[0] * size[1] * size[2];
+
+ if (grid_vol == 0) {
+ double min = DBL_MAX;
+ int index = 0;
+ int nzeros = 0;
+ for (int i = 0; i < 3; ++i) {
+ if (size[i] == 0) {
+ ++nzeros;
+ index = i;
+ }
+ if ((size[i] != 0) && (min > size[i])) {
+ min = size[i];
+ }
+ }
+ if (nzeros > 1) {
+ throw std::runtime_error("Warning: the 3D grid has more than one null dimension");
+ }
+ tmpSize[index] = min;
+ _orig[index] = _orig[index] - min / 2;
+ }
+ // Compute the desired volume of a single cell
+ real cell_vol = grid_vol / nb;
+ // The edge of such a cubic cell is cubic root of cellVolume
+ real edge = pow(cell_vol, 1.0 / 3.0);
+
+ // We compute the number of cells par edge such as we cover at least the whole box.
+ unsigned i;
+ for (i = 0; i < 3; i++)
+ _cells_nb[i] = (unsigned)floor(tmpSize[i] / edge) + 1;
+
+ _size = tmpSize;
+
+ for (i = 0; i < 3; i++)
+ _cell_size[i] = _size[i] / _cells_nb[i];
+}
+
+void Grid::insertOccluder(Polygon3r *occluder)
+{
+ const vector<Vec3r> vertices = occluder->getVertices();
+ if (vertices.size() == 0)
+ return;
+
+ // add this occluder to the grid's occluders list
+ addOccluder(occluder);
+
+ // find the bbox associated to this polygon
+ Vec3r min, max;
+ occluder->getBBox(min, max);
+
+ // Retrieve the cell x, y, z cordinates associated with these min and max
+ Vec3u imax, imin;
+ getCellCoordinates(max, imax);
+ getCellCoordinates(min, imin);
+
+ // We are now going to fill in the cells overlapping with the polygon bbox.
+ // If the polygon is a triangle (most of cases), we also check for each of these cells if it is overlapping with
+ // the triangle in order to only fill in the ones really overlapping the triangle.
+
+ unsigned i, x, y, z;
+ vector<Vec3r>::const_iterator it;
+ Vec3u coord;
+
+ if (vertices.size() == 3) { // Triangle case
+ Vec3r triverts[3];
+ i = 0;
+ for (it = vertices.begin(); it != vertices.end(); it++) {
+ triverts[i] = Vec3r(*it);
+ i++;
+ }
+
+ Vec3r boxmin, boxmax;
+
+ for (z = imin[2]; z <= imax[2]; z++) {
+ for (y = imin[1]; y <= imax[1]; y++) {
+ for (x = imin[0]; x <= imax[0]; x++) {
+ coord[0] = x;
+ coord[1] = y;
+ coord[2] = z;
+ // We retrieve the box coordinates of the current cell
+ getCellBox(coord, boxmin, boxmax);
+ // We check whether the triangle and the box ovewrlap:
+ Vec3r boxcenter((boxmin + boxmax) / 2.0);
+ Vec3r boxhalfsize(_cell_size / 2.0);
+ if (GeomUtils::overlapTriangleBox(boxcenter, boxhalfsize, triverts)) {
+ // We must then create the Cell and add it to the cells list if it does not exist yet.
+ // We must then add the occluder to the occluders list of this cell.
+ Cell *cell = getCell(coord);
+ if (!cell) {
+ cell = new Cell(boxmin);
+ fillCell(coord, *cell);
+ }
+ cell->addOccluder(occluder);
+ }
+ }
+ }
+ }
+ }
+ else { // The polygon is not a triangle, we add all the cells overlapping the polygon bbox.
+ for (z = imin[2]; z <= imax[2]; z++) {
+ for (y = imin[1]; y <= imax[1]; y++) {
+ for (x = imin[0]; x <= imax[0]; x++) {
+ coord[0] = x;
+ coord[1] = y;
+ coord[2] = z;
+ Cell *cell = getCell(coord);
+ if (!cell) {
+ Vec3r orig;
+ getCellOrigin(coord, orig);
+ cell = new Cell(orig);
+ fillCell(coord, *cell);
+ }
+ cell->addOccluder(occluder);
+ }
+ }
+ }
+ }
+}
+
+bool Grid::nextRayCell(Vec3u& current_cell, Vec3u& next_cell)
+{
+ next_cell = current_cell;
+ real t_min, t;
+ unsigned i;
+
+ t_min = FLT_MAX; // init tmin with handle of the case where one or 2 _u[i] = 0.
+ unsigned coord = 0; // predominant coord(0=x, 1=y, 2=z)
+
+
+ // using a parametric equation of a line : B = A + t u, we find the tx, ty and tz respectively coresponding
+ // to the intersections with the plans:
+ // x = _cell_size[0], y = _cell_size[1], z = _cell_size[2]
+ for (i = 0; i < 3; i++) {
+ if (_ray_dir[i] == 0)
+ continue;
+ if (_ray_dir[i] > 0)
+ t = (_cell_size[i] - _pt[i]) / _ray_dir[i];
+ else
+ t = -_pt[i] / _ray_dir[i];
+ if (t < t_min) {
+ t_min = t;
+ coord = i;
+ }
+ }
+
+ // We use the parametric line equation and the found t (tamx) to compute the B coordinates:
+ Vec3r pt_tmp(_pt);
+ _pt = pt_tmp + t_min * _ray_dir;
+
+ // We express B coordinates in the next cell coordinates system. We just have to
+ // set the coordinate coord of B to 0 of _CellSize[coord] depending on the sign of _u[coord]
+ if (_ray_dir[coord] > 0) {
+ next_cell[coord]++;
+ _pt[coord] -= _cell_size[coord];
+ // if we are out of the grid, we must stop
+ if (next_cell[coord] >= _cells_nb[coord])
+ return false;
+ }
+ else {
+ int tmp = next_cell[coord] - 1;
+ _pt[coord] = _cell_size[coord];
+ if (tmp < 0)
+ return false;
+ next_cell[coord]--;
+ }
+
+ _t += t_min;
+ if (_t >= _t_end)
+ return false;
+
+ return true;
+}
+
+void Grid::castRay(const Vec3r& orig, const Vec3r& end, OccludersSet& occluders, unsigned timestamp)
+{
+ initRay(orig, end, timestamp);
+ allOccludersGridVisitor visitor(occluders);
+ castRayInternal(visitor);
+}
+
+void Grid::castInfiniteRay(const Vec3r& orig, const Vec3r& dir, OccludersSet& occluders, unsigned timestamp)
+{
+ Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm());
+ bool inter = initInfiniteRay(orig, dir, timestamp);
+ if (!inter)
+ return;
+ allOccludersGridVisitor visitor(occluders);
+ castRayInternal(visitor);
+}
+
+Polygon3r *Grid::castRayToFindFirstIntersection(const Vec3r& orig, const Vec3r& dir, double& t,
+ double& u, double& v, unsigned timestamp)
+{
+ Polygon3r *occluder = 0;
+ Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm());
+ bool inter = initInfiniteRay(orig, dir, timestamp);
+ if (!inter) {
+ return 0;
+ }
+ firstIntersectionGridVisitor visitor(orig, dir, _cell_size);
+ castRayInternal(visitor);
+ // ARB: This doesn't work, because occluders are unordered within any cell
+ // visitor.occluder() will be an occluder, but we have no guarantee it will be the *first* occluder.
+ // I assume that is the reason this code is not actually used for FindOccludee.
+ occluder = visitor.occluder();
+ t = visitor.t_;
+ u = visitor.u_;
+ v = visitor.v_;
+ return occluder;
+}
+
+void Grid::initRay (const Vec3r &orig, const Vec3r& end, unsigned timestamp)
+{
+ _ray_dir = end - orig;
+ _t_end = _ray_dir.norm();
+ _t = 0;
+ _ray_dir.normalize();
+ _timestamp = timestamp;
+
+ for (unsigned i = 0; i < 3; i++) {
+ _current_cell[i] = (unsigned)floor((orig[i] - _orig[i]) / _cell_size[i]);
+ //soc unused - unsigned u = _current_cell[i];
+ _pt[i] = orig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
+ }
+ //_ray_occluders.clear();
+}
+
+bool Grid::initInfiniteRay (const Vec3r &orig, const Vec3r& dir, unsigned timestamp)
+{
+ _ray_dir = dir;
+ _t_end = FLT_MAX;
+ _t = 0;
+ _ray_dir.normalize();
+ _timestamp = timestamp;
+
+ // check whether the origin is in or out the box:
+ Vec3r boxMin(_orig);
+ Vec3r boxMax(_orig + _size);
+ BBox<Vec3r> box(boxMin, boxMax);
+ if (box.inside(orig)) {
+ for (unsigned int i = 0; i < 3; i++) {
+ _current_cell[i] = (unsigned int)floor((orig[i] - _orig[i]) / _cell_size[i]);
+ //soc unused - unsigned u = _current_cell[i];
+ _pt[i] = orig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
+ }
+ }
+ else {
+ // is the ray intersecting the box?
+ real tmin(-1.0), tmax(-1.0);
+ if (GeomUtils::intersectRayBBox(orig, _ray_dir, boxMin, boxMax, 0, _t_end, tmin, tmax)) {
+ assert(tmin != -1.0);
+ Vec3r newOrig = orig + tmin * _ray_dir;
+ for (unsigned int i = 0; i < 3; i++) {
+ _current_cell[i] = (unsigned)floor((newOrig[i] - _orig[i]) / _cell_size[i]);
+ if (_current_cell[i] == _cells_nb[i])
+ _current_cell[i] = _cells_nb[i] - 1;
+ //soc unused - unsigned u = _current_cell[i];
+ _pt[i] = newOrig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
+ }
+ }
+ else {
+ return false;
+ }
+ }
+ //_ray_occluders.clear();
+
+ return true;
+}
diff --git a/source/blender/freestyle/intern/geometry/Grid.h b/source/blender/freestyle/intern/geometry/Grid.h
new file mode 100644
index 00000000000..f37f7f615f0
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Grid.h
@@ -0,0 +1,384 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __GRID_H__
+#define __GRID_H__
+
+/** \file blender/freestyle/intern/geometry/Grid.h
+ * \ingroup freestyle
+ * \brief Base class to define a cell grid surrounding the bounding box of the scene
+ * \author Stephane Grabli
+ * \date 30/07/2002
+ */
+
+#include <cstring> // for memset
+#include <float.h>
+#ifndef _MSC_VER
+#include <stdint.h> // For SET_UINT_IN_POINTER, i.e. uintptr_t.
+#endif
+#include <vector>
+
+#include "Geom.h"
+#include "GeomUtils.h"
+#include "Polygon.h"
+
+#include "../system/FreestyleConfig.h"
+
+extern "C" {
+ #include "BLI_utildefines.h"
+}
+
+using namespace std;
+using namespace Geometry;
+
+typedef vector<Polygon3r*> OccludersSet;
+
+//
+// Class to define cells used by the regular grid
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class LIB_GEOMETRY_EXPORT Cell
+{
+public:
+ Cell(Vec3r& orig) {
+ _orig = orig;
+ }
+
+ virtual ~Cell() {}
+
+ inline void addOccluder(Polygon3r *o) {
+ if (o)
+ _occluders.push_back(o);
+ }
+
+ inline const Vec3r& getOrigin() {
+ return _orig;
+ }
+
+ inline OccludersSet& getOccluders() {
+ return _occluders;
+ }
+
+private:
+ Vec3r _orig;
+ OccludersSet _occluders;
+};
+
+
+class GridVisitor
+{
+public:
+ virtual ~GridVisitor() {}; //soc
+
+ virtual void discoverCell(Cell *cell) {}
+
+ virtual void examineOccluder(Polygon3r *occ) {}
+
+ virtual void finishCell(Cell *cell) {}
+
+ virtual bool stop() {
+ return false;
+ }
+};
+
+/*! Gathers all the occluders belonging to the cells traversed by the ray */
+class allOccludersGridVisitor : public GridVisitor
+{
+public:
+ allOccludersGridVisitor(OccludersSet& occluders) : GridVisitor(), occluders_(occluders) {}
+
+ virtual void examineOccluder(Polygon3r *occ);
+
+ OccludersSet& occluders() {
+ return occluders_;
+ }
+
+ void clear() {
+ occluders_.clear();
+ }
+
+private:
+ OccludersSet& occluders_;
+};
+
+/*! Finds the first intersection and breaks.
+ * The occluder and the intersection information are stored and accessible.
+ */
+class firstIntersectionGridVisitor : public GridVisitor
+{
+//soc - changed order to remove warnings
+public:
+ double u_, v_, t_;
+
+private:
+ Polygon3r *occluder_;
+ Vec3r ray_org_, ray_dir_, cell_size_;
+ Cell *current_cell_;
+
+public:
+ firstIntersectionGridVisitor(const Vec3r& ray_org, const Vec3r& ray_dir, const Vec3r& cell_size) :
+ GridVisitor(), u_(0), v_(0), t_(DBL_MAX), occluder_(0), ray_org_(ray_org), ray_dir_(ray_dir),
+ cell_size_(cell_size), current_cell_(0)
+ {
+ }
+
+ virtual ~firstIntersectionGridVisitor() {}
+
+ virtual void discoverCell(Cell *cell) {
+ current_cell_ = cell;
+ }
+
+ virtual void examineOccluder(Polygon3r *occ);
+
+ virtual bool stop();
+
+ Polygon3r *occluder() {
+ return occluder_;
+ }
+};
+
+//
+// Class to define a regular grid used for ray casting computations
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class LIB_GEOMETRY_EXPORT Grid
+{
+public:
+ /*! Builds a Grid. Must be followed by a call to configure() */
+ Grid() {}
+
+ virtual ~Grid() {
+ clear();
+ }
+
+ /*! clears the grid
+ * Deletes all the cells, clears the hashtable, resets size, size of cell, number of cells.
+ */
+ virtual void clear();
+
+ /*! Sets the different parameters of the grid
+ * orig
+ * The grid origin
+ * size
+ * The grid's dimensions
+ * nb
+ * The number of cells of the grid
+ */
+ virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
+
+ /*! returns a vector of integer containing the coordinates of the cell containing the point passed as argument
+ * p
+ * The point for which we're looking the cell
+ */
+ inline void getCellCoordinates(const Vec3r& p, Vec3u& res) {
+ int tmp;
+ for (int i = 0; i < 3; i++) {
+ tmp = (int)((p[i] - _orig[i]) / _cell_size[i]);
+ if (tmp < 0)
+ res[i] = 0;
+ else if ((unsigned int)tmp >= _cells_nb[i])
+ res[i] = _cells_nb[i] - 1;
+ else
+ res[i] = tmp;
+ }
+ }
+
+ /*! Fills the case corresponding to coord with the cell */
+ virtual void fillCell(const Vec3u& coord, Cell& cell) = 0;
+
+ /*! returns the cell whose coordinates are pased as argument */
+ virtual Cell *getCell(const Vec3u& coord) = 0;
+
+ /*! returns the cell containing the point passed as argument. If the cell is empty (contains no occluder),
+ * NULL is returned
+ * p
+ * The point for which we're looking the cell
+ */
+ inline Cell *getCell(const Vec3r& p) {
+ Vec3u coord;
+ getCellCoordinates(p, coord);
+ return getCell(coord);
+ }
+
+ /*! Retrieves the x,y,z coordinates of the origin of the cell whose coordinates (i,j,k) is passed as argument
+ * cell_coord
+ * i,j,k integer coordinates for the cell
+ * orig
+ * x,y,x vector to be filled in with the cell origin's coordinates
+ */
+ inline void getCellOrigin(const Vec3u& cell_coord, Vec3r& orig) {
+ for (unsigned int i = 0; i < 3; i++)
+ orig[i] = _orig[i] + cell_coord[i] * _cell_size[i];
+ }
+
+ /*! Retrieves the box corresponding to the cell whose coordinates are passed as argument.
+ * cell_coord
+ * i,j,k integer coordinates for the cell
+ * min_out
+ * The min x,y,x vector of the box. Filled in by the method.
+ * max_out
+ * The max x,y,z coordinates of the box. Filled in by the method.
+ */
+ inline void getCellBox(const Vec3u& cell_coord, Vec3r& min_out, Vec3r& max_out) {
+ getCellOrigin(cell_coord, min_out);
+ max_out = min_out + _cell_size;
+ }
+
+ /*! inserts a convex polygon occluder
+ * This method is quite coarse insofar as it adds all cells intersecting the polygon bounding box
+ * convex_poly
+ * The list of 3D points constituing a convex polygon
+ */
+ void insertOccluder(Polygon3r *convex_poly);
+
+ /*! Adds an occluder to the list of occluders */
+ void addOccluder(Polygon3r *occluder) {
+ _occluders.push_back(occluder);
+ }
+
+ /*! Casts a ray between a starting point and an ending point
+ * Returns the list of occluders contained in the cells intersected by this ray
+ * Starts with a call to InitRay.
+ */
+ void castRay(const Vec3r& orig, const Vec3r& end, OccludersSet& occluders, unsigned timestamp);
+
+ // Prepares to cast ray without generating OccludersSet
+ void initAcceleratedRay(const Vec3r& orig, const Vec3r& end, unsigned timestamp);
+
+ /*! Casts an infinite ray (still finishing at the end of the grid) from a starting point and in a given direction.
+ * Returns the list of occluders contained in the cells intersected by this ray
+ * Starts with a call to InitRay.
+ */
+ void castInfiniteRay(const Vec3r& orig, const Vec3r& dir, OccludersSet& occluders, unsigned timestamp);
+
+ // Prepares to cast ray without generating OccludersSet.
+ bool initAcceleratedInfiniteRay(const Vec3r& orig, const Vec3r& dir, unsigned timestamp);
+
+ /*! Casts an infinite ray (still finishing at the end of the grid) from a starting point and in a given direction.
+ * Returns the first intersection (occluder,t,u,v) or null.
+ * Starts with a call to InitRay.
+ */
+ Polygon3r * castRayToFindFirstIntersection(const Vec3r& orig, const Vec3r& dir, double& t,
+ double& u, double& v, unsigned timestamp);
+
+
+ /*! Init all structures and values for computing the cells intersected by this new ray */
+ void initRay(const Vec3r &orig, const Vec3r& end, unsigned timestamp);
+
+ /*! Init all structures and values for computing the cells intersected by this infinite ray.
+ * Returns false if the ray doesn't intersect the grid.
+ */
+ bool initInfiniteRay(const Vec3r &orig, const Vec3r& dir, unsigned timestamp);
+
+
+ /*! Accessors */
+ inline const Vec3r& getOrigin() const {
+ return _orig;
+ }
+
+ inline Vec3r gridSize() const {
+ return _size;
+ }
+
+ inline Vec3r getCellSize() const {
+ return _cell_size;
+ }
+
+ //ARB profiling only:
+ inline OccludersSet *getOccluders() {
+ return &_occluders;
+ }
+
+ void displayDebug() {
+ cerr << "Cells nb : " << _cells_nb << endl;
+ cerr << "Cell size : " << _cell_size << endl;
+ cerr << "Origin : " << _orig << endl;
+ cerr << "Occluders nb : " << _occluders.size() << endl;
+ }
+
+protected:
+ /*! Core of castRay and castInfiniteRay, find occluders along the given ray */
+ inline void castRayInternal(GridVisitor& visitor) {
+ Cell *current_cell = NULL;
+ do {
+ current_cell = getCell(_current_cell);
+ if (current_cell) {
+ visitor.discoverCell(current_cell);
+ OccludersSet& occluders = current_cell->getOccluders(); // FIXME: I had forgotten the ref &
+ for (OccludersSet::iterator it = occluders.begin(); it != occluders.end(); it++) {
+ if (GET_UINT_FROM_POINTER((*it)->userdata2) != _timestamp) {
+ (*it)->userdata2 = SET_UINT_IN_POINTER(_timestamp);
+ visitor.examineOccluder(*it);
+ }
+ }
+ visitor.finishCell(current_cell);
+ }
+ } while ((!visitor.stop()) && (nextRayCell(_current_cell, _current_cell)));
+ }
+
+
+ /*! returns the cell next to the cell passed as argument. */
+ bool nextRayCell(Vec3u& current_cell, Vec3u& next_cell);
+
+ unsigned int _timestamp;
+
+ Vec3u _cells_nb; // number of cells for x,y,z axis
+ Vec3r _cell_size; // cell x,y,z dimensions
+ Vec3r _size; // grid x,y,x dimensions
+ Vec3r _orig; // grid origin
+
+ Vec3r _ray_dir; // direction vector for the ray
+ Vec3u _current_cell; // The current cell being processed (designated by its 3 coordinates)
+ Vec3r _pt; // Points corresponding to the incoming and outgoing intersections of one cell with the ray
+ real _t_end; // To know when we are at the end of the ray
+ real _t;
+
+ //OccludersSet _ray_occluders; // Set storing the occluders contained in the cells traversed by a ray
+ OccludersSet _occluders; // List of all occluders inserted in the grid
+};
+
+//
+// Class to walk through occluders in grid without building intermediate data structures
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class VirtualOccludersSet {
+public:
+ VirtualOccludersSet(Grid& _grid) : grid (_grid) {};
+ Polygon3r *begin();
+ Polygon3r *next();
+ Polygon3r *next(bool stopOnNewCell);
+
+private:
+ Polygon3r *firstOccluderFromNextCell();
+ Grid& grid;
+ OccludersSet::iterator it, end;
+};
+
+#endif // __GRID_H__
diff --git a/source/blender/freestyle/intern/geometry/GridHelpers.cpp b/source/blender/freestyle/intern/geometry/GridHelpers.cpp
new file mode 100644
index 00000000000..055a47f6bd5
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/GridHelpers.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/geometry/GridHelpers.cpp
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2010-12-21
+ */
+
+#include <math.h>
+
+#include "GridHelpers.h"
+
+void GridHelpers::getDefaultViewProscenium(real viewProscenium[4])
+{
+ // Get proscenium boundary for culling
+ // bufferZone determines the amount by which the area processed should exceed the actual image area.
+ // This is intended to avoid visible artifacts generated along the proscenium edge.
+ // Perhaps this is no longer needed now that entire view edges are culled at once, since that theoretically
+ // should eliminate visible artifacts.
+ // To the extent it is still useful, bufferZone should be put into the UI as configurable percentage value
+ const real bufferZone = 0.05;
+ // borderZone describes a blank border outside the proscenium, but still inside the image area.
+ // Only intended for exposing possible artifacts along or outside the proscenium edge during debugging.
+ const real borderZone = 0.0;
+ viewProscenium[0] = freestyle_viewport[2] * (borderZone - bufferZone);
+ viewProscenium[1] = freestyle_viewport[2] * (1.0f - borderZone + bufferZone);
+ viewProscenium[2] = freestyle_viewport[3] * (borderZone - bufferZone);
+ viewProscenium[3] = freestyle_viewport[3] * (1.0f - borderZone + bufferZone);
+}
+
+GridHelpers::Transform::~Transform ()
+{
+}
diff --git a/source/blender/freestyle/intern/geometry/GridHelpers.h b/source/blender/freestyle/intern/geometry/GridHelpers.h
new file mode 100644
index 00000000000..2503cb2ebbd
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/GridHelpers.h
@@ -0,0 +1,215 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __GRIDHELPERS_H__
+#define __GRIDHELPERS_H__
+
+/** \file blender/freestyle/intern/geometry/GridHelpers.h
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2010-12-13
+ */
+
+#include <vector>
+
+#include "FRS_freestyle.h"
+
+#include "GeomUtils.h"
+#include "Polygon.h"
+
+#include "../winged_edge/WEdge.h"
+
+namespace GridHelpers {
+
+/*! Computes the distance from a point P to a segment AB */
+template<class T>
+T closestPointToSegment(const T& P, const T& A, const T& B, real& distance)
+{
+ T AB, AP, BP;
+ AB = B - A;
+ AP = P - A;
+ BP = P - B;
+
+ real c1(AB * AP);
+ if (c1 <= 0) {
+ distance = AP.norm();
+ return A; // A is closest point
+ }
+
+ real c2(AB * AB);
+ if (c2 <= c1) {
+ distance = BP.norm();
+ return B; // B is closest point
+ }
+
+ real b = c1 / c2;
+ T Pb, PPb;
+ Pb = A + b * AB;
+ PPb = P - Pb;
+
+ distance = PPb.norm();
+ return Pb; // closest point lies on AB
+}
+
+inline Vec3r closestPointOnPolygon(const Vec3r& point, const Polygon3r& poly)
+{
+ // First cast a ray from the point onto the polygon plane
+ // If the ray intersects the polygon, then the intersection point
+ // is the closest point on the polygon
+ real t, u, v;
+ if (poly.rayIntersect(point, poly.getNormal(), t, u, v)) {
+ return point + poly.getNormal() * t;
+ }
+
+ // Otherwise, get the nearest point on each edge, and take the closest
+ real distance;
+ Vec3r closest = closestPointToSegment(point, poly.getVertices()[2], poly.getVertices()[0], distance);
+ for (unsigned int i = 0; i < 2; ++i) {
+ real t;
+ Vec3r p = closestPointToSegment(point, poly.getVertices()[i], poly.getVertices()[i + 1], t);
+ if (t < distance) {
+ distance = t;
+ closest = p;
+ }
+ }
+ return closest;
+}
+
+inline real distancePointToPolygon(const Vec3r& point, const Polygon3r& poly)
+{
+ // First cast a ray from the point onto the polygon plane
+ // If the ray intersects the polygon, then the intersection point
+ // is the closest point on the polygon
+ real t, u, v;
+ if (poly.rayIntersect(point, poly.getNormal(), t, u, v)) {
+ return (t > 0.0) ? t : -t;
+ }
+
+ // Otherwise, get the nearest point on each edge, and take the closest
+ real distance = GeomUtils::distPointSegment(point, poly.getVertices()[2], poly.getVertices()[0]);
+ for (unsigned int i = 0; i < 2; ++i) {
+ real t = GeomUtils::distPointSegment(point, poly.getVertices()[i], poly.getVertices()[i + 1]);
+ if (t < distance) {
+ distance = t;
+ }
+ }
+ return distance;
+}
+
+class Transform
+{
+public:
+ virtual ~Transform () = 0;
+ virtual Vec3r operator()(const Vec3r& point) const = 0;
+};
+
+inline bool insideProscenium (const real proscenium[4], const Polygon3r& polygon)
+{
+ // N.B. The bounding box check is redundant for inserting occluders into cells, because the cell selection code
+ // in insertOccluders has already guaranteed that the bounding boxes will overlap.
+ // First check the viewport edges, since they are the easiest case
+ // Check if the bounding box is entirely outside the proscenium
+ Vec3r bbMin, bbMax;
+ polygon.getBBox(bbMin, bbMax);
+ if (bbMax[0] < proscenium[0] || bbMin[0] > proscenium[1] || bbMax[1] < proscenium[2] || bbMin[1] > proscenium[3]) {
+ return false;
+ }
+
+ Vec3r boxCenter(proscenium[0] + (proscenium[1] - proscenium[0]) / 2.0,
+ proscenium[2] + (proscenium[3] - proscenium[2]) / 2.0, 0.0);
+ Vec3r boxHalfSize((proscenium[1] - proscenium[0]) / 2.0,
+ (proscenium[3] - proscenium[2]) / 2.0, 1.0);
+ Vec3r triverts[3] = {
+ Vec3r(polygon.getVertices()[0][0], polygon.getVertices()[0][1], 0.0),
+ Vec3r(polygon.getVertices()[1][0], polygon.getVertices()[1][1], 0.0),
+ Vec3r(polygon.getVertices()[2][0], polygon.getVertices()[2][1], 0.0)
+ };
+ return GeomUtils::overlapTriangleBox(boxCenter, boxHalfSize, triverts);
+}
+
+inline vector<Vec3r> enumerateVertices(const vector<WOEdge*>& fedges)
+{
+ vector<Vec3r> points;
+ // Iterate over vertices, storing projections in points
+ for (vector<WOEdge*>::const_iterator woe = fedges.begin(), woend = fedges.end(); woe != woend; woe++) {
+ points.push_back((*woe)->GetaVertex()->GetVertex());
+ }
+
+ return points;
+}
+
+void getDefaultViewProscenium(real viewProscenium[4]);
+
+inline void expandProscenium (real proscenium[4], const Polygon3r& polygon)
+{
+ Vec3r bbMin, bbMax;
+ polygon.getBBox(bbMin, bbMax);
+
+ const real epsilon = 1.0e-6;
+
+ if (bbMin[0] <= proscenium[0]) {
+ proscenium[0] = bbMin[0] - epsilon;
+ }
+
+ if (bbMin[1] <= proscenium[2]) {
+ proscenium[2] = bbMin[1] - epsilon;
+ }
+
+ if (bbMax[0] >= proscenium[1]) {
+ proscenium[1] = bbMax[0] + epsilon;
+ }
+
+ if (bbMax[1] >= proscenium[3]) {
+ proscenium[3] = bbMax[1] + epsilon;
+ }
+}
+
+inline void expandProscenium (real proscenium[4], const Vec3r& point)
+{
+ const real epsilon = 1.0e-6;
+
+ if (point[0] <= proscenium[0]) {
+ proscenium[0] = point[0] - epsilon;
+ }
+
+ if (point[1] <= proscenium[2]) {
+ proscenium[2] = point[1] - epsilon;
+ }
+
+ if (point[0] >= proscenium[1]) {
+ proscenium[1] = point[0] + epsilon;
+ }
+
+ if (point[1] >= proscenium[3]) {
+ proscenium[3] = point[1] + epsilon;
+ }
+}
+
+}; // GridHelpers namespace
+
+#endif // __GRIDHELPERS_H__
diff --git a/source/blender/freestyle/intern/geometry/HashGrid.cpp b/source/blender/freestyle/intern/geometry/HashGrid.cpp
new file mode 100644
index 00000000000..3752fc2f32a
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/HashGrid.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/geometry/HashGrid.cpp
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the bounding box of the scene
+ * \author Stephane Grabli
+ * \date 30/07/2002
+ */
+
+#include "HashGrid.h"
+
+void HashGrid::clear()
+{
+ if (!_cells.empty()) {
+ for (GridHashTable::iterator it = _cells.begin(); it != _cells.end(); it++) {
+ Cell *cell = (*it).second;
+ delete cell;
+ }
+ _cells.clear();
+ }
+
+ Grid::clear();
+}
+
+void HashGrid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb)
+{
+ Grid::configure(orig, size, nb);
+}
diff --git a/source/blender/freestyle/intern/geometry/HashGrid.h b/source/blender/freestyle/intern/geometry/HashGrid.h
new file mode 100644
index 00000000000..ea44196b523
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/HashGrid.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __HASHGRID_H__
+#define __HASHGRID_H__
+
+/** \file blender/freestyle/intern/geometry/HashGrid.h
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the bounding box of the scene
+ * \author Stephane Grabli
+ * \date 30/07/2002
+ */
+
+#if 0
+# if defined(__GNUC__) && (__GNUC__ >= 3)
+// hash_map is not part of the C++ standard anymore;
+// hash_map.h has been kept though for backward compatibility
+# include <hash_map.h>
+# else
+# include <hash_map>
+# endif
+#endif
+
+#include <map>
+
+#include "Grid.h"
+
+/*! Defines a hash table used for searching the Cells */
+struct GridHasher
+{
+#define _MUL 950706376UL
+#define _MOD 2147483647UL
+ inline size_t operator() (const Vec3u& p) const
+ {
+ size_t res = ((unsigned long) (p[0] * _MUL)) % _MOD;
+ res = ((res + (unsigned long) (p[1]) * _MUL)) % _MOD;
+ return ((res +(unsigned long) (p[2]) * _MUL)) % _MOD;
+ }
+#undef _MUL
+#undef _MOD
+};
+
+/*! Class to define a regular grid used for ray casting computations */
+class LIB_GEOMETRY_EXPORT HashGrid : public Grid
+{
+public:
+ typedef map<Vec3u, Cell*> GridHashTable;
+
+ HashGrid() : Grid() {}
+
+ virtual ~HashGrid()
+ {
+ clear();
+ }
+
+ /*! clears the grid
+ * Deletes all the cells, clears the hashtable, resets size, size of cell, number of cells.
+ */
+ virtual void clear();
+
+ /*! Sets the different parameters of the grid
+ * orig
+ * The grid origin
+ * size
+ * The grid's dimensions
+ * nb
+ * The number of cells of the grid
+ */
+ virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
+
+ /*! returns the cell whose coordinates are pased as argument */
+ virtual Cell *getCell(const Vec3u& p)
+ {
+ Cell *found_cell = NULL;
+
+ GridHashTable::const_iterator found = _cells.find(p);
+ if (found != _cells.end())
+ found_cell = (*found).second;
+ return found_cell;
+ }
+
+ /*! Fills the case p with the cell iCell */
+ virtual void fillCell(const Vec3u& p, Cell& cell)
+ {
+ _cells[p] = &cell;
+ }
+
+protected:
+ GridHashTable _cells;
+};
+
+#endif // __HASHGRID_H__
diff --git a/source/blender/freestyle/intern/geometry/Noise.cpp b/source/blender/freestyle/intern/geometry/Noise.cpp
new file mode 100644
index 00000000000..0769664fcbb
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Noise.cpp
@@ -0,0 +1,285 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/geometry/Noise.cpp
+ * \ingroup freestyle
+ * \brief Class to define Perlin noise
+ * \author Emmanuel Turquin
+ * \date 12/01/2004
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "Noise.h"
+
+#define MINX -1000000
+#define MINY MINX
+#define MINZ MINX
+
+#define SCURVE(a) ((a) * (a) * (3.0 - 2.0 * (a)))
+
+#define REALSCALE (2.0 / 65536.0)
+#define NREALSCALE (2.0 / 4096.0)
+
+#define HASH3D(a, b, c) hashTable[hashTable[hashTable[(a) & 0xfff] ^ ((b) & 0xfff)] ^ ((c) & 0xfff)]
+#define HASH(a, b, c) (xtab[(xtab[(xtab[(a) & 0xff] ^ (b)) & 0xff] ^ (c)) & 0xff] & 0xff)
+
+#define INCRSUM(m, s, x, y, z) \
+ ((s) * (RTable[m] * 0.5 + RTable[m + 1] * (x) + RTable[m + 2] * (y) + RTable[m + 3] * (z)))
+
+#define MAXSIZE 500
+
+#if 0 // XXX Unused
+#define NRAND() ((float)rand() / (float)RAND_MAX)
+#endif
+#define SEEDNRAND(x) (srand(x * RAND_MAX))
+
+#define BM 0xff
+#define N 0x1000
+#define NP 12 /* 2^N */
+#define NM 0xfff
+
+#define LERP(t, a, b) ((a) + (t) * ((b) - (a)))
+
+#define SETUP(i, b0, b1, r0, r1) \
+ { \
+ (t) = (i) + (N); \
+ (b0) = ((int)(t)) & BM; \
+ (b1) = ((b0) + 1) & BM; \
+ (r0) = (t) - (int)(t); \
+ (r1) = (r0) - 1.0; \
+ } (void)0
+
+static void normalize2(float v[2])
+{
+ float s;
+
+ s = sqrt(v[0] * v[0] + v[1] * v[1]);
+ v[0] = v[0] / s;
+ v[1] = v[1] / s;
+}
+
+static void normalize3(float v[3])
+{
+ float s;
+
+ s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
+ v[0] = v[0] / s;
+ v[1] = v[1] / s;
+ v[2] = v[2] / s;
+}
+
+float Noise::turbulence1(float arg, float freq, float amp, unsigned oct)
+{
+ float t;
+ float vec;
+
+ for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct) {
+ vec = freq * arg;
+ t += smoothNoise1(vec) * amp;
+ }
+ return t;
+}
+
+float Noise::turbulence2(Vec2f& v, float freq, float amp, unsigned oct)
+{
+ float t;
+ Vec2f vec;
+
+ for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct) {
+ vec.x() = freq * v.x();
+ vec.y() = freq * v.y();
+ t += smoothNoise2(vec) * amp;
+ }
+ return t;
+}
+
+float Noise::turbulence3(Vec3f& v, float freq, float amp, unsigned oct)
+{
+ float t;
+ Vec3f vec;
+
+ for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct) {
+ vec.x() = freq * v.x();
+ vec.y() = freq * v.y();
+ vec.z() = freq * v.z();
+ t += smoothNoise3(vec) * amp;
+ }
+ return t;
+}
+
+// Noise functions over 1, 2, and 3 dimensions
+float Noise::smoothNoise1(float arg)
+{
+ int bx0, bx1;
+ float rx0, rx1, sx, t, u, v, vec;
+
+ vec = arg;
+ SETUP(vec, bx0, bx1, rx0, rx1);
+
+ sx = SCURVE(rx0);
+
+ u = rx0 * g1[p[bx0]];
+ v = rx1 * g1[p[bx1]];
+
+ return LERP(sx, u, v);
+}
+
+float Noise::smoothNoise2(Vec2f& vec)
+{
+ int bx0, bx1, by0, by1, b00, b10, b01, b11;
+ float rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
+ register int i, j;
+
+ SETUP(vec.x(), bx0, bx1, rx0, rx1);
+ SETUP(vec.y(), by0, by1, ry0, ry1);
+
+ i = p[bx0];
+ j = p[bx1];
+
+ b00 = p[i + by0];
+ b10 = p[j + by0];
+ b01 = p[i + by1];
+ b11 = p[j + by1];
+
+ sx = SCURVE(rx0);
+ sy = SCURVE(ry0);
+
+#define AT2(rx, ry) ((rx) * q[0] + (ry) * q[1])
+
+ q = g2[b00];
+ u = AT2(rx0, ry0);
+ q = g2[b10];
+ v = AT2(rx1, ry0);
+ a = LERP(sx, u, v);
+
+ q = g2[b01];
+ u = AT2(rx0, ry1);
+ q = g2[b11];
+ v = AT2(rx1, ry1);
+ b = LERP(sx, u, v);
+
+#undef AT2
+
+ return LERP(sy, a, b);
+}
+
+float Noise::smoothNoise3(Vec3f& vec)
+{
+ int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
+ float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
+ register int i, j;
+
+ SETUP(vec.x(), bx0, bx1, rx0, rx1);
+ SETUP(vec.y(), by0, by1, ry0, ry1);
+ SETUP(vec.z(), bz0, bz1, rz0, rz1);
+
+ i = p[bx0];
+ j = p[bx1];
+
+ b00 = p[i + by0];
+ b10 = p[j + by0];
+ b01 = p[i + by1];
+ b11 = p[j + by1];
+
+ t = SCURVE(rx0);
+ sy = SCURVE(ry0);
+ sz = SCURVE(rz0);
+
+#define AT3(rx, ry, rz) ((rx) * q[0] + (ry) * q[1] + (rz) * q[2])
+
+ q = g3[b00 + bz0];
+ u = AT3(rx0, ry0, rz0);
+ q = g3[b10 + bz0];
+ v = AT3(rx1, ry0, rz0);
+ a = LERP(t, u, v);
+
+ q = g3[b01 + bz0];
+ u = AT3(rx0, ry1, rz0);
+ q = g3[b11 + bz0];
+ v = AT3(rx1, ry1, rz0);
+ b = LERP(t, u, v);
+
+ c = LERP(sy, a, b);
+
+ q = g3[b00 + bz1];
+ u = AT3(rx0, ry0, rz1);
+ q = g3[b10 + bz1];
+ v = AT3(rx1, ry0, rz1);
+ a = LERP(t, u, v);
+
+ q = g3[b01 + bz1];
+ u = AT3(rx0, ry1, rz1);
+ q = g3[b11 + bz1];
+ v = AT3(rx1, ry1, rz1);
+ b = LERP(t, u, v);
+
+ d = LERP(sy, a, b);
+
+#undef AT3
+
+ return LERP(sz, c, d);
+}
+
+Noise::Noise(long seed)
+{
+ int i, j, k;
+
+ SEEDNRAND((seed < 0) ? time(NULL) : seed);
+ for (i = 0 ; i < _NOISE_B ; i++) {
+ p[i] = i;
+ g1[i] = (float)((rand() % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B;
+
+ for (j = 0 ; j < 2 ; j++)
+ g2[i][j] = (float)((rand() % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B;
+ normalize2(g2[i]);
+
+ for (j = 0 ; j < 3 ; j++)
+ g3[i][j] = (float)((rand() % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B;
+ normalize3(g3[i]);
+ }
+
+ while (--i) {
+ k = p[i];
+ p[i] = p[j = rand() % _NOISE_B];
+ p[j] = k;
+ }
+
+ for (i = 0 ; i < _NOISE_B + 2 ; i++) {
+ p[_NOISE_B + i] = p[i];
+ g1[_NOISE_B + i] = g1[i];
+
+ for (j = 0 ; j < 2 ; j++)
+ g2[_NOISE_B + i][j] = g2[i][j];
+
+ for (j = 0 ; j < 3 ; j++)
+ g3[_NOISE_B + i][j] = g3[i][j];
+ }
+}
diff --git a/source/blender/freestyle/intern/geometry/Noise.h b/source/blender/freestyle/intern/geometry/Noise.h
new file mode 100644
index 00000000000..35d1af3712f
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Noise.h
@@ -0,0 +1,83 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __NOISE_H__
+#define __NOISE_H__
+
+/** \file blender/freestyle/intern/geometry/Noise.h
+ * \ingroup freestyle
+ * \brief Class to define Perlin noise
+ * \author Emmanuel Turquin
+ * \date 12/01/2004
+ */
+
+#include "Geom.h"
+
+#include "../system/FreestyleConfig.h"
+
+#define _NOISE_B 0x100
+
+using namespace Geometry;
+using namespace std;
+
+/*! Class to provide Perlin Noise functionalities */
+class LIB_GEOMETRY_EXPORT Noise
+{
+public:
+ /*! Builds a Noise object */
+ Noise(long seed = -1);
+
+ /*! Destructor */
+ ~Noise() {}
+
+ /*! Returns a noise value for a 1D element */
+ float turbulence1(float arg, float freq, float amp, unsigned oct = 4);
+
+ /*! Returns a noise value for a 2D element */
+ float turbulence2(Vec2f& v, float freq, float amp, unsigned oct = 4);
+
+ /*! Returns a noise value for a 3D element */
+ float turbulence3(Vec3f& v, float freq, float amp, unsigned oct = 4);
+
+ /*! Returns a smooth noise value for a 1D element */
+ float smoothNoise1(float arg);
+
+ /*! Returns a smooth noise value for a 2D element */
+ float smoothNoise2(Vec2f& vec);
+
+ /*! Returns a smooth noise value for a 3D element */
+ float smoothNoise3(Vec3f& vec);
+
+private:
+ int p[_NOISE_B + _NOISE_B + 2];
+ float g3[_NOISE_B + _NOISE_B + 2][3];
+ float g2[_NOISE_B + _NOISE_B + 2][2];
+ float g1[_NOISE_B + _NOISE_B + 2];
+ int start;
+};
+
+#endif // __NOISE_H__
diff --git a/source/blender/freestyle/intern/geometry/Polygon.h b/source/blender/freestyle/intern/geometry/Polygon.h
new file mode 100644
index 00000000000..e217a67b03e
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Polygon.h
@@ -0,0 +1,221 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __POLYGON_H__
+#define __POLYGON_H__
+
+/** \file blender/freestyle/intern/geometry/Polygon.h
+ * \ingroup freestyle
+ * \brief Class to define a polygon
+ * \author Stephane Grabli
+ * \date 30/07/2002
+ */
+
+#include <vector>
+
+#include "Geom.h"
+#include "GeomUtils.h"
+
+using namespace std;
+
+namespace Geometry {
+
+template <class Point>
+class Polygon
+{
+public:
+ inline Polygon()
+ {
+ _id = 0;
+ userdata = 0;
+ userdata2 = 0;
+ }
+
+ inline Polygon(const vector<Point>& vertices)
+ {
+ _vertices = vertices;
+ computeBBox();
+ _id = 0;
+ userdata = 0;
+ userdata2 = 0;
+ }
+
+ inline Polygon(const Polygon<Point>& poly)
+ {
+ Point p;
+ for (typename vector<Point>::const_iterator it = poly.getVertices().begin();
+ it != poly.getVertices().end();
+ it++)
+ {
+ p = *it;
+ _vertices.push_back(p);
+ }
+
+ _id = poly.getId();
+ poly.getBBox(_min, _max);
+ userdata = 0;
+ userdata2 = 0;
+ }
+
+ virtual ~Polygon() {}
+
+ //
+ // Accessors
+ //
+ /////////////////////////////////////////////////////////////////////////////
+ inline const vector<Point>& getVertices() const
+ {
+ return _vertices;
+ }
+
+ inline void getBBox(Point& min, Point& max) const
+ {
+ min = _min;
+ max = _max;
+ }
+
+ inline Point& getBBoxCenter()
+ {
+ Point result;
+ result = (_min + _max) / 2;
+ return result;
+ }
+
+ inline Point& getCenter()
+ {
+ Point result;
+ for (typename vector<Point>::iterator it = _vertices.begin(); it != _vertices.end(); it++)
+ result += *it;
+ result /= _vertices.size();
+ return result;
+ }
+
+ inline unsigned getId() const
+ {
+ return _id;
+ }
+
+ //
+ // Modifiers
+ //
+ /////////////////////////////////////////////////////////////////////////////
+ inline void setVertices(const vector<Point>& vertices)
+ {
+ _vertices.clear();
+ Point p;
+ for (typename vector<Point>::const_iterator it = vertices.begin(); it != vertices.end(); it++) {
+ p = *it;
+ _vertices.push_back(p);
+ }
+ computeBBox();
+ }
+
+ inline void setId(unsigned id)
+ {
+ _id = id;
+ }
+
+ //
+ // Other methods
+ //
+ /////////////////////////////////////////////////////////////////////////////
+ inline void computeBBox()
+ {
+ if (_vertices.empty())
+ return;
+
+ _max = _vertices[0];
+ _min = _vertices[0];
+
+ for (typename vector<Point>::iterator it = _vertices.begin(); it != _vertices.end(); it++) {
+ for (unsigned int i = 0; i < Point::dim(); i++) {
+ if ((*it)[i] > _max[i])
+ _max[i] = (*it)[i];
+ if ((*it)[i] < _min[i])
+ _min[i] = (*it)[i];
+ }
+ }
+ }
+
+ // FIXME Is it possible to get rid of userdatas ?
+ void *userdata;
+ void *userdata2; // Used during ray casting
+
+protected:
+ vector<Point> _vertices;
+ Point _min;
+ Point _max;
+ unsigned _id;
+};
+
+
+//
+// Polygon3r class
+//
+///////////////////////////////////////////////////////////////////////////////
+class Polygon3r : public Polygon<Vec3r>
+{
+public:
+ inline Polygon3r() : Polygon<Vec3r>() {}
+
+ inline Polygon3r(const vector<Vec3r>& vertices, const Vec3r& normal) : Polygon<Vec3r>(vertices)
+ {
+ setNormal(normal);
+ }
+
+ inline Polygon3r(const Polygon3r& poly) : Polygon<Vec3r>(poly), _normal(poly._normal) {}
+
+ virtual ~Polygon3r() {}
+
+ void setNormal(const Vec3r& normal)
+ {
+ _normal = normal;
+ }
+
+ inline Vec3r getNormal() const
+ {
+ return _normal;
+ }
+
+ /*! Check whether the Polygon intersects with the ray or not */
+ inline bool rayIntersect(const Vec3r& orig, const Vec3r& dir, real& t, real& u, real& v,
+ real epsilon = M_EPSILON) const
+ {
+#if 0
+ if (_vertices.size() < 3)
+ return false;
+#endif
+ return GeomUtils::intersectRayTriangle(orig, dir, _vertices[0], _vertices[1], _vertices[2], t, u, v, epsilon);
+ }
+
+private:
+ Vec3r _normal;
+};
+
+} // end of namespace Geometry
+
+#endif // __POLYGON_H__
diff --git a/source/blender/freestyle/intern/geometry/SweepLine.h b/source/blender/freestyle/intern/geometry/SweepLine.h
new file mode 100644
index 00000000000..d03bc2224c7
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/SweepLine.h
@@ -0,0 +1,332 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __SWEEPLINE_H__
+#define __SWEEPLINE_H__
+
+/** \file blender/freestyle/intern/geometry/SweepLine.h
+ * \ingroup freestyle
+ * \brief Class to define a Sweep Line
+ * \author Stephane Grabli
+ * \date 29/08/2002
+ */
+
+#include <list>
+#include <vector>
+
+/*! Class to define the intersection berween two segments*/
+template<class Edge>
+class Intersection
+{
+public:
+ template<class EdgeClass>
+ Intersection(EdgeClass *eA, real ta, EdgeClass *eB, real tb)
+ {
+ EdgeA = eA;
+ EdgeB = eB;
+ tA = ta;
+ tB = tb;
+ userdata = 0;
+ }
+
+ Intersection(const Intersection& iBrother)
+ {
+ EdgeA = iBrother.EdgeA;
+ EdgeB = iBrother.EdgeB;
+ tA = iBrother.tA;
+ tB = iBrother.tB;
+ userdata = 0;
+ }
+
+ /*! returns the parameter giving the intersection, for the edge iEdge */
+ real getParameter(Edge *iEdge)
+ {
+ if (iEdge == EdgeA)
+ return tA;
+ if (iEdge == EdgeB)
+ return tB;
+ return 0;
+ }
+
+public:
+ void * userdata; // FIXME
+
+ Edge *EdgeA; // first segment
+ Edge *EdgeB; // second segment
+ real tA; // parameter defining the intersection point with respect to the segment EdgeA.
+ real tB; // parameter defining the intersection point with respect to the segment EdgeB.
+};
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4521) // disable warning C4521: multiple copy constructors specified
+#endif
+
+template<class T, class Point>
+class Segment
+{
+public:
+ Segment()
+ {
+ }
+
+ Segment(T& s, const Point& iA, const Point& iB)
+ {
+ _edge = s;
+ if (iA < iB) {
+ A = iA;
+ B = iB;
+ _order = true;
+ }
+ else {
+ A = iB;
+ B = iA;
+ _order = false;
+ }
+ }
+
+ Segment(Segment<T, Point>& iBrother)
+ {
+ _edge = iBrother.edge();
+ A = iBrother.A;
+ B = iBrother.B;
+ _Intersections = iBrother._Intersections;
+ _order = iBrother._order;
+ }
+
+ Segment(const Segment<T, Point>& iBrother)
+ {
+ _edge = iBrother._edge;
+ A = iBrother.A;
+ B = iBrother.B;
+ _Intersections = iBrother._Intersections;
+ _order = iBrother._order;
+ }
+
+ ~Segment()
+ {
+ _Intersections.clear();
+ }
+
+ inline Point operator[](const unsigned short int& i) const
+ {
+ return (i % 2 == 0) ? A : B;
+ }
+
+ inline bool operator==(const Segment<T, Point>& iBrother)
+ {
+ if (_edge == iBrother._edge)
+ return true;
+ return false;
+ }
+
+ /* Adds an intersection for this segment */
+ inline void AddIntersection(Intersection<Segment<T, Point> > *i)
+ {
+ _Intersections.push_back(i);
+ }
+
+ /*! Checks for a common vertex with another edge */
+ inline bool CommonVertex(const Segment<T, Point>& S, Point& CP)
+ {
+ if ((A == S[0]) || (A == S[1])) {
+ CP = A;
+ return true;
+ }
+ if ((B == S[0]) || (B == S[1])) {
+ CP = B;
+ return true;
+ }
+ return false;
+ }
+
+ inline vector<Intersection<Segment<T, Point> >*>& intersections()
+ {
+ return _Intersections;
+ }
+
+ inline bool order()
+ {
+ return _order;
+ }
+
+ inline T& edge()
+ {
+ return _edge;
+ }
+
+private:
+ T _edge;
+ Point A;
+ Point B;
+ std::vector<Intersection<Segment<T, Point> >*> _Intersections; // list of intersections parameters
+ bool _order; // true if A and B are in the same order than _edge.A and _edge.B. false otherwise.
+};
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+/*! defines a binary function that can be overload by the user to specify at each condition the intersection
+ * between 2 edges must be computed
+ */
+template<class T1, class T2>
+struct binary_rule
+{
+ binary_rule() {}
+ template<class T3, class T4> binary_rule(const binary_rule<T3, T4>& brother) {}
+ virtual ~binary_rule() {}
+
+ virtual bool operator()(T1&, T2&)
+ {
+ return true;
+ }
+};
+
+
+template<class T, class Point>
+class SweepLine
+{
+public:
+ SweepLine() {}
+ ~SweepLine()
+ {
+ for (typename vector<Intersection<Segment<T, Point> >*>::iterator i = _Intersections.begin(),
+ iend = _Intersections.end();
+ i != iend;
+ i++)
+ {
+ delete (*i);
+ }
+ }
+
+ inline void process(Point& p, vector<Segment<T, Point>*>& segments,
+#if 0
+ binary_rule<Segment<T, Point>,Segment<T, Point> >& binrule = \
+ binary_rule<Segment<T, Point>, Segment<T, Point> >(),
+#else
+ binary_rule<Segment<T, Point>, Segment<T, Point> >& binrule,
+#endif
+ real epsilon = M_EPSILON)
+ {
+ // first we remove the segments that need to be removed and then we add the segments to add
+ vector<Segment<T, Point>*> toadd;
+ typename vector<Segment<T, Point>*>::iterator s, send;
+ for (s = segments.begin(), send = segments.end(); s != send; s++) {
+ if (p == (*(*s))[0])
+ toadd.push_back((*s));
+ else
+ remove((*s));
+ }
+ for (s = toadd.begin(), send = toadd.end(); s != send; s++) {
+ add((*s), binrule, epsilon);
+ }
+ }
+
+ inline void add(Segment<T, Point> *S,
+#if 0
+ binary_rule<Segment<T, Point>, Segment<T, Point> >& binrule = \
+ binary_rule<Segment<T, Point>, Segment<T, Point> >(),
+#else
+ binary_rule<Segment<T, Point>, Segment<T, Point> >& binrule,
+#endif
+ real epsilon)
+ {
+ real t, u;
+ Point CP;
+ Vec2r v0, v1, v2, v3;
+ if (true == S->order()) {
+ v0[0] = ((*S)[0])[0];
+ v0[1] = ((*S)[0])[1];
+ v1[0] = ((*S)[1])[0];
+ v1[1] = ((*S)[1])[1];
+ }
+ else {
+ v1[0] = ((*S)[0])[0];
+ v1[1] = ((*S)[0])[1];
+ v0[0] = ((*S)[1])[0];
+ v0[1] = ((*S)[1])[1];
+ }
+ for (typename std::list<Segment<T, Point> *>::iterator s = _set.begin(), send = _set.end(); s != send; s++) {
+ Segment<T, Point> *currentS = (*s);
+ if (true != binrule(*S, *currentS))
+ continue;
+
+ if (true == currentS->order()) {
+ v2[0] = ((*currentS)[0])[0];
+ v2[1] = ((*currentS)[0])[1];
+ v3[0] = ((*currentS)[1])[0];
+ v3[1] = ((*currentS)[1])[1];
+ }
+ else {
+ v3[0] = ((*currentS)[0])[0];
+ v3[1] = ((*currentS)[0])[1];
+ v2[0] = ((*currentS)[1])[0];
+ v2[1] = ((*currentS)[1])[1];
+ }
+ if (S->CommonVertex(*currentS, CP))
+ continue; // the two edges have a common vertex->no need to check
+
+ if (GeomUtils::intersect2dSeg2dSegParametric(v0, v1, v2, v3, t, u, epsilon) == GeomUtils::DO_INTERSECT) {
+ // create the intersection
+ Intersection<Segment<T, Point> > *inter = new Intersection<Segment<T, Point> >(S, t, currentS, u);
+ // add it to the intersections list
+ _Intersections.push_back(inter);
+ // add this intersection to the first edge intersections list
+ S->AddIntersection(inter);
+ // add this intersection to the second edge intersections list
+ currentS->AddIntersection(inter);
+ }
+ }
+ // add the added segment to the list of active segments
+ _set.push_back(S);
+ }
+
+ inline void remove(Segment<T, Point> *s)
+ {
+ if (s->intersections().size() > 0)
+ _IntersectedEdges.push_back(s);
+ _set.remove(s);
+ }
+
+ vector<Segment<T, Point> *>& intersectedEdges()
+ {
+ return _IntersectedEdges;
+ }
+
+ vector<Intersection<Segment<T, Point> >*>& intersections()
+ {
+ return _Intersections;
+ }
+
+private:
+ std::list<Segment<T, Point> *> _set; // set of active edges for a given position of the sweep line
+ std::vector<Segment<T, Point> *> _IntersectedEdges; // the list of intersected edges
+ std::vector<Intersection<Segment<T, Point> > *> _Intersections; // the list of all intersections.
+};
+
+#endif // __SWEEPLINE_H__
diff --git a/source/blender/freestyle/intern/geometry/VecMat.h b/source/blender/freestyle/intern/geometry/VecMat.h
new file mode 100644
index 00000000000..34e10d31c4f
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/VecMat.h
@@ -0,0 +1,977 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __VECMAT_H__
+#define __VECMAT_H__
+
+/** \file blender/freestyle/intern/geometry/VecMat.h
+ * \ingroup freestyle
+ * \brief Vectors and Matrices definition and manipulation
+ * \author Sylvain Paris
+ * \author Emmanuel Turquin
+ * \author Stephane Grabli
+ * \date 12/06/2003
+ */
+
+#include <iostream>
+#include <math.h>
+#include <vector>
+
+namespace VecMat {
+
+namespace Internal {
+ template <bool B>
+ struct is_false {};
+
+ template <>
+ struct is_false<false>
+ {
+ static inline void ensure() {}
+ };
+} // end of namespace Internal
+
+//
+// Vector class
+// - T: value type
+// - N: dimension
+//
+/////////////////////////////////////////////////////////////////////////////
+
+template <class T, unsigned N>
+class Vec
+{
+public:
+ typedef T value_type;
+
+ // constructors
+ inline Vec()
+ {
+ for (unsigned int i = 0; i < N; i++)
+ this->_coord[i] = 0;
+ }
+
+ ~Vec()
+ {
+ Internal::is_false<(N == 0)>::ensure();
+ }
+
+ template <class U>
+ explicit inline Vec(const U tab[N])
+ {
+ for (unsigned int i = 0; i < N; i++)
+ this->_coord[i] = (T)tab[i];
+ }
+
+ template <class U>
+ explicit inline Vec(const std::vector<U>& tab)
+ {
+ for (unsigned int i = 0; i < N; i++)
+ this->_coord[i] = (T)tab[i];
+ }
+
+ template <class U>
+ explicit inline Vec(const Vec<U, N>& v)
+ {
+ for (unsigned int i = 0; i < N; i++)
+ this->_coord[i] = (T)v[i];
+ }
+
+ // accessors
+ inline value_type operator[](const unsigned i) const
+ {
+ return this->_coord[i];
+ }
+
+ inline value_type& operator[](const unsigned i)
+ {
+ return this->_coord[i];
+ }
+
+ static inline unsigned dim()
+ {
+ return N;
+ }
+
+ // various useful methods
+ inline value_type norm() const
+ {
+ return (T)sqrt((float)squareNorm());
+ }
+
+ inline value_type squareNorm() const
+ {
+ return (*this) * (*this);
+ }
+
+ inline Vec<T, N>& normalize()
+ {
+ value_type n = norm();
+ for (unsigned int i = 0; i < N; i++)
+ this->_coord[i] /= n;
+ return *this;
+ }
+
+ inline Vec<T, N>& normalizeSafe()
+ {
+ value_type n = norm();
+ if (n) {
+ for (unsigned int i = 0; i < N; i++)
+ this->_coord[i] /= n;
+ }
+ return *this;
+ }
+
+ // classical operators
+ inline Vec<T, N> operator+(const Vec<T, N>& v) const
+ {
+ Vec<T, N> res(v);
+ res += *this;
+ return res;
+ }
+
+ inline Vec<T, N> operator-(const Vec<T, N>& v) const
+ {
+ Vec<T, N> res(*this);
+ res -= v;
+ return res;
+ }
+
+ inline Vec<T, N> operator*(const typename Vec<T, N>::value_type r) const
+ {
+ Vec<T, N> res(*this);
+ res *= r;
+ return res;
+ }
+
+ inline Vec<T, N> operator/(const typename Vec<T, N>::value_type r) const
+ {
+ Vec<T, N> res(*this);
+ if (r)
+ res /= r;
+ return res;
+ }
+
+ // dot product
+ inline value_type operator*(const Vec<T, N>& v) const
+ {
+ value_type sum = 0;
+ for (unsigned int i = 0; i < N; i++)
+ sum += (*this)[i] * v[i];
+ return sum;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator=(const Vec<U, N>& v)
+ {
+ if (this != &v) {
+ for (unsigned int i = 0; i < N; i++)
+ this->_coord[i] = (T)v[i];
+ }
+ return *this;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator+=(const Vec<U, N>& v)
+ {
+ for (unsigned int i = 0 ; i < N; i++)
+ this->_coord[i] += (T)v[i];
+ return *this;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator-=(const Vec<U, N>& v)
+ {
+ for (unsigned int i = 0 ; i < N; i++)
+ this->_coord[i] -= (T)v[i];
+ return *this;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator*=(const U r)
+ {
+ for (unsigned int i = 0 ; i < N; i++)
+ this->_coord[i] *= r;
+ return *this;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator/=(const U r)
+ {
+ if (r) {
+ for (unsigned int i = 0 ; i < N; i++)
+ this->_coord[i] /= r;
+ }
+ return *this;
+ }
+
+ inline bool operator==(const Vec<T, N>& v) const
+ {
+ for (unsigned int i = 0; i < N; i++) {
+ if (this->_coord[i] != v[i])
+ return false;
+ }
+ return true;
+ }
+
+ inline bool operator!=(const Vec<T, N>& v) const
+ {
+ for (unsigned int i = 0; i < N; i++) {
+ if (this->_coord[i] != v[i])
+ return true;
+ }
+ return false;
+ }
+
+ inline bool operator<(const Vec<T, N>& v) const
+ {
+ for (unsigned int i = 0; i < N; i++) {
+ if (this->_coord[i] < v[i])
+ return true;
+ if (this->_coord[i] > v[i])
+ return false;
+ if (this->_coord[i] == v[i])
+ continue;
+ }
+ return false;
+ }
+
+ inline bool operator>(const Vec<T, N>& v) const
+ {
+ for (unsigned int i = 0; i < N; i++) {
+ if (this->_coord[i] > v[i])
+ return true;
+ if (this->_coord[i] < v[i])
+ return false;
+ if (this->_coord[i] == v[i])
+ continue;
+ }
+ return false;
+ }
+
+protected:
+ value_type _coord[N];
+ enum {
+ _dim = N,
+ };
+};
+
+
+//
+// Vec2 class (2D Vector)
+// - T: value type
+//
+/////////////////////////////////////////////////////////////////////////////
+
+template <class T>
+class Vec2 : public Vec<T, 2>
+{
+public:
+ typedef typename Vec<T, 2>::value_type value_type;
+
+ inline Vec2() : Vec<T, 2>() {}
+
+ template <class U>
+ explicit inline Vec2(const U tab[2]) : Vec<T, 2>(tab) {}
+
+ template <class U>
+ explicit inline Vec2(const std::vector<U>& tab) : Vec<T, 2>(tab) {}
+
+ template <class U>
+ inline Vec2(const Vec<U, 2>& v) : Vec<T, 2>(v) {}
+
+ inline Vec2(const value_type x, const value_type y = 0) : Vec<T, 2>()
+ {
+ this->_coord[0] = (T)x;
+ this->_coord[1] = (T)y;
+ }
+
+ inline value_type x() const
+ {
+ return this->_coord[0];
+ }
+
+ inline value_type& x()
+ {
+ return this->_coord[0];
+ }
+
+ inline value_type y() const
+ {
+ return this->_coord[1];
+ }
+
+ inline value_type& y()
+ {
+ return this->_coord[1];
+ }
+
+ inline void setX(const value_type v)
+ {
+ this->_coord[0] = v;
+ }
+
+ inline void setY(const value_type v)
+ {
+ this->_coord[1] = v;
+ }
+
+ // FIXME: hack swig -- no choice
+ inline Vec2<T> operator+(const Vec2<T>& v) const
+ {
+ Vec2<T> res(v);
+ res += *this;
+ return res;
+ }
+
+ inline Vec2<T> operator-(const Vec2<T>& v) const
+ {
+ Vec2<T> res(*this);
+ res -= v;
+ return res;
+ }
+
+ inline Vec2<T> operator*(const value_type r) const
+ {
+ Vec2<T> res(*this);
+ res *= r;
+ return res;
+ }
+
+ inline Vec2<T> operator/(const value_type r) const
+ {
+ Vec2<T> res(*this);
+ if (r)
+ res /= r;
+ return res;
+ }
+
+ // dot product
+ inline value_type operator*(const Vec2<T>& v) const
+ {
+ value_type sum = 0;
+ for (unsigned int i = 0; i < 2; i++)
+ sum += (*this)[i] * v[i];
+ return sum;
+ }
+};
+
+
+//
+// HVec3 class (3D Vector in homogeneous coordinates)
+// - T: value type
+//
+/////////////////////////////////////////////////////////////////////////////
+
+template <class T>
+class HVec3 : public Vec<T, 4>
+{
+public:
+ typedef typename Vec<T, 4>::value_type value_type;
+
+ inline HVec3() : Vec<T, 4>() {}
+
+ template <class U>
+ explicit inline HVec3(const U tab[4]) : Vec<T, 4>(tab) {}
+
+ template <class U>
+ explicit inline HVec3(const std::vector<U>& tab) : Vec<T, 4>(tab) {}
+
+ template<class U>
+ inline HVec3(const Vec<U, 4>& v) : Vec<T, 4>(v) {}
+
+ inline HVec3(const value_type sx, const value_type sy = 0, const value_type sz = 0, const value_type s = 1)
+ {
+ this->_coord[0] = sx;
+ this->_coord[1] = sy;
+ this->_coord[2] = sz;
+ this->_coord[3] = s;
+ }
+
+ template <class U>
+ inline HVec3(const Vec<U, 3>& sv, const U s = 1)
+ {
+ this->_coord[0] = (T)sv[0];
+ this->_coord[1] = (T)sv[1];
+ this->_coord[2] = (T)sv[2];
+ this->_coord[3] = (T)s;
+ }
+
+ inline value_type sx() const
+ {
+ return this->_coord[0];
+ }
+
+ inline value_type& sx()
+ {
+ return this->_coord[0];
+ }
+
+ inline value_type sy() const
+ {
+ return this->_coord[1];
+ }
+
+ inline value_type& sy()
+ {
+ return this->_coord[1];
+ }
+
+ inline value_type sz() const
+ {
+ return this->_coord[2];
+ }
+
+ inline value_type& sz()
+ {
+ return this->_coord[2];
+ }
+
+ inline value_type s() const
+ {
+ return this->_coord[3];
+ }
+
+ inline value_type& s()
+ {
+ return this->_coord[3];
+ }
+
+ // Acces to non-homogeneous coordinates in 3D
+ inline value_type x() const
+ {
+ return this->_coord[0] / this->_coord[3];
+ }
+
+ inline value_type y() const
+ {
+ return this->_coord[1] / this->_coord[3];
+ }
+
+ inline value_type z() const
+ {
+ return this->_coord[2] / this->_coord[3];
+ }
+};
+
+
+//
+// Vec3 class (3D Vec)
+// - T: value type
+//
+/////////////////////////////////////////////////////////////////////////////
+template <class T>
+class Vec3 : public Vec<T, 3>
+{
+public:
+ typedef typename Vec<T, 3>::value_type value_type;
+
+ inline Vec3() : Vec<T, 3>() {}
+
+ template <class U>
+ explicit inline Vec3(const U tab[3]) : Vec<T, 3>(tab) {}
+
+ template <class U>
+ explicit inline Vec3(const std::vector<U>& tab) : Vec<T, 3>(tab) {}
+
+ template<class U>
+ inline Vec3(const Vec<U, 3>& v) : Vec<T, 3>(v) {}
+
+ template<class U>
+ inline Vec3(const HVec3<U>& v)
+ {
+ this->_coord[0] = (T)v.x();
+ this->_coord[1] = (T)v.y();
+ this->_coord[2] = (T)v.z();
+ }
+
+ inline Vec3(const value_type x, const value_type y = 0, const value_type z = 0) : Vec<T, 3>()
+ {
+ this->_coord[0] = x;
+ this->_coord[1] = y;
+ this->_coord[2] = z;
+ }
+
+ inline value_type x() const
+ {
+ return this->_coord[0];
+ }
+
+ inline value_type& x()
+ {
+ return this->_coord[0];
+ }
+
+ inline value_type y() const
+ {
+ return this->_coord[1];
+ }
+
+ inline value_type& y()
+ {
+ return this->_coord[1];
+ }
+
+ inline value_type z() const
+ {
+ return this->_coord[2];
+ }
+
+ inline value_type& z()
+ {
+ return this->_coord[2];
+ }
+
+ inline void setX(const value_type v)
+ {
+ this->_coord[0] = v;
+ }
+
+ inline void setY(const value_type v)
+ {
+ this->_coord[1] = v;
+ }
+
+ inline void setZ(const value_type v)
+ {
+ this->_coord[2] = v;
+ }
+
+ // classical operators
+ // FIXME: hack swig -- no choice
+ inline Vec3<T> operator+(const Vec3<T>& v) const
+ {
+ Vec3<T> res(v);
+ res += *this;
+ return res;
+ }
+
+ inline Vec3<T> operator-(const Vec3<T>& v) const
+ {
+ Vec3<T> res(*this);
+ res -= v;
+ return res;
+ }
+
+ inline Vec3<T> operator*(const value_type r) const
+ {
+ Vec3<T> res(*this);
+ res *= r;
+ return res;
+ }
+
+ inline Vec3<T> operator/(const value_type r) const
+ {
+ Vec3<T> res(*this);
+ if (r)
+ res /= r;
+ return res;
+ }
+
+ // dot product
+ inline value_type operator*(const Vec3<T>& v) const
+ {
+ value_type sum = 0;
+ for (unsigned int i = 0; i < 3; i++)
+ sum += (*this)[i] * v[i];
+ return sum;
+ }
+
+ // cross product for 3D Vectors
+ // FIXME: hack swig -- no choice
+ inline Vec3<T> operator^(const Vec3<T>& v) const
+ {
+ Vec3<T> res((*this)[1] * v[2] - (*this)[2] * v[1],
+ (*this)[2] * v[0] - (*this)[0] * v[2],
+ (*this)[0] * v[1] - (*this)[1] * v[0]);
+ return res;
+ }
+
+ // cross product for 3D Vectors
+ template <typename U>
+ inline Vec3<T> operator^(const Vec<U, 3>& v) const
+ {
+ Vec3<T> res((*this)[1] * v[2] - (*this)[2] * v[1],
+ (*this)[2] * v[0] - (*this)[0] * v[2],
+ (*this)[0] * v[1] - (*this)[1] * v[0]);
+ return res;
+ }
+};
+
+
+//
+// Matrix class
+// - T: value type
+// - M: rows
+// - N: cols
+//
+/////////////////////////////////////////////////////////////////////////////
+
+// Dirty, but icc under Windows needs this
+#define _SIZE (M * N)
+
+template <class T, unsigned M, unsigned N>
+class Matrix
+{
+public:
+ typedef T value_type;
+
+ inline Matrix()
+ {
+ for (unsigned int i = 0; i < _SIZE; i++)
+ this->_coord[i] = 0;
+ }
+
+ ~Matrix()
+ {
+ Internal::is_false<(M == 0)>::ensure();
+ Internal::is_false<(N == 0)>::ensure();
+ }
+
+ template <class U>
+ explicit inline Matrix(const U tab[_SIZE])
+ {
+ for (unsigned int i = 0; i < _SIZE; i++)
+ this->_coord[i] = tab[i];
+ }
+
+ template <class U>
+ explicit inline Matrix(const std::vector<U>& tab)
+ {
+ for (unsigned int i = 0; i < _SIZE; i++)
+ this->_coord[i] = tab[i];
+ }
+
+ template <class U>
+ inline Matrix(const Matrix<U, M, N>& m)
+ {
+ for (unsigned int i = 0; i < M; i++) {
+ for (unsigned int j = 0; j < N; j++)
+ this->_coord[i * N + j] = (T)m(i, j);
+ }
+ }
+
+ inline value_type operator()(const unsigned i, const unsigned j) const
+ {
+ return this->_coord[i * N + j];
+ }
+
+ inline value_type& operator()(const unsigned i, const unsigned j)
+ {
+ return this->_coord[i * N + j];
+ }
+
+ static inline unsigned rows()
+ {
+ return M;
+ }
+
+ static inline unsigned cols()
+ {
+ return N;
+ }
+
+ inline Matrix<T, M, N>& transpose() const
+ {
+ Matrix<T, N, M> res;
+ for (unsigned int i = 0; i < M; i++) {
+ for (unsigned int j = 0; j < N; j++)
+ res(j, i) = this->_coord[i * N + j];
+ }
+ return res;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator=(const Matrix<U, M, N>& m)
+ {
+ if (this != &m) {
+ for (unsigned int i = 0; i < M; i++) {
+ for (unsigned int j = 0; j < N; j++)
+ this->_coord[i * N + j] = (T)m(i, j);
+ }
+ }
+ return *this;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator+=(const Matrix<U, M, N>& m)
+ {
+ for (unsigned int i = 0; i < M; i++) {
+ for (unsigned int j = 0; j < N; j++)
+ this->_coord[i * N + j] += (T)m(i, j);
+ }
+ return *this;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator-=(const Matrix<U, M, N>& m)
+ {
+ for (unsigned int i = 0; i < M; i++) {
+ for (unsigned int j = 0; j < N; j++)
+ this->_coord[i * N + j] -= (T)m(i, j);
+ }
+ return *this;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator*=(const U lambda)
+ {
+ for (unsigned int i = 0; i < M; i++) {
+ for (unsigned int j = 0; j < N; j++)
+ this->_coord[i * N + j] *= lambda;
+ }
+ return *this;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator/=(const U lambda)
+ {
+ if (lambda) {
+ for (unsigned int i = 0; i < M; i++) {
+ for (unsigned int j = 0; j < N; j++)
+ this->_coord[i * N + j] /= lambda;
+ }
+ }
+ return *this;
+ }
+
+protected:
+ value_type _coord[_SIZE];
+};
+
+#undef _SIZE
+
+//
+// SquareMatrix class
+// - T: value type
+// - N: rows & cols
+//
+/////////////////////////////////////////////////////////////////////////////
+
+// Dirty, but icc under Windows needs this
+#define _SIZE (N * N)
+
+template <class T, unsigned N>
+class SquareMatrix : public Matrix<T, N, N>
+{
+public:
+ typedef T value_type;
+
+ inline SquareMatrix() : Matrix<T, N, N>() {}
+
+ template <class U>
+ explicit inline SquareMatrix(const U tab[_SIZE]) : Matrix<T, N, N>(tab) {}
+
+ template <class U>
+ explicit inline SquareMatrix(const std::vector<U>& tab) : Matrix<T, N, N>(tab) {}
+
+ template <class U>
+ inline SquareMatrix(const Matrix<U, N, N>& m) : Matrix<T, N, N>(m) {}
+
+ static inline SquareMatrix<T, N> identity()
+ {
+ SquareMatrix<T, N> res;
+ for (unsigned int i = 0; i < N; i++)
+ res(i, i) = 1;
+ return res;
+ }
+};
+
+#undef _SIZE
+
+//
+// Vector external functions
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if 0
+template <class T, unsigned N>
+inline Vec<T, N> operator+(const Vec<T, N>& v1, const Vec<T, N>& v2)
+{
+ Vec<T, N> res(v1);
+ res += v2;
+ return res;
+}
+
+template <class T, unsigned N>
+inline Vec<T, N> operator-(const Vec<T, N>& v1, const Vec<T, N>& v2)
+{
+ Vec<T, N> res(v1);
+ res -= v2;
+ return res;
+}
+
+template <class T, unsigned N>
+inline Vec<T, N> operator*(const Vec<T, N>& v, const typename Vec<T, N>::value_type r)
+{
+ Vec<T, N> res(v);
+ res *= r;
+ return res;
+}
+#endif
+
+template <class T, unsigned N>
+inline Vec<T, N> operator*(const typename Vec<T, N>::value_type r, const Vec<T, N>& v)
+{
+ Vec<T, N> res(v);
+ res *= r;
+ return res;
+}
+
+#if 0
+template <class T, unsigned N>
+inline Vec<T, N> operator/(const Vec<T, N>& v, const typename Vec<T, N>::value_type r)
+{
+ Vec<T, N> res(v);
+ if (r)
+ res /= r;
+ return res;
+}
+
+// dot product
+template <class T, unsigned N>
+inline typename Vec<T, N>::value_type operator*(const Vec<T, N>& v1, const Vec<T, N>& v2)
+{
+ typename Vec<T, N>::value_type sum = 0;
+ for (unsigned int i = 0; i < N; i++)
+ sum += v1[i] * v2[i];
+ return sum;
+}
+
+// cross product for 3D Vectors
+template <typename T>
+inline Vec3<T> operator^(const Vec<T, 3>& v1, const Vec<T, 3>& v2)
+{
+ Vec3<T> res(v1[1] * v2[2] - v1[2] * v2[1], v1[2] * v2[0] - v1[0] * v2[2], v1[0] * v2[1] - v1[1] * v2[0]);
+ return res;
+}
+#endif
+
+// stream operator
+template <class T, unsigned N>
+inline std::ostream& operator<<(std::ostream& s, const Vec<T, N>& v)
+{
+ unsigned int i;
+ s << "[";
+ for (i = 0; i < N - 1; i++)
+ s << v[i] << ", ";
+ s << v[i] << "]";
+ return s;
+}
+
+//
+// Matrix external functions
+//
+/////////////////////////////////////////////////////////////////////////////
+
+template <class T, unsigned M, unsigned N>
+inline Matrix<T, M, N> operator+(const Matrix<T, M, N>& m1, const Matrix<T, M, N>& m2)
+{
+ Matrix<T, M, N> res(m1);
+ res += m2;
+ return res;
+}
+
+template <class T, unsigned M, unsigned N>
+inline Matrix<T, M, N> operator-(const Matrix<T, M, N>& m1, const Matrix<T, M, N>& m2)
+{
+ Matrix<T, M, N> res(m1);
+ res -= m2;
+ return res;
+}
+
+template <class T, unsigned M, unsigned N>
+inline Matrix<T, M, N> operator*(const Matrix<T, M, N>& m1, const typename Matrix<T, M, N>::value_type lambda)
+{
+ Matrix<T, M, N> res(m1);
+ res *= lambda;
+ return res;
+}
+
+template <class T, unsigned M, unsigned N>
+inline Matrix<T, M, N> operator*(const typename Matrix<T, M, N>::value_type lambda, const Matrix<T, M, N>& m1)
+{
+ Matrix<T, M, N> res(m1);
+ res *= lambda;
+ return res;
+}
+
+template <class T, unsigned M, unsigned N>
+inline Matrix<T, M, N> operator/(const Matrix<T, M, N>& m1, const typename Matrix<T, M, N>::value_type lambda)
+{
+ Matrix<T, M, N> res(m1);
+ res /= lambda;
+ return res;
+}
+
+template <class T, unsigned M, unsigned N, unsigned P>
+inline Matrix<T, M, P> operator*(const Matrix<T, M, N>& m1, const Matrix<T, N, P>& m2)
+{
+ unsigned int i, j, k;
+ Matrix<T, M, P> res;
+ typename Matrix<T, N, P>::value_type scale;
+
+ for (j = 0; j < P; j++) {
+ for (k = 0; k < N; k++) {
+ scale = m2(k, j);
+ for (i = 0; i < N; i++)
+ res(i, j) += m1(i, k) * scale;
+ }
+ }
+ return res;
+}
+
+template <class T, unsigned M, unsigned N>
+inline Vec<T, M> operator*(const Matrix<T, M, N>& m, const Vec<T, N>& v)
+{
+ Vec<T, M> res;
+ typename Matrix<T, M, N>::value_type scale;
+
+ for (unsigned int j = 0; j < M; j++) {
+ scale = v[j];
+ for (unsigned int i = 0; i < N; i++)
+ res[i] += m(i, j) * scale;
+ }
+ return res;
+}
+
+// stream operator
+template <class T, unsigned M, unsigned N>
+inline std::ostream& operator<<(std::ostream& s, const Matrix<T, M, N>& m)
+{
+ unsigned int i, j;
+ for (i = 0; i < M; i++) {
+ s << "[";
+ for (j = 0; j < N - 1; j++)
+ s << m(i, j) << ", ";
+ s << m(i, j) << "]" << std::endl;
+ }
+ return s;
+}
+
+} // end of namespace VecMat
+
+#endif // __VECMAT_H__
diff --git a/source/blender/freestyle/intern/geometry/matrix_util.cpp b/source/blender/freestyle/intern/geometry/matrix_util.cpp
new file mode 100644
index 00000000000..089535561d7
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/matrix_util.cpp
@@ -0,0 +1,266 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * This Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is:
+ * GXML/Graphite: Geometry and Graphics Programming Library + Utilities
+ * Copyright (C) 2000 Bruno Levy
+ * Contact: Bruno Levy
+ * levy@loria.fr
+ * ISA Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/geometry/matrix_util.cpp
+ * \ingroup freestyle
+ * \author Bruno Levy
+ */
+
+#include <math.h>
+
+#include "matrix_util.h"
+
+namespace OGF {
+
+namespace MatrixUtil {
+
+ static const double EPS = 0.00001;
+ static int MAX_ITER = 100;
+
+ void semi_definite_symmetric_eigen(const double *mat, int n, double *eigen_vec, double *eigen_val)
+ {
+ double *a, *v;
+ double a_norm, a_normEPS, thr, thr_nn;
+ int nb_iter = 0;
+ int jj;
+ int i, j, k, ij, ik, l, m, lm, mq, lq, ll, mm, imv, im, iq, ilv, il, nn;
+ int *index;
+ double a_ij, a_lm, a_ll, a_mm, a_im, a_il;
+ double a_lm_2;
+ double v_ilv, v_imv;
+ double x;
+ double sinx, sinx_2, cosx, cosx_2, sincos;
+ double delta;
+
+ // Number of entries in mat
+ nn = (n * (n + 1)) / 2;
+
+ // Step 1: Copy mat to a
+ a = new double[nn];
+
+ for (ij = 0; ij < nn; ij++) {
+ a[ij] = mat[ij];
+ }
+
+ // Ugly Fortran-porting trick: indices for a are between 1 and n
+ a--;
+
+ // Step 2 : Init diagonalization matrix as the unit matrix
+ v = new double[n * n];
+
+ ij = 0;
+ for (i = 0; i < n; i++) {
+ for (j = 0; j < n; j++) {
+ if (i == j) {
+ v[ij++] = 1.0;
+ }
+ else {
+ v[ij++] = 0.0;
+ }
+ }
+ }
+
+ // Ugly Fortran-porting trick: indices for v are between 1 and n
+ v--;
+
+ // Step 3 : compute the weight of the non diagonal terms
+ ij = 1;
+ a_norm = 0.0;
+ for (i = 1; i <= n; i++) {
+ for (j = 1; j <= i; j++) {
+ if (i != j) {
+ a_ij = a[ij];
+ a_norm += a_ij * a_ij;
+ }
+ ij++;
+ }
+ }
+
+ if (a_norm != 0.0) {
+ a_normEPS = a_norm * EPS;
+ thr = a_norm;
+
+ // Step 4 : rotations
+ while (thr > a_normEPS && nb_iter < MAX_ITER) {
+ nb_iter++;
+ thr_nn = thr / nn;
+
+ for (l = 1; l < n; l++) {
+ for (m = l + 1; m <= n; m++) {
+ // compute sinx and cosx
+ lq = (l * l - l) / 2;
+ mq = (m * m - m) / 2;
+
+ lm = l + mq;
+ a_lm = a[lm];
+ a_lm_2 = a_lm * a_lm;
+
+ if (a_lm_2 < thr_nn) {
+ continue;
+ }
+
+ ll = l + lq;
+ mm = m + mq;
+ a_ll = a[ll];
+ a_mm = a[mm];
+
+ delta = a_ll - a_mm;
+
+ if (delta == 0.0) {
+ x = -M_PI / 4;
+ }
+ else {
+ x = -atan((a_lm + a_lm) / delta) / 2.0;
+ }
+
+ sinx = sin(x);
+ cosx = cos(x);
+ sinx_2 = sinx * sinx;
+ cosx_2 = cosx * cosx;
+ sincos = sinx * cosx;
+
+ // rotate L and M columns
+ ilv = n * (l - 1);
+ imv = n * (m - 1);
+
+ for (i = 1; i <= n; i++) {
+ if ((i != l) && (i != m)) {
+ iq = (i * i - i) / 2;
+
+ if (i < m) {
+ im = i + mq;
+ }
+ else {
+ im = m + iq;
+ }
+ a_im = a[im];
+
+ if (i < l) {
+ il = i + lq;
+ }
+ else {
+ il = l + iq;
+ }
+ a_il = a[il];
+
+ a[il] = a_il * cosx - a_im * sinx;
+ a[im] = a_il * sinx + a_im * cosx;
+ }
+
+ ilv++;
+ imv++;
+
+ v_ilv = v[ilv];
+ v_imv = v[imv];
+
+ v[ilv] = cosx * v_ilv - sinx * v_imv;
+ v[imv] = sinx * v_ilv + cosx * v_imv;
+ }
+
+ x = a_lm * sincos;
+ x += x;
+
+ a[ll] = a_ll * cosx_2 + a_mm * sinx_2 - x;
+ a[mm] = a_ll * sinx_2 + a_mm * cosx_2 + x;
+ a[lm] = 0.0;
+
+ thr = fabs(thr - a_lm_2);
+ }
+ }
+ }
+ }
+
+ // Step 5: index conversion and copy eigen values
+
+ // back from Fortran to C++
+ a++;
+
+ for (i = 0; i < n; i++) {
+ k = i + (i * (i + 1)) / 2;
+ eigen_val[i] = a[k];
+ }
+
+ delete[] a;
+
+ // Step 6: sort the eigen values and eigen vectors
+
+ index = new int[n];
+ for (i = 0; i < n; i++) {
+ index[i] = i;
+ }
+
+ for (i = 0; i < (n - 1); i++) {
+ x = eigen_val[i];
+ k = i;
+
+ for (j = i + 1; j < n; j++) {
+ if (x < eigen_val[j]) {
+ k = j;
+ x = eigen_val[j];
+ }
+ }
+
+ eigen_val[k] = eigen_val[i];
+ eigen_val[i] = x;
+
+ jj = index[k];
+ index[k] = index[i];
+ index[i] = jj;
+ }
+
+ // Step 7: save the eigen vectors
+
+ // back from Fortran to to C++
+ v++;
+
+ ij = 0;
+ for (k = 0; k < n; k++) {
+ ik = index[k] * n;
+ for (i = 0; i < n; i++) {
+ eigen_vec[ij++] = v[ik++];
+ }
+ }
+
+ delete[] v;
+ delete[] index;
+ return;
+ }
+
+//_________________________________________________________
+
+} // MatrixUtil namespace
+
+} // OGF namespace
diff --git a/source/blender/freestyle/intern/geometry/matrix_util.h b/source/blender/freestyle/intern/geometry/matrix_util.h
new file mode 100644
index 00000000000..1cf58a8e1fd
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/matrix_util.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.
+ *
+ * This Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is:
+ * GXML/Graphite: Geometry and Graphics Programming Library + Utilities
+ * Copyright (C) 2000 Bruno Levy
+ * Contact: Bruno Levy
+ * levy@loria.fr
+ * ISA Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __MATRIX_UTIL__
+#define __MATRIX_UTIL__
+
+/** \file blender/freestyle/intern/geometry/matrix_util.h
+ * \ingroup freestyle
+ * \author Bruno Levy
+ */
+
+#include "../system/FreestyleConfig.h"
+
+namespace OGF {
+
+namespace MatrixUtil {
+
+ /**
+ * computes the eigen values and eigen vectors of a semi definite symmetric matrix
+ *
+ * @param matrix is stored in column symmetric storage, i.e.
+ * matrix = { m11, m12, m22, m13, m23, m33, m14, m24, m34, m44 ... }
+ * size = n(n+1)/2
+ *
+ * @param eigen_vectors (return) = { v1, v2, v3, ..., vn }
+ * where vk = vk0, vk1, ..., vkn
+ * size = n^2, must be allocated by caller
+ *
+ * @param eigen_values (return) are in decreasing order
+ * size = n, must be allocated by caller
+ */
+ LIB_GEOMETRY_EXPORT
+ void semi_definite_symmetric_eigen(const double *mat, int n, double *eigen_vec, double *eigen_val);
+
+} // MatrixUtil namespace
+
+} // OGF namespace
+
+#endif // __MATRIX_UTIL__
diff --git a/source/blender/freestyle/intern/geometry/normal_cycle.cpp b/source/blender/freestyle/intern/geometry/normal_cycle.cpp
new file mode 100644
index 00000000000..63195b24386
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/normal_cycle.cpp
@@ -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.
+ *
+ * This Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is:
+ * OGF/Graphite: Geometry and Graphics Programming Library + Utilities
+ * Copyright (C) 2000 Bruno Levy
+ * Contact: Bruno Levy
+ * levy@loria.fr
+ * ISA Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/geometry/normal_cycle.cpp
+ * \ingroup freestyle
+ * \author Bruno Levy
+ */
+
+#include "matrix_util.h"
+#include "normal_cycle.h"
+
+namespace OGF {
+
+//_________________________________________________________
+
+
+NormalCycle::NormalCycle()
+{
+}
+
+void NormalCycle::begin()
+{
+ M_[0] = M_[1] = M_[2] = M_[3] = M_[4] = M_[5] = 0;
+}
+
+void NormalCycle::end()
+{
+ double eigen_vectors[9];
+ MatrixUtil::semi_definite_symmetric_eigen(M_, 3, eigen_vectors, eigen_value_);
+
+ axis_[0] = Vec3r(eigen_vectors[0], eigen_vectors[1], eigen_vectors[2]);
+
+ axis_[1] = Vec3r(eigen_vectors[3], eigen_vectors[4], eigen_vectors[5]);
+
+ axis_[2] = Vec3r(eigen_vectors[6], eigen_vectors[7], eigen_vectors[8]);
+
+ // Normalize the eigen vectors
+ for (int i = 0; i < 3; i++) {
+ axis_[i].normalize();
+ }
+
+ // Sort the eigen vectors
+ i_[0] = 0;
+ i_[1] = 1;
+ i_[2] = 2;
+
+ double l0 = ::fabs(eigen_value_[0]);
+ double l1 = ::fabs(eigen_value_[1]);
+ double l2 = ::fabs(eigen_value_[2]);
+
+ if (l1 > l0) {
+ ogf_swap(l0, l1 );
+ ogf_swap(i_[0], i_[1]);
+ }
+ if (l2 > l1) {
+ ogf_swap(l1, l2 );
+ ogf_swap(i_[1], i_[2]);
+ }
+ if (l1 > l0) {
+ ogf_swap(l0, l1 );
+ ogf_swap(i_[0], i_[1]);
+ }
+}
+
+//_________________________________________________________
+
+} // OGF namespace
diff --git a/source/blender/freestyle/intern/geometry/normal_cycle.h b/source/blender/freestyle/intern/geometry/normal_cycle.h
new file mode 100644
index 00000000000..3fbf4fb58ae
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/normal_cycle.h
@@ -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.
+ *
+ * This Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is:
+ * OGF/Graphite: Geometry and Graphics Programming Library + Utilities
+ * Copyright (C) 2000 Bruno Levy
+ * Contact: Bruno Levy
+ * levy@loria.fr
+ * ISA Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __MESH_TOOLS_MATH_NORMAL_CYCLE__
+#define __MESH_TOOLS_MATH_NORMAL_CYCLE__
+
+/** \file blender/freestyle/intern/geometry/normal_cycle.h
+ * \ingroup freestyle
+ * \author Bruno Levy
+ */
+
+#include "Geom.h"
+
+#include "../system/FreestyleConfig.h"
+
+using namespace Geometry;
+
+namespace OGF {
+
+template <class T> inline void ogf_swap(T& x, T& y)
+{
+ T z = x ;
+ x = y ;
+ y = z ;
+}
+
+//_________________________________________________________
+
+/**
+* NormalCycle evaluates the curvature tensor in function
+* of a set of dihedral angles and associated vectors.
+* Reference:
+* Restricted Delaunay Triangulation and Normal Cycle,
+* D. Cohen-Steiner and J.M. Morvan,
+* SOCG 2003
+*/
+class LIB_GEOMETRY_EXPORT NormalCycle {
+public:
+ NormalCycle();
+ void begin();
+ void end();
+ /**
+ * Note: the specified edge vector needs to be pre-clipped by the neighborhood.
+ */
+ void accumulate_dihedral_angle(const Vec3r& edge, real angle, real neigh_area = 1.0);
+
+ const Vec3r& eigen_vector(int i) const
+ {
+ return axis_[i_[i]];
+ }
+
+ real eigen_value(int i) const
+ {
+ return eigen_value_[i_[i]];
+ }
+
+ const Vec3r& N() const
+ {
+ return eigen_vector(2);
+ }
+
+ const Vec3r& Kmax() const
+ {
+ return eigen_vector(1);
+ }
+
+ const Vec3r& Kmin() const
+ {
+ return eigen_vector(0);
+ }
+
+ real n() const
+ {
+ return eigen_value(2);
+ }
+
+ real kmax() const
+ {
+ return eigen_value(1);
+ }
+
+ real kmin() const
+ {
+ return eigen_value(0);
+ }
+
+private:
+ real center_[3];
+ Vec3r axis_[3];
+ real eigen_value_[3];
+ real M_[6];
+ int i_[3];
+};
+
+inline void NormalCycle::accumulate_dihedral_angle(const Vec3r& edge, const double beta, double neigh_area)
+{
+ double s = beta * neigh_area / edge.norm();
+
+ M_[0] += s * edge.x() * edge.x();
+ M_[1] += s * edge.x() * edge.y();
+ M_[2] += s * edge.y() * edge.y();
+ M_[3] += s * edge.x() * edge.z();
+ M_[4] += s * edge.y() * edge.z();
+ M_[5] += s * edge.z() * edge.z();
+}
+
+//_________________________________________________________
+
+} // OGF namespace
+
+#endif // __MESH_TOOLS_MATH_NORMAL_CYCLE__
diff --git a/source/blender/freestyle/intern/image/GaussianFilter.cpp b/source/blender/freestyle/intern/image/GaussianFilter.cpp
new file mode 100644
index 00000000000..be0bef8115c
--- /dev/null
+++ b/source/blender/freestyle/intern/image/GaussianFilter.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/image/GaussianFilter.cpp
+ * \ingroup freestyle
+ * \brief Class to perform gaussian filtering operations on an image
+ * \author Stephane Grabli
+ * \date 20/05/2003
+ */
+
+#include <stdlib.h>
+
+#include "GaussianFilter.h"
+
+GaussianFilter::GaussianFilter(float iSigma)
+{
+ _sigma = iSigma;
+ _mask = 0;
+ computeMask();
+}
+
+GaussianFilter::GaussianFilter(const GaussianFilter& iBrother)
+{
+ _sigma = iBrother._sigma;
+ _maskSize = iBrother._maskSize;
+ _bound = iBrother._bound;
+ _storedMaskSize = iBrother._storedMaskSize;
+ _mask = new float[_maskSize * _maskSize];
+ memcpy(_mask, iBrother._mask, _maskSize * _maskSize * sizeof(float));
+}
+
+GaussianFilter& GaussianFilter::operator=(const GaussianFilter& iBrother)
+{
+ _sigma = iBrother._sigma;
+ _maskSize = iBrother._maskSize;
+ _bound = iBrother._bound;
+ _storedMaskSize = iBrother._storedMaskSize;
+ _mask = new float[_storedMaskSize * _storedMaskSize];
+ memcpy(_mask, iBrother._mask, _storedMaskSize * _storedMaskSize * sizeof(float));
+ return *this;
+}
+
+
+GaussianFilter::~GaussianFilter()
+{
+ if (0 != _mask) {
+ delete[] _mask;
+ }
+}
+
+int GaussianFilter::computeMaskSize(float sigma)
+{
+ int maskSize = (int)floor(4 * sigma) + 1;
+ if (0 == (maskSize % 2))
+ ++maskSize;
+
+ return maskSize;
+}
+
+void GaussianFilter::setSigma(float sigma)
+{
+ _sigma = sigma;
+ computeMask();
+}
+
+void GaussianFilter::computeMask()
+{
+ if (0 != _mask) {
+ delete[] _mask;
+ }
+
+ _maskSize = computeMaskSize(_sigma);
+ _storedMaskSize = (_maskSize + 1) >> 1;
+ _bound = _storedMaskSize - 1;
+
+ float norm = _sigma * _sigma * 2.0f * M_PI;
+ float invNorm = 1.0f / norm;
+ _mask = new float[_storedMaskSize * _storedMaskSize * sizeof(float)];
+ for (int i = 0; i < _storedMaskSize; ++i) {
+ for (int j = 0; j < _storedMaskSize; ++j) {
+#if 0
+ _mask[i * _storedMaskSize + j] = exp(-(i * i + j * j) / (2.0 * _sigma * _sigma));
+#else
+ _mask[i * _storedMaskSize + j] = invNorm * exp(-(i * i + j * j) / (2.0 * _sigma * _sigma));
+#endif
+ }
+ }
+}
diff --git a/source/blender/freestyle/intern/image/GaussianFilter.h b/source/blender/freestyle/intern/image/GaussianFilter.h
new file mode 100644
index 00000000000..08fdf32ecd7
--- /dev/null
+++ b/source/blender/freestyle/intern/image/GaussianFilter.h
@@ -0,0 +1,162 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __GAUSSIANFILTER_H__
+#define __GAUSSIANFILTER_H__
+
+/** \file blender/freestyle/intern/image/GaussianFilter.h
+ * \ingroup freestyle
+ * \brief Class to perform gaussian filtering operations on an image
+ * \author Stephane Grabli
+ * \date 20/05/2003
+ */
+
+#include <cstdlib> // for abs
+#include <string.h> // for memcpy
+
+#include "../system/FreestyleConfig.h"
+
+class LIB_IMAGE_EXPORT GaussianFilter
+{
+protected:
+ /* The mask is a symetrical 2d array (with respect to the middle point).
+ * Thus, M(i,j) = M(-i,j) = M(i,-j) = M(-i,-j).
+ * For this reason, to represent a NxN array (N odd), we only store a ((N+1)/2)x((N+1)/2) array.
+ */
+ float _sigma;
+ float *_mask;
+ int _bound;
+ // the real mask size (must be odd)(the size of the mask we store is ((_maskSize+1)/2)*((_maskSize+1)/2))
+ int _maskSize;
+ int _storedMaskSize; // (_maskSize+1)/2)
+
+public:
+ GaussianFilter(float iSigma = 1.0f);
+ GaussianFilter(const GaussianFilter&);
+ GaussianFilter& operator=(const GaussianFilter&);
+ virtual ~GaussianFilter();
+
+ /*! Returns the value for pixel x,y of image "map" after a gaussian blur, made using the sigma value.
+ * The sigma value determines the mask size (~ 2 x sigma).
+ * \param map
+ * The image we wish to work on. The Map template must implement the following methods:
+ * - float pixel(unsigned int x,unsigned int y) const;
+ * - unsigned width() const;
+ * - unsigned height() const;
+ * \param x
+ * The abscissa of the pixel where we want to evaluate the gaussian blur.
+ * \param y
+ * The ordinate of the pixel where we want to evaluate the gaussian blur.
+ * \param sigma
+ * The sigma value of the gaussian function.
+ */
+ template<class Map>
+ float getSmoothedPixel(Map *map, int x, int y);
+
+ /*! Compute the mask size and returns the REAL mask size ((2*_maskSize)-1)
+ * This method is provided for convenience.
+ */
+ static int computeMaskSize(float sigma);
+
+ /*! accessors */
+ inline float sigma() const
+ {
+ return _sigma;
+ }
+
+ inline int maskSize() const
+ {
+ return _maskSize;
+ }
+
+ inline int getBound()
+ {
+ return _bound;
+ }
+
+ /*! modifiers */
+ void setSigma(float sigma);
+#if 0
+ void SetMaskSize(int size)
+ {
+ _maskSize = size;
+ _storedMaskSize = (_maskSize + 1) >> 1;
+ }
+#endif
+
+protected:
+ void computeMask();
+};
+
+/*
+
+ #############################################
+ #############################################
+ #############################################
+ ###### ######
+ ###### I M P L E M E N T A T I O N ######
+ ###### ######
+ #############################################
+ #############################################
+ #############################################
+
+*/
+
+#include <math.h>
+
+#ifdef __MACH__
+# define sqrtf(x) (sqrt(x))
+#endif
+
+template<class Map>
+float GaussianFilter::getSmoothedPixel(Map *map, int x, int y)
+{
+ float sum = 0.0f;
+ float L = 0.0f;
+ int w = (int)map->width(); //soc
+ int h = (int)map->height(); //soc
+
+ // Current pixel is x,y
+ // Sum surrounding pixels L value:
+ for (int i = -_bound; i <= _bound; ++i) {
+ if ((y + i < 0) || (y + i >= h))
+ continue;
+ for (int j = -_bound; j <= _bound; ++j) {
+ if ((x + j < 0) || (x + j >= w))
+ continue;
+
+ float tmpL = map->pixel(x + j, y + i);
+ float m = _mask[abs(i) * _storedMaskSize + abs(j)];
+ L += m * tmpL;
+ sum += m;
+ }
+ }
+ //L /= sum;
+ return L;
+}
+
+#endif // __GAUSSIANFILTER_H__
diff --git a/source/blender/freestyle/intern/image/Image.h b/source/blender/freestyle/intern/image/Image.h
new file mode 100644
index 00000000000..757f6a8eca3
--- /dev/null
+++ b/source/blender/freestyle/intern/image/Image.h
@@ -0,0 +1,415 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __IMAGE_H__
+#define __IMAGE_H__
+
+/** \file blender/freestyle/intern/image/Image.h
+ * \ingroup freestyle
+ * \brief Class to encapsulate an array of RGB or Gray level values
+ * \author Stephane Grabli
+ * \date 20/05/2003
+ */
+
+#include <string.h> // for memcpy
+
+//
+// Image base class, for all types of images
+//
+///////////////////////////////////////////////////////////////////////////////
+
+/*! This class allows the storing of part of an image, while allowing a normal access to its pixel values.
+ * You can for example only a rectangle of sw*sh, whose lower-left corner is at (ox, oy), of an image of
+ * size w*h, and access these pixels using x,y coordinates specified in the whole image coordinate system.
+ */
+class FrsImage
+{
+public:
+ /*! Default constructor */
+ FrsImage()
+ {
+ _storedWidth = 0;
+ _storedHeight = 0;
+ _width = 0;
+ _height = 0;
+ _Ox = 0;
+ _Oy = 0;
+ }
+
+ /*! Copy constructor */
+ FrsImage(const FrsImage& brother)
+ {
+ _storedWidth = brother._storedWidth;
+ _storedHeight = brother._storedHeight;
+ _width = brother._width;
+ _height = brother._height;
+ _Ox = brother._Ox;
+ _Oy = brother._Oy;
+ }
+
+ /*! Builds an FrsImage from its width and height.
+ * The memory is allocated consequently.
+ */
+ FrsImage(unsigned w, unsigned h)
+ {
+ _width = w;
+ _height = h;
+ _storedWidth = w;
+ _storedHeight = h;
+ _Ox = 0;
+ _Oy = 0;
+ }
+
+ /*! Builds a partial-storing image.
+ * \param w
+ * The width of the complete image
+ * \param h
+ * The height of the complete image
+ * \param sw
+ * The width of the rectangle that will actually be stored.
+ * \param sh
+ * The height of the rectangle that will actually be stored.
+ * \param ox
+ * The x-abscissa of the origin of the rectangle that will actually be stored.
+ * \param oy
+ * The x-abscissa of the origin of the rectangle that will actually be stored.
+ */
+ FrsImage(unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy)
+ {
+ _width = w;
+ _height = h;
+ _storedWidth = sw;
+ _storedHeight = sh;
+ _Ox = ox;
+ _Oy = oy;
+ }
+
+ /*! Operator= */
+ FrsImage& operator=(const FrsImage& brother)
+ {
+ _width = brother._width;
+ _height = brother._height;
+ _storedWidth = brother._storedWidth;
+ _storedHeight = brother._storedHeight;
+ _Ox = brother._Ox;
+ _Oy = brother._Oy;
+ return *this;
+ }
+
+ /*! Destructor */
+ virtual ~FrsImage() {}
+
+ /*! Returns the width of the complete image */
+ inline unsigned width() const
+ {
+ return _width;
+ }
+
+ /*! Returns the height of the complete image */
+ inline unsigned height() const
+ {
+ return _height;
+ }
+
+ /*! Returns the grey value for pixel x,y */
+ virtual float pixel(unsigned x, unsigned y) const = 0;
+
+ /*! Sets the array.
+ * \param array
+ * The array containing the values we wish to store.
+ * Its size is sw*sh.
+ * \param width
+ * The width of the complete image
+ * \param height
+ * The height of the complete image
+ * \param sw
+ * The width of the rectangle that will actually be stored.
+ * \param sh
+ * The height of the rectangle that will actually be stored.
+ * \param ox
+ * The x-abscissa of the origin of the rectangle that will actually be stored.
+ * \param oy
+ * The x-abscissa of the origin of the rectangle that will actually be stored.
+ * \param copy
+ * If true, the array is copied, otherwise the pointer is copied
+ */
+ virtual void setArray(float *array, unsigned width, unsigned height, unsigned sw, unsigned sh,
+ unsigned x, unsigned y, bool copy = true) = 0;
+
+ /*! Returns the array containing the pixels values.
+ * Its size is sw*sh, i.e. potentially a smaller rectangular part of the complete image.
+ */
+ virtual float *getArray() = 0;
+
+protected:
+ unsigned _width;
+ unsigned _height;
+ unsigned _storedWidth;
+ unsigned _storedHeight;
+ unsigned _Ox; // origin of the stored part
+ unsigned _Oy; // origin of the stored part
+};
+
+
+//
+// RGBImage
+//
+///////////////////////////////////////////////////////////////////////////////
+class RGBImage : public FrsImage
+{
+public:
+ RGBImage() : FrsImage()
+ {
+ _rgb = 0;
+ }
+
+ RGBImage(const RGBImage& brother) : FrsImage(brother)
+ {
+ _rgb = new float[3 * _storedWidth * _storedHeight];
+ memcpy(_rgb, brother._rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
+ }
+
+ RGBImage(unsigned w, unsigned h) : FrsImage(w, h)
+ {
+ _rgb = new float[3 * _width * _height];
+ }
+
+ RGBImage(float *rgb, unsigned w, unsigned h) : FrsImage(w, h)
+ {
+ _rgb = new float[3 * _width * _height];
+ memcpy(_rgb, rgb, 3 * _width * _height * sizeof(float));
+ }
+
+ /*! Builds an RGB partial image from the useful part buffer.
+ * \param rgb
+ * The array of size 3*sw*sh containing the RGB values of the sw*sh pixels we need to stored.
+ * These sw*sh pixels constitute a rectangular part of a bigger RGB image containing w*h pixels.
+ * \param w
+ * The width of the complete image
+ * \param h
+ * The height of the complete image
+ * \param sw
+ * The width of the part of the image we want to store and work on
+ * \param sh
+ * The height of the part of the image we want to store and work on
+ */
+ RGBImage(float *rgb, unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy)
+ : FrsImage(w, h, sw, sh, ox, oy)
+ {
+ _rgb = new float[3 * _storedWidth * _storedHeight];
+ memcpy(_rgb, rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
+ }
+
+ RGBImage& operator=(const RGBImage& brother)
+ {
+ dynamic_cast<FrsImage&>(*this) = brother;
+ _rgb = new float[3 * _storedWidth * _storedHeight];
+ memcpy(_rgb, brother._rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
+ return *this;
+ }
+
+ virtual ~RGBImage()
+ {
+ if (_rgb)
+ delete[] _rgb;
+ }
+
+ inline float getR(unsigned x, unsigned y) const
+ {
+ return _rgb[3 * (y - _Oy) * _storedWidth + (x - _Ox) * 3];
+ }
+
+ inline float getG(unsigned x, unsigned y) const
+ {
+ return _rgb[3 * (y - _Oy) * _storedWidth + (x - _Ox) * 3 + 1];
+ }
+
+ inline float getB(unsigned x, unsigned y) const
+ {
+ return _rgb[3 * (y - _Oy) * _storedWidth + (x - _Ox) * 3 + 2];
+ }
+
+ virtual void setPixel(unsigned x, unsigned y, float r, float g, float b)
+ {
+ float *tmp = &(_rgb[3 * (y - _Oy) * _storedWidth + (x - _Ox) * 3]);
+ *tmp = r;
+ tmp++;
+ *tmp = g;
+ tmp++;
+ *tmp = b;
+ }
+
+ virtual float pixel(unsigned x, unsigned y) const
+ {
+ float res = 0.0f;
+ float *tmp = &(_rgb[3 * (y - _Oy) * _storedWidth + (x - _Ox) * 3]);
+ res += 11.0f * (*tmp);
+ tmp++;
+ res += 16.0f * (*tmp);
+ tmp++;
+ res += 5.0f * (*tmp);
+ return res / 32.0f;
+ }
+
+ /*! Sets the RGB array.
+ * copy
+ * If true, the array is copied, otherwise the pointer is copied
+ */
+ virtual void setArray(float *rgb, unsigned width, unsigned height, unsigned sw, unsigned sh,
+ unsigned x, unsigned y, bool copy = true)
+ {
+ _width = width;
+ _height = height;
+ _storedWidth = sw;
+ _storedHeight = sh;
+ _Ox = x;
+ _Oy = y;
+ if (!copy) {
+ _rgb = rgb;
+ return;
+ }
+
+ memcpy(_rgb, rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
+ }
+
+ virtual float *getArray()
+ {
+ return _rgb;
+ }
+
+protected:
+ float *_rgb;
+};
+
+
+//
+// GrayImage
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class GrayImage : public FrsImage
+{
+public:
+ GrayImage() : FrsImage()
+ {
+ _lvl = 0;
+ }
+
+ GrayImage(const GrayImage& brother) : FrsImage(brother)
+ {
+ _lvl = new float[_storedWidth * _storedHeight];
+ memcpy(_lvl, brother._lvl, _storedWidth * _storedHeight * sizeof(*_lvl));
+ }
+
+ /*! Builds an empty gray image */
+ GrayImage(unsigned w, unsigned h) : FrsImage(w, h)
+ {
+ _lvl = new float[_width * _height];
+ }
+
+ GrayImage(float *lvl, unsigned w, unsigned h) : FrsImage(w, h)
+ {
+ _lvl = new float[_width * _height];
+ memcpy(_lvl, lvl, _width * _height * sizeof(*_lvl));
+ }
+
+ /*! Builds a partial image from the useful part buffer.
+ * \param lvl
+ * The array of size sw*sh containing the gray values of the sw*sh pixels we need to stored.
+ * These sw*sh pixels constitute a rectangular part of a bigger gray image containing w*h pixels.
+ * \param w
+ * The width of the complete image
+ * \param h
+ * The height of the complete image
+ * \param sw
+ * The width of the part of the image we want to store and work on
+ * \param sh
+ * The height of the part of the image we want to store and work on
+ */
+ GrayImage(float *lvl, unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy)
+ : FrsImage(w, h, sw, sh, ox, oy)
+ {
+ _lvl = new float[_storedWidth * _storedHeight];
+ memcpy(_lvl, lvl, _storedWidth * _storedHeight * sizeof(float));
+ }
+
+ GrayImage& operator=(const GrayImage& brother)
+ {
+ dynamic_cast<FrsImage&>(*this) = brother;
+ _lvl = new float[_storedWidth * _storedHeight];
+ memcpy(_lvl, brother._lvl, _storedWidth * _storedHeight * sizeof(float));
+ return *this;
+ }
+
+ virtual ~GrayImage()
+ {
+ if (_lvl)
+ delete[] _lvl;
+ }
+
+ inline void setPixel(unsigned x, unsigned y, float v)
+ {
+ _lvl[(y - _Oy) * _storedWidth + (x - _Ox)] = v;
+ }
+
+ inline float pixel(unsigned x, unsigned y) const
+ {
+ return _lvl[(y - _Oy) * _storedWidth + (x - _Ox)];
+ }
+
+ /*! Sets the array.
+ * copy
+ * If true, the array is copie, otherwise the pounsigneder is copied
+ */
+ void setArray(float *lvl, unsigned width, unsigned height, unsigned sw, unsigned sh,
+ unsigned x, unsigned y, bool copy = true)
+ {
+ _width = width;
+ _height = height;
+ _storedWidth = sw;
+ _storedHeight = sh;
+ _Ox = x;
+ _Oy = y;
+ if (!copy) {
+ _lvl = lvl;
+ return;
+ }
+
+ memcpy(_lvl, lvl, _storedWidth * _storedHeight * sizeof(float));
+ }
+
+ /*! Returns the array containing the gray values. */
+ virtual float *getArray()
+ {
+ return _lvl;
+ }
+
+protected:
+ float *_lvl;
+};
+
+#endif // __IMAGE_H__
diff --git a/source/blender/freestyle/intern/image/ImagePyramid.cpp b/source/blender/freestyle/intern/image/ImagePyramid.cpp
new file mode 100644
index 00000000000..b9854782d5b
--- /dev/null
+++ b/source/blender/freestyle/intern/image/ImagePyramid.cpp
@@ -0,0 +1,192 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/image/ImagePyramid.cpp
+ * \ingroup freestyle
+ * \brief Class to represent a pyramid of images
+ * \author Stephane Grabli
+ * \date 25/12/2003
+ */
+
+#include <iostream>
+
+#include "GaussianFilter.h"
+#include "Image.h"
+#include "ImagePyramid.h"
+
+using namespace std;
+
+#if 0
+ImagePyramid::ImagePyramid(const GrayImage& level0, unsigned nbLevels)
+{
+ BuildPyramid(level0,nbLevels);
+}
+#endif
+
+ImagePyramid::ImagePyramid(const ImagePyramid& iBrother)
+{
+ if (!_levels.empty()) {
+ for (vector<GrayImage*>::iterator im = _levels.begin(), imend = _levels.end(); im != imend; ++im) {
+ _levels.push_back(new GrayImage(**im));
+ }
+ }
+}
+
+ImagePyramid::~ImagePyramid()
+{
+ if (!_levels.empty()) {
+ for (vector<GrayImage*>::iterator im = _levels.begin(), imend = _levels.end(); im != imend; ++im) {
+ delete (*im);
+ }
+ _levels.clear();
+ }
+}
+
+GrayImage * ImagePyramid::getLevel(int l)
+{
+ return _levels[l];
+}
+
+float ImagePyramid::pixel(int x, int y, int level)
+{
+ GrayImage *img = _levels[level];
+ if (0 == level) {
+ return img->pixel(x, y);
+ }
+ unsigned int i = 1 << level;
+ unsigned int sx = x >> level;
+ unsigned int sy = y >> level;
+ if (sx >= img->width())
+ sx = img->width() - 1;
+ if (sy >= img->height())
+ sy = img->height() - 1;
+
+ // bilinear interpolation
+ float A = i * (sx + 1) - x;
+ float B = x - i * sx;
+ float C = i * (sy + 1) - y;
+ float D = y - i * sy;
+
+ float P1(0), P2(0);
+ P1 = A * img->pixel(sx, sy);
+ if (sx < img->width() - 1) {
+ if (x % i != 0)
+ P1 += B * img->pixel(sx + 1, sy);
+ }
+ else {
+ P1 += B * img->pixel(sx, sy);
+ }
+ if (sy < img->height() - 1) {
+ if (y % i != 0) {
+ P2 = A * img->pixel(sx, sy + 1);
+ if (sx < img->width() - 1) {
+ if (x % i != 0)
+ P2 += B * img->pixel(sx + 1, sy + 1);
+ }
+ else {
+ P2 += B * img->pixel(sx, sy + 1);
+ }
+ }
+ }
+ else {
+ P2 = P1;
+ }
+ return (1.0f / (float)(1 << (2 * level))) * (C * P1 + D * P2);
+}
+
+int ImagePyramid::width(int level)
+{
+ return _levels[level]->width();
+}
+
+int ImagePyramid::height(int level)
+{
+ return _levels[level]->height();
+}
+
+GaussianPyramid::GaussianPyramid(const GrayImage& level0, unsigned nbLevels, float iSigma) : ImagePyramid()
+{
+ _sigma = iSigma;
+ BuildPyramid(level0, nbLevels);
+}
+
+GaussianPyramid::GaussianPyramid(GrayImage *level0, unsigned nbLevels, float iSigma) : ImagePyramid()
+{
+ _sigma = iSigma;
+ BuildPyramid(level0, nbLevels);
+}
+
+GaussianPyramid::GaussianPyramid(const GaussianPyramid& iBrother) : ImagePyramid(iBrother)
+{
+ _sigma = iBrother._sigma;
+}
+
+void GaussianPyramid::BuildPyramid(const GrayImage& level0, unsigned nbLevels)
+{
+ GrayImage *pLevel = new GrayImage(level0);
+ BuildPyramid(pLevel, nbLevels);
+}
+
+void GaussianPyramid::BuildPyramid(GrayImage *level0, unsigned nbLevels)
+{
+ GrayImage *pLevel = level0;
+ _levels.push_back(pLevel);
+ GaussianFilter gf(_sigma);
+ // build the nbLevels:
+ unsigned w = pLevel->width();
+ unsigned h = pLevel->height();
+ if (nbLevels != 0) {
+ for (unsigned int i = 0; i < nbLevels; ++i) { //soc
+ w = pLevel->width() >> 1;
+ h = pLevel->height() >> 1;
+ GrayImage *img = new GrayImage(w, h);
+ for (unsigned int y = 0; y < h; ++y) {
+ for (unsigned int x = 0; x < w; ++x) {
+ float v = gf.getSmoothedPixel<GrayImage>(pLevel, 2 * x, 2 * y);
+ img->setPixel(x, y, v);
+ }
+ }
+ _levels.push_back(img);
+ pLevel = img;
+ }
+ }
+ else {
+ while ((w > 1) && (h > 1)) {
+ w = pLevel->width() >> 1;
+ h = pLevel->height() >> 1;
+ GrayImage *img = new GrayImage(w, h);
+ for (unsigned int y = 0; y < h; ++y) {
+ for (unsigned int x = 0; x < w; ++x) {
+ float v = gf.getSmoothedPixel<GrayImage>(pLevel, 2 * x, 2 * y);
+ img->setPixel(x, y, v);
+ }
+ }
+ _levels.push_back(img);
+ pLevel = img;
+ }
+ }
+}
diff --git a/source/blender/freestyle/intern/image/ImagePyramid.h b/source/blender/freestyle/intern/image/ImagePyramid.h
new file mode 100644
index 00000000000..0665874a8e9
--- /dev/null
+++ b/source/blender/freestyle/intern/image/ImagePyramid.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __IMAGEPYRAMID_H__
+#define __IMAGEPYRAMID_H__
+
+/** \file blender/freestyle/intern/image/ImagePyramid.h
+ * \ingroup freestyle
+ * \brief Class to represent a pyramid of images
+ * \author Stephane Grabli
+ * \date 25/12/2003
+ */
+
+#include <vector>
+
+#include "../system/FreestyleConfig.h"
+
+class GrayImage;
+
+class LIB_IMAGE_EXPORT ImagePyramid
+{
+protected:
+ std::vector<GrayImage*> _levels;
+
+public:
+ ImagePyramid() {}
+ ImagePyramid(const ImagePyramid& iBrother);
+ //ImagePyramid(const GrayImage& level0, unsigned nbLevels);
+ virtual ~ImagePyramid();
+
+ /*! Builds the pyramid.
+ * must be overloaded by inherited classes.
+ * if nbLevels==0, the complete pyramid is built
+ */
+ virtual void BuildPyramid(const GrayImage& level0, unsigned nbLevels) = 0;
+
+ /*! Builds a pyramid without copying the base level */
+ virtual void BuildPyramid(GrayImage *level0, unsigned nbLevels) = 0;
+
+ virtual GrayImage *getLevel(int l);
+ /*! Returns the pixel x,y using bilinear interpolation.
+ * \param x
+ * the abscissa specified in the finest level coordinate system
+ * \param y
+ * the ordinate specified in the finest level coordinate system
+ * \param level
+ * the level from which we want the pixel to be evaluated
+ */
+ virtual float pixel(int x, int y, int level=0);
+
+ /*! Returns the width of the level-th level image */
+ virtual int width(int level=0);
+
+ /*! Returns the height of the level-th level image */
+ virtual int height(int level=0);
+
+ /*! Returns the number of levels in the pyramid */
+ inline int getNumberOfLevels() const
+ {
+ return _levels.size();
+ }
+};
+
+class LIB_IMAGE_EXPORT GaussianPyramid : public ImagePyramid
+{
+protected:
+ float _sigma;
+
+public:
+ GaussianPyramid(float iSigma=1.f) : ImagePyramid()
+ {
+ _sigma = iSigma;
+ }
+
+ GaussianPyramid(const GrayImage& level0, unsigned nbLevels, float iSigma=1.0f);
+ GaussianPyramid(GrayImage *level0, unsigned nbLevels, float iSigma=1.0f);
+ GaussianPyramid(const GaussianPyramid& iBrother);
+ virtual ~GaussianPyramid() {}
+
+ virtual void BuildPyramid(const GrayImage& level0, unsigned nbLevels);
+ virtual void BuildPyramid(GrayImage *level0, unsigned nbLevels);
+
+ /* accessors */
+ inline float getSigma() const
+ {
+ return _sigma;
+ }
+
+ /* modifiers */
+};
+
+#endif // __IMAGEPYRAMID_H__
diff --git a/source/blender/freestyle/intern/python/BPy_BBox.cpp b/source/blender/freestyle/intern/python/BPy_BBox.cpp
new file mode 100644
index 00000000000..1fff08dbd8f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_BBox.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/python/BPy_BBox.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_BBox.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int BBox_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&BBox_Type) < 0)
+ return -1;
+ Py_INCREF(&BBox_Type);
+ PyModule_AddObject(module, "BBox", (PyObject *)&BBox_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+PyDoc_STRVAR(BBox_doc,
+"Class for representing a bounding box.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.");
+
+static int BBox_init(BPy_BBox *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->bb = new BBox< Vec3r>();
+ return 0;
+}
+
+static void BBox_dealloc(BPy_BBox *self)
+{
+ delete self->bb;
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *BBox_repr(BPy_BBox *self)
+{
+ return PyUnicode_FromFormat("BBox - address: %p", self->bb);
+}
+
+/*-----------------------BPy_BBox type definition ------------------------------*/
+
+PyTypeObject BBox_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BBox", /* tp_name */
+ sizeof(BPy_BBox), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)BBox_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)BBox_repr, /* 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 */
+ BBox_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 */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)BBox_init, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_BBox.h b/source/blender/freestyle/intern/python/BPy_BBox.h
new file mode 100644
index 00000000000..6bd466ac1f1
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_BBox.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_BBox.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_BBOX_H__
+#define __FREESTYLE_PYTHON_BBOX_H__
+
+#include <Python.h>
+
+#include "../geometry/BBox.h"
+#include "../geometry/Geom.h"
+using namespace Geometry;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject BBox_Type;
+
+#define BPy_BBox_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&BBox_Type))
+
+/*---------------------------Python BPy_BBox structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ BBox<Vec3r> *bb;
+} BPy_BBox;
+
+/*---------------------------Python BPy_BBox visible prototypes-----------*/
+
+int BBox_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_BBOX_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp
new file mode 100644
index 00000000000..dc87e283855
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp
@@ -0,0 +1,193 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_BinaryPredicate0D.h"
+
+#include "BPy_Convert.h"
+#include "BPy_Interface0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int BinaryPredicate0D_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&BinaryPredicate0D_Type) < 0)
+ return -1;
+ Py_INCREF(&BinaryPredicate0D_Type);
+ PyModule_AddObject(module, "BinaryPredicate0D", (PyObject *)&BinaryPredicate0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char BinaryPredicate0D___doc__[] =
+"Base class for binary predicates working on :class:`Interface0D`\n"
+"objects. A BinaryPredicate0D is typically an ordering relation\n"
+"between two Interface0D objects. The predicate evaluates a relation\n"
+"between the two Interface0D instances and returns a boolean value (true\n"
+"or false). It is used by invoking the __call__() method.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Must be overload by inherited classes. It evaluates a relation\n"
+" between two Interface0D objects.\n"
+"\n"
+" :arg inter1: The first Interface0D object.\n"
+" :type inter1: :class:`Interface0D`\n"
+" :arg inter2: The second Interface0D object.\n"
+" :type inter2: :class:`Interface0D`\n"
+" :return: True or false.\n"
+" :rtype: bool\n";
+
+static int BinaryPredicate0D___init__(BPy_BinaryPredicate0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->bp0D = new BinaryPredicate0D();
+ self->bp0D->py_bp0D = (PyObject *)self;
+ return 0;
+}
+
+static void BinaryPredicate0D___dealloc__(BPy_BinaryPredicate0D *self)
+{
+ if (self->bp0D)
+ delete self->bp0D;
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *BinaryPredicate0D___repr__(BPy_BinaryPredicate0D *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->bp0D);
+}
+
+static PyObject *BinaryPredicate0D___call__(BPy_BinaryPredicate0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"inter1", "inter2", NULL};
+ BPy_Interface0D *obj1, *obj2;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!", (char **)kwlist,
+ &Interface0D_Type, &obj1, &Interface0D_Type, &obj2))
+ {
+ return NULL;
+ }
+ if (typeid(*(self->bp0D)) == typeid(BinaryPredicate0D)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->bp0D->operator()(*(obj1->if0D), *(obj2->if0D)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return PyBool_from_bool(self->bp0D->result);
+}
+
+/*----------------------BinaryPredicate0D get/setters ----------------------------*/
+
+PyDoc_STRVAR(BinaryPredicate0D_name_doc,
+"The name of the binary 0D predicate.\n"
+"\n"
+":type: str");
+
+static PyObject *BinaryPredicate0D_name_get(BPy_BinaryPredicate0D *self, void *UNUSED(closure))
+{
+ return PyUnicode_FromString(Py_TYPE(self)->tp_name);
+}
+
+static PyGetSetDef BPy_BinaryPredicate0D_getseters[] = {
+ {(char *)"name", (getter)BinaryPredicate0D_name_get, (setter)NULL, (char *)BinaryPredicate0D_name_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_BinaryPredicate0D type definition ------------------------------*/
+
+PyTypeObject BinaryPredicate0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BinaryPredicate0D", /* tp_name */
+ sizeof(BPy_BinaryPredicate0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)BinaryPredicate0D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)BinaryPredicate0D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)BinaryPredicate0D___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ BinaryPredicate0D___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 */
+ BPy_BinaryPredicate0D_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)BinaryPredicate0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h
new file mode 100644
index 00000000000..3df74492c3e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_BINARYPREDICATE0D_H__
+#define __FREESTYLE_PYTHON_BINARYPREDICATE0D_H__
+
+#include <Python.h>
+
+#include "../stroke/Predicates0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject BinaryPredicate0D_Type;
+
+#define BPy_BinaryPredicate0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&BinaryPredicate0D_Type))
+
+/*---------------------------Python BPy_BinaryPredicate0D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ BinaryPredicate0D *bp0D;
+} BPy_BinaryPredicate0D;
+
+/*---------------------------Python BPy_BinaryPredicate0D visible prototypes-----------*/
+
+int BinaryPredicate0D_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_BINARYPREDICATE0D_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp
new file mode 100644
index 00000000000..252fb8a7898
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_BinaryPredicate1D.h"
+
+#include "BPy_Convert.h"
+#include "BPy_Interface1D.h"
+
+#include "BinaryPredicate1D/BPy_FalseBP1D.h"
+#include "BinaryPredicate1D/BPy_Length2DBP1D.h"
+#include "BinaryPredicate1D/BPy_SameShapeIdBP1D.h"
+#include "BinaryPredicate1D/BPy_TrueBP1D.h"
+#include "BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int BinaryPredicate1D_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&BinaryPredicate1D_Type) < 0)
+ return -1;
+ Py_INCREF(&BinaryPredicate1D_Type);
+ PyModule_AddObject(module, "BinaryPredicate1D", (PyObject *)&BinaryPredicate1D_Type);
+
+ if (PyType_Ready(&FalseBP1D_Type) < 0)
+ return -1;
+ Py_INCREF(&FalseBP1D_Type);
+ PyModule_AddObject(module, "FalseBP1D", (PyObject *)&FalseBP1D_Type);
+
+ if (PyType_Ready(&Length2DBP1D_Type) < 0)
+ return -1;
+ Py_INCREF(&Length2DBP1D_Type);
+ PyModule_AddObject(module, "Length2DBP1D", (PyObject *)&Length2DBP1D_Type);
+
+ if (PyType_Ready(&SameShapeIdBP1D_Type) < 0)
+ return -1;
+ Py_INCREF(&SameShapeIdBP1D_Type);
+ PyModule_AddObject(module, "SameShapeIdBP1D", (PyObject *)&SameShapeIdBP1D_Type);
+
+ if (PyType_Ready(&TrueBP1D_Type) < 0)
+ return -1;
+ Py_INCREF(&TrueBP1D_Type);
+ PyModule_AddObject(module, "TrueBP1D", (PyObject *)&TrueBP1D_Type);
+
+ if (PyType_Ready(&ViewMapGradientNormBP1D_Type) < 0)
+ return -1;
+ Py_INCREF(&ViewMapGradientNormBP1D_Type);
+ PyModule_AddObject(module, "ViewMapGradientNormBP1D", (PyObject *)&ViewMapGradientNormBP1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char BinaryPredicate1D___doc__[] =
+"Base class for binary predicates working on :class:`Interface1D`\n"
+"objects. A BinaryPredicate1D is typically an ordering relation\n"
+"between two Interface1D objects. The predicate evaluates a relation\n"
+"between the two Interface1D instances and returns a boolean value (true\n"
+"or false). It is used by invoking the __call__() method.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Must be overload by inherited classes. It evaluates a relation\n"
+" between two Interface1D objects.\n"
+"\n"
+" :arg inter1: The first Interface1D object.\n"
+" :type inter1: :class:`Interface1D`\n"
+" :arg inter2: The second Interface1D object.\n"
+" :type inter2: :class:`Interface1D`\n"
+" :return: True or false.\n"
+" :rtype: bool\n";
+
+static int BinaryPredicate1D___init__(BPy_BinaryPredicate1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->bp1D = new BinaryPredicate1D();
+ self->bp1D->py_bp1D = (PyObject *)self;
+ return 0;
+}
+
+static void BinaryPredicate1D___dealloc__(BPy_BinaryPredicate1D *self)
+{
+ if (self->bp1D)
+ delete self->bp1D;
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *BinaryPredicate1D___repr__(BPy_BinaryPredicate1D *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->bp1D);
+}
+
+static PyObject *BinaryPredicate1D___call__(BPy_BinaryPredicate1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"inter1", "inter2", NULL};
+ BPy_Interface1D *obj1, *obj2;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!", (char **)kwlist,
+ &Interface1D_Type, &obj1, &Interface1D_Type, &obj2))
+ {
+ return NULL;
+ }
+ if (typeid(*(self->bp1D)) == typeid(BinaryPredicate1D)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->bp1D->operator()(*(obj1->if1D), *(obj2->if1D)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return PyBool_from_bool(self->bp1D->result);
+}
+
+/*----------------------BinaryPredicate0D get/setters ----------------------------*/
+
+PyDoc_STRVAR(BinaryPredicate1D_name_doc,
+"The name of the binary 1D predicate.\n"
+"\n"
+":type: str");
+
+static PyObject *BinaryPredicate1D_name_get(BPy_BinaryPredicate1D *self, void *UNUSED(closure))
+{
+ return PyUnicode_FromString(Py_TYPE(self)->tp_name);
+}
+
+static PyGetSetDef BPy_BinaryPredicate1D_getseters[] = {
+ {(char *)"name", (getter)BinaryPredicate1D_name_get, (setter)NULL, (char *)BinaryPredicate1D_name_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_BinaryPredicate1D type definition ------------------------------*/
+PyTypeObject BinaryPredicate1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BinaryPredicate1D", /* tp_name */
+ sizeof(BPy_BinaryPredicate1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)BinaryPredicate1D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)BinaryPredicate1D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)BinaryPredicate1D___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ BinaryPredicate1D___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 */
+ BPy_BinaryPredicate1D_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)BinaryPredicate1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h
new file mode 100644
index 00000000000..1f4511e0815
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_BINARYPREDICATE1D_H__
+#define __FREESTYLE_PYTHON_BINARYPREDICATE1D_H__
+
+#include <Python.h>
+
+#include "../stroke/Predicates1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject BinaryPredicate1D_Type;
+
+#define BPy_BinaryPredicate1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&BinaryPredicate1D_Type))
+
+/*---------------------------Python BPy_BinaryPredicate1D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ BinaryPredicate1D *bp1D;
+} BPy_BinaryPredicate1D;
+
+/*---------------------------Python BPy_BinaryPredicate1D visible prototypes-----------*/
+
+int BinaryPredicate1D_Init(PyObject *module);
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_BINARYPREDICATE1D_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp b/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp
new file mode 100644
index 00000000000..ed3aa882c6a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp
@@ -0,0 +1,287 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ContextFunctions.h"
+#include "BPy_Convert.h"
+
+#include "../stroke/ContextFunctions.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------ MODULE FUNCTIONS ----------------------------------
+
+static char ContextFunctions_get_time_stamp___doc__[] =
+".. function:: get_time_stamp()\n"
+"\n"
+" Returns the system time stamp.\n"
+"\n"
+" :return: The system time stamp.\n"
+" :rtype: int\n";
+
+static PyObject *
+ContextFunctions_get_time_stamp(PyObject *self)
+{
+ return PyLong_FromLong(ContextFunctions::GetTimeStampCF());
+}
+
+static char ContextFunctions_get_canvas_width___doc__[] =
+".. method:: get_canvas_width()\n"
+"\n"
+" Returns the canvas width.\n"
+"\n"
+" :return: The canvas width.\n"
+" :rtype: int\n";
+
+static PyObject *
+ContextFunctions_get_canvas_width(PyObject *self)
+{
+ return PyLong_FromLong(ContextFunctions::GetCanvasWidthCF());
+}
+
+static char ContextFunctions_get_canvas_height___doc__[] =
+".. method:: get_canvas_height()\n"
+"\n"
+" Returns the canvas height.\n"
+"\n"
+" :return: The canvas height.\n"
+" :rtype: int\n";
+
+static PyObject *
+ContextFunctions_get_canvas_height(PyObject *self)
+{
+ return PyLong_FromLong(ContextFunctions::GetCanvasHeightCF());
+}
+
+static char ContextFunctions_load_map___doc__[] =
+".. function:: load_map(file_name, map_name, num_levels=4, sigma=1.0)\n"
+"\n"
+" Loads an image map for further reading.\n"
+"\n"
+" :arg file_name: The name of the image file.\n"
+" :type file_name: str\n"
+" :arg map_name: The name that will be used to access this image.\n"
+" :type map_name: str\n"
+" :arg num_levels: The number of levels in the map pyramid\n"
+" (default = 4). If num_levels == 0, the complete pyramid is\n"
+" built.\n"
+" :type num_levels: int\n"
+" :arg sigma: The sigma value of the gaussian function.\n"
+" :type sigma: float\n";
+
+static PyObject *
+ContextFunctions_load_map(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"file_name", "map_name", "num_levels", "sigma", NULL};
+ char *fileName, *mapName;
+ unsigned nbLevels = 4;
+ float sigma = 1.0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|If", (char **)kwlist, &fileName, &mapName, &nbLevels, &sigma))
+ return NULL;
+ ContextFunctions::LoadMapCF(fileName, mapName, nbLevels, sigma);
+ Py_RETURN_NONE;
+}
+
+static char ContextFunctions_read_map_pixel___doc__[] =
+".. function:: read_map_pixel(map_name, level, x, y)\n"
+"\n"
+" Reads a pixel in a user-defined map.\n"
+"\n"
+" :arg map_name: The name of the map.\n"
+" :type map_name: str\n"
+" :arg level: The level of the pyramid in which we wish to read the\n"
+" pixel.\n"
+" :type level: int\n"
+" :arg x: The x coordinate of the pixel we wish to read. The origin\n"
+" is in the lower-left corner.\n"
+" :type x: int\n"
+" :arg y: The y coordinate of the pixel we wish to read. The origin\n"
+" is in the lower-left corner.\n"
+" :type y: int\n"
+" :return: The floating-point value stored for that pixel.\n"
+" :rtype: float\n";
+
+static PyObject *
+ContextFunctions_read_map_pixel(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"map_name", "level", "x", "y", NULL};
+ char *mapName;
+ int level;
+ unsigned x, y;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "siII", (char **)kwlist, &mapName, &level, &x, &y))
+ return NULL;
+ return PyFloat_FromDouble(ContextFunctions::ReadMapPixelCF(mapName, level, x, y));
+}
+
+static char ContextFunctions_read_complete_view_map_pixel___doc__[] =
+".. function:: read_complete_view_map_pixel(level, x, y)\n"
+"\n"
+" Reads a pixel in the complete view map.\n"
+"\n"
+" :arg level: The level of the pyramid in which we wish to read the\n"
+" pixel.\n"
+" :type level: int\n"
+" :arg x: The x coordinate of the pixel we wish to read. The origin\n"
+" is in the lower-left corner.\n"
+" :type x: int\n"
+" :arg y: The y coordinate of the pixel we wish to read. The origin\n"
+" is in the lower-left corner.\n"
+" :type y: int\n"
+" :return: The floating-point value stored for that pixel.\n"
+" :rtype: float\n";
+
+static PyObject *
+ContextFunctions_read_complete_view_map_pixel(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"level", "x", "y", NULL};
+ int level;
+ unsigned x, y;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "iII", (char **)kwlist, &level, &x, &y))
+ return NULL;
+ return PyFloat_FromDouble(ContextFunctions::ReadCompleteViewMapPixelCF(level, x, y));
+}
+
+static char ContextFunctions_read_directional_view_map_pixel___doc__[] =
+".. function:: read_directional_view_map_pixel(orientation, level, x, y)\n"
+"\n"
+" Reads a pixel in one of the oriented view map images.\n"
+"\n"
+" :arg orientation: The number telling which orientation we want to\n"
+" check.\n"
+" :type orientation: int\n"
+" :arg level: The level of the pyramid in which we wish to read the\n"
+" pixel.\n"
+" :type level: int\n"
+" :arg x: The x coordinate of the pixel we wish to read. The origin\n"
+" is in the lower-left corner.\n"
+" :type x: int\n"
+" :arg y: The y coordinate of the pixel we wish to read. The origin\n"
+" is in the lower-left corner.\n"
+" :type y: int\n"
+" :return: The floating-point value stored for that pixel.\n"
+" :rtype: float\n";
+
+static PyObject *
+ContextFunctions_read_directional_view_map_pixel(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"orientation", "level", "x", "y", NULL};
+ int orientation, level;
+ unsigned x, y;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "iiII", (char **)kwlist, &orientation, &level, &x, &y))
+ return NULL;
+ return PyFloat_FromDouble(ContextFunctions::ReadDirectionalViewMapPixelCF(orientation, level, x, y));
+}
+
+static char ContextFunctions_get_selected_fedge___doc__[] =
+".. function:: get_selected_fedge()\n"
+"\n"
+" Returns the selected FEdge.\n"
+"\n"
+" :return: The selected FEdge.\n"
+" :rtype: :class:`FEdge`\n";
+
+static PyObject *
+ContextFunctions_get_selected_fedge(PyObject *self)
+{
+ FEdge *fe = ContextFunctions::GetSelectedFEdgeCF();
+ if (fe)
+ return Any_BPy_FEdge_from_FEdge(*fe);
+ Py_RETURN_NONE;
+}
+
+/*-----------------------ContextFunctions module docstring-------------------------------*/
+
+static char module_docstring[] = "The Blender Freestyle.ContextFunctions submodule\n\n";
+
+/*-----------------------ContextFunctions module functions definitions-------------------*/
+
+static PyMethodDef module_functions[] = {
+ {"get_time_stamp", (PyCFunction)ContextFunctions_get_time_stamp, METH_NOARGS,
+ ContextFunctions_get_time_stamp___doc__},
+ {"get_canvas_width", (PyCFunction)ContextFunctions_get_canvas_width, METH_NOARGS,
+ ContextFunctions_get_canvas_width___doc__},
+ {"get_canvas_height", (PyCFunction)ContextFunctions_get_canvas_height, METH_NOARGS,
+ ContextFunctions_get_canvas_height___doc__},
+ {"load_map", (PyCFunction)ContextFunctions_load_map, METH_VARARGS | METH_KEYWORDS,
+ ContextFunctions_load_map___doc__},
+ {"read_map_pixel", (PyCFunction)ContextFunctions_read_map_pixel, METH_VARARGS | METH_KEYWORDS,
+ ContextFunctions_read_map_pixel___doc__},
+ {"read_complete_view_map_pixel", (PyCFunction)ContextFunctions_read_complete_view_map_pixel,
+ METH_VARARGS | METH_KEYWORDS,
+ ContextFunctions_read_complete_view_map_pixel___doc__},
+ {"read_directional_view_map_pixel", (PyCFunction)ContextFunctions_read_directional_view_map_pixel,
+ METH_VARARGS | METH_KEYWORDS,
+ ContextFunctions_read_directional_view_map_pixel___doc__},
+ {"get_selected_fedge", (PyCFunction)ContextFunctions_get_selected_fedge, METH_NOARGS,
+ ContextFunctions_get_selected_fedge___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------ContextFunctions module definition--------------------------------*/
+
+static PyModuleDef module_definition = {
+ PyModuleDef_HEAD_INIT,
+ "Freestyle.ContextFunctions",
+ module_docstring,
+ -1,
+ module_functions
+};
+
+//------------------- MODULE INITIALIZATION --------------------------------
+
+int ContextFunctions_Init(PyObject *module)
+{
+ PyObject *m;
+
+ if (module == NULL)
+ return -1;
+
+ m = PyModule_Create(&module_definition);
+ if (m == NULL)
+ return -1;
+ Py_INCREF(m);
+ PyModule_AddObject(module, "ContextFunctions", m);
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.cpp b/source/blender/freestyle/intern/python/BPy_ContextFunctions.h
index 142318cc7c2..9f124dc970a 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.cpp
+++ b/source/blender/freestyle/intern/python/BPy_ContextFunctions.h
@@ -15,7 +15,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
* All rights reserved.
*
* The Original Code is: all of this file.
@@ -25,21 +25,25 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file gameengine/Physics/common/PHY_IPhysicsEnvironment.cpp
- * \ingroup phys
+/** \file source/blender/freestyle/intern/python/BPy_ContextFunctions.h
+ * \ingroup freestyle
*/
+#ifndef __FREESTYLE_PYTHON_CONTEXTFUNCTIONS_H__
+#define __FREESTYLE_PYTHON_CONTEXTFUNCTIONS_H__
-#include "PHY_IPhysicsEnvironment.h"
+#include <Python.h>
-/**
-* Physics Environment takes care of stepping the simulation and is a container for physics entities (rigidbodies,constraints, materials etc.)
-* A derived class may be able to 'construct' entities by loading and/or converting
-*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*---------------------------Python BPy_ContextFunctions visible prototypes-----------*/
+int ContextFunctions_Init(PyObject *module);
-PHY_IPhysicsEnvironment::~PHY_IPhysicsEnvironment()
-{
-
+#ifdef __cplusplus
}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_CONTEXTFUNCTIONS_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_Convert.cpp b/source/blender/freestyle/intern/python/BPy_Convert.cpp
new file mode 100644
index 00000000000..daf643c20c0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Convert.cpp
@@ -0,0 +1,723 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_Convert.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_Convert.h"
+
+#include "BPy_BBox.h"
+#include "BPy_FrsMaterial.h"
+#include "BPy_Id.h"
+#include "BPy_IntegrationType.h"
+#include "BPy_Interface0D.h"
+#include "Interface0D/BPy_CurvePoint.h"
+#include "Interface0D/CurvePoint/BPy_StrokeVertex.h"
+#include "Interface0D/BPy_SVertex.h"
+#include "Interface0D/BPy_ViewVertex.h"
+#include "Interface0D/ViewVertex/BPy_NonTVertex.h"
+#include "Interface0D/ViewVertex/BPy_TVertex.h"
+#include "BPy_Interface1D.h"
+#include "Interface1D/BPy_FEdge.h"
+#include "Interface1D/BPy_Stroke.h"
+#include "Interface1D/BPy_ViewEdge.h"
+#include "Interface1D/Curve/BPy_Chain.h"
+#include "Interface1D/FEdge/BPy_FEdgeSharp.h"
+#include "Interface1D/FEdge/BPy_FEdgeSmooth.h"
+#include "BPy_Nature.h"
+#include "BPy_MediumType.h"
+#include "BPy_SShape.h"
+#include "BPy_StrokeAttribute.h"
+#include "BPy_ViewShape.h"
+
+#include "Iterator/BPy_AdjacencyIterator.h"
+#include "Iterator/BPy_ChainPredicateIterator.h"
+#include "Iterator/BPy_ChainSilhouetteIterator.h"
+#include "Iterator/BPy_ChainingIterator.h"
+#include "Iterator/BPy_CurvePointIterator.h"
+#include "Iterator/BPy_Interface0DIterator.h"
+#include "Iterator/BPy_SVertexIterator.h"
+#include "Iterator/BPy_StrokeVertexIterator.h"
+#include "Iterator/BPy_ViewEdgeIterator.h"
+#include "Iterator/BPy_orientedViewEdgeIterator.h"
+
+#include "../stroke/StrokeRep.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//==============================
+// C++ => Python
+//==============================
+
+PyObject *PyBool_from_bool(bool b)
+{
+ return PyBool_FromLong(b ? 1 : 0);
+}
+
+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);
+}
+
+PyObject *Vector_from_Vec3f(Vec3f& vec)
+{
+ float vec_data[3]; // because vec->_coord is protected
+ vec_data[0] = vec.x();
+ vec_data[1] = vec.y();
+ vec_data[2] = vec.z();
+ return Vector_CreatePyObject(vec_data, 3, Py_NEW, NULL);
+}
+
+PyObject *Vector_from_Vec3r(Vec3r& vec)
+{
+ float vec_data[3]; // because vec->_coord is protected
+ vec_data[0] = vec.x();
+ vec_data[1] = vec.y();
+ vec_data[2] = vec.z();
+ return Vector_CreatePyObject(vec_data, 3, Py_NEW, NULL);
+}
+
+PyObject *BPy_Id_from_Id(Id& id)
+{
+ PyObject *py_id = Id_Type.tp_new(&Id_Type, 0, 0);
+ ((BPy_Id *)py_id)->id = new Id(id.getFirst(), id.getSecond());
+ return py_id;
+}
+
+PyObject *Any_BPy_Interface0D_from_Interface0D(Interface0D& if0D)
+{
+ if (typeid(if0D) == typeid(CurvePoint)) {
+ return BPy_CurvePoint_from_CurvePoint(dynamic_cast<CurvePoint&>(if0D));
+ }
+ else if (typeid(if0D) == typeid(StrokeVertex)) {
+ return BPy_StrokeVertex_from_StrokeVertex(dynamic_cast<StrokeVertex&>(if0D));
+ }
+ else if (typeid(if0D) == typeid(SVertex)) {
+ return BPy_SVertex_from_SVertex(dynamic_cast<SVertex&>(if0D));
+ }
+ else if (typeid(if0D) == typeid(ViewVertex)) {
+ return BPy_ViewVertex_from_ViewVertex(dynamic_cast<ViewVertex&>(if0D));
+ }
+ else if (typeid(if0D) == typeid(NonTVertex)) {
+ return BPy_NonTVertex_from_NonTVertex(dynamic_cast<NonTVertex&>(if0D));
+ }
+ else if (typeid(if0D) == typeid(TVertex)) {
+ return BPy_TVertex_from_TVertex(dynamic_cast<TVertex&>(if0D));
+ }
+ else if (typeid(if0D) == typeid(Interface0D)) {
+ return BPy_Interface0D_from_Interface0D(if0D);
+ }
+ string msg("unexpected type: " + if0D.getExactTypeName());
+ PyErr_SetString(PyExc_TypeError, msg.c_str());
+ return NULL;
+}
+
+PyObject *Any_BPy_Interface1D_from_Interface1D(Interface1D& if1D)
+{
+ if (typeid(if1D) == typeid(ViewEdge)) {
+ return BPy_ViewEdge_from_ViewEdge(dynamic_cast<ViewEdge&>(if1D));
+ }
+ else if (typeid(if1D) == typeid(Chain)) {
+ return BPy_Chain_from_Chain(dynamic_cast<Chain&>(if1D));
+ }
+ else if (typeid(if1D) == typeid(Stroke)) {
+ return BPy_Stroke_from_Stroke(dynamic_cast<Stroke&>(if1D));
+ }
+ else if (typeid(if1D) == typeid(FEdgeSharp)) {
+ return BPy_FEdgeSharp_from_FEdgeSharp(dynamic_cast<FEdgeSharp&>(if1D));
+ }
+ else if (typeid(if1D) == typeid(FEdgeSmooth)) {
+ return BPy_FEdgeSmooth_from_FEdgeSmooth(dynamic_cast<FEdgeSmooth&>(if1D));
+ }
+ else if (typeid(if1D) == typeid(FEdge)) {
+ return BPy_FEdge_from_FEdge(dynamic_cast<FEdge&>(if1D));
+ }
+ else if (typeid(if1D) == typeid(Interface1D)) {
+ return BPy_Interface1D_from_Interface1D(if1D);
+ }
+ string msg("unexpected type: " + if1D.getExactTypeName());
+ PyErr_SetString(PyExc_TypeError, msg.c_str());
+ return NULL;
+}
+
+PyObject *Any_BPy_FEdge_from_FEdge(FEdge& fe)
+{
+ if (typeid(fe) == typeid(FEdgeSharp)) {
+ return BPy_FEdgeSharp_from_FEdgeSharp(dynamic_cast<FEdgeSharp&>(fe));
+ }
+ else if (typeid(fe) == typeid(FEdgeSmooth)) {
+ return BPy_FEdgeSmooth_from_FEdgeSmooth(dynamic_cast<FEdgeSmooth&>(fe));
+ }
+ else if (typeid(fe) == typeid(FEdge)) {
+ return BPy_FEdge_from_FEdge(fe);
+ }
+ string msg("unexpected type: " + fe.getExactTypeName());
+ PyErr_SetString(PyExc_TypeError, msg.c_str());
+ return NULL;
+}
+
+PyObject *Any_BPy_ViewVertex_from_ViewVertex(ViewVertex& vv)
+{
+ if (typeid(vv) == typeid(NonTVertex)) {
+ return BPy_NonTVertex_from_NonTVertex(dynamic_cast<NonTVertex&>(vv));
+ }
+ else if (typeid(vv) == typeid(TVertex)) {
+ return BPy_TVertex_from_TVertex(dynamic_cast<TVertex&>(vv));
+ }
+ else if (typeid(vv) == typeid(ViewVertex)) {
+ return BPy_ViewVertex_from_ViewVertex(vv);
+ }
+ string msg("unexpected type: " + vv.getExactTypeName());
+ PyErr_SetString(PyExc_TypeError, msg.c_str());
+ return NULL;
+}
+
+PyObject *BPy_Interface0D_from_Interface0D(Interface0D& if0D)
+{
+ PyObject *py_if0D = Interface0D_Type.tp_new(&Interface0D_Type, 0, 0);
+ ((BPy_Interface0D *)py_if0D)->if0D = &if0D;
+ ((BPy_Interface0D *)py_if0D)->borrowed = 1;
+ return py_if0D;
+}
+
+PyObject *BPy_Interface1D_from_Interface1D(Interface1D& if1D)
+{
+ PyObject *py_if1D = Interface1D_Type.tp_new(&Interface1D_Type, 0, 0);
+ ((BPy_Interface1D *)py_if1D)->if1D = &if1D;
+ ((BPy_Interface1D *)py_if1D)->borrowed = 1;
+ return py_if1D;
+}
+
+PyObject *BPy_SVertex_from_SVertex(SVertex& sv)
+{
+ PyObject *py_sv = SVertex_Type.tp_new(&SVertex_Type, 0, 0);
+ ((BPy_SVertex *)py_sv)->sv = &sv;
+ ((BPy_SVertex *)py_sv)->py_if0D.if0D = ((BPy_SVertex *)py_sv)->sv;
+ ((BPy_SVertex *)py_sv)->py_if0D.borrowed = 1;
+ return py_sv;
+}
+
+PyObject *BPy_FEdgeSharp_from_FEdgeSharp(FEdgeSharp& fes)
+{
+ PyObject *py_fe = FEdgeSharp_Type.tp_new(&FEdgeSharp_Type, 0, 0);
+ ((BPy_FEdgeSharp *)py_fe)->fes = &fes;
+ ((BPy_FEdgeSharp *)py_fe)->py_fe.fe = ((BPy_FEdgeSharp *)py_fe)->fes;
+ ((BPy_FEdgeSharp *)py_fe)->py_fe.py_if1D.if1D = ((BPy_FEdgeSharp *)py_fe)->fes;
+ ((BPy_FEdgeSharp *)py_fe)->py_fe.py_if1D.borrowed = 1;
+ return py_fe;
+}
+
+PyObject *BPy_FEdgeSmooth_from_FEdgeSmooth(FEdgeSmooth& fes)
+{
+ PyObject *py_fe = FEdgeSmooth_Type.tp_new(&FEdgeSmooth_Type, 0, 0);
+ ((BPy_FEdgeSmooth *)py_fe)->fes = &fes;
+ ((BPy_FEdgeSmooth *)py_fe)->py_fe.fe = ((BPy_FEdgeSmooth *)py_fe)->fes;
+ ((BPy_FEdgeSmooth *)py_fe)->py_fe.py_if1D.if1D = ((BPy_FEdgeSmooth *)py_fe)->fes;
+ ((BPy_FEdgeSmooth *)py_fe)->py_fe.py_if1D.borrowed = 1;
+ return py_fe;
+}
+
+PyObject *BPy_FEdge_from_FEdge(FEdge& fe)
+{
+ PyObject *py_fe = FEdge_Type.tp_new(&FEdge_Type, 0, 0);
+ ((BPy_FEdge *)py_fe)->fe = &fe;
+ ((BPy_FEdge *)py_fe)->py_if1D.if1D = ((BPy_FEdge *)py_fe)->fe;
+ ((BPy_FEdge *)py_fe)->py_if1D.borrowed = 1;
+ return py_fe;
+}
+
+PyObject *BPy_Nature_from_Nature(unsigned short n)
+{
+ PyObject *args = PyTuple_New(1);
+ PyTuple_SET_ITEM(args, 0, PyLong_FromLong(n));
+ PyObject *py_n = Nature_Type.tp_new(&Nature_Type, args, NULL);
+ Py_DECREF(args);
+ return py_n;
+}
+
+PyObject *BPy_Stroke_from_Stroke(Stroke& s)
+{
+ PyObject *py_s = Stroke_Type.tp_new(&Stroke_Type, 0, 0);
+ ((BPy_Stroke *)py_s)->s = &s;
+ ((BPy_Stroke *)py_s)->py_if1D.if1D = ((BPy_Stroke *)py_s)->s;
+ ((BPy_Stroke *)py_s)->py_if1D.borrowed = 1;
+ return py_s;
+}
+
+PyObject *BPy_StrokeAttribute_from_StrokeAttribute(StrokeAttribute& sa)
+{
+ PyObject *py_sa = StrokeAttribute_Type.tp_new(&StrokeAttribute_Type, 0, 0);
+ ((BPy_StrokeAttribute *)py_sa)->sa = &sa;
+ ((BPy_StrokeAttribute *)py_sa)->borrowed = 1;
+ return py_sa;
+}
+
+PyObject *BPy_MediumType_from_MediumType(Stroke::MediumType n)
+{
+ PyObject *args = PyTuple_New(1);
+ PyTuple_SET_ITEM(args, 0, PyLong_FromLong(n));
+ PyObject *py_mt = MediumType_Type.tp_new(&MediumType_Type, args, NULL);
+ Py_DECREF(args);
+ return py_mt;
+}
+
+PyObject *BPy_StrokeVertex_from_StrokeVertex(StrokeVertex& sv)
+{
+ PyObject *py_sv = StrokeVertex_Type.tp_new(&StrokeVertex_Type, 0, 0);
+ ((BPy_StrokeVertex *)py_sv)->sv = &sv;
+ ((BPy_StrokeVertex *)py_sv)->py_cp.cp = ((BPy_StrokeVertex *)py_sv)->sv;
+ ((BPy_StrokeVertex *)py_sv)->py_cp.py_if0D.if0D = ((BPy_StrokeVertex *)py_sv)->sv;
+ ((BPy_StrokeVertex *)py_sv)->py_cp.py_if0D.borrowed = 1;
+ return py_sv;
+}
+
+PyObject *BPy_ViewVertex_from_ViewVertex(ViewVertex& vv)
+{
+ PyObject *py_vv = ViewVertex_Type.tp_new(&ViewVertex_Type, 0, 0);
+ ((BPy_ViewVertex *)py_vv)->vv = &vv;
+ ((BPy_ViewVertex *)py_vv)->py_if0D.if0D = ((BPy_ViewVertex *)py_vv)->vv;
+ ((BPy_ViewVertex *)py_vv)->py_if0D.borrowed = 1;
+ return py_vv;
+}
+
+PyObject *BPy_NonTVertex_from_NonTVertex(NonTVertex& ntv)
+{
+ PyObject *py_ntv = NonTVertex_Type.tp_new(&NonTVertex_Type, 0, 0);
+ ((BPy_NonTVertex *)py_ntv)->ntv = &ntv;
+ ((BPy_NonTVertex *)py_ntv)->py_vv.vv = ((BPy_NonTVertex *)py_ntv)->ntv;
+ ((BPy_NonTVertex *)py_ntv)->py_vv.py_if0D.if0D = ((BPy_NonTVertex *)py_ntv)->ntv;
+ ((BPy_NonTVertex *)py_ntv)->py_vv.py_if0D.borrowed = 1;
+ return py_ntv;
+}
+
+PyObject *BPy_TVertex_from_TVertex(TVertex& tv)
+{
+ PyObject *py_tv = TVertex_Type.tp_new(&TVertex_Type, 0, 0);
+ ((BPy_TVertex *)py_tv)->tv = &tv;
+ ((BPy_TVertex *)py_tv)->py_vv.vv = ((BPy_TVertex *)py_tv)->tv;
+ ((BPy_TVertex *)py_tv)->py_vv.py_if0D.if0D = ((BPy_TVertex *)py_tv)->tv;
+ ((BPy_TVertex *)py_tv)->py_vv.py_if0D.borrowed = 1;
+ return py_tv;
+}
+
+PyObject *BPy_BBox_from_BBox(const BBox< Vec3r > &bb)
+{
+ PyObject *py_bb = BBox_Type.tp_new(&BBox_Type, 0, 0);
+ ((BPy_BBox *)py_bb)->bb = new BBox< Vec3r >(bb);
+ return py_bb;
+}
+
+PyObject *BPy_ViewEdge_from_ViewEdge(ViewEdge& ve)
+{
+ PyObject *py_ve = ViewEdge_Type.tp_new(&ViewEdge_Type, 0, 0);
+ ((BPy_ViewEdge *)py_ve)->ve = &ve;
+ ((BPy_ViewEdge *)py_ve)->py_if1D.if1D = ((BPy_ViewEdge *)py_ve)->ve;
+ ((BPy_ViewEdge *)py_ve)->py_if1D.borrowed = 1;
+ return py_ve;
+}
+
+PyObject *BPy_Chain_from_Chain(Chain& c)
+{
+ PyObject *py_c = Chain_Type.tp_new(&Chain_Type, 0, 0);
+ ((BPy_Chain *)py_c)->c = &c;
+ ((BPy_Chain *)py_c)->py_c.c = ((BPy_Chain *)py_c)->c;
+ ((BPy_Chain *)py_c)->py_c.py_if1D.if1D = ((BPy_Chain *)py_c)->c;
+ ((BPy_Chain *)py_c)->py_c.py_if1D.borrowed = 1;
+ return py_c;
+}
+
+PyObject *BPy_SShape_from_SShape(SShape& ss)
+{
+ PyObject *py_ss = SShape_Type.tp_new(&SShape_Type, 0, 0);
+ ((BPy_SShape *)py_ss)->ss = &ss;
+ ((BPy_SShape *)py_ss)->borrowed = 1;
+ return py_ss;
+}
+
+PyObject *BPy_ViewShape_from_ViewShape(ViewShape& vs)
+{
+ PyObject *py_vs = ViewShape_Type.tp_new(&ViewShape_Type, 0, 0);
+ ((BPy_ViewShape *)py_vs)->vs = &vs;
+ ((BPy_ViewShape *)py_vs)->borrowed = 1;
+ ((BPy_ViewShape *)py_vs)->py_ss = NULL;
+ return py_vs;
+}
+
+PyObject *BPy_FrsMaterial_from_FrsMaterial(const FrsMaterial& m)
+{
+ PyObject *py_m = FrsMaterial_Type.tp_new(&FrsMaterial_Type, 0, 0);
+ ((BPy_FrsMaterial *) py_m)->m = new FrsMaterial(m);
+ return py_m;
+}
+
+PyObject *BPy_IntegrationType_from_IntegrationType(IntegrationType i)
+{
+ PyObject *args = PyTuple_New(1);
+ PyTuple_SET_ITEM(args, 0, PyLong_FromLong(i));
+ PyObject *py_it = IntegrationType_Type.tp_new(&IntegrationType_Type, args, NULL);
+ Py_DECREF(args);
+ return py_it;
+}
+
+PyObject *BPy_CurvePoint_from_CurvePoint(CurvePoint& cp)
+{
+ PyObject *py_cp = CurvePoint_Type.tp_new(&CurvePoint_Type, 0, 0);
+ ((BPy_CurvePoint *) py_cp)->cp = &cp;
+ ((BPy_CurvePoint *) py_cp)->py_if0D.if0D = ((BPy_CurvePoint *)py_cp)->cp;
+ ((BPy_CurvePoint *) py_cp)->py_if0D.borrowed = 1;
+ return py_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));
+ return py_dve;
+}
+
+//==============================
+// Iterators
+//==============================
+
+PyObject *BPy_AdjacencyIterator_from_AdjacencyIterator(AdjacencyIterator& a_it)
+{
+ PyObject *py_a_it = AdjacencyIterator_Type.tp_new(&AdjacencyIterator_Type, 0, 0);
+ ((BPy_AdjacencyIterator *)py_a_it)->a_it = new AdjacencyIterator(a_it);
+ ((BPy_AdjacencyIterator *)py_a_it)->py_it.it = ((BPy_AdjacencyIterator *)py_a_it)->a_it;
+ return py_a_it;
+}
+
+PyObject *BPy_Interface0DIterator_from_Interface0DIterator(Interface0DIterator& if0D_it, int reversed)
+{
+ PyObject *py_if0D_it = Interface0DIterator_Type.tp_new(&Interface0DIterator_Type, 0, 0);
+ ((BPy_Interface0DIterator *)py_if0D_it)->if0D_it = new Interface0DIterator(if0D_it);
+ ((BPy_Interface0DIterator *)py_if0D_it)->py_it.it = ((BPy_Interface0DIterator *)py_if0D_it)->if0D_it;
+ ((BPy_Interface0DIterator *)py_if0D_it)->reversed = reversed;
+ return py_if0D_it;
+}
+
+PyObject *BPy_CurvePointIterator_from_CurvePointIterator(CurveInternal::CurvePointIterator& cp_it)
+{
+ PyObject *py_cp_it = CurvePointIterator_Type.tp_new(&CurvePointIterator_Type, 0, 0);
+ ((BPy_CurvePointIterator *)py_cp_it)->cp_it = new CurveInternal::CurvePointIterator(cp_it);
+ ((BPy_CurvePointIterator *)py_cp_it)->py_it.it = ((BPy_CurvePointIterator *)py_cp_it)->cp_it;
+ return py_cp_it;
+}
+
+PyObject *BPy_StrokeVertexIterator_from_StrokeVertexIterator(StrokeInternal::StrokeVertexIterator& sv_it, int reversed)
+{
+ PyObject *py_sv_it = StrokeVertexIterator_Type.tp_new(&StrokeVertexIterator_Type, 0, 0);
+ ((BPy_StrokeVertexIterator *)py_sv_it)->sv_it = new StrokeInternal::StrokeVertexIterator(sv_it);
+ ((BPy_StrokeVertexIterator *)py_sv_it)->py_it.it = ((BPy_StrokeVertexIterator *)py_sv_it)->sv_it;
+ ((BPy_StrokeVertexIterator *)py_sv_it)->reversed = reversed;
+ return py_sv_it;
+}
+
+PyObject *BPy_SVertexIterator_from_SVertexIterator(ViewEdgeInternal::SVertexIterator& sv_it)
+{
+ PyObject *py_sv_it = SVertexIterator_Type.tp_new(&SVertexIterator_Type, 0, 0);
+ ((BPy_SVertexIterator *)py_sv_it)->sv_it = new ViewEdgeInternal::SVertexIterator(sv_it);
+ ((BPy_SVertexIterator *)py_sv_it)->py_it.it = ((BPy_SVertexIterator *)py_sv_it)->sv_it;
+ return py_sv_it;
+}
+
+PyObject *BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator(ViewVertexInternal::orientedViewEdgeIterator& ove_it, int reversed)
+{
+ PyObject *py_ove_it = orientedViewEdgeIterator_Type.tp_new(&orientedViewEdgeIterator_Type, 0, 0);
+ ((BPy_orientedViewEdgeIterator *)py_ove_it)->ove_it = new ViewVertexInternal::orientedViewEdgeIterator(ove_it);
+ ((BPy_orientedViewEdgeIterator *)py_ove_it)->py_it.it = ((BPy_orientedViewEdgeIterator *)py_ove_it)->ove_it;
+ ((BPy_orientedViewEdgeIterator *)py_ove_it)->reversed = reversed;
+ return py_ove_it;
+}
+
+PyObject *BPy_ViewEdgeIterator_from_ViewEdgeIterator(ViewEdgeInternal::ViewEdgeIterator& ve_it)
+{
+ PyObject *py_ve_it = ViewEdgeIterator_Type.tp_new(&ViewEdgeIterator_Type, 0, 0);
+ ((BPy_ViewEdgeIterator *)py_ve_it)->ve_it = new ViewEdgeInternal::ViewEdgeIterator(ve_it);
+ ((BPy_ViewEdgeIterator *)py_ve_it)->py_it.it = ((BPy_ViewEdgeIterator *)py_ve_it)->ve_it;
+ return py_ve_it;
+}
+
+PyObject *BPy_ChainingIterator_from_ChainingIterator(ChainingIterator& c_it)
+{
+ PyObject *py_c_it = ChainingIterator_Type.tp_new(&ChainingIterator_Type, 0, 0);
+ ((BPy_ChainingIterator *)py_c_it)->c_it = new ChainingIterator(c_it);
+ ((BPy_ChainingIterator *)py_c_it)->py_ve_it.py_it.it = ((BPy_ChainingIterator *)py_c_it)->c_it;
+ return py_c_it;
+}
+
+PyObject *BPy_ChainPredicateIterator_from_ChainPredicateIterator(ChainPredicateIterator& cp_it)
+{
+ PyObject *py_cp_it = ChainPredicateIterator_Type.tp_new(&ChainPredicateIterator_Type, 0, 0);
+ ((BPy_ChainPredicateIterator *)py_cp_it)->cp_it = new ChainPredicateIterator(cp_it);
+ ((BPy_ChainPredicateIterator *)py_cp_it)->py_c_it.py_ve_it.py_it.it = ((BPy_ChainPredicateIterator *)py_cp_it)->cp_it;
+ return py_cp_it;
+}
+
+PyObject *BPy_ChainSilhouetteIterator_from_ChainSilhouetteIterator(ChainSilhouetteIterator& cs_it)
+{
+ PyObject *py_cs_it = ChainSilhouetteIterator_Type.tp_new(&ChainSilhouetteIterator_Type, 0, 0);
+ ((BPy_ChainSilhouetteIterator *)py_cs_it)->cs_it = new ChainSilhouetteIterator(cs_it);
+ ((BPy_ChainSilhouetteIterator *)py_cs_it)->py_c_it.py_ve_it.py_it.it = ((BPy_ChainSilhouetteIterator *)py_cs_it)->cs_it;
+ return py_cs_it;
+}
+
+//==============================
+// Python => C++
+//==============================
+
+bool bool_from_PyBool(PyObject *b)
+{
+ return PyObject_IsTrue(b) != 0;
+}
+
+IntegrationType IntegrationType_from_BPy_IntegrationType(PyObject *obj)
+{
+ return static_cast<IntegrationType>(PyLong_AsLong(obj));
+}
+
+Stroke::MediumType MediumType_from_BPy_MediumType(PyObject *obj)
+{
+ return static_cast<Stroke::MediumType>(PyLong_AsLong(obj));
+}
+
+Nature::EdgeNature EdgeNature_from_BPy_Nature(PyObject *obj)
+{
+ return static_cast<Nature::EdgeNature>(PyLong_AsLong(obj));
+}
+
+Vec2f *Vec2f_ptr_from_PyObject(PyObject *obj)
+{
+ Vec2f *v;
+ if ((v = Vec2f_ptr_from_Vector(obj)))
+ return v;
+ if ((v = Vec2f_ptr_from_PyList(obj)))
+ return v;
+ if ((v = Vec2f_ptr_from_PyTuple(obj)))
+ return v;
+ return NULL;
+}
+
+Vec3f *Vec3f_ptr_from_PyObject(PyObject *obj)
+{
+ Vec3f *v;
+ if ((v = Vec3f_ptr_from_Vector(obj)))
+ return v;
+ if ((v = Vec3f_ptr_from_Color(obj)))
+ return v;
+ if ((v = Vec3f_ptr_from_PyList(obj)))
+ return v;
+ if ((v = Vec3f_ptr_from_PyTuple(obj)))
+ return v;
+ return NULL;
+}
+
+Vec3r *Vec3r_ptr_from_PyObject(PyObject *obj)
+{
+ Vec3r *v;
+ if ((v = Vec3r_ptr_from_Vector(obj)))
+ return v;
+ if ((v = Vec3r_ptr_from_Color(obj)))
+ return v;
+ if ((v = Vec3r_ptr_from_PyList(obj)))
+ return v;
+ if ((v = Vec3r_ptr_from_PyTuple(obj)))
+ return v;
+ return NULL;
+}
+
+Vec2f *Vec2f_ptr_from_Vector(PyObject *obj)
+{
+ if (!VectorObject_Check(obj) || ((VectorObject *)obj)->size != 2)
+ return NULL;
+ float x = ((VectorObject *)obj)->vec[0];
+ float y = ((VectorObject *)obj)->vec[1];
+ return new Vec2f(x, y);
+}
+
+Vec3f *Vec3f_ptr_from_Vector(PyObject *obj)
+{
+ if (!VectorObject_Check(obj) || ((VectorObject *)obj)->size != 3)
+ return NULL;
+ float x = ((VectorObject *)obj)->vec[0];
+ float y = ((VectorObject *)obj)->vec[1];
+ float z = ((VectorObject *)obj)->vec[2];
+ return new Vec3f(x, y, z);
+}
+
+Vec3r *Vec3r_ptr_from_Vector(PyObject *obj)
+{
+ if (!VectorObject_Check(obj) || ((VectorObject *)obj)->size != 3)
+ return NULL;
+ real x = ((VectorObject *)obj)->vec[0];
+ real y = ((VectorObject *)obj)->vec[1];
+ real z = ((VectorObject *)obj)->vec[2];
+ return new Vec3r(x, y, z);
+}
+
+Vec3f *Vec3f_ptr_from_Color(PyObject *obj)
+{
+ if (!ColorObject_Check(obj))
+ return NULL;
+ float r = ((ColorObject *)obj)->col[0];
+ float g = ((ColorObject *)obj)->col[1];
+ float b = ((ColorObject *)obj)->col[2];
+ return new Vec3f(r, g, b);
+}
+
+Vec3r *Vec3r_ptr_from_Color(PyObject *obj)
+{
+ if (!ColorObject_Check(obj))
+ return NULL;
+ real r = ((ColorObject *)obj)->col[0];
+ real g = ((ColorObject *)obj)->col[1];
+ real b = ((ColorObject *)obj)->col[2];
+ return new Vec3r(r, g, b);
+}
+
+static int float_array_from_PyList(PyObject *obj, float *v, int n)
+{
+ for (int i = 0; i < n; i++) {
+ v[i] = PyFloat_AsDouble(PyList_GetItem(obj, i));
+ if (v[i] == -1.0f && PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError, "list elements must be a number");
+ return 0;
+ }
+ }
+ return 1;
+}
+
+Vec2f *Vec2f_ptr_from_PyList(PyObject *obj)
+{
+ float v[2];
+
+ if (!PyList_Check(obj) || PyList_Size(obj) != 2)
+ return NULL;
+ if (!float_array_from_PyList(obj, v, 2))
+ return NULL;
+ return new Vec2f(v[0], v[1]);
+}
+
+Vec3f *Vec3f_ptr_from_PyList(PyObject *obj)
+{
+ float v[3];
+
+ if (!PyList_Check(obj) || PyList_Size(obj) != 3)
+ return NULL;
+ if (!float_array_from_PyList(obj, v, 3))
+ return NULL;
+ return new Vec3f(v[0], v[1], v[2]);
+}
+
+Vec3r *Vec3r_ptr_from_PyList(PyObject *obj)
+{
+ float v[3];
+
+ if (!PyList_Check(obj) || PyList_Size(obj) != 3)
+ return NULL;
+ if (!float_array_from_PyList(obj, v, 3))
+ return NULL;
+ return new Vec3r(v[0], v[1], v[2]);
+}
+
+static int float_array_from_PyTuple(PyObject *obj, float *v, int n)
+{
+ for (int i = 0; i < n; i++) {
+ v[i] = PyFloat_AsDouble(PyTuple_GetItem(obj, i));
+ if (v[i] == -1.0f && PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError, "tuple elements must be a number");
+ return 0;
+ }
+ }
+ return 1;
+}
+
+Vec2f *Vec2f_ptr_from_PyTuple(PyObject *obj)
+{
+ float v[2];
+
+ if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 2)
+ return NULL;
+ if (!float_array_from_PyTuple(obj, v, 2))
+ return NULL;
+ return new Vec2f(v[0], v[1]);
+}
+
+Vec3f *Vec3f_ptr_from_PyTuple(PyObject *obj)
+{
+ float v[3];
+
+ if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 3)
+ return NULL;
+ if (!float_array_from_PyTuple(obj, v, 3))
+ return NULL;
+ return new Vec3f(v[0], v[1], v[2]);
+}
+
+Vec3r *Vec3r_ptr_from_PyTuple(PyObject *obj)
+{
+ float v[3];
+
+ if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 3)
+ return NULL;
+ if (!float_array_from_PyTuple(obj, v, 3))
+ return NULL;
+ return new Vec3r(v[0], v[1], v[2]);
+}
+
+// helper for argument parsing
+
+int float_array_from_PyObject(PyObject *obj, float *v, int n)
+{
+ if (VectorObject_Check(obj) && ((VectorObject *)obj)->size == n) {
+ for (int i = 0; i < n; i++)
+ v[i] = ((VectorObject *)obj)->vec[i];
+ return 1;
+ }
+ else if (PyList_Check(obj) && PyList_Size(obj) == n) {
+ return float_array_from_PyList(obj, v, n);
+ }
+ else if (PyTuple_Check(obj) && PyTuple_Size(obj) == n) {
+ return float_array_from_PyList(obj, v, n);
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_Convert.h b/source/blender/freestyle/intern/python/BPy_Convert.h
new file mode 100644
index 00000000000..20ab9d0d15d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Convert.h
@@ -0,0 +1,183 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_Convert.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_CONVERT_H__
+#define __FREESTYLE_PYTHON_CONVERT_H__
+
+#include <Python.h>
+#include <typeinfo>
+
+#include "../geometry/Geom.h"
+using namespace Geometry;
+
+// BBox
+#include "../geometry/BBox.h"
+
+// FEdge, FEdgeSharp, FEdgeSmooth, SShape, SVertex, FEdgeInternal::SVertexIterator
+#include "../view_map/Silhouette.h"
+
+// Id
+#include "../system/Id.h"
+
+// Interface0D, Interface0DIteratorNested, Interface0DIterator
+#include "../view_map/Interface0D.h"
+
+// Interface1D
+#include "../view_map/Interface1D.h"
+
+// FrsMaterial
+#include "../scene_graph/FrsMaterial.h"
+
+// Nature::VertexNature, Nature::EdgeNature
+#include "../winged_edge/Nature.h"
+
+// Stroke, StrokeAttribute, StrokeVertex
+#include "../stroke/Stroke.h"
+
+// NonTVertex, TVertex, ViewEdge, ViewMap, ViewShape, ViewVertex
+#include "../view_map/ViewMap.h"
+
+// CurvePoint, Curve
+#include "../stroke/Curve.h"
+
+// Chain
+#include "../stroke/Chain.h"
+
+//====== ITERATORS
+
+// AdjacencyIterator, ChainingIterator, ChainSilhouetteIterator, ChainPredicateIterator
+#include "../stroke/ChainingIterators.h"
+
+// ViewVertexInternal::orientedViewEdgeIterator
+// ViewEdgeInternal::SVertexIterator
+// ViewEdgeInternal::ViewEdgeIterator
+#include "../view_map/ViewMapIterators.h"
+
+// StrokeInternal::StrokeVertexIterator
+#include "../stroke/StrokeIterators.h"
+
+// CurveInternal::CurvePointIterator
+#include "../stroke/CurveIterators.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include "mathutils/mathutils.h"
+
+//==============================
+// C++ => Python
+//==============================
+
+PyObject * PyBool_from_bool(bool b);
+PyObject * Vector_from_Vec2f(Vec2f& v);
+PyObject * Vector_from_Vec3f(Vec3f& v);
+PyObject * Vector_from_Vec3r(Vec3r& v);
+
+PyObject * Any_BPy_Interface0D_from_Interface0D(Interface0D& if0D);
+PyObject * Any_BPy_Interface1D_from_Interface1D(Interface1D& if1D);
+PyObject * Any_BPy_FEdge_from_FEdge(FEdge& fe);
+PyObject * Any_BPy_ViewVertex_from_ViewVertex(ViewVertex& vv);
+
+PyObject * BPy_BBox_from_BBox(const BBox< Vec3r > &bb);
+PyObject * BPy_CurvePoint_from_CurvePoint(CurvePoint& cp);
+PyObject * BPy_directedViewEdge_from_directedViewEdge(ViewVertex::directedViewEdge& dve);
+PyObject * BPy_FEdge_from_FEdge(FEdge& fe);
+PyObject * BPy_FEdgeSharp_from_FEdgeSharp(FEdgeSharp& fes);
+PyObject * BPy_FEdgeSmooth_from_FEdgeSmooth(FEdgeSmooth& fes);
+PyObject * BPy_Id_from_Id(Id& id);
+PyObject * BPy_Interface0D_from_Interface0D(Interface0D& if0D);
+PyObject * BPy_Interface1D_from_Interface1D(Interface1D& if1D);
+PyObject * BPy_IntegrationType_from_IntegrationType(IntegrationType i);
+PyObject * BPy_FrsMaterial_from_FrsMaterial(const FrsMaterial& m);
+PyObject * BPy_Nature_from_Nature(unsigned short n);
+PyObject * BPy_MediumType_from_MediumType(Stroke::MediumType n);
+PyObject * BPy_SShape_from_SShape(SShape& ss);
+PyObject * BPy_Stroke_from_Stroke(Stroke& s);
+PyObject * BPy_StrokeAttribute_from_StrokeAttribute(StrokeAttribute& sa);
+PyObject * BPy_StrokeVertex_from_StrokeVertex(StrokeVertex& sv);
+PyObject * BPy_SVertex_from_SVertex(SVertex& sv);
+PyObject * BPy_ViewVertex_from_ViewVertex(ViewVertex& vv);
+PyObject * BPy_NonTVertex_from_NonTVertex(NonTVertex& ntv);
+PyObject * BPy_TVertex_from_TVertex(TVertex& tv);
+PyObject * BPy_ViewEdge_from_ViewEdge(ViewEdge& ve);
+PyObject * BPy_Chain_from_Chain(Chain& c);
+PyObject * BPy_ViewShape_from_ViewShape(ViewShape& vs);
+
+PyObject * BPy_AdjacencyIterator_from_AdjacencyIterator(AdjacencyIterator& a_it);
+PyObject * BPy_Interface0DIterator_from_Interface0DIterator(Interface0DIterator& if0D_it, int reversed);
+PyObject * BPy_CurvePointIterator_from_CurvePointIterator(CurveInternal::CurvePointIterator& cp_it);
+PyObject * BPy_StrokeVertexIterator_from_StrokeVertexIterator(StrokeInternal::StrokeVertexIterator& sv_it,
+ int reversed);
+PyObject * BPy_SVertexIterator_from_SVertexIterator(ViewEdgeInternal::SVertexIterator& sv_it);
+PyObject * BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator(ViewVertexInternal::orientedViewEdgeIterator& ove_it,
+ int reversed);
+PyObject * BPy_ViewEdgeIterator_from_ViewEdgeIterator(ViewEdgeInternal::ViewEdgeIterator& ve_it);
+PyObject * BPy_ChainingIterator_from_ChainingIterator(ChainingIterator& c_it);
+PyObject * BPy_ChainPredicateIterator_from_ChainPredicateIterator(ChainPredicateIterator& cp_it);
+PyObject * BPy_ChainSilhouetteIterator_from_ChainSilhouetteIterator(ChainSilhouetteIterator& cs_it);
+
+//==============================
+// Python => C++
+//==============================
+
+bool bool_from_PyBool(PyObject *b);
+IntegrationType IntegrationType_from_BPy_IntegrationType(PyObject *obj);
+Stroke::MediumType MediumType_from_BPy_MediumType(PyObject *obj);
+Nature::EdgeNature EdgeNature_from_BPy_Nature(PyObject *obj);
+Vec2f * Vec2f_ptr_from_PyObject(PyObject *obj);
+Vec3f * Vec3f_ptr_from_PyObject(PyObject *obj);
+Vec3r * Vec3r_ptr_from_PyObject(PyObject *obj);
+Vec2f * Vec2f_ptr_from_Vector(PyObject *obj);
+Vec3f * Vec3f_ptr_from_Vector(PyObject *obj);
+Vec3r * Vec3r_ptr_from_Vector(PyObject *obj);
+Vec3f * Vec3f_ptr_from_Color(PyObject *obj);
+Vec3r * Vec3r_ptr_from_Color(PyObject *obj);
+Vec2f * Vec2f_ptr_from_PyList(PyObject *obj);
+Vec3f * Vec3f_ptr_from_PyList(PyObject *obj);
+Vec3r * Vec3r_ptr_from_PyList(PyObject *obj);
+Vec2f * Vec2f_ptr_from_PyTuple(PyObject *obj);
+Vec3f * Vec3f_ptr_from_PyTuple(PyObject *obj);
+Vec3r * Vec3r_ptr_from_PyTuple(PyObject *obj);
+
+int float_array_from_PyObject(PyObject *obj, float *v, int n);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_CONVERT_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp
new file mode 100644
index 00000000000..21347dc2dae
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp
@@ -0,0 +1,544 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_Freestyle.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_Freestyle.h"
+
+#include "BPy_BBox.h"
+#include "BPy_BinaryPredicate0D.h"
+#include "BPy_BinaryPredicate1D.h"
+#include "BPy_ContextFunctions.h"
+#include "BPy_Convert.h"
+#include "BPy_FrsMaterial.h"
+#include "BPy_FrsNoise.h"
+#include "BPy_Id.h"
+#include "BPy_IntegrationType.h"
+#include "BPy_Interface0D.h"
+#include "BPy_Interface1D.h"
+#include "BPy_Iterator.h"
+#include "BPy_MediumType.h"
+#include "BPy_Nature.h"
+#include "BPy_Operators.h"
+#include "BPy_SShape.h"
+#include "BPy_StrokeAttribute.h"
+#include "BPy_StrokeShader.h"
+#include "BPy_UnaryFunction0D.h"
+#include "BPy_UnaryFunction1D.h"
+#include "BPy_UnaryPredicate0D.h"
+#include "BPy_UnaryPredicate1D.h"
+#include "BPy_ViewMap.h"
+#include "BPy_ViewShape.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------ MODULE FUNCTIONS ----------------------------------
+
+#include "FRS_freestyle.h"
+#include "RNA_access.h"
+#include "bpy_rna.h" /* pyrna_struct_CreatePyObject() */
+
+static char Freestyle_getCurrentScene___doc__[] =
+".. function:: getCurrentScene()\n"
+"\n"
+" Returns the current scene.\n"
+"\n"
+" :return: The current scene.\n"
+" :rtype: :class:`bpy.types.Scene`\n";
+
+static PyObject *Freestyle_getCurrentScene(PyObject *self)
+{
+ if (!freestyle_scene) {
+ PyErr_SetString(PyExc_TypeError, "current scene not available");
+ return NULL;
+ }
+ PointerRNA ptr_scene;
+ RNA_pointer_create(NULL, &RNA_Scene, freestyle_scene, &ptr_scene);
+ return pyrna_struct_CreatePyObject(&ptr_scene);
+}
+
+#include "DNA_material_types.h"
+
+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;
+ return -1;
+}
+
+#include "BKE_material.h" /* ramp_blend() */
+
+static char Freestyle_blendRamp___doc__[] =
+".. function:: blendRamp(type, color1, fac, color2)\n"
+"\n"
+" Blend two colors according to a ramp blend type.\n"
+"\n"
+" :arg type: Ramp blend type.\n"
+" :type type: int\n"
+" :arg color1: 1st color.\n"
+" :type color1: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"
+" :arg fac: Blend factor.\n"
+" :type fac: float\n"
+" :arg color2: 1st color.\n"
+" :type color2: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"
+" :return: Blended color in RGB format.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject *Freestyle_blendRamp(PyObject *self, PyObject *args)
+{
+ PyObject *obj1, *obj2;
+ char *s;
+ int type;
+ Vec3f *v1 = NULL, *v2 = NULL;
+ float a[3], fac, b[3];
+
+ if (!PyArg_ParseTuple(args, "sOfO", &s, &obj1, &fac, &obj2))
+ return NULL;
+ type = ramp_blend_type(s);
+ if (type < 0) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 is an unknown ramp blend type");
+ goto error;
+ }
+ v1 = Vec3f_ptr_from_PyObject(obj1);
+ if (!v1) {
+ PyErr_SetString(PyExc_TypeError,
+ "argument 2 must be a 3D vector (either a tuple/list of 3 elements or Vector)");
+ goto error;
+ }
+ v2 = Vec3f_ptr_from_PyObject(obj2);
+ if (!v2) {
+ PyErr_SetString(PyExc_TypeError,
+ "argument 4 must be a 3D vector (either a tuple/list of 3 elements or Vector)");
+ goto error;
+ }
+ a[0] = v1->x(); b[0] = v2->x();
+ a[1] = v1->y(); b[1] = v2->y();
+ a[2] = v1->z(); b[2] = v2->z();
+ ramp_blend(type, a, fac, b);
+ delete v1;
+ delete v2;
+ return Vector_CreatePyObject(a, 3, Py_NEW, NULL);
+
+error:
+ if (v1) delete v1;
+ if (v2) delete v2;
+ return NULL;
+}
+
+#include "BKE_texture.h" /* do_colorband() */
+
+static char Freestyle_evaluateColorRamp___doc__[] =
+".. function:: evaluateColorRamp(ramp, in)\n"
+"\n"
+" Evaluate a color ramp at a point in the interval 0 to 1.\n"
+"\n"
+" :arg ramp: Color ramp object.\n"
+" :type ramp: :class:`bpy.types.ColorRamp`\n"
+" :arg in: Value in the interval 0 to 1.\n"
+" :type in: float\n"
+" :return: color in RGBA format.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject *Freestyle_evaluateColorRamp(PyObject *self, PyObject *args)
+{
+ BPy_StructRNA *py_srna;
+ ColorBand *coba;
+ float in, out[4];
+
+ if (!(PyArg_ParseTuple(args, "O!f", &pyrna_struct_Type, &py_srna, &in)))
+ return NULL;
+ if (!RNA_struct_is_a(py_srna->ptr.type, &RNA_ColorRamp)) {
+ PyErr_SetString(PyExc_TypeError, "1st argument is not a ColorRamp object");
+ return NULL;
+ }
+ coba = (ColorBand *)py_srna->ptr.data;
+ if (!do_colorband(coba, in, out)) {
+ PyErr_SetString(PyExc_ValueError, "failed to evaluate the color ramp");
+ return NULL;
+ }
+ return Vector_CreatePyObject(out, 4, Py_NEW, NULL);
+}
+
+#include "DNA_color_types.h"
+#include "BKE_colortools.h" /* curvemapping_evaluateF() */
+
+static char Freestyle_evaluateCurveMappingF___doc__[] =
+".. function:: evaluateCurveMappingF(cumap, cur, value)\n"
+"\n"
+" Evaluate a curve mapping at a point in the interval 0 to 1.\n"
+"\n"
+" :arg cumap: Curve mapping object.\n"
+" :type cumap: :class:`bpy.types.CurveMapping`\n"
+" :arg cur: Index of the curve to be used (0 <= cur <= 3).\n"
+" :type cur: int\n"
+" :arg value: Input value in the interval 0 to 1.\n"
+" :type value: float\n"
+" :return: Mapped output value.\n"
+" :rtype: float\n";
+
+static PyObject *Freestyle_evaluateCurveMappingF(PyObject *self, PyObject *args)
+{
+ BPy_StructRNA *py_srna;
+ CurveMapping *cumap;
+ int cur;
+ float value;
+
+ if (!(PyArg_ParseTuple(args, "O!if", &pyrna_struct_Type, &py_srna, &cur, &value)))
+ return NULL;
+ if (!RNA_struct_is_a(py_srna->ptr.type, &RNA_CurveMapping)) {
+ PyErr_SetString(PyExc_TypeError, "1st argument is not a CurveMapping object");
+ return NULL;
+ }
+ if (cur < 0 || cur > 3) {
+ PyErr_SetString(PyExc_ValueError, "2nd argument is out of range");
+ return NULL;
+ }
+ cumap = (CurveMapping *)py_srna->ptr.data;
+ curvemapping_initialize(cumap);
+ /* disable extrapolation if enabled */
+ if ((cumap->cm[cur].flag & CUMA_EXTEND_EXTRAPOLATE)) {
+ cumap->cm[cur].flag &= ~(CUMA_EXTEND_EXTRAPOLATE);
+ curvemapping_changed(cumap, 0);
+ }
+ return PyFloat_FromDouble(curvemapping_evaluateF(cumap, cur, value));
+}
+
+/*-----------------------Freestyle module docstring----------------------------*/
+
+static char module_docstring[] =
+"This module provides classes for defining line drawing rules (such as\n"
+"predicates, functions, chaining iterators, and stroke shaders), as well\n"
+"as helper functions for style module writing.\n"
+"\n"
+"Class hierarchy:\n"
+"\n"
+"- :class:`BBox`\n"
+"- :class:`BinaryPredicate0D`\n"
+"- :class:`BinaryPredicate1D`\n"
+"\n"
+" - :class:`FalseBP1D`\n"
+" - :class:`Length2DBP1D`\n"
+" - :class:`SameShapeIdBP1D`\n"
+" - :class:`TrueBP1D`\n"
+" - :class:`ViewMapGradientNormBP1D`\n"
+"\n"
+"- :class:`Id`\n"
+"- :class:`Interface0D`\n"
+"\n"
+" - :class:`CurvePoint`\n"
+"\n"
+" - :class:`StrokeVertex`\n"
+"\n"
+" - :class:`SVertex`\n"
+" - :class:`ViewVertex`\n"
+"\n"
+" - :class:`NonTVertex`\n"
+" - :class:`TVertex`\n"
+"\n"
+"- :class:`Interface1D`\n"
+"\n"
+" - :class:`Curve`\n"
+"\n"
+" - :class:`Chain`\n"
+"\n"
+" - :class:`FEdge`\n"
+"\n"
+" - :class:`FEdgeSharp`\n"
+" - :class:`FEdgeSmooth`\n"
+"\n"
+" - :class:`Stroke`\n"
+" - :class:`ViewEdge`\n"
+"\n"
+"- :class:`Iterator`\n"
+"\n"
+" - :class:`AdjacencyIterator`\n"
+" - :class:`CurvePointIterator`\n"
+" - :class:`Interface0DIterator`\n"
+" - :class:`SVertexIterator`\n"
+" - :class:`StrokeVertexIterator`\n"
+" - :class:`ViewEdgeIterator`\n"
+"\n"
+" - :class:`ChainingIterator`\n"
+"\n"
+" - :class:`ChainPredicateIterator`\n"
+" - :class:`ChainSilhouetteIterator`\n"
+"\n"
+" - :class:`orientedViewEdgeIterator`\n"
+"\n"
+"- :class:`Material`\n"
+"- :class:`Noise`\n"
+"- :class:`Operators`\n"
+"- :class:`SShape`\n"
+"- :class:`StrokeAttribute`\n"
+"- :class:`StrokeShader`\n"
+"\n"
+" - :class:`BackboneStretcherShader`\n"
+" - :class:`BezierCurveShader`\n"
+" - :class:`CalligraphicShader`\n"
+" - :class:`ColorNoiseShader`\n"
+" - :class:`ColorVariationPatternShader`\n"
+" - :class:`ConstantColorShader`\n"
+" - :class:`ConstantThicknessShader`\n"
+" - :class:`ConstrainedIncreasingThicknessShader`\n"
+" - :class:`GuidingLinesShader`\n"
+" - :class:`IncreasingColorShader`\n"
+" - :class:`IncreasingThicknessShader`\n"
+" - :class:`PolygonalizationShader`\n"
+" - :class:`SamplingShader`\n"
+" - :class:`SmoothingShader`\n"
+" - :class:`SpatialNoiseShader`\n"
+" - :class:`StrokeTextureShader`\n"
+" - :class:`TextureAssignerShader`\n"
+" - :class:`ThicknessNoiseShader`\n"
+" - :class:`ThicknessVariationPatternShader`\n"
+" - :class:`TipRemoverShader`\n"
+" - :class:`fstreamShader`\n"
+" - :class:`streamShader`\n"
+"\n"
+"- :class:`UnaryFunction0D`\n"
+"\n"
+" - :class:`UnaryFunction0DDouble`\n"
+"\n"
+" - :class:`Curvature2DAngleF0D`\n"
+" - :class:`DensityF0D`\n"
+" - :class:`GetProjectedXF0D`\n"
+" - :class:`GetProjectedYF0D`\n"
+" - :class:`GetProjectedZF0D`\n"
+" - :class:`GetXF0D`\n"
+" - :class:`GetYF0D`\n"
+" - :class:`GetZF0D`\n"
+" - :class:`LocalAverageDepthF0D`\n"
+" - :class:`ZDiscontinuityF0D`\n"
+"\n"
+" - :class:`UnaryFunction0DEdgeNature`\n"
+"\n"
+" - :class:`CurveNatureF0D`\n"
+"\n"
+" - :class:`UnaryFunction0DFloat`\n"
+"\n"
+" - :class:`GetCurvilinearAbscissaF0D`\n"
+" - :class:`GetParameterF0D`\n"
+" - :class:`GetViewMapGradientNormF0D`\n"
+" - :class:`ReadCompleteViewMapPixelF0D`\n"
+" - :class:`ReadMapPixelF0D`\n"
+" - :class:`ReadSteerableViewMapPixelF0D`\n"
+"\n"
+" - :class:`UnaryFunction0DId`\n"
+"\n"
+" - :class:`ShapeIdF0D`\n"
+"\n"
+" - :class:`UnaryFunction0DMaterial`\n"
+"\n"
+" - :class:`MaterialF0D`\n"
+"\n"
+" - :class:`UnaryFunction0DUnsigned`\n"
+"\n"
+" - :class:`QuantitativeInvisibilityF0D`\n"
+"\n"
+" - :class:`UnaryFunction0DVec2f`\n"
+"\n"
+" - :class:`Normal2DF0D`\n"
+" - :class:`VertexOrientation2DF0D`\n"
+"\n"
+" - :class:`UnaryFunction0DVec3f`\n"
+"\n"
+" - :class:`VertexOrientation3DF0D`\n"
+"\n"
+" - :class:`UnaryFunction0DVectorViewShape`\n"
+"\n"
+" - :class:`GetOccludersF0D`\n"
+"\n"
+" - :class:`UnaryFunction0DViewShape`\n"
+"\n"
+" - :class:`GetOccludeeF0D`\n"
+" - :class:`GetShapeF0D`\n"
+"\n"
+"- :class:`UnaryFunction1D`\n"
+"\n"
+" - :class:`UnaryFunction1DDouble`\n"
+"\n"
+" - :class:`Curvature2DAngleF1D`\n"
+" - :class:`DensityF1D`\n"
+" - :class:`GetCompleteViewMapDensityF1D`\n"
+" - :class:`GetDirectionalViewMapDensityF1D`\n"
+" - :class:`GetProjectedXF1D`\n"
+" - :class:`GetProjectedYF1D`\n"
+" - :class:`GetProjectedZF1D`\n"
+" - :class:`GetSteerableViewMapDensityF1D`\n"
+" - :class:`GetViewMapGradientNormF1D`\n"
+" - :class:`GetXF1D`\n"
+" - :class:`GetYF1D`\n"
+" - :class:`GetZF1D`\n"
+" - :class:`LocalAverageDepthF1D`\n"
+" - :class:`ZDiscontinuityF1D`\n"
+"\n"
+" - :class:`UnaryFunction1DEdgeNature`\n"
+"\n"
+" - :class:`CurveNatureF1D`\n"
+"\n"
+" - :class:`UnaryFunction1DFloat`\n"
+" - :class:`UnaryFunction1DUnsigned`\n"
+"\n"
+" - :class:`QuantitativeInvisibilityF1D`\n"
+"\n"
+" - :class:`UnaryFunction1DVec2f`\n"
+"\n"
+" - :class:`Normal2DF1D`\n"
+" - :class:`Orientation2DF1D`\n"
+"\n"
+" - :class:`UnaryFunction1DVec3f`\n"
+"\n"
+" - :class:`Orientation3DF1D`\n"
+"\n"
+" - :class:`UnaryFunction1DVectorViewShape`\n"
+"\n"
+" - :class:`GetOccludeeF1D`\n"
+" - :class:`GetOccludersF1D`\n"
+" - :class:`GetShapeF1D`\n"
+"\n"
+" - :class:`UnaryFunction1DVoid`\n"
+"\n"
+" - :class:`ChainingTimeStampF1D`\n"
+" - :class:`IncrementChainingTimeStampF1D`\n"
+" - :class:`TimeStampF1D`\n"
+"\n"
+"- :class:`UnaryPredicate0D`\n"
+"\n"
+" - :class:`FalseUP0D`\n"
+" - :class:`TrueUP0D`\n"
+"\n"
+"- :class:`UnaryPredicate1D`\n"
+"\n"
+" - :class:`ContourUP1D`\n"
+" - :class:`DensityLowerThanUP1D`\n"
+" - :class:`EqualToChainingTimeStampUP1D`\n"
+" - :class:`EqualToTimeStampUP1D`\n"
+" - :class:`ExternalContourUP1D`\n"
+" - :class:`FalseUP1D`\n"
+" - :class:`QuantitativeInvisibilityUP1D`\n"
+" - :class:`ShapeUP1D`\n"
+" - :class:`TrueUP1D`\n"
+" - :class:`WithinImageBoundaryUP1D`\n"
+"\n"
+"- :class:`ViewMap`\n"
+"- :class:`ViewShape`\n"
+"- :class:`IntegrationType`\n"
+"- :class:`MediumType`\n"
+"- :class:`Nature`\n"
+"\n";
+
+/*-----------------------Freestyle module method def---------------------------*/
+
+static PyMethodDef module_functions[] = {
+ {"getCurrentScene", (PyCFunction) Freestyle_getCurrentScene, METH_NOARGS, Freestyle_getCurrentScene___doc__},
+ {"blendRamp", (PyCFunction) Freestyle_blendRamp, METH_VARARGS, Freestyle_blendRamp___doc__},
+ {"evaluateColorRamp", (PyCFunction) Freestyle_evaluateColorRamp, METH_VARARGS, Freestyle_evaluateColorRamp___doc__},
+ {"evaluateCurveMappingF", (PyCFunction) Freestyle_evaluateCurveMappingF, METH_VARARGS,
+ Freestyle_evaluateCurveMappingF___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------Freestyle module definition---------------------------*/
+
+static PyModuleDef module_definition = {
+ PyModuleDef_HEAD_INIT,
+ "Freestyle",
+ module_docstring,
+ -1,
+ module_functions
+};
+
+//-------------------MODULE INITIALIZATION--------------------------------
+PyObject *Freestyle_Init(void)
+{
+ PyObject *module;
+
+ // initialize modules
+ module = PyModule_Create(&module_definition);
+ if (!module)
+ return NULL;
+ PyDict_SetItemString(PySys_GetObject("modules"), module_definition.m_name, module);
+
+ // attach its classes (adding the object types to the module)
+
+ // those classes have to be initialized before the others
+ MediumType_Init(module);
+ Nature_Init(module);
+
+ BBox_Init(module);
+ BinaryPredicate0D_Init(module);
+ BinaryPredicate1D_Init(module);
+ ContextFunctions_Init(module);
+ FrsMaterial_Init(module);
+ FrsNoise_Init(module);
+ Id_Init(module);
+ IntegrationType_Init(module);
+ Interface0D_Init(module);
+ Interface1D_Init(module);
+ Iterator_Init(module);
+ Operators_Init(module);
+ SShape_Init(module);
+ StrokeAttribute_Init(module);
+ StrokeShader_Init(module);
+ UnaryFunction0D_Init(module);
+ UnaryFunction1D_Init(module);
+ UnaryPredicate0D_Init(module);
+ UnaryPredicate1D_Init(module);
+ ViewMap_Init(module);
+ ViewShape_Init(module);
+
+ return module;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.h b/source/blender/freestyle/intern/python/BPy_Freestyle.h
new file mode 100644
index 00000000000..8fa1f19a57b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Freestyle.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_Freestyle.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_FREESTYLE_H__
+#define __FREESTYLE_PYTHON_FREESTYLE_H__
+
+#include <Python.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*---------------------------Python BPy_Freestyle visible prototypes-----------*/
+
+PyObject *Freestyle_Init(void);
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_FREESTYLE_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
new file mode 100644
index 00000000000..1833708f08c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
@@ -0,0 +1,462 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_FrsMaterial.h"
+
+#include "BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int FrsMaterial_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&FrsMaterial_Type) < 0)
+ return -1;
+ Py_INCREF(&FrsMaterial_Type);
+ PyModule_AddObject(module, "Material", (PyObject *)&FrsMaterial_Type);
+
+ FrsMaterial_mathutils_register_callback();
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+PyDoc_STRVAR(FrsMaterial_doc,
+"Class defining a material.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A Material object.\n"
+" :type brother: :class:`Material`\n"
+"\n"
+".. method:: __init__(diffuse, ambient, specular, emission, shininess)\n"
+"\n"
+" Builds a Material from its diffuse, ambient, specular, emissive\n"
+" colors and a shininess coefficient.\n"
+"\n"
+" :arg diffuse: The diffuse color.\n"
+" :type diffuse: :class:`mathutils.Vector`, list or tuple of 4 float values\n"
+" :arg ambient: The ambient color.\n"
+" :type ambient: :class:`mathutils.Vector`, list or tuple of 4 float values\n"
+" :arg specular: The specular color.\n"
+" :type specular: :class:`mathutils.Vector`, list or tuple of 4 float values\n"
+" :arg emission: The emissive color.\n"
+" :type emission: :class:`mathutils.Vector`, list or tuple of 4 float values\n"
+" :arg shininess: The shininess coefficient.\n"
+" :type shininess: :class:float");
+
+static int convert_v4(PyObject *obj, void *v)
+{
+ return float_array_from_PyObject(obj, (float *)v, 4);
+}
+
+static int FrsMaterial_init(BPy_FrsMaterial *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"diffuse", "ambient", "specular", "emission", "shininess", NULL};
+ PyObject *brother = 0;
+ float diffuse[4], ambient[4], specular[4], emission[4], shininess;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &FrsMaterial_Type, &brother)) {
+ if (!brother) {
+ self->m = new FrsMaterial();
+ }
+ else {
+ FrsMaterial *m = ((BPy_FrsMaterial *)brother)->m;
+ if (!m) {
+ PyErr_SetString(PyExc_RuntimeError, "invalid Material object");
+ return -1;
+ }
+ self->m = new FrsMaterial(*m);
+ }
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O&O&O&O&f", (char **)kwlist_2,
+ convert_v4, diffuse,
+ convert_v4, ambient,
+ convert_v4, specular,
+ convert_v4, emission,
+ &shininess))
+ {
+ self->m = new FrsMaterial(diffuse, ambient, specular, emission, shininess);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ return 0;
+}
+
+static void FrsMaterial_dealloc(BPy_FrsMaterial *self)
+{
+ delete self->m;
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *FrsMaterial_repr(BPy_FrsMaterial *self)
+{
+ return PyUnicode_FromFormat("Material - address: %p", self->m);
+}
+
+/*----------------------mathutils callbacks ----------------------------*/
+
+/* subtype */
+#define MATHUTILS_SUBTYPE_DIFFUSE 1
+#define MATHUTILS_SUBTYPE_SPECULAR 2
+#define MATHUTILS_SUBTYPE_AMBIENT 3
+#define MATHUTILS_SUBTYPE_EMISSION 4
+
+static int FrsMaterial_mathutils_check(BaseMathObject *bmo)
+{
+ if (!BPy_FrsMaterial_Check(bmo->cb_user))
+ return -1;
+ return 0;
+}
+
+static int FrsMaterial_mathutils_get(BaseMathObject *bmo, int subtype)
+{
+ BPy_FrsMaterial *self = (BPy_FrsMaterial *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_DIFFUSE:
+ bmo->data[0] = self->m->diffuseR();
+ bmo->data[1] = self->m->diffuseG();
+ bmo->data[2] = self->m->diffuseB();
+ bmo->data[3] = self->m->diffuseA();
+ break;
+ case MATHUTILS_SUBTYPE_SPECULAR:
+ bmo->data[0] = self->m->specularR();
+ bmo->data[1] = self->m->specularG();
+ bmo->data[2] = self->m->specularB();
+ bmo->data[3] = self->m->specularA();
+ break;
+ case MATHUTILS_SUBTYPE_AMBIENT:
+ bmo->data[0] = self->m->ambientR();
+ bmo->data[1] = self->m->ambientG();
+ bmo->data[2] = self->m->ambientB();
+ bmo->data[3] = self->m->ambientA();
+ break;
+ case MATHUTILS_SUBTYPE_EMISSION:
+ bmo->data[0] = self->m->emissionR();
+ bmo->data[1] = self->m->emissionG();
+ bmo->data[2] = self->m->emissionB();
+ bmo->data[3] = self->m->emissionA();
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int FrsMaterial_mathutils_set(BaseMathObject *bmo, int subtype)
+{
+ BPy_FrsMaterial *self = (BPy_FrsMaterial *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_DIFFUSE:
+ self->m->setDiffuse(bmo->data[0], bmo->data[1], bmo->data[2], bmo->data[3]);
+ break;
+ case MATHUTILS_SUBTYPE_SPECULAR:
+ self->m->setSpecular(bmo->data[0], bmo->data[1], bmo->data[2], bmo->data[3]);
+ break;
+ case MATHUTILS_SUBTYPE_AMBIENT:
+ self->m->setAmbient(bmo->data[0], bmo->data[1], bmo->data[2], bmo->data[3]);
+ break;
+ case MATHUTILS_SUBTYPE_EMISSION:
+ self->m->setEmission(bmo->data[0], bmo->data[1], bmo->data[2], bmo->data[3]);
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int FrsMaterial_mathutils_get_index(BaseMathObject *bmo, int subtype, int index)
+{
+ BPy_FrsMaterial *self = (BPy_FrsMaterial *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_DIFFUSE:
+ {
+ const float *color = self->m->diffuse();
+ bmo->data[index] = color[index];
+ }
+ break;
+ case MATHUTILS_SUBTYPE_SPECULAR:
+ {
+ const float *color = self->m->specular();
+ bmo->data[index] = color[index];
+ }
+ break;
+ case MATHUTILS_SUBTYPE_AMBIENT:
+ {
+ const float *color = self->m->ambient();
+ bmo->data[index] = color[index];
+ }
+ break;
+ case MATHUTILS_SUBTYPE_EMISSION:
+ {
+ const float *color = self->m->emission();
+ bmo->data[index] = color[index];
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int FrsMaterial_mathutils_set_index(BaseMathObject *bmo, int subtype, int index)
+{
+ BPy_FrsMaterial *self = (BPy_FrsMaterial *)bmo->cb_user;
+ float color[4];
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_DIFFUSE:
+ copy_v4_v4(color, self->m->diffuse());
+ color[index] = bmo->data[index];
+ self->m->setDiffuse(color[0], color[1], color[2], color[3]);
+ break;
+ case MATHUTILS_SUBTYPE_SPECULAR:
+ copy_v4_v4(color, self->m->specular());
+ color[index] = bmo->data[index];
+ self->m->setSpecular(color[0], color[1], color[2], color[3]);
+ break;
+ case MATHUTILS_SUBTYPE_AMBIENT:
+ copy_v4_v4(color, self->m->ambient());
+ color[index] = bmo->data[index];
+ self->m->setAmbient(color[0], color[1], color[2], color[3]);
+ break;
+ case MATHUTILS_SUBTYPE_EMISSION:
+ copy_v4_v4(color, self->m->emission());
+ color[index] = bmo->data[index];
+ self->m->setEmission(color[0], color[1], color[2], color[3]);
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static Mathutils_Callback FrsMaterial_mathutils_cb = {
+ FrsMaterial_mathutils_check,
+ FrsMaterial_mathutils_get,
+ FrsMaterial_mathutils_set,
+ FrsMaterial_mathutils_get_index,
+ FrsMaterial_mathutils_set_index
+};
+
+static unsigned char FrsMaterial_mathutils_cb_index = -1;
+
+void FrsMaterial_mathutils_register_callback()
+{
+ FrsMaterial_mathutils_cb_index = Mathutils_RegisterCallback(&FrsMaterial_mathutils_cb);
+}
+
+/*----------------------FrsMaterial get/setters ----------------------------*/
+
+PyDoc_STRVAR(FrsMaterial_diffuse_doc,
+"RGBA components of the diffuse color of the material.\n"
+"\n"
+":type: mathutils.Vector");
+
+static PyObject *FrsMaterial_diffuse_get(BPy_FrsMaterial *self, void *UNUSED(closure))
+{
+ return Vector_CreatePyObject_cb((PyObject *)self, 4, FrsMaterial_mathutils_cb_index, MATHUTILS_SUBTYPE_DIFFUSE);
+}
+
+static int FrsMaterial_diffuse_set(BPy_FrsMaterial *self, PyObject *value, void *UNUSED(closure))
+{
+ float color[4];
+ if (!float_array_from_PyObject(value, color, 4)) {
+ PyErr_SetString(PyExc_ValueError, "value must be a 4-dimensional vector");
+ return -1;
+ }
+ self->m->setDiffuse(color[0], color[1], color[2], color[3]);
+ return 0;
+}
+
+PyDoc_STRVAR(FrsMaterial_specular_doc,
+"RGBA components of the specular color of the material.\n"
+"\n"
+":type: mathutils.Vector");
+
+static PyObject *FrsMaterial_specular_get(BPy_FrsMaterial *self, void *UNUSED(closure))
+{
+ return Vector_CreatePyObject_cb((PyObject *)self, 4, FrsMaterial_mathutils_cb_index, MATHUTILS_SUBTYPE_SPECULAR);
+}
+
+static int FrsMaterial_specular_set(BPy_FrsMaterial *self, PyObject *value, void *UNUSED(closure))
+{
+ float color[4];
+ if (!float_array_from_PyObject(value, color, 4)) {
+ PyErr_SetString(PyExc_ValueError, "value must be a 4-dimensional vector");
+ return -1;
+ }
+ self->m->setSpecular(color[0], color[1], color[2], color[3]);
+ return 0;
+}
+
+PyDoc_STRVAR(FrsMaterial_ambient_doc,
+"RGBA components of the ambient color of the material.\n"
+"\n"
+":type: mathutils.Color");
+
+static PyObject *FrsMaterial_ambient_get(BPy_FrsMaterial *self, void *UNUSED(closure))
+{
+ return Vector_CreatePyObject_cb((PyObject *)self, 4, FrsMaterial_mathutils_cb_index, MATHUTILS_SUBTYPE_AMBIENT);
+}
+
+static int FrsMaterial_ambient_set(BPy_FrsMaterial *self, PyObject *value, void *UNUSED(closure))
+{
+ float color[4];
+ if (!float_array_from_PyObject(value, color, 4)) {
+ PyErr_SetString(PyExc_ValueError, "value must be a 4-dimensional vector");
+ return -1;
+ }
+ self->m->setAmbient(color[0], color[1], color[2], color[3]);
+ return 0;
+}
+
+PyDoc_STRVAR(FrsMaterial_emission_doc,
+"RGBA components of the emissive color of the material.\n"
+"\n"
+":type: mathutils.Color");
+
+static PyObject *FrsMaterial_emission_get(BPy_FrsMaterial *self, void *UNUSED(closure))
+{
+ return Vector_CreatePyObject_cb((PyObject *)self, 4, FrsMaterial_mathutils_cb_index, MATHUTILS_SUBTYPE_EMISSION);
+}
+
+static int FrsMaterial_emission_set(BPy_FrsMaterial *self, PyObject *value, void *UNUSED(closure))
+{
+ float color[4];
+ if (!float_array_from_PyObject(value, color, 4)) {
+ PyErr_SetString(PyExc_ValueError, "value must be a 4-dimensional vector");
+ return -1;
+ }
+ self->m->setEmission(color[0], color[1], color[2], color[3]);
+ return 0;
+}
+
+PyDoc_STRVAR(FrsMaterial_shininess_doc,
+"Shininess coefficient of the material.\n"
+"\n"
+":type: float");
+
+static PyObject *FrsMaterial_shininess_get(BPy_FrsMaterial *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->m->shininess());
+}
+
+static int FrsMaterial_shininess_set(BPy_FrsMaterial *self, PyObject *value, void *UNUSED(closure))
+{
+ float scalar;
+ if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */
+ PyErr_SetString(PyExc_TypeError, "value must be a number");
+ return -1;
+ }
+ self->m->setShininess(scalar);
+ return 0;
+}
+
+static PyGetSetDef BPy_FrsMaterial_getseters[] = {
+ {(char *)"diffuse", (getter)FrsMaterial_diffuse_get, (setter)FrsMaterial_diffuse_set,
+ (char *)FrsMaterial_diffuse_doc, NULL},
+ {(char *)"specular", (getter)FrsMaterial_specular_get, (setter)FrsMaterial_specular_set,
+ (char *)FrsMaterial_specular_doc, NULL},
+ {(char *)"ambient", (getter)FrsMaterial_ambient_get, (setter)FrsMaterial_ambient_set,
+ (char *)FrsMaterial_ambient_doc, NULL},
+ {(char *)"emission", (getter)FrsMaterial_emission_get, (setter)FrsMaterial_emission_set,
+ (char *)FrsMaterial_emission_doc, NULL},
+ {(char *)"shininess", (getter)FrsMaterial_shininess_get, (setter)FrsMaterial_shininess_set,
+ (char *)FrsMaterial_shininess_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_FrsMaterial type definition ------------------------------*/
+
+PyTypeObject FrsMaterial_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Material", /* tp_name */
+ sizeof(BPy_FrsMaterial), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)FrsMaterial_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)FrsMaterial_repr, /* 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 */
+ FrsMaterial_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 */
+ BPy_FrsMaterial_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FrsMaterial_init, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_FrsMaterial.h b/source/blender/freestyle/intern/python/BPy_FrsMaterial.h
new file mode 100644
index 00000000000..90eb4a99b8c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_FrsMaterial.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_FrsMaterial.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_FRSMATERIAL_H__
+#define __FREESTYLE_PYTHON_FRSMATERIAL_H__
+
+#include <Python.h>
+
+#include "../scene_graph/FrsMaterial.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject FrsMaterial_Type;
+
+#define BPy_FrsMaterial_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&FrsMaterial_Type))
+
+/*---------------------------Python BPy_FrsMaterial structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ FrsMaterial *m;
+} BPy_FrsMaterial;
+
+/*---------------------------Python BPy_FrsMaterial visible prototypes-----------*/
+
+int FrsMaterial_Init(PyObject *module);
+void FrsMaterial_mathutils_register_callback();
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_FRSMATERIAL_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp
new file mode 100644
index 00000000000..3e6712eff16
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp
@@ -0,0 +1,321 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_FrsNoise.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_FrsNoise.h"
+#include "BPy_Convert.h"
+
+#include <sstream>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int FrsNoise_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&FrsNoise_Type) < 0)
+ return -1;
+ Py_INCREF(&FrsNoise_Type);
+ PyModule_AddObject(module, "Noise", (PyObject *)&FrsNoise_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+PyDoc_STRVAR(FrsNoise_doc,
+"Class to provide Perlin noise functionalities.\n"
+"\n"
+".. method:: __init__(seed = -1)\n"
+"\n"
+" Builds a Noise object. Seed is an optional argument. The seed value is used\n"
+" as a seed for random number generation if it is equal to or greater than zero;\n"
+" otherwise, time is used as a seed.\n"
+"\n"
+" :arg seed: Seed for random number generation.\n"
+" :type seed: int");
+
+static int FrsNoise_init(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"seed", NULL};
+ long seed = -1;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|l", (char **)kwlist, &seed))
+ return -1;
+ self->n = new Noise(seed);
+ return 0;
+}
+
+static void FrsNoise_dealloc(BPy_FrsNoise *self)
+{
+ delete self->n;
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *FrsNoise_repr(BPy_FrsNoise *self)
+{
+ return PyUnicode_FromFormat("Noise - address: %p", self->n);
+}
+
+PyDoc_STRVAR(FrsNoise_turbulence1_doc,
+".. method:: turbulence1(v, freq, amp, oct=4)\n"
+"\n"
+" Returns a noise value for a 1D element.\n"
+"\n"
+" :arg v: One-dimensional sample point.\n"
+" :type v: float\n"
+" :arg freq: Noise frequency.\n"
+" :type freq: float\n"
+" :arg amp: Amplitude.\n"
+" :type amp: float\n"
+" :arg oct: Number of octaves.\n"
+" :type oct: int\n"
+" :return: A noise value.\n"
+" :rtype: float");
+
+static PyObject *FrsNoise_turbulence1(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"v", "freq", "amp", "oct", NULL};
+ float f1, f2, f3;
+ unsigned int i = 4;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "fff|I", (char **)kwlist, &f1, &f2, &f3, &i))
+ return NULL;
+ return PyFloat_FromDouble(self->n->turbulence1(f1, f2, f3, i));
+}
+
+PyDoc_STRVAR(FrsNoise_turbulence2_doc,
+".. method:: turbulence2(v, freq, amp, oct=4)\n"
+"\n"
+" Returns a noise value for a 2D element.\n"
+"\n"
+" :arg v: Two-dimensional sample point.\n"
+" :type v: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n"
+" :arg freq: Noise frequency.\n"
+" :type freq: float\n"
+" :arg amp: Amplitude.\n"
+" :type amp: float\n"
+" :arg oct: Number of octaves.\n"
+" :type oct: int\n"
+" :return: A noise value.\n"
+" :rtype: float");
+
+static PyObject *FrsNoise_turbulence2(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"v", "freq", "amp", "oct", NULL};
+ PyObject *obj1;
+ float f2, f3;
+ unsigned int i = 4;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "Off|I", (char **)kwlist, &obj1, &f2, &f3, &i))
+ return NULL;
+ Vec2f *v = Vec2f_ptr_from_PyObject(obj1);
+ if (!v) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 2D vector (either a list of 2 elements or Vector)");
+ return NULL;
+ }
+ float t = self->n->turbulence2(*v, f2, f3, i);
+ delete v;
+ return PyFloat_FromDouble(t);
+}
+
+PyDoc_STRVAR(FrsNoise_turbulence3_doc,
+".. method:: turbulence3(v, freq, amp, oct=4)\n"
+"\n"
+" Returns a noise value for a 3D element.\n"
+"\n"
+" :arg v: Three-dimensional sample point.\n"
+" :type v: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"
+" :arg freq: Noise frequency.\n"
+" :type freq: float\n"
+" :arg amp: Amplitude.\n"
+" :type amp: float\n"
+" :arg oct: Number of octaves.\n"
+" :type oct: int\n"
+" :return: A noise value.\n"
+" :rtype: float");
+
+static PyObject *FrsNoise_turbulence3(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"v", "freq", "amp", "oct", NULL};
+ PyObject *obj1;
+ float f2, f3;
+ unsigned int i = 4;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "Off|I", (char **)kwlist, &obj1, &f2, &f3, &i))
+ return NULL;
+ Vec3f *v = Vec3f_ptr_from_PyObject(obj1);
+ if (!v) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ float t = self->n->turbulence3(*v, f2, f3, i);
+ delete v;
+ return PyFloat_FromDouble(t);
+}
+
+PyDoc_STRVAR(FrsNoise_smoothNoise1_doc,
+".. method:: smoothNoise1(v)\n"
+"\n"
+" Returns a smooth noise value for a 1D element.\n"
+"\n"
+" :arg v: One-dimensional sample point.\n"
+" :type v: float\n"
+" :return: A smooth noise value.\n"
+" :rtype: float");
+
+static PyObject *FrsNoise_smoothNoise1(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"v", NULL};
+ float f;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "f", (char **)kwlist, &f))
+ return NULL;
+ return PyFloat_FromDouble(self->n->smoothNoise1(f));
+}
+
+PyDoc_STRVAR(FrsNoise_smoothNoise2_doc,
+".. method:: smoothNoise2(v)\n"
+"\n"
+" Returns a smooth noise value for a 2D element.\n"
+"\n"
+" :arg v: Two-dimensional sample point.\n"
+" :type v: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n"
+" :return: A smooth noise value.\n"
+" :rtype: float");
+
+static PyObject *FrsNoise_smoothNoise2(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"v", NULL};
+ PyObject *obj;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", (char **)kwlist, &obj))
+ return NULL;
+ Vec2f *v = Vec2f_ptr_from_PyObject(obj);
+ if (!v) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 2D vector (either a list of 2 elements or Vector)");
+ return NULL;
+ }
+ float t = self->n->smoothNoise2(*v);
+ delete v;
+ return PyFloat_FromDouble(t);
+}
+
+PyDoc_STRVAR(FrsNoise_smoothNoise3_doc,
+".. method:: smoothNoise3(v)\n"
+"\n"
+" Returns a smooth noise value for a 3D element.\n"
+"\n"
+" :arg v: Three-dimensional sample point.\n"
+" :type v: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"
+" :return: A smooth noise value.\n"
+" :rtype: float");
+
+static PyObject *FrsNoise_smoothNoise3(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"v", NULL};
+ PyObject *obj;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", (char **)kwlist, &obj))
+ return NULL;
+ Vec3f *v = Vec3f_ptr_from_PyObject(obj);
+ if (!v) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ float t = self->n->smoothNoise3(*v);
+ delete v;
+ return PyFloat_FromDouble(t);
+}
+
+static PyMethodDef BPy_FrsNoise_methods[] = {
+ {"turbulence1", (PyCFunction)FrsNoise_turbulence1, METH_VARARGS | METH_KEYWORDS, FrsNoise_turbulence1_doc},
+ {"turbulence2", (PyCFunction)FrsNoise_turbulence2, METH_VARARGS | METH_KEYWORDS, FrsNoise_turbulence2_doc},
+ {"turbulence3", (PyCFunction)FrsNoise_turbulence3, METH_VARARGS | METH_KEYWORDS, FrsNoise_turbulence3_doc},
+ {"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},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_FrsNoise type definition ------------------------------*/
+
+PyTypeObject FrsNoise_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Noise", /* tp_name */
+ sizeof(BPy_FrsNoise), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)FrsNoise_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)FrsNoise_repr, /* 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 */
+ FrsNoise_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_FrsNoise_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FrsNoise_init, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_FrsNoise.h b/source/blender/freestyle/intern/python/BPy_FrsNoise.h
new file mode 100644
index 00000000000..91d29eab602
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_FrsNoise.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_FrsNoise.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_FRSNOISE_H__
+#define __FREESTYLE_PYTHON_FRSNOISE_H__
+
+#include <Python.h>
+
+#include "../geometry/Noise.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject FrsNoise_Type;
+
+#define BPy_FrsNoise_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&FrsNoise_Type))
+
+/*---------------------------Python BPy_FrsNoise structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ Noise *n;
+} BPy_FrsNoise;
+
+/*---------------------------Python BPy_FrsNoise visible prototypes-----------*/
+
+int FrsNoise_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_FRSNOISE_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_Id.cpp b/source/blender/freestyle/intern/python/BPy_Id.cpp
new file mode 100644
index 00000000000..d9f1d12dc71
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Id.cpp
@@ -0,0 +1,232 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_Id.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_Id.h"
+
+#include "BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int Id_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&Id_Type) < 0)
+ return -1;
+
+ Py_INCREF(&Id_Type);
+ PyModule_AddObject(module, "Id", (PyObject *)&Id_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+PyDoc_STRVAR(Id_doc,
+"Class for representing an object Id.\n"
+"\n"
+".. method:: __init__(first=0, second=0)\n"
+"\n"
+" Build the Id from two numbers.\n"
+"\n"
+" :arg first: The first number.\n"
+" :type first: int\n"
+" :arg second: The second number.\n"
+" :type second: int\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: An Id object.\n"
+" :type brother: :class:`Id`");
+
+static int Id_init(BPy_Id *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"first", "second", NULL};
+ PyObject *brother;
+ int first = 0, second = 0;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist_1, &Id_Type, &brother)) {
+ self->id = new Id(*(((BPy_Id *)brother)->id));
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "|ii", (char **)kwlist_2, &first, &second))
+ {
+ self->id = new Id(first, second);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ return 0;
+}
+
+static void Id_dealloc(BPy_Id *self)
+{
+ delete self->id;
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *Id_repr(BPy_Id *self)
+{
+ return PyUnicode_FromFormat("[ first: %i, second: %i ](BPy_Id)", self->id->getFirst(), self->id->getSecond());
+}
+
+static PyObject *Id_RichCompare(BPy_Id *o1, BPy_Id *o2, int opid)
+{
+ switch (opid) {
+ case Py_LT:
+ return PyBool_from_bool(o1->id->operator<(*(o2->id)));
+ break;
+ case Py_LE:
+ return PyBool_from_bool(o1->id->operator<(*(o2->id)) || o1->id->operator==(*(o2->id)));
+ break;
+ case Py_EQ:
+ return PyBool_from_bool(o1->id->operator==(*(o2->id)));
+ break;
+ case Py_NE:
+ return PyBool_from_bool(o1->id->operator!=(*(o2->id)));
+ break;
+ case Py_GT:
+ return PyBool_from_bool(!(o1->id->operator<(*(o2->id)) || o1->id->operator==(*(o2->id))));
+ break;
+ case Py_GE:
+ return PyBool_from_bool(!(o1->id->operator<(*(o2->id))));
+ break;
+ }
+ Py_RETURN_NONE;
+}
+
+/*----------------------Id get/setters ----------------------------*/
+
+PyDoc_STRVAR(Id_first_doc,
+"The first number constituting the Id.\n"
+"\n"
+":type: int");
+
+static PyObject *Id_first_get(BPy_Id *self, void *UNUSED(closure))
+{
+ return PyLong_FromLong(self->id->getFirst());
+}
+
+static int Id_first_set(BPy_Id *self, PyObject *value, void *UNUSED(closure))
+{
+ int scalar;
+ if ((scalar = PyLong_AsLong(value)) == -1 && PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError, "value must be an integer");
+ return -1;
+ }
+ self->id->setFirst(scalar);
+ return 0;
+}
+
+PyDoc_STRVAR(Id_second_doc,
+"The second number constituting the Id.\n"
+"\n"
+":type: int");
+
+static PyObject *Id_second_get(BPy_Id *self, void *UNUSED(closure))
+{
+ return PyLong_FromLong(self->id->getSecond());
+}
+
+static int Id_second_set(BPy_Id *self, PyObject *value, void *UNUSED(closure))
+{
+ int scalar;
+ if ((scalar = PyLong_AsLong(value)) == -1 && PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError, "value must be an integer");
+ return -1;
+ }
+ self->id->setSecond(scalar);
+ return 0;
+}
+
+static PyGetSetDef BPy_Id_getseters[] = {
+ {(char *)"first", (getter)Id_first_get, (setter)Id_first_set, (char *)Id_first_doc, NULL},
+ {(char *)"second", (getter)Id_second_get, (setter)Id_second_set, (char *)Id_second_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_Id type definition ------------------------------*/
+
+PyTypeObject Id_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Id", /* tp_name */
+ sizeof(BPy_Id), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Id_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)Id_repr, /* 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 */
+ Id_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ (richcmpfunc)Id_RichCompare, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ BPy_Id_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Id_init, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_Id.h b/source/blender/freestyle/intern/python/BPy_Id.h
new file mode 100644
index 00000000000..9b9ec5b6e2d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Id.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_Id.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_ID_H__
+#define __FREESTYLE_PYTHON_ID_H__
+
+#include <Python.h>
+#include <iostream>
+using namespace std;
+
+#include "../system/Id.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject Id_Type;
+
+#define BPy_Id_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Id_Type))
+
+/*---------------------------Python BPy_Id structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ Id *id;
+} BPy_Id;
+
+/*---------------------------Python BPy_Id visible prototypes-----------*/
+
+int Id_Init(PyObject *module);
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_ID_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp b/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp
new file mode 100644
index 00000000000..8b447129eca
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp
@@ -0,0 +1,262 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_IntegrationType.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_IntegrationType.h"
+
+#include "BPy_Convert.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DFloat.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h"
+#include "Iterator/BPy_Interface0DIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------ MODULE FUNCTIONS ----------------------------------
+
+PyDoc_STRVAR(Integrator_integrate_doc,
+".. function:: integrate(func, it, it_end, integration_type)\n"
+"\n"
+" Returns a single value from a set of values evaluated at each 0D\n"
+" element of this 1D element.\n"
+"\n"
+" :arg func: The UnaryFunction0D used to compute a value at each\n"
+" Interface0D.\n"
+" :type func: :class:`UnaryFunction0D`\n"
+" :arg it: The Interface0DIterator used to iterate over the 0D\n"
+" elements of this 1D element. The integration will occur over\n"
+" the 0D elements starting from the one pointed by it.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :arg it_end: The Interface0DIterator pointing the end of the 0D\n"
+" elements of the 1D element.\n"
+" :type it_end: :class:`Interface0DIterator`\n"
+" :arg integration_type: The integration method used to compute a\n"
+" single value from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+" :return: The single value obtained for the 1D element. The return\n"
+" value type is float if func is of the :class:`UnaryFunction0DDouble`\n"
+" or :class:`UnaryFunction0DFloat` type, and int if func is of the\n"
+" :class:`UnaryFunction0DUnsigned` type.\n"
+" :rtype: int or float");
+
+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;
+ BPy_Interface0DIterator *obj2, *obj3;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!O!|O!", (char **)kwlist,
+ &UnaryFunction0D_Type, &obj1, &Interface0DIterator_Type, &obj2,
+ &Interface0DIterator_Type, &obj3, &IntegrationType_Type, &obj4))
+ {
+ return NULL;
+ }
+
+ Interface0DIterator it(*(obj2->if0D_it)), it_end(*(obj3->if0D_it));
+ IntegrationType t = (obj4) ? IntegrationType_from_BPy_IntegrationType(obj4) : MEAN;
+
+ if (BPy_UnaryFunction0DDouble_Check(obj1)) {
+ UnaryFunction0D<double> *fun = ((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double;
+ double res = integrate(*fun, it, it_end, t);
+ return PyFloat_FromDouble(res);
+ }
+ else if (BPy_UnaryFunction0DFloat_Check(obj1)) {
+ UnaryFunction0D<float> *fun = ((BPy_UnaryFunction0DFloat *)obj1)->uf0D_float;
+ float res = integrate(*fun, it, it_end, t);
+ return PyFloat_FromDouble(res);
+ }
+ else if (BPy_UnaryFunction0DUnsigned_Check(obj1)) {
+ UnaryFunction0D<unsigned int> *fun = ((BPy_UnaryFunction0DUnsigned *)obj1)->uf0D_unsigned;
+ unsigned int res = integrate(*fun, it, it_end, t);
+ return PyLong_FromLong(res);
+ }
+ else {
+ string class_name(Py_TYPE(obj1)->tp_name);
+ PyErr_SetString(PyExc_TypeError, ("unsupported function type: " + class_name).c_str());
+ return NULL;
+ }
+}
+
+/*-----------------------Integrator module docstring---------------------------------------*/
+
+PyDoc_STRVAR(module_docstring, "The Blender Freestyle.Integrator submodule\n\n");
+
+/*-----------------------Integrator module functions definitions---------------------------*/
+
+static PyMethodDef module_functions[] = {
+ {"integrate", (PyCFunction) Integrator_integrate, METH_VARARGS | METH_KEYWORDS, Integrator_integrate_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------Integrator module definition--------------------------------------*/
+
+static PyModuleDef module_definition = {
+ PyModuleDef_HEAD_INIT,
+ "Freestyle.Integrator",
+ module_docstring,
+ -1,
+ module_functions
+};
+
+/*-----------------------BPy_IntegrationType type definition ------------------------------*/
+
+PyDoc_STRVAR(IntegrationType_doc,
+"Class hierarchy: int > :class:`IntegrationType`\n"
+"\n"
+"Different integration methods that can be invoked to integrate into a\n"
+"single value the set of values obtained from each 0D element of an 1D\n"
+"element:\n"
+"\n"
+"* IntegrationType.MEAN: The value computed for the 1D element is the\n"
+" mean of the values obtained for the 0D elements.\n"
+"* IntegrationType.MIN: The value computed for the 1D element is the\n"
+" minimum of the values obtained for the 0D elements.\n"
+"* IntegrationType.MAX: The value computed for the 1D element is the\n"
+" maximum of the values obtained for the 0D elements.\n"
+"* IntegrationType.FIRST: The value computed for the 1D element is the\n"
+" first of the values obtained for the 0D elements.\n"
+"* IntegrationType.LAST: The value computed for the 1D element is the\n"
+" last of the values obtained for the 0D elements.");
+
+PyTypeObject IntegrationType_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "IntegrationType", /* tp_name */
+ sizeof(PyLongObject), /* 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, /* tp_flags */
+ IntegrationType_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 */
+ &PyLong_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+/*-----------------------BPy_IntegrationType instance definitions -------------------------*/
+
+static PyLongObject _IntegrationType_MEAN = {
+ PyVarObject_HEAD_INIT(&IntegrationType_Type, 1)
+ { MEAN }
+};
+static PyLongObject _IntegrationType_MIN = {
+ PyVarObject_HEAD_INIT(&IntegrationType_Type, 1)
+ { MIN }
+};
+static PyLongObject _IntegrationType_MAX = {
+ PyVarObject_HEAD_INIT(&IntegrationType_Type, 1)
+ { MAX }
+};
+static PyLongObject _IntegrationType_FIRST = {
+ PyVarObject_HEAD_INIT(&IntegrationType_Type, 1)
+ { FIRST }
+};
+static PyLongObject _IntegrationType_LAST = {
+ PyVarObject_HEAD_INIT(&IntegrationType_Type, 1)
+ { LAST }
+};
+
+#define BPy_IntegrationType_MEAN ((PyObject *)&_IntegrationType_MEAN)
+#define BPy_IntegrationType_MIN ((PyObject *)&_IntegrationType_MIN)
+#define BPy_IntegrationType_MAX ((PyObject *)&_IntegrationType_MAX)
+#define BPy_IntegrationType_FIRST ((PyObject *)&_IntegrationType_FIRST)
+#define BPy_IntegrationType_LAST ((PyObject *)&_IntegrationType_LAST)
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int IntegrationType_Init(PyObject *module)
+{
+ PyObject *m, *d, *f;
+
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&IntegrationType_Type) < 0)
+ return -1;
+ Py_INCREF(&IntegrationType_Type);
+ PyModule_AddObject(module, "IntegrationType", (PyObject *)&IntegrationType_Type);
+
+ PyDict_SetItemString(IntegrationType_Type.tp_dict, "MEAN", BPy_IntegrationType_MEAN);
+ PyDict_SetItemString(IntegrationType_Type.tp_dict, "MIN", BPy_IntegrationType_MIN);
+ PyDict_SetItemString(IntegrationType_Type.tp_dict, "MAX", BPy_IntegrationType_MAX);
+ PyDict_SetItemString(IntegrationType_Type.tp_dict, "FIRST", BPy_IntegrationType_FIRST);
+ PyDict_SetItemString(IntegrationType_Type.tp_dict, "LAST", BPy_IntegrationType_LAST);
+
+ m = PyModule_Create(&module_definition);
+ if (m == NULL)
+ return -1;
+ Py_INCREF(m);
+ PyModule_AddObject(module, "Integrator", m);
+
+ // from Integrator import *
+ d = PyModule_GetDict(m);
+ for (PyMethodDef *p = module_functions; p->ml_name; p++) {
+ f = PyDict_GetItemString(d, p->ml_name);
+ Py_INCREF(f);
+ PyModule_AddObject(module, p->ml_name, f);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_IntegrationType.h b/source/blender/freestyle/intern/python/BPy_IntegrationType.h
new file mode 100644
index 00000000000..6b5db759297
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_IntegrationType.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_IntegrationType.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_INTEGRATIONTYPE_H__
+#define __FREESTYLE_PYTHON_INTEGRATIONTYPE_H__
+
+#include <Python.h>
+
+#include "../view_map/Interface1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject IntegrationType_Type;
+
+#define BPy_IntegrationType_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&IntegrationType_Type))
+
+/*---------------------------Python BPy_IntegrationType visible prototypes-----------*/
+
+int IntegrationType_Init(PyObject *module);
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_INTEGRATIONTYPE_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_Interface0D.cpp b/source/blender/freestyle/intern/python/BPy_Interface0D.cpp
new file mode 100644
index 00000000000..0202230ac4c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Interface0D.cpp
@@ -0,0 +1,325 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_Interface0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_Interface0D.h"
+
+#include "BPy_Convert.h"
+#include "Interface0D/BPy_CurvePoint.h"
+#include "Interface0D/CurvePoint/BPy_StrokeVertex.h"
+#include "Interface0D/BPy_SVertex.h"
+#include "Interface0D/BPy_ViewVertex.h"
+#include "Interface0D/ViewVertex/BPy_NonTVertex.h"
+#include "Interface0D/ViewVertex/BPy_TVertex.h"
+#include "Interface1D/BPy_FEdge.h"
+#include "BPy_Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int Interface0D_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&Interface0D_Type) < 0)
+ return -1;
+ Py_INCREF(&Interface0D_Type);
+ PyModule_AddObject(module, "Interface0D", (PyObject *)&Interface0D_Type);
+
+ if (PyType_Ready(&CurvePoint_Type) < 0)
+ return -1;
+ Py_INCREF(&CurvePoint_Type);
+ PyModule_AddObject(module, "CurvePoint", (PyObject *)&CurvePoint_Type);
+
+ if (PyType_Ready(&SVertex_Type) < 0)
+ return -1;
+ Py_INCREF(&SVertex_Type);
+ PyModule_AddObject(module, "SVertex", (PyObject *)&SVertex_Type);
+
+ if (PyType_Ready(&ViewVertex_Type) < 0)
+ return -1;
+ Py_INCREF(&ViewVertex_Type);
+ PyModule_AddObject(module, "ViewVertex", (PyObject *)&ViewVertex_Type);
+
+ if (PyType_Ready(&StrokeVertex_Type) < 0)
+ return -1;
+ Py_INCREF(&StrokeVertex_Type);
+ PyModule_AddObject(module, "StrokeVertex", (PyObject *)&StrokeVertex_Type);
+
+ if (PyType_Ready(&NonTVertex_Type) < 0)
+ return -1;
+ Py_INCREF(&NonTVertex_Type);
+ PyModule_AddObject(module, "NonTVertex", (PyObject *)&NonTVertex_Type);
+
+ if (PyType_Ready(&TVertex_Type) < 0)
+ return -1;
+ Py_INCREF(&TVertex_Type);
+ PyModule_AddObject(module, "TVertex", (PyObject *)&TVertex_Type);
+
+ SVertex_mathutils_register_callback();
+ StrokeVertex_mathutils_register_callback();
+
+ return 0;
+}
+
+/*----------------------Interface1D methods ----------------------------*/
+
+PyDoc_STRVAR(Interface0D_doc,
+"Base class for any 0D element.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.");
+
+static int Interface0D_init(BPy_Interface0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->if0D = new Interface0D();
+ self->borrowed = 0;
+ return 0;
+}
+
+static void Interface0D_dealloc(BPy_Interface0D *self)
+{
+ if (self->if0D && !self->borrowed)
+ delete self->if0D;
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *Interface0D_repr(BPy_Interface0D *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->if0D->getExactTypeName().c_str(), self->if0D);
+}
+
+PyDoc_STRVAR(Interface0D_get_fedge_doc,
+".. method:: get_fedge(inter)\n"
+"\n"
+" Returns the FEdge that lies between this 0D element and the 0D\n"
+" element given as the argument.\n"
+"\n"
+" :arg inter: A 0D element.\n"
+" :type inter: :class:`Interface0D`\n"
+" :return: The FEdge lying between the two 0D elements.\n"
+" :rtype: :class:`FEdge`");
+
+static PyObject *Interface0D_get_fedge(BPy_Interface0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"inter", NULL};
+ PyObject *py_if0D;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface0D_Type, &py_if0D))
+ return NULL;
+ FEdge *fe = self->if0D->getFEdge(*(((BPy_Interface0D *)py_if0D)->if0D));
+ if (PyErr_Occurred())
+ return NULL;
+ if (fe)
+ return Any_BPy_FEdge_from_FEdge(*fe);
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef BPy_Interface0D_methods[] = {
+ {"get_fedge", (PyCFunction)Interface0D_get_fedge, METH_VARARGS | METH_KEYWORDS, Interface0D_get_fedge_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------Interface1D get/setters ----------------------------*/
+
+PyDoc_STRVAR(Interface0D_name_doc,
+"The string of the name of this 0D element.\n"
+"\n"
+":type: str");
+
+static PyObject *Interface0D_name_get(BPy_Interface0D *self, void *UNUSED(closure))
+{
+ return PyUnicode_FromString(Py_TYPE(self)->tp_name);
+}
+
+PyDoc_STRVAR(Interface0D_point_3d_doc,
+"The 3D point of this 0D element.\n"
+"\n"
+":type: mathutils.Vector");
+
+static PyObject *Interface0D_point_3d_get(BPy_Interface0D *self, void *UNUSED(closure))
+{
+ Vec3f p(self->if0D->getPoint3D());
+ if (PyErr_Occurred())
+ return NULL;
+ return Vector_from_Vec3f(p);
+}
+
+PyDoc_STRVAR(Interface0D_projected_x_doc,
+"The X coordinate of the projected 3D point of this 0D element.\n"
+"\n"
+":type: float");
+
+static PyObject *Interface0D_projected_x_get(BPy_Interface0D *self, void *UNUSED(closure))
+{
+ real x = self->if0D->getProjectedX();
+ if (PyErr_Occurred())
+ return NULL;
+ return PyFloat_FromDouble(x);
+}
+
+PyDoc_STRVAR(Interface0D_projected_y_doc,
+"The Y coordinate of the projected 3D point of this 0D element.\n"
+"\n"
+":type: float");
+
+static PyObject *Interface0D_projected_y_get(BPy_Interface0D *self, void *UNUSED(closure))
+{
+ real y = self->if0D->getProjectedY();
+ if (PyErr_Occurred())
+ return NULL;
+ return PyFloat_FromDouble(y);
+}
+
+PyDoc_STRVAR(Interface0D_projected_z_doc,
+"The Z coordinate of the projected 3D point of this 0D element.\n"
+"\n"
+":type: float");
+
+static PyObject *Interface0D_projected_z_get(BPy_Interface0D *self, void *UNUSED(closure))
+{
+ real z = self->if0D->getProjectedZ();
+ if (PyErr_Occurred())
+ return NULL;
+ return PyFloat_FromDouble(z);
+}
+
+PyDoc_STRVAR(Interface0D_point_2d_doc,
+"The 2D point of this 0D element.\n"
+"\n"
+":type: mathutils.Vector");
+
+static PyObject *Interface0D_point_2d_get(BPy_Interface0D *self, void *UNUSED(closure))
+{
+ Vec2f p(self->if0D->getPoint2D());
+ if (PyErr_Occurred())
+ return NULL;
+ return Vector_from_Vec2f(p);
+}
+
+PyDoc_STRVAR(Interface0D_id_doc,
+"The Id of this 0D element.\n"
+"\n"
+":type: :class:`Id`");
+
+static PyObject *Interface0D_id_get(BPy_Interface0D *self, void *UNUSED(closure))
+{
+ Id id(self->if0D->getId());
+ if (PyErr_Occurred())
+ return NULL;
+ return BPy_Id_from_Id(id); // return a copy
+}
+
+PyDoc_STRVAR(Interface0D_nature_doc,
+"The nature of this 0D element.\n"
+"\n"
+":type: :class:`Nature`");
+
+static PyObject *Interface0D_nature_get(BPy_Interface0D *self, void *UNUSED(closure))
+{
+ Nature::VertexNature nature = self->if0D->getNature();
+ if (PyErr_Occurred())
+ return NULL;
+ return BPy_Nature_from_Nature(nature);
+}
+
+static PyGetSetDef BPy_Interface0D_getseters[] = {
+ {(char *)"name", (getter)Interface0D_name_get, (setter)NULL, (char *)Interface0D_name_doc, NULL},
+ {(char *)"point_3d", (getter)Interface0D_point_3d_get, (setter)NULL, (char *)Interface0D_point_3d_doc, NULL},
+ {(char *)"projected_x", (getter)Interface0D_projected_x_get, (setter)NULL,
+ (char *)Interface0D_projected_x_doc, NULL},
+ {(char *)"projected_y", (getter)Interface0D_projected_y_get, (setter)NULL,
+ (char *)Interface0D_projected_y_doc, NULL},
+ {(char *)"projected_z", (getter)Interface0D_projected_z_get, (setter)NULL,
+ (char *)Interface0D_projected_z_doc, NULL},
+ {(char *)"point_2d", (getter)Interface0D_point_2d_get, (setter)NULL, (char *)Interface0D_point_2d_doc, NULL},
+ {(char *)"id", (getter)Interface0D_id_get, (setter)NULL, (char *)Interface0D_id_doc, NULL},
+ {(char *)"nature", (getter)Interface0D_nature_get, (setter)NULL, (char *)Interface0D_nature_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_Interface0D type definition ------------------------------*/
+
+PyTypeObject Interface0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Interface0D", /* tp_name */
+ sizeof(BPy_Interface0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Interface0D_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)Interface0D_repr, /* 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 */
+ Interface0D_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Interface0D_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_Interface0D_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Interface0D_init, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_Interface0D.h b/source/blender/freestyle/intern/python/BPy_Interface0D.h
new file mode 100644
index 00000000000..9b24b9d8631
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Interface0D.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_Interface0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_INTERFACE0D_H__
+#define __FREESTYLE_PYTHON_INTERFACE0D_H__
+
+#include <Python.h>
+
+#include "../view_map/Interface0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject Interface0D_Type;
+
+#define BPy_Interface0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Interface0D_Type))
+
+/*---------------------------Python BPy_Interface0D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ Interface0D *if0D;
+ int borrowed; /* non-zero if *if0D is a borrowed object */
+} BPy_Interface0D;
+
+/*---------------------------Python BPy_Interface0D visible prototypes-----------*/
+
+int Interface0D_Init(PyObject *module);
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_INTERFACE0D_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_Interface1D.cpp b/source/blender/freestyle/intern/python/BPy_Interface1D.cpp
new file mode 100644
index 00000000000..a156e76fab6
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Interface1D.cpp
@@ -0,0 +1,357 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_Interface1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_Interface1D.h"
+
+#include "BPy_Convert.h"
+#include "Interface1D/BPy_FrsCurve.h"
+#include "Interface1D/Curve/BPy_Chain.h"
+#include "Interface1D/BPy_FEdge.h"
+#include "Interface1D/FEdge/BPy_FEdgeSharp.h"
+#include "Interface1D/FEdge/BPy_FEdgeSmooth.h"
+#include "Interface1D/BPy_Stroke.h"
+#include "Interface1D/BPy_ViewEdge.h"
+
+#include "BPy_MediumType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int Interface1D_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&Interface1D_Type) < 0)
+ return -1;
+ Py_INCREF(&Interface1D_Type);
+ PyModule_AddObject(module, "Interface1D", (PyObject *)&Interface1D_Type);
+
+ if (PyType_Ready(&FrsCurve_Type) < 0)
+ return -1;
+ Py_INCREF(&FrsCurve_Type);
+ PyModule_AddObject(module, "Curve", (PyObject *)&FrsCurve_Type);
+
+ if (PyType_Ready(&Chain_Type) < 0)
+ return -1;
+ Py_INCREF(&Chain_Type);
+ PyModule_AddObject(module, "Chain", (PyObject *)&Chain_Type);
+
+ if (PyType_Ready(&FEdge_Type) < 0)
+ return -1;
+ Py_INCREF(&FEdge_Type);
+ PyModule_AddObject(module, "FEdge", (PyObject *)&FEdge_Type);
+
+ if (PyType_Ready(&FEdgeSharp_Type) < 0)
+ return -1;
+ Py_INCREF(&FEdgeSharp_Type);
+ PyModule_AddObject(module, "FEdgeSharp", (PyObject *)&FEdgeSharp_Type);
+
+ if (PyType_Ready(&FEdgeSmooth_Type) < 0)
+ return -1;
+ Py_INCREF(&FEdgeSmooth_Type);
+ PyModule_AddObject(module, "FEdgeSmooth", (PyObject *)&FEdgeSmooth_Type);
+
+ if (PyType_Ready(&Stroke_Type) < 0)
+ return -1;
+ Py_INCREF(&Stroke_Type);
+ PyModule_AddObject(module, "Stroke", (PyObject *)&Stroke_Type);
+
+ PyDict_SetItemString(Stroke_Type.tp_dict, "DRY_MEDIUM", BPy_MediumType_DRY_MEDIUM);
+ PyDict_SetItemString(Stroke_Type.tp_dict, "HUMID_MEDIUM", BPy_MediumType_HUMID_MEDIUM);
+ PyDict_SetItemString(Stroke_Type.tp_dict, "OPAQUE_MEDIUM", BPy_MediumType_OPAQUE_MEDIUM);
+
+ if (PyType_Ready(&ViewEdge_Type) < 0)
+ return -1;
+ Py_INCREF(&ViewEdge_Type);
+ PyModule_AddObject(module, "ViewEdge", (PyObject *)&ViewEdge_Type);
+
+ FEdgeSharp_mathutils_register_callback();
+ FEdgeSmooth_mathutils_register_callback();
+
+ return 0;
+}
+
+/*----------------------Interface1D methods ----------------------------*/
+
+PyDoc_STRVAR(Interface1D_doc,
+"Base class for any 1D element.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.");
+
+static int Interface1D_init(BPy_Interface1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->if1D = new Interface1D();
+ self->borrowed = 0;
+ return 0;
+}
+
+static void Interface1D_dealloc(BPy_Interface1D *self)
+{
+ if (self->if1D && !self->borrowed)
+ delete self->if1D;
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *Interface1D_repr(BPy_Interface1D *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->if1D->getExactTypeName().c_str(), self->if1D);
+}
+
+PyDoc_STRVAR(Interface1D_vertices_begin_doc,
+".. method:: vertices_begin()\n"
+"\n"
+" Returns an iterator over the Interface1D vertices, pointing to the\n"
+" first vertex.\n"
+"\n"
+" :return: An Interface0DIterator pointing to the first vertex.\n"
+" :rtype: :class:`Interface0DIterator`");
+
+static PyObject * Interface1D_vertices_begin(BPy_Interface1D *self)
+{
+ Interface0DIterator if0D_it(self->if1D->verticesBegin());
+ return BPy_Interface0DIterator_from_Interface0DIterator(if0D_it, 0);
+}
+
+PyDoc_STRVAR(Interface1D_vertices_end_doc,
+".. method:: vertices_end()\n"
+"\n"
+" Returns an iterator over the Interface1D vertices, pointing after\n"
+" the last vertex.\n"
+"\n"
+" :return: An Interface0DIterator pointing after the last vertex.\n"
+" :rtype: :class:`Interface0DIterator`");
+
+static PyObject * Interface1D_vertices_end(BPy_Interface1D *self)
+{
+ Interface0DIterator if0D_it(self->if1D->verticesEnd());
+ return BPy_Interface0DIterator_from_Interface0DIterator(if0D_it, 1);
+}
+
+PyDoc_STRVAR(Interface1D_points_begin_doc,
+".. method:: points_begin(t=0.0)\n"
+"\n"
+" Returns an iterator over the Interface1D points, pointing to the\n"
+" first point. The difference with vertices_begin() is that here we can\n"
+" iterate over points of the 1D element at a any given sampling.\n"
+" Indeed, for each iteration, a virtual point is created.\n"
+"\n"
+" :arg t: A sampling with which we want to iterate over points of\n"
+" this 1D element.\n"
+" :type t: float\n"
+" :return: An Interface0DIterator pointing to the first point.\n"
+" :rtype: :class:`Interface0DIterator`");
+
+static PyObject * Interface1D_points_begin(BPy_Interface1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"t", NULL};
+ float f = 0.0f;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|f", (char **)kwlist, &f))
+ return NULL;
+ Interface0DIterator if0D_it(self->if1D->pointsBegin(f));
+ return BPy_Interface0DIterator_from_Interface0DIterator(if0D_it, 0);
+}
+
+PyDoc_STRVAR(Interface1D_points_end_doc,
+".. method:: points_end(t=0.0)\n"
+"\n"
+" Returns an iterator over the Interface1D points, pointing after the\n"
+" last point. The difference with vertices_end() is that here we can\n"
+" iterate over points of the 1D element at a given sampling. Indeed,\n"
+" for each iteration, a virtual point is created.\n"
+"\n"
+" :arg t: A sampling with which we want to iterate over points of\n"
+" this 1D element.\n"
+" :type t: float\n"
+" :return: An Interface0DIterator pointing after the last point.\n"
+" :rtype: :class:`Interface0DIterator`");
+
+static PyObject * Interface1D_points_end(BPy_Interface1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"t", NULL};
+ float f = 0.0f;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|f", (char **)kwlist, &f))
+ return NULL;
+ Interface0DIterator if0D_it(self->if1D->pointsEnd(f));
+ return BPy_Interface0DIterator_from_Interface0DIterator(if0D_it, 1);
+}
+
+static PyMethodDef BPy_Interface1D_methods[] = {
+ {"vertices_begin", (PyCFunction)Interface1D_vertices_begin, METH_NOARGS, Interface1D_vertices_begin_doc},
+ {"vertices_end", (PyCFunction)Interface1D_vertices_end, METH_NOARGS, Interface1D_vertices_end_doc},
+ {"points_begin", (PyCFunction)Interface1D_points_begin, METH_VARARGS | METH_KEYWORDS, Interface1D_points_begin_doc},
+ {"points_end", (PyCFunction)Interface1D_points_end, METH_VARARGS | METH_KEYWORDS, Interface1D_points_end_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------Interface1D get/setters ----------------------------*/
+
+PyDoc_STRVAR(Interface1D_name_doc,
+"The string of the name of the 1D element.\n"
+"\n"
+":type: str");
+
+static PyObject *Interface1D_name_get(BPy_Interface1D *self, void *UNUSED(closure))
+{
+ return PyUnicode_FromString(Py_TYPE(self)->tp_name);
+}
+
+PyDoc_STRVAR(Interface1D_id_doc,
+"The Id of this Interface1D.\n"
+"\n"
+":type: :class:`Id`");
+
+static PyObject *Interface1D_id_get(BPy_Interface1D *self, void *UNUSED(closure))
+{
+ Id id(self->if1D->getId());
+ if (PyErr_Occurred())
+ return NULL;
+ return BPy_Id_from_Id(id); // return a copy
+}
+
+PyDoc_STRVAR(Interface1D_nature_doc,
+"The nature of this Interface1D.\n"
+"\n"
+":type: :class:`Nature`");
+
+static PyObject *Interface1D_nature_get(BPy_Interface1D *self, void *UNUSED(closure))
+{
+ Nature::VertexNature nature = self->if1D->getNature();
+ if (PyErr_Occurred())
+ return NULL;
+ return BPy_Nature_from_Nature(nature);
+}
+
+PyDoc_STRVAR(Interface1D_length_2d_doc,
+"The 2D length of this Interface1D.\n"
+"\n"
+":type: float");
+
+static PyObject *Interface1D_length_2d_get(BPy_Interface1D *self, void *UNUSED(closure))
+{
+ real length = self->if1D->getLength2D();
+ if (PyErr_Occurred())
+ return NULL;
+ return PyFloat_FromDouble((double)length);
+}
+
+PyDoc_STRVAR(Interface1D_time_stamp_doc,
+"The time stamp of the 1D element, mainly used for selection.\n"
+"\n"
+":type: int");
+
+static PyObject *Interface1D_time_stamp_get(BPy_Interface1D *self, void *UNUSED(closure))
+{
+ return PyLong_FromLong(self->if1D->getTimeStamp());
+}
+
+static int Interface1D_time_stamp_set(BPy_Interface1D *self, PyObject *value, void *UNUSED(closure))
+{
+ int timestamp;
+
+ if ((timestamp = PyLong_AsLong(value)) == -1 && PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError, "value must be a number");
+ return -1;
+ }
+ self->if1D->setTimeStamp(timestamp);
+ return 0;
+}
+
+static PyGetSetDef BPy_Interface1D_getseters[] = {
+ {(char *)"name", (getter)Interface1D_name_get, (setter)NULL, (char *)Interface1D_name_doc, NULL},
+ {(char *)"id", (getter)Interface1D_id_get, (setter)NULL, (char *)Interface1D_id_doc, NULL},
+ {(char *)"nature", (getter)Interface1D_nature_get, (setter)NULL, (char *)Interface1D_nature_doc, NULL},
+ {(char *)"length_2d", (getter)Interface1D_length_2d_get, (setter)NULL, (char *)Interface1D_length_2d_doc, NULL},
+ {(char *)"time_stamp", (getter)Interface1D_time_stamp_get, (setter)Interface1D_time_stamp_set,
+ (char *)Interface1D_time_stamp_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_Interface1D type definition ------------------------------*/
+
+PyTypeObject Interface1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Interface1D", /* tp_name */
+ sizeof(BPy_Interface1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Interface1D_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)Interface1D_repr, /* 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 */
+ Interface1D_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Interface1D_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_Interface1D_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Interface1D_init, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_Interface1D.h b/source/blender/freestyle/intern/python/BPy_Interface1D.h
new file mode 100644
index 00000000000..a7a81374d22
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Interface1D.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_Interface1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_INTERFACE1D_H__
+#define __FREESTYLE_PYTHON_INTERFACE1D_H__
+
+#include <Python.h>
+
+#include "../view_map/Interface1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject Interface1D_Type;
+
+#define BPy_Interface1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Interface1D_Type))
+
+/*---------------------------Python BPy_Interface1D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ Interface1D *if1D;
+ int borrowed; /* non-zero if *if1D is a borrowed object */
+} BPy_Interface1D;
+
+/*---------------------------Python BPy_Interface1D visible prototypes-----------*/
+
+int Interface1D_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_INTERFACE1D_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_Iterator.cpp b/source/blender/freestyle/intern/python/BPy_Iterator.cpp
new file mode 100644
index 00000000000..302f3455f52
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Iterator.cpp
@@ -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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_Iterator.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_Iterator.h"
+
+#include "BPy_Convert.h"
+#include "Iterator/BPy_AdjacencyIterator.h"
+#include "Iterator/BPy_Interface0DIterator.h"
+#include "Iterator/BPy_CurvePointIterator.h"
+#include "Iterator/BPy_StrokeVertexIterator.h"
+#include "Iterator/BPy_SVertexIterator.h"
+#include "Iterator/BPy_orientedViewEdgeIterator.h"
+#include "Iterator/BPy_ViewEdgeIterator.h"
+#include "Iterator/BPy_ChainingIterator.h"
+#include "Iterator/BPy_ChainPredicateIterator.h"
+#include "Iterator/BPy_ChainSilhouetteIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int Iterator_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&Iterator_Type) < 0)
+ return -1;
+ Py_INCREF(&Iterator_Type);
+ PyModule_AddObject(module, "Iterator", (PyObject *)&Iterator_Type);
+
+ if (PyType_Ready(&AdjacencyIterator_Type) < 0)
+ return -1;
+ Py_INCREF(&AdjacencyIterator_Type);
+ PyModule_AddObject(module, "AdjacencyIterator", (PyObject *)&AdjacencyIterator_Type);
+
+ if (PyType_Ready(&Interface0DIterator_Type) < 0)
+ return -1;
+ Py_INCREF(&Interface0DIterator_Type);
+ PyModule_AddObject(module, "Interface0DIterator", (PyObject *)&Interface0DIterator_Type);
+
+ if (PyType_Ready(&CurvePointIterator_Type) < 0)
+ return -1;
+ Py_INCREF(&CurvePointIterator_Type);
+ PyModule_AddObject(module, "CurvePointIterator", (PyObject *)&CurvePointIterator_Type);
+
+ if (PyType_Ready(&StrokeVertexIterator_Type) < 0)
+ return -1;
+ Py_INCREF(&StrokeVertexIterator_Type);
+ PyModule_AddObject(module, "StrokeVertexIterator", (PyObject *)&StrokeVertexIterator_Type);
+
+ if (PyType_Ready(&SVertexIterator_Type) < 0)
+ return -1;
+ Py_INCREF(&SVertexIterator_Type);
+ PyModule_AddObject(module, "SVertexIterator", (PyObject *)&SVertexIterator_Type);
+
+ if (PyType_Ready(&orientedViewEdgeIterator_Type) < 0)
+ return -1;
+ Py_INCREF(&orientedViewEdgeIterator_Type);
+ PyModule_AddObject(module, "orientedViewEdgeIterator", (PyObject *)&orientedViewEdgeIterator_Type);
+
+ if (PyType_Ready(&ViewEdgeIterator_Type) < 0)
+ return -1;
+ Py_INCREF(&ViewEdgeIterator_Type);
+ PyModule_AddObject(module, "ViewEdgeIterator", (PyObject *)&ViewEdgeIterator_Type);
+
+ if (PyType_Ready(&ChainingIterator_Type) < 0)
+ return -1;
+ Py_INCREF(&ChainingIterator_Type);
+ PyModule_AddObject(module, "ChainingIterator", (PyObject *)&ChainingIterator_Type);
+
+ if (PyType_Ready(&ChainPredicateIterator_Type) < 0)
+ return -1;
+ Py_INCREF(&ChainPredicateIterator_Type);
+ PyModule_AddObject(module, "ChainPredicateIterator", (PyObject *)&ChainPredicateIterator_Type);
+
+ if (PyType_Ready(&ChainSilhouetteIterator_Type) < 0)
+ return -1;
+ Py_INCREF(&ChainSilhouetteIterator_Type);
+ PyModule_AddObject(module, "ChainSilhouetteIterator", (PyObject *)&ChainSilhouetteIterator_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+PyDoc_STRVAR(Iterator_doc,
+"Base class to define iterators.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.");
+
+static int Iterator_init(BPy_Iterator *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->it = new Iterator();
+ return 0;
+}
+
+static void Iterator_dealloc(BPy_Iterator *self)
+{
+ if (self->it)
+ delete self->it;
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *Iterator_repr(BPy_Iterator *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->it);
+}
+
+PyDoc_STRVAR(Iterator_increment_doc,
+".. method:: increment()\n"
+"\n"
+" Makes the iterator point the next element.");
+
+static PyObject *Iterator_increment(BPy_Iterator *self)
+{
+ if (self->it->isEnd()) {
+ PyErr_SetString(PyExc_RuntimeError, "cannot increment any more");
+ return NULL;
+ }
+ self->it->increment();
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Iterator_decrement_doc,
+".. method:: decrement()\n"
+"\n"
+" Makes the iterator point the previous element.");
+
+static PyObject *Iterator_decrement(BPy_Iterator *self)
+{
+ if (self->it->isBegin()) {
+ PyErr_SetString(PyExc_RuntimeError, "cannot decrement any more");
+ return NULL;
+ }
+ self->it->decrement();
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef BPy_Iterator_methods[] = {
+ {"increment", (PyCFunction) Iterator_increment, METH_NOARGS, Iterator_increment_doc},
+ {"decrement", (PyCFunction) Iterator_decrement, METH_NOARGS, Iterator_decrement_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------Iterator get/setters ----------------------------*/
+
+PyDoc_STRVAR(Iterator_name_doc,
+"The string of the name of this iterator.\n"
+"\n"
+":type: str");
+
+static PyObject *Iterator_name_get(BPy_Iterator *self, void *UNUSED(closure))
+{
+ return PyUnicode_FromString(Py_TYPE(self)->tp_name);
+}
+
+PyDoc_STRVAR(Iterator_is_begin_doc,
+"True if the interator points the first element.\n"
+"\n"
+":type: bool");
+
+static PyObject *Iterator_is_begin_get(BPy_Iterator *self, void *UNUSED(closure))
+{
+ return PyBool_from_bool(self->it->isBegin());
+}
+
+PyDoc_STRVAR(Iterator_is_end_doc,
+"True if the interator points the last element.\n"
+"\n"
+":type: bool");
+
+static PyObject *Iterator_is_end_get(BPy_Iterator *self, void *UNUSED(closure))
+{
+ return PyBool_from_bool(self->it->isEnd());
+}
+
+static PyGetSetDef BPy_Iterator_getseters[] = {
+ {(char *)"name", (getter)Iterator_name_get, (setter)NULL, (char *)Iterator_name_doc, NULL},
+ {(char *)"is_begin", (getter)Iterator_is_begin_get, (setter)NULL, (char *)Iterator_is_begin_doc, NULL},
+ {(char *)"is_end", (getter)Iterator_is_end_get, (setter)NULL, (char *)Iterator_is_end_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_Iterator type definition ------------------------------*/
+
+PyTypeObject Iterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Iterator", /* tp_name */
+ sizeof(BPy_Iterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Iterator_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)Iterator_repr, /* 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 */
+ Iterator_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Iterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_Iterator_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Iterator_init, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_Iterator.h b/source/blender/freestyle/intern/python/BPy_Iterator.h
new file mode 100644
index 00000000000..f301a0b83b0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Iterator.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_Iterator.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_ITERATOR_H__
+#define __FREESTYLE_PYTHON_ITERATOR_H__
+
+#include <Python.h>
+
+#include "../system/Iterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject Iterator_Type;
+
+#define BPy_Iterator_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Iterator_Type))
+
+/*---------------------------Python BPy_Iterator structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ Iterator *it;
+} BPy_Iterator;
+
+/*---------------------------Python BPy_Iterator visible prototypes-----------*/
+
+int Iterator_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_ITERATOR_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_MediumType.cpp b/source/blender/freestyle/intern/python/BPy_MediumType.cpp
new file mode 100644
index 00000000000..fc8c6203c80
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_MediumType.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_MediumType.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_MediumType.h"
+
+#include "BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*-----------------------BPy_MediumType type definition ------------------------------*/
+
+PyDoc_STRVAR(MediumType_doc,
+"Class hierarchy: int > :class:`MediumType`\n"
+"\n"
+"The different blending modes available to similate the interaction\n"
+"media-medium:\n"
+"\n"
+"* Stroke.DRY_MEDIUM: To simulate a dry medium such as Pencil or Charcoal.\n"
+"* Stroke.HUMID_MEDIUM: To simulate ink painting (color substraction blending).\n"
+"* Stroke.OPAQUE_MEDIUM: To simulate an opaque medium (oil, spray...).");
+
+PyTypeObject MediumType_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "MediumType", /* tp_name */
+ sizeof(PyLongObject), /* 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, /* tp_flags */
+ MediumType_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 */
+ &PyLong_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+/*-----------------------BPy_IntegrationType instance definitions -------------------------*/
+
+PyLongObject _BPy_MediumType_DRY_MEDIUM = {
+ PyVarObject_HEAD_INIT(&MediumType_Type, 1)
+ { Stroke::DRY_MEDIUM }
+};
+PyLongObject _BPy_MediumType_HUMID_MEDIUM = {
+ PyVarObject_HEAD_INIT(&MediumType_Type, 1)
+ { Stroke::HUMID_MEDIUM }
+};
+PyLongObject _BPy_MediumType_OPAQUE_MEDIUM = {
+ PyVarObject_HEAD_INIT(&MediumType_Type, 1)
+ { Stroke::OPAQUE_MEDIUM }
+};
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int MediumType_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&MediumType_Type) < 0)
+ return -1;
+ Py_INCREF(&MediumType_Type);
+ PyModule_AddObject(module, "MediumType", (PyObject *)&MediumType_Type);
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_MediumType.h b/source/blender/freestyle/intern/python/BPy_MediumType.h
new file mode 100644
index 00000000000..a7db5b15505
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_MediumType.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_MediumType.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_MEDIUMTYPE_H__
+#define __FREESTYLE_PYTHON_MEDIUMTYPE_H__
+
+#include <Python.h>
+
+#include "../stroke/Stroke.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject MediumType_Type;
+
+#define BPy_MediumType_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&MediumType_Type))
+
+/*---------------------------Python BPy_MediumType structure definition----------*/
+typedef struct {
+ PyLongObject i;
+} BPy_MediumType;
+
+/*---------------------------Python BPy_MediumType visible prototypes-----------*/
+
+int MediumType_Init(PyObject *module);
+
+// internal constants
+extern PyLongObject _BPy_MediumType_DRY_MEDIUM;
+extern PyLongObject _BPy_MediumType_HUMID_MEDIUM;
+extern PyLongObject _BPy_MediumType_OPAQUE_MEDIUM;
+// public constants
+#define BPy_MediumType_DRY_MEDIUM ((PyObject *)&_BPy_MediumType_DRY_MEDIUM)
+#define BPy_MediumType_HUMID_MEDIUM ((PyObject *)&_BPy_MediumType_HUMID_MEDIUM)
+#define BPy_MediumType_OPAQUE_MEDIUM ((PyObject *)&_BPy_MediumType_OPAQUE_MEDIUM)
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_MEDIUMTYPE_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_Nature.cpp b/source/blender/freestyle/intern/python/BPy_Nature.cpp
new file mode 100644
index 00000000000..8336206efb5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Nature.cpp
@@ -0,0 +1,337 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_Nature.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_Nature.h"
+
+#include "BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+static PyObject *BPy_Nature_and(PyObject *a, PyObject *b);
+static PyObject *BPy_Nature_xor(PyObject *a, PyObject *b);
+static PyObject *BPy_Nature_or(PyObject *a, PyObject *b);
+static int BPy_Nature_bool(PyObject *v);
+
+/*-----------------------BPy_Nature number method definitions --------------------*/
+
+static PyNumberMethods nature_as_number = {
+ 0, /* binaryfunc nb_add */
+ 0, /* binaryfunc nb_subtract */
+ 0, /* binaryfunc nb_multiply */
+ 0, /* binaryfunc nb_remainder */
+ 0, /* binaryfunc nb_divmod */
+ 0, /* ternaryfunc nb_power */
+ 0, /* unaryfunc nb_negative */
+ 0, /* unaryfunc nb_positive */
+ 0, /* unaryfunc nb_absolute */
+ (inquiry)BPy_Nature_bool, /* inquiry nb_bool */
+ 0, /* unaryfunc nb_invert */
+ 0, /* binaryfunc nb_lshift */
+ 0, /* binaryfunc nb_rshift */
+ (binaryfunc)BPy_Nature_and, /* binaryfunc nb_and */
+ (binaryfunc)BPy_Nature_xor, /* binaryfunc nb_xor */
+ (binaryfunc)BPy_Nature_or, /* binaryfunc nb_or */
+ 0, /* unaryfunc nb_int */
+ 0, /* void *nb_reserved */
+ 0, /* unaryfunc nb_float */
+ 0, /* binaryfunc nb_inplace_add */
+ 0, /* binaryfunc nb_inplace_subtract */
+ 0, /* binaryfunc nb_inplace_multiply */
+ 0, /* binaryfunc nb_inplace_remainder */
+ 0, /* ternaryfunc nb_inplace_power */
+ 0, /* binaryfunc nb_inplace_lshift */
+ 0, /* binaryfunc nb_inplace_rshift */
+ 0, /* binaryfunc nb_inplace_and */
+ 0, /* binaryfunc nb_inplace_xor */
+ 0, /* binaryfunc nb_inplace_or */
+ 0, /* binaryfunc nb_floor_divide */
+ 0, /* binaryfunc nb_true_divide */
+ 0, /* binaryfunc nb_inplace_floor_divide */
+ 0, /* binaryfunc nb_inplace_true_divide */
+ 0, /* unaryfunc nb_index */
+};
+
+/*-----------------------BPy_Nature docstring ------------------------------------*/
+
+PyDoc_STRVAR(Nature_doc,
+"Class hierarchy: int > :class:`Nature`\n"
+"\n"
+"Different possible natures of 0D and 1D elements of the ViewMap.\n"
+"\n"
+"Vertex natures:\n"
+"\n"
+"* Nature.POINT: True for any 0D element.\n"
+"* Nature.S_VERTEX: True for SVertex.\n"
+"* Nature.VIEW_VERTEX: True for ViewVertex.\n"
+"* Nature.NON_T_VERTEX: True for NonTVertex.\n"
+"* Nature.T_VERTEX: True for TVertex.\n"
+"* Nature.CUSP: True for CUSP.\n"
+"\n"
+"Edge natures:\n"
+"\n"
+"* Nature.NO_FEATURE: True for non feature edges (always false for 1D\n"
+" elements of the ViewMap).\n"
+"* Nature.SILHOUETTE: True for silhouettes.\n"
+"* Nature.BORDER: True for borders.\n"
+"* Nature.CREASE: True for creases.\n"
+"* Nature.RIDGE: True for ridges.\n"
+"* Nature.VALLEY: True for valleys.\n"
+"* Nature.SUGGESTIVE_CONTOUR: True for suggestive contours.\n"
+"* Nature.MATERIAL_BOUNDARY: True for edges at material boundaries.\n"
+"* Nature.EDGE_MARK: True for edges having user-defined edge marks.");
+
+/*-----------------------BPy_Nature type definition ------------------------------*/
+
+PyTypeObject Nature_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Nature", /* tp_name */
+ sizeof(PyLongObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ &nature_as_number, /* 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, /* tp_flags */
+ Nature_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 */
+ &PyLong_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+/*-----------------------BPy_Nature instance definitions ----------------------------------*/
+
+static PyLongObject _Nature_POINT = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::POINT }
+};
+static PyLongObject _Nature_S_VERTEX = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::S_VERTEX }
+};
+static PyLongObject _Nature_VIEW_VERTEX = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::VIEW_VERTEX }
+};
+static PyLongObject _Nature_NON_T_VERTEX = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::NON_T_VERTEX }
+};
+static PyLongObject _Nature_T_VERTEX = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::T_VERTEX }
+};
+static PyLongObject _Nature_CUSP = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::CUSP }
+};
+static PyLongObject _Nature_NO_FEATURE = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::NO_FEATURE }
+};
+static PyLongObject _Nature_SILHOUETTE = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::SILHOUETTE }
+};
+static PyLongObject _Nature_BORDER = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::BORDER }
+};
+static PyLongObject _Nature_CREASE = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::CREASE }
+};
+static PyLongObject _Nature_RIDGE = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::RIDGE }
+};
+static PyLongObject _Nature_VALLEY = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::VALLEY }
+};
+static PyLongObject _Nature_SUGGESTIVE_CONTOUR = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::SUGGESTIVE_CONTOUR }
+};
+static PyLongObject _Nature_MATERIAL_BOUNDARY = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::MATERIAL_BOUNDARY }
+};
+static PyLongObject _Nature_EDGE_MARK = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::EDGE_MARK }
+};
+
+#define BPy_Nature_POINT ((PyObject *)&_Nature_POINT)
+#define BPy_Nature_S_VERTEX ((PyObject *)&_Nature_S_VERTEX)
+#define BPy_Nature_VIEW_VERTEX ((PyObject *)&_Nature_VIEW_VERTEX)
+#define BPy_Nature_NON_T_VERTEX ((PyObject *)&_Nature_NON_T_VERTEX)
+#define BPy_Nature_T_VERTEX ((PyObject *)&_Nature_T_VERTEX)
+#define BPy_Nature_CUSP ((PyObject *)&_Nature_CUSP)
+#define BPy_Nature_NO_FEATURE ((PyObject *)&_Nature_NO_FEATURE)
+#define BPy_Nature_SILHOUETTE ((PyObject *)&_Nature_SILHOUETTE)
+#define BPy_Nature_BORDER ((PyObject *)&_Nature_BORDER)
+#define BPy_Nature_CREASE ((PyObject *)&_Nature_CREASE)
+#define BPy_Nature_RIDGE ((PyObject *)&_Nature_RIDGE)
+#define BPy_Nature_VALLEY ((PyObject *)&_Nature_VALLEY)
+#define BPy_Nature_SUGGESTIVE_CONTOUR ((PyObject *)&_Nature_SUGGESTIVE_CONTOUR)
+#define BPy_Nature_MATERIAL_BOUNDARY ((PyObject *)&_Nature_MATERIAL_BOUNDARY)
+#define BPy_Nature_EDGE_MARK ((PyObject *)&_Nature_EDGE_MARK)
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int Nature_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&Nature_Type) < 0)
+ return -1;
+ Py_INCREF(&Nature_Type);
+ PyModule_AddObject(module, "Nature", (PyObject *)&Nature_Type);
+
+ // VertexNature
+ PyDict_SetItemString(Nature_Type.tp_dict, "POINT", BPy_Nature_POINT);
+ PyDict_SetItemString(Nature_Type.tp_dict, "S_VERTEX", BPy_Nature_S_VERTEX);
+ PyDict_SetItemString(Nature_Type.tp_dict, "VIEW_VERTEX", BPy_Nature_VIEW_VERTEX);
+ PyDict_SetItemString(Nature_Type.tp_dict, "NON_T_VERTEX", BPy_Nature_NON_T_VERTEX);
+ PyDict_SetItemString(Nature_Type.tp_dict, "T_VERTEX", BPy_Nature_T_VERTEX);
+ PyDict_SetItemString(Nature_Type.tp_dict, "CUSP", BPy_Nature_CUSP);
+
+ // EdgeNature
+ PyDict_SetItemString(Nature_Type.tp_dict, "NO_FEATURE", BPy_Nature_NO_FEATURE);
+ PyDict_SetItemString(Nature_Type.tp_dict, "SILHOUETTE", BPy_Nature_SILHOUETTE);
+ PyDict_SetItemString(Nature_Type.tp_dict, "BORDER", BPy_Nature_BORDER);
+ PyDict_SetItemString(Nature_Type.tp_dict, "CREASE", BPy_Nature_CREASE);
+ PyDict_SetItemString(Nature_Type.tp_dict, "RIDGE", BPy_Nature_RIDGE);
+ PyDict_SetItemString(Nature_Type.tp_dict, "VALLEY", BPy_Nature_VALLEY);
+ PyDict_SetItemString(Nature_Type.tp_dict, "SUGGESTIVE_CONTOUR", BPy_Nature_SUGGESTIVE_CONTOUR);
+ PyDict_SetItemString(Nature_Type.tp_dict, "MATERIAL_BOUNDARY", BPy_Nature_MATERIAL_BOUNDARY);
+ PyDict_SetItemString(Nature_Type.tp_dict, "EDGE_MARK", BPy_Nature_EDGE_MARK);
+
+ return 0;
+}
+
+static PyObject *BPy_Nature_bitwise(PyObject *a, int op, PyObject *b)
+{
+ BPy_Nature *result;
+
+ if (!BPy_Nature_Check(a) || !BPy_Nature_Check(b)) {
+ PyErr_SetString(PyExc_TypeError, "operands must be a Nature object");
+ return NULL;
+ }
+ if (Py_SIZE(a) != 1) {
+ stringstream msg;
+ msg << "operand 1: unexpected Nature byte length: " << Py_SIZE(a);
+ PyErr_SetString(PyExc_TypeError, msg.str().c_str());
+ return NULL;
+ }
+ if (Py_SIZE(b) != 1) {
+ stringstream msg;
+ msg << "operand 2: unexpected Nature byte length: " << Py_SIZE(b);
+ PyErr_SetString(PyExc_TypeError, msg.str().c_str());
+ return NULL;
+ }
+ result = PyObject_NewVar(BPy_Nature, &Nature_Type, 1);
+ if (!result)
+ return NULL;
+ if (Py_SIZE(result) != 1) {
+ stringstream msg;
+ msg << "unexpected Nature byte length: " << Py_SIZE(result);
+ PyErr_SetString(PyExc_TypeError, msg.str().c_str());
+ return NULL;
+ }
+ switch (op) {
+ case '&':
+ result->i.ob_digit[0] = (((PyLongObject *)a)->ob_digit[0]) & (((PyLongObject *)b)->ob_digit)[0];
+ break;
+ case '^':
+ result->i.ob_digit[0] = (((PyLongObject *)a)->ob_digit[0]) ^ (((PyLongObject *)b)->ob_digit)[0];
+ break;
+ case '|':
+ result->i.ob_digit[0] = (((PyLongObject *)a)->ob_digit[0]) | (((PyLongObject *)b)->ob_digit)[0];
+ break;
+ }
+ return (PyObject *)result;
+}
+
+static PyObject *BPy_Nature_and(PyObject *a, PyObject *b)
+{
+ return BPy_Nature_bitwise(a, '&', b);
+}
+
+static PyObject *BPy_Nature_xor(PyObject *a, PyObject *b)
+{
+ return BPy_Nature_bitwise(a, '^', b);
+}
+
+static PyObject *BPy_Nature_or(PyObject *a, PyObject *b)
+{
+ return BPy_Nature_bitwise(a, '|', b);
+}
+
+static int BPy_Nature_bool(PyObject *v)
+{
+ return ((PyLongObject *)v)->ob_digit[0] != 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_Nature.h b/source/blender/freestyle/intern/python/BPy_Nature.h
new file mode 100644
index 00000000000..a454af86d25
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Nature.h
@@ -0,0 +1,64 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_Nature.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_NATURE_H__
+#define __FREESTYLE_PYTHON_NATURE_H__
+
+#include <Python.h>
+
+#include "../winged_edge/Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject Nature_Type;
+
+#define BPy_Nature_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Nature_Type))
+
+/*---------------------------Python BPy_Nature structure definition----------*/
+typedef struct {
+ PyLongObject i;
+} BPy_Nature;
+
+/*---------------------------Python BPy_Nature visible prototypes-----------*/
+
+int Nature_Init(PyObject *module);
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_NATURE_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_Operators.cpp b/source/blender/freestyle/intern/python/BPy_Operators.cpp
new file mode 100644
index 00000000000..a3f12f4d274
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Operators.cpp
@@ -0,0 +1,743 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_Operators.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_Operators.h"
+
+#include "BPy_BinaryPredicate1D.h"
+#include "BPy_UnaryPredicate0D.h"
+#include "BPy_UnaryPredicate1D.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVoid.h"
+#include "Iterator/BPy_ViewEdgeIterator.h"
+#include "Iterator/BPy_ChainingIterator.h"
+#include "BPy_StrokeShader.h"
+#include "BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int Operators_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&Operators_Type) < 0)
+ return -1;
+ Py_INCREF(&Operators_Type);
+ PyModule_AddObject(module, "Operators", (PyObject *)&Operators_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+PyDoc_STRVAR(Operators_doc,
+"Class defining the operators used in a style module. There are five\n"
+"types of operators: Selection, chaining, splitting, sorting and\n"
+"creation. All these operators are user controlled through functors,\n"
+"predicates and shaders that are taken as arguments.");
+
+static void Operators_dealloc(BPy_Operators *self)
+{
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+PyDoc_STRVAR(Operators_select_doc,
+".. staticmethod:: select(pred)\n"
+"\n"
+" Selects the ViewEdges of the ViewMap verifying a specified\n"
+" condition.\n"
+"\n"
+" :arg pred: The predicate expressing this condition.\n"
+" :type pred: UnaryPredicate1D");
+
+static PyObject *Operators_select(BPy_Operators *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"pred", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &UnaryPredicate1D_Type, &obj))
+ return NULL;
+ if (!((BPy_UnaryPredicate1D *)obj)->up1D) {
+ PyErr_SetString(PyExc_TypeError, "Operators.select(): 1st argument: invalid UnaryPredicate1D object");
+ return NULL;
+ }
+ if (Operators::select(*(((BPy_UnaryPredicate1D *)obj)->up1D)) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.select() failed");
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Operators_chain_doc,
+".. staticmethod:: chain(it, pred, modifier)\n"
+"\n"
+" Builds a set of chains from the current set of ViewEdges. Each\n"
+" ViewEdge of the current list starts a new chain. The chaining\n"
+" operator then iterates over the ViewEdges of the ViewMap using the\n"
+" user specified iterator. This operator only iterates using the\n"
+" increment operator and is therefore unidirectional.\n"
+"\n"
+" :arg it: The iterator on the ViewEdges of the ViewMap. It contains\n"
+" the chaining rule.\n"
+" :type it: :class:`ViewEdgeIterator`\n"
+" :arg pred: The predicate on the ViewEdge that expresses the\n"
+" stopping condition.\n"
+" :type pred: :class:`UnaryPredicate1D`\n"
+" :arg modifier: A function that takes a ViewEdge as argument and\n"
+" that is used to modify the processed ViewEdge state (the\n"
+" timestamp incrementation is a typical illustration of such a\n"
+" modifier).\n"
+" :type modifier: :class:`UnaryFunction1DVoid`\n"
+"\n"
+".. staticmethod:: chain(it, pred)\n"
+"\n"
+" Builds a set of chains from the current set of ViewEdges. Each\n"
+" ViewEdge of the current list starts a new chain. The chaining\n"
+" operator then iterates over the ViewEdges of the ViewMap using the\n"
+" user specified iterator. This operator only iterates using the\n"
+" increment operator and is therefore unidirectional. This chaining\n"
+" operator is different from the previous one because it doesn't take\n"
+" any modifier as argument. Indeed, the time stamp (insuring that a\n"
+" ViewEdge is processed one time) is automatically managed in this\n"
+" case.\n"
+"\n"
+" :arg it: The iterator on the ViewEdges of the ViewMap. It contains\n"
+" the chaining rule. \n"
+" :type it: :class:`ViewEdgeIterator`\n"
+" :arg pred: The predicate on the ViewEdge that expresses the\n"
+" stopping condition.\n"
+" :type pred: :class:`UnaryPredicate1D`");
+
+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;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!|O!", (char **)kwlist,
+ &ChainingIterator_Type, &obj1,
+ &UnaryPredicate1D_Type, &obj2,
+ &UnaryFunction1DVoid_Type, &obj3))
+ {
+ return NULL;
+ }
+ if (!((BPy_ChainingIterator *)obj1)->c_it) {
+ PyErr_SetString(PyExc_TypeError, "Operators.chain(): 1st argument: invalid ChainingIterator object");
+ return NULL;
+ }
+ if (!((BPy_UnaryPredicate1D *)obj2)->up1D) {
+ PyErr_SetString(PyExc_TypeError, "Operators.chain(): 2nd argument: invalid UnaryPredicate1D object");
+ return NULL;
+ }
+ if (!obj3) {
+ if (Operators::chain(*(((BPy_ChainingIterator *)obj1)->c_it),
+ *(((BPy_UnaryPredicate1D *)obj2)->up1D)) < 0)
+ {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.chain() failed");
+ return NULL;
+ }
+ }
+ else {
+ if (!((BPy_UnaryFunction1DVoid *)obj3)->uf1D_void) {
+ PyErr_SetString(PyExc_TypeError, "Operators.chain(): 3rd argument: invalid UnaryFunction1DVoid object");
+ return NULL;
+ }
+ if (Operators::chain(*(((BPy_ChainingIterator *)obj1)->c_it),
+ *(((BPy_UnaryPredicate1D *)obj2)->up1D),
+ *(((BPy_UnaryFunction1DVoid *)obj3)->uf1D_void)) < 0)
+ {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.chain() failed");
+ return NULL;
+ }
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Operators_bidirectional_chain_doc,
+".. staticmethod:: bidirectional_chain(it, pred)\n"
+"\n"
+" Builds a set of chains from the current set of ViewEdges. Each\n"
+" ViewEdge of the current list potentially starts a new chain. The\n"
+" chaining operator then iterates over the ViewEdges of the ViewMap\n"
+" using the user specified iterator. This operator iterates both using\n"
+" the increment and decrement operators and is therefore bidirectional.\n"
+" This operator works with a ChainingIterator which contains the\n"
+" chaining rules. It is this last one which can be told to chain only\n"
+" edges that belong to the selection or not to process twice a ViewEdge\n"
+" during the chaining. Each time a ViewEdge is added to a chain, its\n"
+" chaining time stamp is incremented. This allows you to keep track of\n"
+" the number of chains to which a ViewEdge belongs to.\n"
+"\n"
+" :arg it: The ChainingIterator on the ViewEdges of the ViewMap. It\n"
+" contains the chaining rule.\n"
+" :type it: :class:`ChainingIterator`\n"
+" :arg pred: The predicate on the ViewEdge that expresses the\n"
+" stopping condition.\n"
+" :type pred: :class:`UnaryPredicate1D`\n"
+"\n"
+".. staticmethod:: bidirectional_chain(it)\n"
+"\n"
+" The only difference with the above bidirectional chaining algorithm\n"
+" is that we don't need to pass a stopping criterion. This might be\n"
+" desirable when the stopping criterion is already contained in the\n"
+" iterator definition. Builds a set of chains from the current set of\n"
+" ViewEdges. Each ViewEdge of the current list potentially starts a new\n"
+" chain. The chaining operator then iterates over the ViewEdges of the\n"
+" ViewMap using the user specified iterator. This operator iterates\n"
+" both using the increment and decrement operators and is therefore\n"
+" bidirectional. This operator works with a ChainingIterator which\n"
+" contains the chaining rules. It is this last one which can be told to\n"
+" chain only edges that belong to the selection or not to process twice\n"
+" a ViewEdge during the chaining. Each time a ViewEdge is added to a\n"
+" chain, its chaining time stamp is incremented. This allows you to\n"
+" keep track of the number of chains to which a ViewEdge belongs to.\n"
+"\n"
+" :arg it: The ChainingIterator on the ViewEdges of the ViewMap. It\n"
+" contains the chaining rule.\n"
+" :type it: :class:`ChainingIterator`");
+
+static PyObject *Operators_bidirectional_chain(BPy_Operators *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"it", "pred", NULL};
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O!", (char **)kwlist,
+ &ChainingIterator_Type, &obj1, &UnaryPredicate1D_Type, &obj2))
+ {
+ return NULL;
+ }
+ if (!((BPy_ChainingIterator *)obj1)->c_it) {
+ PyErr_SetString(PyExc_TypeError,
+ "Operators.bidirectional_chain(): 1st argument: invalid ChainingIterator object");
+ return NULL;
+ }
+ if (!obj2) {
+ if (Operators::bidirectionalChain(*(((BPy_ChainingIterator *)obj1)->c_it)) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.bidirectional_chain() failed");
+ return NULL;
+ }
+ }
+ else {
+ if (!((BPy_UnaryPredicate1D *)obj2)->up1D) {
+ PyErr_SetString(PyExc_TypeError,
+ "Operators.bidirectional_chain(): 2nd argument: invalid UnaryPredicate1D object");
+ return NULL;
+ }
+ if (Operators::bidirectionalChain(*(((BPy_ChainingIterator *)obj1)->c_it),
+ *(((BPy_UnaryPredicate1D *)obj2)->up1D)) < 0)
+ {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.bidirectional_chain() failed");
+ return NULL;
+ }
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Operators_sequential_split_doc,
+".. staticmethod:: sequential_split(starting_pred, stopping_pred, sampling=0.0)\n"
+"\n"
+" Splits each chain of the current set of chains in a sequential way.\n"
+" The points of each chain are processed (with a specified sampling)\n"
+" sequentially. Each time a user specified starting condition is\n"
+" verified, a new chain begins and ends as soon as a user-defined\n"
+" stopping predicate is verified. This allows chains overlapping rather\n"
+" than chains partitioning. The first point of the initial chain is the\n"
+" first point of one of the resulting chains. The splitting ends when\n"
+" no more chain can start.\n"
+"\n"
+" :arg starting_pred: The predicate on a point that expresses the\n"
+" starting condition.\n"
+" :type starting_pred: :class:`UnaryPredicate0D`\n"
+" :arg stopping_pred: The predicate on a point that expresses the\n"
+" stopping condition.\n"
+" :type stopping_pred: :class:`UnaryPredicate0D`\n"
+" :arg sampling: The resolution used to sample the chain for the\n"
+" predicates evaluation. (The chain is not actually resampled;\n"
+" a virtual point only progresses along the curve using this\n"
+" resolution.)\n"
+" :type sampling: float\n"
+"\n"
+".. staticmethod:: sequential_split(pred, sampling=0.0)\n"
+"\n"
+" Splits each chain of the current set of chains in a sequential way.\n"
+" The points of each chain are processed (with a specified sampling)\n"
+" sequentially and each time a user specified condition is verified,\n"
+" the chain is split into two chains. The resulting set of chains is a\n"
+" partition of the initial chain\n"
+"\n"
+" :arg pred: The predicate on a point that expresses the splitting\n"
+" condition.\n"
+" :type pred: :class:`UnaryPredicate0D`\n"
+" :arg sampling: The resolution used to sample the chain for the\n"
+" predicate evaluation. (The chain is not actually resampled; a\n"
+" virtual point only progresses along the curve using this\n"
+" resolution.)\n"
+" :type sampling: float");
+
+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};
+ PyObject *obj1 = 0, *obj2 = 0;
+ float f = 0.0f;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O!O!|f", (char **)kwlist_1,
+ &UnaryPredicate0D_Type, &obj1, &UnaryPredicate0D_Type, &obj2, &f))
+ {
+ if (!((BPy_UnaryPredicate0D *)obj1)->up0D) {
+ PyErr_SetString(PyExc_TypeError,
+ "Operators.sequential_split(): 1st argument: invalid UnaryPredicate0D object");
+ return NULL;
+ }
+ if (!((BPy_UnaryPredicate0D *)obj2)->up0D) {
+ PyErr_SetString(PyExc_TypeError,
+ "Operators.sequential_split(): 2nd argument: invalid UnaryPredicate0D object");
+ return NULL;
+ }
+ if (Operators::sequentialSplit(*(((BPy_UnaryPredicate0D *)obj1)->up0D),
+ *(((BPy_UnaryPredicate0D *)obj2)->up0D),
+ f) < 0)
+ {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.sequential_split() failed");
+ return NULL;
+ }
+ }
+ else if (PyErr_Clear(), (f = 0.0f),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!|f", (char **)kwlist_2,
+ &UnaryPredicate0D_Type, &obj1, &f))
+ {
+ if (!((BPy_UnaryPredicate0D *)obj1)->up0D) {
+ PyErr_SetString(PyExc_TypeError,
+ "Operators.sequential_split(): 1st argument: invalid UnaryPredicate0D object");
+ return NULL;
+ }
+ if (Operators::sequentialSplit(*(((BPy_UnaryPredicate0D *)obj1)->up0D), f) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.sequential_split() failed");
+ return NULL;
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Operators_recursive_split_doc,
+".. staticmethod:: recursive_split(func, pred_1d, sampling=0.0)\n"
+"\n"
+" Splits the current set of chains in a recursive way. We process the\n"
+" points of each chain (with a specified sampling) to find the point\n"
+" minimizing a specified function. The chain is split in two at this\n"
+" point and the two new chains are processed in the same way. The\n"
+" recursivity level is controlled through a predicate 1D that expresses\n"
+" a stopping condition on the chain that is about to be processed.\n"
+"\n"
+" :arg func: The Unary Function evaluated at each point of the chain.\n"
+" The splitting point is the point minimizing this function.\n"
+" :type func: :class:`UnaryFunction0DDouble`\n"
+" :arg pred_1d: The Unary Predicate expressing the recursivity stopping\n"
+" condition. This predicate is evaluated for each curve before it\n"
+" actually gets split. If pred_1d(chain) is true, the curve won't be\n"
+" split anymore.\n"
+" :type pred: :class:`UnaryPredicate1D`\n"
+" :arg sampling: The resolution used to sample the chain for the\n"
+" predicates evaluation. (The chain is not actually resampled, a\n"
+" virtual point only progresses along the curve using this\n"
+" resolution.)\n"
+" :type sampling: float\n"
+"\n"
+".. staticmethod:: recursive_split(func, pred_0d, pred_1d, sampling=0.0)\n"
+"\n"
+" Splits the current set of chains in a recursive way. We process the\n"
+" points of each chain (with a specified sampling) to find the point\n"
+" minimizing a specified function. The chain is split in two at this\n"
+" point and the two new chains are processed in the same way. The user\n"
+" can specify a 0D predicate to make a first selection on the points\n"
+" that can potentially be split. A point that doesn't verify the 0D\n"
+" predicate won't be candidate in realizing the min. The recursivity\n"
+" level is controlled through a predicate 1D that expresses a stopping\n"
+" condition on the chain that is about to be processed.\n"
+"\n"
+" :arg func: The Unary Function evaluated at each point of the chain.\n"
+" The splitting point is the point minimizing this function.\n"
+" :type func: :class:`UnaryFunction0DDouble`\n"
+" :arg pred_0d: The Unary Predicate 0D used to select the candidate\n"
+" points where the split can occur. For example, it is very likely\n"
+" that would rather have your chain splitting around its middle\n"
+" point than around one of its extremities. A 0D predicate working\n"
+" on the curvilinear abscissa allows to add this kind of constraints.\n"
+" :type pred_0d: :class:`UnaryPredicate0D`\n"
+" :arg pred_1d: The Unary Predicate expressing the recursivity stopping\n"
+" condition. This predicate is evaluated for each curve before it\n"
+" actually gets split. If pred_1d(chain) is true, the curve won't be\n"
+" split anymore.\n"
+" :type pred: :class:`UnaryPredicate1D`\n"
+" :arg sampling: The resolution used to sample the chain for the\n"
+" predicates evaluation. (The chain is not actually resampled; a\n"
+" virtual point only progresses along the curve using this\n"
+" resolution.)\n"
+" :type sampling: float");
+
+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};
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0;
+ float f = 0.0f;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O!O!|f", (char **)kwlist_1,
+ &UnaryFunction0DDouble_Type, &obj1, &UnaryPredicate1D_Type, &obj2, &f))
+ {
+ if (!((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double) {
+ PyErr_SetString(PyExc_TypeError,
+ "Operators.recursive_split(): 1st argument: invalid UnaryFunction0DDouble object");
+ return NULL;
+ }
+ if (!((BPy_UnaryPredicate1D *)obj2)->up1D) {
+ PyErr_SetString(PyExc_TypeError,
+ "Operators.recursive_split(): 2nd argument: invalid UnaryPredicate1D object");
+ return NULL;
+ }
+ if (Operators::recursiveSplit(*(((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double),
+ *(((BPy_UnaryPredicate1D *)obj2)->up1D),
+ f) < 0)
+ {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.recursive_split() failed");
+ return NULL;
+ }
+ }
+ else if (PyErr_Clear(), (f = 0.0f),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!O!O!|f", (char **)kwlist_2,
+ &UnaryFunction0DDouble_Type, &obj1, &UnaryPredicate0D_Type, &obj2,
+ &UnaryPredicate1D_Type, &obj3, &f))
+ {
+ if (!((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double) {
+ PyErr_SetString(PyExc_TypeError,
+ "Operators.recursive_split(): 1st argument: invalid UnaryFunction0DDouble object");
+ return NULL;
+ }
+ if (!((BPy_UnaryPredicate0D *)obj2)->up0D) {
+ PyErr_SetString(PyExc_TypeError,
+ "Operators.recursive_split(): 2nd argument: invalid UnaryPredicate0D object");
+ return NULL;
+ }
+ if (!((BPy_UnaryPredicate1D *)obj3)->up1D) {
+ PyErr_SetString(PyExc_TypeError,
+ "Operators.recursive_split(): 3rd argument: invalid UnaryPredicate1D object");
+ return NULL;
+ }
+ if (Operators::recursiveSplit(*(((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double),
+ *(((BPy_UnaryPredicate0D *)obj2)->up0D),
+ *(((BPy_UnaryPredicate1D *)obj3)->up1D),
+ f) < 0)
+ {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.recursive_split() failed");
+ return NULL;
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Operators_sort_doc,
+".. staticmethod:: sort(pred)\n"
+"\n"
+" Sorts the current set of chains (or viewedges) according to the\n"
+" comparison predicate given as argument.\n"
+"\n"
+" :arg pred: The binary predicate used for the comparison.\n"
+" :type pred: BinaryPredicate1D");
+
+static PyObject *Operators_sort(BPy_Operators *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"pred", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &BinaryPredicate1D_Type, &obj))
+ return NULL;
+ if (!((BPy_BinaryPredicate1D *)obj)->bp1D) {
+ PyErr_SetString(PyExc_TypeError, "Operators.sort(): 1st argument: invalid BinaryPredicate1D object");
+ return NULL;
+ }
+ if (Operators::sort(*(((BPy_BinaryPredicate1D *)obj)->bp1D)) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.sort() failed");
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Operators_create_doc,
+".. staticmethod:: create(pred, shaders)\n"
+"\n"
+" Creates and shades the strokes from the current set of chains. A\n"
+" predicate can be specified to make a selection pass on the chains.\n"
+"\n"
+" :arg pred: The predicate that a chain must verify in order to be\n"
+" transform as a stroke.\n"
+" :type pred: :class:`UnaryPredicate1D`\n"
+" :arg shaders: The list of shaders used to shade the strokes.\n"
+" :type shaders: List of StrokeShader objects");
+
+static PyObject *Operators_create(BPy_Operators *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"pred", "shaders", NULL};
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!", (char **)kwlist,
+ &UnaryPredicate1D_Type, &obj1, &PyList_Type, &obj2))
+ {
+ return NULL;
+ }
+ if (!((BPy_UnaryPredicate1D *)obj1)->up1D) {
+ PyErr_SetString(PyExc_TypeError, "Operators.create(): 1st argument: invalid UnaryPredicate1D object");
+ return NULL;
+ }
+ vector<StrokeShader *> shaders;
+ for (int i = 0; i < PyList_Size(obj2); i++) {
+ PyObject *py_ss = PyList_GetItem(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);
+ }
+ if (Operators::create(*(((BPy_UnaryPredicate1D *)obj1)->up1D), shaders) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.create() failed");
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Operators_get_viewedge_from_index_doc,
+".. staticmethod:: get_viewedge_from_index(i)\n"
+"\n"
+" Returns the ViewEdge at the index in the current set of ViewEdges.\n"
+"\n"
+" :arg i: index (0 <= i < Operators.get_view_edges_size()).\n"
+" :type i: int\n"
+" :return: The ViewEdge object.\n"
+" :rtype: :class:`ViewEdge`");
+
+static PyObject *Operators_get_viewedge_from_index(BPy_Operators *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"i", NULL};
+ unsigned int i;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", (char **)kwlist, &i))
+ return NULL;
+ if (i >= Operators::getViewEdgesSize()) {
+ PyErr_SetString(PyExc_IndexError, "index out of range");
+ return NULL;
+ }
+ return BPy_ViewEdge_from_ViewEdge(*(Operators::getViewEdgeFromIndex(i)));
+}
+
+PyDoc_STRVAR(Operators_get_chain_from_index_doc,
+".. staticmethod:: get_chain_from_index(i)\n"
+"\n"
+" Returns the Chain at the index in the current set of Chains.\n"
+"\n"
+" :arg i: index (0 <= i < Operators.get_chains_size()).\n"
+" :type i: int\n"
+" :return: The Chain object.\n"
+" :rtype: :class:`Chain`");
+
+static PyObject *Operators_get_chain_from_index(BPy_Operators *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"i", NULL};
+ unsigned int i;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", (char **)kwlist, &i))
+ return NULL;
+ if (i >= Operators::getChainsSize()) {
+ PyErr_SetString(PyExc_IndexError, "index out of range");
+ return NULL;
+ }
+ return BPy_Chain_from_Chain(*(Operators::getChainFromIndex(i)));
+}
+
+PyDoc_STRVAR(Operators_get_stroke_from_index_doc,
+".. staticmethod:: get_stroke_from_index(i)\n"
+"\n"
+" Returns the Stroke at the index in the current set of Strokes.\n"
+"\n"
+" :arg i: index (0 <= i < Operators.get_strokes_size()).\n"
+" :type i: int\n"
+" :return: The Stroke object.\n"
+" :rtype: :class:`Stroke`");
+
+static PyObject *Operators_get_stroke_from_index(BPy_Operators *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"i", NULL};
+ unsigned int i;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", (char **)kwlist, &i))
+ return NULL;
+ if (i >= Operators::getStrokesSize()) {
+ PyErr_SetString(PyExc_IndexError, "index out of range");
+ return NULL;
+ }
+ return BPy_Stroke_from_Stroke(*(Operators::getStrokeFromIndex(i)));
+}
+
+PyDoc_STRVAR(Operators_get_view_edges_size_doc,
+".. staticmethod:: get_view_edges_size()\n"
+"\n"
+" Returns the number of ViewEdges.\n"
+"\n"
+" :return: The number of ViewEdges.\n"
+" :rtype: int");
+
+static PyObject *Operators_get_view_edges_size(BPy_Operators *self)
+{
+ return PyLong_FromLong(Operators::getViewEdgesSize());
+}
+
+PyDoc_STRVAR(Operators_get_chains_size_doc,
+".. staticmethod:: get_chains_size()\n"
+"\n"
+" Returns the number of Chains.\n"
+"\n"
+" :return: The number of Chains.\n"
+" :rtype: int");
+
+static PyObject *Operators_get_chains_size(BPy_Operators *self)
+{
+ return PyLong_FromLong(Operators::getChainsSize());
+}
+
+PyDoc_STRVAR(Operators_get_strokes_size_doc,
+".. staticmethod:: get_strokes_size()\n"
+"\n"
+" Returns the number of Strokes.\n"
+"\n"
+" :return: The number of Strokes.\n"
+" :rtype: int");
+
+static PyObject *Operators_get_strokes_size(BPy_Operators *self)
+{
+ return PyLong_FromLong(Operators::getStrokesSize());
+}
+
+/*----------------------Operators instance definitions ----------------------------*/
+static PyMethodDef BPy_Operators_methods[] = {
+ {"select", (PyCFunction) Operators_select, METH_VARARGS | METH_KEYWORDS | METH_STATIC, Operators_select_doc},
+ {"chain", (PyCFunction) Operators_chain, METH_VARARGS | METH_KEYWORDS | METH_STATIC, Operators_chain_doc},
+ {"bidirectional_chain", (PyCFunction) Operators_bidirectional_chain, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
+ Operators_bidirectional_chain_doc},
+ {"sequential_split", (PyCFunction) Operators_sequential_split, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
+ Operators_sequential_split_doc},
+ {"recursive_split", (PyCFunction) Operators_recursive_split, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
+ 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},
+ {"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,
+ Operators_get_chain_from_index_doc},
+ {"get_stroke_from_index", (PyCFunction) Operators_get_stroke_from_index, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
+ Operators_get_stroke_from_index_doc},
+ {"get_view_edges_size", (PyCFunction) Operators_get_view_edges_size, METH_NOARGS | METH_STATIC,
+ Operators_get_view_edges_size_doc},
+ {"get_chains_size", (PyCFunction) Operators_get_chains_size, METH_NOARGS | METH_STATIC,
+ Operators_get_chains_size_doc},
+ {"get_strokes_size", (PyCFunction) Operators_get_strokes_size, METH_NOARGS | METH_STATIC,
+ Operators_get_strokes_size_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_Operators type definition ------------------------------*/
+
+PyTypeObject Operators_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Operators", /* tp_name */
+ sizeof(BPy_Operators), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Operators_dealloc, /* 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, /* tp_flags */
+ Operators_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Operators_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_Operators.h b/source/blender/freestyle/intern/python/BPy_Operators.h
new file mode 100644
index 00000000000..e1c2f5be363
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Operators.h
@@ -0,0 +1,65 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_Operators.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_OPERATORS_H__
+#define __FREESTYLE_PYTHON_OPERATORS_H__
+
+#include <Python.h>
+
+#include "../stroke/Operators.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject Operators_Type;
+
+#define BPy_Operators_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Operators_Type))
+
+/*---------------------------Python BPy_Operators structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+} BPy_Operators;
+
+/*---------------------------Python BPy_Operators visible prototypes-----------*/
+
+int Operators_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_OPERATORS_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_SShape.cpp b/source/blender/freestyle/intern/python/BPy_SShape.cpp
new file mode 100644
index 00000000000..4928d91b79d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_SShape.cpp
@@ -0,0 +1,324 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_SShape.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_SShape.h"
+
+#include "BPy_Convert.h"
+#include "BPy_BBox.h"
+#include "BPy_Id.h"
+#include "Interface0D/BPy_SVertex.h"
+#include "Interface1D/BPy_FEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int SShape_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&SShape_Type) < 0)
+ return -1;
+ Py_INCREF(&SShape_Type);
+ PyModule_AddObject(module, "SShape", (PyObject *)&SShape_Type);
+
+ return 0;
+}
+
+/*----------------------SShape methods ----------------------------*/
+
+PyDoc_STRVAR(SShape_doc,
+"Class to define a feature shape. It is the gathering of feature\n"
+"elements from an identified input shape.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: An SShape object.\n"
+" :type brother: :class:`SShape`");
+
+static int SShape_init(BPy_SShape *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"brother", NULL};
+ PyObject *brother = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &SShape_Type, &brother))
+ return -1;
+ if (!brother)
+ self->ss = new SShape();
+ else
+ self->ss = new SShape(*(((BPy_SShape *)brother)->ss));
+ self->borrowed = 0;
+ return 0;
+}
+
+static void SShape_dealloc(BPy_SShape *self)
+{
+ if (self->ss && !self->borrowed)
+ delete self->ss;
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *SShape_repr(BPy_SShape *self)
+{
+ return PyUnicode_FromFormat("SShape - address: %p", self->ss);
+}
+
+static char SShape_add_edge_doc[] =
+".. method:: add_edge(edge)\n"
+"\n"
+" Adds an FEdge to the list of FEdges.\n"
+"\n"
+" :arg edge: An FEdge object.\n"
+" :type edge: :class:`FEdge`\n";
+
+static PyObject *SShape_add_edge(BPy_SShape *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"edge", NULL};
+ PyObject *py_fe = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &FEdge_Type, &py_fe))
+ return NULL;
+ self->ss->AddEdge(((BPy_FEdge *)py_fe)->fe);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(SShape_add_vertex_doc,
+".. method:: add_vertex(vertex)\n"
+"\n"
+" Adds an SVertex to the list of SVertex of this Shape. The SShape\n"
+" attribute of the SVertex is also set to this SShape.\n"
+"\n"
+" :arg vertex: An SVertex object.\n"
+" :type vertex: :class:`SVertex`");
+
+static PyObject * SShape_add_vertex(BPy_SShape *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"edge", NULL};
+ PyObject *py_sv = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &SVertex_Type, &py_sv))
+ return NULL;
+ self->ss->AddNewVertex(((BPy_SVertex *)py_sv)->sv);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(SShape_compute_bbox_doc,
+".. method:: compute_bbox()\n"
+"\n"
+" Compute the bbox of the SShape.");
+
+static PyObject *SShape_compute_bbox(BPy_SShape *self)
+{
+ self->ss->ComputeBBox();
+ Py_RETURN_NONE;
+}
+
+// const Material & material (unsigned i) const
+// const vector< Material > & materials () const
+// void SetMaterials (const vector< Material > &iMaterials)
+
+static PyMethodDef BPy_SShape_methods[] = {
+ {"add_edge", (PyCFunction)SShape_add_edge, METH_VARARGS | METH_KEYWORDS, SShape_add_edge_doc},
+ {"add_vertex", (PyCFunction)SShape_add_vertex, METH_VARARGS | METH_KEYWORDS, SShape_add_vertex_doc},
+ {"compute_bbox", (PyCFunction)SShape_compute_bbox, METH_NOARGS, SShape_compute_bbox_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------SShape get/setters ----------------------------*/
+
+PyDoc_STRVAR(SShape_id_doc,
+"The Id of this SShape.\n"
+"\n"
+":type: :class:`Id`");
+
+static PyObject *SShape_id_get(BPy_SShape *self, void *UNUSED(closure))
+{
+ Id id(self->ss->getId());
+ return BPy_Id_from_Id(id); // return a copy
+}
+
+static int SShape_id_set(BPy_SShape *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_Id_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an Id");
+ return -1;
+ }
+ self->ss->setId(*(((BPy_Id *)value)->id));
+ return 0;
+}
+
+PyDoc_STRVAR(SShape_name_doc,
+"The name of the SShape.\n"
+"\n"
+":type: str");
+
+static PyObject *SShape_name_get(BPy_SShape *self, void *UNUSED(closure))
+{
+ return PyUnicode_FromString(self->ss->getName().c_str());
+}
+
+static int SShape_name_set(BPy_SShape *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!PyUnicode_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be a string");
+ return -1;
+ }
+ const string name = _PyUnicode_AsString(value);
+ self->ss->setName(name);
+ return 0;
+}
+
+PyDoc_STRVAR(SShape_bbox_doc,
+"The bounding box of the SShape.\n"
+"\n"
+":type: :class:`BBox`");
+
+static PyObject *SShape_bbox_get(BPy_SShape *self, void *UNUSED(closure))
+{
+ BBox<Vec3r> bb(self->ss->bbox());
+ return BPy_BBox_from_BBox(bb); // return a copy
+}
+
+static int SShape_bbox_set(BPy_SShape *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_BBox_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be a BBox");
+ return -1;
+ }
+ self->ss->setBBox(*(((BPy_BBox *)value)->bb));
+ return 0;
+}
+
+PyDoc_STRVAR(SShape_vertices_doc,
+"The list of vertices constituting this SShape.\n"
+"\n"
+":type: List of :class:`SVertex` objects");
+
+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;
+
+ for (it = vertices.begin(); it != vertices.end(); it++) {
+ PyList_Append(py_vertices, BPy_SVertex_from_SVertex(*(*it)));
+ }
+
+ return py_vertices;
+}
+
+PyDoc_STRVAR(SShape_edges_doc,
+"The list of edges constituting this SShape.\n"
+"\n"
+":type: List of :class:`FEdge` objects");
+
+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;
+
+ for (it = edges.begin(); it != edges.end(); it++) {
+ PyList_Append(py_edges, Any_BPy_FEdge_from_FEdge(*(*it)));
+ }
+
+ return py_edges;
+}
+
+static PyGetSetDef BPy_SShape_getseters[] = {
+ {(char *)"id", (getter)SShape_id_get, (setter)SShape_id_set, (char *)SShape_id_doc, NULL},
+ {(char *)"name", (getter)SShape_name_get, (setter)SShape_name_set, (char *)SShape_name_doc, NULL},
+ {(char *)"bbox", (getter)SShape_bbox_get, (setter)SShape_bbox_set, (char *)SShape_bbox_doc, NULL},
+ {(char *)"edges", (getter)SShape_edges_get, (setter)NULL, (char *)SShape_edges_doc, NULL},
+ {(char *)"vertices", (getter)SShape_vertices_get, (setter)NULL, (char *)SShape_vertices_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_SShape type definition ------------------------------*/
+
+PyTypeObject SShape_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SShape", /* tp_name */
+ sizeof(BPy_SShape), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)SShape_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)SShape_repr, /* 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 */
+ SShape_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_SShape_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_SShape_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SShape_init, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_SShape.h b/source/blender/freestyle/intern/python/BPy_SShape.h
new file mode 100644
index 00000000000..3f253c33da5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_SShape.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_SShape.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_SSHAPE_H__
+#define __FREESTYLE_PYTHON_SSHAPE_H__
+
+#include <Python.h>
+
+#include "../view_map/Silhouette.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject SShape_Type;
+
+#define BPy_SShape_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&SShape_Type))
+
+/*---------------------------Python BPy_SShape structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ SShape *ss;
+ int borrowed; /* non-zero if *ss is a borrowed object */
+} BPy_SShape;
+
+/*---------------------------Python BPy_SShape visible prototypes-----------*/
+
+int SShape_Init(PyObject *module);
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_SSHAPE_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp
new file mode 100644
index 00000000000..1547de42a91
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp
@@ -0,0 +1,648 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_StrokeAttribute.h"
+
+#include "BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int StrokeAttribute_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&StrokeAttribute_Type) < 0)
+ return -1;
+ Py_INCREF(&StrokeAttribute_Type);
+ PyModule_AddObject(module, "StrokeAttribute", (PyObject *)&StrokeAttribute_Type);
+
+ StrokeAttribute_mathutils_register_callback();
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+PyDoc_STRVAR(StrokeAttribute_doc,
+"Class to define a set of attributes associated with a :class:`StrokeVertex`.\n"
+"The attribute set stores the color, alpha and thickness values for a Stroke\n"
+"Vertex.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A StrokeAttribute object.\n"
+" :type brother: :class:`StrokeAttribute`\n"
+"\n"
+".. method:: __init__(red, green, blue, alpha, thickness_right, thickness_left)\n"
+"\n"
+" Build a stroke vertex attribute from a set of parameters.\n"
+"\n"
+" :arg red: Red component of a stroke color.\n"
+" :type red: float\n"
+" :arg green: Green component of a stroke color.\n"
+" :type green: float\n"
+" :arg blue: Blue component of a stroke color.\n"
+" :type blue: float\n"
+" :arg alpha: Alpha component of a stroke color.\n"
+" :type alpha: float\n"
+" :arg thickness_right: Stroke thickness on the right.\n"
+" :type thickness_right: float\n"
+" :arg thickness_left: Stroke thickness on the left.\n"
+" :type thickness_left: float\n"
+"\n"
+".. method:: __init__(attribute1, attribute2, t)\n"
+"\n"
+" Interpolation constructor. Build a StrokeAttribute from two\n"
+" StrokeAttribute objects and an interpolation parameter.\n"
+"\n"
+" :arg attribute1: The first StrokeAttribute object.\n"
+" :type attribute1: :class:`StrokeAttribute`\n"
+" :arg attribute2: The second StrokeAttribute object.\n"
+" :type attribute2: :class:`StrokeAttribute`\n"
+" :arg t: The interpolation parameter (0 <= t <= 1).\n"
+" :type t: float\n");
+
+static int StrokeAttribute_init(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"attribute1", "attribute2", "t", NULL};
+ static const char *kwlist_3[] = {"red", "green", "blue", "alpha", "thickness_right", "thickness_left", NULL};
+ PyObject *obj1 = 0, *obj2 = 0;
+ float red, green, blue, alpha, thickness_right, thickness_left, t;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &StrokeAttribute_Type, &obj1)) {
+ if (!obj1)
+ self->sa = new StrokeAttribute();
+ else
+ self->sa = new StrokeAttribute(*(((BPy_StrokeAttribute *)obj1)->sa));
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!O!f", (char **)kwlist_2,
+ &StrokeAttribute_Type, &obj1, &StrokeAttribute_Type, &obj2, &t))
+ {
+ self->sa = new StrokeAttribute(*(((BPy_StrokeAttribute *)obj1)->sa), *(((BPy_StrokeAttribute *)obj2)->sa), t);
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "ffffff", (char **)kwlist_3,
+ &red, &green, &blue, &alpha, &thickness_right, &thickness_left))
+ {
+ self->sa = new StrokeAttribute(red, green, blue, alpha, thickness_right, thickness_left);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->borrowed = 0;
+ return 0;
+}
+
+static void StrokeAttribute_dealloc(BPy_StrokeAttribute *self)
+{
+ if (self->sa && !self->borrowed)
+ delete self->sa;
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject * StrokeAttribute_repr(BPy_StrokeAttribute *self)
+{
+ stringstream repr("StrokeAttribute:");
+ repr << " r: " << self->sa->getColorR() << " g: " << self->sa->getColorG() << " b: " << self->sa->getColorB() <<
+ " a: " << self->sa->getAlpha() <<
+ " - R: " << self->sa->getThicknessR() << " L: " << self->sa->getThicknessL();
+
+ return PyUnicode_FromString(repr.str().c_str());
+}
+
+PyDoc_STRVAR(StrokeAttribute_get_attribute_real_doc,
+".. method:: get_attribute_real(name)\n"
+"\n"
+" Returns an attribute of float type.\n"
+"\n"
+" :arg name: The name of the attribute.\n"
+" :type name: str\n"
+" :return: The attribute value.\n"
+" :rtype: float\n");
+
+static PyObject *StrokeAttribute_get_attribute_real(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"name", NULL};
+ char *attr;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &attr))
+ return NULL;
+ double a = self->sa->getAttributeReal(attr);
+ return PyFloat_FromDouble(a);
+}
+
+PyDoc_STRVAR(StrokeAttribute_get_attribute_vec2_doc,
+".. method:: get_attribute_vec2(name)\n"
+"\n"
+" Returns an attribute of two-dimensional vector type.\n"
+"\n"
+" :arg name: The name of the attribute.\n"
+" :type name: str\n"
+" :return: The attribute value.\n"
+" :rtype: :class:`mathutils.Vector`\n");
+
+static PyObject *StrokeAttribute_get_attribute_vec2(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"name", NULL};
+ char *attr;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &attr))
+ return NULL;
+ Vec2f a = self->sa->getAttributeVec2f(attr);
+ return Vector_from_Vec2f(a);
+}
+
+PyDoc_STRVAR(StrokeAttribute_get_attribute_vec3_doc,
+".. method:: get_attribute_vec3(name)\n"
+"\n"
+" Returns an attribute of three-dimensional vector type.\n"
+"\n"
+" :arg name: The name of the attribute.\n"
+" :type name: str\n"
+" :return: The attribute value.\n"
+" :rtype: :class:`mathutils.Vector`\n");
+
+static PyObject *StrokeAttribute_get_attribute_vec3(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"name", NULL};
+ char *attr;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &attr))
+ return NULL;
+ Vec3f a = self->sa->getAttributeVec3f(attr);
+ return Vector_from_Vec3f(a);
+}
+
+PyDoc_STRVAR(StrokeAttribute_has_attribute_real_doc,
+".. method:: has_attribute_real(name)\n"
+"\n"
+" Checks whether the attribute name of float type is available.\n"
+"\n"
+" :arg name: The name of the attribute.\n"
+" :type name: str\n"
+" :return: True if the attribute is availbale.\n"
+" :rtype: bool\n");
+
+static PyObject *StrokeAttribute_has_attribute_real(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"name", NULL};
+ char *attr;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &attr))
+ return NULL;
+ return PyBool_from_bool(self->sa->isAttributeAvailableReal(attr));
+}
+
+PyDoc_STRVAR(StrokeAttribute_has_attribute_vec2_doc,
+".. method:: has_attribute_vec2(name)\n"
+"\n"
+" Checks whether the attribute name of two-dimensional vector type\n"
+" is available.\n"
+"\n"
+" :arg name: The name of the attribute.\n"
+" :type name: str\n"
+" :return: True if the attribute is availbale.\n"
+" :rtype: bool\n");
+
+static PyObject *StrokeAttribute_has_attribute_vec2(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"name", NULL};
+ char *attr;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &attr))
+ return NULL;
+ return PyBool_from_bool(self->sa->isAttributeAvailableVec2f(attr));
+}
+
+PyDoc_STRVAR(StrokeAttribute_has_attribute_vec3_doc,
+".. method:: has_attribute_vec3(name)\n"
+"\n"
+" Checks whether the attribute name of three-dimensional vector\n"
+" type is available.\n"
+"\n"
+" :arg name: The name of the attribute.\n"
+" :type name: str\n"
+" :return: True if the attribute is availbale.\n"
+" :rtype: bool\n");
+
+static PyObject *StrokeAttribute_has_attribute_vec3(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"name", NULL};
+ char *attr;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwlist, &attr))
+ return NULL;
+ return PyBool_from_bool(self->sa->isAttributeAvailableVec3f(attr));
+}
+
+PyDoc_STRVAR(StrokeAttribute_set_attribute_real_doc,
+".. method:: set_attribute_real(name, value)\n"
+"\n"
+" Adds a user-defined attribute of float type. If there is no\n"
+" attribute of the given name, it is added. Otherwise, the new value\n"
+" replaces the old one.\n"
+"\n"
+" :arg name: The name of the attribute.\n"
+" :type name: str\n"
+" :arg value: The attribute value.\n"
+" :type value: float\n");
+
+static PyObject * StrokeAttribute_set_attribute_real(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"name", "value", NULL};
+ char *s = 0;
+ double d = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "sd", (char **)kwlist, &s, &d))
+ return NULL;
+ self->sa->setAttributeReal(s, d);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(StrokeAttribute_set_attribute_vec2_doc,
+".. method:: set_attribute_vec2(name, value)\n"
+"\n"
+" Adds a user-defined attribute of two-dimensional vector type. If\n"
+" there is no attribute of the given name, it is added. Otherwise,\n"
+" the new value replaces the old one.\n"
+"\n"
+" :arg name: The name of the attribute.\n"
+" :type name: str\n"
+" :arg value: The attribute value.\n"
+" :type value: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n");
+
+static PyObject * StrokeAttribute_set_attribute_vec2(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"name", "value", NULL};
+ char *s;
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO", (char **)kwlist, &s, &obj))
+ return NULL;
+ Vec2f *v = Vec2f_ptr_from_PyObject(obj);
+ if (!v) {
+ PyErr_SetString(PyExc_TypeError, "argument 2 must be a 2D vector (either a list of 2 elements or Vector)");
+ return NULL;
+ }
+ self->sa->setAttributeVec2f(s, *v);
+ delete v;
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(StrokeAttribute_set_attribute_vec3_doc,
+".. method:: set_attribute_vec3(name, value)\n"
+"\n"
+" Adds a user-defined attribute of three-dimensional vector type.\n"
+" If there is no attribute of the given name, it is added.\n"
+" Otherwise, the new value replaces the old one.\n"
+"\n"
+" :arg name: The name of the attribute.\n"
+" :type name: str\n"
+" :arg value: The attribute value.\n"
+" :type value: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n");
+
+static PyObject * StrokeAttribute_set_attribute_vec3(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"name", "value", NULL};
+ char *s;
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO", (char **)kwlist, &s, &obj))
+ return NULL;
+ Vec3f *v = Vec3f_ptr_from_PyObject(obj);
+ if (!v) {
+ PyErr_SetString(PyExc_TypeError, "argument 2 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->sa->setAttributeVec3f(s, *v);
+ delete v;
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef BPy_StrokeAttribute_methods[] = {
+ {"get_attribute_real", (PyCFunction) StrokeAttribute_get_attribute_real, METH_VARARGS | METH_KEYWORDS,
+ StrokeAttribute_get_attribute_real_doc},
+ {"get_attribute_vec2", (PyCFunction) StrokeAttribute_get_attribute_vec2, METH_VARARGS | METH_KEYWORDS,
+ StrokeAttribute_get_attribute_vec2_doc},
+ {"get_attribute_vec3", (PyCFunction) StrokeAttribute_get_attribute_vec3, METH_VARARGS | METH_KEYWORDS,
+ StrokeAttribute_get_attribute_vec3_doc},
+ {"has_attribute_real", (PyCFunction) StrokeAttribute_has_attribute_real, METH_VARARGS | METH_KEYWORDS,
+ StrokeAttribute_has_attribute_real_doc},
+ {"has_attribute_vec2", (PyCFunction) StrokeAttribute_has_attribute_vec2, METH_VARARGS | METH_KEYWORDS,
+ StrokeAttribute_has_attribute_vec2_doc},
+ {"has_attribute_vec3", (PyCFunction) StrokeAttribute_has_attribute_vec3, METH_VARARGS | METH_KEYWORDS,
+ StrokeAttribute_has_attribute_vec3_doc},
+ {"set_attribute_real", (PyCFunction) StrokeAttribute_set_attribute_real, METH_VARARGS | METH_KEYWORDS,
+ StrokeAttribute_set_attribute_real_doc},
+ {"set_attribute_vec2", (PyCFunction) StrokeAttribute_set_attribute_vec2, METH_VARARGS | METH_KEYWORDS,
+ StrokeAttribute_set_attribute_vec2_doc},
+ {"set_attribute_vec3", (PyCFunction) StrokeAttribute_set_attribute_vec3, METH_VARARGS | METH_KEYWORDS,
+ StrokeAttribute_set_attribute_vec3_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------mathutils callbacks ----------------------------*/
+
+/* subtype */
+#define MATHUTILS_SUBTYPE_COLOR 1
+#define MATHUTILS_SUBTYPE_THICKNESS 2
+
+static int StrokeAttribute_mathutils_check(BaseMathObject *bmo)
+{
+ if (!BPy_StrokeAttribute_Check(bmo->cb_user))
+ return -1;
+ return 0;
+}
+
+static int StrokeAttribute_mathutils_get(BaseMathObject *bmo, int subtype)
+{
+ BPy_StrokeAttribute *self = (BPy_StrokeAttribute *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_COLOR:
+ bmo->data[0] = self->sa->getColorR();
+ bmo->data[1] = self->sa->getColorG();
+ bmo->data[2] = self->sa->getColorB();
+ break;
+ case MATHUTILS_SUBTYPE_THICKNESS:
+ bmo->data[0] = self->sa->getThicknessR();
+ bmo->data[1] = self->sa->getThicknessL();
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int StrokeAttribute_mathutils_set(BaseMathObject *bmo, int subtype)
+{
+ BPy_StrokeAttribute *self = (BPy_StrokeAttribute *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_COLOR:
+ self->sa->setColor(bmo->data[0], bmo->data[1], bmo->data[2]);
+ break;
+ case MATHUTILS_SUBTYPE_THICKNESS:
+ self->sa->setThickness(bmo->data[0], bmo->data[1]);
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int StrokeAttribute_mathutils_get_index(BaseMathObject *bmo, int subtype, int index)
+{
+ BPy_StrokeAttribute *self = (BPy_StrokeAttribute *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_COLOR:
+ switch (index) {
+ case 0: bmo->data[0] = self->sa->getColorR(); break;
+ case 1: bmo->data[1] = self->sa->getColorG(); break;
+ case 2: bmo->data[2] = self->sa->getColorB(); break;
+ default:
+ return -1;
+ }
+ break;
+ case MATHUTILS_SUBTYPE_THICKNESS:
+ switch (index) {
+ case 0: bmo->data[0] = self->sa->getThicknessR(); break;
+ case 1: bmo->data[1] = self->sa->getThicknessL(); break;
+ default:
+ return -1;
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int StrokeAttribute_mathutils_set_index(BaseMathObject *bmo, int subtype, int index)
+{
+ BPy_StrokeAttribute *self = (BPy_StrokeAttribute *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_COLOR:
+ {
+ float r = (index == 0) ? bmo->data[0] : self->sa->getColorR();
+ float g = (index == 1) ? bmo->data[1] : self->sa->getColorG();
+ float b = (index == 2) ? bmo->data[2] : self->sa->getColorB();
+ self->sa->setColor(r, g, b);
+ }
+ break;
+ case MATHUTILS_SUBTYPE_THICKNESS:
+ {
+ float tr = (index == 0) ? bmo->data[0] : self->sa->getThicknessR();
+ float tl = (index == 1) ? bmo->data[1] : self->sa->getThicknessL();
+ self->sa->setThickness(tr, tl);
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static Mathutils_Callback StrokeAttribute_mathutils_cb = {
+ StrokeAttribute_mathutils_check,
+ StrokeAttribute_mathutils_get,
+ StrokeAttribute_mathutils_set,
+ StrokeAttribute_mathutils_get_index,
+ StrokeAttribute_mathutils_set_index
+};
+
+static unsigned char StrokeAttribute_mathutils_cb_index = -1;
+
+void StrokeAttribute_mathutils_register_callback()
+{
+ StrokeAttribute_mathutils_cb_index = Mathutils_RegisterCallback(&StrokeAttribute_mathutils_cb);
+}
+
+/*----------------------StrokeAttribute get/setters ----------------------------*/
+
+PyDoc_STRVAR(StrokeAttribute_alpha_doc,
+"Alpha component of the stroke color.\n"
+"\n"
+":type: float");
+
+static PyObject *StrokeAttribute_alpha_get(BPy_StrokeAttribute *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->sa->getAlpha());
+}
+
+static int StrokeAttribute_alpha_set(BPy_StrokeAttribute *self, PyObject *value, void *UNUSED(closure))
+{
+ float scalar;
+ if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */
+ PyErr_SetString(PyExc_TypeError, "value must be a number");
+ return -1;
+ }
+ self->sa->setAlpha(scalar);
+ return 0;
+}
+
+PyDoc_STRVAR(StrokeAttribute_color_doc,
+"RGB components of the stroke color.\n"
+"\n"
+":type: mathutils.Color");
+
+static PyObject *StrokeAttribute_color_get(BPy_StrokeAttribute *self, void *UNUSED(closure))
+{
+ return Color_CreatePyObject_cb((PyObject *)self, StrokeAttribute_mathutils_cb_index, MATHUTILS_SUBTYPE_COLOR);
+}
+
+static int StrokeAttribute_color_set(BPy_StrokeAttribute *self, PyObject *value, void *UNUSED(closure))
+{
+ Vec3f *v = Vec3f_ptr_from_PyObject(value);
+ if (!v) {
+ PyErr_SetString(PyExc_ValueError, "value must be a 3-dimensional vector");
+ return -1;
+ }
+ self->sa->setColor(v->x(), v->y(), v->z());
+ return 0;
+}
+
+PyDoc_STRVAR(StrokeAttribute_thickness_doc,
+"Right and left components of the stroke thickness.\n"
+"The right (left) component is the thickness on the right (left) of the vertex\n"
+"when following the stroke.\n"
+"\n"
+":type: mathutils.Vector");
+
+static PyObject *StrokeAttribute_thickness_get(BPy_StrokeAttribute *self, void *UNUSED(closure))
+{
+ return Vector_CreatePyObject_cb((PyObject *)self, 2, StrokeAttribute_mathutils_cb_index,
+ MATHUTILS_SUBTYPE_THICKNESS);
+}
+
+static int StrokeAttribute_thickness_set(BPy_StrokeAttribute *self, PyObject *value, void *UNUSED(closure))
+{
+ Vec2f *v = Vec2f_ptr_from_PyObject(value);
+ if (!v) {
+ PyErr_SetString(PyExc_ValueError, "value must be a 2-dimensional vector");
+ return -1;
+ }
+ self->sa->setThickness(v->x(), v->y());
+ return 0;
+}
+
+PyDoc_STRVAR(StrokeAttribute_visible_doc,
+"The visibility flag. True if the StrokeVertex is visible.\n"
+"\n"
+":type: bool");
+
+static PyObject *StrokeAttribute_visible_get(BPy_StrokeAttribute *self, void *UNUSED(closure))
+{
+ return PyBool_from_bool(self->sa->isVisible());
+}
+
+static int StrokeAttribute_visible_set(BPy_StrokeAttribute *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!PyBool_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be boolean");
+ return -1;
+ }
+ self->sa->setVisible(bool_from_PyBool(value));
+ return 0;
+}
+
+static PyGetSetDef BPy_StrokeAttribute_getseters[] = {
+ {(char *)"alpha", (getter)StrokeAttribute_alpha_get, (setter)StrokeAttribute_alpha_set,
+ (char *)StrokeAttribute_alpha_doc, NULL},
+ {(char *)"color", (getter)StrokeAttribute_color_get, (setter)StrokeAttribute_color_set,
+ (char *)StrokeAttribute_color_doc, NULL},
+ {(char *)"thickness", (getter)StrokeAttribute_thickness_get, (setter)StrokeAttribute_thickness_set,
+ (char *)StrokeAttribute_thickness_doc, NULL},
+ {(char *)"visible", (getter)StrokeAttribute_visible_get, (setter)StrokeAttribute_visible_set,
+ (char *)StrokeAttribute_visible_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_StrokeAttribute type definition ------------------------------*/
+
+PyTypeObject StrokeAttribute_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "StrokeAttribute", /* tp_name */
+ sizeof(BPy_StrokeAttribute), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)StrokeAttribute_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)StrokeAttribute_repr, /* 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 */
+ StrokeAttribute_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_StrokeAttribute_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_StrokeAttribute_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)StrokeAttribute_init, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.h b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.h
new file mode 100644
index 00000000000..c87c38af6d1
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_StrokeAttribute.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_STROKEATTRIBUTE_H__
+#define __FREESTYLE_PYTHON_STROKEATTRIBUTE_H__
+
+#include <Python.h>
+
+#include "../stroke/Stroke.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject StrokeAttribute_Type;
+
+#define BPy_StrokeAttribute_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&StrokeAttribute_Type))
+
+/*---------------------------Python BPy_StrokeAttribute structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ StrokeAttribute *sa;
+ int borrowed; /* non-zero if *sa is a borrowed reference */
+} BPy_StrokeAttribute;
+
+/*---------------------------Python BPy_StrokeAttribute visible prototypes-----------*/
+
+int StrokeAttribute_Init(PyObject *module);
+void StrokeAttribute_mathutils_register_callback();
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_STROKEATTRIBUTE_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp b/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp
new file mode 100644
index 00000000000..bc77e8668dd
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp
@@ -0,0 +1,334 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_StrokeShader.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_StrokeShader.h"
+
+#include "BPy_Convert.h"
+#include "Interface1D/BPy_Stroke.h"
+
+#include "StrokeShader/BPy_BackboneStretcherShader.h"
+#include "StrokeShader/BPy_BezierCurveShader.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"
+#include "StrokeShader/BPy_PolygonalizationShader.h"
+#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_TextureAssignerShader.h"
+#include "StrokeShader/BPy_ThicknessNoiseShader.h"
+#include "StrokeShader/BPy_ThicknessVariationPatternShader.h"
+#include "StrokeShader/BPy_TipRemoverShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int StrokeShader_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&StrokeShader_Type) < 0)
+ return -1;
+ Py_INCREF(&StrokeShader_Type);
+ PyModule_AddObject(module, "StrokeShader", (PyObject *)&StrokeShader_Type);
+
+ if (PyType_Ready(&BackboneStretcherShader_Type) < 0)
+ return -1;
+ Py_INCREF(&BackboneStretcherShader_Type);
+ PyModule_AddObject(module, "BackboneStretcherShader", (PyObject *)&BackboneStretcherShader_Type);
+
+ if (PyType_Ready(&BezierCurveShader_Type) < 0)
+ return -1;
+ Py_INCREF(&BezierCurveShader_Type);
+ PyModule_AddObject(module, "BezierCurveShader", (PyObject *)&BezierCurveShader_Type);
+
+ if (PyType_Ready(&CalligraphicShader_Type) < 0)
+ return -1;
+ Py_INCREF(&CalligraphicShader_Type);
+ PyModule_AddObject(module, "CalligraphicShader", (PyObject *)&CalligraphicShader_Type);
+
+ if (PyType_Ready(&ColorNoiseShader_Type) < 0)
+ return -1;
+ 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);
+ PyModule_AddObject(module, "ConstantColorShader", (PyObject *)&ConstantColorShader_Type);
+
+ if (PyType_Ready(&ConstantThicknessShader_Type) < 0)
+ return -1;
+ Py_INCREF(&ConstantThicknessShader_Type);
+ PyModule_AddObject(module, "ConstantThicknessShader", (PyObject *)&ConstantThicknessShader_Type);
+
+ if (PyType_Ready(&ConstrainedIncreasingThicknessShader_Type) < 0)
+ return -1;
+ Py_INCREF(&ConstrainedIncreasingThicknessShader_Type);
+ 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);
+ PyModule_AddObject(module, "GuidingLinesShader", (PyObject *)&GuidingLinesShader_Type);
+
+ if (PyType_Ready(&IncreasingColorShader_Type) < 0)
+ return -1;
+ Py_INCREF(&IncreasingColorShader_Type);
+ PyModule_AddObject(module, "IncreasingColorShader", (PyObject *)&IncreasingColorShader_Type);
+
+ if (PyType_Ready(&IncreasingThicknessShader_Type) < 0)
+ return -1;
+ Py_INCREF(&IncreasingThicknessShader_Type);
+ PyModule_AddObject(module, "IncreasingThicknessShader", (PyObject *)&IncreasingThicknessShader_Type);
+
+ if (PyType_Ready(&PolygonalizationShader_Type) < 0)
+ return -1;
+ Py_INCREF(&PolygonalizationShader_Type);
+ PyModule_AddObject(module, "PolygonalizationShader", (PyObject *)&PolygonalizationShader_Type);
+
+ if (PyType_Ready(&SamplingShader_Type) < 0)
+ return -1;
+ Py_INCREF(&SamplingShader_Type);
+ PyModule_AddObject(module, "SamplingShader", (PyObject *)&SamplingShader_Type);
+
+ if (PyType_Ready(&SmoothingShader_Type) < 0)
+ return -1;
+ Py_INCREF(&SmoothingShader_Type);
+ PyModule_AddObject(module, "SmoothingShader", (PyObject *)&SmoothingShader_Type);
+
+ if (PyType_Ready(&SpatialNoiseShader_Type) < 0)
+ return -1;
+ 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(&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);
+ PyModule_AddObject(module, "TipRemoverShader", (PyObject *)&TipRemoverShader_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char StrokeShader___doc__[] =
+"Base class for stroke shaders. Any stroke shader must inherit from\n"
+"this class and overload the shade() method. A StrokeShader is\n"
+"designed to modify stroke attributes such as thickness, color,\n"
+"geometry, texture, blending mode, and so on. The basic way for this\n"
+"operation is to iterate over the stroke vertices of the :class:`Stroke`\n"
+"and to modify the :class:`StrokeAttribute` of each vertex. Here is a\n"
+"code example of such an iteration::\n"
+"\n"
+" it = ioStroke.strokeVerticesBegin()\n"
+" while not it.is_end:\n"
+" att = it.object.attribute\n"
+" ## perform here any attribute modification\n"
+" it.increment()\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int StrokeShader___init__(BPy_StrokeShader *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->ss = new StrokeShader();
+ self->ss->py_ss = (PyObject *)self;
+ return 0;
+}
+
+static void StrokeShader___dealloc__(BPy_StrokeShader *self)
+{
+ if (self->ss)
+ delete self->ss;
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *StrokeShader___repr__(BPy_StrokeShader *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->ss);
+}
+
+static char StrokeShader_shade___doc__[] =
+".. method:: shade(stroke)\n"
+"\n"
+" The shading method. Must be overloaded by inherited classes.\n"
+"\n"
+" :arg stroke: A Stroke object.\n"
+" :type stroke: :class:`Stroke`\n";
+
+static PyObject *StrokeShader_shade(BPy_StrokeShader *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"stroke", NULL};
+ PyObject *py_s = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Stroke_Type, &py_s))
+ return NULL;
+
+ if (typeid(*(self->ss)) == typeid(StrokeShader)) {
+ PyErr_SetString(PyExc_TypeError, "shade method not properly overridden");
+ return NULL;
+ }
+ if (self->ss->shade(*(((BPy_Stroke *)py_s)->s)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " shade method failed").c_str());
+ }
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef BPy_StrokeShader_methods[] = {
+ {"shade", (PyCFunction)StrokeShader_shade, METH_VARARGS | METH_KEYWORDS, StrokeShader_shade___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------StrokeShader get/setters ----------------------------*/
+
+PyDoc_STRVAR(StrokeShader_name_doc,
+"The name of the stroke shader.\n"
+"\n"
+":type: str");
+
+static PyObject *StrokeShader_name_get(BPy_StrokeShader *self, void *UNUSED(closure))
+{
+ return PyUnicode_FromString(Py_TYPE(self)->tp_name);
+}
+
+static PyGetSetDef BPy_StrokeShader_getseters[] = {
+ {(char *)"name", (getter)StrokeShader_name_get, (setter)NULL, (char *)StrokeShader_name_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_StrokeShader type definition ------------------------------*/
+
+PyTypeObject StrokeShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "StrokeShader", /* tp_name */
+ sizeof(BPy_StrokeShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)StrokeShader___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)StrokeShader___repr__, /* 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 */
+ StrokeShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_StrokeShader_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_StrokeShader_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)StrokeShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_StrokeShader.h b/source/blender/freestyle/intern/python/BPy_StrokeShader.h
new file mode 100644
index 00000000000..690fdf7e424
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_StrokeShader.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_StrokeShader.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_STROKESHADER_H__
+#define __FREESTYLE_PYTHON_STROKESHADER_H__
+
+#include <Python.h>
+
+#include "../system/FreestyleConfig.h"
+
+using namespace std;
+
+#include "../stroke/StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject StrokeShader_Type;
+
+#define BPy_StrokeShader_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&StrokeShader_Type))
+
+/*---------------------------Python BPy_StrokeShader structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ StrokeShader *ss;
+} BPy_StrokeShader;
+
+/*---------------------------Python BPy_StrokeShader visible prototypes-----------*/
+
+int StrokeShader_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_STROKESHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp
new file mode 100644
index 00000000000..d6d6f3189f9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction0D.h"
+
+#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DFloat.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DId.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DMaterial.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DVec2f.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DVec3f.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int UnaryFunction0D_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction0D_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction0D_Type);
+ PyModule_AddObject(module, "UnaryFunction0D", (PyObject *)&UnaryFunction0D_Type);
+
+ UnaryFunction0DDouble_Init(module);
+ UnaryFunction0DEdgeNature_Init(module);
+ UnaryFunction0DFloat_Init(module);
+ UnaryFunction0DId_Init(module);
+ UnaryFunction0DMaterial_Init(module);
+ UnaryFunction0DUnsigned_Init(module);
+ UnaryFunction0DVec2f_Init(module);
+ UnaryFunction0DVec3f_Init(module);
+ UnaryFunction0DVectorViewShape_Init(module);
+ UnaryFunction0DViewShape_Init(module);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0D___doc__[] =
+"Base class for Unary Functions (functors) working on\n"
+":class:`Interface0DIterator`. A unary function will be used by\n"
+"invoking __call__() on an Interface0DIterator. In Python, several\n"
+"different subclasses of UnaryFunction0D are used depending on the\n"
+"types of functors' return values. For example, you would inherit from\n"
+"a :class:`UnaryFunction0DDouble` if you wish to define a function that\n"
+"returns a double value. Available UnaryFunction0D subclasses are:\n"
+"\n"
+"* :class:`UnaryFunction0DDouble`\n"
+"* :class:`UnaryFunction0DEdgeNature`\n"
+"* :class:`UnaryFunction0DFloat`\n"
+"* :class:`UnaryFunction0DId`\n"
+"* :class:`UnaryFunction0DMaterial`\n"
+"* :class:`UnaryFunction0DUnsigned`\n"
+"* :class:`UnaryFunction0DVec2f`\n"
+"* :class:`UnaryFunction0DVec3f`\n"
+"* :class:`UnaryFunction0DVectorViewShape`\n"
+"* :class:`UnaryFunction0DViewShape`\n";
+
+static void UnaryFunction0D___dealloc__(BPy_UnaryFunction0D *self)
+{
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *UnaryFunction0D___repr__(BPy_UnaryFunction0D *self)
+{
+ return PyUnicode_FromString("UnaryFunction0D");
+}
+
+/*----------------------UnaryFunction0D get/setters ----------------------------*/
+
+PyDoc_STRVAR(UnaryFunction0D_name_doc,
+"The name of the unary 0D function.\n"
+"\n"
+":type: str");
+
+static PyObject *UnaryFunction0D_name_get(BPy_UnaryFunction0D *self, void *UNUSED(closure))
+{
+ return PyUnicode_FromString(Py_TYPE(self)->tp_name);
+}
+
+static PyGetSetDef BPy_UnaryFunction0D_getseters[] = {
+ {(char *)"name", (getter)UnaryFunction0D_name_get, (setter)NULL, (char *)UnaryFunction0D_name_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_UnaryFunction0D type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0D", /* tp_name */
+ sizeof(BPy_UnaryFunction0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0D___repr__, /* 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 */
+ UnaryFunction0D___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 */
+ BPy_UnaryFunction0D_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h
new file mode 100644
index 00000000000..a3a4cd1c201
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h
@@ -0,0 +1,65 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION0D_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION0D_H__
+
+#include <Python.h>
+
+#include "../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject UnaryFunction0D_Type;
+
+#define BPy_UnaryFunction0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction0D_Type))
+
+/*---------------------------Python BPy_UnaryFunction0D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ PyObject *py_uf0D;
+} BPy_UnaryFunction0D;
+
+/*---------------------------Python BPy_UnaryFunction0D visible prototypes-----------*/
+
+int UnaryFunction0D_Init(PyObject *module);
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION0D_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp
new file mode 100644
index 00000000000..231769dede0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction1D.h"
+
+#include "UnaryFunction1D/BPy_UnaryFunction1DDouble.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DFloat.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVec2f.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVec3f.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVoid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int UnaryFunction1D_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction1D_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction1D_Type);
+ PyModule_AddObject(module, "UnaryFunction1D", (PyObject *)&UnaryFunction1D_Type);
+
+ UnaryFunction1DDouble_Init(module);
+ UnaryFunction1DEdgeNature_Init(module);
+ UnaryFunction1DFloat_Init(module);
+ UnaryFunction1DUnsigned_Init(module);
+ UnaryFunction1DVec2f_Init(module);
+ UnaryFunction1DVec3f_Init(module);
+ UnaryFunction1DVectorViewShape_Init(module);
+ UnaryFunction1DVoid_Init(module);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1D___doc__[] =
+"Base class for Unary Functions (functors) working on\n"
+":class:`Interface1D`. A unary function will be used by invoking\n"
+"__call__() on an Interface1D. In Python, several different subclasses\n"
+"of UnaryFunction1D are used depending on the types of functors' return\n"
+"values. For example, you would inherit from a\n"
+":class:`UnaryFunction1DDouble` if you wish to define a function that\n"
+"returns a double value. Available UnaryFunction1D subclasses are:\n"
+"\n"
+"* :class:`UnaryFunction1DDouble`\n"
+"* :class:`UnaryFunction1DEdgeNature`\n"
+"* :class:`UnaryFunction1DFloat`\n"
+"* :class:`UnaryFunction1DUnsigned`\n"
+"* :class:`UnaryFunction1DVec2f`\n"
+"* :class:`UnaryFunction1DVec3f`\n"
+"* :class:`UnaryFunction1DVectorViewShape`\n"
+"* :class:`UnaryFunction1DVoid`\n";
+
+static void UnaryFunction1D___dealloc__(BPy_UnaryFunction1D *self)
+{
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *UnaryFunction1D___repr__(BPy_UnaryFunction1D *self)
+{
+ return PyUnicode_FromString("UnaryFunction1D");
+}
+
+/*----------------------UnaryFunction1D get/setters ----------------------------*/
+
+PyDoc_STRVAR(UnaryFunction1D_name_doc,
+"The name of the unary 1D function.\n"
+"\n"
+":type: str");
+
+static PyObject *UnaryFunction1D_name_get(BPy_UnaryFunction1D *self, void *UNUSED(closure))
+{
+ return PyUnicode_FromString(Py_TYPE(self)->tp_name);
+}
+
+static PyGetSetDef BPy_UnaryFunction1D_getseters[] = {
+ {(char *)"name", (getter)UnaryFunction1D_name_get, (setter)NULL, (char *)UnaryFunction1D_name_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_UnaryFunction1D type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1D", /* tp_name */
+ sizeof(BPy_UnaryFunction1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1D___repr__, /* 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 */
+ UnaryFunction1D___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 */
+ BPy_UnaryFunction1D_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h
new file mode 100644
index 00000000000..40712a40961
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h
@@ -0,0 +1,65 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION1D_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION1D_H__
+
+#include <Python.h>
+
+#include "../view_map/Functions1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject UnaryFunction1D_Type;
+
+#define BPy_UnaryFunction1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction1D_Type))
+
+/*---------------------------Python BPy_UnaryFunction1D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ PyObject *py_uf1D;
+} BPy_UnaryFunction1D;
+
+/*---------------------------Python BPy_UnaryFunction1D visible prototypes-----------*/
+
+int UnaryFunction1D_Init(PyObject *module);
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION1D_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp
new file mode 100644
index 00000000000..18383a1d17b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp
@@ -0,0 +1,209 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryPredicate0D.h"
+
+#include "BPy_Convert.h"
+#include "Iterator/BPy_Interface0DIterator.h"
+#include "UnaryPredicate0D/BPy_FalseUP0D.h"
+#include "UnaryPredicate0D/BPy_TrueUP0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int UnaryPredicate0D_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryPredicate0D_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryPredicate0D_Type);
+ PyModule_AddObject(module, "UnaryPredicate0D", (PyObject *)&UnaryPredicate0D_Type);
+
+ if (PyType_Ready(&FalseUP0D_Type) < 0)
+ return -1;
+ Py_INCREF(&FalseUP0D_Type);
+ PyModule_AddObject(module, "FalseUP0D", (PyObject *)&FalseUP0D_Type);
+
+ if (PyType_Ready(&TrueUP0D_Type) < 0)
+ return -1;
+ Py_INCREF(&TrueUP0D_Type);
+ PyModule_AddObject(module, "TrueUP0D", (PyObject *)&TrueUP0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryPredicate0D___doc__[] =
+"Base class for unary predicates that work on\n"
+":class:`Interface0DIterator`. A UnaryPredicate0D is a functor that\n"
+"evaluates a condition on an Interface0DIterator and returns true or\n"
+"false depending on whether this condition is satisfied or not. The\n"
+"UnaryPredicate0D is used by invoking its __call__() method. Any\n"
+"inherited class must overload the __call__() method.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Must be overload by inherited classes.\n"
+"\n"
+" :arg it: The Interface0DIterator pointing onto the Interface0D at\n"
+" which we wish to evaluate the predicate.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: True if the condition is satisfied, false otherwise.\n"
+" :rtype: bool\n";
+
+static int UnaryPredicate0D___init__(BPy_UnaryPredicate0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->up0D = new UnaryPredicate0D();
+ self->up0D->py_up0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryPredicate0D___dealloc__(BPy_UnaryPredicate0D *self)
+{
+ if (self->up0D)
+ delete self->up0D;
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *UnaryPredicate0D___repr__(BPy_UnaryPredicate0D *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->up0D);
+}
+
+static PyObject *UnaryPredicate0D___call__(BPy_UnaryPredicate0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"it", NULL};
+ PyObject *py_if0D_it;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface0DIterator_Type, &py_if0D_it))
+ return NULL;
+
+ Interface0DIterator *if0D_it = ((BPy_Interface0DIterator *)py_if0D_it)->if0D_it;
+
+ if (!if0D_it) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " has no Interface0DIterator").c_str());
+ return NULL;
+ }
+ if (typeid(*(self->up0D)) == typeid(UnaryPredicate0D)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->up0D->operator()(*if0D_it) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return PyBool_from_bool(self->up0D->result);
+}
+
+/*----------------------UnaryPredicate0D get/setters ----------------------------*/
+
+PyDoc_STRVAR(UnaryPredicate0D_name_doc,
+"The name of the unary 0D predicate.\n"
+"\n"
+":type: str");
+
+static PyObject *UnaryPredicate0D_name_get(BPy_UnaryPredicate0D *self, void *UNUSED(closure))
+{
+ return PyUnicode_FromString(Py_TYPE(self)->tp_name);
+}
+
+static PyGetSetDef BPy_UnaryPredicate0D_getseters[] = {
+ {(char *)"name", (getter)UnaryPredicate0D_name_get, (setter)NULL, (char *)UnaryPredicate0D_name_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_UnaryPredicate0D type definition ------------------------------*/
+
+PyTypeObject UnaryPredicate0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryPredicate0D", /* tp_name */
+ sizeof(BPy_UnaryPredicate0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryPredicate0D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryPredicate0D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryPredicate0D___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryPredicate0D___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 */
+ BPy_UnaryPredicate0D_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryPredicate0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h
new file mode 100644
index 00000000000..b30516aff26
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h
@@ -0,0 +1,65 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYPREDICATE0D_H__
+#define __FREESTYLE_PYTHON_UNARYPREDICATE0D_H__
+
+#include <Python.h>
+
+#include "../stroke/Predicates0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject UnaryPredicate0D_Type;
+
+#define BPy_UnaryPredicate0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryPredicate0D_Type))
+
+/*---------------------------Python BPy_UnaryPredicate0D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ UnaryPredicate0D *up0D;
+} BPy_UnaryPredicate0D;
+
+/*---------------------------Python BPy_UnaryPredicate0D visible prototypes-----------*/
+
+int UnaryPredicate0D_Init(PyObject *module);
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYPREDICATE0D_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp
new file mode 100644
index 00000000000..fe61d0cd3c3
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp
@@ -0,0 +1,257 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryPredicate1D.h"
+
+#include "BPy_Convert.h"
+#include "BPy_Interface1D.h"
+
+#include "UnaryPredicate1D/BPy_ContourUP1D.h"
+#include "UnaryPredicate1D/BPy_DensityLowerThanUP1D.h"
+#include "UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h"
+#include "UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h"
+#include "UnaryPredicate1D/BPy_ExternalContourUP1D.h"
+#include "UnaryPredicate1D/BPy_FalseUP1D.h"
+#include "UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h"
+#include "UnaryPredicate1D/BPy_ShapeUP1D.h"
+#include "UnaryPredicate1D/BPy_TrueUP1D.h"
+#include "UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int UnaryPredicate1D_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryPredicate1D_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryPredicate1D_Type);
+ PyModule_AddObject(module, "UnaryPredicate1D", (PyObject *)&UnaryPredicate1D_Type);
+
+ if (PyType_Ready(&ContourUP1D_Type) < 0)
+ return -1;
+ Py_INCREF(&ContourUP1D_Type);
+ PyModule_AddObject(module, "ContourUP1D", (PyObject *)&ContourUP1D_Type);
+
+ if (PyType_Ready(&DensityLowerThanUP1D_Type) < 0)
+ return -1;
+ Py_INCREF(&DensityLowerThanUP1D_Type);
+ PyModule_AddObject(module, "DensityLowerThanUP1D", (PyObject *)&DensityLowerThanUP1D_Type);
+
+ if (PyType_Ready(&EqualToChainingTimeStampUP1D_Type) < 0)
+ return -1;
+ Py_INCREF(&EqualToChainingTimeStampUP1D_Type);
+ PyModule_AddObject(module, "EqualToChainingTimeStampUP1D", (PyObject *)&EqualToChainingTimeStampUP1D_Type);
+
+ if (PyType_Ready(&EqualToTimeStampUP1D_Type) < 0)
+ return -1;
+ Py_INCREF(&EqualToTimeStampUP1D_Type);
+ PyModule_AddObject(module, "EqualToTimeStampUP1D", (PyObject *)&EqualToTimeStampUP1D_Type);
+
+ if (PyType_Ready(&ExternalContourUP1D_Type) < 0)
+ return -1;
+ Py_INCREF(&ExternalContourUP1D_Type);
+ PyModule_AddObject(module, "ExternalContourUP1D", (PyObject *)&ExternalContourUP1D_Type);
+
+ if (PyType_Ready(&FalseUP1D_Type) < 0)
+ return -1;
+ Py_INCREF(&FalseUP1D_Type);
+ PyModule_AddObject(module, "FalseUP1D", (PyObject *)&FalseUP1D_Type);
+
+ if (PyType_Ready(&QuantitativeInvisibilityUP1D_Type) < 0)
+ return -1;
+ Py_INCREF(&QuantitativeInvisibilityUP1D_Type);
+ PyModule_AddObject(module, "QuantitativeInvisibilityUP1D", (PyObject *)&QuantitativeInvisibilityUP1D_Type);
+
+ if (PyType_Ready(&ShapeUP1D_Type) < 0)
+ return -1;
+ Py_INCREF(&ShapeUP1D_Type);
+ PyModule_AddObject(module, "ShapeUP1D", (PyObject *)&ShapeUP1D_Type);
+
+ if (PyType_Ready(&TrueUP1D_Type) < 0)
+ return -1;
+ Py_INCREF(&TrueUP1D_Type);
+ PyModule_AddObject(module, "TrueUP1D", (PyObject *)&TrueUP1D_Type);
+
+ if (PyType_Ready(&WithinImageBoundaryUP1D_Type) < 0)
+ return -1;
+ Py_INCREF(&WithinImageBoundaryUP1D_Type);
+ PyModule_AddObject(module, "WithinImageBoundaryUP1D", (PyObject *)&WithinImageBoundaryUP1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryPredicate1D___doc__[] =
+"Base class for unary predicates that work on :class:`Interface1D`. A\n"
+"UnaryPredicate1D is a functor that evaluates a condition on a\n"
+"Interface1D and returns true or false depending on whether this\n"
+"condition is satisfied or not. The UnaryPredicate1D is used by\n"
+"invoking its __call__() method. Any inherited class must overload the\n"
+"__call__() method.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Must be overload by inherited classes.\n"
+"\n"
+" :arg inter: The Interface1D on which we wish to evaluate the predicate.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if the condition is satisfied, false otherwise.\n"
+" :rtype: bool\n";
+
+static int UnaryPredicate1D___init__(BPy_UnaryPredicate1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->up1D = new UnaryPredicate1D();
+ self->up1D->py_up1D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryPredicate1D___dealloc__(BPy_UnaryPredicate1D *self)
+{
+ if (self->up1D)
+ delete self->up1D;
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *UnaryPredicate1D___repr__(BPy_UnaryPredicate1D *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->up1D);
+}
+
+static PyObject *UnaryPredicate1D___call__(BPy_UnaryPredicate1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"inter", NULL};
+ PyObject *py_if1D;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface1D_Type, &py_if1D))
+ return NULL;
+
+ Interface1D *if1D = ((BPy_Interface1D *)py_if1D)->if1D;
+
+ if (!if1D) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " has no Interface1D").c_str());
+ return NULL;
+ }
+ if (typeid(*(self->up1D)) == typeid(UnaryPredicate1D)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->up1D->operator()(*if1D) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return PyBool_from_bool(self->up1D->result);
+}
+
+/*----------------------UnaryPredicate1D get/setters ----------------------------*/
+
+PyDoc_STRVAR(UnaryPredicate1D_name_doc,
+"The name of the unary 1D predicate.\n"
+"\n"
+":type: str");
+
+static PyObject *UnaryPredicate1D_name_get(BPy_UnaryPredicate1D *self, void *UNUSED(closure))
+{
+ return PyUnicode_FromString(Py_TYPE(self)->tp_name);
+}
+
+static PyGetSetDef BPy_UnaryPredicate1D_getseters[] = {
+ {(char *)"name", (getter)UnaryPredicate1D_name_get, (setter)NULL, (char *)UnaryPredicate1D_name_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_UnaryPredicate1D type definition ------------------------------*/
+
+PyTypeObject UnaryPredicate1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryPredicate1D", /* tp_name */
+ sizeof(BPy_UnaryPredicate1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryPredicate1D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryPredicate1D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryPredicate1D___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryPredicate1D___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 */
+ BPy_UnaryPredicate1D_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryPredicate1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h
new file mode 100644
index 00000000000..4f755f4d481
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h
@@ -0,0 +1,65 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYPREDICATE1D_H__
+#define __FREESTYLE_PYTHON_UNARYPREDICATE1D_H__
+
+#include <Python.h>
+
+#include "../stroke/Predicates1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject UnaryPredicate1D_Type;
+
+#define BPy_UnaryPredicate1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryPredicate1D_Type))
+
+/*---------------------------Python BPy_UnaryPredicate1D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ UnaryPredicate1D *up1D;
+} BPy_UnaryPredicate1D;
+
+/*---------------------------Python BPy_UnaryPredicate1D visible prototypes-----------*/
+
+int UnaryPredicate1D_Init(PyObject *module);
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYPREDICATE1D_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_ViewMap.cpp b/source/blender/freestyle/intern/python/BPy_ViewMap.cpp
new file mode 100644
index 00000000000..a5f837b0c03
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_ViewMap.cpp
@@ -0,0 +1,225 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_ViewMap.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ViewMap.h"
+
+#include "BPy_Convert.h"
+#include "BPy_BBox.h"
+#include "Interface1D/BPy_FEdge.h"
+#include "Interface1D/BPy_ViewEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int ViewMap_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready( &ViewMap_Type ) < 0)
+ return -1;
+ Py_INCREF(&ViewMap_Type);
+ PyModule_AddObject(module, "ViewMap", (PyObject *)&ViewMap_Type);
+
+ return 0;
+}
+
+/*----------------------ViewMap methods----------------------------*/
+
+PyDoc_STRVAR(ViewMap_doc,
+"Class defining the ViewMap.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.");
+
+static int ViewMap_init(BPy_ViewMap *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->vm = new ViewMap();
+ return 0;
+}
+
+static void ViewMap_dealloc(BPy_ViewMap *self)
+{
+ if (self->vm)
+ delete self->vm;
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *ViewMap_repr(BPy_ViewMap *self)
+{
+ return PyUnicode_FromFormat("ViewMap - address: %p", self->vm);
+}
+
+PyDoc_STRVAR(ViewMap_get_closest_viewedge_doc,
+".. method:: get_closest_viewedge(x, y)\n"
+"\n"
+" Gets the ViewEdge nearest to the 2D point specified as arguments.\n"
+"\n"
+" :arg x: X coordinate of a 2D point.\n"
+" :type x: float\n"
+" :arg y: Y coordinate of a 2D point.\n"
+" :type y: float\n"
+" :return: The ViewEdge nearest to the specified 2D point.\n"
+" :rtype: :class:`ViewEdge`");
+
+static PyObject *ViewMap_get_closest_viewedge(BPy_ViewMap *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"x", "y", NULL};
+ double x, y;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "dd", (char **)kwlist, &x, &y))
+ return NULL;
+ ViewEdge *ve = const_cast<ViewEdge *>(self->vm->getClosestViewEdge(x, y));
+ if (ve)
+ return BPy_ViewEdge_from_ViewEdge(*ve);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(ViewMap_get_closest_fedge_doc,
+".. method:: get_closest_fedge(x, y)\n"
+"\n"
+" Gets the FEdge nearest to the 2D point specified as arguments.\n"
+"\n"
+" :arg x: X coordinate of a 2D point.\n"
+" :type x: float\n"
+" :arg y: Y coordinate of a 2D point.\n"
+" :type y: float\n"
+" :return: The FEdge nearest to the specified 2D point.\n"
+" :rtype: :class:`FEdge`");
+
+static PyObject *ViewMap_get_closest_fedge(BPy_ViewMap *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"x", "y", NULL};
+ double x, y;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "dd", (char **)kwlist, &x, &y))
+ return NULL;
+ FEdge *fe = const_cast<FEdge *>(self->vm->getClosestFEdge(x, y));
+ if (fe)
+ return Any_BPy_FEdge_from_FEdge(*fe);
+ Py_RETURN_NONE;
+}
+
+// static ViewMap *getInstance ();
+
+static PyMethodDef BPy_ViewMap_methods[] = {
+ {"get_closest_viewedge", (PyCFunction)ViewMap_get_closest_viewedge, METH_VARARGS | METH_KEYWORDS,
+ ViewMap_get_closest_viewedge_doc},
+ {"get_closest_fedge", (PyCFunction)ViewMap_get_closest_fedge, METH_VARARGS | METH_KEYWORDS,
+ ViewMap_get_closest_fedge_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------ViewMap get/setters ----------------------------*/
+
+PyDoc_STRVAR(ViewMap_scene_bbox_doc,
+"The 3D bounding box of the scene.\n"
+"\n"
+":type: :class:`BBox`");
+
+static PyObject *ViewMap_scene_bbox_get(BPy_ViewMap *self, void *UNUSED(closure))
+{
+ return BPy_BBox_from_BBox(self->vm->getScene3dBBox());
+}
+
+static int ViewMap_scene_bbox_set(BPy_ViewMap *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_BBox_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be a BBox");
+ return -1;
+ }
+ self->vm->setScene3dBBox(*(((BPy_BBox *)value)->bb));
+ return 0;
+}
+
+static PyGetSetDef BPy_ViewMap_getseters[] = {
+ {(char *)"scene_bbox", (getter)ViewMap_scene_bbox_get, (setter)ViewMap_scene_bbox_set,
+ (char *)ViewMap_scene_bbox_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_ViewMap type definition ------------------------------*/
+
+PyTypeObject ViewMap_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewMap", /* tp_name */
+ sizeof(BPy_ViewMap), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)ViewMap_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)ViewMap_repr, /* 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 */
+ ViewMap_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ViewMap_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_ViewMap_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewMap_init, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_ViewMap.h b/source/blender/freestyle/intern/python/BPy_ViewMap.h
new file mode 100644
index 00000000000..03c6bca2e16
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_ViewMap.h
@@ -0,0 +1,65 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_ViewMap.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_VIEWMAP_H__
+#define __FREESTYLE_PYTHON_VIEWMAP_H__
+
+#include <Python.h>
+
+#include "../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject ViewMap_Type;
+
+#define BPy_ViewMap_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ViewMap_Type))
+
+/*---------------------------Python BPy_ViewMap structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ ViewMap *vm;
+} BPy_ViewMap;
+
+/*---------------------------Python BPy_ViewMap visible prototypes-----------*/
+
+int ViewMap_Init(PyObject *module);
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_VIEWMAP_H__ */
diff --git a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp
new file mode 100644
index 00000000000..a921bf5aed6
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp
@@ -0,0 +1,371 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_ViewShape.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ViewShape.h"
+
+#include "BPy_Convert.h"
+#include "Interface0D/BPy_ViewVertex.h"
+#include "Interface1D/BPy_ViewEdge.h"
+#include "BPy_SShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int ViewShape_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&ViewShape_Type) < 0)
+ return -1;
+ Py_INCREF(&ViewShape_Type);
+ PyModule_AddObject(module, "ViewShape", (PyObject *)&ViewShape_Type);
+
+ return 0;
+}
+
+/*----------------------ViewShape methods ----------------------------*/
+
+PyDoc_STRVAR(ViewShape_doc,
+"Class gathering the elements of the ViewMap (i.e., :class:`ViewVertex`\n"
+"and :class:`ViewEdge`) that are issued from the same input shape.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A ViewShape object.\n"
+" :type brother: :class:`ViewShape`\n"
+"\n"
+".. method:: __init__(sshape)\n"
+"\n"
+" Builds a ViewShape from an SShape.\n"
+"\n"
+" :arg sshape: An SShape object.\n"
+" :type sshape: :class:`SShape`");
+
+static int ViewShape_init(BPy_ViewShape *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"sshape", NULL};
+ PyObject *obj = 0;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &ViewShape_Type, &obj)) {
+ if (!obj) {
+ self->vs = new ViewShape();
+ self->py_ss = NULL;
+ }
+ else {
+ self->vs = new ViewShape(*(((BPy_ViewShape *)obj)->vs));
+ self->py_ss = ((BPy_ViewShape *)obj)->py_ss;
+ }
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist_2, &SShape_Type, &obj))
+ {
+ BPy_SShape *py_ss = (BPy_SShape *)obj;
+ self->vs = new ViewShape(py_ss->ss);
+ self->py_ss = (!py_ss->borrowed) ? py_ss : NULL;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->borrowed = 0;
+ Py_XINCREF(self->py_ss);
+ return 0;
+}
+
+static void ViewShape_dealloc(BPy_ViewShape *self)
+{
+ if (self->py_ss) {
+ self->vs->setSShape((SShape *)NULL);
+ Py_DECREF(self->py_ss);
+ }
+ if (self->vs && !self->borrowed)
+ delete self->vs;
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *ViewShape_repr(BPy_ViewShape *self)
+{
+ return PyUnicode_FromFormat("ViewShape - address: %p", self->vs);
+}
+
+PyDoc_STRVAR(ViewShape_add_edge_doc,
+".. method:: add_edge(edge)\n"
+"\n"
+" Adds a ViewEdge to the list of ViewEdge objects.\n"
+"\n"
+" :arg edge: A ViewEdge object.\n"
+" :type edge: :class:`ViewEdge`\n");
+
+static PyObject *ViewShape_add_edge(BPy_ViewShape *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"edge", NULL};
+ PyObject *py_ve = 0;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &ViewEdge_Type, &py_ve))
+ return NULL;
+ self->vs->AddEdge(((BPy_ViewEdge *)py_ve)->ve);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(ViewShape_add_vertex_doc,
+".. method:: add_vertex(vertex)\n"
+"\n"
+" Adds a ViewVertex to the list of the ViewVertex objects.\n"
+"\n"
+" :arg vertex: A ViewVertex object.\n"
+" :type vertex: :class:`ViewVertex`");
+
+static PyObject *ViewShape_add_vertex(BPy_ViewShape *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"vertex", NULL};
+ PyObject *py_vv = 0;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &ViewVertex_Type, &py_vv))
+ return NULL;
+ self->vs->AddVertex(((BPy_ViewVertex *)py_vv)->vv);
+ Py_RETURN_NONE;
+}
+
+// virtual ViewShape *duplicate()
+
+static PyMethodDef BPy_ViewShape_methods[] = {
+ {"add_edge", (PyCFunction)ViewShape_add_edge, METH_VARARGS | METH_KEYWORDS, ViewShape_add_edge_doc},
+ {"add_vertex", (PyCFunction)ViewShape_add_vertex, METH_VARARGS | METH_KEYWORDS, ViewShape_add_vertex_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------ViewShape get/setters ----------------------------*/
+
+PyDoc_STRVAR(ViewShape_sshape_doc,
+"The SShape on top of which this ViewShape is built.\n"
+"\n"
+":type: :class:`SShape`");
+
+static PyObject *ViewShape_sshape_get(BPy_ViewShape *self, void *UNUSED(closure))
+{
+ SShape *ss = self->vs->sshape();
+ if (!ss)
+ Py_RETURN_NONE;
+ return BPy_SShape_from_SShape(*ss);
+}
+
+static int ViewShape_sshape_set(BPy_ViewShape *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_SShape_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an SShape");
+ return -1;
+ }
+ BPy_SShape *py_ss = (BPy_SShape *)value;
+ self->vs->setSShape(py_ss->ss);
+ if (self->py_ss)
+ Py_DECREF(self->py_ss);
+ if (!py_ss->borrowed) {
+ self->py_ss = py_ss;
+ Py_INCREF(self->py_ss);
+ }
+ return 0;
+}
+
+PyDoc_STRVAR(ViewShape_vertices_doc,
+"The list of ViewVertex objects contained in this ViewShape.\n"
+"\n"
+":type: List of :class:`ViewVertex` objects");
+
+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;
+ for (it = vertices.begin(); it != vertices.end(); it++) {
+ PyList_Append( py_vertices, 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;
+
+ if (!PyList_Check(value)) {
+ 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);
+ if (BPy_ViewVertex_Check(item)) {
+ v.push_back(((BPy_ViewVertex *)item)->vv);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "value must be a list of ViewVertex objects");
+ return -1;
+ }
+ }
+ self->vs->setVertices(v);
+ return 0;
+}
+
+PyDoc_STRVAR(ViewShape_edges_doc,
+"The list of ViewEdge objects contained in this ViewShape.\n"
+"\n"
+":type: List of :class:`ViewEdge` objects");
+
+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;
+
+ for (it = edges.begin(); it != edges.end(); it++) {
+ PyList_Append(py_edges, 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;
+
+ if (!PyList_Check(value)) {
+ 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);
+ if (BPy_ViewEdge_Check(item)) {
+ v.push_back(((BPy_ViewEdge *)item)->ve);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "argument must be list of ViewEdge objects");
+ return -1;
+ }
+ }
+ self->vs->setEdges(v);
+ return 0;
+}
+
+PyDoc_STRVAR(ViewShape_name_doc,
+"The name of the ViewShape.\n"
+"\n"
+":type: str");
+
+static PyObject *ViewShape_name_get(BPy_ViewShape *self, void *UNUSED(closure))
+{
+ return PyUnicode_FromString(self->vs->getName().c_str());
+}
+
+PyDoc_STRVAR(ViewShape_id_doc,
+"The Id of this ViewShape.\n"
+"\n"
+":type: :class:`Id`");
+
+static PyObject *ViewShape_id_get(BPy_ViewShape *self, void *UNUSED(closure))
+{
+ Id id(self->vs->getId());
+ return BPy_Id_from_Id(id); // return a copy
+}
+
+static PyGetSetDef BPy_ViewShape_getseters[] = {
+ {(char *)"sshape", (getter)ViewShape_sshape_get, (setter)ViewShape_sshape_set, (char *)ViewShape_sshape_doc, NULL},
+ {(char *)"vertices", (getter)ViewShape_vertices_get, (setter)ViewShape_vertices_set,
+ (char *)ViewShape_vertices_doc, NULL},
+ {(char *)"edges", (getter)ViewShape_edges_get, (setter)ViewShape_edges_set, (char *)ViewShape_edges_doc, NULL},
+ {(char *)"name", (getter)ViewShape_name_get, (setter)NULL, (char *)ViewShape_name_doc, NULL},
+ {(char *)"id", (getter)ViewShape_id_get, (setter)NULL, (char *)ViewShape_id_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_ViewShape type definition ------------------------------*/
+
+PyTypeObject ViewShape_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewShape", /* tp_name */
+ sizeof(BPy_ViewShape), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)ViewShape_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)ViewShape_repr, /* 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 */
+ ViewShape_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ViewShape_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_ViewShape_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewShape_init, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_ViewShape.h b/source/blender/freestyle/intern/python/BPy_ViewShape.h
new file mode 100644
index 00000000000..e18f7cb23dd
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_ViewShape.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BPy_ViewShape.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_VIEWSHAPE_H__
+#define __FREESTYLE_PYTHON_VIEWSHAPE_H__
+
+#include <Python.h>
+
+#include "../view_map/ViewMap.h"
+
+#include "BPy_SShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject ViewShape_Type;
+
+#define BPy_ViewShape_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ViewShape_Type))
+
+/*---------------------------Python BPy_ViewShape structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ ViewShape *vs;
+ int borrowed; /* non-zero if *vs a borrowed object */
+ BPy_SShape *py_ss;
+} BPy_ViewShape;
+
+/*---------------------------Python BPy_ViewShape visible prototypes-----------*/
+
+int ViewShape_Init(PyObject *module);
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_VIEWSHAPE_H__ */
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp
new file mode 100644
index 00000000000..9fcc8d4a691
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_FalseBP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FalseBP1D___doc__[] =
+"Class hierarchy: :class:`BinaryPredicate1D` > :class:`FalseBP1D`\n"
+"\n"
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Always returns false.\n"
+"\n"
+" :arg inter1: The first Interface1D object.\n"
+" :type inter1: :class:`Interface1D`\n"
+" :arg inter2: The second Interface1D object.\n"
+" :type inter2: :class:`Interface1D`\n"
+" :return: False.\n"
+" :rtype: bool\n";
+
+static int FalseBP1D___init__(BPy_FalseBP1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_bp1D.bp1D = new Predicates1D::FalseBP1D();
+ return 0;
+}
+
+/*-----------------------BPy_FalseBP1D type definition ------------------------------*/
+PyTypeObject FalseBP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FalseBP1D", /* tp_name */
+ sizeof(BPy_FalseBP1D), /* 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 */
+ FalseBP1D___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 */
+ &BinaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FalseBP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.h
new file mode 100644
index 00000000000..952266091b8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_FALSEBP1D_H__
+#define __FREESTYLE_PYTHON_FALSEBP1D_H__
+
+#include "../BPy_BinaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FalseBP1D_Type;
+
+#define BPy_FalseBP1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&FalseBP1D_Type))
+
+/*---------------------------Python BPy_FalseBP1D structure definition----------*/
+typedef struct {
+ BPy_BinaryPredicate1D py_bp1D;
+} BPy_FalseBP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_FALSEBP1D_H__ */
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp
new file mode 100644
index 00000000000..6dd8919f402
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp
@@ -0,0 +1,114 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_Length2DBP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Length2DBP1D___doc__[] =
+"Class hierarchy: :class:`BinaryPredicate1D` > :class:`Length2DBP1D`\n"
+"\n"
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Returns true if the 2D length of inter1 is less than the 2D length\n"
+" of inter2.\n"
+"\n"
+" :arg inter1: The first Interface1D object.\n"
+" :type inter1: :class:`Interface1D`\n"
+" :arg inter2: The second Interface1D object.\n"
+" :type inter2: :class:`Interface1D`\n"
+" :return: True or false.\n"
+" :rtype: bool\n";
+
+static int Length2DBP1D___init__(BPy_Length2DBP1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_bp1D.bp1D = new Predicates1D::Length2DBP1D();
+ return 0;
+}
+
+/*-----------------------BPy_Length2DBP1D type definition ------------------------------*/
+
+PyTypeObject Length2DBP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Length2DBP1D", /* tp_name */
+ sizeof(BPy_Length2DBP1D), /* 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 */
+ Length2DBP1D___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 */
+ &BinaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Length2DBP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.h
new file mode 100644
index 00000000000..69c7706db48
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_LENGTH2DBP1D_H__
+#define __FREESTYLE_PYTHON_LENGTH2DBP1D_H__
+
+#include "../BPy_BinaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Length2DBP1D_Type;
+
+#define BPy_Length2DBP1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Length2DBP1D_Type))
+
+/*---------------------------Python BPy_Length2DBP1D structure definition----------*/
+typedef struct {
+ BPy_BinaryPredicate1D py_bp1D;
+} BPy_Length2DBP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_LENGTH2DBP1D_H__ */
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp
new file mode 100644
index 00000000000..5d991d50ae1
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_SameShapeIdBP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char SameShapeIdBP1D___doc__[] =
+"Class hierarchy: :class:`BinaryPredicate1D` > :class:`SameShapeIdBP1D`\n"
+"\n"
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Returns true if inter1 and inter2 belong to the same shape.\n"
+"\n"
+" :arg inter1: The first Interface1D object.\n"
+" :type inter1: :class:`Interface1D`\n"
+" :arg inter2: The second Interface1D object.\n"
+" :type inter2: :class:`Interface1D`\n"
+" :return: True or false.\n"
+" :rtype: bool\n";
+
+static int SameShapeIdBP1D___init__(BPy_SameShapeIdBP1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_bp1D.bp1D = new Predicates1D::SameShapeIdBP1D();
+ return 0;
+}
+
+/*-----------------------BPy_SameShapeIdBP1D type definition ------------------------------*/
+
+PyTypeObject SameShapeIdBP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SameShapeIdBP1D", /* tp_name */
+ sizeof(BPy_SameShapeIdBP1D), /* 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 */
+ SameShapeIdBP1D___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 */
+ &BinaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SameShapeIdBP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.h
new file mode 100644
index 00000000000..0a4b6ebb556
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_SAMESHAPEIDBP1D_H__
+#define __FREESTYLE_PYTHON_SAMESHAPEIDBP1D_H__
+
+#include "../BPy_BinaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SameShapeIdBP1D_Type;
+
+#define BPy_SameShapeIdBP1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&SameShapeIdBP1D_Type))
+
+/*---------------------------Python BPy_SameShapeIdBP1D structure definition----------*/
+typedef struct {
+ BPy_BinaryPredicate1D py_bp1D;
+} BPy_SameShapeIdBP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_SAMESHAPEIDBP1D_H__ */
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp
new file mode 100644
index 00000000000..9063e407056
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_TrueBP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TrueBP1D___doc__[] =
+"Class hierarchy: :class:`BinaryPredicate1D` > :class:`TrueBP1D`\n"
+"\n"
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Always returns true.\n"
+"\n"
+" :arg inter1: The first Interface1D object.\n"
+" :type inter1: :class:`Interface1D`\n"
+" :arg inter2: The second Interface1D object.\n"
+" :type inter2: :class:`Interface1D`\n"
+" :return: True.\n"
+" :rtype: bool\n";
+
+static int TrueBP1D___init__(BPy_TrueBP1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_bp1D.bp1D = new Predicates1D::TrueBP1D();
+ return 0;
+}
+
+/*-----------------------BPy_TrueBP1D type definition ------------------------------*/
+
+PyTypeObject TrueBP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TrueBP1D", /* tp_name */
+ sizeof(BPy_TrueBP1D), /* 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 */
+ TrueBP1D___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 */
+ &BinaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TrueBP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.h
new file mode 100644
index 00000000000..cf568d7b33e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_TRUEBP1D_H__
+#define __FREESTYLE_PYTHON_TRUEBP1D_H__
+
+#include "../BPy_BinaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TrueBP1D_Type;
+
+#define BPy_TrueBP1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&TrueBP1D_Type))
+
+/*---------------------------Python BPy_TrueBP1D structure definition----------*/
+typedef struct {
+ BPy_BinaryPredicate1D py_bp1D;
+} BPy_TrueBP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_TRUEBP1D_H__ */
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp
new file mode 100644
index 00000000000..a3ebf88b58a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ViewMapGradientNormBP1D.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+//ViewMapGradientNormBP1D(int level, IntegrationType iType=MEAN, float sampling=2.0)
+
+static char ViewMapGradientNormBP1D___doc__[] =
+"Class hierarchy: :class:`BinaryPredicate1D` > :class:`ViewMapGradientNormBP1D`\n"
+"\n"
+".. method:: __init__(level, integration_type=IntegrationType.MEAN, sampling=2.0)\n"
+"\n"
+" Builds a ViewMapGradientNormBP1D object.\n"
+"\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+" :arg sampling: The resolution used to sample the chain:\n"
+" GetViewMapGradientNormF0D is evaluated at each sample point and\n"
+" the result is obtained by combining the resulting values into a\n"
+" single one, following the method specified by integration_type.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Returns true if the evaluation of the Gradient norm Function is\n"
+" higher for inter1 than for inter2.\n"
+"\n"
+" :arg inter1: The first Interface1D object.\n"
+" :type inter1: :class:`Interface1D`\n"
+" :arg inter2: The second Interface1D object.\n"
+" :type inter2: :class:`Interface1D`\n"
+" :return: True or false.\n"
+" :rtype: bool\n";
+
+static int ViewMapGradientNormBP1D___init__(BPy_ViewMapGradientNormBP1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"level", "integration_type", "sampling", NULL};
+ PyObject *obj = 0;
+ int i;
+ float f = 2.0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|O!f", (char **)kwlist, &i, &IntegrationType_Type, &obj, &f))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_bp1D.bp1D = new Predicates1D::ViewMapGradientNormBP1D(i, t, f);
+ return 0;
+}
+
+/*-----------------------BPy_ViewMapGradientNormBP1D type definition ------------------------------*/
+
+PyTypeObject ViewMapGradientNormBP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewMapGradientNormBP1D", /* tp_name */
+ sizeof(BPy_ViewMapGradientNormBP1D), /* 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 */
+ ViewMapGradientNormBP1D___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 */
+ &BinaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewMapGradientNormBP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h
new file mode 100644
index 00000000000..cb5e59f146d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_VIEWMAPGRADIENTNORMBP1D_H__
+#define __FREESTYLE_PYTHON_VIEWMAPGRADIENTNORMBP1D_H__
+
+#include "../BPy_BinaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ViewMapGradientNormBP1D_Type;
+
+#define BPy_ViewMapGradientNormBP1D_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&ViewMapGradientNormBP1D_Type))
+
+/*---------------------------Python BPy_ViewMapGradientNormBP1D structure definition----------*/
+typedef struct {
+ BPy_BinaryPredicate1D py_bp1D;
+} BPy_ViewMapGradientNormBP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_VIEWMAPGRADIENTNORMBP1D_H__ */
diff --git a/source/blender/freestyle/intern/python/Director.cpp b/source/blender/freestyle/intern/python/Director.cpp
new file mode 100644
index 00000000000..04442ae0e37
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Director.cpp
@@ -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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Director.cpp
+ * \ingroup freestyle
+ */
+
+#include "Director.h"
+
+#include "BPy_Convert.h"
+
+#include "BPy_BinaryPredicate0D.h"
+#include "BPy_BinaryPredicate1D.h"
+#include "BPy_FrsMaterial.h"
+#include "BPy_Id.h"
+#include "BPy_UnaryFunction0D.h"
+#include "BPy_UnaryFunction1D.h"
+#include "BPy_UnaryPredicate0D.h"
+#include "BPy_UnaryPredicate1D.h"
+#include "BPy_StrokeShader.h"
+#include "Iterator/BPy_ChainingIterator.h"
+#include "Iterator/BPy_Interface0DIterator.h"
+#include "Interface1D/BPy_Stroke.h"
+#include "Interface1D/BPy_ViewEdge.h"
+#include "BPy_ViewShape.h"
+
+#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DFloat.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DId.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DMaterial.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DVec2f.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DVec3f.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DViewShape.h"
+
+#include "UnaryFunction1D/BPy_UnaryFunction1DDouble.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DFloat.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVec2f.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVec3f.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h"
+
+// BinaryPredicate0D: __call__
+int Director_BPy_BinaryPredicate0D___call__(BinaryPredicate0D *bp0D, Interface0D& i1, Interface0D& i2)
+{
+ if (!bp0D->py_bp0D) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_bp0D) not initialized");
+ return -1;
+ }
+ PyObject *arg1 = Any_BPy_Interface0D_from_Interface0D(i1);
+ PyObject *arg2 = Any_BPy_Interface0D_from_Interface0D(i2);
+ if (!arg1 || !arg2) {
+ Py_XDECREF(arg1);
+ Py_XDECREF(arg2);
+ return -1;
+ }
+ PyObject *result = PyObject_CallMethod(bp0D->py_bp0D, (char *)"__call__", (char *)"OO", arg1, arg2);
+ Py_DECREF(arg1);
+ Py_DECREF(arg2);
+ if (!result)
+ return -1;
+ int ret = PyObject_IsTrue(result);
+ Py_DECREF(result);
+ if (ret < 0)
+ return -1;
+ bp0D->result = ret;
+ return 0;
+}
+
+// BinaryPredicate1D: __call__
+int Director_BPy_BinaryPredicate1D___call__(BinaryPredicate1D *bp1D, Interface1D& i1, Interface1D& i2)
+{
+ if (!bp1D->py_bp1D) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_bp1D) not initialized");
+ return -1;
+ }
+ PyObject *arg1 = Any_BPy_Interface1D_from_Interface1D(i1);
+ PyObject *arg2 = Any_BPy_Interface1D_from_Interface1D(i2);
+ if (!arg1 || !arg2) {
+ Py_XDECREF(arg1);
+ Py_XDECREF(arg2);
+ return -1;
+ }
+ PyObject *result = PyObject_CallMethod(bp1D->py_bp1D, (char *)"__call__", (char *)"OO", arg1, arg2);
+ Py_DECREF(arg1);
+ Py_DECREF(arg2);
+ if (!result)
+ return -1;
+ int ret = PyObject_IsTrue(result);
+ Py_DECREF(result);
+ if (ret < 0)
+ return -1;
+ bp1D->result = ret;
+ return 0;
+}
+
+// UnaryPredicate0D: __call__
+int Director_BPy_UnaryPredicate0D___call__(UnaryPredicate0D *up0D, Interface0DIterator& if0D_it)
+{
+ if (!up0D->py_up0D) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_up0D) not initialized");
+ return -1;
+ }
+ PyObject *arg = BPy_Interface0DIterator_from_Interface0DIterator(if0D_it, 0);
+ if (!arg)
+ return -1;
+ PyObject *result = PyObject_CallMethod(up0D->py_up0D, (char *)"__call__", (char *)"O", arg);
+ Py_DECREF(arg);
+ if (!result)
+ return -1;
+ int ret = PyObject_IsTrue(result);
+ Py_DECREF(result);
+ if (ret < 0)
+ return -1;
+ up0D->result = ret;
+ return 0;
+}
+
+// UnaryPredicate1D: __call__
+int Director_BPy_UnaryPredicate1D___call__(UnaryPredicate1D *up1D, Interface1D& if1D)
+{
+ if (!up1D->py_up1D) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_up1D) not initialized");
+ return -1;
+ }
+ PyObject *arg = Any_BPy_Interface1D_from_Interface1D(if1D);
+ if (!arg)
+ return -1;
+ PyObject *result = PyObject_CallMethod(up1D->py_up1D, (char *)"__call__", (char *)"O", arg);
+ Py_DECREF(arg);
+ if (!result)
+ return -1;
+ int ret = PyObject_IsTrue(result);
+ Py_DECREF(result);
+ if (ret < 0)
+ return -1;
+ up1D->result = ret;
+ return 0;
+}
+
+// StrokeShader: shade
+int Director_BPy_StrokeShader_shade(StrokeShader *ss, Stroke& s)
+{
+ if (!ss->py_ss) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_ss) not initialized");
+ return -1;
+ }
+ PyObject *arg = BPy_Stroke_from_Stroke(s);
+ if (!arg)
+ return -1;
+ PyObject *result = PyObject_CallMethod(ss->py_ss, (char *)"shade", (char *)"O", arg);
+ Py_DECREF(arg);
+ if (!result)
+ return -1;
+ Py_DECREF(result);
+ return 0;
+}
+
+// ChainingIterator: init, traverse
+int Director_BPy_ChainingIterator_init(ChainingIterator *c_it)
+{
+ if (!c_it->py_c_it) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_c_it) not initialized");
+ return -1;
+ }
+ PyObject *result = PyObject_CallMethod(c_it->py_c_it, (char *)"init", NULL);
+ if (!result)
+ return -1;
+ Py_DECREF(result);
+ return 0;
+}
+
+int Director_BPy_ChainingIterator_traverse(ChainingIterator *c_it, AdjacencyIterator& a_it)
+{
+ if (!c_it->py_c_it) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_c_it) not initialized");
+ return -1;
+ }
+ PyObject *arg = BPy_AdjacencyIterator_from_AdjacencyIterator(a_it);
+ if (!arg)
+ return -1;
+ PyObject *result = PyObject_CallMethod(c_it->py_c_it, (char *)"traverse", (char *)"O", arg);
+ Py_DECREF(arg);
+ if (!result)
+ return -1;
+ if (BPy_ViewEdge_Check(result)) {
+ c_it->result = ((BPy_ViewEdge *)result)->ve;
+ }
+ else if (result == Py_None) {
+ c_it->result = NULL;
+ }
+ else {
+ PyErr_SetString(PyExc_RuntimeError, "traverse method returned a wrong value");
+ Py_DECREF(result);
+ return -1;
+ }
+ Py_DECREF(result);
+ return 0;
+}
+
+// BPy_UnaryFunction{0D,1D}: __call__
+int Director_BPy_UnaryFunction0D___call__(void *uf0D, PyObject *obj, Interface0DIterator& if0D_it)
+{
+ if (!obj) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_uf0D) not initialized");
+ return -1;
+ }
+ PyObject *arg = BPy_Interface0DIterator_from_Interface0DIterator(if0D_it, 0);
+ if (!arg)
+ return -1;
+ PyObject *result = PyObject_CallMethod(obj, (char *)"__call__", (char *)"O", arg);
+ Py_DECREF(arg);
+ if (!result)
+ return -1;
+ if (BPy_UnaryFunction0DDouble_Check(obj)) {
+ ((UnaryFunction0D<double> *)uf0D)->result = PyFloat_AsDouble(result);
+ }
+ else if (BPy_UnaryFunction0DEdgeNature_Check(obj)) {
+ ((UnaryFunction0D<Nature::EdgeNature> *)uf0D)->result = EdgeNature_from_BPy_Nature(result);
+ }
+ else if (BPy_UnaryFunction0DFloat_Check(obj)) {
+ ((UnaryFunction0D<float> *)uf0D)->result = PyFloat_AsDouble(result);
+ }
+ else if (BPy_UnaryFunction0DId_Check(obj)) {
+ ((UnaryFunction0D<Id> *)uf0D)->result = *(((BPy_Id *)result)->id);
+ }
+ else if (BPy_UnaryFunction0DMaterial_Check(obj)) {
+ ((UnaryFunction0D<FrsMaterial> *)uf0D)->result = *(((BPy_FrsMaterial *)result)->m);
+ }
+ else if (BPy_UnaryFunction0DUnsigned_Check(obj)) {
+ ((UnaryFunction0D<unsigned> *)uf0D)->result = PyLong_AsLong(result);
+ }
+ else if (BPy_UnaryFunction0DVec2f_Check(obj)) {
+ Vec2f *v = Vec2f_ptr_from_Vector(result);
+ ((UnaryFunction0D<Vec2f> *)uf0D)->result = *v;
+ delete v;
+ }
+ else if (BPy_UnaryFunction0DVec3f_Check(obj)) {
+ Vec3f *v = Vec3f_ptr_from_Vector(result);
+ ((UnaryFunction0D<Vec3f> *)uf0D)->result = *v;
+ delete v;
+ }
+ else if (BPy_UnaryFunction0DVectorViewShape_Check(obj)) {
+ vector<ViewShape*> vec;
+ for (int i = 0; i < PyList_Size(result); i++) {
+ ViewShape *b = ((BPy_ViewShape *)PyList_GetItem(result, i))->vs;
+ vec.push_back(b);
+ }
+ ((UnaryFunction0D< vector<ViewShape*> > *)uf0D)->result = vec;
+ }
+ else if (BPy_UnaryFunction0DViewShape_Check(obj)) {
+ ((UnaryFunction0D<ViewShape*> *)uf0D)->result = ((BPy_ViewShape *)result)->vs;
+ }
+ Py_DECREF(result);
+ return 0;
+}
+
+int Director_BPy_UnaryFunction1D___call__(void *uf1D, PyObject *obj, Interface1D& if1D)
+{
+ if (!obj) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_uf1D) not initialized");
+ return -1;
+ }
+ PyObject *arg = Any_BPy_Interface1D_from_Interface1D(if1D);
+ if (!arg)
+ return -1;
+ PyObject *result = PyObject_CallMethod(obj, (char *)"__call__", (char *)"O", arg);
+ Py_DECREF(arg);
+ if (!result)
+ return -1;
+ if (BPy_UnaryFunction1DDouble_Check(obj)) {
+ ((UnaryFunction1D<double> *)uf1D)->result = PyFloat_AsDouble(result);
+ }
+ else if (BPy_UnaryFunction1DEdgeNature_Check(obj)) {
+ ((UnaryFunction1D<Nature::EdgeNature> *)uf1D)->result = EdgeNature_from_BPy_Nature(result);
+ }
+ else if (BPy_UnaryFunction1DFloat_Check(obj)) {
+ ((UnaryFunction1D<float> *)uf1D)->result = PyFloat_AsDouble(result);
+ }
+ else if (BPy_UnaryFunction1DUnsigned_Check(obj)) {
+ ((UnaryFunction1D<unsigned> *)uf1D)->result = PyLong_AsLong(result);
+ }
+ else if (BPy_UnaryFunction1DVec2f_Check(obj)) {
+ Vec2f *v = Vec2f_ptr_from_Vector(result);
+ ((UnaryFunction1D<Vec2f> *)uf1D)->result = *v;
+ delete v;
+ }
+ else if (BPy_UnaryFunction1DVec3f_Check(obj)) {
+ Vec3f *v = Vec3f_ptr_from_Vector(result);
+ ((UnaryFunction1D<Vec3f> *)uf1D)->result = *v;
+ delete v;
+ }
+ else if (BPy_UnaryFunction1DVectorViewShape_Check(obj)) {
+ vector<ViewShape*> vec;
+ for (int i = 1; i < PyList_Size(result); i++) {
+ ViewShape *b = ((BPy_ViewShape *)PyList_GetItem(result, i))->vs;
+ vec.push_back(b);
+ }
+ ((UnaryFunction1D< vector<ViewShape*> > *)uf1D)->result = vec;
+ }
+ Py_DECREF(result);
+ return 0;
+}
diff --git a/source/blender/freestyle/intern/python/Director.h b/source/blender/freestyle/intern/python/Director.h
new file mode 100644
index 00000000000..b156f6aa8d0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Director.h
@@ -0,0 +1,80 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Director.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_DIRECTOR_H__
+#define __FREESTYLE_PYTHON_DIRECTOR_H__
+
+class UnaryPredicate0D;
+class UnaryPredicate1D;
+class BinaryPredicate0D;
+class BinaryPredicate1D;
+class ChainingIterator;
+class AdjacencyIterator;
+class Interface0D;
+class Interface1D;
+class Interface0DIterator;
+class Stroke;
+class StrokeShader;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <Python.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+// BinaryPredicate0D: __call__
+int Director_BPy_BinaryPredicate0D___call__(BinaryPredicate0D *bp0D, Interface0D& i1, Interface0D& i2);
+
+// BinaryPredicate1D: __call__
+int Director_BPy_BinaryPredicate1D___call__(BinaryPredicate1D *bp1D, Interface1D& i1, Interface1D& i2);
+
+// UnaryFunction{0D,1D}: __call__
+int Director_BPy_UnaryFunction0D___call__(void *uf0D, PyObject *obj, Interface0DIterator& if0D_it);
+int Director_BPy_UnaryFunction1D___call__(void *uf1D, PyObject *obj, Interface1D& if1D);
+
+// UnaryPredicate0D: __call__
+int Director_BPy_UnaryPredicate0D___call__(UnaryPredicate0D *up0D, Interface0DIterator& if0D_it);
+
+// UnaryPredicate1D: __call__
+int Director_BPy_UnaryPredicate1D___call__(UnaryPredicate1D *up1D, Interface1D& if1D);
+
+// StrokeShader: shade
+int Director_BPy_StrokeShader_shade(StrokeShader *ss, Stroke& s);
+
+// ChainingIterator: init, traverse
+int Director_BPy_ChainingIterator_init(ChainingIterator *c_it);
+int Director_BPy_ChainingIterator_traverse(ChainingIterator *c_it, AdjacencyIterator& a_it);
+
+#endif // __FREESTYLE_PYTHON_DIRECTOR_H__
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
new file mode 100644
index 00000000000..4365aa123e9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
@@ -0,0 +1,278 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_CurvePoint.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface0D/BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*----------------------CurvePoint methods----------------------------*/
+
+PyDoc_STRVAR(CurvePoint_doc,
+"Class hierarchy: :class:`Interface0D` > :class:`CurvePoint`\n"
+"\n"
+"Class to represent a point of a curve. A CurvePoint can be any point\n"
+"of a 1D curve (it doesn't have to be a vertex of the curve). Any\n"
+":class:`Interface1D` is built upon ViewEdges, themselves built upon\n"
+"FEdges. Therefore, a curve is basically a polyline made of a list of\n"
+":class:`SVertex` objects. Thus, a CurvePoint is built by linearly\n"
+"interpolating two :class:`SVertex` instances. CurvePoint can be used\n"
+"as virtual points while querying 0D information along a curve at a\n"
+"given resolution.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Defult constructor.\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A CurvePoint object.\n"
+" :type brother: :class:`CurvePoint`\n"
+"\n"
+".. method:: __init__(first_vertex, second_vertex, t2d)\n"
+"\n"
+" Builds a CurvePoint from two SVertex objects and an interpolation parameter.\n"
+"\n"
+" :arg first_vertex: The first SVertex.\n"
+" :type first_vertex: :class:`SVertex`\n"
+" :arg second_vertex: The second SVertex.\n"
+" :type second_vertex: :class:`SVertex`\n"
+" :arg t2d: A 2D interpolation parameter used to linearly interpolate\n"
+" first_vertex and second_vertex.\n"
+" :type t2d: float\n"
+"\n"
+".. method:: __init__(first_point, second_point, t2d)\n"
+"\n"
+" Builds a CurvePoint from two CurvePoint objects and an interpolation\n"
+" parameter.\n"
+"\n"
+" :arg first_point: The first CurvePoint.\n"
+" :type first_point: :class:`CurvePoint`\n"
+" :arg second_point: The second CurvePoint.\n"
+" :type second_point: :class:`CurvePoint`\n"
+" :arg t2d: The 2D interpolation parameter used to linearly interpolate\n"
+" first_point and second_point.\n"
+" :type t2d: float");
+
+static int CurvePoint_init(BPy_CurvePoint *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"first_vertex", "second_vertex", "t2d", NULL};
+ static const char *kwlist_3[] = {"first_point", "second_point", "t2d", NULL};
+ PyObject *obj1 = 0, *obj2 = 0;
+ float t2d;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &CurvePoint_Type, &obj1)) {
+ if (!obj1)
+ self->cp = new CurvePoint();
+ else
+ self->cp = new CurvePoint(*(((BPy_CurvePoint *)obj1)->cp));
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!O!f", (char **)kwlist_2,
+ &SVertex_Type, &obj1, &SVertex_Type, &obj2, &t2d))
+ {
+ self->cp = new CurvePoint(((BPy_SVertex *)obj1)->sv, ((BPy_SVertex *)obj2)->sv, t2d);
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!O!f", (char **)kwlist_3,
+ &CurvePoint_Type, &obj1, &CurvePoint_Type, &obj2, &t2d))
+ {
+ CurvePoint *cp1 = ((BPy_CurvePoint *)obj1)->cp;
+ CurvePoint *cp2 = ((BPy_CurvePoint *)obj2)->cp;
+ if (!cp1 || cp1->A() == 0 || cp1->B() == 0) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 is an invalid CurvePoint object");
+ return -1;
+ }
+ if (!cp2 || cp2->A() == 0 || cp2->B() == 0) {
+ PyErr_SetString(PyExc_TypeError, "argument 2 is an invalid CurvePoint object");
+ return -1;
+ }
+ self->cp = new CurvePoint(cp1, cp2, t2d);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->py_if0D.if0D = self->cp;
+ self->py_if0D.borrowed = 0;
+ return 0;
+}
+
+///bool operator== (const CurvePoint &b)
+
+/*----------------------CurvePoint get/setters ----------------------------*/
+
+PyDoc_STRVAR(CurvePoint_first_svertex_doc,
+"The first SVertex upon which the CurvePoint is built.\n"
+"\n"
+":type: int");
+
+static PyObject *CurvePoint_first_svertex_get(BPy_CurvePoint *self, void *UNUSED(closure))
+{
+ SVertex *A = self->cp->A();
+ if (A)
+ return BPy_SVertex_from_SVertex(*A);
+ Py_RETURN_NONE;
+}
+
+static int CurvePoint_first_svertex_set(BPy_CurvePoint *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_SVertex_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
+ return -1;
+ }
+ self->cp->setA(((BPy_SVertex *)value)->sv);
+ return 0;
+}
+
+PyDoc_STRVAR(CurvePoint_second_svertex_doc,
+"The second SVertex upon which the CurvePoint is built.\n"
+"\n"
+":type: int");
+
+static PyObject *CurvePoint_second_svertex_get(BPy_CurvePoint *self, void *UNUSED(closure))
+{
+ SVertex *B = self->cp->B();
+ if (B)
+ return BPy_SVertex_from_SVertex(*B);
+ Py_RETURN_NONE;
+}
+
+static int CurvePoint_second_svertex_set(BPy_CurvePoint *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_SVertex_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
+ return -1;
+ }
+ self->cp->setB(((BPy_SVertex *)value)->sv);
+ return 0;
+}
+
+PyDoc_STRVAR(CurvePoint_t2d_doc,
+"The 2D interpolation parameter.\n"
+"\n"
+":type: float");
+
+static PyObject *CurvePoint_t2d_get(BPy_CurvePoint *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->cp->t2d());
+}
+
+static int CurvePoint_t2d_set(BPy_CurvePoint *self, PyObject *value, void *UNUSED(closure))
+{
+ float scalar;
+ if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError, "value must be a number");
+ return -1;
+ }
+ self->cp->setT2d(scalar);
+ return 0;
+}
+
+PyDoc_STRVAR(CurvePoint_curvature_fredo_doc,
+"The angle (Fredo's curvature) in radians.\n"
+"\n"
+":type: float");
+
+static PyObject *CurvePoint_curvature_fredo_get(BPy_CurvePoint *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->cp->curvatureFredo());
+}
+
+// todo - CurvePoint.directionFredo()
+
+static PyGetSetDef BPy_CurvePoint_getseters[] = {
+ {(char *)"first_svertex", (getter)CurvePoint_first_svertex_get, (setter)CurvePoint_first_svertex_set,
+ (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 *)"t2d", (getter)CurvePoint_t2d_get, (setter)CurvePoint_t2d_set, (char *)CurvePoint_t2d_doc, NULL},
+ {(char *)"curvature_fredo", (getter)CurvePoint_curvature_fredo_get, (setter)NULL,
+ (char *)CurvePoint_curvature_fredo_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_CurvePoint type definition ------------------------------*/
+PyTypeObject CurvePoint_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "CurvePoint", /* tp_name */
+ sizeof(BPy_CurvePoint), /* 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 */
+ CurvePoint_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 */
+ BPy_CurvePoint_getseters, /* tp_getset */
+ &Interface0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)CurvePoint_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h
new file mode 100644
index 00000000000..3bd39fc0162
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_CURVEPOINT_H__
+#define __FREESTYLE_PYTHON_CURVEPOINT_H__
+
+#include "../BPy_Interface0D.h"
+#include "../../stroke/Curve.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject CurvePoint_Type;
+
+#define BPy_CurvePoint_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&CurvePoint_Type))
+
+/*---------------------------Python BPy_CurvePoint structure definition----------*/
+typedef struct {
+ BPy_Interface0D py_if0D;
+ CurvePoint *cp;
+} BPy_CurvePoint;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_CURVEPOINT_H__ */
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
new file mode 100644
index 00000000000..ae0e1d36143
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
@@ -0,0 +1,482 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_SVertex.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Id.h"
+#include "../Interface1D/BPy_FEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*----------------------SVertex methods ----------------------------*/
+
+PyDoc_STRVAR(SVertex_doc,
+"Class hierarchy: :class:`Interface0D` > :class:`SVertex`\n"
+"\n"
+"Class to define a vertex of the embedding.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A SVertex object.\n"
+" :type brother: :class:`SVertex`\n"
+"\n"
+".. method:: __init__(point_3d, id)\n"
+"\n"
+" Builds a SVertex from 3D coordinates and an Id.\n"
+"\n"
+" :arg point_3d: A three-dimensional vector.\n"
+" :type point_3d: :class:`mathutils.Vector`\n"
+" :arg id: An Id object.\n"
+" :type id: :class:`Id`");
+
+static int convert_v3(PyObject *obj, void *v)
+{
+ return float_array_from_PyObject(obj, (float *)v, 3);
+}
+
+static int SVertex_init(BPy_SVertex *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"point_3d", "id", NULL};
+ PyObject *obj = 0;
+ float v[3];
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &SVertex_Type, &obj)) {
+ if (!obj)
+ self->sv = new SVertex();
+ else
+ self->sv = new SVertex(*(((BPy_SVertex *)obj)->sv));
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O&O!", (char **)kwlist_2, convert_v3, v, &Id_Type, &obj))
+ {
+ Vec3r point_3d(v[0], v[1], v[2]);
+ self->sv = new SVertex(point_3d, *(((BPy_Id *)obj)->id));
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->py_if0D.if0D = self->sv;
+ self->py_if0D.borrowed = 0;
+ return 0;
+}
+
+PyDoc_STRVAR(SVertex_add_normal_doc,
+".. method:: add_normal(normal)\n"
+"\n"
+" Adds a normal to the SVertex's set of normals. If the same normal\n"
+" is already in the set, nothing changes.\n"
+"\n"
+" :arg normal: A three-dimensional vector.\n"
+" :type normal: :class:`mathutils.Vector`, list or tuple of 3 real numbers");
+
+static PyObject *SVertex_add_normal(BPy_SVertex *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"normal", NULL};
+ PyObject *py_normal;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", (char **)kwlist, &py_normal))
+ return NULL;
+ Vec3r *n = Vec3r_ptr_from_PyObject(py_normal);
+ if (!n) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->sv->AddNormal(*n);
+ delete n;
+
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(SVertex_add_fedge_doc,
+".. method:: add_fedge(fedge)\n"
+"\n"
+" Add an FEdge to the list of edges emanating from this SVertex.\n"
+"\n"
+" :arg fedge: An FEdge.\n"
+" :type fedge: :class:`FEdge`");
+
+static PyObject *SVertex_add_fedge(BPy_SVertex *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"fedge", NULL};
+ PyObject *py_fe;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &FEdge_Type, &py_fe))
+ return NULL;
+ self->sv->AddFEdge(((BPy_FEdge *)py_fe)->fe);
+ Py_RETURN_NONE;
+}
+
+// virtual bool operator== (const SVertex &brother)
+
+static PyMethodDef BPy_SVertex_methods[] = {
+ {"add_normal", (PyCFunction)SVertex_add_normal, METH_VARARGS | METH_KEYWORDS, SVertex_add_normal_doc},
+ {"add_fedge", (PyCFunction)SVertex_add_fedge, METH_VARARGS | METH_KEYWORDS, SVertex_add_fedge_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------mathutils callbacks ----------------------------*/
+
+/* subtype */
+#define MATHUTILS_SUBTYPE_POINT3D 1
+#define MATHUTILS_SUBTYPE_POINT2D 2
+
+static int SVertex_mathutils_check(BaseMathObject *bmo)
+{
+ if (!BPy_SVertex_Check(bmo->cb_user))
+ return -1;
+ return 0;
+}
+
+static int SVertex_mathutils_get(BaseMathObject *bmo, int subtype)
+{
+ BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_POINT3D:
+ bmo->data[0] = self->sv->getX();
+ bmo->data[1] = self->sv->getY();
+ bmo->data[2] = self->sv->getZ();
+ break;
+ case MATHUTILS_SUBTYPE_POINT2D:
+ bmo->data[0] = self->sv->getProjectedX();
+ bmo->data[1] = self->sv->getProjectedY();
+ bmo->data[2] = self->sv->getProjectedZ();
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int SVertex_mathutils_set(BaseMathObject *bmo, int subtype)
+{
+ BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_POINT3D:
+ {
+ Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]);
+ self->sv->setPoint3D(p);
+ }
+ break;
+ case MATHUTILS_SUBTYPE_POINT2D:
+ {
+ Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]);
+ self->sv->setPoint2D(p);
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int SVertex_mathutils_get_index(BaseMathObject *bmo, int subtype, int index)
+{
+ BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_POINT3D:
+ switch (index) {
+ case 0: bmo->data[0] = self->sv->getX(); break;
+ case 1: bmo->data[1] = self->sv->getY(); break;
+ case 2: bmo->data[2] = self->sv->getZ(); break;
+ default:
+ return -1;
+ }
+ break;
+ case MATHUTILS_SUBTYPE_POINT2D:
+ switch (index) {
+ case 0: bmo->data[0] = self->sv->getProjectedX(); break;
+ case 1: bmo->data[1] = self->sv->getProjectedY(); break;
+ case 2: bmo->data[2] = self->sv->getProjectedZ(); break;
+ default:
+ return -1;
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int SVertex_mathutils_set_index(BaseMathObject *bmo, int subtype, int index)
+{
+ BPy_SVertex *self = (BPy_SVertex *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_POINT3D:
+ {
+ Vec3r p(self->sv->point3D());
+ p[index] = bmo->data[index];
+ self->sv->setPoint3D(p);
+ }
+ break;
+ case MATHUTILS_SUBTYPE_POINT2D:
+ {
+ Vec3r p(self->sv->point2D());
+ p[index] = bmo->data[index];
+ self->sv->setPoint2D(p);
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static Mathutils_Callback SVertex_mathutils_cb = {
+ SVertex_mathutils_check,
+ SVertex_mathutils_get,
+ SVertex_mathutils_set,
+ SVertex_mathutils_get_index,
+ SVertex_mathutils_set_index
+};
+
+static unsigned char SVertex_mathutils_cb_index = -1;
+
+void SVertex_mathutils_register_callback()
+{
+ SVertex_mathutils_cb_index = Mathutils_RegisterCallback(&SVertex_mathutils_cb);
+}
+
+/*----------------------SVertex get/setters ----------------------------*/
+
+PyDoc_STRVAR(SVertex_point_3d_doc,
+"The 3D coordinates of the SVertex.\n"
+"\n"
+":type: mathutils.Vector");
+
+static PyObject *SVertex_point_3d_get(BPy_SVertex *self, void *UNUSED(closure))
+{
+ return Vector_CreatePyObject_cb((PyObject *)self, 3, SVertex_mathutils_cb_index, MATHUTILS_SUBTYPE_POINT3D);
+}
+
+static int SVertex_point_3d_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ float v[3];
+ if (!float_array_from_PyObject(value, v, 3)) {
+ PyErr_SetString(PyExc_ValueError, "value must be a 3-dimensional vector");
+ return -1;
+ }
+ Vec3r p(v[0], v[1], v[2]);
+ self->sv->setPoint3D(p);
+ return 0;
+}
+
+PyDoc_STRVAR(SVertex_point_2d_doc,
+"The projected 3D coordinates of the SVertex.\n"
+"\n"
+":type: mathutils.Vector");
+
+static PyObject *SVertex_point_2d_get(BPy_SVertex *self, void *UNUSED(closure))
+{
+ return Vector_CreatePyObject_cb((PyObject *)self, 3, SVertex_mathutils_cb_index, MATHUTILS_SUBTYPE_POINT2D);
+}
+
+static int SVertex_point_2d_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ float v[3];
+ if (!float_array_from_PyObject(value, v, 3)) {
+ PyErr_SetString(PyExc_ValueError, "value must be a 3-dimensional vector");
+ return -1;
+ }
+ Vec3r p(v[0], v[1], v[2]);
+ self->sv->setPoint2D(p);
+ return 0;
+}
+
+PyDoc_STRVAR(SVertex_id_doc,
+"The Id of this SVertex.\n"
+"\n"
+":type: :class:`Id`");
+
+static PyObject *SVertex_id_get(BPy_SVertex *self, void *UNUSED(closure))
+{
+ Id id(self->sv->getId());
+ return BPy_Id_from_Id(id); // return a copy
+}
+
+static int SVertex_id_set(BPy_SVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_Id_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an Id");
+ return -1;
+ }
+ self->sv->setId(*(((BPy_Id *)value)->id));
+ return 0;
+}
+
+PyDoc_STRVAR(SVertex_normals_doc,
+"The normals for this Vertex as a list. In a sharp surface, an SVertex\n"
+"has exactly one normal. In a smooth surface, an SVertex can have any\n"
+"number of normals.\n"
+"\n"
+":type: list of :class:`mathutils.Vector` objects");
+
+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));
+ }
+ return py_normals;
+}
+
+PyDoc_STRVAR(SVertex_normals_size_doc,
+"The number of different normals for this SVertex.\n"
+"\n"
+":type: int");
+
+static PyObject *SVertex_normals_size_get(BPy_SVertex *self, void *UNUSED(closure))
+{
+ return PyLong_FromLong(self->sv->normalsSize());
+}
+
+PyDoc_STRVAR(SVertex_viewvertex_doc,
+"If this SVertex is also a ViewVertex, this property refers to the\n"
+"ViewVertex, and None otherwise.\n"
+":type: :class:`ViewVertex`");
+
+static PyObject *SVertex_viewvertex_get(BPy_SVertex *self, void *UNUSED(closure))
+{
+ ViewVertex *vv = self->sv->viewvertex();
+ if (vv)
+ return Any_BPy_ViewVertex_from_ViewVertex(*vv);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(SVertex_curvatures_doc,
+"Curvature information expressed in the form of a seven-element tuple\n"
+"(K1, e1, K2, e2, Kr, er, dKr), where K1 and K2 are scalar values\n"
+"representing the first (maximum) and second (minimum) principal\n"
+"curvatures at this SVertex, respectively; e1 and e2 are\n"
+"three-dimensional vectors representing the first and second principal\n"
+"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"
+"\n"
+":type: tuple");
+
+static PyObject *SVertex_curvatures_get(BPy_SVertex *self, void *UNUSED(closure))
+{
+ const CurvatureInfo *info = self->sv->getCurvatureInfo();
+ if (!info)
+ Py_RETURN_NONE;
+ Vec3r e1(info->e1.x(), info->e1.y(), info->e1.z());
+ 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));
+ return retval;
+}
+
+static PyGetSetDef BPy_SVertex_getseters[] = {
+ {(char *)"point_3d", (getter)SVertex_point_3d_get, (setter)SVertex_point_3d_set,
+ (char *)SVertex_point_3d_doc, NULL},
+ {(char *)"point_2d", (getter)SVertex_point_2d_get, (setter)SVertex_point_2d_set,
+ (char *)SVertex_point_2d_doc, NULL},
+ {(char *)"id", (getter)SVertex_id_get, (setter)SVertex_id_set, (char *)SVertex_id_doc, NULL},
+ {(char *)"normals", (getter)SVertex_normals_get, (setter)NULL, (char *)SVertex_normals_doc, NULL},
+ {(char *)"normals_size", (getter)SVertex_normals_size_get, (setter)NULL, (char *)SVertex_normals_size_doc, NULL},
+ {(char *)"viewvertex", (getter)SVertex_viewvertex_get, (setter)NULL, (char *)SVertex_viewvertex_doc, NULL},
+ {(char *)"curvatures", (getter)SVertex_curvatures_get, (setter)NULL, (char *)SVertex_curvatures_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_SVertex type definition ------------------------------*/
+PyTypeObject SVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SVertex", /* tp_name */
+ sizeof(BPy_SVertex), /* 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 */
+ SVertex_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_SVertex_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_SVertex_getseters, /* tp_getset */
+ &Interface0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SVertex_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h
new file mode 100644
index 00000000000..7c8270e0985
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_SVERTEX_H__
+#define __FREESTYLE_PYTHON_SVERTEX_H__
+
+#include "../../view_map/Silhouette.h"
+#include "../BPy_Interface0D.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SVertex_Type;
+
+#define BPy_SVertex_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&SVertex_Type))
+
+/*---------------------------Python BPy_SVertex structure definition----------*/
+typedef struct {
+ BPy_Interface0D py_if0D;
+ SVertex *sv;
+} BPy_SVertex;
+
+/*---------------------------Python BPy_SVertex visible prototypes-----------*/
+
+void SVertex_mathutils_register_callback();
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_SVERTEX_H__ */
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp
new file mode 100644
index 00000000000..d425105aa9d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp
@@ -0,0 +1,211 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ViewVertex.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+#include "../BPy_Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*----------------------ViewVertex methods----------------------------*/
+
+PyDoc_STRVAR(ViewVertex_doc,
+"Class hierarchy: :class:`Interface0D` > :class:`ViewVertex`\n"
+"\n"
+"Class to define a view vertex. A view vertex is a feature vertex\n"
+"corresponding to a point of the image graph, where the characteristics\n"
+"of an edge (e.g., nature and visibility) might change. A\n"
+":class:`ViewVertex` can be of two kinds: A :class:`TVertex` when it\n"
+"corresponds to the intersection between two ViewEdges or a\n"
+":class:`NonTVertex` when it corresponds to a vertex of the initial\n"
+"input mesh (it is the case for vertices such as corners for example).\n"
+"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)
+{
+ PyErr_SetString(PyExc_TypeError, "cannot instantiate abstract class");
+ return -1;
+}
+
+PyDoc_STRVAR(ViewVertex_edges_begin_doc,
+".. method:: edges_begin()\n"
+"\n"
+" Returns an iterator over the ViewEdges that goes to or comes from\n"
+" this ViewVertex pointing to the first ViewEdge of the list. The\n"
+" orientedViewEdgeIterator allows to iterate in CCW order over these\n"
+" ViewEdges and to get the orientation for each ViewEdge\n"
+" (incoming/outgoing).\n"
+"\n"
+" :return: An orientedViewEdgeIterator pointing to the first ViewEdge.\n"
+" :rtype: :class:`orientedViewEdgeIterator`");
+
+static PyObject *ViewVertex_edges_begin(BPy_ViewVertex *self)
+{
+ ViewVertexInternal::orientedViewEdgeIterator ove_it(self->vv->edgesBegin());
+ return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator(ove_it, 0);
+}
+
+PyDoc_STRVAR(ViewVertex_edges_end_doc,
+".. method:: edges_end()\n"
+"\n"
+" Returns an orientedViewEdgeIterator over the ViewEdges around this\n"
+" ViewVertex, pointing after the last ViewEdge.\n"
+"\n"
+" :return: An orientedViewEdgeIterator pointing after the last ViewEdge.\n"
+" :rtype: :class:`orientedViewEdgeIterator`");
+
+static PyObject *ViewVertex_edges_end(BPy_ViewVertex *self)
+{
+#if 0
+ ViewVertexInternal::orientedViewEdgeIterator ove_it(self->vv->edgesEnd());
+ return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator(ove_it, 1);
+#else
+ PyErr_SetString(PyExc_NotImplementedError, "edges_end method currently disabled");
+ return NULL;
+#endif
+}
+
+PyDoc_STRVAR(ViewVertex_edges_iterator_doc,
+".. method:: edges_iterator(edge)\n"
+"\n"
+" Returns an orientedViewEdgeIterator pointing to the ViewEdge given\n"
+" as argument.\n"
+"\n"
+" :arg edge: A ViewEdge object.\n"
+" :type edge: :class:`ViewEdge`\n"
+" :return: An orientedViewEdgeIterator pointing to the given ViewEdge.\n"
+" :rtype: :class:`orientedViewEdgeIterator`");
+
+static PyObject *ViewVertex_edges_iterator(BPy_ViewVertex *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"edge", NULL};
+ PyObject *py_ve;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &ViewEdge_Type, &py_ve))
+ return NULL;
+ ViewEdge *ve = ((BPy_ViewEdge *)py_ve)->ve;
+ ViewVertexInternal::orientedViewEdgeIterator ove_it(self->vv->edgesIterator(ve));
+ return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator(ove_it, 0);
+}
+
+static PyMethodDef BPy_ViewVertex_methods[] = {
+ {"edges_begin", (PyCFunction)ViewVertex_edges_begin, METH_NOARGS, ViewVertex_edges_begin_doc},
+ {"edges_end", (PyCFunction)ViewVertex_edges_end, METH_NOARGS, ViewVertex_edges_end_doc},
+ {"edges_iterator", (PyCFunction)ViewVertex_edges_iterator, METH_VARARGS | METH_KEYWORDS,
+ ViewVertex_edges_iterator_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------ViewVertex get/setters ----------------------------*/
+
+PyDoc_STRVAR(ViewVertex_nature_doc,
+"The nature of this ViewVertex.\n"
+"\n"
+":type: :class:`Nature`");
+
+static PyObject *ViewVertex_nature_get(BPy_ViewVertex *self, void *UNUSED(closure))
+{
+ Nature::VertexNature nature = self->vv->getNature();
+ if (PyErr_Occurred())
+ return NULL;
+ return BPy_Nature_from_Nature(nature); // return a copy
+}
+
+static int ViewVertex_nature_set(BPy_ViewVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_Nature_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be a Nature");
+ return -1;
+ }
+ self->vv->setNature(PyLong_AsLong((PyObject *)&((BPy_Nature *)value)->i));
+ return 0;
+}
+
+static PyGetSetDef BPy_ViewVertex_getseters[] = {
+ {(char *)"nature", (getter)ViewVertex_nature_get, (setter)ViewVertex_nature_set,
+ (char *)ViewVertex_nature_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_ViewVertex type definition ------------------------------*/
+PyTypeObject ViewVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewVertex", /* tp_name */
+ sizeof(BPy_ViewVertex), /* 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 */
+ ViewVertex_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ViewVertex_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_ViewVertex_getseters, /* tp_getset */
+ &Interface0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewVertex_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h
new file mode 100644
index 00000000000..fcc12c7614a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_VIEWVERTEX_H__
+#define __FREESTYLE_PYTHON_VIEWVERTEX_H__
+
+#include "../../view_map/ViewMap.h"
+#include "../BPy_Interface0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ViewVertex_Type;
+
+#define BPy_ViewVertex_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ViewVertex_Type))
+
+/*---------------------------Python BPy_ViewVertex structure definition----------*/
+typedef struct {
+ BPy_Interface0D py_if0D;
+ ViewVertex *vv;
+} BPy_ViewVertex;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_VIEWVERTEX_H__ */
diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp
new file mode 100644
index 00000000000..590716e1a76
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp
@@ -0,0 +1,388 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_StrokeVertex.h"
+
+#include "../../BPy_Freestyle.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_StrokeAttribute.h"
+#include "../../Interface0D/BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+PyDoc_STRVAR(StrokeVertex_doc,
+"Class hierarchy: :class:`Interface0D` > :class:`CurvePoint` > :class:`StrokeVertex`\n"
+"\n"
+"Class to define a stroke vertex.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A StrokeVertex object.\n"
+" :type brother: :class:`StrokeVertex`\n"
+"\n"
+".. method:: __init__(first_vertex, second_vertex, t3d)\n"
+"\n"
+" Build a stroke vertex from 2 stroke vertices and an interpolation\n"
+" parameter.\n"
+"\n"
+" :arg first_vertex: The first StrokeVertex.\n"
+" :type first_vertex: :class:`StrokeVertex`\n"
+" :arg second_vertex: The second StrokeVertex.\n"
+" :type second_vertex: :class:`StrokeVertex`\n"
+" :arg t3d: An interpolation parameter.\n"
+" :type t3d: float\n"
+"\n"
+".. method:: __init__(point)\n"
+"\n"
+" Build a stroke vertex from a CurvePoint\n"
+"\n"
+" :arg point: A CurvePoint object.\n"
+" :type point: :class:`CurvePoint`\n"
+"\n"
+".. method:: __init__(svertex)\n"
+"\n"
+" Build a stroke vertex from a SVertex\n"
+"\n"
+" :arg svertex: An SVertex object.\n"
+" :type svertex: :class:`SVertex`\n"
+"\n"
+".. method:: __init__(svertex, attribute)\n"
+"\n"
+" Build a stroke vertex from an SVertex and a StrokeAttribute object.\n"
+"\n"
+" :arg svertex: An SVertex object.\n"
+" :type svertex: :class:`SVertex`\n"
+" :arg attribute: A StrokeAttribute object.\n"
+" :type attribute: :class:`StrokeAttribute`");
+
+static int StrokeVertex_init(BPy_StrokeVertex *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"first_vertex", "second_vertex", "t3d", NULL};
+ static const char *kwlist_3[] = {"point", NULL};
+ static const char *kwlist_4[] = {"svertex", "attribute", NULL};
+ PyObject *obj1 = 0, *obj2 = 0;
+ float t3d;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &StrokeVertex_Type, &obj1)) {
+ if (!obj1) {
+ self->sv = new StrokeVertex();
+ }
+ else {
+ if (!((BPy_StrokeVertex *)obj1)->sv) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 is an invalid StrokeVertex object");
+ return -1;
+ }
+ self->sv = new StrokeVertex(*(((BPy_StrokeVertex *)obj1)->sv));
+ }
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!O!f", (char **)kwlist_2,
+ &StrokeVertex_Type, &obj1, &StrokeVertex_Type, &obj2, &t3d))
+ {
+ StrokeVertex *sv1 = ((BPy_StrokeVertex *)obj1)->sv;
+ StrokeVertex *sv2 = ((BPy_StrokeVertex *)obj2)->sv;
+ if (!sv1 || (sv1->A() == 0 && sv1->B() == 0)) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 is an invalid StrokeVertex object");
+ return -1;
+ }
+ if (!sv2 || (sv2->A() == 0 && sv2->B() == 0)) {
+ PyErr_SetString(PyExc_TypeError, "argument 2 is an invalid StrokeVertex object");
+ return -1;
+ }
+ self->sv = new StrokeVertex(sv1, sv2, t3d);
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist_3, &CurvePoint_Type, &obj1))
+ {
+ CurvePoint *cp = ((BPy_CurvePoint *)obj1)->cp;
+ if (!cp || cp->A() == 0 || cp->B() == 0) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 is an invalid CurvePoint object");
+ return -1;
+ }
+ self->sv = new StrokeVertex(cp);
+ }
+ else if (PyErr_Clear(), (obj2 = 0),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!|O!", (char **)kwlist_4,
+ &SVertex_Type, &obj1, &StrokeAttribute_Type, &obj2))
+ {
+ if (!obj2)
+ self->sv = new StrokeVertex(((BPy_SVertex *)obj1)->sv);
+ else
+ self->sv = new StrokeVertex(((BPy_SVertex *)obj1)->sv, *(((BPy_StrokeAttribute *)obj2)->sa));
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->py_cp.cp = self->sv;
+ self->py_cp.py_if0D.if0D = self->sv;
+ self->py_cp.py_if0D.borrowed = 0;
+ return 0;
+}
+
+// real operator[] (const int i) const
+// real & operator[] (const int i)
+
+/*----------------------mathutils callbacks ----------------------------*/
+
+static int StrokeVertex_mathutils_check(BaseMathObject *bmo)
+{
+ if (!BPy_StrokeVertex_Check(bmo->cb_user))
+ return -1;
+ return 0;
+}
+
+static int StrokeVertex_mathutils_get(BaseMathObject *bmo, int subtype)
+{
+ BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user;
+ bmo->data[0] = (float)self->sv->x();
+ bmo->data[1] = (float)self->sv->y();
+ return 0;
+}
+
+static int StrokeVertex_mathutils_set(BaseMathObject *bmo, int subtype)
+{
+ BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user;
+ self->sv->setX((real)bmo->data[0]);
+ self->sv->setY((real)bmo->data[1]);
+ return 0;
+}
+
+static int StrokeVertex_mathutils_get_index(BaseMathObject *bmo, int subtype, int index)
+{
+ BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user;
+ switch (index) {
+ case 0: bmo->data[0] = (float)self->sv->x(); break;
+ case 1: bmo->data[1] = (float)self->sv->y(); break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int StrokeVertex_mathutils_set_index(BaseMathObject *bmo, int subtype, int index)
+{
+ BPy_StrokeVertex *self = (BPy_StrokeVertex *)bmo->cb_user;
+ switch (index) {
+ case 0: self->sv->setX((real)bmo->data[0]); break;
+ case 1: self->sv->setY((real)bmo->data[1]); break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static Mathutils_Callback StrokeVertex_mathutils_cb = {
+ StrokeVertex_mathutils_check,
+ StrokeVertex_mathutils_get,
+ StrokeVertex_mathutils_set,
+ StrokeVertex_mathutils_get_index,
+ StrokeVertex_mathutils_set_index
+};
+
+static unsigned char StrokeVertex_mathutils_cb_index = -1;
+
+void StrokeVertex_mathutils_register_callback()
+{
+ StrokeVertex_mathutils_cb_index = Mathutils_RegisterCallback(&StrokeVertex_mathutils_cb);
+}
+
+/*----------------------StrokeVertex get/setters ----------------------------*/
+
+PyDoc_STRVAR(StrokeVertex_attribute_doc,
+"StrokeAttribute for this StrokeVertex.\n"
+"\n"
+":type: StrokeAttribute");
+
+static PyObject *StrokeVertex_attribute_get(BPy_StrokeVertex *self, void *UNUSED(closure))
+{
+ return BPy_StrokeAttribute_from_StrokeAttribute(self->sv->attribute());
+}
+
+static int StrokeVertex_attribute_set(BPy_StrokeVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_StrokeAttribute_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be a StrokeAttribute object");
+ return -1;
+ }
+ self->sv->setAttribute(*(((BPy_StrokeAttribute *)value)->sa));
+ return 0;
+}
+
+PyDoc_STRVAR(StrokeVertex_curvilinear_abscissa_doc,
+"Curvilinear abscissa of this StrokeVertex in the Stroke.\n"
+"\n"
+":type: float");
+
+static PyObject *StrokeVertex_curvilinear_abscissa_get(BPy_StrokeVertex *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->sv->curvilinearAbscissa());
+}
+
+static int StrokeVertex_curvilinear_abscissa_set(BPy_StrokeVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ float scalar;
+ if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */
+ PyErr_SetString(PyExc_TypeError, "value must be a number");
+ return -1;
+ }
+ self->sv->setCurvilinearAbscissa(scalar);
+ return 0;
+}
+
+PyDoc_STRVAR(StrokeVertex_point_doc,
+"2D point coordinates.\n"
+"\n"
+":type: mathutils.Vector");
+
+static PyObject *StrokeVertex_point_get(BPy_StrokeVertex *self, void *UNUSED(closure))
+{
+ return Vector_CreatePyObject_cb((PyObject *)self, 2, StrokeVertex_mathutils_cb_index, 0);
+}
+
+static int StrokeVertex_point_set(BPy_StrokeVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ float v[2];
+ if (!float_array_from_PyObject(value, v, 2)) {
+ PyErr_SetString(PyExc_ValueError, "value must be a 2-dimensional vector");
+ return -1;
+ }
+ self->sv->setX(v[0]);
+ self->sv->setY(v[1]);
+ return 0;
+}
+
+PyDoc_STRVAR(StrokeVertex_stroke_length_doc,
+"Stroke length (it is only a value retained by the StrokeVertex,\n"
+"and it won't change the real stroke length).\n"
+"\n"
+":type: float");
+
+static PyObject *StrokeVertex_stroke_length_get(BPy_StrokeVertex *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->sv->strokeLength());
+}
+
+static int StrokeVertex_stroke_length_set(BPy_StrokeVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ float scalar;
+ if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */
+ PyErr_SetString(PyExc_TypeError, "value must be a number");
+ return -1;
+ }
+ self->sv->setStrokeLength(scalar);
+ return 0;
+}
+
+PyDoc_STRVAR(StrokeVertex_u_doc,
+"Curvilinear abscissa of this StrokeVertex in the Stroke.\n"
+"\n"
+":type: float");
+
+static PyObject *StrokeVertex_u_get(BPy_StrokeVertex *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->sv->u());
+}
+
+static PyGetSetDef BPy_StrokeVertex_getseters[] = {
+ {(char *)"attribute", (getter)StrokeVertex_attribute_get, (setter)StrokeVertex_attribute_set,
+ (char *)StrokeVertex_attribute_doc, NULL},
+ {(char *)"curvilinear_abscissa", (getter)StrokeVertex_curvilinear_abscissa_get,
+ (setter)StrokeVertex_curvilinear_abscissa_set,
+ (char *)StrokeVertex_curvilinear_abscissa_doc, NULL},
+ {(char *)"point", (getter)StrokeVertex_point_get, (setter)StrokeVertex_point_set,
+ (char *)StrokeVertex_point_doc, NULL},
+ {(char *)"stroke_length", (getter)StrokeVertex_stroke_length_get, (setter)StrokeVertex_stroke_length_set,
+ (char *)StrokeVertex_stroke_length_doc, NULL},
+ {(char *)"u", (getter)StrokeVertex_u_get, (setter)NULL, (char *)StrokeVertex_u_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_StrokeVertex type definition ------------------------------*/
+PyTypeObject StrokeVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "StrokeVertex", /* tp_name */
+ sizeof(BPy_StrokeVertex), /* 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 */
+ StrokeVertex_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 */
+ BPy_StrokeVertex_getseters, /* tp_getset */
+ &CurvePoint_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)StrokeVertex_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h
new file mode 100644
index 00000000000..466a40e1fca
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_STROKEVERTEX_H__
+#define __FREESTYLE_PYTHON_STROKEVERTEX_H__
+
+#include "../BPy_CurvePoint.h"
+#include "../../../stroke/Stroke.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject StrokeVertex_Type;
+
+#define BPy_StrokeVertex_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&StrokeVertex_Type))
+
+/*---------------------------Python BPy_StrokeVertex structure definition----------*/
+typedef struct {
+ BPy_CurvePoint py_cp;
+ StrokeVertex *sv;
+} BPy_StrokeVertex;
+
+/*---------------------------Python BPy_StrokeVertex visible prototypes-----------*/
+
+void StrokeVertex_mathutils_register_callback();
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_STROKEVERTEX_H__ */
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp
new file mode 100644
index 00000000000..8fd4425b291
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp
@@ -0,0 +1,158 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_NonTVertex.h"
+
+#include "../../BPy_Convert.h"
+#include "../BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*----------------------NonTVertex methods ----------------------------*/
+
+PyDoc_STRVAR(NonTVertex_doc,
+"Class hierarchy: :class:`Interface0D` > :class:`ViewVertex` > :class:`NonTVertex`\n"
+"\n"
+"View vertex for corners, cusps, etc. associated to a single SVertex.\n"
+"Can be associated to 2 or more view edges.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(svertex)\n"
+"\n"
+" Build a NonTVertex from a SVertex.\n"
+"\n"
+" :arg svertex: An SVertex object.\n"
+" :type svertex: :class:`SVertex`");
+
+/* Note: No copy constructor in Python because the C++ copy constructor is 'protected'. */
+
+static int NonTVertex_init(BPy_NonTVertex *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"svertex", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &SVertex_Type, &obj))
+ return -1;
+ if (!obj)
+ self->ntv = new NonTVertex();
+ else
+ self->ntv = new NonTVertex(((BPy_SVertex *)obj)->sv);
+ self->py_vv.vv = self->ntv;
+ self->py_vv.py_if0D.if0D = self->ntv;
+ self->py_vv.py_if0D.borrowed = 0;
+ return 0;
+}
+
+/*----------------------NonTVertex get/setters ----------------------------*/
+
+PyDoc_STRVAR(NonTVertex_svertex_doc,
+"The SVertex on top of which this NonTVertex is built.\n"
+"\n"
+":type: :class:`SVertex`");
+
+static PyObject *NonTVertex_svertex_get(BPy_NonTVertex *self, void *UNUSED(closure))
+{
+ SVertex *v = self->ntv->svertex();
+ if (v)
+ return BPy_SVertex_from_SVertex(*v);
+ Py_RETURN_NONE;
+}
+
+static int NonTVertex_svertex_set(BPy_NonTVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_SVertex_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
+ return -1;
+ }
+ self->ntv->setSVertex(((BPy_SVertex *)value)->sv);
+ return 0;
+}
+
+static PyGetSetDef BPy_NonTVertex_getseters[] = {
+ {(char *)"svertex", (getter)NonTVertex_svertex_get, (setter)NonTVertex_svertex_set,
+ (char *)NonTVertex_svertex_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_NonTVertex type definition ------------------------------*/
+PyTypeObject NonTVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "NonTVertex", /* tp_name */
+ sizeof(BPy_NonTVertex), /* 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 */
+ NonTVertex_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 */
+ BPy_NonTVertex_getseters, /* tp_getset */
+ &ViewVertex_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)NonTVertex_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h
new file mode 100644
index 00000000000..4bc59d3597e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_NONTVERTEX_H__
+#define __FREESTYLE_PYTHON_NONTVERTEX_H__
+
+#include "../BPy_ViewVertex.h"
+#include "../../../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject NonTVertex_Type;
+
+#define BPy_NonTVertex_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&NonTVertex_Type))
+
+/*---------------------------Python BPy_NonTVertex structure definition----------*/
+typedef struct {
+ BPy_ViewVertex py_vv;
+ NonTVertex *ntv;
+} BPy_NonTVertex;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_NONTVERTEX_H__ */
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp
new file mode 100644
index 00000000000..e9295f323fb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp
@@ -0,0 +1,254 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_TVertex.h"
+
+#include "../../BPy_Convert.h"
+#include "../BPy_SVertex.h"
+#include "../../BPy_Id.h"
+#include "../../Interface1D/BPy_FEdge.h"
+#include "../../Interface1D/BPy_ViewEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*----------------------TVertex methods ----------------------------*/
+
+PyDoc_STRVAR(TVertex_doc,
+"Class hierarchy: :class:`Interface0D` > :class:`ViewVertex` > :class:`TVertex`\n"
+"\n"
+"Class to define a T vertex, i.e. an intersection between two edges.\n"
+"It points towards two SVertex and four ViewEdges. Among the\n"
+"ViewEdges, two are front and the other two are back. Basically a\n"
+"front edge hides part of a back edge. So, among the back edges, one\n"
+"is of invisibility N and the other of invisibility N+1.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.");
+
+/* Note: No copy constructor in Python because the C++ copy constructor is 'protected'. */
+
+static int TVertex_init(BPy_TVertex *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->tv = new TVertex();
+ self->py_vv.vv = self->tv;
+ self->py_vv.py_if0D.if0D = self->tv;
+ self->py_vv.py_if0D.borrowed = 0;
+ return 0;
+}
+
+PyDoc_STRVAR(TVertex_get_svertex_doc,
+".. method:: get_svertex(fedge)\n"
+"\n"
+" Returns the SVertex (among the 2) belonging to the given FEdge.\n"
+"\n"
+" :arg fedge: An FEdge object.\n"
+" :type fedge: :class:`FEdge`\n"
+" :return: The SVertex belonging to the given FEdge.\n"
+" :rtype: :class:`SVertex`");
+
+static PyObject *TVertex_get_svertex( BPy_TVertex *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"fedge", NULL};
+ PyObject *py_fe;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &FEdge_Type, &py_fe))
+ return NULL;
+ SVertex *sv = self->tv->getSVertex(((BPy_FEdge *)py_fe)->fe);
+ if (sv)
+ return BPy_SVertex_from_SVertex(*sv);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(TVertex_get_mate_doc,
+".. method:: get_mate(viewedge)\n"
+"\n"
+" Returns the mate edge of the ViewEdge given as argument. If the\n"
+" ViewEdge is frontEdgeA, frontEdgeB is returned. If the ViewEdge is\n"
+" frontEdgeB, frontEdgeA is returned. Same for back edges.\n"
+"\n"
+" :arg viewedge: A ViewEdge object.\n"
+" :type viewedge: :class:`ViewEdge`\n"
+" :return: The mate edge of the given ViewEdge.\n"
+" :rtype: :class:`ViewEdge`");
+
+static PyObject *TVertex_get_mate( BPy_TVertex *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"viewedge", NULL};
+ PyObject *py_ve;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &ViewEdge_Type, &py_ve))
+ return NULL;
+ ViewEdge *ve = self->tv->mate(((BPy_ViewEdge *)py_ve)->ve);
+ if (ve)
+ return BPy_ViewEdge_from_ViewEdge(*ve);
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef BPy_TVertex_methods[] = {
+ {"get_svertex", (PyCFunction)TVertex_get_svertex, METH_VARARGS | METH_KEYWORDS, TVertex_get_svertex_doc},
+ {"get_mate", (PyCFunction)TVertex_get_mate, METH_VARARGS | METH_KEYWORDS, TVertex_get_mate_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------TVertex get/setters ----------------------------*/
+
+PyDoc_STRVAR(TVertex_front_svertex_doc,
+"The SVertex that is closer to the viewpoint.\n"
+"\n"
+":type: :class:`SVertex`");
+
+static PyObject *TVertex_front_svertex_get(BPy_TVertex *self, void *UNUSED(closure))
+{
+ SVertex *v = self->tv->frontSVertex();
+ if (v)
+ return BPy_SVertex_from_SVertex(*v);
+ Py_RETURN_NONE;
+}
+
+static int TVertex_front_svertex_set(BPy_TVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_SVertex_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
+ return -1;
+ }
+ self->tv->setFrontSVertex(((BPy_SVertex *)value)->sv);
+ return 0;
+}
+
+PyDoc_STRVAR(TVertex_back_svertex_doc,
+"The SVertex that is further away from the viewpoint.\n"
+"\n"
+":type: :class:`SVertex`");
+
+static PyObject *TVertex_back_svertex_get(BPy_TVertex *self, void *UNUSED(closure))
+{
+ SVertex *v = self->tv->backSVertex();
+ if (v)
+ return BPy_SVertex_from_SVertex(*v);
+ Py_RETURN_NONE;
+}
+
+static int TVertex_back_svertex_set(BPy_TVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_SVertex_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
+ return -1;
+ }
+ self->tv->setBackSVertex(((BPy_SVertex *)value)->sv);
+ return 0;
+}
+
+PyDoc_STRVAR(TVertex_id_doc,
+"The Id of this TVertex.\n"
+"\n"
+":type: :class:`Id`");
+
+static PyObject *TVertex_id_get(BPy_TVertex *self, void *UNUSED(closure))
+{
+ Id id(self->tv->getId());
+ return BPy_Id_from_Id(id); // return a copy
+}
+
+static int TVertex_id_set(BPy_TVertex *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_Id_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an Id");
+ return -1;
+ }
+ self->tv->setId(*(((BPy_Id *)value)->id));
+ return 0;
+}
+
+static PyGetSetDef BPy_TVertex_getseters[] = {
+ {(char *)"front_svertex", (getter)TVertex_front_svertex_get, (setter)TVertex_front_svertex_set,
+ (char *)TVertex_front_svertex_doc, NULL},
+ {(char *)"back_svertex", (getter)TVertex_back_svertex_get, (setter)TVertex_back_svertex_set,
+ (char *)TVertex_back_svertex_doc, NULL},
+ {(char *)"id", (getter)TVertex_id_get, (setter)TVertex_id_set, (char *)TVertex_id_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_TVertex type definition ------------------------------*/
+PyTypeObject TVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TVertex", /* tp_name */
+ sizeof(BPy_TVertex), /* 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 */
+ TVertex_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_TVertex_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_TVertex_getseters, /* tp_getset */
+ &ViewVertex_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TVertex_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h
new file mode 100644
index 00000000000..4d832b2f67f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_TVERTEX_H__
+#define __FREESTYLE_PYTHON_TVERTEX_H__
+
+#include "../BPy_ViewVertex.h"
+#include "../../../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TVertex_Type;
+
+#define BPy_TVertex_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&TVertex_Type))
+
+/*---------------------------Python BPy_TVertex structure definition----------*/
+typedef struct {
+ BPy_ViewVertex py_vv;
+ TVertex *tv;
+} BPy_TVertex;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_TVERTEX_H__ */
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp
new file mode 100644
index 00000000000..0260199ccee
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp
@@ -0,0 +1,385 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_FEdge.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Id.h"
+#include "../Interface0D/BPy_SVertex.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+#include "../BPy_Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*----------------------FEdge methods ----------------------------*/
+
+PyDoc_STRVAR(FEdge_doc,
+"Class hierarchy: :class:`Interface1D` > :class:`FEdge`\n"
+"\n"
+"Base Class for feature edges. This FEdge can represent a silhouette,\n"
+"a crease, a ridge/valley, a border or a suggestive contour. For\n"
+"silhouettes, the FEdge is oriented so that the visible face lies on\n"
+"the left of the edge. For borders, the FEdge is oriented so that the\n"
+"face lies on the left of the edge. An FEdge can represent an initial\n"
+"edge of the mesh or runs accross a face of the initial mesh depending\n"
+"on the smoothness or sharpness of the mesh. This class is specialized\n"
+"into a smooth and a sharp version since their properties slightly vary\n"
+"from one to the other.\n"
+"\n"
+".. method:: FEdge()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: FEdge(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: An FEdge object.\n"
+" :type brother: :class:`FEdge`\n"
+"\n"
+".. method:: FEdge(first_vertex, second_vertex)\n"
+"\n"
+" Builds an FEdge going from the first vertex to the second.\n"
+"\n"
+" :arg first_vertex: The first SVertex.\n"
+" :type first_vertex: :class:`SVertex`\n"
+" :arg second_vertex: The second SVertex.\n"
+" :type second_vertex: :class:`SVertex`");
+
+static int FEdge_init(BPy_FEdge *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"first_vertex", "second_vertex", NULL};
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &FEdge_Type, &obj1)) {
+ if (!obj1)
+ self->fe = new FEdge();
+ else
+ self->fe = new FEdge(*(((BPy_FEdge *)obj1)->fe));
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!O!", (char **)kwlist_2,
+ &SVertex_Type, &obj1, &SVertex_Type, &obj2))
+ {
+ self->fe = new FEdge(((BPy_SVertex *)obj1)->sv, ((BPy_SVertex *)obj2)->sv);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->py_if1D.if1D = self->fe;
+ self->py_if1D.borrowed = 0;
+ return 0;
+}
+
+/*----------------------FEdge sequence protocol ----------------------------*/
+
+static Py_ssize_t FEdge_sq_length(BPy_FEdge *self)
+{
+ return 2;
+}
+
+static PyObject *FEdge_sq_item(BPy_FEdge *self, int keynum)
+{
+ if (keynum < 0)
+ keynum += FEdge_sq_length(self);
+ if (keynum == 0 || keynum == 1) {
+ SVertex *v = self->fe->operator[](keynum);
+ if (v)
+ return BPy_SVertex_from_SVertex(*v);
+ Py_RETURN_NONE;
+ }
+ PyErr_Format(PyExc_IndexError, "FEdge[index]: index %d out of range", keynum);
+ return NULL;
+}
+
+static PySequenceMethods BPy_FEdge_as_sequence = {
+ (lenfunc)FEdge_sq_length, /* sq_length */
+ NULL, /* sq_concat */
+ NULL, /* sq_repeat */
+ (ssizeargfunc)FEdge_sq_item, /* sq_item */
+ NULL, /* sq_slice */
+ NULL, /* sq_ass_item */
+ NULL, /* *was* sq_ass_slice */
+ NULL, /* sq_contains */
+ NULL, /* sq_inplace_concat */
+ NULL, /* sq_inplace_repeat */
+};
+
+/*----------------------FEdge get/setters ----------------------------*/
+
+PyDoc_STRVAR(FEdge_first_svertex_doc,
+"The first SVertex constituting this FEdge.\n"
+"\n"
+":type: :class:`SVertex`");
+
+static PyObject *FEdge_first_svertex_get(BPy_FEdge *self, void *UNUSED(closure))
+{
+ SVertex *A = self->fe->vertexA();
+ if (A)
+ return BPy_SVertex_from_SVertex(*A);
+ Py_RETURN_NONE;
+}
+
+static int FEdge_first_svertex_set(BPy_FEdge *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_SVertex_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
+ return -1;
+ }
+ self->fe->setVertexA(((BPy_SVertex *)value)->sv);
+ return 0;
+}
+
+PyDoc_STRVAR(FEdge_second_svertex_doc,
+"The second SVertex constituting this FEdge.\n"
+"\n"
+":type: :class:`SVertex`");
+
+static PyObject *FEdge_second_svertex_get(BPy_FEdge *self, void *UNUSED(closure))
+{
+ SVertex *B = self->fe->vertexB();
+ if (B)
+ return BPy_SVertex_from_SVertex(*B);
+ Py_RETURN_NONE;
+}
+
+static int FEdge_second_svertex_set(BPy_FEdge *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_SVertex_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an SVertex");
+ return -1;
+ }
+ self->fe->setVertexB(((BPy_SVertex *)value)->sv);
+ return 0;
+}
+
+PyDoc_STRVAR(FEdge_next_fedge_doc,
+"The FEdge following this one in the ViewEdge. The value is None if\n"
+"this FEdge is the last of the ViewEdge.\n"
+"\n"
+":type: :class:`FEdge`");
+
+static PyObject *FEdge_next_fedge_get(BPy_FEdge *self, void *UNUSED(closure))
+{
+ FEdge *fe = self->fe->nextEdge();
+ if (fe)
+ return Any_BPy_FEdge_from_FEdge(*fe);
+ Py_RETURN_NONE;
+}
+
+static int FEdge_next_fedge_set(BPy_FEdge *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_FEdge_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an FEdge");
+ return -1;
+ }
+ self->fe->setNextEdge(((BPy_FEdge *)value)->fe);
+ return 0;
+}
+
+PyDoc_STRVAR(FEdge_previous_fedge_doc,
+"The FEdge preceding this one in the ViewEdge. The value is None if\n"
+"this FEdge is the first one of the ViewEdge.\n"
+"\n"
+":type: :class:`FEdge`");
+
+static PyObject *FEdge_previous_fedge_get(BPy_FEdge *self, void *UNUSED(closure))
+{
+ FEdge *fe = self->fe->previousEdge();
+ if (fe)
+ return Any_BPy_FEdge_from_FEdge(*fe);
+ Py_RETURN_NONE;
+}
+
+static int FEdge_previous_fedge_set(BPy_FEdge *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_FEdge_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an FEdge");
+ return -1;
+ }
+ self->fe->setPreviousEdge(((BPy_FEdge *)value)->fe);
+ return 0;
+}
+
+PyDoc_STRVAR(FEdge_viewedge_doc,
+"The ViewEdge to which this FEdge belongs to.\n"
+"\n"
+":type: :class:`ViewEdge`");
+
+static PyObject *FEdge_viewedge_get(BPy_FEdge *self, void *UNUSED(closure))
+{
+ ViewEdge *ve = self->fe->viewedge();
+ if (ve)
+ return BPy_ViewEdge_from_ViewEdge(*ve);
+ Py_RETURN_NONE;
+}
+
+static int FEdge_viewedge_set(BPy_FEdge *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_ViewEdge_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an ViewEdge");
+ return -1;
+ }
+ self->fe->setViewEdge(((BPy_ViewEdge *)value)->ve);
+ return 0;
+}
+
+PyDoc_STRVAR(FEdge_is_smooth_doc,
+"True if this FEdge is a smooth FEdge.\n"
+"\n"
+":type: bool");
+
+static PyObject *FEdge_is_smooth_get(BPy_FEdge *self, void *UNUSED(closure))
+{
+ return PyBool_from_bool(self->fe->isSmooth());
+}
+
+static int FEdge_is_smooth_set(BPy_FEdge *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!PyBool_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be boolean");
+ return -1;
+ }
+ self->fe->setSmooth(bool_from_PyBool(value));
+ return 0;
+}
+
+PyDoc_STRVAR(FEdge_id_doc,
+"The Id of this FEdge.\n"
+"\n"
+":type: :class:`Id`");
+
+static PyObject *FEdge_id_get(BPy_FEdge *self, void *UNUSED(closure))
+{
+ Id id(self->fe->getId());
+ return BPy_Id_from_Id(id); // return a copy
+}
+
+static int FEdge_id_set(BPy_FEdge *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_Id_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an Id");
+ return -1;
+ }
+ self->fe->setId(*(((BPy_Id *)value)->id));
+ return 0;
+}
+
+PyDoc_STRVAR(FEdge_nature_doc,
+"The nature of this FEdge.\n"
+"\n"
+":type: :class:`Nature`");
+
+static PyObject *FEdge_nature_get(BPy_FEdge *self, void *UNUSED(closure))
+{
+ return BPy_Nature_from_Nature(self->fe->getNature());
+}
+
+static int FEdge_nature_set(BPy_FEdge *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_Nature_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be a Nature");
+ return -1;
+ }
+ self->fe->setNature(PyLong_AsLong((PyObject *)&((BPy_Nature *)value)->i));
+ return 0;
+}
+
+static PyGetSetDef BPy_FEdge_getseters[] = {
+ {(char *)"first_svertex", (getter)FEdge_first_svertex_get, (setter)FEdge_first_svertex_set,
+ (char *)FEdge_first_svertex_doc, NULL},
+ {(char *)"second_svertex", (getter)FEdge_second_svertex_get, (setter)FEdge_second_svertex_set,
+ (char *)FEdge_second_svertex_doc, NULL},
+ {(char *)"next_fedge", (getter)FEdge_next_fedge_get, (setter)FEdge_next_fedge_set,
+ (char *)FEdge_next_fedge_doc, NULL},
+ {(char *)"previous_fedge", (getter)FEdge_previous_fedge_get, (setter)FEdge_previous_fedge_set,
+ (char *)FEdge_previous_fedge_doc, NULL},
+ {(char *)"viewedge", (getter)FEdge_viewedge_get, (setter)FEdge_viewedge_set, (char *)FEdge_viewedge_doc, NULL},
+ {(char *)"is_smooth", (getter)FEdge_is_smooth_get, (setter)FEdge_is_smooth_set, (char *)FEdge_is_smooth_doc, NULL},
+ {(char *)"id", (getter)FEdge_id_get, (setter)FEdge_id_set, (char *)FEdge_id_doc, NULL},
+ {(char *)"nature", (getter)FEdge_nature_get, (setter)FEdge_nature_set, (char *)FEdge_nature_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_FEdge type definition ------------------------------*/
+
+PyTypeObject FEdge_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FEdge", /* tp_name */
+ sizeof(BPy_FEdge), /* 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 */
+ &BPy_FEdge_as_sequence, /* 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 */
+ FEdge_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 */
+ BPy_FEdge_getseters, /* tp_getset */
+ &Interface1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FEdge_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h
new file mode 100644
index 00000000000..468136736ca
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_FEDGE_H__
+#define __FREESTYLE_PYTHON_FEDGE_H__
+
+#include "../BPy_Interface1D.h"
+#include "../../view_map/Silhouette.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FEdge_Type;
+
+#define BPy_FEdge_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&FEdge_Type))
+
+/*---------------------------Python BPy_FEdge structure definition----------*/
+typedef struct {
+ BPy_Interface1D py_if1D;
+ FEdge *fe;
+} BPy_FEdge;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_FEDGE_H__ */
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp
new file mode 100644
index 00000000000..7026d93774a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp
@@ -0,0 +1,240 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_FrsCurve.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Id.h"
+#include "../Interface0D/BPy_CurvePoint.h"
+#include "../Interface0D/BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*----------------------CurvePoint methods ----------------------------*/
+
+PyDoc_STRVAR(FrsCurve_doc,
+"Class hierarchy: :class:`Interface1D` > :class:`Curve`\n"
+"\n"
+"Base class for curves made of CurvePoints. :class:`SVertex` is the\n"
+"type of the initial curve vertices. A :class:`Chain` is a\n"
+"specialization of a Curve.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default Constructor.\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy Constructor.\n"
+"\n"
+" :arg brother: A Curve object.\n"
+" :type brother: :class:`Curve`\n"
+"\n"
+".. method:: __init__(id)\n"
+"\n"
+" Builds a Curve from its Id.\n"
+"\n"
+" :arg id: An Id object.\n"
+" :type id: :class:`Id`");
+
+static int FrsCurve_init(BPy_FrsCurve *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"id", NULL};
+ PyObject *obj = 0;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &FrsCurve_Type, &obj)) {
+ if (!obj)
+ self->c = new Curve();
+ else
+ self->c = new Curve(*(((BPy_FrsCurve *)obj)->c));
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist_2, &Id_Type, &obj))
+ {
+ self->c = new Curve(*(((BPy_Id *)obj)->id));
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->py_if1D.if1D = self->c;
+ self->py_if1D.borrowed = 0;
+ return 0;
+}
+
+PyDoc_STRVAR(FrsCurve_push_vertex_back_doc,
+".. method:: push_vertex_back(vertex)\n"
+"\n"
+" Adds a single vertex at the end of the Curve.\n"
+"\n"
+" :arg vertex: A vertex object.\n"
+" :type vertex: :class:`SVertex` or :class:`CurvePoint`");
+
+static PyObject *FrsCurve_push_vertex_back(BPy_FrsCurve *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"vertex", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", (char **)kwlist, &obj))
+ return NULL;
+
+ if (BPy_CurvePoint_Check(obj)) {
+ self->c->push_vertex_back(((BPy_CurvePoint *)obj)->cp);
+ }
+ else if (BPy_SVertex_Check(obj)) {
+ self->c->push_vertex_back(((BPy_SVertex *)obj)->sv);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(FrsCurve_push_vertex_front_doc,
+".. method:: push_vertex_front(vertex)\n"
+"\n"
+" Adds a single vertex at the front of the Curve.\n"
+"\n"
+" :arg vertex: A vertex object.\n"
+" :type vertex: :class:`SVertex` or :class:`CurvePoint`");
+
+static PyObject *FrsCurve_push_vertex_front(BPy_FrsCurve *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"vertex", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", (char **)kwlist, &obj))
+ return NULL;
+
+ if (BPy_CurvePoint_Check(obj)) {
+ self->c->push_vertex_front(((BPy_CurvePoint *)obj)->cp);
+ }
+ else if (BPy_SVertex_Check(obj)) {
+ self->c->push_vertex_front(((BPy_SVertex *)obj)->sv);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef BPy_FrsCurve_methods[] = {
+ {"push_vertex_back", (PyCFunction)FrsCurve_push_vertex_back, METH_VARARGS | METH_KEYWORDS,
+ FrsCurve_push_vertex_back_doc},
+ {"push_vertex_front", (PyCFunction)FrsCurve_push_vertex_front, METH_VARARGS | METH_KEYWORDS,
+ FrsCurve_push_vertex_front_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------CurvePoint get/setters ----------------------------*/
+
+PyDoc_STRVAR(FrsCurve_is_empty_doc,
+"True if the Curve doesn't have any Vertex yet.\n"
+"\n"
+":type: bool");
+
+static PyObject *FrsCurve_is_empty_get(BPy_FrsCurve *self, void *UNUSED(closure))
+{
+ return PyBool_from_bool(self->c->empty());
+}
+
+PyDoc_STRVAR(FrsCurve_segments_size_doc,
+"The number of segments in the polyline constituing the Curve.\n"
+"\n"
+":type: int");
+
+static PyObject *FrsCurve_segments_size_get(BPy_FrsCurve *self, void *UNUSED(closure))
+{
+ return PyLong_FromLong(self->c->nSegments());
+}
+
+static PyGetSetDef BPy_FrsCurve_getseters[] = {
+ {(char *)"is_empty", (getter)FrsCurve_is_empty_get, (setter)NULL, (char *)FrsCurve_is_empty_doc, NULL},
+ {(char *)"segments_size", (getter)FrsCurve_segments_size_get, (setter)NULL,
+ (char *)FrsCurve_segments_size_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_FrsCurve type definition ------------------------------*/
+
+PyTypeObject FrsCurve_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Curve", /* tp_name */
+ sizeof(BPy_FrsCurve), /* 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 */
+ FrsCurve_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_FrsCurve_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_FrsCurve_getseters, /* tp_getset */
+ &Interface1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FrsCurve_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h
new file mode 100644
index 00000000000..3622870af9a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_FRSCURVE_H__
+#define __FREESTYLE_PYTHON_FRSCURVE_H__
+
+#include "../BPy_Interface1D.h"
+#include "../../stroke/Curve.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FrsCurve_Type;
+
+#define BPy_FrsCurve_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&FrsCurve_Type))
+
+/*---------------------------Python BPy_FrsCurve structure definition----------*/
+typedef struct {
+ BPy_Interface1D py_if1D;
+ Curve *c;
+} BPy_FrsCurve;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_FRSCURVE_H__ */
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
new file mode 100644
index 00000000000..53ec86f3c01
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
@@ -0,0 +1,478 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_Stroke.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Id.h"
+#include "../Interface0D/BPy_SVertex.h"
+#include "../Interface0D/CurvePoint/BPy_StrokeVertex.h"
+#include "../Iterator/BPy_StrokeVertexIterator.h"
+#include "../BPy_MediumType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*----------------------Stroke methods ----------------------------*/
+
+// Stroke ()
+// template<class InputVertexIterator> Stroke (InputVertexIterator begin, InputVertexIterator end)
+//
+// pb: - need to be able to switch representation: InputVertexIterator <=> position
+// - is it even used ? not even in SWIG version
+
+PyDoc_STRVAR(Stroke_doc,
+"Class hierarchy: :class:`Interface1D` > :class:`Stroke`\n"
+"\n"
+"Class to define a stroke. A stroke is made of a set of 2D vertices\n"
+"(:class:`StrokeVertex`), regularly spaced out. This set of vertices\n"
+"defines the stroke's backbone geometry. Each of these stroke vertices\n"
+"defines the stroke's shape and appearance at this vertex position.\n"
+"\n"
+".. method:: Stroke()\n"
+"\n"
+" Default constructor\n"
+"\n"
+".. method:: Stroke(brother)\n"
+"\n"
+" Copy constructor");
+
+static int Stroke_init(BPy_Stroke *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"brother", NULL};
+ PyObject *brother = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &Stroke_Type, &brother))
+ return -1;
+ if (!brother)
+ self->s = new Stroke();
+ else
+ self->s = new Stroke(*(((BPy_Stroke *)brother)->s));
+ self->py_if1D.if1D = self->s;
+ self->py_if1D.borrowed = 0;
+ return 0;
+}
+
+static PyObject *Stroke_iter(PyObject *self)
+{
+ StrokeInternal::StrokeVertexIterator sv_it( ((BPy_Stroke *)self)->s->strokeVerticesBegin() );
+ return BPy_StrokeVertexIterator_from_StrokeVertexIterator( sv_it, 0 );
+}
+
+static Py_ssize_t Stroke_sq_length(BPy_Stroke *self)
+{
+ return self->s->strokeVerticesSize();
+}
+
+static PyObject *Stroke_sq_item(BPy_Stroke *self, int keynum)
+{
+ if (keynum < 0)
+ keynum += Stroke_sq_length(self);
+ if (keynum < 0 || keynum >= Stroke_sq_length(self)) {
+ PyErr_Format(PyExc_IndexError, "Stroke[index]: index %d out of range", keynum);
+ return NULL;
+ }
+ return BPy_StrokeVertex_from_StrokeVertex(self->s->strokeVerticeAt(keynum));
+}
+
+PyDoc_STRVAR(Stroke_compute_sampling_doc,
+".. method:: compute_sampling(n)\n"
+"\n"
+" Compute the sampling needed to get N vertices. If the\n"
+" specified number of vertices is less than the actual number of\n"
+" vertices, the actual sampling value is returned. (To remove Vertices,\n"
+" use the RemoveVertex() method of this class.)\n"
+"\n"
+" :arg n: The number of stroke vertices we eventually want\n"
+" in our Stroke.\n"
+" :type n: int\n"
+" :return: The sampling that must be used in the Resample(float)\n"
+" method.\n"
+" :rtype: float");
+
+static PyObject *Stroke_compute_sampling(BPy_Stroke *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"n", NULL};
+ int i;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", (char **)kwlist, &i))
+ return NULL;
+ return PyFloat_FromDouble(self->s->ComputeSampling(i));
+}
+
+PyDoc_STRVAR(Stroke_resample_doc,
+".. method:: resample(n)\n"
+"\n"
+" Resamples the stroke so that it eventually has N points. That means\n"
+" it is going to add N-vertices_size, where vertices_size is the\n"
+" number of points we already have. If vertices_size >= N, no\n"
+" resampling is done.\n"
+"\n"
+" :arg n: The number of vertices we eventually want in our stroke.\n"
+" :type n: int\n"
+"\n"
+".. method:: resample(sampling)\n"
+"\n"
+" Resamples the stroke with a given sampling. If the sampling is\n"
+" smaller than the actual sampling value, no resampling is done.\n"
+"\n"
+" :arg sampling: The new sampling value.\n"
+" :type sampling: float");
+
+static PyObject *Stroke_resample(BPy_Stroke *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"n", NULL};
+ static const char *kwlist_2[] = {"sampling", NULL};
+ int i;
+ float f;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "i", (char **)kwlist_1, &i)) {
+ self->s->Resample(i);
+ }
+ else if (PyErr_Clear(), PyArg_ParseTupleAndKeywords(args, kwds, "f", (char **)kwlist_2, &f)) {
+ self->s->Resample(f);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Stroke_insert_vertex_doc,
+".. method:: insert_vertex(vertex, next)\n"
+"\n"
+" Inserts the StrokeVertex given as argument into the Stroke before the\n"
+" point specified by next. The length and curvilinear abscissa are\n"
+" updated consequently.\n"
+"\n"
+" :arg vertex: The StrokeVertex to insert in the Stroke.\n"
+" :type vertex: :class:`StrokeVertex`\n"
+" :arg next: A StrokeVertexIterator pointing to the StrokeVertex\n"
+" before which vertex must be inserted.\n"
+" :type next: :class:`StrokeVertexIterator`");
+
+static PyObject *Stroke_insert_vertex(BPy_Stroke *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"vertex", "next", NULL};
+ PyObject *py_sv = 0, *py_sv_it = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!", (char **)kwlist,
+ &StrokeVertex_Type, &py_sv, &StrokeVertexIterator_Type, &py_sv_it))
+ {
+ return NULL;
+ }
+ StrokeVertex *sv = ((BPy_StrokeVertex *)py_sv)->sv;
+ StrokeInternal::StrokeVertexIterator sv_it(*(((BPy_StrokeVertexIterator *)py_sv_it)->sv_it));
+ self->s->InsertVertex(sv, sv_it);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Stroke_remove_vertex_doc,
+".. method:: remove_vertex(vertex)\n"
+"\n"
+" Removes the StrokeVertex given as argument from the Stroke. The length\n"
+" and curvilinear abscissa are updated consequently.\n"
+"\n"
+" :arg vertex: the StrokeVertex to remove from the Stroke.\n"
+" :type vertex: :class:`StrokeVertex`");
+
+static PyObject *Stroke_remove_vertex( BPy_Stroke *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"vertex", NULL};
+ PyObject *py_sv = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &StrokeVertex_Type, &py_sv))
+ return NULL;
+ if (((BPy_StrokeVertex *)py_sv)->sv) {
+ self->s->RemoveVertex(((BPy_StrokeVertex *)py_sv)->sv);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Stroke_update_length_doc,
+".. method:: update_length()\n"
+"\n"
+" Updates the 2D length of the Stroke.");
+
+static PyObject *Stroke_update_length(BPy_Stroke *self)
+{
+ self->s->UpdateLength();
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Stroke_stroke_vertices_begin_doc,
+".. method:: stroke_vertices_begin(t=0.0)\n"
+"\n"
+" Returns a StrokeVertexIterator pointing on the first StrokeVertex of\n"
+" the Stroke. O ne can specify a sampling value to resample the Stroke\n"
+" on the fly if needed.\n"
+"\n"
+" :arg t: The resampling value with which we want our Stroke to be\n"
+" resampled. If 0 is specified, no resampling is done.\n"
+" :type t: float\n"
+" :return: A StrokeVertexIterator pointing on the first StrokeVertex.\n"
+" :rtype: :class:`StrokeVertexIterator`");
+
+static PyObject *Stroke_stroke_vertices_begin(BPy_Stroke *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"t", NULL};
+ float f = 0.0f;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|f", (char **)kwlist, &f))
+ return NULL;
+ StrokeInternal::StrokeVertexIterator sv_it(self->s->strokeVerticesBegin(f));
+ return BPy_StrokeVertexIterator_from_StrokeVertexIterator(sv_it, 0);
+}
+
+PyDoc_STRVAR(Stroke_stroke_vertices_end_doc,
+".. method:: strokeVerticesEnd()\n"
+"\n"
+" Returns a StrokeVertexIterator pointing after the last StrokeVertex\n"
+" of the Stroke.\n"
+"\n"
+" :return: A StrokeVertexIterator pointing after the last StrokeVertex.\n"
+" :rtype: :class:`StrokeVertexIterator`");
+
+static PyObject *Stroke_stroke_vertices_end(BPy_Stroke *self)
+{
+ StrokeInternal::StrokeVertexIterator sv_it(self->s->strokeVerticesEnd());
+ return BPy_StrokeVertexIterator_from_StrokeVertexIterator(sv_it, 1);
+}
+
+PyDoc_STRVAR(Stroke_stroke_vertices_size_doc,
+".. method:: stroke_vertices_size()\n"
+"\n"
+" Returns the number of StrokeVertex constituing the Stroke.\n"
+"\n"
+" :return: The number of stroke vertices.\n"
+" :rtype: int");
+
+static PyObject *Stroke_stroke_vertices_size(BPy_Stroke *self)
+{
+ return PyLong_FromLong(self->s->strokeVerticesSize());
+}
+
+static PyMethodDef BPy_Stroke_methods[] = {
+ {"compute_sampling", (PyCFunction)Stroke_compute_sampling, METH_VARARGS | METH_KEYWORDS,
+ Stroke_compute_sampling_doc},
+ {"resample", (PyCFunction)Stroke_resample, METH_VARARGS | METH_KEYWORDS, Stroke_resample_doc},
+ {"remove_vertex", (PyCFunction)Stroke_remove_vertex, METH_VARARGS | METH_KEYWORDS, Stroke_remove_vertex_doc},
+ {"insert_vertex", (PyCFunction)Stroke_insert_vertex, METH_VARARGS | METH_KEYWORDS, Stroke_insert_vertex_doc},
+ {"update_length", (PyCFunction)Stroke_update_length, METH_NOARGS, Stroke_update_length_doc},
+ {"stroke_vertices_begin", (PyCFunction)Stroke_stroke_vertices_begin, METH_VARARGS | METH_KEYWORDS,
+ Stroke_stroke_vertices_begin_doc},
+ {"stroke_vertices_end", (PyCFunction)Stroke_stroke_vertices_end, METH_NOARGS, Stroke_stroke_vertices_end_doc},
+ {"stroke_vertices_size", (PyCFunction)Stroke_stroke_vertices_size, METH_NOARGS, Stroke_stroke_vertices_size_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------Stroke get/setters ----------------------------*/
+
+PyDoc_STRVAR(Stroke_medium_type_doc,
+"The MediumType used for this Stroke.\n"
+"\n"
+":type: :class:`MediumType`");
+
+static PyObject *Stroke_medium_type_get(BPy_Stroke *self, void *UNUSED(closure))
+{
+ return BPy_MediumType_from_MediumType(self->s->getMediumType());
+}
+
+static int Stroke_medium_type_set(BPy_Stroke *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_MediumType_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be a MediumType");
+ return -1;
+ }
+ self->s->setMediumType(MediumType_from_BPy_MediumType(value));
+ return 0;
+}
+
+PyDoc_STRVAR(Stroke_texture_id_doc,
+"The ID of the texture used to simulate th marks system for this Stroke.\n"
+"\n"
+":type: int");
+
+static PyObject *Stroke_texture_id_get(BPy_Stroke *self, void *UNUSED(closure))
+{
+ return PyLong_FromLong( self->s->getTextureId() );
+}
+
+static int Stroke_texture_id_set(BPy_Stroke *self, PyObject *value, void *UNUSED(closure))
+{
+ unsigned int i = PyLong_AsUnsignedLong(value);
+ if (PyErr_Occurred())
+ return -1;
+ self->s->setTextureId(i);
+ return 0;
+}
+
+PyDoc_STRVAR(Stroke_tips_doc,
+"True if this Stroke uses a texture with tips, and false otherwise.\n"
+"\n"
+":type: bool");
+
+static PyObject *Stroke_tips_get(BPy_Stroke *self, void *UNUSED(closure))
+{
+ return PyBool_from_bool(self->s->hasTips());
+}
+
+static int Stroke_tips_set(BPy_Stroke *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!PyBool_Check(value))
+ return -1;
+ self->s->setTips(bool_from_PyBool(value));
+ return 0;
+}
+
+PyDoc_STRVAR(Stroke_length_2d_doc,
+"The 2D length of the Stroke.\n"
+"\n"
+":type: float");
+
+static PyObject *Stroke_length_2d_get(BPy_Stroke *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->s->getLength2D());
+}
+
+static int Stroke_length_2d_set(BPy_Stroke *self, PyObject *value, void *UNUSED(closure))
+{
+ float scalar;
+ if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */
+ PyErr_SetString(PyExc_TypeError, "value must be a number");
+ return -1;
+ }
+ self->s->setLength(scalar);
+ return 0;
+}
+
+PyDoc_STRVAR(Stroke_id_doc,
+"The Id of this Stroke.\n"
+"\n"
+":type: :class:`Id`");
+
+static PyObject *Stroke_id_get(BPy_Stroke *self, void *UNUSED(closure))
+{
+ Id id(self->s->getId());
+ return BPy_Id_from_Id(id); // return a copy
+}
+
+static int Stroke_id_set(BPy_Stroke *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_Id_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an Id");
+ return -1;
+ }
+ self->s->setId(*(((BPy_Id *)value)->id));
+ return 0;
+}
+
+static PyGetSetDef BPy_Stroke_getseters[] = {
+ {(char *)"medium_type", (getter)Stroke_medium_type_get, (setter)Stroke_medium_type_set,
+ (char *)Stroke_medium_type_doc, NULL},
+ {(char *)"texture_id", (getter)Stroke_texture_id_get, (setter)Stroke_texture_id_set,
+ (char *)Stroke_texture_id_doc, NULL},
+ {(char *)"tips", (getter)Stroke_tips_get, (setter)Stroke_tips_set, (char *)Stroke_tips_doc, NULL},
+ {(char *)"length_2d", (getter)Stroke_length_2d_get, (setter)Stroke_length_2d_set,
+ (char *)Stroke_length_2d_doc, NULL},
+ {(char *)"id", (getter)Stroke_id_get, (setter)Stroke_id_set, (char *)Stroke_id_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_Stroke type definition ------------------------------*/
+
+static PySequenceMethods BPy_Stroke_as_sequence = {
+ (lenfunc)Stroke_sq_length, /* sq_length */
+ NULL, /* sq_concat */
+ NULL, /* sq_repeat */
+ (ssizeargfunc)Stroke_sq_item, /* sq_item */
+ NULL, /* sq_slice */
+ NULL, /* sq_ass_item */
+ NULL, /* *was* sq_ass_slice */
+ NULL, /* sq_contains */
+ NULL, /* sq_inplace_concat */
+ NULL, /* sq_inplace_repeat */
+};
+
+PyTypeObject Stroke_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Stroke", /* tp_name */
+ sizeof(BPy_Stroke), /* 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 */
+ &BPy_Stroke_as_sequence, /* 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 */
+ Stroke_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ (getiterfunc)Stroke_iter, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Stroke_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_Stroke_getseters, /* tp_getset */
+ &Interface1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Stroke_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h
new file mode 100644
index 00000000000..5ad894ce636
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_STROKE_H__
+#define __FREESTYLE_PYTHON_STROKE_H__
+
+#include "../BPy_Interface1D.h"
+#include "../../stroke/Stroke.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Stroke_Type;
+
+#define BPy_Stroke_Check(v) (((PyObject *)v)->ob_type == &Stroke_Type)
+
+/*---------------------------Python BPy_Stroke structure definition----------*/
+typedef struct {
+ BPy_Interface1D py_if1D;
+ Stroke *s;
+} BPy_Stroke;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_STROKE_H__ */
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp
new file mode 100644
index 00000000000..e264b3b6217
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp
@@ -0,0 +1,389 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ViewEdge.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Id.h"
+#include "../Interface0D/BPy_ViewVertex.h"
+#include "../Interface1D/BPy_FEdge.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+#include "../BPy_Nature.h"
+#include "../BPy_ViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*----------------------ViewEdge methods ----------------------------*/
+
+PyDoc_STRVAR(ViewEdge_doc,
+"Class hierarchy: :class:`Interface1D` > :class:`ViewEdge`\n"
+"\n"
+"Class defining a ViewEdge. A ViewEdge in an edge of the image graph.\n"
+"it connnects two :class:`ViewVertex` objects. It is made by connecting\n"
+"a set of FEdges.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A ViewEdge object.\n"
+" :type brother: :class:`ViewEdge`");
+
+static int ViewEdge_init(BPy_ViewEdge *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"brother", NULL};
+ PyObject *brother = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &ViewEdge_Type, &brother))
+ return -1;
+ if (!brother)
+ self->ve = new ViewEdge();
+ else
+ self->ve = new ViewEdge(*(((BPy_ViewEdge *)brother)->ve));
+ self->py_if1D.if1D = self->ve;
+ self->py_if1D.borrowed = 0;
+ return 0;
+}
+
+PyDoc_STRVAR(ViewEdge_update_fedges_doc,
+".. method:: update_fedges()\n"
+"\n"
+" Sets Viewedge to this for all embedded fedges.\n");
+
+static PyObject *ViewEdge_update_fedges(BPy_ViewEdge *self)
+{
+ self->ve->UpdateFEdges();
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef BPy_ViewEdge_methods[] = {
+ {"update_fedges", (PyCFunction)ViewEdge_update_fedges, METH_NOARGS, ViewEdge_update_fedges_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------ViewEdge get/setters ----------------------------*/
+
+PyDoc_STRVAR(ViewEdge_first_viewvertex_doc,
+"The first ViewVertex.\n"
+"\n"
+":type: :class:`ViewVertex`");
+
+static PyObject *ViewEdge_first_viewvertex_get(BPy_ViewEdge *self, void *UNUSED(closure))
+{
+ ViewVertex *v = self->ve->A();
+ if (v)
+ return Any_BPy_ViewVertex_from_ViewVertex(*v);
+ Py_RETURN_NONE;
+}
+
+static int ViewEdge_first_viewvertex_set(BPy_ViewEdge *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_ViewVertex_Check(value))
+ return -1;
+ self->ve->setA(((BPy_ViewVertex *)value)->vv);
+ return 0;
+}
+
+PyDoc_STRVAR(ViewEdge_last_viewvertex_doc,
+"The second ViewVertex.\n"
+"\n"
+":type: :class:`ViewVertex`");
+
+static PyObject *ViewEdge_last_viewvertex_get(BPy_ViewEdge *self, void *UNUSED(closure))
+{
+ ViewVertex *v = self->ve->B();
+ if (v)
+ return Any_BPy_ViewVertex_from_ViewVertex(*v);
+ Py_RETURN_NONE;
+}
+
+static int ViewEdge_last_viewvertex_set(BPy_ViewEdge *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_ViewVertex_Check(value))
+ return -1;
+ self->ve->setB(((BPy_ViewVertex *)value)->vv);
+ return 0;
+}
+
+PyDoc_STRVAR(ViewEdge_first_fedge_doc,
+"The first FEdge that constitutes this ViewEdge.\n"
+"\n"
+":type: :class:`FEdge`");
+
+static PyObject *ViewEdge_first_fedge_get(BPy_ViewEdge *self, void *UNUSED(closure))
+{
+ FEdge *fe = self->ve->fedgeA();
+ if (fe)
+ return Any_BPy_FEdge_from_FEdge(*fe);
+ Py_RETURN_NONE;
+}
+
+static int ViewEdge_first_fedge_set(BPy_ViewEdge *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_FEdge_Check(value))
+ return -1;
+ self->ve->setFEdgeA(((BPy_FEdge *)value)->fe);
+ return 0;
+}
+
+PyDoc_STRVAR(ViewEdge_last_fedge_doc,
+"The last FEdge that constitutes this ViewEdge.\n"
+"\n"
+":type: :class:`FEdge`");
+
+static PyObject *ViewEdge_last_fedge_get(BPy_ViewEdge *self, void *UNUSED(closure))
+{
+ FEdge *fe = self->ve->fedgeB();
+ if (fe)
+ return Any_BPy_FEdge_from_FEdge(*fe);
+ Py_RETURN_NONE;
+}
+
+static int ViewEdge_last_fedge_set(BPy_ViewEdge *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_FEdge_Check(value))
+ return -1;
+ self->ve->setFEdgeB(((BPy_FEdge *)value)->fe);
+ return 0;
+}
+
+PyDoc_STRVAR(ViewEdge_viewshape_doc,
+"The ViewShape to which this ViewEdge belongs to.\n"
+"\n"
+":type: :class:`ViewShape`");
+
+static PyObject *ViewEdge_viewshape_get(BPy_ViewEdge *self, void *UNUSED(closure))
+{
+ ViewShape *vs = self->ve->viewShape();
+ if (vs)
+ return BPy_ViewShape_from_ViewShape(*vs);
+ Py_RETURN_NONE;
+}
+
+static int ViewEdge_viewshape_set(BPy_ViewEdge *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_ViewShape_Check(value))
+ return -1;
+ self->ve->setShape(((BPy_ViewShape *)value)->vs);
+ return 0;
+}
+
+PyDoc_STRVAR(ViewEdge_occludee_doc,
+"The shape that is occluded by the ViewShape to which this ViewEdge\n"
+"belongs to. If no object is occluded, this property is set to None.\n"
+"\n"
+":type: :class:`ViewShape`");
+
+static PyObject *ViewEdge_occludee_get(BPy_ViewEdge *self, void *UNUSED(closure))
+{
+ ViewShape *vs = self->ve->aShape();
+ if (vs)
+ return BPy_ViewShape_from_ViewShape(*vs);
+ Py_RETURN_NONE;
+}
+
+static int ViewEdge_occludee_set(BPy_ViewEdge *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_ViewShape_Check(value))
+ return -1;
+ self->ve->setaShape(((BPy_ViewShape *)value)->vs);
+ return 0;
+}
+
+PyDoc_STRVAR(ViewEdge_is_closed_doc,
+"True if this ViewEdge forms a closed loop.\n"
+"\n"
+":type: bool");
+
+static PyObject *ViewEdge_is_closed_get(BPy_ViewEdge *self, void *UNUSED(closure))
+{
+ return PyBool_from_bool(self->ve->isClosed());
+}
+
+PyDoc_STRVAR(ViewEdge_id_doc,
+"The Id of this ViewEdge.\n"
+"\n"
+":type: :class:`Id`");
+
+static PyObject *ViewEdge_id_get(BPy_ViewEdge *self, void *UNUSED(closure))
+{
+ Id id(self->ve->getId());
+ return BPy_Id_from_Id(id); // return a copy
+}
+
+static int ViewEdge_id_set(BPy_ViewEdge *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_Id_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an Id");
+ return -1;
+ }
+ self->ve->setId(*(((BPy_Id *)value)->id));
+ return 0;
+}
+
+PyDoc_STRVAR(ViewEdge_nature_doc,
+"The nature of this ViewEdge.\n"
+"\n"
+":type: :class:`Nature`");
+
+static PyObject *ViewEdge_nature_get(BPy_ViewEdge *self, void *UNUSED(closure))
+{
+ return BPy_Nature_from_Nature(self->ve->getNature());
+}
+
+static int ViewEdge_nature_set(BPy_ViewEdge *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_Nature_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be a Nature");
+ return -1;
+ }
+ self->ve->setNature(PyLong_AsLong((PyObject *)&((BPy_Nature *)value)->i));
+ return 0;
+}
+
+PyDoc_STRVAR(ViewEdge_qi_doc,
+"The quantitative invisibility.\n"
+"\n"
+":type: int");
+
+static PyObject *ViewEdge_qi_get(BPy_ViewEdge *self, void *UNUSED(closure))
+{
+ return PyLong_FromLong(self->ve->qi());
+}
+
+static int ViewEdge_qi_set(BPy_ViewEdge *self, PyObject *value, void *UNUSED(closure))
+{
+ int qi;
+
+ if ((qi = PyLong_AsLong(value)) == -1 && PyErr_Occurred())
+ return -1;
+ self->ve->setQI(qi);
+ return 0;
+}
+
+PyDoc_STRVAR(ViewEdge_chaining_time_stamp_doc,
+"The time stamp of this ViewEdge.\n"
+"\n"
+":type: int");
+
+static PyObject *ViewEdge_chaining_time_stamp_get(BPy_ViewEdge *self, void *UNUSED(closure))
+{
+ return PyLong_FromLong(self->ve->getChainingTimeStamp());
+}
+
+static int ViewEdge_chaining_time_stamp_set(BPy_ViewEdge *self, PyObject *value, void *UNUSED(closure))
+{
+ int timestamp;
+
+ if ((timestamp = PyLong_AsLong(value)) == -1 && PyErr_Occurred())
+ return -1;
+ self->ve->setChainingTimeStamp(timestamp);
+ return 0;
+}
+
+static PyGetSetDef BPy_ViewEdge_getseters[] = {
+ {(char *)"first_viewvertex", (getter)ViewEdge_first_viewvertex_get, (setter)ViewEdge_first_viewvertex_set,
+ (char *)ViewEdge_first_viewvertex_doc, NULL},
+ {(char *)"last_viewvertex", (getter)ViewEdge_last_viewvertex_get, (setter)ViewEdge_last_viewvertex_set,
+ (char *)ViewEdge_last_viewvertex_doc, NULL},
+ {(char *)"first_fedge", (getter)ViewEdge_first_fedge_get, (setter)ViewEdge_first_fedge_set,
+ (char *)ViewEdge_first_fedge_doc, NULL},
+ {(char *)"last_fedge", (getter)ViewEdge_last_fedge_get, (setter)ViewEdge_last_fedge_set,
+ (char *)ViewEdge_last_fedge_doc, NULL},
+ {(char *)"viewshape", (getter)ViewEdge_viewshape_get, (setter)ViewEdge_viewshape_set,
+ (char *)ViewEdge_viewshape_doc, NULL},
+ {(char *)"occludee", (getter)ViewEdge_occludee_get, (setter)ViewEdge_occludee_set,
+ (char *)ViewEdge_occludee_doc, NULL},
+ {(char *)"is_closed", (getter)ViewEdge_is_closed_get, (setter)NULL, (char *)ViewEdge_is_closed_doc, NULL},
+ {(char *)"id", (getter)ViewEdge_id_get, (setter)ViewEdge_id_set, (char *)ViewEdge_id_doc, NULL},
+ {(char *)"nature", (getter)ViewEdge_nature_get, (setter)ViewEdge_nature_set, (char *)ViewEdge_nature_doc, NULL},
+ {(char *)"qi", (getter)ViewEdge_qi_get, (setter)ViewEdge_qi_set, (char *)ViewEdge_qi_doc, NULL},
+ {(char *)"chaining_time_stamp", (getter)ViewEdge_chaining_time_stamp_get, (setter)ViewEdge_chaining_time_stamp_set,
+ (char *)ViewEdge_chaining_time_stamp_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_ViewEdge type definition ------------------------------*/
+
+PyTypeObject ViewEdge_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewEdge", /* tp_name */
+ sizeof(BPy_ViewEdge), /* 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 */
+ ViewEdge_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ViewEdge_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_ViewEdge_getseters, /* tp_getset */
+ &Interface1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewEdge_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h
new file mode 100644
index 00000000000..e5bb0c891cf
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h
@@ -0,0 +1,63 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_VIEWEDGE_H__
+#define __FREESTYLE_PYTHON_VIEWEDGE_H__
+
+#include "../../view_map/ViewMap.h"
+
+#include "../BPy_Interface1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ViewEdge_Type;
+
+#define BPy_ViewEdge_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ViewEdge_Type))
+
+/*---------------------------Python BPy_ViewEdge structure definition----------*/
+typedef struct {
+ BPy_Interface1D py_if1D;
+ ViewEdge *ve;
+} BPy_ViewEdge;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_VIEWEDGE_H__ */
diff --git a/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp
new file mode 100644
index 00000000000..4a4e0c06fa8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp
@@ -0,0 +1,207 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_Chain.h"
+
+#include "../../BPy_Convert.h"
+#include "../../BPy_Id.h"
+#include "../BPy_ViewEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*----------------------Chain methods ----------------------------*/
+
+PyDoc_STRVAR(Chain_doc,
+"Class hierarchy: :class:`Interface1D` > :class:`Curve` > :class:`Chain`\n"
+"\n"
+"Class to represent a 1D elements issued from the chaining process. A\n"
+"Chain is the last step before the :class:`Stroke` and is used in the\n"
+"Splitting and Creation processes.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A Chain object.\n"
+" :type brother: :class:`Chain`\n"
+"\n"
+".. method:: __init__(id)\n"
+"\n"
+" Builds a chain from its Id.\n"
+"\n"
+" :arg id: An Id object.\n"
+" :type id: :class:`Id`");
+
+static int Chain_init(BPy_Chain *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"id", NULL};
+ PyObject *obj = 0;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &Chain_Type, &obj)) {
+ if (!obj)
+ self->c = new Chain();
+ else
+ self->c = new Chain(*(((BPy_Chain *)obj)->c));
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist_2, &Id_Type, &obj))
+ {
+ self->c = new Chain(*(((BPy_Id *)obj)->id));
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->py_c.c = self->c;
+ self->py_c.py_if1D.if1D = self->c;
+ self->py_c.py_if1D.borrowed = 0;
+ return 0;
+}
+
+PyDoc_STRVAR(Chain_push_viewedge_back_doc,
+".. method:: push_viewedge_back(viewedge, orientation)\n"
+"\n"
+" Adds a ViewEdge at the end of the Chain.\n"
+"\n"
+" :arg viewedge: The ViewEdge that must be added.\n"
+" :type viewedge: :class:`ViewEdge`\n"
+" :arg orientation: The orientation with which the ViewEdge must be\n"
+" processed.\n"
+" :type orientation: bool");
+
+static PyObject *Chain_push_viewedge_back(BPy_Chain *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"viewedge", "orientation", NULL};
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!", (char **)kwlist,
+ &ViewEdge_Type, &obj1, &PyBool_Type, &obj2))
+ {
+ return NULL;
+ }
+ ViewEdge *ve = ((BPy_ViewEdge *)obj1)->ve;
+ bool orientation = bool_from_PyBool(obj2);
+ self->c->push_viewedge_back(ve, orientation);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Chain_push_viewedge_front_doc,
+".. method:: push_viewedge_front(viewedge, orientation)\n"
+"\n"
+" Adds a ViewEdge at the beginning of the Chain.\n"
+"\n"
+" :arg viewedge: The ViewEdge that must be added.\n"
+" :type viewedge: :class:`ViewEdge`\n"
+" :arg orientation: The orientation with which the ViewEdge must be\n"
+" processed.\n"
+" :type orientation: bool");
+
+static PyObject *Chain_push_viewedge_front(BPy_Chain *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"viewedge", "orientation", NULL};
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!", (char **)kwlist,
+ &ViewEdge_Type, &obj1, &PyBool_Type, &obj2))
+ {
+ return NULL;
+ }
+ ViewEdge *ve = ((BPy_ViewEdge *)obj1)->ve;
+ bool orientation = bool_from_PyBool(obj2);
+ self->c->push_viewedge_front(ve, orientation);
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef BPy_Chain_methods[] = {
+ {"push_viewedge_back", (PyCFunction)Chain_push_viewedge_back, METH_VARARGS | METH_KEYWORDS,
+ Chain_push_viewedge_back_doc},
+ {"push_viewedge_front", (PyCFunction)Chain_push_viewedge_front, METH_VARARGS | METH_KEYWORDS,
+ Chain_push_viewedge_front_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_Chain type definition ------------------------------*/
+
+PyTypeObject Chain_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Chain", /* tp_name */
+ sizeof(BPy_Chain), /* 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 */
+ Chain_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Chain_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &FrsCurve_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Chain_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h
new file mode 100644
index 00000000000..bfc72e6aaec
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_CHAIN_H__
+#define __FREESTYLE_PYTHON_CHAIN_H__
+
+#include "../BPy_FrsCurve.h"
+#include "../../../stroke/Chain.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Chain_Type;
+
+#define BPy_Chain_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Chain_Type))
+
+/*---------------------------Python BPy_Chain structure definition----------*/
+typedef struct {
+ BPy_FrsCurve py_c;
+ Chain *c;
+} BPy_Chain;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_CHAIN_H__ */
diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp
new file mode 100644
index 00000000000..183e86a237e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp
@@ -0,0 +1,440 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_FEdgeSharp.h"
+
+#include "../../BPy_Convert.h"
+#include "../../Interface0D/BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*----------------------FEdgeSharp methods ----------------------------*/
+
+PyDoc_STRVAR(FEdgeSharp_doc,
+"Class hierarchy: :class:`Interface1D` > :class:`FEdge` > :class:`FEdgeSharp`\n"
+"\n"
+"Class defining a sharp FEdge. A Sharp FEdge corresponds to an initial\n"
+"edge of the input mesh. It can be a silhouette, a crease or a border.\n"
+"If it is a crease edge, then it is borded by two faces of the mesh.\n"
+"Face a lies on its right whereas Face b lies on its left. If it is a\n"
+"border edge, then it doesn't have any face on its right, and thus Face\n"
+"a is None.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: An FEdgeSharp object.\n"
+" :type brother: :class:`FEdgeSharp`\n"
+"\n"
+".. method:: __init__(first_vertex, second_vertex)\n"
+"\n"
+" Builds an FEdgeSharp going from the first vertex to the second.\n"
+"\n"
+" :arg first_vertex: The first SVertex object.\n"
+" :type first_vertex: :class:`SVertex`\n"
+" :arg second_vertex: The second SVertex object.\n"
+" :type second_vertex: :class:`SVertex`");
+
+static int FEdgeSharp_init(BPy_FEdgeSharp *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"first_vertex", "second_vertex", NULL};
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &FEdgeSharp_Type, &obj1)) {
+ if (!obj1)
+ self->fes = new FEdgeSharp();
+ else
+ self->fes = new FEdgeSharp(*(((BPy_FEdgeSharp *)obj1)->fes));
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!O!", (char **)kwlist_2,
+ &SVertex_Type, &obj1, &SVertex_Type, &obj2))
+ {
+ self->fes = new FEdgeSharp(((BPy_SVertex *)obj1)->sv, ((BPy_SVertex *)obj2)->sv);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->py_fe.fe = self->fes;
+ self->py_fe.py_if1D.if1D = self->fes;
+ self->py_fe.py_if1D.borrowed = 0;
+ return 0;
+}
+
+/*----------------------mathutils callbacks ----------------------------*/
+
+/* subtype */
+#define MATHUTILS_SUBTYPE_NORMAL_A 1
+#define MATHUTILS_SUBTYPE_NORMAL_B 2
+
+static int FEdgeSharp_mathutils_check(BaseMathObject *bmo)
+{
+ if (!BPy_FEdgeSharp_Check(bmo->cb_user))
+ return -1;
+ return 0;
+}
+
+static int FEdgeSharp_mathutils_get(BaseMathObject *bmo, int subtype)
+{
+ BPy_FEdgeSharp *self = (BPy_FEdgeSharp *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_NORMAL_A:
+ {
+ Vec3r p(self->fes->normalA());
+ bmo->data[0] = p[0];
+ bmo->data[1] = p[1];
+ bmo->data[2] = p[2];
+ }
+ break;
+ case MATHUTILS_SUBTYPE_NORMAL_B:
+ {
+ Vec3r p(self->fes->normalB());
+ bmo->data[0] = p[0];
+ bmo->data[1] = p[1];
+ bmo->data[2] = p[2];
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int FEdgeSharp_mathutils_set(BaseMathObject *bmo, int subtype)
+{
+ BPy_FEdgeSharp *self = (BPy_FEdgeSharp *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_NORMAL_A:
+ {
+ Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]);
+ self->fes->setNormalA(p);
+ }
+ break;
+ case MATHUTILS_SUBTYPE_NORMAL_B:
+ {
+ Vec3r p(bmo->data[0], bmo->data[1], bmo->data[2]);
+ self->fes->setNormalB(p);
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int FEdgeSharp_mathutils_get_index(BaseMathObject *bmo, int subtype, int index)
+{
+ BPy_FEdgeSharp *self = (BPy_FEdgeSharp *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_NORMAL_A:
+ {
+ Vec3r p(self->fes->normalA());
+ bmo->data[index] = p[index];
+ }
+ break;
+ case MATHUTILS_SUBTYPE_NORMAL_B:
+ {
+ Vec3r p(self->fes->normalB());
+ bmo->data[index] = p[index];
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int FEdgeSharp_mathutils_set_index(BaseMathObject *bmo, int subtype, int index)
+{
+ BPy_FEdgeSharp *self = (BPy_FEdgeSharp *)bmo->cb_user;
+ switch (subtype) {
+ case MATHUTILS_SUBTYPE_NORMAL_A:
+ {
+ Vec3r p(self->fes->normalA());
+ p[index] = bmo->data[index];
+ self->fes->setNormalA(p);
+ }
+ break;
+ case MATHUTILS_SUBTYPE_NORMAL_B:
+ {
+ Vec3r p(self->fes->normalB());
+ p[index] = bmo->data[index];
+ self->fes->setNormalB(p);
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static Mathutils_Callback FEdgeSharp_mathutils_cb = {
+ FEdgeSharp_mathutils_check,
+ FEdgeSharp_mathutils_get,
+ FEdgeSharp_mathutils_set,
+ FEdgeSharp_mathutils_get_index,
+ FEdgeSharp_mathutils_set_index
+};
+
+static unsigned char FEdgeSharp_mathutils_cb_index = -1;
+
+void FEdgeSharp_mathutils_register_callback()
+{
+ FEdgeSharp_mathutils_cb_index = Mathutils_RegisterCallback(&FEdgeSharp_mathutils_cb);
+}
+
+/*----------------------FEdgeSharp get/setters ----------------------------*/
+
+PyDoc_STRVAR(FEdgeSharp_normal_right_doc,
+"The normal to the face lying on the right of the FEdge. If this FEdge\n"
+"is a border, it has no Face on its right and therefore no normal.\n"
+"\n"
+":type: :class:`mathutils.Vector`");
+
+static PyObject *FEdgeSharp_normal_right_get(BPy_FEdgeSharp *self, void *UNUSED(closure))
+{
+ return Vector_CreatePyObject_cb((PyObject *)self, 3, FEdgeSharp_mathutils_cb_index, MATHUTILS_SUBTYPE_NORMAL_A);
+}
+
+static int FEdgeSharp_normal_right_set(BPy_FEdgeSharp *self, PyObject *value, void *UNUSED(closure))
+{
+ float v[3];
+ if (!float_array_from_PyObject(value, v, 3)) {
+ PyErr_SetString(PyExc_ValueError, "value must be a 3-dimensional vector");
+ return -1;
+ }
+ Vec3r p(v[0], v[1], v[2]);
+ self->fes->setNormalA(p);
+ return 0;
+}
+
+PyDoc_STRVAR(FEdgeSharp_normal_left_doc,
+"The normal to the face lying on the left of the FEdge.\n"
+"\n"
+":type: :class:`mathutils.Vector`");
+
+static PyObject *FEdgeSharp_normal_left_get(BPy_FEdgeSharp *self, void *UNUSED(closure))
+{
+ return Vector_CreatePyObject_cb((PyObject *)self, 3, FEdgeSharp_mathutils_cb_index, MATHUTILS_SUBTYPE_NORMAL_B);
+}
+
+static int FEdgeSharp_normal_left_set(BPy_FEdgeSharp *self, PyObject *value, void *UNUSED(closure))
+{
+ float v[3];
+ if (!float_array_from_PyObject(value, v, 3)) {
+ PyErr_SetString(PyExc_ValueError, "value must be a 3-dimensional vector");
+ return -1;
+ }
+ Vec3r p(v[0], v[1], v[2]);
+ self->fes->setNormalB(p);
+ return 0;
+}
+
+PyDoc_STRVAR(FEdgeSharp_material_index_right_doc,
+"The index of the material of the face lying on the right of the FEdge.\n"
+"If this FEdge is a border, it has no Face on its right and therefore\n"
+"no material.\n"
+"\n"
+":type: int");
+
+static PyObject *FEdgeSharp_material_index_right_get(BPy_FEdgeSharp *self, void *UNUSED(closure))
+{
+ return PyLong_FromLong(self->fes->aFrsMaterialIndex());
+}
+
+static int FEdgeSharp_material_index_right_set(BPy_FEdgeSharp *self, PyObject *value, void *UNUSED(closure))
+{
+ unsigned int i = PyLong_AsUnsignedLong(value);
+ if (PyErr_Occurred())
+ return -1;
+ self->fes->setaFrsMaterialIndex(i);
+ return 0;
+}
+
+PyDoc_STRVAR(FEdgeSharp_material_index_left_doc,
+"The index of the material of the face lying on the left of the FEdge.\n"
+"\n"
+":type: int");
+
+static PyObject *FEdgeSharp_material_index_left_get(BPy_FEdgeSharp *self, void *UNUSED(closure))
+{
+ return PyLong_FromLong(self->fes->aFrsMaterialIndex());
+}
+
+static int FEdgeSharp_material_index_left_set(BPy_FEdgeSharp *self, PyObject *value, void *UNUSED(closure))
+{
+ unsigned int i = PyLong_AsUnsignedLong(value);
+ if (PyErr_Occurred())
+ return -1;
+ self->fes->setbFrsMaterialIndex(i);
+ return 0;
+}
+
+PyDoc_STRVAR(FEdgeSharp_material_right_doc,
+"The material of the face lying on the right of the FEdge. If this FEdge\n"
+"is a border, it has no Face on its right and therefore no material.\n"
+"\n"
+":type: :class:`Material`");
+
+static PyObject *FEdgeSharp_material_right_get(BPy_FEdgeSharp *self, void *UNUSED(closure))
+{
+ return BPy_FrsMaterial_from_FrsMaterial(self->fes->aFrsMaterial());
+}
+
+PyDoc_STRVAR(FEdgeSharp_material_left_doc,
+"The material of the face lying on the left of the FEdge.\n"
+"\n"
+":type: :class:`Material`");
+
+static PyObject *FEdgeSharp_material_left_get(BPy_FEdgeSharp *self, void *UNUSED(closure))
+{
+ return BPy_FrsMaterial_from_FrsMaterial(self->fes->bFrsMaterial());
+}
+
+PyDoc_STRVAR(FEdgeSharp_face_mark_right_doc,
+"The face mark of the face lying on the right of the FEdge. If this FEdge\n"
+"is a border, it has no face on the right and thus this property is set to\n"
+"false.\n"
+"\n"
+":type: bool");
+
+static PyObject *FEdgeSharp_face_mark_right_get(BPy_FEdgeSharp *self, void *UNUSED(closure))
+{
+ return PyBool_from_bool(self->fes->aFaceMark());
+}
+
+static int FEdgeSharp_face_mark_right_set(BPy_FEdgeSharp *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!PyBool_Check(value))
+ return -1;
+ self->fes->setaFaceMark(bool_from_PyBool(value));
+ return 0;
+}
+
+PyDoc_STRVAR(FEdgeSharp_face_mark_left_doc,
+"The face mark of the face lying on the left of the FEdge.\n"
+"\n"
+":type: bool");
+
+static PyObject *FEdgeSharp_face_mark_left_get(BPy_FEdgeSharp *self, void *UNUSED(closure))
+{
+ return PyBool_from_bool(self->fes->bFaceMark());
+}
+
+static int FEdgeSharp_face_mark_left_set(BPy_FEdgeSharp *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!PyBool_Check(value))
+ return -1;
+ self->fes->setbFaceMark(bool_from_PyBool(value));
+ return 0;
+}
+
+static PyGetSetDef BPy_FEdgeSharp_getseters[] = {
+ {(char *)"normal_right", (getter)FEdgeSharp_normal_right_get, (setter)FEdgeSharp_normal_right_set,
+ (char *)FEdgeSharp_normal_right_doc, NULL},
+ {(char *)"normal_left", (getter)FEdgeSharp_normal_left_get, (setter)FEdgeSharp_normal_left_set,
+ (char *)FEdgeSharp_normal_left_doc, NULL},
+ {(char *)"material_index_right", (getter)FEdgeSharp_material_index_right_get,
+ (setter)FEdgeSharp_material_index_right_set,
+ (char *)FEdgeSharp_material_index_right_doc, NULL},
+ {(char *)"material_index_left", (getter)FEdgeSharp_material_index_left_get,
+ (setter)FEdgeSharp_material_index_left_set,
+ (char *)FEdgeSharp_material_index_left_doc, NULL},
+ {(char *)"material_right", (getter)FEdgeSharp_material_right_get, (setter)NULL,
+ (char *)FEdgeSharp_material_right_doc, NULL},
+ {(char *)"material_left", (getter)FEdgeSharp_material_left_get, (setter)NULL,
+ (char *)FEdgeSharp_material_left_doc, NULL},
+ {(char *)"face_mark_right", (getter)FEdgeSharp_face_mark_right_get, (setter)FEdgeSharp_face_mark_right_set,
+ (char *)FEdgeSharp_face_mark_right_doc, NULL},
+ {(char *)"face_mark_left", (getter)FEdgeSharp_face_mark_left_get, (setter)FEdgeSharp_face_mark_left_set,
+ (char *)FEdgeSharp_face_mark_left_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_FEdgeSharp type definition ------------------------------*/
+
+PyTypeObject FEdgeSharp_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FEdgeSharp", /* tp_name */
+ sizeof(BPy_FEdgeSharp), /* 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 */
+ FEdgeSharp_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 */
+ BPy_FEdgeSharp_getseters, /* tp_getset */
+ &FEdge_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FEdgeSharp_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h
new file mode 100644
index 00000000000..f82dc352050
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_FEDGESHARP_H__
+#define __FREESTYLE_PYTHON_FEDGESHARP_H__
+
+#include "../BPy_FEdge.h"
+#include "../../../view_map/Silhouette.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FEdgeSharp_Type;
+
+#define BPy_FEdgeSharp_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&FEdgeSharp_Type))
+
+/*---------------------------Python BPy_FEdgeSharp structure definition----------*/
+typedef struct {
+ BPy_FEdge py_fe;
+ FEdgeSharp *fes;
+} BPy_FEdgeSharp;
+
+/*---------------------------Python BPy_FEdgeSharp visible prototypes-----------*/
+
+void FEdgeSharp_mathutils_register_callback();
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_FEDGESHARP_H__ */
diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp
new file mode 100644
index 00000000000..14b9b66b35c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp
@@ -0,0 +1,288 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_FEdgeSmooth.h"
+
+#include "../../BPy_Convert.h"
+#include "../../Interface0D/BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*----------------------FEdgeSmooth methods ----------------------------*/
+
+PyDoc_STRVAR(FEdgeSmooth_doc,
+"Class hierarchy: :class:`Interface1D` > :class:`FEdge` > :class:`FEdgeSmooth`\n"
+"\n"
+"Class defining a smooth edge. This kind of edge typically runs across\n"
+"a face of the input mesh. It can be a silhouette, a ridge or valley,\n"
+"a suggestive contour.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: An FEdgeSmooth object.\n"
+" :type brother: :class:`FEdgeSmooth`\n"
+"\n"
+".. method:: __init__(first_vertex, second_vertex)\n"
+"\n"
+" Builds an FEdgeSmooth going from the first to the second.\n"
+"\n"
+" :arg first_vertex: The first SVertex object.\n"
+" :type first_vertex: :class:`SVertex`\n"
+" :arg second_vertex: The second SVertex object.\n"
+" :type second_vertex: :class:`SVertex`");
+
+static int FEdgeSmooth_init(BPy_FEdgeSmooth *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"first_vertex", "second_vertex", NULL};
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &FEdgeSmooth_Type, &obj1)) {
+ if (!obj1)
+ self->fes = new FEdgeSmooth();
+ else
+ self->fes = new FEdgeSmooth(*(((BPy_FEdgeSmooth *)obj1)->fes));
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!O!", (char **)kwlist_2,
+ &SVertex_Type, &obj1, &SVertex_Type, &obj2))
+ {
+ self->fes = new FEdgeSmooth(((BPy_SVertex *)obj1)->sv, ((BPy_SVertex *)obj2)->sv);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->py_fe.fe = self->fes;
+ self->py_fe.py_if1D.if1D = self->fes;
+ self->py_fe.py_if1D.borrowed = 0;
+ return 0;
+}
+
+/*----------------------mathutils callbacks ----------------------------*/
+
+static int FEdgeSmooth_mathutils_check(BaseMathObject *bmo)
+{
+ if (!BPy_FEdgeSmooth_Check(bmo->cb_user))
+ return -1;
+ return 0;
+}
+
+static int FEdgeSmooth_mathutils_get(BaseMathObject *bmo, int subtype)
+{
+ BPy_FEdgeSmooth *self = (BPy_FEdgeSmooth *)bmo->cb_user;
+ Vec3r p(self->fes->normal());
+ bmo->data[0] = p[0];
+ bmo->data[1] = p[1];
+ bmo->data[2] = p[2];
+ return 0;
+}
+
+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]);
+ self->fes->setNormal(p);
+ return 0;
+}
+
+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());
+ bmo->data[index] = p[index];
+ return 0;
+}
+
+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());
+ p[index] = bmo->data[index];
+ self->fes->setNormal(p);
+ return 0;
+}
+
+static Mathutils_Callback FEdgeSmooth_mathutils_cb = {
+ FEdgeSmooth_mathutils_check,
+ FEdgeSmooth_mathutils_get,
+ FEdgeSmooth_mathutils_set,
+ FEdgeSmooth_mathutils_get_index,
+ FEdgeSmooth_mathutils_set_index
+};
+
+static unsigned char FEdgeSmooth_mathutils_cb_index = -1;
+
+void FEdgeSmooth_mathutils_register_callback()
+{
+ FEdgeSmooth_mathutils_cb_index = Mathutils_RegisterCallback(&FEdgeSmooth_mathutils_cb);
+}
+
+/*----------------------FEdgeSmooth get/setters ----------------------------*/
+
+PyDoc_STRVAR(FEdgeSmooth_normal_doc,
+"The normal of the face that this FEdge is running across.\n"
+"\n"
+":type: :class:`mathutils.Vector`");
+
+static PyObject *FEdgeSmooth_normal_get(BPy_FEdgeSmooth *self, void *UNUSED(closure))
+{
+ return Vector_CreatePyObject_cb((PyObject *)self, 3, FEdgeSmooth_mathutils_cb_index, 0);
+}
+
+static int FEdgeSmooth_normal_set(BPy_FEdgeSmooth *self, PyObject *value, void *UNUSED(closure))
+{
+ float v[3];
+ if (!float_array_from_PyObject(value, v, 3)) {
+ PyErr_SetString(PyExc_ValueError, "value must be a 3-dimensional vector");
+ return -1;
+ }
+ Vec3r p(v[0], v[1], v[2]);
+ self->fes->setNormal(p);
+ return 0;
+}
+
+PyDoc_STRVAR(FEdgeSmooth_material_index_doc,
+"The index of the material of the face that this FEdge is running across.\n"
+"\n"
+":type: int");
+
+static PyObject *FEdgeSmooth_material_index_get(BPy_FEdgeSmooth *self, void *UNUSED(closure))
+{
+ return PyLong_FromLong(self->fes->frs_materialIndex());
+}
+
+static int FEdgeSmooth_material_index_set(BPy_FEdgeSmooth *self, PyObject *value, void *UNUSED(closure))
+{
+ unsigned int i = PyLong_AsUnsignedLong(value);
+ if (PyErr_Occurred())
+ return -1;
+ self->fes->setFrsMaterialIndex(i);
+ return 0;
+}
+
+PyDoc_STRVAR(FEdgeSmooth_material_doc,
+"The material of the face that this FEdge is running across.\n"
+"\n"
+":type: :class:`Material`");
+
+static PyObject *FEdgeSmooth_material_get(BPy_FEdgeSmooth *self, void *UNUSED(closure))
+{
+ return BPy_FrsMaterial_from_FrsMaterial(self->fes->frs_material());
+}
+
+PyDoc_STRVAR(FEdgeSmooth_face_mark_doc,
+"The face mark of the face that this FEdge is running across.\n"
+"\n"
+":type: bool");
+
+static PyObject *FEdgeSmooth_face_mark_get(BPy_FEdgeSmooth *self, void *UNUSED(closure))
+{
+ return PyBool_from_bool(self->fes->faceMark());
+}
+
+static int FEdgeSmooth_face_mark_set(BPy_FEdgeSmooth *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!PyBool_Check(value))
+ return -1;
+ self->fes->setFaceMark(bool_from_PyBool(value));
+ return 0;
+}
+
+static PyGetSetDef BPy_FEdgeSmooth_getseters[] = {
+ {(char *)"normal", (getter)FEdgeSmooth_normal_get, (setter)FEdgeSmooth_normal_set,
+ (char *)FEdgeSmooth_normal_doc, NULL},
+ {(char *)"material_index", (getter)FEdgeSmooth_material_index_get, (setter)FEdgeSmooth_material_index_set,
+ (char *)FEdgeSmooth_material_index_doc, NULL},
+ {(char *)"material", (getter)FEdgeSmooth_material_get, (setter)NULL, (char *)FEdgeSmooth_material_doc, NULL},
+ {(char *)"face_mark", (getter)FEdgeSmooth_face_mark_get, (setter)FEdgeSmooth_face_mark_set,
+ (char *)FEdgeSmooth_face_mark_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_FEdgeSmooth type definition ------------------------------*/
+
+PyTypeObject FEdgeSmooth_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FEdgeSmooth", /* tp_name */
+ sizeof(BPy_FEdgeSmooth), /* 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 */
+ FEdgeSmooth_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 */
+ BPy_FEdgeSmooth_getseters, /* tp_getset */
+ &FEdge_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FEdgeSmooth_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h
new file mode 100644
index 00000000000..2484ef80e35
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_FEDGESMOOTH_H__
+#define __FREESTYLE_PYTHON_FEDGESMOOTH_H__
+
+#include "../BPy_FEdge.h"
+#include "../../../view_map/Silhouette.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FEdgeSmooth_Type;
+
+#define BPy_FEdgeSmooth_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&FEdgeSmooth_Type))
+
+/*---------------------------Python BPy_FEdgeSmooth structure definition----------*/
+typedef struct {
+ BPy_FEdge py_fe;
+ FEdgeSmooth *fes;
+} BPy_FEdgeSmooth;
+
+/*---------------------------Python BPy_FEdgeSmooth visible prototypes-----------*/
+
+void FEdgeSmooth_mathutils_register_callback();
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_FEDGESMOOTH_H__ */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp
new file mode 100644
index 00000000000..3f245692ac7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp
@@ -0,0 +1,196 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_AdjacencyIterator.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface0D/BPy_ViewVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+PyDoc_STRVAR(AdjacencyIterator_doc,
+"Class hierarchy: :class:`Iterator` > :class:`AdjacencyIterator`\n"
+"\n"
+"Class for representing adjacency iterators used in the chaining\n"
+"process. An AdjacencyIterator is created in the increment() and\n"
+"decrement() methods of a :class:`ChainingIterator` and passed to the\n"
+"traverse() method of the ChainingIterator.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: An AdjacencyIterator object.\n"
+" :type brother: :class:`AdjacencyIterator`\n"
+"\n"
+".. method:: __init__(vertex, restrict_to_selection=True, restrict_to_unvisited=True)\n"
+"\n"
+" Builds a AdjacencyIterator object.\n"
+"\n"
+" :arg vertex: The vertex which is the next crossing.\n"
+" :type vertex: :class:`ViewVertex`\n"
+" :arg restrict_to_selection: Indicates whether to force the chaining\n"
+" to stay within the set of selected ViewEdges or not.\n"
+" :type restrict_to_selection: bool\n"
+" :arg restrict_to_unvisited: Indicates whether a ViewEdge that has\n"
+" already been chained must be ignored ot not.\n"
+" :type restrict_to_unvisited: bool");
+
+static int AdjacencyIterator_init(BPy_AdjacencyIterator *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"vertex", "restrict_to_selection", "restrict_to_unvisited", NULL};
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &AdjacencyIterator_Type, &obj1)) {
+ if (!obj1)
+ self->a_it = new AdjacencyIterator();
+ else
+ self->a_it = new AdjacencyIterator(*(((BPy_AdjacencyIterator *)obj1)->a_it));
+ }
+ else if (PyErr_Clear(), (obj2 = obj3 = 0),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!|O!O!", (char **)kwlist_2,
+ &ViewVertex_Type, &obj1, &PyBool_Type, &obj2, &PyBool_Type, &obj3))
+ {
+ bool restrictToSelection = (!obj2) ? true : bool_from_PyBool(obj2);
+ bool restrictToUnvisited = (!obj3) ? true : bool_from_PyBool(obj3);
+ self->a_it = new AdjacencyIterator(((BPy_ViewVertex *)obj1)->vv, restrictToSelection, restrictToUnvisited);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->py_it.it = self->a_it;
+ return 0;
+}
+
+static PyObject *AdjacencyIterator_iternext(BPy_AdjacencyIterator *self)
+{
+ if (self->a_it->isEnd()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ ViewEdge *ve = self->a_it->operator*();
+ self->a_it->increment();
+ return BPy_ViewEdge_from_ViewEdge(*ve);
+}
+
+/*----------------------AdjacencyIterator get/setters ----------------------------*/
+
+PyDoc_STRVAR(AdjacencyIterator_object_doc,
+"The ViewEdge object currently pointed by this iterator.\n"
+"\n"
+":type: :class:`ViewEdge`");
+
+static PyObject *AdjacencyIterator_object_get(BPy_AdjacencyIterator *self, void *UNUSED(closure))
+{
+ ViewEdge *ve = self->a_it->operator*();
+ if (ve)
+ return BPy_ViewEdge_from_ViewEdge(*ve);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(AdjacencyIterator_is_incoming_doc,
+"True if the current ViewEdge is coming towards the iteration vertex, and\n"
+"False otherwise.\n"
+"\n"
+":type: bool");
+
+static PyObject *AdjacencyIterator_is_incoming_get(BPy_AdjacencyIterator *self, void *UNUSED(closure))
+{
+ return PyBool_from_bool(self->a_it->isIncoming());
+}
+
+static PyGetSetDef BPy_AdjacencyIterator_getseters[] = {
+ {(char *)"is_incoming", (getter)AdjacencyIterator_is_incoming_get, (setter)NULL,
+ (char *)AdjacencyIterator_is_incoming_doc, NULL},
+ {(char *)"object", (getter)AdjacencyIterator_object_get, (setter)NULL, (char *)AdjacencyIterator_object_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_AdjacencyIterator type definition ------------------------------*/
+
+PyTypeObject AdjacencyIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "AdjacencyIterator", /* tp_name */
+ sizeof(BPy_AdjacencyIterator), /* 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 */
+ AdjacencyIterator_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)AdjacencyIterator_iternext, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ BPy_AdjacencyIterator_getseters, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)AdjacencyIterator_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h
new file mode 100644
index 00000000000..d47a6f987e8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h
@@ -0,0 +1,63 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_ADJACENCYITERATOR_H__
+#define __FREESTYLE_PYTHON_ADJACENCYITERATOR_H__
+
+#include "../../stroke/ChainingIterators.h"
+#include "../BPy_Iterator.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject AdjacencyIterator_Type;
+
+#define BPy_AdjacencyIterator_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&AdjacencyIterator_Type))
+
+/*---------------------------Python BPy_AdjacencyIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ AdjacencyIterator *a_it;
+} BPy_AdjacencyIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_ADJACENCYITERATOR_H__ */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp
new file mode 100644
index 00000000000..987075024f0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp
@@ -0,0 +1,227 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ChainPredicateIterator.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_BinaryPredicate1D.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+PyDoc_STRVAR(ChainPredicateIterator_doc,
+"Class hierarchy: :class:`Iterator` > :class:`ViewEdgeIterator` > :class:`ChainingIterator` > "
+":class:`ChainPredicateIterator`\n"
+"\n"
+"A \"generic\" user-controlled ViewEdge iterator. This iterator is in\n"
+"particular built from a unary predicate and a binary predicate.\n"
+"First, the unary predicate is evaluated for all potential next\n"
+"ViewEdges in order to only keep the ones respecting a certain\n"
+"constraint. Then, the binary predicate is evaluated on the current\n"
+"ViewEdge together with each ViewEdge of the previous selection. The\n"
+"first ViewEdge respecting both the unary predicate and the binary\n"
+"predicate is kept as the next one. If none of the potential next\n"
+"ViewEdge respects these two predicates, None is returned.\n"
+"\n"
+".. method:: __init__(restrict_to_selection=True, restrict_to_unvisited=True, begin=None, orientation=True)\n"
+"\n"
+" Builds a ChainPredicateIterator from a starting ViewEdge and its\n"
+" orientation.\n"
+"\n"
+" :arg restrict_to_selection: Indicates whether to force the chaining\n"
+" to stay within the set of selected ViewEdges or not.\n"
+" :type restrict_to_selection: bool\n"
+" :arg restrict_to_unvisited: Indicates whether a ViewEdge that has\n"
+" already been chained must be ignored ot not.\n"
+" :type restrict_to_unvisited: bool\n"
+" :arg begin: The ViewEdge from where to start the iteration.\n"
+" :type begin: :class:`ViewEdge` or None\n"
+" :arg orientation: If true, we'll look for the next ViewEdge among\n"
+" the ViewEdges that surround the ending ViewVertex of begin. If\n"
+" false, we'll search over the ViewEdges surrounding the ending\n"
+" ViewVertex of begin. \n"
+" :type orientation: bool\n"
+"\n"
+".. method:: __init__(upred, bpred, restrict_to_selection=True, restrict_to_unvisited=True, begin=None, "
+"orientation=True)\n"
+"\n"
+" Builds a ChainPredicateIterator from a unary predicate, a binary\n"
+" predicate, a starting ViewEdge and its orientation.\n"
+"\n"
+" :arg upred: The unary predicate that the next ViewEdge must satisfy.\n"
+" :type upred: :class:`UnaryPredicate1D`\n"
+" :arg bpred: The binary predicate that the next ViewEdge must\n"
+" satisfy together with the actual pointed ViewEdge.\n"
+" :type bpred: :class:`BinaryPredicate1D`\n"
+" :arg restrict_to_selection: Indicates whether to force the chaining\n"
+" to stay within the set of selected ViewEdges or not.\n"
+" :type restrict_to_selection: bool\n"
+" :arg restrict_to_unvisited: Indicates whether a ViewEdge that has\n"
+" already been chained must be ignored ot not.\n"
+" :type restrict_to_unvisited: bool\n"
+" :arg begin: The ViewEdge from where to start the iteration.\n"
+" :type begin: :class:`ViewEdge` or None\n"
+" :arg orientation: If true, we'll look for the next ViewEdge among\n"
+" the ViewEdges that surround the ending ViewVertex of begin. If\n"
+" false, we'll search over the ViewEdges surrounding the ending\n"
+" ViewVertex of begin.\n"
+" :type orientation: bool\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A ChainPredicateIterator object.\n"
+" :type brother: :class:`ChainPredicateIterator`");
+
+static int check_begin(PyObject *obj, void *v)
+{
+ if (obj != 0 && obj != Py_None && !BPy_ViewEdge_Check(obj))
+ return 0;
+ *((PyObject **)v) = obj;
+ return 1;
+}
+
+static int ChainPredicateIterator_init(BPy_ChainPredicateIterator *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"upred", "bpred", "restrict_to_selection", "restrict_to_unvisited", "begin",
+ "orientation", NULL};
+ static const char *kwlist_3[] = {"restrict_to_selection", "restrict_to_unvisited", "begin", "orientation", NULL};
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0, *obj4 = 0, *obj5 = 0, *obj6 = 0;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist_1, &ChainingIterator_Type, &obj1)) {
+ self->cp_it = new ChainPredicateIterator(*(((BPy_ChainPredicateIterator *)obj1)->cp_it));
+ }
+ else if (PyErr_Clear(), (obj3 = obj4 = obj5 = obj6 = 0),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!O!|O!O!O&O!", (char **)kwlist_2,
+ &UnaryPredicate1D_Type, &obj1, &BinaryPredicate1D_Type, &obj2,
+ &PyBool_Type, &obj3, &PyBool_Type, &obj4, check_begin, &obj5,
+ &PyBool_Type, &obj6))
+ {
+ UnaryPredicate1D *up1D = ((BPy_UnaryPredicate1D *)obj1)->up1D;
+ BinaryPredicate1D *bp1D = ((BPy_BinaryPredicate1D *)obj2)->bp1D;
+ bool restrict_to_selection = (!obj3) ? true : bool_from_PyBool(obj3);
+ bool restrict_to_unvisited = (!obj4) ? true : bool_from_PyBool(obj4);
+ ViewEdge *begin = (!obj5 || obj5 == Py_None) ? NULL : ((BPy_ViewEdge *)obj5)->ve;
+ bool orientation = (!obj6) ? true : bool_from_PyBool(obj6);
+ self->cp_it = new ChainPredicateIterator(*up1D, *bp1D, restrict_to_selection, restrict_to_unvisited, begin,
+ orientation);
+ self->upred = obj1;
+ self->bpred = obj2;
+ Py_INCREF(self->upred);
+ Py_INCREF(self->bpred);
+ }
+ else if (PyErr_Clear(), (obj1 = obj2 = obj3 = obj4 = 0),
+ PyArg_ParseTupleAndKeywords(args, kwds, "|O!O!O&O!", (char **)kwlist_3,
+ &PyBool_Type, &obj1, &PyBool_Type, &obj2, check_begin, &obj3,
+ &PyBool_Type, &obj4))
+ {
+ bool restrict_to_selection = (!obj1) ? true : bool_from_PyBool(obj1);
+ bool restrict_to_unvisited = (!obj2) ? true : bool_from_PyBool(obj2);
+ ViewEdge *begin = (!obj3 || obj3 == Py_None) ? NULL : ((BPy_ViewEdge *)obj3)->ve;
+ bool orientation = (!obj4) ? true : bool_from_PyBool(obj4);
+ self->cp_it = new ChainPredicateIterator(restrict_to_selection, restrict_to_unvisited, begin, orientation);
+ self->upred = NULL;
+ self->bpred = NULL;
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->py_c_it.c_it = self->cp_it;
+ self->py_c_it.py_ve_it.ve_it = self->cp_it;
+ self->py_c_it.py_ve_it.py_it.it = self->cp_it;
+ return 0;
+}
+
+static void ChainPredicateIterator_dealloc(BPy_ChainPredicateIterator *self)
+{
+ Py_XDECREF(self->upred);
+ Py_XDECREF(self->bpred);
+ ChainingIterator_Type.tp_dealloc((PyObject *)self);
+}
+
+/*-----------------------BPy_ChainPredicateIterator type definition ------------------------------*/
+
+PyTypeObject ChainPredicateIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ChainPredicateIterator", /* tp_name */
+ sizeof(BPy_ChainPredicateIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)ChainPredicateIterator_dealloc, /* 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 */
+ ChainPredicateIterator_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 */
+ &ChainingIterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ChainPredicateIterator_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h
new file mode 100644
index 00000000000..c69d1ad1a7b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_CHAINPREDICATEITERATOR_H__
+#define __FREESTYLE_PYTHON_CHAINPREDICATEITERATOR_H__
+
+
+#include "../../stroke/ChainingIterators.h"
+
+#include "BPy_ChainingIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ChainPredicateIterator_Type;
+
+#define BPy_ChainPredicateIterator_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&ChainPredicateIterator_Type))
+
+/*---------------------------Python BPy_ChainPredicateIterator structure definition----------*/
+typedef struct {
+ BPy_ChainingIterator py_c_it;
+ ChainPredicateIterator *cp_it;
+ PyObject *upred;
+ PyObject *bpred;
+} BPy_ChainPredicateIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_CHAINPREDICATEITERATOR_H__ */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp
new file mode 100644
index 00000000000..80b417d5e74
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp
@@ -0,0 +1,165 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ChainSilhouetteIterator.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+// ChainSilhouetteIterator (bool restrict_to_selection=true, ViewEdge *begin=NULL, bool orientation=true)
+// ChainSilhouetteIterator (const ChainSilhouetteIterator &brother)
+
+PyDoc_STRVAR(ChainSilhouetteIterator_doc,
+"Class hierarchy: :class:`Iterator` > :class:`ViewEdgeIterator` > :class:`ChainingIterator` > "
+":class:`ChainSilhouetteIterator`\n"
+"\n"
+"A ViewEdge Iterator used to follow ViewEdges the most naturally. For\n"
+"example, it will follow visible ViewEdges of same nature. As soon, as\n"
+"the nature or the visibility changes, the iteration stops (by setting\n"
+"the pointed ViewEdge to 0). In the case of an iteration over a set of\n"
+"ViewEdge that are both Silhouette and Crease, there will be a\n"
+"precedence of the silhouette over the crease criterion.\n"
+"\n"
+".. method:: __init__(restrict_to_selection=True, begin=None, orientation=True)\n"
+"\n"
+" Builds a ChainSilhouetteIterator from the first ViewEdge used for\n"
+" iteration and its orientation.\n"
+"\n"
+" :arg restrict_to_selection: Indicates whether to force the chaining\n"
+" to stay within the set of selected ViewEdges or not.\n"
+" :type restrict_to_selection: bool\n"
+" :arg begin: The ViewEdge from where to start the iteration.\n"
+" :type begin: :class:`ViewEdge` or None\n"
+" :arg orientation: If true, we'll look for the next ViewEdge among\n"
+" the ViewEdges that surround the ending ViewVertex of begin. If\n"
+" false, we'll search over the ViewEdges surrounding the ending\n"
+" ViewVertex of begin.\n"
+" :type orientation: bool\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A ChainSilhouetteIterator object.\n"
+" :type brother: :class:`ChainSilhouetteIterator`");
+
+static int check_begin(PyObject *obj, void *v)
+{
+ if (obj != 0 && obj != Py_None && !BPy_ViewEdge_Check(obj))
+ return 0;
+ *((PyObject **)v) = obj;
+ return 1;
+}
+
+static int ChainSilhouetteIterator_init(BPy_ChainSilhouetteIterator *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"restrict_to_selection", "begin", "orientation", NULL};
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist_1, &ChainSilhouetteIterator_Type, &obj1)) {
+ self->cs_it = new ChainSilhouetteIterator(*(((BPy_ChainSilhouetteIterator *)obj1)->cs_it));
+ }
+ else if (PyErr_Clear(), (obj1 = obj2 = obj3 = 0),
+ PyArg_ParseTupleAndKeywords(args, kwds, "|O!O&O!", (char **)kwlist_2,
+ &PyBool_Type, &obj1, check_begin, &obj2, &PyBool_Type, &obj3))
+ {
+ bool restrict_to_selection = (!obj1) ? true : bool_from_PyBool(obj1);
+ ViewEdge *begin = (!obj2 || obj2 == Py_None) ? NULL : ((BPy_ViewEdge *)obj2)->ve;
+ bool orientation = (!obj3) ? true : bool_from_PyBool(obj3);
+ self->cs_it = new ChainSilhouetteIterator(restrict_to_selection, begin, orientation);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->py_c_it.c_it = self->cs_it;
+ self->py_c_it.py_ve_it.ve_it = self->cs_it;
+ self->py_c_it.py_ve_it.py_it.it = self->cs_it;
+ return 0;
+}
+
+/*-----------------------BPy_ChainSilhouetteIterator type definition ------------------------------*/
+
+PyTypeObject ChainSilhouetteIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ChainSilhouetteIterator", /* tp_name */
+ sizeof(BPy_ChainSilhouetteIterator), /* 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 */
+ ChainSilhouetteIterator_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 */
+ &ChainingIterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ChainSilhouetteIterator_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h
new file mode 100644
index 00000000000..acc410b64a6
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h
@@ -0,0 +1,65 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_CHAINSILHOUETTEITERATOR_H__
+#define __FREESTYLE_PYTHON_CHAINSILHOUETTEITERATOR_H__
+
+
+#include "../../stroke/ChainingIterators.h"
+
+#include "BPy_ChainingIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ChainSilhouetteIterator_Type;
+
+#define BPy_ChainSilhouetteIterator_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&ChainSilhouetteIterator_Type))
+
+/*---------------------------Python BPy_ChainSilhouetteIterator structure definition----------*/
+typedef struct {
+ BPy_ChainingIterator py_c_it;
+ ChainSilhouetteIterator *cs_it;
+} BPy_ChainSilhouetteIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_CHAINSILHOUETTEITERATOR_H__ */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp
new file mode 100644
index 00000000000..d193c0aa70b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp
@@ -0,0 +1,272 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ChainingIterator.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface0D/BPy_ViewVertex.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+#include "BPy_AdjacencyIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+PyDoc_STRVAR(ChainingIterator_doc,
+"Class hierarchy: :class:`Iterator` > :class:`ViewEdgeIterator` > :class:`ChainingIterator`\n"
+"\n"
+"Base class for chaining iterators. This class is designed to be\n"
+"overloaded in order to describe chaining rules. It makes the\n"
+"description of chaining rules easier. The two main methods that need\n"
+"to overloaded are traverse() and init(). traverse() tells which\n"
+":class:`ViewEdge` to follow, among the adjacent ones. If you specify\n"
+"restriction rules (such as \"Chain only ViewEdges of the selection\"),\n"
+"they will be included in the adjacency iterator (i.e, the adjacent\n"
+"iterator will only stop on \"valid\" edges).\n"
+"\n"
+".. method:: __init__(restrict_to_selection=True, restrict_to_unvisited=True, begin=None, orientation=True)\n"
+"\n"
+" Builds a Chaining Iterator from the first ViewEdge used for\n"
+" iteration and its orientation.\n"
+"\n"
+" :arg restrict_to_selection: Indicates whether to force the chaining\n"
+" to stay within the set of selected ViewEdges or not.\n"
+" :type restrict_to_selection: bool\n"
+" :arg restrict_to_unvisited: Indicates whether a ViewEdge that has\n"
+" already been chained must be ignored ot not.\n"
+" :type restrict_to_unvisited: bool\n"
+" :arg begin: The ViewEdge from which to start the chain.\n"
+" :type begin: :class:`ViewEdge` or None\n"
+" :arg orientation: The direction to follow to explore the graph. If\n"
+" true, the direction indicated by the first ViewEdge is used.\n"
+" :type orientation: bool\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: \n"
+" :type brother: ChainingIterator");
+
+static int check_begin(PyObject *obj, void *v)
+{
+ if (obj != 0 && obj != Py_None && !BPy_ViewEdge_Check(obj))
+ return 0;
+ *((PyObject **)v) = obj;
+ return 1;
+}
+
+static int ChainingIterator___init__(BPy_ChainingIterator *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"restrict_to_selection", "restrict_to_unvisited", "begin", "orientation", NULL};
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0, *obj4 = 0;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist_1, &ChainingIterator_Type, &obj1)) {
+ self->c_it = new ChainingIterator(*(((BPy_ChainingIterator *)obj1)->c_it));
+ }
+ else if (PyErr_Clear(), (obj1 = obj2 = obj3 = obj4 = 0),
+ PyArg_ParseTupleAndKeywords(args, kwds, "|O!O!O&O!", (char **)kwlist_2,
+ &PyBool_Type, &obj1, &PyBool_Type, &obj2, check_begin, &obj3,
+ &PyBool_Type, &obj4))
+ {
+ bool restrict_to_selection = (!obj1) ? true : bool_from_PyBool(obj1);
+ bool restrict_to_unvisited = (!obj2) ? true : bool_from_PyBool(obj2);
+ ViewEdge *begin = (!obj3 || obj3 == Py_None) ? NULL : ((BPy_ViewEdge *)obj3)->ve;
+ bool orientation = (!obj4) ? true : bool_from_PyBool(obj4);
+ self->c_it = new ChainingIterator(restrict_to_selection, restrict_to_unvisited, begin, orientation);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->py_ve_it.ve_it = self->c_it;
+ self->py_ve_it.py_it.it = self->c_it;
+
+ self->c_it->py_c_it = (PyObject *)self;
+
+ return 0;
+}
+
+PyDoc_STRVAR(ChainingIterator_init_doc,
+".. method:: init()\n"
+"\n"
+" Initializes the iterator context. This method is called each\n"
+" time a new chain is started. It can be used to reset some\n"
+" history information that you might want to keep.");
+
+static PyObject *ChainingIterator_init(BPy_ChainingIterator *self)
+{
+ if (typeid(*(self->c_it)) == typeid(ChainingIterator)) {
+ PyErr_SetString(PyExc_TypeError, "init() method not properly overridden");
+ return NULL;
+ }
+ self->c_it->init();
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(ChainingIterator_traverse_doc,
+".. method:: traverse(it)\n"
+"\n"
+" This method iterates over the potential next ViewEdges and returns\n"
+" the one that will be followed next. Returns the next ViewEdge to\n"
+" follow or None when the end of the chain is reached.\n"
+"\n"
+" :arg it: The iterator over the ViewEdges adjacent to the end vertex\n"
+" of the current ViewEdge. The adjacency iterator reflects the\n"
+" restriction rules by only iterating over the valid ViewEdges.\n"
+" :type it: :class:`AdjacencyIterator`\n"
+" :return: Returns the next ViewEdge to follow, or None if chaining ends.\n"
+" :rtype: :class:`ViewEdge` or None");
+
+static PyObject *ChainingIterator_traverse(BPy_ChainingIterator *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"it", NULL};
+ PyObject *py_a_it;
+
+ if (typeid(*(self->c_it)) == typeid(ChainingIterator)) {
+ PyErr_SetString(PyExc_TypeError, "traverse() method not properly overridden");
+ return NULL;
+ }
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &AdjacencyIterator_Type, &py_a_it))
+ return NULL;
+ if (((BPy_AdjacencyIterator *)py_a_it)->a_it)
+ self->c_it->traverse(*(((BPy_AdjacencyIterator *)py_a_it)->a_it));
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef BPy_ChainingIterator_methods[] = {
+ {"init", (PyCFunction) ChainingIterator_init, METH_NOARGS, ChainingIterator_init_doc},
+ {"traverse", (PyCFunction) ChainingIterator_traverse, METH_VARARGS | METH_KEYWORDS, ChainingIterator_traverse_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------ChainingIterator get/setters ----------------------------*/
+
+PyDoc_STRVAR(ChainingIterator_object_doc,
+"The ViewEdge object currently pointed by this iterator.\n"
+"\n"
+":type: :class:`ViewEdge`");
+
+static PyObject *ChainingIterator_object_get(BPy_ChainingIterator *self, void *UNUSED(closure))
+{
+ ViewEdge *ve = self->c_it->operator*();
+ if (ve)
+ return BPy_ViewEdge_from_ViewEdge(*ve);
+
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(ChainingIterator_next_vertex_doc,
+"The ViewVertex that is the next crossing.\n"
+"\n"
+":type: :class:`ViewVertex`");
+
+static PyObject *ChainingIterator_next_vertex_get(BPy_ChainingIterator *self, void *UNUSED(closure))
+{
+ ViewVertex *v = self->c_it->getVertex();
+ if (v)
+ return Any_BPy_ViewVertex_from_ViewVertex(*v);
+
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(ChainingIterator_is_incrementing_doc,
+"True if the current iteration is an incrementation.\n"
+"\n"
+":type: bool");
+
+static PyObject *ChainingIterator_is_incrementing_get(BPy_ChainingIterator *self, void *UNUSED(closure))
+{
+ return PyBool_from_bool(self->c_it->isIncrementing());
+}
+
+static PyGetSetDef BPy_ChainingIterator_getseters[] = {
+ {(char *)"object", (getter)ChainingIterator_object_get, (setter)NULL, (char *)ChainingIterator_object_doc, NULL},
+ {(char *)"next_vertex", (getter)ChainingIterator_next_vertex_get, (setter)NULL,
+ (char *)ChainingIterator_next_vertex_doc, NULL},
+ {(char *)"is_incrementing", (getter)ChainingIterator_is_incrementing_get, (setter)NULL,
+ (char *)ChainingIterator_is_incrementing_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_ChainingIterator type definition ------------------------------*/
+
+PyTypeObject ChainingIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ChainingIterator", /* tp_name */
+ sizeof(BPy_ChainingIterator), /* 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 */
+ ChainingIterator_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ChainingIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_ChainingIterator_getseters, /* tp_getset */
+ &ViewEdgeIterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ChainingIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h
new file mode 100644
index 00000000000..b791e96a10c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h
@@ -0,0 +1,64 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_CHAININGITERATOR_H__
+#define __FREESTYLE_PYTHON_CHAININGITERATOR_H__
+
+
+#include "../../stroke/ChainingIterators.h"
+
+#include "BPy_ViewEdgeIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ChainingIterator_Type;
+
+#define BPy_ChainingIterator_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ChainingIterator_Type))
+
+/*---------------------------Python BPy_ChainingIterator structure definition----------*/
+typedef struct {
+ BPy_ViewEdgeIterator py_ve_it;
+ ChainingIterator *c_it;
+} BPy_ChainingIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_CHAININGITERATOR_H__ */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp
new file mode 100644
index 00000000000..07d74bf2264
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp
@@ -0,0 +1,185 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_CurvePointIterator.h"
+
+#include "../BPy_Convert.h"
+#include "BPy_Interface0DIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+PyDoc_STRVAR(CurvePointIterator_doc,
+"Class hierarchy: :class:`Iterator` > :class:`CurvePointIterator`\n"
+"\n"
+"Class representing an iterator on a curve. Allows an iterating\n"
+"outside initial vertices. A CurvePoint is instanciated and returned\n"
+"through the .object attribute.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A CurvePointIterator object.\n"
+" :type brother: :class:`CurvePointIterator`\n"
+"\n"
+".. method:: __init__(step=0.0)\n"
+"\n"
+" Builds a CurvePointIterator object.\n"
+"\n"
+" :arg step: A resampling resolution with which the curve is resampled.\n"
+" If zero, no resampling is done (i.e., the iterator iterates over\n"
+" initial vertices).\n"
+" :type step: float");
+
+static int CurvePointIterator_init(BPy_CurvePointIterator *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"step", NULL};
+ PyObject *brother = 0;
+ float step;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &CurvePointIterator_Type, &brother)) {
+ if (!brother)
+ self->cp_it = new CurveInternal::CurvePointIterator();
+ else
+ self->cp_it = new CurveInternal::CurvePointIterator(*(((BPy_CurvePointIterator *)brother)->cp_it));
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "f", (char **)kwlist_2, &step))
+ {
+ self->cp_it = new CurveInternal::CurvePointIterator(step);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->py_it.it = self->cp_it;
+ return 0;
+}
+
+/*----------------------CurvePointIterator get/setters ----------------------------*/
+
+PyDoc_STRVAR(CurvePointIterator_object_doc,
+"The CurvePoint object currently pointed by this iterator.\n"
+"\n"
+":type: :class:`CurvePoint`");
+
+static PyObject *CurvePointIterator_object_get(BPy_CurvePointIterator *self, void *UNUSED(closure))
+{
+ return BPy_CurvePoint_from_CurvePoint(self->cp_it->operator*());
+}
+
+PyDoc_STRVAR(CurvePointIterator_t_doc,
+"The curvilinear abscissa of the current point.\n"
+"\n"
+":type: float");
+
+static PyObject *CurvePointIterator_t_get(BPy_CurvePointIterator *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->cp_it->t());
+}
+
+PyDoc_STRVAR(CurvePointIterator_u_doc,
+"The point parameter at the current point in the stroke (0 <= u <= 1).\n"
+"\n"
+":type: float");
+
+static PyObject *CurvePointIterator_u_get(BPy_CurvePointIterator *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->cp_it->u());
+}
+
+static PyGetSetDef BPy_CurvePointIterator_getseters[] = {
+ {(char *)"object", (getter)CurvePointIterator_object_get, (setter)NULL,
+ (char *)CurvePointIterator_object_doc, NULL},
+ {(char *)"t", (getter)CurvePointIterator_t_get, (setter)NULL, (char *)CurvePointIterator_t_doc, NULL},
+ {(char *)"u", (getter)CurvePointIterator_u_get, (setter)NULL, (char *)CurvePointIterator_u_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_CurvePointIterator type definition ------------------------------*/
+
+PyTypeObject CurvePointIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "CurvePointIterator", /* tp_name */
+ sizeof(BPy_CurvePointIterator), /* 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 */
+ CurvePointIterator_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 */
+ BPy_CurvePointIterator_getseters, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)CurvePointIterator_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h
new file mode 100644
index 00000000000..65b736aee12
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h
@@ -0,0 +1,63 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_CURVEPOINTITERATOR_H__
+#define __FREESTYLE_PYTHON_CURVEPOINTITERATOR_H__
+
+#include "../../stroke/CurveIterators.h"
+
+#include "../BPy_Iterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject CurvePointIterator_Type;
+
+#define BPy_CurvePointIterator_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&CurvePointIterator_Type))
+
+/*---------------------------Python BPy_CurvePointIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ CurveInternal::CurvePointIterator *cp_it;
+} BPy_CurvePointIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_CURVEPOINTITERATOR_H__ */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
new file mode 100644
index 00000000000..f589802b0a5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
@@ -0,0 +1,211 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_Interface0DIterator.h"
+
+#include "../BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+PyDoc_STRVAR(Interface0DIterator_doc,
+"Class hierarchy: :class:`Iterator` > :class:`Interface0DIterator`\n"
+"\n"
+"Class defining an iterator over Interface0D elements. An instance of\n"
+"this iterator is always obtained from a 1D element.\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: An Interface0DIterator object.\n"
+" :type brother: :class:`Interface0DIterator`\n"
+"\n"
+".. method:: __init__(it)\n"
+"\n"
+" Construct a nested Interface0DIterator that can be the argument of\n"
+" a Function0D.\n"
+"\n"
+" :arg it: An iterator object to be nested.\n"
+" :type it: :class:`SVertexIterator`, :class:`CurvePointIterator`, or\n"
+" :class:`StrokeVertexIterator`");
+
+static int convert_nested_it(PyObject *obj, void *v)
+{
+ if (!obj || !BPy_Iterator_Check(obj))
+ return 0;
+ Interface0DIteratorNested *nested_it = dynamic_cast<Interface0DIteratorNested *>(((BPy_Iterator *)obj)->it);
+ if (!nested_it)
+ return 0;
+ *((Interface0DIteratorNested **)v) = nested_it;
+ return 1;
+}
+
+static int Interface0DIterator_init(BPy_Interface0DIterator *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"it", NULL};
+ static const char *kwlist_2[] = {"brother", NULL};
+ Interface0DIteratorNested *nested_it;
+ PyObject *brother;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", (char **)kwlist_1, convert_nested_it, &nested_it)) {
+ self->if0D_it = new Interface0DIterator(nested_it->copy());
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist_2, &Interface0DIterator_Type, &brother))
+ {
+ self->if0D_it = new Interface0DIterator(*(((BPy_Interface0DIterator *)brother)->if0D_it));
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->py_it.it = self->if0D_it;
+ self->reversed = 0;
+ return 0;
+}
+
+static PyObject *Interface0DIterator_iternext(BPy_Interface0DIterator *self)
+{
+ Interface0D *if0D;
+
+ if (self->reversed) {
+ if (self->if0D_it->isBegin()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ self->if0D_it->decrement();
+ if0D = self->if0D_it->operator->();
+ }
+ else {
+ if (self->if0D_it->isEnd()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ if0D = self->if0D_it->operator->();
+ self->if0D_it->increment();
+ }
+ return Any_BPy_Interface0D_from_Interface0D(*if0D);
+}
+
+/*----------------------Interface0DIterator get/setters ----------------------------*/
+
+PyDoc_STRVAR(Interface0DIterator_object_doc,
+"The Interface0D object currently pointed by this iterator.\n"
+"\n"
+":type: :class:`Interface0D`");
+
+static PyObject *Interface0DIterator_object_get(BPy_Interface0DIterator *self, void *UNUSED(closure))
+{
+ return Any_BPy_Interface0D_from_Interface0D(self->if0D_it->operator*());
+}
+
+PyDoc_STRVAR(Interface0DIterator_t_doc,
+"The curvilinear abscissa of the current point.\n"
+"\n"
+":type: float");
+
+static PyObject *Interface0DIterator_t_get(BPy_Interface0DIterator *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->if0D_it->t());
+}
+
+PyDoc_STRVAR(Interface0DIterator_u_doc,
+"The point parameter at the current point in the 1D element (0 <= u <= 1).\n"
+"\n"
+":type: float");
+
+static PyObject *Interface0DIterator_u_get(BPy_Interface0DIterator *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->if0D_it->u());
+}
+
+static PyGetSetDef BPy_Interface0DIterator_getseters[] = {
+ {(char *)"object", (getter)Interface0DIterator_object_get, (setter)NULL,
+ (char *)Interface0DIterator_object_doc, NULL},
+ {(char *)"t", (getter)Interface0DIterator_t_get, (setter)NULL, (char *)Interface0DIterator_t_doc, NULL},
+ {(char *)"u", (getter)Interface0DIterator_u_get, (setter)NULL, (char *)Interface0DIterator_u_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_Interface0DIterator type definition ------------------------------*/
+
+PyTypeObject Interface0DIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Interface0DIterator", /* tp_name */
+ sizeof(BPy_Interface0DIterator), /* 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 */
+ Interface0DIterator_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)Interface0DIterator_iternext, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ BPy_Interface0DIterator_getseters, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Interface0DIterator_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h
new file mode 100644
index 00000000000..72e827fce49
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h
@@ -0,0 +1,64 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_INTERFACE0DITERATOR_H__
+#define __FREESTYLE_PYTHON_INTERFACE0DITERATOR_H__
+
+#include "../../view_map/Interface0D.h"
+#include "../BPy_Iterator.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Interface0DIterator_Type;
+
+#define BPy_Interface0DIterator_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Interface0DIterator_Type))
+
+/*---------------------------Python BPy_Interface0DIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ Interface0DIterator *if0D_it;
+ int reversed;
+} BPy_Interface0DIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_INTERFACE0DITERATOR_H__ */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp
new file mode 100644
index 00000000000..5f9740e5709
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp
@@ -0,0 +1,205 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_SVertexIterator.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface0D/BPy_SVertex.h"
+#include "../Interface1D/BPy_FEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+PyDoc_STRVAR(SVertexIterator_doc,
+"Class hierarchy: :class:`Iterator` > :class:`SVertexIterator`\n"
+"\n"
+"Class representing an iterator over :class:`SVertex` of a\n"
+":class:`ViewEdge`. An instance of an SVertexIterator can be obtained\n"
+"from a ViewEdge by calling verticesBegin() or verticesEnd().\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: An SVertexIterator object.\n"
+" :type brother: :class:`SVertexIterator`\n"
+"\n"
+".. method:: __init__(vertex, begin, previous_edge, next_edge, t)\n"
+"\n"
+" Build an SVertexIterator that starts iteration from an SVertex\n"
+" object v.\n"
+"\n"
+" :arg vertex: The SVertex from which the iterator starts iteration.\n"
+" :type vertex: :class:`SVertex`\n"
+" :arg begin: The first SVertex of a ViewEdge.\n"
+" :type begin: :class:`SVertex`\n"
+" :arg previous_edge: The previous FEdge coming to vertex.\n"
+" :type previous_edge: :class:`FEdge`\n"
+" :arg next_edge: The next FEdge going out from vertex.\n"
+" :type next_edge: :class:`FEdge`\n"
+" :arg t: The curvilinear abscissa at vertex.\n"
+" :type t: float");
+
+static int SVertexIterator_init(BPy_SVertexIterator *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"vertex", "begin", "previous_edge", "next_edge", "t", NULL};
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0, *obj4 = 0;
+ float t;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist_1, &SVertexIterator_Type, &obj1)) {
+ if (!obj1)
+ self->sv_it = new ViewEdgeInternal::SVertexIterator();
+ else
+ self->sv_it = new ViewEdgeInternal::SVertexIterator(*(((BPy_SVertexIterator *)obj1)->sv_it));
+ }
+ else if (PyErr_Clear(),
+ PyArg_ParseTupleAndKeywords(args, kwds, "O!O!O!O!f", (char **)kwlist_2,
+ &SVertex_Type, &obj1,
+ &SVertex_Type, &obj2,
+ &FEdge_Type, &obj3,
+ &FEdge_Type, &obj4,
+ &t))
+ {
+ self->sv_it = new ViewEdgeInternal::SVertexIterator(
+ ((BPy_SVertex *)obj1)->sv,
+ ((BPy_SVertex *)obj2)->sv,
+ ((BPy_FEdge *)obj3)->fe,
+ ((BPy_FEdge *)obj4)->fe,
+ t);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->py_it.it = self->sv_it;
+ return 0;
+}
+
+/*----------------------SVertexIterator get/setters ----------------------------*/
+
+PyDoc_STRVAR(SVertexIterator_object_doc,
+"The SVertex object currently pointed by this iterator.\n"
+"\n"
+":type: :class:`SVertex`");
+
+static PyObject *SVertexIterator_object_get(BPy_SVertexIterator *self, void *UNUSED(closure))
+{
+ SVertex *sv = self->sv_it->operator->();
+ if (sv)
+ return BPy_SVertex_from_SVertex(*sv);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(SVertexIterator_t_doc,
+"The curvilinear abscissa of the current point.\n"
+"\n"
+":type: float");
+
+static PyObject *SVertexIterator_t_get(BPy_SVertexIterator *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->sv_it->t());
+}
+
+PyDoc_STRVAR(SVertexIterator_u_doc,
+"The point parameter at the current point in the 1D element (0 <= u <= 1).\n"
+"\n"
+":type: float");
+
+static PyObject *SVertexIterator_u_get(BPy_SVertexIterator *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->sv_it->u());
+}
+
+static PyGetSetDef BPy_SVertexIterator_getseters[] = {
+ {(char *)"object", (getter)SVertexIterator_object_get, (setter)NULL, (char *)SVertexIterator_object_doc, NULL},
+ {(char *)"t", (getter)SVertexIterator_t_get, (setter)NULL, (char *)SVertexIterator_t_doc, NULL},
+ {(char *)"u", (getter)SVertexIterator_u_get, (setter)NULL, (char *)SVertexIterator_u_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_SVertexIterator type definition ------------------------------*/
+
+PyTypeObject SVertexIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SVertexIterator", /* tp_name */
+ sizeof(BPy_SVertexIterator), /* 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 */
+ SVertexIterator_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 */
+ BPy_SVertexIterator_getseters, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SVertexIterator_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h
new file mode 100644
index 00000000000..435559e6b44
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h
@@ -0,0 +1,64 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_SVERTEXITERATOR_H__
+#define __FREESTYLE_PYTHON_SVERTEXITERATOR_H__
+
+#include "../../view_map/ViewMapIterators.h"
+
+#include "../BPy_Iterator.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SVertexIterator_Type;
+
+#define BPy_SVertexIterator_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&SVertexIterator_Type))
+
+/*---------------------------Python BPy_SVertexIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ ViewEdgeInternal::SVertexIterator *sv_it;
+} BPy_SVertexIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_SVERTEXITERATOR_H__ */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
new file mode 100644
index 00000000000..889e29b6f42
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
@@ -0,0 +1,202 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_StrokeVertexIterator.h"
+
+#include "../BPy_Convert.h"
+#include "BPy_Interface0DIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+PyDoc_STRVAR(StrokeVertexIterator_doc,
+"Class hierarchy: :class:`Iterator` > :class:`StrokeVertexIterator`\n"
+"\n"
+"Class defining an iterator designed to iterate over the\n"
+":class:`StrokeVertex` of a :class:`Stroke`. An instance of a\n"
+"StrokeVertexIterator can only be obtained from a Stroke by calling\n"
+"strokeVerticesBegin() or strokeVerticesEnd(). It is iterating over\n"
+"the same vertices as an :class:`Interface0DIterator`. The difference\n"
+"resides in the object access. Indeed, an Interface0DIterator allows\n"
+"only an access to an Interface0D whereas we could need to access the\n"
+"specialized StrokeVertex type. In this case, one should use a\n"
+"StrokeVertexIterator. The castToInterface0DIterator() method is\n"
+"useful to get an Interface0DIterator from a StrokeVertexIterator in\n"
+"order to call any functions of the UnaryFunction0D type.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A StrokeVertexIterator object.\n"
+" :type brother: :class:`StrokeVertexIterator`");
+
+static int StrokeVertexIterator_init(BPy_StrokeVertexIterator *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"brother", NULL};
+ PyObject *brother = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &StrokeVertexIterator_Type, &brother))
+ return -1;
+ if (!brother)
+ self->sv_it = new StrokeInternal::StrokeVertexIterator();
+ else
+ self->sv_it = new StrokeInternal::StrokeVertexIterator(*(((BPy_StrokeVertexIterator *)brother)->sv_it));
+ self->py_it.it = self->sv_it;
+ self->reversed = 0;
+ return 0;
+}
+
+static PyObject *StrokeVertexIterator_iternext(BPy_StrokeVertexIterator *self)
+{
+ StrokeVertex *sv;
+
+ if (self->reversed) {
+ if (self->sv_it->isBegin()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ self->sv_it->decrement();
+ sv = self->sv_it->operator->();
+ }
+ else {
+ if (self->sv_it->isEnd()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ sv = self->sv_it->operator->();
+ self->sv_it->increment();
+ }
+ return BPy_StrokeVertex_from_StrokeVertex(*sv);
+}
+
+/*----------------------StrokeVertexIterator get/setters ----------------------------*/
+
+PyDoc_STRVAR(StrokeVertexIterator_object_doc,
+"The StrokeVertex object currently pointed by this iterator.\n"
+"\n"
+":type: :class:`StrokeVertex`");
+
+static PyObject *StrokeVertexIterator_object_get(BPy_StrokeVertexIterator *self, void *UNUSED(closure))
+{
+ if (!self->reversed && self->sv_it->isEnd())
+ Py_RETURN_NONE;
+ StrokeVertex *sv = self->sv_it->operator->();
+ if (sv)
+ return BPy_StrokeVertex_from_StrokeVertex(*sv);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(StrokeVertexIterator_t_doc,
+"The curvilinear abscissa of the current point.\n"
+"\n"
+":type: float");
+
+static PyObject *StrokeVertexIterator_t_get(BPy_StrokeVertexIterator *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->sv_it->t());
+}
+
+PyDoc_STRVAR(StrokeVertexIterator_u_doc,
+"The point parameter at the current point in the stroke (0 <= u <= 1).\n"
+"\n"
+":type: float");
+
+static PyObject *StrokeVertexIterator_u_get(BPy_StrokeVertexIterator *self, void *UNUSED(closure))
+{
+ return PyFloat_FromDouble(self->sv_it->u());
+}
+
+static PyGetSetDef BPy_StrokeVertexIterator_getseters[] = {
+ {(char *)"object", (getter)StrokeVertexIterator_object_get, (setter)NULL,
+ (char *)StrokeVertexIterator_object_doc, NULL},
+ {(char *)"t", (getter)StrokeVertexIterator_t_get, (setter)NULL, (char *)StrokeVertexIterator_t_doc, NULL},
+ {(char *)"u", (getter)StrokeVertexIterator_u_get, (setter)NULL, (char *)StrokeVertexIterator_u_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_StrokeVertexIterator type definition ------------------------------*/
+
+PyTypeObject StrokeVertexIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "StrokeVertexIterator", /* tp_name */
+ sizeof(BPy_StrokeVertexIterator), /* 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 */
+ StrokeVertexIterator_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)StrokeVertexIterator_iternext, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ BPy_StrokeVertexIterator_getseters, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)StrokeVertexIterator_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h
new file mode 100644
index 00000000000..0c9bb0d0be7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h
@@ -0,0 +1,64 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_STROKEVERTEXITERATOR_H__
+#define __FREESTYLE_PYTHON_STROKEVERTEXITERATOR_H__
+
+#include "../../stroke/StrokeIterators.h"
+
+#include "../BPy_Iterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject StrokeVertexIterator_Type;
+
+#define BPy_StrokeVertexIterator_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&StrokeVertexIterator_Type))
+
+/*---------------------------Python BPy_StrokeVertexIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ StrokeInternal::StrokeVertexIterator *sv_it;
+ int reversed;
+} BPy_StrokeVertexIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_STROKEVERTEXITERATOR_H__ */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp
new file mode 100644
index 00000000000..0a0f5d249a4
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ViewEdgeIterator.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+PyDoc_STRVAR(ViewEdgeIterator_doc,
+"Class hierarchy: :class:`Iterator` > :class:`ViewEdgeIterator`\n"
+"\n"
+"Base class for iterators over ViewEdges of the :class:`ViewMap` Graph.\n"
+"Basically the increment() operator of this class should be able to\n"
+"take the decision of \"where\" (on which ViewEdge) to go when pointing\n"
+"on a given ViewEdge.\n"
+"\n"
+".. method:: __init__(begin=None, orientation=True)\n"
+"\n"
+" Builds a ViewEdgeIterator from a starting ViewEdge and its\n"
+" orientation.\n"
+"\n"
+" :arg begin: The ViewEdge from where to start the iteration.\n"
+" :type begin: :class:`ViewEdge` or None\n"
+" :arg orientation: If true, we'll look for the next ViewEdge among\n"
+" the ViewEdges that surround the ending ViewVertex of begin. If\n"
+" false, we'll search over the ViewEdges surrounding the ending\n"
+" ViewVertex of begin.\n"
+" :type orientation: bool\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A ViewEdgeIterator object.\n"
+" :type brother: :class:`ViewEdgeIterator`");
+
+static int check_begin(PyObject *obj, void *v)
+{
+ if (obj != 0 && obj != Py_None && !BPy_ViewEdge_Check(obj))
+ return 0;
+ *((PyObject **)v) = obj;
+ return 1;
+}
+
+static int ViewEdgeIterator_init(BPy_ViewEdgeIterator *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist_1[] = {"brother", NULL};
+ static const char *kwlist_2[] = {"begin", "orientation", NULL};
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist_1, &ViewEdgeIterator_Type, &obj1)) {
+ self->ve_it = new ViewEdgeInternal::ViewEdgeIterator(*(((BPy_ViewEdgeIterator *)obj1)->ve_it));
+ }
+ else if (PyErr_Clear(), (obj1 = obj2 = 0),
+ PyArg_ParseTupleAndKeywords(args, kwds, "|O&O!", (char **)kwlist_2,
+ check_begin, &obj1, &PyBool_Type, &obj2))
+ {
+ ViewEdge *begin = (!obj1 || obj1 == Py_None) ? NULL : ((BPy_ViewEdge *)obj1)->ve;
+ bool orientation = (!obj2) ? true : bool_from_PyBool(obj2);
+ self->ve_it = new ViewEdgeInternal::ViewEdgeIterator(begin, orientation);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->py_it.it = self->ve_it;
+ return 0;
+}
+
+PyDoc_STRVAR(ViewEdgeIterator_change_orientation_doc,
+".. method:: change_orientation()\n"
+"\n"
+" Changes the current orientation.");
+
+static PyObject *ViewEdgeIterator_change_orientation(BPy_ViewEdgeIterator *self)
+{
+ self->ve_it->changeOrientation();
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef BPy_ViewEdgeIterator_methods[] = {
+ {"change_orientation", (PyCFunction) ViewEdgeIterator_change_orientation, METH_NOARGS,
+ ViewEdgeIterator_change_orientation_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*----------------------ViewEdgeIterator get/setters ----------------------------*/
+
+PyDoc_STRVAR(ViewEdgeIterator_object_doc,
+"The ViewEdge object currently pointed by this iterator.\n"
+"\n"
+":type: :class:`ViewEdge`");
+
+static PyObject *ViewEdgeIterator_object_get(BPy_ViewEdgeIterator *self, void *UNUSED(closure))
+{
+ ViewEdge *ve = self->ve_it->operator*();
+ if (ve)
+ return BPy_ViewEdge_from_ViewEdge(*ve);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(ViewEdgeIterator_current_edge_doc,
+"The ViewEdge object currently pointed by this iterator.\n"
+"\n"
+":type: :class:`ViewEdge`");
+
+static PyObject *ViewEdgeIterator_current_edge_get(BPy_ViewEdgeIterator *self, void *UNUSED(closure))
+{
+ ViewEdge *ve = self->ve_it->getCurrentEdge();
+ if (ve)
+ return BPy_ViewEdge_from_ViewEdge(*ve);
+ Py_RETURN_NONE;}
+
+static int ViewEdgeIterator_current_edge_set(BPy_ViewEdgeIterator *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_ViewEdge_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be a ViewEdge");
+ return -1;
+ }
+ self->ve_it->setCurrentEdge(((BPy_ViewEdge *)value)->ve);
+ return 0;
+}
+
+PyDoc_STRVAR(ViewEdgeIterator_orientation_doc,
+"The orientation of the pointed ViewEdge in the iteration.\n"
+"If true, the iterator looks for the next ViewEdge among those ViewEdges\n"
+"that surround the ending ViewVertex of the \"begin\" ViewEdge. If false,\n"
+"the iterator searches over the ViewEdges surrounding the ending ViewVertex\n"
+"of the \"begin\" ViewEdge.\n"
+"\n"
+":type: bool");
+
+static PyObject *ViewEdgeIterator_orientation_get(BPy_ViewEdgeIterator *self, void *UNUSED(closure))
+{
+ return PyBool_from_bool(self->ve_it->getOrientation());
+}
+
+static int ViewEdgeIterator_orientation_set(BPy_ViewEdgeIterator *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!PyBool_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be a boolean");
+ return -1;
+ }
+ self->ve_it->setOrientation(bool_from_PyBool(value));
+ return 0;
+}
+
+PyDoc_STRVAR(ViewEdgeIterator_begin_doc,
+"The first ViewEdge used for the iteration.\n"
+"\n"
+":type: :class:`ViewEdge`");
+
+static PyObject *ViewEdgeIterator_begin_get(BPy_ViewEdgeIterator *self, void *UNUSED(closure))
+{
+ ViewEdge *ve = self->ve_it->getBegin();
+ if (ve)
+ return BPy_ViewEdge_from_ViewEdge(*ve);
+ Py_RETURN_NONE;
+}
+
+static int ViewEdgeIterator_begin_set(BPy_ViewEdgeIterator *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_ViewEdge_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be a ViewEdge");
+ return -1;
+ }
+ self->ve_it->setBegin(((BPy_ViewEdge *)value)->ve);
+ return 0;
+}
+
+static PyGetSetDef BPy_ViewEdgeIterator_getseters[] = {
+ {(char *)"object", (getter)ViewEdgeIterator_object_get, (setter)NULL, (char *)ViewEdgeIterator_object_doc, NULL},
+ {(char *)"current_edge", (getter)ViewEdgeIterator_current_edge_get, (setter)ViewEdgeIterator_current_edge_set,
+ (char *)ViewEdgeIterator_current_edge_doc, NULL},
+ {(char *)"orientation", (getter)ViewEdgeIterator_orientation_get, (setter)ViewEdgeIterator_orientation_set,
+ (char *)ViewEdgeIterator_orientation_doc, NULL},
+ {(char *)"begin", (getter)ViewEdgeIterator_begin_get, (setter)ViewEdgeIterator_begin_set,
+ (char *)ViewEdgeIterator_begin_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_ViewEdgeIterator type definition ------------------------------*/
+
+PyTypeObject ViewEdgeIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewEdgeIterator", /* tp_name */
+ sizeof(BPy_ViewEdgeIterator), /* 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 */
+ ViewEdgeIterator_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ViewEdgeIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ BPy_ViewEdgeIterator_getseters, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewEdgeIterator_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h
new file mode 100644
index 00000000000..dd8b1971e82
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h
@@ -0,0 +1,64 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_VIEWEDGEITERATOR_H__
+#define __FREESTYLE_PYTHON_VIEWEDGEITERATOR_H__
+
+
+#include "../../view_map/ViewMapIterators.h"
+
+#include "../BPy_Iterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ViewEdgeIterator_Type;
+
+#define BPy_ViewEdgeIterator_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ViewEdgeIterator_Type))
+
+/*---------------------------Python BPy_ViewEdgeIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ ViewEdgeInternal::ViewEdgeIterator *ve_it;
+} BPy_ViewEdgeIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_VIEWEDGEITERATOR_H__ */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp
new file mode 100644
index 00000000000..d92f3dd2d49
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp
@@ -0,0 +1,169 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_orientedViewEdgeIterator.h"
+
+#include "../BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+PyDoc_STRVAR(orientedViewEdgeIterator_doc,
+"Class hierarchy: :class:`Iterator` > :class:`orientedViewEdgeIterator`\n"
+"\n"
+"Class representing an iterator over oriented ViewEdges around a\n"
+":class:`ViewVertex`. This iterator allows a CCW iteration (in the image\n"
+"plane). An instance of an orientedViewEdgeIterator can only be\n"
+"obtained from a ViewVertex by calling edgesBegin() or edgesEnd().\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: An orientedViewEdgeIterator object.\n"
+" :type iBrother: :class:`orientedViewEdgeIterator`");
+
+static int orientedViewEdgeIterator_init(BPy_orientedViewEdgeIterator *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"brother", NULL};
+ PyObject *brother = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &orientedViewEdgeIterator_Type, &brother))
+ return -1;
+ if (!brother)
+ self->ove_it = new ViewVertexInternal::orientedViewEdgeIterator();
+ else
+ self->ove_it = new ViewVertexInternal::orientedViewEdgeIterator(*(((BPy_orientedViewEdgeIterator *)brother)->ove_it));
+ self->py_it.it = self->ove_it;
+ self->reversed = 0;
+ return 0;
+}
+
+static PyObject *orientedViewEdgeIterator_iternext(BPy_orientedViewEdgeIterator *self)
+{
+ ViewVertex::directedViewEdge *dve;
+
+ if (self->reversed) {
+ if (self->ove_it->isBegin()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ self->ove_it->decrement();
+ dve = self->ove_it->operator->();
+ }
+ else {
+ if (self->ove_it->isEnd()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ dve = self->ove_it->operator->();
+ self->ove_it->increment();
+ }
+ return BPy_directedViewEdge_from_directedViewEdge(*dve);
+}
+
+/*----------------------orientedViewEdgeIterator get/setters ----------------------------*/
+
+PyDoc_STRVAR(orientedViewEdgeIterator_object_doc,
+"The oriented ViewEdge (i.e., a tuple of the pointed ViewEdge and a boolean\n"
+"value) currently pointed by this iterator. If the boolean value is true,\n"
+"the ViewEdge is incoming.\n"
+"\n"
+":type: (:class:`directedViewEdge`, bool)");
+
+static PyObject *orientedViewEdgeIterator_object_get(BPy_orientedViewEdgeIterator *self, void *UNUSED(closure))
+{
+ return BPy_directedViewEdge_from_directedViewEdge(self->ove_it->operator*());
+}
+
+static PyGetSetDef BPy_orientedViewEdgeIterator_getseters[] = {
+ {(char *)"object", (getter)orientedViewEdgeIterator_object_get, (setter)NULL,
+ (char *)orientedViewEdgeIterator_object_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_orientedViewEdgeIterator type definition ------------------------------*/
+
+PyTypeObject orientedViewEdgeIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "orientedViewEdgeIterator", /* tp_name */
+ sizeof(BPy_orientedViewEdgeIterator), /* 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 */
+ orientedViewEdgeIterator_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)orientedViewEdgeIterator_iternext, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ BPy_orientedViewEdgeIterator_getseters, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)orientedViewEdgeIterator_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h
new file mode 100644
index 00000000000..0d2846ce158
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_ORIENTEDVIEWEDGEITERATOR_H__
+#define __FREESTYLE_PYTHON_ORIENTEDVIEWEDGEITERATOR_H__
+
+#include "../../stroke/Stroke.h"
+#include "../../view_map/ViewMapIterators.h"
+
+#include "../BPy_Iterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject orientedViewEdgeIterator_Type;
+
+#define BPy_orientedViewEdgeIterator_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&orientedViewEdgeIterator_Type))
+
+/*---------------------------Python BPy_orientedViewEdgeIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ ViewVertexInternal::orientedViewEdgeIterator *ove_it;
+ int reversed;
+} BPy_orientedViewEdgeIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_ORIENTEDVIEWEDGEITERATOR_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp
new file mode 100644
index 00000000000..7ff97e6cc34
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_BackboneStretcherShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char BackboneStretcherShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`BackboneStretcherShader`\n"
+"\n"
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(amount=2.0)\n"
+"\n"
+" Builds a BackboneStretcherShader object.\n"
+"\n"
+" :arg amount: The stretching amount value.\n"
+" :type amount: float\n"
+"\n"
+".. method:: shade(stroke)\n"
+"\n"
+" Stretches the stroke at its two extremities and following the\n"
+" respective directions: v(1)v(0) and v(n-1)v(n).\n"
+"\n"
+" :arg stroke: A Stroke object.\n"
+" :type stroke: :class:`Stroke`\n";
+
+static int BackboneStretcherShader___init__(BPy_BackboneStretcherShader *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"amount", NULL};
+ float f = 2.0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|f", (char **)kwlist, &f))
+ return -1;
+ self->py_ss.ss = new StrokeShaders::BackboneStretcherShader(f);
+ return 0;
+}
+
+/*-----------------------BPy_BackboneStretcherShader type definition ------------------------------*/
+
+PyTypeObject BackboneStretcherShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BackboneStretcherShader", /* tp_name */
+ sizeof(BPy_BackboneStretcherShader), /* 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 */
+ BackboneStretcherShader___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)BackboneStretcherShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.h
new file mode 100644
index 00000000000..053af43f166
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.h
@@ -0,0 +1,63 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_BACKBONESTRETCHERSHADER_H__
+#define __FREESTYLE_PYTHON_BACKBONESTRETCHERSHADER_H__
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject BackboneStretcherShader_Type;
+
+#define BPy_BackboneStretcherShader_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&BackboneStretcherShader_Type))
+
+/*---------------------------Python BPy_BackboneStretcherShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_BackboneStretcherShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_BACKBONESTRETCHERSHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp
new file mode 100644
index 00000000000..9e398dba42e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_BezierCurveShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char BezierCurveShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`BezierCurveShader`\n"
+"\n"
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(error=4.0)\n"
+"\n"
+" Builds a BezierCurveShader object.\n"
+"\n"
+" :arg error: The error we're allowing for the approximation. This\n"
+" error is the max distance allowed between the new curve and the\n"
+" original geometry.\n"
+" :type error: float\n"
+"\n"
+".. method:: shade(stroke)\n"
+"\n"
+" Transforms the stroke backbone geometry so that it corresponds to a\n"
+" Bezier Curve approximation of the original backbone geometry.\n"
+"\n"
+" :arg stroke: A Stroke object.\n"
+" :type stroke: :class:`Stroke`\n";
+
+static int BezierCurveShader___init__(BPy_BezierCurveShader *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"error", NULL};
+ float f = 4.0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|f", (char **)kwlist, &f))
+ return -1;
+ self->py_ss.ss = new StrokeShaders::BezierCurveShader(f);
+ return 0;
+}
+
+/*-----------------------BPy_BezierCurveShader type definition ------------------------------*/
+
+PyTypeObject BezierCurveShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BezierCurveShader", /* tp_name */
+ sizeof(BPy_BezierCurveShader), /* 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 */
+ BezierCurveShader___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)BezierCurveShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.h
new file mode 100644
index 00000000000..6e11d84e30f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_BEZIERCURVESHADER_H__
+#define __FREESTYLE_PYTHON_BEZIERCURVESHADER_H__
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject BezierCurveShader_Type;
+
+#define BPy_BezierCurveShader_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&BezierCurveShader_Type))
+
+/*---------------------------Python BPy_BezierCurveShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_BezierCurveShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_BEZIERCURVESHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp
new file mode 100644
index 00000000000..51efd94e324
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp
@@ -0,0 +1,146 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_CalligraphicShader.h"
+
+#include "../../stroke/AdvancedStrokeShaders.h"
+#include "../BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char CalligraphicShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`CalligraphicShader`\n"
+"\n"
+"[Thickness Shader]\n"
+"\n"
+".. method:: __init__(thickness_min, thickness_max, orientation, clamp)\n"
+"\n"
+" Builds a CalligraphicShader object.\n"
+"\n"
+" :arg thickness_min: The minimum thickness in the direction\n"
+" perpendicular to the main direction.\n"
+" :type thickness_min: float\n"
+" :arg thickness_max: The maximum thickness in the main direction.\n"
+" :type thickness_max: float\n"
+" :arg orientation: The 2D vector giving the main direction.\n"
+" :type orientation: :class:`mathutils.Vector`\n"
+" :arg clamp: If true, the strokes are drawn in black when the stroke\n"
+" direction is between -90 and 90 degrees with respect to the main\n"
+" direction and drawn in white otherwise. If false, the strokes\n"
+" are always drawn in black.\n"
+" :type clamp: bool\n"
+"\n"
+".. method:: shade(stroke)\n"
+"\n"
+" Assigns thicknesses to the stroke vertices so that the stroke looks\n"
+" like made with a calligraphic tool, i.e. the stroke will be the\n"
+" thickest in a main direction, and the thinest in the direction\n"
+" perpendicular to this one, and an interpolation inbetween.\n"
+"\n"
+" :arg stroke: A Stroke object.\n"
+" :type stroke: :class:`Stroke`\n";
+
+static int convert_v2(PyObject *obj, void *v)
+{
+ return float_array_from_PyObject(obj, (float *)v, 2);
+}
+
+static int CalligraphicShader___init__(BPy_CalligraphicShader *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"thickness_min", "thickness_max", "orientation", "clamp", NULL};
+ double d1, d2;
+ float f3[2];
+ PyObject *obj4 = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "ddO&O!", (char **)kwlist,
+ &d1, &d2, convert_v2, f3, &PyBool_Type, &obj4))
+ {
+ return -1;
+ }
+ Vec2f v(f3[0], f3[1]);
+ self->py_ss.ss = new CalligraphicShader(d1, d2, v, bool_from_PyBool(obj4));
+ return 0;
+}
+
+/*-----------------------BPy_CalligraphicShader type definition ------------------------------*/
+
+PyTypeObject CalligraphicShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "CalligraphicShader", /* tp_name */
+ sizeof(BPy_CalligraphicShader), /* 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 */
+ CalligraphicShader___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)CalligraphicShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.h
new file mode 100644
index 00000000000..74dca914473
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_CALLIGRAPHICSHADER_H__
+#define __FREESTYLE_PYTHON_CALLIGRAPHICSHADER_H__
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject CalligraphicShader_Type;
+
+#define BPy_CalligraphicShader_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&CalligraphicShader_Type)
+
+/*---------------------------Python BPy_CalligraphicShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_CalligraphicShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_CALLIGRAPHICSHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp
new file mode 100644
index 00000000000..6119756f1cd
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp
@@ -0,0 +1,123 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ColorNoiseShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ColorNoiseShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`ColorNoiseShader`\n"
+"\n"
+"[Color shader]\n"
+"\n"
+".. method:: __init__(amplitude, period)\n"
+"\n"
+" Builds a ColorNoiseShader object.\n"
+"\n"
+" :arg amplitude: The amplitude of the noise signal.\n"
+" :type amplitude: float\n"
+" :arg period: The period of the noise signal.\n"
+" :type period: float\n"
+"\n"
+".. method:: shade(stroke)\n"
+"\n"
+" Shader to add noise to the stroke colors.\n"
+"\n"
+" :arg stroke: A Stroke object.\n"
+" :type stroke: :class:`Stroke`\n";
+
+static int ColorNoiseShader___init__(BPy_ColorNoiseShader *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"amplitude", "period", NULL};
+ float f1, f2;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "ff", (char **)kwlist, &f1, &f2))
+ return -1;
+ self->py_ss.ss = new StrokeShaders::ColorNoiseShader(f1, f2);
+ return 0;
+}
+
+/*-----------------------BPy_ColorNoiseShader type definition ------------------------------*/
+
+PyTypeObject ColorNoiseShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ColorNoiseShader", /* tp_name */
+ sizeof(BPy_ColorNoiseShader), /* 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 */
+ ColorNoiseShader___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)ColorNoiseShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.h
new file mode 100644
index 00000000000..c1d1b7f384c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_COLORNOISESHADER_H__
+#define __FREESTYLE_PYTHON_COLORNOISESHADER_H__
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ColorNoiseShader_Type;
+
+#define BPy_ColorNoiseShader_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ColorNoiseShader_Type))
+
+/*---------------------------Python BPy_ColorNoiseShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ColorNoiseShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_COLORNOISESHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp
new file mode 100644
index 00000000000..8e92bbc908c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** 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:`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:`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
new file mode 100644
index 00000000000..f72b4b54abf
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.h
@@ -0,0 +1,63 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** 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
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+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_ConstantColorShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp
new file mode 100644
index 00000000000..627f2a5423c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp
@@ -0,0 +1,127 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ConstantColorShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ConstantColorShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`ConstantColorShader`\n"
+"\n"
+"[Color shader]\n"
+"\n"
+".. method:: __init__(red, green, blue, alpha=1.0)\n"
+"\n"
+" Builds a ConstantColorShader object.\n"
+"\n"
+" :arg red: The red component.\n"
+" :type red: float\n"
+" :arg green: The green component.\n"
+" :type green: float\n"
+" :arg blue: The blue component.\n"
+" :type blue: float\n"
+" :arg alpha: The alpha value.\n"
+" :type alpha: float\n"
+"\n"
+".. method:: shade(stroke)\n"
+"\n"
+" Assigns a constant color to every vertex of the Stroke.\n"
+"\n"
+" :arg stroke: A Stroke object.\n"
+" :type stroke: :class:`Stroke`\n";
+
+static int ConstantColorShader___init__(BPy_ConstantColorShader *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"red", "green", "blue", "alpha", NULL};
+ float f1, f2, f3, f4 = 1.0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "fff|f", (char **)kwlist, &f1, &f2, &f3, &f4))
+ return -1;
+ self->py_ss.ss = new StrokeShaders::ConstantColorShader(f1, f2, f3, f4);
+ return 0;
+}
+
+/*-----------------------BPy_ConstantColorShader type definition ------------------------------*/
+
+PyTypeObject ConstantColorShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ConstantColorShader", /* tp_name */
+ sizeof(BPy_ConstantColorShader), /* 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 */
+ ConstantColorShader___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)ConstantColorShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.h
new file mode 100644
index 00000000000..ad81132fc4f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_CONSTANTCOLORSHADER_H__
+#define __FREESTYLE_PYTHON_CONSTANTCOLORSHADER_H__
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ConstantColorShader_Type;
+
+#define BPy_ConstantColorShader_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ConstantColorShader_Type))
+
+/*---------------------------Python BPy_ConstantColorShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ConstantColorShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_CONSTANTCOLORSHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp
new file mode 100644
index 00000000000..0b2af7c3856
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ConstantThicknessShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ConstantThicknessShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`ConstantThicknessShader`\n"
+"\n"
+"[Thickness shader]\n"
+"\n"
+".. method:: __init__(thickness)\n"
+"\n"
+" Builds a ConstantThicknessShader object.\n"
+"\n"
+" :arg thickness: The thickness that must be assigned to the stroke.\n"
+" :type thickness: float\n"
+"\n"
+".. method:: shade(stroke)\n"
+"\n"
+" Assigns an absolute constant thickness to every vertex of the Stroke.\n"
+"\n"
+" :arg stroke: A Stroke object.\n"
+" :type stroke: :class:`Stroke`\n";
+
+static int ConstantThicknessShader___init__(BPy_ConstantThicknessShader *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"thickness", NULL};
+ float f;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "f", (char **)kwlist, &f))
+ return -1;
+ self->py_ss.ss = new StrokeShaders::ConstantThicknessShader(f);
+ return 0;
+}
+
+/*-----------------------BPy_ConstantThicknessShader type definition ------------------------------*/
+
+PyTypeObject ConstantThicknessShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ConstantThicknessShader", /* tp_name */
+ sizeof(BPy_ConstantThicknessShader), /* 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 */
+ ConstantThicknessShader___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)ConstantThicknessShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.h
new file mode 100644
index 00000000000..c8c22516cf1
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.h
@@ -0,0 +1,63 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_CONSTANTTHICKNESSSHADER_H__
+#define __FREESTYLE_PYTHON_CONSTANTTHICKNESSSHADER_H__
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ConstantThicknessShader_Type;
+
+#define BPy_ConstantThicknessShader_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&ConstantThicknessShader_Type))
+
+/*---------------------------Python BPy_ConstantThicknessShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ConstantThicknessShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_CONSTANTTHICKNESSSHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp
new file mode 100644
index 00000000000..c00897100eb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp
@@ -0,0 +1,128 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ConstrainedIncreasingThicknessShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ConstrainedIncreasingThicknessShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`ConstrainedIncreasingThicknessShader`\n"
+"\n"
+"[Thickness shader]\n"
+"\n"
+".. method:: __init__(thickness_min, thickness_max, ratio)\n"
+"\n"
+" Builds a ConstrainedIncreasingThicknessShader object.\n"
+"\n"
+" :arg thickness_min: The minimum thickness.\n"
+" :type thickness_min: float\n"
+" :arg thickness_max: The maximum thickness.\n"
+" :type thickness_max: float\n"
+" :arg ratio: The thickness/length ratio that we don't want to exceed. \n"
+" :type ratio: float\n"
+"\n"
+".. method:: shade(stroke)\n"
+"\n"
+" Same as the :class:`IncreasingThicknessShader`, but here we allow\n"
+" the user to control the thickness/length ratio so that we don't get\n"
+" fat short lines.\n"
+"\n"
+" :arg stroke: A Stroke object.\n"
+" :type stroke: :class:`Stroke`\n";
+
+static int ConstrainedIncreasingThicknessShader___init__(BPy_ConstrainedIncreasingThicknessShader *self,
+ PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"thickness_min", "thickness_max", "ratio", NULL};
+ float f1, f2, f3;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "fff", (char **)kwlist, &f1, &f2, &f3))
+ return -1;
+ self->py_ss.ss = new StrokeShaders::ConstrainedIncreasingThicknessShader(f1, f2, f3);
+ return 0;
+}
+
+/*-----------------------BPy_ConstrainedIncreasingThicknessShader type definition ------------------------------*/
+
+PyTypeObject ConstrainedIncreasingThicknessShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ConstrainedIncreasingThicknessShader", /* tp_name */
+ sizeof(BPy_ConstrainedIncreasingThicknessShader), /* 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 */
+ ConstrainedIncreasingThicknessShader___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)ConstrainedIncreasingThicknessShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h
new file mode 100644
index 00000000000..104b57542b9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h
@@ -0,0 +1,63 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_CONSTRAINEDINCREASINGTHICKNESSSHADER_H__
+#define __FREESTYLE_PYTHON_CONSTRAINEDINCREASINGTHICKNESSSHADER_H__
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ConstrainedIncreasingThicknessShader_Type;
+
+#define BPy_ConstrainedIncreasingThicknessShader_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&ConstrainedIncreasingThicknessShader_Type))
+
+/*---------------------------Python BPy_ConstrainedIncreasingThicknessShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ConstrainedIncreasingThicknessShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_CONSTRAINEDINCREASINGTHICKNESSSHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp
new file mode 100644
index 00000000000..37b53a496ec
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GuidingLinesShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GuidingLinesShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`GuidingLinesShader`\n"
+"\n"
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(offset)\n"
+"\n"
+" Builds a GuidingLinesShader object.\n"
+"\n"
+" :arg offset: The line that replaces the stroke is initially in the\n"
+" middle of the initial stroke bounding box. offset is the value\n"
+" of the displacement which is applied to this line along its\n"
+" normal.\n"
+" :type offset: float\n"
+"\n"
+".. method:: shade(stroke)\n"
+"\n"
+" Shader to modify the Stroke geometry so that it corresponds to its\n"
+" main direction line. This shader must be used together with the\n"
+" splitting operator using the curvature criterion. Indeed, the\n"
+" precision of the approximation will depend on the size of the\n"
+" stroke's pieces. The bigger the pieces are, the rougher the\n"
+" approximation is.\n"
+"\n"
+" :arg stroke: A Stroke object.\n"
+" :type stroke: :class:`Stroke`\n";
+
+static int GuidingLinesShader___init__(BPy_GuidingLinesShader *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"offset", NULL};
+ float f;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "f", (char **)kwlist, &f))
+ return -1;
+ self->py_ss.ss = new StrokeShaders::GuidingLinesShader(f);
+ return 0;
+}
+
+/*-----------------------BPy_GuidingLinesShader type definition ------------------------------*/
+
+PyTypeObject GuidingLinesShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GuidingLinesShader", /* tp_name */
+ sizeof(BPy_GuidingLinesShader), /* 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 */
+ GuidingLinesShader___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)GuidingLinesShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.h
new file mode 100644
index 00000000000..0b7ca4a5217
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GUIDINGLINESSHADER_H__
+#define __FREESTYLE_PYTHON_GUIDINGLINESSHADER_H__
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GuidingLinesShader_Type;
+
+#define BPy_GuidingLinesShader_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GuidingLinesShader_Type))
+
+/*---------------------------Python BPy_GuidingLinesShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_GuidingLinesShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_GUIDINGLINESSHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp
new file mode 100644
index 00000000000..9db4290e511
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_IncreasingColorShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char IncreasingColorShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`IncreasingColorShader`\n"
+"\n"
+"[Color shader]\n"
+"\n"
+".. method:: __init__(red_min, green_min, blue_min, alpha_min, red_max, green_max, blue_max, alpha_max)\n"
+"\n"
+" Builds an IncreasingColorShader object.\n"
+"\n"
+" :arg red_min: The first color red component.\n"
+" :type red_min: float\n"
+" :arg green_min: The first color green component.\n"
+" :type green_min: float\n"
+" :arg blue_min: The first color blue component.\n"
+" :type blue_min: float\n"
+" :arg alpha_min: The first color alpha value.\n"
+" :type alpha_min: float\n"
+" :arg red_max: The second color red component.\n"
+" :type red_max: float\n"
+" :arg green_max: The second color green component.\n"
+" :type green_max: float\n"
+" :arg blue_max: The second color blue component.\n"
+" :type blue_max: float\n"
+" :arg alpha_max: The second color alpha value.\n"
+" :type alpha_max: float\n"
+"\n"
+".. method:: shade(stroke)\n"
+"\n"
+" Assigns a varying color to the stroke. The user specifies two\n"
+" colors A and B. The stroke color will change linearly from A to B\n"
+" between the first and the last vertex.\n"
+"\n"
+" :arg stroke: A Stroke object.\n"
+" :type stroke: :class:`Stroke`\n";
+
+static int IncreasingColorShader___init__(BPy_IncreasingColorShader *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"red_min", "green_min", "blue_min", "alpha_min",
+ "red_max", "green_max", "blue_max", "alpha_max", NULL};
+ float f1, f2, f3, f4, f5, f6, f7, f8;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "ffffffff", (char **)kwlist, &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8))
+ return -1;
+ self->py_ss.ss = new StrokeShaders::IncreasingColorShader(f1, f2, f3, f4, f5, f6, f7, f8);
+ return 0;
+}
+
+/*-----------------------BPy_IncreasingColorShader type definition ------------------------------*/
+
+PyTypeObject IncreasingColorShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "IncreasingColorShader", /* tp_name */
+ sizeof(BPy_IncreasingColorShader), /* 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 */
+ IncreasingColorShader___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)IncreasingColorShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.h
new file mode 100644
index 00000000000..bc61c7c97d0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_INCREASINGCOLORSHADER_H__
+#define __FREESTYLE_PYTHON_INCREASINGCOLORSHADER_H__
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject IncreasingColorShader_Type;
+
+#define BPy_IncreasingColorShader_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&IncreasingColorShader_Type))
+
+/*---------------------------Python BPy_IncreasingColorShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_IncreasingColorShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_INCREASINGCOLORSHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp
new file mode 100644
index 00000000000..220fccc83d4
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp
@@ -0,0 +1,127 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_IncreasingThicknessShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char IncreasingThicknessShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`IncreasingThicknessShader`\n"
+"\n"
+"[Thickness shader]\n"
+"\n"
+".. method:: __init__(thickness_A, thickness_B)\n"
+"\n"
+" Builds an IncreasingThicknessShader object.\n"
+"\n"
+" :arg thickness_A: The first thickness value.\n"
+" :type thickness_A: float\n"
+" :arg thickness_B: The second thickness value.\n"
+" :type thickness_B: float\n"
+"\n"
+".. method:: shade(stroke)\n"
+"\n"
+" Assigns thicknesses values such as the thickness increases from a\n"
+" thickness value A to a thickness value B between the first vertex\n"
+" to the midpoint vertex and then decreases from B to a A between\n"
+" this midpoint vertex and the last vertex. The thickness is\n"
+" linearly interpolated from A to B.\n"
+"\n"
+" :arg stroke: A Stroke object.\n"
+" :type stroke: :class:`Stroke`\n";
+
+static int IncreasingThicknessShader___init__(BPy_IncreasingThicknessShader *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"thickness_A", "thickness_B", NULL};
+ float f1, f2;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "ff", (char **)kwlist, &f1, &f2))
+ return -1;
+ self->py_ss.ss = new StrokeShaders::IncreasingThicknessShader(f1, f2);
+ return 0;
+}
+
+/*-----------------------BPy_IncreasingThicknessShader type definition ------------------------------*/
+
+PyTypeObject IncreasingThicknessShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "IncreasingThicknessShader", /* tp_name */
+ sizeof(BPy_IncreasingThicknessShader), /* 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 */
+ IncreasingThicknessShader___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)IncreasingThicknessShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.h
new file mode 100644
index 00000000000..e162460a567
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.h
@@ -0,0 +1,63 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_INCREASINGTHICKNESSSHADER_H__
+#define __FREESTYLE_PYTHON_INCREASINGTHICKNESSSHADER_H__
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject IncreasingThicknessShader_Type;
+
+#define BPy_IncreasingThicknessShader_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&IncreasingThicknessShader_Type))
+
+/*---------------------------Python BPy_IncreasingThicknessShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_IncreasingThicknessShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_INCREASINGTHICKNESSSHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp
new file mode 100644
index 00000000000..908040cd0df
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp
@@ -0,0 +1,128 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_PolygonalizationShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char PolygonalizationShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`PolygonalizationShader`\n"
+"\n"
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(error)\n"
+"\n"
+" Builds a PolygonalizationShader object.\n"
+"\n"
+" :arg error: The error we want our polygonal approximation to have\n"
+" with respect to the original geometry. The smaller, the closer\n"
+" the new stroke is to the orinal one. This error corresponds to\n"
+" the maximum distance between the new stroke and the old one.\n"
+" :type error: float\n"
+"\n"
+".. method:: shade(stroke)\n"
+"\n"
+" Modifies the Stroke geometry so that it looks more \"polygonal\".\n"
+" The basic idea is to start from the minimal stroke approximation\n"
+" consisting in a line joining the first vertex to the last one and\n"
+" to subdivide using the original stroke vertices until a certain\n"
+" error is reached.\n"
+"\n"
+" :arg stroke: A Stroke object.\n"
+" :type stroke: :class:`Stroke`\n";
+
+static int PolygonalizationShader___init__(BPy_PolygonalizationShader *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"error", NULL};
+ float f;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "f", (char **)kwlist, &f))
+ return -1;
+ self->py_ss.ss = new StrokeShaders::PolygonalizationShader(f);
+ return 0;
+}
+
+/*-----------------------BPy_PolygonalizationShader type definition ------------------------------*/
+
+PyTypeObject PolygonalizationShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "PolygonalizationShader", /* tp_name */
+ sizeof(BPy_PolygonalizationShader), /* 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 */
+ PolygonalizationShader___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)PolygonalizationShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.h
new file mode 100644
index 00000000000..ed8678143d3
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.h
@@ -0,0 +1,63 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_POLYGONALIZATIONSHADER_H__
+#define __FREESTYLE_PYTHON_POLYGONALIZATIONSHADER_H__
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject PolygonalizationShader_Type;
+
+#define BPy_PolygonalizationShader_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&PolygonalizationShader_Type))
+
+/*---------------------------Python BPy_PolygonalizationShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_PolygonalizationShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_POLYGONALIZATIONSHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp
new file mode 100644
index 00000000000..744ae057147
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_SamplingShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char SamplingShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`SamplingShader`\n"
+"\n"
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(sampling)\n"
+"\n"
+" Builds a SamplingShader object.\n"
+"\n"
+" :arg sampling: The sampling to use for the stroke resampling.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: shade(stroke)\n"
+"\n"
+" Resamples the stroke.\n"
+"\n"
+" :arg stroke: A Stroke object.\n"
+" :type stroke: :class:`Stroke`\n";
+
+static int SamplingShader___init__(BPy_SamplingShader *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"sampling", NULL};
+ float f;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "f", (char **)kwlist, &f))
+ return -1;
+ self->py_ss.ss = new StrokeShaders::SamplingShader(f);
+ return 0;
+}
+
+/*-----------------------BPy_SamplingShader type definition ------------------------------*/
+
+PyTypeObject SamplingShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SamplingShader", /* tp_name */
+ sizeof(BPy_SamplingShader), /* 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 */
+ SamplingShader___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)SamplingShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.h
new file mode 100644
index 00000000000..7e214ce22aa
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_SAMPLINGSHADER_H__
+#define __FREESTYLE_PYTHON_SAMPLINGSHADER_H__
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SamplingShader_Type;
+
+#define BPy_SamplingShader_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&SamplingShader_Type))
+
+/*---------------------------Python BPy_SamplingShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_SamplingShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_SAMPLINGSHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp
new file mode 100644
index 00000000000..d6b0139d315
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp
@@ -0,0 +1,147 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_SmoothingShader.h"
+
+#include "../../stroke/AdvancedStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char SmoothingShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`SmoothingShader`\n"
+"\n"
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(num_iterations=100, factor_point=0.1,\n"
+" factor_curvature=0.0, factor_curvature_difference=0.2,\n"
+" aniso_point=0.0, aniso_normal=0.0, aniso_curvature=0.0,\n"
+" carricature_factor=1.0)\n"
+"\n"
+" Builds a SmoothingShader object.\n"
+"\n"
+" :arg num_iterations: The number of iterations.\n"
+" :type num_iterations: int\n"
+" :arg factor_point: 0.1\n"
+" :type factor_point: float\n"
+" :arg factor_curvature: 0.0\n"
+" :type factor_curvature: float\n"
+" :arg factor_curvature_difference: 0.2\n"
+" :type factor_curvature_difference: float\n"
+" :arg aniso_point: 0.0\n"
+" :type aniso_point: float\n"
+" :arg aniso_normal: 0.0\n"
+" :type aniso_normal: float\n"
+" :arg aniso_curvature: 0.0\n"
+" :type aniso_curvature: float\n"
+" :arg carricature_factor: 1.0\n"
+" :type carricature_factor: float\n"
+"\n"
+".. method:: shade(stroke)\n"
+"\n"
+" Smoothes the stroke by moving the vertices to make the stroke\n"
+" smoother. Uses curvature flow to converge towards a curve of\n"
+" constant curvature. The diffusion method we use is anisotropic to\n"
+" prevent the diffusion accross corners.\n"
+"\n"
+" :arg stroke: A Stroke object.\n"
+" :type stroke: :class:`Stroke`\n";
+
+static int SmoothingShader___init__(BPy_SmoothingShader *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"num_iterations", "factor_point", "factor_curvature",
+ "factor_curvature_difference", "aniso_point", "aniso_normal",
+ "aniso_curvature", "carricature_factor", NULL};
+ int i1 = 100;
+ double d2 = 0.1, d3 = 0.0, d4 = 0.2, d5 = 0.0, d6 = 0.0, d7 = 0.0, d8 = 1.0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iddddddd", (char **)kwlist,
+ &i1, &d2, &d3, &d4, &d5, &d6, &d7, &d8))
+ {
+ return -1;
+ }
+ self->py_ss.ss = new SmoothingShader(i1, d2, d3, d4, d5, d6, d7, d8);
+ return 0;
+}
+
+/*-----------------------BPy_SmoothingShader type definition ------------------------------*/
+
+PyTypeObject SmoothingShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SmoothingShader", /* tp_name */
+ sizeof(BPy_SmoothingShader), /* 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 */
+ SmoothingShader___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)SmoothingShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.h
new file mode 100644
index 00000000000..e00c0bac9de
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHONSMOOTHINGSHADER_H__
+#define __FREESTYLE_PYTHONSMOOTHINGSHADER_H__
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SmoothingShader_Type;
+
+#define BPy_SmoothingShader_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&SmoothingShader_Type))
+
+/*---------------------------Python BPy_SmoothingShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_SmoothingShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHONSMOOTHINGSHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp
new file mode 100644
index 00000000000..3fdb5196818
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_SpatialNoiseShader.h"
+
+#include "../../stroke/AdvancedStrokeShaders.h"
+#include "../BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char SpatialNoiseShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`SpatialNoiseShader`\n"
+"\n"
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(amount, scale, num_octaves, smooth, pure_random)\n"
+"\n"
+" Builds a SpatialNoiseShader object.\n"
+"\n"
+" :arg amount: The amplitude of the noise.\n"
+" :type amount: float\n"
+" :arg scale: The noise frequency.\n"
+" :type scale: float\n"
+" :arg num_octaves: The number of octaves\n"
+" :type num_octaves: int\n"
+" :arg smooth: True if you want the noise to be smooth.\n"
+" :type smooth: bool\n"
+" :arg pure_random: True if you don't want any coherence.\n"
+" :type pure_random: bool\n"
+"\n"
+".. method:: shade(stroke)\n"
+"\n"
+" Spatial Noise stroke shader. Moves the vertices to make the stroke\n"
+" more noisy.\n"
+"\n"
+" :arg stroke: A Stroke object.\n"
+" :type stroke: :class:`Stroke`\n";
+
+static int SpatialNoiseShader___init__(BPy_SpatialNoiseShader *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"amount", "scale", "num_octaves", "smooth", "pure_random", NULL};
+ float f1, f2;
+ int i3;
+ PyObject *obj4 = 0, *obj5 = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "ffiO!O!", (char **)kwlist,
+ &f1, &f2, &i3, &PyBool_Type, &obj4, &PyBool_Type, &obj5))
+ {
+ return -1;
+ }
+ self->py_ss.ss = new SpatialNoiseShader(f1, f2, i3, bool_from_PyBool(obj4), bool_from_PyBool(obj5));
+ return 0;
+}
+
+/*-----------------------BPy_SpatialNoiseShader type definition ------------------------------*/
+
+PyTypeObject SpatialNoiseShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SpatialNoiseShader", /* tp_name */
+ sizeof(BPy_SpatialNoiseShader), /* 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 */
+ SpatialNoiseShader___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)SpatialNoiseShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.h
new file mode 100644
index 00000000000..13b32ee7a31
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_SPATIALNOISESHADER_H__
+#define __FREESTYLE_PYTHON_SPATIALNOISESHADER_H__
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SpatialNoiseShader_Type;
+
+#define BPy_SpatialNoiseShader_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&SpatialNoiseShader_Type))
+
+/*---------------------------Python BPy_SpatialNoiseShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_SpatialNoiseShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_SPATIALNOISESHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp
new file mode 100644
index 00000000000..f83aa819c12
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp
@@ -0,0 +1,150 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** 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:`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:`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:`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
new file mode 100644
index 00000000000..5e28fb51390
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** 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
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+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
new file mode 100644
index 00000000000..3b4027e900d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp
@@ -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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** 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:`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:`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
new file mode 100644
index 00000000000..06070ecf3ee
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** 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
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+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_ThicknessNoiseShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp
new file mode 100644
index 00000000000..3d6b584cf2d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp
@@ -0,0 +1,123 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ThicknessNoiseShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ThicknessNoiseShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`ThicknessNoiseShader`\n"
+"\n"
+"[Thickness shader]\n"
+"\n"
+".. method:: __init__(amplitude, period)\n"
+"\n"
+" Builds a ThicknessNoiseShader object.\n"
+"\n"
+" :arg amplitude: The amplitude of the noise signal.\n"
+" :type amplitude: float\n"
+" :arg period: The period of the noise signal.\n"
+" :type period: float\n"
+"\n"
+".. method:: shade(stroke)\n"
+"\n"
+" Adds some noise to the stroke thickness.\n"
+"\n"
+" :arg stroke: A Stroke object.\n"
+" :type stroke: :class:`Stroke`\n";
+
+static int ThicknessNoiseShader___init__(BPy_ThicknessNoiseShader *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"amplitude", "period", NULL};
+ float f1, f2;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "ff", (char **)kwlist, &f1, &f2))
+ return -1;
+ self->py_ss.ss = new StrokeShaders::ThicknessNoiseShader(f1, f2);
+ return 0;
+}
+
+/*-----------------------BPy_ThicknessNoiseShader type definition ------------------------------*/
+
+PyTypeObject ThicknessNoiseShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ThicknessNoiseShader", /* tp_name */
+ sizeof(BPy_ThicknessNoiseShader), /* 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 */
+ ThicknessNoiseShader___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)ThicknessNoiseShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.h
new file mode 100644
index 00000000000..0f68fed96c3
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_THICKNESSNOISESHADER_H__
+#define __FREESTYLE_PYTHON_THICKNESSNOISESHADER_H__
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ThicknessNoiseShader_Type;
+
+#define BPy_ThicknessNoiseShader_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ThicknessNoiseShader_Type))
+
+/*---------------------------Python BPy_ThicknessNoiseShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ThicknessNoiseShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_THICKNESSNOISESHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp
new file mode 100644
index 00000000000..5f38277b5b4
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp
@@ -0,0 +1,135 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** 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:`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:`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
new file mode 100644
index 00000000000..3556df1a4ae
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h
@@ -0,0 +1,63 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** 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
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+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_TipRemoverShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp
new file mode 100644
index 00000000000..c5e8b0518fc
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_TipRemoverShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TipRemoverShader___doc__[] =
+"Class hierarchy: :class:`StrokeShader` > :class:`TipRemoverShader`\n"
+"\n"
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(tip_length)\n"
+"\n"
+" Builds a TipRemoverShader object.\n"
+"\n"
+" :arg tip_length: The length of the piece of stroke we want to remove\n"
+" at each extremity.\n"
+" :type tip_length: float\n"
+"\n"
+".. method:: shade(stroke)\n"
+"\n"
+" Removes the stroke's extremities.\n"
+"\n"
+" :arg stroke: A Stroke object.\n"
+" :type stroke: :class:`Stroke`\n";
+
+static int TipRemoverShader___init__(BPy_TipRemoverShader *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"tip_length", NULL};
+ double d;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "d", (char **)kwlist, &d))
+ return -1;
+ self->py_ss.ss = new StrokeShaders::TipRemoverShader(d);
+ return 0;
+}
+
+/*-----------------------BPy_TipRemoverShader type definition ------------------------------*/
+
+PyTypeObject TipRemoverShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TipRemoverShader", /* tp_name */
+ sizeof(BPy_TipRemoverShader), /* 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 */
+ TipRemoverShader___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)TipRemoverShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.h
new file mode 100644
index 00000000000..7a3d2063a33
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_TIPREMOVERSHADER_H__
+#define __FREESTYLE_PYTHON_TIPREMOVERSHADER_H__
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TipRemoverShader_Type;
+
+#define BPy_TipRemoverShader_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&TipRemoverShader_Type))
+
+/*---------------------------Python BPy_TipRemoverShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_TipRemoverShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_TIPREMOVERSHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp
new file mode 100644
index 00000000000..b45b52902bf
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** 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:`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:`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
new file mode 100644
index 00000000000..b795ca1c53c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** 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
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+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
new file mode 100644
index 00000000000..aa26f6e30a5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp
@@ -0,0 +1,117 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** 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:`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:`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/StrokeShader/BPy_streamShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.h
new file mode 100644
index 00000000000..7cb9f0c5bf9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** 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__
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject streamShader_Type;
+
+#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 __cplusplus
+}
+#endif
+
+
+#endif /* __FREESTYLE_PYTHON_STREAMSHADER_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp
new file mode 100644
index 00000000000..e8507f729cb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp
@@ -0,0 +1,225 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction0DDouble.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h"
+#include "UnaryFunction0D_double/BPy_DensityF0D.h"
+#include "UnaryFunction0D_double/BPy_GetProjectedXF0D.h"
+#include "UnaryFunction0D_double/BPy_GetProjectedYF0D.h"
+#include "UnaryFunction0D_double/BPy_GetProjectedZF0D.h"
+#include "UnaryFunction0D_double/BPy_GetXF0D.h"
+#include "UnaryFunction0D_double/BPy_GetYF0D.h"
+#include "UnaryFunction0D_double/BPy_GetZF0D.h"
+#include "UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h"
+#include "UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h"
+
+#include "../Director.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DDouble_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction0DDouble_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction0DDouble_Type);
+ PyModule_AddObject(module, "UnaryFunction0DDouble", (PyObject *)&UnaryFunction0DDouble_Type);
+
+ if (PyType_Ready(&DensityF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&DensityF0D_Type);
+ PyModule_AddObject(module, "DensityF0D", (PyObject *)&DensityF0D_Type);
+
+ if (PyType_Ready(&LocalAverageDepthF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&LocalAverageDepthF0D_Type);
+ PyModule_AddObject(module, "LocalAverageDepthF0D", (PyObject *)&LocalAverageDepthF0D_Type);
+
+ if (PyType_Ready(&Curvature2DAngleF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&Curvature2DAngleF0D_Type);
+ PyModule_AddObject(module, "Curvature2DAngleF0D", (PyObject *)&Curvature2DAngleF0D_Type);
+
+ if (PyType_Ready(&GetProjectedXF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetProjectedXF0D_Type);
+ PyModule_AddObject(module, "GetProjectedXF0D", (PyObject *)&GetProjectedXF0D_Type);
+
+ if (PyType_Ready(&GetProjectedYF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetProjectedYF0D_Type);
+ PyModule_AddObject(module, "GetProjectedYF0D", (PyObject *)&GetProjectedYF0D_Type);
+
+ if (PyType_Ready(&GetProjectedZF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetProjectedZF0D_Type);
+ PyModule_AddObject(module, "GetProjectedZF0D", (PyObject *)&GetProjectedZF0D_Type);
+
+ if (PyType_Ready(&GetXF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetXF0D_Type);
+ PyModule_AddObject(module, "GetXF0D", (PyObject *)&GetXF0D_Type);
+
+ if (PyType_Ready(&GetYF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetYF0D_Type);
+ PyModule_AddObject(module, "GetYF0D", (PyObject *)&GetYF0D_Type);
+
+ if (PyType_Ready(&GetZF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetZF0D_Type);
+ PyModule_AddObject(module, "GetZF0D", (PyObject *)&GetZF0D_Type);
+
+ if (PyType_Ready(&ZDiscontinuityF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&ZDiscontinuityF0D_Type);
+ PyModule_AddObject(module, "ZDiscontinuityF0D", (PyObject *)&ZDiscontinuityF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DDouble___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a float value.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DDouble___init__(BPy_UnaryFunction0DDouble *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->uf0D_double = new UnaryFunction0D<double>();
+ self->uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DDouble___dealloc__(BPy_UnaryFunction0DDouble *self)
+{
+ if (self->uf0D_double)
+ delete self->uf0D_double;
+ UnaryFunction0D_Type.tp_dealloc((PyObject *)self);
+}
+
+static PyObject *UnaryFunction0DDouble___repr__(BPy_UnaryFunction0DDouble *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->uf0D_double);
+}
+
+static PyObject *UnaryFunction0DDouble___call__(BPy_UnaryFunction0DDouble *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"it", NULL};
+ PyObject *obj;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if (typeid(*(self->uf0D_double)) == typeid(UnaryFunction0D<double>)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_double->operator()(*(((BPy_Interface0DIterator *)obj)->if0D_it)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return PyFloat_FromDouble(self->uf0D_double->result);
+}
+
+/*-----------------------BPy_UnaryFunction0DDouble type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DDouble_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DDouble", /* tp_name */
+ sizeof(BPy_UnaryFunction0DDouble), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DDouble___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DDouble___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DDouble___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DDouble___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 */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DDouble___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h
new file mode 100644
index 00000000000..4da5cbff435
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h
@@ -0,0 +1,65 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION0DDOUBLE_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION0DDOUBLE_H__
+
+#include "../BPy_UnaryFunction0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DDouble_Type;
+
+#define BPy_UnaryFunction0DDouble_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction0DDouble_Type))
+
+/*---------------------------Python BPy_UnaryFunction0DDouble structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<double> *uf0D_double;
+} BPy_UnaryFunction0DDouble;
+
+/*---------------------------Python BPy_UnaryFunction0DDouble visible prototypes-----------*/
+int UnaryFunction0DDouble_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION0DDOUBLE_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp
new file mode 100644
index 00000000000..de1a5ebe9f3
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp
@@ -0,0 +1,170 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction0DEdgeNature.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DEdgeNature_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction0DEdgeNature_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction0DEdgeNature_Type);
+ PyModule_AddObject(module, "UnaryFunction0DEdgeNature", (PyObject *)&UnaryFunction0DEdgeNature_Type);
+
+ if (PyType_Ready(&CurveNatureF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&CurveNatureF0D_Type);
+ PyModule_AddObject(module, "CurveNatureF0D", (PyObject *)&CurveNatureF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DEdgeNature___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DEdgeNature`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a :class:`Nature` object.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DEdgeNature___init__(BPy_UnaryFunction0DEdgeNature *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->uf0D_edgenature = new UnaryFunction0D<Nature::EdgeNature>();
+ self->uf0D_edgenature->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DEdgeNature___dealloc__(BPy_UnaryFunction0DEdgeNature *self)
+{
+ if (self->uf0D_edgenature)
+ delete self->uf0D_edgenature;
+ UnaryFunction0D_Type.tp_dealloc((PyObject *)self);
+}
+
+static PyObject *UnaryFunction0DEdgeNature___repr__(BPy_UnaryFunction0DEdgeNature *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->uf0D_edgenature);
+}
+
+static PyObject *UnaryFunction0DEdgeNature___call__(BPy_UnaryFunction0DEdgeNature *self,
+ PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"it", NULL};
+ PyObject *obj;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if (typeid(*(self->uf0D_edgenature)) == typeid(UnaryFunction0D<Nature::EdgeNature>)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_edgenature->operator()(*(((BPy_Interface0DIterator *)obj)->if0D_it)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return BPy_Nature_from_Nature(self->uf0D_edgenature->result);
+}
+
+/*-----------------------BPy_UnaryFunction0DEdgeNature type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DEdgeNature_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DEdgeNature", /* tp_name */
+ sizeof(BPy_UnaryFunction0DEdgeNature), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DEdgeNature___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DEdgeNature___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DEdgeNature___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DEdgeNature___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 */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DEdgeNature___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h
new file mode 100644
index 00000000000..8c4c71e634a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION0DEDGENATURE_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION0DEDGENATURE_H__
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include "../../winged_edge/Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DEdgeNature_Type;
+
+#define BPy_UnaryFunction0DEdgeNature_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction0DEdgeNature_Type))
+
+/*---------------------------Python BPy_UnaryFunction0DEdgeNature structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<Nature::EdgeNature> *uf0D_edgenature;
+} BPy_UnaryFunction0DEdgeNature;
+
+/*---------------------------Python BPy_UnaryFunction0DEdgeNature visible prototypes-----------*/
+int UnaryFunction0DEdgeNature_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION0DEDGENATURE_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp
new file mode 100644
index 00000000000..c191c691686
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp
@@ -0,0 +1,199 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction0DFloat.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h"
+#include "UnaryFunction0D_float/BPy_GetParameterF0D.h"
+#include "UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h"
+#include "UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h"
+#include "UnaryFunction0D_float/BPy_ReadMapPixelF0D.h"
+#include "UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DFloat_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction0DFloat_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction0DFloat_Type);
+ PyModule_AddObject(module, "UnaryFunction0DFloat", (PyObject *)&UnaryFunction0DFloat_Type);
+
+ if (PyType_Ready(&GetCurvilinearAbscissaF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetCurvilinearAbscissaF0D_Type);
+ PyModule_AddObject(module, "GetCurvilinearAbscissaF0D", (PyObject *)&GetCurvilinearAbscissaF0D_Type);
+
+ if (PyType_Ready(&GetParameterF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetParameterF0D_Type);
+ PyModule_AddObject(module, "GetParameterF0D", (PyObject *)&GetParameterF0D_Type);
+
+ if (PyType_Ready(&GetViewMapGradientNormF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetViewMapGradientNormF0D_Type);
+ PyModule_AddObject(module, "GetViewMapGradientNormF0D", (PyObject *)&GetViewMapGradientNormF0D_Type);
+
+ if (PyType_Ready(&ReadCompleteViewMapPixelF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&ReadCompleteViewMapPixelF0D_Type);
+ PyModule_AddObject(module, "ReadCompleteViewMapPixelF0D", (PyObject *)&ReadCompleteViewMapPixelF0D_Type);
+
+ if (PyType_Ready(&ReadMapPixelF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&ReadMapPixelF0D_Type);
+ PyModule_AddObject(module, "ReadMapPixelF0D", (PyObject *)&ReadMapPixelF0D_Type);
+
+ if (PyType_Ready(&ReadSteerableViewMapPixelF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&ReadSteerableViewMapPixelF0D_Type);
+ PyModule_AddObject(module, "ReadSteerableViewMapPixelF0D", (PyObject *)&ReadSteerableViewMapPixelF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DFloat___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a float value.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DFloat___init__(BPy_UnaryFunction0DFloat *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->uf0D_float = new UnaryFunction0D<float>();
+ self->uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DFloat___dealloc__(BPy_UnaryFunction0DFloat *self)
+{
+ if (self->uf0D_float)
+ delete self->uf0D_float;
+ UnaryFunction0D_Type.tp_dealloc((PyObject *)self);
+}
+
+static PyObject *UnaryFunction0DFloat___repr__(BPy_UnaryFunction0DFloat *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->uf0D_float);
+}
+
+static PyObject *UnaryFunction0DFloat___call__(BPy_UnaryFunction0DFloat *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"it", NULL};
+ PyObject *obj;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if (typeid(*(self->uf0D_float)) == typeid(UnaryFunction0D<float>)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_float->operator()(*(((BPy_Interface0DIterator *)obj)->if0D_it)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return PyFloat_FromDouble(self->uf0D_float->result);
+}
+
+/*-----------------------BPy_UnaryFunction0DFloat type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DFloat_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DFloat", /* tp_name */
+ sizeof(BPy_UnaryFunction0DFloat), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DFloat___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DFloat___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DFloat___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DFloat___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 */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DFloat___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h
new file mode 100644
index 00000000000..cd80c14328a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h
@@ -0,0 +1,65 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION0DFLOAT_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION0DFLOAT_H__
+
+#include "../BPy_UnaryFunction0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DFloat_Type;
+
+#define BPy_UnaryFunction0DFloat_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction0DFloat_Type))
+
+/*---------------------------Python BPy_UnaryFunction0DFloat structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<float> *uf0D_float;
+} BPy_UnaryFunction0DFloat;
+
+/*---------------------------Python BPy_UnaryFunction0DFloat visible prototypes-----------*/
+int UnaryFunction0DFloat_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION0DFLOAT_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp
new file mode 100644
index 00000000000..d6374208649
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp
@@ -0,0 +1,169 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction0DId.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_Id/BPy_ShapeIdF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DId_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction0DId_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction0DId_Type);
+ PyModule_AddObject(module, "UnaryFunction0DId", (PyObject *)&UnaryFunction0DId_Type);
+
+ if (PyType_Ready(&ShapeIdF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&ShapeIdF0D_Type);
+ PyModule_AddObject(module, "ShapeIdF0D", (PyObject *)&ShapeIdF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DId___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DId`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return an :class:`Id` object.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DId___init__(BPy_UnaryFunction0DId *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->uf0D_id = new UnaryFunction0D<Id>();
+ self->uf0D_id->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DId___dealloc__(BPy_UnaryFunction0DId *self)
+{
+ if (self->uf0D_id)
+ delete self->uf0D_id;
+ UnaryFunction0D_Type.tp_dealloc((PyObject *)self);
+}
+
+static PyObject *UnaryFunction0DId___repr__(BPy_UnaryFunction0DId *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->uf0D_id);
+}
+
+static PyObject *UnaryFunction0DId___call__(BPy_UnaryFunction0DId *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"it", NULL};
+ PyObject *obj;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if (typeid(*(self->uf0D_id)) == typeid(UnaryFunction0D<Id>)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_id->operator()(*(((BPy_Interface0DIterator *)obj)->if0D_it)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return BPy_Id_from_Id(self->uf0D_id->result);
+}
+
+/*-----------------------BPy_UnaryFunction0DId type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DId_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DId", /* tp_name */
+ sizeof(BPy_UnaryFunction0DId), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DId___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DId___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DId___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DId___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 */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DId___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h
new file mode 100644
index 00000000000..3522abd174c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION0DID_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION0DID_H__
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include "../../system/Id.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DId_Type;
+
+#define BPy_UnaryFunction0DId_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction0DId_Type))
+
+/*---------------------------Python BPy_UnaryFunction0DId structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<Id> *uf0D_id;
+} BPy_UnaryFunction0DId;
+
+/*---------------------------Python BPy_UnaryFunction0DId visible prototypes-----------*/
+int UnaryFunction0DId_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION0DID_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp
new file mode 100644
index 00000000000..67ff21d41e5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp
@@ -0,0 +1,169 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction0DMaterial.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_Material/BPy_MaterialF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DMaterial_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction0DMaterial_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction0DMaterial_Type);
+ PyModule_AddObject(module, "UnaryFunction0DMaterial", (PyObject *)&UnaryFunction0DMaterial_Type);
+
+ if (PyType_Ready(&MaterialF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&MaterialF0D_Type);
+ PyModule_AddObject(module, "MaterialF0D", (PyObject *)&MaterialF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DMaterial___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DMaterial`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a :class:`Material` object.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DMaterial___init__(BPy_UnaryFunction0DMaterial *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->uf0D_material = new UnaryFunction0D<FrsMaterial>();
+ self->uf0D_material->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DMaterial___dealloc__(BPy_UnaryFunction0DMaterial *self)
+{
+ if (self->uf0D_material)
+ delete self->uf0D_material;
+ UnaryFunction0D_Type.tp_dealloc((PyObject *)self);
+}
+
+static PyObject *UnaryFunction0DMaterial___repr__(BPy_UnaryFunction0DMaterial *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->uf0D_material);
+}
+
+static PyObject *UnaryFunction0DMaterial___call__(BPy_UnaryFunction0DMaterial *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"it", NULL};
+ PyObject *obj;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if (typeid(*(self->uf0D_material)) == typeid(UnaryFunction0D<FrsMaterial>)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_material->operator()(*(((BPy_Interface0DIterator *)obj)->if0D_it)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return BPy_FrsMaterial_from_FrsMaterial(self->uf0D_material->result);
+}
+
+/*-----------------------BPy_UnaryFunction0DMaterial type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DMaterial_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DMaterial", /* tp_name */
+ sizeof(BPy_UnaryFunction0DMaterial), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DMaterial___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DMaterial___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DMaterial___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DMaterial___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 */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DMaterial___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h
new file mode 100644
index 00000000000..c805ca090d1
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION0DMATERIAL_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION0DMATERIAL_H__
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include "../../scene_graph/FrsMaterial.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DMaterial_Type;
+
+#define BPy_UnaryFunction0DMaterial_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction0DMaterial_Type))
+
+/*---------------------------Python BPy_UnaryFunction0DMaterial structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<FrsMaterial> *uf0D_material;
+} BPy_UnaryFunction0DMaterial;
+
+/*---------------------------Python BPy_UnaryFunction0DMaterial visible prototypes-----------*/
+int UnaryFunction0DMaterial_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION0DMATERIAL_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp
new file mode 100644
index 00000000000..b6f0ba44660
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp
@@ -0,0 +1,169 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction0DUnsigned.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DUnsigned_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction0DUnsigned_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction0DUnsigned_Type);
+ PyModule_AddObject(module, "UnaryFunction0DUnsigned", (PyObject *)&UnaryFunction0DUnsigned_Type);
+
+ if (PyType_Ready(&QuantitativeInvisibilityF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&QuantitativeInvisibilityF0D_Type);
+ PyModule_AddObject(module, "QuantitativeInvisibilityF0D", (PyObject *)&QuantitativeInvisibilityF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DUnsigned___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DUnsigned`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return an int value.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+ " Default constructor.\n";
+
+static int UnaryFunction0DUnsigned___init__(BPy_UnaryFunction0DUnsigned *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->uf0D_unsigned = new UnaryFunction0D<unsigned int>();
+ self->uf0D_unsigned->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DUnsigned___dealloc__(BPy_UnaryFunction0DUnsigned *self)
+{
+ if (self->uf0D_unsigned)
+ delete self->uf0D_unsigned;
+ UnaryFunction0D_Type.tp_dealloc((PyObject *)self);
+}
+
+static PyObject *UnaryFunction0DUnsigned___repr__(BPy_UnaryFunction0DUnsigned *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->uf0D_unsigned);
+}
+
+static PyObject *UnaryFunction0DUnsigned___call__(BPy_UnaryFunction0DUnsigned *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"it", NULL};
+ PyObject *obj;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if (typeid(*(self->uf0D_unsigned)) == typeid(UnaryFunction0D<unsigned int>)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_unsigned->operator()(*(((BPy_Interface0DIterator *)obj)->if0D_it)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return PyLong_FromLong(self->uf0D_unsigned->result);
+}
+
+/*-----------------------BPy_UnaryFunction0DUnsigned type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DUnsigned_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DUnsigned", /* tp_name */
+ sizeof(BPy_UnaryFunction0DUnsigned), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DUnsigned___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DUnsigned___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DUnsigned___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DUnsigned___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 */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DUnsigned___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h
new file mode 100644
index 00000000000..21b5d2d835c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION0DUNSIGNED_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION0DUNSIGNED_H__
+
+#include "../BPy_UnaryFunction0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DUnsigned_Type;
+
+#define BPy_UnaryFunction0DUnsigned_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction0DUnsigned_Type))
+
+/*---------------------------Python BPy_UnaryFunction0DUnsigned structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<unsigned int> *uf0D_unsigned;
+} BPy_UnaryFunction0DUnsigned;
+
+/*---------------------------Python BPy_UnaryFunction0DUnsigned visible prototypes-----------*/
+int UnaryFunction0DUnsigned_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION0DUNSIGNED_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp
new file mode 100644
index 00000000000..f672919b194
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp
@@ -0,0 +1,175 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction0DVec2f.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h"
+#include "UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DVec2f_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction0DVec2f_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction0DVec2f_Type);
+ PyModule_AddObject(module, "UnaryFunction0DVec2f", (PyObject *)&UnaryFunction0DVec2f_Type);
+
+ if (PyType_Ready(&Normal2DF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&Normal2DF0D_Type);
+ PyModule_AddObject(module, "Normal2DF0D", (PyObject *)&Normal2DF0D_Type);
+
+ if (PyType_Ready(&VertexOrientation2DF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&VertexOrientation2DF0D_Type);
+ PyModule_AddObject(module, "VertexOrientation2DF0D", (PyObject *)&VertexOrientation2DF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DVec2f___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DVec2f`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a 2D vector.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DVec2f___init__(BPy_UnaryFunction0DVec2f *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->uf0D_vec2f = new UnaryFunction0D<Vec2f>();
+ self->uf0D_vec2f->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DVec2f___dealloc__(BPy_UnaryFunction0DVec2f *self)
+{
+ if (self->uf0D_vec2f)
+ delete self->uf0D_vec2f;
+ UnaryFunction0D_Type.tp_dealloc((PyObject *)self);
+}
+
+static PyObject *UnaryFunction0DVec2f___repr__(BPy_UnaryFunction0DVec2f *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->uf0D_vec2f);
+}
+
+static PyObject *UnaryFunction0DVec2f___call__(BPy_UnaryFunction0DVec2f *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"it", NULL};
+ PyObject *obj;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if (typeid(*(self->uf0D_vec2f)) == typeid(UnaryFunction0D<Vec2f>)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_vec2f->operator()(*(((BPy_Interface0DIterator *)obj)->if0D_it)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return Vector_from_Vec2f(self->uf0D_vec2f->result);
+}
+
+/*-----------------------BPy_UnaryFunction0DVec2f type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DVec2f_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DVec2f", /* tp_name */
+ sizeof(BPy_UnaryFunction0DVec2f), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DVec2f___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DVec2f___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DVec2f___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DVec2f___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 */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DVec2f___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h
new file mode 100644
index 00000000000..ab5b8e3fe09
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION0DVEC2F_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION0DVEC2F_H__
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include "../../geometry/Geom.h"
+using namespace Geometry;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DVec2f_Type;
+
+#define BPy_UnaryFunction0DVec2f_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction0DVec2f_Type))
+
+/*---------------------------Python BPy_UnaryFunction0DVec2f structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<Vec2f> *uf0D_vec2f;
+} BPy_UnaryFunction0DVec2f;
+
+/*---------------------------Python BPy_UnaryFunction0DVec2f visible prototypes-----------*/
+int UnaryFunction0DVec2f_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION0DVEC2F_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp
new file mode 100644
index 00000000000..fc6c56457f7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp
@@ -0,0 +1,169 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction0DVec3f.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DVec3f_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction0DVec3f_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction0DVec3f_Type);
+ PyModule_AddObject(module, "UnaryFunction0DVec3f", (PyObject *)&UnaryFunction0DVec3f_Type);
+
+ if (PyType_Ready(&VertexOrientation3DF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&VertexOrientation3DF0D_Type);
+ PyModule_AddObject(module, "VertexOrientation3DF0D", (PyObject *)&VertexOrientation3DF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DVec3f___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DVec3f`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a 3D vector.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DVec3f___init__(BPy_UnaryFunction0DVec3f *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->uf0D_vec3f = new UnaryFunction0D<Vec3f>();
+ self->uf0D_vec3f->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DVec3f___dealloc__(BPy_UnaryFunction0DVec3f *self)
+{
+ if (self->uf0D_vec3f)
+ delete self->uf0D_vec3f;
+ UnaryFunction0D_Type.tp_dealloc((PyObject *)self);
+}
+
+static PyObject *UnaryFunction0DVec3f___repr__(BPy_UnaryFunction0DVec3f *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->uf0D_vec3f);
+}
+
+static PyObject *UnaryFunction0DVec3f___call__(BPy_UnaryFunction0DVec3f *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"it", NULL};
+ PyObject *obj;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if (typeid(*(self->uf0D_vec3f)) == typeid(UnaryFunction0D<Vec3f>)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_vec3f->operator()(*(((BPy_Interface0DIterator *)obj)->if0D_it)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return Vector_from_Vec3f(self->uf0D_vec3f->result);
+}
+
+/*-----------------------BPy_UnaryFunction0DVec3f type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DVec3f_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DVec3f", /* tp_name */
+ sizeof(BPy_UnaryFunction0DVec3f), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DVec3f___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DVec3f___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DVec3f___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DVec3f___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 */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DVec3f___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h
new file mode 100644
index 00000000000..1beb0e97932
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION0DVEC3F_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION0DVEC3F_H__
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include "../../geometry/Geom.h"
+using namespace Geometry;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DVec3f_Type;
+
+#define BPy_UnaryFunction0DVec3f_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction0DVec3f_Type))
+
+/*---------------------------Python BPy_UnaryFunction0DVec3f structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<Vec3f> *uf0D_vec3f;
+} BPy_UnaryFunction0DVec3f;
+
+/*---------------------------Python BPy_UnaryFunction0DVec3f visible prototypes-----------*/
+int UnaryFunction0DVec3f_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION0DVEC3F_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp
new file mode 100644
index 00000000000..cf35b6168bc
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp
@@ -0,0 +1,186 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction0DVectorViewShape.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DVectorViewShape_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction0DVectorViewShape_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction0DVectorViewShape_Type);
+ PyModule_AddObject(module, "UnaryFunction0DVectorViewShape", (PyObject *)&UnaryFunction0DVectorViewShape_Type);
+
+ if (PyType_Ready(&GetOccludersF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetOccludersF0D_Type);
+ PyModule_AddObject(module, "GetOccludersF0D", (PyObject *)&GetOccludersF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DVectorViewShape___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DVectorViewShape`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a list of :class:`ViewShape`\n"
+"objects.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DVectorViewShape___init__(BPy_UnaryFunction0DVectorViewShape *self,
+ PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->uf0D_vectorviewshape = new UnaryFunction0D< std::vector<ViewShape*> >();
+ self->uf0D_vectorviewshape->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DVectorViewShape___dealloc__(BPy_UnaryFunction0DVectorViewShape *self)
+{
+ if (self->uf0D_vectorviewshape)
+ delete self->uf0D_vectorviewshape;
+ UnaryFunction0D_Type.tp_dealloc((PyObject *)self);
+}
+
+static PyObject *UnaryFunction0DVectorViewShape___repr__(BPy_UnaryFunction0DVectorViewShape *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->uf0D_vectorviewshape);
+}
+
+static PyObject *UnaryFunction0DVectorViewShape___call__(BPy_UnaryFunction0DVectorViewShape *self,
+ PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"it", NULL};
+ PyObject *obj;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if (typeid(*(self->uf0D_vectorviewshape)) == typeid(UnaryFunction0D< std::vector<ViewShape*> >)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_vectorviewshape->operator()(*(((BPy_Interface0DIterator *)obj)->if0D_it)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ PyObject *list = PyList_New(0);
+ PyObject *item;
+ for (unsigned int i = 0; i < self->uf0D_vectorviewshape->result.size(); 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);
+ }
+
+ return list;
+}
+
+/*-----------------------BPy_UnaryFunction0DVectorViewShape type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DVectorViewShape_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DVectorViewShape", /* tp_name */
+ sizeof(BPy_UnaryFunction0DVectorViewShape), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DVectorViewShape___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DVectorViewShape___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DVectorViewShape___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DVectorViewShape___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 */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DVectorViewShape___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h
new file mode 100644
index 00000000000..38b38e393d3
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION0DVECTORVIEWSHAPE_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION0DVECTORVIEWSHAPE_H__
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include <vector>
+#include "../../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DVectorViewShape_Type;
+
+#define BPy_UnaryFunction0DVectorViewShape_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction0DVectorViewShape_Type))
+
+/*---------------------------Python BPy_UnaryFunction0DVectorViewShape structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D< std::vector<ViewShape*> > *uf0D_vectorviewshape;
+} BPy_UnaryFunction0DVectorViewShape;
+
+/*---------------------------Python BPy_UnaryFunction0DVectorViewShape visible prototypes-----------*/
+int UnaryFunction0DVectorViewShape_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION0DVECTORVIEWSHAPE_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp
new file mode 100644
index 00000000000..5d8d8c70fff
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp
@@ -0,0 +1,175 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction0DViewShape.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h"
+#include "UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DViewShape_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction0DViewShape_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction0DViewShape_Type);
+ PyModule_AddObject(module, "UnaryFunction0DViewShape", (PyObject *)&UnaryFunction0DViewShape_Type);
+
+ if (PyType_Ready(&GetOccludeeF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetOccludeeF0D_Type);
+ PyModule_AddObject(module, "GetOccludeeF0D", (PyObject *)&GetOccludeeF0D_Type);
+
+ if (PyType_Ready(&GetShapeF0D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetShapeF0D_Type);
+ PyModule_AddObject(module, "GetShapeF0D", (PyObject *)&GetShapeF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DViewShape___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DViewShape`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a :class:`ViewShape` object.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DViewShape___init__(BPy_UnaryFunction0DViewShape *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->uf0D_viewshape = new UnaryFunction0D<ViewShape*>();
+ self->uf0D_viewshape->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DViewShape___dealloc__(BPy_UnaryFunction0DViewShape *self)
+{
+ if (self->uf0D_viewshape)
+ delete self->uf0D_viewshape;
+ UnaryFunction0D_Type.tp_dealloc((PyObject *)self);
+}
+
+static PyObject *UnaryFunction0DViewShape___repr__(BPy_UnaryFunction0DViewShape *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->uf0D_viewshape);
+}
+
+static PyObject *UnaryFunction0DViewShape___call__(BPy_UnaryFunction0DViewShape *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"it", NULL};
+ PyObject *obj;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if (typeid(*(self->uf0D_viewshape)) == typeid(UnaryFunction0D<ViewShape*>)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_viewshape->operator()(*(((BPy_Interface0DIterator *)obj)->if0D_it)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return BPy_ViewShape_from_ViewShape(*(self->uf0D_viewshape->result));
+}
+
+/*-----------------------BPy_UnaryFunction0DViewShape type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DViewShape_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DViewShape", /* tp_name */
+ sizeof(BPy_UnaryFunction0DViewShape), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DViewShape___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DViewShape___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DViewShape___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DViewShape___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 */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DViewShape___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h
new file mode 100644
index 00000000000..7a7e4923a2b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION0DVIEWSHAPE_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION0DVIEWSHAPE_H__
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include "../../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DViewShape_Type;
+
+#define BPy_UnaryFunction0DViewShape_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction0DViewShape_Type))
+
+/*---------------------------Python BPy_UnaryFunction0DViewShape structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<ViewShape*> *uf0D_viewshape;
+} BPy_UnaryFunction0DViewShape;
+
+/*---------------------------Python BPy_UnaryFunction0DViewShape visible prototypes-----------*/
+int UnaryFunction0DViewShape_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION0DVIEWSHAPE_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp
new file mode 100644
index 00000000000..5259512953a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp
@@ -0,0 +1,125 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ShapeIdF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ShapeIdF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DId` > :class:`ShapeIdF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a ShapeIdF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the :class:`Id` of the Shape the :class:`Interface0D`\n"
+" pointed by the Interface0DIterator belongs to. This evaluation can\n"
+" be ambiguous (in the case of a :class:`TVertex` for example). This\n"
+" functor tries to remove this ambiguity using the context offered by\n"
+" the 1D element to which the Interface0DIterator belongs to.\n"
+" However, there still can be problematic cases, and the user willing\n"
+" to deal with this cases in a specific way should implement its own\n"
+" getShapeIdF0D functor.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The Id of the Shape the pointed Interface0D belongs to.\n"
+" :rtype: :class:`Id`\n";
+
+static int ShapeIdF0D___init__(BPy_ShapeIdF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_id.uf0D_id = new Functions0D::ShapeIdF0D();
+ self->py_uf0D_id.uf0D_id->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_ShapeIdF0D type definition ------------------------------*/
+
+PyTypeObject ShapeIdF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ShapeIdF0D", /* tp_name */
+ sizeof(BPy_ShapeIdF0D), /* 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 */
+ ShapeIdF0D___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 */
+ &UnaryFunction0DId_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ShapeIdF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.h
new file mode 100644
index 00000000000..a32743d26a5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_SHAPEIDF0D_H__
+#define __FREESTYLE_PYTHON_SHAPEIDF0D_H__
+
+#include "../BPy_UnaryFunction0DId.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ShapeIdF0D_Type;
+
+#define BPy_ShapeIdF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ShapeIdF0D_Type))
+
+/*---------------------------Python BPy_ShapeIdF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DId py_uf0D_id;
+} BPy_ShapeIdF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_SHAPEIDF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp
new file mode 100644
index 00000000000..1d3defd3583
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_MaterialF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char MaterialF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DMaterial` > :class:`MaterialF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a MaterialF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the material of the object evaluated at the\n"
+" :class:`Interface0D` pointed by the Interface0DIterator. This\n"
+" evaluation can be ambiguous (in the case of a :class:`TVertex` for\n"
+" example. This functor tries to remove this ambiguity using the\n"
+" context offered by the 1D element to which the Interface0DIterator\n"
+" belongs to and by arbitrary chosing the material of the face that\n"
+" lies on its left when following the 1D element if there are two\n"
+" different materials on each side of the point. However, there\n"
+" still can be problematic cases, and the user willing to deal with\n"
+" this cases in a specific way should implement its own getMaterial\n"
+" functor.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The material of the object evaluated at the pointed\n"
+" Interface0D.\n"
+" :rtype: :class:`Material`\n";
+
+static int MaterialF0D___init__(BPy_MaterialF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_material.uf0D_material = new Functions0D::MaterialF0D();
+ self->py_uf0D_material.uf0D_material->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_MaterialF0D type definition ------------------------------*/
+
+PyTypeObject MaterialF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "MaterialF0D", /* tp_name */
+ sizeof(BPy_MaterialF0D), /* 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 */
+ MaterialF0D___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 */
+ &UnaryFunction0DMaterial_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)MaterialF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.h
new file mode 100644
index 00000000000..545fe0cee75
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_MATERIALF0D_H__
+#define __FREESTYLE_PYTHON_MATERIALF0D_H__
+
+#include "../BPy_UnaryFunction0DMaterial.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject MaterialF0D_Type;
+
+#define BPy_MaterialF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&MaterialF0D_Type))
+
+/*---------------------------Python BPy_MaterialF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DMaterial py_uf0D_material;
+} BPy_MaterialF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_MATERIALF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp
new file mode 100644
index 00000000000..5f46bb17324
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp
@@ -0,0 +1,120 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_CurveNatureF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char CurveNatureF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DEdgeNature` > :class:`CurveNatureF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a CurveNatureF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the :class:`Nature` of the 1D element the Interface0D pointed\n"
+" by the Interface0DIterator belongs to.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The nature of the 1D element to which the pointed Interface0D\n"
+" belongs.\n"
+" :rtype: :class:`Nature`\n";
+
+static int CurveNatureF0D___init__(BPy_CurveNatureF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_edgenature.uf0D_edgenature = new Functions0D::CurveNatureF0D();
+ self->py_uf0D_edgenature.uf0D_edgenature->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_CurveNatureF0D type definition ------------------------------*/
+
+PyTypeObject CurveNatureF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "CurveNatureF0D", /* tp_name */
+ sizeof(BPy_CurveNatureF0D), /* 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 */
+ CurveNatureF0D___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 */
+ &UnaryFunction0DEdgeNature_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)CurveNatureF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h
new file mode 100644
index 00000000000..9671a5b3223
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_CURVENATUREF0D_H__
+#define __FREESTYLE_PYTHON_CURVENATUREF0D_H__
+
+#include "../BPy_UnaryFunction0DEdgeNature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject CurveNatureF0D_Type;
+
+#define BPy_CurveNatureF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&CurveNatureF0D_Type))
+
+/*---------------------------Python BPy_CurveNatureF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DEdgeNature py_uf0D_edgenature;
+} BPy_CurveNatureF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_CURVENATUREF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp
new file mode 100644
index 00000000000..21e33597568
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_Normal2DF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Normal2DF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DVec2f` > :class:`Normal2DF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a Normal2DF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns a two-dimensional vector giving the normalized 2D normal to\n"
+" the 1D element to which the :class:`Interface0D` pointed by the\n"
+" Interface0DIterator belongs. The normal is evaluated at the pointed\n"
+" Interface0D.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The 2D normal of the 1D element evaluated at the pointed\n"
+" Interface0D.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static int Normal2DF0D___init__(BPy_Normal2DF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_vec2f.uf0D_vec2f = new Functions0D::Normal2DF0D();
+ self->py_uf0D_vec2f.uf0D_vec2f->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_Normal2DF0D type definition ------------------------------*/
+
+PyTypeObject Normal2DF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Normal2DF0D", /* tp_name */
+ sizeof(BPy_Normal2DF0D), /* 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 */
+ Normal2DF0D___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 */
+ &UnaryFunction0DVec2f_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Normal2DF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h
new file mode 100644
index 00000000000..2e1e578760d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_NORMAL2DF0D_H__
+#define __FREESTYLE_PYTHON_NORMAL2DF0D_H__
+
+#include "../BPy_UnaryFunction0DVec2f.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Normal2DF0D_Type;
+
+#define BPy_Normal2DF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Normal2DF0D_Type))
+
+/*---------------------------Python BPy_Normal2DF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DVec2f py_uf0D_vec2f;
+} BPy_Normal2DF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_NORMAL2DF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp
new file mode 100644
index 00000000000..db5ca4a8aa6
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_VertexOrientation2DF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char VertexOrientation2DF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DVec2f` > :class:`VertexOrientation2DF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a VertexOrientation2DF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns a two-dimensional vector giving the 2D oriented tangent to\n"
+" the 1D element to which the :class:`Interface0D` pointed by the\n"
+" Interface0DIterator belongs. The 2D oriented tangent is evaluated\n"
+" at the pointed Interface0D.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The 2D oriented tangent to the 1D element evaluated at the\n"
+" pointed Interface0D.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static int VertexOrientation2DF0D___init__(BPy_VertexOrientation2DF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_vec2f.uf0D_vec2f = new Functions0D::VertexOrientation2DF0D();
+ self->py_uf0D_vec2f.uf0D_vec2f->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_VertexOrientation2DF0D type definition ------------------------------*/
+
+PyTypeObject VertexOrientation2DF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "VertexOrientation2DF0D", /* tp_name */
+ sizeof(BPy_VertexOrientation2DF0D), /* 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 */
+ VertexOrientation2DF0D___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 */
+ &UnaryFunction0DVec2f_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)VertexOrientation2DF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h
new file mode 100644
index 00000000000..364947dfee0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_VERTEXORIENTATION2DF0D_H__
+#define __FREESTYLE_PYTHON_VERTEXORIENTATION2DF0D_H__
+
+#include "../BPy_UnaryFunction0DVec2f.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject VertexOrientation2DF0D_Type;
+
+#define BPy_VertexOrientation2DF0D_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&VertexOrientation2DF0D_Type))
+
+/*---------------------------Python BPy_VertexOrientation2DF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DVec2f py_uf0D_vec2f;
+} BPy_VertexOrientation2DF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_VERTEXORIENTATION2DF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp
new file mode 100644
index 00000000000..c6ede5cb7a5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_VertexOrientation3DF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char VertexOrientation3DF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DVec3f` > :class:`VertexOrientation3DF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a VertexOrientation3DF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns a three-dimensional vector giving the 3D oriented tangent\n"
+" to the 1D element to which the :class:`Interface0D` pointed by the\n"
+" Interface0DIterator belongs. The 3D oriented tangent is evaluated\n"
+" at the pointed Interface0D.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The 3D oriented tangent to the 1D element evaluated at the\n"
+" pointed Interface0D.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static int VertexOrientation3DF0D___init__(BPy_VertexOrientation3DF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_vec3f.uf0D_vec3f = new Functions0D::VertexOrientation3DF0D();
+ self->py_uf0D_vec3f.uf0D_vec3f->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_VertexOrientation3DF0D type definition ------------------------------*/
+
+PyTypeObject VertexOrientation3DF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "VertexOrientation3DF0D", /* tp_name */
+ sizeof(BPy_VertexOrientation3DF0D), /* 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 */
+ VertexOrientation3DF0D___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 */
+ &UnaryFunction0DVec3f_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)VertexOrientation3DF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h
new file mode 100644
index 00000000000..fd8cd7b7173
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_VERTEXORIENTATION3DF0D_H__
+#define __FREESTYLE_PYTHON_VERTEXORIENTATION3DF0D_H__
+
+#include "../BPy_UnaryFunction0DVec3f.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject VertexOrientation3DF0D_Type;
+
+#define BPy_VertexOrientation3DF0D_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&VertexOrientation3DF0D_Type))
+
+/*---------------------------Python BPy_VertexOrientation3DF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DVec3f py_uf0D_vec3f;
+} BPy_VertexOrientation3DF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_VERTEXORIENTATION3DF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp
new file mode 100644
index 00000000000..e36de70e99a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetOccludeeF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetOccludeeF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DViewShape` > :class:`GetOccludeeF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetOccludeeF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the :class:`ViewShape` that the Interface0D pointed by the\n"
+" Interface0DIterator occludes.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The ViewShape occluded by the pointed Interface0D.\n"
+" :rtype: :class:`ViewShape`\n";
+
+static int GetOccludeeF0D___init__(BPy_GetOccludeeF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_viewshape.uf0D_viewshape = new Functions0D::GetOccludeeF0D();
+ self->py_uf0D_viewshape.uf0D_viewshape->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetOccludeeF0D type definition ------------------------------*/
+
+PyTypeObject GetOccludeeF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetOccludeeF0D", /* tp_name */
+ sizeof(BPy_GetOccludeeF0D), /* 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 */
+ GetOccludeeF0D___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 */
+ &UnaryFunction0DViewShape_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetOccludeeF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h
new file mode 100644
index 00000000000..7b4ed05e452
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETOCCLUDEEF0D_H__
+#define __FREESTYLE_PYTHON_GETOCCLUDEEF0D_H__
+
+#include "../BPy_UnaryFunction0DViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetOccludeeF0D_Type;
+
+#define BPy_GetOccludeeF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetOccludeeF0D_Type))
+
+/*---------------------------Python BPy_GetOccludeeF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DViewShape py_uf0D_viewshape;
+} BPy_GetOccludeeF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETOCCLUDEEF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp
new file mode 100644
index 00000000000..c0d34ea0274
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetShapeF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetShapeF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DViewShape` > :class:`GetShapeF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetShapeF0D.cpp object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the :class:`ViewShape` containing the Interface0D pointed\n"
+" by the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The ViewShape containing the pointed Interface0D.\n"
+" :rtype: :class:`ViewShape`\n";
+
+static int GetShapeF0D___init__(BPy_GetShapeF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_viewshape.uf0D_viewshape = new Functions0D::GetShapeF0D();
+ self->py_uf0D_viewshape.uf0D_viewshape->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetShapeF0D type definition ------------------------------*/
+
+PyTypeObject GetShapeF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetShapeF0D", /* tp_name */
+ sizeof(BPy_GetShapeF0D), /* 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 */
+ GetShapeF0D___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 */
+ &UnaryFunction0DViewShape_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetShapeF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h
new file mode 100644
index 00000000000..392b6deb00a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETSHAPEF0D_H__
+#define __FREESTYLE_PYTHON_GETSHAPEF0D_H__
+
+#include "../BPy_UnaryFunction0DViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetShapeF0D_Type;
+
+#define BPy_GetShapeF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetShapeF0D_Type))
+
+/*---------------------------Python BPy_GetShapeF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DViewShape py_uf0D_viewshape;
+} BPy_GetShapeF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETSHAPEF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp
new file mode 100644
index 00000000000..754fadc9753
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_Curvature2DAngleF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Curvature2DAngleF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`Curvature2DAngleF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a Curvature2DAngleF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns a real value giving the 2D curvature (as an angle) of the\n"
+" 1D element to which the :class:`Interface0D` pointed by the\n"
+" Interface0DIterator belongs. The 2D curvature is evaluated at the\n"
+" Interface0D.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The 2D curvature of the 1D element evaluated at the\n"
+" pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int Curvature2DAngleF0D___init__(BPy_Curvature2DAngleF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::Curvature2DAngleF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_Curvature2DAngleF0D type definition ------------------------------*/
+
+PyTypeObject Curvature2DAngleF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Curvature2DAngleF0D", /* tp_name */
+ sizeof(BPy_Curvature2DAngleF0D), /* 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 */
+ Curvature2DAngleF0D___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 */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Curvature2DAngleF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h
new file mode 100644
index 00000000000..d9b64e641f2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_CURVATURE2DANGLEF0D_H__
+#define __FREESTYLE_PYTHON_CURVATURE2DANGLEF0D_H__
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Curvature2DAngleF0D_Type;
+
+#define BPy_Curvature2DAngleF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Curvature2DAngleF0D_Type))
+
+/*---------------------------Python BPy_Curvature2DAngleF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_Curvature2DAngleF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_CURVATURE2DANGLEF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp
new file mode 100644
index 00000000000..8f2c18486da
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp
@@ -0,0 +1,128 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_DensityF0D.h"
+
+#include "../../../stroke/AdvancedFunctions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char DensityF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`DensityF0D`\n"
+"\n"
+".. method:: __init__(sigma=2.0)\n"
+"\n"
+" Builds a DensityF0D object.\n"
+"\n"
+" :arg sigma: The gaussian sigma value indicating the X value for\n"
+" which the gaussian function is 0.5. It leads to the window size\n"
+" value (the larger, the smoother).\n"
+" :type sigma: float\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the density of the (result) image evaluated at the\n"
+" :class:`Interface0D` pointed by the Interface0DIterator. This\n"
+" density is evaluated using a pixels square window around the\n"
+" evaluation point and integrating these values using a gaussian.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The density of the image evaluated at the pointed\n"
+" Interface0D.\n"
+" :rtype: float\n";
+
+static int DensityF0D___init__(BPy_DensityF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"sigma", NULL};
+ double d = 2;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|d", (char **)kwlist, &d))
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::DensityF0D(d);
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_DensityF0D type definition ------------------------------*/
+
+PyTypeObject DensityF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "DensityF0D", /* tp_name */
+ sizeof(BPy_DensityF0D), /* 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 */
+ DensityF0D___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 */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)DensityF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.h
new file mode 100644
index 00000000000..54da109e985
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_DENSITYF0D_H__
+#define __FREESTYLE_PYTHON_DENSITYF0D_H__
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject DensityF0D_Type;
+
+#define BPy_DensityF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&DensityF0D_Type))
+
+/*---------------------------Python BPy_DensityF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_DensityF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_DENSITYF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp
new file mode 100644
index 00000000000..a87a7d536a5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetProjectedXF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetProjectedXF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`GetProjectedXF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetProjectedXF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the X 3D projected coordinate of the :class:`Interface0D`\n"
+" pointed by the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The X 3D projected coordinate of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetProjectedXF0D___init__(BPy_GetProjectedXF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::GetProjectedXF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetProjectedXF0D type definition ------------------------------*/
+
+PyTypeObject GetProjectedXF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetProjectedXF0D", /* tp_name */
+ sizeof(BPy_GetProjectedXF0D), /* 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 */
+ GetProjectedXF0D___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 */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetProjectedXF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.h
new file mode 100644
index 00000000000..101ebbb54be
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETPROJECTEDXF0D_H__
+#define __FREESTYLE_PYTHON_GETPROJECTEDXF0D_H__
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetProjectedXF0D_Type;
+
+#define BPy_GetProjectedXF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetProjectedXF0D_Type))
+
+/*---------------------------Python BPy_GetProjectedXF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_GetProjectedXF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETPROJECTEDXF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp
new file mode 100644
index 00000000000..18cfc014e90
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetProjectedYF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetProjectedYF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`GetProjectedYF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetProjectedYF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the Y 3D projected coordinate of the :class:`Interface0D`\n"
+" pointed by the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The Y 3D projected coordinate of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetProjectedYF0D___init__(BPy_GetProjectedYF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::GetProjectedYF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetProjectedYF0D type definition ------------------------------*/
+
+PyTypeObject GetProjectedYF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetProjectedYF0D", /* tp_name */
+ sizeof(BPy_GetProjectedYF0D), /* 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 */
+ GetProjectedYF0D___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 */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetProjectedYF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.h
new file mode 100644
index 00000000000..c09858f249a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETPROJECTEDYF0D_H__
+#define __FREESTYLE_PYTHON_GETPROJECTEDYF0D_H__
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetProjectedYF0D_Type;
+
+#define BPy_GetProjectedYF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetProjectedYF0D_Type))
+
+/*---------------------------Python BPy_GetProjectedYF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_GetProjectedYF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETPROJECTEDYF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp
new file mode 100644
index 00000000000..c587b978c16
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetProjectedZF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetProjectedZF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`GetProjectedZF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetProjectedZF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the Z 3D projected coordinate of the :class:`Interface0D`\n"
+" pointed by the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The Z 3D projected coordinate of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetProjectedZF0D___init__(BPy_GetProjectedZF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::GetProjectedZF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetProjectedZF0D type definition ------------------------------*/
+
+PyTypeObject GetProjectedZF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetProjectedZF0D", /* tp_name */
+ sizeof(BPy_GetProjectedZF0D), /* 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 */
+ GetProjectedZF0D___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 */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetProjectedZF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.h
new file mode 100644
index 00000000000..224b8544730
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETPROJECTEDZF0D_H__
+#define __FREESTYLE_PYTHON_GETPROJECTEDZF0D_H__
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetProjectedZF0D_Type;
+
+#define BPy_GetProjectedZF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetProjectedZF0D_Type))
+
+/*---------------------------Python BPy_GetProjectedZF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_GetProjectedZF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETPROJECTEDZF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp
new file mode 100644
index 00000000000..e24947038ed
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetXF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetXF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`GetXF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetXF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the X 3D coordinate of the :class:`Interface0D` pointed by\n"
+" the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The X 3D coordinate of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetXF0D___init__(BPy_GetXF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::GetXF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetXF0D type definition ------------------------------*/
+
+PyTypeObject GetXF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetXF0D", /* tp_name */
+ sizeof(BPy_GetXF0D), /* 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 */
+ GetXF0D___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 */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetXF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.h
new file mode 100644
index 00000000000..5fa2bf83dcd
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETXF0D_H__
+#define __FREESTYLE_PYTHON_GETXF0D_H__
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetXF0D_Type;
+
+#define BPy_GetXF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetXF0D_Type))
+
+/*---------------------------Python BPy_GetXF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_GetXF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETXF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp
new file mode 100644
index 00000000000..e831b0ba7c9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetYF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetYF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`GetYF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetYF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the Y 3D coordinate of the :class:`Interface0D` pointed by\n"
+" the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The Y 3D coordinate of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetYF0D___init__(BPy_GetYF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::GetYF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetYF0D type definition ------------------------------*/
+
+PyTypeObject GetYF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetYF0D", /* tp_name */
+ sizeof(BPy_GetYF0D), /* 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 */
+ GetYF0D___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 */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetYF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.h
new file mode 100644
index 00000000000..29289a13d1f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETYF0D_H__
+#define __FREESTYLE_PYTHON_GETYF0D_H__
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetYF0D_Type;
+
+#define BPy_GetYF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetYF0D_Type))
+
+/*---------------------------Python BPy_GetYF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_GetYF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETYF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp
new file mode 100644
index 00000000000..75fddccd251
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetZF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetZF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`GetZF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetZF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the Z 3D coordinate of the :class:`Interface0D` pointed by\n"
+" the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The Z 3D coordinate of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetZF0D___init__(BPy_GetZF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::GetZF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetZF0D type definition ------------------------------*/
+
+PyTypeObject GetZF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetZF0D", /* tp_name */
+ sizeof(BPy_GetZF0D), /* 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 */
+ GetZF0D___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 */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetZF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.h
new file mode 100644
index 00000000000..b385b7c006b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETZF0D_H__
+#define __FREESTYLE_PYTHON_GETZF0D_H__
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetZF0D_Type;
+
+#define BPy_GetZF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetZF0D_Type))
+
+/*---------------------------Python BPy_GetZF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_GetZF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETZF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp
new file mode 100644
index 00000000000..d2849baedb2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_LocalAverageDepthF0D.h"
+
+#include "../../../stroke/AdvancedFunctions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char LocalAverageDepthF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`LocalAverageDepthF0D`\n"
+"\n"
+".. method:: __init__(mask_size=5.0)\n"
+"\n"
+" Builds a LocalAverageDepthF0D object.\n"
+"\n"
+" :arg mask_size: The size of the mask.\n"
+" :type mask_size: float\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the average depth around the :class:`Interface0D` pointed\n"
+" by the Interface0DIterator. The result is obtained by querying the\n"
+" depth buffer on a window around that point.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The average depth around the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int LocalAverageDepthF0D___init__(BPy_LocalAverageDepthF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"mask_size", NULL};
+ double d = 5.0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|d", (char **)kwlist, &d))
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::LocalAverageDepthF0D(d);
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_LocalAverageDepthF0D type definition ------------------------------*/
+
+PyTypeObject LocalAverageDepthF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "LocalAverageDepthF0D", /* tp_name */
+ sizeof(BPy_LocalAverageDepthF0D), /* 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 */
+ LocalAverageDepthF0D___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 */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)LocalAverageDepthF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h
new file mode 100644
index 00000000000..7eebf50a8a2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF0D_H__
+#define __FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF0D_H__
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject LocalAverageDepthF0D_Type;
+
+#define BPy_LocalAverageDepthF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&LocalAverageDepthF0D_Type))
+
+/*---------------------------Python BPy_LocalAverageDepthF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_LocalAverageDepthF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp
new file mode 100644
index 00000000000..07c1fd2dfee
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ZDiscontinuityF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ZDiscontinuityF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`ZDiscontinuityF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a ZDiscontinuityF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns a real value giving the distance between the\n"
+" :class:`Interface0D` pointed by the Interface0DIterator and the\n"
+" shape that lies behind (occludee). This distance is evaluated in\n"
+" the camera space and normalized between 0 and 1. Therefore, if no\n"
+" oject is occluded by the shape to which the Interface0D belongs to,\n"
+" 1 is returned.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The normalized distance between the pointed Interface0D\n"
+" and the occludee.\n"
+" :rtype: float\n";
+
+static int ZDiscontinuityF0D___init__(BPy_ZDiscontinuityF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::ZDiscontinuityF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_ZDiscontinuityF0D type definition ------------------------------*/
+
+PyTypeObject ZDiscontinuityF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ZDiscontinuityF0D", /* tp_name */
+ sizeof(BPy_ZDiscontinuityF0D), /* 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 */
+ ZDiscontinuityF0D___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 */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ZDiscontinuityF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h
new file mode 100644
index 00000000000..c1e648abb36
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_ZDISCONTINUITYF0D_H__
+#define __FREESTYLE_PYTHON_ZDISCONTINUITYF0D_H__
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ZDiscontinuityF0D_Type;
+
+#define BPy_ZDiscontinuityF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ZDiscontinuityF0D_Type))
+
+/*---------------------------Python BPy_ZDiscontinuityF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_ZDiscontinuityF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_ZDISCONTINUITYF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp
new file mode 100644
index 00000000000..8c3e8fb34cd
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp
@@ -0,0 +1,120 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetCurvilinearAbscissaF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetCurvilinearAbscissaF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat` > :class:`GetCurvilinearAbscissaF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetCurvilinearAbscissaF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the curvilinear abscissa of the :class:`Interface0D`\n"
+" pointed by the Interface0DIterator in the context of its 1D\n"
+" element.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The curvilinear abscissa of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetCurvilinearAbscissaF0D___init__(BPy_GetCurvilinearAbscissaF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_float.uf0D_float = new Functions0D::GetCurvilinearAbscissaF0D();
+ self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetCurvilinearAbscissaF0D type definition ------------------------------*/
+
+PyTypeObject GetCurvilinearAbscissaF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetCurvilinearAbscissaF0D", /* tp_name */
+ sizeof(BPy_GetCurvilinearAbscissaF0D), /* 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 */
+ GetCurvilinearAbscissaF0D___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 */
+ &UnaryFunction0DFloat_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetCurvilinearAbscissaF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h
new file mode 100644
index 00000000000..00f9897959b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETCURVILINEARABSCISSAF0D_H__
+#define __FREESTYLE_PYTHON_GETCURVILINEARABSCISSAF0D_H__
+
+#include "../BPy_UnaryFunction0DFloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetCurvilinearAbscissaF0D_Type;
+
+#define BPy_GetCurvilinearAbscissaF0D_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetCurvilinearAbscissaF0D_Type))
+
+/*---------------------------Python BPy_GetCurvilinearAbscissaF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DFloat py_uf0D_float;
+} BPy_GetCurvilinearAbscissaF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETCURVILINEARABSCISSAF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp
new file mode 100644
index 00000000000..6c12eb2730c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetParameterF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetParameterF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat` > :class:`GetParameterF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetParameterF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the parameter of the :class:`Interface0D` pointed by the\n"
+" Interface0DIterator in the context of its 1D element.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The parameter of an Interface0D.\n"
+" :rtype: float\n";
+
+static int GetParameterF0D___init__(BPy_GetParameterF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_float.uf0D_float = new Functions0D::GetParameterF0D();
+ self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetParameterF0D type definition ------------------------------*/
+
+PyTypeObject GetParameterF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetParameterF0D", /* tp_name */
+ sizeof(BPy_GetParameterF0D), /* 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 */
+ GetParameterF0D___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 */
+ &UnaryFunction0DFloat_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetParameterF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.h
new file mode 100644
index 00000000000..6d87e229d39
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETPARAMETERF0D_H__
+#define __FREESTYLE_PYTHON_GETPARAMETERF0D_H__
+
+#include "../BPy_UnaryFunction0DFloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetParameterF0D_Type;
+
+#define BPy_GetParameterF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetParameterF0D_Type))
+
+/*---------------------------Python BPy_GetParameterF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DFloat py_uf0D_float;
+} BPy_GetParameterF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETPARAMETERF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp
new file mode 100644
index 00000000000..ba7db4034f0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp
@@ -0,0 +1,125 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetViewMapGradientNormF0D.h"
+
+#include "../../../stroke/AdvancedFunctions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetViewMapGradientNormF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat` > :class:`GetViewMapGradientNormF0D`\n"
+"\n"
+".. method:: __init__(level)\n"
+"\n"
+" Builds a GetViewMapGradientNormF0D object.\n"
+"\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the norm of the gradient of the global viewmap density\n"
+" image.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The norm of the gradient of the global viewmap density\n"
+" image.\n"
+" :rtype: float\n";
+
+static int GetViewMapGradientNormF0D___init__(BPy_GetViewMapGradientNormF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"level", NULL};
+ int i;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", (char **)kwlist, &i))
+ return -1;
+ self->py_uf0D_float.uf0D_float = new Functions0D::GetViewMapGradientNormF0D(i);
+ self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetViewMapGradientNormF0D type definition ------------------------------*/
+
+PyTypeObject GetViewMapGradientNormF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetViewMapGradientNormF0D", /* tp_name */
+ sizeof(BPy_GetViewMapGradientNormF0D), /* 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 */
+ GetViewMapGradientNormF0D___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 */
+ &UnaryFunction0DFloat_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetViewMapGradientNormF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h
new file mode 100644
index 00000000000..f4c5389008a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF0D_H__
+#define __FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF0D_H__
+
+#include "../BPy_UnaryFunction0DFloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetViewMapGradientNormF0D_Type;
+
+#define BPy_GetViewMapGradientNormF0D_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetViewMapGradientNormF0D_Type))
+
+/*---------------------------Python BPy_GetViewMapGradientNormF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DFloat py_uf0D_float;
+} BPy_GetViewMapGradientNormF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp
new file mode 100644
index 00000000000..f396e27b1e6
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp
@@ -0,0 +1,123 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ReadCompleteViewMapPixelF0D.h"
+
+#include "../../../stroke/AdvancedFunctions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ReadCompleteViewMapPixelF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat` > :class:`ReadCompleteViewMapPixelF0D`\n"
+"\n"
+".. method:: __init__(level)\n"
+"\n"
+" Builds a ReadCompleteViewMapPixelF0D object.\n"
+"\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Reads a pixel in one of the level of the complete viewmap.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: A pixel in one of the level of the complete viewmap.\n"
+" :rtype: float\n";
+
+static int ReadCompleteViewMapPixelF0D___init__(BPy_ReadCompleteViewMapPixelF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"level", NULL};
+ int i;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", (char **)kwlist, &i))
+ return -1;
+ self->py_uf0D_float.uf0D_float = new Functions0D::ReadCompleteViewMapPixelF0D(i);
+ self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_ReadCompleteViewMapPixelF0D type definition ------------------------------*/
+
+PyTypeObject ReadCompleteViewMapPixelF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ReadCompleteViewMapPixelF0D", /* tp_name */
+ sizeof(BPy_ReadCompleteViewMapPixelF0D), /* 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 */
+ ReadCompleteViewMapPixelF0D___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 */
+ &UnaryFunction0DFloat_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ReadCompleteViewMapPixelF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h
new file mode 100644
index 00000000000..8a3610ba2a9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_READCOMPLETEVIEWMAPPIXELF0D_H__
+#define __FREESTYLE_PYTHON_READCOMPLETEVIEWMAPPIXELF0D_H__
+
+#include "../BPy_UnaryFunction0DFloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ReadCompleteViewMapPixelF0D_Type;
+
+#define BPy_ReadCompleteViewMapPixelF0D_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&ReadCompleteViewMapPixelF0D_Type))
+
+/*---------------------------Python BPy_ReadCompleteViewMapPixelF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DFloat py_uf0D_float;
+} BPy_ReadCompleteViewMapPixelF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_READCOMPLETEVIEWMAPPIXELF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp
new file mode 100644
index 00000000000..c9961a359ae
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp
@@ -0,0 +1,126 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ReadMapPixelF0D.h"
+
+#include "../../../stroke/AdvancedFunctions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ReadMapPixelF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat` > :class:`ReadMapPixelF0D`\n"
+"\n"
+".. method:: __init__(map_name, level)\n"
+"\n"
+" Builds a ReadMapPixelF0D object.\n"
+"\n"
+" :arg map_name: The name of the map to be read.\n"
+" :type map_name: str\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Reads a pixel in a map.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: A pixel in a map.\n"
+" :rtype: float\n";
+
+static int ReadMapPixelF0D___init__(BPy_ReadMapPixelF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"map_name", "level", NULL};
+ const char *s;
+ int i;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "si", (char **)kwlist, &s, &i))
+ return -1;
+ self->py_uf0D_float.uf0D_float = new Functions0D::ReadMapPixelF0D(s, i);
+ self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_ReadMapPixelF0D type definition ------------------------------*/
+
+PyTypeObject ReadMapPixelF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ReadMapPixelF0D", /* tp_name */
+ sizeof(BPy_ReadMapPixelF0D), /* 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 */
+ ReadMapPixelF0D___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 */
+ &UnaryFunction0DFloat_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ReadMapPixelF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.h
new file mode 100644
index 00000000000..1c80b9c9bb6
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_READMAPPIXELF0D_H__
+#define __FREESTYLE_PYTHON_READMAPPIXELF0D_H__
+
+#include "../BPy_UnaryFunction0DFloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ReadMapPixelF0D_Type;
+
+#define BPy_ReadMapPixelF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ReadMapPixelF0D_Type))
+
+/*---------------------------Python BPy_ReadMapPixelF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DFloat py_uf0D_float;
+} BPy_ReadMapPixelF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_READMAPPIXELF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp
new file mode 100644
index 00000000000..de3a76476df
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp
@@ -0,0 +1,127 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ReadSteerableViewMapPixelF0D.h"
+
+#include "../../../stroke/AdvancedFunctions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ReadSteerableViewMapPixelF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat` > :class:`ReadSteerableViewMapPixelF0D`\n"
+"\n"
+".. method:: __init__(orientation, level)\n"
+"\n"
+" Builds a ReadSteerableViewMapPixelF0D object.\n"
+"\n"
+" :arg orientation: The integer belonging to [0, 4] indicating the\n"
+" orientation (E, NE, N, NW) we are interested in.\n"
+" :type orientation: int\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Reads a pixel in one of the level of one of the steerable viewmaps.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: A pixel in one of the level of one of the steerable viewmaps.\n"
+" :rtype: float\n";
+
+static int ReadSteerableViewMapPixelF0D___init__(BPy_ReadSteerableViewMapPixelF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"orientation", "level", NULL};
+ unsigned int u;
+ int i;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "Ii", (char **)kwlist, &u, &i))
+ return -1;
+ self->py_uf0D_float.uf0D_float = new Functions0D::ReadSteerableViewMapPixelF0D(u, i);
+ self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_ReadSteerableViewMapPixelF0D type definition ------------------------------*/
+
+PyTypeObject ReadSteerableViewMapPixelF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ReadSteerableViewMapPixelF0D", /* tp_name */
+ sizeof(BPy_ReadSteerableViewMapPixelF0D), /* 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 */
+ ReadSteerableViewMapPixelF0D___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 */
+ &UnaryFunction0DFloat_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ReadSteerableViewMapPixelF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h
new file mode 100644
index 00000000000..8cb7c3ad609
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_READSTEERABLEVIEWMAPPIXELF0D_H__
+#define __FREESTYLE_PYTHON_READSTEERABLEVIEWMAPPIXELF0D_H__
+
+#include "../BPy_UnaryFunction0DFloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ReadSteerableViewMapPixelF0D_Type;
+
+#define BPy_ReadSteerableViewMapPixelF0D_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&ReadSteerableViewMapPixelF0D_Type))
+
+/*---------------------------Python BPy_ReadSteerableViewMapPixelF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DFloat py_uf0D_float;
+} BPy_ReadSteerableViewMapPixelF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_READSTEERABLEVIEWMAPPIXELF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp
new file mode 100644
index 00000000000..11737124245
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp
@@ -0,0 +1,125 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_QuantitativeInvisibilityF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char QuantitativeInvisibilityF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DUnsigned` > :class:`QuantitativeInvisibilityF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a QuantitativeInvisibilityF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the quantitative invisibility of the :class:`Interface0D`\n"
+" pointed by the Interface0DIterator. This evaluation can be\n"
+" ambiguous (in the case of a :class:`TVertex` for example). This\n"
+" functor tries to remove this ambiguity using the context offered by\n"
+" the 1D element to which the Interface0D belongs to. However, there\n"
+" still can be problematic cases, and the user willing to deal with\n"
+" this cases in a specific way should implement its own getQIF0D\n"
+" functor.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The quantitative invisibility of the pointed Interface0D.\n"
+" :rtype: int\n";
+
+static int QuantitativeInvisibilityF0D___init__(BPy_QuantitativeInvisibilityF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_unsigned.uf0D_unsigned = new Functions0D::QuantitativeInvisibilityF0D();
+ self->py_uf0D_unsigned.uf0D_unsigned->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_QuantitativeInvisibilityF0D type definition ------------------------------*/
+
+PyTypeObject QuantitativeInvisibilityF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "QuantitativeInvisibilityF0D", /* tp_name */
+ sizeof(BPy_QuantitativeInvisibilityF0D), /* 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 */
+ QuantitativeInvisibilityF0D___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 */
+ &UnaryFunction0DUnsigned_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)QuantitativeInvisibilityF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h
new file mode 100644
index 00000000000..a7838331995
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF0D_H__
+#define __FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF0D_H__
+
+#include "../BPy_UnaryFunction0DUnsigned.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject QuantitativeInvisibilityF0D_Type;
+
+#define BPy_QuantitativeInvisibilityF0D_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&QuantitativeInvisibilityF0D_Type))
+
+/*---------------------------Python BPy_QuantitativeInvisibilityF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DUnsigned py_uf0D_unsigned;
+} BPy_QuantitativeInvisibilityF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp
new file mode 100644
index 00000000000..bead5fd7b83
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp
@@ -0,0 +1,120 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetOccludersF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetOccludersF0D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DVectorViewShape` > :class:`GetOccludersF0D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetOccludersF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns a list of :class:`ViewShape` objects occluding the\n"
+" :class:`Interface0D` pointed by the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: A list of ViewShape objects occluding the pointed\n"
+" Interface0D.\n"
+" :rtype: list of :class:`ViewShape` objects\n";
+
+static int GetOccludersF0D___init__(BPy_GetOccludersF0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf0D_vectorviewshape.uf0D_vectorviewshape = new Functions0D::GetOccludersF0D();
+ self->py_uf0D_vectorviewshape.uf0D_vectorviewshape->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetOccludersF0D type definition ------------------------------*/
+
+PyTypeObject GetOccludersF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetOccludersF0D", /* tp_name */
+ sizeof(BPy_GetOccludersF0D), /* 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 */
+ GetOccludersF0D___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 */
+ &UnaryFunction0DVectorViewShape_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetOccludersF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h
new file mode 100644
index 00000000000..64d2bdd64c5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETOCCLUDERSF0D_H__
+#define __FREESTYLE_PYTHON_GETOCCLUDERSF0D_H__
+
+#include "../BPy_UnaryFunction0DVectorViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetOccludersF0D_Type;
+
+#define BPy_GetOccludersF0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetOccludersF0D_Type))
+
+/*---------------------------Python BPy_GetOccludersF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DVectorViewShape py_uf0D_vectorviewshape;
+} BPy_GetOccludersF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETOCCLUDERSF0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp
new file mode 100644
index 00000000000..47f7ff6388f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp
@@ -0,0 +1,292 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction1DDouble.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h"
+#include "UnaryFunction1D_double/BPy_DensityF1D.h"
+#include "UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h"
+#include "UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h"
+#include "UnaryFunction1D_double/BPy_GetProjectedXF1D.h"
+#include "UnaryFunction1D_double/BPy_GetProjectedYF1D.h"
+#include "UnaryFunction1D_double/BPy_GetProjectedZF1D.h"
+#include "UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h"
+#include "UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h"
+#include "UnaryFunction1D_double/BPy_GetXF1D.h"
+#include "UnaryFunction1D_double/BPy_GetYF1D.h"
+#include "UnaryFunction1D_double/BPy_GetZF1D.h"
+#include "UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h"
+#include "UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DDouble_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction1DDouble_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction1DDouble_Type);
+ PyModule_AddObject(module, "UnaryFunction1DDouble", (PyObject *)&UnaryFunction1DDouble_Type);
+
+ if (PyType_Ready(&DensityF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&DensityF1D_Type);
+ PyModule_AddObject(module, "DensityF1D", (PyObject *)&DensityF1D_Type);
+
+ if (PyType_Ready(&Curvature2DAngleF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&Curvature2DAngleF1D_Type);
+ PyModule_AddObject(module, "Curvature2DAngleF1D", (PyObject *)&Curvature2DAngleF1D_Type);
+
+ if (PyType_Ready(&GetCompleteViewMapDensityF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetCompleteViewMapDensityF1D_Type);
+ PyModule_AddObject(module, "GetCompleteViewMapDensityF1D", (PyObject *)&GetCompleteViewMapDensityF1D_Type);
+
+ if (PyType_Ready(&GetDirectionalViewMapDensityF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetDirectionalViewMapDensityF1D_Type);
+ PyModule_AddObject(module, "GetDirectionalViewMapDensityF1D", (PyObject *)&GetDirectionalViewMapDensityF1D_Type);
+
+ if (PyType_Ready(&GetProjectedXF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetProjectedXF1D_Type);
+ PyModule_AddObject(module, "GetProjectedXF1D", (PyObject *)&GetProjectedXF1D_Type);
+
+ if (PyType_Ready(&GetProjectedYF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetProjectedYF1D_Type);
+ PyModule_AddObject(module, "GetProjectedYF1D", (PyObject *)&GetProjectedYF1D_Type);
+
+ if (PyType_Ready(&GetProjectedZF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetProjectedZF1D_Type);
+ PyModule_AddObject(module, "GetProjectedZF1D", (PyObject *)&GetProjectedZF1D_Type);
+
+ if (PyType_Ready(&GetSteerableViewMapDensityF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetSteerableViewMapDensityF1D_Type);
+ PyModule_AddObject(module, "GetSteerableViewMapDensityF1D", (PyObject *)&GetSteerableViewMapDensityF1D_Type);
+
+ if (PyType_Ready(&GetViewMapGradientNormF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetViewMapGradientNormF1D_Type);
+ PyModule_AddObject(module, "GetViewMapGradientNormF1D", (PyObject *)&GetViewMapGradientNormF1D_Type);
+
+ if (PyType_Ready(&GetXF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetXF1D_Type);
+ PyModule_AddObject(module, "GetXF1D", (PyObject *)&GetXF1D_Type);
+
+ if (PyType_Ready(&GetYF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetYF1D_Type);
+ PyModule_AddObject(module, "GetYF1D", (PyObject *)&GetYF1D_Type);
+
+ if (PyType_Ready(&GetZF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetZF1D_Type);
+ PyModule_AddObject(module, "GetZF1D", (PyObject *)&GetZF1D_Type);
+
+ if (PyType_Ready(&LocalAverageDepthF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&LocalAverageDepthF1D_Type);
+ PyModule_AddObject(module, "LocalAverageDepthF1D", (PyObject *)&LocalAverageDepthF1D_Type);
+
+ if (PyType_Ready(&ZDiscontinuityF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&ZDiscontinuityF1D_Type);
+ PyModule_AddObject(module, "ZDiscontinuityF1D", (PyObject *)&ZDiscontinuityF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DDouble___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return a float value.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration_type)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration_type: An integration method.\n"
+" :type integration_type: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DDouble___init__(BPy_UnaryFunction1DDouble *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+
+ if (!obj)
+ self->uf1D_double = new UnaryFunction1D<double>();
+ else {
+ self->uf1D_double = new UnaryFunction1D<double>(IntegrationType_from_BPy_IntegrationType(obj));
+ }
+
+ self->uf1D_double->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DDouble___dealloc__(BPy_UnaryFunction1DDouble *self)
+{
+ if (self->uf1D_double)
+ delete self->uf1D_double;
+ UnaryFunction1D_Type.tp_dealloc((PyObject *)self);
+}
+
+static PyObject *UnaryFunction1DDouble___repr__(BPy_UnaryFunction1DDouble *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->uf1D_double);
+}
+
+static PyObject *UnaryFunction1DDouble___call__(BPy_UnaryFunction1DDouble *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"inter", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface1D_Type, &obj))
+ return NULL;
+
+ if (typeid(*(self->uf1D_double)) == typeid(UnaryFunction1D<double>)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_double->operator()(*(((BPy_Interface1D *) obj)->if1D)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return PyFloat_FromDouble(self->uf1D_double->result);
+}
+
+/*----------------------UnaryFunction1DDouble get/setters ----------------------------*/
+
+PyDoc_STRVAR(integration_type_doc,
+"The integration method.\n"
+"\n"
+":type: :class:`IntegrationType`");
+
+static PyObject *integration_type_get(BPy_UnaryFunction1DDouble *self, void *UNUSED(closure))
+{
+ return BPy_IntegrationType_from_IntegrationType(self->uf1D_double->getIntegrationType());
+}
+
+static int integration_type_set(BPy_UnaryFunction1DDouble *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_IntegrationType_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an IntegrationType");
+ return -1;
+ }
+ self->uf1D_double->setIntegrationType(IntegrationType_from_BPy_IntegrationType(value));
+ return 0;
+}
+
+static PyGetSetDef BPy_UnaryFunction1DDouble_getseters[] = {
+ {(char *)"integration_type", (getter)integration_type_get, (setter)integration_type_set,
+ (char *)integration_type_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_UnaryFunction1DDouble type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DDouble_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DDouble", /* tp_name */
+ sizeof(BPy_UnaryFunction1DDouble), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DDouble___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DDouble___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DDouble___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DDouble___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 */
+ BPy_UnaryFunction1DDouble_getseters, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DDouble___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h
new file mode 100644
index 00000000000..aef3885a3eb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h
@@ -0,0 +1,65 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION1DDOUBLE_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION1DDOUBLE_H__
+
+#include "../BPy_UnaryFunction1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DDouble_Type;
+
+#define BPy_UnaryFunction1DDouble_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction1DDouble_Type))
+
+/*---------------------------Python BPy_UnaryFunction1DDouble structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D<double> *uf1D_double;
+} BPy_UnaryFunction1DDouble;
+
+/*---------------------------Python BPy_UnaryFunction1DDouble visible prototypes-----------*/
+int UnaryFunction1DDouble_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION1DDOUBLE_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp
new file mode 100644
index 00000000000..bda06a1d148
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp
@@ -0,0 +1,215 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction1DEdgeNature.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DEdgeNature_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction1DEdgeNature_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction1DEdgeNature_Type);
+ PyModule_AddObject(module, "UnaryFunction1DEdgeNature", (PyObject *)&UnaryFunction1DEdgeNature_Type);
+
+ if (PyType_Ready(&CurveNatureF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&CurveNatureF1D_Type);
+ PyModule_AddObject(module, "CurveNatureF1D", (PyObject *)&CurveNatureF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DEdgeNature___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DEdgeNature`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return a :class:`Nature` object.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration_type)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration_type: An integration method.\n"
+" :type integration_type: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DEdgeNature___init__(BPy_UnaryFunction1DEdgeNature *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+
+ if (!obj)
+ self->uf1D_edgenature = new UnaryFunction1D<Nature::EdgeNature>();
+ else {
+ self->uf1D_edgenature = new UnaryFunction1D<Nature::EdgeNature>(IntegrationType_from_BPy_IntegrationType(obj));
+ }
+
+ self->uf1D_edgenature->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DEdgeNature___dealloc__(BPy_UnaryFunction1DEdgeNature *self)
+{
+ if (self->uf1D_edgenature)
+ delete self->uf1D_edgenature;
+ UnaryFunction1D_Type.tp_dealloc((PyObject *)self);
+}
+
+static PyObject *UnaryFunction1DEdgeNature___repr__(BPy_UnaryFunction1DEdgeNature *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->uf1D_edgenature);
+}
+
+static PyObject *UnaryFunction1DEdgeNature___call__(BPy_UnaryFunction1DEdgeNature *self,
+ PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"inter", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface1D_Type, &obj))
+ return NULL;
+
+ if (typeid(*(self->uf1D_edgenature)) == typeid(UnaryFunction1D<Nature::EdgeNature>)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_edgenature->operator()(*(((BPy_Interface1D *) obj)->if1D)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return BPy_Nature_from_Nature(self->uf1D_edgenature->result);
+}
+
+/*----------------------UnaryFunction1DEdgeNature get/setters ----------------------------*/
+
+PyDoc_STRVAR(integration_type_doc,
+"The integration method.\n"
+"\n"
+":type: :class:`IntegrationType`");
+
+static PyObject *integration_type_get(BPy_UnaryFunction1DEdgeNature *self, void *UNUSED(closure))
+{
+ return BPy_IntegrationType_from_IntegrationType(self->uf1D_edgenature->getIntegrationType());
+}
+
+static int integration_type_set(BPy_UnaryFunction1DEdgeNature *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_IntegrationType_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an IntegrationType");
+ return -1;
+ }
+ self->uf1D_edgenature->setIntegrationType(IntegrationType_from_BPy_IntegrationType(value));
+ return 0;
+}
+
+static PyGetSetDef BPy_UnaryFunction1DEdgeNature_getseters[] = {
+ {(char *)"integration_type", (getter)integration_type_get, (setter)integration_type_set,
+ (char *)integration_type_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_UnaryFunction1DEdgeNature type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DEdgeNature_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DEdgeNature", /* tp_name */
+ sizeof(BPy_UnaryFunction1DEdgeNature), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DEdgeNature___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DEdgeNature___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DEdgeNature___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DEdgeNature___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 */
+ BPy_UnaryFunction1DEdgeNature_getseters, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DEdgeNature___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h
new file mode 100644
index 00000000000..7be7de7c0fe
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION1DEDGENATURE_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION1DEDGENATURE_H__
+
+#include "../BPy_UnaryFunction1D.h"
+
+#include "../../winged_edge/Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DEdgeNature_Type;
+
+#define BPy_UnaryFunction1DEdgeNature_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction1DEdgeNature_Type))
+
+/*---------------------------Python BPy_UnaryFunction1DEdgeNature structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D<Nature::EdgeNature> *uf1D_edgenature;
+} BPy_UnaryFunction1DEdgeNature;
+
+/*---------------------------Python BPy_UnaryFunction1DEdgeNature visible prototypes-----------*/
+int UnaryFunction1DEdgeNature_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION1DEDGENATURE_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp
new file mode 100644
index 00000000000..bccdcd18f90
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp
@@ -0,0 +1,207 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction1DFloat.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DFloat_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction1DFloat_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction1DFloat_Type);
+ PyModule_AddObject(module, "UnaryFunction1DFloat", (PyObject *)&UnaryFunction1DFloat_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DFloat___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DFloat`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return a float value.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration_type)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration_type: An integration method.\n"
+" :type integration_type: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DFloat___init__(BPy_UnaryFunction1DFloat *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+
+ if (!obj)
+ self->uf1D_float = new UnaryFunction1D<float>();
+ else {
+ self->uf1D_float = new UnaryFunction1D<float>(IntegrationType_from_BPy_IntegrationType(obj));
+ }
+
+ self->uf1D_float->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DFloat___dealloc__(BPy_UnaryFunction1DFloat *self)
+{
+ if (self->uf1D_float)
+ delete self->uf1D_float;
+ UnaryFunction1D_Type.tp_dealloc((PyObject *)self);
+}
+
+static PyObject *UnaryFunction1DFloat___repr__(BPy_UnaryFunction1DFloat *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->uf1D_float);
+}
+
+static PyObject *UnaryFunction1DFloat___call__(BPy_UnaryFunction1DFloat *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"inter", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface1D_Type, &obj))
+ return NULL;
+
+ if (typeid(*(self->uf1D_float)) == typeid(UnaryFunction1D<float>)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_float->operator()(*(((BPy_Interface1D *) obj)->if1D)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return PyFloat_FromDouble(self->uf1D_float->result);
+}
+
+/*----------------------UnaryFunction1DFloat get/setters ----------------------------*/
+
+PyDoc_STRVAR(integration_type_doc,
+"The integration method.\n"
+"\n"
+":type: :class:`IntegrationType`");
+
+static PyObject *integration_type_get(BPy_UnaryFunction1DFloat *self, void *UNUSED(closure))
+{
+ return BPy_IntegrationType_from_IntegrationType(self->uf1D_float->getIntegrationType());
+}
+
+static int integration_type_set(BPy_UnaryFunction1DFloat *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_IntegrationType_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an IntegrationType");
+ return -1;
+ }
+ self->uf1D_float->setIntegrationType(IntegrationType_from_BPy_IntegrationType(value));
+ return 0;
+}
+
+static PyGetSetDef BPy_UnaryFunction1DFloat_getseters[] = {
+ {(char *)"integration_type", (getter)integration_type_get, (setter)integration_type_set,
+ (char *)integration_type_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_UnaryFunction1DFloat type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DFloat_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DFloat", /* tp_name */
+ sizeof(BPy_UnaryFunction1DFloat), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DFloat___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DFloat___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DFloat___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DFloat___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 */
+ BPy_UnaryFunction1DFloat_getseters, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DFloat___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h
new file mode 100644
index 00000000000..694435b98b5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h
@@ -0,0 +1,65 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION1DFLOAT_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION1DFLOAT_H__
+
+#include "../BPy_UnaryFunction1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DFloat_Type;
+
+#define BPy_UnaryFunction1DFloat_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction1DFloat_Type))
+
+/*---------------------------Python BPy_UnaryFunction1DFloat structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D<float> *uf1D_float;
+} BPy_UnaryFunction1DFloat;
+
+/*---------------------------Python BPy_UnaryFunction1DFloat visible prototypes-----------*/
+int UnaryFunction1DFloat_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION1DFLOAT_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp
new file mode 100644
index 00000000000..2fbc8658a06
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp
@@ -0,0 +1,214 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction1DUnsigned.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DUnsigned_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction1DUnsigned_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction1DUnsigned_Type);
+ PyModule_AddObject(module, "UnaryFunction1DUnsigned", (PyObject *)&UnaryFunction1DUnsigned_Type);
+
+ if (PyType_Ready(&QuantitativeInvisibilityF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&QuantitativeInvisibilityF1D_Type);
+ PyModule_AddObject(module, "QuantitativeInvisibilityF1D", (PyObject *)&QuantitativeInvisibilityF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DUnsigned___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DUnsigned`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return an int value.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration_type)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration_type: An integration method.\n"
+" :type integration_type: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DUnsigned___init__(BPy_UnaryFunction1DUnsigned *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+
+ if (!obj)
+ self->uf1D_unsigned = new UnaryFunction1D<unsigned int>();
+ else {
+ self->uf1D_unsigned = new UnaryFunction1D<unsigned int>(IntegrationType_from_BPy_IntegrationType(obj));
+ }
+
+ self->uf1D_unsigned->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DUnsigned___dealloc__(BPy_UnaryFunction1DUnsigned *self)
+{
+ if (self->uf1D_unsigned)
+ delete self->uf1D_unsigned;
+ UnaryFunction1D_Type.tp_dealloc((PyObject *)self);
+}
+
+static PyObject *UnaryFunction1DUnsigned___repr__(BPy_UnaryFunction1DUnsigned *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->uf1D_unsigned);
+}
+
+static PyObject *UnaryFunction1DUnsigned___call__(BPy_UnaryFunction1DUnsigned *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"inter", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface1D_Type, &obj))
+ return NULL;
+
+ if (typeid(*(self->uf1D_unsigned)) == typeid(UnaryFunction1D<unsigned int>)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_unsigned->operator()(*(((BPy_Interface1D *) obj)->if1D)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return PyLong_FromLong(self->uf1D_unsigned->result);
+}
+
+/*----------------------UnaryFunction1DUnsigned get/setters ----------------------------*/
+
+PyDoc_STRVAR(integration_type_doc,
+"The integration method.\n"
+"\n"
+":type: :class:`IntegrationType`");
+
+static PyObject *integration_type_get(BPy_UnaryFunction1DUnsigned *self, void *UNUSED(closure))
+{
+ return BPy_IntegrationType_from_IntegrationType(self->uf1D_unsigned->getIntegrationType());
+}
+
+static int integration_type_set(BPy_UnaryFunction1DUnsigned *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_IntegrationType_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an IntegrationType");
+ return -1;
+ }
+ self->uf1D_unsigned->setIntegrationType(IntegrationType_from_BPy_IntegrationType(value));
+ return 0;
+}
+
+static PyGetSetDef BPy_UnaryFunction1DUnsigned_getseters[] = {
+ {(char *)"integration_type", (getter)integration_type_get, (setter)integration_type_set,
+ (char *)integration_type_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_UnaryFunction1DUnsigned type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DUnsigned_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DUnsigned", /* tp_name */
+ sizeof(BPy_UnaryFunction1DUnsigned), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DUnsigned___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DUnsigned___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DUnsigned___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DUnsigned___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 */
+ BPy_UnaryFunction1DUnsigned_getseters, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DUnsigned___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h
new file mode 100644
index 00000000000..fc02d1335f2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION1DUNSIGNED_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION1DUNSIGNED_H__
+
+#include "../BPy_UnaryFunction1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DUnsigned_Type;
+
+#define BPy_UnaryFunction1DUnsigned_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction1DUnsigned_Type))
+
+/*---------------------------Python BPy_UnaryFunction1DUnsigned structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D<unsigned int> *uf1D_unsigned;
+} BPy_UnaryFunction1DUnsigned;
+
+/*---------------------------Python BPy_UnaryFunction1DUnsigned visible prototypes-----------*/
+int UnaryFunction1DUnsigned_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION1DUNSIGNED_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp
new file mode 100644
index 00000000000..41fb70dcfd5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp
@@ -0,0 +1,220 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction1DVec2f.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h"
+#include "UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DVec2f_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction1DVec2f_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction1DVec2f_Type);
+ PyModule_AddObject(module, "UnaryFunction1DVec2f", (PyObject *)&UnaryFunction1DVec2f_Type);
+
+ if (PyType_Ready(&Normal2DF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&Normal2DF1D_Type);
+ PyModule_AddObject(module, "Normal2DF1D", (PyObject *)&Normal2DF1D_Type);
+
+ if (PyType_Ready(&Orientation2DF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&Orientation2DF1D_Type);
+ PyModule_AddObject(module, "Orientation2DF1D", (PyObject *)&Orientation2DF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DVec2f___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVec2f`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return a 2D vector.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration_type)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration_type: An integration method.\n"
+" :type integration_type: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DVec2f___init__(BPy_UnaryFunction1DVec2f *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+
+ if (!obj)
+ self->uf1D_vec2f = new UnaryFunction1D<Vec2f>();
+ else {
+ self->uf1D_vec2f = new UnaryFunction1D<Vec2f>(IntegrationType_from_BPy_IntegrationType(obj));
+ }
+
+ self->uf1D_vec2f->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DVec2f___dealloc__(BPy_UnaryFunction1DVec2f *self)
+{
+ if (self->uf1D_vec2f)
+ delete self->uf1D_vec2f;
+ UnaryFunction1D_Type.tp_dealloc((PyObject *)self);
+}
+
+static PyObject *UnaryFunction1DVec2f___repr__(BPy_UnaryFunction1DVec2f *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->uf1D_vec2f);
+}
+
+static PyObject *UnaryFunction1DVec2f___call__(BPy_UnaryFunction1DVec2f *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"inter", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface1D_Type, &obj))
+ return NULL;
+
+ if (typeid(*(self->uf1D_vec2f)) == typeid(UnaryFunction1D<Vec2f>)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_vec2f->operator()(*(((BPy_Interface1D *) obj)->if1D)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return Vector_from_Vec2f(self->uf1D_vec2f->result);
+}
+
+/*----------------------UnaryFunction1DVec2f get/setters ----------------------------*/
+
+PyDoc_STRVAR(integration_type_doc,
+"The integration method.\n"
+"\n"
+":type: :class:`IntegrationType`");
+
+static PyObject *integration_type_get(BPy_UnaryFunction1DVec2f *self, void *UNUSED(closure))
+{
+ return BPy_IntegrationType_from_IntegrationType(self->uf1D_vec2f->getIntegrationType());
+}
+
+static int integration_type_set(BPy_UnaryFunction1DVec2f *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_IntegrationType_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an IntegrationType");
+ return -1;
+ }
+ self->uf1D_vec2f->setIntegrationType(IntegrationType_from_BPy_IntegrationType(value));
+ return 0;
+}
+
+static PyGetSetDef BPy_UnaryFunction1DVec2f_getseters[] = {
+ {(char *)"integration_type", (getter)integration_type_get, (setter)integration_type_set,
+ (char *)integration_type_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_UnaryFunction1DVec2f type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DVec2f_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DVec2f", /* tp_name */
+ sizeof(BPy_UnaryFunction1DVec2f), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DVec2f___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DVec2f___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DVec2f___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DVec2f___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 */
+ BPy_UnaryFunction1DVec2f_getseters, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DVec2f___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h
new file mode 100644
index 00000000000..61c85d7c9f5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION1DVEC2F_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION1DVEC2F_H__
+
+#include "../BPy_UnaryFunction1D.h"
+
+#include "../../geometry/Geom.h"
+using namespace Geometry;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DVec2f_Type;
+
+#define BPy_UnaryFunction1DVec2f_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction1DVec2f_Type))
+
+/*---------------------------Python BPy_UnaryFunction1DVec2f structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D<Vec2f> *uf1D_vec2f;
+} BPy_UnaryFunction1DVec2f;
+
+/*---------------------------Python BPy_UnaryFunction1DVec2f visible prototypes-----------*/
+int UnaryFunction1DVec2f_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION1DVEC2F_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp
new file mode 100644
index 00000000000..7198949c2a8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp
@@ -0,0 +1,214 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction1DVec3f.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DVec3f_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction1DVec3f_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction1DVec3f_Type);
+ PyModule_AddObject(module, "UnaryFunction1DVec3f", (PyObject *)&UnaryFunction1DVec3f_Type);
+
+ if (PyType_Ready(&Orientation3DF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&Orientation3DF1D_Type);
+ PyModule_AddObject(module, "Orientation3DF1D", (PyObject *)&Orientation3DF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DVec3f___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVec3f`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return a 3D vector.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration_type)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration_type: An integration method.\n"
+" :type integration_type: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DVec3f___init__(BPy_UnaryFunction1DVec3f *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+
+ if (!obj)
+ self->uf1D_vec3f = new UnaryFunction1D<Vec3f>();
+ else {
+ self->uf1D_vec3f = new UnaryFunction1D<Vec3f>(IntegrationType_from_BPy_IntegrationType(obj));
+ }
+
+ self->uf1D_vec3f->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DVec3f___dealloc__(BPy_UnaryFunction1DVec3f *self)
+{
+ if (self->uf1D_vec3f)
+ delete self->uf1D_vec3f;
+ UnaryFunction1D_Type.tp_dealloc((PyObject *)self);
+}
+
+static PyObject *UnaryFunction1DVec3f___repr__(BPy_UnaryFunction1DVec3f *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->uf1D_vec3f);
+}
+
+static PyObject *UnaryFunction1DVec3f___call__(BPy_UnaryFunction1DVec3f *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"inter", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface1D_Type, &obj))
+ return NULL;
+
+ if (typeid(*(self->uf1D_vec3f)) == typeid(UnaryFunction1D<Vec3f>)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_vec3f->operator()(*(((BPy_Interface1D *) obj)->if1D)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ return Vector_from_Vec3f(self->uf1D_vec3f->result);
+}
+
+/*----------------------UnaryFunction1DVec3f get/setters ----------------------------*/
+
+PyDoc_STRVAR(integration_type_doc,
+"The integration method.\n"
+"\n"
+":type: :class:`IntegrationType`");
+
+static PyObject *integration_type_get(BPy_UnaryFunction1DVec3f *self, void *UNUSED(closure))
+{
+ return BPy_IntegrationType_from_IntegrationType(self->uf1D_vec3f->getIntegrationType());
+}
+
+static int integration_type_set(BPy_UnaryFunction1DVec3f *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_IntegrationType_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an IntegrationType");
+ return -1;
+ }
+ self->uf1D_vec3f->setIntegrationType(IntegrationType_from_BPy_IntegrationType(value));
+ return 0;
+}
+
+static PyGetSetDef BPy_UnaryFunction1DVec3f_getseters[] = {
+ {(char *)"integration_type", (getter)integration_type_get, (setter)integration_type_set,
+ (char *)integration_type_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_UnaryFunction1DVec3f type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DVec3f_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DVec3f", /* tp_name */
+ sizeof(BPy_UnaryFunction1DVec3f), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DVec3f___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DVec3f___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DVec3f___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DVec3f___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 */
+ BPy_UnaryFunction1DVec3f_getseters, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DVec3f___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h
new file mode 100644
index 00000000000..67ce5faef7f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION1DVEC3F_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION1DVEC3F_H__
+
+#include "../BPy_UnaryFunction1D.h"
+
+#include "../../geometry/Geom.h"
+using namespace Geometry;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DVec3f_Type;
+
+#define BPy_UnaryFunction1DVec3f_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction1DVec3f_Type))
+
+/*---------------------------Python BPy_UnaryFunction1DVec3f structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D<Vec3f> *uf1D_vec3f;
+} BPy_UnaryFunction1DVec3f;
+
+/*---------------------------Python BPy_UnaryFunction1DVec3f visible prototypes-----------*/
+int UnaryFunction1DVec3f_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION1DVEC3F_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
new file mode 100644
index 00000000000..22adf4ab5cb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
@@ -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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction1DVectorViewShape.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h"
+#include "UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h"
+#include "UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DVectorViewShape_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction1DVectorViewShape_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction1DVectorViewShape_Type);
+ PyModule_AddObject(module, "UnaryFunction1DVectorViewShape", (PyObject *)&UnaryFunction1DVectorViewShape_Type);
+
+ if (PyType_Ready(&GetOccludeeF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetOccludeeF1D_Type);
+ PyModule_AddObject(module, "GetOccludeeF1D", (PyObject *)&GetOccludeeF1D_Type);
+
+ if (PyType_Ready(&GetOccludersF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetOccludersF1D_Type);
+ PyModule_AddObject(module, "GetOccludersF1D", (PyObject *)&GetOccludersF1D_Type);
+
+ if (PyType_Ready(&GetShapeF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&GetShapeF1D_Type);
+ PyModule_AddObject(module, "GetShapeF1D", (PyObject *)&GetShapeF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DVectorViewShape___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVectorViewShape`\n"
+"\n"
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return a list of :class:`ViewShape`\n"
+"objects.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration_type)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration_type: An integration method.\n"
+" :type integration_type: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DVectorViewShape___init__(BPy_UnaryFunction1DVectorViewShape *self,
+ PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+
+ if (!obj) {
+ self->uf1D_vectorviewshape = new UnaryFunction1D< std::vector<ViewShape*> >();
+ }
+ else {
+ self->uf1D_vectorviewshape = new UnaryFunction1D< std::vector<ViewShape*> >(IntegrationType_from_BPy_IntegrationType(obj));
+ }
+
+ self->uf1D_vectorviewshape->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DVectorViewShape___dealloc__(BPy_UnaryFunction1DVectorViewShape *self)
+{
+ if (self->uf1D_vectorviewshape)
+ delete self->uf1D_vectorviewshape;
+ UnaryFunction1D_Type.tp_dealloc((PyObject *)self);
+}
+
+static PyObject *UnaryFunction1DVectorViewShape___repr__(BPy_UnaryFunction1DVectorViewShape *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->uf1D_vectorviewshape);
+}
+
+static PyObject *UnaryFunction1DVectorViewShape___call__(BPy_UnaryFunction1DVectorViewShape *self,
+ PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"inter", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface1D_Type, &obj))
+ return NULL;
+
+ if (typeid(*(self->uf1D_vectorviewshape)) == typeid(UnaryFunction1D< std::vector<ViewShape*> >)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_vectorviewshape->operator()(*(((BPy_Interface1D *) obj)->if1D)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ PyObject *list = PyList_New(0);
+ PyObject *item;
+ for (unsigned int i = 0; i < self->uf1D_vectorviewshape->result.size(); 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);
+ }
+
+ return list;
+}
+
+/*----------------------UnaryFunction1DVectorViewShape get/setters ----------------------------*/
+
+PyDoc_STRVAR(integration_type_doc,
+"The integration method.\n"
+"\n"
+":type: :class:`IntegrationType`");
+
+static PyObject *integration_type_get(BPy_UnaryFunction1DVectorViewShape *self, void *UNUSED(closure))
+{
+ return BPy_IntegrationType_from_IntegrationType(self->uf1D_vectorviewshape->getIntegrationType());
+}
+
+static int integration_type_set(BPy_UnaryFunction1DVectorViewShape *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_IntegrationType_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an IntegrationType");
+ return -1;
+ }
+ self->uf1D_vectorviewshape->setIntegrationType(IntegrationType_from_BPy_IntegrationType(value));
+ return 0;
+}
+
+static PyGetSetDef BPy_UnaryFunction1DVectorViewShape_getseters[] = {
+ {(char *)"integration_type", (getter)integration_type_get, (setter)integration_type_set,
+ (char *)integration_type_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_UnaryFunction1DVectorViewShape type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DVectorViewShape_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DVectorViewShape", /* tp_name */
+ sizeof(BPy_UnaryFunction1DVectorViewShape), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DVectorViewShape___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DVectorViewShape___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DVectorViewShape___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DVectorViewShape___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 */
+ BPy_UnaryFunction1DVectorViewShape_getseters, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DVectorViewShape___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h
new file mode 100644
index 00000000000..02233da1e25
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION1DVECTORVIEWSHAPE_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION1DVECTORVIEWSHAPE_H__
+
+#include "../BPy_UnaryFunction1D.h"
+
+#include <vector>
+#include "../../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DVectorViewShape_Type;
+
+#define BPy_UnaryFunction1DVectorViewShape_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction1DVectorViewShape_Type))
+
+/*---------------------------Python BPy_UnaryFunction1DVectorViewShape structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D< std::vector<ViewShape*> > *uf1D_vectorviewshape;
+} BPy_UnaryFunction1DVectorViewShape;
+
+/*---------------------------Python BPy_UnaryFunction1DVectorViewShape visible prototypes-----------*/
+int UnaryFunction1DVectorViewShape_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION1DVECTORVIEWSHAPE_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp
new file mode 100644
index 00000000000..7b1e5ba9c61
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp
@@ -0,0 +1,227 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_UnaryFunction1DVoid.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h"
+#include "UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h"
+#include "UnaryFunction1D_void/BPy_TimeStampF1D.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DVoid_Init(PyObject *module)
+{
+ if (module == NULL)
+ return -1;
+
+ if (PyType_Ready(&UnaryFunction1DVoid_Type) < 0)
+ return -1;
+ Py_INCREF(&UnaryFunction1DVoid_Type);
+ PyModule_AddObject(module, "UnaryFunction1DVoid", (PyObject *)&UnaryFunction1DVoid_Type);
+
+ if (PyType_Ready(&ChainingTimeStampF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&ChainingTimeStampF1D_Type);
+ PyModule_AddObject(module, "ChainingTimeStampF1D", (PyObject *)&ChainingTimeStampF1D_Type);
+
+ if (PyType_Ready(&IncrementChainingTimeStampF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&IncrementChainingTimeStampF1D_Type);
+ PyModule_AddObject(module, "IncrementChainingTimeStampF1D", (PyObject *)&IncrementChainingTimeStampF1D_Type);
+
+ if (PyType_Ready(&TimeStampF1D_Type) < 0)
+ return -1;
+ Py_INCREF(&TimeStampF1D_Type);
+ PyModule_AddObject(module, "TimeStampF1D", (PyObject *)&TimeStampF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DVoid___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVoid`\n"
+"\n"
+"Base class for unary functions (functors) working on\n"
+":class:`Interface1D`.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration_type)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration_type: An integration method.\n"
+" :type integration_type: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DVoid___init__(BPy_UnaryFunction1DVoid *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+
+ if (!obj)
+ self->uf1D_void = new UnaryFunction1D_void();
+ else {
+ self->uf1D_void = new UnaryFunction1D_void(IntegrationType_from_BPy_IntegrationType(obj));
+ }
+
+ self->uf1D_void->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DVoid___dealloc__(BPy_UnaryFunction1DVoid *self)
+{
+ if (self->uf1D_void)
+ delete self->uf1D_void;
+ UnaryFunction1D_Type.tp_dealloc((PyObject *)self);
+}
+
+static PyObject *UnaryFunction1DVoid___repr__(BPy_UnaryFunction1DVoid *self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", Py_TYPE(self)->tp_name, self->uf1D_void);
+}
+
+static PyObject *UnaryFunction1DVoid___call__(BPy_UnaryFunction1DVoid *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"inter", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char **)kwlist, &Interface1D_Type, &obj))
+ return NULL;
+
+ if (typeid(*(self->uf1D_void)) == typeid(UnaryFunction1D_void)) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_void->operator()(*(((BPy_Interface1D *) obj)->if1D)) < 0) {
+ if (!PyErr_Occurred()) {
+ string class_name(Py_TYPE(self)->tp_name);
+ PyErr_SetString(PyExc_RuntimeError, (class_name + " __call__ method failed").c_str());
+ }
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+/*----------------------UnaryFunction1DVoid get/setters ----------------------------*/
+
+PyDoc_STRVAR(integration_type_doc,
+"The integration method.\n"
+"\n"
+":type: :class:`IntegrationType`");
+
+static PyObject *integration_type_get(BPy_UnaryFunction1DVoid *self, void *UNUSED(closure))
+{
+ return BPy_IntegrationType_from_IntegrationType(self->uf1D_void->getIntegrationType());
+}
+
+static int integration_type_set(BPy_UnaryFunction1DVoid *self, PyObject *value, void *UNUSED(closure))
+{
+ if (!BPy_IntegrationType_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "value must be an IntegrationType");
+ return -1;
+ }
+ self->uf1D_void->setIntegrationType(IntegrationType_from_BPy_IntegrationType(value));
+ return 0;
+}
+
+static PyGetSetDef BPy_UnaryFunction1DVoid_getseters[] = {
+ {(char *)"integration_type", (getter)integration_type_get, (setter)integration_type_set,
+ (char *)integration_type_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+/*-----------------------BPy_UnaryFunction1DVoid type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DVoid_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DVoid", /* tp_name */
+ sizeof(BPy_UnaryFunction1DVoid), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DVoid___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DVoid___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DVoid___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DVoid___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 */
+ BPy_UnaryFunction1DVoid_getseters, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DVoid___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h
new file mode 100644
index 00000000000..40569885e4c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h
@@ -0,0 +1,65 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_UNARYFUNCTION1DVOID_H__
+#define __FREESTYLE_PYTHON_UNARYFUNCTION1DVOID_H__
+
+#include "../BPy_UnaryFunction1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DVoid_Type;
+
+#define BPy_UnaryFunction1DVoid_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&UnaryFunction1DVoid_Type))
+
+/*---------------------------Python BPy_UnaryFunction1DVoid structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D_void *uf1D_void;
+} BPy_UnaryFunction1DVoid;
+
+/*---------------------------Python BPy_UnaryFunction1DVoid visible prototypes-----------*/
+int UnaryFunction1DVoid_Init(PyObject *module);
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_UNARYFUNCTION1DVOID_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp
new file mode 100644
index 00000000000..f431fef1306
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp
@@ -0,0 +1,130 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_CurveNatureF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char CurveNatureF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DEdgeNature` > :class:`CurveNatureF1D`\n"
+"\n"
+".. method:: __init__(integration_type=IntegrationType.MEAN)\n"
+"\n"
+" Builds a CurveNatureF1D object.\n"
+"\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the nature of the Interface1D (silhouette, ridge, crease,\n"
+" and so on). Except if the Interface1D is a :class:`ViewEdge`, this\n"
+" result might be ambiguous. Indeed, the Interface1D might result\n"
+" from the gathering of several 1D elements, each one being of a\n"
+" different nature. An integration method, such as the MEAN, might\n"
+" give, in this case, irrelevant results.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The nature of the Interface1D.\n"
+" :rtype: :class:`Nature`\n";
+
+static int CurveNatureF1D___init__(BPy_CurveNatureF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration_type", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_edgenature.uf1D_edgenature = new Functions1D::CurveNatureF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_CurveNatureF1D type definition ------------------------------*/
+
+PyTypeObject CurveNatureF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "CurveNatureF1D", /* tp_name */
+ sizeof(BPy_CurveNatureF1D), /* 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 */
+ CurveNatureF1D___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 */
+ &UnaryFunction1DEdgeNature_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)CurveNatureF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h
new file mode 100644
index 00000000000..dbdb1180ee8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_CURVENATUREF1D_H__
+#define __FREESTYLE_PYTHON_CURVENATUREF1D_H__
+
+#include "../BPy_UnaryFunction1DEdgeNature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject CurveNatureF1D_Type;
+
+#define BPy_CurveNatureF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&CurveNatureF1D_Type))
+
+/*---------------------------Python BPy_CurveNatureF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DEdgeNature py_uf1D_edgenature;
+} BPy_CurveNatureF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_CURVENATUREF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp
new file mode 100644
index 00000000000..c9c08c1c5dd
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp
@@ -0,0 +1,125 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_Normal2DF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Normal2DF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVec2f` > :class:`Normal2DF1D`\n"
+"\n"
+".. method:: __init__(integration_type=IntegrationType.MEAN)\n"
+"\n"
+" Builds a Normal2DF1D object.\n"
+"\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the 2D normal for the Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The 2D normal for the Interface1D.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static int Normal2DF1D___init__(BPy_Normal2DF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration_type", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_vec2f.uf1D_vec2f = new Functions1D::Normal2DF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_Normal2DF1D type definition ------------------------------*/
+
+PyTypeObject Normal2DF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Normal2DF1D", /* tp_name */
+ sizeof(BPy_Normal2DF1D), /* 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 */
+ Normal2DF1D___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 */
+ &UnaryFunction1DVec2f_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Normal2DF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h
new file mode 100644
index 00000000000..9d49b10c616
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_NORMAL2DF1D_H__
+#define __FREESTYLE_PYTHON_NORMAL2DF1D_H__
+
+#include "../BPy_UnaryFunction1DVec2f.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Normal2DF1D_Type;
+
+#define BPy_Normal2DF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Normal2DF1D_Type))
+
+/*---------------------------Python BPy_Normal2DF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVec2f py_uf1D_vec2f;
+} BPy_Normal2DF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_NORMAL2DF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp
new file mode 100644
index 00000000000..9cdcb8c4969
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp
@@ -0,0 +1,125 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_Orientation2DF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Orientation2DF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVec2f` > :class:`Orientation2DF1D`\n"
+"\n"
+".. method:: __init__(integration_type=IntegrationType.MEAN)\n"
+"\n"
+" Builds an Orientation2DF1D object.\n"
+"\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the 2D orientation of the Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The 2D orientation of the Interface1D.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static int Orientation2DF1D___init__(BPy_Orientation2DF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration_type", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_vec2f.uf1D_vec2f = new Functions1D::Orientation2DF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_Orientation2DF1D type definition ------------------------------*/
+
+PyTypeObject Orientation2DF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Orientation2DF1D", /* tp_name */
+ sizeof(BPy_Orientation2DF1D), /* 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 */
+ Orientation2DF1D___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 */
+ &UnaryFunction1DVec2f_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Orientation2DF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h
new file mode 100644
index 00000000000..ccf69ab394c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_ORIENTATION2DF1D_H__
+#define __FREESTYLE_PYTHON_ORIENTATION2DF1D_H__
+
+#include "../BPy_UnaryFunction1DVec2f.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Orientation2DF1D_Type;
+
+#define BPy_Orientation2DF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Orientation2DF1D_Type))
+
+/*---------------------------Python BPy_Orientation2DF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVec2f py_uf1D_vec2f;
+} BPy_Orientation2DF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_ORIENTATION2DF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp
new file mode 100644
index 00000000000..5d2750546bb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp
@@ -0,0 +1,125 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_Orientation3DF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Orientation3DF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVec3f` > :class:`Orientation3DF1D`\n"
+"\n"
+".. method:: __init__(integration_type=IntegrationType.MEAN)\n"
+"\n"
+" Builds an Orientation3DF1D object.\n"
+"\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the 3D orientation of the Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The 3D orientation of the Interface1D.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static int Orientation3DF1D___init__(BPy_Orientation3DF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration_type", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_vec3f.uf1D_vec3f = new Functions1D::Orientation3DF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_Orientation3DF1D type definition ------------------------------*/
+
+PyTypeObject Orientation3DF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Orientation3DF1D", /* tp_name */
+ sizeof(BPy_Orientation3DF1D), /* 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 */
+ Orientation3DF1D___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 */
+ &UnaryFunction1DVec3f_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Orientation3DF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h
new file mode 100644
index 00000000000..cfce5afdfbd
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_ORIENTATION3DF1D_H__
+#define __FREESTYLE_PYTHON_ORIENTATION3DF1D_H__
+
+#include "../BPy_UnaryFunction1DVec3f.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Orientation3DF1D_Type;
+
+#define BPy_Orientation3DF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Orientation3DF1D_Type))
+
+/*---------------------------Python BPy_Orientation3DF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVec3f py_uf1D_vec3f;
+} BPy_Orientation3DF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_ORIENTATION3DF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp
new file mode 100644
index 00000000000..891cc6b0443
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp
@@ -0,0 +1,125 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_Curvature2DAngleF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Curvature2DAngleF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`Curvature2DAngleF1D`\n"
+"\n"
+".. method:: __init__(integration_type=IntegrationType.MEAN)\n"
+"\n"
+" Builds a Curvature2DAngleF1D object.\n"
+"\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the 2D curvature as an angle for an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The 2D curvature as an angle.\n"
+" :rtype: float\n";
+
+static int Curvature2DAngleF1D___init__(BPy_Curvature2DAngleF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration_type", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::Curvature2DAngleF1D(t);
+ return 0;
+
+}
+/*-----------------------BPy_Curvature2DAngleF1D type definition ------------------------------*/
+
+PyTypeObject Curvature2DAngleF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Curvature2DAngleF1D", /* tp_name */
+ sizeof(BPy_Curvature2DAngleF1D), /* 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 */
+ Curvature2DAngleF1D___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 */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Curvature2DAngleF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h
new file mode 100644
index 00000000000..3f14d6545f9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_CURVATURE2DANGLEF1D_H__
+#define __FREESTYLE_PYTHON_CURVATURE2DANGLEF1D_H__
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Curvature2DAngleF1D_Type;
+
+#define BPy_Curvature2DAngleF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&Curvature2DAngleF1D_Type))
+
+/*---------------------------Python BPy_Curvature2DAngleF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_Curvature2DAngleF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_CURVATURE2DANGLEF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp
new file mode 100644
index 00000000000..7e81f45c295
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_DensityF1D.h"
+
+#include "../../../stroke/AdvancedFunctions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char DensityF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`DensityF1D`\n"
+"\n"
+".. method:: __init__(sigma=2.0, integration_type=IntegrationType.MEAN, sampling=2.0)\n"
+"\n"
+" Builds a DensityF1D object.\n"
+"\n"
+" :arg sigma: The sigma used in DensityF0D and determining the window size\n"
+" used in each density query.\n"
+" :type sigma: float\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+" :arg sampling: The resolution used to sample the chain: the\n"
+" corresponding 0D function is evaluated at each sample point and\n"
+" the result is obtained by combining the resulting values into a\n"
+" single one, following the method specified by integration_type.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the density evaluated for an Interface1D. The density is\n"
+" evaluated for a set of points along the Interface1D (using the\n"
+" :class:`DensityF0D` functor) with a user-defined sampling and then\n"
+" integrated into a single value using a user-defined integration\n"
+" method.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The density evaluated for an Interface1D.\n"
+" :rtype: float\n";
+
+static int DensityF1D___init__(BPy_DensityF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"sigma", "integration_type", "sampling", NULL};
+ PyObject *obj = 0;
+ double d = 2.0;
+ float f = 2.0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|dO!f", (char **)kwlist, &d, &IntegrationType_Type, &obj, &f))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::DensityF1D(d, t, f);
+ return 0;
+}
+
+/*-----------------------BPy_DensityF1D type definition ------------------------------*/
+
+PyTypeObject DensityF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "DensityF1D", /* tp_name */
+ sizeof(BPy_DensityF1D), /* 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 */
+ DensityF1D___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 */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)DensityF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.h
new file mode 100644
index 00000000000..88cbe5f47f0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_DENSITYF1D_H__
+#define __FREESTYLE_PYTHON_DENSITYF1D_H__
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject DensityF1D_Type;
+
+#define BPy_DensityF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&DensityF1D_Type))
+
+/*---------------------------Python BPy_DensityF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_DensityF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_DENSITYF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp
new file mode 100644
index 00000000000..eb478beab8e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetCompleteViewMapDensityF1D.h"
+
+#include "../../../stroke/AdvancedFunctions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetCompleteViewMapDensityF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetCompleteViewMapDensityF1D`\n"
+"\n"
+".. method:: __init__(level, integration_type=IntegrationType.MEAN, sampling=2.0)\n"
+"\n"
+" Builds a GetCompleteViewMapDensityF1D object.\n"
+"\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+" :arg sampling: The resolution used to sample the chain: the\n"
+" corresponding 0D function is evaluated at each sample point and\n"
+" the result is obtained by combining the resulting values into a\n"
+" single one, following the method specified by integration_type.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the density evaluated for an Interface1D in the complete\n"
+" viewmap image. The density is evaluated for a set of points along\n"
+" the Interface1D (using the :class:`ReadCompleteViewMapPixelF0D`\n"
+" functor) and then integrated into a single value using a\n"
+" user-defined integration method.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The density evaluated for the Interface1D in the complete\n"
+" viewmap image.\n"
+" :rtype: float\n";
+
+static int GetCompleteViewMapDensityF1D___init__(BPy_GetCompleteViewMapDensityF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"level", "integration_type", "sampling", NULL};
+ PyObject *obj = 0;
+ int i;
+ float f = 2.0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|O!f", (char **)kwlist, &i, &IntegrationType_Type, &obj, &f))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetCompleteViewMapDensityF1D(i, t, f);
+ return 0;
+}
+
+/*-----------------------BPy_GetCompleteViewMapDensityF1D type definition ------------------------------*/
+
+PyTypeObject GetCompleteViewMapDensityF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetCompleteViewMapDensityF1D", /* tp_name */
+ sizeof(BPy_GetCompleteViewMapDensityF1D), /* 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 */
+ GetCompleteViewMapDensityF1D___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 */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetCompleteViewMapDensityF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h
new file mode 100644
index 00000000000..a9af0580e4b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETCOMPLETEVIEWMAPDENSITYF1D_H__
+#define __FREESTYLE_PYTHON_GETCOMPLETEVIEWMAPDENSITYF1D_H__
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetCompleteViewMapDensityF1D_Type;
+
+#define BPy_GetCompleteViewMapDensityF1D_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetCompleteViewMapDensityF1D_Type))
+
+/*---------------------------Python BPy_GetCompleteViewMapDensityF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetCompleteViewMapDensityF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETCOMPLETEVIEWMAPDENSITYF1D_H__ */
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
new file mode 100644
index 00000000000..2e5c55b9cc3
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp
@@ -0,0 +1,146 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetDirectionalViewMapDensityF1D.h"
+
+#include "../../../stroke/AdvancedFunctions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetDirectionalViewMapDensityF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` "
+"> :class:`GetDirectionalViewMapDensityF1D`\n"
+"\n"
+".. method:: __init__(orientation, level, integration_type=IntegrationType.MEAN, sampling=2.0)\n"
+"\n"
+" Builds a GetDirectionalViewMapDensityF1D object.\n"
+"\n"
+" :arg orientation: The number of the directional map we must work\n"
+" with.\n"
+" :type orientation: int\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+" :arg sampling: The resolution used to sample the chain: the\n"
+" corresponding 0D function is evaluated at each sample point and\n"
+" the result is obtained by combining the resulting values into a\n"
+" single one, following the method specified by integration_type.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the density evaluated for an Interface1D in of the\n"
+" steerable viewmaps image. The direction telling which Directional\n"
+" map to choose is explicitely specified by the user. The density is\n"
+" evaluated for a set of points along the Interface1D (using the\n"
+" :class:`ReadSteerableViewMapPixelF0D` functor) and then integrated\n"
+" into a single value using a user-defined integration method.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: the density evaluated for an Interface1D in of the\n"
+" steerable viewmaps image.\n"
+" :rtype: float\n";
+
+static int GetDirectionalViewMapDensityF1D___init__(BPy_GetDirectionalViewMapDensityF1D *self,
+ PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"orientation", "level", "integration_type", "sampling", NULL};
+ PyObject *obj = 0;
+ unsigned int u1, u2;
+ float f = 2.0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "II|O!f", (char **)kwlist, &u1, &u2, &IntegrationType_Type, &obj, &f))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetDirectionalViewMapDensityF1D(u1, u2, t, f);
+ return 0;
+}
+
+/*-----------------------BPy_GetDirectionalViewMapDensityF1D type definition ------------------------------*/
+
+PyTypeObject GetDirectionalViewMapDensityF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetDirectionalViewMapDensityF1D", /* tp_name */
+ sizeof(BPy_GetDirectionalViewMapDensityF1D), /* 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 */
+ GetDirectionalViewMapDensityF1D___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 */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetDirectionalViewMapDensityF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h
new file mode 100644
index 00000000000..d07ffde97f8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETDIRECTIONALVIEWMAPDENSITYF1D_H__
+#define __FREESTYLE_PYTHON_GETDIRECTIONALVIEWMAPDENSITYF1D_H__
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetDirectionalViewMapDensityF1D_Type;
+
+#define BPy_GetDirectionalViewMapDensityF1D_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetDirectionalViewMapDensityF1D_Type))
+
+/*---------------------------Python BPy_GetDirectionalViewMapDensityF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetDirectionalViewMapDensityF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETDIRECTIONALVIEWMAPDENSITYF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp
new file mode 100644
index 00000000000..882015f092b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp
@@ -0,0 +1,125 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetProjectedXF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetProjectedXF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetProjectedXF1D`\n"
+"\n"
+".. method:: __init__(integration_type=IntegrationType.MEAN)\n"
+"\n"
+" Builds a GetProjectedXF1D object.\n"
+"\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values. \n"
+" :type integration_type: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the projected X 3D coordinate of an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The projected X 3D coordinate of an Interface1D.\n"
+" :rtype: float\n";
+
+static int GetProjectedXF1D___init__(BPy_GetProjectedXF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration_type", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetProjectedXF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_GetProjectedXF1D type definition ------------------------------*/
+
+PyTypeObject GetProjectedXF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetProjectedXF1D", /* tp_name */
+ sizeof(BPy_GetProjectedXF1D), /* 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 */
+ GetProjectedXF1D___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 */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetProjectedXF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.h
new file mode 100644
index 00000000000..2e45eecc04d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETPROJECTEDXF1D_H__
+#define __FREESTYLE_PYTHON_GETPROJECTEDXF1D_H__
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetProjectedXF1D_Type;
+
+#define BPy_GetProjectedXF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetProjectedXF1D_Type))
+
+/*---------------------------Python BPy_GetProjectedXF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetProjectedXF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETPROJECTEDXF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp
new file mode 100644
index 00000000000..7c2c91ba6b9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp
@@ -0,0 +1,125 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetProjectedYF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetProjectedYF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetProjectedYF1D`\n"
+"\n"
+".. method:: __init__(integration_type=IntegrationType.MEAN)\n"
+"\n"
+" Builds a GetProjectedYF1D object.\n"
+"\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values. \n"
+" :type integration_type: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the projected Y 3D coordinate of an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The projected Y 3D coordinate of an Interface1D.\n"
+" :rtype: float\n";
+
+static int GetProjectedYF1D___init__(BPy_GetProjectedYF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration_type", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetProjectedYF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_GetProjectedYF1D type definition ------------------------------*/
+
+PyTypeObject GetProjectedYF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetProjectedYF1D", /* tp_name */
+ sizeof(BPy_GetProjectedYF1D), /* 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 */
+ GetProjectedYF1D___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 */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetProjectedYF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.h
new file mode 100644
index 00000000000..0ab3ea8e82b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETPROJECTEDYF1D_H__
+#define __FREESTYLE_PYTHON_GETPROJECTEDYF1D_H__
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetProjectedYF1D_Type;
+
+#define BPy_GetProjectedYF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetProjectedYF1D_Type))
+
+/*---------------------------Python BPy_GetProjectedYF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetProjectedYF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETPROJECTEDYF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp
new file mode 100644
index 00000000000..28c198f841f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp
@@ -0,0 +1,125 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetProjectedZF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetProjectedZF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetProjectedZF1D`\n"
+"\n"
+".. method:: __init__(integration_type=IntegrationType.MEAN)\n"
+"\n"
+" Builds a GetProjectedZF1D object.\n"
+"\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values. \n"
+" :type integration_type: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the projected Z 3D coordinate of an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The projected Z 3D coordinate of an Interface1D.\n"
+" :rtype: float\n";
+
+static int GetProjectedZF1D___init__(BPy_GetProjectedZF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration_type", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetProjectedZF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_GetProjectedZF1D type definition ------------------------------*/
+
+PyTypeObject GetProjectedZF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetProjectedZF1D", /* tp_name */
+ sizeof(BPy_GetProjectedZF1D), /* 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 */
+ GetProjectedZF1D___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 */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetProjectedZF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.h
new file mode 100644
index 00000000000..d65160dcfe8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETPROJECTEDZF1D_H__
+#define __FREESTYLE_PYTHON_GETPROJECTEDZF1D_H__
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetProjectedZF1D_Type;
+
+#define BPy_GetProjectedZF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetProjectedZF1D_Type))
+
+/*---------------------------Python BPy_GetProjectedZF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetProjectedZF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETPROJECTEDZF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp
new file mode 100644
index 00000000000..73fb0d5d8fc
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetSteerableViewMapDensityF1D.h"
+
+#include "../../../stroke/AdvancedFunctions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetSteerableViewMapDensityF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetSteerableViewMapDensityF1D`\n"
+"\n"
+".. method:: __init__(level, integration_type=IntegrationType.MEAN, sampling=2.0)\n"
+"\n"
+" Builds a GetSteerableViewMapDensityF1D object.\n"
+"\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+" :arg sampling: The resolution used to sample the chain: the\n"
+" corresponding 0D function is evaluated at each sample point and\n"
+" the result is obtained by combining the resulting values into a\n"
+" single one, following the method specified by integration_type.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the density of the ViewMap for a given Interface1D. The\n"
+" density of each :class:`FEdge` is evaluated in the proper steerable\n"
+" :class:`ViewMap` depending on its orientation.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The density of the ViewMap for a given Interface1D.\n"
+" :rtype: float\n";
+
+static int GetSteerableViewMapDensityF1D___init__(BPy_GetSteerableViewMapDensityF1D *self,
+ PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"level", "integration_type", "sampling", NULL};
+ PyObject *obj = 0;
+ int i;
+ float f = 2.0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|O!f", (char **)kwlist, &i, &IntegrationType_Type, &obj, &f))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetSteerableViewMapDensityF1D(i, t, f);
+ return 0;
+}
+
+/*-----------------------BPy_GetSteerableViewMapDensityF1D type definition ------------------------------*/
+
+PyTypeObject GetSteerableViewMapDensityF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetSteerableViewMapDensityF1D", /* tp_name */
+ sizeof(BPy_GetSteerableViewMapDensityF1D), /* 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 */
+ GetSteerableViewMapDensityF1D___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 */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetSteerableViewMapDensityF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h
new file mode 100644
index 00000000000..30872cc4b85
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETSTEERABLEVIEWMAPDENSITYF1D_H__
+#define __FREESTYLE_PYTHON_GETSTEERABLEVIEWMAPDENSITYF1D_H__
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetSteerableViewMapDensityF1D_Type;
+
+#define BPy_GetSteerableViewMapDensityF1D_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetSteerableViewMapDensityF1D_Type))
+/*---------------------------Python BPy_GetSteerableViewMapDensityF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetSteerableViewMapDensityF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETSTEERABLEVIEWMAPDENSITYF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp
new file mode 100644
index 00000000000..b0c7c1b7c4e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp
@@ -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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetViewMapGradientNormF1D.h"
+
+#include "../../../stroke/AdvancedFunctions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetViewMapGradientNormF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetViewMapGradientNormF1D`\n"
+"\n"
+".. method:: __init__(level, integration_type=IntegrationType.MEAN, sampling=2.0)\n"
+"\n"
+" Builds a GetViewMapGradientNormF1D object.\n"
+"\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+" :arg sampling: The resolution used to sample the chain: the\n"
+" corresponding 0D function is evaluated at each sample point and\n"
+" the result is obtained by combining the resulting values into a\n"
+" single one, following the method specified by integration_type.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the density of the ViewMap for a given Interface1D. The\n"
+" density of each :class:`FEdge` is evaluated in the proper steerable\n"
+" :class:`ViewMap` depending on its orientation.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The density of the ViewMap for a given Interface1D.\n"
+" :rtype: float\n";
+
+static int GetViewMapGradientNormF1D___init__(BPy_GetViewMapGradientNormF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"level", "integration_type", "sampling", NULL};
+ PyObject *obj = 0;
+ int i;
+ float f = 2.0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|O!f", (char **)kwlist, &i, &IntegrationType_Type, &obj, &f))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetViewMapGradientNormF1D(i, t, f);
+ return 0;
+}
+
+/*-----------------------BPy_GetViewMapGradientNormF1D type definition ------------------------------*/
+
+PyTypeObject GetViewMapGradientNormF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetViewMapGradientNormF1D", /* tp_name */
+ sizeof(BPy_GetViewMapGradientNormF1D), /* 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 */
+ GetViewMapGradientNormF1D___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 */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetViewMapGradientNormF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h
new file mode 100644
index 00000000000..b8c9fbef4ab
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h
@@ -0,0 +1,63 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF1D_H__
+#define __FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF1D_H__
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetViewMapGradientNormF1D_Type;
+
+#define BPy_GetViewMapGradientNormF1D_Check(v) \
+ (((PyObject *)v)->ob_type == PyObject_IsInstance((PyObject *)v, \
+ (PyObject *)&GetViewMapGradientNormF1D_Type))
+
+/*---------------------------Python BPy_GetViewMapGradientNormF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetViewMapGradientNormF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp
new file mode 100644
index 00000000000..f541b5ef32d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp
@@ -0,0 +1,125 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetXF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetXF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetXF1D`\n"
+"\n"
+".. method:: __init__(integration_type=IntegrationType.MEAN)\n"
+"\n"
+" Builds a GetXF1D object.\n"
+"\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the X 3D coordinate of an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The X 3D coordinate of the Interface1D.\n"
+" :rtype: float\n";
+
+static int GetXF1D___init__(BPy_GetXF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration_type", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetXF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_GetXF1D type definition ------------------------------*/
+
+PyTypeObject GetXF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetXF1D", /* tp_name */
+ sizeof(BPy_GetXF1D), /* 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 */
+ GetXF1D___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 */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetXF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.h
new file mode 100644
index 00000000000..aa1aa123cc9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETXF1D_H__
+#define __FREESTYLE_PYTHON_GETXF1D_H__
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetXF1D_Type;
+
+#define BPy_GetXF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetXF1D_Type))
+
+/*---------------------------Python BPy_GetXF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetXF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETXF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp
new file mode 100644
index 00000000000..5d7b3a4e612
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetYF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetYF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetYF1D`\n"
+"\n"
+".. method:: __init__(integration_type=IntegrationType.MEAN)\n"
+"\n"
+" Builds a GetYF1D object.\n"
+"\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the Y 3D coordinate of an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The Y 3D coordinate of the Interface1D.\n"
+" :rtype: float\n";
+
+static int GetYF1D___init__(BPy_GetYF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration_type", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetYF1D(t);
+ return 0;
+}
+/*-----------------------BPy_GetYF1D type definition ------------------------------*/
+
+PyTypeObject GetYF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetYF1D", /* tp_name */
+ sizeof(BPy_GetYF1D), /* 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 */
+ GetYF1D___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 */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetYF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.h
new file mode 100644
index 00000000000..4a704b199ec
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETYF1D_H__
+#define __FREESTYLE_PYTHON_GETYF1D_H__
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetYF1D_Type;
+
+#define BPy_GetYF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetYF1D_Type))
+
+/*---------------------------Python BPy_GetYF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetYF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETYF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp
new file mode 100644
index 00000000000..8b3322dd386
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp
@@ -0,0 +1,125 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetZF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetZF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetZF1D`\n"
+"\n"
+".. method:: __init__(integration_type=IntegrationType.MEAN)\n"
+"\n"
+" Builds a GetZF1D object.\n"
+"\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the Z 3D coordinate of an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The Z 3D coordinate of the Interface1D.\n"
+" :rtype: float\n";
+
+static int GetZF1D___init__(BPy_GetZF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration_type", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetZF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_GetZF1D type definition ------------------------------*/
+
+PyTypeObject GetZF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetZF1D", /* tp_name */
+ sizeof(BPy_GetZF1D), /* 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 */
+ GetZF1D___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 */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetZF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.h
new file mode 100644
index 00000000000..3810a5810ab
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETZF1D_H__
+#define __FREESTYLE_PYTHON_GETZF1D_H__
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetZF1D_Type;
+
+#define BPy_GetZF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetZF1D_Type))
+
+/*---------------------------Python BPy_GetZF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetZF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETZF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp
new file mode 100644
index 00000000000..67108e82eb8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp
@@ -0,0 +1,133 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_LocalAverageDepthF1D.h"
+
+#include "../../../stroke/AdvancedFunctions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char LocalAverageDepthF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`LocalAverageDepthF1D`\n"
+"\n"
+".. method:: __init__(sigma, integration_type=IntegrationType.MEAN)\n"
+"\n"
+" Builds a LocalAverageDepthF1D object.\n"
+"\n"
+" :arg sigma: The sigma used in DensityF0D and determining the window\n"
+" size used in each density query.\n"
+" :type sigma: float\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the average depth evaluated for an Interface1D. The\n"
+" average depth is evaluated for a set of points along the\n"
+" Interface1D (using the :class:`LocalAverageDepthF0D` functor) with\n"
+" a user-defined sampling and then integrated into a single value\n"
+" using a user-defined integration method.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The average depth evaluated for the Interface1D.\n"
+" :rtype: float\n";
+
+static int LocalAverageDepthF1D___init__(BPy_LocalAverageDepthF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"sigma", "integration_type", NULL};
+ PyObject *obj = 0;
+ double d;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "d|O!", (char **)kwlist, &d, &IntegrationType_Type, &obj))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::LocalAverageDepthF1D(d, t);
+ return 0;
+}
+
+/*-----------------------BPy_LocalAverageDepthF1D type definition ------------------------------*/
+
+PyTypeObject LocalAverageDepthF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "LocalAverageDepthF1D", /* tp_name */
+ sizeof(BPy_LocalAverageDepthF1D), /* 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 */
+ LocalAverageDepthF1D___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 */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)LocalAverageDepthF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h
new file mode 100644
index 00000000000..bd91b66d3ac
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF1D_H__
+#define __FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF1D_H__
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject LocalAverageDepthF1D_Type;
+
+#define BPy_LocalAverageDepthF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&LocalAverageDepthF1D_Type))
+
+/*---------------------------Python BPy_LocalAverageDepthF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_LocalAverageDepthF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp
new file mode 100644
index 00000000000..b7a389e0148
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ZDiscontinuityF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ZDiscontinuityF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`ZDiscontinuityF1D`\n"
+"\n"
+".. method:: __init__(integration_type=IntegrationType.MEAN)\n"
+"\n"
+" Builds a ZDiscontinuityF1D object.\n"
+"\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns a real value giving the distance between an Interface1D\n"
+" and the shape that lies behind (occludee). This distance is\n"
+" evaluated in the camera space and normalized between 0 and 1.\n"
+" Therefore, if no oject is occluded by the shape to which the\n"
+" Interface1D belongs to, 1 is returned.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The normalized distance between the Interface1D and the occludee.\n"
+" :rtype: float\n";
+
+static int ZDiscontinuityF1D___init__(BPy_ZDiscontinuityF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration_type", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::ZDiscontinuityF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_ZDiscontinuityF1D type definition ------------------------------*/
+
+PyTypeObject ZDiscontinuityF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ZDiscontinuityF1D", /* tp_name */
+ sizeof(BPy_ZDiscontinuityF1D), /* 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 */
+ ZDiscontinuityF1D___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 */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ZDiscontinuityF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h
new file mode 100644
index 00000000000..b5e22e3b990
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_ZDISCONTINUITYF1D_H__
+#define __FREESTYLE_PYTHON_ZDISCONTINUITYF1D_H__
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ZDiscontinuityF1D_Type;
+
+#define BPy_ZDiscontinuityF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ZDiscontinuityF1D_Type))
+
+/*---------------------------Python BPy_ZDiscontinuityF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_ZDiscontinuityF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_ZDISCONTINUITYF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp
new file mode 100644
index 00000000000..8e7c0a354b9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_QuantitativeInvisibilityF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char QuantitativeInvisibilityF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DUnsigned` > :class:`QuantitativeInvisibilityF1D`\n"
+"\n"
+".. method:: __init__(integration_type=IntegrationType.MEAN)\n"
+"\n"
+" Builds a QuantitativeInvisibilityF1D object.\n"
+"\n"
+" :arg integration_type: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the Quantitative Invisibility of an Interface1D element.\n"
+" If the Interface1D is a :class:`ViewEdge`, then there is no\n"
+" ambiguity concerning the result. But, if the Interface1D results\n"
+" of a chaining (chain, stroke), then it might be made of several 1D\n"
+" elements of different Quantitative Invisibilities.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The Quantitative Invisibility of the Interface1D.\n"
+" :rtype: int\n";
+
+static int QuantitativeInvisibilityF1D___init__(BPy_QuantitativeInvisibilityF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"integration_type", NULL};
+ PyObject *obj = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &IntegrationType_Type, &obj))
+ return -1;
+ IntegrationType t = (obj) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_unsigned.uf1D_unsigned = new Functions1D::QuantitativeInvisibilityF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_QuantitativeInvisibilityF1D type definition ------------------------------*/
+
+PyTypeObject QuantitativeInvisibilityF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "QuantitativeInvisibilityF1D", /* tp_name */
+ sizeof(BPy_QuantitativeInvisibilityF1D), /* 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 */
+ QuantitativeInvisibilityF1D___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 */
+ &UnaryFunction1DUnsigned_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)QuantitativeInvisibilityF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h
new file mode 100644
index 00000000000..411d92f8c62
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF1D_H__
+#define __FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF1D_H__
+
+#include "../BPy_UnaryFunction1DUnsigned.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject QuantitativeInvisibilityF1D_Type;
+
+#define BPy_QuantitativeInvisibilityF1D_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&QuantitativeInvisibilityF1D_Type))
+
+/*---------------------------Python BPy_QuantitativeInvisibilityF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DUnsigned py_uf1D_unsigned;
+} BPy_QuantitativeInvisibilityF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp
new file mode 100644
index 00000000000..ec0104598e2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetOccludeeF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetOccludeeF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVectorViewShape` > :class:`GetOccludeeF1D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetOccludeeF1D object.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns a list of occluded shapes covered by this Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: A list of occluded shapes covered by the Interface1D.\n"
+" :rtype: list of :class:`ViewShape` objects\n";
+
+static int GetOccludeeF1D___init__(BPy_GetOccludeeF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf1D_vectorviewshape.uf1D_vectorviewshape = new Functions1D::GetOccludeeF1D();
+ return 0;
+}
+
+/*-----------------------BPy_GetOccludeeF1D type definition ------------------------------*/
+
+PyTypeObject GetOccludeeF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetOccludeeF1D", /* tp_name */
+ sizeof(BPy_GetOccludeeF1D), /* 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 */
+ GetOccludeeF1D___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 */
+ &UnaryFunction1DVectorViewShape_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetOccludeeF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h
new file mode 100644
index 00000000000..bd789f3a474
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETOCCLUDEEF1D_H__
+#define __FREESTYLE_PYTHON_GETOCCLUDEEF1D_H__
+
+#include "../BPy_UnaryFunction1DVectorViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetOccludeeF1D_Type;
+
+#define BPy_GetOccludeeF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetOccludeeF1D_Type))
+
+/*---------------------------Python BPy_GetOccludeeF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVectorViewShape py_uf1D_vectorviewshape;
+} BPy_GetOccludeeF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETOCCLUDEEF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp
new file mode 100644
index 00000000000..a189cc18ae1
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetOccludersF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetOccludersF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVectorViewShape` > :class:`GetOccludersF1D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetOccludersF1D object.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns a list of occluding shapes that cover this Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: A list of occluding shapes that cover the Interface1D.\n"
+" :rtype: list of :class:`ViewShape` objects\n";
+
+static int GetOccludersF1D___init__(BPy_GetOccludersF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf1D_vectorviewshape.uf1D_vectorviewshape = new Functions1D::GetOccludersF1D();
+ return 0;
+}
+
+/*-----------------------BPy_GetOccludersF1D type definition ------------------------------*/
+
+PyTypeObject GetOccludersF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetOccludersF1D", /* tp_name */
+ sizeof(BPy_GetOccludersF1D), /* 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 */
+ GetOccludersF1D___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 */
+ &UnaryFunction1DVectorViewShape_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetOccludersF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h
new file mode 100644
index 00000000000..aa52b86dbb9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETOCCLUDERSF1D_H__
+#define __FREESTYLE_PYTHON_GETOCCLUDERSF1D_H__
+
+#include "../BPy_UnaryFunction1DVectorViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetOccludersF1D_Type;
+
+#define BPy_GetOccludersF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetOccludersF1D_Type))
+
+/*---------------------------Python BPy_GetOccludersF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVectorViewShape py_uf1D_vectorviewshape;
+} BPy_GetOccludersF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETOCCLUDERSF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp
new file mode 100644
index 00000000000..47e0bf225df
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_GetShapeF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetShapeF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVectorViewShape` > :class:`GetShapeF1D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a GetShapeF1D object.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns a list of shapes covered by this Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: A list of shapes covered by the Interface1D.\n"
+" :rtype: list of :class:`ViewShape` objects\n";
+
+static int GetShapeF1D___init__(BPy_GetShapeF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf1D_vectorviewshape.uf1D_vectorviewshape = new Functions1D::GetShapeF1D();
+ return 0;
+}
+
+/*-----------------------BPy_GetShapeF1D type definition ------------------------------*/
+
+PyTypeObject GetShapeF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetShapeF1D", /* tp_name */
+ sizeof(BPy_GetShapeF1D), /* 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 */
+ GetShapeF1D___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 */
+ &UnaryFunction1DVectorViewShape_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetShapeF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h
new file mode 100644
index 00000000000..d13320727b7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_GETSHAPEF1D_H__
+#define __FREESTYLE_PYTHON_GETSHAPEF1D_H__
+
+#include "../BPy_UnaryFunction1DVectorViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetShapeF1D_Type;
+
+#define BPy_GetShapeF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&GetShapeF1D_Type))
+
+/*---------------------------Python BPy_GetShapeF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVectorViewShape py_uf1D_vectorviewshape;
+} BPy_GetShapeF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_GETSHAPEF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp
new file mode 100644
index 00000000000..f31452cd22a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp
@@ -0,0 +1,117 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ChainingTimeStampF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ChainingTimeStampF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVoid` > :class:`ChainingTimeStampF1D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a ChainingTimeStampF1D object.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Sets the chaining time stamp of the Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n";
+
+static int ChainingTimeStampF1D___init__(BPy_ChainingTimeStampF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf1D_void.uf1D_void = new Functions1D::ChainingTimeStampF1D();
+ return 0;
+}
+
+/*-----------------------BPy_ChainingTimeStampF1D type definition ------------------------------*/
+
+PyTypeObject ChainingTimeStampF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ChainingTimeStampF1D", /* tp_name */
+ sizeof(BPy_ChainingTimeStampF1D), /* 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 */
+ ChainingTimeStampF1D___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 */
+ &UnaryFunction1DVoid_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ChainingTimeStampF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h
new file mode 100644
index 00000000000..3cca577bcd8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_CHAININGTIMESTAMPF1D_H__
+#define __FREESTYLE_PYTHON_CHAININGTIMESTAMPF1D_H__
+
+#include "../BPy_UnaryFunction1DVoid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ChainingTimeStampF1D_Type;
+
+#define BPy_ChainingTimeStampF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ChainingTimeStampF1D_Type))
+
+/*---------------------------Python BPy_ChainingTimeStampF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVoid py_uf1D_void;
+} BPy_ChainingTimeStampF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_CHAININGTIMESTAMPF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp
new file mode 100644
index 00000000000..14c8dc400b3
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp
@@ -0,0 +1,118 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_IncrementChainingTimeStampF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char IncrementChainingTimeStampF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVoid` > :class:`IncrementChainingTimeStampF1D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds an IncrementChainingTimeStampF1D object.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Increments the chaining time stamp of the Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n";
+
+static int IncrementChainingTimeStampF1D___init__(BPy_IncrementChainingTimeStampF1D *self,
+ PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf1D_void.uf1D_void = new Functions1D::IncrementChainingTimeStampF1D();
+ return 0;
+}
+
+/*-----------------------BPy_IncrementChainingTimeStampF1D type definition ------------------------------*/
+
+PyTypeObject IncrementChainingTimeStampF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "IncrementChainingTimeStampF1D", /* tp_name */
+ sizeof(BPy_IncrementChainingTimeStampF1D), /* 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 */
+ IncrementChainingTimeStampF1D___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 */
+ &UnaryFunction1DVoid_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)IncrementChainingTimeStampF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h
new file mode 100644
index 00000000000..ed4c402f771
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_INCREMENTCHAININGTIMESTAMPF1D_H__
+#define __FREESTYLE_PYTHON_INCREMENTCHAININGTIMESTAMPF1D_H__
+
+#include "../BPy_UnaryFunction1DVoid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject IncrementChainingTimeStampF1D_Type;
+
+#define BPy_IncrementChainingTimeStampF1D_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&IncrementChainingTimeStampF1D_Type))
+
+/*---------------------------Python BPy_IncrementChainingTimeStampF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVoid py_uf1D_void;
+} BPy_IncrementChainingTimeStampF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_INCREMENTCHAININGTIMESTAMPF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp
new file mode 100644
index 00000000000..b7650a2c173
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp
@@ -0,0 +1,117 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_TimeStampF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TimeStampF1D___doc__[] =
+"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVoid` > :class:`TimeStampF1D`\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a TimeStampF1D object.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the time stamp of the Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n";
+
+static int TimeStampF1D___init__(BPy_TimeStampF1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_uf1D_void.uf1D_void = new Functions1D::TimeStampF1D();
+ return 0;
+}
+
+/*-----------------------BPy_TimeStampF1D type definition ------------------------------*/
+
+PyTypeObject TimeStampF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TimeStampF1D", /* tp_name */
+ sizeof(BPy_TimeStampF1D), /* 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 */
+ TimeStampF1D___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 */
+ &UnaryFunction1DVoid_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TimeStampF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.h
new file mode 100644
index 00000000000..eef28f2b644
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_TIMESTAMPF1D_H__
+#define __FREESTYLE_PYTHON_TIMESTAMPF1D_H__
+
+#include "../BPy_UnaryFunction1DVoid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TimeStampF1D_Type;
+
+#define BPy_TimeStampF1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&TimeStampF1D_Type))
+
+/*---------------------------Python BPy_TimeStampF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVoid py_uf1D_void;
+} BPy_TimeStampF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_CHAININGTIMESTAMPF1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp
new file mode 100644
index 00000000000..4621dc83dc4
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_FalseUP0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FalseUP0D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate0D` > :class:`FalseUP0D`\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Always returns false.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: False.\n"
+" :rtype: bool\n";
+
+static int FalseUP0D___init__(BPy_FalseUP0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_up0D.up0D = new Predicates0D::FalseUP0D();
+ return 0;
+}
+
+/*-----------------------BPy_FalseUP0D type definition ------------------------------*/
+
+PyTypeObject FalseUP0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FalseUP0D", /* tp_name */
+ sizeof(BPy_FalseUP0D), /* 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 */
+ FalseUP0D___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 */
+ &UnaryPredicate0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FalseUP0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.h b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.h
new file mode 100644
index 00000000000..be61eaa0754
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_FALSEUP0D_H__
+#define __FREESTYLE_PYTHON_FALSEUP0D_H__
+
+#include "../BPy_UnaryPredicate0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FalseUP0D_Type;
+
+#define BPy_FalseUP0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&FalseUP0D_Type))
+
+/*---------------------------Python BPy_FalseUP0D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate0D py_up0D;
+} BPy_FalseUP0D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_FALSEUP0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp
new file mode 100644
index 00000000000..37ee914cb17
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_TrueUP0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TrueUP0D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate0D` > :class:`TrueUP0D`\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Always returns true.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: True.\n"
+" :rtype: bool\n";
+
+static int TrueUP0D___init__(BPy_TrueUP0D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_up0D.up0D = new Predicates0D::TrueUP0D();
+ return 0;
+}
+
+/*-----------------------BPy_TrueUP0D type definition ------------------------------*/
+
+PyTypeObject TrueUP0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TrueUP0D", /* tp_name */
+ sizeof(BPy_TrueUP0D), /* 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 */
+ TrueUP0D___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 */
+ &UnaryPredicate0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TrueUP0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.h b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.h
new file mode 100644
index 00000000000..ae690b9fd54
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_TRUEUP0D_H__
+#define __FREESTYLE_PYTHON_TRUEUP0D_H__
+
+#include "../BPy_UnaryPredicate0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TrueUP0D_Type;
+
+#define BPy_TrueUP0D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&TrueUP0D_Type))
+
+/*---------------------------Python BPy_TrueUP0D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate0D py_up0D;
+} BPy_TrueUP0D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_TRUEUP0D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp
new file mode 100644
index 00000000000..37fd851bc31
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ContourUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ContourUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`ContourUP1D`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the Interface1D is a contour. An Interface1D is a\n"
+" contour if it is borded by a different shape on each of its sides.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if the Interface1D is a contour, false otherwise.\n"
+" :rtype: bool\n";
+
+static int ContourUP1D___init__(BPy_ContourUP1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::ContourUP1D();
+ return 0;
+}
+
+/*-----------------------BPy_ContourUP1D type definition ------------------------------*/
+
+PyTypeObject ContourUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ContourUP1D", /* tp_name */
+ sizeof(BPy_ContourUP1D), /* 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 */
+ ContourUP1D___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 */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ContourUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.h
new file mode 100644
index 00000000000..a1a37b1526d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_CONTOURUP1D_H__
+#define __FREESTYLE_PYTHON_CONTOURUP1D_H__
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ContourUP1D_Type;
+
+#define BPy_ContourUP1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ContourUP1D_Type))
+
+/*---------------------------Python BPy_ContourUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_ContourUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_CONTOURUP1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp
new file mode 100644
index 00000000000..def464e1241
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp
@@ -0,0 +1,126 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_DensityLowerThanUP1D.h"
+
+#include "../../stroke/AdvancedPredicates1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char DensityLowerThanUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`DensityLowerThanUP1D`\n"
+"\n"
+".. method:: __init__(threshold, sigma=2.0)\n"
+"\n"
+" Builds a DensityLowerThanUP1D object.\n"
+"\n"
+" :arg threshold: The value of the threshold density. Any Interface1D\n"
+" having a density lower than this threshold will match.\n"
+" :type threshold: float\n"
+" :arg sigma: The sigma value defining the density evaluation window\n"
+" size used in the :class:`DensityF0D` functor.\n"
+" :type sigma: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the density evaluated for the Interface1D is less\n"
+" than a user-defined density value.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if the density is lower than a threshold.\n"
+" :rtype: bool\n";
+
+static int DensityLowerThanUP1D___init__(BPy_DensityLowerThanUP1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"threshold", "sigma", NULL};
+ double d1, d2 = 2.0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "d|d", (char **)kwlist, &d1, &d2))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::DensityLowerThanUP1D(d1, d2);
+ return 0;
+}
+
+/*-----------------------BPy_DensityLowerThanUP1D type definition ------------------------------*/
+
+PyTypeObject DensityLowerThanUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "DensityLowerThanUP1D", /* tp_name */
+ sizeof(BPy_DensityLowerThanUP1D), /* 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 */
+ DensityLowerThanUP1D___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 */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)DensityLowerThanUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.h
new file mode 100644
index 00000000000..65aeb24cec9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_DENSITYLOWERTHANUP1D_H__
+#define __FREESTYLE_PYTHON_DENSITYLOWERTHANUP1D_H__
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject DensityLowerThanUP1D_Type;
+
+#define BPy_DensityLowerThanUP1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&DensityLowerThanUP1D_Type))
+
+/*---------------------------Python BPy_DensityLowerThanUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_DensityLowerThanUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_DENSITYLOWERTHANUP1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp
new file mode 100644
index 00000000000..50f736c1cc0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp
@@ -0,0 +1,120 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_EqualToChainingTimeStampUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char EqualToChainingTimeStampUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`EqualToChainingTimeStampUP1D`\n"
+"\n"
+".. method:: __init__(ts)\n"
+"\n"
+" Builds a EqualToChainingTimeStampUP1D object.\n"
+"\n"
+" :arg ts: A time stamp value.\n"
+" :type ts: int\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the Interface1D's time stamp is equal to a certain\n"
+" user-defined value.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if the time stamp is equal to a user-defined value.\n"
+" :rtype: bool\n";
+
+static int EqualToChainingTimeStampUP1D___init__(BPy_EqualToChainingTimeStampUP1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"ts", NULL};
+ unsigned u;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", (char **)kwlist, &u))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::EqualToChainingTimeStampUP1D(u);
+ return 0;
+}
+
+/*-----------------------BPy_EqualToChainingTimeStampUP1D type definition ------------------------------*/
+
+PyTypeObject EqualToChainingTimeStampUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "EqualToChainingTimeStampUP1D", /* tp_name */
+ sizeof(BPy_EqualToChainingTimeStampUP1D), /* 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 */
+ EqualToChainingTimeStampUP1D___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 */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)EqualToChainingTimeStampUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h
new file mode 100644
index 00000000000..a2c9427953a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_EQUALTOCHAININGTIMESTAMPUP1D_H__
+#define __FREESTYLE_PYTHON_EQUALTOCHAININGTIMESTAMPUP1D_H__
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject EqualToChainingTimeStampUP1D_Type;
+
+#define BPy_EqualToChainingTimeStampUP1D_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&EqualToChainingTimeStampUP1D_Type))
+
+/*---------------------------Python BPy_EqualToChainingTimeStampUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_EqualToChainingTimeStampUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_EQUALTOCHAININGTIMESTAMPUP1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp
new file mode 100644
index 00000000000..7e2d3adcb36
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp
@@ -0,0 +1,120 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_EqualToTimeStampUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char EqualToTimeStampUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`EqualToTimeStampUP1D`\n"
+"\n"
+".. method:: __init__(ts)\n"
+"\n"
+" Builds a EqualToTimeStampUP1D object.\n"
+"\n"
+" :arg ts: A time stamp value.\n"
+" :type ts: int\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the Interface1D's time stamp is equal to a certain\n"
+" user-defined value.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if the time stamp is equal to a user-defined value.\n"
+" :rtype: bool\n";
+
+static int EqualToTimeStampUP1D___init__(BPy_EqualToTimeStampUP1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"ts", NULL};
+ unsigned u;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", (char **)kwlist, &u))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::EqualToTimeStampUP1D(u);
+ return 0;
+}
+
+/*-----------------------BPy_EqualToTimeStampUP1D type definition ------------------------------*/
+
+PyTypeObject EqualToTimeStampUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "EqualToTimeStampUP1D", /* tp_name */
+ sizeof(BPy_EqualToTimeStampUP1D), /* 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 */
+ EqualToTimeStampUP1D___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 */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)EqualToTimeStampUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h
new file mode 100644
index 00000000000..07bd9c43cfa
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_EQUALTOTIMESTAMPUP1D_H__
+#define __FREESTYLE_PYTHON_EQUALTOTIMESTAMPUP1D_H__
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject EqualToTimeStampUP1D_Type;
+
+#define BPy_EqualToTimeStampUP1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&EqualToTimeStampUP1D_Type))
+
+/*---------------------------Python BPy_EqualToTimeStampUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_EqualToTimeStampUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_EQUALTOTIMESTAMPUP1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp
new file mode 100644
index 00000000000..98939f4cf34
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp
@@ -0,0 +1,114 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ExternalContourUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ExternalContourUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`ExternalContourUP1D`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the Interface1D is an external contour. An\n"
+" Interface1D is an external contour if it is borded by no shape on\n"
+" one of its sides.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if the Interface1D is an external contour, false\n"
+" otherwise.\n"
+" :rtype: bool\n";
+
+static int ExternalContourUP1D___init__(BPy_ExternalContourUP1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::ExternalContourUP1D();
+ return 0;
+}
+
+/*-----------------------BPy_ExternalContourUP1D type definition ------------------------------*/
+
+PyTypeObject ExternalContourUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ExternalContourUP1D", /* tp_name */
+ sizeof(BPy_ExternalContourUP1D), /* 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 */
+ ExternalContourUP1D___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 */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ExternalContourUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.h
new file mode 100644
index 00000000000..738f978555d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_EXTERNALCONTOURUP1D_H__
+#define __FREESTYLE_PYTHON_EXTERNALCONTOURUP1D_H__
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ExternalContourUP1D_Type;
+
+#define BPy_ExternalContourUP1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ExternalContourUP1D_Type))
+
+/*---------------------------Python BPy_ExternalContourUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_ExternalContourUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_EXTERNALCONTOURUP1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp
new file mode 100644
index 00000000000..356a7a94f0f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_FalseUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FalseUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`FalseUP1D`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Always returns false.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: False.\n"
+" :rtype: bool\n";
+
+static int FalseUP1D___init__(BPy_FalseUP1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::FalseUP1D();
+ return 0;
+}
+
+/*-----------------------BPy_FalseUP1D type definition ------------------------------*/
+
+PyTypeObject FalseUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FalseUP1D", /* tp_name */
+ sizeof(BPy_FalseUP1D), /* 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 */
+ FalseUP1D___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 */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FalseUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.h
new file mode 100644
index 00000000000..6d8412d16f5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_FALSEUP1D_H__
+#define __FREESTYLE_PYTHON_FALSEUP1D_H__
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FalseUP1D_Type;
+
+#define BPy_FalseUP1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&FalseUP1D_Type))
+
+/*---------------------------Python BPy_FalseUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_FalseUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_FALSEUP1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp
new file mode 100644
index 00000000000..b5acc3f1cd3
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp
@@ -0,0 +1,123 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_QuantitativeInvisibilityUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char QuantitativeInvisibilityUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`QuantitativeInvisibilityUP1D`\n"
+"\n"
+".. method:: __init__(qi=0)\n"
+"\n"
+" Builds a QuantitativeInvisibilityUP1D object.\n"
+"\n"
+" :arg qi: The Quantitative Invisibility you want the Interface1D to\n"
+" have.\n"
+" :type qi: int\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the Quantitative Invisibility evaluated at an\n"
+" Interface1D, using the :class:`QuantitativeInvisibilityF1D`\n"
+" functor, equals a certain user-defined value.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if Quantitative Invisibility equals a user-defined\n"
+" value.\n"
+" :rtype: bool\n";
+
+static int QuantitativeInvisibilityUP1D___init__(BPy_QuantitativeInvisibilityUP1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"qi", NULL};
+ int i = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", (char **)kwlist, &i))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::QuantitativeInvisibilityUP1D(i);
+ return 0;
+}
+
+/*-----------------------BPy_QuantitativeInvisibilityUP1D type definition ------------------------------*/
+
+PyTypeObject QuantitativeInvisibilityUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "QuantitativeInvisibilityUP1D", /* tp_name */
+ sizeof(BPy_QuantitativeInvisibilityUP1D), /* 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 */
+ QuantitativeInvisibilityUP1D___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 */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)QuantitativeInvisibilityUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h
new file mode 100644
index 00000000000..00c59b93578
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYUP1D_H__
+#define __FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYUP1D_H__
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject QuantitativeInvisibilityUP1D_Type;
+
+#define BPy_QuantitativeInvisibilityUP1D_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&QuantitativeInvisibilityUP1D_Type))
+
+/*---------------------------Python BPy_QuantitativeInvisibilityUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_QuantitativeInvisibilityUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYUP1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp
new file mode 100644
index 00000000000..1fb69a208ab
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp
@@ -0,0 +1,123 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_ShapeUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ShapeUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`ShapeUP1D`\n"
+"\n"
+".. method:: __init__(first, second=0)\n"
+"\n"
+" Builds a ShapeUP1D object.\n"
+"\n"
+" :arg first: The first Id component.\n"
+" :type first: int\n"
+" :arg second: The second Id component.\n"
+" :type second: int\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the shape to which the Interface1D belongs to has\n"
+" the same :class:`Id` as the one specified by the user.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if Interface1D belongs to the shape of the\n"
+" user-specified Id.\n"
+" :rtype: bool\n";
+
+static int ShapeUP1D___init__(BPy_ShapeUP1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"first", "second", NULL};
+ unsigned u1, u2 = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "I|I", (char **)kwlist, &u1, &u2))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::ShapeUP1D(u1, u2);
+ return 0;
+}
+
+/*-----------------------BPy_ShapeUP1D type definition ------------------------------*/
+
+PyTypeObject ShapeUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ShapeUP1D", /* tp_name */
+ sizeof(BPy_ShapeUP1D), /* 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 */
+ ShapeUP1D___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 */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ShapeUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.h
new file mode 100644
index 00000000000..0d6f58534b2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_SHAPEUP1D_H__
+#define __FREESTYLE_PYTHON_SHAPEUP1D_H__
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ShapeUP1D_Type;
+
+#define BPy_ShapeUP1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&ShapeUP1D_Type))
+
+/*---------------------------Python BPy_ShapeUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_ShapeUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_SHAPEUP1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp
new file mode 100644
index 00000000000..ad94ab7cb12
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_TrueUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TrueUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`TrueUP1D`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Always returns true.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True.\n"
+" :rtype: bool\n";
+
+static int TrueUP1D___init__(BPy_TrueUP1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", (char **)kwlist))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::TrueUP1D();
+ return 0;
+}
+
+/*-----------------------BPy_TrueUP1D type definition ------------------------------*/
+
+PyTypeObject TrueUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TrueUP1D", /* tp_name */
+ sizeof(BPy_TrueUP1D), /* 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 */
+ TrueUP1D___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 */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TrueUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.h
new file mode 100644
index 00000000000..ceed608d059
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_TRUEUP1D_H__
+#define __FREESTYLE_PYTHON_TRUEUP1D_H__
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TrueUP1D_Type;
+
+#define BPy_TrueUP1D_Check(v) (PyObject_IsInstance((PyObject *)v, (PyObject *)&TrueUP1D_Type))
+
+/*---------------------------Python BPy_TrueUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_TrueUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_TRUEUP1D_H__ */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.cpp
new file mode 100644
index 00000000000..dd8dbb55ffb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.cpp
@@ -0,0 +1,120 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.cpp
+ * \ingroup freestyle
+ */
+
+#include "BPy_WithinImageBoundaryUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char WithinImageBoundaryUP1D___doc__[] =
+"Class hierarchy: :class:`UnaryPredicate1D` > :class:`WithinImageBoundaryUP1D`\n"
+"\n"
+".. method:: __init__(xmin, ymin, xmax, ymax)\n"
+"\n"
+" Builds an WithinImageBoundaryUP1D object.\n"
+"\n"
+" :arg xmin: X lower bound of the image boundary.\n"
+" :type xmin: float\n"
+" :arg ymin: Y lower bound of the image boundary.\n"
+" :type ymin: float\n"
+" :arg xmax: X upper bound of the image boundary.\n"
+" :type xmax: float\n"
+" :arg ymax: Y upper bound of the image boundary.\n"
+" :type ymax: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the Interface1D intersects with image boundary.\n";
+
+static int WithinImageBoundaryUP1D___init__(BPy_WithinImageBoundaryUP1D *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"xmin", "ymin", "xmax", "ymax", NULL};
+ double xmin, ymin, xmax, ymax;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "dddd", (char **)kwlist, &xmin, &ymin, &xmax, &ymax))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::WithinImageBoundaryUP1D(xmin, ymin, xmax, ymax);
+ return 0;
+}
+
+/*-----------------------BPy_TrueUP1D type definition ------------------------------*/
+
+PyTypeObject WithinImageBoundaryUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "WithinImageBoundaryUP1D", /* tp_name */
+ sizeof(BPy_WithinImageBoundaryUP1D), /* 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 */
+ WithinImageBoundaryUP1D___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 */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)WithinImageBoundaryUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.h
new file mode 100644
index 00000000000..dea85f87ea5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.h
+ * \ingroup freestyle
+ */
+
+#ifndef __FREESTYLE_PYTHON_WITHINIMAGEBOUNDARYUP1D_H__
+#define __FREESTYLE_PYTHON_WITHINIMAGEBOUNDARYUP1D_H__
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject WithinImageBoundaryUP1D_Type;
+
+#define BPy_WithinImageBoundaryUP1D_Check(v) \
+ (PyObject_IsInstance((PyObject *)v, (PyObject *)&WithinImageBoundaryUP1D_Type))
+
+/*---------------------------Python BPy_WithinImageBoundaryUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_WithinImageBoundaryUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FREESTYLE_PYTHON_WITHINIMAGEBOUNDARYUP1D_H__ */
diff --git a/source/blender/freestyle/intern/scene_graph/DrawingStyle.h b/source/blender/freestyle/intern/scene_graph/DrawingStyle.h
new file mode 100644
index 00000000000..000b6c8575d
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/DrawingStyle.h
@@ -0,0 +1,128 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_DRAWING_STYLE_H__
+#define __FREESTYLE_DRAWING_STYLE_H__
+
+/** \file blender/freestyle/intern/scene_graph/DrawingStyle.h
+ * \ingroup freestyle
+ * \brief Class to define the drawing style of a node
+ * \author Stephane Grabli
+ * \date 10/10/2002
+ */
+
+class DrawingStyle
+{
+public:
+ enum STYLE {
+ FILLED,
+ LINES,
+ POINTS,
+ INVISIBLE,
+ };
+
+ inline DrawingStyle()
+ {
+ Style = FILLED;
+ LineWidth = 2.0f;
+ PointSize = 2.0f;
+ LightingEnabled = true;
+ }
+
+ inline explicit DrawingStyle(const DrawingStyle& iBrother);
+
+ virtual ~DrawingStyle() {}
+
+ /*! operators */
+ inline DrawingStyle& operator=(const DrawingStyle& ds);
+
+ inline void setStyle(const STYLE iStyle)
+ {
+ Style = iStyle;
+ }
+
+ inline void setLineWidth(const float iLineWidth)
+ {
+ LineWidth = iLineWidth;
+ }
+
+ inline void setPointSize(const float iPointSize)
+ {
+ PointSize = iPointSize;
+ }
+
+ inline void setLightingEnabled(const bool on)
+ {
+ LightingEnabled = on;
+ }
+
+ inline STYLE style() const
+ {
+ return Style;
+ }
+
+ inline float lineWidth() const
+ {
+ return LineWidth;
+ }
+
+ inline float pointSize() const
+ {
+ return PointSize;
+ }
+
+ inline bool lightingEnabled() const
+ {
+ return LightingEnabled;
+ }
+
+private:
+ STYLE Style;
+ float LineWidth;
+ float PointSize;
+ bool LightingEnabled;
+};
+
+DrawingStyle::DrawingStyle(const DrawingStyle& iBrother)
+{
+ Style = iBrother.Style;
+ LineWidth = iBrother.LineWidth;
+ PointSize = iBrother.PointSize;
+ LightingEnabled = iBrother.LightingEnabled;
+}
+
+DrawingStyle& DrawingStyle::operator=(const DrawingStyle& ds)
+{
+ Style = ds.Style;
+ LineWidth = ds.LineWidth;
+ PointSize = ds.PointSize;
+ LightingEnabled = ds.LightingEnabled;
+
+ return *this;
+}
+
+#endif // __FREESTYLE_DRAWING_STYLE_H__
diff --git a/source/blender/freestyle/intern/scene_graph/FrsMaterial.h b/source/blender/freestyle/intern/scene_graph/FrsMaterial.h
new file mode 100644
index 00000000000..831c384d472
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/FrsMaterial.h
@@ -0,0 +1,379 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_MATERIAL_H__
+#define __FREESTYLE_MATERIAL_H__
+
+/** \file blender/freestyle/intern/scene_graph/FrsMaterial.h
+ * \ingroup freestyle
+ * \brief Class used to handle materials.
+ * \author Stephane Grabli
+ * \date 10/10/2002
+ */
+
+#include "../system/FreestyleConfig.h"
+
+/*! Class defining a material */
+class FrsMaterial
+{
+public:
+ /*! Default constructor */
+ inline FrsMaterial();
+
+ /*! Builds a Material from its diffuse, ambiant, specular, emissive colors and a shininess coefficient.
+ * \param iDiffuse
+ * A 4 element float-array containing the diffuse color.
+ * \param iAmbiant
+ * A 4 element float-array containing the ambiant color.
+ * \param iSpecular
+ * A 4 element float-array containing the specular color.
+ * \param iEmission
+ * A 4 element float-array containing the emissive color.
+ * \param iShininess
+ * The shininess coefficient.
+ */
+ inline FrsMaterial(const float *iDiffuse, const float *iAmbiant, const float *iSpecular, const float *iEmission,
+ const float iShininess);
+
+ /*! Copy constructor */
+ inline FrsMaterial(const FrsMaterial& m);
+
+ /*! Destructor */
+ virtual ~FrsMaterial() {}
+
+
+ /*! Returns the diffuse color as a 4 float array */
+ inline const float *diffuse() const
+ {
+ return Diffuse;
+ }
+
+ /*! Returns the red component of the diffuse color */
+ inline const float diffuseR() const
+ {
+ return Diffuse[0];
+ }
+
+ /*! Returns the green component of the diffuse color */
+ inline const float diffuseG() const
+ {
+ return Diffuse[1];
+ }
+
+ /*! Returns the blue component of the diffuse color */
+ inline const float diffuseB() const
+ {
+ return Diffuse[2];
+ }
+
+ /*! Returns the alpha component of the diffuse color */
+ inline const float diffuseA() const
+ {
+ return Diffuse[3];
+ }
+
+ /*! Returns the specular color as a 4 float array */
+ inline const float *specular() const
+ {
+ return Specular;
+ }
+
+ /*! Returns the red component of the specular color */
+ inline const float specularR() const
+ {
+ return Specular[0];
+ }
+
+ /*! Returns the green component of the specular color */
+ inline const float specularG() const
+ {
+ return Specular[1];
+ }
+
+ /*! Returns the blue component of the specular color */
+ inline const float specularB() const
+ {
+ return Specular[2];
+ }
+
+ /*! Returns the alpha component of the specular color */
+ inline const float specularA() const
+ {
+ return Specular[3];
+ }
+
+ /*! Returns the ambiant color as a 4 float array */
+ inline const float *ambient() const
+ {
+ return Ambient;
+ }
+
+ /*! Returns the red component of the ambiant color */
+ inline const float ambientR() const
+ {
+ return Ambient[0];
+ }
+
+ /*! Returns the green component of the ambiant color */
+ inline const float ambientG() const
+ {
+ return Ambient[1];
+ }
+
+ /*! Returns the blue component of the ambiant color */
+ inline const float ambientB() const
+ {
+ return Ambient[2];
+ }
+
+ /*! Returns the alpha component of the ambiant color */
+ inline const float ambientA() const
+ {
+ return Ambient[3];
+ }
+
+ /*! Returns the emissive color as a 4 float array */
+ inline const float *emission() const
+ {
+ return Emission;
+ }
+
+ /*! Returns the red component of the emissive color */
+ inline const float emissionR() const
+ {
+ return Emission[0];
+ }
+
+ /*! Returns the green component of the emissive color */
+ inline const float emissionG() const
+ {
+ return Emission[1];
+ }
+
+ /*! Returns the blue component of the emissive color */
+ inline const float emissionB() const
+ {
+ return Emission[2];
+ }
+
+ /*! Returns the alpha component of the emissive color */
+ inline const float emissionA() const
+ {
+ return Emission[3];
+ }
+
+ /*! Returns the shininess coefficient */
+ inline const float shininess() const
+ {
+ return Shininess;
+ }
+
+ /*! Sets the diffuse color.
+ * \param r
+ * Red component
+ * \param g
+ * Green component
+ * \param b
+ * Blue component
+ * \param a
+ * Alpha component
+ */
+ inline void setDiffuse(const float r, const float g, const float b, const float a);
+
+ /*! Sets the specular color.
+ * \param r
+ * Red component
+ * \param g
+ * Green component
+ * \param b
+ * Blue component
+ * \param a
+ * Alpha component
+ */
+ inline void setSpecular(const float r, const float g, const float b, const float a);
+
+ /*! Sets the ambiant color.
+ * \param r
+ * Red component
+ * \param g
+ * Green component
+ * \param b
+ * Blue component
+ * \param a
+ * Alpha component
+ */
+ inline void setAmbient(const float r, const float g, const float b, const float a);
+
+ /*! Sets the emissive color.
+ * \param r
+ * Red component
+ * \param g
+ * Green component
+ * \param b
+ * Blue component
+ * \param a
+ * Alpha component
+ */
+ inline void setEmission(const float r, const float g, const float b, const float a);
+
+ /*! Sets the shininess.
+ * \param s
+ * Shininess
+ */
+ inline void setShininess(const float s);
+
+ /* operators */
+ inline FrsMaterial& operator=(const FrsMaterial& m);
+ inline bool operator!=(const FrsMaterial& m) const;
+ inline bool operator==(const FrsMaterial& m) const;
+
+private:
+ /*! Material properties */
+ float Diffuse[4];
+ float Specular[4];
+ float Ambient[4];
+ float Emission[4];
+ float Shininess;
+};
+
+FrsMaterial::FrsMaterial()
+{
+ Ambient[0] = Ambient[1] = Ambient[2] = 0.2f;
+ Ambient[3] = 1.0f;
+
+ Diffuse[0] = Diffuse[1] = Diffuse[2] = 0.8f;
+ Diffuse[3] = 1.0f;
+
+ Emission[0] = Emission[1] = Emission[2] = 0.0f;
+ Emission[3] = 1.0f;
+
+ Specular[0] = Specular[1] = Specular[2] = 0.0f;
+ Specular[3] = 1.0f;
+
+ Shininess = 0.0f;
+}
+
+FrsMaterial::FrsMaterial(const float *iDiffuse, const float *iAmbiant, const float *iSpecular, const float *iEmission,
+ const float iShininess)
+{
+ for (int i = 0; i < 4; i++) {
+ Diffuse[i] = iDiffuse[i];
+ Specular[i] = iSpecular[i];
+ Ambient[i] = iAmbiant[i];
+ Emission[i] = iEmission[i];
+ }
+
+ Shininess = iShininess;
+}
+
+FrsMaterial::FrsMaterial(const FrsMaterial& m)
+{
+ for (int i = 0; i < 4; i++) {
+ Diffuse[i] = m.diffuse()[i];
+ Specular[i] = m.specular()[i];
+ Ambient[i] = m.ambient()[i];
+ Emission[i] = m.emission()[i];
+ }
+
+ Shininess = m.shininess();
+}
+
+void FrsMaterial::setDiffuse(const float r, const float g, const float b, const float a)
+{
+ Diffuse[0] = r;
+ Diffuse[1] = g;
+ Diffuse[2] = b;
+ Diffuse[3] = a;
+}
+
+void FrsMaterial::setSpecular(const float r, const float g, const float b, const float a)
+{
+ Specular[0] = r;
+ Specular[1] = g;
+ Specular[2] = b;
+ Specular[3] = a;
+}
+
+void FrsMaterial::setAmbient(const float r, const float g, const float b, const float a)
+{
+ Ambient[0] = r;
+ Ambient[1] = g;
+ Ambient[2] = b;
+ Ambient[3] = a;
+}
+
+void FrsMaterial::setEmission(const float r, const float g, const float b, const float a)
+{
+ Emission[0] = r;
+ Emission[1] = g;
+ Emission[2] = b;
+ Emission[3] = a;
+}
+
+void FrsMaterial::setShininess(const float s)
+{
+ Shininess = s;
+}
+
+FrsMaterial& FrsMaterial::operator=(const FrsMaterial& m)
+{
+ for (int i = 0; i < 4; i++) {
+ Diffuse[i] = m.diffuse()[i];
+ Specular[i] = m.specular()[i];
+ Ambient[i] = m.ambient()[i];
+ Emission[i] = m.emission()[i];
+ }
+
+ Shininess = m.shininess();
+ return *this;
+}
+
+bool FrsMaterial::operator!=(const FrsMaterial& m) const
+{
+ if (Shininess != m.shininess())
+ return true;
+
+ for (int i = 0; i < 4; i++) {
+ if (Diffuse[i] != m.diffuse()[i])
+ return true;
+ if (Specular[i] != m.specular()[i])
+ return true;
+ if (Ambient[i] != m.ambient()[i])
+ return true;
+ if (Emission[i] != m.emission()[i])
+ return true;
+ }
+
+ return false;
+}
+
+bool FrsMaterial::operator==(const FrsMaterial& m) const
+{
+ return (!((*this) != m));
+}
+
+#endif // __FREESTYLE_MATERIAL_H__
diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
new file mode 100644
index 00000000000..20c33713db4
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
@@ -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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
+ * \ingroup freestyle
+ * \brief A Set of indexed faces to represent a surfacic object
+ * \author Stephane Grabli
+ * \date 22/01/2002
+ */
+
+#include "IndexedFaceSet.h"
+
+IndexedFaceSet::IndexedFaceSet() : Rep()
+{
+ _Vertices = NULL;
+ _Normals = NULL;
+ _FrsMaterials = 0;
+ _TexCoords = 0;
+ _FaceEdgeMarks = 0;
+ _VSize = 0;
+ _NSize = 0;
+ _MSize = 0;
+ _TSize = 0;
+ _NumFaces = 0;
+ _NumVertexPerFace = NULL;
+ _FaceStyle = NULL;
+ _VIndices = NULL;
+ _VISize = 0;
+ _NIndices = NULL;
+ _NISize = 0;
+ _MIndices = NULL;
+ _MISize = 0;
+ _TIndices = NULL;
+ _TISize = 0;
+ _displayList = 0;
+}
+
+IndexedFaceSet::IndexedFaceSet(real *iVertices, unsigned iVSize, real *iNormals, unsigned iNSize,
+ FrsMaterial **iMaterials, unsigned iMSize, real *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)
+: Rep()
+{
+ if (1 == iCopy) {
+ _VSize = iVSize;
+ _Vertices = new real[_VSize];
+ memcpy(_Vertices, iVertices, iVSize * sizeof(real));
+
+ _NSize = iNSize;
+ _Normals = new real[_NSize];
+ memcpy(_Normals, iNormals, iNSize * sizeof(real));
+
+ _MSize = iMSize;
+ _FrsMaterials = 0;
+ if (iMaterials) {
+ _FrsMaterials = new FrsMaterial * [_MSize];
+ for (unsigned int i = 0; i < _MSize; ++i)
+ _FrsMaterials[i] = new FrsMaterial(*(iMaterials[i]));
+ }
+ _TSize = iTSize;
+ _TexCoords = 0;
+ if (_TSize) {
+ _TexCoords = new real[_TSize];
+ memcpy(_TexCoords, iTexCoords, iTSize * sizeof(real));
+ }
+
+ _NumFaces = iNumFaces;
+ _NumVertexPerFace = new unsigned[_NumFaces];
+ memcpy(_NumVertexPerFace, iNumVertexPerFace, _NumFaces * sizeof(unsigned));
+
+ _FaceStyle = new TRIANGLES_STYLE[_NumFaces];
+ memcpy(_FaceStyle, iFaceStyle, _NumFaces * sizeof(TRIANGLES_STYLE));
+
+ _FaceEdgeMarks = new FaceEdgeMark[_NumFaces];
+ memcpy(_FaceEdgeMarks, iFaceEdgeMarks, _NumFaces * sizeof(FaceEdgeMark));
+
+ _VISize = iVISize;
+ _VIndices = new unsigned[_VISize];
+ memcpy(_VIndices, iVIndices, _VISize * sizeof(unsigned));
+
+ _NISize = iNISize;
+ _NIndices = new unsigned[_NISize];
+ memcpy(_NIndices, iNIndices, _NISize * sizeof(unsigned));
+
+ _MISize = iMISize;
+ _MIndices = 0;
+ if (iMIndices) {
+ _MIndices = new unsigned[_MISize];
+ memcpy(_MIndices, iMIndices, _MISize * sizeof(unsigned));
+ }
+ _TISize = iTISize;
+ _TIndices = 0;
+ if (_TISize) {
+ _TIndices = new unsigned[_TISize];
+ memcpy(_TIndices, iTIndices, _TISize * sizeof(unsigned));
+ }
+ }
+ else {
+ _VSize = iVSize;
+ _Vertices = iVertices;
+
+ _NSize = iNSize;
+ _Normals = iNormals;
+
+ _MSize = iMSize;
+ _FrsMaterials = 0;
+ if (iMaterials)
+ _FrsMaterials = iMaterials;
+
+ _TSize = iTSize;
+ _TexCoords = iTexCoords;
+
+ _NumFaces = iNumFaces;
+ _NumVertexPerFace = iNumVertexPerFace;
+ _FaceStyle = iFaceStyle;
+ _FaceEdgeMarks = iFaceEdgeMarks;
+
+ _VISize = iVISize;
+ _VIndices = iVIndices;
+
+ _NISize = iNISize;
+ _NIndices = iNIndices;
+
+ _MISize = iMISize;
+ _MIndices = 0;
+ if (iMISize)
+ _MIndices = iMIndices;
+
+ _TISize = iTISize;
+ _TIndices = iTIndices;
+ }
+
+ _displayList = 0;
+}
+
+IndexedFaceSet::IndexedFaceSet(const IndexedFaceSet& iBrother) : Rep(iBrother)
+{
+ _VSize = iBrother.vsize();
+ _Vertices = new real[_VSize];
+ memcpy(_Vertices, iBrother.vertices(), _VSize * sizeof(real));
+
+ _NSize = iBrother.nsize();
+ _Normals = new real[_NSize];
+ memcpy(_Normals, iBrother.normals(), _NSize * sizeof(real));
+
+ _MSize = iBrother.msize();
+ if (_MSize) {
+ _FrsMaterials = new FrsMaterial * [_MSize];
+ for (unsigned int i = 0; i < _MSize; ++i) {
+ _FrsMaterials[i] = new FrsMaterial(*(iBrother._FrsMaterials[i]));
+ }
+ }
+ else {
+ _FrsMaterials = 0;
+ }
+
+ _TSize = iBrother.tsize();
+ _TexCoords = 0;
+ if (_TSize) {
+ _TexCoords = new real[_TSize];
+ memcpy(_TexCoords, iBrother.texCoords(), _TSize * sizeof(real));
+ }
+
+ _NumFaces = iBrother.numFaces();
+ _NumVertexPerFace = new unsigned[_NumFaces];
+ memcpy(_NumVertexPerFace, iBrother.numVertexPerFaces(), _NumFaces * sizeof(unsigned));
+
+ _FaceStyle = new TRIANGLES_STYLE[_NumFaces];
+ memcpy(_FaceStyle, iBrother.trianglesStyle(), _NumFaces * sizeof(TRIANGLES_STYLE));
+
+ _FaceEdgeMarks = new FaceEdgeMark[_NumFaces];
+ memcpy(_FaceEdgeMarks, iBrother.faceEdgeMarks(), _NumFaces * sizeof(FaceEdgeMark));
+
+ _VISize = iBrother.visize();
+ _VIndices = new unsigned[_VISize];
+ memcpy(_VIndices, iBrother.vindices(), _VISize * sizeof(unsigned));
+
+ _NISize = iBrother.nisize();
+ _NIndices = new unsigned[_NISize];
+ memcpy(_NIndices, iBrother.nindices(), _NISize * sizeof(unsigned));
+
+ _MISize = iBrother.misize();
+ if (_MISize) {
+ _MIndices = new unsigned[_MISize];
+ memcpy(_MIndices, iBrother.mindices(), _MISize * sizeof(unsigned));
+ }
+ else {
+ _MIndices = 0;
+ }
+
+ _TISize = iBrother.tisize();
+ _TIndices = 0;
+ if (_TISize) {
+ _TIndices = new unsigned[_TISize];
+ memcpy(_TIndices, iBrother.tindices(), _TISize * sizeof(unsigned));
+ }
+
+ _displayList = 0;
+}
+
+IndexedFaceSet::~IndexedFaceSet()
+{
+ if (NULL != _Vertices) {
+ delete[] _Vertices;
+ _Vertices = NULL;
+ }
+
+ if (NULL != _Normals) {
+ delete[] _Normals;
+ _Normals = NULL;
+ }
+
+ if (NULL != _FrsMaterials) {
+ for (unsigned int i = 0; i < _MSize; ++i)
+ delete _FrsMaterials[i];
+ delete[] _FrsMaterials;
+ _FrsMaterials = NULL;
+ }
+
+ if (NULL != _TexCoords) {
+ delete[] _TexCoords;
+ _TexCoords = NULL;
+ }
+
+ if (NULL != _NumVertexPerFace) {
+ delete[] _NumVertexPerFace;
+ _NumVertexPerFace = NULL;
+ }
+
+ if (NULL != _FaceStyle) {
+ delete[] _FaceStyle;
+ _FaceStyle = NULL;
+ }
+
+ if (NULL != _FaceEdgeMarks) {
+ delete[] _FaceEdgeMarks;
+ _FaceEdgeMarks = NULL;
+ }
+
+ if (NULL != _VIndices) {
+ delete[] _VIndices;
+ _VIndices = NULL;
+ }
+
+ if (NULL != _NIndices) {
+ delete[] _NIndices;
+ _NIndices = NULL;
+ }
+
+ if (NULL != _MIndices) {
+ delete[] _MIndices;
+ _MIndices = NULL;
+ }
+ if (NULL != _TIndices) {
+ delete[] _TIndices;
+ _TIndices = NULL;
+ }
+
+ // should find a way to deallocates the displayList
+ // glDeleteLists(GLuint list, GLSizei range)
+ _displayList = 0;
+}
+
+void IndexedFaceSet::accept(SceneVisitor& v)
+{
+ Rep::accept(v);
+ v.visitIndexedFaceSet(*this);
+}
+
+void IndexedFaceSet::ComputeBBox()
+{
+ real XMax = _Vertices[0];
+ real YMax = _Vertices[1];
+ real ZMax = _Vertices[2];
+
+ real XMin = _Vertices[0];
+ real YMin = _Vertices[1];
+ real ZMin = _Vertices[2];
+
+ // parse all the coordinates to find the Xmax, YMax, ZMax
+ real *v = _Vertices;
+
+ for (unsigned int i = 0; i < (_VSize / 3); ++i) {
+ if (*v > XMax)
+ XMax = *v;
+ if (*v < XMin)
+ XMin = *v;
+ ++v;
+
+ if (*v > YMax)
+ YMax = *v;
+ if (*v < YMin)
+ YMin = *v;
+ ++v;
+
+ if (*v > ZMax)
+ ZMax = *v;
+ if (*v < ZMin)
+ ZMin = *v;
+ ++v;
+ }
+
+ setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax)));
+}
diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
new file mode 100644
index 00000000000..c2715812eee
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
@@ -0,0 +1,322 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_INDEXED_FACE_SET_H__
+#define __FREESTYLE_INDEXED_FACE_SET_H__
+
+/** \file blender/freestyle/intern/scene_graph/IndexedFaceSet.h
+ * \ingroup freestyle
+ * \brief A Set of indexed faces to represent a surfacic object
+ * \author Stephane Grabli
+ * \date 22/01/2002
+ */
+
+#include <memory.h>
+#include <stdio.h>
+
+//! inherits from class Rep
+#include "Rep.h"
+
+#include "../system/FreestyleConfig.h"
+
+class LIB_SCENE_GRAPH_EXPORT IndexedFaceSet : public Rep
+{
+public:
+ /*! Triangles description style:*/
+ enum TRIANGLES_STYLE {
+ TRIANGLE_STRIP,
+ TRIANGLE_FAN,
+ TRIANGLES,
+ };
+
+ /*! User-specified face and edge marks for feature edge detection */
+ /* XXX Why in hel not use an enum here too? */
+ typedef unsigned char FaceEdgeMark;
+ static const FaceEdgeMark FACE_MARK = 1 << 0;
+ static const FaceEdgeMark EDGE_MARK_V1V2 = 1 << 1;
+ static const FaceEdgeMark EDGE_MARK_V2V3 = 1 << 2;
+ static const FaceEdgeMark EDGE_MARK_V3V1 = 1 << 3;
+
+ /*! Builds an empty indexed face set */
+ IndexedFaceSet();
+
+ /*! Builds an indexed face set
+ * iVertices
+ * The array of object vertices 3D coordinates (for all faces).
+ * If iCopy != 0, the array is copied; you must desallocate iVertices. Else you must not.
+ * iVSize
+ * The size of iVertices (must be a multiple of 3)
+ * iNormals
+ * The array of object normals 3D coordinates.
+ * If iCopy != 0, the array is copied; you must desallocate iNormals. Else you must not.
+ * iNSize
+ * The size of iNormals
+ * iMaterials
+ * The array of materials
+ * iMSize
+ * The size of iMaterials
+ * iTexCoords
+ * The array of texture coordinates.
+ * iTSize
+ * The size of iTexCoords (must be multiple of 2)
+ * iNumFaces
+ * The number of faces
+ * iNumVertexPerFace
+ * Array containing the number of vertices per face.
+ * iFaceStyle
+ * Array containing the description style of each faces.
+ * The style belongs to:
+ * - TRIANGLE_STRIP: the face indices describe a triangle strip
+ * - TRIANGLE_FAN : the face indices describe a triangle fan
+ * - TRIANGLES : the face indices describe single triangles
+ * If iCopy != 0, the array is copied; you must desallocate iFaceStyle. Else you must not.
+ * iVIndices,
+ * Array of vertices indices.
+ * The integers contained in this array must be multiple of 3.
+ * If iCopy != 0, the array is copied; you must desallocate iVIndices. Else you must not.
+ * iVISize
+ * The size of iVIndices.
+ * iNIndices
+ * Array of normals indices.
+ * The integers contained in this array must be multiple of 3.
+ * If iCopy != 0, the array is copied; you must desallocate iNIndices. Else you must not.
+ * iNISize
+ * The size of iNIndices
+ * iMIndices
+ * The Material indices (per vertex)
+ * iMISize
+ * The size of iMIndices
+ * iTIndices
+ * The Texture coordinates indices (per vertex). The integers contained in this array must be multiple of 2.
+ * iTISize
+ * The size of iMIndices
+ * iCopy
+ * 0 : the arrays are not copied. The pointers passed as arguments are used. IndexedFaceSet takes these
+ * 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,
+ TRIANGLES_STYLE *iFaceStyle, FaceEdgeMark *iFaceEdgeMarks, unsigned *iVIndices, unsigned iVISize,
+ unsigned *iNIndices, unsigned iNISize, unsigned *iMIndices, unsigned iMISize, unsigned *iTIndices,
+ unsigned iTISize, unsigned iCopy = 1);
+
+ /*! Builds an indexed face set from an other indexed face set */
+ IndexedFaceSet(const IndexedFaceSet& iBrother);
+
+ void swap(IndexedFaceSet& ioOther)
+ {
+ std::swap(_Vertices, ioOther._Vertices);
+ std::swap(_Normals, ioOther._Normals);
+ std::swap(_FrsMaterials, ioOther._FrsMaterials);
+ std::swap(_TexCoords, ioOther._TexCoords);
+ std::swap(_FaceEdgeMarks, ioOther._FaceEdgeMarks);
+
+ std::swap(_VSize, ioOther._VSize);
+ std::swap(_NSize, ioOther._NSize);
+ std::swap(_MSize, ioOther._MSize);
+ std::swap(_TSize, ioOther._TSize);
+
+ std::swap(_NumFaces, ioOther._NumFaces);
+ std::swap(_NumVertexPerFace, ioOther._NumVertexPerFace);
+ std::swap(_FaceStyle, ioOther._FaceStyle);
+
+ std::swap(_VIndices, ioOther._VIndices);
+ std::swap(_NIndices, ioOther._NIndices);
+ std::swap(_MIndices, ioOther._MIndices); // Material Indices
+ std::swap(_TIndices, ioOther._TIndices);
+
+ std::swap(_VISize, ioOther._VISize);
+ std::swap(_NISize, ioOther._NISize);
+ std::swap(_MISize, ioOther._MISize);
+ std::swap(_TISize, ioOther._TISize);
+
+ std::swap(_displayList, ioOther._displayList);
+
+ Rep::swap(ioOther);
+ }
+
+ IndexedFaceSet& operator=(const IndexedFaceSet& iBrother)
+ {
+ IndexedFaceSet tmp(iBrother);
+ swap(tmp);
+ return *this;
+ }
+
+ /*! Desctructor
+ * desallocates all the ressources
+ */
+ virtual ~IndexedFaceSet();
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! Compute the Bounding Box */
+ virtual void ComputeBBox();
+
+ /*! modifiers */
+ inline void setDisplayList(unsigned int index)
+ {
+ _displayList = index;
+ }
+
+ /*! Accessors */
+ virtual const real *vertices() const
+ {
+ return _Vertices;
+ }
+
+ virtual const real *normals() const
+ {
+ return _Normals;
+ }
+
+ virtual const FrsMaterial*const* frs_materials() const
+ {
+ return _FrsMaterials;
+ }
+
+ virtual const real *texCoords() const
+ {
+ return _TexCoords;
+ }
+
+ virtual const unsigned vsize() const
+ {
+ return _VSize;
+ }
+
+ virtual const unsigned nsize() const
+ {
+ return _NSize;
+ }
+
+ virtual const unsigned msize() const
+ {
+ return _MSize;
+ }
+
+ virtual const unsigned tsize() const
+ {
+ return _TSize;
+ }
+
+ virtual const unsigned numFaces() const
+ {
+ return _NumFaces;
+ }
+
+ virtual const unsigned *numVertexPerFaces() const
+ {
+ return _NumVertexPerFace;
+ }
+
+ virtual const TRIANGLES_STYLE *trianglesStyle() const
+ {
+ return _FaceStyle;
+ }
+
+ virtual const unsigned char *faceEdgeMarks() const
+ {
+ return _FaceEdgeMarks;
+ }
+
+ virtual const unsigned *vindices() const
+ {
+ return _VIndices;
+ }
+
+ virtual const unsigned *nindices() const
+ {
+ return _NIndices;
+ }
+
+ virtual const unsigned *mindices() const
+ {
+ return _MIndices;
+ }
+
+ virtual const unsigned *tindices() const
+ {
+ return _TIndices;
+ }
+
+ virtual const unsigned visize() const
+ {
+ return _VISize;
+ }
+
+ virtual const unsigned nisize() const
+ {
+ return _NISize;
+ }
+
+ virtual const unsigned misize() const
+ {
+ return _MISize;
+ }
+
+ virtual const unsigned tisize() const
+ {
+ return _TISize;
+ }
+
+ inline unsigned int displayList() const
+ {
+ return _displayList;
+ }
+
+protected:
+ real *_Vertices;
+ real *_Normals;
+ FrsMaterial **_FrsMaterials;
+ real *_TexCoords;
+
+ unsigned _VSize;
+ unsigned _NSize;
+ unsigned _MSize;
+ unsigned _TSize;
+
+ unsigned _NumFaces;
+ unsigned *_NumVertexPerFace;
+ TRIANGLES_STYLE *_FaceStyle;
+ FaceEdgeMark *_FaceEdgeMarks;
+
+ unsigned *_VIndices;
+ unsigned *_NIndices;
+ unsigned *_MIndices; // Material Indices
+ unsigned *_TIndices; // Texture coordinates Indices
+
+ unsigned _VISize;
+ unsigned _NISize;
+ unsigned _MISize;
+ unsigned _TISize;
+
+ unsigned int _displayList;
+};
+
+#endif // __FREESTYLE_INDEXED_FACE_SET_H__
diff --git a/source/blender/freestyle/intern/scene_graph/LineRep.cpp b/source/blender/freestyle/intern/scene_graph/LineRep.cpp
new file mode 100644
index 00000000000..bf442bccbc1
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/LineRep.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/scene_graph/LineRep.cpp
+ * \ingroup freestyle
+ * \brief Class to define the representation of 3D Line.
+ * \author Stephane Grabli
+ * \date 26/03/2002
+ */
+
+#include "LineRep.h"
+
+void LineRep::ComputeBBox()
+{
+ real XMax = _vertices.front()[0];
+ real YMax = _vertices.front()[1];
+ real ZMax = _vertices.front()[2];
+
+ real XMin = _vertices.front()[0];
+ real YMin = _vertices.front()[1];
+ real ZMin = _vertices.front()[2];
+
+ // parse all the coordinates to find
+ // the XMax, YMax, ZMax
+ vector<Vec3r>::iterator v;
+ for (v = _vertices.begin(); v != _vertices.end(); ++v) {
+ // X
+ if ((*v)[0] > XMax)
+ XMax = (*v)[0];
+ if ((*v)[0] < XMin)
+ XMin = (*v)[0];
+
+ // Y
+ if ((*v)[1] > YMax)
+ YMax = (*v)[1];
+ if ((*v)[1] < YMin)
+ YMin = (*v)[1];
+
+ // Z
+ if ((*v)[2] > ZMax)
+ ZMax = (*v)[2];
+ if ((*v)[2] < ZMin)
+ ZMin = (*v)[2];
+ }
+
+ setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax)));
+}
diff --git a/source/blender/freestyle/intern/scene_graph/LineRep.h b/source/blender/freestyle/intern/scene_graph/LineRep.h
new file mode 100644
index 00000000000..3d93db4835d
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/LineRep.h
@@ -0,0 +1,158 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_LINE_REP_H__
+#define __FREESTYLE_LINE_REP_H__
+
+/** \file blender/freestyle/intern/scene_graph/LineRep.h
+ * \ingroup freestyle
+ * \brief Class to define the representation of 3D Line.
+ * \author Stephane Grabli
+ * \date 26/03/2002
+ */
+
+#include <list>
+#include <vector>
+
+#include "Rep.h"
+
+#include "../system/FreestyleConfig.h"
+
+using namespace std;
+
+/*! Base class for all lines objects */
+class LIB_SCENE_GRAPH_EXPORT LineRep : public Rep
+{
+public:
+ /*! Line description style */
+ enum LINES_STYLE {
+ LINES,
+ LINE_STRIP,
+ LINE_LOOP,
+ };
+
+ inline LineRep() : Rep()
+ {
+ _width = 0.0f;
+ }
+
+ /*! Builds a single line from 2 vertices
+ * v1
+ * first vertex
+ * v2
+ * second vertex
+ */
+ inline LineRep(const Vec3r& v1, const Vec3r& v2) : Rep()
+ {
+ setStyle(LINES);
+ AddVertex(v1);
+ AddVertex(v2);
+ _width = 0.0f;
+ }
+
+ /*! Builds a line rep from a vertex chain */
+ inline LineRep(const vector<Vec3r>& vertices) : Rep()
+ {
+ _vertices = vertices;
+ setStyle(LINE_STRIP);
+ _width = 0.0f;
+ }
+
+ /*! Builds a line rep from a vertex chain */
+ inline LineRep(const list<Vec3r>& vertices) : Rep()
+ {
+ for (list<Vec3r>::const_iterator v = vertices.begin(), end = vertices.end(); v != end; ++v) {
+ _vertices.push_back(*v);
+ }
+ setStyle(LINE_STRIP);
+ _width = 0.0f;
+ }
+
+ virtual ~LineRep()
+ {
+ _vertices.clear();
+ }
+
+ /*! accessors */
+ inline const LINES_STYLE style() const
+ {
+ return _Style;
+ }
+
+ inline const vector<Vec3r>& vertices() const
+ {
+ return _vertices;
+ }
+
+ inline float width() const
+ {
+ return _width;
+ }
+
+ /*! modifiers */
+ inline void setStyle(const LINES_STYLE iStyle)
+ {
+ _Style = iStyle;
+ }
+
+ inline void AddVertex(const Vec3r& iVertex)
+ {
+ _vertices.push_back(iVertex);
+ }
+
+ inline void setVertices(const vector<Vec3r>& iVertices)
+ {
+ if (0 != _vertices.size()) {
+ _vertices.clear();
+ }
+ for (vector<Vec3r>::const_iterator v = iVertices.begin(), end = iVertices.end(); v != end; ++v) {
+ _vertices.push_back(*v);
+ }
+ }
+
+ inline void setWidth(float iWidth)
+ {
+ _width = iWidth;
+ }
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v)
+ {
+ Rep::accept(v);
+ v.visitLineRep(*this);
+ }
+
+ /*! Computes the line bounding box.*/
+ virtual void ComputeBBox();
+
+private:
+ LINES_STYLE _Style;
+ vector<Vec3r> _vertices;
+ float _width;
+};
+
+#endif // __FREESTYLE_LINE_REP_H__
diff --git a/source/blender/freestyle/intern/scene_graph/Node.h b/source/blender/freestyle/intern/scene_graph/Node.h
new file mode 100644
index 00000000000..03e9343f7e7
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/Node.h
@@ -0,0 +1,115 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_NODE_H__
+#define __FREESTYLE_NODE_H__
+
+/** \file blender/freestyle/intern/scene_graph/Node.h
+ * \ingroup freestyle
+ * \brief Abstract class for scene graph nodes. Inherits from BaseObject which defines the addRef release mechanism.
+ * \author Stephane Grabli
+ * \date 24/01/2002
+ */
+
+#include "SceneVisitor.h"
+
+#include "../system/BaseObject.h"
+#include "../system/FreestyleConfig.h"
+#include "../system/Precision.h"
+
+#include "../geometry/BBox.h"
+#include "../geometry/Geom.h"
+
+using namespace std;
+using namespace Geometry;
+
+class LIB_SCENE_GRAPH_EXPORT Node : public BaseObject
+{
+public:
+ inline Node() : BaseObject() {}
+
+ inline Node(const Node& iBrother) : BaseObject()
+ {
+ _BBox = iBrother.bbox();
+ }
+
+ virtual ~Node() {}
+
+ /*! Accept the corresponding visitor
+ * Each inherited node must overload this method
+ */
+ virtual void accept(SceneVisitor& v)
+ {
+ v.visitNode(*this);
+ }
+
+ /*! bounding box management */
+ /*! Returns the node bounding box
+ * If no bounding box exists, an empty bbox is returned
+ */
+ virtual const BBox<Vec3r>& bbox() const
+ {
+ return _BBox;
+ }
+
+ /*! Sets the Node bounding box */
+ virtual void setBBox(const BBox<Vec3r>& iBox)
+ {
+ _BBox = iBox;
+ }
+
+ /*! Makes the union of _BBox and iBox */
+ virtual void AddBBox(const BBox<Vec3r>& iBox)
+ {
+ if (iBox.empty())
+ return;
+
+ if (_BBox.empty())
+ _BBox = iBox;
+ else
+ _BBox += iBox;
+ }
+
+ /*! Updates the BBox */
+ virtual const BBox<Vec3r>& UpdateBBox()
+ {
+ return _BBox;
+ }
+
+ /*! Clears the bounding box */
+ virtual void clearBBox()
+ {
+ _BBox.clear();
+ }
+
+protected:
+
+private:
+ BBox<Vec3r> _BBox;
+};
+
+#endif // __FREESTYLE_NODE_H__
diff --git a/source/blender/freestyle/intern/scene_graph/NodeCamera.cpp b/source/blender/freestyle/intern/scene_graph/NodeCamera.cpp
new file mode 100644
index 00000000000..d8b01bf3f64
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeCamera.cpp
@@ -0,0 +1,143 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/scene_graph/NodeCamera.cpp
+ * \ingroup freestyle
+ * \brief Class to represent a light node
+ * \author Stephane Grabli
+ * \date 25/01/2002
+ */
+
+#include <math.h>
+#include <string.h> // for memcpy
+
+#include "NodeCamera.h"
+
+static void loadIdentity(double * matrix)
+{
+ int i;
+
+ // Build Identity matrix
+ for (i = 0; i < 16; ++i) {
+ double value ;
+ if ((i % 5) == 0)
+ value = 1.0;
+ else
+ value = 0;
+ matrix[i] = value;
+ }
+}
+
+NodeCamera::NodeCamera(CameraType camera_type) : camera_type_(camera_type)
+{
+ loadIdentity(modelview_matrix_);
+ loadIdentity(projection_matrix_);
+}
+
+NodeCamera::NodeCamera(const NodeCamera& iBrother) : camera_type_(iBrother.camera_type_)
+{
+ memcpy(modelview_matrix_, iBrother.modelview_matrix_, 16 * sizeof(double));
+ memcpy(projection_matrix_, iBrother.projection_matrix_, 16 * sizeof(double));
+}
+
+void NodeCamera::accept(SceneVisitor& v)
+{
+ v.visitNodeCamera(*this);
+}
+
+void NodeCamera::setModelViewMatrix(double modelview_matrix[16])
+{
+ memcpy(modelview_matrix_, modelview_matrix, 16 * sizeof(double));
+}
+
+void NodeCamera::setProjectionMatrix(double projection_matrix[16])
+{
+ memcpy(projection_matrix_, projection_matrix, 16 * sizeof(double));
+}
+
+NodeOrthographicCamera::NodeOrthographicCamera()
+: NodeCamera(NodeCamera::ORTHOGRAPHIC), left_(0), right_(0), bottom_(0), top_(0), zNear_(0), zFar_(0)
+{
+ loadIdentity(projection_matrix_);
+ loadIdentity(modelview_matrix_);
+}
+
+NodeOrthographicCamera::NodeOrthographicCamera(double left, double right, double bottom, double top,
+ double zNear, double zFar)
+: NodeCamera(NodeCamera::ORTHOGRAPHIC), left_(left), right_(right), bottom_(bottom), top_(top),
+ zNear_(zNear), zFar_(zFar)
+{
+ loadIdentity(projection_matrix_);
+
+ projection_matrix_[0] = 2.0 / (right - left);
+ projection_matrix_[3] = -(right + left) / (right - left) ;
+ projection_matrix_[5] = 2.0 / (top - bottom);
+ projection_matrix_[7] = -(top + bottom) / (top - bottom) ;
+ projection_matrix_[10] = -2.0 / (zFar - zNear);
+ projection_matrix_[11] = -(zFar + zNear) / (zFar - zNear);
+}
+
+NodeOrthographicCamera::NodeOrthographicCamera(const NodeOrthographicCamera& iBrother)
+: NodeCamera(iBrother), left_(iBrother.left_), right_(iBrother.right_), bottom_(iBrother.bottom_), top_(iBrother.top_),
+ zNear_(iBrother.zNear_), zFar_(iBrother.zFar_)
+{
+}
+
+NodePerspectiveCamera::NodePerspectiveCamera() : NodeCamera(NodeCamera::PERSPECTIVE)
+{
+}
+
+NodePerspectiveCamera::NodePerspectiveCamera(double fovy, double aspect, double zNear, double zFar)
+: NodeCamera(NodeCamera::PERSPECTIVE)
+{
+ loadIdentity(projection_matrix_);
+
+ double f = cos(fovy / 2.0) / sin(fovy / 2.0); // cotangent
+
+ projection_matrix_[0] = f / aspect;
+ projection_matrix_[5] = f;
+ projection_matrix_[10] = (zNear + zFar) / (zNear - zFar);
+ projection_matrix_[11] = (2.0 * zNear * zFar) / (zNear - zFar);
+ projection_matrix_[14] = -1.0;
+ projection_matrix_[15] = 0;
+}
+
+NodePerspectiveCamera::NodePerspectiveCamera(double left, double right, double bottom, double top,
+ double zNear, double zFar)
+: NodeCamera(NodeCamera::PERSPECTIVE)
+{
+ loadIdentity(projection_matrix_);
+
+ projection_matrix_[0] = (2.0 * zNear) / (right - left);
+ projection_matrix_[2] = (right + left) / (right - left);
+ projection_matrix_[5] = (2.0 * zNear) / (top - bottom);
+ projection_matrix_[6] = (top + bottom) / (top - bottom);
+ projection_matrix_[10] = -(zFar + zNear) / (zFar - zNear);
+ projection_matrix_[11] = -(2.0 * zFar * zNear) / (zFar - zNear);
+ projection_matrix_[14] = -1.0;
+ projection_matrix_[15] = 0;
+}
diff --git a/source/blender/freestyle/intern/scene_graph/NodeCamera.h b/source/blender/freestyle/intern/scene_graph/NodeCamera.h
new file mode 100644
index 00000000000..f7141a72a51
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeCamera.h
@@ -0,0 +1,216 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_NODE_CAMERA_H__
+#define __FREESTYLE_NODE_CAMERA_H__
+
+/** \file blender/freestyle/intern/scene_graph/NodeCamera.h
+ * \ingroup freestyle
+ * \brief Class to represent a light node
+ * \author Stephane Grabli
+ * \date 25/01/2002
+ */
+
+#include "Node.h"
+
+#include "../geometry/Geom.h"
+
+#include "../system/FreestyleConfig.h"
+
+using namespace Geometry;
+
+class NodeOrthographicCamera;
+
+class NodePerspectiveCamera;
+
+class LIB_SCENE_GRAPH_EXPORT NodeCamera : public Node
+{
+public:
+ typedef enum {
+ PERSPECTIVE,
+ ORTHOGRAPHIC,
+ GENERIC,
+ } CameraType;
+
+ /*! Default matrices: Identity for both projection and modelview. */
+ NodeCamera(CameraType camera_type = GENERIC);
+ NodeCamera(const NodeCamera& iBrother);
+
+ virtual ~NodeCamera() {}
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! Matrix is copied */
+ void setModelViewMatrix(double modelview_matrix[16]);
+
+ /*! Matrix is copied */
+ void setProjectionMatrix(double projection_matrix[16]);
+
+ double * modelViewMatrix()
+ {
+ return modelview_matrix_;
+ }
+
+ double * projectionMatrix()
+ {
+ return projection_matrix_;
+ }
+
+protected:
+ // row major right handed matrix
+ double modelview_matrix_[16];
+ // row major right handed matrix
+ double projection_matrix_[16];
+
+ CameraType camera_type_;
+};
+
+class LIB_SCENE_GRAPH_EXPORT NodeOrthographicCamera : public NodeCamera
+{
+public:
+ NodeOrthographicCamera();
+
+ /*! Builds a parallel projection matrix a la glOrtho.
+ * A 0 0 tx
+ * 0 B 0 ty
+ * 0 0 C tz
+ * 0 0 0 1
+ *
+ * where
+ * A = 2 / (right - left)
+ * B = 2 / (top - bottom)
+ * C = -2 / (far - near)
+ * tx = -(right + left) / (right - left)
+ * ty = -(top + bottom) / (top - bottom)
+ * tz = -(zFar + zNear) / (zFar - zNear)
+ */
+ NodeOrthographicCamera(double left, double right, double bottom, double top, double zNear, double zFar);
+
+ double left() const
+ {
+ return left_;
+ }
+
+ double right() const
+ {
+ return right_;
+ }
+
+ double bottom() const
+ {
+ return bottom_;
+ }
+
+ double top() const
+ {
+ return top_;
+ }
+
+ double zNear() const
+ {
+ return zNear_;
+ }
+
+ double zFar() const
+ {
+ return zFar_;
+ }
+
+ NodeOrthographicCamera(const NodeOrthographicCamera& iBrother);
+
+private:
+ double left_;
+ double right_;
+ double bottom_;
+ double top_;
+ double zNear_;
+ double zFar_;
+};
+
+class LIB_SCENE_GRAPH_EXPORT NodePerspectiveCamera : public NodeCamera
+{
+public:
+ NodePerspectiveCamera();
+
+ /*! Builds a perspective projection matrix a la gluPerspective.
+ * Given f defined as follows:
+ * fovy
+ * f = cotangent(____)
+ * 2
+ * The generated matrix is
+ * ( f )
+ * | ______ 0 0 0 |
+ * | aspect |
+ * | |
+ * | 0 f 0 0 |
+ * | |
+ * | zNear+zFar 2*zNear*zFar |
+ * | 0 0 __________ ____________ |
+ * | zNear-zFar zNear-zFar |
+ * | |
+ * ( 0 0 -1 0 )
+ * \param fovy
+ * Field of View specified in radians.
+ */
+ NodePerspectiveCamera(double fovy, double aspect, double zNear, double zFar);
+
+ /*! Builds a perspective projection matrix a la glFrustum.
+ * ( 2*zNear )
+ * | __________ 0 A 0 |
+ * | right-left |
+ * | |
+ * | 2*zNear |
+ * | 0 __________ B 0 |
+ * | top-bottom |
+ * | |
+ * | 0 0 C D |
+ * | |
+ * | 0 0 -1 0 |
+ * ( )
+ *
+ * right+left
+ * A = __________
+ * right-left
+ *
+ * top+bottom
+ * B = __________
+ * top-bottom
+ *
+ * zFar+zNear
+ * C = - __________
+ * zFar-zNear
+ *
+ * 2*zFar*zNear
+ * D = - ____________
+ * zFar-zNear
+ */
+ NodePerspectiveCamera(double left, double right, double bottom, double top, double zNear, double zFar);
+};
+
+
+#endif // __FREESTYLE_NODE_CAMERA_H__
diff --git a/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.cpp b/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.cpp
new file mode 100644
index 00000000000..fed589b17c5
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/scene_graph/NodeDrawingStyle.cpp
+ * \ingroup freestyle
+ * \brief Class to define a Drawing Style to be applied to the underlying children. Inherits from NodeGroup.
+ * \author Stephane Grabli
+ * \date 06/02/2002
+ */
+
+#include "NodeDrawingStyle.h"
+
+void NodeDrawingStyle::accept(SceneVisitor& v)
+{
+ v.visitNodeDrawingStyle(*this);
+
+ v.visitNodeDrawingStyleBefore(*this);
+ v.visitDrawingStyle(_DrawingStyle);
+ for (vector<Node*>::iterator node = _Children.begin(), end = _Children.end(); node != end; ++node)
+ (*node)->accept(v);
+ v.visitNodeDrawingStyleAfter(*this);
+}
diff --git a/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.h b/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.h
new file mode 100644
index 00000000000..29a05290df1
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_NODE_DRAWING_STYLE_H__
+#define __FREESTYLE_NODE_DRAWING_STYLE_H__
+
+/** \file blender/freestyle/intern/scene_graph/NodeDrawingStyle.h
+ * \ingroup freestyle
+ * \brief Class to define a Drawing Style to be applied to the underlying children. Inherits from NodeGroup.
+ * \author Stephane Grabli
+ * \date 06/02/2002
+ */
+
+#include "DrawingStyle.h"
+#include "NodeGroup.h"
+
+#include "../system/FreestyleConfig.h"
+
+class LIB_SCENE_GRAPH_EXPORT NodeDrawingStyle : public NodeGroup
+{
+public:
+ inline NodeDrawingStyle() : NodeGroup() {}
+ virtual ~NodeDrawingStyle() {}
+
+ inline const DrawingStyle& drawingStyle() const
+ {
+ return _DrawingStyle;
+ }
+
+ inline void setDrawingStyle(const DrawingStyle& iDrawingStyle)
+ {
+ _DrawingStyle = iDrawingStyle;
+ }
+
+ /*! Sets the style. Must be one of FILLED, LINES, POINTS, INVISIBLE. */
+ inline void setStyle(const DrawingStyle::STYLE iStyle)
+ {
+ _DrawingStyle.setStyle(iStyle);
+ }
+
+ /*! Sets the line width in the LINES style case */
+ inline void setLineWidth(const float iLineWidth)
+ {
+ _DrawingStyle.setLineWidth(iLineWidth);
+ }
+
+ /*! Sets the Point size in the POINTS style case */
+ inline void setPointSize(const float iPointSize)
+ {
+ _DrawingStyle.setPointSize(iPointSize);
+ }
+
+ /*! Enables or disables the lighting. TRUE = enable */
+ inline void setLightingEnabled(const bool iEnableLighting)
+ {
+ _DrawingStyle.setLightingEnabled(iEnableLighting);
+ }
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! accessors */
+ inline DrawingStyle::STYLE style() const
+ {
+ return _DrawingStyle.style();
+ }
+
+ inline float lineWidth() const
+ {
+ return _DrawingStyle.lineWidth();
+ }
+
+ inline float pointSize() const
+ {
+ return _DrawingStyle.pointSize();
+ }
+
+ inline bool lightingEnabled() const
+ {
+ return _DrawingStyle.lightingEnabled();
+ }
+
+private:
+ DrawingStyle _DrawingStyle;
+};
+
+#endif // __FREESTYLE_NODE_DRAWING_STYLE_H__
diff --git a/source/blender/freestyle/intern/scene_graph/NodeGroup.cpp b/source/blender/freestyle/intern/scene_graph/NodeGroup.cpp
new file mode 100644
index 00000000000..3ac9cbbcbdc
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeGroup.cpp
@@ -0,0 +1,126 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/scene_graph/NodeGroup.cpp
+ * \ingroup freestyle
+ * \brief Class to represent a group node. This node can contains several children.
+ * \brief It also contains a transform matrix indicating the transform state of the underlying children.
+ * \author Stephane Grabli
+ * \date 24/01/2002
+ */
+
+#include "NodeGroup.h"
+
+void NodeGroup::AddChild(Node *iChild)
+{
+ if (NULL == iChild)
+ return;
+
+ _Children.push_back(iChild);
+ iChild->addRef();
+}
+
+int NodeGroup::destroy()
+{
+ /*! Node::destroy makes a release on the object and then returns the reference counter.
+ * If the reference counter is equal to 0, that means that nobody else is linking this node group and
+ * that we can destroy the whole underlying tree.
+ * Else, one or several Node link this node group, and we only returns the reference counter
+ * decremented by Node::destroy();
+ */
+ int refThis = Node::destroy();
+
+ // if refThis != 0, we can't destroy the tree
+ if (0 != refThis)
+ return refThis;
+
+ // If we are here, that means that nobody else needs our NodeGroup and we can destroy it.
+ int refCount = 0;
+ vector<Node *>::iterator node;
+
+ for (node = _Children.begin(); node != _Children.end(); ++node) {
+ refCount = (*node)->destroy();
+ if (0 == refCount)
+ delete (*node);
+ }
+
+ _Children.clear();
+
+ return refThis;
+}
+
+void NodeGroup::accept(SceneVisitor& v)
+{
+ v.visitNodeGroup(*this);
+
+ v.visitNodeGroupBefore(*this);
+ for (vector<Node *>::iterator node = _Children.begin(), end = _Children.end(); node != end; ++node)
+ (*node)->accept(v);
+ v.visitNodeGroupAfter(*this);
+}
+
+void NodeGroup::DetachChildren()
+{
+ vector<Node *>::iterator node;
+
+ for (node = _Children.begin(); node != _Children.end(); ++node) {
+ (*node)->release();
+ }
+
+ _Children.clear();
+}
+
+void NodeGroup::DetachChild(Node *iChild)
+{
+ /* int found = 0; */ /* UNUSED */
+ vector<Node*>::iterator node;
+
+ for (node = _Children.begin(); node != _Children.end(); ++node) {
+ if ((*node) == iChild) {
+ (*node)->release();
+ _Children.erase(node);
+ /* found = 1; */ /* UNUSED */
+ break;
+ }
+ }
+}
+
+void NodeGroup::RetrieveChildren(vector<Node*>& oNodes)
+{
+ oNodes = _Children;
+}
+
+const BBox<Vec3r>& NodeGroup::UpdateBBox()
+{
+ vector<Node *>::iterator node;
+ clearBBox();
+ for (node = _Children.begin(); node != _Children.end(); ++node) {
+ AddBBox((*node)->UpdateBBox());
+ }
+
+ return Node::UpdateBBox();
+}
diff --git a/source/blender/freestyle/intern/scene_graph/NodeGroup.h b/source/blender/freestyle/intern/scene_graph/NodeGroup.h
new file mode 100644
index 00000000000..aed9562903e
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeGroup.h
@@ -0,0 +1,89 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_NODE_GROUP_H__
+#define __FREESTYLE_NODE_GROUP_H__
+
+/** \file blender/freestyle/intern/scene_graph/NodeGroup.h
+ * \ingroup freestyle
+ * \brief Class to represent a group node. This node can contains several children.
+ * \brief It also contains a transform matrix indicating the transform state of the underlying children.
+ * \author Stephane Grabli
+ * \date 24/01/2002
+ */
+
+#include <vector>
+
+#include "Node.h"
+
+#include "../system/FreestyleConfig.h"
+
+using namespace std;
+
+class LIB_SCENE_GRAPH_EXPORT NodeGroup : public Node
+{
+public:
+ inline NodeGroup(): Node() {}
+ virtual ~NodeGroup() {}
+
+ /*! Adds a child. Makes a addRef on the iChild reference counter */
+ virtual void AddChild(Node *iChild);
+
+ /*! destroys all the underlying nodes
+ * Returns the reference counter after having done a release()
+ */
+ virtual int destroy();
+
+ /*! Detaches all the children */
+ virtual void DetachChildren();
+
+ /*! Detached the sepcified child */
+ virtual void DetachChild(Node *iChild);
+
+ /*! Retrieve children */
+ virtual void RetrieveChildren(vector<Node*>& oNodes);
+
+ /*! Renders every children */
+// virtual void Render(Renderer *iRenderer);
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! Updates the BBox */
+ virtual const BBox<Vec3r>& UpdateBBox();
+
+ /*! Returns the number of children */
+ virtual int numberOfChildren()
+ {
+ return _Children.size();
+ }
+
+protected:
+ vector<Node*> _Children;
+};
+
+#endif // __FREESTYLE_NODE_GROUP_H__
diff --git a/source/blender/freestyle/intern/scene_graph/NodeLight.cpp b/source/blender/freestyle/intern/scene_graph/NodeLight.cpp
new file mode 100644
index 00000000000..f410d2da18e
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeLight.cpp
@@ -0,0 +1,86 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/scene_graph/NodeLight.cpp
+ * \ingroup freestyle
+ * \brief Class to represent a light node
+ * \author Stephane Grabli
+ * \date 25/01/2002
+ */
+
+#include "NodeLight.h"
+
+int NodeLight::numberOfLights = 0;
+
+NodeLight::NodeLight() : Node()
+{
+ if (numberOfLights > 7) {
+ _number = 7;
+ }
+ else {
+ _number = numberOfLights;
+ numberOfLights++;
+ }
+
+ Ambient[0] = Ambient[1] = Ambient[2] = 0.0f;
+ Ambient[3] = 1.0f;
+
+ for (int i = 0; i < 4; i++) {
+ Diffuse[i] = 1.0f;
+ Specular[i] = 1.0f;
+ }
+
+ Position[0] = Position[1] = Position[3] = 0.0f;
+ Position[2] = 1.0f;
+
+ on = true;
+}
+
+NodeLight::NodeLight(NodeLight& iBrother) : Node(iBrother)
+{
+ if (numberOfLights > 7) {
+ _number = 7;
+ }
+ else {
+ _number = numberOfLights;
+ numberOfLights++;
+ }
+
+ for (int i = 0; i < 4; i++) {
+ Ambient[i] = iBrother.ambient()[i];
+ Diffuse[i] = iBrother.diffuse()[i];
+ Specular[i] = iBrother.specular()[i];
+ Position[i] = iBrother.position()[i];
+ }
+
+ on = iBrother.isOn();
+}
+
+void NodeLight::accept(SceneVisitor& v)
+{
+ v.visitNodeLight(*this);
+}
diff --git a/source/blender/freestyle/intern/scene_graph/NodeLight.h b/source/blender/freestyle/intern/scene_graph/NodeLight.h
new file mode 100644
index 00000000000..49484d8b9b3
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeLight.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_NODE_LIGHT_H__
+#define __FREESTYLE_NODE_LIGHT_H__
+
+/** \file blender/freestyle/intern/scene_graph/NodeLight.h
+ * \ingroup freestyle
+ * \brief Class to represent a light node
+ * \author Stephane Grabli
+ * \date 25/01/2002
+ */
+
+#include "Node.h"
+
+#include "../geometry/Geom.h"
+
+#include "../system/FreestyleConfig.h"
+
+using namespace Geometry;
+
+class LIB_SCENE_GRAPH_EXPORT NodeLight : public Node
+{
+public:
+ NodeLight();
+ NodeLight(NodeLight& iBrother);
+
+ virtual ~NodeLight() {}
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! Accessors for the light properties */
+ inline const float * ambient() const
+ {
+ return Ambient;
+ }
+
+ inline const float * diffuse() const
+ {
+ return Diffuse;
+ }
+
+ inline const float * specular() const
+ {
+ return Specular;
+ }
+
+ inline const float * position() const
+ {
+ return Position;
+ }
+
+ inline bool isOn() const
+ {
+ return on;
+ }
+
+ inline int number() const
+ {
+ return _number;
+ }
+
+private:
+ // Data members
+ // ============
+
+ /*! on=true, the light is on */
+ bool on;
+
+ /*! The color definition */
+ float Ambient[4];
+ float Diffuse[4];
+ float Specular[4];
+
+ /*! Light position. if w = 0, the light is placed at infinite. */
+ float Position[4];
+
+ /*! used to manage the number of lights */
+ /*! numberOfLights
+ * the number of lights in the scene.
+ * Initially, 0.
+ */
+ static int numberOfLights;
+ /*! The current lignt number */
+ int _number;
+};
+
+#endif // __FREESTYLE_NODE_LIGHT_H__
diff --git a/source/blender/freestyle/intern/scene_graph/NodeShape.cpp b/source/blender/freestyle/intern/scene_graph/NodeShape.cpp
new file mode 100644
index 00000000000..b1593c9f43b
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeShape.cpp
@@ -0,0 +1,63 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/scene_graph/NodeShape.cpp
+ * \ingroup freestyle
+ * \brief Class to build a shape node. It contains a Rep, which is the shape geometry
+ * \author Stephane Grabli
+ * \date 25/01/2002
+ */
+
+#include "NodeShape.h"
+
+NodeShape::~NodeShape()
+{
+ vector<Rep *>::iterator rep;
+
+ if (0 != _Shapes.size()) {
+ for (rep = _Shapes.begin(); rep != _Shapes.end(); ++rep) {
+ int refCount = (*rep)->destroy();
+ if (0 == refCount)
+ delete (*rep);
+ }
+
+ _Shapes.clear();
+ }
+}
+
+void NodeShape::accept(SceneVisitor& v)
+{
+ v.visitNodeShape(*this);
+
+ v.visitFrsMaterial(_FrsMaterial);
+
+ v.visitNodeShapeBefore(*this);
+ vector<Rep *>::iterator rep;
+ for (rep = _Shapes.begin(); rep != _Shapes.end(); ++rep)
+ (*rep)->accept(v);
+ v.visitNodeShapeAfter(*this);
+}
diff --git a/source/blender/freestyle/intern/scene_graph/NodeShape.h b/source/blender/freestyle/intern/scene_graph/NodeShape.h
new file mode 100644
index 00000000000..046d8b0e392
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeShape.h
@@ -0,0 +1,103 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_NODE_SHAPE_H__
+#define __FREESTYLE_NODE_SHAPE_H__
+
+/** \file blender/freestyle/intern/scene_graph/NodeShape.h
+ * \ingroup freestyle
+ * \brief Class to build a shape node. It contains a Rep, which is the shape geometry
+ * \author Stephane Grabli
+ * \date 25/01/2002
+ */
+
+#include <vector>
+
+#include "../geometry/BBox.h"
+#include "../geometry/Geom.h"
+
+#include "../system/FreestyleConfig.h"
+
+#include "FrsMaterial.h"
+#include "Node.h"
+#include "Rep.h"
+
+using namespace std;
+using namespace Geometry;
+
+class LIB_SCENE_GRAPH_EXPORT NodeShape : public Node
+{
+public:
+ inline NodeShape() : Node() {}
+
+ virtual ~NodeShape();
+
+ /*! Adds a Rep to the _Shapes list
+ * The delete of the rep is done when it is not used any more by the Scene Manager.
+ * So, it must not be deleted by the caller
+ */
+ virtual void AddRep(Rep *iRep)
+ {
+ if (NULL == iRep)
+ return;
+ _Shapes.push_back(iRep);
+ iRep->addRef();
+
+ // updates bbox:
+ AddBBox(iRep->bbox());
+ }
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! Sets the shape material */
+ inline void setFrsMaterial(const FrsMaterial& iMaterial)
+ {
+ _FrsMaterial = iMaterial;
+ }
+
+ /*! accessors */
+ /*! returns the shape's material */
+ inline FrsMaterial& frs_material()
+ {
+ return _FrsMaterial;
+ }
+
+ inline const vector<Rep*>& shapes()
+ {
+ return _Shapes;
+ }
+
+private:
+ /*! list of shapes */
+ vector<Rep*> _Shapes;
+
+ /*! Shape Material */
+ FrsMaterial _FrsMaterial;
+};
+
+#endif // __FREESTYLE_NODE_SHAPE_H__
diff --git a/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp b/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp
new file mode 100644
index 00000000000..aa01200a4d2
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp
@@ -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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/scene_graph/NodeTransform.cpp
+ * \ingroup freestyle
+ * \brief Class to represent a transform node. A Transform node contains one or several children,
+ * \brief all affected by the transformation.
+ * \author Stephane Grabli
+ * \date 06/02/2002
+ */
+
+#include "NodeTransform.h"
+
+#include "../system/FreestyleConfig.h"
+
+void NodeTransform::Translate(real x, real y, real z)
+{
+ _Matrix(0, 3) += x;
+ _Matrix(1, 3) += y;
+ _Matrix(2, 3) += z;
+}
+
+void NodeTransform::Rotate(real iAngle, real x, real y, real z)
+{
+ //Normalize the x,y,z vector;
+ real norm = (real)sqrt(x * x + y * y + z * z);
+ if (0 == norm)
+ return;
+
+ x /= norm;
+ y /= norm;
+ z /= norm;
+
+ /* find the corresponding matrix with the Rodrigues formula:
+ * R = I + sin(iAngle)*Ntilda + (1-cos(iAngle))*Ntilda*Ntilda
+ */
+ Matrix33r Ntilda;
+ Ntilda(0, 0) = Ntilda(1, 1) = Ntilda(2, 2) = 0.0f;
+ Ntilda(0, 1) = -z;
+ Ntilda(0, 2) = y;
+ Ntilda(1, 0) = z;
+ Ntilda(1, 2) = -x;
+ Ntilda(2, 0) = -y;
+ Ntilda(2, 1) = x;
+
+ const Matrix33r Ntilda2(Ntilda * Ntilda);
+
+
+ const real sinAngle = (real)sin((iAngle / 180.0f) * M_PI);
+ const real cosAngle = (real)cos((iAngle / 180.0f) * M_PI);
+
+ Matrix33r NS(Ntilda * sinAngle);
+ Matrix33r NC(Ntilda2 * (1.0f - cosAngle));
+ Matrix33r R;
+ R = Matrix33r::identity();
+ R += NS + NC;
+
+ // R4 is the corresponding 4x4 matrix
+ Matrix44r R4;
+ R4 = Matrix44r::identity();
+
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++)
+ R4(i, j) = R(i, j);
+ }
+
+ // Finally, we multiply our current matrix by R4:
+ Matrix44r mat_tmp(_Matrix);
+ _Matrix = mat_tmp * R4;
+}
+
+void NodeTransform::Scale(real x, real y, real z)
+{
+ _Matrix(0, 0) *= x;
+ _Matrix(1, 1) *= y;
+ _Matrix(2, 2) *= z;
+
+ _Scaled = true;
+}
+
+void NodeTransform::MultiplyMatrix(const Matrix44r &iMatrix)
+{
+ Matrix44r mat_tmp(_Matrix);
+ _Matrix = mat_tmp * iMatrix;
+}
+
+void NodeTransform::setMatrix(const Matrix44r &iMatrix)
+{
+ _Matrix = iMatrix;
+ if (isScaled(iMatrix))
+ _Scaled = true;
+}
+
+void NodeTransform::accept(SceneVisitor& v)
+{
+ v.visitNodeTransform(*this);
+
+ v.visitNodeTransformBefore(*this);
+ for (vector<Node *>::iterator node = _Children.begin(), end = _Children.end(); node != end; ++node)
+ (*node)->accept(v);
+ v.visitNodeTransformAfter(*this);
+}
+
+void NodeTransform::AddBBox(const BBox<Vec3r>& iBBox)
+{
+ Vec3r oldMin(iBBox.getMin());
+ Vec3r oldMax(iBBox.getMax());
+
+ // compute the 8 corners of the bbox
+ HVec3r box[8];
+ box[0] = HVec3r(iBBox.getMin());
+ box[1] = HVec3r(oldMax[0], oldMin[1], oldMin[2]);
+ box[2] = HVec3r(oldMax[0], oldMax[1], oldMin[2]);
+ box[3] = HVec3r(oldMin[0], oldMax[1], oldMin[2]);
+ box[4] = HVec3r(oldMin[0], oldMin[1], oldMax[2]);
+ box[5] = HVec3r(oldMax[0], oldMin[1], oldMax[2]);
+ box[6] = HVec3r(oldMax[0], oldMax[1], oldMax[2]);
+ box[7] = HVec3r(oldMin[0], oldMax[1], oldMax[2]);
+
+ // Computes the transform iBBox
+ HVec3r tbox[8];
+ unsigned int i;
+ for (i = 0; i < 8; i++)
+ tbox[i] = _Matrix * box[i];
+
+ Vec3r newMin(tbox[0]);
+ Vec3r newMax(tbox[0]);
+ for (i = 0; i < 8; i++) {
+ for (unsigned int j = 0; j < 3; j++) {
+ if (newMin[j] > tbox[i][j])
+ newMin[j] = tbox[i][j];
+ if (newMax[j] < tbox[i][j])
+ newMax[j] = tbox[i][j];
+ }
+ }
+
+ BBox<Vec3r> transformBox(newMin, newMax);
+
+ Node::AddBBox(transformBox);
+}
+
+bool NodeTransform::isScaled(const Matrix44r &M)
+{
+ for (unsigned int j = 0; j < 3; j++) {
+ real norm = 0;
+ for (unsigned int i = 0; i < 3; i++) {
+ norm += M(i, j) * M(i, j);
+ }
+ if ((norm > 1.01) || (norm < 0.99))
+ return true;
+ }
+
+ return false;
+}
diff --git a/source/blender/freestyle/intern/scene_graph/NodeTransform.h b/source/blender/freestyle/intern/scene_graph/NodeTransform.h
new file mode 100644
index 00000000000..e98045989d3
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeTransform.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_NODE_TRANSFORM_H__
+#define __FREESTYLE_NODE_TRANSFORM_H__
+
+/** \file blender/freestyle/intern/scene_graph/NodeTransform.h
+ * \ingroup freestyle
+ * \brief Class to represent a transform node. A Transform node contains one or several children,
+ * \brief all affected by the transformation.
+ * \author Stephane Grabli
+ * \date 06/02/2002
+ */
+
+#include "NodeGroup.h"
+
+#include "../geometry/Geom.h"
+
+#include "../system/FreestyleConfig.h"
+
+using namespace Geometry;
+
+class LIB_SCENE_GRAPH_EXPORT NodeTransform : public NodeGroup
+{
+public:
+ inline NodeTransform() : NodeGroup()
+ {
+ _Matrix = Matrix44r::identity();
+ _Scaled = false;
+ }
+
+ virtual ~NodeTransform() {}
+
+ /*! multiplys the current matrix by the x, y, z translation matrix. */
+ void Translate(real x, real y, real z);
+
+ /*! multiplys the current matrix by a rotation matrix
+ * iAngle
+ * The rotation angle
+ * x, y, z
+ * The rotation axis
+ */
+ void Rotate(real iAngle, real x, real y, real z);
+
+ /*! multiplys the current matrix by a scaling matrix.
+ * x, y, z
+ * The scaling coefficients with respect to the x,y,z axis
+ */
+ void Scale(real x, real y, real z);
+
+ /*! Multiplys the current matrix by iMatrix */
+ void MultiplyMatrix(const Matrix44r &iMatrix);
+
+ /*! Sets the current matrix to iMatrix */
+ void setMatrix(const Matrix44r &iMatrix);
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! Overloads the Node::AddBBox in order to take care about the transformation */
+ virtual void AddBBox(const BBox<Vec3r>& iBBox);
+
+ /*! Checks whether a matrix contains a scale factor or not.
+ * Returns true if yes.
+ * M
+ * The matrix to check
+ */
+ bool isScaled(const Matrix44r &M);
+
+ /*! accessors */
+ inline const Matrix44r& matrix() const
+ {
+ return _Matrix;
+ }
+
+ inline bool scaled() const
+ {
+ return _Scaled;
+ }
+
+private:
+ Matrix44r _Matrix;
+ bool _Scaled;
+};
+
+#endif // __FREESTYLE_NODE_TRANSFORM_H__
diff --git a/source/blender/freestyle/intern/scene_graph/OrientedLineRep.cpp b/source/blender/freestyle/intern/scene_graph/OrientedLineRep.cpp
new file mode 100644
index 00000000000..8b29c0256ff
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/OrientedLineRep.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/scene_graph/OrientedLineRep.cpp
+ * \ingroup freestyle
+ * \brief Class to display an oriented line representation.
+ * \author Stephane Grabli
+ * \date 24/10/2002
+ */
+
+#include "OrientedLineRep.h"
+
+#include "../system/BaseObject.h"
+
+void OrientedLineRep::accept(SceneVisitor& v)
+{
+ Rep::accept(v);
+ if (!frs_material())
+ v.visitOrientedLineRep(*this);
+ else
+ v.visitLineRep(*this);
+}
diff --git a/source/blender/freestyle/intern/scene_graph/OrientedLineRep.h b/source/blender/freestyle/intern/scene_graph/OrientedLineRep.h
new file mode 100644
index 00000000000..28b620f5c80
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/OrientedLineRep.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_ORIENTED_LINE_REP_H__
+#define __FREESTYLE_ORIENTED_LINE_REP_H__
+
+/** \file blender/freestyle/intern/scene_graph/OrientedLineRep.h
+ * \ingroup freestyle
+ * \brief Class to display an oriented line representation.
+ * \author Stephane Grabli
+ * \date 24/10/2002
+ */
+
+#include "LineRep.h"
+
+#include "../system/FreestyleConfig.h"
+
+class LIB_SCENE_GRAPH_EXPORT OrientedLineRep : public LineRep
+{
+public:
+ OrientedLineRep() : LineRep() {}
+ /*! Builds a single line from 2 vertices
+ * v1
+ * first vertex
+ * v2
+ * second vertex
+ */
+ inline OrientedLineRep(const Vec3r& v1, const Vec3r& v2) : LineRep(v1, v2) {}
+
+ /*! Builds a line rep from a vertex chain */
+ inline OrientedLineRep(const vector<Vec3r>& vertices) : LineRep(vertices) {}
+
+ /*! Builds a line rep from a vertex chain */
+ inline OrientedLineRep(const list<Vec3r>& vertices) : LineRep(vertices) {}
+
+ virtual ~OrientedLineRep() {}
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+};
+
+#endif // __FREESTYLE_ORIENTED_LINE_REP_H__
diff --git a/source/gameengine/Physics/common/PHY_IMotionState.cpp b/source/blender/freestyle/intern/scene_graph/Rep.cpp
index 1953e748bc0..0319a617a68 100644
--- a/source/gameengine/Physics/common/PHY_IMotionState.cpp
+++ b/source/blender/freestyle/intern/scene_graph/Rep.cpp
@@ -15,7 +15,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
* All rights reserved.
*
* The Original Code is: all of this file.
@@ -25,13 +25,11 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file gameengine/Physics/common/PHY_IMotionState.cpp
- * \ingroup phys
+/** \file blender/freestyle/intern/scene_graph/Rep.cpp
+ * \ingroup freestyle
+ * \brief Base class for all shapes. Inherits from BasicObjects for references counter management (addRef, release).
+ * \author Stephane Grabli
+ * \date 25/01/2002
*/
-#include "PHY_IMotionState.h"
-
-PHY_IMotionState::~PHY_IMotionState()
-{
-
-}
+#include "Rep.h"
diff --git a/source/blender/freestyle/intern/scene_graph/Rep.h b/source/blender/freestyle/intern/scene_graph/Rep.h
new file mode 100644
index 00000000000..055ec0674f8
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/Rep.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_REP_H__
+#define __FREESTYLE_REP_H__
+
+/** \file blender/freestyle/intern/scene_graph/Rep.h
+ * \ingroup freestyle
+ * \brief Base class for all shapes. Inherits from BasicObjects for references counter management (addRef, release).
+ * \author Stephane Grabli
+ * \date 25/01/2002
+ */
+
+#include "FrsMaterial.h"
+#include "SceneVisitor.h"
+
+#include "../geometry/BBox.h"
+#include "../geometry/Geom.h"
+
+#include "../system/BaseObject.h"
+#include "../system/Id.h"
+#include "../system/Precision.h"
+
+using namespace Geometry;
+
+class LIB_SCENE_GRAPH_EXPORT Rep : public BaseObject
+{
+public:
+ inline Rep() : BaseObject()
+ {
+ _Id = 0;
+ _FrsMaterial = 0;
+ }
+
+ inline Rep(const Rep& iBrother) : BaseObject()
+ {
+ _Id = iBrother._Id;
+ _Name = iBrother._Name;
+ if (0 == iBrother._FrsMaterial)
+ _FrsMaterial = 0;
+ else
+ _FrsMaterial = new FrsMaterial(*(iBrother._FrsMaterial));
+
+ _BBox = iBrother.bbox();
+ }
+
+ inline void swap(Rep& ioOther)
+ {
+ std::swap(_BBox, ioOther._BBox);
+ std::swap(_Id, ioOther._Id);
+ std::swap(_Name, ioOther._Name);
+ std::swap(_FrsMaterial, ioOther._FrsMaterial);
+ }
+
+ Rep& operator=(const Rep& iBrother)
+ {
+ if (&iBrother != this) {
+ _Id = iBrother._Id;
+ _Name = iBrother._Name;
+ if (0 == iBrother._FrsMaterial) {
+ _FrsMaterial = 0;
+ }
+ else {
+ if (_FrsMaterial == 0) {
+ _FrsMaterial = new FrsMaterial(*iBrother._FrsMaterial);
+ }
+ else {
+ (*_FrsMaterial) = (*(iBrother._FrsMaterial));
+ }
+ _BBox = iBrother.bbox();
+ }
+ }
+ return *this;
+ }
+
+ virtual ~Rep()
+ {
+ if (0 != _FrsMaterial) {
+ delete _FrsMaterial;
+ _FrsMaterial = 0;
+ }
+ }
+
+ /*! Accept the corresponding visitor
+ * Must be overload by inherited classes
+ */
+ virtual void accept(SceneVisitor& v)
+ {
+ if (_FrsMaterial)
+ v.visitFrsMaterial(*_FrsMaterial);
+ v.visitRep(*this);
+ }
+
+ /*! Computes the rep bounding box.
+ * Each Inherited rep must compute its bbox depending on the way the data are stored. So, each inherited class
+ * must overload this method
+ */
+ virtual void ComputeBBox() = 0;
+
+ /*! Returns the rep bounding box */
+ virtual const BBox<Vec3r>& bbox() const
+ {
+ return _BBox;
+ }
+
+ inline Id getId() const
+ {
+ return _Id;
+ }
+
+ inline const string& getName() const
+ {
+ return _Name;
+ }
+
+ inline const FrsMaterial *frs_material() const
+ {
+ return _FrsMaterial;
+ }
+
+ /*! Sets the Rep bounding box */
+ virtual void setBBox(const BBox<Vec3r>& iBox)
+ {
+ _BBox = iBox;
+ }
+
+ inline void setId(const Id& id)
+ {
+ _Id = id;
+ }
+
+ inline void setName(const string& name)
+ {
+ _Name = name;
+ }
+
+ inline void setFrsMaterial(const FrsMaterial& iMaterial)
+ {
+ _FrsMaterial = new FrsMaterial(iMaterial);
+ }
+
+private:
+ BBox<Vec3r> _BBox;
+ Id _Id;
+ string _Name;
+ FrsMaterial *_FrsMaterial;
+};
+
+#endif // __FREESTYLE_REP_H__
diff --git a/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp
new file mode 100644
index 00000000000..8be3f2527b6
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp
+ * \ingroup freestyle
+ * \brief Class to display textual information about a scene graph.
+ * \author Stephane Grabli
+ * \author Emmanuel Turquin
+ * \date 26/04/2003
+ */
+
+#include <iomanip>
+
+#include "IndexedFaceSet.h"
+#include "ScenePrettyPrinter.h"
+
+#define VISIT(CLASS) \
+ void ScenePrettyPrinter::visit##CLASS(CLASS&) \
+ { \
+ _ofs << _space << #CLASS << endl; \
+ }
+
+VISIT(Node)
+VISIT(NodeShape)
+VISIT(NodeGroup)
+VISIT(NodeLight)
+VISIT(NodeDrawingStyle)
+VISIT(NodeTransform)
+
+void ScenePrettyPrinter::visitNodeShapeBefore(NodeShape&)
+{
+ increaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeShapeAfter(NodeShape&)
+{
+ decreaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeGroupBefore(NodeGroup&)
+{
+ increaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeGroupAfter(NodeGroup&)
+{
+ decreaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeDrawingStyleBefore(NodeDrawingStyle&)
+{
+ increaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeDrawingStyleAfter(NodeDrawingStyle&)
+{
+ decreaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeTransformBefore(NodeTransform&)
+{
+ increaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeTransformAfter(NodeTransform&)
+{
+ decreaseSpace();
+}
+
+VISIT(LineRep)
+VISIT(OrientedLineRep)
+VISIT(TriangleRep)
+VISIT(VertexRep)
+
+void ScenePrettyPrinter::visitIndexedFaceSet(IndexedFaceSet& ifs)
+{
+ const real *vertices = ifs.vertices();
+ unsigned vsize = ifs.vsize();
+
+ _ofs << _space << "IndexedFaceSet" << endl;
+ const real *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/ScenePrettyPrinter.h b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.h
new file mode 100644
index 00000000000..39fb9eceef8
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.h
@@ -0,0 +1,109 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_SCENE_PRETTY_PRINTER_H__
+#define __FREESTYLE_SCENE_PRETTY_PRINTER_H__
+
+/** \file blender/freestyle/intern/scene_graph/ScenePrettyPrinter.h
+ * \ingroup freestyle
+ * \brief Class to display textual information about a scene graph.
+ * \author Stephane Grabli
+ * \author Emmanuel Turquin
+ * \date 26/04/2003
+ */
+
+#include <fstream>
+#include <iostream>
+#include <string>
+
+#include "SceneVisitor.h"
+
+using namespace std;
+
+class ScenePrettyPrinter : public SceneVisitor
+{
+public:
+ ScenePrettyPrinter(const string filename = "SceneLog.txt") : SceneVisitor()
+ {
+ if (!filename.empty())
+ _ofs.open(filename.c_str());
+ if (!_ofs.is_open())
+ cerr << "Warning, unable to open file \"" << filename << "\"" << endl;
+ _space = "";
+ }
+
+ virtual ~ScenePrettyPrinter()
+ {
+ if (_ofs.is_open())
+ _ofs.close();
+ }
+
+
+ //
+ // visitClass methods
+ //
+ //////////////////////////////////////////////
+
+ VISIT_DECL(Node);
+ VISIT_DECL(NodeShape);
+ VISIT_DECL(NodeGroup);
+ VISIT_DECL(NodeLight);
+ VISIT_DECL(NodeDrawingStyle);
+ VISIT_DECL(NodeTransform);
+
+ VISIT_DECL(LineRep);
+ VISIT_DECL(OrientedLineRep);
+ VISIT_DECL(TriangleRep);
+ VISIT_DECL(VertexRep);
+ VISIT_DECL(IndexedFaceSet);
+
+ virtual void visitNodeShapeBefore(NodeShape&);
+ virtual void visitNodeShapeAfter(NodeShape&);
+ virtual void visitNodeGroupBefore(NodeGroup&);
+ virtual void visitNodeGroupAfter(NodeGroup&);
+ virtual void visitNodeDrawingStyleBefore(NodeDrawingStyle&);
+ virtual void visitNodeDrawingStyleAfter(NodeDrawingStyle&);
+ virtual void visitNodeTransformBefore(NodeTransform&);
+ virtual void visitNodeTransformAfter(NodeTransform&);
+
+protected:
+ void increaseSpace()
+ {
+ _space += " ";
+ }
+
+ void decreaseSpace()
+ {
+ _space.erase(0, 2);
+ }
+
+private:
+ ofstream _ofs;
+ string _space;
+};
+
+#endif // __FREESTYLE_SCENE_PRETTY_PRINTER_H__
diff --git a/source/blender/blenloader/BLO_soundfile.h b/source/blender/freestyle/intern/scene_graph/SceneVisitor.cpp
index d2f87139b74..32ba38ece80 100644
--- a/source/blender/blenloader/BLO_soundfile.h
+++ b/source/blender/freestyle/intern/scene_graph/SceneVisitor.cpp
@@ -15,7 +15,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
* All rights reserved.
*
* The Original Code is: all of this file.
@@ -24,18 +24,12 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
-#ifndef __BLO_SOUNDFILE_H__
-#define __BLO_SOUNDFILE_H__
-/** \file BLO_soundfile.h
- * \ingroup blenloader
+/** \file blender/freestyle/intern/scene_graph/SceneVisitor.cpp
+ * \ingroup freestyle
+ * \brief Class to visit (without doing anything) a scene graph structure
+ * \author Emmanuel Turquin
+ * \date 26/04/2003
*/
-#include "DNA_sound_types.h"
-#include "DNA_packedFile_types.h"
-
-struct bSound;
-struct PackedFile;
-
-#endif
-
+#include "SceneVisitor.h"
diff --git a/source/blender/freestyle/intern/scene_graph/SceneVisitor.h b/source/blender/freestyle/intern/scene_graph/SceneVisitor.h
new file mode 100644
index 00000000000..57d3f9189ed
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/SceneVisitor.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_SCENE_VISITOR_H__
+#define __FREESTYLE_SCENE_VISITOR_H__
+
+/** \file blender/freestyle/intern/scene_graph/SceneVisitor.h
+ * \ingroup freestyle
+ * \brief Class to visit (without doing anything) a scene graph structure
+ * \author Emmanuel Turquin
+ * \date 26/04/2003
+ */
+
+#include "../system/FreestyleConfig.h"
+
+#define VISIT_COMPLETE_DEF(type) \
+ virtual void visit##type(type&) {} \
+ virtual void visit##type##Before(type&) {} \
+ virtual void visit##type##After(type&) {}
+
+#define VISIT_DECL(type) \
+ virtual void visit##type(type&);
+
+#define VISIT_COMPLETE_DECL(type) \
+ virtual void visit##type##Before(type&); \
+ virtual void visit##type(type&); \
+ virtual void visit##type##After(type&);
+
+class Node;
+class NodeShape;
+class NodeGroup;
+class NodeLight;
+class NodeCamera;
+class NodeDrawingStyle;
+class NodeTransform;
+
+class Rep;
+class LineRep;
+class OrientedLineRep;
+class TriangleRep;
+class VertexRep;
+class IndexedFaceSet;
+class DrawingStyle;
+class FrsMaterial;
+
+class LIB_SCENE_GRAPH_EXPORT SceneVisitor
+{
+public:
+ SceneVisitor() {}
+ virtual ~SceneVisitor() {}
+
+ virtual void beginScene() {}
+ virtual void endScene() {}
+
+ //
+ // visitClass methods
+ //
+ //////////////////////////////////////////////
+
+ VISIT_COMPLETE_DEF(Node)
+ VISIT_COMPLETE_DEF(NodeShape)
+ VISIT_COMPLETE_DEF(NodeGroup)
+ VISIT_COMPLETE_DEF(NodeLight)
+ VISIT_COMPLETE_DEF(NodeCamera)
+ VISIT_COMPLETE_DEF(NodeDrawingStyle)
+ VISIT_COMPLETE_DEF(NodeTransform)
+
+ VISIT_COMPLETE_DEF(Rep)
+ VISIT_COMPLETE_DEF(LineRep)
+ VISIT_COMPLETE_DEF(OrientedLineRep)
+ VISIT_COMPLETE_DEF(TriangleRep)
+ VISIT_COMPLETE_DEF(VertexRep)
+ VISIT_COMPLETE_DEF(IndexedFaceSet)
+ VISIT_COMPLETE_DEF(DrawingStyle)
+ VISIT_COMPLETE_DEF(FrsMaterial)
+};
+
+#endif // __FREESTYLE_SCENE_VISITOR_H__
diff --git a/source/blender/freestyle/intern/scene_graph/TriangleRep.cpp b/source/blender/freestyle/intern/scene_graph/TriangleRep.cpp
new file mode 100644
index 00000000000..01053561aae
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/TriangleRep.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/scene_graph/TriangleRep.cpp
+ * \ingroup freestyle
+ * \brief Class to define the represenation of a triangle
+ * \author Stephane Grabli
+ * \date 16/12/2002
+ */
+
+#include "TriangleRep.h"
+
+void TriangleRep::ComputeBBox()
+{
+ real XMax = _vertices[0][0];
+ real YMax = _vertices[0][1];
+ real ZMax = _vertices[0][2];
+
+ real XMin = _vertices[0][0];
+ real YMin = _vertices[0][1];
+ real ZMin = _vertices[0][2];
+
+ // parse all the coordinates to find the XMax, YMax, ZMax
+ for (int i = 0; i < 3; ++i) {
+ // X
+ if (_vertices[i][0] > XMax)
+ XMax = _vertices[i][0];
+ if (_vertices[i][0] < XMin)
+ XMin = _vertices[i][0];
+
+ // Y
+ if (_vertices[i][1] > YMax)
+ YMax = _vertices[i][1];
+ if (_vertices[i][1] < YMin)
+ YMin = _vertices[i][1];
+
+ // Z
+ if (_vertices[i][2] > ZMax)
+ ZMax = _vertices[i][2];
+ if (_vertices[i][2] < ZMin)
+ ZMin = _vertices[i][2];
+ }
+
+ setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax)));
+}
diff --git a/source/blender/freestyle/intern/scene_graph/TriangleRep.h b/source/blender/freestyle/intern/scene_graph/TriangleRep.h
new file mode 100644
index 00000000000..c65eee72e03
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/TriangleRep.h
@@ -0,0 +1,150 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_TRIANGLE_REP_H__
+#define __FREESTYLE_TRIANGLE_REP_H__
+
+/** \file blender/freestyle/intern/scene_graph/TriangleRep.h
+ * \ingroup freestyle
+ * \brief Class to define the represenation of a triangle
+ * \author Stephane Grabli
+ * \date 16/12/2002
+ */
+
+//! inherits from class Rep
+#include "Rep.h"
+
+/*! Base class for all lines objects */
+class LIB_SCENE_GRAPH_EXPORT TriangleRep : public Rep
+{
+public:
+ /*! Line description style */
+ enum TRIANGLE_STYLE {
+ FILL,
+ LINES,
+ };
+
+private:
+ TRIANGLE_STYLE _Style;
+ Vec3r _vertices[3];
+ Vec3r _colors[3];
+
+public:
+ inline TriangleRep() : Rep()
+ {
+ _Style = FILL;
+ }
+
+ /*! Builds a triangle from 3 vertices
+ * v0
+ * first vertex
+ * v1
+ * second vertex
+ * v2
+ * third vertex
+ */
+ inline TriangleRep(const Vec3r& v0, const Vec3r& v1, const Vec3r& v2) : Rep()
+ {
+ _vertices[0] = v0;
+ _vertices[1] = v1;
+ _vertices[2] = v2;
+ _Style = FILL;
+ }
+
+ inline TriangleRep(const Vec3r& v0, const Vec3r& c0, const Vec3r& v1, const Vec3r& c1,
+ const Vec3r& v2, const Vec3r& c2)
+ : Rep()
+ {
+ _vertices[0] = v0;
+ _vertices[1] = v1;
+ _vertices[2] = v2;
+ _colors[0] = c0;
+ _colors[1] = c1;
+ _colors[2] = c2;
+ _Style = FILL;
+ }
+
+ virtual ~TriangleRep() {}
+
+ /*! accessors */
+ inline const TRIANGLE_STYLE style() const
+ {
+ return _Style;
+ }
+
+ inline const Vec3r& vertex(int index) const
+ {
+ return _vertices[index];
+ }
+
+ inline const Vec3r& color(int index) const
+ {
+ return _colors[index];
+ }
+
+ /*! modifiers */
+ inline void setStyle(const TRIANGLE_STYLE iStyle)
+ {
+ _Style = iStyle;
+ }
+
+ inline void setVertex(int index, const Vec3r& iVertex)
+ {
+ _vertices[index] = iVertex;
+ }
+
+ inline void setColor(int index, const Vec3r& iColor)
+ {
+ _colors[index] = iColor;
+ }
+
+ inline void setVertices(const Vec3r& v0, const Vec3r& v1, const Vec3r& v2)
+ {
+ _vertices[0] = v0;
+ _vertices[1] = v1;
+ _vertices[2] = v2;
+ }
+
+ inline void setColors(const Vec3r& c0, const Vec3r& c1, const Vec3r& c2)
+ {
+ _colors[0] = c0;
+ _colors[1] = c1;
+ _colors[2] = c2;
+ }
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v)
+ {
+ Rep::accept(v);
+ v.visitTriangleRep(*this);
+ }
+
+ /*! Computes the triangle bounding box.*/
+ virtual void ComputeBBox();
+};
+
+#endif // __FREESTYLE_TRIANGLE_REP_H__
diff --git a/source/blender/freestyle/intern/scene_graph/VertexRep.cpp b/source/blender/freestyle/intern/scene_graph/VertexRep.cpp
new file mode 100644
index 00000000000..75b0d4b91b3
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/VertexRep.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/scene_graph/VertexRep.cpp
+ * \ingroup freestyle
+ * \brief Class to define the representation of a vertex for displaying purpose.
+ * \author Stephane Grabli
+ * \date 03/04/2002
+ */
+
+#include "VertexRep.h"
+
+void VertexRep::ComputeBBox()
+{
+ setBBox(BBox<Vec3r>(Vec3r(_coordinates[0], _coordinates[1], _coordinates[2]),
+ Vec3r(_coordinates[0], _coordinates[1], _coordinates[2])));
+}
diff --git a/source/blender/freestyle/intern/scene_graph/VertexRep.h b/source/blender/freestyle/intern/scene_graph/VertexRep.h
new file mode 100644
index 00000000000..7483806f1fe
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/VertexRep.h
@@ -0,0 +1,141 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_VERTEX_REP_H__
+#define __FREESTYLE_VERTEX_REP_H__
+
+/** \file blender/freestyle/intern/scene_graph/VertexRep.h
+ * \ingroup freestyle
+ * \brief Class to define the representation of a vertex for displaying purpose.
+ * \author Stephane Grabli
+ * \date 03/04/2002
+ */
+
+#include "Rep.h"
+
+class LIB_SCENE_GRAPH_EXPORT VertexRep : public Rep
+{
+public:
+ inline VertexRep() : Rep()
+ {
+ _vid = 0;
+ _PointSize = 0.0f;
+ }
+
+ inline VertexRep(real x, real y, real z, int id = 0) : Rep()
+ {
+ _coordinates[0] = x;
+ _coordinates[1] = y;
+ _coordinates[2] = z;
+
+ _vid = id;
+ _PointSize = 0.0f;
+ }
+
+ inline ~VertexRep() {}
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v)
+ {
+ Rep::accept(v);
+ v.visitVertexRep(*this);
+ }
+
+ /*! Computes the rep bounding box. */
+ virtual void ComputeBBox();
+
+ /*! accessors */
+ inline const int vid() const
+ {
+ return _vid;
+ }
+
+ inline const real * coordinates() const
+ {
+ return _coordinates;
+ }
+
+ inline real x() const
+ {
+ return _coordinates[0];
+ }
+
+ inline real y() const
+ {
+ return _coordinates[1];
+ }
+
+ inline real z() const
+ {
+ return _coordinates[2];
+ }
+
+ inline float pointSize() const
+ {
+ return _PointSize;
+ }
+
+ /*! modifiers */
+ inline void setVid(int id)
+ {
+ _vid = id;
+ }
+
+ inline void setX(real x)
+ {
+ _coordinates[0] = x;
+ }
+
+ inline void setY(real y)
+ {
+ _coordinates[1] = y;
+ }
+
+ inline void setZ(real z)
+ {
+ _coordinates[2] = z;
+ }
+
+ inline void setCoordinates(real x, real y, real z)
+ {
+ _coordinates[0] = x;
+ _coordinates[1] = y;
+ _coordinates[2] = z;
+ }
+
+ inline void setPointSize(float iPointSize)
+ {
+ _PointSize = iPointSize;
+ }
+
+private:
+ int _vid; // vertex id
+ real _coordinates[3];
+ float _PointSize;
+};
+
+#endif // __FREESTYLE_VERTEX_REP_H__
diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp
new file mode 100644
index 00000000000..25b5bdb26dc
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp
+ * \ingroup freestyle
+ * \brief Functions taking 0D input
+ * \author Stephane Grabli
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+#include "AdvancedFunctions0D.h"
+#include "Canvas.h"
+
+#include "../view_map/Functions0D.h"
+#include "../view_map/SteerableViewMap.h"
+
+namespace Functions0D {
+
+int DensityF0D::operator()(Interface0DIterator& iter)
+{
+ Canvas *canvas = Canvas::getInstance();
+ int bound = _filter.getBound();
+
+ if ((iter->getProjectedX() - bound < 0) || (iter->getProjectedX() + bound>canvas->width()) ||
+ (iter->getProjectedY() - bound < 0) || (iter->getProjectedY() + bound>canvas->height()))
+ {
+ result = 0.0;
+ return 0;
+ }
+
+ RGBImage image;
+ canvas->readColorPixels((int)iter->getProjectedX() - bound, (int)iter->getProjectedY() - bound,
+ _filter.maskSize(), _filter.maskSize(), image);
+ result = _filter.getSmoothedPixel<RGBImage>(&image, (int)iter->getProjectedX(), (int)iter->getProjectedY());
+
+ return 0;
+}
+
+
+int LocalAverageDepthF0D::operator()(Interface0DIterator& iter)
+{
+ Canvas *iViewer = Canvas::getInstance();
+ int bound = _filter.getBound();
+
+ if ((iter->getProjectedX() - bound < 0) || (iter->getProjectedX() + bound>iViewer->width()) ||
+ (iter->getProjectedY() - bound < 0) || (iter->getProjectedY() + bound>iViewer->height()))
+ {
+ result = 0.0;
+ return 0;
+ }
+
+ GrayImage image;
+ iViewer->readDepthPixels((int)iter->getProjectedX() - bound, (int)iter->getProjectedY() - bound,
+ _filter.maskSize(), _filter.maskSize(), image);
+ result = _filter.getSmoothedPixel(&image, (int)iter->getProjectedX(), (int)iter->getProjectedY());
+
+ return 0;
+}
+
+int ReadMapPixelF0D::operator()(Interface0DIterator& iter)
+{
+ Canvas *canvas = Canvas::getInstance();
+ result = canvas->readMapPixel(_mapName, _level, (int)iter->getProjectedX(), (int)iter->getProjectedY());
+ return 0;
+}
+
+int ReadSteerableViewMapPixelF0D::operator()(Interface0DIterator& iter)
+{
+ SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap();
+ result = svm->readSteerableViewMapPixel(_orientation, _level, (int)iter->getProjectedX(),
+ (int)iter->getProjectedY());
+ return 0;
+}
+
+int ReadCompleteViewMapPixelF0D::operator()(Interface0DIterator& iter)
+{
+ SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap();
+ result = svm->readCompleteViewMapPixel(_level, (int)iter->getProjectedX(), (int)iter->getProjectedY());
+ return 0;
+}
+
+int GetViewMapGradientNormF0D::operator()(Interface0DIterator& iter)
+{
+ SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap();
+ float pxy = svm->readCompleteViewMapPixel(_level, (int)iter->getProjectedX(), (int)iter->getProjectedY());
+ float gx = svm->readCompleteViewMapPixel(_level, (int)iter->getProjectedX() + _step,
+ (int)iter->getProjectedY()) - pxy;
+ float gy = svm->readCompleteViewMapPixel(_level, (int)iter->getProjectedX(),
+ (int)iter->getProjectedY() + _step) - pxy;
+ result = Vec2f(gx, gy).norm();
+ return 0;
+}
+
+} // end of namespace Functions0D
diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h
new file mode 100644
index 00000000000..2875402700b
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h
@@ -0,0 +1,229 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_ADVANCED_FUNCTIONS_0D_H__
+#define __FREESTYLE_ADVANCED_FUNCTIONS_0D_H__
+
+/** \file blender/freestyle/intern/stroke/AdvancedFunctions0D.h
+ * \ingroup freestyle
+ * \brief Functions taking 0D input
+ * \author Stephane Grabli
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+#include "../image/GaussianFilter.h"
+#include "../image/Image.h"
+
+#include "../view_map/Functions0D.h"
+
+//
+// Functions definitions
+//
+///////////////////////////////////////////////////////////
+
+namespace Functions0D {
+
+// DensityF0D
+/*! Returns the density of the (result) image evaluated at an Interface0D.
+ * This density is evaluated using a pixels square window around the evaluation point and integrating
+ * these values using a gaussian.
+ */
+class LIB_STROKE_EXPORT DensityF0D : public UnaryFunction0D<double>
+{
+public:
+ /*! Builds the functor from the gaussian sigma value.
+ * \param sigma
+ * sigma indicates the x value for which the gaussian function is 0.5. It leads to the window size value.
+ * (the larger, the smoother)
+ */
+ DensityF0D(double sigma = 2) : UnaryFunction0D<double>()
+ {
+ _filter.setSigma((float)sigma);
+ }
+
+ /*! Returns the string "DensityF0D" */
+ string getName() const
+ {
+ return "DensityF0D";
+ }
+
+ /*! The () operator. */
+ int operator()(Interface0DIterator& iter);
+
+private:
+ GaussianFilter _filter;
+};
+
+// LocalAverageDepthF0D
+/*! Returns the average depth around a point.
+ * The result is obtained by querying the depth buffer on a window around that point.
+ */
+class LIB_STROKE_EXPORT LocalAverageDepthF0D : public UnaryFunction0D<double>
+{
+private:
+ GaussianFilter _filter;
+
+public:
+ /*! Builds the functor from the size of the mask that will be used. */
+ LocalAverageDepthF0D(real maskSize = 5.0f) : UnaryFunction0D<double>()
+ {
+ _filter.setSigma((float)maskSize / 2.0f);
+ }
+
+ /*! Returns the string "LocalAverageDepthF0D" */
+ string getName() const
+ {
+ return "LocalAverageDepthF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter);
+};
+
+// ReadMapPixel
+/*! Reads a pixel in a map. */
+class LIB_STROKE_EXPORT ReadMapPixelF0D : public UnaryFunction0D<float>
+{
+private:
+ const char * _mapName;
+ int _level;
+
+public:
+ /*! Builds the functor from name of the
+ * Map that must be read.
+ * \param iMapName
+ * The name of the map.
+ * \param level
+ * The level of the pyramid from which the pixel must be read.
+ */
+ ReadMapPixelF0D(const char *iMapName, int level) : UnaryFunction0D<float>()
+ {
+ _mapName = iMapName;
+ _level = level;
+ }
+
+ /*! Returns the string "ReadMapPixelF0D" */
+ string getName() const
+ {
+ return "ReadMapPixelF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter);
+};
+
+// ReadSteerableViewMapPixel
+/*! Reads a pixel in one of the level of one of the steerable viewmaps. */
+class LIB_STROKE_EXPORT ReadSteerableViewMapPixelF0D : public UnaryFunction0D<float>
+{
+private:
+ unsigned _orientation;
+ int _level;
+
+public:
+ /*! Builds the functor
+ * \param nOrientation
+ * The integer belonging to [0,4] indicating the orientation (E,NE,N,NW) we are interested in.
+ * \param level
+ * The level of the pyramid from which the pixel must be read.
+ */
+ ReadSteerableViewMapPixelF0D(unsigned nOrientation, int level) : UnaryFunction0D<float>()
+ {
+ _orientation = nOrientation;
+ _level = level;
+ }
+
+ /*! Returns the string "ReadSteerableViewMapPixelF0D" */
+ string getName() const
+ {
+ return "ReadSteerableViewMapPixelF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter);
+};
+
+// ReadCompleteViewMapPixel
+/*! Reads a pixel in one of the level of the complete viewmap. */
+class LIB_STROKE_EXPORT ReadCompleteViewMapPixelF0D : public UnaryFunction0D<float>
+{
+private:
+ int _level;
+
+public:
+ /*! Builds the functor
+ * \param level
+ * The level of the pyramid from which the pixel must be read.
+ */
+ ReadCompleteViewMapPixelF0D(int level) : UnaryFunction0D<float>()
+ {
+ _level = level;
+ }
+
+ /*! Returns the string "ReadCompleteViewMapPixelF0D" */
+ string getName() const
+ {
+ return "ReadCompleteViewMapPixelF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter);
+};
+
+// GetViewMapGradientNormF0D
+/*! Returns the norm of the gradient of the global viewmap density image. */
+class LIB_STROKE_EXPORT GetViewMapGradientNormF0D: public UnaryFunction0D< float>
+{
+private:
+ int _level;
+ float _step;
+
+public:
+ /*! Builds the functor
+ * \param level
+ * The level of the pyramid from which the pixel must be read.
+ */
+ GetViewMapGradientNormF0D(int level) : UnaryFunction0D<float>()
+ {
+ _level = level;
+ _step = (float)pow(2.0, _level);
+ }
+
+ /*! Returns the string "GetOccludeeF0D" */
+ string getName() const
+ {
+ return "GetViewMapGradientNormF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter);
+};
+
+} // end of namespace Functions0D
+
+#endif // __FREESTYLE_ADVANCED_FUNCTIONS_0D_H__
diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp
new file mode 100644
index 00000000000..e07afb2566e
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp
+ * \ingroup freestyle
+ * \brief Functions taking 1D input
+ * \author Stephane Grabli
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+#include "AdvancedFunctions1D.h"
+#include "Canvas.h"
+
+#include "../view_map/SteerableViewMap.h"
+
+// FIXME
+namespace Functions1D {
+
+int GetSteerableViewMapDensityF1D::operator()(Interface1D& inter)
+{
+ SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap();
+ Interface0DIterator it = inter.pointsBegin(_sampling);
+ Interface0DIterator itnext = it;
+ ++itnext;
+ FEdge *fe;
+ unsigned nSVM;
+ vector<float> values;
+
+ while (!itnext.isEnd()) {
+ Interface0D& i0D = (*it);
+ Interface0D& i0Dnext = (*itnext);
+ fe = i0D.getFEdge(i0Dnext);
+ if (fe == 0) {
+ cerr << "GetSteerableViewMapDensityF1D warning: no FEdge between " << i0D.getId() << " and " <<
+ i0Dnext.getId() << endl;
+ // compute the direction between these two ???
+ Vec2f dir = i0Dnext.getPoint2D() - i0D.getPoint2D();
+ nSVM = svm->getSVMNumber(dir);
+ }
+ else {
+ nSVM = svm->getSVMNumber(fe->getId().getFirst());
+ }
+ Vec2r m((i0D.getProjectedX() + i0Dnext.getProjectedX()) / 2.0,
+ (i0D.getProjectedY() + i0Dnext.getProjectedY()) / 2.0);
+ values.push_back(svm->readSteerableViewMapPixel(nSVM, _level, (int)m[0], (int)m[1]));
+ ++it;
+ ++itnext;
+ }
+
+ float res, res_tmp;
+ vector<float>::iterator v = values.begin(), vend = values.end();
+ unsigned size = 1;
+ switch (_integration) {
+ case MIN:
+ res = *v;
+ ++v;
+ for (; v != vend; ++v) {
+ res_tmp = *v;
+ if (res_tmp < res)
+ res = res_tmp;
+ }
+ break;
+ case MAX:
+ res = *v;
+ ++v;
+ for (; v != vend; ++v) {
+ res_tmp = *v;
+ if (res_tmp > res)
+ res = res_tmp;
+ }
+ break;
+ case FIRST:
+ res = *v;
+ break;
+ case LAST:
+ --vend;
+ res = *vend;
+ break;
+ case MEAN:
+ default:
+ res = *v;
+ ++v;
+ for (; v != vend; ++v, ++size)
+ res += *v;
+ res /= (size ? size : 1);
+ break;
+ }
+ result = res;
+ return 0;
+}
+
+int GetDirectionalViewMapDensityF1D::operator()(Interface1D& inter)
+{
+ //soc unsigned size;
+ result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration);
+ return 0;
+}
+
+int GetCompleteViewMapDensityF1D::operator()(Interface1D& inter)
+{
+ //soc unsigned size;
+ /* Id id = inter.getId(); */ /* UNUSED */
+ result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration);
+ return 0;
+}
+
+int GetViewMapGradientNormF1D::operator()(Interface1D& inter)
+{
+ result = integrate(_func, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration);
+ return 0;
+}
+
+} // Functions1D namespace
diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h
new file mode 100644
index 00000000000..8373450d440
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h
@@ -0,0 +1,298 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_ADVANCED_FUNCTIONS_1D_H__
+#define __FREESTYLE_ADVANCED_FUNCTIONS_1D_H__
+
+/** \file blender/freestyle/intern/stroke/AdvancedFunctions1D.h
+ * \ingroup freestyle
+ * \brief Functions taking 1D input
+ * \author Stephane Grabli
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+#include "AdvancedFunctions0D.h"
+
+#include "../view_map/Functions1D.h"
+
+//
+// Functions definitions
+//
+///////////////////////////////////////////////////////////
+
+namespace Functions1D {
+
+// DensityF1D
+/*! Returns the density evaluated for an Interface1D.
+ * The density is evaluated for a set of points along the Interface1D (using the DensityF0D functor) with a
+ * user-defined sampling and then integrated into a single value using a user-defined integration method.
+ */
+class DensityF1D : public UnaryFunction1D<double>
+{
+private:
+ float _sampling;
+
+public:
+ /*! Builds the functor.
+ * \param sigma
+ * Thesigma used in DensityF0D and determining the window size used in each density query.
+ * \param iType
+ * The integration method used to compute a single value from a set of values.
+ * \param sampling
+ * The resolution used to sample the chain: the corresponding 0D function is evaluated at each sample point and
+ * the result is obtained by combining the resulting values into a single one, following the method specified
+ * by iType.
+ */
+ DensityF1D(double sigma = 2, IntegrationType iType = MEAN, float sampling = 2.0f)
+ : UnaryFunction1D<double>(iType), _fun(sigma)
+ {
+ _sampling = sampling;
+ }
+
+ /*! Destructor */
+ virtual ~DensityF1D() {}
+
+ /*! Returns the string "DensityF1D"*/
+ string getName() const
+ {
+ return "DensityF1D";
+ }
+
+ /*! the () operator.*/
+ int operator()(Interface1D& inter)
+ {
+ result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration);
+ return 0;
+ }
+
+private:
+ Functions0D::DensityF0D _fun;
+};
+
+// LocalAverageDepthF1D
+/*! Returns the average depth evaluated for an Interface1D.
+ * The average depth is evaluated for a set of points along the Interface1D (using the LocalAverageDepthF0D functor)
+ * with a user-defined sampling and then integrated into a single value using a user-defined integration method.
+ */
+class LocalAverageDepthF1D : public UnaryFunction1D<double>
+{
+public:
+ /*! Builds the functor.
+ * \param sigma
+ * The sigma used in DensityF0D and determining the window size used in each density query.
+ * \param iType
+ * The integration method used to compute a single value from a set of values.
+ */
+ LocalAverageDepthF1D(real sigma, IntegrationType iType = MEAN)
+ : UnaryFunction1D<double>(iType), _fun(sigma)
+ {
+ }
+
+ /*! Returns the string "LocalAverageDepthF1D" */
+ string getName() const
+ {
+ return "LocalAverageDepthF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter)
+ {
+ result = integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+private:
+ Functions0D::LocalAverageDepthF0D _fun;
+};
+
+// GetCompleteViewMapDensity
+/*! Returns the density evaluated for an Interface1D in the complete viewmap image.
+ * The density is evaluated for a set of points along the Interface1D (using the ReadCompleteViewMapPixelF0D functor)
+ * and then integrated into a single value using a user-defined integration method.
+ */
+class LIB_STROKE_EXPORT GetCompleteViewMapDensityF1D : public UnaryFunction1D<double>
+{
+public:
+ /*! Builds the functor.
+ * \param level
+ * The level of the pyramid from which
+ * the pixel must be read.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ * \param sampling
+ * The resolution used to sample the chain: the corresponding 0D function
+ * is evaluated at each sample point and the result is obtained by
+ * combining the resulting values into a single one, following the
+ * method specified by iType.
+ */
+ GetCompleteViewMapDensityF1D(unsigned level, IntegrationType iType = MEAN, float sampling = 2.0f)
+ : UnaryFunction1D<double>(iType), _fun(level)
+ {
+ _sampling = sampling;
+ }
+
+ /*! Returns the string "GetCompleteViewMapDensityF1D" */
+ string getName() const
+ {
+ return "GetCompleteViewMapDensityF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+
+private:
+ Functions0D::ReadCompleteViewMapPixelF0D _fun;
+ float _sampling;
+};
+
+// 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 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.
+ */
+class LIB_STROKE_EXPORT GetDirectionalViewMapDensityF1D : public UnaryFunction1D<double>
+{
+public:
+ /*! Builds the functor.
+ * \param iOrientation
+ * The number of the directional map we must work with.
+ * \param level
+ * The level of the pyramid from which the pixel must be read.
+ * \param iType
+ * The integration method used to compute a single value from a set of values.
+ * \param sampling
+ * The resolution used to sample the chain: the corresponding 0D function is evaluated at each sample point and
+ * the result is obtained by combining the resulting values into a single one, following the method specified
+ * by iType.
+ */
+ GetDirectionalViewMapDensityF1D(unsigned iOrientation, unsigned level, IntegrationType iType = MEAN,
+ float sampling = 2.0f)
+ : UnaryFunction1D<double>(iType), _fun(iOrientation, level)
+ {
+ _sampling = sampling;
+ }
+
+ /*! Returns the string "GetDirectionalViewMapDensityF1D" */
+ string getName() const
+ {
+ return "GetDirectionalViewMapDensityF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+
+private:
+ Functions0D::ReadSteerableViewMapPixelF0D _fun;
+ float _sampling;
+};
+
+// GetSteerableViewMapDensityF1D
+/*! Returns the density of the viewmap for a given Interface1D. The density of each FEdge is evaluated
+ * in the proper steerable ViewMap depending on its oorientation.
+ */
+class LIB_STROKE_EXPORT GetSteerableViewMapDensityF1D : public UnaryFunction1D<real>
+{
+private:
+ int _level;
+ float _sampling;
+
+public:
+ /*! Builds the functor from the level of the pyramid from which the pixel must be read.
+ * \param level
+ * The level of the pyramid from which the pixel must be read.
+ * \param iType
+ * The integration method used to compute a single value from a set of values.
+ * \param sampling
+ * The resolution used to sample the chain: the corresponding 0D function is evaluated at each sample point and
+ * the result is obtained by combining the resulting values into a single one, following the method specified
+ * by iType.
+ */
+ GetSteerableViewMapDensityF1D(int level, IntegrationType iType = MEAN, float sampling = 2.0f)
+ : UnaryFunction1D<real>(iType)
+ {
+ _level = level;
+ _sampling = sampling;
+ }
+
+ /*! Destructor */
+ virtual ~GetSteerableViewMapDensityF1D() {}
+
+ /*! Returns the string "GetSteerableViewMapDensityF1D" */
+ string getName() const
+ {
+ return "GetSteerableViewMapDensityF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+// GetViewMapGradientNormF1D
+/*! Returns the density of the viewmap for a given Interface1D. The density of each FEdge is evaluated in
+ * the proper steerable ViewMap depending on its oorientation.
+ */
+class LIB_STROKE_EXPORT GetViewMapGradientNormF1D : public UnaryFunction1D<real>
+{
+private:
+ int _level;
+ float _sampling;
+ Functions0D::GetViewMapGradientNormF0D _func;
+
+public:
+ /*! Builds the functor from the level of the pyramid from which the pixel must be read.
+ * \param level
+ * The level of the pyramid from which the pixel must be read.
+ * \param iType
+ * The integration method used to compute a single value from a set of values.
+ * \param sampling
+ * The resolution used to sample the chain: the corresponding 0D function is evaluated at each sample point and
+ * the result is obtained by combining the resulting values into a single one, following the method specified
+ * by iType.
+ */
+ GetViewMapGradientNormF1D(int level, IntegrationType iType = MEAN, float sampling = 2.0f)
+ : UnaryFunction1D<real>(iType), _func(level)
+ {
+ _level = level;
+ _sampling = sampling;
+ }
+
+ /*! Returns the string "GetSteerableViewMapDensityF1D" */
+ string getName() const
+ {
+ return "GetViewMapGradientNormF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+} // end of namespace Functions1D
+
+#endif // __FREESTYLE_ADVANCED_FUNCTIONS_1D_H__
diff --git a/source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h b/source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h
new file mode 100644
index 00000000000..9235598da78
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h
@@ -0,0 +1,95 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_ADVANCED_PREDICATES_1D_H__
+#define __FREESTYLE_ADVANCED_PREDICATES_1D_H__
+
+/** \file blender/freestyle/intern/stroke/AdvancedPredicates1D.h
+ * \ingroup freestyle
+ * \brief Class gathering stroke creation algorithms
+ * \author Stephane Grabli
+ * \date 01/07/2003
+ */
+
+#include <string>
+
+#include "AdvancedFunctions1D.h"
+#include "Predicates1D.h"
+
+#include "../view_map/Interface1D.h"
+
+//
+// Predicates definitions
+//
+///////////////////////////////////////////////////////////
+
+namespace Predicates1D {
+
+// DensityLowerThanUP1D
+/*! Returns true if the density evaluated for the
+* Interface1D is less than a user-defined density value.
+*/
+class DensityLowerThanUP1D : public UnaryPredicate1D
+{
+public:
+ /*! Builds the functor.
+ * \param threshold
+ * The value of the threshold density.
+ * Any Interface1D having a density lower than this threshold will match.
+ * \param sigma
+ * The sigma value defining the density evaluation window size used in the DensityF0D functor.
+ */
+ DensityLowerThanUP1D(double threshold, double sigma = 2)
+ {
+ _threshold = threshold;
+ _sigma = sigma;
+ }
+
+ /*! Returns the string "DensityLowerThanUP1D" */
+ string getName() const
+ {
+ return "DensityLowerThanUP1D";
+ }
+
+ /*! The () operator. */
+ int operator()(Interface1D& inter)
+ {
+ Functions1D::DensityF1D fun(_sigma);
+ if (fun(inter) < 0)
+ return -1;
+ result = (fun.result < _threshold);
+ return 0;
+ }
+
+private:
+ double _sigma;
+ double _threshold;
+};
+
+} // end of namespace Predicates1D
+
+#endif // __FREESTYLE_ADVANCED_PREDICATES_1D_H__
diff --git a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp
new file mode 100644
index 00000000000..e631b9f4471
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp
@@ -0,0 +1,404 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp
+ * \ingroup freestyle
+ * \brief Fredo's stroke shaders
+ * \author Fredo Durand
+ * \date 17/12/2002
+ */
+
+#include "AdvancedStrokeShaders.h"
+#include "StrokeIterators.h"
+
+#include "../system/PseudoNoise.h"
+#include "../system/RandGen.h"
+
+/////////////////////////////////////////
+//
+// CALLIGRAPHICS SHADER
+//
+/////////////////////////////////////////
+
+CalligraphicShader::CalligraphicShader(real iMinThickness, real iMaxThickness, const Vec2f &iOrientation, bool clamp)
+: StrokeShader()
+{
+ _minThickness = iMinThickness;
+ _maxThickness = iMaxThickness;
+ _orientation = iOrientation;
+ _orientation.normalize();
+ _clamp = clamp;
+}
+
+float ksinToto = 0.0f;
+
+int CalligraphicShader::shade(Stroke &ioStroke) const
+{
+ Interface0DIterator v;
+ Functions0D::VertexOrientation2DF0D fun;
+ StrokeVertex *sv;
+ for (v = ioStroke.verticesBegin(); !v.isEnd(); ++v) {
+ real thickness;
+ if (fun(v) < 0)
+ return -1;
+
+ Vec2f vertexOri(fun.result);
+ Vec2r ori2d(-vertexOri[1], vertexOri[0]);
+ ori2d.normalizeSafe();
+ real scal = ori2d * _orientation;
+ sv = dynamic_cast<StrokeVertex*>(&(*v));
+ if (_clamp && (scal<0)) {
+ scal = 0.0;
+ sv->attribute().setColor(1, 1, 1);
+ }
+ else {
+ scal = fabs(scal);
+ sv->attribute().setColor(0, 0, 0);
+ }
+ thickness = _minThickness + scal * (_maxThickness - _minThickness);
+ if (thickness < 0.0)
+ thickness = 0.0;
+ sv->attribute().setThickness(thickness / 2.0, thickness / 2.0);
+ }
+
+ 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
+//
+/////////////////////////////////////////
+
+static const unsigned NB_VALUE_NOISE = 512;
+
+SpatialNoiseShader::SpatialNoiseShader(float ioamount, float ixScale, int nbOctave, bool smooth, bool pureRandom)
+: StrokeShader()
+{
+ _amount = ioamount;
+ if (ixScale == 0)
+ _xScale = 0;
+ else
+ _xScale = 1.0 / ixScale / real(NB_VALUE_NOISE);
+ _nbOctave = nbOctave;
+ _smooth = smooth;
+ _pureRandom = pureRandom;
+}
+
+int SpatialNoiseShader::shade(Stroke &ioStroke) const
+{
+ Interface0DIterator v, v2;
+ v = ioStroke.verticesBegin();
+ Vec2r p(v->getProjectedX(), v->getProjectedY());
+ v2 = v;
+ ++v2;
+ Vec2r p0(v2->getProjectedX(), v2->getProjectedY());
+ p0 = p + 2 * (p - p0);
+ StrokeVertex *sv;
+ sv = dynamic_cast<StrokeVertex*>(&(*v));
+ real initU = sv->strokeLength() * real(NB_VALUE_NOISE);
+ if (_pureRandom)
+ initU += RandGen::drand48() * real(NB_VALUE_NOISE);
+
+ Functions0D::VertexOrientation2DF0D fun;
+ while (!v.isEnd()) {
+ sv = dynamic_cast<StrokeVertex*>(&(*v));
+ Vec2r p(sv->getPoint());
+ if (fun(v) < 0)
+ return -1;
+ Vec2r vertexOri(fun.result);
+ Vec2r ori2d(vertexOri[0], vertexOri[1]);
+ ori2d = Vec2r(p - p0);
+ ori2d.normalizeSafe();
+
+ PseudoNoise mynoise;
+ real bruit;
+
+ if (_smooth)
+ bruit = mynoise.turbulenceSmooth(_xScale * sv->curvilinearAbscissa() + initU, _nbOctave);
+ else
+ bruit = mynoise.turbulenceLinear(_xScale * sv->curvilinearAbscissa() + initU, _nbOctave);
+
+ Vec2r noise(-ori2d[1] * _amount * bruit, ori2d[0] * _amount * bruit);
+
+ sv->setPoint(p[0] + noise[0], p[1] + noise[1]);
+ p0 = p;
+
+ ++v;
+ }
+
+ return 0;
+}
+
+/////////////////////////////////////////
+//
+// SMOOTHING SHADER
+//
+/////////////////////////////////////////
+
+SmoothingShader::SmoothingShader(int ionbIteration, real iFactorPoint, real ifactorCurvature,
+ real iFactorCurvatureDifference, real iAnisoPoint, real iAnisoNormal,
+ real iAnisoCurvature, real iCarricatureFactor)
+: StrokeShader()
+{
+ _nbIterations = ionbIteration;
+ _factorCurvature = ifactorCurvature;
+ _factorCurvatureDifference = iFactorCurvatureDifference;
+ _anisoNormal = iAnisoNormal;
+ _anisoCurvature = iAnisoCurvature;
+ _carricatureFactor = iCarricatureFactor;
+ _factorPoint = iFactorPoint;
+ _anisoPoint = iAnisoPoint;
+}
+
+int SmoothingShader::shade(Stroke &ioStroke) const
+{
+ // cerr << " Smoothing a stroke " << endl;
+
+ Smoother smoother(ioStroke);
+ smoother.smooth(_nbIterations, _factorPoint, _factorCurvature, _factorCurvatureDifference, _anisoPoint,
+ _anisoNormal, _anisoCurvature, _carricatureFactor);
+ return 0;
+}
+
+// SMOOTHER
+////////////////////////////
+
+Smoother::Smoother(Stroke &ioStroke)
+{
+ _stroke = &ioStroke;
+
+ _nbVertices = ioStroke.vertices_size();
+ _vertex = new Vec2r[_nbVertices];
+ _curvature = new real[_nbVertices];
+ _normal = new Vec2r[_nbVertices];
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int i = 0;
+ for (v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd(); v != vend; ++v, ++i) {
+ _vertex[i] = (v)->getPoint();
+ }
+ Vec2r vec_tmp(_vertex[0] - _vertex[_nbVertices - 1]);
+ _isClosedCurve = (vec_tmp.norm() < M_EPSILON);
+
+ _safeTest = (_nbVertices > 4);
+}
+
+void Smoother::smooth(int nbIteration, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference,
+ real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real iCarricatureFactor)
+{
+ _factorCurvature = ifactorCurvature;
+ _factorCurvatureDifference = iFactorCurvatureDifference;
+ _anisoNormal = iAnisoNormal;
+ _anisoCurvature = iAnisoCurvature;
+ _carricatureFactor = iCarricatureFactor;
+ _factorPoint = iFactorPoint;
+ _anisoPoint = iAnisoPoint;
+
+ for (int i = 0; i < nbIteration; ++i)
+ iteration ();
+ copyVertices();
+}
+
+static real edgeStopping(real x, real sigma)
+{
+ if (sigma == 0.0)
+ return 1.0;
+ return exp(-x * x / (sigma * sigma));
+}
+
+void Smoother::iteration()
+{
+ computeCurvature();
+ for (int i = 1; i < (_nbVertices - 1); ++i) {
+ real motionNormal = _factorCurvature * _curvature[i] * edgeStopping(_curvature[i], _anisoNormal);
+
+ real diffC1 = _curvature[i] - _curvature[i - 1];
+ real diffC2 = _curvature[i] - _curvature[i + 1];
+ real motionCurvature = edgeStopping(diffC1, _anisoCurvature) * diffC1 +
+ edgeStopping(diffC2, _anisoCurvature) * diffC2; //_factorCurvatureDifference;
+ motionCurvature *= _factorCurvatureDifference;
+ //motionCurvature = _factorCurvatureDifference * (diffC1 + diffC2);
+ if (_safeTest)
+ _vertex[i] = Vec2r(_vertex[i] + (motionNormal + motionCurvature) * _normal[i]);
+ Vec2r v1(_vertex[i - 1] - _vertex[i]);
+ Vec2r v2(_vertex[i + 1] - _vertex[i]);
+ real d1 = v1.norm();
+ real d2 = v2.norm();
+ _vertex[i] = Vec2r(_vertex[i] +
+ _factorPoint * edgeStopping(d2, _anisoPoint) * (_vertex[i - 1] - _vertex[i]) +
+ _factorPoint * edgeStopping(d1, _anisoPoint) * (_vertex[i + 1] - _vertex[i]));
+ }
+
+ if (_isClosedCurve) {
+ real motionNormal = _factorCurvature * _curvature[0] * edgeStopping(_curvature[0], _anisoNormal);
+
+ real diffC1 = _curvature[0] - _curvature[_nbVertices - 2];
+ real diffC2 = _curvature[0] - _curvature[1];
+ real motionCurvature = edgeStopping(diffC1, _anisoCurvature) * diffC1 +
+ edgeStopping(diffC2, _anisoCurvature) * diffC2; //_factorCurvatureDifference;
+ motionCurvature *= _factorCurvatureDifference;
+ //motionCurvature = _factorCurvatureDifference * (diffC1 + diffC2);
+ _vertex[0] = Vec2r(_vertex[0] + (motionNormal + motionCurvature) * _normal[0]);
+ _vertex[_nbVertices - 1] = _vertex[0];
+ }
+}
+
+
+void Smoother::computeCurvature()
+{
+ int i;
+ Vec2r BA, BC, normalCurvature;
+ for (i = 1; i < (_nbVertices - 1); ++i) {
+ BA = _vertex[i - 1] - _vertex[i];
+ BC = _vertex[i + 1] - _vertex[i];
+ real lba = BA.norm(), lbc = BC.norm();
+ BA.normalizeSafe();
+ BC.normalizeSafe();
+ normalCurvature = BA + BC;
+
+ _normal[i] = Vec2r(-(BC - BA)[1], (BC - BA)[0]);
+ _normal[i].normalizeSafe();
+
+ _curvature[i] = normalCurvature * _normal[i];
+ if (lba + lbc > M_EPSILON)
+ _curvature[i] /= (0.5 * lba + lbc);
+ }
+ _curvature[0] = _curvature[1];
+ _curvature[_nbVertices - 1] = _curvature[_nbVertices - 2];
+ Vec2r di(_vertex[1] - _vertex[0]);
+ _normal[0] = Vec2r(-di[1], di[0]);
+ _normal[0].normalizeSafe();
+ di = _vertex[_nbVertices - 1] - _vertex[_nbVertices - 2];
+ _normal[_nbVertices - 1] = Vec2r(-di[1], di[0]);
+ _normal[_nbVertices - 1].normalizeSafe();
+
+ if (_isClosedCurve) {
+ BA = _vertex[_nbVertices - 2] - _vertex[0];
+ BC = _vertex[1] - _vertex[0];
+ real lba = BA.norm(), lbc = BC.norm();
+ BA.normalizeSafe();
+ BC.normalizeSafe();
+ normalCurvature = BA + BC;
+
+ _normal[i] = Vec2r(-(BC - BA)[1], (BC - BA)[0]);
+ _normal[i].normalizeSafe();
+
+ _curvature[i] = normalCurvature * _normal[i];
+ if (lba + lbc > M_EPSILON)
+ _curvature[i] /= (0.5 * lba + lbc);
+
+ _normal[_nbVertices - 1] = _normal[0];
+ _curvature[_nbVertices - 1] = _curvature[0];
+ }
+}
+
+void Smoother::copyVertices()
+{
+ int i = 0;
+ StrokeInternal::StrokeVertexIterator v, vend;
+ for (v = _stroke->strokeVerticesBegin(), vend = _stroke->strokeVerticesEnd(); v != vend; ++v) {
+ const Vec2r p0((v)->getPoint());
+ const Vec2r p1(_vertex[i]);
+ Vec2r p(p0 + _carricatureFactor * (p1 - p0));
+
+ (v)->setPoint(p[0], p[1]);
+ ++i;
+ }
+}
+
+#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
diff --git a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h
new file mode 100644
index 00000000000..a957a3f7155
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h
@@ -0,0 +1,226 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_ADVANCED_STROKE_SHADERS_H__
+#define __FREESTYLE_ADVANCED_STROKE_SHADERS_H__
+
+/** \file blender/freestyle/intern/stroke/AdvancedStrokeShaders.h
+ * \ingroup freestyle
+ * \brief Fredo's stroke shaders
+ * \author Fredo Durand
+ * \date 17/12/2002
+ */
+
+#include "BasicStrokeShaders.h"
+
+/*! [ Thickness Shader ].
+ * Assigns thicknesses to the stroke vertices so that the stroke looks like made with a calligraphic tool.
+ * i.e. The stroke will be the thickest in a main direction, the thinest in the direction perpendicular to this one,
+ * and an interpolation inbetween.
+ */
+class LIB_STROKE_EXPORT CalligraphicShader : public StrokeShader
+{
+public:
+ /*! Builds the shader.
+ * \param iMinThickness
+ * The minimum thickness in the direction perpandicular to the main direction.
+ * \param iMaxThickness
+ * The maximum thickness in the main direction.
+ * \param iOrientation
+ * The 2D vector giving the main direction.
+ * \param clamp
+ * Tells ???
+ */
+ CalligraphicShader(real iMinThickness, real iMaxThickness, const Vec2f &iOrientation, bool clamp);
+
+ /*! Destructor. */
+ virtual ~CalligraphicShader() {}
+
+ /*! The shading method */
+ virtual int shade(Stroke &ioStroke) const;
+
+protected:
+ real _maxThickness;
+ real _minThickness;
+ Vec2f _orientation;
+ bool _clamp;
+};
+
+/*! [ Geometry Shader ].
+ * Spatial Noise stroke shader.
+ * Moves the vertices to make the stroke more noisy.
+ * @see \htmlonly <a href=noise/noise.html>noise/noise.html</a> \endhtmlonly
+ */
+class LIB_STROKE_EXPORT SpatialNoiseShader : public StrokeShader
+{
+public:
+ /*! Builds the shader.
+ * \param iAmount
+ * The amplitude of the noise.
+ * \param ixScale
+ * The noise frequency
+ * \param nbOctave
+ * The number of octaves
+ * \param smooth
+ * If you want the noise to be smooth
+ * \param pureRandom
+ * If you don't want any coherence
+ */
+ SpatialNoiseShader(float iAmount, float ixScale, int nbOctave, bool smooth, bool pureRandom);
+
+ /*! Destructor. */
+ virtual ~SpatialNoiseShader() {}
+
+ /*! The shading method. */
+ virtual int shade(Stroke &ioStroke) const;
+
+protected:
+ float _amount;
+ float _xScale;
+ int _nbOctave;
+ bool _smooth;
+ bool _pureRandom;
+};
+
+/*! [ Geometry Shader ].
+ * Smoothes the stroke.
+ * (Moves the vertices to make the stroke smoother).
+ * Uses curvature flow to converge towards a curve of constant curvature. The diffusion method we use is anisotropic
+ * to prevent the diffusion accross corners.
+ * @see \htmlonly <a href=/smoothing/smoothing.html>smoothing/smoothing.html</a> endhtmlonly
+ */
+class LIB_STROKE_EXPORT SmoothingShader : public StrokeShader
+{
+public:
+ /*! Builds the shader.
+ * \param iNbIteration
+ * The number of iterations. (400)
+ * \param iFactorPoint
+ * 0
+ * \param ifactorCurvature
+ * 0
+ * \param iFactorCurvatureDifference
+ * 0.2
+ * \param iAnisoPoint
+ * 0
+ * \param iAnisNormal
+ * 0
+ * \param iAnisoCurvature
+ * 0
+ * \param icarricatureFactor
+ * 1
+ */
+ SmoothingShader(int iNbIteration, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference,
+ real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real icarricatureFactor);
+
+ /*! Destructor. */
+ virtual ~SmoothingShader() {}
+
+ /*! The shading method. */
+ virtual int shade(Stroke &ioStroke) const;
+
+protected:
+ int _nbIterations;
+ real _factorPoint;
+ real _factorCurvature;
+ real _factorCurvatureDifference;
+ real _anisoPoint;
+ real _anisoNormal;
+ real _anisoCurvature;
+ real _carricatureFactor;
+};
+
+class LIB_STROKE_EXPORT Smoother
+{
+public:
+ Smoother(Stroke &ioStroke);
+
+ virtual ~Smoother() {}
+
+ void smooth(int nbIterations, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference,
+ real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real icarricatureFactor);
+
+ void computeCurvature();
+
+protected:
+ real _factorPoint;
+ real _factorCurvature;
+ real _factorCurvatureDifference;
+ real _anisoPoint;
+ real _anisoNormal;
+ real _anisoCurvature;
+ real _carricatureFactor;
+
+ void iteration();
+ void copyVertices ();
+
+ Stroke *_stroke;
+ int _nbVertices;
+ Vec2r *_vertex;
+ Vec2r *_normal;
+ real *_curvature;
+ bool *_isFixedVertex;
+
+ bool _isClosedCurve;
+ bool _safeTest;
+};
+
+class LIB_STROKE_EXPORT Omitter : public Smoother
+{
+public:
+ Omitter(Stroke &ioStroke);
+
+ virtual ~Omitter() {}
+
+ void omit(real sizeWindow, real thrVari, real thrFlat, real lFlat);
+
+protected:
+ real *_u;
+
+ real _sizeWindow;
+ real _thresholdVariation;
+ real _thresholdFlat;
+ real _lengthFlat;
+};
+
+/*! Omission shader */
+class LIB_STROKE_EXPORT OmissionShader : public StrokeShader
+{
+public:
+ OmissionShader(real sizeWindow, real thrVari, real thrFlat, real lFlat);
+ virtual ~OmissionShader() {}
+
+ virtual int shade(Stroke &ioStroke) const;
+
+protected:
+ real _sizeWindow;
+ real _thresholdVariation;
+ real _thresholdFlat;
+ real _lengthFlat;
+};
+
+#endif // __FREESTYLE_ADVANCED_STROKE_SHADERS_H__
diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp
new file mode 100644
index 00000000000..7aa66841859
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp
@@ -0,0 +1,1137 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/stroke/BasicStrokeShaders.cpp
+ * \ingroup freestyle
+ * \brief Class gathering basic stroke shaders
+ * \author Stephane Grabli
+ * \date 17/12/2002
+ */
+
+#include <fstream>
+
+#include "AdvancedFunctions0D.h"
+#include "AdvancedFunctions1D.h"
+#include "BasicStrokeShaders.h"
+#include "StrokeIO.h"
+#include "StrokeIterators.h"
+#include "StrokeRenderer.h"
+
+#include "../system/PseudoNoise.h"
+#include "../system/RandGen.h"
+#include "../system/StringUtils.h"
+
+#include "../view_map/Functions0D.h"
+#include "../view_map/Functions1D.h"
+
+#include "BKE_global.h"
+
+//soc #include <qimage.h>
+//soc #include <QString>
+
+extern "C" {
+# include "IMB_imbuf.h"
+# include "IMB_imbuf_types.h"
+}
+
+// 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 {
+
+//
+// Thickness modifiers
+//
+//////////////////////////////////////////////////////////
+
+int ConstantThicknessShader::shade(Stroke& stroke) const
+{
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int i = 0;
+ int size = stroke.strokeVerticesSize();
+ for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
+ // XXX What's the use of i here? And is not the thickness always overriden by the last line of the loop?
+ if ((1 == i) || (size - 2 == i))
+ v->attribute().setThickness(_thickness / 4.0, _thickness / 4.0);
+ if ((0 == i) || (size - 1 == i))
+ v->attribute().setThickness(0, 0);
+
+ v->attribute().setThickness(_thickness / 2.0, _thickness / 2.0);
+ }
+ return 0;
+}
+
+int ConstantExternThicknessShader::shade(Stroke& stroke) const
+{
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int i = 0;
+ int size = stroke.strokeVerticesSize();
+ for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
+ // XXX What's the use of i here? And is not the thickness always overriden by the last line of the loop?
+ if ((1 == i) || (size - 2 == i))
+ v->attribute().setThickness(_thickness / 2.0, 0);
+ if ((0 == i) || (size - 1 == i))
+ v->attribute().setThickness(0, 0);
+
+ v->attribute().setThickness(_thickness, 0);
+ }
+ return 0;
+}
+
+int IncreasingThicknessShader::shade(Stroke& stroke) const
+{
+ int n = stroke.strokeVerticesSize() - 1, i;
+ StrokeInternal::StrokeVertexIterator v, vend;
+ for (i = 0, v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd();
+ v != vend;
+ ++v, ++i)
+ {
+ float t;
+ if (i < (float)n / 2.0f)
+ t = (1.0 - (float)i / (float)n) * _ThicknessMin + (float)i / (float)n * _ThicknessMax;
+ else
+ t = (1.0 - (float)i / (float)n) * _ThicknessMax + (float)i / (float)n * _ThicknessMin;
+ v->attribute().setThickness(t / 2.0, t / 2.0);
+ }
+ return 0;
+}
+
+int ConstrainedIncreasingThicknessShader::shade(Stroke& stroke) const
+{
+ float slength = stroke.getLength2D();
+ float maxT = min(_ratio * slength, _ThicknessMax);
+ int n = stroke.strokeVerticesSize() - 1, i;
+ StrokeInternal::StrokeVertexIterator v, vend;
+ for (i = 0, v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd();
+ v != vend;
+ ++v, ++i)
+ {
+ // XXX Why not using an if/else here? Else, if last condition is true, everything else is computed for nothing!
+ float t;
+ if (i < (float)n / 2.0f)
+ t = (1.0 - (float)i / (float)n) * _ThicknessMin + (float)i / (float)n * maxT;
+ else
+ t = (1.0 - (float)i / (float)n) * maxT + (float)i / (float)n * _ThicknessMin;
+ v->attribute().setThickness(t / 2.0, t / 2.0);
+ if (i == n - 1)
+ v->attribute().setThickness(_ThicknessMin / 2.0, _ThicknessMin / 2.0);
+ }
+ return 0;
+}
+
+
+int LengthDependingThicknessShader::shade(Stroke& stroke) const
+{
+ float step = (_maxThickness - _minThickness) / 3.0f;
+ float l = stroke.getLength2D();
+ float thickness = 0.0f;
+ if (l > 300.0f)
+ thickness = _minThickness + 3.0f * step;
+ else if ((l < 300.0f) && (l > 100.0f))
+ thickness = _minThickness + 2.0f * step;
+ else if ((l < 100.0f) && (l > 50.0f))
+ thickness = _minThickness + 1.0f * step;
+ else // else if (l < 50.0f), tsst...
+ thickness = _minThickness;
+
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int i = 0;
+ int size = stroke.strokeVerticesSize();
+ for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
+ // XXX What's the use of i here? And is not the thickness always overriden by the last line of the loop?
+ if ((1 == i) || (size - 2 == i))
+ v->attribute().setThickness(thickness / 4.0, thickness / 4.0);
+ if ((0 == i) || (size - 1 == i))
+ v->attribute().setThickness(0, 0);
+
+ v->attribute().setThickness(thickness / 2.0, thickness / 2.0);
+ }
+ 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()
+{
+ _amplitude = 1.0f;
+ _scale = 1.0f / 2.0f / (float)NB_VALUE_NOISE;
+}
+
+ThicknessNoiseShader::ThicknessNoiseShader(float iAmplitude, float iPeriod) : StrokeShader()
+{
+ _amplitude = iAmplitude;
+ _scale = 1.0f / iPeriod / (float)NB_VALUE_NOISE;
+}
+
+int ThicknessNoiseShader::shade(Stroke& stroke) const
+{
+ StrokeInternal::StrokeVertexIterator v = stroke.strokeVerticesBegin(), vend;
+ real initU1 = v->strokeLength() * real(NB_VALUE_NOISE) + RandGen::drand48() * real(NB_VALUE_NOISE);
+ real initU2 = v->strokeLength() * real(NB_VALUE_NOISE) + RandGen::drand48() * real(NB_VALUE_NOISE);
+
+ real bruit, bruit2;
+ PseudoNoise mynoise, mynoise2;
+ for (vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
+ 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];
+ float l = bruit2 * _amplitude + originalThickness[1];
+ v->attribute().setThickness(r, l);
+ }
+
+ return 0;
+}
+
+//
+// Color shaders
+//
+///////////////////////////////////////////////////////////////////////////////
+
+int ConstantColorShader::shade(Stroke& stroke) const
+{
+ StrokeInternal::StrokeVertexIterator v, vend;
+ for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
+ v->attribute().setColor(_color[0], _color[1], _color[2]);
+ v->attribute().setAlpha(_color[3]);
+ }
+ return 0;
+}
+
+int IncreasingColorShader::shade(Stroke& stroke) const
+{
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int n = stroke.strokeVerticesSize() - 1, yo;
+ float newcolor[4];
+ for (yo = 0, v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd();
+ v != vend;
+ ++v, ++yo)
+ {
+ for (int i = 0; i < 4; ++i) {
+ newcolor[i] = (1.0 - (float) yo / (float)n) * _colorMin[i] + (float)yo / (float)n * _colorMax[i];
+ }
+ v->attribute().setColor(newcolor[0], newcolor[1], newcolor[2]);
+ v->attribute().setAlpha(newcolor[3]);
+ }
+ 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;
+ Functions0D::MaterialF0D fun;
+ StrokeVertex *sv;
+ for (v = stroke.verticesBegin(), vend = stroke.verticesEnd(); v != vend; ++v) {
+ if (fun(v) < 0)
+ return -1;
+ const float *diffuse = fun.result.diffuse();
+ sv = dynamic_cast<StrokeVertex*>(&(*v));
+ sv->attribute().setColor(diffuse[0] * _coefficient, diffuse[1] * _coefficient, diffuse[2] * _coefficient);
+ sv->attribute().setAlpha(diffuse[3]);
+ }
+ 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;
+ _scale = 1.0f / 2.0f / (float)NB_VALUE_NOISE;
+}
+
+ColorNoiseShader::ColorNoiseShader(float iAmplitude, float iPeriod) : StrokeShader()
+{
+ _amplitude = iAmplitude;
+ _scale = 1.0f / iPeriod / (float)NB_VALUE_NOISE;
+}
+
+int ColorNoiseShader::shade(Stroke& stroke) const
+{
+ StrokeInternal::StrokeVertexIterator v = stroke.strokeVerticesBegin(), vend;
+ real initU = v->strokeLength() * real(NB_VALUE_NOISE) + RandGen::drand48() * real(NB_VALUE_NOISE);
+
+ real bruit;
+ PseudoNoise mynoise;
+ for (vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
+ bruit = mynoise.turbulenceSmooth(_scale * v->curvilinearAbscissa() + initU, 2); // 2 : nbOctaves
+ const float *originalColor = v->attribute().getColor();
+ float r = bruit * _amplitude + originalColor[0];
+ float g = bruit * _amplitude + originalColor[1];
+ float b = bruit * _amplitude + originalColor[2];
+ v->attribute().setColor(r, g, b);
+ }
+
+ return 0;
+}
+
+
+//
+// Texture Shaders
+//
+///////////////////////////////////////////////////////////////////////////////
+
+int TextureAssignerShader::shade(Stroke& stroke) const
+{
+#if 0
+ getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::HUMID_MEDIUM);
+ getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::HUMID_MEDIUM);
+ getBrushTextureIndex(TEXTURES_DIR "/brushes/oil.bmp", Stroke::HUMID_MEDIUM);
+ getBrushTextureIndex(TEXTURES_DIR "/brushes/oilnoblend.bmp", Stroke::HUMID_MEDIUM);
+ getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::DRY_MEDIUM);
+ getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::DRY_MEDIUM);
+ getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueDryBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
+ getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
+#endif
+
+ TextureManager *instance = TextureManager::getInstance();
+ if (!instance)
+ return 0;
+ string pathname;
+ Stroke::MediumType mediumType;
+ bool hasTips = false;
+ switch (_textureId) {
+ case 0:
+ //pathname = TextureManager::Options::getBrushesPath() + "/charcoalAlpha.bmp";
+ pathname = "/charcoalAlpha.bmp";
+ mediumType = Stroke::HUMID_MEDIUM;
+ hasTips = false;
+ break;
+ case 1:
+ pathname = "/washbrushAlpha.bmp";
+ mediumType = Stroke::HUMID_MEDIUM;
+ hasTips = true;
+ break;
+ case 2:
+ pathname = "/oil.bmp";
+ mediumType = Stroke::HUMID_MEDIUM;
+ hasTips = true;
+ break;
+ case 3:
+ pathname = "/oilnoblend.bmp";
+ mediumType = Stroke::HUMID_MEDIUM;
+ hasTips = true;
+ break;
+ case 4:
+ pathname = "/charcoalAlpha.bmp";
+ mediumType = Stroke::DRY_MEDIUM;
+ hasTips = false;
+ break;
+ case 5:
+ mediumType = Stroke::DRY_MEDIUM;
+ hasTips = true;
+ break;
+ case 6:
+ pathname = "/opaqueDryBrushAlpha.bmp";
+ mediumType = Stroke::OPAQUE_MEDIUM;
+ hasTips = true;
+ break;
+ case 7:
+ pathname = "/opaqueBrushAlpha.bmp";
+ mediumType = Stroke::OPAQUE_MEDIUM;
+ hasTips = true;
+ break;
+ default:
+ pathname = "/smoothAlpha.bmp";
+ mediumType = Stroke::OPAQUE_MEDIUM;
+ hasTips = false;
+ break;
+ }
+ unsigned int texId = instance->getBrushTextureIndex(pathname, mediumType);
+ stroke.setMediumType(mediumType);
+ stroke.setTips(hasTips);
+ stroke.setTextureId(texId);
+ return 0;
+}
+
+// FIXME
+int StrokeTextureShader::shade(Stroke& stroke) const
+{
+ TextureManager *instance = TextureManager::getInstance();
+ if (!instance)
+ return 0;
+ string pathname = TextureManager::Options::getBrushesPath() + "/" + _texturePath;
+ unsigned int texId = instance->getBrushTextureIndex(pathname, _mediumType);
+ stroke.setMediumType(_mediumType);
+ stroke.setTips(_tips);
+ stroke.setTextureId(texId);
+ return 0;
+}
+
+//
+// Geometry Shaders
+//
+///////////////////////////////////////////////////////////////////////////////
+
+int BackboneStretcherShader::shade(Stroke& stroke) const
+{
+ float l = stroke.getLength2D();
+ if (l <= 1.0e-6)
+ return 0;
+
+ StrokeInternal::StrokeVertexIterator v0 = stroke.strokeVerticesBegin();
+ StrokeInternal::StrokeVertexIterator v1 = v0;
+ ++v1;
+ StrokeInternal::StrokeVertexIterator vn = stroke.strokeVerticesEnd();
+ --vn;
+ StrokeInternal::StrokeVertexIterator vn_1 = vn;
+ --vn_1;
+
+
+ Vec2d first((v0)->x(), (v0)->y());
+ Vec2d last((vn)->x(), (vn)->y());
+
+ Vec2d d1(first - Vec2d((v1)->x(), (v1)->y()));
+ d1.normalize();
+ Vec2d dn(last - Vec2d((vn_1)->x(), (vn_1)->y()));
+ dn.normalize();
+
+ Vec2d newFirst(first + _amount * d1);
+ (v0)->setPoint(newFirst[0], newFirst[1]);
+ Vec2d newLast(last + _amount * dn);
+ (vn)->setPoint(newLast[0], newLast[1]);
+
+ stroke.UpdateLength();
+ return 0;
+}
+
+int SamplingShader::shade(Stroke& stroke) const
+{
+ stroke.Resample(_sampling);
+ stroke.UpdateLength();
+ return 0;
+}
+
+int ExternalContourStretcherShader::shade(Stroke& stroke) const
+{
+ //float l = stroke.getLength2D();
+ Interface0DIterator it;
+ Functions0D::Normal2DF0D fun;
+ StrokeVertex *sv;
+ for (it = stroke.verticesBegin(); !it.isEnd(); ++it) {
+ if (fun(it) < 0)
+ return -1;
+ Vec2f n(fun.result);
+ sv = dynamic_cast<StrokeVertex*>(&(*it));
+ Vec2d newPoint(sv->x() + _amount * n.x(), sv->y() + _amount * n.y());
+ sv->setPoint(newPoint[0], newPoint[1]);
+ }
+ stroke.UpdateLength();
+ 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
+{
+ if (stroke.strokeVerticesSize() < 4)
+ return 0;
+
+ // Build the Bezier curve from this set of data points:
+ vector<Vec2d> data;
+ StrokeInternal::StrokeVertexIterator v = stroke.strokeVerticesBegin(), vend;
+ data.push_back(Vec2d(v->x(), v->y())); //first one
+ StrokeInternal::StrokeVertexIterator previous = v;
+ ++v;
+ for (vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
+ if (!((fabs(v->x() - (previous)->x()) < M_EPSILON) && ((fabs(v->y() - (previous)->y()) < M_EPSILON))))
+ data.push_back(Vec2d(v->x(), v->y()));
+ 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);
+
+ // bad performances are here !!! // FIXME
+ vector<Vec2d> CurveVertices;
+ vector<BezierCurveSegment*>& bsegments = bcurve.segments();
+ vector<BezierCurveSegment*>::iterator s = bsegments.begin(), send;
+ vector<Vec2d>& segmentsVertices = (*s)->vertices();
+ vector<Vec2d>::iterator p, pend;
+ // first point
+ CurveVertices.push_back(segmentsVertices[0]);
+ for (send = bsegments.end(); s != send; ++s) {
+ segmentsVertices = (*s)->vertices();
+ p = segmentsVertices.begin();
+ ++p;
+ for (pend = segmentsVertices.end(); p != pend; ++p) {
+ CurveVertices.push_back((*p));
+ }
+ }
+
+#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
+ float sampling = stroke.ComputeSampling(originalSize);
+ stroke.Resample(sampling);
+#endif
+ stroke.Resample(originalSize);
+ int newsize = stroke.strokeVerticesSize();
+ int nExtraVertex = 0;
+ if (newsize < originalSize) {
+ 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) {
+ cout << "Bezier Shader : Stroke " << stroke.getId() << " have not been resampled" << endl;
+ }
+ }
+ }
+
+ // assigns the new coordinates:
+ p = CurveVertices.begin();
+ 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();
+
+ // Deal with extra vertices:
+ if (nExtraVertex == 0)
+ return 0;
+
+ // nExtraVertex should stay unassigned
+ vector<StrokeAttribute> attributes;
+ vector<StrokeVertex*> verticesToRemove;
+ for (int i = 0; i < nExtraVertex; ++i, ++it, ++n) {
+ verticesToRemove.push_back(&(*it));
+ if (it.isEnd()) {
+ // XXX Shocking! :P Shouldn't we break in this case???
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "fucked up" << endl;
+ }
+ }
+ }
+ for (it = stroke.strokeVerticesBegin(); it != itend; ++it) {
+ attributes.push_back(it->attribute());
+ }
+
+ for (vector<StrokeVertex*>::iterator vr = verticesToRemove.begin(), vrend = verticesToRemove.end();
+ vr != vrend;
+ ++vr)
+ {
+ stroke.RemoveVertex(*vr);
+ }
+
+ vector<StrokeAttribute>::iterator a = attributes.begin(), aend = attributes.end();
+ int index = 0;
+ int index1 = (int)floor((float)originalSize / 2.0);
+ int index2 = index1 + nExtraVertex;
+ for (it = stroke.strokeVerticesBegin(), itend = stroke.strokeVerticesEnd();
+ (it != itend) && (a != aend);
+ ++it)
+ {
+ (it)->setAttribute(*a);
+ if ((index <= index1) || (index > index2))
+ ++a;
+ ++index;
+ }
+ 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
+{
+public:
+ StrokeInternal::StrokeVertexIterator _begin;
+ StrokeInternal::StrokeVertexIterator _last;
+ Vec2d A;
+ Vec2d B;
+ int size;
+ float _error;
+
+ CurvePiece(StrokeInternal::StrokeVertexIterator b, StrokeInternal::StrokeVertexIterator l, int iSize)
+ {
+ _begin = b;
+ _last = l;
+ A = Vec2d((_begin)->x(), (_begin)->y());
+ B = Vec2d((_last)->x(), (_last)->y());
+ size = iSize;
+ }
+
+ float error()
+ {
+ float maxE = 0.0f;
+ for (StrokeInternal::StrokeVertexIterator it = _begin; it != _last; ++it) {
+ Vec2d P(it->x(), it->y());
+ float d = GeomUtils::distPointSegment(P, A, B);
+ if (d > maxE)
+ maxE = d;
+ }
+ _error = maxE;
+ return maxE;
+ }
+
+ //! Subdivides the curve into two pieces.
+ // The first piece is this same object (modified)
+ // The second piece is returned by the method
+ CurvePiece *subdivide()
+ {
+ StrokeInternal::StrokeVertexIterator it = _begin;
+ int ns = size - 1; // number of segments (ns > 1)
+ int ns1 = ns / 2;
+ int ns2 = ns - ns1;
+ for (int i = 0; i < ns1; ++it, ++i);
+
+ CurvePiece *second = new CurvePiece(it, _last, ns2 + 1);
+ size = ns1 + 1;
+ _last = it;
+ B = Vec2d((_last)->x(), (_last)->y());
+ return second;
+ }
+};
+
+int PolygonalizationShader::shade(Stroke& stroke) const
+{
+ vector<CurvePiece*> _pieces;
+ vector<CurvePiece*> _results;
+ vector<CurvePiece*>::iterator cp, cpend;
+
+ // Compute first approx:
+ StrokeInternal::StrokeVertexIterator a = stroke.strokeVerticesBegin();
+ StrokeInternal::StrokeVertexIterator b = stroke.strokeVerticesEnd();
+ --b;
+ int size = stroke.strokeVerticesSize();
+
+ CurvePiece *piece = new CurvePiece(a, b, size);
+ _pieces.push_back(piece);
+
+ while (!_pieces.empty()) {
+ piece = _pieces.back();
+ _pieces.pop_back();
+ if (piece->size > 2 && piece->error() > _error) {
+ CurvePiece *second = piece->subdivide();
+ _pieces.push_back(second);
+ _pieces.push_back(piece);
+ }
+ else {
+ _results.push_back(piece);
+ }
+ }
+
+ // actually modify the geometry for each piece:
+ for (cp = _results.begin(), cpend = _results.end(); cp != cpend; ++cp) {
+ a = (*cp)->_begin;
+ b = (*cp)->_last;
+ Vec2d u = (*cp)->B - (*cp)->A;
+ Vec2d n(u[1], -u[0]);
+ n.normalize();
+ //Vec2d n(0, 0);
+ float offset = ((*cp)->_error);
+ StrokeInternal::StrokeVertexIterator v;
+ for (v = a; v != b; ++v) {
+ v->setPoint((*cp)->A.x() + v->u() * u.x() + n.x() * offset,
+ (*cp)->A.y() + v->u() * u.y() + n.y() * offset);
+ }
+#if 0
+ u.normalize();
+ (*a)->setPoint((*a)->x() - u.x() * 10, (*a)->y() - u.y() * 10);
+#endif
+ }
+ stroke.UpdateLength();
+
+ // delete stuff
+ for (cp = _results.begin(), cpend = _results.end(); cp != cpend; ++cp) {
+ delete (*cp);
+ }
+ _results.clear();
+ return 0;
+}
+
+int GuidingLinesShader::shade(Stroke& stroke) const
+{
+ Functions1D::Normal2DF1D norm_fun;
+ StrokeInternal::StrokeVertexIterator a = stroke.strokeVerticesBegin();
+ StrokeInternal::StrokeVertexIterator b = stroke.strokeVerticesEnd();
+ --b;
+ int size = stroke.strokeVerticesSize();
+ CurvePiece piece(a, b, size);
+
+ Vec2d u = piece.B - piece.A;
+ Vec2f n(u[1], -u[0]);
+ n.normalize();
+ if (norm_fun(stroke) < 0)
+ return -1;
+ Vec2f strokeN(norm_fun.result);
+ if (n * strokeN < 0) {
+ n[0] = -n[0];
+ n[1] = -n[1];
+ }
+ float offset = (piece.error()) / 2.0f * _offset;
+ StrokeInternal::StrokeVertexIterator v, vend;
+ for (v = a, vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
+ v->setPoint(piece.A.x() + v->u() * u.x() + n.x() * offset,
+ piece.A.y() + v->u() * u.y() + n.y() * offset);
+ }
+ stroke.UpdateLength();
+ return 0;
+}
+
+/////////////////////////////////////////
+//
+// Tip Remover
+//
+/////////////////////////////////////////
+
+
+TipRemoverShader::TipRemoverShader(real tipLength) : StrokeShader()
+{
+ _tipLength = tipLength;
+}
+
+int TipRemoverShader::shade(Stroke& stroke) const
+{
+ int originalSize = stroke.strokeVerticesSize();
+
+ if (originalSize < 4)
+ return 0;
+
+ StrokeInternal::StrokeVertexIterator v, vend;
+ vector<StrokeVertex*> verticesToRemove;
+ vector<StrokeAttribute> oldAttributes;
+ for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
+ if ((v->curvilinearAbscissa() < _tipLength) || (v->strokeLength() - v->curvilinearAbscissa() < _tipLength)) {
+ verticesToRemove.push_back(&(*v));
+ }
+ oldAttributes.push_back(v->attribute());
+ }
+
+ if (originalSize - verticesToRemove.size() < 2)
+ return 0;
+
+ vector<StrokeVertex*>::iterator sv, svend;
+ for (sv = verticesToRemove.begin(), svend = verticesToRemove.end(); sv != svend; ++sv) {
+ stroke.RemoveVertex((*sv));
+ }
+
+ // Resample so that our new stroke have the same number of vertices than before
+ stroke.Resample(originalSize);
+
+ if ((int)stroke.strokeVerticesSize() != originalSize) //soc
+ cerr << "Warning: resampling problem" << endl;
+
+ // 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
diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h
new file mode 100644
index 00000000000..97667211729
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h
@@ -0,0 +1,902 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_BASIC_STROKE_SHADERS_H__
+#define __FREESTYLE_BASIC_STROKE_SHADERS_H__
+
+/** \file blender/freestyle/intern/stroke/BasicStrokeShaders.h
+ * \ingroup freestyle
+ * \brief Class gathering basic stroke shaders
+ * \author Stephane Grabli
+ * \date 17/12/2002
+ */
+
+#include <fstream>
+
+#include "Stroke.h"
+#include "StrokeShader.h"
+
+#include "../geometry/Bezier.h"
+#include "../geometry/Geom.h"
+
+using namespace std;
+using namespace Geometry;
+
+namespace StrokeShaders {
+
+//
+// Thickness modifiers
+//
+//////////////////////////////////////////////////////
+
+/*! [ Thickness Shader ].
+ * Assigns an absolute constant thickness to every vertices of the Stroke.
+ */
+class LIB_STROKE_EXPORT ConstantThicknessShader : public StrokeShader
+{
+public:
+ /*! Builds the shader.
+ * \param thickness
+ * The thickness that must be assigned to the stroke.
+ */
+ ConstantThicknessShader(float thickness) : StrokeShader()
+ {
+ _thickness = thickness;
+ }
+
+ /*! Destructor. */
+ virtual ~ConstantThicknessShader() {}
+
+ /*! Returns the string "ConstantThicknessShader".*/
+ virtual string getName() const
+ {
+ return "ConstantThicknessShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+
+private:
+ float _thickness;
+};
+
+/* [ Thickness Shader ].
+ * Assigns an absolute constant external thickness to every vertices of the Stroke. The external thickness of a point
+ * is its thickness from the point to the strip border in the direction pointing outside the object the
+ * Stroke delimitates.
+ */
+class LIB_STROKE_EXPORT ConstantExternThicknessShader : public StrokeShader
+{
+public:
+ ConstantExternThicknessShader(float thickness) : StrokeShader()
+ {
+ _thickness = thickness;
+ }
+
+ virtual ~ConstantExternThicknessShader() {}
+
+ virtual string getName() const
+ {
+ return "ConstantExternThicknessShader";
+ }
+
+ virtual int shade(Stroke& stroke) const;
+
+private:
+ float _thickness;
+};
+
+/*! [ Thickness Shader ].
+ * Assigns thicknesses values such as the thickness increases from a thickness value A to a thickness value B between
+ * the first vertex to the midpoint vertex and then decreases from B to a A between this midpoint vertex
+ * and the last vertex.
+ * The thickness is linearly interpolated from A to B.
+ */
+class LIB_STROKE_EXPORT IncreasingThicknessShader : public StrokeShader
+{
+public:
+ /*! Builds the shader.
+ * \param iThicknessMin
+ * The first thickness value.
+ * \param iThicknessMax
+ * The second thickness value.
+ */
+ IncreasingThicknessShader(float iThicknessMin, float iThicknessMax) : StrokeShader()
+ {
+ _ThicknessMin = iThicknessMin;
+ _ThicknessMax = iThicknessMax;
+ }
+
+ /*! Destructor.*/
+ virtual ~IncreasingThicknessShader() {}
+
+ virtual string getName() const
+ {
+ return "IncreasingThicknessShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+
+private:
+ float _ThicknessMin;
+ float _ThicknessMax;
+};
+
+/*! [ Thickness shader ].
+ * Same as previous but here we allow the user to control the ratio thickness/length so that we don't get
+ * fat short lines
+ */
+class LIB_STROKE_EXPORT ConstrainedIncreasingThicknessShader : public StrokeShader
+{
+private:
+ float _ThicknessMin;
+ float _ThicknessMax;
+ float _ratio;
+
+public:
+ /*! Builds the shader.
+ * \param iThicknessMin
+ * The first thickness value.
+ * \param iThicknessMax
+ * The second thickness value.
+ * \param iRatio
+ * The ration thickness/length we don't want to exceed.
+ */
+ ConstrainedIncreasingThicknessShader(float iThicknessMin, float iThicknessMax, float iRatio) : StrokeShader()
+ {
+ _ThicknessMin = iThicknessMin;
+ _ThicknessMax = iThicknessMax;
+ _ratio = iRatio;
+ }
+
+ /*! Destructor.*/
+ virtual ~ConstrainedIncreasingThicknessShader() {}
+
+ virtual string getName() const
+ {
+ return "ConstrainedIncreasingThicknessShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+};
+
+/* [ Thickness Shader ].
+ * Modifys the thickness in a relative way depending on its length.
+ */
+class LIB_STROKE_EXPORT LengthDependingThicknessShader : public StrokeShader
+{
+private:
+ float _minThickness;
+ float _maxThickness;
+ // We divide the strokes in 4 categories:
+ // l > 300
+ // 100 < l < 300
+ // 50 < l < 100
+ // l < 50
+
+public:
+ LengthDependingThicknessShader(float iMinThickness, float iMaxThickness) : StrokeShader()
+ {
+ _minThickness = iMinThickness;
+ _maxThickness = iMaxThickness;
+ }
+
+ virtual ~LengthDependingThicknessShader() {}
+
+ virtual string getName() const
+ {
+ return "LengthDependingThicknessShader";
+ }
+
+ 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 LIB_STROKE_EXPORT 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.
+ * \see \htmlonly <a href=noise/noise.html>noise/noise.html</a>\endhtmlonly
+ */
+class LIB_STROKE_EXPORT ThicknessNoiseShader : public StrokeShader
+{
+private:
+ float _amplitude;
+ float _scale;
+
+public:
+ ThicknessNoiseShader();
+
+ /*! Builds a Thickness Noise Shader
+ * \param iAmplitude
+ * The amplitude of the noise signal
+ * \param iPeriod
+ * The period of the noise signal
+ */
+ ThicknessNoiseShader(float iAmplitude, float iPeriod);
+
+ virtual string getName() const
+ {
+ return "ThicknessNoiseShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+};
+
+
+//
+// Color shaders
+//
+/////////////////////////////////////////////////////////
+/*! [ Color Shader ].
+ * Assigns a constant color to every vertices of the Stroke.
+ */
+class LIB_STROKE_EXPORT ConstantColorShader : public StrokeShader
+{
+public:
+ /*! Builds the shader from a user-specified color.
+ * \param iR
+ * The red component
+ * \param iG
+ * The green component
+ * \param iB
+ * The blue component
+ * \param iAlpha
+ * The alpha value
+ */
+ ConstantColorShader(float iR, float iG, float iB, float iAlpha = 1.0f) : StrokeShader()
+ {
+ _color[0] = iR;
+ _color[1] = iG;
+ _color[2] = iB;
+ _color[3] = iAlpha;
+ }
+
+ virtual string getName() const
+ {
+ return "ConstantColorShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+
+private:
+ float _color[4];
+};
+
+/*! [ Color Shader ].
+ * Assigns a varying color to the stroke.
+ * The user specifies 2 colors A and B. The stroke color will change linearly from A to B between the
+ * first and the last vertex.
+ */
+class LIB_STROKE_EXPORT IncreasingColorShader : public StrokeShader
+{
+private:
+ float _colorMin[4];
+ float _colorMax[4];
+
+public:
+ /*! Builds the shader from 2 user-specified colors.
+ * \param iRm
+ * The first color red component
+ * \param iGm
+ * The first color green component
+ * \param iBm
+ * The first color blue component
+ * \param iAlpham
+ * The first color alpha value
+ * \param iRM
+ * The second color red component
+ * \param iGM
+ * The second color green component
+ * \param iBM
+ * The second color blue component
+ * \param iAlphaM
+ * The second color alpha value
+ */
+ IncreasingColorShader(float iRm, float iGm, float iBm, float iAlpham,
+ float iRM, float iGM, float iBM, float iAlphaM)
+ : StrokeShader()
+ {
+ _colorMin[0] = iRm;
+ _colorMin[1] = iGm;
+ _colorMin[2] = iBm;
+ _colorMin[3] = iAlpham;
+
+ _colorMax[0] = iRM;
+ _colorMax[1] = iGM;
+ _colorMax[2] = iBM;
+ _colorMax[3] = iAlphaM;
+ }
+
+ virtual string getName() const
+ {
+ return "IncreasingColorShader";
+ }
+
+ /*! The shading method. */
+ 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 LIB_STROKE_EXPORT 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)
+ */
+class LIB_STROKE_EXPORT MaterialColorShader : public StrokeShader
+{
+private:
+ float _coefficient;
+
+public:
+ MaterialColorShader(float coeff = 1.0f) : StrokeShader()
+ {
+ _coefficient = coeff;
+ }
+
+ virtual string getName() const
+ {
+ return "MaterialColorShader";
+ }
+
+ virtual int shade(Stroke& stroke) const;
+};
+
+class LIB_STROKE_EXPORT CalligraphicColorShader : public StrokeShader
+{
+private:
+ 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.
+ */
+class LIB_STROKE_EXPORT ColorNoiseShader : public StrokeShader
+{
+private:
+ float _amplitude;
+ float _scale;
+
+public:
+ ColorNoiseShader();
+
+ /*! Builds a Color Noise Shader
+ * \param iAmplitude
+ * The amplitude of the noise signal
+ * \param iPeriod
+ * The period of the noise signal
+ */
+ ColorNoiseShader(float iAmplitude, float iPeriod);
+
+ virtual string getName() const
+ {
+ return "ColorNoiseShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+};
+
+//
+// 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 LIB_STROKE_EXPORT 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 LIB_STROKE_EXPORT 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
+//
+///////////////////////////////////////////////////////////////////////////////
+/*! [ Geometry Shader ].
+ * Stretches the stroke at its two extremities and following the respective directions: v(1)v(0) and v(n-1)v(n).
+ */
+class LIB_STROKE_EXPORT BackboneStretcherShader : public StrokeShader
+{
+private:
+ float _amount;
+
+public:
+ /*! Builds the shader.
+ * \param iAmount
+ * The stretching amount value.
+ */
+ BackboneStretcherShader(float iAmount = 2.0f) : StrokeShader()
+ {
+ _amount = iAmount;
+ }
+
+ virtual string getName() const
+ {
+ return "BackboneStretcherShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+};
+
+/*! [ Geometry Shader. ]
+ * Resamples the stroke.
+ * @see Stroke::Resample(float).
+ */
+class LIB_STROKE_EXPORT SamplingShader: public StrokeShader
+{
+private:
+ float _sampling;
+
+public:
+ /*! Builds the shader.
+ * \param sampling
+ * The sampling to use for the stroke resampling
+ */
+ SamplingShader(float sampling) : StrokeShader()
+ {
+ _sampling = sampling;
+ }
+
+ virtual string getName() const
+ {
+ return "SamplingShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+};
+
+
+class LIB_STROKE_EXPORT ExternalContourStretcherShader : public StrokeShader
+{
+private:
+ float _amount;
+
+public:
+ ExternalContourStretcherShader(float iAmount = 2.0f) : StrokeShader()
+ {
+ _amount = iAmount;
+ }
+
+ virtual string getName() const
+ {
+ return "ExternalContourStretcherShader";
+ }
+
+ virtual int shade(Stroke& stroke) const;
+};
+
+// B-Spline stroke shader
+class LIB_STROKE_EXPORT BSplineShader: public StrokeShader
+{
+public:
+ BSplineShader() : StrokeShader() {}
+
+ virtual string getName() const
+ {
+ return "BSplineShader";
+ }
+
+ virtual int shade(Stroke& stroke) const;
+};
+
+
+// Bezier curve stroke shader
+/*! [ Geometry Shader ].
+ * Transforms the stroke backbone geometry so that it corresponds to a Bezier Curve approximation of the
+ * original backbone geometry.
+ * @see \htmlonly <a href=bezier/bezier.html>bezier/bezier.html</a> \endhtmlonly
+ */
+class LIB_STROKE_EXPORT BezierCurveShader : public StrokeShader
+{
+private:
+ float _error;
+
+public:
+ /*! Builds the shader.
+ * \param error
+ * The error we're allowing for the approximation.
+ * This error is the max distance allowed between the new curve and the original geometry.
+ */
+ BezierCurveShader(float error = 4.0) : StrokeShader()
+ {
+ _error = error;
+ }
+
+ virtual string getName() const
+ {
+ return "BezierCurveShader";
+ }
+
+ /*! The shading method */
+ 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 LIB_STROKE_EXPORT 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".
+ * The basic idea is to start from the minimal stroke approximation consisting in a line joining the first vertex
+ * to the last one and to subdivide using the original stroke vertices until a certain error is reached.
+ */
+class LIB_STROKE_EXPORT PolygonalizationShader : public StrokeShader
+{
+private:
+ float _error;
+
+public:
+ /*! Builds the shader.
+ * \param iError
+ * The error we want our polygonal approximation to have with respect to the original geometry.
+ * The smaller, the closer the new stroke to the orinal one.
+ * This error corresponds to the maximum distance between the new stroke and the old one.
+ */
+ PolygonalizationShader(float iError) : StrokeShader()
+ {
+ _error = iError;
+ }
+
+ virtual string getName() const
+ {
+ return "PolygonalizationShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+};
+
+
+/*! [ Geometry Shader ].
+ * Shader to modify the Stroke geometry so that it corresponds to its main direction line.
+ * This shader must be used together with the splitting operator using the curvature criterion.
+ * Indeed, the precision of the approximation will depend on the size of the stroke's pieces.
+ * The bigger the pieces, the rougher the approximation.
+ */
+class LIB_STROKE_EXPORT GuidingLinesShader : public StrokeShader
+{
+private:
+ float _offset;
+
+public:
+ /*! Builds a Guiding Lines shader
+ * \param iOffset
+ * The line that replaces the stroke is initially in the middle of the initial stroke "bbox".
+ * iOffset is the value of the displacement which is applied to this line along its normal.
+ */
+ GuidingLinesShader(float iOffset) : StrokeShader()
+ {
+ _offset = iOffset;
+ }
+
+ virtual string getName() const
+ {
+ return "GuidingLinesShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+};
+
+/*! [ Geometry Shader ].
+ * Removes the stroke's extremities.
+ */
+class LIB_STROKE_EXPORT TipRemoverShader : public StrokeShader
+{
+public:
+ /*! Builds the shader.
+ * \param tipLength
+ * The length of the piece of stroke we want to remove at each extremity.
+ */
+ TipRemoverShader (real tipLength);
+
+ /*! Destructor. */
+ virtual ~TipRemoverShader () {}
+
+ /*! The shading method */
+ virtual string getName() const
+ {
+ return "TipRemoverShader";
+ }
+
+ virtual int shade(Stroke &stroke) const;
+
+protected:
+ real _tipLength;
+};
+
+/*! [ output Shader ].
+ * streams the Stroke
+ */
+class LIB_STROKE_EXPORT 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 LIB_STROKE_EXPORT 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;
+};
+
+} // end of namespace StrokeShaders
+
+#endif // __FREESTYLE_BASIC_STROKE_SHADERS_H__
diff --git a/source/blender/freestyle/intern/stroke/Canvas.cpp b/source/blender/freestyle/intern/stroke/Canvas.cpp
new file mode 100644
index 00000000000..ddcf83b0616
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Canvas.cpp
@@ -0,0 +1,477 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/stroke/Canvas.cpp
+ * \ingroup freestyle
+ * \brief Class to define a canvas designed to draw style modules
+ * \author Stephane Grabli
+ * \date 20/10/2002
+ */
+
+#include <sstream>
+#include <vector>
+
+#include "Canvas.h"
+#include "StrokeRenderer.h"
+#include "StyleModule.h"
+
+#include "../image/Image.h"
+#include "../image/GaussianFilter.h"
+#include "../image/ImagePyramid.h"
+
+#include "../system/FreestyleConfig.h"
+#include "../system/TimeStamp.h"
+#include "../system/PseudoNoise.h"
+
+#include "../view_map/SteerableViewMap.h"
+
+#include "BKE_global.h"
+
+//soc #include <qimage.h>
+//soc #include <QString>
+
+extern "C" {
+# include "IMB_imbuf.h"
+# include "IMB_imbuf_types.h"
+}
+
+using namespace std;
+
+LIB_STROKE_EXPORT
+Canvas *Canvas::_pInstance = 0;
+
+LIB_STROKE_EXPORT
+const char *Canvas::_MapsPath = 0;
+
+Canvas::Canvas()
+{
+ _SelectedFEdge = 0;
+ _pInstance = this;
+ PseudoNoise::init(42);
+ _Renderer = 0;
+ _current_sm = NULL;
+ _steerableViewMap = new SteerableViewMap(NB_STEERABLE_VIEWMAP - 1);
+ _basic = false;
+}
+
+Canvas::Canvas(const Canvas& iBrother)
+{
+ _SelectedFEdge = iBrother._SelectedFEdge;
+ _pInstance = this;
+ PseudoNoise::init(42);
+ _Renderer = iBrother._Renderer;
+ _current_sm = iBrother._current_sm;
+ _steerableViewMap = new SteerableViewMap(*(iBrother._steerableViewMap));
+ _basic = iBrother._basic;
+}
+
+Canvas::~Canvas()
+{
+ _pInstance = 0;
+
+ Clear();
+ if (_Renderer) {
+ delete _Renderer;
+ _Renderer = 0;
+ }
+ // FIXME: think about an easy control for the maps memory management...
+ if (!_maps.empty()) {
+ for (mapsMap::iterator m = _maps.begin(), mend = _maps.end(); m != mend; ++m) {
+ delete ((*m).second);
+ }
+ _maps.clear();
+ }
+ if (_steerableViewMap)
+ delete _steerableViewMap;
+}
+
+void Canvas::preDraw() {}
+
+void Canvas::Draw()
+{
+ if (_StyleModules.empty())
+ return;
+ preDraw();
+ TimeStamp *timestamp = TimeStamp::instance();
+
+ for (unsigned int i = 0; i < _StyleModules.size(); ++i) {
+ _current_sm = _StyleModules[i];
+
+ if (i < _Layers.size() && _Layers[i])
+ delete _Layers[i];
+
+ _Layers[i] = _StyleModules[i]->execute();
+ if (!_Layers[i])
+ continue;
+
+ stroke_count += _Layers[i]->strokes_size();
+
+ timestamp->increment();
+ }
+ postDraw();
+}
+
+void Canvas::postDraw()
+{
+ update();
+}
+
+void Canvas::Clear()
+{
+ if (!_Layers.empty()) {
+ for (deque<StrokeLayer*>::iterator sl = _Layers.begin(), slend = _Layers.end(); sl != slend; ++sl) {
+ if (*sl)
+ delete (*sl);
+ }
+ _Layers.clear();
+ }
+
+ if (!_StyleModules.empty()) {
+ for (deque<StyleModule*>::iterator s = _StyleModules.begin(), send = _StyleModules.end(); s != send; ++s) {
+ if (*s) {
+ (*s)->close();
+ delete (*s);
+ }
+ }
+ _StyleModules.clear();
+ }
+ if (_steerableViewMap)
+ _steerableViewMap->Reset();
+
+ stroke_count = 0;
+}
+
+void Canvas::Erase()
+{
+ if (!_Layers.empty()) {
+ for (deque<StrokeLayer*>::iterator sl = _Layers.begin(), slend = _Layers.end(); sl != slend; ++sl) {
+ if (*sl)
+ (*sl)->clear();
+ }
+ }
+ if (_steerableViewMap)
+ _steerableViewMap->Reset();
+ update();
+
+ stroke_count = 0;
+}
+
+void Canvas::PushBackStyleModule(StyleModule *iStyleModule)
+{
+ StrokeLayer *layer = new StrokeLayer();
+ _StyleModules.push_back(iStyleModule);
+ _Layers.push_back(layer);
+}
+
+void Canvas::InsertStyleModule(unsigned index, StyleModule *iStyleModule)
+{
+ unsigned size = _StyleModules.size();
+ StrokeLayer *layer = new StrokeLayer();
+ if ((_StyleModules.empty()) || (index == size)) {
+ _StyleModules.push_back(iStyleModule);
+ _Layers.push_back(layer);
+ return;
+ }
+ _StyleModules.insert(_StyleModules.begin() + index, iStyleModule);
+ _Layers.insert(_Layers.begin() + index, layer);
+}
+
+void Canvas::RemoveStyleModule(unsigned index)
+{
+ unsigned int i = 0;
+ if (!_StyleModules.empty()) {
+ for (deque<StyleModule*>::iterator s = _StyleModules.begin(), send = _StyleModules.end();
+ s != send;
+ ++s, ++i)
+ {
+ if (i == index) {
+ // remove shader
+ if (*s)
+ delete *s;
+ _StyleModules.erase(s);
+ break;
+ }
+ }
+ }
+
+ if (!_Layers.empty()) {
+ i = 0;
+ for (deque<StrokeLayer*>::iterator sl = _Layers.begin(), slend = _Layers.end();
+ sl != slend;
+ ++sl, ++i)
+ {
+ if (i == index) {
+ // remove layer
+ if (*sl)
+ delete *sl;
+ _Layers.erase(sl);
+ break;
+ }
+ }
+ }
+}
+
+void Canvas::SwapStyleModules(unsigned i1, unsigned i2)
+{
+ StyleModule *tmp;
+ tmp = _StyleModules[i1];
+ _StyleModules[i1] = _StyleModules[i2];
+ _StyleModules[i2] = tmp;
+
+ StrokeLayer *tmp2;
+ tmp2 = _Layers[i1];
+ _Layers[i1] = _Layers[i2];
+ _Layers[i2] = tmp2;
+}
+
+void Canvas::ReplaceStyleModule(unsigned index, StyleModule *iStyleModule)
+{
+ unsigned i = 0;
+ for (deque<StyleModule*>::iterator s = _StyleModules.begin(), send = _StyleModules.end(); s != send; ++s, ++i) {
+ if (i == index) {
+ if (*s)
+ delete *s;
+ *s = iStyleModule;
+ break;
+ }
+ }
+}
+
+void Canvas::setVisible(unsigned index, bool iVisible)
+{
+ _StyleModules[index]->setDisplayed(iVisible);
+}
+
+void Canvas::setModified(unsigned index, bool iMod)
+{
+ _StyleModules[index]->setModified(iMod);
+}
+
+void Canvas::resetModified(bool iMod/* = false */)
+{
+ unsigned int size = _StyleModules.size();
+ for (unsigned int i = 0; i < size; ++i)
+ setModified(i, iMod);
+}
+
+void Canvas::causalStyleModules(vector<unsigned>& vec, unsigned index)
+{
+ unsigned int size = _StyleModules.size();
+
+ for (unsigned int i = index; i < size; ++i) {
+ if (_StyleModules[i]->getCausal())
+ vec.push_back(i);
+ }
+}
+
+void Canvas::Render(const StrokeRenderer *iRenderer)
+{
+ for (unsigned int i = 0; i < _StyleModules.size(); ++i) {
+ if (!_StyleModules[i]->getDisplayed() || !_Layers[i])
+ continue;
+ _Layers[i]->Render(iRenderer);
+ }
+}
+
+void Canvas::RenderBasic(const StrokeRenderer *iRenderer)
+{
+ for (unsigned int i = 0; i < _StyleModules.size(); ++i) {
+ if (!_StyleModules[i]->getDisplayed() || !_Layers[i])
+ continue;
+ _Layers[i]->RenderBasic(iRenderer);
+ }
+}
+
+void Canvas::loadMap(const char *iFileName, const char *iMapName, unsigned int iNbLevels, float iSigma)
+{
+ // check whether this map was already loaded:
+ if (!_maps.empty()) {
+ mapsMap::iterator m = _maps.find(iMapName);
+ if (m != _maps.end()) {
+ // lazy check for size changes
+ ImagePyramid *pyramid = (*m).second;
+ if ((pyramid->width() != width()) || (pyramid->height() != height())) {
+ delete pyramid;
+ }
+ else {
+ return;
+ }
+ }
+ }
+
+ string filePath;
+ if (_MapsPath) {
+ filePath = _MapsPath;
+ filePath += iFileName;
+ }
+ else {
+ filePath = iFileName;
+ }
+
+#if 0 //soc
+ QImage *qimg;
+ QImage newMap(filePath.c_str());
+ if (newMap.isNull()) {
+ cerr << "Could not load image file " << filePath << endl;
+ return;
+ }
+ qimg = &newMap;
+#endif
+ /* OCIO_TODO: support different input color space */
+ ImBuf *qimg = IMB_loadiffname(filePath.c_str(), 0, NULL);
+ if (qimg == 0) {
+ cerr << "Could not load image file " << filePath << endl;
+ return;
+ }
+
+#if 0 // soc
+ // resize
+ QImage scaledImg;
+ if ((newMap.width() != width()) || (newMap.height() != height())) {
+ scaledImg = newMap.scaled(width(), height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ qimg = &scaledImg;
+ }
+#endif
+ ImBuf *scaledImg;
+ if ((qimg->x != width()) || (qimg->y != height())) {
+ scaledImg = IMB_dupImBuf(qimg);
+ IMB_scaleImBuf(scaledImg, width(), height());
+ }
+
+
+ // deal with color image
+#if 0
+ if (newMap->depth() != 8) {
+ int w = newMap->width();
+ int h = newMap->height();
+ QImage *tmp = new QImage(w, h, 8);
+ for (unsigned int y = 0; y < h; ++y) {
+ for (unsigned int x = 0; x < w; ++x) {
+ int c = qGray(newMap->pixel(x, y));
+ tmp->setPixel(x, y, c);
+ }
+ }
+ delete newMap;
+ newMap = tmp;
+ }
+#endif
+
+ int x, y;
+ int w = qimg->x;
+ int h = qimg->y;
+ int rowbytes = w * 4;
+ GrayImage tmp(w, h);
+ char *pix;
+
+ for (y = 0; y < h; ++y) {
+ for (x = 0; x < w; ++x) {
+ pix = (char *)qimg->rect + y * rowbytes + x * 4;
+ float c = (pix[0] * 11 + pix[1] * 16 + pix[2] * 5) / 32;
+ tmp.setPixel(x, y, c);
+ }
+ }
+
+#if 0
+ GrayImage blur(w, h);
+ GaussianFilter gf(4.0f);
+ //int bound = gf.getBound();
+ for (y = 0; y < h; ++y) {
+ for (x = 0; x < w; ++x) {
+ int c = gf.getSmoothedPixel<GrayImage>(&tmp, x, y);
+ blur.setPixel(x, y, c);
+ }
+ }
+#endif
+
+ GaussianPyramid *pyramid = new GaussianPyramid(tmp, iNbLevels, iSigma);
+ int ow = pyramid->width(0);
+ int oh = pyramid->height(0);
+ string base(iMapName); //soc
+ for (int i = 0; i < pyramid->getNumberOfLevels(); ++i) {
+ // save each image:
+#if 0
+ w = pyramid.width(i);
+ h = pyramid.height(i);
+#endif
+
+ //soc QImage qtmp(ow, oh, QImage::Format_RGB32);
+ ImBuf *qtmp = IMB_allocImBuf(ow, oh, 32, IB_rect);
+
+ //int k = (1 << i);
+ for (y = 0; y < oh; ++y) {
+ for (x = 0; x < ow; ++x) {
+ int c = pyramid->pixel(x, y, i); // 255 * pyramid->pixel(x, y, i);
+ //soc qtmp.setPixel(x, y, qRgb(c, c, c));
+ pix = (char *)qtmp->rect + y * rowbytes + x * 4;
+ pix[0] = pix[1] = pix[2] = c;
+ }
+ }
+ //soc qtmp.save(base + QString::number(i) + ".bmp", "BMP");
+ stringstream filename;
+ filename << base;
+ filename << i << ".bmp";
+ qtmp->ftype = BMP;
+ IMB_saveiff(qtmp, const_cast<char *>(filename.str().c_str()), 0);
+ }
+
+#if 0
+ QImage *qtmp = new QImage(w, h, 32);
+ for (y = 0; y < h; ++y) {
+ for (x = 0; x < w; ++x) {
+ int c = (int)blur.pixel(x, y);
+ qtmp->setPixel(x, y, qRgb(c, c, c));
+ }
+ }
+ delete newMap;
+ newMap = qtmp;
+#endif
+
+ _maps[iMapName] = pyramid;
+ //newMap->save("toto.bmp", "BMP");
+}
+
+float Canvas::readMapPixel(const char *iMapName, int level, int x, int y)
+{
+ if (_maps.empty()) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "readMapPixel warning: no map was loaded "<< endl;
+ }
+ return -1;
+ }
+ mapsMap::iterator m = _maps.find(iMapName);
+ if (m == _maps.end()) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "readMapPixel warning: no map was loaded with the name " << iMapName << endl;
+ }
+ return -1;
+ }
+ ImagePyramid *pyramid = (*m).second;
+ if ((x < 0) || (x >= pyramid->width()) || (y < 0) || (y >= pyramid->height()))
+ return 0;
+
+ return pyramid->pixel(x, height() - 1 - y, level);
+}
diff --git a/source/blender/freestyle/intern/stroke/Canvas.h b/source/blender/freestyle/intern/stroke/Canvas.h
new file mode 100644
index 00000000000..a583381599f
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Canvas.h
@@ -0,0 +1,249 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_CANVAS_H__
+#define __FREESTYLE_CANVAS_H__
+
+/** \file blender/freestyle/intern/stroke/Canvas.h
+ * \ingroup freestyle
+ * \brief Class to define a canvas designed to draw style modules
+ * \author Stephane Grabli
+ * \date 20/10/2002
+ */
+
+#include <cstring>
+#include <deque>
+#include <map>
+#include <vector>
+
+#include "StrokeLayer.h"
+
+#include "../geometry/BBox.h"
+#include "../geometry/Geom.h"
+
+#include "../system/FreestyleConfig.h"
+
+using namespace Geometry;
+
+struct ltstr
+{
+ bool operator()(const char *s1, const char *s2) const
+ {
+ return strcmp(s1, s2) < 0;
+ }
+};
+
+class InformationMap;
+class StrokeRenderer;
+class ViewMap;
+class ViewEdge;
+class FEdge;
+class RGBImage;
+class GrayImage;
+class QImage;
+class ImagePyramid;
+class SteerableViewMap;
+class StyleModule;
+
+/*! Class to define the canvas on which strokes are drawn.
+ * It's used to store state information about the drawing.
+ */
+class LIB_STROKE_EXPORT Canvas
+{
+public:
+ /*! Returns a pointer on the Canvas instance */
+ static Canvas *getInstance()
+ {
+ return _pInstance;
+ }
+
+ typedef std::map<const char *, ImagePyramid *, ltstr> mapsMap;
+ static const int NB_STEERABLE_VIEWMAP = 5;
+
+protected:
+ static Canvas *_pInstance;
+ std::deque<StrokeLayer*> _Layers;
+ std::deque<StyleModule*> _StyleModules;
+ FEdge *_SelectedFEdge;
+
+ StrokeRenderer *_Renderer;
+ StyleModule *_current_sm;
+ mapsMap _maps;
+ static const char *_MapsPath;
+ SteerableViewMap *_steerableViewMap;
+ bool _basic;
+
+public:
+ /* Builds the Canvas */
+ Canvas();
+ /* Copy constructor */
+ Canvas(const Canvas& iBrother);
+ /* Destructor */
+ virtual ~Canvas();
+
+ /* operations that need to be done before a draw */
+ virtual void preDraw();
+
+ /* Draw the canvas using the current shader */
+ virtual void Draw();
+
+ /* operations that need to be done after a draw */
+ virtual void postDraw();
+
+ /* Renders the created strokes */
+ virtual void Render(const StrokeRenderer *iRenderer);
+ /* Basic Renders the created strokes */
+ virtual void RenderBasic(const StrokeRenderer *iRenderer);
+ /* Renders a stroke */
+ virtual void RenderStroke(Stroke *iStroke) = 0;
+
+ /* init the canvas */
+ virtual void init() = 0;
+
+ /* Clears the Canvas (shaders stack, layers stack...) */
+ void Clear();
+
+ /* Erases the layers */
+ virtual void Erase();
+
+ /* Reads a pixel area from the canvas */
+ virtual void readColorPixels(int x, int y, int w, int h, RGBImage& oImage) const = 0;
+ /* Reads a depth pixel area from the canvas */
+ virtual void readDepthPixels(int x, int y, int w, int h, GrayImage& oImage) const = 0;
+
+ /* update the canvas (display) */
+ virtual void update() = 0;
+
+ /* checks whether the canvas is empty or not */
+ bool isEmpty() const
+ {
+ return (_Layers.empty());
+ }
+
+ /* Maps management */
+ /*! Loads an image map. The map will be scaled (without preserving the ratio in order to fit the actual
+ * canvas size.).
+ * The image must be a gray values image...
+ * \param iFileName
+ * The name of the image file
+ * \param iMapName
+ * The name that will be used to access this image
+ * \param iNbLevels
+ * The number of levels in the map pyramid. (default = 4).
+ * If iNbLevels == 0, the complete pyramid is built.
+ */
+ void loadMap(const char *iFileName, const char *iMapName, unsigned iNbLevels = 4, float iSigma = 1.0f);
+
+ /*! Reads a pixel value in a map.
+ * Returns a value between 0 and 1.
+ * \param iMapName
+ * The name of the map
+ * \param level
+ * The level of the pyramid from which the pixel must be read.
+ * \param x
+ * The abscissa of the desired pixel specified in level0 coordinate system. The origin is the lower left corner.
+ * \param y
+ * The ordinate of the desired pixel specified in level0 coordinate system. The origin is the lower left corner.
+ */
+ float readMapPixel(const char *iMapName, int level, int x, int y);
+
+ /*! Sets the steerable viewmap */
+ void loadSteerableViewMap(SteerableViewMap *iSVM)
+ {
+ _steerableViewMap = iSVM;
+ }
+
+ /*! Returns the steerable VM */
+ SteerableViewMap *getSteerableViewMap()
+ {
+ return _steerableViewMap;
+ }
+
+ /*! accessors */
+ inline const FEdge *selectedFEdge() const
+ {
+ return _SelectedFEdge;
+ }
+
+ inline FEdge *selectedFEdge()
+ {
+ return _SelectedFEdge;
+ }
+
+ virtual int width() const = 0;
+ virtual int height() const = 0;
+ virtual BBox<Vec3r> scene3DBBox() const = 0;
+
+ inline const StrokeRenderer *renderer() const
+ {
+ return _Renderer;
+ }
+
+ inline StyleModule *getCurrentStyleModule()
+ {
+ return _current_sm;
+ }
+
+ virtual bool getRecordFlag() const
+ {
+ return false;
+ }
+
+ int stroke_count;
+
+ /*! modifiers */
+ inline void setSelectedFEdge(FEdge *iFEdge)
+ {
+ _SelectedFEdge = iFEdge;
+ }
+
+ /*! inserts a shader at pos index+1 */
+ void PushBackStyleModule(StyleModule *iStyleModule);
+ void InsertStyleModule(unsigned index, StyleModule *iStyleModule);
+ void RemoveStyleModule(unsigned index);
+ void SwapStyleModules(unsigned i1, unsigned i2);
+ void ReplaceStyleModule(unsigned index, StyleModule *iStyleModule);
+ void setVisible(unsigned index, bool iVisible) ;
+
+#if 0
+ inline void setDensityMap(InformationMap<RGBImage> *iMap)
+ {
+ _DensityMap = iMap;
+ }
+#endif
+
+ inline void AddLayer(StrokeLayer *iLayer)
+ {
+ _Layers.push_back(iLayer);
+ }
+
+ void resetModified(bool iMod = false);
+ void causalStyleModules(std::vector<unsigned>& vec, unsigned index = 0);
+ void setModified(unsigned index, bool b);
+};
+
+#endif // __FREESTYLE_CANVAS_H__
diff --git a/source/blender/freestyle/intern/stroke/Chain.cpp b/source/blender/freestyle/intern/stroke/Chain.cpp
new file mode 100644
index 00000000000..68ae8b70003
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Chain.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/stroke/Chain.cpp
+ * \ingroup freestyle
+ * \brief Class to define a chain of viewedges.
+ * \author Stephane Grabli
+ * \date 09/01/2003
+ */
+
+#include "Chain.h"
+
+#include "../view_map/ViewMapAdvancedIterators.h"
+#include "../view_map/ViewMapIterators.h"
+
+void Chain::push_viewedge_back(ViewEdge *iViewEdge, bool orientation)
+{
+ ViewEdge::vertex_iterator v;
+ ViewEdge::vertex_iterator vend;
+ ViewEdge::vertex_iterator vfirst;
+ Vec3r previous, current;
+ if (true == orientation) {
+ v = iViewEdge->vertices_begin();
+ vfirst = v;
+ vend = iViewEdge->vertices_end();
+ }
+ else {
+ v = iViewEdge->vertices_last();
+ vfirst = v;
+ vend = iViewEdge->vertices_end();
+ }
+
+ if (!_Vertices.empty()) {
+ previous = _Vertices.back()->point2d();
+ if (orientation)
+ ++v;
+ else
+ --v;
+ // Ensure the continuity of underlying FEdges
+ CurvePoint *cp = _Vertices.back(); // assumed to be instantiated as new CurvePoint(iSVertex, 0, 0.f);
+ SVertex *sv_first = (*vfirst);
+ FEdge *fe = _fedgeB->duplicate();
+ fe->setVertexB(sv_first);
+ fe->vertexA()->shape()->AddEdge(fe);
+ fe->vertexA()->AddFEdge(fe);
+ fe->vertexB()->AddFEdge(fe);
+ cp->setA(sv_first);
+ }
+ else {
+ previous = (*v)->point2d();
+ }
+ do {
+ current = (*v)->point2d();
+ Curve::push_vertex_back(*v);
+ //_Length += (current - previous).norm();
+ previous = current;
+ if (orientation)
+ ++v;
+ else
+ --v;
+ } while ((v != vend) && (v != vfirst));
+
+ if (v == vfirst) {
+ //Add last one:
+ current = (*v)->point2d();
+ Curve::push_vertex_back(*v);
+ //_Length += (current - previous).norm();
+ }
+
+ _fedgeB = (orientation) ? iViewEdge->fedgeB() : iViewEdge->fedgeA();
+}
+
+void Chain::push_viewedge_front(ViewEdge *iViewEdge, bool orientation)
+{
+ orientation = !orientation;
+ ViewEdge::vertex_iterator v;
+ ViewEdge::vertex_iterator vend;
+ ViewEdge::vertex_iterator vfirst;
+ Vec3r previous, current;
+ if (true == orientation) {
+ v = iViewEdge->vertices_begin();
+ vfirst = v;
+ vend = iViewEdge->vertices_end();
+ }
+ else {
+ v = iViewEdge->vertices_last();
+ vfirst = v;
+ vend = iViewEdge->vertices_end();
+ }
+
+ if (!_Vertices.empty()) {
+ previous = _Vertices.front()->point2d();
+ if (orientation)
+ ++v;
+ else
+ --v;
+ // Ensure the continuity of underlying FEdges
+ CurvePoint *cp = _Vertices.front(); // assumed to be instantiated as new CurvePoint(iSVertex, 0, 0.f);
+ SVertex *sv_last = cp->A();
+ SVertex *sv_curr = (*v);
+ FEdge *fe = (orientation) ? iViewEdge->fedgeA() : iViewEdge->fedgeB();
+ FEdge *fe2 = fe->duplicate();
+ fe2->setVertexA(sv_curr);
+ fe2->setVertexB(sv_last);
+ sv_last->AddFEdge(fe2);
+ sv_curr->AddFEdge(fe2);
+ sv_curr->shape()->AddEdge(fe2);
+ }
+ else {
+ previous = (*v)->point2d();
+ }
+ do {
+ current = (*v)->point2d();
+ Curve::push_vertex_front((*v));
+ //_Length += (current - previous).norm();
+ previous = current;
+ if (orientation)
+ ++v;
+ else
+ --v;
+ } while ((v != vend) && (v != vfirst));
+
+ if (v == vfirst) {
+ //Add last one:
+ current = (*v)->point2d();
+ Curve::push_vertex_front(*v);
+ //_Length += (current - previous).norm();
+ }
+
+ if (!_fedgeB)
+ _fedgeB = (orientation) ? iViewEdge->fedgeB() : iViewEdge->fedgeA();
+}
diff --git a/source/blender/freestyle/intern/stroke/Chain.h b/source/blender/freestyle/intern/stroke/Chain.h
new file mode 100644
index 00000000000..688d55f1f0c
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Chain.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_CHAIN_H__
+#define __FREESTYLE_CHAIN_H__
+
+/** \file blender/freestyle/intern/stroke/Chain.h
+ * \ingroup freestyle
+ * \brief Class to define a chain of viewedges.
+ * \author Stephane Grabli
+ * \date 09/01/2003
+ */
+
+#include "Curve.h"
+
+#include "../view_map/ViewMap.h"
+
+/*! Class to represent a 1D elements issued from the chaining process.
+ * A Chain is the last step before the Stroke and is used in the Splitting and Creation processes.
+ */
+class Chain : public Curve
+{
+protected:
+ // tmp
+ Id *_splittingId;
+ FEdge *_fedgeB; // the last FEdge of the ViewEdge passed to the last call for push_viewedge_back().
+
+public:
+ /*! Defult constructor. */
+ Chain() : Curve()
+ {
+ _splittingId = 0;
+ _fedgeB = 0;
+ }
+
+ /*! Builds a chain from its Id. */
+ Chain(const Id& id) : Curve(id)
+ {
+ _splittingId = 0;
+ _fedgeB = 0;
+ }
+
+ /*! Copy Constructor */
+ Chain(const Chain& iBrother) : Curve(iBrother)
+ {
+ _splittingId = iBrother._splittingId;
+ _fedgeB = iBrother._fedgeB;
+ }
+
+ /*! Destructor. */
+ virtual ~Chain() {
+ // only the last splitted deletes this id
+ if (_splittingId) {
+ if (*_splittingId == _Id)
+ delete _splittingId;
+ }
+ }
+
+ /*! Returns the string "Chain" */
+ virtual string getExactTypeName() const
+ {
+ return "Chain";
+ }
+
+ /*! Adds a ViewEdge at the end of the chain
+ * \param iViewEdge
+ * The ViewEdge that must be added.
+ * \param orientation
+ * The orientation with which this ViewEdge must be processed.
+ */
+ void push_viewedge_back(ViewEdge *iViewEdge, bool orientation);
+
+ /*! Adds a ViewEdge at the beginning of the chain
+ * \param iViewEdge
+ * The ViewEdge that must be added.
+ * \param orientation
+ * The orientation with which this ViewEdge must be processed.
+ */
+ void push_viewedge_front(ViewEdge *iViewEdge, bool orientation);
+
+ inline void setSplittingId(Id *sid)
+ {
+ _splittingId = sid;
+ }
+
+ inline Id *getSplittingId()
+ {
+ return _splittingId;
+ }
+};
+
+#endif // __FREESTYLE_CHAIN_H__
diff --git a/source/blender/freestyle/intern/stroke/ChainingIterators.cpp b/source/blender/freestyle/intern/stroke/ChainingIterators.cpp
new file mode 100644
index 00000000000..ccf944a7fcc
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/ChainingIterators.cpp
@@ -0,0 +1,202 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/stroke/ChainingIterators.cpp
+ * \ingroup freestyle
+ * \brief Chaining iterators
+ * \author Stephane Grabli
+ * \date 01/07/2003
+ */
+
+#include "ChainingIterators.h"
+
+#include "../system/TimeStamp.h"
+
+ViewEdge *AdjacencyIterator::operator*()
+{
+ return (*_internalIterator).first;
+}
+
+bool AdjacencyIterator::isIncoming() const
+{
+ return (*_internalIterator).second;
+}
+
+int AdjacencyIterator::increment()
+{
+ ++_internalIterator;
+ while ((!_internalIterator.isEnd()) && (!isValid((*_internalIterator).first)))
+ ++_internalIterator;
+ return 0;
+}
+
+bool AdjacencyIterator::isValid(ViewEdge *edge)
+{
+ if (_restrictToSelection) {
+ if (edge->getTimeStamp() != TimeStamp::instance()->getTimeStamp())
+ return false;
+ }
+ if (_restrictToUnvisited) {
+ if (edge->getChainingTimeStamp() > TimeStamp::instance()->getTimeStamp())
+ return false;
+ }
+ return true;
+}
+
+int ChainingIterator::increment()
+{
+ _increment = true;
+ ViewVertex *vertex = getVertex();
+ if (!vertex) {
+ _edge = 0;
+ return 0;
+ }
+ AdjacencyIterator it = AdjacencyIterator(vertex, _restrictToSelection, _restrictToUnvisited);
+ if (it.isEnd()) {
+ _edge = 0;
+ return 0;
+ }
+ if (traverse(it) < 0)
+ return -1;
+ _edge = result;
+ if (_edge == 0)
+ return 0;
+ if (_edge->A() == vertex)
+ _orientation = true;
+ else
+ _orientation = false;
+ return 0;
+}
+
+int ChainingIterator::decrement()
+{
+ _increment = false;
+ ViewVertex *vertex = getVertex();
+ if (!vertex) {
+ _edge = 0;
+ return 0;
+ }
+ AdjacencyIterator it = AdjacencyIterator(vertex, _restrictToSelection, _restrictToUnvisited);
+ if (it.isEnd()) {
+ _edge = 0;
+ return 0;
+ }
+ if (traverse(it) < 0)
+ return -1;
+ _edge = result;
+ if (_edge == 0)
+ return 0;
+ if (_edge->B() == vertex)
+ _orientation = true;
+ else
+ _orientation = false;
+ return 0;
+}
+
+//
+// ChainSilhouetteIterators
+//
+///////////////////////////////////////////////////////////
+
+int ChainSilhouetteIterator::traverse(const AdjacencyIterator& ait)
+{
+ AdjacencyIterator it(ait);
+ ViewVertex *nextVertex = getVertex();
+ // we can't get a NULL nextVertex here, it was intercepted before
+ if (nextVertex->getNature() & Nature::T_VERTEX) {
+ TVertex *tvertex = (TVertex *)nextVertex;
+ ViewEdge *mate = (tvertex)->mate(getCurrentEdge());
+ while (!it.isEnd()) {
+ ViewEdge *ve = *it;
+ if (ve == mate) {
+ result = ve;
+ return 0;
+ }
+ ++it;
+ }
+ result = 0;
+ return 0;
+ }
+ if (nextVertex->getNature() & Nature::NON_T_VERTEX) {
+ //soc NonTVertex *nontvertex = (NonTVertex*)nextVertex;
+ ViewEdge *newEdge(0);
+ // we'll try to chain the edges by keeping the same nature...
+ // the preseance order is : SILHOUETTE, BORDER, CREASE, SUGGESTIVE, VALLEY, RIDGE
+ Nature::EdgeNature natures[6] = {
+ Nature::SILHOUETTE,
+ Nature::BORDER,
+ Nature::CREASE,
+ Nature::SUGGESTIVE_CONTOUR,
+ Nature::VALLEY,
+ Nature::RIDGE
+ };
+ for (unsigned int i = 0; i < 6; ++i) {
+ if (getCurrentEdge()->getNature() & natures[i]) {
+ int n = 0;
+ while (!it.isEnd()) {
+ ViewEdge *ve = *it;
+ if (ve->getNature() & natures[i]) {
+ ++n;
+ newEdge = ve;
+ }
+ ++it;
+ }
+ if (n == 1) {
+ result = newEdge;
+ }
+ else {
+ result = 0;
+ }
+ return 0;
+ }
+ }
+ }
+ result = 0;
+ return 0;
+}
+
+int ChainPredicateIterator::traverse(const AdjacencyIterator& ait)
+{
+ AdjacencyIterator it(ait);
+ // Iterates over next edges to see if one of them respects the predicate:
+ while (!it.isEnd()) {
+ ViewEdge *ve = *it;
+ if (_unary_predicate->operator()(*ve) < 0)
+ return -1;
+ if (_unary_predicate->result) {
+ if (_binary_predicate->operator()(*(getCurrentEdge()), *(ve)) < 0)
+ return -1;
+ if (_binary_predicate->result) {
+ result = ve;
+ return 0;
+ }
+ }
+ ++it;
+ }
+ result = 0;
+ return 0;
+}
diff --git a/source/blender/freestyle/intern/stroke/ChainingIterators.h b/source/blender/freestyle/intern/stroke/ChainingIterators.h
new file mode 100644
index 00000000000..522513d09ef
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/ChainingIterators.h
@@ -0,0 +1,407 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_CHAINING_ITERATORS_H__
+#define __FREESTYLE_CHAINING_ITERATORS_H__
+
+/** \file blender/freestyle/intern/stroke/ChainingIterators.h
+ * \ingroup freestyle
+ * \brief Chaining iterators
+ * \author Stephane Grabli
+ * \date 01/07/2003
+ */
+
+#include <iostream>
+
+#include "Predicates1D.h"
+
+#include "../python/Director.h"
+
+#include "../system/Iterator.h" //soc
+
+#include "../view_map/ViewMap.h"
+#include "../view_map/ViewMapIterators.h"
+#include "../view_map/ViewMapAdvancedIterators.h"
+
+//using namespace ViewEdgeInternal;
+
+//
+// Adjacency iterator used in the chaining process
+//
+///////////////////////////////////////////////////////////
+class LIB_STROKE_EXPORT AdjacencyIterator : public Iterator
+{
+protected:
+ ViewVertexInternal::orientedViewEdgeIterator _internalIterator;
+ bool _restrictToSelection;
+ bool _restrictToUnvisited;
+
+public:
+ AdjacencyIterator()
+ {
+ _restrictToSelection = true;
+ _restrictToUnvisited = true;
+ }
+
+ AdjacencyIterator(ViewVertex *iVertex, bool iRestrictToSelection = true, bool iRestrictToUnvisited = true)
+ {
+ _restrictToSelection = iRestrictToSelection;
+ _restrictToUnvisited = iRestrictToUnvisited;
+ _internalIterator = iVertex->edgesBegin();
+ while ((!_internalIterator.isEnd()) && (!isValid((*_internalIterator).first)))
+ ++_internalIterator;
+ }
+
+ AdjacencyIterator(const AdjacencyIterator& iBrother)
+ {
+ _internalIterator = iBrother._internalIterator;
+ _restrictToSelection = iBrother._restrictToSelection;
+ _restrictToUnvisited = iBrother._restrictToUnvisited;
+ }
+
+ AdjacencyIterator& operator=(const AdjacencyIterator& iBrother)
+ {
+ _internalIterator = iBrother._internalIterator;
+ _restrictToSelection = iBrother._restrictToSelection;
+ _restrictToUnvisited = iBrother._restrictToUnvisited;
+ return *this;
+ }
+
+ virtual ~AdjacencyIterator() {}
+
+ virtual string getExactTypeName() const
+ {
+ return "AdjacencyIterator";
+ }
+
+ virtual inline bool isEnd() const
+ {
+ return _internalIterator.isEnd();
+ }
+
+ virtual inline bool isBegin() const
+ {
+ return _internalIterator.isBegin();
+ }
+
+ /*! Returns true if the current ViewEdge is is coming towards the iteration vertex. False otherwise. */
+ bool isIncoming() const;
+
+ /*! Returns a *pointer* to the pointed ViewEdge. */
+ virtual ViewEdge *operator*();
+
+ virtual ViewEdge *operator->()
+ {
+ return operator*();
+ }
+
+ virtual AdjacencyIterator& operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ virtual AdjacencyIterator operator++(int)
+ {
+ AdjacencyIterator tmp(*this);
+ increment();
+ return tmp;
+ }
+
+ virtual int increment();
+
+ virtual int decrement()
+ {
+ cerr << "Warning: method decrement() not implemented" << endl;
+ return 0;
+ }
+
+protected:
+ bool isValid(ViewEdge *edge);
+};
+
+//
+// Base class for Chaining Iterators
+//
+///////////////////////////////////////////////////////////
+
+/*! Base class for chaining iterators.
+ * This class is designed to be overloaded in order to describe chaining rules.
+ * It makes the works of chaining rules description easier.
+ * The two main methods that need to overloaded are traverse() and init().
+ * traverse() tells which ViewEdge to follow, among the adjacent ones.
+ * If you specify restriction rules (such as "Chain only ViewEdges of the selection"), they will be included
+ * in the adjacency iterator. (i.e, the adjacent iterator will only stop on "valid" edges).
+ */
+class LIB_STROKE_EXPORT ChainingIterator : public ViewEdgeInternal::ViewEdgeIterator
+{
+protected:
+ bool _restrictToSelection;
+ bool _restrictToUnvisited;
+ bool _increment; //true if we're currently incrementing, false when decrementing
+
+public:
+ ViewEdge *result;
+ PyObject *py_c_it;
+
+ /*! Builds a Chaining Iterator from the first ViewEdge used for iteration and its orientation.
+ * \param iRestrictToSelection
+ * Indicates whether to force the chaining to stay within the set of selected ViewEdges or not.
+ * \param iRestrictToUnvisited
+ * Indicates whether a ViewEdge that has already been chained must be ignored ot not.
+ * \param begin
+ * The ViewEdge from which to start the chain.
+ * \param orientation
+ * The direction to follow to explore the graph. If true, the direction indicated by the first ViewEdge is used.
+ */
+ ChainingIterator(bool iRestrictToSelection = true, bool iRestrictToUnvisited = true, ViewEdge *begin = NULL,
+ bool orientation = true)
+ : ViewEdgeIterator(begin, orientation)
+ {
+ _restrictToSelection = iRestrictToSelection;
+ _restrictToUnvisited = iRestrictToUnvisited;
+ _increment = true;
+ py_c_it = NULL;
+ }
+
+ /*! Copy constructor */
+ ChainingIterator(const ChainingIterator& brother)
+ : ViewEdgeIterator(brother)
+ {
+ _restrictToSelection = brother._restrictToSelection;
+ _restrictToUnvisited = brother._restrictToUnvisited;
+ _increment = brother._increment;
+ py_c_it = brother.py_c_it;
+ }
+
+ /*! Returns the string "ChainingIterator" */
+ virtual string getExactTypeName() const
+ {
+ return "ChainingIterator";
+ }
+
+ /*! Inits the iterator context.
+ * This method is called each time a new chain is started.
+ * It can be used to reset some history information that you might want to keep.
+ */
+ virtual int init()
+ {
+ return Director_BPy_ChainingIterator_init(this);
+ }
+
+ /*! This method iterates over the potential next ViewEdges and returns the one that will be followed next.
+ * returns the next ViewEdge to follow or 0 when the end of the chain is reached.
+ * \param it
+ * The iterator over the ViewEdges adjacent to the end vertex of the current ViewEdge.
+ * The Adjacency iterator reflects the restriction rules by only iterating over the valid ViewEdges.
+ */
+ virtual int traverse(const AdjacencyIterator &it)
+ {
+ return Director_BPy_ChainingIterator_traverse(this, const_cast<AdjacencyIterator &>(it));
+ }
+
+ /* accessors */
+ /*! Returns true if the orientation of the current ViewEdge corresponds to its natural orientation */
+ //inline bool getOrientation() const {}
+
+ /*! Returns the vertex which is the next crossing */
+ inline ViewVertex *getVertex()
+ {
+ if (_increment) {
+ if (_orientation) {
+ return _edge->B();
+ }
+ else {
+ return _edge->A();
+ }
+ }
+ else {
+ if (_orientation) {
+ return _edge->A();
+ }
+ else {
+ return _edge->B();
+ }
+ }
+ }
+
+ /*! Returns true if the current iteration is an incrementation */
+ inline bool isIncrementing() const
+ {
+ return _increment;
+ }
+
+ /* increments.*/
+ virtual int increment();
+ virtual int decrement();
+};
+
+//
+// Chaining iterators definitions
+//
+///////////////////////////////////////////////////////////
+
+/*! A ViewEdge Iterator used to follow ViewEdges the most naturally.
+ * For example, it will follow visible ViewEdges of same nature.
+ * As soon, as the nature or the visibility changes, the iteration stops (by setting the pointed ViewEdge to 0).
+ * In the case of an iteration over a set of ViewEdge that are both Silhouette and Crease, there will be a precedence
+ * of the silhouette over the crease criterion.
+ */
+class LIB_STROKE_EXPORT ChainSilhouetteIterator : public ChainingIterator
+{
+public:
+ /*! Builds a ChainSilhouetteIterator from the first ViewEdge used for iteration and its orientation.
+ * \param iRestrictToSelection
+ * Indicates whether to force the chaining to stay within the set of selected ViewEdges or not.
+ * \param begin
+ * The ViewEdge from where to start the iteration.
+ * \param orientation
+ * If true, we'll look for the next ViewEdge among the ViewEdges that surround the ending ViewVertex of begin.
+ * If false, we'll search over the ViewEdges surrounding the ending ViewVertex of begin.
+ */
+ ChainSilhouetteIterator(bool iRestrictToSelection = true, ViewEdge *begin = NULL, bool orientation = true)
+ : ChainingIterator(iRestrictToSelection, true, begin, orientation)
+ {
+ }
+
+ /*! Copy constructor */
+ ChainSilhouetteIterator(const ChainSilhouetteIterator& brother) : ChainingIterator(brother) {}
+
+ /*! Returns the string "ChainSilhouetteIterator" */
+ virtual string getExactTypeName() const
+ {
+ return "ChainSilhouetteIterator";
+ }
+
+ /*! This method iterates over the potential next ViewEdges and returns the one that will be followed next.
+ * When reaching the end of a chain, 0 is returned.
+ */
+ virtual int traverse(const AdjacencyIterator& it);
+
+ /*! Inits the iterator context */
+ virtual int init()
+ {
+ return 0;
+ }
+};
+
+//
+// ChainPredicateIterator
+//
+///////////////////////////////////////////////////////////
+
+/*! A "generic" user-controlled ViewEdge iterator. This iterator is in particular built from a unary predicate and
+ * a binary predicate.
+ * First, the unary predicate is evaluated for all potential next ViewEdges in order to only keep the ones respecting
+ * a certain constraint.
+ * Then, the binary predicate is evaluated on the current ViewEdge together with each ViewEdge of the previous
+ * selection. The first ViewEdge respecting both the unary predicate and the binary predicate is kept as the next one.
+ * If none of the potential next ViewEdge respects these 2 predicates, 0 is returned.
+ */
+class LIB_STROKE_EXPORT ChainPredicateIterator : public ChainingIterator
+{
+protected:
+ BinaryPredicate1D *_binary_predicate; // the caller is responsible for the deletion of this object
+ UnaryPredicate1D *_unary_predicate; // the caller is responsible for the deletion of this object
+
+public:
+ /*! Builds a ChainPredicateIterator from a starting ViewEdge and its orientation.
+ * \param iRestrictToSelection
+ * Indicates whether to force the chaining to stay within the set of selected ViewEdges or not.
+ * \param iRestrictToUnvisited
+ * Indicates whether a ViewEdge that has already been chained must be ignored ot not.
+ * \param begin
+ * The ViewEdge from where to start the iteration.
+ * \param orientation
+ * If true, we'll look for the next ViewEdge among the ViewEdges that surround the ending ViewVertex of begin.
+ * If false, we'll search over the ViewEdges surrounding the ending ViewVertex of begin.
+ */
+ ChainPredicateIterator(bool iRestrictToSelection = true, bool iRestrictToUnvisited = true, ViewEdge *begin = NULL,
+ bool orientation = true)
+ : ChainingIterator(iRestrictToSelection, iRestrictToUnvisited, begin, orientation)
+ {
+ _binary_predicate = 0;
+ _unary_predicate = 0;
+ }
+
+ /*! Builds a ChainPredicateIterator from a unary predicate, a binary predicate, a starting ViewEdge and
+ * its orientation.
+ * \param iRestrictToSelection
+ * Indicates whether to force the chaining to stay within the set of selected ViewEdges or not.
+ * \param iRestrictToUnvisited
+ * Indicates whether a ViewEdge that has already been chained must be ignored ot not.
+ * \param upred
+ * The unary predicate that the next ViewEdge must satisfy.
+ * \param bpred
+ * The binary predicate that the next ViewEdge must satisfy together with the actual pointed ViewEdge.
+ * \param begin
+ * The ViewEdge from where to start the iteration.
+ * \param orientation
+ * If true, we'll look for the next ViewEdge among the ViewEdges that surround the ending ViewVertex of begin.
+ * If false, we'll search over the ViewEdges surrounding the ending ViewVertex of begin.
+ */
+ ChainPredicateIterator(UnaryPredicate1D& upred, BinaryPredicate1D& bpred, bool iRestrictToSelection = true,
+ bool iRestrictToUnvisited = true, ViewEdge *begin = NULL, bool orientation = true)
+ : ChainingIterator(iRestrictToSelection, iRestrictToUnvisited, begin, orientation)
+ {
+ _unary_predicate = &upred;
+ _binary_predicate = &bpred;
+ }
+
+ /*! Copy constructor */
+ ChainPredicateIterator(const ChainPredicateIterator& brother) : ChainingIterator(brother)
+ {
+ _unary_predicate = brother._unary_predicate;
+ _binary_predicate = brother._binary_predicate;
+ }
+
+ /*! Destructor. */
+ virtual ~ChainPredicateIterator()
+ {
+ _unary_predicate = 0;
+ _binary_predicate = 0;
+ }
+
+ /*! Returns the string "ChainPredicateIterator" */
+ virtual string getExactTypeName() const
+ {
+ return "ChainPredicateIterator";
+ }
+
+ /*! This method iterates over the potential next ViewEdges and returns the one that will be followed next.
+ * When reaching the end of a chain, 0 is returned.
+ */
+ virtual int traverse(const AdjacencyIterator &it);
+
+ /*! Inits the iterator context */
+ virtual int init()
+ {
+ return 0;
+ }
+};
+
+#endif // __FREESTYLE_CHAINING_ITERATORS_H__
diff --git a/source/blender/freestyle/intern/stroke/ContextFunctions.cpp b/source/blender/freestyle/intern/stroke/ContextFunctions.cpp
new file mode 100644
index 00000000000..5dfa212ee83
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/ContextFunctions.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/stroke/ContextFunctions.cpp
+ * \ingroup freestyle
+ * \brief Functions related to context queries
+ * \brief Interface to access the context related information.
+ * \author Stephane Grabli
+ * \date 20/12/2003
+ */
+
+#include "ContextFunctions.h"
+
+#include "../view_map/SteerableViewMap.h"
+
+#include "../system/TimeStamp.h"
+
+namespace ContextFunctions {
+
+unsigned GetTimeStampCF()
+{
+ return TimeStamp::instance()->getTimeStamp();
+}
+
+unsigned GetCanvasWidthCF()
+{
+ return Canvas::getInstance()->width();
+}
+
+unsigned GetCanvasHeightCF()
+{
+ return Canvas::getInstance()->height();
+}
+
+void LoadMapCF(const char *iFileName, const char *iMapName, unsigned iNbLevels, float iSigma)
+{
+ return Canvas::getInstance()->loadMap(iFileName, iMapName, iNbLevels, iSigma);
+}
+
+float ReadMapPixelCF(const char *iMapName, int level, unsigned x, unsigned y)
+{
+ Canvas *canvas = Canvas::getInstance();
+ return canvas->readMapPixel(iMapName, level, x, y);
+}
+
+float ReadCompleteViewMapPixelCF(int level, unsigned x, unsigned y)
+{
+ SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap();
+ return svm->readCompleteViewMapPixel(level, x, y);
+}
+
+float ReadDirectionalViewMapPixelCF(int iOrientation, int level, unsigned x, unsigned y)
+{
+ SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap();
+ return svm->readSteerableViewMapPixel(iOrientation, level, x, y);
+}
+
+FEdge *GetSelectedFEdgeCF()
+{
+ return Canvas::getInstance()->selectedFEdge();
+}
+
+} // ContextFunctions namespace
diff --git a/source/blender/freestyle/intern/stroke/ContextFunctions.h b/source/blender/freestyle/intern/stroke/ContextFunctions.h
new file mode 100644
index 00000000000..0718ebb1d6a
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/ContextFunctions.h
@@ -0,0 +1,120 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_CONTEXT_FUNCTIONS_H__
+#define __FREESTYLE_CONTEXT_FUNCTIONS_H__
+
+/** \file blender/freestyle/intern/stroke/ContextFunctions.h
+ * \ingroup freestyle
+ * \brief Functions related to context queries
+ * \brief Interface to access the context related information.
+ * \author Stephane Grabli
+ * \date 20/12/2003
+ */
+
+#include "Canvas.h"
+
+#include "../image/GaussianFilter.h"
+#include "../image/Image.h"
+
+//
+// Context Functions definitions
+//
+///////////////////////////////////////////////////////////
+/*! namespace containing all the Context related functions */
+namespace ContextFunctions {
+
+// GetTimeStamp
+/*! Returns the system time stamp */
+LIB_STROKE_EXPORT
+unsigned GetTimeStampCF();
+
+// GetCanvasWidth
+/*! Returns the canvas width */
+LIB_STROKE_EXPORT
+unsigned GetCanvasWidthCF();
+
+// GetCanvasHeight
+/*! Returns the canvas width */
+LIB_STROKE_EXPORT
+unsigned GetCanvasHeightCF();
+
+// Load map
+/*! Loads an image map for further reading */
+LIB_STROKE_EXPORT
+void LoadMapCF(const char *iFileName, const char *iMapName, unsigned iNbLevels = 4, float iSigma = 1.0f);
+
+// ReadMapPixel
+/*! Reads a pixel in a user-defined map
+ * \return the floating value stored for that pixel
+ * \param iMapName
+ * The name of the map
+ * \param level
+ * The level of the pyramid in which we wish to read the pixel
+ * \param x
+ * The x-coordinate of the pixel we wish to read. The origin is in the lower-left corner.
+ * \param y
+ * The y-coordinate of the pixel we wish to read. The origin is in the lower-left corner.
+ */
+LIB_STROKE_EXPORT
+float ReadMapPixelCF(const char *iMapName, int level, unsigned x, unsigned y);
+
+// ReadCompleteViewMapPixel
+/*! Reads a pixel in the complete view map
+ * \return the floating value stored for that pixel
+ * \param level
+ * The level of the pyramid in which we wish to read the pixel
+ * \param x
+ * The x-coordinate of the pixel we wish to read. The origin is in the lower-left corner.
+ * \param y
+ * The y-coordinate of the pixel we wish to read. The origin is in the lower-left corner.
+ */
+LIB_STROKE_EXPORT
+float ReadCompleteViewMapPixelCF(int level, unsigned x, unsigned y);
+
+// ReadOrientedViewMapPixel
+/*! Reads a pixel in one of the oriented view map images
+ * \return the floating value stored for that pixel
+ * \param iOrientation
+ * The number telling which orientation we want to check
+ * \param level
+ * The level of the pyramid in which we wish to read the pixel
+ * \param x
+ * The x-coordinate of the pixel we wish to read. The origin is in the lower-left corner.
+ * \param y
+ * The y-coordinate of the pixel we wish to read. The origin is in the lower-left corner.
+ */
+LIB_STROKE_EXPORT
+float ReadDirectionalViewMapPixelCF(int iOrientation, int level, unsigned x, unsigned y);
+
+// DEBUG
+LIB_STROKE_EXPORT
+FEdge *GetSelectedFEdgeCF();
+
+} // end of namespace ContextFunctions
+
+#endif // __FREESTYLE_CONTEXT_FUNCTIONS_H__
diff --git a/source/blender/freestyle/intern/stroke/Curve.cpp b/source/blender/freestyle/intern/stroke/Curve.cpp
new file mode 100644
index 00000000000..0a95771d201
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Curve.cpp
@@ -0,0 +1,932 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/stroke/Curve.cpp
+ * \ingroup freestyle
+ * \brief Class to define a container for curves
+ * \author Stephane Grabli
+ * \date 11/01/2003
+ */
+
+#include "Curve.h"
+#include "CurveAdvancedIterators.h"
+#include "CurveIterators.h"
+
+#include "BKE_global.h"
+
+/**********************************/
+/* */
+/* */
+/* CurvePoint */
+/* */
+/* */
+/**********************************/
+
+CurvePoint::CurvePoint()
+{
+ __A = 0;
+ __B = 0;
+ _t2d = 0;
+}
+
+CurvePoint::CurvePoint(SVertex *iA, SVertex *iB, float t)
+{
+ __A = iA;
+ __B = iB;
+ _t2d = t;
+ if ((iA == 0) && (t == 1.0f)) {
+ _Point2d = __B->point2d();
+ _Point3d = __B->point3d();
+ }
+ else if ((iB == 0) && (t == 0.0f)) {
+ _Point2d = __A->point2d();
+ _Point3d = __A->point3d();
+ }
+ else {
+ _Point2d = __A->point2d() + _t2d * (__B->point2d() - __A->point2d());
+ _Point3d = __A->point3d() + _t2d * (__B->point3d() - __A->point3d());
+ }
+}
+
+CurvePoint::CurvePoint(CurvePoint *iA, CurvePoint *iB, float t3)
+{
+ __A = 0;
+ __B = 0;
+ float t1 = iA->t2d();
+ float t2 = iB->t2d();
+ if ((iA->A() == iB->A()) && (iA->B() == iB->B()) &&
+ (iA->A() != 0) && (iA->B() != 0) && (iB->A() != 0) && (iB->B() != 0))
+ {
+ __A = iA->A();
+ __B = iB->B();
+ _t2d = t1 + t2 * t3 - t1 * t3;
+ }
+ else if ((iA->B() == 0) && (iB->B() == 0)) {
+ __A = iA->A();
+ __B = iB->A();
+ _t2d = t3;
+ }
+ else if ((iA->t2d() == 0) && (iB->t2d() == 0)) {
+ __A = iA->A();
+ __B = iB->A();
+ _t2d = t3;
+ }
+ else if (iA->A() == iB->A()) {
+iA_A_eq_iB_A:
+ if (iA->t2d() == 0) {
+ __A = iB->A();
+ __B = iB->B();
+ _t2d = t3;
+ }
+ else if (iB->t2d() == 0) {
+ __A = iA->A();
+ __B = iA->B();
+ _t2d = t3;
+ }
+ }
+ else if (iA->B() == iB->B()) {
+iA_B_eq_iB_B:
+ if (iA->t2d() == 1) {
+ __A = iB->A();
+ __B = iB->B();
+ _t2d = t3;
+ }
+ else if (iB->t2d() == 1) {
+ __A = iA->A();
+ __B = iA->B();
+ _t2d = t3;
+ }
+ }
+ else if (iA->B() == iB->A()) {
+iA_B_eq_iB_A:
+ if ((iA->t2d() != 1.0f) && (iB->t2d() == 0.0f)) {
+ __A = iA->A();
+ __B = iA->B();
+ _t2d = t1 + t3 - t1 * t3;
+ //_t2d = t3;
+ }
+ else if ((iA->t2d() == 1.0f) && (iB->t2d() != 0.0f)) {
+ __A = iB->A();
+ __B = iB->B();
+ //_t2d = t3;
+ _t2d = t2 * t3;
+ }
+ else if ((iA->getPoint2D() - iA->getPoint2D()).norm() < 1.0e-6) {
+ __A = iB->A();
+ __B = iB->B();
+ //_t2d = t3;
+ _t2d = t2 * t3;
+ }
+ }
+ else if (iA->A() != 0 && iB->A() != 0 && (iA->A()->point3d() - iB->A()->point3d()).norm() < 1.0e-6) {
+ goto iA_A_eq_iB_A;
+ }
+ else if (iA->B() != 0 && iB->B() != 0 && (iA->B()->point3d() - iB->B()->point3d()).norm() < 1.0e-6) {
+ goto iA_B_eq_iB_B;
+ }
+ else if (iA->B() != 0 && iB->A() != 0 && (iA->B()->point3d() - iB->A()->point3d()).norm() < 1.0e-6) {
+ goto iA_B_eq_iB_A;
+ }
+
+ if (!__A || !__B) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("iA A 0x%p p (%f, %f)\n", iA->A(), iA->A()->getPoint2D().x(), iA->A()->getPoint2D().y());
+ printf("iA B 0x%p p (%f, %f)\n", iA->B(), iA->B()->getPoint2D().x(), iA->B()->getPoint2D().y());
+ printf("iB A 0x%p p (%f, %f)\n", iB->A(), iB->A()->getPoint2D().x(), iB->A()->getPoint2D().y());
+ printf("iB B 0x%p p (%f, %f)\n", iB->B(), iB->B()->getPoint2D().x(), iB->B()->getPoint2D().y());
+ printf("iA t2d %f p (%f, %f)\n", iA->t2d(), iA->getPoint2D().x(), iA->getPoint2D().y());
+ printf("iB t2d %f p (%f, %f)\n", iB->t2d(), iB->getPoint2D().x(), iB->getPoint2D().y());
+ }
+ cerr << "Fatal error in CurvePoint::CurvePoint(CurvePoint *iA, CurvePoint *iB, float t3)" << endl;
+ }
+ assert(__A != 0 && __B != 0);
+
+#if 0
+ _Point2d = __A->point2d() + _t2d * (__B->point2d() - __A->point2d());
+ _Point3d = __A->point3d() + _t2d * (__B->point3d() - __A->point3d());
+#endif
+
+ _Point2d = iA->point2d() + t3 * (iB->point2d() - iA->point2d());
+ _Point3d = __A->point3d() + _t2d * (__B->point3d() - __A->point3d());
+}
+
+CurvePoint::CurvePoint(const CurvePoint& iBrother)
+{
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _t2d = iBrother._t2d;
+ _Point2d = iBrother._Point2d;
+ _Point3d = iBrother._Point3d;
+}
+
+CurvePoint& CurvePoint::operator=(const CurvePoint& iBrother)
+{
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _t2d = iBrother._t2d;
+ _Point2d = iBrother._Point2d;
+ _Point3d = iBrother._Point3d;
+ return *this;
+}
+
+
+FEdge *CurvePoint::fedge()
+{
+ if (getNature() & Nature::T_VERTEX)
+ return 0;
+ return __A->fedge();
+}
+
+
+FEdge *CurvePoint::getFEdge(Interface0D& inter)
+{
+ CurvePoint *iVertexB = dynamic_cast<CurvePoint*>(&inter);
+ if (!iVertexB) {
+ cerr << "Warning: CurvePoint::getFEdge() failed to cast the given 0D element to CurvePoint." << endl;
+ return 0;
+ }
+ if (((__A == iVertexB->__A) && (__B == iVertexB->__B)) ||
+ ((__A == iVertexB->__B) && (__B == iVertexB->__A)))
+ {
+ return __A->getFEdge(*__B);
+ }
+ if (__B == 0) {
+ if (iVertexB->__B == 0)
+ return __A->getFEdge(*(iVertexB->__A));
+ else if (iVertexB->__A == __A)
+ return __A->getFEdge(*(iVertexB->__B));
+ else if (iVertexB->__B == __A)
+ return __A->getFEdge(*(iVertexB->__A));
+ }
+ if (iVertexB->__B == 0) {
+ if (iVertexB->__A == __A)
+ return __B->getFEdge(*(iVertexB->__A));
+ else if (iVertexB->__A == __B)
+ return __A->getFEdge(*(iVertexB->__A));
+ }
+ if (__B == iVertexB->__A) {
+ if ((_t2d != 1) && (iVertexB->_t2d == 0))
+ return __A->getFEdge(*__B);
+ if ((_t2d == 1) && (iVertexB->_t2d != 0))
+ return iVertexB->__A->getFEdge(*(iVertexB->__B));
+ }
+ if (__B == iVertexB->__B) {
+ if ((_t2d != 1) && (iVertexB->_t2d == 1))
+ return __A->getFEdge(*__B);
+ if ((_t2d == 1) && (iVertexB->_t2d != 1))
+ return iVertexB->__A->getFEdge(*(iVertexB->__B));
+ }
+ if (__A == iVertexB->__A) {
+ if ((_t2d == 0) && (iVertexB->_t2d != 0))
+ return iVertexB->__A->getFEdge(*(iVertexB->__B));
+ if ((_t2d != 0) && (iVertexB->_t2d == 0))
+ return __A->getFEdge(*__B);
+ }
+ if (__A == iVertexB->__B) {
+ if ((_t2d == 0) && (iVertexB->_t2d != 1))
+ return iVertexB->__A->getFEdge(*(iVertexB->__B));
+ if ((_t2d != 0) && (iVertexB->_t2d == 1))
+ return __A->getFEdge(*__B);
+ }
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("__A 0x%p p (%f, %f)\n", __A, __A->getPoint2D().x(), __A->getPoint2D().y());
+ printf("__B 0x%p p (%f, %f)\n", __B, __B->getPoint2D().x(), __B->getPoint2D().y());
+ printf("iVertexB->A() 0x%p p (%f, %f)\n", iVertexB->A(), iVertexB->A()->getPoint2D().x(),
+ iVertexB->A()->getPoint2D().y());
+ printf("iVertexB->B() 0x%p p (%f, %f)\n", iVertexB->B(), iVertexB->B()->getPoint2D().x(),
+ iVertexB->B()->getPoint2D().y());
+ printf("_t2d %f p (%f, %f)\n", _t2d, getPoint2D().x(), getPoint2D().y());
+ printf("iVertexB->t2d() %f p (%f, %f)\n", iVertexB->t2d(), iVertexB->getPoint2D().x(),
+ iVertexB->getPoint2D().y());
+ }
+#endif
+ cerr << "Warning: CurvePoint::getFEdge() failed." << endl;
+
+ return NULL;
+}
+
+
+Vec3r CurvePoint::normal() const
+{
+ if (__B == 0)
+ return __A->normal();
+ if (__A == 0)
+ return __B->normal();
+ Vec3r Na = __A->normal();
+ if (Exception::getException())
+ Na = Vec3r(0, 0, 0);
+ Vec3r Nb = __B->normal();
+ if (Exception::getException())
+ Nb = Vec3r(0, 0, 0);
+ // compute t3d:
+ real t3d = SilhouetteGeomEngine::ImageToWorldParameter(__A->getFEdge(*__B), _t2d);
+ return ((1 - t3d) * Na + t3d * Nb);
+}
+
+
+#if 0
+Material CurvePoint::material() const
+{
+ if (__A == 0)
+ return __B->material();
+ return __A->material();
+}
+
+Id CurvePoint::shape_id() const
+{
+ if (__A == 0)
+ return __B->shape_id();
+ return __A->shape_id();
+}
+#endif
+
+
+const SShape *CurvePoint::shape() const
+{
+ if (__A == 0)
+ return __B->shape();
+ return __A->shape();
+}
+
+#if 0
+float CurvePoint::shape_importance() const
+{
+ if (__A == 0)
+ return __B->shape_importance();
+ return __A->shape_importance();
+}
+
+
+const unsigned CurvePoint::qi() const
+{
+ if (__A == 0)
+ return __B->qi();
+ if (__B == 0)
+ return __A->qi();
+ return __A->getFEdge(*__B)->qi();
+}
+#endif
+
+occluder_container::const_iterator CurvePoint::occluders_begin() const
+{
+ if (__A == 0)
+ return __B->occluders_begin();
+ if (__B == 0)
+ return __A->occluders_begin();
+ return __A->getFEdge(*__B)->occluders_begin();
+}
+
+occluder_container::const_iterator CurvePoint::occluders_end() const
+{
+ if (__A == 0)
+ return __B->occluders_end();
+ if (__B == 0)
+ return __A->occluders_end();
+ return __A->getFEdge(*__B)->occluders_end();
+}
+
+bool CurvePoint::occluders_empty() const
+{
+ if (__A == 0)
+ return __B->occluders_empty();
+ if (__B == 0)
+ return __A->occluders_empty();
+ return __A->getFEdge(*__B)->occluders_empty();
+}
+
+int CurvePoint::occluders_size() const
+{
+ if (__A == 0)
+ return __B->occluders_size();
+ if (__B == 0)
+ return __A->occluders_size();
+ return __A->getFEdge(*__B)->occluders_size();
+}
+
+const SShape *CurvePoint::occluded_shape() const
+{
+ if (__A == 0)
+ return __B->occluded_shape();
+ if (__B == 0)
+ return __A->occluded_shape();
+ return __A->getFEdge(*__B)->occluded_shape();
+}
+
+const Polygon3r& CurvePoint::occludee() const
+{
+ if (__A == 0)
+ return __B->occludee();
+ if (__B == 0)
+ return __A->occludee();
+ return __A->getFEdge(*__B)->occludee();
+}
+
+const bool CurvePoint::occludee_empty() const
+{
+ if (__A == 0)
+ return __B->occludee_empty();
+ if (__B == 0)
+ return __A->occludee_empty();
+ return __A->getFEdge(*__B)->occludee_empty();
+}
+
+real CurvePoint::z_discontinuity() const
+{
+ if (__A == 0)
+ return __B->z_discontinuity();
+ if (__B == 0)
+ return __A->z_discontinuity();
+ if (__A->getFEdge(*__B) == 0)
+ return 0.0;
+
+ return __A->getFEdge(*__B)->z_discontinuity();
+}
+
+#if 0
+float CurvePoint::local_average_depth() const
+{
+ return local_average_depth_function<CurvePoint >(this);
+}
+
+float CurvePoint::local_depth_variance() const
+{
+ return local_depth_variance_function<CurvePoint >(this);
+}
+
+real CurvePoint::local_average_density(float sigma) const
+{
+ //return local_average_density<CurvePoint >(this);
+ return density_function<CurvePoint >(this);
+}
+
+Vec3r shaded_color() const;
+
+Vec3r CurvePoint::orientation2d() const
+{
+ if (__A == 0)
+ return __B->orientation2d();
+ if (__B == 0)
+ return __A->orientation2d();
+ return __B->point2d() - __A->point2d();
+}
+
+Vec3r CurvePoint::orientation3d() const
+{
+ if (__A == 0)
+ return __B->orientation3d();
+ if (__B == 0)
+ return __A->orientation3d();
+ return __B->point3d() - __A->point3d();
+}
+
+real curvature2d() const
+{
+ return viewedge()->curvature2d((_VertexA->point2d() + _VertexB->point2d()) / 2.0);
+}
+
+Vec3r CurvePoint::curvature2d_as_vector() const
+{
+#if 0
+ Vec3r edgeA = (_FEdges[0])->orientation2d().normalize();
+ Vec3r edgeB = (_FEdges[1])->orientation2d().normalize();
+ return edgeA + edgeB;
+#endif
+ if (__A == 0)
+ return __B->curvature2d_as_vector();
+ if (__B == 0)
+ return __A->curvature2d_as_vector();
+ return ((1 - _t2d) * __A->curvature2d_as_vector() + _t2d * __B->curvature2d_as_vector());
+}
+
+real CurvePoint::curvature2d_as_angle() const
+{
+#if 0
+ Vec3r edgeA = (_FEdges[0])->orientation2d();
+ Vec3r edgeB = (_FEdges[1])->orientation2d();
+ Vec2d N1(-edgeA.y(), edgeA.x());
+ N1.normalize();
+ Vec2d N2(-edgeB.y(), edgeB.x());
+ N2.normalize();
+ return acos((N1 * N2));
+#endif
+ if (__A == 0)
+ return __B->curvature2d_as_angle();
+ if (__B == 0)
+ return __A->curvature2d_as_angle();
+ return ((1 - _t2d) * __A->curvature2d_as_angle() + _t2d * __B->curvature2d_as_angle());
+}
+#endif
+
+real CurvePoint::curvatureFredo() const
+{
+ if (__A == 0)
+ return __B->curvatureFredo();
+ if (__B == 0)
+ return __A->curvatureFredo();
+ return ((1 - _t2d) * __A->curvatureFredo() + _t2d * __B->curvatureFredo());
+}
+
+Vec2d CurvePoint::directionFredo () const
+{
+ if (__A == 0)
+ return __B->directionFredo();
+ if (__B == 0)
+ return __A->directionFredo();
+ return ((1 - _t2d) * __A->directionFredo() + _t2d * __B->directionFredo());
+}
+
+/**********************************/
+/* */
+/* */
+/* Curve */
+/* */
+/* */
+/**********************************/
+
+/* for functions */
+
+Curve::~Curve()
+{
+ if (!_Vertices.empty()) {
+ for (vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end(); it != itend; ++it) {
+ delete (*it);
+ }
+ _Vertices.clear();
+ }
+}
+
+/*! iterators access */
+Curve::point_iterator Curve::points_begin(float step)
+{
+ vertex_container::iterator second = _Vertices.begin();
+ ++second;
+ return point_iterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), _nSegments, step, 0.0f, 0.0f);
+ //return point_iterator(_Vertices.begin(), second, _nSegments, step, 0.0f, 0.0f);
+}
+
+Curve::const_point_iterator Curve::points_begin(float step) const
+{
+ vertex_container::const_iterator second = _Vertices.begin();
+ ++second;
+ return const_point_iterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(),
+ _nSegments, step, 0.0f, 0.0f);
+ //return const_point_iterator(_Vertices.begin(), second, _nSegments, step, 0.0f, 0.0f);
+}
+
+Curve::point_iterator Curve::points_end(float step)
+{
+ return point_iterator(_Vertices.end(), _Vertices.end(), _Vertices.begin(), _Vertices.end(),
+ _nSegments, step, 1.0f, _Length);
+ //return point_iterator(_Vertices.end(), _Vertices.end(), _nSegments, step, 1.0f, _Length);
+}
+
+Curve::const_point_iterator Curve::points_end(float step) const
+{
+ return const_point_iterator(_Vertices.end(), _Vertices.end(), _Vertices.begin(), _Vertices.end(),
+ _nSegments, step, 1.0f, _Length);
+ //return const_point_iterator(_Vertices.end(), _Vertices.end(), _nSegments, step, 1.0f, _Length);
+}
+
+// Adavnced Iterators access
+Curve::point_iterator Curve::vertices_begin()
+{
+ return points_begin(0);
+}
+
+Curve::const_point_iterator Curve::vertices_begin() const
+{
+ return points_begin(0);
+}
+
+Curve::point_iterator Curve::vertices_end()
+{
+ return points_end(0);
+}
+
+Curve::const_point_iterator Curve::vertices_end() const
+{
+ return points_end(0);
+}
+
+// specialized iterators access
+CurveInternal::CurvePointIterator Curve::curvePointsBegin(float t)
+{
+ vertex_container::iterator second = _Vertices.begin();
+ ++second;
+ return CurveInternal::CurvePointIterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(),
+ 0, _nSegments, _Length, t, 0.0f, 0.0f);
+}
+
+CurveInternal::CurvePointIterator Curve::curvePointsEnd(float t)
+{
+ vertex_container::iterator last = _Vertices.end();
+ --last;
+ return CurveInternal::CurvePointIterator(last, _Vertices.end(), _Vertices.begin(), _Vertices.end(),
+ _nSegments, _nSegments, _Length, t, 0.0f, _Length);
+}
+
+CurveInternal::CurvePointIterator Curve::curveVerticesBegin()
+{
+ return curvePointsBegin(0);
+}
+
+CurveInternal::CurvePointIterator Curve::curveVerticesEnd()
+{
+ return curvePointsEnd(0);
+}
+
+Interface0DIterator Curve::pointsBegin(float t)
+{
+ vertex_container::iterator second = _Vertices.begin();
+ ++second;
+ Interface0DIterator ret(new CurveInternal::CurvePointIterator(_Vertices.begin(), second, _Vertices.begin(),
+ _Vertices.end(), 0, _nSegments, _Length,
+ t, 0.0f, 0.0f));
+ return ret;
+}
+
+Interface0DIterator Curve::pointsEnd(float t)
+{
+ vertex_container::iterator last = _Vertices.end();
+ --last;
+ Interface0DIterator ret(new CurveInternal::CurvePointIterator(last, _Vertices.end(), _Vertices.begin(),
+ _Vertices.end(), _nSegments, _nSegments,
+ _Length, t, 0.0f, _Length));
+ return ret;
+}
+
+Interface0DIterator Curve::verticesBegin()
+{
+ return pointsBegin(0);
+}
+
+Interface0DIterator Curve::verticesEnd()
+{
+ return pointsEnd(0);
+}
+
+#if 0
+Vec3r shaded_color(int iCombination = 0) const;
+
+Vec3r Curve::orientation2d(point_iterator it) const
+{
+ return (*it)->orientation2d();
+}
+
+template <class BaseVertex>
+Vec3r Curve::orientation2d(int iCombination) const
+{
+ return edge_orientation2d_function<Curve >(this, iCombination);
+}
+
+Vec3r Curve::orientation3d(point_iterator it) const
+{
+ return (*it)->orientation3d();
+}
+
+Vec3r Curve::orientation3d(int iCombination) const
+{
+ return edge_orientation3d_function<Curve >(this, iCombination);
+}
+
+real curvature2d(point_iterator it) const
+{
+ return (*it)->curvature2d();
+}
+
+real curvature2d(int iCombination = 0) const;
+
+Material Curve::material() const
+{
+ const_vertex_iterator v = vertices_begin(), vend = vertices_end();
+ const Material& mat = (*v)->material();
+ for (; v != vend; ++v) {
+ if ((*v)->material() != mat)
+ Exception::raiseException();
+ }
+ return mat;
+}
+
+int Curve::qi() const
+{
+ const_vertex_iterator v = vertices_begin(), vend = vertices_end();
+ int qi_ = (*v)->qi();
+ for (; v != vend; ++v) {
+ if ((*v)->qi() != qi_)
+ Exception::raiseException();
+ }
+ return qi_;
+}
+
+occluder_container::const_iterator occluders_begin() const
+{
+ return _FEdgeA->occluders().begin();
+}
+
+occluder_container::const_iterator occluders_end() const
+{
+ return _FEdgeA->occluders().end();
+}
+
+int Curve::occluders_size() const
+{
+ return qi();
+}
+
+bool Curve::occluders_empty() const
+{
+ const_vertex_iterator v = vertices_begin(), vend = vertices_end();
+ bool empty = (*v)->occluders_empty();
+ for (; v != vend; ++v) {
+ if ((*v)->occluders_empty() != empty)
+ Exception::raiseException();
+ }
+ return empty;
+}
+
+const Polygon3r& occludee() const
+{
+ return *(_FEdgeA->aFace());
+}
+
+const SShape *Curve::occluded_shape() const
+{
+ const_vertex_iterator v = vertices_begin(), vend = vertices_end();
+ const SShape *sshape = (*v)->occluded_shape();
+ for (; v != vend; ++v) {
+ if ((*v)->occluded_shape() != sshape)
+ Exception::raiseException();
+ }
+ return sshape;
+}
+
+const bool Curve::occludee_empty() const
+{
+ const_vertex_iterator v = vertices_begin(), vend = vertices_end();
+ bool empty = (*v)->occludee_empty();
+ for (; v != vend; ++v) {
+ if ((*v)->occludee_empty() != empty)
+ Exception::raiseException();
+ }
+ return empty;
+}
+real Curve::z_discontinuity(int iCombination) const
+{
+ return z_discontinuity_edge_function<Curve>(this, iCombination);
+}
+
+int Curve::shape_id() const
+{
+ const_vertex_iterator v = vertices_begin(), vend = vertices_end();
+ Id id = (*v)->shape_id();
+ for (; v != vend; ++v) {
+ if ((*v)->shape_id() != id)
+ Exception::raiseException();
+ }
+ return id.first;
+}
+
+
+const SShape *Curve::shape() const
+{
+ const_vertex_iterator v = vertices_begin(), vend = vertices_end();
+ const SShape *sshape = (*v)->shape();
+ for (; v != vend; ++v) {
+ if ((*v)->shape() != sshape)
+ Exception::raiseException();
+ }
+ return sshape;
+}
+
+
+occluder_container::const_iterator Curve::occluders_begin() const
+{
+ const_vertex_iterator v = vertices_begin();
+ return (*v)->occluders_begin();
+}
+
+
+occluder_container::const_iterator Curve::occluders_end() const
+{
+ const_vertex_iterator v = vertices_end();
+ return (*v)->occluders_end();
+}
+
+Vec3r Curve::curvature2d_as_vector(int iCombination) const
+{
+ return curvature2d_as_vector_edge_function<Curve>(this, iCombination);
+}
+
+real Curve::curvature2d_as_angle(int iCombination) const
+{
+ return curvature2d_as_angle_edge_function<Curve>(this, iCombination);
+}
+
+float Curve::shape_importance(int iCombination) const
+{
+ return shape_importance_edge_function<Curve>(this, iCombination);
+}
+
+float Curve::local_average_depth(int iCombination) const
+{
+ return local_average_depth_edge_function<Curve>(this, iCombination);
+}
+
+float Curve::local_depth_variance(int iCombination ) const
+{
+ return local_depth_variance_edge_function<Curve>(this, iCombination);
+#if 0
+ local_depth_variance_functor<Point> functor;
+ float result;
+ Evaluate<float, local_depth_variance_functor<Point> >(&functor, iCombination, result);
+ return result;
+#endif
+}
+
+real Curve::local_average_density(float sigma, int iCombination ) const
+{
+ return density_edge_function<Curve>(this, iCombination);
+#if 0
+ density_functor<Point> functor;
+ real result;
+ Evaluate<real, density_functor<Point> >(&functor, iCombination, result);
+ return result;
+#endif
+}
+#endif
+
+#define EPS_CURVA_DIR 0.01
+
+void Curve::computeCurvatureAndOrientation ()
+{
+#if 0
+ const_vertex_iterator v = vertices_begin(), vend = vertices_end(), v2, prevV, v0;
+ Vec2d p0, p1, p2;
+ Vec3r p;
+
+ p = (*v)->point2d();
+ p0 = Vec2d(p[0], p[1]);
+ prevV = v;
+ ++v;
+ p = (*v)->point2d();
+ p1 = Vec2d(p[0], p[1]);
+ Vec2d prevDir(p1 - p0);
+
+ for (; v! = vend; ++v) {
+ v2 = v;
+ ++v2;
+ if (v2 == vend)
+ break;
+ Vec3r p2 = (*v2)->point2d();
+
+ Vec2d BA = p0 - p1;
+ Vec2d BC = p2 - p1;
+ real lba = BA.norm(), lbc = BC.norm();
+ BA.normalizeSafe();
+ BC.normalizeSafe();
+ Vec2d normalCurvature = BA + BC;
+ Vec2d dir = Vec2d(BC - BA);
+ Vec2d normal = Vec2d(-dir[1], dir[0]);
+
+ normal.normalizeSafe();
+ real curvature = normalCurvature * normal;
+ if (lba + lbc > MY_EPSILON)
+ curvature /= (0.5 * lba + lbc);
+ if (dir.norm() < MY_EPSILON)
+ dir = 0.1 * prevDir;
+ (*v)->setCurvatureFredo(curvature);
+ (*v)->setDirectionFredo(dir);
+
+ prevV = v;
+ p0 = p1;
+ p1 = p2;
+ prevDir = dir;
+ prevDir.normalize();
+ }
+ (*v)->setCurvatureFredo((*prevV)->curvatureFredo());
+ (*v)->setDirectionFredo((*v)->point2d() - (*prevV)->point2d());
+ v0 = vertices_begin();
+ v2 = v0;
+ ++v2;
+ (*v0)->setCurvatureFredo((*v2)->curvatureFredo());
+ (*v0)->setDirectionFredo((*v2)->point2d() - (*v0)->point2d());
+
+ //closed curve case one day...
+
+ //
+ return;
+
+ //numerical degeneracy verification... we'll see later
+ const_vertex_iterator vLastReliable = vertices_begin();
+
+ v = vertices_begin();
+ p = (*v)->point2d();
+ p0 = Vec2d(p[0], p[1]);
+ prevV = v;
+ ++v;
+ p = (*v)->point2d();
+ p1 = Vec2d(p[0], p[1]);
+ bool isReliable = false;
+ if ((p1 - p0).norm > EPS_CURVA) {
+ vLastReliable = v;
+ isReliable = true;
+ }
+
+ for (; v != vend; ++v) {
+ v2 = v;
+ ++v2;
+ if (v2 == vend)
+ break;
+ Vec3r p2 = (*v2)->point2d();
+
+ Vec2d BA = p0 - p1;
+ Vec2d BC = p2 - p1;
+ real lba = BA.norm(), lbc = BC.norm();
+
+ if ((lba + lbc) < EPS_CURVA) {
+ isReliable = false;
+ cerr << "/";
+ }
+ else {
+ if (!isReliable) { //previous points were not reliable
+ const_vertex_iterator vfix = vLastReliable;
+ ++vfix;
+ for (; vfix != v; ++vfix) {
+ (*vfix)->setCurvatureFredo((*v)->curvatureFredo());
+ (*vfix)->setDirectionFredo((*v)->directionFredo());
+ }
+ }
+ isReliable = true;
+ vLastReliable = v;
+ }
+ prevV = v;
+ p0 = p1;
+ p1 = p2;
+ }
+#endif
+}
diff --git a/source/blender/freestyle/intern/stroke/Curve.h b/source/blender/freestyle/intern/stroke/Curve.h
new file mode 100644
index 00000000000..c8dbf368323
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Curve.h
@@ -0,0 +1,589 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_CURVE_H__
+#define __FREESTYLE_CURVE_H__
+
+/** \file blender/freestyle/intern/stroke/Curve.h
+ * \ingroup freestyle
+ * \brief Class to define a container for curves
+ * \author Stephane Grabli
+ * \date 11/01/2003
+ */
+
+#include <deque>
+
+#include "../geometry/Geom.h"
+
+//#include "../scene_graph/FrsMaterial.h"
+
+#include "../view_map/Interface0D.h"
+#include "../view_map/Interface1D.h"
+#include "../view_map/Silhouette.h"
+#include "../view_map/SilhouetteGeomEngine.h"
+
+#include "../system/BaseIterator.h"
+
+using namespace std;
+using namespace Geometry;
+
+/**********************************/
+/* */
+/* */
+/* CurvePoint */
+/* */
+/* */
+/**********************************/
+
+/*! Class to represent a point of a curve.
+ * A CurvePoint can be any point of a 1D curve (it doesn't have to be a vertex of the curve).
+ * Any Interface1D is built upon ViewEdges, themselves built upon FEdges. Therefore, a curve is basically
+ * a polyline made of a list SVertex.
+ * Thus, a CurvePoint is built by lineraly interpolating two SVertex.
+ * CurvePoint can be used as virtual points while querying 0D information along a curve at a given resolution.
+ */
+class LIB_STROKE_EXPORT CurvePoint : public Interface0D
+{
+public: // Implementation of Interface0D
+ /*! Returns the string "CurvePoint"*/
+ virtual string getExactTypeName() const
+ {
+ return "CurvePoint";
+ }
+
+ // Data access methods
+ /*! Returns the 3D X coordinate of the point */
+ virtual real getX() const
+ {
+ return _Point3d.x();
+ }
+
+ /*! Returns the 3D Y coordinate of the point */
+ virtual real getY() const
+ {
+ return _Point3d.y();
+ }
+
+ /*! Returns the 3D Z coordinate of the point */
+ virtual real getZ() const
+ {
+ return _Point3d.z();
+ }
+
+ /*! Returns the 3D point. */
+ virtual Vec3f getPoint3D() const
+ {
+ return _Point3d;
+ }
+
+ /*! Returns the projected 3D X coordinate of the point */
+ virtual real getProjectedX() const
+ {
+ return _Point2d.x();
+ }
+
+ /*! Returns the projected 3D Y coordinate of the point */
+ virtual real getProjectedY() const
+ {
+ return _Point2d.y();
+ }
+
+ /*! Returns the projected 3D Z coordinate of the point */
+ virtual real getProjectedZ() const
+ {
+ return _Point2d.z();
+ }
+
+ /*! Returns the 2D point. */
+ virtual Vec2f getPoint2D() const
+ {
+ return Vec2f((float)_Point2d.x(), (float)_Point2d.y());
+ }
+
+ virtual FEdge *getFEdge(Interface0D& inter);
+
+ /*! Returns the CurvePoint's Id */
+ virtual Id getId() const
+ {
+ Id id;
+ if (_t2d == 0)
+ return __A->getId();
+ else if (_t2d == 1)
+ return __B->getId();
+ return id;
+ }
+
+ /*! Returns the CurvePoint's Nature */
+ virtual Nature::VertexNature getNature() const
+ {
+ Nature::VertexNature nature = Nature::POINT;
+ if (_t2d == 0)
+ nature |= __A->getNature();
+ else if (_t2d == 1)
+ nature |= __B->getNature();
+ return nature;
+ }
+
+ /*! Cast the Interface0D in SVertex if it can be. */
+ virtual SVertex *castToSVertex()
+ {
+ if (_t2d == 0)
+ return __A;
+ else if (_t2d == 1)
+ return __B;
+ return Interface0D::castToSVertex();
+ }
+
+ /*! Cast the Interface0D in ViewVertex if it can be. */
+ virtual ViewVertex *castToViewVertex()
+ {
+ if (_t2d == 0)
+ return __A->castToViewVertex();
+ else if (_t2d == 1)
+ return __B->castToViewVertex();
+ return Interface0D::castToViewVertex();
+ }
+
+ /*! Cast the Interface0D in NonTVertex if it can be. */
+ virtual NonTVertex *castToNonTVertex()
+ {
+ if (_t2d == 0)
+ return __A->castToNonTVertex();
+ else if (_t2d == 1)
+ return __B->castToNonTVertex();
+ return Interface0D::castToNonTVertex();
+ }
+
+ /*! Cast the Interface0D in TVertex if it can be. */
+ virtual TVertex *castToTVertex()
+ {
+ if (_t2d == 0)
+ return __A->castToTVertex();
+ else if (_t2d == 1)
+ return __B->castToTVertex();
+ return Interface0D::castToTVertex();
+ }
+
+public:
+ typedef SVertex vertex_type;
+
+protected:
+ SVertex *__A;
+ SVertex *__B;
+ float _t2d;
+ //float _t3d;
+ Vec3r _Point2d;
+ Vec3r _Point3d;
+
+public:
+ /*! Defult Constructor. */
+ CurvePoint();
+
+ /*! Builds a CurvePoint from two SVertex and an interpolation parameter.
+ * \param iA
+ * The first SVertex
+ * \param iB
+ * The second SVertex
+ * \param t2d
+ * A 2D interpolation parameter used to linearly interpolate \a iA and \a iB
+ */
+ CurvePoint(SVertex *iA, SVertex *iB, float t2d);
+
+ /*! Builds a CurvePoint from two CurvePoint and an interpolation parameter.
+ * \param iA
+ * The first CurvePoint
+ * \param iB
+ * The second CurvePoint
+ * \param t2d
+ * The 2D interpolation parameter used to linearly interpolate \a iA and \a iB.
+ */
+ CurvePoint(CurvePoint *iA, CurvePoint *iB, float t2d);
+
+ //CurvePoint(SVertex *iA, SVertex *iB, float t2d, float t3d);
+
+ /*! Copy Constructor. */
+ CurvePoint(const CurvePoint& iBrother);
+
+ /*! Operator = */
+ CurvePoint& operator=(const CurvePoint& iBrother);
+
+ /*! Destructor */
+ virtual ~CurvePoint() {}
+
+ /*! Operator == */
+ bool operator==(const CurvePoint& b)
+ {
+ return ((__A == b.__A) && (__B == b.__B) && (_t2d == b._t2d));
+ }
+
+ /* accessors */
+ /*! Returns the first SVertex upon which the CurvePoint is built. */
+ inline SVertex *A()
+ {
+ return __A;
+ }
+
+ /*! Returns the second SVertex upon which the CurvePoint is built. */
+ inline SVertex *B()
+ {
+ return __B;
+ }
+
+ /*! Returns the interpolation parameter. */
+ inline float t2d() const
+ {
+ return _t2d;
+ }
+
+#if 0
+ inline const float t3d() const
+ {
+ return _t3d;
+ }
+#endif
+
+ /* modifiers */
+ /*! Sets the first SVertex upon which to build the CurvePoint. */
+ inline void setA(SVertex *iA)
+ {
+ __A = iA;
+ }
+
+ /*! Sets the second SVertex upon which to build the CurvePoint. */
+ inline void setB(SVertex *iB)
+ {
+ __B = iB;
+ }
+
+ /*! Sets the 2D interpolation parameter to use. */
+ inline void setT2d(float t)
+ {
+ _t2d = t;
+ }
+
+#if 0
+ inline void SetT3d(float t)
+ {
+ _t3d = t;
+ }
+#endif
+
+ /* Information access interface */
+
+ FEdge *fedge();
+
+ inline const Vec3r& point2d() const
+ {
+ return _Point2d;
+ }
+
+ inline const Vec3r& point3d() const
+ {
+ return _Point3d;
+ }
+
+ Vec3r normal() const;
+ //FrsMaterial material() const;
+ //Id shape_id() const;
+ const SShape *shape() const;
+ //float shape_importance() const;
+
+ //const unsigned qi() const;
+ occluder_container::const_iterator occluders_begin() const;
+ occluder_container::const_iterator occluders_end() const;
+ bool occluders_empty() const;
+ int occluders_size() const;
+ const Polygon3r& occludee() const;
+ const SShape *occluded_shape() const;
+ const bool occludee_empty() const;
+ real z_discontinuity() const;
+#if 0
+ float local_average_depth() const;
+ float local_depth_variance() const;
+ real local_average_density(float sigma = 2.3f) const;
+ Vec3r shaded_color() const;
+ Vec3r orientation2d() const;
+ Vec3r orientation3d() const;
+
+ real curvature2d() const
+ {
+ return viewedge()->curvature2d((_VertexA->point2d() + _VertexB->point2d()) / 2.0);
+ }
+
+ Vec3r curvature2d_as_vector() const;
+ /*! angle in radians */
+ real curvature2d_as_angle() const;
+#endif
+
+ real curvatureFredo() const;
+ Vec2d directionFredo() const;
+};
+
+
+/**********************************/
+/* */
+/* */
+/* Curve */
+/* */
+/* */
+/**********************************/
+
+namespace CurveInternal {
+
+class CurvePoint_const_traits;
+class CurvePoint_nonconst_traits;
+template<class Traits> class __point_iterator;
+class CurvePointIterator;
+
+} // end of namespace CurveInternal
+
+/*! Base class for curves made of CurvePoints.
+ * SVertex is the type of the initial curve vertices.
+ * A Chain is a specialization of a Curve.
+ */
+class LIB_STROKE_EXPORT Curve : public Interface1D
+{
+public:
+ typedef CurvePoint Vertex;
+ typedef CurvePoint Point;
+ typedef Point point_type;
+ typedef Vertex vertex_type;
+ typedef deque<Vertex*> vertex_container;
+
+ /* Iterator to iterate over a vertex edges */
+
+ typedef CurveInternal::__point_iterator<CurveInternal::CurvePoint_nonconst_traits > point_iterator;
+ typedef CurveInternal::__point_iterator<CurveInternal::CurvePoint_const_traits > const_point_iterator;
+ typedef point_iterator vertex_iterator ;
+ typedef const_point_iterator const_vertex_iterator ;
+
+protected:
+ vertex_container _Vertices;
+ double _Length;
+ Id _Id;
+ unsigned _nSegments; // number of segments
+
+public:
+ /*! Default Constructor. */
+ Curve()
+ {
+ _Length = 0;
+ _Id = 0;
+ _nSegments = 0;
+ }
+
+ /*! Builds a Curve from its id */
+ Curve(const Id& id)
+ {
+ _Length = 0;
+ _Id = id;
+ _nSegments = 0;
+ }
+
+ /*! Copy Constructor. */
+ Curve(const Curve& iBrother)
+ {
+ _Length = iBrother._Length;
+ _Vertices = iBrother._Vertices;
+ _Id = iBrother._Id;
+ _nSegments = 0;
+ }
+
+ /*! Destructor. */
+ virtual ~Curve();
+
+ /*! Returns the string "Curve" */
+ virtual string getExactTypeName() const
+ {
+ return "Curve";
+ }
+
+ /* fredo's curvature storage */
+ void computeCurvatureAndOrientation();
+
+ /*! Adds a single vertex (CurvePoint) at the end of the Curve */
+ inline void push_vertex_back(Vertex *iVertex)
+ {
+ if (!_Vertices.empty()) {
+ Vec3r vec_tmp(iVertex->point2d() - _Vertices.back()->point2d());
+ _Length += vec_tmp.norm();
+ ++_nSegments;
+ }
+ Vertex *new_vertex = new Vertex(*iVertex);
+ _Vertices.push_back(new_vertex);
+ }
+
+ /*! Adds a single vertex (SVertex) at the end of the Curve */
+ inline void push_vertex_back(SVertex *iVertex)
+ {
+ if (!_Vertices.empty()) {
+ Vec3r vec_tmp(iVertex->point2d() - _Vertices.back()->point2d());
+ _Length += vec_tmp.norm();
+ ++_nSegments;
+ }
+ Vertex *new_vertex = new Vertex(iVertex, 0, 0);
+ _Vertices.push_back(new_vertex);
+ }
+
+ /*! Adds a single vertex (CurvePoint) at the front of the Curve */
+ inline void push_vertex_front(Vertex *iVertex)
+ {
+ if (!_Vertices.empty()) {
+ Vec3r vec_tmp(iVertex->point2d() - _Vertices.front()->point2d());
+ _Length += vec_tmp.norm();
+ ++_nSegments;
+ }
+ Vertex *new_vertex = new Vertex(*iVertex);
+ _Vertices.push_front(new_vertex);
+ }
+
+ /*! Adds a single vertex (SVertex) at the front of the Curve */
+ inline void push_vertex_front(SVertex *iVertex)
+ {
+ if (!_Vertices.empty()) {
+ Vec3r vec_tmp(iVertex->point2d() - _Vertices.front()->point2d());
+ _Length += vec_tmp.norm();
+ ++_nSegments;
+ }
+ Vertex *new_vertex = new Vertex(iVertex, 0, 0);
+ _Vertices.push_front(new_vertex);
+ }
+
+ /*! Returns true is the Curve doesn't have any Vertex yet. */
+ inline bool empty() const
+ {
+ return _Vertices.empty();
+ }
+
+ /*! Returns the 2D length of the Curve. */
+ inline real getLength2D() const
+ {
+ return _Length;
+ }
+
+ /*! Returns the Id of the 1D element. */
+ virtual Id getId() const
+ {
+ return _Id;
+ }
+
+ /*! Returns the number of segments in the polyline constituing the Curve. */
+ inline unsigned int nSegments() const
+ {
+ return _nSegments;
+ }
+
+ inline void setId(const Id& id)
+ {
+ _Id = id;
+ }
+
+ /* Information access interface */
+
+#if 0
+ inline Vec3r shaded_color(int iCombination = 0) const;
+ inline Vec3r orientation2d(point_iterator it) const;
+ Vec3r orientation2d(int iCombination = 0) const;
+ Vec3r orientation3d(point_iterator it) const;
+ Vec3r orientation3d(int iCombination = 0) const;
+
+ real curvature2d(point_iterator it) const
+ {
+ return (*it)->curvature2d();
+ }
+
+ real curvature2d(int iCombination = 0) const;
+ FrsMaterial material() const;
+ int qi() const;
+ occluder_container::const_iterator occluders_begin() const;
+ occluder_container::const_iterator occluders_end() const;
+ int occluders_size() const;
+ bool occluders_empty() const;
+
+ const Polygon3r& occludee() const
+ {
+ return *(_FEdgeA->aFace());
+ }
+
+ const SShape *occluded_shape() const;
+ const bool occludee_empty() const;
+ real z_discontinuity(int iCombination = 0) const;
+ int shape_id() const;
+ const SShape *shape() const;
+ float shape_importance(int iCombination = 0) const;
+ float local_average_depth(int iCombination = 0) const;
+ float local_depth_variance(int iCombination = 0) const;
+ real local_average_density(float sigma = 2.3f, int iCombination = 0) const;
+ Vec3r curvature2d_as_vector(int iCombination = 0) const;
+ /*! angle in radians */
+ real curvature2d_as_angle(int iCombination = 0) const;
+#endif
+
+ /* advanced iterators access */
+ point_iterator points_begin(float step = 0);
+ const_point_iterator points_begin(float step = 0) const;
+ point_iterator points_end(float step = 0);
+ const_point_iterator points_end(float step = 0) const;
+
+ /* methods given for convenience */
+ point_iterator vertices_begin();
+ const_point_iterator vertices_begin() const;
+ point_iterator vertices_end();
+ const_point_iterator vertices_end() const;
+
+ // specialized iterators access
+ CurveInternal::CurvePointIterator curvePointsBegin(float t = 0.0f);
+ CurveInternal::CurvePointIterator curvePointsEnd(float t = 0.0f);
+
+ CurveInternal::CurvePointIterator curveVerticesBegin();
+ CurveInternal::CurvePointIterator curveVerticesEnd();
+
+ // Iterators access
+ /*! Returns an Interface0DIterator pointing onto the first vertex of the Curve and that can iterate
+ * over the \a vertices of the Curve.
+ */
+ virtual Interface0DIterator verticesBegin();
+
+ /*! Returns an Interface0DIterator pointing after the last vertex of the Curve and that can iterate
+ * over the \a vertices of the Curve.
+ */
+ virtual Interface0DIterator verticesEnd();
+
+ /*! Returns an Interface0DIterator pointing onto the first point of the Curve and that can iterate
+ * over the \a points of the Curve at any resolution.
+ * At each iteration a virtual temporary CurvePoint is created.
+ */
+ virtual Interface0DIterator pointsBegin(float t = 0.0f);
+
+ /*! Returns an Interface0DIterator pointing after the last point of the Curve and that can iterate
+ * over the \a points of the Curve at any resolution.
+ * At each iteration a virtual temporary CurvePoint is created.
+ */
+ virtual Interface0DIterator pointsEnd(float t = 0.0f);
+};
+
+#endif // __FREESTYLE_CURVE_H__
diff --git a/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h b/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h
new file mode 100644
index 00000000000..b87af512220
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h
@@ -0,0 +1,383 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_CURVE_ADVANCED_ITERATORS_H__
+#define __FREESTYLE_CURVE_ADVANCED_ITERATORS_H__
+
+/** \file blender/freestyle/intern/stroke/CurveAdvancedIterators.h
+ * \ingroup freestyle
+ * \brief Iterators used to iterate over the elements of the Curve. Can't be used in python
+ * \author Stephane Grabli
+ * \date 01/08/2003
+ */
+
+#include "Stroke.h"
+
+namespace CurveInternal {
+
+class CurvePoint_const_traits : public Const_traits<CurvePoint*>
+{
+public:
+ typedef deque<CurvePoint*> vertex_container;
+ typedef vertex_container::const_iterator vertex_container_iterator;
+ typedef SVertex vertex_type;
+};
+
+class CurvePoint_nonconst_traits : public Nonconst_traits<CurvePoint*>
+{
+public:
+ typedef deque<CurvePoint*> vertex_container;
+ typedef vertex_container::iterator vertex_container_iterator;
+ typedef SVertex vertex_type;
+};
+
+/**********************************/
+/* */
+/* */
+/* CurvePoint Iterator */
+/* */
+/* */
+/**********************************/
+
+
+/*! iterator on a curve. Allows an iterating outside initial vertices. A CurvePoint is instanciated an returned
+ * when the iterator is dereferenced.
+ */
+template<class Traits>
+class __point_iterator : public IteratorBase<Traits, BidirectionalIteratorTag_Traits>
+{
+public:
+ typedef __point_iterator <Traits> Self;
+ typedef typename Traits::vertex_container_iterator vertex_container_iterator;
+ typedef typename Traits::vertex_type vertex_type;
+ typedef CurvePoint Point;
+ typedef Point point_type;
+
+ typedef __point_iterator<CurvePoint_nonconst_traits> iterator;
+ typedef __point_iterator<CurvePoint_const_traits> const_iterator;
+
+#if 0
+ typedef Vertex vertex_type ;
+ typedef vertex_container_iterator vertex_iterator_type;
+ typedef CurvePoint<Vertex> Point;
+ typedef Point point_type;
+#endif
+ typedef IteratorBase<Traits, BidirectionalIteratorTag_Traits> parent_class;
+#if 0
+#if defined(__GNUC__) && (__GNUC__ < 3)
+ typedef bidirectional_iterator<CurvePoint<Vertex>, ptrdiff_t> bidirectional_point_iterator;
+#else
+ typedef iterator<bidirectional_iterator_tag, CurvePoint<Vertex>, ptrdiff_t> bidirectional_point_iterator;
+#endif
+#endif
+ friend class Curve;
+#if 0
+ friend class Curve::vertex_iterator;
+ friend class __point_iterator<CurvePoint_nonconst_traits>;
+ friend class iterator;
+#endif
+//protected:
+public:
+ float _CurvilinearLength;
+ float _step;
+ vertex_container_iterator __A;
+ vertex_container_iterator __B;
+ vertex_container_iterator _begin;
+ vertex_container_iterator _end;
+ int _n;
+ int _currentn;
+ float _t;
+ mutable Point *_Point;
+
+public:
+ inline __point_iterator(float step = 0.0f) : parent_class()
+ {
+ _step = step;
+ _CurvilinearLength = 0.0f;
+ _t = 0.0f;
+ _Point = 0;
+ _n = 0;
+ _currentn = 0;
+ }
+
+ inline __point_iterator(const iterator& iBrother) : parent_class()
+ {
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _CurvilinearLength = iBrother._CurvilinearLength;
+ _step = iBrother._step;
+ _t = iBrother._t;
+ if (iBrother._Point == 0)
+ _Point = 0;
+ else
+ _Point = new Point(*(iBrother._Point));
+ _n = iBrother._n;
+ _currentn = iBrother._currentn;
+ }
+
+ inline __point_iterator(const const_iterator& iBrother) : parent_class()
+ {
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _CurvilinearLength = iBrother._CurvilinearLength;
+ _step = iBrother._step;
+ _t = iBrother._t;
+ if (iBrother._Point == 0)
+ _Point = 0;
+ else
+ _Point = new Point(*(iBrother._Point));
+ _n = iBrother._n;
+ _currentn = iBrother._currentn;
+ }
+
+ inline Self& operator=(const Self& iBrother)
+ {
+ //((bidirectional_point_iterator*)this)->operator=(iBrother);
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _CurvilinearLength = iBrother._CurvilinearLength;
+ _step = iBrother._step;
+ _t = iBrother._t;
+ if (iBrother._Point == 0)
+ _Point = 0;
+ else
+ _Point = new Point(*(iBrother._Point));
+ _n = iBrother._n;
+ _currentn = iBrother._currentn;
+ return *this;
+ }
+
+ virtual ~__point_iterator()
+ {
+ if (_Point != 0)
+ delete _Point;
+ }
+
+//protected: //FIXME
+public:
+ inline __point_iterator(vertex_container_iterator iA, vertex_container_iterator iB,
+ vertex_container_iterator ibegin, vertex_container_iterator iend,
+ int currentn, int n, float step, float t = 0.0f, float iCurvilinearLength = 0.0f)
+ : parent_class()
+ {
+ __A = iA;
+ __B = iB;
+ _begin = ibegin;
+ _end = iend;
+ _CurvilinearLength = iCurvilinearLength;
+ _step = step;
+ _t = t;
+ _Point = 0;
+ _n = n;
+ _currentn = currentn;
+ }
+
+public:
+ // operators
+ inline Self& operator++() // operator corresponding to ++i
+ {
+ increment();
+ return *this;
+ }
+
+ /* Operator corresponding to i++, i.e. it returns the value *and then* increments.
+ * That’s why we store the value in a temp.
+ */
+ inline Self operator++(int)
+ {
+ Self tmp = *this;
+ increment();
+ return tmp;
+ }
+
+ inline Self& operator--() // operator corresponding to --i
+ {
+ decrement();
+ return *this;
+ }
+
+ inline Self operator--(int) // operator corresponding to i--
+ {
+ Self tmp = *this;
+ decrement();
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const Self& b) const
+ {
+ return ((__A != b.__A) || (__B != b.__B) || (_t != b._t));
+ }
+
+ virtual bool operator==(const Self& b) const
+ {
+ return !(*this != b);
+ }
+
+ // dereferencing
+ virtual typename Traits::reference operator*() const
+ {
+ if (_Point != 0) {
+ delete _Point;
+ _Point = 0;
+ }
+ if ((_currentn < 0) || (_currentn >= _n))
+ return _Point; // 0 in this case
+ return (_Point = new Point(*__A, *__B, _t));
+ }
+
+ virtual typename Traits::pointer operator->() const
+ {
+ return &(operator*());
+ }
+
+ virtual bool begin() const
+ {
+ if ((__A == _begin) && (_t < (float)M_EPSILON))
+ return true;
+ return false;
+ }
+
+ virtual bool end() const
+ {
+ if ((__B == _end))
+ return true;
+ return false;
+ }
+
+protected:
+ virtual void increment()
+ {
+ if (_Point != 0) {
+ delete _Point;
+ _Point = 0;
+ }
+ if ((_currentn == _n - 1) && (_t == 1.0f)) {
+ // we're setting the iterator to end
+ ++__A;
+ ++__B;
+ ++_currentn;
+ _t = 0.0f;
+ return;
+ }
+
+ if (0 == _step) { // means we iterate over initial vertices
+ Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d());
+ _CurvilinearLength += vec_tmp.norm();
+ if (_currentn == _n - 1) {
+ _t = 1.0f;
+ return;
+ }
+ ++__B;
+ ++__A;
+ ++_currentn;
+ return;
+ }
+
+ // compute the new position:
+ Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d());
+ float normAB = vec_tmp2.norm();
+
+ if (normAB > M_EPSILON) {
+ _CurvilinearLength += _step;
+ _t = _t + _step / normAB;
+ }
+ else {
+ _t = 1.0f; // AB is a null segment, we're directly at its end
+ }
+ //if normAB ~= 0, we don't change these values
+ if (_t >= 1) {
+ _CurvilinearLength -= normAB * (_t - 1);
+ if (_currentn == _n - 1) {
+ _t = 1.0f;
+ }
+ else {
+ _t = 0.0f;
+ ++_currentn;
+ ++__A;
+ ++__B;
+ }
+ }
+ }
+
+ virtual void decrement()
+ {
+ if (_Point != 0) {
+ delete _Point;
+ _Point = 0;
+ }
+
+ if (_t == 0.0f) { // we're at the beginning of the edge
+ _t = 1.0f;
+ --_currentn;
+ --__A;
+ --__B;
+ if (_currentn == _n - 1)
+ return;
+ }
+
+ if (0 == _step) { // means we iterate over initial vertices
+ Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d());
+ _CurvilinearLength -= vec_tmp.norm();
+ _t = 0;
+ return;
+ }
+
+ // compute the new position:
+ Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d());
+ float normAB = vec_tmp2.norm();
+
+ if (normAB >M_EPSILON) {
+ _CurvilinearLength -= _step;
+ _t = _t - _step / normAB;
+ }
+ else {
+ _t = -1.0f; // We just need a negative value here
+ }
+
+ // round value
+ if (fabs(_t) < (float)M_EPSILON)
+ _t = 0.0f;
+ if (_t < 0) {
+ if (_currentn == 0)
+ _CurvilinearLength = 0.0f;
+ else
+ _CurvilinearLength += normAB * (-_t);
+ _t = 0.0f;
+ }
+ }
+};
+
+} // end of namespace CurveInternal
+
+#endif // __FREESTYLE_CURVE_ADVANCED_ITERATORS_H__
diff --git a/source/blender/freestyle/intern/stroke/CurveIterators.h b/source/blender/freestyle/intern/stroke/CurveIterators.h
new file mode 100644
index 00000000000..e3c63aefd5b
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/CurveIterators.h
@@ -0,0 +1,302 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_CURVE_ITERATORS_H__
+#define __FREESTYLE_CURVE_ITERATORS_H__
+
+/** \file blender/freestyle/intern/stroke/CurveIterators.h
+ * \ingroup freestyle
+ * \brief Iterators used to iterate over the elements of the Curve
+ * \author Stephane Grabli
+ * \date 01/08/2003
+ */
+
+#include "Curve.h"
+#include "Stroke.h"
+
+namespace CurveInternal {
+
+/*! iterator on a curve. Allows an iterating outside
+ * initial vertices. A CurvePoint is instanciated an returned
+ * when the iterator is dereferenced.
+ */
+
+class CurvePointIterator : public Interface0DIteratorNested
+{
+public:
+ friend class ::Curve;
+
+public:
+ float _CurvilinearLength;
+ float _step;
+ ::Curve::vertex_container::iterator __A;
+ ::Curve::vertex_container::iterator __B;
+ ::Curve::vertex_container::iterator _begin;
+ ::Curve::vertex_container::iterator _end;
+ int _n;
+ int _currentn;
+ float _t;
+ mutable CurvePoint _Point;
+ float _CurveLength;
+
+public:
+ inline CurvePointIterator(float step = 0.0f) : Interface0DIteratorNested()
+ {
+ _step = step;
+ _CurvilinearLength = 0.0f;
+ _t = 0.0f;
+ //_Point = 0;
+ _n = 0;
+ _currentn = 0;
+ _CurveLength = 0;
+ }
+
+ inline CurvePointIterator(const CurvePointIterator& iBrother) : Interface0DIteratorNested()
+ {
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _CurvilinearLength = iBrother._CurvilinearLength;
+ _step = iBrother._step;
+ _t = iBrother._t;
+ _Point = iBrother._Point;
+ _n = iBrother._n;
+ _currentn = iBrother._currentn;
+ _CurveLength = iBrother._CurveLength;
+ }
+
+ inline CurvePointIterator& operator=(const CurvePointIterator& iBrother)
+ {
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _CurvilinearLength = iBrother._CurvilinearLength;
+ _step = iBrother._step;
+ _t = iBrother._t;
+ _Point = iBrother._Point;
+ _n = iBrother._n;
+ _currentn = iBrother._currentn;
+ _CurveLength = iBrother._CurveLength;
+ return *this;
+ }
+
+ virtual ~CurvePointIterator() {}
+
+protected:
+ inline CurvePointIterator(::Curve::vertex_container::iterator iA, ::Curve::vertex_container::iterator iB,
+ ::Curve::vertex_container::iterator ibegin, ::Curve::vertex_container::iterator iend,
+ int currentn, int n, float iCurveLength, float step, float t = 0.0f,
+ float iCurvilinearLength = 0.0f)
+ : Interface0DIteratorNested()
+ {
+ __A = iA;
+ __B = iB;
+ _begin = ibegin;
+ _end = iend;
+ _CurvilinearLength = iCurvilinearLength;
+ _step = step;
+ _t = t;
+ _n = n;
+ _currentn = currentn;
+ _CurveLength = iCurveLength;
+ }
+
+public:
+ virtual CurvePointIterator *copy() const
+ {
+ return new CurvePointIterator(*this);
+ }
+
+ inline Interface0DIterator castToInterface0DIterator() const
+ {
+ Interface0DIterator ret(new CurveInternal::CurvePointIterator(*this));
+ return ret;
+ }
+
+ virtual string getExactTypeName() const
+ {
+ return "CurvePointIterator";
+ }
+
+ // operators
+ inline CurvePointIterator& operator++() // operator corresponding to ++i
+ {
+ increment();
+ return *this;
+ }
+
+ inline CurvePointIterator& operator--() // operator corresponding to --i
+ {
+ decrement();
+ return *this;
+ }
+
+ // comparibility
+ virtual bool operator==(const Interface0DIteratorNested& b) const
+ {
+ const CurvePointIterator *it_exact = dynamic_cast<const CurvePointIterator*>(&b);
+ if (!it_exact)
+ return false;
+ return ((__A == it_exact->__A) && (__B == it_exact->__B) && (_t == it_exact->_t));
+ }
+
+ // dereferencing
+ virtual CurvePoint& operator*()
+ {
+ return (_Point = CurvePoint(*__A, *__B, _t));
+ }
+
+ virtual CurvePoint *operator->()
+ {
+ return &(operator*());
+ }
+
+ virtual bool isBegin() const
+ {
+ if ((__A == _begin) && (_t < (float)M_EPSILON))
+ return true;
+ return false;
+ }
+
+ virtual bool isEnd() const
+ {
+ if (__B == _end)
+ return true;
+ return false;
+ }
+
+//protected:
+ virtual int increment()
+ {
+ if ((_currentn == _n - 1) && (_t == 1.0f)) {
+ // we're setting the iterator to end
+ ++__A;
+ ++__B;
+ ++_currentn;
+ _t = 0.0f;
+ return 0;
+ }
+
+ if (0 == _step) { // means we iterate over initial vertices
+ Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d());
+ _CurvilinearLength += (float)vec_tmp.norm();
+ if (_currentn == _n - 1) {
+ _t = 1.0f;
+ return 0;
+ }
+ ++__B;
+ ++__A;
+ ++_currentn;
+ return 0;
+ }
+
+ // compute the new position:
+ Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d());
+ float normAB = (float)vec_tmp2.norm();
+
+ if (normAB > M_EPSILON) {
+ _CurvilinearLength += _step;
+ _t = _t + _step / normAB;
+ }
+ else {
+ _t = 1.0f; // AB is a null segment, we're directly at its end
+ }
+ //if normAB ~= 0, we don't change these values
+ if (_t >= 1) {
+ _CurvilinearLength -= normAB * (_t - 1);
+ if (_currentn == _n - 1) {
+ _t = 1.0f;
+ }
+ else {
+ _t = 0.0f;
+ ++_currentn;
+ ++__A;
+ ++__B;
+ }
+ }
+ return 0;
+ }
+
+ virtual int decrement()
+ {
+ if (_t == 0.0f) { //we're at the beginning of the edge
+ _t = 1.0f;
+ --_currentn;
+ --__A;
+ --__B;
+ if (_currentn == _n - 1)
+ return 0;
+ }
+
+ if (0 == _step) { // means we iterate over initial vertices
+ Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d());
+ _CurvilinearLength -= (float)vec_tmp.norm();
+ _t = 0;
+ return 0;
+ }
+
+ // compute the new position:
+ Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d());
+ float normAB = (float)vec_tmp2.norm();
+
+ if (normAB > M_EPSILON) {
+ _CurvilinearLength -= _step;
+ _t = _t - _step / normAB;
+ }
+ else {
+ _t = -1.0f; // We just need a negative value here
+ }
+
+ // round value
+ if (fabs(_t) < (float)M_EPSILON)
+ _t = 0.0f;
+ if (_t < 0) {
+ if (_currentn == 0)
+ _CurvilinearLength = 0.0f;
+ else
+ _CurvilinearLength += normAB * (-_t);
+ _t = 0.0f;
+ }
+ return 0;
+ }
+
+ virtual float t() const
+ {
+ return _CurvilinearLength;
+ }
+
+ virtual float u() const
+ {
+ return _CurvilinearLength / _CurveLength;
+ }
+};
+
+} // end of namespace CurveInternal
+
+#endif // __FREESTYLE_CURVE_ITERATORS_H__
diff --git a/source/blender/freestyle/intern/stroke/Modifiers.h b/source/blender/freestyle/intern/stroke/Modifiers.h
new file mode 100644
index 00000000000..daa02002b7b
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Modifiers.h
@@ -0,0 +1,74 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_MODIFIERS_H__
+#define __FREESTYLE_MODIFIERS_H__
+
+/** \file blender/freestyle/intern/stroke/Modifiers.h
+ * \ingroup freestyle
+ * \brief modifiers...
+ * \author Stephane Grabli
+ * \date 05/01/2003
+ */
+
+#include "TimeStamp.h"
+
+/* ----------------------------------------- *
+ * *
+ * modifiers *
+ * *
+ * ----------------------------------------- */
+
+/*! Base class for modifiers.
+ * Modifiers are used in the Operators in order to "mark" the processed Interface1D.
+ */
+template<class Edge>
+struct EdgeModifier : public unary_function<Edge, void>
+{
+ /*! Default construction */
+ EdgeModifier() : unary_function<Edge, void>() {}
+
+ /*! the () operator */
+ virtual void operator()(Edge& iEdge) {}
+};
+
+/*! Modifier that sets the time stamp of an Interface1D to the time stamp of the system. */
+template<class Edge>
+struct TimestampModifier : public EdgeModifier<Edge>
+{
+ /*! Default constructor */
+ TimestampModifier() : EdgeModifier<Edge>() {}
+
+ /*! The () operator. */
+ virtual void operator()(Edge& iEdge)
+ {
+ TimeStamp *timestamp = TimeStamp::instance();
+ iEdge.setTimeStamp(timestamp->getTimeStamp());
+ }
+};
+
+#endif // MODIFIERS_H
diff --git a/source/blender/freestyle/intern/stroke/Module.h b/source/blender/freestyle/intern/stroke/Module.h
new file mode 100644
index 00000000000..99cb5a08ded
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Module.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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_MODULE_H__
+#define __FREESTYLE_MODULE_H__
+
+/** \file blender/freestyle/intern/stroke/Module.h
+ * \ingroup freestyle
+ * \brief Set the type of the module
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+#include "Canvas.h"
+#include "StyleModule.h"
+
+class Module
+{
+public:
+ static void setAlwaysRefresh(bool b = true)
+ {
+ getCurrentStyleModule()->setAlwaysRefresh(b);
+ }
+
+ static void setCausal(bool b = true)
+ {
+ getCurrentStyleModule()->setCausal(b);
+ }
+
+ static void setDrawable(bool b = true)
+ {
+ getCurrentStyleModule()->setDrawable(b);
+ }
+
+ static bool getAlwaysRefresh()
+ {
+ return getCurrentStyleModule()->getAlwaysRefresh();
+ }
+
+ static bool getCausal()
+ {
+ return getCurrentStyleModule()->getCausal();
+ }
+
+ static bool getDrawable()
+ {
+ return getCurrentStyleModule()->getDrawable();
+ }
+
+private:
+ static StyleModule *getCurrentStyleModule()
+ {
+ Canvas *canvas = Canvas::getInstance();
+ return canvas->getCurrentStyleModule();
+ }
+};
+
+#endif // __FREESTYLE_MODULE_H__
diff --git a/source/blender/freestyle/intern/stroke/Operators.cpp b/source/blender/freestyle/intern/stroke/Operators.cpp
new file mode 100644
index 00000000000..b9213b86acb
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Operators.cpp
@@ -0,0 +1,1281 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/stroke/Operators.cpp
+ * \ingroup freestyle
+ * \brief Class gathering stroke creation algorithms
+ * \author Stephane Grabli
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+#include <algorithm>
+#include <stdexcept>
+
+#include "Operators.h"
+#include "Canvas.h"
+#include "Stroke.h"
+
+#include "BKE_global.h"
+
+LIB_STROKE_EXPORT Operators::I1DContainer Operators::_current_view_edges_set;
+LIB_STROKE_EXPORT Operators::I1DContainer Operators::_current_chains_set;
+LIB_STROKE_EXPORT Operators::I1DContainer *Operators::_current_set = NULL;
+LIB_STROKE_EXPORT Operators::StrokesContainer Operators::_current_strokes_set;
+
+int Operators::select(UnaryPredicate1D& pred)
+{
+ if (!_current_set)
+ return 0;
+ if (_current_set->empty())
+ return 0;
+ I1DContainer new_set;
+ I1DContainer rejected;
+ Functions1D::ChainingTimeStampF1D cts;
+ Functions1D::TimeStampF1D ts;
+ I1DContainer::iterator it = _current_set->begin();
+ I1DContainer::iterator itbegin = it;
+ while (it != _current_set->end()) {
+ Interface1D *i1d = *it;
+ cts(*i1d); // mark everyone's chaining time stamp anyway
+ if (pred(*i1d) < 0) {
+ new_set.clear();
+ rejected.clear();
+ return -1;
+ }
+ if (pred.result) {
+ new_set.push_back(i1d);
+ ts(*i1d);
+ }
+ else {
+ rejected.push_back(i1d);
+ }
+ ++it;
+ }
+ if ((*itbegin)->getExactTypeName() != "ViewEdge") {
+ for (it = rejected.begin(); it != rejected.end(); ++it)
+ delete *it;
+ }
+ rejected.clear();
+ _current_set->clear();
+ *_current_set = new_set;
+ return 0;
+}
+
+
+int Operators::chain(ViewEdgeInternal::ViewEdgeIterator& it, UnaryPredicate1D& pred, UnaryFunction1D_void& modifier)
+{
+ if (_current_view_edges_set.empty())
+ return 0;
+
+ unsigned id = 0;
+ ViewEdge *edge;
+ I1DContainer new_chains_set;
+
+ for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
+ it_edge != _current_view_edges_set.end();
+ ++it_edge)
+ {
+ if (pred(**it_edge) < 0)
+ goto error;
+ if (pred.result)
+ continue;
+
+ edge = dynamic_cast<ViewEdge*>(*it_edge);
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+
+ Chain *new_chain = new Chain(id);
+ ++id;
+ while (TRUE) {
+ new_chain->push_viewedge_back(*it, it.getOrientation());
+ if (modifier(**it) < 0) {
+ delete new_chain;
+ goto error;
+ }
+ ++it;
+ if (it.isEnd())
+ break;
+ if (pred(**it) < 0) {
+ delete new_chain;
+ goto error;
+ }
+ if (pred.result)
+ break;
+ }
+ new_chains_set.push_back(new_chain);
+ }
+
+ if (!new_chains_set.empty()) {
+ for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
+ _current_chains_set.push_back(*it);
+ }
+ new_chains_set.clear();
+ _current_set = &_current_chains_set;
+ }
+ return 0;
+
+error:
+ for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
+ delete (*it);
+ }
+ new_chains_set.clear();
+ return -1;
+}
+
+
+int Operators::chain(ViewEdgeInternal::ViewEdgeIterator& it, UnaryPredicate1D& pred)
+{
+ if (_current_view_edges_set.empty())
+ return 0;
+
+ unsigned id = 0;
+ Functions1D::IncrementChainingTimeStampF1D ts;
+ Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp() + 1);
+ ViewEdge *edge;
+ I1DContainer new_chains_set;
+
+ for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
+ it_edge != _current_view_edges_set.end();
+ ++it_edge)
+ {
+ if (pred(**it_edge) < 0)
+ goto error;
+ if (pred.result)
+ continue;
+ if (pred_ts(**it_edge) < 0)
+ goto error;
+ if (pred_ts.result)
+ continue;
+
+ edge = dynamic_cast<ViewEdge*>(*it_edge);
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+
+ Chain *new_chain = new Chain(id);
+ ++id;
+ while (TRUE) {
+ new_chain->push_viewedge_back(*it, it.getOrientation());
+ ts(**it);
+ ++it;
+ if (it.isEnd())
+ break;
+ if (pred(**it) < 0) {
+ delete new_chain;
+ goto error;
+ }
+ if (pred.result)
+ break;
+ if (pred_ts(**it) < 0) {
+ delete new_chain;
+ goto error;
+ }
+ if (pred_ts.result)
+ break;
+ }
+ new_chains_set.push_back(new_chain);
+ }
+
+ if (!new_chains_set.empty()) {
+ for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
+ _current_chains_set.push_back(*it);
+ }
+ new_chains_set.clear();
+ _current_set = &_current_chains_set;
+ }
+ return 0;
+
+error:
+ for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
+ delete (*it);
+ }
+ new_chains_set.clear();
+ return -1;
+}
+
+
+#if 0
+void Operators::bidirectionalChain(ViewEdgeIterator& it, UnaryPredicate1D& pred, UnaryFunction1D_void& modifier)
+{
+ if (_current_view_edges_set.empty())
+ return;
+
+ unsigned id = 0;
+ ViewEdge *edge;
+ Chain *new_chain;
+
+ for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
+ it_edge != _current_view_edges_set.end();
+ ++it_edge)
+ {
+ if (pred(**it_edge))
+ continue;
+
+ edge = dynamic_cast<ViewEdge*>(*it_edge);
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+
+ Chain *new_chain = new Chain(id);
+ ++id;
+#if 0 // FIXME
+ ViewEdgeIterator it_back(it);
+ --it_back;
+#endif
+ do {
+ new_chain->push_viewedge_back(*it, it.getOrientation());
+ modifier(**it);
+ ++it;
+ } while (!it.isEnd() && !pred(**it));
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+ --it;
+ while (!it.isEnd() && !pred(**it)) {
+ new_chain->push_viewedge_front(*it, it.getOrientation());
+ modifier(**it);
+ --it;
+ }
+
+ _current_chains_set.push_back(new_chain);
+ }
+
+ if (!_current_chains_set.empty())
+ _current_set = &_current_chains_set;
+}
+
+void Operators::bidirectionalChain(ViewEdgeIterator& it, UnaryPredicate1D& pred)
+{
+ if (_current_view_edges_set.empty())
+ return;
+
+ unsigned id = 0;
+ Functions1D::IncrementChainingTimeStampF1D ts;
+ Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp() + 1);
+
+ ViewEdge *edge;
+ Chain *new_chain;
+
+ for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
+ it_edge != _current_view_edges_set.end();
+ ++it_edge)
+ {
+ if (pred(**it_edge) || pred_ts(**it_edge))
+ continue;
+
+ edge = dynamic_cast<ViewEdge*>(*it_edge);
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+
+ Chain *new_chain = new Chain(id);
+ ++id;
+#if 0 //FIXME
+ ViewEdgeIterator it_back(it);
+ --it_back;
+#endif
+ do {
+ new_chain->push_viewedge_back(*it, it.getOrientation());
+ ts(**it);
+ ++it;
+ } while (!it.isEnd() && !pred(**it) && !pred_ts(**it));
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+ --it;
+ while (!it.isEnd() && !pred(**it) && !pred_ts(**it)) {
+ new_chain->push_viewedge_front(*it, it.getOrientation());
+ ts(**it);
+ --it;
+ }
+
+ _current_chains_set.push_back(new_chain);
+ }
+
+ if (!_current_chains_set.empty())
+ _current_set = &_current_chains_set;
+}
+#endif
+
+int Operators::bidirectionalChain(ChainingIterator& it, UnaryPredicate1D& pred)
+{
+ if (_current_view_edges_set.empty())
+ return 0;
+
+ unsigned id = 0;
+ Functions1D::IncrementChainingTimeStampF1D ts;
+ Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp() + 1);
+ ViewEdge *edge;
+ I1DContainer new_chains_set;
+
+ for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
+ it_edge != _current_view_edges_set.end();
+ ++it_edge)
+ {
+ if (pred(**it_edge) < 0)
+ goto error;
+ if (pred.result)
+ continue;
+ if (pred_ts(**it_edge) < 0)
+ goto error;
+ if (pred_ts.result)
+ continue;
+
+ edge = dynamic_cast<ViewEdge*>(*it_edge);
+ // re-init iterator
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+ it.setOrientation(true);
+ if (it.init() < 0)
+ goto error;
+
+ Chain *new_chain = new Chain(id);
+ ++id;
+#if 0 // FIXME
+ ViewEdgeIterator it_back(it);
+ --it_back;
+#endif
+ while (TRUE) {
+ new_chain->push_viewedge_back(*it, it.getOrientation());
+ ts(**it);
+ if (it.increment() < 0) {
+ delete new_chain;
+ goto error;
+ }
+ if (it.isEnd())
+ break;
+ if (pred(**it) < 0) {
+ delete new_chain;
+ goto error;
+ }
+ if (pred.result)
+ break;
+ }
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+ it.setOrientation(true);
+ if (it.decrement() < 0) {
+ delete new_chain;
+ goto error;
+ }
+ while (!it.isEnd()) {
+ if (pred(**it) < 0) {
+ delete new_chain;
+ goto error;
+ }
+ if (pred.result)
+ break;
+ new_chain->push_viewedge_front(*it, it.getOrientation());
+ ts(**it);
+ if (it.decrement() < 0) {
+ delete new_chain;
+ goto error;
+ }
+ }
+ new_chains_set.push_back(new_chain);
+ }
+
+ if (!new_chains_set.empty()) {
+ for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
+ _current_chains_set.push_back(*it);
+ }
+ new_chains_set.clear();
+ _current_set = &_current_chains_set;
+ }
+ return 0;
+
+error:
+ for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
+ delete (*it);
+ }
+ new_chains_set.clear();
+ return -1;
+}
+
+int Operators::bidirectionalChain(ChainingIterator& it)
+{
+ if (_current_view_edges_set.empty())
+ return 0;
+
+ unsigned id = 0;
+ Functions1D::IncrementChainingTimeStampF1D ts;
+ Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp() + 1);
+ ViewEdge *edge;
+ I1DContainer new_chains_set;
+
+ for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
+ it_edge != _current_view_edges_set.end();
+ ++it_edge)
+ {
+ if (pred_ts(**it_edge) < 0)
+ goto error;
+ if (pred_ts.result)
+ continue;
+
+ edge = dynamic_cast<ViewEdge*>(*it_edge);
+ // re-init iterator
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+ it.setOrientation(true);
+ if (it.init() < 0)
+ goto error;
+
+ Chain *new_chain = new Chain(id);
+ ++id;
+#if 0 // FIXME
+ ViewEdgeIterator it_back(it);
+ --it_back;
+#endif
+ do {
+ new_chain->push_viewedge_back(*it, it.getOrientation());
+ ts(**it);
+ if (it.increment() < 0) { // FIXME
+ delete new_chain;
+ goto error;
+ }
+ } while (!it.isEnd());
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+ it.setOrientation(true);
+ if (it.decrement() < 0) { // FIXME
+ delete new_chain;
+ goto error;
+ }
+ while (!it.isEnd()) {
+ new_chain->push_viewedge_front(*it, it.getOrientation());
+ ts(**it);
+ if (it.decrement() < 0) { // FIXME
+ delete new_chain;
+ goto error;
+ }
+ }
+ new_chains_set.push_back(new_chain);
+ }
+
+ if (!new_chains_set.empty()) {
+ for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
+ _current_chains_set.push_back(*it);
+ }
+ new_chains_set.clear();
+ _current_set = &_current_chains_set;
+ }
+ return 0;
+
+error:
+ for (I1DContainer::iterator it = new_chains_set.begin(); it != new_chains_set.end(); ++it) {
+ delete (*it);
+ }
+ new_chains_set.clear();
+ return -1;
+}
+
+int Operators::sequentialSplit(UnaryPredicate0D& pred, float sampling)
+{
+ if (_current_chains_set.empty()) {
+ cerr << "Warning: current set empty" << endl;
+ return 0;
+ }
+ CurvePoint *point;
+ Chain *new_curve;
+ I1DContainer splitted_chains;
+ Interface0DIterator first;
+ Interface0DIterator end;
+ Interface0DIterator last;
+ Interface0DIterator it;
+ I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end();
+ for (; cit != citend; ++cit) {
+ Id currentId = (*cit)->getId();
+ new_curve = new Chain(currentId);
+ first = (*cit)->pointsBegin(sampling);
+ end = (*cit)->pointsEnd(sampling);
+ last = end;
+ --last;
+ it = first;
+
+ point = dynamic_cast<CurvePoint*>(&(*it));
+ new_curve->push_vertex_back(point);
+ ++it;
+ for (; it != end; ++it) {
+ point = dynamic_cast<CurvePoint*>(&(*it));
+ new_curve->push_vertex_back(point);
+ if (pred(it) < 0) {
+ delete new_curve;
+ goto error;
+ }
+ if (pred.result && (it != last)) {
+ splitted_chains.push_back(new_curve);
+ currentId.setSecond(currentId.getSecond() + 1);
+ new_curve = new Chain(currentId);
+ new_curve->push_vertex_back(point);
+ }
+ }
+ if (new_curve->nSegments() == 0) {
+ delete new_curve;
+ return 0;
+ }
+
+ splitted_chains.push_back(new_curve);
+ }
+
+ // Update the current set of chains:
+ cit = _current_chains_set.begin();
+ for (; cit != citend; ++cit) {
+ delete (*cit);
+ }
+ _current_chains_set.clear();
+#if 0
+ _current_chains_set = splitted_chains;
+#else
+ for (cit = splitted_chains.begin(), citend = splitted_chains.end(); cit != citend; ++cit) {
+ if ((*cit)->getLength2D() < M_EPSILON) {
+ delete (*cit);
+ continue;
+ }
+ _current_chains_set.push_back(*cit);
+ }
+#endif
+ splitted_chains.clear();
+
+ if (!_current_chains_set.empty())
+ _current_set = &_current_chains_set;
+ return 0;
+
+error:
+ cit = splitted_chains.begin();
+ citend = splitted_chains.end();
+ for (; cit != citend; ++cit) {
+ delete (*cit);
+ }
+ splitted_chains.clear();
+ return -1;
+}
+
+int Operators::sequentialSplit(UnaryPredicate0D& startingPred, UnaryPredicate0D& stoppingPred, float sampling)
+{
+ if (_current_chains_set.empty()) {
+ cerr << "Warning: current set empty" << endl;
+ return 0;
+ }
+ CurvePoint *point;
+ Chain *new_curve;
+ I1DContainer splitted_chains;
+ Interface0DIterator first;
+ Interface0DIterator end;
+ Interface0DIterator last;
+ Interface0DIterator itStart;
+ Interface0DIterator itStop;
+ I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end();
+ for (; cit != citend; ++cit) {
+ Id currentId = (*cit)->getId();
+ first = (*cit)->pointsBegin(sampling);
+ end = (*cit)->pointsEnd(sampling);
+ last = end;
+ --last;
+ itStart = first;
+ do {
+ itStop = itStart;
+ ++itStop;
+
+ new_curve = new Chain(currentId);
+ currentId.setSecond(currentId.getSecond() + 1);
+
+ point = dynamic_cast<CurvePoint*>(&(*itStart));
+ new_curve->push_vertex_back(point);
+ do {
+ point = dynamic_cast<CurvePoint*>(&(*itStop));
+ new_curve->push_vertex_back(point);
+ ++itStop;
+ if (itStop == end)
+ break;
+ if (stoppingPred(itStop) < 0) {
+ delete new_curve;
+ goto error;
+ }
+ } while (!stoppingPred.result);
+ if (itStop != end) {
+ point = dynamic_cast<CurvePoint*>(&(*itStop));
+ new_curve->push_vertex_back(point);
+ }
+ if (new_curve->nSegments() == 0) {
+ delete new_curve;
+ }
+ else {
+ splitted_chains.push_back(new_curve);
+ }
+ // find next start
+ do {
+ ++itStart;
+ if (itStart == end)
+ break;
+ if (startingPred(itStart) < 0)
+ goto error;
+ } while (!startingPred.result);
+ } while ((itStart != end) && (itStart != last));
+ }
+
+ // Update the current set of chains:
+ cit = _current_chains_set.begin();
+ for (; cit != citend; ++cit) {
+ delete (*cit);
+ }
+ _current_chains_set.clear();
+#if 0
+ _current_chains_set = splitted_chains;
+#else
+ for (cit = splitted_chains.begin(), citend = splitted_chains.end(); cit != citend; ++cit) {
+ if ((*cit)->getLength2D() < M_EPSILON) {
+ delete (*cit);
+ continue;
+ }
+ _current_chains_set.push_back(*cit);
+ }
+#endif
+ splitted_chains.clear();
+
+ if (!_current_chains_set.empty())
+ _current_set = &_current_chains_set;
+ return 0;
+
+error:
+ cit = splitted_chains.begin();
+ citend = splitted_chains.end();
+ for (; cit != citend; ++cit) {
+ delete (*cit);
+ }
+ splitted_chains.clear();
+ return -1;
+}
+
+#include "CurveIterators.h"
+
+// Internal function
+static int __recursiveSplit(Chain *_curve, UnaryFunction0D<double>& func, UnaryPredicate1D& pred, float sampling,
+ Operators::I1DContainer& newChains, Operators::I1DContainer& splitted_chains)
+{
+ if (((_curve->nSegments() == 1) && (sampling == 0)) || (_curve->getLength2D() <= sampling)) {
+ newChains.push_back(_curve);
+ return 0;
+ }
+
+ CurveInternal::CurvePointIterator first = _curve->curvePointsBegin(sampling);
+ CurveInternal::CurvePointIterator second = first;
+ ++second;
+ CurveInternal::CurvePointIterator end = _curve->curvePointsEnd(sampling);
+ CurveInternal::CurvePointIterator it = second;
+ CurveInternal::CurvePointIterator split = second;
+ Interface0DIterator it0d = it.castToInterface0DIterator();
+ real _min = FLT_MAX; // func(it0d);
+ ++it;
+ CurveInternal::CurvePointIterator next = it;
+ ++next;
+
+ bool bsplit = false;
+ for (; ((it != end) && (next != end)); ++it, ++next) {
+ it0d = it.castToInterface0DIterator();
+ if (func(it0d) < 0)
+ return -1;
+ if (func.result < _min) {
+ _min = func.result;
+ split = it;
+ bsplit = true;
+ }
+ }
+
+ if (!bsplit) { // we didn't find any minimum
+ newChains.push_back(_curve);
+ return 0;
+ }
+
+ // retrieves the current splitting id
+ Id *newId = _curve->getSplittingId();
+ if (newId == 0) {
+ newId = new Id(_curve->getId());
+ _curve->setSplittingId(newId);
+ }
+
+ Chain *new_curve_a = new Chain(*newId);
+ newId->setSecond(newId->getSecond() + 1);
+ new_curve_a->setSplittingId(newId);
+ Chain *new_curve_b = new Chain(*newId);
+ newId->setSecond(newId->getSecond() + 1);
+ new_curve_b->setSplittingId(newId);
+
+ CurveInternal::CurvePointIterator vit = _curve->curveVerticesBegin(), vitend = _curve->curveVerticesEnd();
+ CurveInternal::CurvePointIterator vnext = vit;
+ ++vnext;
+
+ for (; (vit != vitend) && (vnext != vitend) && (vnext._CurvilinearLength < split._CurvilinearLength);
+ ++vit, ++vnext)
+ {
+ new_curve_a->push_vertex_back(&(*vit));
+ }
+ if ((vit == vitend) || (vnext == vitend)) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "The split takes place in bad location" << endl;
+ }
+ newChains.push_back(_curve);
+ delete new_curve_a;
+ delete new_curve_b;
+ return 0;
+ }
+
+ // build the two resulting chains
+ new_curve_a->push_vertex_back(&(*vit));
+ new_curve_a->push_vertex_back(&(*split));
+ new_curve_b->push_vertex_back(&(*split));
+
+ for (vit = vnext; vit != vitend; ++vit)
+ new_curve_b->push_vertex_back(&(*vit));
+
+ // let's check whether one or two of the two new curves satisfy the stopping condition or not.
+ // (if one of them satisfies it, we don't split)
+ if (pred(*new_curve_a) < 0 || (!pred.result && pred(*new_curve_b) < 0)) {
+ delete new_curve_a;
+ delete new_curve_b;
+ return -1;
+ }
+ if (pred.result) {
+ // we don't actually create these two chains
+ newChains.push_back(_curve);
+ delete new_curve_a;
+ delete new_curve_b;
+ return 0;
+ }
+ // here we know we'll split _curve:
+ splitted_chains.push_back(_curve);
+
+ __recursiveSplit(new_curve_a, func, pred, sampling, newChains, splitted_chains);
+ __recursiveSplit(new_curve_b, func, pred, sampling, newChains, splitted_chains);
+ return 0;
+}
+
+int Operators::recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate1D& pred, float sampling)
+{
+ if (_current_chains_set.empty()) {
+ cerr << "Warning: current set empty" << endl;
+ return 0;
+ }
+
+ Chain *currentChain = 0;
+ I1DContainer splitted_chains;
+ I1DContainer newChains;
+ I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end();
+ for (; cit != citend; ++cit) {
+ currentChain = dynamic_cast<Chain*>(*cit);
+ if (!currentChain)
+ continue;
+ // let's check the first one:
+ if (pred(*currentChain) < 0)
+ return -1;
+ if (!pred.result) {
+ __recursiveSplit(currentChain, func, pred, sampling, newChains, splitted_chains);
+ }
+ else {
+ newChains.push_back(currentChain);
+ }
+ }
+ // Update the current set of chains:
+ if (!splitted_chains.empty()) {
+ for (cit = splitted_chains.begin(), citend = splitted_chains.end(); cit != citend; ++cit) {
+ delete (*cit);
+ }
+ splitted_chains.clear();
+ }
+
+ _current_chains_set.clear();
+#if 0
+ _current_chains_set = newChains;
+#else
+ for (cit = newChains.begin(), citend = newChains.end(); cit != citend; ++cit) {
+ if ((*cit)->getLength2D() < M_EPSILON) {
+ delete (*cit);
+ continue;
+ }
+ _current_chains_set.push_back(*cit);
+ }
+#endif
+ newChains.clear();
+
+ if (!_current_chains_set.empty())
+ _current_set = &_current_chains_set;
+ return 0;
+}
+
+
+// recursive split with pred 0D
+static int __recursiveSplit(Chain *_curve, UnaryFunction0D<double>& func, UnaryPredicate0D& pred0d,
+ UnaryPredicate1D& pred, float sampling,
+ Operators::I1DContainer& newChains, Operators::I1DContainer& splitted_chains)
+{
+ if (((_curve->nSegments() == 1) && (sampling == 0)) || (_curve->getLength2D() <= sampling)) {
+ newChains.push_back(_curve);
+ return 0;
+ }
+
+ CurveInternal::CurvePointIterator first = _curve->curvePointsBegin(sampling);
+ CurveInternal::CurvePointIterator second = first;
+ ++second;
+ CurveInternal::CurvePointIterator end = _curve->curvePointsEnd(sampling);
+ CurveInternal::CurvePointIterator it = second;
+ CurveInternal::CurvePointIterator split = second;
+ Interface0DIterator it0d = it.castToInterface0DIterator();
+#if 0
+ real _min = func(it0d);
+ ++it;
+#endif
+ real _min = FLT_MAX;
+ ++it;
+ real mean = 0.f;
+ //soc unused - real variance = 0.0f;
+ unsigned count = 0;
+ CurveInternal::CurvePointIterator next = it;
+ ++next;
+
+ bool bsplit = false;
+ for (; ((it != end) && (next != end)); ++it, ++next) {
+ ++count;
+ it0d = it.castToInterface0DIterator();
+ if (pred0d(it0d) < 0)
+ return -1;
+ if (!pred0d.result)
+ continue;
+ if (func(it0d) < 0)
+ return -1;
+ mean += func.result;
+ if (func.result < _min) {
+ _min = func.result;
+ split = it;
+ bsplit = true;
+ }
+ }
+ mean /= (float)count;
+
+ //if ((!bsplit) || (mean - _min > mean)) { // we didn't find any minimum
+ if (!bsplit) { // we didn't find any minimum
+ newChains.push_back(_curve);
+ return 0;
+ }
+
+ // retrieves the current splitting id
+ Id *newId = _curve->getSplittingId();
+ if (newId == NULL) {
+ newId = new Id(_curve->getId());
+ _curve->setSplittingId(newId);
+ }
+
+ Chain *new_curve_a = new Chain(*newId);
+ newId->setSecond(newId->getSecond() + 1);
+ new_curve_a->setSplittingId(newId);
+ Chain *new_curve_b = new Chain(*newId);
+ newId->setSecond(newId->getSecond() + 1);
+ new_curve_b->setSplittingId(newId);
+
+ CurveInternal::CurvePointIterator vit = _curve->curveVerticesBegin(), vitend = _curve->curveVerticesEnd();
+ CurveInternal::CurvePointIterator vnext = vit;
+ ++vnext;
+
+ for (;
+ (vit != vitend) && (vnext != vitend) && (vnext._CurvilinearLength < split._CurvilinearLength);
+ ++vit, ++vnext)
+ {
+ new_curve_a->push_vertex_back(&(*vit));
+ }
+ if ((vit == vitend) || (vnext == vitend)) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "The split takes place in bad location" << endl;
+ }
+ newChains.push_back(_curve);
+ delete new_curve_a;
+ delete new_curve_b;
+ return 0;
+ }
+
+ // build the two resulting chains
+ new_curve_a->push_vertex_back(&(*vit));
+ new_curve_a->push_vertex_back(&(*split));
+ new_curve_b->push_vertex_back(&(*split));
+
+ for (vit = vnext; vit != vitend; ++vit)
+ new_curve_b->push_vertex_back(&(*vit));
+
+ // let's check whether one or two of the two new curves satisfy the stopping condition or not.
+ // (if one of them satisfies it, we don't split)
+ if (pred(*new_curve_a) < 0 || (!pred.result && pred(*new_curve_b) < 0)) {
+ delete new_curve_a;
+ delete new_curve_b;
+ return -1;
+ }
+ if (pred.result) {
+ // we don't actually create these two chains
+ newChains.push_back(_curve);
+ delete new_curve_a;
+ delete new_curve_b;
+ return 0;
+ }
+ // here we know we'll split _curve:
+ splitted_chains.push_back(_curve);
+
+ __recursiveSplit(new_curve_a, func, pred0d, pred, sampling, newChains, splitted_chains);
+ __recursiveSplit(new_curve_b, func, pred0d, pred, sampling, newChains, splitted_chains);
+ return 0;
+}
+
+int Operators::recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate0D& pred0d, UnaryPredicate1D& pred,
+ float sampling)
+{
+ if (_current_chains_set.empty()) {
+ cerr << "Warning: current set empty" << endl;
+ return 0;
+ }
+
+ Chain *currentChain = 0;
+ I1DContainer splitted_chains;
+ I1DContainer newChains;
+ I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end();
+ for (; cit != citend; ++cit) {
+ currentChain = dynamic_cast<Chain*>(*cit);
+ if (!currentChain)
+ continue;
+ // let's check the first one:
+ if (pred(*currentChain) < 0)
+ return -1;
+ if (!pred.result) {
+ __recursiveSplit(currentChain, func, pred0d, pred, sampling, newChains, splitted_chains);
+ }
+ else {
+ newChains.push_back(currentChain);
+ }
+ }
+ // Update the current set of chains:
+ if (!splitted_chains.empty()) {
+ for (cit = splitted_chains.begin(), citend = splitted_chains.end(); cit != citend; ++cit) {
+ delete (*cit);
+ }
+ splitted_chains.clear();
+ }
+
+ _current_chains_set.clear();
+#if 0
+ _current_chains_set = newChains;
+#else
+ for (cit = newChains.begin(), citend = newChains.end(); cit != citend; ++cit) {
+ if ((*cit)->getLength2D() < M_EPSILON) {
+ delete (*cit);
+ continue;
+ }
+ _current_chains_set.push_back(*cit);
+ }
+#endif
+ newChains.clear();
+
+ if (!_current_chains_set.empty())
+ _current_set = &_current_chains_set;
+ return 0;
+}
+
+// Internal class
+class PredicateWrapper
+{
+public:
+ inline PredicateWrapper(BinaryPredicate1D& pred)
+ {
+ _pred = &pred;
+ }
+
+ inline bool operator()(Interface1D *i1, Interface1D *i2)
+ {
+ if ((*_pred)(*i1, *i2) < 0)
+ throw std::runtime_error("comparison failed");
+ return _pred->result;
+ }
+
+private:
+ BinaryPredicate1D *_pred;
+};
+
+int Operators::sort(BinaryPredicate1D& pred)
+{
+ if (!_current_set)
+ return 0;
+ PredicateWrapper wrapper(pred);
+ try {
+ std::sort(_current_set->begin(), _current_set->end(), wrapper);
+ }
+ catch (std::runtime_error &e) {
+ cerr << "Warning: Operator.sort(): " << e.what() << endl;
+ return -1;
+ }
+ return 0;
+}
+
+static Stroke *createStroke(Interface1D& inter)
+{
+ Stroke *stroke = new Stroke;
+ stroke->setId(inter.getId());
+
+ float currentCurvilignAbscissa = 0.0f;
+
+ Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd();
+ Interface0DIterator itfirst = it;
+
+ Vec2r current(it->getPoint2D());
+ Vec2r previous = current;
+ SVertex *sv;
+ CurvePoint *cp;
+ StrokeVertex *stroke_vertex = NULL;
+ bool hasSingularity = false;
+
+ do {
+ cp = dynamic_cast<CurvePoint*>(&(*it));
+ if (!cp) {
+ sv = dynamic_cast<SVertex*>(&(*it));
+ if (!sv) {
+ cerr << "Warning: unexpected Vertex type" << endl;
+ continue;
+ }
+ stroke_vertex = new StrokeVertex(sv);
+ }
+ else {
+ stroke_vertex = new StrokeVertex(cp);
+ }
+ current = stroke_vertex->getPoint2D();
+ Vec2r vec_tmp(current - previous);
+ real dist = vec_tmp.norm();
+ if (dist < 1.0e-6)
+ hasSingularity = true;
+ currentCurvilignAbscissa += dist;
+ stroke_vertex->setCurvilinearAbscissa(currentCurvilignAbscissa);
+ stroke->push_back(stroke_vertex);
+ previous = current;
+ ++it;
+ } while ((it != itend) && (it != itfirst));
+
+ if (it == itfirst) {
+ // Add last vertex:
+ cp = dynamic_cast<CurvePoint*>(&(*it));
+ if (!cp) {
+ sv = dynamic_cast<SVertex*>(&(*it));
+ if (!sv)
+ cerr << "Warning: unexpected Vertex type" << endl;
+ else
+ stroke_vertex = new StrokeVertex(sv);
+ }
+ else {
+ stroke_vertex = new StrokeVertex(cp);
+ }
+ current = stroke_vertex->getPoint2D();
+ Vec2r vec_tmp(current - previous);
+ real dist = vec_tmp.norm();
+ if (dist < 1.0e-6)
+ hasSingularity = true;
+ currentCurvilignAbscissa += dist;
+ stroke_vertex->setCurvilinearAbscissa(currentCurvilignAbscissa);
+ stroke->push_back(stroke_vertex);
+ }
+ // Discard the stroke if the number of stroke vertices is less than two
+ if (stroke->strokeVerticesSize() < 2) {
+ delete stroke;
+ return NULL;
+ }
+ stroke->setLength(currentCurvilignAbscissa);
+ if (hasSingularity) {
+ // Try to address singular points such that the distance between two subsequent vertices
+ // are smaller than epsilon.
+ Interface0DIterator v = stroke->verticesBegin();
+ Interface0DIterator vnext = v;
+ ++vnext;
+ Vec2r next((*v).getPoint2D());
+ while (!vnext.isEnd()) {
+ current = next;
+ next = (*vnext).getPoint2D();
+ if ((next - current).norm() < 1.0e-6) {
+ Interface0DIterator vprevious = v;
+ if (!vprevious.isBegin())
+ --vprevious;
+
+ // collect a set of overlapping vertices
+ std::vector<Interface0D *> overlapping_vertices;
+ overlapping_vertices.push_back(&(*v));
+ do {
+ overlapping_vertices.push_back(&(*vnext));
+ current = next;
+ ++v;
+ ++vnext;
+ if (vnext.isEnd())
+ break;
+ next = (*vnext).getPoint2D();
+ } while ((next - current).norm() < 1.0e-6);
+
+ Vec2r target;
+ bool reverse;
+ if (!vnext.isEnd()) {
+ target = (*vnext).getPoint2D();
+ reverse = false;
+ }
+ else if (!vprevious.isBegin()) {
+ target = (*vprevious).getPoint2D();
+ reverse = true;
+ }
+ else {
+ // Discard the stroke because all stroke vertices are overlapping
+ delete stroke;
+ return NULL;
+ }
+ current = overlapping_vertices.front()->getPoint2D();
+ Vec2r dir(target - current);
+ real dist = dir.norm();
+ real len = 1.0e-3; // default offset length
+ int nvert = overlapping_vertices.size();
+ if (dist < len * nvert) {
+ len = dist / nvert;
+ }
+ dir.normalize();
+ Vec2r offset(dir * len);
+ // add the offset to the overlapping vertices
+ StrokeVertex *sv;
+ std::vector<Interface0D *>::iterator it = overlapping_vertices.begin();
+ if (!reverse) {
+ for (int n = 1; n < nvert; n++) {
+ sv = dynamic_cast<StrokeVertex*>(*it);
+ sv->setPoint(sv->getPoint() + offset * n);
+ ++it;
+ }
+ }
+ else {
+ int last = nvert - 1;
+ for (int n = 0; n < last; n++) {
+ sv = dynamic_cast<StrokeVertex*>(*it);
+ sv->setPoint(sv->getPoint() + offset * (last - n));
+ ++it;
+ }
+ }
+
+ if (vnext.isEnd())
+ break;
+ }
+ ++v;
+ ++vnext;
+ }
+ }
+ {
+ // Check if the stroke no longer contains singular points
+ Interface0DIterator v = stroke->verticesBegin();
+ Interface0DIterator vnext = v;
+ ++vnext;
+ Vec2r next((*v).getPoint2D());
+ bool warning = false;
+ while (!vnext.isEnd()) {
+ current = next;
+ next = (*vnext).getPoint2D();
+ if ((next - current).norm() < 1.0e-6) {
+ warning = true;
+ break;
+ }
+ ++v;
+ ++vnext;
+ }
+ if (warning && G.debug & G_DEBUG_FREESTYLE) {
+ printf("Warning: stroke contains singular points.\n");
+ }
+ }
+ return stroke;
+}
+
+
+inline int applyShading(Stroke& stroke, vector<StrokeShader*>& shaders)
+{
+ for (vector<StrokeShader*>::iterator it = shaders.begin(); it != shaders.end(); ++it) {
+ if ((*it)->shade(stroke) < 0) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+int Operators::create(UnaryPredicate1D& pred, vector<StrokeShader*> shaders)
+{
+ //Canvas* canvas = Canvas::getInstance();
+ if (!_current_set) {
+ cerr << "Warning: current set empty" << endl;
+ return 0;
+ }
+ StrokesContainer new_strokes_set;
+ for (Operators::I1DContainer::iterator it = _current_set->begin(); it != _current_set->end(); ++it) {
+ if (pred(**it) < 0)
+ goto error;
+ if (!pred.result)
+ continue;
+
+ Stroke *stroke = createStroke(**it);
+ if (stroke) {
+ if (applyShading(*stroke, shaders) < 0) {
+ delete stroke;
+ goto error;
+ }
+ //canvas->RenderStroke(stroke);
+ new_strokes_set.push_back(stroke);
+ }
+ }
+
+ for (StrokesContainer::iterator it = new_strokes_set.begin(); it != new_strokes_set.end(); ++it) {
+ _current_strokes_set.push_back(*it);
+ }
+ new_strokes_set.clear();
+ return 0;
+
+error:
+ for (StrokesContainer::iterator it = new_strokes_set.begin(); it != new_strokes_set.end(); ++it) {
+ delete (*it);
+ }
+ new_strokes_set.clear();
+ return -1;
+}
+
+void Operators::reset()
+{
+ ViewMap *vm = ViewMap::getInstance();
+ if (!vm) {
+ cerr << "Error: no ViewMap computed yet" << endl;
+ return;
+ }
+ _current_view_edges_set.clear();
+ 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) {
+ if ((*ve)->getLength2D() < M_EPSILON)
+ continue;
+ _current_view_edges_set.push_back(*ve);
+ }
+#endif
+ _current_set = &_current_view_edges_set;
+ _current_strokes_set.clear();
+}
diff --git a/source/blender/freestyle/intern/stroke/Operators.h b/source/blender/freestyle/intern/stroke/Operators.h
new file mode 100644
index 00000000000..aafbc2350d9
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Operators.h
@@ -0,0 +1,274 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_OPERATORS_H__
+#define __FREESTYLE_OPERATORS_H__
+
+/** \file blender/freestyle/intern/stroke/Operators.h
+ * \ingroup freestyle
+ * \brief Class gathering stroke creation algorithms
+ * \author Stephane Grabli
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+#include <iostream>
+#include <vector>
+
+#include "Chain.h"
+#include "ChainingIterators.h"
+#include "Predicates0D.h"
+#include "Predicates1D.h"
+#include "StrokeShader.h"
+
+#include "../system/TimeStamp.h"
+
+#include "../view_map/Interface1D.h"
+#include "../view_map/ViewMap.h"
+
+/*! Class defining the operators used in a style module.
+ * There are 4 classes of operators: Selection, Chaining, Splitting and Creating. All these operators are
+ * user controlled in the scripting language through Functors, Predicates and Shaders that are taken as arguments.
+ */
+class LIB_STROKE_EXPORT Operators {
+
+public:
+ typedef vector<Interface1D*> I1DContainer;
+ typedef vector<Stroke*> StrokesContainer;
+
+ //
+ // Operators
+ //
+ ////////////////////////////////////////////////
+
+ /*! Selects the ViewEdges of the ViewMap verifying a specified condition.
+ * \param pred The predicate expressing this condition
+ */
+ static int select(UnaryPredicate1D& pred);
+
+ /*! Builds a set of chains from the current set of ViewEdges.
+ * Each ViewEdge of the current list starts a new chain. The chaining operator then iterates over the ViewEdges
+ * of the ViewMap using the user specified iterator.
+ * This operator only iterates using the increment operator and is therefore unidirectional.
+ * \param it
+ * The iterator on the ViewEdges of the ViewMap. It contains the chaining rule.
+ * \param pred
+ * The predicate on the ViewEdge that expresses the stopping condition.
+ * \param modifier
+ * A function that takes a ViewEdge as argument and that is used to modify the processed ViewEdge
+ * state (the timestamp incrementation is a typical illustration of such a modifier)
+ */
+ static int chain(ViewEdgeInternal::ViewEdgeIterator& it, UnaryPredicate1D& pred, UnaryFunction1D_void& modifier);
+
+ /*! Builds a set of chains from the current set of ViewEdges.
+ * Each ViewEdge of the current list starts a new chain. The chaining operator then iterates over the ViewEdges
+ * of the ViewMap using the user specified iterator.
+ * This operator only iterates using the increment operator and is therefore unidirectional.
+ * This chaining operator is different from the previous one because it doesn't take any modifier as argument.
+ * Indeed, the time stamp (insuring that a ViewEdge is processed one time) is automatically managed in this case.
+ * \param it
+ * The iterator on the ViewEdges of the ViewMap. It contains the chaining rule.
+ * \param pred
+ * The predicate on the ViewEdge that expresses the stopping condition.
+ */
+ static int chain(ViewEdgeInternal::ViewEdgeIterator& it, UnaryPredicate1D& pred);
+
+ /*! Builds a set of chains from the current set of ViewEdges.
+ * Each ViewEdge of the current list potentially starts a new chain. The chaining operator then iterates over
+ * the ViewEdges of the ViewMap using the user specified iterator.
+ * This operator iterates both using the increment and decrement operators and is therefore bidirectional.
+ * This operator works with a ChainingIterator which contains the chaining rules. It is this last one which can
+ * be told to chain only edges that belong to the selection or not to process twice a ViewEdge during the chaining.
+ * Each time a ViewEdge is added to a chain, its chaining time stamp is incremented. This allows you to keep track
+ * of the number of chains to which a ViewEdge belongs to.
+ * \param it
+ * The ChainingIterator on the ViewEdges of the ViewMap. It contains the chaining rule.
+ * \param pred
+ * The predicate on the ViewEdge that expresses the stopping condition.
+ */
+ static int bidirectionalChain(ChainingIterator& it, UnaryPredicate1D& pred);
+
+ /*! The only difference with the above bidirectional chaining algorithm is that we don't need to pass a stopping
+ * criterion. This might be desirable when the stopping criterion is already contained in the iterator definition.
+ * Builds a set of chains from the current set of ViewEdges.
+ * Each ViewEdge of the current list potentially starts a new chain. The chaining operator then iterates over
+ * the ViewEdges of the ViewMap using the user specified iterator.
+ * This operator iterates both using the increment and decrement operators and is therefore bidirectional.
+ * This operator works with a ChainingIterator which contains the chaining rules. It is this last one which can be
+ * told to chain only edges that belong to the selection or not to process twice a ViewEdge during the chaining.
+ * Each time a ViewEdge is added to a chain, its chaining time stamp is incremented. This allows you to keep track
+ * of the number of chains to which a ViewEdge belongs to.
+ * \param it
+ * The ChainingIterator on the ViewEdges of the ViewMap. It contains the chaining rule.
+ */
+ static int bidirectionalChain(ChainingIterator& it);
+
+ /*! Splits each chain of the current set of chains in a sequential way.
+ * The points of each chain are processed (with a specified sampling) sequentially.
+ * Each time a user specified starting condition is verified, a new chain begins and ends as soon as a
+ * user-defined stopping predicate is verified.
+ * This allows chains overlapping rather than chains partitioning.
+ * The first point of the initial chain is the first point of one of the resulting chains.
+ * The splitting ends when no more chain can start.
+ * \param startingPred
+ * The predicate on a point that expresses the starting condition
+ * \param stoppingPred
+ * The predicate on a point that expresses the stopping condition
+ * \param sampling
+ * The resolution used to sample the chain for the predicates evaluation. (The chain is not actually
+ * resampled, a virtual point only progresses along the curve using this resolution)
+ */
+ static int sequentialSplit(UnaryPredicate0D& startingPred, UnaryPredicate0D& stoppingPred, float sampling = 0.0f);
+
+ /*! Splits each chain of the current set of chains in a sequential way.
+ * The points of each chain are processed (with a specified sampling) sequentially and each time a user
+ * specified condition is verified, the chain is split into two chains.
+ * The resulting set of chains is a partition of the initial chain
+ * \param pred
+ * The predicate on a point that expresses the splitting condition
+ * \param sampling
+ * The resolution used to sample the chain for the predicate evaluation. (The chain is not actually
+ * resampled, a virtual point only progresses along the curve using this resolution)
+ */
+ static int sequentialSplit(UnaryPredicate0D& pred, float sampling = 0.0f);
+
+ /*! Splits the current set of chains in a recursive way.
+ * We process the points of each chain (with a specified sampling) to find the point minimizing a specified
+ * function. The chain is split in two at this point and the two new chains are processed in the same way.
+ * The recursivity level is controlled through a predicate 1D that expresses a stopping condition
+ * on the chain that is about to be processed.
+ * \param func
+ * The Unary Function evaluated at each point of the chain.
+ * The splitting point is the point minimizing this function
+ * \param pred
+ * The Unary Predicate ex pressing the recursivity stopping condition.
+ * This predicate is evaluated for each curve before it actually gets split.
+ * If pred(chain) is true, the curve won't be split anymore.
+ * \param sampling
+ * The resolution used to sample the chain for the predicates evaluation. (The chain is not actually
+ * resampled, a virtual point only progresses along the curve using this resolution)
+ */
+ static int recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate1D& pred, float sampling = 0);
+
+ /*! Splits the current set of chains in a recursive way.
+ * We process the points of each chain (with a specified sampling) to find the point minimizing a specified
+ * function. The chain is split in two at this point and the two new chains are processed in the same way.
+ * The user can specify a 0D predicate to make a first selection on the points that can potentially be split.
+ * A point that doesn't verify the 0D predicate won't be candidate in realizing the min.
+ * The recursivity level is controlled through a predicate 1D that expresses a stopping condition
+ * on the chain that is about to be processed.
+ * \param func
+ * The Unary Function evaluated at each point of the chain.
+ * The splitting point is the point minimizing this function
+ * \param pred0d
+ * The Unary Predicate 0D used to select the candidate points where the split can occur.
+ * For example, it is very likely that would rather have your chain splitting around its middle point
+ * than around one of its extremities. A 0D predicate working on the curvilinear abscissa allows
+ * to add this kind of constraints.
+ * \param pred
+ * The Unary Predicate ex pressing the recursivity stopping condition.
+ * This predicate is evaluated for each curve before it actually gets split.
+ * If pred(chain) is true, the curve won't be split anymore.
+ * \param sampling
+ * The resolution used to sample the chain for the predicates evaluation. (The chain is not actually
+ * resampled, a virtual point only progresses along the curve using this resolution)
+ */
+ static int recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate0D& pred0d, UnaryPredicate1D& pred,
+ float sampling = 0.0f);
+
+ /*! Sorts the current set of chains (or viewedges) according to the comparison predicate given as argument.
+ * \param pred
+ * The binary predicate used for the comparison
+ */
+ static int sort(BinaryPredicate1D& pred);
+
+ /*! Creates and shades the strokes from the current set of chains.
+ * A predicate can be specified to make a selection pass on the chains.
+ * \param pred
+ * The predicate that a chain must verify in order to be transform as a stroke
+ * \param shaders
+ * The list of shaders used to shade the strokes
+ */
+ static int create(UnaryPredicate1D& pred, vector<StrokeShader*> shaders);
+
+ //
+ // Data access
+ //
+ ////////////////////////////////////////////////
+
+ static ViewEdge *getViewEdgeFromIndex(unsigned i)
+ {
+ return dynamic_cast<ViewEdge*>(_current_view_edges_set[i]);
+ }
+
+ static Chain *getChainFromIndex(unsigned i)
+ {
+ return dynamic_cast<Chain*>(_current_chains_set[i]);
+ }
+
+ static Stroke *getStrokeFromIndex(unsigned i)
+ {
+ return _current_strokes_set[i];
+ }
+
+ static unsigned getViewEdgesSize()
+ {
+ return _current_view_edges_set.size();
+ }
+
+ static unsigned getChainsSize()
+ {
+ return _current_chains_set.size();
+ }
+
+ static unsigned getStrokesSize()
+ {
+ return _current_strokes_set.size();
+ }
+
+ //
+ // Not exported in Python
+ //
+ //////////////////////////////////////////////////
+
+ static StrokesContainer *getStrokesSet()
+ {
+ return &_current_strokes_set;
+ }
+
+ static void reset();
+
+private:
+ Operators() {}
+
+ static I1DContainer _current_view_edges_set;
+ static I1DContainer _current_chains_set;
+ static I1DContainer *_current_set;
+ static StrokesContainer _current_strokes_set;
+};
+
+#endif // __FREESTYLE_OPERATORS_H__
diff --git a/source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp
new file mode 100644
index 00000000000..ddb58e2b54a
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp
@@ -0,0 +1,106 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/stroke/PSStrokeRenderer.cpp
+ * \ingroup freestyle
+ * \brief Class to define the Postscript rendering of a stroke
+ * \author Stephane Grabli
+ * \date 10/26/2004
+ */
+
+#include "Canvas.h"
+#include "PSStrokeRenderer.h"
+
+PSStrokeRenderer::PSStrokeRenderer(const char *iFileName) : StrokeRenderer()
+{
+ if (!iFileName)
+ iFileName = "freestyle.ps";
+ // open the stream:
+ _ofstream.open(iFileName, ios::out);
+ if (!_ofstream.is_open()) {
+ cerr << "couldn't open the output file " << iFileName << endl;
+ }
+ _ofstream << "%!PS-Adobe-2.0 EPSF-2.0" << endl;
+ _ofstream << "%%Creator: Freestyle (http://artis.imag.fr/Software/Freestyle)" << endl;
+ _ofstream << "%%BoundingBox: " << 0 << " "<< 0 << " " << Canvas::getInstance()->width() << " " <<
+ Canvas::getInstance()->height() << endl;
+ _ofstream << "%%EndComments" << endl;
+}
+
+PSStrokeRenderer::~PSStrokeRenderer()
+{
+ Close();
+}
+
+void PSStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
+{
+ RenderStrokeRepBasic(iStrokeRep);
+}
+
+void PSStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
+{
+ vector<Strip*>& strips = iStrokeRep->getStrips();
+ Strip::vertex_container::iterator v[3];
+ StrokeVertexRep *svRep[3];
+ Vec3r color[3];
+ for (vector<Strip*>::iterator s = strips.begin(), send = strips.end(); s != send; ++s) {
+ Strip::vertex_container& vertices = (*s)->vertices();
+ v[0] = vertices.begin();
+ v[1] = v[0];
+ ++(v[1]);
+ v[2] = v[1];
+ ++(v[2]);
+
+ while (v[2] != vertices.end()) {
+ svRep[0] = *(v[0]);
+ svRep[1] = *(v[1]);
+ svRep[2] = *(v[2]);
+
+ color[0] = svRep[0]->color();
+ //color[1] = svRep[1]->color();
+ //color[2] = svRep[2]->color();
+
+ _ofstream << "newpath" << endl;
+ _ofstream << (color[0])[0] << " " << (color[0])[1] << " " << (color[0])[2] << " setrgbcolor" <<endl;
+ _ofstream << svRep[0]->point2d()[0] << " " <<svRep[0]->point2d()[1] << " moveto" << endl;
+ _ofstream << svRep[1]->point2d()[0] << " " <<svRep[1]->point2d()[1] << " lineto" << endl;
+ _ofstream << svRep[2]->point2d()[0] << " " <<svRep[2]->point2d()[1] << " lineto" << endl;
+ _ofstream << "closepath" << endl;
+ _ofstream << "fill" << endl;
+
+ ++v[0];
+ ++v[1];
+ ++v[2];
+ }
+ }
+}
+
+void PSStrokeRenderer::Close()
+{
+ if (_ofstream.is_open())
+ _ofstream.close();
+}
diff --git a/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h
new file mode 100644
index 00000000000..fad15ece6d8
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_PS_STROKE_RENDERER_H__
+#define __FREESTYLE_PS_STROKE_RENDERER_H__
+
+/** \file blender/freestyle/intern/stroke/PSStrokeRenderer.h
+ * \ingroup freestyle
+ * \brief Class to define the Postscript rendering of a stroke
+ * \author Stephane Grabli
+ * \date 10/26/2004
+ */
+
+#include <fstream>
+
+#include "StrokeRenderer.h"
+
+#include "../system/FreestyleConfig.h"
+
+/**********************************/
+/* */
+/* */
+/* PSStrokeRenderer */
+/* */
+/* */
+/**********************************/
+
+class LIB_STROKE_EXPORT PSStrokeRenderer : public StrokeRenderer
+{
+public:
+ PSStrokeRenderer(const char *iFileName = NULL);
+ virtual ~PSStrokeRenderer();
+
+ /*! Renders a stroke rep */
+ virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const;
+ virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const;
+
+ /*! Closes the output PS file */
+ void Close();
+
+protected:
+ mutable ofstream _ofstream;
+};
+
+#endif // __FREESTYLE_PS_STROKE_RENDERER_H__
diff --git a/source/blender/freestyle/intern/stroke/Predicates0D.h b/source/blender/freestyle/intern/stroke/Predicates0D.h
new file mode 100644
index 00000000000..796bbdef0f6
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Predicates0D.h
@@ -0,0 +1,186 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_PREDICATES_0D_H__
+#define __FREESTYLE_PREDICATES_0D_H__
+
+/** \file blender/freestyle/intern/stroke/Predicates0D.h
+ * \ingroup freestyle
+ * \brief Class gathering stroke creation algorithms
+ * \author Stephane Grabli
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+#include "../python/Director.h"
+
+#include "../view_map/Functions0D.h"
+
+//
+// UnaryPredicate0D (base class for predicates in 0D)
+//
+///////////////////////////////////////////////////////////
+
+/*! Base class for Unary Predicates that work on Interface0DIterator.
+ * A UnaryPredicate0D is a functor that evaluates a condition on a Interface0DIterator and returns
+ * true or false depending on whether this condition is satisfied or not.
+ * The UnaryPredicate0D is used by calling its () operator.
+ * Any inherited class must overload the () operator.
+ */
+class UnaryPredicate0D
+{
+public:
+ bool result;
+ PyObject *py_up0D;
+
+ /*! Default constructor. */
+ UnaryPredicate0D()
+ {
+ py_up0D = 0;
+ }
+
+ /*! Destructor. */
+ virtual ~UnaryPredicate0D() {}
+
+ /*! Returns the string of the name of the UnaryPredicate0D. */
+ virtual string getName() const
+ {
+ return "UnaryPredicate0D";
+ }
+
+ /*! The () operator. Must be overload by inherited classes.
+ * \param it
+ * The Interface0DIterator pointing onto the Interface0D at which we wish to evaluate the predicate.
+ * \return true if the condition is satisfied, false otherwise.
+ */
+ virtual int operator()(Interface0DIterator& it)
+ {
+ return Director_BPy_UnaryPredicate0D___call__(this, it);
+ }
+};
+
+
+//
+// BinaryPredicate0D (base class for predicates in 0D)
+//
+///////////////////////////////////////////////////////////
+
+/*! Base class for Binary Predicates working on Interface0D.
+ * A BinaryPredicate0D is typically an ordering relation between two Interface0D.
+ * It evaluates a relation between 2 Interface0D and returns true or false.
+ * It is used by calling the () operator.
+ */
+class BinaryPredicate0D
+{
+public:
+ bool result;
+ PyObject *py_bp0D;
+
+ /*! Default constructor. */
+ BinaryPredicate0D()
+ {
+ py_bp0D = 0;
+ }
+
+ /*! Destructor. */
+ virtual ~BinaryPredicate0D() {}
+
+ /*! Returns the string of the name of the binary predicate. */
+ virtual string getName() const
+ {
+ return "BinaryPredicate0D";
+ }
+
+ /*! The () operator. Must be overload by inherited classes.
+ * It evaluates a relation between 2 Interface0D.
+ * \param inter1
+ * The first Interface0D.
+ * \param inter2
+ * The second Interface0D.
+ * \return true or false.
+ */
+ virtual int operator()(Interface0D& inter1, Interface0D& inter2)
+ {
+ return Director_BPy_BinaryPredicate0D___call__(this, inter1, inter2);
+ }
+};
+
+
+//
+// Predicates definitions
+//
+///////////////////////////////////////////////////////////
+
+namespace Predicates0D {
+
+// TrueUP0D
+/*! Returns true any time */
+class TrueUP0D : public UnaryPredicate0D
+{
+public:
+ /*! Default constructor. */
+ TrueUP0D() {}
+
+ /*! Returns the string "TrueUP0D"*/
+ string getName() const
+ {
+ return "TrueUP0D";
+ }
+
+ /*! The () operator. */
+ int operator()(Interface0DIterator&)
+ {
+ result = true;
+ return 0;
+ }
+};
+
+// FalseUP0D
+/*! Returns false any time */
+class FalseUP0D : public UnaryPredicate0D
+{
+public:
+ /*! Default constructor. */
+ FalseUP0D() {}
+
+ /*! Returns the string "FalseUP0D"*/
+ string getName() const
+ {
+ return "FalseUP0D";
+ }
+
+ /*! The () operator. */
+ int operator()(Interface0DIterator&)
+ {
+ result = false;
+ return 0;
+ }
+};
+
+} // end of namespace Predicates0D
+
+#endif // __FREESTYLE_PREDICATES_0D_H__
diff --git a/source/blender/freestyle/intern/stroke/Predicates1D.h b/source/blender/freestyle/intern/stroke/Predicates1D.h
new file mode 100644
index 00000000000..cf19bf2c03c
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Predicates1D.h
@@ -0,0 +1,588 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_PREDICATES_1D_H__
+#define __FREESTYLE_PREDICATES_1D_H__
+
+/** \file blender/freestyle/intern/stroke/Predicates1D.h
+ * \ingroup freestyle
+ * \brief Class gathering stroke creation algorithms
+ * \author Stephane Grabli
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+#include <string>
+
+#include "AdvancedFunctions1D.h"
+
+#include "../python/Director.h"
+
+#include "../system/TimeStamp.h"
+
+#include "../view_map/Interface1D.h"
+#include "../view_map/Functions1D.h"
+
+//
+// UnaryPredicate1D (base class for predicates in 1D)
+//
+///////////////////////////////////////////////////////////
+
+/*! Base class for Unary Predicates that work on Interface1D.
+ * A UnaryPredicate1D is a functor that evaluates a condition on a Interface1D and returns
+ * true or false depending on whether this condition is satisfied or not.
+ * The UnaryPredicate1D is used by calling its () operator.
+ * Any inherited class must overload the () operator.
+ */
+class UnaryPredicate1D
+{
+public:
+ bool result;
+ PyObject *py_up1D;
+
+ /*! Default constructor. */
+ UnaryPredicate1D()
+ {
+ py_up1D = NULL;
+ }
+
+ /*! Destructor. */
+ virtual ~UnaryPredicate1D() {}
+
+ /*! Returns the string of the name of the UnaryPredicate1D. */
+ virtual string getName() const
+ {
+ return "UnaryPredicate1D";
+ }
+
+ /*! The () operator. Must be overload by inherited classes.
+ * \param inter
+ * The Interface1D on which we wish to evaluate the predicate.
+ * \return true if the condition is satisfied, false otherwise.
+ */
+ virtual int operator()(Interface1D& inter)
+ {
+ return Director_BPy_UnaryPredicate1D___call__(this, inter);
+ }
+};
+
+
+//
+// BinaryPredicate1D (base class for predicates in 1D)
+//
+///////////////////////////////////////////////////////////
+
+/*! Base class for Binary Predicates working on Interface1D.
+ * A BinaryPredicate1D is typically an ordering relation between two Interface1D.
+ * It evaluates a relation between 2 Interface1D and returns true or false.
+ * It is used by calling the () operator.
+ */
+class BinaryPredicate1D
+{
+public:
+ bool result;
+ PyObject *py_bp1D;
+
+ /*! Default constructor. */
+ BinaryPredicate1D()
+ {
+ py_bp1D = NULL;
+ }
+
+ /*! Destructor. */
+ virtual ~BinaryPredicate1D() {}
+
+ /*! Returns the string of the name of the binary predicate. */
+ virtual string getName() const
+ {
+ return "BinaryPredicate1D";
+ }
+
+ /*! The () operator. Must be overload by inherited classes.
+ * It evaluates a relation between 2 Interface1D.
+ * \param inter1
+ * The first Interface1D.
+ * \param inter2
+ * The second Interface1D.
+ * \return true or false.
+ */
+ virtual int operator()(Interface1D& inter1, Interface1D& inter2)
+ {
+ return Director_BPy_BinaryPredicate1D___call__(this, inter1, inter2);
+ }
+};
+
+
+//
+// Predicates definitions
+//
+///////////////////////////////////////////////////////////
+
+namespace Predicates1D {
+
+// TrueUP1D
+/*! Returns true */
+class TrueUP1D : public UnaryPredicate1D
+{
+public:
+ /*! Constructor */
+ TrueUP1D() {}
+
+ /*! Returns the string "TrueUP1D"*/
+ string getName() const
+ {
+ return "TrueUP1D";
+ }
+
+ /*! the () operator */
+ int operator()(Interface1D&)
+ {
+ result = true;
+ return 0;
+ }
+};
+
+// FalseUP1D
+/*! Returns false */
+class FalseUP1D : public UnaryPredicate1D
+{
+public:
+ /*! Constructor */
+ FalseUP1D() {}
+
+ /*! Returns the string "FalseUP1D"*/
+ string getName() const
+ {
+ return "FalseUP1D";
+ }
+
+ /*! the () operator */
+ int operator()(Interface1D&)
+ {
+ result = false;
+ return 0;
+ }
+};
+
+// QuantitativeInvisibilityUP1D
+/*! Returns true if the Quantitative Invisibility evaluated at an Interface1D, using the QuantitativeInvisibilityF1D
+ * functor, equals a certain user-defined value.
+ */
+class QuantitativeInvisibilityUP1D : public UnaryPredicate1D
+{
+public:
+ /*! Builds the Predicate.
+ * \param qi
+ * The Quantitative Invisibility you want the Interface1D to have
+ */
+ QuantitativeInvisibilityUP1D(unsigned qi = 0) : _qi(qi) {}
+
+ /*! Returns the string "QuantitativeInvisibilityUP1D" */
+ string getName() const
+ {
+ return "QuantitativeInvisibilityUP1D";
+ }
+
+ /*! the () operator */
+ int operator()(Interface1D& inter)
+ {
+ Functions1D::QuantitativeInvisibilityF1D func;
+ if (func(inter) < 0)
+ return -1;
+ result = (func.result == _qi);
+ return 0;
+ }
+
+private:
+ unsigned _qi;
+};
+
+// ContourUP1D
+/*! Returns true if the Interface1D is a contour.
+ * An Interface1D is a contour if it is borded by a different shape on each of its sides.
+ */
+class ContourUP1D : public UnaryPredicate1D
+{
+private:
+ Functions1D::CurveNatureF1D _getNature;
+
+public:
+ /*! Returns the string "ContourUP1D"*/
+ string getName() const
+ {
+ return "ContourUP1D";
+ }
+
+ /*! The () operator. */
+ int operator()(Interface1D& inter)
+ {
+ if (_getNature(inter) < 0)
+ return -1;
+ if ((_getNature.result & Nature::SILHOUETTE) || (_getNature.result & Nature::BORDER)) {
+ Interface0DIterator it = inter.verticesBegin();
+ for (; !it.isEnd(); ++it) {
+ if (Functions0D::getOccludeeF0D(it) != Functions0D::getShapeF0D(it)) {
+ result = true;
+ return 0;
+ }
+ }
+ }
+ result = false;
+ return 0;
+ }
+};
+
+// ExternalContourUP1D
+/*! Returns true if the Interface1D is an external contour.
+ * An Interface1D is an external contour if it is borded by no shape on one of its sides.
+ */
+class ExternalContourUP1D : public UnaryPredicate1D
+{
+private:
+ Functions1D::CurveNatureF1D _getNature;
+
+public:
+ /*! Returns the string "ExternalContourUP1D" */
+ string getName() const
+ {
+ return "ExternalContourUP1D";
+ }
+
+ /*! The () operator. */
+ int operator()(Interface1D& inter)
+ {
+ if (_getNature(inter) < 0)
+ return -1;
+ if ((_getNature.result & Nature::SILHOUETTE) || (_getNature.result & Nature::BORDER)) {
+ set<ViewShape*> occluded;
+ Functions1D::getOccludeeF1D(inter, occluded);
+ for (set<ViewShape*>::iterator os = occluded.begin(), osend = occluded.end(); os != osend; ++os) {
+ if ((*os) == 0) {
+ result = true;
+ return 0;
+ }
+ }
+ }
+ result = false;
+ return 0;
+ }
+};
+
+// EqualToTimeStampUP1D
+/*! Returns true if the Interface1D's time stamp is equal to a certain user-defined value. */
+class EqualToTimeStampUP1D : public UnaryPredicate1D
+{
+protected:
+ unsigned _timeStamp;
+
+public:
+ EqualToTimeStampUP1D(unsigned ts) : UnaryPredicate1D()
+ {
+ _timeStamp = ts;
+ }
+
+ /*! Returns the string "EqualToTimeStampUP1D"*/
+ string getName() const
+ {
+ return "EqualToTimeStampUP1D";
+ }
+
+ /*! The () operator. */
+ int operator()(Interface1D& inter)
+ {
+ result = (inter.getTimeStamp() == _timeStamp);
+ return 0;
+ }
+};
+
+// EqualToChainingTimeStampUP1D
+/*! Returns true if the Interface1D's time stamp is equal to a certain user-defined value. */
+class EqualToChainingTimeStampUP1D : public UnaryPredicate1D
+{
+protected:
+ unsigned _timeStamp;
+
+public:
+ EqualToChainingTimeStampUP1D(unsigned ts) : UnaryPredicate1D()
+ {
+ _timeStamp = ts;
+ }
+
+ /*! Returns the string "EqualToChainingTimeStampUP1D"*/
+ string getName() const
+ {
+ return "EqualToChainingTimeStampUP1D";
+ }
+
+ /*! The () operator. */
+ int operator()(Interface1D& inter)
+ {
+ ViewEdge *edge = dynamic_cast<ViewEdge*>(&inter);
+ if (!edge) {
+ result = false;
+ return 0;
+ }
+ result = (edge->getChainingTimeStamp() >= _timeStamp);
+ return 0;
+ }
+};
+
+// ShapeUP1D
+/*! Returns true if the shape to which the Interface1D belongs to has the same Id as the one specified by the user. */
+class ShapeUP1D: public UnaryPredicate1D
+{
+private:
+ Id _id;
+
+public:
+ /*! Builds the Predicate.
+ * \param idFirst
+ * The first Id component.
+ * \param idSecond
+ * The second Id component.
+ */
+ ShapeUP1D(unsigned idFirst, unsigned idSecond = 0) : UnaryPredicate1D()
+ {
+ _id = Id(idFirst, idSecond);
+ }
+
+ /*! Returns the string "ShapeUP1D"*/
+ string getName() const
+ {
+ return "ShapeUP1D";
+ }
+
+ /*! The () operator. */
+ int operator()(Interface1D& inter)
+ {
+ set<ViewShape*> shapes;
+ Functions1D::getShapeF1D(inter, shapes);
+ for (set<ViewShape*>::iterator s = shapes.begin(), send = shapes.end(); s != send; ++s) {
+ if ((*s)->getId() == _id) {
+ result = true;
+ return 0;
+ }
+ }
+ result = false;
+ return 0;
+ }
+};
+
+// WithinImageBoundaryUP1D
+/*! Returns true if the Interface1D is (partly) within the image boundary. */
+class WithinImageBoundaryUP1D: public UnaryPredicate1D
+{
+private:
+ real _xmin, _ymin, _xmax, _ymax;
+
+public:
+ /*! Builds the Predicate.
+ * \param xmin
+ * The X lower bound of the image boundary.
+ * \param ymin
+ * The Y lower bound of the image boundary.
+ * \param xmax
+ * The X upper bound of the image boundary.
+ * \param ymax
+ * The Y upper bound of the image boundary.
+ */
+ WithinImageBoundaryUP1D(const real xmin, const real ymin, const real xmax, const real ymax)
+ : _xmin(xmin), _ymin(ymin), _xmax(xmax), _ymax(ymax)
+ {
+ }
+
+ /*! Returns the string "WithinImageBoundaryUP1D" */
+ string getName() const
+ {
+ return "WithinImageBoundaryUP1D";
+ }
+
+ /*! The () operator. */
+ int operator()(Interface1D& inter)
+ {
+ // 1st pass: check if a point is within the image boundary.
+ Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd();
+ for (; it != itend; ++it) {
+ real x = (*it).getProjectedX();
+ real y = (*it).getProjectedY();
+ if (_xmin <= x && x <= _xmax && _ymin <= y && y <= _ymax) {
+ result = true;
+ return 0;
+ }
+ }
+ // 2nd pass: check if a line segment intersects with the image boundary.
+ it = inter.verticesBegin();
+ if (it != itend) {
+ Vec2r pmin(_xmin, _ymin);
+ Vec2r pmax(_xmax, _ymax);
+ Vec2r prev((*it).getPoint2D());
+ ++it;
+ for (; it != itend; ++it) {
+ Vec2r p((*it).getPoint2D());
+ if (GeomUtils::intersect2dSeg2dArea (pmin, pmax, prev, p)) {
+ result = true;
+ return 0;
+ }
+ prev = p;
+ }
+ }
+ result = false;
+ return 0;
+ }
+};
+
+//
+// Binary Predicates definitions
+//
+///////////////////////////////////////////////////////////
+
+// TrueBP1D
+/*! Returns true. */
+class TrueBP1D : public BinaryPredicate1D
+{
+public:
+ /*! Returns the string "TrueBP1D" */
+ string getName() const
+ {
+ return "TrueBP1D";
+ }
+
+ /*! The () operator. */
+ int operator()(Interface1D& i1, Interface1D& i2)
+ {
+ result = true;
+ return 0;
+ }
+};
+
+// FalseBP1D
+/*! Returns false. */
+class FalseBP1D : public BinaryPredicate1D
+{
+public:
+ /*! Returns the string "FalseBP1D" */
+ string getName() const
+ {
+ return "FalseBP1D";
+ }
+
+ /*! The () operator. */
+ int operator()(Interface1D& i1, Interface1D& i2)
+ {
+ result = false;
+ return 0;
+ }
+};
+
+// Length2DBP1D
+/*! Returns true if the 2D length of the Interface1D i1 is less than the 2D length of the Interface1D i2. */
+class Length2DBP1D : public BinaryPredicate1D
+{
+public:
+ /*! Returns the string "Length2DBP1D" */
+ string getName() const
+ {
+ return "Length2DBP1D";
+ }
+
+ /*! The () operator. */
+ int operator()(Interface1D& i1, Interface1D& i2)
+ {
+ result = (i1.getLength2D() > i2.getLength2D());
+ return 0;
+ }
+};
+
+// SameShapeIdBP1D
+/*! Returns true if the Interface1D i1 and i2 belong to the same shape. */
+class SameShapeIdBP1D : public BinaryPredicate1D
+{
+public:
+ /*! Returns the string "SameShapeIdBP1D" */
+ string getName() const
+ {
+ return "SameShapeIdBP1D";
+ }
+
+ /*! The () operator. */
+ int operator()(Interface1D& i1, Interface1D& i2)
+ {
+ set<ViewShape*> shapes1;
+ Functions1D::getShapeF1D(i1, shapes1);
+ set<ViewShape*> shapes2;
+ Functions1D::getShapeF1D(i2, shapes2);
+ // FIXME:// n2 algo, can do better...
+ for (set<ViewShape*>::iterator s = shapes1.begin(), send = shapes1.end(); s != send; ++s) {
+ Id current = (*s)->getId();
+ for (set<ViewShape*>::iterator s2 = shapes2.begin(), s2end = shapes2.end(); s2 != s2end; ++s2) {
+ if ((*s2)->getId() == current) {
+ result = true;
+ return 0;
+ }
+ }
+ }
+ result = false;
+ return 0;
+ }
+};
+
+// ViewMapGradientNormBP1D
+/*! Returns true if the evaluation of the Gradient norm Function is higher for Interface1D i1 than for i2. */
+class ViewMapGradientNormBP1D : public BinaryPredicate1D
+{
+private:
+ Functions1D::GetViewMapGradientNormF1D _func;
+
+public:
+ ViewMapGradientNormBP1D(int level, IntegrationType iType = MEAN, float sampling = 2.0)
+ : BinaryPredicate1D(), _func(level, iType, sampling)
+ {
+ }
+
+ /*! Returns the string "ViewMapGradientNormBP1D" */
+ string getName() const
+ {
+ return "ViewMapGradientNormBP1D";
+ }
+
+ /*! The () operator. */
+ int operator()(Interface1D& i1, Interface1D& i2)
+ {
+ if (_func(i1) < 0)
+ return -1;
+ real n1 = _func.result;
+ if (_func(i2) < 0)
+ return -1;
+ real n2 = _func.result;
+ result = (n1 > n2);
+ return 0;
+ }
+};
+
+} // end of namespace Predicates1D
+
+#endif // __FREESTYLE_PREDICATES_1D_H__
diff --git a/source/blender/freestyle/intern/stroke/QInformationMap.h b/source/blender/freestyle/intern/stroke/QInformationMap.h
new file mode 100644
index 00000000000..38a126d0f66
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/QInformationMap.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_Q_INFORMATION_MAP_H__
+#define __FREESTYLE_Q_INFORMATION_MAP_H__
+
+/** \file blender/freestyle/intern/stroke/QInformationMap.h
+ * \ingroup freestyle
+ * \brief Class defining an information map using a QImage
+ * \author Stephane Grabli
+ * \date 04/01/2003
+ */
+
+#include <qimage.h>
+
+#include "InformationMap.h"
+
+class QInformationMap : public InformationMap
+{
+private:
+ QImage _map; // the image or a piece of image
+
+public:
+ QInformationMap();
+ QInformationMap(const QImage&);
+ QInformationMap(const QInformationMap&);
+ QInformationMap& operator=(const QInformationMap&);
+
+ //float getSmoothedPixel(int x, int y, float sigma = 0.2f);1
+ virtual float getMean(int x, int y);
+ virtual void retrieveMeanAndVariance(int x, int y, float &oMean, float &oVariance);
+
+ inline const QImage& map() const
+ {
+ return _map;
+ }
+
+ inline void setMap(const QImage& iMap, float iw, float ih)
+ {
+ _map = iMap.copy();
+ _w = iw;
+ _h = ih;
+ }
+
+protected:
+ virtual float computeGaussian(int x, int y);
+};
+
+#endif // __FREESTYLE_Q_INFORMATION_MAP_H__
diff --git a/source/blender/freestyle/intern/stroke/Stroke.cpp b/source/blender/freestyle/intern/stroke/Stroke.cpp
new file mode 100644
index 00000000000..b043afba036
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Stroke.cpp
@@ -0,0 +1,954 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/stroke/Stroke.cpp
+ * \ingroup freestyle
+ * \brief Classes to define a stroke
+ * \author Stephane Grabli
+ * \date 09/09/2002
+ */
+
+#include "Stroke.h"
+#include "StrokeAdvancedIterators.h"
+#include "StrokeIterators.h"
+#include "StrokeRenderer.h"
+
+#include "BKE_global.h"
+
+/**********************************/
+/* */
+/* */
+/* StrokeAttribute */
+/* */
+/* */
+/**********************************/
+
+StrokeAttribute::StrokeAttribute()
+{
+ int i;
+ _alpha = 1.0f;
+ _thickness[0] = 1.0f;
+ _thickness[1] = 1.0f;
+ for (i = 0; i < 3; ++i)
+ _color[i] = 0.2f;
+ _color[0] = 0.8f;
+ _userAttributesReal = NULL;
+ _userAttributesVec2f = NULL;
+ _userAttributesVec3f = NULL;
+ _visible = true;
+}
+
+StrokeAttribute::StrokeAttribute(const StrokeAttribute& iBrother)
+{
+ _alpha = iBrother._alpha;
+ _thickness[0] = iBrother._thickness[0];
+ _thickness[1] = iBrother._thickness[1];
+ for (int i = 0; i < 3; ++i)
+ _color[i] = iBrother._color[i];
+ _visible = iBrother._visible;
+ if (iBrother._userAttributesReal)
+ _userAttributesReal = new realMap(*iBrother._userAttributesReal);
+ else
+ _userAttributesReal = NULL;
+ if (iBrother._userAttributesVec2f)
+ _userAttributesVec2f = new Vec2fMap(*iBrother._userAttributesVec2f);
+ else
+ _userAttributesVec2f = NULL;
+ if (iBrother._userAttributesVec3f)
+ _userAttributesVec3f = new Vec3fMap(*iBrother._userAttributesVec3f);
+ else
+ _userAttributesVec3f = NULL;
+}
+
+StrokeAttribute::StrokeAttribute(float iRColor, float iGColor, float iBColor, float iAlpha,
+ float iRThickness, float iLThickness)
+{
+ _color[0] = iRColor;
+ _color[1] = iGColor;
+ _color[2] = iBColor;
+
+ _alpha = iAlpha;
+
+ _thickness[0] = iRThickness;
+ _thickness[1] = iLThickness;
+
+ _visible = true;
+
+ _userAttributesReal = NULL;
+ _userAttributesVec2f = NULL;
+ _userAttributesVec3f = NULL;
+}
+
+StrokeAttribute::StrokeAttribute(const StrokeAttribute& a1, const StrokeAttribute& a2, float t)
+{
+ _alpha = (1 - t) * a1._alpha + t * a2._alpha;
+ _thickness[0] = (1 - t) * a1._thickness[0] + t * a2._thickness[0];
+ _thickness[1] = (1 - t) * a1._thickness[1] + t * a2._thickness[1];
+ for (int i = 0; i < 3; ++i)
+ _color[i] = (1 - t) * a1._color[i] + t * a2._color[i];
+
+ _visible = true;
+
+ // FIXME: to be checked (and enhanced)
+ if ((a1._userAttributesReal) && (a2._userAttributesReal)) {
+ if (a1._userAttributesReal->size() == a2._userAttributesReal->size()) {
+ _userAttributesReal = new realMap;
+ realMap::iterator it1 = a1._userAttributesReal->begin(), it1end = a1._userAttributesReal->end();
+ realMap::iterator it2 = a2._userAttributesReal->begin(), it2end = a2._userAttributesReal->end();
+ for (; it1 != it1end; ++it1) {
+ (*_userAttributesReal)[(*it1).first] = ((1 - t) * (*it1).second + t * (*it2).second);
+ }
+ }
+ }
+ else {
+ _userAttributesReal = NULL;
+ }
+ if ((a1._userAttributesVec2f) && (a2._userAttributesVec2f)) {
+ if (a1._userAttributesVec2f->size() == a2._userAttributesVec2f->size()) {
+ _userAttributesVec2f = new Vec2fMap;
+ Vec2fMap::iterator it1 = a1._userAttributesVec2f->begin(), it1end = a1._userAttributesVec2f->end();
+ Vec2fMap::iterator it2 = a2._userAttributesVec2f->begin(), it2end = a2._userAttributesVec2f->end();
+ for (; it1 != it1end; ++it1) {
+ (*_userAttributesVec2f)[(*it1).first] = ((1 - t) * (*it1).second + t * (*it2).second);
+ }
+ }
+ }
+ else {
+ _userAttributesVec2f = NULL;
+ }
+ if ((a1._userAttributesVec3f) && (a2._userAttributesVec3f)) {
+ if (a1._userAttributesVec3f->size() == a2._userAttributesVec3f->size()) {
+ _userAttributesVec3f = new Vec3fMap;
+ Vec3fMap::iterator it1 = a1._userAttributesVec3f->begin(), it1end = a1._userAttributesVec3f->end();
+ Vec3fMap::iterator it2 = a2._userAttributesVec3f->begin(), it2end = a2._userAttributesVec3f->end();
+ for (; it1 != it1end; ++it1) {
+ (*_userAttributesVec3f)[(*it1).first] = ((1 - t) * (*it1).second + t * (*it2).second);
+ }
+ }
+ }
+ else {
+ _userAttributesVec3f = NULL;
+ }
+}
+
+StrokeAttribute::~StrokeAttribute()
+{
+ if (_userAttributesReal) {
+ _userAttributesReal->clear();
+ delete _userAttributesReal;
+ }
+ if (_userAttributesVec2f) {
+ _userAttributesVec2f->clear();
+ delete _userAttributesVec2f;
+ }
+ if (_userAttributesVec3f) {
+ _userAttributesVec3f->clear();
+ delete _userAttributesVec3f;
+ }
+}
+
+StrokeAttribute& StrokeAttribute::operator=(const StrokeAttribute& iBrother)
+{
+ int i;
+ _alpha = iBrother._alpha;
+ _thickness[0] = iBrother._thickness[0];
+ _thickness[1] = iBrother._thickness[1];
+ for (i = 0; i < 3; ++i)
+ _color[i] = iBrother._color[i];
+ _visible = iBrother._visible;
+ if (iBrother._userAttributesReal) {
+ if (!_userAttributesReal)
+ _userAttributesReal = new realMap;
+ _userAttributesReal = new realMap(*(iBrother._userAttributesReal));
+ }
+ else {
+ _userAttributesReal = NULL;
+ }
+ if (iBrother._userAttributesVec2f) {
+ if (!_userAttributesVec2f)
+ _userAttributesVec2f = new Vec2fMap;
+ _userAttributesVec2f = new Vec2fMap(*(iBrother._userAttributesVec2f));
+ }
+ else {
+ _userAttributesVec2f = NULL;
+ }
+ if (iBrother._userAttributesVec3f) {
+ if (!_userAttributesVec3f)
+ _userAttributesVec3f = new Vec3fMap;
+ _userAttributesVec3f = new Vec3fMap(*(iBrother._userAttributesVec3f));
+ }
+ else {
+ _userAttributesVec3f = NULL;
+ }
+ return *this;
+}
+
+float StrokeAttribute::getAttributeReal(const char *iName) const
+{
+ if (!_userAttributesReal) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "StrokeAttribute warning: no real attribute was defined" << endl;
+ }
+ return 0.0f;
+ }
+ realMap::iterator a = _userAttributesReal->find(iName);
+ if (a == _userAttributesReal->end()) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "StrokeAttribute warning: no real attribute was added with the name " << iName << endl;
+ }
+ return 0.0f;
+ }
+ return (*a).second;
+}
+
+Vec2f StrokeAttribute::getAttributeVec2f(const char *iName) const
+{
+ if (!_userAttributesVec2f) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "StrokeAttribute warning: no Vec2f attribute was defined" << endl;
+ }
+ return 0;
+ }
+ Vec2fMap::iterator a = _userAttributesVec2f->find(iName);
+ if (a == _userAttributesVec2f->end()) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "StrokeAttribute warning: no Vec2f attribute was added with the name " << iName << endl;
+ }
+ return 0;
+ }
+ return (*a).second;
+}
+
+Vec3f StrokeAttribute::getAttributeVec3f(const char *iName) const
+{
+ if (!_userAttributesVec3f) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "StrokeAttribute warning: no Vec3f attribute was defined" << endl;
+ }
+ return 0;
+ }
+ Vec3fMap::iterator a = _userAttributesVec3f->find(iName);
+ if (a == _userAttributesVec3f->end()) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "StrokeAttribute warning: no Vec3f attribute was added with the name " << iName << endl;
+ }
+ return 0;
+ }
+ return (*a).second;
+}
+
+bool StrokeAttribute::isAttributeAvailableReal(const char *iName) const
+{
+ if (!_userAttributesReal) {
+ return false;
+ }
+ realMap::iterator a = _userAttributesReal->find(iName);
+ if (a == _userAttributesReal->end()) {
+ return false;
+ }
+ return true;
+}
+
+bool StrokeAttribute::isAttributeAvailableVec2f(const char *iName) const
+{
+ if (!_userAttributesVec2f) {
+ return false;
+ }
+ Vec2fMap::iterator a = _userAttributesVec2f->find(iName);
+ if (a == _userAttributesVec2f->end()) {
+ return false;
+ }
+ return true;
+}
+
+bool StrokeAttribute::isAttributeAvailableVec3f(const char *iName) const
+{
+ if (!_userAttributesVec3f) {
+ return false;
+ }
+ Vec3fMap::iterator a = _userAttributesVec3f->find(iName);
+ if (a == _userAttributesVec3f->end()) {
+ return false;
+ }
+ return true;
+}
+
+void StrokeAttribute::setAttributeReal(const char *iName, float att)
+{
+ if (!_userAttributesReal)
+ _userAttributesReal = new realMap;
+ (*_userAttributesReal)[iName] = att;
+}
+
+void StrokeAttribute::setAttributeVec2f(const char *iName, const Vec2f& att)
+{
+ if (!_userAttributesVec2f)
+ _userAttributesVec2f = new Vec2fMap;
+ (*_userAttributesVec2f)[iName] = att;
+}
+
+void StrokeAttribute::setAttributeVec3f(const char *iName, const Vec3f& att)
+{
+ if (!_userAttributesVec3f)
+ _userAttributesVec3f = new Vec3fMap;
+ (*_userAttributesVec3f)[iName] = att;
+}
+
+
+/**********************************/
+/* */
+/* */
+/* StrokeVertex */
+/* */
+/* */
+/**********************************/
+
+StrokeVertex::StrokeVertex() : CurvePoint()
+{
+ _CurvilignAbscissa = 0.0f;
+ _StrokeLength = 0.0f;
+}
+
+StrokeVertex::StrokeVertex(const StrokeVertex& iBrother) : CurvePoint(iBrother)
+{
+ _Attribute = iBrother._Attribute;
+ _CurvilignAbscissa = 0.0f;
+ _StrokeLength = 0.0f;
+}
+
+StrokeVertex::StrokeVertex(SVertex *iSVertex) : CurvePoint(iSVertex, 0, 0.0f)
+{
+ _CurvilignAbscissa = 0.0f;
+ _StrokeLength = 0.0f;
+}
+
+StrokeVertex::StrokeVertex(CurvePoint *iPoint) : CurvePoint(*iPoint)
+{
+ _CurvilignAbscissa = 0.0f;
+ _StrokeLength = 0.0f;
+}
+
+StrokeVertex::StrokeVertex(StrokeVertex *iA, StrokeVertex *iB, float t3) : CurvePoint(iA, iB, t3)
+{
+ // interpolate attributes:
+ _Attribute = StrokeAttribute(iA->attribute(), iB->attribute(), t3);
+ _CurvilignAbscissa = (1 - t3) * iA->curvilinearAbscissa() + t3 * iB->curvilinearAbscissa();
+ _StrokeLength = iA->strokeLength();
+}
+
+StrokeVertex::StrokeVertex(SVertex *iSVertex, const StrokeAttribute& iAttribute) : CurvePoint(iSVertex, 0, 0.0f)
+{
+ _Attribute = iAttribute;
+ _CurvilignAbscissa = 0.0f;
+ _StrokeLength = 0.0f;
+}
+
+StrokeVertex::~StrokeVertex() {}
+
+StrokeVertex& StrokeVertex::operator=(const StrokeVertex& iBrother)
+{
+ ((CurvePoint *)this)->operator=(iBrother);
+ _Attribute = iBrother._Attribute;
+
+ _CurvilignAbscissa = 0.0f;
+
+ _StrokeLength = 0.0f;
+ return *this;
+}
+
+
+
+/**********************************/
+/* */
+/* */
+/* Stroke */
+/* */
+/* */
+/**********************************/
+
+Stroke::Stroke()
+{
+ _Length = 0;
+ _id = 0;
+ _sampling = FLT_MAX;
+ //_mediumType = DEFAULT_STROKE;
+ _mediumType = OPAQUE_MEDIUM;
+ _textureId = 0;
+ _tips = false;
+ _rep = NULL;
+}
+
+Stroke::Stroke(const Stroke& iBrother)
+{
+ for (vertex_container::const_iterator v = iBrother._Vertices.begin(), vend = iBrother._Vertices.end();
+ v != vend;
+ v++)
+ {
+ _Vertices.push_back(*v);
+ }
+ _Length = 0;
+ _id = iBrother._id;
+ _ViewEdges = iBrother._ViewEdges;
+ _sampling = iBrother._sampling;
+ _mediumType = iBrother._mediumType;
+ _textureId = iBrother._textureId;
+ _tips = iBrother._tips;
+ if (iBrother._rep)
+ _rep = new StrokeRep(*(iBrother._rep));
+ else
+ _rep = NULL;
+}
+
+Stroke::~Stroke()
+{
+ if (!_Vertices.empty()) {
+ for (vertex_container::iterator v = _Vertices.begin(), vend = _Vertices.end(); v != vend; v++) {
+ delete (*v);
+ }
+ _Vertices.clear();
+ }
+
+ _ViewEdges.clear();
+ if (_rep) {
+ delete _rep;
+ _rep = NULL;
+ }
+}
+
+Stroke& Stroke::operator=(const Stroke& iBrother)
+{
+ if (!_Vertices.empty())
+ _Vertices.clear();
+
+ for (vertex_container::const_iterator v = iBrother._Vertices.begin(), vend = iBrother._Vertices.end();
+ v != vend;
+ v++)
+ {
+ _Vertices.push_back(*v);
+ }
+ _Length = iBrother._Length;
+ _id = iBrother._id;
+ _ViewEdges = iBrother._ViewEdges;
+ _sampling = iBrother._sampling;
+ if (_rep)
+ delete _rep;
+ if (iBrother._rep)
+ _rep = new StrokeRep(*(iBrother._rep));
+ return *this;
+}
+
+void Stroke::setLength(float iLength)
+{
+ _Length = iLength;
+ for (vertex_container::iterator v = _Vertices.begin(), vend = _Vertices.end(); v != vend; ++v) {
+ (*v)->setStrokeLength(iLength);
+ }
+}
+
+float Stroke::ComputeSampling(int iNVertices)
+{
+ if (iNVertices <= (int)_Vertices.size()) //soc
+ return _sampling;
+
+ float sampling = _Length / (float)(iNVertices - _Vertices.size() + 1);
+ return sampling;
+}
+
+class StrokeSegment
+{
+public:
+ StrokeInternal::StrokeVertexIterator _begin;
+ StrokeInternal::StrokeVertexIterator _end;
+ float _length;
+ int _n;
+ float _sampling;
+ bool _resampled;
+
+ StrokeSegment(StrokeInternal::StrokeVertexIterator ibegin, StrokeInternal::StrokeVertexIterator iend,
+ float ilength, int in, float isampling)
+ {
+ _begin = ibegin;
+ _end = iend;
+ _length = ilength;
+ _n = in;
+ _sampling = isampling;
+ _resampled = false;
+ }
+};
+
+void Stroke::Resample(int iNPoints)
+{
+ int vertsize = strokeVerticesSize();
+ if (iNPoints <= vertsize)
+ return;
+
+ StrokeInternal::StrokeVertexIterator it = strokeVerticesBegin();
+ StrokeInternal::StrokeVertexIterator next = it;
+ ++next;
+ StrokeInternal::StrokeVertexIterator itend = strokeVerticesEnd();
+
+ vertex_container newVertices;
+ real t = 0.0f;
+ StrokeVertex *newVertex = NULL;
+ vector<StrokeSegment> strokeSegments;
+ int N = 0;
+ float meanlength = 0;
+ int nsegments = 0;
+ while ((it != itend) && (next != itend)) {
+ Vec2r a((it)->getPoint());
+ Vec2r b((next)->getPoint());
+ Vec2r vec_tmp(b - a);
+ real norm_var = vec_tmp.norm();
+ int numberOfPointsToAdd = (int)floor((iNPoints - strokeVerticesSize()) * norm_var / _Length);
+ float csampling = norm_var / (float)(numberOfPointsToAdd + 1);
+ strokeSegments.push_back(StrokeSegment(it, next, norm_var, numberOfPointsToAdd, csampling));
+ N += numberOfPointsToAdd;
+ meanlength += norm_var;
+ ++nsegments;
+ ++it;
+ ++next;
+ }
+ meanlength /= (float)nsegments;
+
+ // if we don't have enough points let's resample finer some segments
+ int NPointsToAdd = iNPoints - vertsize;
+ bool checkEveryone = false;
+ while (N < NPointsToAdd) {
+ for (vector<StrokeSegment>::iterator s = strokeSegments.begin(), send = strokeSegments.end(); s != send; ++s) {
+ if (s->_sampling == 0.0f)
+ continue;
+
+ if (s->_resampled == false) {
+ if ((!checkEveryone) && (s->_length < meanlength))
+ continue;
+ //resample
+ s->_n = s->_n + 1;
+ s->_sampling = s->_length / (float)(s->_n + 1);
+ s->_resampled = true;
+ N++;
+ if (N == NPointsToAdd)
+ break;
+ }
+ }
+ checkEveryone = true;
+ }
+ //actually resample:
+ for (vector<StrokeSegment>::iterator s = strokeSegments.begin(), send = strokeSegments.end(); s != send; ++s) {
+ newVertices.push_back(&(*(s->_begin)));
+ if (s->_sampling < _sampling)
+ _sampling = s->_sampling;
+
+ t = s->_sampling / s->_length;
+ for (int i = 0; i < s->_n; ++i) {
+ newVertex = new StrokeVertex(&(*(s->_begin)), &(*(s->_end)), t);
+ newVertices.push_back(newVertex);
+ t += s->_sampling / s->_length;
+ }
+ it = s->_begin;
+ next = s->_end;
+ }
+
+ // add last:
+ ++it;
+ ++next;
+ if ((it != itend) && (next == itend)/* && (t == 0.0f)*/)
+ newVertices.push_back(&(*it));
+
+ int newsize = newVertices.size();
+ if (newsize != iNPoints)
+ cerr << "Warning: incorrect points number" << endl;
+
+ _Vertices.clear();
+ _Vertices = newVertices;
+ newVertices.clear();
+
+ if (_rep) {
+ delete _rep;
+ _rep = new StrokeRep(this);
+ }
+}
+
+void Stroke::Resample(float iSampling)
+{
+ //cerr << "old size :" << strokeVerticesSize() << endl;
+ if (iSampling == 0)
+ return;
+ if (iSampling >= _sampling)
+ return;
+
+ _sampling = iSampling;
+ // Resample...
+ //real curvilinearLength = 0.0f;
+ vertex_container newVertices;
+ real t = 0.0f;
+ const real limit = 0.99;
+ StrokeVertex *newVertex = NULL;
+ StrokeInternal::StrokeVertexIterator it = strokeVerticesBegin();
+ StrokeInternal::StrokeVertexIterator next = it;
+ ++next;
+ StrokeInternal::StrokeVertexIterator itend = strokeVerticesEnd();
+ while ((it != itend) && (next != itend)) {
+ newVertices.push_back(&(*it));
+ Vec2r a((it)->getPoint());
+ Vec2r b((next)->getPoint());
+ Vec2r vec_tmp(b - a);
+ real norm_var = vec_tmp.norm();
+ if (norm_var <= _sampling) {
+ //curvilinearLength += norm_var;
+ ++it;
+ ++next;
+ continue;
+ }
+
+ //curvilinearLength += _sampling;
+ t = _sampling / norm_var;
+ while (t < limit) {
+ newVertex = new StrokeVertex(&(*it), &(*next), t);
+ //newVertex->setCurvilinearAbscissa(curvilinearLength);
+ newVertices.push_back(newVertex);
+ t = t + _sampling / norm_var;
+ }
+ ++it;
+ ++next;
+ }
+ // add last:
+ if ((it != itend) && (next == itend)/* && (t == 0.f)*/)
+ newVertices.push_back(&(*it));
+
+ _Vertices.clear();
+ _Vertices = newVertices;
+ newVertices.clear();
+
+ if (_rep) {
+ delete _rep;
+ _rep = new StrokeRep(this);
+ }
+}
+
+void Stroke::RemoveVertex(StrokeVertex *iVertex)
+{
+ vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end();
+ for (; it != itend; ++it) {
+ if ((*it) == iVertex) {
+ delete iVertex;
+ it = _Vertices.erase(it); // it is now the element just after the erased element
+ break;
+ }
+ }
+ UpdateLength();
+}
+
+void Stroke::InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next)
+{
+ vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end();
+
+ vertex_container::iterator itnext = next.getIt();
+ _Vertices.insert(itnext, iVertex);
+ UpdateLength();
+}
+
+void Stroke::UpdateLength()
+{
+ // recompute curvilinear abscissa and stroke length
+ float curvabsc = 0.0f;
+ vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end();
+ vertex_container::iterator previous = it;
+ for (; it != itend; ++it) {
+ curvabsc += ((*it)->getPoint() - (*previous)->getPoint()).norm();
+ (*it)->setCurvilinearAbscissa(curvabsc);
+ previous = it;
+ }
+ _Length = curvabsc;
+ for (it = _Vertices.begin(); it != itend; ++it) {
+ (*it)->setStrokeLength(_Length);
+ }
+}
+
+//! embedding vertex iterator
+Stroke::const_vertex_iterator Stroke::vertices_begin() const
+{
+ return const_vertex_iterator(_Vertices.begin(), _Vertices.begin(), _Vertices.end());
+}
+
+Stroke::const_vertex_iterator Stroke::vertices_end() const
+{
+ return const_vertex_iterator(_Vertices.end(), _Vertices.begin(), _Vertices.end());
+}
+
+Stroke::vertex_iterator Stroke::vertices_end()
+{
+ return vertex_iterator(_Vertices.end(), _Vertices.begin(), _Vertices.end());
+}
+
+StrokeInternal::StrokeVertexIterator Stroke::strokeVerticesBegin(float t)
+{
+ if ((t != 0) && (t < _sampling))
+ Resample(t);
+ return StrokeInternal::StrokeVertexIterator(this->_Vertices.begin(), this->_Vertices.begin(),
+ this->_Vertices.end());
+}
+
+StrokeInternal::StrokeVertexIterator Stroke::strokeVerticesEnd()
+{
+ return StrokeInternal::StrokeVertexIterator(this->_Vertices.end(), this->_Vertices.begin(), this->_Vertices.end());
+}
+
+Interface0DIterator Stroke::verticesBegin()
+{
+Interface0DIterator ret(new StrokeInternal::StrokeVertexIterator(this->_Vertices.begin(), this->_Vertices.begin(),
+ this->_Vertices.end()));
+return ret;
+}
+
+Interface0DIterator Stroke::verticesEnd()
+{
+ Interface0DIterator ret(new StrokeInternal::StrokeVertexIterator(this->_Vertices.end(), this->_Vertices.begin(),
+ this->_Vertices.end()));
+ return ret;
+}
+
+Interface0DIterator Stroke::pointsBegin(float t)
+{
+ return verticesBegin(); // FIXME
+}
+
+Interface0DIterator Stroke::pointsEnd(float t)
+{
+ return verticesEnd();
+}
+
+void Stroke::ScaleThickness(float iFactor)
+{
+ for (vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end(); it != itend; ++it) {
+ StrokeAttribute& attr = (*it)->attribute();
+ attr.setThickness(iFactor * attr.getThicknessR(), iFactor * attr.getThicknessL());
+ }
+}
+
+void Stroke::Render(const StrokeRenderer *iRenderer)
+{
+ if (!_rep)
+ _rep = new StrokeRep(this);
+ iRenderer->RenderStrokeRep(_rep);
+}
+
+void Stroke::RenderBasic(const StrokeRenderer *iRenderer)
+{
+ if (!_rep)
+ _rep = new StrokeRep(this);
+ iRenderer->RenderStrokeRepBasic(_rep);
+}
+
+Stroke::vertex_iterator Stroke::vertices_begin(float sampling)
+{
+ // Resample if necessary
+ if ((sampling != 0) && (sampling < _sampling))
+ Resample(sampling);
+ return vertex_iterator(_Vertices.begin(), _Vertices.begin(), _Vertices.end());
+ //return _Vertices.begin();
+}
+
+#if 0
+Stroke::vertex_iterator Stroke::vertices_last()
+{
+ vertex_iterator res = vertices_begin();
+ vertex_iterator next = res;
+ ++next;
+ while (!next.end()) {
+ ++next;
+ ++res;
+ }
+ return res;
+}
+
+Stroke::const_vertex_iterator Stroke::vertices_last() const
+{
+ const_vertex_iterator res = vertices_begin();
+ const_vertex_iterator next = res;
+ ++next;
+ while (!next.end()) {
+ ++next;
+ ++res;
+ }
+ return res;
+}
+
+Stroke::vertex_container::reverse_iterator Stroke::vertices_last(float sampling)
+{
+ // Resample if necessary
+ if (sampling < _sampling)
+ Resample(sampling);
+ return _Vertices.rbegin();
+}
+
+
+inline Vec3r shaded_color(int iCombination = 0) const;
+
+inline Vec<3, real> Stroke::orientation2d(const_vertex_iterator it) const
+{
+ return iterator_edge_orientation2d_function<Stroke, const_vertex_iterator>(this, it);
+}
+
+Vec3r Stroke::orientation2d(int iCombination) const
+{
+ return edge_orientation2d_function<Stroke>(*this, iCombination);
+}
+
+inline Vec3r Stroke::orientation3d(const_vertex_iterator it) const
+{
+ return iterator_edge_orientation3d_function<Stroke, const_vertex_iterator>(*this, it);
+}
+
+Vec3r Stroke::orientation3d(int iCombination) const
+{
+ return edge_orientation3d_function<Stroke>(*this, iCombination);
+}
+
+Material Stroke::material() const
+{
+ const_vertex_iterator v = vertices_begin(), vend = strokeVerticesEnd();
+ Material mat = (*v)->material();
+ for (; v != vend; ++v) {
+ if (mat != (*v)->material())
+ Exception::raiseException();
+ }
+ return mat;
+}
+
+int Stroke::qi() const
+{
+ const_vertex_iterator v = vertices_begin(), vend = vertices_end();
+ int qi_= (*v)->qi();
+ for (; v != vend; ++v) {
+ if ((*v)->qi() != qi_)
+ Exception::raiseException();
+ }
+ return qi_;
+}
+
+inline occluder_container::const_iterator occluders_begin() const
+{
+ return _FEdgeA->occluders().begin();
+}
+
+inline occluder_container::const_iterator occluders_end() const
+{
+ return _FEdgeA->occluders().end();
+}
+
+int Stroke::occluders_size() const
+{
+ return qi();
+}
+
+bool Stroke::occluders_empty() const
+{
+ const_vertex_iterator v = vertices_begin(), vend = vertices_end();
+ bool empty = (*v)->occluders_empty();
+ for (; v != vend; ++v) {
+ if ((*v)->occluders_empty() != empty)
+ Exception::raiseException();
+ }
+ return empty;
+}
+
+#if 0
+inline const polygon3d& occludee() const
+{
+ return *(_FEdgeA->aFace());
+}
+#endif
+
+const SShape *Stroke::occluded_shape() const
+{
+ const_vertex_iterator v = vertices_begin(), vend = vertices_end();
+ const SShape *sshape = (*v)->occluded_shape();
+ for (; v != vend; ++v) {
+ if ((*v)->occluded_shape() != sshape)
+ Exception::raiseException();
+ }
+ return sshape;
+}
+
+const bool Stroke::occludee_empty() const
+{
+ const_vertex_iterator v = vertices_begin(), vend = vertices_end();
+ bool empty = (*v)->occludee_empty();
+ for (; v != vend; ++v) {
+ if ((*v)->occludee_empty() != empty)
+ Exception::raiseException();
+ }
+ return empty;
+}
+
+const SShape *Stroke::shape() const
+{
+ const_vertex_iterator v = vertices_begin(), vend = vertices_end();
+ const SShape *sshape = (*v)->shape();
+ for (; v != vend; ++v) {
+ if ((*v)->shape() != sshape)
+ Exception::raiseException();
+ }
+ return sshape;
+}
+
+real Stroke::z_discontinuity(int iCombination) const
+{
+ return z_discontinuity_edge_function<Stroke>(*this, iCombination);
+}
+
+Vec3r Stroke::curvature2d_as_vector(int iCombination) const
+{
+ return curvature2d_as_vector_edge_function<Stroke>(*this, iCombination);
+}
+
+real Stroke::curvature2d_as_angle(int iCombination) const
+{
+ return curvature2d_as_angle_edge_function<Stroke>(*this, iCombination);
+}
+
+float Stroke::shape_importance(int iCombination) const
+{
+ return shape_importance_edge_function<Stroke>(*this, iCombination);
+}
+
+
+float Stroke::local_average_depth(int iCombination ) const
+{
+ return local_average_depth_edge_function<Stroke >(*this, iCombination);
+}
+
+float Stroke::local_depth_variance(int iCombination) const
+{
+ return local_depth_variance_edge_function<Stroke>(*this, iCombination);
+}
+
+real Stroke::local_average_density(float sigma , int iCombination ) const
+{
+ return density_edge_function<Stroke>(*this, iCombination);
+}
+#endif
diff --git a/source/blender/freestyle/intern/stroke/Stroke.h b/source/blender/freestyle/intern/stroke/Stroke.h
new file mode 100644
index 00000000000..a2ff7e4dc07
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Stroke.h
@@ -0,0 +1,822 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_STROKE_H__
+#define __FREESTYLE_STROKE_H__
+
+/** \file blender/freestyle/intern/stroke/Stroke.h
+ * \ingroup freestyle
+ * \brief Classes to define a stroke
+ * \author Stephane Grabli
+ * \date 09/09/2002
+ */
+
+#include <map>
+#include <vector>
+
+#include "Curve.h"
+
+#include "../view_map/Interface1D.h"
+#include "../view_map/Silhouette.h"
+
+#include "../system/FreestyleConfig.h"
+#include "../system/StringUtils.h"
+
+
+//
+// StrokeAttribute
+//
+////////////////////////////////////////////////////////
+
+/*! Class to define an attribute associated to a Stroke Vertex.
+ * This attribute stores the color, alpha and thickness values for a Stroke Vertex.
+ */
+class LIB_STROKE_EXPORT StrokeAttribute
+{
+public:
+ /*! default constructor */
+ StrokeAttribute();
+
+ /*! Copy constructor */
+ StrokeAttribute(const StrokeAttribute& iBrother);
+
+ /*! Builds a stroke vertex attribute from a set of parameters.
+ * \param iRColor
+ * The Red Component value.
+ * \param iGColor
+ * The Green Component value.
+ * \param iBColor
+ * The Blue Component value.
+ * \param iAlpha
+ * The transparency value
+ * \param iRThickness
+ * The thickness of the stroke on the right
+ * \param iLThickness
+ * The Thickness of the stroke on the left
+ */
+ StrokeAttribute(float iRColor, float iGColor, float iBColor, float iAlpha, float iRThickness, float iLThickness);
+
+ /*! Interpolation constructor.
+ * Builds a StrokeAttribute from two StrokeAttributes and an interpolation parameter.
+ * \param a1
+ * The first Attribute.
+ * \param a2
+ * The second parameter.
+ * \param t
+ * The interpolation parameter.
+ */
+ StrokeAttribute(const StrokeAttribute& a1, const StrokeAttribute& a2, float t);
+
+ /*! destructor */
+ virtual ~StrokeAttribute();
+
+ /* operators */
+ /*! operator = */
+ StrokeAttribute& operator=(const StrokeAttribute& iBrother);
+
+ /* accessors */
+ /*! Returns the attribute's color.
+ * \return The array of 3 floats containing the R,G,B values of the attribute's color.
+ */
+ inline const float *getColor() const
+ {
+ return _color;
+ }
+
+ /*! Returns the R color component. */
+ inline const float getColorR() const
+ {
+ return _color[0];
+ }
+
+ /*! Returns the G color component. */
+ inline const float getColorG() const
+ {
+ return _color[1];
+ }
+
+ /*! Returns the B color component. */
+ inline const float getColorB() const
+ {
+ return _color[2];
+ }
+
+ /*! Returns the RGB color components. */
+ inline Vec3f getColorRGB() const
+ {
+ return Vec3f(_color[0], _color[1], _color[2]);
+ }
+
+ /*! Returns the alpha color component. */
+ inline float getAlpha() const
+ {
+ return _alpha;
+ }
+
+ /*! Returns the attribute's thickness.
+ * \return an array of 2 floats. the first value is the thickness on the right of the vertex when following
+ * the stroke, the second one is the thickness on the left.
+ */
+ inline const float *getThickness() const
+ {
+ return _thickness;
+ }
+
+ /*! Returns the thickness on the right of the vertex when following the stroke. */
+ inline const float getThicknessR() const
+ {
+ return _thickness[0];
+ }
+
+ /*! Returns the thickness on the left of the vertex when following the stroke. */
+ inline const float getThicknessL() const
+ {
+ return _thickness[1];
+ }
+
+ /*! Returns the thickness on the right and on the left of the vertex when following the stroke. */
+ inline Vec2f getThicknessRL() const
+ {
+ return Vec2f(_thickness[0], _thickness[1]);
+ }
+
+ /*! Returns true if the strokevertex is visible, false otherwise */
+ inline bool isVisible() const
+ {
+ return _visible;
+ }
+
+ /*! Returns an attribute of type real
+ * \param iName
+ * The name of the attribute
+ */
+ float getAttributeReal(const char *iName) const;
+
+ /*! Returns an attribute of type Vec2f
+ * \param iName
+ * The name of the attribute
+ */
+ Vec2f getAttributeVec2f(const char *iName) const;
+
+ /*! Returns an attribute of type Vec3f
+ * \param iName
+ * The name of the attribute
+ */
+ Vec3f getAttributeVec3f(const char *iName) const;
+
+ /*! Checks whether the attribute iName is availbale */
+ bool isAttributeAvailableReal(const char *iName) const;
+
+ /*! Checks whether the attribute iName is availbale */
+ bool isAttributeAvailableVec2f(const char *iName) const;
+
+ /*! Checks whether the attribute iName is availbale */
+ bool isAttributeAvailableVec3f(const char *iName) const;
+
+ /* modifiers */
+ /*! sets the attribute's color.
+ * \param r
+ * The new R value.
+ * \param g
+ * The new G value.
+ * \param b
+ * The new B value.
+ */
+ inline void setColor(float r, float g, float b)
+ {
+ _color[0] = r;
+ _color[1] = g;
+ _color[2] = b;
+ }
+
+ /*! sets the attribute's color.
+ * \param iRGB
+ * The new RGB values.
+ */
+ inline void setColor(const Vec3f& iRGB)
+ {
+ _color[0] = iRGB[0];
+ _color[1] = iRGB[1];
+ _color[2] = iRGB[2];
+ }
+
+ /*! sets the attribute's alpha value.
+ * \param alpha
+ * The new alpha value.
+ */
+ inline void setAlpha(float alpha)
+ {
+ _alpha = alpha;
+ }
+
+ /*! sets the attribute's thickness.
+ * \param tr
+ * The thickness on the right of the vertex when following the stroke.
+ * \param tl
+ * The thickness on the left of the vertex when following the stroke.
+ */
+ inline void setThickness(float tr, float tl)
+ {
+ _thickness[0] = tr;
+ _thickness[1] = tl;
+ }
+
+ /*! sets the attribute's thickness.
+ * \param tRL
+ * The thickness on the right and on the left of the vertex when following the stroke.
+ */
+ inline void setThickness(const Vec2f& tRL)
+ {
+ _thickness[0] = tRL[0];
+ _thickness[1] = tRL[1];
+ }
+
+ /*! sets the visible flag. True means visible. */
+ inline void setVisible(bool iVisible)
+ {
+ _visible = iVisible;
+ }
+
+ /*! Adds a user defined attribute of type real
+ * If there is no attribute of name iName, it is added.
+ * Otherwise, the new value replaces the old one.
+ * \param iName
+ * The name of the attribute
+ * \param att
+ * The attribute's value
+ */
+ void setAttributeReal(const char *iName, float att);
+
+ /*! Adds a user defined attribute of type Vec2f
+ * If there is no attribute of name iName, it is added.
+ * Otherwise, the new value replaces the old one.
+ * \param iName
+ * The name of the attribute
+ * \param att
+ * The attribute's value
+ */
+ void setAttributeVec2f(const char *iName, const Vec2f& att);
+
+ /*! Adds a user defined attribute of type Vec3f
+ * If there is no attribute of name iName, it is added.
+ * Otherwise, the new value replaces the old one.
+ * \param iName
+ * The name of the attribute
+ * \param att
+ * The attribute's value
+ */
+ void setAttributeVec3f(const char *iName, const Vec3f& att);
+
+private:
+ typedef std::map<const char *, float, StringUtils::ltstr> realMap;
+ typedef std::map<const char *, Vec2f, StringUtils::ltstr> Vec2fMap;
+ typedef std::map<const char *, Vec3f, StringUtils::ltstr> Vec3fMap;
+
+ float _color[3]; //! the color
+ float _alpha; //! alpha
+ float _thickness[2]; //! the thickness on the right and on the left of the backbone vertex (the stroke is oriented)
+ bool _visible;
+ realMap *_userAttributesReal;
+ Vec2fMap *_userAttributesVec2f;
+ Vec3fMap *_userAttributesVec3f;
+};
+
+
+//
+// StrokeVertex
+//
+////////////////////////////////////////////////////////
+
+/*! Class to define a stroke vertex. */
+class LIB_STROKE_EXPORT StrokeVertex : public CurvePoint
+{
+public: // Implementation of Interface0D
+ /*! Returns the string "StrokeVertex" */
+ virtual string getExactTypeName() const
+ {
+ return "StrokeVertex";
+ }
+
+private:
+ StrokeAttribute _Attribute; //! The attribute associated to the vertex
+ float _CurvilignAbscissa; //! the curvilign abscissa
+ float _StrokeLength; // stroke length
+
+public:
+ /*! default constructor */
+ StrokeVertex();
+
+ /*! Copy constructor */
+ StrokeVertex(const StrokeVertex& iBrother);
+
+ /*! Builds a stroke vertex from a SVertex */
+ StrokeVertex(SVertex *iSVertex);
+
+ /*! Builds a stroke vertex from a CurvePoint */
+ StrokeVertex(CurvePoint *iPoint);
+
+ /*! Builds Stroke Vertex from 2 stroke vertices and an interpolation parameter*/
+ StrokeVertex(StrokeVertex *iA, StrokeVertex *iB, float t3);
+
+ /*! Builds a stroke from a view vertex and an attribute */
+ StrokeVertex(SVertex *iSVertex, const StrokeAttribute& iAttribute);
+
+ /*! destructor */
+ virtual ~StrokeVertex();
+
+ /* operators */
+ /*! operator = */
+ StrokeVertex& operator=(const StrokeVertex& iBrother);
+
+ /* accessors */
+ /*! Returns the 2D point x coordinate */
+ inline real x() const
+ {
+ return _Point2d[0];
+ }
+
+ /*! Returns the 2D point y coordinate */
+ inline real y() const
+ {
+ return _Point2d[1];
+ }
+
+ /*! Returns the 2D point coordinates as a Vec2d */
+ Vec2f getPoint ()
+ {
+ return Vec2f((float)point2d()[0], (float)point2d()[1]);
+ }
+
+ /*! Returns the ith 2D point coordinate (i=0 or 1)*/
+ inline real operator[](const int i) const
+ {
+ return _Point2d[i];
+ }
+
+ /*! Returns the StrokeAttribute for this StrokeVertex */
+ inline const StrokeAttribute& attribute() const
+ {
+ return _Attribute;
+ }
+
+ /*! Returns a non-const reference to the StrokeAttribute of this StrokeVertex */
+ inline StrokeAttribute& attribute()
+ {
+ return _Attribute;
+ }
+
+ /*! Returns the curvilinear abscissa */
+ inline float curvilinearAbscissa() const
+ {
+ return _CurvilignAbscissa;
+ }
+
+ /*! Returns the length of the Stroke to which this StrokeVertex belongs */
+ inline float strokeLength() const
+ {
+ return _StrokeLength;
+ }
+
+ /*! Returns the curvilinear abscissa of this StrokeVertex in the Stroke */
+ inline float u() const
+ {
+ return _CurvilignAbscissa / _StrokeLength;
+ }
+
+ /* modifiers */
+ /*! sets the 2D x value */
+ inline void setX(real x)
+ {
+ _Point2d[0] = x;
+ }
+
+ /*! sets the 2D y value */
+ inline void setY(real y)
+ {
+ _Point2d[1] = y;
+ }
+
+ /*! sets the 2D x and y values */
+ inline void setPoint(real x, real y)
+ {
+ _Point2d[0] = x;
+ _Point2d[1] = y;
+ }
+
+ /*! sets the 2D x and y values */
+ inline void setPoint(const Vec2f& p)
+ {
+ _Point2d[0] = p[0];
+ _Point2d[1] = p[1];
+ }
+
+ /*! Returns a reference to the ith 2D point coordinate (i=0 or 1) */
+ inline real& operator[](const int i)
+ {
+ return _Point2d[i];
+ }
+
+ /*! sets the attribute. */
+ inline void setAttribute(const StrokeAttribute& iAttribute)
+ {
+ _Attribute = iAttribute;
+ }
+
+ /*! sets the curvilinear abscissa of this StrokeVertex in the Stroke */
+ inline void setCurvilinearAbscissa(float iAbscissa)
+ {
+ _CurvilignAbscissa = iAbscissa;
+ }
+
+ /*! sets the Stroke's length (it's only a value stored by the Stroke Vertex, it won't change the real
+ * Stroke's length.)
+ */
+ inline void setStrokeLength(float iLength)
+ {
+ _StrokeLength = iLength;
+ }
+
+ /* interface definition */
+ /* inherited */
+};
+
+
+//
+// Stroke
+//
+////////////////////////////////////////////////////////
+
+class StrokeRenderer;
+class StrokeRep;
+
+namespace StrokeInternal {
+
+class vertex_const_traits;
+class vertex_nonconst_traits;
+template<class Traits> class vertex_iterator_base;
+class StrokeVertexIterator;
+
+} // end of namespace StrokeInternal
+
+/*! Class to define a stroke.
+ * A stroke is made of a set of 2D vertices (StrokeVertex), regularly spaced out.
+ * This set of vertices defines the stroke's backbone geometry.
+ * Each of these stroke vertices defines the stroke's shape and appearance at this vertex position.
+ */
+class LIB_STROKE_EXPORT Stroke : public Interface1D
+{
+public: // Implementation of Interface1D
+ /*! Returns the string "Stroke" */
+ virtual string getExactTypeName() const
+ {
+ return "Stroke";
+ }
+
+ // Data access methods
+
+ /*! Returns the Id of the Stroke */
+ virtual Id getId() const
+ {
+ return _id;
+ }
+
+ /*! The different blending modes available to similate the interaction media-medium. */
+ typedef enum {
+ DRY_MEDIUM, /*!< To simulate a dry medium such as Pencil or Charcoal.*/
+ HUMID_MEDIUM, /*!< To simulate ink painting (color substraction blending).*/
+ OPAQUE_MEDIUM, /*!< To simulate an opaque medium (oil, spray...).*/
+ } MediumType;
+
+public:
+ typedef std::deque<StrokeVertex*> vertex_container; // the vertices container
+ typedef std::vector<ViewEdge*> viewedge_container; // the viewedges container
+ typedef StrokeInternal::vertex_iterator_base<StrokeInternal::vertex_nonconst_traits > vertex_iterator;
+ typedef StrokeInternal::vertex_iterator_base<StrokeInternal::vertex_const_traits> const_vertex_iterator;
+
+public:
+ //typedef StrokeVertex vertex_type;
+
+private:
+ vertex_container _Vertices; //! The stroke's backbone vertices
+ Id _id;
+ float _Length; // The stroke length
+ viewedge_container _ViewEdges;
+ float _sampling;
+ StrokeRenderer *_renderer; // mark implementation OpenGL renderer
+ MediumType _mediumType;
+ unsigned int _textureId;
+ bool _tips;
+ Vec2r _extremityOrientations[2]; // the orientations of the first and last extermity
+ StrokeRep *_rep;
+
+public:
+ /*! default constructor */
+ Stroke();
+
+ /*! copy constructor */
+ Stroke(const Stroke& iBrother);
+
+ /*! Builds a stroke from a set of StrokeVertex.
+ * This constructor is templated by an iterator type.
+ * This iterator type must allow the vertices parsing using the ++ operator.
+ * \param iBegin
+ * The iterator pointing to the first vertex.
+ * \param iEnd
+ * The iterator pointing to the end of the vertex list.
+ */
+ template<class InputVertexIterator>
+ Stroke(InputVertexIterator iBegin, InputVertexIterator iEnd);
+
+ /*! Destructor */
+ virtual ~Stroke();
+
+ /* operators */
+ /*! operator = */
+ Stroke& operator=(const Stroke& iBrother);
+
+ /*! Compute the sampling needed to get iNVertices vertices.
+ * If the specified number of vertices is less than the actual number of vertices, the actual sampling value
+ * is returned. (To remove Vertices, use the RemoveVertex() method of this class).
+ * \param iNVertices
+ * The number of StrokeVertices we eventually want in our Stroke.
+ * \return the sampling that must be used in the Resample(float) method.
+ * @see Resample(int)
+ * @see Resample(float)
+ */
+ float ComputeSampling(int iNVertices);
+
+ /*! Resampling method.
+ * Resamples the curve so that it eventually has iNPoints. That means it is going to add iNPoints-vertices_size,
+ * if vertices_size is the number of points we already have.
+ * If vertices_size >= iNPoints, no resampling is done.
+ * \param iNPoints
+ * The number of vertices we eventually want in our stroke.
+ */
+ void Resample(int iNPoints);
+
+ /*! Resampling method.
+ * Resamples the curve with a given sampling.
+ * If this sampling is < to the actual sampling value, no resampling is done.
+ * \param iSampling
+ * The new sampling value.
+ */
+ void Resample(float iSampling);
+
+ /*! Removes the stroke vertex iVertex
+ * from the stroke.
+ * The length and curvilinear abscissa are updated
+ * consequently.
+ */
+ void RemoveVertex(StrokeVertex *iVertex);
+
+ /*! Inserts the stroke vertex iVertex in the stroke before next.
+ * The length, curvilinear abscissa are updated consequently.
+ * \param iVertex
+ * The StrokeVertex to insert in the Stroke.
+ * \param next
+ * A StrokeVertexIterator pointing to the StrokeVeretx before which iVertex must be inserted.
+ */
+ void InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next);
+
+ /*! Updates the 2D length of the Stroke */
+ void UpdateLength();
+
+ /* Render method */
+ void ScaleThickness(float iFactor);
+ void Render(const StrokeRenderer *iRenderer);
+ void RenderBasic(const StrokeRenderer *iRenderer);
+
+ /* Iterator definition */
+
+ /* accessors */
+ /*! Returns the 2D length of the Stroke */
+ inline real getLength2D() const
+ {
+ return _Length;
+ }
+
+ /*! Returns a reference to the time stamp value of the stroke. */
+ /*! Returns the MediumType used for this Stroke. */
+ inline MediumType getMediumType() const
+ {
+ return _mediumType;
+ }
+
+ /*! Returns the id of the texture used to simulate th marks system for this Stroke */
+ inline unsigned int getTextureId() {return _textureId;}
+
+ /*! Returns true if this Stroke uses a texture with tips, false otherwise. */
+ inline bool hasTips() const
+ {
+ return _tips;
+ }
+
+ /* these advanced iterators are used only in C++ */
+ inline int vertices_size() const
+ {
+ return _Vertices.size();
+ }
+
+ inline viewedge_container::const_iterator viewedges_begin() const
+ {
+ return _ViewEdges.begin();
+ }
+
+ inline viewedge_container::iterator viewedges_begin()
+ {
+ return _ViewEdges.begin();
+ }
+
+ inline viewedge_container::const_iterator viewedges_end() const
+ {
+ return _ViewEdges.end();
+ }
+
+ inline viewedge_container::iterator viewedges_end()
+ {
+ return _ViewEdges.end();
+ }
+
+ inline int viewedges_size() const
+ {
+ return _ViewEdges.size();
+ }
+
+ inline Vec2r getBeginningOrientation() const
+ {
+ return _extremityOrientations[0];
+ }
+
+ inline real getBeginningOrientationX() const
+ {
+ return _extremityOrientations[0].x();
+ }
+
+ inline real getBeginningOrientationY() const
+ {
+ return _extremityOrientations[0].y();
+ }
+
+ inline Vec2r getEndingOrientation() const
+ {
+ return _extremityOrientations[1];
+ }
+
+ inline real getEndingOrientationX() const
+ {
+ return _extremityOrientations[1].x();
+ }
+
+ inline real getEndingOrientationY() const
+ {
+ return _extremityOrientations[1].y();
+ }
+
+
+ /* modifiers */
+ /*! sets the Id of the Stroke. */
+ inline void setId(const Id& id)
+ {
+ _id = id;
+ }
+
+ /*! sets the 2D length of the Stroke. */
+ void setLength(float iLength);
+
+ /*! sets the medium type that must be used for this Stroke. */
+ inline void setMediumType(MediumType iType)
+ {
+ _mediumType = iType;
+ }
+
+ /*! sets the texture id to be used to simulate the marks system for this Stroke. */
+ inline void setTextureId(unsigned int id)
+ {
+ _textureId = id;
+ }
+
+ /*! sets the flag telling whether this stroke is using a texture with tips or not. */
+ inline void setTips(bool iTips)
+ {
+ _tips = iTips;
+ }
+
+ inline void push_back(StrokeVertex *iVertex)
+ {
+ _Vertices.push_back(iVertex);
+ }
+
+ inline void push_front(StrokeVertex *iVertex)
+ {
+ _Vertices.push_front(iVertex);
+ }
+
+ inline void AddViewEdge(ViewEdge *iViewEdge)
+ {
+ _ViewEdges.push_back(iViewEdge);
+ }
+
+ inline void setBeginningOrientation(const Vec2r& iOrientation)
+ {
+ _extremityOrientations[0] = iOrientation;
+ }
+
+ inline void setBeginningOrientation(real x, real y)
+ {
+ _extremityOrientations[0] = Vec2r(x, y);
+ }
+
+ inline void setEndingOrientation(const Vec2r& iOrientation)
+ {
+ _extremityOrientations[1] = iOrientation;
+ }
+
+ inline void setEndingOrientation(real x, real y)
+ {
+ _extremityOrientations[1] = Vec2r(x, y);
+ }
+
+ /* Information access interface */
+
+ // embedding vertex iterator
+ const_vertex_iterator vertices_begin() const;
+ vertex_iterator vertices_begin(float t = 0.0f);
+ const_vertex_iterator vertices_end() const;
+ vertex_iterator vertices_end();
+
+ /*! Returns a StrokeVertexIterator pointing on the first StrokeVertex of the Stroke. One can specifly a sampling
+ * value to resample the Stroke on the fly if needed.
+ * \param t
+ * The resampling value with which we want our Stroke to be resampled.
+ * If 0 is specified, no resampling is done.
+ */
+ StrokeInternal::StrokeVertexIterator strokeVerticesBegin(float t = 0.0f);
+
+ /*! Returns a StrokeVertexIterator pointing after the last StrokeVertex of the Stroke. */
+ StrokeInternal::StrokeVertexIterator strokeVerticesEnd();
+
+ /*! Returns the number of StrokeVertex constituing the Stroke. */
+ inline unsigned int strokeVerticesSize() const
+ {
+ return _Vertices.size();
+ }
+
+ /*! Returns the i-th StrokeVertex constituting the Stroke. */
+ inline StrokeVertex& strokeVerticeAt(unsigned int i)
+ {
+ return *(_Vertices.at(i));
+ }
+
+ // Iterator access (Interface1D)
+ /*! Returns an Interface0DIterator pointing on the first StrokeVertex of the Stroke. */
+ virtual Interface0DIterator verticesBegin();
+
+ /*! Returns an Interface0DIterator pointing after the last StrokeVertex of the Stroke. */
+ virtual Interface0DIterator verticesEnd();
+
+ virtual Interface0DIterator pointsBegin(float t = 0.0f);
+ virtual Interface0DIterator pointsEnd(float t = 0.0f);
+};
+
+
+//
+// Implementation
+//
+////////////////////////////////////////////////////////
+
+
+template<class InputVertexIterator>
+Stroke::Stroke(InputVertexIterator iBegin, InputVertexIterator iEnd)
+{
+ for (InputVertexIterator v = iBegin, vend = iEnd; v != vend; v++) {
+ _Vertices.push_back(*v);
+ }
+ _Length = 0;
+ _id = 0;
+}
+
+#endif // __FREESTYLE_STROKE_H__
diff --git a/source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h b/source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h
new file mode 100644
index 00000000000..3d0f13276fb
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h
@@ -0,0 +1,191 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_STROKE_ADVANCED_ITERATORS_H__
+#define __FREESTYLE_STROKE_ADVANCED_ITERATORS_H__
+
+/** \file blender/freestyle/intern/stroke/StrokeAdvancedIterators.h
+ * \ingroup freestyle
+ * \brief Iterators used to iterate over the elements of the Stroke. Can't be used in python
+ * \author Stephane Grabli
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+#include "Stroke.h"
+
+namespace StrokeInternal {
+
+class vertex_const_traits : public Const_traits<StrokeVertex*>
+{
+public:
+ typedef std::deque<StrokeVertex*> vertex_container;
+ typedef vertex_container::const_iterator vertex_container_iterator;
+};
+
+class vertex_nonconst_traits : public Nonconst_traits<StrokeVertex*>
+{
+public:
+ typedef std::deque<StrokeVertex*> vertex_container; //! the vertices container
+ typedef vertex_container::iterator vertex_container_iterator;
+};
+
+
+template<class Traits>
+class vertex_iterator_base : public IteratorBase<Traits, BidirectionalIteratorTag_Traits>
+{
+public:
+ typedef vertex_iterator_base<Traits> Self;
+
+protected:
+ typedef IteratorBase<Traits, BidirectionalIteratorTag_Traits> parent_class;
+ typedef typename Traits::vertex_container_iterator vertex_container_iterator;
+ typedef vertex_iterator_base<vertex_nonconst_traits> iterator;
+ typedef vertex_iterator_base<vertex_const_traits> const_iterator;
+
+//protected:
+public:
+ vertex_container_iterator _it;
+ vertex_container_iterator _begin;
+ vertex_container_iterator _end;
+
+public:
+ friend class Stroke;
+ //friend class vertex_iterator;
+
+ inline vertex_iterator_base() : parent_class() {}
+
+ inline vertex_iterator_base(const iterator& iBrother) : parent_class()
+ {
+ _it = iBrother._it;
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ }
+
+ inline vertex_iterator_base(const const_iterator& iBrother) : parent_class()
+ {
+ _it = iBrother._it;
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ }
+
+//protected: //FIXME
+public:
+ inline vertex_iterator_base(vertex_container_iterator it, vertex_container_iterator begin,
+ vertex_container_iterator end)
+ : parent_class()
+ {
+ _it = it;
+ _begin = begin;
+ _end = end;
+ }
+
+public:
+ virtual ~vertex_iterator_base() {}
+
+ virtual bool begin() const
+ {
+ return (_it == _begin) ? true : false;
+ }
+
+ virtual bool end() const
+ {
+ return (_it == _end) ? true : false;
+ }
+
+ // operators
+ inline Self& operator++() // operator corresponding to ++i
+ {
+ ++_it;
+ return *(this);
+ }
+
+ /* Operator corresponding to i++, i.e. which returns the value *and then* increments.
+ * That's why we store the value in a temp.
+ */
+ inline Self operator++(int)
+ {
+ Self tmp = *this;
+ ++_it;
+ return tmp;
+ }
+
+ inline Self& operator--() // operator corresponding to --i
+ {
+ --_it;
+ return *(this);
+ }
+
+ inline Self operator--(int)
+ {
+ Self tmp = *this;
+ --_it;
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const Self& b) const
+ {
+ return (_it != b._it);
+ }
+
+ virtual bool operator==(const Self& b) const
+ {
+ return !(*this != b);
+ }
+
+ // dereferencing
+ virtual typename Traits::reference operator*() const
+ {
+ return *(_it);
+ }
+
+ virtual typename Traits::pointer operator->() const
+ {
+ return &(operator*());
+ }
+
+ /*! accessors */
+ inline vertex_container_iterator it() const
+ {
+ return _it;
+ }
+
+ inline vertex_container_iterator getBegin() const
+ {
+ return _begin;
+ }
+
+ inline vertex_container_iterator getEnd() const
+ {
+ return _end;
+ }
+};
+
+} // end of namespace StrokeInternal
+
+#endif // __FREESTYLE_STROKE_ADVANCED_ITERATORS_H__
diff --git a/source/blender/freestyle/intern/stroke/StrokeIO.cpp b/source/blender/freestyle/intern/stroke/StrokeIO.cpp
new file mode 100644
index 00000000000..182ae258480
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeIO.cpp
@@ -0,0 +1,77 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/stroke/StrokeIO.cpp
+ * \ingroup freestyle
+ * \brief Functions to manage I/O for the stroke
+ * \author Stephane Grabli
+ * \date 03/02/2004
+ */
+
+#include "StrokeAdvancedIterators.h"
+
+#include "StrokeIO.h"
+
+ostream& operator<<(ostream& out, const StrokeAttribute& iStrokeAttribute)
+{
+ out << " StrokeAttribute" << endl;
+ out << " color : (" << iStrokeAttribute.getColorR() << "," << iStrokeAttribute.getColorG() <<
+ "," << iStrokeAttribute.getColorB() << ")" << endl;
+ out << " alpha : " << iStrokeAttribute.getAlpha() << endl;
+ out << " thickness : " << iStrokeAttribute.getThicknessR() << ", " << iStrokeAttribute.getThicknessL() <<
+ endl;
+ out << " visible : " << iStrokeAttribute.isVisible() << endl;
+ return out;
+}
+
+ostream& operator<<(ostream& out, const StrokeVertex& iStrokeVertex)
+{
+ out << " StrokeVertex" << endl;
+ out << " id : " << iStrokeVertex.getId() << endl;
+ out << " curvilinear length : " << iStrokeVertex.curvilinearAbscissa() << endl;
+ out << " 2d coordinates : (" << iStrokeVertex.getProjectedX() << "," << iStrokeVertex.getProjectedY() <<
+ "," << iStrokeVertex.getProjectedZ() << ")" << endl;
+ out << " 3d coordinates : (" << iStrokeVertex.getX() << "," << iStrokeVertex.getY() <<
+ "," << iStrokeVertex.getZ() << ")" << endl;
+ out << iStrokeVertex.attribute() << endl;
+ return out;
+}
+
+ostream& operator<<(ostream& out, const Stroke& iStroke)
+{
+ out << "Stroke" << endl;
+ out << " id : " << iStroke.getId() << endl;
+ out << " length : " << iStroke.getLength2D() << endl;
+ out << " medium type : " << iStroke.getMediumType() << endl;
+ for (Stroke::const_vertex_iterator v = iStroke.vertices_begin(), vend = iStroke.vertices_end();
+ v != vend;
+ ++v)
+ {
+ out << *(*v) << endl;
+ }
+ return out;
+}
diff --git a/source/blender/freestyle/intern/stroke/StrokeIO.h b/source/blender/freestyle/intern/stroke/StrokeIO.h
new file mode 100644
index 00000000000..789c9c92c93
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeIO.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_STROKE_IO_H__
+#define __FREESTYLE_STROKE_IO_H__
+
+/** \file blender/freestyle/intern/stroke/StrokeIO.h
+ * \ingroup freestyle
+ * \brief Functions to manage I/O for the stroke
+ * \author Stephane Grabli
+ * \date 03/02/2004
+ */
+
+#include <iostream>
+
+#include "Stroke.h"
+
+#include "../system/FreestyleConfig.h"
+
+LIB_STROKE_EXPORT
+ostream& operator<<(ostream& out, const StrokeAttribute& iStrokeAttribute);
+
+LIB_STROKE_EXPORT
+ostream& operator<<(ostream& out, const StrokeVertex& iStrokeVertex);
+
+LIB_STROKE_EXPORT
+ostream& operator<<(ostream& out, const Stroke& iStroke);
+
+#endif // __FREESTYLE_STROKE_IO_H__
diff --git a/source/blender/freestyle/intern/stroke/StrokeIterators.h b/source/blender/freestyle/intern/stroke/StrokeIterators.h
new file mode 100644
index 00000000000..9cb8f517684
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeIterators.h
@@ -0,0 +1,229 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_STROKE_ITERATORS_H__
+#define __FREESTYLE_STROKE_ITERATORS_H__
+
+/** \file blender/freestyle/intern/stroke/StrokeIterators.h
+ * \ingroup freestyle
+ * \brief Iterators used to iterate over the elements of the Stroke
+ * \author Stephane Grabli
+ * \date 01/07/2003
+ */
+
+#include "Stroke.h"
+
+namespace StrokeInternal {
+
+//
+// StrokeVertexIterator
+//
+/////////////////////////////////////////////////
+
+/*! Class defining an iterator designed to iterate over the StrokeVertex of a Stroke.
+ * An instance of a StrokeVertexIterator can only be obtained from a Stroke by calling strokeVerticesBegin() or
+ * strokeVerticesEnd().
+ * It is iterating over the same vertices as an Interface0DIterator.
+ * The difference resides in the object access. Indeed, an Interface0DIterator allows only an access to an
+ * Interface0D whereas we could need to access the specialized StrokeVertex type. In this case, one
+ * should use a StrokeVertexIterator.
+ * The castToInterface0DIterator() method is useful to get an Interface0DIterator from a StrokeVertexIterator in
+ * order to call any functions of the type UnaryFunction0D.
+ * \attention In the scripting language, you must call \code it2 = StrokeVertexIterator(it1) \endcode instead of
+ * \code it2 = it1 \endcode where \a it1 and \a it2 are 2 StrokeVertexIterator.
+ * Otherwise, incrementing \a it1 will also increment \a it2.
+ */
+class StrokeVertexIterator : public Interface0DIteratorNested
+{
+public:
+ /*! Default constructor. */
+ StrokeVertexIterator() {}
+
+ /*! Copy constructor. */
+ StrokeVertexIterator(const StrokeVertexIterator& vi)
+ {
+ _it = vi._it;
+ _begin = vi._begin;
+ _end = vi._end;
+ }
+
+ StrokeVertexIterator(const ::Stroke::vertex_container::iterator& it,
+ const ::Stroke::vertex_container::iterator& begin,
+ const ::Stroke::vertex_container::iterator& end)
+ {
+ _it = it;
+ _begin = begin;
+ _end = end;
+ }
+
+ virtual ~StrokeVertexIterator() {}
+
+ /*! Casts this StrokeVertexIterator into an Interface0DIterator.
+ * Useful for any call to a function of the type UnaryFunction0D.
+ */
+ inline Interface0DIterator castToInterface0DIterator() const
+ {
+ Interface0DIterator ret(new StrokeVertexIterator(*this));
+ return ret;
+ }
+
+ /*! operator=
+ * \attention In the scripting language, you must call \code it2 = StrokeVertexIterator(it1) \endcode instead of
+ * \code it2 = it1 \endcode, where \a it1 and \a it2 are 2 StrokeVertexIterator.
+ * Otherwise, incrementing \a it1 will also increment \a it2.
+ */
+ StrokeVertexIterator& operator=(const StrokeVertexIterator& vi)
+ {
+ _it = vi._it;
+ _begin = vi._begin;
+ _end = vi._end;
+ return *this;
+ }
+
+ /*! Returns the string "StrokeVertexIterator". */
+ virtual string getExactTypeName() const
+ {
+ return "StrokeVertexIterator";
+ }
+
+ /*! Returns a reference to the pointed StrokeVertex.
+ * In the scripting language, you must call "getObject()"instead.
+ */
+ virtual StrokeVertex& operator*()
+ {
+ return **_it;
+ }
+
+ /*! Returns a pointer to the pointed StrokeVertex.
+ * Can't be called in the scripting language.
+ */
+ virtual StrokeVertex *operator->()
+ {
+ return &(operator*());
+ }
+
+ /*! Increments. In the scripting language, call "increment()". */
+ virtual StrokeVertexIterator& operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ /*! Increments. In the scripting language, call "increment()". */
+ virtual StrokeVertexIterator operator++(int)
+ {
+ StrokeVertexIterator ret(*this);
+ increment();
+ return ret;
+ }
+
+ /*! Decrements. In the scripting language, call "decrement()". */
+ virtual StrokeVertexIterator& operator--()
+ {
+ decrement();
+ return *this;
+ }
+
+ /*! Decrements. In the scripting language, call "decrement()". */
+ virtual StrokeVertexIterator operator--(int)
+ {
+ StrokeVertexIterator ret(*this);
+ decrement();
+ return ret;
+ }
+
+ /*! Increments. */
+ virtual int increment()
+ {
+ ++_it;
+ return 0;
+ }
+
+ /*! Decrements. */
+ virtual int decrement()
+ {
+ --_it;
+ return 0;
+ }
+
+ /*! Returns true if the pointed StrokeVertex is the first of the Stroke. */
+ bool isBegin() const
+ {
+ return _it == _begin;
+ }
+
+ /*! Returns true if the pointed StrokeVertex is after the last StrokeVertex of the Stroke. */
+ bool isEnd() const
+ {
+ return _it == _end;
+ }
+
+ /*! operator == */
+ virtual bool operator==(const Interface0DIteratorNested& it) const
+ {
+ const StrokeVertexIterator *it_exact = dynamic_cast<const StrokeVertexIterator *>(&it);
+ if (!it_exact)
+ return false;
+ return (_it == it_exact->_it);
+ }
+
+ /*! Returns the curvilinear abscissa of the current point */
+ virtual float t() const
+ {
+ return (*_it)->curvilinearAbscissa();
+ }
+
+ /*! Returns the point's parameter in the stroke */
+ virtual float u() const
+ {
+ return (*_it)->u();
+ }
+
+ /*! Cloning method */
+ virtual StrokeVertexIterator *copy() const
+ {
+ return new StrokeVertexIterator(*this);
+ }
+
+ //
+ // Not exported in Python
+ //
+ //////////////////////////////////////////////////
+ const ::Stroke::vertex_container::iterator& getIt()
+ {
+ return _it;
+ }
+
+private:
+ ::Stroke::vertex_container::iterator _it;
+ ::Stroke::vertex_container::iterator _begin;
+ ::Stroke::vertex_container::iterator _end;
+};
+
+} // end of namespace StrokeInternal
+
+#endif // __FREESTYLE_STROKE_ITERATORS_H__
diff --git a/source/blender/freestyle/intern/stroke/StrokeLayer.cpp b/source/blender/freestyle/intern/stroke/StrokeLayer.cpp
new file mode 100644
index 00000000000..b12477c3e34
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeLayer.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/stroke/StrokeLayer.cpp
+ * \ingroup freestyle
+ * \brief Class to define a layer of strokes.
+ * \author Stephane Grabli
+ * \date 18/12/2002
+ */
+
+#include "Canvas.h"
+#include "Stroke.h"
+#include "StrokeLayer.h"
+
+StrokeLayer::~StrokeLayer()
+{
+ clear();
+}
+
+void StrokeLayer::ScaleThickness(float iFactor)
+{
+ for (StrokeLayer::stroke_container::iterator s = _strokes.begin(), send = _strokes.end(); s != send; ++s) {
+ (*s)->ScaleThickness(iFactor);
+ }
+}
+
+void StrokeLayer::Render(const StrokeRenderer *iRenderer)
+{
+ for (StrokeLayer::stroke_container::iterator s = _strokes.begin(), send = _strokes.end(); s != send; ++s) {
+ (*s)->Render(iRenderer);
+ }
+}
+
+void StrokeLayer::RenderBasic(const StrokeRenderer *iRenderer)
+{
+ for (StrokeLayer::stroke_container::iterator s = _strokes.begin(), send = _strokes.end(); s != send; ++s) {
+ (*s)->RenderBasic(iRenderer);
+ }
+}
+
+void StrokeLayer::clear()
+{
+ for (stroke_container::iterator s = _strokes.begin(), send = _strokes.end(); s != send; ++s)
+ delete *s;
+ _strokes.clear();
+}
diff --git a/source/blender/freestyle/intern/stroke/StrokeLayer.h b/source/blender/freestyle/intern/stroke/StrokeLayer.h
new file mode 100644
index 00000000000..ff830db337a
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeLayer.h
@@ -0,0 +1,106 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_STROKE_LAYER_H__
+#define __FREESTYLE_STROKE_LAYER_H__
+
+/** \file blender/freestyle/intern/stroke/StrokeLayer.h
+ * \ingroup freestyle
+ * \brief Class to define a layer of strokes.
+ * \author Stephane Grabli
+ * \date 18/12/2002
+ */
+
+#include <deque>
+
+class Stroke;
+class StrokeRenderer;
+class StrokeLayer
+{
+public:
+ typedef std::deque<Stroke*> stroke_container;
+
+protected:
+ stroke_container _strokes;
+
+public:
+ StrokeLayer() {}
+
+ StrokeLayer(const stroke_container& iStrokes)
+ {
+ _strokes = iStrokes;
+ }
+
+ StrokeLayer(const StrokeLayer& iBrother)
+ {
+ _strokes = iBrother._strokes;
+ }
+
+ virtual ~StrokeLayer();
+
+ /*! Render method */
+ void ScaleThickness(float iFactor);
+ void Render(const StrokeRenderer *iRenderer);
+ void RenderBasic(const StrokeRenderer *iRenderer);
+
+ /*! clears the layer */
+ void clear();
+
+ /*! accessors */
+ inline stroke_container::iterator strokes_begin()
+ {
+ return _strokes.begin();
+ }
+
+ inline stroke_container::iterator strokes_end()
+ {
+ return _strokes.end();
+ }
+
+ inline int strokes_size() const
+ {
+ return _strokes.size();
+ }
+
+ inline bool empty() const
+ {
+ return _strokes.empty();
+ }
+
+ /*! modifiers */
+ inline void setStrokes(stroke_container& iStrokes)
+ {
+ _strokes = iStrokes;
+ }
+
+ inline void AddStroke(Stroke *iStroke)
+ {
+ _strokes.push_back(iStroke);
+ }
+};
+
+#endif // __FREESTYLE_STROKE_LAYER_H__
diff --git a/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp b/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp
new file mode 100644
index 00000000000..604cf6bd93d
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/stroke/StrokeRenderer.cpp
+ * \ingroup freestyle
+ * \brief Classes to render a stroke with OpenGL
+ * \author Fredo Durand
+ * \date 09/09/2002
+ */
+
+#include "StrokeRenderer.h"
+
+#include "../geometry/GeomUtils.h"
+
+using namespace std;
+
+/**********************************/
+/* */
+/* */
+/* StrokeRenderer */
+/* */
+/* */
+/**********************************/
+
+LIB_STROKE_EXPORT
+TextureManager *StrokeRenderer::_textureManager = 0;
+
+StrokeRenderer::StrokeRenderer() {}
+
+StrokeRenderer::~StrokeRenderer() {}
+
+bool StrokeRenderer::loadTextures()
+{
+ _textureManager->load();
+ return true;
+}
+
+
+/**********************************/
+/* */
+/* */
+/* TextureManager */
+/* */
+/* */
+/**********************************/
+
+
+LIB_STROKE_EXPORT
+TextureManager *TextureManager::_pInstance = 0;
+
+LIB_STROKE_EXPORT
+string TextureManager::_patterns_path;
+
+LIB_STROKE_EXPORT
+string TextureManager::_brushes_path;
+
+TextureManager::TextureManager()
+{
+ _hasLoadedTextures = false;
+ _pInstance = this;
+ _defaultTextureId = 0;
+}
+
+TextureManager::~TextureManager()
+{
+ if (!_brushesMap.empty())
+ _brushesMap.clear();
+ _pInstance = 0;
+}
+
+void TextureManager::load()
+{
+ if (_hasLoadedTextures)
+ return;
+ loadStandardBrushes();
+ _hasLoadedTextures = true;
+}
+
+unsigned TextureManager::getBrushTextureIndex(string name, Stroke::MediumType loadingMode)
+{
+ BrushTexture bt(name, loadingMode);
+ brushesMap::iterator b = _brushesMap.find(bt);
+ if (b == _brushesMap.end()) {
+ unsigned texId = loadBrush(name, loadingMode);
+ _brushesMap[bt] = texId;
+ return texId;
+ // XXX!
+ cerr << "brush file " << name << " not found" << endl;
+ return 0;
+ }
+ else {
+ return _brushesMap[bt];
+ }
+}
+
+void TextureManager::Options::setPatternsPath(const string& path)
+{
+ _patterns_path = path;
+}
+
+string TextureManager::Options::getPatternsPath()
+{
+ return _patterns_path;
+}
+
+void TextureManager::Options::setBrushesPath(const string& path)
+{
+ _brushes_path = path;
+}
+
+string TextureManager::Options::getBrushesPath()
+{
+ return _brushes_path;
+}
diff --git a/source/blender/freestyle/intern/stroke/StrokeRenderer.h b/source/blender/freestyle/intern/stroke/StrokeRenderer.h
new file mode 100644
index 00000000000..db169fb3fa2
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeRenderer.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_STROKE_RENDERER_H__
+#define __FREESTYLE_STROKE_RENDERER_H__
+
+/** \file blender/freestyle/intern/stroke/StrokeRenderer.h
+ * \ingroup freestyle
+ * \brief Classes to render a stroke with OpenGL
+ * \author Fredo Durand
+ * \date 09/09/2002
+ */
+
+#include <map>
+#include <string.h>
+#include <utility>
+#include <vector>
+
+#include "Stroke.h"
+#include "StrokeRep.h"
+
+#include "../system/FreestyleConfig.h"
+
+/**********************************/
+/* */
+/* */
+/* TextureManager */
+/* */
+/* */
+/**********************************/
+
+
+/*! Class to load textures */
+class LIB_STROKE_EXPORT TextureManager
+{
+public:
+ TextureManager ();
+ virtual ~TextureManager ();
+
+ static TextureManager *getInstance()
+ {
+ return _pInstance;
+ }
+
+ void load();
+ unsigned getBrushTextureIndex(string name, Stroke::MediumType iType = Stroke::OPAQUE_MEDIUM);
+
+ inline bool hasLoaded() const
+ {
+ return _hasLoadedTextures;
+ }
+
+ inline unsigned int getDefaultTextureId() const
+ {
+ return _defaultTextureId;
+ }
+
+ struct LIB_STROKE_EXPORT Options
+ {
+ static void setPatternsPath(const string& path);
+ static string getPatternsPath();
+
+ static void setBrushesPath(const string& path);
+ static string getBrushesPath();
+ };
+
+protected:
+ virtual void loadStandardBrushes() = 0;
+ virtual unsigned loadBrush(string fileName, Stroke::MediumType = Stroke::OPAQUE_MEDIUM) = 0;
+
+ typedef std::pair<string, Stroke::MediumType> BrushTexture;
+ struct cmpBrushTexture
+ {
+ bool operator()(const BrushTexture& bt1, const BrushTexture& bt2) const
+ {
+ int r = strcmp(bt1.first.c_str(), bt2.first.c_str());
+ if (r != 0)
+ return (r < 0);
+ else
+ return (bt1.second < bt2.second);
+ }
+ };
+ typedef std::map<BrushTexture, unsigned, cmpBrushTexture> brushesMap;
+
+ static TextureManager *_pInstance;
+ bool _hasLoadedTextures;
+ brushesMap _brushesMap;
+ static string _patterns_path;
+ static string _brushes_path;
+ unsigned int _defaultTextureId;
+};
+
+
+/**********************************/
+/* */
+/* */
+/* StrokeRenderer */
+/* */
+/* */
+/**********************************/
+
+/*! Class to render a stroke. Creates a triangle strip and stores it strip is lazily created at the first rendering */
+class LIB_STROKE_EXPORT StrokeRenderer
+{
+public:
+ StrokeRenderer();
+ virtual ~StrokeRenderer();
+
+ /*! Renders a stroke rep */
+ virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const = 0;
+ virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const = 0;
+
+ // initializes the texture manager
+ // lazy, checks if it has already been done
+ static bool loadTextures();
+
+ //static unsigned int getTextureIndex(unsigned int index);
+ static TextureManager *_textureManager;
+};
+
+#endif // __FREESTYLE_STROKE_RENDERER_H__
diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.cpp b/source/blender/freestyle/intern/stroke/StrokeRep.cpp
new file mode 100644
index 00000000000..10c3c2efe18
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeRep.cpp
@@ -0,0 +1,789 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/stroke/StrokeRep.cpp
+ * \ingroup freestyle
+ * \brief Class to define the representation of a stroke (for display purpose)
+ * \author Stephane Grabli
+ * \date 05/03/2003
+ */
+
+#include "Stroke.h"
+#include "StrokeAdvancedIterators.h"
+#include "StrokeIterators.h"
+#include "StrokeRenderer.h"
+#include "StrokeRep.h"
+
+using namespace std;
+
+//
+// STROKE VERTEX REP
+/////////////////////////////////////
+
+StrokeVertexRep::StrokeVertexRep(const StrokeVertexRep& iBrother)
+{
+ _point2d = iBrother._point2d;
+ _texCoord = iBrother._texCoord;
+ _color = iBrother._color;
+ _alpha = iBrother._alpha;
+}
+
+//
+// STRIP
+/////////////////////////////////////
+
+Strip::Strip(const vector<StrokeVertex*>& iStrokeVertices, bool hasTips, bool beginTip, bool endTip)
+{
+ createStrip(iStrokeVertices);
+ if (!hasTips)
+ computeTexCoord (iStrokeVertices);
+ else
+ computeTexCoordWithTips (iStrokeVertices, beginTip, endTip);
+}
+
+Strip::Strip(const Strip& iBrother)
+{
+ if (!iBrother._vertices.empty()) {
+ for (vertex_container::const_iterator v = iBrother._vertices.begin(), vend = iBrother._vertices.end();
+ v != vend;
+ ++v)
+ {
+ _vertices.push_back(new StrokeVertexRep(**v));
+ }
+ }
+ _averageThickness = iBrother._averageThickness;
+}
+
+Strip::~Strip()
+{
+ if (!_vertices.empty()) {
+ for (vertex_container::iterator v = _vertices.begin(), vend = _vertices.end(); v != vend; ++v) {
+ delete (*v);
+ }
+ _vertices.clear();
+ }
+}
+
+//////////////////////////
+// Strip creation
+//////////////////////////
+
+#define EPS_SINGULARITY_RENDERER 0.05
+#define ZERO 0.00001
+#define MAX_RATIO_LENGTH_SINGU 2
+#define HUGE_COORD 1.0e4
+
+static bool notValid (Vec2r p)
+{
+ return (p[0] != p[0]) || (p[1] != p[1]) || (fabs(p[0]) > HUGE_COORD) || (fabs(p[1]) > HUGE_COORD) ||
+ (p[0] < -HUGE_COORD) || (p[1] < -HUGE_COORD);
+}
+
+static real crossP(const Vec2r& A, const Vec2r& B)
+{
+ return A[0] * B[1] - A[1] * B[0];
+}
+
+void Strip::createStrip (const vector<StrokeVertex*>& iStrokeVertices)
+{
+ //computeParameterization();
+ if (iStrokeVertices.size() < 2) {
+ cerr << "Warning: strip has less than 2 vertices" << endl;
+ return;
+ }
+ _vertices.reserve(2 * iStrokeVertices.size());
+ if (!_vertices.empty()) {
+ for (vertex_container::iterator v = _vertices.begin(), vend = _vertices.end(); v != vend; ++v) {
+ delete (*v);
+ }
+ _vertices.clear();
+ }
+ _averageThickness = 0.0;
+
+ vector<StrokeVertex *>::const_iterator v, vend, v2, vPrev;
+ StrokeVertex *sv, *sv2, *svPrev;
+
+ //special case of first vertex
+ v = iStrokeVertices.begin();
+ sv = *v;
+ vPrev = v; //in case the stroke has only 2 vertices;
+ ++v;
+ sv2 = *v;
+ Vec2r dir(sv2->getPoint() - sv->getPoint());
+ Vec2r orthDir(-dir[1], dir[0]);
+ if (orthDir.norm() > ZERO)
+ orthDir.normalize();
+ Vec2r stripDir(orthDir);
+ // check whether the orientation was user defined
+ if (sv->attribute().isAttributeAvailableVec2f("orientation")) {
+ Vec2r userDir = sv->attribute().getAttributeVec2f("orientation");
+ userDir.normalize();
+ real dp = userDir * orthDir;
+ if (dp < 0)
+ userDir = userDir * (-1.0f);
+ stripDir = userDir;
+ }
+ const float *thickness = sv->attribute().getThickness();
+ _vertices.push_back(new StrokeVertexRep(sv->getPoint() + thickness[1] * stripDir));
+ _vertices.push_back(new StrokeVertexRep(sv->getPoint() - thickness[0] * stripDir));
+
+#if 0
+ Vec2r userDir = _stroke->getBeginningOrientation();
+ if (userDir != Vec2r(0, 0)) {
+ userDir.normalize();
+ real o1 = (orthDir * userDir);
+ real o2 = crossP(orthDir, userDir);
+ real orientation = o1 * o2;
+ if (orientation > 0) {
+ // then the vertex to move is v0
+ if (o1 > 0)
+ _vertex[0] = _vertex[1] + userDir;
+ else
+ _vertex[0] = _vertex[1] - userDir;
+ }
+ if (orientation < 0) {
+ // then we must move v1
+ if (o1 < 0)
+ _vertex[1] = _vertex[0] + userDir;
+ else
+ _vertex[1] = _vertex[0] - userDir;
+ }
+ }
+#endif
+
+ int i = 2; // 2 because we have already processed the first vertex
+
+ for (vend = iStrokeVertices.end(); v != vend; ++v) {
+ v2 = v;
+ ++v2;
+ if (v2 == vend)
+ break;
+ sv = (*v);
+ sv2 = (*v2);
+ svPrev = (*vPrev);
+ Vec2r p(sv->getPoint()), p2(sv2->getPoint()), pPrev(svPrev->getPoint());
+
+ //direction and orthogonal vector to the next segment
+ Vec2r dir(p2 - p);
+ float dirNorm = dir.norm();
+ dir.normalize();
+ Vec2r orthDir(-dir[1], dir[0]);
+ Vec2r stripDir = orthDir;
+ if (sv->attribute().isAttributeAvailableVec2f("orientation")) {
+ Vec2r userDir = sv->attribute().getAttributeVec2f("orientation");
+ userDir.normalize();
+ real dp = userDir * orthDir;
+ if (dp < 0)
+ userDir = userDir * (-1.0f);
+ stripDir = userDir;
+ }
+
+ //direction and orthogonal vector to the previous segment
+ Vec2r dirPrev(p - pPrev);
+ float dirPrevNorm = dirPrev.norm();
+ dirPrev.normalize();
+ Vec2r orthDirPrev(-dirPrev[1], dirPrev[0]);
+ Vec2r stripDirPrev = orthDirPrev;
+ if (svPrev->attribute().isAttributeAvailableVec2f("orientation")) {
+ Vec2r userDir = svPrev->attribute().getAttributeVec2f("orientation");
+ userDir.normalize();
+ real dp = userDir * orthDir;
+ if (dp < 0)
+ userDir = userDir * (-1.0f);
+ stripDirPrev = userDir;
+ }
+
+ const float *thickness = sv->attribute().getThickness();
+ _averageThickness += thickness[0] + thickness[1];
+ Vec2r pInter;
+ int interResult;
+
+ interResult = GeomUtils::intersect2dLine2dLine(Vec2r(pPrev + thickness[1] * stripDirPrev),
+ Vec2r(p + thickness[1] * stripDirPrev),
+ Vec2r(p + thickness[1] * stripDir),
+ Vec2r(p2 + thickness[1] * stripDir),
+ pInter);
+ if (interResult == GeomUtils::DO_INTERSECT)
+ _vertices.push_back(new StrokeVertexRep(pInter));
+ else
+ _vertices.push_back(new StrokeVertexRep(p + thickness[1] * stripDir));
+ ++i;
+
+ interResult = GeomUtils::intersect2dLine2dLine(Vec2r(pPrev - thickness[0] * stripDirPrev),
+ Vec2r(p - thickness[0] * stripDirPrev),
+ Vec2r(p - thickness[0] * stripDir),
+ Vec2r(p2 - thickness[0] * stripDir),
+ pInter);
+ if (interResult == GeomUtils::DO_INTERSECT)
+ _vertices.push_back(new StrokeVertexRep(pInter));
+ else
+ _vertices.push_back(new StrokeVertexRep(p - thickness[0] * stripDir));
+ ++i;
+
+ // if the angle is obtuse, we simply average the directions to avoid the singularity
+ stripDir = stripDir + stripDirPrev;
+ if ((dirNorm < ZERO) || (dirPrevNorm < ZERO) || (stripDir.norm() < ZERO)) {
+ stripDir[0] = 0;
+ stripDir[1] = 0;
+ }
+ else {
+ stripDir.normalize();
+ }
+
+ Vec2r vec_tmp(_vertices[i - 2]->point2d() - p);
+ if ((vec_tmp.norm() > thickness[1] * MAX_RATIO_LENGTH_SINGU) || (dirNorm < ZERO) || (dirPrevNorm < ZERO) ||
+ notValid(_vertices[i - 2]->point2d()) || (fabs(stripDir * dir) < EPS_SINGULARITY_RENDERER))
+ {
+ _vertices[i - 2]->setPoint2d(p + thickness[1] * stripDir);
+ }
+
+ vec_tmp = _vertices[i - 1]->point2d() - p;
+ if ((vec_tmp.norm() > thickness[0] * MAX_RATIO_LENGTH_SINGU) || (dirNorm < ZERO) || (dirPrevNorm < ZERO) ||
+ notValid(_vertices[i - 1]->point2d()) || (fabs(stripDir * dir) < EPS_SINGULARITY_RENDERER))
+ {
+ _vertices[i - 1]->setPoint2d(p - thickness[0] * stripDir);
+ }
+
+ vPrev = v;
+ } // end of for
+
+ //special case of last vertex
+ sv = *v;
+ sv2 = *vPrev;
+ dir = Vec2r(sv->getPoint() - sv2->getPoint());
+ orthDir = Vec2r(-dir[1], dir[0]);
+ if (orthDir.norm() > ZERO)
+ orthDir.normalize();
+ Vec2r stripDirLast(orthDir);
+ // check whether the orientation was user defined
+ if (sv->attribute().isAttributeAvailableVec2f("orientation")) {
+ Vec2r userDir = sv->attribute().getAttributeVec2f("orientation");
+ userDir.normalize();
+ real dp = userDir * orthDir;
+ if (dp < 0)
+ userDir = userDir * (-1.0f);
+ stripDirLast = userDir;
+ }
+ const float *thicknessLast = sv->attribute().getThickness();
+ _vertices.push_back(new StrokeVertexRep(sv->getPoint() + thicknessLast[1] * stripDirLast));
+ ++i;
+ _vertices.push_back(new StrokeVertexRep(sv->getPoint() - thicknessLast[0] * stripDirLast));
+ ++i;
+
+#if 0
+ int n = i - 1;
+ // check whether the orientation of the extremity was user defined
+ userDir = _stroke->getEndingOrientation();
+ if (userDir != Vec2r(0, 0)) {
+ userDir.normalize();
+ real o1 = (orthDir * userDir);
+ real o2 = crossP(orthDir, userDir);
+ real orientation = o1 * o2;
+ if (orientation > 0) {
+ // then the vertex to move is vn
+ if (o1 < 0)
+ _vertex[n] = _vertex[n - 1] + userDir;
+ else
+ _vertex[n] = _vertex[n - 1] - userDir;
+ }
+ if (orientation < 0) {
+ // then we must move vn-1
+ if (o1 > 0)
+ _vertex[n - 1] = _vertex[n] + userDir;
+ else
+ _vertex[n - 1] = _vertex[n] - userDir;
+ }
+ }
+#endif
+
+ _averageThickness /= float(iStrokeVertices.size() - 2);
+ //I did not use the first and last vertex for the average
+ if (iStrokeVertices.size() < 3)
+ _averageThickness = 0.5 * (thicknessLast[1] + thicknessLast[0] + thickness[0] + thickness[1]);
+
+ if (i != 2 * (int)iStrokeVertices.size())
+ cerr << "Warning: problem with stripe size\n";
+
+ cleanUpSingularities (iStrokeVertices);
+}
+
+// CLEAN UP
+/////////////////////////
+
+void Strip::cleanUpSingularities (const vector<StrokeVertex*>& iStrokeVertices)
+{
+ int k;
+ int sizeStrip = _vertices.size();
+
+ for (k = 0; k < sizeStrip; k++) {
+ if (notValid(_vertices[k]->point2d())) {
+ cerr << "Warning: strip vertex " << k << " non valid" << endl;
+ return;
+ }
+ }
+
+ //return;
+ if (iStrokeVertices.size() < 2)
+ return;
+ int i = 0, j;
+ vector<StrokeVertex *>::const_iterator v, vend, v2, vPrev;
+ StrokeVertex *sv, *sv2; //soc unused - *svPrev;
+
+ bool singu1 = false, singu2 = false;
+ int timeSinceSingu1 = 0, timeSinceSingu2 = 0;
+
+ //special case of first vertex
+ v = iStrokeVertices.begin();
+ for (vend = iStrokeVertices.end(); v != vend; v++) {
+ v2 = v;
+ ++v2;
+ if (v2 == vend)
+ break;
+ sv = (*v);
+ sv2 = (*v2);
+ Vec2r p(sv->getPoint()), p2(sv2->getPoint());
+
+ Vec2r dir(p2 - p);
+ if (dir.norm() > ZERO)
+ dir.normalize();
+ Vec2r dir1, dir2;
+ dir1 = _vertices[2 * i + 2]->point2d() - _vertices[2 * i]->point2d();
+ dir2 = _vertices[2 * i + 3]->point2d() - _vertices[2 * i + 1]->point2d();
+
+ if ((dir1 * dir) < -ZERO) {
+ singu1 = true;
+ timeSinceSingu1++;
+ }
+ else {
+ if (singu1) {
+ int toto = i - timeSinceSingu1;
+ if (toto < 0)
+ cerr << "Stephane dit \"Toto\"" << endl;
+ //traverse all the vertices of the singularity and average them
+ Vec2r avP(0.0, 0.0);
+ for (j = i - timeSinceSingu1; j < i + 1; j++)
+ avP = Vec2r(avP + _vertices[2 * j]->point2d());
+ avP = Vec2r( 1.0 / float(timeSinceSingu1 + 1) * avP);
+ for (j = i - timeSinceSingu1; j < i + 1; j++)
+ _vertices[2 * j]->setPoint2d(avP);
+ //_vertex[2 * j] = _vertex[2 * i];
+ singu1 = false;
+ timeSinceSingu1 = 0;
+ }
+ }
+ if ((dir2 * dir) < -ZERO) {
+ singu2 = true;
+ timeSinceSingu2++;
+ }
+ else {
+ if (singu2) {
+ int toto = i - timeSinceSingu2;
+ if (toto < 0)
+ cerr << "Stephane dit \"Toto\"" << endl;
+ //traverse all the vertices of the singularity and average them
+ Vec2r avP(0.0, 0.0);
+ for (j = i - timeSinceSingu2; j < i + 1; j++)
+ avP = Vec2r(avP + _vertices[2 * j + 1]->point2d());
+ avP = Vec2r(1.0 / float(timeSinceSingu2 + 1) * avP);
+ for (j = i - timeSinceSingu2; j < i + 1; j++)
+ _vertices[2 * j + 1]->setPoint2d(avP);
+ //_vertex[2 * j + 1] = _vertex[2 * i + 1];
+ singu2 = false;
+ timeSinceSingu2 = 0;
+ }
+ }
+ i++;
+ }
+
+ if (singu1) {
+ //traverse all the vertices of the singularity and average them
+ 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) * avP);
+ for (j = i - timeSinceSingu1; j < i; j++)
+ _vertices[2 * j]->setPoint2d(avP);
+ }
+ if (singu2) {
+ //traverse all the vertices of the singularity and average them
+ Vec2r avP(0.0, 0.0);
+ for (j = i - timeSinceSingu2; j < i; j++)
+ avP = Vec2r(avP + _vertices[2 * j + 1]->point2d());
+ avP = Vec2r(1.0 / float(timeSinceSingu2) * avP);
+ for (j = i - timeSinceSingu2; j < i; j++)
+ _vertices[2 * j + 1]->setPoint2d(avP);
+ }
+
+ for (k = 0; k < sizeStrip; k++) {
+ if (notValid(_vertices[k]->point2d())) {
+ cerr << "Warning: strip vertex " << k << " non valid after cleanup" << endl;
+ return;
+ }
+ }
+}
+
+
+// Texture coordinates
+////////////////////////////////
+
+void Strip::computeTexCoord (const vector<StrokeVertex *>& iStrokeVertices)
+{
+ vector<StrokeVertex *>::const_iterator v, vend;
+ StrokeVertex *sv;
+ int i = 0;
+ for (v = iStrokeVertices.begin(), vend = iStrokeVertices.end(); v != vend; v++) {
+ sv = (*v);
+ _vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / _averageThickness), 0));
+ _vertices[i]->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
+ sv->attribute().getColor()[2]));
+ _vertices[i]->setAlpha(sv->attribute().getAlpha());
+ i++;
+ _vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / _averageThickness), 1));
+ _vertices[i]->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
+ sv->attribute().getColor()[2]));
+ _vertices[i]->setAlpha(sv->attribute().getAlpha());
+ i++;
+#if 0
+ cerr << "col=("<<sv->attribute().getColor()[0] << ", "
+ << sv->attribute().getColor()[1] << ", " << sv->attribute().getColor()[2] << ")" << endl;
+#endif
+ }
+}
+
+void Strip::computeTexCoordWithTips (const vector<StrokeVertex*>& iStrokeVertices, bool tipBegin, bool tipEnd)
+{
+ //soc unused - unsigned int sizeStrip = _vertices.size() + 8; //for the transition between the tip and the body
+ vector<StrokeVertex*>::const_iterator v, vend;
+ StrokeVertex *sv = NULL;
+
+ v = iStrokeVertices.begin();
+ vend = iStrokeVertices.end();
+ float l = (*v)->strokeLength() / _averageThickness;
+ int tiles = int(l);
+ float fact = (float(tiles) + 0.5) / l;
+ //soc unused - float uTip2 = float(tiles) + 0.25;
+ float u = 0;
+ float uPrev = 0;
+ int i = 0;
+ float t;
+ StrokeVertexRep *tvRep1, *tvRep2;
+
+#if 0
+ cerr << "l=" << l << " tiles=" << tiles << " _averageThicnkess="
+ << _averageThickness << " strokeLength=" << (*v)->strokeLength() << endl;
+#endif
+
+ vector<StrokeVertexRep*>::iterator currentSV = _vertices.begin();
+ StrokeVertexRep *svRep;
+ if (tipBegin) {
+ for (; v != vend; v++) {
+ sv = (*v);
+ svRep = *currentSV;
+ u = sv->curvilinearAbscissa() / _averageThickness * fact;
+ if (u > 0.25)
+ break;
+
+ svRep->setTexCoord(Vec2r((real)u, 0.5));
+ svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
+ sv->attribute().getColor()[2]));
+ svRep->setAlpha(sv->attribute().getAlpha());
+ i++;
+ ++currentSV;
+
+ svRep = *currentSV;
+ svRep->setTexCoord(Vec2r((real)u, 1));
+ svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
+ sv->attribute().getColor()[2]));
+ svRep->setAlpha(sv->attribute().getAlpha());
+ i++;
+ ++currentSV;
+ uPrev = u;
+ }
+ //first transition vertex
+
+ if (fabs(u - uPrev) > ZERO)
+ t = (0.25 - uPrev) / (u - uPrev);
+ else
+ t = 0;
+#if 0
+ if (!tiles)
+ t = 0.5;
+#endif
+ tvRep1 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d()));
+ tvRep1->setTexCoord(Vec2r(0.25, 0.5));
+ tvRep1->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() +
+ t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
+ sv->attribute().getColor()[2])));
+ tvRep1->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha());
+ i++;
+
+ tvRep2 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t *_vertices[i]->point2d()));
+ tvRep2->setTexCoord(Vec2r(0.25, 1));
+ tvRep2->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() +
+ t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
+ sv->attribute().getColor()[2])));
+ tvRep2->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha());
+ i++;
+
+ currentSV = _vertices.insert(currentSV, tvRep1);
+ ++currentSV;
+ currentSV = _vertices.insert(currentSV, tvRep2);
+ ++currentSV;
+
+ // copy the vertices with different texture coordinates
+ tvRep1 = new StrokeVertexRep(_vertices[i - 2]->point2d());
+ tvRep1->setTexCoord(Vec2r(0.25, 0));
+ tvRep1->setColor(_vertices[i - 2]->color());
+ tvRep1->setAlpha(_vertices[i - 2]->alpha());
+ i++;
+
+ tvRep2 = new StrokeVertexRep(_vertices[i - 2]->point2d());
+ tvRep2->setTexCoord(Vec2r(0.25, 0.5));
+ tvRep2->setColor(_vertices[i - 2]->color());
+ tvRep2->setAlpha(_vertices[i - 2]->alpha());
+ i++;
+
+ currentSV = _vertices.insert(currentSV, tvRep1);
+ ++currentSV;
+ currentSV = _vertices.insert(currentSV, tvRep2);
+ ++currentSV;
+ }
+ uPrev = 0;
+
+ //body of the stroke
+ for (; v != vend; v++) {
+ sv = (*v);
+ svRep = *currentSV;
+ u = sv->curvilinearAbscissa() / _averageThickness * fact - 0.25;
+ if (u > tiles)
+ break;
+
+ svRep->setTexCoord(Vec2r((real)u, 0));
+ svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
+ sv->attribute().getColor()[2]));
+ svRep->setAlpha(sv->attribute().getAlpha());
+ i++;
+ ++currentSV;
+
+ svRep = *currentSV;
+ svRep->setTexCoord(Vec2r((real)u, 0.5));
+ svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
+ sv->attribute().getColor()[2]));
+ svRep->setAlpha(sv->attribute().getAlpha());
+ i++;
+ ++currentSV;
+
+ uPrev = u;
+ }
+ if (tipEnd) {
+ //second transition vertex
+ if ((fabs(u - uPrev) > ZERO))
+ t = (float(tiles) - uPrev) / (u - uPrev);
+ else
+ t = 0;
+
+ tvRep1 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d()));
+ tvRep1->setTexCoord(Vec2r((real)tiles, 0));
+ tvRep1->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() +
+ t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
+ sv->attribute().getColor()[2])));
+ tvRep1->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha());
+ i++;
+
+ tvRep2 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d()));
+ tvRep2->setTexCoord(Vec2r((real)tiles, 0.5));
+ tvRep2->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() +
+ t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
+ sv->attribute().getColor()[2])));
+ tvRep2->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha());
+ i++;
+
+ currentSV = _vertices.insert(currentSV, tvRep1);
+ ++currentSV;
+ currentSV = _vertices.insert(currentSV, tvRep2);
+ ++currentSV;
+
+ //copy the vertices with different texture coordinates
+ tvRep1 = new StrokeVertexRep(_vertices[i - 2]->point2d());
+ tvRep1->setTexCoord(Vec2r(0.75, 0.5));
+ tvRep1->setColor(_vertices[i - 2]->color());
+ tvRep1->setAlpha(_vertices[i - 2]->alpha());
+ i++;
+
+ tvRep2 = new StrokeVertexRep(_vertices[i - 2]->point2d());
+ tvRep2->setTexCoord(Vec2r(0.75, 1));
+ tvRep2->setColor(_vertices[i - 2]->color());
+ tvRep2->setAlpha(_vertices[i - 2]->alpha());
+ i++;
+
+ currentSV = _vertices.insert(currentSV, tvRep1);
+ ++currentSV;
+ currentSV = _vertices.insert(currentSV, tvRep2);
+ ++currentSV;
+
+ //end tip
+ for (; v != vend; v++) {
+ sv = (*v);
+ svRep = *currentSV;
+ u = 0.75 + sv->curvilinearAbscissa() / _averageThickness * fact - float(tiles) - 0.25;
+
+ svRep->setTexCoord(Vec2r((real)u, 0.5));
+ svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
+ sv->attribute().getColor()[2]));
+ svRep->setAlpha(sv->attribute().getAlpha());
+ i++;
+ ++currentSV;
+
+ svRep = *currentSV;
+ svRep->setTexCoord(Vec2r((real)u, 1));
+ svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
+ sv->attribute().getColor()[2]));
+ svRep->setAlpha(sv->attribute().getAlpha());
+ i++;
+ ++currentSV;
+ }
+ }
+
+#if 0
+ cerr << "u=" << u << " i=" << i << "/" << _sizeStrip << endl;
+
+ for (i = 0; i < _sizeStrip; i++)
+ _alpha[i] = 1.0;
+
+ for (i = 0; i < _sizeStrip; i++)
+ cerr << "(" << _texCoord[i][0] << ", " << _texCoord[i][1] << ") ";
+ cerr << endl;
+
+ Vec2r vec_tmp;
+ for (i = 0; i < _sizeStrip / 2; i++)
+ vec_tmp = _vertex[2 * i] - _vertex[2 * i + 1];
+ if (vec_tmp.norm() > 4 * _averageThickness)
+ cerr << "Warning (from Fredo): There is a pb in the texture coordinates computation" << endl;
+#endif
+}
+
+//
+// StrokeRep
+/////////////////////////////////////
+
+StrokeRep::StrokeRep()
+{
+ _stroke = 0;
+ _strokeType = Stroke::OPAQUE_MEDIUM;
+ TextureManager *ptm = TextureManager::getInstance();
+ if (ptm)
+ _textureId = ptm->getDefaultTextureId();
+#if 0
+ _averageTextureAlpha = 0.5; //default value
+ if (_strokeType == OIL_STROKE)
+ _averageTextureAlpha = 0.75;
+ if (_strokeType >= NO_BLEND_STROKE)
+ _averageTextureAlpha = 1.0
+#endif
+}
+
+StrokeRep::StrokeRep(Stroke *iStroke)
+{
+ _stroke = iStroke;
+ _strokeType = iStroke->getMediumType();
+ _textureId = iStroke->getTextureId();
+ if (_textureId == 0) {
+ TextureManager *ptm = TextureManager::getInstance();
+ if (ptm)
+ _textureId = ptm->getDefaultTextureId();
+ }
+
+#if 0
+ _averageTextureAlpha = 0.5; //default value
+ if (_strokeType == OIL_STROKE)
+ _averageTextureAlpha = 0.75;
+ if (_strokeType >= NO_BLEND_STROKE)
+ _averageTextureAlpha = 1.0;
+#endif
+ create();
+}
+
+StrokeRep::StrokeRep(const StrokeRep& iBrother)
+{
+ //soc unused - int i = 0;
+ _stroke = iBrother._stroke;
+ _strokeType = iBrother._strokeType;
+ _textureId = iBrother._textureId;
+ for (vector<Strip*>::const_iterator s = iBrother._strips.begin(), send = iBrother._strips.end();
+ s != send;
+ ++s)
+ {
+ _strips.push_back(new Strip(**s));
+ }
+}
+
+StrokeRep::~StrokeRep()
+{
+ if (!_strips.empty()) {
+ for (vector<Strip*>::iterator s = _strips.begin(), send = _strips.end(); s != send; ++s) {
+ delete (*s);
+ }
+ _strips.clear();
+ }
+}
+
+void StrokeRep::create()
+{
+ vector<StrokeVertex*> strip;
+ StrokeInternal::StrokeVertexIterator v = _stroke->strokeVerticesBegin();
+ StrokeInternal::StrokeVertexIterator vend = _stroke->strokeVerticesEnd();
+
+ bool first = true;
+ bool end = false;
+ while (v != vend) {
+ while ((v != vend) && (!(*v).attribute().isVisible())) {
+ ++v;
+ first = false;
+ }
+ while ((v != vend) && ((*v).attribute().isVisible())) {
+ strip.push_back(&(*v));
+ ++v;
+ }
+ if (v != vend) {
+ // add the last vertex and create
+ strip.push_back(&(*v));
+ }
+ else {
+ end = true;
+ }
+ if ((!strip.empty()) && (strip.size() > 1)) {
+ _strips.push_back(new Strip(strip, _stroke->hasTips(), first, end));
+ strip.clear();
+ }
+ first = false;
+ }
+}
+
+void StrokeRep::Render(const StrokeRenderer *iRenderer)
+{
+ iRenderer->RenderStrokeRep(this);
+}
diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.h b/source/blender/freestyle/intern/stroke/StrokeRep.h
new file mode 100644
index 00000000000..419659d1427
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeRep.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_STROKE_REP_H__
+#define __FREESTYLE_STROKE_REP_H__
+
+/** \file blender/freestyle/intern/stroke/StrokeRep.h
+ * \ingroup freestyle
+ * \brief Class to define the representation of a stroke (for display purpose)
+ * \author Stephane Grabli
+ * \date 05/03/2003
+ */
+
+#include "Stroke.h"
+
+#include "../geometry/Geom.h"
+
+using namespace Geometry;
+
+#if 0
+//symbolic constant to call the appropriate renderers and textures
+#define NO_TEXTURE_WITH_BLEND_STROKE -2
+#define NO_TEXTURE_STROKE -1
+#define PSEUDO_CHARCOAL_STROKE 0
+#define WASH_BRUSH_STROKE 1
+#define OIL_STROKE 2
+#define NO_BLEND_STROKE 3
+#define CHARCOAL_MIN_STROKE 4
+#define BRUSH_MIN_STROKE 5
+#define OPAQUE_DRY_STROKE 6
+#define OPAQUE_STROKE 7
+
+#define DEFAULT_STROKE 0
+
+#define NUMBER_STROKE_RENDERER 8
+
+#endif
+
+class StrokeVertexRep
+{
+public:
+ StrokeVertexRep() {}
+
+ StrokeVertexRep(const Vec2r& iPoint2d)
+ {
+ _point2d = iPoint2d;
+ }
+
+ StrokeVertexRep(const StrokeVertexRep& iBrother);
+
+ virtual ~StrokeVertexRep() {}
+
+ inline Vec2r& point2d()
+ {
+ return _point2d;
+ }
+
+ inline Vec2r& texCoord()
+ {
+ return _texCoord;
+ }
+
+ inline Vec3r& color()
+ {
+ return _color;
+ }
+
+ inline float alpha()
+ {
+ return _alpha;
+ }
+
+ inline void setPoint2d(const Vec2r& p)
+ {
+ _point2d = p;
+ }
+
+ inline void setTexCoord(const Vec2r& p)
+ {
+ _texCoord = p;
+ }
+
+ inline void setColor(const Vec3r& p)
+ {
+ _color = p;
+ }
+
+ inline void setAlpha(float a)
+ {
+ _alpha = a;
+ }
+
+protected:
+ Vec2r _point2d;
+ Vec2r _texCoord;
+ Vec3r _color;
+ float _alpha;
+};
+
+class Strip
+{
+public:
+ typedef std::vector<StrokeVertexRep*> vertex_container;
+
+protected:
+ vertex_container _vertices;
+ float _averageThickness;
+
+public:
+ Strip(const std::vector<StrokeVertex*>& iStrokeVertices, bool hasTips = false,
+ bool tipBegin = false, bool tipEnd = false);
+ Strip(const Strip& iBrother);
+ virtual ~Strip();
+
+protected:
+ void createStrip(const std::vector<StrokeVertex*>& iStrokeVertices);
+ void cleanUpSingularities(const std::vector<StrokeVertex*>& iStrokeVertices);
+ void computeTexCoord (const std::vector<StrokeVertex*>& iStrokeVertices);
+ void computeTexCoordWithTips (const std::vector<StrokeVertex*>& iStrokeVertices, bool tipBegin, bool tipEnd);
+
+public:
+ inline int sizeStrip() const
+ {
+ return _vertices.size();
+ }
+
+ inline vertex_container& vertices()
+ {
+ return _vertices;
+ }
+};
+
+class StrokeRep
+{
+protected:
+ Stroke *_stroke;
+ vector<Strip*> _strips;
+ Stroke::MediumType _strokeType;
+ unsigned int _textureId;
+
+ // float _averageTextureAlpha;
+
+public:
+ StrokeRep();
+ StrokeRep(const StrokeRep&);
+ StrokeRep(Stroke *iStroke);
+ virtual ~StrokeRep();
+
+ /*! Creates the strips */
+ virtual void create();
+
+ /*! Renders the stroke using a Renderer */
+ virtual void Render(const StrokeRenderer *iRenderer);
+
+ /*! accessors */
+ inline Stroke::MediumType getMediumType() const
+ {
+ return _strokeType;
+ }
+
+ inline unsigned getTextureId() const
+ {
+ return _textureId;
+ }
+
+ inline vector<Strip*>& getStrips()
+ {
+ return _strips;
+ }
+
+ inline unsigned int getNumberOfStrips() const
+ {
+ return _strips.size();
+ }
+
+ inline Stroke *getStroke()
+ {
+ return _stroke;
+ }
+
+ /*! modifiers */
+ inline void setMediumType(Stroke::MediumType itype)
+ {
+ _strokeType = itype;
+ }
+
+ inline void setTextureId(unsigned textureId)
+ {
+ _textureId = textureId;
+ }
+};
+
+#endif // __FREESTYLE_STROKE_REP_H__
diff --git a/source/blender/freestyle/intern/stroke/StrokeShader.h b/source/blender/freestyle/intern/stroke/StrokeShader.h
new file mode 100644
index 00000000000..c8364f7a737
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeShader.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_STROKE_SHADERS_H__
+#define __FREESTYLE_STROKE_SHADERS_H__
+
+/** \file blender/freestyle/intern/stroke/StrokeShader.h
+ * \ingroup freestyle
+ * \brief Class defining StrokeShader
+ * \author Stephane Grabli
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+#include <iostream>
+#include <vector>
+
+#include "../python/Director.h"
+
+//
+// StrokeShader base class
+//
+//////////////////////////////////////////////////////
+
+class Stroke;
+
+/*! Base class for Stroke Shaders.
+ * Any Stroke Shader must inherit from this class and overload the shade() method.
+ * A StrokeShader is designed to modify any Stroke's attribute such as Thickness, Color,
+ * Geometry, Texture, Blending mode...
+ * The basic way to achieve this operation consists in iterating over the StrokeVertices of the Stroke
+ * and to modify each one's StrokeAttribute.
+ * Here is a python code example of such an iteration:
+ * \code
+ * it = ioStroke.strokeVerticesBegin()
+ * while not it.isEnd():
+ * att = it.getObject().attribute()
+ * ## perform here any attribute modification
+ * it.increment()
+ * \endcode
+ * Here is a C++ code example of such an iteration:
+ * \code
+ * for(StrokeInternal::StrokeVertexIterator v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd();
+ * v != vend;
+ * ++v)
+ * {
+ * StrokeAttribute& att = v->attribute();
+ * // perform any attribute modification here...
+ * }
+ * \endcode
+ */
+class LIB_STROKE_EXPORT StrokeShader
+{
+public:
+ PyObject *py_ss;
+
+ /*! Default constructor. */
+ StrokeShader()
+ {
+ py_ss = 0;
+ }
+
+ /*! Destructor. */
+ virtual ~StrokeShader() {}
+
+ /*! Returns the string corresponding to the shader's name. */
+ virtual string getName() const
+ {
+ return "StrokeShader";
+ }
+
+ /*! The shading method. This method must be overloaded by inherited classes.
+ * \param ioStroke
+ * The stroke we wish to shade. this Stroke is modified by the Shader (which typically
+ * modifies the Stroke's attribute's values such as Color, Thickness, Geometry...)
+ */
+ virtual int shade(Stroke& ioStroke) const
+ {
+ return Director_BPy_StrokeShader_shade( const_cast<StrokeShader *>(this), ioStroke);
+ }
+};
+
+#endif // __FREESTYLE_STROKE_SHADERS_H__
diff --git a/source/blender/freestyle/intern/stroke/StrokeTesselator.cpp b/source/blender/freestyle/intern/stroke/StrokeTesselator.cpp
new file mode 100644
index 00000000000..b6805e4220d
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeTesselator.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/stroke/StrokeTesselator.cpp
+ * \ingroup freestyle
+ * \brief Class to build a Node Tree designed to be displayed from a set of strokes structure.
+ * \author Stephane Grabli
+ * \date 26/03/2002
+ */
+
+#include "StrokeAdvancedIterators.h"
+#include "StrokeTesselator.h"
+
+#include "../scene_graph/OrientedLineRep.h"
+#include "../scene_graph/NodeGroup.h"
+#include "../scene_graph/NodeShape.h"
+
+LineRep *StrokeTesselator::Tesselate(Stroke *iStroke)
+{
+ if (0 == iStroke)
+ return 0;
+
+ LineRep *line;
+ line = new OrientedLineRep();
+
+ Stroke::vertex_iterator v, vend;
+ if (2 == iStroke->vertices_size()) {
+ line->setStyle(LineRep::LINES);
+ v = iStroke->vertices_begin();
+ StrokeVertex *svA = (*v);
+ v++;
+ StrokeVertex *svB = (*v);
+ Vec3r A((*svA)[0], (*svA)[1], 0);
+ Vec3r B((*svB)[0], (*svB)[1], 0);
+ line->AddVertex(A);
+ line->AddVertex(B);
+ }
+ else {
+ if (_overloadFrsMaterial)
+ line->setFrsMaterial(_FrsMaterial);
+
+ line->setStyle(LineRep::LINE_STRIP);
+
+ for (v = iStroke->vertices_begin(), vend = iStroke->vertices_end(); v != vend; v++) {
+ StrokeVertex *sv = (*v);
+ Vec3r V((*sv)[0], (*sv)[1], 0);
+ line->AddVertex(V);
+ }
+ }
+ line->setId(iStroke->getId());
+ line->ComputeBBox();
+
+ return line;
+}
+
+template<class StrokeVertexIterator>
+NodeGroup *StrokeTesselator::Tesselate(StrokeVertexIterator begin, StrokeVertexIterator end)
+{
+ NodeGroup *group = new NodeGroup;
+ NodeShape *tshape = new NodeShape;
+ group->AddChild(tshape);
+ //tshape->material().setDiffuse(0.0f, 0.0f, 0.0f, 1.0f);
+ tshape->setFrsMaterial(_FrsMaterial);
+
+ for (StrokeVertexIterator c = begin, cend = end; c != cend; c++) {
+ tshape->AddRep(Tesselate((*c)));
+ }
+
+ return group;
+}
diff --git a/source/blender/freestyle/intern/stroke/StrokeTesselator.h b/source/blender/freestyle/intern/stroke/StrokeTesselator.h
new file mode 100644
index 00000000000..e04f75a6f3e
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeTesselator.h
@@ -0,0 +1,78 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_STROKE_TESSELATOR_H__
+#define __FREESTYLE_STROKE_TESSELATOR_H__
+
+/** \file blender/freestyle/intern/stroke/StrokeTesselator.h
+ * \ingroup freestyle
+ * \brief Class to build a Node Tree designed to be displayed from a set of strokes structure.
+ * \author Stephane Grabli
+ * \date 26/03/2002
+ */
+
+#include "Stroke.h"
+
+#include "../scene_graph/LineRep.h"
+
+class StrokeTesselator
+{
+public:
+ inline StrokeTesselator()
+ {
+ _FrsMaterial.setDiffuse(0, 0, 0, 1);
+ _overloadFrsMaterial = false;
+ }
+
+ virtual ~StrokeTesselator() {}
+
+ /*! Builds a line rep contained from a Stroke */
+ LineRep *Tesselate(Stroke *iStroke);
+
+ /*! Builds a set of lines rep contained under a a NodeShape, itself contained under a NodeGroup
+ * from a set of strokes.
+ */
+ template<class StrokeIterator>
+ NodeGroup *Tesselate(StrokeIterator begin, StrokeIterator end);
+
+ inline void setFrsMaterial(const FrsMaterial& iMaterial)
+ {
+ _FrsMaterial = iMaterial;
+ _overloadFrsMaterial = true;
+ }
+
+ inline const FrsMaterial& frs_material() const
+ {
+ return _FrsMaterial;
+ }
+
+private:
+ FrsMaterial _FrsMaterial;
+ bool _overloadFrsMaterial;
+};
+
+#endif // __FREESTYLE_STROKE_TESSELATOR_H__
diff --git a/source/blender/freestyle/intern/stroke/StyleModule.h b/source/blender/freestyle/intern/stroke/StyleModule.h
new file mode 100644
index 00000000000..3d053f9b4e1
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StyleModule.h
@@ -0,0 +1,186 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_STYLE_MODULE_H__
+#define __FREESTYLE_STYLE_MODULE_H__
+
+/** \file blender/freestyle/intern/stroke/StyleModule.h
+ * \ingroup freestyle
+ * \brief Class representing a style module
+ * \author Stephane Grabli
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+#include <iostream>
+#include <string>
+
+#include "Operators.h"
+#include "StrokeLayer.h"
+#include "StrokeShader.h"
+
+#include "../system/Interpreter.h"
+#include "../system/StringUtils.h"
+
+using namespace std;
+
+class StyleModule
+{
+public:
+ StyleModule(const string& file_name, Interpreter *inter) : _file_name(file_name)
+ {
+ _always_refresh = false;
+ _causal = false;
+ _drawable = true;
+ _modified = true;
+ _displayed = true;
+ _inter = inter;
+ }
+
+ virtual ~StyleModule() {}
+
+ StrokeLayer *execute()
+ {
+ if (!_inter) {
+ cerr << "Error: no interpreter was found to execute the script" << endl;
+ return NULL;
+ }
+
+ if (!_drawable) {
+ cerr << "Error: not drawable" << endl;
+ return NULL;
+ }
+
+ Operators::reset();
+
+ if (interpret()) {
+ cerr << "Error: interpretation failed" << endl;
+ Operators::reset();
+ return NULL;
+ }
+
+ Operators::StrokesContainer *strokes_set = Operators::getStrokesSet();
+ if (strokes_set->empty()) {
+ cerr << "Error: strokes set empty" << endl;
+ Operators::reset();
+ return NULL;
+ }
+
+ StrokeLayer *sl = new StrokeLayer;
+ for (Operators::StrokesContainer::iterator it = strokes_set->begin(); it != strokes_set->end(); ++it)
+ sl->AddStroke(*it);
+
+ Operators::reset();
+ return sl;
+ }
+
+ virtual void close() {}
+
+protected:
+ virtual int interpret()
+ {
+ return _inter->interpretFile(_file_name);
+ }
+
+public:
+ // accessors
+ const string getFileName() const
+ {
+ return _file_name;
+ }
+
+ bool getAlwaysRefresh() const
+ {
+ return _always_refresh;
+ }
+
+ bool getCausal() const
+ {
+ return _causal;
+ }
+
+ bool getDrawable() const
+ {
+ return _drawable;
+ }
+
+ bool getModified() const
+ {
+ return _modified;
+ }
+
+ bool getDisplayed() const
+ {
+ return _displayed;
+ }
+
+ // modifiers
+ void setFileName(const string& file_name)
+ {
+ _file_name = file_name;
+ }
+
+ void setAlwaysRefresh(bool b = true)
+ {
+ _always_refresh = b;
+ }
+
+ void setCausal(bool b = true)
+ {
+ _causal = b;
+ }
+
+ void setDrawable(bool b = true)
+ {
+ _drawable = b;
+ }
+
+ void setModified(bool b = true)
+ {
+ if (_always_refresh)
+ return;
+ _modified = b;
+ }
+
+ void setDisplayed(bool b = true)
+ {
+ _displayed = b;
+ }
+
+private:
+ string _file_name;
+ bool _always_refresh;
+ bool _causal;
+ bool _drawable;
+ bool _modified;
+ bool _displayed;
+
+protected:
+ Interpreter *_inter;
+};
+
+#endif // __FREESTYLE_STYLE_MODULE_H__
diff --git a/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp
new file mode 100644
index 00000000000..37583660dd2
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp
@@ -0,0 +1,79 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+# include "TextStrokeRenderer.h"
+# include "Canvas.h"
+# include "StrokeIterators.h"
+
+TextStrokeRenderer::TextStrokeRenderer(const char *iFileName)
+:StrokeRenderer()
+{
+ if (!iFileName)
+ iFileName = "freestyle.txt";
+ // open the stream:
+ _ofstream.open(iFileName, ios::out);
+ if (!_ofstream.is_open()) {
+ cerr << "couldn't open the output file " << iFileName << endl;
+ }
+ _ofstream << "%!FREESTYLE" << endl;
+ _ofstream << "%Creator: Freestyle (http://artis.imag.fr/Software/Freestyle)" << endl;
+ // Bounding box
+ _ofstream << 0 << " "<< 0 << " " << Canvas::getInstance()->width() << " " << Canvas::getInstance()->height() <<
+ endl;
+ _ofstream << "%u x y z tleft tright r g b ..." << endl;
+}
+
+TextStrokeRenderer::~TextStrokeRenderer()
+{
+ Close();
+}
+
+void TextStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
+{
+ RenderStrokeRepBasic(iStrokeRep);
+}
+
+void TextStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
+{
+ Stroke *stroke = iStrokeRep->getStroke();
+ if (!stroke) {
+ cerr << "no stroke associated with Rep" << endl;
+ return;
+ }
+
+ StrokeInternal::StrokeVertexIterator v = stroke->strokeVerticesBegin();
+ StrokeAttribute att;
+ while (!v.isEnd()) {
+ att = v->attribute();
+ _ofstream << v->u() << " " << v->getProjectedX() << " " << v->getProjectedY() << " " << v->getProjectedZ() <<
+ " " << att.getThicknessL() << " " << att.getThicknessR() << " " <<
+ att.getColorR() << " " << att.getColorG() << " " << att.getColorB() << " ";
+ ++v;
+ }
+ _ofstream << endl;
+}
+
+void TextStrokeRenderer::Close()
+{
+ if (_ofstream.is_open())
+ _ofstream.close();
+}
+
diff --git a/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h
new file mode 100644
index 00000000000..144724f26f8
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h
@@ -0,0 +1,68 @@
+//
+// Filename : TextStrokeRenderer.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define the text rendering of a stroke
+// Format:
+// x y width height // bbox
+// //list of vertices :
+// t x y z t1 t2 r g b alpha ...
+// ...
+// Date of creation : 01/14/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TEXTSTROKERENDERER_H
+# define TEXTSTROKERENDERER_H
+
+# include "StrokeRenderer.h"
+# include "../system/FreestyleConfig.h"
+# include <fstream>
+
+/**********************************/
+/* */
+/* */
+/* TextStrokeRenderer */
+/* */
+/* */
+/**********************************/
+
+class LIB_STROKE_EXPORT TextStrokeRenderer : public StrokeRenderer
+{
+public:
+ TextStrokeRenderer(const char *iFileName = NULL);
+ virtual ~TextStrokeRenderer();
+
+ /*! Renders a stroke rep */
+ virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const;
+ virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const;
+
+ /*! Closes the output file */
+ void Close();
+
+protected:
+ mutable ofstream _ofstream;
+};
+
+#endif // TEXTSTROKERENDERER_H
+
diff --git a/source/blender/freestyle/intern/system/BaseIterator.h b/source/blender/freestyle/intern/system/BaseIterator.h
new file mode 100644
index 00000000000..836f6c83eb8
--- /dev/null
+++ b/source/blender/freestyle/intern/system/BaseIterator.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_BASE_ITERATOR_H__
+#define __FREESTYLE_BASE_ITERATOR_H__
+
+/** \file blender/freestyle/intern/system/BaseIterator.h
+ * \ingroup freestyle
+ * \brief Classes defining the basic "Iterator" design pattern
+ * \author Stephane Grabli
+ * \date 18/03/2003
+ */
+
+#include <iterator>
+
+// use for iterators defintions
+template <class Element>
+class Nonconst_traits;
+
+template <class Element>
+class Const_traits
+{
+public:
+ typedef Element value_type;
+ typedef const Element& reference;
+ typedef const Element *pointer;
+ typedef ptrdiff_t difference_type;
+ typedef Nonconst_traits<Element> Non_const_traits;
+};
+
+template <class Element>
+class Nonconst_traits
+{
+public:
+ typedef Element value_type;
+ typedef Element& reference;
+ typedef Element *pointer;
+ typedef ptrdiff_t difference_type;
+ typedef Nonconst_traits<Element> Non_const_traits;
+};
+
+class InputIteratorTag_Traits
+{
+public:
+ typedef std::input_iterator_tag iterator_category;
+};
+
+class BidirectionalIteratorTag_Traits
+{
+public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+};
+
+template<class Traits, class IteratorTagTraits>
+class IteratorBase
+{
+public:
+ virtual ~IteratorBase() {}
+
+ virtual bool begin() const = 0;
+ virtual bool end() const = 0;
+
+ typedef typename IteratorTagTraits::iterator_category iterator_category;
+ typedef typename Traits::value_type value_type;
+ typedef typename Traits::difference_type difference_type;
+ typedef typename Traits::pointer pointer;
+ typedef typename Traits::reference reference;
+
+protected:
+ IteratorBase() {}
+};
+
+#endif // BASEITERATOR_H
diff --git a/source/blender/freestyle/intern/system/BaseObject.cpp b/source/blender/freestyle/intern/system/BaseObject.cpp
new file mode 100644
index 00000000000..2088585c33b
--- /dev/null
+++ b/source/blender/freestyle/intern/system/BaseObject.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/system/BaseObject.cpp
+ * \ingroup freestyle
+ * \brief Base Class for most shared objects (Node, Rep). Defines the addRef, release system.
+ * \brief Inspired by COM IUnknown system.
+ * \author Stephane Grabli
+ * \date 06/02/2002
+ */
+
+#include "BaseObject.h"
diff --git a/source/blender/freestyle/intern/system/BaseObject.h b/source/blender/freestyle/intern/system/BaseObject.h
new file mode 100644
index 00000000000..1fe2770c313
--- /dev/null
+++ b/source/blender/freestyle/intern/system/BaseObject.h
@@ -0,0 +1,77 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_BASE_OBJECT_H__
+#define __FREESTYLE_BASE_OBJECT_H__
+
+/** \file blender/freestyle/intern/system/BaseObject.h
+ * \ingroup freestyle
+ * \brief Base Class for most shared objects (Node, Rep). Defines the addRef, release system.
+ * \brief Inspired by COM IUnknown system.
+ * \author Stephane Grabli
+ * \date 06/02/2002
+ */
+
+#include "FreestyleConfig.h"
+
+class LIB_SYSTEM_EXPORT BaseObject
+{
+public:
+ inline BaseObject()
+ {
+ _ref_counter = 0;
+ }
+
+ virtual ~BaseObject() {}
+
+ /*! At least makes a release on this.
+ * The BaseObject::destroy method must be explicitely called at the end of any overloaded destroy
+ */
+ virtual int destroy()
+ {
+ return release();
+ }
+
+ /*! Increments the reference counter */
+ inline int addRef()
+ {
+ return ++_ref_counter;
+ }
+
+ /*! Decrements the reference counter */
+ inline int release()
+ {
+ if (_ref_counter)
+ _ref_counter--;
+ return _ref_counter;
+ }
+
+private:
+ unsigned _ref_counter;
+};
+
+#endif // __FREESTYLE_BASE_OBJECT_H__
diff --git a/source/blender/freestyle/intern/system/Cast.h b/source/blender/freestyle/intern/system/Cast.h
new file mode 100644
index 00000000000..02dd5699214
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Cast.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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_CAST_H__
+#define __FREESTYLE_CAST_H__
+
+/** \file blender/freestyle/intern/system/Cast.h
+ * \ingroup freestyle
+ * \brief Cast function
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+namespace Cast
+{
+ template <class T, class U>
+ U *cast(T *in)
+ {
+ if (!in)
+ return NULL;
+ return dynamic_cast<U*>(in);
+ }
+} // end of namespace Cast
+
+#endif // __FREESTYLE_CAST_H__
diff --git a/source/blender/freestyle/intern/system/Exception.cpp b/source/blender/freestyle/intern/system/Exception.cpp
new file mode 100644
index 00000000000..7c7c16fdf40
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Exception.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/system/Exception.cpp
+ * \ingroup freestyle
+ * \brief Singleton to manage exceptions
+ * \author Stephane Grabli
+ * \date 10/01/2003
+ */
+
+#include "Exception.h"
+
+Exception::exception_type Exception::_exception = Exception::NO_EXCEPTION;
diff --git a/source/blender/freestyle/intern/system/Exception.h b/source/blender/freestyle/intern/system/Exception.h
new file mode 100644
index 00000000000..b9bfa00cf97
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Exception.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_EXCEPTION_H__
+#define __FREESTYLE_EXCEPTION_H__
+
+/** \file blender/freestyle/intern/system/Exception.h
+ * \ingroup freestyle
+ * \brief Singleton to manage exceptions
+ * \author Stephane Grabli
+ * \date 10/01/2003
+ */
+
+#include "FreestyleConfig.h"
+
+class LIB_SYSTEM_EXPORT Exception
+{
+public:
+ typedef enum {
+ NO_EXCEPTION,
+ UNDEFINED,
+ } exception_type;
+
+ static int getException()
+ {
+ exception_type e = _exception;
+ _exception = NO_EXCEPTION;
+ return e;
+ }
+
+ static int raiseException(exception_type exception = UNDEFINED)
+ {
+ _exception = exception;
+ return _exception;
+ }
+
+ static void reset()
+ {
+ _exception = NO_EXCEPTION;
+ }
+
+private:
+ static exception_type _exception;
+};
+
+#endif // __FREESTYLE_EXCEPTION_H__
diff --git a/source/blender/freestyle/intern/system/FreestyleConfig.h b/source/blender/freestyle/intern/system/FreestyleConfig.h
new file mode 100644
index 00000000000..7c79caa5259
--- /dev/null
+++ b/source/blender/freestyle/intern/system/FreestyleConfig.h
@@ -0,0 +1,96 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_CONFIG_H__
+#define __FREESTYLE_CONFIG_H__
+
+/** \file blender/freestyle/intern/system/FreestyleConfig.h
+ * \ingroup freestyle
+ * \brief Configuration definitions
+ * \author Emmanuel Turquin
+ * \date 25/02/2003
+ */
+
+#include <string>
+
+#include "BLI_math.h"
+
+using namespace std;
+
+namespace Config {
+
+// Directory separators
+// TODO Use Blender's stuff for such things!
+#ifdef WIN32
+ static const string DIR_SEP("\\");
+ static const string PATH_SEP(";");
+#else
+ static const string DIR_SEP("/");
+ static const string PATH_SEP(":");
+#endif // WIN32
+
+// DLL import/export macros for Win32
+
+#ifndef LIB_SYSTEM_EXPORT
+# define LIB_SYSTEM_EXPORT
+#endif // LIB_SYSTEM_EXPORT
+
+#ifndef LIB_IMAGE_EXPORT
+# define LIB_IMAGE_EXPORT
+#endif // LIB_IMAGE_EXPORT
+
+#ifndef LIB_GEOMETRY_EXPORT
+# define LIB_GEOMETRY_EXPORT
+#endif // LIB_GEOMETRY_EXPORT
+
+#ifndef LIB_SCENE_GRAPH_EXPORT
+# define LIB_SCENE_GRAPH_EXPORT
+#endif // LIB_SCENE_GRAPH_EXPORT
+
+#ifndef LIB_WINGED_EDGE_EXPORT
+# define LIB_WINGED_EDGE_EXPORT
+#endif // LIB_WINGED_EDGE_EXPORT
+
+#ifndef LIB_VIEW_MAP_EXPORT
+# define LIB_VIEW_MAP_EXPORT
+#endif // LIB_VIEW_MAP_EXPORT
+
+#ifndef LIB_STROKE_EXPORT
+# define LIB_STROKE_EXPORT
+#endif // LIB_STROKE_EXPORT
+
+#ifndef LIB_RENDERING_EXPORT
+# define LIB_RENDERING_EXPORT
+#endif // LIB_RENDERING_EXPORT
+
+#ifndef LIB_WRAPPER_EXPORT
+# define LIB_WRAPPER_EXPORT
+#endif // LIB_WRAPPER_EXPORT
+
+} // end of namespace Config
+
+#endif // __FREESTYLE_CONFIG_H__
diff --git a/source/blender/freestyle/intern/system/Id.h b/source/blender/freestyle/intern/system/Id.h
new file mode 100644
index 00000000000..d6e39bff167
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Id.h
@@ -0,0 +1,142 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_ID_H__
+#define __FREESTYLE_ID_H__
+
+/** \file blender/freestyle/intern/system/Id.h
+ * \ingroup freestyle
+ * \brief Identification system
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+/*! Class used to tag any object by an id.
+ * It is made of two unsigned integers.
+ */
+class Id
+{
+public:
+ typedef unsigned id_type;
+
+ /*! Default constructor */
+ Id()
+ {
+ _first = 0;
+ _second = 0;
+ }
+
+ /*! Builds an Id from an integer.
+ * The second number is set to 0.
+ */
+ Id(id_type id)
+ {
+ _first = id;
+ _second = 0;
+ }
+
+ /*! Builds the Id from the two numbers */
+ Id(id_type ifirst, id_type isecond)
+ {
+ _first = ifirst;
+ _second = isecond;
+ }
+
+ /*! Copy constructor */
+ Id(const Id& iBrother)
+ {
+ _first = iBrother._first;
+ _second = iBrother._second;
+ }
+
+ /*! Operator= */
+ Id& operator=(const Id& iBrother)
+ {
+ _first = iBrother._first;
+ _second = iBrother._second;
+ return *this;
+ }
+
+ /*! Returns the first Id number */
+ id_type getFirst() const
+ {
+ return _first;
+ }
+
+ /*! Returns the second Id number */
+ id_type getSecond() const
+ {
+ return _second;
+ }
+
+ /*! Sets the first number constituing the Id */
+ void setFirst(id_type first)
+ {
+ _first = first;
+ }
+
+ /*! Sets the second number constituing the Id */
+ void setSecond(id_type second)
+ {
+ _second = second;
+ }
+
+ /*! Operator== */
+ bool operator==(const Id& id) const
+ {
+ return ((_first == id._first) && (_second == id._second));
+ }
+
+ /*! Operator!= */
+ bool operator!=(const Id& id) const
+ {
+ return !((*this) == id);
+ }
+
+ /*! Operator< */
+ bool operator<(const Id& id) const
+ {
+ if (_first < id._first)
+ return true;
+ if (_first == id._first && _second < id._second)
+ return true;
+ return false;
+ }
+
+private:
+ id_type _first;
+ id_type _second;
+};
+
+// stream operator
+inline std::ostream& operator<<(std::ostream& s, const Id& id)
+{
+ s << "[" << id.getFirst() << ", " << id.getSecond() << "]";
+ return s;
+}
+
+# endif // __FREESTYLE_ID_H__
diff --git a/source/blender/freestyle/intern/system/Interpreter.h b/source/blender/freestyle/intern/system/Interpreter.h
new file mode 100644
index 00000000000..7928db9aed2
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Interpreter.h
@@ -0,0 +1,65 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_INTERPRETER_H__
+#define __FREESTYLE_INTERPRETER_H__
+
+/** \file blender/freestyle/intern/system/Interpreter.h
+ * \ingroup freestyle
+ * \brief Base Class of all script interpreters
+ * \author Emmanuel Turquin
+ * \date 17/04/2003
+ */
+
+#include <string>
+
+using namespace std;
+
+class LIB_SYSTEM_EXPORT Interpreter
+{
+public:
+ Interpreter()
+ {
+ _language = "Unknown";
+ }
+
+ virtual ~Interpreter() {}; //soc
+
+ virtual int interpretFile(const string& filename) = 0;
+
+ virtual string getLanguage() const
+ {
+ return _language;
+ }
+
+ virtual void reset() = 0;
+
+protected:
+ string _language;
+};
+
+#endif // __FREESTYLE_INTERPRETER_H__
diff --git a/source/gameengine/Physics/common/PHY_IController.cpp b/source/blender/freestyle/intern/system/Iterator.cpp
index 8568ffa74e6..2e89880b3d7 100644
--- a/source/gameengine/Physics/common/PHY_IController.cpp
+++ b/source/blender/freestyle/intern/system/Iterator.cpp
@@ -15,7 +15,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
* All rights reserved.
*
* The Original Code is: all of this file.
@@ -25,14 +25,8 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file gameengine/Physics/common/PHY_IController.cpp
- * \ingroup phys
+/** \file blender/freestyle/intern/system/Iterator.cpp
+ * \ingroup freestyle
*/
-#include "PHY_IController.h"
-
-PHY_IController::~PHY_IController()
-{
-
-}
-
+#include "Iterator.h"
diff --git a/source/blender/freestyle/intern/system/Iterator.h b/source/blender/freestyle/intern/system/Iterator.h
new file mode 100644
index 00000000000..9cd0f16275b
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Iterator.h
@@ -0,0 +1,75 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_ITERATOR_H__
+#define __FREESTYLE_ITERATOR_H__
+
+/** \file blender/freestyle/intern/system/Iterator.h
+ * \ingroup freestyle
+ */
+
+#include <iostream>
+#include <string>
+
+using namespace std;
+
+class Iterator
+{
+public:
+ virtual ~Iterator() {}
+
+ virtual string getExactTypeName() const
+ {
+ return "Iterator";
+ }
+
+ virtual int increment()
+ {
+ cerr << "Warning: increment() not implemented" << endl;
+ return 0;
+ }
+
+ virtual int decrement()
+ {
+ cerr << "Warning: decrement() not implemented" << endl;
+ return 0;
+ }
+
+ virtual bool isBegin() const
+ {
+ cerr << "Warning: isBegin() not implemented" << endl;
+ return false;
+ }
+
+ virtual bool isEnd() const
+ {
+ cerr << "Warning: isEnd() not implemented" << endl;
+ return false;
+ }
+};
+
+#endif // __FREESTYLE_ITERATOR_H__
diff --git a/source/blender/freestyle/intern/system/PointerSequence.h b/source/blender/freestyle/intern/system/PointerSequence.h
new file mode 100644
index 00000000000..c97f4516d00
--- /dev/null
+++ b/source/blender/freestyle/intern/system/PointerSequence.h
@@ -0,0 +1,96 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_POINTER_SEQUENCE_H__
+#define __FREESTYLE_POINTER_SEQUENCE_H__
+
+/** \file blender/freestyle/intern/system/PointerSequence.h
+ * \ingroup freestyle
+ * \brief Simple RAII wrappers for std:: sequential containers
+ * \author 22/11/2010
+ * \date 18/03/2003
+ *
+ * PointerSequence
+ *
+ * Produces a wrapped version of a sequence type (std::vector, std::deque, std::list) that will take ownership of
+ * pointers tht it stores. Those pointers will be deleted in its destructor.
+ *
+ * Because the contained pointers are wholly owned by the sequence, you cannot make a copy of the sequence.
+ * Making a copy would result in a double free.
+ *
+ * This is a no-frills class that provides no additional facilities. The user is responsible for managing any
+ * pointers that are removed from the list, and for making sure that any pointers contained in the class are not
+ * deleted elsewhere. Because this class does no reference counting, the user must also make sure that any pointer
+ * appears only once in the sequence.
+ *
+ * If more sophisticated facilities are needed, use tr1::shared_ptr or boost::shared_ptr.
+ * This class is only intended to allow one to eke by in projects where tr1 or boost are not available.
+ *
+ * Usage: The template takes two parameters, the standard container, and the class held in the container. This is a
+ * limitation of C++ templates, where T::iterator is not a type when T is a template parameter. If anyone knows a way
+ * around this limitation, then the second parameter can be eliminated.
+ *
+ * Example:
+ * PointerSequence<vector<Widget*>, Widget*> v;
+ * v.push_back(new Widget);
+ * cout << v[0] << endl; // operator[] is provided by std::vector, not by PointerSequence
+ * v.destroy(); // Deletes all pointers in sequence and sets them to NULL.
+ *
+ * The idiom for removing a pointer from a sequence is:
+ * Widget* w = v[3];
+ * v.erase(v.begin() + 3); // or v[3] = 0;
+ * The user is now responsible for disposing of w properly.
+ */
+
+#include <algorithm>
+
+template <typename C, typename T>
+class PointerSequence : public C
+{
+ PointerSequence (PointerSequence& other);
+ PointerSequence& operator=(PointerSequence& other);
+
+ static void destroyer(T t)
+ {
+ delete t;
+ }
+
+public:
+ PointerSequence () {};
+
+ ~PointerSequence ()
+ {
+ destroy();
+ }
+
+ void destroy ()
+ {
+ for_each(this->begin(), this->end(), destroyer);
+ }
+};
+
+#endif // __FREESTYLE_POINTER_SEQUENCE_H__
diff --git a/source/blender/freestyle/intern/system/Precision.h b/source/blender/freestyle/intern/system/Precision.h
new file mode 100644
index 00000000000..c2a9e24e635
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Precision.h
@@ -0,0 +1,44 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_PRECISION_H__
+#define __FREESTYLE_PRECISION_H__
+
+/** \file blender/freestyle/intern/system/Precision.h
+ * \ingroup freestyle
+ * \brief Define the float precision used in the program
+ * \author Stephane Grabli
+ * \date 30/07/2002
+ */
+
+typedef double real;
+
+#ifndef SWIG
+ static const real M_EPSILON = 0.00000001;
+#endif // SWIG
+
+#endif // __FREESTYLE_PRECISION_H__
diff --git a/source/blender/freestyle/intern/system/ProgressBar.h b/source/blender/freestyle/intern/system/ProgressBar.h
new file mode 100644
index 00000000000..2837c148754
--- /dev/null
+++ b/source/blender/freestyle/intern/system/ProgressBar.h
@@ -0,0 +1,96 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_PROGRESS_BAR_H__
+#define __FREESTYLE_PROGRESS_BAR_H__
+
+/** \file blender/freestyle/intern/system/ProgressBar.h
+ * \ingroup freestyle
+ * \brief Class to encapsulate a progress bar
+ * \author Stephane Grabli
+ * \date 27/08/2002
+ */
+
+#include <string>
+
+using namespace std;
+
+class ProgressBar
+{
+public:
+ inline ProgressBar()
+ {
+ _numtotalsteps = 0;
+ _progress = 0;
+ }
+
+ virtual ~ProgressBar() {}
+
+ virtual void reset()
+ {
+ _numtotalsteps = 0;
+ _progress = 0;
+ }
+
+ virtual void setTotalSteps(unsigned n)
+ {
+ _numtotalsteps = n;
+ }
+
+ virtual void setProgress(unsigned i)
+ {
+ _progress = i;
+ }
+
+ virtual void setLabelText(const string& s)
+ {
+ _label = s;
+ }
+
+ /*! accessors */
+ inline unsigned int getTotalSteps() const
+ {
+ return _numtotalsteps;
+ }
+
+ inline unsigned int getProgress() const
+ {
+ return _progress;
+ }
+
+ inline string getLabelText() const
+ {
+ return _label;
+ }
+
+protected:
+ unsigned _numtotalsteps;
+ unsigned _progress;
+ string _label;
+};
+
+#endif // __FREESTYLE_PROGRESS_BAR_H__
diff --git a/source/blender/freestyle/intern/system/PseudoNoise.cpp b/source/blender/freestyle/intern/system/PseudoNoise.cpp
new file mode 100644
index 00000000000..27158bfd4aa
--- /dev/null
+++ b/source/blender/freestyle/intern/system/PseudoNoise.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/system/PseudoNoise.cpp
+ * \ingroup freestyle
+ * \brief Class to define a pseudo Perlin noise
+ * \author Fredo Durand
+ * \date 16/06/2003
+ */
+
+#include <math.h>
+
+#include "PseudoNoise.h"
+#include "RandGen.h"
+
+static const unsigned NB_VALUE_NOISE = 512;
+
+real *PseudoNoise::_values;
+
+PseudoNoise::PseudoNoise() {}
+
+void PseudoNoise::init(long seed)
+{
+ _values = new real[NB_VALUE_NOISE];
+ RandGen::srand48(seed);
+ for (unsigned int i = 0; i < NB_VALUE_NOISE; i++)
+ _values[i] = -1.0 + 2.0 * RandGen::drand48();
+}
+
+real PseudoNoise::linearNoise(real x)
+{
+ real tmp;
+ int i = modf(x, &tmp) * NB_VALUE_NOISE;
+ real x1 = _values[i], x2 = _values[(i + 1) % NB_VALUE_NOISE];
+ real t = modf(x * NB_VALUE_NOISE, &tmp);
+ return x1 * (1 - t) + x2 * t;
+}
+
+static real LanczosWindowed(real t)
+{
+ if (fabs(t) > 2)
+ return 0;
+ if (fabs(t) < M_EPSILON)
+ return 1.0;
+ return sin(M_PI * t) / (M_PI * t) * sin(M_PI * t / 2.0) / (M_PI * t / 2.0);
+}
+
+real PseudoNoise::smoothNoise(real x)
+{
+ real tmp;
+ int i = modf(x, &tmp) * NB_VALUE_NOISE;
+ int h = i - 1;
+ if (h < 0) {
+ h = NB_VALUE_NOISE + h;
+ }
+
+ real x1 = _values[i], x2 = _values[(i + 1) % NB_VALUE_NOISE];
+ real x0 = _values[h], x3 = _values[(i + 2) % NB_VALUE_NOISE];
+
+ real t = modf(x * NB_VALUE_NOISE, &tmp);
+ real y0 = LanczosWindowed(-1 -t);
+ real y1 = LanczosWindowed(-t);
+ real y2 = LanczosWindowed(1 - t);
+ real y3 = LanczosWindowed(2 - t);
+#if 0
+ cerr << "x0=" << x0 << " x1=" << x1 << " x2=" << x2 << " x3=" << x3 << endl;
+ cerr << "y0=" << y0 << " y1=" << y1 << " y2=" << y2 << " y3=" << y3 << " :" << endl;
+#endif
+ return (x0 * y0 + x1 * y1 + x2 * y2 + x3 * y3) / (y0 + y1 + y2 + y3);
+}
+
+real PseudoNoise::turbulenceSmooth(real x, unsigned nbOctave)
+{
+ real y = 0;
+ real k = 1.0;
+ for (unsigned int i = 0; i < nbOctave; i++) {
+ y = y + k * smoothNoise(x * k);
+ k = k / 2.0;
+ }
+ return y;
+}
+
+real PseudoNoise::turbulenceLinear(real x, unsigned nbOctave)
+{
+ real y = 0;
+ real k = 1.0;
+ for (unsigned int i = 0; i < nbOctave; i++) {
+ y = y + k * linearNoise(x * k);
+ k = k / 2.0;
+ }
+ return y;
+}
diff --git a/source/blender/freestyle/intern/system/PseudoNoise.h b/source/blender/freestyle/intern/system/PseudoNoise.h
new file mode 100644
index 00000000000..7b414ae76e5
--- /dev/null
+++ b/source/blender/freestyle/intern/system/PseudoNoise.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_PSEUDO_NOISE_H__
+#define __FREESTYLE_PSEUDO_NOISE_H__
+
+/** \file blender/freestyle/intern/system/PseudoNoise.h
+ * \ingroup freestyle
+ * \brief Class to define a pseudo Perlin noise
+ * \author Fredo Durand
+ * \date 16/06/2003
+ */
+
+#include "FreestyleConfig.h"
+#include "Precision.h"
+
+class LIB_SYSTEM_EXPORT PseudoNoise
+{
+public:
+ PseudoNoise();
+
+ virtual ~PseudoNoise() {}
+
+ real smoothNoise(real x);
+ real linearNoise(real x);
+
+ real turbulenceSmooth(real x, unsigned nbOctave = 8);
+ real turbulenceLinear(real x, unsigned nbOctave = 8);
+
+ static void init(long seed);
+
+protected:
+ static real *_values;
+};
+
+#endif // __FREESTYLE_PSEUDO_NOISE_H__
diff --git a/source/blender/freestyle/intern/system/PythonInterpreter.cpp b/source/blender/freestyle/intern/system/PythonInterpreter.cpp
new file mode 100644
index 00000000000..aa8df8f418b
--- /dev/null
+++ b/source/blender/freestyle/intern/system/PythonInterpreter.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/system/PythonInterpreter.cpp
+ * \ingroup freestyle
+ * \brief Python Interpreter
+ * \author Emmanuel Turquin
+ * \date 17/04/2003
+ */
+
+#include "PythonInterpreter.h"
+
+string PythonInterpreter::_path = "";
+bool PythonInterpreter::_initialized = false;
diff --git a/source/blender/freestyle/intern/system/PythonInterpreter.h b/source/blender/freestyle/intern/system/PythonInterpreter.h
new file mode 100644
index 00000000000..3a5e45604b6
--- /dev/null
+++ b/source/blender/freestyle/intern/system/PythonInterpreter.h
@@ -0,0 +1,198 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_PYTHON_INTERPRETER_H__
+#define __FREESTYLE_PYTHON_INTERPRETER_H__
+
+/** \file blender/freestyle/intern/system/PythonInterpreter.h
+ * \ingroup freestyle
+ * \brief Python Interpreter
+ * \author Emmanuel Turquin
+ * \date 17/04/2003
+ */
+
+#include <iostream>
+#include <Python.h>
+
+#include "StringUtils.h"
+#include "Interpreter.h"
+
+//soc
+extern "C" {
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_text_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+#include "BKE_text.h"
+
+#include "BPY_extern.h"
+
+}
+
+class LIB_SYSTEM_EXPORT PythonInterpreter : public Interpreter
+{
+public:
+ PythonInterpreter()
+ {
+ _language = "Python";
+ _context = 0;
+ //Py_Initialize();
+ }
+
+ virtual ~PythonInterpreter()
+ {
+ //Py_Finalize();
+ }
+
+ void setContext(bContext *C)
+ {
+ _context = C;
+ }
+
+ int interpretFile(const string& filename)
+ {
+ initPath();
+
+ ReportList *reports = CTX_wm_reports(_context);
+ BKE_reports_clear(reports);
+ char *fn = const_cast<char*>(filename.c_str());
+#if 0
+ int status = BPY_filepath_exec(_context, fn, reports);
+#else
+ int status;
+ Text *text = BKE_text_load(G.main, fn, G.main->name);
+ if (text) {
+ status = BPY_text_exec(_context, text, reports, false);
+ BKE_text_unlink(G.main, text);
+ BKE_libblock_free(&G.main->text, text);
+ }
+ else {
+ BKE_reportf(reports, RPT_ERROR, "Cannot open file: %s", fn);
+ status = 0;
+ }
+#endif
+
+ if (status != 1) {
+ cerr << "\nError executing Python script from PythonInterpreter::interpretFile" << endl;
+ cerr << "File: " << fn << endl;
+ cerr << "Errors: " << endl;
+ BKE_reports_print(reports, RPT_ERROR);
+ return 1;
+ }
+
+ // cleaning up
+ BKE_reports_clear(reports);
+
+ return 0;
+ }
+
+ int interpretText(struct Text *text, const string& name) {
+ initPath();
+
+ ReportList *reports = CTX_wm_reports(_context);
+
+ BKE_reports_clear(reports);
+
+ if (!BPY_text_exec(_context, text, reports, false)) {
+ cerr << "\nError executing Python script from PythonInterpreter::interpretText" << endl;
+ cerr << "Name: " << name << endl;
+ cerr << "Errors: " << endl;
+ BKE_reports_print(reports, RPT_ERROR);
+ return 1;
+ }
+
+ BKE_reports_clear(reports);
+
+ return 0;
+ }
+
+ struct Options
+ {
+ static void setPythonPath(const string& path)
+ {
+ _path = path;
+ }
+
+ static string getPythonPath()
+ {
+ return _path;
+ }
+ };
+
+ void reset()
+ {
+ Py_Finalize();
+ Py_Initialize();
+ _initialized = false;
+ }
+
+private:
+ bContext *_context;
+
+ void initPath()
+ {
+ if (_initialized)
+ return;
+
+ vector<string> pathnames;
+ StringUtils::getPathName(_path, "", pathnames);
+
+ struct Text *text = BKE_text_add(G.main, "tmp_freestyle_initpath.txt");
+ string cmd = "import sys\n";
+ txt_insert_buf(text, const_cast<char*>(cmd.c_str()));
+
+ for (vector<string>::const_iterator it = pathnames.begin(); it != pathnames.end(); ++it) {
+ if (!it->empty()) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Adding Python path: " << *it << endl;
+ }
+ cmd = "sys.path.append(r\"" + *it + "\")\n";
+ txt_insert_buf(text, const_cast<char *>(cmd.c_str()));
+ }
+ }
+
+ BPY_text_exec(_context, text, NULL, false);
+
+ // cleaning up
+ BKE_text_unlink(G.main, text);
+ BKE_libblock_free(&G.main->text, text);
+
+ //PyRun_SimpleString("from Freestyle import *");
+ _initialized = true;
+ }
+
+ static bool _initialized;
+ static string _path;
+};
+
+#endif // __FREESTYLE_PYTHON_INTERPRETER_H__
diff --git a/source/blender/freestyle/intern/system/RandGen.cpp b/source/blender/freestyle/intern/system/RandGen.cpp
new file mode 100644
index 00000000000..193df1b4239
--- /dev/null
+++ b/source/blender/freestyle/intern/system/RandGen.cpp
@@ -0,0 +1,132 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/system/RandGen.cpp
+ * \ingroup freestyle
+ * \brief Pseudo-random number generator
+ * \author Fredo Durand
+ * \date 20/05/2003
+ */
+
+#include "RandGen.h"
+
+//
+// Macro definitions
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#define N 16
+#define MASK ((unsigned)(1 << (N - 1)) + (1 << (N - 1)) - 1)
+#define X0 0x330E
+#define X1 0xABCD
+#define X2 0x1234
+#define A0 0xE66D
+#define A1 0xDEEC
+#define A2 0x5
+#define C 0xB
+#define HI_BIT (1L << (2 * N - 1))
+
+#define LOW(x) ((unsigned)(x) & MASK)
+#define HIGH(x) LOW((x) >> N)
+
+#define MUL(x, y, z) \
+ { \
+ long l = (long)(x) * (long)(y); \
+ (z)[0] = LOW(l); \
+ (z)[1] = HIGH(l); \
+ }
+
+#define CARRY(x, y) ((unsigned long)((long)(x) + (long)(y)) > MASK)
+#define ADDEQU(x, y, z) (z = CARRY(x, (y)), x = LOW(x + (y)))
+#define SET3(x, x0, x1, x2) ((x)[0] = (x0), (x)[1] = (x1), (x)[2] = (x2))
+#define SETLOW(x, y, n) SET3(x, LOW((y)[n]), LOW((y)[(n)+1]), LOW((y)[(n)+2]))
+#define SEED(x0, x1, x2) (SET3(x, x0, x1, x2), SET3(a, A0, A1, A2), c = C)
+
+#define REST(v) \
+ for (i = 0; i < 3; i++) { \
+ xsubi[i] = x[i]; \
+ x[i] = temp[i]; \
+ } \
+ return (v); \
+ (void) 0
+
+#define NEST(TYPE, f, F) \
+ TYPE f(register unsigned short *xsubi) { \
+ register int i; \
+ register TYPE v; \
+ unsigned temp[3]; \
+ for (i = 0; i < 3; i++) { \
+ temp[i] = x[i]; \
+ x[i] = LOW(xsubi[i]); \
+ } \
+ v = F(); \
+ REST(v); \
+ }
+
+static unsigned x[3] = {
+ X0,
+ X1,
+ X2
+};
+static unsigned a[3] = {
+ A0,
+ A1,
+ A2
+};
+static unsigned c = C;
+
+//
+// Methods implementation
+//
+///////////////////////////////////////////////////////////////////////////////
+
+real RandGen::drand48()
+{
+ static real two16m = 1.0 / (1L << N);
+ next();
+ return (two16m * (two16m * (two16m * x[0] + x[1]) + x[2]));
+}
+
+void RandGen::srand48(long seedval)
+{
+ SEED(X0, LOW(seedval), HIGH(seedval));
+}
+
+void RandGen::next()
+{
+ unsigned p[2], q[2], r[2], carry0, carry1;
+
+ MUL(a[0], x[0], p);
+ ADDEQU(p[0], c, carry0);
+ ADDEQU(p[1], carry0, carry1);
+ MUL(a[0], x[1], q);
+ ADDEQU(p[1], q[0], carry0);
+ MUL(a[1], x[0], r);
+ x[2] = LOW(carry0 + carry1 + CARRY(p[1], r[0]) + q[1] + r[1] + a[0] * x[2] + a[1] * x[1] + a[2] * x[0]);
+ x[1] = LOW(p[1] + r[0]);
+ x[0] = LOW(p[0]);
+}
diff --git a/source/blender/freestyle/intern/system/RandGen.h b/source/blender/freestyle/intern/system/RandGen.h
new file mode 100644
index 00000000000..914b405d7f3
--- /dev/null
+++ b/source/blender/freestyle/intern/system/RandGen.h
@@ -0,0 +1,54 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_RAND_GEN_H__
+#define __FREESTYLE_RAND_GEN_H__
+
+/** \file blender/freestyle/intern/system/RandGen.h
+ * \ingroup freestyle
+ * \brief Pseudo-random number generator
+ * \author Fredo Durand
+ * \date 20/05/2003
+ */
+
+// TODO Check whether we could replace this with BLI rand stuff...
+
+#include "FreestyleConfig.h"
+
+#include "../system/Precision.h"
+
+class LIB_SYSTEM_EXPORT RandGen
+{
+public:
+ static real drand48();
+ static void srand48(long value);
+
+private:
+ static void next();
+};
+
+#endif // __FREESTYLE_RAND_GEN_H__
diff --git a/source/blender/freestyle/intern/system/RenderMonitor.h b/source/blender/freestyle/intern/system/RenderMonitor.h
new file mode 100644
index 00000000000..6052c0abe01
--- /dev/null
+++ b/source/blender/freestyle/intern/system/RenderMonitor.h
@@ -0,0 +1,63 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_RENDER_MONITOR_H__
+#define __FREESTYLE_RENDER_MONITOR_H__
+
+/** \file blender/freestyle/intern/system/RenderMonitor.h
+ * \ingroup freestyle
+ * \brief Classes defining the basic "Iterator" design pattern
+ * \author Stephane Grabli
+ * \date 18/03/2003
+ */
+
+extern "C" {
+
+#include "render_types.h"
+
+}
+
+class RenderMonitor
+{
+public:
+ inline RenderMonitor(Render *re)
+ {
+ _re = re;
+ }
+
+ virtual ~RenderMonitor() {}
+
+ inline bool testBreak()
+ {
+ return _re && _re->test_break(_re->tbh);
+ }
+
+protected:
+ Render *_re;
+};
+
+#endif // __FREESTYLE_RENDER_MONITOR_H__
diff --git a/source/blender/freestyle/intern/system/StringUtils.cpp b/source/blender/freestyle/intern/system/StringUtils.cpp
new file mode 100644
index 00000000000..ee06d3d1f4b
--- /dev/null
+++ b/source/blender/freestyle/intern/system/StringUtils.cpp
@@ -0,0 +1,89 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/system/StringUtils.cpp
+ * \ingroup freestyle
+ * \brief String utilities
+ * \author Emmanuel Turquin
+ * \date 20/05/2003
+ */
+
+//soc #include <qfileinfo.h>
+
+#include "FreestyleConfig.h"
+#include "StringUtils.h"
+
+namespace StringUtils {
+
+void getPathName(const string& path, const string& base, vector<string>& pathnames)
+{
+ string dir;
+ string res;
+ char cleaned[FILE_MAX];
+ unsigned size = path.size();
+
+ pathnames.push_back(base);
+
+ for (unsigned int pos = 0, sep = path.find(Config::PATH_SEP, pos);
+ pos < size;
+ pos = sep + 1, sep = path.find(Config::PATH_SEP, pos))
+ {
+ if (sep == (unsigned)string::npos)
+ sep = size;
+
+ dir = path.substr(pos, sep - pos);
+
+ BLI_strncpy(cleaned, dir.c_str(), FILE_MAX);
+ BLI_cleanup_file(NULL, cleaned);
+ res = toAscii(string(cleaned));
+
+ if (!base.empty())
+ res += Config::DIR_SEP + base;
+
+ pathnames.push_back(res);
+ }
+}
+
+string toAscii(const string &str)
+{
+ stringstream out("");
+ char s;
+
+ for (unsigned int i = 0; i < str.size() ; i++) {
+ s = ((char)(str.at(i) & 0x7F));
+ out << s;
+ }
+
+ return out.str();
+}
+
+const char *toAscii(const char *str)
+{
+ return toAscii(string(str)).c_str();
+}
+
+} // end of namespace StringUtils
diff --git a/source/blender/freestyle/intern/system/StringUtils.h b/source/blender/freestyle/intern/system/StringUtils.h
new file mode 100644
index 00000000000..d8970da0dce
--- /dev/null
+++ b/source/blender/freestyle/intern/system/StringUtils.h
@@ -0,0 +1,75 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_STRING_UTILS_H__
+#define __FREESTYLE_STRING_UTILS_H__
+
+/** \file blender/freestyle/intern/system/StringUtils.h
+ * \ingroup freestyle
+ * \brief String utilities
+ * \author Emmanuel Turquin
+ * \date 20/05/2003
+ */
+
+#include <cstring>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "FreestyleConfig.h"
+
+//soc
+extern "C" {
+
+#include "BKE_utildefines.h"
+
+#include "BLI_blenlib.h"
+
+}
+
+using namespace std;
+
+namespace StringUtils {
+
+LIB_SYSTEM_EXPORT
+void getPathName(const string& path, const string& base, vector<string>& pathnames);
+string toAscii(const string &str);
+const char *toAscii(const char *str);
+
+// STL related
+struct ltstr
+{
+ bool operator()(const char *s1, const char *s2) const
+ {
+ return strcmp(s1, s2) < 0;
+ }
+};
+
+} // end of namespace StringUtils
+
+#endif // __FREESTYLE_STRING_UTILS_H__
diff --git a/source/gameengine/Physics/common/PHY_IGraphicController.cpp b/source/blender/freestyle/intern/system/TimeStamp.cpp
index 0b8f89ceed2..6a7f0b00b79 100644
--- a/source/gameengine/Physics/common/PHY_IGraphicController.cpp
+++ b/source/blender/freestyle/intern/system/TimeStamp.cpp
@@ -15,7 +15,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
* All rights reserved.
*
* The Original Code is: all of this file.
@@ -25,14 +25,14 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file gameengine/Physics/common/PHY_IGraphicController.cpp
- * \ingroup phys
+/** \file blender/freestyle/intern/system/TimeStamp.cpp
+ * \ingroup freestyle
+ * \brief Class defining a singleton used as timestamp
+ * \author Stephane Grabli
+ * \date 12/12/2002
*/
-#include "PHY_IGraphicController.h"
-
-PHY_IGraphicController::~PHY_IGraphicController()
-{
-
-}
+#include "TimeStamp.h"
+LIB_SYSTEM_EXPORT
+TimeStamp *TimeStamp::_instance = 0;
diff --git a/source/blender/freestyle/intern/system/TimeStamp.h b/source/blender/freestyle/intern/system/TimeStamp.h
new file mode 100644
index 00000000000..6f9bb3d4e44
--- /dev/null
+++ b/source/blender/freestyle/intern/system/TimeStamp.h
@@ -0,0 +1,78 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_TIME_STAMP_H__
+#define __FREESTYLE_TIME_STAMP_H__
+
+/** \file blender/freestyle/intern/system/TimeStamp.h
+ * \ingroup freestyle
+ * \brief Class defining a singleton used as timestamp
+ * \author Stephane Grabli
+ * \date 12/12/2002
+ */
+
+#include "FreestyleConfig.h"
+
+class LIB_SYSTEM_EXPORT TimeStamp
+{
+public:
+ static inline TimeStamp *instance()
+ {
+ if (_instance == NULL)
+ _instance = new TimeStamp;
+ return _instance;
+ }
+
+ inline unsigned getTimeStamp() const
+ {
+ return _time_stamp;
+ }
+
+ inline void increment()
+ {
+ ++_time_stamp;
+ }
+
+ inline void reset()
+ {
+ _time_stamp = 1;
+ }
+
+protected:
+ TimeStamp()
+ {
+ _time_stamp = 1;
+ }
+
+ TimeStamp(const TimeStamp&) {}
+
+private:
+ static TimeStamp *_instance;
+ unsigned _time_stamp;
+};
+
+#endif // __FREESTYLE_TIME_STAMP_H__
diff --git a/source/blender/freestyle/intern/system/TimeUtils.h b/source/blender/freestyle/intern/system/TimeUtils.h
new file mode 100644
index 00000000000..d42813dd560
--- /dev/null
+++ b/source/blender/freestyle/intern/system/TimeUtils.h
@@ -0,0 +1,64 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_TIME_UTILS_H__
+#define __FREESTYLE_TIME_UTILS_H__
+
+/** \file blender/freestyle/intern/system/TimeUtils.h
+ * \ingroup freestyle
+ * \brief Class to measure ellapsed time
+ * \author Stephane Grabli
+ * \date 10/04/2002
+ */
+
+#include <time.h>
+
+#include "FreestyleConfig.h"
+
+class Chronometer
+{
+public:
+ inline Chronometer() {}
+ inline ~Chronometer() {}
+
+ inline clock_t start()
+ {
+ _start = clock();
+ return _start;
+ }
+
+ inline double stop()
+ {
+ clock_t stop = clock();
+ return (double)(stop - _start) / CLOCKS_PER_SEC;
+ }
+
+private:
+ clock_t _start;
+};
+
+#endif // __FREESTYLE_TIME_UTILS_H__
diff --git a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp
new file mode 100644
index 00000000000..24cef37f381
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2011-2-5
+ */
+
+#include "ArbitraryGridDensityProvider.h"
+
+#include "BKE_global.h"
+
+ArbitraryGridDensityProvider::ArbitraryGridDensityProvider(OccluderSource& source, const real proscenium[4],
+ unsigned numCells)
+: GridDensityProvider(source), numCells(numCells)
+{
+ initialize (proscenium);
+}
+
+ArbitraryGridDensityProvider::ArbitraryGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
+ const GridHelpers::Transform& transform, unsigned numCells)
+: GridDensityProvider(source), numCells(numCells)
+{
+ real proscenium[4];
+ calculateQuickProscenium(transform, bbox, proscenium);
+
+ initialize (proscenium);
+}
+
+ArbitraryGridDensityProvider::ArbitraryGridDensityProvider(OccluderSource& source, unsigned numCells)
+: GridDensityProvider(source), numCells(numCells)
+{
+ real proscenium[4];
+ calculateOptimalProscenium(source, proscenium);
+
+ initialize (proscenium);
+}
+
+ArbitraryGridDensityProvider::~ArbitraryGridDensityProvider() {}
+
+void ArbitraryGridDensityProvider::initialize(const real proscenium[4])
+{
+ float prosceniumWidth = (proscenium[1] - proscenium[0]);
+ float prosceniumHeight = (proscenium[3] - proscenium[2]);
+ real cellArea = prosceniumWidth * prosceniumHeight / numCells;
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << prosceniumWidth << " x " << prosceniumHeight << " grid with cells of area " << cellArea << "." << endl;
+ }
+
+ _cellSize = sqrt(cellArea);
+ // Now we know how many cells make each side of our grid
+ _cellsX = ceil(prosceniumWidth / _cellSize);
+ _cellsY = ceil(prosceniumHeight / _cellSize);
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl;
+ }
+
+ // Make sure the grid exceeds the proscenium by a small amount
+ float safetyZone = 0.1f;
+ if (_cellsX * _cellSize < prosceniumWidth * (1.0 + safetyZone)) {
+ _cellsX = prosceniumWidth * (1.0 + safetyZone) / _cellSize;
+ }
+ if (_cellsY * _cellSize < prosceniumHeight * (1.0 + safetyZone)) {
+ _cellsY = prosceniumHeight * (1.0 + safetyZone) / _cellSize;
+ }
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl;
+ }
+
+ // Find grid origin
+ _cellOrigin[0] = ((proscenium[0] + proscenium[1]) / 2.0) - (_cellsX / 2.0) * _cellSize;
+ _cellOrigin[1] = ((proscenium[2] + proscenium[3]) / 2.0) - (_cellsY / 2.0) * _cellSize;
+}
+
+ArbitraryGridDensityProviderFactory::ArbitraryGridDensityProviderFactory(unsigned numCells)
+: numCells(numCells)
+{
+}
+
+ArbitraryGridDensityProviderFactory::~ArbitraryGridDensityProviderFactory() {}
+
+auto_ptr<GridDensityProvider> ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source,
+ const real proscenium[4])
+{
+ return auto_ptr<GridDensityProvider>(new ArbitraryGridDensityProvider(source, proscenium, numCells));
+}
+
+auto_ptr<GridDensityProvider>
+ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
+ const GridHelpers::Transform& transform)
+{
+ return auto_ptr<GridDensityProvider>(new ArbitraryGridDensityProvider(source, bbox, transform, numCells));
+}
+
+auto_ptr<GridDensityProvider> ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source)
+{
+ return auto_ptr<GridDensityProvider>(new ArbitraryGridDensityProvider(source, numCells));
+}
diff --git a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h
new file mode 100644
index 00000000000..f8d43f19936
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h
@@ -0,0 +1,75 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_ARBITRARY_GRID_DENSITY_PROVIDER_H__
+#define __FREESTYLE_ARBITRARY_GRID_DENSITY_PROVIDER_H__
+
+/** \file blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2011-2-5
+ */
+
+#include "GridDensityProvider.h"
+
+class ArbitraryGridDensityProvider : public GridDensityProvider
+{
+ // Disallow copying and assignment
+ ArbitraryGridDensityProvider(const ArbitraryGridDensityProvider& other);
+ ArbitraryGridDensityProvider& operator=(const ArbitraryGridDensityProvider& other);
+
+public:
+ ArbitraryGridDensityProvider(OccluderSource& source, const real proscenium[4], unsigned numCells);
+ ArbitraryGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
+ const GridHelpers::Transform& transform, unsigned numCells);
+ ArbitraryGridDensityProvider(OccluderSource& source, unsigned numCells);
+ virtual ~ArbitraryGridDensityProvider();
+
+protected:
+ unsigned numCells;
+
+private:
+ void initialize (const real proscenium[4]);
+};
+
+class ArbitraryGridDensityProviderFactory : public GridDensityProviderFactory
+{
+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);
+
+protected:
+ unsigned numCells;
+};
+
+#endif // __FREESTYLE_ARBITRARY_GRID_DENSITY_PROVIDER_H__
diff --git a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp
new file mode 100644
index 00000000000..d293ed8189f
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2011-2-9
+ */
+
+#include "AverageAreaGridDensityProvider.h"
+
+#include "BKE_global.h"
+
+AverageAreaGridDensityProvider::AverageAreaGridDensityProvider(OccluderSource& source, const real proscenium[4],
+ real sizeFactor)
+: GridDensityProvider(source)
+{
+ initialize (proscenium, sizeFactor);
+}
+
+AverageAreaGridDensityProvider::AverageAreaGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
+ const GridHelpers::Transform& transform, real sizeFactor)
+: GridDensityProvider(source)
+{
+ real proscenium[4];
+ calculateQuickProscenium(transform, bbox, proscenium);
+
+ initialize(proscenium, sizeFactor);
+}
+
+AverageAreaGridDensityProvider::AverageAreaGridDensityProvider(OccluderSource& source, real sizeFactor)
+: GridDensityProvider(source)
+{
+ real proscenium[4];
+ calculateOptimalProscenium(source, proscenium);
+
+ initialize(proscenium, sizeFactor);
+}
+
+AverageAreaGridDensityProvider::~AverageAreaGridDensityProvider() {}
+
+void AverageAreaGridDensityProvider::initialize(const real proscenium[4], real sizeFactor)
+{
+ float prosceniumWidth = (proscenium[1] - proscenium[0]);
+ float prosceniumHeight = (proscenium[3] - proscenium[2]);
+
+ real cellArea = 0.0;
+ unsigned numFaces = 0;
+ for (source.begin(); source.isValid(); source.next()) {
+ Polygon3r& poly(source.getGridSpacePolygon());
+ Vec3r min, max;
+ poly.getBBox(min, max);
+ cellArea += (max[0] - min[0]) * (max[1] - min[1]);
+ ++numFaces;
+ }
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Total area: " << cellArea << ". Number of faces: " << numFaces << "." << endl;
+ }
+ cellArea /= numFaces;
+ cellArea *= sizeFactor;
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Building grid with average area " << cellArea << endl;
+ }
+
+ _cellSize = sqrt(cellArea);
+ // Now we know how many cells make each side of our grid
+ _cellsX = ceil(prosceniumWidth / _cellSize);
+ _cellsY = ceil(prosceniumHeight / _cellSize);
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl;
+ }
+
+ // Make sure the grid exceeds the proscenium by a small amount
+ float safetyZone = 0.1f;
+ if (_cellsX * _cellSize < prosceniumWidth * (1.0 + safetyZone)) {
+ _cellsX = prosceniumWidth * (1.0 + safetyZone) / _cellSize;
+ }
+ if (_cellsY * _cellSize < prosceniumHeight * (1.0 + safetyZone)) {
+ _cellsY = prosceniumHeight * (1.0 + safetyZone) / _cellSize;
+ }
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl;
+ }
+
+ // Find grid origin
+ _cellOrigin[0] = ((proscenium[0] + proscenium[1]) / 2.0) - (_cellsX / 2.0) * _cellSize;
+ _cellOrigin[1] = ((proscenium[2] + proscenium[3]) / 2.0) - (_cellsY / 2.0) * _cellSize;
+}
+
+AverageAreaGridDensityProviderFactory::AverageAreaGridDensityProviderFactory(real sizeFactor)
+: sizeFactor(sizeFactor)
+{
+}
+
+AverageAreaGridDensityProviderFactory::~AverageAreaGridDensityProviderFactory() {}
+
+auto_ptr<GridDensityProvider>
+AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4])
+{
+ return auto_ptr<GridDensityProvider>(new AverageAreaGridDensityProvider(source, proscenium, sizeFactor));
+}
+
+auto_ptr<GridDensityProvider>
+AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
+ const GridHelpers::Transform& transform)
+{
+ return auto_ptr<GridDensityProvider>(new AverageAreaGridDensityProvider(source, bbox, transform, sizeFactor));
+}
+
+auto_ptr<GridDensityProvider> AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source)
+{
+ return auto_ptr<GridDensityProvider>(new AverageAreaGridDensityProvider(source, sizeFactor));
+}
diff --git a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h
new file mode 100644
index 00000000000..05d2ae1ed9d
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_AVERAGE_AREA_GRID_DENSITY_PROVIDER_H__
+#define __FREESTYLE_AVERAGE_AREA_GRID_DENSITY_PROVIDER_H__
+
+/** \file blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2011-2-9
+ */
+
+#include "GridDensityProvider.h"
+
+class AverageAreaGridDensityProvider : public GridDensityProvider
+{
+ // Disallow copying and assignment
+ AverageAreaGridDensityProvider(const AverageAreaGridDensityProvider& other);
+ AverageAreaGridDensityProvider& operator=(const AverageAreaGridDensityProvider& other);
+
+public:
+ AverageAreaGridDensityProvider(OccluderSource& source, const real proscenium[4], real sizeFactor);
+ AverageAreaGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
+ const GridHelpers::Transform& transform, real sizeFactor);
+ AverageAreaGridDensityProvider(OccluderSource& source, real sizeFactor);
+ virtual ~AverageAreaGridDensityProvider();
+
+private:
+ void initialize (const real proscenium[4], real sizeFactor);
+};
+
+class AverageAreaGridDensityProviderFactory : public GridDensityProviderFactory
+{
+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);
+
+protected:
+ real sizeFactor;
+};
+
+#endif // __FREESTYLE_AVERAGE_AREA_GRID_DENSITY_PROVIDER_H__
diff --git a/source/blender/freestyle/intern/view_map/BoxGrid.cpp b/source/blender/freestyle/intern/view_map/BoxGrid.cpp
new file mode 100644
index 00000000000..2be2fe2cb5a
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/BoxGrid.cpp
@@ -0,0 +1,241 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/BoxGrid.cpp
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2011-1-29
+ */
+
+#include <algorithm>
+#include <stdexcept>
+
+#include "BoxGrid.h"
+
+#include "BKE_global.h"
+
+using namespace std;
+
+// Helper Classes
+
+// OccluderData
+///////////////
+
+// Cell
+/////////
+
+BoxGrid::Cell::Cell() {}
+
+BoxGrid::Cell::~Cell() {}
+
+void BoxGrid::Cell::setDimensions(real x, real y, real sizeX, real sizeY)
+{
+ const real epsilon = 1.0e-06;
+ boundary[0] = x - epsilon;
+ boundary[1] = x + sizeX + epsilon;
+ boundary[2] = y - epsilon;
+ boundary[3] = y + sizeY + epsilon;
+}
+
+bool BoxGrid::Cell::compareOccludersByShallowestPoint(const BoxGrid::OccluderData *a, const BoxGrid::OccluderData *b)
+{
+ return a->shallowest < b->shallowest;
+}
+
+void BoxGrid::Cell::indexPolygons()
+{
+ // Sort occluders by their shallowest points.
+ sort(faces.begin(), faces.end(), compareOccludersByShallowestPoint);
+}
+
+// Iterator
+//////////////////
+
+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 (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
+
+ // Set iterator
+ _current = _cell->faces.begin();
+}
+
+BoxGrid::Iterator::~Iterator() {}
+
+// BoxGrid
+/////////////////
+
+BoxGrid::BoxGrid(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap, Vec3r& viewpoint,
+ bool enableQI)
+: _viewpoint(viewpoint), _enableQI(enableQI)
+{
+ // Generate Cell structure
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Generate Cell structure" << endl;
+ }
+ assignCells(source, density, viewMap);
+
+ // Fill Cells
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Distribute occluders" << endl;
+ }
+ distributePolygons(source);
+
+ // Reorganize Cells
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Reorganize cells" << endl;
+ }
+ reorganizeCells();
+
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Ready to use BoxGrid" << endl;
+ }
+}
+
+BoxGrid::~BoxGrid() {}
+
+void BoxGrid::assignCells (OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap)
+{
+ _cellSize = density.cellSize();
+ _cellsX = density.cellsX();
+ _cellsY = density.cellsY();
+ _cellOrigin[0] = density.cellOrigin(0);
+ _cellOrigin[1] = density.cellOrigin(1);
+
+ // Now allocate the cell table and fill it with default (empty) cells
+ _cells.resize(_cellsX * _cellsY);
+ for (cellContainer::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) {
+ (*i) = NULL;
+ }
+
+ // Identify cells that will be used, and set the dimensions for each
+ ViewMap::fedges_container& fedges = viewMap->FEdges();
+ for (ViewMap::fedges_container::iterator f = fedges.begin(), fend = fedges.end(); f != fend; ++f) {
+ if ((*f)->isInImage()) {
+ Vec3r point = transform((*f)->center3d());
+ unsigned int i, j;
+ getCellCoordinates(point, i, j);
+ if (_cells[i * _cellsY + j] == NULL) {
+ // This is an uninitialized cell
+ real x, y, width, height;
+
+ x = _cellOrigin[0] + _cellSize * i;
+ width = _cellSize;
+
+ y = _cellOrigin[1] + _cellSize * j;
+ height = _cellSize;
+
+ // Initialize cell
+ Cell *b = _cells[i * _cellsY + j] = new Cell();
+ b->setDimensions(x, y, width, height);
+ }
+ }
+ }
+}
+
+void BoxGrid::distributePolygons(OccluderSource& source)
+{
+ unsigned long nFaces = 0;
+ unsigned long nKeptFaces = 0;
+
+ for (source.begin(); source.isValid(); source.next()) {
+ OccluderData *occluder = NULL;
+
+ try {
+ if (insertOccluder(source, occluder)) {
+ _faces.push_back(occluder);
+ ++nKeptFaces;
+ }
+ }
+ catch (...) {
+ // If an exception was thrown, _faces.push_back() cannot have succeeded.
+ // occluder is not owned by anyone, and must be deleted.
+ // If the exception was thrown before or during new OccluderData(), then
+ // occluder is NULL, and this delete is harmless.
+ delete occluder;
+ throw;
+ }
+ ++nFaces;
+ }
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Distributed " << nFaces << " occluders. Retained " << nKeptFaces << "." << endl;
+ }
+}
+
+void BoxGrid::reorganizeCells()
+{
+ // Sort the occluders by shallowest point
+ for (vector<Cell*>::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) {
+ if (*i != NULL) {
+ (*i)->indexPolygons();
+ }
+ }
+}
+
+void BoxGrid::getCellCoordinates(const Vec3r& point, unsigned& x, unsigned& y)
+{
+ x = min(_cellsX - 1, (unsigned) floor (max((double) 0.0f, point[0] - _cellOrigin[0]) / _cellSize));
+ y = min(_cellsY - 1, (unsigned) floor (max((double) 0.0f, point[1] - _cellOrigin[1]) / _cellSize));
+}
+
+BoxGrid::Cell *BoxGrid::findCell(const Vec3r& point)
+{
+ unsigned int x, y;
+ getCellCoordinates(point, x, y);
+ return _cells[x * _cellsY + y];
+}
+
+bool BoxGrid::orthographicProjection() const
+{
+ return true;
+}
+
+const Vec3r& BoxGrid::viewpoint() const
+{
+ return _viewpoint;
+}
+
+bool BoxGrid::enableQI() const
+{
+ return _enableQI;
+}
+
+BoxGrid::Transform::Transform() : GridHelpers::Transform() {}
+
+Vec3r BoxGrid::Transform::operator()(const Vec3r& point) const
+{
+ return Vec3r(point[0], point[1], -point[2]);
+}
diff --git a/source/blender/freestyle/intern/view_map/BoxGrid.h b/source/blender/freestyle/intern/view_map/BoxGrid.h
new file mode 100644
index 00000000000..22f3b6fa698
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/BoxGrid.h
@@ -0,0 +1,417 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_BOX_GRID_H__
+#define __FREESTYLE_BOX_GRID_H__
+
+/** \file blender/freestyle/intern/view_map/BoxGrid.h
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2011-1-29
+ */
+
+#define BOX_GRID_LOGGING FALSE
+
+// I would like to avoid using deque because including ViewMap.h and <deque> or <vector>
+// separately results in redefinitions of identifiers. ViewMap.h already includes <vector>
+// so it should be a safe fall-back.
+//#include <vector>
+//#include <deque>
+
+#include "GridDensityProvider.h"
+#include "OccluderSource.h"
+#include "ViewMap.h"
+
+#include "../geometry/BBox.h"
+#include "../geometry/GridHelpers.h"
+#include "../geometry/Polygon.h"
+
+#include "../system/PointerSequence.h"
+
+#include "../winged_edge/WEdge.h"
+
+#include "BKE_global.h"
+
+class BoxGrid
+{
+public:
+ // Helper classes
+ struct OccluderData
+ {
+ explicit OccluderData(OccluderSource& source, Polygon3r& p);
+ Polygon3r poly;
+ Polygon3r cameraSpacePolygon;
+ real shallowest, deepest;
+ // N.B. We could, of course, store face in poly's userdata member, like the old ViewMapBuilder code does.
+ // However, code comments make it clear that userdata is deprecated, so we avoid the temptation
+ // to save 4 or 8 bytes.
+ WFace *face;
+ };
+
+private:
+ struct Cell
+ {
+ // Can't store Cell in a vector without copy and assign
+ // Cell(const Cell& other);
+ // Cell& operator=(const Cell& other);
+
+ explicit Cell();
+ ~Cell();
+
+ static bool compareOccludersByShallowestPoint(const OccluderData *a, const OccluderData *b);
+
+ void setDimensions(real x, real y, real sizeX, real sizeY);
+ void checkAndInsert(OccluderSource& source, Polygon3r& poly, OccluderData*& occluder);
+ void indexPolygons();
+
+ real boundary[4];
+ //deque<OccluderData*> faces;
+ vector<OccluderData*> faces;
+ };
+
+public:
+ /* Iterator needs to allow the user to avoid full 3D comparison in two cases:
+ *
+ * (1) Where (*current)->deepest < target[2], where the occluder is unambiguously in front of the target point.
+ *
+ * (2) Where (*current)->shallowest > target[2], where the occluder is unambiguously in back of the target point.
+ *
+ * In addition, when used by OptimizedFindOccludee, Iterator should stop iterating as soon as it has an
+ * occludee candidate and (*current)->shallowest > candidate[2], because at that point forward no new occluder
+ * could possibly be a better occludee.
+ */
+ class Iterator
+ {
+ public:
+ // epsilon is not used in this class, but other grids with the same interface may need an epsilon
+ explicit Iterator(BoxGrid& grid, Vec3r& center, real epsilon = 1.0e-06);
+ ~Iterator();
+ void initBeforeTarget();
+ void initAfterTarget();
+ void nextOccluder();
+ void nextOccludee();
+ bool validBeforeTarget();
+ bool validAfterTarget();
+ WFace *getWFace() const;
+ Polygon3r *getCameraSpacePolygon();
+ void reportDepth(Vec3r origin, Vec3r u, real t);
+
+ private:
+ bool testOccluder(bool wantOccludee);
+ void markCurrentOccludeeCandidate(real depth);
+
+ Cell *_cell;
+ Vec3r _target;
+ bool _foundOccludee;
+ real _occludeeDepth;
+ //deque<OccluderData*>::iterator _current, _occludeeCandidate;
+ vector<OccluderData*>::iterator _current, _occludeeCandidate;
+ };
+
+ class Transform : public GridHelpers::Transform
+ {
+ public:
+ explicit Transform();
+ explicit Transform(Transform& other);
+ Vec3r operator()(const Vec3r& point) const;
+ };
+
+private:
+ // Prevent implicit copies and assignments.
+ BoxGrid(const BoxGrid& other);
+ BoxGrid& operator=(const BoxGrid& other);
+
+public:
+ explicit BoxGrid(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap, Vec3r& viewpoint,
+ bool enableQI);
+ virtual ~BoxGrid();
+
+ // Generate Cell structure
+ void assignCells(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap);
+ // Fill Cells
+ void distributePolygons(OccluderSource& source);
+ // Insert one polygon into each matching cell, return true if any cell consumes the polygon
+ bool insertOccluder(OccluderSource& source, OccluderData*& occluder);
+ // Sort occluders in each cell
+ void reorganizeCells();
+
+ Cell *findCell(const Vec3r& point);
+
+ // Accessors:
+ bool orthographicProjection() const;
+ const Vec3r& viewpoint() const;
+ bool enableQI() const;
+ Transform transform;
+
+private:
+ void getCellCoordinates(const Vec3r& point, unsigned& x, unsigned& y);
+
+ typedef PointerSequence<vector<Cell*>, Cell*> cellContainer;
+ //typedef PointerSequence<deque<OccluderData*>, OccluderData*> occluderContainer;
+ typedef PointerSequence<vector<OccluderData*>, OccluderData*> occluderContainer;
+ unsigned _cellsX, _cellsY;
+ float _cellSize;
+ float _cellOrigin[2];
+ cellContainer _cells;
+ occluderContainer _faces;
+ Vec3r _viewpoint;
+ bool _enableQI;
+};
+
+inline void BoxGrid::Iterator::initBeforeTarget()
+{
+ _current = _cell->faces.begin();
+ while (_current != _cell->faces.end() && !testOccluder(false)) {
+ ++_current;
+ }
+}
+
+inline void BoxGrid::Iterator::initAfterTarget()
+{
+ if (_foundOccludee) {
+#if BOX_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "\tStarting occludee search from occludeeCandidate at depth " <<
+ _occludeeDepth << std::endl;
+ }
+#endif
+ _current = _occludeeCandidate;
+ return;
+ }
+
+#if BOX_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "\tStarting occludee search from current position" << std::endl;
+ }
+#endif
+
+ while (_current != _cell->faces.end() && !testOccluder(true)) {
+ ++_current;
+ }
+}
+
+inline bool BoxGrid::Iterator::testOccluder(bool wantOccludee)
+{
+ // End-of-list is not even a valid iterator position
+ if (_current == _cell->faces.end()) {
+ // Returning true seems strange, but it will break us out of whatever loop is calling testOccluder,
+ // and _current = _cell->face.end() will make the calling routine give up.
+ return true;
+ }
+#if BOX_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "\tTesting occluder " << (*_current)->poly.getVertices()[0];
+ for (unsigned int i = 1; i < (*_current)->poly.getVertices().size(); ++i) {
+ std::cout << ", " << (*_current)->poly.getVertices()[i];
+ }
+ std::cout << " from shape " << (*_current)->face->GetVertex(0)->shape()->GetId() << std::endl;
+ }
+#endif
+
+ // If we have an occluder candidate and we are unambiguously after it, abort
+ if (_foundOccludee && (*_current)->shallowest > _occludeeDepth) {
+#if BOX_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "\t\tAborting: shallowest > occludeeCandidate->deepest" << std::endl;
+ }
+#endif
+ _current = _cell->faces.end();
+
+ // See note above
+ return true;
+ }
+
+ // Specific continue or stop conditions when searching for each type
+ if (wantOccludee) {
+ if ((*_current)->deepest < _target[2]) {
+#if BOX_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "\t\tSkipping: shallower than target while looking for occludee" << std::endl;
+ }
+#endif
+ return false;
+ }
+ }
+ else {
+ if ((*_current)->shallowest > _target[2]) {
+#if BOX_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "\t\tStopping: deeper than target while looking for occluder" << std::endl;
+ }
+#endif
+ return true;
+ }
+ }
+
+ // Depthwise, this is a valid occluder.
+
+ // Check to see if target is in the 2D bounding box
+ Vec3r bbMin, bbMax;
+ (*_current)->poly.getBBox(bbMin, bbMax);
+ if (_target[0] < bbMin[0] || _target[0] > bbMax[0] || _target[1] < bbMin[1] || _target[1] > bbMax[1]) {
+#if BOX_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "\t\tSkipping: bounding box violation" << std::endl;
+ }
+#endif
+ return false;
+ }
+
+ // We've done all the corner cutting we can.
+ // Let the caller work out whether or not the geometry is correct.
+ return true;
+}
+
+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 (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "\t\tReporting depth of occluder/ee: " << depth;
+ }
+ #endif
+ if (depth > _target[2]) {
+#if BOX_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << " is deeper than target" << std::endl;
+ }
+#endif
+ // If the current occluder is the best occludee so far, save it.
+ if (! _foundOccludee || _occludeeDepth > depth) {
+ markCurrentOccludeeCandidate(depth);
+ }
+ }
+ else {
+#if BOX_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << std::endl;
+ }
+#endif
+ }
+}
+
+inline void BoxGrid::Iterator::nextOccluder()
+{
+ if (_current != _cell->faces.end()) {
+ do {
+ ++_current;
+ } while (_current != _cell->faces.end() && ! testOccluder(false));
+ }
+}
+
+inline void BoxGrid::Iterator::nextOccludee()
+{
+ if (_current != _cell->faces.end()) {
+ do {
+ ++_current;
+ } while (_current != _cell->faces.end() && ! testOccluder(true));
+ }
+}
+
+inline bool BoxGrid::Iterator::validBeforeTarget()
+{
+ return _current != _cell->faces.end() && (*_current)->shallowest <= _target[2];
+}
+
+inline bool BoxGrid::Iterator::validAfterTarget()
+{
+ return _current != _cell->faces.end();
+}
+
+inline void BoxGrid::Iterator::markCurrentOccludeeCandidate(real depth)
+{
+#if BOX_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "\t\tFound occludeeCandidate at depth " << depth << std::endl;
+ }
+#endif
+ _occludeeCandidate = _current;
+ _occludeeDepth = depth;
+ _foundOccludee = true;
+}
+
+inline WFace *BoxGrid::Iterator::getWFace() const
+{
+ return (*_current)->face;
+}
+
+inline Polygon3r *BoxGrid::Iterator::getCameraSpacePolygon()
+{
+ return &((*_current)->cameraSpacePolygon);
+}
+
+inline BoxGrid::OccluderData::OccluderData(OccluderSource& source, Polygon3r& p)
+: poly(p),
+ cameraSpacePolygon(source.getCameraSpacePolygon()),
+ face(source.getWFace())
+{
+ // Set shallowest and deepest based on bbox
+ Vec3r min, max;
+ poly.getBBox(min, max);
+ shallowest = min[2];
+ deepest = max[2];
+}
+
+inline void BoxGrid::Cell::checkAndInsert(OccluderSource& source, Polygon3r& poly, OccluderData*& occluder)
+{
+ if (GridHelpers::insideProscenium (boundary, poly)) {
+ if (occluder == NULL) {
+ // Disposal of occluder will be handled in BoxGrid::distributePolygons(),
+ // or automatically by BoxGrid::_faces;
+ occluder = new OccluderData(source, poly);
+ }
+ faces.push_back(occluder);
+ }
+}
+
+inline bool BoxGrid::insertOccluder(OccluderSource& source, OccluderData*& occluder)
+{
+ Polygon3r& poly(source.getGridSpacePolygon());
+ occluder = NULL;
+
+ Vec3r bbMin, bbMax;
+ poly.getBBox(bbMin, bbMax);
+ // Check overlapping cells
+ unsigned startX, startY, endX, endY;
+ getCellCoordinates(bbMin, startX, startY);
+ getCellCoordinates(bbMax, endX, endY);
+
+ for (unsigned int i = startX; i <= endX; ++i) {
+ for (unsigned int j = startY; j <= endY; ++j) {
+ if (_cells[i * _cellsY + j] != NULL) {
+ _cells[i * _cellsY + j]->checkAndInsert(source, poly, occluder);
+ }
+ }
+ }
+
+ return occluder != NULL;
+}
+
+#endif // __FREESTYLE_BOX_GRID_H__
diff --git a/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp b/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp
new file mode 100644
index 00000000000..53bd76b81f2
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp
@@ -0,0 +1,287 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/CulledOccluderSource.cpp
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2010-12-21
+ */
+
+#include "CulledOccluderSource.h"
+
+#include "FRS_freestyle.h"
+
+#include "../geometry/GridHelpers.h"
+
+#include "BKE_global.h"
+
+CulledOccluderSource::CulledOccluderSource(const GridHelpers::Transform& t, WingedEdge& we, ViewMap& viewMap,
+ bool extensiveFEdgeSearch)
+: OccluderSource(t, we), rejected(0), gridSpaceOccluderProsceniumInitialized(false)
+{
+ cullViewEdges(viewMap, extensiveFEdgeSearch);
+
+ // If we have not found any visible FEdges during our cull, then there is nothing to iterate over.
+ // Short-circuit everything.
+ valid = gridSpaceOccluderProsceniumInitialized;
+
+ if (valid && ! testCurrent()) {
+ next();
+ }
+}
+
+CulledOccluderSource::~CulledOccluderSource() {}
+
+bool CulledOccluderSource::testCurrent()
+{
+ if (valid) {
+ // The test for gridSpaceOccluderProsceniumInitialized should not be necessary
+ return gridSpaceOccluderProsceniumInitialized &&
+ GridHelpers::insideProscenium(gridSpaceOccluderProscenium, cachedPolygon);
+ }
+ return false;
+}
+
+bool CulledOccluderSource::next()
+{
+ while (OccluderSource::next()) {
+ if (testCurrent()) {
+ ++rejected;
+ return true;
+ }
+ }
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "Finished generating occluders. Rejected " << rejected << " faces." << std::endl;
+ }
+ return false;
+}
+
+void CulledOccluderSource::getOccluderProscenium(real proscenium[4])
+{
+ for (unsigned int i = 0; i < 4; ++i) {
+ proscenium[i] = gridSpaceOccluderProscenium[i];
+ }
+}
+
+static inline real distance2D(const Vec3r & point, const real origin[2])
+{
+ return ::hypot((point[0] - origin[0]), (point[1] - origin[1]));
+}
+
+static inline bool crossesProscenium(real proscenium[4], FEdge *fe)
+{
+ Vec2r min(proscenium[0], proscenium[2]);
+ Vec2r max(proscenium[1], proscenium[3]);
+ Vec2r A(fe->vertexA()->getProjectedX(), fe->vertexA()->getProjectedY());
+ Vec2r B(fe->vertexB()->getProjectedX(), fe->vertexB()->getProjectedY());
+
+ return GeomUtils::intersect2dSeg2dArea (min, max, A, B);
+}
+
+static inline bool insideProscenium(real proscenium[4], const Vec3r& point)
+{
+ return !(point[0] < proscenium[0] || point[0] > proscenium[1] ||
+ point[1] < proscenium[2] || point[1] > proscenium[3]);
+}
+
+void CulledOccluderSource::cullViewEdges(ViewMap& viewMap, bool extensiveFEdgeSearch)
+{
+ // Cull view edges by marking them as non-displayable.
+ // This avoids the complications of trying to delete edges from the ViewMap.
+
+ // Non-displayable view edges will be skipped over during visibility calculation.
+
+ // View edges will be culled according to their position w.r.t. the viewport proscenium (viewport + 5% border,
+ // or some such).
+
+ // Get proscenium boundary for culling
+ real viewProscenium[4];
+ GridHelpers::getDefaultViewProscenium(viewProscenium);
+ real prosceniumOrigin[2];
+ prosceniumOrigin[0] = (viewProscenium[1] - viewProscenium[0]) / 2.0;
+ prosceniumOrigin[1] = (viewProscenium[3] - viewProscenium[2]) / 2.0;
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Proscenium culling:" << endl;
+ cout << "Proscenium: [" << viewProscenium[0] << ", " << viewProscenium[1] << ", " << viewProscenium[2] <<
+ ", " << viewProscenium[3] << "]"<< endl;
+ cout << "Origin: [" << prosceniumOrigin[0] << ", " << prosceniumOrigin[1] << "]"<< endl;
+ }
+
+ // A separate occluder proscenium will also be maintained, starting out the same as the viewport proscenium, and
+ // expanding as necessary so that it encompasses the center point of at least one feature edge in each
+ // retained view edge.
+ // The occluder proscenium will be used later to cull occluding triangles before they are inserted into the Grid.
+ // The occluder proscenium starts out the same size as the view proscenium
+ GridHelpers::getDefaultViewProscenium(occluderProscenium);
+
+ // XXX Freestyle is inconsistent in its use of ViewMap::viewedges_container and vector<ViewEdge*>::iterator.
+ // Probably all occurences of vector<ViewEdge*>::iterator should be replaced ViewMap::viewedges_container
+ // throughout the code.
+ // For each view edge
+ ViewMap::viewedges_container::iterator ve, veend;
+
+ for (ve = viewMap.ViewEdges().begin(), veend = viewMap.ViewEdges().end(); ve != veend; ve++) {
+ // Overview:
+ // Search for a visible feature edge
+ // If none: mark view edge as non-displayable
+ // Otherwise:
+ // Find a feature edge with center point inside occluder proscenium.
+ // If none exists, find the feature edge with center point closest to viewport origin.
+ // Expand occluder proscenium to enclose center point.
+
+ // For each feature edge, while bestOccluderTarget not found and view edge not visibile
+ bool bestOccluderTargetFound = false;
+ FEdge *bestOccluderTarget = NULL;
+ real bestOccluderDistance = 0.0;
+ FEdge *festart = (*ve)->fedgeA();
+ FEdge *fe = festart;
+ // All ViewEdges start culled
+ (*ve)->setIsInImage(false);
+
+ // For simple visibility calculation: mark a feature edge that is known to have a center point inside
+ // the occluder proscenium. Cull all other feature edges.
+ do {
+ // All FEdges start culled
+ fe->setIsInImage(false);
+
+ // Look for the visible edge that can most easily be included in the occluder proscenium.
+ if (!bestOccluderTargetFound) {
+ // If center point is inside occluder proscenium,
+ if (insideProscenium(occluderProscenium, fe->center2d())) {
+ // Use this feature edge for visibility deterimination
+ fe->setIsInImage(true);
+ expandGridSpaceOccluderProscenium(fe);
+ // Mark bestOccluderTarget as found
+ bestOccluderTargetFound = true;
+ bestOccluderTarget = fe;
+ }
+ else {
+ real d = distance2D(fe->center2d(), prosceniumOrigin);
+ // If center point is closer to viewport origin than current target
+ if (bestOccluderTarget == NULL || d < bestOccluderDistance) {
+ // Then store as bestOccluderTarget
+ bestOccluderDistance = d;
+ bestOccluderTarget = fe;
+ }
+ }
+ }
+
+ // If feature edge crosses the view proscenium
+ if (!(*ve)->isInImage() && crossesProscenium(viewProscenium, fe)) {
+ // Then the view edge will be included in the image
+ (*ve)->setIsInImage(true);
+ }
+ fe = fe->nextEdge();
+ } while (fe != NULL && fe != festart && !(bestOccluderTargetFound && (*ve)->isInImage()));
+
+ // Either we have run out of FEdges, or we already have the one edge we need to determine visibility
+ // Cull all remaining edges.
+ while (fe != NULL && fe != festart) {
+ fe->setIsInImage(false);
+ fe = fe->nextEdge();
+ }
+
+ // If bestOccluderTarget was not found inside the occluder proscenium,
+ // we need to expand the occluder proscenium to include it.
+ if ((*ve)->isInImage() && bestOccluderTarget != NULL && ! bestOccluderTargetFound) {
+ // Expand occluder proscenium to enclose bestOccluderTarget
+ Vec3r point = bestOccluderTarget->center2d();
+ if (point[0] < occluderProscenium[0]) {
+ occluderProscenium[0] = point[0];
+ }
+ else if (point[0] > occluderProscenium[1]) {
+ occluderProscenium[1] = point[0];
+ }
+ if (point[1] < occluderProscenium[2]) {
+ occluderProscenium[2] = point[1];
+ }
+ else if (point[1] > occluderProscenium[3]) {
+ occluderProscenium[3] = point[1];
+ }
+ // Use bestOccluderTarget for visibility determination
+ bestOccluderTarget->setIsInImage(true);
+ }
+ }
+
+ // We are done calculating the occluder proscenium.
+ // Expand the occluder proscenium by an epsilon to avoid rounding errors.
+ const real epsilon = 1.0e-6;
+ occluderProscenium[0] -= epsilon;
+ occluderProscenium[1] += epsilon;
+ occluderProscenium[2] -= epsilon;
+ occluderProscenium[3] += epsilon;
+
+ // For "Normal" or "Fast" style visibility computation only:
+
+ // For more detailed visibility calculation, make a second pass through the view map, marking all feature edges
+ // with center points inside the final occluder proscenium. All of these feature edges can be considered during
+ // visibility calculation.
+
+ // So far we have only found one FEdge per ViewEdge. The "Normal" and "Fast" styles of visibility computation
+ // want to consider many FEdges for each ViewEdge.
+ // Here we re-scan the view map to find any usable FEdges that we skipped on the first pass, or that have become
+ // usable because the occluder proscenium has been expanded since the edge was visited on the first pass.
+ if (extensiveFEdgeSearch) {
+ // For each view edge,
+ for (ve = viewMap.ViewEdges().begin(), veend = viewMap.ViewEdges().end(); ve != veend; ve++) {
+ if (!(*ve)->isInImage()) {
+ continue;
+ }
+ // For each feature edge,
+ FEdge *festart = (*ve)->fedgeA();
+ FEdge *fe = festart;
+ do {
+ // If not (already) visible and center point inside occluder proscenium,
+ if (!fe->isInImage() && insideProscenium(occluderProscenium, fe->center2d())) {
+ // Use the feature edge for visibility determination
+ fe->setIsInImage(true);
+ expandGridSpaceOccluderProscenium(fe);
+ }
+ fe = fe->nextEdge();
+ } while (fe != NULL && fe != festart);
+ }
+ }
+
+ // Up until now, all calculations have been done in camera space.
+ // However, the occluder source's iteration and the grid that consumes the occluders both work in gridspace,
+ // so we need a version of the occluder proscenium in gridspace.
+ // Set the gridspace occlude proscenium
+}
+
+void CulledOccluderSource::expandGridSpaceOccluderProscenium(FEdge *fe)
+{
+ if (gridSpaceOccluderProsceniumInitialized) {
+ GridHelpers::expandProscenium(gridSpaceOccluderProscenium, transform(fe->center3d()));
+ }
+ else {
+ const Vec3r& point = transform(fe->center3d());
+ gridSpaceOccluderProscenium[0] = gridSpaceOccluderProscenium[1] = point[0];
+ gridSpaceOccluderProscenium[2] = gridSpaceOccluderProscenium[3] = point[1];
+ gridSpaceOccluderProsceniumInitialized = true;
+ }
+}
diff --git a/source/blender/freestyle/intern/view_map/CulledOccluderSource.h b/source/blender/freestyle/intern/view_map/CulledOccluderSource.h
new file mode 100644
index 00000000000..a9c5484ca9c
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/CulledOccluderSource.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_CULLED_OCCLUDER_SOURCE_H__
+#define __FREESTYLE_CULLED_OCCLUDER_SOURCE_H__
+
+/** \file blender/freestyle/intern/view_map/CulledOccluderSource.h
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2010-12-21
+ */
+
+#include "OccluderSource.h"
+#include "ViewMap.h"
+
+class CulledOccluderSource : public OccluderSource
+{
+ // Disallow copying and assignment
+ CulledOccluderSource(const CulledOccluderSource& other);
+ CulledOccluderSource& operator=(const CulledOccluderSource& other);
+
+public:
+ CulledOccluderSource(const GridHelpers::Transform& transform, WingedEdge& we, ViewMap& viewMap,
+ bool extensiveFEdgeSearch = true);
+ virtual ~CulledOccluderSource();
+
+ void cullViewEdges(ViewMap& viewMap, bool extensiveFEdgeSearch);
+
+ bool next();
+
+ void getOccluderProscenium(real proscenium[4]);
+
+private:
+ bool testCurrent();
+ void expandGridSpaceOccluderProscenium(FEdge *fe);
+
+ real occluderProscenium[4];
+ real gridSpaceOccluderProscenium[4];
+
+ unsigned long rejected;
+ bool gridSpaceOccluderProsceniumInitialized;
+};
+
+#endif // __FREESTYLE_CULLED_OCCLUDER_SOURCE_H__
diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp
new file mode 100644
index 00000000000..e95bbe44627
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp
@@ -0,0 +1,762 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/FEdgeXDetector.cpp
+ * \ingroup freestyle
+ * \brief Detects/flags/builds extended features edges on the WXEdge structure
+ * \author Stephane Grabli
+ * \date 26/10/2003
+ */
+
+#include <float.h>
+#include <math.h>
+
+#include "FEdgeXDetector.h"
+
+#include "../geometry/GeomUtils.h"
+#include "../geometry/normal_cycle.h"
+
+#include "BKE_global.h"
+
+void FEdgeXDetector::processShapes(WingedEdge& we)
+{
+ bool progressBarDisplay = false;
+ Vec3r Min, Max;
+ vector<WShape*> wshapes = we.getWShapes();
+ WXShape *wxs;
+
+ if (_pProgressBar != NULL) {
+ _pProgressBar->reset();
+ _pProgressBar->setLabelText("Detecting feature lines");
+ _pProgressBar->setTotalSteps(wshapes.size() * 3);
+ _pProgressBar->setProgress(0);
+ progressBarDisplay = true;
+ }
+
+ for (vector<WShape*>::const_iterator it = wshapes.begin(); it != wshapes.end(); it++) {
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ break;
+ wxs = dynamic_cast<WXShape*>(*it);
+ wxs->bbox(Min, Max);
+ _bbox_diagonal = (Max - Min).norm();
+ 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;
+ }
+ else if (!(wxs)->getComputeViewIndependantFlag()) {
+ wxs->Reset();
+ _computeViewIndependant = false;
+ }
+ else {
+ _computeViewIndependant = true;
+ }
+ preProcessShape(wxs);
+ if (progressBarDisplay)
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+ processBorderShape(wxs);
+ if (_computeMaterialBoundaries)
+ processMaterialBoundaryShape(wxs);
+ processCreaseShape(wxs);
+ if (_computeRidgesAndValleys)
+ processRidgesAndValleysShape(wxs);
+ if (_computeSuggestiveContours)
+ processSuggestiveContourShape(wxs);
+ processSilhouetteShape(wxs);
+ processEdgeMarksShape(wxs);
+ if (progressBarDisplay)
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+
+ // build smooth edges:
+ buildSmoothEdges(wxs);
+
+ // Post processing for suggestive contours
+ if (_computeSuggestiveContours)
+ postProcessSuggestiveContourShape(wxs);
+ if (progressBarDisplay)
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+
+ wxs->setComputeViewIndependantFlag(false);
+ _computeViewIndependant = false;
+ _changes = false;
+
+ // reset user data
+ (*it)->ResetUserData();
+ }
+}
+
+// GENERAL STUFF
+////////////////
+void FEdgeXDetector::preProcessShape(WXShape *iWShape)
+{
+ _meanK1 = 0;
+ _meanKr = 0;
+ _minK1 = FLT_MAX;
+ _maxK1 = -FLT_MAX;
+ _minKr = FLT_MAX;
+ _maxKr = -FLT_MAX;
+ _nPoints = 0;
+ _meanEdgeSize = iWShape->getMeanEdgeSize();
+
+ vector<WFace*>& wfaces = iWShape->GetFaceList();
+ vector<WFace*>::iterator f, fend;
+ // view dependant stuff
+ for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
+ preProcessFace((WXFace *)(*f));
+ }
+
+ if (_computeRidgesAndValleys || _computeSuggestiveContours) {
+ vector<WVertex*>& wvertices = iWShape->getVertexList();
+ for (vector<WVertex*>::iterator wv = wvertices.begin(), wvend = wvertices.end(); wv != wvend; ++wv) {
+ // Compute curvatures
+ WXVertex *wxv = dynamic_cast<WXVertex*>(*wv);
+ computeCurvatures(wxv);
+ }
+ _meanK1 /= (real)(_nPoints);
+ _meanKr /= (real)(_nPoints);
+ }
+}
+
+void FEdgeXDetector::preProcessFace(WXFace *iFace)
+{
+ Vec3r firstPoint = iFace->GetVertex(0)->GetVertex();
+ Vec3r N = iFace->GetNormal();
+
+ // Compute the dot product between V (=_Viewpoint - firstPoint) and N:
+ Vec3r V;
+ if (_orthographicProjection) {
+ V = Vec3r(0.0, 0.0, _Viewpoint.z() - firstPoint.z());
+ }
+ else {
+ V = Vec3r(_Viewpoint - firstPoint);
+ }
+ N.normalize();
+ V.normalize();
+ iFace->setDotP(N * V);
+
+ // compute the distance between the face center and the viewpoint:
+ if (_orthographicProjection) {
+ iFace->setZ(iFace->center().z() - _Viewpoint.z());
+ }
+ else {
+ Vec3r dist_vec(iFace->center() - _Viewpoint);
+ iFace->setZ(dist_vec.norm());
+ }
+}
+
+void FEdgeXDetector::computeCurvatures(WXVertex *vertex)
+{
+ // TODO: for some reason, the 'vertex' may have no associated edges
+ // (i.e., WVertex::_EdgeList is empty), which causes a crash due to
+ // a subsequent call of WVertex::_EdgeList.front().
+ if (vertex->GetEdges().empty()) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("Warning: WVertex %d has no associated edges.\n", vertex->GetId());
+ }
+ return;
+ }
+
+ // CURVATURE LAYER
+ // store all the curvature datas for each vertex
+
+ //soc unused - real K1, K2
+ real cos2theta, sin2theta;
+ Vec3r e1, n, v;
+ // one vertex curvature info :
+ CurvatureInfo *C;
+ float radius = _sphereRadius * _meanEdgeSize;
+
+ // view independant stuff
+ if (_computeViewIndependant) {
+ C = new CurvatureInfo();
+ vertex->setCurvatures(C);
+ OGF::NormalCycle ncycle;
+ ncycle.begin();
+ if (radius > 0) {
+ OGF::compute_curvature_tensor(vertex, radius, ncycle);
+ }
+ else {
+ OGF::compute_curvature_tensor_one_ring(vertex, ncycle);
+ }
+ ncycle.end();
+ C->K1 = ncycle.kmin();
+ C->K2 = ncycle.kmax();
+ C->e1 = ncycle.Kmax(); //ncycle.kmin() * ncycle.Kmax();
+ C->e2 = ncycle.Kmin(); //ncycle.kmax() * ncycle.Kmin();
+
+ real absK1 = fabs(C->K1);
+ _meanK1 += absK1;
+ if (absK1 > _maxK1)
+ _maxK1 = absK1;
+ if (absK1 < _minK1)
+ _minK1 = absK1;
+ }
+ // view dependant
+ C = vertex->curvatures();
+ if (C == 0)
+ return;
+
+ // compute radial curvature :
+ n = C->e1 ^ C->e2;
+ if (_orthographicProjection) {
+ v = Vec3r(0.0, 0.0, _Viewpoint.z() - vertex->GetVertex().z());
+ }
+ else {
+ v = Vec3r(_Viewpoint - vertex->GetVertex());
+ }
+ C->er = v - (v * n) * n;
+ C->er.normalize();
+ e1 = C->e1;
+ e1.normalize();
+ cos2theta = C->er * e1;
+ cos2theta *= cos2theta;
+ sin2theta = 1 - cos2theta;
+ C->Kr = C->K1 * cos2theta + C->K2 * sin2theta;
+ real absKr = fabs(C->Kr);
+ _meanKr += absKr;
+ if (absKr > _maxKr)
+ _maxKr = absKr;
+ if (absKr < _minKr)
+ _minKr = absKr;
+
+ ++_nPoints;
+}
+
+// SILHOUETTE
+/////////////
+void FEdgeXDetector::processSilhouetteShape(WXShape *iWShape)
+{
+ // Make a first pass on every polygons in order to compute all their silhouette relative values:
+ vector<WFace*>& wfaces = iWShape->GetFaceList();
+ vector<WFace*>::iterator f, fend;
+ for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
+ ProcessSilhouetteFace((WXFace *)(*f));
+ }
+
+ // Make a pass on the edges to detect the silhouette edges that are not smooth
+ vector<WEdge*>::iterator we, weend;
+ vector<WEdge*> &wedges = iWShape->getEdgeList();
+ for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
+ ProcessSilhouetteEdge((WXEdge *)(*we));
+ }
+}
+
+void FEdgeXDetector::ProcessSilhouetteFace(WXFace *iFace)
+{
+ // SILHOUETTE LAYER
+ Vec3r normal;
+ // Compute the dot products between View direction and N at each vertex of the face:
+ Vec3r point;
+ int closestPointId = 0;
+ real 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;
+ if (_orthographicProjection) {
+ V = Vec3r(0.0, 0.0, _Viewpoint.z() - point.z());
+ }
+ else {
+ V = Vec3r(_Viewpoint - point);
+ }
+ V.normalize();
+ real 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);
+ dist = dist_vec.norm();
+ }
+ if (dist < minDist) {
+ minDist = dist;
+ closestPointId = i;
+ }
+ }
+ // Set the closest point id:
+ faceLayer->setClosestPointIndex(closestPointId);
+ // Add this layer to the face:
+ iFace->AddSmoothLayer(faceLayer);
+}
+
+void FEdgeXDetector::ProcessSilhouetteEdge(WXEdge *iEdge)
+{
+ if (iEdge->nature() & Nature::BORDER)
+ return;
+ // SILHOUETTE ?
+ //-------------
+ WXFace *fA = (WXFace *)iEdge->GetaOEdge()->GetaFace();
+ WXFace *fB = (WXFace *)iEdge->GetaOEdge()->GetbFace();
+
+ if ((fA->front()) ^ (fB->front())) { // fA->visible XOR fB->visible (true if one is 0 and the other is 1)
+ // The only edges we want to set as silhouette edges in this way are the ones with 2 different normals
+ // for 1 vertex for these two faces
+ //--------------------
+ // In reality we only test the normals for 1 of the 2 vertices.
+ if (fA->GetVertexNormal(iEdge->GetaVertex()) == fB->GetVertexNormal(iEdge->GetaVertex()))
+ return;
+ iEdge->AddNature(Nature::SILHOUETTE);
+ if (fB->front())
+ iEdge->setOrder(1);
+ else
+ iEdge->setOrder(-1);
+ }
+}
+
+// BORDER
+/////////
+void FEdgeXDetector::processBorderShape(WXShape *iWShape)
+{
+ if (!_computeViewIndependant)
+ return;
+ // Make a pass on the edges to detect the BORDER
+ vector<WEdge*>::iterator we, weend;
+ vector<WEdge*> &wedges = iWShape->getEdgeList();
+ for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
+ ProcessBorderEdge((WXEdge *)(*we));
+ }
+}
+
+void FEdgeXDetector::ProcessBorderEdge(WXEdge *iEdge)
+{
+ // first check whether it is a border edge: BORDER ?
+ //---------
+ if (iEdge->GetaFace() == 0) {
+ // it is a border edge
+ iEdge->AddNature(Nature::BORDER);
+ }
+}
+
+
+// CREASE
+/////////
+void FEdgeXDetector::processCreaseShape(WXShape *iWShape)
+{
+ if (!_computeViewIndependant)
+ return;
+
+ // Make a pass on the edges to detect the CREASE
+ vector<WEdge*>::iterator we, weend;
+ vector<WEdge*> &wedges = iWShape->getEdgeList();
+ for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
+ ProcessCreaseEdge((WXEdge *)(*we));
+ }
+}
+
+void FEdgeXDetector::ProcessCreaseEdge(WXEdge *iEdge)
+{
+ // CREASE ?
+ //---------
+ if (iEdge->nature() & Nature::BORDER)
+ return;
+ WXFace *fA = (WXFace *)iEdge->GetaOEdge()->GetaFace();
+ WXFace *fB = (WXFace *)iEdge->GetaOEdge()->GetbFace();
+
+ WVertex *aVertex = iEdge->GetaVertex();
+ if ((fA->GetVertexNormal(aVertex) * fB->GetVertexNormal(aVertex)) <= _creaseAngle)
+ iEdge->AddNature(Nature::CREASE);
+}
+
+// RIDGES AND VALLEYS
+/////////////////////
+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)
+ return;
+
+ // Here the curvatures must already have been computed
+ vector<WFace*>& wfaces = iWShape->GetFaceList();
+ vector<WFace*>::iterator f, fend;
+ for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
+ ProcessRidgeFace((WXFace *)(*f));
+ }
+}
+
+
+// RIDGES
+/////////
+void FEdgeXDetector::ProcessRidgeFace(WXFace *iFace)
+{
+ WXFaceLayer *flayer = new WXFaceLayer(iFace, Nature::RIDGE | Nature::VALLEY, false);
+ iFace->AddSmoothLayer(flayer);
+
+ unsigned int numVertices = iFace->numberOfVertices();
+ for (unsigned int i = 0; i < numVertices; ++i) {
+ WVertex *wv = iFace->GetVertex(i);
+ WXVertex *wxv = dynamic_cast<WXVertex*>(wv);
+ flayer->PushDotP(wxv->curvatures()->K1);
+ }
+
+ real threshold = 0;
+ //real threshold = _maxK1 - (_maxK1 - _meanK1) / 20.0;
+
+ if (flayer->nPosDotP() != numVertices) {
+ if ((fabs(flayer->dotP(0)) < threshold) && (fabs(flayer->dotP(1)) < threshold) &&
+ (fabs(flayer->dotP(2)) < threshold))
+ {
+ flayer->ReplaceDotP(0, 0);
+ flayer->ReplaceDotP(1, 0);
+ flayer->ReplaceDotP(2, 0);
+ }
+ }
+}
+
+#if 0
+void FEdgeXDetector::ProcessRidgeFace(WXFace *iFace)
+{
+ // RIDGE LAYER
+ // Compute the RidgeFunction, that is the derivative of the ppal curvature along e1 at each vertex of the face
+ WVertex *v;
+ Vec3r v1v2;
+ real t;
+ vector<WXFaceLayer*> SmoothLayers;
+ WXFaceLayer *faceLayer;
+ Face_Curvature_Info *layer_info;
+ real K1_a(0), K1_b(0);
+ Vec3r Inter_a, Inter_b;
+
+ // find the ridge layer of the face
+ iFace->retrieveSmoothLayers(Nature::RIDGE, SmoothLayers);
+ if ( SmoothLayers.size()!=1 )
+ return;
+ faceLayer = SmoothLayers[0];
+ // retrieve the curvature info of this layer
+ layer_info = (Face_Curvature_Info *)faceLayer->userdata;
+
+ int numVertices = iFace->numberOfVertices();
+ for (int i = 0; i < numVertices; i++) {
+ v = iFace->GetVertex(i);
+ // vec_curvature_info[i] contains the curvature info of this vertex
+ Vec3r e2 = layer_info->vec_curvature_info[i]->K2*layer_info->vec_curvature_info[i]->e2;
+ Vec3r e1 = layer_info->vec_curvature_info[i]->K1*layer_info->vec_curvature_info[i]->e1;
+ e2.normalize();
+
+ WVertex::face_iterator fit = v->faces_begin();
+ WVertex::face_iterator fitend = v->faces_end();
+ for (; fit != fitend; ++fit) {
+ WXFace *wxf = dynamic_cast<WXFace*>(*fit);
+ WOEdge *oppositeEdge;
+ if (!(wxf->getOppositeEdge(v, oppositeEdge)))
+ continue;
+ v1v2 = oppositeEdge->GetbVertex()->GetVertex() - oppositeEdge->GetaVertex()->GetVertex();
+ GeomUtils::intersection_test res;
+ res = GeomUtils::intersectRayPlane(oppositeEdge->GetaVertex()->GetVertex(), v1v2, e2, -(v->GetVertex()*e2),
+ t, 1.0e-06);
+ if ((res == GeomUtils::DO_INTERSECT) && (t >= 0.0) && (t <= 1.0)) {
+ vector<WXFaceLayer*> second_ridge_layer;
+ wxf->retrieveSmoothLayers(Nature::RIDGE, second_ridge_layer);
+ if (second_ridge_layer.size() != 1)
+ continue;
+ Face_Curvature_Info *second_layer_info = (Face_Curvature_Info*)second_ridge_layer[0]->userdata;
+
+ unsigned index1 = wxf->GetIndex(oppositeEdge->GetaVertex());
+ unsigned index2 = wxf->GetIndex(oppositeEdge->GetbVertex());
+ real K1_1 = second_layer_info->vec_curvature_info[index1]->K1;
+ real K1_2 = second_layer_info->vec_curvature_info[index2]->K1;
+ real K1 = (1.0 - t) * K1_1 + t * K1_2;
+ Vec3r inter((1.0 - t) * oppositeEdge->GetaVertex()->GetVertex() +
+ t * oppositeEdge->GetbVertex()->GetVertex());
+ Vec3r vtmp(inter - v->GetVertex());
+ // is it K1_a or K1_b ?
+ if (vtmp * e1 > 0) {
+ K1_b = K1;
+ Inter_b = inter;
+ }
+ else {
+ K1_a = K1;
+ Inter_a = inter;
+ }
+ }
+ }
+ // Once we have K1 along the 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;
+ //real threshold = _meanK1;
+ //if ((fabs(K1_b) > threshold) || ((fabs(K1_a) > threshold)))
+ d = (K1_b) - (K1_a) / (Inter_b - Inter_a).norm();
+ faceLayer->PushDotP(d);
+ //faceLayer->PushDotP(layer_info->vec_curvature_info[i]->K1);
+ }
+
+ // Make the values relevant by checking whether all principal directions have the "same" direction:
+ Vec3r e0((layer_info->vec_curvature_info[0]->K1 * layer_info->vec_curvature_info[0]->e1));
+ e0.normalize();
+ Vec3r e1((layer_info->vec_curvature_info[1]->K1 * layer_info->vec_curvature_info[1]->e1));
+ e1.normalize();
+ Vec3r e2((layer_info->vec_curvature_info[2]->K1 * layer_info->vec_curvature_info[2]->e1));
+ e2.normalize();
+ if (e0 * e1 < 0)
+ // invert dotP[1]
+ faceLayer->ReplaceDotP(1, -faceLayer->dotP(1));
+ if (e0 * e2 < 0)
+ // invert dotP[2]
+ faceLayer->ReplaceDotP(2, -faceLayer->dotP(2));
+
+#if 0 // remove the weakest values;
+ real minDiff = (_maxK1 - _minK1) / 10.0;
+ real minDiff = _meanK1;
+ if ((faceLayer->dotP(0) < minDiff) && (faceLayer->dotP(1) < minDiff) && (faceLayer->dotP(2) < minDiff)) {
+ faceLayer->ReplaceDotP(0, 0);
+ faceLayer->ReplaceDotP(1, 0);
+ faceLayer->ReplaceDotP(2, 0);
+ }
+#endif
+}
+#endif
+
+// SUGGESTIVE CONTOURS
+//////////////////////
+
+void FEdgeXDetector::processSuggestiveContourShape(WXShape *iWShape)
+{
+ // Here the curvatures must already have been computed
+ vector<WFace*>& wfaces = iWShape->GetFaceList();
+ vector<WFace*>::iterator f, fend;
+ for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
+ ProcessSuggestiveContourFace((WXFace *)(*f));
+ }
+}
+
+void FEdgeXDetector::ProcessSuggestiveContourFace(WXFace *iFace)
+{
+ WXFaceLayer *faceLayer = new WXFaceLayer(iFace, Nature::SUGGESTIVE_CONTOUR, true);
+ iFace->AddSmoothLayer(faceLayer);
+
+ unsigned int numVertices = iFace->numberOfVertices();
+ for (unsigned int i = 0; i < numVertices; ++i) {
+ WVertex *wv = iFace->GetVertex(i);
+ WXVertex *wxv = dynamic_cast<WXVertex*>(wv);
+ faceLayer->PushDotP(wxv->curvatures()->Kr);
+ }
+
+#if 0 // FIXME: find a more clever way to compute the threshold
+ real threshold = _meanKr;
+ if (faceLayer->nPosDotP()!=numVertices) {
+ if ((fabs(faceLayer->dotP(0)) < threshold) && (fabs(faceLayer->dotP(1)) < threshold) &&
+ (fabs(faceLayer->dotP(2)) < threshold)) {
+ faceLayer->ReplaceDotP(0, 0);
+ faceLayer->ReplaceDotP(1, 0);
+ faceLayer->ReplaceDotP(2, 0);
+ }
+ }
+#endif
+}
+
+void FEdgeXDetector::postProcessSuggestiveContourShape(WXShape *iShape)
+{
+ vector<WFace*>& wfaces = iShape->GetFaceList();
+ vector<WFace*>::iterator f, fend;
+ for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
+ postProcessSuggestiveContourFace((WXFace *)(*f));
+ }
+}
+
+void FEdgeXDetector::postProcessSuggestiveContourFace(WXFace *iFace)
+{
+ // Compute the derivative of the radial curvature in the radial direction, at the two extremities
+ // of the smooth edge.
+ // If the derivative is smaller than a given threshold _kr_derivative_epsilon, discard the edge.
+
+ // Find the suggestive contour layer of the face (zero or one edge).
+ vector<WXFaceLayer*> sc_layers;
+ iFace->retrieveSmoothEdgesLayers(Nature::SUGGESTIVE_CONTOUR, sc_layers);
+ if (sc_layers.empty())
+ return;
+
+ WXFaceLayer *sc_layer;
+ sc_layer = sc_layers[0];
+
+ // Compute the derivative value at each vertex of the face, and add it in a vector.
+ vector<real> kr_derivatives;
+
+ unsigned vertices_nb = iFace->numberOfVertices();
+ WXVertex *v, *opposite_vertex_a, *opposite_vertex_b;
+ WXFace *wxf;
+ WOEdge *opposite_edge;
+ Vec3r normal_vec, radial_normal_vec, er_vec, v_vec, inter, inter1, inter2, tmp_vec;
+ GeomUtils::intersection_test res;
+ real kr(0), kr1(0), kr2(0), t;
+
+ for (unsigned int i = 0; i < vertices_nb; ++i) {
+ v = (WXVertex *)(iFace->GetVertex(i));
+
+ // v is a singular vertex, skip it.
+ if (v->isBoundary()) {
+ kr_derivatives.push_back(0);
+ continue;
+ }
+
+ v_vec = v->GetVertex();
+ er_vec = v->curvatures()->er;
+
+ // For each vertex, iterate on its adjacent faces.
+ for (WVertex::face_iterator fit = v->faces_begin(), fitend = v->faces_end(); fit != fitend; ++fit) {
+ wxf = dynamic_cast<WXFace*>(*fit);
+ if (!wxf->getOppositeEdge(v, opposite_edge))
+ continue;
+
+ opposite_vertex_a = (WXVertex *)opposite_edge->GetaVertex();
+ opposite_vertex_b = (WXVertex *)opposite_edge->GetbVertex();
+ normal_vec = wxf->GetVertexNormal(v); // FIXME: what about e1 ^ e2 ?
+ radial_normal_vec = er_vec ^ normal_vec;
+
+ // Test wether the radial plan intersects with the edge at the opposite of v.
+ res = GeomUtils::intersectRayPlane(opposite_vertex_a->GetVertex(), opposite_edge->GetVec(),
+ radial_normal_vec, -(v_vec * radial_normal_vec),
+ t, 1.0e-06);
+
+ // If there is an intersection, compute the value of the derivative ath that point.
+ if ((res == GeomUtils::DO_INTERSECT) && (t >= 0) && (t <= 1)) {
+ kr = t * opposite_vertex_a->curvatures()->Kr + (1 - t) * opposite_vertex_b->curvatures()->Kr;
+ inter = opposite_vertex_a->GetVertex() + t * opposite_edge->GetVec();
+ tmp_vec = inter - v->GetVertex();
+ // Is it kr1 or kr2?
+ if (tmp_vec * er_vec > 0) {
+ kr2 = kr;
+ inter2 = inter;
+ }
+ else {
+ kr1 = kr;
+ inter1 = inter;
+ }
+ }
+ }
+
+ // Now we have kr1 and kr2 along the radial direction, for one vertex of iFace.
+ // We have to compute the derivative of kr for that vertex, equal to:
+ // (kr2 - kr1) / dist(inter1, inter2).
+ // Then we add it to the vector of derivatives.
+ v->curvatures()->dKr = (kr2 - kr1) / (inter2 - inter1).norm();
+ kr_derivatives.push_back(v->curvatures()->dKr);
+ }
+
+ // At that point, we have the derivatives for each vertex of iFace.
+ // All we have to do now is to use linear interpolation to compute the values at the extremities of the smooth edge.
+ WXSmoothEdge *sc_edge = sc_layer->getSmoothEdge();
+ WOEdge *sc_oedge = sc_edge->woea();
+ t = sc_edge->ta();
+ if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] +
+ (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] < _kr_derivative_epsilon)
+ {
+ sc_layer->removeSmoothEdge();
+ return;
+ }
+ sc_oedge = sc_edge->woeb();
+ t = sc_edge->tb();
+ if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] +
+ (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] < _kr_derivative_epsilon)
+ {
+ sc_layer->removeSmoothEdge();
+ }
+}
+
+// MATERIAL_BOUNDARY
+////////////////////
+void FEdgeXDetector::processMaterialBoundaryShape(WXShape *iWShape)
+{
+ if (!_computeViewIndependant)
+ return;
+ // Make a pass on the edges to detect material boundaries
+ vector<WEdge*>::iterator we, weend;
+ vector<WEdge*> &wedges = iWShape->getEdgeList();
+ for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
+ ProcessMaterialBoundaryEdge((WXEdge *)(*we));
+ }
+}
+
+void FEdgeXDetector::ProcessMaterialBoundaryEdge(WXEdge *iEdge)
+{
+ // check whether the edge is a material boundary?
+ WFace *aFace = iEdge->GetaFace();
+ WFace *bFace = iEdge->GetbFace();
+ if (aFace && bFace && aFace->frs_materialIndex() != bFace->frs_materialIndex()) {
+ iEdge->AddNature(Nature::MATERIAL_BOUNDARY);
+ }
+}
+
+// EDGE MARKS
+/////////////
+void FEdgeXDetector::processEdgeMarksShape(WXShape *iShape)
+{
+ // Make a pass on the edges to detect material boundaries
+ vector<WEdge*>::iterator we, weend;
+ vector<WEdge*> &wedges = iShape->getEdgeList();
+ for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
+ ProcessEdgeMarks((WXEdge *)(*we));
+ }
+}
+
+void FEdgeXDetector::ProcessEdgeMarks(WXEdge *iEdge)
+{
+ if (iEdge->GetMark()) {
+ iEdge->AddNature(Nature::EDGE_MARK);
+ }
+}
+
+// Build Smooth edges
+/////////////////////
+void FEdgeXDetector::buildSmoothEdges(WXShape *iShape)
+{
+ bool hasSmoothEdges = false;
+
+ // Make a last pass to build smooth edges from the previous stored values:
+ //--------------------------------------------------------------------------
+ vector<WFace*>& wfaces = iShape->GetFaceList();
+ for (vector<WFace *>::iterator f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
+ vector<WXFaceLayer *>& faceLayers = ((WXFace *)(*f))->getSmoothLayers();
+ for (vector<WXFaceLayer *>::iterator wxfl = faceLayers.begin(), wxflend = faceLayers.end();
+ wxfl != wxflend;
+ ++wxfl)
+ {
+ if ((*wxfl)->BuildSmoothEdge())
+ hasSmoothEdges = true;
+ }
+ }
+
+ if (hasSmoothEdges && !_computeRidgesAndValleys && !_computeSuggestiveContours) {
+ vector<WVertex *>& wvertices = iShape->getVertexList();
+ for (vector<WVertex*>::iterator wv = wvertices.begin(), wvend = wvertices.end(); wv != wvend; ++wv) {
+ // Compute curvatures
+ WXVertex *wxv = dynamic_cast<WXVertex *>(*wv);
+ computeCurvatures(wxv);
+ }
+ _meanK1 /= (real)(_nPoints);
+ _meanKr /= (real)(_nPoints);
+ }
+}
diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.h b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h
new file mode 100644
index 00000000000..5df9423b4cf
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h
@@ -0,0 +1,241 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_FEDGE_X_DETECTOR_H__
+#define __FREESTYLE_FEDGE_X_DETECTOR_H__
+
+/** \file blender/freestyle/intern/view_map/FEdgeXDetector.h
+ * \ingroup freestyle
+ * \brief Detects/flags/builds extended features edges on the WXEdge structure
+ * \author Stephane Grabli
+ * \date 26/10/2003
+ */
+
+#include <vector>
+
+#include "../geometry/Geom.h"
+
+#include "../system/FreestyleConfig.h"
+#include "../system/ProgressBar.h"
+#include "../system/RenderMonitor.h"
+
+#include "../winged_edge/Curvature.h"
+#include "../winged_edge/WXEdge.h"
+
+using namespace Geometry;
+
+/*! This class takes as input a WXEdge structure and fills it */
+class LIB_VIEW_MAP_EXPORT FEdgeXDetector
+{
+public:
+ FEdgeXDetector()
+ {
+ _pProgressBar = NULL;
+ _pRenderMonitor = NULL;
+ _computeViewIndependant = true;
+ _bbox_diagonal = 1.0;
+ _meanEdgeSize = 0;
+ _computeRidgesAndValleys = true;
+ _computeSuggestiveContours = true;
+ _computeMaterialBoundaries = true;
+ _sphereRadius = 1.0;
+ _orthographicProjection = false;
+ _faceSmoothness = false;
+ _changes = false;
+ _kr_derivative_epsilon = 0.0;
+ _creaseAngle = 0.7; // angle of 134.43 degrees
+ }
+
+ virtual ~FEdgeXDetector() {}
+
+ /*! Process shapes from a WingedEdge containing a list of WShapes */
+ virtual void processShapes(WingedEdge&);
+
+ // GENERAL STUFF
+ virtual void preProcessShape(WXShape *iShape);
+ virtual void preProcessFace(WXFace *iFace);
+ virtual void computeCurvatures(WXVertex *iVertex);
+
+ // SILHOUETTE
+ virtual void processSilhouetteShape(WXShape *iShape);
+ virtual void ProcessSilhouetteFace(WXFace *iFace);
+ virtual void ProcessSilhouetteEdge(WXEdge *iEdge);
+
+ // CREASE
+ virtual void processCreaseShape(WXShape *iShape);
+ virtual void ProcessCreaseEdge(WXEdge *iEdge);
+
+ /*! Sets the minimum angle for detecting crease edges
+ * \param angle
+ * The angular threshold in degrees (between 0 and 180) for detecting crease edges. An edge is considered
+ * 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)
+ {
+ if (angle < 0.0)
+ angle = 0.0;
+ else if (angle > 180.0)
+ angle = 180.0;
+ angle = cos(M_PI * (180.0 - angle) / 180.0);
+ if (angle != _creaseAngle) {
+ _creaseAngle = angle;
+ _changes = true;
+ }
+ }
+
+ // BORDER
+ virtual void processBorderShape(WXShape *iShape);
+ virtual void ProcessBorderEdge(WXEdge *iEdge);
+
+ // RIDGES AND VALLEYS
+ virtual void processRidgesAndValleysShape(WXShape *iShape);
+ virtual void ProcessRidgeFace(WXFace *iFace);
+
+ // SUGGESTIVE CONTOURS
+ virtual void processSuggestiveContourShape(WXShape *iShape);
+ virtual void ProcessSuggestiveContourFace(WXFace *iFace);
+ virtual void postProcessSuggestiveContourShape(WXShape *iShape);
+ virtual void postProcessSuggestiveContourFace(WXFace *iFace);
+ /*! Sets the minimal derivative of the radial curvature for suggestive contours
+ * \param dkr
+ * The minimal derivative of the radial curvature
+ */
+ inline void setSuggestiveContourKrDerivativeEpsilon(real dkr)
+ {
+ if (dkr != _kr_derivative_epsilon) {
+ _kr_derivative_epsilon = dkr;
+ _changes = true;
+ }
+ }
+
+ // MATERIAL BOUNDARY
+ virtual void processMaterialBoundaryShape(WXShape *iWShape);
+ virtual void ProcessMaterialBoundaryEdge(WXEdge *iEdge);
+
+ // EDGE MARKS
+ virtual void processEdgeMarksShape(WXShape *iShape);
+ virtual void ProcessEdgeMarks(WXEdge *iEdge);
+
+ // EVERYBODY
+ virtual void buildSmoothEdges(WXShape *iShape);
+
+ /*! Sets the current viewpoint */
+ inline void setViewpoint(const Vec3r& ivp)
+ {
+ _Viewpoint = ivp;
+ }
+
+ inline void enableOrthographicProjection(bool b)
+ {
+ _orthographicProjection = b;
+ }
+
+ inline void enableRidgesAndValleysFlag(bool b)
+ {
+ _computeRidgesAndValleys = b;
+ }
+
+ inline void enableSuggestiveContours(bool b)
+ {
+ _computeSuggestiveContours = b;
+ }
+
+ inline void enableMaterialBoundaries(bool b)
+ {
+ _computeMaterialBoundaries = b;
+ }
+
+ inline void enableFaceSmoothness(bool b)
+ {
+ if (b != _faceSmoothness) {
+ _faceSmoothness = b;
+ _changes = true;
+ }
+ }
+
+ inline void enableFaceMarks(bool b)
+ {
+ if (b != _faceMarks) {
+ _faceMarks = b;
+ _changes = true;
+ }
+ }
+
+ /*! Sets the radius of the geodesic sphere around each vertex (for the curvature computation)
+ * \param r
+ * The radius of the sphere expressed as a ratio of the mean edge size
+ */
+ inline void setSphereRadius(real r)
+ {
+ if (r != _sphereRadius) {
+ _sphereRadius = r;
+ _changes = true;
+ }
+ }
+
+ inline void setProgressBar(ProgressBar *iProgressBar)
+ {
+ _pProgressBar = iProgressBar;
+ }
+
+ inline void setRenderMonitor(RenderMonitor *iRenderMonitor)
+ {
+ _pRenderMonitor = iRenderMonitor;
+ }
+
+protected:
+ Vec3r _Viewpoint;
+ real _bbox_diagonal; // diagonal of the current processed shape bbox
+ //oldtmp values
+ bool _computeViewIndependant;
+ real _meanK1;
+ real _meanKr;
+ real _minK1;
+ real _minKr;
+ real _maxK1;
+ real _maxKr;
+ unsigned _nPoints;
+ real _meanEdgeSize;
+ bool _orthographicProjection;
+
+ bool _computeRidgesAndValleys;
+ bool _computeSuggestiveContours;
+ 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
+ bool _changes;
+
+ real _kr_derivative_epsilon;
+
+ ProgressBar *_pProgressBar;
+ RenderMonitor *_pRenderMonitor;
+};
+
+#endif // __FREESTYLE_FEDGE_X_DETECTOR_H__
diff --git a/source/blender/freestyle/intern/view_map/Functions0D.cpp b/source/blender/freestyle/intern/view_map/Functions0D.cpp
new file mode 100644
index 00000000000..527d67cee2a
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Functions0D.cpp
@@ -0,0 +1,376 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/Functions0D.cpp
+ * \ingroup freestyle
+ * \brief Functions taking 0D input
+ * \author Stephane Grabli
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+#include "Functions0D.h"
+#include "ViewMap.h"
+
+#include "BKE_global.h"
+
+using namespace std;
+
+namespace Functions0D {
+
+// Internal function
+FEdge *getFEdge(Interface0D& it1, Interface0D& it2)
+{
+ return it1.getFEdge(it2);
+}
+
+void getFEdges(Interface0DIterator& it, FEdge *&fe1, FEdge *&fe2)
+{
+ // count number of vertices
+ Interface0DIterator prev = it, next = it;
+ ++next;
+ int count = 1;
+ if (!it.isBegin() && !next.isEnd()) {
+ count = 3;
+ }
+ if (count < 3) {
+ // if we only have 2 vertices
+ FEdge *fe = 0;
+ Interface0DIterator tmp = it;
+ if (it.isBegin()) {
+ ++tmp;
+ fe = it->getFEdge(*tmp);
+ }
+ else {
+ --tmp;
+ fe = it->getFEdge(*tmp);
+ }
+ fe1 = fe;
+ fe2 = NULL;
+ }
+ else {
+ // we have more than 2 vertices
+ bool begin = false, last = false;
+ Interface0DIterator previous = it;
+ if (!previous.isBegin())
+ --previous;
+ else
+ begin = true;
+ Interface0DIterator next = it;
+ ++next;
+ if (next.isEnd())
+ last = true;
+ if (begin) {
+ fe1 = it->getFEdge(*next);
+ fe2 = NULL;
+ }
+ else if (last) {
+ fe1 = previous->getFEdge(*it);
+ fe2 = NULL;
+ }
+ else {
+ fe1 = previous->getFEdge(*it);
+ fe2 = it->getFEdge(*next);
+ }
+ }
+}
+
+void getViewEdges(Interface0DIterator &it, ViewEdge *&ve1, ViewEdge *&ve2)
+{
+ FEdge *fe1, *fe2;
+ getFEdges(it, fe1, fe2);
+ ve1 = fe1->viewedge();
+ if (fe2 != NULL) {
+ ve2 = fe2->viewedge();
+ if (ve2 == ve1)
+ ve2 = NULL;
+ }
+ else {
+ ve2 = NULL;
+ }
+}
+
+ViewShape *getShapeF0D(Interface0DIterator& it)
+{
+ ViewEdge *ve1, *ve2;
+ getViewEdges(it, ve1, ve2);
+ return ve1->viewShape();
+}
+
+void getOccludersF0D(Interface0DIterator& it, set<ViewShape*>& oOccluders)
+{
+ ViewEdge *ve1, *ve2;
+ getViewEdges(it, ve1, ve2);
+ occluder_container::const_iterator oit = ve1->occluders_begin();
+ occluder_container::const_iterator oitend = ve1->occluders_end();
+
+ for (; oit != oitend; ++oit)
+ oOccluders.insert((*oit));
+
+ if (ve2 != NULL) {
+ oit = ve2->occluders_begin();
+ oitend = ve2->occluders_end();
+ for (; oit != oitend; ++oit)
+ oOccluders.insert((*oit));
+ }
+}
+
+ViewShape *getOccludeeF0D(Interface0DIterator& it)
+{
+ ViewEdge *ve1, *ve2;
+ getViewEdges(it, ve1, ve2);
+ ViewShape *aShape = ve1->aShape();
+ return aShape;
+}
+
+//
+int VertexOrientation2DF0D::operator()(Interface0DIterator& iter)
+{
+ Vec2f A, C;
+ Vec2f B(iter->getProjectedX(), iter->getProjectedY());
+ if (iter.isBegin()) {
+ A = Vec2f(iter->getProjectedX(), iter->getProjectedY());
+ }
+ else {
+ Interface0DIterator previous = iter;
+ --previous ;
+ A = Vec2f(previous->getProjectedX(), previous->getProjectedY());
+ }
+ Interface0DIterator next = iter;
+ ++next;
+ if (next.isEnd())
+ C = Vec2f(iter->getProjectedX(), iter->getProjectedY());
+ else
+ C = Vec2f(next->getProjectedX(), next->getProjectedY());
+
+ Vec2f AB(B - A);
+ if (AB.norm() != 0)
+ AB.normalize();
+ Vec2f BC(C - B);
+ if (BC.norm() != 0)
+ BC.normalize();
+ result = AB + BC;
+ if (result.norm() != 0)
+ result.normalize();
+ return 0;
+}
+
+int VertexOrientation3DF0D::operator()(Interface0DIterator& iter)
+{
+ Vec3r A, C;
+ Vec3r B(iter->getX(), iter->getY(), iter->getZ());
+ if (iter.isBegin()) {
+ A = Vec3r(iter->getX(), iter->getY(), iter->getZ());
+ }
+ else {
+ Interface0DIterator previous = iter;
+ --previous ;
+ A = Vec3r(previous->getX(), previous->getY(), previous->getZ());
+ }
+ Interface0DIterator next = iter;
+ ++next ;
+ if (next.isEnd())
+ C = Vec3r(iter->getX(), iter->getY(), iter->getZ());
+ else
+ C = Vec3r(next->getX(), next->getY(), next->getZ());
+
+ Vec3r AB(B - A);
+ if (AB.norm() != 0)
+ AB.normalize();
+ Vec3r BC(C - B);
+ if (BC.norm() != 0)
+ BC.normalize();
+ result = AB + BC;
+ if (result.norm() != 0)
+ result.normalize();
+ return 0;
+}
+
+int Curvature2DAngleF0D::operator()(Interface0DIterator& iter)
+{
+ Interface0DIterator tmp1 = iter, tmp2 = iter;
+ ++tmp2;
+ unsigned count = 1;
+ while ((!tmp1.isBegin()) && (count < 3)) {
+ --tmp1;
+ ++count;
+ }
+ while ((!tmp2.isEnd()) && (count < 3)) {
+ ++tmp2;
+ ++count;
+ }
+ if (count < 3) {
+ // if we only have 2 vertices
+ result = 0;
+ return 0;
+ }
+
+ Interface0DIterator v = iter;
+ if (iter.isBegin())
+ ++v;
+ Interface0DIterator next = v;
+ ++next;
+ if (next.isEnd()) {
+ next = v;
+ --v;
+ }
+ Interface0DIterator prev = v;
+ --prev;
+
+ Vec2r A(prev->getProjectedX(), prev->getProjectedY());
+ Vec2r B(v->getProjectedX(), v->getProjectedY());
+ Vec2r C(next->getProjectedX(), next->getProjectedY());
+ Vec2r AB(B - A);
+ Vec2r BC(C - B);
+ Vec2r N1(-AB[1], AB[0]);
+ if (N1.norm() != 0)
+ N1.normalize();
+ Vec2r N2(-BC[1], BC[0]);
+ if (N2.norm() != 0)
+ N2.normalize();
+ if ((N1.norm() == 0) && (N2.norm() == 0)) {
+ Exception::raiseException();
+ result = 0;
+ return -1;
+ }
+ double cosin = N1 * N2;
+ if (cosin > 1)
+ cosin = 1;
+ if (cosin < -1)
+ cosin = -1;
+ result = acos(cosin);
+ return 0;
+}
+
+int ZDiscontinuityF0D::operator()(Interface0DIterator& iter)
+{
+ FEdge *fe1, *fe2;
+ getFEdges(iter, fe1, fe2);
+ result = fe1->z_discontinuity();
+ if (fe2 != NULL) {
+ result += fe2->z_discontinuity();
+ result /= 2.0f;
+ }
+ return 0;
+}
+
+int Normal2DF0D::operator()(Interface0DIterator& iter)
+{
+ FEdge *fe1, *fe2;
+ getFEdges(iter, fe1, fe2);
+ Vec3f e1(fe1->orientation2d());
+ Vec2f n1(e1[1], -e1[0]);
+ Vec2f n(n1);
+ if (fe2 != NULL) {
+ Vec3f e2(fe2->orientation2d());
+ Vec2f n2(e2[1], -e2[0]);
+ n += n2;
+ }
+ n.normalize();
+ result = n;
+ return 0;
+}
+
+int MaterialF0D::operator()(Interface0DIterator& iter)
+{
+ FEdge *fe1, *fe2;
+ getFEdges(iter, fe1, fe2);
+ if (fe1 == NULL)
+ return -1;
+ if (fe1->isSmooth())
+ result = ((FEdgeSmooth *)fe1)->frs_material();
+ else
+ result = ((FEdgeSharp *)fe1)->bFrsMaterial();
+#if 0
+ const SShape *sshape = getShapeF0D(iter);
+ return sshape->material();
+#endif
+ return 0;
+}
+
+int ShapeIdF0D::operator()(Interface0DIterator& iter)
+{
+ ViewShape *vshape = getShapeF0D(iter);
+ result = vshape->getId();
+ return 0;
+}
+
+int QuantitativeInvisibilityF0D::operator()(Interface0DIterator& iter)
+{
+ ViewEdge *ve1, *ve2;
+ getViewEdges(iter, ve1, ve2);
+ unsigned int qi1, qi2;
+ qi1 = ve1->qi();
+ if (ve2 != NULL) {
+ qi2 = ve2->qi();
+ if (qi2 != qi1) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "QuantitativeInvisibilityF0D: ambiguous evaluation for point " << iter->getId() << endl;
+ }
+ }
+ }
+ result = qi1;
+ return 0;
+}
+
+int CurveNatureF0D::operator()(Interface0DIterator& iter)
+{
+ Nature::EdgeNature nat = 0;
+ ViewEdge *ve1, *ve2;
+ getViewEdges(iter, ve1, ve2);
+ nat |= ve1->getNature();
+ if (ve2 != NULL)
+ nat |= ve2->getNature();
+ result = nat;
+ return 0;
+}
+
+int GetOccludersF0D::operator()(Interface0DIterator& iter)
+{
+ set<ViewShape*> occluders;
+ getOccludersF0D(iter, occluders);
+ result.clear();
+ //vsOccluders.insert(vsOccluders.begin(), occluders.begin(), occluders.end());
+ for (set<ViewShape*>::iterator it = occluders.begin(), itend = occluders.end(); it != itend; ++it) {
+ result.push_back((*it));
+ }
+ return 0;
+}
+
+int GetShapeF0D::operator()(Interface0DIterator& iter)
+{
+ result = getShapeF0D(iter);
+ return 0;
+}
+
+int GetOccludeeF0D::operator()(Interface0DIterator& iter)
+{
+ result = getOccludeeF0D(iter);
+ return 0;
+}
+
+} // end of namespace Functions0D
diff --git a/source/blender/freestyle/intern/view_map/Functions0D.h b/source/blender/freestyle/intern/view_map/Functions0D.h
new file mode 100644
index 00000000000..03ab008736c
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Functions0D.h
@@ -0,0 +1,532 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_FUNCTIONS_0D_H__
+#define __FREESTYLE_FUNCTIONS_0D_H__
+
+/** \file blender/freestyle/intern/view_map/Functions0D.h
+ * \ingroup freestyle
+ * \brief Functions taking 0D input
+ * \author Stephane Grabli
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+#include <set>
+#include <vector>
+
+#include "Interface0D.h"
+
+#include "../geometry/Geom.h"
+
+#include "../python/Director.h"
+
+#include "../scene_graph/FrsMaterial.h"
+
+#include "../system/Exception.h"
+#include "../system/Precision.h"
+
+class FEdge;
+class ViewEdge;
+class SShape;
+
+using namespace Geometry;
+
+//
+// UnaryFunction0D (base class for functions in 0D)
+//
+///////////////////////////////////////////////////////////
+
+/*! Base class for Unary Functions (functors) working on Interface0DIterator.
+ * A unary function will be used by calling its operator() on an Interface0DIterator.
+ * \attention In the scripting language, there exists several prototypes depending on the returned value type.
+ * For example, you would inherit from a UnaryFunction0DDouble if you wish to define a function that returns a double.
+ * The different existing prototypes are:
+ * - UnaryFunction0DVoid
+ * - UnaryFunction0DUnsigned
+ * - UnaryFunction0DReal
+ * - UnaryFunction0DFloat
+ * - UnaryFunction0DDouble
+ * - UnaryFunction0DVec2f
+ * - UnaryFunction0DVec3f
+ */
+template <class T>
+class /*LIB_VIEW_MAP_EXPORT*/ UnaryFunction0D
+{
+public:
+ T result;
+ PyObject *py_uf0D;
+
+ /*! The type of the value returned by the functor. */
+ typedef T ReturnedValueType;
+
+ /*! Default constructor. */
+ UnaryFunction0D()
+ {
+ py_uf0D = NULL;
+ }
+
+ /*! Destructor; */
+ virtual ~UnaryFunction0D() {}
+
+ /*! Returns the string "UnaryFunction0D" */
+ virtual string getName() const
+ {
+ return "UnaryFunction0D";
+ }
+
+ /*! The operator ().
+ * \param iter
+ * An Interface0DIterator pointing onto the point at which we wish to evaluate the function.
+ * \return the result of the function of type T.
+ */
+ virtual int operator()(Interface0DIterator& iter)
+ {
+ return Director_BPy_UnaryFunction0D___call__(this, py_uf0D, iter);
+ }
+};
+
+#ifdef SWIG
+%feature("director") UnaryFunction0D<void>;
+%feature("director") UnaryFunction0D<unsigned>;
+%feature("director") UnaryFunction0D<float>;
+%feature("director") UnaryFunction0D<double>;
+%feature("director") UnaryFunction0D<Vec2f>;
+%feature("director") UnaryFunction0D<Vec3f>;
+%feature("director") UnaryFunction0D<Id>;
+
+%template(UnaryFunction0DVoid) UnaryFunction0D<void>;
+%template(UnaryFunction0DUnsigned) UnaryFunction0D<unsigned>;
+%template(UnaryFunction0DFloat) UnaryFunction0D<float>;
+%template(UnaryFunction0DDouble) UnaryFunction0D<double>;
+%template(UnaryFunction0DVec2f) UnaryFunction0D<Vec2f>;
+%template(UnaryFunction0DVec3f) UnaryFunction0D<Vec3f>;
+%template(UnaryFunction0DId) UnaryFunction0D<Id>;
+%template(UnaryFunction0DViewShape) UnaryFunction0D<ViewShape*>;
+%template(UnaryFunction0DVectorViewShape) UnaryFunction0D<std::vector<ViewShape*> >;
+#endif // SWIG
+
+//
+// Functions definitions
+//
+///////////////////////////////////////////////////////////
+class ViewShape;
+
+namespace Functions0D {
+
+// GetXF0D
+/*! Returns the X 3D coordinate of an Interface0D. */
+class LIB_VIEW_MAP_EXPORT GetXF0D : public UnaryFunction0D<real>
+{
+public:
+ /*! Returns the string "GetXF0D" */
+ string getName() const
+ {
+ return "GetXF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter)
+ {
+ result = iter->getX();
+ return 0;
+ }
+};
+
+// GetYF0D
+/*! Returns the Y 3D coordinate of an Interface0D. */
+class LIB_VIEW_MAP_EXPORT GetYF0D : public UnaryFunction0D<real>
+{
+public:
+ /*! Returns the string "GetYF0D" */
+ string getName() const
+ {
+ return "GetYF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter)
+ {
+ result = iter->getY();
+ return 0;
+ }
+};
+
+// GetZF0D
+/*! Returns the Z 3D coordinate of an Interface0D. */
+class LIB_VIEW_MAP_EXPORT GetZF0D : public UnaryFunction0D<real>
+{
+public:
+ /*! Returns the string "GetZF0D" */
+ string getName() const
+ {
+ return "GetZF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter)
+ {
+ result = iter->getZ();
+ return 0;
+ }
+};
+
+// GetProjectedXF0D
+/*! Returns the X 3D projected coordinate of an Interface0D. */
+class LIB_VIEW_MAP_EXPORT GetProjectedXF0D : public UnaryFunction0D<real>
+{
+public:
+ /*! Returns the string "GetProjectedXF0D" */
+ string getName() const
+ {
+ return "GetProjectedXF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter)
+ {
+ result = iter->getProjectedX();
+ return 0;
+ }
+};
+
+// GetProjectedYF0D
+/*! Returns the Y projected 3D coordinate of an Interface0D. */
+class LIB_VIEW_MAP_EXPORT GetProjectedYF0D : public UnaryFunction0D<real>
+{
+public:
+ /*! Returns the string "GetProjectedYF0D" */
+ string getName() const
+ {
+ return "GetProjectedYF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter)
+ {
+ result = iter->getProjectedY();
+ return 0;
+ }
+};
+
+// GetProjectedZF0D
+/*! Returns the Z projected 3D coordinate of an Interface0D. */
+class LIB_VIEW_MAP_EXPORT GetProjectedZF0D : public UnaryFunction0D<real>
+{
+public:
+ /*! Returns the string "GetProjectedZF0D" */
+ string getName() const
+ {
+ return "GetProjectedZF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter)
+ {
+ result = iter->getProjectedZ();
+ return 0;
+ }
+};
+
+// GetCurvilinearAbscissaF0D
+/*! Returns the curvilinear abscissa of an Interface0D in the context of its 1D element. */
+class LIB_VIEW_MAP_EXPORT GetCurvilinearAbscissaF0D : public UnaryFunction0D<float>
+{
+public:
+ /*! Returns the string "GetCurvilinearAbscissaF0D" */
+ string getName() const
+ {
+ return "GetCurvilinearAbscissaF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter)
+ {
+ result = iter.t();
+ return 0;
+ }
+};
+
+// GetParameterF0D
+/*! Returns the parameter of an Interface0D in the context of its 1D element. */
+class LIB_VIEW_MAP_EXPORT GetParameterF0D : public UnaryFunction0D<float>
+{
+public:
+ /*! Returns the string "GetCurvilinearAbscissaF0D" */
+ string getName() const
+ {
+ return "GetParameterF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter)
+ {
+ result = iter.u();
+ return 0;
+ }
+};
+
+// VertexOrientation2DF0D
+/*! Returns a Vec2r giving the 2D oriented tangent to the 1D element to which the Interface0DIterator& belongs to and
+ * evaluated at the Interface0D pointed by this Interface0DIterator&.
+ */
+class LIB_VIEW_MAP_EXPORT VertexOrientation2DF0D : public UnaryFunction0D<Vec2f>
+{
+public:
+ /*! Returns the string "VertexOrientation2DF0D" */
+ string getName() const
+ {
+ return "VertexOrientation2DF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter);
+};
+
+// VertexOrientation3DF0D
+/*! Returns a Vec3r giving the 3D oriented tangent to the 1D element to which the Interface0DIterator& belongs to and
+ * evaluated at the Interface0D pointed by this Interface0DIterator&.
+ */
+class LIB_VIEW_MAP_EXPORT VertexOrientation3DF0D : public UnaryFunction0D<Vec3f>
+{
+public:
+ /*! Returns the string "VertexOrientation3DF0D" */
+ string getName() const
+ {
+ return "VertexOrientation3DF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter);
+};
+
+// Curvature2DAngleF0D
+/*! Returns a real giving the 2D curvature (as an angle) of the 1D element to which the Interface0DIterator&
+ * belongs to and evaluated at the Interface0D pointed by this Interface0DIterator&.
+ */
+class LIB_VIEW_MAP_EXPORT Curvature2DAngleF0D : public UnaryFunction0D<real>
+{
+public:
+ /*! Returns the string "Curvature2DAngleF0D" */
+ string getName() const
+ {
+ return "Curvature2DAngleF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter);
+};
+
+// ZDiscontinuity
+/*! Returns a real giving the distance between and Interface0D and the shape that lies behind (occludee).
+ * This distance is evaluated in the camera space and normalized between 0 and 1. Therefore, if no oject is occluded
+ * by the shape to which the Interface0D belongs to, 1 is returned.
+ */
+class LIB_VIEW_MAP_EXPORT ZDiscontinuityF0D : public UnaryFunction0D<real>
+{
+public:
+ /*! Returns the string "ZDiscontinuityF0D" */
+ string getName() const
+ {
+ return "ZDiscontinuityF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter);
+};
+
+// Normal2DF0D
+/*! Returns a Vec2f giving the normalized 2D normal to the 1D element to which the Interface0DIterator& belongs to and
+ * evaluated at the Interface0D pointed by this Interface0DIterator&.
+ */
+class LIB_VIEW_MAP_EXPORT Normal2DF0D : public UnaryFunction0D<Vec2f>
+{
+public:
+ /*! Returns the string "Normal2DF0D" */
+ string getName() const
+ {
+ return "Normal2DF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter);
+};
+
+// MaterialF0D
+/*! Returns the material of the object evaluated at the Interface0D.
+ * This evaluation can be ambiguous (in the case of a TVertex for example.
+ * This functor tries to remove this ambiguity using the context offered by the 1D element to which the
+ * Interface0DIterator& belongs to and by arbitrary chosing the material of the face that lies on its left when
+ * following the 1D element if there are two different materials on each side of the point.
+ * However, there still can be problematic cases, and the user willing to deal with this cases in a specific way
+ * should implement its own getMaterial functor.
+ */
+class LIB_VIEW_MAP_EXPORT MaterialF0D : public UnaryFunction0D<FrsMaterial>
+{
+public:
+ /*! Returns the string "MaterialF0D" */
+ string getName() const
+ {
+ return "MaterialF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter);
+};
+
+// ShapeIdF0D
+/*! Returns the Id of the Shape the Interface0D belongs to.
+ * This evaluation can be ambiguous (in the case of a TVertex for example).
+ * This functor tries to remove this ambiguity using the context offered by the 1D element to which the
+ * Interface0DIterator& belongs to.
+ * However, there still can be problematic cases, and the user willing to deal with this cases in a specific way
+ * should implement its own getShapeIdF0D functor.
+ */
+class LIB_VIEW_MAP_EXPORT ShapeIdF0D : public UnaryFunction0D<Id>
+{
+public:
+ /*! Returns the string "ShapeIdF0D" */
+ string getName() const
+ {
+ return "ShapeIdF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter);
+};
+
+// QiF0D
+/*! Returns the quantitative invisibility of this Interface0D.
+* This evaluation can be ambiguous (in the case of a TVertex for example).
+* This functor tries to remove this ambiguity using the context offered by the 1D element to which the
+* Interface0DIterator& belongs to.
+* However, there still can be problematic cases, and the user willing to deal with this cases in a specific way
+* should implement its own getQIF0D functor.
+*/
+class LIB_VIEW_MAP_EXPORT QuantitativeInvisibilityF0D : public UnaryFunction0D<unsigned int>
+{
+public:
+ /*! Returns the string "QuantitativeInvisibilityF0D" */
+ string getName() const
+ {
+ return "QuantitativeInvisibilityF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter);
+};
+
+// CurveNatureF0D
+/*! Returns the Nature::EdgeNature of the 1D element the Interface0DIterator& belongs to. */
+class LIB_VIEW_MAP_EXPORT CurveNatureF0D : public UnaryFunction0D<Nature::EdgeNature>
+{
+public:
+ /*! Returns the string "QuantitativeInvisibilityF0D" */
+ string getName() const
+ {
+ return "CurveNatureF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter);
+};
+
+// GetShapeF0D
+/*! Returns the ViewShape* containing the Interface0D */
+class LIB_VIEW_MAP_EXPORT GetShapeF0D : public UnaryFunction0D< ViewShape*>
+{
+public:
+ /*! Returns the string "GetShapeF0D" */
+ string getName() const
+ {
+ return "GetShapeF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter);
+};
+
+// GetOccludersF0D
+/*! Returns a vector containing the ViewShape* occluding the Interface0D */
+class LIB_VIEW_MAP_EXPORT GetOccludersF0D : public UnaryFunction0D< std::vector<ViewShape*> >
+{
+public:
+ /*! Returns the string "GetOccludersF0D" */
+ string getName() const
+ {
+ return "GetOccludersF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter);
+};
+
+// GetOccludeeF0D
+/*! Returns the ViewShape* "occluded" by the Interface0D */
+class LIB_VIEW_MAP_EXPORT GetOccludeeF0D: public UnaryFunction0D< ViewShape*>
+{
+public:
+ /*! Returns the string "GetOccludeeF0D" */
+ string getName() const
+ {
+ return "GetOccludeeF0D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface0DIterator& iter);
+};
+
+
+/////////////////////////// Internal ////////////////////////////
+
+// getFEdge
+LIB_VIEW_MAP_EXPORT
+FEdge *getFEdge(Interface0D& it1, Interface0D& it2);
+
+// getFEdges
+LIB_VIEW_MAP_EXPORT
+void getFEdges(Interface0DIterator& it, FEdge *&fe1, FEdge *&fe2);
+
+// getViewEdges
+LIB_VIEW_MAP_EXPORT
+void getViewEdges(Interface0DIterator& it, ViewEdge *&ve1, ViewEdge *&ve2);
+
+// getShapeF0D
+LIB_VIEW_MAP_EXPORT
+ViewShape *getShapeF0D(Interface0DIterator& it);
+
+// getOccludersF0D
+LIB_VIEW_MAP_EXPORT
+void getOccludersF0D(Interface0DIterator& it, std::set<ViewShape*>& oOccluders);
+
+// getOccludeeF0D
+LIB_VIEW_MAP_EXPORT
+ViewShape *getOccludeeF0D(Interface0DIterator& it);
+
+} // end of namespace Functions0D
+
+#endif // __FREESTYLE_FUNCTIONS_0D_H__
diff --git a/source/blender/freestyle/intern/view_map/Functions1D.cpp b/source/blender/freestyle/intern/view_map/Functions1D.cpp
new file mode 100644
index 00000000000..e8f18fe8077
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Functions1D.cpp
@@ -0,0 +1,271 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/Functions1D.cpp
+ * \ingroup freestyle
+ * \brief Functions taking 1D input
+ * \author Stephane Grabli
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+# include "Functions1D.h"
+
+using namespace std;
+
+namespace Functions1D {
+
+int GetXF1D::operator()(Interface1D& inter)
+{
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+}
+
+int GetYF1D::operator()(Interface1D& inter)
+{
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+}
+
+int GetZF1D::operator()(Interface1D& inter)
+{
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+}
+
+int GetProjectedXF1D::operator()(Interface1D& inter)
+{
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+}
+
+int GetProjectedYF1D::operator()(Interface1D& inter)
+{
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+}
+
+int GetProjectedZF1D::operator()(Interface1D& inter)
+{
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+}
+
+int Orientation2DF1D::operator()(Interface1D& inter)
+{
+ FEdge *fe = dynamic_cast<FEdge*>(&inter);
+ if (fe) {
+ Vec3r res = fe->orientation2d();
+ result = Vec2f(res[0], res[1]);
+ }
+ else {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ }
+ return 0;
+}
+
+int Orientation3DF1D::operator()(Interface1D& inter)
+{
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+}
+
+int ZDiscontinuityF1D::operator()(Interface1D& inter)
+{
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+}
+
+int QuantitativeInvisibilityF1D::operator()(Interface1D& inter)
+{
+ ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve) {
+ result = ve->qi();
+ return 0;
+ }
+ FEdge *fe = dynamic_cast<FEdge*>(&inter);
+ if (fe) {
+ result = ve->qi();
+ return 0;
+ }
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+}
+
+int CurveNatureF1D::operator()(Interface1D& inter)
+{
+ ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve) {
+ result = ve->getNature();
+ }
+ else {
+ // we return a nature that contains every natures of the viewedges spanned by the chain.
+ Nature::EdgeNature nat = Nature::NO_FEATURE;
+ Interface0DIterator it = inter.verticesBegin();
+ while (!it.isEnd()) {
+ nat |= _func(it);
+ ++it;
+ }
+ result = nat;
+ }
+ return 0;
+}
+
+int TimeStampF1D::operator()(Interface1D& inter)
+{
+ TimeStamp *timestamp = TimeStamp::instance();
+ inter.setTimeStamp(timestamp->getTimeStamp());
+ return 0;
+}
+
+int ChainingTimeStampF1D::operator()(Interface1D& inter)
+{
+ TimeStamp *timestamp = TimeStamp::instance();
+ ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve)
+ ve->setChainingTimeStamp(timestamp->getTimeStamp());
+ return 0;
+}
+
+int IncrementChainingTimeStampF1D::operator()(Interface1D& inter)
+{
+ ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve)
+ ve->setChainingTimeStamp(ve->getChainingTimeStamp() + 1);
+ return 0;
+}
+
+int GetShapeF1D::operator()(Interface1D& inter)
+{
+ vector<ViewShape*> shapesVector;
+ set<ViewShape*> shapesSet;
+ ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve) {
+ shapesVector.push_back(ve->viewShape());
+ }
+ else {
+ Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd();
+ for (; it != itend; ++it)
+ shapesSet.insert(Functions0D::getShapeF0D(it));
+ shapesVector.insert<set<ViewShape*>::iterator>(shapesVector.begin(), shapesSet.begin(), shapesSet.end());
+ }
+ result = shapesVector;
+ return 0;
+}
+
+int GetOccludersF1D::operator()(Interface1D& inter)
+{
+ vector<ViewShape*> shapesVector;
+ set<ViewShape*> shapesSet;
+ ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve) {
+ result = ve->occluders();
+ }
+ else {
+ Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd();
+ for (; it != itend; ++it) {
+ Functions0D::getOccludersF0D(it, shapesSet);
+ }
+ shapesVector.insert(shapesVector.begin(), shapesSet.begin(), shapesSet.end());
+ result = shapesVector;
+ }
+ return 0;
+}
+
+int GetOccludeeF1D::operator()(Interface1D& inter)
+{
+ vector<ViewShape*> shapesVector;
+ set<ViewShape*> shapesSet;
+ ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve) {
+ ViewShape *aShape = ve->aShape();
+ shapesVector.push_back(aShape);
+ }
+ else {
+ Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd();
+ for (; it != itend; ++it) {
+ shapesSet.insert(Functions0D::getOccludeeF0D(it));
+ }
+ shapesVector.insert<set<ViewShape*>::iterator>(shapesVector.begin(), shapesSet.begin(), shapesSet.end());
+ }
+ result = shapesVector;
+ return 0;
+}
+
+// Internal
+////////////
+
+void getOccludeeF1D(Interface1D& inter, set<ViewShape*>& oShapes)
+{
+ ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve) {
+ ViewShape *aShape = ve->aShape();
+ if (aShape == 0) {
+ oShapes.insert(0);
+ return;
+ }
+ oShapes.insert(aShape);
+ }
+ else {
+ Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd();
+ for (; it != itend; ++it)
+ oShapes.insert(Functions0D::getOccludeeF0D(it));
+ }
+}
+
+void getOccludersF1D(Interface1D& inter, set<ViewShape*>& oShapes)
+{
+ ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve) {
+ vector<ViewShape*>& occluders = ve->occluders();
+ oShapes.insert<vector<ViewShape*>::iterator>(occluders.begin(), occluders.end());
+ }
+ else {
+ Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd();
+ for (; it != itend; ++it) {
+ set<ViewShape*> shapes;
+ Functions0D::getOccludersF0D(it, shapes);
+ for (set<ViewShape*>::iterator s = shapes.begin(), send = shapes.end(); s != send; ++s)
+ oShapes.insert(*s);
+ }
+ }
+}
+
+void getShapeF1D(Interface1D& inter, set<ViewShape*>& oShapes)
+{
+ ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve) {
+ oShapes.insert(ve->viewShape());
+ }
+ else {
+ Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd();
+ for (; it != itend; ++it)
+ oShapes.insert(Functions0D::getShapeF0D(it));
+ }
+}
+
+} // end of namespace Functions1D
diff --git a/source/blender/freestyle/intern/view_map/Functions1D.h b/source/blender/freestyle/intern/view_map/Functions1D.h
new file mode 100644
index 00000000000..f1885aa1762
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Functions1D.h
@@ -0,0 +1,627 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_FUNCTIONS_1D_H__
+#define __FREESTYLE_FUNCTIONS_1D_H__
+
+/** \file blender/freestyle/intern/view_map/Functions1D.h
+ * \ingroup freestyle
+ * \brief Functions taking 1D input
+ * \author Stephane Grabli
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+#include "Functions0D.h"
+#include "Interface1D.h"
+#include "ViewMap.h"
+
+#include "../system/FreestyleConfig.h"
+#include "../system/Precision.h"
+#include "../system/TimeStamp.h"
+
+#include "../python/Director.h"
+
+//
+// UnaryFunction1D (base class for functions in 1D)
+//
+///////////////////////////////////////////////////////////
+
+/*! Base class for Unary Functions (functors) working on Interface1D.
+ * A unary function will be used by calling its operator() on an Interface1D.
+ * \attention In the scripting language, there exists several prototypes depending on the returned value type.
+ * For example, you would inherit from a UnaryFunction1DDouble if you wish to define a function that returns a double.
+ * The different existing prototypes are:
+ * - UnaryFunction1DVoid
+ * - UnaryFunction1DUnsigned
+ * - UnaryFunction1DReal
+ * - UnaryFunction1DFloat
+ * - UnaryFunction1DDouble
+ * - UnaryFunction1DVec2f
+ * - UnaryFunction1DVec3f
+ */
+template <class T>
+class /*LIB_VIEW_MAP_EXPORT*/ UnaryFunction1D
+{
+public:
+ T result;
+ PyObject *py_uf1D;
+
+ /*! The type of the value returned by the functor. */
+ typedef T ReturnedValueType;
+
+ /*! Default constructor */
+ UnaryFunction1D()
+ {
+ _integration = MEAN;
+ }
+
+ /*! Builds a UnaryFunction1D from an integration type.
+ * \param iType
+ * In case the result for the Interface1D would be obtained by evaluating a 0D function over the different
+ * Interface0D of the Interface1D, \a iType tells which integration method to use.
+ * The default integration method is the MEAN.
+ */
+ UnaryFunction1D(IntegrationType iType)
+ {
+ _integration = iType;
+ }
+
+ /*! destructor. */
+ virtual ~UnaryFunction1D() {}
+
+ /*! returns the string "UnaryFunction1D". */
+ virtual string getName() const
+ {
+ return "UnaryFunction1D";
+ }
+
+ /*! The operator ().
+ * \param inter
+ * The Interface1D on which we wish to evaluate the function.
+ * \return the result of the function of type T.
+ */
+ virtual int operator()(Interface1D& inter)
+ {
+ return Director_BPy_UnaryFunction1D___call__(this, py_uf1D, inter);
+ }
+
+ /*! Sets the integration method */
+ void setIntegrationType(IntegrationType integration)
+ {
+ _integration = integration;
+ }
+
+ /*! Returns the integration method. */
+ IntegrationType getIntegrationType() const
+ {
+ return _integration;
+ }
+
+protected:
+ IntegrationType _integration;
+};
+
+
+class UnaryFunction1D_void
+{
+public:
+ PyObject *py_uf1D;
+
+ UnaryFunction1D_void()
+ {
+ _integration = MEAN;
+ }
+
+ UnaryFunction1D_void(IntegrationType iType)
+ {
+ _integration = iType;
+ }
+
+ virtual ~UnaryFunction1D_void() {}
+
+ virtual string getName() const
+ {
+ return "UnaryFunction1D_void";
+ }
+
+ int operator()(Interface1D& inter)
+ {
+ return Director_BPy_UnaryFunction1D___call__(this, py_uf1D, inter);
+ }
+
+ void setIntegrationType(IntegrationType integration)
+ {
+ _integration = integration;
+ }
+
+ IntegrationType getIntegrationType() const
+ {
+ return _integration;
+ }
+
+protected:
+ IntegrationType _integration;
+};
+
+
+//
+// Functions definitions
+//
+///////////////////////////////////////////////////////////
+
+namespace Functions1D {
+
+// GetXF1D
+/*! Returns the X 3D coordinate of an Interface1D. */
+class LIB_VIEW_MAP_EXPORT GetXF1D : public UnaryFunction1D<real>
+{
+private:
+ Functions0D::GetXF0D _func;
+
+public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute a single value from a set of values.
+ */
+ GetXF1D(IntegrationType iType) : UnaryFunction1D<real>(iType) {}
+
+ /*! Returns the string "GetXF1D" */
+ string getName() const
+ {
+ return "GetXF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+// GetYF1D
+/*! Returns the Y 3D coordinate of an Interface1D. */
+class LIB_VIEW_MAP_EXPORT GetYF1D : public UnaryFunction1D<real>
+{
+private:
+Functions0D::GetYF0D _func;
+
+public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute a single value from a set of values.
+ */
+ GetYF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType) {}
+
+ /*! Returns the string "GetYF1D" */
+ string getName() const
+ {
+ return "GetYF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+// GetZF1D
+/*! Returns the Z 3D coordinate of an Interface1D. */
+class LIB_VIEW_MAP_EXPORT GetZF1D : public UnaryFunction1D<real>
+{
+private:
+ Functions0D::GetZF0D _func;
+
+public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute a single value from a set of values.
+ */
+ GetZF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType) {}
+
+ /*! Returns the string "GetZF1D" */
+ string getName() const
+ {
+ return "GetZF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+// GetProjectedXF1D
+/*! Returns the projected X 3D coordinate of an Interface1D. */
+class LIB_VIEW_MAP_EXPORT GetProjectedXF1D : public UnaryFunction1D<real>
+{
+private:
+ Functions0D::GetProjectedXF0D _func;
+
+public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute a single value from a set of values.
+ */
+ GetProjectedXF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType) {}
+
+ /*! Returns the string "GetProjectedXF1D" */
+ string getName() const
+ {
+ return "GetProjectedXF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+// GetProjectedYF1D
+/*! Returns the projected Y 3D coordinate of an Interface1D. */
+class LIB_VIEW_MAP_EXPORT GetProjectedYF1D : public UnaryFunction1D<real>
+{
+private:
+ Functions0D::GetProjectedYF0D _func;
+
+public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute a single value from a set of values.
+ */
+ GetProjectedYF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType) {}
+
+ /*! Returns the string "GetProjectedYF1D" */
+ string getName() const
+ {
+ return "GetProjectedYF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+// GetProjectedZF1D
+/*! Returns the projected Z 3D coordinate of an Interface1D. */
+class LIB_VIEW_MAP_EXPORT GetProjectedZF1D : public UnaryFunction1D<real>
+{
+private:
+ Functions0D::GetProjectedZF0D _func;
+
+public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute a single value from a set of values.
+ */
+ GetProjectedZF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType) {}
+
+ /*! Returns the string "GetProjectedZF1D" */
+ string getName() const
+ {
+ return "GetProjectedZF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+// Orientation2DF1D
+/*! Returns the 2D orientation as a Vec2f*/
+class LIB_VIEW_MAP_EXPORT Orientation2DF1D : public UnaryFunction1D<Vec2f>
+{
+private:
+ Functions0D::VertexOrientation2DF0D _func;
+
+public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute a single value from a set of values.
+ */
+ Orientation2DF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Vec2f>(iType) {}
+
+ /*! Returns the string "Orientation2DF1D" */
+ string getName() const
+ {
+ return "Orientation2DF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+// Orientation3DF1D
+/*! Returns the 3D orientation as a Vec3f. */
+class LIB_VIEW_MAP_EXPORT Orientation3DF1D : public UnaryFunction1D<Vec3f>
+{
+private:
+ Functions0D::VertexOrientation3DF0D _func;
+
+public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute a single value from a set of values.
+ */
+ Orientation3DF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Vec3f>(iType) {}
+
+ /*! Returns the string "Orientation3DF1D" */
+ string getName() const
+ {
+ return "Orientation3DF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+// ZDiscontinuityF1D
+/*! Returns a real giving the distance between and Interface1D and the shape that lies behind (occludee).
+ * This distance is evaluated in the camera space and normalized between 0 and 1. Therefore, if no oject is occluded
+ * by the shape to which the Interface1D belongs to, 1 is returned.
+ */
+class LIB_VIEW_MAP_EXPORT ZDiscontinuityF1D : public UnaryFunction1D<real>
+{
+private:
+ Functions0D::ZDiscontinuityF0D _func;
+
+public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute a single value from a set of values.
+ */
+ ZDiscontinuityF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType) {}
+
+ /*! Returns the string "ZDiscontinuityF1D" */
+ string getName() const
+ {
+ return "ZDiscontinuityF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+// QuantitativeInvisibilityF1D
+/*! Returns the Quantitative Invisibility of an Interface1D element.
+ * If the Interface1D is a ViewEdge, then there is no ambiguity concerning the result. But, if the Interface1D
+ * results of a chaining (chain, stroke), then it might be made of several 1D elements of different
+ * Quantitative Invisibilities.
+ */
+class LIB_VIEW_MAP_EXPORT QuantitativeInvisibilityF1D : public UnaryFunction1D<unsigned>
+{
+private:
+ Functions0D::QuantitativeInvisibilityF0D _func;
+
+public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute a single value from a set of values.
+ */
+ QuantitativeInvisibilityF1D(IntegrationType iType = MEAN) : UnaryFunction1D<unsigned int>(iType) {}
+
+ /*! Returns the string "QuantitativeInvisibilityF1D" */
+ string getName() const
+ {
+ return "QuantitativeInvisibilityF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+// CurveNatureF1D
+/*! Returns the nature of the Interface1D (silhouette, ridge, crease...).
+ * Except if the Interface1D is a ViewEdge, this result might be ambiguous.
+ * Indeed, the Interface1D might result from the gathering of several 1D elements, each one being of a different
+ * nature. An integration method, such as the MEAN, might give, in this case, irrelevant results.
+ */
+class LIB_VIEW_MAP_EXPORT CurveNatureF1D : public UnaryFunction1D<Nature::EdgeNature>
+{
+private:
+ Functions0D::CurveNatureF0D _func;
+
+public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute a single value from a set of values.
+ */
+ CurveNatureF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Nature::EdgeNature>(iType) {}
+
+ /*! Returns the string "CurveNatureF1D" */
+ string getName() const
+ {
+ return "CurveNatureF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+// TimeStampF1D
+/*! Returns the time stamp of the Interface1D. */
+class LIB_VIEW_MAP_EXPORT TimeStampF1D : public UnaryFunction1D_void
+{
+public:
+ /*! Returns the string "TimeStampF1D" */
+ string getName() const
+ {
+ return "TimeStampF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+// IncrementChainingTimeStampF1D
+/*! Increments the chaining time stamp of the Interface1D. */
+class LIB_VIEW_MAP_EXPORT IncrementChainingTimeStampF1D : public UnaryFunction1D_void
+{
+public:
+ /*! Returns the string "IncrementChainingTimeStampF1D" */
+ string getName() const
+ {
+ return "IncrementChainingTimeStampF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+// ChainingTimeStampF1D
+/*! Sets the chaining time stamp of the Interface1D. */
+class LIB_VIEW_MAP_EXPORT ChainingTimeStampF1D : public UnaryFunction1D_void
+{
+public:
+ /*! Returns the string "ChainingTimeStampF1D" */
+ string getName() const
+ {
+ return "ChainingTimeStampF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+
+// Curvature2DAngleF1D
+/*! Returns the 2D curvature as an angle for an Interface1D. */
+class LIB_VIEW_MAP_EXPORT Curvature2DAngleF1D : public UnaryFunction1D<real>
+{
+public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute a single value from a set of values.
+ */
+ Curvature2DAngleF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType) {}
+
+ /*! Returns the string "Curvature2DAngleF1D" */
+ string getName() const
+ {
+ return "Curvature2DAngleF1D";
+ }
+
+ /*! the () operator.*/
+ int operator()(Interface1D& inter)
+ {
+ result = integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+private:
+ Functions0D::Curvature2DAngleF0D _fun;
+};
+
+// Normal2DF1D
+/*! Returns the 2D normal for an interface 1D. */
+class LIB_VIEW_MAP_EXPORT Normal2DF1D : public UnaryFunction1D<Vec2f>
+{
+public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute a single value from a set of values.
+ */
+ Normal2DF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Vec2f>(iType) {}
+
+ /*! Returns the string "Normal2DF1D" */
+ string getName() const
+ {
+ return "Normal2DF1D";
+ }
+
+ /*! the () operator.*/
+ int operator()(Interface1D& inter)
+ {
+ result = integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+private:
+ Functions0D::Normal2DF0D _fun;
+};
+
+// GetShapeF1D
+/*! Returns list of shapes covered by this Interface1D. */
+class LIB_VIEW_MAP_EXPORT GetShapeF1D : public UnaryFunction1D<std::vector<ViewShape*> >
+{
+public:
+ /*! Builds the functor. */
+ GetShapeF1D() : UnaryFunction1D<std::vector<ViewShape*> >() {}
+
+ /*! Returns the string "GetShapeF1D" */
+ string getName() const
+ {
+ return "GetShapeF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+// GetOccludersF1D
+/*! Returns list of occluding shapes covered by this Interface1D. */
+class LIB_VIEW_MAP_EXPORT GetOccludersF1D : public UnaryFunction1D<std::vector<ViewShape*> >
+{
+public:
+ /*! Builds the functor. */
+ GetOccludersF1D() : UnaryFunction1D<std::vector<ViewShape*> >() {}
+
+ /*! Returns the string "GetOccludersF1D" */
+ string getName() const
+ {
+ return "GetOccludersF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+// GetOccludeeF1D
+/*! Returns list of occluded shapes covered by this Interface1D. */
+class LIB_VIEW_MAP_EXPORT GetOccludeeF1D : public UnaryFunction1D<std::vector<ViewShape*> >
+{
+public:
+ /*! Builds the functor. */
+ GetOccludeeF1D() : UnaryFunction1D<std::vector<ViewShape*> >() {}
+
+ /*! Returns the string "GetOccludeeF1D" */
+ string getName() const
+ {
+ return "GetOccludeeF1D";
+ }
+
+ /*! the () operator. */
+ int operator()(Interface1D& inter);
+};
+
+// internal
+////////////
+
+// getOccludeeF1D
+LIB_VIEW_MAP_EXPORT
+void getOccludeeF1D(Interface1D& inter, set<ViewShape*>& oShapes);
+
+// getOccludersF1D
+LIB_VIEW_MAP_EXPORT
+void getOccludersF1D(Interface1D& inter, set<ViewShape*>& oShapes);
+
+// getShapeF1D
+LIB_VIEW_MAP_EXPORT
+void getShapeF1D(Interface1D& inter, set<ViewShape*>& oShapes);
+
+} // end of namespace Functions1D
+
+#endif // __FREESTYLE_FUNCTIONS_1D_H__
diff --git a/source/blender/freestyle/intern/view_map/GridDensityProvider.h b/source/blender/freestyle/intern/view_map/GridDensityProvider.h
new file mode 100644
index 00000000000..930bb0af200
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/GridDensityProvider.h
@@ -0,0 +1,152 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_GRID_DENSITY_PROVIDER_H__
+#define __FREESTYLE_GRID_DENSITY_PROVIDER_H__
+
+/** \file blender/freestyle/intern/view_map/GridDensityProvider.h
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2011-2-5
+ */
+
+#include <stdexcept>
+#include <memory>
+
+#include "OccluderSource.h"
+
+#include "../geometry/BBox.h"
+
+#include "BKE_global.h"
+
+class GridDensityProvider
+{
+ // Disallow copying and assignment
+ GridDensityProvider(const GridDensityProvider& other);
+ GridDensityProvider& operator=(const GridDensityProvider& other);
+
+public:
+ GridDensityProvider(OccluderSource& source) : source(source) {}
+
+ virtual ~GridDensityProvider() {};
+
+ float cellSize()
+ {
+ return _cellSize;
+ }
+
+ unsigned cellsX()
+ {
+ return _cellsX;
+ }
+
+ unsigned cellsY()
+ {
+ return _cellsY;
+ }
+
+ float cellOrigin(int index)
+ {
+ if (index < 2) {
+ return _cellOrigin[index];
+ }
+ else {
+ throw new out_of_range("GridDensityProvider::cellOrigin can take only indexes of 0 or 1.");
+ }
+ }
+
+ static void calculateOptimalProscenium(OccluderSource& source, real proscenium[4])
+ {
+ source.begin();
+ if (source.isValid()) {
+ const Vec3r& initialPoint = source.getGridSpacePolygon().getVertices()[0];
+ proscenium[0] = proscenium[1] = initialPoint[0];
+ proscenium[2] = proscenium[3] = initialPoint[1];
+ while (source.isValid()) {
+ GridHelpers::expandProscenium (proscenium, source.getGridSpacePolygon());
+ source.next();
+ }
+ }
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Proscenium: (" << proscenium[0] << ", " << proscenium[1] << ", " << proscenium[2] <<
+ ", " << proscenium[3] << ")" << endl;
+ }
+ }
+
+ static void calculateQuickProscenium(const GridHelpers::Transform& transform, const BBox<Vec3r>& bbox,
+ real proscenium[4])
+ {
+ real z;
+ // We want to use the z-coordinate closest to the camera to determine the proscenium face
+ if (::fabs(bbox.getMin()[2]) < ::fabs(bbox.getMax()[2])) {
+ z = bbox.getMin()[2];
+ }
+ else {
+ z = bbox.getMax()[2];
+ }
+ // Now calculate the proscenium according to the min and max values of the x and y coordinates
+ Vec3r minPoint = transform(Vec3r(bbox.getMin()[0], bbox.getMin()[1], z));
+ Vec3r maxPoint = transform(Vec3r(bbox.getMax()[0], bbox.getMax()[1], z));
+ proscenium[0] = std::min(minPoint[0], maxPoint[0]);
+ proscenium[1] = std::max(minPoint[0], maxPoint[0]);
+ proscenium[2] = std::min(minPoint[1], maxPoint[1]);
+ proscenium[3] = std::max(minPoint[1], maxPoint[1]);
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Bounding box: " << minPoint << " to " << maxPoint << endl;
+ cout << "Proscenium : " << proscenium[0] << ", " << proscenium[1] << ", " << proscenium[2] << ", " <<
+ proscenium[3] << endl;
+ }
+ }
+
+protected:
+ OccluderSource& source;
+ unsigned _cellsX, _cellsY;
+ float _cellSize;
+ float _cellOrigin[2];
+};
+
+class GridDensityProviderFactory
+{
+ // Disallow copying and assignment
+ GridDensityProviderFactory(const GridDensityProviderFactory& other);
+ GridDensityProviderFactory& operator=(const GridDensityProviderFactory& other);
+
+public:
+ GridDensityProviderFactory() {}
+
+ virtual auto_ptr<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 auto_ptr<GridDensityProvider> newGridDensityProvider(OccluderSource& source) = 0;
+
+ virtual ~GridDensityProviderFactory () {}
+};
+
+#endif // __FREESTYLE_GRID_DENSITY_PROVIDER_H__
diff --git a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp
new file mode 100644
index 00000000000..5e17c85808b
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2011-2-8
+ */
+
+#include "HeuristicGridDensityProviderFactory.h"
+
+HeuristicGridDensityProviderFactory::HeuristicGridDensityProviderFactory(real sizeFactor, unsigned numFaces)
+: sizeFactor(sizeFactor), numFaces(numFaces)
+{
+}
+
+HeuristicGridDensityProviderFactory::~HeuristicGridDensityProviderFactory() {}
+
+auto_ptr<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));
+ if (avg->cellSize() > p23->cellSize()) {
+ return (auto_ptr<GridDensityProvider>) p23;
+ }
+ else {
+ return (auto_ptr<GridDensityProvider>) avg;
+ }
+}
+
+auto_ptr<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));
+ if (avg->cellSize() > p23->cellSize()) {
+ return (auto_ptr<GridDensityProvider>) p23;
+ }
+ else {
+ return (auto_ptr<GridDensityProvider>) avg;
+ }
+}
+
+auto_ptr<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));
+ if (avg->cellSize() > p23->cellSize()) {
+ return (auto_ptr<GridDensityProvider>) p23;
+ }
+ else {
+ return (auto_ptr<GridDensityProvider>) avg;
+ }
+}
diff --git a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h
new file mode 100644
index 00000000000..a7557f04565
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_HEURISTIC_GRID_DENSITY_PROVIDER_FACTORY_H__
+#define __FREESTYLE_HEURISTIC_GRID_DENSITY_PROVIDER_FACTORY_H__
+
+/** \file blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2011-2-8
+ */
+
+//#include <memory> // provided by GridDensityProvider.h
+
+#include "AverageAreaGridDensityProvider.h"
+//#include "GridDensityProvider.h" // provided by *GridDensityProvider.h below
+#include "Pow23GridDensityProvider.h"
+
+class HeuristicGridDensityProviderFactory : public GridDensityProviderFactory
+{
+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);
+
+protected:
+ real sizeFactor;
+ unsigned numFaces;
+};
+
+#endif // __FREESTYLE_HEURISTIC_GRID_DENSITY_PROVIDER_FACTORY_H__
diff --git a/source/blender/freestyle/intern/view_map/Interface0D.h b/source/blender/freestyle/intern/view_map/Interface0D.h
new file mode 100644
index 00000000000..f7c814a63d8
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Interface0D.h
@@ -0,0 +1,390 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_INTERFACE_0D_H__
+#define __FREESTYLE_INTERFACE_0D_H__
+
+/** \file blender/freestyle/intern/view_map/Interface0D.h
+ * \ingroup freestyle
+ * \brief Interface to 0D elts
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+#include <iostream>
+#include <Python.h>
+#include <string>
+
+#include "../geometry/Geom.h"
+
+#include "../system/Id.h"
+#include "../system/Iterator.h" //soc
+#include "../system/Precision.h"
+
+#include "../winged_edge/Nature.h"
+
+using namespace std;
+
+//
+// Interface0D
+//
+//////////////////////////////////////////////////
+
+class FEdge;
+class SVertex;
+class ViewVertex;
+class NonTVertex;
+class TVertex;
+
+/*! Base class for any 0D element. */
+class Interface0D
+{
+public:
+ /*! Default constructor */
+ Interface0D() {}
+ virtual ~Interface0D() {}; //soc
+
+ /*! Returns the string "Interface0D". */
+ virtual string getExactTypeName() const
+ {
+ return "Interface0D";
+ }
+
+ // Data access methods
+
+ /*! Returns the 3D x coordinate of the point. */
+ virtual real getX() const
+ {
+ PyErr_SetString(PyExc_TypeError, "method getX() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 3D y coordinate of the point. */
+ virtual real getY() const
+ {
+ PyErr_SetString(PyExc_TypeError, "method getY() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 3D z coordinate of the point. */
+ virtual real getZ() const
+ {
+ PyErr_SetString(PyExc_TypeError, "method getZ() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 3D point. */
+ virtual Geometry::Vec3f getPoint3D() const
+ {
+ PyErr_SetString(PyExc_TypeError, "method getPoint3D() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 2D x coordinate of the point. */
+ virtual real getProjectedX() const
+ {
+ PyErr_SetString(PyExc_TypeError, "method getProjectedX() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 2D y coordinate of the point. */
+ virtual real getProjectedY() const
+ {
+ PyErr_SetString(PyExc_TypeError, "method getProjectedY() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 2D z coordinate of the point. */
+ virtual real getProjectedZ() const
+ {
+ PyErr_SetString(PyExc_TypeError, "method getProjectedZ() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 2D point. */
+ virtual Geometry::Vec2f getPoint2D() const
+ {
+ PyErr_SetString(PyExc_TypeError, "method getPoint2D() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the FEdge that lies between this Interface0D and the Interface0D given as argument. */
+ virtual FEdge *getFEdge(Interface0D&)
+ {
+ PyErr_SetString(PyExc_TypeError, "method getFEdge() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the Id of the point. */
+ virtual Id getId() const
+ {
+ PyErr_SetString(PyExc_TypeError, "method getId() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the nature of the point. */
+ virtual Nature::VertexNature getNature() const
+ {
+ PyErr_SetString(PyExc_TypeError, "method getNature() not properly overridden");
+ return Nature::POINT;
+ }
+
+
+ /*! Cast the Interface0D in SVertex if it can be. */
+ virtual SVertex *castToSVertex()
+ {
+ PyErr_SetString(PyExc_TypeError, "method castToSVertex() not properly overridden");
+ return 0;
+ }
+
+ /*! Cast the Interface0D in ViewVertex if it can be. */
+ virtual ViewVertex *castToViewVertex()
+ {
+ PyErr_SetString(PyExc_TypeError, "method castToViewVertex() not properly overridden");
+ return 0;
+ }
+
+ /*! Cast the Interface0D in NonTVertex if it can be. */
+ virtual NonTVertex *castToNonTVertex()
+ {
+ PyErr_SetString(PyExc_TypeError, "method castToNonTVertex() not properly overridden");
+ return 0;
+ }
+
+ /*! Cast the Interface0D in TVertex if it can be. */
+ virtual TVertex *castToTVertex()
+ {
+ PyErr_SetString(PyExc_TypeError, "method castToTVertex() not properly overridden");
+ return 0;
+ }
+};
+
+
+//
+// Interface0DIteratorNested
+//
+//////////////////////////////////////////////////
+
+class Interface0DIteratorNested : public Iterator
+{
+public:
+ virtual ~Interface0DIteratorNested() {}
+
+ virtual string getExactTypeName() const
+ {
+ return "Interface0DIteratorNested";
+ }
+
+ virtual Interface0D& operator*() = 0;
+
+ virtual Interface0D *operator->()
+ {
+ return &(operator*());
+ }
+
+ virtual int increment() = 0;
+
+ virtual int decrement() = 0;
+
+ virtual bool isBegin() const = 0;
+
+ virtual bool isEnd() const = 0;
+
+ virtual bool operator==(const Interface0DIteratorNested& it) const = 0;
+
+ virtual bool operator!=(const Interface0DIteratorNested& it) const
+ {
+ return !(*this == it);
+ }
+
+ /*! Returns the curvilinear abscissa */
+ virtual float t() const = 0;
+
+ /*! Returns the point parameter 0<u<1 */
+ virtual float u() const = 0;
+
+ virtual Interface0DIteratorNested *copy() const = 0;
+};
+
+
+//
+// Interface0DIterator
+//
+//////////////////////////////////////////////////
+
+/*! Class defining an iterator over Interface0D elements.
+ * An instance of this iterator is always obtained from a 1D element.
+ * \attention In the scripting language, you must call \code it2 = Interface0DIterator(it1) \endcode instead of
+ * \code it2 = it1 \endcode where \a it1 and \a it2 are 2 Interface0DIterator.
+ * Otherwise, incrementing \a it1 will also increment \a it2.
+ */
+class Interface0DIterator : public Iterator
+{
+public:
+ Interface0DIterator(Interface0DIteratorNested *it = NULL)
+ {
+ _iterator = it;
+ }
+
+ /*! Copy constructor */
+ Interface0DIterator(const Interface0DIterator& it)
+ {
+ _iterator = it._iterator->copy();
+ }
+
+ /*! Destructor */
+ virtual ~Interface0DIterator()
+ {
+ if (_iterator)
+ delete _iterator;
+ }
+
+ /*! Operator =
+ * \attention In the scripting language, you must call \code it2 = Interface0DIterator(it1) \endcode instead of
+ * \code it2 = it1 \endcode where \a it1 and \a it2 are 2 Interface0DIterator.
+ * Otherwise, incrementing \a it1 will also increment \a it2.
+ */
+ Interface0DIterator& operator=(const Interface0DIterator& it)
+ {
+ if (_iterator)
+ delete _iterator;
+ _iterator = it._iterator->copy();
+ return *this;
+ }
+
+ /*! Returns the string "Interface0DIterator". */
+ virtual string getExactTypeName() const
+ {
+ if (!_iterator)
+ return "Interface0DIterator";
+ return _iterator->getExactTypeName() + "Proxy";
+ }
+
+ // FIXME test it != 0 (exceptions ?)
+
+ /*! Returns a reference to the pointed Interface0D.
+ * In the scripting language, you must call "getObject()" instead using this operator.
+ */
+ Interface0D& operator*()
+ {
+ return _iterator->operator*();
+ }
+
+ /*! Returns a pointer to the pointed Interface0D.
+ * Can't be called in the scripting language.
+ */
+ Interface0D *operator->()
+ {
+ return &(operator*());
+ }
+
+ /*! Increments. In the scripting language, call "increment()". */
+ Interface0DIterator& operator++()
+ {
+ _iterator->increment();
+ return *this;
+ }
+
+ /*! Increments. In the scripting language, call "increment()". */
+ Interface0DIterator operator++(int)
+ {
+ Interface0DIterator ret(*this);
+ _iterator->increment();
+ return ret;
+ }
+
+ /*! Decrements. In the scripting language, call "decrement()". */
+ Interface0DIterator& operator--()
+ {
+ _iterator->decrement();
+ return *this;
+ }
+
+ /*! Decrements. In the scripting language, call "decrement()". */
+ Interface0DIterator operator--(int)
+ {
+ Interface0DIterator ret(*this);
+ _iterator->decrement();
+ return ret;
+ }
+
+ /*! Increments. */
+ virtual int increment()
+ {
+ return _iterator->increment();
+ }
+
+ /*! Decrements. */
+ virtual int decrement()
+ {
+ return _iterator->decrement();
+ }
+
+ /*! Returns true if the pointed Interface0D is the first of the 1D element containing the points over which
+ * we're iterating.
+ */
+ virtual bool isBegin() const
+ {
+ return _iterator->isBegin();
+ }
+
+ /*! Returns true if the pointed Interface0D is after the after the last point of the 1D element we're
+ * iterating from. */
+ virtual bool isEnd() const
+ {
+ return _iterator->isEnd();
+ }
+
+ /*! operator == . */
+ bool operator==(const Interface0DIterator& it) const
+ {
+ return _iterator->operator==(*(it._iterator));
+ }
+
+ /*! operator != . */
+ bool operator!=(const Interface0DIterator& it) const
+ {
+ return !(*this == it);
+ }
+
+ /*! Returns the curvilinear abscissa. */
+ inline float t() const
+ {
+ return _iterator->t();
+ }
+
+ /*! Returns the point parameter in the curve 0<=u<=1. */
+ inline float u() const
+ {
+ return _iterator->u();
+ }
+
+protected:
+ Interface0DIteratorNested *_iterator;
+};
+
+#endif // __FREESTYLE_INTERFACE_0D_H__
diff --git a/source/blender/freestyle/intern/view_map/Interface1D.h b/source/blender/freestyle/intern/view_map/Interface1D.h
new file mode 100644
index 00000000000..440c6f275b8
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Interface1D.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_INTERFACE_1D_H__
+#define __FREESTYLE_INTERFACE_1D_H__
+
+/** \file blender/freestyle/intern/view_map/Interface1D.h
+ * \ingroup freestyle
+ * \brief Interface 1D and related tools definitions
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+#include <float.h>
+#include <iostream>
+#include <Python.h>
+#include <string>
+
+#include "Functions0D.h"
+
+#include "../system/Id.h"
+#include "../system/Precision.h"
+
+#include "../winged_edge/Nature.h"
+
+using namespace std;
+
+// Integration method
+/*! The different integration methods that can be invoked to integrate into a single value the set of values obtained
+ * from each 0D element of a 1D element.
+ */
+typedef enum {
+ MEAN, /*!< The value computed for the 1D element is the mean of the values obtained for the 0D elements.*/
+ MIN, /*!< The value computed for the 1D element is the minimum of the values obtained for the 0D elements.*/
+ MAX, /*!< The value computed for the 1D element is the maximum of the values obtained for the 0D elements.*/
+ FIRST, /*!< The value computed for the 1D element is the first of the values obtained for the 0D elements.*/
+ LAST /*!< The value computed for the 1D element is the last of the values obtained for the 0D elements.*/
+} IntegrationType;
+
+/*! Returns a single value from a set of values evaluated at each 0D element of this 1D element.
+ * \param fun
+ * The UnaryFunction0D used to compute a value at each Interface0D.
+ * \param it
+ * The Interface0DIterator used to iterate over the 0D elements of this 1D element. The integration will occur
+ * over the 0D elements starting from the one pointed by it.
+ * \param it_end
+ * The Interface0DIterator pointing the end of the 0D elements of the 1D element.
+ * \param integration_type
+ * The integration method used to compute a single value from a set of values.
+ * \return the single value obtained for the 1D element.
+ */
+template <class T>
+T integrate(UnaryFunction0D<T>& fun, Interface0DIterator it, Interface0DIterator it_end,
+ IntegrationType integration_type = MEAN)
+{
+ T res;
+ unsigned size;
+ switch (integration_type) {
+ case MIN:
+ fun(it);
+ res = fun.result;
+ ++it;
+ for (; !it.isEnd(); ++it) {
+ fun(it);
+ if (fun.result < res)
+ res = fun.result;
+ }
+ break;
+ case MAX:
+ fun(it);
+ res = fun.result;
+ ++it;
+ for (; !it.isEnd(); ++it) {
+ fun(it);
+ if (fun.result > res)
+ res = fun.result;
+ }
+ break;
+ case FIRST:
+ fun(it);
+ res = fun.result;
+ break;
+ case LAST:
+ fun(--it_end);
+ res = fun.result;
+ break;
+ case MEAN:
+ default:
+ fun(it);
+ res = fun.result;
+ ++it;
+ for (size = 1; !it.isEnd(); ++it, ++size) {
+ fun(it);
+ res += fun.result;
+ }
+ res /= (size ? size : 1);
+ break;
+ }
+ return res;
+}
+
+//
+// Interface1D
+//
+//////////////////////////////////////////////////
+
+/*! Base class for any 1D element. */
+class Interface1D
+{
+public:
+ /*! Default constructor */
+ Interface1D()
+ {
+ _timeStamp = 0;
+ }
+
+ virtual ~Interface1D() {}; //soc
+
+ /*! Returns the string "Interface1D". */
+ virtual string getExactTypeName() const
+ {
+ return "Interface1D";
+ }
+
+ // Iterator access
+
+ /*! Returns an iterator over the Interface1D vertices, pointing to the first vertex. */
+ virtual Interface0DIterator verticesBegin()
+ {
+ PyErr_SetString(PyExc_TypeError, "method verticesBegin() not properly overridden");
+ return Interface0DIterator();
+ }
+
+ /*! Returns an iterator over the Interface1D vertices, pointing after the last vertex. */
+ virtual Interface0DIterator verticesEnd()
+ {
+ PyErr_SetString(PyExc_TypeError, "method verticesEnd() not properly overridden");
+ return Interface0DIterator();
+ }
+
+ /*! Returns an iterator over the Interface1D points, pointing to the first point. The difference with
+ * verticesBegin() is that here we can iterate over points of the 1D element at a any given sampling.
+ * Indeed, for each iteration, a virtual point is created.
+ * \param t
+ * The sampling with which we want to iterate over points of this 1D element.
+ */
+ virtual Interface0DIterator pointsBegin(float t = 0.0f)
+ {
+ PyErr_SetString(PyExc_TypeError, "method pointsBegin() not properly overridden");
+ return Interface0DIterator();
+ }
+
+ /*! Returns an iterator over the Interface1D points, pointing after the last point. The difference with
+ * verticesEnd() is that here we can iterate over points of the 1D element at a any given sampling.
+ * Indeed, for each iteration, a virtual point is created.
+ * \param t
+ * The sampling with which we want to iterate over points of this 1D element.
+ */
+ virtual Interface0DIterator pointsEnd(float t = 0.0f)
+ {
+ PyErr_SetString(PyExc_TypeError, "method pointsEnd() not properly overridden");
+ return Interface0DIterator();
+ }
+
+ // Data access methods
+
+ /*! Returns the 2D length of the 1D element. */
+ virtual real getLength2D() const
+ {
+ PyErr_SetString(PyExc_TypeError, "method getLength2D() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the Id of the 1D element. */
+ virtual Id getId() const
+ {
+ PyErr_SetString(PyExc_TypeError, "method getId() not properly overridden");
+ return Id(0, 0);
+ }
+
+
+ // FIXME: ce truc n'a rien a faire la...(c une requete complexe qui doit etre ds les Function1D)
+ /*! Returns the nature of the 1D element. */
+ virtual Nature::EdgeNature getNature() const
+ {
+ PyErr_SetString(PyExc_TypeError, "method getNature() not properly overridden");
+ return Nature::NO_FEATURE;
+ }
+
+ /*! Returns the time stamp of the 1D element. Mainly used for selection. */
+ virtual unsigned getTimeStamp() const
+ {
+ return _timeStamp;
+ }
+
+ /*! Sets the time stamp for the 1D element. */
+ inline void setTimeStamp(unsigned iTimeStamp)
+ {
+ _timeStamp = iTimeStamp;
+ }
+
+protected:
+ unsigned _timeStamp;
+};
+
+#endif // __FREESTYLE_INTERFACE_1D_H__
diff --git a/source/blender/freestyle/intern/view_map/OccluderSource.cpp b/source/blender/freestyle/intern/view_map/OccluderSource.cpp
new file mode 100644
index 00000000000..b9fd5a3ebff
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/OccluderSource.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/OccluderSource.cpp
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2010-12-21
+ */
+
+#include <algorithm>
+
+#include "OccluderSource.h"
+
+#include "BKE_global.h"
+
+OccluderSource::OccluderSource(const GridHelpers::Transform& t, WingedEdge& we)
+: wingedEdge(we), valid(false), transform(t)
+{
+ begin();
+}
+
+OccluderSource::~OccluderSource() {}
+
+void OccluderSource::buildCachedPolygon()
+{
+ vector<Vec3r> vertices(GridHelpers::enumerateVertices((*currentFace)->getEdgeList()));
+ // This doesn't work, because our functor's polymorphism won't survive the copy:
+ // std::transform(vertices.begin(), vertices.end(), vertices.begin(), transform);
+ // so we have to do:
+ for (vector<Vec3r>::iterator i = vertices.begin(); i != vertices.end(); ++i) {
+ (*i) = transform(*i);
+ }
+ cachedPolygon = Polygon3r(vertices, transform((*currentFace)->GetNormal()));
+}
+
+void OccluderSource::begin()
+{
+ vector<WShape*>& wshapes = wingedEdge.getWShapes();
+ currentShape = wshapes.begin();
+ shapesEnd = wshapes.end();
+ valid = false;
+ if (currentShape != shapesEnd) {
+ vector<WFace*>& wFaces = (*currentShape)->GetFaceList();
+ currentFace = wFaces.begin();
+ facesEnd = wFaces.end();
+
+ if (currentFace != facesEnd) {
+ buildCachedPolygon();
+ valid = true;
+ }
+ }
+}
+
+bool OccluderSource::next()
+{
+ if (valid) {
+ ++currentFace;
+ while (currentFace == facesEnd) {
+ ++currentShape;
+ if (currentShape == shapesEnd) {
+ valid = false;
+ return false;
+ }
+ else {
+ vector<WFace*>& wFaces = (*currentShape)->GetFaceList();
+ currentFace = wFaces.begin();
+ facesEnd = wFaces.end();
+ }
+ }
+ buildCachedPolygon();
+ return true;
+ }
+ return false;
+}
+
+bool OccluderSource::isValid()
+{
+ // Or:
+ // return currentShapes != shapesEnd && currentFace != facesEnd;
+ return valid;
+}
+
+WFace *OccluderSource::getWFace()
+{
+ return valid ? *currentFace : NULL;
+}
+
+Polygon3r OccluderSource::getCameraSpacePolygon()
+{
+ return Polygon3r(GridHelpers::enumerateVertices((*currentFace)->getEdgeList()), (*currentFace)->GetNormal());
+}
+
+Polygon3r& OccluderSource::getGridSpacePolygon()
+{
+ return cachedPolygon;
+}
+
+void OccluderSource::getOccluderProscenium(real proscenium[4])
+{
+ begin();
+ const Vec3r& initialPoint = cachedPolygon.getVertices()[0];
+ proscenium[0] = proscenium[1] = initialPoint[0];
+ proscenium[2] = proscenium[3] = initialPoint[1];
+ while (isValid()) {
+ GridHelpers::expandProscenium (proscenium, cachedPolygon);
+ next();
+ }
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Proscenium: (" << proscenium[0] << ", " << proscenium[1] << ", " << proscenium[2] << ", " <<
+ proscenium[3] << ")" << endl;
+ }
+}
+
+real OccluderSource::averageOccluderArea()
+{
+ real area = 0.0;
+ unsigned numFaces = 0;
+ for (begin(); isValid(); next()) {
+ Vec3r min, max;
+ cachedPolygon.getBBox(min, max);
+ area += (max[0] - min[0]) * (max[1] - min[1]);
+ ++numFaces;
+ }
+ area /= numFaces;
+ return area;
+}
diff --git a/source/blender/freestyle/intern/view_map/OccluderSource.h b/source/blender/freestyle/intern/view_map/OccluderSource.h
new file mode 100644
index 00000000000..14f8f54fa1a
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/OccluderSource.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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_OCCLUDER_SOURCE_H__
+#define __FREESTYLE_OCCLUDER_SOURCE_H__
+
+/** \file blender/freestyle/intern/view_map/OccluderSource.h
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2010-12-21
+ */
+
+#include "../geometry/GridHelpers.h"
+
+#include "../winged_edge/WEdge.h"
+
+class OccluderSource
+{
+ // Disallow copying and assignment
+ OccluderSource(const OccluderSource& other);
+ OccluderSource& operator=(const OccluderSource& other);
+
+public:
+ OccluderSource(const GridHelpers::Transform& transform, WingedEdge& we);
+ virtual ~OccluderSource();
+
+ void begin();
+ virtual bool next();
+ bool isValid();
+
+ WFace *getWFace();
+ Polygon3r getCameraSpacePolygon();
+ Polygon3r& getGridSpacePolygon();
+
+ virtual void getOccluderProscenium(real proscenium[4]);
+ virtual real averageOccluderArea();
+
+protected:
+ WingedEdge& wingedEdge;
+ vector<WShape*>::const_iterator currentShape, shapesEnd;
+ vector<WFace*>::const_iterator currentFace, facesEnd;
+
+ bool valid;
+
+ Polygon3r cachedPolygon;
+ const GridHelpers::Transform& transform;
+
+ void buildCachedPolygon();
+};
+
+#endif // __FREESTYLE_OCCLUDER_SOURCE_H__
diff --git a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp
new file mode 100644
index 00000000000..10c6265ebb4
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp
@@ -0,0 +1,123 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2011-2-8
+ */
+
+#include "Pow23GridDensityProvider.h"
+
+#include "BKE_global.h"
+
+Pow23GridDensityProvider::Pow23GridDensityProvider(OccluderSource& source, const real proscenium[4], unsigned numFaces)
+: GridDensityProvider(source), numFaces(numFaces)
+{
+ initialize (proscenium);
+}
+
+Pow23GridDensityProvider::Pow23GridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
+ const GridHelpers::Transform& transform, unsigned numFaces)
+: GridDensityProvider(source), numFaces(numFaces)
+{
+ real proscenium[4];
+ calculateQuickProscenium(transform, bbox, proscenium);
+
+ initialize (proscenium);
+}
+
+Pow23GridDensityProvider::Pow23GridDensityProvider(OccluderSource& source, unsigned numFaces)
+: GridDensityProvider(source), numFaces(numFaces)
+{
+ real proscenium[4];
+ calculateOptimalProscenium(source, proscenium);
+
+ initialize (proscenium);
+}
+
+Pow23GridDensityProvider::~Pow23GridDensityProvider () {}
+
+void Pow23GridDensityProvider::initialize(const real proscenium[4])
+{
+ float prosceniumWidth = (proscenium[1] - proscenium[0]);
+ float prosceniumHeight = (proscenium[3] - proscenium[2]);
+ real cellArea = prosceniumWidth * prosceniumHeight / pow(numFaces, 2.0f / 3.0f);
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << prosceniumWidth << " x " << prosceniumHeight << " grid with cells of area " << cellArea << "." << endl;
+ }
+
+ _cellSize = sqrt(cellArea);
+ // Now we know how many cells make each side of our grid
+ _cellsX = ceil(prosceniumWidth / _cellSize);
+ _cellsY = ceil(prosceniumHeight / _cellSize);
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl;
+ }
+
+ // Make sure the grid exceeds the proscenium by a small amount
+ float safetyZone = 0.1;
+ if (_cellsX * _cellSize < prosceniumWidth * (1.0 + safetyZone)) {
+ _cellsX = prosceniumWidth * (1.0 + safetyZone) / _cellSize;
+ }
+ if (_cellsY * _cellSize < prosceniumHeight * (1.0 + safetyZone)) {
+ _cellsY = prosceniumHeight * (1.0 + safetyZone) / _cellSize;
+ }
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl;
+ }
+
+ // Find grid origin
+ _cellOrigin[0] = ((proscenium[0] + proscenium[1]) / 2.0) - (_cellsX / 2.0) * _cellSize;
+ _cellOrigin[1] = ((proscenium[2] + proscenium[3]) / 2.0) - (_cellsY / 2.0) * _cellSize;
+}
+
+Pow23GridDensityProviderFactory::Pow23GridDensityProviderFactory(unsigned numFaces)
+: numFaces(numFaces)
+{
+}
+
+Pow23GridDensityProviderFactory::~Pow23GridDensityProviderFactory () {}
+
+auto_ptr<GridDensityProvider>
+Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4])
+{
+ return auto_ptr<GridDensityProvider>(new Pow23GridDensityProvider(source, proscenium, numFaces));
+}
+
+auto_ptr<GridDensityProvider>
+Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox,
+ const GridHelpers::Transform& transform)
+{
+ return auto_ptr<GridDensityProvider>(new Pow23GridDensityProvider(source, bbox, transform, numFaces));
+}
+
+auto_ptr<GridDensityProvider> Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source)
+{
+ return auto_ptr<GridDensityProvider>(new Pow23GridDensityProvider(source, numFaces));
+}
diff --git a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h
new file mode 100644
index 00000000000..0e26793cec7
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h
@@ -0,0 +1,75 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_POW_23_GRID_DENSITY_PROVIDER_H__
+#define __FREESTYLE_POW_23_GRID_DENSITY_PROVIDER_H__
+
+/** \file blender/freestyle/intern/view_map/Pow23GridDensityProvider.h
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2011-2-8
+ */
+
+#include "GridDensityProvider.h"
+
+class Pow23GridDensityProvider : public GridDensityProvider
+{
+ // Disallow copying and assignment
+ Pow23GridDensityProvider(const Pow23GridDensityProvider& other);
+ Pow23GridDensityProvider& operator=(const Pow23GridDensityProvider& other);
+
+public:
+ Pow23GridDensityProvider(OccluderSource& source, const real proscenium[4], unsigned numFaces);
+ Pow23GridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, const GridHelpers::Transform& transform,
+ unsigned numFaces);
+ Pow23GridDensityProvider(OccluderSource& source, unsigned numFaces);
+ virtual ~Pow23GridDensityProvider();
+
+protected:
+ unsigned numFaces;
+
+private:
+ void initialize(const real proscenium[4]);
+};
+
+class Pow23GridDensityProviderFactory : public GridDensityProviderFactory
+{
+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);
+
+protected:
+ unsigned numFaces;
+};
+
+#endif // __FREESTYLE_POW_23_GRID_DENSITY_PROVIDER_H__
diff --git a/source/blender/freestyle/intern/view_map/Silhouette.cpp b/source/blender/freestyle/intern/view_map/Silhouette.cpp
new file mode 100644
index 00000000000..f71c58c320c
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Silhouette.cpp
@@ -0,0 +1,420 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/Silhouette.cpp
+ * \ingroup freestyle
+ * \brief Classes to define a silhouette structure
+ * \author Stephane Grabli
+ * \date 25/03/2002
+ */
+
+#include "Silhouette.h"
+#include "ViewMap.h"
+
+/**********************************/
+/* */
+/* */
+/* SVertex */
+/* */
+/* */
+/**********************************/
+
+Nature::VertexNature SVertex::getNature() const
+{
+ Nature::VertexNature nature = Nature::S_VERTEX;
+ if (_pViewVertex)
+ nature |= _pViewVertex->getNature();
+ return nature;
+}
+
+SVertex *SVertex::castToSVertex()
+{
+ return this;
+}
+
+ViewVertex *SVertex::castToViewVertex()
+{
+ return _pViewVertex;
+}
+
+NonTVertex *SVertex::castToNonTVertex()
+{
+ return dynamic_cast<NonTVertex*>(_pViewVertex);
+}
+
+TVertex *SVertex::castToTVertex()
+{
+ return dynamic_cast<TVertex*>(_pViewVertex);
+}
+
+float SVertex::shape_importance() const
+{
+ return shape()->importance();
+}
+
+#if 0
+Material SVertex::material() const
+{
+ return _Shape->material();
+}
+#endif
+
+Id SVertex::shape_id() const
+{
+ return _Shape->getId();
+}
+
+const SShape *SVertex::shape() const
+{
+ return _Shape;
+}
+
+const int SVertex::qi() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->qi();
+}
+
+occluder_container::const_iterator SVertex::occluders_begin() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occluders_begin();
+}
+
+occluder_container::const_iterator SVertex::occluders_end() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occluders_end();
+}
+
+bool SVertex::occluders_empty() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occluders_empty();
+}
+
+int SVertex::occluders_size() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occluders_size();
+}
+
+const Polygon3r& SVertex::occludee() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occludee();
+}
+
+const SShape *SVertex::occluded_shape() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occluded_shape();
+}
+
+const bool SVertex::occludee_empty() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occludee_empty();
+}
+
+real SVertex::z_discontinuity() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->z_discontinuity();
+}
+
+FEdge *SVertex::fedge()
+{
+ if (getNature() & Nature::T_VERTEX)
+ return NULL;
+ return _FEdges[0];
+}
+
+FEdge *SVertex::getFEdge(Interface0D& inter)
+{
+ FEdge *result = NULL;
+ SVertex *iVertexB = dynamic_cast<SVertex*>(&inter);
+ if (!iVertexB)
+ return result;
+ vector<FEdge*>::const_iterator fe = _FEdges.begin(), feend = _FEdges.end();
+ for (; fe != feend; ++fe) {
+ if ((((*fe)->vertexA() == this) && ((*fe)->vertexB() == iVertexB)) ||
+ (((*fe)->vertexB() == this) && ((*fe)->vertexA() == iVertexB)))
+ {
+ result = (*fe);
+ }
+ }
+ if ((result == 0) && (getNature() & Nature::T_VERTEX)) {
+ SVertex *brother;
+ ViewVertex *vvertex = viewvertex();
+ TVertex *tvertex = dynamic_cast<TVertex*>(vvertex);
+ if (tvertex) {
+ brother = tvertex->frontSVertex();
+ if (this == brother)
+ brother = tvertex->backSVertex();
+ const vector<FEdge*>& fedges = brother->fedges();
+ for (fe = fedges.begin(), feend = fedges.end(); fe != feend; ++fe) {
+ if ((((*fe)->vertexA() == brother) && ((*fe)->vertexB() == iVertexB)) ||
+ (((*fe)->vertexB() == brother) && ((*fe)->vertexA() == iVertexB)))
+ {
+ result = (*fe);
+ }
+ }
+ }
+ }
+ if ((result == 0) && (iVertexB->getNature() & Nature::T_VERTEX)) {
+ SVertex *brother;
+ ViewVertex *vvertex = iVertexB->viewvertex();
+ TVertex *tvertex = dynamic_cast<TVertex*>(vvertex);
+ if (tvertex) {
+ brother = tvertex->frontSVertex();
+ if (iVertexB == brother)
+ brother = tvertex->backSVertex();
+ for (fe = _FEdges.begin(), feend = _FEdges.end(); fe != feend; ++fe) {
+ if ((((*fe)->vertexA() == this) && ((*fe)->vertexB() == brother)) ||
+ (((*fe)->vertexB() == this) && ((*fe)->vertexA() == brother)))
+ {
+ result = (*fe);
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+
+/**********************************/
+/* */
+/* */
+/* FEdge */
+/* */
+/* */
+/**********************************/
+
+
+int FEdge::viewedge_nature() const
+{
+ return _ViewEdge->getNature();
+}
+
+#if 0
+float FEdge::viewedge_length() const
+{
+ return _ViewEdge->viewedge_length();
+}
+#endif
+
+const SShape *FEdge::occluded_shape() const
+{
+ ViewShape *aShape = _ViewEdge->aShape();
+ if (aShape == 0)
+ return 0;
+ return aShape->sshape();
+}
+
+float FEdge::shape_importance() const
+{
+ return _VertexA->shape()->importance();
+}
+
+int FEdge::invisibility() const
+{
+ return _ViewEdge->qi();
+}
+
+occluder_container::const_iterator FEdge::occluders_begin() const
+{
+ return _ViewEdge->occluders_begin();
+}
+
+occluder_container::const_iterator FEdge::occluders_end() const
+{
+ return _ViewEdge->occluders_end();
+}
+
+bool FEdge::occluders_empty() const
+{
+ return _ViewEdge->occluders_empty();
+}
+
+int FEdge::occluders_size() const
+{
+ return _ViewEdge->occluders_size();
+}
+
+const bool FEdge::occludee_empty() const
+{
+ return _ViewEdge->occludee_empty();
+}
+
+Id FEdge::shape_id() const
+{
+ return _VertexA->shape()->getId();
+}
+
+const SShape *FEdge::shape() const
+{
+ return _VertexA->shape();
+}
+
+real FEdge::z_discontinuity() const
+{
+ if (!(getNature() & Nature::SILHOUETTE) && !(getNature() & Nature::BORDER)) {
+ return 0;
+ }
+
+ BBox<Vec3r> box = ViewMap::getInstance()->getScene3dBBox();
+
+ Vec3r bbox_size_vec(box.getMax() - box.getMin());
+ real bboxsize = bbox_size_vec.norm();
+ if (occludee_empty()) {
+ //return FLT_MAX;
+ return 1.0;
+ //return bboxsize;
+ }
+
+#if 0
+ real result;
+ z_discontinuity_functor<SVertex> _functor;
+ Evaluate<SVertex, z_discontinuity_functor<SVertex> >(&_functor, iCombination, result);
+#endif
+ Vec3r middle((_VertexB->point3d() - _VertexA->point3d()));
+ middle /= 2;
+ Vec3r disc_vec(middle - _occludeeIntersection);
+ real res = disc_vec.norm() / bboxsize;
+
+ return res;
+ //return fabs((middle.z() - _occludeeIntersection.z()));
+}
+
+#if 0
+float FEdge::local_average_depth(int iCombination ) const
+{
+ float result;
+ local_average_depth_functor<SVertex> functor;
+ Evaluate(&functor, iCombination, result);
+
+ return result;
+}
+
+float FEdge::local_depth_variance(int iCombination ) const
+{
+ float result;
+
+ local_depth_variance_functor<SVertex> functor;
+
+ Evaluate(&functor, iCombination, result);
+
+ return result;
+}
+
+real FEdge::local_average_density( float sigma, int iCombination) const
+{
+ float result;
+
+ density_functor<SVertex> functor(sigma);
+
+ Evaluate(&functor, iCombination, result);
+
+ return result;
+}
+
+Vec3r FEdge::normal(int& oException /* = Exception::NO_EXCEPTION */)
+{
+ Vec3r Na = _VertexA->normal(oException);
+ if (oException != Exception::NO_EXCEPTION)
+ return Na;
+ Vec3r Nb = _VertexB->normal(oException);
+ if (oException != Exception::NO_EXCEPTION)
+ return Nb;
+ return (Na + Nb) / 2.0;
+}
+
+Vec3r FEdge::curvature2d_as_vector(int iCombination) const
+{
+ Vec3r result;
+ curvature2d_as_vector_functor<SVertex> _functor;
+ Evaluate<Vec3r, curvature2d_as_vector_functor<SVertex> >(&_functor, iCombination, result);
+ return result;
+}
+
+real FEdge::curvature2d_as_angle(int iCombination) const
+{
+ real result;
+ curvature2d_as_angle_functor<SVertex> _functor;
+ Evaluate<real, curvature2d_as_angle_functor<SVertex> >(&_functor, iCombination, result);
+ return result;
+}
+#endif
+
+/**********************************/
+/* */
+/* */
+/* FEdgeSharp */
+/* */
+/* */
+/**********************************/
+
+#if 0
+Material FEdge::material() const
+{
+ return _VertexA->shape()->material();
+}
+#endif
+
+const FrsMaterial& FEdgeSharp::aFrsMaterial() const
+{
+ return _VertexA->shape()->frs_material(_aFrsMaterialIndex);
+}
+
+const FrsMaterial& FEdgeSharp::bFrsMaterial() const
+{
+ return _VertexA->shape()->frs_material(_bFrsMaterialIndex);
+}
+
+/**********************************/
+/* */
+/* */
+/* FEdgeSmooth */
+/* */
+/* */
+/**********************************/
+
+const FrsMaterial& FEdgeSmooth::frs_material() const
+{
+ return _VertexA->shape()->frs_material(_FrsMaterialIndex);
+}
diff --git a/source/blender/freestyle/intern/view_map/Silhouette.h b/source/blender/freestyle/intern/view_map/Silhouette.h
new file mode 100644
index 00000000000..8f37532191e
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Silhouette.h
@@ -0,0 +1,1876 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_SILHOUETTE_H__
+#define __FREESTYLE_SILHOUETTE_H__
+
+/** \file blender/freestyle/intern/view_map/Silhouette.h
+ * \ingroup freestyle
+ * \brief Classes to define a silhouette structure
+ * \author Stephane Grabli
+ * \date 25/03/2002
+ */
+
+#include <float.h>
+#include <iostream>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "Interface0D.h"
+#include "Interface1D.h"
+
+#include "../geometry/BBox.h"
+#include "../geometry/Geom.h"
+#include "../geometry/Polygon.h"
+
+#include "../scene_graph/FrsMaterial.h"
+
+#include "../system/Exception.h"
+#include "../system/FreestyleConfig.h"
+
+#include "../winged_edge/Curvature.h"
+
+using namespace std;
+using namespace Geometry;
+
+class ViewShape;
+typedef vector<ViewShape*> occluder_container;
+
+/**********************************/
+/* */
+/* */
+/* SVertex */
+/* */
+/* */
+/**********************************/
+
+class FEdge;
+class ViewVertex;
+class SShape;
+
+/*! Class to define a vertex of the embedding. */
+class LIB_VIEW_MAP_EXPORT SVertex : public Interface0D
+{
+public: // Implementation of Interface0D
+ /*! Returns the string "SVertex" .*/
+ virtual string getExactTypeName() const
+ {
+ return "SVertex";
+ }
+
+ // Data access methods
+ /*! Returns the 3D x coordinate of the vertex .*/
+ virtual real getX() const
+ {
+ return _Point3D.x();
+ }
+
+ /*! Returns the 3D y coordinate of the vertex .*/
+ virtual real getY() const
+ {
+ return _Point3D.y();
+ }
+
+ /*! Returns the 3D z coordinate of the vertex .*/
+ virtual real getZ() const
+ {
+ return _Point3D.z();
+ }
+
+ /*! Returns the 3D point. */
+ virtual Vec3f getPoint3D() const
+ {
+ return _Point3D;
+ }
+
+ /*! Returns the projected 3D x coordinate of the vertex .*/
+ virtual real getProjectedX() const
+ {
+ return _Point2D.x();
+ }
+
+ /*! Returns the projected 3D y coordinate of the vertex .*/
+ virtual real getProjectedY() const
+ {
+ return _Point2D.y();
+ }
+
+ /*! Returns the projected 3D z coordinate of the vertex .*/
+ virtual real getProjectedZ() const
+ {
+ return _Point2D.z();
+ }
+
+ /*! Returns the 2D point. */
+ virtual Vec2f getPoint2D() const
+ {
+ return Vec2f((float)_Point2D.x(), (float)_Point2D.y());
+ }
+
+ /*! Returns the FEdge that lies between this Svertex and the Interface0D given as argument. */
+ virtual FEdge *getFEdge(Interface0D&);
+
+ /*! Returns the Id of the vertex .*/
+ virtual Id getId() const
+ {
+ return _Id;
+ }
+
+ /*! Returns the nature of the vertex .*/
+ virtual Nature::VertexNature getNature() const;
+
+ /*! Cast the Interface0D in SVertex if it can be. */
+ virtual SVertex *castToSVertex();
+
+ /*! Cast the Interface0D in ViewVertex if it can be. */
+ virtual ViewVertex *castToViewVertex();
+
+ /*! Cast the Interface0D in NonTVertex if it can be. */
+ virtual NonTVertex *castToNonTVertex();
+
+ /*! Cast the Interface0D in TVertex if it can be. */
+ virtual TVertex *castToTVertex();
+
+public:
+ typedef vector<FEdge*> fedges_container;
+
+private:
+ Id _Id;
+ Vec3r _Point3D;
+ Vec3r _Point2D;
+ set<Vec3r> _Normals;
+ vector<FEdge*> _FEdges; // the edges containing this vertex
+ SShape *_Shape; // the shape to which belongs the vertex
+ ViewVertex *_pViewVertex; // The associated viewvertex, in case there is one.
+ real _curvatureFredo;
+ Vec2r _directionFredo;
+ CurvatureInfo *_curvature_info;
+
+public:
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void *userdata;
+
+ /*! Default constructor.*/
+ inline SVertex()
+ {
+ _Id = 0;
+ userdata = NULL;
+ _Shape = NULL;
+ _pViewVertex = 0;
+ _curvature_info = 0;
+ }
+
+ /*! Builds a SVertex from 3D coordinates and an Id. */
+ inline SVertex(const Vec3r &iPoint3D, const Id& id)
+ {
+ _Point3D = iPoint3D;
+ _Id = id;
+ userdata = NULL;
+ _Shape = NULL;
+ _pViewVertex = 0;
+ _curvature_info = 0;
+ }
+
+ /*! Copy constructor. */
+ inline SVertex(SVertex& iBrother)
+ {
+ _Id = iBrother._Id;
+ _Point3D = iBrother.point3D();
+ _Point2D = iBrother.point2D();
+ _Normals = iBrother._Normals;
+ _FEdges = iBrother.fedges();
+ _Shape = iBrother.shape();
+ _pViewVertex = iBrother._pViewVertex;
+ if (!(iBrother._curvature_info))
+ _curvature_info = 0;
+ else
+ _curvature_info = new CurvatureInfo(*(iBrother._curvature_info));
+ iBrother.userdata = this;
+ userdata = 0;
+ }
+
+ /*! Destructor. */
+ virtual ~SVertex()
+ {
+ if (_curvature_info)
+ delete _curvature_info;
+ }
+
+ /*! Cloning method. */
+ virtual SVertex *duplicate()
+ {
+ SVertex *clone = new SVertex(*this);
+ return clone;
+ }
+
+ /*! operator == */
+ virtual bool operator==(const SVertex& iBrother)
+ {
+ return ((_Point2D == iBrother._Point2D) && (_Point3D == iBrother._Point3D));
+ }
+
+ /* accessors */
+ inline const Vec3r& point3D() const
+ {
+ return _Point3D;
+ }
+
+ inline const Vec3r& point2D() const
+ {
+ return _Point2D;
+ }
+
+ /*! Returns the set of normals for this Vertex.
+ * In a smooth surface, a vertex has exactly one normal.
+ * In a sharp surface, a vertex can have any number of normals.
+ */
+ inline set<Vec3r> normals()
+ {
+ return _Normals;
+ }
+
+ /*! Returns the number of different normals for this vertex. */
+ inline unsigned normalsSize() const
+ {
+ return _Normals.size();
+ }
+
+ inline const vector<FEdge*>& fedges()
+ {
+ return _FEdges;
+ }
+
+ inline fedges_container::iterator fedges_begin()
+ {
+ return _FEdges.begin();
+ }
+
+ inline fedges_container::iterator fedges_end()
+ {
+ return _FEdges.end();
+ }
+
+ inline SShape *shape()
+ {
+ return _Shape;
+ }
+
+ inline real z() const
+ {
+ return _Point2D[2];
+ }
+
+ /*! If this SVertex is also a ViewVertex, this method returns a pointer onto this ViewVertex.
+ * 0 is returned otherwise.
+ */
+ inline ViewVertex *viewvertex()
+ {
+ return _pViewVertex;
+ }
+
+ /*! modifiers */
+ /*! Sets the 3D coordinates of the SVertex. */
+ inline void setPoint3D(const Vec3r &iPoint3D)
+ {
+ _Point3D = iPoint3D;
+ }
+
+ /*! Sets the 3D projected coordinates of the SVertex. */
+ inline void setPoint2D(const Vec3r &iPoint2D)
+ {
+ _Point2D = iPoint2D;
+ }
+
+ /*! Adds a normal to the Svertex's set of normals. If the same normal is already in the set, nothing changes. */
+ inline void AddNormal(const Vec3r& iNormal)
+ {
+ _Normals.insert(iNormal); // if iNormal in the set already exists, nothing is done
+ }
+
+ void setCurvatureInfo(CurvatureInfo *ci)
+ {
+ if (_curvature_info) // Q. is this an error condition? (T.K. 02-May-2011)
+ delete _curvature_info;
+ _curvature_info = ci;
+ }
+
+ const CurvatureInfo *getCurvatureInfo() const
+ {
+ return _curvature_info;
+ }
+
+ /* Fredo's normal and curvature*/
+ void setCurvatureFredo(real c)
+ {
+ _curvatureFredo = c;
+ }
+
+ void setDirectionFredo(Vec2r d)
+ {
+ _directionFredo = d;
+ }
+
+ real curvatureFredo ()
+ {
+ return _curvatureFredo;
+ }
+
+ const Vec2r directionFredo ()
+ {
+ return _directionFredo;
+ }
+
+ /*! Sets the Id */
+ inline void setId(const Id& id)
+ {
+ _Id = id;
+ }
+
+ inline void setFEdges(const vector<FEdge*>& iFEdges)
+ {
+ _FEdges = iFEdges;
+ }
+
+ inline void setShape(SShape *iShape)
+ {
+ _Shape = iShape;
+ }
+
+ inline void setViewVertex(ViewVertex *iViewVertex)
+ {
+ _pViewVertex = iViewVertex;
+ }
+
+ /*! Add an FEdge to the list of edges emanating from this SVertex. */
+ inline void AddFEdge(FEdge *iFEdge)
+ {
+ _FEdges.push_back(iFEdge);
+ }
+
+ /* replaces edge 1 by edge 2 in the list of edges */
+ inline void Replace(FEdge *e1, FEdge *e2)
+ {
+ vector<FEdge *>::iterator insertedfe;
+ for (vector<FEdge *>::iterator fe = _FEdges.begin(), fend = _FEdges.end(); fe != fend; fe++) {
+ if ((*fe) == e1) {
+ insertedfe = _FEdges.insert(fe, e2);// inserts e2 before fe.
+ // returns an iterator pointing toward e2. fe is invalidated.
+ // we want to remove e1, but we can't use fe anymore:
+ ++insertedfe; // insertedfe points now to e1
+ _FEdges.erase(insertedfe);
+ return;
+ }
+ }
+ }
+
+public:
+ /* Information access interface */
+ FEdge *fedge(); // for non T vertex
+
+ inline const Vec3r& point2d() const
+ {
+ return point2D();
+ }
+
+ inline const Vec3r& point3d() const
+ {
+ return point3D();
+ }
+
+ inline Vec3r normal() const
+ {
+ if (_Normals.size() == 1)
+ return (*(_Normals.begin()));
+ Exception::raiseException();
+ return *(_Normals.begin());
+ }
+
+ //Material material() const ;
+ Id shape_id() const;
+ const SShape *shape() const;
+ float shape_importance() const;
+
+ const int qi() const;
+ occluder_container::const_iterator occluders_begin() const;
+ occluder_container::const_iterator occluders_end() const;
+ bool occluders_empty() const;
+ int occluders_size() const;
+ const Polygon3r& occludee() const;
+ const SShape *occluded_shape() const;
+ const bool occludee_empty() const;
+ real z_discontinuity() const;
+#if 0
+ inline float local_average_depth() const;
+ inline float local_depth_variance() const;
+ inline real local_average_density(float sigma = 2.3f) const;
+ inline Vec3r shaded_color() const;
+ inline Vec3r orientation2d() const;
+ inline Vec3r orientation3d() const;
+ inline Vec3r curvature2d_as_vector() const;
+ /*! angle in radians */
+ inline real curvature2d_as_angle() const;
+#endif
+};
+
+/**********************************/
+/* */
+/* */
+/* FEdge */
+/* */
+/* */
+/**********************************/
+
+class ViewEdge;
+
+/*! Base Class for feature edges.
+ * This FEdge can represent a silhouette, a crease, a ridge/valley, a border or a suggestive contour.
+ * For silhouettes, the FEdge is oriented such as, the visible face lies on the left of the edge.
+ * For borders, the FEdge is oriented such as, the face lies on the left of the edge.
+ * An FEdge can represent an initial edge of the mesh or runs accross a face of the initial mesh depending
+ * on the smoothness or sharpness of the mesh.
+ * This class is specialized into a smooth and a sharp version since their properties slightly vary from
+ * one to the other.
+ */
+class LIB_VIEW_MAP_EXPORT FEdge : public Interface1D
+{
+public: // Implementation of Interface0D
+ /*! Returns the string "FEdge". */
+ virtual string getExactTypeName() const
+ {
+ return "FEdge";
+ }
+
+ // Data access methods
+
+ /*! Returns the 2D length of the FEdge. */
+ virtual real getLength2D() const
+ {
+ if (!_VertexA || !_VertexB)
+ return 0;
+ return (_VertexB->getPoint2D() - _VertexA->getPoint2D()).norm();
+ }
+
+ /*! Returns the Id of the FEdge. */
+ virtual Id getId() const
+ {
+ return _Id;
+ }
+
+public:
+ // An edge can only be of one kind (SILHOUETTE or BORDER, etc...)
+ // For an multi-nature edge there must be several different FEdge.
+ // DEBUG:
+ // Vec3r A;
+ // Vec3r u;
+ // vector<Polygon3r> _Occludees;
+ // Vec3r intersection;
+ // vector<Vec3i> _Cells;
+
+protected:
+ SVertex *_VertexA;
+ SVertex *_VertexB;
+ Id _Id;
+ Nature::EdgeNature _Nature;
+ //vector<Polygon3r> _Occluders; // visibility // NOT HANDLED BY THE COPY CONSTRUCTOR!!
+
+ FEdge *_NextEdge; // next edge on the chain
+ FEdge *_PreviousEdge;
+ ViewEdge *_ViewEdge;
+ // Sometimes we need to deport the visibility computation onto another edge. For example the exact edges use
+ // edges of the mesh to compute their visibility
+
+ Polygon3r _aFace; // The occluded face which lies on the right of a silhouette edge
+ Vec3r _occludeeIntersection;
+ bool _occludeeEmpty;
+
+ bool _isSmooth;
+
+ bool _isInImage;
+
+public:
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void *userdata;
+
+ /*! Default constructor */
+ inline FEdge()
+ {
+ userdata = NULL;
+ _VertexA = NULL;
+ _VertexB = NULL;
+ _Nature = Nature::NO_FEATURE;
+ _NextEdge = NULL;
+ _PreviousEdge = NULL;
+ _ViewEdge = NULL;
+ //_hasVisibilityPoint = false;
+ _occludeeEmpty = true;
+ _isSmooth = false;
+ _isInImage = true;
+ }
+
+ /*! Builds an FEdge going from vA to vB. */
+ inline FEdge(SVertex *vA, SVertex *vB)
+ {
+ userdata = NULL;
+ _VertexA = vA;
+ _VertexB = vB;
+ _Nature = Nature::NO_FEATURE;
+ _NextEdge = NULL;
+ _PreviousEdge = NULL;
+ _ViewEdge = NULL;
+ //_hasVisibilityPoint = false;
+ _occludeeEmpty = true;
+ _isSmooth = false;
+ _isInImage = true;
+ }
+
+ /*! Copy constructor */
+ inline FEdge(FEdge& iBrother)
+ {
+ _VertexA = iBrother.vertexA();
+ _VertexB = iBrother.vertexB();
+ _NextEdge = iBrother.nextEdge();
+ _PreviousEdge = iBrother._PreviousEdge;
+ _Nature = iBrother.getNature();
+ _Id = iBrother._Id;
+ _ViewEdge = iBrother._ViewEdge;
+ //_hasVisibilityPoint = iBrother._hasVisibilityPoint;
+ //_VisibilityPointA = iBrother._VisibilityPointA;
+ //_VisibilityPointB = iBrother._VisibilityPointB;
+ _aFace = iBrother._aFace;
+ _occludeeEmpty = iBrother._occludeeEmpty;
+ _isSmooth = iBrother._isSmooth;
+ _isInImage = iBrother._isInImage;
+ iBrother.userdata = this;
+ userdata = 0;
+ }
+
+ /*! Destructor */
+ virtual ~FEdge() {}
+
+ /*! Cloning method. */
+ virtual FEdge *duplicate()
+ {
+ FEdge *clone = new FEdge(*this);
+ return clone;
+ }
+
+ /* accessors */
+ /*! Returns the first SVertex. */
+ inline SVertex *vertexA()
+ {
+ return _VertexA;
+ }
+
+ /*! Returns the second SVertex. */
+ inline SVertex *vertexB()
+ {
+ return _VertexB;
+ }
+
+ /*! Returns the first SVertex if i=0, the seccond SVertex if i=1. */
+ inline SVertex *operator[](const unsigned short int& i) const
+ {
+ return (i % 2 == 0) ? _VertexA : _VertexB;
+ }
+
+ /*! Returns the nature of the FEdge. */
+ inline Nature::EdgeNature getNature() const
+ {
+ return _Nature;
+ }
+
+ /*! Returns the FEdge following this one in the ViewEdge.
+ * If this FEdge is the last of the ViewEdge, 0 is returned.
+ */
+ inline FEdge *nextEdge()
+ {
+ return _NextEdge;
+ }
+
+ /*! Returns the Edge preceding this one in the ViewEdge.
+ * If this FEdge is the first one of the ViewEdge, 0 is returned.
+ */
+ inline FEdge *previousEdge()
+ {
+ return _PreviousEdge;
+ }
+
+ inline SShape *shape()
+ {
+ return _VertexA->shape();
+ }
+
+#if 0
+ inline int invisibility() const
+ {
+ return _Occluders.size();
+ }
+#endif
+
+ int invisibility() const;
+
+#if 0
+ inline const vector<Polygon3r>& occluders() const
+ {
+ return _Occluders;
+ }
+#endif
+
+ /*! Returns a pointer to the ViewEdge to which this FEdge belongs to. */
+ inline ViewEdge *viewedge() const
+ {
+ return _ViewEdge;
+ }
+
+ inline Vec3r center3d()
+ {
+ return Vec3r((_VertexA->point3D() + _VertexB->point3D()) / 2.0);
+ }
+
+ inline Vec3r center2d()
+ {
+ return Vec3r((_VertexA->point2D() + _VertexB->point2D()) / 2.0);
+ }
+
+#if 0
+ inline bool hasVisibilityPoint() const
+ {
+ return _hasVisibilityPoint;
+ }
+
+ inline Vec3r visibilityPointA() const
+ {
+ return _VisibilityPointA;
+ }
+
+ inline Vec3r visibilityPointB() const
+ {
+ return _VisibilityPointB;
+ }
+#endif
+
+ inline const Polygon3r& aFace() const
+ {
+ return _aFace;
+ }
+
+ inline const Vec3r& getOccludeeIntersection()
+ {
+ return _occludeeIntersection;
+ }
+
+ inline bool getOccludeeEmpty()
+ {
+ return _occludeeEmpty;
+ }
+
+ /*! Returns true if this FEdge is a smooth FEdge. */
+ inline bool isSmooth() const
+ {
+ return _isSmooth;
+ }
+
+ inline bool isInImage () const
+ {
+ return _isInImage;
+ }
+
+ /* modifiers */
+ /*! Sets the first SVertex. */
+ inline void setVertexA(SVertex *vA)
+ {
+ _VertexA = vA;
+ }
+
+ /*! Sets the second SVertex. */
+ inline void setVertexB(SVertex *vB)
+ {
+ _VertexB = vB;
+ }
+
+ /*! Sets the FEdge Id . */
+ inline void setId(const Id& id)
+ {
+ _Id = id;
+ }
+
+ /*! Sets the pointer to the next FEdge. */
+ inline void setNextEdge(FEdge *iEdge)
+ {
+ _NextEdge = iEdge;
+ }
+
+ /*! Sets the pointer to the previous FEdge. */
+ inline void setPreviousEdge(FEdge *iEdge)
+ {
+ _PreviousEdge = iEdge;
+ }
+
+ /*! Sets the nature of this FEdge. */
+ inline void setNature(Nature::EdgeNature iNature)
+ {
+ _Nature = iNature;
+ }
+
+#if 0
+ inline void AddOccluder(Polygon3r& iPolygon)
+ {
+ _Occluders.push_back(iPolygon);
+ }
+#endif
+
+ /*! Sets the ViewEdge to which this FEdge belongs to. */
+ inline void setViewEdge(ViewEdge *iViewEdge)
+ {
+ _ViewEdge = iViewEdge;
+ }
+
+#if 0
+ inline void setHasVisibilityPoint(bool iBool)
+ {
+ _hasVisibilityPoint = iBool;
+ }
+
+ inline void setVisibilityPointA(const Vec3r& iPoint)
+ {
+ _VisibilityPointA = iPoint;
+ }
+
+ inline void setVisibilityPointB(const Vec3r& iPoint)
+ {
+ _VisibilityPointB = iPoint;
+ }
+#endif
+
+ inline void setaFace(Polygon3r& iFace)
+ {
+ _aFace = iFace;
+ }
+
+ inline void setOccludeeIntersection(const Vec3r& iPoint)
+ {
+ _occludeeIntersection = iPoint;
+ }
+
+ inline void setOccludeeEmpty(bool iempty)
+ {
+ _occludeeEmpty = iempty;
+ }
+
+ /*! Sets the flag telling whether this FEdge is smooth or sharp.
+ * true for Smooth, false for Sharp.
+ */
+ inline void setSmooth(bool iFlag)
+ {
+ _isSmooth = iFlag;
+ }
+
+ inline void setIsInImage (bool iFlag)
+ {
+ _isInImage = iFlag;
+ }
+
+ /* checks whether two FEdge have a common vertex.
+ * Returns a pointer on the common vertex if it exists, NULL otherwise.
+ */
+ static inline SVertex *CommonVertex(FEdge *iEdge1, FEdge *iEdge2)
+ {
+ if ((NULL == iEdge1) || (NULL == iEdge2))
+ return NULL;
+
+ SVertex *sv1 = iEdge1->vertexA();
+ SVertex *sv2 = iEdge1->vertexB();
+ SVertex *sv3 = iEdge2->vertexA();
+ SVertex *sv4 = iEdge2->vertexB();
+
+ if ((sv1 == sv3) || (sv1 == sv4)) {
+ return sv1;
+ }
+ else if ((sv2 == sv3) || (sv2 == sv4)) {
+ return sv2;
+ }
+
+ return NULL;
+ }
+
+ inline const SVertex *min2d() const
+ {
+ if (_VertexA->point2D() < _VertexB->point2D())
+ return _VertexA;
+ else
+ return _VertexB;
+ }
+
+ inline const SVertex *max2d() const
+ {
+ if (_VertexA->point2D() < _VertexB->point2D())
+ return _VertexB;
+ else
+ return _VertexA;
+ }
+
+ /* Information access interface */
+
+ //Material material() const;
+ Id shape_id() const;
+ const SShape *shape() const;
+ float shape_importance() const;
+
+ inline const int qi() const
+ {
+ return invisibility();
+ }
+
+ occluder_container::const_iterator occluders_begin() const;
+ occluder_container::const_iterator occluders_end() const;
+ bool occluders_empty() const;
+ int occluders_size() const;
+
+ inline const Polygon3r& occludee() const
+ {
+ return aFace();
+ }
+
+ const SShape *occluded_shape() const;
+
+#if 0
+ inline const bool occludee_empty() const
+ {
+ return _occludeeEmpty;
+ }
+#endif
+
+ const bool occludee_empty() const;
+ real z_discontinuity() const;
+
+#if 0
+ inline float local_average_depth(int iCombination = 0) const;
+ inline float local_depth_variance(int iCombination = 0) const;
+ inline real local_average_density(float sigma = 2.3f, int iCombination = 0) const;
+ inline Vec3r shaded_color(int iCombination = 0) const {}
+#endif
+
+ int viewedge_nature() const;
+
+ //float viewedge_length() const;
+
+ inline Vec3r orientation2d() const
+ {
+ return Vec3r(_VertexB->point2d() - _VertexA->point2d());
+ }
+
+ inline Vec3r orientation3d() const
+ {
+ return Vec3r(_VertexB->point3d() - _VertexA->point3d());
+ }
+
+#if 0
+ inline real curvature2d() const
+ {
+ return viewedge()->curvature2d((_VertexA->point2d() + _VertexB->point2d()) / 2.0);
+ }
+
+ inline Vec3r curvature2d_as_vector(int iCombination = 0) const;
+
+ /* angle in degrees*/
+ inline real curvature2d_as_angle(int iCombination = 0) const;
+#endif
+
+ // Iterator access (Interface1D)
+ /*! Returns an iterator over the 2 (!) SVertex pointing to the first SVertex. */
+ virtual inline Interface0DIterator verticesBegin();
+
+ /*! Returns an iterator over the 2 (!) SVertex pointing after the last SVertex. */
+ virtual inline Interface0DIterator verticesEnd();
+
+ /*! Returns an iterator over the FEdge points, pointing to the first point. The difference with verticesBegin()
+ * is that here we can iterate over points of the FEdge at a any given sampling.
+ * Indeed, for each iteration, a virtual point is created.
+ * \param t
+ * The sampling with which we want to iterate over points of this FEdge.
+ */
+ virtual inline Interface0DIterator pointsBegin(float t = 0.0f);
+
+ /*! Returns an iterator over the FEdge points, pointing after the last point. The difference with verticesEnd()
+ * is that here we can iterate over points of the FEdge at a any given sampling.
+ * Indeed, for each iteration, a virtual point is created.
+ * \param t
+ * The sampling with which we want to iterate over points of this FEdge.
+ */
+ virtual inline Interface0DIterator pointsEnd(float t = 0.0f);
+};
+
+//
+// SVertexIterator
+//
+/////////////////////////////////////////////////
+
+namespace FEdgeInternal {
+
+class SVertexIterator : public Interface0DIteratorNested
+{
+public:
+ SVertexIterator()
+ {
+ _vertex = NULL;
+ _edge = NULL;
+ }
+
+ SVertexIterator(const SVertexIterator& vi)
+ {
+ _vertex = vi._vertex;
+ _edge = vi._edge;
+ }
+
+ SVertexIterator(SVertex *v, FEdge *edge)
+ {
+ _vertex = v;
+ _edge = edge;
+ }
+
+ SVertexIterator& operator=(const SVertexIterator& vi)
+ {
+ _vertex = vi._vertex;
+ _edge = vi._edge;
+ return *this;
+ }
+
+ virtual string getExactTypeName() const
+ {
+ return "SVertexIterator";
+ }
+
+ virtual SVertex& operator*()
+ {
+ return *_vertex;
+ }
+
+ virtual SVertex *operator->()
+ {
+ return &(operator*());
+ }
+
+ virtual SVertexIterator& operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ virtual SVertexIterator operator++(int)
+ {
+ SVertexIterator ret(*this);
+ increment();
+ return ret;
+ }
+
+ virtual SVertexIterator& operator--()
+ {
+ decrement();
+ return *this;
+ }
+
+ virtual SVertexIterator operator--(int)
+ {
+ SVertexIterator ret(*this);
+ decrement();
+ return ret;
+ }
+
+ virtual int increment()
+ {
+ if (_vertex == _edge->vertexB()) {
+ _vertex = 0;
+ return 0;
+ }
+ _vertex = _edge->vertexB();
+ return 0;
+ }
+
+ virtual int decrement()
+ {
+ if (_vertex == _edge->vertexA()) {
+ _vertex = 0;
+ return 0;
+ }
+ _vertex = _edge->vertexA();
+ return 0;
+ }
+
+ virtual bool isBegin() const
+ {
+ return _vertex == _edge->vertexA();
+ }
+
+ virtual bool isEnd() const
+ {
+ return _vertex == _edge->vertexB();
+ }
+
+ virtual bool operator==(const Interface0DIteratorNested& it) const
+ {
+ const SVertexIterator *it_exact = dynamic_cast<const SVertexIterator*>(&it);
+ if (!it_exact)
+ return false;
+ return ((_vertex == it_exact->_vertex) && (_edge == it_exact->_edge));
+ }
+
+ virtual float t() const
+ {
+ if (_vertex == _edge->vertexA()) {
+ return 0.0f;
+ }
+ return ((float)_edge->getLength2D());
+ }
+ virtual float u() const
+ {
+ if (_vertex == _edge->vertexA()) {
+ return 0.0f;
+ }
+ return 1.0f;
+ }
+
+ virtual SVertexIterator *copy() const
+ {
+ return new SVertexIterator(*this);
+ }
+
+private:
+ SVertex *_vertex;
+ FEdge *_edge;
+};
+
+} // end of namespace FEdgeInternal
+
+// Iterator access (implementation)
+
+Interface0DIterator FEdge::verticesBegin()
+{
+ Interface0DIterator ret(new FEdgeInternal::SVertexIterator(_VertexA, this));
+ return ret;
+}
+
+Interface0DIterator FEdge::verticesEnd()
+{
+ Interface0DIterator ret(new FEdgeInternal::SVertexIterator(0, this));
+ return ret;
+}
+
+Interface0DIterator FEdge::pointsBegin(float t)
+{
+ return verticesBegin();
+}
+
+Interface0DIterator FEdge::pointsEnd(float t)
+{
+ return verticesEnd();
+}
+
+/*! Class defining a sharp FEdge. A Sharp FEdge corresponds to an initial edge of the input mesh.
+ * It can be a silhouette, a crease or a border. If it is a crease edge, then it is borded
+ * by two faces of the mesh. Face a lies on its right whereas Face b lies on its left.
+ * If it is a border edge, then it doesn't have any face on its right, and thus Face a = 0.
+ */
+class LIB_VIEW_MAP_EXPORT FEdgeSharp : public FEdge
+{
+protected:
+ Vec3r _aNormal; // When following the edge, normal of the right face
+ Vec3r _bNormal; // When following the edge, normal of the left face
+ unsigned _aFrsMaterialIndex;
+ unsigned _bFrsMaterialIndex;
+ bool _aFaceMark;
+ bool _bFaceMark;
+
+public:
+ /*! Returns the string "FEdgeSharp" . */
+ virtual string getExactTypeName() const
+ {
+ return "FEdgeSharp";
+ }
+
+ /*! Default constructor. */
+ inline FEdgeSharp() : FEdge()
+ {
+ _aFrsMaterialIndex = _bFrsMaterialIndex = 0;
+ _aFaceMark = _bFaceMark = false;
+ }
+
+ /*! Builds an FEdgeSharp going from vA to vB. */
+ inline FEdgeSharp(SVertex *vA, SVertex *vB) : FEdge(vA, vB)
+ {
+ _aFrsMaterialIndex = _bFrsMaterialIndex = 0;
+ _aFaceMark = _bFaceMark = false;
+ }
+
+ /*! Copy constructor. */
+ inline FEdgeSharp(FEdgeSharp& iBrother) : FEdge(iBrother)
+ {
+ _aNormal = iBrother._aNormal;
+ _bNormal = iBrother._bNormal;
+ _aFrsMaterialIndex = iBrother._aFrsMaterialIndex;
+ _bFrsMaterialIndex = iBrother._bFrsMaterialIndex;
+ _aFaceMark = iBrother._aFaceMark;
+ _bFaceMark = iBrother._bFaceMark;
+ }
+
+ /*! Destructor. */
+ virtual ~FEdgeSharp() {}
+
+ /*! Cloning method. */
+ virtual FEdge *duplicate()
+ {
+ FEdge *clone = new FEdgeSharp(*this);
+ return clone;
+ }
+
+ /*! Returns the normal to the face lying on the right of the FEdge. If this FEdge is a border,
+ * it has no Face on its right and therefore, no normal.
+ */
+ inline const Vec3r& normalA()
+ {
+ return _aNormal;
+ }
+
+ /*! Returns the normal to the face lying on the left of the FEdge. */
+ inline const Vec3r& normalB()
+ {
+ return _bNormal;
+ }
+
+ /*! Returns the index of the material of the face lying on the
+ * right of the FEdge. If this FEdge is a border,
+ * it has no Face on its right and therefore, no material.
+ */
+ inline unsigned aFrsMaterialIndex() const
+ {
+ return _aFrsMaterialIndex;
+ }
+
+ /*! Returns the material of the face lying on the right of the FEdge. If this FEdge is a border,
+ * it has no Face on its right and therefore, no material.
+ */
+ const FrsMaterial& aFrsMaterial() const;
+
+ /*! Returns the index of the material of the face lying on the left of the FEdge. */
+ inline unsigned bFrsMaterialIndex() const
+ {
+ return _bFrsMaterialIndex;
+ }
+
+ /*! Returns the material of the face lying on the left of the FEdge. */
+ const FrsMaterial& bFrsMaterial() const;
+
+ /*! Returns the face mark of the face lying on the right of the FEdge.
+ * If this FEdge is a border, it has no Face on its right and thus false is returned.
+ */
+ inline bool aFaceMark() const
+ {
+ return _aFaceMark;
+ }
+
+ /*! Returns the face mark of the face lying on the left of the FEdge. */
+ inline bool bFaceMark() const
+ {
+ return _bFaceMark;
+ }
+
+ /*! Sets the normal to the face lying on the right of the FEdge. */
+ inline void setNormalA(const Vec3r& iNormal)
+ {
+ _aNormal = iNormal;
+ }
+
+ /*! Sets the normal to the face lying on the left of the FEdge. */
+ inline void setNormalB(const Vec3r& iNormal)
+ {
+ _bNormal = iNormal;
+ }
+
+ /*! Sets the index of the material lying on the right of the FEdge.*/
+ inline void setaFrsMaterialIndex(unsigned i)
+ {
+ _aFrsMaterialIndex = i;
+ }
+
+ /*! Sets the index of the material lying on the left of the FEdge.*/
+ inline void setbFrsMaterialIndex(unsigned i)
+ {
+ _bFrsMaterialIndex = i;
+ }
+
+ /*! Sets the face mark of the face lying on the right of the FEdge. */
+ inline void setaFaceMark(bool iFaceMark)
+ {
+ _aFaceMark = iFaceMark;
+ }
+
+ /*! Sets the face mark of the face lying on the left of the FEdge. */
+ inline void setbFaceMark(bool iFaceMark)
+ {
+ _bFaceMark = iFaceMark;
+ }
+};
+
+/*! Class defining a smooth edge. This kind of edge typically runs across a face of the input mesh. It can be
+ * a silhouette, a ridge or valley, a suggestive contour.
+ */
+class LIB_VIEW_MAP_EXPORT FEdgeSmooth : public FEdge
+{
+protected:
+ Vec3r _Normal;
+ unsigned _FrsMaterialIndex;
+#if 0
+ bool _hasVisibilityPoint;
+ Vec3r _VisibilityPointA; // The edge on which the visibility will be computed represented
+ Vec3r _VisibilityPointB; // using its 2 extremity points A and B
+#endif
+ void *_Face; // In case of exact silhouette, Face is the WFace crossed by Fedge
+ // NOT HANDLED BY THE COPY CONSTRUCTEUR
+ bool _FaceMark;
+
+public:
+ /*! Returns the string "FEdgeSmooth" . */
+ virtual string getExactTypeName() const
+ {
+ return "FEdgeSmooth";
+ }
+
+ /*! Default constructor. */
+ inline FEdgeSmooth() : FEdge()
+ {
+ _Face = NULL;
+ _FaceMark = false;
+ _FrsMaterialIndex = 0;
+ _isSmooth = true;
+ }
+
+ /*! Builds an FEdgeSmooth going from vA to vB. */
+ inline FEdgeSmooth(SVertex *vA, SVertex *vB) : FEdge(vA, vB)
+ {
+ _Face = NULL;
+ _FaceMark = false;
+ _FrsMaterialIndex = 0;
+ _isSmooth = true;
+ }
+
+ /*! Copy constructor. */
+ inline FEdgeSmooth(FEdgeSmooth& iBrother) : FEdge(iBrother)
+ {
+ _Normal = iBrother._Normal;
+ _Face = iBrother._Face;
+ _FaceMark = iBrother._FaceMark;
+ _FrsMaterialIndex = iBrother._FrsMaterialIndex;
+ _isSmooth = true;
+ }
+
+ /*! Destructor. */
+ virtual ~FEdgeSmooth() {}
+
+ /*! Cloning method. */
+ virtual FEdge *duplicate()
+ {
+ FEdge *clone = new FEdgeSmooth(*this);
+ return clone;
+ }
+
+ inline void *face() const
+ {
+ return _Face;
+ }
+
+ /*! Returns the face mark of the face it is running across. */
+ inline bool faceMark() const
+ {
+ return _FaceMark;
+ }
+
+ /*! Returns the normal to the Face it is running accross. */
+ inline const Vec3r& normal()
+ {
+ return _Normal;
+ }
+
+ /*! Returns the index of the material of the face it is running accross. */
+ inline unsigned frs_materialIndex() const
+ {
+ return _FrsMaterialIndex;
+ }
+
+ /*! Returns the material of the face it is running accross. */
+ const FrsMaterial& frs_material() const;
+
+ inline void setFace(void *iFace)
+ {
+ _Face = iFace;
+ }
+
+ /*! Sets the face mark of the face it is running across. */
+ inline void setFaceMark(bool iFaceMark)
+ {
+ _FaceMark = iFaceMark;
+ }
+
+ /*! Sets the normal to the Face it is running accross. */
+ inline void setNormal(const Vec3r& iNormal)
+ {
+ _Normal = iNormal;
+ }
+
+ /*! Sets the index of the material of the face it is running accross. */
+ inline void setFrsMaterialIndex(unsigned i)
+ {
+ _FrsMaterialIndex = i;
+ }
+};
+
+
+/**********************************/
+/* */
+/* */
+/* SShape */
+/* */
+/* */
+/**********************************/
+
+
+/*! Class to define a feature shape. It is the gathering of feature elements from an identified input shape */
+class LIB_VIEW_MAP_EXPORT SShape
+{
+private:
+ vector<FEdge*> _chains; // list of fedges that are chains starting points.
+ vector<SVertex*> _verticesList; // list of all vertices
+ vector<FEdge*> _edgesList; // list of all edges
+ Id _Id;
+ string _Name;
+ BBox<Vec3r> _BBox;
+ vector<FrsMaterial> _FrsMaterials;
+
+ float _importance;
+
+ ViewShape *_ViewShape;
+
+public:
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void *userdata; // added by E.T.
+
+ /*! Default constructor */
+ inline SShape()
+ {
+ userdata = NULL;
+ _importance = 0.0f;
+ _ViewShape = NULL;
+ }
+
+ /*! Copy constructor */
+ inline SShape(SShape& iBrother)
+ {
+ userdata = NULL;
+ _Id = iBrother._Id;
+ _Name = iBrother._Name;
+ _BBox = iBrother.bbox();
+ _FrsMaterials = iBrother._FrsMaterials;
+ _importance = iBrother._importance;
+ _ViewShape = iBrother._ViewShape;
+
+ //---------
+ // vertices
+ //---------
+ vector<SVertex*>::iterator sv, svend;
+ vector<SVertex*>& verticesList = iBrother.getVertexList();
+ for (sv = verticesList.begin(), svend = verticesList.end(); sv != svend; sv++) {
+ SVertex *newv = new SVertex(*(*sv));
+ newv->setShape(this);
+ _verticesList.push_back(newv);
+ }
+
+ //------
+ // edges
+ //------
+ vector<FEdge*>::iterator e, eend;
+ vector<FEdge*>& edgesList = iBrother.getEdgeList();
+ for (e = edgesList.begin(), eend = edgesList.end(); e != eend; e++) {
+ FEdge *newe = (*e)->duplicate();
+ _edgesList.push_back(newe);
+ }
+
+ //-------------------------
+ // starting chain edges
+ //-------------------------
+ vector<FEdge*>::iterator fe, fend;
+ vector<FEdge*>& fedges = iBrother.getChains();
+ for (fe = fedges.begin(), fend = fedges.end(); fe != fend; fe++) {
+ _chains.push_back((FEdge *)((*fe)->userdata));
+ }
+
+ //-------------------------
+ // remap edges in vertices:
+ //-------------------------
+ for (sv = _verticesList.begin(), svend = _verticesList.end(); sv != svend; sv++) {
+ const vector<FEdge*>& fedgeList = (*sv)->fedges();
+ vector<FEdge*> newfedgelist;
+ for (vector<FEdge*>::const_iterator fed = fedgeList.begin(), fedend = fedgeList.end();
+ fed != fedend;
+ fed++)
+ {
+ FEdge *current = *fed;
+ newfedgelist.push_back((FEdge *)current->userdata);
+ }
+ (*sv)->setFEdges(newfedgelist);
+ }
+
+ //-------------------------------------
+ // remap vertices and nextedge in edges:
+ //-------------------------------------
+ for (e = _edgesList.begin(), eend = _edgesList.end(); e != eend; e++) {
+ (*e)->setVertexA((SVertex *)((*e)->vertexA()->userdata));
+ (*e)->setVertexB((SVertex *)((*e)->vertexB()->userdata));
+ (*e)->setNextEdge((FEdge *)((*e)->nextEdge()->userdata));
+ (*e)->setPreviousEdge((FEdge *)((*e)->previousEdge()->userdata));
+ }
+
+ // reset all brothers userdata to NULL:
+ //-------------------------------------
+ //---------
+ // vertices
+ //---------
+ for (sv = _verticesList.begin(), svend = _verticesList.end(); sv != svend; sv++) {
+ (*sv)->userdata = NULL;
+ }
+
+ //------
+ // edges
+ //------
+ for (e = _edgesList.begin(), eend = _edgesList.end(); e != eend; e++) {
+ (*e)->userdata = NULL;
+ }
+ }
+
+ /*! Cloning method. */
+ virtual SShape *duplicate()
+ {
+ SShape *clone = new SShape(*this);
+ return clone;
+ }
+
+ /*! Destructor. */
+ virtual inline ~SShape()
+ {
+ vector<SVertex*>::iterator sv, svend;
+ vector<FEdge*>::iterator e, eend;
+ if (0 != _verticesList.size()) {
+ for (sv = _verticesList.begin(), svend = _verticesList.end(); sv != svend; sv++) {
+ delete (*sv);
+ }
+ _verticesList.clear();
+ }
+
+ if (0 != _edgesList.size()) {
+ for (e = _edgesList.begin(), eend = _edgesList.end(); e != eend; e++) {
+ delete (*e);
+ }
+ _edgesList.clear();
+ }
+
+ //! Clear the chains list
+ //-----------------------
+ if (0 != _chains.size()) {
+ _chains.clear();
+ }
+ }
+
+ /*! Adds a FEdge to the list of FEdges. */
+ inline void AddEdge(FEdge *iEdge)
+ {
+ _edgesList.push_back(iEdge);
+ }
+
+ /*! Adds a SVertex to the list of SVertex of this Shape.
+ * The SShape attribute of the SVertex is also set to 'this'.
+ */
+ inline void AddNewVertex(SVertex *iv)
+ {
+ iv->setShape(this);
+ _verticesList.push_back(iv);
+ }
+
+ inline void AddChain(FEdge *iEdge)
+ {
+ _chains.push_back(iEdge);
+ }
+
+ inline SVertex *CreateSVertex(const Vec3r& P3D, const Vec3r& P2D, const Id& id)
+ {
+ SVertex *Ia = new SVertex(P3D, id);
+ Ia->setPoint2D(P2D);
+ AddNewVertex(Ia);
+ return Ia;
+ }
+
+ /*! Splits an edge into several edges.
+ * The edge's vertices are passed rather than the edge itself. This way, all feature edges (SILHOUETTE,
+ * CREASE, BORDER) are splitted in the same time.
+ * The processed edges are flagged as done (using the userdata flag).One single new vertex is created whereas
+ * several splitted edges might created for the different kinds of edges. These new elements are added to the lists
+ * maintained by the shape.
+ * New chains are also created.
+ * ioA
+ * The first vertex for the edge that gets splitted
+ * ioB
+ * The second vertex for the edge that gets splitted
+ * iParameters
+ * A vector containing 2D real vectors indicating the parameters giving the intersections coordinates in
+ * 3D and in 2D. These intersections points must be sorted from B to A.
+ * Each parameter defines the intersection point I as I=A+T*AB. T<0 and T>1 are then incorrect insofar as
+ * they give intersections points that lie outside the segment.
+ * ioNewEdges
+ * The edges that are newly created (the initial edges are not included) are added to this list.
+ */
+ inline void SplitEdge(FEdge *fe, const vector<Vec2r>& iParameters, vector<FEdge*>& ioNewEdges)
+ {
+ SVertex *ioA = fe->vertexA();
+ SVertex *ioB = fe->vertexB();
+ Vec3r A = ioA->point3D();
+ Vec3r B = ioB->point3D();
+ Vec3r a = ioA->point2D();
+ Vec3r b = ioB->point2D();
+
+ Vec3r newpoint3d, newpoint2d;
+ vector<SVertex*> intersections;
+ real t, T;
+ for (vector<Vec2r>::const_iterator p = iParameters.begin(), pend = iParameters.end(); p != pend; p++) {
+ T = (*p)[0];
+ t = (*p)[1];
+
+ if ((t < 0) || (t > 1))
+ cerr << "Warning: Intersection out of range for edge " << ioA->getId() << " - " << ioB->getId() << endl;
+
+ // compute the 3D and 2D coordinates for the intersections points:
+ newpoint3d = Vec3r(A + T * (B - A));
+ newpoint2d = Vec3r(a + t * (b - a));
+
+ // create new SVertex:
+ // (we keep B's id)
+ SVertex *newVertex = new SVertex(newpoint3d, ioB->getId());
+ newVertex->setPoint2D(newpoint2d);
+
+ // Add this vertex to the intersections list:
+ intersections.push_back(newVertex);
+
+ // Add this vertex to this sshape:
+ AddNewVertex(newVertex);
+ }
+
+ for (vector<SVertex*>::iterator sv = intersections.begin(), svend = intersections.end(); sv != svend; sv++) {
+ //SVertex *svA = fe->vertexA();
+ SVertex *svB = fe->vertexB();
+
+ // We split edge AB into AA' and A'B. A' and A'B are created.
+ // AB becomes (address speaking) AA'. B is updated.
+ //--------------------------------------------------
+ // The edge AB becomes edge AA'.
+ (fe)->setVertexB((*sv));
+ // a new edge, A'B is created.
+ FEdge *newEdge;
+ if (fe->isSmooth()) {
+ newEdge = new FEdgeSmooth((*sv), svB);
+ FEdgeSmooth *se = dynamic_cast<FEdgeSmooth*>(newEdge);
+ FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth*>(fe);
+ se->setFrsMaterialIndex(fes->frs_materialIndex());
+ }
+ else {
+ newEdge = new FEdgeSharp((*sv), svB);
+ FEdgeSharp *se = dynamic_cast<FEdgeSharp*>(newEdge);
+ FEdgeSharp *fes = dynamic_cast<FEdgeSharp*>(fe);
+ se->setaFrsMaterialIndex(fes->aFrsMaterialIndex());
+ se->setbFrsMaterialIndex(fes->bFrsMaterialIndex());
+ }
+
+ newEdge->setNature((fe)->getNature());
+
+ // to build a new chain:
+ AddChain(newEdge);
+ // add the new edge to the sshape edges list.
+ AddEdge(newEdge);
+ // add new edge to the list of new edges passed as argument:
+ ioNewEdges.push_back(newEdge);
+
+ // update edge A'B for the next pointing edge
+ newEdge->setNextEdge((fe)->nextEdge());
+ fe->nextEdge()->setPreviousEdge(newEdge);
+ Id id(fe->getId().getFirst(), fe->getId().getSecond() + 1);
+ newEdge->setId(fe->getId());
+ fe->setId(id);
+
+ // update edge AA' for the next pointing edge
+ //ioEdge->setNextEdge(newEdge);
+ (fe)->setNextEdge(NULL);
+
+ // update vertex pointing edges list:
+ // -- vertex B --
+ svB->Replace((fe), newEdge);
+ // -- vertex A' --
+ (*sv)->AddFEdge((fe));
+ (*sv)->AddFEdge(newEdge);
+ }
+ }
+
+ /* splits an edge into 2 edges. The new vertex and edge are added to the sshape list of vertices and edges
+ * a new chain is also created.
+ * returns the new edge.
+ * ioEdge
+ * The edge that gets splitted
+ * newpoint
+ * x,y,z coordinates of the new point.
+ */
+ inline FEdge *SplitEdgeIn2(FEdge *ioEdge, SVertex *ioNewVertex)
+ {
+ //soc unused - SVertex *A = ioEdge->vertexA();
+ SVertex *B = ioEdge->vertexB();
+
+ // We split edge AB into AA' and A'B. A' and A'B are created.
+ // AB becomes (address speaking) AA'. B is updated.
+ //--------------------------------------------------
+ // a new edge, A'B is created.
+ FEdge *newEdge;
+ if (ioEdge->isSmooth()) {
+ newEdge = new FEdgeSmooth(ioNewVertex, B);
+ FEdgeSmooth *se = dynamic_cast<FEdgeSmooth*>(newEdge);
+ FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth*>(ioEdge);
+ se->setNormal(fes->normal());
+ se->setFrsMaterialIndex(fes->frs_materialIndex());
+ }
+ else {
+ newEdge = new FEdgeSharp(ioNewVertex, B);
+ FEdgeSharp *se = dynamic_cast<FEdgeSharp*>(newEdge);
+ FEdgeSharp *fes = dynamic_cast<FEdgeSharp*>(ioEdge);
+ se->setNormalA(fes->normalA());
+ se->setNormalB(fes->normalB());
+ se->setaFrsMaterialIndex(fes->aFrsMaterialIndex());
+ se->setbFrsMaterialIndex(fes->bFrsMaterialIndex());
+ }
+ newEdge->setNature(ioEdge->getNature());
+
+ if (ioEdge->nextEdge() != 0)
+ ioEdge->nextEdge()->setPreviousEdge(newEdge);
+
+ // update edge A'B for the next pointing edge
+ newEdge->setNextEdge(ioEdge->nextEdge());
+ // update edge A'B for the previous pointing edge
+ newEdge->setPreviousEdge(0); // because it is now a TVertex
+ Id id(ioEdge->getId().getFirst(), ioEdge->getId().getSecond() + 1);
+ newEdge->setId(ioEdge->getId());
+ ioEdge->setId(id);
+
+ // update edge AA' for the next pointing edge
+ ioEdge->setNextEdge(0); // because it is now a TVertex
+
+ // update vertex pointing edges list:
+ // -- vertex B --
+ B->Replace(ioEdge, newEdge);
+ // -- vertex A' --
+ ioNewVertex->AddFEdge(ioEdge);
+ ioNewVertex->AddFEdge(newEdge);
+
+ // to build a new chain:
+ AddChain(newEdge);
+ AddEdge(newEdge); // FIXME ??
+
+ // The edge AB becomes edge AA'.
+ ioEdge->setVertexB(ioNewVertex);
+
+ if (ioEdge->isSmooth()) {
+ ((FEdgeSmooth *)newEdge)->setFace(((FEdgeSmooth *)ioEdge)->face());
+ }
+
+ return newEdge;
+ }
+
+ /*! Sets the Bounding Box of the Shape */
+ inline void setBBox(const BBox<Vec3r>& iBBox)
+ {
+ _BBox = iBBox;
+ }
+
+ /*! Compute the bbox of the sshape */
+ inline void ComputeBBox()
+ {
+ if (0 == _verticesList.size())
+ return;
+
+ Vec3r firstVertex = _verticesList[0]->point3D();
+ real XMax = firstVertex[0];
+ real YMax = firstVertex[1];
+ real ZMax = firstVertex[2];
+
+ real XMin = firstVertex[0];
+ real YMin = firstVertex[1];
+ real ZMin = firstVertex[2];
+
+ vector<SVertex*>::iterator v, vend;
+ // parse all the coordinates to find the Xmax, YMax, ZMax
+ for (v = _verticesList.begin(), vend = _verticesList.end(); v != vend; v++) {
+ Vec3r vertex = (*v)->point3D();
+ // X
+ real x = vertex[0];
+ if (x > XMax)
+ XMax = x;
+ else if (x < XMin)
+ XMin = x;
+
+ // Y
+ real y = vertex[1];
+ if (y > YMax)
+ YMax = y;
+ else if (y < YMin)
+ YMin = y;
+
+ // Z
+ real z = vertex[2];
+ if (z > ZMax)
+ ZMax = z;
+ else if (z < ZMin)
+ ZMin = z;
+ }
+
+ setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax)));
+ }
+
+ inline void RemoveEdgeFromChain(FEdge *iEdge)
+ {
+ for (vector<FEdge*>::iterator fe = _chains.begin(), feend = _chains.end(); fe != feend; fe++) {
+ if (iEdge == (*fe)) {
+ _chains.erase(fe);
+ break;
+ }
+ }
+ }
+
+ inline void RemoveEdge(FEdge *iEdge)
+ {
+ for (vector<FEdge*>::iterator fe = _edgesList.begin(), feend = _edgesList.end(); fe != feend; fe++) {
+ if (iEdge == (*fe)) {
+ _edgesList.erase(fe);
+ break;
+ }
+ }
+ }
+
+ /* accessors */
+ /*! Returns the list of SVertex of the Shape. */
+ inline vector<SVertex*>& getVertexList()
+ {
+ return _verticesList;
+ }
+
+ /*! Returns the list of FEdges of the Shape. */
+ inline vector<FEdge*>& getEdgeList()
+ {
+ return _edgesList;
+ }
+
+ inline vector<FEdge*>& getChains()
+ {
+ return _chains;
+ }
+
+ /*! Returns the bounding box of the shape. */
+ inline const BBox<Vec3r>& bbox()
+ {
+ return _BBox;
+ }
+
+ /*! Returns the ith material of the shape. */
+ inline const FrsMaterial& frs_material(unsigned i) const
+ {
+ return _FrsMaterials[i];
+ }
+
+ /*! Returns the list of materials of the Shape. */
+ inline const vector<FrsMaterial>& frs_materials() const
+ {
+ return _FrsMaterials;
+ }
+
+ inline ViewShape *viewShape()
+ {
+ return _ViewShape;
+ }
+
+ inline float importance() const
+ {
+ return _importance;
+ }
+
+ /*! Returns the Id of the Shape. */
+ inline Id getId() const
+ {
+ return _Id;
+ }
+
+ /*! Returns the name of the Shape. */
+ inline const string& getName() const
+ {
+ return _Name;
+ }
+
+ /* Modififers */
+ /*! Sets the Id of the shape.*/
+ inline void setId(Id id)
+ {
+ _Id = id;
+ }
+
+ /*! Sets the name of the shape.*/
+ inline void setName(const string& name)
+ {
+ _Name = name;
+ }
+
+ /*! Sets the list of materials for the shape */
+ inline void setFrsMaterials(const vector<FrsMaterial>& iMaterials)
+ {
+ _FrsMaterials = iMaterials;
+ }
+
+ inline void setViewShape(ViewShape *iShape)
+ {
+ _ViewShape = iShape;
+ }
+
+ inline void setImportance(float importance)
+ {
+ _importance = importance;
+ }
+};
+
+#endif // __FREESTYLE_SILHOUETTE_H__
diff --git a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp
new file mode 100644
index 00000000000..2de6be4c68a
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp
@@ -0,0 +1,322 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp
+ * \ingroup freestyle
+ * \brief Class to perform all geometric operations dedicated to silhouette. That, for example, implies that
+ * this geom engine has as member data the viewpoint, transformations, projections...
+ * \author Stephane Grabli
+ * \date 03/09/2002
+ */
+
+#include "Silhouette.h"
+#include "SilhouetteGeomEngine.h"
+
+#include "../geometry/GeomUtils.h"
+
+#include "BKE_global.h"
+
+using namespace std;
+
+Vec3r SilhouetteGeomEngine::_Viewpoint = Vec3r(0, 0, 0);
+real SilhouetteGeomEngine::_translation[3] = {0, 0, 0};
+real SilhouetteGeomEngine::_modelViewMatrix[4][4] = {
+ {1, 0, 0, 0},
+ {0, 1, 0, 0},
+ {0, 0, 1, 0},
+ {0, 0, 0, 1}
+};
+real SilhouetteGeomEngine::_projectionMatrix[4][4] = {
+ {1, 0, 0, 0},
+ {0, 1, 0, 0},
+ {0, 0, 1, 0},
+ {0, 0, 0, 1}
+};
+real SilhouetteGeomEngine::_transform[4][4] = {
+ {1, 0, 0, 0},
+ {0, 1, 0, 0},
+ {0, 0, 1, 0},
+ {0, 0, 0, 1}
+};
+int SilhouetteGeomEngine::_viewport[4] = {1, 1, 1, 1};
+real SilhouetteGeomEngine::_Focal = 0.0;
+
+real SilhouetteGeomEngine::_glProjectionMatrix[4][4] = {
+ {1, 0, 0, 0},
+ {0, 1, 0, 0},
+ {0, 0, 1, 0},
+ {0, 0, 0, 1}
+};
+real SilhouetteGeomEngine::_glModelViewMatrix[4][4] = {
+ {1, 0, 0, 0},
+ {0, 1, 0, 0},
+ {0, 0, 1, 0},
+ {0, 0, 0, 1}
+};
+real SilhouetteGeomEngine::_znear = 0.0;
+real SilhouetteGeomEngine::_zfar = 100.0;
+bool SilhouetteGeomEngine::_isOrthographicProjection = false;
+
+SilhouetteGeomEngine *SilhouetteGeomEngine::_pInstance = NULL;
+
+void SilhouetteGeomEngine::setTransform(const real iModelViewMatrix[4][4], const real iProjectionMatrix[4][4],
+ const int iViewport[4], real iFocal)
+{
+ unsigned int i, j;
+ _translation[0] = iModelViewMatrix[3][0];
+ _translation[1] = iModelViewMatrix[3][1];
+ _translation[2] = iModelViewMatrix[3][2];
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 4; j++) {
+ _modelViewMatrix[i][j] = iModelViewMatrix[j][i];
+ _glModelViewMatrix[i][j] = iModelViewMatrix[i][j];
+ }
+ }
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 4; j++) {
+ _projectionMatrix[i][j] = iProjectionMatrix[j][i];
+ _glProjectionMatrix[i][j] = iProjectionMatrix[i][j];
+ }
+ }
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 4; j++) {
+ _transform[i][j] = 0;
+ for (unsigned int k = 0; k < 4; k++)
+ _transform[i][j] += _projectionMatrix[i][k] * _modelViewMatrix[k][j];
+ }
+ }
+
+ for (i = 0; i < 4; i++) {
+ _viewport[i] = iViewport[i];
+ }
+ _Focal = iFocal;
+
+ _isOrthographicProjection = (iProjectionMatrix[3][3] != 0.0);
+}
+
+void SilhouetteGeomEngine::setFrustum(real iZNear, real iZFar)
+{
+ _znear = iZNear;
+ _zfar = iZFar;
+}
+
+void SilhouetteGeomEngine::retrieveViewport(int viewport[4])
+{
+ memcpy(viewport, _viewport, 4 * sizeof(int));
+}
+
+//#define HUGE 1.0e9
+
+void SilhouetteGeomEngine::ProjectSilhouette(vector<SVertex*>& ioVertices)
+{
+ Vec3r newPoint;
+#if 0
+ real min = HUGE;
+ real max = -HUGE;
+#endif
+ vector<SVertex*>::iterator sv, svend;
+ const real depth = _zfar - _znear;
+ const real fac = (depth < 1.0e-6) ? 1.0 : 1.0 / depth;
+
+ for (sv = ioVertices.begin(), svend = ioVertices.end(); sv != svend; sv++) {
+ GeomUtils::fromWorldToImage((*sv)->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport);
+ newPoint[2] = (-newPoint[2] - _znear) * fac; // normalize Z between 0 and 1
+ (*sv)->setPoint2D(newPoint);
+#if 0
+ cerr << (*sv)->point2d().z() << " ";
+ real d = (*sv)->point2d()[2];
+ if (d > max)
+ max =d;
+ if (d < min)
+ min =d;
+#endif
+ }
+#if 0
+ for (sv = ioVertices.begin(), svend = ioVertices.end(); sv != svend; sv++) {
+ Vec3r P((*sv)->point2d());
+ (*sv)->setPoint2D(Vec3r(P[0], P[1], 1.0 - (P[2] - min) / (max - min)));
+ //cerr << (*sv)->point2d()[2] << " ";
+ }
+#endif
+}
+
+void SilhouetteGeomEngine::ProjectSilhouette(SVertex *ioVertex)
+{
+ Vec3r newPoint;
+#if 0
+ real min = HUGE;
+ real max = -HUGE;
+ vector<SVertex*>::iterator sv, svend;
+#endif
+ const real depth = _zfar - _znear;
+ const real fac = (depth < 1.0e-6) ? 1.0 : 1.0 / depth;
+ GeomUtils::fromWorldToImage(ioVertex->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport);
+ newPoint[2] = (-newPoint[2] - _znear) * fac; // normalize Z between 0 and 1
+ ioVertex->setPoint2D(newPoint);
+}
+
+real SilhouetteGeomEngine::ImageToWorldParameter(FEdge *fe, real t)
+{
+ if (_isOrthographicProjection)
+ return t;
+
+ // we need to compute for each parameter t the corresponding parameter T which gives the intersection in 3D.
+ real T;
+
+ // suffix w for world, c for camera, r for retina, i for image
+ Vec3r Aw = (fe)->vertexA()->point3D();
+ Vec3r Bw = (fe)->vertexB()->point3D();
+ Vec3r Ac, Bc;
+ GeomUtils::fromWorldToCamera(Aw, Ac, _modelViewMatrix);
+ GeomUtils::fromWorldToCamera(Bw, Bc, _modelViewMatrix);
+ Vec3r ABc = Bc - Ac;
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Ac " << Ac << endl;
+ cout << "Bc " << Bc << endl;
+ cout << "ABc " << ABc << endl;
+ }
+#endif
+ Vec3r Ai = (fe)->vertexA()->point2D();
+ Vec3r Bi = (fe)->vertexB()->point2D();
+ Vec3r Ii = Ai + t * (Bi - Ai); // the intersection point in the 2D image space
+ Vec3r Ir, Ic;
+ GeomUtils::fromImageToRetina(Ii, Ir, _viewport);
+
+ real alpha, beta, denom;
+ real m11 = _projectionMatrix[0][0];
+ real m13 = _projectionMatrix[0][2];
+ real m22 = _projectionMatrix[1][1];
+ real m23 = _projectionMatrix[1][2];
+
+ if (fabs(ABc[0]) > 1.0e-6) {
+ alpha = ABc[2] / ABc[0];
+ beta = Ac[2] - alpha * Ac[0];
+ denom = alpha * (Ir[0] + m13) + m11;
+ if (fabs(denom) < 1.0e-6)
+ goto iter;
+ Ic[0] = -beta * (Ir[0] + m13) / denom;
+#if 0
+ Ic[1] = -(Ir[1] + m23) * (alpha * Ic[0] + beta) / m22;
+ Ic[2] = alpha * (Ic[0] - Ac[0]) + Ac[2];
+#endif
+ T = (Ic[0] - Ac[0]) / ABc[0];
+
+ }
+ else if (fabs(ABc[1]) > 1.0e-6) {
+ alpha = ABc[2] / ABc[1];
+ beta = Ac[2] - alpha * Ac[1];
+ denom = alpha * (Ir[1] + m23) + m22;
+ if (fabs(denom) < 1.0e-6)
+ goto iter;
+ Ic[1] = -beta * (Ir[1] + m23) / denom;
+#if 0
+ Ic[0] = -(Ir[0] + m13) * (alpha * Ic[1] + beta) / m11;
+ Ic[2] = alpha * (Ic[1] - Ac[1]) + Ac[2];
+#endif
+ T = (Ic[1] - Ac[1]) / ABc[1];
+ }
+ else {
+iter:
+ bool x_coords, less_than;
+ if (fabs(Bi[0] - Ai[0]) > 1.0e-6) {
+ x_coords = true;
+ less_than = Ai[0] < Bi[0];
+ }
+ else {
+ x_coords = false;
+ less_than = Ai[1] < Bi[1];
+ }
+ Vec3r Pc, Pr, Pi;
+ real T_sta = 0.0;
+ real T_end = 1.0;
+ real delta_x, delta_y, dist, dist_threshold = 1.0e-6;
+ int i, max_iters = 100;
+ for (i = 0; i < max_iters; i++) {
+ T = T_sta + 0.5 * (T_end - T_sta);
+ Pc = Ac + T * ABc;
+ GeomUtils::fromCameraToRetina(Pc, Pr, _projectionMatrix);
+ GeomUtils::fromRetinaToImage(Pr, Pi, _viewport);
+ delta_x = Ii[0] - Pi[0];
+ delta_y = Ii[1] - Pi[1];
+ dist = sqrt(delta_x * delta_x + delta_y * delta_y);
+ if (dist < dist_threshold)
+ break;
+ if (x_coords) {
+ if (less_than) {
+ if (Pi[0] < Ii[0])
+ T_sta = T;
+ else
+ T_end = T;
+ }
+ else {
+ if (Pi[0] > Ii[0])
+ T_sta = T;
+ else
+ T_end = T;
+ }
+ }
+ else {
+ if (less_than) {
+ if (Pi[1] < Ii[1])
+ T_sta = T;
+ else
+ T_end = T;
+ }
+ else {
+ if (Pi[1] > Ii[1])
+ T_sta = T;
+ else
+ T_end = T;
+ }
+ }
+ }
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("SilhouetteGeomEngine::ImageToWorldParameter(): #iters = %d, dist = %e\n", i, dist);
+ }
+#endif
+ if (i == max_iters && G.debug & G_DEBUG_FREESTYLE) {
+ printf("SilhouetteGeomEngine::ImageToWorldParameter(): reached to max_iters (dist = %e)\n", dist);
+ }
+ }
+
+ return T;
+}
+
+Vec3r SilhouetteGeomEngine::WorldToImage(const Vec3r& M)
+{
+ const real depth = _zfar - _znear;
+ const real fac = (depth < 1.0e-6) ? 1.0 : 1.0 / depth;
+ Vec3r newPoint;
+ GeomUtils::fromWorldToImage(M, newPoint, _transform, _viewport);
+ newPoint[2] = (-newPoint[2] - _znear) * fac; // normalize Z between 0 and 1
+ return newPoint;
+}
diff --git a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h
new file mode 100644
index 00000000000..f1c6b25c49e
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_SILHOUETTE_GEOM_ENGINE_H__
+#define __FREESTYLE_SILHOUETTE_GEOM_ENGINE_H__
+
+/** \file blender/freestyle/intern/view_map/SilhouetteGeomEngine.h
+ * \ingroup freestyle
+ * \brief Class to perform all geometric operations dedicated to silhouette. That, for example, implies that
+ * this geom engine has as member data the viewpoint, transformations, projections...
+ * \author Stephane Grabli
+ * \date 03/09/2002
+ */
+
+#include <vector>
+
+#include "../geometry/Geom.h"
+
+#include "../system/FreestyleConfig.h"
+
+using namespace Geometry;
+
+class SVertex;
+class FEdge;
+
+class LIB_VIEW_MAP_EXPORT SilhouetteGeomEngine
+{
+private:
+ // The viewpoint under which the silhouette has to be computed
+ static Vec3r _Viewpoint;
+ static real _translation[3];
+ // the model view matrix (_modelViewMatrix[i][j] means element of line i and column j)
+ static real _modelViewMatrix[4][4];
+ // the projection matrix (_projectionMatrix[i][j] means element of line i and column j)
+ static real _projectionMatrix[4][4];
+ // the global transformation from world to screen (projection included)
+ // (_transform[i][j] means element of line i and column j)
+ static real _transform[4][4];
+ // the viewport
+ static int _viewport[4];
+ static real _Focal;
+
+ static real _znear;
+ static real _zfar;
+
+ // GL style (column major) projection matrix
+ static real _glProjectionMatrix[4][4];
+ // GL style (column major) model view matrix
+ static real _glModelViewMatrix[4][4];
+
+ static bool _isOrthographicProjection;
+
+ static SilhouetteGeomEngine *_pInstance;
+
+public:
+ /*! retrieves an instance on the singleton */
+ static SilhouetteGeomEngine *getInstance()
+ {
+ if (_pInstance == NULL) {
+ _pInstance = new SilhouetteGeomEngine;
+ }
+ return _pInstance;
+ }
+
+ /*! Sets the current viewpoint */
+ static inline void setViewpoint(const Vec3r& ivp)
+ {
+ _Viewpoint = ivp;
+ }
+
+ /*! Sets the current transformation
+ * iModelViewMatrix
+ * The 4x4 model view matrix, in column major order (openGL like).
+ * iProjection matrix
+ * The 4x4 projection matrix, in column major order (openGL like).
+ * iViewport
+ * The viewport. 4 real array: origin.x, origin.y, width, length
+ * iFocal
+ * The focal length
+ */
+ static void setTransform(const real iModelViewMatrix[4][4], const real iProjectionMatrix[4][4],
+ const int iViewport[4], real iFocal);
+
+ /*! Sets the current znear and zfar */
+ static void setFrustum(real iZNear, real iZFar);
+
+ /* accessors */
+ static void retrieveViewport(int viewport[4]);
+
+ /*! Projects the silhouette in camera coordinates
+ * This method modifies the ioEdges passed as argument.
+ * ioVertices
+ * The vertices to project. It is modified during the operation.
+ */
+ static void ProjectSilhouette(std::vector<SVertex*>& ioVertices);
+ static void ProjectSilhouette(SVertex *ioVertex);
+
+ /*! transforms the parameter t defining a 2D intersection for edge fe in order to obtain
+ * the parameter giving the corresponding 3D intersection.
+ * Returns the 3D parameter
+ * fe
+ * The edge
+ * t
+ * The parameter for the 2D intersection.
+ */
+ static real ImageToWorldParameter(FEdge *fe, real t);
+
+ /*! From world to image */
+ static Vec3r WorldToImage(const Vec3r& M);
+};
+
+#endif // __FREESTYLE_SILHOUETTE_GEOM_ENGINE_H__
diff --git a/source/blender/freestyle/intern/view_map/SphericalGrid.cpp b/source/blender/freestyle/intern/view_map/SphericalGrid.cpp
new file mode 100644
index 00000000000..2cd8e5ebe66
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SphericalGrid.cpp
@@ -0,0 +1,249 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/SphericalGrid.cpp
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2010-12-19
+ */
+
+#include <algorithm>
+#include <stdexcept>
+
+#include "SphericalGrid.h"
+
+#include "BKE_global.h"
+
+using namespace std;
+
+// Helper Classes
+
+// OccluderData
+///////////////
+
+// Cell
+/////////
+
+SphericalGrid::Cell::Cell() {}
+
+SphericalGrid::Cell::~Cell() {}
+
+void SphericalGrid::Cell::setDimensions(real x, real y, real sizeX, real sizeY)
+{
+ const real epsilon = 1.0e-06;
+ boundary[0] = x - epsilon;
+ boundary[1] = x + sizeX + epsilon;
+ boundary[2] = y - epsilon;
+ boundary[3] = y + sizeY + epsilon;
+}
+
+bool SphericalGrid::Cell::compareOccludersByShallowestPoint(const SphericalGrid::OccluderData *a,
+ const SphericalGrid::OccluderData *b)
+{
+ return a->shallowest < b->shallowest;
+}
+
+void SphericalGrid::Cell::indexPolygons()
+{
+ // Sort occluders by their shallowest points.
+ sort(faces.begin(), faces.end(), compareOccludersByShallowestPoint);
+}
+
+// Iterator
+//////////////////
+
+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 (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
+
+ // Set iterator
+ _current = _cell->faces.begin();
+}
+
+SphericalGrid::Iterator::~Iterator() {}
+
+// SphericalGrid
+/////////////////
+
+SphericalGrid::SphericalGrid(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap,
+ Vec3r& viewpoint, bool enableQI)
+: _viewpoint(viewpoint), _enableQI(enableQI)
+{
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Generate Cell structure" << endl;
+ }
+ // Generate Cell structure
+ assignCells(source, density, viewMap);
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Distribute occluders" << endl;
+ }
+ // Fill Cells
+ distributePolygons(source);
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Reorganize cells" << endl;
+ }
+ // Reorganize Cells
+ reorganizeCells();
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Ready to use SphericalGrid" << endl;
+ }
+}
+
+SphericalGrid::~SphericalGrid() {}
+
+void SphericalGrid::assignCells(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap)
+{
+ _cellSize = density.cellSize();
+ _cellsX = density.cellsX();
+ _cellsY = density.cellsY();
+ _cellOrigin[0] = density.cellOrigin(0);
+ _cellOrigin[1] = density.cellOrigin(1);
+
+ // Now allocate the cell table and fill it with default (empty) cells
+ _cells.resize(_cellsX * _cellsY);
+ for (cellContainer::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) {
+ (*i) = NULL;
+ }
+
+ // Identify cells that will be used, and set the dimensions for each
+ ViewMap::fedges_container& fedges = viewMap->FEdges();
+ for (ViewMap::fedges_container::iterator f = fedges.begin(), fend = fedges.end(); f != fend; ++f) {
+ if ((*f)->isInImage()) {
+ Vec3r point = SphericalGrid::Transform::sphericalProjection((*f)->center3d());
+ unsigned i, j;
+ getCellCoordinates(point, i, j);
+ if (_cells[i * _cellsY + j] == NULL) {
+ // This is an uninitialized cell
+ real x, y, width, height;
+
+ x = _cellOrigin[0] + _cellSize * i;
+ width = _cellSize;
+
+ y = _cellOrigin[1] + _cellSize * j;
+ height = _cellSize;
+
+ // Initialize cell
+ Cell *b = _cells[i * _cellsY + j] = new Cell();
+ b->setDimensions(x, y, width, height);
+ }
+ }
+ }
+}
+
+void SphericalGrid::distributePolygons(OccluderSource& source)
+{
+ unsigned long nFaces = 0;
+ unsigned long nKeptFaces = 0;
+
+ for (source.begin(); source.isValid(); source.next()) {
+ OccluderData *occluder = NULL;
+
+ try {
+ if (insertOccluder(source, occluder)) {
+ _faces.push_back(occluder);
+ ++nKeptFaces;
+ }
+ }
+ catch (...) {
+ // If an exception was thrown, _faces.push_back() cannot have succeeded. Occluder is not owned by anyone,
+ // and must be deleted. If the exception was thrown before or during new OccluderData(), then
+ // occluder is NULL, and this delete is harmless.
+ delete occluder;
+ throw;
+ }
+ ++nFaces;
+ }
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Distributed " << nFaces << " occluders. Retained " << nKeptFaces << "." << endl;
+ }
+}
+
+void SphericalGrid::reorganizeCells()
+{
+ // Sort the occluders by shallowest point
+ for (vector<Cell*>::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) {
+ if (*i != NULL) {
+ (*i)->indexPolygons();
+ }
+ }
+}
+
+void SphericalGrid::getCellCoordinates(const Vec3r& point, unsigned& x, unsigned& y)
+{
+ x = min(_cellsX - 1, (unsigned) floor (max((double) 0.0f, point[0] - _cellOrigin[0]) / _cellSize));
+ y = min(_cellsY - 1, (unsigned) floor (max((double) 0.0f, point[1] - _cellOrigin[1]) / _cellSize));
+}
+
+SphericalGrid::Cell *SphericalGrid::findCell(const Vec3r& point)
+{
+ unsigned x, y;
+ getCellCoordinates(point, x, y);
+ return _cells[x * _cellsY + y];
+}
+
+bool SphericalGrid::orthographicProjection() const
+{
+ return false;
+}
+
+const Vec3r& SphericalGrid::viewpoint() const
+{
+ return _viewpoint;
+}
+
+bool SphericalGrid::enableQI() const
+{
+ return _enableQI;
+}
+
+SphericalGrid::Transform::Transform () : GridHelpers::Transform() {}
+
+Vec3r SphericalGrid::Transform::operator()(const Vec3r& point) const
+{
+ return sphericalProjection(point);
+}
+
+Vec3r SphericalGrid::Transform::sphericalProjection(const Vec3r& M)
+{
+ Vec3r newPoint;
+
+ newPoint[0] = ::atan(M[0] / M[2]);
+ newPoint[1] = ::atan(M[1] / M[2]);
+ newPoint[2] = ::sqrt(M[0] * M[0] + M[1] * M[1] + M[2] * M[2]);
+
+ return newPoint;
+}
diff --git a/source/blender/freestyle/intern/view_map/SphericalGrid.h b/source/blender/freestyle/intern/view_map/SphericalGrid.h
new file mode 100644
index 00000000000..774ec9ab517
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SphericalGrid.h
@@ -0,0 +1,423 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_SPHERICAL_GRID_H__
+#define __FREESTYLE_SPHERICAL_GRID_H__
+
+/** \file blender/freestyle/intern/view_map/SphericalGrid.h
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2010-12-19
+ */
+
+#define SPHERICAL_GRID_LOGGING FALSE
+
+// I would like to avoid using deque because including ViewMap.h and <deque> or <vector> separately results in
+// redefinitions of identifiers. ViewMap.h already includes <vector> so it should be a safe fall-back.
+//#include <vector>
+//#include <deque>
+
+#include "GridDensityProvider.h"
+#include "OccluderSource.h"
+#include "ViewMap.h"
+
+#include "../geometry/Polygon.h"
+#include "../geometry/BBox.h"
+#include "../geometry/GridHelpers.h"
+
+#include "../system/PointerSequence.h"
+
+#include "../winged_edge/WEdge.h"
+
+#include "BKE_global.h"
+
+class SphericalGrid
+{
+public:
+ // Helper classes
+ struct OccluderData
+ {
+ explicit OccluderData (OccluderSource& source, Polygon3r& p);
+ Polygon3r poly;
+ Polygon3r cameraSpacePolygon;
+ real shallowest, deepest;
+ // N.B. We could, of course, store face in poly's userdata member, like the old ViewMapBuilder code does.
+ // However, code comments make it clear that userdata is deprecated, so we avoid the temptation to save
+ // 4 or 8 bytes.
+ WFace *face;
+ };
+
+private:
+ struct Cell
+ {
+ // Can't store Cell in a vector without copy and assign
+ //Cell(const Cell& other);
+ //Cell& operator=(const Cell& other);
+
+ explicit Cell();
+ ~Cell();
+
+ static bool compareOccludersByShallowestPoint(const OccluderData *a, const OccluderData *b);
+
+ void setDimensions(real x, real y, real sizeX, real sizeY);
+ void checkAndInsert(OccluderSource& source, Polygon3r& poly, OccluderData*& occluder);
+ void indexPolygons();
+
+ real boundary[4];
+ //deque<OccluderData*> faces;
+ vector<OccluderData*> faces;
+ };
+
+public:
+ /*! Iterator needs to allow the user to avoid full 3D comparison in two cases:
+ *
+ * (1) Where (*current)->deepest < target[2], where the occluder is unambiguously in front of the target point.
+ *
+ * (2) Where (*current)->shallowest > target[2], where the occluder is unambiguously in back of the target point.
+ *
+ * In addition, when used by OptimizedFindOccludee, Iterator should stop iterating as soon as it has an occludee
+ * candidate and (*current)->shallowest > candidate[2], because at that point forward no new occluder could
+ * possibly be a better occludee.
+ */
+
+ class Iterator
+ {
+ public:
+ // epsilon is not used in this class, but other grids with the same interface may need an epsilon
+ explicit Iterator(SphericalGrid& grid, Vec3r& center, real epsilon = 1.0e-06);
+ ~Iterator();
+ void initBeforeTarget();
+ void initAfterTarget();
+ void nextOccluder();
+ void nextOccludee();
+ bool validBeforeTarget();
+ bool validAfterTarget();
+ WFace *getWFace() const;
+ Polygon3r *getCameraSpacePolygon();
+ void reportDepth(Vec3r origin, Vec3r u, real t);
+ private:
+ bool testOccluder(bool wantOccludee);
+ void markCurrentOccludeeCandidate(real depth);
+
+ Cell *_cell;
+ Vec3r _target;
+ bool _foundOccludee;
+ real _occludeeDepth;
+ //deque<OccluderData*>::iterator _current, _occludeeCandidate;
+ vector<OccluderData*>::iterator _current, _occludeeCandidate;
+ };
+
+ class Transform : public GridHelpers::Transform
+ {
+ public:
+ explicit Transform();
+ explicit Transform(Transform& other);
+ Vec3r operator()(const Vec3r& point) const;
+ static Vec3r sphericalProjection(const Vec3r& M);
+ };
+
+private:
+ // Prevent implicit copies and assignments.
+ SphericalGrid(const SphericalGrid& other);
+ SphericalGrid& operator=(const SphericalGrid& other);
+
+public:
+ explicit SphericalGrid(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap,
+ Vec3r& viewpoint, bool enableQI);
+ virtual ~SphericalGrid();
+
+ // Generate Cell structure
+ void assignCells(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap);
+ // Fill Cells
+ void distributePolygons(OccluderSource& source);
+ // Insert one polygon into each matching cell, return true if any cell consumes the polygon
+ bool insertOccluder(OccluderSource& source, OccluderData*& occluder);
+ // Sort occluders in each cell
+ void reorganizeCells();
+
+ Cell *findCell(const Vec3r& point);
+
+ // Accessors:
+ bool orthographicProjection() const;
+ const Vec3r& viewpoint() const;
+ bool enableQI() const;
+
+private:
+ void getCellCoordinates(const Vec3r& point, unsigned& x, unsigned& y);
+
+ typedef PointerSequence<vector<Cell*>, Cell*> cellContainer;
+ //typedef PointerSequence<deque<OccluderData*>, OccluderData*> occluderContainer;
+ typedef PointerSequence<vector<OccluderData*>, OccluderData*> occluderContainer;
+ unsigned _cellsX, _cellsY;
+ float _cellSize;
+ float _cellOrigin[2];
+ cellContainer _cells;
+ occluderContainer _faces;
+ Vec3r _viewpoint;
+ bool _enableQI;
+};
+
+inline void SphericalGrid::Iterator::initBeforeTarget()
+{
+ _current = _cell->faces.begin();
+ while (_current != _cell->faces.end() && !testOccluder(false)) {
+ ++_current;
+ }
+}
+
+inline void SphericalGrid::Iterator::initAfterTarget()
+{
+ if (_foundOccludee) {
+#if SPHERICAL_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "\tStarting occludee search from occludeeCandidate at depth " <<
+ _occludeeDepth << std::endl;
+ }
+#endif
+ _current = _occludeeCandidate;
+ return;
+ }
+
+#if SPHERICAL_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "\tStarting occludee search from current position" << std::endl;
+ }
+#endif
+
+ while (_current != _cell->faces.end() && !testOccluder(true)) {
+ ++_current;
+ }
+}
+
+inline bool SphericalGrid::Iterator::testOccluder(bool wantOccludee)
+{
+ // End-of-list is not even a valid iterator position
+ if (_current == _cell->faces.end()) {
+ // Returning true seems strange, but it will break us out of whatever loop is calling testOccluder, and
+ // _current=_cell->face.end() will make the calling routine give up.
+ return true;
+ }
+#if SPHERICAL_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "\tTesting occluder " << (*_current)->poly.getVertices()[0];
+ for (unsigned int i = 1; i < (*_current)->poly.getVertices().size(); ++i) {
+ std::cout << ", " << (*_current)->poly.getVertices()[i];
+ }
+ std::cout << " from shape " << (*_current)->face->GetVertex(0)->shape()->GetId() << std::endl;
+ }
+#endif
+
+ // If we have an occluder candidate and we are unambiguously after it, abort
+ if (_foundOccludee && (*_current)->shallowest > _occludeeDepth) {
+#if SPHERICAL_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "\t\tAborting: shallowest > occludeeCandidate->deepest" << std::endl;
+ }
+#endif
+ _current = _cell->faces.end();
+
+ // See note above
+ return true;
+ }
+
+ // Specific continue or stop conditions when searching for each type
+ if (wantOccludee) {
+ if ((*_current)->deepest < _target[2]) {
+#if SPHERICAL_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "\t\tSkipping: shallower than target while looking for occludee" << std::endl;
+ }
+#endif
+ return false;
+ }
+ }
+ else {
+ if ((*_current)->shallowest > _target[2]) {
+#if SPHERICAL_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "\t\tStopping: deeper than target while looking for occluder" << std::endl;
+ }
+#endif
+ return true;
+ }
+ }
+
+ // Depthwise, this is a valid occluder.
+
+ // Check to see if target is in the 2D bounding box
+ Vec3r bbMin, bbMax;
+ (*_current)->poly.getBBox(bbMin, bbMax);
+ if (_target[0] < bbMin[0] || _target[0] > bbMax[0] || _target[1] < bbMin[1] || _target[1] > bbMax[1]) {
+#if SPHERICAL_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "\t\tSkipping: bounding box violation" << std::endl;
+ }
+#endif
+ return false;
+ }
+
+ // We've done all the corner cutting we can. Let the caller work out whether or not the geometry is correct.
+ return true;
+}
+
+inline void SphericalGrid::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 the distance from viewpoint
+ // If origin is the viewpoint, depth == t. A future optimization could allow the caller to tell us if origin is
+ // viewponit or target, at the cost of changing the OptimizedGrid API.
+ real depth = (origin + u * t).norm();
+#if SPHERICAL_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "\t\tReporting depth of occluder/ee: " << depth;
+ }
+#endif
+ if (depth > _target[2]) {
+#if SPHERICAL_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << " is deeper than target" << std::endl;
+ }
+#endif
+ // If the current occluder is the best occludee so far, save it.
+ if (! _foundOccludee || _occludeeDepth > depth) {
+ markCurrentOccludeeCandidate(depth);
+ }
+ }
+ else {
+#if SPHERICAL_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << std::endl;
+ }
+#endif
+ }
+}
+
+inline void SphericalGrid::Iterator::nextOccluder()
+{
+ if (_current != _cell->faces.end()) {
+ do {
+ ++_current;
+ } while (_current != _cell->faces.end() && !testOccluder(false));
+ }
+}
+
+inline void SphericalGrid::Iterator::nextOccludee()
+{
+ if (_current != _cell->faces.end()) {
+ do {
+ ++_current;
+ } while (_current != _cell->faces.end() && !testOccluder(true));
+ }
+}
+
+inline bool SphericalGrid::Iterator::validBeforeTarget()
+{
+ return _current != _cell->faces.end() && (*_current)->shallowest <= _target[2];
+}
+
+inline bool SphericalGrid::Iterator::validAfterTarget()
+{
+ return _current != _cell->faces.end();
+}
+
+inline void SphericalGrid::Iterator::markCurrentOccludeeCandidate(real depth)
+{
+#if SPHERICAL_GRID_LOGGING
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ std::cout << "\t\tFound occludeeCandidate at depth " << depth << std::endl;
+ }
+#endif
+ _occludeeCandidate = _current;
+ _occludeeDepth = depth;
+ _foundOccludee = true;
+}
+
+inline WFace *SphericalGrid::Iterator::getWFace() const
+{
+ return (*_current)->face;
+}
+
+inline Polygon3r *SphericalGrid::Iterator::getCameraSpacePolygon()
+{
+ return &((*_current)->cameraSpacePolygon);
+}
+
+inline SphericalGrid::OccluderData::OccluderData (OccluderSource& source, Polygon3r& p)
+: poly(p), cameraSpacePolygon(source.getCameraSpacePolygon()), face(source.getWFace())
+{
+ const Vec3r viewpoint(0, 0, 0);
+ // Get the point on the camera-space polygon that is closest to the viewpoint
+ // shallowest is the distance from the viewpoint to that point
+ shallowest = GridHelpers::distancePointToPolygon(viewpoint, cameraSpacePolygon);
+
+ // Get the point on the camera-space polygon that is furthest from the viewpoint
+ // deepest is the distance from the viewpoint to that point
+ deepest = cameraSpacePolygon.getVertices()[2].norm();
+ for (unsigned int i = 0; i < 2; ++i) {
+ real t = cameraSpacePolygon.getVertices()[i].norm();
+ if (t > deepest) {
+ deepest = t;
+ }
+ }
+}
+
+inline void SphericalGrid::Cell::checkAndInsert(OccluderSource& source, Polygon3r& poly, OccluderData*& occluder)
+{
+ if (GridHelpers::insideProscenium (boundary, poly)) {
+ if (occluder == NULL) {
+ // Disposal of occluder will be handled in SphericalGrid::distributePolygons(),
+ // or automatically by SphericalGrid::_faces;
+ occluder = new OccluderData(source, poly);
+ }
+ faces.push_back(occluder);
+ }
+}
+
+inline bool SphericalGrid::insertOccluder(OccluderSource& source, OccluderData*& occluder)
+{
+ Polygon3r& poly(source.getGridSpacePolygon());
+ occluder = NULL;
+
+ Vec3r bbMin, bbMax;
+ poly.getBBox(bbMin, bbMax);
+ // Check overlapping cells
+ unsigned startX, startY, endX, endY;
+ getCellCoordinates(bbMin, startX, startY);
+ getCellCoordinates(bbMax, endX, endY);
+
+ for (unsigned int i = startX; i <= endX; ++i) {
+ for (unsigned int j = startY; j <= endY; ++j) {
+ if (_cells[i * _cellsY + j] != NULL) {
+ _cells[i * _cellsY + j]->checkAndInsert(source, poly, occluder);
+ }
+ }
+ }
+
+ return occluder != NULL;
+}
+
+#endif // __FREESTYLE_SPHERICAL_GRID_H__
diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp
new file mode 100644
index 00000000000..98345b396f4
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp
@@ -0,0 +1,302 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/SteerableViewMap.cpp
+ * \ingroup freestyle
+ * \brief Convenient access to the steerable ViewMap to which any element of the ViewMap belongs to.
+ * \author Stephane Grabli
+ * \date 01/07/2003
+ */
+
+#include <math.h>
+//soc #include <qimage.h>
+//soc #include <qstring.h>
+#include <sstream>
+
+#include "Silhouette.h"
+#include "SteerableViewMap.h"
+
+#include "../geometry/Geom.h"
+
+#include "../image/ImagePyramid.h"
+#include "../image/Image.h"
+
+#include "BKE_global.h"
+
+extern "C" {
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+}
+
+using namespace Geometry;
+
+SteerableViewMap::SteerableViewMap(unsigned int nbOrientations)
+{
+ _nbOrientations = nbOrientations;
+ _bound = cos(M_PI / (float)_nbOrientations);
+ for (unsigned int i = 0; i < _nbOrientations; ++i) {
+ _directions.push_back(Vec2d(cos((float)i * M_PI / (float)_nbOrientations),
+ sin((float)i * M_PI / (float)_nbOrientations)));
+ }
+ Build();
+}
+
+void SteerableViewMap::Build()
+{
+ _imagesPyramids = new ImagePyramid *[_nbOrientations + 1]; // one more map to store the complete visible VM
+ memset((_imagesPyramids), 0, (_nbOrientations + 1) * sizeof(ImagePyramid *));
+}
+
+SteerableViewMap::SteerableViewMap(const SteerableViewMap& iBrother)
+{
+ _nbOrientations = iBrother._nbOrientations;
+ unsigned int i;
+ _bound = iBrother._bound;
+ _directions = iBrother._directions;
+ _mapping = iBrother._mapping;
+ _imagesPyramids = new ImagePyramid *[_nbOrientations + 1]; // one more map to store the complete visible VM
+ for (i = 0; i < _nbOrientations + 1; ++i)
+ _imagesPyramids[i] = new GaussianPyramid(*(dynamic_cast<GaussianPyramid*>(iBrother._imagesPyramids[i])));
+}
+
+SteerableViewMap::~SteerableViewMap()
+{
+ Clear();
+}
+
+void SteerableViewMap::Clear()
+{
+ unsigned int i;
+ if (_imagesPyramids) {
+ for (i = 0; i <= _nbOrientations; ++i) {
+ if (_imagesPyramids[i])
+ delete (_imagesPyramids)[i];
+ }
+ delete[] _imagesPyramids;
+ _imagesPyramids = 0;
+ }
+ if (!_mapping.empty()) {
+ for (map<unsigned int, double*>::iterator m = _mapping.begin(), mend = _mapping.end(); m != mend; ++m) {
+ delete[] (*m).second;
+ }
+ _mapping.clear();
+ }
+}
+
+void SteerableViewMap::Reset()
+{
+ Clear();
+ Build();
+}
+
+double SteerableViewMap::ComputeWeight(const Vec2d& dir, unsigned i)
+{
+ double dotp = fabs(dir * _directions[i]);
+ if (dotp < _bound)
+ return 0.0;
+ if (dotp > 1.0)
+ dotp = 1.0;
+
+ return cos((float)_nbOrientations / 2.0 * acos(dotp));
+}
+
+double *SteerableViewMap::AddFEdge(FEdge *iFEdge)
+{
+ unsigned i;
+ unsigned id = iFEdge->getId().getFirst();
+ map<unsigned int, double *>::iterator o = _mapping.find(id);
+ if (o != _mapping.end()) {
+ return (*o).second;
+ }
+ double *res = new double[_nbOrientations];
+ for (i = 0; i < _nbOrientations; ++i) {
+ res[i] = 0.0;
+ }
+ Vec3r o2d3 = iFEdge->orientation2d();
+ Vec2r o2d2(o2d3.x(), o2d3.y());
+ real norm = o2d2.norm();
+ if (norm < 1.0e-6) {
+ return res;
+ }
+ o2d2 /= norm;
+
+ for (i = 0; i < _nbOrientations; ++i) {
+ res[i] = ComputeWeight(o2d2, i);
+ }
+ _mapping[id] = res;
+ return res;
+}
+
+unsigned SteerableViewMap::getSVMNumber(const Vec2f& orient)
+{
+ Vec2f dir(orient);
+ //soc unsigned res = 0;
+ real norm = dir.norm();
+ if (norm < 1.0e-6) {
+ return _nbOrientations + 1;
+ }
+ dir /= norm;
+ double maxw = 0.0f;
+ unsigned winner = _nbOrientations + 1;
+ for (unsigned int i = 0; i < _nbOrientations; ++i) {
+ double w = ComputeWeight(dir, i);
+ if (w > maxw) {
+ maxw = w;
+ winner = i;
+ }
+ }
+ return winner;
+}
+
+unsigned SteerableViewMap::getSVMNumber(unsigned id)
+{
+ map<unsigned int, double *>::iterator o = _mapping.find(id);
+ if (o != _mapping.end()) {
+ double *wvalues = (*o).second;
+ double maxw = 0.0;
+ unsigned winner = _nbOrientations + 1;
+ for (unsigned i = 0; i < _nbOrientations; ++i) {
+ double w = wvalues[i];
+ if (w > maxw) {
+ maxw = w;
+ winner = i;
+ }
+ }
+ return winner;
+ }
+ return _nbOrientations + 1;
+}
+
+void SteerableViewMap::buildImagesPyramids(GrayImage **steerableBases, bool copy, unsigned iNbLevels, float iSigma)
+{
+ for (unsigned int i = 0; i <= _nbOrientations; ++i) {
+ ImagePyramid *svm = (_imagesPyramids)[i];
+ if (svm)
+ delete svm;
+ if (copy)
+ svm = new GaussianPyramid(*(steerableBases[i]), iNbLevels, iSigma);
+ else
+ svm = new GaussianPyramid(steerableBases[i], iNbLevels, iSigma);
+ _imagesPyramids[i] = svm;
+ }
+}
+
+float SteerableViewMap::readSteerableViewMapPixel(unsigned iOrientation, int iLevel, int x, int y)
+{
+ ImagePyramid *pyramid = _imagesPyramids[iOrientation];
+ if (!pyramid) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Warning: this steerable ViewMap level doesn't exist" << endl;
+ }
+ return 0.0f;
+ }
+ if ((x < 0) || (x >= pyramid->width()) || (y < 0) || (y >= pyramid->height()))
+ return 0;
+ //float v = pyramid->pixel(x, pyramid->height() - 1 - y, iLevel) * 255.0f;
+ // We encode both the directionality and the lines counting on 8 bits (because of frame buffer). Thus, we allow
+ // until 8 lines to pass through the same pixel, so that we can discretize the Pi/_nbOrientations angle into
+ // 32 slices. Therefore, for example, in the vertical direction, a vertical line will have the value 32 on
+ // each pixel it passes through.
+ float v = pyramid->pixel(x, pyramid->height() - 1 - y, iLevel) / 32.0f;
+ return v;
+}
+
+float SteerableViewMap::readCompleteViewMapPixel(int iLevel, int x, int y)
+{
+ return readSteerableViewMapPixel(_nbOrientations, iLevel, x, y);
+}
+
+unsigned int SteerableViewMap::getNumberOfPyramidLevels() const
+{
+ if (_imagesPyramids[0])
+ return _imagesPyramids[0]->getNumberOfLevels();
+ return 0;
+}
+
+void SteerableViewMap::saveSteerableViewMap() const
+{
+ for (unsigned int i = 0; i <= _nbOrientations; ++i) {
+ if (_imagesPyramids[i] == 0) {
+ cerr << "SteerableViewMap warning: orientation " << i <<
+ " of steerable View Map whas not been computed yet" << endl;
+ continue;
+ }
+ int ow = _imagesPyramids[i]->width(0);
+ int oh = _imagesPyramids[i]->height(0);
+
+ //soc QString base("SteerableViewMap");
+ string base("SteerableViewMap");
+ stringstream filename;
+
+ for (int j = 0; j < _imagesPyramids[i]->getNumberOfLevels(); ++j) { //soc
+ float coeff = 1.0f; // 1 / 255.0f; // 100 * 255; // * pow(2, j);
+ //soc QImage qtmp(ow, oh, QImage::Format_RGB32);
+ ImBuf *ibuf = IMB_allocImBuf(ow, oh, 32, IB_rect);
+ int rowbytes = ow * 4;
+ char *pix;
+
+ for (int y = 0; y < oh; ++y) { //soc
+ for (int x = 0; x < ow; ++x) { //soc
+ int c = (int)(coeff * _imagesPyramids[i]->pixel(x, y, j));
+ if (c > 255)
+ c = 255;
+ //int c = (int)(_imagesPyramids[i]->pixel(x, y, j));
+
+ //soc qtmp.setPixel(x, y, qRgb(c, c, c));
+ pix = (char *)ibuf->rect + y * rowbytes + x * 4;
+ pix[0] = pix[1] = pix[2] = c;
+ }
+ }
+
+ //soc qtmp.save(base+QString::number(i)+"-"+QString::number(j)+".png", "PNG");
+ filename << base;
+ filename << i << "-" << j << ".png";
+ ibuf->ftype = PNG;
+ IMB_saveiff(ibuf, const_cast<char *>(filename.str().c_str()), 0);
+ }
+#if 0
+ QString base("SteerableViewMap");
+ for (unsigned j = 0; j < _imagesPyramids[i]->getNumberOfLevels(); ++j) {
+ GrayImage *img = _imagesPyramids[i]->getLevel(j);
+ int ow = img->width();
+ int oh = img->height();
+ float coeff = 1.0f; // 100 * 255; // * pow(2, j);
+ QImage qtmp(ow, oh, 32);
+ for (unsigned int y = 0; y < oh; ++y) {
+ for (unsigned int x = 0; x < ow; ++x) {
+ int c = (int)(coeff * img->pixel(x, y));
+ if (c > 255)
+ c = 255;
+ //int c = (int)(_imagesPyramids[i]->pixel(x, y, j));
+ qtmp.setPixel(x, y, qRgb(c, c, c));
+ }
+ }
+ qtmp.save(base + QString::number(i) + "-" + QString::number(j) + ".png", "PNG");
+ }
+#endif
+ }
+}
diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.h b/source/blender/freestyle/intern/view_map/SteerableViewMap.h
new file mode 100644
index 00000000000..28504350ac5
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.h
@@ -0,0 +1,154 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_STEERABLE_VIEW_MAP_H__
+#define __FREESTYLE_STEERABLE_VIEW_MAP_H__
+
+/** \file blender/freestyle/intern/view_map/SteerableViewMap.h
+ * \ingroup freestyle
+ * \brief Convenient access to the steerable ViewMap to which any element of the ViewMap belongs to.
+ * \author Stephane Grabli
+ * \date 01/07/2003
+ */
+
+#include <map>
+
+#include "../geometry/Geom.h"
+
+#include "../system/FreestyleConfig.h"
+
+using namespace Geometry;
+
+using namespace std;
+
+class FEdge;
+class ImagePyramid;
+class GrayImage;
+
+/*! This class checks for every FEdge in which steerable it belongs and stores the mapping allowing to retrieve
+ * this information from the FEdge Id.
+ */
+class LIB_VIEW_MAP_EXPORT SteerableViewMap
+{
+protected:
+ // for each vector the list of nbOrientations weigths corresponding to its contributions
+ // to the nbOrientations directional maps
+ map<unsigned int, double*> _mapping;
+ unsigned _nbOrientations;
+ ImagePyramid **_imagesPyramids; // the pyramids of images storing the different SVM
+
+ // internal
+ double _bound; // cos(Pi/N)
+ vector<Vec2d> _directions;
+
+public:
+ SteerableViewMap(unsigned int nbOrientations = 4);
+ SteerableViewMap(const SteerableViewMap& iBrother);
+ virtual ~SteerableViewMap();
+
+ /*! Resets everything */
+ virtual void Reset();
+
+ /*! Adds a FEdge to steerable VM.
+ * Returns the nbOrientations weigths corresponding to the FEdge contributions to the nbOrientations
+ * directional maps.
+ */
+ double *AddFEdge(FEdge *iFEdge);
+
+ /*! Compute the weight of direction dir for orientation iNOrientation */
+ double ComputeWeight(const Vec2d& dir, unsigned iNOrientation);
+
+ /*! Returns the number of the SVM to which a direction belongs to.
+ * \param dir
+ * The direction
+ */
+ unsigned getSVMNumber(const Vec2f& dir);
+
+ /*! Returns the number of the SVM to which a FEdge belongs most.
+ * \param id
+ * The First element of the Id struct of the FEdge we're intersted in.
+ */
+ unsigned getSVMNumber(unsigned id);
+
+ /*! Builds _nbOrientations+1 pyramids of images from the _nbOrientations+1 base images of the steerable viewmap.
+ * \param steerableBases
+ * The _nbOrientations+1 images constituing the basis for the steerable pyramid.
+ * \param copy
+ * If false, the data is not duplicated, and Canvas deals with the memory management of these
+ * _nbOrientations+1 images. If true, data is copied, and it's up to the caller to delete the images.
+ * \params iNbLevels
+ * The number of levels desired for each pyramid.
+ * If iNbLevels == 0, the complete pyramid is built.
+ * \param iSigma
+ * The sigma that will be used for the gaussian blur
+ */
+ void buildImagesPyramids(GrayImage **steerableBases, bool copy = false, unsigned iNbLevels = 4,
+ float iSigma = 1.0f);
+
+ /*! Reads a pixel value in one of the VewMap density steerable pyramids.
+ * Returns a value between 0 and 1.
+ * \param iOrientation
+ * the number telling which orientation we need to check.
+ * There are _nbOrientations+1 oriented ViewMaps:
+ * 0 -> the ViewMap containing every horizontal lines
+ * 1 -> the ViewMap containing every lines whose orientation is around PI/4
+ * 2 -> the ViewMap containing every vertical lines
+ * 3 -> the ViewMap containing every lines whose orientation is around 3PI/4
+ * 4 -> the complete ViewMap
+ * \param iLevel
+ * The level of the pyramid we want to read
+ * \param x
+ * The abscissa of the desired pixel specified in level0 coordinate system. The origin is the lower left corner.
+ * \param y
+ * The ordinate of the desired pixel specified in level0 coordinate system. The origin is the lower left corner.
+ */
+ float readSteerableViewMapPixel(unsigned iOrientation, int iLevel, int x, int y);
+
+ /*! Reads a pixel in the one of the level of the pyramid containing the images of the complete ViewMap.
+ * Returns a value between 0 and 1.
+ * Equivalent to : readSteerableViewMapPixel(nbOrientations, x, y)
+ */
+ float readCompleteViewMapPixel(int iLevel, int x, int y);
+
+ /*! Returns the number of levels in the pyramids */
+ unsigned int getNumberOfPyramidLevels() const;
+
+ /*! Returns the number of orientations */
+ unsigned int getNumberOfOrientations() const
+ {
+ return _nbOrientations;
+ }
+
+ /*! for debug purposes */
+ void saveSteerableViewMap() const;
+
+protected:
+ void Clear();
+ void Build();
+};
+
+#endif // __FREESTYLE_STEERABLE_VIEW_MAP_H__
diff --git a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp
new file mode 100644
index 00000000000..537688e4c44
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp
@@ -0,0 +1,753 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp
+ * \ingroup freestyle
+ * \brief Class to build view edges and the underlying chains of feature edges...
+ * \author Stephane Grabli
+ * \date 27/10/2003
+ */
+
+#include <list>
+
+#include "SilhouetteGeomEngine.h"
+#include "ViewEdgeXBuilder.h"
+#include "ViewMap.h"
+
+#include "../winged_edge/WXEdge.h"
+
+using namespace std;
+
+void ViewEdgeXBuilder::Init(ViewShape *oVShape)
+{
+ if (0 == oVShape)
+ return;
+
+ // for design conveniance, we store the current SShape.
+ _pCurrentSShape = oVShape->sshape();
+ if (0 == _pCurrentSShape)
+ return;
+
+ _pCurrentVShape = oVShape;
+
+ // Reset previous data
+ //--------------------
+ if (!_SVertexMap.empty())
+ _SVertexMap.clear();
+}
+
+void ViewEdgeXBuilder::BuildViewEdges(WXShape *iWShape, ViewShape *oVShape, vector<ViewEdge*>& ioVEdges,
+ vector<ViewVertex*>& ioVVertices, vector<FEdge*>& ioFEdges,
+ vector<SVertex*>& ioSVertices)
+{
+ // Reinit structures
+ Init(oVShape);
+
+ /* ViewEdge *vedge; */ /* UNUSED */
+ // Let us build the smooth stuff
+ //----------------------------------------
+ // We parse all faces to find the ones that contain smooth edges
+ vector<WFace*>& wfaces = iWShape->GetFaceList();
+ vector<WFace*>::iterator wf, wfend;
+ WXFace *wxf;
+ for (wf = wfaces.begin(), wfend = wfaces.end(); wf != wfend; wf++) {
+ wxf = dynamic_cast<WXFace*>(*wf);
+ if (false == ((wxf))->hasSmoothEdges()) // does it contain at least one smooth edge ?
+ continue;
+ // parse all smooth layers:
+ vector<WXFaceLayer*>& smoothLayers = wxf->getSmoothLayers();
+ for (vector<WXFaceLayer*>::iterator sl = smoothLayers.begin(), slend = smoothLayers.end(); sl != slend; ++sl) {
+ if (!(*sl)->hasSmoothEdge())
+ continue;
+ if (stopSmoothViewEdge((*sl))) // has it been parsed already ?
+ continue;
+ // here we know that we're dealing with a face layer that has not been processed yet and that contains
+ // a smooth edge.
+ /* vedge =*/ /* UNUSED */ BuildSmoothViewEdge(OWXFaceLayer(*sl, true));
+ }
+ }
+
+ // Now let's build sharp view edges:
+ //----------------------------------
+ // Reset all userdata for WXEdge structure
+ //----------------------------------------
+ //iWShape->ResetUserData();
+
+ WXEdge *wxe;
+ vector<WEdge*>& wedges = iWShape->getEdgeList();
+ //------------------------------
+ for (vector<WEdge*>::iterator we = wedges.begin(), weend = wedges.end(); we != weend; we++) {
+ wxe = dynamic_cast<WXEdge*>(*we);
+ if (Nature::NO_FEATURE == wxe->nature())
+ continue;
+
+ if (!stopSharpViewEdge(wxe)) {
+ bool b = true;
+ if (wxe->order() == -1)
+ b = false;
+ BuildSharpViewEdge(OWXEdge(wxe, b));
+ }
+ }
+
+ // Reset all userdata for WXEdge structure
+ //----------------------------------------
+ iWShape->ResetUserData();
+
+ // Add all these new edges to the scene's feature edges list:
+ //-----------------------------------------------------------
+ vector<FEdge*>& newedges = _pCurrentSShape->getEdgeList();
+ vector<SVertex*>& newVertices = _pCurrentSShape->getVertexList();
+ vector<ViewVertex*>& newVVertices = _pCurrentVShape->vertices();
+ vector<ViewEdge*>& newVEdges = _pCurrentVShape->edges();
+
+ // inserts in ioFEdges, at its end, all the edges of newedges
+ ioFEdges.insert(ioFEdges.end(), newedges.begin(), newedges.end());
+ ioSVertices.insert(ioSVertices.end(), newVertices.begin(), newVertices.end());
+ ioVVertices.insert(ioVVertices.end(), newVVertices.begin(), newVVertices.end());
+ ioVEdges.insert(ioVEdges.end(), newVEdges.begin(), newVEdges.end());
+}
+
+ViewEdge *ViewEdgeXBuilder::BuildSmoothViewEdge(const OWXFaceLayer& iFaceLayer)
+{
+ // Find first edge:
+ OWXFaceLayer first = iFaceLayer;
+ OWXFaceLayer currentFace = first;
+
+ // bidirectional chaining.
+ // first direction
+ list<OWXFaceLayer> facesChain;
+ unsigned size = 0;
+ while (!stopSmoothViewEdge(currentFace.fl)) {
+ facesChain.push_back(currentFace);
+ ++size;
+ currentFace.fl->userdata = (void *)1; // processed
+ // Find the next edge!
+ currentFace = FindNextFaceLayer(currentFace);
+ }
+ OWXFaceLayer end = facesChain.back();
+ // second direction
+ currentFace = FindPreviousFaceLayer(first);
+ while (!stopSmoothViewEdge(currentFace.fl)) {
+ facesChain.push_front(currentFace);
+ ++size;
+ currentFace.fl->userdata = (void *)1; // processed
+ // Find the previous edge!
+ currentFace = FindPreviousFaceLayer(currentFace);
+ }
+ first = facesChain.front();
+
+ if (iFaceLayer.fl->nature() & Nature::RIDGE) {
+ if (size < 4) {
+ return 0;
+ }
+ }
+
+ // Start a new chain edges
+ ViewEdge *newVEdge = new ViewEdge;
+ newVEdge->setId(_currentViewId);
+ ++_currentViewId;
+
+ _pCurrentVShape->AddEdge(newVEdge);
+
+ // build FEdges
+ FEdge *feprevious = NULL;
+ FEdge *fefirst = NULL;
+ FEdge *fe = NULL;
+ for (list<OWXFaceLayer>::iterator fl = facesChain.begin(), flend = facesChain.end(); fl != flend; ++fl) {
+ fe = BuildSmoothFEdge(feprevious, (*fl));
+ if (feprevious && fe == feprevious)
+ continue;
+ fe->setViewEdge(newVEdge);
+ if (!fefirst)
+ fefirst = fe;
+ feprevious = fe;
+ }
+ // Store the chain starting edge:
+ _pCurrentSShape->AddChain(fefirst);
+ newVEdge->setNature(iFaceLayer.fl->nature());
+ newVEdge->setFEdgeA(fefirst);
+ newVEdge->setFEdgeB(fe);
+
+ // is it a closed loop ?
+ if ((first == end) && (size != 1)) {
+ fefirst->setPreviousEdge(fe);
+ fe->setNextEdge(fefirst);
+ newVEdge->setA(0);
+ newVEdge->setB(0);
+ }
+ else {
+ ViewVertex *vva = MakeViewVertex(fefirst->vertexA());
+ ViewVertex *vvb = MakeViewVertex(fe->vertexB());
+
+ ((NonTVertex *)vva)->AddOutgoingViewEdge(newVEdge);
+ ((NonTVertex *)vvb)->AddIncomingViewEdge(newVEdge);
+
+ newVEdge->setA(vva);
+ newVEdge->setB(vvb);
+ }
+
+ return newVEdge;
+}
+
+ViewEdge *ViewEdgeXBuilder::BuildSharpViewEdge(const OWXEdge& iWEdge)
+{
+ // Start a new sharp chain edges
+ ViewEdge *newVEdge = new ViewEdge;
+ newVEdge->setId(_currentViewId);
+ ++_currentViewId;
+ unsigned size = 0;
+
+ _pCurrentVShape->AddEdge(newVEdge);
+
+ // Find first edge:
+ OWXEdge firstWEdge = iWEdge;
+ /* OWXEdge previousWEdge = firstWEdge; */ /* UNUSED */
+ OWXEdge currentWEdge = firstWEdge;
+ list<OWXEdge> edgesChain;
+#if 0 /* TK 02-Sep-2012 Experimental fix for incorrect view edge visibility. */
+ // bidirectional chaining
+ // first direction:
+ while (!stopSharpViewEdge(currentWEdge.e)) {
+ edgesChain.push_back(currentWEdge);
+ ++size;
+ currentWEdge.e->userdata = (void *)1; // processed
+ // Find the next edge!
+ currentWEdge = FindNextWEdge(currentWEdge);
+ }
+ OWXEdge endWEdge = edgesChain.back();
+ // second direction
+ currentWEdge = FindPreviousWEdge(firstWEdge);
+ while (!stopSharpViewEdge(currentWEdge.e)) {
+ edgesChain.push_front(currentWEdge);
+ ++size;
+ currentWEdge.e->userdata = (void *)1; // processed
+ // Find the previous edge!
+ currentWEdge = FindPreviousWEdge(currentWEdge);
+ }
+#else
+ edgesChain.push_back(currentWEdge);
+ ++size;
+ currentWEdge.e->userdata = (void *)1; // processed
+ OWXEdge endWEdge = edgesChain.back();
+#endif
+ firstWEdge = edgesChain.front();
+
+ // build FEdges
+ FEdge *feprevious = NULL;
+ FEdge *fefirst = NULL;
+ FEdge *fe = NULL;
+ for (list<OWXEdge>::iterator we = edgesChain.begin(), weend = edgesChain.end(); we != weend; ++we) {
+ fe = BuildSharpFEdge(feprevious, (*we));
+ fe->setViewEdge(newVEdge);
+ if (!fefirst)
+ fefirst = fe;
+ feprevious = fe;
+ }
+ // Store the chain starting edge:
+ _pCurrentSShape->AddChain(fefirst);
+ newVEdge->setNature(iWEdge.e->nature());
+ newVEdge->setFEdgeA(fefirst);
+ newVEdge->setFEdgeB(fe);
+
+ // is it a closed loop ?
+ if ((firstWEdge == endWEdge) && (size != 1)) {
+ fefirst->setPreviousEdge(fe);
+ fe->setNextEdge(fefirst);
+ newVEdge->setA(0);
+ newVEdge->setB(0);
+ }
+ else {
+ ViewVertex *vva = MakeViewVertex(fefirst->vertexA());
+ ViewVertex *vvb = MakeViewVertex(fe->vertexB());
+
+ ((NonTVertex *)vva)->AddOutgoingViewEdge(newVEdge);
+ ((NonTVertex *)vvb)->AddIncomingViewEdge(newVEdge);
+
+ newVEdge->setA(vva);
+ newVEdge->setB(vvb);
+ }
+
+ return newVEdge;
+}
+
+OWXFaceLayer ViewEdgeXBuilder::FindNextFaceLayer(const OWXFaceLayer& iFaceLayer)
+{
+ WXFace *nextFace = NULL;
+ WOEdge *woeend;
+ real tend;
+ if (iFaceLayer.order) {
+ woeend = iFaceLayer.fl->getSmoothEdge()->woeb();
+ tend = iFaceLayer.fl->getSmoothEdge()->tb();
+ }
+ else {
+ woeend = iFaceLayer.fl->getSmoothEdge()->woea();
+ tend = iFaceLayer.fl->getSmoothEdge()->ta();
+ }
+ // special case of EDGE_VERTEX config:
+ if ((tend == 0.0) || (tend == 1.0)) {
+ WVertex *nextVertex;
+ if (tend == 0.0)
+ nextVertex = woeend->GetaVertex();
+ else
+ nextVertex = woeend->GetbVertex();
+ if (nextVertex->isBoundary()) // if it's a non-manifold vertex -> ignore
+ return OWXFaceLayer(0, true);
+ bool found = false;
+ WVertex::face_iterator f = nextVertex->faces_begin();
+ WVertex::face_iterator fend = nextVertex->faces_end();
+ while ((!found) && (f != fend)) {
+ nextFace = dynamic_cast<WXFace*>(*f);
+ if ((0 != nextFace) && (nextFace != iFaceLayer.fl->getFace())) {
+ vector<WXFaceLayer*> sameNatureLayers;
+ nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
+ // don't know... Maybe should test whether this face has also a vertex_edge configuration.
+ if (sameNatureLayers.size() == 1) {
+ WXFaceLayer *winner = sameNatureLayers[0];
+ // check face mark continuity
+ if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark())
+ return OWXFaceLayer(NULL, true);
+ if (woeend == winner->getSmoothEdge()->woea()->twin())
+ return OWXFaceLayer(winner, true);
+ else
+ return OWXFaceLayer(winner, false);
+ }
+ }
+ ++f;
+ }
+ }
+ else {
+ nextFace = dynamic_cast<WXFace*>(iFaceLayer.fl->getFace()->GetBordingFace(woeend));
+ if (!nextFace)
+ return OWXFaceLayer(NULL, true);
+ // if the next face layer has either no smooth edge or no smooth edge of same nature, no next face
+ if (!nextFace->hasSmoothEdges())
+ return OWXFaceLayer(NULL, true);
+ vector<WXFaceLayer*> sameNatureLayers;
+ nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
+ // don't know how to deal with several edges of same nature on a single face
+ if ((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) {
+ return OWXFaceLayer(NULL, true);
+ }
+ else {
+ WXFaceLayer *winner = sameNatureLayers[0];
+ // check face mark continuity
+ if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark())
+ return OWXFaceLayer(NULL, true);
+ if (woeend == winner->getSmoothEdge()->woea()->twin())
+ return OWXFaceLayer(winner, true);
+ else
+ return OWXFaceLayer(winner, false);
+ }
+ }
+ return OWXFaceLayer(NULL, true);
+}
+
+OWXFaceLayer ViewEdgeXBuilder::FindPreviousFaceLayer(const OWXFaceLayer& iFaceLayer)
+{
+ WXFace *previousFace = NULL;
+ WOEdge *woebegin;
+ real tend;
+ if (iFaceLayer.order) {
+ woebegin = iFaceLayer.fl->getSmoothEdge()->woea();
+ tend = iFaceLayer.fl->getSmoothEdge()->ta();
+ }
+ else {
+ woebegin = iFaceLayer.fl->getSmoothEdge()->woeb();
+ tend = iFaceLayer.fl->getSmoothEdge()->tb();
+ }
+
+ // special case of EDGE_VERTEX config:
+ if ((tend == 0.0) || (tend == 1.0)) {
+ WVertex *previousVertex;
+ if (tend == 0.0)
+ previousVertex = woebegin->GetaVertex();
+ else
+ previousVertex = woebegin->GetbVertex();
+ if (previousVertex->isBoundary()) // if it's a non-manifold vertex -> ignore
+ return OWXFaceLayer(NULL, true);
+ bool found = false;
+ WVertex::face_iterator f = previousVertex->faces_begin();
+ WVertex::face_iterator fend = previousVertex->faces_end();
+ for (; (!found) && (f != fend); ++f) {
+ previousFace = dynamic_cast<WXFace*>(*f);
+ if ((0 != previousFace) && (previousFace != iFaceLayer.fl->getFace())) {
+ vector<WXFaceLayer*> sameNatureLayers;
+ previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
+ // don't know... Maybe should test whether this face has also a vertex_edge configuration
+ if (sameNatureLayers.size() == 1) {
+ WXFaceLayer *winner = sameNatureLayers[0];
+ // check face mark continuity
+ if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark())
+ return OWXFaceLayer(NULL, true);
+ if (woebegin == winner->getSmoothEdge()->woeb()->twin())
+ return OWXFaceLayer(winner, true);
+ else
+ return OWXFaceLayer(winner, false);
+ }
+ }
+ }
+ }
+ else {
+ previousFace = dynamic_cast<WXFace*>(iFaceLayer.fl->getFace()->GetBordingFace(woebegin));
+ if (0 == previousFace)
+ return OWXFaceLayer(NULL, true);
+ // if the next face layer has either no smooth edge or no smooth edge of same nature, no next face
+ if (!previousFace->hasSmoothEdges())
+ return OWXFaceLayer(NULL, true);
+ vector<WXFaceLayer*> sameNatureLayers;
+ previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
+ // don't know how to deal with several edges of same nature on a single face
+ if ((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) {
+ return OWXFaceLayer(NULL, true);
+ }
+ else {
+ WXFaceLayer *winner = sameNatureLayers[0];
+ // check face mark continuity
+ if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark())
+ return OWXFaceLayer(NULL, true);
+ if (woebegin == winner->getSmoothEdge()->woeb()->twin())
+ return OWXFaceLayer(winner, true);
+ else
+ return OWXFaceLayer(winner, false);
+ }
+ }
+ return OWXFaceLayer(NULL, true);
+}
+
+FEdge *ViewEdgeXBuilder::BuildSmoothFEdge(FEdge *feprevious, const OWXFaceLayer& ifl)
+{
+ WOEdge *woea, *woeb;
+ real ta, tb;
+ SVertex *va, *vb;
+ FEdgeSmooth *fe;
+ // retrieve exact silhouette data
+ WXSmoothEdge *se = ifl.fl->getSmoothEdge();
+
+ if (ifl.order) {
+ woea = se->woea();
+ woeb = se->woeb();
+ ta = se->ta();
+ tb = se->tb();
+ }
+ else {
+ woea = se->woeb();
+ woeb = se->woea();
+ ta = se->tb();
+ tb = se->ta();
+ }
+
+ Vec3r normal;
+ // Make the 2 Svertices
+ if (feprevious == 0) { // that means that we don't have any vertex already built for that face
+ Vec3r A1(woea->GetaVertex()->GetVertex());
+ Vec3r A2(woea->GetbVertex()->GetVertex());
+ Vec3r A(A1 + ta * (A2 - A1));
+
+ va = MakeSVertex(A, false);
+ // Set normal:
+ Vec3r NA1(ifl.fl->getFace()->GetVertexNormal(woea->GetaVertex()));
+ Vec3r NA2(ifl.fl->getFace()->GetVertexNormal(woea->GetbVertex()));
+ Vec3r na((1 - ta) * NA1 + ta * NA2);
+ na.normalize();
+ va->AddNormal(na);
+ normal = na;
+
+ // Set CurvatureInfo
+ CurvatureInfo *curvature_info_a =
+ new CurvatureInfo(*(dynamic_cast<WXVertex*>(woea->GetaVertex())->curvatures()),
+ *(dynamic_cast<WXVertex*>(woea->GetbVertex())->curvatures()), ta);
+ va->setCurvatureInfo(curvature_info_a);
+ }
+ else {
+ va = feprevious->vertexB();
+ }
+
+ Vec3r B1(woeb->GetaVertex()->GetVertex());
+ Vec3r B2(woeb->GetbVertex()->GetVertex());
+ Vec3r B(B1 + tb * (B2 - B1));
+
+ if (feprevious && (B - va->point3D()).norm() < 1.0e-6)
+ return feprevious;
+
+ vb = MakeSVertex(B, false);
+ // Set normal:
+ Vec3r NB1(ifl.fl->getFace()->GetVertexNormal(woeb->GetaVertex()));
+ Vec3r NB2(ifl.fl->getFace()->GetVertexNormal(woeb->GetbVertex()));
+ Vec3r nb((1 - tb) * NB1 + tb * NB2);
+ nb.normalize();
+ normal += nb;
+ vb->AddNormal(nb);
+
+ // Set CurvatureInfo
+ CurvatureInfo *curvature_info_b =
+ new CurvatureInfo(*(dynamic_cast<WXVertex*>(woeb->GetaVertex())->curvatures()),
+ *(dynamic_cast<WXVertex*>(woeb->GetbVertex())->curvatures()), tb);
+ vb->setCurvatureInfo(curvature_info_b);
+
+ // Creates the corresponding feature edge
+ fe = new FEdgeSmooth(va, vb);
+ fe->setNature(ifl.fl->nature());
+ fe->setId(_currentFId);
+ fe->setFrsMaterialIndex(ifl.fl->getFace()->frs_materialIndex());
+ fe->setFace(ifl.fl->getFace());
+ fe->setFaceMark(ifl.fl->getFace()->GetMark());
+ if (feprevious == 0)
+ normal.normalize();
+ fe->setNormal(normal);
+ fe->setPreviousEdge(feprevious);
+ if (feprevious)
+ feprevious->setNextEdge(fe);
+ _pCurrentSShape->AddEdge(fe);
+ va->AddFEdge(fe);
+ vb->AddFEdge(fe);
+
+ ++_currentFId;
+ ifl.fl->userdata = fe;
+ return fe;
+}
+
+bool ViewEdgeXBuilder::stopSmoothViewEdge(WXFaceLayer *iFaceLayer)
+{
+ if (0 == iFaceLayer)
+ return true;
+ if (iFaceLayer->userdata == 0)
+ return false;
+ return true;
+}
+
+int ViewEdgeXBuilder::retrieveFaceMarks(WXEdge *iEdge)
+{
+ WFace *aFace = iEdge->GetaFace();
+ WFace *bFace = iEdge->GetbFace();
+ int result = 0;
+ if (aFace && aFace->GetMark())
+ result += 1;
+ if (bFace && bFace->GetMark())
+ result += 2;
+ return result;
+}
+
+OWXEdge ViewEdgeXBuilder::FindNextWEdge(const OWXEdge& iEdge)
+{
+ if (Nature::NO_FEATURE == iEdge.e->nature())
+ return OWXEdge(NULL, true);
+
+ WVertex *v;
+ if (true == iEdge.order)
+ v = iEdge.e->GetbVertex();
+ else
+ v = iEdge.e->GetaVertex();
+
+ if (((WXVertex *)v)->isFeature())
+ return 0; /* XXX eeek? NULL? OWXEdge(NULL, true/false)?*/
+
+ int faceMarks = retrieveFaceMarks(iEdge.e);
+ vector<WEdge*>& vEdges = (v)->GetEdges();
+ for (vector<WEdge*>::iterator ve = vEdges.begin(), veend = vEdges.end(); ve != veend; ve++) {
+ WXEdge *wxe = dynamic_cast<WXEdge*>(*ve);
+ if (wxe == iEdge.e)
+ continue; // same edge as the one processed
+
+ if (wxe->nature() != iEdge.e->nature())
+ continue;
+
+ // check face mark continuity
+ if (retrieveFaceMarks(wxe) != faceMarks)
+ continue;
+
+ if (wxe->GetaVertex() == v) {
+ // That means that the face necesarily lies on the edge left.
+ // So the vertex order is OK.
+ return OWXEdge(wxe, true);
+ }
+ else {
+ // That means that the face necesarily lies on the edge left.
+ // So the vertex order is OK.
+ return OWXEdge(wxe, false);
+ }
+ }
+ // we did not find:
+ return OWXEdge(NULL, true);
+}
+
+OWXEdge ViewEdgeXBuilder::FindPreviousWEdge(const OWXEdge& iEdge)
+{
+ if (Nature::NO_FEATURE == iEdge.e->nature())
+ return OWXEdge(NULL, true);
+
+ WVertex *v;
+ if (true == iEdge.order)
+ v = iEdge.e->GetaVertex();
+ else
+ v = iEdge.e->GetbVertex();
+
+ if (((WXVertex *)v)->isFeature())
+ return 0;
+
+ int faceMarks = retrieveFaceMarks(iEdge.e);
+ vector<WEdge *>& vEdges = (v)->GetEdges();
+ for (vector<WEdge *>::iterator ve = vEdges.begin(), veend = vEdges.end(); ve != veend; ve++) {
+ WXEdge *wxe = dynamic_cast<WXEdge *>(*ve);
+ if (wxe == iEdge.e)
+ continue; // same edge as the one processed
+
+ if (wxe->nature() != iEdge.e->nature())
+ continue;
+
+ // check face mark continuity
+ if (retrieveFaceMarks(wxe) != faceMarks)
+ continue;
+
+ if (wxe->GetbVertex() == v) {
+ return OWXEdge(wxe, true);
+ }
+ else {
+ return OWXEdge(wxe, false);
+ }
+ }
+ // we did not find:
+ return OWXEdge(NULL, true);
+}
+
+FEdge *ViewEdgeXBuilder::BuildSharpFEdge(FEdge *feprevious, const OWXEdge& iwe)
+{
+ SVertex *va, *vb;
+ FEdgeSharp *fe;
+ WXVertex *wxVA, *wxVB;
+ if (iwe.order) {
+ wxVA = (WXVertex *)iwe.e->GetaVertex();
+ wxVB = (WXVertex *)iwe.e->GetbVertex();
+ }
+ else {
+ wxVA = (WXVertex *)iwe.e->GetbVertex();
+ wxVB = (WXVertex *)iwe.e->GetaVertex();
+ }
+ // Make the 2 SVertex
+ va = MakeSVertex(wxVA->GetVertex(), true);
+ vb = MakeSVertex(wxVB->GetVertex(), true);
+
+ // get the faces normals and the material indices
+ Vec3r normalA, normalB;
+ unsigned matA(0), matB(0);
+ bool faceMarkA = false, faceMarkB = false;
+ if (iwe.order) {
+ normalB = (iwe.e->GetbFace()->GetNormal());
+ matB = (iwe.e->GetbFace()->frs_materialIndex());
+ faceMarkB = (iwe.e->GetbFace()->GetMark());
+ if (!(iwe.e->nature() & Nature::BORDER)) {
+ normalA = (iwe.e->GetaFace()->GetNormal());
+ matA = (iwe.e->GetaFace()->frs_materialIndex());
+ faceMarkA = (iwe.e->GetaFace()->GetMark());
+ }
+ }
+ else {
+ normalA = (iwe.e->GetbFace()->GetNormal());
+ matA = (iwe.e->GetbFace()->frs_materialIndex());
+ faceMarkA = (iwe.e->GetbFace()->GetMark());
+ if (!(iwe.e->nature() & Nature::BORDER)) {
+ normalB = (iwe.e->GetaFace()->GetNormal());
+ matB = (iwe.e->GetaFace()->frs_materialIndex());
+ faceMarkB = (iwe.e->GetaFace()->GetMark());
+ }
+ }
+ // Creates the corresponding feature edge
+ fe = new FEdgeSharp(va, vb);
+ fe->setNature(iwe.e->nature());
+ fe->setId(_currentFId);
+ fe->setaFrsMaterialIndex(matA);
+ fe->setbFrsMaterialIndex(matB);
+ fe->setaFaceMark(faceMarkA);
+ fe->setbFaceMark(faceMarkB);
+ fe->setNormalA(normalA);
+ fe->setNormalB(normalB);
+ fe->setPreviousEdge(feprevious);
+ if (feprevious)
+ feprevious->setNextEdge(fe);
+ _pCurrentSShape->AddEdge(fe);
+ va->AddFEdge(fe);
+ vb->AddFEdge(fe);
+ //Add normals:
+ va->AddNormal(normalA);
+ va->AddNormal(normalB);
+ vb->AddNormal(normalA);
+ vb->AddNormal(normalB);
+
+ ++_currentFId;
+ iwe.e->userdata = fe;
+ return fe;
+}
+
+bool ViewEdgeXBuilder::stopSharpViewEdge(WXEdge *iEdge)
+{
+ if (0 == iEdge)
+ return true;
+ if (iEdge->userdata == 0)
+ return false;
+ return true;
+}
+
+SVertex *ViewEdgeXBuilder::MakeSVertex(Vec3r& iPoint)
+{
+ SVertex *va = new SVertex(iPoint, _currentSVertexId);
+ SilhouetteGeomEngine::ProjectSilhouette(va);
+ ++_currentSVertexId;
+ // Add the svertex to the SShape svertex list:
+ _pCurrentSShape->AddNewVertex(va);
+ return va;
+}
+
+SVertex *ViewEdgeXBuilder::MakeSVertex(Vec3r& iPoint, bool shared)
+{
+ SVertex *va;
+ if (!shared) {
+ va = MakeSVertex(iPoint);
+ }
+ else {
+ // Check whether the iPoint is already in the table
+ SVertexMap::const_iterator found = _SVertexMap.find(iPoint);
+ if (shared && found != _SVertexMap.end()) {
+ va = (*found).second;
+ }
+ else {
+ va = MakeSVertex(iPoint);
+ // Add the svertex into the table using iPoint as the key
+ _SVertexMap[iPoint] = va;
+ }
+ }
+ return va;
+}
+
+ViewVertex *ViewEdgeXBuilder::MakeViewVertex(SVertex *iSVertex)
+{
+ ViewVertex *vva = iSVertex->viewvertex();
+ if (vva)
+ return vva;
+ vva = new NonTVertex(iSVertex);
+ // Add the view vertex to the ViewShape svertex list:
+ _pCurrentVShape->AddVertex(vva);
+ return vva;
+}
diff --git a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h
new file mode 100644
index 00000000000..024ab7eac5f
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h
@@ -0,0 +1,288 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_VIEW_EDGE_X_BUILDER_H__
+#define __FREESTYLE_VIEW_EDGE_X_BUILDER_H__
+
+/** \file blender/freestyle/intern/view_map/ViewEdgeXBuilder.h
+ * \ingroup freestyle
+ * \brief Class to build view edges and the underlying chains of feature edges...
+ * \author Stephane Grabli
+ * \date 27/10/2003
+ */
+
+#include <map>
+#include <utility>
+#include <vector>
+
+#if 0 // soc
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+//hash_map is not part of the C++ standard anymore; hash_map.h has been kept though for backward compatibility
+# include <hash_map.h>
+#else
+# include <hash_map>
+#endif
+#endif
+
+#include "Interface1D.h"
+
+#include "../geometry/Geom.h"
+
+#include "../system/FreestyleConfig.h"
+
+using namespace Geometry;
+using namespace std;
+
+class SVertex;
+
+/*! Defines a hash table used for searching the SVertex */
+struct SVertexHasher
+{
+#define _MUL 950706376UL
+#define _MOD 2147483647UL
+ inline size_t operator()(const Vec3r& p) const
+ {
+ size_t res = ((unsigned long)(p[0] * _MUL)) % _MOD;
+ res = ((res + (unsigned long)(p[1]) * _MUL)) % _MOD;
+ return ((res +(unsigned long)(p[2]) * _MUL)) % _MOD;
+ }
+#undef _MUL
+#undef _MOD
+};
+
+// Key_compare predicate for hash_map. In particular, return false if equal.
+struct epsilonEquals
+{
+ bool operator()(const Vec3r& v1, const Vec3r& v2) const
+ {
+ real norm = (v1 - v2).norm();
+ return (norm < 1.0e-06);
+ }
+};
+
+
+// typedef hash_map<Vec3r, SVertex*, SVertexHasher, epsilonEquals> SVertexMap;
+typedef map<Vec3r, SVertex *> SVertexMap;
+
+class WXFaceLayer;
+
+/*! class to describe an oriented smooth edge */
+class OWXFaceLayer
+{
+public:
+ WXFaceLayer *fl;
+ bool order;
+
+ OWXFaceLayer()
+ {
+ fl = NULL;
+ order = true;
+ }
+
+ OWXFaceLayer(WXFaceLayer *ifl, bool iOrder = true)
+ {
+ fl = ifl;
+ order = iOrder;
+ }
+
+ OWXFaceLayer& operator=(const OWXFaceLayer& iBrother)
+ {
+ fl = iBrother.fl;
+ order = iBrother.order;
+ return *this;
+ }
+
+ bool operator==(const OWXFaceLayer& b)
+ {
+ return ((fl == b.fl) && (order == b.order));
+ }
+
+ bool operator!=(const OWXFaceLayer& b)
+ {
+ return !(*this == b);
+ }
+};
+
+class WXEdge;
+
+/*! class to describe an oriented sharp edge */
+class OWXEdge
+{
+public:
+ WXEdge *e;
+ bool order;
+
+ OWXEdge()
+ {
+ e = NULL;
+ order = true;
+ }
+
+ OWXEdge(WXEdge *ie, bool iOrder = true)
+ {
+ e = ie;
+ order = iOrder;
+ }
+
+ OWXEdge& operator=(const OWXEdge& iBrother)
+ {
+ e = iBrother.e;
+ order = iBrother.order;
+ return *this;
+ }
+
+ bool operator==(const OWXEdge& b)
+ {
+ return ((e == b.e) && (order == b.order));
+ }
+
+ bool operator!=(const OWXEdge& b)
+ {
+ return !(*this == b);
+ }
+};
+
+class WOEdge;
+class WXEdge;
+class WXShape;
+class SVertex;
+class FEdge;
+class ViewVertex;
+class ViewEdge;
+class ViewShape;
+
+class LIB_VIEW_MAP_EXPORT ViewEdgeXBuilder
+{
+protected:
+ int _currentViewId; // Id for view edges
+ int _currentFId; // Id for FEdges
+ int _currentSVertexId; // Id for SVertex
+
+public:
+ inline ViewEdgeXBuilder()
+ {
+ _currentViewId = 1;
+ _currentFId = 0;
+ _currentSVertexId = 0;
+ }
+
+ virtual ~ViewEdgeXBuilder() {}
+
+ /*! Builds a view shape from a WXShape in which the feature edges are flagged
+ * Builds chains of feature edges (so ViewEdges) from a WXShape
+ * iWShape
+ * The Winged Edge structure in which all silhouette edges and vertices are flagged.
+ * oViewShape
+ * The Silhouette Shape in which the chains must be added.
+ * ioVEdges
+ * The list of new ViewEdges.
+ * ioVVertices
+ * THe new ViewVertices
+ * ioFEdges
+ * A list in which all new FEdges are added
+ * ioSVertices
+ * A list of SVertex where all created SVertex are added.
+ */
+ virtual void BuildViewEdges(WXShape *iWShape, ViewShape *oVShape, std::vector<ViewEdge*>& ioVEdges,
+ std::vector<ViewVertex*>& ioVVertices, std::vector<FEdge*>& ioFEdges,
+ std::vector<SVertex*>& ioSVertices);
+
+ /*! Builds a smooth view edge, starting the face iFace. */
+ ViewEdge *BuildSmoothViewEdge(const OWXFaceLayer& iFaceLayer);
+
+ /*! Makes a sharp viewedge */
+ ViewEdge *BuildSharpViewEdge(const OWXEdge& iWEdge);
+
+public:
+ /*! accessors */
+ inline int currentViewId() const
+ {
+ return _currentViewId;
+ }
+
+ inline int currentFId() const
+ {
+ return _currentFId;
+ }
+
+ inline int currentSVertexId() const
+ {
+ return _currentSVertexId;
+ }
+
+ /*! modifiers */
+ inline void setCurrentViewId(int id)
+ {
+ _currentViewId = id;
+ }
+
+ inline void setCurrentFId(int id)
+ {
+ _currentFId = id;
+ }
+
+ inline void setCurrentSVertexId(int id)
+ {
+ _currentSVertexId = id;
+ }
+
+protected:
+ /*! Init the view edges building */
+ virtual void Init(ViewShape *oVShape);
+
+ // SMOOTH //
+ /*! checks whether a face has already been processed or not */
+ bool stopSmoothViewEdge(WXFaceLayer *iFaceLayer);
+ OWXFaceLayer FindNextFaceLayer(const OWXFaceLayer& iFaceLayer);
+ OWXFaceLayer FindPreviousFaceLayer(const OWXFaceLayer& iFaceLayer);
+ FEdge *BuildSmoothFEdge(FEdge *feprevious, const OWXFaceLayer& ifl);
+
+ // SHARP //
+ /*! checks whether a WEdge has already been processed or not */
+ bool stopSharpViewEdge(WXEdge *iFace);
+ int retrieveFaceMarks(WXEdge *iEdge);
+ OWXEdge FindNextWEdge(const OWXEdge& iEdge);
+ OWXEdge FindPreviousWEdge(const OWXEdge& iEdge);
+ FEdge *BuildSharpFEdge(FEdge *feprevious, const OWXEdge& iwe);
+
+ // GENERAL //
+ /*! Instanciate a SVertex */
+ SVertex *MakeSVertex(Vec3r& iPoint);
+ /*! Instanciate a SVertex if it hasn't been already created */
+ SVertex *MakeSVertex(Vec3r& iPoint, bool shared);
+ /*! instanciate a ViewVertex from a SVertex, if it doesn't exist yet */
+ ViewVertex *MakeViewVertex(SVertex *iSVertex);
+
+ //oldtmp values
+ //IdHashTable _hashtable;
+ //VVIdHashTable _multivertexHashTable;
+ SVertexMap _SVertexMap;
+ SShape *_pCurrentSShape;
+ ViewShape *_pCurrentVShape;
+};
+
+#endif // __FREESTYLE_VIEW_EDGE_X_BUILDER_H__
diff --git a/source/blender/freestyle/intern/view_map/ViewMap.cpp b/source/blender/freestyle/intern/view_map/ViewMap.cpp
new file mode 100644
index 00000000000..7f8c797b5b9
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMap.cpp
@@ -0,0 +1,754 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/ViewMap.cpp
+ * \ingroup freestyle
+ * \brief Classes to define a View Map (ViewVertex, ViewEdge, etc.)
+ * \author Stephane Grabli
+ * \date 03/09/2002
+ */
+
+#include <float.h>
+
+#include "ViewMap.h"
+#include "ViewMapAdvancedIterators.h"
+#include "ViewMapIterators.h"
+
+#include "../geometry/GeomUtils.h"
+
+/**********************************/
+/* */
+/* */
+/* ViewMap */
+/* */
+/* */
+/**********************************/
+
+ViewMap *ViewMap::_pInstance = NULL;
+
+ViewMap::~ViewMap()
+{
+ // The view vertices must be deleted here as some of them are shared between two shapes:
+ for (vector<ViewVertex*>::iterator vv = _VVertices.begin(), vvend = _VVertices.end(); vv != vvend; vv++) {
+ delete (*vv);
+ }
+ _VVertices.clear();
+
+ for (vector<ViewShape*>::iterator vs = _VShapes.begin(), vsend = _VShapes.end(); vs != vsend; vs++) {
+ delete (*vs);
+ }
+ _VShapes.clear();
+
+ _FEdges.clear();
+ _SVertices.clear();
+ _VEdges.clear();
+}
+
+ViewShape *ViewMap::viewShape(unsigned id)
+{
+ int index = _shapeIdToIndex[id];
+ return _VShapes[ index ];
+}
+
+void ViewMap::AddViewShape(ViewShape *iVShape)
+{
+ _shapeIdToIndex[iVShape->getId().getFirst()] = _VShapes.size();
+ _VShapes.push_back(iVShape);
+}
+
+const FEdge *ViewMap::getClosestFEdge(real x, real y) const
+{
+ // find the closest of this candidates:
+ real minDist = DBL_MAX;
+ FEdge *winner = NULL;
+ for (fedges_container::const_iterator fe = _FEdges.begin(), feend = _FEdges.end(); fe != feend; fe++) {
+ Vec2d A((*fe)->vertexA()->point2D()[0], (*fe)->vertexA()->point2D()[1]);
+ Vec2d B((*fe)->vertexB()->point2D()[0], (*fe)->vertexB()->point2D()[1]);
+ real dist = GeomUtils::distPointSegment<Vec2r>(Vec2r(x, y), A, B);
+ if (dist < minDist) {
+ minDist = dist;
+ winner = (*fe);
+ }
+ }
+
+ return winner;
+}
+
+const ViewEdge *ViewMap::getClosestViewEdge(real x, real y) const
+{
+ // find the closest of this candidates:
+ real minDist = DBL_MAX;
+ FEdge *winner = NULL;
+ for (fedges_container::const_iterator fe = _FEdges.begin(), feend = _FEdges.end(); fe != feend; fe++) {
+ Vec2d A((*fe)->vertexA()->point2D()[0], (*fe)->vertexA()->point2D()[1]);
+ Vec2d B((*fe)->vertexB()->point2D()[0], (*fe)->vertexB()->point2D()[1]);
+ real dist = GeomUtils::distPointSegment<Vec2r>(Vec2r(x, y), A, B);
+ if (dist < minDist) {
+ minDist = dist;
+ winner = (*fe);
+ }
+ }
+ if (!winner)
+ return NULL;
+
+ return winner->viewedge();
+}
+
+
+TVertex *ViewMap::CreateTVertex(const Vec3r& iA3D, const Vec3r& iA2D, FEdge *iFEdgeA,
+ const Vec3r& iB3D, const Vec3r& iB2D, FEdge *iFEdgeB, const Id& id)
+{
+ ViewShape *vshapeA = iFEdgeA->viewedge()->viewShape();
+ SShape *shapeA = iFEdgeA->shape();
+ ViewShape *vshapeB = iFEdgeB->viewedge()->viewShape();
+ SShape *shapeB = iFEdgeB->shape();
+
+ SVertex *Ia = shapeA->CreateSVertex(iA3D, iA2D, iFEdgeA->vertexA()->getId());
+ SVertex *Ib = shapeB->CreateSVertex(iB3D, iB2D, iFEdgeB->vertexA()->getId());
+
+ // depending on which of these 2 svertices is the nearest from the viewpoint, we're going to build the TVertex
+ // by giving them in an order or another (the first one must be the nearest)
+ real dista = Ia->point2D()[2];
+ real distb = Ib->point2D()[2];
+
+ TVertex *tvertex;
+ if (dista < distb)
+ tvertex = new TVertex(Ia, Ib);
+ else
+ tvertex = new TVertex(Ib, Ia);
+
+ tvertex->setId(id);
+
+ // add these vertices to the view map
+ AddViewVertex(tvertex);
+ AddSVertex(Ia);
+ AddSVertex(Ib);
+
+ // and this T Vertex to the view shapes:
+ vshapeA->AddVertex(tvertex);
+ vshapeB->AddVertex(tvertex);
+
+ return tvertex;
+}
+
+ViewVertex *ViewMap::InsertViewVertex(SVertex *iVertex, vector<ViewEdge*>& newViewEdges)
+{
+ NonTVertex *vva = dynamic_cast<NonTVertex*>(iVertex->viewvertex());
+ if (vva)
+ return vva;
+ // because it is not already a ViewVertex, this SVertex must have only 2 FEdges. The incoming one still belongs
+ // to ioEdge, the outgoing one now belongs to newVEdge
+ const vector<FEdge *>& fedges = iVertex->fedges();
+ if (fedges.size() != 2) {
+ cerr << "ViewMap warning: Can't split the ViewEdge" << endl;
+ return NULL;
+ }
+ FEdge *fend(NULL), *fbegin(NULL);
+ for (vector<FEdge *>::const_iterator fe = fedges.begin(), feend = fedges.end(); fe != feend; ++fe) {
+ if ((*fe)->vertexB() == iVertex) {
+ fend = (*fe);
+ }
+ if ((*fe)->vertexA() == iVertex) {
+ fbegin = (*fe);
+ }
+ if ((fbegin != NULL) && (fend != NULL))
+ break;
+ }
+ ViewEdge *ioEdge = fbegin->viewedge();
+ ViewShape *vshape = ioEdge->viewShape();
+ vva = new NonTVertex(iVertex);
+ // if the ViewEdge is a closed loop, we don't create a new VEdge
+ if (ioEdge->A() == 0) {
+ // closed loop
+ ioEdge->setA(vva);
+ ioEdge->setB(vva);
+ // update sshape
+ vshape->sshape()->RemoveEdgeFromChain(ioEdge->fedgeA());
+ vshape->sshape()->RemoveEdgeFromChain(ioEdge->fedgeB());
+
+ ioEdge->setFEdgeA(fbegin);
+ ioEdge->setFEdgeB(fend);
+
+ // Update FEdges
+ fend->setNextEdge(NULL);
+ fbegin->setPreviousEdge(NULL);
+
+ // update new View Vertex:
+ vva->AddOutgoingViewEdge(ioEdge);
+ vva->AddIncomingViewEdge(ioEdge);
+
+ vshape->sshape()->AddChain(ioEdge->fedgeA());
+ vshape->sshape()->AddChain(ioEdge->fedgeB());
+ }
+ else {
+ // Create new ViewEdge
+ ViewEdge *newVEdge = new ViewEdge(vva, ioEdge->B(), fbegin, ioEdge->fedgeB(), vshape);
+ newVEdge->setId(Id(ioEdge->getId().getFirst(), ioEdge->getId().getSecond() + 1));
+ newVEdge->setNature(ioEdge->getNature());
+ //newVEdge->UpdateFEdges(); // done in the ViewEdge constructor
+ // Update old ViewEdge
+ ioEdge->setB(vva);
+ ioEdge->setFEdgeB(fend);
+
+ // Update FEdges
+ fend->setNextEdge(NULL);
+ fbegin->setPreviousEdge(NULL);
+
+ // update new View Vertex:
+ vva->AddOutgoingViewEdge(newVEdge);
+ vva->AddIncomingViewEdge(ioEdge);
+ // update ViewShape
+ //vshape->AddEdge(newVEdge);
+ // update SShape
+ vshape->sshape()->AddChain(fbegin);
+ // update ViewMap
+ //_VEdges.push_back(newVEdge);
+ newViewEdges.push_back(newVEdge);
+ }
+
+ // update ViewShape
+ vshape->AddVertex(vva);
+
+ // update ViewMap
+ _VVertices.push_back(vva);
+
+ return vva;
+}
+
+#if 0
+FEdge *ViewMap::Connect(FEdge *ioEdge, SVertex *ioVertex, vector<ViewEdge*>& oNewVEdges)
+{
+ SShape *sshape = ioEdge->shape();
+ FEdge *newFEdge = sshape->SplitEdgeIn2(ioEdge, ioVertex);
+ AddFEdge(newFEdge);
+ InsertViewVertex(ioVertex, oNewVEdges);
+ return newFEdge;
+}
+#endif
+
+/**********************************/
+/* */
+/* */
+/* TVertex */
+/* */
+/* */
+/**********************************/
+
+// is dve1 before dve2 ? (does it have a smaller angle ?)
+static bool ViewEdgeComp(ViewVertex::directedViewEdge& dve1, ViewVertex::directedViewEdge& dve2)
+{
+ FEdge *fe1;
+ if (dve1.second)
+ fe1 = dve1.first->fedgeB();
+ else
+ fe1 = dve1.first->fedgeA();
+ FEdge *fe2;
+ if (dve2.second)
+ fe2 = dve2.first->fedgeB();
+ else
+ fe2 = dve2.first->fedgeA();
+
+ Vec3r V1 = fe1->orientation2d();
+ Vec2r v1(V1.x(), V1.y());
+ v1.normalize();
+ Vec3r V2 = fe2->orientation2d();
+ Vec2r v2(V2.x(), V2.y());
+ v2.normalize();
+ if (v1.y() > 0) {
+ if (v2.y() < 0)
+ return true;
+ else
+ return (v1.x() > v2.x());
+ }
+ else {
+ if (v2.y() > 0)
+ return false;
+ else
+ return (v1.x() < v2.x());
+ }
+ return false;
+}
+
+void TVertex::setFrontEdgeA(ViewEdge *iFrontEdgeA, bool incoming)
+{
+ if (!iFrontEdgeA) {
+ cerr << "Warning: null pointer passed as argument of TVertex::setFrontEdgeA()" << endl;
+ return;
+ }
+ _FrontEdgeA = directedViewEdge(iFrontEdgeA, incoming);
+ if (!_sortedEdges.empty()) {
+ edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end();
+ for (; (dve != dveend) && ViewEdgeComp(**dve, _FrontEdgeA); ++dve);
+ _sortedEdges.insert( dve, &_FrontEdgeA);
+ }
+ else {
+ _sortedEdges.push_back(&_FrontEdgeA);
+ }
+}
+
+void TVertex::setFrontEdgeB(ViewEdge *iFrontEdgeB, bool incoming)
+{
+ if (!iFrontEdgeB) {
+ cerr << "Warning: null pointer passed as argument of TVertex::setFrontEdgeB()" << endl;
+ return;
+ }
+ _FrontEdgeB = directedViewEdge(iFrontEdgeB, incoming);
+ if (!_sortedEdges.empty()) {
+ edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end();
+ for (; (dve != dveend) && ViewEdgeComp(**dve, _FrontEdgeB); ++dve);
+ _sortedEdges.insert(dve, &_FrontEdgeB);
+ }
+ else {
+ _sortedEdges.push_back(&_FrontEdgeB);
+ }
+}
+
+void TVertex::setBackEdgeA(ViewEdge *iBackEdgeA, bool incoming)
+{
+ if (!iBackEdgeA) {
+ cerr << "Warning: null pointer passed as argument of TVertex::setBackEdgeA()" << endl;
+ return;
+ }
+ _BackEdgeA = directedViewEdge(iBackEdgeA, incoming);
+ if (!_sortedEdges.empty()) {
+ edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end();
+ for (; (dve != dveend) && ViewEdgeComp(**dve, _BackEdgeA); ++dve);
+ _sortedEdges.insert(dve, &_BackEdgeA);
+ }
+ else {
+ _sortedEdges.push_back(&_BackEdgeA);
+ }
+}
+
+void TVertex::setBackEdgeB(ViewEdge *iBackEdgeB, bool incoming)
+{
+ if (!iBackEdgeB) {
+ cerr << "Warning: null pointer passed as argument of TVertex::setBackEdgeB()" << endl;
+ return;
+ }
+ _BackEdgeB = directedViewEdge(iBackEdgeB, incoming);
+ if (!_sortedEdges.empty()) {
+ edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end();
+ for (; (dve != dveend) && ViewEdgeComp(**dve, _BackEdgeB); ++dve);
+ _sortedEdges.insert(dve, &_BackEdgeB);
+ }
+ else {
+ _sortedEdges.push_back(&_BackEdgeB);
+ }
+}
+
+void TVertex::Replace(ViewEdge *iOld, ViewEdge *iNew)
+{
+ // theoritically, we only replace edges for which this
+ // view vertex is the B vertex
+ if ((iOld == _FrontEdgeA.first) && (_FrontEdgeA.first->B() == this)) {
+ _FrontEdgeA.first = iNew;
+ return;
+ }
+ if ((iOld == _FrontEdgeB.first) && (_FrontEdgeB.first->B() == this)) {
+ _FrontEdgeB.first = iNew;
+ return;
+ }
+ if ((iOld == _BackEdgeA.first) && (_BackEdgeA.first->B() == this)) {
+ _BackEdgeA.first = iNew;
+ return;
+ }
+ if ((iOld == _BackEdgeB.first) && (_BackEdgeB.first->B() == this)) {
+ _BackEdgeB.first = iNew;
+ return;
+ }
+}
+
+/*! iterators access */
+ViewVertex::edge_iterator TVertex::edges_begin()
+{
+ //return edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, _FrontEdgeA);
+ return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
+}
+
+ViewVertex::const_edge_iterator TVertex::edges_begin() const
+{
+ //return const_edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, _FrontEdgeA);
+ return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
+}
+
+ViewVertex::edge_iterator TVertex::edges_end()
+{
+ //return edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, directedViewEdge(0,true));
+ return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.end());
+}
+
+ViewVertex::const_edge_iterator TVertex::edges_end() const
+{
+ //return const_edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, directedViewEdge(0, true));
+ return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.end());
+}
+
+ViewVertex::edge_iterator TVertex::edges_iterator(ViewEdge *iEdge)
+{
+ for (edge_pointers_container::iterator it = _sortedEdges.begin(), itend = _sortedEdges.end(); it != itend; it++) {
+ if ((*it)->first == iEdge)
+ return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), it);
+ }
+ return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
+
+#if 0
+ directedViewEdge dEdge;
+ if (_FrontEdgeA.first == iEdge)
+ dEdge = _FrontEdgeA;
+ else if (_FrontEdgeB.first == iEdge)
+ dEdge = _FrontEdgeB;
+ else if (_BackEdgeA.first == iEdge)
+ dEdge = _BackEdgeA;
+ else if (_BackEdgeB.first == iEdge)
+ dEdge = _BackEdgeB;
+ return edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, dEdge);
+#endif
+}
+
+ViewVertex::const_edge_iterator TVertex::edges_iterator(ViewEdge *iEdge) const
+{
+ for (edge_pointers_container::const_iterator it = _sortedEdges.begin(), itend = _sortedEdges.end();
+ it != itend;
+ it++)
+ {
+ if ((*it)->first == iEdge)
+ return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), it);
+ }
+ return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
+
+#if 0
+ directedViewEdge dEdge;
+ if (_FrontEdgeA.first == iEdge)
+ dEdge = _FrontEdgeA;
+ else if (_FrontEdgeB.first == iEdge)
+ dEdge = _FrontEdgeB;
+ else if (_BackEdgeA.first == iEdge)
+ dEdge = _BackEdgeA;
+ else if (_BackEdgeB.first == iEdge)
+ dEdge = _BackEdgeB;
+ return const_edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, dEdge);
+#endif
+}
+
+ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesBegin()
+{
+ return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
+}
+
+ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesEnd()
+{
+ return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.end());
+}
+
+ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesIterator(ViewEdge *iEdge)
+{
+ for (edge_pointers_container::iterator it = _sortedEdges.begin(), itend = _sortedEdges.end(); it != itend; it++) {
+ if ((*it)->first == iEdge)
+ return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), it);
+ }
+ return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
+}
+
+/**********************************/
+/* */
+/* */
+/* NonTVertex */
+/* */
+/* */
+/**********************************/
+
+void NonTVertex::AddOutgoingViewEdge(ViewEdge *iVEdge)
+{
+ // let's keep the viewedges ordered in CCW order in the 2D image plan
+ directedViewEdge idve(iVEdge, false);
+ if (!_ViewEdges.empty()) {
+ edges_container::iterator dve = _ViewEdges.begin(), dveend = _ViewEdges.end();
+ for (; (dve != dveend) && ViewEdgeComp(*dve, idve); ++dve);
+ _ViewEdges.insert(dve, idve);
+ }
+ else {
+ _ViewEdges.push_back(idve);
+ }
+}
+
+void NonTVertex::AddIncomingViewEdge(ViewEdge *iVEdge)
+{
+ // let's keep the viewedges ordered in CCW order in the 2D image plan
+ directedViewEdge idve(iVEdge, true);
+ if (!_ViewEdges.empty()) {
+ edges_container::iterator dve = _ViewEdges.begin(), dveend = _ViewEdges.end();
+ for (; (dve != dveend) && ViewEdgeComp(*dve, idve); ++dve);
+ _ViewEdges.insert(dve, idve);
+ }
+ else {
+ _ViewEdges.push_back(idve);
+ }
+}
+
+/*! iterators access */
+ViewVertex::edge_iterator NonTVertex::edges_begin()
+{
+ return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
+}
+
+ViewVertex::const_edge_iterator NonTVertex::edges_begin() const
+{
+ return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
+}
+
+ViewVertex::edge_iterator NonTVertex::edges_end()
+{
+ return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.end());
+}
+
+ViewVertex::const_edge_iterator NonTVertex::edges_end() const
+{
+ return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.end());
+}
+
+ViewVertex::edge_iterator NonTVertex::edges_iterator(ViewEdge *iEdge)
+{
+ for (edges_container::iterator it = _ViewEdges.begin(), itend = _ViewEdges.end(); it != itend; it++) {
+ if ((it)->first == iEdge)
+ return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), it);
+ }
+ return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
+}
+
+ViewVertex::const_edge_iterator NonTVertex::edges_iterator(ViewEdge *iEdge) const
+{
+ for (edges_container::const_iterator it = _ViewEdges.begin(), itend = _ViewEdges.end(); it != itend; it++) {
+ if ((it)->first == iEdge)
+ return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), it);
+ }
+ return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
+}
+
+ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesBegin()
+{
+ return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
+}
+
+ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesEnd()
+{
+ return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.end());
+}
+
+ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesIterator(ViewEdge *iEdge)
+{
+ for (edges_container::iterator it = _ViewEdges.begin(), itend = _ViewEdges.end(); it != itend; it++) {
+ if ((it)->first == iEdge)
+ return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), it);
+ }
+ return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
+}
+
+/**********************************/
+/* */
+/* */
+/* ViewEdge */
+/* */
+/* */
+/**********************************/
+
+real ViewEdge::getLength2D() const
+{
+ float length = 0.0f;
+ ViewEdge::const_fedge_iterator itlast = fedge_iterator_last();
+ ViewEdge::const_fedge_iterator it = fedge_iterator_begin(), itend = fedge_iterator_end();
+ Vec2r seg;
+ do {
+ seg = Vec2r((*it)->orientation2d()[0], (*it)->orientation2d()[1]);
+ length += seg.norm();
+ ++it;
+ } while ((it != itend) && (it != itlast));
+ return length;
+}
+
+//! view edge iterator
+ViewEdge::edge_iterator ViewEdge::ViewEdge_iterator()
+{
+ return edge_iterator(this);
+}
+
+ViewEdge::const_edge_iterator ViewEdge::ViewEdge_iterator() const
+{
+ return const_edge_iterator((ViewEdge *)this);
+}
+
+//! feature edge iterator
+ViewEdge::fedge_iterator ViewEdge::fedge_iterator_begin()
+{
+ return fedge_iterator(this->_FEdgeA, this->_FEdgeB);
+}
+
+ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_begin() const
+{
+ return const_fedge_iterator(this->_FEdgeA, this->_FEdgeB);
+}
+
+ViewEdge::fedge_iterator ViewEdge::fedge_iterator_last()
+{
+ return fedge_iterator(this->_FEdgeB, this->_FEdgeB);
+}
+
+ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_last() const
+{
+ return const_fedge_iterator(this->_FEdgeB, this->_FEdgeB);
+}
+
+ViewEdge::fedge_iterator ViewEdge::fedge_iterator_end()
+{
+ return fedge_iterator(0, this->_FEdgeB);
+}
+
+ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_end() const
+{
+ return const_fedge_iterator(0, this->_FEdgeB);
+}
+
+//! embedding vertex iterator
+ViewEdge::const_vertex_iterator ViewEdge::vertices_begin() const
+{
+ return const_vertex_iterator(this->_FEdgeA->vertexA(), 0, _FEdgeA);
+}
+
+ViewEdge::vertex_iterator ViewEdge::vertices_begin()
+{
+ return vertex_iterator(this->_FEdgeA->vertexA(), 0, _FEdgeA);
+}
+
+ViewEdge::const_vertex_iterator ViewEdge::vertices_last() const
+{
+ return const_vertex_iterator(this->_FEdgeB->vertexB(), _FEdgeB, 0);
+}
+
+ViewEdge::vertex_iterator ViewEdge::vertices_last()
+{
+ return vertex_iterator(this->_FEdgeB->vertexB(), _FEdgeB, 0);
+}
+
+ViewEdge::const_vertex_iterator ViewEdge::vertices_end() const
+{
+ return const_vertex_iterator(0, _FEdgeB, 0);
+}
+
+ViewEdge::vertex_iterator ViewEdge::vertices_end()
+{
+ return vertex_iterator(0, _FEdgeB, 0);
+}
+
+Interface0DIterator ViewEdge::verticesBegin()
+{
+ Interface0DIterator ret(new ViewEdgeInternal::SVertexIterator(this->_FEdgeA->vertexA(),
+ this->_FEdgeA->vertexA(), NULL, _FEdgeA, 0.0f));
+ return ret;
+}
+
+Interface0DIterator ViewEdge::verticesEnd()
+{
+ Interface0DIterator ret(new ViewEdgeInternal::SVertexIterator(NULL, this->_FEdgeA->vertexA(),
+ _FEdgeB, NULL, getLength2D()));
+ return ret;
+}
+
+Interface0DIterator ViewEdge::pointsBegin(float t)
+{
+ return verticesBegin();
+}
+
+Interface0DIterator ViewEdge::pointsEnd(float t)
+{
+ return verticesEnd();
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewShape */
+ /* */
+ /* */
+ /**********************************/
+
+ViewShape::~ViewShape()
+{
+ _Vertices.clear();
+
+ if (!(_Edges.empty())) {
+ for (vector<ViewEdge*>::iterator e = _Edges.begin(), eend = _Edges.end(); e != eend; e++) {
+ delete (*e);
+ }
+ _Edges.clear();
+ }
+
+ if (_SShape) {
+ delete _SShape;
+ _SShape = NULL;
+ }
+}
+
+void ViewShape::RemoveEdge(ViewEdge *iViewEdge)
+{
+ FEdge *fedge = iViewEdge->fedgeA();
+ for (vector<ViewEdge*>::iterator ve = _Edges.begin(), veend = _Edges.end(); ve != veend; ve++) {
+ if (iViewEdge == (*ve)) {
+ _Edges.erase(ve);
+ _SShape->RemoveEdge(fedge);
+ break;
+ }
+ }
+}
+
+void ViewShape::RemoveVertex(ViewVertex *iViewVertex)
+{
+ for (vector<ViewVertex*>::iterator vv = _Vertices.begin(), vvend = _Vertices.end(); vv != vvend; vv++) {
+ if (iViewVertex == (*vv)) {
+ _Vertices.erase(vv);
+ break;
+ }
+ }
+}
+
+/**********************************/
+/* */
+/* */
+/* ViewEdge */
+/* */
+/* */
+/**********************************/
+
+void ViewEdge::UpdateFEdges()
+{
+ FEdge *currentEdge = _FEdgeA;
+ do {
+ currentEdge->setViewEdge(this);
+ currentEdge = currentEdge->nextEdge();
+ } while ((currentEdge != NULL) && (currentEdge != _FEdgeB));
+ // last one
+ _FEdgeB->setViewEdge(this);
+}
diff --git a/source/blender/freestyle/intern/view_map/ViewMap.h b/source/blender/freestyle/intern/view_map/ViewMap.h
new file mode 100644
index 00000000000..1dce71051ee
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMap.h
@@ -0,0 +1,1779 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_VIEW_MAP_H__
+#define __FREESTYLE_VIEW_MAP_H__
+
+/** \file blender/freestyle/intern/view_map/ViewMap.h
+ * \ingroup freestyle
+ * \brief Classes to define a View Map (ViewVertex, ViewEdge, etc.)
+ * \author Stephane Grabli
+ * \date 03/09/2002
+ */
+
+#include <map>
+
+#include "Interface0D.h"
+#include "Interface1D.h"
+#include "Silhouette.h" // defines the embedding
+
+#include "../geometry/GeomUtils.h"
+
+#include "../system/BaseIterator.h"
+#include "../system/FreestyleConfig.h"
+
+/**********************************/
+/* */
+/* */
+/* ViewMap */
+/* */
+/* */
+/**********************************/
+
+
+/* Density
+ * Mean area depth value
+ * distance to a point
+ */
+
+class ViewVertex;
+class ViewEdge;
+class ViewShape;
+class TVertex;
+
+/*! Class defining the ViewMap.*/
+class LIB_VIEW_MAP_EXPORT ViewMap
+{
+public:
+ typedef vector<ViewEdge*> viewedges_container;
+ typedef vector<ViewVertex*> viewvertices_container;
+ typedef vector<ViewShape*> viewshapes_container;
+ typedef vector<SVertex*> svertices_container;
+ typedef vector<FEdge*> fedges_container;
+ typedef map<int, int> id_to_index_map;
+
+private:
+ static ViewMap *_pInstance;
+ viewshapes_container _VShapes; // view shapes
+ viewedges_container _VEdges; // view edges
+ viewvertices_container _VVertices; // view vertices
+ fedges_container _FEdges; // feature edges (embedded edges)
+ svertices_container _SVertices; // embedded vertices
+ BBox<Vec3r> _scene3DBBox;
+ // Mapping between the WShape or VShape id to the VShape index in the _VShapes vector. Used in the method
+ // viewShape(int id) to access a shape from its id.
+ id_to_index_map _shapeIdToIndex;
+
+public:
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void *userdata;
+
+ /*! Default constructor. */
+ ViewMap()
+ {
+ _pInstance = this;
+ userdata = NULL;
+ }
+
+ /*! Destructor. */
+ virtual ~ViewMap();
+
+ /*! Gets the viewedge the nearest to the 2D position specified as argument */
+ const ViewEdge *getClosestViewEdge(real x, real y) const;
+
+ /*! Gets the Fedge the nearest to the 2D position specified as argument */
+ const FEdge *getClosestFEdge(real x, real y) const;
+
+ /* accessors */
+ /*! The ViewMap is a singleton class. This static method returns the instance of the ViewMap. */
+ static inline ViewMap *getInstance()
+ {
+ return _pInstance;
+ }
+
+ /* Returns the list of ViewShapes of the scene. */
+ inline viewshapes_container& ViewShapes()
+ {
+ return _VShapes;
+ }
+
+ /* Returns the list of ViewEdges of the scene. */
+ inline viewedges_container& ViewEdges()
+ {
+ return _VEdges;
+ }
+
+ /* Returns the list of ViewVertices of the scene. */
+ inline viewvertices_container& ViewVertices()
+ {
+ return _VVertices;
+ }
+
+ /* Returns the list of FEdges of the scene. */
+ inline fedges_container& FEdges()
+ {
+ return _FEdges;
+ }
+
+ /* Returns the list of SVertices of the scene. */
+ inline svertices_container& SVertices()
+ {
+ return _SVertices;
+ }
+
+ /* Returns an iterator pointing onto the first ViewEdge of the list. */
+ inline viewedges_container::iterator viewedges_begin()
+ {
+ return _VEdges.begin();
+ }
+
+ inline viewedges_container::iterator viewedges_end()
+ {
+ return _VEdges.end();
+ }
+
+ inline int viewedges_size()
+ {
+ return _VEdges.size();
+ }
+
+ ViewShape *viewShape(unsigned index);
+
+ id_to_index_map& shapeIdToIndexMap()
+ {
+ return _shapeIdToIndex;
+ }
+
+ /*! Returns the scene 3D bounding box. */
+ inline BBox<Vec3r> getScene3dBBox() const
+ {
+ return _scene3DBBox;
+ }
+
+ /* modifiers */
+ void AddViewShape(ViewShape *iVShape);
+
+ inline void AddViewEdge(ViewEdge *iVEdge)
+ {
+ _VEdges.push_back(iVEdge);
+ }
+
+ inline void AddViewVertex(ViewVertex *iVVertex)
+ {
+ _VVertices.push_back(iVVertex);
+ }
+
+ inline void AddFEdge(FEdge *iFEdge)
+ {
+ _FEdges.push_back(iFEdge);
+ }
+
+ inline void AddSVertex(SVertex *iSVertex)
+ {
+ _SVertices.push_back(iSVertex);
+ }
+
+ /*! Sets the scene 3D bounding box. */
+ inline void setScene3dBBox(const BBox<Vec3r>& bbox)
+ {
+ _scene3DBBox = bbox;
+ }
+
+ /* Creates a T vertex in the view map.
+ * A T vertex is the intersection between 2 FEdges (before these ones are splitted).
+ * The TVertex is a 2D intersection but it corresponds to a 3D point on each of the 2 FEdges.
+ * iA3D
+ * The 3D coordinates of the point corresponding to the intersection on the first edge.
+ * iA2D
+ * The x,y,z 2D coordinates of the projection of iA3D
+ * iFEdgeA
+ * The first FEdge
+ * iB3D
+ * The 3D coordinates of the point corresponding to the intersection on the second edge.
+ * iB2D
+ * The x,y,z 2D coordinates of the projection of iB3D
+ * iFEdgeB
+ * The second FEdge
+ * id
+ * The id that must be given to that TVertex
+ */
+ TVertex *CreateTVertex(const Vec3r& iA3D, const Vec3r& iA2D, FEdge *iFEdgeA, const Vec3r& iB3D, const Vec3r& iB2D,
+ FEdge *iFEdgeB, const Id& id);
+
+ /* Updates the structures to take into account the fact that a SVertex must now be considered as a ViewVertex
+ * iVertex
+ * The SVertex on top of which the ViewVertex is built (it is necessarily a NonTVertex because it is a SVertex)
+ * newViewEdges
+ * The new ViewEdges that must be add to the ViewMap
+ */
+ ViewVertex *InsertViewVertex(SVertex *iVertex, vector<ViewEdge*>& newViewEdges);
+
+ /* connects a FEdge to the graph trough a SVertex */
+ //FEdge *Connect(FEdge *ioEdge, SVertex *ioVertex);
+};
+
+/**********************************/
+/* */
+/* */
+/* ViewVertex */
+/* */
+/* */
+/**********************************/
+
+class ViewEdge;
+class SShape;
+
+namespace ViewVertexInternal {
+
+class edge_const_traits;
+class edge_nonconst_traits;
+template<class Traits> class edge_iterator_base;
+class orientedViewEdgeIterator;
+
+} // end of namespace ViewEdgeInternal
+
+/*! Class to define a view vertex.
+ * A view vertex is a feature vertex corresponding to a point of the image graph, where the characteristics of an
+ * edge might change (nature, visibility, ...).
+ * A ViewVertex can be of two kinds: a TVertex when it corresponds to the intersection between two ViewEdges or a
+ * NonTVertex when it corresponds to a vertex of the initial input mesh (it is the case for vertices such as corners
+ * for example). Thus, this class can be specialized into two classes, the TVertex class and the NonTVertex class.
+ */
+class LIB_VIEW_MAP_EXPORT ViewVertex : public Interface0D
+{
+public: // Implementation of Interface0D
+ /*! Returns the string "ViewVertex". */
+ virtual string getExactTypeName() const
+ {
+ return "ViewVertex";
+ }
+
+public:
+ friend class ViewShape;
+ typedef pair<ViewEdge *, bool> directedViewEdge; // if bool = true, the ViewEdge is incoming
+
+ typedef vector<directedViewEdge> edges_container;
+
+ typedef ViewVertexInternal::edge_iterator_base<ViewVertexInternal::edge_nonconst_traits> edge_iterator;
+ typedef ViewVertexInternal::edge_iterator_base<ViewVertexInternal::edge_const_traits> const_edge_iterator;
+
+private:
+ Nature::VertexNature _Nature;
+
+public:
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void *userdata;
+
+ /*! Default constructor.*/
+ inline ViewVertex()
+ {
+ userdata = NULL;
+ _Nature = Nature::VIEW_VERTEX;
+ }
+
+ inline ViewVertex(Nature::VertexNature nature)
+ {
+ userdata = NULL;
+ _Nature = Nature::VIEW_VERTEX | nature;
+ }
+
+protected:
+ /*! Copy constructor. */
+ inline ViewVertex(ViewVertex& iBrother)
+ {
+ _Nature = iBrother._Nature;
+ iBrother.userdata = this;
+ userdata = NULL;
+ }
+
+ /*! Cloning method. */
+ virtual ViewVertex *duplicate() = 0;
+
+public:
+ /*! Destructor. */
+ virtual ~ViewVertex() {}
+
+ /* accessors */
+ /*! Returns the nature of the vertex .*/
+ virtual Nature::VertexNature getNature() const
+ {
+ return _Nature;
+ }
+
+ /* modifiers */
+ /*! Sets the nature of the vertex. */
+ inline void setNature(Nature::VertexNature iNature)
+ {
+ _Nature = iNature;
+ }
+
+ /* Replaces old edge by new edge */
+ virtual void Replace(ViewEdge *, ViewEdge *) {}
+
+public:
+ /* iterators access */
+ // allows iteration on the edges that comes from/goes to this vertex in CCW order (order defined in 2D in the
+ // image plan)
+ virtual edge_iterator edges_begin() = 0;
+ virtual const_edge_iterator edges_begin() const = 0;
+ virtual edge_iterator edges_end() = 0;
+ virtual const_edge_iterator edges_end() const = 0;
+ virtual edge_iterator edges_iterator(ViewEdge *iEdge) = 0;
+ virtual const_edge_iterator edges_iterator(ViewEdge *iEdge) const = 0;
+
+ // Iterator access
+ /*! Returns an iterator over the ViewEdges that goes to or comes from this ViewVertex pointing to the first
+ * ViewEdge of the list. The orientedViewEdgeIterator allows to iterate in CCW order over these ViewEdges
+ * and to get the orientation for each ViewEdge (incoming/outgoing).
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesBegin() = 0;
+
+ /*! Returns an orientedViewEdgeIterator over the ViewEdges around this ViewVertex, pointing after the last ViewEdge.
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesEnd() = 0;
+
+ /*! Returns an orientedViewEdgeIterator pointing to the ViewEdge given as argument. */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge) = 0;
+};
+
+/**********************************/
+/* */
+/* */
+/* TVertex */
+/* */
+/* */
+/**********************************/
+
+/*! class to define a T vertex, i.e. an intersection between two edges.
+ * It points towards 2 SVertex and 4 View edges.
+ * Among these ViewEdges, 2 are front and 2 are back.
+ * Basically the front edge hides part of the back edge.
+ * So, among the back edges, 1 is of invisibility n and the other of visibility n+1
+ */
+class LIB_VIEW_MAP_EXPORT TVertex : public ViewVertex
+{
+public:
+ typedef vector<directedViewEdge*> edge_pointers_container;
+
+public: // Implementation of Interface0D
+ /*! Returns the string "TVertex". */
+ virtual string getExactTypeName() const
+ {
+ return "TVertex";
+ }
+
+ // Data access methods
+ /* Returns the 3D x coordinate of the vertex. Ambiguous in this case. */
+ virtual real getX() const
+ {
+ cerr << "Warning: getX() undefined for this point" << endl;
+ return _FrontSVertex->point3D().x();
+ }
+
+ virtual real getY() const
+ {
+ cerr << "Warning: getX() undefined for this point" << endl;
+ return _FrontSVertex->point3D().y();
+ }
+
+ virtual real getZ() const
+ {
+ cerr << "Warning: getX() undefined for this point" << endl;
+ return _FrontSVertex->point3D().z();
+ }
+
+ /*! Returns the 3D point. */
+ virtual Vec3f getPoint3D() const
+ {
+ cerr << "Warning: getPoint3D() undefined for this point" << endl;
+ return _FrontSVertex->getPoint3D();
+ }
+
+ /*! Returns the projected 3D x coordinate of the vertex. */
+ virtual real getProjectedX() const
+ {
+ return _FrontSVertex->point2D().x();
+ }
+
+ /*! Returns the projected 3D y coordinate of the vertex. */
+ virtual real getProjectedY() const
+ {
+ return _FrontSVertex->point2D().y();
+ }
+
+ virtual real getProjectedZ() const
+ {
+ return _FrontSVertex->point2D().z();
+ }
+
+ /*! Returns the 2D point. */
+ virtual Vec2f getPoint2D() const
+ {
+ return _FrontSVertex->getPoint2D();
+ }
+
+ /*! Returns the Id of the TVertex. */
+ virtual Id getId() const
+ {
+ return _Id;
+ }
+
+ /*! Cast the Interface0D in SVertex if it can be. */
+ // it can't
+ virtual ViewVertex *castToViewVertex()
+ {
+ return this;
+ }
+
+ /*! Cast the Interface0D in TVertex if it can be. */
+ virtual TVertex *castToTVertex()
+ {
+ return this;
+ }
+
+private:
+ SVertex *_FrontSVertex;
+ SVertex *_BackSVertex;
+ directedViewEdge _FrontEdgeA;
+ directedViewEdge _FrontEdgeB;
+ directedViewEdge _BackEdgeA;
+ directedViewEdge _BackEdgeB;
+ Id _Id; // id to identify t vertices . these id will be negative in order not to be mixed with NonTVertex ids.
+ edge_pointers_container _sortedEdges; // the list of the four ViewEdges, ordered in CCW order (in the image plan)
+
+public:
+ /*! Default constructor.*/
+ inline TVertex() : ViewVertex(Nature::T_VERTEX)
+ {
+ _FrontSVertex = NULL;
+ _BackSVertex = NULL;
+ _FrontEdgeA.first = 0;
+ _FrontEdgeB.first = 0;
+ _BackEdgeA.first = 0;
+ _BackEdgeB.first = 0;
+ }
+
+ inline TVertex(SVertex *svFront, SVertex *svBack) : ViewVertex(Nature::T_VERTEX)
+ {
+ _FrontSVertex = svFront;
+ _BackSVertex = svBack;
+ _FrontEdgeA.first = 0;
+ _FrontEdgeB.first = 0;
+ _BackEdgeA.first = 0;
+ _BackEdgeB.first = 0;
+ svFront->setViewVertex(this);
+ svBack->setViewVertex(this);
+ }
+
+protected:
+ /*! Copy constructor. */
+ inline TVertex(TVertex& iBrother) : ViewVertex(iBrother)
+ {
+ _FrontSVertex = iBrother._FrontSVertex;
+ _BackSVertex = iBrother._BackSVertex;
+ _FrontEdgeA = iBrother._FrontEdgeA;
+ _FrontEdgeB = iBrother._FrontEdgeB;
+ _BackEdgeA = iBrother._BackEdgeA;
+ _BackEdgeB = iBrother._BackEdgeB;
+ _sortedEdges = iBrother._sortedEdges;
+ }
+
+ /*! Cloning method. */
+ virtual ViewVertex *duplicate()
+ {
+ TVertex *clone = new TVertex(*this);
+ return clone;
+ }
+
+public:
+ /* accessors */
+ /*! Returns the SVertex that is closer to the viewpoint. */
+ inline SVertex *frontSVertex()
+ {
+ return _FrontSVertex;
+ }
+
+ /*! Returns the SVertex that is further away from the viewpoint. */
+ inline SVertex *backSVertex()
+ {
+ return _BackSVertex;
+ }
+
+ inline directedViewEdge& frontEdgeA()
+ {
+ return _FrontEdgeA;
+ }
+
+ inline directedViewEdge& frontEdgeB()
+ {
+ return _FrontEdgeB;
+ }
+
+ inline directedViewEdge& backEdgeA()
+ {
+ return _BackEdgeA;
+ }
+
+ inline directedViewEdge& backEdgeB()
+ {
+ return _BackEdgeB;
+ }
+
+ /* modifiers */
+ /*! Sets the SVertex that is closer to the viewpoint. */
+ inline void setFrontSVertex(SVertex *iFrontSVertex)
+ {
+ _FrontSVertex = iFrontSVertex;
+ _FrontSVertex->setViewVertex(this);
+ }
+
+ /*! Sets the SVertex that is further away from the viewpoint. */
+ inline void setBackSVertex(SVertex *iBackSVertex)
+ {
+ _BackSVertex = iBackSVertex;
+ _BackSVertex->setViewVertex(this);
+ }
+
+ void setFrontEdgeA(ViewEdge *iFrontEdgeA, bool incoming = true);
+ void setFrontEdgeB(ViewEdge *iFrontEdgeB, bool incoming = true);
+ void setBackEdgeA(ViewEdge *iBackEdgeA, bool incoming = true);
+ void setBackEdgeB(ViewEdge *iBackEdgeB, bool incoming = true);
+
+ /*! Sets the Id. */
+ inline void setId(const Id& iId)
+ {
+ _Id = iId;
+ }
+
+ /*! Returns the SVertex (among the 2) belonging to the FEdge iFEdge */
+ inline SVertex *getSVertex(FEdge *iFEdge)
+ {
+ const vector<FEdge*>& vfEdges = _FrontSVertex->fedges();
+ vector<FEdge*>::const_iterator fe, fend;
+ for (fe = vfEdges.begin(), fend = vfEdges.end(); fe != fend; fe++) {
+ if ((*fe) == iFEdge)
+ return _FrontSVertex;
+ }
+
+ const vector<FEdge*>& vbEdges = _BackSVertex->fedges();
+ for (fe = vbEdges.begin(), fend = vbEdges.end(); fe != fend; fe++) {
+ if ((*fe) == iFEdge)
+ return _BackSVertex;
+ }
+ return NULL;
+ }
+
+ virtual void Replace(ViewEdge *iOld, ViewEdge *iNew);
+
+ /*! returns the mate edge of iEdgeA.
+ * For example, if iEdgeA is frontEdgeA, then frontEdgeB is returned. If iEdgeA is frontEdgeB then frontEdgeA
+ * is returned. Same for back edges
+ */
+ virtual ViewEdge *mate(ViewEdge *iEdgeA)
+ {
+ if (iEdgeA == _FrontEdgeA.first)
+ return _FrontEdgeB.first;
+ if (iEdgeA == _FrontEdgeB.first)
+ return _FrontEdgeA.first;
+ if (iEdgeA == _BackEdgeA.first)
+ return _BackEdgeB.first;
+ if (iEdgeA == _BackEdgeB.first)
+ return _BackEdgeA.first;
+ return NULL;
+ }
+
+ /* iterators access */
+ virtual edge_iterator edges_begin();
+ virtual const_edge_iterator edges_begin() const;
+ virtual edge_iterator edges_end();
+ virtual const_edge_iterator edges_end() const;
+ virtual edge_iterator edges_iterator(ViewEdge *iEdge);
+ virtual const_edge_iterator edges_iterator(ViewEdge *iEdge) const;
+
+ /*! Returns an iterator over the ViewEdges that goes to or comes from this ViewVertex pointing to the first
+ * ViewEdge of the list. The orientedViewEdgeIterator allows to iterate in CCW order over these ViewEdges
+ * and to get the orientation for each ViewEdge (incoming/outgoing).
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesBegin();
+
+ /*! Returns an orientedViewEdgeIterator over the ViewEdges around this ViewVertex, pointing after the last ViewEdge.
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesEnd();
+
+ /*! Returns an orientedViewEdgeIterator pointing to the ViewEdge given as argument. */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge);
+};
+
+
+/**********************************/
+/* */
+/* */
+/* NonTVertex */
+/* */
+/* */
+/**********************************/
+
+
+// (non T vertex)
+/*! View vertex for corners, cusps, etc...
+ * Associated to a single SVertex.
+ * Can be associated to 2 or several view edges
+ */
+class LIB_VIEW_MAP_EXPORT NonTVertex : public ViewVertex
+{
+public:
+ typedef vector<directedViewEdge> edges_container;
+
+public: // Implementation of Interface0D
+ /*! Returns the string "ViewVertex". */
+ virtual string getExactTypeName() const
+ {
+ return "NonTVertex";
+ }
+
+ // Data access methods
+ /*! Returns the 3D x coordinate of the vertex. */
+ virtual real getX() const
+ {
+ return _SVertex->point3D().x();
+ }
+
+ /*! Returns the 3D y coordinate of the vertex. */
+ virtual real getY() const
+ {
+ return _SVertex->point3D().y();
+ }
+
+ /*! Returns the 3D z coordinate of the vertex. */
+ virtual real getZ() const
+ {
+ return _SVertex->point3D().z();
+ }
+
+ /*! Returns the 3D point. */
+ virtual Vec3f getPoint3D() const
+ {
+ return _SVertex->getPoint3D();
+ }
+
+ /*! Returns the projected 3D x coordinate of the vertex. */
+ virtual real getProjectedX() const
+ {
+ return _SVertex->point2D().x();
+ }
+
+ /*! Returns the projected 3D y coordinate of the vertex. */
+ virtual real getProjectedY() const
+ {
+ return _SVertex->point2D().y();
+ }
+
+ /*! Returns the projected 3D z coordinate of the vertex. */
+ virtual real getProjectedZ() const
+ {
+ return _SVertex->point2D().z();
+ }
+
+ /*! Returns the 2D point. */
+ virtual Vec2f getPoint2D() const
+ {
+ return _SVertex->getPoint2D();
+ }
+
+ /*! Returns the Id of the vertex. */
+ virtual Id getId() const
+ {
+ return _SVertex->getId();
+ }
+
+ /*! Cast the Interface0D in SVertex if it can be. */
+ virtual SVertex *castToSVertex()
+ {
+ return _SVertex;
+ }
+
+ /*! Cast the Interface0D in ViewVertex if it can be. */
+ virtual ViewVertex *castToViewVertex()
+ {
+ return this;
+ }
+
+ /*! Cast the Interface0D in NonTVertex if it can be. */
+ virtual NonTVertex *castToNonTVertex()
+ {
+ return this;
+ }
+
+private:
+ SVertex *_SVertex;
+ edges_container _ViewEdges;
+
+public:
+ /*! Default constructor.*/
+ inline NonTVertex() : ViewVertex(Nature::NON_T_VERTEX)
+ {
+ _SVertex = NULL;
+ }
+
+ /*! Builds a NonTVertex from a SVertex. */
+ inline NonTVertex(SVertex *iSVertex) : ViewVertex(Nature::NON_T_VERTEX)
+ {
+ _SVertex = iSVertex;
+ _SVertex->setViewVertex(this);
+ }
+
+protected:
+ /*! Copy constructor. */
+ inline NonTVertex(NonTVertex& iBrother) : ViewVertex(iBrother)
+ {
+ _SVertex = iBrother._SVertex;
+ _SVertex->setViewVertex(this);
+ _ViewEdges = iBrother._ViewEdges;
+ }
+
+ /*! Cloning method. */
+ virtual ViewVertex *duplicate()
+ {
+ NonTVertex *clone = new NonTVertex(*this);
+ return clone;
+ }
+
+public:
+ /*! destructor. */
+ virtual ~NonTVertex() {}
+
+ /* accessors */
+ /*! Returns the SVertex on top of which this NonTVertex is built. */
+ inline SVertex *svertex()
+ {
+ return _SVertex;
+ }
+
+ inline edges_container& viewedges()
+ {
+ return _ViewEdges;
+ }
+
+ /* modifiers */
+ /*! Sets the SVertex on top of which this NonTVertex is built. */
+ inline void setSVertex(SVertex *iSVertex)
+ {
+ _SVertex = iSVertex;
+ _SVertex->setViewVertex(this);
+ }
+
+ inline void setViewEdges(const vector<directedViewEdge>& iViewEdges)
+ {
+ _ViewEdges = iViewEdges;
+ }
+
+ void AddIncomingViewEdge(ViewEdge *iVEdge);
+ void AddOutgoingViewEdge(ViewEdge *iVEdge);
+
+ inline void AddViewEdge(ViewEdge *iVEdge, bool incoming = true)
+ {
+ if (incoming)
+ AddIncomingViewEdge(iVEdge);
+ else
+ AddOutgoingViewEdge(iVEdge);
+ }
+
+ /* Replaces old edge by new edge */
+ virtual void Replace(ViewEdge *iOld, ViewEdge *iNew)
+ {
+ edges_container::iterator insertedve;
+ for (edges_container::iterator ve = _ViewEdges.begin(), vend = _ViewEdges.end(); ve != vend; ve++) {
+ if ((ve)->first == iOld) {
+ insertedve = _ViewEdges.insert(ve, directedViewEdge(iNew, ve->second));// inserts e2 before ve.
+ // returns an iterator pointing toward e2. ve is invalidated.
+ // we want to remove e1, but we can't use ve anymore:
+ insertedve++; // insertedve points now to e1
+ _ViewEdges.erase(insertedve);
+ return;
+ }
+ }
+ }
+
+ /* iterators access */
+ virtual edge_iterator edges_begin();
+ virtual const_edge_iterator edges_begin() const;
+ virtual edge_iterator edges_end();
+ virtual const_edge_iterator edges_end() const;
+ virtual edge_iterator edges_iterator(ViewEdge *iEdge);
+ virtual const_edge_iterator edges_iterator(ViewEdge *iEdge) const;
+
+ /*! Returns an iterator over the ViewEdges that goes to or comes from this ViewVertex pointing to the first
+ * ViewEdge of the list. The orientedViewEdgeIterator allows to iterate in CCW order over these ViewEdges
+ * and to get the orientation for each ViewEdge (incoming/outgoing).
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesBegin();
+
+ /*! Returns an orientedViewEdgeIterator over the ViewEdges around this ViewVertex, pointing after the last ViewEdge.
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesEnd();
+
+ /*! Returns an orientedViewEdgeIterator pointing to the ViewEdge given as argument. */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge);
+};
+
+/**********************************/
+/* */
+/* */
+/* ViewEdge */
+/* */
+/* */
+/**********************************/
+
+/* Geometry(normals...)
+ * Nature of edges
+ * 2D spaces (1or2, material, z...)
+ * Parent Shape
+ * 3D Shading, material
+ * Importance
+ * Occluders
+ */
+class ViewShape;
+
+namespace ViewEdgeInternal {
+
+template<class Traits> class edge_iterator_base;
+template<class Traits> class fedge_iterator_base;
+template<class Traits> class vertex_iterator_base;
+
+} // end of namespace ViewEdgeInternal
+
+/*! Class defining a ViewEdge. A ViewEdge in an edge of the image graph. it connnects two ViewVertex.
+ * It is made by connecting a set of FEdges.
+ */
+class LIB_VIEW_MAP_EXPORT ViewEdge : public Interface1D
+{
+public: // Implementation of Interface0D
+ /*! Returns the string "ViewEdge". */
+ virtual string getExactTypeName() const
+ {
+ return "ViewEdge";
+ }
+
+ // Data access methods
+ /*! Returns the Id of the vertex. */
+ virtual Id getId() const
+ {
+ return _Id;
+ }
+
+ /*! Returns the nature of the ViewEdge. */
+ virtual Nature::EdgeNature getNature() const
+ {
+ return _Nature;
+ }
+
+public:
+ typedef SVertex vertex_type;
+ friend class ViewShape;
+ // for ViewEdge iterator
+ typedef ViewEdgeInternal::edge_iterator_base<Nonconst_traits<ViewEdge*> > edge_iterator;
+ typedef ViewEdgeInternal::edge_iterator_base<Const_traits<ViewEdge*> > const_edge_iterator;
+ // for fedge iterator
+ typedef ViewEdgeInternal::fedge_iterator_base<Nonconst_traits<FEdge*> > fedge_iterator;
+ typedef ViewEdgeInternal::fedge_iterator_base<Const_traits<FEdge*> > const_fedge_iterator;
+ // for svertex iterator
+ typedef ViewEdgeInternal::vertex_iterator_base<Nonconst_traits<SVertex*> > vertex_iterator;
+ typedef ViewEdgeInternal::vertex_iterator_base<Const_traits<SVertex*> > const_vertex_iterator;
+
+private:
+ ViewVertex *__A; // edge starting vertex
+ ViewVertex *__B; // edge ending vertex
+ Nature::EdgeNature _Nature; // nature of view edge
+ ViewShape *_Shape; // shape to which the view edge belongs
+ FEdge *_FEdgeA; // first edge of the embedded fedges chain
+ FEdge *_FEdgeB; // last edge of the embedded fedges chain
+ Id _Id;
+ unsigned _ChainingTimeStamp;
+ // The silhouette view edge separates 2 2D spaces. The one on the left is necessarly the Shape _Shape (the one to
+ // which this edge belongs to) and _aShape is the one on its right
+ // NOT HANDLED BY THE COPY CONSTRUCTOR
+ ViewShape *_aShape;
+ int _qi;
+ vector<ViewShape*> _Occluders;
+ bool _isInImage;
+
+ // tmp
+ Id *_splittingId;
+
+public:
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void *userdata;
+
+ /*! Default constructor. */
+ inline ViewEdge()
+ {
+ __A = NULL;
+ __B = NULL;
+ _FEdgeA = NULL;
+ _FEdgeB = NULL;
+ _ChainingTimeStamp = 0;
+ _qi = 0;
+ _aShape = NULL;
+ userdata = NULL;
+ _splittingId = NULL;
+ _isInImage = true;
+ }
+
+ inline ViewEdge(ViewVertex *iA, ViewVertex *iB)
+ {
+ __A = iA;
+ __B = iB;
+ _FEdgeA = NULL;
+ _FEdgeB = NULL;
+ _Shape = 0;
+ _ChainingTimeStamp = 0;
+ _qi = 0;
+ _aShape = NULL;
+ userdata = NULL;
+ _splittingId = NULL;
+ _isInImage = true;
+ }
+
+ inline ViewEdge(ViewVertex *iA, ViewVertex *iB, FEdge *iFEdgeA)
+ {
+ __A = iA;
+ __B = iB;
+ _FEdgeA = iFEdgeA;
+ _FEdgeB = NULL;
+ _Shape = NULL;
+ _ChainingTimeStamp = 0;
+ _qi = 0;
+ _aShape = NULL;
+ userdata = NULL;
+ _splittingId = NULL;
+ _isInImage = true;
+ }
+
+ inline ViewEdge(ViewVertex *iA, ViewVertex *iB, FEdge *iFEdgeA, FEdge *iFEdgeB, ViewShape *iShape)
+ {
+ __A = iA;
+ __B = iB;
+ _FEdgeA = iFEdgeA;
+ _FEdgeB = iFEdgeB;
+ _Shape = iShape;
+ _ChainingTimeStamp = 0;
+ _qi = 0;
+ _aShape = NULL;
+ userdata = NULL;
+ _splittingId = NULL;
+ _isInImage = true;
+ UpdateFEdges(); // tells every FEdge between iFEdgeA and iFEdgeB that this is theit ViewEdge
+ }
+
+//soc protected:
+ /*! Copy constructor. */
+ inline ViewEdge(ViewEdge& iBrother)
+ {
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _FEdgeA = iBrother._FEdgeA;
+ _FEdgeB = iBrother._FEdgeB;
+ _Nature = iBrother._Nature;
+ _Shape = NULL;
+ _Id = iBrother._Id;
+ _ChainingTimeStamp = iBrother._ChainingTimeStamp;
+ _aShape = iBrother._aShape;
+ _qi = iBrother._qi;
+ _splittingId = NULL;
+ _isInImage = iBrother._isInImage;
+ iBrother.userdata = this;
+ userdata = NULL;
+ }
+
+ /*! Cloning method. */
+ virtual ViewEdge *duplicate()
+ {
+ ViewEdge *clone = new ViewEdge(*this);
+ return clone;
+ }
+
+public:
+ /*! Destructor. */
+ virtual ~ViewEdge()
+ {
+#if 0
+ if (_aFace) {
+ delete _aFace;
+ _aFace = NULL;
+ }
+#endif
+ // only the last splitted deletes this id
+ if (_splittingId) {
+ if (*_splittingId == _Id)
+ delete _splittingId;
+ }
+ }
+
+ /* accessors */
+ /*! Returns the first ViewVertex. */
+ inline ViewVertex *A()
+ {
+ return __A;
+ }
+
+ /*! Returns the second ViewVertex. */
+ inline ViewVertex *B()
+ {
+ return __B;
+ }
+
+ /*! Returns the first FEdge that constitues this ViewEdge. */
+ inline FEdge *fedgeA()
+ {
+ return _FEdgeA;
+ }
+
+ /*! Returns the last FEdge that constitues this ViewEdge. */
+ inline FEdge *fedgeB()
+ {
+ return _FEdgeB;
+ }
+
+ /*! Returns the ViewShape to which this ViewEdge belongs to .*/
+ inline ViewShape *viewShape()
+ {
+ return _Shape;
+ }
+
+ /*! Returns the shape that is occluded by the ViewShape to which this ViewEdge belongs to. If no object is occluded,
+ * NULL is returned.
+ * \return The occluded ViewShape.
+ */
+ inline ViewShape *aShape()
+ {
+ return _aShape;
+ }
+
+ /*! Tells whether this ViewEdge forms a closed loop or not. */
+ inline bool isClosed()
+ {
+ if (!__B)
+ return true;
+ return false;
+ }
+
+ /*! Returns the time stamp of this ViewEdge. */
+ inline unsigned getChainingTimeStamp()
+ {
+ return _ChainingTimeStamp;
+ }
+
+ inline const ViewShape *aShape() const
+ {
+ return _aShape;
+ }
+
+ inline const ViewShape *bShape() const
+ {
+ return _Shape;
+ }
+
+ inline vector<ViewShape*>& occluders()
+ {
+ return _Occluders;
+ }
+
+ inline Id *splittingId()
+ {
+ return _splittingId;
+ }
+
+ inline bool isInImage() const
+ {
+ return _isInImage;
+ }
+
+ /* modifiers */
+ /*! Sets the first ViewVertex of the ViewEdge. */
+ inline void setA(ViewVertex *iA)
+ {
+ __A = iA;
+ }
+
+ /*! Sets the last ViewVertex of the ViewEdge. */
+ inline void setB(ViewVertex *iB)
+ {
+ __B = iB;
+ }
+
+ /*! Sets the nature of the ViewEdge. */
+ inline void setNature(Nature::EdgeNature iNature)
+ {
+ _Nature = iNature;
+ }
+
+ /*! Sets the first FEdge of the ViewEdge. */
+ inline void setFEdgeA(FEdge *iFEdge)
+ {
+ _FEdgeA = iFEdge;
+ }
+
+ /*! Sets the last FEdge of the ViewEdge. */
+ inline void setFEdgeB(FEdge *iFEdge)
+ {
+ _FEdgeB = iFEdge;
+ }
+
+ /*! Sets the ViewShape to which this ViewEdge belongs to.*/
+ inline void setShape(ViewShape *iVShape)
+ {
+ _Shape = iVShape;
+ }
+
+ /*! Sets the ViewEdge id. */
+ inline void setId(const Id& id)
+ {
+ _Id = id;
+ }
+
+ /*! Sets Viewedge to this for all embedded fedges */
+ void UpdateFEdges();
+
+ /*! Sets the occluded ViewShape */
+ inline void setaShape(ViewShape *iShape)
+ {
+ _aShape = iShape;
+ }
+
+ /*! Sets the quantitative invisibility value. */
+ inline void setQI(int qi)
+ {
+ _qi = qi;
+ }
+
+ /*! Sets the time stamp value. */
+ inline void setChainingTimeStamp(unsigned ts)
+ {
+ _ChainingTimeStamp = ts;
+ }
+
+ inline void AddOccluder(ViewShape *iShape)
+ {
+ _Occluders.push_back(iShape);
+ }
+
+ inline void setSplittingId(Id *id)
+ {
+ _splittingId = id;
+ }
+
+ inline void setIsInImage(bool iFlag)
+ {
+ _isInImage = iFlag;
+ }
+
+ /* stroke interface definition */
+ inline bool intersect_2d_area(const Vec2r& iMin, const Vec2r& iMax) const
+ {
+ // parse edges to check if one of them is intersection the region:
+ FEdge *current = _FEdgeA;
+ do {
+ if (GeomUtils::intersect2dSeg2dArea(iMin, iMax,
+ Vec2r(current->vertexA()->point2D()[0],
+ current->vertexA()->point2D()[1]),
+ Vec2r(current->vertexB()->point2D()[0],
+ current->vertexB()->point2D()[1])))
+ {
+ return true;
+ }
+ current = current->nextEdge();
+ } while ((current != 0) && (current != _FEdgeA));
+
+ return false;
+ }
+
+ inline bool include_in_2d_area(const Vec2r& iMin, const Vec2r& iMax) const
+ {
+ // parse edges to check if all of them are intersection the region:
+ FEdge *current = _FEdgeA;
+
+ do {
+ if (!GeomUtils::include2dSeg2dArea(iMin, iMax,
+ Vec2r(current->vertexA()->point2D()[0],
+ current->vertexA()->point2D()[1]),
+ Vec2r(current->vertexB()->point2D()[0],
+ current->vertexB()->point2D()[1])))
+ {
+ return false;
+ }
+ current = current->nextEdge();
+ } while ((current != 0) && (current != _FEdgeA));
+
+ return true;
+ }
+
+ /* Information access interface */
+
+#if 0
+ inline Nature::EdgeNature viewedge_nature() const
+ {
+ return getNature();
+ }
+
+ float viewedge_length() const;
+#endif
+
+ /*! Returns the 2D length of the Viewedge. */
+ real getLength2D() const;
+
+#if 0
+ inline Material material() const
+ {
+ return _FEdgeA->vertexA()->shape()->material();
+ }
+#endif
+
+ inline int qi() const
+ {
+ return _qi;
+ }
+
+ inline occluder_container::const_iterator occluders_begin() const
+ {
+ return _Occluders.begin();
+ }
+
+ inline occluder_container::const_iterator occluders_end() const
+ {
+ return _Occluders.end();
+ }
+
+ inline int occluders_size() const
+ {
+ return _Occluders.size();
+ }
+
+ inline bool occluders_empty() const
+ {
+ return _Occluders.empty();
+ }
+
+ inline const Polygon3r& occludee() const
+ {
+ return (_FEdgeA->aFace());
+ }
+
+ inline const SShape *occluded_shape() const;
+
+ inline const bool occludee_empty() const
+ {
+ if (_aShape == 0)
+ return true;
+ return false;
+ }
+
+ //inline real z_discontinuity(int iCombination = 0) const;
+
+ inline Id shape_id() const
+ {
+ return _FEdgeA->vertexA()->shape()->getId();
+ }
+
+ inline const SShape *shape() const
+ {
+ return _FEdgeA->vertexA()->shape();
+ }
+
+ inline float shape_importance() const
+ {
+ return _FEdgeA->shape_importance();
+ }
+
+ /* iterators access */
+ // view edge iterator
+ edge_iterator ViewEdge_iterator();
+ const_edge_iterator ViewEdge_iterator() const;
+ // feature edge iterator
+ fedge_iterator fedge_iterator_begin();
+ const_fedge_iterator fedge_iterator_begin() const;
+ fedge_iterator fedge_iterator_last();
+ const_fedge_iterator fedge_iterator_last() const;
+ fedge_iterator fedge_iterator_end();
+ const_fedge_iterator fedge_iterator_end() const;
+ // embedding vertex iterator
+ const_vertex_iterator vertices_begin() const;
+ vertex_iterator vertices_begin();
+ const_vertex_iterator vertices_last() const;
+ vertex_iterator vertices_last();
+ const_vertex_iterator vertices_end() const;
+ vertex_iterator vertices_end();
+
+ // Iterator access (Interface1D)
+ /*! Returns an Interface0DIterator to iterate over the SVertex constituing the embedding of this ViewEdge.
+ * The returned Interface0DIterator points to the first SVertex of the ViewEdge.
+ */
+ virtual Interface0DIterator verticesBegin();
+
+ /*! Returns an Interface0DIterator to iterate over the SVertex constituing the embedding of this ViewEdge.
+ * The returned Interface0DIterator points after the last SVertex of the ViewEdge.
+ */
+ virtual Interface0DIterator verticesEnd();
+
+ /*! Returns an Interface0DIterator to iterate over the points of this ViewEdge at a given resolution.
+ * The returned Interface0DIterator points on the first Point of the ViewEdge.
+ * \param t
+ * the sampling value.
+ */
+ virtual Interface0DIterator pointsBegin(float t = 0.0f);
+
+ /*! Returns an Interface0DIterator to iterate over the points of this ViewEdge at a given resolution.
+ * The returned Interface0DIterator points after the last Point of the ViewEdge.
+ * \param t
+ * the sampling value.
+ */
+ virtual Interface0DIterator pointsEnd(float t = 0.0f);
+};
+
+
+/**********************************/
+/* */
+/* */
+/* ViewShape */
+/* */
+/* */
+/**********************************/
+
+/*! Class gathering the elements of the ViewMap (ViewVertex, ViewEdge) that are issued from the same input shape. */
+class LIB_VIEW_MAP_EXPORT ViewShape
+{
+private:
+ vector<ViewVertex*> _Vertices;
+ vector<ViewEdge*> _Edges;
+ SShape *_SShape;
+
+public:
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void *userdata;
+
+ /*! Default constructor.*/
+ inline ViewShape()
+ {
+ userdata = NULL;
+ _SShape = NULL;
+ }
+
+ /*! Builds a ViewShape from a SShape. */
+ inline ViewShape(SShape *iSShape)
+ {
+ userdata = NULL;
+ _SShape = iSShape;
+ //_SShape->setViewShape(this);
+ }
+
+ /*! Copy constructor. */
+ inline ViewShape(ViewShape& iBrother)
+ {
+ userdata = NULL;
+ vector<ViewVertex *>::iterator vv, vvend;
+ vector<ViewEdge *>::iterator ve, veend;
+
+ _SShape = iBrother._SShape;
+
+ vector<ViewVertex*>& vvertices = iBrother.vertices();
+ // duplicate vertices
+ for (vv = vvertices.begin(), vvend = vvertices.end(); vv != vvend; vv++) {
+ ViewVertex *newVertex = (*vv)->duplicate();
+ AddVertex(newVertex);
+ }
+
+ vector<ViewEdge*>& vvedges = iBrother.edges();
+ // duplicate edges
+ for (ve = vvedges.begin(), veend = vvedges.end(); ve != veend; ve++) {
+ ViewEdge *newEdge = (*ve)->duplicate();
+ AddEdge(newEdge); // here the shape is set as the edge's shape
+ }
+
+ //-------------------------
+ // remap edges in vertices:
+ //-------------------------
+ for (vv = _Vertices.begin(), vvend = _Vertices.end(); vv != vvend; vv++) {
+ switch ((*vv)->getNature()) {
+ case Nature::T_VERTEX:
+ {
+ TVertex *v = (TVertex *)(*vv);
+ ViewEdge *veFrontA = (ViewEdge *)(v)->frontEdgeA().first->userdata;
+ ViewEdge *veFrontB = (ViewEdge *)(v)->frontEdgeB().first->userdata;
+ ViewEdge *veBackA = (ViewEdge *)(v)->backEdgeA().first->userdata;
+ ViewEdge *veBackB = (ViewEdge *)(v)->backEdgeB().first->userdata;
+
+ v->setFrontEdgeA(veFrontA, v->frontEdgeA().second);
+ v->setFrontEdgeB(veFrontB, v->frontEdgeB().second);
+ v->setBackEdgeA(veBackA, v->backEdgeA().second);
+ v->setBackEdgeB(veBackB, v->backEdgeB().second);
+ }
+ break;
+ case Nature::NON_T_VERTEX:
+ {
+ NonTVertex *v = (NonTVertex *)(*vv);
+ vector<ViewVertex::directedViewEdge>& vedges = (v)->viewedges();
+ vector<ViewVertex::directedViewEdge> newEdges;
+ for (vector<ViewVertex::directedViewEdge>::iterator ve = vedges.begin(), veend = vedges.end();
+ ve != veend;
+ ve++)
+ {
+ ViewEdge *current = (ViewEdge *)((ve)->first)->userdata;
+ newEdges.push_back(ViewVertex::directedViewEdge(current, ve->second));
+ }
+ (v)->setViewEdges(newEdges);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ //-------------------------------------
+ // remap vertices in edges:
+ //-------------------------------------
+ for (ve = _Edges.begin(), veend = _Edges.end(); ve != veend; ve++) {
+ (*ve)->setA((ViewVertex *)((*ve)->A()->userdata));
+ (*ve)->setB((ViewVertex *)((*ve)->B()->userdata));
+ //---------------------------------------
+ // Update all embedded FEdges
+ //---------------------------------------
+ (*ve)->UpdateFEdges();
+ }
+
+ // reset all brothers userdata to NULL:
+ //-------------------------------------
+ //---------
+ // vertices
+ //---------
+ for (vv = vvertices.begin(), vvend = vvertices.end(); vv != vvend; vv++) {
+ (*vv)->userdata = NULL;
+ }
+
+ //------
+ // edges
+ //------
+ for (ve = vvedges.begin(), veend = vvedges.end(); ve != veend; ve++) {
+ (*ve)->userdata = NULL;
+ }
+ }
+
+ /*! Cloning method. */
+ virtual ViewShape *duplicate()
+ {
+ ViewShape *clone = new ViewShape(*this);
+ return clone;
+ }
+
+ /*! Destructor. */
+ virtual ~ViewShape();
+
+ /* splits a view edge into several view edges.
+ * fe
+ * The FEdge that gets splitted
+ * iViewVertices
+ * The view vertices corresponding to the different intersections for the edge fe.
+ * This list need to be sorted such as the first view vertex is the farther away from fe->vertexA.
+ * ioNewEdges
+ * The feature edges that are newly created (the initial edges are not included) are added to this list.
+ * ioNewViewEdges
+ * The view edges that are newly created (the initial edges are not included) are added to this list.
+ */
+ inline void SplitEdge(FEdge *fe, const vector<TVertex*>& iViewVertices, vector<FEdge*>& ioNewEdges,
+ vector<ViewEdge*>& ioNewViewEdges);
+
+ /* accessors */
+ /*! Returns the SShape on top of which this ViewShape is built. */
+ inline SShape *sshape()
+ {
+ return _SShape;
+ }
+
+ /*! Returns the SShape on top of which this ViewShape is built. */
+ inline const SShape *sshape() const
+ {
+ return _SShape;
+ }
+
+ /*! Returns the list of ViewVertex contained in this ViewShape. */
+ inline vector<ViewVertex*>& vertices()
+ {
+ return _Vertices;
+ }
+
+ /*! Returns the list of ViewEdge contained in this ViewShape. */
+ inline vector<ViewEdge*>& edges()
+ {
+ return _Edges;
+ }
+
+ /*! Returns the ViewShape id. */
+ inline Id getId() const
+ {
+ return _SShape->getId();
+ }
+
+ /*! Returns the ViewShape id. */
+ inline const string& getName() const
+ {
+ return _SShape->getName();
+ }
+
+ /* modifiers */
+ /*! Sets the SShape on top of which the ViewShape is built. */
+ inline void setSShape(SShape *iSShape)
+ {
+ _SShape = iSShape;
+ }
+
+ /*! Sets the list of ViewVertex contained in this ViewShape. */
+ inline void setVertices(const vector<ViewVertex*>& iVertices)
+ {
+ _Vertices = iVertices;
+ }
+
+ /*! Sets the list of ViewEdge contained in this ViewShape. */
+ inline void setEdges(const vector<ViewEdge*>& iEdges)
+ {
+ _Edges = iEdges;
+ }
+
+ /*! Adds a ViewVertex to the list. */
+ inline void AddVertex(ViewVertex *iVertex)
+ {
+ _Vertices.push_back(iVertex);
+ //_SShape->AddNewVertex(iVertex->svertex());
+ }
+
+ /*! Adds a ViewEdge to the list */
+ inline void AddEdge(ViewEdge *iEdge)
+ {
+ _Edges.push_back(iEdge);
+ iEdge->setShape(this);
+ //_SShape->AddNewEdge(iEdge->fedge());
+ }
+
+ /* removes the view edge iViewEdge in the View Shape and the associated FEdge chain entry in the underlying SShape
+ */
+ void RemoveEdge(ViewEdge *iViewEdge);
+
+ /* removes the view vertex iViewVertex in the View Shape. */
+ void RemoveVertex(ViewVertex *iViewVertex);
+};
+
+
+/*
+ #############################################
+ #############################################
+ #############################################
+ ###### ######
+ ###### I M P L E M E N T A T I O N ######
+ ###### ######
+ #############################################
+ #############################################
+ #############################################
+*/
+/* for inline functions */
+
+void ViewShape::SplitEdge(FEdge *fe, const vector<TVertex*>& iViewVertices, vector<FEdge*>& ioNewEdges,
+ vector<ViewEdge*>& ioNewViewEdges)
+{
+ ViewEdge *vEdge = fe->viewedge();
+
+ // We first need to sort the view vertices from farther to closer to fe->vertexA
+ SVertex *sv, *sv2;
+ ViewVertex *vva, *vvb;
+ vector<TVertex*>::const_iterator vv, vvend;
+ for (vv = iViewVertices.begin(), vvend = iViewVertices.end(); vv != vvend; vv++) {
+ // Add the viewvertices to the ViewShape
+ AddVertex((*vv));
+
+ // retrieve the correct SVertex from the view vertex
+ //--------------------------------------------------
+ sv = (*vv)->frontSVertex();
+ sv2 = (*vv)->backSVertex();
+
+ if (sv->shape() != sv2->shape()) {
+ if (sv->shape() != _SShape)
+ sv = sv2;
+ }
+ else {
+ // if the shape is the same we can safely differ the two vertices using their ids:
+ if (sv->getId() != fe->vertexA()->getId())
+ sv = sv2;
+ }
+
+ vva = vEdge->A();
+ vvb = vEdge->B();
+
+ // We split Fedge AB into AA' and A'B. A' and A'B are created.
+ // AB becomes (address speaking) AA'. B is updated.
+ //--------------------------------------------------
+ SShape *shape = fe->shape();
+
+ // a new edge, A'B is created.
+ FEdge *newEdge = shape->SplitEdgeIn2(fe, sv);
+ /* One of the two FEdges (fe and newEdge) may have a 2D length less than M_EPSILON.
+ * (22 Feb 2011, T.K.)
+ */
+
+ ioNewEdges.push_back(newEdge);
+ ViewEdge *newVEdge;
+
+ if ((vva == 0) || (vvb == 0)) { // that means we're dealing with a closed viewedge (loop)
+ // remove the chain that was starting by the fedge A of vEdge (which is different from fe !!!!)
+ shape->RemoveEdgeFromChain(vEdge->fedgeA());
+ // we set
+ vEdge->setA(*vv);
+ vEdge->setB(*vv);
+ vEdge->setFEdgeA(newEdge);
+ //FEdge *previousEdge = newEdge->previousEdge();
+ vEdge->setFEdgeB(fe);
+ newVEdge = vEdge;
+ vEdge->fedgeA()->setViewEdge(newVEdge);
+ }
+ else {
+ // while we create the view edge, it updates the "ViewEdge" pointer of every underlying FEdges to this.
+ newVEdge = new ViewEdge((*vv), vvb); //, newEdge, vEdge->fedgeB());
+ newVEdge->setNature((fe)->getNature());
+ newVEdge->setFEdgeA(newEdge);
+ //newVEdge->setFEdgeB(fe);
+ // If our original viewedge is made of one FEdge, then
+ if ((vEdge->fedgeA() == vEdge->fedgeB()) || (fe == vEdge->fedgeB()))
+ newVEdge->setFEdgeB(newEdge);
+ else
+ newVEdge->setFEdgeB(vEdge->fedgeB()); //MODIF
+
+ Id *newId = vEdge->splittingId();
+ if (newId == 0) {
+ newId = new Id(vEdge->getId());
+ vEdge->setSplittingId(newId);
+ }
+ newId->setSecond(newId->getSecond() + 1);
+ newVEdge->setId(*newId);
+ newVEdge->setSplittingId(newId);
+#if 0
+ Id id(vEdge->getId().getFirst(), vEdge->getId().getSecond() + 1);
+ newVEdge->setId(vEdge->getId());
+ vEdge->setId(id);
+#endif
+
+ AddEdge(newVEdge); // here this shape is set as the edge's shape
+
+ // add new edge to the list of new edges passed as argument:
+ ioNewViewEdges.push_back(newVEdge);
+
+ if (0 != vvb)
+ vvb->Replace((vEdge), newVEdge);
+
+ // we split the view edge:
+ vEdge->setB((*vv));
+ vEdge->setFEdgeB(fe); //MODIF
+
+ // Update fedges so that they point to the new viewedge:
+ newVEdge->UpdateFEdges();
+ }
+ // check whether this vertex is a front vertex or a back one
+ if (sv == (*vv)->frontSVertex()) {
+ // -- View Vertex A' --
+ (*vv)->setFrontEdgeA(vEdge, true);
+ (*vv)->setFrontEdgeB(newVEdge, false);
+ }
+ else {
+ // -- View Vertex A' --
+ (*vv)->setBackEdgeA(vEdge, true);
+ (*vv)->setBackEdgeB(newVEdge, false);
+ }
+ }
+}
+
+/**********************************/
+/* */
+/* */
+/* ViewEdge */
+/* */
+/* */
+/**********************************/
+
+#if 0
+inline Vec3r ViewEdge::orientation2d(int iCombination) const
+{
+ return edge_orientation2d_function<ViewEdge>(*this, iCombination);
+}
+
+inline Vec3r ViewEdge::orientation3d(int iCombination) const
+{
+ return edge_orientation3d_function<ViewEdge>(*this, iCombination);
+}
+
+inline real ViewEdge::z_discontinuity(int iCombination) const
+{
+ return z_discontinuity_edge_function<ViewEdge>(*this, iCombination);
+}
+
+inline float ViewEdge::local_average_depth(int iCombination ) const
+{
+ return local_average_depth_edge_function<ViewEdge>(*this, iCombination);
+}
+
+inline float ViewEdge::local_depth_variance(int iCombination) const
+{
+ return local_depth_variance_edge_function<ViewEdge>(*this, iCombination);
+}
+
+inline real ViewEdge::local_average_density(float sigma, int iCombination) const
+{
+ return density_edge_function<ViewEdge>(*this, iCombination);
+}
+#endif
+
+inline const SShape *ViewEdge::occluded_shape() const
+{
+ if (0 == _aShape)
+ return 0;
+ return _aShape->sshape();
+}
+
+#if 0
+inline Vec3r ViewEdge::curvature2d_as_vector(int iCombination) const
+{
+ return curvature2d_as_vector_edge_function<ViewEdge>(*this, iCombination);
+}
+
+inline real ViewEdge::curvature2d_as_angle(int iCombination) const
+{
+ return curvature2d_as_angle_edge_function<ViewEdge>(*this, iCombination);
+}
+#endif
+
+#endif // __FREESTYLE_VIEW_MAP_H__
diff --git a/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h b/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h
new file mode 100644
index 00000000000..d7ed73ed795
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h
@@ -0,0 +1,789 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_VIEW_MAP_ADVANCED_ITERATORS_H__
+#define __FREESTYLE_VIEW_MAP_ADVANCED_ITERATORS_H__
+
+/** \file blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h
+ * \ingroup freestyle
+ * \brief Iterators used to iterate over the various elements of the ViewMap.
+ * These iterators can't be exported to python.
+ * \author Stephane Grabli
+ * \date 01/07/2003
+ */
+
+#include "ViewMap.h"
+
+#include "../system/Iterator.h" //soc
+
+/**********************************/
+/* */
+/* */
+/* ViewMap */
+/* */
+/* */
+/**********************************/
+
+/**********************************/
+/* */
+/* */
+/* ViewVertex */
+/* */
+/* */
+/**********************************/
+
+namespace ViewVertexInternal {
+
+class edge_const_traits : public Const_traits< ::ViewVertex::directedViewEdge>
+{
+public:
+ typedef vector< ::ViewVertex::directedViewEdge> edges_container;
+ typedef edges_container::const_iterator edges_container_iterator;
+ typedef vector< ::ViewVertex::directedViewEdge*> edge_pointers_container;
+ typedef edge_pointers_container::const_iterator edge_pointers_container_iterator;
+};
+
+class edge_nonconst_traits : public Nonconst_traits< ::ViewVertex::directedViewEdge>
+{
+public:
+ typedef vector< ::ViewVertex::directedViewEdge> edges_container;
+ typedef edges_container::iterator edges_container_iterator;
+ typedef vector< ::ViewVertex::directedViewEdge*> edge_pointers_container;
+ typedef edge_pointers_container::iterator edge_pointers_container_iterator;
+};
+
+template<class Traits>
+class edge_iterator_base : public IteratorBase<Traits, InputIteratorTag_Traits>
+{
+public:
+ typedef typename Traits::value_type value_type;
+ typedef typename Traits::difference_type difference_type;
+ typedef typename Traits::pointer pointer;
+ typedef typename Traits::reference reference;
+ typedef edge_iterator_base<Traits> Self;
+ typedef typename Traits::edges_container_iterator edges_container_iterator;
+ typedef typename Traits::edge_pointers_container_iterator edge_pointers_container_iterator;
+ typedef edge_iterator_base<edge_nonconst_traits> iterator;
+ typedef edge_iterator_base<edge_const_traits> const_iterator;
+
+public:
+ friend class ViewVertex;
+ friend class TVertex;
+ friend class NonTVertex;
+ friend class ViewEdge;
+ friend class edge_iterator;
+
+protected:
+ Nature::VertexNature _Nature; // the nature of the underlying vertex
+ // T vertex attributes
+ edge_pointers_container_iterator _tbegin;
+ edge_pointers_container_iterator _tend;
+ edge_pointers_container_iterator _tvertex_iter;
+
+#if 0
+ mutable value_type _tvertex_iter;
+ value_type _feA;
+ value_type _feB;
+ value_type _beA;
+ value_type _beB;
+#endif
+
+ // Non TVertex attributes
+ edges_container_iterator _begin;
+ edges_container_iterator _end;
+ edges_container_iterator _nontvertex_iter;
+
+ typedef IteratorBase<Traits, InputIteratorTag_Traits> parent_class;
+
+public:
+ inline edge_iterator_base() : parent_class() {}
+
+ inline edge_iterator_base(Nature::VertexNature iNature) : parent_class()
+ {
+ _Nature = iNature;
+ }
+
+ edge_iterator_base(const edge_iterator_base<edge_nonconst_traits>& iBrother) : parent_class(iBrother)
+ {
+ _Nature = iBrother._Nature;
+ if (_Nature & Nature::T_VERTEX) {
+#if 0
+ _feA = iBrother._feA;
+ _feB = iBrother._feB;
+ _beA = iBrother._beA;
+ _beB = iBrother._beB;
+ _tvertex_iter = iBrother._tvertex_iter;
+#endif
+ _tbegin = iBrother._tbegin;
+ _tend = iBrother._tend;
+ _tvertex_iter = iBrother._tvertex_iter;
+ }
+ else {
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _nontvertex_iter = iBrother._nontvertex_iter;
+ }
+ }
+
+ edge_iterator_base(const edge_iterator_base<edge_const_traits>& iBrother) : parent_class(iBrother)
+ {
+ _Nature = iBrother._Nature;
+ if (_Nature & Nature::T_VERTEX) {
+#if 0
+ _feA = iBrother._feA;
+ _feB = iBrother._feB;
+ _beA = iBrother._beA;
+ _beB = iBrother._beB;
+ _tvertex_iter = iBrother._tvertex_iter;
+#endif
+ _tbegin = iBrother._tbegin;
+ _tend = iBrother._tend;
+ _tvertex_iter = iBrother._tvertex_iter;
+ }
+ else {
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _nontvertex_iter = iBrother._nontvertex_iter;
+ }
+ }
+
+ virtual ~edge_iterator_base() {}
+
+//protected://FIXME
+public:
+#if 0
+ inline edge_iterator_base(value_type ifeA, value_type ifeB, value_type ibeA, value_type ibeB, value_type iter)
+ : parent_class()
+ {
+ _Nature = Nature::T_VERTEX;
+ _feA = ifeA;
+ _feB = ifeB;
+ _beA = ibeA;
+ _beB = ibeB;
+ _tvertex_iter = iter;
+ }
+#endif
+
+ inline edge_iterator_base(edge_pointers_container_iterator begin, edge_pointers_container_iterator end,
+ edge_pointers_container_iterator iter)
+ : parent_class()
+ {
+ _Nature = Nature::T_VERTEX;
+ _tbegin = begin;
+ _tend = end;
+ _tvertex_iter = iter;
+ }
+
+ inline edge_iterator_base(edges_container_iterator begin, edges_container_iterator end,
+ edges_container_iterator iter)
+ : parent_class()
+ {
+ _Nature = Nature::NON_T_VERTEX;
+ _begin = begin;
+ _end = end;
+ _nontvertex_iter = iter;
+ }
+
+public:
+ virtual bool begin() const
+ {
+ if (_Nature & Nature::T_VERTEX)
+ return (_tvertex_iter == _tbegin);
+ //return (_tvertex_iter == _feA);
+ else
+ return (_nontvertex_iter == _begin);
+ }
+
+ virtual bool end() const
+ {
+ if (_Nature & Nature::T_VERTEX)
+ //return (_tvertex_iter.first == 0);
+ return (_tvertex_iter == _tend);
+ else
+ return (_nontvertex_iter == _end);
+ }
+
+ // operators
+ // operator corresponding to ++i
+ virtual Self& operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ // operator corresponding to i++, i.e. which returns the value *and then* increments it.
+ // That's why we store the value in a temp.
+ virtual Self operator++(int) // opérateur correspondant à i++
+ {
+ Self tmp = *this;
+ increment();
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const Self& b) const
+ {
+ if (_Nature & Nature::T_VERTEX)
+ return (_tvertex_iter != b._tvertex_iter);
+ else
+ return (_nontvertex_iter != b._nontvertex_iter);
+ }
+
+ virtual bool operator==(const Self& b) const
+ {
+ return !(*this != b);
+ }
+
+ // dereferencing
+ virtual reference operator*() const
+ {
+ if (_Nature & Nature::T_VERTEX)
+ //return _tvertex_iter;
+ return **_tvertex_iter;
+ else
+ return (*_nontvertex_iter);
+ }
+
+ virtual pointer operator->() const
+ {
+ return &(operator*());
+ }
+
+protected:
+ inline void increment()
+ {
+ if (_Nature & Nature::T_VERTEX) {
+ value_type tmp = (**_tvertex_iter);
+ ++_tvertex_iter;
+ value_type tmp2 = (**_tvertex_iter);
+ if (tmp2.first == tmp.first)
+ ++_tvertex_iter;
+#if 0
+ // Hack to deal with cusp. the result of a cusp is a TVertex having two identical viewedges.
+ // In order to iterate properly, we chose to to skip these last ones.
+ if (_feB.first == _beA.first) {
+ if (_feA.first == _beB.first) {
+ _tvertex_iter.first = 0;
+ return;
+ }
+
+ if (_tvertex_iter.first == _feA.first)
+ _tvertex_iter.first = _beB.first;
+ else if (_tvertex_iter.first == _beB.first)
+ _tvertex_iter.first = 0;
+ else
+ _tvertex_iter.first = _feA.first;
+ return;
+ }
+ if (_feA.first == _beB.first) {
+ if (_feB.first == _beA.first) {
+ _tvertex_iter.first = 0;
+ return;
+ }
+
+ if (_tvertex_iter.first == _feB.first)
+ _tvertex_iter.first = _beA.first;
+ else if (_tvertex_iter.first == _beA.first)
+ _tvertex_iter.first = 0;
+ else
+ _tvertex_iter.first = _feB.first;
+ return;
+ }
+ // End of hack
+
+ if (_tvertex_iter.first == _feA.first) {
+ // we return bea or beb
+ // choose one of them
+ _tvertex_iter.first = _feB.first;
+ return;
+ }
+ if (_tvertex_iter.first == _feB.first) {
+ _tvertex_iter.first = _beA.first;
+ return;
+ }
+ if (_tvertex_iter.first == _beA.first) {
+ _tvertex_iter.first = _beB.first;
+ return;
+ }
+ if (_tvertex_iter.first == _beB.first) {
+ _tvertex_iter.first = 0;
+ return;
+ }
+#endif
+ }
+ else {
+ ++_nontvertex_iter;
+ }
+ }
+};
+
+} // ViewVertexInternal namespace
+
+/**********************************/
+/* */
+/* */
+/* ViewEdge */
+/* */
+/* */
+/**********************************/
+
+namespace ViewEdgeInternal {
+
+/*!----------------------*/
+/*! Iterators definition */
+/*!----------------------*/
+template<class Traits>
+class edge_iterator_base : public IteratorBase<Traits, BidirectionalIteratorTag_Traits>
+{
+public:
+ typedef typename Traits::value_type value_type;
+ typedef typename Traits::difference_type difference_type;
+ typedef typename Traits::pointer pointer;
+ typedef typename Traits::reference reference;
+ typedef edge_iterator_base<Traits> Self;
+
+public:
+ mutable value_type _ViewEdge;
+ //friend class edge_iterator_base<Nonconst_traits<ViewEdge*> >;
+ //friend class edge_iterator_base<Const_traits<ViewEdge*> >;
+ value_type _first;
+ bool _orientation;
+ typedef IteratorBase<Traits, BidirectionalIteratorTag_Traits> parent_class;
+
+public:
+ friend class ViewEdge;
+ inline edge_iterator_base() : parent_class()
+ {
+ _orientation = true;
+ _first = 0;
+ }
+
+ inline edge_iterator_base(const edge_iterator_base<Nonconst_traits< ::ViewEdge*> >& iBrother) : parent_class()
+ {
+ _ViewEdge = iBrother._ViewEdge;
+ _first = iBrother._first;
+ _orientation = iBrother._orientation;
+ }
+
+ inline edge_iterator_base(const edge_iterator_base<Const_traits< ::ViewEdge*> >& iBrother) : parent_class()
+ {
+ _ViewEdge = iBrother._ViewEdge;
+ _first = iBrother._first;
+ _orientation = iBrother._orientation;
+ }
+
+//protected://FIXME
+public:
+ inline edge_iterator_base(value_type iEdge, bool orientation = true) : parent_class()
+ {
+ _ViewEdge = iEdge;
+ _first = iEdge;
+ _orientation = orientation;
+ }
+
+public:
+ virtual Self *clone() const
+ {
+ return new edge_iterator_base(*this);
+ }
+
+ virtual ~edge_iterator_base() {}
+
+public:
+ virtual bool orientation()
+ {
+ return _orientation;
+ }
+
+ virtual void set_edge(value_type iVE)
+ {
+ _ViewEdge = iVE;
+ }
+
+ virtual void set_orientation(bool iOrientation)
+ {
+ _orientation = iOrientation;
+ }
+
+ virtual void change_orientation()
+ {
+ _orientation = !_orientation;
+ }
+
+ // operators
+ // operator corresponding to ++i
+ inline Self& operator++()
+ {
+ //++_ViewEdge->getTimeStamp();
+ increment();
+ return *this;
+ }
+
+ // operator corresponding to i++, i.e. which returns the value *and then* increments it.
+ // That's why we store the value in a temp.
+ inline Self operator++(int)
+ {
+ //++_ViewEdge->getTimeStamp();
+ Self tmp = *this;
+ increment();
+ return tmp;
+ }
+
+ // operator corresponding to --i
+ inline Self& operator--()
+ {
+ //++_ViewEdge->getTimeStamp();
+ decrement();
+ return *this;
+ }
+
+ // operator corresponding to i--, i.e. which returns the value *and then* increments it.
+ // That's why we store the value in a temp.
+ inline Self operator--(int)
+ {
+ //++_ViewEdge->getTimeStamp();
+ Self tmp = *this;
+ decrement();
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const Self& b) const
+ {
+ return (_ViewEdge != b._ViewEdge);
+ }
+
+ virtual bool operator==(const Self& b) const
+ {
+ return !(*this != b);
+ }
+
+ // dereferencing
+ virtual reference operator*() const
+ {
+ return (_ViewEdge);
+ }
+
+ virtual pointer operator->() const
+ {
+ return &(operator*());
+ }
+
+public:
+ virtual bool begin() const
+ {
+ return (_ViewEdge == _first) ? true : false;
+ }
+
+ virtual bool end() const
+ {
+ return (_ViewEdge == 0) ? true : false;
+ }
+
+protected:
+ virtual void increment() {}
+ virtual void decrement() {}
+};
+
+template<class Traits>
+class fedge_iterator_base : public IteratorBase<Traits, BidirectionalIteratorTag_Traits>
+{
+public:
+ typedef typename Traits::value_type value_type;
+ typedef typename Traits::difference_type difference_type;
+ typedef typename Traits::pointer pointer;
+ typedef typename Traits::reference reference;
+ typedef fedge_iterator_base<Traits> Self;
+
+public:
+ typedef IteratorBase<Traits, BidirectionalIteratorTag_Traits> parent_class;
+ mutable value_type _FEdge;
+ value_type _first;
+ value_type _FEdgeB; // last fedge of the view edge
+
+public:
+ friend class ::ViewEdge;
+ friend class fedge_iterator;
+
+ inline fedge_iterator_base() : parent_class() {}
+
+ inline fedge_iterator_base(const fedge_iterator_base<Nonconst_traits<FEdge*> >& iBrother) : parent_class()
+ {
+ _FEdge = iBrother._FEdge;
+ _first = iBrother._first;
+ _FEdgeB = iBrother._FEdgeB;
+ }
+
+ inline fedge_iterator_base(const fedge_iterator_base<Const_traits<FEdge*> >& iBrother) : parent_class()
+ {
+ _FEdge = iBrother._FEdge;
+ _first = iBrother._first;
+ _FEdgeB = iBrother._FEdgeB;
+ }
+
+//protected://FIXME
+public:
+ inline fedge_iterator_base(value_type iEdge, value_type iFEdgeB) : parent_class()
+ {
+ _FEdge = iEdge;
+ _first = iEdge;
+ _FEdgeB = iFEdgeB;
+ }
+
+public:
+ virtual ~fedge_iterator_base() {}
+
+ // operators
+ // operator corresponding to ++i.
+ inline Self& operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ // operator corresponding to i++, i.e. which returns the value *and then* increments it.
+ // That's why we store the value in a temp.
+ inline Self operator++(int)
+ {
+ Self tmp = *this;
+ increment();
+ return tmp;
+ }
+
+ // operator corresponding to --i
+ inline Self& operator--()
+ {
+ decrement();
+ return *this;
+ }
+
+ // operator corresponding to i--, i.e. which returns the value *and then* increments it.
+ // That's why we store the value in a temp.
+ inline Self operator--(int)
+ {
+ Self tmp = *this;
+ decrement();
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const Self& b) const
+ {
+ return (_FEdge != b._FEdge);
+ }
+
+ virtual bool operator==(const Self& b) const
+ {
+ return !(*this != b);
+ }
+
+ // dereferencing
+ virtual reference operator*() const
+ {
+ return (_FEdge);
+ }
+
+ virtual pointer operator->() const
+ {
+ return &(operator*());
+ }
+
+public:
+ virtual bool begin() const
+ {
+ return (_FEdge == _first) ? true : false;
+ }
+
+ virtual bool end() const
+ {
+ return (_FEdge == 0) ? true : false;
+ }
+
+protected:
+ virtual void increment()
+ {
+ _FEdge = _FEdge->nextEdge(); // we don't change or
+ }
+
+ virtual void decrement()
+ {
+ if (0 == _FEdge) {
+ _FEdge = _FEdgeB;
+ return;
+ }
+ _FEdge = _FEdge->previousEdge(); // we don't change or
+ }
+};
+
+template<class Traits>
+class vertex_iterator_base : public IteratorBase<Traits, BidirectionalIteratorTag_Traits>
+{
+public:
+ typedef typename Traits::value_type value_type;
+ typedef typename Traits::difference_type difference_type;
+ typedef typename Traits::pointer pointer;
+ typedef typename Traits::reference reference;
+ typedef vertex_iterator_base<Traits> Self;
+
+protected:
+ typedef IteratorBase<Traits, BidirectionalIteratorTag_Traits> parent_class;
+
+public:
+ mutable value_type _SVertex;
+ FEdge *_NextFEdge;
+ FEdge *_PreviousFEdge;
+
+public:
+ friend class ViewEdge;
+ friend class vertex_iterator;
+
+ inline vertex_iterator_base() : parent_class() {}
+
+ inline vertex_iterator_base(const vertex_iterator_base<Const_traits<SVertex*> >& iBrother) : parent_class()
+ {
+ _SVertex = iBrother._SVertex;
+ _NextFEdge = iBrother._NextFEdge;
+ _PreviousFEdge = iBrother._PreviousFEdge;
+ }
+
+ inline vertex_iterator_base(const vertex_iterator_base<Nonconst_traits<SVertex*> >& iBrother) : parent_class()
+ {
+ _SVertex = iBrother._SVertex;
+ _NextFEdge = iBrother._NextFEdge;
+ _PreviousFEdge = iBrother._PreviousFEdge;
+ }
+
+//protected://FIXME
+public:
+ inline vertex_iterator_base(value_type iVertex, FEdge *iPreviousFEdge, FEdge *iNextFEdge) : parent_class()
+ {
+ _SVertex = iVertex;
+ _NextFEdge = iNextFEdge;
+ _PreviousFEdge = iPreviousFEdge;
+ }
+
+public:
+ virtual ~vertex_iterator_base() {}
+
+ virtual bool begin() const
+ {
+ return (_PreviousFEdge == 0) ? true : false;
+ }
+
+ virtual bool end() const
+ {
+ return (_SVertex == 0) ? true : false;
+ }
+
+ // operators
+ // operator corresponding to ++i
+ inline Self& operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ // operator corresponding to i++, i.e. which returns the value *and then* increments it.
+ // That's why we store the value in a temp.
+ inline Self operator++(int)
+ {
+ Self tmp = *this;
+ increment();
+ return tmp;
+ }
+
+ // operator corresponding to --i
+ inline Self& operator--()
+ {
+ decrement();
+ return *this;
+ }
+
+ // operator corresponding to --i, i.e. which returns the value *and then* increments it.
+ // That's why we store the value in a temp.
+ inline Self operator--(int)
+ {
+ Self tmp = *this;
+ decrement();
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const Self& b) const
+ {
+ return (_SVertex != b._SVertex);
+ }
+
+ virtual bool operator==(const Self& b) const
+ {
+ return !(*this != b);
+ }
+
+ // dereferencing
+ virtual reference operator*() const
+ {
+ return (_SVertex);
+ }
+
+ virtual pointer operator->() const
+ {
+ return &(operator*());
+ }
+
+protected:
+ virtual void increment()
+ {
+ if (!_NextFEdge) {
+ _SVertex = NULL;
+ return;
+ }
+ _SVertex = _NextFEdge->vertexB();
+ _PreviousFEdge = _NextFEdge;
+ _NextFEdge = _NextFEdge->nextEdge();
+ }
+
+ virtual void decrement()
+ {
+#if 0
+ if (!_SVertex) {
+ _SVertex = _PreviousFEdge->vertexB();
+ return;
+ }
+#endif
+ if (!_PreviousFEdge) {
+ _SVertex = NULL;
+ return;
+ }
+ _SVertex = _PreviousFEdge->vertexA();
+ _NextFEdge = _PreviousFEdge;
+ _PreviousFEdge = _PreviousFEdge->previousEdge();
+ }
+};
+
+} // end of namespace ViewEdgeInternal
+
+#endif // __FREESTYLE_VIEW_MAP_ADVANCED_ITERATORS_H__
diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
new file mode 100644
index 00000000000..6727a44465a
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
@@ -0,0 +1,2391 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/ViewMapBuilder.cpp
+ * \ingroup freestyle
+ * \brief Class to build silhouette edges from a Winged-Edge structure
+ * \author Stephane Grabli
+ * \date 25/03/2002
+ */
+
+#include <algorithm>
+#include <memory>
+#include <stdexcept>
+
+#include "FRS_freestyle.h"
+
+#include "BoxGrid.h"
+#include "CulledOccluderSource.h"
+#include "HeuristicGridDensityProviderFactory.h"
+#include "OccluderSource.h"
+#include "SphericalGrid.h"
+#include "ViewMapBuilder.h"
+
+#include "../geometry/GridHelpers.h"
+#include "../geometry/GeomUtils.h"
+
+#include "../winged_edge/WFillGrid.h"
+
+#include "BKE_global.h"
+
+// XXX Grmll... G is used as template's typename parameter :/
+const Global &_global = G;
+
+#define LOGGING FALSE
+
+using namespace std;
+
+template <typename G, typename I>
+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;
+ if (fe->isSmooth()) {
+ FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth*>(fe);
+ face = (WFace *)fes->face();
+ }
+ WFace *oface;
+ bool skipFace;
+
+ WVertex::incoming_edge_iterator ie;
+
+ *oaWFace = NULL;
+ if (((fe)->getNature() & Nature::SILHOUETTE) || ((fe)->getNature() & Nature::BORDER)) {
+ // we cast a ray from A in the same direction but looking behind
+ Vec3r v(-u[0], -u[1], -u[2]);
+ bool noIntersection = true;
+ real mint = FLT_MAX;
+
+ for (occluders.initAfterTarget(); occluders.validAfterTarget(); occluders.nextOccludee()) {
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\t\tEvaluating intersection for occludee " << occluders.getWFace() << " and ray " << A <<
+ " * " << u << endl;
+ }
+#endif
+ oface = occluders.getWFace();
+ Polygon3r *p = occluders.getCameraSpacePolygon();
+ real d = -((p->getVertices())[0] * p->getNormal());
+ real t, t_u, t_v;
+
+ if (0 != face) {
+ skipFace = false;
+
+ if (face == oface)
+ continue;
+
+ if (faceVertices.empty())
+ continue;
+
+ for (vector<WVertex*>::iterator fv = faceVertices.begin(), fvend = faceVertices.end();
+ fv != fvend;
+ ++fv)
+ {
+ if ((*fv)->isBoundary())
+ continue;
+ WVertex::incoming_edge_iterator iebegin = (*fv)->incoming_edges_begin();
+ WVertex::incoming_edge_iterator ieend = (*fv)->incoming_edges_end();
+ for (ie = iebegin; ie != ieend; ++ie) {
+ if ((*ie) == 0)
+ continue;
+
+ WFace *sface = (*ie)->GetbFace();
+ if (sface == oface) {
+ skipFace = true;
+ break;
+ }
+ }
+ if (skipFace)
+ break;
+ }
+ if (skipFace)
+ continue;
+ }
+ else {
+ // check whether the edge and the polygon plane are coincident:
+ //-------------------------------------------------------------
+ //first let us compute the plane equation.
+ if (GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edge, p->getNormal(), d, t, epsilon))
+ {
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\t\tRejecting occluder for target coincidence." << endl;
+ }
+#endif
+ continue;
+ }
+ }
+
+ if (p->rayIntersect(A, v, t, t_u, t_v)) {
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\t\tRay " << A << " * " << v << " intersects at time " << t << endl;
+ cout << "\t\t(v * normal) == " << (v * p->getNormal()) << " for normal " << p->getNormal() << endl;
+ }
+#endif
+ if (fabs(v * p->getNormal()) > 0.0001) {
+ if ((t > 0.0)) { // && (t<1.0))
+ if (t < mint) {
+ *oaWFace = oface;
+ mint = t;
+ noIntersection = false;
+ fe->setOccludeeIntersection(Vec3r(A + t * v));
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\t\tIs occludee" << endl;
+ }
+#endif
+ }
+ }
+ }
+
+ occluders.reportDepth(A, v, t);
+ }
+ }
+
+ if (noIntersection)
+ *oaWFace = NULL;
+ }
+}
+
+template <typename G, typename I>
+static void findOccludee(FEdge *fe, G& grid, real epsilon, ViewEdge *ve, WFace **oaFace)
+{
+ Vec3r A;
+ Vec3r edge;
+ Vec3r origin;
+ A = Vec3r(((fe)->vertexA()->point3D() + (fe)->vertexB()->point3D()) / 2.0);
+ edge = Vec3r((fe)->vertexB()->point3D() - (fe)->vertexA()->point3D());
+ origin = Vec3r((fe)->vertexA()->point3D());
+ Vec3r u;
+ if (grid.orthographicProjection()) {
+ u = Vec3r(0.0, 0.0, grid.viewpoint().z() - A.z());
+ }
+ else {
+ u = Vec3r(grid.viewpoint() - A);
+ }
+ u.normalize();
+
+ vector<WVertex*> faceVertices;
+
+ WFace *face = NULL;
+ if (fe->isSmooth()) {
+ FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth*>(fe);
+ face = (WFace *)fes->face();
+ }
+
+ if (face) {
+ face->RetrieveVertexList(faceVertices);
+ }
+
+ I occluders(grid, A, epsilon);
+ findOccludee<G, I>(fe, grid, occluders, epsilon, oaFace, u, A, origin, edge, faceVertices);
+}
+
+// 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,
+ set<ViewShape*> *foundOccluders)
+{
+ int qi = 0;
+
+ Vec3r center;
+ Vec3r edge;
+ Vec3r origin;
+
+ center = fe->center3d();
+ edge = Vec3r(fe->vertexB()->point3D() - fe->vertexA()->point3D());
+ origin = Vec3r(fe->vertexA()->point3D());
+
+ Vec3r vp;
+ if (grid.orthographicProjection()) {
+ vp = Vec3r(center.x(), center.y(), grid.viewpoint().z());
+ }
+ else {
+ vp = Vec3r(grid.viewpoint());
+ }
+ Vec3r u(vp - center);
+ real raylength = u.norm();
+ u.normalize();
+
+ WFace *face = NULL;
+ if (fe->isSmooth()) {
+ FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth*>(fe);
+ face = (WFace *)fes->face();
+ }
+ vector<WVertex*> faceVertices;
+ WVertex::incoming_edge_iterator ie;
+
+ WFace *oface;
+ bool skipFace;
+
+ if (face)
+ face->RetrieveVertexList(faceVertices);
+
+ I occluders(grid, center, epsilon);
+
+ for (occluders.initBeforeTarget(); occluders.validBeforeTarget(); occluders.nextOccluder()) {
+ // If we're dealing with an exact silhouette, check whether we must take care of this occluder of not.
+ // (Indeed, we don't consider the occluders that share at least one vertex with the face containing this edge).
+ //-----------
+ oface = occluders.getWFace();
+ Polygon3r *p = occluders.getCameraSpacePolygon();
+ real t, t_u, t_v;
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\t\tEvaluating intersection for occluder " << (p->getVertices())[0] << (p->getVertices())[1] <<
+ (p->getVertices())[2] << endl << "\t\t\tand ray " << vp << " * " << u << " (center " << center <<
+ ")" << endl;
+ }
+#endif
+
+#if LOGGING
+ Vec3r v(vp - center);
+ real rl = v.norm();
+ v.normalize();
+ vector<Vec3r> points;
+ // Iterate over vertices, storing projections in points
+ for (vector<WOEdge*>::const_iterator woe = oface->getEdgeList().begin(), woend = oface->getEdgeList().end();
+ woe != woend;
+ woe++)
+ {
+ points.push_back(Vec3r((*woe)->GetaVertex()->GetVertex()));
+ }
+ Polygon3r p1(points, oface->GetNormal());
+ Vec3r v1((p1.getVertices())[0]);
+ real d = -(v1 * p->getNormal());
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\t\tp: " << (p->getVertices())[0] << (p->getVertices())[1] << (p->getVertices())[2] << ", norm: " <<
+ p->getNormal() << endl;
+ cout << "\t\tp1: " << (p1.getVertices())[0] << (p1.getVertices())[1] << (p1.getVertices())[2] << ", norm: " <<
+ p1.getNormal() << endl;
+ }
+#else
+ real d = -((p->getVertices())[0] * p->getNormal());
+#endif
+
+ if (face) {
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\t\tDetermining face adjacency...";
+ }
+#endif
+ skipFace = false;
+
+ if (face == oface) {
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << " Rejecting occluder for face concurrency." << endl;
+ }
+#endif
+ continue;
+ }
+
+
+ for (vector<WVertex*>::iterator fv = faceVertices.begin(), fvend = faceVertices.end(); fv != fvend; ++fv) {
+ if ((*fv)->isBoundary())
+ continue;
+
+ WVertex::incoming_edge_iterator iebegin = (*fv)->incoming_edges_begin();
+ WVertex::incoming_edge_iterator ieend = (*fv)->incoming_edges_end();
+ for (ie = iebegin; ie != ieend; ++ie) {
+ if ((*ie) == 0)
+ continue;
+
+ WFace *sface = (*ie)->GetbFace();
+ //WFace *sfacea = (*ie)->GetaFace();
+ //if ((sface == oface) || (sfacea == oface))
+ if (sface == oface) {
+ skipFace = true;
+ break;
+ }
+ }
+ if (skipFace)
+ break;
+ }
+ if (skipFace) {
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << " Rejecting occluder for face adjacency." << endl;
+ }
+#endif
+ continue;
+ }
+ }
+ else {
+ // check whether the edge and the polygon plane are coincident:
+ //-------------------------------------------------------------
+ //first let us compute the plane equation.
+ if (GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edge, p->getNormal(), d, t, epsilon)) {
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\t\tRejecting occluder for target coincidence." << endl;
+ }
+#endif
+ continue;
+ }
+ }
+
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ real x;
+ if (p1.rayIntersect(center, v, x, t_u, t_v)) {
+ cout << "\t\tRay should intersect at time " << (rl - x) << ". Center: " << center << ", V: " << v <<
+ ", RL: " << rl << ", T:" << x << endl;
+ }
+ else {
+ cout << "\t\tRay should not intersect. Center: " << center << ", V: " << v << ", RL: " << rl << endl;
+ }
+ }
+#endif
+
+ if (p->rayIntersect(center, u, t, t_u, t_v)) {
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\t\tRay " << center << " * " << u << " intersects at time " << t << " (raylength is " <<
+ raylength << ")" << endl;
+ cout << "\t\t(u * normal) == " << (u * p->getNormal()) << " for normal " << p->getNormal() << endl;
+ }
+#endif
+ if (fabs(u * p->getNormal()) > 0.0001) {
+ if ((t > 0.0) && (t < raylength)) {
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\t\tIs occluder" << endl;
+ }
+#endif
+ if ( foundOccluders != NULL ) {
+ ViewShape *vshape = viewMap->viewShape(oface->GetVertex(0)->shape()->GetId());
+ foundOccluders->insert(vshape);
+ }
+ ++qi;
+
+ if (! grid.enableQI())
+ break;
+ }
+
+ occluders.reportDepth(center, u, t);
+ }
+ }
+ }
+
+ // Find occludee
+ findOccludee<G, I>(fe, grid, occluders, epsilon, oaWFace, u, center, origin, edge, faceVertices);
+
+ return qi;
+}
+
+// computeCumulativeVisibility returns the lowest x such that the majority of FEdges have QI <= x
+//
+// This was probably the original intention of the "normal" algorithm on which computeDetailedVisibility is based.
+// But because the "normal" algorithm chooses the most popular QI, without considering any other values, a ViewEdge
+// with FEdges having QIs of 0, 21, 22, 23, 24 and 25 will end up having a total QI of 0, even though most of the
+// FEdges are heavily occluded. computeCumulativeVisibility will treat this case as a QI of 22 because 3 out of
+// 6 occluders have QI <= 22.
+
+template <typename G, typename I>
+static void computeCumulativeVisibility(ViewMap *ioViewMap, G& grid, real epsilon, RenderMonitor *iRenderMonitor)
+{
+ vector<ViewEdge*>& vedges = ioViewMap->ViewEdges();
+
+ FEdge *fe, *festart;
+ int nSamples = 0;
+ vector<WFace*> wFaces;
+ WFace *wFace = NULL;
+ unsigned tmpQI = 0;
+ unsigned qiClasses[256];
+ unsigned maxIndex, maxCard;
+ unsigned qiMajority;
+ for (vector<ViewEdge*>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) {
+ if (iRenderMonitor && iRenderMonitor->testBreak())
+ break;
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "Processing ViewEdge " << (*ve)->getId() << endl;
+ }
+#endif
+ // Find an edge to test
+ if (!(*ve)->isInImage()) {
+ // This view edge has been proscenium culled
+ (*ve)->setQI(255);
+ (*ve)->setaShape(0);
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tCulled." << endl;
+ }
+#endif
+ continue;
+ }
+
+ // Test edge
+ festart = (*ve)->fedgeA();
+ fe = (*ve)->fedgeA();
+ qiMajority = 0;
+ do {
+ if (fe != NULL && fe->isInImage()) {
+ qiMajority++;
+ }
+ fe = fe->nextEdge();
+ } while (fe && fe != festart);
+
+ if (qiMajority == 0) {
+ // There are no occludable FEdges on this ViewEdge
+ // This should be impossible.
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "View Edge in viewport without occludable FEdges: " << (*ve)->getId() << endl;
+ }
+ // We can recover from this error:
+ // Treat this edge as fully visible with no occludee
+ (*ve)->setQI(0);
+ (*ve)->setaShape(0);
+ continue;
+ }
+ else {
+ ++qiMajority;
+ qiMajority >>= 1;
+ }
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tqiMajority: " << qiMajority << endl;
+ }
+#endif
+
+ tmpQI = 0;
+ maxIndex = 0;
+ maxCard = 0;
+ nSamples = 0;
+ memset(qiClasses, 0, 256 * sizeof(*qiClasses));
+ set<ViewShape*> foundOccluders;
+
+ fe = (*ve)->fedgeA();
+ do {
+ if (!fe || !fe->isInImage()) {
+ fe = fe->nextEdge();
+ continue;
+ }
+ if ((maxCard < qiMajority)) {
+ //ARB: change &wFace to wFace and use reference in called function
+ tmpQI = computeVisibility<G, I>(ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders);
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tFEdge: visibility " << tmpQI << endl;
+ }
+#endif
+
+ //ARB: This is an error condition, not an alert condition.
+ // Some sort of recovery or abort is necessary.
+ if (tmpQI >= 256) {
+ cerr << "Warning: too many occluding levels" << endl;
+ //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255
+ tmpQI = 255;
+ }
+
+ if (++qiClasses[tmpQI] > maxCard) {
+ maxCard = qiClasses[tmpQI];
+ maxIndex = tmpQI;
+ }
+ }
+ else {
+ //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called
+ //ARB: change &wFace to wFace and use reference in called function
+ findOccludee<G, I>(fe, grid, epsilon, *ve, &wFace);
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tFEdge: occludee only (" << (wFace != NULL ? "found" : "not found") << ")" << endl;
+ }
+#endif
+ }
+
+ // Store test results
+ if (wFace) {
+ vector<Vec3r> vertices;
+ for (int i = 0, numEdges = wFace->numberOfEdges(); i < numEdges; ++i) {
+ vertices.push_back(Vec3r(wFace->GetVertex(i)->GetVertex()));
+ }
+ Polygon3r poly(vertices, wFace->GetNormal());
+ poly.userdata = (void *)wFace;
+ fe->setaFace(poly);
+ wFaces.push_back(wFace);
+ fe->setOccludeeEmpty(false);
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tFound occludee" << endl;
+ }
+#endif
+ }
+ else {
+ fe->setOccludeeEmpty(true);
+ }
+
+ ++nSamples;
+ fe = fe->nextEdge();
+ } while ((maxCard < qiMajority) && (fe) && (fe != festart));
+
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tFinished with " << nSamples << " samples, maxCard = " << maxCard << endl;
+ }
+#endif
+
+ // ViewEdge
+ // qi --
+ // Find the minimum value that is >= the majority of the QI
+ for (unsigned count = 0, i = 0; i < 256; ++i) {
+ count += qiClasses[i];
+ if (count >= qiMajority) {
+ (*ve)->setQI(i);
+ break;
+ }
+ }
+ // occluders --
+ // I would rather not have to go through the effort of creating this set and then copying out its contents.
+ // Is there a reason why ViewEdge::_Occluders cannot be converted to a set<>?
+ for (set<ViewShape*>::iterator o = foundOccluders.begin(), oend = foundOccluders.end(); o != oend; ++o) {
+ (*ve)->AddOccluder((*o));
+ }
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tConclusion: QI = " << maxIndex << ", " << (*ve)->occluders_size() << " occluders." << endl;
+ }
+#else
+ (void)maxIndex;
+#endif
+ // occludee --
+ if (!wFaces.empty()) {
+ if (wFaces.size() <= (float)nSamples / 2.0f) {
+ (*ve)->setaShape(0);
+ }
+ else {
+ ViewShape *vshape = ioViewMap->viewShape((*wFaces.begin())->GetVertex(0)->shape()->GetId());
+ (*ve)->setaShape(vshape);
+ }
+ }
+
+ wFaces.clear();
+ }
+}
+
+template <typename G, typename I>
+static void computeDetailedVisibility(ViewMap *ioViewMap, G& grid, real epsilon, RenderMonitor *iRenderMonitor)
+{
+ vector<ViewEdge*>& vedges = ioViewMap->ViewEdges();
+
+ FEdge *fe, *festart;
+ int nSamples = 0;
+ vector<WFace*> wFaces;
+ WFace *wFace = NULL;
+ unsigned tmpQI = 0;
+ unsigned qiClasses[256];
+ unsigned maxIndex, maxCard;
+ unsigned qiMajority;
+ for (vector<ViewEdge*>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) {
+ if (iRenderMonitor && iRenderMonitor->testBreak())
+ break;
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "Processing ViewEdge " << (*ve)->getId() << endl;
+ }
+#endif
+ // Find an edge to test
+ if (!(*ve)->isInImage()) {
+ // This view edge has been proscenium culled
+ (*ve)->setQI(255);
+ (*ve)->setaShape(0);
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tCulled." << endl;
+ }
+#endif
+ continue;
+ }
+
+ // Test edge
+ festart = (*ve)->fedgeA();
+ fe = (*ve)->fedgeA();
+ qiMajority = 0;
+ do {
+ if (fe != NULL && fe->isInImage()) {
+ qiMajority++;
+ }
+ fe = fe->nextEdge();
+ } while (fe && fe != festart);
+
+ if (qiMajority == 0) {
+ // There are no occludable FEdges on this ViewEdge
+ // This should be impossible.
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "View Edge in viewport without occludable FEdges: " << (*ve)->getId() << endl;
+ }
+ // We can recover from this error:
+ // Treat this edge as fully visible with no occludee
+ (*ve)->setQI(0);
+ (*ve)->setaShape(0);
+ continue;
+ }
+ else {
+ ++qiMajority;
+ qiMajority >>= 1;
+ }
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tqiMajority: " << qiMajority << endl;
+ }
+#endif
+
+ tmpQI = 0;
+ maxIndex = 0;
+ maxCard = 0;
+ nSamples = 0;
+ memset(qiClasses, 0, 256 * sizeof(*qiClasses));
+ set<ViewShape*> foundOccluders;
+
+ fe = (*ve)->fedgeA();
+ do {
+ if (fe == NULL || ! fe->isInImage()) {
+ fe = fe->nextEdge();
+ continue;
+ }
+ if ((maxCard < qiMajority)) {
+ //ARB: change &wFace to wFace and use reference in called function
+ tmpQI = computeVisibility<G, I>(ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders);
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tFEdge: visibility " << tmpQI << endl;
+ }
+#endif
+
+ //ARB: This is an error condition, not an alert condition.
+ // Some sort of recovery or abort is necessary.
+ if (tmpQI >= 256) {
+ cerr << "Warning: too many occluding levels" << endl;
+ //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255
+ tmpQI = 255;
+ }
+
+ if (++qiClasses[tmpQI] > maxCard) {
+ maxCard = qiClasses[tmpQI];
+ maxIndex = tmpQI;
+ }
+ }
+ else {
+ //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called
+ //ARB: change &wFace to wFace and use reference in called function
+ findOccludee<G, I>(fe, grid, epsilon, *ve, &wFace);
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tFEdge: occludee only (" << (wFace != NULL ? "found" : "not found") << ")" << endl;
+ }
+#endif
+ }
+
+ // Store test results
+ if (wFace) {
+ vector<Vec3r> vertices;
+ for (int i = 0, numEdges = wFace->numberOfEdges(); i < numEdges; ++i) {
+ vertices.push_back(Vec3r(wFace->GetVertex(i)->GetVertex()));
+ }
+ Polygon3r poly(vertices, wFace->GetNormal());
+ poly.userdata = (void *)wFace;
+ fe->setaFace(poly);
+ wFaces.push_back(wFace);
+ fe->setOccludeeEmpty(false);
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tFound occludee" << endl;
+ }
+#endif
+ }
+ else {
+ fe->setOccludeeEmpty(true);
+ }
+
+ ++nSamples;
+ fe = fe->nextEdge();
+ } while ((maxCard < qiMajority) && (fe) && (fe != festart));
+
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tFinished with " << nSamples << " samples, maxCard = " << maxCard << endl;
+ }
+#endif
+
+ // ViewEdge
+ // qi --
+ (*ve)->setQI(maxIndex);
+ // occluders --
+ // I would rather not have to go through the effort of creating this this set and then copying out its contents.
+ // Is there a reason why ViewEdge::_Occluders cannot be converted to a set<>?
+ for (set<ViewShape*>::iterator o = foundOccluders.begin(), oend = foundOccluders.end(); o != oend; ++o) {
+ (*ve)->AddOccluder((*o));
+ }
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tConclusion: QI = " << maxIndex << ", " << (*ve)->occluders_size() << " occluders." << endl;
+ }
+#endif
+ // occludee --
+ if (!wFaces.empty()) {
+ if (wFaces.size() <= (float)nSamples / 2.0f) {
+ (*ve)->setaShape(0);
+ }
+ else {
+ ViewShape *vshape = ioViewMap->viewShape((*wFaces.begin())->GetVertex(0)->shape()->GetId());
+ (*ve)->setaShape(vshape);
+ }
+ }
+
+ wFaces.clear();
+ }
+}
+
+template <typename G, typename I>
+static void computeFastVisibility(ViewMap *ioViewMap, G& grid, real epsilon)
+{
+ vector<ViewEdge*>& vedges = ioViewMap->ViewEdges();
+
+ FEdge *fe, *festart;
+ unsigned nSamples = 0;
+ vector<WFace*> wFaces;
+ WFace *wFace = NULL;
+ unsigned tmpQI = 0;
+ unsigned qiClasses[256];
+ unsigned maxIndex, maxCard;
+ unsigned qiMajority;
+ bool even_test;
+ for (vector<ViewEdge*>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) {
+ // Find an edge to test
+ if (!(*ve)->isInImage()) {
+ // This view edge has been proscenium culled
+ (*ve)->setQI(255);
+ (*ve)->setaShape(0);
+ continue;
+ }
+
+ // Test edge
+ festart = (*ve)->fedgeA();
+ fe = (*ve)->fedgeA();
+
+ even_test = true;
+ qiMajority = 0;
+ do {
+ if (even_test && fe && fe->isInImage()) {
+ qiMajority++;
+ even_test = !even_test;
+ }
+ fe = fe->nextEdge();
+ } while (fe && fe != festart);
+
+ if (qiMajority == 0 ) {
+ // There are no occludable FEdges on this ViewEdge
+ // This should be impossible.
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "View Edge in viewport without occludable FEdges: " << (*ve)->getId() << endl;
+ }
+ // We can recover from this error:
+ // Treat this edge as fully visible with no occludee
+ (*ve)->setQI(0);
+ (*ve)->setaShape(0);
+ continue;
+ }
+ else {
+ ++qiMajority;
+ qiMajority >>= 1;
+ }
+
+ even_test = true;
+ maxIndex = 0;
+ maxCard = 0;
+ nSamples = 0;
+ memset(qiClasses, 0, 256 * sizeof(*qiClasses));
+ set<ViewShape*> foundOccluders;
+
+ fe = (*ve)->fedgeA();
+ do {
+ if (!fe || !fe->isInImage()) {
+ fe = fe->nextEdge();
+ continue;
+ }
+ if (even_test) {
+ if ((maxCard < qiMajority)) {
+ //ARB: change &wFace to wFace and use reference in called function
+ tmpQI = computeVisibility<G, I>(ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders);
+
+ //ARB: This is an error condition, not an alert condition.
+ // Some sort of recovery or abort is necessary.
+ if (tmpQI >= 256) {
+ cerr << "Warning: too many occluding levels" << endl;
+ //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255
+ tmpQI = 255;
+ }
+
+ if (++qiClasses[tmpQI] > maxCard) {
+ maxCard = qiClasses[tmpQI];
+ maxIndex = tmpQI;
+ }
+ }
+ else {
+ //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called
+ //ARB: change &wFace to wFace and use reference in called function
+ findOccludee<G, I>(fe, grid, epsilon, *ve, &wFace);
+ }
+
+ if (wFace) {
+ vector<Vec3r> vertices;
+ for (int i = 0, numEdges = wFace->numberOfEdges(); i < numEdges; ++i) {
+ vertices.push_back(Vec3r(wFace->GetVertex(i)->GetVertex()));
+ }
+ Polygon3r poly(vertices, wFace->GetNormal());
+ poly.userdata = (void *)wFace;
+ fe->setaFace(poly);
+ wFaces.push_back(wFace);
+ }
+ ++nSamples;
+ }
+
+ even_test = ! even_test;
+ fe = fe->nextEdge();
+ } while ((maxCard < qiMajority) && (fe) && (fe != festart));
+
+ // qi --
+ (*ve)->setQI(maxIndex);
+
+ // occluders --
+ for (set<ViewShape*>::iterator o = foundOccluders.begin(), oend = foundOccluders.end(); o != oend; ++o) {
+ (*ve)->AddOccluder((*o));
+ }
+
+ // occludee --
+ if (!wFaces.empty()) {
+ if (wFaces.size() < nSamples / 2) {
+ (*ve)->setaShape(0);
+ }
+ else {
+ ViewShape *vshape = ioViewMap->viewShape((*wFaces.begin())->GetVertex(0)->shape()->GetId());
+ (*ve)->setaShape(vshape);
+ }
+ }
+
+ wFaces.clear();
+ }
+}
+
+template <typename G, typename I>
+static void computeVeryFastVisibility(ViewMap *ioViewMap, G& grid, real epsilon)
+{
+ vector<ViewEdge*>& vedges = ioViewMap->ViewEdges();
+
+ FEdge *fe;
+ unsigned qi = 0;
+ WFace *wFace = 0;
+
+ for (vector<ViewEdge*>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) {
+ // Find an edge to test
+ if (!(*ve)->isInImage()) {
+ // This view edge has been proscenium culled
+ (*ve)->setQI(255);
+ (*ve)->setaShape(0);
+ continue;
+ }
+ fe = (*ve)->fedgeA();
+ // Find a FEdge inside the occluder proscenium to test for visibility
+ FEdge *festart = fe;
+ while (fe && !fe->isInImage() && fe != festart) {
+ fe = fe->nextEdge();
+ }
+
+ // Test edge
+ if (!fe || !fe->isInImage()) {
+ // There are no occludable FEdges on this ViewEdge
+ // This should be impossible.
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "View Edge in viewport without occludable FEdges: " << (*ve)->getId() << endl;
+ }
+ // We can recover from this error:
+ // Treat this edge as fully visible with no occludee
+ qi = 0;
+ wFace = NULL;
+ }
+ else {
+ qi = computeVisibility<G, I>(ioViewMap, fe, grid, epsilon, *ve, &wFace, NULL);
+ }
+
+ // Store test results
+ if (wFace) {
+ vector<Vec3r> vertices;
+ for (int i = 0, numEdges = wFace->numberOfEdges(); i < numEdges; ++i) {
+ vertices.push_back(Vec3r(wFace->GetVertex(i)->GetVertex()));
+ }
+ Polygon3r poly(vertices, wFace->GetNormal());
+ poly.userdata = (void *)wFace;
+ fe->setaFace(poly); // This works because setaFace *copies* the polygon
+ ViewShape *vshape = ioViewMap->viewShape(wFace->GetVertex(0)->shape()->GetId());
+ (*ve)->setaShape(vshape);
+ }
+ else {
+ (*ve)->setaShape(0);
+ }
+ (*ve)->setQI(qi);
+ }
+}
+
+void ViewMapBuilder::BuildGrid(WingedEdge& we, const BBox<Vec3r>& bbox, unsigned int sceneNumFaces)
+{
+ _Grid->clear();
+ Vec3r size;
+ for (unsigned int i = 0; i < 3; i++) {
+ size[i] = fabs(bbox.getMax()[i] - bbox.getMin()[i]);
+ // let make the grid 1/10 bigger to avoid numerical errors while computing triangles/cells intersections.
+ size[i] += size[i] / 10.0;
+ if (size[i] == 0) {
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "Warning: the bbox size is 0 in dimension " << i << endl;
+ }
+ }
+ }
+ _Grid->configure(Vec3r(bbox.getMin() - size / 20.0), size, sceneNumFaces);
+
+ // Fill in the grid:
+ WFillGrid fillGridRenderer(_Grid, &we);
+ fillGridRenderer.fillGrid();
+
+ // DEBUG
+ _Grid->displayDebug();
+}
+
+ViewMap *ViewMapBuilder::BuildViewMap(WingedEdge& we, visibility_algo iAlgo, real epsilon,
+ const BBox<Vec3r>& bbox, unsigned int sceneNumFaces)
+{
+ _ViewMap = new ViewMap;
+ _currentId = 1;
+ _currentFId = 0;
+ _currentSVertexId = 0;
+
+ // Builds initial view edges
+ computeInitialViewEdges(we);
+
+ // Detects cusps
+ computeCusps(_ViewMap);
+
+ // Compute intersections
+ ComputeIntersections(_ViewMap, sweep_line, epsilon);
+
+ // Compute visibility
+ ComputeEdgesVisibility(_ViewMap, we, bbox, sceneNumFaces, iAlgo, epsilon);
+
+ return _ViewMap;
+}
+
+static inline real distance2D(const Vec3r & point, const real origin[2])
+{
+ return ::hypot((point[0] - origin[0]), (point[1] - origin[1]));
+}
+
+static inline bool crossesProscenium(real proscenium[4], FEdge *fe)
+{
+ Vec2r min(proscenium[0], proscenium[2]);
+ Vec2r max(proscenium[1], proscenium[3]);
+ Vec2r A(fe->vertexA()->getProjectedX(), fe->vertexA()->getProjectedY());
+ Vec2r B(fe->vertexB()->getProjectedX(), fe->vertexB()->getProjectedY());
+
+ return GeomUtils::intersect2dSeg2dArea (min, max, A, B);
+}
+
+static inline bool insideProscenium(real proscenium[4], const Vec3r& point)
+{
+ return !(point[0] < proscenium[0] || point[0] > proscenium[1] ||
+ point[1] < proscenium[2] || point[1] > proscenium[3]);
+}
+
+void ViewMapBuilder::CullViewEdges(ViewMap *ioViewMap, real viewProscenium[4], real occluderProscenium[4],
+ bool extensiveFEdgeSearch)
+{
+ // Cull view edges by marking them as non-displayable.
+ // This avoids the complications of trying to delete edges from the ViewMap.
+
+ // Non-displayable view edges will be skipped over during visibility calculation.
+
+ // View edges will be culled according to their position w.r.t. the viewport proscenium (viewport + 5% border,
+ // or some such).
+
+ // Get proscenium boundary for culling
+ GridHelpers::getDefaultViewProscenium(viewProscenium);
+ real prosceniumOrigin[2];
+ prosceniumOrigin[0] = (viewProscenium[1] - viewProscenium[0]) / 2.0;
+ prosceniumOrigin[1] = (viewProscenium[3] - viewProscenium[2]) / 2.0;
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "Proscenium culling:" << endl;
+ cout << "Proscenium: [" << viewProscenium[0] << ", " << viewProscenium[1] << ", " << viewProscenium[2] <<
+ ", " << viewProscenium[3] << "]"<< endl;
+ cout << "Origin: [" << prosceniumOrigin[0] << ", " << prosceniumOrigin[1] << "]"<< endl;
+ }
+
+ // A separate occluder proscenium will also be maintained, starting out the same as the viewport proscenium, and
+ // expanding as necessary so that it encompasses the center point of at least one feature edge in each retained view
+ // edge.
+ // The occluder proscenium will be used later to cull occluding triangles before they are inserted into the Grid.
+ // The occluder proscenium starts out the same size as the view proscenium
+ GridHelpers::getDefaultViewProscenium(occluderProscenium);
+
+ // N.B. Freestyle is inconsistent in its use of ViewMap::viewedges_container and vector<ViewEdge*>::iterator.
+ // Probably all occurences of vector<ViewEdge*>::iterator should be replaced ViewMap::viewedges_container
+ // throughout the code.
+ // For each view edge
+ ViewMap::viewedges_container::iterator ve, veend;
+
+ for (ve = ioViewMap->ViewEdges().begin(), veend = ioViewMap->ViewEdges().end(); ve != veend; ve++) {
+ // Overview:
+ // Search for a visible feature edge
+ // If none: mark view edge as non-displayable
+ // Otherwise:
+ // Find a feature edge with center point inside occluder proscenium.
+ // If none exists, find the feature edge with center point closest to viewport origin.
+ // Expand occluder proscenium to enclose center point.
+
+ // For each feature edge, while bestOccluderTarget not found and view edge not visibile
+ bool bestOccluderTargetFound = false;
+ FEdge *bestOccluderTarget = NULL;
+ real bestOccluderDistance = 0.0;
+ FEdge *festart = (*ve)->fedgeA();
+ FEdge *fe = festart;
+ // All ViewEdges start culled
+ (*ve)->setIsInImage(false);
+
+ // For simple visibility calculation: mark a feature edge that is known to have a center point inside the
+ // occluder proscenium. Cull all other feature edges.
+ do {
+ // All FEdges start culled
+ fe->setIsInImage(false);
+
+ // Look for the visible edge that can most easily be included in the occluder proscenium.
+ if (!bestOccluderTargetFound) {
+ // If center point is inside occluder proscenium,
+ if (insideProscenium(occluderProscenium, fe->center2d())) {
+ // Use this feature edge for visibility deterimination
+ fe->setIsInImage(true);
+ // Mark bestOccluderTarget as found
+ bestOccluderTargetFound = true;
+ bestOccluderTarget = fe;
+ }
+ else {
+ real d = distance2D(fe->center2d(), prosceniumOrigin);
+ // If center point is closer to viewport origin than current target
+ if (bestOccluderTarget == NULL || d < bestOccluderDistance) {
+ // Then store as bestOccluderTarget
+ bestOccluderDistance = d;
+ bestOccluderTarget = fe;
+ }
+ }
+ }
+
+ // If feature edge crosses the view proscenium
+ if (!(*ve)->isInImage() && crossesProscenium(viewProscenium, fe)) {
+ // Then the view edge will be included in the image
+ (*ve)->setIsInImage(true);
+ }
+ fe = fe->nextEdge();
+ } while (fe && fe != festart && !(bestOccluderTargetFound && (*ve)->isInImage()));
+
+ // Either we have run out of FEdges, or we already have the one edge we need to determine visibility
+ // Cull all remaining edges.
+ while (fe && fe != festart) {
+ fe->setIsInImage(false);
+ fe = fe->nextEdge();
+ }
+
+ // If bestOccluderTarget was not found inside the occluder proscenium, we need to expand the occluder
+ // proscenium to include it.
+ if ((*ve)->isInImage() && bestOccluderTarget != NULL && !bestOccluderTargetFound) {
+ // Expand occluder proscenium to enclose bestOccluderTarget
+ Vec3r point = bestOccluderTarget->center2d();
+ if (point[0] < occluderProscenium[0]) {
+ occluderProscenium[0] = point[0];
+ }
+ else if (point[0] > occluderProscenium[1]) {
+ occluderProscenium[1] = point[0];
+ }
+ if (point[1] < occluderProscenium[2]) {
+ occluderProscenium[2] = point[1];
+ }
+ else if (point[1] > occluderProscenium[3]) {
+ occluderProscenium[3] = point[1];
+ }
+ // Use bestOccluderTarget for visibility determination
+ bestOccluderTarget->setIsInImage(true);
+ }
+ }
+
+ // We are done calculating the occluder proscenium.
+ // Expand the occluder proscenium by an epsilon to avoid rounding errors.
+ const real epsilon = 1.0e-6;
+ occluderProscenium[0] -= epsilon;
+ occluderProscenium[1] += epsilon;
+ occluderProscenium[2] -= epsilon;
+ occluderProscenium[3] += epsilon;
+
+ // For "Normal" or "Fast" style visibility computation only:
+
+ // For more detailed visibility calculation, make a second pass through the view map, marking all feature edges
+ // with center points inside the final occluder proscenium. All of these feature edges can be considered during
+ // visibility calculation.
+
+ // So far we have only found one FEdge per ViewEdge. The "Normal" and "Fast" styles of visibility computation
+ // want to consider many FEdges for each ViewEdge.
+ // Here we re-scan the view map to find any usable FEdges that we skipped on the first pass, or that have become
+ // usable because the occluder proscenium has been expanded since the edge was visited on the first pass.
+ if (extensiveFEdgeSearch) {
+ // For each view edge,
+ for (ve = ioViewMap->ViewEdges().begin(), veend = ioViewMap->ViewEdges().end(); ve != veend; ve++) {
+ if (!(*ve)->isInImage()) {
+ continue;
+ }
+ // For each feature edge,
+ FEdge *festart = (*ve)->fedgeA();
+ FEdge *fe = festart;
+ do {
+ // If not (already) visible and center point inside occluder proscenium,
+ if (!fe->isInImage() && insideProscenium(occluderProscenium, fe->center2d())) {
+ // Use the feature edge for visibility determination
+ fe->setIsInImage(true);
+ }
+ fe = fe->nextEdge();
+ } while (fe && fe != festart);
+ }
+ }
+}
+
+void ViewMapBuilder::computeInitialViewEdges(WingedEdge& we)
+{
+ vector<WShape*> wshapes = we.getWShapes();
+ SShape *psShape;
+
+ for (vector<WShape*>::const_iterator it = wshapes.begin(); it != wshapes.end(); it++) {
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ break;
+
+ // create the embedding
+ psShape = new SShape;
+ psShape->setId((*it)->GetId());
+ psShape->setName((*it)->getName());
+ psShape->setFrsMaterials((*it)->frs_materials()); // FIXME
+
+ // create the view shape
+ ViewShape *vshape = new ViewShape(psShape);
+ // add this view shape to the view map:
+ _ViewMap->AddViewShape(vshape);
+
+ // we want to number the view edges in a unique way for the while scene.
+ _pViewEdgeBuilder->setCurrentViewId(_currentId);
+ // we want to number the feature edges in a unique way for the while scene.
+ _pViewEdgeBuilder->setCurrentFId(_currentFId);
+ // we want to number the SVertex in a unique way for the while scene.
+ _pViewEdgeBuilder->setCurrentSVertexId(_currentFId);
+ _pViewEdgeBuilder->BuildViewEdges(dynamic_cast<WXShape*>(*it), vshape, _ViewMap->ViewEdges(),
+ _ViewMap->ViewVertices(), _ViewMap->FEdges(), _ViewMap->SVertices());
+
+ _currentId = _pViewEdgeBuilder->currentViewId() + 1;
+ _currentFId = _pViewEdgeBuilder->currentFId() + 1;
+ _currentSVertexId = _pViewEdgeBuilder->currentSVertexId() + 1;
+
+ psShape->ComputeBBox();
+ }
+}
+
+void ViewMapBuilder::computeCusps(ViewMap *ioViewMap)
+{
+ vector<ViewVertex*> newVVertices;
+ vector<ViewEdge*> newVEdges;
+ ViewMap::viewedges_container& vedges = ioViewMap->ViewEdges();
+ ViewMap::viewedges_container::iterator ve = vedges.begin(), veend = vedges.end();
+ for (; ve != veend; ++ve) {
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ break;
+ if ((!((*ve)->getNature() & Nature::SILHOUETTE)) || (!((*ve)->fedgeA()->isSmooth())))
+ continue;
+ FEdge *fe = (*ve)->fedgeA();
+ FEdge *fefirst = fe;
+ bool first = true;
+ bool positive = true;
+ do {
+ FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth*>(fe);
+ Vec3r A((fes)->vertexA()->point3d());
+ Vec3r B((fes)->vertexB()->point3d());
+ Vec3r AB(B - A);
+ AB.normalize();
+ Vec3r m((A + B) / 2.0);
+ Vec3r crossP(AB ^ (fes)->normal());
+ crossP.normalize();
+ Vec3r viewvector;
+ if (_orthographicProjection) {
+ viewvector = Vec3r(0.0, 0.0, m.z() - _viewpoint.z());
+ }
+ else {
+ viewvector = Vec3r(m - _viewpoint);
+ }
+ viewvector.normalize();
+ if (first) {
+ if (((crossP) * (viewvector)) > 0)
+ positive = true;
+ else
+ positive = false;
+ first = false;
+ }
+ // If we're in a positive part, we need a stronger negative value to change
+ NonTVertex *cusp = NULL;
+ if (positive) {
+ if (((crossP) * (viewvector)) < -0.1) {
+ // state changes
+ positive = false;
+ // creates and insert cusp
+ cusp = dynamic_cast<NonTVertex*>(ioViewMap->InsertViewVertex(fes->vertexA(), newVEdges));
+ if (cusp)
+ cusp->setNature(cusp->getNature() | Nature::CUSP);
+ }
+ }
+ else {
+ // If we're in a negative part, we need a stronger negative value to change
+ if (((crossP) * (viewvector)) > 0.1) {
+ positive = true;
+ cusp = dynamic_cast<NonTVertex*>(ioViewMap->InsertViewVertex(fes->vertexA(), newVEdges));
+ if (cusp)
+ cusp->setNature(cusp->getNature() | Nature::CUSP);
+ }
+ }
+ fe = fe->nextEdge();
+ } while (fe && fe != fefirst);
+ }
+ for (ve = newVEdges.begin(), veend = newVEdges.end(); ve != veend; ++ve) {
+ (*ve)->viewShape()->AddEdge(*ve);
+ vedges.push_back(*ve);
+ }
+}
+
+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;
+
+ if (_orthographicProjection) {
+ transform.reset(new BoxGrid::Transform);
+ }
+ else {
+ transform.reset(new SphericalGrid::Transform);
+ }
+
+ if (cull) {
+ source.reset(new CulledOccluderSource(*transform, we, *ioViewMap, true));
+ }
+ else {
+ source.reset(new OccluderSource(*transform, we));
+ }
+
+ auto_ptr<GridDensityProvider> density(factory.newGridDensityProvider(*source, bbox, *transform));
+
+ if (_orthographicProjection) {
+ BoxGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI);
+ computeCumulativeVisibility<BoxGrid, BoxGrid::Iterator>(ioViewMap, grid, epsilon, _pRenderMonitor);
+ }
+ else {
+ SphericalGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI);
+ computeCumulativeVisibility<SphericalGrid, SphericalGrid::Iterator>(ioViewMap, grid, epsilon, _pRenderMonitor);
+ }
+}
+
+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;
+
+ if (_orthographicProjection) {
+ transform.reset(new BoxGrid::Transform);
+ }
+ else {
+ transform.reset(new SphericalGrid::Transform);
+ }
+
+ if (cull) {
+ source.reset(new CulledOccluderSource(*transform, we, *ioViewMap, true));
+ }
+ else {
+ source.reset(new OccluderSource(*transform, we));
+ }
+
+ auto_ptr<GridDensityProvider> density(factory.newGridDensityProvider(*source, bbox, *transform));
+
+ if (_orthographicProjection) {
+ BoxGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI);
+ computeDetailedVisibility<BoxGrid, BoxGrid::Iterator>(ioViewMap, grid, epsilon, _pRenderMonitor);
+ }
+ else {
+ SphericalGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI);
+ computeDetailedVisibility<SphericalGrid, SphericalGrid::Iterator>(ioViewMap, grid, epsilon, _pRenderMonitor);
+ }
+}
+
+void ViewMapBuilder::ComputeEdgesVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox<Vec3r>& bbox,
+ unsigned int sceneNumFaces, visibility_algo iAlgo, real epsilon)
+{
+ switch (iAlgo) {
+ case ray_casting:
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "Using ordinary ray casting" << endl;
+ }
+ BuildGrid(we, bbox, sceneNumFaces);
+ ComputeRayCastingVisibility(ioViewMap, epsilon);
+ break;
+ case ray_casting_fast:
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "Using fast ray casting" << endl;
+ }
+ BuildGrid(we, bbox, sceneNumFaces);
+ ComputeFastRayCastingVisibility(ioViewMap, epsilon);
+ break;
+ case ray_casting_very_fast:
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "Using very fast ray casting" << endl;
+ }
+ BuildGrid(we, bbox, sceneNumFaces);
+ ComputeVeryFastRayCastingVisibility(ioViewMap, epsilon);
+ break;
+ case ray_casting_culled_adaptive_traditional:
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "Using culled adaptive grid with heuristic density and traditional QI calculation" << endl;
+ }
+ try {
+ HeuristicGridDensityProviderFactory factory(0.5f, sceneNumFaces);
+ ComputeDetailedVisibility(ioViewMap, we, bbox, epsilon, true, factory);
+ }
+ catch (...) {
+ // Last resort catch to make sure RAII semantics hold for OptimizedGrid. Can be replaced with
+ // try...catch block around main() if the program as a whole is converted to RAII
+
+ // This is the little-mentioned caveat of RAII: RAII does not work unless destructors are always
+ // called, but destructors are only called if all exceptions are caught (or std::terminate() is
+ // replaced).
+
+ // We don't actually handle the exception here, so re-throw it now that our destructors have had a
+ // chance to run.
+ throw;
+ }
+ break;
+ case ray_casting_adaptive_traditional:
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "Using unculled adaptive grid with heuristic density and traditional QI calculation" << endl;
+ }
+ try {
+ HeuristicGridDensityProviderFactory factory(0.5f, sceneNumFaces);
+ ComputeDetailedVisibility(ioViewMap, we, bbox, epsilon, false, factory);
+ }
+ catch (...) {
+ throw;
+ }
+ break;
+ case ray_casting_culled_adaptive_cumulative:
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "Using culled adaptive grid with heuristic density and cumulative QI calculation" << endl;
+ }
+ try {
+ HeuristicGridDensityProviderFactory factory(0.5f, sceneNumFaces);
+ ComputeCumulativeVisibility(ioViewMap, we, bbox, epsilon, true, factory);
+ }
+ catch (...) {
+ throw;
+ }
+ break;
+ case ray_casting_adaptive_cumulative:
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "Using unculled adaptive grid with heuristic density and cumulative QI calculation" << endl;
+ }
+ try {
+ HeuristicGridDensityProviderFactory factory(0.5f, sceneNumFaces);
+ ComputeCumulativeVisibility(ioViewMap, we, bbox, epsilon, false, factory);
+ }
+ catch (...) {
+ throw;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static const unsigned gProgressBarMaxSteps = 10;
+static const unsigned gProgressBarMinSize = 2000;
+
+void ViewMapBuilder::ComputeRayCastingVisibility(ViewMap *ioViewMap, real epsilon)
+{
+ vector<ViewEdge*>& vedges = ioViewMap->ViewEdges();
+ bool progressBarDisplay = false;
+ unsigned progressBarStep = 0;
+ unsigned vEdgesSize = vedges.size();
+ unsigned fEdgesSize = ioViewMap->FEdges().size();
+
+ if (_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) {
+ unsigned progressBarSteps = min(gProgressBarMaxSteps, vEdgesSize);
+ progressBarStep = vEdgesSize / progressBarSteps;
+ _pProgressBar->reset();
+ _pProgressBar->setLabelText("Computing Ray casting Visibility");
+ _pProgressBar->setTotalSteps(progressBarSteps);
+ _pProgressBar->setProgress(0);
+ progressBarDisplay = true;
+ }
+
+ unsigned counter = progressBarStep;
+ FEdge *fe, *festart;
+ int nSamples = 0;
+ vector<Polygon3r*> aFaces;
+ Polygon3r *aFace = NULL;
+ unsigned tmpQI = 0;
+ unsigned qiClasses[256];
+ unsigned maxIndex, maxCard;
+ unsigned qiMajority;
+ static unsigned timestamp = 1;
+ for (vector<ViewEdge*>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) {
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ break;
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "Processing ViewEdge " << (*ve)->getId() << endl;
+ }
+#endif
+ festart = (*ve)->fedgeA();
+ fe = (*ve)->fedgeA();
+ qiMajority = 1;
+ do {
+ qiMajority++;
+ fe = fe->nextEdge();
+ } while (fe && fe != festart);
+ qiMajority >>= 1;
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tqiMajority: " << qiMajority << endl;
+ }
+#endif
+
+ tmpQI = 0;
+ maxIndex = 0;
+ maxCard = 0;
+ nSamples = 0;
+ fe = (*ve)->fedgeA();
+ memset(qiClasses, 0, 256 * sizeof(*qiClasses));
+ set<ViewShape*> occluders;
+ do {
+ if ((maxCard < qiMajority)) {
+ tmpQI = ComputeRayCastingVisibility(fe, _Grid, epsilon, occluders, &aFace, timestamp++);
+
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tFEdge: visibility " << tmpQI << endl;
+ }
+#endif
+ //ARB: This is an error condition, not an alert condition.
+ // Some sort of recovery or abort is necessary.
+ if (tmpQI >= 256) {
+ cerr << "Warning: too many occluding levels" << endl;
+ //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255
+ tmpQI = 255;
+ }
+
+ if (++qiClasses[tmpQI] > maxCard) {
+ maxCard = qiClasses[tmpQI];
+ maxIndex = tmpQI;
+ }
+ }
+ else {
+ //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called
+ FindOccludee(fe, _Grid, epsilon, &aFace, timestamp++);
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tFEdge: occludee only (" << (aFace != NULL ? "found" : "not found") << ")" << endl;
+ }
+#endif
+ }
+
+ if (aFace) {
+ fe->setaFace(*aFace);
+ aFaces.push_back(aFace);
+ fe->setOccludeeEmpty(false);
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tFound occludee" << endl;
+ }
+#endif
+ }
+ else {
+ //ARB: We are arbitrarily using the last observed value for occludee (almost always the value observed
+ // for the edge before festart). Is that meaningful?
+ // ...in fact, _occludeeEmpty seems to be unused.
+ fe->setOccludeeEmpty(true);
+ }
+
+ ++nSamples;
+ fe = fe->nextEdge();
+ } while ((maxCard < qiMajority) && (fe) && (fe != festart));
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tFinished with " << nSamples << " samples, maxCard = " << maxCard << endl;
+ }
+#endif
+
+ // ViewEdge
+ // qi --
+ (*ve)->setQI(maxIndex);
+ // occluders --
+ for (set<ViewShape*>::iterator o = occluders.begin(), oend = occluders.end(); o != oend; ++o)
+ (*ve)->AddOccluder((*o));
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\tConclusion: QI = " << maxIndex << ", " << (*ve)->occluders_size() << " occluders." << endl;
+ }
+#endif
+ // occludee --
+ if (!aFaces.empty()) {
+ if (aFaces.size() <= (float)nSamples / 2.0f) {
+ (*ve)->setaShape(0);
+ }
+ else {
+ vector<Polygon3r*>::iterator p = aFaces.begin();
+ WFace *wface = (WFace *)((*p)->userdata);
+ ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId());
+ ++p;
+ (*ve)->setaShape(vshape);
+ }
+ }
+
+ if (progressBarDisplay) {
+ counter--;
+ if (counter <= 0) {
+ counter = progressBarStep;
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+ }
+ }
+ aFaces.clear();
+ }
+}
+
+void ViewMapBuilder::ComputeFastRayCastingVisibility(ViewMap *ioViewMap, real epsilon)
+{
+ vector<ViewEdge*>& vedges = ioViewMap->ViewEdges();
+ bool progressBarDisplay = false;
+ unsigned progressBarStep = 0;
+ unsigned vEdgesSize = vedges.size();
+ unsigned fEdgesSize = ioViewMap->FEdges().size();
+
+ if (_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) {
+ unsigned progressBarSteps = min(gProgressBarMaxSteps, vEdgesSize);
+ progressBarStep = vEdgesSize / progressBarSteps;
+ _pProgressBar->reset();
+ _pProgressBar->setLabelText("Computing Ray casting Visibility");
+ _pProgressBar->setTotalSteps(progressBarSteps);
+ _pProgressBar->setProgress(0);
+ progressBarDisplay = true;
+ }
+
+ unsigned counter = progressBarStep;
+ FEdge *fe, *festart;
+ unsigned nSamples = 0;
+ vector<Polygon3r*> aFaces;
+ Polygon3r *aFace = NULL;
+ unsigned tmpQI = 0;
+ unsigned qiClasses[256];
+ unsigned maxIndex, maxCard;
+ unsigned qiMajority;
+ static unsigned timestamp = 1;
+ bool even_test;
+ for (vector<ViewEdge*>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) {
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ break;
+
+ festart = (*ve)->fedgeA();
+ fe = (*ve)->fedgeA();
+ qiMajority = 1;
+ do {
+ qiMajority++;
+ fe = fe->nextEdge();
+ } while (fe && fe != festart);
+ if (qiMajority >= 4)
+ qiMajority >>= 2;
+ else
+ qiMajority = 1;
+
+ set<ViewShape*> occluders;
+
+ even_test = true;
+ maxIndex = 0;
+ maxCard = 0;
+ nSamples = 0;
+ memset(qiClasses, 0, 256 * sizeof(*qiClasses));
+ fe = (*ve)->fedgeA();
+ do {
+ if (even_test) {
+ if ((maxCard < qiMajority)) {
+ tmpQI = ComputeRayCastingVisibility(fe, _Grid, epsilon, occluders, &aFace, timestamp++);
+
+ //ARB: This is an error condition, not an alert condition.
+ // Some sort of recovery or abort is necessary.
+ if (tmpQI >= 256) {
+ cerr << "Warning: too many occluding levels" << endl;
+ //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255
+ tmpQI = 255;
+ }
+
+ if (++qiClasses[tmpQI] > maxCard) {
+ maxCard = qiClasses[tmpQI];
+ maxIndex = tmpQI;
+ }
+ }
+ else {
+ //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called
+ FindOccludee(fe, _Grid, epsilon, &aFace, timestamp++);
+ }
+
+ if (aFace) {
+ fe->setaFace(*aFace);
+ aFaces.push_back(aFace);
+ }
+ ++nSamples;
+ even_test = false;
+ }
+ else {
+ even_test = true;
+ }
+ fe = fe->nextEdge();
+ } while ((maxCard < qiMajority) && (fe) && (fe != festart));
+
+ (*ve)->setQI(maxIndex);
+
+ if (!aFaces.empty()) {
+ if (aFaces.size() < nSamples / 2) {
+ (*ve)->setaShape(0);
+ }
+ else {
+ vector<Polygon3r*>::iterator p = aFaces.begin();
+ WFace *wface = (WFace *)((*p)->userdata);
+ ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId());
+ ++p;
+#if 0
+ for (; p != pend; ++p) {
+ WFace *f = (WFace*)((*p)->userdata);
+ ViewShape *vs = ioViewMap->viewShape(f->GetVertex(0)->shape()->GetId());
+ if (vs != vshape) {
+ sameShape = false;
+ break;
+ }
+ }
+ if (sameShape)
+#endif
+ (*ve)->setaShape(vshape);
+ }
+ }
+
+ //(*ve)->setaFace(aFace);
+
+ if (progressBarDisplay) {
+ counter--;
+ if (counter <= 0) {
+ counter = progressBarStep;
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+ }
+ }
+ aFaces.clear();
+ }
+}
+
+void ViewMapBuilder::ComputeVeryFastRayCastingVisibility(ViewMap *ioViewMap, real epsilon)
+{
+ vector<ViewEdge*>& vedges = ioViewMap->ViewEdges();
+ bool progressBarDisplay = false;
+ unsigned progressBarStep = 0;
+ unsigned vEdgesSize = vedges.size();
+ unsigned fEdgesSize = ioViewMap->FEdges().size();
+
+ if (_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) {
+ unsigned progressBarSteps = min(gProgressBarMaxSteps, vEdgesSize);
+ progressBarStep = vEdgesSize / progressBarSteps;
+ _pProgressBar->reset();
+ _pProgressBar->setLabelText("Computing Ray casting Visibility");
+ _pProgressBar->setTotalSteps(progressBarSteps);
+ _pProgressBar->setProgress(0);
+ progressBarDisplay = true;
+ }
+
+ unsigned counter = progressBarStep;
+ FEdge *fe;
+ unsigned qi = 0;
+ Polygon3r *aFace = NULL;
+ static unsigned timestamp = 1;
+ for (vector<ViewEdge*>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) {
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ break;
+
+ set<ViewShape*> occluders;
+
+ fe = (*ve)->fedgeA();
+ qi = ComputeRayCastingVisibility(fe, _Grid, epsilon, occluders, &aFace, timestamp++);
+ if (aFace) {
+ fe->setaFace(*aFace);
+ WFace *wface = (WFace *)(aFace->userdata);
+ ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId());
+ (*ve)->setaShape(vshape);
+ }
+ else {
+ (*ve)->setaShape(0);
+ }
+
+ (*ve)->setQI(qi);
+
+ if (progressBarDisplay) {
+ counter--;
+ if (counter <= 0) {
+ counter = progressBarStep;
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+ }
+ }
+ }
+}
+
+void ViewMapBuilder::FindOccludee(FEdge *fe, Grid *iGrid, real epsilon, Polygon3r **oaPolygon, unsigned timestamp,
+ Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edge, vector<WVertex*>& faceVertices)
+{
+ WFace *face = NULL;
+ if (fe->isSmooth()) {
+ FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth*>(fe);
+ face = (WFace *)fes->face();
+ }
+ OccludersSet occluders;
+ WFace *oface;
+ bool skipFace;
+
+ WVertex::incoming_edge_iterator ie;
+ OccludersSet::iterator p, pend;
+
+ *oaPolygon = NULL;
+ if (((fe)->getNature() & Nature::SILHOUETTE) || ((fe)->getNature() & Nature::BORDER)) {
+ occluders.clear();
+ // we cast a ray from A in the same direction but looking behind
+ Vec3r v(-u[0], -u[1], -u[2]);
+ iGrid->castInfiniteRay(A, v, occluders, timestamp);
+
+ bool noIntersection = true;
+ real mint = FLT_MAX;
+ // we met some occluders, let us fill the aShape field with the first intersected occluder
+ for (p = occluders.begin(), pend = occluders.end(); p != pend; p++) {
+ // check whether the edge and the polygon plane are coincident:
+ //-------------------------------------------------------------
+ //first let us compute the plane equation.
+ oface = (WFace *)(*p)->userdata;
+ Vec3r v1(((*p)->getVertices())[0]);
+ Vec3r normal((*p)->getNormal());
+ real d = -(v1 * normal);
+ real t, t_u, t_v;
+
+ if (face) {
+ skipFace = false;
+
+ if (face == oface)
+ continue;
+
+ if (faceVertices.empty())
+ continue;
+
+ for (vector<WVertex*>::iterator fv = faceVertices.begin(), fvend = faceVertices.end();
+ fv != fvend;
+ ++fv)
+ {
+ if ((*fv)->isBoundary())
+ continue;
+ WVertex::incoming_edge_iterator iebegin = (*fv)->incoming_edges_begin();
+ WVertex::incoming_edge_iterator ieend = (*fv)->incoming_edges_end();
+ for (ie = iebegin; ie != ieend; ++ie) {
+ if ((*ie) == 0)
+ continue;
+
+ WFace *sface = (*ie)->GetbFace();
+ if (sface == oface) {
+ skipFace = true;
+ break;
+ }
+ }
+ if (skipFace)
+ break;
+ }
+ if (skipFace)
+ continue;
+ }
+ else {
+ if (GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edge, normal, d, t, epsilon))
+ continue;
+ }
+ if ((*p)->rayIntersect(A, v, t, t_u, t_v)) {
+ if (fabs(v * normal) > 0.0001) {
+ if (t > 0.0) { // && t < 1.0) {
+ if (t < mint) {
+ *oaPolygon = (*p);
+ mint = t;
+ noIntersection = false;
+ fe->setOccludeeIntersection(Vec3r(A + t * v));
+ }
+ }
+ }
+ }
+ }
+
+ if (noIntersection)
+ *oaPolygon = NULL;
+ }
+}
+
+void ViewMapBuilder::FindOccludee(FEdge *fe, Grid *iGrid, real epsilon, Polygon3r **oaPolygon, unsigned timestamp)
+{
+ OccludersSet occluders;
+
+ Vec3r A;
+ Vec3r edge;
+ Vec3r origin;
+ A = Vec3r(((fe)->vertexA()->point3D() + (fe)->vertexB()->point3D()) / 2.0);
+ edge = Vec3r((fe)->vertexB()->point3D() - (fe)->vertexA()->point3D());
+ origin = Vec3r((fe)->vertexA()->point3D());
+ Vec3r u;
+ if (_orthographicProjection) {
+ u = Vec3r(0.0, 0.0, _viewpoint.z() - A.z());
+ }
+ else {
+ u = Vec3r(_viewpoint - A);
+ }
+ u.normalize();
+ if (A < iGrid->getOrigin())
+ cerr << "Warning: point is out of the grid for fedge " << fe->getId().getFirst() << "-" <<
+ fe->getId().getSecond() << endl;
+
+ vector<WVertex*> faceVertices;
+
+ WFace *face = NULL;
+ if (fe->isSmooth()) {
+ FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth*>(fe);
+ face = (WFace *)fes->face();
+ }
+ if (face)
+ face->RetrieveVertexList(faceVertices);
+
+ return FindOccludee(fe, iGrid, epsilon, oaPolygon, timestamp, u, A, origin, edge, faceVertices);
+}
+
+int ViewMapBuilder::ComputeRayCastingVisibility(FEdge *fe, Grid *iGrid, real epsilon, set<ViewShape*>& oOccluders,
+ Polygon3r **oaPolygon, unsigned timestamp)
+{
+ OccludersSet occluders;
+ int qi = 0;
+
+ Vec3r center;
+ Vec3r edge;
+ Vec3r origin;
+
+ center = fe->center3d();
+ edge = Vec3r(fe->vertexB()->point3D() - fe->vertexA()->point3D());
+ origin = Vec3r(fe->vertexA()->point3D());
+ // Is the edge outside the view frustum ?
+ Vec3r gridOrigin(iGrid->getOrigin());
+ Vec3r gridExtremity(iGrid->getOrigin() + iGrid->gridSize());
+
+ if ((center.x() < gridOrigin.x()) || (center.y() < gridOrigin.y()) || (center.z() < gridOrigin.z()) ||
+ (center.x() > gridExtremity.x()) || (center.y() > gridExtremity.y()) || (center.z() > gridExtremity.z()))
+ {
+ cerr << "Warning: point is out of the grid for fedge " << fe->getId() << endl;
+ //return 0;
+ }
+
+#if 0
+ Vec3r A(fe->vertexA()->point2d());
+ Vec3r B(fe->vertexB()->point2d());
+ int viewport[4];
+ SilhouetteGeomEngine::retrieveViewport(viewport);
+ if ((A.x() < viewport[0]) || (A.x() > viewport[2]) || (A.y() < viewport[1]) || (A.y() > viewport[3]) ||
+ (B.x() < viewport[0]) || (B.x() > viewport[2]) || (B.y() < viewport[1]) || (B.y() > viewport[3])) {
+ cerr << "Warning: point is out of the grid for fedge " << fe->getId() << endl;
+ //return 0;
+ }
+#endif
+
+ Vec3r vp;
+ if (_orthographicProjection) {
+ vp = Vec3r(center.x(), center.y(), _viewpoint.z());
+ }
+ else {
+ vp = Vec3r(_viewpoint);
+ }
+ Vec3r u(vp - center);
+ real raylength = u.norm();
+ u.normalize();
+#if 0
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "grid origin " << iGrid->getOrigin().x() << "," << iGrid->getOrigin().y() << ","
+ << iGrid->getOrigin().z() << endl;
+ cout << "center " << center.x() << "," << center.y() << "," << center.z() << endl;
+ }
+#endif
+
+ iGrid->castRay(center, vp, occluders, timestamp);
+
+ WFace *face = NULL;
+ if (fe->isSmooth()) {
+ FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth *>(fe);
+ face = (WFace *)fes->face();
+ }
+ vector<WVertex *> faceVertices;
+ WVertex::incoming_edge_iterator ie;
+
+ WFace *oface;
+ bool skipFace;
+ OccludersSet::iterator p, pend;
+ if (face)
+ face->RetrieveVertexList(faceVertices);
+
+ for (p = occluders.begin(), pend = occluders.end(); p != pend; p++) {
+ // If we're dealing with an exact silhouette, check whether we must take care of this occluder of not.
+ // (Indeed, we don't consider the occluders that share at least one vertex with the face containing this edge).
+ //-----------
+ oface = (WFace *)(*p)->userdata;
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\t\tEvaluating intersection for occluder " << ((*p)->getVertices())[0] <<
+ ((*p)->getVertices())[1] << ((*p)->getVertices())[2] << endl << "\t\t\tand ray " << vp <<
+ " * " << u << " (center " << center << ")" << endl;
+ }
+#endif
+ Vec3r v1(((*p)->getVertices())[0]);
+ Vec3r normal((*p)->getNormal());
+ real d = -(v1 * normal);
+ real t, t_u, t_v;
+
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\t\tp: " << ((*p)->getVertices())[0] << ((*p)->getVertices())[1] << ((*p)->getVertices())[2] <<
+ ", norm: " << (*p)->getNormal() << endl;
+ }
+#endif
+
+ if (face) {
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\t\tDetermining face adjacency...";
+ }
+#endif
+ skipFace = false;
+
+ if (face == oface) {
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << " Rejecting occluder for face concurrency." << endl;
+ }
+#endif
+ continue;
+ }
+
+ for (vector<WVertex*>::iterator fv = faceVertices.begin(), fvend = faceVertices.end();
+ fv != fvend;
+ ++fv)
+ {
+ if ((*fv)->isBoundary())
+ continue;
+
+ WVertex::incoming_edge_iterator iebegin = (*fv)->incoming_edges_begin();
+ WVertex::incoming_edge_iterator ieend = (*fv)->incoming_edges_end();
+ for (ie = iebegin; ie != ieend; ++ie) {
+ if ((*ie) == 0)
+ continue;
+
+ WFace *sface = (*ie)->GetbFace();
+ //WFace *sfacea = (*ie)->GetaFace();
+ //if ((sface == oface) || (sfacea == oface)) {
+ if (sface == oface) {
+ skipFace = true;
+ break;
+ }
+ }
+ if (skipFace)
+ break;
+ }
+ if (skipFace) {
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << " Rejecting occluder for face adjacency." << endl;
+ }
+#endif
+ continue;
+ }
+ }
+ else {
+ // check whether the edge and the polygon plane are coincident:
+ //-------------------------------------------------------------
+ //first let us compute the plane equation.
+
+ if (GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edge, normal, d, t, epsilon)) {
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\t\tRejecting occluder for target coincidence." << endl;
+ }
+#endif
+ continue;
+ }
+ }
+
+ if ((*p)->rayIntersect(center, u, t, t_u, t_v)) {
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\t\tRay " << vp << " * " << u << " intersects at time " << t << " (raylength is " <<
+ raylength << ")" << endl;
+ cout << "\t\t(u * normal) == " << (u * normal) << " for normal " << normal << endl;
+ }
+#endif
+ if (fabs(u * normal) > 0.0001) {
+ if ((t>0.0) && (t<raylength)) {
+#if LOGGING
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ cout << "\t\tIs occluder" << endl;
+ }
+#endif
+ WFace *f = (WFace *)((*p)->userdata);
+ ViewShape *vshape = _ViewMap->viewShape(f->GetVertex(0)->shape()->GetId());
+ oOccluders.insert(vshape);
+ ++qi;
+ if (!_EnableQI)
+ break;
+ }
+ }
+ }
+ }
+
+ // Find occludee
+ FindOccludee(fe, iGrid, epsilon, oaPolygon, timestamp, u, center, edge, origin, faceVertices);
+
+ return qi;
+}
+
+void ViewMapBuilder::ComputeIntersections(ViewMap *ioViewMap, intersection_algo iAlgo, real epsilon)
+{
+ switch (iAlgo) {
+ case sweep_line:
+ ComputeSweepLineIntersections(ioViewMap, epsilon);
+ break;
+ 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) {
+ cout << "TVertex " << tvertex->getId() << " has :" << endl;
+ cout << "FrontEdgeA: " << tvertex->frontEdgeA().first << endl;
+ cout << "FrontEdgeB: " << tvertex->frontEdgeB().first << endl;
+ cout << "BackEdgeA: " << tvertex->backEdgeA().first << endl;
+ cout << "BackEdgeB: " << tvertex->backEdgeB().first << endl << endl;
+ }
+ }
+ }
+}
+
+struct less_SVertex2D : public binary_function<SVertex *, SVertex *, bool>
+{
+ real epsilon;
+
+ less_SVertex2D(real eps) : binary_function<SVertex *, SVertex *, bool>()
+ {
+ epsilon = eps;
+ }
+
+ bool operator()(SVertex *x, SVertex *y)
+ {
+ Vec3r A = x->point2D();
+ Vec3r B = y->point2D();
+ for (unsigned int i = 0; i < 3; i++) {
+ if ((fabs(A[i] - B[i])) < epsilon)
+ continue;
+ if (A[i] < B[i])
+ return true;
+ if (A[i] > B[i])
+ return false;
+ }
+ return false;
+ }
+};
+
+typedef Segment<FEdge *, Vec3r> segment;
+typedef Intersection<segment> intersection;
+
+struct less_Intersection : public binary_function<intersection *, intersection *, bool>
+{
+ segment *edge;
+
+ less_Intersection(segment *iEdge) : binary_function<intersection *, intersection *, bool>()
+ {
+ edge = iEdge;
+ }
+
+ bool operator()(intersection *x, intersection *y)
+ {
+ real tx = x->getParameter(edge);
+ real ty = y->getParameter(edge);
+ if (tx > ty)
+ return true;
+ return false;
+ }
+};
+
+struct silhouette_binary_rule : public binary_rule<segment, segment>
+{
+ silhouette_binary_rule() : binary_rule<segment, segment>() {}
+
+ virtual bool operator()(segment& s1, segment& s2)
+ {
+ FEdge *f1 = s1.edge();
+ FEdge *f2 = s2.edge();
+
+ if ((!(((f1)->getNature() & Nature::SILHOUETTE) || ((f1)->getNature() & Nature::BORDER))) &&
+ (!(((f2)->getNature() & Nature::SILHOUETTE) || ((f2)->getNature() & Nature::BORDER))))
+ {
+ return false;
+ }
+
+ return true;
+ }
+};
+
+void ViewMapBuilder::ComputeSweepLineIntersections(ViewMap *ioViewMap, real epsilon)
+{
+ vector<SVertex *>& svertices = ioViewMap->SVertices();
+ bool progressBarDisplay = false;
+ unsigned sVerticesSize = svertices.size();
+ unsigned fEdgesSize = ioViewMap->FEdges().size();
+#if 0
+ if (_global.debug & G_DEBUG_FREESTYLE) {
+ ViewMap::fedges_container& fedges = ioViewMap->FEdges();
+ for (ViewMap::fedges_container::const_iterator f = fedges.begin(), end = fedges.end(); f != end; ++f) {
+ cout << (*f)->aMaterialIndex() << "-" << (*f)->bMaterialIndex() << endl;
+ }
+ }
+#endif
+ unsigned progressBarStep = 0;
+
+ if (_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) {
+ unsigned progressBarSteps = min(gProgressBarMaxSteps, sVerticesSize);
+ progressBarStep = sVerticesSize / progressBarSteps;
+ _pProgressBar->reset();
+ _pProgressBar->setLabelText("Computing Sweep Line Intersections");
+ _pProgressBar->setTotalSteps(progressBarSteps);
+ _pProgressBar->setProgress(0);
+ progressBarDisplay = true;
+ }
+
+ unsigned counter = progressBarStep;
+
+ sort(svertices.begin(), svertices.end(), less_SVertex2D(epsilon));
+
+ SweepLine<FEdge *, Vec3r> SL;
+
+ vector<FEdge *>& ioEdges = ioViewMap->FEdges();
+
+ vector<segment*> segments;
+
+ vector<FEdge*>::iterator fe, fend;
+
+ for (fe = ioEdges.begin(), fend = ioEdges.end(); fe != fend; fe++) {
+ segment *s = new segment((*fe), (*fe)->vertexA()->point2D(), (*fe)->vertexB()->point2D());
+ (*fe)->userdata = s;
+ segments.push_back(s);
+ }
+
+ vector<segment*> vsegments;
+ for (vector<SVertex*>::iterator sv = svertices.begin(), svend = svertices.end(); sv != svend; sv++) {
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ break;
+
+ const vector<FEdge*>& vedges = (*sv)->fedges();
+
+ for (vector<FEdge *>::const_iterator sve = vedges.begin(), sveend = vedges.end(); sve != sveend; sve++) {
+ vsegments.push_back((segment *)((*sve)->userdata));
+ }
+
+ Vec3r evt((*sv)->point2D());
+ silhouette_binary_rule sbr;
+ SL.process(evt, vsegments, sbr, epsilon);
+
+ if (progressBarDisplay) {
+ counter--;
+ if (counter <= 0) {
+ counter = progressBarStep;
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+ }
+ }
+ vsegments.clear();
+ }
+
+ if (_pRenderMonitor && _pRenderMonitor->testBreak()) {
+ // delete segments
+ if (!segments.empty()) {
+ vector<segment*>::iterator s, send;
+ for (s = segments.begin(), send = segments.end(); s != send; s++) {
+ delete *s;
+ }
+ }
+ return;
+ }
+
+ // reset userdata:
+ for (fe = ioEdges.begin(), fend = ioEdges.end(); fe != fend; fe++)
+ (*fe)->userdata = NULL;
+
+ // list containing the new edges resulting from splitting operations.
+ vector<FEdge*> newEdges;
+
+ // retrieve the intersected edges:
+ vector<segment*>& iedges = SL.intersectedEdges();
+ // retrieve the intersections:
+ vector<intersection*>& intersections = SL.intersections();
+
+ int id = 0;
+ // create a view vertex for each intersection and linked this one with the intersection object
+ vector<intersection*>::iterator i, iend;
+ for (i = intersections.begin(), iend = intersections.end(); i != iend; i++) {
+ FEdge *fA = (*i)->EdgeA->edge();
+ FEdge *fB = (*i)->EdgeB->edge();
+
+ Vec3r A1 = fA->vertexA()->point3D();
+ Vec3r A2 = fA->vertexB()->point3D();
+ Vec3r B1 = fB->vertexA()->point3D();
+ Vec3r B2 = fB->vertexB()->point3D();
+
+ Vec3r a1 = fA->vertexA()->point2D();
+ Vec3r a2 = fA->vertexB()->point2D();
+ Vec3r b1 = fB->vertexA()->point2D();
+ Vec3r b2 = fB->vertexB()->point2D();
+
+ real ta = (*i)->tA;
+ real tb = (*i)->tB;
+
+ if ((ta < -epsilon) || (ta > 1 + epsilon))
+ cerr << "Warning: 2D intersection out of range for edge " << fA->vertexA()->getId() << " - " <<
+ fA->vertexB()->getId() << endl;
+
+ if ((tb < -epsilon) || (tb > 1 + epsilon))
+ cerr << "Warning: 2D intersection out of range for edge " << fB->vertexA()->getId() << " - " <<
+ fB->vertexB()->getId() << endl;
+
+ real Ta = SilhouetteGeomEngine::ImageToWorldParameter(fA, ta);
+ real Tb = SilhouetteGeomEngine::ImageToWorldParameter(fB, tb);
+
+ if ((Ta < -epsilon) || (Ta > 1 + epsilon))
+ cerr << "Warning: 3D intersection out of range for edge " << fA->vertexA()->getId() << " - " <<
+ fA->vertexB()->getId() << endl;
+
+ if ((Tb < -epsilon) || (Tb > 1 + epsilon))
+ cerr << "Warning: 3D intersection out of range for edge " << fB->vertexA()->getId() << " - " <<
+ fB->vertexB()->getId() << endl;
+
+#if 0
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ if ((Ta < -epsilon) || (Ta > 1 + epsilon) || (Tb < -epsilon) || (Tb > 1 + epsilon)) {
+ printf("ta %.12e\n", ta);
+ printf("tb %.12e\n", tb);
+ printf("a1 %e, %e -- b1 %e, %e\n", a1[0], a1[1], b1[0], b1[1]);
+ printf("a2 %e, %e -- b2 %e, %e\n", a2[0], a2[1], b2[0], b2[1]);
+ if ((Ta < -epsilon) || (Ta > 1 + epsilon))
+ printf("Ta %.12e\n", Ta);
+ if ((Tb < -epsilon) || (Tb > 1 + epsilon))
+ printf("Tb %.12e\n", Tb);
+ printf("A1 %e, %e, %e -- B1 %e, %e, %e\n", A1[0], A1[1], A1[2], B1[0], B1[1], B1[2]);
+ printf("A2 %e, %e, %e -- B2 %e, %e, %e\n", A2[0], A2[1], A2[2], B2[0], B2[1], B2[2]);
+ }
+ }
+#endif
+
+ TVertex *tvertex = ioViewMap->CreateTVertex(Vec3r(A1 + Ta * (A2 - A1)), Vec3r(a1 + ta * (a2 - a1)), fA,
+ Vec3r(B1 + Tb * (B2 - B1)), Vec3r(b1 + tb * (b2 - b1)), fB, id);
+
+ (*i)->userdata = tvertex;
+ ++id;
+ }
+
+ progressBarStep = 0;
+
+ if (progressBarDisplay) {
+ unsigned iEdgesSize = iedges.size();
+ unsigned progressBarSteps = min(gProgressBarMaxSteps, iEdgesSize);
+ progressBarStep = iEdgesSize / progressBarSteps;
+ _pProgressBar->reset();
+ _pProgressBar->setLabelText("Splitting intersected edges");
+ _pProgressBar->setTotalSteps(progressBarSteps);
+ _pProgressBar->setProgress(0);
+ }
+
+ counter = progressBarStep;
+
+ vector<TVertex*> edgeVVertices;
+ vector<ViewEdge*> newVEdges;
+ vector<segment*>::iterator s, send;
+ for (s = iedges.begin(), send = iedges.end(); s != send; s++) {
+ edgeVVertices.clear();
+ newEdges.clear();
+ newVEdges.clear();
+
+ FEdge *fedge = (*s)->edge();
+ ViewEdge *vEdge = fedge->viewedge();
+ ViewShape *shape = vEdge->viewShape();
+
+ vector<intersection*>& eIntersections = (*s)->intersections();
+ // we first need to sort these intersections from farther to closer to A
+ sort(eIntersections.begin(), eIntersections.end(), less_Intersection(*s));
+ for (i = eIntersections.begin(), iend = eIntersections.end(); i != iend; i++)
+ edgeVVertices.push_back((TVertex *)(*i)->userdata);
+
+ shape->SplitEdge(fedge, edgeVVertices, ioViewMap->FEdges(), ioViewMap->ViewEdges());
+
+ if (progressBarDisplay) {
+ counter--;
+ if (counter <= 0) {
+ counter = progressBarStep;
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+ }
+ }
+ }
+
+ // reset userdata:
+ for (fe = ioEdges.begin(), fend = ioEdges.end(); fe != fend; fe++)
+ (*fe)->userdata = NULL;
+
+ // delete segments
+ if (!segments.empty()) {
+ for (s = segments.begin(), send = segments.end(); s != send; s++) {
+ delete *s;
+ }
+ }
+}
diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.h b/source/blender/freestyle/intern/view_map/ViewMapBuilder.h
new file mode 100644
index 00000000000..2d5d24a0ffe
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.h
@@ -0,0 +1,257 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_VIEW_MAP_BUILDER_H__
+#define __FREESTYLE_VIEW_MAP_BUILDER_H__
+
+/** \file blender/freestyle/intern/view_map/ViewMapBuilder.h
+ * \ingroup freestyle
+ * \brief Class to build silhouette edges from a Winged-Edge structure
+ * \author Stephane Grabli
+ * \date 25/03/2002
+ */
+
+#include <vector>
+
+#include "GridDensityProvider.h"
+#include "Silhouette.h"
+#include "SilhouetteGeomEngine.h"
+#include "ViewEdgeXBuilder.h"
+#include "ViewMap.h"
+
+#include "../geometry/Geom.h"
+#include "../geometry/GeomUtils.h"
+#include "../geometry/Grid.h"
+#include "../geometry/SweepLine.h"
+
+#include "../scene_graph/NodeGroup.h"
+#include "../scene_graph/TriangleRep.h"
+
+#include "../system/FreestyleConfig.h"
+#include "../system/ProgressBar.h"
+#include "../system/RenderMonitor.h"
+#include "../system/TimeUtils.h"
+
+#include "../winged_edge/WEdge.h"
+#include "../winged_edge/WXEdge.h"
+
+using namespace Geometry;
+
+class LIB_VIEW_MAP_EXPORT ViewMapBuilder
+{
+private:
+ ViewMap *_ViewMap; // result
+ //SilhouetteGeomEngine _GeomEngine;
+ ProgressBar *_pProgressBar;
+ RenderMonitor *_pRenderMonitor;
+ Vec3r _viewpoint;
+ bool _orthographicProjection;
+ Grid *_Grid;
+ ViewEdgeXBuilder *_pViewEdgeBuilder;
+ bool _EnableQI;
+ double _epsilon;
+
+ // tmp values:
+ int _currentId;
+ int _currentFId;
+ int _currentSVertexId;
+
+public:
+ typedef enum {
+ sweep_line,
+ } intersection_algo;
+
+ typedef enum {
+ ray_casting,
+ ray_casting_fast,
+ ray_casting_very_fast,
+ ray_casting_culled_adaptive_traditional,
+ ray_casting_adaptive_traditional,
+ ray_casting_culled_adaptive_cumulative,
+ ray_casting_adaptive_cumulative,
+ } visibility_algo;
+
+ inline ViewMapBuilder()
+ {
+ _pProgressBar = NULL;
+ _pRenderMonitor = NULL;
+ _Grid = NULL;
+ _currentId = 1;
+ _currentFId = 0;
+ _currentSVertexId = 0;
+ _pViewEdgeBuilder = new ViewEdgeXBuilder;
+ _EnableQI = true;
+ }
+
+ inline ~ViewMapBuilder()
+ {
+ if (_pViewEdgeBuilder) {
+ delete _pViewEdgeBuilder;
+ _pViewEdgeBuilder = NULL;
+ }
+ }
+
+ /* Build Grid for ray casting */
+ /*! Build non-culled Grid in camera space for ray casting */
+ void BuildGrid(WingedEdge& we, const BBox<Vec3r>& bbox, unsigned int sceneNumFaces);
+
+ /*! Compute Shapes from a WingedEdge containing a list of WShapes */
+ void computeInitialViewEdges(WingedEdge&);
+
+ /*! Compute Cusps */
+ void computeCusps(ViewMap *ioViewMap);
+
+ /*! Detects cusps (for a single ViewEdge) among SVertices and builds a ViewVertex on top of each cusp SVertex
+ * We use a hysteresis approach to avoid noise.
+ */
+ void DetectCusps(ViewEdge *ioEdge);
+
+ /*! Sets the current viewpoint */
+ inline void setViewpoint(const Vec3r& ivp)
+ {
+ _viewpoint = ivp;
+ SilhouetteGeomEngine::setViewpoint(ivp);
+ }
+
+ /*! Sets the current transformation
+ * iModelViewMatrix
+ * The 4x4 model view matrix, in column major order (openGL like).
+ * iProjection matrix
+ * The 4x4 projection matrix, in column major order (openGL like).
+ * iViewport
+ * 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)
+ {
+ _orthographicProjection = (iProjectionMatrix[3][3] != 0.0);
+ SilhouetteGeomEngine::setTransform(iModelViewMatrix, iProjectionMatrix, iViewport, iFocalLength);
+ }
+
+ inline void setFrustum(real iZnear, real iZfar)
+ {
+ SilhouetteGeomEngine::setFrustum(iZnear, iZfar);
+ }
+
+ /*! Builds the scene view map returns the list the view map
+ * it is up to the caller to delete this ViewMap
+ * iWRoot
+ * The root group node containing the WEdge structured scene
+ */
+ ViewMap *BuildViewMap(WingedEdge& we, visibility_algo iAlgo, real epsilon, const BBox<Vec3r>& bbox,
+ unsigned int sceneNumFaces);
+
+ void CullViewEdges(ViewMap *ioViewMap, real viewProscenium[4], real occluderProscenium[4],
+ bool extensiveFEdgeSearch = true);
+
+ /*! computes the intersection between all 2D feature edges of the scene.
+ * ioViewMap
+ * The view map. It is modified by the method.
+ * The list of all features edges of the scene.
+ * Each time an intersection is found, the 2 intersecting edges are splitted (creating 2 new vertices)
+ * At the end, this list is updated with the adding of all new created edges (resulting from splitting).
+ * iAlgo
+ * The algo to use for computing the intersections
+ */
+ void ComputeIntersections(ViewMap *ioViewMap, intersection_algo iAlgo = sweep_line, real epsilon = 1.0e-06);
+
+ /*! Computes the 2D scene silhouette edges visibility
+ * iGrid
+ * For the Ray Casting algorithm.
+ */
+ void ComputeEdgesVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox<Vec3r>& bbox, unsigned int sceneNumFaces,
+ visibility_algo iAlgo = ray_casting, real epsilon = 1.0e-6);
+
+ void setGrid(Grid *iGrid)
+ {
+ _Grid = iGrid;
+ }
+
+ /*! accessors */
+
+ /*! Modifiers */
+ inline void setProgressBar(ProgressBar *iProgressBar)
+ {
+ _pProgressBar = iProgressBar;
+ }
+
+ inline void setRenderMonitor(RenderMonitor *iRenderMonitor)
+ {
+ _pRenderMonitor = iRenderMonitor;
+ }
+
+ inline void setEnableQI(bool iBool)
+ {
+ _EnableQI = iBool;
+ }
+
+protected:
+ /*! Computes intersections on all edges of the scene using a sweep line algorithm */
+ void ComputeSweepLineIntersections(ViewMap *ioViewMap, real epsilon = 1.0e-6);
+
+ /*! Computes the 2D scene silhouette edges visibility using a ray casting. On each edge, a ray is cast
+ * to check its quantitative invisibility. The list of occluders are each time stored in the tested edge.
+ * ioViewMap
+ * The view map.
+ * The 2D scene silhouette edges as FEdges.
+ * These edges have already been splitted at their intersections points.
+ * Thus, these edges do not intersect anymore.
+ * The visibility corresponding to each edge of ioScene is set is this edge.
+ */
+ void ComputeRayCastingVisibility(ViewMap *ioViewMap, real epsilon = 1.0e-6);
+ void ComputeFastRayCastingVisibility(ViewMap *ioViewMap, real epsilon = 1.0e-6);
+ void ComputeVeryFastRayCastingVisibility(ViewMap *ioViewMap, real epsilon = 1.0e-6);
+
+ void ComputeCumulativeVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox<Vec3r>& bbox, real epsilon,
+ bool cull, GridDensityProviderFactory& factory);
+ void ComputeDetailedVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox<Vec3r>& bbox, real epsilon,
+ bool cull, GridDensityProviderFactory& factory);
+
+ /*! Compute the visibility for the FEdge fe.
+ * The occluders are added to fe occluders list.
+ * fe
+ * The FEdge
+ * iGrid
+ * The grid used to compute the ray casting visibility
+ * epsilon
+ * The epsilon used for computation
+ * oShapeId
+ * fe is the border (in 2D) between 2 2D spaces.
+ * if fe is a silhouette, One of these 2D spaces is occupied by the shape to which fe belongs (on its left)
+ * and the other one is either occupied by another shape or empty or occupied by the same shape.
+ * We use this ray csating operation to determine which shape lies on fe's right.
+ * The result is the shape id stored in oShapeId
+ */
+ int ComputeRayCastingVisibility(FEdge *fe, Grid *iGrid, real epsilon, set<ViewShape*>& oOccluders,
+ Polygon3r **oaPolygon, unsigned timestamp);
+ // FIXME
+ void FindOccludee(FEdge *fe, Grid *iGrid, real epsilon, Polygon3r **oaPolygon, unsigned timestamp);
+ void FindOccludee(FEdge *fe, Grid *iGrid, real epsilon, Polygon3r **oaPolygon, unsigned timestamp,
+ Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edge, vector<WVertex*>& faceVertices);
+};
+
+#endif // __FREESTYLE_VIEW_MAP_BUILDER_H__
diff --git a/source/blender/freestyle/intern/view_map/ViewMapIO.cpp b/source/blender/freestyle/intern/view_map/ViewMapIO.cpp
new file mode 100644
index 00000000000..2e94a84861d
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapIO.cpp
@@ -0,0 +1,1258 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/ViewMapIO.cpp
+ * \ingroup freestyle
+ * \brief Functions to manage I/O for the view map
+ * \author Emmanuel Turquin
+ * \date 09/01/2003
+ */
+
+#include "ViewMapIO.h"
+
+#ifdef IRIX
+# define WRITE(n) Internal::write<sizeof((n))>(out, (const char *)(&(n)))
+# define READ(n) Internal::read<sizeof((n))>(in, (char *)(&(n)))
+#else
+# define WRITE(n) out.write((const char *)(&(n)), sizeof((n)))
+# define READ(n) in.read((char *)(&(n)), sizeof((n)))
+#endif
+
+#define WRITE_IF_NON_NULL(ptr) \
+ if (ptr) { \
+ WRITE((ptr)->userdata); \
+ } \
+ else { \
+ WRITE(ZERO); \
+ } (void)0
+
+#define READ_IF_NON_NULL(ptr, array) \
+ READ(tmp); \
+ if (tmp) { \
+ (ptr) = (array)[tmp]; \
+ } \
+ else { \
+ (ptr) = NULL; \
+ } (void)0
+
+namespace ViewMapIO {
+
+namespace Internal {
+
+static ViewMap *g_vm;
+
+//////////////////// 'load' Functions ////////////////////
+
+inline int load(istream& in, Vec3r& v)
+{
+ if (Options::getFlags() & Options::FLOAT_VECTORS) {
+ float tmp;
+ READ(tmp);
+ v[0] = tmp;
+ READ(tmp);
+ v[1] = tmp;
+ READ(tmp);
+ v[2] = tmp;
+ }
+ else {
+ Vec3r::value_type tmp;
+ READ(tmp);
+ v[0] = tmp;
+ READ(tmp);
+ v[1] = tmp;
+ READ(tmp);
+ v[2] = tmp;
+ }
+ return 0;
+}
+
+inline int load(istream& in, Polygon3r& p)
+{
+ unsigned tmp;
+
+ // Id
+ READ(tmp);
+ p.setId(tmp);
+
+ // vertices (List)
+ vector<Vec3r> tmp_vec;
+ Vec3r v;
+ READ(tmp);
+ for (unsigned int i = 0; i < tmp; i++) {
+ load(in, v);
+ tmp_vec.push_back(v);
+ }
+ p.setVertices(tmp_vec);
+
+ // min & max
+ // Already computed (in the SetVertices() method)
+
+ return 0;
+}
+
+inline int load(istream& in, FrsMaterial& m)
+{
+ float tmp_array[4];
+ int i;
+
+ // Diffuse
+ for (i = 0; i < 4; i++)
+ READ(tmp_array[i]);
+ m.setDiffuse(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]);
+
+ // Specular
+ for (i = 0; i < 4; i++)
+ READ(tmp_array[i]);
+ m.setSpecular(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]);
+
+ // Ambient
+ for (i = 0; i < 4; i++)
+ READ(tmp_array[i]);
+ m.setAmbient(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]);
+
+ // Emission
+ for (i = 0; i < 4; i++)
+ READ(tmp_array[i]);
+ m.setEmission(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]);
+
+ // Shininess
+ READ(tmp_array[0]);
+ m.setShininess(tmp_array[0]);
+
+ return 0;
+}
+
+static int load(istream& in, ViewShape *vs)
+{
+ if (!vs || !vs->sshape())
+ return 1;
+
+ // SShape
+
+ // -> Id
+ Id::id_type id1, id2;
+ READ(id1);
+ READ(id2);
+ vs->sshape()->setId(Id(id1, id2));
+
+ // -> Importance
+ float importance;
+ READ(importance);
+ vs->sshape()->setImportance(importance);
+
+ // -> BBox
+ // Not necessary (only used during view map computatiom)
+
+ unsigned i, size, tmp;
+
+ // -> Material
+ READ(size);
+ vector<FrsMaterial> frs_materials;
+ FrsMaterial m;
+ for (i = 0; i < size; ++i) {
+ load(in, m);
+ frs_materials.push_back(m);
+ }
+ vs->sshape()->setFrsMaterials(frs_materials);
+
+ // -> VerticesList (List)
+ READ(size);
+ for (i = 0; i < size; i++) {
+ SVertex *sv;
+ READ_IF_NON_NULL(sv, g_vm->SVertices());
+ vs->sshape()->AddNewVertex(sv);
+ }
+
+ // -> Chains (List)
+ READ(size);
+ for (i = 0; i < size; i++) {
+ FEdge *fe;
+ READ_IF_NON_NULL(fe, g_vm->FEdges());
+ vs->sshape()->AddChain(fe);
+ }
+
+ // -> EdgesList (List)
+ READ(size);
+ for (i = 0; i < size; i++) {
+ FEdge *fe;
+ READ_IF_NON_NULL(fe, g_vm->FEdges());
+ vs->sshape()->AddEdge(fe);
+ }
+
+ // ViewEdges (List)
+ READ(size);
+ for (i = 0; i < size; i++) {
+ ViewEdge *ve;
+ READ_IF_NON_NULL(ve, g_vm->ViewEdges());
+ vs->AddEdge(ve);
+ }
+
+ // ViewVertices (List)
+ READ(size);
+ for (i = 0; i < size; i++) {
+ ViewVertex *vv;
+ READ_IF_NON_NULL(vv, g_vm->ViewVertices());
+ vs->AddVertex(vv);
+ }
+
+ return 0;
+}
+
+
+static int load(istream& in, FEdge *fe)
+{
+ if (!fe)
+ return 1;
+
+ bool b;
+
+ FEdgeSmooth *fesmooth = NULL;
+ FEdgeSharp *fesharp = NULL;
+ if (fe->isSmooth()) {
+ fesmooth = dynamic_cast<FEdgeSmooth*>(fe);
+ }
+ else {
+ fesharp = dynamic_cast<FEdgeSharp*>(fe);
+ }
+
+ // Id
+ Id::id_type id1, id2;
+ READ(id1);
+ READ(id2);
+ fe->setId(Id(id1, id2));
+
+ // Nature
+ Nature::EdgeNature nature;
+ READ(nature);
+ fe->setNature(nature);
+
+#if 0 // hasVisibilityPoint
+ bool b;
+ READ(b);
+ fe->setHasVisibilityPoint(b);
+#endif
+
+ Vec3r v;
+ unsigned int matindex;
+
+#if 0
+ // VisibilityPointA
+ load(in, v);
+ fe->setVisibilityPointA(v);
+
+ // VisibilityPointB
+ load(in, v);
+ fe->setVisibilityPointB(v);
+#endif
+
+ if (fe->isSmooth()) {
+ // Normal
+ load(in, v);
+ fesmooth->setNormal(v);
+
+ // Material
+ READ(matindex);
+ fesmooth->setFrsMaterialIndex(matindex);
+ }
+ else {
+ // aNormal
+ load(in, v);
+ fesharp->setNormalA(v);
+
+ // bNormal
+ load(in, v);
+ fesharp->setNormalB(v);
+
+ // Materials
+ READ(matindex);
+ fesharp->setaFrsMaterialIndex(matindex);
+ READ(matindex);
+ fesharp->setbFrsMaterialIndex(matindex);
+ }
+
+ unsigned tmp;
+
+ // VertexA
+ SVertex *sva;
+ READ_IF_NON_NULL(sva, g_vm->SVertices());
+ fe->setVertexA(sva);
+
+ // VertexB
+ SVertex *svb;
+ READ_IF_NON_NULL(svb, g_vm->SVertices());
+ fe->setVertexB(svb);
+
+ // NextEdge
+ FEdge *nfe;
+ READ_IF_NON_NULL(nfe, g_vm->FEdges());
+ fe->setNextEdge(nfe);
+
+ // PreviousEdge
+ FEdge *pfe;
+ READ_IF_NON_NULL(pfe, g_vm->FEdges());
+ fe->setPreviousEdge(pfe);
+
+ // ViewEdge
+ ViewEdge *ve;
+ READ_IF_NON_NULL(ve, g_vm->ViewEdges());
+ fe->setViewEdge(ve);
+
+ // Face
+ // Not necessary (only used during view map computatiom)
+
+ Polygon3r p;
+
+ // aFace
+ load(in, p);
+ fe->setaFace(p);
+
+ // occludeeEmpty
+ READ(b);
+ fe->setOccludeeEmpty(b);
+
+ // occludeeIntersection
+ load(in, v);
+ fe->setOccludeeIntersection(v);
+
+ return 0;
+}
+
+static int load(istream& in, SVertex *sv)
+{
+ if (!sv)
+ return 1;
+
+ // Id
+ Id::id_type id1, id2;
+ READ(id1);
+ READ(id2);
+ sv->setId(Id(id1, id2));
+
+ Vec3r v;
+
+ // Point3D
+ load(in, v);
+ sv->setPoint3D(v);
+
+ // Point2D
+ load(in, v);
+ sv->setPoint2D(v);
+
+ unsigned tmp;
+
+ // Shape
+ ViewShape *vs;
+ READ_IF_NON_NULL(vs, g_vm->ViewShapes());
+ sv->setShape(vs->sshape());
+
+ // pViewVertex
+ ViewVertex *vv;
+ READ_IF_NON_NULL(vv, g_vm->ViewVertices());
+ sv->setViewVertex(vv);
+
+ unsigned i, size;
+
+ // Normals (List)
+ READ(size);
+ for (i = 0; i < size; i++) {
+ load(in, v);
+ sv->AddNormal(v);
+ }
+
+ // FEdges (List)
+ READ(size);
+ FEdge *fe;
+ for (i = 0; i < size; i++) {
+ READ_IF_NON_NULL(fe, g_vm->FEdges());
+ sv->AddFEdge(fe);
+ }
+
+ return 0;
+}
+
+
+static int load(istream& in, ViewEdge *ve)
+{
+ if (!ve)
+ return 1;
+
+ unsigned tmp;
+
+ // Id
+ Id::id_type id1, id2;
+ READ(id1);
+ READ(id2);
+ ve->setId(Id(id1, id2));
+
+ // Nature
+ Nature::EdgeNature nature;
+ READ(nature);
+ ve->setNature(nature);
+
+ // QI
+ READ(tmp);
+ ve->setQI(tmp);
+
+ // Shape
+ ViewShape *vs;
+ READ_IF_NON_NULL(vs, g_vm->ViewShapes());
+ ve->setShape(vs);
+
+ // aShape
+ ViewShape *avs;
+ READ_IF_NON_NULL(avs, g_vm->ViewShapes());
+ ve->setaShape(avs);
+
+ // FEdgeA
+ FEdge *fea;
+ READ_IF_NON_NULL(fea, g_vm->FEdges());
+ ve->setFEdgeA(fea);
+
+ // FEdgeB
+ FEdge *feb;
+ READ_IF_NON_NULL(feb, g_vm->FEdges());
+ ve->setFEdgeB(feb);
+
+ // A
+ ViewVertex *vva;
+ READ_IF_NON_NULL(vva, g_vm->ViewVertices());
+ ve->setA(vva);
+
+ // B
+ ViewVertex *vvb;
+ READ_IF_NON_NULL(vvb, g_vm->ViewVertices());
+ ve->setB(vvb);
+
+ // Occluders (List)
+ if (!(Options::getFlags() & Options::NO_OCCLUDERS)) {
+ unsigned size;
+ READ(size);
+ ViewShape *vso;
+ for (unsigned int i = 0; i < size; i++) {
+ READ_IF_NON_NULL(vso, g_vm->ViewShapes());
+ ve->AddOccluder(vso);
+ }
+ }
+
+ return 0;
+}
+
+
+static int load(istream& in, ViewVertex *vv)
+{
+ if (!vv)
+ return 1;
+
+ unsigned tmp;
+ bool b;
+
+ // Nature
+ Nature::VertexNature nature;
+ READ(nature);
+ vv->setNature(nature);
+
+ if (vv->getNature() & Nature::T_VERTEX) {
+ TVertex *tv = dynamic_cast<TVertex*>(vv);
+
+ // Id
+ Id::id_type id1, id2;
+ READ(id1);
+ READ(id2);
+ tv->setId(Id(id1, id2));
+
+ // FrontSVertex
+ SVertex *fsv;
+ READ_IF_NON_NULL(fsv, g_vm->SVertices());
+ tv->setFrontSVertex(fsv);
+
+ // BackSVertex
+ SVertex *bsv;
+ READ_IF_NON_NULL(bsv, g_vm->SVertices());
+ tv->setBackSVertex(bsv);
+
+ // FrontEdgeA
+ ViewEdge *fea;
+ READ_IF_NON_NULL(fea, g_vm->ViewEdges());
+ READ(b);
+ tv->setFrontEdgeA(fea, b);
+
+ // FrontEdgeB
+ ViewEdge *feb;
+ READ_IF_NON_NULL(feb, g_vm->ViewEdges());
+ READ(b);
+ tv->setFrontEdgeB(feb, b);
+
+ // BackEdgeA
+ ViewEdge *bea;
+ READ_IF_NON_NULL(bea, g_vm->ViewEdges());
+ READ(b);
+ tv->setBackEdgeA(bea, b);
+
+ // BackEdgeB
+ ViewEdge *beb;
+ READ_IF_NON_NULL(beb, g_vm->ViewEdges());
+ READ(b);
+ tv->setBackEdgeB(beb, b);
+ }
+ else if (vv->getNature() & Nature::NON_T_VERTEX) {
+ NonTVertex *ntv = dynamic_cast<NonTVertex*>(vv);
+
+ // SVertex
+ SVertex *sv;
+ READ_IF_NON_NULL(sv, g_vm->SVertices());
+ ntv->setSVertex(sv);
+
+ // ViewEdges (List)
+ unsigned size;
+ READ(size);
+ ViewEdge *ve;
+ for (unsigned int i = 0; i < size; i++) {
+ READ_IF_NON_NULL(ve, g_vm->ViewEdges());
+ READ(b);
+ ntv->AddViewEdge(ve, b);
+ }
+ }
+
+ return 0;
+}
+
+//////////////////// 'save' Functions ////////////////////
+
+inline int save(ostream& out, const Vec3r& v)
+{
+ if (Options::getFlags() & Options::FLOAT_VECTORS) {
+ float tmp;
+
+ tmp = v[0];
+ WRITE(tmp);
+ tmp = v[1];
+ WRITE(tmp);
+ tmp = v[2];
+ WRITE(tmp);
+ }
+ else {
+ Vec3r::value_type tmp;
+
+ tmp = v[0];
+ WRITE(tmp);
+ tmp = v[1];
+ WRITE(tmp);
+ tmp = v[2];
+ WRITE(tmp);
+ }
+ return 0;
+}
+
+
+inline int save(ostream& out, const Polygon3r& p)
+{
+ unsigned tmp;
+
+ // Id
+ tmp = p.getId();
+ WRITE(tmp);
+
+ // vertices (List)
+ tmp = p.getVertices().size();
+ WRITE(tmp);
+ for (vector<Vec3r>::const_iterator i = p.getVertices().begin(); i != p.getVertices().end(); i++) {
+ save(out, *i);
+ }
+
+ // min & max
+ // Do not need to be saved
+
+ return 0;
+}
+
+inline int save(ostream& out, const FrsMaterial& m)
+{
+ unsigned i;
+
+ // Diffuse
+ for (i = 0; i < 4; i++)
+ WRITE(m.diffuse()[i]);
+
+ // Specular
+ for (i = 0; i < 4; i++)
+ WRITE(m.specular()[i]);
+
+ // Ambient
+ for (i = 0; i < 4; i++)
+ WRITE(m.ambient()[i]);
+
+ // Emission
+ for (i = 0; i < 4; i++)
+ WRITE(m.emission()[i]);
+
+ // Shininess
+ float shininess = m.shininess();
+ WRITE(shininess);
+
+ return 0;
+}
+
+static int save(ostream& out, ViewShape *vs)
+{
+ if (!vs || !vs->sshape()) {
+ cerr << "Warning: null ViewShape" << endl;
+ return 1;
+ }
+
+ unsigned tmp;
+
+ // SShape
+
+ // -> Id
+ Id::id_type id = vs->sshape()->getId().getFirst();
+ WRITE(id);
+ id = vs->sshape()->getId().getSecond();
+ WRITE(id);
+
+ // -> Importance
+ float importance = vs->sshape()->importance();
+ WRITE(importance);
+
+ // -> BBox
+ // Not necessary (only used during view map computatiom)
+
+ // -> Material
+ unsigned int size = vs->sshape()->frs_materials().size();
+ WRITE(size);
+ for (unsigned int i = 0; i < size; ++i)
+ save(out, vs->sshape()->frs_material(i));
+
+ // -> VerticesList (List)
+ tmp = vs->sshape()->getVertexList().size();
+ WRITE(tmp);
+ for (vector<SVertex*>::const_iterator i1 = vs->sshape()->getVertexList().begin();
+ i1 != vs->sshape()->getVertexList().end();
+ i1++)
+ {
+ WRITE_IF_NON_NULL(*i1);
+ }
+
+ // -> Chains (List)
+ tmp = vs->sshape()->getChains().size();
+ WRITE(tmp);
+ for (vector<FEdge*>::const_iterator i2 = vs->sshape()->getChains().begin();
+ i2 != vs->sshape()->getChains().end();
+ i2++)
+ {
+ WRITE_IF_NON_NULL(*i2);
+ }
+
+ // -> EdgesList (List)
+ tmp = vs->sshape()->getEdgeList().size();
+ WRITE(tmp);
+ for (vector<FEdge*>::const_iterator i3 = vs->sshape()->getEdgeList().begin();
+ i3 != vs->sshape()->getEdgeList().end();
+ i3++)
+ {
+ WRITE_IF_NON_NULL(*i3);
+ }
+
+ // ViewEdges (List)
+ tmp = vs->edges().size();
+ WRITE(tmp);
+ for (vector<ViewEdge*>::const_iterator i4 = vs->edges().begin(); i4 != vs->edges().end(); i4++)
+ WRITE_IF_NON_NULL(*i4);
+
+ // ViewVertices (List)
+ tmp = vs->vertices().size();
+ WRITE(tmp);
+ for (vector<ViewVertex*>::const_iterator i5 = vs->vertices().begin(); i5 != vs->vertices().end(); i5++)
+ WRITE_IF_NON_NULL(*i5);
+
+ return 0;
+}
+
+
+static int save(ostream& out, FEdge *fe)
+{
+ if (!fe) {
+ cerr << "Warning: null FEdge" << endl;
+ return 1;
+ }
+
+ FEdgeSmooth *fesmooth = dynamic_cast<FEdgeSmooth*>(fe);
+ FEdgeSharp *fesharp = dynamic_cast<FEdgeSharp*>(fe);
+
+ // Id
+ Id::id_type id = fe->getId().getFirst();
+ WRITE(id);
+ id = fe->getId().getSecond();
+ WRITE(id);
+
+ // Nature
+ Nature::EdgeNature nature = fe->getNature();
+ WRITE(nature);
+
+ bool b;
+
+#if 0
+ // hasVisibilityPoint
+ b = fe->hasVisibilityPoint();
+ WRITE(b);
+
+ // VisibilityPointA
+ save(out, fe->visibilityPointA());
+
+ // VisibilityPointB
+ save(out, fe->visibilityPointB());
+#endif
+
+ unsigned index;
+ if (fe->isSmooth()) {
+ // normal
+ save(out, fesmooth->normal());
+ // material
+ index = fesmooth->frs_materialIndex();
+ WRITE(index);
+ }
+ else {
+ // aNormal
+ save(out, fesharp->normalA());
+ // bNormal
+ save(out, fesharp->normalB());
+ // aMaterial
+ index = fesharp->aFrsMaterialIndex();
+ WRITE(index);
+ // bMaterial
+ index = fesharp->bFrsMaterialIndex();
+ WRITE(index);
+ }
+
+ // VertexA
+ WRITE_IF_NON_NULL(fe->vertexA());
+
+ // VertexB
+ WRITE_IF_NON_NULL(fe->vertexB());
+
+ // NextEdge
+ WRITE_IF_NON_NULL(fe->nextEdge());
+
+ // PreviousEdge
+ WRITE_IF_NON_NULL(fe->previousEdge());
+
+ // ViewEdge
+ WRITE_IF_NON_NULL(fe->viewedge());
+
+ // Face
+ // Not necessary (only used during view map computatiom)
+
+ // aFace
+ save(out, (Polygon3r&)fe->aFace());
+
+ // occludeeEmpty
+ b = fe->getOccludeeEmpty();
+ WRITE(b);
+
+ // occludeeIntersection
+ save(out, fe->getOccludeeIntersection());
+
+ return 0;
+}
+
+static int save(ostream& out, SVertex *sv)
+{
+ if (!sv) {
+ cerr << "Warning: null SVertex" << endl;
+ return 1;
+ }
+
+ unsigned tmp;
+
+ // Id
+ Id::id_type id = sv->getId().getFirst();
+ WRITE(id);
+ id = sv->getId().getSecond();
+ WRITE(id);
+
+ Vec3r v;
+
+ // Point3D
+ v = sv->point3D();
+ save(out, sv->point3D());
+
+ // Point2D
+ v = sv->point2D();
+ save(out, v);
+
+ // Shape
+ WRITE_IF_NON_NULL(sv->shape());
+
+ // pViewVertex
+ WRITE_IF_NON_NULL(sv->viewvertex());
+
+ // Normals (List)
+ // Note: the 'size()' method of a set doesn't seem to return the actual size of the given set, so we have to
+ // hack it...
+ set<Vec3r>::const_iterator i;
+ for (i = sv->normals().begin(), tmp = 0; i != sv->normals().end(); i++, tmp++);
+ WRITE(tmp);
+ for (i = sv->normals().begin(); i != sv->normals().end(); i++)
+ save(out, *i);
+
+ // FEdges (List)
+ tmp = sv->fedges().size();
+ WRITE(tmp);
+ for (vector<FEdge*>::const_iterator j = sv->fedges_begin(); j != sv->fedges_end(); j++)
+ WRITE_IF_NON_NULL(*j);
+
+ return 0;
+}
+
+
+static int save(ostream& out, ViewEdge *ve)
+{
+ if (!ve) {
+ cerr << "Warning: null ViewEdge" << endl;
+ return 1;
+ }
+
+ unsigned tmp;
+
+ // Id
+ Id::id_type id = ve->getId().getFirst();
+ WRITE(id);
+ id = ve->getId().getSecond();
+ WRITE(id);
+
+ // Nature
+ Nature::EdgeNature nature = ve->getNature();
+ WRITE(nature);
+
+ // QI
+ unsigned qi = ve->qi();
+ WRITE(qi);
+
+ // Shape
+ WRITE_IF_NON_NULL(ve->shape());
+
+ // aShape
+ WRITE_IF_NON_NULL(ve->aShape());
+
+ // FEdgeA
+ WRITE_IF_NON_NULL(ve->fedgeA());
+
+ // FEdgeB
+ WRITE_IF_NON_NULL(ve->fedgeB());
+
+ // A
+ WRITE_IF_NON_NULL(ve->A());
+
+ // B
+ WRITE_IF_NON_NULL(ve->B());
+
+ // Occluders (List)
+ if (!(Options::getFlags() & Options::NO_OCCLUDERS)) {
+ tmp = ve->occluders().size();
+ WRITE(tmp);
+ for (vector<ViewShape*>::const_iterator i = ve->occluders().begin(); i != ve->occluders().end(); i++)
+ WRITE_IF_NON_NULL((*i));
+ }
+
+ return 0;
+}
+
+
+static int save(ostream& out, ViewVertex *vv)
+{
+ if (!vv) {
+ cerr << "Warning: null ViewVertex" << endl;
+ return 1;
+ }
+
+ // Nature
+ Nature::VertexNature nature = vv->getNature();
+ WRITE(nature);
+
+ if (vv->getNature() & Nature::T_VERTEX) {
+ TVertex *tv = dynamic_cast<TVertex*>(vv);
+
+ // Id
+ Id::id_type id = tv->getId().getFirst();
+ WRITE(id);
+ id = tv->getId().getSecond();
+ WRITE(id);
+
+ // FrontSVertex
+ WRITE_IF_NON_NULL(tv->frontSVertex());
+
+ // BackSVertex
+ WRITE_IF_NON_NULL(tv->backSVertex());
+
+ // FrontEdgeA
+ WRITE_IF_NON_NULL(tv->frontEdgeA().first);
+ WRITE(tv->frontEdgeA().second);
+
+ // FrontEdgeB
+ WRITE_IF_NON_NULL(tv->frontEdgeB().first);
+ WRITE(tv->frontEdgeB().second);
+
+ // BackEdgeA
+ WRITE_IF_NON_NULL(tv->backEdgeA().first);
+ WRITE(tv->backEdgeA().second);
+
+ // BackEdgeB
+ WRITE_IF_NON_NULL(tv->backEdgeB().first);
+ WRITE(tv->backEdgeB().second);
+ }
+ else if (vv->getNature() & Nature::NON_T_VERTEX) {
+ NonTVertex *ntv = dynamic_cast<NonTVertex*>(vv);
+
+ // SVertex
+ WRITE_IF_NON_NULL(ntv->svertex());
+
+ // ViewEdges (List)
+ unsigned size = ntv->viewedges().size();
+ WRITE(size);
+ vector<ViewVertex::directedViewEdge>::const_iterator i = ntv->viewedges().begin();
+ for (; i != ntv->viewedges().end(); i++) {
+ WRITE_IF_NON_NULL(i->first);
+ WRITE(i->second);
+ }
+ }
+ else {
+ cerr << "Warning: unexpected ViewVertex nature" << endl;
+ return 1;
+ }
+
+ return 0;
+}
+
+} // End of namespace Internal
+
+
+//////////////////// "Public" 'load' and 'save' functions ////////////////////
+
+#define SET_PROGRESS(n) \
+ if (pb) { \
+ pb->setProgress((n)); \
+ } (void)0
+
+int load(istream& in, ViewMap *vm, ProgressBar *pb)
+{
+ if (!vm)
+ return 1;
+
+ //soc unused - unsigned tmp;
+ int err = 0;
+ Internal::g_vm = vm;
+
+ // Management of the progress bar (if present)
+ if (pb) {
+ pb->reset();
+ pb->setLabelText("Loading View Map...");
+ pb->setTotalSteps(6);
+ pb->setProgress(0);
+ }
+
+ // Read and set the options
+ unsigned char flags;
+ READ(flags);
+ Options::setFlags(flags);
+
+ // Read the size of the five ViewMap's lists (with some extra informations for the ViewVertices)
+ // and instantiate them (with default costructors)
+ unsigned vs_s, fe_s, fe_rle1, fe_rle2, sv_s, ve_s, vv_s, vv_rle1, vv_rle2;
+ READ(vs_s);
+ READ(fe_s);
+
+ if (fe_s) {
+ bool b;
+ READ(b);
+ for (READ(fe_rle1), fe_rle2 = 0; fe_rle1 < fe_s + 1; fe_rle2 = fe_rle1, READ(fe_rle1)) {
+ if (b) {
+ for (unsigned int i = fe_rle2; i < fe_rle1; i++) {
+ FEdgeSmooth *fes = new FEdgeSmooth;
+ vm->AddFEdge(fes);
+ }
+ b = !b;
+ }
+ else if (!b) {
+ for (unsigned int i = fe_rle2; i < fe_rle1; i++) {
+ FEdgeSharp *fes = new FEdgeSharp;
+ vm->AddFEdge(fes);
+ }
+ b = !b;
+ }
+ }
+ }
+
+ READ(sv_s);
+ READ(ve_s);
+ READ(vv_s);
+
+ if (vv_s) {
+ Nature::VertexNature nature;
+ READ(nature);
+ for (READ(vv_rle1), vv_rle2 = 0; vv_rle1 < vv_s + 1; vv_rle2 = vv_rle1, READ(vv_rle1)) {
+ if (nature & Nature::T_VERTEX) {
+ for (unsigned int i = vv_rle2; i < vv_rle1; i++) {
+ TVertex *tv = new TVertex();
+ vm->AddViewVertex(tv);
+ }
+ nature = Nature::NON_T_VERTEX;
+ }
+ else if (nature & Nature::NON_T_VERTEX) {
+ for (unsigned int i = vv_rle2; i < vv_rle1; i++) {
+ NonTVertex *ntv = new NonTVertex();
+ vm->AddViewVertex(ntv);
+ }
+ nature = Nature::T_VERTEX;
+ }
+ }
+ }
+
+ for (unsigned int i0 = 0; i0 < vs_s; i0++) {
+ SShape *ss = new SShape();
+ ViewShape *vs = new ViewShape();
+ vs->setSShape(ss);
+ ss->setViewShape(vs);
+ vm->AddViewShape(vs);
+ }
+#if 0
+ for (unsigned int i1 = 0; i1 < fe_s; i1++) {
+ FEdge *fe = new FEdge();
+ vm->AddFEdge(fe);
+ }
+#endif
+ for (unsigned int i2 = 0; i2 < sv_s; i2++) {
+ SVertex *sv = new SVertex();
+ vm->AddSVertex(sv);
+ }
+ for (unsigned int i3 = 0; i3 < ve_s; i3++) {
+ ViewEdge *ve = new ViewEdge();
+ vm->AddViewEdge(ve);
+ }
+
+ // Read the values for all the objects created above
+ SET_PROGRESS(1);
+ for (vector<ViewShape*>::const_iterator i4 = vm->ViewShapes().begin(); i4 != vm->ViewShapes().end(); i4++)
+ err += Internal::load(in, *i4);
+ SET_PROGRESS(2);
+ for (vector<FEdge*>::const_iterator i5 = vm->FEdges().begin(); i5 != vm->FEdges().end(); i5++)
+ err += Internal::load(in, *i5);
+ SET_PROGRESS(3);
+ for (vector<SVertex*>::const_iterator i6 = vm->SVertices().begin(); i6 != vm->SVertices().end(); i6++)
+ err += Internal::load(in, *i6);
+ SET_PROGRESS(4);
+ for (vector<ViewEdge*>::const_iterator i7 = vm->ViewEdges().begin(); i7 != vm->ViewEdges().end(); i7++)
+ err += Internal::load(in, *i7);
+ SET_PROGRESS(5);
+ for (vector<ViewVertex*>::const_iterator i8 = vm->ViewVertices().begin(); i8 != vm->ViewVertices().end(); i8++)
+ err += Internal::load(in, *i8);
+ SET_PROGRESS(6);
+
+ // Read the shape id to index mapping
+ unsigned map_s;
+ READ(map_s);
+ unsigned id, index;
+ for (unsigned int i4 = 0; i4 < map_s; ++i4) {
+ READ(id);
+ READ(index);
+ vm->shapeIdToIndexMap()[id] = index;
+ }
+
+ return err;
+}
+
+
+int save(ostream& out, ViewMap *vm, ProgressBar *pb)
+{
+ if (!vm)
+ return 1;
+
+ int err = 0;
+
+ // Management of the progress bar (if present)
+ if (pb) {
+ pb->reset();
+ pb->setLabelText("Saving View Map...");
+ pb->setTotalSteps(6);
+ pb->setProgress(0);
+ }
+
+ // For every object, initialize its userdata member to its index in the ViewMap list
+ for (unsigned int i0 = 0; i0 < vm->ViewShapes().size(); i0++) {
+ vm->ViewShapes()[i0]->userdata = SET_UINT_IN_POINTER(i0);
+ vm->ViewShapes()[i0]->sshape()->userdata = SET_UINT_IN_POINTER(i0);
+ }
+ for (unsigned int i1 = 0; i1 < vm->FEdges().size(); i1++)
+ vm->FEdges()[i1]->userdata = SET_UINT_IN_POINTER(i1);
+ for (unsigned int i2 = 0; i2 < vm->SVertices().size(); i2++)
+ vm->SVertices()[i2]->userdata = SET_UINT_IN_POINTER(i2);
+ for (unsigned int i3 = 0; i3 < vm->ViewEdges().size(); i3++)
+ vm->ViewEdges()[i3]->userdata = SET_UINT_IN_POINTER(i3);
+ for (unsigned int i4 = 0; i4 < vm->ViewVertices().size(); i4++)
+ vm->ViewVertices()[i4]->userdata = SET_UINT_IN_POINTER(i4);
+
+ // Write the current options
+ unsigned char flags = Options::getFlags();
+ WRITE(flags);
+
+ // Write the size of the five lists (with some extra informations for the ViewVertices)
+ unsigned size;
+ size = vm->ViewShapes().size();
+ WRITE(size);
+ size = vm->FEdges().size();
+ WRITE(size);
+ if (size) {
+ bool b = vm->FEdges()[0]->isSmooth();
+ WRITE(b);
+ for (unsigned int i = 0; i < size; i++) {
+ while (i < size && (vm->FEdges()[i]->isSmooth() == b))
+ i++;
+ if (i < size) {
+ WRITE(i);
+ b = !b;
+ }
+ }
+ WRITE(size);
+ size++;
+ WRITE(size);
+ }
+ size = vm->SVertices().size();
+ WRITE(size);
+ size = vm->ViewEdges().size();
+ WRITE(size);
+ size = vm->ViewVertices().size();
+ WRITE(size);
+ if (size) {
+ Nature::VertexNature nature = vm->ViewVertices()[0]->getNature();
+ WRITE(nature);
+ nature &= ~Nature::VIEW_VERTEX;
+ for (unsigned int i = 0; i < size; i++) {
+ while (i < size && (vm->ViewVertices()[i]->getNature() & nature))
+ i++;
+ if (i < size) {
+ WRITE(i);
+ nature = vm->ViewVertices()[i]->getNature() & ~Nature::VIEW_VERTEX;
+ }
+ }
+ WRITE(size);
+ size++;
+ WRITE(size);
+ }
+
+ // Write all the elts of the ViewShapes List
+ SET_PROGRESS(1);
+ for (vector<ViewShape*>::const_iterator i5 = vm->ViewShapes().begin(); i5 != vm->ViewShapes().end(); i5++)
+ err += Internal::save(out, *i5);
+ SET_PROGRESS(2);
+ for (vector<FEdge*>::const_iterator i6 = vm->FEdges().begin(); i6 != vm->FEdges().end(); i6++)
+ err += Internal::save(out, *i6);
+ SET_PROGRESS(3);
+ for (vector<SVertex*>::const_iterator i7 = vm->SVertices().begin(); i7 != vm->SVertices().end(); i7++)
+ err += Internal::save(out, *i7);
+ SET_PROGRESS(4);
+ for (vector<ViewEdge*>::const_iterator i8 = vm->ViewEdges().begin(); i8 != vm->ViewEdges().end(); i8++)
+ err += Internal::save(out, *i8);
+ SET_PROGRESS(5);
+ for (vector<ViewVertex*>::const_iterator i9 = vm->ViewVertices().begin(); i9 != vm->ViewVertices().end(); i9++)
+ err += Internal::save(out, *i9);
+
+ // Write the shape id to index mapping
+ size = vm->shapeIdToIndexMap().size();
+ WRITE(size);
+ unsigned int id, index;
+ for (ViewMap::id_to_index_map::iterator mit = vm->shapeIdToIndexMap().begin(),
+ mitend = vm->shapeIdToIndexMap().end();
+ mit != mitend;
+ ++mit)
+ {
+ id = mit->first;
+ index = mit->second;
+ WRITE(id);
+ WRITE(index);
+ }
+
+ // Reset 'userdata' members
+ for (vector<ViewShape*>::const_iterator j0 = vm->ViewShapes().begin(); j0 != vm->ViewShapes().end(); j0++) {
+ (*j0)->userdata = NULL;
+ (*j0)->sshape()->userdata = NULL;
+ }
+ for (vector<FEdge*>::const_iterator j1 = vm->FEdges().begin(); j1 != vm->FEdges().end(); j1++)
+ (*j1)->userdata = NULL;
+ for (vector<SVertex*>::const_iterator j2 = vm->SVertices().begin(); j2 != vm->SVertices().end(); j2++)
+ (*j2)->userdata = NULL;
+ for (vector<ViewEdge*>::const_iterator j3 = vm->ViewEdges().begin(); j3 != vm->ViewEdges().end(); j3++)
+ (*j3)->userdata = NULL;
+ for (vector<ViewVertex*>::const_iterator j4 = vm->ViewVertices().begin(); j4 != vm->ViewVertices().end(); j4++)
+ (*j4)->userdata = NULL;
+ SET_PROGRESS(6);
+
+ return err;
+}
+
+
+//////////////////// Options ////////////////////
+
+namespace Options {
+
+namespace Internal {
+
+static unsigned char g_flags = 0;
+static string g_models_path;
+
+} // End of namespace Internal
+
+void setFlags(const unsigned char flags)
+{
+ Internal::g_flags = flags;
+}
+
+void addFlags(const unsigned char flags)
+{
+ Internal::g_flags |= flags;
+}
+
+void rmFlags(const unsigned char flags)
+{
+ Internal::g_flags &= ~flags;
+}
+
+unsigned char getFlags()
+{
+ return Internal::g_flags;
+}
+
+void setModelsPath(const string& path)
+{
+ Internal::g_models_path = path;
+}
+
+string getModelsPath()
+{
+ return Internal::g_models_path;
+}
+
+} // End of namepace Options
+
+} // End of namespace ViewMapIO
diff --git a/source/blender/freestyle/intern/view_map/ViewMapIO.h b/source/blender/freestyle/intern/view_map/ViewMapIO.h
new file mode 100644
index 00000000000..6a7268a71a9
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapIO.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_VIEW_MAP_IO_H__
+#define __FREESTYLE_VIEW_MAP_IO_H__
+
+/** \file blender/freestyle/intern/view_map/ViewMapIO.h
+ * \ingroup freestyle
+ * \brief Functions to manage I/O for the view map
+ * \author Emmanuel Turquin
+ * \date 09/01/2003
+ */
+
+#include <fstream>
+#include <string>
+
+#include "ViewMap.h"
+
+#include "../system/FreestyleConfig.h"
+#include "../system/ProgressBar.h"
+
+namespace ViewMapIO {
+
+static const unsigned ZERO = UINT_MAX;
+
+LIB_VIEW_MAP_EXPORT
+int load(istream& in, ViewMap *vm, ProgressBar *pb = NULL);
+
+LIB_VIEW_MAP_EXPORT
+int save(ostream& out, ViewMap *vm, ProgressBar *pb = NULL);
+
+namespace Options {
+
+static const unsigned char FLOAT_VECTORS = 1;
+static const unsigned char NO_OCCLUDERS = 2;
+
+LIB_VIEW_MAP_EXPORT
+void setFlags(const unsigned char flags);
+
+LIB_VIEW_MAP_EXPORT
+void addFlags(const unsigned char flags);
+
+LIB_VIEW_MAP_EXPORT
+void rmFlags(const unsigned char flags);
+
+LIB_VIEW_MAP_EXPORT
+unsigned char getFlags();
+
+LIB_VIEW_MAP_EXPORT
+void setModelsPath(const string& path);
+
+LIB_VIEW_MAP_EXPORT
+string getModelsPath();
+
+}; // End of namepace Options
+
+#ifdef IRIX
+
+namespace Internal {
+
+template <unsigned S>
+ostream& write(ostream& out, const char *str)
+{
+ out.put(str[S - 1]);
+ return write<S - 1>(out, str);
+}
+
+template<>
+ostream& write<1>(ostream& out, const char *str)
+{
+ return out.put(str[0]);
+}
+
+template<>
+ostream& write<0>(ostream& out, const char *)
+{
+ return out;
+}
+
+template <unsigned S>
+istream& read(istream& in, char *str)
+{
+ in.get(str[S - 1]);
+ return read<S - 1>(in, str);
+}
+
+template<>
+istream& read<1>(istream& in, char *str)
+{
+ return in.get(str[0]);
+}
+
+template<>
+istream& read<0>(istream& in, char *)
+{
+ return in;
+}
+
+} // End of namespace Internal
+
+#endif // IRIX
+
+} // End of namespace ViewMapIO
+
+#endif // __FREESTYLE_VIEW_MAP_IO_H__
diff --git a/source/blender/freestyle/intern/view_map/ViewMapIterators.h b/source/blender/freestyle/intern/view_map/ViewMapIterators.h
new file mode 100644
index 00000000000..78c09c863cc
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapIterators.h
@@ -0,0 +1,574 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_VIEW_MAP_ITERATORS_H__
+#define __FREESTYLE_VIEW_MAP_ITERATORS_H__
+
+/** \file blender/freestyle/intern/view_map/ViewMapIterators.h
+ * \ingroup freestyle
+ * \brief Iterators used to iterate over the various elements of the ViewMap
+ * \author Stephane Grabli
+ * \date 01/07/2003
+ */
+
+#include "ViewMap.h"
+
+#include "../system/Iterator.h" //soc
+
+
+/**********************************/
+/* */
+/* */
+/* ViewMap */
+/* */
+/* */
+/**********************************/
+
+/**********************************/
+/* */
+/* */
+/* ViewVertex */
+/* */
+/* */
+/**********************************/
+
+namespace ViewVertexInternal {
+
+/*! Class representing an iterator over oriented ViewEdges around a ViewVertex. This iterator allows a CCW iteration
+ * (in the image plane).
+ * An instance of an orientedViewEdgeIterator can only be obtained from a ViewVertex by calling edgesBegin()
+ * or edgesEnd().
+ */
+class orientedViewEdgeIterator : public Iterator
+{
+public:
+ friend class ViewVertex;
+ friend class TVertex;
+ friend class NonTVertex;
+ friend class ViewEdge;
+
+ // FIXME
+ typedef ::TVertex::edge_pointers_container edge_pointers_container;
+ typedef ::NonTVertex::edges_container edges_container;
+
+protected:
+ Nature::VertexNature _Nature; // the nature of the underlying vertex
+ // T vertex attributes
+ edge_pointers_container::iterator _tbegin;
+ edge_pointers_container::iterator _tend;
+ edge_pointers_container::iterator _tvertex_iter;
+
+ // Non TVertex attributes
+ edges_container::iterator _begin;
+ edges_container::iterator _end;
+ edges_container::iterator _nontvertex_iter;
+
+public:
+ /*! Default constructor */
+ inline orientedViewEdgeIterator() {}
+
+ inline orientedViewEdgeIterator(Nature::VertexNature iNature)
+ {
+ _Nature = iNature;
+ }
+
+ /*! Copy constructor */
+ orientedViewEdgeIterator(const orientedViewEdgeIterator& iBrother)
+ {
+ _Nature = iBrother._Nature;
+ if (_Nature & Nature::T_VERTEX) {
+ _tbegin = iBrother._tbegin;
+ _tend = iBrother._tend;
+ _tvertex_iter = iBrother._tvertex_iter;
+ }
+ else {
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _nontvertex_iter = iBrother._nontvertex_iter;
+ }
+ }
+
+ virtual ~orientedViewEdgeIterator() {}
+
+public:
+ inline orientedViewEdgeIterator(edge_pointers_container::iterator begin, edge_pointers_container::iterator end,
+ edge_pointers_container::iterator iter)
+ {
+ _Nature = Nature::T_VERTEX;
+ _tbegin = begin;
+ _tend = end;
+ _tvertex_iter = iter;
+ }
+
+ inline orientedViewEdgeIterator(edges_container::iterator begin, edges_container::iterator end,
+ edges_container::iterator iter)
+ {
+ _Nature = Nature::NON_T_VERTEX;
+ _begin = begin;
+ _end = end;
+ _nontvertex_iter = iter;
+ }
+
+public:
+ /*! Tells whether the ViewEdge pointed by this iterator is the first one of the iteration list or not. */
+ virtual bool isBegin() const
+ {
+ if (_Nature & Nature::T_VERTEX)
+ return (_tvertex_iter == _tbegin);
+ else
+ return (_nontvertex_iter == _begin);
+ }
+
+ /*! Tells whether the ViewEdge pointed by this iterator is after the last one of the iteration list or not. */
+ virtual bool isEnd() const
+ {
+ if (_Nature & Nature::T_VERTEX)
+ return (_tvertex_iter == _tend);
+ else
+ return (_nontvertex_iter == _end);
+ }
+
+ // operators
+ /*! Increments. In the scripting language, call "increment()". */
+ // operator corresponding to ++i
+ virtual orientedViewEdgeIterator& operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ // operator corresponding to i++, i.e. which returns the value *and then* increments.
+ // That's why we store the value in a temp.
+ virtual orientedViewEdgeIterator operator++(int)
+ {
+ orientedViewEdgeIterator tmp = *this;
+ increment();
+ return tmp;
+ }
+
+ // comparibility
+ /*! operator != */
+ virtual bool operator!=(const orientedViewEdgeIterator& b) const
+ {
+ if (_Nature & Nature::T_VERTEX)
+ return (_tvertex_iter != b._tvertex_iter);
+ else
+ return (_nontvertex_iter != b._nontvertex_iter);
+ }
+
+ /*! operator == */
+ virtual bool operator==(const orientedViewEdgeIterator& b) const
+ {
+ return !(*this != b);
+ }
+
+ // dereferencing
+ /*! Returns a reference to the pointed orientedViewEdge.
+ * In the scripting language, you must call "getObject()" instead.
+ */
+ virtual ::ViewVertex::directedViewEdge& operator*() const
+ {
+ if (_Nature & Nature::T_VERTEX)
+ //return _tvertex_iter;
+ return **_tvertex_iter;
+ else
+ return (*_nontvertex_iter);
+ }
+ /*! Returns a pointer to the pointed orientedViewEdge.
+ * Can't be called in the scripting language.
+ */
+ virtual ::ViewVertex::directedViewEdge *operator->() const
+ {
+ return &(operator*());
+ }
+
+public:
+ /*! increments.*/
+ virtual inline int increment()
+ {
+ if (_Nature & Nature::T_VERTEX) {
+ ::ViewVertex::directedViewEdge tmp = (**_tvertex_iter);
+ ++_tvertex_iter;
+ if (_tvertex_iter != _tend) {
+ // FIXME : pquoi deja ?
+ ::ViewVertex::directedViewEdge tmp2 = (**_tvertex_iter);
+ if (tmp2.first == tmp.first)
+ ++_tvertex_iter;
+ }
+ }
+ else {
+ ++_nontvertex_iter;
+ }
+ return 0;
+ }
+};
+
+} // ViewVertexInternal namespace
+
+/**********************************/
+/* */
+/* */
+/* ViewEdge */
+/* */
+/* */
+/**********************************/
+
+namespace ViewEdgeInternal {
+
+//
+// SVertexIterator
+//
+/////////////////////////////////////////////////
+
+class SVertexIterator : public Interface0DIteratorNested
+{
+public:
+ SVertexIterator()
+ {
+ _vertex = NULL;
+ _begin = NULL;
+ _previous_edge = NULL;
+ _next_edge = NULL;
+ _t = 0;
+ }
+
+ SVertexIterator(const SVertexIterator& vi)
+ {
+ _vertex = vi._vertex;
+ _begin = vi._begin;
+ _previous_edge = vi._previous_edge;
+ _next_edge = vi._next_edge;
+ _t = vi._t;
+ }
+
+ SVertexIterator(SVertex *v, SVertex *begin, FEdge *prev, FEdge *next, float t)
+ {
+ _vertex = v;
+ _begin = begin;
+ _previous_edge = prev;
+ _next_edge = next;
+ _t = t;
+ }
+
+ SVertexIterator& operator=(const SVertexIterator& vi)
+ {
+ _vertex = vi._vertex;
+ _begin = vi._begin;
+ _previous_edge = vi._previous_edge;
+ _next_edge = vi._next_edge;
+ _t = vi._t;
+ return *this;
+ }
+
+ virtual ~SVertexIterator() {}
+
+ virtual string getExactTypeName() const
+ {
+ return "SVertexIterator";
+ }
+
+ virtual SVertex& operator*()
+ {
+ return *_vertex;
+ }
+
+ virtual SVertex *operator->()
+ {
+ return &(operator*());
+ }
+
+ virtual SVertexIterator& operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ virtual SVertexIterator operator++(int)
+ {
+ SVertexIterator ret(*this);
+ increment();
+ return ret;
+ }
+
+ virtual SVertexIterator& operator--()
+ {
+ decrement();
+ return *this;
+ }
+
+ virtual SVertexIterator operator--(int)
+ {
+ SVertexIterator ret(*this);
+ decrement();
+ return ret;
+ }
+
+ virtual int increment()
+ {
+ if (!_next_edge) {
+ _vertex = NULL;
+ return 0;
+ }
+ _t += (float)_next_edge->getLength2D();
+ _vertex = _next_edge->vertexB();
+ _previous_edge = _next_edge;
+ _next_edge = _next_edge->nextEdge();
+ return 0;
+ }
+
+ virtual int decrement()
+ {
+ if (!_previous_edge) {
+ _vertex = NULL;
+ return 0;
+ }
+ if ((!_next_edge) && (!_vertex)) {
+ _vertex = _previous_edge->vertexB();
+ return 0;
+ }
+ _t -= (float)_previous_edge->getLength2D();
+ _vertex = _previous_edge->vertexA();
+ _next_edge = _previous_edge;
+ _previous_edge = _previous_edge->previousEdge();
+ return 0;
+ }
+
+ virtual bool isBegin() const
+ {
+ return _vertex == _begin;
+ }
+
+ virtual bool isEnd() const
+ {
+ return (!_vertex) || (_vertex == _begin && _previous_edge);
+ }
+
+ virtual float t() const
+ {
+ return _t;
+ }
+
+ virtual float u() const
+ {
+ return _t / (float)_next_edge->viewedge()->getLength2D();
+ }
+
+ virtual bool operator==(const Interface0DIteratorNested& it) const
+ {
+ const SVertexIterator *it_exact = dynamic_cast<const SVertexIterator*>(&it);
+ if (!it_exact)
+ return false;
+ return (_vertex == it_exact->_vertex);
+ }
+
+ virtual SVertexIterator *copy() const
+ {
+ return new SVertexIterator(*this);
+ }
+
+private:
+ SVertex *_vertex;
+ SVertex *_begin;
+ FEdge *_previous_edge;
+ FEdge *_next_edge;
+ float _t; // curvilinear abscissa
+};
+
+
+//
+// ViewEdgeIterator (base class)
+//
+///////////////////////////////////////////////////////////
+
+/*! Base class for iterators over ViewEdges of the ViewMap Graph.
+ * Basically the "increment()" operator of this class should be able to take the decision of "where" (on which
+ * ViewEdge) to go when pointing on a given ViewEdge.
+ * ::Caution::: the dereferencing operator returns a *pointer* to the pointed ViewEdge.
+ */
+class ViewEdgeIterator : public Iterator
+{
+public:
+ /*! Builds a ViewEdgeIterator from a starting ViewEdge and its orientation.
+ * \param begin
+ * The ViewEdge from where to start the iteration.
+ * \param orientation
+ * If true, we'll look for the next ViewEdge among the ViewEdges that surround the ending ViewVertex of begin.
+ * If false, we'll search over the ViewEdges surrounding the ending ViewVertex of begin.
+ */
+ ViewEdgeIterator(ViewEdge *begin = NULL, bool orientation = true)
+ {
+ _orientation = orientation;
+ _edge = begin;
+ _begin = begin;
+ }
+
+ /*! Copy constructor */
+ ViewEdgeIterator(const ViewEdgeIterator& it)
+ {
+ _orientation = it._orientation;
+ _edge = it._edge;
+ _begin = it._begin;
+ }
+
+ virtual ~ViewEdgeIterator() {}
+
+ /*! Returns the string "ViewEdgeIterator" */
+ virtual string getExactTypeName() const
+ {
+ return "ViewEdgeIterator";
+ }
+
+ /*! Returns the current pointed ViewEdge. */
+ ViewEdge *getCurrentEdge()
+ {
+ return _edge;
+ }
+
+ /*! Sets the current pointed ViewEdge. */
+ void setCurrentEdge(ViewEdge *edge)
+ {
+ _edge = edge;
+ }
+
+ /*! Returns the first ViewEdge used for the iteration. */
+ ViewEdge *getBegin()
+ {
+ return _begin;
+ }
+
+ /*! Sets the first ViewEdge used for the iteration. */
+ void setBegin(ViewEdge *begin)
+ {
+ _begin = begin;
+ }
+
+ /*! Gets the orientation of the pointed ViewEdge in the iteration. */
+ bool getOrientation() const
+ {
+ return _orientation;
+ }
+
+ /*! Sets the orientation of the pointed ViewEdge in the iteration. */
+ void setOrientation(bool orientation)
+ {
+ _orientation = orientation;
+ }
+
+ /*! Changes the current orientation. */
+ void changeOrientation()
+ {
+ _orientation = !_orientation;
+ }
+
+ /*! Returns a *pointer* to the pointed ViewEdge. */
+ virtual ViewEdge *operator*()
+ {
+ return _edge;
+ }
+
+ virtual ViewEdge *operator->()
+ {
+ return operator*();
+ }
+
+ /*! Increments. In the scripting language, call "increment()". */
+ virtual ViewEdgeIterator& operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ /*! Increments. In the scripting language, call "increment()". */
+ virtual ViewEdgeIterator operator++(int)
+ {
+ ViewEdgeIterator tmp(*this);
+ increment();
+ return tmp;
+ }
+
+ /*! increments. */
+ virtual int increment()
+ {
+ cerr << "Warning: method increment() not implemented" << endl;
+ return 0;
+ }
+
+ /*! Decrements. In the scripting language, call "decrement()". */
+ virtual ViewEdgeIterator& operator--()
+ {
+ decrement();
+ return *this;
+ }
+
+ /*! Decrements. In the scripting language, call "decrement()". */
+ virtual ViewEdgeIterator operator--(int)
+ {
+ ViewEdgeIterator tmp(*this);
+ decrement();
+ return tmp;
+ }
+
+ /*! decrements. */
+ virtual int decrement()
+ {
+ cerr << "Warning: method decrement() not implemented" << endl;
+ return 0;
+ }
+
+ /*! Returns true if the pointed ViewEdge is the first one used for the iteration. */
+ virtual bool isBegin() const
+ {
+ return _edge == _begin;
+ }
+
+ /*! Returns true if the pointed ViewEdge* equals 0. */
+ virtual bool isEnd() const
+ {
+ return !_edge;
+ }
+
+ /*! operator == */
+ virtual bool operator==(ViewEdgeIterator& it) const
+ {
+ return _edge == it._edge;
+ }
+
+ /*! operator != */
+ virtual bool operator!=(ViewEdgeIterator& it) const
+ {
+ return !(*this == it);
+ }
+
+protected:
+ bool _orientation;
+ ViewEdge *_edge;
+ ViewEdge *_begin;
+};
+
+} // end of namespace ViewEdgeInternal
+
+#endif // __FREESTYLE_VIEW_MAP_ITERATORS_H__
diff --git a/source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp b/source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp
new file mode 100644
index 00000000000..d1adc55d3ac
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp
@@ -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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/view_map/ViewMapTesselator.cpp
+ * \ingroup freestyle
+ * \brief Class to build a Node Tree designed to be displayed from a Silhouette View Map structure.
+ * \author Stephane Grabli
+ * \date 26/03/2002
+ */
+
+#include "ViewMapTesselator.h"
+
+NodeGroup *ViewMapTesselator::Tesselate(ViewMap *iViewMap)
+{
+ if (0 == iViewMap->ViewEdges().size())
+ return NULL;
+
+ const vector<ViewEdge*>& viewedges = iViewMap->ViewEdges();
+ return Tesselate(viewedges.begin(), viewedges.end());
+}
+
+NodeGroup *ViewMapTesselator::Tesselate(WShape *)
+{
+ return NULL;
+}
diff --git a/source/blender/freestyle/intern/view_map/ViewMapTesselator.h b/source/blender/freestyle/intern/view_map/ViewMapTesselator.h
new file mode 100644
index 00000000000..c1ed7e3926a
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapTesselator.h
@@ -0,0 +1,211 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_VIEW_MAP_TESSELATOR_H__
+#define __FREESTYLE_VIEW_MAP_TESSELATOR_H__
+
+/** \file blender/freestyle/intern/view_map/ViewMapTesselator.h
+ * \ingroup freestyle
+ * \brief Class to build a Node Tree designed to be displayed from a Silhouette View Map structure.
+ * \author Stephane Grabli
+ * \date 26/03/2002
+ */
+
+#include "Silhouette.h"
+#include "ViewMap.h"
+
+#include "../scene_graph/LineRep.h"
+#include "../scene_graph/NodeShape.h"
+#include "../scene_graph/NodeGroup.h"
+#include "../scene_graph/OrientedLineRep.h"
+#include "../scene_graph/VertexRep.h"
+
+#include "../winged_edge/WEdge.h"
+
+class NodeShape;
+class NodeGroup;
+class SShape;
+class WShape;
+
+class LIB_VIEW_MAP_EXPORT ViewMapTesselator
+{
+public:
+ inline ViewMapTesselator()
+ {
+ _nature = Nature::SILHOUETTE | Nature::BORDER | Nature::CREASE;
+ _FrsMaterial.setDiffuse(0, 0, 0, 1);
+ _overloadFrsMaterial = false;
+ }
+
+ virtual ~ViewMapTesselator() {}
+
+ /*! Builds a set of lines rep contained under a a NodeShape, itself contained under a NodeGroup from a ViewMap */
+ NodeGroup *Tesselate(ViewMap *iViewMap);
+
+ /*! Builds a set of lines rep contained under a a NodeShape, itself contained under a NodeGroup from a set of
+ * view edges
+ */
+ template<class ViewEdgesIterator>
+ NodeGroup *Tesselate(ViewEdgesIterator begin, ViewEdgesIterator end);
+
+ /*! Builds a set of lines rep contained among a NodeShape, from a WShape */
+ NodeGroup *Tesselate(WShape *iWShape);
+
+ inline void setNature(Nature::EdgeNature iNature)
+ {
+ _nature = iNature;
+ }
+
+ inline void setFrsMaterial(const FrsMaterial& iMaterial)
+ {
+ _FrsMaterial = iMaterial;
+ _overloadFrsMaterial = true;
+ }
+
+ inline Nature::EdgeNature nature()
+ {
+ return _nature;
+ }
+
+ inline const FrsMaterial& frs_material() const
+ {
+ return _FrsMaterial;
+ }
+
+protected:
+ virtual void AddVertexToLine(LineRep *iLine, SVertex *v) = 0;
+
+private:
+ Nature::EdgeNature _nature;
+ FrsMaterial _FrsMaterial;
+ bool _overloadFrsMaterial;
+};
+
+/*! Class to tesselate the 2D projected silhouette */
+class ViewMapTesselator2D : public ViewMapTesselator
+{
+public:
+ inline ViewMapTesselator2D() : ViewMapTesselator() {}
+ virtual ~ViewMapTesselator2D() {}
+
+protected:
+ virtual void AddVertexToLine(LineRep *iLine, SVertex *v)
+ {
+ iLine->AddVertex(v->point2D());
+ }
+};
+
+/*! Class to tesselate the 3D silhouette */
+class ViewMapTesselator3D : public ViewMapTesselator
+{
+public:
+ inline ViewMapTesselator3D() : ViewMapTesselator() {}
+ virtual ~ViewMapTesselator3D() {}
+
+protected:
+ virtual void AddVertexToLine(LineRep *iLine, SVertex *v)
+ {
+ iLine->AddVertex(v->point3D());
+ }
+};
+
+//
+// Implementation
+//
+///////////////////////////////////////////////
+
+template<class ViewEdgesIterator>
+NodeGroup *ViewMapTesselator::Tesselate(ViewEdgesIterator begin, ViewEdgesIterator end)
+{
+ NodeGroup *group = new NodeGroup;
+ NodeShape *tshape = new NodeShape;
+ group->AddChild(tshape);
+ //tshape->frs_material().setDiffuse(0.0f, 0.0f, 0.0f, 1.0f);
+ tshape->setFrsMaterial(_FrsMaterial);
+
+ LineRep *line;
+
+ FEdge *firstEdge;
+ FEdge *nextFEdge, *currentEdge;
+
+ int id = 0;
+ //for (vector<ViewEdge*>::const_iterator c = viewedges.begin(), cend = viewedges.end(); c != cend; c++)
+ for (ViewEdgesIterator c = begin, cend = end; c != cend; c++) {
+#if 0
+ if ((*c)->qi() > 0) {
+ continue;
+ }
+ if (!((*c)->nature() & (_nature))) {
+ continue;
+ }
+#endif
+ firstEdge = (*c)->fedgeA();
+
+#if 0
+ if (firstEdge->invisibility() > 0)
+ continue;
+#endif
+
+ line = new OrientedLineRep();
+ if (_overloadFrsMaterial)
+ line->setFrsMaterial(_FrsMaterial);
+
+ // there might be chains containing a single element
+ if (0 == (firstEdge)->nextEdge()) {
+ line->setStyle(LineRep::LINES);
+ //line->AddVertex((*c)->vertexA()->point3D());
+ //line->AddVertex((*c)->vertexB()->point3D());
+ AddVertexToLine(line, firstEdge->vertexA());
+ AddVertexToLine(line, firstEdge->vertexB());
+ }
+ else {
+ line->setStyle(LineRep::LINE_STRIP);
+
+ //firstEdge = (*c);
+ nextFEdge = firstEdge;
+ currentEdge = firstEdge;
+ do {
+ //line->AddVertex(nextFEdge->vertexA()->point3D());
+ AddVertexToLine(line, nextFEdge->vertexA());
+ currentEdge = nextFEdge;
+ nextFEdge = nextFEdge->nextEdge();
+ } while ((nextFEdge != NULL) && (nextFEdge != firstEdge));
+ // Add the last vertex
+ //line->AddVertex(currentEdge->vertexB()->point3D());
+ AddVertexToLine(line, currentEdge->vertexB());
+ }
+
+ line->setId((*c)->getId().getFirst());
+ line->ComputeBBox();
+ tshape->AddRep(line);
+ id++;
+ }
+
+ return group;
+}
+
+#endif // __FREESTYLE_VIEW_MAP_TESSELATOR_H__
diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.cpp b/source/blender/freestyle/intern/winged_edge/Curvature.cpp
new file mode 100644
index 00000000000..5cf45a2a934
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/Curvature.cpp
@@ -0,0 +1,642 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * This Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is:
+ * GTS - Library for the manipulation of triangulated surfaces
+ * Copyright (C) 1999 Stephane Popinet
+ * and:
+ * OGF/Graphite: Geometry and Graphics Programming Library + Utilities
+ * Copyright (C) 2000-2003 Bruno Levy
+ * Contact: Bruno Levy levy@loria.fr
+ * ISA Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/winged_edge/Curvature.cpp
+ * \ingroup freestyle
+ * \brief GTS - Library for the manipulation of triangulated surfaces
+ * \author Stephane Popinet
+ * \date 1999
+ * \brief OGF/Graphite: Geometry and Graphics Programming Library + Utilities
+ * \author Bruno Levy
+ * \date 2000-2003
+ */
+
+#include <assert.h>
+#include <cstdlib> // for malloc and free
+#include <math.h>
+#include <set>
+#include <stack>
+
+#include "Curvature.h"
+#include "WEdge.h"
+
+#include "../geometry/normal_cycle.h"
+
+#include "../system/FreestyleConfig.h"
+
+static bool angle_obtuse(WVertex *v, WFace *f)
+{
+ WOEdge *e;
+ f->getOppositeEdge(v, e);
+
+ Vec3r vec1(e->GetaVertex()->GetVertex() - v->GetVertex());
+ Vec3r vec2(e->GetbVertex()->GetVertex() - v->GetVertex());
+ return ((vec1 * vec2) < 0);
+}
+
+// FIXME
+// WVvertex is useless but kept for history reasons
+static bool triangle_obtuse(WVertex *, WFace *f)
+{
+ bool b = false;
+ for (int i = 0; i < 3; i++)
+ b = b || ((f->getEdgeList()[i]->GetVec() * f->getEdgeList()[(i + 1) % 3]->GetVec()) < 0);
+ return b;
+}
+
+static real cotan(WVertex *vo, WVertex *v1, WVertex *v2)
+{
+ /* cf. Appendix B of [Meyer et al 2002] */
+ real udotv, denom;
+
+ Vec3r u(v1->GetVertex() - vo->GetVertex());
+ Vec3r v(v2->GetVertex() - vo->GetVertex());
+
+ udotv = u * v;
+ denom = sqrt(u.squareNorm() * v.squareNorm() - udotv * udotv);
+
+ /* denom can be zero if u==v. Returning 0 is acceptable, based on the callers of this function below. */
+ if (denom == 0.0)
+ return 0.0;
+ return (udotv / denom);
+}
+
+static real angle_from_cotan(WVertex *vo, WVertex *v1, WVertex *v2)
+{
+ /* cf. Appendix B and the caption of Table 1 from [Meyer et al 2002] */
+ real udotv, denom;
+
+ Vec3r u (v1->GetVertex() - vo->GetVertex());
+ Vec3r v(v2->GetVertex() - vo->GetVertex());
+
+ udotv = u * v;
+ denom = sqrt(u.squareNorm() * v.squareNorm() - udotv * udotv);
+
+ /* Note: I assume this is what they mean by using atan2(). -Ray Jones */
+
+ /* tan = denom/udotv = y/x (see man page for atan2) */
+ return (fabs(atan2(denom, udotv)));
+}
+
+/*! gts_vertex_mean_curvature_normal:
+ * @v: a #WVertex.
+ * @s: a #GtsSurface.
+ * @Kh: the Mean Curvature Normal at @v.
+ *
+ * Computes the Discrete Mean Curvature Normal approximation at @v.
+ * The mean curvature at @v is half the magnitude of the vector @Kh.
+ *
+ * Note: the normal computed is not unit length, and may point either into or out of the surface, depending on
+ * the curvature at @v. It is the responsibility of the caller of the function to use the mean curvature normal
+ * appropriately.
+ *
+ * This approximation is from the paper:
+ * Discrete Differential-Geometry Operators for Triangulated 2-Manifolds
+ * Mark Meyer, Mathieu Desbrun, Peter Schroder, Alan H. Barr
+ * VisMath '02, Berlin (Germany)
+ * http://www-grail.usc.edu/pubs.html
+ *
+ * Returns: %TRUE if the operator could be evaluated, %FALSE if the evaluation failed for some reason (@v is
+ * boundary or is the endpoint of a non-manifold edge.)
+ */
+bool gts_vertex_mean_curvature_normal(WVertex *v, Vec3r &Kh)
+{
+ real area = 0.0;
+
+ if (!v)
+ return false;
+
+ /* this operator is not defined for boundary edges */
+ if (v->isBoundary())
+ return false;
+
+ WVertex::incoming_edge_iterator itE;
+
+ for (itE = v->incoming_edges_begin(); itE != v->incoming_edges_end(); itE++)
+ area += (*itE)->GetaFace()->getArea();
+
+ Kh = Vec3r(0.0, 0.0, 0.0);
+
+ for (itE = v->incoming_edges_begin(); itE != v->incoming_edges_end(); itE++) {
+ WOEdge *e = (*itE)->getPrevOnFace();
+#if 0
+ if ((e->GetaVertex() == v) || (e->GetbVertex() == v))
+ cerr<< "BUG ";
+#endif
+ WVertex *v1 = e->GetaVertex();
+ WVertex *v2 = e->GetbVertex();
+ real temp;
+
+ temp = cotan(v1, v, v2);
+ Kh = Vec3r(Kh + temp * (v2->GetVertex() - v->GetVertex()));
+
+ temp = cotan(v2, v, v1);
+ Kh = Vec3r(Kh + temp * (v1->GetVertex() - v->GetVertex()));
+ }
+ if (area > 0.0) {
+ Kh[0] /= 2 * area;
+ Kh[1] /= 2 * area;
+ Kh[2] /= 2 * area;
+ }
+ else {
+ return false;
+ }
+
+ return true;
+}
+
+/*! gts_vertex_gaussian_curvature:
+ * @v: a #WVertex.
+ * @s: a #GtsSurface.
+ * @Kg: the Discrete Gaussian Curvature approximation at @v.
+ *
+ * Computes the Discrete Gaussian Curvature approximation at @v.
+ *
+ * This approximation is from the paper:
+ * Discrete Differential-Geometry Operators for Triangulated 2-Manifolds
+ * Mark Meyer, Mathieu Desbrun, Peter Schroder, Alan H. Barr
+ * VisMath '02, Berlin (Germany)
+ * http://www-grail.usc.edu/pubs.html
+ *
+ * Returns: %TRUE if the operator could be evaluated, %FALSE if the evaluation failed for some reason (@v is
+ * boundary or is the endpoint of a non-manifold edge.)
+ */
+bool gts_vertex_gaussian_curvature(WVertex *v, real *Kg)
+{
+ real area = 0.0;
+ real angle_sum = 0.0;
+
+ if (!v)
+ return false;
+ if (!Kg)
+ return false;
+
+ /* this operator is not defined for boundary edges */
+ if (v->isBoundary()) {
+ *Kg = 0.0;
+ return false;
+ }
+
+ 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++) {
+ WOEdge *e = (*itE)->getPrevOnFace();
+ WVertex *v1 = e->GetaVertex();
+ WVertex *v2 = e->GetbVertex();
+ angle_sum += angle_from_cotan(v, v1, v2);
+ }
+
+ *Kg = (2.0 * M_PI - angle_sum) / area;
+
+ return true;
+}
+
+/*! gts_vertex_principal_curvatures:
+ * @Kh: mean curvature.
+ * @Kg: Gaussian curvature.
+ * @K1: first principal curvature.
+ * @K2: second principal curvature.
+ *
+ * Computes the principal curvatures at a point given the mean and Gaussian curvatures at that point.
+ *
+ * The mean curvature can be computed as one-half the magnitude of the vector computed by
+ * gts_vertex_mean_curvature_normal().
+ *
+ * The Gaussian curvature can be computed with gts_vertex_gaussian_curvature().
+ */
+void gts_vertex_principal_curvatures (real Kh, real Kg, real *K1, real *K2)
+{
+ real temp = Kh * Kh - Kg;
+
+ if (!K1 || !K2)
+ return;
+
+ if (temp < 0.0)
+ temp = 0.0;
+ temp = sqrt (temp);
+ *K1 = Kh + temp;
+ *K2 = Kh - temp;
+}
+
+/* from Maple */
+static void linsolve(real m11, real m12, real b1, real m21, real m22, real b2, real *x1, real *x2)
+{
+ real temp;
+
+ temp = 1.0 / (m21 * m12 - m11 * m22);
+ *x1 = (m12 * b2 - m22 * b1) * temp;
+ *x2 = (m11 * b2 - m21 * b1) * temp;
+}
+
+/* from Maple - largest eigenvector of [a b; b c] */
+static void eigenvector(real a, real b, real c, Vec3r e)
+{
+ if (b == 0.0) {
+ e[0] = 0.0;
+ }
+ else {
+ e[0] = -(c - a - sqrt(c * c - 2 * a * c + a * a + 4 * b * b)) / (2 * b);
+ }
+ e[1] = 1.0;
+ e[2] = 0.0;
+}
+
+/*! gts_vertex_principal_directions:
+ * @v: a #WVertex.
+ * @s: a #GtsSurface.
+ * @Kh: mean curvature normal (a #Vec3r).
+ * @Kg: Gaussian curvature (a real).
+ * @e1: first principal curvature direction (direction of largest curvature).
+ * @e2: second principal curvature direction.
+ *
+ * Computes the principal curvature directions at a point given @Kh and @Kg, the mean curvature normal and
+ * Gaussian curvatures at that point, computed with gts_vertex_mean_curvature_normal() and
+ * gts_vertex_gaussian_curvature(), respectively.
+ *
+ * Note that this computation is very approximate and tends to be unstable. Smoothing of the surface or the principal
+ * directions may be necessary to achieve reasonable results.
+ */
+void gts_vertex_principal_directions(WVertex *v, Vec3r Kh, real Kg, Vec3r &e1, Vec3r &e2)
+{
+ Vec3r N;
+ real normKh;
+
+ Vec3r basis1, basis2, d, eig;
+ real ve2, vdotN;
+ real aterm_da, bterm_da, cterm_da, const_da;
+ real aterm_db, bterm_db, cterm_db, const_db;
+ real a, b, c;
+ real K1, K2;
+ real *weights, *kappas, *d1s, *d2s;
+ int edge_count;
+ real err_e1, err_e2;
+ int e;
+ WVertex::incoming_edge_iterator itE;
+
+ /* compute unit normal */
+ normKh = Kh.norm();
+
+ if (normKh > 0.0) {
+ Kh.normalize();
+ }
+ else {
+ /* This vertex is a point of zero mean curvature (flat or saddle point). Compute a normal by averaging
+ * the adjacent triangles
+ */
+ N[0] = N[1] = N[2] = 0.0;
+
+ for (itE = v->incoming_edges_begin(); itE != v->incoming_edges_end(); itE++)
+ N = Vec3r(N + (*itE)->GetaFace()->GetNormal());
+ real normN = N.norm();
+ if (normN <= 0.0)
+ return;
+ N.normalize();
+ }
+
+ /* construct a basis from N: */
+ /* set basis1 to any component not the largest of N */
+ basis1[0] = basis1[1] = basis1[2] = 0.0;
+ if (fabs (N[0]) > fabs (N[1]))
+ basis1[1] = 1.0;
+ else
+ basis1[0] = 1.0;
+
+ /* make basis2 orthogonal to N */
+ basis2 = (N ^ basis1);
+ basis2.normalize();
+
+ /* make basis1 orthogonal to N and basis2 */
+ basis1 = (N ^ basis2);
+ basis1.normalize();
+
+ aterm_da = bterm_da = cterm_da = const_da = 0.0;
+ aterm_db = bterm_db = cterm_db = const_db = 0.0;
+ int nb_edges = v->GetEdges().size();
+
+ weights = (real *)malloc(sizeof(real) * nb_edges);
+ kappas = (real *)malloc(sizeof(real) * nb_edges);
+ d1s = (real *)malloc(sizeof(real) * nb_edges);
+ d2s = (real *)malloc(sizeof(real) * nb_edges);
+ edge_count = 0;
+
+ for (itE = v->incoming_edges_begin(); itE != v->incoming_edges_end(); itE++) {
+ WOEdge *e;
+ WFace *f1, *f2;
+ real weight, kappa, d1, d2;
+ Vec3r vec_edge;
+ if (!*itE)
+ continue;
+ e = *itE;
+
+ /* since this vertex passed the tests in gts_vertex_mean_curvature_normal(), this should be true. */
+ //g_assert(gts_edge_face_number (e, s) == 2);
+
+ /* identify the two triangles bordering e in s */
+ f1 = e->GetaFace();
+ f2 = e->GetbFace();
+
+ /* We are solving for the values of the curvature tensor
+ * B = [ a b ; b c ].
+ * The computations here are from section 5 of [Meyer et al 2002].
+ *
+ * The first step is to calculate the linear equations governing the values of (a,b,c). These can be computed
+ * by setting the derivatives of the error E to zero (section 5.3).
+ *
+ * Since a + c = norm(Kh), we only compute the linear equations for dE/da and dE/db. (NB: [Meyer et al 2002]
+ * has the equation a + b = norm(Kh), but I'm almost positive this is incorrect).
+ *
+ * Note that the w_ij (defined in section 5.2) are all scaled by (1/8*A_mixed). We drop this uniform scale
+ * factor because the solution of the linear equations doesn't rely on it.
+ *
+ * The terms of the linear equations are xterm_dy with x in {a,b,c} and y in {a,b}. There are also const_dy
+ * terms that are the constant factors in the equations.
+ */
+
+ /* find the vector from v along edge e */
+ vec_edge = Vec3r(-1 * e->GetVec());
+
+ ve2 = vec_edge.squareNorm();
+ vdotN = vec_edge * N;
+
+ /* section 5.2 - There is a typo in the computation of kappa. The edges should be x_j-x_i. */
+ kappa = 2.0 * vdotN / ve2;
+
+ /* section 5.2 */
+
+ /* I don't like performing a minimization where some of the weights can be negative (as can be the case
+ * if f1 or f2 are obtuse). To ensure all-positive weights, we check for obtuseness. */
+ weight = 0.0;
+ if (!triangle_obtuse(v, f1)) {
+ weight += ve2 * cotan(f1->GetNextOEdge(e->twin())->GetbVertex(), e->GetaVertex(), e->GetbVertex()) / 8.0;
+ }
+ else {
+ if (angle_obtuse(v, f1)) {
+ weight += ve2 * f1->getArea() / 4.0;
+ }
+ else {
+ weight += ve2 * f1->getArea() / 8.0;
+ }
+ }
+
+ if (!triangle_obtuse(v, f2)) {
+ weight += ve2 * cotan (f2->GetNextOEdge(e)->GetbVertex(), e->GetaVertex(), e->GetbVertex()) / 8.0;
+ }
+ else {
+ if (angle_obtuse(v, f2)) {
+ weight += ve2 * f1->getArea() / 4.0;
+ }
+ else {
+ weight += ve2 * f1->getArea() / 8.0;
+ }
+ }
+
+ /* projection of edge perpendicular to N (section 5.3) */
+ d[0] = vec_edge[0] - vdotN * N[0];
+ d[1] = vec_edge[1] - vdotN * N[1];
+ d[2] = vec_edge[2] - vdotN * N[2];
+ d.normalize();
+
+ /* not explicit in the paper, but necessary. Move d to 2D basis. */
+ d1 = d * basis1;
+ d2 = d * basis2;
+
+ /* store off the curvature, direction of edge, and weights for later use */
+ weights[edge_count] = weight;
+ kappas[edge_count] = kappa;
+ d1s[edge_count] = d1;
+ d2s[edge_count] = d2;
+ edge_count++;
+
+ /* Finally, update the linear equations */
+ aterm_da += weight * d1 * d1 * d1 * d1;
+ bterm_da += weight * d1 * d1 * 2 * d1 * d2;
+ cterm_da += weight * d1 * d1 * d2 * d2;
+ const_da += weight * d1 * d1 * (-kappa);
+
+ aterm_db += weight * d1 * d2 * d1 * d1;
+ bterm_db += weight * d1 * d2 * 2 * d1 * d2;
+ cterm_db += weight * d1 * d2 * d2 * d2;
+ const_db += weight * d1 * d2 * (-kappa);
+ }
+
+ /* now use the identity (Section 5.3) a + c = |Kh| = 2 * kappa_h */
+ aterm_da -= cterm_da;
+ const_da += cterm_da * normKh;
+
+ aterm_db -= cterm_db;
+ const_db += cterm_db * normKh;
+
+ /* check for solvability of the linear system */
+ if (((aterm_da * bterm_db - aterm_db * bterm_da) != 0.0) && ((const_da != 0.0) || (const_db != 0.0))) {
+ linsolve(aterm_da, bterm_da, -const_da, aterm_db, bterm_db, -const_db, &a, &b);
+
+ c = normKh - a;
+
+ eigenvector(a, b, c, eig);
+ }
+ else {
+ /* region of v is planar */
+ eig[0] = 1.0;
+ eig[1] = 0.0;
+ }
+
+ /* Although the eigenvectors of B are good estimates of the principal directions, it seems that which one is
+ * attached to which curvature direction is a bit arbitrary. This may be a bug in my implementation, or just
+ * a side-effect of the inaccuracy of B due to the discrete nature of the sampling.
+ *
+ * To overcome this behavior, we'll evaluate which assignment best matches the given eigenvectors by comparing
+ * the curvature estimates computed above and the curvatures calculated from the discrete differential operators.
+ */
+
+ gts_vertex_principal_curvatures(0.5 * normKh, Kg, &K1, &K2);
+
+ err_e1 = err_e2 = 0.0;
+ /* loop through the values previously saved */
+ for (e = 0; e < edge_count; e++) {
+ real weight, kappa, d1, d2;
+ real temp1, temp2;
+ real delta;
+
+ weight = weights[e];
+ kappa = kappas[e];
+ d1 = d1s[e];
+ d2 = d2s[e];
+
+ temp1 = fabs (eig[0] * d1 + eig[1] * d2);
+ temp1 = temp1 * temp1;
+ temp2 = fabs (eig[1] * d1 - eig[0] * d2);
+ temp2 = temp2 * temp2;
+
+ /* err_e1 is for K1 associated with e1 */
+ delta = K1 * temp1 + K2 * temp2 - kappa;
+ err_e1 += weight * delta * delta;
+
+ /* err_e2 is for K1 associated with e2 */
+ delta = K2 * temp1 + K1 * temp2 - kappa;
+ err_e2 += weight * delta * delta;
+ }
+ free (weights);
+ free (kappas);
+ free (d1s);
+ free (d2s);
+
+ /* rotate eig by a right angle if that would decrease the error */
+ if (err_e2 < err_e1) {
+ real temp = eig[0];
+
+ eig[0] = eig[1];
+ eig[1] = -temp;
+ }
+
+ e1[0] = eig[0] * basis1[0] + eig[1] * basis2[0];
+ e1[1] = eig[0] * basis1[1] + eig[1] * basis2[1];
+ e1[2] = eig[0] * basis1[2] + eig[1] * basis2[2];
+ e1.normalize();
+
+ /* make N,e1,e2 a right handed coordinate sytem */
+ e2 = N ^ e1;
+ e2.normalize();
+}
+
+namespace OGF {
+
+inline static real angle(WOEdge *h)
+{
+ const Vec3r& n1 = h->GetbFace()->GetNormal();
+ const Vec3r& n2 = h->GetaFace()->GetNormal();
+ const Vec3r v = h->getVec3r();
+ real sine = (n1 ^ n2) * v / v.norm();
+ if (sine >= 1.0) {
+ return M_PI / 2.0;
+ }
+ if (sine <= -1.0) {
+ return -M_PI / 2.0;
+ }
+ return ::asin(sine);
+}
+
+// precondition1: P is inside the sphere
+// precondition2: P,V points to the outside of the sphere (i.e. OP.V > 0)
+static bool sphere_clip_vector(const Vec3r& O, real r, const Vec3r& P, Vec3r& V)
+{
+ Vec3r W = P - O;
+ real a = V.squareNorm();
+ real b = 2.0 * V * W;
+ real c = W.squareNorm() - r * r;
+ real delta = b * b - 4 * a * c;
+ if (delta < 0) {
+ // Should not happen, but happens sometimes (numerical precision)
+ return true;
+ }
+ real t = - b + ::sqrt(delta) / (2.0 * a);
+ if (t < 0.0) {
+ // Should not happen, but happens sometimes (numerical precision)
+ return true;
+ }
+ if (t >= 1.0) {
+ // Inside the sphere
+ return false;
+ }
+
+ V[0] = (t * V.x());
+ V[1] = (t * V.y());
+ V[2] = (t * V.z());
+
+ return true;
+}
+
+// TODO: check optimizations:
+// use marking ? (measure *timings* ...)
+void compute_curvature_tensor(WVertex *start, real radius, NormalCycle& nc)
+{
+ // in case we have a non-manifold vertex, skip it...
+ if (start->isBoundary())
+ return;
+
+ std::set<WVertex*> vertices;
+ const Vec3r& O = start->GetVertex();
+ std::stack<WVertex*> S;
+ S.push(start);
+ vertices.insert(start);
+ while (!S.empty()) {
+ WVertex *v = S.top();
+ S.pop();
+ if (v->isBoundary())
+ continue;
+ const Vec3r& P = v->GetVertex();
+ WVertex::incoming_edge_iterator woeit = v->incoming_edges_begin();
+ WVertex::incoming_edge_iterator woeitend = v->incoming_edges_end();
+ for (; woeit != woeitend; ++woeit) {
+ WOEdge *h = *woeit;
+ if ((v == start) || h->GetVec() * (O - P) > 0.0) {
+ Vec3r V(-1 * h->GetVec());
+ bool isect = sphere_clip_vector(O, radius, P, V);
+ assert (h->GetOwner()->GetNumberOfOEdges() == 2); // Because otherwise v->isBoundary() would be true
+ nc.accumulate_dihedral_angle(V, h->GetAngle());
+
+ if (!isect) {
+ WVertex *w = h->GetaVertex();
+ if (vertices.find(w) == vertices.end()) {
+ vertices.insert(w);
+ S.push(w);
+ }
+ }
+ }
+ }
+ }
+}
+
+void compute_curvature_tensor_one_ring(WVertex *start, NormalCycle& nc)
+{
+ // in case we have a non-manifold vertex, skip it...
+ if (start->isBoundary())
+ return;
+
+ WVertex::incoming_edge_iterator woeit = start->incoming_edges_begin();
+ WVertex::incoming_edge_iterator woeitend = start->incoming_edges_end();
+ for (; woeit != woeitend; ++woeit) {
+ WOEdge *h = (*woeit)->twin();
+ nc.accumulate_dihedral_angle(h->GetVec(), h->GetAngle());
+ WOEdge *hprev = h->getPrevOnFace();
+ nc.accumulate_dihedral_angle(hprev->GetVec(), hprev->GetAngle());
+ }
+}
+
+} // OGF namespace
diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.h b/source/blender/freestyle/intern/winged_edge/Curvature.h
new file mode 100644
index 00000000000..20450dbdb38
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/Curvature.h
@@ -0,0 +1,143 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * This Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is:
+ * GTS - Library for the manipulation of triangulated surfaces
+ * Copyright (C) 1999 Stephane Popinet
+ * and:
+ * OGF/Graphite: Geometry and Graphics Programming Library + Utilities
+ * Copyright (C) 2000-2003 Bruno Levy
+ * Contact: Bruno Levy levy@loria.fr
+ * ISA Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_CURVATURE_H__
+#define __FREESTYLE_CURVATURE_H__
+
+/** \file blender/freestyle/intern/winged_edge/Curvature.h
+ * \ingroup freestyle
+ * \brief GTS - Library for the manipulation of triangulated surfaces
+ * \author Stephane Popinet
+ * \date 1999
+ * \brief OGF/Graphite: Geometry and Graphics Programming Library + Utilities
+ * \author Bruno Levy
+ * \date 2000-2003
+ */
+
+#include "../geometry/Geom.h"
+
+#include "../system/FreestyleConfig.h"
+#include "../system/Precision.h"
+
+using namespace Geometry;
+
+class WVertex;
+
+class LIB_WINGED_EDGE_EXPORT CurvatureInfo
+{
+public:
+ CurvatureInfo()
+ {
+ K1 = 0.0;
+ K2 = 0.0;
+ e1 = Vec3r(0.0, 0.0, 0.0);
+ e2 = Vec3r(0.0, 0.0, 0.0);
+ Kr = 0.0;
+ dKr = 0.0;
+ er = Vec3r(0.0, 0.0, 0.0);
+ }
+
+ CurvatureInfo(const CurvatureInfo& iBrother)
+ {
+ K1 = iBrother.K1;
+ K2 = iBrother.K2;
+ e1 = iBrother.e1;
+ e2 = iBrother.e2;
+ Kr = iBrother.Kr;
+ dKr = iBrother.dKr;
+ er = iBrother.er;
+ }
+
+ CurvatureInfo(const CurvatureInfo& ca, const CurvatureInfo& cb, real t)
+ {
+ K1 = ca.K1 + t * (cb.K1 - ca.K1);
+ K2 = ca.K2 + t * (cb.K2 - ca.K2);
+ e1 = ca.e1 + t * (cb.e1 - ca.e1);
+ e2 = ca.e2 + t * (cb.e2 - ca.e2);
+ Kr = ca.Kr + t * (cb.Kr - ca.Kr);
+ dKr = ca.dKr + t * (cb.dKr - ca.dKr);
+ er = ca.er + t * (cb.er - ca.er);
+ }
+
+ real K1; // maximum curvature
+ real K2; // minimum curvature
+ Vec3r e1; // maximum curvature direction
+ Vec3r e2; // minimum curvature direction
+ real Kr; // radial curvature
+ real dKr; // radial curvature
+ Vec3r er; // radial curvature direction
+};
+
+class Face_Curvature_Info
+{
+public:
+ Face_Curvature_Info() {}
+
+ ~Face_Curvature_Info()
+ {
+ for (vector<CurvatureInfo*>::iterator ci = vec_curvature_info.begin(), ciend = vec_curvature_info.end();
+ ci != ciend;
+ ++ci)
+ {
+ delete (*ci);
+ }
+ vec_curvature_info.clear();
+ }
+
+ vector<CurvatureInfo *> vec_curvature_info;
+};
+
+bool LIB_WINGED_EDGE_EXPORT gts_vertex_mean_curvature_normal(WVertex *v, Vec3r &n);
+
+bool LIB_WINGED_EDGE_EXPORT gts_vertex_gaussian_curvature(WVertex *v, real *Kg);
+
+void LIB_WINGED_EDGE_EXPORT gts_vertex_principal_curvatures(real Kh, real Kg, real *K1, real *K2);
+
+void LIB_WINGED_EDGE_EXPORT gts_vertex_principal_directions(WVertex *v, Vec3r Kh, real Kg, Vec3r &e1, Vec3r &e2);
+
+namespace OGF {
+
+class NormalCycle ;
+
+void LIB_WINGED_EDGE_EXPORT compute_curvature_tensor( WVertex *start, double radius, NormalCycle& nc);
+
+void LIB_WINGED_EDGE_EXPORT compute_curvature_tensor_one_ring(WVertex *start, NormalCycle& nc);
+
+} // OGF namespace
+
+#endif /* __FREESTYLE_CURVATURE_H__ */
diff --git a/source/blender/freestyle/intern/winged_edge/Nature.h b/source/blender/freestyle/intern/winged_edge/Nature.h
new file mode 100644
index 00000000000..0ce64f3f1cb
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/Nature.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_NATURE_H__
+#define __FREESTYLE_NATURE_H__
+
+/** \file blender/freestyle/intern/winged_edge/Nature.h
+ * \ingroup freestyle
+ * \brief Different natures for both vertices and edges
+ * \author Emmanuel Turquin
+ * \date 01/07/2003
+ */
+
+/*! Namespace gathering the different possible natures of 0D and 1D elements of the ViewMap */
+namespace Nature {
+
+/* XXX Why not using enums??? */
+
+typedef unsigned short VertexNature;
+/*! true for any 0D element */
+static const VertexNature POINT = 0; // 0
+/*! true for SVertex */
+static const VertexNature S_VERTEX = (1 << 0); // 1
+/*! true for ViewVertex */
+static const VertexNature VIEW_VERTEX = (1 << 1); // 2
+/*! true for NonTVertex */
+static const VertexNature NON_T_VERTEX = (1 << 2); // 4
+/*! true for TVertex */
+static const VertexNature T_VERTEX = (1 << 3); // 8
+/*! true for CUSP */
+static const VertexNature CUSP = (1 << 4); // 16
+
+typedef unsigned short EdgeNature;
+/*! true for non feature edges (always false for 1D elements of the ViewMap) */
+static const EdgeNature NO_FEATURE = 0; // 0
+/*! true for silhouettes */
+static const EdgeNature SILHOUETTE = (1 << 0); // 1
+/*! true for borders */
+static const EdgeNature BORDER = (1 << 1); // 2
+/*! true for creases */
+static const EdgeNature CREASE = (1 << 2); // 4
+/*! true for ridges */
+static const EdgeNature RIDGE = (1 << 3); // 8
+/*! true for valleys */
+static const EdgeNature VALLEY = (1 << 4); // 16
+/*! true for suggestive contours */
+static const EdgeNature SUGGESTIVE_CONTOUR = (1 << 5); // 32
+/*! true for material boundaries */
+static const EdgeNature MATERIAL_BOUNDARY = (1 << 6); // 64
+/*! true for user-defined edge marks */
+static const EdgeNature EDGE_MARK = (1 << 7); // 128
+
+} // end of namespace Nature
+
+#endif // __FREESTYLE_NATURE_H__
diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.cpp b/source/blender/freestyle/intern/winged_edge/WEdge.cpp
new file mode 100644
index 00000000000..b3ac888361b
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WEdge.cpp
@@ -0,0 +1,714 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/winged_edge/WEdge.cpp
+ * \ingroup freestyle
+ * \brief Classes to define a Winged Edge data structure.
+ * \author Stephane Grabli
+ * \date 18/02/2002
+ */
+
+#include <iostream>
+
+#include "WEdge.h"
+
+/*! Temporary structures */
+class vertexdata
+{
+public:
+ WVertex *_copy;
+};
+
+class oedgedata
+{
+public:
+ WOEdge *_copy;
+};
+
+class edgedata
+{
+public:
+ WEdge *_copy;
+};
+
+class facedata
+{
+public:
+ WFace *_copy;
+};
+
+
+/**********************************
+ * *
+ * *
+ * WVertex *
+ * *
+ * *
+ **********************************/
+
+WVertex::WVertex(WVertex& iBrother)
+{
+ _Id = iBrother._Id;
+ _Vertex = iBrother._Vertex;
+ _EdgeList = iBrother._EdgeList;
+
+ _Shape = iBrother._Shape;
+ _Smooth = iBrother._Smooth;
+ _Border = iBrother._Border;
+ userdata = NULL;
+ iBrother.userdata = new vertexdata;
+ ((vertexdata *)(iBrother.userdata))->_copy = this;
+}
+
+WVertex *WVertex::duplicate()
+{
+ WVertex *clone = new WVertex(*this);
+ return clone;
+}
+
+WOEdge *WVertex::incoming_edge_iterator::operator*()
+{
+ return _current;
+}
+
+void WVertex::incoming_edge_iterator::increment()
+{
+ WOEdge *twin = _current->twin();
+ if (!twin) {
+ // we reached a hole
+ _current = 0;
+ return;
+ }
+ WOEdge *next = twin->getPrevOnFace();
+ if (next == _begin) {
+ next = NULL;
+ }
+ _current = next;
+}
+
+WFace *WVertex::face_iterator::operator*()
+{
+ WOEdge *woedge = *_edge_it;
+ if (!woedge)
+ return NULL;
+ return (woedge)->GetbFace();
+}
+
+#if 0
+bool WVertex::isBoundary () const
+{
+ return _Border;
+}
+#endif
+bool WVertex::isBoundary ()
+{
+ if (_Border == 1)
+ return true;
+ else if (_Border == 0)
+ return false;
+
+ vector<WEdge *>::const_iterator it;
+ for (it = _EdgeList.begin(); it != _EdgeList.end(); it++) {
+ if ((*it)->GetNumberOfOEdges() == 1) {
+ _Border = 1;
+ return true;
+ }
+ }
+#if 0
+ if (!(*it)->GetaOEdge()->GetaFace())
+ return true;
+#endif
+ _Border = 0;
+ return false;
+}
+
+void WVertex::AddEdge(WEdge *iEdge)
+{
+ _EdgeList.push_back(iEdge);
+}
+
+WVertex::incoming_edge_iterator WVertex::incoming_edges_begin()
+{
+ WOEdge *begin;
+ WEdge *wedge = _EdgeList.front();
+ WOEdge *aOEdge = wedge->GetaOEdge();
+ if (aOEdge->GetbVertex() == this)
+ begin = aOEdge;
+ else
+ begin = _EdgeList.front()->GetbOEdge();
+ return incoming_edge_iterator(this, begin, begin);
+}
+
+WVertex::incoming_edge_iterator WVertex::incoming_edges_end()
+{
+ WOEdge *begin;
+ WOEdge *aOEdge = _EdgeList.front()->GetaOEdge();
+ if (aOEdge->GetbVertex() == this)
+ begin = aOEdge;
+ else
+ begin = _EdgeList.front()->GetbOEdge();
+ return incoming_edge_iterator(this, begin, 0);
+}
+#if 0
+WOEdge **WVertex::incoming_edge_iterator::operator->()
+{
+ WOEdge **ppaOEdge = (*_iter)->GetaOEdge();
+ if (aOEdge->GetbVertex() == _vertex) {
+ return ppaOEdge;
+ }
+ else {
+ WOEdge *bOEdge = (*_iter)->GetbOEdge();
+ return &bOEdge;
+ }
+}
+#endif
+
+/**********************************
+ * *
+ * *
+ * WOEdge *
+ * *
+ * *
+ **********************************/
+
+WOEdge::WOEdge(WOEdge& iBrother)
+{
+ _paVertex = iBrother.GetaVertex();
+ _pbVertex = iBrother.GetbVertex();
+ _paFace = iBrother.GetaFace();
+ _pbFace = iBrother.GetbFace();
+ _pOwner = iBrother.GetOwner();
+ userdata = NULL;
+ iBrother.userdata = new oedgedata;
+ ((oedgedata *)(iBrother.userdata))->_copy = this;
+
+ _vec = iBrother._vec;
+ _angle = iBrother._angle;
+}
+
+WOEdge *WOEdge::duplicate()
+{
+ WOEdge *clone = new WOEdge(*this);
+ return clone;
+}
+
+Vec3r WOEdge::getVec3r ()
+{
+ return Vec3r(_pbVertex->GetVertex() - _paVertex->GetVertex());
+}
+
+WOEdge *WOEdge::twin ()
+{
+ return GetOwner()->GetOtherOEdge(this);
+}
+
+WOEdge *WOEdge::getPrevOnFace()
+{
+ return _pbFace->GetPrevOEdge(this);
+}
+
+/**********************************
+ * *
+ * *
+ * WEdge *
+ * *
+ * *
+ **********************************/
+
+WEdge::WEdge(WEdge& iBrother)
+{
+ _paOEdge = NULL;
+ _pbOEdge = NULL;
+ WOEdge *aoedge = iBrother.GetaOEdge();
+ WOEdge *boedge = iBrother.GetbOEdge();
+ userdata = NULL;
+
+ if (aoedge)
+ //_paOEdge = new WOEdge(*aoedge);
+ _paOEdge = aoedge->duplicate();
+ if (boedge)
+ //_pbOEdge = new WOEdge(*boedge);
+ _pbOEdge = boedge->duplicate();
+
+ _nOEdges = iBrother.GetNumberOfOEdges();
+ _Id = iBrother.GetId();
+ iBrother.userdata = new edgedata;
+ ((edgedata *)(iBrother.userdata))->_copy = this;
+}
+
+WEdge *WEdge::duplicate()
+{
+ WEdge *clone = new WEdge(*this);
+ return clone;
+}
+
+/**********************************
+ * *
+ * *
+ * WFace *
+ * *
+ * *
+ **********************************/
+
+WFace::WFace(WFace& iBrother)
+{
+ _OEdgeList = iBrother.getEdgeList();
+ _Normal = iBrother.GetNormal();
+ _VerticesNormals = iBrother._VerticesNormals;
+ _VerticesTexCoords = iBrother._VerticesTexCoords;
+ _Id = iBrother.GetId();
+ _FrsMaterialIndex = iBrother._FrsMaterialIndex;
+ _Mark = iBrother._Mark;
+ userdata = NULL;
+ iBrother.userdata = new facedata;
+ ((facedata *)(iBrother.userdata))->_copy = this;
+}
+
+WFace *WFace::duplicate()
+{
+ WFace *clone = new WFace(*this);
+ return clone;
+}
+
+const FrsMaterial& WFace::frs_material()
+{
+ return getShape()->frs_material(_FrsMaterialIndex);
+}
+
+WOEdge *WFace::MakeEdge(WVertex *v1, WVertex *v2)
+{
+ // First check whether the same oriented edge already exists or not:
+ vector<WEdge *>& v1Edges = v1->GetEdges();
+ for (vector<WEdge*>::iterator it1 = v1Edges.begin(), end = v1Edges.end(); it1 != end; it1++) {
+ WEdge *we = (*it1);
+ WOEdge *woea = we->GetaOEdge();
+
+ //if ((*it1)->GetbVertex() == v2) {
+ if ((woea->GetaVertex() == v1) && (woea->GetbVertex() == v2)) {
+ // The oriented edge already exists
+ cerr << "Warning: edge " << v1->GetId() << " - " << v2->GetId() << " appears twice, correcting" << endl;
+ // Adds the edge to the face
+ //AddEdge((*it1)->GetaOEdge());
+ AddEdge(woea);
+ (*it1)->setNumberOfOEdges((*it1)->GetNumberOfOEdges() + 1);
+ //sets these vertices as border:
+ v1->setBorder(true);
+ v2->setBorder(true);
+ //return (*it1)->GetaOEdge();
+ return woea;
+ }
+
+ WOEdge *woeb = we->GetbOEdge();
+ //if ((*it1)->GetbVertex() == v2)
+ if (woeb && (woeb->GetaVertex() == v1) && (woeb->GetbVertex() == v2)) {
+ // The oriented edge already exists
+ cerr << "Warning: edge " << v1->GetId() << " - " << v2->GetId() << " appears twice, correcting" << endl;
+ // Adds the edge to the face
+ //AddEdge((*it1)->GetaOEdge());
+ AddEdge(woeb);
+ (*it1)->setNumberOfOEdges((*it1)->GetNumberOfOEdges() + 1);
+ //sets these vertices as border:
+ v1->setBorder(true);
+ v2->setBorder(true);
+ //return (*it1)->GetaOEdge();
+ return woeb;
+ }
+ }
+
+ // the oriented edge we're about to build
+ WOEdge *pOEdge = new WOEdge;
+ // The edge containing the oriented edge.
+ WEdge *edge;
+
+ // checks whether this edge already exists or not
+ // If it exists, it points outward v2
+ bool exist = false;
+ WOEdge *pInvertEdge = NULL; // The inverted edge if it exists
+ vector<WEdge *>& v2Edges = v2->GetEdges();
+ vector<WEdge *>::iterator it;
+ for (it = v2Edges.begin(); it != v2Edges.end(); it++) {
+ if ((*it)->GetbVertex() == v1) {
+ // The invert edge already exists
+ exist = true;
+ pInvertEdge = (*it)->GetaOEdge();
+ break;
+ }
+ }
+
+ //DEBUG:
+ if (true == exist) { // The invert edge already exists
+ // Retrieves the corresponding edge
+ edge = pInvertEdge->GetOwner();
+
+ // Sets the a Face (retrieved from pInvertEdge
+ pOEdge->setaFace(pInvertEdge->GetbFace());
+
+ // Updates the invert edge:
+ pInvertEdge->setaFace(this);
+ }
+ else { // The invert edge does not exist yet
+ // we must create a new edge
+ //edge = new WEdge;
+ edge = instanciateEdge();
+
+ // updates the a,b vertex edges list:
+ v1->AddEdge(edge);
+ v2->AddEdge(edge);
+ }
+
+ pOEdge->setOwner(edge);
+ // Add the vertices:
+ pOEdge->setaVertex(v1);
+ pOEdge->setbVertex(v2);
+
+ // Debug:
+ if (v1->GetId() == v2->GetId())
+ cerr << "Warning: edge " << this << " null with vertex " << v1->GetId() << endl;
+
+ edge->AddOEdge(pOEdge);
+ //edge->setNumberOfOEdges(edge->GetNumberOfOEdges() + 1);
+
+ // Add this face (the b face)
+ pOEdge->setbFace(this);
+
+ // Adds the edge to the face
+ AddEdge(pOEdge);
+
+ return pOEdge;
+}
+
+
+bool WFace::getOppositeEdge(const WVertex *v, WOEdge *&e)
+{
+ if (_OEdgeList.size() != 3)
+ return false;
+
+ vector<WOEdge *>::iterator it;
+ e = NULL;
+ for (it = _OEdgeList.begin(); it != _OEdgeList.end(); it++) {
+ if ((*it)->GetaVertex() == v)
+ e = *it;
+ }
+ if (!e)
+ return false;
+ e = NULL;
+ for (it = _OEdgeList.begin(); it != _OEdgeList.end(); it++) {
+ if (((*it)->GetaVertex() != v) && ((*it)->GetbVertex() != v))
+ e = *it;
+ }
+ if (!e)
+ return false;
+ else
+ return true;
+}
+
+real WFace::getArea ()
+{
+ vector<WOEdge *>::iterator it;
+ Vec3r origin = (*(_OEdgeList.begin()))->GetaVertex()->GetVertex();
+ it = _OEdgeList.begin();
+ real 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;
+ }
+ return a;
+}
+
+
+WOEdge *WFace::GetPrevOEdge(WOEdge *iOEdge)
+{
+ vector<WOEdge *>::iterator woe, woend, woefirst;
+ woefirst = _OEdgeList.begin();
+ woend = _OEdgeList.end();
+ WOEdge *prev = *woefirst;
+ woe = woefirst;
+ ++woe;
+ for (; woe != woend; woe++) {
+ if ((*woe) == iOEdge)
+ return prev;
+ prev = *woe;
+ }
+ // We left the loop. That means that the first OEdge was the good one:
+ if ((*woefirst) == iOEdge)
+ return prev;
+
+ return NULL;
+}
+
+WShape *WFace::getShape()
+{
+ return GetVertex(0)->shape();
+}
+
+
+/**********************************
+ * *
+ * *
+ * WShape *
+ * *
+ * *
+ **********************************/
+
+LIB_WINGED_EDGE_EXPORT
+unsigned WShape::_SceneCurrentId = 0;
+
+WShape *WShape::duplicate()
+{
+ WShape *clone = new WShape(*this);
+ return clone;
+}
+
+WShape::WShape(WShape& iBrother)
+{
+ _Id = iBrother.GetId();
+ _Name = iBrother._Name;
+ _FrsMaterials = iBrother._FrsMaterials;
+ _meanEdgeSize = iBrother._meanEdgeSize;
+ iBrother.bbox(_min, _max);
+ vector<WVertex *>& vertexList = iBrother.getVertexList();
+ vector<WVertex *>::iterator v = vertexList.begin(), vend = vertexList.end();
+ for (; v != vend; ++v) {
+ //WVertex *newVertex = new WVertex(*(*v));
+ WVertex *newVertex = (*v)->duplicate();
+
+ newVertex->setShape(this);
+ AddVertex(newVertex);
+ }
+
+ vector<WEdge *>& edgeList = iBrother.getEdgeList();
+ vector<WEdge *>::iterator e = edgeList.begin(), eend = edgeList.end();
+ for (; e != eend; ++e) {
+ //WEdge *newEdge = new WEdge(*(*e));
+ WEdge *newEdge = (*e)->duplicate();
+ AddEdge(newEdge);
+ }
+
+ vector<WFace *>& faceList = iBrother.GetFaceList();
+ vector<WFace *>::iterator f = faceList.begin(), fend = faceList.end();
+ for (; f != fend; ++f) {
+ //WFace *newFace = new WFace(*(*f));
+ WFace *newFace = (*f)->duplicate();
+ AddFace(newFace);
+ }
+
+ // update all pointed addresses thanks to the newly created objects:
+ vend = _VertexList.end();
+ for (v = _VertexList.begin(); v != vend; ++v) {
+ const vector<WEdge *>& vedgeList = (*v)->GetEdges();
+ vector<WEdge *> newvedgelist;
+ unsigned int i;
+ for (i = 0; i < vedgeList.size(); i++) {
+ WEdge *current = vedgeList[i];
+ edgedata *currentvedata = (edgedata *)current->userdata;
+ newvedgelist.push_back(currentvedata->_copy);
+ }
+ (*v)->setEdges(newvedgelist);
+ }
+
+ eend = _EdgeList.end();
+ for (e = _EdgeList.begin(); e != eend; ++e) {
+ // update aOedge:
+ WOEdge *aoEdge = (*e)->GetaOEdge();
+ aoEdge->setaVertex(((vertexdata *)(aoEdge->GetaVertex()->userdata))->_copy);
+ aoEdge->setbVertex(((vertexdata *)(aoEdge->GetbVertex()->userdata))->_copy);
+ if (aoEdge->GetaFace())
+ aoEdge->setaFace(((facedata *)(aoEdge->GetaFace()->userdata))->_copy);
+ aoEdge->setbFace(((facedata *)(aoEdge->GetbFace()->userdata))->_copy);
+ aoEdge->setOwner(((edgedata *)(aoEdge->GetOwner()->userdata))->_copy);
+
+ // update bOedge:
+ WOEdge *boEdge = (*e)->GetbOEdge();
+ if (boEdge) {
+ boEdge->setaVertex(((vertexdata *)(boEdge->GetaVertex()->userdata))->_copy);
+ boEdge->setbVertex(((vertexdata *)(boEdge->GetbVertex()->userdata))->_copy);
+ if (boEdge->GetaFace())
+ boEdge->setaFace(((facedata *)(boEdge->GetaFace()->userdata))->_copy);
+ boEdge->setbFace(((facedata *)(boEdge->GetbFace()->userdata))->_copy);
+ boEdge->setOwner(((edgedata *)(boEdge->GetOwner()->userdata))->_copy);
+ }
+ }
+
+ fend = _FaceList.end();
+ for (f = _FaceList.begin(); f != fend; ++f) {
+ unsigned int i;
+ const vector<WOEdge *>& oedgeList = (*f)->getEdgeList();
+ vector<WOEdge *> newoedgelist;
+
+ unsigned int n = oedgeList.size();
+ for (i = 0; i < n; i++) {
+ WOEdge *current = oedgeList[i];
+ oedgedata *currentoedata = (oedgedata *)current->userdata;
+ newoedgelist.push_back(currentoedata->_copy);
+ //oedgeList[i] = currentoedata->_copy;
+ //oedgeList[i] = ((oedgedata *)(oedgeList[i]->userdata))->_copy;
+ }
+ (*f)->setEdgeList(newoedgelist);
+ }
+
+ // Free all memory (arghh!)
+ // Vertex
+ vend = iBrother.getVertexList().end();
+ for (v = iBrother.getVertexList().begin(); v != vend; ++v) {
+ delete (vertexdata *)((*v)->userdata);
+ (*v)->userdata = NULL;
+ }
+
+ // Edges and OEdges:
+ eend = iBrother.getEdgeList().end();
+ for (e = iBrother.getEdgeList().begin(); e != eend; ++e) {
+ delete (edgedata *)((*e)->userdata);
+ (*e)->userdata = NULL;
+ // OEdge a:
+ delete (oedgedata *)((*e)->GetaOEdge()->userdata);
+ (*e)->GetaOEdge()->userdata = NULL;
+ // OEdge b:
+ WOEdge *oedgeb = (*e)->GetbOEdge();
+ if (oedgeb) {
+ delete (oedgedata *)(oedgeb->userdata);
+ oedgeb->userdata = NULL;
+ }
+ }
+
+ // Faces
+ fend = iBrother.GetFaceList().end();
+ for (f = iBrother.GetFaceList().begin(); f != fend; ++f) {
+ delete (facedata *)((*f)->userdata);
+ (*f)->userdata = NULL;
+ }
+}
+
+WFace *WShape::MakeFace(vector<WVertex *>& iVertexList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterial)
+{
+ // allocate the new face
+ WFace *face = instanciateFace();
+
+ WFace *result = MakeFace(iVertexList, iFaceEdgeMarksList, iMaterial, face);
+ if (!result)
+ delete face;
+ return result;
+}
+
+WFace *WShape::MakeFace(vector<WVertex *>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList,
+ vector<bool>& iFaceEdgeMarksList, unsigned iMaterial)
+{
+ // allocate the new face
+ WFace *face = MakeFace(iVertexList, iFaceEdgeMarksList, iMaterial);
+
+ if (!face)
+ return NULL;
+
+ // set the list of per-vertex normals
+ face->setNormalList(iNormalsList);
+ // set the list of per-vertex tex coords
+ face->setTexCoordsList(iTexCoordsList);
+
+ return face;
+}
+
+WFace *WShape::MakeFace(vector<WVertex *>& iVertexList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterial,
+ WFace *face)
+{
+ int id = _FaceList.size();
+
+ face->setFrsMaterialIndex(iMaterial);
+
+ // Check whether we have a degenerated face:
+
+ // LET'S HACK IT FOR THE TRIANGLE CASE:
+
+ if (3 == iVertexList.size()) {
+ if ((iVertexList[0] == iVertexList[1]) ||
+ (iVertexList[0] == iVertexList[2]) ||
+ (iVertexList[2] == iVertexList[1]))
+ {
+ cerr << "Warning: degenerated triangle detected, correcting" << endl;
+ return NULL;
+ }
+ }
+
+ vector<WVertex *>::iterator it;
+
+ // compute the face normal (v1v2 ^ v1v3)
+ WVertex *v1, *v2, *v3;
+ it = iVertexList.begin();
+ v1 = *it;
+ it++;
+ v2 = *it;
+ it++;
+ v3 = *it;
+
+ Vec3r vector1(v2->GetVertex() - v1->GetVertex());
+ Vec3r vector2(v3->GetVertex() - v1->GetVertex());
+
+ Vec3r normal(vector1 ^ vector2);
+ normal.normalize();
+ face->setNormal(normal);
+
+ vector<bool>::iterator mit = iFaceEdgeMarksList.begin();
+ face->setMark(*mit);
+ mit++;
+
+ // vertex pointers used to build each edge
+ vector<WVertex *>::iterator va, vb;
+
+ va = iVertexList.begin();
+ vb = va;
+ for (; va != iVertexList.end(); va = vb) {
+ ++vb;
+ // Adds va to the vertex list:
+ //face->AddVertex(*va);
+
+ WOEdge *oedge;
+ if (*va == iVertexList.back())
+ oedge = face->MakeEdge(*va, iVertexList.front()); //for the last (closing) edge
+ else
+ oedge = face->MakeEdge(*va, *vb);
+
+ if (!oedge)
+ return NULL;
+
+ WEdge *edge = oedge->GetOwner();
+ if (1 == edge->GetNumberOfOEdges()) {
+ // 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);
+ // compute the mean edge value:
+ _meanEdgeSize += edge->GetaOEdge()->GetVec().norm();
+ }
+
+ edge->setMark(*mit);
+ ++mit;
+ }
+
+ // Add the face to the shape's faces list:
+ face->setId(id);
+ AddFace(face);
+
+ return face;
+} \ No newline at end of file
diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.h b/source/blender/freestyle/intern/winged_edge/WEdge.h
new file mode 100644
index 00000000000..1646d995a22
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WEdge.h
@@ -0,0 +1,1344 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_W_EDGE_H__
+#define __FREESTYLE_W_EDGE_H__
+
+/** \file blender/freestyle/intern/winged_edge/WEdge.h
+ * \ingroup freestyle
+ * \brief Classes to define a Winged Edge data structure.
+ * \author Stephane Grabli
+ * \date 18/02/2002
+ */
+
+#include <iterator>
+#include <math.h>
+#include <vector>
+
+#include "../geometry/Geom.h"
+
+#include "../scene_graph/FrsMaterial.h"
+
+#include "../system/FreestyleConfig.h"
+
+using namespace std;
+using namespace Geometry;
+
+
+/**********************************
+ * *
+ * *
+ * WVertex *
+ * *
+ * *
+ **********************************/
+
+
+class WOEdge;
+class WEdge;
+class WShape;
+class WFace;
+
+class LIB_WINGED_EDGE_EXPORT WVertex
+{
+protected:
+ int _Id; // an identificator
+ Vec3r _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
+
+public:
+ void *userdata; // designed to store specific user data
+ inline WVertex(const Vec3r &v)
+ {
+ _Id = 0;
+ _Vertex = v;
+ userdata = NULL;
+ _Shape = NULL;
+ _Smooth = true;
+ _Border = -1;
+ }
+
+ /*! Copy constructor */
+ WVertex(WVertex& iBrother);
+ virtual WVertex *duplicate();
+ virtual ~WVertex() {}
+
+ /*! accessors */
+ inline Vec3r& GetVertex()
+ {
+ return _Vertex;
+ }
+
+ inline vector<WEdge*>& GetEdges()
+ {
+ return _EdgeList;
+ }
+
+ inline int GetId()
+ {
+ return _Id;
+ }
+
+ inline WShape *shape() const
+ {
+ return _Shape;
+ }
+
+ inline bool isSmooth() const
+ {
+ return _Smooth;
+ }
+
+ bool isBoundary();
+
+ /*! modifiers */
+ inline void setVertex(const Vec3r& v)
+ {
+ _Vertex = v;
+ }
+
+ inline void setEdges(const vector<WEdge *>& iEdgeList)
+ {
+ _EdgeList = iEdgeList;
+ }
+
+ inline void setId(int id)
+ {
+ _Id = id;
+ }
+
+ inline void setShape(WShape *iShape)
+ {
+ _Shape = iShape;
+ }
+
+ inline void setSmooth(bool b)
+ {
+ _Smooth = b;
+ }
+
+ inline void setBorder(bool b)
+ {
+ if (b)
+ _Border = 1;
+ else
+ _Border = 0;
+ }
+
+ /*! Adds an edge to the edges list */
+ void AddEdge(WEdge *iEdge);
+
+ virtual void ResetUserData()
+ {
+ userdata = NULL;
+ }
+
+public:
+ /*! Iterator to iterate over a vertex incoming edges in the CCW order*/
+#if defined(__GNUC__) && (__GNUC__ < 3)
+ class incoming_edge_iterator : public input_iterator<WOEdge *, ptrdiff_t>
+#else
+ class LIB_WINGED_EDGE_EXPORT incoming_edge_iterator
+ : public iterator<input_iterator_tag, WOEdge *, ptrdiff_t>
+#endif
+ {
+ private:
+ WVertex *_vertex;
+ //
+ WOEdge *_begin;
+ WOEdge *_current;
+
+ public:
+#if defined(__GNUC__) && (__GNUC__ < 3)
+ inline incoming_edge_iterator() : input_iterator<WOEdge *, ptrdiff_t>() {}
+#else
+ inline incoming_edge_iterator() : iterator<input_iterator_tag, WOEdge *, ptrdiff_t>() {}
+#endif
+ virtual ~incoming_edge_iterator() {}; //soc
+
+ protected:
+ friend class WVertex;
+ inline incoming_edge_iterator(WVertex *iVertex, WOEdge *iBegin, WOEdge *iCurrent)
+#if defined(__GNUC__) && (__GNUC__ < 3)
+ : input_iterator<WOEdge *, ptrdiff_t>()
+#else
+ : iterator<input_iterator_tag, WOEdge *, ptrdiff_t>()
+#endif
+ {
+ _vertex = iVertex;
+ _begin = iBegin;
+ _current = iCurrent;
+ }
+
+ public:
+ inline incoming_edge_iterator(const incoming_edge_iterator& iBrother)
+#if defined(__GNUC__) && (__GNUC__ < 3)
+ : input_iterator<WOEdge *, ptrdiff_t>(iBrother)
+#else
+ : iterator<input_iterator_tag, WOEdge *, ptrdiff_t>(iBrother)
+#endif
+ {
+ _vertex = iBrother._vertex;
+ _begin = iBrother._begin;
+ _current = iBrother._current;
+ }
+
+ public:
+ // operators
+ // operator corresponding to ++i
+ virtual incoming_edge_iterator& operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ // operator corresponding to i++
+ virtual incoming_edge_iterator operator++(int)
+ {
+ incoming_edge_iterator tmp = *this;
+ increment();
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const incoming_edge_iterator& b) const
+ {
+ return ((_current) != (b._current));
+ }
+
+ virtual bool operator==(const incoming_edge_iterator& b) const
+ {
+ return ((_current) == (b._current));
+ }
+
+ // dereferencing
+ virtual WOEdge *operator*();
+ //virtual WOEdge **operator->();
+ protected:
+ virtual void increment();
+ };
+
+ /*! Iterator to iterate over a vertex faces in the CCW order */
+#if defined(__GNUC__) && (__GNUC__ < 3)
+ class face_iterator : public input_iterator<WFace *, ptrdiff_t>
+#else
+ class LIB_WINGED_EDGE_EXPORT face_iterator : public iterator<input_iterator_tag, WFace *, ptrdiff_t>
+#endif
+ {
+ private:
+ incoming_edge_iterator _edge_it;
+
+ public:
+#if defined(__GNUC__) && (__GNUC__ < 3)
+ inline face_iterator() : input_iterator<WFace *, ptrdiff_t>() {}
+#else
+ inline face_iterator() : iterator<input_iterator_tag, WFace *, ptrdiff_t>() {}
+#endif
+ virtual ~face_iterator() {}; //soc
+
+ protected:
+ friend class WVertex;
+ inline face_iterator(incoming_edge_iterator it)
+#if defined(__GNUC__) && (__GNUC__ < 3)
+ : input_iterator<WFace *, ptrdiff_t>()
+#else
+ : iterator<input_iterator_tag, WFace *, ptrdiff_t>()
+#endif
+ {
+ _edge_it = it;
+ }
+
+ public:
+ inline face_iterator(const face_iterator& iBrother)
+#if defined(__GNUC__) && (__GNUC__ < 3)
+ : input_iterator<WFace *, ptrdiff_t>(iBrother)
+#else
+ : iterator<input_iterator_tag, WFace *, ptrdiff_t>(iBrother)
+#endif
+ {
+ _edge_it = iBrother._edge_it;
+ }
+
+ public:
+ // operators
+ // operator corresponding to ++i
+ virtual face_iterator& operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ // operator corresponding to i++
+ virtual face_iterator operator++(int)
+ {
+ face_iterator tmp = *this;
+ increment();
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const face_iterator& b) const
+ {
+ return ((_edge_it) != (b._edge_it));
+ }
+
+ virtual bool operator==(const face_iterator& b) const
+ {
+ return ((_edge_it) == (b._edge_it));
+ }
+
+ // dereferencing
+ virtual WFace *operator*();
+ //virtual WOEdge **operator->();
+
+ protected:
+ inline void increment()
+ {
+ ++_edge_it;
+ }
+ };
+
+public:
+ /*! iterators access */
+ virtual incoming_edge_iterator incoming_edges_begin();
+ virtual incoming_edge_iterator incoming_edges_end();
+
+ virtual face_iterator faces_begin()
+ {
+ return face_iterator(incoming_edges_begin());
+ }
+
+ virtual face_iterator faces_end()
+ {
+ return face_iterator(incoming_edges_end());
+ }
+};
+
+
+/**********************************
+ * *
+ * *
+ * WOEdge *
+ * *
+ * *
+ **********************************/
+
+class WFace;
+class WEdge;
+
+class LIB_WINGED_EDGE_EXPORT WOEdge
+{
+protected:
+#if 0
+ WOEdge *_paCWEdge; // edge reached when traveling clockwise on aFace from the edge
+ WOEdge *_pbCWEdge; // edge reached when traveling clockwise on bFace from the edge
+ WOEdge *_paCCWEdge; // edge reached when traveling counterclockwise on aFace from the edge
+ WOEdge *_pbCCWEdge; // edge reached when traveling counterclockwise on bFace from the edge
+#endif
+ WVertex *_paVertex; // starting vertex
+ WVertex *_pbVertex; // ending vertex
+ WFace *_paFace; // when following the edge, face on the right
+ WFace *_pbFace; // when following the edge, face on the left
+ WEdge *_pOwner; // Edge
+
+ Vec3r _vec;
+ real _angle;
+
+public:
+ void *userdata;
+
+ inline WOEdge()
+ {
+#if 0
+ _paCWEdge = NULL;
+ _pbCWEdge = NULL;
+ _paCCWEdge = NULL;
+ _pbCCWEdge = NULL;
+#endif
+ _paVertex = NULL;
+ _pbVertex = NULL;
+ _paFace = NULL;
+ _pbFace = NULL;
+ _pOwner = NULL;
+ userdata = NULL;
+ }
+
+ virtual ~WOEdge() {}; //soc
+
+ /*! copy constructor */
+ WOEdge(WOEdge& iBrother);
+ virtual WOEdge *duplicate();
+
+ /*! accessors */
+#if 0
+ inline WOEdge *GetaCWEdge()
+ {
+ return _paCWEdge;
+ }
+
+ inline WOEdge *GetbCWEdge()
+ {
+ return _pbCWEdge;
+ }
+
+ inline WOEdge *GetaCCWEdge()
+ {
+ return _paCCWEdge;
+ }
+
+ inline WOEdge *GetbCCWEdge()
+ {
+ return _pbCCWEdge;
+ }
+#endif
+
+ inline WVertex *GetaVertex()
+ {
+ return _paVertex;
+ }
+
+ inline WVertex *GetbVertex()
+ {
+ return _pbVertex;
+ }
+
+ inline WFace *GetaFace()
+ {
+ return _paFace;
+ }
+
+ inline WFace *GetbFace()
+ {
+ return _pbFace;
+ }
+
+ inline WEdge *GetOwner()
+ {
+ return _pOwner;
+ }
+
+ inline const Vec3r& GetVec()
+ {
+ return _vec;
+ }
+
+ inline const real GetAngle()
+ {
+ return _angle;
+ }
+
+
+ /*! modifiers */
+#if 0
+ inline void SetaCWEdge(WOEdge *pe)
+ {
+ _paCWEdge = pe;
+ }
+
+ inline void SetbCWEdge(WOEdge *pe)
+ {
+ _pbCWEdge = pe;
+ }
+
+ inline void SetaCCWEdge(WOEdge *pe)
+ {
+ _paCCWEdge = pe;
+ }
+
+ inline void SetbCCCWEdge(WOEdge *pe)
+ {
+ _pbCCWEdge = pe;
+ }
+#endif
+
+ inline void setVecAndAngle();
+
+ inline void setaVertex(WVertex *pv)
+ {
+ _paVertex = pv;
+ setVecAndAngle();
+ }
+
+ inline void setbVertex(WVertex *pv)
+ {
+ _pbVertex = pv;
+ setVecAndAngle();
+ }
+
+ inline void setaFace(WFace *pf)
+ {
+ _paFace = pf;
+ setVecAndAngle();
+ }
+
+ inline void setbFace(WFace *pf)
+ {
+ _pbFace = pf;
+ setVecAndAngle();
+ }
+
+ inline void setOwner(WEdge *pe)
+ {
+ _pOwner = pe;
+ }
+
+ /*! Retrieves the list of edges in CW order */
+ inline void RetrieveCWOrderedEdges(vector<WEdge*>& oEdges);
+
+ /*! returns the vector between the two vertices */
+ Vec3r getVec3r ();
+ WOEdge *twin ();
+ WOEdge *getPrevOnFace();
+
+ virtual void ResetUserData()
+ {
+ userdata = NULL;
+ }
+};
+
+
+/**********************************
+ * *
+ * *
+ * WEdge *
+ * *
+ * *
+ **********************************/
+
+class LIB_WINGED_EDGE_EXPORT 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)
+ bool _Mark; // user-specified edge mark for feature edge detection
+ int _Id; // Identifier for the edge
+
+public:
+ void *userdata; // designed to store specific user data
+
+ inline WEdge()
+ {
+ _paOEdge = NULL;
+ _pbOEdge = NULL;
+ _nOEdges = 0;
+ userdata = NULL;
+ }
+
+ inline WEdge(WOEdge *iOEdge)
+ {
+ _paOEdge = iOEdge;
+ _pbOEdge = NULL;
+ _nOEdges = 1;
+ userdata = NULL;
+ }
+
+ inline WEdge(WOEdge *iaOEdge, WOEdge *ibOEdge)
+ {
+ _paOEdge = iaOEdge;
+ _pbOEdge = ibOEdge;
+ _nOEdges = 2;
+ userdata = NULL;
+ }
+
+ /*! Copy constructor */
+ WEdge(WEdge& iBrother);
+ virtual WEdge *duplicate();
+
+ virtual ~WEdge()
+ {
+ if (_paOEdge) {
+ delete _paOEdge;
+ _paOEdge = NULL;
+ }
+
+ if (_pbOEdge) {
+ delete _pbOEdge;
+ _pbOEdge = NULL;
+ }
+ }
+
+ /*! checks whether two WEdge have a common vertex.
+ * Returns a pointer on the common vertex if it exists, NULL otherwise.
+ */
+ static inline WVertex *CommonVertex(WEdge *iEdge1, WEdge *iEdge2)
+ {
+ if (!iEdge1 || !iEdge2)
+ return NULL;
+
+ WVertex *wv1 = iEdge1->GetaOEdge()->GetaVertex();
+ WVertex *wv2 = iEdge1->GetaOEdge()->GetbVertex();
+ WVertex *wv3 = iEdge2->GetaOEdge()->GetaVertex();
+ WVertex *wv4 = iEdge2->GetaOEdge()->GetbVertex();
+
+ if ((wv1 == wv3) || (wv1 == wv4)) {
+ return wv1;
+ }
+ else if ((wv2 == wv3) || (wv2 == wv4)) {
+ return wv2;
+ }
+ return NULL;
+ }
+
+ /*! accessors */
+ inline WOEdge *GetaOEdge()
+ {
+ return _paOEdge;
+ }
+
+ inline WOEdge *GetbOEdge()
+ {
+ return _pbOEdge;
+ }
+
+ inline int GetNumberOfOEdges()
+ {
+ return _nOEdges;
+ }
+
+ inline bool GetMark()
+ {
+ return _Mark;
+ }
+
+ inline int GetId()
+ {
+ return _Id;
+ }
+
+ inline WVertex *GetaVertex()
+ {
+ return _paOEdge->GetaVertex();
+ }
+
+ inline WVertex *GetbVertex()
+ {
+ return _paOEdge->GetbVertex();
+ }
+
+ inline WFace *GetaFace()
+ {
+ return _paOEdge->GetaFace();
+ }
+
+ inline WFace *GetbFace()
+ {
+ return _paOEdge->GetbFace();
+ }
+
+ inline WOEdge *GetOtherOEdge(WOEdge *iOEdge) {
+ if (iOEdge == _paOEdge)
+ return _pbOEdge;
+ else
+ return _paOEdge;
+ }
+
+ /*! modifiers */
+ inline void setaOEdge(WOEdge *iEdge)
+ {
+ _paOEdge = iEdge;
+ }
+
+ inline void setbOEdge(WOEdge *iEdge)
+ {
+ _pbOEdge = iEdge;
+ }
+
+ inline void AddOEdge(WOEdge *iEdge)
+ {
+ if (!_paOEdge) {
+ _paOEdge = iEdge;
+ _nOEdges++;
+ return;
+ }
+ if (!_pbOEdge) {
+ _pbOEdge = iEdge;
+ _nOEdges++;
+ return;
+ }
+ }
+
+ inline void setNumberOfOEdges(int n)
+ {
+ _nOEdges = n;
+ }
+
+ inline void setMark(bool mark)
+ {
+ _Mark = mark;
+ }
+
+ inline void setId(int id)
+ {
+ _Id = id;
+ }
+
+ virtual void ResetUserData()
+ {
+ userdata = NULL;
+ }
+};
+
+
+/**********************************
+ * *
+ * *
+ * WFace *
+ * *
+ * *
+ **********************************/
+
+
+class LIB_WINGED_EDGE_EXPORT WFace
+{
+protected:
+ vector<WOEdge *> _OEdgeList; // list of oriented edges of bording the face
+ Vec3r _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;
+
+ int _Id;
+ unsigned _FrsMaterialIndex;
+ bool _Mark; // Freestyle face mark (if true, feature edges on this face are ignored)
+
+public:
+ void *userdata;
+ inline WFace()
+ {
+ userdata = NULL;
+ _FrsMaterialIndex = 0;
+ }
+
+ /*! copy constructor */
+ WFace(WFace& iBrother);
+ virtual WFace *duplicate();
+ virtual ~WFace() {}
+
+ /*! accessors */
+ inline const vector<WOEdge*>& getEdgeList()
+ {
+ return _OEdgeList;
+ }
+
+ inline WOEdge *GetOEdge(int i)
+ {
+ return _OEdgeList[i];
+ }
+
+ inline Vec3r& GetNormal()
+ {
+ return _Normal;
+ }
+
+ inline int GetId()
+ {
+ return _Id;
+ }
+
+ inline unsigned frs_materialIndex() const
+ {
+ return _FrsMaterialIndex;
+ }
+
+ inline bool GetMark() const
+ {
+ return _Mark;
+ }
+
+ const FrsMaterial& frs_material();
+
+ /*! The vertex of index i corresponds to the a vertex of the edge of index i */
+ inline WVertex *GetVertex(unsigned int index)
+ {
+#if 0
+ if (index >= _OEdgeList.size())
+ return NULL;
+#endif
+ return _OEdgeList[index]->GetaVertex();
+ }
+
+ /*! returns the index at which iVertex is stored in the array.
+ * returns -1 if iVertex doesn't belong to the face.
+ */
+ inline int GetIndex(WVertex *iVertex)
+ {
+ int index = 0;
+ for (vector<WOEdge*>::iterator woe = _OEdgeList.begin(), woend = _OEdgeList.end(); woe != woend; woe++) {
+ if ((*woe)->GetaVertex() == iVertex)
+ return index;
+ ++index;
+ }
+ return -1;
+ }
+
+ inline void RetrieveVertexList(vector<WVertex *>& oVertices)
+ {
+ for (vector<WOEdge *>::iterator woe = _OEdgeList.begin(), woend = _OEdgeList.end(); woe != woend; woe++) {
+ oVertices.push_back((*woe)->GetaVertex());
+ }
+ }
+
+ inline void RetrieveBorderFaces(vector<const WFace *>& oWFaces)
+ {
+ for (vector<WOEdge *>::iterator woe = _OEdgeList.begin(), woend = _OEdgeList.end(); woe != woend; woe++) {
+ WFace *af;
+ if ((af = (*woe)->GetaFace()))
+ oWFaces.push_back(af);
+ }
+ }
+
+ inline WFace *GetBordingFace(int index)
+ {
+#if 0
+ if (index >= _OEdgeList.size())
+ return NULL;
+#endif
+ return _OEdgeList[index]->GetaFace();
+ }
+
+ inline WFace *GetBordingFace(WOEdge *iOEdge)
+ {
+ return iOEdge->GetaFace();
+ }
+
+ inline vector<Vec3r>& GetPerVertexNormals()
+ {
+ return _VerticesNormals;
+ }
+
+ inline vector<Vec2r>& GetPerVertexTexCoords()
+ {
+ return _VerticesTexCoords;
+ }
+
+ /*! Returns the normal of the vertex of index index */
+ inline Vec3r& GetVertexNormal(int index)
+ {
+ return _VerticesNormals[index];
+ }
+
+ /*! Returns the tex coords of the vertex of index index */
+ inline Vec2r& GetVertexTexCoords(int index)
+ {
+ return _VerticesTexCoords[index];
+ }
+
+ /*! Returns the normal of the vertex iVertex for that face */
+ inline Vec3r& GetVertexNormal(WVertex *iVertex)
+ {
+ int i = 0;
+ int index = 0;
+ for (vector<WOEdge *>::const_iterator woe = _OEdgeList.begin(), woend = _OEdgeList.end(); woe != woend; woe++) {
+ if ((*woe)->GetaVertex() == iVertex) {
+ index = i;
+ break;
+ }
+ ++i;
+ }
+
+ return _VerticesNormals[index];
+ }
+
+ inline WOEdge *GetNextOEdge(WOEdge *iOEdge)
+ {
+ bool found = false;
+ vector<WOEdge *>::iterator woe, woend, woefirst;
+ woefirst = _OEdgeList.begin();
+ for (woe = woefirst, woend = _OEdgeList.end(); woe != woend; ++woe) {
+ if (found)
+ return (*woe);
+
+ if ((*woe) == iOEdge) {
+ found = true;
+ }
+ }
+
+ // We left the loop. That means that the first OEdge was the good one:
+ if (found)
+ return (*woefirst);
+
+ return NULL;
+ }
+
+ WOEdge *GetPrevOEdge(WOEdge *iOEdge);
+
+ inline int numberOfEdges() const
+ {
+ return _OEdgeList.size();
+ }
+
+ inline int numberOfVertices() const
+ {
+ return _OEdgeList.size();
+ }
+
+ /*! Returns true if the face has one ot its edge which is a border edge */
+ inline bool isBorder() const
+ {
+ for (vector<WOEdge*>::const_iterator woe = _OEdgeList.begin(), woeend = _OEdgeList.end();
+ woe != woeend;
+ ++woe)
+ {
+ if ((*woe)->GetOwner()->GetbOEdge() == 0)
+ return true;
+ }
+ return false;
+ }
+
+ /*! modifiers */
+ inline void setEdgeList(const vector<WOEdge *>& iEdgeList)
+ {
+ _OEdgeList = iEdgeList;
+ }
+
+ inline void setNormal(const Vec3r& iNormal)
+ {
+ _Normal = iNormal;
+ }
+
+ inline void setNormalList(const vector<Vec3r>& iNormalsList)
+ {
+ _VerticesNormals = iNormalsList;
+ }
+
+ inline void setTexCoordsList(const vector<Vec2r>& iTexCoordsList)
+ {
+ _VerticesTexCoords = iTexCoordsList;
+ }
+
+ inline void setId(int id)
+ {
+ _Id = id;
+ }
+
+ inline void setFrsMaterialIndex(unsigned iMaterialIndex)
+ {
+ _FrsMaterialIndex = iMaterialIndex;
+ }
+
+ inline void setMark(bool iMark)
+ {
+ _Mark = iMark;
+ }
+
+ /*! designed to build a specialized WEdge for use in MakeEdge */
+ virtual WEdge *instanciateEdge() const
+ {
+ return new WEdge;
+ }
+
+ /*! Builds an oriented edge
+ * Returns the built edge.
+ * v1, v2
+ * Vertices at the edge's extremities
+ * The edge is oriented from v1 to v2.
+ */
+ virtual WOEdge *MakeEdge(WVertex *v1, WVertex *v2);
+
+ /*! Adds an edge to the edges list */
+ inline void AddEdge(WOEdge *iEdge)
+ {
+ _OEdgeList.push_back(iEdge);
+ }
+
+ /*! 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
+ */
+ bool getOppositeEdge (const WVertex *v, WOEdge *&e);
+
+ /*! compute the area of the face */
+ real getArea ();
+
+ WShape *getShape();
+ virtual void ResetUserData()
+ {
+ userdata = NULL;
+ }
+};
+
+
+/**********************************
+ * *
+ * *
+ * WShape *
+ * *
+ * *
+ **********************************/
+
+
+class LIB_WINGED_EDGE_EXPORT WShape
+{
+protected:
+ vector<WVertex *> _VertexList;
+ vector<WEdge *> _EdgeList;
+ vector<WFace *> _FaceList;
+ int _Id;
+ string _Name;
+ static unsigned _SceneCurrentId;
+ Vec3r _min;
+ Vec3r _max;
+ vector<FrsMaterial> _FrsMaterials;
+ real _meanEdgeSize;
+
+public:
+ inline WShape()
+ {
+ _meanEdgeSize = 0;
+ _Id = _SceneCurrentId;
+ _SceneCurrentId++;
+ }
+
+ /*! copy constructor */
+ WShape(WShape& iBrother);
+ virtual WShape *duplicate();
+
+ virtual ~WShape()
+ {
+ if (_EdgeList.size() != 0) {
+ vector<WEdge *>::iterator e;
+ for (e = _EdgeList.begin(); e != _EdgeList.end(); ++e) {
+ delete (*e);
+ }
+ _EdgeList.clear();
+ }
+
+ if (_VertexList.size() != 0) {
+ vector<WVertex *>::iterator v;
+ for (v = _VertexList.begin(); v != _VertexList.end(); ++v) {
+ delete (*v);
+ }
+ _VertexList.clear();
+ }
+
+ if (_FaceList.size() != 0) {
+ vector<WFace *>::iterator f;
+ for (f = _FaceList.begin(); f != _FaceList.end(); ++f) {
+ delete (*f);
+ }
+ _FaceList.clear();
+ }
+ }
+
+ /*! accessors */
+ inline vector<WEdge *>& getEdgeList()
+ {
+ return _EdgeList;
+ }
+
+ inline vector<WVertex *>& getVertexList()
+ {
+ return _VertexList;
+ }
+
+ inline vector<WFace *>& GetFaceList()
+ {
+ return _FaceList;
+ }
+
+ inline unsigned GetId()
+ {
+ return _Id;
+ }
+
+ inline void bbox(Vec3r& min, Vec3r& max)
+ {
+ min = _min;
+ max = _max;
+ }
+
+ inline const FrsMaterial& frs_material(unsigned i) const
+ {
+ return _FrsMaterials[i];
+ }
+
+ inline const vector<FrsMaterial>& frs_materials() const
+ {
+ return _FrsMaterials;
+ }
+
+ inline const real getMeanEdgeSize() const
+ {
+ return _meanEdgeSize;
+ }
+
+ inline const string& getName() const
+ {
+ return _Name;
+ }
+
+ /*! modifiers */
+ static inline void setCurrentId(const unsigned id)
+ {
+ _SceneCurrentId = id;
+ }
+
+ inline void setEdgeList(const vector<WEdge *>& iEdgeList)
+ {
+ _EdgeList = iEdgeList;
+ }
+
+ inline void setVertexList(const vector<WVertex *>& iVertexList)
+ {
+ _VertexList = iVertexList;
+ }
+
+ inline void setFaceList(const vector<WFace *>& iFaceList)
+ {
+ _FaceList = iFaceList;
+ }
+
+ inline void setId(int id)
+ {
+ _Id = id;
+ }
+
+ inline void setBBox(const Vec3r& min, const Vec3r& max)
+ {
+ _min = min;
+ _max = max;
+ }
+
+ inline void setFrsMaterial(const FrsMaterial& frs_material, unsigned i)
+ {
+ _FrsMaterials[i] = frs_material;
+ }
+
+ inline void setFrsMaterials(const vector<FrsMaterial>& iMaterials)
+ {
+ _FrsMaterials = iMaterials;
+ }
+
+ inline void setName(const string& name)
+ {
+ _Name = name;
+ }
+
+ /*! designed to build a specialized WFace for use in MakeFace */
+ virtual WFace *instanciateFace() const
+ {
+ return new WFace;
+ }
+
+ /*! adds a new face to the shape
+ * returns the built face.
+ * iVertexList
+ * List of face's vertices. These vertices are not added to the WShape vertex list; they are supposed to be
+ * already stored when calling MakeFace.
+ * The order in which the vertices are stored in the list determines the face's edges orientation and (so) the
+ * face orientation.
+ * iMaterialIndex
+ * The material index for this face
+ */
+ virtual WFace *MakeFace(vector<WVertex *>& iVertexList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex);
+
+ /*! adds a new face to the shape. The difference with the previous method is that this one is designed
+ * to build a WingedEdge structure for which there are per vertex normals, opposed to per face normals.
+ * returns the built face.
+ * iVertexList
+ * List of face's vertices. These vertices are not added to the WShape vertex list; they are supposed to be
+ * already stored when calling MakeFace.
+ * The order in which the vertices are stored in the list determines the face's edges orientation and (so) the
+ * face orientation.
+ * iMaterialIndex
+ * The materialIndex for this face
+ * iNormalsList
+ * The list of normals, iNormalsList[i] corresponding to the normal of the vertex iVertexList[i] for that face.
+ * iTexCoordsList
+ * 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,
+ vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex);
+
+ inline void AddEdge(WEdge *iEdge)
+ {
+ _EdgeList.push_back(iEdge);
+ }
+
+ inline void AddFace(WFace *iFace)
+ {
+ _FaceList.push_back(iFace);
+ }
+
+ inline void AddVertex(WVertex *iVertex)
+ {
+ iVertex->setShape(this);
+ _VertexList.push_back(iVertex);
+ }
+
+ inline void ResetUserData()
+ {
+ for (vector<WVertex *>::iterator v = _VertexList.begin(), vend = _VertexList.end(); v != vend; v++) {
+ (*v)->ResetUserData();
+ }
+
+ for (vector<WEdge *>::iterator e = _EdgeList.begin(), eend = _EdgeList.end(); e != eend; e++) {
+ (*e)->ResetUserData();
+ // manages WOEdge:
+ WOEdge *oe = (*e)->GetaOEdge();
+ if (oe)
+ oe->ResetUserData();
+ oe = (*e)->GetbOEdge();
+ if (oe)
+ oe->ResetUserData();
+ }
+
+ for (vector<WFace *>::iterator f = _FaceList.begin(), fend = _FaceList.end(); f != fend; f++) {
+ (*f)->ResetUserData();
+ }
+ }
+
+ inline void ComputeBBox()
+ {
+ _min = _VertexList[0]->GetVertex();
+ _max = _VertexList[0]->GetVertex();
+
+ Vec3r 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();
+ if (v[i] < _min[i])
+ _min[i] = v[i];
+ if (v[i] > _max[i])
+ _max[i] = v[i];
+ }
+ }
+ }
+
+ inline real ComputeMeanEdgeSize()
+ {
+ _meanEdgeSize = _meanEdgeSize / _EdgeList.size();
+ return _meanEdgeSize;
+ }
+
+protected:
+ /*! Builds the face passed as argument (which as already been allocated)
+ * iVertexList
+ * List of face's vertices. These vertices are not added to the WShape vertex list; they are supposed to be
+ * already stored when calling MakeFace.
+ * The order in which the vertices are stored in the list determines the face's edges orientation and (so) the
+ * face orientation.
+ * iMaterialIndex
+ * The material index for this face
+ * face
+ * The Face that is filled in
+ */
+ virtual WFace *MakeFace(vector<WVertex *>& iVertexList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex,
+ WFace *face);
+};
+
+
+/**********************************
+ * *
+ * *
+ * WingedEdge *
+ * *
+ * *
+ **********************************/
+
+class WingedEdge
+{
+public:
+ WingedEdge() {}
+
+ ~WingedEdge()
+ {
+ clear();
+ }
+
+ void clear()
+ {
+ for (vector<WShape *>::iterator it = _wshapes.begin(); it != _wshapes.end(); it++)
+ delete *it;
+ _wshapes.clear();
+ }
+
+ void addWShape(WShape *wshape)
+ {
+ _wshapes.push_back(wshape);
+ }
+
+ vector<WShape *>& getWShapes()
+ {
+ return _wshapes;
+ }
+
+private:
+ vector<WShape *> _wshapes;
+};
+
+
+
+/*
+
+#############################################
+#############################################
+#############################################
+###### ######
+###### I M P L E M E N T A T I O N ######
+###### ######
+#############################################
+#############################################
+#############################################
+
+*/
+/* for inline functions */
+void WOEdge::RetrieveCWOrderedEdges(vector<WEdge *>& oEdges)
+{
+ WOEdge *currentOEdge = this;
+ do {
+ WOEdge *nextOEdge = currentOEdge->GetbFace()->GetNextOEdge(currentOEdge);
+ oEdges.push_back(nextOEdge->GetOwner());
+ currentOEdge = nextOEdge->GetOwner()->GetOtherOEdge(nextOEdge);
+ } while (currentOEdge && (currentOEdge->GetOwner() != GetOwner()));
+}
+
+inline void WOEdge::setVecAndAngle()
+{
+ if (_paVertex && _pbVertex) {
+ _vec = _pbVertex->GetVertex() - _paVertex->GetVertex();
+ if (_paFace && _pbFace) {
+ real sine = (_pbFace->GetNormal() ^ _paFace->GetNormal()) * _vec / _vec.norm();
+ if (sine >= 1.0) {
+ _angle = M_PI / 2.0;
+ return;
+ }
+ if (sine <= -1.0) {
+ _angle = -M_PI / 2.0;
+ return;
+ }
+ _angle = ::asin(sine);
+ }
+ }
+}
+
+#endif // __FREESTYLE_W_EDGE_H__ \ No newline at end of file
diff --git a/source/blender/freestyle/intern/winged_edge/WFillGrid.cpp b/source/blender/freestyle/intern/winged_edge/WFillGrid.cpp
new file mode 100644
index 00000000000..8b446791efc
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WFillGrid.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/winged_edge/WFillGrid.cpp
+ * \ingroup freestyle
+ * \brief Class to fill in a grid from a SceneGraph (uses only the WingedEdge structures)
+ * \author Emmanuel Turquin
+ * \author Stephane Grabli
+ * \date 03/05/2003
+ */
+
+#include "WEdge.h"
+#include "WFillGrid.h"
+
+void WFillGrid::fillGrid()
+{
+ if (!_winged_edge || !_grid)
+ return;
+
+ vector<WShape *> wshapes = _winged_edge->getWShapes();
+ vector<WVertex *> fvertices;
+ vector<Vec3r> vectors;
+ vector<WFace *> faces;
+
+ for (vector<WShape *>::const_iterator it = wshapes.begin(); it != wshapes.end(); ++it) {
+ faces = (*it)->GetFaceList();
+
+ for (vector<WFace *>::const_iterator f = faces.begin(); f != faces.end(); ++f) {
+ (*f)->RetrieveVertexList(fvertices);
+
+ for (vector<WVertex*>::const_iterator wv = fvertices.begin(); wv != fvertices.end(); ++wv)
+ vectors.push_back(Vec3r((*wv)->GetVertex()));
+
+ // occluder will be deleted by the grid
+ Polygon3r *occluder = new Polygon3r(vectors, (*f)->GetNormal());
+ occluder->setId(_polygon_id++);
+ occluder->userdata = (void *)(*f);
+ _grid->insertOccluder(occluder);
+ vectors.clear();
+ fvertices.clear();
+ }
+ faces.clear();
+ }
+} \ No newline at end of file
diff --git a/source/blender/freestyle/intern/winged_edge/WFillGrid.h b/source/blender/freestyle/intern/winged_edge/WFillGrid.h
new file mode 100644
index 00000000000..223c5a786d8
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WFillGrid.h
@@ -0,0 +1,88 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_W_FILL_GRID_H__
+#define __FREESTYLE_W_FILL_GRID_H__
+
+/** \file blender/freestyle/intern/winged_edge/WFillGrid.h
+ * \ingroup freestyle
+ * \brief Class to fill in a grid from a SceneGraph (uses only the WingedEdge structures)
+ * \author Emmanuel Turquin
+ * \author Stephane Grabli
+ * \date 03/05/2003
+ */
+
+#include "WEdge.h"
+
+#include "../geometry/Grid.h"
+#include "../geometry/Polygon.h"
+
+class LIB_WINGED_EDGE_EXPORT WFillGrid
+{
+public:
+ inline WFillGrid(Grid *grid = NULL, WingedEdge *winged_edge = NULL)
+ {
+ _winged_edge = winged_edge;
+ _grid = grid;
+ _polygon_id = 0;
+ }
+
+ virtual ~WFillGrid() {}
+
+ void fillGrid();
+
+ /*! Accessors */
+ WingedEdge *getWingedEdge()
+ {
+ return _winged_edge;
+ }
+
+ Grid *getGrid()
+ {
+ return _grid;
+ }
+
+ /*! Modifiers */
+ void setWingedEdge(WingedEdge *winged_edge)
+ {
+ if (winged_edge)
+ _winged_edge = winged_edge;
+ }
+
+ void setGrid(Grid *grid)
+ {
+ if (grid)
+ _grid = grid;
+ }
+
+private:
+ Grid *_grid;
+ WingedEdge *_winged_edge;
+ unsigned _polygon_id;
+};
+
+#endif // __FREESTYLE_W_FILL_GRID_H__ \ No newline at end of file
diff --git a/source/blender/freestyle/intern/winged_edge/WSFillGrid.cpp b/source/blender/freestyle/intern/winged_edge/WSFillGrid.cpp
new file mode 100644
index 00000000000..3504a8ab179
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WSFillGrid.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/winged_edge/WSFillGrid.cpp
+ * \ingroup freestyle
+ * \brief Class to fill in a grid from a SceneGraph (uses only the WingedEdge structures)
+ * \author Stephane Grabli
+ * \date 03/05/2003
+ */
+
+#include "WEdge.h"
+#include "WSFillGrid.h"
+
+void WSFillGrid::fillGrid()
+{
+ if (!_winged_edge || !_grid)
+ return;
+
+ vector<WShape *> wshapes = _winged_edge->getWShapes();
+ vector<WVertex *> fvertices;
+ vector<Vec3r> vectors;
+ vector<WFace *> faces;
+
+ for (vector<WShape *>::const_iterator it = wshapes.begin(); it != wshapes.end(); ++it) {
+ faces = (*it)->GetFaceList();
+
+ for (vector<WFace *>::const_iterator f = faces.begin(); f != faces.end(); ++f) {
+ (*f)->RetrieveVertexList(fvertices);
+
+ for (vector<WVertex*>::const_iterator wv = fvertices.begin(); wv != fvertices.end(); ++wv)
+ vectors.push_back(Vec3r((*wv)->GetVertex()));
+
+ // occluder will be deleted by the grid
+ Polygon3r *occluder = new Polygon3r(vectors, (*f)->GetNormal());
+ occluder->setId(_polygon_id++);
+ occluder->userdata = (void *)(*f);
+ _grid->insertOccluder(occluder);
+ vectors.clear();
+ fvertices.clear();
+ }
+ faces.clear();
+ }
+} \ No newline at end of file
diff --git a/source/blender/freestyle/intern/winged_edge/WSFillGrid.h b/source/blender/freestyle/intern/winged_edge/WSFillGrid.h
new file mode 100644
index 00000000000..55bedd83cce
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WSFillGrid.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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_WS_FILL_GRID_H__
+#define __FREESTYLE_WS_FILL_GRID_H__
+
+/** \file blender/freestyle/intern/winged_edge/WSFillGrid.h
+ * \ingroup freestyle
+ * \brief Class to fill in a grid from a SceneGraph (uses only the WingedEdge structures)
+ * \author Stephane Grabli
+ * \date 03/05/2003
+ */
+
+#include "WEdge.h"
+
+#include "../geometry/Grid.h"
+#include "../geometry/Polygon.h"
+
+class LIB_WINGED_EDGE_EXPORT WSFillGrid
+{
+public:
+ inline WSFillGrid(Grid *grid = NULL, WingedEdge *winged_edge = NULL)
+ {
+ _winged_edge = winged_edge;
+ _grid = grid;
+ _polygon_id = 0;
+ }
+
+ virtual ~WSFillGrid() {}
+
+ void fillGrid();
+
+ /*! Accessors */
+ WingedEdge *getWingedEdge()
+ {
+ return _winged_edge;
+ }
+
+ Grid *getGrid()
+ {
+ return _grid;
+ }
+
+ /*! Modifiers */
+ void setWingedEdge(WingedEdge *winged_edge)
+ {
+ if (winged_edge)
+ _winged_edge = winged_edge;
+ }
+
+ void setGrid(Grid *grid)
+ {
+ if (grid)
+ _grid = grid;
+ }
+
+private:
+ Grid *_grid;
+ WingedEdge *_winged_edge;
+ unsigned _polygon_id;
+};
+
+#endif // __FREESTYLE_WS_FILL_GRID_H__ \ No newline at end of file
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp
new file mode 100644
index 00000000000..6190318e415
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp
@@ -0,0 +1,301 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/winged_edge/WXEdge.cpp
+ * \ingroup freestyle
+ * \brief Classes to define an Extended Winged Edge data structure.
+ * \author Stephane Grabli
+ * \date 26/10/2003
+ */
+
+#include "WXEdge.h"
+#include "BKE_global.h"
+
+/**********************************
+ * *
+ * *
+ * WXFace *
+ * *
+ * *
+ **********************************/
+
+unsigned int WXFaceLayer::Get0VertexIndex() const
+{
+ int i = 0;
+ int nEdges = _pWXFace->numberOfEdges();
+ for (i = 0; i < nEdges; ++i) {
+ if (_DotP[i] == 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+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)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+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) {
+ // we got one
+ oCuspEdges.push_back(i);
+ }
+ }
+}
+
+WXSmoothEdge *WXFaceLayer::BuildSmoothEdge()
+{
+ // if the smooth edge has already been built: exit
+ if (_pSmoothEdge)
+ return _pSmoothEdge;
+ real ta, tb;
+ WOEdge *woea(0), *woeb(0);
+ bool ok = false;
+ vector<int> cuspEdgesIndices;
+ int indexStart, indexEnd;
+ unsigned nedges = _pWXFace->numberOfEdges();
+ if (_nNullDotP == nedges) {
+ _pSmoothEdge = NULL;
+ return _pSmoothEdge;
+ }
+ if ((_nPosDotP != 0) && (_nPosDotP != _DotP.size()) && (_nNullDotP == 0)) {
+ // that means that we have a smooth edge that starts from an edge and ends at an edge
+ //-----------------------------
+ // We retrieve the 2 edges for which we have opposite signs for each extremity
+ RetrieveCuspEdgesIndices(cuspEdgesIndices);
+ if (cuspEdgesIndices.size() != 2) // we necessarly have 2 cusp edges
+ return 0;
+
+ // let us determine which cusp edge corresponds to the starting:
+ // We can do that because we defined that a silhouette edge had the back facing part on its right.
+ // 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) {
+ woea = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
+ woeb = _pWXFace->GetOEdge(cuspEdgesIndices[1]);
+ indexStart = cuspEdgesIndices[0];
+ indexEnd = cuspEdgesIndices[1];
+ }
+ else {
+ woea = _pWXFace->GetOEdge(cuspEdgesIndices[1]);
+ woeb = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
+ indexStart = cuspEdgesIndices[1];
+ indexEnd = cuspEdgesIndices[0];
+ }
+
+ // Compute the interpolation:
+ ta = _DotP[indexStart] / (_DotP[indexStart] - _DotP[(indexStart + 1) % nedges]);
+ tb = _DotP[indexEnd] / (_DotP[indexEnd] - _DotP[(indexEnd + 1) % nedges]);
+ ok = true;
+ }
+ else if (_nNullDotP == 1) {
+ // that means that we have exactly one of the 2 extremities of our silhouette edge is a vertex of the mesh
+ if ((_nPosDotP == 2) || (_nPosDotP == 0)) {
+ _pSmoothEdge = NULL;
+ return _pSmoothEdge;
+ }
+ RetrieveCuspEdgesIndices(cuspEdgesIndices);
+ // We should have only one EdgeCusp:
+ if (cuspEdgesIndices.size() != 1) {
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << "Warning in BuildSmoothEdge: weird WXFace configuration" << endl;
+ }
+ _pSmoothEdge = NULL;
+ return NULL;
+ }
+ unsigned index0 = Get0VertexIndex(); // retrieve the 0 vertex index
+ unsigned nedges = _pWXFace->numberOfEdges();
+ if (_DotP[cuspEdgesIndices[0]] > 0) {
+ woea = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
+ woeb = _pWXFace->GetOEdge(index0);
+ indexStart = cuspEdgesIndices[0];
+ ta = _DotP[indexStart] / (_DotP[indexStart] - _DotP[(indexStart + 1) % nedges]);
+ tb = 0.0;
+ }
+ else {
+ woea = _pWXFace->GetOEdge(index0);
+ woeb = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
+ indexEnd = cuspEdgesIndices[0];
+ ta = 0.0;
+ tb = _DotP[indexEnd] / (_DotP[indexEnd] - _DotP[(indexEnd + 1) % nedges]);
+ }
+ ok = true;
+ }
+ else if (_nNullDotP == 2) {
+ // that means that the silhouette edge is an edge of the mesh
+ int index = GetSmoothEdgeIndex();
+ if (!_pWXFace->front()) { // is it in the right order ?
+ // the order of the WOEdge index is wrong
+ woea = _pWXFace->GetOEdge((index + 1) % nedges);
+ woeb = _pWXFace->GetOEdge((index - 1) % nedges);
+ ta = 0;
+ tb = 1;
+ ok = true;
+ }
+ else {
+ // here it's not good, our edge is a single point -> skip that face
+ ok = false;
+#if 0
+ // the order of the WOEdge index is good
+ woea = _pWXFace->GetOEdge((index - 1) % nedges);
+ woeb = _pWXFace->GetOEdge((index + 1) % nedges);
+ ta = 1;
+ tb = 0;
+#endif
+ }
+ }
+ if (ok) {
+ _pSmoothEdge = new WXSmoothEdge;
+ _pSmoothEdge->setWOeA(woea);
+ _pSmoothEdge->setWOeB(woeb);
+ _pSmoothEdge->setTa(ta);
+ _pSmoothEdge->setTb(tb);
+ if (_Nature & Nature::SILHOUETTE) {
+ if (_nNullDotP != 2) {
+ if (_DotP[_ClosestPointIndex] + 0.01 > 0)
+ _pSmoothEdge->setFront(true);
+ else
+ _pSmoothEdge->setFront(false);
+ }
+ }
+ }
+
+#if 0
+ // check bording edges to see if they have different dotp values in bording faces.
+ for (int i = 0; i < numberOfEdges(); i++) {
+ WSFace *bface = (WSFace *)GetBordingFace(i);
+ if (bface) {
+ if ((front()) ^ (bface->front())) { // fA->front XOR fB->front (true if one is 0 and the other is 1)
+ // that means that the edge i of the face is a silhouette edge
+ // CHECK FIRST WHETHER THE EXACTSILHOUETTEEDGE HAS NOT YET BEEN BUILT ON THE OTHER FACE (1 is enough).
+ if (((WSExactFace *)bface)->exactSilhouetteEdge()) {
+ // that means that this silhouette edge has already been built
+ return ((WSExactFace *)bface)->exactSilhouetteEdge();
+ }
+ // Else we must build it
+ WOEdge *woea, *woeb;
+ real ta, tb;
+ if (!front()) { // is it in the right order ?
+ // the order of the WOEdge index is wrong
+ woea = _OEdgeList[(i + 1) % numberOfEdges()];
+ if (0 == i)
+ woeb = _OEdgeList[numberOfEdges() - 1];
+ else
+ woeb = _OEdgeList[(i - 1)];
+ ta = 0;
+ tb = 1;
+ }
+ else {
+ // the order of the WOEdge index is good
+ if (0 == i)
+ woea = _OEdgeList[numberOfEdges() - 1];
+ else
+ woea = _OEdgeList[(i - 1)];
+ woeb = _OEdgeList[(i + 1) % numberOfEdges()];
+ ta = 1;
+ tb = 0;
+ }
+
+ _pSmoothEdge = new ExactSilhouetteEdge(ExactSilhouetteEdge::VERTEX_VERTEX);
+ _pSmoothEdge->setWOeA(woea);
+ _pSmoothEdge->setWOeA(woeb);
+ _pSmoothEdge->setTa(ta);
+ _pSmoothEdge->setTb(tb);
+
+ return _pSmoothEdge;
+ }
+ }
+ }
+#endif
+ return _pSmoothEdge;
+}
+
+
+void WXFace::ComputeCenter()
+{
+ vector<WVertex *> iVertexList;
+ RetrieveVertexList(iVertexList);
+ Vec3r center;
+ for (vector<WVertex *>::iterator wv = iVertexList.begin(), wvend = iVertexList.end(); wv != wvend; ++wv) {
+ center += (*wv)->GetVertex();
+ }
+ center /= (real)iVertexList.size();
+ setCenter(center);
+}
+
+/**********************************
+ * *
+ * *
+ * WXShape *
+ * *
+ * *
+ **********************************/
+
+WFace *WXShape::MakeFace(vector<WVertex *>& iVertexList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex)
+{
+ WFace *face = WShape::MakeFace(iVertexList, iFaceEdgeMarksList, iMaterialIndex);
+ if (!face)
+ return NULL;
+
+ Vec3r center;
+ for (vector<WVertex *>::iterator wv = iVertexList.begin(), wvend = iVertexList.end(); wv != wvend; ++wv) {
+ center += (*wv)->GetVertex();
+ }
+ center /= (real)iVertexList.size();
+ ((WXFace *)face)->setCenter(center);
+
+ return face;
+}
+
+WFace *WXShape::MakeFace(vector<WVertex *>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList,
+ vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex)
+{
+ WFace *face = WShape::MakeFace(iVertexList, iNormalsList, iTexCoordsList, iFaceEdgeMarksList, iMaterialIndex);
+
+#if 0
+ Vec3r 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);
+#endif
+
+ return face;
+} \ No newline at end of file
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.h b/source/blender/freestyle/intern/winged_edge/WXEdge.h
new file mode 100644
index 00000000000..cb111dd516c
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WXEdge.h
@@ -0,0 +1,809 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_WX_EDGE_H__
+#define __FREESTYLE_WX_EDGE_H__
+
+/** \file blender/freestyle/intern/winged_edge/WXEdge.h
+ * \ingroup freestyle
+ * \brief Classes to define an Extended Winged Edge data structure.
+ * \author Stephane Grabli
+ * \date 26/10/2003
+ */
+
+#include "Curvature.h"
+#include "Nature.h"
+#include "WEdge.h"
+
+typedef Nature::EdgeNature WXNature;
+
+/**********************************
+ * *
+ * *
+ * WXVertex *
+ * *
+ * *
+ **********************************/
+
+class WXVertex : public WVertex
+{
+private:
+ // Curvature info
+ CurvatureInfo *_curvatures;
+
+public:
+ inline WXVertex(const Vec3r &v) : WVertex(v)
+ {
+ _curvatures = NULL;
+ }
+
+ /*! Copy constructor */
+ WXVertex(WXVertex& iBrother) : WVertex(iBrother)
+ {
+ _curvatures = new CurvatureInfo(*iBrother._curvatures);
+ }
+
+ virtual WVertex *duplicate()
+ {
+ WXVertex *clone = new WXVertex(*this);
+ return clone;
+ }
+
+ virtual ~WXVertex()
+ {
+ if (_curvatures)
+ delete _curvatures;
+ }
+
+ virtual void Reset()
+ {
+ if (_curvatures)
+ _curvatures->Kr = 0.0;
+ }
+
+ inline void setCurvatures(CurvatureInfo *ci)
+ {
+ _curvatures = ci;
+ }
+
+ inline bool isFeature();
+
+ inline CurvatureInfo *curvatures()
+ {
+ return _curvatures;
+ }
+};
+
+
+/**********************************
+ * *
+ * *
+ * WXEdge *
+ * *
+ * *
+ **********************************/
+
+class WXEdge : public WEdge
+{
+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;
+ // 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;
+
+public:
+ inline WXEdge() : WEdge()
+ {
+ _nature = Nature::NO_FEATURE;
+ _front = false;
+ _order = 0;
+ }
+
+ inline WXEdge(WOEdge *iOEdge) : WEdge(iOEdge)
+ {
+ _nature = Nature::NO_FEATURE;
+ _front = false;
+ _order = 0;
+ }
+
+ inline WXEdge(WOEdge *iaOEdge, WOEdge *ibOEdge) : WEdge(iaOEdge, ibOEdge)
+ {
+ _nature = Nature::NO_FEATURE;
+ _front = false;
+ _order = 0;
+ }
+
+ /*! Copy constructor */
+ inline WXEdge(WXEdge& iBrother) : WEdge(iBrother)
+ {
+ _nature = iBrother.nature();
+ _front = iBrother._front;
+ _order = iBrother._order;
+ }
+
+ virtual WEdge *duplicate()
+ {
+ WXEdge *clone = new WXEdge(*this);
+ return clone;
+ }
+
+ virtual ~WXEdge() {}
+
+ virtual void Reset()
+ {
+ _nature = _nature & ~Nature::SILHOUETTE;
+ _nature = _nature & ~Nature::SUGGESTIVE_CONTOUR;
+ }
+
+ /*! accessors */
+ inline WXNature nature()
+ {
+ return _nature;
+ }
+
+ inline bool front()
+ {
+ return _front;
+ }
+
+ inline int order() const
+ {
+ return _order;
+ }
+
+ /*! modifiers */
+ inline void setFront(bool iFront)
+ {
+ _front = iFront;
+ }
+
+ inline void setNature(WXNature iNature)
+ {
+ _nature = iNature;
+ }
+
+ inline void AddNature(WXNature iNature)
+ {
+ _nature = _nature | iNature;
+ }
+
+ inline void setOrder(int i)
+ {
+ _order = i;
+ }
+};
+
+/**********************************
+ * *
+ * *
+ * WXFace *
+ * *
+ * *
+ **********************************/
+
+/*! Class to store a smooth edge (i.e Hertzman & Zorin smooth silhouette edges) */
+class WXSmoothEdge
+{
+public:
+ typedef enum {
+ EDGE_EDGE,
+ VERTEX_EDGE,
+ EDGE_VERTEX,
+ } Configuration;
+
+ 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])
+ bool _front;
+ Configuration _config;
+
+ WXSmoothEdge()
+ {
+ _woea = NULL;
+ _woeb = NULL;
+ _ta = 0;
+ _tb = 0;
+ _front = false;
+ _config = EDGE_EDGE;
+ }
+
+ WXSmoothEdge(const WXSmoothEdge& iBrother)
+ {
+ _woea = iBrother._woea;
+ _woeb = iBrother._woeb;
+ _ta = iBrother._ta;
+ _tb = iBrother._tb;
+ _config = iBrother._config;
+ _front = iBrother._front;
+ }
+
+ ~WXSmoothEdge() {}
+
+ inline WOEdge *woea()
+ {
+ return _woea;
+ }
+
+ inline WOEdge *woeb()
+ {
+ return _woeb;
+ }
+
+ inline real ta() const
+ {
+ return _ta;
+ }
+
+ inline real tb() const
+ {
+ return _tb;
+ }
+
+ inline bool front() const
+ {
+ return _front;
+ }
+
+ inline Configuration configuration() const
+ {
+ return _config;
+ }
+
+ /*! modifiers */
+ inline void setWOeA(WOEdge *iwoea)
+ {
+ _woea = iwoea;
+ }
+
+ inline void setWOeB(WOEdge *iwoeb)
+ {
+ _woeb = iwoeb;
+ }
+
+ inline void setTa(real ta)
+ {
+ _ta = ta;
+ }
+
+ inline void setTb(real tb)
+ {
+ _tb = tb;
+ }
+
+ inline void setFront(bool iFront)
+ {
+ _front = iFront;
+ }
+
+ inline void setConfiguration(Configuration iConf)
+ {
+ _config = iConf;
+ }
+};
+
+/* Class to store a value per vertex and a smooth edge.
+ * The WXFace stores a list of these
+ */
+class WXFace;
+
+class LIB_WINGED_EDGE_EXPORT WXFaceLayer
+{
+public:
+ void *userdata;
+ 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;
+ WXSmoothEdge *_pSmoothEdge;
+ WXNature _Nature;
+
+ //oldtmp values
+ // count the number of positive dot products for vertices.
+ // if this number is != 0 and !=_DotP.size() -> it is a silhouette fac
+ unsigned _nPosDotP;
+
+ unsigned _nNullDotP; // count the number of null dot products for vertices.
+ unsigned _ClosestPointIndex;
+ bool _viewDependant;
+
+ WXFaceLayer(WXFace *iFace, WXNature iNature, bool viewDependant)
+ {
+ _pWXFace = iFace;
+ _pSmoothEdge = NULL;
+ _nPosDotP = 0;
+ _nNullDotP = 0;
+ _Nature = iNature;
+ _viewDependant = viewDependant;
+ userdata = NULL;
+ }
+
+ WXFaceLayer(const WXFaceLayer& iBrother)
+ {
+ _pWXFace = iBrother._pWXFace;
+ _pSmoothEdge = NULL;
+ _DotP = iBrother._DotP;
+ _nPosDotP = iBrother._nPosDotP;
+ _nNullDotP = iBrother._nNullDotP;
+ _Nature = iBrother._Nature;
+ if (iBrother._pSmoothEdge) { // XXX ? It's set to null a few lines above!
+ _pSmoothEdge = new WXSmoothEdge(*(iBrother._pSmoothEdge));
+ }
+ _viewDependant = iBrother._viewDependant;
+ userdata = NULL;
+ }
+
+ virtual ~WXFaceLayer()
+ {
+ if (!_DotP.empty())
+ _DotP.clear();
+ if (_pSmoothEdge) {
+ delete _pSmoothEdge;
+ _pSmoothEdge = NULL;
+ }
+ }
+
+ inline const real dotP(int i) const
+ {
+ return _DotP[i];
+ }
+
+ inline unsigned nPosDotP() const
+ {
+ return _nPosDotP;
+ }
+
+ inline unsigned nNullDotP() const
+ {
+ return _nNullDotP;
+ }
+
+ inline int closestPointIndex() const
+ {
+ return _ClosestPointIndex;
+ }
+
+ inline Nature::EdgeNature nature() const
+ {
+ return _Nature;
+ }
+
+ inline bool hasSmoothEdge() const
+ {
+ if (_pSmoothEdge)
+ return true;
+ return false;
+ }
+
+ inline WXFace *getFace()
+ {
+ return _pWXFace;
+ }
+
+ inline WXSmoothEdge *getSmoothEdge()
+ {
+ return _pSmoothEdge;
+ }
+
+ inline bool isViewDependant() const
+ {
+ return _viewDependant;
+ }
+
+ inline void setClosestPointIndex(int iIndex)
+ {
+ _ClosestPointIndex = iIndex;
+ }
+
+ inline void removeSmoothEdge()
+ {
+ if (!_DotP.empty())
+ _DotP.clear();
+ if (_pSmoothEdge) {
+ delete _pSmoothEdge;
+ _pSmoothEdge = NULL;
+ }
+ }
+
+ /*! If one of the face layer vertex has a DotP equal to 0, this method returns the vertex where it happens */
+ unsigned int Get0VertexIndex() const;
+
+ /*! In case one of the edge of the triangle is a smooth edge, this method allows to retrieve the concerned edge */
+ unsigned int GetSmoothEdgeIndex() const;
+
+ /*! retrieves the edges of the triangle for which the signs are different (a null value is not considered) for
+ * the dotp values at each edge extrimity
+ */
+ void RetrieveCuspEdgesIndices(vector<int>& oCuspEdges);
+
+ WXSmoothEdge *BuildSmoothEdge();
+
+ inline void setDotP(const vector<real>& iDotP)
+ {
+ _DotP = iDotP;
+ }
+
+ inline void PushDotP(real iDotP)
+ {
+ _DotP.push_back(iDotP);
+ if (iDotP > 0)
+ ++_nPosDotP;
+ if (iDotP == 0)
+ ++_nNullDotP;
+ }
+
+ inline void ReplaceDotP(unsigned int index, real newDotP)
+ {
+ _DotP[index] = newDotP;
+ updateDotPInfos();
+ }
+
+ inline void updateDotPInfos()
+ {
+ _nPosDotP = 0;
+ _nNullDotP = 0;
+ for (vector<real>::iterator d = _DotP.begin(), dend = _DotP.end(); d != dend; ++d) {
+ if ((*d) > 0)
+ ++_nPosDotP;
+ if ((*d) == 0)
+ ++_nNullDotP;
+ }
+ }
+};
+
+class WXFace : public WFace
+{
+protected:
+ Vec3r _center; // center of the face
+ real _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
+
+ vector<WXFaceLayer *> _SmoothLayers; // The data needed to store one or several smooth edges that traverse the face
+
+public:
+ inline WXFace() : WFace()
+ {
+ _Z = 0.0;
+ _front = false;
+ }
+
+ /*! Copy constructor */
+ WXFace(WXFace& iBrother) : WFace(iBrother)
+ {
+ _center = iBrother.center();
+ _Z = iBrother.Z();
+ _front = iBrother.front();
+ for (vector<WXFaceLayer*>::iterator wxf = iBrother._SmoothLayers.begin(), wxfend = iBrother._SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf)
+ {
+ _SmoothLayers.push_back(new WXFaceLayer(**wxf));
+ }
+ }
+
+ virtual WFace *duplicate()
+ {
+ WXFace *clone = new WXFace(*this);
+ return clone;
+ }
+
+ virtual ~WXFace()
+ {
+ if (!_SmoothLayers.empty()) {
+ for (vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf)
+ {
+ delete (*wxf);
+ }
+ _SmoothLayers.clear();
+ }
+ }
+
+ /*! designed to build a specialized WEdge for use in MakeEdge */
+ virtual WEdge *instanciateEdge() const
+ {
+ return new WXEdge;
+ }
+
+ /*! accessors */
+ inline Vec3r& center()
+ {
+ return _center;
+ }
+
+ inline real Z()
+ {
+ return _Z;
+ }
+
+ inline bool front()
+ {
+ return _front;
+ }
+
+ inline real dotp()
+ {
+ return _dotp;
+ }
+
+ inline bool hasSmoothEdges() const
+ {
+ for (vector<WXFaceLayer*>::const_iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf)
+ {
+ if ((*wxf)->hasSmoothEdge()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ vector<WXFaceLayer*>& getSmoothLayers()
+ {
+ return _SmoothLayers;
+ }
+
+ /*! retrieve the smooth edges that match the Nature given as argument */
+ void retrieveSmoothEdges(WXNature iNature, vector<WXSmoothEdge *>& oSmoothEdges)
+ {
+ for (vector<WXFaceLayer *>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf)
+ {
+ if ((*wxf)->hasSmoothEdge() && ((*wxf)->_Nature & iNature)) {
+ oSmoothEdges.push_back((*wxf)->_pSmoothEdge);
+ }
+ }
+ }
+
+ void retrieveSmoothEdgesLayers(WXNature iNature, vector<WXFaceLayer *>& oSmoothEdgesLayers)
+ {
+ for (vector<WXFaceLayer *>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf)
+ {
+ if ((*wxf)->hasSmoothEdge() && ((*wxf)->_Nature & iNature)) {
+ oSmoothEdgesLayers.push_back((*wxf));
+ }
+ }
+ }
+
+ void retrieveSmoothLayers(WXNature iNature, vector<WXFaceLayer *>& oSmoothLayers)
+ {
+ for (vector<WXFaceLayer *>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf)
+ {
+ if ((*wxf)->_Nature & iNature) {
+ oSmoothLayers.push_back(*wxf);
+ }
+ }
+ }
+
+ /*! modifiers */
+ inline void setCenter(const Vec3r& iCenter)
+ {
+ _center = iCenter;
+ }
+
+ void ComputeCenter();
+
+ inline void setZ(real z)
+ {
+ _Z = z;
+ }
+
+ inline void setFront(bool iFront)
+ {
+ _front = iFront;
+ }
+
+ inline void setDotP(real iDotP)
+ {
+ _dotp = iDotP;
+ if (_dotp > 0)
+ _front = true;
+ else
+ _front = false;
+ }
+
+ inline void AddSmoothLayer(WXFaceLayer *iLayer)
+ {
+ _SmoothLayers.push_back(iLayer);
+ }
+
+ inline void Reset()
+ {
+ vector<WXFaceLayer *> layersToKeep;
+ for (vector<WXFaceLayer *>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf)
+ {
+ if ((*wxf)->isViewDependant())
+ delete (*wxf);
+ else
+ layersToKeep.push_back(*wxf);
+ }
+ _SmoothLayers = layersToKeep;
+ }
+
+ /*! Clears everything */
+ inline void Clear()
+ {
+ for (vector<WXFaceLayer *>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf)
+ {
+ delete (*wxf);
+ }
+ _SmoothLayers.clear();
+ }
+
+ virtual void ResetUserData()
+ {
+ WFace::ResetUserData();
+ for (vector<WXFaceLayer *>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf)
+ {
+ (*wxf)->userdata = NULL;
+ }
+ }
+};
+
+
+/**********************************
+ * *
+ * *
+ * WXShape *
+ * *
+ * *
+ **********************************/
+
+class WXShape : public WShape
+{
+public:
+ typedef WXShape type_name;
+
+protected:
+ bool _computeViewIndependant; // flag to indicate whether the view independant stuff must be computed or not
+
+public:
+ inline WXShape() : WShape()
+ {
+ _computeViewIndependant = true;
+ }
+
+ /*! copy constructor */
+ inline WXShape(WXShape& iBrother) : WShape(iBrother)
+ {
+ _computeViewIndependant = iBrother._computeViewIndependant;
+ }
+
+ virtual WShape *duplicate()
+ {
+ WXShape *clone = new WXShape(*this);
+ return clone;
+ }
+
+ virtual ~WXShape() {}
+
+ inline bool getComputeViewIndependantFlag() const
+ {
+ return _computeViewIndependant;
+ }
+
+ inline void setComputeViewIndependantFlag(bool iFlag)
+ {
+ _computeViewIndependant = iFlag;
+ }
+
+ /*! designed to build a specialized WFace for use in MakeFace */
+ virtual WFace *instanciateFace() const
+ {
+ return new WXFace;
+ }
+
+ /*! adds a new face to the shape returns the built face.
+ * iVertexList
+ * List of face's vertices. These vertices are not added to the WShape vertex list; they are supposed
+ * to be already stored when calling MakeFace. The order in which the vertices are stored in the list
+ * determines the face's edges orientation and (so) the face orientation.
+ */
+ virtual WFace *MakeFace(vector<WVertex *>& iVertexList, vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex);
+
+ /*! adds a new face to the shape. The difference with the previous method is that this one is designed to build
+ * a WingedEdge structure for which there are per vertex normals, opposed to per face normals.
+ * returns the built face.
+ * iVertexList
+ * List of face's vertices. These vertices are not added to the WShape vertex list; they are supposed to be
+ * already stored when calling MakeFace.
+ * The order in which the vertices are stored in the list determines the face's edges orientation and (so) the
+ * face orientation.
+ * iNormalsList
+ * The list of normals, iNormalsList[i] corresponding to the normal of the vertex iVertexList[i] for that face.
+ * iTexCoordsList
+ * 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,
+ vector<bool>& iFaceEdgeMarksList, unsigned iMaterialIndex);
+
+ /*! Reset all edges and vertices flags (which might have been set up on a previous pass) */
+ virtual void Reset()
+ {
+ // Reset Edges
+ vector<WEdge *>& wedges = getEdgeList();
+ for (vector<WEdge *>::iterator we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
+ ((WXEdge *)(*we))->Reset();
+ }
+
+ //Reset faces:
+ vector<WFace *>& wfaces = GetFaceList();
+ for (vector<WFace *>::iterator wf = wfaces.begin(), wfend = wfaces.end(); wf != wfend; ++wf) {
+ ((WXFace *)(*wf))->Reset();
+ }
+ }
+ /*! accessors */
+};
+
+/*
+
+#############################################
+#############################################
+#############################################
+###### ######
+###### I M P L E M E N T A T I O N ######
+###### ######
+#############################################
+#############################################
+#############################################
+
+*/
+/* for inline functions */
+
+bool WXVertex::isFeature()
+{
+ int counter = 0;
+ vector<WEdge *>& vedges = GetEdges();
+ for (vector<WEdge *>::iterator ve = vedges.begin(), vend = vedges.end(); ve != vend; ++ve) {
+ if (((WXEdge *)(*ve))->nature() != Nature::NO_FEATURE)
+ counter++;
+ }
+
+ if ((counter == 1) || (counter > 2))
+ return true;
+ return false;
+}
+
+#endif // __FREESTYLE_WX_EDGE_H__ \ No newline at end of file
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp
new file mode 100644
index 00000000000..772a88a05af
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp
@@ -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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp
+ * \ingroup freestyle
+ * \brief Class inherited from WingedEdgeBuilder and designed to build a WX (WingedEdge + extended info
+ * (silhouette etc...)) structure from a polygonal model
+ * \author Stephane Grabli
+ * \date 28/05/2003
+ */
+
+#include "WXEdge.h"
+#include "WXEdgeBuilder.h"
+
+void WXEdgeBuilder::visitIndexedFaceSet(IndexedFaceSet& ifs)
+{
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ return;
+ WXShape *shape = new WXShape;
+ buildWShape(*shape, ifs);
+ shape->setId(ifs.getId().getFirst());
+ shape->setName(ifs.getName());
+ //ifs.setId(shape->GetId());
+}
+
+void WXEdgeBuilder::buildWVertices(WShape& shape, const real *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->setId(i / 3);
+ shape.AddVertex(vertex);
+ }
+} \ No newline at end of file
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h
new file mode 100644
index 00000000000..690126c533e
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h
@@ -0,0 +1,54 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_WX_EDGE_BUILDER_H__
+#define __FREESTYLE_WX_EDGE_BUILDER_H__
+
+/** \file blender/freestyle/intern/winged_edge/WXEdgeBuilder.h
+ * \ingroup freestyle
+ * \brief Class inherited from WingedEdgeBuilder and designed to build a WX (WingedEdge + extended info
+ * (silhouette etc...)) structure from a polygonal model
+ * \author Stephane Grabli
+ * \date 28/05/2003
+ */
+
+#include "WingedEdgeBuilder.h"
+
+#include "../scene_graph/IndexedFaceSet.h"
+
+class LIB_WINGED_EDGE_EXPORT WXEdgeBuilder : public WingedEdgeBuilder
+{
+public:
+ WXEdgeBuilder() : WingedEdgeBuilder() {}
+ virtual ~WXEdgeBuilder() {}
+ VISIT_DECL(IndexedFaceSet)
+
+protected:
+ virtual void buildWVertices(WShape& shape, const real *vertices, unsigned vsize);
+};
+
+#endif // __FREESTYLE_WX_EDGE_BUILDER_H__ \ No newline at end of file
diff --git a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp
new file mode 100644
index 00000000000..c1a93f70a7e
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp
@@ -0,0 +1,373 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp
+ * \ingroup freestyle
+ * \brief Class to render a WingedEdge data structure from a polyhedral data structure organized in nodes
+ * of a scene graph
+ * \author Stephane Grabli
+ * \date 28/05/2003
+ */
+
+#include <set>
+
+#include "WingedEdgeBuilder.h"
+
+#include "../geometry/GeomUtils.h"
+
+#include "../scene_graph/NodeShape.h"
+
+using namespace std;
+
+void WingedEdgeBuilder::visitIndexedFaceSet(IndexedFaceSet& ifs)
+{
+ if (_pRenderMonitor && _pRenderMonitor->testBreak())
+ return;
+ WShape *shape = new WShape;
+ buildWShape(*shape, ifs);
+ shape->setId(ifs.getId().getFirst());
+ //ifs.setId(shape->GetId());
+}
+
+void WingedEdgeBuilder::visitNodeShape(NodeShape& ns)
+{
+ //Sets the current material to iShapeode->material:
+ _current_frs_material = &(ns.frs_material());
+}
+
+void WingedEdgeBuilder::visitNodeTransform(NodeTransform& tn)
+{
+ if (!_current_matrix) {
+ _current_matrix = new Matrix44r(tn.matrix());
+ return;
+ }
+
+ _matrices_stack.push_back(_current_matrix);
+ Matrix44r *new_matrix = new Matrix44r(*_current_matrix * tn.matrix());
+ _current_matrix = new_matrix;
+}
+
+void WingedEdgeBuilder::visitNodeTransformAfter(NodeTransform&)
+{
+ if (_current_matrix)
+ delete _current_matrix;
+
+ if (_matrices_stack.empty()) {
+ _current_matrix = NULL;
+ return;
+ }
+
+ _current_matrix = _matrices_stack.back();
+ _matrices_stack.pop_back();
+}
+
+void WingedEdgeBuilder::buildWShape(WShape& shape, IndexedFaceSet& ifs)
+{
+ unsigned int vsize = ifs.vsize();
+ 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();
+
+ real *new_vertices;
+ real *new_normals;
+
+ new_vertices = new real[vsize];
+ new_normals = new real[nsize];
+
+ // transform coordinates from local to world system
+ if (_current_matrix) {
+ transformVertices(vertices, vsize, *_current_matrix, new_vertices);
+ transformNormals(normals, nsize, *_current_matrix, new_normals);
+ }
+ else {
+ memcpy(new_vertices, vertices, vsize * sizeof(*new_vertices));
+ memcpy(new_normals, normals, nsize * sizeof(*new_normals));
+ }
+
+ const IndexedFaceSet::TRIANGLES_STYLE *faceStyle = ifs.trianglesStyle();
+
+ vector<FrsMaterial> frs_materials;
+ if (ifs.msize()) {
+ const FrsMaterial *const *mats = ifs.frs_materials();
+ for (unsigned i = 0; i < ifs.msize(); ++i)
+ frs_materials.push_back(*(mats[i]));
+ shape.setFrsMaterials(frs_materials);
+ }
+
+#if 0
+ const FrsMaterial *mat = (ifs.frs_material());
+ if (mat)
+ shape.setFrsMaterial(*mat);
+ else if (_current_frs_material)
+ shape.setFrsMaterial(*_current_frs_material);
+#endif
+ const IndexedFaceSet::FaceEdgeMark *faceEdgeMarks = ifs.faceEdgeMarks();
+
+ // sets the current WShape to shape
+ _current_wshape = &shape;
+
+ // create a WVertex for each vertex
+ buildWVertices(shape, new_vertices, vsize);
+
+ const unsigned int *vindices = ifs.vindices();
+ const unsigned int *nindices = ifs.nindices();
+ const unsigned int *tindices = NULL;
+ if (ifs.tsize()) {
+ tindices = ifs.tindices();
+ }
+
+ const unsigned int *mindices = NULL;
+ if (ifs.msize())
+ mindices = ifs.mindices();
+ const unsigned int *numVertexPerFace = ifs.numVertexPerFaces();
+ const unsigned int numfaces = ifs.numFaces();
+
+ for (unsigned int index = 0; index < numfaces; index++) {
+ switch (faceStyle[index]) {
+ case IndexedFaceSet::TRIANGLE_STRIP:
+ buildTriangleStrip(new_vertices, new_normals, frs_materials, texCoords, faceEdgeMarks, vindices,
+ nindices, mindices, tindices, numVertexPerFace[index]);
+ break;
+ case IndexedFaceSet::TRIANGLE_FAN:
+ buildTriangleFan(new_vertices, new_normals, frs_materials, texCoords, faceEdgeMarks, vindices,
+ nindices, mindices, tindices, numVertexPerFace[index]);
+ break;
+ case IndexedFaceSet::TRIANGLES:
+ buildTriangles(new_vertices, new_normals, frs_materials, texCoords, faceEdgeMarks, vindices,
+ nindices, mindices, tindices, numVertexPerFace[index]);
+ break;
+ }
+ vindices += numVertexPerFace[index];
+ nindices += numVertexPerFace[index];
+ if (mindices)
+ mindices += numVertexPerFace[index];
+ if (tindices)
+ tindices += numVertexPerFace[index];
+ faceEdgeMarks++;
+ }
+
+ delete[] new_vertices;
+ delete[] new_normals;
+
+ // compute bbox
+ shape.ComputeBBox();
+ // compute mean edge size:
+ shape.ComputeMeanEdgeSize();
+
+ // Parse the built winged-edge shape to update post-flags
+ set<Vec3r> normalsSet;
+ vector<WVertex *>& wvertices = shape.getVertexList();
+ for (vector<WVertex *>::iterator wv = wvertices.begin(), wvend = wvertices.end(); wv != wvend; ++wv) {
+ if ((*wv)->isBoundary())
+ continue;
+ if ((*wv)->GetEdges().size() == 0) // This means that the WVertex has no incoming edges... (12-Sep-2011 T.K.)
+ continue;
+ normalsSet.clear();
+ WVertex::face_iterator fit = (*wv)->faces_begin();
+ WVertex::face_iterator fitend = (*wv)->faces_end();
+ for (; fit != fitend; ++fit) {
+ WFace *face = *fit;
+ normalsSet.insert(face->GetVertexNormal(*wv));
+ if (normalsSet.size() != 1) {
+ break;
+ }
+ }
+ if (normalsSet.size() != 1) {
+ (*wv)->setSmooth(false);
+ }
+ }
+ // Adds the new WShape to the WingedEdge structure
+ _winged_edge->addWShape(&shape);
+}
+
+void WingedEdgeBuilder::buildWVertices(WShape& shape, const real *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->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,
+ const unsigned *vindices, const unsigned *nindices, const unsigned *mindices,
+ const unsigned *tindices, const unsigned nvertices)
+{
+ unsigned nDoneVertices = 2; // number of vertices already treated
+ unsigned nTriangle = 0; // number of the triangle currently being treated
+ //int nVertex = 0; // vertex number
+
+ WShape *currentShape = _current_wshape; // the current shape being built
+ vector<WVertex *> triangleVertices;
+ vector<Vec3r> triangleNormals;
+ vector<Vec2r> triangleTexCoords;
+ vector<bool> triangleFaceEdgeMarks;
+
+ while (nDoneVertices < nvertices) {
+ //clear the vertices list:
+ triangleVertices.clear();
+ //Then rebuild it:
+ if (0 == nTriangle % 2) { // if nTriangle is even
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle] / 3]);
+ 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],
+ normals[nindices[nTriangle] + 2]));
+ triangleNormals.push_back(Vec3r(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],
+ 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]],
+ texCoords[tindices[nTriangle + 1] + 1]));
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle + 2]],
+ texCoords[tindices[nTriangle + 2] + 1]));
+ }
+ }
+ else { // if nTriangle is odd
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle] / 3]);
+ 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],
+ normals[nindices[nTriangle] + 2]));
+ triangleNormals.push_back(Vec3r(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],
+ 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]],
+ texCoords[tindices[nTriangle + 2] + 1]));
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle + 1]],
+ texCoords[tindices[nTriangle + 1] + 1]));
+ }
+ }
+ triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle / 3] & IndexedFaceSet::FACE_MARK) != 0);
+ triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle / 3] & IndexedFaceSet::EDGE_MARK_V1V2) != 0);
+ triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle / 3] & IndexedFaceSet::EDGE_MARK_V2V3) != 0);
+ triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle / 3] & IndexedFaceSet::EDGE_MARK_V3V1) != 0);
+ if (mindices) {
+ currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks,
+ mindices[nTriangle / 3]);
+ }
+ else {
+ currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, 0);
+ }
+ nDoneVertices++; // with a strip, each triangle is one vertex more
+ nTriangle++;
+ }
+}
+
+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)
+{
+ // Nothing to be done
+}
+
+void WingedEdgeBuilder::buildTriangles(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)
+{
+ WShape *currentShape = _current_wshape; // the current shape begin built
+ vector<WVertex *> triangleVertices;
+ vector<Vec3r> triangleNormals;
+ vector<Vec2r> triangleTexCoords;
+ vector<bool> triangleFaceEdgeMarks;
+
+ // Each triplet of vertices is considered as an independent triangle
+ for (unsigned int i = 0; i < nvertices / 3; i++) {
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[3 * i] / 3]);
+ 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],
+ normals[nindices[3 * i] + 2]));
+ triangleNormals.push_back(Vec3r(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],
+ 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]));
+ }
+
+ triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::FACE_MARK) != 0);
+ triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::EDGE_MARK_V1V2) != 0);
+ triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::EDGE_MARK_V2V3) != 0);
+ triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::EDGE_MARK_V3V1) != 0);
+ }
+ if (mindices)
+ currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks,
+ mindices[0]);
+ else
+ currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, 0);
+}
+
+void WingedEdgeBuilder::transformVertices(const real *vertices, unsigned vsize, const Matrix44r& transform, real *res)
+{
+ const real *v = vertices;
+ real *pv = res;
+
+ for (unsigned int i = 0; i < vsize / 3; i++) {
+ HVec3r hv_tmp(v[0], v[1], v[2]);
+ HVec3r hv(transform * hv_tmp);
+ for (unsigned int j = 0; j < 3; j++)
+ pv[j] = hv[j] / hv[3];
+ v += 3;
+ pv += 3;
+ }
+}
+
+void WingedEdgeBuilder::transformNormals(const real *normals, unsigned nsize, const Matrix44r& transform, real *res)
+{
+ const real *n = normals;
+ real *pn = res;
+
+ for (unsigned int i = 0; i < nsize / 3; i++) {
+ Vec3r hn(n[0], n[1], n[2]);
+ hn = GeomUtils::rotateVector(transform, hn);
+ for (unsigned int j = 0; j < 3; j++)
+ pn[j] = hn[j];
+ n += 3;
+ pn += 3;
+ }
+} \ No newline at end of file
diff --git a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h
new file mode 100644
index 00000000000..cf32c1191b2
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h
@@ -0,0 +1,157 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FREESTYLE_WINGED_EDGE_BUILDER_H__
+#define __FREESTYLE_WINGED_EDGE_BUILDER_H__
+
+/** \file blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h
+ * \ingroup freestyle
+ * \brief Class to render a WingedEdge data structure from a polyhedral data structure organized in nodes
+ * of a scene graph
+ * \author Stephane Grabli
+ * \date 28/05/2003
+ */
+
+#include "WEdge.h"
+
+#include "../scene_graph/IndexedFaceSet.h"
+#include "../scene_graph/NodeTransform.h"
+#include "../scene_graph/SceneVisitor.h"
+
+#include "../system/FreestyleConfig.h"
+#include "../system/RenderMonitor.h"
+
+class LIB_WINGED_EDGE_EXPORT WingedEdgeBuilder : public SceneVisitor
+{
+public:
+ inline WingedEdgeBuilder() : SceneVisitor()
+ {
+ _current_wshape = NULL;
+ _current_frs_material = NULL;
+ _current_matrix = NULL;
+ _winged_edge = new WingedEdge; // Not deleted by the destructor
+ _pRenderMonitor = NULL;
+ }
+
+ virtual ~WingedEdgeBuilder()
+ {
+ for (vector<Matrix44r*>::iterator it = _matrices_stack.begin(); it != _matrices_stack.end(); ++it)
+ delete *it;
+ _matrices_stack.clear();
+ }
+
+ VISIT_DECL(IndexedFaceSet)
+ VISIT_DECL(NodeShape)
+ VISIT_DECL(NodeTransform)
+
+ virtual void visitNodeTransformAfter(NodeTransform&);
+
+ //
+ // Accessors
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ inline WingedEdge *getWingedEdge()
+ {
+ return _winged_edge;
+ }
+
+ inline WShape *getCurrentWShape()
+ {
+ return _current_wshape;
+ }
+
+ inline FrsMaterial *getCurrentFrsMaterial()
+ {
+ return _current_frs_material;
+ }
+
+ inline Matrix44r *getCurrentMatrix()
+ {
+ return _current_matrix;
+ }
+
+ //
+ // Modifiers
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ inline void setCurrentWShape(WShape *wshape)
+ {
+ _current_wshape = wshape;
+ }
+
+ inline void setCurrentFrsMaterial(FrsMaterial *mat)
+ {
+ _current_frs_material = mat;
+ }
+
+#if 0
+ inline void setCurrentMatrix(Matrix44r *matrix)
+ {
+ _current_matrix = matrix;
+ }
+#endif
+
+ inline void setRenderMonitor(RenderMonitor *iRenderMonitor) {
+ _pRenderMonitor = iRenderMonitor;
+ }
+
+protected:
+ virtual void buildWShape(WShape& shape, IndexedFaceSet& ifs);
+ virtual void buildWVertices(WShape& shape, const real *vertices, unsigned vsize);
+
+ RenderMonitor *_pRenderMonitor;
+
+private:
+ void buildTriangleStrip(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 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 buildTriangles(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 transformVertices(const real *vertices, unsigned vsize, const Matrix44r& transform, real *res);
+
+ void transformNormals(const real *normals, unsigned nsize, const Matrix44r& transform, real *res);
+
+ WShape *_current_wshape;
+ FrsMaterial *_current_frs_material;
+ WingedEdge *_winged_edge;
+ Matrix44r *_current_matrix;
+ vector<Matrix44r *> _matrices_stack;
+};
+
+#endif // __FREESTYLE_WINGED_EDGE_BUILDER_H__ \ No newline at end of file
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 9ce42d9e0bb..485f5d65853 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -28,6 +28,7 @@ set(INC
../blenkernel
../blenlib
../blenloader
+ ../bmesh
../imbuf
../makesdna
../makesrna
@@ -50,18 +51,22 @@ set(SRC
intern/gpu_draw.c
intern/gpu_extensions.c
intern/gpu_material.c
+ intern/gpu_simple_shader.c
GPU_buffers.h
GPU_draw.h
GPU_extensions.h
GPU_material.h
+ GPU_simple_shader.h
intern/gpu_codegen.h
)
data_to_c_simple(shaders/gpu_shader_material.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_vertex.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_vsm_store_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vsm_store_vert.glsl SRC)
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index 36fbd818f11..9f6f80585ab 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -39,12 +39,15 @@
#define DEBUG_VBO(X)
#endif
+struct BMesh;
struct CCGElem;
struct CCGKey;
struct CustomData;
struct DMFlagMat;
struct DerivedMesh;
+struct GHash;
struct GPUVertPointLink;
+struct PBVH;
typedef struct GPUBuffer {
int size; /* in bytes */
@@ -168,12 +171,21 @@ void GPU_update_mesh_buffers(GPU_Buffers *buffers, MVert *mvert,
GPU_Buffers *GPU_build_grid_buffers(int *grid_indices, int totgrid,
unsigned int **grid_hidden, int gridsize);
+GPU_Buffers *GPU_build_bmesh_buffers(int smooth_shading);
+
+void GPU_update_bmesh_buffers(GPU_Buffers *buffers,
+ struct BMesh *bm,
+ struct GHash *bm_faces,
+ struct GHash *bm_unique_verts,
+ struct GHash *bm_other_verts);
+
void GPU_update_grid_buffers(GPU_Buffers *buffers, struct CCGElem **grids,
const struct DMFlagMat *grid_flag_mats,
int *grid_indices, int totgrid, const struct CCGKey *key,
int show_diffuse_color);
-void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial);
+void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial,
+ int wireframe);
int GPU_buffers_diffuse_changed(GPU_Buffers *buffers, int show_diffuse_color);
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index 974865db1c0..959c5126305 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -69,7 +69,7 @@ void GPU_state_print(void);
* - after drawing, the material must be disabled again */
void GPU_begin_object_materials(struct View3D *v3d, struct RegionView3D *rv3d,
- struct Scene *scene, struct Object *ob, int glsl, int *do_alpha_after);
+ struct Scene *scene, struct Object *ob, bool glsl, bool *do_alpha_after);
void GPU_end_object_materials(void);
int GPU_enable_material(int nr, void *attribs);
@@ -124,7 +124,7 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap);
void GPU_paint_update_image(struct Image *ima, 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, int compare, int mipmap, int isdata);
+int GPU_verify_image(struct Image *ima, struct ImageUser *iuser, int tftile, int compare, int mipmap, bool is_data);
void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float *frect, int rectw, int recth, int mipmap, int 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);
int GPU_upload_dxt_texture(struct ImBuf *ibuf);
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index 7eaa4084e61..0ae45775473 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -32,13 +32,16 @@
#ifndef __GPU_EXTENSIONS_H__
#define __GPU_EXTENSIONS_H__
+#include "BLI_utildefines.h"
+
#ifdef __cplusplus
extern "C" {
#endif
struct Image;
struct ImageUser;
-
+struct PreviewImage;
+
struct GPUTexture;
typedef struct GPUTexture GPUTexture;
@@ -112,6 +115,8 @@ 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_from_blender(struct Image *ima,
struct ImageUser *iuser, int isdata, double time, int mipmap);
+GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap);
+
void GPU_texture_free(GPUTexture *tex);
void GPU_texture_ref(GPUTexture *tex);
@@ -152,22 +157,24 @@ void GPU_offscreen_free(GPUOffScreen *ofs);
void GPU_offscreen_bind(GPUOffScreen *ofs);
void GPU_offscreen_unbind(GPUOffScreen *ofs);
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
+int GPU_offscreen_width(GPUOffScreen *ofs);
+int GPU_offscreen_height(GPUOffScreen *ofs);
/* 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); /*GPUShader *lib);*/
-/*GPUShader *GPU_shader_create_lib(const char *code);*/
+GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *libcode, const char *defines);
void GPU_shader_free(GPUShader *shader);
void GPU_shader_bind(GPUShader *shader);
-void GPU_shader_unbind(GPUShader *shader);
+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);
void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex);
+void GPU_shader_uniform_int(GPUShader *shader, int location, int value);
int GPU_shader_get_attribute(GPUShader *shader, const char *name);
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 20791652735..17d3ce3cd73 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -54,6 +54,7 @@ struct GPUNodeStack;
struct GPUMaterial;
struct GPUTexture;
struct GPULamp;
+struct PreviewImage;
typedef struct GPUNode GPUNode;
typedef struct GPUNodeLink GPUNodeLink;
@@ -108,6 +109,7 @@ GPUNodeLink *GPU_attribute(int type, const char *name);
GPUNodeLink *GPU_uniform(float *num);
GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data);
GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, int isdata);
+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_builtin(GPUBuiltin builtin);
@@ -122,6 +124,7 @@ GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]);
/* High level functions to create and use GPU materials */
GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma);
+GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma);
void GPU_material_free(struct Material *ma);
void GPU_materials_free(void);
@@ -234,6 +237,7 @@ int GPU_lamp_has_shadow_buffer(GPULamp *lamp);
void GPU_lamp_update_buffer_mats(GPULamp *lamp);
void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4]);
void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp);
+int GPU_lamp_shadow_buffer_type(GPULamp *lamp);
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);
diff --git a/source/blender/gpu/GPU_simple_shader.h b/source/blender/gpu/GPU_simple_shader.h
new file mode 100644
index 00000000000..c8fb1f09b04
--- /dev/null
+++ b/source/blender/gpu/GPU_simple_shader.h
@@ -0,0 +1,89 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_simple_shader.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_SIMPLE_SHADER_H__
+#define __GPU_SIMPLE_SHADER_H__
+
+#include "BLI_utildefines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Fixed Function Shader */
+
+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_SOLID_LIGHTING = (1<<4), /* use faster lighting (set automatically) */
+ GPU_SHADER_OPTIONS_NUM = 5,
+ GPU_SHADER_OPTION_COMBINATIONS = (1<<GPU_SHADER_OPTIONS_NUM)
+} GPUSimpleShaderOption;
+
+void GPU_simple_shaders_init(void);
+void GPU_simple_shaders_exit(void);
+
+void GPU_simple_shader_bind(int options);
+void GPU_simple_shader_unbind(void);
+
+void GPU_simple_shader_colors(const float diffuse[3], const float specular[3],
+ int shininess, float alpha);
+
+bool GPU_simple_shader_need_normals(void);
+
+/* Fixed Function Lighting */
+
+typedef struct GPULightData {
+ float position[4];
+ float diffuse[4];
+ float specular[4];
+
+ float constant_attenuation;
+ float linear_attenuation;
+ float quadratic_attenuation;
+
+ float spot_direction[3];
+ float spot_cutoff;
+ float spot_exponent;
+} GPULightData;
+
+void GPU_simple_shader_light_set(int light_num, GPULightData *light);
+void GPU_simple_shader_light_set_viewer(bool local);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript
index 9b8a86eac15..6e3722e403a 100644
--- a/source/blender/gpu/SConscript
+++ b/source/blender/gpu/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('intern/*.c')
@@ -7,7 +33,7 @@ sources += env.Glob('shaders/*.c')
defs = [ 'GLEW_STATIC' ]
incs = '../blenlib ../blenkernel ../makesdna ../makesrna ../include ../blenloader ../nodes ../nodes/intern'
-incs += ' #/extern/glew/include #intern/guardedalloc #intern/smoke/extern ../imbuf .'
+incs += ' #/extern/glew/include #intern/guardedalloc #intern/smoke/extern ../imbuf ../bmesh .'
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
@@ -18,17 +44,19 @@ if env['WITH_BF_SMOKE']:
defs.append('WITH_SMOKE')
if env['WITH_BF_DDS']:
- defs.append('WITH_DDS')
+ defs.append('WITH_DDS')
# generated data files
import os
sources.extend((
- os.path.join(env['DATA_SOURCES'], "gpu_shader_material.glsl.c"),
- os.path.join(env['DATA_SOURCES'], "gpu_shader_vertex.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_vsm_store_frag.glsl.c"),
- os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_vert.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_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_vsm_store_frag.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_vert.glsl.c"),
+ ))
env.BlenderLib ( 'bf_gpu', sources, Split(incs), defines = defs, libtype=['core','player'], priority=[160,110] )
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 6e475ace09d..5bef7a8ae0b 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -45,6 +45,7 @@
#include "BLI_threads.h"
#include "DNA_meshdata_types.h"
+#include "DNA_material_types.h"
#include "BKE_ccg.h"
#include "BKE_DerivedMesh.h"
@@ -56,6 +57,8 @@
#include "GPU_buffers.h"
#include "GPU_draw.h"
+#include "bmesh.h"
+
typedef enum {
GPU_BUFFER_VERTEX_STATE = 1,
GPU_BUFFER_NORMAL_STATE = 2,
@@ -66,8 +69,8 @@ typedef enum {
#define MAX_GPU_ATTRIB_DATA 32
-/* material number is an 16-bit short and the range of short is from -16383 to 16383 (assume material number is non-negative) */
-#define MAX_MATERIALS 16384
+/* material number is an 16-bit signed short and the range (assume material number is non-negative) */
+#define MAX_MATERIALS MAXMAT
/* -1 - undefined, 0 - vertex arrays, 1 - VBOs */
static int useVBOs = -1;
@@ -1268,6 +1271,8 @@ struct GPU_Buffers {
int totgrid;
int has_hidden;
+ int use_bmesh;
+
unsigned int tot_tri, tot_quad;
/* The PBVH ensures that either all faces in the node are
@@ -1386,7 +1391,7 @@ void GPU_update_mesh_buffers(GPU_Buffers *buffers, MVert *mvert,
vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
if (vert_data) {
- /* Vertex data is shared if smooth-shaded, but seperate
+ /* Vertex data is shared if smooth-shaded, but separate
copies are made for flat shading because normals
shouldn't be shared. */
if (buffers->smooth) {
@@ -1861,6 +1866,244 @@ GPU_Buffers *GPU_build_grid_buffers(int *grid_indices, int totgrid,
#undef FILL_QUAD_BUFFER
+/* Output a BMVert into a VertexBufferFormat array
+ *
+ * The vertex is skipped if hidden, otherwise the output goes into
+ * index '*v_index' in the 'vert_data' array and '*v_index' is
+ * incremented.
+ */
+static void gpu_bmesh_vert_to_buffer_copy(BMVert *v, BMesh *bm,
+ VertexBufferFormat *vert_data,
+ int *v_index,
+ const float fno[3],
+ const float *fmask)
+{
+ VertexBufferFormat *vd = &vert_data[*v_index];
+ float *mask;
+
+ if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
+ /* TODO: should use material color */
+ float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
+
+ /* Set coord, normal, and mask */
+ copy_v3_v3(vd->co, v->co);
+ normal_float_to_short_v3(vd->no, fno ? fno : v->no);
+ mask = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_PAINT_MASK);
+ gpu_color_from_mask_copy(fmask ? *fmask : *mask,
+ diffuse_color,
+ vd->color);
+
+
+ /* Assign index for use in the triangle index buffer */
+ BM_elem_index_set(v, (*v_index)); /* set_dirty! */
+
+ (*v_index)++;
+ }
+}
+
+/* Return the total number of vertices that don't have BM_ELEM_HIDDEN set */
+static int gpu_bmesh_vert_visible_count(GHash *bm_unique_verts,
+ GHash *bm_other_verts)
+{
+ GHashIterator gh_iter;
+ int totvert = 0;
+
+ GHASH_ITER (gh_iter, bm_unique_verts) {
+ BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN))
+ totvert++;
+ }
+ GHASH_ITER (gh_iter, bm_other_verts) {
+ BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN))
+ totvert++;
+ }
+
+ return totvert;
+}
+
+/* Return the total number of visible faces */
+static int gpu_bmesh_face_visible_count(GHash *bm_faces)
+{
+ GHashIterator gh_iter;
+ int totface = 0;
+
+ GHASH_ITER (gh_iter, bm_faces) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+
+ if (!paint_is_bmesh_face_hidden(f))
+ totface++;
+ }
+
+ return totface;
+}
+
+/* Creates a vertex buffer (coordinate, normal, color) and, if smooth
+ shading, an element index buffer. */
+void GPU_update_bmesh_buffers(GPU_Buffers *buffers,
+ BMesh *bm,
+ GHash *bm_faces,
+ GHash *bm_unique_verts,
+ GHash *bm_other_verts)
+{
+ VertexBufferFormat *vert_data;
+ void *tri_data;
+ int tottri, totvert, maxvert = 0;
+
+ if (!buffers->vert_buf || (buffers->smooth && !buffers->index_buf))
+ return;
+
+ /* Count visible triangles */
+ tottri = gpu_bmesh_face_visible_count(bm_faces);
+
+ if (buffers->smooth) {
+ /* Count visible vertices */
+ totvert = gpu_bmesh_vert_visible_count(bm_unique_verts, bm_other_verts);
+ }
+ else
+ totvert = tottri * 3;
+
+ /* Initialize vertex buffer */
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
+ glBufferDataARB(GL_ARRAY_BUFFER_ARB,
+ sizeof(VertexBufferFormat) * totvert,
+ NULL, GL_STATIC_DRAW_ARB);
+
+ /* Fill vertex buffer */
+ vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ if (vert_data) {
+ GHashIterator gh_iter;
+ int v_index = 0;
+
+ if (buffers->smooth) {
+ /* Vertices get an index assigned for use in the triangle
+ index buffer */
+ bm->elem_index_dirty |= BM_VERT;
+
+ GHASH_ITER (gh_iter, bm_unique_verts) {
+ gpu_bmesh_vert_to_buffer_copy(BLI_ghashIterator_getKey(&gh_iter),
+ bm, vert_data, &v_index, NULL, NULL);
+ }
+
+ GHASH_ITER (gh_iter, bm_other_verts) {
+ gpu_bmesh_vert_to_buffer_copy(BLI_ghashIterator_getKey(&gh_iter),
+ bm, vert_data, &v_index, NULL, NULL);
+ }
+
+ maxvert = v_index;
+ }
+ else {
+ GHASH_ITER (gh_iter, bm_faces) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+
+ BLI_assert(f->len == 3);
+
+ if (!paint_is_bmesh_face_hidden(f)) {
+ BMVert *v[3];
+ float fmask = 0;
+ int i;
+
+ // BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void**)v, 3);
+ BM_face_as_array_vert_tri(f, v);
+
+ /* Average mask value */
+ for (i = 0; i < 3; i++) {
+ fmask += *((float*)CustomData_bmesh_get(&bm->vdata,
+ v[i]->head.data,
+ CD_PAINT_MASK));
+ }
+ fmask /= 3.0f;
+
+ for (i = 0; i < 3; i++) {
+ gpu_bmesh_vert_to_buffer_copy(v[i], bm, vert_data,
+ &v_index, f->no, &fmask);
+ }
+ }
+ }
+
+ buffers->tot_tri = tottri;
+ }
+
+ glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
+ }
+ else {
+ /* Memory map failed */
+ glDeleteBuffersARB(1, &buffers->vert_buf);
+ buffers->vert_buf = 0;
+ return;
+ }
+
+ if (buffers->smooth) {
+ 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);
+
+ /* Fill triangle index buffer */
+ tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ if (tri_data) {
+ GHashIterator gh_iter;
+
+ GHASH_ITER (gh_iter, bm_faces) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+
+ if (!paint_is_bmesh_face_hidden(f)) {
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BMVert *v = l_iter->v;
+ if (use_short) {
+ unsigned short *elem = tri_data;
+ (*elem) = BM_elem_index_get(v);
+ elem++;
+ tri_data = elem;
+ }
+ else {
+ unsigned int *elem = tri_data;
+ (*elem) = BM_elem_index_get(v);
+ elem++;
+ tri_data = elem;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+
+ glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
+
+ buffers->tot_tri = tottri;
+ buffers->index_type = (use_short ?
+ GL_UNSIGNED_SHORT :
+ GL_UNSIGNED_INT);
+ }
+ else {
+ /* Memory map failed */
+ glDeleteBuffersARB(1, &buffers->index_buf);
+ buffers->index_buf = 0;
+ }
+ }
+}
+
+GPU_Buffers *GPU_build_bmesh_buffers(int smooth_shading)
+{
+ GPU_Buffers *buffers;
+
+ buffers = MEM_callocN(sizeof(GPU_Buffers), "GPU_Buffers");
+ if (smooth_shading)
+ glGenBuffersARB(1, &buffers->index_buf);
+ glGenBuffersARB(1, &buffers->vert_buf);
+ buffers->use_bmesh = TRUE;
+ buffers->smooth = smooth_shading;
+
+ return buffers;
+}
+
static void gpu_draw_buffers_legacy_mesh(GPU_Buffers *buffers)
{
const MVert *mvert = buffers->mvert;
@@ -2059,7 +2302,8 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers)
}
}
-void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial)
+void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial,
+ int wireframe)
{
if (buffers->totface) {
const MFace *f = &buffers->mface[buffers->face_indices[0]];
@@ -2076,14 +2320,19 @@ void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial)
if (buffers->vert_buf) {
glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_NORMAL_ARRAY);
- gpu_colors_enable(VBO_ENABLED);
+ if (!wireframe) {
+ glEnableClientState(GL_NORMAL_ARRAY);
+ gpu_colors_enable(VBO_ENABLED);
+ }
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
if (buffers->index_buf)
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
+ if (wireframe)
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
if (buffers->tot_quad) {
char *offset = 0;
int i, last = buffers->has_hidden ? 1 : buffers->totgrid;
@@ -2116,13 +2365,18 @@ void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial)
glDrawArrays(GL_TRIANGLES, 0, totelem);
}
+ 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);
glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
- gpu_colors_disable(VBO_ENABLED);
+ if (!wireframe) {
+ glDisableClientState(GL_NORMAL_ARRAY);
+ gpu_colors_disable(VBO_ENABLED);
+ }
}
/* fallbacks if we are out of memory or VBO is disabled */
else if (buffers->totface) {
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 4432627ee7e..840b16a4567 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -68,6 +68,9 @@ static char *glsl_material_library = NULL;
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. */
@@ -194,7 +197,7 @@ static char *gpu_generate_function_prototyps(GHash *hash)
* generated code, to avoid have to add the actual code & recompile all */
ghi = BLI_ghashIterator_new(hash);
- for (; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) {
+ for (; BLI_ghashIterator_notDone(ghi); BLI_ghashIterator_step(ghi)) {
name = BLI_ghashIterator_getValue(ghi);
function = BLI_ghashIterator_getValue(ghi);
@@ -234,8 +237,6 @@ 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);
- /*FUNCTION_PROTOTYPES = gpu_generate_function_prototyps(FUNCTION_HASH);
- FUNCTION_LIB = GPU_shader_create_lib(datatoc_gpu_shader_material_glsl);*/
}
return (GPUFunction*)BLI_ghash_lookup(FUNCTION_HASH, (void *)name);
@@ -339,7 +340,7 @@ static int codegen_input_has_texture(GPUInput *input)
{
if (input->link)
return 0;
- else if (input->ima)
+ else if (input->ima || input->prv)
return 1;
else
return input->tex != NULL;
@@ -411,6 +412,17 @@ static void codegen_set_unique_ids(ListBase *nodes)
else
input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, 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));
+ }
else {
if (!BLI_ghash_haskey(bindhash, input->tex)) {
/* input is user created texture, check tex pointer */
@@ -718,7 +730,7 @@ static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
continue;
}
- if (input->ima || input->tex)
+ if (input->ima || input->tex || input->prv)
BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
else
BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
@@ -726,7 +738,7 @@ static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
/* pass non-dynamic uniforms to opengl */
extract = 0;
- if (input->ima || input->tex) {
+ if (input->ima || input->tex || input->prv) {
if (input->bindtex)
extract = 1;
}
@@ -744,7 +756,7 @@ static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
}
}
- GPU_shader_unbind(shader);
+ GPU_shader_unbind();
}
void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
@@ -762,11 +774,14 @@ void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
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)
+ input->tex = GPU_texture_from_preview(input->prv, mipmap);
if (input->tex && input->bindtex) {
GPU_texture_bind(input->tex, input->texid);
GPU_shader_uniform_texture(shader, input->shaderloc, input->tex);
}
+
}
}
@@ -781,7 +796,7 @@ void GPU_pass_update_uniforms(GPUPass *pass)
/* pass dynamic inputs to opengl, others were removed */
for (input=inputs->first; input; input=input->next)
- if (!(input->ima || input->tex))
+ if (!(input->ima || input->tex || input->prv))
GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
input->dynamicvec);
}
@@ -799,11 +814,11 @@ void GPU_pass_unbind(GPUPass *pass)
if (input->tex && input->bindtex)
GPU_texture_unbind(input->tex);
- if (input->ima)
+ if (input->ima || input->prv)
input->tex = NULL;
}
- GPU_shader_unbind(shader);
+ GPU_shader_unbind();
}
/* Node Link Functions */
@@ -915,9 +930,13 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
input->type = GPU_VEC4;
input->source = GPU_SOURCE_TEX;
- input->ima = link->ptr1;
- input->iuser = link->ptr2;
- input->image_isdata = link->image_isdata;
+ if (link->image == LINK_IMAGE_PREVIEW)
+ input->prv = link->ptr1;
+ else {
+ input->ima = link->ptr1;
+ input->iuser = link->ptr2;
+ input->image_isdata = link->image_isdata;
+ }
input->textarget = GL_TEXTURE_2D;
input->textype = GPU_TEX2D;
MEM_freeN(link);
@@ -1117,7 +1136,7 @@ GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, int isdata)
{
GPUNodeLink *link = GPU_node_link_create(0);
- link->image= 1;
+ link->image= LINK_IMAGE_BLENDER;
link->ptr1= ima;
link->ptr2= iuser;
link->image_isdata= isdata;
@@ -1125,6 +1144,17 @@ GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, int isdata)
return link;
}
+GPUNodeLink *GPU_image_preview(PreviewImage *prv)
+{
+ GPUNodeLink *link = GPU_node_link_create(0);
+
+ link->image= LINK_IMAGE_PREVIEW;
+ link->ptr1= prv;
+
+ return link;
+}
+
+
GPUNodeLink *GPU_texture(int size, float *pixels)
{
GPUNodeLink *link = GPU_node_link_create(0);
@@ -1336,7 +1366,7 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri
/* generate code and compile with opengl */
fragmentcode = code_generate_fragment(nodes, outlink->output, name);
vertexcode = code_generate_vertex(nodes);
- shader = GPU_shader_create(vertexcode, fragmentcode, glsl_material_library); /*FUNCTION_LIB);*/
+ shader = GPU_shader_create(vertexcode, fragmentcode, glsl_material_library, NULL);
/* failed? */
if (!shader) {
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index f61f34908c5..2e4cfe2e37c 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -43,6 +43,7 @@ struct GPUOutput;
struct GPUNode;
struct GPUVertexAttribs;
struct GPUFrameBuffer;
+struct PreviewImage;
#define MAX_FUNCTION_NAME 64
#define MAX_PARAMETER 32
@@ -138,6 +139,7 @@ typedef struct GPUInput {
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) */
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index f4810c540c3..33402426b62 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -52,6 +52,9 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "BLI_threads.h"
+#include "BLI_blenlib.h"
+
#include "BKE_bmfont.h"
#include "BKE_global.h"
#include "BKE_image.h"
@@ -62,9 +65,6 @@
#include "BKE_scene.h"
#include "BKE_DerivedMesh.h"
-#include "BLI_threads.h"
-#include "BLI_blenlib.h"
-
#include "GPU_buffers.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
@@ -92,7 +92,7 @@ void GPU_render_text(MTFace *tface, int mode,
float *v1, float *v2, float *v3, float *v4, int glattrib)
{
if ((mode & GEMAT_TEXT) && (textlen>0) && tface->tpage) {
- Image* ima = (Image*)tface->tpage;
+ Image* ima = (Image *)tface->tpage;
int index, character;
float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance;
float advance_tab;
@@ -101,9 +101,9 @@ void GPU_render_text(MTFace *tface, int mode,
float line_start= 0.0f, line_height;
if (v4)
- line_height= MAX4(v1[1], v2[1], v3[1], v4[2]) - MIN4(v1[1], v2[1], v3[1], v4[2]);
+ line_height = max_ffff(v1[1], v2[1], v3[1], v4[2]) - min_ffff(v1[1], v2[1], v3[1], v4[2]);
else
- line_height= MAX3(v1[1], v2[1], v3[1]) - MIN3(v1[1], v2[1], v3[1]);
+ line_height = max_fff(v1[1], v2[1], v3[1]) - min_fff(v1[1], v2[1], v3[1]);
line_height *= 1.2f; /* could be an option? */
/* end multiline */
@@ -189,30 +189,21 @@ void GPU_render_text(MTFace *tface, int mode,
/* Checking powers of two for images since opengl 1.x requires it */
-static int is_pow2_limit(int num)
+static bool is_power_of_2_resolution(int w, int h)
{
- /* take texture clamping into account */
-
- /* XXX: texturepaint not global! */
-#if 0
- if (G.f & G_TEXTUREPAINT)
- return 1;*/
-#endif
+ return is_power_of_2_i(w) && is_power_of_2_i(h);
+}
- if (U.glreslimit != 0 && num > U.glreslimit)
- return 0;
+static bool is_over_resolution_limit(int w, int h)
+{
+ if (U.glreslimit != 0)
+ return (w > U.glreslimit || h > U.glreslimit);
- return is_power_of_2_i(num);
+ return false;
}
-static int smaller_pow2_limit(int num)
+static int smaller_power_of_2_limit(int num)
{
- /* XXX: texturepaint not global! */
-#if 0
- if (G.f & G_TEXTUREPAINT)
- return 1;*/
-#endif
-
/* take texture clamping into account */
if (U.glreslimit != 0 && num > U.glreslimit)
return U.glreslimit;
@@ -252,6 +243,25 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap)
}
}
+static void gpu_generate_mipmap(GLenum target)
+{
+ int is_ati = GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY);
+ int target_enabled = 0;
+
+ /* work around bug in ATI driver, need to have GL_TEXTURE_2D enabled
+ * http://www.opengl.org/wiki/Common_Mistakes#Automatic_mipmap_generation */
+ if (is_ati) {
+ target_enabled = glIsEnabled(target);
+ if (!target_enabled)
+ glEnable(target);
+ }
+
+ glGenerateMipmapEXT(target);
+
+ if (is_ati && !target_enabled)
+ glDisable(target);
+}
+
void GPU_set_mipmap(int mipmap)
{
if (GTS.domipmap != (mipmap != 0)) {
@@ -376,7 +386,12 @@ static void gpu_set_alpha_blend(GPUBlendMode alphablend)
}
else if (ELEM(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ALPHA_SORT)) {
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ /* for OpenGL render we use the alpha channel, this makes alpha blend correct */
+ 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);
/* if U.glalphaclip == 1.0, some cards go bonkers...
* turn off alpha test in this case */
@@ -424,7 +439,7 @@ static void gpu_verify_reflection(Image *ima)
}
}
-int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int mipmap, int is_data)
+int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int mipmap, bool is_data)
{
ImBuf *ibuf = NULL;
unsigned int *bind = NULL;
@@ -537,8 +552,9 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
if (do_color_management) {
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, 0,
+ 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;
@@ -562,8 +578,9 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
if (do_color_management) {
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, 0,
+ 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);
}
@@ -643,7 +660,8 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
return *bind;
}
-void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float * frect, int rectw, int recth, int mipmap, int use_high_bit_depth, Image *ima)
+/* Image *ima can be NULL */
+void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float *frect, int rectw, int recth, int mipmap, int use_high_bit_depth, Image *ima)
{
unsigned int *scalerect = NULL;
float *fscalerect = NULL;
@@ -654,9 +672,10 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float * frect, int
/* scale if not a power of two. this is not strictly necessary for newer
* GPUs (OpenGL version >= 2.0) since they support non-power-of-two-textures
* Then don't bother scaling for hardware that supports NPOT textures! */
- if (!GPU_non_power_of_two_support() && (!is_pow2_limit(rectw) || !is_pow2_limit(recth))) {
- rectw= smaller_pow2_limit(rectw);
- recth= smaller_pow2_limit(recth);
+ 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);
if (use_high_bit_depth) {
fscalerect= MEM_mallocN(rectw*recth*sizeof(*fscalerect)*4, "fscalerect");
@@ -691,7 +710,7 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float * frect, int
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix);
- glGenerateMipmapEXT(GL_TEXTURE_2D);
+ gpu_generate_mipmap(GL_TEXTURE_2D);
}
else {
if (use_high_bit_depth)
@@ -702,7 +721,8 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float * frect, int
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));
- ima->tpageflag |= IMA_MIPMAP_COMPLETE;
+ if (ima)
+ ima->tpageflag |= IMA_MIPMAP_COMPLETE;
}
if (GLEW_EXT_texture_filter_anisotropic)
@@ -744,16 +764,19 @@ int GPU_upload_dxt_texture(ImBuf *ibuf)
return FALSE;
}
- if (!is_power_of_2_i(width) || !is_power_of_2_i(height)) {
+ if (!is_power_of_2_resolution(width, height)) {
printf("Unable to load non-power-of-two DXT image resolution, falling back to uncompressed\n");
return FALSE;
}
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ 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));
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ if (GLEW_EXT_texture_filter_anisotropic)
+ 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) {
if (width == 0)
@@ -791,7 +814,7 @@ void GPU_create_gl_tex_compressed(unsigned int *bind, unsigned int *pix, int x,
glBindTexture(GL_TEXTURE_2D, *bind);
if (GPU_upload_dxt_texture(ibuf) == 0) {
- glDeleteTextures(1, (GLuint*)bind);
+ glDeleteTextures(1, (GLuint *)bind);
GPU_create_gl_tex(bind, pix, NULL, x, y, mipmap, 0, ima);
}
#endif
@@ -904,8 +927,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
if (ima->repbind || (GPU_get_mipmap() && !GTS.gpu_mipmap) || !ima->bindcode || !ibuf ||
- (!is_power_of_2_i(ibuf->x) || !is_power_of_2_i(ibuf->y)) ||
- (w == 0) || (h == 0))
+ (w == 0) || (h == 0))
{
/* these cases require full reload still */
GPU_free_image(ima);
@@ -934,7 +956,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
/* we have already accounted for the case where GTS.gpu_mipmap is false
* so we will be using GPU mipmap generation here */
if (GPU_get_mipmap()) {
- glGenerateMipmapEXT(GL_TEXTURE_2D);
+ gpu_generate_mipmap(GL_TEXTURE_2D);
}
else {
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
@@ -959,7 +981,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
/* see comment above as to why we are using gpu mipmap generation here */
if (GPU_get_mipmap()) {
- glGenerateMipmapEXT(GL_TEXTURE_2D);
+ gpu_generate_mipmap(GL_TEXTURE_2D);
}
else {
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
@@ -1242,7 +1264,7 @@ static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat,
static Material *gpu_active_node_material(Material *ma)
{
if (ma && ma->use_nodes && ma->nodetree) {
- bNode *node= nodeGetActiveID(ma->nodetree, ID_MA);
+ bNode *node = nodeGetActiveID(ma->nodetree, ID_MA);
if (node)
return (Material *)node->id;
@@ -1253,16 +1275,15 @@ static Material *gpu_active_node_material(Material *ma)
return ma;
}
-void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, Object *ob, int glsl, int *do_alpha_after)
+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;
int a;
-
int gamma = BKE_scene_check_color_management_enabled(scene);
-
int new_shading_nodes = BKE_scene_use_new_shading_nodes(scene);
+ int use_matcap = (v3d->flag2 & V3D_SHOW_SOLID_MATCAP); /* assumes v3d->defmaterial->preview is set */
/* initialize state */
memset(&GMS, 0, sizeof(GMS));
@@ -1274,7 +1295,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
GMS.gob = ob;
GMS.gscene = scene;
- GMS.totmat= ob->totcol+1; /* materials start from 1, default material is 0 */
+ 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.gviewmat= rv3d->viewmat;
GMS.gviewinv= rv3d->viewinv;
@@ -1287,7 +1308,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
GMS.use_alpha_pass = (do_alpha_after != NULL);
GMS.is_alpha_pass = (v3d->transp != FALSE);
if (GMS.use_alpha_pass)
- *do_alpha_after = FALSE;
+ *do_alpha_after = false;
if (GMS.totmat > FIXEDMAT) {
GMS.matbuf= MEM_callocN(sizeof(GPUMaterialFixed)*GMS.totmat, "GMS.matbuf");
@@ -1300,59 +1321,72 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
GMS.alphablend= GMS.alphablend_fixed;
}
- /* no materials assigned? */
- if (ob->totcol==0) {
- gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes);
-
+ /* 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);
+
/* 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.alphablend[0]= GPU_BLEND_SOLID;
}
+ else {
- /* setup materials */
- 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;
-
- /* create glsl material if requested */
- gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL;
-
- if (gpumat) {
- /* do glsl only if creating it succeed, else fallback */
- 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);
+ /* no materials assigned? */
+ if (ob->totcol==0) {
+ gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes);
- if (GMS.use_alpha_pass) {
- GMS.matbuf[a].diff[3]= ma->alpha;
- alphablend = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA;
+ /* 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.alphablend[0]= GPU_BLEND_SOLID;
+ }
+
+ /* setup materials */
+ 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;
+
+ /* create glsl material if requested */
+ gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL;
+
+ if (gpumat) {
+ /* do glsl only if creating it succeed, else fallback */
+ GMS.gmatbuf[a]= ma;
+ alphablend = GPU_material_alpha_blend(gpumat, ob->col);
}
else {
- GMS.matbuf[a].diff[3]= 1.0f;
- alphablend = GPU_BLEND_SOLID;
+ /* fixed function opengl materials */
+ gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes);
+
+ if (GMS.use_alpha_pass) {
+ 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;
+ alphablend = GPU_BLEND_SOLID;
+ }
}
- }
- /* setting 'do_alpha_after = TRUE' indicates this object needs to be
- * drawn in a second alpha pass for improved blending */
- if (do_alpha_after && !GMS.is_alpha_pass)
- if (ELEM3(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT))
- *do_alpha_after = TRUE;
+ /* setting 'do_alpha_after = TRUE' indicates this object needs to be
+ * drawn in a second alpha pass for improved blending */
+ if (do_alpha_after && !GMS.is_alpha_pass)
+ if (ELEM3(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT))
+ *do_alpha_after = true;
- GMS.alphablend[a]= alphablend;
+ GMS.alphablend[a]= alphablend;
+ }
}
-
+
/* let's start with a clean state */
GPU_disable_material();
}
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 7a0ac29c9ab..c7a421a49fc 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -36,15 +36,15 @@
#include "MEM_guardedalloc.h"
-#include "BKE_global.h"
-
-
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_math_base.h"
+#include "BKE_global.h"
+
#include "GPU_draw.h"
#include "GPU_extensions.h"
+#include "GPU_simple_shader.h"
#include "gpu_codegen.h"
#include <stdlib.h>
@@ -134,8 +134,8 @@ void GPU_extensions_init(void)
glGetIntegerv(GL_BLUE_BITS, &b);
GG.colordepth = r+g+b; /* assumes same depth for RGB */
- vendor = (const char*)glGetString(GL_VENDOR);
- renderer = (const char*)glGetString(GL_RENDERER);
+ vendor = (const char *)glGetString(GL_VENDOR);
+ renderer = (const char *)glGetString(GL_RENDERER);
if (strstr(vendor, "ATI")) {
GG.device = GPU_DEVICE_ATI;
@@ -206,12 +206,15 @@ void GPU_extensions_init(void)
#else
GG.os = GPU_OS_UNIX;
#endif
+
+ GPU_simple_shaders_init();
}
void GPU_extensions_exit(void)
{
gpu_extensions_init = 0;
GPU_codegen_exit();
+ GPU_simple_shaders_exit();
}
int GPU_glsl_support(void)
@@ -539,6 +542,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int isdata, d
glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode);
GPU_update_image_time(ima, time);
+ /* this binds a texture, so that's why to restore it with lastbindcode */
bindcode = GPU_verify_image(ima, iuser, 0, 0, mipmap, isdata);
if (ima->gputexture) {
@@ -579,6 +583,59 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int isdata, d
return tex;
}
+GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
+{
+ GPUTexture *tex = prv->gputexture[0];
+ GLint w, h, lastbindcode;
+ GLuint bindcode = 0;
+
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode);
+
+ if (tex)
+ bindcode = tex->bindcode;
+
+ /* this binds a texture, so that's why to restore it */
+ if (bindcode == 0) {
+ GPU_create_gl_tex(&bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], mipmap, 0, NULL);
+ }
+ if (tex) {
+ tex->bindcode = bindcode;
+ glBindTexture(GL_TEXTURE_2D, lastbindcode);
+ return tex;
+ }
+
+ /* error binding anything */
+ if (!bindcode) {
+ glBindTexture(GL_TEXTURE_2D, lastbindcode);
+ return NULL;
+ }
+
+ tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
+ tex->bindcode = bindcode;
+ tex->number = -1;
+ tex->refcount = 1;
+ tex->target = GL_TEXTURE_2D;
+
+ prv->gputexture[0]= tex;
+
+ if (!glIsTexture(tex->bindcode)) {
+ GPU_print_error("Blender Texture");
+ }
+ 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;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, lastbindcode);
+
+ return tex;
+
+}
+
GPUTexture *GPU_texture_create_1D(int w, float *fpixels, char err_out[256])
{
GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, err_out);
@@ -848,10 +905,8 @@ void GPU_framebuffer_texture_bind(GPUFrameBuffer *UNUSED(fb), GPUTexture *tex, i
glMatrixMode(GL_PROJECTION);
glPushMatrix();
- glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
- glLoadIdentity();
}
void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
@@ -916,7 +971,7 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 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, (float *)scaleh);
GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex);
glViewport(0, 0, GPU_texture_opengl_width(blurtex), GPU_texture_opengl_height(blurtex));
@@ -942,7 +997,7 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
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);
+ GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, (float *)scalev);
GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
GPU_texture_bind(blurtex, 0);
@@ -953,7 +1008,7 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
glTexCoord2d(0, 1); glVertex2f(1, -1);
glEnd();
- GPU_shader_unbind(blur_shader);
+ GPU_shader_unbind();
}
/* GPUOffScreen */
@@ -1039,6 +1094,16 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
glReadPixels(0, 0, ofs->w, ofs->h, GL_RGBA, type, pixels);
}
+int GPU_offscreen_width(GPUOffScreen *ofs)
+{
+ return ofs->w;
+}
+
+int GPU_offscreen_height(GPUOffScreen *ofs)
+{
+ return ofs->h;
+}
+
/* GPUShader */
struct GPUShader {
@@ -1071,13 +1136,24 @@ static void shader_print_errors(const char *task, char *log, const char *code)
fprintf(stderr, "%s\n", log);
}
-GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, /*GPUShader *lib,*/ const char *libcode)
+static const char *gpu_shader_standard_defines(void)
+{
+ /* some useful defines to detect GPU type */
+ if(GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY))
+ return "#define GPU_ATI\n";
+ else if(GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY))
+ return "#define GPU_NVIDIA\n";
+ else if(GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY))
+ return "#define GPU_INTEL\n";
+
+ return "";
+}
+
+GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *libcode, const char *defines)
{
GLint status;
GLcharARB log[5000];
- const char *fragsource[2];
GLsizei length = 0;
- GLint count;
GPUShader *shader;
if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader)
@@ -1101,8 +1177,16 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, /*GPU
}
if (vertexcode) {
+ const char *source[3];
+ int num_source = 0;
+
+ source[num_source++] = gpu_shader_standard_defines();
+
+ if (defines) source[num_source++] = defines;
+ if (vertexcode) source[num_source++] = vertexcode;
+
glAttachObjectARB(shader->object, shader->vertex);
- glShaderSourceARB(shader->vertex, 1, (const char**)&vertexcode, NULL);
+ glShaderSourceARB(shader->vertex, num_source, source, NULL);
glCompileShaderARB(shader->vertex);
glGetObjectParameterivARB(shader->vertex, GL_OBJECT_COMPILE_STATUS_ARB, &status);
@@ -1117,12 +1201,17 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, /*GPU
}
if (fragcode) {
- count = 0;
- if (libcode) fragsource[count++] = libcode;
- if (fragcode) fragsource[count++] = fragcode;
+ const char *source[4];
+ int num_source = 0;
+
+ source[num_source++] = gpu_shader_standard_defines();
+
+ if (defines) source[num_source++] = defines;
+ if (libcode) source[num_source++] = libcode;
+ if (fragcode) source[num_source++] = fragcode;
glAttachObjectARB(shader->object, shader->fragment);
- glShaderSourceARB(shader->fragment, count, fragsource, NULL);
+ glShaderSourceARB(shader->fragment, num_source, source, NULL);
glCompileShaderARB(shader->fragment);
glGetObjectParameterivARB(shader->fragment, GL_OBJECT_COMPILE_STATUS_ARB, &status);
@@ -1201,7 +1290,7 @@ void GPU_shader_bind(GPUShader *shader)
GPU_print_error("Post Shader Bind");
}
-void GPU_shader_unbind(GPUShader *UNUSED(shader))
+void GPU_shader_unbind(void)
{
GPU_print_error("Pre Shader Unbind");
glUseProgramObjectARB(0);
@@ -1243,6 +1332,16 @@ void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int leng
GPU_print_error("Post Uniform Vector");
}
+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");
+}
+
void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
{
GLenum arbnumber;
@@ -1291,12 +1390,12 @@ 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);
+ GG.shaders.vsm_store = GPU_shader_create(datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, NULL, NULL);
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);
+ 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);
retval = GG.shaders.sep_gaussian_blur;
break;
}
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 09776fd1714..999e3b5c20e 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -278,6 +278,7 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim
}
GPU_pass_bind(material->pass, time, mipmap);
+ GPU_pass_update_uniforms(material->pass);
material->bound = 1;
}
}
@@ -338,8 +339,6 @@ void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float
mult_m4_m4m4(lamp->dynpersmat, lamp->persmat, viewinv);
}
}
-
- GPU_pass_update_uniforms(material->pass);
}
}
@@ -1035,8 +1034,7 @@ static void do_material_tex(GPUShadeInput *shi)
GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser, FALSE), &tin, &trgb);
rgbnor= TEX_RGB;
- if (tex->imaflag & TEX_USEALPHA)
- talpha= 1;
+ talpha = ((tex->imaflag & TEX_USEALPHA) && tex->ima && (tex->ima->flag & IMA_IGNORE_ALPHA) == 0);
}
else {
continue;
@@ -1507,6 +1505,52 @@ static GPUNodeLink *gpu_material_diffuse_bsdf(GPUMaterial *mat, Material *ma)
return outlink;
}
+static GPUNodeLink *gpu_material_preview_matcap(GPUMaterial *mat, Material *ma)
+{
+ GPUNodeLink *outlink;
+
+ GPU_link(mat, "material_preview_matcap", GPU_uniform(&ma->r), GPU_image_preview(ma->preview), GPU_builtin(GPU_VIEW_NORMAL), &outlink);
+
+ return outlink;
+}
+
+/* new solid draw mode with glsl matcaps */
+GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma)
+{
+ GPUMaterial *mat;
+ GPUNodeLink *outlink;
+ LinkData *link;
+
+ for (link=ma->gpumaterial.first; link; link=link->next)
+ if (((GPUMaterial*)link->data)->scene == scene)
+ return link->data;
+
+ /* allocate material */
+ mat = GPU_material_construct_begin(ma);
+ mat->scene = scene;
+
+ if (ma->preview && ma->preview->rect[0]) {
+ outlink = gpu_material_preview_matcap(mat, ma);
+ }
+ else {
+ outlink = gpu_material_diffuse_bsdf(mat, ma);
+ }
+
+ GPU_material_output_link(mat, outlink);
+
+ GPU_material_construct_end(mat);
+
+ /* 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(&ma->gpumaterial, link);
+
+ return mat;
+}
+
GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma)
{
GPUMaterial *mat;
@@ -1526,7 +1570,7 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma)
ntreeGPUMaterialNodes(ma->nodetree, mat);
}
else {
- if(BKE_scene_use_new_shading_nodes(scene)) {
+ if (BKE_scene_use_new_shading_nodes(scene)) {
/* create simple diffuse material instead of nodes */
outlink = gpu_material_diffuse_bsdf(mat, ma);
}
@@ -1874,7 +1918,7 @@ void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsiz
void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp)
{
if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
- GPU_shader_unbind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE));
+ GPU_shader_unbind();
GPU_framebuffer_blur(lamp->fb, lamp->tex, lamp->blurfb, lamp->blurtex);
}
@@ -1883,6 +1927,11 @@ void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp)
glEnable(GL_SCISSOR_TEST);
}
+int GPU_lamp_shadow_buffer_type(GPULamp *lamp)
+{
+ return lamp->la->shadowmap_type;
+}
+
int GPU_lamp_shadow_layer(GPULamp *lamp)
{
if (lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER|LA_LAYER_SHADOW)))
diff --git a/source/blender/gpu/intern/gpu_simple_shader.c b/source/blender/gpu/intern/gpu_simple_shader.c
new file mode 100644
index 00000000000..88f768d6cf8
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_simple_shader.c
@@ -0,0 +1,283 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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): Brecht Van Lommel.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_simple_shader.c
+ * \ingroup gpu
+ */
+
+/* GLSL shaders to replace fixed function OpenGL materials and lighting. These
+ * are deprecated in newer OpenGL versions and missing in OpenGL ES 2.0. Also,
+ * two sided lighting is no longer natively supported on NVidia cards which
+ * results in slow software fallback.
+ *
+ * Todo:
+ * - Replace glLight and glMaterial functions entirely with GLSL uniforms, to
+ * make OpenGL ES 2.0 work.
+ * - Replace glTexCoord and glColor with generic attributes.
+ * - Optimize for case where fewer than 3 or 8 lights are used.
+ * - Optimize for case where specular is not used.
+ * - Optimize for case where no texture matrix is used.
+ */
+
+#include "GL/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"
+
+/* State */
+
+// #define NUM_OPENGL_LIGHTS 8
+
+static struct {
+ GPUShader *cached_shaders[GPU_SHADER_OPTION_COMBINATIONS];
+ bool failed_shaders[GPU_SHADER_OPTION_COMBINATIONS];
+
+ bool need_normals;
+
+ int lights_enabled;
+ int lights_directional;
+} GPU_MATERIAL_STATE;
+
+/* Init / exit */
+
+void GPU_simple_shaders_init(void)
+{
+ memset(&GPU_MATERIAL_STATE, 0, sizeof(GPU_MATERIAL_STATE));
+}
+
+void GPU_simple_shaders_exit(void)
+{
+ int i;
+
+ for (i = 0; i < GPU_SHADER_OPTION_COMBINATIONS; i++)
+ if (GPU_MATERIAL_STATE.cached_shaders[i])
+ GPU_shader_free(GPU_MATERIAL_STATE.cached_shaders[i]);
+}
+
+/* Shader lookup / create */
+
+static bool solid_compatible_lighting(void)
+{
+ int enabled = GPU_MATERIAL_STATE.lights_enabled;
+ int directional = GPU_MATERIAL_STATE.lights_directional;
+
+ /* more than 3 lights? */
+ if (enabled >= (1 << 3))
+ return false;
+
+ /* all directional? */
+ return ((directional & enabled) == enabled);
+}
+
+#if 0
+static int detect_options()
+{
+ GLint two_sided;
+ int options = 0;
+
+ if (glIsEnabled(GL_TEXTURE_2D))
+ options |= GPU_SHADER_TEXTURE_2D;
+ if (glIsEnabled(GL_COLOR_MATERIAL))
+ options |= GPU_SHADER_OVERRIDE_DIFFUSE;
+
+ if (glIsEnabled(GL_LIGHTING))
+ options |= GPU_SHADER_LIGHTING;
+
+ glGetIntegerv(GL_LIGHT_MODEL_TWO_SIDE, &two_sided);
+ if (two_sided == GL_TRUE)
+ options |= GPU_SHADER_TWO_SIDED;
+
+ return options;
+}
+#endif
+
+static GPUShader *gpu_simple_shader(int options)
+{
+ /* glsl code */
+ extern char datatoc_gpu_shader_simple_vert_glsl[];
+ extern char datatoc_gpu_shader_simple_frag_glsl[];
+ GPUShader *shader;
+
+ /* detect if we can do faster lighting for solid draw mode */
+ if (options & GPU_SHADER_LIGHTING)
+ if (solid_compatible_lighting())
+ options |= GPU_SHADER_SOLID_LIGHTING;
+
+ /* cached shaders */
+ shader = GPU_MATERIAL_STATE.cached_shaders[options];
+
+ if (!shader && !GPU_MATERIAL_STATE.failed_shaders[options]) {
+ /* create shader if it doesn't exist yet */
+ char defines[64*GPU_SHADER_OPTIONS_NUM] = "";
+
+ if (options & GPU_SHADER_OVERRIDE_DIFFUSE)
+ strcat(defines, "#define USE_COLOR\n");
+ if (options & GPU_SHADER_TWO_SIDED)
+ strcat(defines, "#define USE_TWO_SIDED\n");
+ if (options & GPU_SHADER_TEXTURE_2D)
+ strcat(defines, "#define USE_TEXTURE\n");
+
+ if (options & GPU_SHADER_SOLID_LIGHTING)
+ strcat(defines, "#define USE_SOLID_LIGHTING\n");
+ else if (options & GPU_SHADER_LIGHTING)
+ strcat(defines, "#define USE_SCENE_LIGHTING\n");
+
+ shader = GPU_shader_create(
+ datatoc_gpu_shader_simple_vert_glsl,
+ datatoc_gpu_shader_simple_frag_glsl,
+ NULL, defines);
+
+ if (shader) {
+ /* set texture map to first texture unit */
+ if (options & GPU_SHADER_TEXTURE_2D)
+ glUniform1i(GPU_shader_get_uniform(shader, "texture_map"), 0);
+
+ GPU_MATERIAL_STATE.cached_shaders[options] = shader;
+ }
+ else
+ GPU_MATERIAL_STATE.failed_shaders[options] = true;
+ }
+
+ return shader;
+}
+
+/* Bind / unbind */
+
+void GPU_simple_shader_bind(int options)
+{
+ if (GPU_glsl_support()) {
+ GPUShader *shader = gpu_simple_shader(options);
+
+ if (shader)
+ GPU_shader_bind(shader);
+ }
+ else {
+ // XXX where does this fit, depends on ortho/persp?
+
+ if (options & GPU_SHADER_LIGHTING)
+ glEnable(GL_LIGHTING);
+
+ if (options & GPU_SHADER_TWO_SIDED)
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
+
+ if (options & GPU_SHADER_OVERRIDE_DIFFUSE) {
+ glEnable(GL_COLOR_MATERIAL);
+ glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+ }
+
+ if (options & GPU_SHADER_TEXTURE_2D)
+ glEnable(GL_TEXTURE_2D);
+ }
+
+ /* temporary hack, should be solved outside of this file */
+ GPU_MATERIAL_STATE.need_normals = (options & GPU_SHADER_LIGHTING);
+}
+
+void GPU_simple_shader_unbind(void)
+{
+ if (GPU_glsl_support()) {
+ GPU_shader_unbind();
+ }
+ else {
+ glDisable(GL_LIGHTING);
+ glDisable(GL_COLOR_MATERIAL);
+ glDisable(GL_TEXTURE_2D);
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
+ }
+}
+
+/* Material Colors */
+
+void GPU_simple_shader_colors(const float diffuse[3], const float specular[3],
+ int shininess, float alpha)
+{
+ float gl_diffuse[4], gl_specular[4];
+
+ copy_v3_v3(gl_diffuse, diffuse);
+ gl_diffuse[3] = alpha;
+
+ copy_v3_v3(gl_specular, specular);
+ gl_specular[3] = 1.0f;
+
+ glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, gl_diffuse);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, gl_specular);
+ glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(shininess, 1, 128));
+}
+
+bool GPU_simple_shader_need_normals(void)
+{
+ return GPU_MATERIAL_STATE.need_normals;
+}
+
+void GPU_simple_shader_light_set(int light_num, GPULightData *light)
+{
+ int light_bit = (1 << light_num);
+
+ GPU_MATERIAL_STATE.lights_enabled &= ~light_bit;
+ GPU_MATERIAL_STATE.lights_directional &= ~light_bit;
+
+ if (light) {
+ glEnable(GL_LIGHT0+light_num);
+
+ glLightfv(GL_LIGHT0+light_num, GL_POSITION, light->position);
+ glLightfv(GL_LIGHT0+light_num, GL_DIFFUSE, light->diffuse);
+ glLightfv(GL_LIGHT0+light_num, GL_SPECULAR, light->specular);
+
+ glLightf(GL_LIGHT0+light_num, GL_CONSTANT_ATTENUATION, light->constant_attenuation);
+ glLightf(GL_LIGHT0+light_num, GL_LINEAR_ATTENUATION, light->linear_attenuation);
+ glLightf(GL_LIGHT0+light_num, GL_QUADRATIC_ATTENUATION, light->quadratic_attenuation);
+
+ glLightfv(GL_LIGHT0+light_num, GL_SPOT_DIRECTION, light->spot_direction);
+ glLightf(GL_LIGHT0+light_num, GL_SPOT_CUTOFF, light->spot_cutoff);
+ glLightf(GL_LIGHT0+light_num, GL_SPOT_EXPONENT, light->spot_exponent);
+
+ GPU_MATERIAL_STATE.lights_enabled |= light_bit;
+ if(light->position[3] == 0.0f)
+ GPU_MATERIAL_STATE.lights_directional |= light_bit;
+ }
+ else {
+ const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ glLightfv(GL_LIGHT0+light_num, GL_POSITION, zero);
+ glLightfv(GL_LIGHT0+light_num, GL_DIFFUSE, zero);
+ glLightfv(GL_LIGHT0+light_num, GL_SPECULAR, zero);
+
+ glDisable(GL_LIGHT0+light_num);
+ }
+}
+
+void GPU_simple_shader_light_set_viewer(bool local)
+{
+ glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (local)? GL_TRUE: GL_FALSE);
+}
+
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 9a238e979fa..4fc04175bba 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -233,7 +233,7 @@ void math_pow(float val1, float val2, out float outval)
else {
float val2_mod_1 = mod(abs(val2), 1.0);
- if (val2_mod_1 > 0.999 || val2_mod_1 < 0.001)
+ if (val2_mod_1 > 0.999 || val2_mod_1 < 0.001)
outval = compatible_pow(val1, floor(val2 + 0.5));
else
outval = 0.0;
@@ -390,6 +390,17 @@ void set_rgba_zero(out vec4 outval)
outval = vec4(0.0);
}
+void brightness_contrast(vec4 col, float brightness, float contrast, out vec4 outcol)
+{
+ float a = 1.0 + contrast;
+ float b = brightness - contrast*0.5;
+
+ outcol.r = max(a*col.r + b, 0.0);
+ outcol.g = max(a*col.g + b, 0.0);
+ outcol.b = max(a*col.b + b, 0.0);
+ outcol.a = col.a;
+}
+
void mix_blend(float fac, vec4 col1, vec4 col2, out vec4 outcol)
{
fac = clamp(fac, 0.0, 1.0);
@@ -811,7 +822,7 @@ void mtex_rgb_mul(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 inc
float facm;
fact *= facg;
- facm = 1.0-facg;
+ facm = 1.0-fact;
incol = (facm + fact*texcol)*outcol;
}
@@ -821,7 +832,7 @@ void mtex_rgb_screen(vec3 outcol, vec3 texcol, float fact, float facg, out vec3
float facm;
fact *= facg;
- facm = 1.0-facg;
+ facm = 1.0-fact;
incol = vec3(1.0) - (vec3(facm) + fact*(vec3(1.0) - texcol))*(vec3(1.0) - outcol);
}
@@ -831,7 +842,7 @@ void mtex_rgb_overlay(vec3 outcol, vec3 texcol, float fact, float facg, out vec3
float facm;
fact *= facg;
- facm = 1.0-facg;
+ facm = 1.0-fact;
if(outcol.r < 0.5)
incol.r = outcol.r*(facm + 2.0*fact*texcol.r);
@@ -888,11 +899,11 @@ void mtex_rgb_dark(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 in
fact *= facg;
facm = 1.0-fact;
- col = fact*texcol.r;
+ col= texcol.r + ((1.0 -texcol.r)*facm);
if(col < outcol.r) incol.r = col; else incol.r = outcol.r;
- col = fact*texcol.g;
+ col= texcol.g + ((1.0 -texcol.g)*facm);
if(col < outcol.g) incol.g = col; else incol.g = outcol.g;
- col = fact*texcol.b;
+ col= texcol.b + ((1.0 -texcol.b)*facm);
if(col < outcol.b) incol.b = col; else incol.b = outcol.b;
}
@@ -901,7 +912,6 @@ void mtex_rgb_light(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 i
float facm, col;
fact *= facg;
- facm = 1.0-fact;
col = fact*texcol.r;
if(col > outcol.r) incol.r = col; else incol.r = outcol.r;
@@ -2257,3 +2267,18 @@ void node_output_material(vec4 surface, vec4 volume, float displacement, out vec
result = surface;
}
+/* ********************** matcap style render ******************** */
+
+void material_preview_matcap(vec4 color, sampler2D ima, vec3 N, out vec4 result)
+{
+ vec2 tex;
+
+ if (N.z < 0.0) {
+ N.z = 0.0;
+ N = normalize(N);
+ }
+
+ tex.x = 0.5 + 0.49 * N.x;
+ tex.y = 0.5 + 0.49 * N.y;
+ result = texture2D(ima, tex);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_simple_frag.glsl b/source/blender/gpu/shaders/gpu_shader_simple_frag.glsl
new file mode 100644
index 00000000000..9610e0cf5aa
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_simple_frag.glsl
@@ -0,0 +1,169 @@
+
+/* Options:
+ *
+ * USE_COLOR: use glColor for diffuse colors
+ * USE_TEXTURE: use texture for diffuse colors
+ * USE_SCENE_LIGHTING: use lights (up to 8)
+ * USE_SOLID_LIGHTING: assume 3 directional lights for solid draw mode
+ * USE_TWO_SIDED: flip normal towards viewer
+ * NO_SPECULAR: use specular component
+ */
+
+#define NUM_SOLID_LIGHTS 3
+#define NUM_SCENE_LIGHTS 8
+
+#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
+varying vec3 varying_normal;
+
+#ifndef USE_SOLID_LIGHTING
+varying vec3 varying_position;
+#endif
+#endif
+
+#ifdef USE_COLOR
+varying vec4 varying_vertex_color;
+#endif
+
+#ifdef USE_TEXTURE
+varying vec2 varying_texture_coord;
+uniform sampler2D texture_map;
+#endif
+
+void main()
+{
+#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
+ /* compute normal */
+ vec3 N = normalize(varying_normal);
+
+#ifdef USE_TWO_SIDED
+ if (!gl_FrontFacing)
+ N = -N;
+#endif
+
+ /* compute diffuse and specular lighting */
+ vec3 L_diffuse = vec3(0.0);
+#ifndef NO_SPECULAR
+ vec3 L_specular = vec3(0.0);
+#endif
+
+#ifdef USE_SOLID_LIGHTING
+ /* assume 3 directional lights */
+ for (int i = 0; i < NUM_SOLID_LIGHTS; i++) {
+ vec3 light_direction = gl_LightSource[i].position.xyz;
+
+ /* diffuse light */
+ vec3 light_diffuse = gl_LightSource[i].diffuse.rgb;
+ float diffuse_bsdf = max(dot(N, light_direction), 0.0);
+ L_diffuse += light_diffuse*diffuse_bsdf;
+
+#ifndef NO_SPECULAR
+ /* specular light */
+ vec3 light_specular = gl_LightSource[i].specular.rgb;
+ vec3 H = gl_LightSource[i].halfVector.xyz;
+
+ float specular_bsdf = pow(max(dot(N, H), 0.0), gl_FrontMaterial.shininess);
+ L_specular += light_specular*specular_bsdf;
+#endif
+ }
+#else
+ /* all 8 lights, makes no assumptions, potentially slow */
+
+#ifndef NO_SPECULAR
+ /* view vector computation, depends on orthographics or perspective */
+ vec3 V = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(varying_position): vec3(0.0, 0.0, -1.0);
+#endif
+
+ for (int i = 0; i < NUM_SCENE_LIGHTS; i++) {
+ /* todo: this is a slow check for disabled lights */
+ if (gl_LightSource[i].specular.a == 0.0)
+ continue;
+
+ float intensity = 1.0;
+ vec3 light_direction;
+
+ if (gl_LightSource[i].position.w == 0.0) {
+ /* directional light */
+ light_direction = gl_LightSource[i].position.xyz;
+ }
+ else {
+ /* point light */
+ vec3 d = gl_LightSource[i].position.xyz - varying_position;
+ light_direction = normalize(d);
+
+ /* spot light cone */
+ if (gl_LightSource[i].spotCutoff < 90.0) {
+ float cosine = max(dot(light_direction, -gl_LightSource[i].spotDirection), 0.0);
+ intensity = pow(cosine, gl_LightSource[i].spotExponent);
+ intensity *= step(gl_LightSource[i].spotCosCutoff, cosine);
+ }
+
+ /* falloff */
+ float distance = length(d);
+
+ intensity /= gl_LightSource[i].constantAttenuation +
+ gl_LightSource[i].linearAttenuation * distance +
+ gl_LightSource[i].quadraticAttenuation * distance * distance;
+ }
+
+ /* diffuse light */
+ vec3 light_diffuse = gl_LightSource[i].diffuse.rgb;
+ float diffuse_bsdf = max(dot(N, light_direction), 0.0);
+ L_diffuse += light_diffuse*diffuse_bsdf*intensity;
+
+#ifndef NO_SPECULAR
+ /* specular light */
+ vec3 light_specular = gl_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
+ }
+#endif
+
+ /* compute diffuse color, possibly from texture or vertex colors */
+ float alpha;
+
+#if defined(USE_TEXTURE) && defined(USE_COLOR)
+ vec4 texture_color = texture2D(texture_map, varying_texture_coord);
+
+ L_diffuse *= texture_color.rgb * varying_vertex_color.rgb;
+ alpha = texture_color.a * varying_vertex_color.a;
+#elif defined(USE_TEXTURE)
+ vec4 texture_color = texture2D(texture_map, varying_texture_coord);
+
+ L_diffuse *= texture_color.rgb;
+ alpha = texture_color.a;
+#elif defined(USE_COLOR)
+ L_diffuse *= varying_vertex_color.rgb;
+ alpha = varying_vertex_color.a;
+#else
+ L_diffuse *= gl_FrontMaterial.diffuse.rgb;
+ alpha = gl_FrontMaterial.diffuse.a;
+#endif
+
+ /* sum lighting */
+ vec3 L = gl_FrontLightModelProduct.sceneColor.rgb + L_diffuse;
+
+#ifndef NO_SPECULAR
+ L += L_specular*gl_FrontMaterial.specular.rgb;
+#endif
+
+ /* write out fragment color */
+ gl_FragColor = vec4(L, alpha);
+#else
+
+ /* no lighting */
+#if defined(USE_TEXTURE) && defined(USE_COLOR)
+ gl_FragColor = texture2D(texture_map, varying_texture_coord) * varying_vertex_color;
+#elif defined(USE_TEXTURE)
+ gl_FragColor = texture2D(texture_map, varying_texture_coord);
+#elif defined(USE_COLOR)
+ gl_FragColor = varying_vertex_color;
+#else
+ gl_FragColor = gl_FrontMaterial.diffuse;
+#endif
+
+#endif
+}
+
diff --git a/source/blender/gpu/shaders/gpu_shader_simple_vert.glsl b/source/blender/gpu/shaders/gpu_shader_simple_vert.glsl
new file mode 100644
index 00000000000..9491eaa672d
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_simple_vert.glsl
@@ -0,0 +1,46 @@
+
+#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
+varying vec3 varying_normal;
+
+#ifndef USE_SOLID_LIGHTING
+varying vec3 varying_position;
+#endif
+#endif
+
+#ifdef USE_COLOR
+varying vec4 varying_vertex_color;
+#endif
+
+#ifdef USE_TEXTURE
+varying vec2 varying_texture_coord;
+#endif
+
+void main()
+{
+ vec4 co = gl_ModelViewMatrix * gl_Vertex;
+
+#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
+ varying_normal = normalize(gl_NormalMatrix * gl_Normal);
+
+#ifndef USE_SOLID_LIGHTING
+ varying_position = co.xyz;
+#endif
+#endif
+
+ gl_Position = gl_ProjectionMatrix * co;
+
+#ifdef GPU_NVIDIA
+ // Setting gl_ClipVertex is necessary to get glClipPlane working on NVIDIA
+ // graphic cards, while on ATI it can cause a software fallback.
+ gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#endif
+
+#ifdef USE_COLOR
+ varying_vertex_color = gl_Color;
+#endif
+
+#ifdef USE_TEXTURE
+ varying_texture_coord = (gl_TextureMatrix[0] * gl_MultiTexCoord0).st;
+#endif
+}
+
diff --git a/source/blender/gpu/shaders/gpu_shader_vertex.glsl b/source/blender/gpu/shaders/gpu_shader_vertex.glsl
index 574455e42b3..8741a13ea9b 100644
--- a/source/blender/gpu/shaders/gpu_shader_vertex.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vertex.glsl
@@ -10,11 +10,9 @@ void main()
varnormal = normalize(gl_NormalMatrix * gl_Normal);
gl_Position = gl_ProjectionMatrix * co;
- // Setting gl_ClipVertex is necessary to get glClipPlane working on NVIDIA graphic cards.
- // gl_ClipVertex works only on NVIDIA graphic cards so we have to check with
- // __GLSL_CG_DATA_TYPES if a NVIDIA graphic card is used (Cg support).
- // gl_ClipVerte is supported up to GLSL 1.20.
- #ifdef __GLSL_CG_DATA_TYPES
- gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
- #endif
+#ifdef GPU_NVIDIA
+ // Setting gl_ClipVertex is necessary to get glClipPlane working on NVIDIA
+ // graphic cards, while on ATI it can cause a software fallback.
+ gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
+#endif
diff --git a/source/blender/ikplugin/SConscript b/source/blender/ikplugin/SConscript
index 97b1cf18e0d..0d201cb423c 100644
--- a/source/blender/ikplugin/SConscript
+++ b/source/blender/ikplugin/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
defs = []
sources = env.Glob('intern/*.c') + env.Glob('intern/*.cpp')
diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c
index 75aaa23369b..9ec115f10e8 100644
--- a/source/blender/ikplugin/intern/iksolver_plugin.c
+++ b/source/blender/ikplugin/intern/iksolver_plugin.c
@@ -200,7 +200,9 @@ static void make_dmats(bPoseChannel *pchan)
invert_m4_m4(iR_parmat, pchan->parent->pose_mat);
mult_m4_m4m4(pchan->chan_mat, iR_parmat, pchan->pose_mat); // delta mat
}
- else copy_m4_m4(pchan->chan_mat, pchan->pose_mat);
+ else {
+ copy_m4_m4(pchan->chan_mat, pchan->pose_mat);
+ }
}
/* applies IK matrix to pchan, IK is done separated */
@@ -372,7 +374,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
/* 1.0=ctime, we pass on object for auto-ik (owner-type here is object, even though
* strictly speaking, it is a posechannel)
*/
- get_constraint_target_matrix(scene, target->con, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
+ BKE_get_constraint_target_matrix(scene, target->con, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
/* and set and transform goal */
mult_m4_m4m4(goal, goalinv, rootmat);
@@ -383,7 +385,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
/* same for pole vector target */
if (data->poletar) {
- get_constraint_target_matrix(scene, target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
+ BKE_get_constraint_target_matrix(scene, target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
if (data->flag & CONSTRAINT_IK_SETANGLE) {
/* don't solve IK when we are setting the pole angle */
diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp
index 903080d5b79..96bdb6c9bdd 100644
--- a/source/blender/ikplugin/intern/itasc_plugin.cpp
+++ b/source/blender/ikplugin/intern/itasc_plugin.cpp
@@ -370,7 +370,7 @@ static int initialize_chain(Object *ob, bPoseChannel *pchan_tip, bConstraint *co
static bool is_cartesian_constraint(bConstraint *con)
{
- //bKinematicConstraint* data=(bKinematicConstraint*)con->data;
+ //bKinematicConstraint* data=(bKinematicConstraint *)con->data;
return true;
}
@@ -551,7 +551,7 @@ static bool target_callback(const iTaSC::Timestamp& timestamp, const iTaSC::Fram
bConstraint *constraint = (bConstraint *)target->blenderConstraint;
float tarmat[4][4];
- get_constraint_target_matrix(target->blscene, constraint, 0, CONSTRAINT_OBTYPE_OBJECT, target->owner, tarmat, 1.0);
+ BKE_get_constraint_target_matrix(target->blscene, constraint, 0, CONSTRAINT_OBTYPE_OBJECT, target->owner, tarmat, 1.0);
// rootmat contains the target pose in world coordinate
// if enforce is != 1.0, blend the target position with the end effector position
@@ -620,7 +620,7 @@ static bool base_callback(const iTaSC::Timestamp& timestamp, const iTaSC::Frame&
IK_Channel &rootchan = ikscene->channels[0];
// get polar target matrix in world space
- get_constraint_target_matrix(ikscene->blscene, ikscene->polarConstraint, 1, CONSTRAINT_OBTYPE_OBJECT, ikscene->blArmature, mat, 1.0);
+ BKE_get_constraint_target_matrix(ikscene->blscene, ikscene->polarConstraint, 1, CONSTRAINT_OBTYPE_OBJECT, ikscene->blArmature, mat, 1.0);
// convert to armature space
mult_m4_m4m4(polemat, imat, mat);
// get the target in world space (was computed before as target object are defined before base object)
@@ -864,7 +864,7 @@ static bool joint_callback(const iTaSC::Timestamp& timestamp, iTaSC::ConstraintV
}
// build array of joint corresponding to IK chain
-static int convert_channels(IK_Scene *ikscene, PoseTree *tree)
+static int convert_channels(IK_Scene *ikscene, PoseTree *tree, float ctime)
{
IK_Channel *ikchan;
bPoseChannel *pchan;
@@ -877,6 +877,14 @@ static int convert_channels(IK_Scene *ikscene, PoseTree *tree)
ikchan->parent = (a > 0) ? tree->parent[a] : -1;
ikchan->owner = ikscene->blArmature;
+ // the constraint and channels must be applied before we build the iTaSC scene,
+ // this is because some of the pose data (e.g. pose head) don't have corresponding
+ // joint angles and can't be applied to the iTaSC armature dynamically
+ if (!(pchan->flag & POSE_DONE))
+ BKE_pose_where_is_bone(ikscene->blscene, ikscene->blArmature, pchan, ctime, 1);
+ // tell blender that this channel was controlled by IK, it's cleared on each BKE_pose_where_is()
+ pchan->flag |= (POSE_DONE | POSE_CHAIN);
+
/* set DoF flag */
flag = 0;
if (!(pchan->ikflag & BONE_IK_NO_XDOF) && !(pchan->ikflag & BONE_IK_NO_XDOF_TEMP) &&
@@ -1049,7 +1057,7 @@ static void BKE_pose_rest(IK_Scene *ikscene)
}
}
-static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
+static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan, float ctime)
{
PoseTree *tree = (PoseTree *)pchan->iktree.first;
PoseTarget *target;
@@ -1068,6 +1076,7 @@ static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
float length;
bool ret = true, ingame;
double *rot;
+ float start[3];
if (tree->totchannel == 0)
return NULL;
@@ -1126,7 +1135,7 @@ static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
std::vector<double> weights;
double weight[3];
// build the array of joints corresponding to the IK chain
- convert_channels(ikscene, tree);
+ convert_channels(ikscene, tree, ctime);
if (ingame) {
// in the GE, set the initial joint angle to match the current pose
// this will update the jointArray in ikscene
@@ -1137,17 +1146,37 @@ static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
BKE_pose_rest(ikscene);
}
rot = ikscene->jointArray(0);
+
for (a = 0, ikchan = ikscene->channels; a < tree->totchannel; ++a, ++ikchan) {
pchan = ikchan->pchan;
bone = pchan->bone;
KDL::Frame tip(iTaSC::F_identity);
+ // compute the position and rotation of the head from previous segment
Vector3 *fl = bone->bone_mat;
KDL::Rotation brot(
fl[0][0], fl[1][0], fl[2][0],
fl[0][1], fl[1][1], fl[2][1],
fl[0][2], fl[1][2], fl[2][2]);
- KDL::Vector bpos(bone->head[0], bone->head[1], bone->head[2]);
+ // if the bone is disconnected, the head is movable in pose mode
+ // take that into account by using pose matrix instead of bone
+ // Note that pose is expressed in armature space, convert to previous bone space
+ {
+ float R_parmat[3][3];
+ float iR_parmat[3][3];
+ if (pchan->parent)
+ copy_m3_m4(R_parmat, pchan->parent->pose_mat);
+ else
+ unit_m3(R_parmat);
+ if (pchan->parent)
+ sub_v3_v3v3(start, pchan->pose_head, pchan->parent->pose_tail);
+ else
+ start[0] = start[1] = start[2] = 0.0f;
+ invert_m3_m3(iR_parmat, R_parmat);
+ normalize_m3(iR_parmat);
+ mul_m3_v3(iR_parmat, start);
+ }
+ KDL::Vector bpos(start[0], start[1], start[2]);
bpos *= ikscene->blScale;
KDL::Frame head(brot, bpos);
@@ -1155,7 +1184,7 @@ static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
length = bone->length * ikscene->blScale;
parent = (a > 0) ? ikscene->channels[tree->parent[a]].tail : root;
// first the fixed segment to the bone head
- if (head.p.Norm() > KDL::epsilon || head.M.GetRot().Norm() > KDL::epsilon) {
+ if (!(ikchan->pchan->bone->flag & BONE_CONNECTED) || head.M.GetRot().Norm() > KDL::epsilon) {
joint = bone->name;
joint += ":H";
ret = arm->addSegment(joint, parent, KDL::Joint::None, 0.0, head);
@@ -1490,14 +1519,15 @@ static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
if (!ret ||
!scene->addCache(ikscene->cache) ||
!scene->addSolver(ikscene->solver) ||
- !scene->initialize()) {
+ !scene->initialize())
+ {
delete ikscene;
ikscene = NULL;
}
return ikscene;
}
-static void create_scene(Scene *scene, Object *ob)
+static void create_scene(Scene *scene, Object *ob, float ctime)
{
bPoseChannel *pchan;
@@ -1508,7 +1538,7 @@ static void create_scene(Scene *scene, Object *ob)
if (tree) {
IK_Data *ikdata = get_ikdata(ob->pose);
// convert tree in iTaSC::Scene
- IK_Scene *ikscene = convert_tree(scene, ob, pchan);
+ IK_Scene *ikscene = convert_tree(scene, ob, pchan, ctime);
if (ikscene) {
ikscene->next = ikdata->first;
ikdata->first = ikscene;
@@ -1537,7 +1567,8 @@ static int init_scene(Object *ob)
if (ob->pose->ikdata) {
for (scene = ((IK_Data *)ob->pose->ikdata)->first;
scene != NULL;
- scene = scene->next) {
+ scene = scene->next)
+ {
if (fabs(scene->blScale - scale) > KDL::epsilon)
return 1;
scene->channels[0].pchan->flag |= POSE_IKTREE;
@@ -1732,15 +1763,21 @@ void itasc_initialize_tree(struct Scene *scene, Object *ob, float ctime)
count += initialize_scene(ob, pchan);
}
// if at least one tree, create the scenes from the PoseTree stored in the channels
- if (count)
- create_scene(scene, ob);
- itasc_update_param(ob->pose);
+ // postpone until execute_tree: this way the pose constraint are included
+ //if (count)
+ // create_scene(scene, ob, ctime);
+ //itasc_update_param(ob->pose);
// make sure we don't rebuilt until the user changes something important
ob->pose->flag &= ~POSE_WAS_REBUILT;
}
void itasc_execute_tree(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime)
{
+ if (!ob->pose->ikdata) {
+ // IK tree not yet created, no it now
+ create_scene(scene, ob, ctime);
+ itasc_update_param(ob->pose);
+ }
if (ob->pose->ikdata) {
IK_Data *ikdata = (IK_Data *)ob->pose->ikdata;
bItasc *ikparam = (bItasc *) ob->pose->ikparam;
diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h
index 0653956e113..b981390582e 100644
--- a/source/blender/imbuf/IMB_colormanagement.h
+++ b/source/blender/imbuf/IMB_colormanagement.h
@@ -70,6 +70,8 @@ void IMB_colormanagement_transform_threaded(float *buffer, int width, int height
void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace);
void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], struct ColorSpace *colorspace);
+void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4], int predivide, struct ColorSpace *colorspace);
+
void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], struct ColorSpace *colorspace);
void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, int predivide);
@@ -133,11 +135,14 @@ void IMB_partial_display_buffer_update(struct ImBuf *ibuf, const float *linear_b
int xmin, int ymin, int xmax, int ymax,
int update_orig_byte_buffer);
+void IMB_partial_display_buffer_update_delayed(struct ImBuf *ibuf, int xmin, int ymin, int xmax, int ymax);
+
/* ** Pixel processor functions ** */
struct ColormanageProcessor *IMB_colormanagement_display_processor_new(const struct ColorManagedViewSettings *view_settings,
const struct ColorManagedDisplaySettings *display_settings);
struct ColormanageProcessor *IMB_colormanagement_colorspace_processor_new(const char *from_colorspace, const char *to_colorspace);
void IMB_colormanagement_processor_apply_v4(struct ColormanageProcessor *cm_processor, float pixel[4]);
+void IMB_colormanagement_processor_apply_v4_predivide(struct ColormanageProcessor *cm_processor, float pixel[4]);
void IMB_colormanagement_processor_apply_v3(struct ColormanageProcessor *cm_processor, float pixel[3]);
void IMB_colormanagement_processor_apply(struct ColormanageProcessor *cm_processor, float *buffer, int width, int height,
int channels, int predivide);
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index db1404813b1..48c14fc07f2 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -338,6 +338,12 @@ struct ImBuf *IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned
/**
*
+ * \attention Defined in scaling.c
+ */
+void IMB_scaleImBuf_threaded(struct ImBuf *ibuf, unsigned int newx, unsigned int newy);
+
+/**
+ *
* \attention Defined in writeimage.c
*/
short IMB_saveiff(struct ImBuf *ibuf, const char *filepath, int flags);
@@ -373,9 +379,6 @@ void IMB_rect_from_float(struct ImBuf *ibuf);
* Changed part will be stored in buffer. This is expected to be used for texture painting updates */
void IMB_partial_rect_from_float(struct ImBuf *ibuf, float *buffer, int x, int y, int w, int h, int is_data);
void IMB_float_from_rect(struct ImBuf *ibuf);
-void IMB_float_from_rect_simple(struct ImBuf *ibuf); /* no profile conversion */
-/* note, check that the conversion exists, only some are supported */
-float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc);
void IMB_color_to_bw(struct ImBuf *ibuf);
void IMB_saturation(struct ImBuf *ibuf, float sat);
@@ -393,6 +396,8 @@ void IMB_buffer_byte_from_byte(unsigned char *rect_to, const unsigned char *rect
int profile_to, int profile_from, int predivide,
int width, int height, int stride_to, int stride_from);
void IMB_buffer_float_clamp(float *buf, int width, int height);
+void IMB_buffer_float_unpremultiply(float *buf, int width, int height);
+void IMB_buffer_float_premultiply(float *buf, int width, int height);
/**
* Change the ordering of the color bytes pointed to by rect from
@@ -415,6 +420,9 @@ void nearest_interpolation_color(struct ImBuf *in, unsigned char col[4], float c
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);
+void IMB_alpha_under_color_float(float *rect_float, int x, int y, float backcol[3]);
+void IMB_alpha_under_color_byte(unsigned char *rect, int x, int y, float backcol[3]);
+
/**
*
* \attention defined in readimage.c
@@ -467,6 +475,7 @@ void IMB_flipy(struct ImBuf *ibuf);
/* Premultiply alpha */
void IMB_premultiply_alpha(struct ImBuf *ibuf);
+void IMB_unpremultiply_alpha(struct ImBuf *ibuf);
/**
*
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index 28e62d496b2..dde8d4d4ab7 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -28,6 +28,8 @@
#ifndef __IMB_IMBUF_TYPES_H__
#define __IMB_IMBUF_TYPES_H__
+#include "DNA_vec_types.h" /* for rcti */
+
/**
* \file IMB_imbuf_types.h
* \ingroup imbuf
@@ -132,6 +134,7 @@ typedef struct ImBuf {
unsigned int *display_buffer_flags; /* array of per-display display buffers dirty flags */
struct ColormanageCache *colormanage_cache; /* cache used by color management */
int colormanage_flag;
+ rcti invalid_rect;
/* information for compressed textures */
struct DDSData dds_data;
@@ -167,14 +170,15 @@ typedef struct ImBuf {
#define IB_animdeinterlace (1 << 9)
#define IB_tiles (1 << 10)
#define IB_tilecache (1 << 11)
-#define IB_premul (1 << 12)
-#define IB_cm_predivide (1 << 13)
+#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 10 bits is used for storing custom flags
+ * Note that the lower 11 bits is used for storing custom flags
*/
-#define IB_CUSTOM_FLAGS_MASK 0x3ff
+#define IB_CUSTOM_FLAGS_MASK 0x7ff
#define PNG (1 << 30)
#define TGA (1 << 28)
@@ -217,8 +221,12 @@ typedef struct ImBuf {
#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))
diff --git a/source/blender/imbuf/IMB_moviecache.h b/source/blender/imbuf/IMB_moviecache.h
index 4588c2bcee5..1c569712968 100644
--- a/source/blender/imbuf/IMB_moviecache.h
+++ b/source/blender/imbuf/IMB_moviecache.h
@@ -58,7 +58,9 @@ void IMB_moviecache_set_priority_callback(struct MovieCache *cache, MovieCacheGe
MovieCachePriorityDeleterFP prioritydeleterfp);
void IMB_moviecache_put(struct MovieCache *cache, void *userkey, struct ImBuf *ibuf);
+int IMB_moviecache_put_if_possible(struct MovieCache *cache, void *userkey, struct ImBuf *ibuf);
struct ImBuf *IMB_moviecache_get(struct MovieCache *cache, void *userkey);
+int IMB_moviecache_has_frame(struct MovieCache *cache, void *userkey);
void IMB_moviecache_free(struct MovieCache *cache);
void IMB_moviecache_cleanup(struct MovieCache *cache, int (cleanup_check_cb) (void *userkey, void *userdata), void *userdata);
diff --git a/source/blender/imbuf/IMB_thumbs.h b/source/blender/imbuf/IMB_thumbs.h
index a6f38516a14..9fc075e4e8b 100644
--- a/source/blender/imbuf/IMB_thumbs.h
+++ b/source/blender/imbuf/IMB_thumbs.h
@@ -58,7 +58,7 @@ typedef enum ThumbSource {
} ThumbSource;
/* don't generate thumbs for images bigger then this (100mb) */
-#define THUMB_SIZE_MAX (100 * 1024*1024)
+#define THUMB_SIZE_MAX (100 * 1024 * 1024)
// IB_metadata
diff --git a/source/blender/imbuf/SConscript b/source/blender/imbuf/SConscript
index 976108cd84e..453cf6a509e 100644
--- a/source/blender/imbuf/SConscript
+++ b/source/blender/imbuf/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
import os
Import ('env')
@@ -27,7 +53,7 @@ else:
if env['WITH_BF_TIFF']:
defs.append('WITH_TIFF')
else:
- sources.remove(os.path.join('intern', 'tiff.c'))
+ sources.remove(os.path.join('intern', 'tiff.c'))
if env['WITH_BF_DDS']:
defs.append('WITH_DDS')
@@ -38,7 +64,7 @@ if env['WITH_BF_CINEON']:
if env['WITH_BF_HDR']:
defs.append('WITH_HDR')
else:
- sources.remove(os.path.join('intern', 'radiance_hdr.c'))
+ sources.remove(os.path.join('intern', 'radiance_hdr.c'))
if env['WITH_BF_FFMPEG']:
defs.append('WITH_FFMPEG')
@@ -48,7 +74,7 @@ if env['WITH_BF_OPENJPEG']:
defs.append('WITH_OPENJPEG')
incs += ' ' + env['BF_OPENJPEG_INC']
else:
- sources.remove(os.path.join('intern', 'jp2.c'))
+ sources.remove(os.path.join('intern', 'jp2.c'))
if env['WITH_BF_REDCODE']:
defs.append('WITH_REDCODE')
diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h
index ba9e20ac411..c372e125a66 100644
--- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h
+++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h
@@ -33,16 +33,17 @@
#include "DNA_listBase.h"
-#define BCM_CONFIG_FILE "config.ocio"
-
struct OCIO_ConstProcessorRcPtr;
struct ImBuf;
+#define MAX_COLORSPACE_NAME 64
+#define MAX_COLORSPACE_DESCRIPTION 512
+
typedef struct ColorSpace {
struct ColorSpace *next, *prev;
int index;
- char name[64];
- char description[64];
+ char name[MAX_COLORSPACE_NAME];
+ char description[MAX_COLORSPACE_DESCRIPTION];
struct OCIO_ConstProcessorRcPtr *to_scene_linear;
struct OCIO_ConstProcessorRcPtr *from_scene_linear;
@@ -54,7 +55,7 @@ typedef struct ColorSpace {
typedef struct ColorManagedDisplay {
struct ColorManagedDisplay *next, *prev;
int index;
- char name[64];
+ char name[MAX_COLORSPACE_NAME];
ListBase views;
struct OCIO_ConstProcessorRcPtr *to_scene_linear;
@@ -64,7 +65,7 @@ typedef struct ColorManagedDisplay {
typedef struct ColorManagedView {
struct ColorManagedView *next, *prev;
int index;
- char name[64];
+ char name[MAX_COLORSPACE_NAME];
} ColorManagedView;
/* ** Initialization / De-initialization ** */
diff --git a/source/blender/imbuf/intern/IMB_filter.h b/source/blender/imbuf/intern/IMB_filter.h
index eaedb160c94..6bd5f44307f 100644
--- a/source/blender/imbuf/intern/IMB_filter.h
+++ b/source/blender/imbuf/intern/IMB_filter.h
@@ -41,6 +41,9 @@ void imb_filterx(struct ImBuf *ibuf);
void IMB_premultiply_rect(unsigned int *rect, char planes, int w, int h);
void IMB_premultiply_rect_float(float *rect_float, char planes, int w, int h);
+void IMB_unpremultiply_rect(unsigned int *rect, char planes, int w, int h);
+void IMB_unpremultiply_rect_float(float *rect_float, char planes, int w, int h);
+
void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1);
#endif
diff --git a/source/blender/imbuf/intern/IMB_indexer.h b/source/blender/imbuf/intern/IMB_indexer.h
index 9c95531e90d..d114df945ae 100644
--- a/source/blender/imbuf/intern/IMB_indexer.h
+++ b/source/blender/imbuf/intern/IMB_indexer.h
@@ -116,9 +116,6 @@ void IMB_indexer_close(struct anim_index * idx);
void IMB_free_indices(struct anim * anim);
-int IMB_anim_index_get_frame_index(
- struct anim *anim, IMB_Timecode_Type tc, int position);
-
struct anim *IMB_anim_open_proxy(
struct anim *anim, IMB_Proxy_Size preview_size);
struct anim_index * IMB_anim_open_index(
diff --git a/source/blender/imbuf/intern/IMB_metadata.h b/source/blender/imbuf/intern/IMB_metadata.h
index a68d7a7813e..f731fd69620 100644
--- a/source/blender/imbuf/intern/IMB_metadata.h
+++ b/source/blender/imbuf/intern/IMB_metadata.h
@@ -42,7 +42,7 @@ typedef struct ImMetaData {
int len;
} ImMetaData;
-/** The metadata is a list of key/value pairs (both char*) that can me
+/** 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
* 'Software' and 'Description' (png standard) we'll use keys within the
diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c
index 1b3a6d4a4cd..ca0b26fa4b7 100644
--- a/source/blender/imbuf/intern/allocimbuf.c
+++ b/source/blender/imbuf/intern/allocimbuf.c
@@ -355,7 +355,7 @@ ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar planes, unsigned int
ibuf->x = x;
ibuf->y = y;
ibuf->planes = planes;
- ibuf->ftype = TGA;
+ ibuf->ftype = PNG | 90; /* the 90 means, set compression to nearly the maximum */
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 */
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index 8dfdbd4fddc..4ef1f962a0f 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -64,9 +64,9 @@
#include <io.h>
#endif
+#include "BLI_utildefines.h"
#include "BLI_string.h"
#include "BLI_path_util.h"
-#include "BLI_utildefines.h"
#include "BLI_math_base.h"
#include "MEM_guardedalloc.h"
@@ -486,7 +486,7 @@ static int startffmpeg(struct anim *anim)
return -1;
}
- if (av_find_stream_info(pFormatCtx) < 0) {
+ if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
av_close_input_file(pFormatCtx);
return -1;
}
@@ -523,7 +523,7 @@ static int startffmpeg(struct anim *anim)
pCodecCtx->workaround_bugs = 1;
- if (avcodec_open(pCodecCtx, pCodec) < 0) {
+ if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
av_close_input_file(pFormatCtx);
return -1;
}
@@ -822,10 +822,10 @@ static int ffmpeg_decode_video_frame(struct anim *anim)
if (rval == AVERROR_EOF) {
/* this sets size and data fields to zero,
- which is necessary to decode the remaining data
- in the decoder engine after EOF. It also prevents a memory
- leak, since av_read_frame spills out a full size packet even
- on EOF... (and: it's save to call on NULL packets) */
+ * which is necessary to decode the remaining data
+ * in the decoder engine after EOF. It also prevents a memory
+ * leak, since av_read_frame spills out a full size packet even
+ * on EOF... (and: it's save to call on NULL packets) */
av_free_packet(&anim->next_packet);
diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c
index 32733668052..856124ab5cb 100644
--- a/source/blender/imbuf/intern/bmp.c
+++ b/source/blender/imbuf/intern/bmp.c
@@ -29,6 +29,7 @@
* \ingroup imbuf
*/
+#include "BLI_utildefines.h"
#include "BLI_fileops.h"
#include "imbuf.h"
@@ -60,6 +61,7 @@ typedef struct BMPINFOHEADER {
unsigned int biClrImportant;
} BMPINFOHEADER;
+#if 0
typedef struct BMPHEADER {
unsigned short biType;
unsigned int biSize;
@@ -67,6 +69,7 @@ typedef struct BMPHEADER {
unsigned short biRes2;
unsigned int biOffBits;
} BMPHEADER;
+#endif
#define BMP_FILEHEADER_SIZE 14
@@ -125,6 +128,7 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char co
int x, y, depth, skip, i;
unsigned char *bmp, *rect;
unsigned short col;
+ double xppm, yppm;
(void)size; /* unused */
@@ -144,6 +148,8 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char co
x = LITTLE_LONG(bmi.biWidth);
y = LITTLE_LONG(bmi.biHeight);
depth = LITTLE_SHORT(bmi.biBitCount);
+ xppm = LITTLE_LONG(bmi.biXPelsPerMeter);
+ yppm = LITTLE_LONG(bmi.biYPelsPerMeter);
#if 0
printf("skip: %d, x: %d y: %d, depth: %d (%x)\n", skip, x, y,
@@ -199,6 +205,8 @@ 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;
}
@@ -250,8 +258,8 @@ int imb_savebmp(struct ImBuf *ibuf, const char *name, int flags)
putShortLSB(24, ofile);
putIntLSB(0, ofile);
putIntLSB(bytesize + BMP_FILEHEADER_SIZE + sizeof(infoheader), ofile);
- putIntLSB(0, ofile);
- putIntLSB(0, ofile);
+ putIntLSB((int)(ibuf->ppm[0] + 0.5), ofile);
+ putIntLSB((int)(ibuf->ppm[1] + 0.5), ofile);
putIntLSB(0, ofile);
putIntLSB(0, ofile);
diff --git a/source/blender/imbuf/intern/cineon/SConscript b/source/blender/imbuf/intern/cineon/SConscript
index a07334632d7..d8fc2502081 100644
--- a/source/blender/imbuf/intern/cineon/SConscript
+++ b/source/blender/imbuf/intern/cineon/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
source_files = env.Glob('*.c')
diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c
index c8bc3f8ebb8..255af7dc039 100644
--- a/source/blender/imbuf/intern/cineon/cineon_dpx.c
+++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c
@@ -63,37 +63,33 @@ static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, size_t size, int us
image = logImageOpenFromMemory(mem, size);
- if (image == 0) {
+ if (image == NULL) {
printf("DPX/Cineon: error opening image.\n");
- return 0;
+ return NULL;
}
logImageGetSize(image, &width, &height, &depth);
- if (width == 0 || height == 0) {
- logImageClose(image);
- return 0;
- }
-
ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags);
- if (ibuf == 0) {
+ if (ibuf == NULL) {
logImageClose(image);
- return 0;
+ return NULL;
}
- if (logImageGetDataRGBA(image, ibuf->rect_float, 1) != 0) {
- /* Conversion not possible (probably because the format is unsupported) */
- logImageClose(image);
- MEM_freeN(ibuf);
- return 0;
+ if (!(flags & IB_test)) {
+ if (logImageGetDataRGBA(image, ibuf->rect_float, 1) != 0) {
+ logImageClose(image);
+ IMB_freeImBuf(ibuf);
+ return NULL;
+ }
+ IMB_flipy(ibuf);
}
logImageClose(image);
ibuf->ftype = use_cineon ? CINEON : DPX;
- IMB_flipy(ibuf);
- if (flags & IB_rect)
- IMB_rect_from_float(ibuf);
+ if (flags & IB_alphamode_detect)
+ ibuf->flags |= IB_alphamode_premul;
return ibuf;
}
@@ -131,14 +127,14 @@ static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon
logImage = logImageCreate(filename, use_cineon, ibuf->x, ibuf->y, bitspersample, (depth == 4),
(ibuf->ftype & CINEON_LOG), -1, -1, -1, "Blender");
- if (logImage == 0) {
+ if (logImage == NULL) {
printf("DPX/Cineon: error creating file.\n");
return 0;
}
- if (ibuf->rect_float != 0 && bitspersample != 8) {
+ if (ibuf->rect_float != NULL && bitspersample != 8) {
/* don't use the float buffer to save 8 bpp picture to prevent color banding
- (there's no dithering algorithm behing the logImageSetDataRGBA function) */
+ * (there's no dithering algorithm behing the logImageSetDataRGBA function) */
fbuf = (float *)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), "fbuf in imb_save_dpx_cineon");
@@ -154,11 +150,11 @@ static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon
MEM_freeN(fbuf);
}
else {
- if (ibuf->rect == 0)
+ if (ibuf->rect == NULL)
IMB_rect_from_float(ibuf);
fbuf = (float *)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), "fbuf in imb_save_dpx_cineon");
- if (fbuf == 0) {
+ if (fbuf == NULL) {
printf("DPX/Cineon: error allocating memory.\n");
logImageClose(logImage);
return 0;
@@ -195,7 +191,7 @@ ImBuf *imb_load_cineon(unsigned char *mem, size_t size, int flags, char colorspa
{
if (imb_is_cineon(mem))
return imb_load_dpx_cineon(mem, size, 1, flags, colorspace);
- return 0;
+ return NULL;
}
int imb_save_dpx(struct ImBuf *buf, const char *myfile, int flags)
@@ -212,5 +208,5 @@ ImBuf *imb_load_dpx(unsigned char *mem, size_t size, int flags, char colorspace[
{
if (imb_is_dpx(mem))
return imb_load_dpx_cineon(mem, size, 0, flags, colorspace);
- return 0;
+ return NULL;
}
diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c
index 3049a5be514..1481b2aaa66 100644
--- a/source/blender/imbuf/intern/cineon/cineonlib.c
+++ b/source/blender/imbuf/intern/cineon/cineonlib.c
@@ -50,7 +50,8 @@
static int verbose = 0;
-void cineonSetVerbose(int verbosity) {
+void cineonSetVerbose(int verbosity)
+{
verbose = verbosity;
}
@@ -74,7 +75,7 @@ static void fillCineonMainHeader(LogImageFile *cineon, CineonMainHeader *header,
strcpy(header->fileHeader.version, "v4.5");
strncpy(header->fileHeader.file_name, filename, 99);
header->fileHeader.file_name[99] = 0;
- fileClock = time(0);
+ fileClock = time(NULL);
fileTime = localtime(&fileClock);
strftime(header->fileHeader.creation_date, 12, "%Y:%m:%d", fileTime);
strftime(header->fileHeader.creation_time, 12, "%H:%M:%S%Z", fileTime);
@@ -141,28 +142,28 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t
int i;
unsigned int dataOffset;
- if (cineon == 0) {
+ if (cineon == NULL) {
if (verbose) printf("Cineon: Failed to malloc cineon file structure.\n");
- return 0;
+ return NULL;
}
/* zero the header */
memset(&header, 0, sizeof(CineonMainHeader));
/* for close routine */
- cineon->file = 0;
+ cineon->file = NULL;
if (fromMemory == 0) {
/* byteStuff is then the filename */
cineon->file = BLI_fopen(filename, "rb");
- if (cineon->file == 0) {
+ if (cineon->file == NULL) {
if (verbose) printf("Cineon: Failed to open file \"%s\".\n", filename);
logImageClose(cineon);
- return 0;
+ return NULL;
}
/* not used in this case */
- cineon->memBuffer = 0;
- cineon->memCursor = 0;
+ cineon->memBuffer = NULL;
+ cineon->memCursor = NULL;
cineon->memBufferSize = 0;
}
else {
@@ -174,7 +175,7 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t
if (logimage_fread(&header, sizeof(header), 1, cineon) == 0) {
if (verbose) printf("Cineon: Not enough data for header in \"%s\".\n", byteStuff);
logImageClose(cineon);
- return 0;
+ return NULL;
}
/* endianness determination */
@@ -190,11 +191,18 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t
if (verbose) printf("Cineon: Bad magic number %lu in \"%s\".\n",
(unsigned long)header.fileHeader.magic_num, byteStuff);
logImageClose(cineon);
- return 0;
+ return NULL;
}
cineon->width = swap_uint(header.imageHeader.element[0].pixels_per_line, cineon->isMSB);
cineon->height = swap_uint(header.imageHeader.element[0].lines_per_image, cineon->isMSB);
+
+ if (cineon->width == 0 || cineon->height == 0) {
+ if (verbose) printf("Cineon: Wrong image dimension: %dx%d\n", cineon->width, cineon->height);
+ logImageClose(cineon);
+ return NULL;
+ }
+
cineon->depth = header.imageHeader.elements_per_image;
cineon->srcFormat = format_Cineon;
@@ -204,7 +212,8 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t
cineon->numElements = header.imageHeader.elements_per_image;
else {
if (verbose) printf("Cineon: Data interleave not supported: %d\n", header.imageHeader.interleave);
- return 0;
+ logImageClose(cineon);
+ return NULL;
}
if (cineon->depth == 1) {
@@ -234,7 +243,8 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t
}
else {
if (verbose) printf("Cineon: Cineon image depth unsupported: %d\n", cineon->depth);
- return 0;
+ logImageClose(cineon);
+ return NULL;
}
dataOffset = swap_uint(header.fileHeader.offset, cineon->isMSB);
@@ -263,7 +273,8 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t
default:
/* Not supported */
if (verbose) printf("Cineon: packing unsupported: %d\n", header.imageHeader.packing);
- return 0;
+ logImageClose(cineon);
+ return NULL;
}
if (cineon->element[i].refLowData == CINEON_UNDEFINED_U32 || isnan(cineon->element[i].refLowData))
@@ -318,20 +329,20 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t
LogImageFile *cineonCreate(const char *filename, int width, int height, int bitsPerSample, const char *creator)
{
CineonMainHeader header;
- const char *shortFilename = 0;
+ const char *shortFilename = NULL;
/* unsigned char pad[6044]; */
LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
- if (cineon == 0) {
+ if (cineon == NULL) {
if (verbose) printf("cineon: Failed to malloc cineon file structure.\n");
- return 0;
+ return NULL;
}
/* Only 10 bits Cineon are supported */
if (bitsPerSample != 10) {
if (verbose) printf("cineon: Only 10 bits Cineon are supported.\n");
logImageClose(cineon);
- return 0;
+ return NULL;
}
cineon->width = width;
@@ -355,16 +366,16 @@ LogImageFile *cineonCreate(const char *filename, int width, int height, int bits
cineon->gamma = 1.7f;
shortFilename = strrchr(filename, '/');
- if (shortFilename == 0)
+ if (shortFilename == NULL)
shortFilename = filename;
else
shortFilename++;
cineon->file = BLI_fopen(filename, "wb");
- if (cineon->file == 0) {
+ if (cineon->file == NULL) {
if (verbose) printf("cineon: Couldn't open file %s\n", filename);
logImageClose(cineon);
- return 0;
+ return NULL;
}
fillCineonMainHeader(cineon, &header, shortFilename, creator);
@@ -372,7 +383,7 @@ LogImageFile *cineonCreate(const char *filename, int width, int height, int bits
if (fwrite(&header, sizeof(header), 1, cineon->file) == 0) {
if (verbose) printf("cineon: Couldn't write image header\n");
logImageClose(cineon);
- return 0;
+ return NULL;
}
return cineon;
diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c
index 4c9b5e620dd..5a4371d84ba 100644
--- a/source/blender/imbuf/intern/cineon/dpxlib.c
+++ b/source/blender/imbuf/intern/cineon/dpxlib.c
@@ -48,7 +48,8 @@
static int verbose = 0;
-void dpxSetVerbose(int verbosity) {
+void dpxSetVerbose(int verbosity)
+{
verbose = verbosity;
}
@@ -75,7 +76,7 @@ static void fillDpxMainHeader(LogImageFile *dpx, DpxMainHeader *header, const ch
header->fileHeader.user_data_size = DPX_UNDEFINED_U32;
strncpy(header->fileHeader.file_name, filename, 99);
header->fileHeader.file_name[99] = 0;
- fileClock = time(0);
+ fileClock = time(NULL);
fileTime = localtime(&fileClock);
strftime(header->fileHeader.creation_date, 24, "%Y:%m:%d:%H:%M:%S%Z", fileTime);
header->fileHeader.creation_date[23] = 0;
@@ -137,28 +138,28 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf
char *filename = (char *)byteStuff;
int i;
- if (dpx == 0) {
+ if (dpx == NULL) {
if (verbose) printf("DPX: Failed to malloc dpx file structure.\n");
- return 0;
+ return NULL;
}
/* zero the header */
memset(&header, 0, sizeof(DpxMainHeader));
/* for close routine */
- dpx->file = 0;
+ dpx->file = NULL;
if (fromMemory == 0) {
/* byteStuff is then the filename */
dpx->file = BLI_fopen(filename, "rb");
- if (dpx->file == 0) {
+ if (dpx->file == NULL) {
if (verbose) printf("DPX: Failed to open file \"%s\".\n", filename);
logImageClose(dpx);
- return 0;
+ return NULL;
}
/* not used in this case */
- dpx->memBuffer = 0;
- dpx->memCursor = 0;
+ dpx->memBuffer = NULL;
+ dpx->memCursor = NULL;
dpx->memBufferSize = 0;
}
else {
@@ -170,7 +171,7 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf
if (logimage_fread(&header, sizeof(header), 1, dpx) == 0) {
if (verbose) printf("DPX: Not enough data for header in \"%s\".\n", byteStuff);
logImageClose(dpx);
- return 0;
+ return NULL;
}
/* endianness determination */
@@ -186,13 +187,26 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf
if (verbose) printf("DPX: Bad magic number %lu in \"%s\".\n",
(uintptr_t)header.fileHeader.magic_num, byteStuff);
logImageClose(dpx);
- return 0;
+ return NULL;
}
dpx->srcFormat = format_DPX;
dpx->numElements = swap_ushort(header.imageHeader.elements_per_image, dpx->isMSB);
+ if (dpx->numElements == 0) {
+ if (verbose) printf("DPX: Wrong number of elements: %d\n", dpx->numElements);
+ logImageClose(dpx);
+ return NULL;
+ }
+
dpx->width = swap_uint(header.imageHeader.pixels_per_line, dpx->isMSB);
dpx->height = swap_uint(header.imageHeader.lines_per_element, dpx->isMSB);
+
+ if (dpx->width == 0 || dpx->height == 0) {
+ if (verbose) printf("DPX: Wrong image dimension: %dx%d\n", dpx->width, dpx->height);
+ logImageClose(dpx);
+ return NULL;
+ }
+
dpx->depth = 0;
for (i = 0; i < dpx->numElements; i++) {
@@ -237,12 +251,27 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf
if (dpx->depth == 0 || dpx->depth > 4) {
if (verbose) printf("DPX: Unsupported image depth: %d\n", dpx->depth);
logImageClose(dpx);
- return 0;
+ return NULL;
}
dpx->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample;
+ if (dpx->element[i].bitsPerSample != 1 && dpx->element[i].bitsPerSample != 8 &&
+ dpx->element[i].bitsPerSample != 10 && dpx->element[i].bitsPerSample != 12 &&
+ dpx->element[i].bitsPerSample != 16)
+ {
+ if (verbose) printf("DPX: Unsupported bitsPerSample for elements %d: %d\n", i, dpx->element[i].bitsPerSample);
+ logImageClose(dpx);
+ return NULL;
+ }
+
dpx->element[i].maxValue = powf(2, dpx->element[i].bitsPerSample) - 1.0f;
+
dpx->element[i].packing = swap_ushort(header.imageHeader.element[i].packing, dpx->isMSB);
+ if (dpx->element[i].packing > 2) {
+ if (verbose) printf("DPX: Unsupported packing for element %d: %d\n", i, dpx->element[i].packing);
+ logImageClose(dpx);
+ return NULL;
+ }
/* Sometimes, the offset is not set correctly in the header */
dpx->element[i].dataOffset = swap_uint(header.imageHeader.element[i].data_offset, dpx->isMSB);
@@ -252,7 +281,7 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf
if (dpx->element[i].dataOffset == 0) {
if (verbose) printf("DPX: Image header is corrupted.\n");
logImageClose(dpx);
- return 0;
+ return NULL;
}
dpx->element[i].transfer = header.imageHeader.element[i].transfer;
@@ -322,7 +351,6 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf
(dpx->referenceWhite == DPX_UNDEFINED_R32 || dpx->referenceWhite <= dpx->referenceBlack || isnan(dpx->referenceWhite)) ||
(dpx->gamma == DPX_UNDEFINED_R32 || dpx->gamma <= 0 || isnan(dpx->gamma)))
{
-
dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue;
dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue;
dpx->gamma = 1.7f;
@@ -358,13 +386,13 @@ LogImageFile *dpxCreate(const char *filename, int width, int height, int bitsPer
const char *creator)
{
DpxMainHeader header;
- const char *shortFilename = 0;
+ const char *shortFilename = NULL;
unsigned char pad[6044];
LogImageFile *dpx = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__);
- if (dpx == 0) {
+ if (dpx == NULL) {
if (verbose) printf("DPX: Failed to malloc dpx file structure.\n");
- return 0;
+ return NULL;
}
dpx->width = width;
@@ -390,7 +418,7 @@ LogImageFile *dpxCreate(const char *filename, int width, int height, int bitsPer
default:
if (verbose) printf("DPX: bitsPerSample not supported: %d\n", bitsPerSample);
logImageClose(dpx);
- return 0;
+ return NULL;
}
if (hasAlpha == 0) {
@@ -435,17 +463,17 @@ LogImageFile *dpxCreate(const char *filename, int width, int height, int bitsPer
shortFilename = strrchr(filename, '/');
- if (shortFilename == 0)
+ if (shortFilename == NULL)
shortFilename = filename;
else
shortFilename++;
dpx->file = BLI_fopen(filename, "wb");
- if (dpx->file == 0) {
+ if (dpx->file == NULL) {
if (verbose) printf("DPX: Couldn't open file %s\n", filename);
logImageClose(dpx);
- return 0;
+ return NULL;
}
fillDpxMainHeader(dpx, &header, shortFilename, creator);
@@ -453,7 +481,7 @@ LogImageFile *dpxCreate(const char *filename, int width, int height, int bitsPer
if (fwrite(&header, sizeof(header), 1, dpx->file) == 0) {
if (verbose) printf("DPX: Couldn't write image header\n");
logImageClose(dpx);
- return 0;
+ return NULL;
}
/* Header should be rounded to next 8k block
@@ -462,7 +490,7 @@ LogImageFile *dpxCreate(const char *filename, int width, int height, int bitsPer
if (fwrite(&pad, 6044, 1, dpx->file) == 0) {
if (verbose) printf("DPX: Couldn't write image header\n");
logImageClose(dpx);
- return 0;
+ return NULL;
}
return dpx;
diff --git a/source/blender/imbuf/intern/cineon/logImageCore.c b/source/blender/imbuf/intern/cineon/logImageCore.c
index 3911e5c2ef3..c10f201fb55 100644
--- a/source/blender/imbuf/intern/cineon/logImageCore.c
+++ b/source/blender/imbuf/intern/cineon/logImageCore.c
@@ -97,12 +97,12 @@ LogImageFile *logImageOpenFromFile(const char *filename, int cineon)
(void)cineon;
- if (f == 0)
- return 0;
+ if (f == NULL)
+ return NULL;
if (fread(&magicNum, sizeof(unsigned int), 1, f) != 1) {
fclose(f);
- return 0;
+ return NULL;
}
fclose(f);
@@ -112,7 +112,7 @@ LogImageFile *logImageOpenFromFile(const char *filename, int cineon)
else if (logImageIsCineon(&magicNum))
return cineonOpen((const unsigned char *)filename, 0, 0);
- return 0;
+ return NULL;
}
LogImageFile *logImageOpenFromMemory(const unsigned char *buffer, unsigned int size)
@@ -122,7 +122,7 @@ LogImageFile *logImageOpenFromMemory(const unsigned char *buffer, unsigned int s
else if (logImageIsCineon(buffer))
return cineonOpen(buffer, 1, size);
- return 0;
+ return NULL;
}
LogImageFile *logImageCreate(const char *filename, int cineon, int width, int height, int bitsPerSample,
@@ -136,15 +136,15 @@ LogImageFile *logImageCreate(const char *filename, int cineon, int width, int he
return dpxCreate(filename, width, height, bitsPerSample, isLogarithmic, hasAlpha,
referenceWhite, referenceBlack, gamma, creator);
- return 0;
+ return NULL;
}
void logImageClose(LogImageFile *logImage)
{
- if (logImage != 0) {
+ if (logImage != NULL) {
if (logImage->file) {
fclose(logImage->file);
- logImage->file = 0;
+ logImage->file = NULL;
}
MEM_freeN(logImage);
}
@@ -203,7 +203,7 @@ int logImageSetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB
int returnValue;
elementData = (float *)MEM_mallocN(logImage->width * logImage->height * logImage->depth * sizeof(float), __func__);
- if (elementData == 0)
+ if (elementData == NULL)
return 1;
if (convertRGBAToLogElement(data, elementData, logImage, logImage->element[0], dataIsLinearRGB) != 0) {
@@ -244,7 +244,7 @@ static int logImageSetData8(LogImageFile *logImage, LogImageElement logElement,
int x, y;
row = (unsigned char *)MEM_mallocN(rowLength, __func__);
- if (row == 0) {
+ if (row == NULL) {
if (verbose) printf("DPX/Cineon: Cannot allocate row.\n");
return 1;
}
@@ -272,7 +272,7 @@ static int logImageSetData10(LogImageFile *logImage, LogImageElement logElement,
int x, y, offset;
row = (unsigned int *)MEM_mallocN(rowLength, __func__);
- if (row == 0) {
+ if (row == NULL) {
if (verbose) printf("DPX/Cineon: Cannot allocate row.\n");
return 1;
}
@@ -313,7 +313,7 @@ static int logImageSetData12(LogImageFile *logImage, LogImageElement logElement,
int x, y;
row = (unsigned short *)MEM_mallocN(rowLength, __func__);
- if (row == 0) {
+ if (row == NULL) {
if (verbose) printf("DPX/Cineon: Cannot allocate row.\n");
return 1;
}
@@ -339,7 +339,7 @@ static int logImageSetData16(LogImageFile *logImage, LogImageElement logElement,
int x, y;
row = (unsigned short *)MEM_mallocN(rowLength, __func__);
- if (row == 0) {
+ if (row == NULL) {
if (verbose) printf("DPX/Cineon: Cannot allocate row.\n");
return 1;
}
@@ -374,7 +374,7 @@ int logImageGetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB
LogImageElement mergedElement;
/* Determine the depth of the picture and if there's a separate alpha element.
- If the element is supported, load it into an unsigned ints array. */
+ * If the element is supported, load it into an unsigned ints array. */
memset(&elementData, 0, 8 * sizeof(float *));
hasAlpha = 0;
@@ -383,10 +383,10 @@ int logImageGetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB
if (logImage->element[i].descriptor != descriptor_Depth && logImage->element[i].descriptor != descriptor_Composite) {
/* Allocate memory */
elementData[i] = (float *)MEM_mallocN(logImage->width * logImage->height * logImage->element[i].depth * sizeof(float), __func__);
- if (elementData[i] == 0) {
+ if (elementData[i] == NULL) {
if (verbose) printf("DPX/Cineon: Cannot allocate memory for elementData[%d]\n.", i);
for (j = 0; j < i; j++)
- if (elementData[j] != 0)
+ if (elementData[j] != NULL)
MEM_freeN(elementData[j]);
return 1;
}
@@ -396,7 +396,7 @@ int logImageGetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB
if (logImageElementGetData(logImage, logImage->element[i], elementData[i]) != 0) {
if (verbose) printf("DPX/Cineon: Cannot read elementData[%d]\n.", i);
for (j = 0; j < i; j++)
- if (elementData[j] != 0)
+ if (elementData[j] != NULL)
MEM_freeN(elementData[j]);
return 1;
}
@@ -531,10 +531,10 @@ int logImageGetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB
}
mergedData = (float *)MEM_mallocN(logImage->width * logImage->height * mergedElement.depth * sizeof(float), __func__);
- if (mergedData == 0) {
+ if (mergedData == NULL) {
if (verbose) printf("DPX/Cineon: Cannot allocate mergedData.\n");
for (i = 0; i < logImage->numElements; i++)
- if (elementData[i] != 0)
+ if (elementData[i] != NULL)
MEM_freeN(elementData[i]);
return 1;
}
@@ -548,7 +548,7 @@ int logImageGetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB
/* Done with elements data, clean-up */
for (i = 0; i < logImage->numElements; i++)
- if (elementData[i] != 0)
+ if (elementData[i] != NULL)
MEM_freeN(elementData[i]);
returnValue = convertLogElementToRGBA(mergedData, data, logImage, mergedElement, dataIsLinearRGB);
@@ -1383,7 +1383,7 @@ static int convertRGBAToLogElement(float *src, float *dst, LogImageFile *logImag
if (srcIsLinearRGB != 0) {
/* we need to convert src to sRGB */
srgbSrc = (float *)MEM_mallocN(4 * logImage->width * logImage->height * sizeof(float), __func__);
- if (srgbSrc == 0)
+ if (srgbSrc == NULL)
return 1;
memcpy(srgbSrc, src, 4 * logImage->width * logImage->height * sizeof(float));
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index 1c68a466ade..aa3dd05dbd1 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -57,6 +57,7 @@
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_threads.h"
+#include "BLI_rect.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
@@ -70,7 +71,6 @@
/*********************** Global declarations *************************/
-#define MAX_COLORSPACE_NAME 64
#define DISPLAY_BUFFER_CHANNELS 4
/* ** list of all supported color spaces, displays and views */
@@ -189,7 +189,6 @@ typedef struct ColormnaageCacheData {
int flag; /* view flags of cached buffer */
float exposure; /* exposure value cached buffer is calculated with */
float gamma; /* gamma value cached buffer is calculated with */
- int predivide; /* predivide flag of cached buffer */
CurveMapping *curve_mapping; /* curve mapping used for cached buffer */
int curve_mapping_timestamp; /* time stamp of curve mapping used for cached buffer */
} ColormnaageCacheData;
@@ -323,7 +322,6 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV
ColormanageCacheKey key;
ImBuf *cache_ibuf;
int view_flag = 1 << (view_settings->view - 1);
- int predivide = ibuf->flags & IB_cm_predivide;
CurveMapping *curve_mapping = view_settings->curve_mapping;
int curve_mapping_timestamp = curve_mapping ? curve_mapping->changed_timestamp : 0;
@@ -353,10 +351,9 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV
if (cache_data->exposure != view_settings->exposure ||
cache_data->gamma != view_settings->gamma ||
- cache_data->predivide != predivide ||
- cache_data->flag != view_settings->flag ||
- cache_data->curve_mapping != curve_mapping ||
- cache_data->curve_mapping_timestamp != curve_mapping_timestamp)
+ cache_data->flag != view_settings->flag ||
+ cache_data->curve_mapping != curve_mapping ||
+ cache_data->curve_mapping_timestamp != curve_mapping_timestamp)
{
*cache_handle = NULL;
@@ -379,7 +376,6 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting
ImBuf *cache_ibuf;
ColormnaageCacheData *cache_data;
int view_flag = 1 << (view_settings->view - 1);
- int predivide = ibuf->flags & IB_cm_predivide;
struct MovieCache *moviecache = colormanage_moviecache_ensure(ibuf);
CurveMapping *curve_mapping = view_settings->curve_mapping;
int curve_mapping_timestamp = curve_mapping ? curve_mapping->changed_timestamp : 0;
@@ -400,7 +396,6 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting
cache_data = MEM_callocN(sizeof(ColormnaageCacheData), "color manage cache imbuf data");
cache_data->exposure = view_settings->exposure;
cache_data->gamma = view_settings->gamma;
- cache_data->predivide = predivide;
cache_data->flag = view_settings->flag;
cache_data->curve_mapping = curve_mapping;
cache_data->curve_mapping_timestamp = curve_mapping_timestamp;
@@ -686,7 +681,7 @@ static ColorSpace *display_transform_get_colorspace(const ColorManagedViewSettin
}
static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *view_transform, const char *display,
- float exposure, float gamma)
+ float exposure, float gamma)
{
OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig();
OCIO_DisplayTransformRcPtr *dt;
@@ -703,7 +698,7 @@ static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *vie
if (exposure != 0.0f) {
OCIO_MatrixTransformRcPtr *mt;
float gain = powf(2.0f, exposure);
- const float scale4f[] = {gain, gain, gain, gain};
+ const float scale4f[] = {gain, gain, gain, 1.0f};
float m44[16], offset4[4];
OCIO_matrixTransformScale(m44, offset4, scale4f);
@@ -736,7 +731,7 @@ static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *vie
}
static OCIO_ConstProcessorRcPtr *create_colorspace_transform_processor(const char *from_colorspace,
- const char *to_colorspace)
+ const char *to_colorspace)
{
OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig();
OCIO_ConstProcessorRcPtr *processor;
@@ -897,13 +892,12 @@ void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace)
if (ibuf->rect_float) {
const char *to_colorspace = global_role_scene_linear;
- int predivide = ibuf->flags & IB_cm_predivide;
if (ibuf->rect)
imb_freerectImBuf(ibuf);
IMB_colormanagement_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
- from_colorspace, to_colorspace, predivide);
+ from_colorspace, to_colorspace, TRUE);
}
}
@@ -1130,7 +1124,6 @@ typedef struct DisplayBufferThread {
int channels;
float dither;
- int predivide;
int is_data;
const char *byte_colorspace;
@@ -1158,7 +1151,6 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l
DisplayBufferInitData *init_data = (DisplayBufferInitData *) init_data_v;
ImBuf *ibuf = init_data->ibuf;
- int predivide = ibuf->flags & IB_cm_predivide;
int channels = ibuf->channels;
float dither = ibuf->dither;
int is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA;
@@ -1189,7 +1181,6 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l
handle->channels = channels;
handle->dither = dither;
- handle->predivide = predivide;
handle->is_data = is_data;
handle->byte_colorspace = init_data->byte_colorspace;
@@ -1206,7 +1197,6 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle)
int buffer_size = channels * width * height;
- int predivide = handle->predivide;
int is_data = handle->is_data;
int is_data_display = handle->cm_processor->is_data_result;
@@ -1224,16 +1214,25 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle)
/* first convert byte buffer to float, keep in image space */
for (i = 0, fp = linear_buffer, cp = byte_buffer;
- i < channels * width * height;
- i++, fp++, cp++)
+ i < width * height;
+ i++, fp += channels, cp += channels)
{
- *fp = (float)(*cp) / 255.0f;
+ if (channels == 3) {
+ rgb_uchar_to_float(fp, cp);
+ }
+ else if (channels == 4) {
+ rgba_uchar_to_float(fp, cp);
+ straight_to_premul_v4(fp);
+ }
+ else {
+ BLI_assert(!"Buffers of 3 or 4 channels are only supported here");
+ }
}
if (!is_data && !is_data_display) {
/* convert float buffer to scene linear space */
IMB_colormanagement_transform(linear_buffer, width, height, channels,
- from_colorspace, to_colorspace, predivide);
+ from_colorspace, to_colorspace, TRUE);
}
}
else if (handle->float_colorspace) {
@@ -1249,7 +1248,7 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle)
memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float));
IMB_colormanagement_transform(linear_buffer, width, height, channels,
- from_colorspace, to_colorspace, predivide);
+ from_colorspace, to_colorspace, TRUE);
}
else {
/* some processors would want to modify float original buffer
@@ -1277,13 +1276,12 @@ static void *do_display_buffer_apply_thread(void *handle_v)
int width = handle->width;
int height = handle->tot_line;
float dither = handle->dither;
- int predivide = handle->predivide;
int is_data = handle->is_data;
if (cm_processor == NULL) {
if (display_buffer_byte) {
IMB_buffer_byte_from_byte(display_buffer_byte, handle->byte_buffer, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
- FALSE, width, height, width, width);
+ FALSE, width, height, width, width);
}
if (display_buffer) {
@@ -1301,7 +1299,7 @@ static void *do_display_buffer_apply_thread(void *handle_v)
}
else {
/* apply processor */
- IMB_colormanagement_processor_apply(cm_processor, linear_buffer, width, height, channels, predivide);
+ IMB_colormanagement_processor_apply(cm_processor, linear_buffer, width, height, channels, TRUE);
}
/* copy result to output buffers */
@@ -1309,7 +1307,7 @@ static void *do_display_buffer_apply_thread(void *handle_v)
/* do conversion */
IMB_buffer_byte_from_float(display_buffer_byte, linear_buffer,
channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
- predivide, width, height, width, width);
+ TRUE, width, height, width, width);
}
if (display_buffer)
@@ -1355,6 +1353,23 @@ static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned c
display_buffer_init_handle, do_display_buffer_apply_thread);
}
+static int is_ibuf_rect_in_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings)
+{
+ if ((view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) == 0 &&
+ view_settings->exposure == 0.0f &&
+ view_settings->gamma == 1.0f)
+ {
+ const char *from_colorspace = ibuf->rect_colorspace->name;
+ const char *to_colorspace = display_transform_get_colorspace_name(view_settings, display_settings);
+
+ if (to_colorspace && !strcmp(from_colorspace, to_colorspace))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_buffer, unsigned char *display_buffer_byte,
const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings)
@@ -1368,16 +1383,7 @@ static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_bu
* computation noticeable faster
*/
if (ibuf->rect_float == NULL && ibuf->rect_colorspace) {
- if ((view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) == 0 &&
- view_settings->exposure == 0.0f &&
- view_settings->gamma == 1.0f)
- {
- const char *from_colorspace = ibuf->rect_colorspace->name;
- const char *to_colorspace = display_transform_get_colorspace_name(view_settings, display_settings);
-
- if (to_colorspace && !strcmp(from_colorspace, to_colorspace))
- skip_transform = TRUE;
- }
+ skip_transform = is_ibuf_rect_in_display_space(ibuf, view_settings, display_settings);
}
if (skip_transform == FALSE)
@@ -1577,6 +1583,26 @@ void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], ColorSpac
OCIO_processorApplyRGB(processor, pixel);
}
+void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4], int predivide, ColorSpace *colorspace)
+{
+ OCIO_ConstProcessorRcPtr *processor;
+
+ if (!colorspace) {
+ /* should never happen */
+ printf("%s: perform conversion from unknown color space\n", __func__);
+ return;
+ }
+
+ processor = colorspace_to_scene_linear_processor(colorspace);
+
+ if (processor) {
+ if (predivide)
+ OCIO_processorApplyRGBA_predivide(processor, pixel);
+ else
+ OCIO_processorApplyRGBA(processor, pixel);
+ }
+}
+
void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, int predivide)
{
OCIO_ConstProcessorRcPtr *processor;
@@ -1593,14 +1619,14 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, in
OCIO_PackedImageDesc *img;
img = OCIO_createOCIO_PackedImageDesc(buffer, width, height, channels, sizeof(float),
- channels * sizeof(float), channels * sizeof(float) * width);
+ channels * sizeof(float), channels * sizeof(float) * width);
if (predivide)
OCIO_processorApply_predivide(processor, img);
else
OCIO_processorApply(processor, img);
- OCIO_OCIO_PackedImageDescRelease(img);
+ OCIO_PackedImageDescRelease(img);
}
}
@@ -1663,7 +1689,7 @@ static void colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorMan
if (global_tot_display == 0 || global_tot_view == 0) {
IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float, ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB,
- ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+ TRUE, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
}
else {
colormanage_display_buffer_process_ex(ibuf, ibuf->rect_float, (unsigned char *)ibuf->rect,
@@ -1693,15 +1719,13 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, int save_as_render, int
{
ImBuf *colormanaged_ibuf = ibuf;
int do_colormanagement;
- int is_movie = BKE_imtype_is_movie(image_format_data->imtype);
+ bool is_movie = BKE_imtype_is_movie(image_format_data->imtype);
int requires_linear_float = BKE_imtype_requires_linear_float(image_format_data->imtype);
+ int do_alpha_under = image_format_data->planes != R_IMF_PLANES_RGBA;
do_colormanagement = save_as_render && (is_movie || !requires_linear_float);
- if (do_colormanagement) {
- int make_byte = FALSE;
- ImFileType *type;
-
+ if (do_colormanagement || do_alpha_under) {
if (allocate_result) {
colormanaged_ibuf = IMB_dupImBuf(ibuf);
}
@@ -1720,6 +1744,41 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, int save_as_render, int
ibuf->mall |= IB_rectfloat;
}
}
+ }
+
+ /* If we're saving from RGBA to RGB buffer then it's not
+ * so much useful to just ignore alpha -- it leads to bad
+ * artifacts especially when saving byte images.
+ *
+ * What we do here is we're overing our image on top of
+ * background color (which is currently black).
+ *
+ * This is quite much the same as what Gimp does and it
+ * seems to be what artists expects from saving.
+ *
+ * Do a conversion here, so image format writers could
+ * happily assume all the alpha tricks were made already.
+ * helps keep things locally here, not spreading it to
+ * all possible image writers we've got.
+ */
+ if (do_alpha_under) {
+ float color[3] = {0, 0, 0};
+
+ if (colormanaged_ibuf->rect_float && colormanaged_ibuf->channels == 4) {
+ IMB_alpha_under_color_float(colormanaged_ibuf->rect_float, colormanaged_ibuf->x,
+ colormanaged_ibuf->y, color);
+ }
+
+ if (colormanaged_ibuf->rect) {
+ IMB_alpha_under_color_byte((unsigned char *)colormanaged_ibuf->rect,
+ colormanaged_ibuf->x, colormanaged_ibuf->y,
+ color);
+ }
+ }
+
+ if (do_colormanagement) {
+ int make_byte = FALSE;
+ 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
@@ -1814,9 +1873,29 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet
applied_view_settings = &default_view_settings;
}
+ /* early out: no float buffer and byte buffer is already in display space,
+ * let's just use if
+ */
+ if (ibuf->rect_float == NULL && ibuf->rect_colorspace) {
+ if (is_ibuf_rect_in_display_space(ibuf, applied_view_settings, display_settings))
+ return (unsigned char *) ibuf->rect;
+ }
+
colormanage_view_settings_to_cache(&cache_view_settings, applied_view_settings);
colormanage_display_settings_to_cache(&cache_display_settings, display_settings);
+ if (ibuf->invalid_rect.xmin != ibuf->invalid_rect.xmax) {
+ if ((ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) == 0) {
+ IMB_partial_display_buffer_update(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect,
+ ibuf->x, 0, 0, applied_view_settings, display_settings,
+ ibuf->invalid_rect.xmin, ibuf->invalid_rect.ymin,
+ ibuf->invalid_rect.xmax, ibuf->invalid_rect.ymax,
+ FALSE);
+ }
+
+ BLI_rcti_init(&ibuf->invalid_rect, 0, 0, 0, 0);
+ }
+
BLI_lock_thread(LOCK_COLORMANAGE);
/* ensure color management bit fields exists */
@@ -2112,7 +2191,7 @@ static void colormanage_description_strip(char *description)
{
int i, n;
- for (i = strlen(description) - 1; i >= 0; i--) {
+ for (i = (int)strlen(description) - 1; i >= 0; i--) {
if (ELEM(description[i], '\r', '\n')) {
description[i] = '\0';
}
@@ -2326,7 +2405,6 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
{
int x, y;
int channels = ibuf->channels;
- int predivide = ibuf->flags & IB_cm_predivide;
float dither = ibuf->dither;
ColorSpace *rect_colorspace = ibuf->rect_colorspace;
float *display_buffer_float = NULL;
@@ -2335,37 +2413,67 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
int is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA;
if (dither != 0.0f) {
+ /* cm_processor is NULL in cases byte_buffer's space matches display
+ * buffer's space
+ * in this case we could skip extra transform and only apply dither
+ * use 4 channels for easier byte->float->byte conversion here so
+ * (this is only needed to apply dither, in other cases we'll convert
+ * byte buffer to display directly)
+ */
+ if (!cm_processor)
+ channels = 4;
+
display_buffer_float = MEM_callocN(channels * width * height * sizeof(float), "display buffer for dither");
}
- for (y = ymin; y < ymax; y++) {
- for (x = xmin; x < xmax; x++) {
- int display_index = (y * display_stride + x) * channels;
- int linear_index = ((y - linear_offset_y) * linear_stride + (x - linear_offset_x)) * channels;
- float pixel[4];
-
- if (linear_buffer) {
- copy_v4_v4(pixel, (float *) linear_buffer + linear_index);
- }
- else if (byte_buffer) {
- rgba_uchar_to_float(pixel, byte_buffer + linear_index);
- IMB_colormanagement_colorspace_to_scene_linear_v3(pixel, rect_colorspace);
- }
-
- if (!is_data) {
- if (predivide)
- IMB_colormanagement_processor_apply_v4(cm_processor, pixel);
- else
- IMB_colormanagement_processor_apply_v4(cm_processor, pixel);
+ if (cm_processor) {
+ for (y = ymin; y < ymax; y++) {
+ for (x = xmin; x < xmax; x++) {
+ int display_index = (y * display_stride + x) * channels;
+ int linear_index = ((y - linear_offset_y) * linear_stride + (x - linear_offset_x)) * channels;
+ float pixel[4];
+
+ if (linear_buffer) {
+ copy_v4_v4(pixel, (float *) linear_buffer + linear_index);
+ }
+ else if (byte_buffer) {
+ rgba_uchar_to_float(pixel, byte_buffer + linear_index);
+ IMB_colormanagement_colorspace_to_scene_linear_v3(pixel, rect_colorspace);
+ straight_to_premul_v4(pixel);
+ }
+
+ if (!is_data) {
+ IMB_colormanagement_processor_apply_v4_predivide(cm_processor, pixel);
+ }
+
+ if (display_buffer_float) {
+ int index = ((y - ymin) * width + (x - xmin)) * channels;
+
+ copy_v4_v4(display_buffer_float + index, pixel);
+ }
+ else {
+ float pixel_straight[4];
+ premul_to_straight_v4_v4(pixel_straight, pixel);
+ rgba_float_to_uchar(display_buffer + display_index, pixel_straight);
+ }
}
+ }
+ }
+ else {
+ if (display_buffer_float) {
+ /* huh, for dither we need float buffer first, no cheaper way. currently */
+ IMB_buffer_float_from_byte(display_buffer_float, byte_buffer,
+ IB_PROFILE_SRGB, IB_PROFILE_SRGB, TRUE,
+ width, height, width, display_stride);
+ }
+ else {
+ int i, width = xmax - xmin;
- if (display_buffer_float) {
- int index = ((y - ymin) * width + (x - xmin)) * channels;
+ for (i = ymin; i < ymax; i++) {
+ int byte_offset = (linear_stride * i + xmin) * 4;
+ int display_offset = (display_stride * i + xmin) * 4;
- copy_v4_v4(display_buffer_float + index, pixel);
- }
- else {
- rgba_float_to_uchar(display_buffer + display_index, pixel);
+ memcpy(display_buffer + display_offset, byte_buffer + byte_offset, 4 * sizeof(char) * width);
}
}
}
@@ -2374,7 +2482,7 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
int display_index = (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, FALSE, width, height, display_stride, width);
+ IB_PROFILE_SRGB, IB_PROFILE_SRGB, TRUE, width, height, display_stride, width);
MEM_freeN(display_buffer_float);
}
@@ -2389,7 +2497,6 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
/* update byte buffer created by legacy color management */
unsigned char *rect = (unsigned char *) ibuf->rect;
- int predivide = ibuf->flags & IB_cm_predivide;
int channels = ibuf->channels;
int width = xmax - xmin;
int height = ymax - ymin;
@@ -2397,7 +2504,7 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
int linear_index = ((ymin - offset_y) * stride + (xmin - offset_x)) * channels;
IMB_buffer_byte_from_float(rect + rect_index, linear_buffer + linear_index, channels, ibuf->dither,
- IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide, width, height, ibuf->x, stride);
+ IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, TRUE, width, height, ibuf->x, stride);
}
if (ibuf->display_buffer_flags) {
@@ -2430,20 +2537,42 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
BLI_unlock_thread(LOCK_COLORMANAGE);
if (display_buffer) {
- ColormanageProcessor *cm_processor;
+ ColormanageProcessor *cm_processor = NULL;
+ int skip_transform = 0;
- cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
+ /* byte buffer is assumed to be in imbuf's rect space, so if byte buffer
+ * is known we could skip display->linear->display conversion in case
+ * display color space matches imbuf's rect space
+ */
+ if (byte_buffer != NULL)
+ skip_transform = is_ibuf_rect_in_display_space(ibuf, view_settings, display_settings);
+
+ if (!skip_transform)
+ cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
partial_buffer_update_rect(ibuf, display_buffer, linear_buffer, byte_buffer, buffer_width, stride,
offset_x, offset_y, cm_processor, xmin, ymin, xmax, ymax);
- IMB_colormanagement_processor_free(cm_processor);
+ if (cm_processor)
+ IMB_colormanagement_processor_free(cm_processor);
IMB_display_buffer_release(cache_handle);
}
}
}
+void IMB_partial_display_buffer_update_delayed(ImBuf *ibuf, int xmin, int ymin, int xmax, int ymax)
+{
+ if (ibuf->invalid_rect.xmin == ibuf->invalid_rect.xmax) {
+ BLI_rcti_init(&ibuf->invalid_rect, xmin, xmax, ymin, ymax);
+ }
+ else {
+ rcti rect;
+ BLI_rcti_init(&rect, xmin, xmax, ymin, ymax);
+ BLI_rcti_union(&ibuf->invalid_rect, &rect);
+ }
+}
+
/*********************** Pixel processor functions *************************/
ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManagedViewSettings *view_settings,
@@ -2503,6 +2632,15 @@ void IMB_colormanagement_processor_apply_v4(ColormanageProcessor *cm_processor,
OCIO_processorApplyRGBA(cm_processor->processor, pixel);
}
+void IMB_colormanagement_processor_apply_v4_predivide(ColormanageProcessor *cm_processor, float pixel[4])
+{
+ if (cm_processor->curve_mapping)
+ curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel);
+
+ if (cm_processor->processor)
+ OCIO_processorApplyRGBA_predivide(cm_processor->processor, pixel);
+}
+
void IMB_colormanagement_processor_apply_v3(ColormanageProcessor *cm_processor, float pixel[3])
{
if (cm_processor->curve_mapping)
@@ -2533,14 +2671,14 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, flo
/* apply OCIO processor */
img = OCIO_createOCIO_PackedImageDesc(buffer, width, height, channels, sizeof(float),
- channels * sizeof(float), channels * sizeof(float) * width);
+ channels * sizeof(float), channels * sizeof(float) * width);
if (predivide)
OCIO_processorApply_predivide(cm_processor->processor, img);
else
OCIO_processorApply(cm_processor->processor, img);
- OCIO_OCIO_PackedImageDescRelease(img);
+ OCIO_PackedImageDescRelease(img);
}
}
diff --git a/source/blender/imbuf/intern/dds/BlockDXT.cpp b/source/blender/imbuf/intern/dds/BlockDXT.cpp
index db2ca5969ec..348e1e9f53a 100644
--- a/source/blender/imbuf/intern/dds/BlockDXT.cpp
+++ b/source/blender/imbuf/intern/dds/BlockDXT.cpp
@@ -250,7 +250,7 @@ void BlockDXT1::decodeBlockNV5x(ColorBlock * block) const
}
}
-void BlockDXT1::setIndices(int * idx)
+void BlockDXT1::setIndices(int *idx)
{
indices = 0;
for (uint i = 0; i < 16; i++) {
@@ -595,7 +595,7 @@ void BlockCTX1::decodeBlock(ColorBlock * block) const
}
}
-void BlockCTX1::setIndices(int * idx)
+void BlockCTX1::setIndices(int *idx)
{
indices = 0;
for (uint i = 0; i < 16; i++) {
diff --git a/source/blender/imbuf/intern/dds/ColorBlock.h b/source/blender/imbuf/intern/dds/ColorBlock.h
index f0864f06e6f..730a19d84fd 100644
--- a/source/blender/imbuf/intern/dds/ColorBlock.h
+++ b/source/blender/imbuf/intern/dds/ColorBlock.h
@@ -69,7 +69,7 @@ struct ColorBlock
private:
- Color32 m_color[4*4];
+ Color32 m_color[4 * 4];
};
diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
index ccf72f9af86..df15cb3e357 100644
--- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
+++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
@@ -1092,7 +1092,7 @@ void DirectDrawSurface::setUserVersion(int version)
header.setUserVersion(version);
}
-void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap)
+void DirectDrawSurface::mipmap(Image *img, uint face, uint mipmap)
{
stream.seek(offset(face, mipmap));
@@ -1158,7 +1158,7 @@ void* DirectDrawSurface::readData(uint &rsize)
return data;
}
-void DirectDrawSurface::readLinearImage(Image * img)
+void DirectDrawSurface::readLinearImage(Image *img)
{
const uint w = img->width();
@@ -1204,7 +1204,7 @@ void DirectDrawSurface::readLinearImage(Image * img)
}
}
-void DirectDrawSurface::readBlockImage(Image * img)
+void DirectDrawSurface::readBlockImage(Image *img)
{
const uint w = img->width();
@@ -1246,7 +1246,7 @@ static Color32 buildNormal(uint8 x, uint8 y)
}
-void DirectDrawSurface::readBlock(ColorBlock * rgba)
+void DirectDrawSurface::readBlock(ColorBlock *rgba)
{
uint fourcc = header.pf.fourcc;
diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.h b/source/blender/imbuf/intern/dds/DirectDrawSurface.h
index 72a524daba2..11e6d4a5708 100644
--- a/source/blender/imbuf/intern/dds/DirectDrawSurface.h
+++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.h
@@ -172,7 +172,7 @@ public:
void setUserVersion(int version);
void mipmap(Image * img, uint f, uint m);
- void* readData(uint &size);
+ void *readData(uint &size);
// void mipmap(FloatImage * img, uint f, uint m);
void printInfo() const;
diff --git a/source/blender/imbuf/intern/dds/FlipDXT.cpp b/source/blender/imbuf/intern/dds/FlipDXT.cpp
index 05821b27ca6..4f63d17dc90 100644
--- a/source/blender/imbuf/intern/dds/FlipDXT.cpp
+++ b/source/blender/imbuf/intern/dds/FlipDXT.cpp
@@ -147,10 +147,10 @@ static void FlipDXT5BlockFull(uint8_t *block)
block[2] = line_3_2 & 0xff;
block[3] = (line_3_2 & 0xff00) >> 8;
- block[4] = (line_3_2 & 0xff0000) >> 8;
+ block[4] = (line_3_2 & 0xff0000) >> 16;
block[5] = line_1_0 & 0xff;
block[6] = (line_1_0 & 0xff00) >> 8;
- block[7] = (line_1_0 & 0xff0000) >> 8;
+ block[7] = (line_1_0 & 0xff0000) >> 16;
// And flip the DXT1 block using the above function.
FlipDXT1BlockFull(block + 8);
@@ -165,7 +165,7 @@ static void FlipDXT5BlockHalf(uint8_t *block)
((line_0_1 & 0xfff000) >> 12);
block[2] = line_1_0 & 0xff;
block[3] = (line_1_0 & 0xff00) >> 8;
- block[4] = (line_1_0 & 0xff0000) >> 8;
+ block[4] = (line_1_0 & 0xff0000) >> 16;
FlipDXT1BlockHalf(block + 8);
}
@@ -241,7 +241,7 @@ int FlipDXTCImage(unsigned int width, unsigned int height, unsigned int levels,
memcpy(line2, temp_line, row_bytes);
}
- delete temp_line;
+ delete[] temp_line;
}
// mip levels are contiguous.
diff --git a/source/blender/imbuf/intern/dds/SConscript b/source/blender/imbuf/intern/dds/SConscript
index 475d21135aa..960e15f8e55 100644
--- a/source/blender/imbuf/intern/dds/SConscript
+++ b/source/blender/imbuf/intern/dds/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
source_files = ['dds_api.cpp', 'DirectDrawSurface.cpp', 'Stream.cpp', 'BlockDXT.cpp', 'ColorBlock.cpp', 'Image.cpp', 'FlipDXT.cpp']
diff --git a/source/blender/imbuf/intern/dds/Stream.cpp b/source/blender/imbuf/intern/dds/Stream.cpp
index 00e1b679c69..57a251261a1 100644
--- a/source/blender/imbuf/intern/dds/Stream.cpp
+++ b/source/blender/imbuf/intern/dds/Stream.cpp
@@ -47,7 +47,7 @@ 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?)");
return(0);
- };
+ }
memcpy(&i, mem.mem + mem.pos, 8); // @@ todo: make sure little endian
mem.pos += 8;
return(8);
@@ -58,7 +58,7 @@ 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?)");
return(0);
- };
+ }
memcpy(&i, mem.mem + mem.pos, 4); // @@ todo: make sure little endian
mem.pos += 4;
return(4);
@@ -69,7 +69,7 @@ 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?)");
return(0);
- };
+ }
memcpy(&i, mem.mem + mem.pos, 2); // @@ todo: make sure little endian
mem.pos += 2;
return(2);
@@ -80,7 +80,7 @@ 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?)");
return(0);
- };
+ }
i = (mem.mem + mem.pos)[0];
mem.pos += 1;
return(1);
@@ -91,7 +91,7 @@ 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?)");
return(0);
- };
+ }
memcpy(i, mem.mem + mem.pos, cnt);
mem.pos += cnt;
return(cnt);
diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp
index 5459cffe590..0c240f16227 100644
--- a/source/blender/imbuf/intern/dds/dds_api.cpp
+++ b/source/blender/imbuf/intern/dds/dds_api.cpp
@@ -96,7 +96,7 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags, char colo
Color32 pixel;
Color32 *pixels = 0;
- /* OCIO_TODO: never was able to save DDS, so can'ttest loading
+ /* OCIO_TODO: never was able to save DDS, so can't test loading
* but profile used to be set to sRGB and can't see rect_float here, so
* default byte space should work fine
*/
@@ -136,9 +136,9 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags, char colo
if (pixel.a != 255) {
bits_per_pixel = 32;
break;
- };
- };
- };
+ }
+ }
+ }
ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0);
if (ibuf == 0) return(0); /* memory allocation failed */
@@ -164,7 +164,7 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags, char colo
}
if (ibuf->dds_data.fourcc != FOURCC_DDS) {
- ibuf->dds_data.data = (unsigned char*)dds.readData(ibuf->dds_data.size);
+ ibuf->dds_data.data = (unsigned char *)dds.readData(ibuf->dds_data.size);
/* flip compressed texture */
FlipDXTCImage(dds.width(), dds.height(), dds.mipmapCount(), dds.fourCC(), ibuf->dds_data.data);
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index f049c404e2d..20d51fddb35 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -39,6 +39,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "IMB_allocimbuf.h"
+#include "IMB_filter.h"
#include "IMB_colormanagement.h"
#include "IMB_colormanagement_intern.h"
@@ -249,11 +250,25 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
uchar *to = rect_to + stride_to * y * 4;
if (profile_to == profile_from) {
+ float straight[4];
+
/* no color space conversion */
- if (dither) {
+ if (dither && predivide) {
+ for (x = 0; x < width; x++, from += 4, to += 4) {
+ premul_to_straight_v4_v4(straight, from);
+ float_to_byte_dither_v4(to, straight, di);
+ }
+ }
+ else if (dither) {
for (x = 0; x < width; x++, from += 4, to += 4)
float_to_byte_dither_v4(to, from, di);
}
+ else if (predivide) {
+ for (x = 0; x < width; x++, from += 4, to += 4) {
+ premul_to_straight_v4_v4(straight, from);
+ rgba_float_to_uchar(to, straight);
+ }
+ }
else {
for (x = 0; x < width; x++, from += 4, to += 4)
rgba_float_to_uchar(to, from);
@@ -262,10 +277,12 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
else if (profile_to == IB_PROFILE_SRGB) {
/* convert from linear to sRGB */
unsigned short us[4];
+ float straight[4];
if (dither && predivide) {
for (x = 0; x < width; x++, from += 4, to += 4) {
- linearrgb_to_srgb_ushort4_predivide(us, from);
+ premul_to_straight_v4_v4(straight, from);
+ linearrgb_to_srgb_ushort4(us, from);
ushort_to_byte_dither_v4(to, us, di);
}
}
@@ -277,7 +294,8 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
}
else if (predivide) {
for (x = 0; x < width; x++, from += 4, to += 4) {
- linearrgb_to_srgb_ushort4_predivide(us, from);
+ premul_to_straight_v4_v4(straight, from);
+ linearrgb_to_srgb_ushort4(us, from);
ushort_to_byte_v4(to, us);
}
}
@@ -526,7 +544,6 @@ void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from,
void IMB_rect_from_float(ImBuf *ibuf)
{
- int predivide = (ibuf->flags & IB_cm_predivide);
float *buffer;
const char *from_colorspace;
@@ -548,7 +565,10 @@ void IMB_rect_from_float(ImBuf *ibuf)
buffer = MEM_dupallocN(ibuf->rect_float);
/* first make float buffer in byte space */
- IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, ibuf->rect_colorspace->name, predivide);
+ IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, ibuf->rect_colorspace->name, TRUE);
+
+ /* convert from float's premul alpha to byte's straight alpha */
+ IMB_unpremultiply_rect_float(buffer, ibuf->planes, ibuf->x, ibuf->y);
/* convert float to byte */
IMB_buffer_byte_from_float((unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
@@ -565,7 +585,6 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
{
float *rect_float;
uchar *rect_byte;
- int predivide = (ibuf->flags & IB_cm_predivide);
int profile_from = IB_PROFILE_LINEAR_RGB;
/* verify we have a float buffer */
@@ -588,12 +607,12 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
/* and do color space conversion to byte */
IMB_buffer_byte_from_float(rect_byte, rect_float,
- 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide,
+ 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, TRUE,
w, h, ibuf->x, w);
}
else {
IMB_buffer_float_from_float(buffer, rect_float,
- ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide,
+ ibuf->channels, IB_PROFILE_SRGB, profile_from, TRUE,
w, h, w, ibuf->x);
/* XXX: need to convert to image buffer's rect space */
@@ -608,8 +627,6 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
void IMB_float_from_rect(ImBuf *ibuf)
{
- int predivide = (ibuf->flags & IB_cm_predivide);
-
/* verify if we byte and float buffers */
if (ibuf->rect == NULL)
return;
@@ -634,69 +651,12 @@ void IMB_float_from_rect(ImBuf *ibuf)
/* then make float be in linear space */
IMB_colormanagement_colorspace_to_scene_linear(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
- ibuf->rect_colorspace, predivide);
-
- BLI_unlock_thread(LOCK_COLORMANAGE);
-}
-
-/* no profile conversion */
-void IMB_float_from_rect_simple(ImBuf *ibuf)
-{
- int predivide = (ibuf->flags & IB_cm_predivide);
-
- if (ibuf->rect_float == NULL)
- imb_addrectfloatImBuf(ibuf);
-
- IMB_buffer_float_from_byte(ibuf->rect_float, (uchar *)ibuf->rect,
- IB_PROFILE_SRGB, IB_PROFILE_SRGB, predivide,
- ibuf->x, ibuf->y, ibuf->x, ibuf->x);
-}
+ ibuf->rect_colorspace, FALSE);
-/* use when you need to get a buffer with a certain profile
- * if the return */
+ /* byte buffer is straight alpha, float should always be premul */
+ IMB_premultiply_rect_float(ibuf->rect_float, ibuf->planes, ibuf->x, ibuf->y);
-/* OCIO_TODO: used only by Cineon/DPX exporter which is still broken, so can not guarantee
- * this function is working properly
- */
-float *IMB_float_profile_ensure(ImBuf *ibuf, int profile, int *alloc)
-{
- int predivide = (ibuf->flags & IB_cm_predivide);
- int profile_from = IB_PROFILE_LINEAR_RGB;
- int profile_to;
-
- /* determine profile */
- if (profile == IB_PROFILE_NONE)
- profile_to = IB_PROFILE_LINEAR_RGB;
- else
- profile_to = IB_PROFILE_SRGB;
-
- if (profile_from == profile_to) {
- /* simple case, just allocate the buffer and return */
- *alloc = 0;
-
- if (ibuf->rect_float == NULL)
- IMB_float_from_rect(ibuf);
-
- return ibuf->rect_float;
- }
- else {
- /* conversion is needed, first check */
- float *fbuf = MEM_mallocN(ibuf->x * ibuf->y * sizeof(float) * 4, "IMB_float_profile_ensure");
- *alloc = 1;
-
- if (ibuf->rect_float == NULL) {
- IMB_buffer_float_from_byte(fbuf, (uchar *)ibuf->rect,
- profile_to, profile_from, predivide,
- ibuf->x, ibuf->y, ibuf->x, ibuf->x);
- }
- else {
- IMB_buffer_float_from_float(fbuf, ibuf->rect_float,
- 4, profile_to, profile_from, predivide,
- ibuf->x, ibuf->y, ibuf->x, ibuf->x);
- }
-
- return fbuf;
- }
+ BLI_unlock_thread(LOCK_COLORMANAGE);
}
/**************************** Color to Grayscale *****************************/
@@ -727,6 +687,26 @@ 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;
+ float *fp = buf;
+ while (total--) {
+ premul_to_straight_v4(fp);
+ fp += 4;
+ }
+}
+
+void IMB_buffer_float_premultiply(float *buf, int width, int height)
+{
+ int total = width * height;
+ float *fp = buf;
+ while (total--) {
+ straight_to_premul_v4(fp);
+ fp += 4;
+ }
+}
+
/**************************** alter saturation *****************************/
void IMB_saturation(ImBuf *ibuf, float sat)
diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c
index 5c2dc0c7df9..37070c7e2bf 100644
--- a/source/blender/imbuf/intern/filetype.c
+++ b/source/blender/imbuf/intern/filetype.c
@@ -26,6 +26,9 @@
#include <stddef.h>
+
+#include "BLI_utildefines.h"
+
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_filetype.h"
@@ -56,7 +59,7 @@ static int imb_ftype_iris(ImFileType *type, ImBuf *ibuf)
return (ibuf->ftype == IMAGIC);
}
#ifdef WITH_QUICKTIME
-static int imb_ftype_quicktime(ImFileType *type, ImBuf *ibuf)
+static int imb_ftype_quicktime(ImFileType *UNUSED(type), ImBuf *UNUSED(ibuf))
{
return 0; /* XXX */
}
diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c
index 678b2908b96..9193954f1d6 100644
--- a/source/blender/imbuf/intern/filter.c
+++ b/source/blender/imbuf/intern/filter.c
@@ -506,6 +506,10 @@ void IMB_makemipmap(ImBuf *ibuf, int use_filter)
imb_freemipmapImBuf(ibuf);
+ /* no mipmap for non RGBA images */
+ if (ibuf->rect_float && ibuf->channels < 4)
+ return;
+
ibuf->miptot = 1;
while (curmap < IB_MIPMAP_LEVELS) {
@@ -599,3 +603,67 @@ void IMB_premultiply_alpha(ImBuf *ibuf)
IMB_premultiply_rect_float(ibuf->rect_float, ibuf->planes, ibuf->x, ibuf->y);
}
+void IMB_unpremultiply_rect(unsigned int *rect, char planes, int w, int h)
+{
+ char *cp;
+ int x, y;
+ float val;
+
+ if (planes == 24) { /* put alpha at 255 */
+ cp = (char *)(rect);
+
+ for (y = 0; y < h; y++)
+ for (x = 0; x < w; x++, cp += 4)
+ cp[3] = 255;
+ }
+ else {
+ cp = (char *)(rect);
+
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++, cp += 4) {
+ val = cp[3] != 0 ? 1.0f / (float)cp[3] : 1.0f;
+ cp[0] = FTOCHAR(cp[0] * val);
+ cp[1] = FTOCHAR(cp[1] * val);
+ cp[2] = FTOCHAR(cp[2] * val);
+ }
+ }
+ }
+}
+
+void IMB_unpremultiply_rect_float(float *rect_float, char planes, int w, int h)
+{
+ float val, *fp;
+ int x, y;
+
+ if (planes == 24) { /* put alpha at 1.0 */
+ fp = rect_float;
+
+ for (y = 0; y < h; y++)
+ for (x = 0; x < w; x++, fp += 4)
+ fp[3] = 1.0;
+ }
+ else {
+ fp = rect_float;
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++, fp += 4) {
+ val = fp[3] != 0.0f ? 1.0f / fp[3] : 1.0f;
+ fp[0] = fp[0] * val;
+ fp[1] = fp[1] * val;
+ fp[2] = fp[2] * val;
+ }
+ }
+ }
+
+}
+
+void IMB_unpremultiply_alpha(ImBuf *ibuf)
+{
+ if (ibuf == NULL)
+ return;
+
+ if (ibuf->rect)
+ IMB_unpremultiply_rect(ibuf->rect, ibuf->planes, ibuf->x, ibuf->y);
+
+ if (ibuf->rect_float)
+ IMB_unpremultiply_rect_float(ibuf->rect_float, ibuf->planes, ibuf->x, ibuf->y);
+}
diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c
index 92b8dd8c724..26dd0f2977a 100644
--- a/source/blender/imbuf/intern/imageprocess.c
+++ b/source/blender/imbuf/intern/imageprocess.c
@@ -104,7 +104,7 @@ void bicubic_interpolation_color(struct ImBuf *in, unsigned char outI[4], float
BLI_bicubic_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v);
}
else {
- BLI_bicubic_interpolation_char((unsigned char*) in->rect, outI, in->x, in->y, 4, u, v);
+ BLI_bicubic_interpolation_char((unsigned char *) in->rect, outI, in->x, in->y, 4, u, v);
}
}
@@ -130,7 +130,7 @@ void bilinear_interpolation_color(struct ImBuf *in, unsigned char outI[4], float
BLI_bilinear_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v);
}
else {
- BLI_bilinear_interpolation_char((unsigned char*) in->rect, outI, in->x, in->y, 4, u, v);
+ BLI_bilinear_interpolation_char((unsigned char *) in->rect, outI, in->x, in->y, 4, u, v);
}
}
@@ -327,3 +327,53 @@ void IMB_processor_apply_threaded(int buffer_lines, int handle_size, void *init_
MEM_freeN(handles);
}
+
+/* Alpha-under */
+
+void IMB_alpha_under_color_float(float *rect_float, int x, int y, float backcol[3])
+{
+ int a = x * y;
+ float *fp = rect_float;
+
+ while (a--) {
+ if (fp[3] == 0.0f) {
+ copy_v3_v3(fp, backcol);
+ }
+ else {
+ float mul = 1.0f - fp[3];
+
+ fp[0] += mul * backcol[0];
+ fp[1] += mul * backcol[1];
+ fp[2] += mul * backcol[2];
+ }
+
+ fp[3] = 1.0f;
+
+ fp += 4;
+ }
+}
+
+void IMB_alpha_under_color_byte(unsigned char *rect, int x, int y, float backcol[3])
+{
+ int a = x * y;
+ unsigned char *cp = rect;
+
+ while (a--) {
+ if (cp[3] == 0) {
+ cp[0] = backcol[0] * 255;
+ cp[1] = backcol[1] * 255;
+ cp[2] = backcol[2] * 255;
+ }
+ else {
+ int mul = 255 - cp[3];
+
+ cp[0] = (cp[0] * cp[3] >> 8) + mul * backcol[0] / 255;
+ cp[1] = (cp[1] * cp[3] >> 8) + mul * backcol[1] / 255;
+ cp[2] = (cp[2] * cp[3] >> 8) + mul * backcol[2] / 255;
+ }
+
+ cp[3] = 255;
+
+ cp += 4;
+ }
+}
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index 277f50bcdbc..002ffd409a2 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -332,7 +332,7 @@ int IMB_proxy_size_to_array_index(IMB_Proxy_Size pr_size)
return 3;
default:
return 0;
- };
+ }
return 0;
}
@@ -352,7 +352,7 @@ int IMB_timecode_to_array_index(IMB_Timecode_Type tc)
return 3;
default:
return 0;
- };
+ }
return 0;
}
@@ -361,17 +361,16 @@ int IMB_timecode_to_array_index(IMB_Timecode_Type tc)
* - rebuild helper functions
* ---------------------------------------------------------------------- */
-static void get_index_dir(struct anim *anim, char *index_dir)
+static void get_index_dir(struct anim *anim, char *index_dir, size_t index_dir_len)
{
if (!anim->index_dir[0]) {
char fname[FILE_MAXFILE];
- BLI_strncpy(index_dir, anim->name, FILE_MAXDIR);
- BLI_splitdirstring(index_dir, fname);
- BLI_join_dirfile(index_dir, FILE_MAXDIR, index_dir, "BL_proxy");
- BLI_join_dirfile(index_dir, FILE_MAXDIR, index_dir, fname);
+ BLI_split_dirfile(anim->name, index_dir, fname, index_dir_len, sizeof(fname));
+ BLI_join_dirfile(index_dir, index_dir_len, index_dir, "BL_proxy");
+ BLI_join_dirfile(index_dir, index_dir_len, index_dir, fname);
}
else {
- BLI_strncpy(index_dir, anim->index_dir, FILE_MAXDIR);
+ BLI_strncpy(index_dir, anim->index_dir, index_dir_len);
}
}
@@ -396,7 +395,7 @@ static void get_proxy_filename(struct anim *anim, IMB_Proxy_Size preview_size,
BLI_snprintf(proxy_temp_name, sizeof(proxy_temp_name), "proxy_%d%s_part.avi",
(int) (proxy_fac[i] * 100), stream_suffix);
- get_index_dir(anim, index_dir);
+ 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);
@@ -425,7 +424,7 @@ static void get_tc_filename(struct anim *anim, IMB_Timecode_Type tc,
BLI_snprintf(index_name, 256, index_names[i], stream_suffix);
- get_index_dir(anim, index_dir);
+ get_index_dir(anim, index_dir, sizeof(index_dir));
BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR,
index_dir, index_name);
@@ -492,11 +491,13 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
rv->of = avformat_alloc_context();
rv->of->oformat = av_guess_format("avi", NULL, NULL);
- BLI_snprintf(rv->of->filename, sizeof(rv->of->filename), "%s", fname);
+ BLI_strncpy(rv->of->filename, fname, sizeof(rv->of->filename));
fprintf(stderr, "Starting work on proxy: %s\n", rv->of->filename);
- rv->st = av_new_stream(rv->of, 0);
+ rv->st = avformat_new_stream(rv->of, NULL);
+ rv->st->id = 0;
+
rv->c = rv->st->codec;
rv->c->codec_type = AVMEDIA_TYPE_VIDEO;
rv->c->codec_id = CODEC_ID_MJPEG;
@@ -531,8 +532,8 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
/* there's no way to set JPEG quality in the same way as in AVI JPEG and image sequence,
* but this seems to be giving expected quality result */
ffmpeg_quality = (int)(1.0f + 30.0f * (1.0f - (float)quality / 100.0f) + 0.5f);
- av_set_int(rv->c, "qmin", ffmpeg_quality);
- av_set_int(rv->c, "qmax", ffmpeg_quality);
+ av_opt_set_int(rv->c, "qmin", ffmpeg_quality, 0);
+ av_opt_set_int(rv->c, "qmax", ffmpeg_quality, 0);
if (rv->of->flags & AVFMT_GLOBALHEADER) {
rv->c->flags |= CODEC_FLAG_GLOBAL_HEADER;
@@ -545,7 +546,7 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
return 0;
}
- avcodec_open(rv->c, rv->codec);
+ avcodec_open2(rv->c, rv->codec, NULL);
rv->video_buffersize = 2000000;
rv->video_buffer = (uint8_t *)MEM_mallocN(
@@ -758,7 +759,7 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, IMB_Tim
return NULL;
}
- if (av_find_stream_info(context->iFormatCtx) < 0) {
+ if (avformat_find_stream_info(context->iFormatCtx, NULL) < 0) {
av_close_input_file(context->iFormatCtx);
MEM_freeN(context);
return NULL;
@@ -797,7 +798,7 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, IMB_Tim
context->iCodecCtx->workaround_bugs = 1;
- if (avcodec_open(context->iCodecCtx, context->iCodec) < 0) {
+ if (avcodec_open2(context->iCodecCtx, context->iCodec, NULL) < 0) {
av_close_input_file(context->iFormatCtx);
MEM_freeN(context);
return NULL;
diff --git a/source/blender/imbuf/intern/iris.c b/source/blender/imbuf/intern/iris.c
index dec5f6fb39e..ac1bb246dce 100644
--- a/source/blender/imbuf/intern/iris.c
+++ b/source/blender/imbuf/intern/iris.c
@@ -32,6 +32,7 @@
#include <string.h>
+#include "BLI_utildefines.h"
#include "BLI_fileops.h"
#include "MEM_guardedalloc.h"
@@ -672,7 +673,7 @@ static void expandrow(unsigned char *optr, unsigned char *iptr, int z)
* represents one pixel. xsize and ysize specify the dimensions of
* the pixel array. zsize specifies what kind of image file to
* write out. if zsize is 1, the luminance of the pixels are
- * calculated, and a sinlge channel black and white image is saved.
+ * calculated, and a single channel black and white image is saved.
* If zsize is 3, an RGB image file is saved. If zsize is 4, an
* RGBA image file is saved.
*
diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c
index 3a2bf99c75c..f4ac4322747 100644
--- a/source/blender/imbuf/intern/jp2.c
+++ b/source/blender/imbuf/intern/jp2.c
@@ -108,6 +108,13 @@ static void info_callback(const char *msg, void *client_data)
i++, _rect += 4) \
{ \
+# define PIXEL_LOOPER_BEGIN_CHANNELS(_rect, _channels) \
+ for (y = h - 1; y != (unsigned int)(-1); y--) { \
+ for (i = y * w, i_next = (y + 1) * w; \
+ i < i_next; \
+ i++, _rect += _channels) \
+ { \
+
# define PIXEL_LOOPER_END \
} \
} (void)0 \
@@ -228,6 +235,10 @@ struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags, char co
}
ibuf->ftype = JP2;
+ if (is_jp2)
+ ibuf->ftype |= JP2_JP2;
+ else
+ ibuf->ftype |= JP2_J2K;
if (use_float) {
float *rect_float = ibuf->rect_float;
@@ -552,7 +563,7 @@ static float channel_colormanage_noop(float value)
static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters)
{
unsigned char *rect_uchar;
- float *rect_float;
+ float *rect_float, from_straight[4];
unsigned int subsampling_dx = parameters->subsampling_dx;
unsigned int subsampling_dy = parameters->subsampling_dy;
@@ -659,70 +670,198 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters)
}
if (rect_float) {
+ int channels_in_float = ibuf->channels ? ibuf->channels : 4;
+
switch (prec) {
case 8: /* Convert blenders float color channels to 8, 12 or 16bit ints */
if (numcomps == 4) {
- PIXEL_LOOPER_BEGIN(rect_float)
- {
- r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0]));
- g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[1]));
- b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[2]));
- a[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[3]);
+ if (channels_in_float == 4) {
+ PIXEL_LOOPER_BEGIN(rect_float)
+ {
+ premul_to_straight_v4_v4(from_straight, rect_float);
+ r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[2]));
+ a[i] = DOWNSAMPLE_FLOAT_TO_8BIT(from_straight[3]);
+ }
+ PIXEL_LOOPER_END;
+ }
+ else if (channels_in_float == 3) {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[2]));
+ a[i] = 255;
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = b[i] = r[i];
+ a[i] = 255;
+ }
+ PIXEL_LOOPER_END;
}
- PIXEL_LOOPER_END;
}
else {
- PIXEL_LOOPER_BEGIN(rect_float)
- {
- r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0]));
- g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[1]));
- b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[2]));
+ if (channels_in_float == 4) {
+ PIXEL_LOOPER_BEGIN(rect_float)
+ {
+ premul_to_straight_v4_v4(from_straight, rect_float);
+ r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[2]));
+ }
+ PIXEL_LOOPER_END;
+ }
+ else if (channels_in_float == 3) {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[2]));
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = b[i] = r[i];
+ }
+ PIXEL_LOOPER_END;
}
- PIXEL_LOOPER_END;
}
break;
case 12:
if (numcomps == 4) {
- PIXEL_LOOPER_BEGIN(rect_float)
- {
- r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0]));
- g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[1]));
- b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[2]));
- a[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[3]);
+ if (channels_in_float == 4) {
+ PIXEL_LOOPER_BEGIN(rect_float)
+ {
+ premul_to_straight_v4_v4(from_straight, rect_float);
+ r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[2]));
+ a[i] = DOWNSAMPLE_FLOAT_TO_12BIT(from_straight[3]);
+ }
+ PIXEL_LOOPER_END;
+ }
+ else if (channels_in_float == 3) {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[2]));
+ a[i] = 4095;
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = b[i] = r[i];
+ a[i] = 4095;
+ }
+ PIXEL_LOOPER_END;
}
- PIXEL_LOOPER_END;
}
else {
- PIXEL_LOOPER_BEGIN(rect_float)
- {
- r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0]));
- g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[1]));
- b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[2]));
+ if (channels_in_float == 4) {
+ PIXEL_LOOPER_BEGIN(rect_float)
+ {
+ premul_to_straight_v4_v4(from_straight, rect_float);
+ r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[2]));
+ }
+ PIXEL_LOOPER_END;
+ }
+ else if (channels_in_float == 3) {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[2]));
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = b[i] = r[i];
+ }
+ PIXEL_LOOPER_END;
}
- PIXEL_LOOPER_END;
}
break;
case 16:
if (numcomps == 4) {
- PIXEL_LOOPER_BEGIN(rect_float)
- {
- r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0]));
- g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[1]));
- b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[2]));
- a[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[3]);
+ if (channels_in_float == 4) {
+ PIXEL_LOOPER_BEGIN(rect_float)
+ {
+ premul_to_straight_v4_v4(from_straight, rect_float);
+ r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[2]));
+ a[i] = DOWNSAMPLE_FLOAT_TO_16BIT(from_straight[3]);
+ }
+ PIXEL_LOOPER_END;
+ }
+ else if (channels_in_float == 3) {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[2]));
+ a[i] = 65535;
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = b[i] = r[i];
+ a[i] = 65535;
+ }
+ PIXEL_LOOPER_END;
}
- PIXEL_LOOPER_END;
}
else {
- PIXEL_LOOPER_BEGIN(rect_float)
- {
- r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0]));
- g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[1]));
- b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[2]));
+ if (channels_in_float == 4) {
+ PIXEL_LOOPER_BEGIN(rect_float)
+ {
+ premul_to_straight_v4_v4(from_straight, rect_float);
+ r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[2]));
+ }
+ PIXEL_LOOPER_END;
+ }
+ else if (channels_in_float == 3) {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 3)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[2]));
+ }
+ PIXEL_LOOPER_END;
+ }
+ else {
+ PIXEL_LOOPER_BEGIN_CHANNELS(rect_float, 1)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0]));
+ g[i] = b[i] = r[i];
+ }
+ PIXEL_LOOPER_END;
}
- PIXEL_LOOPER_END;
}
break;
}
@@ -852,9 +991,15 @@ int imb_savejp2(struct ImBuf *ibuf, const char *name, int flags)
int codestream_length;
opj_cio_t *cio = NULL;
FILE *f = NULL;
+ opj_cinfo_t *cinfo = NULL;
/* get a JP2 compressor handle */
- opj_cinfo_t *cinfo = opj_create_compress(CODEC_JP2);
+ if (ibuf->ftype & JP2_JP2)
+ cinfo = opj_create_compress(CODEC_JP2);
+ else if (ibuf->ftype & JP2_J2K)
+ cinfo = opj_create_compress(CODEC_J2K);
+ else
+ BLI_assert(!"Unsupported codec was specified in save settings");
/* catch events using our callbacks and give a local context */
opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c
index 758617bdd48..bf0e4187aa6 100644
--- a/source/blender/imbuf/intern/jpeg.c
+++ b/source/blender/imbuf/intern/jpeg.c
@@ -37,6 +37,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
#include "BLI_string.h"
#include "BLI_fileops.h"
@@ -120,10 +121,12 @@ static void jpeg_error(j_common_ptr cinfo)
* INPUT HANDLER FROM MEMORY
*---------------------------------------------------------- */
+#if 0
typedef struct {
unsigned char *buffer;
int filled;
} buffer_struct;
+#endif
typedef struct {
struct jpeg_source_mgr pub; /* public fields */
@@ -234,7 +237,7 @@ static void memory_source(j_decompress_ptr cinfo, unsigned char *buffer, size_t
* If must suspend, take the specified action (typically "return FALSE").
*/
#define INPUT_BYTE(cinfo, V, action) \
- MAKESTMT(MAKE_BYTE_AVAIL(cinfo,action); \
+ MAKESTMT(MAKE_BYTE_AVAIL(cinfo, action); \
bytes_in_buffer--; \
V = GETJOCTET(*next_input_byte++); )
@@ -242,7 +245,7 @@ static void memory_source(j_decompress_ptr cinfo, unsigned char *buffer, size_t
* V should be declared unsigned int or perhaps INT32.
*/
#define INPUT_2BYTES(cinfo, V, action) \
- MAKESTMT(MAKE_BYTE_AVAIL(cinfo,action); \
+ MAKESTMT(MAKE_BYTE_AVAIL(cinfo, action); \
bytes_in_buffer--; \
V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \
MAKE_BYTE_AVAIL(cinfo, action); \
diff --git a/source/blender/imbuf/intern/moviecache.c b/source/blender/imbuf/intern/moviecache.c
index d5aa635f548..94fe1f44d91 100644
--- a/source/blender/imbuf/intern/moviecache.c
+++ b/source/blender/imbuf/intern/moviecache.c
@@ -145,7 +145,7 @@ static void check_unused_keys(MovieCache *cache)
GHashIterator *iter;
iter = BLI_ghashIterator_new(cache->hash);
- while (!BLI_ghashIterator_isDone(iter)) {
+ while (BLI_ghashIterator_notDone(iter)) {
MovieCacheKey *key = BLI_ghashIterator_getKey(iter);
MovieCacheItem *item = BLI_ghashIterator_getValue(iter);
int remove = 0;
@@ -306,7 +306,7 @@ void IMB_moviecache_set_priority_callback(struct MovieCache *cache, MovieCacheGe
cache->prioritydeleterfp = prioritydeleterfp;
}
-void IMB_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf)
+static void do_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf, int need_lock)
{
MovieCacheKey *key;
MovieCacheItem *item;
@@ -341,7 +341,8 @@ void IMB_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf)
memcpy(cache->last_userkey, userkey, cache->keysize);
}
- BLI_mutex_lock(&limitor_lock);
+ if (need_lock)
+ BLI_mutex_lock(&limitor_lock);
item->c_handle = MEM_CacheLimiter_insert(limitor, item);
@@ -349,7 +350,8 @@ void IMB_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf)
MEM_CacheLimiter_enforce_limits(limitor);
MEM_CacheLimiter_unref(item->c_handle);
- BLI_mutex_unlock(&limitor_lock);
+ if (need_lock)
+ BLI_mutex_unlock(&limitor_lock);
/* cache limiter can't remove unused keys which points to destoryed values */
check_unused_keys(cache);
@@ -360,6 +362,32 @@ void IMB_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf)
}
}
+void IMB_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf)
+{
+ do_moviecache_put(cache, userkey, ibuf, TRUE);
+}
+
+int IMB_moviecache_put_if_possible(MovieCache *cache, void *userkey, ImBuf *ibuf)
+{
+ size_t mem_in_use, mem_limit, elem_size;
+ int result = FALSE;
+
+ elem_size = IMB_get_size_in_memory(ibuf);
+ mem_limit = MEM_CacheLimiter_get_maximum();
+
+ BLI_mutex_lock(&limitor_lock);
+ mem_in_use = MEM_CacheLimiter_get_memory_in_use(limitor);
+
+ if (mem_in_use + elem_size <= mem_limit) {
+ do_moviecache_put(cache, userkey, ibuf, FALSE);
+ result = TRUE;
+ }
+
+ BLI_mutex_unlock(&limitor_lock);
+
+ return result;
+}
+
ImBuf *IMB_moviecache_get(MovieCache *cache, void *userkey)
{
MovieCacheKey key;
@@ -384,6 +412,18 @@ ImBuf *IMB_moviecache_get(MovieCache *cache, void *userkey)
return NULL;
}
+int IMB_moviecache_has_frame(MovieCache *cache, void *userkey)
+{
+ MovieCacheKey key;
+ MovieCacheItem *item;
+
+ key.cache_owner = cache;
+ key.userkey = userkey;
+ item = (MovieCacheItem *)BLI_ghash_lookup(cache->hash, &key);
+
+ return item != NULL;
+}
+
void IMB_moviecache_free(MovieCache *cache)
{
PRINT("%s: cache '%s' free\n", __func__, cache->name);
@@ -408,7 +448,7 @@ void IMB_moviecache_cleanup(MovieCache *cache, int (cleanup_check_cb) (void *use
GHashIterator *iter;
iter = BLI_ghashIterator_new(cache->hash);
- while (!BLI_ghashIterator_isDone(iter)) {
+ while (BLI_ghashIterator_notDone(iter)) {
MovieCacheKey *key = BLI_ghashIterator_getKey(iter);
int remove;
@@ -457,7 +497,7 @@ void IMB_moviecache_get_cache_segments(MovieCache *cache, int proxy, int render_
iter = BLI_ghashIterator_new(cache->hash);
a = 0;
- while (!BLI_ghashIterator_isDone(iter)) {
+ while (BLI_ghashIterator_notDone(iter)) {
MovieCacheKey *key = BLI_ghashIterator_getKey(iter);
MovieCacheItem *item = BLI_ghashIterator_getValue(iter);
int framenr, curproxy, curflags;
diff --git a/source/blender/imbuf/intern/openexr/SConscript b/source/blender/imbuf/intern/openexr/SConscript
index a6c5ad984e2..ac38c0458d9 100644
--- a/source/blender/imbuf/intern/openexr/SConscript
+++ b/source/blender/imbuf/intern/openexr/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
source_files = ['openexr_api.cpp']
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index da7b31cc2ba..defbfcd3e99 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -85,6 +85,7 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void)
#include <ImfCompression.h>
#include <ImfCompressionAttribute.h>
#include <ImfStringAttribute.h>
+#include <ImfStandardAttributes.h>
using namespace Imf;
using namespace Imath;
@@ -302,6 +303,9 @@ static void openexr_header_metadata(Header *header, struct ImBuf *ibuf)
for (info = ibuf->metadata; info; info = info->next)
header->insert(info->key, StringAttribute(info->value));
+
+ if (ibuf->ppm[0] > 0.0f)
+ addXDensity(*header, ibuf->ppm[0] / 39.3700787f); /* 1 meter = 39.3700787 inches */
}
static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags)
@@ -882,6 +886,14 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa
const char *token;
char tokenbuf[EXR_TOT_MAXNAME];
int len;
+
+ /* some multilayers have the combined buffer with names A B G R saved */
+ if (name[1] == 0) {
+ echan->chan_id = name[0];
+ layname[0] = '\0';
+ strcpy(passname, "Combined");
+ return 1;
+ }
/* last token is single character channel identifier */
len = imb_exr_split_token(name, end, &token);
@@ -1093,11 +1105,29 @@ static int exr_is_multilayer(InputFile *file)
const ChannelList &channels = file->header().channels();
std::set <std::string> layerNames;
+ /* will not include empty layer names */
channels.layers(layerNames);
if (comments || layerNames.size() > 1)
return 1;
+ 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++) {
+ std::string layerName = i.name();
+ size_t pos = layerName.rfind ('.');
+
+ if (pos == std::string::npos)
+ return 1;
+ }
+ }
+
return 0;
}
@@ -1136,6 +1166,12 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char
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] * file->header().pixelAspectRatio();
+ }
+
ibuf->ftype = OPENEXR;
if (!(flags & IB_test)) {
@@ -1197,6 +1233,9 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char
delete file;
}
}
+
+ if (flags & IB_alphamode_detect)
+ ibuf->flags |= IB_alphamode_premul;
}
return(ibuf);
}
diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c
index dcfebb95b87..a7e05612472 100644
--- a/source/blender/imbuf/intern/png.c
+++ b/source/blender/imbuf/intern/png.c
@@ -33,6 +33,7 @@
#include "png.h"
+#include "BLI_utildefines.h"
#include "BLI_fileops.h"
#include "BLI_math.h"
@@ -60,6 +61,11 @@ static void ReadData(png_structp png_ptr, png_bytep data, png_size_t length);
static void WriteData(png_structp png_ptr, png_bytep data, png_size_t length);
static void Flush(png_structp png_ptr);
+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 ret_val = 0;
@@ -102,6 +108,17 @@ static void ReadData(png_structp png_ptr, png_bytep data, png_size_t length)
longjmp(png_jmpbuf(png_ptr), 1);
}
+static float channel_colormanage_noop(float value)
+{
+ return value;
+}
+
+/* wrap to avoid macro calling functions multiple times */
+BLI_INLINE unsigned short ftoshort(float val)
+{
+ return FTOUSHORT(val);
+}
+
int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
{
png_structp png_ptr;
@@ -109,22 +126,39 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
unsigned char *pixels = NULL;
unsigned char *from, *to;
+ unsigned short *pixels16 = NULL, *to16;
+ float *from_float, from_straight[4];
png_bytepp row_pointers = NULL;
int i, bytesperpixel, color_type = PNG_COLOR_TYPE_GRAY;
FILE *fp = NULL;
+ bool is_16bit = (ibuf->ftype & PNG_16BIT);
+ bool has_float = (ibuf->rect_float != NULL);
+ int channels_in_float = ibuf->channels ? ibuf->channels : 4;
+
+ float (*chanel_colormanage_cb)(float);
+
/* use the jpeg quality setting for compression */
int compression;
compression = (int)(((float)(ibuf->ftype & 0xff) / 11.1111f));
compression = compression < 0 ? 0 : (compression > 9 ? 9 : compression);
+ if (ibuf->float_colorspace) {
+ /* float buffer was managed already, no need in color space conversion */
+ chanel_colormanage_cb = channel_colormanage_noop;
+ }
+ else {
+ /* standard linear-to-srgb conversion if float buffer wasn't managed */
+ chanel_colormanage_cb = linearrgb_to_srgb;
+ }
+
/* for prints */
if (flags & IB_mem)
name = "<memory>";
bytesperpixel = (ibuf->planes + 7) >> 3;
if ((bytesperpixel > 4) || (bytesperpixel == 2)) {
- printf("imb_savepng: Cunsupported bytes per pixel: %d for file: '%s'\n", bytesperpixel, name);
+ printf("imb_savepng: Unsupported bytes per pixel: %d for file: '%s'\n", bytesperpixel, name);
return (0);
}
@@ -150,8 +184,12 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
/* copy image data */
- pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels");
- if (pixels == NULL) {
+ if (is_16bit)
+ pixels16 = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned short), "png 16bit pixels");
+ else
+ pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "png 8bit pixels");
+
+ if (pixels == NULL && pixels16 == NULL) {
png_destroy_write_struct(&png_ptr, &info_ptr);
printf("imb_savepng: Cannot allocate pixels array of %dx%d, %d bytes per pixel for file: '%s'\n", ibuf->x, ibuf->y, bytesperpixel, name);
return 0;
@@ -159,32 +197,152 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
from = (unsigned char *) ibuf->rect;
to = pixels;
+ from_float = ibuf->rect_float;
+ to16 = pixels16;
switch (bytesperpixel) {
case 4:
color_type = PNG_COLOR_TYPE_RGBA;
- for (i = ibuf->x * ibuf->y; i > 0; i--) {
- to[0] = from[0];
- to[1] = from[1];
- to[2] = from[2];
- to[3] = from[3];
- to += 4; from += 4;
+ if (is_16bit) {
+ if (has_float) {
+ if (channels_in_float == 4) {
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ premul_to_straight_v4_v4(from_straight, from_float);
+ to16[0] = ftoshort(chanel_colormanage_cb(from_straight[0]));
+ to16[1] = ftoshort(chanel_colormanage_cb(from_straight[1]));
+ to16[2] = ftoshort(chanel_colormanage_cb(from_straight[2]));
+ to16[3] = ftoshort(chanel_colormanage_cb(from_straight[3]));
+ to16 += 4; from_float += 4;
+ }
+ }
+ else if (channels_in_float == 3) {
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
+ to16[1] = ftoshort(chanel_colormanage_cb(from_float[1]));
+ to16[2] = ftoshort(chanel_colormanage_cb(from_float[2]));
+ to16[3] = 65535;
+ to16 += 4; from_float += 3;
+ }
+ }
+ else {
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
+ to16[2] = to16[1] = to16[0];
+ to16[3] = 65535;
+ to16 += 4; from_float++;
+ }
+ }
+ }
+ else {
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ to16[0] = UPSAMPLE_8_TO_16(from[0]);
+ to16[1] = UPSAMPLE_8_TO_16(from[1]);
+ to16[2] = UPSAMPLE_8_TO_16(from[2]);
+ to16[3] = UPSAMPLE_8_TO_16(from[3]);
+ to16 += 4; from += 4;
+ }
+ }
+ }
+ else {
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ to[0] = from[0];
+ to[1] = from[1];
+ to[2] = from[2];
+ to[3] = from[3];
+ to += 4; from += 4;
+ }
}
break;
case 3:
color_type = PNG_COLOR_TYPE_RGB;
- for (i = ibuf->x * ibuf->y; i > 0; i--) {
- to[0] = from[0];
- to[1] = from[1];
- to[2] = from[2];
- to += 3; from += 4;
+ if (is_16bit) {
+ if (has_float) {
+ if (channels_in_float == 4) {
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ premul_to_straight_v4_v4(from_straight, from_float);
+ to16[0] = ftoshort(chanel_colormanage_cb(from_straight[0]));
+ to16[1] = ftoshort(chanel_colormanage_cb(from_straight[1]));
+ to16[2] = ftoshort(chanel_colormanage_cb(from_straight[2]));
+ to16 += 3; from_float += 4;
+ }
+ }
+ else if (channels_in_float == 3) {
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
+ to16[1] = ftoshort(chanel_colormanage_cb(from_float[1]));
+ to16[2] = ftoshort(chanel_colormanage_cb(from_float[2]));
+ to16 += 3; from_float += 3;
+ }
+ }
+ else {
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
+ to16[2] = to16[1] = to16[0];
+ to16 += 3; from_float++;
+ }
+ }
+ }
+ else {
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ to16[0] = UPSAMPLE_8_TO_16(from[0]);
+ to16[1] = UPSAMPLE_8_TO_16(from[1]);
+ to16[2] = UPSAMPLE_8_TO_16(from[2]);
+ to16 += 3; from += 4;
+ }
+ }
+ }
+ else {
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ to[0] = from[0];
+ to[1] = from[1];
+ to[2] = from[2];
+ to += 3; from += 4;
+ }
}
break;
case 1:
color_type = PNG_COLOR_TYPE_GRAY;
- for (i = ibuf->x * ibuf->y; i > 0; i--) {
- to[0] = from[0];
- to++; from += 4;
+ if (is_16bit) {
+ if (has_float) {
+ float rgb[3];
+ if (channels_in_float == 4) {
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ premul_to_straight_v4_v4(from_straight, from_float);
+ 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++; from_float += 4;
+ }
+ }
+ else if (channels_in_float == 3) {
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ 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++; from_float += 3;
+ }
+ }
+ else {
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
+ to16++; from_float++;
+ }
+ }
+ }
+ else {
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ to16[0] = UPSAMPLE_8_TO_16(from[0]);
+ to16++; from += 4;
+ }
+ }
+ }
+ else {
+ for (i = ibuf->x * ibuf->y; i > 0; i--) {
+ to[0] = from[0];
+ to++; from += 4;
+ }
}
break;
}
@@ -203,7 +361,10 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
fp = BLI_fopen(name, "wb");
if (!fp) {
png_destroy_write_struct(&png_ptr, &info_ptr);
- MEM_freeN(pixels);
+ if (pixels)
+ MEM_freeN(pixels);
+ if (pixels16)
+ MEM_freeN(pixels16);
printf("imb_savepng: Cannot open file for writing: '%s'\n", name);
return 0;
}
@@ -227,7 +388,7 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
info_ptr,
ibuf->x,
ibuf->y,
- 8,
+ is_16bit ? 16 : 8,
color_type,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
@@ -268,12 +429,19 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
/* write the file header information */
png_write_info(png_ptr, info_ptr);
+#ifdef __LITTLE_ENDIAN__
+ png_set_swap(png_ptr);
+#endif
+
/* allocate memory for an array of row-pointers */
row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers");
if (row_pointers == NULL) {
printf("imb_savepng: Cannot allocate row-pointers array for file '%s'\n", name);
png_destroy_write_struct(&png_ptr, &info_ptr);
- MEM_freeN(pixels);
+ if (pixels)
+ MEM_freeN(pixels);
+ if (pixels16)
+ MEM_freeN(pixels16);
if (fp) {
fclose(fp);
}
@@ -281,9 +449,17 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
}
/* 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));
+ 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);
+ }
+ }
+ 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));
+ }
}
/* write out the entire image data in one call */
@@ -293,7 +469,10 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
png_write_end(png_ptr, info_ptr);
/* clean up */
- MEM_freeN(pixels);
+ if (pixels)
+ MEM_freeN(pixels);
+ if (pixels16)
+ MEM_freeN(pixels16);
MEM_freeN(row_pointers);
png_destroy_write_struct(&png_ptr, &info_ptr);
@@ -394,6 +573,8 @@ ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[I
if (ibuf) {
ibuf->ftype = PNG;
+ if (bit_depth == 16)
+ ibuf->ftype |= PNG_16BIT;
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) {
int unit_type;
diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c
index 03ed1bb8008..d45438e2853 100644
--- a/source/blender/imbuf/intern/radiance_hdr.c
+++ b/source/blender/imbuf/intern/radiance_hdr.c
@@ -43,6 +43,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
#include "BLI_fileops.h"
#include "imbuf.h"
@@ -212,6 +213,9 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags, char color
if (ibuf == NULL) return NULL;
ibuf->ftype = RADHDR;
+ if (flags & IB_alphamode_detect)
+ ibuf->flags |= IB_alphamode_premul;
+
if (flags & IB_test) return ibuf;
/* read in and decode the actual data */
@@ -315,7 +319,9 @@ static int fwritecolrs(FILE *file, int width, int channels, unsigned char *ibufs
putc((unsigned char)(128 + cnt), file);
putc(rgbe_scan[beg][i], file);
}
- else cnt = 0;
+ else {
+ cnt = 0;
+ }
}
}
MEM_freeN(rgbe_scan);
diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c
index be20c80bdec..d73fa9a7ab7 100644
--- a/source/blender/imbuf/intern/readimage.c
+++ b/source/blender/imbuf/intern/readimage.c
@@ -43,12 +43,11 @@
#endif
#include <stdlib.h>
+#include "BLI_utildefines.h"
#include "BLI_string.h"
#include "BLI_path_util.h"
#include "BLI_fileops.h"
-#include "BLI_utildefines.h"
-
#include "imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -75,6 +74,8 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char co
if (type->load) {
ibuf = type->load(mem, size, flags, effective_colorspace);
if (ibuf) {
+ int alpha_flags;
+
if (colorspace) {
if (ibuf->rect) {
/* byte buffer is never internally converted to some standard space,
@@ -86,15 +87,37 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char co
BLI_strncpy(colorspace, effective_colorspace, IM_MAX_SPACE);
}
+ if (flags & IB_alphamode_detect)
+ alpha_flags = ibuf->flags & IB_alphamode_premul;
+ else
+ alpha_flags = flags & IB_alphamode_premul;
+
+ if (flags & IB_ignore_alpha) {
+ IMB_rectfill_alpha(ibuf, 1.0f);
+ }
+ else {
+ if (alpha_flags & IB_alphamode_premul) {
+ if (ibuf->rect) {
+ IMB_unpremultiply_alpha(ibuf);
+ }
+ else {
+ /* pass, floats are expected to be premul */
+ }
+ }
+ else {
+ if (ibuf->rect_float) {
+ IMB_premultiply_alpha(ibuf);
+ }
+ else {
+ /* pass, bytes are expected to be straight */
+ }
+ }
+ }
+
/* OCIO_TODO: in some cases it's faster to do threaded conversion,
* but how to distinguish such cases */
colormanage_imbuf_make_linear(ibuf, effective_colorspace);
- if (flags & IB_premul) {
- IMB_premultiply_alpha(ibuf);
- ibuf->flags |= IB_premul;
- }
-
return ibuf;
}
}
@@ -230,4 +253,3 @@ void imb_loadtile(ImBuf *ibuf, int tx, int ty, unsigned int *rect)
close(file);
}
-
diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c
index d2b0645cf93..958070c1479 100644
--- a/source/blender/imbuf/intern/rectop.c
+++ b/source/blender/imbuf/intern/rectop.c
@@ -121,6 +121,27 @@ static void blend_color_darken(char cp[3], const char cp1[3], const char cp2[3],
}
}
+static void blend_color_erase_alpha(char cp[4], const char cp1[4], const char cp2[4], const int fac)
+{
+ int temp = (cp1[3] - fac * cp2[3] / 255);
+
+ cp[0] = cp1[0];
+ cp[1] = cp1[1];
+ cp[2] = cp1[2];
+ cp[3] = (temp < 0) ? 0 : temp;
+}
+
+static void blend_color_add_alpha(char cp[4], const char cp1[4], const char cp2[4], const int fac)
+{
+ int temp = (cp1[3] + fac * cp2[3] / 255);
+
+ cp[0] = cp1[0];
+ cp[1] = cp1[1];
+ cp[2] = cp1[2];
+ cp[3] = (temp > 255)? 255 : ((temp < 0) ? 0 : temp);
+}
+
+
unsigned int IMB_blend_color(unsigned int src1, unsigned int src2, int fac, IMB_BlendMode mode)
{
unsigned int dst;
@@ -230,6 +251,27 @@ static void blend_color_darken_float(float cp[3], const float cp1[3], const floa
blend_color_mix_float(cp, cp1, cp2, fac);
}
+static void blend_color_erase_alpha_float(float cp[4], const float cp1[4], const float cp2[4], const float fac)
+{
+ cp[0] = cp1[0];
+ cp[1] = cp1[1];
+ cp[2] = cp1[2];
+
+ cp[3] = (cp1[3] - fac * cp2[3]);
+ if (cp[3] < 0.0f) cp[3] = 0.0f;
+}
+
+static void blend_color_add_alpha_float(float cp[4], const float cp1[4], const float cp2[4], const float fac)
+{
+ cp[0] = cp1[0];
+ cp[1] = cp1[1];
+ cp[2] = cp1[2];
+
+ cp[3] = (cp1[3] + fac * cp2[3]);
+ if (cp[3] < 0.0f) cp[3] = 0.0f;
+ if (cp[3] > 1.0f) cp[3] = 1.0f;
+}
+
void IMB_blend_color_float(float *dst, float *src1, float *src2, float fac, IMB_BlendMode mode)
{
if (fac == 0) {
@@ -326,12 +368,18 @@ void IMB_rectcpy(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx,
IMB_BLEND_COPY);
}
+typedef void (*IMB_blend_func)(char *dst, const char *src1, const char *src2, const int fac);
+typedef void (*IMB_blend_func_float)(float *dst, const float *src1, const float *src2, const float fac);
+
+
void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx,
int desty, int srcx, int srcy, int width, int height, IMB_BlendMode mode)
{
unsigned int *drect = NULL, *srect = NULL, *dr, *sr;
float *drectf = NULL, *srectf = NULL, *drf, *srf;
int do_float, do_char, srcskip, destskip, x;
+ IMB_blend_func func = NULL;
+ IMB_blend_func_float func_float = NULL;
if (dbuf == NULL) return;
@@ -427,13 +475,52 @@ void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx,
}
}
else {
+ switch (mode) {
+ case IMB_BLEND_MIX:
+ func = blend_color_mix;
+ func_float = blend_color_mix_float;
+ break;
+ case IMB_BLEND_ADD:
+ func = blend_color_add;
+ func_float = blend_color_add_float;
+ break;
+ case IMB_BLEND_SUB:
+ func = blend_color_sub;
+ func_float = blend_color_sub_float;
+ break;
+ case IMB_BLEND_MUL:
+ func = blend_color_mul;
+ func_float = blend_color_mul_float;
+ break;
+ case IMB_BLEND_LIGHTEN:
+ func = blend_color_lighten;
+ func_float = blend_color_lighten_float;
+ break;
+ case IMB_BLEND_DARKEN:
+ func = blend_color_darken;
+ func_float = blend_color_darken_float;
+ break;
+ case IMB_BLEND_ERASE_ALPHA:
+ func = blend_color_erase_alpha;
+ func_float = blend_color_erase_alpha_float;
+ break;
+ case IMB_BLEND_ADD_ALPHA:
+ func = blend_color_add_alpha;
+ func_float = blend_color_add_alpha_float;
+ break;
+ default:
+ break;
+ }
+
/* blend */
for (; height > 0; height--) {
if (do_char) {
dr = drect;
sr = srect;
- for (x = width; x > 0; x--, dr++, sr++)
- *dr = IMB_blend_color(*dr, *sr, ((char *)sr)[3], mode);
+ for (x = width; x > 0; x--, dr++, sr++) {
+ if (((char *)sr)[3])
+ func((char *)dr, (char *)dr, (char *)sr, ((char *)sr)[3]);
+ }
drect += destskip;
srect += srcskip;
@@ -442,9 +529,10 @@ void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx,
if (do_float) {
drf = drectf;
srf = srectf;
- for (x = width; x > 0; x--, drf += 4, srf += 4)
- IMB_blend_color_float(drf, drf, srf, srf[3], mode);
-
+ for (x = width; x > 0; x--, drf += 4, srf += 4) {
+ if (srf[3] != 0)
+ func_float(drf, drf, srf, srf[3]);
+ }
drectf += destskip * 4;
srectf += srcskip * 4;
}
@@ -594,11 +682,13 @@ void IMB_rectfill_area(struct ImBuf *ibuf, const float col[4], int x1, int y1, i
void IMB_rectfill_alpha(ImBuf *ibuf, const float value)
{
int i;
- if (ibuf->rect_float) {
+
+ if (ibuf->rect_float && (ibuf->channels == 4)) {
float *fbuf = ibuf->rect_float + 3;
for (i = ibuf->x * ibuf->y; i > 0; i--, fbuf += 4) { *fbuf = value; }
}
- else {
+
+ if (ibuf->rect) {
const unsigned char cvalue = value * 255;
unsigned char *cbuf = ((unsigned char *)ibuf->rect) + 3;
for (i = ibuf->x * ibuf->y; i > 0; i--, cbuf += 4) { *cbuf = cvalue; }
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index 1e701b8d615..553a530ecf4 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -33,6 +33,8 @@
#include "BLI_utildefines.h"
+#include "BLI_math_color.h"
+#include "BLI_math_interp.h"
#include "MEM_guardedalloc.h"
#include "imbuf.h"
@@ -291,6 +293,37 @@ struct ImBuf *IMB_double_y(struct ImBuf *ibuf1)
return (ibuf2);
}
+/* pretty much specific functions which converts uchar <-> ushort but assumes
+ * ushort range of 255*255 which is more convenient here
+ */
+MINLINE void straight_uchar_to_premul_ushort(unsigned short result[4], const unsigned char color[4])
+{
+ unsigned short alpha = color[3];
+
+ result[0] = color[0] * alpha;
+ result[1] = color[1] * alpha;
+ result[2] = color[2] * alpha;
+ result[3] = alpha * 255;
+}
+
+MINLINE void premul_ushort_to_straight_uchar(unsigned char *result, const unsigned short color[4])
+{
+ if (color[3] <= 255) {
+ result[0] = color[0] / 255;
+ result[1] = color[1] / 255;
+ result[2] = color[2] / 255;
+ result[3] = color[3] / 255;
+ }
+ else {
+ unsigned short alpha = color[3] / 255;
+
+ result[0] = color[0] / alpha;
+ result[1] = color[1] / alpha;
+ result[2] = color[2] / alpha;
+ result[3] = alpha;
+ }
+}
+
/* result in ibuf2, scaling should be done correctly */
void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1)
{
@@ -303,23 +336,33 @@ void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1)
}
if (do_rect) {
- char *p1, *p2, *dest;
+ unsigned char *cp1, *cp2, *dest;
- p1 = (char *) ibuf1->rect;
- dest = (char *) ibuf2->rect;
+ cp1 = (unsigned char *) ibuf1->rect;
+ dest = (unsigned char *) ibuf2->rect;
for (y = ibuf2->y; y > 0; y--) {
- p2 = p1 + (ibuf1->x << 2);
+ cp2 = cp1 + (ibuf1->x << 2);
for (x = ibuf2->x; x > 0; x--) {
- dest[0] = (p1[0] + p2[0] + p1[4] + p2[4]) >> 2;
- dest[1] = (p1[1] + p2[1] + p1[5] + p2[5]) >> 2;
- dest[2] = (p1[2] + p2[2] + p1[6] + p2[6]) >> 2;
- dest[3] = (p1[3] + p2[3] + p1[7] + p2[7]) >> 2;
- p1 += 8;
- p2 += 8;
+ unsigned short p1i[8], p2i[8], desti[4];
+
+ straight_uchar_to_premul_ushort(p1i, cp1);
+ straight_uchar_to_premul_ushort(p2i, cp2);
+ straight_uchar_to_premul_ushort(p1i + 4, cp1 + 4);
+ straight_uchar_to_premul_ushort(p2i + 4, cp2 + 4);
+
+ desti[0] = ((unsigned int) p1i[0] + p2i[0] + p1i[4] + p2i[4]) >> 2;
+ desti[1] = ((unsigned int) p1i[1] + p2i[1] + p1i[5] + p2i[5]) >> 2;
+ desti[2] = ((unsigned int) p1i[2] + p2i[2] + p1i[6] + p2i[6]) >> 2;
+ desti[3] = ((unsigned int) p1i[3] + p2i[3] + p1i[7] + p2i[7]) >> 2;
+
+ premul_ushort_to_straight_uchar(dest, desti);
+
+ cp1 += 8;
+ cp2 += 8;
dest += 4;
}
- p1 = p2;
- if (ibuf1->x & 1) p1 += 4;
+ cp1 = cp2;
+ if (ibuf1->x & 1) cp1 += 4;
}
}
@@ -1562,3 +1605,113 @@ struct ImBuf *IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned
return(ibuf);
}
+/* ******** threaded scaling ******** */
+
+typedef struct ScaleTreadInitData {
+ ImBuf *ibuf;
+
+ unsigned int newx;
+ unsigned int newy;
+
+ unsigned char *byte_buffer;
+ float *float_buffer;
+} ScaleTreadInitData;
+
+typedef struct ScaleThreadData {
+ ImBuf *ibuf;
+
+ unsigned int newx;
+ unsigned int newy;
+
+ int start_line;
+ int tot_line;
+
+ unsigned char *byte_buffer;
+ float *float_buffer;
+} ScaleThreadData;
+
+static void scale_thread_init(void *data_v, int start_line, int tot_line, void *init_data_v)
+{
+ ScaleThreadData *data = (ScaleThreadData *) data_v;
+ ScaleTreadInitData *init_data = (ScaleTreadInitData *) init_data_v;
+
+ data->ibuf = init_data->ibuf;
+
+ data->newx = init_data->newx;
+ data->newy = init_data->newy;
+
+ data->start_line = start_line;
+ data->tot_line = tot_line;
+
+ data->byte_buffer = init_data->byte_buffer;
+ data->float_buffer = init_data->float_buffer;
+}
+
+static void *do_scale_thread(void *data_v)
+{
+ ScaleThreadData *data = (ScaleThreadData *) data_v;
+ ImBuf *ibuf = data->ibuf;
+ int i;
+ float factor_x = (float) ibuf->x / data->newx;
+ float factor_y = (float) ibuf->y / data->newy;
+
+ for (i = 0; i < data->tot_line; i++) {
+ int y = data->start_line + i;
+ int x;
+
+ for (x = 0; x < data->newx; x++) {
+ float u = (float) x * factor_x;
+ float v = (float) y * factor_y;
+ int offset = y * data->newx + x;
+
+ if (data->byte_buffer) {
+ unsigned char *pixel = data->byte_buffer + 4 * offset;
+ BLI_bilinear_interpolation_char((unsigned char *) ibuf->rect, pixel, ibuf->x, ibuf->y, 4, u, v);
+ }
+
+ if (data->float_buffer) {
+ float *pixel = data->float_buffer + ibuf->channels * offset;
+ BLI_bilinear_interpolation_fl(ibuf->rect_float, pixel, ibuf->x, ibuf->y, ibuf->channels, u, v);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+void IMB_scaleImBuf_threaded(ImBuf *ibuf, unsigned int newx, unsigned int newy)
+{
+ ScaleTreadInitData init_data = {NULL};
+
+ /* prepare initialization data */
+ init_data.ibuf = ibuf;
+
+ init_data.newx = newx;
+ init_data.newy = newy;
+
+ if (ibuf->rect)
+ init_data.byte_buffer = MEM_mallocN(4 * newx * newy * sizeof(char), "threaded scale byte buffer");
+
+ if (ibuf->rect_float)
+ init_data.float_buffer = MEM_mallocN(ibuf->channels * newx * newy * sizeof(float), "threaded scale float buffer");
+
+ /* actual scaling threads */
+ IMB_processor_apply_threaded(newy, sizeof(ScaleThreadData), &init_data,
+ scale_thread_init, do_scale_thread);
+
+ /* alter image buffer */
+ ibuf->x = newx;
+ ibuf->y = newy;
+
+ if (ibuf->rect) {
+ imb_freerectImBuf(ibuf);
+ ibuf->mall |= IB_rect;
+ ibuf->rect = (unsigned int *) init_data.byte_buffer;
+ }
+
+ if (ibuf->rect_float) {
+ imb_freerectfloatImBuf(ibuf);
+ ibuf->mall |= IB_rectfloat;
+ ibuf->rect_float = init_data.float_buffer;
+ }
+}
diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c
index eaad77f1ff9..0c30af60388 100644
--- a/source/blender/imbuf/intern/targa.c
+++ b/source/blender/imbuf/intern/targa.c
@@ -34,6 +34,7 @@
# include <io.h>
#endif
+#include "BLI_utildefines.h"
#include "BLI_fileops.h"
#include "MEM_guardedalloc.h"
@@ -76,8 +77,8 @@ static int tga_out1(unsigned int data, FILE *file)
uchar *p;
p = (uchar *) &data;
- if (putc(p[0], file) == EOF) return(EOF);
- return (~EOF);
+ if (putc(p[0], file) == EOF) return EOF;
+ return ~EOF;
}
static int tga_out2(unsigned int data, FILE *file)
@@ -85,9 +86,9 @@ static int tga_out2(unsigned int data, FILE *file)
uchar *p;
p = (uchar *) &data;
- if (putc(p[0], file) == EOF) return(EOF);
- if (putc(p[1], file) == EOF) return(EOF);
- return (~EOF);
+ if (putc(p[0], file) == EOF) return EOF;
+ if (putc(p[1], file) == EOF) return EOF;
+ return ~EOF;
}
@@ -96,10 +97,10 @@ static int tga_out3(unsigned int data, FILE *file)
uchar *p;
p = (uchar *) &data;
- if (putc(p[2], file) == EOF) return(EOF);
- if (putc(p[1], file) == EOF) return(EOF);
- if (putc(p[0], file) == EOF) return(EOF);
- return (~EOF);
+ if (putc(p[2], file) == EOF) return EOF;
+ if (putc(p[1], file) == EOF) return EOF;
+ if (putc(p[0], file) == EOF) return EOF;
+ return ~EOF;
}
@@ -109,11 +110,11 @@ static int tga_out4(unsigned int data, FILE *file)
p = (uchar *) &data;
/* order = bgra */
- if (putc(p[2], file) == EOF) return(EOF);
- if (putc(p[1], file) == EOF) return(EOF);
- if (putc(p[0], file) == EOF) return(EOF);
- if (putc(p[3], file) == EOF) return(EOF);
- return (~EOF);
+ if (putc(p[2], file) == EOF) return EOF;
+ if (putc(p[1], file) == EOF) return EOF;
+ if (putc(p[0], file) == EOF) return EOF;
+ if (putc(p[3], file) == EOF) return EOF;
+ return ~EOF;
}
static short makebody_tga(ImBuf *ibuf, FILE *file, int (*out)(unsigned int, FILE *))
@@ -153,9 +154,9 @@ static short makebody_tga(ImBuf *ibuf, FILE *file, int (*out)(unsigned int, FILE
last = copy;
if (copy >= 128) last = 128;
copy -= last;
- if (fputc(last - 1, file) == EOF) return(0);
+ if (fputc(last - 1, file) == EOF) return 0;
do {
- if (out(*rect++, file) == EOF) return(0);
+ if (out(*rect++, file) == EOF) return 0;
} while (--last != 0);
}
rectstart = rect;
@@ -176,23 +177,23 @@ static short makebody_tga(ImBuf *ibuf, FILE *file, int (*out)(unsigned int, FILE
while (copy) {
if (copy > 128) {
- if (fputc(255, file) == EOF) return(0);
+ if (fputc(255, file) == EOF) return 0;
copy -= 128;
}
else {
if (copy == 1) {
- if (fputc(0, file) == EOF) return(0);
+ if (fputc(0, file) == EOF) return 0;
}
- else if (fputc(127 + copy, file) == EOF) return(0);
+ else if (fputc(127 + copy, file) == EOF) return 0;
copy = 0;
}
- if (out(last, file) == EOF) return(0);
+ if (out(last, file) == EOF) return 0;
}
copy = TRUE;
}
}
}
- return (1);
+ return 1;
}
static int dumptarga(struct ImBuf *ibuf, FILE *file)
@@ -200,15 +201,15 @@ static int dumptarga(struct ImBuf *ibuf, FILE *file)
int size;
uchar *rect;
- if (ibuf == NULL) return (0);
- if (ibuf->rect == NULL) return (0);
+ if (ibuf == NULL) return 0;
+ if (ibuf->rect == NULL) return 0;
size = ibuf->x * ibuf->y;
rect = (uchar *) ibuf->rect;
if (ibuf->planes <= 8) {
while (size > 0) {
- if (putc(*rect, file) == EOF) return (0);
+ if (putc(*rect, file) == EOF) return 0;
size--;
rect += 4;
}
@@ -216,7 +217,7 @@ static int dumptarga(struct ImBuf *ibuf, FILE *file)
else if (ibuf->planes <= 16) {
while (size > 0) {
putc(rect[0], file);
- if (putc(rect[1], file) == EOF) return (0);
+ if (putc(rect[1], file) == EOF) return 0;
size--;
rect += 4;
}
@@ -225,7 +226,7 @@ static int dumptarga(struct ImBuf *ibuf, FILE *file)
while (size > 0) {
putc(rect[2], file);
putc(rect[1], file);
- if (putc(rect[0], file) == EOF) return (0);
+ if (putc(rect[0], file) == EOF) return 0;
size--;
rect += 4;
}
@@ -235,14 +236,16 @@ static int dumptarga(struct ImBuf *ibuf, FILE *file)
putc(rect[2], file);
putc(rect[1], file);
putc(rect[0], file);
- if (putc(rect[3], file) == EOF) return (0);
+ if (putc(rect[3], file) == EOF) return 0;
size--;
rect += 4;
}
}
- else return (0);
-
- return (1);
+ else {
+ return 0;
+ }
+
+ return 1;
}
@@ -284,7 +287,7 @@ int imb_savetarga(struct ImBuf *ibuf, const char *name, int flags)
if (fwrite(buf, 1, 18, fildes) != 18) {
fclose(fildes);
- return (0);
+ return 0;
}
if (ibuf->ftype == RAWTGA) {
@@ -308,7 +311,7 @@ int imb_savetarga(struct ImBuf *ibuf, const char *name, int flags)
}
fclose(fildes);
- return (ok);
+ return ok;
}
@@ -328,7 +331,7 @@ static int checktarga(TARGA *tga, unsigned char *mem)
tga->pixsize = mem[16];
tga->imgdes = mem[17];
- if (tga->maptyp > 1) return(0);
+ if (tga->maptyp > 1) return 0;
switch (tga->imgtyp) {
case 1: /* raw cmap */
case 2: /* raw rgb */
@@ -338,14 +341,14 @@ static int checktarga(TARGA *tga, unsigned char *mem)
case 11: /* b&w */
break;
default:
- return(0);
+ return 0;
}
- if (tga->mapsize && tga->mapbits > 32) return(0);
- if (tga->xsize <= 0 || tga->xsize >= 8192) return(0);
- if (tga->ysize <= 0 || tga->ysize >= 8192) return(0);
- if (tga->pixsize > 32) return(0);
- if (tga->pixsize == 0) return(0);
- return(1);
+ if (tga->mapsize && tga->mapbits > 32) return 0;
+ if (tga->xsize <= 0 || tga->xsize >= 8192) return 0;
+ if (tga->ysize <= 0 || tga->ysize >= 8192) return 0;
+ if (tga->pixsize > 32) return 0;
+ if (tga->pixsize == 0) return 0;
+ return 1;
}
int imb_is_a_targa(unsigned char *buf)
@@ -556,14 +559,16 @@ ImBuf *imb_loadtarga(unsigned char *mem, size_t mem_size, int flags, char colors
unsigned int *rect, *cmap = NULL /*, mincol = 0*/, maxcol = 0;
uchar *cp = (uchar *) &col;
- if (checktarga(&tga, mem) == 0) return(NULL);
+ if (checktarga(&tga, mem) == 0) {
+ return NULL;
+ }
colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
if (flags & IB_test) ibuf = IMB_allocImBuf(tga.xsize, tga.ysize, tga.pixsize, 0);
else ibuf = IMB_allocImBuf(tga.xsize, tga.ysize, (tga.pixsize + 0x7) & ~0x7, IB_rect);
- if (ibuf == NULL) return(NULL);
+ if (ibuf == NULL) return NULL;
ibuf->ftype = TGA;
mem = mem + 18 + tga.numid;
@@ -612,7 +617,9 @@ ImBuf *imb_loadtarga(unsigned char *mem, size_t mem_size, int flags, char colors
}
}
- if (flags & IB_test) return (ibuf);
+ if (flags & IB_test) {
+ return ibuf;
+ }
if (tga.imgtyp != 1 && tga.imgtyp != 9) { /* happens sometimes (beuh) */
if (cmap) {
@@ -692,5 +699,5 @@ ImBuf *imb_loadtarga(unsigned char *mem, size_t mem_size, int flags, char colors
if (ibuf->rect)
IMB_convert_rgba_to_abgr(ibuf);
- return(ibuf);
+ return ibuf;
}
diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c
index 94bb85b49ea..51c6c2fc2d9 100644
--- a/source/blender/imbuf/intern/thumbs.c
+++ b/source/blender/imbuf/intern/thumbs.c
@@ -34,6 +34,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
#include "BLI_string.h"
#include "BLI_path_util.h"
#include "BLI_fileops.h"
@@ -154,7 +155,7 @@ static void escape_uri_string(const char *string, char *escaped_string, int len,
*q++ = *p;
}
}
-
+
*q = '\0';
}
@@ -422,7 +423,7 @@ void IMB_thumb_delete(const char *path, ThumbSize size)
return;
}
if (BLI_exists(thumb)) {
- BLI_delete(thumb, 0, 0);
+ BLI_delete(thumb, false, false);
}
}
}
@@ -447,7 +448,7 @@ ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source)
if (BLI_exists(thumb)) {
/* clear out of date fail case */
if (BLI_file_older(thumb, path)) {
- BLI_delete(thumb, 0, 0);
+ BLI_delete(thumb, false, false);
}
else {
return NULL;
diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c
index 83830f260e1..2630aebef3b 100644
--- a/source/blender/imbuf/intern/tiff.c
+++ b/source/blender/imbuf/intern/tiff.c
@@ -376,7 +376,7 @@ static void imb_read_tiff_resolution(ImBuf *ibuf, TIFF *image)
* This method is most flexible and can handle multiple different bit depths
* and RGB channel orderings.
*/
-static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image, int premul)
+static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image)
{
ImBuf *tmpibuf;
int success = 0;
@@ -390,6 +390,23 @@ static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image, int premul)
TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp); /* number of 'channels' */
TIFFGetField(image, TIFFTAG_PLANARCONFIG, &config);
+ if (spp == 4) {
+ /* HACK: this is really tricky hack, which is only needed to force libtiff
+ * do not touch RGB channels when there's alpha channel present
+ * The thing is: libtiff will premul RGB if alpha mode is set to
+ * unassociated, which really conflicts with blender's assumptions
+ *
+ * Alternative would be to unpremul after load, but it'll be really
+ * lossy and unwanted behavior
+ *
+ * So let's keep this thing here for until proper solution is found (sergey)
+ */
+
+ unsigned short extraSampleTypes[1];
+ extraSampleTypes[0] = EXTRASAMPLE_ASSOCALPHA;
+ TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1, extraSampleTypes);
+ }
+
imb_read_tiff_resolution(ibuf, image);
scanline = TIFFScanlineSize(image);
@@ -471,10 +488,6 @@ static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image, int premul)
if (bitspersample < 16)
if (ENDIAN_ORDER == B_ENDIAN)
IMB_convert_rgba_to_abgr(tmpibuf);
- if (premul) {
- IMB_premultiply_alpha(tmpibuf);
- ibuf->flags |= IB_premul;
- }
/* assign rect last */
if (tmpibuf->rect_float)
@@ -557,6 +570,18 @@ ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[
return NULL;
}
+ /* get alpha mode from file header */
+ if (flags & IB_alphamode_detect) {
+ if (spp == 4) {
+ unsigned short extra, *extraSampleTypes;
+
+ TIFFGetField(image, TIFFTAG_EXTRASAMPLES, &extra, &extraSampleTypes);
+
+ if (extraSampleTypes[0] == EXTRASAMPLE_ASSOCALPHA)
+ ibuf->flags |= IB_alphamode_premul;
+ }
+ }
+
/* if testing, we're done */
if (flags & IB_test) {
TIFFClose(image);
@@ -585,9 +610,6 @@ ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[
hbuf->miplevel = level;
hbuf->ftype = ibuf->ftype;
ibuf->mipmap[level - 1] = hbuf;
-
- if (flags & IB_premul)
- hbuf->flags |= IB_premul;
}
else
hbuf = ibuf;
@@ -608,7 +630,7 @@ ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[
}
/* read pixels */
- if (!(ibuf->flags & IB_tilecache) && !imb_read_tiff_pixels(ibuf, image, 0)) {
+ if (!(ibuf->flags & IB_tilecache) && !imb_read_tiff_pixels(ibuf, image)) {
fprintf(stderr, "imb_loadtiff: Failed to read tiff image.\n");
TIFFClose(image);
return NULL;
@@ -644,9 +666,6 @@ void imb_loadtiletiff(ImBuf *ibuf, unsigned char *mem, size_t size, int tx, int
if (TIFFReadRGBATile(image, tx * ibuf->tilex, (ibuf->ytiles - 1 - ty) * ibuf->tiley, rect) == 1) {
if (ibuf->tiley > ibuf->y)
memmove(rect, rect + ibuf->tilex * (ibuf->tiley - ibuf->y), sizeof(int) * ibuf->tilex * ibuf->y);
-
- if (ibuf->flags & IB_premul)
- IMB_premultiply_rect(rect, 32, ibuf->tilex, ibuf->tiley);
}
else
printf("imb_loadtiff: failed to read tiff tile at mipmap level %d\n", ibuf->miplevel);
@@ -689,8 +708,6 @@ int imb_savetiff(ImBuf *ibuf, const char *name, int flags)
float *fromf = NULL;
float xres, yres;
int x, y, from_i, to_i, i;
- int extraSampleTypes[1] = { EXTRASAMPLE_ASSOCALPHA };
-
/* check for a valid number of bytes per pixel. Like the PNG writer,
* the TIFF writer supports 1, 3 or 4 bytes per pixel, corresponding
@@ -763,6 +780,13 @@ int imb_savetiff(ImBuf *ibuf, const char *name, int flags)
TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
if (samplesperpixel == 4) {
+ unsigned short extraSampleTypes[1];
+
+ if (bitspersample == 16)
+ extraSampleTypes[0] = EXTRASAMPLE_ASSOCALPHA;
+ else
+ extraSampleTypes[0] = EXTRASAMPLE_UNASSALPHA;
+
/* RGBA images */
TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1,
extraSampleTypes);
diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c
index 42fb0c79b62..68d1c906a1f 100644
--- a/source/blender/imbuf/intern/util.c
+++ b/source/blender/imbuf/intern/util.c
@@ -41,9 +41,9 @@
#include <stdlib.h>
+#include "BLI_utildefines.h"
#include "BLI_path_util.h"
#include "BLI_fileops.h"
-#include "BLI_utildefines.h"
#include "BLI_string.h"
#include "DNA_userdef_types.h"
@@ -306,8 +306,8 @@ static int isffmpeg(const char *filename)
return 0;
}
- if (av_find_stream_info(pFormatCtx) < 0) {
- if (UTIL_DEBUG) fprintf(stderr, "isffmpeg: av_find_stream_info failed\n");
+ if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
+ if (UTIL_DEBUG) fprintf(stderr, "isffmpeg: avformat_find_stream_info failed\n");
av_close_input_file(pFormatCtx);
return 0;
}
@@ -340,7 +340,7 @@ static int isffmpeg(const char *filename)
return 0;
}
- if (avcodec_open(pCodecCtx, pCodec) < 0) {
+ if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
av_close_input_file(pFormatCtx);
return 0;
}
diff --git a/source/blender/makesdna/CMakeLists.txt b/source/blender/makesdna/CMakeLists.txt
index 638d618d785..c60907060f7 100644
--- a/source/blender/makesdna/CMakeLists.txt
+++ b/source/blender/makesdna/CMakeLists.txt
@@ -23,4 +23,8 @@
#
# ***** END GPL LICENSE BLOCK *****
+if(WITH_FREESTYLE)
+ add_definitions(-DWITH_FREESTYLE)
+endif()
+
add_subdirectory(intern)
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index a769ce742c9..9103914c3e7 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -42,7 +42,9 @@ extern "C" {
struct Library;
struct FileData;
struct ID;
-
+struct PackedFile;
+struct GPUTexture;
+
typedef struct IDPropertyData {
void *pointer;
ListBase group;
@@ -102,7 +104,7 @@ typedef struct IDProperty {
/* 2 characters for ID code and 64 for actual name */
#define MAX_ID_NAME 66
-/* There's a nasty circular dependency here.... void* to the rescue! I
+/* There's a nasty circular dependency here.... 'void *' to the rescue! I
* really wonder why this is needed. */
typedef struct ID {
void *next, *prev;
@@ -136,6 +138,8 @@ typedef struct Library {
* setting 'name' directly and it will be kept in
* sync - campbell */
struct Library *parent; /* set for indirectly linked libs, used in the outliner and while reading */
+
+ struct PackedFile *packedfile;
} Library;
enum eIconSizes {
@@ -151,6 +155,7 @@ typedef struct PreviewImage {
short changed[2];
short changed_timestamp[2];
unsigned int *rect[2];
+ struct GPUTexture *gputexture[2];
} PreviewImage;
/**
@@ -207,6 +212,7 @@ typedef struct PreviewImage {
#define ID_WM MAKE_ID2('W', 'M') /* WindowManager */
#define ID_MC MAKE_ID2('M', 'C') /* MovieClip */
#define ID_MSK MAKE_ID2('M', 'S') /* Mask */
+#define ID_LS MAKE_ID2('L', 'S') /* FreestyleLineStyle */
/* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */
#define ID_SEQ MAKE_ID2('S', 'Q')
@@ -228,7 +234,8 @@ typedef struct PreviewImage {
#ifdef GS
# undef GS
#endif
-#define GS(a) (*((short *)(a)))
+// #define GS(a) (*((short *)(a)))
+#define GS(a) (CHECK_TYPE_INLINE(a, const char), (*((short *)(a))))
#define ID_NEW(a) if ( (a) && (a)->id.newid ) (a) = (void *)(a)->id.newid
#define ID_NEW_US(a) if ( (a)->id.newid) { (a) = (void *)(a)->id.newid; (a)->id.us++; }
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index f227af78dab..eded0b4b76e 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -27,6 +27,10 @@
/** \file DNA_action_types.h
* \ingroup DNA
+ *
+ * Define actions data-block for the animation system.
+ * A collection of animation curves and drivers to be assigned to data-blocks
+ * or sequenced in the non-linear-editor (NLA).
*/
#ifndef __DNA_ACTION_TYPES_H__
@@ -556,6 +560,7 @@ typedef enum eDopeSheet_FilterFlag {
ADS_FILTER_NONTREE = (1 << 19),
ADS_FILTER_NOTEX = (1 << 20),
ADS_FILTER_NOSPK = (1 << 21),
+ ADS_FILTER_NOLINESTYLE = (1 << 22),
/* 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 */
@@ -689,4 +694,4 @@ typedef enum ACHAN_FLAG {
ACHAN_MOVED = (1 << 31)
} ACHAN_FLAG;
-#endif
+#endif /* __DNA_ACTION_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h
index b445d59db2c..1495ba1b1a5 100644
--- a/source/blender/makesdna/DNA_actuator_types.h
+++ b/source/blender/makesdna/DNA_actuator_types.h
@@ -27,6 +27,8 @@
/** \file DNA_actuator_types.h
* \ingroup DNA
+ *
+ * #bActuator type is specifically for use by Object logic-bricks in the game-engine.
*/
#ifndef __DNA_ACTUATOR_TYPES_H__
@@ -277,10 +279,13 @@ typedef struct bActuator {
#define ACT_ANG_VEL_LOCAL 32
//#define ACT_ADD_LIN_VEL_LOCAL 64
#define ACT_ADD_LIN_VEL 64
+#define ACT_ADD_CHAR_LOC 128
+#define ACT_CHAR_JUMP 256
/* objectactuator->type */
-#define ACT_OBJECT_NORMAL 0
-#define ACT_OBJECT_SERVO 1
+#define ACT_OBJECT_NORMAL 0
+#define ACT_OBJECT_SERVO 1
+#define ACT_OBJECT_CHARACTER 2
/* actuator->type */
#define ACT_OBJECT 0
@@ -532,6 +537,4 @@ typedef struct bActuator {
#define ACT_STEERING_AUTOMATICFACING 4
#define ACT_STEERING_NORMALUP 8
-#endif
-
-
+#endif /* __DNA_ACTUATOR_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index 1ac6e6db94b..73e2a9f433b 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -284,15 +284,18 @@ typedef enum eDriverTarget_Flag {
/* used for targets that use the pchan_name instead of RNA path
* (i.e. rotation difference)
*/
- DTAR_FLAG_STRUCT_REF = (1<<0),
+ DTAR_FLAG_STRUCT_REF = (1 << 0),
/* idtype can only be 'Object' */
- DTAR_FLAG_ID_OB_ONLY = (1<<1),
+ DTAR_FLAG_ID_OB_ONLY = (1 << 1),
/* "localspace" flags */
/* base flag - basically "pre parent+constraints" */
- DTAR_FLAG_LOCALSPACE = (1<<2),
+ DTAR_FLAG_LOCALSPACE = (1 << 2),
/* include constraints transformed to space including parents */
- DTAR_FLAG_LOCAL_CONSTS = (1<<3),
+ DTAR_FLAG_LOCAL_CONSTS = (1 << 3),
+
+ /* error flags */
+ DTAR_FLAG_INVALID = (1 << 4),
} eDriverTarget_Flag;
/* Transform Channels for Driver Targets */
diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h
index fd68a6d9a27..8fcb079cd4f 100644
--- a/source/blender/makesdna/DNA_armature_types.h
+++ b/source/blender/makesdna/DNA_armature_types.h
@@ -198,7 +198,9 @@ typedef enum eBone_Flag {
BONE_EDITMODE_LOCKED = (1 << 19), /* bone transforms are locked in EditMode */
BONE_TRANSFORM_CHILD = (1 << 20), /* Indicates that a parent is also being transformed */
BONE_UNSELECTABLE = (1 << 21), /* bone cannot be selected */
- BONE_NO_LOCAL_LOCATION = (1 << 22) /* bone location is in armature space */
+ BONE_NO_LOCAL_LOCATION = (1 << 22), /* bone location is in armature space */
+ BONE_RELATIVE_PARENTING = (1 << 23) /* object child will use relative transform (like deform) */
+
} eBone_Flag;
#define MAXBONENAME 64
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index cc26ee479d7..147791b4835 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -71,6 +71,8 @@ typedef struct Brush {
int size; /* brush diameter */
int flag; /* general purpose flag */
float jitter; /* jitter the position of the brush */
+ int jitter_absolute; /* absolute jitter in pixels */
+ int pad;
int spacing; /* spacing of paint operations */
int smooth_stroke_radius; /* turning radius (in pixels) for smooth stroke */
float smooth_stroke_factor; /* higher values limit fast changes in the stroke direction */
@@ -112,7 +114,7 @@ typedef enum BrushFlags {
BRUSH_SIZE_PRESSURE = (1 << 3),
BRUSH_JITTER_PRESSURE = (1 << 4),
BRUSH_SPACING_PRESSURE = (1 << 5),
- BRUSH_FIXED_TEX = (1 << 6),
+ // BRUSH_FIXED_TEX = (1 << 6), /* obsolete, use mtex->brush_map_mode = MTEX_MAP_MODE_TILED instead */
BRUSH_RAKE = (1 << 7),
BRUSH_ANCHORED = (1 << 8),
BRUSH_DIR_IN = (1 << 9),
@@ -137,7 +139,8 @@ typedef enum BrushFlags {
/* temporary flag which sets up automatically for correct brush
* drawing when inverted modal operator is running */
- BRUSH_INVERTED = (1 << 29)
+ BRUSH_INVERTED = (1 << 29),
+ BRUSH_ABSOLUTE_JITTER = (1 << 30)
} BrushFlags;
/* Brush.sculpt_tool */
@@ -156,10 +159,7 @@ typedef enum BrushSculptTool {
SCULPT_TOOL_THUMB = 12,
SCULPT_TOOL_SNAKE_HOOK = 13,
SCULPT_TOOL_ROTATE = 14,
-
- /* slot 15 is free for use */
- /* SCULPT_TOOL_ = 15, */
-
+ SCULPT_TOOL_SIMPLIFY = 15,
SCULPT_TOOL_CREASE = 16,
SCULPT_TOOL_BLOB = 17,
SCULPT_TOOL_CLAY_STRIPS = 18,
@@ -167,10 +167,12 @@ typedef enum BrushSculptTool {
} BrushSculptTool;
/* ImagePaintSettings.tool */
-#define PAINT_TOOL_DRAW 0
-#define PAINT_TOOL_SOFTEN 1
-#define PAINT_TOOL_SMEAR 2
-#define PAINT_TOOL_CLONE 3
+typedef enum BrushImagePaintTool {
+ PAINT_TOOL_DRAW = 0,
+ PAINT_TOOL_SOFTEN = 1,
+ PAINT_TOOL_SMEAR = 2,
+ PAINT_TOOL_CLONE = 3
+} BrushImagePaintTool;
/* direction that the brush displaces along */
enum {
diff --git a/source/blender/makesdna/DNA_controller_types.h b/source/blender/makesdna/DNA_controller_types.h
index bdfedb5b4d1..0c1aaf5fd20 100644
--- a/source/blender/makesdna/DNA_controller_types.h
+++ b/source/blender/makesdna/DNA_controller_types.h
@@ -27,6 +27,8 @@
/** \file DNA_controller_types.h
* \ingroup DNA
+ *
+ * #bController type is specifically for use by Object logic-bricks in the game-engine.
*/
#ifndef __DNA_CONTROLLER_TYPES_H__
@@ -89,5 +91,4 @@ typedef struct bController {
#define CONT_PY_SCRIPT 0
#define CONT_PY_MODULE 1
-#endif
-
+#endif /* __DNA_CONTROLLER_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h
index 6f7bb5a723e..8debadf24c3 100644
--- a/source/blender/makesdna/DNA_customdata_types.h
+++ b/source/blender/makesdna/DNA_customdata_types.h
@@ -27,6 +27,8 @@
/** \file DNA_customdata_types.h
* \ingroup DNA
+ *
+ * Used for custom mesh data types (stored per vert/edge/loop/face)
*/
#ifndef __DNA_CUSTOMDATA_TYPES_H__
@@ -46,7 +48,7 @@ typedef struct CustomDataLayer {
int active_clone; /* number of the layer to render*/
int active_mask; /* number of the layer to render*/
int uid; /* shape keyblock unique id reference*/
- char name[64]; /* layer name, MAX_CUSTOMDATA_LAYER_AAME */
+ char name[64]; /* layer name, MAX_CUSTOMDATA_LAYER_NAME */
void *data; /* layer data */
} CustomDataLayer;
@@ -61,7 +63,7 @@ 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[37]; /* runtime only! - maps types to indices of first layer of that type,
+ int typemap[39]; /* 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 totlayer, maxlayer; /* number of layers, size of layers array */
@@ -112,7 +114,9 @@ typedef struct CustomData {
#define CD_PAINT_MASK 34
#define CD_GRID_PAINT_MASK 35
#define CD_MVERT_SKIN 36
-#define CD_NUMTYPES 37
+#define CD_FREESTYLE_EDGE 37
+#define CD_FREESTYLE_FACE 38
+#define CD_NUMTYPES 39
/* Bits for CustomDataMask */
#define CD_MASK_MVERT (1 << CD_MVERT)
@@ -154,6 +158,8 @@ typedef struct CustomData {
#define CD_MASK_PAINT_MASK (1LL << CD_PAINT_MASK)
#define CD_MASK_GRID_PAINT_MASK (1LL << CD_GRID_PAINT_MASK)
#define CD_MASK_MVERT_SKIN (1LL << CD_MVERT_SKIN)
+#define CD_MASK_FREESTYLE_EDGE (1LL << CD_FREESTYLE_EDGE)
+#define CD_MASK_FREESTYLE_FACE (1LL << CD_FREESTYLE_FACE)
/* CustomData.flag */
@@ -177,4 +183,4 @@ typedef struct CustomData {
}
#endif
-#endif
+#endif /* __DNA_CUSTOMDATA_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_defs.h b/source/blender/makesdna/DNA_defs.h
index 774fbcf081a..ffe4fc970b1 100644
--- a/source/blender/makesdna/DNA_defs.h
+++ b/source/blender/makesdna/DNA_defs.h
@@ -22,6 +22,8 @@
/** \file DNA_defs.h
* \ingroup DNA
+ *
+ * Group generic defines for all DNA headers may use in this file.
*/
#ifndef __DNA_DEFS_H__
diff --git a/source/blender/makesdna/DNA_freestyle_types.h b/source/blender/makesdna/DNA_freestyle_types.h
new file mode 100644
index 00000000000..01b28ca1700
--- /dev/null
+++ b/source/blender/makesdna/DNA_freestyle_types.h
@@ -0,0 +1,128 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __DNA_FREESTYLE_TYPES_H__
+#define __DNA_FREESTYLE_TYPES_H__
+
+#include "DNA_listBase.h"
+
+struct FreestyleLineStyle;
+
+/* 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)
+
+/* FreestyleConfig::mode */
+#define FREESTYLE_CONTROL_SCRIPT_MODE 1
+#define 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)
+
+/* 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)
+
+/* 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)
+
+/* FreestyleLineSet::qi */
+#define FREESTYLE_QI_VISIBLE 1
+#define FREESTYLE_QI_HIDDEN 2
+#define 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
+
+typedef struct FreestyleLineSet {
+ struct FreestyleLineSet *next, *prev;
+
+ char name[64]; /* line set name, MAX_NAME */
+ int flags;
+
+ int selection; /* selection criteria */
+ short qi; /* quantitative invisibility */
+ short pad1;
+ int qi_start, qi_end;
+ int edge_types, exclude_edge_types; /* feature edge types */
+ int pad2;
+ struct Group *group; /* group of target objects */
+
+ struct FreestyleLineStyle *linestyle;
+} FreestyleLineSet;
+
+typedef struct FreestyleModuleConfig {
+ struct FreestyleModuleConfig *next, *prev;
+
+ char module_path[1024]; /* FILE_MAX */
+ short is_displayed;
+ short pad[3];
+} FreestyleModuleConfig;
+
+typedef struct FreestyleConfig {
+ ListBase modules;
+
+ int mode; /* scripting, editor */
+ int raycasting_algorithm; /* XXX deprecated */
+ int flags; /* suggestive contours, ridges/valleys, material boundaries */
+ float sphere_radius;
+ float dkr_epsilon;
+ float crease_angle; /* in radians! */
+
+ ListBase linesets;
+} FreestyleConfig;
+
+#endif
diff --git a/source/blender/makesdna/DNA_genfile.h b/source/blender/makesdna/DNA_genfile.h
index 2d1549ff487..96d71288c62 100644
--- a/source/blender/makesdna/DNA_genfile.h
+++ b/source/blender/makesdna/DNA_genfile.h
@@ -35,9 +35,13 @@
struct SDNA;
-extern const unsigned char DNAstr[]; /* DNA.c */
-extern const int DNAlen;
+/* DNAstr contains the prebuilt SDNA structure defining the layouts of the types
+ * used by this version of Blender. It is defined in a file dna.c, which is
+ * generated by the makesdna program during the build process (see makesdna.c). */
+extern const unsigned char DNAstr[];
+extern const int DNAlen; /* length of DNAstr */
+/* primitive (non-struct, non-pointer/function/array) types--do not change ordering! */
typedef enum eSDNA_Type {
SDNA_TYPE_CHAR = 0,
SDNA_TYPE_UCHAR = 1,
@@ -56,7 +60,7 @@ typedef enum eSDNA_Type {
/* define so switch statements don't complain */
#define SDNA_TYPE_VOID 9
-struct SDNA *DNA_sdna_from_data(const void *data, const int datalen, int do_endian_swap);
+struct SDNA *DNA_sdna_from_data(const void *data, const int datalen, bool do_endian_swap);
void DNA_sdna_free(struct SDNA *sdna);
int DNA_struct_find_nr(struct SDNA *sdna, const char *str);
@@ -67,6 +71,8 @@ void *DNA_struct_reconstruct(struct SDNA *newsdna, struct SDNA *oldsdna, char *c
int DNA_elem_array_size(const char *astr, int len);
int DNA_elem_offset(struct SDNA *sdna, const char *stype, const char *vartype, const char *name);
+bool DNA_struct_elem_find(struct SDNA *sdna, const char *stype, const char *vartype, const char *name);
+
int DNA_elem_type_size(const eSDNA_Type elem_nr);
diff --git a/source/blender/makesdna/DNA_group_types.h b/source/blender/makesdna/DNA_group_types.h
index a084bee1c2d..2740281b4c0 100644
--- a/source/blender/makesdna/DNA_group_types.h
+++ b/source/blender/makesdna/DNA_group_types.h
@@ -27,6 +27,8 @@
/** \file DNA_group_types.h
* \ingroup DNA
+ *
+ * \brief Object groups, one object can be in many groups at once.
*/
#ifndef __DNA_GROUP_TYPES_H__
@@ -58,4 +60,4 @@ typedef struct Group {
float dupli_ofs[3];
} Group;
-#endif
+#endif /* __DNA_GROUP_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h
index fe3550327f7..54ec07c1855 100644
--- a/source/blender/makesdna/DNA_image_types.h
+++ b/source/blender/makesdna/DNA_image_types.h
@@ -101,16 +101,21 @@ typedef struct Image {
float lastupdate;
int lastused;
short animspeed;
+ short pad2;
/* for generated images */
- short gen_x, gen_y;
+ int gen_x, gen_y;
char gen_type, gen_flag;
+ char gen_pad[2];
/* display aspect - for UV editing images resized for faster openGL display */
float aspx, aspy;
/* color management */
ColorManagedColorspaceSettings colorspace_settings;
+ char alpha_mode;
+
+ char pad[7];
} Image;
@@ -119,15 +124,16 @@ typedef struct Image {
/* Image.flag */
#define IMA_FIELDS 1
#define IMA_STD_FIELD 2
-#define IMA_DO_PREMUL 4
+#define IMA_DO_PREMUL 4 /* deprecated, should not be used */
#define IMA_REFLECT 16
#define IMA_NOCOLLECT 32
-#define IMA_DEPRECATED 64
+#define IMA_DONE_TAG 64
#define IMA_OLD_PREMUL 128
-#define IMA_CM_PREDIVIDE 256
+/*#define IMA_CM_PREDIVIDE 256*/ /* deprecated, should not be used */
#define IMA_USED_FOR_RENDER 512
#define IMA_USER_FRAME_IN_RANGE 1024 /* for image user, but these flags are mixed */
#define IMA_VIEW_AS_RENDER 2048
+#define IMA_IGNORE_ALPHA 4096
/* Image.tpageflag */
#define IMA_TILES 1
@@ -148,4 +154,10 @@ typedef struct Image {
/* gen_flag */
#define IMA_GEN_FLOAT 1
+/* alpha_mode */
+enum {
+ IMA_ALPHA_STRAIGHT = 0,
+ IMA_ALPHA_PREMUL = 1,
+};
+
#endif
diff --git a/source/blender/makesdna/DNA_key_types.h b/source/blender/makesdna/DNA_key_types.h
index 6e5861043c1..4783247420c 100644
--- a/source/blender/makesdna/DNA_key_types.h
+++ b/source/blender/makesdna/DNA_key_types.h
@@ -29,6 +29,10 @@
/** \file DNA_key_types.h
* \ingroup DNA
+ *
+ * This file defines structures for Shape-Keys (not animation keyframes),
+ * attached to Mesh, Curve and Lattice Data. Even though Key's are ID blocks they
+ * aren't intended to be shared between multiple data blocks as with other ID types.
*/
#include "DNA_defs.h"
diff --git a/source/blender/makesdna/DNA_linestyle_types.h b/source/blender/makesdna/DNA_linestyle_types.h
new file mode 100644
index 00000000000..f5473d3d84a
--- /dev/null
+++ b/source/blender/makesdna/DNA_linestyle_types.h
@@ -0,0 +1,410 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __DNA_LINESTYLE_TYPES_H__
+#define __DNA_LINESTYLE_TYPES_H__
+
+#include "DNA_listBase.h"
+#include "DNA_ID.h"
+
+struct ColorBand;
+struct CurveMapping;
+
+typedef struct LineStyleModifier {
+ struct LineStyleModifier *next, *prev;
+
+ char name[64]; /* MAX_NAME */
+ int type;
+ float influence;
+ int flags;
+ int blend;
+
+} LineStyleModifier;
+
+/* LineStyleModifier::type */
+#define LS_MODIFIER_ALONG_STROKE 1
+#define LS_MODIFIER_DISTANCE_FROM_CAMERA 2
+#define LS_MODIFIER_DISTANCE_FROM_OBJECT 3
+#define LS_MODIFIER_MATERIAL 4
+#define LS_MODIFIER_SAMPLING 5
+#define LS_MODIFIER_BEZIER_CURVE 6
+#define LS_MODIFIER_SINUS_DISPLACEMENT 7
+#define LS_MODIFIER_SPATIAL_NOISE 8
+#define LS_MODIFIER_PERLIN_NOISE_1D 9
+#define LS_MODIFIER_PERLIN_NOISE_2D 10
+#define LS_MODIFIER_BACKBONE_STRETCHER 11
+#define LS_MODIFIER_TIP_REMOVER 12
+#define LS_MODIFIER_CALLIGRAPHY 13
+#define LS_MODIFIER_POLYGONIZATION 14
+#define LS_MODIFIER_GUIDING_LINES 15
+#define LS_MODIFIER_BLUEPRINT 16
+#define LS_MODIFIER_2D_OFFSET 17
+#define LS_MODIFIER_2D_TRANSFORM 18
+#define LS_MODIFIER_NUM 19
+
+/* LineStyleModifier::flags */
+#define LS_MODIFIER_ENABLED 1
+#define LS_MODIFIER_EXPANDED 2
+
+/* flags (for color) */
+#define LS_MODIFIER_USE_RAMP 1
+
+/* flags (for alpha & thickness) */
+#define LS_MODIFIER_USE_CURVE 1
+#define LS_MODIFIER_INVERT 2
+
+/* blend (for alpha & thickness) */
+#define LS_VALUE_BLEND 0
+#define LS_VALUE_ADD 1
+#define LS_VALUE_MULT 2
+#define LS_VALUE_SUB 3
+#define LS_VALUE_DIV 4
+#define LS_VALUE_DIFF 5
+#define LS_VALUE_MIN 6
+#define LS_VALUE_MAX 7
+
+/* Along Stroke modifiers */
+
+typedef struct LineStyleColorModifier_AlongStroke {
+ struct LineStyleModifier modifier;
+
+ struct ColorBand *color_ramp;
+} LineStyleColorModifier_AlongStroke;
+
+typedef struct LineStyleAlphaModifier_AlongStroke {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags;
+ int pad;
+} LineStyleAlphaModifier_AlongStroke;
+
+typedef struct LineStyleThicknessModifier_AlongStroke {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags;
+ float value_min, value_max;
+ int pad;
+} LineStyleThicknessModifier_AlongStroke;
+
+/* Distance from Camera modifiers */
+
+typedef struct LineStyleColorModifier_DistanceFromCamera {
+ struct LineStyleModifier modifier;
+
+ struct ColorBand *color_ramp;
+ float range_min, range_max;
+} LineStyleColorModifier_DistanceFromCamera;
+
+typedef struct LineStyleAlphaModifier_DistanceFromCamera {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags;
+ float range_min, range_max;
+ int pad;
+} LineStyleAlphaModifier_DistanceFromCamera;
+
+typedef struct LineStyleThicknessModifier_DistanceFromCamera {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags;
+ float range_min, range_max;
+ float value_min, value_max;
+ int pad;
+} LineStyleThicknessModifier_DistanceFromCamera;
+
+/* Distance from Object modifiers */
+
+typedef struct LineStyleColorModifier_DistanceFromObject {
+ struct LineStyleModifier modifier;
+
+ struct Object *target;
+ struct ColorBand *color_ramp;
+ float range_min, range_max;
+} LineStyleColorModifier_DistanceFromObject;
+
+typedef struct LineStyleAlphaModifier_DistanceFromObject {
+ struct LineStyleModifier modifier;
+
+ struct Object *target;
+ struct CurveMapping *curve;
+ int flags;
+ float range_min, range_max;
+ int pad;
+} LineStyleAlphaModifier_DistanceFromObject;
+
+typedef struct LineStyleThicknessModifier_DistanceFromObject {
+ struct LineStyleModifier modifier;
+
+ struct Object *target;
+ struct CurveMapping *curve;
+ int flags;
+ float range_min, range_max;
+ float value_min, value_max;
+ int pad;
+} LineStyleThicknessModifier_DistanceFromObject;
+
+/* Material modifiers */
+
+/* mat_attr */
+#define LS_MODIFIER_MATERIAL_DIFF 1
+#define LS_MODIFIER_MATERIAL_DIFF_R 2
+#define LS_MODIFIER_MATERIAL_DIFF_G 3
+#define LS_MODIFIER_MATERIAL_DIFF_B 4
+#define LS_MODIFIER_MATERIAL_SPEC 5
+#define LS_MODIFIER_MATERIAL_SPEC_R 6
+#define LS_MODIFIER_MATERIAL_SPEC_G 7
+#define LS_MODIFIER_MATERIAL_SPEC_B 8
+#define LS_MODIFIER_MATERIAL_SPEC_HARD 9
+#define LS_MODIFIER_MATERIAL_ALPHA 10
+
+typedef struct LineStyleColorModifier_Material {
+ struct LineStyleModifier modifier;
+
+ struct ColorBand *color_ramp;
+ int flags;
+ int mat_attr;
+} LineStyleColorModifier_Material;
+
+typedef struct LineStyleAlphaModifier_Material {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags;
+ int mat_attr;
+} LineStyleAlphaModifier_Material;
+
+typedef struct LineStyleThicknessModifier_Material {
+ struct LineStyleModifier modifier;
+
+ struct CurveMapping *curve;
+ int flags;
+ float value_min, value_max;
+ int mat_attr;
+} LineStyleThicknessModifier_Material;
+
+/* Geometry modifiers */
+
+typedef struct LineStyleGeometryModifier_Sampling {
+ struct LineStyleModifier modifier;
+
+ float sampling;
+ int pad;
+} LineStyleGeometryModifier_Sampling;
+
+typedef struct LineStyleGeometryModifier_BezierCurve {
+ struct LineStyleModifier modifier;
+
+ float error;
+ int pad;
+} LineStyleGeometryModifier_BezierCurve;
+
+typedef struct LineStyleGeometryModifier_SinusDisplacement {
+ struct LineStyleModifier modifier;
+
+ float wavelength, amplitude, phase;
+ int pad;
+} LineStyleGeometryModifier_SinusDisplacement;
+
+/* LineStyleGeometryModifier_SpatialNoise::flags */
+#define LS_MODIFIER_SPATIAL_NOISE_SMOOTH 1
+#define LS_MODIFIER_SPATIAL_NOISE_PURERANDOM 2
+
+typedef struct LineStyleGeometryModifier_SpatialNoise {
+ struct LineStyleModifier modifier;
+
+ float amplitude, scale;
+ unsigned int octaves;
+ int flags;
+} LineStyleGeometryModifier_SpatialNoise;
+
+typedef struct LineStyleGeometryModifier_PerlinNoise1D {
+ struct LineStyleModifier modifier;
+
+ float frequency, amplitude;
+ float angle; /* in radians! */
+ unsigned int octaves;
+ int seed;
+ int pad1;
+} LineStyleGeometryModifier_PerlinNoise1D;
+
+typedef struct LineStyleGeometryModifier_PerlinNoise2D {
+ struct LineStyleModifier modifier;
+
+ float frequency, amplitude;
+ float angle; /* in radians! */
+ unsigned int octaves;
+ int seed;
+ int pad1;
+} LineStyleGeometryModifier_PerlinNoise2D;
+
+typedef struct LineStyleGeometryModifier_BackboneStretcher {
+ struct LineStyleModifier modifier;
+
+ float backbone_length;
+ int pad;
+} LineStyleGeometryModifier_BackboneStretcher;
+
+typedef struct LineStyleGeometryModifier_TipRemover {
+ struct LineStyleModifier modifier;
+
+ float tip_length;
+ int pad;
+} LineStyleGeometryModifier_TipRemover;
+
+typedef struct LineStyleGeometryModifier_Polygonalization {
+ struct LineStyleModifier modifier;
+
+ float error;
+ int pad;
+} LineStyleGeometryModifier_Polygonalization;
+
+typedef struct LineStyleGeometryModifier_GuidingLines {
+ struct LineStyleModifier modifier;
+
+ float offset;
+ int pad;
+} LineStyleGeometryModifier_GuidingLines;
+
+/* LineStyleGeometryModifier_BluePrintLines::shape */
+#define LS_MODIFIER_BLUEPRINT_CIRCLES 1
+#define LS_MODIFIER_BLUEPRINT_ELLIPSES 2
+#define LS_MODIFIER_BLUEPRINT_SQUARES 4
+
+typedef struct LineStyleGeometryModifier_Blueprint {
+ struct LineStyleModifier modifier;
+
+ int flags;
+ unsigned int rounds;
+ float backbone_length;
+ unsigned int random_radius;
+ unsigned int random_center;
+ unsigned int random_backbone;
+} LineStyleGeometryModifier_Blueprint;
+
+typedef struct LineStyleGeometryModifier_2DOffset {
+ struct LineStyleModifier modifier;
+
+ float start, end;
+ float x, y;
+} LineStyleGeometryModifier_2DOffset;
+
+/* LineStyleGeometryModifier_2DTransform::pivot */
+#define LS_MODIFIER_2D_TRANSFORM_PIVOT_CENTER 1
+#define LS_MODIFIER_2D_TRANSFORM_PIVOT_START 2
+#define LS_MODIFIER_2D_TRANSFORM_PIVOT_END 3
+#define LS_MODIFIER_2D_TRANSFORM_PIVOT_PARAM 4
+#define LS_MODIFIER_2D_TRANSFORM_PIVOT_ABSOLUTE 5
+
+typedef struct LineStyleGeometryModifier_2DTransform {
+ struct LineStyleModifier modifier;
+
+ int pivot;
+ float scale_x, scale_y;
+ float angle; /* in radians! */
+ float pivot_u;
+ float pivot_x, pivot_y;
+ int pad;
+} LineStyleGeometryModifier_2DTransform;
+
+/* Calligraphic thickness modifier */
+
+typedef struct LineStyleThicknessModifier_Calligraphy {
+ struct LineStyleModifier modifier;
+
+ float min_thickness, max_thickness;
+ float orientation; /* in radians! */
+ int pad;
+} LineStyleThicknessModifier_Calligraphy;
+
+/* FreestyleLineStyle::panel */
+#define LS_PANEL_STROKES 1
+#define LS_PANEL_COLOR 2
+#define LS_PANEL_ALPHA 3
+#define LS_PANEL_THICKNESS 4
+#define LS_PANEL_GEOMETRY 5
+#define LS_PANEL_MISC 6
+
+/* FreestyleLineStyle::flag */
+#define LS_DS_EXPAND (1 << 0) /* for animation editors */
+#define LS_SAME_OBJECT (1 << 1)
+#define LS_DASHED_LINE (1 << 2)
+#define LS_MATERIAL_BOUNDARY (1 << 3)
+#define LS_MIN_2D_LENGTH (1 << 4)
+#define LS_MAX_2D_LENGTH (1 << 5)
+#define LS_NO_CHAINING (1 << 6)
+#define LS_MIN_2D_ANGLE (1 << 7)
+#define LS_MAX_2D_ANGLE (1 << 8)
+#define LS_SPLIT_LENGTH (1 << 9)
+#define LS_SPLIT_PATTERN (1 << 10)
+
+/* FreestyleLineStyle::chaining */
+#define LS_CHAINING_PLAIN 1
+#define LS_CHAINING_SKETCHY 2
+
+/* FreestyleLineStyle::caps */
+#define LS_CAPS_BUTT 1
+#define LS_CAPS_ROUND 2
+#define LS_CAPS_SQUARE 3
+
+/* FreestyleLineStyle::thickness_position */
+#define LS_THICKNESS_CENTER 1
+#define LS_THICKNESS_INSIDE 2
+#define LS_THICKNESS_OUTSIDE 3
+#define LS_THICKNESS_RELATIVE 4 /* thickness_ratio is used */
+
+typedef struct FreestyleLineStyle {
+ ID id;
+ struct AnimData *adt;
+
+ float r, g, b, alpha;
+ float thickness;
+ int thickness_position;
+ float thickness_ratio;
+ int flag, caps;
+ int chaining;
+ unsigned int rounds;
+ float split_length;
+ float min_angle, max_angle; /* in radians, for splitting */
+ float min_length, max_length;
+ unsigned short split_dash1, split_gap1;
+ unsigned short split_dash2, split_gap2;
+ unsigned short split_dash3, split_gap3;
+ int pad;
+ unsigned short dash1, gap1, dash2, gap2, dash3, gap3;
+ int panel; /* for UI */
+
+ ListBase color_modifiers;
+ ListBase alpha_modifiers;
+ ListBase thickness_modifiers;
+ ListBase geometry_modifiers;
+} FreestyleLineStyle;
+
+#endif
diff --git a/source/blender/makesdna/DNA_listBase.h b/source/blender/makesdna/DNA_listBase.h
index 333e414278d..f6035cd6653 100644
--- a/source/blender/makesdna/DNA_listBase.h
+++ b/source/blender/makesdna/DNA_listBase.h
@@ -31,6 +31,9 @@
* \ingroup DNA
* \brief These structs are the foundation for all linked lists in the
* library system.
+ *
+ * Doubly-linked lists start from a ListBase and contain elements beginning
+ * with Link.
*/
#ifndef __DNA_LISTBASE_H__
@@ -40,13 +43,13 @@
extern "C" {
#endif
-/* generic - all structs which are used in linked-lists used this */
+/* generic - all structs which are put into linked lists begin with this */
typedef struct Link {
struct Link *next, *prev;
} Link;
-/* use this when it is not worth defining a custom one... */
+/* simple subclass of Link--use this when it is not worth defining a custom one... */
typedef struct LinkData {
struct LinkData *next, *prev;
void *data;
diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h
index 5b25d1a072c..1b6b802f2de 100644
--- a/source/blender/makesdna/DNA_mask_types.h
+++ b/source/blender/makesdna/DNA_mask_types.h
@@ -30,6 +30,9 @@
* \ingroup DNA
* \since march-2012
* \author Sergey Sharybin
+ *
+ * Mask data-blocks are collections of 2D curves to be used
+ * for image masking in the compositor and sequencer.
*/
#ifndef __DNA_MASK_TYPES_H__
diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h
index 9a8d3bf981c..e23b85b5a4e 100644
--- a/source/blender/makesdna/DNA_material_types.h
+++ b/source/blender/makesdna/DNA_material_types.h
@@ -177,6 +177,9 @@ typedef struct Material {
short shadowonly_flag; /* "shadowsonly" type */
short index; /* custom index for render passes */
+ short vcol_alpha;
+ short pad4[3];
+
ListBase gpumaterial; /* runtime */
} Material;
@@ -309,7 +312,7 @@ typedef struct Material {
#define MA_SPEC_WARDISO 4
/* dynamode */
-#define MA_DRAW_DYNABUTS 1 /* deprecated */
+// #define MA_DRAW_DYNABUTS 1 /* deprecated */
#define MA_FH_NOR 2
/* ramps */
@@ -373,7 +376,7 @@ typedef struct Material {
#define MAP_AMB 2048
#define MAP_DISPLACE 4096
#define MAP_WARP 8192
-#define MAP_LAYER 16384 /* unused */
+// #define MAP_LAYER 16384 /* unused */
/* volume mapto - reuse definitions for now - a bit naughty! */
#define MAP_DENSITY 128
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index dd0845dbf1e..df8b423fcad 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -119,7 +119,10 @@ typedef struct Mesh {
short texflag, drawflag;
short smoothresh, flag;
- short subdiv DNA_DEPRECATED, subdivr DNA_DEPRECATED;
+ /* customdata flag, for bevel-weight and crease, which are now optional */
+ char cd_flag, pad;
+
+ char subdiv DNA_DEPRECATED, subdivr DNA_DEPRECATED;
char subsurftype DNA_DEPRECATED; /* only kept for backwards compat, not used anymore */
char editflag;
@@ -147,15 +150,15 @@ typedef struct TFace {
#define ME_EDIT_MIRROR_Y (1 << 1) // unused so far
#define ME_EDIT_MIRROR_Z (1 << 2) // unused so far
-#define ME_EDIT_PAINT_MASK (1 << 3)
+#define ME_EDIT_PAINT_FACE_SEL (1 << 3)
#define ME_EDIT_MIRROR_TOPO (1 << 4)
-#define ME_EDIT_VERT_SEL (1 << 5)
+#define ME_EDIT_PAINT_VERT_SEL (1 << 5)
/* we cant have both flags enabled at once,
* flags defined in DNA_scene_types.h */
#define ME_EDIT_PAINT_SEL_MODE(_me) ( \
- (_me->editflag & ME_EDIT_PAINT_MASK) ? SCE_SELECT_FACE : \
- (_me->editflag & ME_EDIT_VERT_SEL) ? SCE_SELECT_VERTEX : \
+ (_me->editflag & ME_EDIT_PAINT_FACE_SEL) ? SCE_SELECT_FACE : \
+ (_me->editflag & ME_EDIT_PAINT_VERT_SEL) ? SCE_SELECT_VERTEX : \
0 \
)
@@ -170,6 +173,14 @@ typedef struct TFace {
#define ME_SUBSURF 128
#define ME_OPT_EDGES 256
#define ME_DS_EXPAND 512
+#define ME_SCULPT_DYNAMIC_TOPOLOGY 1024
+
+/* me->cd_flag */
+#define ME_CDFLAG_VERT_BWEIGHT (1 << 0)
+#define ME_CDFLAG_EDGE_BWEIGHT (1 << 1)
+#define ME_CDFLAG_EDGE_CREASE (1 << 2)
+#define ME_CDFLAG_FREESTYLE_EDGE (1 << 3)
+#define ME_CDFLAG_FREESTYLE_FACE (1 << 4)
/* me->drawflag, short */
#define ME_DRAWEDGES (1 << 0)
@@ -177,7 +188,7 @@ typedef struct TFace {
#define ME_DRAWNORMALS (1 << 2)
#define ME_DRAW_VNORMALS (1 << 3)
-#define ME_ALLEDGES (1 << 4)
+// #define ME_ALLEDGES (1 << 4)
#define ME_HIDDENEDGES (1 << 5)
#define ME_DRAWCREASES (1 << 6)
@@ -192,6 +203,9 @@ typedef struct TFace {
/* debug only option */
#define ME_DRAWEXTRA_INDICES (1 << 13)
+#define ME_DRAW_FREESTYLE_EDGE (1 << 14)
+#define ME_DRAW_FREESTYLE_FACE (1 << 15)
+
/* Subsurf Type */
#define ME_CC_SUBSURF 0
#define ME_SIMPLE_SUBSURF 1
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index 0c193e9be21..0eba83dae55 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -118,9 +118,14 @@ typedef struct MLoopUV {
#define MLOOPUV_VERTSEL 2
#define MLOOPUV_PINNED 4
-/* at the moment alpha is abused for vertex painting
- * and not used for transparency,
- * note that red and blue are _not_ swapped, as they are with #MCol */
+/**
+ * at the moment alpha is abused for vertex painting,
+ * otherwise it should _always_ be initialized to 255
+ * Mostly its not used for transparency...
+ * (except for blender-internal rendering, see [#34096]).
+ *
+ * \note red and blue are _not_ swapped, as they are with #MCol
+ */
typedef struct MLoopCol {
char r, g, b, a;
} MLoopCol;
@@ -167,7 +172,7 @@ typedef struct MIntProperty {
int i;
} MIntProperty;
typedef struct MStringProperty {
- char s[256];
+ char s[255], s_len;
} MStringProperty;
typedef struct OrigSpaceFace {
@@ -274,6 +279,22 @@ typedef struct MVertSkin {
int flag;
} MVertSkin;
+typedef struct FreestyleEdge {
+ char flag;
+ char pad[3];
+} FreestyleEdge;
+
+/* FreestyleEdge->flag */
+#define FREESTYLE_EDGE_MARK 1
+
+typedef struct FreestyleFace {
+ char flag;
+ char pad[3];
+} FreestyleFace;
+
+/* FreestyleFace->flag */
+#define FREESTYLE_FACE_MARK 1
+
/* mvert->flag (1=SELECT) */
#define ME_SPHERETEST 2
#define ME_VERT_TMP_TAG 4
@@ -290,6 +311,7 @@ typedef struct MVertSkin {
#define ME_LOOSEEDGE (1<<7)
/* #define ME_SEAM_LAST (1<<8) */ /* UNUSED */
#define ME_SHARP (1<<9) /* only reason this flag remains a 'short' */
+#define ME_FREESTYLE_EDGE (1<<10) /* TO BE REMOVED when the trunk merger is done */
/* puno = vertexnormal (mface) */
#define ME_PROJXY 16
@@ -306,6 +328,7 @@ typedef struct MVertSkin {
/* flag (mface) */
#define ME_SMOOTH 1
#define ME_FACE_SEL 2
+#define ME_FREESTYLE_FACE 4 /* TO BE REMOVED when the trunk merger is done */
/* flag ME_HIDE==16 is used here too */
#define ME_POLY_LOOP_PREV(mloop, mp, i) (&(mloop)[(mp)->loopstart + (((i) + (mp)->totloop - 1) % (mp)->totloop)])
diff --git a/source/blender/makesdna/DNA_meta_types.h b/source/blender/makesdna/DNA_meta_types.h
index 5b37ff523cb..56683bf4797 100644
--- a/source/blender/makesdna/DNA_meta_types.h
+++ b/source/blender/makesdna/DNA_meta_types.h
@@ -121,6 +121,8 @@ typedef struct MetaBall {
#define MB_ELIPSOID 6
#define MB_CUBE 7
+#define MB_TYPE_SIZE_SQUARED(type) (type == MB_ELIPSOID)
+
/* ml->flag */
#define MB_NEGATIVE 2
#define MB_HIDE 8
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 68aa7600cd1..66685c131d4 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -76,7 +76,9 @@ typedef enum ModifierType {
eModifierType_Remesh = 41,
eModifierType_Skin = 42,
eModifierType_LaplacianSmooth = 43,
- eModifierType_Triangulate = 44,
+ eModifierType_Triangulate = 44,
+ eModifierType_UVWarp = 45,
+ eModifierType_MeshCache = 46,
NUM_MODIFIER_TYPES
} ModifierType;
@@ -742,6 +744,8 @@ typedef struct SolidifyModifierData {
float offset; /* new surface offset level*/
float offset_fac; /* midpoint of the offset */
float offset_fac_vg; /* factor for the minimum weight to use when vgroups are used, avoids 0.0 weights giving duplicate geometry */
+ float offset_clamp; /* clamp offset based on surrounding geometry */
+ float pad;
float crease_inner;
float crease_outer;
float crease_rim;
@@ -1132,6 +1136,7 @@ enum {
#define MOD_LAPLACIANSMOOTH_Y (1<<2)
#define MOD_LAPLACIANSMOOTH_Z (1<<3)
#define MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME (1 << 4)
+#define MOD_LAPLACIANSMOOTH_NORMALIZED (1 << 5)
typedef struct LaplacianSmoothModifierData {
ModifierData modifier;
@@ -1140,4 +1145,80 @@ typedef struct LaplacianSmoothModifierData {
short flag, repeat;
} LaplacianSmoothModifierData;
-#endif
+typedef struct UVWarpModifierData {
+ ModifierData modifier;
+
+ char axis_u, axis_v;
+ char pad[6];
+ float center[2]; /* used for rotate/scale */
+
+ struct Object *object_src; /* source */
+ char bone_src[64]; /* optional name of bone target, MAX_ID_NAME-2 */
+ struct Object *object_dst; /* target */
+ char bone_dst[64]; /* optional name of bone target, MAX_ID_NAME-2 */
+
+ char vgroup_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */
+ char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
+} UVWarpModifierData;
+
+/* cache modifier */
+typedef struct MeshCacheModifierData {
+ ModifierData modifier;
+ char flag;
+ char type; /* file format */
+ char time_mode;
+ char play_mode;
+
+ /* axis conversion */
+ char forward_axis;
+ char up_axis;
+ char flip_axis;
+
+ char interp;
+
+ float factor;
+ char deform_mode;
+ char pad[7];
+
+ /* play_mode == MOD_MESHCACHE_PLAY_CFEA */
+ float frame_start;
+ float frame_scale;
+
+ /* play_mode == MOD_MESHCACHE_PLAY_EVAL */
+ /* we could use one float for all these but their purpose is very different */
+ float eval_frame;
+ float eval_time;
+ float eval_factor;
+
+ char filepath[1024]; // FILE_MAX
+} MeshCacheModifierData;
+
+enum {
+ MOD_MESHCACHE_TYPE_MDD = 1,
+ MOD_MESHCACHE_TYPE_PC2 = 2
+};
+
+enum {
+ MOD_MESHCACHE_DEFORM_OVERWRITE = 0,
+ MOD_MESHCACHE_DEFORM_INTEGRATE = 1
+};
+
+enum {
+ MOD_MESHCACHE_INTERP_NONE = 0,
+ MOD_MESHCACHE_INTERP_LINEAR = 1,
+ // MOD_MESHCACHE_INTERP_CARDINAL = 2
+};
+
+enum {
+ MOD_MESHCACHE_TIME_FRAME = 0,
+ MOD_MESHCACHE_TIME_SECONDS = 1,
+ MOD_MESHCACHE_TIME_FACTOR = 2,
+};
+
+enum {
+ MOD_MESHCACHE_PLAY_CFEA = 0,
+ MOD_MESHCACHE_PLAY_EVAL = 1,
+};
+
+
+#endif /* __DNA_MODIFIER_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h
index 499f1c50155..119d2cdfdf7 100644
--- a/source/blender/makesdna/DNA_movieclip_types.h
+++ b/source/blender/makesdna/DNA_movieclip_types.h
@@ -98,6 +98,11 @@ typedef struct MovieClip {
/* color management */
ColorManagedColorspaceSettings colorspace_settings;
+
+ /* runtime prefetching stuff */
+ char prefetch_ok;
+
+ char pad[7];
} MovieClip;
typedef struct MovieClipScopes {
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index a05ff66e683..b6a5c758dc0 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -44,11 +44,19 @@ struct SpaceNode;
struct bNodeLink;
struct bNodeType;
struct bNodeTreeExec;
+struct bNodePreview;
+struct bNodeInstanceHash;
struct AnimData;
struct bGPdata;
struct uiBlock;
struct Image;
+/* In writefile.c: write deprecated DNA data,
+ * to ensure forward compatibility in 2.6x versions.
+ * Will be removed eventually.
+ */
+#define USE_NODE_COMPAT_CUSTOMNODES
+
#define NODE_MAXSTR 64
typedef struct bNodeStack {
@@ -79,13 +87,22 @@ typedef struct bNodeStack {
typedef struct bNodeSocket {
struct bNodeSocket *next, *prev, *new_sock;
+ IDProperty *prop; /* user-defined properties */
+
+ char identifier[64]; /* unique identifier for mapping */
+
char name[64]; /* MAX_NAME */
+ /* XXX deprecated, only used for the Image and OutputFile nodes,
+ * should be removed at some point.
+ */
void *storage; /* custom storage */
short type, flag;
short limit; /* max. number of links */
- short pad1;
+ short in_out; /* input/output type */
+ struct bNodeSocketType *typeinfo; /* runtime type information */
+ char idname[64]; /* runtime type identifier */
float locx, locy;
@@ -98,11 +115,14 @@ typedef struct bNodeSocket {
int resizemode; /* compositor resize mode of the socket */
void *cache; /* cached data from execution */
- /* internal data to retrieve relations and groups */
- int own_index; /* group socket identifiers, to find matching pairs after reading files */
+ /* internal data to retrieve relations and groups
+ * DEPRECATED, now uses the generic identifier string instead
+ */
+ int own_index DNA_DEPRECATED; /* group socket identifiers, to find matching pairs after reading files */
/* XXX deprecated, only used for restoring old group node links */
int to_index DNA_DEPRECATED;
- struct bNodeSocket *groupsock;
+ /* XXX deprecated, still forward compatible since verification restores pointer from matching own_index. */
+ struct bNodeSocket *groupsock DNA_DEPRECATED;
struct bNodeLink *link; /* a link pointer, set in ntreeUpdateTree */
@@ -111,31 +131,34 @@ typedef struct bNodeSocket {
} bNodeSocket;
/* sock->type */
+#define SOCK_CUSTOM -1 /* socket has no integer type */
#define SOCK_FLOAT 0
#define SOCK_VECTOR 1
#define SOCK_RGBA 2
#define SOCK_SHADER 3
#define SOCK_BOOLEAN 4
-#define SOCK_MESH 5
+#define __SOCK_MESH 5 /* deprecated */
#define SOCK_INT 6
#define SOCK_STRING 7
#define NUM_SOCKET_TYPES 8 /* must be last! */
/* socket side (input/output) */
-#define SOCK_IN 1
-#define SOCK_OUT 2
+typedef enum eNodeSocketInOut {
+ SOCK_IN = 1,
+ SOCK_OUT = 2
+} eNodeSocketInOut;
/* sock->flag, first bit is select */
/* hidden is user defined, to hide unused */
#define SOCK_HIDDEN 2
/* for quick check if socket is linked */
-#define SOCK_IN_USE 4 /* XXX deprecated */
+#define SOCK_IN_USE 4
/* unavailable is for dynamic sockets */
#define SOCK_UNAVAIL 8
- /* dynamic socket (can be modified by user) */
-#define SOCK_DYNAMIC 16
- /* group socket should not be exposed */
-#define SOCK_INTERNAL 32
+ /* DEPRECATED dynamic socket (can be modified by user) */
+#define __SOCK_DYNAMIC 16
+ /* DEPRECATED group socket should not be exposed */
+#define __SOCK_INTERNAL 32
/* socket collapsed in UI */
#define SOCK_COLLAPSED 64
/* hide socket value, if it gets auto default */
@@ -144,19 +167,18 @@ typedef struct bNodeSocket {
/* DEPRECATED, only kept here to avoid reusing the flag */
#define SOCK_AUTO_HIDDEN__DEPRECATED 256
-typedef struct bNodePreview {
- unsigned char *rect;
- short xsize, ysize;
- int pad;
-} bNodePreview;
-
/* limit data in bNode to what we want to see saved? */
typedef struct bNode {
struct bNode *next, *prev, *new_node;
+
+ IDProperty *prop; /* user-defined properties */
+
+ struct bNodeType *typeinfo; /* runtime type information */
+ char idname[64]; /* runtime type identifier */
char name[64]; /* MAX_NAME */
int flag;
- short type, pad2;
+ short type, pad;
short done, level; /* both for dependency and sorting */
short lasty, menunr; /* lasty: check preview render status, menunr: browse ID blocks */
short stack_index; /* for groupnode, offset in global caller stack */
@@ -186,10 +208,17 @@ typedef struct bNode {
rctf totr; /* entire boundbox (worldspace) */
rctf butr; /* optional buttons area */
rctf prvr; /* optional preview area */
- bNodePreview *preview; /* optional preview image */
+ /* XXX TODO
+ * Node totr size depends on the prvr size, which in turn is determined from preview size.
+ * In earlier versions bNodePreview was stored directly in nodes, but since now there can be
+ * multiple instances using different preview images it is possible that required node size varies between instances.
+ * preview_xsize, preview_ysize defines a common reserved size for preview rect for now,
+ * could be replaced by more accurate node instance drawing, but that requires removing totr from DNA
+ * and replacing all uses with per-instance data.
+ */
+ short preview_xsize, preview_ysize; /* reserved size of the preview rect */
+ int pad2;
struct uiBlock *block; /* runtime during drawing */
-
- struct bNodeType *typeinfo; /* lookup of callbacks and defaults */
} bNode;
/* node->flag */
@@ -200,7 +229,7 @@ typedef struct bNode {
#define NODE_ACTIVE 16
#define NODE_ACTIVE_ID 32
#define NODE_DO_OUTPUT 64
-#define NODE_GROUP_EDIT 128
+#define __NODE_GROUP_EDIT 128 /* DEPRECATED */
/* free test flag, undefined */
#define NODE_TEST 256
/* node is disabled */
@@ -221,6 +250,17 @@ typedef struct bNode {
#define NODE_ACTIVE_TEXTURE (1<<14)
/* use a custom color for the node */
#define NODE_CUSTOM_COLOR (1<<15)
+ /* Node has been initialized
+ * This flag indicates the node->typeinfo->init function has been called.
+ * In case of undefined type at creation time this can be delayed until
+ * until the node type is registered.
+ */
+#define NODE_INIT (1<<16)
+
+ /* do recalc of output, used to skip recalculation of unwanted
+ * composite out nodes when editing tree
+ */
+#define NODE_DO_OUTPUT_RECALC (1<<17)
/* node->update */
/* XXX NODE_UPDATE is a generic update flag. More fine-grained updates
@@ -229,6 +269,36 @@ typedef struct bNode {
#define NODE_UPDATE 0xFFFF /* generic update flag (includes all others) */
#define NODE_UPDATE_ID 1 /* associated id data block has changed */
+/* Unique hash key for identifying node instances
+ * Defined as a struct because DNA does not support other typedefs.
+ */
+typedef struct bNodeInstanceKey
+{
+ unsigned int value;
+} bNodeInstanceKey;
+
+/* Base struct for entries in node instance hash.
+ * WARNING: pointers are cast to this struct internally,
+ * it must be first member in hash entry structs!
+ */
+typedef struct bNodeInstanceHashEntry {
+ bNodeInstanceKey key;
+
+ /* tags for cleaning the cache */
+ short tag;
+ short pad;
+} bNodeInstanceHashEntry;
+
+
+typedef struct bNodePreview {
+ bNodeInstanceHashEntry hash_entry; /* must be first */
+
+ unsigned char *rect;
+ short xsize, ysize;
+ int pad;
+} bNodePreview;
+
+
typedef struct bNodeLink {
struct bNodeLink *next, *prev;
@@ -263,7 +333,13 @@ typedef struct bNodeTree {
ID id;
struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */
+ struct bNodeTreeType *typeinfo; /* runtime type information */
+ char idname[64]; /* runtime type identifier */
+
+ struct StructRNA *interface_type; /* runtime RNA type of the group interface */
+
struct bGPdata *gpd; /* grease pencil data */
+ float view_center[2]; /* node tree stores own offset for consistent editor view */
ListBase nodes, links;
@@ -272,14 +348,28 @@ typedef struct bNodeTree {
* will increase this counter */
int flag;
int update; /* update flags */
+ short is_updating; /* flag to prevent reentrant update calls */
+ short done; /* generic temporary flag for recursion check (DFS/BFS) */
+ int pad2;
- int nodetype; /* specific node type this tree is used for */
+ int nodetype DNA_DEPRECATED; /* specific node type this tree is used for */
short edit_quality; /* Quality setting when editing */
short render_quality; /* Quality setting when rendering */
int chunksize; /* tile size for compositor engine */
- ListBase inputs, outputs; /* external sockets for group nodes */
+ rctf viewer_border;
+
+ /* Lists of bNodeSocket to hold default values and own_index.
+ * Warning! Don't make links to these sockets, input/output nodes are used for that.
+ * These sockets are used only for generating external interfaces.
+ */
+ ListBase inputs, outputs;
+
+ /* Node preview hash table
+ * Only available in base node trees (e.g. scene->node_tree)
+ */
+ struct bNodeInstanceHash *previews;
/* execution data */
/* XXX It would be preferable to completely move this data out of the underlying node tree,
@@ -300,33 +390,42 @@ typedef struct bNodeTree {
} bNodeTree;
/* ntree->type, index */
+#define NTREE_CUSTOM -1 /* for dynamically registered custom types */
#define NTREE_SHADER 0
#define NTREE_COMPOSIT 1
#define NTREE_TEXTURE 2
-#define NUM_NTREE_TYPES 3
/* ntree->init, flag */
#define NTREE_TYPE_INIT 1
/* ntree->flag */
-#define NTREE_DS_EXPAND 1 /* for animation editors */
-#define NTREE_COM_OPENCL 2 /* use opencl */
-#define NTREE_TWO_PASS 4 /* two pass */
+#define NTREE_DS_EXPAND 1 /* for animation editors */
+#define NTREE_COM_OPENCL 2 /* use opencl */
+#define NTREE_TWO_PASS 4 /* two pass */
+#define NTREE_COM_GROUPNODE_BUFFER 8 /* use groupnode buffers */
+#define NTREE_VIEWER_BORDER 16 /* use a border for viewer nodes */
+
/* XXX not nice, but needed as a temporary flags
* for group updates after library linking.
*/
-#define NTREE_DO_VERSIONS_GROUP_EXPOSE 1024
+#define NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2 1024 /* changes from r35033 */
+#define NTREE_DO_VERSIONS_CUSTOMNODES_GROUP 2048 /* custom_nodes branch: remove links to node tree sockets */
+#define NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE 4096 /* custom_nodes branch: create group input/output nodes */
/* ntree->update */
-#define NTREE_UPDATE 0xFFFF /* generic update flag (includes all others) */
-#define NTREE_UPDATE_LINKS 1 /* links have been added or removed */
-#define NTREE_UPDATE_NODES 2 /* nodes or sockets have been added or removed */
-#define NTREE_UPDATE_GROUP_IN 16 /* group inputs have changed */
-#define NTREE_UPDATE_GROUP_OUT 32 /* group outputs have changed */
-#define NTREE_UPDATE_GROUP 48 /* group has changed (generic flag including all other group flags) */
-
-
-/* socket value structs for input buttons */
+typedef enum eNodeTreeUpdate {
+ NTREE_UPDATE = 0xFFFF, /* generic update flag (includes all others) */
+ NTREE_UPDATE_LINKS = 1, /* links have been added or removed */
+ NTREE_UPDATE_NODES = 2, /* nodes or sockets have been added or removed */
+ NTREE_UPDATE_GROUP_IN = 16, /* group inputs have changed */
+ NTREE_UPDATE_GROUP_OUT = 32, /* group outputs have changed */
+ NTREE_UPDATE_GROUP = 48 /* group has changed (generic flag including all other group flags) */
+} eNodeTreeUpdate;
+
+
+/* socket value structs for input buttons
+ * DEPRECATED now using ID properties
+ */
typedef struct bNodeSocketValueInt {
int subtype; /* RNA subtype */
@@ -711,6 +810,13 @@ typedef struct NodeTrackPosData {
char track_name[64];
} NodeTrackPosData;
+typedef struct NodeTranslateData {
+ char wrap_axis;
+ char relative;
+ char pad[6];
+} NodeTranslateData;
+
+
typedef struct NodeShaderScript {
int mode;
int flag;
@@ -719,8 +825,6 @@ typedef struct NodeShaderScript {
char bytecode_hash[64];
char *bytecode;
-
- IDProperty *prop;
} NodeShaderScript;
typedef struct NodeShaderTangent {
@@ -746,6 +850,9 @@ typedef struct NodeShaderNormalMap {
#define NODE_FRAME_SHRINK 1 /* keep the bounding box minimal */
#define NODE_FRAME_RESIZEABLE 2 /* test flag, if frame can be resized by user */
+/* proxy node flags */
+#define NODE_PROXY_AUTOTYPE 1 /* automatically change output type based on link */
+
/* comp channel matte */
#define CMP_NODE_CHANNEL_MATTE_CS_RGB 1
#define CMP_NODE_CHANNEL_MATTE_CS_HSV 2
@@ -837,6 +944,51 @@ typedef struct NodeShaderNormalMap {
#define CMP_NODE_BLUR_ASPECT_Y 1
#define CMP_NODE_BLUR_ASPECT_X 2
+/* wrapping */
+#define CMP_NODE_WRAP_NONE 0
+#define CMP_NODE_WRAP_X 1
+#define CMP_NODE_WRAP_Y 2
+#define CMP_NODE_WRAP_XY 3
+
#define CMP_NODE_MASK_MBLUR_SAMPLES_MAX 64
+/* geometry output socket defines */
+#define GEOM_OUT_GLOB 0
+#define GEOM_OUT_LOCAL 1
+#define GEOM_OUT_VIEW 2
+#define GEOM_OUT_ORCO 3
+#define GEOM_OUT_UV 4
+#define GEOM_OUT_NORMAL 5
+#define GEOM_OUT_VCOL 6
+#define GEOM_OUT_VCOL_ALPHA 7
+#define GEOM_OUT_FRONTBACK 8
+
+/* material input socket defines */
+#define MAT_IN_COLOR 0
+#define MAT_IN_SPEC 1
+#define MAT_IN_REFL 2
+#define MAT_IN_NORMAL 3
+#define MAT_IN_MIR 4
+#define MAT_IN_AMB 5
+#define MAT_IN_EMIT 6
+#define MAT_IN_SPECTRA 7
+#define MAT_IN_RAY_MIRROR 8
+#define MAT_IN_ALPHA 9
+#define MAT_IN_TRANSLUCENCY 10
+#define NUM_MAT_IN 11 /* for array size */
+
+/* material output socket defines */
+#define MAT_OUT_COLOR 0
+#define MAT_OUT_ALPHA 1
+#define MAT_OUT_NORMAL 2
+#define MAT_OUT_DIFFUSE 3
+#define MAT_OUT_SPEC 4
+#define MAT_OUT_AO 5
+
+/* image */
+#define CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT 1
+
+/* viewer and cmposite output */
+#define CMP_NODE_OUTPUT_IGNORE_ALPHA 1
+
#endif
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 89328c33674..de34f101c31 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -56,6 +56,7 @@ struct ParticleSystem;
struct DerivedMesh;
struct SculptSession;
struct bGPdata;
+struct RigidBodyOb;
/* Vertex Groups - Name Info */
@@ -170,7 +171,7 @@ typedef struct Object {
float sf; /* sf is time-offset */
short flag; /* copy of Base */
- short colbits DNA_DEPRECATED; /* deprecated */
+ short colbits DNA_DEPRECATED; /* deprecated, use 'matbits' */
short transflag, protectflag; /* transformation settings and transform locks */
short trackflag, upflag;
@@ -178,7 +179,7 @@ typedef struct Object {
short ipoflag; // xxx deprecated... old animation system
short scaflag; /* ui state for game logic */
char scavisflag; /* more display settings for game logic */
- char pad5;
+ char depsflag;
int dupon, dupoff, dupsta, dupend;
@@ -218,10 +219,8 @@ typedef struct Object {
char boundtype; /* bounding box use for drawing */
char collision_boundtype; /* bounding box type used for collision */
- char restrictflag; /* for restricting view, select, render etc. accessible in outliner */
-
+ short dtx; /* viewport draw extra settings */
char dt; /* viewport draw type */
- char dtx; /* viewport draw extra settings */
char empty_drawtype;
float empty_drawsize;
float dupfacesca; /* dupliface scale */
@@ -241,8 +240,9 @@ typedef struct Object {
struct BulletSoftBody *bsoft; /* settings for game engine bullet soft body */
+ char restrictflag; /* for restricting view, select, render etc. accessible in outliner */
+ char recalc; /* dependency flag */
short softflag; /* softbody settings */
- short recalc; /* dependency flag */
float anisotropicFriction[3];
ListBase constraints; /* object constraints */
@@ -271,6 +271,9 @@ typedef struct Object {
ListBase gpulamp; /* runtime, for glsl lamp display only */
ListBase pc_ids;
ListBase *duplilist; /* for temporary dupli list storage, only for use by RNA API */
+
+ struct RigidBodyOb *rigidbody_object; /* settings for Bullet rigid body */
+ struct RigidBodyCon *rigidbody_constraint; /* settings for Bullet constraint */
float ima_ofs[2]; /* offset for image empties */
} Object;
@@ -348,6 +351,9 @@ typedef struct DupliObject {
#define OB_DATA_SUPPORT_ID(_id_type) \
(ELEM8(_id_type, ID_ME, ID_CU, ID_MB, ID_LA, ID_SPK, ID_CA, ID_LT, ID_AR))
+#define OB_DATA_SUPPORT_ID_CASE \
+ ID_ME: case ID_CU: case ID_MB: case ID_LA: case ID_SPK: case ID_CA: case ID_LT: case ID_AR
+
/* partype: first 4 bits: type */
#define PARTYPE 15
#define PAROBJECT 0
@@ -406,17 +412,19 @@ typedef struct DupliObject {
#define OB_PAINT 100 /* temporary used in draw code */
-/* dtx: flags, char! */
-#define OB_AXIS 2
-#define OB_TEXSPACE 4
-#define OB_DRAWNAME 8
-#define OB_DRAWIMAGE 16
+/* dtx: flags (short) */
+#define OB_DRAWBOUNDOX (1 << 0)
+#define OB_AXIS (1 << 1)
+#define OB_TEXSPACE (1 << 2)
+#define OB_DRAWNAME (1 << 3)
+#define OB_DRAWIMAGE (1 << 4)
/* for solid+wire display */
-#define OB_DRAWWIRE 32
- /* for overdraw */
-#define OB_DRAWXRAY 64
+#define OB_DRAWWIRE (1 << 5)
+ /* for overdraw s*/
+#define OB_DRAWXRAY (1 << 6)
/* enable transparent draw */
-#define OB_DRAWTRANSP 128
+#define OB_DRAWTRANSP (1 << 7)
+#define OB_DRAW_ALL_EDGES (1 << 8) /* only for meshes currently */
/* empty_drawtype: no flags */
#define OB_ARROWS 1
@@ -530,6 +538,10 @@ typedef struct DupliObject {
#define OB_BODY_TYPE_NAVMESH 7
#define OB_BODY_TYPE_CHARACTER 8
+/* ob->depsflag */
+#define OB_DEPS_EXTRA_OB_RECALC 1
+#define OB_DEPS_EXTRA_DATA_RECALC 2
+
/* ob->scavisflag */
#define OB_VIS_SENS 1
#define OB_VIS_CONT 2
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index 5952aa8afb0..ec2a724ac82 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -116,6 +116,9 @@ typedef struct ParticleData {
float size; /* size and multiplier so that we can update size when ever */
+ float sphdensity; /* density of sph particle */
+ int pad;
+
int hair_index;
short flag;
short alive; /* the life state of a particle */
@@ -130,6 +133,8 @@ typedef struct SPHFluidSettings {
float stiffness_k, stiffness_knear, rest_density;
float buoyancy;
int flag, spring_frames;
+ short solver;
+ short pad[3];
} SPHFluidSettings;
/* fluid->flag */
@@ -141,6 +146,10 @@ typedef struct SPHFluidSettings {
#define SPH_FAC_VISCOSITY 32
#define SPH_FAC_REST_LENGTH 64
+/* fluid->solver (numerical ID field, not bitfield) */
+#define SPH_SOLVER_DDR 0
+#define SPH_SOLVER_CLASSICAL 1
+
typedef struct ParticleSettings {
ID id;
struct AnimData *adt;
@@ -164,7 +173,8 @@ typedef struct ParticleSettings {
/* adaptive path rendering */
short adapt_angle, adapt_pix;
- short disp, omat, interpolation, rotfrom, integrator;
+ short disp, omat, interpolation, integrator;
+ short rotfrom DNA_DEPRECATED;
short kink, kink_axis;
/* billboards */
@@ -350,11 +360,6 @@ typedef struct ParticleSystem {
#define PART_SELF_EFFECT (1<<22)
-/* part->rotfrom */
-#define PART_ROT_KEYS 0 /* interpolate directly from keys */
-#define PART_ROT_ZINCR 1 /* same as zdir but done incrementally from previous position */
-#define PART_ROT_IINCR 2 /* same as idir but done incrementally from previous position */
-
/* part->from */
#define PART_FROM_VERT 0
#define PART_FROM_FACE 1
diff --git a/source/blender/makesdna/DNA_property_types.h b/source/blender/makesdna/DNA_property_types.h
index c1b810cd42b..c8275a41404 100644
--- a/source/blender/makesdna/DNA_property_types.h
+++ b/source/blender/makesdna/DNA_property_types.h
@@ -31,6 +31,8 @@
* \author nzc
* \attention Renderrecipe and scene decription. The fact that there is a
* hierarchy here is a bit strange, and not desirable.
+ *
+ * #bProperty type is specifically for use by Objects game-logic.
*/
#ifndef __DNA_PROPERTY_TYPES_H__
@@ -60,5 +62,4 @@ typedef struct bProperty {
#define MAX_PROPSTRING 128
-#endif
-
+#endif /* __DNA_PROPERTY_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_rigidbody_types.h b/source/blender/makesdna/DNA_rigidbody_types.h
new file mode 100644
index 00000000000..4a96c324f04
--- /dev/null
+++ b/source/blender/makesdna/DNA_rigidbody_types.h
@@ -0,0 +1,292 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joshua Leung, Sergej Reich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file DNA_rigidbody_types.h
+ * \ingroup DNA
+ * \brief Types and defines for representing Rigid Body entities
+ */
+
+#ifndef __DNA_RIGIDBODY_TYPES_H__
+#define __DNA_RIGIDBODY_TYPES_H__
+
+#include "DNA_listBase.h"
+
+struct Group;
+
+struct EffectorWeights;
+
+/* ******************************** */
+/* RigidBody World */
+
+/* RigidBodyWorld (rbw)
+ *
+ * Represents a "simulation scene" existing within the parent scene.
+ */
+typedef struct RigidBodyWorld {
+ /* Sim World Settings ------------------------------------------------------------- */
+ struct EffectorWeights *effector_weights; /* effectors info */
+
+ struct Group *group; /* Group containing objects to use for Rigid Bodies */
+ struct Object **objects; /* Array to access group objects by index, only used at runtime */
+
+ struct Group *constraints; /* Group containing objects to use for Rigid Body Constraints*/
+
+ int pad;
+ float ltime; /* last frame world was evaluated for (internal) */
+
+ /* cache */
+ struct PointCache *pointcache;
+ struct ListBase ptcaches;
+ int numbodies; /* number of objects in rigid body group */
+
+ short steps_per_second; /* number of simulation steps thaken per second */
+ short num_solver_iterations;/* number of constraint solver iterations made per simulation step */
+
+ int flag; /* (eRigidBodyWorld_Flag) settings for this RigidBodyWorld */
+ float time_scale; /* used to speed up or slow down the simulation */
+
+ /* References to Physics Sim objects. Exist at runtime only ---------------------- */
+ void *physics_world; /* Physics sim world (i.e. btDiscreteDynamicsWorld) */
+} RigidBodyWorld;
+
+/* Flags for RigidBodyWorld */
+typedef enum eRigidBodyWorld_Flag {
+ /* should sim world be skipped when evaluating (user setting) */
+ RBW_FLAG_MUTED = (1 << 0),
+ /* sim data needs to be rebuilt */
+ RBW_FLAG_NEEDS_REBUILD = (1 << 1),
+ /* usse split impulse when stepping the simulation */
+ RBW_FLAG_USE_SPLIT_IMPULSE = (1 << 2)
+} eRigidBodyWorld_Flag;
+
+/* ******************************** */
+/* RigidBody Object */
+
+/* RigidBodyObject (rbo)
+ *
+ * Represents an object participating in a RigidBody sim.
+ * This is attached to each object that is currently
+ * participating in a sim.
+ */
+typedef struct RigidBodyOb {
+ /* References to Physics Sim objects. Exist at runtime only */
+ void *physics_object; /* Physics object representation (i.e. btRigidBody) */
+ void *physics_shape; /* Collision shape used by physics sim (i.e. btCollisionShape) */
+
+ /* General Settings for this RigidBodyOb */
+ short type; /* (eRigidBodyOb_Type) role of RigidBody in sim */
+ short shape; /* (eRigidBody_Shape) collision shape to use */
+
+ int flag; /* (eRigidBodyOb_Flag) */
+ int col_groups; /* Collision groups that determines wich rigid bodies can collide with each other */
+ int pad;
+
+ /* Physics Parameters */
+ float mass; /* how much object 'weighs' (i.e. absolute 'amount of stuff' it holds) */
+
+ float friction; /* resistance of object to movement */
+ float restitution; /* how 'bouncy' object is when it collides */
+
+ float margin; /* tolerance for detecting collisions */
+
+ float lin_damping; /* damping for linear velocities */
+ float ang_damping; /* damping for angular velocities */
+
+ float lin_sleep_thresh; /* deactivation threshold for linear velocities */
+ float ang_sleep_thresh; /* deactivation threshold for angular velocities */
+
+ float orn[4]; /* rigid body orientation */
+ float pos[3]; /* rigid body position */
+ float pad1;
+} RigidBodyOb;
+
+
+/* Participation types for RigidBodyOb */
+typedef enum eRigidBodyOb_Type {
+ /* active geometry participant in simulation. is directly controlled by sim */
+ RBO_TYPE_ACTIVE = 0,
+ /* passive geometry participant in simulation. is directly controlled by animsys */
+ RBO_TYPE_PASSIVE
+} eRigidBodyOb_Type;
+
+/* Flags for RigidBodyOb */
+typedef enum eRigidBodyOb_Flag {
+ /* rigidbody is kinematic (controlled by the animation system) */
+ RBO_FLAG_KINEMATIC = (1 << 0),
+ /* rigidbody needs to be validated (usually set after duplicating and not hooked up yet) */
+ RBO_FLAG_NEEDS_VALIDATE = (1 << 1),
+ /* rigidbody shape needs refreshing (usually after exiting editmode) */
+ RBO_FLAG_NEEDS_RESHAPE = (1 << 2),
+ /* rigidbody can be deactivated */
+ RBO_FLAG_USE_DEACTIVATION = (1 << 3),
+ /* rigidbody is deactivated at the beginning of simulation */
+ RBO_FLAG_START_DEACTIVATED = (1 << 4),
+ /* rigidbody is not dynamically simulated */
+ RBO_FLAG_DISABLED = (1 << 5),
+ /* collision margin is not embedded (only used by convex hull shapes for now) */
+ RBO_FLAG_USE_MARGIN = (1 << 6)
+} eRigidBodyOb_Flag;
+
+/* RigidBody Collision Shape */
+typedef enum eRigidBody_Shape {
+ /* simple box (i.e. bounding box) */
+ RB_SHAPE_BOX = 0,
+ /* sphere */
+ RB_SHAPE_SPHERE,
+ /* rounded "pill" shape (i.e. calcium tablets) */
+ RB_SHAPE_CAPSULE,
+ /* cylinder (i.e. pringles can) */
+ RB_SHAPE_CYLINDER,
+ /* cone (i.e. party hat) */
+ RB_SHAPE_CONE,
+
+ /* convex hull (minimal shrinkwrap encompassing all verts) */
+ RB_SHAPE_CONVEXH,
+ /* triangulated mesh */
+ RB_SHAPE_TRIMESH,
+
+ /* concave mesh approximated using primitives */
+ //RB_SHAPE_COMPOUND,
+} eRigidBody_Shape;
+
+/* ******************************** */
+/* RigidBody Constraint */
+
+/* RigidBodyConstraint (rbc)
+ *
+ * Represents an constraint connecting two rigid bodies.
+ */
+typedef struct RigidBodyCon {
+ struct Object *ob1; /* First object influenced by the constraint */
+ struct Object *ob2; /* Second object influenced by the constraint */
+
+ /* General Settings for this RigidBodyCon */
+ short type; /* (eRigidBodyCon_Type) role of RigidBody in sim */
+ short num_solver_iterations;/* number of constraint solver iterations made per simulation step */
+
+ int flag; /* (eRigidBodyCon_Flag) */
+
+ float breaking_threshold; /* breaking impulse threshold */
+ float pad;
+
+ /* limits */
+ /* translation limits */
+ float limit_lin_x_lower;
+ float limit_lin_x_upper;
+ float limit_lin_y_lower;
+ float limit_lin_y_upper;
+ float limit_lin_z_lower;
+ float limit_lin_z_upper;
+ /* rotation limits */
+ float limit_ang_x_lower;
+ float limit_ang_x_upper;
+ float limit_ang_y_lower;
+ float limit_ang_y_upper;
+ float limit_ang_z_lower;
+ float limit_ang_z_upper;
+
+ /* spring settings */
+ /* resistance to deformation */
+ float spring_stiffness_x;
+ float spring_stiffness_y;
+ float spring_stiffness_z;
+ /* amount of velocity lost over time */
+ float spring_damping_x;
+ float spring_damping_y;
+ float spring_damping_z;
+
+ /* motor settings */
+ float motor_lin_target_velocity; /* linear velocity the motor tries to hold */
+ float motor_ang_target_velocity; /* angular velocity the motor tries to hold */
+ float motor_lin_max_impulse; /* maximum force used to reach linear target velocity */
+ float motor_ang_max_impulse; /* maximum force used to reach angular target velocity */
+
+ /* References to Physics Sim object. Exist at runtime only */
+ void *physics_constraint; /* Physics object representation (i.e. btTypedConstraint) */
+} RigidBodyCon;
+
+
+/* Participation types for RigidBodyOb */
+typedef enum eRigidBodyCon_Type {
+ /* lets bodies rotate around a specified point */
+ RBC_TYPE_POINT = 0,
+ /* lets bodies rotate around a specified axis */
+ RBC_TYPE_HINGE,
+ /* simulates wheel suspension */
+ RBC_TYPE_HINGE2,
+ /* restricts movent to a specified axis */
+ RBC_TYPE_SLIDER,
+ /* lets object rotate within a cpecified cone */
+ RBC_TYPE_CONE_TWIST,
+ /* allows user to specify constraint axes */
+ RBC_TYPE_6DOF,
+ /* like 6DOF but has springs */
+ RBC_TYPE_6DOF_SPRING,
+ /* simulates a universal joint */
+ RBC_TYPE_UNIVERSAL,
+ /* glues two bodies together */
+ RBC_TYPE_FIXED,
+ /* similar to slider but also allows rotation around slider axis */
+ RBC_TYPE_PISTON,
+ /* Simplified spring constraint with only once axis that's automatically placed between the connected bodies */
+ RBC_TYPE_SPRING,
+ /* dirves bodies by applying linear and angular forces */
+ RBC_TYPE_MOTOR
+} eRigidBodyCon_Type;
+
+/* Flags for RigidBodyCon */
+typedef enum eRigidBodyCon_Flag {
+ /* constraint influences rigid body motion */
+ RBC_FLAG_ENABLED = (1 << 0),
+ /* constraint needs to be validated */
+ RBC_FLAG_NEEDS_VALIDATE = (1 << 1),
+ /* allow constrained bodies to collide */
+ RBC_FLAG_DISABLE_COLLISIONS = (1 << 2),
+ /* constraint can break */
+ RBC_FLAG_USE_BREAKING = (1 << 3),
+ /* constraint use custom number of constraint solver iterations */
+ RBC_FLAG_OVERRIDE_SOLVER_ITERATIONS = (1 << 4),
+ /* limits */
+ RBC_FLAG_USE_LIMIT_LIN_X = (1 << 5),
+ RBC_FLAG_USE_LIMIT_LIN_Y = (1 << 6),
+ RBC_FLAG_USE_LIMIT_LIN_Z = (1 << 7),
+ RBC_FLAG_USE_LIMIT_ANG_X = (1 << 8),
+ RBC_FLAG_USE_LIMIT_ANG_Y = (1 << 9),
+ RBC_FLAG_USE_LIMIT_ANG_Z = (1 << 10),
+ /* springs */
+ RBC_FLAG_USE_SPRING_X = (1 << 11),
+ RBC_FLAG_USE_SPRING_Y = (1 << 12),
+ RBC_FLAG_USE_SPRING_Z = (1 << 13),
+ /* motors */
+ RBC_FLAG_USE_MOTOR_LIN = (1 << 14),
+ RBC_FLAG_USE_MOTOR_ANG = (1 << 15)
+} eRigidBodyCon_Flag;
+
+/* ******************************** */
+
+#endif /* __DNA_RIGIDBODY_TYPES_H__ */
+
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 1599b71d832..a106afd38b2 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -45,6 +45,7 @@ extern "C" {
#include "DNA_vec_types.h"
#include "DNA_listBase.h"
#include "DNA_ID.h"
+#include "DNA_freestyle_types.h"
struct Object;
struct Brush;
@@ -187,6 +188,8 @@ typedef struct SceneRenderLayer {
int samples;
int pad;
+
+ struct FreestyleConfig freestyleConfig;
} SceneRenderLayer;
/* srl->layflag */
@@ -196,7 +199,8 @@ typedef struct SceneRenderLayer {
#define SCE_LAY_EDGE 8
#define SCE_LAY_SKY 16
#define SCE_LAY_STRAND 32
- /* flags between 32 and 0x8000 are set to 1 already, for future options */
+#define SCE_LAY_FRS 64
+ /* flags between 128 and 0x8000 are set to 1 already, for future options */
#define SCE_LAY_ALL_Z 0x8000
#define SCE_LAY_XOR 0x10000
@@ -271,8 +275,9 @@ typedef struct ImageFormatData {
/* Jpeg2000 */
char jp2_flag;
+ char jp2_codec;
- char pad[7];
+ char pad[6];
/* color management */
ColorManagedViewSettings view_settings;
@@ -341,6 +346,10 @@ typedef struct ImageFormatData {
#define R_IMF_JP2_FLAG_CINE_PRESET (1<<1) /* was R_JPEG2K_CINE_PRESET */
#define R_IMF_JP2_FLAG_CINE_48 (1<<2) /* was R_JPEG2K_CINE_48FPS */
+/* ImageFormatData.jp2_codec */
+#define R_IMF_JP2_CODEC_JP2 0
+#define R_IMF_JP2_CODEC_J2K 1
+
/* ImageFormatData.cineon_flag */
#define R_IMF_CINEON_FLAG_LOG (1<<0) /* was R_CINEON_LOG */
@@ -384,15 +393,19 @@ typedef struct RenderData {
short filtertype; /* filter is box, tent, gauss, mitch, etc */
short size, maximsize; /* size in %, max in Kb */
+
+ short pad6;
+
/* from buttons: */
/**
* The desired number of pixels in the x direction
*/
- short xsch;
+ int xsch;
/**
* The desired number of pixels in the y direction
*/
- short ysch;
+ int ysch;
+
/**
* The number of part to use in the x direction
*/
@@ -405,7 +418,7 @@ typedef struct RenderData {
/**
* render tile dimensions
*/
- short tilex, tiley;
+ int tilex, tiley;
short planes DNA_DEPRECATED, imtype DNA_DEPRECATED, subimtype DNA_DEPRECATED, quality DNA_DEPRECATED; /*deprecated!*/
@@ -413,6 +426,7 @@ typedef struct RenderData {
* Render to image editor, fullscreen or to new window.
*/
short displaymode;
+ short pad7;
/**
* Flags for render settings. Use bit-masking to access the settings.
@@ -453,8 +467,6 @@ typedef struct RenderData {
short frs_sec, edgeint;
- int pad;
-
/* safety, border and display rect */
rctf safety, border;
@@ -491,7 +503,8 @@ typedef struct RenderData {
/* Bake Render options */
short bake_osa, bake_filter, bake_mode, bake_flag;
short bake_normal_space, bake_quad_split;
- float bake_maxdist, bake_biasdist, bake_pad;
+ float bake_maxdist, bake_biasdist;
+ short bake_samples, bake_pad;
/* path to render output */
char pic[1024]; /* 1024 = FILE_MAX */
@@ -535,6 +548,10 @@ typedef struct RenderData {
float pad2;
struct Text *dometext DNA_DEPRECATED; // XXX deprecated since 2.5
+ /* Freestyle line thickness options */
+ int line_thickness_mode;
+ float unit_line_thickness; /* in pixels */
+
/* render engine */
char engine[32];
} RenderData;
@@ -635,7 +652,8 @@ typedef struct GameData {
short physicsEngine;
short exitkey, pad;
short ticrate, maxlogicstep, physubstep, maxphystep;
- short obstacleSimulation, pad1;
+ short obstacleSimulation;
+ short raster_storage;
float levelHeight;
float deactivationtime, lineardeactthreshold, angulardeactthreshold, pad2;
} GameData;
@@ -662,6 +680,12 @@ typedef struct GameData {
#define OBSTSIMULATION_TOI_rays 1
#define OBSTSIMULATION_TOI_cells 2
+/* Raster storage */
+#define RAS_STORE_AUTO 0
+#define RAS_STORE_IMMEDIATE 1
+#define RAS_STORE_VA 2
+#define RAS_STORE_VBO 3
+
/* GameData.flag */
#define GAME_RESTRICT_ANIM_UPDATES (1 << 0)
#define GAME_ENABLE_ALL_FRAMES (1 << 1)
@@ -680,6 +704,7 @@ typedef struct GameData {
#define GAME_SHOW_MOUSE (1 << 14)
#define GAME_GLSL_NO_COLOR_MANAGEMENT (1 << 15)
#define GAME_SHOW_OBSTACLE_SIMULATION (1 << 16)
+#define GAME_NO_MATERIAL_CACHING (1 << 17)
/* Note: GameData.flag is now an int (max 32 flags). A short could only take 16 flags */
/* GameData.playerflag */
@@ -800,23 +825,11 @@ typedef struct Sculpt {
//char tablet_size, tablet_strength; XXX not used?
int radial_symm[3];
- // all this below is used to communicate with the cursor drawing routine
-
- /* record movement of mouse so that rake can start at an intuitive angle */
- float last_x, last_y;
- float last_angle;
-
- int draw_anchored;
- int anchored_size;
- float anchored_location[3];
- float anchored_initial_mouse[2];
+ /* Maximum edge length for dynamic topology sculpting (in pixels) */
+ int detail_size;
- int draw_pressure;
- float pressure_value;
-
- float special_rotation;
-
- int pad;
+ /* Direction used for SCULPT_OT_symmetrize operator */
+ int symmetrize_direction;
} Sculpt;
typedef struct UvSculpt {
@@ -879,7 +892,29 @@ typedef struct UnifiedPaintSettings {
/* user preferences for sculpt and paint */
int flag;
+
+ /* rake rotation */
+
+ /* record movement of mouse so that rake can start at an intuitive angle */
+ float last_rake[2];
int pad;
+
+ float brush_rotation;
+
+ // all this below is used to communicate with the cursor drawing routine
+ int draw_anchored;
+ int anchored_size;
+ float anchored_initial_mouse[2];
+
+ /* drawing pressure */
+ int draw_pressure;
+ float pressure_value;
+
+ /* position of mouse, used to sample the texture */
+ float tex_mouse[2];
+ /* radius of brush, premultiplied with pressure.
+ * In case of anchored brushes contains that radius */
+ float pixel_radius;
} UnifiedPaintSettings;
typedef enum {
@@ -945,7 +980,7 @@ typedef struct ToolSettings {
short uvcalc_mapalign;
short uvcalc_flag;
short uv_flag, uv_selectmode;
- short uv_subsurf_level;
+ short pad2;
/* Grease Pencil */
short gpencil_flags;
@@ -973,7 +1008,7 @@ typedef struct ToolSettings {
/* Multires */
char multires_subdiv_type;
- char pad2[5];
+ char pad3[5];
/* Skeleton generation */
short skgen_resolution;
@@ -1014,10 +1049,11 @@ typedef struct ToolSettings {
short proportional, prop_mode;
char proportional_objects; /* proportional edit, object mode */
char proportional_mask; /* proportional edit, object mode */
- char pad4[2];
+ char pad4[1];
char auto_normalize; /*auto normalizing mode in wpaint*/
char multipaint; /* paint multiple bones in wpaint */
+ char weightuser;
/* UV painting */
int use_uv_sculpt;
@@ -1118,12 +1154,9 @@ typedef struct Scene {
/* none of the dependency graph vars is mean to be saved */
struct DagForest *theDag;
- short dagisvalid, dagflags;
+ short dagflags;
short recalc; /* recalc = counterpart of ob->recalc */
- short pad6;
- int pad5;
-
/* User-Defined KeyingSets */
int active_keyingset; /* index of the active KeyingSet. first KeyingSet has index 1, 'none' active is 0, 'add new' is -1 */
ListBase keyingsets; /* KeyingSets for this scene */
@@ -1151,6 +1184,9 @@ typedef struct Scene {
ColorManagedViewSettings view_settings;
ColorManagedDisplaySettings display_settings;
ColorManagedColorspaceSettings sequencer_colorspace_settings;
+
+ /* RigidBody simulation world+settings */
+ struct RigidBodyWorld *rigidbody_world;
} Scene;
@@ -1198,6 +1234,7 @@ typedef struct Scene {
/* seq_flag */
#define R_SEQ_GL_PREV 1
// #define R_SEQ_GL_REND 2 // UNUSED, opengl render has its own operator now.
+#define R_SEQ_SOLID_TEX 4
/* displaymode */
@@ -1271,11 +1308,11 @@ typedef struct Scene {
/* alphamode */
#define R_ADDSKY 0
#define R_ALPHAPREMUL 1
-#define R_ALPHAKEY 2
+/*#define R_ALPHAKEY 2*/ /* deprecated, shouldn't be used */
/* color_mgt_flag */
#define R_COLOR_MANAGEMENT (1 << 0) /* deprecated, should only be used in versioning code only */
-#define R_COLOR_MANAGEMENT_PREDIVIDE (1 << 1)
+/*#define R_COLOR_MANAGEMENT_PREDIVIDE (1 << 1)*/ /* deprecated, shouldn't be used */
/* subimtype, flag options for imtype */
#define R_OPENEXR_HALF 1 /*deprecated*/
@@ -1298,6 +1335,7 @@ typedef struct Scene {
#define R_BAKE_NORMALIZE 8
#define R_BAKE_MULTIRES 16
#define R_BAKE_LORES_MESH 32
+#define R_BAKE_VCOL 64
/* bake_normal_space */
#define R_BAKE_SPACE_CAMERA 0
@@ -1308,6 +1346,10 @@ typedef struct Scene {
/* simplify_flag */
#define R_SIMPLE_NO_TRIANGULATE 1
+/* line_thickness_mode */
+#define R_LINE_THICKNESS_ABSOLUTE 1
+#define R_LINE_THICKNESS_RELATIVE 2
+
/* sequencer seq_prev_type seq_rend_type */
@@ -1421,6 +1463,13 @@ typedef struct Scene {
#define PROP_EDIT_ON 1
#define PROP_EDIT_CONNECTED 2
+/* toolsettings->weightuser */
+enum {
+ OB_DRAW_GROUPUSER_NONE = 0,
+ OB_DRAW_GROUPUSER_ACTIVE = 1,
+ OB_DRAW_GROUPUSER_ALL = 2
+};
+
/* sce->flag */
#define SCE_DS_SELECTED (1<<0)
#define SCE_DS_COLLAPSED (1<<1)
@@ -1464,6 +1513,14 @@ typedef enum SculptFlags {
SCULPT_USE_OPENMP = (1<<7),
SCULPT_ONLY_DEFORM = (1<<8),
SCULPT_SHOW_DIFFUSE = (1<<9),
+
+ /* If set, the mesh will be drawn with smooth-shading in
+ * dynamic-topology mode */
+ SCULPT_DYNTOPO_SMOOTH_SHADING = (1<<10),
+
+ /* If set, dynamic-topology brushes will collapse short edges in
+ * addition to subdividing long ones */
+ SCULPT_DYNTOPO_COLLAPSE = (1<<11)
} SculptFlags;
/* ImagePaintSettings.flag */
@@ -1472,7 +1529,6 @@ typedef enum SculptFlags {
// #define IMAGEPAINT_DRAW_TOOL_DRAWING 4 // deprecated
/* projection painting only */
-#define IMAGEPAINT_PROJECT_DISABLE 8 /* Non projection 3D painting */
#define IMAGEPAINT_PROJECT_XRAY 16
#define IMAGEPAINT_PROJECT_BACKFACE 32
#define IMAGEPAINT_PROJECT_FLAT 64
@@ -1502,6 +1558,7 @@ typedef enum SculptFlags {
#define EDGE_MODE_TAG_SHARP 2
#define EDGE_MODE_TAG_CREASE 3
#define EDGE_MODE_TAG_BEVEL 4
+#define EDGE_MODE_TAG_FREESTYLE 5
/* toolsettings->gpencil_flags */
#define GP_TOOL_FLAG_PAINTSESSIONS_ON (1<<0)
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index b1cd54950e6..ceae4e28d1f 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -82,7 +82,8 @@ typedef struct bScreen {
typedef struct ScrVert {
struct ScrVert *next, *prev, *newv;
vec2s vec;
- int flag;
+ /* first one used internally, second one for tools */
+ short flag, editflag;
} ScrVert;
typedef struct ScrEdge {
@@ -109,12 +110,26 @@ typedef struct Panel { /* the part from uiBlock that needs saved in file */
int sortorder; /* panels are aligned according to increasing sortorder */
struct Panel *paneltab; /* this panel is tabbed in *paneltab */
void *activedata; /* runtime for panel manipulation */
-
- int list_scroll, list_size;
- int list_last_len, list_grip_size;
- char list_search[64];
} Panel;
+typedef struct uiList { /* some list UI data need to be saved in file */
+ struct uiList *next, *prev;
+
+ struct uiListType *type; /* runtime */
+ void *padp;
+
+ char list_id[64]; /* defined as UI_MAX_NAME_STR */
+
+ int layout_type; /* How items are layedout in the list */
+ int padi;
+
+ int list_scroll;
+ int list_size;
+ int list_last_len;
+ int list_grip_size;
+/* char list_search[64]; */
+} uiList;
+
typedef struct ScrArea {
struct ScrArea *next, *prev;
@@ -127,9 +142,11 @@ typedef struct ScrArea {
short winx, winy; /* size */
short headertype; /* OLD! 0=no header, 1= down, 2= up */
- short pad;
short do_refresh; /* private, for spacetype refresh callback */
- short cursor, flag;
+ short flag;
+ short region_active_win; /* index of last used region of 'RGN_TYPE_WINDOW'
+ * runtuime variable, updated by executing operators */
+ short pad;
struct SpaceType *type; /* callbacks for this space type */
@@ -159,14 +176,18 @@ typedef struct ARegion {
short do_draw; /* private, cached notifier events */
short do_draw_overlay; /* private, cached notifier events */
short swap; /* private, indicator to survive swap-exchange */
- short pad[3];
+ short overlap; /* private, set for indicate drawing overlapped */
+ short pad[2];
struct ARegionType *type; /* callbacks for this region type */
ListBase uiblocks; /* uiBlock */
ListBase panels; /* Panel */
+ ListBase ui_lists; /* uiList */
ListBase handlers; /* wmEventHandler */
+ struct wmTimer *regiontimer; /* blend in/out */
+
char *headerstr; /* use this string to draw info */
void *regiondata; /* XXX 2.50, need spacedata equivalent? */
} ARegion;
@@ -212,6 +233,13 @@ typedef struct ARegion {
#define PNL_DEFAULT_CLOSED 1
#define PNL_NO_HEADER 2
+/* uilist layout_type */
+enum {
+ UILST_LAYOUT_DEFAULT = 0,
+ UILST_LAYOUT_COMPACT = 1,
+ UILST_LAYOUT_GRID = 2,
+};
+
/* regiontype, first two are the default set */
/* Do NOT change order, append on end. Types are hardcoded needed */
enum {
@@ -235,10 +263,6 @@ enum {
#define RGN_ALIGN_VSPLIT 6
#define RGN_ALIGN_FLOAT 7
#define RGN_ALIGN_QSPLIT 8
-#define RGN_OVERLAP_TOP 9
-#define RGN_OVERLAP_BOTTOM 10
-#define RGN_OVERLAP_LEFT 11
-#define RGN_OVERLAP_RIGHT 12
#define RGN_SPLIT_PREV 32
diff --git a/source/blender/makesdna/DNA_sensor_types.h b/source/blender/makesdna/DNA_sensor_types.h
index 05927e3a486..d8cf80d047b 100644
--- a/source/blender/makesdna/DNA_sensor_types.h
+++ b/source/blender/makesdna/DNA_sensor_types.h
@@ -29,6 +29,8 @@
* \ingroup DNA
* \since mar-2001
* \author nzc
+ *
+ * #bSensor type is specifically for use by Object logic-bricks in the game-engine.
*/
#ifndef __DNA_SENSOR_TYPES_H__
@@ -324,5 +326,5 @@ typedef struct bJoystickSensor {
#define SENS_DELAY_REPEAT 1
// should match JOYINDEX_MAX in SCA_JoystickDefines.h */
#define SENS_JOY_MAXINDEX 8
-#endif
+#endif /* __DNA_SENSOR_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index f106c8f918a..455350d8310 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -28,6 +28,14 @@
* \ingroup DNA
* \since mar-2001
* \author nzc
+ *
+ * Structs for use by the 'Sequencer' (Video Editor)
+ *
+ * Note on terminology
+ * - #Sequence: video/effect/audio data you can select and manipulate in the sequencer.
+ * - #Sequence.machine: Strange name for the channel.
+ * - #Strip: The data referenced by the #Sequence
+ * - Meta Strip (SEQ_TYPE_META): Support for nesting Sequences.
*/
#ifndef __DNA_SEQUENCE_TYPES_H__
@@ -172,7 +180,10 @@ typedef struct Sequence {
float blend_opacity;
/* is sfra needed anymore? - it looks like its only used in one place */
- int sfra, pad; /* starting frame according to the timeline of the scene. */
+ int sfra; /* starting frame according to the timeline of the scene. */
+
+ char alpha_mode;
+ char pad[3];
/* modifiers */
ListBase modifiers;
@@ -315,7 +326,7 @@ typedef struct SequencerScopes {
#define SEQ_OVERLAP (1 << 3)
#define SEQ_FILTERY (1 << 4)
#define SEQ_MUTE (1 << 5)
-#define SEQ_MAKE_PREMUL (1 << 6)
+#define SEQ_MAKE_PREMUL (1 << 6) /* deprecated, used for compatibility code only */
#define SEQ_REVERSE_FRAMES (1 << 7)
#define SEQ_IPO_FRAME_LOCKED (1 << 8)
#define SEQ_EFFECT_NOT_LOADED (1 << 9)
@@ -366,6 +377,12 @@ typedef struct SequencerScopes {
#define SEQ_PROXY_TC_RECORD_RUN_NO_GAPS 8
#define SEQ_PROXY_TC_ALL 15
+/* seq->alpha_mode */
+enum {
+ SEQ_ALPHA_STRAIGHT = 0,
+ SEQ_ALPHA_PREMUL = 1
+};
+
/* seq->type WATCH IT: SEQ_TYPE_EFFECT BIT is used to determine if this is an effect strip!!! */
enum {
SEQ_TYPE_IMAGE = 0,
@@ -432,4 +449,4 @@ enum {
SEQUENCE_MASK_INPUT_ID = 1
};
-#endif
+#endif /* __DNA_SEQUENCE_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index be6464778e5..b9c4788336f 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -28,6 +28,8 @@
* \ingroup DNA
* \since mar-2001
* \author nzc
+ *
+ * Structs for each of space type in the user interface.
*/
#ifndef __DNA_SPACE_TYPES_H__
@@ -41,6 +43,7 @@
#include "DNA_image_types.h" /* ImageUser */
#include "DNA_movieclip_types.h" /* MovieClipUser */
#include "DNA_sequence_types.h" /* SequencerScopes */
+#include "DNA_node_types.h" /* for bNodeInstanceKey */
/* Hum ... Not really nice... but needed for spacebuts. */
#include "DNA_view2d_types.h"
@@ -180,6 +183,7 @@ typedef enum eSpaceButtons_Context {
BCONTEXT_MODIFIER = 10,
BCONTEXT_CONSTRAINT = 11,
BCONTEXT_BONE_CONSTRAINT = 12,
+ BCONTEXT_RENDER_LAYER = 13,
/* always as last... */
BCONTEXT_TOT
@@ -434,7 +438,7 @@ typedef enum eScreen_Redraws_Flag {
TIME_WITH_SEQ_AUDIO = (1 << 4), /* DEPRECATED */
TIME_SEQ = (1 << 5),
TIME_ALL_IMAGE_WIN = (1 << 6),
- TIME_CONTINUE_PHYSICS = (1 << 7),
+ TIME_CONTINUE_PHYSICS = (1 << 7), /* UNUSED */
TIME_NODES = (1 << 8),
TIME_CLIPS = (1 << 9),
} eScreen_Redraws_Flag;
@@ -447,6 +451,7 @@ typedef enum eTimeline_Cache_Flag {
TIME_CACHE_CLOTH = (1 << 3),
TIME_CACHE_SMOKE = (1 << 4),
TIME_CACHE_DYNAMICPAINT = (1 << 5),
+ TIME_CACHE_RIGIDBODY = (1 << 6),
} eTimeline_Cache_Flag;
@@ -494,8 +499,9 @@ typedef enum eSpaceSeq_Flag {
SEQ_MARKER_TRANS = (1 << 1),
SEQ_DRAW_COLOR_SEPARATED = (1 << 2),
SEQ_DRAW_SAFE_MARGINS = (1 << 3),
-/* SEQ_DRAW_GPENCIL = (1 << 4), */ /* DEPRECATED */
+ SEQ_SHOW_GPENCIL = (1 << 4),
SEQ_NO_DRAW_CFRANUM = (1 << 5),
+ SEQ_USE_ALPHA = (1 << 6), /* use RGBA display mode for preview */
} eSpaceSeq_Flag;
/* sseq->view */
@@ -776,7 +782,7 @@ typedef enum eSpaceImage_Flag {
SI_DRAW_TILE = (1 << 19),
SI_SMOOTH_UV = (1 << 20),
SI_DRAW_STRETCH = (1 << 21),
-/* SI_DISPGP = (1 << 22), */ /* deprecated */
+ SI_SHOW_GPENCIL = (1 << 22),
SI_DRAW_OTHER = (1 << 23),
SI_COLOR_CORRECTION = (1 << 24),
@@ -797,7 +803,7 @@ typedef struct SpaceText {
int top, viewlines;
short flags, menunr;
- short lheight; /* user preference */
+ short lheight; /* user preference, is font_size! */
char cwidth, linenrs_tot; /* runtime computed, character width and the number of chars to use when showing line numbers */
int left;
int showlinenrs;
@@ -816,8 +822,9 @@ typedef struct SpaceText {
char findstr[256]; /* ST_MAX_FIND_STR */
char replacestr[256]; /* ST_MAX_FIND_STR */
- short margin_column; /* column number to show right margin at */
- char pad[6];
+ short margin_column; /* column number to show right margin at */
+ short lheight_dpi; /* actual lineheight, dpi controlled */
+ char pad[4];
void *drawcache; /* cache for faster drawing */
} SpaceText;
@@ -875,6 +882,17 @@ typedef struct SpaceScript {
/* Nodes Editor =========================================== */
/* Node Editor */
+
+typedef struct bNodeTreePath {
+ struct bNodeTreePath *next, *prev;
+
+ struct bNodeTree *nodetree;
+ bNodeInstanceKey parent_key; /* base key for nodes in this tree instance */
+ int pad;
+ /* XXX this is not automatically updated when node names are changed! */
+ char node_name[64]; /* MAX_NAME */
+} bNodeTreePath;
+
typedef struct SpaceNode {
SpaceLink *next, *prev;
ListBase regionbase; /* storage of regions for inactive spaces */
@@ -886,18 +904,30 @@ typedef struct SpaceNode {
struct ID *id, *from; /* context, no need to save in file? well... pinning... */
short flag, pad1; /* menunr: browse id block in header */
- float aspect, aspect_sqrt;
+ float aspect, pad2; /* internal state variables */
float xof, yof; /* offset for drawing the backdrop */
float zoom; /* zoom for backdrop */
float cursor[2]; /* mouse pos for drawing socketless link and adding nodes */
+ /* XXX nodetree pointer info is all in the path stack now,
+ * remove later on and use bNodeTreePath instead. For now these variables are set when pushing/popping
+ * from path stack, to avoid having to update all the functions and operators. Can be done when
+ * design is accepted and everything is properly tested.
+ */
+ ListBase treepath;
+
struct bNodeTree *nodetree, *edittree;
- int treetype; /* treetype: as same nodetree->type */
+
+ /* tree type for the current node tree */
+ char tree_idname[64];
+ 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 pad[3];
+ short pad4;
ListBase linkdrag; /* temporary data for modal linking operator */
struct bGPdata *gpd; /* grease-pencil data */
@@ -906,7 +936,7 @@ typedef struct SpaceNode {
/* snode->flag */
typedef enum eSpaceNode_Flag {
SNODE_BACKDRAW = (1 << 1),
-/* SNODE_DISPGP = (1 << 2), */ /* XXX: Grease Pencil - deprecated? */
+ SNODE_SHOW_GPENCIL = (1 << 2),
SNODE_USE_ALPHA = (1 << 3),
SNODE_SHOW_ALPHA = (1 << 4),
SNODE_SHOW_R = (1 << 7),
@@ -915,6 +945,8 @@ typedef enum eSpaceNode_Flag {
SNODE_AUTO_RENDER = (1 << 5),
SNODE_SHOW_HIGHLIGHT = (1 << 6),
SNODE_USE_HIDDEN_PREVIEW = (1 << 10),
+ SNODE_NEW_SHADERS = (1 << 11),
+ SNODE_PIN = (1 << 12),
} eSpaceNode_Flag;
/* snode->texfrom */
@@ -1000,8 +1032,8 @@ typedef struct SpaceUserPref {
ListBase regionbase; /* storage of regions for inactive spaces */
int spacetype;
- int pad;
-
+ char pad[3];
+ char filter_type;
char filter[64]; /* search term for filtering in the UI */
} SpaceUserPref;
@@ -1060,7 +1092,7 @@ typedef enum eSpaceClip_Flag {
SC_SHOW_GRID = (1 << 9),
SC_SHOW_STABLE = (1 << 10),
SC_MANUAL_CALIBRATION = (1 << 11),
-/* SC_SHOW_GPENCIL = (1 << 12),*/ /* UNUSED */
+ SC_SHOW_GPENCIL = (1 << 12),
SC_SHOW_FILTERS = (1 << 13),
SC_SHOW_GRAPH_FRAMES = (1 << 14),
SC_SHOW_GRAPH_TRACKS = (1 << 15),
@@ -1129,4 +1161,4 @@ typedef enum eSpace_Type {
#define IMG_SIZE_FALLBACK 256
-#endif
+#endif /* __DNA_SPACE_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_text_types.h b/source/blender/makesdna/DNA_text_types.h
index 6ce883905d4..8b18ecd7253 100644
--- a/source/blender/makesdna/DNA_text_types.h
+++ b/source/blender/makesdna/DNA_text_types.h
@@ -28,6 +28,9 @@
* \ingroup DNA
* \since mar-2001
* \author nzc
+ *
+ * Text blocks used for Python-Scripts, OpenShadingLanguage
+ * and arbitrary text data to store in blend files.
*/
#ifndef __DNA_TEXT_TYPES_H__
@@ -75,12 +78,4 @@ typedef struct Text {
#define TXT_FOLLOW 0x0200 /* always follow cursor (console) */
#define TXT_TABSTOSPACES 0x0400 /* use space instead of tabs */
-/* format continuation flags */
-#define TXT_NOCONT 0x00 /* no continuation */
-#define TXT_SNGQUOTSTR 0x01 /* single quotes */
-#define TXT_DBLQUOTSTR 0x02 /* double quotes */
-#define TXT_TRISTR 0x04 /* triplets of quotes: """ or ''' */
-#define TXT_SNGTRISTR 0x05 /*(TXT_TRISTR | TXT_SNGQUOTSTR)*/
-#define TXT_DBLTRISTR 0x06 /*(TXT_TRISTR | TXT_DBLQUOTSTR)*/
-
-#endif
+#endif /* __DNA_TEXT_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h
index b258fbaa668..73cda070fd2 100644
--- a/source/blender/makesdna/DNA_tracking_types.h
+++ b/source/blender/makesdna/DNA_tracking_types.h
@@ -30,6 +30,8 @@
* \ingroup DNA
* \since may-2011
* \author Sergey Sharybin
+ *
+ * Structs used for camera tracking and the movie-clip editor.
*/
#ifndef __DNA_TRACKING_TYPES_H__
@@ -248,13 +250,28 @@ typedef struct MovieTrackingDopesheetChannel {
int max_segment, total_frames; /* longest segment length and total number of tracked frames */
} MovieTrackingDopesheetChannel;
+typedef struct MovieTrackingDopesheetCoverageSegment {
+ struct MovieTrackingDopesheetCoverageSegment *next, *prev;
+
+ int coverage;
+ int start_frame;
+ int end_frame;
+
+ int pad;
+} MovieTrackingDopesheetCoverageSegment;
+
typedef struct MovieTrackingDopesheet {
int ok; /* flag if dopesheet information is still relevant */
short sort_method; /* method to be used to sort tracks */
short flag; /* dopesheet building flag such as inverted order of sort */
- /* runtime stuff */
+ /* ** runtime stuff ** */
+
+ /* summary */
+ ListBase coverage_segments;
+
+ /* detailed */
ListBase channels;
int tot_channel;
@@ -409,4 +426,11 @@ enum {
TRACKING_DOPE_SHOW_HIDDEN = (1 << 2)
};
-#endif
+/* MovieTrackingDopesheetCoverageSegment->trackness */
+enum {
+ TRACKING_COVERAGE_BAD = 0,
+ TRACKING_COVERAGE_ACCEPTABLE = 1,
+ TRACKING_COVERAGE_OK = 2
+};
+
+#endif /* __DNA_TRACKING_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 2e2f65dbec7..1d7658d974e 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -66,7 +66,7 @@ typedef struct uiFont {
short blf_id; /* from blfont lib */
short uifont_id; /* own id */
short r_to_l; /* fonts that read from left to right */
- short pad;
+ short hinting;
} uiFont;
/* this state defines appearance of text */
@@ -143,10 +143,19 @@ typedef struct uiWidgetStateColors {
typedef struct uiPanelColors {
char header[4];
+ char back[4];
short show_header;
- short pad;
+ short show_back;
+ int pad;
} uiPanelColors;
+typedef struct uiGradientColors {
+ char gradient[4];
+ char high_gradient[4];
+ int show_grad;
+ int pad2;
+} uiGradientColors;
+
typedef struct ThemeUI {
/* Interface Elements (buttons, menus, icons) */
uiWidgetColors wcol_regular, wcol_tool, wcol_text;
@@ -157,8 +166,14 @@ typedef struct ThemeUI {
uiWidgetStateColors wcol_state;
- uiPanelColors panel;
+ uiPanelColors panel; /* depricated, but we keep it for do_versions (2.66.1) */
+ /* fac: 0 - 1 for blend factor, width in pixels */
+ float menu_shadow_fac;
+ short menu_shadow_width;
+
+ short pad;
+
char iconfile[256]; // FILE_MAXFILE length
float icon_alpha;
@@ -172,34 +187,39 @@ typedef struct ThemeUI {
typedef struct ThemeSpace {
/* main window colors */
char back[4];
- char title[4];
+ char title[4]; /* panel title */
char text[4];
char text_hi[4];
/* header colors */
- char header[4];
- char header_title[4];
+ char header[4]; /* region background */
+ char header_title[4]; /* unused */
char header_text[4];
char header_text_hi[4];
/* button/tool regions */
- char button[4];
- char button_title[4];
+ char button[4]; /* region background */
+ char button_title[4]; /* panel title */
char button_text[4];
char button_text_hi[4];
/* listview regions */
- char list[4];
- char list_title[4];
+ char list[4]; /* region background */
+ char list_title[4]; /* panel title */
char list_text[4];
char list_text_hi[4];
/* float panel */
- char panel[4];
- char panel_title[4];
- char panel_text[4];
- char panel_text_hi[4];
+/* char panel[4]; unused */
+/* char panel_title[4]; unused */
+/* char panel_text[4]; unused */
+/* char panel_text_hi[4]; unused */
+ /* note, cannot use name 'panel' because of DNA mapping old files */
+ uiPanelColors panelcolors;
+
+ uiGradientColors gradients;
+
char shade1[4];
char shade2[4];
@@ -209,7 +229,7 @@ typedef struct ThemeSpace {
char wire[4], select[4];
char lamp[4], speaker[4], empty[4], camera[4], pad[8];
char active[4], group[4], group_active[4], transform[4];
- char vertex[4], vertex_select[4];
+ char vertex[4], vertex_select[4], vertex_unreferenced[4];
char edge[4], edge_select[4];
char edge_seam[4], edge_sharp[4], edge_facesel[4], edge_crease[4];
char face[4], face_select[4]; /* solid faces */
@@ -220,6 +240,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 freestyle_edge_mark[4], freestyle_face_mark[4];
char nurb_uline[4], nurb_vline[4];
char act_spline[4], nurb_sel_uline[4], nurb_sel_vline[4], lastsel_point[4];
@@ -230,20 +251,24 @@ typedef struct ThemeSpace {
char ds_channel[4], ds_subchannel[4]; /* dopesheet */
char console_output[4], console_input[4], console_info[4], console_error[4];
- char console_cursor[4];
+ char console_cursor[4], console_select[4], pad1[4];
char vertex_size, outline_width, facedot_size;
char noodle_curving;
- char syntaxl[4], syntaxn[4], syntaxb[4]; /* syntax for textwindow and nodes */
+ /* syntax for textwindow and nodes */
+ char syntaxl[4], syntaxs[4];
+ char syntaxb[4], syntaxn[4];
char syntaxv[4], syntaxc[4];
+ char syntaxd[4], syntaxr[4];
char movie[4], movieclip[4], mask[4], image[4], scene[4], audio[4]; /* for sequence editor */
- char effect[4], hpad0[4], transition[4], meta[4];
+ char effect[4], transition[4], meta[4];
char editmesh_active[4];
char handle_vertex[4];
char handle_vertex_select[4];
+ char pad2[4];
char handle_vertex_size;
@@ -332,6 +357,7 @@ typedef struct bTheme {
typedef struct bAddon {
struct bAddon *next, *prev;
char module[64];
+ IDProperty *prop; /* User-Defined Properties on this Addon (for storing preferences) */
} bAddon;
typedef struct SolidLight {
@@ -340,6 +366,9 @@ typedef struct SolidLight {
} SolidLight;
typedef struct UserDef {
+ /* UserDef has separate do-version handling, and can be read from other files */
+ int versionfile, subversionfile;
+
int flag, dupflag;
int savetime;
char tempdir[768]; /* FILE_MAXDIR length */
@@ -359,9 +388,10 @@ typedef struct UserDef {
short versions;
short dbl_click_time;
- int gameflags;
- int wheellinescroll;
- int uiflag, language;
+ short gameflags;
+ short wheellinescroll;
+ int uiflag, uiflag2;
+ int language;
short userpref, viewzoom;
int mixbufsize;
@@ -412,7 +442,7 @@ typedef struct UserDef {
short scrcastfps; /* frame rate for screencast to be played back */
short scrcastwait; /* milliseconds between screencast snapshots */
- short widget_unit; /* defaults to 20 for 72 DPI setting */
+ short widget_unit; /* private, defaults to 20 for 72 DPI setting */
short anisotropic_filter;
short use_16bit_textures, use_gpu_mipmap;
@@ -421,7 +451,8 @@ typedef struct UserDef {
int ndof_flag; /* flags for 3D mouse */
short ogl_multisamples; /* amount of samples for OpenGL FSA, if zero no FSA */
- short pad4;
+
+ short image_gpubuffer_limit; /* If set, amount of mega-pixels to use for texture drawing of images */
float glalphaclip;
@@ -443,7 +474,7 @@ typedef struct UserDef {
int compute_device_id;
float fcu_inactive_alpha; /* opacity of inactive F-Curves in F-Curve Editor */
- float pad;
+ float pixelsize; /* private, set by GHOST, to multiply DPI with */
} UserDef;
extern UserDef U; /* from blenkernel blender.c */
@@ -539,6 +570,13 @@ typedef enum eUserpref_UI_Flag {
USER_HIDE_SYSTEM_BOOKMARKS = (1 << 31)
} eUserpref_UI_Flag;
+/* uiflag2 */
+typedef enum eUserpref_UI_Flag2 {
+ USER_KEEP_SESSION = (1 << 0),
+ USER_REGION_OVERLAP = (1 << 1),
+ USER_TRACKPAD_NATURAL = (1 << 2)
+} eUserpref_UI_Flag2;
+
/* Auto-Keying mode */
typedef enum eAutokey_Mode {
/* AUTOKEY_ON is a bitflag */
@@ -569,12 +607,13 @@ typedef enum eAutokey_Flag {
typedef enum eUserpref_Translation_Flags {
USER_TR_TOOLTIPS = (1 << 0),
USER_TR_IFACE = (1 << 1),
-/* USER_TR_MENUS = (1 << 2) deprecated */
-/* USER_TR_FILESELECT = (1 << 3) deprecated */
-/* USER_TR_TEXTEDIT = (1 << 4) deprecated */
+/* USER_TR_MENUS = (1 << 2), deprecated */
+/* USER_TR_FILESELECT = (1 << 3), deprecated */
+/* USER_TR_TEXTEDIT = (1 << 4), deprecated */
USER_DOTRANSLATE = (1 << 5),
USER_USETEXTUREFONT = (1 << 6),
-/* CONVERT_TO_UTF8 = (1 << 7) deprecated */
+/* CONVERT_TO_UTF8 = (1 << 7), deprecated */
+ USER_TR_NEWDATANAME = (1 << 8),
} eUserpref_Translation_Flags;
/* dupflag */
diff --git a/source/blender/makesdna/DNA_vfont_types.h b/source/blender/makesdna/DNA_vfont_types.h
index 7aaeaf23db2..416c5f594a3 100644
--- a/source/blender/makesdna/DNA_vfont_types.h
+++ b/source/blender/makesdna/DNA_vfont_types.h
@@ -29,6 +29,9 @@
* \ingroup DNA
* \since mar-2001
* \author nzc
+ *
+ * Vector Fonts used for text in the 3D view-port
+ * (unrelated to text used to render the GUI).
*/
#ifndef __DNA_VFONT_TYPES_H__
@@ -63,5 +66,5 @@ typedef struct VFont {
#define FO_SELCHANGE 10
#define FO_BUILTIN_NAME "<builtin>"
-#endif
+#endif /* __DNA_VFONT_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_view2d_types.h b/source/blender/makesdna/DNA_view2d_types.h
index 084496871bf..a7921be44d5 100644
--- a/source/blender/makesdna/DNA_view2d_types.h
+++ b/source/blender/makesdna/DNA_view2d_types.h
@@ -123,9 +123,9 @@ typedef struct View2D {
/* horizontal scrollbar */
#define V2D_SCROLL_TOP (1<<2)
#define V2D_SCROLL_BOTTOM (1<<3)
- /* special hack for outliner hscroll - prevent hanging older versions of Blender */
-#define V2D_SCROLL_BOTTOM_O (1<<4)
-#define V2D_SCROLL_HORIZONTAL (V2D_SCROLL_TOP|V2D_SCROLL_BOTTOM|V2D_SCROLL_BOTTOM_O)
+
+/* UNUSED (1<<4) */
+#define V2D_SCROLL_HORIZONTAL (V2D_SCROLL_TOP|V2D_SCROLL_BOTTOM)
/* scale markings - vertical */
#define V2D_SCROLL_SCALE_VERTICAL (1<<5)
/* scale markings - horizontal */
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index c83b0bc366f..294c47aa9db 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -46,6 +46,7 @@ struct RenderEngine;
struct bGPdata;
struct SmoothView3DStore;
struct wmTimer;
+struct Material;
/* This is needed to not let VC choke on near and far... old
* proprietary MS extensions... */
@@ -106,6 +107,7 @@ typedef struct RegionView3D {
struct RenderInfo *ri;
struct RenderEngine *render_engine;
struct ViewDepths *depths;
+ void *gpuoffscreen;
/* animated smooth view */
struct SmoothView3DStore *sms;
@@ -117,7 +119,6 @@ typedef struct RegionView3D {
float viewquat[4]; /* view rotation, must be kept normalized */
float dist; /* distance from 'ofs' along -viewinv[2] vector, where result is negative as is 'ofs' */
- float zfac; /* initgrabz() result */
float camdx, camdy; /* camera view offsets, 1.0 = viewplane moves entire width/height */
float pixsize; /* runtime only */
float ofs[3]; /* view center & orbit pivot, negative of worldspace location,
@@ -128,10 +129,11 @@ typedef struct RegionView3D {
char persp;
char view;
char viewlock;
+ char pad[4];
short twdrawflag;
short rflag;
-
+
/* last view (use when switching out of camera view) */
float lviewquat[4];
@@ -160,8 +162,8 @@ typedef struct View3D {
float bundle_size; /* size of bundles in reconstructed data */
short bundle_drawtype; /* display style for bundle */
-
- char pad[6];
+ short pad;
+ int matcap_icon; /* icon id */
unsigned int lay_used; /* used while drawing */
@@ -209,11 +211,11 @@ typedef struct View3D {
/* drawflags, denoting state */
short zbuf, transp, xray;
-
char pad3[2];
- void *properties_storage; /* Nkey panel stores stuff here (runtime only!) */
-
+ void *properties_storage; /* Nkey panel stores stuff here (runtime only!) */
+ struct Material *defmaterial; /* used by matcap now */
+
/* XXX deprecated? */
struct bGPdata *gpd DNA_DEPRECATED; /* Grease-Pencil Data (annotation layers) */
@@ -225,6 +227,7 @@ typedef struct View3D {
#define V3D_DISPBGPICS 2
#define V3D_HIDE_HELPLINES 4
#define V3D_INVALID_BACKBUF 8
+#define V3D_INVALID_BACKBUF 8
#define V3D_ALIGN 1024
#define V3D_SELECT_OUTLINE 2048
@@ -261,14 +264,16 @@ typedef struct View3D {
/* View3d->flag2 (short) */
#define V3D_RENDER_OVERRIDE 4
#define V3D_SOLID_TEX 8
-#define V3D_DISPGP 16
+#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_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_RENDER_BORDER 2048
+#define V3D_SOLID_MATCAP 4096 /* user flag */
+#define V3D_SHOW_SOLID_MATCAP 8192 /* runtime flag */
/* View3D->around */
#define V3D_CENTER 0
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index 2294abc0735..27aef3b8ec6 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -65,19 +65,21 @@ struct uiLayout;
/* keep in sync with 'wm_report_items' in wm_rna.c */
typedef enum ReportType {
- RPT_DEBUG = 1<<0,
- RPT_INFO = 1<<1,
- RPT_OPERATOR = 1<<2,
- RPT_WARNING = 1<<3,
- RPT_ERROR = 1<<4,
- RPT_ERROR_INVALID_INPUT = 1<<5,
- RPT_ERROR_INVALID_CONTEXT = 1<<6,
- RPT_ERROR_OUT_OF_MEMORY = 1<<7
+ RPT_DEBUG = 1 << 0,
+ RPT_INFO = 1 << 1,
+ RPT_OPERATOR = 1 << 2,
+ RPT_PROPERTY = 1 << 3,
+ RPT_WARNING = 1 << 4,
+ RPT_ERROR = 1 << 5,
+ RPT_ERROR_INVALID_INPUT = 1 << 6,
+ RPT_ERROR_INVALID_CONTEXT = 1 << 7,
+ RPT_ERROR_OUT_OF_MEMORY = 1 << 8
} ReportType;
#define RPT_DEBUG_ALL (RPT_DEBUG)
#define RPT_INFO_ALL (RPT_INFO)
#define RPT_OPERATOR_ALL (RPT_OPERATOR)
+#define RPT_PROPERTY_ALL (RPT_PROPERTY)
#define RPT_WARNING_ALL (RPT_WARNING)
#define RPT_ERROR_ALL (RPT_ERROR|RPT_ERROR_INVALID_INPUT|RPT_ERROR_INVALID_CONTEXT|RPT_ERROR_OUT_OF_MEMORY)
diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h
index 8a14564f8a4..02dc81ccd4d 100644
--- a/source/blender/makesdna/DNA_world_types.h
+++ b/source/blender/makesdna/DNA_world_types.h
@@ -59,10 +59,7 @@ typedef struct World {
float horr, horg, horb;
float zenr, zeng, zenb;
float ambr, ambg, ambb;
- float pad2;
- unsigned int fastcol;
-
/**
* Exposure= mult factor. unused now, but maybe back later. Kept in to be upward compat.
* New is exp/range control. linfac & logfac are constants... don't belong in
diff --git a/source/blender/makesdna/SConscript b/source/blender/makesdna/SConscript
index c3d39783b00..dba0f84170e 100644
--- a/source/blender/makesdna/SConscript
+++ b/source/blender/makesdna/SConscript
@@ -1,11 +1,41 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
objs = []
+defs = []
o = SConscript('intern/SConscript')
objs += o
-incs = '#/intern/guardedalloc .'
+incs = '#/intern/guardedalloc . ../blenlib'
+
+if env['WITH_BF_FREESTYLE']:
+ defs.append('WITH_FREESTYLE')
-env.BlenderLib ( 'bf_dna', objs, Split(incs), [], libtype=['core','player'], priority = [215,200] )
+env.BlenderLib ( 'bf_dna', objs, Split(incs), defs, libtype=['core','player'], priority = [215,200] )
diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt
index 1dd1d7e8f87..0ad52d9b3a3 100644
--- a/source/blender/makesdna/intern/CMakeLists.txt
+++ b/source/blender/makesdna/intern/CMakeLists.txt
@@ -34,7 +34,6 @@ blender_include_dirs(
..
)
-
# -----------------------------------------------------------------------------
# Build makesdna executable
set(SRC
diff --git a/source/blender/makesdna/intern/SConscript b/source/blender/makesdna/intern/SConscript
index c1e6eb5281d..add9611866d 100644
--- a/source/blender/makesdna/intern/SConscript
+++ b/source/blender/makesdna/intern/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
import sys
import os
diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c
index 10c3b0bbee4..1225821102a 100644
--- a/source/blender/makesdna/intern/dna_genfile.c
+++ b/source/blender/makesdna/intern/dna_genfile.c
@@ -29,7 +29,10 @@
/** \file blender/makesdna/intern/dna_genfile.c
* \ingroup DNA
*
- * Functions for struct-dna, the genetic file dot c!
+ * Lowest-level functions for decoding the parts of a saved .blend
+ * file, including interpretation of its SDNA block and conversion of
+ * contents of other parts according to the differences between that
+ * SDNA and the SDNA of the current (running) version of Blender.
*/
@@ -39,8 +42,9 @@
#include "MEM_guardedalloc.h" // for MEM_freeN MEM_mallocN MEM_callocN
+#include "BLI_utildefines.h"
+
#ifdef WITH_DNA_GHASH
-# include "BLI_utildefines.h"
# include "BLI_ghash.h"
#endif
@@ -134,12 +138,11 @@ typedef long long __int64;
*
*/
-/* local */
-static int le_int(int temp);
-static short le_short(short temp);
-
/* ************************* ENDIAN STUFF ********************** */
+/**
+ * converts a short between big/little endian.
+ */
static short le_short(short temp)
{
short new;
@@ -151,7 +154,9 @@ static short le_short(short temp)
return new;
}
-
+/**
+ * converts an int between big/little endian.
+ */
static int le_int(int temp)
{
int new;
@@ -169,6 +174,10 @@ static int le_int(int temp)
/* ************************* MAKE DNA ********************** */
/* allowed duplicate code from makesdna.c */
+
+/**
+ * parses the "[n]" on the end of an array name and returns the number of array elements n.
+ */
int DNA_elem_array_size(const char *astr, int len)
{
int a, mul = 1;
@@ -207,14 +216,23 @@ void DNA_sdna_free(SDNA *sdna)
MEM_freeN(sdna);
}
-static int ispointer(const char *name)
+/**
+ * Return true if the name indicates a pointer of some kind.
+ */
+static bool ispointer(const char *name)
{
/* check if pointer or function pointer */
return (name[0] == '*' || (name[0] == '(' && name[1] == '*'));
}
-static int elementsize(SDNA *sdna, short type, short name)
-/* call with numbers from struct-array */
+/**
+ * Returns the size of struct fields of the specified type and name.
+ *
+ * \param type Index into sdna->types/typelens
+ * \param name Index into sdna->names,
+ * needed to extract possible pointer/array information.
+ */
+static int elementsize(const SDNA *sdna, short type, short name)
{
int mul, namelen, len;
const char *cp;
@@ -225,16 +243,20 @@ static int elementsize(SDNA *sdna, short type, short name)
namelen = strlen(cp);
/* is it a pointer or function pointer? */
if (ispointer(cp)) {
- /* has the naam an extra length? (array) */
+ /* has the name an extra length? (array) */
mul = 1;
- if (cp[namelen - 1] == ']') mul = DNA_elem_array_size(cp, namelen);
+ if (cp[namelen - 1] == ']') {
+ mul = DNA_elem_array_size(cp, namelen);
+ }
len = sdna->pointerlen * mul;
}
else if (sdna->typelens[type]) {
- /* has the naam an extra length? (array) */
+ /* has the name an extra length? (array) */
mul = 1;
- if (cp[namelen - 1] == ']') mul = DNA_elem_array_size(cp, namelen);
+ if (cp[namelen - 1] == ']') {
+ mul = DNA_elem_array_size(cp, namelen);
+ }
len = mul * sdna->typelens[type];
@@ -262,6 +284,9 @@ static void printstruct(SDNA *sdna, short strnr)
}
#endif
+/**
+ * Returns a pointer to the start of the struct info for the struct with the specified name.
+ */
static short *findstruct_name(SDNA *sdna, const char *str)
{
int a;
@@ -272,19 +297,26 @@ static short *findstruct_name(SDNA *sdna, const char *str)
sp = sdna->structs[a];
- if (strcmp(sdna->types[sp[0]], str) == 0) return sp;
+ if (strcmp(sdna->types[sp[0]], str) == 0) {
+ return sp;
+ }
}
return NULL;
}
+/**
+ * Returns the index of the struct info for the struct with the specified name.
+ */
int DNA_struct_find_nr(SDNA *sdna, const char *str)
{
short *sp = NULL;
if (sdna->lastfind < sdna->nr_structs) {
sp = sdna->structs[sdna->lastfind];
- if (strcmp(sdna->types[sp[0]], str) == 0) return sdna->lastfind;
+ if (strcmp(sdna->types[sp[0]], str) == 0) {
+ return sdna->lastfind;
+ }
}
#ifdef WITH_DNA_GHASH
@@ -311,8 +343,10 @@ int DNA_struct_find_nr(SDNA *sdna, const char *str)
/* ************************* READ DNA ********************** */
-static void init_structDNA(SDNA *sdna, int do_endian_swap)
-/* in sdna->data the data, now we convert that to something understandable */
+/**
+ * In sdna->data the data, now we convert that to something understandable
+ */
+static void init_structDNA(SDNA *sdna, bool do_endian_swap)
{
int *data, *verg, gravity_fix = -1;
intptr_t nr;
@@ -481,7 +515,7 @@ static void init_structDNA(SDNA *sdna, int do_endian_swap)
if (sp[1] != 2 || (sdna->pointerlen != 4 && sdna->pointerlen != 8)) {
printf("ListBase struct error! Needs it to calculate pointerize.\n");
- exit(0);
+ exit(1);
/* well, at least sizeof(ListBase) is error proof! (ton) */
}
@@ -506,7 +540,10 @@ static void init_structDNA(SDNA *sdna, int do_endian_swap)
}
}
-SDNA *DNA_sdna_from_data(const void *data, const int datalen, int do_endian_swap)
+/**
+ * Constructs and returns a decoded SDNA structure from the given encoded SDNA data block.
+ */
+SDNA *DNA_sdna_from_data(const void *data, const int datalen, bool do_endian_swap)
{
SDNA *sdna = MEM_mallocN(sizeof(*sdna), "sdna");
@@ -525,7 +562,11 @@ SDNA *DNA_sdna_from_data(const void *data, const int datalen, int do_endian_swap
/* ******************* HANDLE DNA ***************** */
-static void recurs_test_compflags(SDNA *sdna, char *compflags, int structnr)
+/**
+ * Used by #DNA_struct_get_compareflags (below) to recursively mark all structs
+ * containing a field of type structnr as changed between old and current SDNAs.
+ */
+static void recurs_test_compflags(const SDNA *sdna, char *compflags, int structnr)
{
int a, b, typenr, elems;
short *sp;
@@ -554,75 +595,70 @@ static void recurs_test_compflags(SDNA *sdna, char *compflags, int structnr)
}
-/* Unsure of exact function - compares the sdna argument to
- * newsdna and sets up the information necessary to convert
- * data written with a dna of oldsdna to in-memory data with a
- * structure defined by the newsdna sdna (I think). -zr
- */
-/* well, the function below is just a lookup table to speed
- * up reading files. doh! -ton
+/**
+ * Constructs and returns an array of byte flags with one element for each struct in oldsdna,
+ * indicating how it compares to newsdna:
+ *
+ * flag value:
+ * - 0 Struct has disappeared (values of this struct type will not be loaded by the current Blender)
+ * - 1 Struct is the same (can be loaded with straight memory copy after any necessary endian conversion)
+ * - 2 Struct is different in some way (needs to be copied/converted field by field)
*/
-
-
-char *DNA_struct_get_compareflags(SDNA *sdna, SDNA *newsdna)
+char *DNA_struct_get_compareflags(SDNA *oldsdna, SDNA *newsdna)
{
- /* flag: 0: doesn't exist anymore (or not yet)
- * 1: is equal
- * 2: is different
- */
int a, b;
- short *spold, *spcur;
+ const short *sp_old, *sp_new;
const char *str1, *str2;
char *compflags;
- if (sdna->nr_structs == 0) {
+ if (oldsdna->nr_structs == 0) {
printf("error: file without SDNA\n");
return NULL;
}
-
- compflags = MEM_callocN(sdna->nr_structs, "compflags");
- /* we check all structs in 'sdna' and compare them with
+ compflags = MEM_callocN(oldsdna->nr_structs, "compflags");
+
+ /* we check all structs in 'oldsdna' and compare them with
* the structs in 'newsdna'
*/
- for (a = 0; a < sdna->nr_structs; a++) {
- spold = sdna->structs[a];
+ for (a = 0; a < oldsdna->nr_structs; a++) {
+ sp_old = oldsdna->structs[a];
/* search for type in cur */
- spcur = findstruct_name(newsdna, sdna->types[spold[0]]);
+ sp_new = findstruct_name(newsdna, oldsdna->types[sp_old[0]]);
- if (spcur) {
- compflags[a] = 2;
+ if (sp_new) {
+ compflags[a] = 2; /* initial assumption */
/* compare length and amount of elems */
- if (spcur[1] == spold[1]) {
- if (newsdna->typelens[spcur[0]] == sdna->typelens[spold[0]]) {
+ if (sp_new[1] == sp_old[1]) {
+ if (newsdna->typelens[sp_new[0]] == oldsdna->typelens[sp_old[0]]) {
/* same length, same amount of elems, now per type and name */
- b = spold[1];
- spold += 2;
- spcur += 2;
+ b = sp_old[1];
+ sp_old += 2;
+ sp_new += 2;
while (b > 0) {
- str1 = newsdna->types[spcur[0]];
- str2 = sdna->types[spold[0]];
+ str1 = newsdna->types[sp_new[0]];
+ str2 = oldsdna->types[sp_old[0]];
if (strcmp(str1, str2) != 0) break;
- str1 = newsdna->names[spcur[1]];
- str2 = sdna->names[spold[1]];
+ str1 = newsdna->names[sp_new[1]];
+ str2 = oldsdna->names[sp_old[1]];
if (strcmp(str1, str2) != 0) break;
/* same type and same name, now pointersize */
if (ispointer(str1)) {
- if (sdna->pointerlen != newsdna->pointerlen) break;
+ if (oldsdna->pointerlen != newsdna->pointerlen) break;
}
b--;
- spold += 2;
- spcur += 2;
+ sp_old += 2;
+ sp_new += 2;
}
- if (b == 0) compflags[a] = 1;
+ if (b == 0) compflags[a] = 1; /* no differences found */
}
}
@@ -638,15 +674,15 @@ char *DNA_struct_get_compareflags(SDNA *sdna, SDNA *newsdna)
/* Because structs can be inside structs, we recursively
* set flags when a struct is altered
*/
- for (a = 0; a < sdna->nr_structs; a++) {
- if (compflags[a] == 2) recurs_test_compflags(sdna, compflags, a);
+ for (a = 0; a < oldsdna->nr_structs; a++) {
+ if (compflags[a] == 2) recurs_test_compflags(oldsdna, compflags, a);
}
#if 0
- for (a = 0; a < sdna->nr_structs; a++) {
+ for (a = 0; a < oldsdna->nr_structs; a++) {
if (compflags[a] == 2) {
- spold = sdna->structs[a];
- printf("changed: %s\n", sdna->types[spold[0]]);
+ spold = oldsdna->structs[a];
+ printf("changed: %s\n", oldsdna->types[spold[0]]);
}
}
#endif
@@ -654,6 +690,9 @@ char *DNA_struct_get_compareflags(SDNA *sdna, SDNA *newsdna)
return compflags;
}
+/**
+ * Converts the name of a primitive type to its enumeration code.
+ */
static eSDNA_Type sdna_type_nr(const char *dna_type)
{
if ((strcmp(dna_type, "char") == 0) || (strcmp(dna_type, "const char") == 0)) return SDNA_TYPE_CHAR;
@@ -670,7 +709,20 @@ static eSDNA_Type sdna_type_nr(const char *dna_type)
else return -1; /* invalid! */
}
-static void cast_elem(const char *ctype, const char *otype, const char *name, char *curdata, char *olddata)
+/**
+ * Converts a value of one primitive type to another.
+ * Note there is no optimization for the case where otype and ctype are the same:
+ * assumption is that caller will handle this case.
+ *
+ * \param ctype Name of type to convert to
+ * \param otype Name of type to convert from
+ * \param name Field name to extract array-size information
+ * \param curdata Where to put converted data
+ * \param olddata Data of type otype to convert
+ */
+static void cast_elem(
+ const char *ctype, const char *otype, const char *name,
+ char *curdata, const char *olddata)
{
double val = 0.0;
int arrlen, curlen = 1, oldlen = 1;
@@ -748,7 +800,18 @@ static void cast_elem(const char *ctype, const char *otype, const char *name, ch
}
}
-static void cast_pointer(int curlen, int oldlen, const char *name, char *curdata, char *olddata)
+/**
+ * Converts pointer values between different sizes. These are only used
+ * as lookup keys to identify data blocks in the saved .blend file, not
+ * as actual in-memory pointers.
+ *
+ * \param curlen Pointer length to conver to
+ * \param oldlen Length of pointers in olddata
+ * \param name Field name to extract array-size information
+ * \param curdata Where to put converted data
+ * \param olddata Data to convert
+ */
+static void cast_pointer(int curlen, int oldlen, const char *name, char *curdata, const char *olddata)
{
#ifdef WIN32
__int64 lval;
@@ -770,7 +833,10 @@ static void cast_pointer(int curlen, int oldlen, const char *name, char *curdata
#else
lval = *( (long long *)olddata);
#endif
- *((int *)curdata) = lval >> 3; /* is of course gambling! */
+ /* WARNING: 32-bit Blender trying to load file saved by 64-bit Blender,
+ * pointers may lose uniqueness on truncation! (Hopefully this wont
+ * happen unless/until we ever get to multi-gigabyte .blend files...) */
+ *((int *)curdata) = lval >> 3;
}
else if (curlen == 8 && oldlen == 4) {
#ifdef WIN32
@@ -791,22 +857,42 @@ static void cast_pointer(int curlen, int oldlen, const char *name, char *curdata
}
}
+/**
+ * Equality test on name and oname excluding any array-size suffix.
+ */
static int elem_strcmp(const char *name, const char *oname)
{
int a = 0;
- /* strcmp without array part */
-
while (1) {
if (name[a] != oname[a]) return 1;
- if (name[a] == '[') break;
- if (name[a] == 0) break;
+ if (name[a] == '[' || oname[a] == '[') break;
+ if (name[a] == 0 || oname[a] == 0) break;
a++;
}
return 0;
}
-static char *find_elem(SDNA *sdna, const char *type, const char *name, short *old, char *olddata, short **sppo)
+/**
+ * Returns the address of the data for the specified field within olddata
+ * according to the struct format pointed to by old, or NULL if no such
+ * field can be found.
+ *
+ * \param sdna Old SDNA
+ * \param type Current field type name
+ * \param name Current field name
+ * \param old Pointer to struct information in sdna
+ * \param olddata Struct data
+ * \param sppo Optional place to return pointer to field info in sdna
+ * \return Data address.
+ */
+static char *find_elem(
+ const SDNA *sdna,
+ const char *type,
+ const char *name,
+ const short *old,
+ char *olddata,
+ const short **sppo)
{
int a, elemcount, len;
const char *otype, *oname;
@@ -823,8 +909,8 @@ static char *find_elem(SDNA *sdna, const char *type, const char *name, short *ol
len = elementsize(sdna, old[0], old[1]);
- if (elem_strcmp(name, oname) == 0) { /* naam equal */
- if (strcmp(type, otype) == 0) { /* type equal */
+ if (elem_strcmp(name, oname) == 0) { /* name equal */
+ if (strcmp(type, otype) == 0) { /* type equal */
if (sppo) *sppo = old;
return olddata;
}
@@ -837,8 +923,26 @@ static char *find_elem(SDNA *sdna, const char *type, const char *name, short *ol
return NULL;
}
-static void reconstruct_elem(SDNA *newsdna, SDNA *oldsdna,
- char *type, const char *name, char *curdata, short *old, char *olddata)
+/**
+ * Converts the contents of a single field of a struct, of a non-struct type,
+ * from oldsdna to newsdna format.
+ *
+ * \param newsdna SDNA of current Blender
+ * \param oldsdna SDNA of Blender that saved file
+ * \param type current field type name
+ * \param name current field name
+ * \param curdata put field data converted to newsdna here
+ * \param old pointer to struct info in oldsdna
+ * \param olddata struct contents laid out according to oldsdna
+ */
+static void reconstruct_elem(
+ const SDNA *newsdna,
+ const SDNA *oldsdna,
+ const char *type,
+ const char *name,
+ char *curdata,
+ const short *old,
+ const char *olddata)
{
/* rules: test for NAME:
* - name equal:
@@ -849,17 +953,16 @@ static void reconstruct_elem(SDNA *newsdna, SDNA *oldsdna,
* (nzc 2-4-2001 I want the 'unsigned' bit to be parsed as well. Where
* can I force this?)
*/
- int a, elemcount, len, array, oldsize, cursize, mul;
- char *otype;
- const char *oname, *cp;
+ int a, elemcount, len, countpos, oldsize, cursize, mul;
+ const char *otype, *oname, *cp;
/* is 'name' an array? */
cp = name;
- array = 0;
+ countpos = 0;
while (*cp && *cp != '[') {
- cp++; array++;
+ cp++; countpos++;
}
- if (*cp != '[') array = 0;
+ if (*cp != '[') countpos = 0;
/* in old is the old struct */
elemcount = old[1];
@@ -877,33 +980,38 @@ static void reconstruct_elem(SDNA *newsdna, SDNA *oldsdna,
else if (strcmp(type, otype) == 0) { /* type equal */
memcpy(curdata, olddata, len);
}
- else cast_elem(type, otype, name, curdata, olddata);
+ else {
+ cast_elem(type, otype, name, curdata, olddata);
+ }
return;
}
- else if (array) { /* name is an array */
+ else if (countpos != 0) { /* name is an array */
- if (oname[array] == '[' && strncmp(name, oname, array) == 0) { /* basis equal */
+ if (oname[countpos] == '[' && strncmp(name, oname, countpos) == 0) { /* basis equal */
cursize = DNA_elem_array_size(name, strlen(name));
oldsize = DNA_elem_array_size(oname, strlen(oname));
- if (ispointer(name)) { /* handle pointer or functionpointer */
- if (cursize > oldsize) cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, oname, curdata, olddata);
- else cast_pointer(newsdna->pointerlen, oldsdna->pointerlen, name, curdata, olddata);
+ if (ispointer(name)) { /* handle pointer or functionpointer */
+ cast_pointer(newsdna->pointerlen, oldsdna->pointerlen,
+ cursize > oldsize ? oname : name,
+ curdata, olddata);
}
- else if (name[0] == '*' || strcmp(type, otype) == 0) { /* type equal */
- mul = len / oldsize;
- mul *= (cursize < oldsize) ? cursize : oldsize;
+ else if (strcmp(type, otype) == 0) { /* type equal */
+ mul = len / oldsize; /* size of single old array element */
+ mul *= (cursize < oldsize) ? cursize : oldsize; /* smaller of sizes of old and new arrays */
memcpy(curdata, olddata, mul);
- /* terminate strings */
- if (oldsize > cursize && strcmp(type, "char") == 0)
- curdata[mul - 1] = 0;
+ if (oldsize > cursize && strcmp(type, "char") == 0) {
+ /* string had to be truncated, ensure it's still null-terminated */
+ curdata[mul - 1] = '\0';
+ }
}
else {
- if (cursize > oldsize) cast_elem(type, otype, oname, curdata, olddata);
- else cast_elem(type, otype, name, curdata, olddata);
+ cast_elem(type, otype,
+ cursize > oldsize ? oname : name,
+ curdata, olddata);
}
return;
}
@@ -912,16 +1020,37 @@ static void reconstruct_elem(SDNA *newsdna, SDNA *oldsdna,
}
}
-static void reconstruct_struct(SDNA *newsdna, SDNA *oldsdna,
- char *compflags, int oldSDNAnr, char *data, int curSDNAnr, char *cur)
+/**
+ * Converts the contents of an entire struct from oldsdna to newsdna format.
+ *
+ * \param newsdna SDNA of current Blender
+ * \param oldsdna SDNA of Blender that saved file
+ * \param compflags
+ *
+ * Result from DNA_struct_get_compareflags to avoid needless conversions.
+ * \param oldSDNAnr Index of old struct definition in oldsdna
+ * \param data Struct contents laid out according to oldsdna
+ * \param curSDNAnr Index of current struct definition in newsdna
+ * \param cur Where to put converted struct contents
+ */
+static void reconstruct_struct(
+ SDNA *newsdna,
+ SDNA *oldsdna,
+ const char *compflags,
+
+ int oldSDNAnr,
+ char *data,
+ int curSDNAnr,
+ char *cur)
{
/* Recursive!
* Per element from cur_struct, read data from old_struct.
* If element is a struct, call recursive.
*/
int a, elemcount, elen, eleno, mul, mulo, firststructtypenr;
- short *spo, *spc, *sppo;
- char *type, *cpo, *cpc;
+ const short *spo, *spc, *sppo;
+ const char *type;
+ char *cpo, *cpc;
const char *name, *nameo;
if (oldSDNAnr == -1) return;
@@ -945,7 +1074,7 @@ static void reconstruct_struct(SDNA *newsdna, SDNA *oldsdna,
spc += 2;
cpc = cur;
- for (a = 0; a < elemcount; a++, spc += 2) {
+ for (a = 0; a < elemcount; a++, spc += 2) { /* convert each field */
type = newsdna->types[spc[0]];
name = newsdna->names[spc[1]];
@@ -953,7 +1082,7 @@ static void reconstruct_struct(SDNA *newsdna, SDNA *oldsdna,
/* test: is type a struct? */
if (spc[0] >= firststructtypenr && !ispointer(name)) {
-
+ /* struct field type */
/* where does the old struct data start (and is there an old one?) */
cpo = find_elem(oldsdna, type, name, spo, data, &sppo);
@@ -981,26 +1110,34 @@ static void reconstruct_struct(SDNA *newsdna, SDNA *oldsdna,
if (mulo <= 0) break;
}
}
- else cpc += elen;
+ else {
+ cpc += elen; /* skip field no longer present */
+ }
}
else {
-
+ /* non-struct field type */
reconstruct_elem(newsdna, oldsdna, type, name, cpc, spo, data);
cpc += elen;
-
}
}
}
+/**
+ * Does endian swapping on the fields of a struct value.
+ *
+ * \param oldsdna SDNA of Blender that saved file
+ * \param oldSDNAnr Index of struct info within oldsdna
+ * \param data Struct data
+ */
void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data)
{
/* Recursive!
* If element is a struct, call recursive.
*/
int a, mul, elemcount, elen, elena, firststructtypenr;
- short *spo, *spc, skip;
- char *type, *cpo, *cur, cval;
- const char *name;
+ const short *spo, *spc;
+ char *cpo, *cur, cval;
+ const char *type, *name;
if (oldSDNAnr == -1) return;
firststructtypenr = *(oldsdna->structs[0]);
@@ -1021,6 +1158,7 @@ void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data)
/* test: is type a struct? */
if (spc[0] >= firststructtypenr && !ispointer(name)) {
+ /* struct field type */
/* where does the old data start (is there one?) */
cpo = find_elem(oldsdna, type, name, spo, data, NULL);
if (cpo) {
@@ -1036,7 +1174,7 @@ void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data)
}
}
else {
-
+ /* non-struct field type */
if (ispointer(name)) {
if (oldsdna->pointerlen == 8) {
@@ -1060,15 +1198,15 @@ void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data)
{
/* exception: variable called blocktype/ipowin: derived from ID_ */
- skip = 0;
+ bool skip = false;
if (name[0] == 'b' && name[1] == 'l') {
- if (strcmp(name, "blocktype") == 0) skip = 1;
+ if (strcmp(name, "blocktype") == 0) skip = true;
}
else if (name[0] == 'i' && name[1] == 'p') {
- if (strcmp(name, "ipowin") == 0) skip = 1;
+ if (strcmp(name, "ipowin") == 0) skip = true;
}
- if (skip == 0) {
+ if (skip == false) {
mul = DNA_elem_array_size(name, strlen(name));
cpo = cur;
while (mul--) {
@@ -1111,17 +1249,30 @@ void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data)
cpo += 8;
}
}
+ /* FIXME: no conversion for SDNA_TYPE_DOUBLE? */
}
}
cur += elen;
}
}
+/**
+ * \param newsdna SDNA of current Blender
+ * \param oldsdna SDNA of Blender that saved file
+ * \param compflags
+ *
+ * Result from DNA_struct_get_compareflags to avoid needless conversions
+ * \param oldSDNAnr Index of struct info within oldsdna
+ * \param blocks The number of array elements
+ * \param data Array of struct data
+ * \return An allocated reconstructed struct
+ */
void *DNA_struct_reconstruct(SDNA *newsdna, SDNA *oldsdna, char *compflags, int oldSDNAnr, int blocks, void *data)
{
int a, curSDNAnr, curlen = 0, oldlen;
- short *spo, *spc;
- char *cur, *type, *cpc, *cpo;
+ const short *spo, *spc;
+ char *cur, *cpc, *cpo;
+ const char *type;
/* oldSDNAnr == structnr, we're looking for the corresponding 'cur' number */
spo = oldsdna->structs[oldSDNAnr];
@@ -1150,18 +1301,41 @@ void *DNA_struct_reconstruct(SDNA *newsdna, SDNA *oldsdna, char *compflags, int
return cur;
}
+/**
+ * Returns the offset of the field with the specified name and type within the specified
+ * struct type in sdna.
+ */
int DNA_elem_offset(SDNA *sdna, const char *stype, const char *vartype, const char *name)
{
- int SDNAnr = DNA_struct_find_nr(sdna, stype);
- short *spo = sdna->structs[SDNAnr];
- char *cp = find_elem(sdna, vartype, name, spo, NULL, NULL);
+ const int SDNAnr = DNA_struct_find_nr(sdna, stype);
+ const short * const spo = sdna->structs[SDNAnr];
+ char * const cp = find_elem(sdna, vartype, name, spo, NULL, NULL);
return (int)((intptr_t)cp);
}
+bool DNA_struct_elem_find(SDNA *sdna, const char *stype, const char *vartype, const char *name)
+{
+
+ const int SDNAnr = DNA_struct_find_nr(sdna, stype);
+
+ if (SDNAnr >= 0) {
+ const short * const spo = sdna->structs[SDNAnr];
+ char * const cp = find_elem(sdna, vartype, name, spo, NULL, NULL);
+
+ if (cp) return true;
+ return (int)((intptr_t)cp);
+ }
+ return false;
+}
+
+
+/**
+ * Returns the size in bytes of a primitive type.
+ */
int DNA_elem_type_size(const eSDNA_Type elem_nr)
{
- /* should containt all enum types */
+ /* should contain all enum types */
switch (elem_nr) {
case SDNA_TYPE_CHAR:
case SDNA_TYPE_UCHAR:
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index fa0b313a120..da1811656a6 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -133,6 +133,9 @@ static const char *includefiles[] = {
"DNA_tracking_types.h",
"DNA_dynamicpaint_types.h",
"DNA_mask_types.h",
+ "DNA_rigidbody_types.h",
+ "DNA_freestyle_types.h",
+ "DNA_linestyle_types.h",
/* empty string to indicate end of includefiles */
""
@@ -208,7 +211,7 @@ static int calculate_structlens(int);
/**
* Construct the DNA.c file
*/
-void dna_write(FILE *file, void *pntr, int size);
+static void dna_write(FILE *file, const void *pntr, const int size);
/**
* Report all structures found so far, and print their lengths.
@@ -250,7 +253,9 @@ static int add_type(const char *str, int len)
}
/* append new type */
- if (nr_types == 0) cp = typedata;
+ if (nr_types == 0) {
+ cp = typedata;
+ }
else {
cp = types[nr_types - 1] + strlen(types[nr_types - 1]) + 1;
}
@@ -396,7 +401,9 @@ static int add_name(const char *str)
}
/* append new type */
- if (nr_names == 0) cp = namedata;
+ if (nr_names == 0) {
+ cp = namedata;
+ }
else {
cp = names[nr_names - 1] + strlen(names[nr_names - 1]) + 1;
}
@@ -892,7 +899,7 @@ static int calculate_structlens(int firststruct)
#define MAX_DNA_LINE_LENGTH 20
-void dna_write(FILE *file, void *pntr, int size)
+static void dna_write(FILE *file, const void *pntr, const int size)
{
static int linelength = 0;
int i;
@@ -934,7 +941,7 @@ void printStructLengths(void)
}
-static int make_structDNA(char *baseDirectory, FILE *file)
+static int make_structDNA(const char *baseDirectory, FILE *file)
{
int len, i;
short *sp;
@@ -984,7 +991,7 @@ static int make_structDNA(char *baseDirectory, FILE *file)
/* little test first... */
/* Mind the breaking condition here! */
if (debugSDNA) printf("\tStart of header scan:\n");
- for (i = 0; strlen(includefiles[i]); i++) {
+ for (i = 0; *(includefiles[i]) != '\0'; i++) {
sprintf(str, "%s%s", baseDirectory, includefiles[i]);
if (debugSDNA) printf("\t|-- Converting %s\n", str);
if (convert_include(str)) {
@@ -1036,12 +1043,10 @@ static int make_structDNA(char *baseDirectory, FILE *file)
/* pass */
}
else {
- strcpy(str, "SDNA");
- dna_write(file, str, 4);
+ dna_write(file, "SDNA", 4);
/* write names */
- strcpy(str, "NAME");
- dna_write(file, str, 4);
+ dna_write(file, "NAME", 4);
len = nr_names;
dna_write(file, &len, 4);
@@ -1053,8 +1058,7 @@ static int make_structDNA(char *baseDirectory, FILE *file)
dna_write(file, names[0], len);
/* write TYPES */
- strcpy(str, "TYPE");
- dna_write(file, str, 4);
+ dna_write(file, "TYPE", 4);
len = nr_types;
dna_write(file, &len, 4);
@@ -1067,16 +1071,14 @@ static int make_structDNA(char *baseDirectory, FILE *file)
dna_write(file, types[0], len);
/* WRITE TYPELENGTHS */
- strcpy(str, "TLEN");
- dna_write(file, str, 4);
+ dna_write(file, "TLEN", 4);
len = 2 * nr_types;
if (nr_types & 1) len += 2;
dna_write(file, typelens_native, len);
/* WRITE STRUCTS */
- strcpy(str, "STRC");
- dna_write(file, str, 4);
+ dna_write(file, "STRC", 4);
len = nr_structs;
dna_write(file, &len, 4);
@@ -1100,7 +1102,7 @@ static int make_structDNA(char *baseDirectory, FILE *file)
else {
/* add all include files defined in the global array */
- for (i = 0; strlen(includefiles[i]); i++) {
+ for (i = 0; *(includefiles[i]) != '\0'; i++) {
fprintf(fp, "#include \"%s%s\"\n", baseDirectory, includefiles[i]);
}
@@ -1165,13 +1167,13 @@ int main(int argc, char **argv)
return_status = 1;
}
else {
- char baseDirectory[256];
+ const char *baseDirectory;
if (argc == 3) {
- strcpy(baseDirectory, argv[2]);
+ baseDirectory = argv[2];
}
else {
- strcpy(baseDirectory, BASE_HEADER);
+ baseDirectory = BASE_HEADER;
}
fprintf(file, "const unsigned char DNAstr[] = {\n");
@@ -1267,4 +1269,7 @@ int main(int argc, char **argv)
#include "DNA_tracking_types.h"
#include "DNA_dynamicpaint_types.h"
#include "DNA_mask_types.h"
+#include "DNA_rigidbody_types.h"
+#include "DNA_freestyle_types.h"
+#include "DNA_linestyle_types.h"
/* end of list */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 0e5f9c5fa5f..22259d71a2f 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -54,6 +54,7 @@ extern StructRNA RNA_ActionPoseMarkers;
extern StructRNA RNA_Actuator;
extern StructRNA RNA_ActuatorSensor;
extern StructRNA RNA_Addon;
+extern StructRNA RNA_AddonPreferences;
extern StructRNA RNA_AdjustmentSequence;
extern StructRNA RNA_AlwaysSensor;
extern StructRNA RNA_AndController;
@@ -91,6 +92,7 @@ extern StructRNA RNA_BoolProperty;
extern StructRNA RNA_Brush;
extern StructRNA RNA_BrushTextureSlot;
extern StructRNA RNA_BuildModifier;
+extern StructRNA RNA_MeshCacheModifier;
extern StructRNA RNA_Camera;
extern StructRNA RNA_CastModifier;
extern StructRNA RNA_ChildOfConstraint;
@@ -104,7 +106,8 @@ extern StructRNA RNA_CollectionProperty;
extern StructRNA RNA_CollisionModifier;
extern StructRNA RNA_CollisionSensor;
extern StructRNA RNA_CollisionSettings;
-extern StructRNA RNA_ColorManagedColorspaceSettings;
+extern StructRNA RNA_ColorManagedInputColorspaceSettings;
+extern StructRNA RNA_ColorManagedSequencerColorspaceSettings;
extern StructRNA RNA_ColorManagedDisplaySettings;
extern StructRNA RNA_ColorManagedViewSettings;
extern StructRNA RNA_ColorRamp;
@@ -240,6 +243,10 @@ extern StructRNA RNA_FluidFluidSettings;
extern StructRNA RNA_FluidSettings;
extern StructRNA RNA_FluidSimulationModifier;
extern StructRNA RNA_FollowPathConstraint;
+extern StructRNA RNA_FreestyleLineStyle;
+extern StructRNA RNA_FreestyleLineSet;
+extern StructRNA RNA_FreestyleModuleSettings;
+extern StructRNA RNA_FreestyleSettings;
extern StructRNA RNA_Function;
extern StructRNA RNA_GPencilFrame;
extern StructRNA RNA_GPencilLayer;
@@ -296,6 +303,37 @@ extern StructRNA RNA_LimitDistanceConstraint;
extern StructRNA RNA_LimitLocationConstraint;
extern StructRNA RNA_LimitRotationConstraint;
extern StructRNA RNA_LimitScaleConstraint;
+extern StructRNA RNA_LineStyleAlphaModifier;
+extern StructRNA RNA_LineStyleAlphaModifier_AlongStroke;
+extern StructRNA RNA_LineStyleAlphaModifier_DistanceFromCamera;
+extern StructRNA RNA_LineStyleAlphaModifier_DistanceFromObject;
+extern StructRNA RNA_LineStyleAlphaModifier_Material;
+extern StructRNA RNA_LineStyleColorModifier;
+extern StructRNA RNA_LineStyleColorModifier_AlongStroke;
+extern StructRNA RNA_LineStyleColorModifier_DistanceFromCamera;
+extern StructRNA RNA_LineStyleColorModifier_DistanceFromObject;
+extern StructRNA RNA_LineStyleColorModifier_Material;
+extern StructRNA RNA_LineStyleGeometryModifier;
+extern StructRNA RNA_LineStyleGeometryModifier_2DOffset;
+extern StructRNA RNA_LineStyleGeometryModifier_2DTransform;
+extern StructRNA RNA_LineStyleGeometryModifier_BackboneStretcher;
+extern StructRNA RNA_LineStyleGeometryModifier_BezierCurve;
+extern StructRNA RNA_LineStyleGeometryModifier_Blueprint;
+extern StructRNA RNA_LineStyleGeometryModifier_GuidingLines;
+extern StructRNA RNA_LineStyleGeometryModifier_PerlinNoise1D;
+extern StructRNA RNA_LineStyleGeometryModifier_PerlinNoise2D;
+extern StructRNA RNA_LineStyleGeometryModifier_Polygonalization;
+extern StructRNA RNA_LineStyleGeometryModifier_Sampling;
+extern StructRNA RNA_LineStyleGeometryModifier_SinusDisplacement;
+extern StructRNA RNA_LineStyleGeometryModifier_SpatialNoise;
+extern StructRNA RNA_LineStyleGeometryModifier_TipRemover;
+extern StructRNA RNA_LineStyleModifier;
+extern StructRNA RNA_LineStyleThicknessModifier;
+extern StructRNA RNA_LineStyleThicknessModifier_AlongStroke;
+extern StructRNA RNA_LineStyleThicknessModifier_Calligraphy;
+extern StructRNA RNA_LineStyleThicknessModifier_DistanceFromCamera;
+extern StructRNA RNA_LineStyleThicknessModifier_DistanceFromObject;
+extern StructRNA RNA_LineStyleThicknessModifier_Material;
extern StructRNA RNA_LockedTrackConstraint;
extern StructRNA RNA_Macro;
extern StructRNA RNA_MagicTexture;
@@ -350,7 +388,6 @@ extern StructRNA RNA_MouseSensor;
extern StructRNA RNA_MovieSequence;
extern StructRNA RNA_MovieClipSequence;
extern StructRNA RNA_MovieTracking;
-extern StructRNA RNA_MovieTrackingTrack;
extern StructRNA RNA_MovieTrackingObject;
extern StructRNA RNA_MovieTrackingTrack;
extern StructRNA RNA_MulticamSequence;
@@ -361,14 +398,13 @@ extern StructRNA RNA_NearSensor;
extern StructRNA RNA_NlaStrip;
extern StructRNA RNA_NlaTrack;
extern StructRNA RNA_Node;
-extern StructRNA RNA_NodeForLoop;
-extern StructRNA RNA_NodeGroup;
extern StructRNA RNA_NodeOutputFileSlotFile;
extern StructRNA RNA_NodeOutputFileSlotLayer;
+extern StructRNA RNA_NodeInstanceHash;
extern StructRNA RNA_NodeLink;
extern StructRNA RNA_NodeSocket;
+extern StructRNA RNA_NodeSocketInterface;
extern StructRNA RNA_NodeTree;
-extern StructRNA RNA_NodeWhileLoop;
extern StructRNA RNA_NoiseTexture;
extern StructRNA RNA_NorController;
extern StructRNA RNA_Object;
@@ -425,6 +461,8 @@ extern StructRNA RNA_RenderLayer;
extern StructRNA RNA_RenderPass;
extern StructRNA RNA_RenderResult;
extern StructRNA RNA_RenderSettings;
+extern StructRNA RNA_RigidBodyWorld;
+extern StructRNA RNA_RigidBodyObject;
extern StructRNA RNA_RigidBodyJointConstraint;
extern StructRNA RNA_SPHFluidSettings;
extern StructRNA RNA_Scene;
@@ -569,6 +607,7 @@ extern StructRNA RNA_ThemeOutliner;
extern StructRNA RNA_ThemeProperties;
extern StructRNA RNA_ThemeSequenceEditor;
extern StructRNA RNA_ThemeSpaceGeneric;
+extern StructRNA RNA_ThemeSpaceGradient;
extern StructRNA RNA_ThemeSpaceListGeneric;
extern StructRNA RNA_ThemeStyle;
extern StructRNA RNA_ThemeTextEditor;
@@ -586,7 +625,8 @@ extern StructRNA RNA_TrackToConstraint;
extern StructRNA RNA_TransformConstraint;
extern StructRNA RNA_TransformSequence;
extern StructRNA RNA_UILayout;
-extern StructRNA RNA_UIListItem;
+extern StructRNA RNA_UIList;
+extern StructRNA RNA_UVWarpModifier;
extern StructRNA RNA_UVProjectModifier;
extern StructRNA RNA_UVProjector;
extern StructRNA RNA_UnitSettings;
@@ -649,7 +689,9 @@ StructRNA *RNA_struct_find(const char *identifier);
const char *RNA_struct_identifier(StructRNA *type);
const char *RNA_struct_ui_name(StructRNA *type);
+const char *RNA_struct_ui_name_raw(StructRNA *type);
const char *RNA_struct_ui_description(StructRNA *type);
+const char *RNA_struct_ui_description_raw(StructRNA *type);
const char *RNA_struct_translation_context(StructRNA *type);
int RNA_struct_ui_icon(StructRNA *type);
@@ -657,10 +699,10 @@ PropertyRNA *RNA_struct_name_property(StructRNA *type);
PropertyRNA *RNA_struct_iterator_property(StructRNA *type);
StructRNA *RNA_struct_base(StructRNA *type);
-int RNA_struct_is_ID(StructRNA *type);
-int RNA_struct_is_a(StructRNA *type, StructRNA *srna);
+bool RNA_struct_is_ID(StructRNA *type);
+bool RNA_struct_is_a(StructRNA *type, StructRNA *srna);
-int RNA_struct_undo_check(StructRNA *type);
+bool RNA_struct_undo_check(StructRNA *type);
StructRegisterFunc RNA_struct_register(StructRNA *type);
StructUnregisterFunc RNA_struct_unregister(StructRNA *type);
@@ -672,13 +714,13 @@ void RNA_struct_py_type_set(StructRNA *srna, void *py_type);
void *RNA_struct_blender_type_get(StructRNA *srna);
void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type);
-struct IDProperty *RNA_struct_idprops(PointerRNA *ptr, int create);
-int RNA_struct_idprops_check(StructRNA *srna);
-int RNA_struct_idprops_register_check(StructRNA *type);
-int RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier);
+struct IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create);
+bool RNA_struct_idprops_check(StructRNA *srna);
+bool RNA_struct_idprops_register_check(StructRNA *type);
+bool RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier);
PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier);
-int RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test);
+bool RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test);
/* lower level functions for access to type properties */
const struct ListBase *RNA_struct_type_properties(StructRNA *srna);
@@ -705,17 +747,19 @@ PropertyUnit RNA_property_unit(PropertyRNA *prop);
int RNA_property_flag(PropertyRNA *prop);
void *RNA_property_py_data_get(PropertyRNA *prop);
-int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop);
-int RNA_property_array_check(PropertyRNA *prop);
-int RNA_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int dimension);
-int RNA_property_array_dimension(PointerRNA *ptr, PropertyRNA *prop, int length[]);
+int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop);
+bool RNA_property_array_check(PropertyRNA *prop);
+int RNA_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int dimension);
+int RNA_property_array_dimension(PointerRNA *ptr, PropertyRNA *prop, int length[]);
char RNA_property_array_item_char(PropertyRNA *prop, int index);
-int RNA_property_array_item_index(PropertyRNA *prop, char name);
+int RNA_property_array_item_index(PropertyRNA *prop, char name);
int RNA_property_string_maxlength(PropertyRNA *prop);
const char *RNA_property_ui_name(PropertyRNA *prop);
+const char *RNA_property_ui_name_raw(PropertyRNA *prop);
const char *RNA_property_ui_description(PropertyRNA *prop);
+const char *RNA_property_ui_description_raw(PropertyRNA *prop);
const char *RNA_property_translation_context(PropertyRNA *prop);
int RNA_property_ui_icon(PropertyRNA *prop);
@@ -730,31 +774,31 @@ void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *soft
int RNA_property_float_clamp(PointerRNA *ptr, PropertyRNA *prop, float *value);
int RNA_property_int_clamp(PointerRNA *ptr, PropertyRNA *prop, int *value);
-int RNA_enum_identifier(EnumPropertyItem *item, const int value, const char **identifier);
-int RNA_enum_bitflag_identifiers(EnumPropertyItem *item, const int value, const char **identifier);
-int RNA_enum_name(EnumPropertyItem *item, const int value, const char **name);
-int RNA_enum_description(EnumPropertyItem *item, const int value, const char **description);
+bool RNA_enum_identifier(EnumPropertyItem *item, const int value, const char **identifier);
+int RNA_enum_bitflag_identifiers(EnumPropertyItem *item, const int value, const char **identifier);
+bool RNA_enum_name(EnumPropertyItem *item, const int value, const char **r_name);
+bool RNA_enum_description(EnumPropertyItem *item, const int value, const char **description);
void RNA_property_enum_items(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, EnumPropertyItem **item, int *totitem, int *free);
void RNA_property_enum_items_gettexted(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, EnumPropertyItem **item, int *totitem, int *free);
-int RNA_property_enum_value(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *value);
-int RNA_property_enum_identifier(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier);
-int RNA_property_enum_name(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name);
+bool RNA_property_enum_value(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *r_value);
+bool RNA_property_enum_identifier(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier);
+bool RNA_property_enum_name(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name);
int RNA_property_enum_bitflag_identifiers(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier);
StructRNA *RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop);
int RNA_property_pointer_poll(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *value);
-int RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop);
-int RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index);
-int RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop); /* without lib check, only checks the flag */
-int RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop);
-int RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop);
-int RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop); /* slow, use with care */
+bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop);
+bool RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index);
+bool RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop); /* without lib check, only checks the flag */
+bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop);
+bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop);
+bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop); /* slow, use with care */
void RNA_property_update(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop);
void RNA_property_update_main(struct Main *bmain, struct Scene *scene, PointerRNA *ptr, PropertyRNA *prop);
-int RNA_property_update_check(struct PropertyRNA *prop);
+bool RNA_property_update_check(struct PropertyRNA *prop);
void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop);
void RNA_property_update_cache_flush(struct Main *bmain, struct Scene *scene);
@@ -819,7 +863,7 @@ int RNA_property_collection_lookup_index(PointerRNA *ptr, PropertyRNA *prop, Poi
int RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr);
int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr);
int RNA_property_collection_assign_int(PointerRNA *ptr, PropertyRNA *prop, const int key, const PointerRNA *assign_ptr);
-int RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr);
+bool RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr);
/* efficient functions to set properties for arrays */
int RNA_property_collection_raw_array(PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, RawArray *array);
@@ -833,13 +877,13 @@ RawPropertyType RNA_property_raw_type(PropertyRNA *prop);
void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop);
void RNA_property_pointer_remove(PointerRNA *ptr, PropertyRNA *prop);
void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr);
-int RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key);
+bool RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key);
void RNA_property_collection_clear(PointerRNA *ptr, PropertyRNA *prop);
-int RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, int pos);
+bool RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, int pos);
/* copy/reset */
-int RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, int index);
-int RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index);
+bool RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, int index);
+bool RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index);
/* Path
*
@@ -862,7 +906,12 @@ int RNA_path_resolve_full(PointerRNA *ptr, const char *path,
char *RNA_path_from_ID_to_struct(PointerRNA *ptr);
char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop);
-char *RNA_path_from_ID_python(struct ID *id);
+
+char *RNA_path_full_ID_py(struct ID *id);
+char *RNA_path_full_struct_py(struct PointerRNA *ptr);
+char *RNA_path_full_property_py(struct PointerRNA *ptr, struct PropertyRNA *prop, int index);
+char *RNA_path_struct_property_py(struct PointerRNA *ptr, struct PropertyRNA *prop, int index);
+char *RNA_path_property_py(struct PointerRNA *ptr, struct PropertyRNA *prop, int index);
/* Quick name based property access
*
@@ -873,36 +922,36 @@ char *RNA_path_from_ID_python(struct ID *id);
* There is no support for pointers and collections here yet, these can be
* added when ID properties support them. */
-int RNA_boolean_get(PointerRNA *ptr, const char *name);
+int RNA_boolean_get(PointerRNA *ptr, const char *name);
void RNA_boolean_set(PointerRNA *ptr, const char *name, int value);
void RNA_boolean_get_array(PointerRNA *ptr, const char *name, int *values);
void RNA_boolean_set_array(PointerRNA *ptr, const char *name, const int *values);
-int RNA_int_get(PointerRNA *ptr, const char *name);
+int RNA_int_get(PointerRNA *ptr, const char *name);
void RNA_int_set(PointerRNA *ptr, const char *name, int value);
void RNA_int_get_array(PointerRNA *ptr, const char *name, int *values);
void RNA_int_set_array(PointerRNA *ptr, const char *name, const int *values);
float RNA_float_get(PointerRNA *ptr, const char *name);
-void RNA_float_set(PointerRNA *ptr, const char *name, float value);
-void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values);
-void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values);
+void RNA_float_set(PointerRNA *ptr, const char *name, float value);
+void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values);
+void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values);
-int RNA_enum_get(PointerRNA *ptr, const char *name);
+int RNA_enum_get(PointerRNA *ptr, const char *name);
void RNA_enum_set(PointerRNA *ptr, const char *name, int value);
void RNA_enum_set_identifier(PointerRNA *ptr, const char *name, const char *id);
-int RNA_enum_is_equal(struct bContext *C, PointerRNA *ptr, const char *name, const char *enumname);
+bool RNA_enum_is_equal(struct bContext *C, PointerRNA *ptr, const char *name, const char *enumname);
/* lower level functions that don't use a PointerRNA */
-int RNA_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *value);
-int RNA_enum_id_from_value(EnumPropertyItem *item, int value, const char **identifier);
-int RNA_enum_icon_from_value(EnumPropertyItem *item, int value, int *icon);
-int RNA_enum_name_from_value(EnumPropertyItem *item, int value, const char **name);
+bool RNA_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *r_value);
+bool RNA_enum_id_from_value(EnumPropertyItem *item, int value, const char **r_identifier);
+bool RNA_enum_icon_from_value(EnumPropertyItem *item, int value, int *r_icon);
+bool RNA_enum_name_from_value(EnumPropertyItem *item, int value, const char **r_name);
-void RNA_string_get(PointerRNA *ptr, const char *name, char *value);
+void RNA_string_get(PointerRNA *ptr, const char *name, char *value);
char *RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen);
-int RNA_string_length(PointerRNA *ptr, const char *name);
-void RNA_string_set(PointerRNA *ptr, const char *name, const char *value);
+int RNA_string_length(PointerRNA *ptr, const char *name);
+void RNA_string_set(PointerRNA *ptr, const char *name, const char *value);
/**
* Retrieve the named property from PointerRNA.
@@ -913,7 +962,7 @@ void RNA_pointer_set(PointerRNA *ptr, const char *name, PointerRNA ptr_value);
void RNA_pointer_add(PointerRNA *ptr, const char *name);
void RNA_collection_begin(PointerRNA *ptr, const char *name, CollectionPropertyIterator *iter);
-int RNA_collection_length(PointerRNA *ptr, const char *name);
+int RNA_collection_length(PointerRNA *ptr, const char *name);
void RNA_collection_add(PointerRNA *ptr, const char *name, PointerRNA *r_value);
void RNA_collection_clear(PointerRNA *ptr, const char *name);
@@ -963,15 +1012,17 @@ void RNA_collection_clear(PointerRNA *ptr, const char *name);
}
/* check if the idproperty exists, for operators */
-int RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, int use_ghost);
-int RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop);
-int RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, int use_ghost);
-int RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier);
-int RNA_property_is_idprop(PropertyRNA *prop);
+bool RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, bool use_ghost);
+bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop);
+void RNA_property_unset(PointerRNA *ptr, PropertyRNA *prop);
+bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost);
+bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier);
+bool RNA_property_is_idprop(PropertyRNA *prop);
+void RNA_struct_property_unset(PointerRNA *ptr, const char *identifier);
/* python compatible string representation of this property, (must be freed!) */
-char *RNA_property_as_string(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop);
-char *RNA_pointer_as_string(struct bContext *C, PointerRNA *ptr);
+char *RNA_property_as_string(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index);
+char *RNA_pointer_as_string(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop_ptr, PointerRNA *ptr_prop);
char *RNA_pointer_as_string_keywords_ex(struct bContext *C, PointerRNA *ptr, PointerRNA *ptr_default,
const short skip_optional_value, const short all_args,
PropertyRNA *iterprop);
@@ -984,6 +1035,7 @@ char *RNA_function_as_string_keywords(struct bContext *C, FunctionRNA *func, Poi
const char *RNA_function_identifier(FunctionRNA *func);
const char *RNA_function_ui_description(FunctionRNA *func);
+const char *RNA_function_ui_description_raw(FunctionRNA *func);
int RNA_function_flag(FunctionRNA *func);
int RNA_function_defined(FunctionRNA *func);
@@ -1012,21 +1064,27 @@ int RNA_parameter_length_get_data(ParameterList *parms, PropertyRNA *parm, void
void RNA_parameter_length_set(ParameterList *parms, PropertyRNA *parm, int length);
void RNA_parameter_length_set_data(ParameterList *parms, PropertyRNA *parm, void *data, int length);
-int RNA_function_call(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, FunctionRNA *func, ParameterList *parms);
-int RNA_function_call_lookup(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, const char *identifier, ParameterList *parms);
+int RNA_function_call(struct bContext *C, struct ReportList *reports, PointerRNA *ptr,
+ FunctionRNA *func, ParameterList *parms);
+int RNA_function_call_lookup(struct bContext *C, struct ReportList *reports, PointerRNA *ptr,
+ const char *identifier, ParameterList *parms);
-int RNA_function_call_direct(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, FunctionRNA *func, const char *format, ...)
+int RNA_function_call_direct(struct bContext *C, struct ReportList *reports, PointerRNA *ptr,
+ FunctionRNA *func, const char *format, ...)
#ifdef __GNUC__
__attribute__ ((format(printf, 5, 6)))
#endif
;
-int RNA_function_call_direct_lookup(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, const char *identifier, const char *format, ...)
+int RNA_function_call_direct_lookup(struct bContext *C, struct ReportList *reports, PointerRNA *ptr,
+ const char *identifier, const char *format, ...)
#ifdef __GNUC__
__attribute__ ((format(printf, 5, 6)))
#endif
;
-int RNA_function_call_direct_va(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, FunctionRNA *func, const char *format, va_list args);
-int RNA_function_call_direct_va_lookup(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, const char *identifier, const char *format, va_list args);
+int RNA_function_call_direct_va(struct bContext *C, struct ReportList *reports, PointerRNA *ptr,
+ FunctionRNA *func, const char *format, va_list args);
+int RNA_function_call_direct_va_lookup(struct bContext *C, struct ReportList *reports, PointerRNA *ptr,
+ const char *identifier, const char *format, va_list args);
/* ID */
diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h
index 9939d0839e6..924fc505fda 100644
--- a/source/blender/makesrna/RNA_define.h
+++ b/source/blender/makesrna/RNA_define.h
@@ -43,12 +43,14 @@ BlenderRNA *RNA_create(void);
void RNA_define_free(BlenderRNA *brna);
void RNA_free(BlenderRNA *brna);
void RNA_define_verify_sdna(int verify);
+void RNA_define_animate_sdna(int animate);
void RNA_init(void);
void RNA_exit(void);
/* Struct */
+StructRNA *RNA_def_struct_ptr(BlenderRNA *brna, const char *identifier, StructRNA *srnafrom);
StructRNA *RNA_def_struct(BlenderRNA *brna, const char *identifier, const char *from);
void RNA_def_struct_sdna(StructRNA *srna, const char *structname);
void RNA_def_struct_sdna_from(StructRNA *srna, const char *structname, const char *propname);
@@ -86,12 +88,10 @@ PropertyRNA *RNA_def_string(StructOrFunctionRNA *cont, const char *identifier, c
PropertyRNA *RNA_def_string_file_path(StructOrFunctionRNA *cont, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description);
PropertyRNA *RNA_def_string_dir_path(StructOrFunctionRNA *cont, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description);
PropertyRNA *RNA_def_string_file_name(StructOrFunctionRNA *cont, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description);
-PropertyRNA *RNA_def_string_translate(StructOrFunctionRNA *cont, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description);
PropertyRNA *RNA_def_enum(StructOrFunctionRNA *cont, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description);
PropertyRNA *RNA_def_enum_flag(StructOrFunctionRNA *cont, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description);
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc);
-void RNA_def_enum_py_data(PropertyRNA *prop, void *py_data);
PropertyRNA *RNA_def_float(StructOrFunctionRNA *cont, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax);
PropertyRNA *RNA_def_float_vector(StructOrFunctionRNA *cont, const char *identifier, int len, const float *default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax);
@@ -177,6 +177,17 @@ void RNA_def_property_collection_funcs(PropertyRNA *prop, const char *begin, con
void RNA_def_property_srna(PropertyRNA *prop, const char *type);
void RNA_def_py_data(PropertyRNA *prop, void *py_data);
+void RNA_def_property_boolean_funcs_runtime(PropertyRNA *prop, BooleanPropertyGetFunc getfunc, BooleanPropertySetFunc setfunc);
+void RNA_def_property_boolean_array_funcs_runtime(PropertyRNA *prop, BooleanArrayPropertyGetFunc getfunc, BooleanArrayPropertySetFunc setfunc);
+void RNA_def_property_int_funcs_runtime(PropertyRNA *prop, IntPropertyGetFunc getfunc, IntPropertySetFunc setfunc, IntPropertyRangeFunc rangefunc);
+void RNA_def_property_int_array_funcs_runtime(PropertyRNA *prop, IntArrayPropertyGetFunc getfunc, IntArrayPropertySetFunc setfunc, IntPropertyRangeFunc rangefunc);
+void RNA_def_property_float_funcs_runtime(PropertyRNA *prop, FloatPropertyGetFunc getfunc, FloatPropertySetFunc setfunc, FloatPropertyRangeFunc rangefunc);
+void RNA_def_property_float_array_funcs_runtime(PropertyRNA *prop, FloatArrayPropertyGetFunc getfunc, FloatArrayPropertySetFunc setfunc, FloatPropertyRangeFunc rangefunc);
+void RNA_def_property_enum_funcs_runtime(PropertyRNA *prop, EnumPropertyGetFunc getfunc, EnumPropertySetFunc setfunc, EnumPropertyItemFunc itemfunc);
+void RNA_def_property_string_funcs_runtime(PropertyRNA *prop, StringPropertyGetFunc getfunc, StringPropertyLengthFunc lengthfunc, StringPropertySetFunc setfunc);
+
+void RNA_def_property_enum_py_data(PropertyRNA *prop, void *py_data);
+
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context);
/* Function */
@@ -212,6 +223,8 @@ const char *RNA_property_typename(PropertyType type);
#define IS_DNATYPE_FLOAT_COMPAT(_str) (strcmp(_str, "float") == 0 || strcmp(_str, "double") == 0)
#define IS_DNATYPE_INT_COMPAT(_str) (strcmp(_str, "int") == 0 || strcmp(_str, "short") == 0 || strcmp(_str, "char") == 0)
+void RNA_identifier_sanitize(char *identifier, int property);
+
/* max size for dynamic defined type descriptors,
* this value is arbitrary */
#define RNA_DYN_DESCR_MAX 240
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 0f9a00de7b6..e6ee1b7c382 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -29,6 +29,10 @@
#include "RNA_types.h"
+struct bNodeTreeType;
+struct bNodeType;
+struct bNodeSocketType;
+
/* Types */
extern EnumPropertyItem id_type_items[];
@@ -70,6 +74,7 @@ extern EnumPropertyItem keyframe_handle_type_items[];
extern EnumPropertyItem keyblock_type_items[];
extern EnumPropertyItem keyingset_path_grouping_items[];
+extern EnumPropertyItem keying_flag_items[];
extern EnumPropertyItem keyframe_paste_offset_items[];
extern EnumPropertyItem keyframe_paste_merge_items[];
@@ -89,6 +94,8 @@ extern EnumPropertyItem brush_sculpt_tool_items[];
extern EnumPropertyItem brush_vertex_tool_items[];
extern EnumPropertyItem brush_image_tool_items[];
+extern EnumPropertyItem symmetrize_direction_items[];
+
extern EnumPropertyItem texture_type_items[];
extern EnumPropertyItem lamp_type_items[];
@@ -99,6 +106,12 @@ extern EnumPropertyItem object_type_items[];
extern EnumPropertyItem object_type_curve_items[];
+extern EnumPropertyItem rigidbody_ob_type_items[];
+extern EnumPropertyItem rigidbody_ob_shape_items[];
+extern EnumPropertyItem rigidbody_con_type_items[];
+
+extern EnumPropertyItem object_axis_items[];
+
extern EnumPropertyItem controller_type_items[];
extern EnumPropertyItem keymap_propvalue_items[];
@@ -119,8 +132,23 @@ extern EnumPropertyItem gameproperty_type_items[];
extern EnumPropertyItem viewport_shade_items[];
-extern EnumPropertyItem nodetree_type_items[];
-extern EnumPropertyItem node_socket_type_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);
+EnumPropertyItem *rna_node_tree_type_itemf(void *data, int (*poll)(void *data, struct bNodeTreeType *), int *free);
+
+int rna_node_type_to_enum(struct bNodeType *typeinfo);
+int rna_node_idname_to_enum(const char *idname);
+struct bNodeType *rna_node_type_from_enum(int value);
+EnumPropertyItem *rna_node_type_itemf(void *data, int (*poll)(void *data, struct bNodeType *), int *free);
+
+int rna_node_socket_type_to_enum(struct bNodeSocketType *typeinfo);
+int rna_node_socket_idname_to_enum(const char *idname);
+struct bNodeSocketType *rna_node_socket_type_from_enum(int value);
+EnumPropertyItem *rna_node_socket_type_itemf(void *data, int (*poll)(void *data, struct bNodeSocketType *), int *free);
+
+extern EnumPropertyItem node_socket_in_out_items[];
+extern EnumPropertyItem node_icon_items[];
extern EnumPropertyItem node_math_items[];
extern EnumPropertyItem node_vec_math_items[];
@@ -132,6 +160,14 @@ extern EnumPropertyItem prop_dynamicpaint_type_items[];
extern EnumPropertyItem clip_editor_mode_items[];
+extern EnumPropertyItem icon_items[];
+extern EnumPropertyItem uilist_layout_type_items[];
+
+extern EnumPropertyItem linestyle_color_modifier_type_items[];
+extern EnumPropertyItem linestyle_alpha_modifier_type_items[];
+extern EnumPropertyItem linestyle_thickness_modifier_type_items[];
+extern EnumPropertyItem linestyle_geometry_modifier_type_items[];
+
struct bContext;
struct PointerRNA;
struct PropertyRNA;
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index 87504dc6eb7..b69c95d0363 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -88,7 +88,8 @@ typedef enum PropertyUnit {
PROP_UNIT_ROTATION = (5 << 16), /* radians */
PROP_UNIT_TIME = (6 << 16), /* frame */
PROP_UNIT_VELOCITY = (7 << 16), /* m/s */
- PROP_UNIT_ACCELERATION = (8 << 16) /* m/(s^2) */
+ PROP_UNIT_ACCELERATION = (8 << 16), /* m/(s^2) */
+ PROP_UNIT_CAMERA = (9 << 16) /* mm */
} PropertyUnit;
#define RNA_SUBTYPE_UNIT(subtype) ((subtype) & 0x00FF0000)
@@ -110,10 +111,9 @@ typedef enum PropertySubType {
PROP_FILEPATH = 1,
PROP_DIRPATH = 2,
PROP_FILENAME = 3,
- PROP_BYTESTRING = 4, /* a string which should be represented as bytes
- * in python, still NULL terminated though. */
- PROP_TRANSLATE = 5, /* a string which should be translated */
- PROP_PASSWORD = 6, /* a string which should not be displayed in UI */
+ PROP_BYTESTRING = 4, /* a string which should be represented as bytes in python, still NULL terminated though. */
+ /* 5 was used by "PROP_TRANSLATE" sub-type, which is now a flag. */
+ PROP_PASSWORD = 6, /* a string which should not be displayed in UI */
/* numbers */
PROP_UNSIGNED = 13,
@@ -121,7 +121,9 @@ typedef enum PropertySubType {
PROP_FACTOR = 15,
PROP_ANGLE = 16 | PROP_UNIT_ROTATION,
PROP_TIME = 17 | PROP_UNIT_TIME,
+ /* distance in 3d space, don't use for pixel distance for eg. */
PROP_DISTANCE = 18 | PROP_UNIT_LENGTH,
+ PROP_DISTANCE_CAMERA = 19 | PROP_UNIT_CAMERA,
/* number arrays */
PROP_COLOR = 20,
@@ -135,7 +137,7 @@ typedef enum PropertySubType {
PROP_AXISANGLE = 28,
PROP_XYZ = 29,
PROP_XYZ_LENGTH = 29 | PROP_UNIT_LENGTH,
- PROP_COLOR_GAMMA = 30,
+ PROP_COLOR_GAMMA = 30, /* used for colors which would be color managed before display */
PROP_COORDS = 31, /* generic array, no units applied, only that x/y/z/w are used (python vec) */
/* booleans */
@@ -144,6 +146,7 @@ typedef enum PropertySubType {
} PropertySubType;
/* Make sure enums are updated with thses */
+/* HIGHEST FLAG IN USE: 1 << 28 */
typedef enum PropertyFlag {
/* editable means the property is editable in the user
* interface, properties are editable by default except
@@ -269,7 +272,27 @@ typedef struct EnumPropertyItem {
const char *description;
} EnumPropertyItem;
-/* this is a copy of 'PropEnumItemFunc' defined in rna_internal_types.h */
+/* extended versions with PropertyRNA argument */
+typedef int (*BooleanPropertyGetFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop);
+typedef void (*BooleanPropertySetFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop, int value);
+typedef void (*BooleanArrayPropertyGetFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop, int *values);
+typedef void (*BooleanArrayPropertySetFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop, const int *values);
+typedef int (*IntPropertyGetFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop);
+typedef void (*IntPropertySetFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop, int value);
+typedef void (*IntArrayPropertyGetFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop, int *values);
+typedef void (*IntArrayPropertySetFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop, const int *values);
+typedef void (*IntPropertyRangeFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop, int *min, int *max, int *softmin, int *softmax);
+typedef float (*FloatPropertyGetFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop);
+typedef void (*FloatPropertySetFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop, float value);
+typedef void (*FloatArrayPropertyGetFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop, float *values);
+typedef void (*FloatArrayPropertySetFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop, const float *values);
+typedef void (*FloatPropertyRangeFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop, float *min, float *max, float *softmin, float *softmax);
+typedef void (*StringPropertyGetFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop, char *value);
+typedef int (*StringPropertyLengthFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop);
+typedef void (*StringPropertySetFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop, const char *value);
+typedef int (*EnumPropertyGetFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop);
+typedef void (*EnumPropertySetFunc)(struct PointerRNA *ptr, struct PropertyRNA *prop, int value);
+/* same as PropEnumItemFunc */
typedef EnumPropertyItem *(*EnumPropertyItemFunc)(struct bContext *C, PointerRNA *ptr, struct PropertyRNA *prop, int *free);
typedef struct PropertyRNA PropertyRNA;
@@ -309,15 +332,16 @@ typedef struct ParameterDynAlloc {
typedef enum FunctionFlag {
FUNC_NO_SELF = 1, /* for static functions */
- FUNC_USE_MAIN = 2,
- FUNC_USE_CONTEXT = 4,
- FUNC_USE_REPORTS = 8,
+ FUNC_USE_SELF_TYPE = 2, /* for class methods, only used when FUNC_NO_SELF is set */
+ FUNC_USE_MAIN = 4,
+ FUNC_USE_CONTEXT = 8,
+ FUNC_USE_REPORTS = 16,
FUNC_USE_SELF_ID = 2048,
FUNC_ALLOW_WRITE = 4096,
/* registering */
- FUNC_REGISTER = 16,
- FUNC_REGISTER_OPTIONAL = 16 | 32,
+ FUNC_REGISTER = 32,
+ FUNC_REGISTER_OPTIONAL = 32 | 64,
/* internal flags */
FUNC_BUILTIN = 128,
diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript
index 29910121e2a..3b6745de470 100644
--- a/source/blender/makesrna/SConscript
+++ b/source/blender/makesrna/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
objs = []
@@ -20,6 +46,10 @@ defs = []
if env['WITH_BF_SMOKE']:
defs.append('WITH_SMOKE')
+if env['WITH_BF_BULLET']:
+ defs.append('WITH_BULLET')
+ incs += ' #/intern/rigidbody'
+
if env['WITH_BF_OPENEXR']:
defs.append('WITH_OPENEXR')
@@ -77,6 +107,10 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', '
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
+if env['WITH_BF_FREESTYLE']:
+ incs += ' ../freestyle'
+ defs.append('WITH_FREESTYLE')
+
rnalib = env.BlenderLib ( 'bf_rna', objs, Split(incs), defines=defs, libtype=['core','player'], priority = [165,20] )
Return ('rnalib')
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 82c0757456d..609592cc1cd 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -54,6 +54,7 @@ set(DEFSRC
rna_key.c
rna_lamp.c
rna_lattice.c
+ rna_linestyle.c
rna_main.c
rna_mask.c
rna_material.c
@@ -70,6 +71,7 @@ set(DEFSRC
rna_pose.c
rna_property.c
rna_render.c
+ rna_rigidbody.c
rna_rna.c
rna_scene.c
rna_screen.c
@@ -104,6 +106,7 @@ set(APISRC
rna_main_api.c
rna_material_api.c
rna_mesh_api.c
+ rna_meta_api.c
rna_texture_api.c
rna_object_api.c
rna_pose_api.c
@@ -237,6 +240,13 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
+if(WITH_BULLET)
+ list(APPEND INC
+ ../../../../intern/rigidbody
+ )
+ add_definitions(-DWITH_BULLET)
+endif()
+
# Build makesrna executable
blender_include_dirs(
.
@@ -250,6 +260,7 @@ blender_include_dirs(
../../imbuf
../../ikplugin
../../makesdna
+ ../../nodes/
../../windowmanager
../../editors/include
../../render/extern/include
@@ -260,6 +271,11 @@ blender_include_dirs(
../../../../intern/smoke/extern
)
+if(WITH_FREESTYLE)
+ # TO BE REMOVED when the trunk merger is done
+ add_definitions(-DWITH_FREESTYLE)
+endif()
+
blender_include_dirs_sys(
${GLEW_INCLUDE_PATH}
)
@@ -268,6 +284,9 @@ 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(
@@ -284,7 +303,6 @@ set(SRC
${SRC_RNA_INC}
rna_internal.h
rna_internal_types.h
- rna_nodetree_types.h
rna_mesh_utils.h
)
diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript
index d26de50fae0..910cf8385f5 100644
--- a/source/blender/makesrna/intern/SConscript
+++ b/source/blender/makesrna/intern/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
import sys
import os
@@ -12,6 +38,8 @@ root_build_dir=normpath(env['BF_BUILDDIR'])
source_files = env.Glob('*.c')
source_files.remove('rna_access.c')
+if not env['WITH_BF_FREESTYLE']:
+ source_files.remove('rna_linestyle.c')
generated_files = source_files[:]
generated_files.remove('rna_define.c')
@@ -39,7 +67,11 @@ incs += ' #/intern/smoke/extern'
if env['WITH_BF_SMOKE']:
defs.append('WITH_SMOKE')
-
+
+if env['WITH_BF_BULLET']:
+ defs.append('WITH_BULLET')
+ incs += ' #/intern/rigidbody'
+
if env['WITH_BF_OPENEXR']:
defs.append('WITH_OPENEXR')
@@ -106,6 +138,10 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', '
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
+if env['WITH_BF_FREESTYLE']:
+ # TO BE REMOVED when the trunk merger is done
+ defs.append('WITH_FREESTYLE')
+
if not env['BF_DEBUG']:
defs.append('NDEBUG')
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 6fa53f4e029..6fc4ab33ad1 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -24,7 +24,6 @@
* \ingroup RNA
*/
-
#include <float.h>
#include <limits.h>
#include <stdio.h>
@@ -34,6 +33,8 @@
#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_types.h"
@@ -91,7 +92,7 @@ static void rna_generate_static_parameter_prototypes(FILE *f, StructRNA *srna, F
{ \
WRITE_COMMA; \
fprintf(f, param); \
- }
+ } (void)0
static int replace_if_different(char *tmpfile, const char *dep_files[])
{
@@ -415,10 +416,10 @@ static const char *rna_type_type_name(PropertyRNA *prop)
return "float";
case PROP_STRING:
if (prop->flag & PROP_THICK_WRAP) {
- return "char*";
+ return "char *";
}
else {
- return "const char*";
+ return "const char *";
}
default:
return NULL;
@@ -760,7 +761,7 @@ static void rna_clamp_value(FILE *f, PropertyRNA *prop, int array)
if (prop->type == PROP_INT) {
IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
- if (iprop->hardmin != INT_MIN || iprop->hardmax != INT_MAX) {
+ if (iprop->hardmin != INT_MIN || iprop->hardmax != INT_MAX || iprop->range) {
if (array) fprintf(f, "CLAMPIS(values[i], ");
else fprintf(f, "CLAMPIS(value, ");
if (iprop->range) {
@@ -776,7 +777,7 @@ static void rna_clamp_value(FILE *f, PropertyRNA *prop, int array)
else if (prop->type == PROP_FLOAT) {
FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
- if (fprop->hardmin != -FLT_MAX || fprop->hardmax != FLT_MAX) {
+ if (fprop->hardmin != -FLT_MAX || fprop->hardmax != FLT_MAX || fprop->range) {
if (array) fprintf(f, "CLAMPIS(values[i], ");
else fprintf(f, "CLAMPIS(value, ");
if (fprop->range) {
@@ -870,16 +871,16 @@ static char *rna_def_property_set_func(FILE *f, StructRNA *srna, PropertyRNA *pr
if (prop->flag & PROP_ID_REFCOUNT) {
fprintf(f, "\n if (data->%s)\n", dp->dnaname);
- fprintf(f, " id_us_min((ID*)data->%s);\n", dp->dnaname);
+ fprintf(f, " id_us_min((ID *)data->%s);\n", dp->dnaname);
fprintf(f, " if (value.data)\n");
- fprintf(f, " id_us_plus((ID*)value.data);\n\n");
+ fprintf(f, " id_us_plus((ID *)value.data);\n\n");
}
else {
PointerPropertyRNA *pprop = (PointerPropertyRNA *)dp->prop;
StructRNA *type = rna_find_struct((const char *)pprop->type);
if (type && (type->flag & STRUCT_ID)) {
fprintf(f, " if (value.data)\n");
- fprintf(f, " id_lib_extern((ID*)value.data);\n\n");
+ fprintf(f, " id_lib_extern((ID *)value.data);\n\n");
}
}
@@ -1084,7 +1085,7 @@ static char *rna_def_property_begin_func(FILE *f, StructRNA *srna, PropertyRNA *
fprintf(f, "\n memset(iter, 0, sizeof(*iter));\n");
fprintf(f, " iter->parent= *ptr;\n");
- fprintf(f, " iter->prop= (PropertyRNA*)&rna_%s_%s;\n", srna->identifier, prop->identifier);
+ fprintf(f, " iter->prop= (PropertyRNA *)&rna_%s_%s;\n", srna->identifier, prop->identifier);
if (dp->dnalengthname || dp->dnalengthfixed) {
if (manualfunc) {
@@ -1768,7 +1769,7 @@ static void rna_def_property_funcs_header_cpp(FILE *f, StructRNA *srna, Property
const char *collection_funcs = "DefaultCollectionFunctions";
if (!(dp->prop->flag & (PROP_IDPROPERTY | PROP_BUILTIN)) && cprop->property.srna)
- collection_funcs = (char*)cprop->property.srna;
+ collection_funcs = (char *)cprop->property.srna;
if (cprop->item_type)
fprintf(f, "\tCOLLECTION_PROPERTY(%s, %s, %s, %s, %s, %s, %s)", collection_funcs, (const char *)cprop->item_type, srna->identifier,
@@ -1798,7 +1799,7 @@ static const char *rna_parameter_type_cpp_name(PropertyRNA *prop)
}
}
-static void rna_def_struct_function_prototype_cpp(FILE *f, StructRNA *srna, FunctionDefRNA *dfunc,
+static void rna_def_struct_function_prototype_cpp(FILE *f, StructRNA *UNUSED(srna), FunctionDefRNA *dfunc,
const char *namespace, int close_prototype)
{
PropertyDefRNA *dp;
@@ -1989,6 +1990,10 @@ static void rna_def_struct_function_call_impl_cpp(FILE *f, StructRNA *srna, Func
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) {
+ WRITE_COMMA;
+ fprintf(f, "this->ptr.type");
+ }
if (func->flag & FUNC_USE_MAIN)
WRITE_PARAM("(::Main *) main");
@@ -2112,8 +2117,12 @@ static void rna_def_function_wrapper_funcs(FILE *f, StructDefRNA *dsrna, Functio
if (func->flag & FUNC_USE_SELF_ID)
WRITE_PARAM("_selfid");
- if ((func->flag & FUNC_NO_SELF) == 0)
+ if ((func->flag & FUNC_NO_SELF) == 0) {
WRITE_PARAM("_self");
+ }
+ else if (func->flag & FUNC_USE_SELF_TYPE) {
+ WRITE_PARAM("_type");
+ }
if (func->flag & FUNC_USE_MAIN)
WRITE_PARAM("bmain");
@@ -2174,6 +2183,9 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
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) {
+ fprintf(f, "\tstruct StructRNA *_type;\n");
+ }
dparm = dfunc->cont.properties.first;
for (; dparm; dparm = dparm->next) {
@@ -2223,6 +2235,9 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
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) {
+ fprintf(f, "\t_type= _ptr->type;\n");
+ }
if (has_data) {
fprintf(f, "\t_data= (char *)_parms->data;\n");
@@ -2300,6 +2315,11 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
fprintf(f, "_self");
first = 0;
}
+ else if (func->flag & FUNC_USE_SELF_TYPE) {
+ if (!first) fprintf(f, ", ");
+ fprintf(f, "_type");
+ first = 0;
+ }
if (func->flag & FUNC_USE_MAIN) {
if (!first) fprintf(f, ", ");
@@ -2425,13 +2445,13 @@ static const char *rna_property_subtypename(PropertySubType type)
case PROP_FILENAME: return "PROP_FILENAME";
case PROP_DIRPATH: return "PROP_DIRPATH";
case PROP_BYTESTRING: return "PROP_BYTESTRING";
- case PROP_TRANSLATE: return "PROP_TRANSLATE";
case PROP_UNSIGNED: return "PROP_UNSIGNED";
case PROP_PERCENTAGE: return "PROP_PERCENTAGE";
case PROP_FACTOR: return "PROP_FACTOR";
case PROP_ANGLE: return "PROP_ANGLE";
case PROP_TIME: return "PROP_TIME";
case PROP_DISTANCE: return "PROP_DISTANCE";
+ case PROP_DISTANCE_CAMERA: return "PROP_DISTANCE_CAMERA";
case PROP_COLOR: return "PROP_COLOR";
case PROP_TRANSLATION: return "PROP_TRANSLATION";
case PROP_DIRECTION: return "PROP_DIRECTION";
@@ -2447,7 +2467,8 @@ static const char *rna_property_subtypename(PropertySubType type)
case PROP_LAYER: return "PROP_LAYER";
case PROP_LAYER_MEMBER: return "PROP_LAYER_MEMBER";
case PROP_PASSWORD: return "PROP_PASSWORD";
- default: {
+ default:
+ {
/* in case we don't have a type preset that includes the subtype */
if (RNA_SUBTYPE_UNIT(type)) {
return rna_property_subtypename(type & ~RNA_SUBTYPE_UNIT(type));
@@ -2471,6 +2492,7 @@ static const char *rna_property_subtype_unit(PropertySubType type)
case PROP_UNIT_TIME: return "PROP_UNIT_TIME";
case PROP_UNIT_VELOCITY: return "PROP_UNIT_VELOCITY";
case PROP_UNIT_ACCELERATION: return "PROP_UNIT_ACCELERATION";
+ case PROP_UNIT_CAMERA: return "PROP_UNIT_CAMERA";
default: return "PROP_UNIT_UNKNOWN";
}
}
@@ -2613,6 +2635,11 @@ static void rna_generate_static_parameter_prototypes(FILE *f, StructRNA *srna, F
else fprintf(f, "struct %s *_self", srna->identifier);
first = 0;
}
+ else if (func->flag & FUNC_USE_SELF_TYPE) {
+ if (!first) fprintf(f, ", ");
+ fprintf(f, "struct StructRNA *_type");
+ first = 0;
+ }
if (func->flag & FUNC_USE_MAIN) {
if (!first) fprintf(f, ", ");
@@ -2882,9 +2909,9 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
rna_property_structname(prop->type),
srna->identifier, strnest, prop->identifier);
- if (prop->next) fprintf(f, "\t{(PropertyRNA*)&rna_%s%s_%s, ", srna->identifier, strnest, prop->next->identifier);
+ if (prop->next) fprintf(f, "\t{(PropertyRNA *)&rna_%s%s_%s, ", srna->identifier, strnest, prop->next->identifier);
else fprintf(f, "\t{NULL, ");
- if (prop->prev) fprintf(f, "(PropertyRNA*)&rna_%s%s_%s,\n", srna->identifier, strnest, prop->prev->identifier);
+ if (prop->prev) fprintf(f, "(PropertyRNA *)&rna_%s%s_%s,\n", srna->identifier, strnest, prop->prev->identifier);
else fprintf(f, "NULL,\n");
fprintf(f, "\t%d, ", prop->magic);
rna_print_c_string(f, prop->identifier);
@@ -2923,11 +2950,15 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
case PROP_BOOLEAN:
{
BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
- fprintf(f, "\t%s, %s, %s, %s, %d, ",
+ fprintf(f, "\t%s, %s, %s, %s, %s, %s, %s, %s, %d, ",
rna_function_string(bprop->get),
rna_function_string(bprop->set),
rna_function_string(bprop->getarray),
rna_function_string(bprop->setarray),
+ rna_function_string(bprop->get_ex),
+ rna_function_string(bprop->set_ex),
+ rna_function_string(bprop->getarray_ex),
+ rna_function_string(bprop->setarray_ex),
bprop->defaultvalue);
if (prop->arraydimension && prop->totarraylength)
fprintf(f, "rna_%s%s_%s_default\n", srna->identifier, strnest, prop->identifier);
@@ -2937,12 +2968,17 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
case PROP_INT:
{
IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
- fprintf(f, "\t%s, %s, %s, %s, %s,\n\t",
+ fprintf(f, "\t%s, %s, %s, %s, %s, %s, %s, %s, %s, %s,\n\t",
rna_function_string(iprop->get),
rna_function_string(iprop->set),
rna_function_string(iprop->getarray),
rna_function_string(iprop->setarray),
- rna_function_string(iprop->range));
+ rna_function_string(iprop->range),
+ rna_function_string(iprop->get_ex),
+ rna_function_string(iprop->set_ex),
+ rna_function_string(iprop->getarray_ex),
+ rna_function_string(iprop->setarray_ex),
+ rna_function_string(iprop->range_ex));
rna_int_print(f, iprop->softmin); fprintf(f, ", ");
rna_int_print(f, iprop->softmax); fprintf(f, ", ");
rna_int_print(f, iprop->hardmin); fprintf(f, ", ");
@@ -2957,12 +2993,17 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
case PROP_FLOAT:
{
FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
- fprintf(f, "\t%s, %s, %s, %s, %s, ",
+ fprintf(f, "\t%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, ",
rna_function_string(fprop->get),
rna_function_string(fprop->set),
rna_function_string(fprop->getarray),
rna_function_string(fprop->setarray),
- rna_function_string(fprop->range));
+ rna_function_string(fprop->range),
+ rna_function_string(fprop->get_ex),
+ rna_function_string(fprop->set_ex),
+ rna_function_string(fprop->getarray_ex),
+ rna_function_string(fprop->setarray_ex),
+ rna_function_string(fprop->range_ex));
rna_float_print(f, fprop->softmin); fprintf(f, ", ");
rna_float_print(f, fprop->softmax); fprintf(f, ", ");
rna_float_print(f, fprop->hardmin); fprintf(f, ", ");
@@ -2978,10 +3019,13 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
case PROP_STRING:
{
StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
- fprintf(f, "\t%s, %s, %s, %d, ",
+ fprintf(f, "\t%s, %s, %s, %s, %s, %s, %d, ",
rna_function_string(sprop->get),
rna_function_string(sprop->length),
rna_function_string(sprop->set),
+ rna_function_string(sprop->get_ex),
+ rna_function_string(sprop->length_ex),
+ rna_function_string(sprop->set_ex),
sprop->maxlength);
rna_print_c_string(f, sprop->defaultvalue); fprintf(f, "\n");
break;
@@ -2989,10 +3033,12 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
case PROP_ENUM:
{
EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
- fprintf(f, "\t%s, %s, %s, NULL, ",
+ fprintf(f, "\t%s, %s, %s, %s, %s, NULL, ",
rna_function_string(eprop->get),
rna_function_string(eprop->set),
- rna_function_string(eprop->itemf));
+ rna_function_string(eprop->itemf),
+ rna_function_string(eprop->get_ex),
+ rna_function_string(eprop->set_ex));
if (eprop->item)
fprintf(f, "rna_%s%s_%s_items, ", srna->identifier, strnest, prop->identifier);
else
@@ -3056,12 +3102,12 @@ static void rna_generate_struct(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE
fprintf(f, "%s%s rna_%s_%s_func = {\n", "", "FunctionRNA", srna->identifier, func->identifier);
if (func->cont.next)
- fprintf(f, "\t{(FunctionRNA*)&rna_%s_%s_func, ", srna->identifier,
+ fprintf(f, "\t{(FunctionRNA *)&rna_%s_%s_func, ", srna->identifier,
((FunctionRNA *)func->cont.next)->identifier);
else
fprintf(f, "\t{NULL, ");
if (func->cont.prev)
- fprintf(f, "(FunctionRNA*)&rna_%s_%s_func,\n", srna->identifier,
+ fprintf(f, "(FunctionRNA *)&rna_%s_%s_func,\n", srna->identifier,
((FunctionRNA *)func->cont.prev)->identifier);
else
fprintf(f, "NULL,\n");
@@ -3069,11 +3115,11 @@ static void rna_generate_struct(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE
fprintf(f, "\tNULL,\n");
parm = func->cont.properties.first;
- if (parm) fprintf(f, "\t{(PropertyRNA*)&rna_%s_%s_%s, ", srna->identifier, func->identifier, parm->identifier);
+ if (parm) fprintf(f, "\t{(PropertyRNA *)&rna_%s_%s_%s, ", srna->identifier, func->identifier, parm->identifier);
else fprintf(f, "\t{NULL, ");
parm = func->cont.properties.last;
- if (parm) fprintf(f, "(PropertyRNA*)&rna_%s_%s_%s}},\n", srna->identifier, func->identifier, parm->identifier);
+ if (parm) fprintf(f, "(PropertyRNA *)&rna_%s_%s_%s}},\n", srna->identifier, func->identifier, parm->identifier);
else fprintf(f, "NULL}},\n");
fprintf(f, "\t");
@@ -3086,7 +3132,7 @@ static void rna_generate_struct(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE
else fprintf(f, "\tNULL,\n");
if (func->c_ret)
- fprintf(f, "\t(PropertyRNA*)&rna_%s_%s_%s\n", srna->identifier, func->identifier, func->c_ret->identifier);
+ fprintf(f, "\t(PropertyRNA *)&rna_%s_%s_%s\n", srna->identifier, func->identifier, func->c_ret->identifier);
else
fprintf(f, "\tNULL\n");
@@ -3104,11 +3150,11 @@ static void rna_generate_struct(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE
fprintf(f, "\tNULL,\n");
prop = srna->cont.properties.first;
- if (prop) fprintf(f, "\t{(PropertyRNA*)&rna_%s_%s, ", srna->identifier, prop->identifier);
+ if (prop) fprintf(f, "\t{(PropertyRNA *)&rna_%s_%s, ", srna->identifier, prop->identifier);
else fprintf(f, "\t{NULL, ");
prop = srna->cont.properties.last;
- if (prop) fprintf(f, "(PropertyRNA*)&rna_%s_%s}},\n", srna->identifier, prop->identifier);
+ if (prop) fprintf(f, "(PropertyRNA *)&rna_%s_%s}},\n", srna->identifier, prop->identifier);
else fprintf(f, "NULL}},\n");
fprintf(f, "\t");
rna_print_c_string(f, srna->identifier);
@@ -3127,15 +3173,17 @@ static void rna_generate_struct(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE
while (base->base && base->base->nameproperty == prop)
base = base->base;
- fprintf(f, "\t(PropertyRNA*)&rna_%s_%s, ", base->identifier, prop->identifier);
+ fprintf(f, "\t(PropertyRNA *)&rna_%s_%s, ", base->identifier, prop->identifier);
+ }
+ else {
+ fprintf(f, "\tNULL, ");
}
- else fprintf(f, "\tNULL, ");
prop = srna->iteratorproperty;
base = srna;
while (base->base && base->base->iteratorproperty == prop)
base = base->base;
- fprintf(f, "(PropertyRNA*)&rna_%s_rna_properties,\n", base->identifier);
+ fprintf(f, "(PropertyRNA *)&rna_%s_rna_properties,\n", base->identifier);
if (srna->base) fprintf(f, "\t&RNA_%s,\n", srna->base->identifier);
else fprintf(f, "\tNULL,\n");
@@ -3157,11 +3205,11 @@ static void rna_generate_struct(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE
}
func = srna->functions.first;
- if (func) fprintf(f, "\t{(FunctionRNA*)&rna_%s_%s_func, ", srna->identifier, func->identifier);
+ if (func) fprintf(f, "\t{(FunctionRNA *)&rna_%s_%s_func, ", srna->identifier, func->identifier);
else fprintf(f, "\t{NULL, ");
func = srna->functions.last;
- if (func) fprintf(f, "(FunctionRNA*)&rna_%s_%s_func}\n", srna->identifier, func->identifier);
+ if (func) fprintf(f, "(FunctionRNA *)&rna_%s_%s_func}\n", srna->identifier, func->identifier);
else fprintf(f, "NULL}\n");
fprintf(f, "};\n");
@@ -3202,10 +3250,11 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_key.c", NULL, RNA_def_key},
{"rna_lamp.c", NULL, RNA_def_lamp},
{"rna_lattice.c", NULL, RNA_def_lattice},
+ {"rna_linestyle.c", NULL, RNA_def_linestyle},
{"rna_main.c", "rna_main_api.c", RNA_def_main},
{"rna_material.c", "rna_material_api.c", RNA_def_material},
{"rna_mesh.c", "rna_mesh_api.c", RNA_def_mesh},
- {"rna_meta.c", NULL, RNA_def_meta},
+ {"rna_meta.c", "rna_meta_api.c", RNA_def_meta},
{"rna_modifier.c", NULL, RNA_def_modifier},
{"rna_nla.c", NULL, RNA_def_nla},
{"rna_nodetree.c", NULL, RNA_def_nodetree},
@@ -3216,6 +3265,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_pose.c", "rna_pose_api.c", RNA_def_pose},
{"rna_property.c", NULL, RNA_def_gameproperty},
{"rna_render.c", NULL, RNA_def_render},
+ {"rna_rigidbody.c", NULL, RNA_def_rigidbody},
{"rna_scene.c", "rna_scene_api.c", RNA_def_scene},
{"rna_screen.c", NULL, RNA_def_screen},
{"rna_sculpt_paint.c", NULL, RNA_def_sculpt_paint},
@@ -3383,7 +3433,7 @@ static const char *cpp_classes = ""
"namespace BL {\n"
"\n"
"#define BOOLEAN_PROPERTY(sname, identifier) \\\n"
-" inline bool sname::identifier(void) { return sname##_##identifier##_get(&ptr)? true: false; } \\\n"
+" inline bool sname::identifier(void) { return sname##_##identifier##_get(&ptr) ? true: false; } \\\n"
" inline void sname::identifier(int value) { sname##_##identifier##_set(&ptr, value); }\n"
"\n"
"#define BOOLEAN_ARRAY_PROPERTY(sname, size, identifier) \\\n"
@@ -3501,8 +3551,27 @@ static const char *cpp_classes = ""
"#define COLLECTION_PROPERTY_LOOKUP_STRING_FALSE(sname, identifier) \\\n"
" inline static int sname##_##identifier##_lookup_string_wrap(PointerRNA *ptr, const char *key, PointerRNA *r_ptr) \\\n"
" { \\\n"
-" memset(r_ptr, 0, sizeof(*r_ptr)); \\\n"
-" return 0; \\\n"
+" CollectionPropertyIterator iter; \\\n"
+" int found = 0; \\\n"
+" PropertyRNA *item_name_prop = RNA_struct_name_property(ptr->type); \\\n"
+" sname##_##identifier##_begin(&iter, ptr); \\\n"
+" while (iter.valid && !found) { \\\n"
+" char name_fixed[32]; \\\n"
+" const char *name; \\\n"
+" int name_length; \\\n"
+" name = RNA_property_string_get_alloc(&iter.ptr, item_name_prop, name_fixed, sizeof(name_fixed), &name_length); \\\n"
+" if (!strncmp(name, key, name_length)) { \\\n"
+" *r_ptr = iter.ptr; \\\n"
+" found = 1; \\\n"
+" } \\\n"
+" if (name_fixed != name) \\\n"
+" MEM_freeN((void *) name); \\\n"
+" sname##_##identifier##_next(&iter); \\\n"
+" } \\\n"
+" sname##_##identifier##_end(&iter); \\\n"
+" if (!found) \\\n"
+" memset(r_ptr, 0, sizeof(*r_ptr)); \\\n"
+" return found; \\\n"
" } \n"
"#define COLLECTION_PROPERTY_LOOKUP_STRING_TRUE(sname, identifier) \\\n"
" inline static int sname##_##identifier##_lookup_string_wrap(PointerRNA *ptr, const char *key, PointerRNA *r_ptr) \\\n"
@@ -3523,7 +3592,7 @@ static const char *cpp_classes = ""
"public:\n"
" Pointer(const PointerRNA &p) : ptr(p) { }\n"
" operator const PointerRNA&() { return ptr; }\n"
-" bool is_a(StructRNA *type) { return RNA_struct_is_a(ptr.type, type)? true: false; }\n"
+" bool is_a(StructRNA *type) { return RNA_struct_is_a(ptr.type, type) ? true: false; }\n"
" operator void*() { return ptr.data; }\n"
" operator bool() { return ptr.data != NULL; }\n"
"\n"
@@ -3551,7 +3620,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 = (float *)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"
@@ -3562,7 +3631,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 = (float *)malloc(sizeof(T) * other.length);\n"
" memcpy(data, other.data, sizeof(T) * other.length);\n"
" length = other.length;\n"
" }\n"
@@ -3593,7 +3662,7 @@ static const char *cpp_classes = ""
"{ return iter.valid != other.iter.valid; }\n"
"\n"
" void begin(const Pointer &ptr)\n"
-" { if (init) Tend(&iter); Tbegin(&iter, (PointerRNA*)&ptr.ptr); t = T(iter.ptr); init = true; }\n"
+" { if (init) Tend(&iter); Tbegin(&iter, (PointerRNA *)&ptr.ptr); t = T(iter.ptr); init = true; }\n"
"\n"
"private:\n"
" const CollectionIterator<T, Tbegin, Tnext, Tend>& operator="
@@ -3727,13 +3796,13 @@ static void rna_generate_header_cpp(BlenderRNA *UNUSED(brna), FILE *f)
if (first_collection_func_struct == NULL)
first_collection_func_struct = ds->srna->identifier;
- if (!rna_is_collection_functions_struct(collection_func_structs, (char*)prop->srna)) {
+ if (!rna_is_collection_functions_struct(collection_func_structs, (char *)prop->srna)) {
if (all_collection_func_structs >= max_collection_func_structs) {
printf("Array size to store all collection structures names is too small\n");
exit(1);
}
- collection_func_structs[all_collection_func_structs++] = (char*)prop->srna;
+ collection_func_structs[all_collection_func_structs++] = (char *)prop->srna;
}
}
}
@@ -3819,6 +3888,13 @@ static int rna_preprocess(const char *outfile)
if (PROCESS_ITEMS[i].define) {
PROCESS_ITEMS[i].define(brna);
+ /* sanity check */
+ if (!DefRNA.animate) {
+ fprintf(stderr,
+ "Error: DefRNA.animate left disabled in %s\n",
+ PROCESS_ITEMS[i].filename);
+ }
+
for (ds = DefRNA.structs.first; ds; ds = ds->cont.next)
if (!ds->filename)
ds->filename = PROCESS_ITEMS[i].filename;
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 11ce7345e41..0489f85a37f 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -24,18 +24,19 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
#include <stdio.h>
-#include "RNA_access.h"
-#include "RNA_define.h"
-
#include "DNA_ID.h"
#include "DNA_vfont_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
+#include "BLI_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
#include "WM_types.h"
#include "rna_internal.h"
@@ -56,6 +57,7 @@ EnumPropertyItem id_type_items[] = {
{ID_KE, "KEY", ICON_SHAPEKEY_DATA, "Key", ""},
{ID_LA, "LAMP", ICON_LAMP_DATA, "Lamp", ""},
{ID_LI, "LIBRARY", ICON_LIBRARY_DATA_DIRECT, "Library", ""},
+ {ID_LS, "LINESTYLE", ICON_PARTICLE_DATA, "FreestyleLineStyle", ""}, /* FIXME proper icon */
{ID_LT, "LATTICE", ICON_LATTICE_DATA, "Lattice", ""},
{ID_MA, "MATERIAL", ICON_MATERIAL_DATA, "Material", ""},
{ID_MB, "META", ICON_META_DATA, "MetaBall", ""},
@@ -102,7 +104,7 @@ void rna_ID_name_set(PointerRNA *ptr, const char *value)
{
ID *id = (ID *)ptr->data;
BLI_strncpy_utf8(id->name + 2, value, sizeof(id->name) - 2);
- test_idbutton(id->name + 2);
+ test_idbutton(id->name);
}
static int rna_ID_name_editable(PointerRNA *ptr)
@@ -131,6 +133,7 @@ short RNA_type_to_ID_code(StructRNA *type)
if (RNA_struct_is_a(type, &RNA_Key)) return ID_KE;
if (RNA_struct_is_a(type, &RNA_Lamp)) return ID_LA;
if (RNA_struct_is_a(type, &RNA_Library)) return ID_LI;
+ if (RNA_struct_is_a(type, &RNA_FreestyleLineStyle)) return ID_LS;
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;
@@ -167,6 +170,7 @@ StructRNA *ID_code_to_RNA_type(short idcode)
case ID_KE: return &RNA_Key;
case ID_LA: return &RNA_Lamp;
case ID_LI: return &RNA_Library;
+ case ID_LS: return &RNA_FreestyleLineStyle;
case ID_LT: return &RNA_Lattice;
case ID_MA: return &RNA_Material;
case ID_MB: return &RNA_MetaBall;
@@ -196,7 +200,7 @@ StructRNA *rna_ID_refine(PointerRNA *ptr)
return ID_code_to_RNA_type(GS(id->name));
}
-IDProperty *rna_ID_idprops(PointerRNA *ptr, int create)
+IDProperty *rna_ID_idprops(PointerRNA *ptr, bool create)
{
return IDP_GetProperties(ptr->data, create);
}
@@ -215,7 +219,7 @@ void rna_ID_fake_user_set(PointerRNA *ptr, int value)
}
}
-IDProperty *rna_PropertyGroup_idprops(PointerRNA *ptr, int UNUSED(create))
+IDProperty *rna_PropertyGroup_idprops(PointerRNA *ptr, bool UNUSED(create))
{
return ptr->data;
}
@@ -248,7 +252,7 @@ StructRNA *rna_PropertyGroup_register(Main *UNUSED(bmain), ReportList *reports,
return NULL;
}
- return RNA_def_struct(&BLENDER_RNA, identifier, "PropertyGroup"); /* XXX */
+ return RNA_def_struct_ptr(&BLENDER_RNA, identifier, &RNA_PropertyGroup); /* XXX */
}
StructRNA *rna_PropertyGroup_refine(PointerRNA *ptr)
@@ -260,7 +264,7 @@ static ID *rna_ID_copy(ID *id)
{
ID *newid;
- if (id_copy(id, &newid, 0)) {
+ if (id_copy(id, &newid, false)) {
if (newid) id_us_min(newid);
return newid;
}
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 488dbffc3db..b9ee9b6ad1c 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -40,6 +40,7 @@
#include "BLI_utildefines.h"
#include "BLI_dynstr.h"
#include "BLI_ghash.h"
+#include "BLI_math.h"
#include "BLF_api.h"
#include "BLF_translation.h"
@@ -51,12 +52,11 @@
#include "BKE_main.h"
#include "BKE_report.h"
-
-#include "WM_api.h"
-
#include "RNA_access.h"
#include "RNA_define.h"
+#include "WM_api.h"
+
/* flush updates */
#include "DNA_object_types.h"
#include "BKE_depsgraph.h"
@@ -257,7 +257,7 @@ static IDProperty *rna_idproperty_ui(PropertyRNA *prop)
return NULL;
}
-IDProperty *RNA_struct_idprops(PointerRNA *ptr, int create)
+IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create)
{
StructRNA *type = ptr->type;
@@ -267,9 +267,9 @@ IDProperty *RNA_struct_idprops(PointerRNA *ptr, int create)
return NULL;
}
-int RNA_struct_idprops_check(StructRNA *srna)
+bool RNA_struct_idprops_check(StructRNA *srna)
{
- return (srna && srna->idproperties) ? 1 : 0;
+ return (srna && srna->idproperties);
}
static IDProperty *rna_idproperty_find(PointerRNA *ptr, const char *name)
@@ -282,6 +282,20 @@ static IDProperty *rna_idproperty_find(PointerRNA *ptr, const char *name)
return NULL;
}
+static void rna_idproperty_free(PointerRNA *ptr, const char *name)
+{
+ IDProperty *group = RNA_struct_idprops(ptr, 0);
+
+ if (group) {
+ IDProperty *idprop = IDP_GetPropertyFromGroup(group, name);
+ if (idprop) {
+ IDP_RemFromGroup(group, idprop);
+ IDP_FreeProperty(idprop);
+ MEM_freeN(idprop);
+ }
+ }
+}
+
static int rna_ensure_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
{
if (prop->magic == RNA_MAGIC) {
@@ -298,15 +312,15 @@ static int rna_ensure_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
}
}
-static int rna_ensure_property_array_check(PropertyRNA *prop)
+static bool rna_ensure_property_array_check(PropertyRNA *prop)
{
if (prop->magic == RNA_MAGIC) {
- return (prop->getlength || prop->totarraylength) ? 1 : 0;
+ return (prop->getlength || prop->totarraylength);
}
else {
IDProperty *idprop = (IDProperty *)prop;
- return idprop->type == IDP_ARRAY ? 1 : 0;
+ return (idprop->type == IDP_ARRAY);
}
}
@@ -328,7 +342,7 @@ static void rna_ensure_property_multi_array_length(PointerRNA *ptr, PropertyRNA
}
}
-static int rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDProperty *idprop)
+static bool rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDProperty *idprop)
{
/* this verifies if the idproperty actually matches the property
* description and otherwise removes it. this is to ensure that
@@ -338,40 +352,40 @@ static int rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDPro
switch (idprop->type) {
case IDP_IDPARRAY:
if (prop->type != PROP_COLLECTION)
- return 0;
+ return false;
break;
case IDP_ARRAY:
if (rna_ensure_property_array_length(ptr, prop) != idprop->len)
- return 0;
+ return false;
if (idprop->subtype == IDP_FLOAT && prop->type != PROP_FLOAT)
- return 0;
+ return false;
if (idprop->subtype == IDP_INT && !ELEM3(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
- return 0;
+ return false;
break;
case IDP_INT:
if (!ELEM3(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
- return 0;
+ return false;
break;
case IDP_FLOAT:
case IDP_DOUBLE:
if (prop->type != PROP_FLOAT)
- return 0;
+ return false;
break;
case IDP_STRING:
if (prop->type != PROP_STRING)
- return 0;
+ return false;
break;
case IDP_GROUP:
if (prop->type != PROP_POINTER)
- return 0;
+ return false;
break;
default:
- return 0;
+ return false;
}
- return 1;
+ return true;
}
static PropertyRNA *typemap[IDP_NUMTYPES] = {
@@ -477,7 +491,7 @@ static const char *rna_ensure_property_description(PropertyRNA *prop)
description = ((IDProperty *)prop)->name; /* XXX - not correct */
}
- return TIP_(description);
+ return description;
}
static const char *rna_ensure_property_name(PropertyRNA *prop)
@@ -489,7 +503,7 @@ static const char *rna_ensure_property_name(PropertyRNA *prop)
else
name = ((IDProperty *)prop)->name;
- return CTX_IFACE_(prop->translation_context, name);
+ return name;
}
/* Structs */
@@ -515,6 +529,11 @@ const char *RNA_struct_ui_name(StructRNA *type)
return CTX_IFACE_(type->translation_context, type->name);
}
+const char *RNA_struct_ui_name_raw(StructRNA *type)
+{
+ return type->name;
+}
+
int RNA_struct_ui_icon(StructRNA *type)
{
if (type)
@@ -528,9 +547,14 @@ const char *RNA_struct_ui_description(StructRNA *type)
return TIP_(type->description);
}
+const char *RNA_struct_ui_description_raw(StructRNA *type)
+{
+ return type->description;
+}
+
const char *RNA_struct_translation_context(StructRNA *type)
{
- return type->translation_context ? type->translation_context : BLF_I18NCONTEXT_DEFAULT;
+ return type->translation_context;
}
PropertyRNA *RNA_struct_name_property(StructRNA *type)
@@ -548,23 +572,23 @@ StructRNA *RNA_struct_base(StructRNA *type)
return type->base;
}
-int RNA_struct_is_ID(StructRNA *type)
+bool RNA_struct_is_ID(StructRNA *type)
{
return (type->flag & STRUCT_ID) != 0;
}
-int RNA_struct_undo_check(StructRNA *type)
+bool RNA_struct_undo_check(StructRNA *type)
{
return (type->flag & STRUCT_UNDO) != 0;
}
-int RNA_struct_idprops_register_check(StructRNA *type)
+bool RNA_struct_idprops_register_check(StructRNA *type)
{
return (type->flag & STRUCT_NO_IDPROPERTIES) == 0;
}
/* remove an id-property */
-int RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier)
+bool RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier)
{
IDProperty *group = RNA_struct_idprops(ptr, 0);
@@ -575,25 +599,25 @@ int RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier)
IDP_FreeProperty(idp);
MEM_freeN(idp);
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
-int RNA_struct_is_a(StructRNA *type, StructRNA *srna)
+bool RNA_struct_is_a(StructRNA *type, StructRNA *srna)
{
StructRNA *base;
if (!type)
- return 0;
+ return false;
/* ptr->type is always maximally refined */
for (base = type; base; base = base->base)
if (base == srna)
- return 1;
+ return true;
- return 0;
+ return false;
}
PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
@@ -636,13 +660,13 @@ static PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna)
return prop;
}
-int RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test)
+bool RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test)
{
/* note, prop_test could be freed memory, only use for comparison */
/* validate the RNA is ok */
PropertyRNA *iterprop;
- int found = FALSE;
+ bool found = false;
iterprop = RNA_struct_iterator_property(ptr->type);
@@ -650,7 +674,7 @@ int RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test)
{
/* PropertyRNA *prop = itemptr.data; */
if (prop_test == (PropertyRNA *)itemptr.data) {
- found = TRUE;
+ found = true;
break;
}
}
@@ -778,7 +802,7 @@ const char *RNA_property_identifier(PropertyRNA *prop)
const char *RNA_property_description(PropertyRNA *prop)
{
- return rna_ensure_property_description(prop);
+ return TIP_(rna_ensure_property_description(prop));
}
PropertyType RNA_property_type(PropertyRNA *prop)
@@ -811,7 +835,7 @@ int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
return rna_ensure_property_array_length(ptr, prop);
}
-int RNA_property_array_check(PropertyRNA *prop)
+bool RNA_property_array_check(PropertyRNA *prop)
{
return rna_ensure_property_array_check(prop);
}
@@ -844,6 +868,8 @@ char RNA_property_array_item_char(PropertyRNA *prop, int index)
const char *coloritem = "RGBA";
PropertySubType subtype = rna_ensure_property(prop)->subtype;
+ BLI_assert(index >= 0);
+
/* get string to use for array index */
if ((index < 4) && ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
return quatitem[index];
@@ -937,6 +963,12 @@ void RNA_property_int_range(PointerRNA *ptr, PropertyRNA *prop, int *hardmin, in
iprop->range(ptr, hardmin, hardmax, &softmin, &softmax);
}
+ else if (iprop->range_ex) {
+ *hardmin = INT_MIN;
+ *hardmax = INT_MAX;
+
+ iprop->range_ex(ptr, prop, hardmin, hardmax, &softmin, &softmax);
+ }
else {
*hardmin = iprop->hardmin;
*hardmax = iprop->hardmax;
@@ -977,8 +1009,17 @@ void RNA_property_int_ui_range(PointerRNA *ptr, PropertyRNA *prop, int *softmin,
iprop->range(ptr, &hardmin, &hardmax, softmin, softmax);
- *softmin = MAX2(*softmin, hardmin);
- *softmax = MIN2(*softmax, hardmax);
+ *softmin = max_ii(*softmin, hardmin);
+ *softmax = min_ii(*softmax, hardmax);
+ }
+ else if (iprop->range_ex) {
+ hardmin = INT_MIN;
+ hardmax = INT_MAX;
+
+ iprop->range_ex(ptr, prop, &hardmin, &hardmax, softmin, softmax);
+
+ *softmin = max_ii(*softmin, hardmin);
+ *softmax = min_ii(*softmax, hardmax);
}
*step = iprop->step;
@@ -1012,6 +1053,12 @@ void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin
fprop->range(ptr, hardmin, hardmax, &softmin, &softmax);
}
+ else if (fprop->range_ex) {
+ *hardmin = -FLT_MAX;
+ *hardmax = FLT_MAX;
+
+ fprop->range_ex(ptr, prop, hardmin, hardmax, &softmin, &softmax);
+ }
else {
*hardmin = fprop->hardmin;
*hardmax = fprop->hardmax;
@@ -1056,8 +1103,17 @@ void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *soft
fprop->range(ptr, &hardmin, &hardmax, softmin, softmax);
- *softmin = MAX2(*softmin, hardmin);
- *softmax = MIN2(*softmax, hardmax);
+ *softmin = max_ff(*softmin, hardmin);
+ *softmax = min_ff(*softmax, hardmax);
+ }
+ else if (fprop->range_ex) {
+ hardmin = -FLT_MAX;
+ hardmax = FLT_MAX;
+
+ fprop->range_ex(ptr, prop, &hardmin, &hardmax, softmin, softmax);
+
+ *softmin = max_ff(*softmin, hardmin);
+ *softmax = min_ff(*softmax, hardmax);
}
*step = fprop->step;
@@ -1197,11 +1253,16 @@ void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA
RNA_property_enum_items(C, ptr, prop, item, totitem, free);
#ifdef WITH_INTERNATIONAL
- /* Note: keep directly using BLF_gettext here, has we have already done tests like BLF_translate_iface... */
- if (BLF_translate_iface()) {
+ {
int i;
+ /* Note: Only do those tests once, and then use BLF_pgettext. */
+ int do_iface = BLF_translate_iface();
+ int do_tooltip = BLF_translate_tooltips();
EnumPropertyItem *nitem;
+ if (!(do_iface || do_tooltip))
+ return;
+
if (*free) {
nitem = *item;
}
@@ -1217,18 +1278,16 @@ void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA
for (i = 0; (*item)[i].identifier; i++)
nitem[i] = (*item)[i];
- *free = 1;
+ *free = TRUE;
}
for (i = 0; nitem[i].identifier; i++) {
- if (nitem[i].name) {
- if (prop->translation_context)
- nitem[i].name = BLF_pgettext(prop->translation_context, nitem[i].name);
- else
- nitem[i].name = BLF_pgettext(NULL, nitem[i].name);
+ if (nitem[i].name && do_iface) {
+ nitem[i].name = BLF_pgettext(prop->translation_context, nitem[i].name);
}
- if (nitem[i].description)
+ if (nitem[i].description && do_tooltip) {
nitem[i].description = BLF_pgettext(NULL, nitem[i].description);
+ }
}
*item = nitem;
@@ -1237,17 +1296,18 @@ void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA
}
-int RNA_property_enum_value(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *value)
+bool RNA_property_enum_value(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *r_value)
{
EnumPropertyItem *item, *item_array;
- int free, found;
+ int free;
+ bool found;
RNA_property_enum_items(C, ptr, prop, &item_array, NULL, &free);
if (item_array) {
for (item = item_array; item->identifier; item++) {
if (item->identifier[0] && strcmp(item->identifier, identifier) == 0) {
- *value = item->value;
+ *r_value = item->value;
break;
}
}
@@ -1259,97 +1319,100 @@ int RNA_property_enum_value(bContext *C, PointerRNA *ptr, PropertyRNA *prop, con
}
}
else {
- found = 0;
+ found = false;
}
return found;
}
-int RNA_enum_identifier(EnumPropertyItem *item, const int value, const char **identifier)
+bool RNA_enum_identifier(EnumPropertyItem *item, const int value, const char **identifier)
{
for (; item->identifier; item++) {
if (item->identifier[0] && item->value == value) {
*identifier = item->identifier;
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
-int RNA_enum_bitflag_identifiers(EnumPropertyItem *item, const int value, const char **identifier)
+int RNA_enum_bitflag_identifiers(EnumPropertyItem *item, const int value, const char **r_identifier)
{
int index = 0;
for (; item->identifier; item++) {
if (item->identifier[0] && item->value & value) {
- identifier[index++] = item->identifier;
+ r_identifier[index++] = item->identifier;
}
}
- identifier[index] = NULL;
+ r_identifier[index] = NULL;
return index;
}
-int RNA_enum_name(EnumPropertyItem *item, const int value, const char **name)
+bool RNA_enum_name(EnumPropertyItem *item, const int value, const char **r_name)
{
for (; item->identifier; item++) {
if (item->identifier[0] && item->value == value) {
- *name = item->name;
- return 1;
+ *r_name = item->name;
+ return true;
}
}
- return 0;
+ return false;
}
-int RNA_enum_description(EnumPropertyItem *item, const int value, const char **description)
+bool RNA_enum_description(EnumPropertyItem *item, const int value, const char **r_description)
{
for (; item->identifier; item++) {
if (item->identifier[0] && item->value == value) {
- *description = item->description;
- return 1;
+ *r_description = item->description;
+ return true;
}
}
- return 0;
+ return false;
}
-int RNA_property_enum_identifier(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
- const char **identifier)
+bool RNA_property_enum_identifier(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
+ const char **identifier)
{
EnumPropertyItem *item = NULL;
- int result, free;
+ int free;
RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
if (item) {
+ bool result;
result = RNA_enum_identifier(item, value, identifier);
if (free)
MEM_freeN(item);
return result;
}
- return 0;
+ return false;
}
-int RNA_property_enum_name(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name)
+bool RNA_property_enum_name(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name)
{
EnumPropertyItem *item = NULL;
- int result, free;
+ int free;
RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
if (item) {
+ bool result;
result = RNA_enum_name(item, value, name);
if (free)
MEM_freeN(item);
return result;
}
- return 0;
+ return false;
}
int RNA_property_enum_bitflag_identifiers(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
const char **identifier)
{
EnumPropertyItem *item = NULL;
- int result, free;
+ int free;
RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
if (item) {
+ int result;
result = RNA_enum_bitflag_identifiers(item, value, identifier);
if (free)
MEM_freeN(item);
@@ -1361,18 +1424,28 @@ int RNA_property_enum_bitflag_identifiers(bContext *C, PointerRNA *ptr, Property
const char *RNA_property_ui_name(PropertyRNA *prop)
{
+ return CTX_IFACE_(prop->translation_context, rna_ensure_property_name(prop));
+}
+
+const char *RNA_property_ui_name_raw(PropertyRNA *prop)
+{
return rna_ensure_property_name(prop);
}
const char *RNA_property_ui_description(PropertyRNA *prop)
{
+ return TIP_(rna_ensure_property_description(prop));
+}
+
+const char *RNA_property_ui_description_raw(PropertyRNA *prop)
+{
return rna_ensure_property_description(prop);
}
const char *RNA_property_translation_context(PropertyRNA *_prop)
{
PropertyRNA *prop = rna_ensure_property(_prop);
- return prop->translation_context ? prop->translation_context : BLF_I18NCONTEXT_DEFAULT;
+ return prop->translation_context;
}
int RNA_property_ui_icon(PropertyRNA *prop)
@@ -1380,7 +1453,7 @@ int RNA_property_ui_icon(PropertyRNA *prop)
return rna_ensure_property(prop)->icon;
}
-int RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
+bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
{
ID *id = ptr->id.data;
int flag;
@@ -1390,21 +1463,23 @@ int RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
return (flag & PROP_EDITABLE) && (!id || !id->lib || (prop->flag & PROP_LIB_EXCEPTION));
}
-int RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop)
+bool RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop)
{
int flag;
prop = rna_ensure_property(prop);
flag = prop->editable ? prop->editable(ptr) : prop->flag;
- return (flag & PROP_EDITABLE);
+ return (flag & PROP_EDITABLE) != 0;
}
/* same as RNA_property_editable(), except this checks individual items in an array */
-int RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index)
+bool RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index)
{
ID *id;
int flag;
+ BLI_assert(index >= 0);
+
prop = rna_ensure_property(prop);
flag = prop->flag;
@@ -1420,34 +1495,34 @@ int RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index)
return (flag & PROP_EDITABLE) && (!id || !id->lib || (prop->flag & PROP_LIB_EXCEPTION));
}
-int RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop)
+bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop)
{
/* check that base ID-block can support animation data */
if (!id_type_can_have_animdata(ptr->id.data))
- return 0;
+ return false;
prop = rna_ensure_property(prop);
if (!(prop->flag & PROP_ANIMATABLE))
- return 0;
+ return false;
- return (prop->flag & PROP_EDITABLE);
+ return (prop->flag & PROP_EDITABLE) != 0;
}
-int RNA_property_animated(PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop))
+bool RNA_property_animated(PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop))
{
/* would need to ask animation system */
- return 0;
+ return false;
}
/* this function is to check if its possible to create a valid path from the ID
* its slow so don't call in a loop */
-int RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop)
+bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop)
{
char *path = RNA_path_from_ID_to_property(ptr, prop);
- int ret = 0;
+ bool ret = false;
if (path) {
PointerRNA id_ptr;
@@ -1458,9 +1533,6 @@ int RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop)
if (RNA_path_resolve(&id_ptr, path, &r_ptr, &r_prop) == TRUE) {
ret = (prop == r_prop);
}
- else {
- ret = FALSE;
- }
MEM_freeN(path);
}
@@ -1470,7 +1542,7 @@ int RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop)
static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
{
- int is_rna = (prop->magic == RNA_MAGIC);
+ const bool is_rna = (prop->magic == RNA_MAGIC);
prop = rna_ensure_property(prop);
if (is_rna) {
@@ -1505,7 +1577,7 @@ static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerR
/* must keep in sync with 'rna_property_update'
* note, its possible this returns a false positive in the case of PROP_CONTEXT_UPDATE
* but this isn't likely to be a performance problem. */
-int RNA_property_update_check(PropertyRNA *prop)
+bool RNA_property_update_check(PropertyRNA *prop)
{
return (prop->magic != RNA_MAGIC || prop->update || prop->noteflag);
}
@@ -1550,19 +1622,19 @@ static ListBase rna_updates_cache = {NULL, NULL};
void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop)
{
+ const bool is_rna = (prop->magic == RNA_MAGIC);
tRnaUpdateCacheElem *uce = NULL;
UpdateFunc fn = NULL;
LinkData *ld;
- short is_rna = (prop->magic == RNA_MAGIC);
/* sanity check */
- if (ELEM(NULL, ptr, prop))
+ if (NULL == ptr)
return;
prop = rna_ensure_property(prop);
/* we can only handle update calls with no context args for now (makes animsys updates easier) */
- if ((is_rna == 0) || (prop->update == NULL) || (prop->flag & PROP_CONTEXT_UPDATE))
+ if ((is_rna == false) || (prop->update == NULL) || (prop->flag & PROP_CONTEXT_UPDATE))
return;
fn = prop->update;
@@ -1635,12 +1707,14 @@ int RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
IDProperty *idprop;
BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
- BLI_assert(RNA_property_array_check(prop) == 0);
+ BLI_assert(RNA_property_array_check(prop) == false);
if ((idprop = rna_idproperty_check(&prop, ptr)))
return IDP_Int(idprop);
else if (bprop->get)
return bprop->get(ptr);
+ else if (bprop->get_ex)
+ return bprop->get_ex(ptr, prop);
else
return bprop->defaultvalue;
}
@@ -1651,7 +1725,7 @@ void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, int value)
IDProperty *idprop;
BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
- BLI_assert(RNA_property_array_check(prop) == 0);
+ BLI_assert(RNA_property_array_check(prop) == false);
/* just in case other values are passed */
if (value) value = 1;
@@ -1663,6 +1737,9 @@ void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, int value)
else if (bprop->set) {
bprop->set(ptr, value);
}
+ else if (bprop->set_ex) {
+ bprop->set_ex(ptr, prop, value);
+ }
else if (prop->flag & PROP_EDITABLE) {
IDPropertyTemplate val = {0};
IDProperty *group;
@@ -1681,7 +1758,7 @@ void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, int *val
IDProperty *idprop;
BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
- BLI_assert(RNA_property_array_check(prop) != 0);
+ BLI_assert(RNA_property_array_check(prop) != false);
if ((idprop = rna_idproperty_check(&prop, ptr))) {
if (prop->arraydimension == 0)
@@ -1693,6 +1770,8 @@ void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, int *val
values[0] = RNA_property_boolean_get(ptr, prop);
else if (bprop->getarray)
bprop->getarray(ptr, values);
+ else if (bprop->getarray_ex)
+ bprop->getarray_ex(ptr, prop, values);
else if (bprop->defaultarray)
memcpy(values, bprop->defaultarray, sizeof(int) * prop->totarraylength);
else
@@ -1705,7 +1784,8 @@ int RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index
int len = rna_ensure_property_array_length(ptr, prop);
BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
- BLI_assert(RNA_property_array_check(prop) != 0);
+ BLI_assert(RNA_property_array_check(prop) != false);
+ BLI_assert(index >= 0);
if (len <= RNA_MAX_ARRAY_LENGTH) {
RNA_property_boolean_get_array(ptr, prop, tmp);
@@ -1729,7 +1809,7 @@ void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const in
IDProperty *idprop;
BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
- BLI_assert(RNA_property_array_check(prop) != 0);
+ BLI_assert(RNA_property_array_check(prop) != false);
if ((idprop = rna_idproperty_check(&prop, ptr))) {
if (prop->arraydimension == 0)
@@ -1743,6 +1823,8 @@ void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const in
RNA_property_boolean_set(ptr, prop, values[0]);
else if (bprop->setarray)
bprop->setarray(ptr, values);
+ else if (bprop->setarray_ex)
+ bprop->setarray_ex(ptr, prop, values);
else if (prop->flag & PROP_EDITABLE) {
IDPropertyTemplate val = {0};
IDProperty *group;
@@ -1765,7 +1847,8 @@ void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int inde
int len = rna_ensure_property_array_length(ptr, prop);
BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
- BLI_assert(RNA_property_array_check(prop) != 0);
+ BLI_assert(RNA_property_array_check(prop) != false);
+ BLI_assert(index >= 0);
if (len <= RNA_MAX_ARRAY_LENGTH) {
RNA_property_boolean_get_array(ptr, prop, tmp);
@@ -1788,7 +1871,7 @@ int RNA_property_boolean_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
- BLI_assert(RNA_property_array_check(prop) == 0);
+ BLI_assert(RNA_property_array_check(prop) == false);
return bprop->defaultvalue;
}
@@ -1798,7 +1881,7 @@ void RNA_property_boolean_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA
BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
- BLI_assert(RNA_property_array_check(prop) != 0);
+ BLI_assert(RNA_property_array_check(prop) != false);
if (prop->arraydimension == 0)
values[0] = bprop->defaultvalue;
@@ -1814,7 +1897,8 @@ int RNA_property_boolean_get_default_index(PointerRNA *ptr, PropertyRNA *prop, i
int len = rna_ensure_property_array_length(ptr, prop);
BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
- BLI_assert(RNA_property_array_check(prop) != 0);
+ BLI_assert(RNA_property_array_check(prop) != false);
+ BLI_assert(index >= 0);
if (len <= RNA_MAX_ARRAY_LENGTH) {
RNA_property_boolean_get_default_array(ptr, prop, tmp);
@@ -1838,12 +1922,14 @@ int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
IDProperty *idprop;
BLI_assert(RNA_property_type(prop) == PROP_INT);
- BLI_assert(RNA_property_array_check(prop) == 0);
+ BLI_assert(RNA_property_array_check(prop) == false);
if ((idprop = rna_idproperty_check(&prop, ptr)))
return IDP_Int(idprop);
else if (iprop->get)
return iprop->get(ptr);
+ else if (iprop->get_ex)
+ return iprop->get_ex(ptr, prop);
else
return iprop->defaultvalue;
}
@@ -1854,7 +1940,7 @@ void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
IDProperty *idprop;
BLI_assert(RNA_property_type(prop) == PROP_INT);
- BLI_assert(RNA_property_array_check(prop) == 0);
+ BLI_assert(RNA_property_array_check(prop) == false);
/* useful to check on bad values but set function should clamp */
/* BLI_assert(RNA_property_int_clamp(ptr, prop, &value) == 0); */
@@ -1864,6 +1950,8 @@ void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
}
else if (iprop->set)
iprop->set(ptr, value);
+ else if (iprop->set_ex)
+ iprop->set_ex(ptr, prop, value);
else if (prop->flag & PROP_EDITABLE) {
IDPropertyTemplate val = {0};
IDProperty *group;
@@ -1884,7 +1972,7 @@ void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
IDProperty *idprop;
BLI_assert(RNA_property_type(prop) == PROP_INT);
- BLI_assert(RNA_property_array_check(prop) != 0);
+ BLI_assert(RNA_property_array_check(prop) != false);
if ((idprop = rna_idproperty_check(&prop, ptr))) {
if (prop->arraydimension == 0)
@@ -1896,6 +1984,8 @@ void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
values[0] = RNA_property_int_get(ptr, prop);
else if (iprop->getarray)
iprop->getarray(ptr, values);
+ else if (iprop->getarray_ex)
+ iprop->getarray_ex(ptr, prop, values);
else if (iprop->defaultarray)
memcpy(values, iprop->defaultarray, sizeof(int) * prop->totarraylength);
else
@@ -1945,7 +2035,8 @@ int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
int len = rna_ensure_property_array_length(ptr, prop);
BLI_assert(RNA_property_type(prop) == PROP_INT);
- BLI_assert(RNA_property_array_check(prop) != 0);
+ BLI_assert(RNA_property_array_check(prop) != false);
+ BLI_assert(index >= 0);
if (len <= RNA_MAX_ARRAY_LENGTH) {
RNA_property_int_get_array(ptr, prop, tmp);
@@ -1969,7 +2060,7 @@ void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *v
IDProperty *idprop;
BLI_assert(RNA_property_type(prop) == PROP_INT);
- BLI_assert(RNA_property_array_check(prop) != 0);
+ BLI_assert(RNA_property_array_check(prop) != false);
if ((idprop = rna_idproperty_check(&prop, ptr))) {
if (prop->arraydimension == 0)
@@ -1983,6 +2074,8 @@ void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *v
RNA_property_int_set(ptr, prop, values[0]);
else if (iprop->setarray)
iprop->setarray(ptr, values);
+ else if (iprop->setarray_ex)
+ iprop->setarray_ex(ptr, prop, values);
else if (prop->flag & PROP_EDITABLE) {
IDPropertyTemplate val = {0};
IDProperty *group;
@@ -2007,7 +2100,8 @@ void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, i
int len = rna_ensure_property_array_length(ptr, prop);
BLI_assert(RNA_property_type(prop) == PROP_INT);
- BLI_assert(RNA_property_array_check(prop) != 0);
+ BLI_assert(RNA_property_array_check(prop) != false);
+ BLI_assert(index >= 0);
if (len <= RNA_MAX_ARRAY_LENGTH) {
RNA_property_int_get_array(ptr, prop, tmp);
@@ -2036,7 +2130,7 @@ void RNA_property_int_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *pr
IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
BLI_assert(RNA_property_type(prop) == PROP_INT);
- BLI_assert(RNA_property_array_check(prop) != 0);
+ BLI_assert(RNA_property_array_check(prop) != false);
if (prop->arraydimension == 0)
values[0] = iprop->defaultvalue;
@@ -2051,6 +2145,10 @@ int RNA_property_int_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int i
int tmp[RNA_MAX_ARRAY_LENGTH];
int len = rna_ensure_property_array_length(ptr, prop);
+ BLI_assert(RNA_property_type(prop) == PROP_INT);
+ BLI_assert(RNA_property_array_check(prop) != false);
+ BLI_assert(index >= 0);
+
if (len <= RNA_MAX_ARRAY_LENGTH) {
RNA_property_int_get_default_array(ptr, prop, tmp);
return tmp[index];
@@ -2073,7 +2171,7 @@ float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
IDProperty *idprop;
BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
- BLI_assert(RNA_property_array_check(prop) == 0);
+ BLI_assert(RNA_property_array_check(prop) == false);
if ((idprop = rna_idproperty_check(&prop, ptr))) {
if (idprop->type == IDP_FLOAT)
@@ -2083,6 +2181,8 @@ float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
}
else if (fprop->get)
return fprop->get(ptr);
+ else if (fprop->get_ex)
+ return fprop->get_ex(ptr, prop);
else
return fprop->defaultvalue;
}
@@ -2093,7 +2193,7 @@ void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
IDProperty *idprop;
BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
- BLI_assert(RNA_property_array_check(prop) == 0);
+ BLI_assert(RNA_property_array_check(prop) == false);
/* useful to check on bad values but set function should clamp */
/* BLI_assert(RNA_property_float_clamp(ptr, prop, &value) == 0); */
@@ -2108,6 +2208,9 @@ void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
else if (fprop->set) {
fprop->set(ptr, value);
}
+ else if (fprop->set_ex) {
+ fprop->set_ex(ptr, prop, value);
+ }
else if (prop->flag & PROP_EDITABLE) {
IDPropertyTemplate val = {0};
IDProperty *group;
@@ -2129,7 +2232,7 @@ void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *val
int i;
BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
- BLI_assert(RNA_property_array_check(prop) != 0);
+ BLI_assert(RNA_property_array_check(prop) != false);
if ((idprop = rna_idproperty_check(&prop, ptr))) {
if (prop->arraydimension == 0)
@@ -2146,6 +2249,8 @@ void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *val
values[0] = RNA_property_float_get(ptr, prop);
else if (fprop->getarray)
fprop->getarray(ptr, values);
+ else if (fprop->getarray_ex)
+ fprop->getarray_ex(ptr, prop, values);
else if (fprop->defaultarray)
memcpy(values, fprop->defaultarray, sizeof(float) * prop->totarraylength);
else
@@ -2195,7 +2300,8 @@ float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index
int len = rna_ensure_property_array_length(ptr, prop);
BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
- BLI_assert(RNA_property_array_check(prop) != 0);
+ BLI_assert(RNA_property_array_check(prop) != false);
+ BLI_assert(index >= 0);
if (len <= RNA_MAX_ARRAY_LENGTH) {
RNA_property_float_get_array(ptr, prop, tmp);
@@ -2211,7 +2317,6 @@ float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index
return value;
}
-
}
void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
@@ -2221,7 +2326,7 @@ void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const floa
int i;
BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
- BLI_assert(RNA_property_array_check(prop) != 0);
+ BLI_assert(RNA_property_array_check(prop) != false);
if ((idprop = rna_idproperty_check(&prop, ptr))) {
if (prop->arraydimension == 0) {
@@ -2245,6 +2350,9 @@ void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const floa
else if (fprop->setarray) {
fprop->setarray(ptr, values);
}
+ else if (fprop->setarray_ex) {
+ fprop->setarray_ex(ptr, prop, values);
+ }
else if (prop->flag & PROP_EDITABLE) {
IDPropertyTemplate val = {0};
IDProperty *group;
@@ -2269,7 +2377,8 @@ void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index,
int len = rna_ensure_property_array_length(ptr, prop);
BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
- BLI_assert(RNA_property_array_check(prop) != 0);
+ BLI_assert(RNA_property_array_check(prop) != false);
+ BLI_assert(index >= 0);
if (len <= RNA_MAX_ARRAY_LENGTH) {
RNA_property_float_get_array(ptr, prop, tmp);
@@ -2292,7 +2401,7 @@ float RNA_property_float_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
- BLI_assert(RNA_property_array_check(prop) == 0);
+ BLI_assert(RNA_property_array_check(prop) == false);
return fprop->defaultvalue;
}
@@ -2302,7 +2411,7 @@ void RNA_property_float_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *
FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
- BLI_assert(RNA_property_array_check(prop) != 0);
+ BLI_assert(RNA_property_array_check(prop) != false);
if (prop->arraydimension == 0)
values[0] = fprop->defaultvalue;
@@ -2318,7 +2427,8 @@ float RNA_property_float_get_default_index(PointerRNA *ptr, PropertyRNA *prop, i
int len = rna_ensure_property_array_length(ptr, prop);
BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
- BLI_assert(RNA_property_array_check(prop) != 0);
+ BLI_assert(RNA_property_array_check(prop) != false);
+ BLI_assert(index >= 0);
if (len <= RNA_MAX_ARRAY_LENGTH) {
RNA_property_float_get_default_array(ptr, prop, tmp);
@@ -2357,6 +2467,9 @@ void RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop, char *value)
else if (sprop->get) {
sprop->get(ptr, value);
}
+ else if (sprop->get_ex) {
+ sprop->get_ex(ptr, prop, value);
+ }
else {
strcpy(value, sprop->defaultvalue);
}
@@ -2417,6 +2530,8 @@ int RNA_property_string_length(PointerRNA *ptr, PropertyRNA *prop)
}
else if (sprop->length)
return sprop->length(ptr);
+ else if (sprop->length_ex)
+ return sprop->length_ex(ptr, prop);
else
return strlen(sprop->defaultvalue);
}
@@ -2435,6 +2550,8 @@ void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *val
}
else if (sprop->set)
sprop->set(ptr, value); /* set function needs to clamp its self */
+ else if (sprop->set_ex)
+ sprop->set_ex(ptr, prop, value); /* set function needs to clamp its self */
else if (prop->flag & PROP_EDITABLE) {
IDProperty *group;
@@ -2493,6 +2610,8 @@ int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
return IDP_Int(idprop);
else if (eprop->get)
return eprop->get(ptr);
+ else if (eprop->get_ex)
+ return eprop->get_ex(ptr, prop);
else
return eprop->defaultvalue;
}
@@ -2511,6 +2630,9 @@ void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
else if (eprop->set) {
eprop->set(ptr, value);
}
+ else if (eprop->set_ex) {
+ eprop->set_ex(ptr, prop, value);
+ }
else if (prop->flag & PROP_EDITABLE) {
IDPropertyTemplate val = {0};
IDProperty *group;
@@ -2790,7 +2912,7 @@ void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA
}
}
-int RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key)
+bool RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key)
{
IDProperty *idprop;
/* CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; */
@@ -2815,10 +2937,11 @@ int RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key)
IDP_ResizeIDPArray(idprop, len - 1);
}
- return 1;
+ return true;
+ }
+ else if (prop->flag & PROP_IDPROPERTY) {
+ return true;
}
- else if (prop->flag & PROP_IDPROPERTY)
- return 1;
/* py api calls directly */
#if 0
@@ -2830,15 +2953,15 @@ int RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key)
RNA_parameter_list_free(&params);
}
- return 0;
+ return false;
}
/*else
printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);*/
#endif
- return 0;
+ return false;
}
-int RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, int pos)
+bool RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, int pos)
{
IDProperty *idprop;
@@ -2860,12 +2983,13 @@ int RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, in
memcpy(&array[pos], &tmp, sizeof(IDProperty));
}
- return 1;
+ return true;
+ }
+ else if (prop->flag & PROP_IDPROPERTY) {
+ return true;
}
- else if (prop->flag & PROP_IDPROPERTY)
- return 1;
- return 0;
+ return false;
}
void RNA_property_collection_clear(PointerRNA *ptr, PropertyRNA *prop)
@@ -2992,7 +3116,7 @@ int RNA_property_collection_assign_int(PointerRNA *ptr, PropertyRNA *prop, const
return 0;
}
-int RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
+bool RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
{
BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
@@ -3073,6 +3197,21 @@ int RNA_raw_type_sizeof(RawPropertyType type)
}
}
+static int rna_property_array_length_all_dimensions(PointerRNA *ptr, PropertyRNA *prop)
+{
+ int i, len[RNA_MAX_ARRAY_DIMENSION];
+ const int dim = RNA_property_array_dimension(ptr, prop, len);
+ int size;
+
+ if (dim == 0)
+ return 0;
+
+ for (size = 1, i = 0; i < dim; i++)
+ size *= len[i];
+
+ return size;
+}
+
static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, const char *propname,
void *inarray, RawPropertyType intype, int inlen, int set)
{
@@ -3110,8 +3249,12 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro
/* check item array */
itemlen = RNA_property_array_length(&itemptr, itemprop);
+ /* dynamic array? need to get length per item */
+ if (itemprop->getlength) {
+ itemprop = NULL;
+ }
/* try to access as raw array */
- if (RNA_property_collection_raw_array(ptr, prop, itemprop, &out)) {
+ else if (RNA_property_collection_raw_array(ptr, prop, itemprop, &out)) {
int arraylen = (itemlen == 0) ? 1 : itemlen;
if (in.len != arraylen * out.len) {
BKE_reportf(reports, RPT_ERROR, "Array length mismatch (expected %d, got %d)",
@@ -3169,7 +3312,7 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro
iprop = RNA_struct_find_property(&itemptr, propname);
if (iprop) {
- itemlen = RNA_property_array_length(&itemptr, iprop);
+ itemlen = rna_property_array_length_all_dimensions(&itemptr, iprop);
itemtype = RNA_property_type(iprop);
}
else {
@@ -4030,8 +4173,9 @@ static char *rna_idp_path(PointerRNA *ptr, IDProperty *haystack, IDProperty *nee
else {
if (iter->type == IDP_GROUP) {
/* ensure this is RNA */
- PointerRNA child_ptr = RNA_pointer_get(ptr, iter->name);
- if (child_ptr.type) {
+ PropertyRNA *prop = RNA_struct_find_property(ptr, iter->name);
+ if (prop && prop->type == PROP_POINTER) {
+ PointerRNA child_ptr = RNA_property_pointer_get(ptr, prop);
link.name = iter->name;
link.index = -1;
if ((path = rna_idp_path(&child_ptr, iter, needle, &link))) {
@@ -4135,11 +4279,11 @@ char *RNA_path_from_ID_to_struct(PointerRNA *ptr)
char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop)
{
- int is_rna = (prop->magic == RNA_MAGIC);
+ const bool is_rna = (prop->magic == RNA_MAGIC);
const char *propname;
char *ptrpath, *path;
- if (!ptr->id.data || !ptr->data || !prop)
+ if (!ptr->id.data || !ptr->data)
return NULL;
/* path from ID to the struct holding this property */
@@ -4168,7 +4312,7 @@ char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop)
* Get the ID as a python representation, eg:
* bpy.data.foo["bar"]
*/
-char *RNA_path_from_ID_python(ID *id)
+char *RNA_path_full_ID_py(ID *id)
{
char id_esc[(sizeof(id->name) - 2) * 2];
@@ -4177,6 +4321,122 @@ char *RNA_path_from_ID_python(ID *id)
return BLI_sprintfN("bpy.data.%s[\"%s\"]", BKE_idcode_to_name_plural(GS(id->name)), id_esc);
}
+/**
+ * Get the ID.struct as a python representation, eg:
+ * bpy.data.foo["bar"].some_struct
+ */
+char *RNA_path_full_struct_py(struct PointerRNA *ptr)
+{
+ char *id_path;
+ char *data_path;
+
+ char *ret;
+
+ if (!ptr->id.data) {
+ return NULL;
+ }
+
+ /* never fails */
+ id_path = RNA_path_full_ID_py(ptr->id.data);
+
+ data_path = RNA_path_from_ID_to_struct(ptr);
+
+ ret = BLI_sprintfN("%s.%s",
+ id_path, data_path);
+
+ MEM_freeN(data_path);
+
+ return ret;
+}
+
+/**
+ * Get the ID.struct.property as a python representation, eg:
+ * bpy.data.foo["bar"].some_struct.some_prop[10]
+ */
+char *RNA_path_full_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
+{
+ char *id_path;
+ char *data_path;
+
+ char *ret;
+
+ if (!ptr->id.data) {
+ return NULL;
+ }
+
+ /* never fails */
+ id_path = RNA_path_full_ID_py(ptr->id.data);
+
+ data_path = RNA_path_from_ID_to_property(ptr, prop);
+
+ if ((index == -1) || (RNA_property_array_check(prop) == FALSE)) {
+ ret = BLI_sprintfN("%s.%s",
+ id_path, data_path);
+ }
+ else {
+ ret = BLI_sprintfN("%s.%s[%d]",
+ id_path, data_path, index);
+ }
+ MEM_freeN(id_path);
+ if (data_path) {
+ MEM_freeN(data_path);
+ }
+
+ return ret;
+}
+
+/**
+ * Get the struct.property as a python representation, eg:
+ * some_struct.some_prop[10]
+ */
+char *RNA_path_struct_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
+{
+ char *data_path;
+
+ char *ret;
+
+ if (!ptr->id.data) {
+ return NULL;
+ }
+
+ data_path = RNA_path_from_ID_to_property(ptr, prop);
+
+ if ((index == -1) || (RNA_property_array_check(prop) == FALSE)) {
+ ret = BLI_sprintfN("%s",
+ data_path);
+ }
+ else {
+ ret = BLI_sprintfN("%s[%d]",
+ data_path, index);
+ }
+
+ if (data_path) {
+ MEM_freeN(data_path);
+ }
+
+ return ret;
+}
+
+/**
+ * Get the struct.property as a python representation, eg:
+ * some_prop[10]
+ */
+char *RNA_path_property_py(PointerRNA *UNUSED(ptr), PropertyRNA *prop, int index)
+{
+ char *ret;
+
+ if ((index == -1) || (RNA_property_array_check(prop) == FALSE)) {
+ ret = BLI_sprintfN("%s",
+ RNA_property_identifier(prop));
+ }
+ else {
+ ret = BLI_sprintfN("%s[%d]",
+ RNA_property_identifier(prop), index);
+ }
+
+ return ret;
+}
+
/* Quick name based property access */
int RNA_boolean_get(PointerRNA *ptr, const char *name)
@@ -4347,7 +4607,7 @@ void RNA_enum_set_identifier(PointerRNA *ptr, const char *name, const char *id)
}
}
-int RNA_enum_is_equal(bContext *C, PointerRNA *ptr, const char *name, const char *enumname)
+bool RNA_enum_is_equal(bContext *C, PointerRNA *ptr, const char *name, const char *enumname)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, name);
EnumPropertyItem *item;
@@ -4364,60 +4624,60 @@ int RNA_enum_is_equal(bContext *C, PointerRNA *ptr, const char *name, const char
MEM_freeN(item);
printf("%s: %s.%s item %s not found.\n", __func__, ptr->type->identifier, name, enumname);
- return 0;
+ return false;
}
else {
printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
- return 0;
+ return false;
}
}
-int RNA_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *value)
+bool RNA_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *r_value)
{
for (; item->identifier; item++) {
if (strcmp(item->identifier, identifier) == 0) {
- *value = item->value;
- return 1;
+ *r_value = item->value;
+ return true;
}
}
- return 0;
+ return false;
}
-int RNA_enum_id_from_value(EnumPropertyItem *item, int value, const char **identifier)
+bool RNA_enum_id_from_value(EnumPropertyItem *item, int value, const char **r_identifier)
{
for (; item->identifier; item++) {
if (item->value == value) {
- *identifier = item->identifier;
- return 1;
+ *r_identifier = item->identifier;
+ return true;
}
}
- return 0;
+ return false;
}
-int RNA_enum_icon_from_value(EnumPropertyItem *item, int value, int *icon)
+bool RNA_enum_icon_from_value(EnumPropertyItem *item, int value, int *r_icon)
{
for (; item->identifier; item++) {
if (item->value == value) {
- *icon = item->icon;
- return 1;
+ *r_icon = item->icon;
+ return true;
}
}
- return 0;
+ return false;
}
-int RNA_enum_name_from_value(EnumPropertyItem *item, int value, const char **name)
+bool RNA_enum_name_from_value(EnumPropertyItem *item, int value, const char **r_name)
{
for (; item->identifier; item++) {
if (item->value == value) {
- *name = item->name;
- return 1;
+ *r_name = item->name;
+ return true;
}
}
- return 0;
+ return false;
}
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
@@ -4548,29 +4808,36 @@ int RNA_collection_length(PointerRNA *ptr, const char *name)
}
}
-int RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, int use_ghost)
+bool RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, bool use_ghost)
{
if (prop->flag & PROP_IDPROPERTY) {
IDProperty *idprop = rna_idproperty_find(ptr, prop->identifier);
- return ((idprop != NULL) && (use_ghost == FALSE || !(idprop->flag & IDP_FLAG_GHOST)));
+ return ((idprop != NULL) && (use_ghost == false || !(idprop->flag & IDP_FLAG_GHOST)));
}
else {
- return 1;
+ return true;
}
}
-int RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
+bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
{
if (prop->flag & PROP_IDPROPERTY) {
IDProperty *idprop = rna_idproperty_find(ptr, prop->identifier);
return ((idprop != NULL) && !(idprop->flag & IDP_FLAG_GHOST));
}
else {
- return 1;
+ return true;
+ }
+}
+
+void RNA_property_unset(PointerRNA *ptr, PropertyRNA *prop)
+{
+ if (prop->flag & PROP_IDPROPERTY) {
+ rna_idproperty_free(ptr, prop->identifier);
}
}
-int RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, int use_ghost)
+bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, identifier);
@@ -4584,7 +4851,7 @@ int RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, int u
}
}
-int RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
+bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, identifier);
@@ -4598,7 +4865,16 @@ int RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
}
}
-int RNA_property_is_idprop(PropertyRNA *prop)
+void RNA_struct_property_unset(PointerRNA *ptr, const char *identifier)
+{
+ PropertyRNA *prop = RNA_struct_find_property(ptr, identifier);
+
+ if (prop) {
+ RNA_property_unset(ptr, prop);
+ }
+}
+
+bool RNA_property_is_idprop(PropertyRNA *prop)
{
return (prop->magic != RNA_MAGIC);
}
@@ -4606,7 +4882,7 @@ int RNA_property_is_idprop(PropertyRNA *prop)
/* string representation of a property, python
* compatible but can be used for display too,
* context may be NULL */
-char *RNA_pointer_as_string(bContext *C, PointerRNA *ptr)
+static char *rna_pointer_as_string__idprop(bContext *C, PointerRNA *ptr)
{
DynStr *dynstr = BLI_dynstr_new();
char *cstring;
@@ -4627,7 +4903,7 @@ char *RNA_pointer_as_string(bContext *C, PointerRNA *ptr)
BLI_dynstr_append(dynstr, ", ");
first_time = 0;
- cstring = RNA_property_as_string(C, ptr, prop);
+ cstring = RNA_property_as_string(C, ptr, prop, -1);
BLI_dynstr_appendf(dynstr, "\"%s\":%s", propname, cstring);
MEM_freeN(cstring);
}
@@ -4641,6 +4917,28 @@ char *RNA_pointer_as_string(bContext *C, PointerRNA *ptr)
return cstring;
}
+static char *rna_pointer_as_string__bldata(PointerRNA *ptr)
+{
+ if (ptr->type == NULL) {
+ return BLI_strdup("None");
+ }
+ else if (RNA_struct_is_ID(ptr->type)) {
+ return RNA_path_full_ID_py(ptr->id.data);
+ }
+ else {
+ return RNA_path_full_struct_py(ptr);
+ }
+}
+
+char *RNA_pointer_as_string(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *prop_ptr, PointerRNA *ptr_prop)
+{
+ if (RNA_property_flag(prop_ptr) & PROP_IDPROPERTY) {
+ return rna_pointer_as_string__idprop(C, ptr_prop);
+ }
+ else {
+ return rna_pointer_as_string__bldata(ptr_prop);
+ }
+}
/* context and ptr_default can be NULL */
char *RNA_pointer_as_string_keywords_ex(bContext *C, PointerRNA *ptr, PointerRNA *ptr_default,
@@ -4693,7 +4991,7 @@ char *RNA_pointer_as_string_keywords_ex(bContext *C, PointerRNA *ptr, PointerRNA
}
}
else {
- buf = RNA_property_as_string(C, ptr, prop);
+ buf = RNA_property_as_string(C, ptr, prop, -1);
}
ok = TRUE;
@@ -4704,7 +5002,7 @@ char *RNA_pointer_as_string_keywords_ex(bContext *C, PointerRNA *ptr, PointerRNA
prop_default = RNA_struct_find_property(ptr_default, arg_name);
if (prop_default) {
- buf_default = RNA_property_as_string(C, ptr_default, prop_default);
+ buf_default = RNA_property_as_string(C, ptr_default, prop_default, -1);
if (strcmp(buf, buf_default) == 0)
ok = FALSE; /* values match, don't bother printing */
@@ -4754,7 +5052,12 @@ char *RNA_function_as_string_keywords(bContext *C, FunctionRNA *func, PointerRNA
iterprop);
}
-char *RNA_property_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
+static const char *bool_as_py_string(const int var)
+{
+ return var ? "True" : "False";
+}
+
+char *RNA_property_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index)
{
int type = RNA_property_type(prop);
int len = RNA_property_array_length(ptr, prop);
@@ -4768,17 +5071,22 @@ char *RNA_property_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
switch (type) {
case PROP_BOOLEAN:
if (len == 0) {
- BLI_dynstr_append(dynstr, RNA_property_boolean_get(ptr, prop) ? "True" : "False");
+ BLI_dynstr_append(dynstr, bool_as_py_string(RNA_property_boolean_get(ptr, prop)));
}
else {
- BLI_dynstr_append(dynstr, "(");
- for (i = 0; i < len; i++) {
- BLI_dynstr_appendf(dynstr, i ? ", %s" : "%s",
- RNA_property_boolean_get_index(ptr, prop, i) ? "True" : "False");
+ if (index != -1) {
+ BLI_dynstr_append(dynstr, bool_as_py_string(RNA_property_boolean_get_index(ptr, prop, index)));
+ }
+ else {
+ 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)));
+ }
+ if (len == 1)
+ BLI_dynstr_append(dynstr, ","); /* otherwise python wont see it as a tuple */
+ BLI_dynstr_append(dynstr, ")");
}
- if (len == 1)
- BLI_dynstr_append(dynstr, ","); /* otherwise python wont see it as a tuple */
- BLI_dynstr_append(dynstr, ")");
}
break;
case PROP_INT:
@@ -4786,13 +5094,18 @@ char *RNA_property_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
BLI_dynstr_appendf(dynstr, "%d", RNA_property_int_get(ptr, prop));
}
else {
- 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));
+ if (index != -1) {
+ BLI_dynstr_appendf(dynstr, "%d", RNA_property_int_get_index(ptr, prop, index));
+ }
+ else {
+ 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));
+ }
+ if (len == 1)
+ BLI_dynstr_append(dynstr, ","); /* otherwise python wont see it as a tuple */
+ BLI_dynstr_append(dynstr, ")");
}
- if (len == 1)
- BLI_dynstr_append(dynstr, ","); /* otherwise python wont see it as a tuple */
- BLI_dynstr_append(dynstr, ")");
}
break;
case PROP_FLOAT:
@@ -4800,13 +5113,18 @@ char *RNA_property_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
BLI_dynstr_appendf(dynstr, "%g", RNA_property_float_get(ptr, prop));
}
else {
- 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));
+ if (index != -1) {
+ BLI_dynstr_appendf(dynstr, "%g", RNA_property_float_get_index(ptr, prop, index));
+ }
+ else {
+ 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));
+ }
+ if (len == 1)
+ BLI_dynstr_append(dynstr, ","); /* otherwise python wont see it as a tuple */
+ BLI_dynstr_append(dynstr, ")");
}
- if (len == 1)
- BLI_dynstr_append(dynstr, ","); /* otherwise python wont see it as a tuple */
- BLI_dynstr_append(dynstr, ")");
}
break;
case PROP_STRING:
@@ -4872,7 +5190,7 @@ char *RNA_property_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
case PROP_POINTER:
{
PointerRNA tptr = RNA_property_pointer_get(ptr, prop);
- cstring = RNA_pointer_as_string(C, &tptr);
+ cstring = RNA_pointer_as_string(C, ptr, prop, &tptr);
BLI_dynstr_append(dynstr, cstring);
MEM_freeN(cstring);
break;
@@ -4893,7 +5211,7 @@ char *RNA_property_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
first_time = 0;
/* now get every prop of the collection */
- cstring = RNA_pointer_as_string(C, &itemptr);
+ cstring = RNA_pointer_as_string(C, ptr, prop, &itemptr);
BLI_dynstr_append(dynstr, cstring);
MEM_freeN(cstring);
}
@@ -4921,6 +5239,11 @@ const char *RNA_function_identifier(FunctionRNA *func)
const char *RNA_function_ui_description(FunctionRNA *func)
{
+ return TIP_(func->description);
+}
+
+const char *RNA_function_ui_description_raw(FunctionRNA *func)
+{
return func->description;
}
@@ -5635,7 +5958,7 @@ int RNA_function_call_direct_va_lookup(bContext *C, ReportList *reports, Pointer
return 0;
}
-int RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index)
+bool RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index)
{
int len;
@@ -5663,7 +5986,7 @@ int RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index)
int value = RNA_property_boolean_get_default(ptr, prop);
RNA_property_boolean_set(ptr, prop, value);
}
- return 1;
+ return true;
case PROP_INT:
if (len) {
if (index == -1) {
@@ -5683,7 +6006,7 @@ int RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index)
int value = RNA_property_int_get_default(ptr, prop);
RNA_property_int_set(ptr, prop, value);
}
- return 1;
+ return true;
case PROP_FLOAT:
if (len) {
if (index == -1) {
@@ -5703,12 +6026,12 @@ int RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index)
float value = RNA_property_float_get_default(ptr, prop);
RNA_property_float_set(ptr, prop, value);
}
- return 1;
+ return true;
case PROP_ENUM:
{
int value = RNA_property_enum_get_default(ptr, prop);
RNA_property_enum_set(ptr, prop, value);
- return 1;
+ return true;
}
case PROP_STRING:
@@ -5716,23 +6039,23 @@ int RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index)
char *value = RNA_property_string_get_default_alloc(ptr, prop, NULL, 0);
RNA_property_string_set(ptr, prop, value);
MEM_freeN(value);
- return 1;
+ return true;
}
case PROP_POINTER:
{
PointerRNA value = RNA_property_pointer_get_default(ptr, prop);
RNA_property_pointer_set(ptr, prop, value);
- return 1;
+ return true;
}
default:
/* FIXME: are there still any cases that haven't been handled? comment out "default" block to check :) */
- return 0;
+ return false;
}
}
-int RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, int index)
+bool RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, int index)
{
int len, fromlen;
@@ -5741,7 +6064,7 @@ int RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, i
fromlen = RNA_property_array_length(fromptr, prop);
if (len != fromlen)
- return 0;
+ return false;
/* get and set the default values as appropriate for the various types */
switch (RNA_property_type(prop)) {
@@ -5764,7 +6087,7 @@ int RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, i
int value = RNA_property_boolean_get(fromptr, prop);
RNA_property_boolean_set(ptr, prop, value);
}
- return 1;
+ return true;
case PROP_INT:
if (len) {
if (index == -1) {
@@ -5784,7 +6107,7 @@ int RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, i
int value = RNA_property_int_get(fromptr, prop);
RNA_property_int_set(ptr, prop, value);
}
- return 1;
+ return true;
case PROP_FLOAT:
if (len) {
if (index == -1) {
@@ -5804,31 +6127,31 @@ int RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, i
float value = RNA_property_float_get(fromptr, prop);
RNA_property_float_set(ptr, prop, value);
}
- return 1;
+ return true;
case PROP_ENUM:
{
int value = RNA_property_enum_get(fromptr, prop);
RNA_property_enum_set(ptr, prop, value);
- return 1;
+ return true;
}
case PROP_POINTER:
{
PointerRNA value = RNA_property_pointer_get(fromptr, prop);
RNA_property_pointer_set(ptr, prop, value);
- return 1;
+ return true;
}
case PROP_STRING:
{
char *value = RNA_property_string_get_alloc(fromptr, prop, NULL, 0, NULL);
RNA_property_string_set(ptr, prop, value);
MEM_freeN(value);
- return 1;
+ return true;
}
default:
- return 0;
+ return false;
}
- return 0;
+ return false;
}
/* use RNA_warning macro which includes __func__ suffix */
@@ -5864,7 +6187,8 @@ int RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop)
/* get and set the default values as appropriate for the various types */
switch (RNA_property_type(prop)) {
- case PROP_BOOLEAN: {
+ case PROP_BOOLEAN:
+ {
if (len) {
int fixed_a[16], fixed_b[16];
int *array_a, *array_b;
@@ -5889,7 +6213,8 @@ int RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop)
}
}
- case PROP_INT: {
+ case PROP_INT:
+ {
if (len) {
int fixed_a[16], fixed_b[16];
int *array_a, *array_b;
@@ -5914,7 +6239,8 @@ int RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop)
}
}
- case PROP_FLOAT: {
+ case PROP_FLOAT:
+ {
if (len) {
float fixed_a[16], fixed_b[16];
float *array_a, *array_b;
@@ -5939,12 +6265,14 @@ int RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop)
}
}
- case PROP_ENUM: {
+ case PROP_ENUM:
+ {
int value = RNA_property_enum_get(a, prop);
return value == RNA_property_enum_get(b, prop);
}
- case PROP_STRING: {
+ case PROP_STRING:
+ {
char fixed_a[128], fixed_b[128];
int len_a, len_b;
char *value_a = RNA_property_string_get_alloc(a, prop, fixed_a, sizeof(fixed_a), &len_a);
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index 07c394ae4d8..6ab6b8528f9 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -24,23 +24,24 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
-#include "RNA_access.h"
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
-#include "rna_internal.h"
-
#include "DNA_anim_types.h"
#include "DNA_action_types.h"
#include "DNA_scene_types.h"
#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
+
#include "BKE_action.h"
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
#include "WM_types.h"
@@ -157,7 +158,7 @@ static TimeMarker *rna_Action_pose_markers_new(bAction *act, const char name[])
static void rna_Action_pose_markers_remove(bAction *act, ReportList *reports, PointerRNA *marker_ptr)
{
TimeMarker *marker = marker_ptr->data;
- if (BLI_remlink_safe(&act->markers, marker) == FALSE) {
+ if (!BLI_remlink_safe(&act->markers, marker)) {
BKE_reportf(reports, RPT_ERROR, "Timeline marker '%s' not found in action '%s'", marker->name, act->id.name + 2);
return;
}
@@ -395,6 +396,12 @@ static void rna_def_dopesheet(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_LAMP_DATA, 0);
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ prop = RNA_def_property(srna, "show_linestyles", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOLINESTYLE);
+ RNA_def_property_ui_text(prop, "Display Line Style", "Include visualization of Line Style related Animation data");
+ RNA_def_property_ui_icon(prop, ICON_BRUSH_DATA, 0); /* FIXME */
+ RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+
prop = RNA_def_property(srna, "show_textures", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOTEX);
RNA_def_property_ui_text(prop, "Display Texture", "Include visualization of texture related animation data");
diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c
index b653289e44d..2c022e80ddd 100644
--- a/source/blender/makesrna/intern/rna_actuator.c
+++ b/source/blender/makesrna/intern/rna_actuator.c
@@ -27,22 +27,23 @@
#include <stdlib.h>
-#include "RNA_define.h"
-#include "RNA_access.h"
-#include "RNA_enum_types.h"
-
-#include "rna_internal.h"
#include "DNA_constraint_types.h"
#include "DNA_object_types.h"
#include "DNA_actuator_types.h"
#include "DNA_scene_types.h" /* for MAXFRAME */
-#include "WM_types.h"
-
#include "BLI_utildefines.h"
#include "BLF_translation.h"
+#include "RNA_define.h"
+#include "RNA_access.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
+#include "WM_types.h"
+
/* Always keep in alphabetical order */
EnumPropertyItem actuator_type_items[] = {
{ACT_ACTION, "ACTION", 0, "Action", ""},
@@ -389,6 +390,12 @@ static void rna_ObjectActuator_type_set(struct PointerRNA *ptr, int value)
oa->forcerot[1] = 0.5f;
oa->forcerot[2] = 0.0f;
break;
+
+ case ACT_OBJECT_CHARACTER:
+ memset(oa, 0, sizeof(bObjectActuator));
+ oa->flag = ACT_DLOC_LOCAL | ACT_DROT_LOCAL;
+ oa->type = ACT_OBJECT_CHARACTER;
+ break;
}
}
}
@@ -701,6 +708,7 @@ static void rna_def_object_actuator(BlenderRNA *brna)
static EnumPropertyItem prop_type_items[] = {
{ACT_OBJECT_NORMAL, "OBJECT_NORMAL", 0, "Simple Motion", ""},
{ACT_OBJECT_SERVO, "OBJECT_SERVO", 0, "Servo Control", ""},
+ {ACT_OBJECT_CHARACTER, "OBJECT_CHARACTER", 0, "Character Motion", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -867,6 +875,11 @@ static void rna_def_object_actuator(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Add", "Toggles between ADD and SET linV");
RNA_def_property_update(prop, NC_LOGIC, NULL);
+ prop = RNA_def_property(srna, "use_add_character_location", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_ADD_CHAR_LOC);
+ RNA_def_property_ui_text(prop, "Add", "Toggle between ADD and SET character location");
+ RNA_def_property_update(prop, NC_LOGIC, NULL);
+
prop = RNA_def_property(srna, "use_servo_limit_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_SERVO_LIMIT_X);
RNA_def_property_ui_text(prop, "X", "Set limit to force along the X axis");
@@ -881,6 +894,11 @@ static void rna_def_object_actuator(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_SERVO_LIMIT_Z);
RNA_def_property_ui_text(prop, "Z", "Set limit to force along the Z axis");
RNA_def_property_update(prop, NC_LOGIC, NULL);
+
+ prop = RNA_def_property(srna, "use_character_jump", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_CHAR_JUMP);
+ RNA_def_property_ui_text(prop, "Jump", "Make the character jump using the settings in the physics properties");
+ RNA_def_property_update(prop, NC_LOGIC, NULL);
}
static void rna_def_camera_actuator(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index 7229dddf6d6..50f156dd985 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -26,12 +26,6 @@
#include <stdlib.h>
-#include "RNA_access.h"
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
-#include "rna_internal.h"
-
#include "DNA_anim_types.h"
#include "DNA_action_types.h"
#include "DNA_scene_types.h"
@@ -40,10 +34,16 @@
#include "MEM_guardedalloc.h"
-#include "ED_keyframing.h"
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
#include "WM_types.h"
+#include "ED_keyframing.h"
+
/* exported for use in API */
EnumPropertyItem keyingset_path_grouping_items[] = {
{KSP_GROUP_NAMED, "NAMED", 0, "Named Group", ""},
@@ -52,6 +52,20 @@ EnumPropertyItem keyingset_path_grouping_items[] = {
{0, NULL, 0, NULL, NULL}
};
+/* It would be cool to get rid of this 'INSERTKEY_' prefix in 'py strings' values, but it would break existing
+ * exported keyingset... :/
+ */
+EnumPropertyItem keying_flag_items[] = {
+ {INSERTKEY_NEEDED, "INSERTKEY_NEEDED", 0, "Only Needed",
+ "Only insert keyframes where they're needed in the relevant F-Curves"},
+ {INSERTKEY_MATRIX, "INSERTKEY_VISUAL", 0, "Visual Keying",
+ "Insert keyframes based on 'visual transforms'"},
+ {INSERTKEY_XYZ2RGB, "INSERTKEY_XYZ_TO_RGB", 0, "XYZ=RGB Colors",
+ "Color for newly added transformation F-Curves (Location, Rotation, Scale) "
+ "and also Color is based on the transform axis"},
+ {0, NULL, 0, NULL, NULL}
+};
+
#ifdef RNA_RUNTIME
#include "BLI_math_base.h"
@@ -184,6 +198,8 @@ static void rna_KeyingSetInfo_unregister(Main *bmain, StructRNA *type)
RNA_struct_free_extension(type, &ksi->ext);
RNA_struct_free(&BLENDER_RNA, type);
+ WM_main_add_notifier(NC_WINDOW, NULL);
+
/* unlink Blender-side data */
ANIM_keyingset_info_unregister(bmain, ksi);
}
@@ -220,7 +236,7 @@ static StructRNA *rna_KeyingSetInfo_register(Main *bmain, ReportList *reports, v
memcpy(ksi, &dummyksi, sizeof(KeyingSetInfo));
/* set RNA-extensions info */
- ksi->ext.srna = RNA_def_struct(&BLENDER_RNA, ksi->idname, "KeyingSetInfo");
+ ksi->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, ksi->idname, &RNA_KeyingSetInfo);
ksi->ext.data = data;
ksi->ext.call = call;
ksi->ext.free = free;
@@ -235,6 +251,8 @@ static StructRNA *rna_KeyingSetInfo_register(Main *bmain, ReportList *reports, v
/* add and register with other info as needed */
ANIM_keyingset_info_register(ksi);
+ WM_main_add_notifier(NC_WINDOW, NULL);
+
/* return the struct-rna added */
return ksi->ext.srna;
}
@@ -518,17 +536,6 @@ static void rna_def_common_keying_flags(StructRNA *srna, short UNUSED(reg))
{
PropertyRNA *prop;
- static EnumPropertyItem keying_flag_items[] = {
- {INSERTKEY_NEEDED, "INSERTKEY_NEEDED", 0, "Only Needed",
- "Only insert keyframes where they're needed in the relevant F-Curves"},
- {INSERTKEY_MATRIX, "INSERTKEY_VISUAL", 0, "Visual Keying",
- "Insert keyframes based on 'visual transforms'"},
- {INSERTKEY_XYZ2RGB, "INSERTKEY_XYZ_TO_RGB", 0, "XYZ=RGB Colors",
- "Color for newly added transformation F-Curves (Location, Rotation, Scale) "
- "and also Color is based on the transform axis"},
- {0, NULL, 0, NULL, NULL}
- };
-
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);
@@ -574,7 +581,7 @@ static void rna_def_keyingset_info(BlenderRNA *brna)
RNA_def_struct_name_property(srna, prop);
RNA_def_property_flag(prop, PROP_REGISTER);
- prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_TRANSLATE);
+ prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "description");
RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
@@ -774,7 +781,7 @@ static void rna_def_keyingset(BlenderRNA *brna)
RNA_def_struct_name_property(srna, prop);
RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_RENAME, NULL);
- prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_TRANSLATE);
+ prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "description");
RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
@@ -888,6 +895,7 @@ static void rna_def_animdata(BlenderRNA *brna)
srna = RNA_def_struct(brna, "AnimData", NULL);
RNA_def_struct_ui_text(srna, "Animation Data", "Animation data for datablock");
+ RNA_def_struct_ui_icon(srna, ICON_ANIM_DATA);
/* NLA */
prop = RNA_def_property(srna, "nla_tracks", PROP_COLLECTION, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_animviz.c b/source/blender/makesrna/intern/rna_animviz.c
index 68075823a86..9f8f30b00a7 100644
--- a/source/blender/makesrna/intern/rna_animviz.c
+++ b/source/blender/makesrna/intern/rna_animviz.c
@@ -24,19 +24,20 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
#include "RNA_define.h"
-#include "rna_internal.h"
-
#include "DNA_anim_types.h"
#include "DNA_action_types.h"
#include "DNA_scene_types.h"
+#include "BLI_utildefines.h"
+
#include "MEM_guardedalloc.h"
+#include "rna_internal.h"
+
#include "WM_types.h"
/* Which part of bone(s) get baked */
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index 4c566d71981..1bc6c7e4f6f 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -207,7 +207,7 @@ static char *rna_Bone_path(PointerRNA *ptr)
return BLI_sprintfN("bones[\"%s\"]", bone->name);
}
-static IDProperty *rna_Bone_idprops(PointerRNA *ptr, int create)
+static IDProperty *rna_Bone_idprops(PointerRNA *ptr, bool create)
{
Bone *bone = ptr->data;
@@ -219,7 +219,7 @@ static IDProperty *rna_Bone_idprops(PointerRNA *ptr, int create)
return bone->prop;
}
-static IDProperty *rna_EditBone_idprops(PointerRNA *ptr, int create)
+static IDProperty *rna_EditBone_idprops(PointerRNA *ptr, bool create)
{
EditBone *ebone = ptr->data;
@@ -529,6 +529,11 @@ static void rna_def_bone_common(StructRNA *srna, int editbone)
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_NO_LOCAL_LOCATION);
RNA_def_property_update(prop, 0, "rna_Armature_update_data");
+ prop = RNA_def_property(srna, "use_relative_parent", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Relative Parenting", "Object children will use relative transform, like deform");
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_RELATIVE_PARENTING);
+ RNA_def_property_update(prop, 0, "rna_Armature_update_data");
+
prop = RNA_def_property(srna, "show_wire", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_DRAWWIRE);
RNA_def_property_ui_text(prop, "Draw Wire",
diff --git a/source/blender/makesrna/intern/rna_boid.c b/source/blender/makesrna/intern/rna_boid.c
index 3da718afd1c..9d44ae87b57 100644
--- a/source/blender/makesrna/intern/rna_boid.c
+++ b/source/blender/makesrna/intern/rna_boid.c
@@ -29,20 +29,21 @@
* \ingroup RNA
*/
-
#include <float.h>
#include <limits.h>
#include <stdlib.h>
-#include "RNA_define.h"
-
-#include "rna_internal.h"
-
#include "DNA_scene_types.h"
#include "DNA_boid_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
+#include "BLI_utildefines.h"
+
+#include "RNA_define.h"
+
+#include "rna_internal.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -100,7 +101,7 @@ static void rna_Boids_reset(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRN
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
}
-static void rna_Boids_reset_deps(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Boids_reset_deps(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
if (ptr->type == &RNA_ParticleSystem) {
ParticleSystem *psys = (ParticleSystem *)ptr->data;
@@ -112,7 +113,7 @@ static void rna_Boids_reset_deps(Main *bmain, Scene *scene, PointerRNA *ptr)
else
DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA | PSYS_RECALC_RESET);
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
}
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 7bdebd620ee..8480427c433 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -24,14 +24,11 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
#include <assert.h>
#include "RNA_define.h"
-#include "rna_internal.h"
-
#include "DNA_brush_types.h"
#include "DNA_texture_types.h"
#include "DNA_scene_types.h"
@@ -39,6 +36,8 @@
#include "BLI_math.h"
+#include "rna_internal.h"
+
#include "IMB_imbuf.h"
#include "WM_types.h"
@@ -65,6 +64,7 @@ EnumPropertyItem brush_sculpt_tool_items[] = {
{SCULPT_TOOL_PINCH, "PINCH", ICON_BRUSH_PINCH, "Pinch", ""},
{SCULPT_TOOL_ROTATE, "ROTATE", ICON_BRUSH_ROTATE, "Rotate", ""},
{SCULPT_TOOL_SCRAPE, "SCRAPE", ICON_BRUSH_SCRAPE, "Scrape", ""},
+ {SCULPT_TOOL_SIMPLIFY, "SIMPLIFY", ICON_BRUSH_SUBTRACT /* icon TODO */, "Simplify", ""},
{SCULPT_TOOL_SMOOTH, "SMOOTH", ICON_BRUSH_SMOOTH, "Smooth", ""},
{SCULPT_TOOL_SNAKE_HOOK, "SNAKE_HOOK", ICON_BRUSH_SNAKE_HOOK, "Snake Hook", ""},
{SCULPT_TOOL_THUMB, "THUMB", ICON_BRUSH_THUMB, "Thumb", ""},
@@ -106,7 +106,7 @@ EnumPropertyItem brush_image_tool_items[] = {
#include "WM_api.h"
-static int rna_SculptCapabilities_has_accumulate_get(PointerRNA *ptr)
+static int rna_SculptToolCapabilities_has_accumulate_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ELEM6(br->sculpt_tool,
@@ -114,19 +114,19 @@ static int rna_SculptCapabilities_has_accumulate_get(PointerRNA *ptr)
SCULPT_TOOL_DRAW, SCULPT_TOOL_INFLATE, SCULPT_TOOL_LAYER);
}
-static int rna_SculptCapabilities_has_auto_smooth_get(PointerRNA *ptr)
+static int rna_SculptToolCapabilities_has_auto_smooth_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return !ELEM(br->sculpt_tool, SCULPT_TOOL_MASK, SCULPT_TOOL_SMOOTH);
}
-static int rna_SculptCapabilities_has_height_get(PointerRNA *ptr)
+static int rna_SculptToolCapabilities_has_height_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return br->sculpt_tool == SCULPT_TOOL_LAYER;
}
-static int rna_SculptCapabilities_has_jitter_get(PointerRNA *ptr)
+static int rna_SculptToolCapabilities_has_jitter_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return (!(br->flag & BRUSH_ANCHORED) &&
@@ -136,13 +136,13 @@ static int rna_SculptCapabilities_has_jitter_get(PointerRNA *ptr)
SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
}
-static int rna_SculptCapabilities_has_normal_weight_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);
}
-static int rna_SculptCapabilities_has_overlay_get(PointerRNA *ptr)
+static int rna_BrushCapabilities_has_overlay_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ELEM(br->mtex.brush_map_mode,
@@ -150,38 +150,43 @@ static int rna_SculptCapabilities_has_overlay_get(PointerRNA *ptr)
MTEX_MAP_MODE_TILED);
}
-static int rna_SculptCapabilities_has_persistence_get(PointerRNA *ptr)
+static int rna_SculptToolCapabilities_has_persistence_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return br->sculpt_tool == SCULPT_TOOL_LAYER;
}
-static int rna_SculptCapabilities_has_pinch_factor_get(PointerRNA *ptr)
+static int rna_SculptToolCapabilities_has_pinch_factor_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ELEM(br->sculpt_tool, SCULPT_TOOL_BLOB, SCULPT_TOOL_CREASE);
}
-static int rna_SculptCapabilities_has_plane_offset_get(PointerRNA *ptr)
+static int rna_SculptToolCapabilities_has_plane_offset_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ELEM5(br->sculpt_tool, SCULPT_TOOL_CLAY, SCULPT_TOOL_CLAY_STRIPS,
SCULPT_TOOL_FILL, SCULPT_TOOL_FLATTEN, SCULPT_TOOL_SCRAPE);
}
-static int rna_SculptCapabilities_has_random_texture_angle_get(PointerRNA *ptr)
+static int rna_SculptToolCapabilities_has_random_texture_angle_get(PointerRNA *ptr)
+{
+ Brush *br = (Brush *)ptr->data;
+ return (!ELEM4(br->sculpt_tool,
+ SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
+}
+
+static int rna_BrushCapabilities_has_random_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) &&
- !(br->flag & BRUSH_ANCHORED) &&
- !ELEM4(br->sculpt_tool,
- SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
+ !(br->flag & BRUSH_ANCHORED));
}
-static int rna_SculptCapabilities_has_sculpt_plane_get(PointerRNA *ptr)
+static int rna_SculptToolCapabilities_has_sculpt_plane_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return !ELEM4(br->sculpt_tool, SCULPT_TOOL_INFLATE,
@@ -189,7 +194,7 @@ static int rna_SculptCapabilities_has_sculpt_plane_get(PointerRNA *ptr)
SCULPT_TOOL_SMOOTH);
}
-static int rna_SculptCapabilities_has_secondary_color_get(PointerRNA *ptr)
+static int rna_SculptToolCapabilities_has_secondary_color_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ELEM10(br->sculpt_tool,
@@ -199,7 +204,7 @@ static int rna_SculptCapabilities_has_secondary_color_get(PointerRNA *ptr)
SCULPT_TOOL_SCRAPE);
}
-static int rna_SculptCapabilities_has_smooth_stroke_get(PointerRNA *ptr)
+static int rna_SculptToolCapabilities_has_smooth_stroke_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return (!(br->flag & BRUSH_ANCHORED) &&
@@ -209,7 +214,7 @@ static int rna_SculptCapabilities_has_smooth_stroke_get(PointerRNA *ptr)
SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
}
-static int rna_SculptCapabilities_has_space_attenuation_get(PointerRNA *ptr)
+static int rna_SculptToolCapabilities_has_space_attenuation_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ((br->flag & BRUSH_SPACE) &&
@@ -217,22 +222,19 @@ static int rna_SculptCapabilities_has_space_attenuation_get(PointerRNA *ptr)
SCULPT_TOOL_SMOOTH, SCULPT_TOOL_SNAKE_HOOK));
}
-static int rna_SculptCapabilities_has_spacing_get(PointerRNA *ptr)
+static int rna_BrushCapabilities_has_spacing_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return (!(br->flag & BRUSH_ANCHORED) &&
- !ELEM4(br->sculpt_tool,
- SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
+ return (!(br->flag & BRUSH_ANCHORED));
}
-static int rna_SculptCapabilities_has_strength_get(PointerRNA *ptr)
+static int rna_SculptToolCapabilities_has_strength_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return !ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK);
}
-static int rna_SculptCapabilities_has_texture_angle_get(PointerRNA *ptr)
+static int rna_BrushCapabilities_has_texture_angle_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ELEM3(br->mtex.brush_map_mode,
@@ -241,7 +243,7 @@ static int rna_SculptCapabilities_has_texture_angle_get(PointerRNA *ptr)
MTEX_MAP_MODE_TILED);
}
-static int rna_SculptCapabilities_has_texture_angle_source_get(PointerRNA *ptr)
+static int rna_BrushCapabilities_has_texture_angle_source_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ELEM(br->mtex.brush_map_mode,
@@ -249,9 +251,14 @@ static int rna_SculptCapabilities_has_texture_angle_source_get(PointerRNA *ptr)
MTEX_MAP_MODE_AREA);
}
-static PointerRNA rna_Brush_sculpt_capabilities_get(PointerRNA *ptr)
+static PointerRNA rna_Sculpt_sculpt_tool_capabilities_get(PointerRNA *ptr)
+{
+ return rna_pointer_inherit_refine(ptr, &RNA_SculptToolCapabilities, ptr->id.data);
+}
+
+static PointerRNA rna_Brush_capabilities_get(PointerRNA *ptr)
{
- return rna_pointer_inherit_refine(ptr, &RNA_SculptCapabilities, ptr->id.data);
+ return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilities, ptr->id.data);
}
static void rna_Brush_reset_icon(Brush *br, const char *UNUSED(type))
@@ -428,6 +435,13 @@ static void rna_def_brush_texture_slot(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem prop_tex_paint_map_mode_items[] = {
+ {MTEX_MAP_MODE_VIEW, "VIEW_PLANE", 0, "View Plane", ""},
+ {MTEX_MAP_MODE_TILED, "TILED", 0, "Tiled", ""},
+ {MTEX_MAP_MODE_3D, "3D", 0, "3D", ""},
+ {0, NULL, 0, NULL, 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");
@@ -443,6 +457,12 @@ static void rna_def_brush_texture_slot(BlenderRNA *brna)
RNA_def_property_enum_items(prop, prop_map_mode_items);
RNA_def_property_ui_text(prop, "Mode", "");
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
+
+ prop = RNA_def_property(srna, "tex_paint_map_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "brush_map_mode");
+ RNA_def_property_enum_items(prop, prop_tex_paint_map_mode_items);
+ RNA_def_property_ui_text(prop, "Mode", "");
+ RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
}
static void rna_def_sculpt_capabilities(BlenderRNA *brna)
@@ -450,41 +470,66 @@ static void rna_def_sculpt_capabilities(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
- srna = RNA_def_struct(brna, "SculptCapabilities", NULL);
+ srna = RNA_def_struct(brna, "SculptToolCapabilities", NULL);
RNA_def_struct_sdna(srna, "Brush");
RNA_def_struct_nested(brna, srna, "Brush");
RNA_def_struct_ui_text(srna, "Sculpt Capabilities",
"Read-only indications of which brush operations "
"are supported by the current sculpt tool");
+#define SCULPT_TOOL_CAPABILITY(prop_name_, ui_name_) \
+ prop = RNA_def_property(srna, #prop_name_, \
+ PROP_BOOLEAN, PROP_NONE); \
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE); \
+ RNA_def_property_boolean_funcs(prop, "rna_SculptToolCapabilities_" \
+ #prop_name_ "_get", NULL); \
+ RNA_def_property_ui_text(prop, ui_name_, NULL)
+
+ SCULPT_TOOL_CAPABILITY(has_accumulate, "Has Accumulate");
+ SCULPT_TOOL_CAPABILITY(has_auto_smooth, "Has Auto Smooth");
+ SCULPT_TOOL_CAPABILITY(has_height, "Has Height");
+ SCULPT_TOOL_CAPABILITY(has_jitter, "Has Jitter");
+ SCULPT_TOOL_CAPABILITY(has_normal_weight, "Has Crease/Pinch Factor");
+ SCULPT_TOOL_CAPABILITY(has_persistence, "Has Persistence");
+ SCULPT_TOOL_CAPABILITY(has_pinch_factor, "Has Pinch Factor");
+ SCULPT_TOOL_CAPABILITY(has_plane_offset, "Has Plane Offset");
+ SCULPT_TOOL_CAPABILITY(has_random_texture_angle, "Has Random Texture Angle");
+ SCULPT_TOOL_CAPABILITY(has_sculpt_plane, "Has Sculpt Plane");
+ 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");
+
+#undef SCULPT_CAPABILITY
+}
+
+static void rna_def_brush_capabilities(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "BrushCapabilities", NULL);
+ RNA_def_struct_sdna(srna, "Brush");
+ RNA_def_struct_nested(brna, srna, "Brush");
+ RNA_def_struct_ui_text(srna, "Brush Capabilities",
+ "Read-only indications of which brush operations "
+ "are supported by the current brush");
+
#define BRUSH_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_SculptCapabilities_" \
+ RNA_def_property_boolean_funcs(prop, "rna_BrushCapabilities_" \
#prop_name_ "_get", NULL); \
RNA_def_property_ui_text(prop, ui_name_, NULL)
- BRUSH_CAPABILITY(has_accumulate, "Has Accumulate");
- BRUSH_CAPABILITY(has_auto_smooth, "Has Auto Smooth");
- BRUSH_CAPABILITY(has_height, "Has Height");
- BRUSH_CAPABILITY(has_jitter, "Has Jitter");
- BRUSH_CAPABILITY(has_normal_weight, "Has Crease/Pinch Factor");
BRUSH_CAPABILITY(has_overlay, "Has Overlay");
- BRUSH_CAPABILITY(has_persistence, "Has Persistence");
- BRUSH_CAPABILITY(has_pinch_factor, "Has Pinch Factor");
- BRUSH_CAPABILITY(has_plane_offset, "Has Plane Offset");
BRUSH_CAPABILITY(has_random_texture_angle, "Has Random Texture Angle");
- BRUSH_CAPABILITY(has_sculpt_plane, "Has Sculpt Plane");
- BRUSH_CAPABILITY(has_secondary_color, "Has Secondary Color");
- BRUSH_CAPABILITY(has_smooth_stroke, "Has Smooth Stroke");
- BRUSH_CAPABILITY(has_space_attenuation, "Has Space Attenuation");
- BRUSH_CAPABILITY(has_spacing, "Has Spacing");
- BRUSH_CAPABILITY(has_strength, "Has Strength");
BRUSH_CAPABILITY(has_texture_angle, "Has Texture Angle");
BRUSH_CAPABILITY(has_texture_angle_source, "Has Texture Angle Source");
+ BRUSH_CAPABILITY(has_spacing, "Has Spacing");
-#undef SCULPT_CAPABILITY
+#undef BRUSH_CAPABILITY
}
static void rna_def_brush(BlenderRNA *brna)
@@ -604,7 +649,7 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Brush_update");
/* number values */
- prop = RNA_def_property(srna, "size", PROP_INT, PROP_DISTANCE);
+ prop = RNA_def_property(srna, "size", PROP_INT, PROP_NONE);
RNA_def_property_int_funcs(prop, NULL, "rna_Brush_set_size", NULL);
RNA_def_property_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS * 10);
RNA_def_property_ui_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS, 1, 0);
@@ -620,10 +665,17 @@ static void rna_def_brush(BlenderRNA *brna)
prop = RNA_def_property(srna, "jitter", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "jitter");
- RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_range(prop, 0.0f, 1000.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 2.0f, 0.1, 4);
RNA_def_property_ui_text(prop, "Jitter", "Jitter the position of the brush while painting");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "jitter_absolute", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "jitter_absolute");
+ RNA_def_property_range(prop, 0, 1000000);
+ RNA_def_property_ui_text(prop, "Jitter", "Jitter the position of the brush in pixels while painting");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "spacing", PROP_INT, PROP_PERCENTAGE);
RNA_def_property_int_sdna(prop, NULL, "spacing");
RNA_def_property_range(prop, 1, 1000);
@@ -631,7 +683,7 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Spacing", "Spacing between brush daubs as a percentage of brush diameter");
RNA_def_property_update(prop, 0, "rna_Brush_update");
- prop = RNA_def_property(srna, "smooth_stroke_radius", PROP_INT, PROP_DISTANCE);
+ prop = RNA_def_property(srna, "smooth_stroke_radius", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 10, 200);
RNA_def_property_ui_text(prop, "Smooth Stroke Radius", "Minimum distance from last point before stroke continues");
RNA_def_property_update(prop, 0, "rna_Brush_update");
@@ -780,6 +832,11 @@ static void rna_def_brush(BlenderRNA *brna)
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_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");
@@ -854,11 +911,6 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_RESTORE_MESH);
RNA_def_property_ui_text(prop, "Restore Mesh", "Allow a single dot to be carefully positioned");
RNA_def_property_update(prop, 0, "rna_Brush_update");
-
- prop = RNA_def_property(srna, "use_fixed_texture", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_FIXED_TEX);
- RNA_def_property_ui_text(prop, "Fixed Texture", "Keep texture origin in fixed position");
- RNA_def_property_update(prop, 0, "rna_Brush_update");
/* only for projection paint, TODO, other paint modes */
prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE);
@@ -948,11 +1000,17 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_range(prop, -1.0f, 1.0f, 10.0f, 3);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, "rna_Brush_update");
+ prop = RNA_def_property(srna, "brush_capabilities", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "BrushCapabilities");
+ RNA_def_property_pointer_funcs(prop, "rna_Brush_capabilities_get", NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Brush Capabilities", "Brush's capabilities");
+
/* brush capabilities (mode-dependent) */
prop = RNA_def_property(srna, "sculpt_capabilities", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_struct_type(prop, "SculptCapabilities");
- RNA_def_property_pointer_funcs(prop, "rna_Brush_sculpt_capabilities_get", NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "SculptToolCapabilities");
+ RNA_def_property_pointer_funcs(prop, "rna_Sculpt_sculpt_tool_capabilities_get", NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Sculpt Capabilities", "Brush's capabilities in sculpt mode");
}
@@ -1014,6 +1072,7 @@ static void rna_def_operator_stroke_element(BlenderRNA *brna)
void RNA_def_brush(BlenderRNA *brna)
{
rna_def_brush(brna);
+ rna_def_brush_capabilities(brna);
rna_def_sculpt_capabilities(brna);
rna_def_brush_texture_slot(brna);
rna_def_operator_stroke_element(brna);
diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c
index b72bba0422a..5743fcf2b9f 100644
--- a/source/blender/makesrna/intern/rna_camera.c
+++ b/source/blender/makesrna/intern/rna_camera.c
@@ -24,17 +24,16 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
-#include "RNA_define.h"
-
-#include "rna_internal.h"
-
#include "DNA_camera_types.h"
#include "BLI_math.h"
+#include "RNA_define.h"
+
+#include "rna_internal.h"
+
#include "WM_types.h"
#ifdef RNA_RUNTIME
@@ -112,8 +111,8 @@ void RNA_def_camera(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem prop_lens_unit_items[] = {
- {0, "MILLIMETERS", 0, "Millimeters", ""},
- {CAM_ANGLETOGGLE, "DEGREES", 0, "Degrees", ""},
+ {0, "MILLIMETERS", 0, "Millimeters", "Specify the lens in millimeters"},
+ {CAM_ANGLETOGGLE, "FOV", 0, "Field of View", "Specify the lens as the field of view's angle"},
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem sensor_fit_items[] = {
@@ -154,23 +153,23 @@ void RNA_def_camera(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
prop = RNA_def_property(srna, "angle_x", PROP_FLOAT, PROP_ANGLE);
- RNA_def_property_range(prop, M_PI * (0.367 / 180.0), M_PI * (172.847 / 180.0));
+ RNA_def_property_range(prop, DEG2RAD(0.367), DEG2RAD(172.847));
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Horizontal FOV", "Camera lens horizontal field of view in degrees");
+ RNA_def_property_ui_text(prop, "Horizontal FOV", "Camera lens horizontal field of view");
RNA_def_property_float_funcs(prop, "rna_Camera_angle_x_get", "rna_Camera_angle_x_set", NULL);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update");
prop = RNA_def_property(srna, "angle_y", PROP_FLOAT, PROP_ANGLE);
- RNA_def_property_range(prop, M_PI * (0.367 / 180.0), M_PI * (172.847 / 180.0));
+ RNA_def_property_range(prop, DEG2RAD(0.367), DEG2RAD(172.847));
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Vertical FOV", "Camera lens vertical field of view in degrees");
+ RNA_def_property_ui_text(prop, "Vertical FOV", "Camera lens vertical field of view");
RNA_def_property_float_funcs(prop, "rna_Camera_angle_y_get", "rna_Camera_angle_y_set", NULL);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update");
prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
- RNA_def_property_range(prop, M_PI * (0.367 / 180.0), M_PI * (172.847 / 180.0));
+ RNA_def_property_range(prop, DEG2RAD(0.367), DEG2RAD(172.847));
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Field of View", "Camera lens field of view in degrees");
+ RNA_def_property_ui_text(prop, "Field of View", "Camera lens field of view");
RNA_def_property_float_funcs(prop, "rna_Camera_angle_get", "rna_Camera_angle_set", NULL);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update");
@@ -186,20 +185,20 @@ void RNA_def_camera(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Clip End", "Camera far clipping distance");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
- prop = RNA_def_property(srna, "lens", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "lens", PROP_FLOAT, PROP_DISTANCE_CAMERA);
RNA_def_property_float_sdna(prop, NULL, "lens");
RNA_def_property_range(prop, 1.0f, 5000.0f);
RNA_def_property_ui_text(prop, "Focal Length", "Perspective Camera lens value in millimeters");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update");
- prop = RNA_def_property(srna, "sensor_width", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "sensor_width", PROP_FLOAT, PROP_DISTANCE_CAMERA);
RNA_def_property_float_sdna(prop, NULL, "sensor_x");
RNA_def_property_range(prop, 1.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 1.0f, 100.f, 1, 2);
RNA_def_property_ui_text(prop, "Sensor Width", "Horizontal size of the image sensor area in millimeters");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update");
- prop = RNA_def_property(srna, "sensor_height", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "sensor_height", PROP_FLOAT, PROP_DISTANCE_CAMERA);
RNA_def_property_float_sdna(prop, NULL, "sensor_y");
RNA_def_property_range(prop, 1.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 1.0f, 100.f, 1, 2);
@@ -208,7 +207,8 @@ void RNA_def_camera(BlenderRNA *brna)
prop = RNA_def_property(srna, "ortho_scale", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "ortho_scale");
- RNA_def_property_range(prop, 0.01f, 4000.0f);
+ RNA_def_property_range(prop, FLT_MIN, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.001f, 10000.0f, 10, 3);
RNA_def_property_ui_text(prop, "Orthographic Scale", "Orthographic Camera scale (similar to zoom)");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update");
diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c
index b9e86e116a2..1bf15fd0838 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -24,14 +24,9 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
#include <limits.h>
-#include "RNA_define.h"
-
-#include "rna_internal.h"
-
#include "BKE_cloth.h"
#include "BKE_modifier.h"
@@ -39,6 +34,10 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "RNA_define.h"
+
+#include "rna_internal.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -403,8 +402,8 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
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, 200);
- RNA_def_property_ui_text(prop, "Pre Roll", "Simulation starts on this frame");
+ 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);
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index 5752fd318c7..640e91adabf 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -24,16 +24,17 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
#include <stdio.h>
-#include "RNA_define.h"
-#include "rna_internal.h"
-
#include "DNA_color_types.h"
#include "DNA_texture_types.h"
+#include "BLI_utildefines.h"
+
+#include "RNA_define.h"
+#include "rna_internal.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -56,6 +57,7 @@
#include "BKE_node.h"
#include "BKE_sequencer.h"
#include "BKE_texture.h"
+#include "BKE_linestyle.h"
#include "ED_node.h"
@@ -184,6 +186,14 @@ static char *rna_ColorRamp_path(PointerRNA *ptr)
break;
}
+ case ID_LS:
+ {
+ char *path = BKE_path_from_ID_to_color_ramp((FreestyleLineStyle *)id, (ColorBand *)ptr->data);
+ if (path)
+ return path;
+ break;
+ }
+
default:
/* everything else just uses 'color_ramp' */
path = BLI_strdup("color_ramp");
@@ -259,6 +269,20 @@ static char *rna_ColorRampElement_path(PointerRNA *ptr)
}
break;
+ case ID_LS:
+ {
+ ListBase listbase;
+ LinkData *link;
+
+ BKE_list_modifier_color_ramps((FreestyleLineStyle *)id, &listbase);
+ for (link = (LinkData *)listbase.first; link; link = link->next) {
+ RNA_pointer_create(id, &RNA_ColorRamp, link->data, &ramp_ptr);
+ COLRAMP_GETPATH;
+ }
+ BLI_freelistN(&listbase);
+ break;
+ }
+
default: /* everything else should have a "color_ramp" property */
{
/* create pointer to the ID block, and try to resolve "color_ramp" pointer */
@@ -297,7 +321,7 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *
for (node = ntree->nodes.first; node; node = node->next) {
if (ELEM3(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) {
- ED_node_generic_update(bmain, ntree, node);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
}
}
@@ -310,6 +334,13 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *
WM_main_add_notifier(NC_TEXTURE, tex);
}
break;
+ case ID_LS:
+ {
+ FreestyleLineStyle *linestyle= ptr->id.data;
+
+ WM_main_add_notifier(NC_LINESTYLE, linestyle);
+ break;
+ }
default:
break;
}
@@ -377,7 +408,8 @@ static void rna_ColorManagedDisplaySettings_display_device_set(struct PointerRNA
}
}
-static EnumPropertyItem *rna_ColorManagedDisplaySettings_display_device_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free)
+static EnumPropertyItem *rna_ColorManagedDisplaySettings_display_device_itemf(bContext *UNUSED(C), PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop), int *free)
{
EnumPropertyItem *items = NULL;
int totitem = 0;
@@ -424,7 +456,8 @@ static void rna_ColorManagedViewSettings_view_transform_set(PointerRNA *ptr, int
}
}
-static EnumPropertyItem* rna_ColorManagedViewSettings_view_transform_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free)
+static EnumPropertyItem *rna_ColorManagedViewSettings_view_transform_itemf(bContext *C, PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop), int *free)
{
Scene *scene = CTX_data_scene(C);
EnumPropertyItem *items = NULL;
@@ -471,7 +504,8 @@ static void rna_ColorManagedColorspaceSettings_colorspace_set(struct PointerRNA
}
}
-static EnumPropertyItem *rna_ColorManagedColorspaceSettings_colorspace_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free)
+static EnumPropertyItem *rna_ColorManagedColorspaceSettings_colorspace_itemf(bContext *UNUSED(C), PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop), int *free)
{
EnumPropertyItem *items = NULL;
int totitem = 0;
@@ -848,7 +882,7 @@ static void rna_def_histogram(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_line", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", HISTO_FLAG_LINE);
- RNA_def_property_ui_text(prop, "Show Line", "Display lines rather then filled shapes");
+ RNA_def_property_ui_text(prop, "Show Line", "Display lines rather than filled shapes");
RNA_def_property_ui_icon(prop, ICON_IPO, 0);
}
@@ -973,15 +1007,28 @@ static void rna_def_colormanage(BlenderRNA *brna)
RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update");
/* ** Colorspace ** */
- srna = RNA_def_struct(brna, "ColorManagedColorspaceSettings", NULL);
- RNA_def_struct_ui_text(srna, "ColorManagedColorspaceSettings", "Input color space settings");
+ srna = RNA_def_struct(brna, "ColorManagedInputColorspaceSettings", NULL);
+ RNA_def_struct_ui_text(srna, "ColorManagedInputColorspaceSettings", "Input color space settings");
+
+ prop = RNA_def_property(srna, "name", PROP_ENUM, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT);
+ RNA_def_property_enum_items(prop, color_space_items);
+ RNA_def_property_enum_funcs(prop, "rna_ColorManagedColorspaceSettings_colorspace_get",
+ "rna_ColorManagedColorspaceSettings_colorspace_set",
+ "rna_ColorManagedColorspaceSettings_colorspace_itemf");
+ RNA_def_property_ui_text(prop, "Input Color Space", "Color space of the image or movie on disk");
+ RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedColorspaceSettings_reload_update");
+
+ srna = RNA_def_struct(brna, "ColorManagedSequencerColorspaceSettings", NULL);
+ RNA_def_struct_ui_text(srna, "ColorManagedSequencerColorspaceSettings", "Input color space settings");
prop = RNA_def_property(srna, "name", PROP_ENUM, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT);
RNA_def_property_enum_items(prop, color_space_items);
RNA_def_property_enum_funcs(prop, "rna_ColorManagedColorspaceSettings_colorspace_get",
"rna_ColorManagedColorspaceSettings_colorspace_set",
"rna_ColorManagedColorspaceSettings_colorspace_itemf");
- RNA_def_property_ui_text(prop, "Color Space", "Input color space name");
+ RNA_def_property_ui_text(prop, "Color Space", "Color space that the sequencer operates in");
RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedColorspaceSettings_reload_update");
}
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 30a9bfd81f6..c96ea72fee2 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -24,13 +24,8 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
-#include "RNA_define.h"
-
-#include "rna_internal.h"
-
#include "BLI_math.h"
#include "BLF_translation.h"
@@ -41,46 +36,73 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "ED_object.h"
+#include "RNA_define.h"
+
+#include "rna_internal.h"
+
#include "WM_types.h"
+#include "ED_object.h"
+
/* please keep the names in sync with constraint.c */
EnumPropertyItem constraint_type_items[] = {
{0, "", 0, N_("Motion Tracking"), ""},
{CONSTRAINT_TYPE_CAMERASOLVER, "CAMERA_SOLVER", ICON_CONSTRAINT_DATA, "Camera Solver", ""},
+ {CONSTRAINT_TYPE_FOLLOWTRACK, "FOLLOW_TRACK", ICON_CONSTRAINT_DATA, "Follow Track", ""},
{CONSTRAINT_TYPE_OBJECTSOLVER, "OBJECT_SOLVER", ICON_CONSTRAINT_DATA, "Object Solver", ""},
- {CONSTRAINT_TYPE_FOLLOWTRACK, "FOLLOW_TRACK", ICON_CONSTRAINT_DATA, "Follow Track", ""},
{0, "", 0, N_("Transform"), ""},
- {CONSTRAINT_TYPE_LOCLIKE, "COPY_LOCATION", ICON_CONSTRAINT_DATA, "Copy Location", ""},
- {CONSTRAINT_TYPE_ROTLIKE, "COPY_ROTATION", ICON_CONSTRAINT_DATA, "Copy Rotation", ""},
- {CONSTRAINT_TYPE_SIZELIKE, "COPY_SCALE", ICON_CONSTRAINT_DATA, "Copy Scale", ""},
- {CONSTRAINT_TYPE_TRANSLIKE, "COPY_TRANSFORMS", ICON_CONSTRAINT_DATA, "Copy Transforms", ""},
- {CONSTRAINT_TYPE_DISTLIMIT, "LIMIT_DISTANCE", ICON_CONSTRAINT_DATA, "Limit Distance", ""},
- {CONSTRAINT_TYPE_LOCLIMIT, "LIMIT_LOCATION", ICON_CONSTRAINT_DATA, "Limit Location", ""},
- {CONSTRAINT_TYPE_ROTLIMIT, "LIMIT_ROTATION", ICON_CONSTRAINT_DATA, "Limit Rotation", ""},
- {CONSTRAINT_TYPE_SIZELIMIT, "LIMIT_SCALE", ICON_CONSTRAINT_DATA, "Limit Scale", ""},
- {CONSTRAINT_TYPE_SAMEVOL, "MAINTAIN_VOLUME", ICON_CONSTRAINT_DATA, "Maintain Volume", ""},
- {CONSTRAINT_TYPE_TRANSFORM, "TRANSFORM", ICON_CONSTRAINT_DATA, "Transformation", ""},
+ {CONSTRAINT_TYPE_LOCLIKE, "COPY_LOCATION", ICON_CONSTRAINT_DATA, "Copy Location",
+ "Copy the location of a target (with an optional offset), so that they move together"},
+ {CONSTRAINT_TYPE_ROTLIKE, "COPY_ROTATION", ICON_CONSTRAINT_DATA, "Copy Rotation",
+ "Copy the rotation of a target (with an optional offset), so that they rotate together"},
+ {CONSTRAINT_TYPE_SIZELIKE, "COPY_SCALE", ICON_CONSTRAINT_DATA, "Copy Scale",
+ "Copy the scale factors of a target (with an optional offset), so that they are scaled by the same amount"},
+ {CONSTRAINT_TYPE_TRANSLIKE, "COPY_TRANSFORMS", ICON_CONSTRAINT_DATA, "Copy Transforms",
+ "Copy all the transformations of a target, so that they move together"},
+ {CONSTRAINT_TYPE_DISTLIMIT, "LIMIT_DISTANCE", ICON_CONSTRAINT_DATA, "Limit Distance",
+ "Restrict movements to within a certain distance of a target (at the time of constraint evaluation only)"},
+ {CONSTRAINT_TYPE_LOCLIMIT, "LIMIT_LOCATION", ICON_CONSTRAINT_DATA, "Limit Location",
+ "Restrict movement along each axis within given ranges"},
+ {CONSTRAINT_TYPE_ROTLIMIT, "LIMIT_ROTATION", ICON_CONSTRAINT_DATA, "Limit Rotation",
+ "Restrict rotation along each axis within given ranges"},
+ {CONSTRAINT_TYPE_SIZELIMIT, "LIMIT_SCALE", ICON_CONSTRAINT_DATA, "Limit Scale",
+ "Restrict scaling along each axis with given ranges"},
+ {CONSTRAINT_TYPE_SAMEVOL, "MAINTAIN_VOLUME", ICON_CONSTRAINT_DATA, "Maintain Volume",
+ "Compensate for scaling one axis by applying suitable scaling to the other two axes"},
+ {CONSTRAINT_TYPE_TRANSFORM, "TRANSFORM", ICON_CONSTRAINT_DATA, "Transformation",
+ "Use one transform property from target to control another (or same) property on owner"},
{0, "", 0, N_("Tracking"), ""},
- {CONSTRAINT_TYPE_CLAMPTO, "CLAMP_TO", ICON_CONSTRAINT_DATA, "Clamp To", ""},
+ {CONSTRAINT_TYPE_CLAMPTO, "CLAMP_TO", ICON_CONSTRAINT_DATA, "Clamp To",
+ "Restrict movements to lie along a curve by remapping location along curve's longest axis"},
{CONSTRAINT_TYPE_DAMPTRACK, "DAMPED_TRACK", ICON_CONSTRAINT_DATA, "Damped Track",
- "Tracking by taking the shortest path"},
- {CONSTRAINT_TYPE_KINEMATIC, "IK", ICON_CONSTRAINT_DATA, "Inverse Kinematics", ""},
+ "Point towards a target by performing the smallest rotation necessary"},
+ {CONSTRAINT_TYPE_KINEMATIC, "IK", ICON_CONSTRAINT_DATA, "Inverse Kinematics",
+ "Control a chain of bones by specifying the endpoint target (Bones only)"},
{CONSTRAINT_TYPE_LOCKTRACK, "LOCKED_TRACK", ICON_CONSTRAINT_DATA, "Locked Track",
- "Tracking along a single axis"},
- {CONSTRAINT_TYPE_SPLINEIK, "SPLINE_IK", ICON_CONSTRAINT_DATA, "Spline IK", ""},
- {CONSTRAINT_TYPE_STRETCHTO, "STRETCH_TO", ICON_CONSTRAINT_DATA, "Stretch To", ""},
- {CONSTRAINT_TYPE_TRACKTO, "TRACK_TO", ICON_CONSTRAINT_DATA, "Track To",
- "Legacy tracking constraint prone to twisting artifacts"},
+ "Rotate around the specified ('locked') axis to point towards a target"},
+ {CONSTRAINT_TYPE_SPLINEIK, "SPLINE_IK", ICON_CONSTRAINT_DATA, "Spline IK",
+ "Align chain of bones along a curve (Bones only)"},
+ {CONSTRAINT_TYPE_STRETCHTO, "STRETCH_TO", ICON_CONSTRAINT_DATA, "Stretch To",
+ "Stretch along Y-Axis to point towards a target"},
+ {CONSTRAINT_TYPE_TRACKTO, "TRACK_TO", ICON_CONSTRAINT_DATA, "Track To",
+ "Legacy tracking constraint prone to twisting artifacts"},
{0, "", 0, N_("Relationship"), ""},
- {CONSTRAINT_TYPE_ACTION, "ACTION", ICON_CONSTRAINT_DATA, "Action", ""},
- {CONSTRAINT_TYPE_CHILDOF, "CHILD_OF", ICON_CONSTRAINT_DATA, "Child Of", ""},
- {CONSTRAINT_TYPE_MINMAX, "FLOOR", ICON_CONSTRAINT_DATA, "Floor", ""},
- {CONSTRAINT_TYPE_FOLLOWPATH, "FOLLOW_PATH", ICON_CONSTRAINT_DATA, "Follow Path", ""},
- {CONSTRAINT_TYPE_PIVOT, "PIVOT", ICON_CONSTRAINT_DATA, "Pivot", ""},
- {CONSTRAINT_TYPE_RIGIDBODYJOINT, "RIGID_BODY_JOINT", ICON_CONSTRAINT_DATA, "Rigid Body Joint", ""},
- {CONSTRAINT_TYPE_PYTHON, "SCRIPT", ICON_CONSTRAINT_DATA, "Script", ""},
- {CONSTRAINT_TYPE_SHRINKWRAP, "SHRINKWRAP", ICON_CONSTRAINT_DATA, "Shrinkwrap", ""},
+ {CONSTRAINT_TYPE_ACTION, "ACTION", ICON_CONSTRAINT_DATA, "Action",
+ "Use transform property of target to look up pose for owner from an Action"},
+ {CONSTRAINT_TYPE_CHILDOF, "CHILD_OF", ICON_CONSTRAINT_DATA, "Child Of",
+ "Make target the 'detachable' parent of owner"},
+ {CONSTRAINT_TYPE_MINMAX, "FLOOR", ICON_CONSTRAINT_DATA, "Floor",
+ "Use position (and optionally rotation) of target to define a 'wall' or 'floor' that the owner can not cross"},
+ {CONSTRAINT_TYPE_FOLLOWPATH, "FOLLOW_PATH", ICON_CONSTRAINT_DATA, "Follow Path",
+ "Use to animate an object/bone following a path"},
+ {CONSTRAINT_TYPE_PIVOT, "PIVOT", ICON_CONSTRAINT_DATA, "Pivot",
+ "Change pivot point for transforms (buggy)"},
+ {CONSTRAINT_TYPE_RIGIDBODYJOINT, "RIGID_BODY_JOINT", ICON_CONSTRAINT_DATA, "Rigid Body Joint",
+ "Use to define a Rigid Body Constraint (for Game Engine use only)"},
+ /* {CONSTRAINT_TYPE_PYTHON, "SCRIPT", ICON_CONSTRAINT_DATA, "Script",
+ "Custom constraint(s) written in Python (Not yet implemented)"}, */
+ {CONSTRAINT_TYPE_SHRINKWRAP, "SHRINKWRAP", ICON_CONSTRAINT_DATA, "Shrinkwrap",
+ "Restrict movements to surface of target mesh"},
{0, NULL, 0, NULL, NULL}
};
@@ -214,7 +236,7 @@ static void rna_Constraint_name_set(PointerRNA *ptr, const char *value)
/* if we have the list, check for unique name, otherwise give up */
if (list)
- unique_constraint_name(con, list);
+ BKE_unique_constraint_name(con, list);
}
/* fix all the animation data which may link to this */
@@ -244,9 +266,9 @@ static void rna_Constraint_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi
ED_object_constraint_update(ptr->id.data);
}
-static void rna_Constraint_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Constraint_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- ED_object_constraint_dependency_update(bmain, scene, ptr->id.data);
+ ED_object_constraint_dependency_update(bmain, ptr->id.data);
}
static void rna_Constraint_influence_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -293,7 +315,7 @@ static EnumPropertyItem *rna_Constraint_target_space_itemf(bContext *UNUSED(C),
PropertyRNA *UNUSED(prop), int *UNUSED(free))
{
bConstraint *con = (bConstraint *)ptr->data;
- bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+ bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
@@ -1392,19 +1414,19 @@ static void rna_def_constraint_rigid_body_joint(BlenderRNA *brna)
prop = RNA_def_property(srna, "axis_x", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "axX");
RNA_def_property_range(prop, -M_PI * 2, M_PI * 2);
- RNA_def_property_ui_text(prop, "Axis X", "Rotate pivot on X axis in degrees");
+ RNA_def_property_ui_text(prop, "Axis X", "Rotate pivot on X axis");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
prop = RNA_def_property(srna, "axis_y", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "axY");
RNA_def_property_range(prop, -M_PI * 2, M_PI * 2);
- RNA_def_property_ui_text(prop, "Axis Y", "Rotate pivot on Y axis in degrees");
+ RNA_def_property_ui_text(prop, "Axis Y", "Rotate pivot on Y axis");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
prop = RNA_def_property(srna, "axis_z", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "axZ");
RNA_def_property_range(prop, -M_PI * 2, M_PI * 2);
- RNA_def_property_ui_text(prop, "Axis Z", "Rotate pivot on Z axis in degrees");
+ RNA_def_property_ui_text(prop, "Axis Z", "Rotate pivot on Z axis");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
prop = RNA_def_property(srna, "use_linked_collision", PROP_BOOLEAN, PROP_NONE);
@@ -1528,7 +1550,7 @@ static void rna_def_constraint_clamp_to(BlenderRNA *brna)
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", "Target Object");
+ RNA_def_property_ui_text(prop, "Target", "Target Object (Curves only)");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c
index 4204506e67b..d7a679e9702 100644
--- a/source/blender/makesrna/intern/rna_context.c
+++ b/source/blender/makesrna/intern/rna_context.c
@@ -24,17 +24,17 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
#include "DNA_ID.h"
#include "DNA_userdef_types.h"
+#include "BLI_utildefines.h"
+#include "BKE_context.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
-#include "BKE_context.h"
-
#include "rna_internal.h" /* own include */
#ifdef RNA_RUNTIME
diff --git a/source/blender/makesrna/intern/rna_controller.c b/source/blender/makesrna/intern/rna_controller.c
index c59e376da82..472cc6e89e6 100644
--- a/source/blender/makesrna/intern/rna_controller.c
+++ b/source/blender/makesrna/intern/rna_controller.c
@@ -24,15 +24,18 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
-#include "WM_types.h"
+#include "DNA_object_types.h"
+#include "DNA_controller_types.h"
+
+#include "BLI_utildefines.h"
+
#include "RNA_define.h"
#include "rna_internal.h"
-#include "DNA_object_types.h"
-#include "DNA_controller_types.h"
+
+#include "WM_types.h"
EnumPropertyItem controller_type_items[] = {
{CONT_LOGIC_AND, "LOGIC_AND", 0, "And", "Logic And"},
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index 21aed20ccc3..479af956591 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -26,11 +26,6 @@
#include <stdlib.h>
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "rna_internal.h"
-
#include "DNA_curve_types.h"
#include "DNA_key_types.h"
#include "DNA_material_types.h"
@@ -40,6 +35,11 @@
#include "BKE_font.h"
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "rna_internal.h"
+
#include "WM_types.h"
#include "BKE_curve.h"
@@ -281,7 +281,7 @@ static int rna_Nurb_length(PointerRNA *ptr)
static void rna_Nurb_type_set(PointerRNA *ptr, int value)
{
Nurb *nu = (Nurb *)ptr->data;
- ED_nurb_set_spline_type(nu, value);
+ BKE_nurb_type_convert(nu, value, true);
}
static void rna_BPoint_array_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
@@ -304,7 +304,7 @@ static void rna_Curve_update_data(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_Curve_update_deps(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
rna_Curve_update_data(bmain, scene, ptr);
}
@@ -460,7 +460,7 @@ static void rna_Curve_body_set(PointerRNA *ptr, const char *value)
/* don't know why this is +4, just duplicating load_editText() */
cu->strinfo = MEM_callocN((len + 4) * sizeof(CharInfo), "strinfo");
- /*BLI_strncpy_wchar_as_utf8(cu->str, value, len+1); *//* value is not wchar_t */
+ /*BLI_strncpy_wchar_as_utf8(cu->str, value, len + 1); *//* value is not wchar_t */
BLI_strncpy(cu->str, value, len + 1);
}
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index bb1ecea6a24..6649d58d718 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -33,6 +33,7 @@
#include <string.h>
#include <ctype.h>
+#include "BLI_utildefines.h"
#include "MEM_guardedalloc.h"
#include "DNA_genfile.h"
@@ -61,7 +62,7 @@
/* Global used during defining */
-BlenderDefRNA DefRNA = {NULL, {NULL, NULL}, {NULL, NULL}, NULL, 0, 0, 0, 1};
+BlenderDefRNA DefRNA = {NULL, {NULL, NULL}, {NULL, NULL}, NULL, 0, 0, 0, 1, 1};
/* Duplicated code since we can't link in blenkernel or blenlib */
@@ -391,7 +392,9 @@ static int rna_validate_identifier(const char *identifier, char *error, int prop
{
int a = 0;
- /* list from http://docs.python.org/py3k/reference/lexical_analysis.html#keywords */
+ /* list is from...
+ * ", ".join(['"%s"' % kw for kw in __import__("keyword").kwlist if kw not in {"False", "None", "True"}])
+ */
static const char *kwlist[] = {
/* "False", "None", "True", */
"and", "as", "assert", "break",
@@ -455,6 +458,78 @@ static int rna_validate_identifier(const char *identifier, char *error, int prop
return 1;
}
+void RNA_identifier_sanitize(char *identifier, int property)
+{
+ int a = 0;
+
+ /* list from http://docs.python.org/py3k/reference/lexical_analysis.html#keywords */
+ static const char *kwlist[] = {
+ /* "False", "None", "True", */
+ "and", "as", "assert", "break",
+ "class", "continue", "def", "del", "elif", "else", "except",
+ "finally", "for", "from", "global", "if", "import", "in",
+ "is", "lambda", "nonlocal", "not", "or", "pass", "raise",
+ "return", "try", "while", "with", "yield", NULL
+ };
+
+
+ if (!isalpha(identifier[0])) {
+ /* first character failed isalpha() check */
+ identifier[0] = '_';
+ }
+
+ for (a = 0; identifier[a]; a++) {
+ if (DefRNA.preprocess && property) {
+ if (isalpha(identifier[a]) && isupper(identifier[a])) {
+ /* property names must contain lower case characters only */
+ identifier[a] = tolower(identifier[a]);
+ }
+ }
+
+ if (identifier[a] == '_') {
+ continue;
+ }
+
+ if (identifier[a] == ' ') {
+ /* spaces are not okay in identifier names */
+ identifier[a] = '_';
+ }
+
+ if (isalnum(identifier[a]) == 0) {
+ /* one of the characters failed an isalnum() check and is not an underscore */
+ identifier[a] = '_';
+ }
+ }
+
+ for (a = 0; kwlist[a]; a++) {
+ if (strcmp(identifier, kwlist[a]) == 0) {
+ /* this keyword is reserved by python.
+ * just replace the last character by '_' to keep it readable.
+ */
+ identifier[strlen(identifier) - 1] = '_';
+ break;
+ }
+ }
+
+ if (property) {
+ static const char *kwlist_prop[] = {
+ /* not keywords but reserved all the same because py uses */
+ "keys", "values", "items", "get",
+ NULL
+ };
+
+ for (a = 0; kwlist_prop[a]; a++) {
+ if (strcmp(identifier, kwlist_prop[a]) == 0) {
+ /* this keyword is reserved by python.
+ * just replace the last character by '_' to keep it readable.
+ */
+ identifier[strlen(identifier) - 1] = '_';
+ break;
+ }
+ }
+ }
+}
+
/* Blender Data Definition */
BlenderRNA *RNA_create(void)
@@ -463,7 +538,7 @@ BlenderRNA *RNA_create(void)
brna = MEM_callocN(sizeof(BlenderRNA), "BlenderRNA");
- DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, 0);
+ DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false);
DefRNA.structs.first = DefRNA.structs.last = NULL;
DefRNA.error = 0;
DefRNA.preprocess = 1;
@@ -504,6 +579,13 @@ void RNA_define_verify_sdna(int verify)
DefRNA.verify = verify;
}
+#ifndef RNA_RUNTIME
+void RNA_define_animate_sdna(int animate)
+{
+ DefRNA.animate = animate;
+}
+#endif
+
void RNA_struct_free_extension(StructRNA *srna, ExtensionRNA *ext)
{
#ifdef RNA_RUNTIME
@@ -621,33 +703,20 @@ static StructDefRNA *rna_find_def_struct(StructRNA *srna)
}
/* Struct Definition */
-
-StructRNA *RNA_def_struct(BlenderRNA *brna, const char *identifier, const char *from)
+StructRNA *RNA_def_struct_ptr(BlenderRNA *brna, const char *identifier, StructRNA *srnafrom)
{
- StructRNA *srna, *srnafrom = NULL;
+ StructRNA *srna;
StructDefRNA *ds = NULL, *dsfrom = NULL;
PropertyRNA *prop;
-
+
if (DefRNA.preprocess) {
char error[512];
- if (rna_validate_identifier(identifier, error, 0) == 0) {
+ if (rna_validate_identifier(identifier, error, FALSE) == 0) {
fprintf(stderr, "%s: struct identifier \"%s\" error - %s\n", __func__, identifier, error);
DefRNA.error = 1;
}
}
-
- if (from) {
- /* find struct to derive from */
- for (srnafrom = brna->structs.first; srnafrom; srnafrom = srnafrom->cont.next)
- if (strcmp(srnafrom->identifier, from) == 0)
- break;
-
- if (!srnafrom) {
- fprintf(stderr, "%s: struct %s not found to define %s.\n", __func__, from, identifier);
- DefRNA.error = 1;
- }
- }
srna = MEM_callocN(sizeof(StructRNA), "StructRNA");
DefRNA.laststruct = srna;
@@ -668,10 +737,12 @@ StructRNA *RNA_def_struct(BlenderRNA *brna, const char *identifier, const char *
else
srna->base = srnafrom;
}
-
+
srna->identifier = identifier;
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->flag |= STRUCT_UNDO;
if (!srnafrom)
srna->icon = ICON_DOT;
@@ -739,6 +810,28 @@ StructRNA *RNA_def_struct(BlenderRNA *brna, const char *identifier, const char *
return srna;
}
+StructRNA *RNA_def_struct(BlenderRNA *brna, const char *identifier, const char *from)
+{
+ StructRNA *srnafrom = NULL;
+
+ /* only use RNA_def_struct() while pre-processing, otherwise use RNA_def_struct_ptr() */
+ BLI_assert(DefRNA.preprocess);
+
+ if (from) {
+ /* find struct to derive from */
+ for (srnafrom = brna->structs.first; srnafrom; srnafrom = srnafrom->cont.next)
+ if (strcmp(srnafrom->identifier, from) == 0)
+ break;
+
+ if (!srnafrom) {
+ fprintf(stderr, "%s: struct %s not found to define %s.\n", __func__, from, identifier);
+ DefRNA.error = 1;
+ }
+ }
+
+ return RNA_def_struct_ptr(brna, identifier, srnafrom);
+}
+
void RNA_def_struct_sdna(StructRNA *srna, const char *structname)
{
StructDefRNA *ds;
@@ -893,7 +986,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;
+ srna->translation_context = context ? context : BLF_I18NCONTEXT_DEFAULT_BPYRNA;
}
/* Property Definition */
@@ -909,7 +1002,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier
if (DefRNA.preprocess) {
char error[512];
- if (rna_validate_identifier(identifier, error, 1) == 0) {
+ if (rna_validate_identifier(identifier, error, TRUE) == 0) {
fprintf(stderr, "%s: property identifier \"%s.%s\" - %s\n", __func__,
CONTAINER_RNA_ID(cont), identifier, error);
DefRNA.error = 1;
@@ -926,6 +1019,16 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier
dprop = MEM_callocN(sizeof(PropertyDefRNA), "PropertyDefRNA");
rna_addtail(&dcont->properties, dprop);
}
+ else {
+#ifdef DEBUG
+ char error[512];
+ if (rna_validate_identifier(identifier, error, TRUE) == 0) {
+ fprintf(stderr, "%s: runtime property identifier \"%s.%s\" - %s\n", __func__,
+ CONTAINER_RNA_ID(cont), identifier, error);
+ DefRNA.error = 1;
+ }
+#endif
+ }
prop = MEM_callocN(rna_property_type_sizeof(type), "PropertyRNA");
@@ -943,6 +1046,14 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier
{
IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
+#ifndef RNA_RUNTIME
+ if (subtype == PROP_DISTANCE) {
+ fprintf(stderr, "%s: subtype does not apply to 'PROP_INT' \"%s.%s\"\n", __func__,
+ CONTAINER_RNA_ID(cont), identifier);
+ DefRNA.error = 1;
+ }
+#endif
+
iprop->hardmin = (subtype == PROP_UNSIGNED) ? 0 : INT_MIN;
iprop->hardmax = INT_MAX;
@@ -1004,14 +1115,22 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier
prop->subtype = subtype;
prop->name = identifier;
prop->description = "";
+ prop->translation_context = BLF_I18NCONTEXT_DEFAULT_BPYRNA;
/* a priori not raw editable */
prop->rawtype = -1;
if (type != PROP_COLLECTION && type != PROP_POINTER) {
prop->flag = PROP_EDITABLE;
- if (type != PROP_STRING)
+ if (type != PROP_STRING) {
+#ifdef RNA_RUNTIME
prop->flag |= PROP_ANIMATABLE;
+#else
+ if (DefRNA.animate) {
+ prop->flag |= PROP_ANIMATABLE;
+ }
+#endif
+ }
}
if (type == PROP_STRING) {
@@ -1189,6 +1308,15 @@ void RNA_def_property_ui_icon(PropertyRNA *prop, int icon, int consecutive)
prop->flag |= PROP_ICONS_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 precision The number of zeros to show
+ * (as a whole number - common range is 1 - 6), see PRECISION_FLOAT_MAX
+ */
void RNA_def_property_ui_range(PropertyRNA *prop, double min, double max, double step, int precision)
{
StructRNA *srna = DefRNA.laststruct;
@@ -1209,6 +1337,21 @@ void RNA_def_property_ui_range(PropertyRNA *prop, double min, double max, double
fprop->softmax = (float)max;
fprop->step = (float)step;
fprop->precision = (int)precision;
+#if 0 /* handy but annoying */
+ if (DefRNA.preprocess) {
+ /* check we're not over PRECISION_FLOAT_MAX */
+ if (fprop->precision > 6) {
+ fprintf(stderr, "%s: \"%s.%s\", precision value over maximum.\n",
+ __func__, srna->identifier, prop->identifier);
+ DefRNA.error = 1;
+ }
+ else if (fprop->precision < 1) {
+ fprintf(stderr, "%s: \"%s.%s\", precision value under minimum.\n",
+ __func__, srna->identifier, prop->identifier);
+ DefRNA.error = 1;
+ }
+ }
+#endif
break;
}
default:
@@ -1917,7 +2060,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;
+ prop->translation_context = context ? context : BLF_I18NCONTEXT_DEFAULT_BPYRNA;
}
/* Functions */
@@ -2005,6 +2148,38 @@ void RNA_def_property_boolean_funcs(PropertyRNA *prop, const char *get, const ch
}
}
+void RNA_def_property_boolean_funcs_runtime(PropertyRNA *prop, BooleanPropertyGetFunc getfunc, BooleanPropertySetFunc setfunc)
+{
+ BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
+
+ if (getfunc) bprop->get_ex = getfunc;
+ if (setfunc) bprop->set_ex = setfunc;
+
+ if (getfunc || setfunc) {
+ /* don't save in id properties */
+ prop->flag &= ~PROP_IDPROPERTY;
+
+ if (!setfunc)
+ prop->flag &= ~PROP_EDITABLE;
+ }
+}
+
+void RNA_def_property_boolean_array_funcs_runtime(PropertyRNA *prop, BooleanArrayPropertyGetFunc getfunc, BooleanArrayPropertySetFunc setfunc)
+{
+ BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
+
+ if (getfunc) bprop->getarray_ex = getfunc;
+ if (setfunc) bprop->setarray_ex = setfunc;
+
+ if (getfunc || setfunc) {
+ /* don't save in id properties */
+ prop->flag &= ~PROP_IDPROPERTY;
+
+ if (!setfunc)
+ prop->flag &= ~PROP_EDITABLE;
+ }
+}
+
void RNA_def_property_int_funcs(PropertyRNA *prop, const char *get, const char *set, const char *range)
{
StructRNA *srna = DefRNA.laststruct;
@@ -2037,6 +2212,40 @@ void RNA_def_property_int_funcs(PropertyRNA *prop, const char *get, const char *
}
}
+void RNA_def_property_int_funcs_runtime(PropertyRNA *prop, IntPropertyGetFunc getfunc, IntPropertySetFunc setfunc, IntPropertyRangeFunc rangefunc)
+{
+ IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
+
+ if (getfunc) iprop->get_ex = getfunc;
+ if (setfunc) iprop->set_ex = setfunc;
+ if (rangefunc) iprop->range_ex = rangefunc;
+
+ if (getfunc || setfunc) {
+ /* don't save in id properties */
+ prop->flag &= ~PROP_IDPROPERTY;
+
+ if (!setfunc)
+ prop->flag &= ~PROP_EDITABLE;
+ }
+}
+
+void RNA_def_property_int_array_funcs_runtime(PropertyRNA *prop, IntArrayPropertyGetFunc getfunc, IntArrayPropertySetFunc setfunc, IntPropertyRangeFunc rangefunc)
+{
+ IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
+
+ if (getfunc) iprop->getarray_ex = getfunc;
+ if (setfunc) iprop->setarray_ex = setfunc;
+ if (rangefunc) iprop->range_ex = rangefunc;
+
+ if (getfunc || setfunc) {
+ /* don't save in id properties */
+ prop->flag &= ~PROP_IDPROPERTY;
+
+ if (!setfunc)
+ prop->flag &= ~PROP_EDITABLE;
+ }
+}
+
void RNA_def_property_float_funcs(PropertyRNA *prop, const char *get, const char *set, const char *range)
{
StructRNA *srna = DefRNA.laststruct;
@@ -2069,6 +2278,40 @@ void RNA_def_property_float_funcs(PropertyRNA *prop, const char *get, const char
}
}
+void RNA_def_property_float_funcs_runtime(PropertyRNA *prop, FloatPropertyGetFunc getfunc, FloatPropertySetFunc setfunc, FloatPropertyRangeFunc rangefunc)
+{
+ FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
+
+ if (getfunc) fprop->get_ex = getfunc;
+ if (setfunc) fprop->set_ex = setfunc;
+ if (rangefunc) fprop->range_ex = rangefunc;
+
+ if (getfunc || setfunc) {
+ /* don't save in id properties */
+ prop->flag &= ~PROP_IDPROPERTY;
+
+ if (!setfunc)
+ prop->flag &= ~PROP_EDITABLE;
+ }
+}
+
+void RNA_def_property_float_array_funcs_runtime(PropertyRNA *prop, FloatArrayPropertyGetFunc getfunc, FloatArrayPropertySetFunc setfunc, FloatPropertyRangeFunc rangefunc)
+{
+ FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
+
+ if (getfunc) fprop->getarray_ex = getfunc;
+ if (setfunc) fprop->setarray_ex = setfunc;
+ if (rangefunc) fprop->range_ex = rangefunc;
+
+ if (getfunc || setfunc) {
+ /* don't save in id properties */
+ prop->flag &= ~PROP_IDPROPERTY;
+
+ if (!setfunc)
+ prop->flag &= ~PROP_EDITABLE;
+ }
+}
+
void RNA_def_property_enum_funcs(PropertyRNA *prop, const char *get, const char *set, const char *item)
{
StructRNA *srna = DefRNA.laststruct;
@@ -2095,6 +2338,29 @@ void RNA_def_property_enum_funcs(PropertyRNA *prop, const char *get, const char
}
}
+void RNA_def_property_enum_funcs_runtime(PropertyRNA *prop, EnumPropertyGetFunc getfunc, EnumPropertySetFunc setfunc, EnumPropertyItemFunc itemfunc)
+{
+ EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
+
+ if (getfunc) eprop->get_ex = getfunc;
+ if (setfunc) eprop->set_ex = setfunc;
+ if (itemfunc) eprop->itemf = itemfunc;
+
+ if (getfunc || setfunc) {
+ /* don't save in id properties */
+ prop->flag &= ~PROP_IDPROPERTY;
+
+ if (!setfunc)
+ prop->flag &= ~PROP_EDITABLE;
+ }
+}
+
+void RNA_def_property_enum_py_data(PropertyRNA *prop, void *py_data)
+{
+ EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
+ eprop->py_data = py_data;
+}
+
void RNA_def_property_string_funcs(PropertyRNA *prop, const char *get, const char *length, const char *set)
{
StructRNA *srna = DefRNA.laststruct;
@@ -2121,6 +2387,23 @@ void RNA_def_property_string_funcs(PropertyRNA *prop, const char *get, const cha
}
}
+void RNA_def_property_string_funcs_runtime(PropertyRNA *prop, StringPropertyGetFunc getfunc, StringPropertyLengthFunc lengthfunc, StringPropertySetFunc setfunc)
+{
+ StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
+
+ if (getfunc) sprop->get_ex = getfunc;
+ if (lengthfunc) sprop->length_ex = lengthfunc;
+ if (setfunc) sprop->set_ex = setfunc;
+
+ if (getfunc || setfunc) {
+ /* don't save in id properties */
+ prop->flag &= ~PROP_IDPROPERTY;
+
+ if (!setfunc)
+ prop->flag &= ~PROP_EDITABLE;
+ }
+}
+
void RNA_def_property_pointer_funcs(PropertyRNA *prop, const char *get, const char *set,
const char *typef, const char *poll)
{
@@ -2375,20 +2658,6 @@ PropertyRNA *RNA_def_string_file_name(StructOrFunctionRNA *cont_, const char *id
return prop;
}
-PropertyRNA *RNA_def_string_translate(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value,
- int maxlen, const char *ui_name, const char *ui_description)
-{
- ContainerRNA *cont = cont_;
- PropertyRNA *prop;
-
- prop = RNA_def_property(cont, identifier, PROP_STRING, PROP_TRANSLATE);
- if (maxlen != 0) RNA_def_property_string_maxlength(prop, maxlen);
- if (default_value) RNA_def_property_string_default(prop, default_value);
- RNA_def_property_ui_text(prop, ui_name, ui_description);
-
- return prop;
-}
-
PropertyRNA *RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items,
int default_value, const char *ui_name, const char *ui_description)
{
@@ -2435,12 +2704,6 @@ void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
eprop->itemf = itemfunc;
}
-void RNA_def_enum_py_data(PropertyRNA *prop, void *py_data)
-{
- EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
- eprop->py_data = py_data;
-}
-
PropertyRNA *RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, float default_value,
float hardmin, float hardmax, const char *ui_name, const char *ui_description,
float softmin, float softmax)
@@ -2674,7 +2937,7 @@ static FunctionRNA *rna_def_function(StructRNA *srna, const char *identifier)
if (DefRNA.preprocess) {
char error[512];
- if (rna_validate_identifier(identifier, error, 0) == 0) {
+ if (rna_validate_identifier(identifier, error, FALSE) == 0) {
fprintf(stderr, "%s: function identifier \"%s\" - %s\n", __func__, identifier, error);
DefRNA.error = 1;
}
diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c
index 4f9f2009a14..8d30a0be0f1 100644
--- a/source/blender/makesrna/intern/rna_dynamicpaint.c
+++ b/source/blender/makesrna/intern/rna_dynamicpaint.c
@@ -24,13 +24,10 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
#include <limits.h>
-#include "RNA_define.h"
-
-#include "rna_internal.h"
+#include "BLI_math_base.h"
#include "BKE_modifier.h"
#include "BKE_dynamicpaint.h"
@@ -41,6 +38,10 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "RNA_define.h"
+
+#include "rna_internal.h"
+
#include "WM_types.h"
EnumPropertyItem prop_dynamicpaint_type_items[] = {
@@ -150,7 +151,7 @@ static void rna_DynamicPaintSurfaces_changeFormat(Main *bmain, Scene *scene, Poi
static void rna_DynamicPaint_resetDependancy(Main *bmain, Scene *scene, PointerRNA *ptr)
{
rna_DynamicPaintSurface_reset(bmain, scene, ptr);
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
}
static PointerRNA rna_PaintSurface_active_get(PointerRNA *ptr)
@@ -219,6 +220,14 @@ static int rna_DynamicPaint_is_cache_user_get(PointerRNA *ptr)
return (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ) ? 1 : 0;
}
+/* is some 3D view preview available */
+static int rna_DynamicPaint_use_color_preview_get(PointerRNA *ptr)
+{
+ DynamicPaintSurface *surface = (DynamicPaintSurface *)ptr->data;
+
+ return dynamicPaint_surfaceHasColorPreview(surface);
+}
+
/* does output layer exist*/
static int rna_DynamicPaint_is_output_exists(DynamicPaintSurface *surface, Object *ob, int index)
{
@@ -239,6 +248,7 @@ static EnumPropertyItem *rna_DynamicPaint_surface_type_itemf(bContext *C, Pointe
tmp.value = MOD_DPAINT_SURFACE_T_PAINT;
tmp.identifier = "PAINT";
tmp.name = "Paint";
+ tmp.icon = ICON_TPAINT_HLT;
RNA_enum_item_add(&item, &totitem, &tmp);
/* Displace */
@@ -248,6 +258,7 @@ static EnumPropertyItem *rna_DynamicPaint_surface_type_itemf(bContext *C, Pointe
tmp.value = MOD_DPAINT_SURFACE_T_DISPLACE;
tmp.identifier = "DISPLACE";
tmp.name = "Displace";
+ tmp.icon = ICON_MOD_DISPLACE;
RNA_enum_item_add(&item, &totitem, &tmp);
}
@@ -256,6 +267,7 @@ static EnumPropertyItem *rna_DynamicPaint_surface_type_itemf(bContext *C, Pointe
tmp.value = MOD_DPAINT_SURFACE_T_WEIGHT;
tmp.identifier = "WEIGHT";
tmp.name = "Weight";
+ tmp.icon = ICON_MOD_VERTEX_WEIGHT;
RNA_enum_item_add(&item, &totitem, &tmp);
}
@@ -264,6 +276,7 @@ static EnumPropertyItem *rna_DynamicPaint_surface_type_itemf(bContext *C, Pointe
tmp.value = MOD_DPAINT_SURFACE_T_WAVE;
tmp.identifier = "WAVE";
tmp.name = "Waves";
+ tmp.icon = ICON_MOD_WAVE;
RNA_enum_item_add(&item, &totitem, &tmp);
}
@@ -705,6 +718,14 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
RNA_def_property_boolean_funcs(prop, "rna_DynamicPaint_is_cache_user_get", NULL);
RNA_def_property_ui_text(prop, "Use Cache", "");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
+
+ /* whether this surface has preview data for 3D view */
+ RNA_define_verify_sdna(FALSE);
+ prop = RNA_def_property(srna, "use_color_preview", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_DynamicPaint_use_color_preview_get", NULL);
+ RNA_def_property_ui_text(prop, "Use Color Preview", "Whether this surface has some color preview for 3D view");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
+ RNA_define_verify_sdna(TRUE);
}
static void rna_def_dynamic_paint_canvas_settings(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index 4250acf5848..2ad8ded4656 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -24,15 +24,8 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
-#include "RNA_access.h"
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
-#include "rna_internal.h"
-
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -43,6 +36,12 @@
#include "BKE_action.h"
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
#include "WM_types.h"
#include "ED_keyframing.h"
@@ -116,7 +115,7 @@ static void rna_ChannelDriver_update_data(Main *bmain, Scene *scene, PointerRNA
driver->flag &= ~DRIVER_FLAG_INVALID;
/* TODO: this really needs an update guard... */
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
DAG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA);
WM_main_add_notifier(NC_SCENE | ND_FRAME, scene);
@@ -633,6 +632,81 @@ static void rna_fcurve_range(FCurve *fcu, float range[2])
calc_fcurve_range(fcu, range, range + 1, FALSE, FALSE);
}
+
+static FCM_EnvelopeData *rna_FModifierEnvelope_points_add(FModifier *fmod, ReportList *reports, float frame)
+{
+ FCM_EnvelopeData fed;
+ FMod_Envelope *env = (FMod_Envelope *)fmod->data;
+ int i;
+
+ /* init template data */
+ fed.min = -1.0f;
+ fed.max = 1.0f;
+ fed.time = frame;
+ fed.f1 = fed.f2 = 0;
+
+ if (env->data) {
+ bool exists;
+ i = BKE_fcm_envelope_find_index(env->data, frame, env->totvert, &exists);
+ if (exists) {
+ BKE_reportf(reports, RPT_ERROR, "Already a control point at frame %.6f", frame);
+ return NULL;
+ }
+
+ /* realloc memory for extra point */
+ env->data = (FCM_EnvelopeData *) MEM_reallocN((void *)env->data, (env->totvert + 1) * sizeof(FCM_EnvelopeData));
+
+ /* move the points after the added point */
+ if (i < env->totvert) {
+ memmove(env->data + i + 1, env->data + i, (env->totvert - i) * sizeof(FCM_EnvelopeData));
+ }
+
+ env->totvert++;
+ }
+ else {
+ env->data = MEM_mallocN(sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
+ env->totvert = 1;
+ i = 0;
+ }
+
+ /* add point to paste at index i */
+ *(env->data + i) = fed;
+ return (env->data + i);
+}
+
+void rna_FModifierEnvelope_points_remove(FModifier *fmod, ReportList *reports, PointerRNA *point)
+{
+ FCM_EnvelopeData *cp = point->data;
+ FMod_Envelope *env = (FMod_Envelope *)fmod->data;
+
+ int index = (int)(cp - env->data);
+
+ /* test point is in range */
+ if (index < 0 || index >= env->totvert) {
+ BKE_report(reports, RPT_ERROR, "Control point not in Envelope F-Modifier");
+ return;
+ }
+
+ if (env->totvert > 1) {
+ /* move data after the removed point */
+
+ memmove(env->data + index, env->data + (index + 1), sizeof(FCM_EnvelopeData) * ((env->totvert - index) - 1));
+
+ /* realloc smaller array */
+ env->totvert--;
+ env->data = (FCM_EnvelopeData *) MEM_reallocN((void *)env->data, (env->totvert) * sizeof(FCM_EnvelopeData));
+ }
+ else {
+ /* just free array, since the only vert was deleted */
+ if (env->data) {
+ MEM_freeN(env->data);
+ env->data = NULL;
+ }
+ env->totvert = 0;
+ }
+ RNA_POINTER_INVALIDATE(point);
+}
+
#else
static void rna_def_fmodifier_generator(BlenderRNA *brna)
@@ -770,6 +844,36 @@ static void rna_def_fmodifier_envelope_ctrl(BlenderRNA *brna)
/* - selection flags (not implemented in UI yet though) */
}
+static void rna_def_fmodifier_envelope_control_points(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "FModifierEnvelopeControlPoints");
+ srna = RNA_def_struct(brna, "FModifierEnvelopeControlPoints", NULL);
+ RNA_def_struct_sdna(srna, "FModifier");
+
+ RNA_def_struct_ui_text(srna, "Control Points", "Control points defining the shape of the envelope");
+
+ func = RNA_def_function(srna, "add", "rna_FModifierEnvelope_points_add");
+ RNA_def_function_ui_description(func, "Add a control point to a FModifierEnvelope");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_float(func, "frame", 0.0f, -FLT_MAX, FLT_MAX, "",
+ "Frame to add this control-point", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_pointer(func, "point", "FModifierEnvelopeControlPoint", "", "Newly created control-point");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_FModifierEnvelope_points_remove");
+ RNA_def_function_ui_description(func, "Remove a control-point from an FModifierEnvelope");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "point", "FModifierEnvelopeControlPoint", "", "Control-point to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+}
+
+
static void rna_def_fmodifier_envelope(BlenderRNA *brna)
{
StructRNA *srna;
@@ -784,6 +888,7 @@ static void rna_def_fmodifier_envelope(BlenderRNA *brna)
RNA_def_property_collection_sdna(prop, NULL, "data", "totvert");
RNA_def_property_struct_type(prop, "FModifierEnvelopeControlPoint");
RNA_def_property_ui_text(prop, "Control Points", "Control points defining the shape of the envelope");
+ rna_def_fmodifier_envelope_control_points(brna, prop);
/* Range Settings */
prop = RNA_def_property(srna, "reference_value", PROP_FLOAT, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c
index 84ff53ee68f..9ff83daa2f8 100644
--- a/source/blender/makesrna/intern/rna_fluidsim.c
+++ b/source/blender/makesrna/intern/rna_fluidsim.c
@@ -28,6 +28,7 @@
#include "DNA_object_fluidsim.h"
+#include "BLI_utildefines.h"
#include "BLI_path_util.h"
#include "RNA_define.h"
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index b3c1f4dd505..7156b76bab2 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -24,19 +24,20 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "rna_internal.h"
-
#include "DNA_gpencil_types.h"
#include "DNA_scene_types.h"
#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "rna_internal.h"
+
#include "WM_types.h"
#ifdef RNA_RUNTIME
@@ -118,7 +119,7 @@ static void rna_GPencil_stroke_point_add(bGPDstroke *stroke, int count)
if (stroke->points == NULL)
stroke->points = MEM_callocN(sizeof(bGPDspoint) * count, "gp_stroke_points");
else
- stroke->points = MEM_reallocN(stroke->points, sizeof(bGPDspoint) * (stroke->totpoints + count));
+ stroke->points = MEM_recallocN(stroke->points, sizeof(bGPDspoint) * (stroke->totpoints + count));
stroke->totpoints += count;
}
@@ -547,7 +548,9 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GP_LAYER_NO_XRAY);
RNA_def_property_ui_text(prop, "X Ray", "Make the layer draw in front of objects");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
-
+
+
+ /* 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");
}
diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c
index 4baf46fd0b5..1ac59f9caed 100644
--- a/source/blender/makesrna/intern/rna_group.c
+++ b/source/blender/makesrna/intern/rna_group.c
@@ -24,15 +24,16 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
+#include "DNA_group_types.h"
+
+#include "BLI_utildefines.h"
+
#include "RNA_define.h"
#include "rna_internal.h"
-#include "DNA_group_types.h"
-
#ifdef RNA_RUNTIME
#include "DNA_scene_types.h"
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index 9fedbee41ff..81136193883 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -24,21 +24,22 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
-#include "rna_internal.h"
-
#include "DNA_image_types.h"
#include "DNA_scene_types.h"
+#include "BLI_utildefines.h"
+
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_image.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
#include "WM_types.h"
#include "WM_api.h"
@@ -88,11 +89,15 @@ static int rna_Image_dirty_get(PointerRNA *ptr)
return 0;
}
-static void rna_Image_source_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_Image_source_set(PointerRNA *ptr, int value)
{
Image *ima = ptr->id.data;
- BKE_image_signal(ima, NULL, IMA_SIGNAL_SRC_CHANGE);
- DAG_id_tag_update(&ima->id, 0);
+
+ if (value != ima->source) {
+ ima->source = value;
+ BKE_image_signal(ima, NULL, IMA_SIGNAL_SRC_CHANGE);
+ DAG_id_tag_update(&ima->id, 0);
+ }
}
static void rna_Image_fields_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -116,15 +121,6 @@ static void rna_Image_fields_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P
BKE_image_release_ibuf(ima, ibuf, lock);
}
-static void rna_Image_free_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- Image *ima = ptr->id.data;
- BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
- WM_main_add_notifier(NC_IMAGE | NA_EDITED, &ima->id);
- DAG_id_tag_update(&ima->id, 0);
-}
-
-
static void rna_Image_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Image *ima = ptr->id.data;
@@ -139,6 +135,15 @@ static void rna_Image_generated_update(Main *UNUSED(bmain), Scene *UNUSED(scene)
BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
}
+static void rna_Image_colormanage_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ Image *ima = ptr->id.data;
+ BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE);
+ DAG_id_tag_update(&ima->id, 0);
+ WM_main_add_notifier(NC_IMAGE | ND_DISPLAY, &ima->id);
+ WM_main_add_notifier(NC_IMAGE | NA_EDITED, &ima->id);
+}
+
static void rna_ImageUser_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
{
ImageUser *iuser = ptr->data;
@@ -377,6 +382,38 @@ static void rna_Image_pixels_set(PointerRNA *ptr, const float *values)
BKE_image_release_ibuf(ima, ibuf, lock);
}
+static int rna_Image_channels_get(PointerRNA *ptr)
+{
+ Image *im = (Image *)ptr->data;
+ ImBuf *ibuf;
+ void *lock;
+ int channels = 0;
+
+ ibuf = BKE_image_acquire_ibuf(im, NULL, &lock);
+ if (ibuf)
+ channels = ibuf->channels;
+
+ BKE_image_release_ibuf(im, ibuf, lock);
+
+ return channels;
+}
+
+static int rna_Image_is_float_get(PointerRNA *ptr)
+{
+ Image *im = (Image *)ptr->data;
+ ImBuf *ibuf;
+ void *lock;
+ int is_float = FALSE;
+
+ ibuf = BKE_image_acquire_ibuf(im, NULL, &lock);
+ if (ibuf)
+ is_float = ibuf->rect_float != NULL;
+
+ BKE_image_release_ibuf(im, ibuf, lock);
+
+ return is_float;
+}
+
#else
static void rna_def_imageuser(BlenderRNA *brna)
@@ -395,6 +432,11 @@ static void rna_def_imageuser(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_ImageUser_update");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ prop = RNA_def_property(srna, "frame_current", PROP_INT, PROP_TIME);
+ RNA_def_property_int_sdna(prop, NULL, "framenr");
+ RNA_def_property_range(prop, MINAFRAME, MAXFRAME);
+ RNA_def_property_ui_text(prop, "Current Frame", "Current frame number in image sequence or movie");
+
/* animation */
prop = RNA_def_property(srna, "use_cyclic", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "cycl", 0);
@@ -413,7 +455,6 @@ static void rna_def_imageuser(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "offset");
RNA_def_property_ui_text(prop, "Offset", "Offset the number of the frame to use in the animation");
RNA_def_property_update(prop, 0, "rna_ImageUser_update");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "sfra");
@@ -463,6 +504,11 @@ static void rna_def_image(BlenderRNA *brna)
{IMA_STD_FIELD, "ODD", 0, "Lower First", "Lower field first"},
{0, NULL, 0, NULL, NULL}
};
+ static const EnumPropertyItem alpha_mode_items[] = {
+ {IMA_ALPHA_STRAIGHT, "STRAIGHT", 0, "Straight", "Transparent RGB and alpha pixels are unmodified"},
+ {IMA_ALPHA_PREMUL, "PREMUL", 0, "Premultiplied", "Transparent RGB pixels are multiplied by the alpha channel"},
+ {0, NULL, 0, NULL, NULL}
+ };
srna = RNA_def_struct(brna, "Image", "ID");
RNA_def_struct_ui_text(srna, "Image", "Image datablock referencing an external or packed image");
@@ -485,9 +531,9 @@ static void rna_def_image(BlenderRNA *brna)
prop = RNA_def_property(srna, "source", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, image_source_items);
- RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Image_source_itemf");
+ RNA_def_property_enum_funcs(prop, NULL, "rna_Image_source_set", "rna_Image_source_itemf");
RNA_def_property_ui_text(prop, "Source", "Where the image comes from");
- RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_source_update");
+ RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_type_items);
@@ -512,23 +558,17 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_fields_update");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- prop = RNA_def_property(srna, "use_premultiply", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_DO_PREMUL);
- RNA_def_property_ui_text(prop, "Premultiply", "Convert RGB from key alpha to premultiplied alpha");
- RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_free_update");
-
- prop = RNA_def_property(srna, "use_color_unpremultiply", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_CM_PREDIVIDE);
- RNA_def_property_ui_text(prop, "Color Unpremultiply",
- "For premultiplied alpha images, do color space conversion on colors without alpha, "
- "to avoid fringing for images with light backgrounds");
- RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_free_update");
prop = RNA_def_property(srna, "view_as_render", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_VIEW_AS_RENDER);
RNA_def_property_ui_text(prop, "View as Render", "Apply render part of display transformation when displaying this image on the screen");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
+ prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMA_IGNORE_ALPHA);
+ 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, "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);
@@ -544,14 +584,14 @@ static void rna_def_image(BlenderRNA *brna)
prop = RNA_def_property(srna, "generated_width", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "gen_x");
- RNA_def_property_range(prop, 1, 16384);
+ RNA_def_property_range(prop, 1, 65536);
RNA_def_property_ui_text(prop, "Generated Width", "Generated image width");
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_height", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "gen_y");
- RNA_def_property_range(prop, 1, 16384);
+ RNA_def_property_range(prop, 1, 65536);
RNA_def_property_ui_text(prop, "Generated Height", "Generated image height");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
@@ -665,6 +705,10 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Duration", "Duration (in frames) of the image (1 when not a video/sequence)");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ /* NOTE about pixels/channels/is_floa:
+ * this properties describes how image is stored internally (inside of ImBuf),
+ * not how it was saved to disk or how it'll be saved on disk
+ */
prop = RNA_def_property(srna, "pixels", PROP_FLOAT, PROP_NONE);
RNA_def_property_flag(prop, PROP_DYNAMIC);
RNA_def_property_multi_array(prop, 1, NULL);
@@ -672,11 +716,26 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_dynamic_array_funcs(prop, "rna_Image_pixels_get_length");
RNA_def_property_float_funcs(prop, "rna_Image_pixels_get", "rna_Image_pixels_set", NULL);
+ prop = RNA_def_property(srna, "channels", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_funcs(prop, "rna_Image_channels_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Channels", "Number of channels in pixels buffer");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ prop = RNA_def_property(srna, "is_float", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_Image_is_float_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Is Float", "True if this image is stored in float buffer");
+
prop = RNA_def_property(srna, "colorspace_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "colorspace_settings");
- RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings");
+ RNA_def_property_struct_type(prop, "ColorManagedInputColorspaceSettings");
RNA_def_property_ui_text(prop, "Color Space Settings", "Input color space settings");
+ prop = RNA_def_property(srna, "alpha_mode", PROP_ENUM, PROP_NONE);
+ 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_IMAGE | ND_DISPLAY, "rna_Image_colormanage_update");
+
RNA_api_image(srna);
}
diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c
index 686e6c80f1d..c1769f02974 100644
--- a/source/blender/makesrna/intern/rna_image_api.c
+++ b/source/blender/makesrna/intern/rna_image_api.c
@@ -34,13 +34,15 @@
#include <string.h>
#include <time.h>
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
#include "DNA_packedFile_types.h"
+#include "BLI_utildefines.h"
+
#include "BIF_gl.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
#include "rna_internal.h" /* own include */
#ifdef RNA_RUNTIME
@@ -318,9 +320,9 @@ void RNA_api_image(StructRNA *srna)
RNA_def_function_ui_description(func, "Delay the image from being cleaned from the cache due inactivity");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_int(func, "filter", GL_LINEAR_MIPMAP_NEAREST, -INT_MAX, INT_MAX, "Filter",
- "The texture minifying function to use if the image wan't loaded", -INT_MAX, INT_MAX);
+ "The texture minifying function to use if the image wasn't loaded", -INT_MAX, INT_MAX);
RNA_def_int(func, "mag", GL_LINEAR, -INT_MAX, INT_MAX, "Magnification",
- "The texture magnification function to use if the image wan't loaded", -INT_MAX, INT_MAX);
+ "The texture magnification function to use if the image wasn't loaded", -INT_MAX, INT_MAX);
/* return value */
parm = RNA_def_int(func, "error", 0, -INT_MAX, INT_MAX, "Error", "OpenGL error value", -INT_MAX, INT_MAX);
RNA_def_function_return(func, parm);
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 6520f22fbf5..09ea82e5ec7 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -24,12 +24,13 @@
* \ingroup RNA
*/
-
#ifndef __RNA_INTERNAL_H__
#define __RNA_INTERNAL_H__
#include "UI_resources.h"
+#include "BLI_utildefines.h"
+
#include "rna_internal_types.h"
#define RNA_MAGIC ((int)~0)
@@ -117,7 +118,7 @@ typedef struct BlenderDefRNA {
ListBase structs;
ListBase allocs;
struct StructRNA *laststruct;
- int error, silent, preprocess, verify;
+ int error, silent, preprocess, verify, animate;
} BlenderDefRNA;
extern BlenderDefRNA DefRNA;
@@ -151,6 +152,7 @@ void RNA_def_image(struct BlenderRNA *brna);
void RNA_def_key(struct BlenderRNA *brna);
void RNA_def_lamp(struct BlenderRNA *brna);
void RNA_def_lattice(struct BlenderRNA *brna);
+void RNA_def_linestyle(struct BlenderRNA *brna);
void RNA_def_main(struct BlenderRNA *brna);
void RNA_def_material(struct BlenderRNA *brna);
void RNA_def_mesh(struct BlenderRNA *brna);
@@ -164,6 +166,7 @@ void RNA_def_packedfile(struct BlenderRNA *brna);
void RNA_def_particle(struct BlenderRNA *brna);
void RNA_def_pose(struct BlenderRNA *brna);
void RNA_def_render(struct BlenderRNA *brna);
+void RNA_def_rigidbody(struct BlenderRNA *brna);
void RNA_def_rna(struct BlenderRNA *brna);
void RNA_def_scene(struct BlenderRNA *brna);
void RNA_def_screen(struct BlenderRNA *brna);
@@ -207,9 +210,9 @@ void rna_ID_name_get(struct PointerRNA *ptr, char *value);
int rna_ID_name_length(struct PointerRNA *ptr);
void rna_ID_name_set(struct PointerRNA *ptr, const char *value);
struct StructRNA *rna_ID_refine(struct PointerRNA *ptr);
-struct IDProperty *rna_ID_idprops(struct PointerRNA *ptr, int create);
+struct IDProperty *rna_ID_idprops(struct PointerRNA *ptr, bool create);
void rna_ID_fake_user_set(struct PointerRNA *ptr, int value);
-struct IDProperty *rna_PropertyGroup_idprops(struct PointerRNA *ptr, int create);
+struct IDProperty *rna_PropertyGroup_idprops(struct PointerRNA *ptr, bool create);
void rna_PropertyGroup_unregister(struct Main *bmain, struct StructRNA *type);
struct StructRNA *rna_PropertyGroup_register(struct Main *bmain, struct ReportList *reports, void *data,
const char *identifier, StructValidateFunc validate,
@@ -263,6 +266,7 @@ void RNA_api_keymapitems(struct StructRNA *srna);
void RNA_api_main(struct StructRNA *srna);
void RNA_api_material(StructRNA *srna);
void RNA_api_mesh(struct StructRNA *srna);
+void RNA_api_meta(struct StructRNA *srna);
void RNA_api_object(struct StructRNA *srna);
void RNA_api_object_base(struct StructRNA *srna);
void RNA_api_pose(struct StructRNA *srna);
@@ -310,6 +314,7 @@ void RNA_def_main_particles(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);
+void RNA_def_main_linestyles(BlenderRNA *brna, PropertyRNA *cprop);
/* ID Properties */
@@ -397,6 +402,10 @@ PointerRNA rna_pointer_inherit_refine(struct PointerRNA *ptr, struct StructRNA *
int rna_parameter_size(struct PropertyRNA *parm);
int rna_parameter_size_alloc(struct PropertyRNA *parm);
+struct Mesh *rna_Main_meshes_new_from_object(
+ struct Main *bmain, struct ReportList *reports, struct Scene *sce,
+ struct Object *ob, int apply_modifiers, int settings, int calc_tessface);
+
/* XXX, these should not need to be defined here~! */
struct MTex *rna_mtex_texture_slots_add(struct ID *self, struct bContext *C, struct ReportList *reports);
struct MTex *rna_mtex_texture_slots_create(struct ID *self, struct bContext *C, struct ReportList *reports, int index);
@@ -410,6 +419,4 @@ int rna_IDMaterials_assign_int(struct PointerRNA *ptr, int key, const struct Poi
void rna_RenderLayer_rect_set(PointerRNA *ptr, const float *values);
void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values);
-#endif /* __RNA_INTERNAL_H__ */
-
-
+#endif /* __RNA_INTERNAL_H__ */
diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h
index ccfb83b61e3..1dce89c343d 100644
--- a/source/blender/makesrna/intern/rna_internal_types.h
+++ b/source/blender/makesrna/intern/rna_internal_types.h
@@ -30,6 +30,8 @@
#include "DNA_listBase.h"
+#include "RNA_types.h"
+
struct BlenderRNA;
struct ContainerRNA;
struct StructRNA;
@@ -64,7 +66,7 @@ typedef void (*ContextPropUpdateFunc)(struct bContext *C, struct PointerRNA *ptr
typedef void (*ContextUpdateFunc)(struct bContext *C, struct PointerRNA *ptr);
typedef int (*EditableFunc)(struct PointerRNA *ptr);
typedef int (*ItemEditableFunc)(struct PointerRNA *ptr, int index);
-typedef struct IDProperty* (*IDPropertiesFunc)(struct PointerRNA *ptr, int create);
+typedef struct IDProperty *(*IDPropertiesFunc)(struct PointerRNA *ptr, bool create);
typedef struct StructRNA *(*StructRefineFunc)(struct PointerRNA *ptr);
typedef char *(*StructPathFunc)(struct PointerRNA *ptr);
@@ -91,7 +93,7 @@ typedef void (*PropEnumSetFunc)(struct PointerRNA *ptr, int value);
typedef EnumPropertyItem *(*PropEnumItemFunc)(struct bContext *C, struct PointerRNA *ptr,
struct PropertyRNA *prop, int *free);
typedef PointerRNA (*PropPointerGetFunc)(struct PointerRNA *ptr);
-typedef StructRNA* (*PropPointerTypeFunc)(struct PointerRNA *ptr);
+typedef StructRNA *(*PropPointerTypeFunc)(struct PointerRNA *ptr);
typedef void (*PropPointerSetFunc)(struct PointerRNA *ptr, const PointerRNA value);
typedef int (*PropPointerPollFunc)(struct PointerRNA *ptr, const PointerRNA value);
typedef void (*PropCollectionBeginFunc)(struct CollectionPropertyIterator *iter, struct PointerRNA *ptr);
@@ -103,6 +105,27 @@ typedef int (*PropCollectionLookupIntFunc)(struct PointerRNA *ptr, int key, stru
typedef int (*PropCollectionLookupStringFunc)(struct PointerRNA *ptr, const char *key, struct PointerRNA *r_ptr);
typedef int (*PropCollectionAssignIntFunc)(struct PointerRNA *ptr, int key, const struct PointerRNA *assign_ptr);
+/* extended versions with PropertyRNA argument */
+typedef int (*PropBooleanGetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop);
+typedef void (*PropBooleanSetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop, int value);
+typedef void (*PropBooleanArrayGetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop, int *values);
+typedef void (*PropBooleanArraySetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop, const int *values);
+typedef int (*PropIntGetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop);
+typedef void (*PropIntSetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop, int value);
+typedef void (*PropIntArrayGetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop, int *values);
+typedef void (*PropIntArraySetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop, const int *values);
+typedef void (*PropIntRangeFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop, int *min, int *max, int *softmin, int *softmax);
+typedef float (*PropFloatGetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop);
+typedef void (*PropFloatSetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop, float value);
+typedef void (*PropFloatArrayGetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop, float *values);
+typedef void (*PropFloatArraySetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop, const float *values);
+typedef void (*PropFloatRangeFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop, float *min, float *max, float *softmin, float *softmax);
+typedef void (*PropStringGetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop, char *value);
+typedef int (*PropStringLengthFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop);
+typedef void (*PropStringSetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop, const char *value);
+typedef int (*PropEnumGetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop);
+typedef void (*PropEnumSetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop, int value);
+
/* Container - generic abstracted container of RNA properties */
typedef struct ContainerRNA {
void *next, *prev;
@@ -193,10 +216,14 @@ typedef struct BoolPropertyRNA {
PropBooleanGetFunc get;
PropBooleanSetFunc set;
-
PropBooleanArrayGetFunc getarray;
PropBooleanArraySetFunc setarray;
+ PropBooleanGetFuncEx get_ex;
+ PropBooleanSetFuncEx set_ex;
+ PropBooleanArrayGetFuncEx getarray_ex;
+ PropBooleanArraySetFuncEx setarray_ex;
+
int defaultvalue;
const int *defaultarray;
} BoolPropertyRNA;
@@ -206,12 +233,16 @@ typedef struct IntPropertyRNA {
PropIntGetFunc get;
PropIntSetFunc set;
-
PropIntArrayGetFunc getarray;
PropIntArraySetFunc setarray;
-
PropIntRangeFunc range;
+ PropIntGetFuncEx get_ex;
+ PropIntSetFuncEx set_ex;
+ PropIntArrayGetFuncEx getarray_ex;
+ PropIntArraySetFuncEx setarray_ex;
+ PropIntRangeFuncEx range_ex;
+
int softmin, softmax;
int hardmin, hardmax;
int step;
@@ -225,12 +256,16 @@ typedef struct FloatPropertyRNA {
PropFloatGetFunc get;
PropFloatSetFunc set;
-
PropFloatArrayGetFunc getarray;
PropFloatArraySetFunc setarray;
-
PropFloatRangeFunc range;
+ PropFloatGetFuncEx get_ex;
+ PropFloatSetFuncEx set_ex;
+ PropFloatArrayGetFuncEx getarray_ex;
+ PropFloatArraySetFuncEx setarray_ex;
+ PropFloatRangeFuncEx range_ex;
+
float softmin, softmax;
float hardmin, hardmax;
float step;
@@ -247,6 +282,10 @@ typedef struct StringPropertyRNA {
PropStringLengthFunc length;
PropStringSetFunc set;
+ PropStringGetFuncEx get_ex;
+ PropStringLengthFuncEx length_ex;
+ PropStringSetFuncEx set_ex;
+
int maxlength; /* includes string terminator! */
const char *defaultvalue;
@@ -258,6 +297,9 @@ typedef struct EnumPropertyRNA {
PropEnumGetFunc get;
PropEnumSetFunc set;
PropEnumItemFunc itemf;
+
+ PropEnumGetFuncEx get_ex;
+ PropEnumSetFuncEx set_ex;
void *py_data; /* store py callback here */
EnumPropertyItem *item;
diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c
index 33bbaeec282..1577019f22a 100644
--- a/source/blender/makesrna/intern/rna_key.c
+++ b/source/blender/makesrna/intern/rna_key.c
@@ -24,14 +24,8 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "rna_internal.h"
-
#include "DNA_ID.h"
#include "DNA_scene_types.h"
#include "DNA_curve_types.h"
@@ -39,6 +33,13 @@
#include "DNA_lattice_types.h"
#include "DNA_mesh_types.h"
+#include "BLI_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "rna_internal.h"
+
#ifdef RNA_RUNTIME
#include <stddef.h>
diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c
index af39500442d..7fee67cd569 100644
--- a/source/blender/makesrna/intern/rna_lamp.c
+++ b/source/blender/makesrna/intern/rna_lamp.c
@@ -24,24 +24,25 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
+#include "BLI_math_base.h"
+
+#include "BLF_translation.h"
+
#include "RNA_define.h"
#include "RNA_enum_types.h"
-
#include "rna_internal.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_texture_types.h"
-#include "BLI_math_base.h"
-
#ifdef RNA_RUNTIME
#include "MEM_guardedalloc.h"
+#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_texture.h"
@@ -54,7 +55,7 @@ static void rna_Lamp_buffer_size_set(PointerRNA *ptr, int value)
{
Lamp *la = (Lamp *)ptr->data;
- CLAMP(value, 512, 10240);
+ CLAMP(value, 128, 10240);
la->bufsize = value;
la->bufsize &= (~15); /* round to multiple of 16 */
}
@@ -169,14 +170,14 @@ static void rna_Lamp_spot_size_set(PointerRNA *ptr, float value)
la->spotsize = RAD2DEGF(value);
}
-static void rna_Lamp_use_nodes_update(Main *blain, Scene *scene, PointerRNA *ptr)
+static void rna_Lamp_use_nodes_update(bContext *C, PointerRNA *ptr)
{
Lamp *la = (Lamp *)ptr->data;
if (la->use_nodes && la->nodetree == NULL)
- ED_node_shader_default(scene, &la->id);
+ ED_node_shader_default(C, &la->id);
- rna_Lamp_update(blain, scene, ptr);
+ rna_Lamp_update(CTX_data_main(C), CTX_data_scene(C), ptr);
}
#else
@@ -364,6 +365,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_update(prop, 0, "rna_Lamp_draw_update");
prop = RNA_def_property(srna, "distance", PROP_FLOAT, PROP_DISTANCE);
@@ -413,6 +415,7 @@ static void rna_def_lamp(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes to render the lamp");
RNA_def_property_update(prop, 0, "rna_Lamp_use_nodes_update");
@@ -540,7 +543,7 @@ static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area)
prop = RNA_def_property(srna, "shadow_buffer_size", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "bufsize");
- RNA_def_property_range(prop, 512, 10240);
+ RNA_def_property_range(prop, 128, 10240);
RNA_def_property_ui_text(prop, "Shadow Buffer Size",
"Resolution of the shadow buffer, higher values give crisper shadows "
"but use more memory");
diff --git a/source/blender/makesrna/intern/rna_lattice.c b/source/blender/makesrna/intern/rna_lattice.c
index e4a29d9c674..b2790a25e47 100644
--- a/source/blender/makesrna/intern/rna_lattice.c
+++ b/source/blender/makesrna/intern/rna_lattice.c
@@ -24,19 +24,19 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
-#include "rna_internal.h"
-
#include "DNA_curve_types.h"
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
#include "DNA_meshdata_types.h"
+#include "BLI_utildefines.h"
+
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+#include "rna_internal.h"
+
#ifdef RNA_RUNTIME
#include "DNA_object_types.h"
diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c
new file mode 100644
index 00000000000..a1225acb305
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_linestyle.c
@@ -0,0 +1,1146 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 (2008).
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/makesrna/intern/rna_linestyle.c
+ * \ingroup RNA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
+#include "DNA_linestyle_types.h"
+#include "DNA_material_types.h"
+#include "DNA_texture_types.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+EnumPropertyItem linestyle_color_modifier_type_items[] = {
+ {LS_MODIFIER_ALONG_STROKE, "ALONG_STROKE", ICON_MODIFIER, "Along Stroke", ""},
+ {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", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem linestyle_alpha_modifier_type_items[] = {
+ {LS_MODIFIER_ALONG_STROKE, "ALONG_STROKE", ICON_MODIFIER, "Along Stroke", ""},
+ {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", ""},
+ {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_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", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem linestyle_geometry_modifier_type_items[] = {
+ {LS_MODIFIER_2D_OFFSET, "2D_OFFSET", ICON_MODIFIER, "2D Offset", ""},
+ {LS_MODIFIER_2D_TRANSFORM, "2D_TRANSFORM", ICON_MODIFIER, "2D Transform", ""},
+ {LS_MODIFIER_BACKBONE_STRETCHER, "BACKBONE_STRETCHER", ICON_MODIFIER, "Backbone Stretcher", ""},
+ {LS_MODIFIER_BEZIER_CURVE, "BEZIER_CURVE", ICON_MODIFIER, "Bezier Curve", ""},
+ {LS_MODIFIER_BLUEPRINT, "BLUEPRINT", ICON_MODIFIER, "Blueprint", ""},
+ {LS_MODIFIER_GUIDING_LINES, "GUIDING_LINES", ICON_MODIFIER, "Guiding Lines", ""},
+ {LS_MODIFIER_PERLIN_NOISE_1D, "PERLIN_NOISE_1D", ICON_MODIFIER, "Perlin Noise 1D", ""},
+ {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_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", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+#ifdef RNA_RUNTIME
+
+#include "BKE_linestyle.h"
+
+static StructRNA *rna_LineStyle_color_modifier_refine(struct PointerRNA *ptr)
+{
+ LineStyleModifier *m = (LineStyleModifier *)ptr->data;
+
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ return &RNA_LineStyleColorModifier_AlongStroke;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ return &RNA_LineStyleColorModifier_DistanceFromCamera;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ return &RNA_LineStyleColorModifier_DistanceFromObject;
+ case LS_MODIFIER_MATERIAL:
+ return &RNA_LineStyleColorModifier_Material;
+ default:
+ return &RNA_LineStyleColorModifier;
+ }
+}
+
+static StructRNA *rna_LineStyle_alpha_modifier_refine(struct PointerRNA *ptr)
+{
+ LineStyleModifier *m = (LineStyleModifier *)ptr->data;
+
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ return &RNA_LineStyleAlphaModifier_AlongStroke;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ return &RNA_LineStyleAlphaModifier_DistanceFromCamera;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ return &RNA_LineStyleAlphaModifier_DistanceFromObject;
+ case LS_MODIFIER_MATERIAL:
+ return &RNA_LineStyleAlphaModifier_Material;
+ default:
+ return &RNA_LineStyleAlphaModifier;
+ }
+}
+
+static StructRNA *rna_LineStyle_thickness_modifier_refine(struct PointerRNA *ptr)
+{
+ LineStyleModifier *m = (LineStyleModifier *)ptr->data;
+
+ switch (m->type) {
+ case LS_MODIFIER_ALONG_STROKE:
+ return &RNA_LineStyleThicknessModifier_AlongStroke;
+ case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+ return &RNA_LineStyleThicknessModifier_DistanceFromCamera;
+ case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+ return &RNA_LineStyleThicknessModifier_DistanceFromObject;
+ case LS_MODIFIER_MATERIAL:
+ return &RNA_LineStyleThicknessModifier_Material;
+ case LS_MODIFIER_CALLIGRAPHY:
+ return &RNA_LineStyleThicknessModifier_Calligraphy;
+ default:
+ return &RNA_LineStyleThicknessModifier;
+ }
+}
+
+static StructRNA *rna_LineStyle_geometry_modifier_refine(struct PointerRNA *ptr)
+{
+ LineStyleModifier *m = (LineStyleModifier *)ptr->data;
+
+ switch (m->type) {
+ case LS_MODIFIER_SAMPLING:
+ return &RNA_LineStyleGeometryModifier_Sampling;
+ case LS_MODIFIER_BEZIER_CURVE:
+ return &RNA_LineStyleGeometryModifier_BezierCurve;
+ case LS_MODIFIER_SINUS_DISPLACEMENT:
+ return &RNA_LineStyleGeometryModifier_SinusDisplacement;
+ case LS_MODIFIER_SPATIAL_NOISE:
+ return &RNA_LineStyleGeometryModifier_SpatialNoise;
+ case LS_MODIFIER_PERLIN_NOISE_1D:
+ return &RNA_LineStyleGeometryModifier_PerlinNoise1D;
+ case LS_MODIFIER_PERLIN_NOISE_2D:
+ return &RNA_LineStyleGeometryModifier_PerlinNoise2D;
+ case LS_MODIFIER_BACKBONE_STRETCHER:
+ return &RNA_LineStyleGeometryModifier_BackboneStretcher;
+ case LS_MODIFIER_TIP_REMOVER:
+ return &RNA_LineStyleGeometryModifier_TipRemover;
+ case LS_MODIFIER_POLYGONIZATION:
+ return &RNA_LineStyleGeometryModifier_Polygonalization;
+ case LS_MODIFIER_GUIDING_LINES:
+ return &RNA_LineStyleGeometryModifier_GuidingLines;
+ case LS_MODIFIER_BLUEPRINT:
+ return &RNA_LineStyleGeometryModifier_Blueprint;
+ case LS_MODIFIER_2D_OFFSET:
+ return &RNA_LineStyleGeometryModifier_2DOffset;
+ case LS_MODIFIER_2D_TRANSFORM:
+ return &RNA_LineStyleGeometryModifier_2DTransform;
+ default:
+ return &RNA_LineStyleGeometryModifier;
+ }
+}
+
+static char *rna_LineStyle_color_modifier_path(PointerRNA *ptr)
+{
+ return BLI_sprintfN("color_modifiers[\"%s\"]", ((LineStyleModifier *)ptr->data)->name);
+}
+
+static char *rna_LineStyle_alpha_modifier_path(PointerRNA *ptr)
+{
+ return BLI_sprintfN("alpha_modifiers[\"%s\"]", ((LineStyleModifier *)ptr->data)->name);
+}
+
+static char *rna_LineStyle_thickness_modifier_path(PointerRNA *ptr)
+{
+ return BLI_sprintfN("thickness_modifiers[\"%s\"]", ((LineStyleModifier *)ptr->data)->name);
+}
+
+static char *rna_LineStyle_geometry_modifier_path(PointerRNA *ptr)
+{
+ return BLI_sprintfN("geometry_modifiers[\"%s\"]", ((LineStyleModifier *)ptr->data)->name);
+}
+
+static void rna_LineStyleColorModifier_name_set(PointerRNA *ptr, const char *value)
+{
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data;
+ LineStyleModifier *m = (LineStyleModifier *)ptr->data;
+
+ BLI_strncpy_utf8(m->name, value, sizeof(m->name));
+ BLI_uniquename(&linestyle->color_modifiers, m, "ColorModifier", '.',
+ offsetof(LineStyleModifier, name), sizeof(m->name));
+}
+
+static void rna_LineStyleAlphaModifier_name_set(PointerRNA *ptr, const char *value)
+{
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data;
+ LineStyleModifier *m = (LineStyleModifier *)ptr->data;
+
+ BLI_strncpy_utf8(m->name, value, sizeof(m->name));
+ BLI_uniquename(&linestyle->alpha_modifiers, m, "AlphaModifier", '.',
+ offsetof(LineStyleModifier, name), sizeof(m->name));
+}
+
+static void rna_LineStyleThicknessModifier_name_set(PointerRNA *ptr, const char *value)
+{
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data;
+ LineStyleModifier *m = (LineStyleModifier *)ptr->data;
+
+ BLI_strncpy_utf8(m->name, value, sizeof(m->name));
+ BLI_uniquename(&linestyle->thickness_modifiers, m, "ThicknessModifier", '.',
+ offsetof(LineStyleModifier, name), sizeof(m->name));
+}
+
+static void rna_LineStyleGeometryModifier_name_set(PointerRNA *ptr, const char *value)
+{
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data;
+ LineStyleModifier *m = (LineStyleModifier *)ptr->data;
+
+ BLI_strncpy_utf8(m->name, value, sizeof(m->name));
+ BLI_uniquename(&linestyle->geometry_modifiers, m, "GeometryModifier", '.',
+ offsetof(LineStyleModifier, name), sizeof(m->name));
+}
+
+#else
+
+#include "BLI_math.h"
+
+static void rna_def_modifier_type_common(StructRNA *srna, EnumPropertyItem *modifier_type_items,
+ char *set_name_func, int blend, int color)
+{
+ PropertyRNA *prop;
+
+ /* TODO: Check this is not already defined somewhere else, e.g. in nodes... */
+ static EnumPropertyItem value_blend_items[] = {
+ {LS_VALUE_BLEND, "MIX", 0, "Mix", ""},
+ {LS_VALUE_ADD, "ADD", 0, "Add", ""},
+ {LS_VALUE_SUB, "SUBTRACT", 0, "Subtract", ""},
+ {LS_VALUE_MULT, "MULTIPLY", 0, "Multiply", ""},
+ {LS_VALUE_DIV, "DIVIDE", 0, "Divide", ""},
+ {LS_VALUE_DIFF, "DIFFERENCE", 0, "Difference", ""},
+ {LS_VALUE_MIN, "MININUM", 0, "Minimum", ""},
+ {LS_VALUE_MAX, "MAXIMUM", 0, "Maximum", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "modifier.type");
+ RNA_def_property_enum_items(prop, modifier_type_items);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Modifier Type", "Type of the modifier");
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "modifier.name");
+ RNA_def_property_string_funcs(prop, NULL, NULL, set_name_func);
+ RNA_def_property_ui_text(prop, "Modifier Name", "Name of the modifier");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+ RNA_def_struct_name_property(srna, prop);
+
+ if (blend) {
+ prop = RNA_def_property(srna, "blend", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "modifier.blend");
+ RNA_def_property_enum_items(prop, (color) ? ramp_blend_items : value_blend_items);
+ RNA_def_property_ui_text(prop, "Blend", "Specify how the modifier value is blended into the base value");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "influence", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "modifier.influence");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Influence", "Influence factor by which the modifier changes the property");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+ }
+
+ prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "modifier.flags", LS_MODIFIER_ENABLED);
+ RNA_def_property_ui_text(prop, "Use", "Enable or disable this modifier during stroke rendering");
+
+ prop = RNA_def_property(srna, "expanded", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "modifier.flags", LS_MODIFIER_EXPANDED);
+ RNA_def_property_ui_text(prop, "Expanded", "True if the modifier tab is expanded");
+}
+
+static void rna_def_color_modifier(StructRNA *srna)
+{
+ rna_def_modifier_type_common(srna, linestyle_color_modifier_type_items,
+ "rna_LineStyleColorModifier_name_set", TRUE, TRUE);
+}
+
+static void rna_def_alpha_modifier(StructRNA *srna)
+{
+ rna_def_modifier_type_common(srna, linestyle_alpha_modifier_type_items,
+ "rna_LineStyleAlphaModifier_name_set", TRUE, FALSE);
+}
+
+static void rna_def_thickness_modifier(StructRNA *srna)
+{
+ rna_def_modifier_type_common(srna, linestyle_thickness_modifier_type_items,
+ "rna_LineStyleThicknessModifier_name_set", TRUE, FALSE);
+}
+
+static void rna_def_geometry_modifier(StructRNA *srna)
+{
+ rna_def_modifier_type_common(srna, linestyle_geometry_modifier_type_items,
+ "rna_LineStyleGeometryModifier_name_set", FALSE, FALSE);
+}
+
+static void rna_def_modifier_color_ramp_common(StructRNA *srna, int range)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "color_ramp", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "color_ramp");
+ RNA_def_property_struct_type(prop, "ColorRamp");
+ RNA_def_property_ui_text(prop, "Color Ramp", "Color ramp used to change line color");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ if (range) {
+ prop = RNA_def_property(srna, "range_min", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "range_min");
+ RNA_def_property_ui_text(prop, "Range Min", "Lower bound of the input range the mapping is applied");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "range_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "range_max");
+ RNA_def_property_ui_text(prop, "Range Max", "Upper bound of the input range the mapping is applied");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+ }
+}
+
+static void rna_def_modifier_curve_common(StructRNA *srna, int range, int value)
+{
+ PropertyRNA *prop;
+
+ static EnumPropertyItem mapping_items[] = {
+ {0, "LINEAR", 0, "Linear", "Use linear mapping"},
+ {LS_MODIFIER_USE_CURVE, "CURVE", 0, "Curve", "Use curve mapping"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ prop = RNA_def_property(srna, "mapping", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
+ RNA_def_property_enum_items(prop, mapping_items);
+ RNA_def_property_ui_text(prop, "Mapping", "Select the mapping type");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "invert", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", LS_MODIFIER_INVERT);
+ RNA_def_property_ui_text(prop, "Invert", "Invert the fade-out direction of the linear mapping");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "curve", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "curve");
+ RNA_def_property_struct_type(prop, "CurveMapping");
+ RNA_def_property_ui_text(prop, "Curve", "Curve used for the curve mapping");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ if (range) {
+ prop = RNA_def_property(srna, "range_min", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "range_min");
+ RNA_def_property_ui_text(prop, "Range Min", "Lower bound of the input range the mapping is applied");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "range_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "range_max");
+ RNA_def_property_ui_text(prop, "Range Max", "Upper bound of the input range the mapping is applied");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+ }
+
+ if (value) {
+ prop = RNA_def_property(srna, "value_min", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "value_min");
+ RNA_def_property_ui_text(prop, "Value Min", "Minimum output value of the mapping");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "value_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "value_max");
+ RNA_def_property_ui_text(prop, "Value Max", "Maximum output value of the mapping");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+ }
+}
+
+static void rna_def_modifier_material_common(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ static EnumPropertyItem mat_attr_items[] = {
+ {LS_MODIFIER_MATERIAL_DIFF, "DIFF", 0, "Diffuse", ""},
+ {LS_MODIFIER_MATERIAL_DIFF_R, "DIFF_R", 0, "Diffuse Red", ""},
+ {LS_MODIFIER_MATERIAL_DIFF_G, "DIFF_G", 0, "Diffuse Green", ""},
+ {LS_MODIFIER_MATERIAL_DIFF_B, "DIFF_B", 0, "Diffuse Blue", ""},
+ {LS_MODIFIER_MATERIAL_SPEC, "SPEC", 0, "Specular", ""},
+ {LS_MODIFIER_MATERIAL_SPEC_R, "SPEC_R", 0, "Specular Red", ""},
+ {LS_MODIFIER_MATERIAL_SPEC_G, "SPEC_G", 0, "Specular Green", ""},
+ {LS_MODIFIER_MATERIAL_SPEC_B, "SPEC_B", 0, "Specular Blue", ""},
+ {LS_MODIFIER_MATERIAL_SPEC_HARD, "SPEC_HARD", 0, "Specular Hardness", ""},
+ {LS_MODIFIER_MATERIAL_ALPHA, "ALPHA", 0, "Alpha", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ prop = RNA_def_property(srna, "material_attr", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "mat_attr");
+ RNA_def_property_enum_items(prop, mat_attr_items);
+ RNA_def_property_ui_text(prop, "Material Attribute", "Specify which material attribute is used");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+}
+
+static void rna_def_linestyle_modifiers(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem blueprint_shape_items[] = {
+ {LS_MODIFIER_BLUEPRINT_CIRCLES, "CIRCLES", 0, "Circles", "Draw a blueprint using circular contour strokes"},
+ {LS_MODIFIER_BLUEPRINT_ELLIPSES, "ELLIPSES", 0, "Ellipses", "Draw a blueprint using elliptic contour strokes"},
+ {LS_MODIFIER_BLUEPRINT_SQUARES, "SQUARES", 0, "Squares", "Draw a blueprint using square contour strokes"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem transform_pivot_items[] = {
+ {LS_MODIFIER_2D_TRANSFORM_PIVOT_CENTER, "CENTER", 0, "Stroke Center", ""},
+ {LS_MODIFIER_2D_TRANSFORM_PIVOT_START, "START", 0, "Stroke Start", ""},
+ {LS_MODIFIER_2D_TRANSFORM_PIVOT_END, "END", 0, "Stroke End", ""},
+ {LS_MODIFIER_2D_TRANSFORM_PIVOT_PARAM, "PARAM", 0, "Stroke Point Parameter", ""},
+ {LS_MODIFIER_2D_TRANSFORM_PIVOT_ABSOLUTE, "ABSOLUTE", 0, "Absolute 2D Point", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ srna = RNA_def_struct(brna, "LineStyleModifier", NULL);
+ RNA_def_struct_ui_text(srna, "Line Style Modifier", "Base type to define modifiers");
+
+ /* line color modifiers */
+
+ srna = RNA_def_struct(brna, "LineStyleColorModifier", "LineStyleModifier");
+ RNA_def_struct_sdna(srna, "LineStyleModifier");
+ RNA_def_struct_refine_func(srna, "rna_LineStyle_color_modifier_refine");
+ RNA_def_struct_path_func(srna, "rna_LineStyle_color_modifier_path");
+ RNA_def_struct_ui_text(srna, "Line Style Color Modifier", "Base type to define line color modifiers");
+
+ srna = RNA_def_struct(brna, "LineStyleColorModifier_AlongStroke", "LineStyleColorModifier");
+ RNA_def_struct_ui_text(srna, "Along Stroke", "Change line color along stroke");
+ rna_def_color_modifier(srna);
+ rna_def_modifier_color_ramp_common(srna, FALSE);
+
+ srna = RNA_def_struct(brna, "LineStyleColorModifier_DistanceFromCamera", "LineStyleColorModifier");
+ RNA_def_struct_ui_text(srna, "Distance from Camera", "Change line color based on the distance from the camera");
+ rna_def_color_modifier(srna);
+ rna_def_modifier_color_ramp_common(srna, TRUE);
+
+ srna = RNA_def_struct(brna, "LineStyleColorModifier_DistanceFromObject", "LineStyleColorModifier");
+ RNA_def_struct_ui_text(srna, "Distance from Object", "Change line color based on the distance from an object");
+ rna_def_color_modifier(srna);
+ rna_def_modifier_color_ramp_common(srna, TRUE);
+
+ prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "target");
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Target", "Target object from which the distance is measured");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna = RNA_def_struct(brna, "LineStyleColorModifier_Material", "LineStyleColorModifier");
+ RNA_def_struct_ui_text(srna, "Material", "Change line color based on a material attribute");
+ rna_def_color_modifier(srna);
+ rna_def_modifier_material_common(srna);
+ rna_def_modifier_color_ramp_common(srna, FALSE);
+
+ prop = RNA_def_property(srna, "use_ramp", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", LS_MODIFIER_USE_RAMP);
+ 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, NULL);
+
+ /* alpha transparency modifiers */
+
+ srna = RNA_def_struct(brna, "LineStyleAlphaModifier", "LineStyleModifier");
+ RNA_def_struct_sdna(srna, "LineStyleModifier");
+ RNA_def_struct_refine_func(srna, "rna_LineStyle_alpha_modifier_refine");
+ RNA_def_struct_path_func(srna, "rna_LineStyle_alpha_modifier_path");
+ RNA_def_struct_ui_text(srna, "Line Style Alpha Modifier", "Base type to define alpha transparency modifiers");
+
+ srna = RNA_def_struct(brna, "LineStyleAlphaModifier_AlongStroke", "LineStyleAlphaModifier");
+ RNA_def_struct_ui_text(srna, "Along Stroke", "Change alpha transparency along stroke");
+ rna_def_alpha_modifier(srna);
+ rna_def_modifier_curve_common(srna, FALSE, FALSE);
+
+ srna = RNA_def_struct(brna, "LineStyleAlphaModifier_DistanceFromCamera", "LineStyleAlphaModifier");
+ RNA_def_struct_ui_text(srna, "Distance from Camera",
+ "Change alpha transparency based on the distance from the camera");
+ rna_def_alpha_modifier(srna);
+ rna_def_modifier_curve_common(srna, TRUE, FALSE);
+
+ srna= RNA_def_struct(brna, "LineStyleAlphaModifier_DistanceFromObject", "LineStyleAlphaModifier");
+ RNA_def_struct_ui_text(srna, "Distance from Object",
+ "Change alpha transparency based on the distance from an object");
+ rna_def_alpha_modifier(srna);
+ rna_def_modifier_curve_common(srna, TRUE, FALSE);
+
+ prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "target");
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Target", "Target object from which the distance is measured");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna = RNA_def_struct(brna, "LineStyleAlphaModifier_Material", "LineStyleAlphaModifier");
+ RNA_def_struct_ui_text(srna, "Material", "Change alpha transparency based on a material attribute");
+ rna_def_alpha_modifier(srna);
+ rna_def_modifier_material_common(srna);
+ rna_def_modifier_curve_common(srna, FALSE, FALSE);
+
+ /* 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_AlongStroke", "LineStyleThicknessModifier");
+ RNA_def_struct_ui_text(srna, "Along Stroke", "Change line thickness along stroke");
+ rna_def_thickness_modifier(srna);
+ rna_def_modifier_curve_common(srna, FALSE, TRUE);
+
+ srna = RNA_def_struct(brna, "LineStyleThicknessModifier_DistanceFromCamera", "LineStyleThicknessModifier");
+ RNA_def_struct_ui_text(srna, "Distance from Camera", "Change line thickness based on the distance from the camera");
+ rna_def_thickness_modifier(srna);
+ rna_def_modifier_curve_common(srna, TRUE, TRUE);
+
+ srna = RNA_def_struct(brna, "LineStyleThicknessModifier_DistanceFromObject", "LineStyleThicknessModifier");
+ RNA_def_struct_ui_text(srna, "Distance from Object", "Change line thickness based on the distance from an object");
+ rna_def_thickness_modifier(srna);
+ rna_def_modifier_curve_common(srna, TRUE, TRUE);
+
+ prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "target");
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Target", "Target object from which the distance is measured");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna = RNA_def_struct(brna, "LineStyleThicknessModifier_Material", "LineStyleThicknessModifier");
+ RNA_def_struct_ui_text(srna, "Material", "Change line thickness based on a material attribute");
+ rna_def_thickness_modifier(srna);
+ rna_def_modifier_material_common(srna);
+ rna_def_modifier_curve_common(srna, FALSE, TRUE);
+
+ srna = RNA_def_struct(brna, "LineStyleThicknessModifier_Calligraphy", "LineStyleThicknessModifier");
+ RNA_def_struct_ui_text(srna, "Calligraphy",
+ "Change line thickness so that stroke looks like made with a calligraphic pen");
+ rna_def_thickness_modifier(srna);
+
+ prop = RNA_def_property(srna, "orientation", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "orientation");
+ RNA_def_property_ui_text(prop, "Orientation", "Angle of the main direction");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "min_thickness", 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 in the direction perpendicular to the main direction");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "max_thickness", 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 in the main direction");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ /* geometry modifiers */
+
+ srna = RNA_def_struct(brna, "LineStyleGeometryModifier", "LineStyleModifier");
+ RNA_def_struct_sdna(srna, "LineStyleModifier");
+ RNA_def_struct_refine_func(srna, "rna_LineStyle_geometry_modifier_refine");
+ RNA_def_struct_path_func(srna, "rna_LineStyle_geometry_modifier_path");
+ RNA_def_struct_ui_text(srna, "Line Style Geometry Modifier", "Base type to define stroke geometry modifiers");
+
+ srna = RNA_def_struct(brna, "LineStyleGeometryModifier_Sampling", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Sampling",
+ "Specify a new sampling value that determines the resolution of stroke polylines");
+ rna_def_geometry_modifier(srna);
+
+ prop = RNA_def_property(srna, "sampling", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "sampling");
+ RNA_def_property_ui_text(prop, "Sampling", "New sampling value to be used for subsequent modifiers");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna = RNA_def_struct(brna, "LineStyleGeometryModifier_BezierCurve", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Bezier Curve",
+ "Replace stroke backbone geometry by a Bezier curve approximation of the "
+ "original backbone geometry");
+ rna_def_geometry_modifier(srna);
+
+ prop = RNA_def_property(srna, "error", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "error");
+ RNA_def_property_ui_text(prop, "Error",
+ "Maximum distance allowed between the new Bezier curve and the "
+ "original backbone geometry)");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna = RNA_def_struct(brna, "LineStyleGeometryModifier_SinusDisplacement", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Sinus Displacement", "Add sinus displacement to stroke backbone geometry");
+ rna_def_geometry_modifier(srna);
+
+ prop = RNA_def_property(srna, "wavelength", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "wavelength");
+ RNA_def_property_ui_text(prop, "Wavelength", "Wavelength of the sinus displacement");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ 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 sinus displacement");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "phase", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "phase");
+ RNA_def_property_ui_text(prop, "Phase", "Phase of the sinus displacement");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna = RNA_def_struct(brna, "LineStyleGeometryModifier_SpatialNoise", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Spatial Noise", "Add spatial noise to stroke backbone geometry");
+ rna_def_geometry_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 spatial noise");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "scale");
+ RNA_def_property_ui_text(prop, "Scale", "Scale of the spatial noise");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "octaves", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "octaves");
+ RNA_def_property_ui_text(prop, "Octaves", "Number of octaves (i.e., the amount of detail of the spatial noise)");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "smooth", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", LS_MODIFIER_SPATIAL_NOISE_SMOOTH);
+ RNA_def_property_ui_text(prop, "Smooth", "If true, the spatial noise is smooth");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "pure_random", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", LS_MODIFIER_SPATIAL_NOISE_PURERANDOM);
+ RNA_def_property_ui_text(prop, "Pure Random", "If true, the spatial noise does not show any coherence");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna = RNA_def_struct(brna, "LineStyleGeometryModifier_PerlinNoise1D", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Perlin Noise 1D", "Add one-dimensional Perlin noise to stroke backbone geometry");
+ rna_def_geometry_modifier(srna);
+
+ prop = RNA_def_property(srna, "frequency", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "frequency");
+ RNA_def_property_ui_text(prop, "Frequency", "Frequency of the Perlin noise");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ 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 Perlin noise");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "octaves", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "octaves");
+ RNA_def_property_ui_text(prop, "Octaves", "Number of octaves (i.e., the amount of detail of the Perlin noise)");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "angle");
+ RNA_def_property_ui_text(prop, "Angle", "Displacement direction");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ 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 random number generation (if negative, time is used as a seed instead)");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna = RNA_def_struct(brna, "LineStyleGeometryModifier_PerlinNoise2D", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Perlin Noise 2D", "Add two-dimensional Perlin noise to stroke backbone geometry");
+ rna_def_geometry_modifier(srna);
+
+ prop = RNA_def_property(srna, "frequency", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "frequency");
+ RNA_def_property_ui_text(prop, "Frequency", "Frequency of the Perlin noise");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ 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 Perlin noise");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "octaves", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "octaves");
+ RNA_def_property_ui_text(prop, "Octaves", "Number of octaves (i.e., the amount of detail of the Perlin noise)");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "angle");
+ RNA_def_property_ui_text(prop, "Angle", "Displacement direction");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ 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 random number generation (if negative, time is used as a seed instead)");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna = RNA_def_struct(brna, "LineStyleGeometryModifier_BackboneStretcher", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Backbone Stretcher", "Stretch the beginning and the end of stroke backbone");
+ rna_def_geometry_modifier(srna);
+
+ prop = RNA_def_property(srna, "backbone_length", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "backbone_length");
+ RNA_def_property_ui_text(prop, "Backbone Length", "Amount of backbone stretching");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna = RNA_def_struct(brna, "LineStyleGeometryModifier_TipRemover", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Tip Remover",
+ "Remove a piece of stroke at the beginning and the end of stroke backbone");
+ rna_def_geometry_modifier(srna);
+
+ prop = RNA_def_property(srna, "tip_length", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "tip_length");
+ RNA_def_property_ui_text(prop, "Tip Length", "Length of tips to be removed");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna = RNA_def_struct(brna, "LineStyleGeometryModifier_Polygonalization", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Polygonalization", "Modify the stroke geometry so that it looks more 'polygonal'");
+ rna_def_geometry_modifier(srna);
+
+ prop = RNA_def_property(srna, "error", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "error");
+ RNA_def_property_ui_text(prop, "Error",
+ "Maximum distance between the original stroke and its polygonal approximation");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna = RNA_def_struct(brna, "LineStyleGeometryModifier_GuidingLines", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Guiding Lines",
+ "Modify the stroke geometry so that it corresponds to its main direction line");
+ rna_def_geometry_modifier(srna);
+
+ prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "offset");
+ RNA_def_property_ui_text(prop, "Offset",
+ "Displacement that is applied to the main direction line along its normal");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna = RNA_def_struct(brna, "LineStyleGeometryModifier_Blueprint", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "Blueprint",
+ "Produce a blueprint using circular, elliptic, and square contour strokes");
+ rna_def_geometry_modifier(srna);
+
+ prop = RNA_def_property(srna, "shape", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
+ RNA_def_property_enum_items(prop, blueprint_shape_items);
+ RNA_def_property_ui_text(prop, "Shape", "Select the shape of blueprint contour strokes");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "rounds", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "rounds");
+ RNA_def_property_range(prop, 1, 1000);
+ RNA_def_property_ui_text(prop, "Rounds", "Number of rounds in contour strokes");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "backbone_length", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "backbone_length");
+ RNA_def_property_ui_text(prop, "Backbone Length", "Amount of backbone stretching");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "random_radius", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "random_radius");
+ RNA_def_property_ui_text(prop, "Random Radius", "Randomness of the radius");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "random_center", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "random_center");
+ RNA_def_property_ui_text(prop, "Random Center", "Randomness of the center");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "random_backbone", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "random_backbone");
+ RNA_def_property_ui_text(prop, "Random Backbone", "Randomness of the backbone stretching");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna = RNA_def_struct(brna, "LineStyleGeometryModifier_2DOffset", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "2D Offset", "Add two-dimensional offsets to stroke backbone geometry");
+ rna_def_geometry_modifier(srna);
+
+ prop = RNA_def_property(srna, "start", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "start");
+ RNA_def_property_ui_text(prop, "Start", "Displacement that is applied from the beginning of the stroke");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "end", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "end");
+ RNA_def_property_ui_text(prop, "End", "Displacement that is applied from the end of the stroke");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "x", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "x");
+ RNA_def_property_ui_text(prop, "X", "Displacement that is applied to the X coordinates of stroke vertices");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "y", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "y");
+ RNA_def_property_ui_text(prop, "Y", "Displacement that is applied to the Y coordinates of stroke vertices");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ srna = RNA_def_struct(brna, "LineStyleGeometryModifier_2DTransform", "LineStyleGeometryModifier");
+ RNA_def_struct_ui_text(srna, "2D Transform",
+ "Apply two-dimensional scaling and rotation to stroke backbone geometry");
+ rna_def_geometry_modifier(srna);
+
+ prop = RNA_def_property(srna, "pivot", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "pivot");
+ RNA_def_property_enum_items(prop, transform_pivot_items);
+ RNA_def_property_ui_text(prop, "Pivot", "Pivot of scaling and rotation operations");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "scale_x", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "scale_x");
+ RNA_def_property_ui_text(prop, "Scale X", "Scaling factor that is applied along the X axis");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "scale_y", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "scale_y");
+ RNA_def_property_ui_text(prop, "Scale Y", "Scaling factor that is applied along the Y axis");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "angle");
+ RNA_def_property_ui_text(prop, "Rotation Angle", "Rotation angle");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "pivot_u", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "pivot_u");
+ RNA_def_property_range(prop, 0.f, 1.f);
+ RNA_def_property_ui_text(prop, "Stroke Point Parameter",
+ "Pivot in terms of the stroke point parameter u (0 <= u <= 1)");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "pivot_x", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "pivot_x");
+ RNA_def_property_ui_text(prop, "Pivot X", "2D X coordinate of the absolute pivot");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "pivot_y", PROP_FLOAT, PROP_NONE);
+ 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, NULL);
+}
+
+static void rna_def_linestyle(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem panel_items[] = {
+ {LS_PANEL_STROKES, "STROKES", 0, "Strokes", "Show the panel for stroke construction"},
+ {LS_PANEL_COLOR, "COLOR", 0, "Color", "Show the panel for line color options"},
+ {LS_PANEL_ALPHA, "ALPHA", 0, "Alpha", "Show the panel for alpha transparency options"},
+ {LS_PANEL_THICKNESS, "THICKNESS", 0, "Thickness", "Show the panel for line thickness options"},
+ {LS_PANEL_GEOMETRY, "GEOMETRY", 0, "Geometry", "Show the panel for stroke geometry options"},
+#if 0 /* hidden for now */
+ {LS_PANEL_MISC, "MISC", 0, "Misc", "Show the panel for miscellaneous options"},
+#endif
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem chaining_items[] = {
+ {LS_CHAINING_PLAIN, "PLAIN", 0, "Plain", "Plain chaining"},
+ {LS_CHAINING_SKETCHY, "SKETCHY", 0, "Sketchy", "Sketchy chaining with a multiple touch"},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem cap_items[] = {
+ {LS_CAPS_BUTT, "BUTT", 0, "Butt", "Butt cap (flat)"},
+ {LS_CAPS_ROUND, "ROUND", 0, "Round", "Round cap (half-circle)"},
+ {LS_CAPS_SQUARE, "SQUARE", 0, "Square", "Square cap (flat and extended)"},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem thickness_position_items[] = {
+ {LS_THICKNESS_CENTER, "CENTER", 0, "Center", "Stroke is centered along stroke geometry"},
+ {LS_THICKNESS_INSIDE, "INSIDE", 0, "Inside", "Stroke is drawn inside stroke geometry"},
+ {LS_THICKNESS_OUTSIDE, "OUTSIDE", 0, "Outside", "Stroke is drawn outside stroke geometry"},
+ {LS_THICKNESS_RELATIVE, "RELATIVE", 0, "Relative", "Stroke thinkness is split by a user-defined ratio"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ srna = RNA_def_struct(brna, "FreestyleLineStyle", "ID");
+ RNA_def_struct_ui_text(srna, "Freestyle Line Style", "Freestyle line style, reusable by multiple line sets");
+ RNA_def_struct_ui_icon(srna, ICON_BRUSH_DATA); /* FIXME: use a proper icon */
+
+ prop = RNA_def_property(srna, "panel", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "panel");
+ RNA_def_property_enum_items(prop, panel_items);
+ RNA_def_property_ui_text(prop, "Panel", "Select the property panel to be shown");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_float_sdna(prop, NULL, "r");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Color", "Base line color, possibly modified by line color modifiers");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "alpha");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Alpha",
+ "Base alpha transparency, possibly modified by alpha transparency modifiers");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "thickness", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "thickness");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Thickness", "Base line thickness, possibly modified by line thickness modifiers");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "thickness_position", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "thickness_position");
+ RNA_def_property_enum_items(prop, thickness_position_items);
+ RNA_def_property_ui_text(prop, "Thickness Position", "Select the position of stroke thickness");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "thickness_ratio", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "thickness_ratio");
+ RNA_def_property_range(prop, 0.f, 1.f);
+ RNA_def_property_ui_text(prop, "Thickness Ratio",
+ "A number between 0 (inside) and 1 (outside) specifying the relative position of "
+ "stroke thickness");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "color_modifiers", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "color_modifiers", NULL);
+ RNA_def_property_struct_type(prop, "LineStyleColorModifier");
+ RNA_def_property_ui_text(prop, "Color Modifiers", "List of line color modifiers");
+
+ prop = RNA_def_property(srna, "alpha_modifiers", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "alpha_modifiers", NULL);
+ RNA_def_property_struct_type(prop, "LineStyleAlphaModifier");
+ RNA_def_property_ui_text(prop, "Alpha Modifiers", "List of alpha trancparency modifiers");
+
+ prop = RNA_def_property(srna, "thickness_modifiers", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "thickness_modifiers", NULL);
+ RNA_def_property_struct_type(prop, "LineStyleThicknessModifier");
+ RNA_def_property_ui_text(prop, "Thickness Modifiers", "List of line thickness modifiers");
+
+ prop = RNA_def_property(srna, "use_chaining", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", LS_NO_CHAINING);
+ RNA_def_property_ui_text(prop, "Chaining", "Enable chaining of feature edges");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "chaining", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "chaining");
+ RNA_def_property_enum_items(prop, chaining_items);
+ RNA_def_property_ui_text(prop, "Chaining", "Select the way how feature edges are jointed to form chains");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "rounds", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "rounds");
+ RNA_def_property_range(prop, 1, 1000);
+ RNA_def_property_ui_text(prop, "Rounds", "Number of rounds in a sketchy multiple touch");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "geometry_modifiers", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "geometry_modifiers", NULL);
+ RNA_def_property_struct_type(prop, "LineStyleGeometryModifier");
+ RNA_def_property_ui_text(prop, "Geometry Modifiers", "List of stroke geometry modifiers");
+
+ prop = RNA_def_property(srna, "same_object", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_SAME_OBJECT);
+ RNA_def_property_ui_text(prop, "Same Object", "If true, only feature edges of the same object are joined");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "use_split_length", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_SPLIT_LENGTH);
+ RNA_def_property_ui_text(prop, "Use Split Length", "Enable chain splitting by curvilinear 2D length");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "split_length", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "split_length");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Split Length", "Curvilinear 2D length for chain splitting");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "use_min_angle", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_MIN_2D_ANGLE);
+ RNA_def_property_ui_text(prop, "Use Min 2D Angle",
+ "Split chains at points with angles smaller than the minimum 2D angle");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "min_angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "min_angle");
+ RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
+ RNA_def_property_ui_text(prop, "Min 2D Angle", "Minimum 2D angle for splitting chains");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "use_max_angle", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_MAX_2D_ANGLE);
+ RNA_def_property_ui_text(prop, "Use Max 2D Angle",
+ "Split chains at points with angles larger than the maximum 2D angle");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "max_angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "max_angle");
+ RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
+ RNA_def_property_ui_text(prop, "Max 2D Angle", "Maximum 2D angle for splitting chains");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "use_min_length", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_MIN_2D_LENGTH);
+ RNA_def_property_ui_text(prop, "Use Min 2D Length", "Enable the selection of chains by a minimum 2D length");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "min_length", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "min_length");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ RNA_def_property_ui_text(prop, "Min 2D Length", "Minimum curvilinear 2D length for the selection of chains");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "use_max_length", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_MAX_2D_LENGTH);
+ RNA_def_property_ui_text(prop, "Use Max 2D Length", "Enable the selection of chains by a maximum 2D length");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "max_length", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "max_length");
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
+ 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, NULL);
+
+ 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");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "split_dash1", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "split_dash1");
+ RNA_def_property_range(prop, 0, USHRT_MAX);
+ RNA_def_property_ui_text(prop, "Split Dash 1", "Length of the 1st dash for splitting");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "split_gap1", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "split_gap1");
+ RNA_def_property_range(prop, 0, USHRT_MAX);
+ RNA_def_property_ui_text(prop, "Split Gap 1", "Length of the 1st gap for splitting");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "split_dash2", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "split_dash2");
+ RNA_def_property_range(prop, 0, USHRT_MAX);
+ RNA_def_property_ui_text(prop, "Split Dash 2", "Length of the 2nd dash for splitting");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "split_gap2", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "split_gap2");
+ RNA_def_property_range(prop, 0, USHRT_MAX);
+ RNA_def_property_ui_text(prop, "Split Gap 2", "Length of the 2nd gap for splitting");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "split_dash3", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "split_dash3");
+ RNA_def_property_range(prop, 0, USHRT_MAX);
+ RNA_def_property_ui_text(prop, "Split Dash 3", "Length of the 3rd dash for splitting");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "split_gap3", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "split_gap3");
+ RNA_def_property_range(prop, 0, USHRT_MAX);
+ RNA_def_property_ui_text(prop, "Split Gap 3", "Length of the 3rd gap for splitting");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "material_boundary", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_MATERIAL_BOUNDARY);
+ RNA_def_property_ui_text(prop, "Material Boundary", "If true, chains of feature edges are split at material boundaries");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "use_dashed_line", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_DASHED_LINE);
+ RNA_def_property_ui_text(prop, "Dashed Line", "Enable or disable dashed line");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "caps", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "caps");
+ RNA_def_property_enum_items(prop, cap_items);
+ RNA_def_property_ui_text(prop, "Cap", "Select the shape of both ends of strokes");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "dash1", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "dash1");
+ RNA_def_property_range(prop, 0, USHRT_MAX);
+ RNA_def_property_ui_text(prop, "Dash 1", "Length of the 1st dash for dashed lines");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "gap1", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "gap1");
+ RNA_def_property_range(prop, 0, USHRT_MAX);
+ RNA_def_property_ui_text(prop, "Gap 1", "Length of the 1st gap for dashed lines");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "dash2", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "dash2");
+ RNA_def_property_range(prop, 0, USHRT_MAX);
+ RNA_def_property_ui_text(prop, "Dash 2", "Length of the 2nd dash for dashed lines");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "gap2", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "gap2");
+ RNA_def_property_range(prop, 0, USHRT_MAX);
+ RNA_def_property_ui_text(prop, "Gap 2", "Length of the 2nd gap for dashed lines");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "dash3", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "dash3");
+ RNA_def_property_range(prop, 0, USHRT_MAX);
+ RNA_def_property_ui_text(prop, "Dash 3", "Length of the 3rd dash for dashed lines");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+
+ prop = RNA_def_property(srna, "gap3", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "gap3");
+ RNA_def_property_range(prop, 0, USHRT_MAX);
+ RNA_def_property_ui_text(prop, "Gap 3", "Length of the 3rd gap for dashed lines");
+ RNA_def_property_update(prop, NC_LINESTYLE, NULL);
+}
+
+void RNA_def_linestyle(BlenderRNA *brna)
+{
+ rna_def_linestyle_modifiers(brna);
+ rna_def_linestyle(brna);
+}
+
+#endif
diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c
index 04b8d2fa3df..389ec426428 100644
--- a/source/blender/makesrna/intern/rna_main.c
+++ b/source/blender/makesrna/intern/rna_main.c
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <string.h>
+#include "BLI_utildefines.h"
#include "BLI_path_util.h"
#include "RNA_define.h"
@@ -258,6 +259,12 @@ static void rna_Main_masks_begin(CollectionPropertyIterator *iter, PointerRNA *p
rna_iterator_listbase_begin(iter, &bmain->mask, NULL);
}
+static void rna_Main_linestyle_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Main *bmain = (Main*)ptr->data;
+ rna_iterator_listbase_begin(iter, &bmain->linestyle, NULL);
+}
+
#ifdef UNIT_TEST
static PointerRNA rna_Test_test_get(PointerRNA *ptr)
@@ -322,6 +329,7 @@ void RNA_def_main(BlenderRNA *brna)
{"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},
+ {"linestyles", "FreestyleLineStyle", "rna_Main_linestyle_begin", "Line Styles", "Line Style datablocks", RNA_def_main_linestyles},
{NULL, NULL, NULL, NULL, NULL, NULL}
};
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index cf9415a75e7..fb0aeffcffb 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -34,7 +34,9 @@
#include <errno.h>
#include "DNA_ID.h"
+#include "DNA_modifier_types.h"
+#include "BLI_utildefines.h"
#include "BLI_path_util.h"
#include "RNA_define.h"
@@ -48,6 +50,8 @@
#include "BKE_main.h"
#include "BKE_camera.h"
#include "BKE_curve.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_displist.h"
#include "BKE_mesh.h"
#include "BKE_armature.h"
#include "BKE_lamp.h"
@@ -72,6 +76,7 @@
#include "BKE_movieclip.h"
#include "BKE_mask.h"
#include "BKE_gpencil.h"
+#include "BKE_linestyle.h"
#include "DNA_armature_types.h"
#include "DNA_camera_types.h"
@@ -99,9 +104,9 @@
#include "BLF_translation.h"
-static Camera *rna_Main_cameras_new(Main *UNUSED(bmain), const char *name)
+static Camera *rna_Main_cameras_new(Main *bmain, const char *name)
{
- ID *id = BKE_camera_add(name);
+ ID *id = BKE_camera_add(bmain, name);
id_us_min(id);
return (Camera *)id;
}
@@ -118,9 +123,9 @@ static void rna_Main_cameras_remove(Main *bmain, ReportList *reports, PointerRNA
}
}
-static Scene *rna_Main_scenes_new(Main *UNUSED(bmain), const char *name)
+static Scene *rna_Main_scenes_new(Main *bmain, const char *name)
{
- return BKE_scene_add(name);
+ return BKE_scene_add(bmain, name);
}
static void rna_Main_scenes_remove(Main *bmain, bContext *C, ReportList *reports, PointerRNA *scene_ptr)
{
@@ -144,7 +149,7 @@ static void rna_Main_scenes_remove(Main *bmain, bContext *C, ReportList *reports
}
}
-static Object *rna_Main_objects_new(Main *UNUSED(bmain), ReportList *reports, const char *name, ID *data)
+static Object *rna_Main_objects_new(Main *bmain, ReportList *reports, const char *name, ID *data)
{
Object *ob;
int type = OB_EMPTY;
@@ -189,7 +194,7 @@ static Object *rna_Main_objects_new(Main *UNUSED(bmain), ReportList *reports, co
id_us_plus(data);
}
- ob = BKE_object_add_only_object(type, name);
+ ob = BKE_object_add_only_object(bmain, type, name);
id_us_min(&ob->id);
ob->data = data;
@@ -212,9 +217,9 @@ static void rna_Main_objects_remove(Main *bmain, ReportList *reports, PointerRNA
}
}
-static Material *rna_Main_materials_new(Main *UNUSED(bmain), const char *name)
+static Material *rna_Main_materials_new(Main *bmain, const char *name)
{
- ID *id = (ID *)BKE_material_add(name);
+ ID *id = (ID *)BKE_material_add(bmain, name);
id_us_min(id);
return (Material *)id;
}
@@ -231,32 +236,240 @@ static void rna_Main_materials_remove(Main *bmain, ReportList *reports, PointerR
}
}
-static bNodeTree *rna_Main_nodetree_new(Main *UNUSED(bmain), const char *name, int type)
+static EnumPropertyItem *rna_Main_nodetree_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
{
- bNodeTree *tree = ntreeAddTree(name, type, NODE_GROUP);
-
- id_us_min(&tree->id);
- return tree;
+ return rna_node_tree_type_itemf(NULL, NULL, free);
+}
+static struct bNodeTree *rna_Main_nodetree_new(Main *bmain, const char *name, int type)
+{
+ bNodeTreeType *typeinfo = rna_node_tree_type_from_enum(type);
+ if (typeinfo) {
+ bNodeTree *ntree = ntreeAddTree(bmain, name, typeinfo->idname);
+
+ id_us_min(&ntree->id);
+ return ntree;
+ }
+ else
+ return NULL;
}
-static void rna_Main_nodetree_remove(Main *bmain, ReportList *reports, PointerRNA *tree_ptr)
+static void rna_Main_nodetree_remove(Main *bmain, ReportList *reports, PointerRNA *ntree_ptr)
{
- bNodeTree *tree = tree_ptr->data;
- if (ID_REAL_USERS(tree) <= 0) {
- BKE_libblock_free(&bmain->nodetree, tree);
- RNA_POINTER_INVALIDATE(tree_ptr);
+ bNodeTree *ntree = ntree_ptr->data;
+ if (ID_REAL_USERS(ntree) <= 0) {
+ BKE_libblock_free(&bmain->nodetree, ntree);
+ RNA_POINTER_INVALIDATE(ntree_ptr);
}
else {
BKE_reportf(reports, RPT_ERROR, "Node tree '%s' must have zero users to be removed, found %d",
- tree->id.name + 2, ID_REAL_USERS(tree));
+ ntree->id.name + 2, ID_REAL_USERS(ntree));
}
}
-static Mesh *rna_Main_meshes_new(Main *UNUSED(bmain), const char *name)
+static Mesh *rna_Main_meshes_new(Main *bmain, const char *name)
{
- Mesh *me = BKE_mesh_add(name);
+ Mesh *me = BKE_mesh_add(bmain, name);
id_us_min(&me->id);
return me;
}
+
+/* copied from Mesh_getFromObject and adapted to RNA interface */
+/* settings: 1 - preview, 2 - render */
+Mesh *rna_Main_meshes_new_from_object(
+ Main *bmain, ReportList *reports, Scene *sce,
+ Object *ob, int apply_modifiers, int settings, int calc_tessface)
+{
+ Mesh *tmpmesh;
+ Curve *tmpcu = NULL, *copycu;
+ Object *tmpobj = NULL;
+ int render = settings == eModifierMode_Render, i;
+ int cage = !apply_modifiers;
+
+ /* perform the mesh extraction based on type */
+ switch (ob->type) {
+ case OB_FONT:
+ case OB_CURVE:
+ case OB_SURF:
+ {
+ ListBase dispbase = {NULL, NULL};
+ DerivedMesh *derivedFinal = NULL;
+ int uv_from_orco;
+
+ /* copies object and modifiers (but not the data) */
+ tmpobj = BKE_object_copy_ex(bmain, ob, TRUE);
+ tmpcu = (Curve *)tmpobj->data;
+ tmpcu->id.us--;
+
+ /* if getting the original caged mesh, delete object modifiers */
+ if (cage)
+ BKE_object_free_modifiers(tmpobj);
+
+ /* copies the data */
+ copycu = tmpobj->data = BKE_curve_copy((Curve *) ob->data);
+
+ /* temporarily set edit so we get updates from edit mode, but
+ * also because for text datablocks copying it while in edit
+ * mode gives invalid data structures */
+ copycu->editfont = tmpcu->editfont;
+ copycu->editnurb = tmpcu->editnurb;
+
+ /* get updated display list, and convert to a mesh */
+ BKE_displist_make_curveTypes_forRender(sce, tmpobj, &dispbase, &derivedFinal, FALSE);
+
+ copycu->editfont = NULL;
+ copycu->editnurb = NULL;
+
+ tmpobj->derivedFinal = derivedFinal;
+
+ /* convert object type to mesh */
+ uv_from_orco = (tmpcu->flag & CU_UV_ORCO) != 0;
+ BKE_mesh_from_nurbs_displist(tmpobj, &dispbase, uv_from_orco);
+
+ tmpmesh = tmpobj->data;
+
+ BKE_displist_free(&dispbase);
+
+ /* BKE_mesh_from_nurbs changes the type to a mesh, check it worked */
+ if (tmpobj->type != OB_MESH) {
+ BKE_libblock_free_us(&(G.main->object), tmpobj);
+ BKE_report(reports, RPT_ERROR, "Cannot convert curve to mesh (does the curve have any segments?)");
+ return NULL;
+ }
+
+ BKE_libblock_free_us(&bmain->object, tmpobj);
+ break;
+ }
+
+ case OB_MBALL:
+ {
+ /* metaballs don't have modifiers, so just convert to mesh */
+ Object *basis_ob = BKE_mball_basis_find(sce, ob);
+ /* todo, re-generatre for render-res */
+ /* metaball_polygonize(scene, ob) */
+
+ if (ob != basis_ob)
+ return NULL; /* only do basis metaball */
+
+ tmpmesh = BKE_mesh_add(bmain, "Mesh");
+ /* BKE_mesh_add gives us a user count we don't need */
+ tmpmesh->id.us--;
+
+ if (render) {
+ ListBase disp = {NULL, NULL};
+ BKE_displist_make_mball_forRender(sce, ob, &disp);
+ BKE_mesh_from_metaball(&disp, tmpmesh);
+ BKE_displist_free(&disp);
+ }
+ else
+ BKE_mesh_from_metaball(&ob->disp, tmpmesh);
+
+ break;
+
+ }
+ case OB_MESH:
+ /* copies object and modifiers (but not the data) */
+ if (cage) {
+ /* copies the data */
+ tmpmesh = BKE_mesh_copy_ex(bmain, ob->data);
+ /* if not getting the original caged mesh, get final derived mesh */
+ }
+ else {
+ /* Make a dummy mesh, saves copying */
+ DerivedMesh *dm;
+ /* CustomDataMask mask = CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL; */
+ CustomDataMask mask = CD_MASK_MESH; /* this seems more suitable, exporter,
+ * for example, needs CD_MASK_MDEFORMVERT */
+
+ /* Write the display mesh into the dummy mesh */
+ if (render)
+ dm = mesh_create_derived_render(sce, ob, mask);
+ else
+ dm = mesh_create_derived_view(sce, ob, mask);
+
+ tmpmesh = BKE_mesh_add(bmain, "Mesh");
+ DM_to_mesh(dm, tmpmesh, ob);
+ dm->release(dm);
+ }
+
+ /* BKE_mesh_add/copy gives us a user count we don't need */
+ tmpmesh->id.us--;
+
+ break;
+ default:
+ BKE_report(reports, RPT_ERROR, "Object does not have geometry data");
+ return NULL;
+ }
+
+ /* Copy materials to new mesh */
+ switch (ob->type) {
+ case OB_SURF:
+ case OB_FONT:
+ case OB_CURVE:
+ tmpmesh->totcol = tmpcu->totcol;
+
+ /* free old material list (if it exists) and adjust user counts */
+ if (tmpcu->mat) {
+ for (i = tmpcu->totcol; i-- > 0; ) {
+ /* are we an object material or data based? */
+
+ tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : tmpcu->mat[i];
+
+ if (tmpmesh->mat[i]) {
+ tmpmesh->mat[i]->id.us++;
+ }
+ }
+ }
+ break;
+
+#if 0
+ /* Crashes when assigning the new material, not sure why */
+ case OB_MBALL:
+ tmpmb = (MetaBall *)ob->data;
+ tmpmesh->totcol = tmpmb->totcol;
+
+ /* free old material list (if it exists) and adjust user counts */
+ if (tmpmb->mat) {
+ for (i = tmpmb->totcol; i-- > 0; ) {
+ tmpmesh->mat[i] = tmpmb->mat[i]; /* CRASH HERE ??? */
+ if (tmpmesh->mat[i]) {
+ tmpmb->mat[i]->id.us++;
+ }
+ }
+ }
+ break;
+#endif
+
+ case OB_MESH:
+ if (!cage) {
+ Mesh *origmesh = ob->data;
+ tmpmesh->flag = origmesh->flag;
+ tmpmesh->mat = MEM_dupallocN(origmesh->mat);
+ tmpmesh->totcol = origmesh->totcol;
+ tmpmesh->smoothresh = origmesh->smoothresh;
+ if (origmesh->mat) {
+ for (i = origmesh->totcol; i-- > 0; ) {
+ /* are we an object material or data based? */
+ tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : origmesh->mat[i];
+
+ if (tmpmesh->mat[i]) {
+ tmpmesh->mat[i]->id.us++;
+ }
+ }
+ }
+ }
+ break;
+ } /* end copy materials */
+
+ if (calc_tessface) {
+ /* cycles and exporters rely on this still */
+ BKE_mesh_tessface_ensure(tmpmesh);
+ }
+
+ /* make sure materials get updated in objects */
+ test_object_materials(&tmpmesh->id);
+
+ return tmpmesh;
+}
+
static void rna_Main_meshes_remove(Main *bmain, ReportList *reports, PointerRNA *mesh_ptr)
{
Mesh *mesh = mesh_ptr->data;
@@ -270,9 +483,9 @@ static void rna_Main_meshes_remove(Main *bmain, ReportList *reports, PointerRNA
}
}
-static Lamp *rna_Main_lamps_new(Main *UNUSED(bmain), const char *name, int type)
+static Lamp *rna_Main_lamps_new(Main *bmain, const char *name, int type)
{
- Lamp *lamp = BKE_lamp_add(name);
+ Lamp *lamp = BKE_lamp_add(bmain, name);
lamp->type = type;
id_us_min(&lamp->id);
return lamp;
@@ -290,19 +503,19 @@ static void rna_Main_lamps_remove(Main *bmain, ReportList *reports, PointerRNA *
}
}
-static Image *rna_Main_images_new(Main *UNUSED(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)
{
float color[4] = {0.0, 0.0, 0.0, 1.0};
- Image *image = BKE_image_add_generated(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);
id_us_min(&image->id);
return image;
}
-static Image *rna_Main_images_load(Main *UNUSED(bmain), ReportList *reports, const char *filepath)
+static Image *rna_Main_images_load(Main *bmain, ReportList *reports, const char *filepath)
{
Image *ima;
errno = 0;
- ima = BKE_image_load(filepath);
+ ima = BKE_image_load(bmain, filepath);
if (!ima) {
BKE_reportf(reports, RPT_ERROR, "Cannot read '%s': %s", filepath,
@@ -324,9 +537,9 @@ static void rna_Main_images_remove(Main *bmain, ReportList *reports, PointerRNA
}
}
-static Lattice *rna_Main_lattices_new(Main *UNUSED(bmain), const char *name)
+static Lattice *rna_Main_lattices_new(Main *bmain, const char *name)
{
- Lattice *lt = BKE_lattice_add(name);
+ Lattice *lt = BKE_lattice_add(bmain, name);
id_us_min(&lt->id);
return lt;
}
@@ -343,9 +556,9 @@ static void rna_Main_lattices_remove(Main *bmain, ReportList *reports, PointerRN
}
}
-static Curve *rna_Main_curves_new(Main *UNUSED(bmain), const char *name, int type)
+static Curve *rna_Main_curves_new(Main *bmain, const char *name, int type)
{
- Curve *cu = BKE_curve_add(name, type);
+ Curve *cu = BKE_curve_add(bmain, name, type);
id_us_min(&cu->id);
return cu;
}
@@ -362,9 +575,9 @@ static void rna_Main_curves_remove(Main *bmain, ReportList *reports, PointerRNA
}
}
-static MetaBall *rna_Main_metaballs_new(Main *UNUSED(bmain), const char *name)
+static MetaBall *rna_Main_metaballs_new(Main *bmain, const char *name)
{
- MetaBall *mb = BKE_mball_add(name);
+ MetaBall *mb = BKE_mball_add(bmain, name);
id_us_min(&mb->id);
return mb;
}
@@ -408,9 +621,9 @@ static void rna_Main_fonts_remove(Main *bmain, ReportList *reports, PointerRNA *
}
}
-static Tex *rna_Main_textures_new(Main *UNUSED(bmain), const char *name, int type)
+static Tex *rna_Main_textures_new(Main *bmain, const char *name, int type)
{
- Tex *tex = add_texture(name);
+ Tex *tex = add_texture(bmain, name);
tex_set_type(tex, type);
id_us_min(&tex->id);
return tex;
@@ -428,9 +641,9 @@ static void rna_Main_textures_remove(Main *bmain, ReportList *reports, PointerRN
}
}
-static Brush *rna_Main_brushes_new(Main *UNUSED(bmain), const char *name)
+static Brush *rna_Main_brushes_new(Main *bmain, const char *name)
{
- Brush *brush = BKE_brush_add(name);
+ Brush *brush = BKE_brush_add(bmain, name);
id_us_min(&brush->id);
return brush;
}
@@ -447,9 +660,9 @@ static void rna_Main_brushes_remove(Main *bmain, ReportList *reports, PointerRNA
}
}
-static World *rna_Main_worlds_new(Main *UNUSED(bmain), const char *name)
+static World *rna_Main_worlds_new(Main *bmain, const char *name)
{
- World *world = add_world(name);
+ World *world = add_world(bmain, name);
id_us_min(&world->id);
return world;
}
@@ -466,9 +679,9 @@ static void rna_Main_worlds_remove(Main *bmain, ReportList *reports, PointerRNA
}
}
-static Group *rna_Main_groups_new(Main *UNUSED(bmain), const char *name)
+static Group *rna_Main_groups_new(Main *bmain, const char *name)
{
- return add_group(name);
+ return add_group(bmain, name);
}
static void rna_Main_groups_remove(Main *bmain, PointerRNA *group_ptr)
{
@@ -478,9 +691,9 @@ static void rna_Main_groups_remove(Main *bmain, PointerRNA *group_ptr)
RNA_POINTER_INVALIDATE(group_ptr);
}
-static Speaker *rna_Main_speakers_new(Main *UNUSED(bmain), const char *name)
+static Speaker *rna_Main_speakers_new(Main *bmain, const char *name)
{
- Speaker *speaker = BKE_speaker_add(name);
+ Speaker *speaker = BKE_speaker_add(bmain, name);
id_us_min(&speaker->id);
return speaker;
}
@@ -497,9 +710,9 @@ static void rna_Main_speakers_remove(Main *bmain, ReportList *reports, PointerRN
}
}
-static Text *rna_Main_texts_new(Main *UNUSED(bmain), const char *name)
+static Text *rna_Main_texts_new(Main *bmain, const char *name)
{
- return BKE_text_add(name);
+ return BKE_text_add(bmain, name);
}
static void rna_Main_texts_remove(Main *bmain, PointerRNA *text_ptr)
{
@@ -514,7 +727,7 @@ static Text *rna_Main_texts_load(Main *bmain, ReportList *reports, const char *f
Text *txt;
errno = 0;
- txt = BKE_text_load(filepath, bmain->name);
+ txt = BKE_text_load(bmain, filepath, bmain->name);
if (!txt)
BKE_reportf(reports, RPT_ERROR, "Cannot read '%s': %s", filepath,
@@ -523,9 +736,9 @@ static Text *rna_Main_texts_load(Main *bmain, ReportList *reports, const char *f
return txt;
}
-static bArmature *rna_Main_armatures_new(Main *UNUSED(bmain), const char *name)
+static bArmature *rna_Main_armatures_new(Main *bmain, const char *name)
{
- bArmature *arm = BKE_armature_add(name);
+ bArmature *arm = BKE_armature_add(bmain, name);
id_us_min(&arm->id);
return arm;
}
@@ -542,9 +755,9 @@ static void rna_Main_armatures_remove(Main *bmain, ReportList *reports, PointerR
}
}
-static bAction *rna_Main_actions_new(Main *UNUSED(bmain), const char *name)
+static bAction *rna_Main_actions_new(Main *bmain, const char *name)
{
- bAction *act = add_empty_action(name);
+ bAction *act = add_empty_action(bmain, name);
id_us_min(&act->id);
act->id.flag &= ~LIB_FAKEUSER;
return act;
@@ -581,12 +794,12 @@ static void rna_Main_particles_remove(Main *bmain, ReportList *reports, PointerR
}
}
-static MovieClip *rna_Main_movieclip_load(Main *UNUSED(bmain), ReportList *reports, const char *filepath)
+static MovieClip *rna_Main_movieclip_load(Main *bmain, ReportList *reports, const char *filepath)
{
MovieClip *clip;
errno = 0;
- clip = BKE_movieclip_file_add(filepath);
+ clip = BKE_movieclip_file_add(bmain, filepath);
if (!clip)
BKE_reportf(reports, RPT_ERROR, "Cannot read '%s': %s", filepath,
@@ -603,11 +816,11 @@ static void rna_Main_movieclips_remove(Main *bmain, PointerRNA *clip_ptr)
RNA_POINTER_INVALIDATE(clip_ptr);
}
-static Mask *rna_Main_mask_new(Main *UNUSED(bmain), const char *name)
+static Mask *rna_Main_mask_new(Main *bmain, const char *name)
{
Mask *mask;
- mask = BKE_mask_new("Mask");
+ mask = BKE_mask_new(bmain, "Mask");
return mask;
}
@@ -633,6 +846,23 @@ static void rna_Main_grease_pencil_remove(Main *bmain, ReportList *reports, Poin
gpd->id.name + 2, ID_REAL_USERS(gpd));
}
+FreestyleLineStyle *rna_Main_linestyles_new(Main *bmain, const char* name)
+{
+ FreestyleLineStyle *linestyle = BKE_new_linestyle(name, bmain);
+ id_us_min(&linestyle->id);
+ return linestyle;
+}
+
+void rna_Main_linestyles_remove(Main *bmain, ReportList *reports, FreestyleLineStyle *linestyle)
+{
+ if(ID_REAL_USERS(linestyle) <= 0)
+ BKE_libblock_free(&bmain->linestyle, linestyle);
+ else
+ BKE_reportf(reports, RPT_ERROR, "Line style '%s' must have zero users to be removed, found %d", linestyle->id.name+2, ID_REAL_USERS(linestyle));
+
+ /* XXX python now has invalid pointer? */
+}
+
/* tag functions, all the same */
static void rna_Main_cameras_tag(Main *bmain, int value) { tag_main_lb(&bmain->camera, value); }
static void rna_Main_scenes_tag(Main *bmain, int value) { tag_main_lb(&bmain->scene, value); }
@@ -664,6 +894,7 @@ static void rna_Main_particles_tag(Main *bmain, int value) { tag_main_lb(&bmain-
static void rna_Main_gpencil_tag(Main *bmain, int value) { tag_main_lb(&bmain->gpencil, value); }
static void rna_Main_movieclips_tag(Main *bmain, int value) { tag_main_lb(&bmain->movieclip, value); }
static void rna_Main_masks_tag(Main *bmain, int value) { tag_main_lb(&bmain->mask, value); }
+static void rna_Main_linestyle_tag(Main *bmain, int value) { tag_main_lb(&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); }
@@ -866,10 +1097,8 @@ void RNA_def_main_node_groups(BlenderRNA *brna, PropertyRNA *cprop)
PropertyRNA *parm;
PropertyRNA *prop;
- static EnumPropertyItem node_nodetree_items[] = {
- {0, "SHADER", 0, "Shader", ""},
- {1, "COMPOSITE", 0, "Composite", ""},
- {2, "TEXTURE", 0, "Texture", ""},
+ static EnumPropertyItem dummy_items[] = {
+ {0, "DUMMY", 0, "", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -882,7 +1111,8 @@ void RNA_def_main_node_groups(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_ui_description(func, "Add a new node tree to the main database");
parm = RNA_def_string(func, "name", "NodeGroup", 0, "", "New name for the datablock");
RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_enum(func, "type", node_nodetree_items, 0, "Type", "The type of node_group to add");
+ parm = RNA_def_enum(func, "type", dummy_items, 0, "Type", "The type of node_group to add");
+ RNA_def_property_enum_funcs(parm, NULL, NULL, "rna_Main_nodetree_type_itemf");
RNA_def_property_flag(parm, PROP_REQUIRED);
/* return type */
parm = RNA_def_pointer(func, "tree", "NodeTree", "", "New node tree datablock");
@@ -910,6 +1140,12 @@ void RNA_def_main_meshes(BlenderRNA *brna, PropertyRNA *cprop)
PropertyRNA *parm;
PropertyRNA *prop;
+ static EnumPropertyItem mesh_type_items[] = {
+ {eModifierMode_Realtime, "PREVIEW", 0, "Preview", "Apply modifier preview settings"},
+ {eModifierMode_Render, "RENDER", 0, "Render", "Apply modifier render settings"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
RNA_def_property_srna(cprop, "BlendDataMeshes");
srna = RNA_def_struct(brna, "BlendDataMeshes", NULL);
RNA_def_struct_sdna(srna, "Main");
@@ -923,6 +1159,22 @@ void RNA_def_main_meshes(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "mesh", "Mesh", "", "New mesh datablock");
RNA_def_function_return(func, parm);
+ func = RNA_def_function(srna, "new_from_object", "rna_Main_meshes_new_from_object");
+ RNA_def_function_ui_description(func, "Add a new mesh created from object with modifiers applied");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene within which to evaluate modifiers");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_pointer(func, "object", "Object", "", "Object to create mesh from");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_enum(func, "settings", mesh_type_items, 0, "", "Modifier settings to apply");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_boolean(func, "calc_tessface", true, "Calculate Tessellation", "Calculate tessellation faces");
+ parm = RNA_def_pointer(func, "mesh", "Mesh", "",
+ "Mesh created from object, remove it if it is only used for export");
+ RNA_def_function_return(func, parm);
+
func = RNA_def_function(srna, "remove", "rna_Main_meshes_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a mesh from the current blendfile");
@@ -1685,4 +1937,30 @@ void RNA_def_main_masks(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
}
+void RNA_def_main_linestyles(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "BlendDataLineStyles");
+ srna = RNA_def_struct(brna, "BlendDataLineStyles", NULL);
+ RNA_def_struct_sdna(srna, "Main");
+ RNA_def_struct_ui_text(srna, "Main Line Styles", "Collection of line styles");
+
+ func = RNA_def_function(srna, "new", "rna_Main_linestyles_new");
+ RNA_def_function_ui_description(func, "Add a new line style instance to the main database");
+ parm = RNA_def_string(func, "name", "FreestyleLineStyle", 0, "", "New name for the datablock");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ /* return type */
+ parm = RNA_def_pointer(func, "linestyle", "FreestyleLineStyle", "", "New line style datablock");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_Main_linestyles_remove");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_ui_description(func, "Remove a line style instance from the current blendfile");
+ parm = RNA_def_pointer(func, "linestyle", "FreestyleLineStyle", "", "Line style to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+}
+
#endif
diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c
index 3f23a376ea3..72b0030ee23 100644
--- a/source/blender/makesrna/intern/rna_mask.c
+++ b/source/blender/makesrna/intern/rna_mask.c
@@ -31,6 +31,10 @@
#include "MEM_guardedalloc.h"
+#include "DNA_mask_types.h"
+#include "DNA_object_types.h" /* SELECT */
+#include "DNA_scene_types.h"
+
#include "BKE_movieclip.h"
#include "BKE_tracking.h"
@@ -39,10 +43,6 @@
#include "rna_internal.h"
-#include "DNA_mask_types.h"
-#include "DNA_object_types.h" /* SELECT */
-#include "DNA_scene_types.h"
-
#include "WM_types.h"
#include "IMB_imbuf_types.h"
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index 1221b84372c..8936609c7db 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -24,17 +24,16 @@
* \ingroup RNA
*/
-
#include <float.h>
#include <stdlib.h>
+#include "DNA_material_types.h"
+#include "DNA_texture_types.h"
+
#include "RNA_define.h"
#include "rna_internal.h"
-#include "DNA_material_types.h"
-#include "DNA_texture_types.h"
-
#include "WM_api.h"
#include "WM_types.h"
@@ -83,6 +82,7 @@ EnumPropertyItem ramp_blend_items[] = {
#include "DNA_node_types.h"
#include "DNA_object_types.h"
+#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -112,9 +112,9 @@ static void rna_Material_update_previews(Main *bmain, Scene *scene, PointerRNA *
Material *ma = ptr->id.data;
if (ma->nodetree)
- ntreeClearPreview(ma->nodetree);
+ BKE_node_preview_clear_tree(ma->nodetree);
- rna_Material_update(bmain, scene, ptr);
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING, ma);
}
@@ -274,7 +274,7 @@ static void rna_Material_use_diffuse_ramp_set(PointerRNA *ptr, int value)
else ma->mode &= ~MA_RAMP_COL;
if ((ma->mode & MA_RAMP_COL) && ma->ramp_col == NULL)
- ma->ramp_col = add_colorband(0);
+ ma->ramp_col = add_colorband(false);
}
static void rna_Material_use_specular_ramp_set(PointerRNA *ptr, int value)
@@ -285,17 +285,17 @@ static void rna_Material_use_specular_ramp_set(PointerRNA *ptr, int value)
else ma->mode &= ~MA_RAMP_SPEC;
if ((ma->mode & MA_RAMP_SPEC) && ma->ramp_spec == NULL)
- ma->ramp_spec = add_colorband(0);
+ ma->ramp_spec = add_colorband(false);
}
-static void rna_Material_use_nodes_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Material_use_nodes_update(bContext *C, PointerRNA *ptr)
{
Material *ma = (Material *)ptr->data;
if (ma->use_nodes && ma->nodetree == NULL)
- ED_node_shader_default(scene, &ma->id);
+ ED_node_shader_default(C, &ma->id);
- rna_Material_update(bmain, scene, ptr);
+ rna_Material_update(CTX_data_main(C), CTX_data_scene(C), ptr);
}
static EnumPropertyItem *rna_Material_texture_coordinates_itemf(bContext *UNUSED(C), PointerRNA *ptr,
@@ -2025,6 +2025,7 @@ void RNA_def_material(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes to render the material");
RNA_def_property_update(prop, 0, "rna_Material_use_nodes_update");
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index cdf8d6614f3..aed0e49cf7e 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -28,28 +28,27 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
#include "MEM_guardedalloc.h"
-#include "RNA_access.h"
-#include "RNA_define.h"
-#include "RNA_types.h"
-
-#include "rna_internal.h"
-
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "WM_types.h"
-
#include "BLI_array.h"
#include "BLI_math_base.h"
#include "BLI_math_rotation.h"
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_types.h"
+
+#include "rna_internal.h"
+
+#include "WM_types.h"
+
#ifdef RNA_RUNTIME
#include "DNA_scene_types.h"
@@ -152,8 +151,8 @@ void rna_Mesh_update_draw(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_Mesh_update_vertmask(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Mesh *me = ptr->data;
- if ((me->editflag & ME_EDIT_VERT_SEL) && (me->editflag & ME_EDIT_PAINT_MASK)) {
- me->editflag ^= ME_EDIT_PAINT_MASK;
+ if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) && (me->editflag & ME_EDIT_PAINT_FACE_SEL)) {
+ me->editflag &= ~ME_EDIT_PAINT_FACE_SEL;
}
rna_Mesh_update_draw(bmain, scene, ptr);
}
@@ -161,8 +160,8 @@ static void rna_Mesh_update_vertmask(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_Mesh_update_facemask(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Mesh *me = ptr->data;
- if ((me->editflag & ME_EDIT_VERT_SEL) && (me->editflag & ME_EDIT_PAINT_MASK)) {
- me->editflag ^= ME_EDIT_VERT_SEL;
+ if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) && (me->editflag & ME_EDIT_PAINT_FACE_SEL)) {
+ me->editflag &= ~ME_EDIT_PAINT_VERT_SEL;
}
rna_Mesh_update_draw(bmain, scene, ptr);
}
@@ -529,7 +528,7 @@ static void rna_CustomDataLayer_active_set(PointerRNA *ptr, CustomData *data, in
else CustomData_set_layer_active(ldata, CD_MLOOPUV, n);
}
- mesh_update_customdata_pointers(me, TRUE);
+ BKE_mesh_update_customdata_pointers(me, true);
}
static void rna_CustomDataLayer_clone_set(PointerRNA *ptr, CustomData *data, int value, int type, int render)
@@ -552,7 +551,7 @@ DEFINE_CUSTOMDATA_LAYER_COLLECTION_ACTIVEITEM(uv_layer, ldata, CD_MLOOPUV, rende
/* MeshUVLoopLayer */
-static char *rna_MeshUVLoopLayer_path(PointerRNA * ptr)
+static char *rna_MeshUVLoopLayer_path(PointerRNA *ptr)
{
return BLI_sprintfN("uv_layers[\"%s\"]", ((CustomDataLayer *)ptr->data)->name);
}
@@ -1233,6 +1232,26 @@ static char *rna_MeshStringProperty_path(PointerRNA *ptr)
return rna_PolyCustomData_data_path(ptr, "layers_string", CD_PROP_STR);
}
+/* XXX, we dont have propper byte string support yet, so for now use the (bytes + 1)
+ * bmesh API exposes correct python/bytestring access */
+void rna_MeshStringProperty_s_get(PointerRNA *ptr, char *value)
+{
+ MStringProperty *ms = (MStringProperty *)ptr->data;
+ BLI_strncpy(value, ms->s, (int)ms->s_len + 1);
+}
+
+int rna_MeshStringProperty_s_length(PointerRNA *ptr)
+{
+ MStringProperty *ms = (MStringProperty *)ptr->data;
+ return (int)ms->s_len + 1;
+}
+
+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)
{
Mesh *me = rna_mesh(ptr);
@@ -1249,12 +1268,12 @@ static int rna_Mesh_tot_face_get(PointerRNA *ptr)
return me->edit_btmesh ? me->edit_btmesh->bm->totfacesel : 0;
}
-static PointerRNA rna_Mesh_vertex_color_new(struct Mesh *me, struct bContext *C, const char *name)
+static PointerRNA rna_Mesh_vertex_color_new(struct Mesh *me, const char *name)
{
PointerRNA ptr;
CustomData *ldata;
CustomDataLayer *cdl = NULL;
- int index = ED_mesh_color_add(C, NULL, NULL, me, name, FALSE);
+ int index = ED_mesh_color_add(me, name, false);
if (index != -1) {
ldata = rna_mesh_ldata_helper(me);
@@ -1265,8 +1284,14 @@ static PointerRNA rna_Mesh_vertex_color_new(struct Mesh *me, struct bContext *C,
return ptr;
}
-static PointerRNA rna_Mesh_tessface_vertex_color_new(struct Mesh *me, struct bContext *C, ReportList *reports,
- const char *name)
+static void rna_Mesh_vertex_color_remove(struct Mesh *me, ReportList *reports, CustomDataLayer *layer)
+{
+ if (ED_mesh_color_remove_named(me, layer->name) == false) {
+ BKE_reportf(reports, RPT_ERROR, "vertex color '%s' not found", layer->name);
+ }
+}
+
+static PointerRNA rna_Mesh_tessface_vertex_color_new(struct Mesh *me, ReportList *reports, const char *name)
{
PointerRNA ptr;
CustomData *fdata;
@@ -1283,7 +1308,7 @@ static PointerRNA rna_Mesh_tessface_vertex_color_new(struct Mesh *me, struct bCo
return PointerRNA_NULL;
}
- index = ED_mesh_color_add(C, NULL, NULL, me, name, FALSE);
+ index = ED_mesh_color_add(me, name, false);
if (index != -1) {
fdata = rna_mesh_fdata_helper(me);
@@ -1339,12 +1364,12 @@ static PointerRNA rna_Mesh_polygon_string_property_new(struct Mesh *me, struct b
return ptr;
}
-static PointerRNA rna_Mesh_uv_texture_new(struct Mesh *me, struct bContext *C, const char *name)
+static PointerRNA rna_Mesh_uv_texture_new(struct Mesh *me, const char *name)
{
PointerRNA ptr;
CustomData *pdata;
CustomDataLayer *cdl = NULL;
- int index = ED_mesh_uv_texture_add(C, me, name, FALSE);
+ int index = ED_mesh_uv_texture_add(me, name, false);
if (index != -1) {
pdata = rna_mesh_pdata_helper(me);
@@ -1355,11 +1380,17 @@ static PointerRNA rna_Mesh_uv_texture_new(struct Mesh *me, struct bContext *C, c
return ptr;
}
+static void rna_Mesh_uv_texture_layers_remove(struct Mesh *me, ReportList *reports, CustomDataLayer *layer)
+{
+ if (ED_mesh_uv_texture_remove_named(me, layer->name) == false) {
+ BKE_reportf(reports, RPT_ERROR, "texture layer '%s' not found", layer->name);
+ }
+}
+
/* while this is supposed to be readonly,
* keep it to support importers that only make tessfaces */
-static PointerRNA rna_Mesh_tessface_uv_texture_new(struct Mesh *me, struct bContext *C, ReportList *reports,
- const char *name)
+static PointerRNA rna_Mesh_tessface_uv_texture_new(struct Mesh *me, ReportList *reports, const char *name)
{
PointerRNA ptr;
CustomData *fdata;
@@ -1376,7 +1407,7 @@ static PointerRNA rna_Mesh_tessface_uv_texture_new(struct Mesh *me, struct bCont
return PointerRNA_NULL;
}
- index = ED_mesh_uv_texture_add(C, me, name, FALSE);
+ index = ED_mesh_uv_texture_add(me, name, false);
if (index != -1) {
fdata = rna_mesh_fdata_helper(me);
@@ -1550,6 +1581,13 @@ static void rna_def_medge(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Sharp", "Sharp edge for the EdgeSplit modifier");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+#ifdef WITH_FREESTYLE /* TO BE REMOVED when the trunk merger is done */
+ prop = RNA_def_property(srna, "use_freestyle_edge_mark", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_FREESTYLE_EDGE);
+ RNA_def_property_ui_text(prop, "Freestyle Edge Mark", "Edge mark for Freestyle feature edge detection");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+#endif
+
prop = RNA_def_property(srna, "is_loose", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_LOOSEEDGE);
RNA_def_property_ui_text(prop, "Loose", "Loose edge");
@@ -1605,6 +1643,13 @@ static void rna_def_mface(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_SMOOTH);
RNA_def_property_ui_text(prop, "Smooth", "");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+
+#ifdef WITH_FREESTYLE /* TO BE REMOVED when the trunk merger is done */
+ prop = RNA_def_property(srna, "use_freestyle_face_mark", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_FREESTYLE_FACE);
+ RNA_def_property_ui_text(prop, "Freestyle Face Mark", "Face mark for Freestyle feature edge detection");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+#endif
prop = RNA_def_property(srna, "normal", PROP_FLOAT, PROP_DIRECTION);
RNA_def_property_array(prop, 3);
@@ -1703,6 +1748,11 @@ static void rna_def_mpolygon(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Smooth", "");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+ prop = RNA_def_property(srna, "use_freestyle_face_mark", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_FREESTYLE_FACE);
+ RNA_def_property_ui_text(prop, "Freestyle Face Mark", "Face mark for Freestyle feature edge detection");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+
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);
@@ -2161,6 +2211,7 @@ static void rna_def_mproperties(BlenderRNA *brna)
/* 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");
}
@@ -2346,7 +2397,7 @@ static void rna_def_tessface_vertex_colors(BlenderRNA *brna, PropertyRNA *cprop)
/* eventually deprecate this */
func = RNA_def_function(srna, "new", "rna_Mesh_tessface_vertex_color_new");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Add a vertex color layer to Mesh");
RNA_def_string(func, "name", "Col", 0, "", "Vertex color name");
parm = RNA_def_pointer(func, "layer", "MeshColorLayer", "", "The newly created layer");
@@ -2381,27 +2432,24 @@ static void rna_def_loop_colors(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_struct_ui_text(srna, "Loop Colors", "Collection of vertex colors");
func = RNA_def_function(srna, "new", "rna_Mesh_vertex_color_new");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT);
RNA_def_function_ui_description(func, "Add a vertex color layer to Mesh");
RNA_def_string(func, "name", "Col", 0, "", "Vertex color name");
parm = RNA_def_pointer(func, "layer", "MeshLoopColorLayer", "", "The newly created layer");
RNA_def_property_flag(parm, PROP_RNAPTR);
RNA_def_function_return(func, parm);
-#if 0
func = RNA_def_function(srna, "remove", "rna_Mesh_vertex_color_remove");
RNA_def_function_ui_description(func, "Remove a vertex color layer");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "layer", "Layer", "", "The layer to remove");
- RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ parm = RNA_def_pointer(func, "layer", "MeshLoopColorLayer", "", "The layer to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
-#endif
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "MeshLoopColorLayer");
RNA_def_property_pointer_funcs(prop, "rna_Mesh_vertex_color_active_get",
"rna_Mesh_vertex_color_active_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
RNA_def_property_ui_text(prop, "Active Vertex Color Layer", "Active vertex color layer");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
@@ -2429,7 +2477,7 @@ static void rna_def_uv_layers(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_struct_type(prop, "MeshUVLoopLayer");
RNA_def_property_pointer_funcs(prop, "rna_Mesh_uv_layer_active_get",
"rna_Mesh_uv_layer_active_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
RNA_def_property_ui_text(prop, "Active UV loop layer", "Active UV loop layer");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
@@ -2522,7 +2570,7 @@ static void rna_def_tessface_uv_textures(BlenderRNA *brna, PropertyRNA *cprop)
/* eventually deprecate this */
func = RNA_def_function(srna, "new", "rna_Mesh_tessface_uv_texture_new");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Add a UV tessface-texture layer to Mesh (only for meshes with no polygons)");
RNA_def_string(func, "name", "UVMap", 0, "", "UV map name");
parm = RNA_def_pointer(func, "layer", "MeshTextureFaceLayer", "", "The newly created layer");
@@ -2559,27 +2607,23 @@ static void rna_def_uv_textures(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_struct_ui_text(srna, "UV Maps", "Collection of UV maps");
func = RNA_def_function(srna, "new", "rna_Mesh_uv_texture_new");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT);
RNA_def_function_ui_description(func, "Add a UV map layer to Mesh");
RNA_def_string(func, "name", "UVMap", 0, "", "UV map name");
parm = RNA_def_pointer(func, "layer", "MeshTexturePolyLayer", "", "The newly created layer");
RNA_def_property_flag(parm, PROP_RNAPTR);
RNA_def_function_return(func, parm);
-#if 0
func = RNA_def_function(srna, "remove", "rna_Mesh_uv_texture_layers_remove");
RNA_def_function_ui_description(func, "Remove a vertex color layer");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "layer", "Layer", "", "The layer to remove");
- RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
-#endif
+ parm = RNA_def_pointer(func, "layer", "MeshTexturePolyLayer", "", "The layer to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "MeshTexturePolyLayer");
RNA_def_property_pointer_funcs(prop, "rna_Mesh_uv_texture_active_get",
"rna_Mesh_uv_texture_active_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
RNA_def_property_ui_text(prop, "Active UV Map", "Active UV Map");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
@@ -2879,11 +2923,6 @@ static void rna_def_mesh(BlenderRNA *brna)
"Display selected edges using highlights in the 3D view and UV editor");
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
- prop = RNA_def_property(srna, "show_all_edges", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_ALLEDGES);
- RNA_def_property_ui_text(prop, "All Edges", "Display all edges for wireframe in all view modes in the 3D view");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
-
prop = RNA_def_property(srna, "show_faces", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWFACES);
RNA_def_property_ui_text(prop, "Draw Faces", "Display all faces as shades in the 3D view and UV editor");
@@ -2919,6 +2958,16 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Draw Sharp", "Display sharp edges, used with the EdgeSplit modifier");
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
+ prop = RNA_def_property(srna, "show_freestyle_edge_marks", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAW_FREESTYLE_EDGE);
+ RNA_def_property_ui_text(prop, "Draw Freestyle Edge Marks", "Display Freestyle edge marks, used with the Freestyle renderer");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
+
+ prop = RNA_def_property(srna, "show_freestyle_face_marks", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAW_FREESTYLE_FACE);
+ RNA_def_property_ui_text(prop, "Draw Freestyle Face Marks", "Display Freestyle face marks, used with the Freestyle renderer");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
+
prop = RNA_def_property(srna, "show_extra_edge_length", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWEXTRA_EDGELEN);
RNA_def_property_ui_text(prop, "Edge Length",
@@ -2928,7 +2977,7 @@ static void rna_def_mesh(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_extra_face_angle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWEXTRA_FACEANG);
RNA_def_property_ui_text(prop, "Face Angles",
- "Display the angles in the selected edges in degrees, "
+ "Display the angles in the selected edges, "
"using global values when set in the transform panel");
RNA_def_property_update(prop, 0, "rna_Mesh_update_draw");
@@ -2966,17 +3015,33 @@ static void rna_def_mesh(BlenderRNA *brna)
"(for when both sides of mesh have matching, unique topology)");
prop = RNA_def_property(srna, "use_paint_mask", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "editflag", ME_EDIT_PAINT_MASK);
+ RNA_def_property_boolean_sdna(prop, NULL, "editflag", ME_EDIT_PAINT_FACE_SEL);
RNA_def_property_ui_text(prop, "Paint Mask", "Face selection masking for painting");
RNA_def_property_ui_icon(prop, ICON_FACESEL_HLT, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_Mesh_update_facemask");
prop = RNA_def_property(srna, "use_paint_mask_vertex", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "editflag", ME_EDIT_VERT_SEL);
+ RNA_def_property_boolean_sdna(prop, NULL, "editflag", ME_EDIT_PAINT_VERT_SEL);
RNA_def_property_ui_text(prop, "Vertex Selection", "Vertex selection masking for painting (weight paint only)");
RNA_def_property_ui_icon(prop, ICON_VERTEXSEL, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_Mesh_update_vertmask");
+
+
+ /* customdata flags */
+ prop = RNA_def_property(srna, "use_customdata_vertex_bevel", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "cd_flag", ME_CDFLAG_VERT_BWEIGHT);
+ RNA_def_property_ui_text(prop, "Store Vertex Bevel Weight", "");
+
+ prop = RNA_def_property(srna, "use_customdata_edge_bevel", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "cd_flag", ME_CDFLAG_EDGE_BWEIGHT);
+ RNA_def_property_ui_text(prop, "Store Edge Bevel Weight", "");
+
+ prop = RNA_def_property(srna, "use_customdata_edge_crease", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "cd_flag", ME_CDFLAG_EDGE_CREASE);
+ RNA_def_property_ui_text(prop, "Store Edge Crease", "");
+
+
/* readonly editmesh info - use for extrude menu */
prop = RNA_def_property(srna, "total_vert_sel", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_funcs(prop, "rna_Mesh_tot_vert_get", NULL, NULL);
diff --git a/source/blender/makesrna/intern/rna_mesh_utils.h b/source/blender/makesrna/intern/rna_mesh_utils.h
index cfb9f7e8f3d..581c06c2c4e 100644
--- a/source/blender/makesrna/intern/rna_mesh_utils.h
+++ b/source/blender/makesrna/intern/rna_mesh_utils.h
@@ -110,7 +110,7 @@
CustomData *ldata = rna_mesh_ldata_helper(me); \
CustomData_set_layer_##active_type(ldata, CD_MLOOPUV, a); \
} \
- mesh_update_customdata_pointers(me, TRUE); \
+ BKE_mesh_update_customdata_pointers(me, true); \
return; \
} \
} \
@@ -139,7 +139,7 @@
CustomData *ldata = rna_mesh_ldata_helper(me); \
CustomData_set_layer_##active_type(ldata, CD_MLOOPUV, value); \
} \
- mesh_update_customdata_pointers(me, TRUE); \
+ BKE_mesh_update_customdata_pointers(me, true); \
} \
}
diff --git a/source/blender/makesrna/intern/rna_meta.c b/source/blender/makesrna/intern/rna_meta.c
index 08eefc082bf..f38151fd721 100644
--- a/source/blender/makesrna/intern/rna_meta.c
+++ b/source/blender/makesrna/intern/rna_meta.c
@@ -24,18 +24,19 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+
+#include "BLI_utildefines.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "rna_internal.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meta_types.h"
-
#ifdef RNA_RUNTIME
#include "BLI_math.h"
@@ -351,6 +352,8 @@ static void rna_def_metaball(BlenderRNA *brna)
/* anim */
rna_def_animdata_common(srna);
+
+ RNA_api_meta(srna);
}
void RNA_def_meta(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_meta_api.c b/source/blender/makesrna/intern/rna_meta_api.c
new file mode 100644
index 00000000000..500e202b16f
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_meta_api.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.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/makesrna/intern/rna_meta_api.c
+ * \ingroup RNA
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "RNA_define.h"
+
+#include "BLO_sys_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "ED_mball.h"
+
+#include "rna_internal.h" /* own include */
+
+#ifdef RNA_RUNTIME
+/* none */
+#else
+
+void RNA_api_meta(StructRNA *srna)
+{
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ func = RNA_def_function(srna, "transform", "ED_mball_transform");
+ RNA_def_function_ui_description(func, "Transform meta elements by a matrix");
+ parm = RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+}
+
+#endif
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index a2b0945fb46..185968ded79 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -29,11 +29,6 @@
#include <limits.h>
#include <stdlib.h>
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
-#include "rna_internal.h"
-
#include "DNA_armature_types.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
@@ -53,12 +48,19 @@
#include "BKE_multires.h"
#include "BKE_smoke.h" /* For smokeModifier_free & smokeModifier_createType */
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
#include "WM_api.h"
#include "WM_types.h"
EnumPropertyItem modifier_type_items[] = {
{0, "", 0, N_("Modify"), ""},
+ {eModifierType_MeshCache, "MESH_CACHE", ICON_MOD_MESHDEFORM, "Mesh Cache", ""},
{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", ""},
{eModifierType_WeightVGMix, "VERTEX_WEIGHT_MIX", ICON_MOD_VERTEX_WEIGHT, "Vertex Weight Mix", ""},
{eModifierType_WeightVGProximity, "VERTEX_WEIGHT_PROXIMITY", ICON_MOD_VERTEX_WEIGHT,
@@ -129,7 +131,7 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
{
ModifierData *md = (ModifierData *)ptr->data;
- switch (md->type) {
+ switch ((ModifierType)md->type) {
case eModifierType_Subsurf:
return &RNA_SubsurfModifier;
case eModifierType_Lattice:
@@ -216,9 +218,18 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
return &RNA_LaplacianSmoothModifier;
case eModifierType_Triangulate:
return &RNA_TriangulateModifier;
- default:
+ case eModifierType_UVWarp:
+ return &RNA_UVWarpModifier;
+ case eModifierType_MeshCache:
+ return &RNA_MeshCacheModifier;
+ /* Default */
+ case eModifierType_None:
+ case eModifierType_ShapeKey:
+ case NUM_MODIFIER_TYPES:
return &RNA_Modifier;
}
+
+ return &RNA_Modifier;
}
static void rna_Modifier_name_set(PointerRNA *ptr, const char *value)
@@ -256,7 +267,7 @@ static void rna_Modifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Point
static void rna_Modifier_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
rna_Modifier_update(bmain, scene, ptr);
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
}
static void rna_Smoke_set_type(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -659,15 +670,6 @@ static void rna_UVProjectModifier_num_projectors_set(PointerRNA *ptr, int value)
md->projectors[a] = NULL;
}
-static int rna_OceanModifier_is_build_enabled_get(PointerRNA *UNUSED(ptr))
-{
-#ifdef WITH_OCEANSIM
- return 1;
-#else /* WITH_OCEANSIM */
- return 0;
-#endif /* WITH_OCEANSIM */
-}
-
static void rna_OceanModifier_init_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
OceanModifierData *omd = (OceanModifierData *)ptr->data;
@@ -738,6 +740,24 @@ static void rna_BevelModifier_angle_limit_set(PointerRNA *ptr, float value)
md->bevel_angle = (int)value;
}
+static void rna_BevelModifier_defgrp_name_set(PointerRNA *ptr, const char *value)
+{
+ BevelModifierData *md = (BevelModifierData *)ptr->data;
+ rna_object_vgroup_name_set(ptr, value, md->defgrp_name, sizeof(md->defgrp_name));
+}
+
+static void rna_UVWarpModifier_vgroup_set(PointerRNA *ptr, const char *value)
+{
+ UVWarpModifierData *umd = (UVWarpModifierData *)ptr->data;
+ rna_object_vgroup_name_set(ptr, value, umd->vgroup_name, sizeof(umd->vgroup_name));
+}
+
+static void rna_UVWarpModifier_uvlayer_set(PointerRNA *ptr, const char *value)
+{
+ UVWarpModifierData *umd = (UVWarpModifierData *)ptr->data;
+ rna_object_uvlayer_name_set(ptr, value, umd->uvlayer_name, sizeof(umd->uvlayer_name));
+}
+
#else
static PropertyRNA *rna_def_property_subdivision_common(StructRNA *srna, const char type[])
@@ -1646,7 +1666,7 @@ static void rna_def_modifier_displace(BlenderRNA *brna)
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_DisplaceModifier_vgroup_set");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
- prop = RNA_def_property(srna, "mid_level", PROP_FLOAT, PROP_DISTANCE);
+ prop = RNA_def_property(srna, "mid_level", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "midlevel");
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
RNA_def_property_ui_range(prop, 0, 1, 10, 3);
@@ -1820,18 +1840,23 @@ static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME);
RNA_def_property_ui_text(prop, "Preserve Volume", "Apply volume preservation after smooth");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "use_normalized", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_NORMALIZED);
+ RNA_def_property_ui_text(prop, "Normalized", "Improve and stabilize the enhanced shape");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "lambda_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.0000001, 1000.0, 0.0000001, 8);
+ RNA_def_property_ui_range(prop, -1000.0, 1000.0, 5, 3);
RNA_def_property_ui_text(prop, "Lambda Factor", "Smooth factor effect");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "lambda_border", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "lambda_border");
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
- RNA_def_property_ui_range(prop, 0.0000001, 1000.0, 0.0000001, 8);
+ RNA_def_property_ui_range(prop, -1000.0, 1000.0, 5, 3);
RNA_def_property_ui_text(prop, "Lambda Border", "Lambda factor in border");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
@@ -2263,11 +2288,13 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
{0, "NONE", 0, "None", "Bevel the entire mesh by a constant amount"},
{BME_BEVEL_ANGLE, "ANGLE", 0, "Angle", "Only bevel edges with sharp enough angles between faces"},
{BME_BEVEL_WEIGHT, "WEIGHT", 0, "Weight",
- "Use bevel weights to determine how much bevel is applied; "
- "apply them separately in vert/edge select mode"},
+ "Use bevel weights to determine how much bevel is applied in edge mode"},
+ {BME_BEVEL_VGROUP, "VGROUP", 0, "Vertex Group",
+ "Use vertex group weights to determine how much bevel is applied in vertex mode"},
{0, NULL, 0, NULL, NULL}
};
+ /* TO BE DEPRECATED */
static EnumPropertyItem prop_edge_weight_method_items[] = {
{0, "AVERAGE", 0, "Average", ""},
{BME_BEVEL_EMIN, "SHARPEST", 0, "Sharpest", ""},
@@ -2287,6 +2314,12 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Width", "Bevel value/amount");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "segments", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "res");
+ RNA_def_property_range(prop, 1, 100);
+ RNA_def_property_ui_text(prop, "Segments", "Number of segments for round edges/verts");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
prop = RNA_def_property(srna, "use_only_vertices", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", BME_BEVEL_VERT);
RNA_def_property_ui_text(prop, "Only Vertices", "Bevel verts/corners, not edges");
@@ -2298,6 +2331,7 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Limit Method", "");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ /* TO BE DEPRECATED */
prop = RNA_def_property(srna, "edge_weight_method", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "e_flags");
RNA_def_property_enum_items(prop, prop_edge_weight_method_items);
@@ -2320,15 +2354,10 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Modifier_update");
#ifdef USE_BM_BEVEL_OP_AS_MOD
- prop = RNA_def_property(srna, "use_even_offset", PROP_BOOLEAN, PROP_NONE); /* name matches solidify */
- RNA_def_property_boolean_sdna(prop, NULL, "flags", BME_BEVEL_EVEN);
- RNA_def_property_ui_text(prop, "Even", "Use even bevel distance correction");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
- prop = RNA_def_property(srna, "use_distance_offset", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flags", BME_BEVEL_DIST);
- RNA_def_property_ui_text(prop, "Distance",
- "Use the width as a distance in rather then a factor of the face size");
+ 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");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_BevelModifier_defgrp_name_set");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
#endif
@@ -2555,6 +2584,13 @@ static void rna_def_modifier_simpledeform(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Factor", "Amount to deform object");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "factor");
+ RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+ RNA_def_property_ui_range(prop, -10, 10, 1, 3);
+ RNA_def_property_ui_text(prop, "Angle", "Angle of deformation");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
prop = RNA_def_property(srna, "limits", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "limit");
RNA_def_property_array(prop, 2);
@@ -2603,6 +2639,13 @@ static void rna_def_modifier_solidify(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Thickness", "Thickness of the shell");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "thickness_clamp", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "offset_clamp");
+ RNA_def_property_range(prop, 0, 100.0);
+ RNA_def_property_ui_range(prop, 0, 2.0, 0.1, 4);
+ RNA_def_property_ui_text(prop, "Clamp", "Offset clamp based on geometry scale");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
prop = RNA_def_property(srna, "thickness_vertex_group", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "offset_fac_vg");
RNA_def_property_range(prop, 0.0, 1.0);
@@ -2773,6 +2816,75 @@ static void rna_def_modifier_screw(BlenderRNA *brna)
#endif
}
+static void rna_def_modifier_uvwarp(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem uvwarp_axis[] = {
+ {0, "X", 0, "X", ""},
+ {1, "Y", 0, "Y", ""},
+ {2, "Z", 0, "Z", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ srna = RNA_def_struct(brna, "UVWarpModifier", "Modifier");
+ RNA_def_struct_ui_text(srna, "UVWarp Modifier", "Add target position to uv coordinates");
+ RNA_def_struct_sdna(srna, "UVWarpModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_UVPROJECT);
+
+ prop = RNA_def_property(srna, "axis_u", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "axis_u");
+ RNA_def_property_enum_items(prop, uvwarp_axis);
+ RNA_def_property_ui_text(prop, "U-Axis", "Pole axis for rotation");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "axis_v", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "axis_v");
+ RNA_def_property_enum_items(prop, uvwarp_axis);
+ RNA_def_property_ui_text(prop, "V-Axis", "Pole axis for rotation");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "center", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "center");
+ RNA_def_property_ui_text(prop, "UV Center", "Center point for rotate/scale");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ 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_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_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_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_update(prop, 0, "rna_Modifier_dependency_update");
+
+ prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "vgroup_name");
+ RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_UVWarpModifier_vgroup_set");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "uvlayer_name");
+ RNA_def_property_ui_text(prop, "UV Layer", "UV Layer name");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_UVWarpModifier_uvlayer_set");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+}
+
static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna), StructRNA *srna)
{
static EnumPropertyItem weightvg_mask_tex_map_items[] = {
@@ -3166,12 +3278,6 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "OceanModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_OCEAN);
- /* General check if blender was built with OceanSim modifier support */
- prop = RNA_def_property(srna, "is_build_enabled", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_OceanModifier_is_build_enabled_get", NULL);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Build Enabled", "True if the OceanSim modifier is enabled in this build");
-
prop = RNA_def_property(srna, "geometry_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "geometry_mode");
RNA_def_property_enum_items(prop, geometry_items);
@@ -3180,7 +3286,7 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "size");
- RNA_def_property_ui_text(prop, "Size", "");
+ RNA_def_property_ui_text(prop, "Size", "Surface scale factor (does not affect the height of the waves)");
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, 0);
RNA_def_property_update(prop, 0, "rna_OceanModifier_topology_update");
@@ -3221,16 +3327,17 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Resolution", "Resolution of the generated surface");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
- prop = RNA_def_property(srna, "spatial_size", PROP_INT, PROP_DISTANCE);
+ prop = RNA_def_property(srna, "spatial_size", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "spatial_size");
RNA_def_property_ui_range(prop, 1, 512, 2, 0);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Spatial Size", "Physical size of the simulation domain (m)");
+ RNA_def_property_ui_text(prop, "Spatial Size",
+ "Size of the simulation domain (in meters), and of the generated geometry (in BU)");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
prop = RNA_def_property(srna, "wind_velocity", PROP_FLOAT, PROP_VELOCITY);
RNA_def_property_float_sdna(prop, NULL, "wind_velocity");
- RNA_def_property_ui_text(prop, "Wind Velocity", "Wind speed (m/s)");
+ RNA_def_property_ui_text(prop, "Wind Velocity", "Wind speed");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
prop = RNA_def_property(srna, "damping", PROP_FLOAT, PROP_FACTOR);
@@ -3243,42 +3350,43 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "smallest_wave");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 0.0, FLT_MAX);
- RNA_def_property_ui_text(prop, "Smallest Wave", "Shortest allowed wavelength (m)");
+ RNA_def_property_ui_text(prop, "Smallest Wave", "Shortest allowed wavelength");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
prop = RNA_def_property(srna, "wave_alignment", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "wave_alignment");
RNA_def_property_range(prop, 0.0, 10.0);
- RNA_def_property_ui_text(prop, "Wave Alignment", "");
+ RNA_def_property_ui_text(prop, "Wave Alignment", "How much the waves are aligned to each other");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
prop = RNA_def_property(srna, "wave_direction", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "wave_direction");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Wave Direction", "");
+ RNA_def_property_ui_text(prop, "Wave Direction", "Main direction of the waves when they are (partially) aligned");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
prop = RNA_def_property(srna, "wave_scale", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "wave_scale");
- RNA_def_property_ui_text(prop, "Wave Scale", "");
+ RNA_def_property_ui_text(prop, "Wave Scale", "Scale of the displacement effect");
RNA_def_property_update(prop, 0, "rna_OceanModifier_sim_update");
- prop = RNA_def_property(srna, "depth", PROP_FLOAT, PROP_UNSIGNED);
+ prop = RNA_def_property(srna, "depth", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "depth");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Depth", "");
+ RNA_def_property_ui_text(prop, "Depth", "Depth of the solid ground below the water surface");
RNA_def_property_ui_range(prop, 0, 250, 1, 0);
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
prop = RNA_def_property(srna, "foam_coverage", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "foam_coverage");
- RNA_def_property_ui_text(prop, "Foam Coverage", "");
+ RNA_def_property_ui_text(prop, "Foam Coverage", "Amount of generated foam");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "bake_foam_fade", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "foam_fade");
- RNA_def_property_ui_text(prop, "Foam Fade", "");
- RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, 0);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_ui_text(prop, "Foam Fade", "How much foam accumulates over time (baked ocean only)");
+ RNA_def_property_ui_range(prop, 0.0, 10.0, 1, 0);
RNA_def_property_update(prop, 0, NULL);
prop = RNA_def_property(srna, "foam_layer_name", PROP_STRING, PROP_NONE);
@@ -3288,33 +3396,34 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
prop = RNA_def_property(srna, "choppiness", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "chop_amount");
- RNA_def_property_ui_text(prop, "Choppiness", "");
+ RNA_def_property_ui_text(prop, "Choppiness",
+ "Choppiness of the wave's crest (adds some horizontal component to the displacement)");
RNA_def_property_ui_range(prop, 0.0, 4.0, 3, 0);
RNA_def_property_float_funcs(prop, NULL, "rna_OceanModifier_ocean_chop_set", NULL);
RNA_def_property_update(prop, 0, "rna_OceanModifier_sim_update");
prop = RNA_def_property(srna, "time", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "time");
- RNA_def_property_ui_text(prop, "Time", "");
+ RNA_def_property_ui_text(prop, "Time", "Current time of the simulation");
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, 0);
RNA_def_property_update(prop, 0, "rna_OceanModifier_sim_update");
prop = RNA_def_property(srna, "random_seed", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "seed");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Random Seed", "");
+ RNA_def_property_ui_text(prop, "Random Seed", "Seed of the random generator");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "bakestart");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Bake Start", "");
+ RNA_def_property_ui_text(prop, "Bake Start", "Start frame of the ocean baking");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "bakeend");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Bake End", "");
+ RNA_def_property_ui_text(prop, "Bake End", "End frame of the ocean baking");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
prop = RNA_def_property(srna, "is_cached", PROP_BOOLEAN, PROP_NONE);
@@ -3381,6 +3490,158 @@ static void rna_def_modifier_triangulate(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
+static void rna_def_modifier_meshcache(BlenderRNA *brna)
+{
+ static EnumPropertyItem prop_format_type_items[] = {
+ {MOD_MESHCACHE_TYPE_MDD, "MDD", 0, "MDD ", ""},
+ {MOD_MESHCACHE_TYPE_PC2, "PC2", 0, "PC2", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem prop_deform_mode_items[] = {
+ {MOD_MESHCACHE_DEFORM_OVERWRITE, "OVERWRITE", 0, "Overwrite",
+ "Replace vertex coords with cached values"},
+ {MOD_MESHCACHE_DEFORM_INTEGRATE, "INTEGRATE", 0, "Integrate",
+ "Integrate deformation from this modifiers input with the mesh-cache coords (useful for shape keys)"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem prop_interpolation_type_items[] = {
+ {MOD_MESHCACHE_INTERP_NONE, "NONE", 0, "None ", ""},
+ {MOD_MESHCACHE_INTERP_LINEAR, "LINEAR", 0, "Linear", ""},
+ /* for cardinal we'd need to read 4x cache's */
+ // {MOD_MESHCACHE_INTERP_CARDINAL, "CARDINAL", 0, "Cardinal", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem prop_time_type_items[] = {
+ /* use 'eval_frame' */
+ {MOD_MESHCACHE_TIME_FRAME, "FRAME", 0, "Frame", "Control playback using a frame-number "
+ "(ignoring time FPS and start frame from the file)"},
+ /* use 'eval_time' */
+ {MOD_MESHCACHE_TIME_SECONDS, "TIME", 0, "Time", "Control playback using time in seconds"},
+ /* use 'eval_factor' */
+ {MOD_MESHCACHE_TIME_FACTOR, "FACTOR", 0, "Factor", "Control playback using a value between [0, 1]"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem prop_time_play_items[] = {
+ {MOD_MESHCACHE_PLAY_CFEA, "SCENE", 0, "Scene", "Use the time from the scene"},
+ {MOD_MESHCACHE_PLAY_EVAL, "CUSTOM", 0, "Custom", "Use the modifier's own time evaluation"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem prop_flip_axis_flag_items[] = {
+ {(1 << 0), "X", 0, "X", ""},
+ {(1 << 1), "Y", 0, "Y", ""},
+ {(1 << 2), "Z", 0, "Z", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "MeshCacheModifier", "Modifier");
+ RNA_def_struct_ui_text(srna, "Cache Modifier", "Cache Mesh");
+ RNA_def_struct_sdna(srna, "MeshCacheModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM); /* XXX, needs own icon */
+
+ prop = RNA_def_property(srna, "cache_format", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, prop_format_type_items);
+ RNA_def_property_ui_text(prop, "Format", "");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "interpolation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "interp");
+ RNA_def_property_enum_items(prop, prop_interpolation_type_items);
+ RNA_def_property_ui_text(prop, "Interpolation", "");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "time_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "time_mode");
+ RNA_def_property_enum_items(prop, prop_time_type_items);
+ RNA_def_property_ui_text(prop, "Time Mode", "Method to control playback time");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "play_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "play_mode");
+ RNA_def_property_enum_items(prop, prop_time_play_items);
+ RNA_def_property_ui_text(prop, "Time Mode", "");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "deform_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "deform_mode");
+ RNA_def_property_enum_items(prop, prop_deform_mode_items);
+ RNA_def_property_ui_text(prop, "Deform Mode", "");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
+ RNA_def_property_ui_text(prop, "File Path", "Path to external displacements file");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "factor");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Influence", "Influence of the deformation");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ /* -------------------------------------------------------------------- */
+ /* Axis Conversion */
+ prop = RNA_def_property(srna, "forward_axis", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "forward_axis");
+ RNA_def_property_enum_items(prop, object_axis_items);
+ RNA_def_property_ui_text(prop, "Forward", "");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "up_axis", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "up_axis");
+ RNA_def_property_enum_items(prop, object_axis_items);
+ RNA_def_property_ui_text(prop, "Up", "");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "flip_axis", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "flip_axis");
+ RNA_def_property_enum_items(prop, prop_flip_axis_flag_items);
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_property_ui_text(prop, "Flip Axis", "");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ /* -------------------------------------------------------------------- */
+ /* For Scene time */
+ prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "frame_start");
+ RNA_def_property_range(prop, -MAXFRAME, MAXFRAME);
+ RNA_def_property_ui_text(prop, "Frame Start", "Add this to the start frame");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "frame_scale", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "frame_scale");
+ RNA_def_property_range(prop, 0.0f, 100.0f);
+ RNA_def_property_ui_text(prop, "Frame Scale", "Evaluation time in seconds");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ /* -------------------------------------------------------------------- */
+ /* eval values depend on 'time_mode' */
+ prop = RNA_def_property(srna, "eval_frame", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "eval_frame");
+ RNA_def_property_range(prop, MINFRAME, MAXFRAME);
+ RNA_def_property_ui_text(prop, "Evaluation Frame", "The frame to evaluate (starting at 0)");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "eval_time", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "eval_time");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_text(prop, "Evaluation Time", "Evaluation time in seconds");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "eval_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "eval_factor");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Evaluation Factor", "Evaluation time in seconds");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+}
+
void RNA_def_modifier(BlenderRNA *brna)
{
StructRNA *srna;
@@ -3480,6 +3741,7 @@ void RNA_def_modifier(BlenderRNA *brna)
rna_def_modifier_smoke(brna);
rna_def_modifier_solidify(brna);
rna_def_modifier_screw(brna);
+ rna_def_modifier_uvwarp(brna);
rna_def_modifier_weightvgedit(brna);
rna_def_modifier_weightvgmix(brna);
rna_def_modifier_weightvgproximity(brna);
@@ -3489,6 +3751,7 @@ void RNA_def_modifier(BlenderRNA *brna)
rna_def_modifier_skin(brna);
rna_def_modifier_laplaciansmooth(brna);
rna_def_modifier_triangulate(brna);
+ rna_def_modifier_meshcache(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c
index 99effc990a8..cc3d5e5ca5e 100644
--- a/source/blender/makesrna/intern/rna_movieclip.c
+++ b/source/blender/makesrna/intern/rna_movieclip.c
@@ -25,7 +25,6 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
#include <limits.h>
@@ -34,13 +33,13 @@
#include "BKE_movieclip.h"
#include "BKE_tracking.h"
+#include "DNA_movieclip_types.h"
+#include "DNA_scene_types.h"
+
#include "RNA_define.h"
#include "rna_internal.h"
-#include "DNA_movieclip_types.h"
-#include "DNA_scene_types.h"
-
#include "WM_types.h"
#include "IMB_imbuf_types.h"
@@ -308,7 +307,7 @@ static void rna_def_movieclip(BlenderRNA *brna)
/* color management */
prop = RNA_def_property(srna, "colorspace_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "colorspace_settings");
- RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings");
+ RNA_def_property_struct_type(prop, "ColorManagedInputColorspaceSettings");
RNA_def_property_ui_text(prop, "Color Space Settings", "Input color space settings");
}
diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c
index 574f06e9107..9afaad96019 100644
--- a/source/blender/makesrna/intern/rna_nla.c
+++ b/source/blender/makesrna/intern/rna_nla.c
@@ -24,20 +24,21 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "rna_internal.h"
-
#include "DNA_anim_types.h"
#include "DNA_action_types.h"
#include "DNA_scene_types.h"
+#include "BLI_utildefines.h"
+
#include "MEM_guardedalloc.h"
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "rna_internal.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -115,7 +116,7 @@ static void rna_NlaStrip_start_frame_set(PointerRNA *ptr, float value)
if (data->prev->type == NLASTRIP_TYPE_TRANSITION) {
CLAMP(value, data->prev->start + NLASTRIP_MIN_LEN_THRESH, data->end - NLASTRIP_MIN_LEN_THRESH);
- /* readjust the transition to stick to the endpoints of the action-clips */
+ /* re-adjust the transition to stick to the endpoints of the action-clips */
data->prev->end = value;
}
else {
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 1da9a450c2c..d8dd9ff3c33 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -26,13 +26,7 @@
#include <stdlib.h>
#include <string.h>
-
-#include "RNA_access.h"
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
-#include "rna_internal.h"
-#include "rna_internal_types.h"
+#include <limits.h>
#include "BLI_listbase.h"
#include "BLI_math.h"
@@ -54,16 +48,35 @@
#include "BKE_texture.h"
#include "BKE_idprop.h"
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+#include "rna_internal_types.h"
+
#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
#include "WM_types.h"
#include "MEM_guardedalloc.h"
-EnumPropertyItem nodetree_type_items[] = {
- {NTREE_SHADER, "SHADER", ICON_MATERIAL, "Shader", "Shader nodes"},
- {NTREE_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture nodes"},
- {NTREE_COMPOSIT, "COMPOSITING", ICON_RENDERLAYERS, "Compositing", "Compositing nodes"},
+EnumPropertyItem node_socket_in_out_items[] = {
+ { SOCK_IN, "IN", 0, "Input", "" },
+ { SOCK_OUT, "OUT", 0, "Output", "" },
+ { 0, NULL, 0, NULL, NULL }
+};
+
+EnumPropertyItem node_socket_type_items[] = {
+ {SOCK_CUSTOM, "CUSTOM", 0, "Custom", ""},
+ {SOCK_FLOAT, "VALUE", 0, "Value", ""},
+ {SOCK_INT, "INT", 0, "Int", ""},
+ {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""},
+ {SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
+ {SOCK_STRING, "STRING", 0, "String", ""},
+ {SOCK_RGBA, "RGBA", 0, "RGBA", ""},
+ {SOCK_SHADER, "SHADER", 0, "Shader", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -84,17 +97,15 @@ EnumPropertyItem node_chunksize_items[] = {
{0, NULL, 0, NULL, NULL}
};
-EnumPropertyItem node_socket_type_items[] = {
- {SOCK_FLOAT, "VALUE", 0, "Value", ""},
- {SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
- {SOCK_RGBA, "RGBA", 0, "RGBA", ""},
- {SOCK_SHADER, "SHADER", 0, "Shader", ""},
- {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""},
- {SOCK_MESH, "MESH", 0, "Mesh", ""},
- {SOCK_INT, "INT", 0, "Int", ""},
- {SOCK_STRING, "STRING", 0, "String", ""},
- {0, NULL, 0, NULL, NULL}
-};
+#define DEF_ICON_BLANK_SKIP
+#define DEF_ICON(name) {ICON_##name, (#name), 0, (#name), ""},
+#define DEF_VICO(name)
+EnumPropertyItem node_icon_items[] = {
+#include "UI_icons.h"
+ {0, NULL, 0, NULL, NULL}};
+#undef DEF_ICON_BLANK_SKIP
+#undef DEF_ICON
+#undef DEF_VICO
EnumPropertyItem node_math_items[] = {
{ 0, "ADD", 0, "Add", ""},
@@ -173,52 +184,20 @@ EnumPropertyItem prop_wave_items[] = {
};
#endif
-/* Add any new socket value subtype here.
- * When adding a new subtype here, make sure you also add it
- * to the subtype definitions in DNA_node_types.h.
- * This macro is used by the RNA and the internal converter functions
- * to define all socket subtypes. The SUBTYPE macro must be defined
- * before using this macro, and undefined afterwards.
- */
-#define NODE_DEFINE_SUBTYPES_INT \
- SUBTYPE(INT, Int, NONE, None) \
- SUBTYPE(INT, Int, UNSIGNED, Unsigned)
-
-#define NODE_DEFINE_SUBTYPES_FLOAT \
- SUBTYPE(FLOAT, Float, NONE, None) \
- SUBTYPE(FLOAT, Float, UNSIGNED, Unsigned) \
- SUBTYPE(FLOAT, Float, PERCENTAGE, Percentage) \
- SUBTYPE(FLOAT, Float, FACTOR, Factor) \
- SUBTYPE(FLOAT, Float, ANGLE, Angle) \
- SUBTYPE(FLOAT, Float, TIME, Time) \
- SUBTYPE(FLOAT, Float, DISTANCE, Distance)
-
-#define NODE_DEFINE_SUBTYPES_STRING \
- SUBTYPE(STRING, String, NONE, None) \
- SUBTYPE(STRING, String, FILEPATH, Filepath)
-
-#define NODE_DEFINE_SUBTYPES_VECTOR \
- SUBTYPE(VECTOR, Vector, NONE, None) \
- SUBTYPE(VECTOR, Vector, TRANSLATION, Translation) \
- SUBTYPE(VECTOR, Vector, DIRECTION, Direction) \
- SUBTYPE(VECTOR, Vector, VELOCITY, Velocity) \
- SUBTYPE(VECTOR, Vector, ACCELERATION, Acceleration) \
- SUBTYPE(VECTOR, Vector, EULER, Euler) \
- SUBTYPE(VECTOR, Vector, XYZ, XYZ)
-
-#define NODE_DEFINE_SUBTYPES \
- NODE_DEFINE_SUBTYPES_INT \
- NODE_DEFINE_SUBTYPES_FLOAT \
- NODE_DEFINE_SUBTYPES_STRING \
- NODE_DEFINE_SUBTYPES_VECTOR \
-
#ifdef RNA_RUNTIME
#include "BLI_linklist.h"
+#include "BLI_string.h"
+
+#include "BKE_context.h"
+#include "BKE_idprop.h"
#include "BKE_global.h"
#include "ED_node.h"
+#include "ED_render.h"
+
+#include "NOD_socket.h"
#include "RE_engine.h"
#include "RE_pipeline.h"
@@ -226,260 +205,1372 @@ EnumPropertyItem prop_wave_items[] = {
#include "DNA_scene_types.h"
#include "WM_api.h"
-static StructRNA *rna_Node_refine(struct PointerRNA *ptr)
+
+int rna_node_tree_type_to_enum(bNodeTreeType *typeinfo)
{
- bNode *node = (bNode *)ptr->data;
+ int i = 0, result = -1;
+ NODE_TREE_TYPES_BEGIN(nt)
+ if (nt == typeinfo) {
+ result = i;
+ break;
+ }
+ ++i;
+ NODE_TREE_TYPES_END
+ return result;
+}
+
+int rna_node_tree_idname_to_enum(const char *idname)
+{
+ int i = 0, result = -1;
+ NODE_TREE_TYPES_BEGIN(nt)
+ if (STREQ(nt->idname, idname)) {
+ result = i;
+ break;
+ }
+ ++i;
+ NODE_TREE_TYPES_END
+ return result;
+}
+
+bNodeTreeType *rna_node_tree_type_from_enum(int value)
+{
+ int i = 0;
+ bNodeTreeType *result = NULL;
+ NODE_TREE_TYPES_BEGIN(nt)
+ if (i == value) {
+ result = nt;
+ break;
+ }
+ ++i;
+ NODE_TREE_TYPES_END
+ return result;
+}
- switch (node->type) {
+EnumPropertyItem *rna_node_tree_type_itemf(void *data, int (*poll)(void *data, bNodeTreeType *), int *free)
+{
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ EnumPropertyItem *item = NULL;
+ int totitem = 0, i = 0;
+
+ NODE_TREE_TYPES_BEGIN(nt)
+ if (poll && !poll(data, nt)) {
+ ++i;
+ continue;
+ }
- #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
- case ID: return &RNA_##Category##StructName;
-
- #include "rna_nodetree_types.h"
+ tmp.value = i;
+ tmp.identifier = nt->idname;
+ tmp.icon = nt->ui_icon;
+ tmp.name = nt->ui_name;
+ tmp.description = nt->ui_description;
- case NODE_GROUP:
- return &RNA_NodeGroup;
- case NODE_FRAME:
- return &RNA_NodeFrame;
- case NODE_REROUTE:
- return &RNA_NodeReroute;
- default:
- return &RNA_Node;
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ ++i;
+ NODE_TREE_TYPES_END
+
+ RNA_enum_item_end(&item, &totitem);
+ *free = 1;
+
+ return item;
+}
+
+int rna_node_type_to_enum(bNodeType *typeinfo)
+{
+ int i = 0, result = -1;
+ NODE_TYPES_BEGIN(ntype)
+ if (ntype == typeinfo) {
+ result = i;
+ break;
+ }
+ ++i;
+ NODE_TYPES_END
+ return result;
+}
+
+int rna_node_idname_to_enum(const char *idname)
+{
+ int i = 0, result = -1;
+ NODE_TYPES_BEGIN(ntype)
+ if (STREQ(ntype->idname, idname)) {
+ result = i;
+ break;
+ }
+ ++i;
+ NODE_TYPES_END
+ return result;
+}
+
+bNodeType *rna_node_type_from_enum(int value)
+{
+ int i = 0;
+ bNodeType *result = NULL;
+ NODE_TYPES_BEGIN(ntype)
+ if (i == value) {
+ result = ntype;
+ break;
+ }
+ ++i;
+ NODE_TYPES_END
+ return result;
+}
+
+EnumPropertyItem *rna_node_type_itemf(void *data, int (*poll)(void *data, bNodeType *), int *free)
+{
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ int totitem = 0, i = 0;
+
+ NODE_TYPES_BEGIN(ntype)
+ if (poll && !poll(data, ntype)) {
+ ++i;
+ continue;
+ }
+
+ tmp.value = i;
+ tmp.identifier = ntype->idname;
+ tmp.icon = ntype->ui_icon;
+ tmp.name = ntype->ui_name;
+ tmp.description = ntype->ui_description;
+
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ ++i;
+ NODE_TYPES_END
+ RNA_enum_item_end(&item, &totitem);
+ *free = 1;
+
+ return item;
+}
+
+int rna_node_socket_type_to_enum(bNodeSocketType *typeinfo)
+{
+ int i = 0, result = -1;
+ NODE_SOCKET_TYPES_BEGIN(stype)
+ if (stype == typeinfo) {
+ result = i;
+ break;
+ }
+ ++i;
+ NODE_SOCKET_TYPES_END
+ return result;
+}
+
+int rna_node_socket_idname_to_enum(const char *idname)
+{
+ int i = 0, result = -1;
+ NODE_SOCKET_TYPES_BEGIN(stype)
+ if (STREQ(stype->idname, idname)) {
+ result = i;
+ break;
+ }
+ ++i;
+ NODE_SOCKET_TYPES_END
+ return result;
+}
+
+bNodeSocketType *rna_node_socket_type_from_enum(int value)
+{
+ int i = 0;
+ bNodeSocketType *result = NULL;
+ NODE_SOCKET_TYPES_BEGIN(stype)
+ if (i == value) {
+ result = stype;
+ break;
+ }
+ ++i;
+ NODE_SOCKET_TYPES_END
+ return result;
+}
+
+EnumPropertyItem *rna_node_socket_type_itemf(void *data, int (*poll)(void *data, bNodeSocketType *), int *free)
+{
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ int totitem = 0, i = 0;
+ StructRNA *srna;
+
+ NODE_SOCKET_TYPES_BEGIN(stype)
+ if (poll && !poll(data, stype)) {
+ ++i;
+ continue;
+ }
+
+ srna = stype->ext_socket.srna;
+ tmp.value = i;
+ tmp.identifier = stype->idname;
+ tmp.icon = RNA_struct_ui_icon(srna);
+ tmp.name = RNA_struct_ui_name(srna);
+ tmp.description = RNA_struct_ui_description(srna);
+
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ ++i;
+ NODE_SOCKET_TYPES_END
+ RNA_enum_item_end(&item, &totitem);
+ *free = 1;
+
+ return item;
+}
+
+static EnumPropertyItem *rna_node_static_type_itemf(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free)
+{
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp;
+ int totitem = 0;
+
+ /* hack, don't want to add include path to RNA just for this, since in the future RNA types
+ * for nodes should be defined locally at runtime anyway ...
+ */
+
+ tmp.value = NODE_CUSTOM;
+ tmp.identifier = "CUSTOM";
+ tmp.name = "Custom";
+ tmp.description = "Custom Node";
+ tmp.icon = ICON_NONE;
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ tmp.value = NODE_UNDEFINED;
+ tmp.identifier = "UNDEFINED";
+ tmp.name = "UNDEFINED";
+ tmp.description = "";
+ tmp.icon = ICON_NONE;
+ RNA_enum_item_add(&item, &totitem, &tmp);
+
+ #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ if (STREQ(#Category, "Node")) { \
+ tmp.value = ID; \
+ tmp.identifier = EnumName; \
+ tmp.name = UIName; \
+ tmp.description = UIDesc; \
+ tmp.icon = ICON_NONE; \
+ RNA_enum_item_add(&item, &totitem, &tmp); \
+ }
+ #include "../../nodes/NOD_static_types.h"
+ #undef DefNode
+
+ if (RNA_struct_is_a(ptr->type, &RNA_ShaderNode)) {
+ #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ if (STREQ(#Category, "ShaderNode")) { \
+ tmp.value = ID; \
+ tmp.identifier = EnumName; \
+ tmp.name = UIName; \
+ tmp.description = UIDesc; \
+ tmp.icon = ICON_NONE; \
+ RNA_enum_item_add(&item, &totitem, &tmp); \
+ }
+ #include "../../nodes/NOD_static_types.h"
+ #undef DefNode
}
+
+ if (RNA_struct_is_a(ptr->type, &RNA_CompositorNode)) {
+ #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ if (STREQ(#Category, "CompositorNode")) { \
+ tmp.value = ID; \
+ tmp.identifier = EnumName; \
+ tmp.name = UIName; \
+ tmp.description = UIDesc; \
+ tmp.icon = ICON_NONE; \
+ RNA_enum_item_add(&item, &totitem, &tmp); \
+ }
+ #include "../../nodes/NOD_static_types.h"
+ #undef DefNode
+ }
+
+ if (RNA_struct_is_a(ptr->type, &RNA_TextureNode)) {
+ #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ if (STREQ(#Category, "TextureNode")) { \
+ tmp.value = ID; \
+ tmp.identifier = EnumName; \
+ tmp.name = UIName; \
+ tmp.description = UIDesc; \
+ tmp.icon = ICON_NONE; \
+ RNA_enum_item_add(&item, &totitem, &tmp); \
+ }
+ #include "../../nodes/NOD_static_types.h"
+ #undef DefNode
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *free = 1;
+
+ return item;
}
+/* ******** Node Tree ******** */
+
static StructRNA *rna_NodeTree_refine(struct PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->data;
+
+ if (ntree->typeinfo && ntree->typeinfo->ext.srna)
+ return ntree->typeinfo->ext.srna;
+ else
+ return &RNA_NodeTree;
+}
- switch (ntree->type) {
- case NTREE_SHADER:
- return &RNA_ShaderNodeTree;
- case NTREE_COMPOSIT:
- return &RNA_CompositorNodeTree;
- case NTREE_TEXTURE:
- return &RNA_TextureNodeTree;
- default:
- return &RNA_NodeTree;
- }
+static int rna_NodeTree_poll(const bContext *C, bNodeTreeType *ntreetype)
+{
+ extern FunctionRNA rna_NodeTree_poll_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret;
+ int visible;
+
+ RNA_pointer_create(NULL, ntreetype->ext.srna, NULL, &ptr); /* dummy */
+ func = &rna_NodeTree_poll_func; /* RNA_struct_find_function(&ptr, "poll"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ ntreetype->ext.call((bContext *)C, &ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "visible", &ret);
+ visible = *(int *)ret;
+
+ RNA_parameter_list_free(&list);
+
+ return visible;
}
-static char *rna_Node_path(PointerRNA *ptr)
+static void rna_NodeTree_draw_add_menu(const bContext *C, struct uiLayout *layout, bNodeTree *ntree)
{
- bNode *node = (bNode *)ptr->data;
+ extern FunctionRNA rna_NodeTree_draw_add_menu_func;
- return BLI_sprintfN("nodes[\"%s\"]", node->name);
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ RNA_id_pointer_create(&ntree->id, &ptr);
+ func = &rna_NodeTree_draw_add_menu_func; /* RNA_struct_find_function(&ptr, "draw_add_menu"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "layout", &layout);
+ ntree->typeinfo->ext.call((bContext *)C, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
}
-static StructRNA *rna_NodeSocket_refine(PointerRNA *ptr)
+static void rna_NodeTree_get_from_context(const bContext *C, bNodeTreeType *ntreetype,
+ bNodeTree **r_ntree, ID **r_id, ID **r_from)
{
- bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ extern FunctionRNA rna_NodeTree_get_from_context_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret1, *ret2, *ret3;
+
+ RNA_pointer_create(NULL, ntreetype->ext.srna, NULL, &ptr); /* dummy */
+ func = &rna_NodeTree_get_from_context_func; /* RNA_struct_find_function(&ptr, "get_from_context"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ ntreetype->ext.call((bContext *)C, &ptr, func, &list);
- if (sock->default_value) {
- /* This returns the refined socket type with the full definition
- * of the default input value with type and subtype.
- */
+ RNA_parameter_get_lookup(&list, "result_1", &ret1);
+ RNA_parameter_get_lookup(&list, "result_2", &ret2);
+ RNA_parameter_get_lookup(&list, "result_3", &ret3);
+ *r_ntree = *(bNodeTree **)ret1;
+ *r_id = *(ID **)ret2;
+ *r_from = *(ID **)ret3;
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_NodeTree_unregister(Main *UNUSED(bmain), StructRNA *type)
+{
+ bNodeTreeType *nt = RNA_struct_blender_type_get(type);
+
+ if (!nt)
+ return;
+
+ RNA_struct_free_extension(type, &nt->ext);
+
+ ntreeTypeFreeLink(nt);
+
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
+}
+
+static StructRNA *rna_NodeTree_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeTreeType *nt, dummynt;
+ bNodeTree dummyntree;
+ PointerRNA dummyptr;
+ int have_function[3];
+
+ /* setup dummy tree & tree type to store static properties in */
+ memset(&dummynt, 0, sizeof(bNodeTreeType));
+ memset(&dummyntree, 0, sizeof(bNodeTree));
+ dummyntree.typeinfo = &dummynt;
+ RNA_pointer_create(NULL, &RNA_NodeTree, &dummyntree, &dummyptr);
+
+ /* validate the python class */
+ if (validate(&dummyptr, data, have_function) != 0)
+ return NULL;
+
+ if (strlen(identifier) >= sizeof(dummynt.idname)) {
+ BKE_reportf(reports, RPT_ERROR, "Registering node tree class: '%s' is too long, maximum length is %d",
+ identifier, (int)sizeof(dummynt.idname));
+ return NULL;
+ }
+
+ /* check if we have registered this tree type before, and remove it */
+ nt = ntreeTypeFind(dummynt.idname);
+ if (nt)
+ rna_NodeTree_unregister(bmain, nt->ext.srna);
+
+ /* create a new node tree type */
+ nt = MEM_callocN(sizeof(bNodeTreeType), "node tree type");
+ memcpy(nt, &dummynt, sizeof(dummynt));
+
+ nt->type = NTREE_CUSTOM;
+
+ nt->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, nt->idname, &RNA_NodeTree);
+ nt->ext.data = data;
+ nt->ext.call = call;
+ nt->ext.free = free;
+ RNA_struct_blender_type_set(nt->ext.srna, nt);
+
+ RNA_def_struct_ui_text(nt->ext.srna, nt->ui_name, nt->ui_description);
+ RNA_def_struct_ui_icon(nt->ext.srna, nt->ui_icon);
+
+ nt->poll = (have_function[0]) ? rna_NodeTree_poll : NULL;
+ nt->draw_add_menu = (have_function[1]) ? rna_NodeTree_draw_add_menu : NULL;
+ nt->get_from_context = (have_function[2]) ? rna_NodeTree_get_from_context : NULL;
+
+ ntreeTypeAdd(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
+
+ return nt->ext.srna;
+}
+
+static bool rna_NodeTree_check(bNodeTree *ntree, ReportList *reports)
+{
+ if (!ntreeIsRegistered(ntree)) {
+ if (reports)
+ BKE_reportf(reports, RPT_ERROR, "Node tree '%s' has undefined type %s", ntree->id.name + 2, ntree->idname);
- #define SUBTYPE(socktype, stypename, id, idname) \
- { \
- bNodeSocketValue##stypename * value = (bNodeSocketValue##stypename *)sock->default_value; \
- if (value->subtype == PROP_##id) \
- return &RNA_NodeSocket##stypename##idname; \
+ return false;
+ }
+ else
+ return true;
+}
+
+static void rna_NodeTree_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+
+ /* when using border, make it so no old data from outside of
+ * border is hanging around
+ * ideally shouldn't be in RNA callback, but how to teach
+ * compo to only clear frame when border usage is actually
+ * toggling
+ */
+ if (ntree->flag & NTREE_VIEWER_BORDER) {
+ Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ void *lock;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
+
+ if (ibuf) {
+ if (ibuf->rect)
+ memset(ibuf->rect, 0, 4 * ibuf->x * ibuf->y);
+
+ if (ibuf->rect_float)
+ memset(ibuf->rect_float, 0, 4 * ibuf->x * ibuf->y * sizeof(float));
+
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
}
-
- switch (sock->type) {
- case SOCK_FLOAT:
- NODE_DEFINE_SUBTYPES_FLOAT
- break;
- case SOCK_INT:
- NODE_DEFINE_SUBTYPES_INT
- break;
- case SOCK_BOOLEAN:
- return &RNA_NodeSocketBoolean;
- case SOCK_VECTOR:
- NODE_DEFINE_SUBTYPES_VECTOR
- break;
- case SOCK_STRING:
- NODE_DEFINE_SUBTYPES_STRING
- break;
- case SOCK_RGBA:
- return &RNA_NodeSocketRGBA;
- case SOCK_SHADER:
- return &RNA_NodeSocketShader;
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ }
+
+ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_NODES, &ntree->id);
+
+ ED_node_tag_update_nodetree(bmain, ntree);
+}
+
+static bNode *rna_NodeTree_node_new(bNodeTree *ntree, bContext *C, ReportList *reports, const char *type)
+{
+ bNodeType *ntype;
+ bNode *node;
+
+ if (!rna_NodeTree_check(ntree, reports))
+ return NULL;
+
+ ntype = nodeTypeFind(type);
+ if (!ntype) {
+ BKE_reportf(reports, RPT_ERROR, "Node type %s undefined", type);
+ return NULL;
+ }
+
+ if (ntype->poll && !ntype->poll(ntype, ntree)) {
+ BKE_reportf(reports, RPT_ERROR, "Cannot add node of type %s to node tree '%s'", type, ntree->id.name + 2);
+ return NULL;
+ }
+
+ node = nodeAddNode(C, ntree, type);
+ BLI_assert(node && node->typeinfo);
+
+ /* XXX ugly stuff, should be done with specialized operators (after actual node creation)! */
+ if (ntree->type == NTREE_COMPOSIT) {
+ if (ELEM4(node->type, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE, CMP_NODE_R_LAYERS)) {
+ /* annoying, find the node tree we are in, scene can be NULL */
+ Scene *scene;
+ for (scene = CTX_data_main(C)->scene.first; scene; scene = scene->id.next) {
+ if (scene->nodetree == ntree) {
+ break;
+ }
+ }
+ node->id = (ID *)scene;
+ id_us_plus(node->id);
}
- #undef SUBTYPE
+ ntreeCompositForceHidden(ntree, CTX_data_scene(C));
+ }
+ else if (ntree->type == NTREE_TEXTURE) {
+ ntreeTexCheckCyclics(ntree);
}
- return &RNA_NodeSocket;
+ ntreeUpdateTree(ntree);
+ nodeUpdate(ntree, node);
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+
+ return node;
}
-static char *rna_NodeSocket_path(PointerRNA *ptr)
+static void rna_NodeTree_node_remove(bNodeTree *ntree, ReportList *reports, PointerRNA *node_ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- bNodeSocket *sock = (bNodeSocket *)ptr->data;
- bNode *node;
- int socketindex;
+ bNode *node = node_ptr->data;
- /* group sockets */
- socketindex = BLI_findindex(&ntree->inputs, sock);
- if (socketindex != -1)
- return BLI_sprintfN("inputs[%d]", socketindex);
+ if (!rna_NodeTree_check(ntree, reports))
+ return;
- socketindex = BLI_findindex(&ntree->outputs, sock);
- if (socketindex != -1)
- return BLI_sprintfN("outputs[%d]", socketindex);
+ if (BLI_findindex(&ntree->nodes, node) == -1) {
+ BKE_reportf(reports, RPT_ERROR, "Unable to locate node '%s' in node tree", node->name);
+ return;
+ }
+
+ id_us_min(node->id);
+ nodeFreeNode(ntree, node);
+ RNA_POINTER_INVALIDATE(node_ptr);
+
+ ntreeUpdateTree(ntree); /* update group node socket links */
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+}
+
+static void rna_NodeTree_node_clear(bNodeTree *ntree, ReportList *reports)
+{
+ bNode *node = ntree->nodes.first;
+
+ if (!rna_NodeTree_check(ntree, reports))
+ return;
+
+ while (node) {
+ bNode *next_node = node->next;
+
+ if (node->id)
+ id_us_min(node->id);
+
+ nodeFreeNode(ntree, node);
+
+ node = next_node;
+ }
+
+ ntreeUpdateTree(ntree);
+
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+}
+
+static PointerRNA rna_NodeTree_active_node_get(PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->data;
+ bNode *node = nodeGetActive(ntree);
+ return rna_pointer_inherit_refine(ptr, &RNA_Node, node);
+}
+
+static void rna_NodeTree_active_node_set(PointerRNA *ptr, const PointerRNA value)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->data;
+ bNode *node = (bNode *)value.data;
- /* node sockets */
- if (!nodeFindNode(ntree, sock, &node, NULL, NULL)) return NULL;
+ if (node && BLI_findindex(&ntree->nodes, node) != -1)
+ nodeSetActive(ntree, node);
+ else
+ nodeClearActive(ntree);
+}
+
+static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, ReportList *reports,
+ bNodeSocket *fromsock, bNodeSocket *tosock,
+ int verify_limits)
+{
+ bNodeLink *ret;
+ bNode *fromnode = NULL, *tonode = NULL;
+
+ if (!rna_NodeTree_check(ntree, reports))
+ return NULL;
+
+ nodeFindNode(ntree, fromsock, &fromnode, NULL);
+ nodeFindNode(ntree, tosock, &tonode, NULL);
- socketindex = BLI_findindex(&node->inputs, sock);
- if (socketindex != -1)
- return BLI_sprintfN("nodes[\"%s\"].inputs[%d]", node->name, socketindex);
+ if (&fromsock->in_out == &tosock->in_out) {
+ BKE_report(reports, RPT_ERROR, "Same input/output direction of sockets");
+ return NULL;
+ }
+
+ if (verify_limits) {
+ /* remove other socket links if limit is exceeded */
+ if (nodeCountSocketLinks(ntree, fromsock) + 1 > fromsock->limit)
+ nodeRemSocketLinks(ntree, fromsock);
+ if (nodeCountSocketLinks(ntree, tosock) + 1 > tosock->limit)
+ nodeRemSocketLinks(ntree, tosock);
+ }
+
+ ret = nodeAddLink(ntree, fromnode, fromsock, tonode, tosock);
- socketindex = BLI_findindex(&node->outputs, sock);
- if (socketindex != -1)
- return BLI_sprintfN("nodes[\"%s\"].outputs[%d]", node->name, socketindex);
+ if (ret) {
+ if (tonode)
+ nodeUpdate(ntree, tonode);
+
+ ntreeUpdateTree(ntree);
+
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+ }
+ return ret;
+}
+
+static void rna_NodeTree_link_remove(bNodeTree *ntree, ReportList *reports, PointerRNA *link_ptr)
+{
+ bNodeLink *link = link_ptr->data;
+
+ if (!rna_NodeTree_check(ntree, reports))
+ return;
+
+ if (BLI_findindex(&ntree->links, link) == -1) {
+ BKE_report(reports, RPT_ERROR, "Unable to locate link in node tree");
+ return;
+ }
+
+ nodeRemLink(ntree, link);
+ RNA_POINTER_INVALIDATE(link_ptr);
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+}
+
+static void rna_NodeTree_link_clear(bNodeTree *ntree, ReportList *reports)
+{
+ bNodeLink *link = ntree->links.first;
+
+ if (!rna_NodeTree_check(ntree, reports))
+ return;
+
+ while (link) {
+ bNodeLink *next_link = link->next;
+
+ nodeRemLink(ntree, link);
+
+ link = next_link;
+ }
+ ntreeUpdateTree(ntree);
+
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+}
+
+static int rna_NodeTree_active_input_get(PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->data;
+ bNodeSocket *gsock;
+ int index;
+
+ for (gsock = ntree->inputs.first, index = 0; gsock; gsock = gsock->next, ++index)
+ if (gsock->flag & SELECT)
+ return index;
+ return -1;
+}
+
+static void rna_NodeTree_active_input_set(PointerRNA *ptr, int value)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->data;
+ bNodeSocket *gsock;
+ int index;
- return NULL;
+ for (gsock = ntree->inputs.first, index = 0; gsock; gsock = gsock->next, ++index) {
+ if (index == value)
+ gsock->flag |= SELECT;
+ else
+ gsock->flag &= ~SELECT;
+ }
+ for (gsock = ntree->outputs.first; gsock; gsock = gsock->next) {
+ gsock->flag &= ~SELECT;
+ }
}
-static void rna_NodeSocket_hide_set(PointerRNA *ptr, int value)
+static int rna_NodeTree_active_output_get(PointerRNA *ptr)
{
- bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ bNodeTree *ntree = (bNodeTree *)ptr->data;
+ bNodeSocket *gsock;
+ int index;
+
+ for (gsock = ntree->outputs.first, index = 0; gsock; gsock = gsock->next, ++index)
+ if (gsock->flag & SELECT)
+ return index;
+ return -1;
+}
+
+static void rna_NodeTree_active_output_set(PointerRNA *ptr, int value)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->data;
+ bNodeSocket *gsock;
+ int index;
- /* don't hide linked sockets */
- if (sock->flag & SOCK_IN_USE)
+ for (gsock = ntree->inputs.first; gsock; gsock = gsock->next) {
+ gsock->flag &= ~SELECT;
+ }
+ for (gsock = ntree->outputs.first, index = 0; gsock; gsock = gsock->next, ++index) {
+ if (index == value)
+ gsock->flag |= SELECT;
+ else
+ gsock->flag &= ~SELECT;
+ }
+}
+
+static int rna_NodeTree_inputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->data;
+ bNodeSocket *sock = ntreeFindSocketInterface(ntree, SOCK_IN, key);
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocketInterface, sock, r_ptr);
+ return (sock != NULL);
+}
+
+static int rna_NodeTree_outputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->data;
+ bNodeSocket *sock = ntreeFindSocketInterface(ntree, SOCK_OUT, key);
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocketInterface, sock, r_ptr);
+ return (sock != NULL);
+}
+
+static bNodeSocket *rna_NodeTree_inputs_new(bNodeTree *ntree, ReportList *reports, const char *type, const char *name)
+{
+ bNodeSocket *sock;
+
+ if (!rna_NodeTree_check(ntree, reports))
+ return NULL;
+
+ sock = ntreeAddSocketInterface(ntree, SOCK_IN, type, name);
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+
+ return sock;
+}
+
+static bNodeSocket *rna_NodeTree_outputs_new(bNodeTree *ntree, ReportList *reports, const char *type, const char *name)
+{
+ bNodeSocket *sock;
+
+ if (!rna_NodeTree_check(ntree, reports))
+ return NULL;
+
+ sock = ntreeAddSocketInterface(ntree, SOCK_OUT, type, name);
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+
+ return sock;
+}
+
+static void rna_NodeTree_socket_remove(bNodeTree *ntree, ReportList *reports, bNodeSocket *sock)
+{
+ if (!rna_NodeTree_check(ntree, reports))
return;
- if (value)
- sock->flag |= SOCK_HIDDEN;
- else
- sock->flag &= ~SOCK_HIDDEN;
+ if (BLI_findindex(&ntree->inputs, sock) == -1 && BLI_findindex(&ntree->outputs, sock) == -1) {
+ BKE_reportf(reports, RPT_ERROR, "Unable to locate socket '%s' in node", sock->identifier);
+ }
+ else {
+ ntreeRemoveSocketInterface(ntree, sock);
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+ }
}
-/* Button Set Funcs for Matte Nodes */
-static void rna_Matte_t1_set(PointerRNA *ptr, float value)
+static void rna_NodeTree_inputs_clear(bNodeTree *ntree, ReportList *reports)
{
- bNode *node = (bNode *)ptr->data;
- NodeChroma *chroma = node->storage;
+ bNodeSocket *sock, *nextsock;
- chroma->t1 = value;
+ if (!rna_NodeTree_check(ntree, reports))
+ return;
- if (value < chroma->t2)
- chroma->t2 = value;
+ for (sock = ntree->inputs.first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ ntreeRemoveSocketInterface(ntree, sock);
+ }
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
-static void rna_Matte_t2_set(PointerRNA *ptr, float value)
+static void rna_NodeTree_outputs_clear(bNodeTree *ntree, ReportList *reports)
{
- bNode *node = (bNode *)ptr->data;
- NodeChroma *chroma = node->storage;
+ bNodeSocket *sock, *nextsock;
- if (value > chroma->t1)
- value = chroma->t1;
+ if (!rna_NodeTree_check(ntree, reports))
+ return;
- chroma->t2 = value;
+ for (sock = ntree->outputs.first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ ntreeRemoveSocketInterface(ntree, sock);
+ }
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
-static void rna_distance_matte_t1_set(PointerRNA *ptr, float value)
+static void rna_NodeTree_interface_update(bNodeTree *ntree, bContext *C)
{
- bNode *node = (bNode *)ptr->data;
- NodeChroma *chroma = node->storage;
+ ntree->update |= NTREE_UPDATE_GROUP;
+ ntreeUpdateTree(ntree);
+
+ ED_node_tag_update_nodetree(CTX_data_main(C), ntree);
+}
- chroma->t1 = value;
+static void rna_NodeTree_bl_idname_get(PointerRNA *ptr, char *value)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ strcpy(value, ntree->typeinfo->idname);
+ else
+ strcpy(value, "UNDEFINED");
+}
+static int rna_NodeTree_bl_idname_length(PointerRNA *ptr)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ return strlen(ntree->typeinfo->idname);
+ else
+ return strlen("UNDEFINED");
}
-static void rna_distance_matte_t2_set(PointerRNA *ptr, float value)
+static void rna_NodeTree_bl_label_get(PointerRNA *ptr, char *value)
{
- bNode *node = (bNode *)ptr->data;
- NodeChroma *chroma = node->storage;
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ strcpy(value, ntree->typeinfo->ui_name);
+ else
+ strcpy(value, "UNDEFINED");
+}
+static int rna_NodeTree_bl_label_length(PointerRNA *ptr)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ return strlen(ntree->typeinfo->ui_name);
+ else
+ return strlen("UNDEFINED");
+}
- chroma->t2 = value;
+static void rna_NodeTree_bl_description_get(PointerRNA *ptr, char *value)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ strcpy(value, ntree->typeinfo->ui_description);
+ else
+ strcpy(value, "UNDEFINED");
+}
+static int rna_NodeTree_bl_description_length(PointerRNA *ptr)
+{
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ return strlen(ntree->typeinfo->ui_description);
+ else
+ return strlen("UNDEFINED");
}
-static void rna_difference_matte_t1_set(PointerRNA *ptr, float value)
+static int rna_NodeTree_bl_icon_get(PointerRNA *ptr)
{
- bNode *node = (bNode *)ptr->data;
- NodeChroma *chroma = node->storage;
+ bNodeTree *ntree = ptr->data;
+ if (ntree->typeinfo)
+ return ntree->typeinfo->ui_icon;
+ else
+ return ICON_NONE;
+}
- chroma->t1 = value;
+
+/* ******** NodeLink ******** */
+
+static int rna_NodeLink_is_hidden_get(PointerRNA *ptr)
+{
+ bNodeLink *link = ptr->data;
+ return nodeLinkIsHidden(link);
}
-static void rna_difference_matte_t2_set(PointerRNA *ptr, float value)
+
+/* ******** Node ******** */
+
+static StructRNA *rna_Node_refine(struct PointerRNA *ptr)
{
bNode *node = (bNode *)ptr->data;
- NodeChroma *chroma = node->storage;
+
+ if (node->typeinfo && node->typeinfo->ext.srna)
+ return node->typeinfo->ext.srna;
+ else
+ return ptr->type;
+}
- chroma->t2 = value;
+static char *rna_Node_path(PointerRNA *ptr)
+{
+ bNode *node = (bNode *)ptr->data;
+
+ return BLI_sprintfN("nodes[\"%s\"]", node->name);
}
+static int rna_Node_poll(bNodeType *ntype, bNodeTree *ntree)
+{
+ extern FunctionRNA rna_Node_poll_func;
-static void rna_Node_scene_set(PointerRNA *ptr, PointerRNA value)
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret;
+ int visible;
+
+ RNA_pointer_create(NULL, ntype->ext.srna, NULL, &ptr); /* dummy */
+ func = &rna_Node_poll_func; /* RNA_struct_find_function(&ptr, "poll"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "node_tree", &ntree);
+ ntype->ext.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "visible", &ret);
+ visible = *(int *)ret;
+
+ RNA_parameter_list_free(&list);
+
+ return visible;
+}
+
+static int rna_Node_poll_instance(bNode *node, bNodeTree *ntree)
{
- bNode *node = (bNode *)ptr->data;
+ extern FunctionRNA rna_Node_poll_instance_func;
- if (node->id) {
- id_us_min(node->id);
- node->id = NULL;
- }
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret;
+ int visible;
- node->id = value.data;
+ if (!node->typeinfo)
+ return FALSE;
- id_us_plus(node->id);
+ RNA_pointer_create(NULL, node->typeinfo->ext.srna, node, &ptr); /* dummy */
+ func = &rna_Node_poll_instance_func; /* RNA_struct_find_function(&ptr, "poll_instance"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "node_tree", &ntree);
+ node->typeinfo->ext.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "visible", &ret);
+ visible = *(int *)ret;
+
+ RNA_parameter_list_free(&list);
+
+ return visible;
+}
+
+static int rna_Node_poll_instance_default(bNode *node, bNodeTree *ntree)
+{
+ if (!node->typeinfo)
+ return FALSE;
+
+ /* use the basic poll function */
+ return rna_Node_poll(node->typeinfo, ntree);
}
+static void rna_Node_update_reg(bNodeTree *ntree, bNode *node)
+{
+ extern FunctionRNA rna_Node_update_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!node->typeinfo)
+ return;
+
+ RNA_pointer_create((ID *)ntree, node->typeinfo->ext.srna, node, &ptr);
+ func = &rna_Node_update_func; /* RNA_struct_find_function(&ptr, "update"); */
+ RNA_parameter_list_create(&list, &ptr, func);
+ node->typeinfo->ext.call(NULL, &ptr, func, &list);
-static void node_update(Main *bmain, Scene *UNUSED(scene), bNodeTree *ntree, bNode *node)
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_Node_init(const bContext *C, PointerRNA *ptr)
{
- ED_node_generic_update(bmain, ntree, node);
+ extern FunctionRNA rna_Node_init_func;
+
+ bNode *node = (bNode *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!node->typeinfo)
+ return;
+
+ func = &rna_Node_init_func; /* RNA_struct_find_function(&ptr, "init"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ node->typeinfo->ext.call((bContext *)C, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
}
-static void rna_Node_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Node_copy(PointerRNA *ptr, struct bNode *copynode)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ extern FunctionRNA rna_Node_copy_func;
+
bNode *node = (bNode *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!node->typeinfo)
+ return;
+
+ func = &rna_Node_copy_func; /* RNA_struct_find_function(&ptr, "copy"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "node", &copynode);
+ node->typeinfo->ext.call(NULL, ptr, func, &list);
- node_update(bmain, scene, ntree, node);
+ RNA_parameter_list_free(&list);
}
-static void rna_Node_tex_image_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Node_free(PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ extern FunctionRNA rna_Node_free_func;
+
bNode *node = (bNode *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
- node_update(bmain, scene, ntree, node);
- WM_main_add_notifier(NC_IMAGE, NULL);
+ if (!node->typeinfo)
+ return;
+
+ func = &rna_Node_free_func; /* RNA_struct_find_function(&ptr, "free"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ node->typeinfo->ext.call(NULL, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
}
-static void rna_Node_material_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Node_draw_buttons(struct uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ extern FunctionRNA rna_Node_draw_buttons_func;
+
bNode *node = (bNode *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
- if (node->id)
- nodeSetActive(ntree, node);
+ if (!node->typeinfo)
+ return;
+
+ func = &rna_Node_draw_buttons_func; /* RNA_struct_find_function(&ptr, "draw_buttons"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "layout", &layout);
+ node->typeinfo->ext.call(C, ptr, func, &list);
- node_update(bmain, scene, ntree, node);
+ RNA_parameter_list_free(&list);
}
-static void rna_NodeGroup_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Node_draw_buttons_ext(struct uiLayout *layout, bContext *C, PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ extern FunctionRNA rna_Node_draw_buttons_ext_func;
+
bNode *node = (bNode *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!node->typeinfo)
+ return;
+
+ func = &rna_Node_draw_buttons_ext_func; /* RNA_struct_find_function(&ptr, "draw_buttons_ext"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "layout", &layout);
+ node->typeinfo->ext.call(C, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static int rna_Node_is_registered_node_type(StructRNA *type)
+{
+ return (RNA_struct_blender_type_get(type) != NULL);
+}
+
+static void rna_Node_is_registered_node_type_runtime(bContext *UNUSED(C), ReportList *UNUSED(reports), PointerRNA *ptr, ParameterList *parms)
+{
+ int result = (RNA_struct_blender_type_get(ptr->type) != NULL);
+ RNA_parameter_set_lookup(parms, "result", &result);
+}
+
+static void rna_Node_unregister(Main *UNUSED(bmain), StructRNA *type)
+{
+ bNodeType *nt = RNA_struct_blender_type_get(type);
+
+ if (!nt)
+ return;
+
+ RNA_struct_free_extension(type, &nt->ext);
+
+ /* this also frees the allocated nt pointer, no MEM_free call needed! */
+ nodeUnregisterType(nt);
+
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
+}
+
+/* Generic internal registration function.
+ * Can be used to implement callbacks for registerable RNA node subtypes.
+ */
+static bNodeType *rna_Node_register_base(Main *bmain, ReportList *reports, StructRNA *basetype,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeType *nt, dummynt;
+ bNode dummynode;
+ PointerRNA dummyptr;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+ int have_function[8];
+
+ /* setup dummy node & node type to store static properties in */
+ memset(&dummynt, 0, sizeof(bNodeType));
+ /* this does some additional initialization of default values */
+ node_type_base_custom(&dummynt, identifier, "", 0, 0);
+
+ memset(&dummynode, 0, sizeof(bNode));
+ dummynode.typeinfo = &dummynt;
+ RNA_pointer_create(NULL, basetype, &dummynode, &dummyptr);
+
+ /* validate the python class */
+ if (validate(&dummyptr, data, have_function) != 0)
+ return NULL;
+
+ if (strlen(identifier) >= sizeof(dummynt.idname)) {
+ BKE_reportf(reports, RPT_ERROR, "Registering node class: '%s' is too long, maximum length is %d",
+ identifier, (int)sizeof(dummynt.idname));
+ return NULL;
+ }
+
+ /* check if we have registered this node type before, and remove it */
+ nt = nodeTypeFind(dummynt.idname);
+ if (nt)
+ rna_Node_unregister(bmain, nt->ext.srna);
+
+ /* create a new node type */
+ nt = MEM_callocN(sizeof(bNodeType), "node type");
+ memcpy(nt, &dummynt, sizeof(dummynt));
+ /* make sure the node type struct is freed on unregister */
+ nt->needs_free = 1;
+
+ nt->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, nt->idname, basetype);
+ nt->ext.data = data;
+ nt->ext.call = call;
+ nt->ext.free = free;
+ RNA_struct_blender_type_set(nt->ext.srna, nt);
+
+ RNA_def_struct_ui_text(nt->ext.srna, nt->ui_name, nt->ui_description);
+ RNA_def_struct_ui_icon(nt->ext.srna, nt->ui_icon);
+
+ func = RNA_def_function_runtime(nt->ext.srna, "is_registered_node_type", rna_Node_is_registered_node_type_runtime);
+ RNA_def_function_ui_description(func, "True if a registered node type");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_SELF_TYPE);
+ parm = RNA_def_boolean(func, "result", FALSE, "Result", "");
+ RNA_def_function_return(func, parm);
+
+ /* XXX bad level call! needed to initialize the basic draw functions ... */
+ ED_init_custom_node_type(nt);
+
+ nt->poll = (have_function[0]) ? rna_Node_poll : NULL;
+ nt->poll_instance = (have_function[1]) ? rna_Node_poll_instance : rna_Node_poll_instance_default;
+ nt->updatefunc = (have_function[2]) ? rna_Node_update_reg : NULL;
+ nt->initfunc_api = (have_function[3]) ? rna_Node_init : NULL;
+ nt->copyfunc_api = (have_function[4]) ? rna_Node_copy : NULL;
+ nt->freefunc_api = (have_function[5]) ? rna_Node_free : NULL;
+ nt->uifunc = (have_function[6]) ? rna_Node_draw_buttons : NULL;
+ nt->uifuncbut = (have_function[7]) ? rna_Node_draw_buttons_ext : NULL;
+ /* node buttons are only drawn if the options flag is set */
+ if (nt->uifunc || nt->uifuncbut)
+ nt->flag |= NODE_OPTIONS;
- ntreeUpdateTree((bNodeTree *)node->id);
+ return nt;
+}
+
+static StructRNA *rna_Node_register(Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_Node, data, identifier, validate, call, free);
+ if (!nt)
+ return NULL;
+
+ nodeRegisterType(nt);
- node_update(bmain, scene, ntree, node);
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
+
+ return nt->ext.srna;
}
-static int rna_NodeGroup_node_tree_poll(PointerRNA *ptr, const PointerRNA value)
+static StructRNA *rna_NodeGroup_register(Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- bNodeTree *ngroup = (bNodeTree *)value.data;
+ bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_NodeGroup, data, identifier, validate, call, free);
+ if (!nt)
+ return NULL;
- /* only allow node trees of the same type as the group node's tree */
- return (ngroup->type == ntree->type);
+ nodeRegisterType(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
+
+ return nt->ext.srna;
+}
+
+static StructRNA *rna_ShaderNode_register(Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_ShaderNode, data, identifier, validate, call, free);
+ if (!nt)
+ return NULL;
+
+ nodeRegisterType(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
+
+ return nt->ext.srna;
+}
+
+static StructRNA *rna_CompositorNode_register(Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_CompositorNode, data, identifier, validate, call, free);
+ if (!nt)
+ return NULL;
+
+ nodeRegisterType(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
+
+ return nt->ext.srna;
+}
+
+static StructRNA *rna_TextureNode_register(Main *bmain, ReportList *reports,
+ void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeType *nt = rna_Node_register_base(bmain, reports, &RNA_TextureNode, data, identifier, validate, call, free);
+ if (!nt)
+ return NULL;
+
+ nodeRegisterType(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
+
+ return nt->ext.srna;
+}
+
+static IDProperty *rna_Node_idprops(PointerRNA *ptr, bool create)
+{
+ bNode *node = ptr->data;
+
+ if (create && !node->prop) {
+ IDPropertyTemplate val = {0};
+ node->prop = IDP_New(IDP_GROUP, &val, "RNA_Node ID properties");
+ }
+
+ return node->prop;
+}
+
+static void rna_Node_parent_set(PointerRNA *ptr, PointerRNA value)
+{
+ bNode *node = ptr->data;
+ bNode *parent = value.data;
+
+ if (parent) {
+ /* XXX only Frame node allowed for now,
+ * in the future should have a poll function or so to test possible attachment.
+ */
+ if (parent->type != NODE_FRAME)
+ return;
+
+ /* make sure parent is not attached to the node */
+ if (nodeAttachNodeCheck(parent, node))
+ return;
+ }
+
+ nodeDetachNode(node);
+ if (parent) {
+ nodeAttachNode(node, parent);
+ }
+}
+
+static int rna_Node_parent_poll(PointerRNA *ptr, PointerRNA value)
+{
+ bNode *node = ptr->data;
+ bNode *parent = value.data;
+
+ /* XXX only Frame node allowed for now,
+ * in the future should have a poll function or so to test possible attachment.
+ */
+ if (parent->type != NODE_FRAME)
+ return FALSE;
+
+ /* make sure parent is not attached to the node */
+ if (nodeAttachNodeCheck(parent, node))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void rna_Node_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ ED_node_tag_update_nodetree(bmain, ntree);
+}
+
+static void rna_Node_socket_value_update(ID *id, bNode *UNUSED(node), bContext *C)
+{
+ ED_node_tag_update_nodetree(CTX_data_main(C), (bNodeTree *)id);
+}
+
+static void rna_Node_select_set(PointerRNA *ptr, int value)
+{
+ bNode *node = (bNode *)ptr->data;
+ nodeSetSelected(node, value);
}
static void rna_Node_name_set(PointerRNA *ptr, const char *value)
@@ -499,60 +1590,903 @@ static void rna_Node_name_set(PointerRNA *ptr, const char *value)
BKE_all_animdata_fix_paths_rename(NULL, "nodes", oldname, node->name);
}
-static void rna_NodeSocket_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static int rna_Node_inputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
+{
+ bNode *node = (bNode *)ptr->data;
+ bNodeSocket *sock = nodeFindSocket(node, SOCK_IN, key);
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, sock, r_ptr);
+ return (sock != NULL);
+}
+
+static int rna_Node_outputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
+{
+ bNode *node = (bNode *)ptr->data;
+ bNodeSocket *sock = nodeFindSocket(node, SOCK_OUT, key);
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, sock, r_ptr);
+ return (sock != NULL);
+}
+
+static bNodeSocket *rna_Node_inputs_new(ID *id, bNode *node, ReportList *reports, const char *type, const char *name, const char *identifier)
+{
+ bNodeTree *ntree = (bNodeTree *)id;
+ bNodeSocket *sock;
+
+ if (!node->typeinfo) {
+ BKE_reportf(reports, RPT_ERROR, "Node type %s of node %s undefined", node->idname, node->name);
+ return NULL;
+ }
+
+ sock = nodeAddSocket(ntree, node, SOCK_IN, type, identifier, name);
+
+ if (sock == NULL) {
+ BKE_report(reports, RPT_ERROR, "Unable to create socket");
+ }
+ else {
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+ }
+
+ return sock;
+}
+
+static bNodeSocket *rna_Node_outputs_new(ID *id, bNode *node, ReportList *reports, const char *type, const char *name, const char *identifier)
+{
+ bNodeTree *ntree = (bNodeTree *)id;
+ bNodeSocket *sock;
+
+ if (!node->typeinfo) {
+ BKE_reportf(reports, RPT_ERROR, "Node type %s of node %s undefined", node->idname, node->name);
+ return NULL;
+ }
+
+ sock = nodeAddSocket(ntree, node, SOCK_OUT, type, identifier, name);
+
+ if (sock == NULL) {
+ BKE_reportf(reports, RPT_ERROR, "Unable to create socket");
+ }
+ else {
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+ }
+
+ return sock;
+}
+
+static void rna_Node_socket_remove(ID *id, bNode *node, ReportList *reports, bNodeSocket *sock)
+{
+ bNodeTree *ntree = (bNodeTree *)id;
+
+ if (!node->typeinfo) {
+ BKE_reportf(reports, RPT_ERROR, "Node type %s of node %s undefined", node->idname, node->name);
+ return;
+ }
+
+ if (BLI_findindex(&node->inputs, sock) == -1 && BLI_findindex(&node->outputs, sock) == -1) {
+ BKE_reportf(reports, RPT_ERROR, "Unable to locate socket '%s' in node", sock->identifier);
+ }
+ else {
+ nodeRemoveSocket(ntree, node, sock);
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+ }
+}
+
+static void rna_Node_inputs_clear(ID *id, bNode *node, ReportList *reports)
+{
+ bNodeTree *ntree = (bNodeTree *)id;
+ bNodeSocket *sock, *nextsock;
+
+ if (!node->typeinfo) {
+ BKE_reportf(reports, RPT_ERROR, "Node type %s of node %s undefined", node->idname, node->name);
+ return;
+ }
+
+ for (sock = node->inputs.first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ nodeRemoveSocket(ntree, node, sock);
+ }
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+}
+
+static void rna_Node_outputs_clear(ID *id, bNode *node, ReportList *reports)
+{
+ bNodeTree *ntree = (bNodeTree *)id;
+ bNodeSocket *sock, *nextsock;
+
+ if (!node->typeinfo) {
+ BKE_reportf(reports, RPT_ERROR, "Node type %s of node %s undefined", node->idname, node->name);
+ return;
+ }
+
+ for (sock = node->outputs.first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ nodeRemoveSocket(ntree, node, sock);
+ }
+
+ ntreeUpdateTree(ntree);
+ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
+}
+
+static void rna_Node_width_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo) {
+ *min = *softmin = node->typeinfo->minwidth;
+ *max = *softmax = node->typeinfo->maxwidth;
+ }
+ else {
+ *min = *softmin = 0.0f;
+ *max = *softmax = 0.0f;
+ }
+}
+
+static void rna_Node_height_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo) {
+ *min = *softmin = node->typeinfo->minheight;
+ *max = *softmax = node->typeinfo->maxheight;
+ }
+ else {
+ *min = *softmin = 0.0f;
+ *max = *softmax = 0.0f;
+ }
+}
+
+static void rna_Node_bl_idname_get(PointerRNA *ptr, char *value)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo)
+ strcpy(value, node->typeinfo->idname);
+ else
+ strcpy(value, "UNDEFINED");
+}
+static int rna_Node_bl_idname_length(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo)
+ return strlen(node->typeinfo->idname);
+ else
+ return strlen("UNDEFINED");
+}
+
+static void rna_Node_bl_label_get(PointerRNA *ptr, char *value)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo)
+ strcpy(value, node->typeinfo->ui_name);
+ else
+ strcpy(value, "UNDEFINED");
+}
+static int rna_Node_bl_label_length(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo)
+ return strlen(node->typeinfo->ui_name);
+ else
+ return strlen("UNDEFINED");
+}
+
+static void rna_Node_bl_description_get(PointerRNA *ptr, char *value)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo)
+ strcpy(value, node->typeinfo->ui_description);
+ else
+ strcpy(value, "");
+}
+static int rna_Node_bl_description_length(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo)
+ return strlen(node->typeinfo->ui_description);
+ else
+ return strlen("");
+}
+
+static int rna_Node_bl_icon_get(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo)
+ return node->typeinfo->ui_icon;
+ else
+ return ICON_NONE;
+}
+
+static int rna_Node_bl_static_type_get(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ if (node->typeinfo)
+ return node->typeinfo->type;
+ else
+ return NODE_UNDEFINED;
+}
+
+
+/* ******** Node Socket ******** */
+
+static void rna_NodeSocket_draw(bContext *C, struct uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr)
+{
+ extern FunctionRNA rna_NodeSocket_draw_func;
+
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!sock->typeinfo)
+ return;
+
+ func = &rna_NodeSocket_draw_func; /* RNA_struct_find_function(&ptr, "draw"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "layout", &layout);
+ RNA_parameter_set_lookup(&list, "node", node_ptr);
+ sock->typeinfo->ext_socket.call(C, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_NodeSocket_draw_color(bContext *C, PointerRNA *ptr, PointerRNA *node_ptr, float *r_color)
+{
+ extern FunctionRNA rna_NodeSocket_draw_color_func;
+
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret;
+
+ if (!sock->typeinfo)
+ return;
+
+ func = &rna_NodeSocket_draw_color_func; /* RNA_struct_find_function(&ptr, "draw_color"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "node", node_ptr);
+ sock->typeinfo->ext_socket.call(C, ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "color", &ret);
+ copy_v4_v4(r_color, (float *)ret);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_NodeSocket_unregister(Main *UNUSED(bmain), StructRNA *type)
+{
+ bNodeSocketType *st = RNA_struct_blender_type_get(type);
+ if (!st)
+ return;
+
+ RNA_struct_free_extension(type, &st->ext_socket);
+
+ nodeUnregisterSocketType(st);
+
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
+}
+
+static StructRNA *rna_NodeSocket_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeSocketType *st, dummyst;
+ bNodeSocket dummysock;
+ PointerRNA dummyptr;
+ int have_function[2];
+
+ /* setup dummy socket & socket type to store static properties in */
+ memset(&dummyst, 0, sizeof(bNodeSocketType));
+
+ memset(&dummysock, 0, sizeof(bNodeSocket));
+ dummysock.typeinfo = &dummyst;
+ RNA_pointer_create(NULL, &RNA_NodeSocket, &dummysock, &dummyptr);
+
+ /* validate the python class */
+ if (validate(&dummyptr, data, have_function) != 0)
+ return NULL;
+
+ if (strlen(identifier) >= sizeof(dummyst.idname)) {
+ BKE_reportf(reports, RPT_ERROR, "Registering node socket class: '%s' is too long, maximum length is %d",
+ identifier, (int)sizeof(dummyst.idname));
+ return NULL;
+ }
+
+ /* check if we have registered this socket type before */
+ st = nodeSocketTypeFind(dummyst.idname);
+ if (!st) {
+ /* create a new node socket type */
+ st = MEM_callocN(sizeof(bNodeSocketType), "node socket type");
+ memcpy(st, &dummyst, sizeof(dummyst));
+
+ nodeRegisterSocketType(st);
+ }
+
+ /* if RNA type is already registered, unregister first */
+ if (st->ext_socket.srna) {
+ StructRNA *srna = st->ext_socket.srna;
+ RNA_struct_free_extension(srna, &st->ext_socket);
+ RNA_struct_free(&BLENDER_RNA, srna);
+ }
+ st->ext_socket.srna = RNA_def_struct_ptr(&BLENDER_RNA, st->idname, &RNA_NodeSocket);
+ st->ext_socket.data = data;
+ st->ext_socket.call = call;
+ st->ext_socket.free = free;
+ RNA_struct_blender_type_set(st->ext_socket.srna, st);
+
+ /* XXX bad level call! needed to initialize the basic draw functions ... */
+ ED_init_custom_node_socket_type(st);
+
+ st->draw = (have_function[0]) ? rna_NodeSocket_draw : NULL;
+ st->draw_color = (have_function[1]) ? rna_NodeSocket_draw_color : NULL;
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
+
+ return st->ext_socket.srna;
+}
+
+static StructRNA *rna_NodeSocket_refine(PointerRNA *ptr)
+{
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+
+ if (sock->typeinfo && sock->typeinfo->ext_socket.srna)
+ return sock->typeinfo->ext_socket.srna;
+ else
+ return &RNA_NodeSocket;
+}
+
+static char *rna_NodeSocket_path(PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
bNodeSocket *sock = (bNodeSocket *)ptr->data;
bNode *node;
+ int socketindex;
- if (nodeFindNode(ntree, sock, &node, NULL, NULL))
- node_update(bmain, scene, ntree, node);
+ if (!nodeFindNode(ntree, sock, &node, &socketindex))
+ return NULL;
+
+ if (sock->in_out == SOCK_IN)
+ return BLI_sprintfN("nodes[\"%s\"].inputs[%d]", node->name, socketindex);
+ else
+ return BLI_sprintfN("nodes[\"%s\"].outputs[%d]", node->name, socketindex);
+
+ return NULL;
}
-static void rna_NodeGroupSocket_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static IDProperty *rna_NodeSocket_idprops(PointerRNA *ptr, bool create)
+{
+ bNodeSocket *sock = ptr->data;
+
+ if (create && !sock->prop) {
+ IDPropertyTemplate val = {0};
+ sock->prop = IDP_New(IDP_GROUP, &val, "RNA_NodeSocket ID properties");
+ }
+
+ return sock->prop;
+}
+
+static void rna_NodeSocket_bl_idname_get(PointerRNA *ptr, char *value)
+{
+ bNodeSocket *sock = ptr->data;
+ if (sock->typeinfo)
+ strcpy(value, sock->typeinfo->idname);
+ else
+ strcpy(value, "UNDEFINED");
+}
+static int rna_NodeSocket_bl_idname_length(PointerRNA *ptr)
+{
+ bNodeSocket *sock = ptr->data;
+ if (sock->typeinfo)
+ return strlen(sock->typeinfo->idname);
+ else
+ return strlen("UNDEFINED");
+}
+
+static PointerRNA rna_NodeSocket_node_get(PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
bNodeSocket *sock = (bNodeSocket *)ptr->data;
bNode *node;
+ PointerRNA r_ptr;
- ntreeUpdateTree(ntree);
+ nodeFindNode(ntree, sock, &node, NULL);
- if (nodeFindNode(ntree, sock, &node, NULL, NULL))
- node_update(bmain, scene, ntree, node);
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &r_ptr);
+ return r_ptr;
}
-#if 0 /* UNUSED */
-static void rna_NodeLink_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_NodeSocket_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ ED_node_tag_update_nodetree(bmain, ntree);
+}
- ntree->update |= NTREE_UPDATE_LINKS;
- ntreeUpdateTree(ntree);
+static void rna_NodeSocket_hide_set(PointerRNA *ptr, int value)
+{
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+
+ /* don't hide linked sockets */
+ if (sock->flag & SOCK_IN_USE)
+ return;
+
+ if (value)
+ sock->flag |= SOCK_HIDDEN;
+ else
+ sock->flag &= ~SOCK_HIDDEN;
}
-#endif
-static void rna_NodeSocketInt_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+
+static void rna_NodeSocketInterface_draw(bContext *C, struct uiLayout *layout, PointerRNA *ptr)
+{
+ extern FunctionRNA rna_NodeSocketInterface_draw_func;
+
+ bNodeSocket *stemp = (bNodeSocket *)ptr->data;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!stemp->typeinfo)
+ return;
+
+ func = &rna_NodeSocketInterface_draw_func; /* RNA_struct_find_function(&ptr, "draw"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "layout", &layout);
+ stemp->typeinfo->ext_interface.call(C, ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_NodeSocketInterface_draw_color(bContext *C, PointerRNA *ptr, float *r_color)
{
+ extern FunctionRNA rna_NodeSocketInterface_draw_color_func;
+
bNodeSocket *sock = (bNodeSocket *)ptr->data;
- bNodeSocketValueInt *val = (bNodeSocketValueInt *)sock->default_value;
- *softmin = val->min;
- *softmax = val->max;
+ ParameterList list;
+ FunctionRNA *func;
+ void *ret;
+
+ if (!sock->typeinfo)
+ return;
+
+ func = &rna_NodeSocketInterface_draw_color_func; /* RNA_struct_find_function(&ptr, "draw_color"); */
+
+ RNA_parameter_list_create(&list, ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ sock->typeinfo->ext_interface.call(C, ptr, func, &list);
+
+ RNA_parameter_get_lookup(&list, "color", &ret);
+ copy_v4_v4(r_color, (float *)ret);
+
+ RNA_parameter_list_free(&list);
}
-static void rna_NodeSocketFloat_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static void rna_NodeSocketInterface_register_properties(bNodeTree *ntree, bNodeSocket *stemp, StructRNA *data_srna)
+{
+ extern FunctionRNA rna_NodeSocketInterface_register_properties_func;
+
+ PointerRNA ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!stemp->typeinfo)
+ return;
+
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, stemp, &ptr);
+ func = &rna_NodeSocketInterface_register_properties_func; /* RNA_struct_find_function(&ptr, "register_properties"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "data_rna_type", &data_srna);
+ stemp->typeinfo->ext_interface.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_NodeSocketInterface_init_socket(bNodeTree *ntree, bNodeSocket *stemp, bNode *node, bNodeSocket *sock, const char *data_path)
+{
+ extern FunctionRNA rna_NodeSocketInterface_init_socket_func;
+
+ PointerRNA ptr, node_ptr, sock_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!stemp->typeinfo)
+ return;
+
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, stemp, &ptr);
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sock_ptr);
+ func = &rna_NodeSocketInterface_init_socket_func; /* RNA_struct_find_function(&ptr, "init_socket"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "node", &node_ptr);
+ RNA_parameter_set_lookup(&list, "socket", &sock_ptr);
+ RNA_parameter_set_lookup(&list, "data_path", &data_path);
+ stemp->typeinfo->ext_interface.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_NodeSocketInterface_from_socket(bNodeTree *ntree, bNodeSocket *stemp, bNode *node, bNodeSocket *sock)
+{
+ extern FunctionRNA rna_NodeSocketInterface_from_socket_func;
+
+ PointerRNA ptr, node_ptr, sock_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ if (!stemp->typeinfo)
+ return;
+
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, stemp, &ptr);
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sock_ptr);
+ func = &rna_NodeSocketInterface_from_socket_func; /* RNA_struct_find_function(&ptr, "from_socket"); */
+
+ RNA_parameter_list_create(&list, &ptr, func);
+ RNA_parameter_set_lookup(&list, "node", &node_ptr);
+ RNA_parameter_set_lookup(&list, "socket", &sock_ptr);
+ stemp->typeinfo->ext_interface.call(NULL, &ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_NodeSocketInterface_unregister(Main *UNUSED(bmain), StructRNA *type)
+{
+ bNodeSocketType *st = RNA_struct_blender_type_get(type);
+ if (!st)
+ return;
+
+ RNA_struct_free_extension(type, &st->ext_interface);
+
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
+}
+
+static StructRNA *rna_NodeSocketInterface_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bNodeSocketType *st, dummyst;
+ bNodeSocket dummysock;
+ PointerRNA dummyptr;
+ int have_function[5];
+
+ /* setup dummy socket & socket type to store static properties in */
+ memset(&dummyst, 0, sizeof(bNodeSocketType));
+
+ memset(&dummysock, 0, sizeof(bNodeSocket));
+ dummysock.typeinfo = &dummyst;
+ RNA_pointer_create(NULL, &RNA_NodeSocketInterface, &dummysock, &dummyptr);
+
+ /* validate the python class */
+ if (validate(&dummyptr, data, have_function) != 0)
+ return NULL;
+
+ /* check if we have registered this socket type before */
+ st = nodeSocketTypeFind(dummyst.idname);
+ if (st) {
+ /* basic socket type registered by a socket class before. */
+ }
+ else {
+ /* create a new node socket type */
+ st = MEM_callocN(sizeof(bNodeSocketType), "node socket type");
+ memcpy(st, &dummyst, sizeof(dummyst));
+
+ nodeRegisterSocketType(st);
+ }
+
+ /* if RNA type is already registered, unregister first */
+ if (st->ext_interface.srna) {
+ StructRNA *srna = st->ext_interface.srna;
+ RNA_struct_free_extension(srna, &st->ext_interface);
+ RNA_struct_free(&BLENDER_RNA, srna);
+ }
+ st->ext_interface.srna = RNA_def_struct_ptr(&BLENDER_RNA, identifier, &RNA_NodeSocketInterface);
+ st->ext_interface.data = data;
+ st->ext_interface.call = call;
+ st->ext_interface.free = free;
+ RNA_struct_blender_type_set(st->ext_interface.srna, st);
+
+ st->interface_draw = (have_function[0]) ? rna_NodeSocketInterface_draw : NULL;
+ st->interface_draw_color = (have_function[1]) ? rna_NodeSocketInterface_draw_color : NULL;
+ st->interface_register_properties = (have_function[2]) ? rna_NodeSocketInterface_register_properties : NULL;
+ st->interface_init_socket = (have_function[3]) ? rna_NodeSocketInterface_init_socket : NULL;
+ st->interface_from_socket = (have_function[4]) ? rna_NodeSocketInterface_from_socket : NULL;
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
+
+ return st->ext_interface.srna;
+}
+
+static StructRNA *rna_NodeSocketInterface_refine(PointerRNA *ptr)
{
bNodeSocket *sock = (bNodeSocket *)ptr->data;
- bNodeSocketValueFloat *val = (bNodeSocketValueFloat *)sock->default_value;
- *softmin = val->min;
- *softmax = val->max;
+
+ if (sock->typeinfo && sock->typeinfo->ext_interface.srna)
+ return sock->typeinfo->ext_interface.srna;
+ else
+ return &RNA_NodeSocketInterface;
}
-static void rna_NodeSocketVector_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+static char *rna_NodeSocketInterface_path(PointerRNA *ptr)
{
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
bNodeSocket *sock = (bNodeSocket *)ptr->data;
- bNodeSocketValueVector *val = (bNodeSocketValueVector *)sock->default_value;
- *softmin = val->min;
- *softmax = val->max;
+ int socketindex;
+
+ socketindex = BLI_findindex(&ntree->inputs, sock);
+ if (socketindex != -1)
+ return BLI_sprintfN("inputs[%d]", socketindex);
+
+ socketindex = BLI_findindex(&ntree->outputs, sock);
+ if (socketindex != -1)
+ return BLI_sprintfN("outputs[%d]", socketindex);
+
+ return NULL;
+}
+
+static IDProperty *rna_NodeSocketInterface_idprops(PointerRNA *ptr, bool create)
+{
+ bNodeSocket *sock = ptr->data;
+
+ if (create && !sock->prop) {
+ IDPropertyTemplate val = {0};
+ sock->prop = IDP_New(IDP_GROUP, &val, "RNA_NodeSocketInterface ID properties");
+ }
+
+ return sock->prop;
+}
+
+static void rna_NodeSocketInterface_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ bNodeTree *ntree = ptr->id.data;
+ bNodeSocket *stemp = ptr->data;
+
+ if (!stemp->typeinfo)
+ return;
+
+ ntree->update |= NTREE_UPDATE_GROUP;
+ ntreeUpdateTree(ntree);
+
+ ED_node_tag_update_nodetree(bmain, ntree);
+}
+
+
+/* ******** Standard Node Socket Base Types ******** */
+
+static void rna_NodeSocketStandard_draw(ID *id, bNodeSocket *sock, struct bContext *C, struct uiLayout *layout, PointerRNA *nodeptr)
+{
+ PointerRNA ptr;
+ RNA_pointer_create(id, &RNA_NodeSocket, sock, &ptr);
+ sock->typeinfo->draw(C, layout, &ptr, nodeptr);
+}
+
+static void rna_NodeSocketStandard_draw_color(ID *id, bNodeSocket *sock, struct bContext *C, PointerRNA *nodeptr, float *r_color)
+{
+ PointerRNA ptr;
+ RNA_pointer_create(id, &RNA_NodeSocket, sock, &ptr);
+ sock->typeinfo->draw_color(C, &ptr, nodeptr, r_color);
+}
+
+static void rna_NodeSocketInterfaceStandard_draw(ID *id, bNodeSocket *sock, struct bContext *C, struct uiLayout *layout)
+{
+ PointerRNA ptr;
+ RNA_pointer_create(id, &RNA_NodeSocket, sock, &ptr);
+ sock->typeinfo->interface_draw(C, layout, &ptr);
+}
+
+static void rna_NodeSocketInterfaceStandard_draw_color(ID *id, bNodeSocket *sock, struct bContext *C, float *r_color)
+{
+ PointerRNA ptr;
+ RNA_pointer_create(id, &RNA_NodeSocket, sock, &ptr);
+ sock->typeinfo->interface_draw_color(C, &ptr, r_color);
+}
+
+static void rna_NodeSocketStandard_float_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+{
+ bNodeSocket *sock = ptr->data;
+ bNodeSocketValueFloat *dval = sock->default_value;
+ int subtype = sock->typeinfo->subtype;
+
+ *min = (subtype == PROP_UNSIGNED ? 0.0f : -FLT_MAX);
+ *max = FLT_MAX;
+ *softmin = dval->min;
+ *softmax = dval->max;
+}
+
+static void rna_NodeSocketStandard_int_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
+{
+ bNodeSocket *sock = ptr->data;
+ bNodeSocketValueInt *dval = sock->default_value;
+ int subtype = sock->typeinfo->subtype;
+
+ *min = (subtype == PROP_UNSIGNED ? 0 : INT_MIN);
+ *max = INT_MAX;
+ *softmin = dval->min;
+ *softmax = dval->max;
+}
+
+static void rna_NodeSocketStandard_vector_range(PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
+{
+ bNodeSocket *sock = ptr->data;
+ bNodeSocketValueVector *dval = sock->default_value;
+
+ *min = -FLT_MAX;
+ *max = FLT_MAX;
+ *softmin = dval->min;
+ *softmax = dval->max;
+}
+
+/* using a context update function here, to avoid searching the node if possible */
+static void rna_NodeSocketStandard_value_update(struct bContext *C, PointerRNA *ptr)
+{
+ bNode *node;
+
+ /* default update */
+ rna_NodeSocket_update(CTX_data_main(C), CTX_data_scene(C), ptr);
+
+ /* try to use node from context, faster */
+ node = CTX_data_pointer_get(C, "node").data;
+ if (!node) {
+ bNodeTree *ntree = ptr->id.data;
+ bNodeSocket *sock = ptr->data;
+
+ /* fall back to searching node in the tree */
+ nodeFindNode(ntree, sock, &node, NULL);
+ }
+
+ if (node)
+ nodeSynchronizeID(node, true);
+}
+
+
+/* ******** Node Types ******** */
+
+static void rna_CompositorNode_tag_need_exec(bNode *node)
+{
+ node->need_exec = TRUE;
+}
+
+static void rna_Node_tex_image_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+
+ ED_node_tag_update_nodetree(bmain, ntree);
+ WM_main_add_notifier(NC_IMAGE, NULL);
+}
+
+static void rna_Node_material_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNode *node = (bNode *)ptr->data;
+
+ if (node->id)
+ nodeSetActive(ntree, node);
+
+ ED_node_tag_update_nodetree(bmain, ntree);
+}
+
+static void rna_NodeGroup_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNode *node = (bNode *)ptr->data;
+
+ if (node->id)
+ ntreeUpdateTree((bNodeTree *)node->id);
+
+ ED_node_tag_update_nodetree(bmain, ntree);
+}
+
+static int rna_NodeGroup_node_tree_poll(PointerRNA *ptr, const PointerRNA value)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeTree *ngroup = (bNodeTree *)value.data;
+
+ /* only allow node trees of the same type as the group node's tree */
+ return (ngroup->type == ntree->type);
+}
+
+
+static StructRNA *rna_NodeGroup_interface_typef(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ bNodeTree *ngroup = (bNodeTree *)node->id;
+
+ if (ngroup) {
+ StructRNA *srna = ntreeInterfaceTypeGet(ngroup, TRUE);
+ if (srna)
+ return srna;
+ }
+ return &RNA_PropertyGroup;
+}
+
+static StructRNA *rna_NodeGroupInputOutput_interface_typef(PointerRNA *ptr)
+{
+ bNodeTree *ntree = ptr->id.data;
+
+ if (ntree) {
+ StructRNA *srna = ntreeInterfaceTypeGet(ntree, TRUE);
+ if (srna)
+ return srna;
+ }
+ return &RNA_PropertyGroup;
+}
+
+static void rna_distance_matte_t1_set(PointerRNA *ptr, float value)
+{
+ bNode *node = (bNode *)ptr->data;
+ NodeChroma *chroma = node->storage;
+
+ chroma->t1 = value;
+}
+
+static void rna_distance_matte_t2_set(PointerRNA *ptr, float value)
+{
+ bNode *node = (bNode *)ptr->data;
+ NodeChroma *chroma = node->storage;
+
+ chroma->t2 = value;
+}
+
+static void rna_difference_matte_t1_set(PointerRNA *ptr, float value)
+{
+ bNode *node = (bNode *)ptr->data;
+ NodeChroma *chroma = node->storage;
+
+ chroma->t1 = value;
+}
+
+static void rna_difference_matte_t2_set(PointerRNA *ptr, float value)
+{
+ bNode *node = (bNode *)ptr->data;
+ NodeChroma *chroma = node->storage;
+
+ chroma->t2 = value;
+}
+
+/* Button Set Funcs for Matte Nodes */
+static void rna_Matte_t1_set(PointerRNA *ptr, float value)
+{
+ bNode *node = (bNode *)ptr->data;
+ NodeChroma *chroma = node->storage;
+
+ chroma->t1 = value;
+
+ if (value < chroma->t2)
+ chroma->t2 = value;
+}
+
+static void rna_Matte_t2_set(PointerRNA *ptr, float value)
+{
+ bNode *node = (bNode *)ptr->data;
+ NodeChroma *chroma = node->storage;
+
+ if (value > chroma->t1)
+ value = chroma->t1;
+
+ chroma->t2 = value;
+}
+
+static void rna_Node_scene_set(PointerRNA *ptr, PointerRNA value)
+{
+ bNode *node = (bNode *)ptr->data;
+
+ if (node->id) {
+ id_us_min(node->id);
+ node->id = NULL;
+ }
+
+ node->id = value.data;
+
+ id_us_plus(node->id);
}
static void rna_Node_image_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -677,264 +2611,13 @@ static EnumPropertyItem *rna_Node_channel_itemf(bContext *UNUSED(C), PointerRNA
return item;
}
-static PointerRNA rna_NodeTree_active_node_get(PointerRNA *ptr)
-{
- bNodeTree *ntree = (bNodeTree *)ptr->data;
- bNode *node = nodeGetActive(ntree);
- return rna_pointer_inherit_refine(ptr, &RNA_Node, node);
-}
-
-static void rna_NodeTree_active_node_set(PointerRNA *ptr, PointerRNA value)
-{
- bNodeTree *ntree = (bNodeTree *)ptr->data;
- bNode *node = (bNode *)value.data;
- if (node && BLI_findindex(&ntree->nodes, node) != -1)
- nodeSetActive(ntree, node);
- else
- nodeClearActive(ntree);
-}
-
-static bNode *rna_NodeTree_node_new(bNodeTree *ntree, bContext *C, ReportList *reports,
- int type, bNodeTree *group)
+static void rna_Image_Node_update_id(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- bNode *node;
- bNodeTemplate ntemp;
-
- if (type == NODE_GROUP && group == NULL) {
- BKE_report(reports, RPT_ERROR, "Node type 'GROUP' missing group argument");
- return NULL;
- }
-
- ntemp.type = type;
- ntemp.ngroup = group;
- ntemp.scene = CTX_data_scene(C);
- ntemp.main = CTX_data_main(C);
- node = nodeAddNode(ntree, &ntemp);
-
- if (node == NULL) {
- BKE_report(reports, RPT_ERROR, "Unable to create node");
- }
- else {
- ntreeUpdateTree(ntree); /* update group node socket links*/
- nodeUpdate(ntree, node);
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
-
- if (group)
- id_us_plus(&group->id);
- }
-
- return node;
-}
-
-static bNode *rna_NodeTree_node_composite_new(bNodeTree *ntree, bContext *C, ReportList *reports,
- int type, bNodeTree *group)
-{
- /* raises error on failure */
- bNode *node = rna_NodeTree_node_new(ntree, C, reports, type, group);
-
- if (node) {
- if (ELEM4(node->type, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE, CMP_NODE_R_LAYERS)) {
- /* annoying, find the node tree we are in, scene can be NULL */
- Scene *scene;
- for (scene = CTX_data_main(C)->scene.first; scene; scene = scene->id.next) {
- if (scene->nodetree == ntree) {
- break;
- }
- }
- node->id = (ID *)scene;
- id_us_plus(node->id);
- }
-
- ntreeCompositForceHidden(ntree, CTX_data_scene(C));
- ntreeUpdateTree(ntree);
- }
-
- return node;
-}
-
-static bNode *rna_NodeTree_node_texture_new(bNodeTree *ntree, bContext *C, ReportList *reports,
- int type, bNodeTree *group)
-{
- /* raises error on failure */
- bNode *node = rna_NodeTree_node_new(ntree, C, reports, type, group);
-
- if (node) {
- ntreeTexCheckCyclics(ntree);
- }
-
- return node;
-}
-
-static void rna_NodeTree_node_remove(bNodeTree *ntree, ReportList *reports, PointerRNA *node_ptr)
-{
- bNode *node = node_ptr->data;
- if (BLI_findindex(&ntree->nodes, node) == -1) {
- BKE_reportf(reports, RPT_ERROR, "Unable to locate node '%s' in node tree", node->name);
- return;
- }
-
- id_us_min(node->id);
- nodeFreeNode(ntree, node);
- RNA_POINTER_INVALIDATE(node_ptr);
-
- ntreeUpdateTree(ntree); /* update group node socket links */
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
-}
-
-static void rna_NodeTree_node_clear(bNodeTree *ntree)
-{
- bNode *node = ntree->nodes.first;
-
- while (node) {
- bNode *next_node = node->next;
-
- if (node->id)
- id_us_min(node->id);
-
- nodeFreeNode(ntree, node);
-
- node = next_node;
- }
-
- ntreeUpdateTree(ntree); /* update group node socket links*/
-
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
-}
-
-static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, ReportList *reports,
- bNodeSocket *fromsock, bNodeSocket *tosock)
-{
- bNodeLink *ret;
- bNode *fromnode = NULL, *tonode = NULL;
- int from_in_out, to_in_out;
-
- nodeFindNode(ntree, fromsock, &fromnode, NULL, &from_in_out);
- nodeFindNode(ntree, tosock, &tonode, NULL, &to_in_out);
-
- if (&from_in_out == &to_in_out) {
- BKE_report(reports, RPT_ERROR, "Same input/output direction of sockets");
- return NULL;
- }
-
- /* unlink node input socket */
- if (to_in_out == SOCK_IN)
- nodeRemSocketLinks(ntree, tosock);
- else
- nodeRemSocketLinks(ntree, fromsock);
-
- ret = nodeAddLink(ntree, fromnode, fromsock, tonode, tosock);
-
- if (ret) {
- if (tonode)
- nodeUpdate(ntree, tonode);
-
- ntreeUpdateTree(ntree);
-
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
- }
-
- return ret;
-}
-
-static void rna_NodeTree_link_remove(bNodeTree *ntree, ReportList *reports, PointerRNA *link_ptr)
-{
- bNodeLink *link = link_ptr->data;
- if (BLI_findindex(&ntree->links, link) == -1) {
- BKE_report(reports, RPT_ERROR, "Unable to locate link in node tree");
- return;
- }
-
- nodeRemLink(ntree, link);
- RNA_POINTER_INVALIDATE(link_ptr);
-
- ntreeUpdateTree(ntree);
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
-}
-
-static void rna_NodeTree_link_clear(bNodeTree *ntree)
-{
- bNodeLink *link = ntree->links.first;
-
- while (link) {
- bNodeLink *next_link = link->next;
-
- nodeRemLink(ntree, link);
-
- link = next_link;
- }
- ntreeUpdateTree(ntree);
-
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
-}
-
-static bNodeSocket *rna_NodeTree_input_new(bNodeTree *ntree, ReportList *UNUSED(reports), const char *name, int type)
-{
- /* XXX should check if tree is a group here! no good way to do this currently. */
- bNodeSocket *gsock = node_group_add_socket(ntree, name, type, SOCK_IN);
-
- ntree->update |= NTREE_UPDATE_GROUP_IN;
- ntreeUpdateTree(ntree);
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
- return gsock;
-}
-
-static bNodeSocket *rna_NodeTree_output_new(bNodeTree *ntree, ReportList *UNUSED(reports), const char *name, int type)
-{
- /* XXX should check if tree is a group here! no good way to do this currently. */
- bNodeSocket *gsock = node_group_add_socket(ntree, name, type, SOCK_OUT);
-
- ntree->update |= NTREE_UPDATE_GROUP_OUT;
- ntreeUpdateTree(ntree);
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
- return gsock;
-}
-
-static bNodeSocket *rna_NodeTree_input_expose(bNodeTree *ntree, ReportList *reports, bNodeSocket *sock, int add_link)
-{
- bNode *node;
- bNodeSocket *gsock;
- int index, in_out;
-
- if (!nodeFindNode(ntree, sock, &node, &index, &in_out))
- BKE_report(reports, RPT_ERROR, "Unable to locate socket in node tree");
- else if (in_out != SOCK_IN)
- BKE_report(reports, RPT_ERROR, "Socket is not an input");
- else {
- /* XXX should check if tree is a group here! no good way to do this currently. */
- gsock = node_group_add_socket(ntree, sock->name, sock->type, SOCK_IN);
- if (add_link)
- nodeAddLink(ntree, NULL, gsock, node, sock);
-
- ntree->update |= NTREE_UPDATE_GROUP_IN;
- ntreeUpdateTree(ntree);
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
- return gsock;
- }
- return NULL;
-}
+ bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNode *node = (bNode *)ptr->data;
-static bNodeSocket *rna_NodeTree_output_expose(bNodeTree *ntree, ReportList *reports, bNodeSocket *sock, int add_link)
-{
- bNode *node;
- bNodeSocket *gsock;
- int index, in_out;
-
- if (!nodeFindNode(ntree, sock, &node, &index, &in_out))
- BKE_report(reports, RPT_ERROR, "Unable to locate socket in node tree");
- else if (in_out != SOCK_OUT)
- BKE_report(reports, RPT_ERROR, "Socket is not an output");
- else {
- /* XXX should check if tree is a group here! no good way to do this currently. */
- gsock = node_group_add_socket(ntree, sock->name, sock->type, SOCK_OUT);
- if (add_link)
- nodeAddLink(ntree, node, sock, NULL, gsock);
-
- ntree->update |= NTREE_UPDATE_GROUP_OUT;
- ntreeUpdateTree(ntree);
- WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
- return gsock;
- }
- return NULL;
+ node->update |= NODE_UPDATE_ID;
+ nodeUpdate(ntree, node); /* to update image node sockets */
}
static void rna_Mapping_Node_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -958,6 +2641,8 @@ static PointerRNA rna_NodeOutputFile_slot_file_get(CollectionPropertyIterator *i
return ptr;
}
+/* ******** Node Socket Types ******** */
+
static PointerRNA rna_NodeOutputFile_slot_layer_get(CollectionPropertyIterator *iter)
{
PointerRNA ptr;
@@ -1011,53 +2696,6 @@ static void rna_NodeOutputFileSlotLayer_name_set(PointerRNA *ptr, const char *va
}
}
-static bNodeSocket *rna_ShaderNodeScript_find_socket(bNode *node, const char *name, int is_output)
-{
- bNodeSocket *sock;
-
- if (is_output) {
- for (sock = node->outputs.first; sock; sock = sock->next) {
- if (strcmp(sock->name, name) == 0) {
- return sock;
- }
- }
- }
- else {
- for (sock = node->inputs.first; sock; sock = sock->next) {
- if (strcmp(sock->name, name) == 0) {
- return sock;
- }
- }
- }
-
- return NULL;
-}
-
-static void rna_ShaderNodeScript_remove_socket(ID *id, bNode *node, bNodeSocket *sock)
-{
- bNodeTree *ntree = (bNodeTree *)id;
-
- nodeRemoveSocket(ntree, node, sock);
-
- ED_node_generic_update(G.main, ntree, node);
-}
-
-static bNodeSocket *rna_ShaderNodeScript_add_socket(ID *id, bNode *node, const char *name, int type, int is_output)
-{
- bNodeTree *ntree = (bNodeTree *)id;
- bNodeSocket *sock;
-
- /* replace existing socket with the same name, to keep it unique */
- sock = rna_ShaderNodeScript_find_socket(node, name, is_output);
- if (sock)
- nodeRemoveSocket(ntree, node, sock);
- sock = nodeAddSocket(ntree, node, (is_output ? SOCK_OUT : SOCK_IN), name, type);
-
- ED_node_generic_update(G.main, ntree, node);
-
- return sock;
-}
-
static void rna_ShaderNodeScript_mode_set(PointerRNA *ptr, int value)
{
bNode *node = (bNode *)ptr->data;
@@ -1070,7 +2708,7 @@ static void rna_ShaderNodeScript_mode_set(PointerRNA *ptr, int value)
/* replace text datablock by filepath */
if (node->id) {
- Text *text = (Text*)node->id;
+ Text *text = (Text *)node->id;
if (value == NODE_SCRIPT_EXTERNAL && text->name) {
BLI_strncpy(nss->filepath, text->name, sizeof(nss->filepath));
@@ -1121,19 +2759,6 @@ static void rna_ShaderNodeScript_bytecode_set(PointerRNA *ptr, const char *value
nss->bytecode = NULL;
}
-static IDProperty *rna_ShaderNodeScript_idprops(PointerRNA *ptr, int create)
-{
- bNode *node = (bNode *)ptr->data;
- NodeShaderScript *nss = node->storage;
-
- if (create && !nss->prop) {
- IDPropertyTemplate val = {0};
- nss->prop = IDP_New(IDP_GROUP, &val, "RNA_ShaderNodeScript ID properties");
- }
-
- return nss->prop;
-}
-
static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
@@ -1147,7 +2772,7 @@ static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *p
RE_engine_free(engine);
}
- node_update(bmain, scene, ntree, node);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
#else
@@ -1196,131 +2821,41 @@ static EnumPropertyItem node_script_mode_items[] = {
{0, NULL, 0, NULL, NULL}
};
-#define MaxNodes 50000
-
-enum
-{
- Category_GroupNode,
- Category_LayoutNode,
- Category_ShaderNode,
- Category_CompositorNode,
- Category_TextureNode,
-};
-
-typedef struct NodeInfo {
- int defined;
- int category;
- const char *enum_name;
- const char *struct_name;
- const char *base_name;
- int icon;
- const char *ui_name;
- const char *ui_desc;
-} NodeInfo;
-
-static NodeInfo nodes[MaxNodes];
-
-static void reg_node(int ID, int category, const char *enum_name, const char *struct_name,
- const char *base_name, const char *ui_name, const char *ui_desc)
-{
- NodeInfo *ni = nodes + ID;
-
- ni->defined = 1;
- ni->category = category;
- ni->enum_name = enum_name;
- ni->struct_name = struct_name;
- ni->base_name = base_name;
- ni->ui_name = ui_name;
- ni->ui_desc = ui_desc;
-}
-
-static void init(void)
-{
- memset(nodes, 0, sizeof nodes);
-
- #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
- reg_node(ID, Category_##Category, EnumName, STRINGIFY_ARG(Category##StructName), #Category, UIName, UIDesc);
-
- #include "rna_nodetree_types.h"
-
- reg_node(NODE_GROUP, Category_GroupNode, "GROUP", "NodeGroup", "SpecialNode", "Group", "");
- reg_node(NODE_FRAME, Category_LayoutNode, "FRAME", "NodeFrame", "SpecialNode", "Frame", "");
- reg_node(NODE_REROUTE, Category_LayoutNode, "REROUTE", "NodeReroute", "SpecialNode", "Reroute", "");
-}
+/* -- Common nodes ---------------------------------------------------------- */
-static StructRNA *def_node(BlenderRNA *brna, int node_id)
+static void def_group_input(StructRNA *srna)
{
- StructRNA *srna;
- NodeInfo *node = nodes + node_id;
-
- srna = RNA_def_struct(brna, node->struct_name, node->base_name);
- RNA_def_struct_ui_text(srna, node->ui_name, node->ui_desc);
- RNA_def_struct_sdna(srna, "bNode");
+ PropertyRNA *prop;
- return srna;
+ prop = RNA_def_property(srna, "interface", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, "rna_NodeGroupInputOutput_interface_typef", NULL);
+ RNA_def_property_struct_type(prop, "PropertyGroup");
+ RNA_def_property_flag(prop, PROP_IDPROPERTY);
+ RNA_def_property_ui_text(prop, "Interface", "Interface socket data");
}
-static void alloc_node_type_items(EnumPropertyItem *items, int category)
+static void def_group_output(StructRNA *srna)
{
- int i;
- int count = 4;
- EnumPropertyItem *item = items;
-
- for (i = 0; i < MaxNodes; i++)
- if (nodes[i].defined && nodes[i].category == category)
- count++;
-
- /*item = items = MEM_callocN(count * sizeof(EnumPropertyItem), "alloc_node_type_items");*/
-
- for (i = 0; i < MaxNodes; i++) {
- NodeInfo *node = nodes + i;
- if (node->defined && node->category == category) {
- item->value = i;
- item->identifier = node->enum_name;
- item->icon = node->icon;
- item->name = node->ui_name;
- item->description = node->ui_desc;
-
- item++;
- }
- }
-
- item->value = NODE_GROUP;
- item->identifier = "GROUP";
- item->icon = 0;
- item->name = "Group";
- item->description = "";
-
- item++;
-
- item->value = NODE_REROUTE;
- item->identifier = "REROUTE";
- item->icon = 0;
- item->name = "Reroute";
- item->description = "";
-
- item++;
-
- item->value = NODE_FRAME;
- item->identifier = "FRAME";
- item->icon = 0;
- item->name = "Frame";
- item->description = "";
-
- item++;
+ PropertyRNA *prop;
- /* NOTE!, increase 'count' when adding items here */
+ prop = RNA_def_property(srna, "interface", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, "rna_NodeGroupInputOutput_interface_typef", NULL);
+ RNA_def_property_struct_type(prop, "PropertyGroup");
+ RNA_def_property_flag(prop, PROP_IDPROPERTY);
+ RNA_def_property_ui_text(prop, "Interface", "Interface socket data");
- memset(item, 0, sizeof(EnumPropertyItem));
+ prop = RNA_def_property(srna, "is_active_output", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_DO_OUTPUT);
+ RNA_def_property_ui_text(prop, "Active Output", "True if this node is used as the active group output");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
-
-/* -- Common nodes ---------------------------------------------------------- */
-
static void def_group(StructRNA *srna)
{
PropertyRNA *prop;
+ RNA_def_struct_register_funcs(srna, "rna_NodeGroup_register", "rna_Node_unregister", NULL);
+
prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_struct_type(prop, "NodeTree");
@@ -1328,6 +2863,18 @@ static void def_group(StructRNA *srna)
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Node Tree", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeGroup_update");
+
+ prop = RNA_def_property(srna, "interface", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, "rna_NodeGroup_interface_typef", NULL);
+ RNA_def_property_struct_type(prop, "PropertyGroup");
+ RNA_def_property_flag(prop, PROP_IDPROPERTY);
+ RNA_def_property_ui_text(prop, "Interface", "Interface socket data");
+
+ /* registration */
+ prop = RNA_def_property(srna, "bl_group_tree_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->group_tree_idname");
+ RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
+ RNA_def_property_ui_text(prop, "Group Tree Type", "");
}
static void def_frame(StructRNA *srna)
@@ -1939,8 +3486,7 @@ static void def_sh_tangent(StructRNA *srna)
static void def_sh_script(StructRNA *srna)
{
- FunctionRNA *func;
- PropertyRNA *prop, *parm;
+ PropertyRNA *prop;
prop = RNA_def_property(srna, "script", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "id");
@@ -1950,7 +3496,6 @@ static void def_sh_script(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeScript_update");
RNA_def_struct_sdna_from(srna, "NodeShaderScript", "storage");
- RNA_def_struct_idprops_func(srna, "rna_ShaderNodeScript_idprops");
prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
RNA_def_property_ui_text(prop, "File Path", "Shader script path");
@@ -1981,7 +3526,8 @@ static void def_sh_script(StructRNA *srna)
RNA_def_struct_sdna_from(srna, "bNode", NULL);
/* API functions */
-
+
+#if 0 /* XXX TODO use general node api for this */
func = RNA_def_function(srna, "find_socket", "rna_ShaderNodeScript_find_socket");
RNA_def_function_ui_description(func, "Find a socket by name");
parm = RNA_def_string(func, "name", "", 0, "Socket name", "");
@@ -2006,6 +3552,7 @@ static void def_sh_script(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_SELF_ID);
parm = RNA_def_pointer(func, "sock", "NodeSocket", "Socket", "");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+#endif
}
/* -- Compositor Nodes ------------------------------------------------------ */
@@ -2331,8 +3878,13 @@ static void def_cmp_image(StructRNA *srna)
RNA_def_property_struct_type(prop, "Image");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Image", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Image_Node_update_id");
+
+ prop = RNA_def_property(srna, "use_straight_alpha_output", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "custom1", CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT);
+ RNA_def_property_ui_text(prop, "Straight Alpha Output", "Put Node output buffer to straight alpha instead of premultiplied");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
-
+
/* NB: image user properties used in the UI are redefined in def_node_image_user,
* to trigger correct updates of the node editor. RNA design problem that prevents
* updates from nested structs ...
@@ -2441,7 +3993,7 @@ static void def_cmp_dilate_erode(StructRNA *srna)
{
PropertyRNA *prop;
- static EnumPropertyItem type_items[] = {
+ static EnumPropertyItem mode_items[] = {
{CMP_NODE_DILATEERODE_STEP, "STEP", 0, "Step", ""},
{CMP_NODE_DILATEERODE_DISTANCE_THRESH, "THRESHOLD", 0, "Threshold", ""},
{CMP_NODE_DILATEERODE_DISTANCE, "DISTANCE", 0, "Distance", ""},
@@ -2449,15 +4001,16 @@ static void def_cmp_dilate_erode(StructRNA *srna)
{0, NULL, 0, NULL, NULL}
};
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "custom1");
- RNA_def_property_enum_items(prop, type_items);
- RNA_def_property_ui_text(prop, "Distance", "Distance to grow/shrink (number of iterations)");
+ RNA_def_property_enum_items(prop, mode_items);
+ RNA_def_property_ui_text(prop, "Mode", "Growing/shrinking mode");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "distance", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "custom2");
- RNA_def_property_range(prop, -100, 100);
+ RNA_def_property_range(prop, -5000, 5000);
+ RNA_def_property_ui_range(prop, -100, 100, 0, 0);
RNA_def_property_ui_text(prop, "Distance", "Distance to grow/shrink (number of iterations)");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
@@ -3178,8 +4731,8 @@ static void def_cmp_premul_key(StructRNA *srna)
PropertyRNA *prop;
static EnumPropertyItem type_items[] = {
- {0, "KEY_TO_PREMUL", 0, "Key to Premul", ""},
- {1, "PREMUL_TO_KEY", 0, "Premul to Key", ""},
+ {0, "STRAIGHT_TO_PREMUL", 0, "Straight to Premul", ""},
+ {1, "PREMUL_TO_STRAIGHT", 0, "Premul to Straight", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -3719,7 +5272,8 @@ static void def_cmp_bokehblur(StructRNA *srna)
/* duplicated in def_cmp_blur */
prop = RNA_def_property(srna, "use_variable_size", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "custom1", CMP_NODEFLAG_BLUR_VARIABLE_SIZE);
- RNA_def_property_ui_text(prop, "Variable Size", "Support variable blue per-pixel when using an image for size input");
+ RNA_def_property_ui_text(prop, "Variable Size",
+ "Support variable blur per-pixel when using an image for size input");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
#if 0
@@ -4002,6 +5556,21 @@ static void def_cmp_viewer(StructRNA *srna)
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Y", "");
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_negative_sdna(prop, NULL, "custom2", CMP_NODE_OUTPUT_IGNORE_ALPHA);
+ RNA_def_property_ui_text(prop, "Use Alpha", "Colors are treated alpha premultiplied, or colors output straight (alpha gets set to 1)");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
+static void def_cmp_composite(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "custom2", CMP_NODE_OUTPUT_IGNORE_ALPHA);
+ RNA_def_property_ui_text(prop, "Use Alpha", "Colors are treated alpha premultiplied, or colors output straight (alpha gets set to 1)");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_cmp_keyingscreen(StructRNA *srna)
@@ -4144,6 +5713,33 @@ static void def_cmp_trackpos(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_cmp_translate(StructRNA *srna)
+{
+ static EnumPropertyItem translate_items[] = {
+ {CMP_NODE_WRAP_NONE, "NONE", 0, "None", "No wrapping on X and Y"},
+ {CMP_NODE_WRAP_X, "XAXIS", 0, "X Axis", "Wrap all pixels on the X axis"},
+ {CMP_NODE_WRAP_Y, "YAXIS", 0, "Y Axis", "Wrap all pixels on the Y axis"},
+ {CMP_NODE_WRAP_XY, "BOTH", 0, "Both Axes", "Wrap all pixels on both axes"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "NodeTranslateData", "storage");
+
+ prop = RNA_def_property(srna, "use_relative", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "relative", 1);
+ RNA_def_property_ui_text(prop, "Relative", "Use relative (percent) values to define blur radius");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "wrap_axis", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "wrap_axis");
+ RNA_def_property_enum_items(prop, translate_items);
+ RNA_def_property_ui_text(prop, "Wrapping", "Wrap image on a specific axis");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
+
/* -- Texture Nodes --------------------------------------------------------- */
static void def_tex_output(StructRNA *srna)
@@ -4210,390 +5806,574 @@ static void def_tex_bricks(StructRNA *srna)
/* -------------------------------------------------------------------------- */
-static EnumPropertyItem shader_node_type_items[MaxNodes];
static void rna_def_shader_node(BlenderRNA *brna)
{
StructRNA *srna;
- PropertyRNA *prop;
- alloc_node_type_items(shader_node_type_items, Category_ShaderNode);
-
srna = RNA_def_struct(brna, "ShaderNode", "Node");
RNA_def_struct_ui_text(srna, "Shader Node", "Material shader node");
RNA_def_struct_sdna(srna, "bNode");
-
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_enum_items(prop, shader_node_type_items);
- RNA_def_property_ui_text(prop, "Type", "");
+ RNA_def_struct_register_funcs(srna, "rna_ShaderNode_register", "rna_Node_unregister", NULL);
}
-static EnumPropertyItem compositor_node_type_items[MaxNodes];
static void rna_def_compositor_node(BlenderRNA *brna)
{
StructRNA *srna;
- PropertyRNA *prop;
-
- alloc_node_type_items(compositor_node_type_items, Category_CompositorNode);
+ FunctionRNA *func;
srna = RNA_def_struct(brna, "CompositorNode", "Node");
RNA_def_struct_ui_text(srna, "Compositor Node", "");
RNA_def_struct_sdna(srna, "bNode");
-
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_enum_items(prop, compositor_node_type_items);
- RNA_def_property_ui_text(prop, "Type", "");
+ RNA_def_struct_register_funcs(srna, "rna_CompositorNode_register", "rna_Node_unregister", NULL);
+
+ /* compositor node need_exec flag */
+ func = RNA_def_function(srna, "tag_need_exec", "rna_CompositorNode_tag_need_exec");
+ RNA_def_function_ui_description(func, "Tag the node for compositor update");
}
-static EnumPropertyItem texture_node_type_items[MaxNodes];
static void rna_def_texture_node(BlenderRNA *brna)
{
StructRNA *srna;
- PropertyRNA *prop;
-
- alloc_node_type_items(texture_node_type_items, Category_TextureNode);
srna = RNA_def_struct(brna, "TextureNode", "Node");
RNA_def_struct_ui_text(srna, "Texture Node", "");
RNA_def_struct_sdna(srna, "bNode");
-
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_enum_items(prop, texture_node_type_items);
- RNA_def_property_ui_text(prop, "Type", "");
+ RNA_def_struct_register_funcs(srna, "rna_TextureNode_register", "rna_Node_unregister", NULL);
}
-static void rna_def_special_node(BlenderRNA *brna)
+/* -------------------------------------------------------------------------- */
+
+static void rna_def_node_socket(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ PropertyRNA *parm;
+ FunctionRNA *func;
+
+ static float default_draw_color[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+
+ srna = RNA_def_struct(brna, "NodeSocket", NULL);
+ RNA_def_struct_ui_text(srna, "Node Socket", "Input or output socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+ RNA_def_struct_refine_func(srna, "rna_NodeSocket_refine");
+ RNA_def_struct_ui_icon(srna, ICON_PLUG);
+ RNA_def_struct_path_func(srna, "rna_NodeSocket_path");
+ RNA_def_struct_register_funcs(srna, "rna_NodeSocket_register", "rna_NodeSocket_unregister", NULL);
+ RNA_def_struct_idprops_func(srna, "rna_NodeSocket_idprops");
- static EnumPropertyItem specific_node_type_items[] = {
- {NODE_GROUP, "GROUP", ICON_NODE, "Group", ""},
- {NODE_FRAME, "FRAME", ICON_NODE, "Frame", ""},
- {NODE_REROUTE, "REROUTE", ICON_NODE, "Reroute", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- srna = RNA_def_struct(brna, "SpecialNode", "Node");
- RNA_def_struct_ui_text(srna, "Special Node", "");
- RNA_def_struct_sdna(srna, "bNode");
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Name", "Socket name");
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ prop = RNA_def_property(srna, "identifier", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "identifier");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_enum_items(prop, specific_node_type_items);
- RNA_def_property_ui_text(prop, "Type", "");
-}
+ RNA_def_property_ui_text(prop, "Identifier", "Unique identifier for mapping sockets");
-/* -------------------------------------------------------------------------- */
+ prop = RNA_def_property(srna, "in_out", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "in_out");
+ RNA_def_property_enum_items(prop, node_socket_in_out_items);
+ RNA_def_property_enum_default(prop, SOCK_IN);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Input or Output", "Input or Output type");
-static void rna_def_nodetree_link_api(BlenderRNA *brna, PropertyRNA *cprop)
-{
- StructRNA *srna;
- PropertyRNA *parm;
- FunctionRNA *func;
+ prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_HIDDEN);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_NodeSocket_hide_set");
+ RNA_def_property_ui_text(prop, "Hide", "Hide the socket");
+ RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
- RNA_def_property_srna(cprop, "NodeLinks");
- srna = RNA_def_struct(brna, "NodeLinks", NULL);
- RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_text(srna, "Node Links", "Collection of Node Links");
+ prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SOCK_UNAVAIL);
+ RNA_def_property_ui_text(prop, "Enabled", "Enable the socket");
+ RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
- func = RNA_def_function(srna, "new", "rna_NodeTree_link_new");
- RNA_def_function_ui_description(func, "Add a node link to this node tree");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "input", "NodeSocket", "", "The input socket");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_pointer(func, "output", "NodeSocket", "", "The output socket");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- /* return */
- parm = RNA_def_pointer(func, "link", "NodeLink", "", "New node link");
- RNA_def_function_return(func, parm);
+ prop = RNA_def_property(srna, "is_linked", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_IN_USE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Linked", "True if the socket is connected");
- func = RNA_def_function(srna, "remove", "rna_NodeTree_link_remove");
- RNA_def_function_ui_description(func, "remove a node link from the node tree");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "link", "NodeLink", "", "The node link to remove");
- RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SOCK_COLLAPSED);
+ RNA_def_property_ui_text(prop, "Expanded", "Socket links are expanded in the user interface");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, NULL);
- func = RNA_def_function(srna, "clear", "rna_NodeTree_link_clear");
- RNA_def_function_ui_description(func, "remove all node links from the node tree");
-}
+ prop = RNA_def_property(srna, "node", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_funcs(prop, "rna_NodeSocket_node_get", NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "Node");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Node", "Node owning this socket");
-/* shared between all note tree types*/
-static void rna_def_nodetree_active_api(StructRNA *srna, PropertyRNA *UNUSED(cprop))
-{
- PropertyRNA *prop;
+ /* NB: the type property is used by standard sockets.
+ * Ideally should be defined only for the registered subclass,
+ * but to use the existing DNA is added in the base type here.
+ * Future socket types can ignore or override this if needed.
+ */
+ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, node_socket_type_items);
+ RNA_def_property_enum_default(prop, SOCK_FLOAT);
+ RNA_def_property_ui_text(prop, "Type", "Data type");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
+
+ /* registration */
+ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->idname");
+ RNA_def_property_string_funcs(prop, "rna_NodeSocket_bl_idname_get", "rna_NodeSocket_bl_idname_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
+ RNA_def_property_ui_text(prop, "ID Name", "");
+
+ /* draw socket */
+ func = RNA_def_function(srna, "draw", NULL);
+ RNA_def_function_ui_description(func, "Draw socket");
+ RNA_def_function_flag(func, FUNC_REGISTER);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "node", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "Node");
+ RNA_def_property_ui_text(parm, "Node", "Node the socket belongs to");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "Node");
- RNA_def_property_pointer_funcs(prop, "rna_NodeTree_active_node_get", "rna_NodeTree_active_node_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
- RNA_def_property_ui_text(prop, "Active Node", "Active node in this tree");
- RNA_def_property_update(prop, NC_SCENE | ND_OB_ACTIVE, NULL);
+ func = RNA_def_function(srna, "draw_color", NULL);
+ RNA_def_function_ui_description(func, "Color of the socket icon");
+ RNA_def_function_flag(func, FUNC_REGISTER);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "node", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "Node");
+ RNA_def_property_ui_text(parm, "Node", "Node the socket belongs to");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ parm = RNA_def_float_array(func, "color", 4, default_draw_color, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f);
+ RNA_def_function_output(func, parm);
}
-static void rna_def_composite_nodetree_api(BlenderRNA *brna, PropertyRNA *cprop)
+static void rna_def_node_socket_interface(BlenderRNA *brna)
{
StructRNA *srna;
+ PropertyRNA *prop;
PropertyRNA *parm;
FunctionRNA *func;
+
+ static float default_draw_color[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+
+ srna = RNA_def_struct(brna, "NodeSocketInterface", NULL);
+ RNA_def_struct_ui_text(srna, "Node Socket Template", "Parameters to define node sockets");
+ /* XXX Using bNodeSocket DNA for templates is a compatibility hack.
+ * This allows to keep the inputs/outputs lists in bNodeTree working for earlier versions
+ * and at the same time use them for socket templates in groups.
+ */
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+ RNA_def_struct_refine_func(srna, "rna_NodeSocketInterface_refine");
+ RNA_def_struct_path_func(srna, "rna_NodeSocketInterface_path");
+ RNA_def_struct_idprops_func(srna, "rna_NodeSocketInterface_idprops");
+ RNA_def_struct_register_funcs(srna, "rna_NodeSocketInterface_register", "rna_NodeSocketInterface_unregister", NULL);
- RNA_def_property_srna(cprop, "CompositorNodes");
- srna = RNA_def_struct(brna, "CompositorNodes", NULL);
- RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_text(srna, "Compositor Nodes", "Collection of Compositor Nodes");
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Name", "Socket name");
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update");
- func = RNA_def_function(srna, "new", "rna_NodeTree_node_composite_new");
- RNA_def_function_ui_description(func, "Add a node to this node tree");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
- parm = RNA_def_enum(func, "type", compositor_node_type_items, 0, "Type", "Type of node to add");
+ prop = RNA_def_property(srna, "identifier", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "identifier");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Identifier", "Unique identifier for mapping sockets");
+
+ prop = RNA_def_property(srna, "in_out", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "in_out");
+ RNA_def_property_enum_items(prop, node_socket_in_out_items);
+ RNA_def_property_enum_default(prop, SOCK_IN);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Input or Output", "Input or Output type");
+
+ /* registration */
+ prop = RNA_def_property(srna, "bl_socket_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->idname");
+ RNA_def_property_string_funcs(prop, "rna_NodeSocket_bl_idname_get", "rna_NodeSocket_bl_idname_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
+ RNA_def_property_ui_text(prop, "ID Name", "");
+
+ func = RNA_def_function(srna, "draw", NULL);
+ RNA_def_function_ui_description(func, "Draw template settings");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ func = RNA_def_function(srna, "draw_color", NULL);
+ RNA_def_function_ui_description(func, "Color of the socket icon");
+ RNA_def_function_flag(func, FUNC_REGISTER);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_float_array(func, "color", 4, default_draw_color, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f);
+ RNA_def_function_output(func, parm);
+
+ func = RNA_def_function(srna, "register_properties", NULL);
+ RNA_def_function_ui_description(func, "Define RNA properties of a socket");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "data_rna_type", "Struct", "Data RNA Type", "RNA type for special socket properties");
RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_pointer(func, "group", "NodeTree", "", "The group tree");
- /* return value */
- parm = RNA_def_pointer(func, "node", "Node", "", "New node");
- RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_NodeTree_node_remove");
- RNA_def_function_ui_description(func, "Remove a node from this node tree");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "node", "Node", "", "The node to remove");
+ func = RNA_def_function(srna, "init_socket", NULL);
+ RNA_def_function_ui_description(func, "Initialize a node socket instance");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "node", "Node", "Node", "Node of the socket to initialize");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ parm = RNA_def_pointer(func, "socket", "NodeSocket", "Socket", "Socket to initialize");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ parm = RNA_def_string(func, "data_path", "", 0, "Data Path", "Path to specialized socket data");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
- func = RNA_def_function(srna, "clear", "rna_NodeTree_node_clear");
- RNA_def_function_ui_description(func, "Remove all nodes from this node tree");
+ func = RNA_def_function(srna, "from_socket", NULL);
+ RNA_def_function_ui_description(func, "Setup template parameters from an existing socket");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "node", "Node", "Node", "Node of the original socket");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+ parm = RNA_def_pointer(func, "socket", "NodeSocket", "Socket", "Original socket");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+}
- rna_def_nodetree_active_api(srna, cprop);
+static void rna_def_node_socket_float(BlenderRNA *brna, const char *idname, const char *interface_idname, PropertySubType subtype)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, idname, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Float Node Socket", "Floating point number socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueFloat", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_FLOAT, subtype);
+ RNA_def_property_float_sdna(prop, NULL, "value");
+ RNA_def_property_float_funcs(prop, NULL, NULL, "rna_NodeSocketStandard_float_range");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Float Node Socket Interface", "Floating point number socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
}
-static void rna_def_shader_nodetree_api(BlenderRNA *brna, PropertyRNA *cprop)
+static void rna_def_node_socket_int(BlenderRNA *brna, const char *identifier, const char *interface_idname, PropertySubType subtype)
{
StructRNA *srna;
- PropertyRNA *parm;
- FunctionRNA *func;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Integer Node Socket", "Integer number socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueInt", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_INT, subtype);
+ RNA_def_property_int_sdna(prop, NULL, "value");
+ RNA_def_property_int_funcs(prop, NULL, NULL, "rna_NodeSocketStandard_int_range");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Integer Node Socket Interface", "Integer number socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
- RNA_def_property_srna(cprop, "ShaderNodes");
- srna = RNA_def_struct(brna, "ShaderNodes", NULL);
- RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_text(srna, "Shader Nodes", "Collection of Shader Nodes");
+static void rna_def_node_socket_bool(BlenderRNA *brna, const char *identifier, const char *interface_idname)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Boolean Node Socket", "Boolean value socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueBoolean", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "value", 1);
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Boolean Node Socket Interface", "Boolean value socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
- func = RNA_def_function(srna, "new", "rna_NodeTree_node_new");
- RNA_def_function_ui_description(func, "Add a node to this node tree");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
- parm = RNA_def_enum(func, "type", shader_node_type_items, 0, "Type", "Type of node to add");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_pointer(func, "group", "NodeTree", "", "The group tree");
- /* return value */
- parm = RNA_def_pointer(func, "node", "Node", "", "New node");
- RNA_def_function_return(func, parm);
+static void rna_def_node_socket_vector(BlenderRNA *brna, const char *identifier, const char *interface_idname, PropertySubType subtype)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Vector Node Socket", "3D vector socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueVector", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_FLOAT, subtype);
+ RNA_def_property_float_sdna(prop, NULL, "value");
+ RNA_def_property_float_funcs(prop, NULL, NULL, "rna_NodeSocketStandard_vector_range");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Vector Node Socket Interface", "3D vector socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
- func = RNA_def_function(srna, "remove", "rna_NodeTree_node_remove");
- RNA_def_function_ui_description(func, "Remove a node from this node tree");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "node", "Node", "", "The node 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_node_socket_color(BlenderRNA *brna, const char *identifier, const char *interface_idname)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Color Node Socket", "RGBA color socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueRGBA", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_float_sdna(prop, NULL, "value");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Color Node Socket Interface", "RGBA color socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
- func = RNA_def_function(srna, "clear", "rna_NodeTree_node_clear");
- RNA_def_function_ui_description(func, "Remove all nodes from this node tree");
+static void rna_def_node_socket_string(BlenderRNA *brna, const char *identifier, const char *interface_idname)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "String Node Socket", "String socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueString", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "value");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+
+ /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
+ RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "String Node Socket Interface", "String socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
+
+static void rna_def_node_socket_shader(BlenderRNA *brna, const char *identifier, const char *interface_idname)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Shader Node Socket", "Shader socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Shader Node Socket Interface", "Shader socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
- rna_def_nodetree_active_api(srna, cprop);
+static void rna_def_node_socket_virtual(BlenderRNA *brna, const char *identifier)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Virtual Node Socket", "Virtual socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
}
-static void rna_def_texture_nodetree_api(BlenderRNA *brna, PropertyRNA *cprop)
+static void rna_def_node_socket_standard_types(BlenderRNA *brna)
{
+ /* XXX Workaround: Registered functions are not exposed in python by bpy,
+ * it expects them to be registered from python and use the native implementation.
+ * However, the standard socket types below are not registering these functions from python,
+ * so in order to call them in py scripts we need to overload and replace them with plain C callbacks.
+ * These types provide a usable basis for socket types defined in C.
+ */
+
StructRNA *srna;
PropertyRNA *parm;
FunctionRNA *func;
+
+ static float default_draw_color[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+
+ srna = RNA_def_struct(brna, "NodeSocketStandard", "NodeSocket");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ /* draw socket */
+ func = RNA_def_function(srna, "draw", "rna_NodeSocketStandard_draw");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Draw socket");
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "node", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "Node");
+ RNA_def_property_ui_text(parm, "Node", "Node the socket belongs to");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- RNA_def_property_srna(cprop, "TextureNodes");
- srna = RNA_def_struct(brna, "TextureNodes", NULL);
- RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_text(srna, "Texture Nodes", "Collection of Texture Nodes");
-
- func = RNA_def_function(srna, "new", "rna_NodeTree_node_texture_new");
- RNA_def_function_ui_description(func, "Add a node to this node tree");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
- parm = RNA_def_enum(func, "type", texture_node_type_items, 0, "Type", "Type of node to add");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_pointer(func, "group", "NodeTree", "", "The group tree");
- /* return value */
- parm = RNA_def_pointer(func, "node", "Node", "", "New node");
- RNA_def_function_return(func, parm);
-
- func = RNA_def_function(srna, "remove", "rna_NodeTree_node_remove");
- RNA_def_function_ui_description(func, "Remove a node from this node tree");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "node", "Node", "", "The node to remove");
+ func = RNA_def_function(srna, "draw_color", "rna_NodeSocketStandard_draw_color");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Color of the socket icon");
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "node", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "Node");
+ RNA_def_property_ui_text(parm, "Node", "Node the socket belongs to");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+ parm = RNA_def_float_array(func, "color", 4, default_draw_color, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f);
+ RNA_def_function_output(func, parm);
+
+
+ srna = RNA_def_struct(brna, "NodeSocketInterfaceStandard", "NodeSocketInterface");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ func = RNA_def_function(srna, "draw", "rna_NodeSocketInterfaceStandard_draw");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Draw template settings");
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
- func = RNA_def_function(srna, "clear", "rna_NodeTree_node_clear");
- RNA_def_function_ui_description(func, "Remove all nodes from this node tree");
+ func = RNA_def_function(srna, "draw_color", "rna_NodeSocketInterfaceStandard_draw_color");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Color of the socket icon");
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_float_array(func, "color", 4, default_draw_color, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f);
+ RNA_def_function_output(func, parm);
- rna_def_nodetree_active_api(srna, cprop);
-}
-static void rna_def_node_socket(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
+ /* XXX These types should eventually be registered at runtime.
+ * Then use the nodeStaticSocketType and nodeStaticSocketInterfaceType functions
+ * to get the idname strings from int type and subtype (see node_socket.c, register_standard_node_socket_types).
+ */
+
+ rna_def_node_socket_float(brna, "NodeSocketFloat", "NodeSocketInterfaceFloat", PROP_NONE);
+ rna_def_node_socket_float(brna, "NodeSocketFloatUnsigned", "NodeSocketInterfaceFloatUnsigned", PROP_UNSIGNED);
+ rna_def_node_socket_float(brna, "NodeSocketFloatPercentage", "NodeSocketInterfaceFloatPercentage", PROP_PERCENTAGE);
+ rna_def_node_socket_float(brna, "NodeSocketFloatFactor", "NodeSocketInterfaceFloatFactor", PROP_FACTOR);
+ rna_def_node_socket_float(brna, "NodeSocketFloatAngle", "NodeSocketInterfaceFloatAngle", PROP_ANGLE);
+ rna_def_node_socket_float(brna, "NodeSocketFloatTime", "NodeSocketInterfaceFloatTime", PROP_TIME);
- srna = RNA_def_struct(brna, "NodeSocket", NULL);
- RNA_def_struct_ui_text(srna, "Node Socket", "Input or output socket of a node");
- RNA_def_struct_sdna(srna, "bNodeSocket");
- RNA_def_struct_refine_func(srna, "rna_NodeSocket_refine");
- RNA_def_struct_ui_icon(srna, ICON_PLUG);
- RNA_def_struct_path_func(srna, "rna_NodeSocket_path");
+ rna_def_node_socket_int(brna, "NodeSocketInt", "NodeSocketInterfaceInt", PROP_NONE);
+ rna_def_node_socket_int(brna, "NodeSocketIntUnsigned", "NodeSocketInterfaceIntUnsigned", PROP_UNSIGNED);
+ rna_def_node_socket_int(brna, "NodeSocketIntPercentage", "NodeSocketInterfaceIntPercentage", PROP_PERCENTAGE);
+ rna_def_node_socket_int(brna, "NodeSocketIntFactor", "NodeSocketInterfaceIntFactor", PROP_FACTOR);
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "type");
- RNA_def_property_enum_items(prop, node_socket_type_items);
- RNA_def_property_enum_default(prop, 0);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Type", "Node Socket type");
+ rna_def_node_socket_bool(brna, "NodeSocketBool", "NodeSocketInterfaceBool");
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- /* XXX must be editable for group sockets. if necessary use a special rna definition for these */
-/* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
- RNA_def_property_ui_text(prop, "Name", "Socket name");
- RNA_def_struct_name_property(srna, prop);
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeGroupSocket_update");
+ rna_def_node_socket_vector(brna, "NodeSocketVector", "NodeSocketInterfaceVector", PROP_NONE);
+ rna_def_node_socket_vector(brna, "NodeSocketVectorTranslation", "NodeSocketInterfaceVectorTranslation", PROP_TRANSLATION);
+ rna_def_node_socket_vector(brna, "NodeSocketVectorDirection", "NodeSocketInterfaceVectorDirection", PROP_DIRECTION);
+ rna_def_node_socket_vector(brna, "NodeSocketVectorVelocity", "NodeSocketInterfaceVectorVelocity", PROP_VELOCITY);
+ rna_def_node_socket_vector(brna, "NodeSocketVectorAcceleration", "NodeSocketInterfaceVectorAcceleration", PROP_ACCELERATION);
+ rna_def_node_socket_vector(brna, "NodeSocketVectorEuler", "NodeSocketInterfaceVectorEuler", PROP_EULER);
+ rna_def_node_socket_vector(brna, "NodeSocketVectorXYZ", "NodeSocketInterfaceVectorXYZ", PROP_XYZ);
- prop = RNA_def_property(srna, "group_socket", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "groupsock");
- RNA_def_property_struct_type(prop, "NodeSocket");
- RNA_def_property_ui_text(prop, "Group Socket",
- "For group nodes, the group input or output socket this corresponds to");
+ rna_def_node_socket_color(brna, "NodeSocketColor", "NodeSocketInterfaceColor");
- prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_HIDDEN);
- RNA_def_property_boolean_funcs(prop, NULL, "rna_NodeSocket_hide_set");
- RNA_def_property_ui_text(prop, "Hide", "Hide the socket");
- RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
+ rna_def_node_socket_string(brna, "NodeSocketString", "NodeSocketInterfaceString");
- prop = RNA_def_property(srna, "is_linked", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_IN_USE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Linked", "True if the socket is connected");
+ rna_def_node_socket_shader(brna, "NodeSocketShader", "NodeSocketInterfaceShader");
- prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SOCK_COLLAPSED);
- RNA_def_property_ui_text(prop, "Expanded", "Socket links are expanded in the user interface");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, NULL);
+ rna_def_node_socket_virtual(brna, "NodeSocketVirtual");
}
-static void rna_def_node_socket_subtype(BlenderRNA *brna, int type, int subtype, const char *name, const char *ui_name)
+static void rna_def_node_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, int in_out)
{
StructRNA *srna;
- PropertyRNA *prop = NULL;
- PropertySubType propsubtype = PROP_NONE;
-
- #define SUBTYPE(socktype, stypename, id, idname) { PROP_##id, #socktype "_" #id, 0, #idname, ""},
- static EnumPropertyItem subtype_items[] = {
- NODE_DEFINE_SUBTYPES
- {0, NULL, 0, NULL, NULL}
- };
- #undef SUBTYPE
+ PropertyRNA *parm;
+ FunctionRNA *func;
+ const char *structtype = (in_out == SOCK_IN ? "NodeInputs" : "NodeOutputs");
+ const char *uiname = (in_out == SOCK_IN ? "Node Inputs" : "Node Outputs");
+ const char *newfunc = (in_out == SOCK_IN ? "rna_Node_inputs_new" : "rna_Node_outputs_new");
+ const char *clearfunc = (in_out == SOCK_IN ? "rna_Node_inputs_clear" : "rna_Node_outputs_clear");
- #define SUBTYPE(socktype, stypename, id, idname) if (subtype == (PROP_##id)) propsubtype = PROP_##id;
- NODE_DEFINE_SUBTYPES
- #undef SUBTYPE
-
- srna = RNA_def_struct(brna, name, "NodeSocket");
- RNA_def_struct_ui_text(srna, ui_name, "Input or output socket of a node");
- RNA_def_struct_sdna(srna, "bNodeSocket");
- RNA_def_struct_ui_icon(srna, ICON_PLUG);
- RNA_def_struct_path_func(srna, "rna_NodeSocket_path");
-
- switch (type) {
- case SOCK_INT:
- RNA_def_struct_sdna_from(srna, "bNodeSocketValueInt", "default_value");
-
- prop = RNA_def_property(srna, "subtype", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "subtype");
- RNA_def_property_enum_items(prop, subtype_items);
- RNA_def_property_ui_text(prop, "Subtype", "Subtype defining the socket value details");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
-
- prop = RNA_def_property(srna, "default_value", PROP_INT, propsubtype);
- RNA_def_property_int_sdna(prop, NULL, "value");
- RNA_def_property_int_funcs(prop, NULL, NULL, "rna_NodeSocketInt_range");
- RNA_def_property_ui_text(prop, "Default Value", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- break;
- case SOCK_FLOAT:
- RNA_def_struct_sdna_from(srna, "bNodeSocketValueFloat", "default_value");
-
- prop = RNA_def_property(srna, "subtype", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "subtype");
- RNA_def_property_enum_items(prop, subtype_items);
- RNA_def_property_ui_text(prop, "Subtype", "Subtype defining the socket value details");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
-
- prop = RNA_def_property(srna, "default_value", PROP_FLOAT, propsubtype);
- RNA_def_property_float_sdna(prop, NULL, "value");
- RNA_def_property_float_funcs(prop, NULL, NULL, "rna_NodeSocketFloat_range");
- RNA_def_property_ui_text(prop, "Default Value", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- break;
- case SOCK_BOOLEAN:
- RNA_def_struct_sdna_from(srna, "bNodeSocketValueBoolean", "default_value");
-
- prop = RNA_def_property(srna, "default_value", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "value", 1);
- RNA_def_property_ui_text(prop, "Default Value", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- break;
- case SOCK_VECTOR:
- RNA_def_struct_sdna_from(srna, "bNodeSocketValueVector", "default_value");
-
- prop = RNA_def_property(srna, "subtype", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "subtype");
- RNA_def_property_enum_items(prop, subtype_items);
- RNA_def_property_ui_text(prop, "Subtype", "Subtype defining the socket value details");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
-
- prop = RNA_def_property(srna, "default_value", PROP_FLOAT, propsubtype);
- RNA_def_property_float_sdna(prop, NULL, "value");
- RNA_def_property_float_funcs(prop, NULL, NULL, "rna_NodeSocketVector_range");
- RNA_def_property_ui_text(prop, "Default Value", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- break;
- case SOCK_RGBA:
- RNA_def_struct_sdna_from(srna, "bNodeSocketValueRGBA", "default_value");
+ RNA_def_property_srna(cprop, structtype);
+ srna = RNA_def_struct(brna, structtype, NULL);
+ RNA_def_struct_sdna(srna, "bNode");
+ RNA_def_struct_ui_text(srna, uiname, "Collection of Node Sockets");
- prop = RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_COLOR);
- RNA_def_property_float_sdna(prop, NULL, "value");
- RNA_def_property_ui_text(prop, "Default Value", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- break;
- case SOCK_STRING:
- RNA_def_struct_sdna_from(srna, "bNodeSocketValueString", "default_value");
-
- prop = RNA_def_property(srna, "subtype", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "subtype");
- RNA_def_property_enum_items(prop, subtype_items);
- RNA_def_property_ui_text(prop, "Subtype", "Subtype defining the socket value details");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
-
- prop = RNA_def_property(srna, "default_value", PROP_STRING, PROP_FILEPATH);
- RNA_def_property_string_sdna(prop, NULL, "value");
- RNA_def_property_ui_text(prop, "Default Value", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- break;
- }
-
- /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */
- RNA_def_struct_sdna_from(srna, "bNodeSocket", NULL);
+ func = RNA_def_function(srna, "new", newfunc);
+ RNA_def_function_ui_description(func, "Add a socket to this node");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS);
+ parm = RNA_def_string(func, "type", "", MAX_NAME, "Type", "Data type");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_string(func, "name", "", MAX_NAME, "Name", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_string(func, "identifier", "", MAX_NAME, "Identifier", "Unique socket identifier");
+ /* return value */
+ parm = RNA_def_pointer(func, "socket", "NodeSocket", "", "New socket");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_Node_socket_remove");
+ RNA_def_function_ui_description(func, "Remove a socket from this node");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "socket", "NodeSocket", "", "The socket to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ func = RNA_def_function(srna, "clear", clearfunc);
+ RNA_def_function_ui_description(func, "Remove all sockets from this node");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS);
}
static void rna_def_node(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ static EnumPropertyItem dummy_static_type_items[] = {
+ {NODE_CUSTOM, "CUSTOM", 0, "Custom", "Custom Node"},
+ {0, NULL, 0, NULL, NULL}};
srna = RNA_def_struct(brna, "Node", NULL);
RNA_def_struct_ui_text(srna, "Node", "Node in a node tree");
@@ -4601,14 +6381,42 @@ static void rna_def_node(BlenderRNA *brna)
RNA_def_struct_ui_icon(srna, ICON_NODE);
RNA_def_struct_refine_func(srna, "rna_Node_refine");
RNA_def_struct_path_func(srna, "rna_Node_path");
+ RNA_def_struct_register_funcs(srna, "rna_Node_register", "rna_Node_unregister", NULL);
+ RNA_def_struct_idprops_func(srna, "rna_Node_idprops");
+
+ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, dummy_static_type_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_node_static_type_itemf");
+ RNA_def_property_enum_default(prop, NODE_CUSTOM);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Type", "Node type (deprecated, use bl_static_type or bl_idname for the actual identifier string)");
prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "locx");
RNA_def_property_array(prop, 2);
- RNA_def_property_range(prop, -10000.0f, 10000.0f);
+ RNA_def_property_range(prop, -100000.0f, 100000.0f);
RNA_def_property_ui_text(prop, "Location", "");
RNA_def_property_update(prop, NC_NODE, "rna_Node_update");
+ prop = RNA_def_property(srna, "width", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_float_sdna(prop, NULL, "width");
+ RNA_def_property_float_funcs(prop, NULL, NULL, "rna_Node_width_range");
+ RNA_def_property_ui_text(prop, "Width", "Width of the node");
+ RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
+
+ prop = RNA_def_property(srna, "width_hidden", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_float_sdna(prop, NULL, "miniwidth");
+ RNA_def_property_float_funcs(prop, NULL, NULL, "rna_Node_width_range");
+ RNA_def_property_ui_text(prop, "Width Hidden", "Width of the node in hidden state");
+ RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
+
+ prop = RNA_def_property(srna, "height", PROP_FLOAT, PROP_XYZ);
+ RNA_def_property_float_sdna(prop, NULL, "height");
+ RNA_def_property_float_funcs(prop, NULL, NULL, "rna_Node_height_range");
+ RNA_def_property_ui_text(prop, "Height", "Height of the node");
+ RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
+
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Name", "Unique node identifier");
RNA_def_struct_name_property(srna, prop);
@@ -4622,18 +6430,30 @@ static void rna_def_node(BlenderRNA *brna)
prop = RNA_def_property(srna, "inputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "inputs", NULL);
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL,
+ "rna_Node_inputs_lookupstring", NULL);
RNA_def_property_struct_type(prop, "NodeSocket");
RNA_def_property_ui_text(prop, "Inputs", "");
+ rna_def_node_sockets_api(brna, prop, SOCK_IN);
prop = RNA_def_property(srna, "outputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "outputs", NULL);
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL,
+ "rna_Node_outputs_lookupstring", NULL);
RNA_def_property_struct_type(prop, "NodeSocket");
RNA_def_property_ui_text(prop, "Outputs", "");
+ rna_def_node_sockets_api(brna, prop, SOCK_OUT);
+
+ prop = RNA_def_property(srna, "internal_links", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "internal_links", NULL);
+ RNA_def_property_struct_type(prop, "NodeLink");
+ RNA_def_property_ui_text(prop, "Internal Links", "Internal input-to-output connections for muting");
prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "parent");
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_Node_parent_set", NULL, "rna_Node_parent_poll");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "Node");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Parent", "Parent this node is attached to");
prop = RNA_def_property(srna, "use_custom_color", PROP_BOOLEAN, PROP_NONE);
@@ -4649,8 +6469,9 @@ static void rna_def_node(BlenderRNA *brna)
RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL);
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_SELECT);
- RNA_def_property_ui_text(prop, "Select", "");
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_Node_select_set");
+ RNA_def_property_ui_text(prop, "Select", "Node selection state");
RNA_def_property_update(prop, NC_NODE | NA_SELECTED, NULL);
prop = RNA_def_property(srna, "show_options", PROP_BOOLEAN, PROP_NONE);
@@ -4677,6 +6498,115 @@ static void rna_def_node(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_ACTIVE_TEXTURE);
RNA_def_property_ui_text(prop, "Show Texture", "Draw node in viewport textured draw mode");
RNA_def_property_update(prop, 0, "rna_Node_update");
+
+ /* generic property update function */
+ func = RNA_def_function(srna, "socket_value_update", "rna_Node_socket_value_update");
+ RNA_def_function_ui_description(func, "Update after property changes");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ func = RNA_def_function(srna, "is_registered_node_type", "rna_Node_is_registered_node_type");
+ RNA_def_function_ui_description(func, "True if a registered node type");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_SELF_TYPE);
+ parm = RNA_def_boolean(func, "result", FALSE, "Result", "");
+ RNA_def_function_return(func, parm);
+
+ /* registration */
+ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->idname");
+ RNA_def_property_string_funcs(prop, "rna_Node_bl_idname_get", "rna_Node_bl_idname_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
+ RNA_def_property_ui_text(prop, "ID Name", "");
+
+ prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->ui_name");
+ RNA_def_property_string_funcs(prop, "rna_Node_bl_label_get", "rna_Node_bl_label_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER);
+ RNA_def_property_ui_text(prop, "Label", "The node label");
+
+ prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_TRANSLATION);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->ui_description");
+ RNA_def_property_string_funcs(prop, "rna_Node_bl_description_get", "rna_Node_bl_description_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
+ prop = RNA_def_property(srna, "bl_icon", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "typeinfo->ui_icon");
+ RNA_def_property_enum_funcs(prop, "rna_Node_bl_icon_get", NULL, NULL);
+ RNA_def_property_enum_items(prop, node_icon_items);
+ RNA_def_property_enum_default(prop, ICON_NODE);
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+ RNA_def_property_ui_text(prop, "Icon", "The node icon");
+
+ prop = RNA_def_property(srna, "bl_static_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "typeinfo->type");
+ RNA_def_property_enum_funcs(prop, "rna_Node_bl_static_type_get", NULL, NULL);
+ RNA_def_property_enum_items(prop, dummy_static_type_items);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_node_static_type_itemf");
+ RNA_def_property_enum_default(prop, NODE_CUSTOM);
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+ RNA_def_property_ui_text(prop, "Static Type", "Node type (deprecated, use with care)");
+
+ /* poll */
+ func = RNA_def_function(srna, "poll", NULL);
+ RNA_def_function_ui_description(func, "If non-null output is returned, the node type can be added to the tree");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER);
+ RNA_def_function_return(func, RNA_def_boolean(func, "visible", FALSE, "", ""));
+ parm = RNA_def_pointer(func, "node_tree", "NodeTree", "Node Tree", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ func = RNA_def_function(srna, "poll_instance", NULL);
+ RNA_def_function_ui_description(func, "If non-null output is returned, the node can be added to the tree");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ RNA_def_function_return(func, RNA_def_boolean(func, "visible", FALSE, "", ""));
+ parm = RNA_def_pointer(func, "node_tree", "NodeTree", "Node Tree", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ /* update */
+ func = RNA_def_function(srna, "update", NULL);
+ RNA_def_function_ui_description(func, "Update on editor changes");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+
+ /* init */
+ func = RNA_def_function(srna, "init", NULL);
+ RNA_def_function_ui_description(func, "Initialize a new instance of this node");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ /* copy */
+ func = RNA_def_function(srna, "copy", NULL);
+ RNA_def_function_ui_description(func, "Initialize a new instance of this node from an existing node");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+ parm = RNA_def_pointer(func, "node", "Node", "Node", "Existing node to copy");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ /* free */
+ func = RNA_def_function(srna, "free", NULL);
+ RNA_def_function_ui_description(func, "Clean up node on removal");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+
+ /* draw buttons */
+ func = RNA_def_function(srna, "draw_buttons", NULL);
+ RNA_def_function_ui_description(func, "Draw node buttons");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ /* draw buttons extended */
+ func = RNA_def_function(srna, "draw_buttons_ext", NULL);
+ RNA_def_function_ui_description(func, "Draw node buttons in the sidebar");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
}
static void rna_def_node_link(BlenderRNA *brna)
@@ -4689,63 +6619,165 @@ static void rna_def_node_link(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "bNodeLink");
RNA_def_struct_ui_icon(srna, ICON_NODE);
+ prop = RNA_def_property(srna, "is_valid", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_LINK_VALID);
+ RNA_def_struct_ui_text(srna, "Valid", "Link is valid");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, NULL);
+
prop = RNA_def_property(srna, "from_node", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "fromnode");
RNA_def_property_struct_type(prop, "Node");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "From node", "");
prop = RNA_def_property(srna, "to_node", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tonode");
RNA_def_property_struct_type(prop, "Node");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "To node", "");
prop = RNA_def_property(srna, "from_socket", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "fromsock");
RNA_def_property_struct_type(prop, "NodeSocket");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "From socket", "");
prop = RNA_def_property(srna, "to_socket", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tosock");
RNA_def_property_struct_type(prop, "NodeSocket");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "To socket", "");
+
+ prop = RNA_def_property(srna, "is_hidden", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_NodeLink_is_hidden_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Is Hidden", "Link is hidden due to invisible sockets");
+}
+
+static void rna_def_nodetree_nodes_api(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ PropertyRNA *parm, *prop;
+ FunctionRNA *func;
+
+ RNA_def_property_srna(cprop, "Nodes");
+ srna = RNA_def_struct(brna, "Nodes", NULL);
+ RNA_def_struct_sdna(srna, "bNodeTree");
+ RNA_def_struct_ui_text(srna, "Nodes", "Collection of Nodes");
+
+ func = RNA_def_function(srna, "new", "rna_NodeTree_node_new");
+ RNA_def_function_ui_description(func, "Add a node to this node tree");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ parm = RNA_def_string(func, "type", "", MAX_NAME, "Type", "Type of node to add");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ /* return value */
+ parm = RNA_def_pointer(func, "node", "Node", "", "New node");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_NodeTree_node_remove");
+ RNA_def_function_ui_description(func, "Remove a node from this node tree");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "node", "Node", "", "The node 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_NodeTree_node_clear");
+ RNA_def_function_ui_description(func, "Remove all nodes from this node tree");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+
+ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Node");
+ RNA_def_property_pointer_funcs(prop, "rna_NodeTree_active_node_get", "rna_NodeTree_active_node_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
+ RNA_def_property_ui_text(prop, "Active Node", "Active node in this tree");
+ RNA_def_property_update(prop, NC_SCENE | ND_OB_ACTIVE, NULL);
}
-static void rna_def_group_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, int in_out)
+static void rna_def_nodetree_link_api(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
PropertyRNA *parm;
FunctionRNA *func;
- RNA_def_property_srna(cprop, (in_out == SOCK_IN ? "GroupInputs" : "GroupOutputs"));
- srna = RNA_def_struct(brna, (in_out == SOCK_IN ? "GroupInputs" : "GroupOutputs"), NULL);
+ RNA_def_property_srna(cprop, "NodeLinks");
+ srna = RNA_def_struct(brna, "NodeLinks", NULL);
RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_text(srna, "Group Sockets", "Collection of group sockets");
+ RNA_def_struct_ui_text(srna, "Node Links", "Collection of Node Links");
- func = RNA_def_function(srna, "new", (in_out == SOCK_IN ? "rna_NodeTree_input_new" : "rna_NodeTree_output_new"));
- RNA_def_function_ui_description(func, "Add a socket to the group tree");
+ func = RNA_def_function(srna, "new", "rna_NodeTree_link_new");
+ RNA_def_function_ui_description(func, "Add a node link to this node tree");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
- RNA_def_string(func, "name", "Socket", MAX_NAME, "Name", "Name of the socket");
- RNA_def_enum(func, "type", node_socket_type_items, SOCK_FLOAT, "Type", "Type of socket");
- /* return value */
- parm = RNA_def_pointer(func, "socket", "NodeSocket", "", "New socket");
+ parm = RNA_def_pointer(func, "input", "NodeSocket", "", "The input socket");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_pointer(func, "output", "NodeSocket", "", "The output socket");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_boolean(func, "verify_limits", TRUE, "Verify Limits", "Remove existing links if connection limit is exceeded");
+ /* return */
+ parm = RNA_def_pointer(func, "link", "NodeLink", "", "New node link");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "expose",
- (in_out == SOCK_IN ? "rna_NodeTree_input_expose" : "rna_NodeTree_output_expose"));
- RNA_def_function_ui_description(func, "Expose an internal socket in the group tree");
+ func = RNA_def_function(srna, "remove", "rna_NodeTree_link_remove");
+ RNA_def_function_ui_description(func, "remove a node link from the node tree");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "link", "NodeLink", "", "The node link 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_NodeTree_link_clear");
+ RNA_def_function_ui_description(func, "remove all node links from the node tree");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
- RNA_def_pointer(func, "sock", "NodeSocket", "Socket", "Internal node socket to expose");
+}
+
+static void rna_def_node_tree_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, int in_out)
+{
+ StructRNA *srna;
+ PropertyRNA *parm;
+ FunctionRNA *func;
+ const char *structtype = (in_out == SOCK_IN ? "NodeTreeInputs" : "NodeTreeOutputs");
+ const char *uiname = (in_out == SOCK_IN ? "Node Tree Inputs" : "Node Tree Outputs");
+ const char *newfunc = (in_out == SOCK_IN ? "rna_NodeTree_inputs_new" : "rna_NodeTree_outputs_new");
+ const char *clearfunc = (in_out == SOCK_IN ? "rna_NodeTree_inputs_clear" : "rna_NodeTree_outputs_clear");
+
+ RNA_def_property_srna(cprop, structtype);
+ srna = RNA_def_struct(brna, structtype, NULL);
+ RNA_def_struct_sdna(srna, "bNodeTree");
+ RNA_def_struct_ui_text(srna, uiname, "Collection of Node Tree Sockets");
+
+ func = RNA_def_function(srna, "new", newfunc);
+ RNA_def_function_ui_description(func, "Add a socket to this node tree");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_string(func, "type", "", MAX_NAME, "Type", "Data type");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_string(func, "name", "", MAX_NAME, "Name", "");
RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_boolean(func, "add_link", TRUE, "Add Link", "If TRUE, adds a link to the internal socket");
/* return value */
- parm = RNA_def_pointer(func, "socket", "NodeSocket", "", "New socket");
+ parm = RNA_def_pointer(func, "socket", "NodeSocketInterface", "", "New socket");
RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_NodeTree_socket_remove");
+ RNA_def_function_ui_description(func, "Remove a socket from this node tree");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "socket", "NodeSocketInterface", "", "The socket to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ func = RNA_def_function(srna, "clear", clearfunc);
+ RNA_def_function_ui_description(func, "Remove all sockets from this node tree");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
}
static void rna_def_nodetree(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ static EnumPropertyItem static_type_items[] = {
+ {NTREE_SHADER, "SHADER", ICON_MATERIAL, "Shader", "Shader nodes"},
+ {NTREE_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture nodes"},
+ {NTREE_COMPOSIT, "COMPOSITING", ICON_RENDERLAYERS, "Compositing", "Compositing nodes"},
+ {0, NULL, 0, NULL, NULL}
+ };
srna = RNA_def_struct(brna, "NodeTree", "ID");
RNA_def_struct_ui_text(srna, "Node Tree",
@@ -4753,10 +6785,18 @@ static void rna_def_nodetree(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "bNodeTree");
RNA_def_struct_ui_icon(srna, ICON_NODETREE);
RNA_def_struct_refine_func(srna, "rna_NodeTree_refine");
+ RNA_def_struct_register_funcs(srna, "rna_NodeTree_register", "rna_NodeTree_unregister", NULL);
/* AnimData */
rna_def_animdata_common(srna);
-
+
+ /* Nodes Collection */
+ prop = RNA_def_property(srna, "nodes", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "nodes", NULL);
+ RNA_def_property_struct_type(prop, "Node");
+ RNA_def_property_ui_text(prop, "Nodes", "");
+ rna_def_nodetree_nodes_api(brna, prop);
+
/* NodeLinks Collection */
prop = RNA_def_property(srna, "links", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "links", NULL);
@@ -4774,21 +6814,100 @@ static void rna_def_nodetree(BlenderRNA *brna)
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_enum_items(prop, nodetree_type_items);
- RNA_def_property_ui_text(prop, "Type", "Node Tree type");
+ RNA_def_property_enum_items(prop, static_type_items);
+ RNA_def_property_ui_text(prop, "Type", "Node Tree type (deprecated, bl_idname is the actual node tree type identifier)");
- /* group sockets */
prop = RNA_def_property(srna, "inputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "inputs", NULL);
- RNA_def_property_struct_type(prop, "NodeSocket");
- RNA_def_property_ui_text(prop, "Inputs", "");
- rna_def_group_sockets_api(brna, prop, SOCK_IN);
-
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL,
+ "rna_NodeTree_inputs_lookupstring", NULL);
+ RNA_def_property_struct_type(prop, "NodeSocketInterface");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Inputs", "Node tree inputs");
+ rna_def_node_tree_sockets_api(brna, prop, SOCK_IN);
+
+ prop = RNA_def_property(srna, "active_input", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_funcs(prop, "rna_NodeTree_active_input_get", "rna_NodeTree_active_input_set", NULL);
+ RNA_def_property_ui_text(prop, "Active Input", "Index of the active input");
+ RNA_def_property_update(prop, NC_NODE, NULL);
+
prop = RNA_def_property(srna, "outputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "outputs", NULL);
- RNA_def_property_struct_type(prop, "NodeSocket");
- RNA_def_property_ui_text(prop, "Outputs", "");
- rna_def_group_sockets_api(brna, prop, SOCK_OUT);
+ RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL,
+ "rna_NodeTree_outputs_lookupstring", NULL);
+ RNA_def_property_struct_type(prop, "NodeSocketInterface");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Outputs", "Node tree outputs");
+ rna_def_node_tree_sockets_api(brna, prop, SOCK_OUT);
+
+ prop = RNA_def_property(srna, "active_output", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_funcs(prop, "rna_NodeTree_active_output_get", "rna_NodeTree_active_output_set", NULL);
+ RNA_def_property_ui_text(prop, "Active Output", "Index of the active output");
+ RNA_def_property_update(prop, NC_NODE, NULL);
+
+ /* exposed as a function for runtime interface type properties */
+ func = RNA_def_function(srna, "interface_update", "rna_NodeTree_interface_update");
+ RNA_def_function_ui_description(func, "Updated node group interface");
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ /* registration */
+ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->idname");
+ RNA_def_property_string_funcs(prop, "rna_NodeTree_bl_idname_get", "rna_NodeTree_bl_idname_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
+ RNA_def_property_ui_text(prop, "ID Name", "");
+
+ prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->ui_name");
+ RNA_def_property_string_funcs(prop, "rna_NodeTree_bl_label_get", "rna_NodeTree_bl_label_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER);
+ RNA_def_property_ui_text(prop, "Label", "The node tree label");
+
+ prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_TRANSLATION);
+ RNA_def_property_string_sdna(prop, NULL, "typeinfo->ui_description");
+ RNA_def_property_string_funcs(prop, "rna_NodeTree_bl_description_get", "rna_NodeTree_bl_description_length", NULL);
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+
+ prop = RNA_def_property(srna, "bl_icon", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "typeinfo->ui_icon");
+ RNA_def_property_enum_funcs(prop, "rna_NodeTree_bl_icon_get", NULL, NULL);
+ RNA_def_property_enum_items(prop, node_icon_items);
+ RNA_def_property_enum_default(prop, ICON_NODETREE);
+ RNA_def_property_flag(prop, PROP_REGISTER);
+ RNA_def_property_ui_text(prop, "Icon", "The node tree icon");
+
+ /* poll */
+ func = RNA_def_function(srna, "poll", NULL);
+ RNA_def_function_ui_description(func, "Check visibility in the editor");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ RNA_def_function_return(func, RNA_def_boolean(func, "visible", FALSE, "", ""));
+
+ /* draw add menu */
+ func = RNA_def_function(srna, "draw_add_menu", NULL);
+ RNA_def_function_ui_description(func, "Draw the menu for adding nodes");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_property(func, "layout", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(parm, "UILayout");
+ RNA_def_property_ui_text(parm, "Layout", "Menu layout in the UI");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+
+ /* get a node tree from context */
+ func = RNA_def_function(srna, "get_from_context", NULL);
+ RNA_def_function_ui_description(func, "Get a node tree from the context");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_pointer(func, "result_1", "NodeTree", "Node Tree", "Active node tree from context");
+ RNA_def_function_output(func, parm);
+ parm = RNA_def_pointer(func, "result_2", "ID", "Owner ID", "ID data block that owns the node tree");
+ RNA_def_function_output(func, parm);
+ parm = RNA_def_pointer(func, "result_3", "ID", "From ID", "Original ID data block selected from the context");
+ RNA_def_function_output(func, parm);
}
static void rna_def_composite_nodetree(BlenderRNA *brna)
@@ -4799,15 +6918,7 @@ static void rna_def_composite_nodetree(BlenderRNA *brna)
srna = RNA_def_struct(brna, "CompositorNodeTree", "NodeTree");
RNA_def_struct_ui_text(srna, "Compositor Node Tree", "Node tree consisting of linked nodes used for compositing");
RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_icon(srna, ICON_NODETREE);
-
- /* Nodes Collection */
- prop = RNA_def_property(srna, "nodes", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "nodes", NULL);
- RNA_def_property_struct_type(prop, "Node");
- RNA_def_property_ui_text(prop, "Nodes", "");
-
- rna_def_composite_nodetree_api(brna, prop);
+ RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS);
prop = RNA_def_property(srna, "render_quality", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "render_quality");
@@ -4829,98 +6940,115 @@ static void rna_def_composite_nodetree(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", NTREE_COM_OPENCL);
RNA_def_property_ui_text(prop, "OpenCL", "Enable GPU calculations");
+ prop = RNA_def_property(srna, "use_groupnode_buffer", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NTREE_COM_GROUPNODE_BUFFER);
+ RNA_def_property_ui_text(prop, "Buffer Groups", "Enable buffering of group nodes");
+
prop = RNA_def_property(srna, "two_pass", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", NTREE_TWO_PASS);
RNA_def_property_ui_text(prop, "Two Pass", "Use two pass execution during editing: first calculate fast nodes, "
"second pass calculate all nodes");
+
+ prop = RNA_def_property(srna, "use_viewer_border", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NTREE_VIEWER_BORDER);
+ RNA_def_property_ui_text(prop, "Viewer Border", "Use boundaries for viewer nodes and composite backdrop");
+ RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, "rna_NodeTree_update");
}
static void rna_def_shader_nodetree(BlenderRNA *brna)
{
StructRNA *srna;
- PropertyRNA *prop;
srna = RNA_def_struct(brna, "ShaderNodeTree", "NodeTree");
RNA_def_struct_ui_text(srna, "Shader Node Tree",
"Node tree consisting of linked nodes used for materials (and other shading datablocks)");
RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_icon(srna, ICON_NODETREE);
-
- /* Nodes Collection */
- prop = RNA_def_property(srna, "nodes", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "nodes", NULL);
- RNA_def_property_struct_type(prop, "Node");
- RNA_def_property_ui_text(prop, "Nodes", "");
-
- rna_def_shader_nodetree_api(brna, prop);
+ RNA_def_struct_ui_icon(srna, ICON_MATERIAL);
}
static void rna_def_texture_nodetree(BlenderRNA *brna)
{
StructRNA *srna;
- PropertyRNA *prop;
srna = RNA_def_struct(brna, "TextureNodeTree", "NodeTree");
RNA_def_struct_ui_text(srna, "Texture Node Tree", "Node tree consisting of linked nodes used for textures");
RNA_def_struct_sdna(srna, "bNodeTree");
- RNA_def_struct_ui_icon(srna, ICON_NODETREE);
+ RNA_def_struct_ui_icon(srna, ICON_TEXTURE);
+}
- /* Nodes Collection */
- prop = RNA_def_property(srna, "nodes", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "nodes", NULL);
- RNA_def_property_struct_type(prop, "Node");
- RNA_def_property_ui_text(prop, "Nodes", "");
+static void define_specific_node(BlenderRNA *brna, const char *struct_name, const char *base_name,
+ const char *ui_name, const char *ui_desc, void (*def_func)(StructRNA *))
+{
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ srna = RNA_def_struct(brna, struct_name, base_name);
+ RNA_def_struct_ui_text(srna, ui_name, ui_desc);
+ RNA_def_struct_sdna(srna, "bNode");
+
+ func = RNA_def_function(srna, "is_registered_node_type", "rna_Node_is_registered_node_type");
+ RNA_def_function_ui_description(func, "True if a registered node type");
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_SELF_TYPE);
+ parm = RNA_def_boolean(func, "result", FALSE, "Result", "");
+ RNA_def_function_return(func, parm);
- rna_def_texture_nodetree_api(brna, prop);
+ if (def_func)
+ def_func(srna);
}
-static void define_specific_node(BlenderRNA *brna, int id, void (*func)(StructRNA *))
+static void rna_def_node_instance_hash(BlenderRNA *brna)
{
- StructRNA *srna = def_node(brna, id);
+ StructRNA *srna;
- if (func)
- func(srna);
+ srna = RNA_def_struct(brna, "NodeInstanceHash", NULL);
+ RNA_def_struct_ui_text(srna, "Node Instance Hash", "Hash table containing node instance data");
+
+ /* XXX This type is a stub for now, only used to store instance hash in the context.
+ * Eventually could use a StructRNA pointer to define a specific data type
+ * and expose lookup functions.
+ */
}
void RNA_def_nodetree(BlenderRNA *brna)
{
- init();
- rna_def_nodetree(brna);
-
rna_def_node_socket(brna);
-
- /* Generate RNA definitions for all socket subtypes */
- #define SUBTYPE(socktype, stypename, id, idname) \
- rna_def_node_socket_subtype(brna, SOCK_##socktype, PROP_##id, "NodeSocket"#stypename#idname, \
- #idname" "#stypename" Node Socket");
- NODE_DEFINE_SUBTYPES
- #undef SUBTYPE
- rna_def_node_socket_subtype(brna, SOCK_BOOLEAN, 0, "NodeSocketBoolean", "Boolean Node Socket");
- rna_def_node_socket_subtype(brna, SOCK_RGBA, 0, "NodeSocketRGBA", "RGBA Node Socket");
- rna_def_node_socket_subtype(brna, SOCK_SHADER, 0, "NodeSocketShader", "Shader Closure Node Socket");
+ rna_def_node_socket_interface(brna);
rna_def_node(brna);
rna_def_node_link(brna);
rna_def_shader_node(brna);
rna_def_compositor_node(brna);
rna_def_texture_node(brna);
- rna_def_special_node(brna);
+
+ rna_def_nodetree(brna);
+
+ rna_def_node_socket_standard_types(brna);
rna_def_composite_nodetree(brna);
rna_def_shader_nodetree(brna);
rna_def_texture_nodetree(brna);
+
#define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
- define_specific_node(brna, ID, DefFunc);
-
- #include "rna_nodetree_types.h"
+ define_specific_node(brna, #Category #StructName, #Category, UIName, UIDesc, DefFunc);
- define_specific_node(brna, NODE_GROUP, def_group);
- define_specific_node(brna, NODE_FRAME, def_frame);
- define_specific_node(brna, NODE_REROUTE, 0);
+ /* hack, don't want to add include path to RNA just for this, since in the future RNA types
+ * for nodes should be defined locally at runtime anyway ...
+ */
+ #include "../../nodes/NOD_static_types.h"
+
+ /* Node group types need to be defined for shader, compositor, texture nodes individually.
+ * Cannot use the static types header for this, since they share the same int id.
+ */
+ define_specific_node(brna, "ShaderNodeGroup", "ShaderNode", "Group", "", def_group);
+ define_specific_node(brna, "CompositorNodeGroup", "CompositorNode", "Group", "", def_group);
+ define_specific_node(brna, "TextureNodeGroup", "TextureNode", "Group", "", def_group);
/* special socket types */
rna_def_cmp_output_file_slot_file(brna);
rna_def_cmp_output_file_slot_layer(brna);
+
+ rna_def_node_instance_hash(brna);
}
/* clean up macro definition */
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index df7c4d78531..594b86f000c 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -24,16 +24,9 @@
* \ingroup RNA
*/
-
#include <stdio.h>
#include <stdlib.h>
-#include "RNA_access.h"
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
-#include "rna_internal.h"
-
#include "DNA_action_types.h"
#include "DNA_customdata_types.h"
#include "DNA_controller_types.h"
@@ -48,9 +41,16 @@
#include "BLI_utildefines.h"
+#include "BKE_paint.h"
#include "BKE_tessmesh.h"
#include "BKE_group.h" /* needed for object_in_group() */
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
#include "BLO_sys_types.h" /* needed for intptr_t used in ED_mesh.h */
#include "ED_mesh.h"
@@ -94,6 +94,7 @@ static EnumPropertyItem parent_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
+#ifndef RNA_RUNTIME
static EnumPropertyItem dupli_items[] = {
{0, "NONE", 0, "None", ""},
{OB_DUPLIFRAMES, "FRAMES", 0, "Frames", "Make copy of object for every frame"},
@@ -102,6 +103,7 @@ static EnumPropertyItem dupli_items[] = {
{OB_DUPLIGROUP, "GROUP", 0, "Group", "Enable group instancing"},
{0, NULL, 0, NULL, NULL}
};
+#endif
static EnumPropertyItem collision_bounds_items[] = {
{OB_BOUND_BOX, "BOX", 0, "Box", ""},
@@ -153,6 +155,15 @@ EnumPropertyItem object_type_curve_items[] = {
{0, NULL, 0, NULL, NULL}
};
+EnumPropertyItem object_axis_items[] = {
+ {OB_POSX, "POS_X", 0, "+X", ""},
+ {OB_POSY, "POS_Y", 0, "+Y", ""},
+ {OB_POSZ, "POS_Z", 0, "+Z", ""},
+ {OB_NEGX, "NEG_X", 0, "-X", ""},
+ {OB_NEGY, "NEG_Y", 0, "-Y", ""},
+ {OB_NEGZ, "NEG_Z", 0, "-Z", ""},
+ {0, NULL, 0, NULL, NULL}
+};
#ifdef RNA_RUNTIME
@@ -281,12 +292,10 @@ static void rna_Object_active_shape_update(Main *bmain, Scene *scene, PointerRNA
rna_Object_internal_update_data(bmain, scene, ptr);
}
-static void rna_Object_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Object_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
DAG_id_tag_update(ptr->id.data, OB_RECALC_OB);
- if (scene) {
- DAG_scene_sort(bmain, scene);
- }
+ DAG_relations_tag_update(bmain);
WM_main_add_notifier(NC_OBJECT | ND_PARENT, ptr->id.data);
}
@@ -320,7 +329,7 @@ static void rna_Object_layer_update__internal(Main *bmain, Scene *scene, Base *b
/* pass */
}
else {
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
}
DAG_id_type_tag(bmain, ID_OB);
@@ -374,7 +383,7 @@ static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value)
}
}
else if (ob->type == OB_MESH) {
- set_mesh(ob, (Mesh *)id);
+ BKE_mesh_assign_object(ob, (Mesh *)id);
}
else {
if (ob->data) {
@@ -1121,7 +1130,7 @@ static void rna_GameObjectSettings_used_state_get(PointerRNA *ptr, int *values)
static void rna_GameObjectSettings_col_group_get(PointerRNA *ptr, int *values)
{
- Object *ob = (Object*)ptr->data;
+ Object *ob = (Object *)ptr->data;
int i;
for (i = 0; i < OB_MAX_COL_MASKS; i++) {
@@ -1131,7 +1140,7 @@ static void rna_GameObjectSettings_col_group_get(PointerRNA *ptr, int *values)
static void rna_GameObjectSettings_col_group_set(PointerRNA *ptr, const int *values)
{
- Object *ob = (Object*)ptr->data;
+ Object *ob = (Object *)ptr->data;
int i, tot = 0;
/* ensure we always have some group selected */
@@ -1150,7 +1159,7 @@ static void rna_GameObjectSettings_col_group_set(PointerRNA *ptr, const int *val
static void rna_GameObjectSettings_col_mask_get(PointerRNA *ptr, int *values)
{
- Object *ob = (Object*)ptr->data;
+ Object *ob = (Object *)ptr->data;
int i;
for (i = 0; i < OB_MAX_COL_MASKS; i++) {
@@ -1160,7 +1169,7 @@ static void rna_GameObjectSettings_col_mask_get(PointerRNA *ptr, int *values)
static void rna_GameObjectSettings_col_mask_set(PointerRNA *ptr, const int *values)
{
- Object *ob = (Object*)ptr->data;
+ Object *ob = (Object *)ptr->data;
int i, tot = 0;
/* ensure we always have some mask selected */
@@ -1250,20 +1259,20 @@ static PointerRNA rna_Object_collision_get(PointerRNA *ptr)
static PointerRNA rna_Object_active_constraint_get(PointerRNA *ptr)
{
Object *ob = (Object *)ptr->id.data;
- bConstraint *con = constraints_get_active(&ob->constraints);
+ bConstraint *con = BKE_constraints_get_active(&ob->constraints);
return rna_pointer_inherit_refine(ptr, &RNA_Constraint, con);
}
static void rna_Object_active_constraint_set(PointerRNA *ptr, PointerRNA value)
{
Object *ob = (Object *)ptr->id.data;
- constraints_set_active(&ob->constraints, (bConstraint *)value.data);
+ BKE_constraints_set_active(&ob->constraints, (bConstraint *)value.data);
}
static bConstraint *rna_Object_constraints_new(Object *object, int type)
{
WM_main_add_notifier(NC_OBJECT | ND_CONSTRAINT | NA_ADDED, object);
- return add_ob_constraint(object, NULL, type);
+ return BKE_add_ob_constraint(object, NULL, type);
}
static void rna_Object_constraints_remove(Object *object, ReportList *reports, PointerRNA *con_ptr)
@@ -1274,7 +1283,7 @@ static void rna_Object_constraints_remove(Object *object, ReportList *reports, P
return;
}
- remove_constraint(&object->constraints, con);
+ BKE_remove_constraint(&object->constraints, con);
RNA_POINTER_INVALIDATE(con_ptr);
ED_object_constraint_update(object);
@@ -1284,7 +1293,7 @@ static void rna_Object_constraints_remove(Object *object, ReportList *reports, P
static void rna_Object_constraints_clear(Object *object)
{
- free_constraints(&object->constraints);
+ BKE_free_constraints(&object->constraints);
ED_object_constraint_update(object);
ED_object_constraint_set_active(object, NULL);
@@ -1301,7 +1310,7 @@ static ModifierData *rna_Object_modifier_new(Object *object, bContext *C, Report
static void rna_Object_modifier_remove(Object *object, bContext *C, ReportList *reports, PointerRNA *md_ptr)
{
ModifierData *md = md_ptr->data;
- if (ED_object_modifier_remove(reports, CTX_data_main(C), CTX_data_scene(C), object, md) == FALSE) {
+ if (ED_object_modifier_remove(reports, CTX_data_main(C), object, md) == FALSE) {
/* error is already set */
return;
}
@@ -1313,7 +1322,7 @@ static void rna_Object_modifier_remove(Object *object, bContext *C, ReportList *
static void rna_Object_modifier_clear(Object *object, bContext *C)
{
- ED_object_modifier_clear(CTX_data_main(C), CTX_data_scene(C), object);
+ ED_object_modifier_clear(CTX_data_main(C), object);
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER | NA_REMOVED, object);
}
@@ -1434,6 +1443,12 @@ int rna_DupliObject_index_get(PointerRNA *ptr)
return dob->persistent_id[0];
}
+int rna_Object_use_dynamic_topology_sculpting_get(PointerRNA *ptr)
+{
+ SculptSession *ss = ((Object *)ptr->id.data)->sculpt;
+ return (ss && ss->bm);
+}
+
#else
static int rna_matrix_dimsize_4x4[] = {4, 4};
@@ -1993,16 +2008,6 @@ static void rna_def_object(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
-
- static EnumPropertyItem track_items[] = {
- {OB_POSX, "POS_X", 0, "+X", ""},
- {OB_POSY, "POS_Y", 0, "+Y", ""},
- {OB_POSZ, "POS_Z", 0, "+Z", ""},
- {OB_NEGX, "NEG_X", 0, "-X", ""},
- {OB_NEGY, "NEG_Y", 0, "-Y", ""},
- {OB_NEGZ, "NEG_Z", 0, "-Z", ""},
- {0, NULL, 0, NULL, NULL}
- };
static EnumPropertyItem up_items[] = {
{OB_POSX, "X", 0, "X", ""},
@@ -2025,6 +2030,7 @@ static void rna_def_object(BlenderRNA *brna)
{OB_BOUND_SPHERE, "SPHERE", 0, "Sphere", "Draw bounds as sphere"},
{OB_BOUND_CYLINDER, "CYLINDER", 0, "Cylinder", "Draw bounds as cylinder"},
{OB_BOUND_CONE, "CONE", 0, "Cone", "Draw bounds as cone"},
+ {OB_BOUND_CAPSULE, "CAPSULE", 0, "Capsule", "Draw bounds as capsule"},
{0, NULL, 0, NULL, NULL}
};
@@ -2080,6 +2086,7 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_boolean_funcs(prop, NULL, "rna_Object_layer_set");
RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_layer_update");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
prop = RNA_def_property(srna, "layers_local_view", PROP_BOOLEAN, PROP_LAYER_MEMBER);
RNA_def_property_boolean_sdna(prop, NULL, "lay", 0x01000000);
@@ -2132,7 +2139,7 @@ static void rna_def_object(BlenderRNA *brna)
* since some other tools still refer to this */
prop = RNA_def_property(srna, "track_axis", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "trackflag");
- RNA_def_property_enum_items(prop, track_items);
+ RNA_def_property_enum_items(prop, object_axis_items);
RNA_def_property_ui_text(prop, "Track Axis",
"Axis that points in 'forward' direction (applies to DupliFrame when "
"parent 'Follow' is enabled)");
@@ -2419,6 +2426,17 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Particle Systems", "Particle systems emitted from the object");
rna_def_object_particle_systems(brna, prop);
+
+ prop = RNA_def_property(srna, "rigid_body", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "rigidbody_object");
+ RNA_def_property_struct_type(prop, "RigidBodyObject");
+ RNA_def_property_ui_text(prop, "Rigid Body Settings", "Settings for rigid body simulation");
+
+ prop = RNA_def_property(srna, "rigid_body_constraint", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "rigidbody_constraint");
+ RNA_def_property_struct_type(prop, "RigidBodyConstraint");
+ RNA_def_property_ui_text(prop, "Rigid Body Constraint", "Constraint constraining rigid bodies");
+
/* restrict */
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_VIEW);
@@ -2459,6 +2477,15 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Slow Parent Offset", "Delay in the parent relationship");
RNA_def_property_update(prop, NC_OBJECT | ND_TRANSFORM, "rna_Object_internal_update");
+ /* depsgraph hack */
+ prop = RNA_def_property(srna, "extra_recalc_object", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "depsflag", OB_DEPS_EXTRA_OB_RECALC);
+ RNA_def_property_ui_text(prop, "Extra Object Update", "Refresh this object again on frame changes, dependency graph hack");
+
+ prop = RNA_def_property(srna, "extra_recalc_data", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "depsflag", OB_DEPS_EXTRA_DATA_RECALC);
+ RNA_def_property_ui_text(prop, "Extra Data Update", "Refresh this object's data again on frame changes, dependency graph hack");
+
/* duplicates */
prop = RNA_def_property(srna, "dupli_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "transflag");
@@ -2538,7 +2565,7 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
prop = RNA_def_property(srna, "show_bounds", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_BOUNDBOX);
+ RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_DRAWBOUNDOX);
RNA_def_property_ui_text(prop, "Draw Bounds", "Display the object's bounds");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
@@ -2567,7 +2594,12 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_DRAWWIRE);
RNA_def_property_ui_text(prop, "Draw Wire", "Add the object's wireframe over solid drawing");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
-
+
+ prop = RNA_def_property(srna, "show_all_edges", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_DRAW_ALL_EDGES);
+ RNA_def_property_ui_text(prop, "Draw All Edges", "Display all edges for mesh objects");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
prop = RNA_def_property(srna, "show_transparent", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_DRAWTRANSP);
RNA_def_property_ui_text(prop, "Draw Transparent",
@@ -2626,6 +2658,12 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Active Shape Key Index", "Current shape key index");
RNA_def_property_update(prop, 0, "rna_Object_active_shape_update");
+ /* sculpt */
+ prop = RNA_def_property(srna, "use_dynamic_topology_sculpting", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_Object_use_dynamic_topology_sculpting_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Dynamic Topology Sculpting", NULL);
+
RNA_api_object(srna);
}
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 87fc3be28a2..7715dfa64de 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -34,265 +34,90 @@
#include <string.h>
#include <time.h>
+#include "BLI_utildefines.h"
+
#include "RNA_define.h"
-#include "DNA_object_types.h"
+#include "DNA_constraint_types.h"
#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
#include "rna_internal.h" /* own include */
+static EnumPropertyItem space_items[] = {
+ {CONSTRAINT_SPACE_WORLD, "WORLD", 0, "World Space",
+ "The most gobal space in Blender"},
+ {CONSTRAINT_SPACE_POSE, "POSE", 0, "Pose Space",
+ "The pose space of a bone (its armature's object space)"},
+ {CONSTRAINT_SPACE_PARLOCAL, "LOCAL_WITH_PARENT", 0, "Local With Parent",
+ "The local space of a bone's parent bone"},
+ {CONSTRAINT_SPACE_LOCAL, "LOCAL", 0, "Local Space",
+ "The local space of an object/bone"},
+ {0, NULL, 0, NULL, NULL}
+};
+
#ifdef RNA_RUNTIME
+
#include "BLI_math.h"
-#include "BKE_main.h"
-#include "BKE_global.h"
-#include "BKE_context.h"
-#include "BKE_report.h"
-#include "BKE_object.h"
-#include "BKE_mesh.h"
-#include "BKE_DerivedMesh.h"
+#include "BKE_anim.h"
#include "BKE_bvhutils.h"
-
+#include "BKE_cdderivedmesh.h"
+#include "BKE_constraint.h"
+#include "BKE_context.h"
#include "BKE_customdata.h"
-#include "BKE_anim.h"
#include "BKE_depsgraph.h"
-#include "BKE_displist.h"
#include "BKE_font.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
#include "BKE_mball.h"
#include "BKE_modifier.h"
-#include "BKE_cdderivedmesh.h"
+#include "BKE_object.h"
+#include "BKE_report.h"
+#include "ED_object.h"
+
+#include "DNA_curve_types.h"
#include "DNA_mesh_types.h"
-#include "DNA_scene_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_curve_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_constraint_types.h"
+#include "DNA_scene_types.h"
#include "DNA_view3d_types.h"
#include "MEM_guardedalloc.h"
-/* copied from Mesh_getFromObject and adapted to RNA interface */
-/* settings: 0 - preview, 1 - render */
-static Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_modifiers, int settings)
+/* 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)
{
- Mesh *tmpmesh;
- Curve *tmpcu = NULL, *copycu;
- Object *tmpobj = NULL;
- int render = settings == eModifierMode_Render, i;
- int cage = !apply_modifiers;
-
- /* perform the mesh extraction based on type */
- switch (ob->type) {
- case OB_FONT:
- case OB_CURVE:
- case OB_SURF:
- {
- ListBase dispbase = {NULL, NULL};
- DerivedMesh *derivedFinal = NULL;
- int uv_from_orco;
-
- int (*orco_index)[4] = NULL;
- float (*orco)[3] = NULL;
-
- /* copies object and modifiers (but not the data) */
- tmpobj = BKE_object_copy_with_caches(ob);
- tmpcu = (Curve *)tmpobj->data;
- tmpcu->id.us--;
-
- /* if getting the original caged mesh, delete object modifiers */
- if (cage)
- BKE_object_free_modifiers(tmpobj);
-
- /* copies the data */
- copycu = tmpobj->data = BKE_curve_copy((Curve *) ob->data);
-
- /* temporarily set edit so we get updates from edit mode, but
- * also because for text datablocks copying it while in edit
- * mode gives invalid data structures */
- copycu->editfont = tmpcu->editfont;
- copycu->editnurb = tmpcu->editnurb;
-
- /* get updated display list, and convert to a mesh */
- BKE_displist_make_curveTypes_forRender(sce, tmpobj, &dispbase, &derivedFinal, FALSE);
-
- copycu->editfont = NULL;
- copycu->editnurb = NULL;
-
- tmpobj->derivedFinal = derivedFinal;
-
- uv_from_orco = (tmpcu->flag & CU_UV_ORCO) != 0;
-
- if (uv_from_orco) {
- /* before curve conversion */
- orco = (float (*)[3])BKE_curve_make_orco(sce, tmpobj);
- }
-
- /* convert object type to mesh */
- BKE_mesh_from_nurbs_displist(tmpobj, &dispbase, uv_from_orco ? (int **)&orco_index : NULL);
-
- tmpmesh = tmpobj->data;
-
- if (uv_from_orco && orco && orco_index) {
- const char *uvname = "Orco";
- /* add UV's */
- MTexPoly *mtpoly = CustomData_add_layer_named(&tmpmesh->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, tmpmesh->totpoly, uvname);
- MLoopUV *mloopuvs = CustomData_add_layer_named(&tmpmesh->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, tmpmesh->totloop, uvname);
-
- BKE_mesh_nurbs_to_mdata_orco(tmpmesh->mpoly, tmpmesh->totpoly,
- tmpmesh->mloop, mloopuvs,
- orco, orco_index);
-
- (void)mtpoly;
- }
-
- if (orco_index) {
- MEM_freeN(orco_index);
- }
- if (orco) {
- MEM_freeN(orco);
- }
-
- BKE_displist_free(&dispbase);
-
- /* BKE_mesh_from_nurbs changes the type to a mesh, check it worked */
- if (tmpobj->type != OB_MESH) {
- BKE_libblock_free_us(&(G.main->object), tmpobj);
- BKE_report(reports, RPT_ERROR, "Cannot convert curve to mesh (does the curve have any segments?)");
- return NULL;
- }
-
- BKE_libblock_free_us(&G.main->object, tmpobj);
- break;
+ copy_m4_m4((float (*)[4])mat_ret, (float (*)[4])mat);
+
+ /* Error in case of invalid from/to values when pchan is NULL */
+ if (pchan == NULL) {
+ if (ELEM(from, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_PARLOCAL)) {
+ const char *identifier = NULL;
+ RNA_enum_identifier(space_items, from, &identifier);
+ BKE_reportf(reports, RPT_ERROR, "'from_space' '%s' is invalid when no pose bone is given!", identifier);
+ return;
}
-
- case OB_MBALL:
- {
- /* metaballs don't have modifiers, so just convert to mesh */
- Object *basis_ob = BKE_mball_basis_find(sce, ob);
- /* todo, re-generatre for render-res */
- /* metaball_polygonize(scene, ob) */
-
- if (ob != basis_ob)
- return NULL; /* only do basis metaball */
-
- tmpmesh = BKE_mesh_add("Mesh");
- /* BKE_mesh_add gives us a user count we don't need */
- tmpmesh->id.us--;
-
- if (render) {
- ListBase disp = {NULL, NULL};
- BKE_displist_make_mball_forRender(sce, ob, &disp);
- BKE_mesh_from_metaball(&disp, tmpmesh);
- BKE_displist_free(&disp);
- }
- else
- BKE_mesh_from_metaball(&ob->disp, tmpmesh);
-
- break;
-
+ if (ELEM(to, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_PARLOCAL)) {
+ const char *identifier = NULL;
+ RNA_enum_identifier(space_items, to, &identifier);
+ BKE_reportf(reports, RPT_ERROR, "'to_space' '%s' is invalid when no pose bone is given!", identifier);
+ return;
}
- case OB_MESH:
- /* copies object and modifiers (but not the data) */
- if (cage) {
- /* copies the data */
- tmpmesh = BKE_mesh_copy(ob->data);
- /* if not getting the original caged mesh, get final derived mesh */
- }
- else {
- /* Make a dummy mesh, saves copying */
- DerivedMesh *dm;
- /* CustomDataMask mask = CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL; */
- CustomDataMask mask = CD_MASK_MESH; /* this seems more suitable, exporter,
- * for example, needs CD_MASK_MDEFORMVERT */
-
- /* Write the display mesh into the dummy mesh */
- if (render)
- dm = mesh_create_derived_render(sce, ob, mask);
- else
- dm = mesh_create_derived_view(sce, ob, mask);
-
- tmpmesh = BKE_mesh_add("Mesh");
- DM_to_mesh(dm, tmpmesh, ob);
- dm->release(dm);
- }
-
- /* BKE_mesh_add/copy gives us a user count we don't need */
- tmpmesh->id.us--;
-
- break;
- default:
- BKE_report(reports, RPT_ERROR, "Object does not have geometry data");
- return NULL;
}
- /* Copy materials to new mesh */
- switch (ob->type) {
- case OB_SURF:
- case OB_FONT:
- case OB_CURVE:
- tmpmesh->totcol = tmpcu->totcol;
-
- /* free old material list (if it exists) and adjust user counts */
- if (tmpcu->mat) {
- for (i = tmpcu->totcol; i-- > 0; ) {
- /* are we an object material or data based? */
-
- tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : tmpcu->mat[i];
-
- if (tmpmesh->mat[i]) {
- tmpmesh->mat[i]->id.us++;
- }
- }
- }
- break;
-
-#if 0
- /* Crashes when assigning the new material, not sure why */
- case OB_MBALL:
- tmpmb = (MetaBall *)ob->data;
- tmpmesh->totcol = tmpmb->totcol;
-
- /* free old material list (if it exists) and adjust user counts */
- if (tmpmb->mat) {
- for (i = tmpmb->totcol; i-- > 0; ) {
- tmpmesh->mat[i] = tmpmb->mat[i]; /* CRASH HERE ??? */
- if (tmpmesh->mat[i]) {
- tmpmb->mat[i]->id.us++;
- }
- }
- }
- break;
-#endif
-
- case OB_MESH:
- if (!cage) {
- Mesh *origmesh = ob->data;
- tmpmesh->flag = origmesh->flag;
- tmpmesh->mat = MEM_dupallocN(origmesh->mat);
- tmpmesh->totcol = origmesh->totcol;
- tmpmesh->smoothresh = origmesh->smoothresh;
- if (origmesh->mat) {
- for (i = origmesh->totcol; i-- > 0; ) {
- /* are we an object material or data based? */
- tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : origmesh->mat[i];
-
- if (tmpmesh->mat[i]) {
- tmpmesh->mat[i]->id.us++;
- }
- }
- }
- }
- break;
- } /* end copy materials */
-
- /* cycles and exporters rely on this still */
- BKE_mesh_tessface_ensure(tmpmesh);
-
- /* make sure materials get updated in objects */
- test_object_materials(&tmpmesh->id);
+ BKE_constraint_mat_convertspace(ob, pchan, (float (*)[4])mat_ret, from, to);
+}
- return tmpmesh;
+/* copied from Mesh_getFromObject and adapted to RNA interface */
+/* settings: 0 - preview, 1 - render */
+static Mesh *rna_Object_to_mesh(
+ Object *ob, ReportList *reports, Scene *sce,
+ int apply_modifiers, int settings, int calc_tessface)
+{
+ return rna_Main_meshes_new_from_object(G.main, reports, sce, ob, apply_modifiers, settings, calc_tessface);
}
/* mostly a copy from convertblender.c */
@@ -570,7 +395,14 @@ void rna_Object_dm_info(struct Object *ob, int type, char *result)
}
#endif /* NDEBUG */
-#else
+static int rna_Object_update_from_editmode(Object *ob)
+{
+ if (ob->mode & OB_MODE_EDIT) {
+ return ED_object_editmode_load(ob);
+ }
+ return false;
+}
+#else /* RNA_RUNTIME */
void RNA_api_object(StructRNA *srna)
{
@@ -583,6 +415,8 @@ void RNA_api_object(StructRNA *srna)
{0, NULL, 0, NULL, NULL}
};
+ static int rna_matrix_dimsize_4x4[] = {4, 4};
+
#ifndef NDEBUG
static EnumPropertyItem mesh_dm_info_items[] = {
{0, "SOURCE", 0, "Source", "Source mesh"},
@@ -592,6 +426,25 @@ void RNA_api_object(StructRNA *srna)
};
#endif
+ /* Matrix space conversion */
+ func = RNA_def_function(srna, "convert_space", "rna_Scene_mat_convert_space");
+ RNA_def_function_ui_description(func, "Convert (transform) the given matrix from one space to another");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "pose_bone", "PoseBone", "",
+ "Bone to use to define spaces (may be None, in which case only the two 'WORLD' and "
+ "'LOCAL' spaces are usable)");
+ parm = RNA_def_property(func, "matrix", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_multi_array(parm, 2, rna_matrix_dimsize_4x4);
+ RNA_def_property_ui_text(parm, "", "The matrix to transform");
+ parm = RNA_def_property(func, "matrix_return", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_multi_array(parm, 2, rna_matrix_dimsize_4x4);
+ RNA_def_property_ui_text(parm, "", "The transformed matrix");
+ RNA_def_function_output(func, parm);
+ parm = RNA_def_enum(func, "from_space", space_items, CONSTRAINT_SPACE_WORLD, "",
+ "The space in which 'matrix' is currently");
+ parm = RNA_def_enum(func, "to_space", space_items, CONSTRAINT_SPACE_WORLD, "",
+ "The space to which you want to transform 'matrix'");
+
/* 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");
@@ -602,6 +455,7 @@ void RNA_api_object(StructRNA *srna)
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_enum(func, "settings", mesh_type_items, 0, "", "Modifier settings to apply");
RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_boolean(func, "calc_tessface", true, "Calculate Tessellation", "Calculate tessellation faces");
parm = RNA_def_pointer(func, "mesh", "Mesh", "",
"Mesh created from object, remove it if it is only used for export");
RNA_def_function_return(func, parm);
@@ -722,6 +576,11 @@ void RNA_api_object(StructRNA *srna)
RNA_def_property_flag(parm, PROP_THICK_WRAP); /* needed for string return value */
RNA_def_function_output(func, parm);
#endif /* NDEBUG */
+
+ func = RNA_def_function(srna, "update_from_editmode", "rna_Object_update_from_editmode");
+ 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);
}
@@ -737,5 +596,4 @@ void RNA_api_object_base(StructRNA *srna)
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
}
-#endif
-
+#endif /* RNA_RUNTIME */
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 6d7187da7d9..ab8b54334fe 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -24,13 +24,8 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
-#include "RNA_define.h"
-
-#include "rna_internal.h"
-
#include "DNA_cloth_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
@@ -38,6 +33,10 @@
#include "DNA_scene_types.h"
#include "DNA_smoke_types.h"
+#include "RNA_define.h"
+
+#include "rna_internal.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -484,7 +483,7 @@ static void rna_FieldSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
part->pd->tex = NULL;
}
- if (part->pd2->forcefield != PFIELD_TEXTURE && part->pd2->tex) {
+ if (part->pd2 && part->pd2->forcefield != PFIELD_TEXTURE && part->pd2->tex) {
part->pd2->tex->id.us--;
part->pd2->tex = NULL;
}
@@ -521,7 +520,7 @@ static void rna_FieldSettings_shape_update(Main *bmain, Scene *scene, PointerRNA
}
else {
if (!pd || pd->shape != PFIELD_SHAPE_SURFACE)
- ED_object_modifier_remove(NULL, bmain, scene, ob, md);
+ ED_object_modifier_remove(NULL, bmain, ob, md);
}
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
@@ -547,7 +546,7 @@ static void rna_FieldSettings_dependency_update(Main *bmain, Scene *scene, Point
rna_FieldSettings_shape_update(bmain, scene, ptr);
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
if (ob->type == OB_CURVE && ob->pd->forcefield == PFIELD_GUIDE)
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
@@ -590,9 +589,9 @@ static void rna_EffectorWeight_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
}
-static void rna_EffectorWeight_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_EffectorWeight_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
DAG_id_tag_update((ID *)ptr->id.data, OB_RECALC_DATA | PSYS_RECALC_RESET);
@@ -669,7 +668,7 @@ static void rna_CollisionSettings_dependency_update(Main *bmain, Scene *scene, P
if (ob->pd->deflect && !md)
ED_object_modifier_add(NULL, bmain, scene, ob, NULL, eModifierType_Collision);
else if (!ob->pd->deflect && md)
- ED_object_modifier_remove(NULL, bmain, scene, ob, md);
+ ED_object_modifier_remove(NULL, bmain, ob, md);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
}
@@ -763,7 +762,8 @@ static void rna_def_pointcache(BlenderRNA *brna)
prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "startframe");
- RNA_def_property_range(prop, 1, MAXFRAME);
+ RNA_def_property_range(prop, -MAXFRAME, MAXFRAME);
+ RNA_def_property_ui_range(prop, 1, MAXFRAME, 1, 1);
RNA_def_property_ui_text(prop, "Start", "Frame on which the simulation starts");
prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_TIME);
@@ -1181,7 +1181,7 @@ static void rna_def_field(BlenderRNA *brna)
prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "f_strength");
- RNA_def_property_range(prop, -1000.0f, 1000.0f);
+ RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
RNA_def_property_ui_text(prop, "Strength", "Strength of force field");
RNA_def_property_update(prop, 0, "rna_FieldSettings_update");
diff --git a/source/blender/makesrna/intern/rna_packedfile.c b/source/blender/makesrna/intern/rna_packedfile.c
index e691ca46c69..a72188591a1 100644
--- a/source/blender/makesrna/intern/rna_packedfile.c
+++ b/source/blender/makesrna/intern/rna_packedfile.c
@@ -24,15 +24,16 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
+#include "BLI_utildefines.h"
+
+#include "DNA_packedFile_types.h"
+
#include "RNA_define.h"
#include "rna_internal.h"
-#include "DNA_packedFile_types.h"
-
EnumPropertyItem unpack_method_items[] = {
{PF_USE_LOCAL, "USE_LOCAL", 0, "Use Local File", ""},
{PF_WRITE_LOCAL, "WRITE_LOCAL", 0, "Write Local File (overwrite existing)", ""},
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 6825d3d781d..c675aa6ebc3 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -27,16 +27,10 @@
* \ingroup RNA
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
-#include "rna_internal.h"
-
#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
@@ -48,6 +42,11 @@
#include "DNA_boid_types.h"
#include "DNA_texture_types.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
#include "WM_types.h"
#include "WM_api.h"
@@ -238,7 +237,369 @@ static void rna_ParticleHairKey_location_object_set(PointerRNA *ptr, const float
}
}
-/* property update functions */
+static void rna_ParticleHairKey_co_object(HairKey *hairkey, Object *object, ParticleSystemModifierData *modifier, ParticleData *particle,
+ float n_co[3])
+{
+
+ DerivedMesh *hairdm = (modifier->psys->flag & PSYS_HAIR_DYNAMICS) ? modifier->psys->hair_out_dm : NULL;
+ if (particle) {
+ if (hairdm) {
+ MVert *mvert = CDDM_get_vert(hairdm, particle->hair_index + (hairkey - particle->hair));
+ copy_v3_v3(n_co, mvert->co);
+ }
+ else {
+ float hairmat[4][4];
+ psys_mat_hair_to_object(object, modifier->dm, modifier->psys->part->from, particle, hairmat);
+ copy_v3_v3(n_co, hairkey->co);
+ mul_m4_v3(hairmat, n_co);
+ }
+ }
+ else {
+ zero_v3(n_co);
+ }
+}
+
+static void rna_Particle_uv_on_emitter(ParticleData *particle, ParticleSystemModifierData *modifier, float n_uv[2])
+{
+ /*psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co, nor, 0, 0, sd.orco, 0);*/
+
+ /* get uvco & mcol */
+ int num = particle->num_dmcache;
+ int from = modifier->psys->part->from;
+
+ if (num == DMCACHE_NOTFOUND)
+ if (particle->num < modifier->dm->getNumTessFaces(modifier->dm))
+ num = particle->num;
+
+ /* get uvco */
+ if (n_uv && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+
+ if (num != DMCACHE_NOTFOUND) {
+ MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
+ MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0);
+ mtface += num;
+
+ psys_interpolate_uvs(mtface, mface->v4, particle->fuv, n_uv);
+ }
+ else {
+ n_uv[0] = 0.0f;
+ n_uv[1] = 0.0f;
+ }
+ }
+}
+
+static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *object, ParticleSystemModifierData *modifier,
+ int particle_no, int step, float n_co[3])
+{
+ ParticleSettings *part = 0;
+ ParticleData *pars = 0;
+ ParticleCacheKey *cache = 0;
+ int totchild = 0;
+ int path_nbr = 0;
+ int totpart;
+ int max_k = 0;
+ int step_nbr = 0;
+
+ if (particlesystem == NULL)
+ return;
+
+ part = particlesystem->part;
+ pars = particlesystem->particles;
+
+ if (particlesystem->renderdata) {
+ step_nbr = part->ren_step;
+ totchild = particlesystem->totchild;
+ }
+ else {
+ step_nbr = part->draw_step;
+ totchild = (int)((float)particlesystem->totchild * (float)(part->disp) / 100.0f);
+ }
+
+ if (part == NULL || pars == NULL || !psys_check_enabled(object, particlesystem))
+ return;
+
+ if (part->ren_as == PART_DRAW_OB || part->ren_as == PART_DRAW_GR || part->ren_as == PART_DRAW_NOT)
+ return;
+
+ /* can happen for disconnected/global hair */
+ if (part->type == PART_HAIR && !particlesystem->childcache)
+ totchild = 0;
+
+ totpart = particlesystem->totpart;
+
+ if (particle_no >= totpart + totchild)
+ return;
+
+ if (part->ren_as == PART_DRAW_PATH && particlesystem->pathcache)
+ path_nbr = (int)pow(2.0, step_nbr);
+
+ if (particle_no < totpart) {
+
+ if (path_nbr) {
+ cache = particlesystem->pathcache[particle_no];
+ max_k = (int)cache->steps;
+ }
+
+ }
+ else {
+
+ if (path_nbr) {
+ cache = particlesystem->childcache[particle_no - totpart];
+
+ if (cache->steps < 0)
+ max_k = 0;
+ else
+ max_k = (int)cache->steps;
+ }
+ }
+
+ /*strands key loop data stored in cache + step->co*/
+ if (path_nbr) {
+ if (step >= 0 && step <= path_nbr) {
+ if (step <= max_k) {
+ copy_v3_v3(n_co, (cache + step)->co);
+ mul_m4_v3(particlesystem->imat, n_co);
+ mul_m4_v3(object->obmat, n_co);
+ }
+ }
+ }
+
+}
+
+static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, ParticleSystemModifierData *modifier, ParticleData *particle, int particle_no, int uv_no,
+ float n_uv[2])
+{
+ ParticleSettings *part = 0;
+ int totpart;
+ int totchild = 0;
+ int num;
+
+ /* 1. check that everything is ok & updated */
+ if (particlesystem == NULL)
+ return;
+
+ part = particlesystem->part;
+
+ if (particlesystem->renderdata) {
+ totchild = particlesystem->totchild;
+ }
+ else {
+ totchild = (int)((float)particlesystem->totchild * (float)(part->disp) / 100.0f);
+ }
+
+ /* can happen for disconnected/global hair */
+ if (part->type == PART_HAIR && !particlesystem->childcache)
+ totchild = 0;
+
+ totpart = particlesystem->totpart;
+
+ if (particle_no >= totpart + totchild)
+ return;
+
+/* 3. start creating renderable things */
+ /* setup per particle individual stuff */
+ if (particle_no < totpart) {
+
+ /* get uvco & mcol */
+ num = particle->num_dmcache;
+
+ if (num == DMCACHE_NOTFOUND)
+ if (particle->num < modifier->dm->getNumTessFaces(modifier->dm))
+ num = particle->num;
+
+ if (n_uv && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if (num != DMCACHE_NOTFOUND) {
+ MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
+ MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, uv_no);
+ mtface += num;
+
+ psys_interpolate_uvs(mtface, mface->v4, particle->fuv, n_uv);
+ }
+ else {
+ n_uv[0] = 0.0f;
+ n_uv[1] = 0.0f;
+ }
+ }
+ }
+ else {
+ ChildParticle *cpa = particlesystem->child + particle_no - totpart;
+
+ num = cpa->num;
+
+ /* get uvco & mcol */
+ if (part->childtype == PART_CHILD_FACES) {
+ if (n_uv && ELEM(PART_FROM_FACE, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if (cpa->num != DMCACHE_NOTFOUND) {
+ MFace *mface = modifier->dm->getTessFaceData(modifier->dm, cpa->num, CD_MFACE);
+ MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, uv_no);
+ mtface += cpa->num;
+
+ psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, n_uv);
+ }
+ else {
+ n_uv[0] = 0.0f;
+ n_uv[1] = 0.0f;
+ }
+ }
+ }
+ else {
+ ParticleData *parent = particlesystem->particles + cpa->parent;
+ num = parent->num_dmcache;
+
+ if (num == DMCACHE_NOTFOUND)
+ if (parent->num < modifier->dm->getNumTessFaces(modifier->dm))
+ num = parent->num;
+
+ if (n_uv && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if (num != DMCACHE_NOTFOUND) {
+ MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
+ MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, uv_no);
+ mtface += num;
+
+ psys_interpolate_uvs(mtface, mface->v4, parent->fuv, n_uv);
+ }
+ else {
+ n_uv[0] = 0.0f;
+ n_uv[1] = 0.0f;
+ }
+ }
+ }
+ }
+}
+
+static void rna_ParticleSystem_mcol_on_emitter(ParticleSystem *particlesystem, ParticleSystemModifierData *modifier,
+ ParticleData *particle, int particle_no, int vcol_no,
+ float n_mcol[3])
+{
+ ParticleSettings *part;
+ int totpart;
+ int totchild = 0;
+ int num;
+ MCol mcol = {255, 255, 255, 255};
+
+ /* 1. check that everything is ok & updated */
+ if (particlesystem == NULL)
+ return;
+
+ part = particlesystem->part;
+
+ if (particlesystem->renderdata) {
+ totchild = particlesystem->totchild;
+ }
+ else {
+ totchild = (int)((float)particlesystem->totchild * (float)(part->disp) / 100.0f);
+ }
+
+ /* can happen for disconnected/global hair */
+ if (part->type == PART_HAIR && !particlesystem->childcache)
+ totchild = 0;
+
+ totpart = particlesystem->totpart;
+
+ if (particle_no >= totpart + totchild)
+ return;
+
+ /* 3. start creating renderable things */
+ /* setup per particle individual stuff */
+ if (particle_no < totpart) {
+
+ /* get uvco & mcol */
+ num = particle->num_dmcache;
+
+ if (num == DMCACHE_NOTFOUND)
+ if (particle->num < modifier->dm->getNumTessFaces(modifier->dm))
+ num = particle->num;
+
+ if (n_mcol && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if (num != DMCACHE_NOTFOUND) {
+ MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
+ MCol *mc = (MCol *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MCOL, vcol_no);
+ mc += num * 4;
+
+ psys_interpolate_mcol(mc, mface->v4, particle->fuv, &mcol);
+ n_mcol[0] = (float)mcol.b / 255.0f;
+ n_mcol[1] = (float)mcol.g / 255.0f;
+ n_mcol[2] = (float)mcol.r / 255.0f;
+ }
+ else {
+ n_mcol[0] = 0.0f;
+ n_mcol[1] = 0.0f;
+ n_mcol[2] = 0.0f;
+ }
+ }
+ }
+ else {
+ ChildParticle *cpa = particlesystem->child + particle_no - totpart;
+
+ num = cpa->num;
+
+ /* get uvco & mcol */
+ if (part->childtype == PART_CHILD_FACES) {
+ if (n_mcol && ELEM(PART_FROM_FACE, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if (cpa->num != DMCACHE_NOTFOUND) {
+ MFace *mface = modifier->dm->getTessFaceData(modifier->dm, cpa->num, CD_MFACE);
+ MCol *mc = (MCol *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MCOL, vcol_no);
+ mc += cpa->num * 4;
+
+ psys_interpolate_mcol(mc, mface->v4, cpa->fuv, &mcol);
+ n_mcol[0] = (float)mcol.b / 255.0f;
+ n_mcol[1] = (float)mcol.g / 255.0f;
+ n_mcol[2] = (float)mcol.r / 255.0f;
+ }
+ else {
+ n_mcol[0] = 0.0f;
+ n_mcol[1] = 0.0f;
+ n_mcol[2] = 0.0f;
+ }
+ }
+ }
+ else {
+ ParticleData *parent = particlesystem->particles + cpa->parent;
+ num = parent->num_dmcache;
+
+ if (num == DMCACHE_NOTFOUND)
+ if (parent->num < modifier->dm->getNumTessFaces(modifier->dm))
+ num = parent->num;
+
+ if (n_mcol && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if (num != DMCACHE_NOTFOUND) {
+ MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
+ MCol *mc = (MCol *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MCOL, vcol_no);
+ mc += num * 4;
+
+ psys_interpolate_mcol(mc, mface->v4, parent->fuv, &mcol);
+ n_mcol[0] = (float)mcol.b / 255.0f;
+ n_mcol[1] = (float)mcol.g / 255.0f;
+ n_mcol[2] = (float)mcol.r / 255.0f;
+ }
+ else {
+ n_mcol[0] = 0.0f;
+ n_mcol[1] = 0.0f;
+ n_mcol[2] = 0.0f;
+ }
+ }
+ }
+ }
+}
+
+static void rna_ParticleSystem_set_resolution(ParticleSystem *particlesystem, Scene *scene, Object *object, int resolution)
+{
+ if (resolution == eModifierMode_Render) {
+ ParticleSystemModifierData *psmd = psys_get_modifier(object, particlesystem);
+ float mat[4][4];
+
+ unit_m4(mat);
+
+ psys_render_set(object, particlesystem, mat, mat, 1, 1, 0.f);
+ psmd->flag &= ~eParticleSystemFlag_psys_updated;
+ particle_system_update(scene, object, particlesystem);
+ }
+ else {
+ if (particlesystem->renderdata)
+ psys_render_restore(object, particlesystem);
+ }
+}
+
static void particle_recalc(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr, short flag)
{
if (ptr->type == &RNA_ParticleSystem) {
@@ -260,7 +621,7 @@ static void rna_Particle_redo(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_Particle_redo_dependency(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
rna_Particle_redo(bmain, scene, ptr);
}
@@ -297,7 +658,7 @@ static ParticleSystem *rna_particle_system_for_target(Object *ob, ParticleTarget
return NULL;
}
-static void rna_Particle_target_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Particle_target_reset(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
if (ptr->type == &RNA_ParticleTarget) {
Object *ob = (Object *)ptr->id.data;
@@ -325,7 +686,7 @@ static void rna_Particle_target_reset(Main *bmain, Scene *scene, PointerRNA *ptr
psys->recalc = PSYS_RECALC_RESET;
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
}
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
@@ -905,6 +1266,7 @@ static void rna_def_particle_hair_key(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ FunctionRNA *func;
srna = RNA_def_struct(brna, "ParticleHairKey", NULL);
RNA_def_struct_sdna(srna, "HairKey");
@@ -923,11 +1285,24 @@ static void rna_def_particle_hair_key(BlenderRNA *brna)
RNA_def_property_float_funcs(prop, "rna_ParticleHairKey_location_object_get",
"rna_ParticleHairKey_location_object_set", NULL);
- prop = RNA_def_property(srna, "co_hair_space", PROP_FLOAT, PROP_TRANSLATION);
+ prop = RNA_def_property(srna, "co_local", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_float_sdna(prop, NULL, "co");
RNA_def_property_ui_text(prop, "Location",
- "Location of the hair key in its internal coordinate system, "
+ "Location of the hair key in its local coordinate system, "
"relative to the emitting face");
+
+ /* Aided co func */
+ func = RNA_def_function(srna, "co_object", "rna_ParticleHairKey_co_object");
+ RNA_def_function_ui_description(func, "Obtain hairkey location with particle and modifier data");
+
+ prop = RNA_def_pointer(func, "object", "Object", "", "Object");
+ prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
+ prop = RNA_def_pointer(func, "particle", "Particle", "", "hair particle");
+
+ prop = RNA_def_float_vector(func, "co", 3, NULL, -FLT_MAX, FLT_MAX, "Co",
+ "Exported hairkey location", -1e4, 1e4);
+ RNA_def_property_flag(prop, PROP_THICK_WRAP);
+ RNA_def_function_output(func, prop);
}
static void rna_def_particle_key(BlenderRNA *brna)
@@ -979,6 +1354,7 @@ static void rna_def_particle(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ FunctionRNA *func;
static EnumPropertyItem alive_items[] = {
/*{PARS_KILLED, "KILLED", 0, "Killed", ""}, */
@@ -1083,6 +1459,15 @@ static void rna_def_particle(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Alive State", "");
/* short rt2; */
+
+/* UVs */
+ func = RNA_def_function(srna, "uv_on_emitter", "rna_Particle_uv_on_emitter");
+ RNA_def_function_ui_description(func, "Obtain uv for particle on derived mesh");
+ prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
+ prop = RNA_def_property(func, "uv", PROP_FLOAT, PROP_COORDS);
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_flag(prop, PROP_THICK_WRAP);
+ RNA_def_function_output(func, prop);
}
static void rna_def_particle_dupliweight(BlenderRNA *brna)
@@ -1112,12 +1497,25 @@ static void rna_def_fluid_settings(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
-
+
+ static EnumPropertyItem sph_solver_items[] = {
+ {SPH_SOLVER_DDR, "DDR", 0, "Double-Density", "An artistic solver with strong surface tension effects (original)"},
+ {SPH_SOLVER_CLASSICAL, "CLASSICAL", 0, "Classical", "A more physically-accurate solver"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "SPHFluidSettings", NULL);
RNA_def_struct_path_func(srna, "rna_SPHFluidSettings_path");
RNA_def_struct_ui_text(srna, "SPH Fluid Settings", "Settings for particle fluids physics");
-
+
/* Fluid settings */
+ prop = RNA_def_property(srna, "solver", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "solver");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_enum_items(prop, sph_solver_items);
+ RNA_def_property_ui_text(prop, "SPH Solver", "The code used to calculate internal forces on particles");
+ RNA_def_property_update(prop, 0, "rna_Particle_reset");
+
prop = RNA_def_property(srna, "spring_force", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "spring_k");
RNA_def_property_range(prop, 0.0f, 100.0f);
@@ -1186,9 +1584,9 @@ static void rna_def_fluid_settings(BlenderRNA *brna)
/* Double density relaxation */
prop = RNA_def_property(srna, "stiffness", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "stiffness_k");
- RNA_def_property_range(prop, 0.0f, 100.0f);
+ RNA_def_property_range(prop, 0.0f, 1000.0f);
RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
- RNA_def_property_ui_text(prop, "Stiffness", "How incompressible the fluid is");
+ RNA_def_property_ui_text(prop, "Stiffness", "How incompressible the fluid is (speed of sound)");
RNA_def_property_update(prop, 0, "rna_Particle_reset");
prop = RNA_def_property(srna, "repulsion", PROP_FLOAT, PROP_NONE);
@@ -1201,7 +1599,7 @@ static void rna_def_fluid_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "rest_density", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "rest_density");
- RNA_def_property_range(prop, 0.0f, 100.0f);
+ RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_ui_range(prop, 0.0f, 2.0f, 1, 3);
RNA_def_property_ui_text(prop, "Rest Density", "Fluid rest density");
RNA_def_property_update(prop, 0, "rna_Particle_reset");
@@ -1538,14 +1936,6 @@ static void rna_def_particle_settings(BlenderRNA *brna)
};
/*TODO: names, tooltips */
-#if 0
- static EnumPropertyItem rot_from_items[] = {
- {PART_ROT_KEYS, "KEYS", 0, "keys", ""},
- {PART_ROT_ZINCR, "ZINCR", 0, "zincr", ""},
- {PART_ROT_IINCR, "IINCR", 0, "iincr", ""},
- {0, NULL, 0, NULL, NULL}
- };
-#endif
static EnumPropertyItem integrator_type_items[] = {
{PART_INT_EULER, "EULER", 0, "Euler", ""},
{PART_INT_VERLET, "VERLET", 0, "Verlet", ""},
@@ -1947,15 +2337,6 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Material", "Material used for the particles");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- /* not used anywhere, why is this in DNA??? */
-#if 0
- prop = RNA_def_property(srna, "rotate_from", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "rotfrom");
- RNA_def_property_enum_items(prop, rot_from_items);
- RNA_def_property_ui_text(prop, "Rotate From", "");
-#endif
-
prop = RNA_def_property(srna, "integrator", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, integrator_type_items);
RNA_def_property_ui_text(prop, "Integration",
@@ -2129,11 +2510,11 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Particle_reset");
prop = RNA_def_property(srna, "courant_target", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.01, 10);
- RNA_def_property_float_default(prop, 0.2);
+ RNA_def_property_range(prop, 0.0001, 10);
+ RNA_def_property_float_default(prop, 0.1);
RNA_def_property_ui_text(prop, "Adaptive Subframe Threshold",
"The relative distance a particle can move before requiring more subframes "
- "(target Courant number); 0.1-0.3 is the recommended range");
+ "(target Courant number); 0.01-0.3 is the recommended range");
RNA_def_property_update(prop, 0, "rna_Particle_reset");
prop = RNA_def_property(srna, "jitter_factor", PROP_FLOAT, PROP_NONE);
@@ -2281,7 +2662,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
/* physical properties */
prop = RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.001f, 100000.0f);
+ RNA_def_property_range(prop, 0.00000001f, 100000.0f);
RNA_def_property_ui_range(prop, 0.01, 100, 1, 3);
RNA_def_property_ui_text(prop, "Mass", "Mass of the particles");
RNA_def_property_update(prop, 0, "rna_Particle_reset");
@@ -2510,7 +2891,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_float_funcs(prop, "rna_PartSetting_linelentail_get", "rna_PartSetting_linelentail_set", NULL);
RNA_def_property_range(prop, 0.0f, 100000.0f);
RNA_def_property_ui_range(prop, 0.0f, 10.0f, 0.1, 3);
- RNA_def_property_ui_text(prop, "Back", "Length of the line's tail");
+ RNA_def_property_ui_text(prop, "Tail", "Length of the line's tail");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
prop = RNA_def_property(srna, "line_length_head", PROP_FLOAT, PROP_NONE);
@@ -2683,6 +3064,13 @@ static void rna_def_particle_system(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ FunctionRNA *func;
+
+ static EnumPropertyItem resolution_items[] = {
+ {eModifierMode_Realtime, "PREVIEW", 0, "Preview", "Apply modifier preview settings"},
+ {eModifierMode_Render, "RENDER", 0, "Render", "Apply modifier render settings"},
+ {0, NULL, 0, NULL, NULL}
+ };
srna = RNA_def_struct(brna, "ParticleSystem", NULL);
RNA_def_struct_ui_text(srna, "Particle System", "Particle system in an object");
@@ -2780,7 +3168,6 @@ static void rna_def_particle_system(BlenderRNA *brna)
"rna_ParticleSystem_active_particle_target_index_range");
RNA_def_property_ui_text(prop, "Active Particle Target Index", "");
-
/* billboard */
prop = RNA_def_property(srna, "billboard_normal_uv", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "bb_uvname[0]");
@@ -2982,6 +3369,52 @@ static void rna_def_particle_system(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_struct_path_func(srna, "rna_ParticleSystem_path");
+
+ /* set viewport or render resolution */
+ func = RNA_def_function(srna, "set_resolution", "rna_ParticleSystem_set_resolution");
+ RNA_def_function_ui_description(func, "Set the resolution to use for the number of particles");
+ prop = RNA_def_pointer(func, "scene", "Scene", "", "Scene");
+ prop = RNA_def_pointer(func, "object", "Object", "", "Object");
+ prop = RNA_def_enum(func, "resolution", resolution_items, 0, "", "Resolution settings to apply");
+
+ /* extract cached hair location data */
+ func = RNA_def_function(srna, "co_hair", "rna_ParticleSystem_co_hair");
+ RNA_def_function_ui_description(func, "Obtain cache hair data");
+
+ prop = RNA_def_pointer(func, "object", "Object", "", "Object");
+ prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
+ prop = RNA_def_int(func, "particle_no", 0, INT_MIN, INT_MAX, "Particle no", "", INT_MIN, INT_MAX);
+ prop = RNA_def_int(func, "step", 0, INT_MIN, INT_MAX, "step no", "", INT_MIN, INT_MAX);
+
+ prop = RNA_def_float_vector(func, "co", 3, NULL, -FLT_MAX, FLT_MAX, "Co",
+ "Exported hairkey location", -1e4, 1e4);
+ RNA_def_property_flag(prop, PROP_THICK_WRAP);
+ RNA_def_function_output(func, prop);
+
+ /* extract hair UVs */
+ func = RNA_def_function(srna, "uv_on_emitter", "rna_ParticleSystem_uv_on_emitter");
+ RNA_def_function_ui_description(func, "Obtain uv for all particles");
+ prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
+ prop = RNA_def_pointer(func, "particle", "Particle", "", "Particle");
+ prop = RNA_def_int(func, "particle_no", 0, INT_MIN, INT_MAX, "Particle no", "", INT_MIN, INT_MAX);
+ prop = RNA_def_int(func, "uv_no", 0, INT_MIN, INT_MAX, "UV no", "", INT_MIN, INT_MAX);
+ prop = RNA_def_property(func, "uv", PROP_FLOAT, PROP_COORDS);
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_flag(prop, PROP_THICK_WRAP);
+ RNA_def_function_output(func, prop);
+
+ /* extract hair mcols */
+ func = RNA_def_function(srna, "mcol_on_emitter", "rna_ParticleSystem_mcol_on_emitter");
+ RNA_def_function_ui_description(func, "Obtain mcol for all particles");
+ prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
+ prop = RNA_def_pointer(func, "particle", "Particle", "", "Particle");
+ prop = RNA_def_int(func, "particle_no", 0, INT_MIN, INT_MAX, "Particle no", "", INT_MIN, INT_MAX);
+ prop = RNA_def_int(func, "vcol_no", 0, INT_MIN, INT_MAX, "vcol no", "", INT_MIN, INT_MAX);
+ prop = RNA_def_property(func, "mcol", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_flag(prop, PROP_THICK_WRAP);
+ RNA_def_function_output(func, prop);
+
}
void RNA_def_particle(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index 28d1de2c601..6a1b3d4cfc5 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -159,7 +159,7 @@ static void rna_BoneGroup_name_set(PointerRNA *ptr, const char *value)
BLI_uniquename(&ob->pose->agroups, agrp, "Group", '.', offsetof(bActionGroup, name), sizeof(agrp->name));
}
-static IDProperty *rna_PoseBone_idprops(PointerRNA *ptr, int create)
+static IDProperty *rna_PoseBone_idprops(PointerRNA *ptr, bool create)
{
bPoseChannel *pchan = ptr->data;
@@ -187,13 +187,13 @@ static void rna_Pose_ik_solver_set(struct PointerRNA *ptr, int value)
}
}
-static void rna_Pose_ik_solver_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Pose_ik_solver_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
Object *ob = ptr->id.data;
bPose *pose = ptr->data;
pose->flag |= POSE_RECALC; /* checks & sorts pose channels */
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
BKE_pose_update_constraint_flags(pose);
@@ -444,7 +444,7 @@ static void rna_pose_bgroup_name_index_set(PointerRNA *ptr, const char *value, s
int a;
for (a = 1, grp = pose->agroups.first; grp; grp = grp->next, a++) {
- if (strcmp(grp->name, value) == 0) {
+ if (STREQ(grp->name, value)) {
*index = a;
return;
}
@@ -459,7 +459,7 @@ static void rna_pose_pgroup_name_set(PointerRNA *ptr, const char *value, char *r
bActionGroup *grp;
for (grp = pose->agroups.first; grp; grp = grp->next) {
- if (strcmp(grp->name, value) == 0) {
+ if (STREQ(grp->name, value)) {
BLI_strncpy(result, value, maxlen);
return;
}
@@ -472,14 +472,14 @@ static void rna_pose_pgroup_name_set(PointerRNA *ptr, const char *value, char *r
static PointerRNA rna_PoseChannel_active_constraint_get(PointerRNA *ptr)
{
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
- bConstraint *con = constraints_get_active(&pchan->constraints);
+ bConstraint *con = BKE_constraints_get_active(&pchan->constraints);
return rna_pointer_inherit_refine(ptr, &RNA_Constraint, con);
}
static void rna_PoseChannel_active_constraint_set(PointerRNA *ptr, PointerRNA value)
{
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
- constraints_set_active(&pchan->constraints, (bConstraint *)value.data);
+ BKE_constraints_set_active(&pchan->constraints, (bConstraint *)value.data);
}
static bConstraint *rna_PoseChannel_constraints_new(bPoseChannel *pchan, int type)
@@ -487,7 +487,7 @@ static bConstraint *rna_PoseChannel_constraints_new(bPoseChannel *pchan, int typ
/*WM_main_add_notifier(NC_OBJECT|ND_CONSTRAINT|NA_ADDED, object); */
/* TODO, pass object also */
/* TODO, new pose bones don't have updated draw flags */
- return add_pose_constraint(NULL, pchan, NULL, type);
+ return BKE_add_pose_constraint(NULL, pchan, NULL, type);
}
static void rna_PoseChannel_constraints_remove(ID *id, bPoseChannel *pchan, ReportList *reports, PointerRNA *con_ptr)
@@ -501,12 +501,12 @@ static void rna_PoseChannel_constraints_remove(ID *id, bPoseChannel *pchan, Repo
return;
}
- remove_constraint(&pchan->constraints, con);
+ BKE_remove_constraint(&pchan->constraints, con);
RNA_POINTER_INVALIDATE(con_ptr);
ED_object_constraint_update(ob);
- constraints_set_active(&pchan->constraints, NULL); /* XXX, is this really needed? - Campbell */
+ BKE_constraints_set_active(&pchan->constraints, NULL); /* XXX, is this really needed? - Campbell */
WM_main_add_notifier(NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, id);
@@ -786,14 +786,14 @@ static void rna_def_pose_channel(BlenderRNA *brna)
RNA_def_property_editable_array_func(prop, "rna_PoseChannel_location_editable");
RNA_def_property_ui_text(prop, "Location", "");
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
- RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_IK_update");
prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "size");
RNA_def_property_editable_array_func(prop, "rna_PoseChannel_scale_editable");
RNA_def_property_float_array_default(prop, default_scale);
RNA_def_property_ui_text(prop, "Scale", "");
- RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_IK_update");
prop = RNA_def_property(srna, "rotation_quaternion", PROP_FLOAT, PROP_QUATERNION);
RNA_def_property_float_sdna(prop, NULL, "quat");
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index 46b22cd0963..8cf352311f7 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -28,6 +28,7 @@
#include "DNA_scene_types.h"
+#include "BLI_utildefines.h"
#include "BLI_path_util.h"
#include "RNA_define.h"
@@ -137,7 +138,7 @@ static void engine_update_script_node(RenderEngine *engine, struct bNodeTree *nt
FunctionRNA *func;
RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr);
- RNA_pointer_create((ID*)ntree, &RNA_Node, node, &nodeptr);
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &nodeptr);
func = &rna_RenderEngine_update_script_node_func;
RNA_parameter_list_create(&list, &ptr, func);
@@ -196,7 +197,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo
et = MEM_callocN(sizeof(RenderEngineType), "python render engine");
memcpy(et, &dummyet, sizeof(dummyet));
- et->ext.srna = RNA_def_struct(&BLENDER_RNA, et->idname, "RenderEngine");
+ et->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, et->idname, &RNA_RenderEngine);
et->ext.data = data;
et->ext.call = call;
et->ext.free = free;
@@ -225,6 +226,20 @@ static StructRNA *rna_RenderEngine_refine(PointerRNA *ptr)
return (engine->type && engine->type->ext.srna) ? engine->type->ext.srna : &RNA_RenderEngine;
}
+static PointerRNA rna_RenderEngine_render_get(PointerRNA *ptr)
+{
+ RenderEngine *engine = (RenderEngine *)ptr->data;
+
+ if (engine->re) {
+ RenderData *r = RE_engine_get_render_data(engine->re);
+
+ return rna_pointer_inherit_refine(ptr, &RNA_RenderSettings, r);
+ }
+ else {
+ return rna_pointer_inherit_refine(ptr, &RNA_RenderSettings, NULL);
+ }
+}
+
static void rna_RenderResult_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
RenderResult *rr = (RenderResult *)ptr->data;
@@ -299,19 +314,19 @@ static void rna_def_render_engine(BlenderRNA *brna)
/* final render callbacks */
func = RNA_def_function(srna, "update", NULL);
RNA_def_function_ui_description(func, "Export scene data for render");
- RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
RNA_def_pointer(func, "data", "BlendData", "", "");
RNA_def_pointer(func, "scene", "Scene", "", "");
func = RNA_def_function(srna, "render", NULL);
RNA_def_function_ui_description(func, "Render scene into an image");
- RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
RNA_def_pointer(func, "scene", "Scene", "", "");
/* viewport render callbacks */
func = RNA_def_function(srna, "view_update", NULL);
RNA_def_function_ui_description(func, "Update on data changes for viewport render");
- RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
RNA_def_pointer(func, "context", "Context", "", "");
func = RNA_def_function(srna, "view_draw", NULL);
@@ -406,13 +421,22 @@ static void rna_def_render_engine(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "resolution_y");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ /* Render Data */
+ prop = RNA_def_property(srna, "render", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "RenderSettings");
+ RNA_def_property_pointer_funcs(prop, "rna_RenderEngine_render_get", NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Render Data", "");
+
+ prop = RNA_def_property(srna, "use_highlight_tiles", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RE_ENGINE_HIGHLIGHT_TILES);
+
/* registration */
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->idname");
RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
- prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_TRANSLATE);
+ prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->name");
RNA_def_property_flag(prop, PROP_REGISTER);
diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c
new file mode 100644
index 00000000000..171bc702bc5
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_rigidbody.c
@@ -0,0 +1,1150 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 2013, Joshua Leung, Sergej Reich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file rna_rigidbody.c
+ * \ingroup rna
+ * \brief RNA property definitions for Rigid Body datatypes
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "RNA_define.h"
+
+#include "rna_internal.h"
+
+#include "DNA_group_types.h"
+#include "DNA_object_types.h"
+#include "DNA_rigidbody_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "WM_types.h"
+
+/* roles of objects in RigidBody Sims */
+EnumPropertyItem rigidbody_ob_type_items[] = {
+ {RBO_TYPE_ACTIVE, "ACTIVE", 0, "Active", "Object is directly controlled by simulation results"},
+ {RBO_TYPE_PASSIVE, "PASSIVE", 0, "Passive", "Object is directly controlled by animation system"},
+ {0, NULL, 0, NULL, NULL}};
+
+/* collision shapes of objects in rigid body sim */
+EnumPropertyItem rigidbody_ob_shape_items[] = {
+ {RB_SHAPE_BOX, "BOX", ICON_MESH_CUBE, "Box", "Box-like shapes (i.e. cubes), including planes (i.e. ground planes)"},
+ {RB_SHAPE_SPHERE, "SPHERE", ICON_MESH_UVSPHERE, "Sphere", ""},
+ {RB_SHAPE_CAPSULE, "CAPSULE", ICON_OUTLINER_OB_META, "Capsule", ""},
+ {RB_SHAPE_CYLINDER, "CYLINDER", ICON_MESH_CYLINDER, "Cylinder", ""},
+ {RB_SHAPE_CONE, "CONE", ICON_MESH_CONE, "Cone", ""},
+ {RB_SHAPE_CONVEXH, "CONVEX_HULL", ICON_MESH_ICOSPHERE, "Convex Hull",
+ "A mesh-like surface encompassing (i.e. shrinkwrap over) all vertices (best results with "
+ "fewer vertices)"},
+ {RB_SHAPE_TRIMESH, "MESH", ICON_MESH_MONKEY, "Mesh",
+ "Mesh consisting of triangles only, allowing for more detailed interactions than convex hulls"},
+ {0, NULL, 0, NULL, NULL}};
+
+/* collision shapes of constraints in rigid body sim */
+EnumPropertyItem rigidbody_con_type_items[] = {
+ {RBC_TYPE_FIXED, "FIXED", ICON_NONE, "Fixed", "Glue rigid bodies together"},
+ {RBC_TYPE_POINT, "POINT", ICON_NONE, "Point", "Constrain rigid bodies to move around common pivot point"},
+ {RBC_TYPE_HINGE, "HINGE", ICON_NONE, "Hinge", "Restrict rigid body rotation to one axis"},
+ {RBC_TYPE_SLIDER, "SLIDER", ICON_NONE, "Slider", "Restrict rigid body translation to one axis"},
+ {RBC_TYPE_PISTON, "PISTON", ICON_NONE, "Piston", "Restrict rigid body translation and rotation to one axis"},
+ {RBC_TYPE_6DOF, "GENERIC", ICON_NONE, "Generic", "Restrict translation and rotation to specified axes"},
+ {RBC_TYPE_6DOF_SPRING, "GENERIC_SPRING", ICON_NONE, "Generic Spring",
+ "Restrict translation and rotation to specified axes with springs"},
+ {RBC_TYPE_MOTOR, "MOTOR", ICON_NONE, "Motor", "Drive rigid body around or along an axis"},
+ {0, NULL, 0, NULL, NULL}};
+
+
+#ifdef RNA_RUNTIME
+
+#ifdef WITH_BULLET
+# include "RBI_api.h"
+#endif
+
+#include "BKE_depsgraph.h"
+#include "BKE_rigidbody.h"
+
+#define RB_FLAG_SET(dest, value, flag) { \
+ if (value) \
+ dest |= flag; \
+ else \
+ dest &= ~flag; \
+}
+
+
+/* ******************************** */
+
+static void rna_RigidBodyWorld_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ RigidBodyWorld *rbw = (RigidBodyWorld *)ptr->data;
+
+ BKE_rigidbody_cache_reset(rbw);
+}
+
+static char *rna_RigidBodyWorld_path(PointerRNA *ptr)
+{
+ return BLI_sprintfN("rigidbody_world");
+}
+
+static void rna_RigidBodyWorld_num_solver_iterations_set(PointerRNA *ptr, int value)
+{
+ RigidBodyWorld *rbw = (RigidBodyWorld *)ptr->data;
+
+ rbw->num_solver_iterations = value;
+
+#ifdef WITH_BULLET
+ if (rbw->physics_world) {
+ RB_dworld_set_solver_iterations(rbw->physics_world, value);
+ }
+#endif
+}
+
+static void rna_RigidBodyWorld_split_impulse_set(PointerRNA *ptr, int value)
+{
+ RigidBodyWorld *rbw = (RigidBodyWorld *)ptr->data;
+
+ RB_FLAG_SET(rbw->flag, value, RBW_FLAG_USE_SPLIT_IMPULSE);
+
+#ifdef WITH_BULLET
+ if (rbw->physics_world) {
+ RB_dworld_set_split_impulse(rbw->physics_world, value);
+ }
+#endif
+}
+
+/* ******************************** */
+
+static void rna_RigidBodyOb_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ RigidBodyWorld *rbw = scene->rigidbody_world;
+
+ BKE_rigidbody_cache_reset(rbw);
+}
+
+static void rna_RigidBodyOb_shape_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ RigidBodyWorld *rbw = scene->rigidbody_world;
+ RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+
+ BKE_rigidbody_cache_reset(rbw);
+ if (rbo->physics_shape)
+ rbo->flag |= RBO_FLAG_NEEDS_RESHAPE;
+}
+
+static char *rna_RigidBodyOb_path(PointerRNA *ptr)
+{
+ /* NOTE: this hardcoded path should work as long as only Objects have this */
+ return BLI_sprintfN("rigid_body");
+}
+
+static void rna_RigidBodyOb_type_set(PointerRNA *ptr, int value)
+{
+ RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+
+ rbo->type = value;
+ rbo->flag |= RBO_FLAG_NEEDS_VALIDATE;
+}
+
+static void rna_RigidBodyOb_disabled_set(PointerRNA *ptr, int value)
+{
+ RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+
+ RB_FLAG_SET(rbo->flag, !value, RBO_FLAG_DISABLED);
+
+#ifdef WITH_BULLET
+ /* update kinematic state if necessary - only needed for active bodies */
+ if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
+ RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
+ RB_body_set_kinematic_state(rbo->physics_object, !value);
+ rbo->flag |= RBO_FLAG_NEEDS_VALIDATE;
+ }
+#endif
+}
+
+static void rna_RigidBodyOb_mass_set(PointerRNA *ptr, float value)
+{
+ RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+
+ rbo->mass = value;
+
+#ifdef WITH_BULLET
+ /* only active bodies need mass update */
+ if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
+ RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
+ }
+#endif
+}
+
+static void rna_RigidBodyOb_friction_set(PointerRNA *ptr, float value)
+{
+ RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+
+ rbo->friction = value;
+
+#ifdef WITH_BULLET
+ if (rbo->physics_object) {
+ RB_body_set_friction(rbo->physics_object, value);
+ }
+#endif
+}
+
+static void rna_RigidBodyOb_restitution_set(PointerRNA *ptr, float value)
+{
+ RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+
+ rbo->restitution = value;
+#ifdef WITH_BULLET
+ if (rbo->physics_object) {
+ RB_body_set_restitution(rbo->physics_object, value);
+ }
+#endif
+}
+
+static void rna_RigidBodyOb_collision_margin_set(PointerRNA *ptr, float value)
+{
+ RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+
+ rbo->margin = value;
+
+#ifdef WITH_BULLET
+ if (rbo->physics_shape) {
+ RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo));
+ }
+#endif
+}
+
+static void rna_RigidBodyOb_collision_groups_set(PointerRNA *ptr, const int *values)
+{
+ RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+ int i;
+
+ for (i = 0; i < 20; i++) {
+ if (values[i])
+ rbo->col_groups |= (1 << i);
+ else
+ rbo->col_groups &= ~(1 << i);
+ }
+ rbo->flag |= RBO_FLAG_NEEDS_VALIDATE;
+}
+
+static void rna_RigidBodyOb_kinematic_state_set(PointerRNA *ptr, int value)
+{
+ RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+
+ RB_FLAG_SET(rbo->flag, value, RBO_FLAG_KINEMATIC);
+
+#ifdef WITH_BULLET
+ /* update kinematic state if necessary */
+ if (rbo->physics_object) {
+ RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
+ RB_body_set_kinematic_state(rbo->physics_object, value);
+ rbo->flag |= RBO_FLAG_NEEDS_VALIDATE;
+ }
+#endif
+}
+
+static void rna_RigidBodyOb_activation_state_set(PointerRNA *ptr, int value)
+{
+ RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+
+ RB_FLAG_SET(rbo->flag, value, RBO_FLAG_USE_DEACTIVATION);
+
+#ifdef WITH_BULLET
+ /* update activation state if necessary - only active bodies can be deactivated */
+ if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
+ RB_body_set_activation_state(rbo->physics_object, value);
+ }
+#endif
+}
+
+static void rna_RigidBodyOb_linear_sleepThresh_set(PointerRNA *ptr, float value)
+{
+ RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+
+ rbo->lin_sleep_thresh = value;
+
+#ifdef WITH_BULLET
+ /* only active bodies need sleep threshold update */
+ if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
+ RB_body_set_linear_sleep_thresh(rbo->physics_object, value);
+ }
+#endif
+}
+
+static void rna_RigidBodyOb_angular_sleepThresh_set(PointerRNA *ptr, float value)
+{
+ RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+
+ rbo->ang_sleep_thresh = value;
+
+#ifdef WITH_BULLET
+ /* only active bodies need sleep threshold update */
+ if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
+ RB_body_set_angular_sleep_thresh(rbo->physics_object, value);
+ }
+#endif
+}
+
+static void rna_RigidBodyOb_linear_damping_set(PointerRNA *ptr, float value)
+{
+ RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+
+ rbo->lin_damping = value;
+
+#ifdef WITH_BULLET
+ /* only active bodies need damping update */
+ if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
+ RB_body_set_linear_damping(rbo->physics_object, value);
+ }
+#endif
+}
+
+static void rna_RigidBodyOb_angular_damping_set(PointerRNA *ptr, float value)
+{
+ RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+
+ rbo->ang_damping = value;
+
+#ifdef WITH_BULLET
+ /* only active bodies need damping update */
+ if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
+ RB_body_set_angular_damping(rbo->physics_object, value);
+ }
+#endif
+}
+
+static char *rna_RigidBodyCon_path(PointerRNA *ptr)
+{
+ /* NOTE: this hardcoded path should work as long as only Objects have this */
+ return BLI_sprintfN("rigid_body_constraint");
+}
+
+static void rna_RigidBodyCon_type_set(PointerRNA *ptr, int value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ rbc->type = value;
+ rbc->flag |= RBC_FLAG_NEEDS_VALIDATE;
+}
+
+static void rna_RigidBodyCon_enabled_set(PointerRNA *ptr, int value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ RB_FLAG_SET(rbc->flag, value, RBC_FLAG_ENABLED);
+
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint) {
+ RB_constraint_set_enabled(rbc->physics_constraint, value);
+ }
+#endif
+}
+
+static void rna_RigidBodyCon_disable_collisions_set(PointerRNA *ptr, int value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ RB_FLAG_SET(rbc->flag, value, RBC_FLAG_DISABLE_COLLISIONS);
+
+ rbc->flag |= RBC_FLAG_NEEDS_VALIDATE;
+}
+
+static void rna_RigidBodyCon_use_breaking_set(PointerRNA *ptr, int value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ if (value) {
+ rbc->flag |= RBC_FLAG_USE_BREAKING;
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint) {
+ RB_constraint_set_breaking_threshold(rbc->physics_constraint, rbc->breaking_threshold);
+ }
+#endif
+ }
+ else {
+ rbc->flag &= ~RBC_FLAG_USE_BREAKING;
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint) {
+ RB_constraint_set_breaking_threshold(rbc->physics_constraint, FLT_MAX);
+ }
+#endif
+ }
+}
+
+static void rna_RigidBodyCon_breaking_threshold_set(PointerRNA *ptr, float value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ rbc->breaking_threshold = value;
+
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint && (rbc->flag & RBC_FLAG_USE_BREAKING)) {
+ RB_constraint_set_breaking_threshold(rbc->physics_constraint, value);
+ }
+#endif
+}
+
+static void rna_RigidBodyCon_override_solver_iterations_set(PointerRNA *ptr, int value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ if (value) {
+ rbc->flag |= RBC_FLAG_OVERRIDE_SOLVER_ITERATIONS;
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint) {
+ RB_constraint_set_solver_iterations(rbc->physics_constraint, rbc->num_solver_iterations);
+ }
+#endif
+ }
+ else {
+ rbc->flag &= ~RBC_FLAG_OVERRIDE_SOLVER_ITERATIONS;
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint) {
+ RB_constraint_set_solver_iterations(rbc->physics_constraint, -1);
+ }
+#endif
+ }
+}
+
+static void rna_RigidBodyCon_num_solver_iterations_set(PointerRNA *ptr, int value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ rbc->num_solver_iterations = value;
+
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint && (rbc->flag & RBC_FLAG_OVERRIDE_SOLVER_ITERATIONS)) {
+ RB_constraint_set_solver_iterations(rbc->physics_constraint, value);
+ }
+#endif
+}
+
+static void rna_RigidBodyCon_spring_stiffness_x_set(PointerRNA *ptr, float value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ rbc->spring_stiffness_x = value;
+
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_X)) {
+ RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, value);
+ }
+#endif
+}
+
+static void rna_RigidBodyCon_spring_stiffness_y_set(PointerRNA *ptr, float value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ rbc->spring_stiffness_y = value;
+
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Y)) {
+ RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, value);
+ }
+#endif
+}
+
+static void rna_RigidBodyCon_spring_stiffness_z_set(PointerRNA *ptr, float value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ rbc->spring_stiffness_z = value;
+
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Z)) {
+ RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, value);
+ }
+#endif
+}
+
+static void rna_RigidBodyCon_spring_damping_x_set(PointerRNA *ptr, float value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ rbc->spring_damping_x = value;
+
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_X)) {
+ RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, value);
+ }
+#endif
+}
+
+static void rna_RigidBodyCon_spring_damping_y_set(PointerRNA *ptr, float value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ rbc->spring_damping_y = value;
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Y)) {
+ RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, value);
+ }
+#endif
+}
+
+static void rna_RigidBodyCon_spring_damping_z_set(PointerRNA *ptr, float value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ rbc->spring_damping_z = value;
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Z)) {
+ RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, value);
+ }
+#endif
+}
+
+static void rna_RigidBodyCon_motor_lin_max_impulse_set(PointerRNA *ptr, float value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ rbc->motor_lin_max_impulse = value;
+
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint && rbc->type == RBC_TYPE_MOTOR) {
+ RB_constraint_set_max_impulse_motor(rbc->physics_constraint, value, rbc->motor_ang_max_impulse);
+ }
+#endif
+}
+
+static void rna_RigidBodyCon_use_motor_lin_set(PointerRNA *ptr, int value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ RB_FLAG_SET(rbc->flag, value, RBC_FLAG_USE_MOTOR_LIN);
+
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint) {
+ RB_constraint_set_enable_motor(rbc->physics_constraint, rbc->flag & RBC_FLAG_USE_MOTOR_LIN, rbc->flag & RBC_FLAG_USE_MOTOR_ANG);
+ }
+#endif
+}
+
+static void rna_RigidBodyCon_use_motor_ang_set(PointerRNA *ptr, int value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ RB_FLAG_SET(rbc->flag, value, RBC_FLAG_USE_MOTOR_ANG);
+
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint) {
+ RB_constraint_set_enable_motor(rbc->physics_constraint, rbc->flag & RBC_FLAG_USE_MOTOR_LIN, rbc->flag & RBC_FLAG_USE_MOTOR_ANG);
+ }
+#endif
+}
+
+static void rna_RigidBodyCon_motor_lin_target_velocity_set(PointerRNA *ptr, float value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ rbc->motor_lin_target_velocity = value;
+
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint && rbc->type == RBC_TYPE_MOTOR) {
+ RB_constraint_set_target_velocity_motor(rbc->physics_constraint, value, rbc->motor_ang_target_velocity);
+ }
+#endif
+}
+
+static void rna_RigidBodyCon_motor_ang_max_impulse_set(PointerRNA *ptr, float value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ rbc->motor_ang_max_impulse = value;
+
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint && rbc->type == RBC_TYPE_MOTOR) {
+ RB_constraint_set_max_impulse_motor(rbc->physics_constraint, rbc->motor_lin_max_impulse, value);
+ }
+#endif
+}
+
+static void rna_RigidBodyCon_motor_ang_target_velocity_set(PointerRNA *ptr, float value)
+{
+ RigidBodyCon *rbc = (RigidBodyCon *)ptr->data;
+
+ rbc->motor_ang_target_velocity = value;
+
+#ifdef WITH_BULLET
+ if (rbc->physics_constraint && rbc->type == RBC_TYPE_MOTOR) {
+ RB_constraint_set_target_velocity_motor(rbc->physics_constraint, rbc->motor_lin_target_velocity, value);
+ }
+#endif
+}
+
+
+#else
+
+static void rna_def_rigidbody_world(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "RigidBodyWorld", NULL);
+ RNA_def_struct_sdna(srna, "RigidBodyWorld");
+ RNA_def_struct_ui_text(srna, "Rigid Body World", "Self-contained rigid body simulation environment and settings");
+ RNA_def_struct_path_func(srna, "rna_RigidBodyWorld_path");
+
+ /* groups */
+ prop = RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Group");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_ui_text(prop, "Group", "Group containing objects participating in this simulation");
+ RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset");
+
+ prop = RNA_def_property(srna, "constraints", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Group");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_ui_text(prop, "Constraints", "Group containing rigid body constraint objects");
+ RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset");
+
+ /* booleans */
+ prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", RBW_FLAG_MUTED);
+ RNA_def_property_ui_text(prop, "Enabled", "Simulation will be evaluated");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ /* time scale */
+ prop = RNA_def_property(srna, "time_scale", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "time_scale");
+ RNA_def_property_range(prop, 0.0f, 100.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_ui_text(prop, "Time Scale", "Change the speed of the simulation");
+ RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset");
+
+ /* timestep */
+ prop = RNA_def_property(srna, "steps_per_second", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "steps_per_second");
+ RNA_def_property_range(prop, 1, SHRT_MAX);
+ RNA_def_property_ui_range(prop, 60, 1000, 1, 0);
+ RNA_def_property_int_default(prop, 60);
+ RNA_def_property_ui_text(prop, "Steps Per Second",
+ "Number of simulation steps taken per second (higher values are more accurate "
+ "but slower)");
+ RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset");
+
+ /* constraint solver iterations */
+ prop = RNA_def_property(srna, "num_solver_iterations", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "num_solver_iterations");
+ RNA_def_property_range(prop, 1, 1000);
+ RNA_def_property_ui_range(prop, 10, 100, 1, 0);
+ RNA_def_property_int_default(prop, 10);
+ RNA_def_property_int_funcs(prop, NULL, "rna_RigidBodyWorld_num_solver_iterations_set", NULL);
+ RNA_def_property_ui_text(prop, "Solver Iterations",
+ "Number of constraint solver iterations made per simulation step (higher values are more "
+ "accurate but slower)");
+ RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset");
+
+ /* split impulse */
+ prop = RNA_def_property(srna, "use_split_impulse", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBW_FLAG_USE_SPLIT_IMPULSE);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyWorld_split_impulse_set");
+ RNA_def_property_ui_text(prop, "Split Impulse",
+ "Reduce extra velocity that can build up when objects collide (lowers simulation "
+ "stability a little so use only when necessary)");
+ RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset");
+
+ /* cache */
+ prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_pointer_sdna(prop, NULL, "pointcache");
+ RNA_def_property_ui_text(prop, "Point Cache", "");
+
+ /* effector weights */
+ prop = RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "EffectorWeights");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Effector Weights", "");
+}
+
+static void rna_def_rigidbody_object(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+
+ srna = RNA_def_struct(brna, "RigidBodyObject", NULL);
+ RNA_def_struct_sdna(srna, "RigidBodyOb");
+ RNA_def_struct_ui_text(srna, "Rigid Body Object", "Settings for object participating in Rigid Body Simulation");
+ RNA_def_struct_path_func(srna, "rna_RigidBodyOb_path");
+
+ /* Enums */
+ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, rigidbody_ob_type_items);
+ RNA_def_property_enum_funcs(prop, NULL, "rna_RigidBodyOb_type_set", NULL);
+ RNA_def_property_ui_text(prop, "Type", "Role 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");
+
+ /* booleans */
+ prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", RBO_FLAG_DISABLED);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyOb_disabled_set");
+ RNA_def_property_ui_text(prop, "Enabled", "Rigid Body actively participates to the simulation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "collision_shape", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "shape");
+ RNA_def_property_enum_items(prop, rigidbody_ob_shape_items);
+ 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");
+
+ prop = RNA_def_property(srna, "kinematic", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBO_FLAG_KINEMATIC);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyOb_kinematic_state_set");
+ RNA_def_property_ui_text(prop, "Kinematic", "Allow rigid body to be controlled by the animation system");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ /* Physics Parameters */
+ prop = RNA_def_property(srna, "mass", PROP_FLOAT, PROP_UNIT_MASS);
+ RNA_def_property_float_sdna(prop, NULL, "mass");
+ RNA_def_property_range(prop, 0.001f, FLT_MAX); // range must always be positive (and non-zero)
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_mass_set", NULL);
+ RNA_def_property_ui_text(prop, "Mass", "How much the object 'weighs' irrespective of gravity");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ /* Dynamics Parameters - Activation */
+ // TODO: define and figure out how to implement these
+
+ /* Dynamics Parameters - Deactivation */
+ prop = RNA_def_property(srna, "use_deactivation", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBO_FLAG_USE_DEACTIVATION);
+ RNA_def_property_boolean_default(prop, TRUE);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyOb_activation_state_set");
+ RNA_def_property_ui_text(prop, "Enable Deactivation",
+ "Enable deactivation of resting rigid bodies (increases performance and stability "
+ "but can cause glitches)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "start_deactivated", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBO_FLAG_START_DEACTIVATED);
+ RNA_def_property_ui_text(prop, "Start Deactivated", "Deactivate rigid body at the start of the simulation");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "deactivate_linear_velocity", PROP_FLOAT, PROP_UNIT_VELOCITY);
+ RNA_def_property_float_sdna(prop, NULL, "lin_sleep_thresh");
+ RNA_def_property_range(prop, FLT_MIN, FLT_MAX); // range must always be positive (and non-zero)
+ RNA_def_property_float_default(prop, 0.4f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_linear_sleepThresh_set", NULL);
+ RNA_def_property_ui_text(prop, "Linear Velocity Deactivation Threshold",
+ "Linear Velocity below which simulation stops simulating object");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "deactivate_angular_velocity", PROP_FLOAT, PROP_UNIT_VELOCITY);
+ RNA_def_property_float_sdna(prop, NULL, "ang_sleep_thresh");
+ RNA_def_property_range(prop, FLT_MIN, FLT_MAX); // range must always be positive (and non-zero)
+ RNA_def_property_float_default(prop, 0.5f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_angular_sleepThresh_set", NULL);
+ RNA_def_property_ui_text(prop, "Angular Velocity Deactivation Threshold",
+ "Angular Velocity below which simulation stops simulating object");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ /* Dynamics Parameters - Damping Parameters */
+ prop = RNA_def_property(srna, "linear_damping", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "lin_damping");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_float_default(prop, 0.04f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_linear_damping_set", NULL);
+ RNA_def_property_ui_text(prop, "Linear Damping", "Amount of linear velocity that is lost over time");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "angular_damping", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "ang_damping");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_float_default(prop, 0.1f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_angular_damping_set", NULL);
+ RNA_def_property_ui_text(prop, "Angular Damping", "Amount of angular velocity that is lost over time");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ /* Collision Parameters - Surface Parameters */
+ prop = RNA_def_property(srna, "friction", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "friction");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, 3);
+ RNA_def_property_float_default(prop, 0.5f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_friction_set", NULL);
+ RNA_def_property_ui_text(prop, "Friction", "Resistance of object to movement");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "restitution", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "restitution");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, 3);
+ RNA_def_property_float_default(prop, 0.0f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_restitution_set", NULL);
+ RNA_def_property_ui_text(prop, "Restitution",
+ "Tendency of object to bounce after colliding with another "
+ "(0 = stays still, 1 = perfectly elastic)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ /* Collision Parameters - Sensitivity */
+ prop = RNA_def_property(srna, "use_margin", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBO_FLAG_USE_MARGIN);
+ RNA_def_property_boolean_default(prop, FALSE);
+ RNA_def_property_ui_text(prop, "Collision Margin",
+ "Use custom collision margin (some shapes will have a visible gap around them)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_shape_reset");
+
+ prop = RNA_def_property(srna, "collision_margin", PROP_FLOAT, PROP_UNIT_LENGTH);
+ RNA_def_property_float_sdna(prop, NULL, "margin");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.01, 3);
+ RNA_def_property_float_default(prop, 0.04f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_collision_margin_set", NULL);
+ RNA_def_property_ui_text(prop, "Collision Margin",
+ "Threshold of distance near surface where collisions are still considered "
+ "(best results when non-zero)");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_shape_reset");
+
+ prop = RNA_def_property(srna, "collision_groups", PROP_BOOLEAN, PROP_LAYER_MEMBER);
+ RNA_def_property_boolean_sdna(prop, NULL, "col_groups", 1);
+ RNA_def_property_array(prop, 20);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyOb_collision_groups_set");
+ RNA_def_property_ui_text(prop, "Collision Groups", "Collision Groups Rigid Body belongs to");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+ RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
+}
+
+static void rna_def_rigidbody_constraint(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "RigidBodyConstraint", NULL);
+ RNA_def_struct_sdna(srna, "RigidBodyCon");
+ RNA_def_struct_ui_text(srna, "Rigid Body Constraint",
+ "Constraint influencing Objects inside Rigid Body Simulation");
+ RNA_def_struct_path_func(srna, "rna_RigidBodyCon_path");
+
+ /* Enums */
+ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, rigidbody_con_type_items);
+ RNA_def_property_enum_funcs(prop, NULL, "rna_RigidBodyCon_type_set", NULL);
+ RNA_def_property_ui_text(prop, "Type", "Type of Rigid Body Constraint");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_ENABLED);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyCon_enabled_set");
+ RNA_def_property_ui_text(prop, "Enabled", "Enable this constraint");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "disable_collisions", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_DISABLE_COLLISIONS);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyCon_disable_collisions_set");
+ RNA_def_property_ui_text(prop, "Disable Collisions", "Disable collisions between constrained rigid bodies");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "object1", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "ob1");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Object 1", "First Rigid Body Object to be constrained");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "object2", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "ob2");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Object 2", "Second Rigid Body Object to be constrained");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ /* Breaking Threshold */
+ prop = RNA_def_property(srna, "use_breaking", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_BREAKING);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyCon_use_breaking_set");
+ RNA_def_property_ui_text(prop, "Breakable",
+ "Constraint can be broken if it receives an impulse above the threshold");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "breaking_threshold", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "breaking_threshold");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0f, 1000.0f, 100.0, 2);
+ RNA_def_property_float_default(prop, 10.0f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_breaking_threshold_set", NULL);
+ RNA_def_property_ui_text(prop, "Breaking Threshold",
+ "Impulse threshold that must be reached for the constraint to break");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ /* Solver Iterations */
+ prop = RNA_def_property(srna, "override_solver_iterations", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_OVERRIDE_SOLVER_ITERATIONS);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyCon_override_solver_iterations_set");
+ RNA_def_property_ui_text(prop, "Override Solver Iterations",
+ "Override the number of solver iterations for this constraint");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "num_solver_iterations", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "num_solver_iterations");
+ RNA_def_property_range(prop, 1, 1000);
+ RNA_def_property_ui_range(prop, 1, 100, 1, 0);
+ RNA_def_property_int_default(prop, 10);
+ RNA_def_property_int_funcs(prop, NULL, "rna_RigidBodyCon_num_solver_iterations_set", NULL);
+ RNA_def_property_ui_text(prop, "Solver Iterations",
+ "Number of constraint solver iterations made per simulation step (higher values are more "
+ "accurate but slower)");
+ RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
+
+ /* Limits */
+ prop = RNA_def_property(srna, "use_limit_lin_x", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_LIMIT_LIN_X);
+ RNA_def_property_ui_text(prop, "X Axis", "Limit translation on X axis");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "use_limit_lin_y", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_LIMIT_LIN_Y);
+ RNA_def_property_ui_text(prop, "Y Axis", "Limit translation on Y axis");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "use_limit_lin_z", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_LIMIT_LIN_Z);
+ RNA_def_property_ui_text(prop, "Z Axis", "Limit translation on Z axis");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "use_limit_ang_x", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_LIMIT_ANG_X);
+ RNA_def_property_ui_text(prop, "X Angle", "Limit rotation around X axis");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "use_limit_ang_y", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_LIMIT_ANG_Y);
+ RNA_def_property_ui_text(prop, "Y Angle", "Limit rotation around Y axis");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "use_limit_ang_z", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_LIMIT_ANG_Z);
+ RNA_def_property_ui_text(prop, "Z Angle", "Limit rotation around Z axis");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "use_spring_x", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_SPRING_X);
+ RNA_def_property_ui_text(prop, "X Spring", "Enable spring on X axis");
+ RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "use_spring_y", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_SPRING_Y);
+ RNA_def_property_ui_text(prop, "Y Spring", "Enable spring on Y axis");
+ RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "use_spring_z", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_SPRING_Z);
+ RNA_def_property_ui_text(prop, "Z Spring", "Enable spring on Z axis");
+ RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "use_motor_lin", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_MOTOR_LIN);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyCon_use_motor_lin_set");
+ RNA_def_property_ui_text(prop, "Linear Motor", "Enable linear motor");
+ RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "use_motor_ang", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_MOTOR_ANG);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyCon_use_motor_ang_set");
+ RNA_def_property_ui_text(prop, "Angular Motor", "Enable angular motor");
+ RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "limit_lin_x_lower", PROP_FLOAT, PROP_UNIT_LENGTH);
+ RNA_def_property_float_sdna(prop, NULL, "limit_lin_x_lower");
+ RNA_def_property_float_default(prop, -1.0f);
+ RNA_def_property_ui_text(prop, "Lower X Limit", "Lower limit of X axis translation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "limit_lin_x_upper", PROP_FLOAT, PROP_UNIT_LENGTH);
+ RNA_def_property_float_sdna(prop, NULL, "limit_lin_x_upper");
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_ui_text(prop, "Upper X Limit", "Upper limit of X axis translation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "limit_lin_y_lower", PROP_FLOAT, PROP_UNIT_LENGTH);
+ RNA_def_property_float_sdna(prop, NULL, "limit_lin_y_lower");
+ RNA_def_property_float_default(prop, -1.0f);
+ RNA_def_property_ui_text(prop, "Lower Y Limit", "Lower limit of Y axis translation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "limit_lin_y_upper", PROP_FLOAT, PROP_UNIT_LENGTH);
+ RNA_def_property_float_sdna(prop, NULL, "limit_lin_y_upper");
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_ui_text(prop, "Upper Y Limit", "Upper limit of Y axis translation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "limit_lin_z_lower", PROP_FLOAT, PROP_UNIT_LENGTH);
+ RNA_def_property_float_sdna(prop, NULL, "limit_lin_z_lower");
+ RNA_def_property_float_default(prop, -1.0f);
+ RNA_def_property_ui_text(prop, "Lower Z Limit", "Lower limit of Z axis translation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "limit_lin_z_upper", PROP_FLOAT, PROP_UNIT_LENGTH);
+ RNA_def_property_float_sdna(prop, NULL, "limit_lin_z_upper");
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_ui_text(prop, "Upper Z Limit", "Upper limit of Z axis translation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "limit_ang_x_lower", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "limit_ang_x_lower");
+ RNA_def_property_range(prop, -M_PI * 2, M_PI * 2);
+ RNA_def_property_float_default(prop, -M_PI_4);
+ RNA_def_property_ui_text(prop, "Lower X Angle Limit", "Lower limit of X axis rotation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "limit_ang_x_upper", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "limit_ang_x_upper");
+ RNA_def_property_range(prop, -M_PI * 2, M_PI * 2);
+ RNA_def_property_float_default(prop, M_PI_4);
+ RNA_def_property_ui_text(prop, "Upper X Angle Limit", "Upper limit of X axis rotation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "limit_ang_y_lower", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "limit_ang_y_lower");
+ RNA_def_property_range(prop, -M_PI * 2, M_PI * 2);
+ RNA_def_property_float_default(prop, -M_PI_4);
+ RNA_def_property_ui_text(prop, "Lower Y Angle Limit", "Lower limit of Y axis rotation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "limit_ang_y_upper", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "limit_ang_y_upper");
+ RNA_def_property_range(prop, -M_PI * 2, M_PI * 2);
+ RNA_def_property_float_default(prop, M_PI_4);
+ RNA_def_property_ui_text(prop, "Upper Y Angle Limit", "Upper limit of Y axis rotation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "limit_ang_z_lower", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "limit_ang_z_lower");
+ RNA_def_property_range(prop, -M_PI * 2, M_PI * 2);
+ RNA_def_property_float_default(prop, -M_PI_4);
+ RNA_def_property_ui_text(prop, "Lower Z Angle Limit", "Lower limit of Z axis rotation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "limit_ang_z_upper", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "limit_ang_z_upper");
+ RNA_def_property_range(prop, -M_PI * 2, M_PI * 2);
+ RNA_def_property_float_default(prop, M_PI_4);
+ RNA_def_property_ui_text(prop, "Upper Z Angle Limit", "Upper limit of Z axis rotation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "spring_stiffness_x", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "spring_stiffness_x");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
+ RNA_def_property_float_default(prop, 10.0f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_stiffness_x_set", NULL);
+ RNA_def_property_ui_text(prop, "X Axis Stiffness", "Stiffness on the X axis");
+ RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "spring_stiffness_y", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "spring_stiffness_y");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
+ RNA_def_property_float_default(prop, 10.0f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_stiffness_y_set", NULL);
+ RNA_def_property_ui_text(prop, "Y Axis Stiffness", "Stiffness on the Y axis");
+ RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "spring_stiffness_z", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "spring_stiffness_z");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
+ RNA_def_property_float_default(prop, 10.0f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_stiffness_z_set", NULL);
+ RNA_def_property_ui_text(prop, "Z Axis Stiffness", "Stiffness on the Z axis");
+ RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "spring_damping_x", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "spring_damping_x");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_float_default(prop, 0.5f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_damping_x_set", NULL);
+ RNA_def_property_ui_text(prop, "Damping X", "Damping on the X axis");
+ RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "spring_damping_y", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "spring_damping_y");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_float_default(prop, 0.5f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_damping_y_set", NULL);
+ RNA_def_property_ui_text(prop, "Damping Y", "Damping on the Y axis");
+ RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "spring_damping_z", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "spring_damping_z");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_float_default(prop, 0.5f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_damping_z_set", NULL);
+ RNA_def_property_ui_text(prop, "Damping Z", "Damping on the Z axis");
+ RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "motor_lin_target_velocity", PROP_FLOAT, PROP_UNIT_VELOCITY);
+ RNA_def_property_float_sdna(prop, NULL, "motor_lin_target_velocity");
+ RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+ RNA_def_property_ui_range(prop, -100.0f, 100.0f, 1, 3);
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_motor_lin_target_velocity_set", NULL);
+ RNA_def_property_ui_text(prop, "Target Velocity", "Target linear motor velocity");
+ RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "motor_lin_max_impulse", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "motor_lin_max_impulse");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_motor_lin_max_impulse_set", NULL);
+ RNA_def_property_ui_text(prop, "Max Impulse", "Maximum linear motor impulse");
+ RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "motor_ang_target_velocity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "motor_ang_target_velocity");
+ RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+ RNA_def_property_ui_range(prop, -100.0f, 100.0f, 1, 3);
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_motor_ang_target_velocity_set", NULL);
+ RNA_def_property_ui_text(prop, "Target Velocity", "Target angular motor velocity");
+ RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
+
+ prop = RNA_def_property(srna, "motor_ang_max_impulse", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "motor_ang_max_impulse");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_motor_ang_max_impulse_set", NULL);
+ RNA_def_property_ui_text(prop, "Max Impulse", "Maximum angular motor impulse");
+ RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset");
+}
+
+void RNA_def_rigidbody(BlenderRNA *brna)
+{
+ rna_def_rigidbody_world(brna);
+ rna_def_rigidbody_object(brna);
+ rna_def_rigidbody_constraint(brna);
+}
+
+
+#endif
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index 7355e464fc3..67fc3056485 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -24,13 +24,15 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
#include "DNA_ID.h"
+#include "BLI_utildefines.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "rna_internal.h"
@@ -45,6 +47,9 @@ EnumPropertyItem property_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
+/* XXX Keep in sync with bpy_props.c's property_subtype_xxx_items ???
+ * Currently it is not...
+ */
EnumPropertyItem property_subtype_items[] = {
{PROP_NONE, "NONE", 0, "None", ""},
@@ -52,7 +57,7 @@ EnumPropertyItem property_subtype_items[] = {
{PROP_FILEPATH, "FILEPATH", 0, "File Path", ""},
{PROP_DIRPATH, "DIRPATH", 0, "Directory Path", ""},
{PROP_FILENAME, "FILENAME", 0, "File Name", ""},
- {PROP_TRANSLATE, "TRANSLATE", 0, "Translate", ""},
+ {PROP_PASSWORD, "PASSWORD", 0, "Password", "A string that is displayed hidden ('********')"},
/* numbers */
{PROP_UNSIGNED, "UNSIGNED", 0, "Unsigned", ""},
@@ -61,6 +66,7 @@ EnumPropertyItem property_subtype_items[] = {
{PROP_ANGLE, "ANGLE", 0, "Angle", ""},
{PROP_TIME, "TIME", 0, "Time", ""},
{PROP_DISTANCE, "DISTANCE", 0, "Distance", ""},
+ {PROP_DISTANCE_CAMERA, "DISTANCE_CAMERA", 0, "Camera Distance", ""},
/* number arrays */
{PROP_COLOR, "COLOR", 0, "Color", ""},
@@ -92,6 +98,7 @@ EnumPropertyItem property_unit_items[] = {
{PROP_UNIT_TIME, "TIME", 0, "Time", ""},
{PROP_UNIT_VELOCITY, "VELOCITY", 0, "Velocity", ""},
{PROP_UNIT_ACCELERATION, "ACCELERATION", 0, "Acceleration", ""},
+ {PROP_UNIT_CAMERA, "CAMERA", 0, "Camera", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -134,12 +141,12 @@ static int rna_Struct_name_length(PointerRNA *ptr)
static void rna_Struct_translation_context_get(PointerRNA *ptr, char *value)
{
- strcpy(value, ((StructRNA *)ptr->data)->translation_context ? ((StructRNA *)ptr->data)->translation_context : "");
+ strcpy(value, ((StructRNA *)ptr->data)->translation_context);
}
static int rna_Struct_translation_context_length(PointerRNA *ptr)
{
- return ((StructRNA *)ptr->data)->translation_context ? strlen(((StructRNA *)ptr->data)->translation_context) : 0;
+ return strlen(((StructRNA *)ptr->data)->translation_context);
}
static PointerRNA rna_Struct_base_get(PointerRNA *ptr)
@@ -484,14 +491,14 @@ static void rna_Property_translation_context_get(PointerRNA *ptr, char *value)
{
PropertyRNA *prop = (PropertyRNA *)ptr->data;
rna_idproperty_check(&prop, ptr);
- strcpy(value, prop->translation_context ? prop->translation_context : "");
+ strcpy(value, prop->translation_context);
}
static int rna_Property_translation_context_length(PointerRNA *ptr)
{
PropertyRNA *prop = (PropertyRNA *)ptr->data;
rna_idproperty_check(&prop, ptr);
- return prop->translation_context ? strlen(prop->translation_context) : 0;
+ return strlen(prop->translation_context);
}
static int rna_Property_type_get(PointerRNA *ptr)
@@ -522,6 +529,13 @@ static int rna_Property_unit_get(PointerRNA *ptr)
return RNA_SUBTYPE_UNIT(prop->subtype);
}
+static int rna_Property_icon_get(PointerRNA *ptr)
+{
+ PropertyRNA *prop = (PropertyRNA *)ptr->data;
+ rna_idproperty_check(&prop, ptr);
+ return prop->icon;
+}
+
static int rna_Property_readonly_get(PointerRNA *ptr)
{
PropertyRNA *prop = (PropertyRNA *)ptr->data;
@@ -880,6 +894,11 @@ static int rna_EnumPropertyItem_value_get(PointerRNA *ptr)
return ((EnumPropertyItem *)ptr->data)->value;
}
+static int rna_EnumPropertyItem_icon_get(PointerRNA *ptr)
+{
+ return ((EnumPropertyItem *)ptr->data)->icon;
+}
+
static PointerRNA rna_PointerProperty_fixed_type_get(PointerRNA *ptr)
{
PropertyRNA *prop = (PropertyRNA *)ptr->data;
@@ -930,7 +949,7 @@ static int rna_Function_registered_get(PointerRNA *ptr)
static int rna_Function_registered_optional_get(PointerRNA *ptr)
{
FunctionRNA *func = (FunctionRNA *)ptr->data;
- return func->flag & FUNC_REGISTER_OPTIONAL;
+ return func->flag & (FUNC_REGISTER_OPTIONAL & ~FUNC_REGISTER);
}
static int rna_Function_no_self_get(PointerRNA *ptr)
@@ -939,6 +958,12 @@ static int rna_Function_no_self_get(PointerRNA *ptr)
return !(func->flag & FUNC_NO_SELF);
}
+static int rna_Function_use_self_type_get(PointerRNA *ptr)
+{
+ FunctionRNA *func = (FunctionRNA *)ptr->data;
+ return (func->flag & FUNC_USE_SELF_TYPE);
+}
+
/* Blender RNA */
static void rna_BlenderRNA_structs_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
@@ -1125,6 +1150,12 @@ static void rna_def_property(BlenderRNA *brna)
RNA_def_property_enum_funcs(prop, "rna_Property_unit_get", NULL, NULL);
RNA_def_property_ui_text(prop, "Unit", "Type of units for this property");
+ prop = RNA_def_property(srna, "icon", PROP_ENUM, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_enum_items(prop, icon_items);
+ RNA_def_property_enum_funcs(prop, "rna_Property_icon_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Icon", "Icon of the item");
+
prop = RNA_def_property(srna, "is_readonly", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_boolean_funcs(prop, "rna_Property_readonly_get", NULL);
@@ -1230,7 +1261,13 @@ static void rna_def_function(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_boolean_funcs(prop, "rna_Function_no_self_get", NULL);
RNA_def_property_ui_text(prop, "No Self",
- "Function does not pass its self as an argument (becomes a class method in python)");
+ "Function does not pass its self as an argument (becomes a static method in python)");
+
+ prop = RNA_def_property(srna, "use_self_type", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_boolean_funcs(prop, "rna_Function_use_self_type_get", NULL);
+ RNA_def_property_ui_text(prop, "Use Self Type",
+ "Function passes its self type as an argument (becomes a class method in python if use_self is false)");
}
static void rna_def_number_property(StructRNA *srna, PropertyType type)
@@ -1396,6 +1433,12 @@ static void rna_def_enum_property(BlenderRNA *brna, StructRNA *srna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_int_funcs(prop, "rna_EnumPropertyItem_value_get", NULL, NULL);
RNA_def_property_ui_text(prop, "Value", "Value of the item");
+
+ prop = RNA_def_property(srna, "icon", PROP_ENUM, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_enum_items(prop, icon_items);
+ RNA_def_property_enum_funcs(prop, "rna_EnumPropertyItem_icon_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Icon", "Icon of the item");
}
static void rna_def_pointer_property(StructRNA *srna, PropertyType type)
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 2d405f4fc0d..ebce22bac79 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -26,16 +26,13 @@
#include <stdlib.h>
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
-#include "rna_internal.h"
-
#include "DNA_brush_types.h"
#include "DNA_group_types.h"
#include "DNA_modifier_types.h"
#include "DNA_particle_types.h"
+#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
+#include "DNA_linestyle_types.h"
#include "DNA_userdef_types.h"
#include "DNA_world_types.h"
@@ -43,8 +40,14 @@
#include "BLF_translation.h"
+#include "BKE_freestyle.h"
#include "BKE_tessmesh.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
/* Include for Bake Options */
#include "RE_engine.h"
#include "RE_pipeline.h"
@@ -116,7 +119,8 @@ EnumPropertyItem proportional_falloff_curve_only_items[] = {
EnumPropertyItem proportional_editing_items[] = {
{PROP_EDIT_OFF, "DISABLED", ICON_PROP_OFF, "Disable", "Proportional Editing disabled"},
{PROP_EDIT_ON, "ENABLED", ICON_PROP_ON, "Enable", "Proportional Editing enabled"},
- {PROP_EDIT_CONNECTED, "CONNECTED", ICON_PROP_CON, "Connected", "Proportional Editing using connected geometry only"},
+ {PROP_EDIT_CONNECTED, "CONNECTED", ICON_PROP_CON, "Connected",
+ "Proportional Editing using connected geometry only"},
{0, NULL, 0, NULL, NULL}
};
@@ -274,9 +278,11 @@ EnumPropertyItem image_color_mode_items[] = {
{0, NULL, 0, NULL, NULL}
};
+#ifdef RNA_RUNTIME
#define IMAGE_COLOR_MODE_BW image_color_mode_items[0]
#define IMAGE_COLOR_MODE_RGB image_color_mode_items[1]
#define IMAGE_COLOR_MODE_RGBA image_color_mode_items[2]
+#endif
EnumPropertyItem image_color_depth_items[] = {
/* 1 (monochrome) not used */
@@ -377,10 +383,10 @@ static Base *rna_Scene_object_link(Scene *scene, bContext *C, ReportList *report
if (scene == scene_act)
ob->lay = base->lay;
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* slows down importers too much, run scene.update() */
- /* DAG_scene_sort(G.main, scene); */
+ /* DAG_srelations_tag_update(G.main); */
WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, scene);
@@ -402,14 +408,13 @@ static void rna_Scene_object_unlink(Scene *scene, ReportList *reports, Object *o
scene->basact = NULL;
}
- BLI_remlink(&scene->base, base);
+ BKE_scene_base_unlink(scene, base);
MEM_freeN(base);
ob->id.us--;
/* needed otherwise the depgraph will contain freed objects which can crash, see [#20958] */
- DAG_scene_sort(G.main, scene);
- DAG_ids_flush_update(G.main, 0);
+ DAG_relations_tag_update(G.main);
WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, scene);
}
@@ -873,7 +878,7 @@ 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.imtype);
+ BKE_add_image_extension(ext, &rd->im_format);
return strlen(ext);
}
@@ -881,7 +886,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.imtype);
+ BKE_add_image_extension(str, &rd->im_format);
}
#ifdef WITH_QUICKTIME
@@ -906,16 +911,13 @@ static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_codecType_itemf(bCon
EnumPropertyItem tmp = {0, "", 0, "", ""};
QuicktimeCodecTypeDesc *codecTypeDesc;
int i = 1, totitem = 0;
- char id[5];
-
+
for (i = 0; i < quicktime_get_num_videocodecs(); i++) {
codecTypeDesc = quicktime_get_videocodecType_desc(i);
if (!codecTypeDesc) break;
-
+
tmp.value = codecTypeDesc->rnatmpvalue;
- *((int *)id) = codecTypeDesc->codecType;
- id[4] = 0;
- tmp.identifier = id;
+ tmp.identifier = codecTypeDesc->codecName;
tmp.name = codecTypeDesc->codecName;
RNA_enum_item_add(&item, &totitem, &tmp);
}
@@ -1130,7 +1132,7 @@ static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value)
static char *rna_SceneRenderLayer_path(PointerRNA *ptr)
{
- SceneRenderLayer *srl = (SceneRenderLayer*)ptr->data;
+ SceneRenderLayer *srl = (SceneRenderLayer *)ptr->data;
return BLI_sprintfN("render.layers[\"%s\"]", srl->name);
}
@@ -1173,13 +1175,12 @@ static void rna_SceneRenderLayer_pass_update(Main *bmain, Scene *activescene, Po
rna_Scene_glsl_update(bmain, activescene, ptr);
}
-static void rna_Scene_use_nodes_set(PointerRNA *ptr, int value)
+static void rna_Scene_use_nodes_update(bContext *C, PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->data;
- scene->use_nodes = value;
if (scene->use_nodes && scene->nodetree == NULL)
- ED_node_composit_default(scene);
+ ED_node_composit_default(C, scene);
}
static void rna_Physics_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -1247,27 +1248,31 @@ static void object_simplify_update(Object *ob)
}
}
-static void rna_Scene_use_simplify_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
+static void rna_Scene_use_simplify_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
+ Scene *sce = ptr->id.data;
Scene *sce_iter;
Base *base;
- for (SETLOOPER(scene, sce_iter, base))
+ for (SETLOOPER(sce, sce_iter, base))
object_simplify_update(base->object);
- DAG_ids_flush_update(bmain, 0);
WM_main_add_notifier(NC_GEOM | ND_DATA, NULL);
}
-static void rna_Scene_simplify_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Scene_simplify_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- if (scene->r.mode & R_SIMPLIFY)
- rna_Scene_use_simplify_update(bmain, scene, ptr);
+ Scene *sce = ptr->id.data;
+
+ if (sce->r.mode & R_SIMPLIFY)
+ rna_Scene_use_simplify_update(bmain, sce, ptr);
}
-static void rna_Scene_use_persistent_data_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
+static void rna_Scene_use_persistent_data_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- if (!(scene->r.mode & R_PERSISTENT_DATA))
+ Scene *sce = ptr->id.data;
+
+ if (!(sce->r.mode & R_PERSISTENT_DATA))
RE_FreePersistentData();
}
@@ -1356,7 +1361,8 @@ static void rna_TimeLine_remove(Scene *scene, ReportList *reports, PointerRNA *m
{
TimeMarker *marker = marker_ptr->data;
if (BLI_remlink_safe(&scene->markers, marker) == FALSE) {
- BKE_reportf(reports, RPT_ERROR, "Timeline marker '%s' not found in scene '%s'", marker->name, scene->id.name + 2);
+ BKE_reportf(reports, RPT_ERROR, "Timeline marker '%s' not found in scene '%s'",
+ marker->name, scene->id.name + 2);
return;
}
@@ -1411,6 +1417,11 @@ static void rna_UnifiedPaintSettings_unprojected_radius_set(PointerRNA *ptr, flo
ups->unprojected_radius = value;
}
+static char *rna_UnifiedPaintSettings_path(PointerRNA *ptr)
+{
+ return BLI_strdup("tool_settings.unified_paint_settings");
+}
+
/* note: without this, when Multi-Paint is activated/deactivated, the colors
* will not change right away when multiple bones are selected, this function
* is not for general use and only for the few cases where changing scene
@@ -1440,6 +1451,55 @@ static void rna_SceneSequencer_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
BKE_sequencer_preprocessed_cache_cleanup();
}
+static char *rna_ToolSettings_path(PointerRNA *ptr)
+{
+ return BLI_strdup("tool_settings");
+}
+
+static PointerRNA rna_FreestyleLineSet_linestyle_get(PointerRNA *ptr)
+{
+ FreestyleLineSet *lineset = (FreestyleLineSet *)ptr->data;
+
+ return rna_pointer_inherit_refine(ptr, &RNA_FreestyleLineStyle, lineset->linestyle);
+}
+
+static void rna_FreestyleLineSet_linestyle_set(PointerRNA *ptr, PointerRNA value)
+{
+ FreestyleLineSet *lineset = (FreestyleLineSet*)ptr->data;
+
+ lineset->linestyle->id.us--;
+ lineset->linestyle = (FreestyleLineStyle *)value.data;
+ lineset->linestyle->id.us++;
+}
+
+static PointerRNA rna_FreestyleSettings_active_lineset_get(PointerRNA *ptr)
+{
+ FreestyleConfig *config = (FreestyleConfig *)ptr->data;
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
+ return rna_pointer_inherit_refine(ptr, &RNA_FreestyleLineSet, lineset);
+}
+
+static void rna_FreestyleSettings_active_lineset_index_range(PointerRNA *ptr, int *min, int *max,
+ int *softmin, int *softmax)
+{
+ FreestyleConfig *config = (FreestyleConfig *)ptr->data;
+
+ *min = 0;
+ *max = max_ii(0, BLI_countlist(&config->linesets) - 1);
+}
+
+static int rna_FreestyleSettings_active_lineset_index_get(PointerRNA *ptr)
+{
+ FreestyleConfig *config = (FreestyleConfig *)ptr->data;
+ return BKE_freestyle_lineset_get_active_index(config);
+}
+
+static void rna_FreestyleSettings_active_lineset_index_set(PointerRNA *ptr, int value)
+{
+ FreestyleConfig *config = (FreestyleConfig *)ptr->data;
+ BKE_freestyle_lineset_set_active_index(config, value);
+}
+
#else
static void rna_def_transform_orientation(BlenderRNA *brna)
@@ -1507,10 +1567,19 @@ static void rna_def_tool_settings(BlenderRNA *brna)
{EDGE_MODE_TAG_SHARP, "SHARP", 0, "Tag Sharp", ""},
{EDGE_MODE_TAG_CREASE, "CREASE", 0, "Tag Crease", ""},
{EDGE_MODE_TAG_BEVEL, "BEVEL", 0, "Tag Bevel", ""},
+ {EDGE_MODE_TAG_FREESTYLE, "FREESTYLE", 0, "Tag Freestyle Edge Mark", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem draw_groupuser_items[] = {
+ {OB_DRAW_GROUPUSER_NONE, "NONE", 0, "None", ""},
+ {OB_DRAW_GROUPUSER_ACTIVE, "ACTIVE", 0, "Active", "Show vertices with no weights in the active group"},
+ {OB_DRAW_GROUPUSER_ALL, "ALL", 0, "All", "Show vertices with no weights in any group"},
{0, NULL, 0, NULL, NULL}
};
srna = RNA_def_struct(brna, "ToolSettings", NULL);
+ RNA_def_struct_path_func(srna, "rna_ToolSettings_path");
RNA_def_struct_ui_text(srna, "Tool Settings", "");
prop = RNA_def_property(srna, "sculpt", PROP_POINTER, PROP_NONE);
@@ -1531,6 +1600,13 @@ static void rna_def_tool_settings(BlenderRNA *brna)
"weight painting");
RNA_def_property_update(prop, 0, "rna_Scene_update_active_object_data");
+ prop = RNA_def_property(srna, "vertex_group_user", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "weightuser");
+ RNA_def_property_enum_items(prop, draw_groupuser_items);
+ RNA_def_property_ui_text(prop, "Mask Non-Group Vertices", "Display unweighted vertices (multi-paint overrides)");
+ RNA_def_property_update(prop, 0, "rna_Scene_update_active_object_data");
+
+
prop = RNA_def_property(srna, "vertex_paint", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "vpaint");
RNA_def_property_ui_text(prop, "Vertex Paint", "");
@@ -1753,28 +1829,29 @@ static void rna_def_tool_settings(BlenderRNA *brna)
/* etch-a-ton */
prop = RNA_def_property(srna, "use_bone_sketching", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "bone_sketching", BONE_SKETCHING);
- RNA_def_property_ui_text(prop, "Use Bone Sketching", "DOC BROKEN");
+ RNA_def_property_ui_text(prop, "Use Bone Sketching", "Use sketching to create and edit bones");
/* RNA_def_property_ui_icon(prop, ICON_EDIT, 0); */
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "use_etch_quick", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "bone_sketching", BONE_SKETCHING_QUICK);
- RNA_def_property_ui_text(prop, "Quick Sketching", "DOC BROKEN");
+ RNA_def_property_ui_text(prop, "Quick Sketching", "Automatically convert and delete on stroke end");
prop = RNA_def_property(srna, "use_etch_overdraw", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "bone_sketching", BONE_SKETCHING_ADJUST);
- RNA_def_property_ui_text(prop, "Overdraw Sketching", "DOC BROKEN");
+ RNA_def_property_ui_text(prop, "Overdraw Sketching", "Adjust strokes by drawing near them");
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", "DOC BROKEN");
+ 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");
- RNA_def_property_ui_text(prop, "Number", "DOC BROKEN");
+ RNA_def_property_ui_text(prop, "Number", "Text to replace &N with (e.g. 'Finger.&N' -> 'Finger.1' or 'Finger.One')");
prop = RNA_def_property(srna, "etch_side", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "skgen_num_string");
- RNA_def_property_ui_text(prop, "Side", "DOC BROKEN");
+ RNA_def_property_ui_text(prop, "Side", "Text to replace &S with (e.g. 'Arm.&S' -> 'Arm.R' or 'Arm.Right')");
prop = RNA_def_property(srna, "etch_template", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "skgen_template");
@@ -1793,14 +1870,14 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "skgen_correlation_limit");
RNA_def_property_range(prop, 0.00001, 1.0);
RNA_def_property_ui_range(prop, 0.01, 1.0, 0.01, 2);
- RNA_def_property_ui_text(prop, "Limit", "Number of bones in the subdivided stroke");
+ RNA_def_property_ui_text(prop, "Limit", "Correlation threshold for number of bones in the subdivided stroke");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "etch_length_limit", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "skgen_length_limit");
RNA_def_property_range(prop, 0.00001, 100000.0);
RNA_def_property_ui_range(prop, 0.001, 100.0, 0.1, 3);
- RNA_def_property_ui_text(prop, "Length", "Number of bones in the subdivided stroke");
+ RNA_def_property_ui_text(prop, "Length", "Maximum length of the subdivided bones");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "etch_roll_mode", PROP_ENUM, PROP_NONE);
@@ -1827,6 +1904,7 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
PropertyRNA *prop;
srna = RNA_def_struct(brna, "UnifiedPaintSettings", NULL);
+ RNA_def_struct_path_func(srna, "rna_UnifiedPaintSettings_path");
RNA_def_struct_ui_text(srna, "Unified Paint Settings", "Overrides for some of the active brush's settings");
/* high-level flags to enable or disable unified paint settings */
@@ -1847,7 +1925,7 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
/* unified paint settings that override the equivalent settings
* from the active brush */
- prop = RNA_def_property(srna, "size", PROP_INT, PROP_DISTANCE);
+ prop = RNA_def_property(srna, "size", PROP_INT, PROP_NONE);
RNA_def_property_int_funcs(prop, NULL, "rna_UnifiedPaintSettings_size_set", NULL);
RNA_def_property_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS * 10);
RNA_def_property_ui_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS, 1, 0);
@@ -1989,7 +2067,8 @@ void rna_def_render_layer_common(StructRNA *srna, int scene)
if (scene) {
prop = RNA_def_property(srna, "samples", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_ui_text(prop, "Samples", "Override number of render samples for this render layer, 0 will use the scene setting");
+ RNA_def_property_ui_text(prop, "Samples", "Override number of render samples for this render layer, "
+ "0 will use the scene setting");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
}
@@ -2055,6 +2134,14 @@ void rna_def_render_layer_common(StructRNA *srna, int scene)
if (scene) RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ prop = RNA_def_property(srna, "use_freestyle", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "layflag", SCE_LAY_FRS);
+ RNA_def_property_ui_text(prop, "Freestyle", "Render stylized strokes in this Layer");
+ if (scene)
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ else
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
/* passes */
prop = RNA_def_property(srna, "use_pass_combined", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_COMBINED);
@@ -2275,6 +2362,414 @@ void rna_def_render_layer_common(StructRNA *srna, int scene)
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
}
+static void rna_def_freestyle_linesets(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ RNA_def_property_srna(cprop, "Linesets");
+ srna = RNA_def_struct(brna, "Linesets", NULL);
+ RNA_def_struct_sdna(srna, "FreestyleSettings");
+ RNA_def_struct_ui_text(srna, "Line Sets", "Line sets for associating lines and style parameters");
+
+ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "FreestyleLineSet");
+ RNA_def_property_pointer_funcs(prop, "rna_FreestyleSettings_active_lineset_get", NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Active Line Set", "Active line set being displayed");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_funcs(prop, "rna_FreestyleSettings_active_lineset_index_get",
+ "rna_FreestyleSettings_active_lineset_index_set",
+ "rna_FreestyleSettings_active_lineset_index_range");
+ RNA_def_property_ui_text(prop, "Active Line Set Index", "Index of active line set slot");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+}
+
+static void rna_def_freestyle_settings(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem edge_type_negation_items[] = {
+ {0, "INCLUSIVE", 0, "Inclusive", "Select feature edges satisfying the given edge type conditions"},
+ {FREESTYLE_LINESET_FE_NOT, "EXCLUSIVE", 0, "Exclusive",
+ "Select feature edges not satisfying the given edge type conditions"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem edge_type_combination_items[] = {
+ {0, "OR", 0, "Logical OR", "Combine feature edge type conditions by logical OR (logical disjunction)"},
+ {FREESTYLE_LINESET_FE_AND, "AND", 0, "Logical AND",
+ "Combine feature edge type conditions by logical AND (logical conjunction)"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem group_negation_items[] = {
+ {0, "INCLUSIVE", 0, "Inclusive", "Select feature edges belonging to some object in the group"},
+ {FREESTYLE_LINESET_GR_NOT, "EXCLUSIVE", 0, "Exclusive",
+ "Select feature edges not belonging to any object in the group"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem face_mark_negation_items[] = {
+ {0, "INCLUSIVE", 0, "Inclusive", "Select feature edges satisfying the given face mark conditions"},
+ {FREESTYLE_LINESET_FM_NOT, "EXCLUSIVE", 0, "Exclusive",
+ "Select feature edges not satisfying the given face mark conditions"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem face_mark_condition_items[] = {
+ {0, "ONE", 0, "One Face", "Select feature edges if one of faces on the right and left has a face mark"},
+ {FREESTYLE_LINESET_FM_BOTH, "BOTH", 0, "Both Faces",
+ "Select feature edges if both faces on the right and left faces have a face mark"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem freestyle_ui_mode_items[] = {
+ {FREESTYLE_CONTROL_SCRIPT_MODE, "SCRIPT", 0, "Python Scripting Mode",
+ "Advanced mode for using style modules in Python"},
+ {FREESTYLE_CONTROL_EDITOR_MODE, "EDITOR", 0, "Parameter Editor Mode",
+ "Basic mode for interactive style parameter editing"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem visibility_items[] ={
+ {FREESTYLE_QI_VISIBLE, "VISIBLE", 0, "Visible", "Select visible feature edges"},
+ {FREESTYLE_QI_HIDDEN, "HIDDEN", 0, "Hidden", "Select hidden feature edges"},
+ {FREESTYLE_QI_RANGE, "RANGE", 0, "QI Range",
+ "Select feature edges within a range of quantitative invisibility (QI) values"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem freestyle_raycasting_algorithm_items[] = {
+ {FREESTYLE_ALGO_REGULAR, "REGULAR", 0, "Normal Ray Casting", "Consider all FEdges in each ViewEdge"},
+ {FREESTYLE_ALGO_FAST, "FAST", 0, "Fast Ray Casting", "Sample some FEdges in each ViewEdge"},
+ {FREESTYLE_ALGO_VERYFAST, "VERYFAST", 0, "Very Fast Ray Casting",
+ "Sample one FEdge in each ViewEdge; do not save list of occluders"},
+ {FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL, "CULLEDADAPTIVETRADITIONAL", 0,
+ "Culled Traditional Visibility Detection",
+ "Culled adaptive grid with heuristic density and "
+ "traditional QI calculation"},
+ {FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL, "ADAPTIVETRADITIONAL", 0, "Unculled Traditional Visibility Detection",
+ "Adaptive grid with heuristic density and traditional QI calculation"},
+ {FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE, "CULLEDADAPTIVECUMULATIVE", 0,
+ "Culled Cumulative Visibility Detection",
+ "Culled adaptive grid with heuristic density and "
+ "cumulative QI calculation"},
+ {FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE, "ADAPTIVECUMULATIVE", 0, "Unculled Cumulative Visibility Detection",
+ "Adaptive grid with heuristic density and cumulative QI calculation"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+
+ /* FreestyleLineSet */
+
+ srna = RNA_def_struct(brna, "FreestyleLineSet", NULL);
+ RNA_def_struct_ui_text(srna, "Freestyle Line Set", "Line set for associating lines and style parameters");
+
+ /* access to line style settings is redirected through functions
+ * to allow proper id-buttons functionality
+ */
+ prop = RNA_def_property(srna, "linestyle", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "FreestyleLineStyle");
+ RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_NULL);
+ RNA_def_property_pointer_funcs(prop, "rna_FreestyleLineSet_linestyle_get",
+ "rna_FreestyleLineSet_linestyle_set", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Line Style", "Line style settings");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "name");
+ RNA_def_property_ui_text(prop, "Line Set Name", "Line set name");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_struct_name_property(srna, prop);
+
+ prop = RNA_def_property(srna, "show_render", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_LINESET_ENABLED);
+ RNA_def_property_ui_text(prop, "Render", "Enable or disable this line set during stroke rendering");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "select_by_visibility", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_VISIBILITY);
+ RNA_def_property_ui_text(prop, "Selection by Visibility", "Select feature edges based on visibility");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "select_by_edge_types", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_EDGE_TYPES);
+ RNA_def_property_ui_text(prop, "Selection by Edge Types", "Select feature edges based on edge types");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "select_by_group", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_GROUP);
+ RNA_def_property_ui_text(prop, "Selection by Group", "Select feature edges based on a group of objects");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "select_by_image_border", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_IMAGE_BORDER);
+ RNA_def_property_ui_text(prop, "Selection by Image Border",
+ "Select feature edges by image border (less memory consumption)");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "select_by_face_marks", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_FACE_MARK);
+ RNA_def_property_ui_text(prop, "Selection by Face Marks", "Select feature edges by face marks");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "edge_type_negation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
+ RNA_def_property_enum_items(prop, edge_type_negation_items);
+ RNA_def_property_ui_text(prop, "Edge Type Negation",
+ "Set the negation operation for conditions on feature edge types");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "edge_type_combination", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
+ RNA_def_property_enum_items(prop, edge_type_combination_items);
+ RNA_def_property_ui_text(prop, "Edge Type Combination",
+ "Set the combination operation for conditions on feature edge types");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "group");
+ RNA_def_property_struct_type(prop, "Group");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Group", "A group of objects based on which feature edges are selected");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "group_negation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
+ RNA_def_property_enum_items(prop, group_negation_items);
+ RNA_def_property_ui_text(prop, "Group Negation",
+ "Set the negation operation for conditions on feature edge types");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "face_mark_negation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags");
+ RNA_def_property_enum_items(prop, face_mark_negation_items);
+ RNA_def_property_ui_text(prop, "Face Mark Negation",
+ "Set the negation operation for the condition on face marks");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ 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", "Set a feature edge selection condition on face marks");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ 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 silhouette edges");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "select_border", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_BORDER);
+ RNA_def_property_ui_text(prop, "Border", "Select border edges");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ 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");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ 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");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "select_suggestive_contour", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_SUGGESTIVE_CONTOUR);
+ RNA_def_property_ui_text(prop, "Suggestive Contour", "Select suggestive contours");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "select_material_boundary", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_MATERIAL_BOUNDARY);
+ RNA_def_property_ui_text(prop, "Material Boundary", "Select edges at material boundaries");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "select_contour", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_CONTOUR);
+ RNA_def_property_ui_text(prop, "Contour", "Select contours");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ 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");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "select_edge_mark", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_EDGE_MARK);
+ RNA_def_property_ui_text(prop, "Edge Mark", "Select edge marks");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "exclude_silhouette", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_SILHOUETTE);
+ RNA_def_property_ui_text(prop, "Silhouette", "Exclude silhouette edges");
+ RNA_def_property_ui_icon(prop, ICON_X, 0);
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "exclude_border", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_BORDER);
+ RNA_def_property_ui_text(prop, "Border", "Exclude border edges");
+ RNA_def_property_ui_icon(prop, ICON_X, 0);
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "exclude_crease", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_CREASE);
+ RNA_def_property_ui_text(prop, "Crease", "Exclude crease edges");
+ RNA_def_property_ui_icon(prop, ICON_X, 0);
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "exclude_ridge_valley", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_RIDGE_VALLEY);
+ RNA_def_property_ui_text(prop, "Ridge & Valley", "Exclude ridges and valleys");
+ RNA_def_property_ui_icon(prop, ICON_X, 0);
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "exclude_suggestive_contour", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_SUGGESTIVE_CONTOUR);
+ RNA_def_property_ui_text(prop, "Suggestive Contour", "Exclude suggestive contours");
+ RNA_def_property_ui_icon(prop, ICON_X, 0);
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "exclude_material_boundary", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_MATERIAL_BOUNDARY);
+ RNA_def_property_ui_text(prop, "Material Boundary", "Exclude edges at material boundaries");
+ RNA_def_property_ui_icon(prop, ICON_X, 0);
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "exclude_contour", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_CONTOUR);
+ RNA_def_property_ui_text(prop, "Contour", "Exclude contours");
+ RNA_def_property_ui_icon(prop, ICON_X, 0);
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "exclude_external_contour", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_EXTERNAL_CONTOUR);
+ RNA_def_property_ui_text(prop, "External Contour", "Exclude external contours");
+ RNA_def_property_ui_icon(prop, ICON_X, 0);
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "exclude_edge_mark", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_EDGE_MARK);
+ RNA_def_property_ui_text(prop, "Edge Mark", "Exclude edge marks");
+ RNA_def_property_ui_icon(prop, ICON_X, 0);
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "visibility", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "qi");
+ RNA_def_property_enum_items(prop, visibility_items);
+ RNA_def_property_ui_text(prop, "Visibility", "Determine how to use visibility for feature edge selection");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "qi_start", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "qi_start");
+ RNA_def_property_range(prop, 0, INT_MAX);
+ RNA_def_property_ui_text(prop, "Start", "First QI value of the QI range");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "qi_end", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "qi_end");
+ RNA_def_property_range(prop, 0, INT_MAX);
+ RNA_def_property_ui_text(prop, "End", "Last QI value of the QI range");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ /* FreestyleModuleSettings */
+
+ srna = RNA_def_struct(brna, "FreestyleModuleSettings", NULL);
+ RNA_def_struct_sdna(srna, "FreestyleModuleConfig");
+ RNA_def_struct_ui_text(srna, "Freestyle Module", "Style module configuration for specifying a style module");
+
+ prop = RNA_def_property(srna, "module_path", PROP_STRING, PROP_FILEPATH);
+ RNA_def_property_string_sdna(prop, NULL, "module_path");
+ RNA_def_property_ui_text(prop, "Module Path", "Path to a style module file");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "is_displayed", 1);
+ RNA_def_property_ui_text(prop, "Use", "Enable or disable this style module during stroke rendering");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ /* FreestyleSettings */
+
+ srna = RNA_def_struct(brna, "FreestyleSettings", NULL);
+ RNA_def_struct_sdna(srna, "FreestyleConfig");
+ RNA_def_struct_nested(brna, srna, "SceneRenderLayer");
+ RNA_def_struct_ui_text(srna, "Frestyle Settings", "Freestyle settings for a SceneRenderLayer datablock");
+
+ prop = RNA_def_property(srna, "modules", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "modules", NULL);
+ RNA_def_property_struct_type(prop, "FreestyleModuleSettings");
+ RNA_def_property_ui_text(prop, "Style modules", "A list of style modules (to be applied from top to bottom)");
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "mode");
+ RNA_def_property_enum_items(prop, freestyle_ui_mode_items);
+ RNA_def_property_ui_text(prop, "Control Mode", "Select the Freestyle control mode");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "raycasting_algorithm", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "raycasting_algorithm");
+ RNA_def_property_enum_items(prop, freestyle_raycasting_algorithm_items);
+ RNA_def_property_ui_text(prop, "Raycasting Algorithm", "Select the Freestyle raycasting algorithm");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "use_culling", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_CULLING);
+ RNA_def_property_ui_text(prop, "Culling", "If enabled, out-of-view edges are ignored");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "use_suggestive_contours", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_SUGGESTIVE_CONTOURS_FLAG);
+ RNA_def_property_ui_text(prop, "Suggestive Contours", "Enable suggestive contours");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "use_ridges_and_valleys", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_RIDGES_AND_VALLEYS_FLAG);
+ RNA_def_property_ui_text(prop, "Ridges and Valleys", "Enable ridges and valleys");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "use_material_boundaries", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_MATERIAL_BOUNDARIES_FLAG);
+ RNA_def_property_ui_text(prop, "Material Boundaries", "Enable material boundaries");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "use_smoothness", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_FACE_SMOOTHNESS_FLAG);
+ RNA_def_property_ui_text(prop, "Face Smoothness", "Take face smoothness into account in view map calculation");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "use_advanced_options", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_ADVANCED_OPTIONS_FLAG);
+ RNA_def_property_ui_text(prop, "Advanced Edge Detection Options",
+ "Enable advanced edge detection options (sphere radius and Kr derivative epsilon)");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ 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);
+ RNA_def_property_ui_text(prop, "Sphere Radius", "Sphere radius for computing curvatures");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "kr_derivative_epsilon", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "dkr_epsilon");
+ RNA_def_property_range(prop, -1000.0, 1000.0);
+ RNA_def_property_ui_text(prop, "Kr Derivative Epsilon", "Kr derivative epsilon for computing suggestive contours");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "crease_angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "crease_angle");
+ RNA_def_property_range(prop, 0.0, DEG2RAD(180.0));
+ RNA_def_property_ui_text(prop, "Crease Angle", "Angular threshold for detecting crease edges");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "linesets", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "linesets", NULL);
+ RNA_def_property_struct_type(prop, "FreestyleLineSet");
+ RNA_def_property_ui_text(prop, "Line Sets", "");
+ rna_def_freestyle_linesets(brna, prop);
+}
+
static void rna_def_scene_game_recast_data(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2318,7 +2813,7 @@ static void rna_def_scene_game_recast_data(BlenderRNA *brna)
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_ui_text(prop, "Max Slope", "Maximum walkable slope angle in degrees");
+ RNA_def_property_ui_text(prop, "Max Slope", "Maximum walkable slope angle");
RNA_def_property_update(prop, NC_SCENE, NULL);
@@ -2417,10 +2912,6 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
static EnumPropertyItem physics_engine_items[] = {
{WOPHY_NONE, "NONE", 0, "None", "Don't use a physics engine"},
- /*{WOPHY_ENJI, "ENJI", 0, "Enji", ""}, */
- /*{WOPHY_SUMO, "SUMO", 0, "Sumo (Deprecated)", ""}, */
- /*{WOPHY_DYNAMO, "DYNAMO", 0, "Dynamo", ""}, */
- /*{WOPHY_ODE, "ODE", 0, "ODE", ""}, */
{WOPHY_BULLET, "BULLET", 0, "Bullet", "Use the Bullet physics engine"},
{0, NULL, 0, NULL, NULL}
};
@@ -2439,6 +2930,16 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem storage_items[] = {
+ {RAS_STORE_AUTO, "AUTO", 0, "Auto Select", "Chooses the best supported mode"},
+ {RAS_STORE_IMMEDIATE, "IMMEDIATE", 0, "Immediate Mode", "Slowest performance, requires OpenGL (any version)"},
+ {RAS_STORE_VA, "VERTEX_ARRAY", 0, "Vertex Arrays", "Better performance, requires at least OpenGL 1.1"},
+#if 0 /* XXX VBOS are currently disabled since they cannot beat vertex array with display lists in performance. */
+ {RAS_STORE_VBO, "VERTEX_BUFFER_OBJECT", 0, "Vertex Buffer Objects",
+ "Best performance, requires at least OpenGL 1.4"},
+#endif
+ {0, NULL, 0, NULL, NULL}};
+
srna = RNA_def_struct(brna, "SceneGameData", NULL);
RNA_def_struct_sdna(srna, "GameData");
RNA_def_struct_nested(brna, srna, "Scene");
@@ -2471,7 +2972,13 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "exitkey");
RNA_def_property_enum_items(prop, event_type_items);
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_ui_text(prop, "Exit Key", "The key that exits the Game Engine");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop = RNA_def_property(srna, "raster_storage", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "raster_storage");
+ RNA_def_property_enum_items(prop, storage_items);
+ RNA_def_property_ui_text(prop, "Storage", "Set the storage mode used by the rasterizer");
RNA_def_property_update(prop, NC_SCENE, NULL);
/* Do we need it here ? (since we already have it in World */
@@ -2522,7 +3029,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "eyeseparation");
RNA_def_property_range(prop, 0.01, 5.0);
RNA_def_property_ui_text(prop, "Eye Separation",
- "Set the distance between the eyes - the camera focal length/30 should be fine");
+ "Set the distance between the eyes - the camera focal distance/30 should be fine");
RNA_def_property_update(prop, NC_SCENE, NULL);
/* Dome */
@@ -2588,7 +3095,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "fps", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "ticrate");
RNA_def_property_ui_range(prop, 1, 60, 1, 1);
- RNA_def_property_range(prop, 1, 250);
+ RNA_def_property_range(prop, 1, 10000);
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)");
@@ -2647,10 +3154,12 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SCENE, NULL);
/* mode */
+ /* not used *//* deprecated !!!!!!!!!!!!! */
prop = RNA_def_property(srna, "use_occlusion_culling", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", WO_DBVT_CULLING);
- RNA_def_property_ui_text(prop, "DBVT culling",
- "Use optimized Bullet DBVT tree for view frustum and occlusion culling");
+ RNA_def_property_ui_text(prop, "DBVT Culling",
+ "Use optimized Bullet DBVT tree for view frustum and occlusion culling (more efficient, "
+ "but it can waste unnecessary CPU if the scene doesn't have occluder objects)");
/* not used *//* deprecated !!!!!!!!!!!!! */
prop = RNA_def_property(srna, "use_activity_culling", PROP_BOOLEAN, PROP_NONE);
@@ -2757,6 +3266,12 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
"Use extra textures like normal or specular maps for GLSL rendering");
RNA_def_property_update(prop, NC_SCENE | NA_EDITED, "rna_Scene_glsl_update");
+ prop = RNA_def_property(srna, "use_material_caching", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GAME_NO_MATERIAL_CACHING);
+ RNA_def_property_ui_text(prop, "Use Material Caching",
+ "Cache materials in the converter (this is faster, but can cause problems with older "
+ "Singletexture and Multitexture games)");
+
/* obstacle simulation */
prop = RNA_def_property(srna, "obstacle_simulation", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "obstacleSimulation");
@@ -2789,6 +3304,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
static void rna_def_scene_render_layer(BlenderRNA *brna)
{
StructRNA *srna;
+ PropertyRNA *prop;
srna = RNA_def_struct(brna, "SceneRenderLayer", NULL);
RNA_def_struct_ui_text(srna, "Scene Render Layer", "Render layer");
@@ -2796,6 +3312,15 @@ static void rna_def_scene_render_layer(BlenderRNA *brna)
RNA_def_struct_path_func(srna, "rna_SceneRenderLayer_path");
rna_def_render_layer_common(srna, 1);
+
+ /* Freestyle */
+ rna_def_freestyle_settings(brna);
+
+ prop = RNA_def_property(srna, "freestyle_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_pointer_sdna(prop, NULL, "freestyleConfig");
+ RNA_def_property_struct_type(prop, "FreestyleSettings");
+ RNA_def_property_ui_text(prop, "Freestyle Settings", "");
}
/* curve.splines */
@@ -2862,6 +3387,14 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna)
};
#endif
+#ifdef WITH_OPENJPEG
+ static EnumPropertyItem jp2_codec_items[] = {
+ {R_IMF_JP2_CODEC_JP2, "JP2", 0, "JP2", ""},
+ {R_IMF_JP2_CODEC_J2K, "J2K", 0, "J2K", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+#endif
+
StructRNA *srna;
PropertyRNA *prop;
@@ -2949,6 +3482,12 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "jp2_flag", R_IMF_JP2_FLAG_CINE_48);
RNA_def_property_ui_text(prop, "Cinema (48)", "Use Openjpeg Cinema Preset (48fps)");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
+ prop = RNA_def_property(srna, "jpeg2k_codec", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "jp2_codec");
+ RNA_def_property_enum_items(prop, jp2_codec_items);
+ RNA_def_property_ui_text(prop, "Codec", "Codec settings for Jpek2000");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
#endif
/* Cineon and DPX */
@@ -3022,8 +3561,9 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna)
{CODEC_ID_THEORA, "THEORA", 0, "Theora", ""},
{CODEC_ID_FLV1, "FLASH", 0, "Flash Video", ""},
{CODEC_ID_FFV1, "FFV1", 0, "FFmpeg video codec #1", ""},
- {CODEC_ID_QTRLE, "QTRLE", 0, "QTRLE", ""},
+ {CODEC_ID_QTRLE, "QTRLE", 0, "QT rle / QT Animation", ""},
{CODEC_ID_DNXHD, "DNXHD", 0, "DNxHD", ""},
+ {CODEC_ID_PNG, "PNG", 0, "PNG", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -3071,21 +3611,18 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "video_bitrate", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "video_bitrate");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, 1, 64000);
RNA_def_property_ui_text(prop, "Bitrate", "Video bitrate (kb/s)");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "minrate", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "rc_min_rate");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, 0, 48000);
RNA_def_property_ui_text(prop, "Min Rate", "Rate control: min rate (kb/s)");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "maxrate", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "rc_max_rate");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, 1, 96000);
RNA_def_property_ui_text(prop, "Max Rate", "Rate control: max rate (kb/s)");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
@@ -3291,8 +3828,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
static EnumPropertyItem alpha_mode_items[] = {
{R_ADDSKY, "SKY", 0, "Sky", "Transparent pixels are filled with sky color"},
- {R_ALPHAPREMUL, "PREMUL", 0, "Premultiplied", "Transparent RGB pixels are multiplied by the alpha channel"},
- {R_ALPHAKEY, "STRAIGHT", 0, "Straight Alpha", "Transparent RGB and alpha pixels are unmodified"},
+ {R_ALPHAPREMUL, "TRANSPARENT", 0, "Transparent", "World background is transparent with premultiplied alpha"},
{0, NULL, 0, NULL, NULL}
};
@@ -3379,6 +3915,13 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem freestyle_thickness_items[] = {
+ {R_LINE_THICKNESS_ABSOLUTE, "ABSOLUTE", 0, "Absolute", "Specify unit line thickness in pixels"},
+ {R_LINE_THICKNESS_RELATIVE, "RELATIVE", 0, "Relative",
+ "Unit line thickness is scaled by the proportion of the present vertical image "
+ "resolution to 480 pixels"},
+ {0, NULL, 0, NULL, NULL}};
+
rna_def_scene_ffmpeg_settings(brna);
#ifdef WITH_QUICKTIME
rna_def_scene_quicktime_settings(brna);
@@ -3400,14 +3943,14 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "resolution_x", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "xsch");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, 4, 10000);
+ RNA_def_property_range(prop, 4, 65536);
RNA_def_property_ui_text(prop, "Resolution X", "Number of horizontal pixels in the rendered image");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneCamera_update");
prop = RNA_def_property(srna, "resolution_y", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "ysch");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, 4, 10000);
+ RNA_def_property_range(prop, 4, 65536);
RNA_def_property_ui_text(prop, "Resolution Y", "Number of vertical pixels in the rendered image");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_SceneCamera_update");
@@ -3421,13 +3964,13 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "tile_x", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "tilex");
- RNA_def_property_range(prop, 8, 10000);
+ RNA_def_property_range(prop, 8, 65536);
RNA_def_property_ui_text(prop, "Tile X", "Horizontal tile size to use while rendering");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "tile_y", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "tiley");
- RNA_def_property_range(prop, 8, 10000);
+ RNA_def_property_range(prop, 8, 65536);
RNA_def_property_ui_text(prop, "Tile Y", "Vertical tile size to use while rendering");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
@@ -3582,13 +4125,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
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);
-
-#if 0
- prop = RNA_def_property(srna, "use_radiosity", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "mode", R_RADIO);
- RNA_def_property_ui_text(prop, "Radiosity", "Calculate radiosity in a pre-process before rendering");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-#endif
prop = RNA_def_property(srna, "use_sss", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "mode", R_SSS);
@@ -3623,6 +4159,11 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Edge Color", "Edge color");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ prop = RNA_def_property(srna, "use_freestyle", PROP_BOOLEAN, PROP_NONE);
+ 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, NULL);
+
/* threads */
prop = RNA_def_property(srna, "threads", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "threads");
@@ -3653,10 +4194,9 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
- prop = RNA_def_property(srna, "motion_blur_shutter", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "motion_blur_shutter", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "blurfac");
- RNA_def_property_range(prop, 0.01f, 10.0f);
- RNA_def_property_ui_range(prop, 0.01, 2.0f, 1, 0);
+ RNA_def_property_ui_range(prop, 0.01f, 2.0f, 1, 1);
RNA_def_property_ui_text(prop, "Shutter", "Time taken in frames between shutter open and close");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
@@ -3670,27 +4210,33 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
"(note that this disables save_buffers and full_sample)");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
+
prop = RNA_def_property(srna, "border_min_x", PROP_FLOAT, PROP_NONE);
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_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "border_min_y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "border.ymin");
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 Y", "Minimum Y value for the render border");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "border_max_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "border.xmax");
RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Border Maximum X", "Maximum X value for the render border");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "border_max_y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "border.ymax");
RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Border Maximum Y", "Maximum Y value for the render border");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
@@ -3727,13 +4273,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
"editor pipeline, if sequencer strips exist");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
- prop = RNA_def_property(srna, "use_color_unpremultiply", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "color_mgt_flag", R_COLOR_MANAGEMENT_PREDIVIDE);
- RNA_def_property_ui_text(prop, "Color Unpremultiply",
- "For premultiplied alpha render output, do color space conversion on "
- "colors without alpha, to avoid fringing on light backgrounds");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-
prop = RNA_def_property(srna, "use_file_extension", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_EXTENSION);
RNA_def_property_ui_text(prop, "File Extensions",
@@ -3879,6 +4418,19 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
"Calculate heights against unsubdivided low resolution mesh");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ prop = RNA_def_property(srna, "bake_samples", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "bake_samples");
+ RNA_def_property_range(prop, 64, 1024);
+ RNA_def_property_int_default(prop, 256);
+ RNA_def_property_ui_text(prop, "Samples", "Number of samples used for ambient occlusion baking from multires");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
+ prop = RNA_def_property(srna, "use_bake_to_vertex_color", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "bake_flag", R_BAKE_VCOL);
+ RNA_def_property_ui_text(prop, "Bake to Vertex Color",
+ "Bake to vertex colors instead of to a UV-mapped image");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
/* stamp */
prop = RNA_def_property(srna, "use_stamp_time", PROP_BOOLEAN, PROP_NONE);
@@ -3992,6 +4544,11 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_enum_items(prop, viewport_shade_items);
RNA_def_property_ui_text(prop, "Sequencer Preview Shading", "Method to draw in the sequencer view");
+ prop = RNA_def_property(srna, "use_sequencer_gl_textured_solid", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "seq_flag", R_SEQ_SOLID_TEX);
+ RNA_def_property_ui_text(prop, "Textured Solid", "Draw face-assigned textures in solid draw method");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SceneSequencer_update");
+
/* layers */
prop = RNA_def_property(srna, "layers", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "layers", NULL);
@@ -4068,6 +4625,17 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Persistent Data", "Keep render data around for faster re-renders");
RNA_def_property_update(prop, 0, "rna_Scene_use_persistent_data_update");
+ /* Freestyle line thickness options */
+ prop = RNA_def_property(srna, "line_thickness_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "line_thickness_mode");
+ RNA_def_property_enum_items(prop, freestyle_thickness_items);
+ RNA_def_property_ui_text(prop, "Line Thickness Mode", "Line thickness mode for Freestyle line drawing");
+
+ prop = RNA_def_property(srna, "unit_line_thickness", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "unit_line_thickness");
+ RNA_def_property_range(prop, 0.f, 10000.f);
+ RNA_def_property_ui_text(prop, "Unit Line Thickness", "Unit line thickness in pixels");
+
/* Scene API */
RNA_api_scene_render(srna);
}
@@ -4453,9 +5021,9 @@ void RNA_def_scene(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1);
- RNA_def_property_boolean_funcs(prop, NULL, "rna_Scene_use_nodes_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Use Nodes", "Enable the compositing node tree");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_use_nodes_update");
/* Sequencer */
prop = RNA_def_property(srna, "sequence_editor", PROP_POINTER, PROP_NONE);
@@ -4489,6 +5057,13 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET, NULL);
rna_def_scene_keying_sets_all(brna, prop);
+ /* Rigid Body Simulation */
+ prop = RNA_def_property(srna, "rigidbody_world", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "rigidbody_world");
+ RNA_def_property_struct_type(prop, "RigidBodyWorld");
+ RNA_def_property_ui_text(prop, "Rigid Body World", "");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
/* Tool Settings */
prop = RNA_def_property(srna, "tool_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
@@ -4623,19 +5198,23 @@ void RNA_def_scene(BlenderRNA *brna)
prop = RNA_def_property(srna, "sequencer_colorspace_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "sequencer_colorspace_settings");
- RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings");
+ 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");
/* Nestled Data */
+ /* *** Non-Animated *** */
+ RNA_define_animate_sdna(false);
rna_def_tool_settings(brna);
rna_def_unified_paint_settings(brna);
rna_def_unit_settings(brna);
rna_def_scene_image_format_data(brna);
- rna_def_scene_render_data(brna);
rna_def_scene_game_data(brna);
- rna_def_scene_render_layer(brna);
rna_def_transform_orientation(brna);
rna_def_selected_uv_element(brna);
+ RNA_define_animate_sdna(true);
+ /* *** Animated *** */
+ rna_def_scene_render_data(brna);
+ rna_def_scene_render_layer(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 012767b5845..82f054e62e0 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -32,6 +32,7 @@
#include <stdlib.h>
#include <stdio.h>
+#include "BLI_utildefines.h"
#include "BLI_path_util.h"
#include "RNA_define.h"
@@ -55,8 +56,10 @@
static void rna_Scene_frame_set(Scene *scene, int frame, float subframe)
{
- scene->r.cfra = frame;
- scene->r.subframe = subframe;
+ float cfra = (float)frame + subframe;
+
+ scene->r.cfra = floorf(cfra);
+ scene->r.subframe = cfra - floorf(cfra);
CLAMP(scene->r.cfra, MINAFRAME, MAXFRAME);
BKE_scene_update_for_newframe(G.main, scene, (1 << 20) - 1);
@@ -84,7 +87,7 @@ static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, 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.imtype,
+ BKE_makepicstring(name, rd->pic, G.main->name, (frame == INT_MIN) ? rd->cfra : frame, &rd->im_format,
rd->scemode & R_EXTENSION, TRUE);
}
@@ -101,6 +104,7 @@ static void rna_Scene_collada_export(
int selected,
int include_children,
int include_armatures,
+ int include_shapekeys,
int deform_bones_only,
int active_uv_only,
@@ -108,14 +112,16 @@ static void rna_Scene_collada_export(
int include_material_textures,
int use_texture_copies,
+ int use_ngons,
int use_object_instantiation,
int sort_by_name,
+ int export_transformation_type,
int second_life)
{
collada_export(scene, filepath, apply_modifiers, export_mesh_type, selected,
- include_children, include_armatures, deform_bones_only,
+ include_children, include_armatures, include_shapekeys, deform_bones_only,
active_uv_only, include_uv_textures, include_material_textures,
- use_texture_copies, use_object_instantiation, sort_by_name, second_life);
+ use_texture_copies, use_ngons, use_object_instantiation, sort_by_name, export_transformation_type, second_life);
}
#endif
@@ -149,6 +155,7 @@ void RNA_api_scene(StructRNA *srna)
parm = RNA_def_boolean(func, "selected", 0, "Selection Only", "Export only selected elements");
parm = RNA_def_boolean(func, "include_children", 0, "Include Children", "Export all children of selected objects (even if not selected)");
parm = RNA_def_boolean(func, "include_armatures", 0, "Include Armatures", "Export related armatures (even if not selected)");
+ parm = RNA_def_boolean(func, "include_shapekeys", 0, "Include Shape Keys", "Export all Shape Keys from Mesh Objects");
parm = RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only", "Only export deforming bones with armatures");
parm = RNA_def_boolean(func, "active_uv_only", 0, "Active UV Layer only", "Export only the active UV Layer");
@@ -156,9 +163,14 @@ void RNA_api_scene(StructRNA *srna)
parm = RNA_def_boolean(func, "include_material_textures", 0, "Include Material Textures", "Export textures assigned to the object Materials");
parm = RNA_def_boolean(func, "use_texture_copies", 0, "copy", "Copy textures to same folder where the .dae file is exported");
+ parm = RNA_def_boolean(func, "use_ngons", 1, "Use NGons", "Keep NGons in Export");
parm = RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instances", "Instantiate multiple Objects from same Data");
parm = RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name");
parm = RNA_def_boolean(func, "second_life", 0, "Export for Second Life", "Compatibility mode for Second Life");
+
+ parm = RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX,
+ "Transformation", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
+
RNA_def_function_ui_description(func, "Export to collada file");
#endif
}
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index 84e76fae896..b8b4ad5bb76 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -40,6 +40,9 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "BLI_utildefines.h"
+#include "bmesh.h"
+
static EnumPropertyItem particle_edit_hair_brush_items[] = {
{PE_BRUSH_NONE, "NONE", 0, "None", "Don't use any brush"},
{PE_BRUSH_COMB, "COMB", 0, "Comb", "Comb hairs"},
@@ -52,6 +55,18 @@ static EnumPropertyItem particle_edit_hair_brush_items[] = {
{0, NULL, 0, NULL, NULL}
};
+EnumPropertyItem symmetrize_direction_items[] = {
+ {BMO_SYMMETRIZE_NEGATIVE_X, "NEGATIVE_X", 0, "-X to +X", ""},
+ {BMO_SYMMETRIZE_POSITIVE_X, "POSITIVE_X", 0, "+X to -X", ""},
+
+ {BMO_SYMMETRIZE_NEGATIVE_Y, "NEGATIVE_Y", 0, "-Y to +Y", ""},
+ {BMO_SYMMETRIZE_POSITIVE_Y, "POSITIVE_Y", 0, "+Y to -Y", ""},
+
+ {BMO_SYMMETRIZE_NEGATIVE_Z, "NEGATIVE_Z", 0, "-Z to +Z", ""},
+ {BMO_SYMMETRIZE_POSITIVE_Z, "POSITIVE_Z", 0, "+Z to -Z", ""},
+ {0, NULL, 0, NULL, NULL},
+};
+
#ifdef RNA_RUNTIME
#include "MEM_guardedalloc.h"
@@ -59,8 +74,7 @@ static EnumPropertyItem particle_edit_hair_brush_items[] = {
#include "BKE_pointcache.h"
#include "BKE_particle.h"
#include "BKE_depsgraph.h"
-
-#include "BLI_pbvh.h"
+#include "BKE_pbvh.h"
#include "ED_particle.h"
@@ -176,6 +190,11 @@ static int rna_ParticleEdit_hair_get(PointerRNA *ptr)
return 0;
}
+static char *rna_ParticleEdit_path(PointerRNA *ptr)
+{
+ return BLI_strdup("tool_settings.particle_edit");
+}
+
static int rna_Brush_mode_poll(PointerRNA *ptr, PointerRNA value)
{
Scene *scene = (Scene *)ptr->id.data;
@@ -205,6 +224,11 @@ static void rna_Sculpt_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNU
if (ob) {
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
+
+ if (ob->sculpt) {
+ ob->sculpt->bm_smooth_shading = (scene->toolsettings->sculpt->flags &
+ SCULPT_DYNTOPO_SMOOTH_SHADING);
+ }
}
}
@@ -212,7 +236,7 @@ static void rna_Sculpt_ShowDiffuseColor_update(Main *UNUSED(bmain), Scene *scene
{
Object *ob = (scene->basact) ? scene->basact->object : NULL;
- if (ob) {
+ if (ob && ob->sculpt) {
Sculpt *sd = scene->toolsettings->sculpt;
ob->sculpt->show_diffuse_color = sd->flags & SCULPT_SHOW_DIFFUSE;
@@ -223,6 +247,38 @@ static void rna_Sculpt_ShowDiffuseColor_update(Main *UNUSED(bmain), Scene *scene
}
}
+static char *rna_Sculpt_path(PointerRNA *ptr)
+{
+ return BLI_strdup("tool_settings.sculpt");
+}
+
+static char *rna_VertexPaint_path(PointerRNA *ptr)
+{
+ Scene *scene = (Scene *)ptr->id.data;
+ ToolSettings *ts = scene->toolsettings;
+ if (ptr->data == ts->vpaint) {
+ return BLI_strdup("tool_settings.vertex_paint");
+ }
+ else {
+ return BLI_strdup("tool_settings.weight_paint");
+ }
+}
+
+static char *rna_ImagePaintSettings_path(PointerRNA *ptr)
+{
+ return BLI_strdup("tool_settings.image_paint");
+}
+
+static char *rna_UvSculpt_path(PointerRNA *ptr)
+{
+ return BLI_strdup("tool_settings.uv_sculpt");
+}
+
+static char *rna_ParticleBrush_path(PointerRNA *ptr)
+{
+ return BLI_strdup("tool_settings.particle_edit.brush");
+}
+
#else
static void rna_def_paint(BlenderRNA *brna)
@@ -264,6 +320,7 @@ static void rna_def_sculpt(BlenderRNA *brna)
PropertyRNA *prop;
srna = RNA_def_struct(brna, "Sculpt", "Paint");
+ RNA_def_struct_path_func(srna, "rna_Sculpt_path");
RNA_def_struct_ui_text(srna, "Sculpt", "");
prop = RNA_def_property(srna, "radial_symmetry", PROP_INT, PROP_XYZ);
@@ -320,6 +377,27 @@ static void rna_def_sculpt(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Show Diffuse Color",
"Show diffuse color of object and overlay sculpt mask on top of it");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Sculpt_ShowDiffuseColor_update");
+
+ prop = RNA_def_property(srna, "detail_size", PROP_INT, PROP_NONE);
+ RNA_def_property_ui_range(prop, 2, 100, 0, 0);
+ RNA_def_property_ui_text(prop, "Detail Size", "Maximum edge length for dynamic topology sculpting (in pixels)");
+
+ prop = RNA_def_property(srna, "use_smooth_shading", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_DYNTOPO_SMOOTH_SHADING);
+ RNA_def_property_ui_text(prop, "Smooth Shading",
+ "Show faces in dynamic-topology mode with smooth "
+ "shading rather than flat shaded");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Sculpt_update");
+
+ prop = RNA_def_property(srna, "use_edge_collapse", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_DYNTOPO_COLLAPSE);
+ RNA_def_property_ui_text(prop, "Collapse Short Edges",
+ "In dynamic-topology mode, collapse short edges "
+ "in addition to subdividing long ones");
+
+ prop = RNA_def_property(srna, "symmetrize_direction", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, symmetrize_direction_items);
+ RNA_def_property_ui_text(prop, "Direction", "Source and destination for symmetrize operator");
}
@@ -328,6 +406,7 @@ static void rna_def_uv_sculpt(BlenderRNA *brna)
StructRNA *srna;
srna = RNA_def_struct(brna, "UvSculpt", "Paint");
+ RNA_def_struct_path_func(srna, "rna_UvSculpt_path");
RNA_def_struct_ui_text(srna, "UV Sculpting", "");
}
@@ -340,6 +419,7 @@ static void rna_def_vertex_paint(BlenderRNA *brna)
srna = RNA_def_struct(brna, "VertexPaint", "Paint");
RNA_def_struct_sdna(srna, "VPaint");
+ RNA_def_struct_path_func(srna, "rna_VertexPaint_path");
RNA_def_struct_ui_text(srna, "Vertex Paint", "Properties of vertex and weight paint mode");
/* vertex paint only */
@@ -368,14 +448,10 @@ static void rna_def_image_paint(BlenderRNA *brna)
srna = RNA_def_struct(brna, "ImagePaint", "Paint");
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");
- /* booleans */
- prop = RNA_def_property(srna, "use_projection", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_DISABLE);
- RNA_def_property_ui_text(prop, "Project Paint",
- "Use projection painting for improved consistency in the brush strokes");
-
+ /* booleans */
prop = RNA_def_property(srna, "use_occlude", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_XRAY);
RNA_def_property_ui_text(prop, "Occlude", "Only paint onto the faces directly under the brush (slower)");
@@ -452,6 +528,7 @@ static void rna_def_particle_edit(BlenderRNA *brna)
srna = RNA_def_struct(brna, "ParticleEdit", NULL);
RNA_def_struct_sdna(srna, "ParticleEditSettings");
+ RNA_def_struct_path_func(srna, "rna_ParticleEdit_path");
RNA_def_struct_ui_text(srna, "Particle Edit", "Properties of particle editing mode");
prop = RNA_def_property(srna, "tool", PROP_ENUM, PROP_NONE);
@@ -547,9 +624,10 @@ static void rna_def_particle_edit(BlenderRNA *brna)
srna = RNA_def_struct(brna, "ParticleBrush", NULL);
RNA_def_struct_sdna(srna, "ParticleBrushData");
+ RNA_def_struct_path_func(srna, "rna_ParticleBrush_path");
RNA_def_struct_ui_text(srna, "Particle Brush", "Particle editing brush");
- prop = RNA_def_property(srna, "size", PROP_INT, PROP_DISTANCE);
+ prop = RNA_def_property(srna, "size", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 1, SHRT_MAX);
RNA_def_property_ui_range(prop, 1, 100, 10, 3);
RNA_def_property_ui_text(prop, "Radius", "Radius of the brush in pixels");
@@ -593,12 +671,15 @@ static void rna_def_particle_edit(BlenderRNA *brna)
void RNA_def_sculpt_paint(BlenderRNA *brna)
{
+ /* *** Non-Animated *** */
+ RNA_define_animate_sdna(false);
rna_def_paint(brna);
rna_def_sculpt(brna);
rna_def_uv_sculpt(brna);
rna_def_vertex_paint(brna);
rna_def_image_paint(brna);
rna_def_particle_edit(brna);
+ RNA_define_animate_sdna(true);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c
index 6097fa2ae96..547d0ff78c9 100644
--- a/source/blender/makesrna/intern/rna_sensor.c
+++ b/source/blender/makesrna/intern/rna_sensor.c
@@ -24,19 +24,20 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
+#include "DNA_constraint_types.h"
+#include "DNA_object_types.h"
+#include "DNA_sensor_types.h"
+
+#include "BLI_utildefines.h"
+
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "RNA_access.h"
#include "rna_internal.h"
-#include "DNA_constraint_types.h"
-#include "DNA_object_types.h"
-#include "DNA_sensor_types.h"
-
#include "WM_types.h"
/* Always keep in alphabetical order */
diff --git a/source/blender/makesrna/intern/rna_sensor_api.c b/source/blender/makesrna/intern/rna_sensor_api.c
index d920cbef4a2..476f0589bc9 100644
--- a/source/blender/makesrna/intern/rna_sensor_api.c
+++ b/source/blender/makesrna/intern/rna_sensor_api.c
@@ -28,15 +28,17 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
#include <stdio.h>
-#include "WM_types.h"
+#include "BLI_utildefines.h"
+
#include "RNA_define.h"
#include "rna_internal.h" /* own include */
+#include "WM_types.h"
+
#ifdef RNA_RUNTIME
#include "BKE_sca.h"
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 18a9b9683f8..ed9d12cd1e0 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -24,22 +24,19 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
#include <limits.h>
-#include "RNA_access.h"
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
-#include "rna_internal.h"
-
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "DNA_movieclip_types.h"
+#include "BLI_math.h"
+
+#include "BLF_translation.h"
+
#include "BKE_animsys.h"
#include "BKE_global.h"
#include "BKE_sequencer.h"
@@ -47,10 +44,13 @@
#include "MEM_guardedalloc.h"
-#include "WM_types.h"
-#include "BLI_math.h"
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
-#include "BLF_translation.h"
+#include "rna_internal.h"
+
+#include "WM_types.h"
typedef struct EffectInfo {
const char *struct_name;
@@ -412,7 +412,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_all_animdata_fix_paths_rename(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);
@@ -1325,6 +1325,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_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
@@ -1401,26 +1402,26 @@ static void rna_def_sequence(BlenderRNA *brna)
prop = RNA_def_property(srna, "frame_offset_start", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "startofs");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */
+// RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */
RNA_def_property_ui_text(prop, "Start Offset", "");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "frame_offset_end", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "endofs");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */
+// RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */
RNA_def_property_ui_text(prop, "End Offset", "");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "frame_still_start", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "startstill");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */
+// RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */
RNA_def_property_range(prop, 0, MAXFRAME);
RNA_def_property_ui_text(prop, "Start Still", "");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "frame_still_end", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "endstill");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */
+// RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* overlap tests */
RNA_def_property_range(prop, 0, MAXFRAME);
RNA_def_property_ui_text(prop, "End Still", "");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
@@ -1541,14 +1542,20 @@ static void rna_def_filter_video(StructRNA *srna)
{
PropertyRNA *prop;
+ static const EnumPropertyItem alpha_mode_items[] = {
+ {SEQ_ALPHA_STRAIGHT, "STRAIGHT", 0, "Straight", "RGB channels in transparent pixels are unaffected by the alpha channel"},
+ {SEQ_ALPHA_PREMUL, "PREMUL", 0, "Premultiplied", "RGB channels in transparent pixels are multiplied by the alpha channel"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
prop = RNA_def_property(srna, "use_deinterlace", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_FILTERY);
RNA_def_property_ui_text(prop, "De-Interlace", "For video movies to remove fields");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update_reopen_files");
- prop = RNA_def_property(srna, "use_premultiply", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_MAKE_PREMUL);
- RNA_def_property_ui_text(prop, "Premultiply", "Convert RGB from key alpha to premultiplied alpha");
+ prop = RNA_def_property(srna, "alpha_mode", PROP_ENUM, PROP_NONE);
+ 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_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "use_flip_x", PROP_BOOLEAN, PROP_NONE);
@@ -1694,7 +1701,7 @@ static void rna_def_color_management(StructRNA *srna)
prop = RNA_def_property(srna, "colorspace_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "strip->colorspace_settings");
- RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings");
+ RNA_def_property_struct_type(prop, "ColorManagedInputColorspaceSettings");
RNA_def_property_ui_text(prop, "Color Space Settings", "Input color space settings");
}
@@ -2052,13 +2059,13 @@ static void rna_def_transform(StructRNA *srna)
prop = RNA_def_property(srna, "scale_start_x", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "ScalexIni");
RNA_def_property_ui_text(prop, "Scale X", "");
- RNA_def_property_ui_range(prop, 0, 10, 3, 10);
+ RNA_def_property_ui_range(prop, 0, 10, 3, 6);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "scale_start_y", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "ScaleyIni");
RNA_def_property_ui_text(prop, "Scale Y", "");
- RNA_def_property_ui_range(prop, 0, 10, 3, 10);
+ RNA_def_property_ui_range(prop, 0, 10, 3, 6);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "use_uniform_scale", PROP_BOOLEAN, PROP_NONE);
@@ -2069,13 +2076,13 @@ static void rna_def_transform(StructRNA *srna)
prop = RNA_def_property(srna, "translate_start_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "xIni");
RNA_def_property_ui_text(prop, "Translate X", "");
- RNA_def_property_ui_range(prop, -500.0f, 500.0f, 3, 10);
+ RNA_def_property_ui_range(prop, -500.0f, 500.0f, 3, 6);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "translate_start_y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "yIni");
RNA_def_property_ui_text(prop, "Translate Y", "");
- RNA_def_property_ui_range(prop, -500.0f, 500.0f, 3, 10);
+ RNA_def_property_ui_range(prop, -500.0f, 500.0f, 3, 6);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "rotation_start", PROP_FLOAT, PROP_NONE);
@@ -2104,7 +2111,7 @@ static void rna_def_solid_color(StructRNA *srna)
RNA_def_struct_sdna_from(srna, "SolidColorVars", "effectdata");
- prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "col");
RNA_def_property_ui_text(prop, "Color", "");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c
index 7602ec99c2b..0c58d5cab6b 100644
--- a/source/blender/makesrna/intern/rna_sequencer_api.c
+++ b/source/blender/makesrna/intern/rna_sequencer_api.c
@@ -28,15 +28,17 @@
#include <stdio.h>
#include <string.h>
+#include "DNA_scene_types.h"
+#include "DNA_sequence_types.h"
+
+#include "BLI_utildefines.h"
+
#include "RNA_define.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "rna_internal.h"
-#include "DNA_scene_types.h"
-#include "DNA_sequence_types.h"
-
#ifdef RNA_RUNTIME
//#include "DNA_anim_types.h"
@@ -62,6 +64,16 @@
#include "WM_api.h"
+static void rna_Sequence_update_rnafunc(ID *id, Sequence *self, int do_data)
+{
+ if (do_data) {
+ BKE_sequencer_update_changed_seq_and_deps((Scene *)id, self, true, true);
+ // new_tstripdata(self); // need 2.6x version of this.
+ }
+ BKE_sequence_calc((Scene *)id, self);
+ BKE_sequence_calc_disp((Scene *)id, self);
+}
+
static void rna_Sequence_swap_internal(Sequence *seq_self, ReportList *reports, Sequence *seq_other)
{
const char *error_msg;
@@ -70,14 +82,14 @@ static void rna_Sequence_swap_internal(Sequence *seq_self, ReportList *reports,
BKE_report(reports, RPT_ERROR, error_msg);
}
-static Sequence *alloc_generic_sequence(Editing *ed, const char *name, int start_frame,
+static Sequence *alloc_generic_sequence(Editing *ed, const char *name, int frame_start,
int channel, int type, const char *file)
{
Sequence *seq;
Strip *strip;
StripElem *se;
- seq = BKE_sequence_alloc(ed->seqbasep, start_frame, channel);
+ seq = BKE_sequence_alloc(ed->seqbasep, frame_start, channel);
seq->type = type;
BLI_strncpy(seq->name + 2, name, sizeof(seq->name) - 2);
@@ -101,12 +113,12 @@ static Sequence *alloc_generic_sequence(Editing *ed, const char *name, int start
static Sequence *rna_Sequences_new_clip(ID *id, Editing *ed,
const char *name, MovieClip *clip, int channel,
- int start_frame)
+ int frame_start)
{
Scene *scene = (Scene *)id;
Sequence *seq;
- seq = alloc_generic_sequence(ed, name, start_frame, channel, SEQ_TYPE_MOVIECLIP, clip->name);
+ seq = alloc_generic_sequence(ed, name, frame_start, channel, SEQ_TYPE_MOVIECLIP, clip->name);
seq->clip = clip;
seq->len = BKE_movieclip_get_duration(clip);
id_us_plus((ID *)clip);
@@ -120,12 +132,12 @@ static Sequence *rna_Sequences_new_clip(ID *id, Editing *ed,
static Sequence *rna_Sequences_new_mask(ID *id, Editing *ed,
const char *name, Mask *mask, int channel,
- int start_frame)
+ int frame_start)
{
Scene *scene = (Scene *)id;
Sequence *seq;
- seq = alloc_generic_sequence(ed, name, start_frame, channel, SEQ_TYPE_MASK, mask->id.name);
+ seq = alloc_generic_sequence(ed, name, frame_start, channel, SEQ_TYPE_MASK, mask->id.name);
seq->mask = mask;
seq->len = BKE_mask_get_duration(mask);
id_us_plus((ID *)mask);
@@ -139,15 +151,15 @@ static Sequence *rna_Sequences_new_mask(ID *id, Editing *ed,
static Sequence *rna_Sequences_new_scene(ID *id, Editing *ed,
const char *name, Scene *sce_seq, int channel,
- int start_frame)
+ int frame_start)
{
Scene *scene = (Scene *)id;
Sequence *seq;
- seq = alloc_generic_sequence(ed, name, start_frame, channel, SEQ_TYPE_SCENE, NULL);
+ 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, start_frame, start_frame + seq->len, 0);
+ seq->scene_sound = 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);
@@ -159,12 +171,12 @@ static Sequence *rna_Sequences_new_scene(ID *id, Editing *ed,
static Sequence *rna_Sequences_new_image(ID *id, Editing *ed, ReportList *reports,
const char *name, const char *file, int channel,
- int start_frame)
+ int frame_start)
{
Scene *scene = (Scene *)id;
Sequence *seq;
- seq = alloc_generic_sequence(ed, name, start_frame, channel, SEQ_TYPE_IMAGE, file);
+ seq = alloc_generic_sequence(ed, name, frame_start, channel, SEQ_TYPE_IMAGE, file);
seq->len = 1;
if (seq->strip->stripdata->name[0] == '\0') {
@@ -183,12 +195,11 @@ static Sequence *rna_Sequences_new_image(ID *id, Editing *ed, ReportList *report
static Sequence *rna_Sequences_new_movie(ID *id, Editing *ed, ReportList *reports,
const char *name, const char *file, int channel,
- int start_frame)
+ int frame_start)
{
Scene *scene = (Scene *)id;
Sequence *seq;
- /* OCIO_TODO: support configurable color spaces for strips */
struct anim *an = openanim(file, IB_rect, 0, NULL);
if (an == NULL) {
@@ -196,7 +207,7 @@ static Sequence *rna_Sequences_new_movie(ID *id, Editing *ed, ReportList *report
return NULL;
}
- seq = alloc_generic_sequence(ed, name, start_frame, channel, SEQ_TYPE_MOVIE, file);
+ seq = alloc_generic_sequence(ed, name, frame_start, channel, SEQ_TYPE_MOVIE, file);
seq->anim = an;
seq->anim_preseek = IMB_anim_get_preseek(an);
seq->len = IMB_anim_get_duration(an, IMB_TC_RECORD_RUN);
@@ -210,7 +221,7 @@ static Sequence *rna_Sequences_new_movie(ID *id, Editing *ed, ReportList *report
#ifdef WITH_AUDASPACE
static Sequence *rna_Sequences_new_sound(ID *id, Editing *ed, Main *bmain, ReportList *reports,
- const char *name, const char *file, int channel, int start_frame)
+ const char *name, const char *file, int channel, int frame_start)
{
Scene *scene = (Scene *)id;
Sequence *seq;
@@ -222,11 +233,11 @@ static Sequence *rna_Sequences_new_sound(ID *id, Editing *ed, Main *bmain, Repor
return NULL;
}
- seq = alloc_generic_sequence(ed, name, start_frame, channel, SEQ_TYPE_SOUND_RAM, sound->name);
+ 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->scene_sound = sound_add_scene_sound(scene, seq, start_frame, start_frame + seq->len, 0);
+ seq->scene_sound = sound_add_scene_sound(scene, seq, frame_start, frame_start + seq->len, 0);
BKE_sequence_calc_disp(scene, seq);
@@ -237,7 +248,7 @@ static Sequence *rna_Sequences_new_sound(ID *id, Editing *ed, Main *bmain, Repor
#else /* WITH_AUDASPACE */
static Sequence *rna_Sequences_new_sound(ID *UNUSED(id), Editing *UNUSED(ed), Main *UNUSED(bmain), ReportList *reports,
const char *UNUSED(name), const char *UNUSED(file), int UNUSED(channel),
- int UNUSED(start_frame))
+ int UNUSED(frame_start))
{
BKE_report(reports, RPT_ERROR, "Blender compiled without Audaspace support");
return NULL;
@@ -246,7 +257,7 @@ static Sequence *rna_Sequences_new_sound(ID *UNUSED(id), Editing *UNUSED(ed), Ma
static Sequence *rna_Sequences_new_effect(ID *id, Editing *ed, ReportList *reports,
const char *name, int type, int channel,
- int start_frame, int end_frame,
+ int frame_start, int frame_end,
Sequence *seq1, Sequence *seq2, Sequence *seq3)
{
Scene *scene = (Scene *)id;
@@ -256,7 +267,7 @@ static Sequence *rna_Sequences_new_effect(ID *id, Editing *ed, ReportList *repor
switch (num_inputs) {
case 0:
- if (end_frame <= start_frame) {
+ if (frame_end <= frame_start) {
BKE_report(reports, RPT_ERROR, "Sequences.new_effect: end frame not set");
return NULL;
}
@@ -286,7 +297,7 @@ static Sequence *rna_Sequences_new_effect(ID *id, Editing *ed, ReportList *repor
return NULL;
}
- seq = alloc_generic_sequence(ed, name, start_frame, channel, type, NULL);
+ seq = alloc_generic_sequence(ed, name, frame_start, channel, type, NULL);
sh = BKE_sequence_get_effect(seq);
@@ -298,7 +309,7 @@ static Sequence *rna_Sequences_new_effect(ID *id, Editing *ed, ReportList *repor
if (!seq1) { /* effect has no deps */
seq->len = 1;
- BKE_sequence_tx_set_final_right(seq, end_frame);
+ BKE_sequence_tx_set_final_right(seq, frame_end);
}
seq->flag |= SEQ_USE_EFFECT_DEFAULT_FADE;
@@ -389,7 +400,13 @@ void RNA_api_sequence_strip(StructRNA *srna)
FunctionRNA *func;
PropertyRNA *parm;
- func = RNA_def_function(srna, "getStripElem", "BKE_sequencer_give_stripelem");
+ func = RNA_def_function(srna, "update", "rna_Sequence_update_rnafunc");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_ui_description(func, "Update the strip dimensions");
+ parm = RNA_def_boolean(func, "data", false, "Frame",
+ "Update strip data");
+
+ func = RNA_def_function(srna, "strip_elem_from_frame", "BKE_sequencer_give_stripelem");
RNA_def_function_ui_description(func, "Return the strip element from a given frame or None");
parm = RNA_def_int(func, "frame", 0, -MAXFRAME, MAXFRAME, "Frame",
"The frame to get the strip element from", -MAXFRAME, MAXFRAME);
@@ -470,7 +487,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_int(func, "channel", 0, 0, MAXSEQ - 1, "Channel",
"The channel for the new sequence", 0, MAXSEQ - 1);
RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_int(func, "start_frame", 0, -MAXFRAME, MAXFRAME, "",
+ parm = RNA_def_int(func, "frame_start", 0, -MAXFRAME, MAXFRAME, "",
"The start frame for the new sequence", -MAXFRAME, MAXFRAME);
RNA_def_property_flag(parm, PROP_REQUIRED);
/* return type */
@@ -487,7 +504,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_int(func, "channel", 0, 0, MAXSEQ - 1, "Channel",
"The channel for the new sequence", 0, MAXSEQ - 1);
RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_int(func, "start_frame", 0, -MAXFRAME, MAXFRAME, "",
+ parm = RNA_def_int(func, "frame_start", 0, -MAXFRAME, MAXFRAME, "",
"The start frame for the new sequence", -MAXFRAME, MAXFRAME);
RNA_def_property_flag(parm, PROP_REQUIRED);
/* return type */
@@ -504,7 +521,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_int(func, "channel", 0, 0, MAXSEQ - 1, "Channel",
"The channel for the new sequence", 0, MAXSEQ - 1);
RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_int(func, "start_frame", 0, -MAXFRAME, MAXFRAME, "",
+ parm = RNA_def_int(func, "frame_start", 0, -MAXFRAME, MAXFRAME, "",
"The start frame for the new sequence", -MAXFRAME, MAXFRAME);
RNA_def_property_flag(parm, PROP_REQUIRED);
/* return type */
@@ -521,7 +538,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_int(func, "channel", 0, 0, MAXSEQ - 1, "Channel",
"The channel for the new sequence", 0, MAXSEQ - 1);
RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_int(func, "start_frame", 0, -MAXFRAME, MAXFRAME, "",
+ parm = RNA_def_int(func, "frame_start", 0, -MAXFRAME, MAXFRAME, "",
"The start frame for the new sequence", -MAXFRAME, MAXFRAME);
RNA_def_property_flag(parm, PROP_REQUIRED);
/* return type */
@@ -538,7 +555,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_int(func, "channel", 0, 0, MAXSEQ - 1, "Channel",
"The channel for the new sequence", 0, MAXSEQ - 1);
RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_int(func, "start_frame", 0, -MAXFRAME, MAXFRAME, "",
+ parm = RNA_def_int(func, "frame_start", 0, -MAXFRAME, MAXFRAME, "",
"The start frame for the new sequence", -MAXFRAME, MAXFRAME);
RNA_def_property_flag(parm, PROP_REQUIRED);
/* return type */
@@ -555,7 +572,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_int(func, "channel", 0, 0, MAXSEQ - 1, "Channel",
"The channel for the new sequence", 0, MAXSEQ - 1);
RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_int(func, "start_frame", 0, -MAXFRAME, MAXFRAME, "",
+ parm = RNA_def_int(func, "frame_start", 0, -MAXFRAME, MAXFRAME, "",
"The start frame for the new sequence", -MAXFRAME, MAXFRAME);
RNA_def_property_flag(parm, PROP_REQUIRED);
/* return type */
@@ -572,12 +589,13 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
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);
+ /* don't use MAXFRAME since it makes importer scripts fail */
RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_int(func, "start_frame", 0, -MAXFRAME, MAXFRAME, "",
- "The start frame for the new sequence", -MAXFRAME, MAXFRAME);
+ parm = RNA_def_int(func, "frame_start", 0, INT_MIN, INT_MAX, "",
+ "The start frame for the new sequence", INT_MIN, INT_MAX);
RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_int(func, "end_frame", 0, -MAXFRAME, MAXFRAME, "",
- "The end frame for the new sequence", -MAXFRAME, MAXFRAME);
+ RNA_def_int(func, "frame_end", 0, INT_MIN, INT_MAX, "",
+ "The end frame for the new sequence", INT_MIN, INT_MAX);
RNA_def_pointer(func, "seq1", "Sequence", "", "Sequence 1 for effect");
RNA_def_pointer(func, "seq2", "Sequence", "", "Sequence 2 for effect");
RNA_def_pointer(func, "seq3", "Sequence", "", "Sequence 3 for effect");
diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c
index bdcda79583e..86b97b93437 100644
--- a/source/blender/makesrna/intern/rna_smoke.c
+++ b/source/blender/makesrna/intern/rna_smoke.c
@@ -62,7 +62,7 @@ static void rna_Smoke_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR
static void rna_Smoke_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
rna_Smoke_update(bmain, scene, ptr);
- DAG_scene_sort(bmain, scene);
+ DAG_relations_tag_update(bmain);
}
static void rna_Smoke_resetCache(Main *bmain, Scene *scene, PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 2b2e8d97499..309de9c7fd1 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -24,23 +24,20 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
+#include <string.h>
#include "MEM_guardedalloc.h"
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "rna_internal.h"
-
#include "BLF_translation.h"
#include "BKE_key.h"
#include "BKE_movieclip.h"
+#include "BKE_node.h"
#include "DNA_action_types.h"
#include "DNA_key_types.h"
+#include "DNA_material_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_space_types.h"
@@ -48,6 +45,11 @@
#include "DNA_mask_types.h"
#include "DNA_view3d_types.h"
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "rna_internal.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -79,9 +81,9 @@ EnumPropertyItem space_type_items[] = {
};
static EnumPropertyItem draw_channels_items[] = {
- {0, "COLOR", ICON_IMAGE_RGB, "Color", "Draw image with RGB colors"},
{SI_USE_ALPHA, "COLOR_ALPHA", ICON_IMAGE_RGB_ALPHA, "Color and Alpha",
"Draw image with RGB colors and alpha transparency"},
+ {0, "COLOR", ICON_IMAGE_RGB, "Color", "Draw image with RGB colors"},
{SI_SHOW_ALPHA, "ALPHA", ICON_IMAGE_ALPHA, "Alpha", "Draw alpha transparency channel"},
{SI_SHOW_ZBUF, "Z_BUFFER", ICON_IMAGE_ZDEPTH, "Z-Buffer",
"Draw Z-buffer associated with image (mapped from camera clip start to end)"},
@@ -144,6 +146,7 @@ EnumPropertyItem clip_editor_mode_items[] = {
#include "BKE_paint.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "BKE_icons.h"
#include "ED_image.h"
#include "ED_node.h"
@@ -152,6 +155,8 @@ EnumPropertyItem clip_editor_mode_items[] = {
#include "ED_sequencer.h"
#include "ED_clip.h"
+#include "GPU_material.h"
+
#include "IMB_imbuf_types.h"
static StructRNA *rna_Space_refine(struct PointerRNA *ptr)
@@ -321,7 +326,7 @@ static void rna_View3D_CursorLocation_get(PointerRNA *ptr, float *values)
View3D *v3d = (View3D *)(ptr->data);
bScreen *sc = (bScreen *)ptr->id.data;
Scene *scene = (Scene *)sc->scene;
- float *loc = give_cursor(scene, v3d);
+ const float *loc = give_cursor(scene, v3d);
copy_v3_v3(values, loc);
}
@@ -376,6 +381,31 @@ static void rna_SpaceView3D_viewport_shade_update(Main *UNUSED(bmain), Scene *UN
}
}
+static void rna_SpaceView3D_matcap_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ View3D *v3d = (View3D *)(ptr->data);
+
+ if (v3d->defmaterial) {
+ Material *ma = v3d->defmaterial;
+
+ if (ma->preview)
+ BKE_previewimg_free(&ma->preview);
+
+ if (ma->gpumaterial.first)
+ GPU_material_free(ma);
+
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, ma);
+ }
+}
+
+static void rna_SpaceView3D_matcap_enable(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ View3D *v3d = (View3D *)(ptr->data);
+
+ if (v3d->matcap_icon == 0)
+ v3d->matcap_icon = ICON_MATCAP_01;
+}
+
static void rna_SpaceView3D_pivot_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
if (U.uiflag & USER_LOCKAROUND) {
@@ -482,8 +512,9 @@ static void rna_RegionView3D_view_rotation_set(PointerRNA *ptr, const float *val
static void rna_RegionView3D_view_matrix_set(PointerRNA *ptr, const float *values)
{
RegionView3D *rv3d = (RegionView3D *)(ptr->data);
- negate_v3_v3(rv3d->ofs, values);
- ED_view3d_from_m4((float (*)[4])values, rv3d->ofs, rv3d->viewquat, &rv3d->dist);
+ float mat[4][4];
+ invert_m4_m4(mat, (float (*)[4])values);
+ ED_view3d_from_m4(mat, rv3d->ofs, rv3d->viewquat, &rv3d->dist);
}
/* api call */
@@ -603,15 +634,18 @@ static EnumPropertyItem *rna_SpaceImageEditor_draw_channels_itemf(bContext *UNUS
if (alpha && zbuf)
return draw_channels_items;
- RNA_enum_items_add_value(&item, &totitem, draw_channels_items, 0);
-
if (alpha) {
RNA_enum_items_add_value(&item, &totitem, draw_channels_items, SI_USE_ALPHA);
+ RNA_enum_items_add_value(&item, &totitem, draw_channels_items, 0);
RNA_enum_items_add_value(&item, &totitem, draw_channels_items, SI_SHOW_ALPHA);
}
else if (zbuf) {
+ RNA_enum_items_add_value(&item, &totitem, draw_channels_items, 0);
RNA_enum_items_add_value(&item, &totitem, draw_channels_items, SI_SHOW_ZBUF);
}
+ else {
+ RNA_enum_items_add_value(&item, &totitem, draw_channels_items, 0);
+ }
RNA_enum_item_end(&item, &totitem);
*free = 1;
@@ -775,7 +809,7 @@ static void rna_SpaceProperties_align_set(PointerRNA *ptr, int value)
static void rna_ConsoleLine_body_get(PointerRNA *ptr, char *value)
{
ConsoleLine *ci = (ConsoleLine *)ptr->data;
- strcpy(value, ci->line);
+ memcpy(value, ci->line, ci->len + 1);
}
static int rna_ConsoleLine_body_length(PointerRNA *ptr)
@@ -871,6 +905,9 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *UNUSED(bmain), Scene *s
/* show new id-count of action we're replacing */
adt->action = saction->action;
id_us_plus(&adt->action->id);
+
+ /* force update of animdata */
+ adt->recalc |= ADT_RECALC_ANIM;
}
/* force depsgraph flush too */
@@ -979,20 +1016,91 @@ static void rna_BackgroundImage_clear(View3D *v3d)
/* Space Node Editor */
-static int rna_SpaceNodeEditor_node_tree_poll(PointerRNA *ptr, PointerRNA value)
+static void rna_SpaceNodeEditor_node_tree_set(PointerRNA *ptr, const PointerRNA value)
+{
+ SpaceNode *snode = (SpaceNode *)ptr->data;
+ ED_node_tree_start(snode, (bNodeTree *)value.data, NULL, NULL);
+}
+
+static int rna_SpaceNodeEditor_node_tree_poll(PointerRNA *ptr, const PointerRNA value)
{
SpaceNode *snode = (SpaceNode *)ptr->data;
bNodeTree *ntree = (bNodeTree *)value.data;
- /* exclude group trees, only trees of the active type */
- return (ntree->nodetype == 0 && ntree->type == snode->treetype);
+ /* node tree type must match the selected type in node editor */
+ return (strcmp(snode->tree_idname, ntree->idname) == 0);
}
-static void rna_SpaceNodeEditor_node_tree_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+static void rna_SpaceNodeEditor_node_tree_update(const bContext *C, PointerRNA *UNUSED(ptr))
+{
+ ED_node_tree_update(C);
+}
+
+static int rna_SpaceNodeEditor_tree_type_get(PointerRNA *ptr)
+{
+ SpaceNode *snode = (SpaceNode *)ptr->data;
+ return rna_node_tree_idname_to_enum(snode->tree_idname);
+}
+static void rna_SpaceNodeEditor_tree_type_set(PointerRNA *ptr, int value)
{
SpaceNode *snode = (SpaceNode *)ptr->data;
+ ED_node_set_tree_type(snode, rna_node_tree_type_from_enum(value));
+}
+static int rna_SpaceNodeEditor_tree_type_poll(void *Cv, bNodeTreeType *type)
+{
+ bContext *C = (bContext *)Cv;
+ if (type->poll)
+ return type->poll(C, type);
+ else
+ return TRUE;
+}
+static EnumPropertyItem *rna_SpaceNodeEditor_tree_type_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
+{
+ return rna_node_tree_type_itemf(C, rna_SpaceNodeEditor_tree_type_poll, free);
+}
+
+static void rna_SpaceNodeEditor_path_get(PointerRNA *ptr, char *value)
+{
+ SpaceNode *snode = ptr->data;
+ ED_node_tree_path_get(snode, value);
+}
+
+static int rna_SpaceNodeEditor_path_length(PointerRNA *ptr)
+{
+ SpaceNode *snode = ptr->data;
+ return ED_node_tree_path_length(snode);
+}
+
+void rna_SpaceNodeEditor_path_clear(SpaceNode *snode, bContext *C)
+{
+ ED_node_tree_start(snode, NULL, NULL, NULL);
+ ED_node_tree_update(C);
+}
+
+void rna_SpaceNodeEditor_path_start(SpaceNode *snode, bContext *C, PointerRNA *node_tree)
+{
+ ED_node_tree_start(snode, (bNodeTree *)node_tree->data, NULL, NULL);
+ ED_node_tree_update(C);
+}
+
+void rna_SpaceNodeEditor_path_push(SpaceNode *snode, bContext *C, ReportList *reports, PointerRNA *node)
+{
+ PointerRNA tree_ptr;
+
+ tree_ptr = RNA_pointer_get(node, "node_tree");
+ if (!tree_ptr.data) {
+ BKE_reportf(reports, RPT_WARNING, "Missing node group tree in node %s", ((bNode *)node->data)->name);
+ return;
+ }
- ED_node_tree_update(snode, scene);
+ ED_node_tree_push(snode, (bNodeTree *)tree_ptr.data, (bNode *)node->data);
+ ED_node_tree_update(C);
+}
+
+void rna_SpaceNodeEditor_path_pop(SpaceNode *snode, bContext *C)
+{
+ ED_node_tree_pop(snode);
+ ED_node_tree_update(C);
}
static EnumPropertyItem *rna_SpaceProperties_texture_context_itemf(bContext *C, PointerRNA *UNUSED(ptr),
@@ -1250,9 +1358,9 @@ static void rna_def_space_outliner(BlenderRNA *brna)
{SO_SAME_TYPE, "SAME_TYPES", 0, "Same Types",
"Display datablocks of all objects of same type as selected object"},
{SO_GROUPS, "GROUPS", 0, "Groups", "Display groups and their datablocks"},
- {SO_LIBRARIES, "LIBRARIES", 0, "Libraries", "Display libraries"},
{SO_SEQUENCE, "SEQUENCE", 0, "Sequence", "Display sequence datablocks"},
- {SO_DATABLOCKS, "DATABLOCKS", 0, "Datablocks", "Display raw datablocks"},
+ {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_KEYMAP, "KEYMAPS", 0, "Key Maps", "Display keymap datablocks"},
{0, NULL, 0, NULL, NULL}
@@ -1460,6 +1568,7 @@ static void rna_def_backgroundImages(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_ui_description(func, "Remove all background images");
}
+
static void rna_def_space_view3d(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1496,6 +1605,35 @@ static void rna_def_space_view3d(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem view3d_matcap_items[] = {
+ {ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""},
+ {ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""},
+ {ICON_MATCAP_03, "03", ICON_MATCAP_03, "", ""},
+ {ICON_MATCAP_04, "04", ICON_MATCAP_04, "", ""},
+ {ICON_MATCAP_05, "05", ICON_MATCAP_05, "", ""},
+ {ICON_MATCAP_06, "06", ICON_MATCAP_06, "", ""},
+ {ICON_MATCAP_07, "07", ICON_MATCAP_07, "", ""},
+ {ICON_MATCAP_08, "08", ICON_MATCAP_08, "", ""},
+ {ICON_MATCAP_09, "09", ICON_MATCAP_09, "", ""},
+ {ICON_MATCAP_10, "10", ICON_MATCAP_10, "", ""},
+ {ICON_MATCAP_11, "11", ICON_MATCAP_11, "", ""},
+ {ICON_MATCAP_12, "12", ICON_MATCAP_12, "", ""},
+ {ICON_MATCAP_13, "13", ICON_MATCAP_13, "", ""},
+ {ICON_MATCAP_14, "14", ICON_MATCAP_14, "", ""},
+ {ICON_MATCAP_15, "15", ICON_MATCAP_15, "", ""},
+ {ICON_MATCAP_16, "16", ICON_MATCAP_16, "", ""},
+ {ICON_MATCAP_17, "17", ICON_MATCAP_17, "", ""},
+ {ICON_MATCAP_18, "18", ICON_MATCAP_18, "", ""},
+ {ICON_MATCAP_19, "19", ICON_MATCAP_19, "", ""},
+ {ICON_MATCAP_20, "20", ICON_MATCAP_20, "", ""},
+ {ICON_MATCAP_21, "21", ICON_MATCAP_21, "", ""},
+ {ICON_MATCAP_22, "22", ICON_MATCAP_22, "", ""},
+ {ICON_MATCAP_23, "23", ICON_MATCAP_23, "", ""},
+ {ICON_MATCAP_24, "24", ICON_MATCAP_24, "", ""},
+ {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");
@@ -1659,6 +1797,12 @@ static void rna_def_space_view3d(BlenderRNA *brna)
"Show dashed lines indicating parent or constraint relationships");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ prop = RNA_def_property(srna, "show_grease_pencil", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_SHOW_GPENCIL);
+ RNA_def_property_ui_text(prop, "Show Grease Pencil",
+ "Show grease pencil for this view");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
prop = RNA_def_property(srna, "show_textured_solid", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_SOLID_TEX);
RNA_def_property_ui_text(prop, "Textured Solid", "Display face-assigned textures in solid view");
@@ -1810,6 +1954,17 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Show 3D Marker Names", "Show names for reconstructed tracks objects");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ prop = RNA_def_property(srna, "use_matcap", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_SOLID_MATCAP);
+ RNA_def_property_ui_text(prop, "Matcap", "Active Objects draw images mapped on normals, enhancing Solid Draw Mode");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_matcap_enable");
+
+ prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "matcap_icon");
+ RNA_def_property_enum_items(prop, view3d_matcap_items);
+ 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");
+
/* region */
srna = RNA_def_struct(brna, "RegionView3D", NULL);
@@ -1914,6 +2069,7 @@ static void rna_def_space_buttons(BlenderRNA *brna)
static EnumPropertyItem buttons_context_items[] = {
{BCONTEXT_SCENE, "SCENE", ICON_SCENE, "Scene", "Scene"},
{BCONTEXT_RENDER, "RENDER", ICON_SCENE_DATA, "Render", "Render"},
+ {BCONTEXT_RENDER_LAYER, "RENDER_LAYER", ICON_RENDERLAYERS, "Render Layers", "Render Layers"},
{BCONTEXT_WORLD, "WORLD", ICON_WORLD, "World", "World"},
{BCONTEXT_OBJECT, "OBJECT", ICON_OBJECT_DATA, "Object", "Object"},
{BCONTEXT_CONSTRAINT, "CONSTRAINT", ICON_CONSTRAINT, "Constraints", "Constraints"},
@@ -1970,7 +2126,7 @@ static void rna_def_space_buttons(BlenderRNA *brna)
/* note: custom set function is ONLY to avoid rna setting a user for this. */
RNA_def_property_pointer_funcs(prop, NULL, "rna_SpaceProperties_pin_id_set",
"rna_SpaceProperties_pin_id_typef", NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_PROPERTIES, "rna_SpaceProperties_pin_id_update");
prop = RNA_def_property(srna, "use_pin_id", PROP_BOOLEAN, PROP_NONE);
@@ -2044,6 +2200,12 @@ static void rna_def_space_image(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Draw Repeated", "Draw the image repeated outside of the main view");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
+ prop = RNA_def_property(srna, "show_grease_pencil", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_SHOW_GPENCIL);
+ RNA_def_property_ui_text(prop, "Show Grease Pencil",
+ "Show grease pencil for this view");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
+
prop = RNA_def_property(srna, "draw_channels", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, draw_channels_items);
@@ -2159,6 +2321,13 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem preview_channels_items[] = {
+ {SEQ_USE_ALPHA, "COLOR_ALPHA", ICON_IMAGE_RGB_ALPHA, "Color and Alpha",
+ "Draw image with RGB colors and alpha transparency"},
+ {0, "COLOR", ICON_IMAGE_RGB, "Color", "Draw image with RGB colors"},
+ {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");
@@ -2176,7 +2345,7 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
RNA_def_property_enum_items(prop, display_mode_items);
RNA_def_property_ui_text(prop, "Display Mode", "View mode to use for displaying sequencer output");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
-
+
/* flags */
prop = RNA_def_property(srna, "show_frame_indicator", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SEQ_NO_DRAW_CFRANUM);
@@ -2209,13 +2378,25 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
+ prop = RNA_def_property(srna, "show_grease_pencil", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_GPENCIL);
+ RNA_def_property_ui_text(prop, "Show Grease Pencil",
+ "Show grease pencil for this view");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
+
prop = RNA_def_property(srna, "display_channel", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "chanshown");
RNA_def_property_ui_text(prop, "Display Channel",
"The channel number shown in the image preview. 0 is the result of all strips combined");
RNA_def_property_range(prop, -5, MAXSEQ);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
-
+
+ prop = RNA_def_property(srna, "preview_channels", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
+ RNA_def_property_enum_items(prop, preview_channels_items);
+ 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, "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");
@@ -2353,11 +2534,11 @@ static void rna_def_space_dopesheet(BlenderRNA *brna)
/* XXX: action-editor is currently for object-level only actions, so show that using object-icon hint */
static EnumPropertyItem mode_items[] = {
- {SACTCONT_DOPESHEET, "DOPESHEET", ICON_OOPS, "DopeSheet", "DopeSheet Editor"},
- {SACTCONT_ACTION, "ACTION", ICON_OBJECT_DATA, "Action Editor", "Action Editor"},
- {SACTCONT_SHAPEKEY, "SHAPEKEY", ICON_SHAPEKEY_DATA, "ShapeKey Editor", "ShapeKey Editor"},
- {SACTCONT_GPENCIL, "GPENCIL", ICON_GREASEPENCIL, "Grease Pencil", "Grease Pencil"},
- {SACTCONT_MASK, "MASK", ICON_MOD_MASK, "Mask", "Mask Editor"},
+ {SACTCONT_DOPESHEET, "DOPESHEET", ICON_OOPS, "DopeSheet", "Edit all keyframes in scene"},
+ {SACTCONT_ACTION, "ACTION", ICON_OBJECT_DATA, "Action Editor", "Edit keyframes in active object's Object-level action"},
+ {SACTCONT_SHAPEKEY, "SHAPEKEY", ICON_SHAPEKEY_DATA, "ShapeKey Editor", "Edit keyframes in active object's Shape Keys action"},
+ {SACTCONT_GPENCIL, "GPENCIL", ICON_GREASEPENCIL, "Grease Pencil", "Edit timings for all Grease Pencil sketches in file"},
+ {SACTCONT_MASK, "MASK", ICON_MOD_MASK, "Mask", "Edit timings for Mask Editor splines"},
{0, NULL, 0, NULL, NULL}
};
@@ -2453,7 +2634,7 @@ static void rna_def_space_graph(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- /* this is basically the same as the one for the 3D-View, but with some entries ommitted */
+ /* this is basically the same as the one for the 3D-View, but with some entries omitted */
static EnumPropertyItem gpivot_items[] = {
{V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center", ""},
{V3D_CURSOR, "CURSOR", ICON_CURSOR, "2D Cursor", ""},
@@ -2677,6 +2858,11 @@ static void rna_def_space_time(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_DYNAMICPAINT);
RNA_def_property_ui_text(prop, "Dynamic Paint", "Show the active object's Dynamic Paint cache");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL);
+
+ prop = RNA_def_property(srna, "cache_rigidbody", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_RIGIDBODY);
+ RNA_def_property_ui_text(prop, "Rigid Body", "Show the active object's Rigid Body cache");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL);
}
static void rna_def_console_line(BlenderRNA *brna)
@@ -2701,6 +2887,7 @@ static void rna_def_console_line(BlenderRNA *brna)
"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);
prop = RNA_def_property(srna, "current_character", PROP_INT, PROP_NONE); /* copied from text editor */
RNA_def_property_int_sdna(prop, NULL, "cursor");
@@ -2940,19 +3127,82 @@ static void rna_def_space_info(BlenderRNA *brna)
static void rna_def_space_userpref(BlenderRNA *brna)
{
+ static EnumPropertyItem filter_type_items[] = {
+ {0, "NAME", 0, "Name", "Filter based on the operator name"},
+ {1, "KEY", 0, "Key-Binding", "Filter based on key bindings"},
+ {0, NULL, 0, NULL, NULL}};
+
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "SpaceUserPreferences", "Space");
RNA_def_struct_sdna(srna, "SpaceUserPref");
RNA_def_struct_ui_text(srna, "Space User Preferences", "User preferences space data");
-
+
+ prop = RNA_def_property(srna, "filter_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "filter_type");
+ RNA_def_property_enum_items(prop, filter_type_items);
+ RNA_def_property_ui_text(prop, "Filter Type", "Filter method");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, NULL);
+
prop = RNA_def_property(srna, "filter_text", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "filter");
RNA_def_property_ui_text(prop, "Filter", "Search term for filtering in the UI");
}
+static void rna_def_node_tree_path(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "NodeTreePath", NULL);
+ RNA_def_struct_sdna(srna, "bNodeTreePath");
+ RNA_def_struct_ui_text(srna, "Node Tree Path", "Element of the node space tree path");
+
+ prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "nodetree");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Node Tree", "Base node tree from context");
+}
+
+static void rna_def_space_node_path_api(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ PropertyRNA *prop, *parm;
+ FunctionRNA *func;
+
+ RNA_def_property_srna(cprop, "SpaceNodeEditorPath");
+ srna = RNA_def_struct(brna, "SpaceNodeEditorPath", NULL);
+ RNA_def_struct_sdna(srna, "SpaceNode");
+ RNA_def_struct_ui_text(srna, "Space Node Editor Path", "History of node trees in the editor");
+
+ prop = RNA_def_property(srna, "to_string", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop, "rna_SpaceNodeEditor_path_get", "rna_SpaceNodeEditor_path_length", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_struct_ui_text(srna, "Path", "Get the node tree path as a string");
+
+ func = RNA_def_function(srna, "clear", "rna_SpaceNodeEditor_path_clear");
+ RNA_def_function_ui_description(func, "Reset the node tree path");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+
+ func = RNA_def_function(srna, "start", "rna_SpaceNodeEditor_path_start");
+ RNA_def_function_ui_description(func, "Set the root node tree");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ parm = RNA_def_pointer(func, "node_tree", "NodeTree", "Node Tree", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
+
+ func = RNA_def_function(srna, "push", "rna_SpaceNodeEditor_path_push");
+ RNA_def_function_ui_description(func, "Append a node group tree to the path");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "node", "NodeGroup", "Node", "Group node");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
+
+ func = RNA_def_function(srna, "pop", "rna_SpaceNodeEditor_path_pop");
+ RNA_def_function_ui_description(func, "Remove the last node tree from the path");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+}
+
static void rna_def_space_node(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2972,9 +3222,9 @@ static void rna_def_space_node(BlenderRNA *brna)
};
static EnumPropertyItem backdrop_channels_items[] = {
- {0, "COLOR", ICON_IMAGE_RGB, "Color", "Draw image with RGB colors"},
{SNODE_USE_ALPHA, "COLOR_ALPHA", ICON_IMAGE_RGB_ALPHA, "Color and Alpha",
"Draw image with RGB colors and alpha transparency"},
+ {0, "COLOR", ICON_IMAGE_RGB, "Color", "Draw image with RGB colors"},
{SNODE_SHOW_ALPHA, "ALPHA", ICON_IMAGE_ALPHA, "Alpha", "Draw alpha transparency channel"},
{SNODE_SHOW_R, "RED", ICON_COLOR_RED, "Red", ""},
{SNODE_SHOW_G, "GREEN", ICON_COLOR_GREEN, "Green", ""},
@@ -2982,13 +3232,17 @@ static void rna_def_space_node(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem dummy_items[] = {
+ {0, "DUMMY", 0, "", ""},
+ {0, NULL, 0, NULL, NULL}};
+
srna = RNA_def_struct(brna, "SpaceNodeEditor", "Space");
RNA_def_struct_sdna(srna, "SpaceNode");
RNA_def_struct_ui_text(srna, "Space Node Editor", "Node editor space data");
prop = RNA_def_property(srna, "tree_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "treetype");
- RNA_def_property_enum_items(prop, nodetree_type_items);
+ RNA_def_property_enum_items(prop, dummy_items);
+ RNA_def_property_enum_funcs(prop, "rna_SpaceNodeEditor_tree_type_get", "rna_SpaceNodeEditor_tree_type_set", "rna_SpaceNodeEditor_tree_type_itemf");
RNA_def_property_ui_text(prop, "Tree Type", "Node tree type to display and edit");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, NULL);
@@ -3013,23 +3267,41 @@ static void rna_def_space_node(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "ID From", "Datablock from which the edited datablock is linked");
+ prop = RNA_def_property(srna, "path", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "treepath", NULL);
+ RNA_def_property_struct_type(prop, "NodeTreePath");
+ RNA_def_property_ui_text(prop, "Node Tree Path", "Path from the data block to the currently edited node tree");
+ rna_def_space_node_path_api(brna, prop);
+
prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_SpaceNodeEditor_node_tree_set", NULL, "rna_SpaceNodeEditor_node_tree_poll");
RNA_def_property_pointer_sdna(prop, NULL, "nodetree");
- RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_SpaceNodeEditor_node_tree_poll");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Node Tree", "Node tree being displayed");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
+ RNA_def_property_ui_text(prop, "Node Tree", "Base node tree from context");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, "rna_SpaceNodeEditor_node_tree_update");
prop = RNA_def_property(srna, "edit_tree", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "edittree");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Edit Tree", "Edited node tree");
+ RNA_def_property_ui_text(prop, "Edit Tree", "Node tree being displayed and edited");
+
+ prop = RNA_def_property(srna, "pin", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_PIN);
+ RNA_def_property_ui_text(prop, "Pinned", "Use the pinned node tree");
+ RNA_def_property_ui_icon(prop, ICON_UNPINNED, 1);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, NULL);
prop = RNA_def_property(srna, "show_backdrop", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_BACKDRAW);
RNA_def_property_ui_text(prop, "Backdrop", "Use active Viewer Node output as backdrop for compositing nodes");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
+ prop = RNA_def_property(srna, "show_grease_pencil", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_SHOW_GPENCIL);
+ RNA_def_property_ui_text(prop, "Show Grease Pencil",
+ "Show grease pencil for this view");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
+
prop = RNA_def_property(srna, "use_auto_render", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_AUTO_RENDER);
RNA_def_property_ui_text(prop, "Auto Render", "Re-render and composite changed layers on 3D edits");
@@ -3208,6 +3480,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_update(prop, NC_SPACE | ND_SPACE_CLIP, "rna_SpaceClipEditor_view_type_update");
/* show pattern */
@@ -3302,6 +3575,13 @@ static void rna_def_space_clip(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Manual Calibration", "Use manual calibration helpers");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL);
+ /* show grease pencil */
+ prop = RNA_def_property(srna, "show_grease_pencil", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SC_SHOW_GPENCIL);
+ RNA_def_property_ui_text(prop, "Show Grease Pencil",
+ "Show grease pencil for this view");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL);
+
/* show filters */
prop = RNA_def_property(srna, "show_filters", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SC_SHOW_FILTERS);
@@ -3374,6 +3654,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_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
/* pivot point */
@@ -3405,6 +3686,7 @@ void RNA_def_space(BlenderRNA *brna)
rna_def_console_line(brna);
rna_def_space_info(brna);
rna_def_space_userpref(brna);
+ rna_def_node_tree_path(brna);
rna_def_space_node(brna);
rna_def_space_logic(brna);
rna_def_space_clip(brna);
diff --git a/source/blender/makesrna/intern/rna_speaker.c b/source/blender/makesrna/intern/rna_speaker.c
index 139582104ee..8a75aa2d227 100644
--- a/source/blender/makesrna/intern/rna_speaker.c
+++ b/source/blender/makesrna/intern/rna_speaker.c
@@ -62,6 +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_update(prop, 0, "rna_Speaker_update"); */
#if 0 /* This shouldn't be changed actually, hiding it! */
diff --git a/source/blender/makesrna/intern/rna_text.c b/source/blender/makesrna/intern/rna_text.c
index b1637ef4c8a..df6181af4b2 100644
--- a/source/blender/makesrna/intern/rna_text.c
+++ b/source/blender/makesrna/intern/rna_text.c
@@ -30,6 +30,8 @@
#include "MEM_guardedalloc.h"
+#include "BLF_translation.h"
+
#include "BKE_text.h"
#include "RNA_define.h"
@@ -127,6 +129,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);
}
static void rna_def_text(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_text_api.c b/source/blender/makesrna/intern/rna_text_api.c
index 5f67f367195..de398bc10a6 100644
--- a/source/blender/makesrna/intern/rna_text_api.c
+++ b/source/blender/makesrna/intern/rna_text_api.c
@@ -24,10 +24,11 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
#include <stdio.h>
+#include "BLI_utildefines.h"
+
#include "RNA_define.h"
#include "rna_internal.h" /* own include */
diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c
index bdf9fa4e436..e8f812506e2 100644
--- a/source/blender/makesrna/intern/rna_texture.c
+++ b/source/blender/makesrna/intern/rna_texture.c
@@ -24,16 +24,10 @@
* \ingroup RNA
*/
-
#include <float.h>
#include <stdio.h>
#include <stdlib.h>
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
-#include "rna_internal.h"
-
#include "DNA_brush_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
@@ -44,8 +38,15 @@
#include "DNA_particle_types.h"
#include "DNA_scene_types.h" /* MAXFRAME only */
+#include "BLI_utildefines.h"
+
#include "BKE_node.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -71,12 +72,12 @@ EnumPropertyItem texture_type_items[] = {
{TEX_MUSGRAVE, "MUSGRAVE", ICON_TEXTURE, "Musgrave", "Procedural - highly flexible fractal noise texture"},
{TEX_NOISE, "NOISE", ICON_TEXTURE, "Noise",
"Procedural - random noise, gives a different result every time, for every frame, for every pixel"},
+ {TEX_OCEAN, "OCEAN", ICON_TEXTURE, "Ocean", "Use a texture generated by an Ocean modifier"},
{TEX_POINTDENSITY, "POINT_DENSITY", ICON_TEXTURE, "Point Density", ""},
{TEX_STUCCI, "STUCCI", ICON_TEXTURE, "Stucci", "Procedural - create a fractal noise texture"},
{TEX_VORONOI, "VORONOI", ICON_TEXTURE, "Voronoi", "Procedural - create cell-like patterns based on Worley noise"},
{TEX_VOXELDATA, "VOXEL_DATA", ICON_TEXTURE, "Voxel Data", "Create a 3D texture based on volumetric data"},
{TEX_WOOD, "WOOD", ICON_TEXTURE, "Wood", "Procedural - wave generated bands or rings, with optional noise"},
- {TEX_OCEAN, "OCEAN", ICON_TEXTURE, "Ocean", "Use a texture generated by an Ocean modifier"},
{0, NULL, 0, NULL, NULL}
};
@@ -106,6 +107,7 @@ EnumPropertyItem blend_type_items[] = {
#include "RNA_access.h"
+#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_image.h"
#include "BKE_texture.h"
@@ -166,7 +168,7 @@ static void rna_Texture_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *pt
}
else if (GS(id->name) == ID_NT) {
bNodeTree *ntree = ptr->id.data;
- ED_node_generic_update(bmain, ntree, NULL);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
}
@@ -380,18 +382,21 @@ static void rna_Texture_use_color_ramp_set(PointerRNA *ptr, int value)
else tex->flag &= ~TEX_COLORBAND;
if ((tex->flag & TEX_COLORBAND) && tex->coba == NULL)
- tex->coba = add_colorband(0);
+ tex->coba = add_colorband(false);
}
-static void rna_Texture_use_nodes_set(PointerRNA *ptr, int v)
+static void rna_Texture_use_nodes_update(bContext *C, PointerRNA *ptr)
{
Tex *tex = (Tex *)ptr->data;
- tex->use_nodes = v;
- tex->type = 0;
+ if (tex->use_nodes) {
+ tex->type = 0;
+
+ if (tex->nodetree == NULL)
+ ED_node_texture_default(C, tex);
+ }
- if (v && tex->nodetree == NULL)
- ED_node_texture_default(tex);
+ rna_Texture_nodes_update(CTX_data_main(C), CTX_data_scene(C), ptr);
}
static void rna_ImageTexture_mipmap_set(PointerRNA *ptr, int value)
@@ -563,7 +568,7 @@ static void rna_def_colormapping(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Color_mapping_update");
prop = RNA_def_property(srna, "contrast", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.01, 5);
+ RNA_def_property_range(prop, 0.0, 5);
RNA_def_property_ui_text(prop, "Contrast", "Adjust the contrast of the texture");
RNA_def_property_update(prop, 0, "rna_Color_mapping_update");
@@ -1845,7 +1850,7 @@ static void rna_def_texture_voxeldata(BlenderRNA *brna)
prop = RNA_def_property(srna, "file_format", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "file_format");
RNA_def_property_enum_items(prop, file_format_items);
- RNA_def_property_ui_text(prop, "File Format", "Format of the source data set to render ");
+ RNA_def_property_ui_text(prop, "File Format", "Format of the source data set to render");
RNA_def_property_update(prop, 0, "rna_Texture_voxeldata_update");
prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
@@ -1983,7 +1988,7 @@ static void rna_def_texture(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Texture_update");
prop = RNA_def_property(srna, "contrast", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.01, 5);
+ RNA_def_property_range(prop, 0.0, 5);
RNA_def_property_ui_text(prop, "Contrast", "Adjust the contrast of the texture");
RNA_def_property_update(prop, 0, "rna_Texture_update");
@@ -2020,9 +2025,9 @@ static void rna_def_texture(BlenderRNA *brna)
/* nodetree */
prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1);
- RNA_def_property_boolean_funcs(prop, NULL, "rna_Texture_use_nodes_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Use Nodes", "Make this a node-based texture");
- RNA_def_property_update(prop, 0, "rna_Texture_nodes_update");
+ RNA_def_property_update(prop, 0, "rna_Texture_use_nodes_update");
prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "nodetree");
diff --git a/source/blender/makesrna/intern/rna_texture_api.c b/source/blender/makesrna/intern/rna_texture_api.c
index 5be9d3a0dec..10ac5a9548a 100644
--- a/source/blender/makesrna/intern/rna_texture_api.c
+++ b/source/blender/makesrna/intern/rna_texture_api.c
@@ -28,6 +28,7 @@
#include <stdio.h>
#include <string.h>
+#include "BLI_utildefines.h"
#include "BLI_path_util.h"
#include "RNA_define.h"
@@ -71,7 +72,7 @@ static void clear_envmap(struct EnvMap *env, bContext *C)
static void texture_evaluate(struct Tex *tex, float value[3], float color_r[4])
{
TexResult texres = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
- multitex_ext(tex, value, NULL, NULL, 1, &texres);
+ multitex_ext(tex, value, NULL, NULL, 1, &texres, NULL);
color_r[0] = texres.tr;
color_r[1] = texres.tg;
diff --git a/source/blender/makesrna/intern/rna_timeline.c b/source/blender/makesrna/intern/rna_timeline.c
index 3842fe95894..a732b550261 100644
--- a/source/blender/makesrna/intern/rna_timeline.c
+++ b/source/blender/makesrna/intern/rna_timeline.c
@@ -24,15 +24,14 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
+#include "DNA_scene_types.h"
+
#include "RNA_define.h"
#include "rna_internal.h"
-#include "DNA_scene_types.h"
-
#include "WM_types.h"
#ifdef RNA_RUNTIME
diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c
index f5bcab3e530..6f0478b5eec 100644
--- a/source/blender/makesrna/intern/rna_tracking.c
+++ b/source/blender/makesrna/intern/rna_tracking.c
@@ -113,6 +113,7 @@ static void rna_tracking_active_object_index_set(PointerRNA *ptr, int value)
MovieClip *clip = (MovieClip *)ptr->id.data;
clip->tracking.objectnr = value;
+ BKE_tracking_dopesheet_tag_update(&clip->tracking);
}
static void rna_tracking_active_object_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
@@ -280,7 +281,7 @@ static void rna_tracking_flushUpdate(Main *UNUSED(bmain), Scene *scene, PointerR
static void rna_trackingObject_tracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
- MovieTrackingObject *object = (MovieTrackingObject * )ptr->data;
+ MovieTrackingObject *object = (MovieTrackingObject *)ptr->data;
if (object->flag & TRACKING_OBJECT_CAMERA) {
MovieClip *clip = (MovieClip *)ptr->id.data;
@@ -294,7 +295,7 @@ static void rna_trackingObject_tracks_begin(CollectionPropertyIterator *iter, Po
static PointerRNA rna_trackingObject_reconstruction_get(PointerRNA *ptr)
{
- MovieTrackingObject *object = (MovieTrackingObject * )ptr->data;
+ MovieTrackingObject *object = (MovieTrackingObject *)ptr->data;
if (object->flag & TRACKING_OBJECT_CAMERA) {
MovieClip *clip = (MovieClip *)ptr->id.data;
@@ -402,39 +403,52 @@ static void rna_trackingDopesheet_tagUpdate(Main *UNUSED(bmain), Scene *scene, P
/* API */
-static void add_tracks_to_base(MovieClip *clip, MovieTracking *tracking, ListBase *tracksbase, int frame, int number)
+static MovieTrackingTrack *add_track_to_base(MovieClip *clip, MovieTracking *tracking, ListBase *tracksbase, const char *name, int frame)
{
- int a, width, height;
+ int width, height;
MovieClipUser user = {0};
+ MovieTrackingTrack *track;
user.framenr = 1;
BKE_movieclip_get_size(clip, &user, &width, &height);
- for (a = 0; a < number; a++)
- BKE_tracking_track_add(tracking, tracksbase, 0, 0, frame, width, height);
+ track = BKE_tracking_track_add(tracking, tracksbase, 0, 0, frame, width, height);
+
+ if (name && name[0]) {
+ BLI_strncpy(track->name, name, sizeof(track->name));
+ BKE_tracking_track_unique_name(tracksbase, track);
+ }
+
+ return track;
}
-static void rna_trackingTracks_add(ID *id, MovieTracking *tracking, int frame, int number)
+static MovieTrackingTrack *rna_trackingTracks_new(ID *id, MovieTracking *tracking, const char *name, int frame)
{
MovieClip *clip = (MovieClip *) id;
+ MovieTrackingTrack *track;
- add_tracks_to_base(clip, tracking, &tracking->tracks, frame, number);
+ track = add_track_to_base(clip, tracking, &tracking->tracks, name, frame);
WM_main_add_notifier(NC_MOVIECLIP | NA_EDITED, clip);
+
+ return track;
}
-static void rna_trackingObject_tracks_add(ID *id, MovieTrackingObject *object, int frame, int number)
+static MovieTrackingTrack *rna_trackingObject_tracks_new(ID *id, MovieTrackingObject *object, const char *name, int frame)
{
MovieClip *clip = (MovieClip *) id;
ListBase *tracksbase = &object->tracks;
+ MovieTrackingTrack *track;
if (object->flag & TRACKING_OBJECT_CAMERA)
tracksbase = &clip->tracking.tracks;
- add_tracks_to_base(clip, &clip->tracking, tracksbase, frame, number);
+ track = add_track_to_base(clip, &clip->tracking, tracksbase, name, frame);
WM_main_add_notifier(NC_MOVIECLIP | NA_EDITED, NULL);
+
+ return track;
}
static MovieTrackingObject *rna_trackingObject_new(MovieTracking *tracking, const char *name)
@@ -475,6 +489,14 @@ static MovieTrackingMarker *rna_trackingMarkers_insert_frame(MovieTrackingTrack
marker.framenr = framenr;
copy_v2_v2(marker.pos, co);
+ /* a bit arbitrary, but better than creating markers with zero pattern
+ * which is forbidden actually
+ */
+ copy_v2_v2(marker.pattern_corners[0], track->markers[0].pattern_corners[0]);
+ copy_v2_v2(marker.pattern_corners[1], track->markers[0].pattern_corners[1]);
+ copy_v2_v2(marker.pattern_corners[2], track->markers[0].pattern_corners[2]);
+ copy_v2_v2(marker.pattern_corners[3], track->markers[0].pattern_corners[3]);
+
new_marker = BKE_tracking_marker_insert(track, &marker);
WM_main_add_notifier(NC_MOVIECLIP | NA_EDITED, NULL);
@@ -558,6 +580,9 @@ static void rna_def_trackingSettings(BlenderRNA *brna)
{REFINE_FOCAL_LENGTH |
REFINE_PRINCIPAL_POINT, "FOCAL_LENGTH_PRINCIPAL_POINT", 0, "Focal Length, Optical Center",
"Refine focal length and optical center"},
+ {REFINE_RADIAL_DISTORTION_K1 |
+ REFINE_RADIAL_DISTORTION_K2, "RADIAL_K1_K2", 0, "K1, K2",
+ "Refine radial distortion K1 and K2"},
{0, NULL, 0, NULL, NULL}
};
@@ -1318,16 +1343,19 @@ static void rna_def_trackingTracks(BlenderRNA *brna)
StructRNA *srna;
FunctionRNA *func;
PropertyRNA *prop;
+ PropertyRNA *parm;
srna = RNA_def_struct(brna, "MovieTrackingTracks", NULL);
RNA_def_struct_sdna(srna, "MovieTracking");
RNA_def_struct_ui_text(srna, "Movie Tracks", "Collection of movie tracking tracks");
- func = RNA_def_function(srna, "add", "rna_trackingTracks_add");
+ func = RNA_def_function(srna, "new", "rna_trackingTracks_new");
RNA_def_function_flag(func, FUNC_USE_SELF_ID);
- RNA_def_function_ui_description(func, "Add a number of tracks to this movie clip");
- RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame", "Frame number to add tracks on", MINFRAME, MAXFRAME);
- RNA_def_int(func, "count", 1, 0, INT_MAX, "Number", "Number of tracks to add to the movie clip", 0, INT_MAX);
+ RNA_def_function_ui_description(func, "Create new motion track in this movie clip");
+ RNA_def_string(func, "name", "", 0, "", "Name of new track");
+ RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame", "Frame number to add track on", MINFRAME, MAXFRAME);
+ parm = RNA_def_pointer(func, "track", "MovieTrackingTrack", "", "Newly created track");
+ RNA_def_function_return(func, parm);
/* active track */
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
@@ -1342,16 +1370,19 @@ static void rna_def_trackingObjectTracks(BlenderRNA *brna)
StructRNA *srna;
FunctionRNA *func;
PropertyRNA *prop;
+ PropertyRNA *parm;
srna = RNA_def_struct(brna, "MovieTrackingObjectTracks", NULL);
RNA_def_struct_sdna(srna, "MovieTrackingObject");
RNA_def_struct_ui_text(srna, "Movie Tracks", "Collection of movie tracking tracks");
- func = RNA_def_function(srna, "add", "rna_trackingObject_tracks_add");
+ func = RNA_def_function(srna, "new", "rna_trackingObject_tracks_new");
RNA_def_function_flag(func, FUNC_USE_SELF_ID);
- RNA_def_function_ui_description(func, "Add a number of tracks to this movie clip");
+ RNA_def_function_ui_description(func, "create new motion track in this movie clip");
+ RNA_def_string(func, "name", "", 0, "", "Name of new track");
RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame", "Frame number to add tracks on", MINFRAME, MAXFRAME);
- RNA_def_int(func, "count", 1, 0, INT_MAX, "Number", "Number of tracks to add to the movie clip", 0, INT_MAX);
+ parm = RNA_def_pointer(func, "track", "MovieTrackingTrack", "", "Newly created track");
+ RNA_def_function_return(func, parm);
/* active track */
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index a0a9f6183af..9efe3d9f1d6 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -29,6 +29,8 @@
#include "DNA_screen_types.h"
+#include "BLF_translation.h"
+
#include "RNA_define.h"
#include "rna_internal.h"
@@ -55,6 +57,16 @@ EnumPropertyItem operator_context_items[] = {
{0, NULL, 0, NULL, NULL}
};
+EnumPropertyItem uilist_layout_type_items[] = {
+ {UILST_LAYOUT_DEFAULT, "DEFAULT", 0, "Default Layout",
+ "Use the default, multi-rows layout"},
+ {UILST_LAYOUT_COMPACT, "COMPACT", 0, "Compact Layout",
+ "Use the compact, single-row layout"},
+ {UILST_LAYOUT_GRID, "GRID", 0, "Grid Layout",
+ "Use the grid-based layout"},
+ {0, NULL, 0, NULL, NULL}
+};
+
#ifdef RNA_RUNTIME
#include <assert.h>
@@ -155,7 +167,7 @@ static void panel_draw_header(const bContext *C, Panel *pnl)
RNA_parameter_list_free(&list);
}
-static void rna_Panel_unregister(Main *UNUSED(bmain), StructRNA *type)
+static void rna_Panel_unregister(Main *bmain, StructRNA *type)
{
ARegionType *art;
PanelType *pt = RNA_struct_blender_type_get(type);
@@ -171,7 +183,7 @@ static void rna_Panel_unregister(Main *UNUSED(bmain), StructRNA *type)
RNA_struct_free(&BLENDER_RNA, type);
/* update while blender is running */
- WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
+ WM_main_add_notifier(NC_WINDOW, NULL);
}
static StructRNA *rna_Panel_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
@@ -187,6 +199,9 @@ static StructRNA *rna_Panel_register(Main *bmain, ReportList *reports, void *dat
dummypanel.type = &dummypt;
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);
+
/* validate the python class */
if (validate(&dummyptr, data, have_function) != 0)
return NULL;
@@ -215,7 +230,8 @@ static StructRNA *rna_Panel_register(Main *bmain, ReportList *reports, void *dat
pt = MEM_callocN(sizeof(PanelType), "python buttons panel");
memcpy(pt, &dummypt, sizeof(dummypt));
- pt->ext.srna = RNA_def_struct(&BLENDER_RNA, pt->idname, "Panel");
+ pt->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, pt->idname, &RNA_Panel);
+ RNA_def_struct_translation_context(pt->ext.srna, pt->translation_context);
pt->ext.data = data;
pt->ext.call = call;
pt->ext.free = free;
@@ -241,7 +257,7 @@ static StructRNA *rna_Panel_register(Main *bmain, ReportList *reports, void *dat
BLI_addtail(&art->paneltypes, pt);
/* update while blender is running */
- WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
+ WM_main_add_notifier(NC_WINDOW, NULL);
return pt->ext.srna;
}
@@ -252,6 +268,105 @@ static StructRNA *rna_Panel_refine(PointerRNA *ptr)
return (hdr->type && hdr->type->ext.srna) ? hdr->type->ext.srna : &RNA_Panel;
}
+/* UIList */
+static void uilist_draw_item(uiList *ui_list, bContext *C, uiLayout *layout, PointerRNA *dataptr, PointerRNA *itemptr,
+ int icon, PointerRNA *active_dataptr, const char *active_propname, int index)
+{
+ extern FunctionRNA rna_UIList_draw_item_func;
+
+ PointerRNA ul_ptr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ RNA_pointer_create(&CTX_wm_screen(C)->id, ui_list->type->ext.srna, ui_list, &ul_ptr);
+ func = &rna_UIList_draw_item_func; /* RNA_struct_find_function(&ul_ptr, "draw_item"); */
+
+ RNA_parameter_list_create(&list, &ul_ptr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "layout", &layout);
+ RNA_parameter_set_lookup(&list, "data", dataptr);
+ RNA_parameter_set_lookup(&list, "item", itemptr);
+ RNA_parameter_set_lookup(&list, "icon", &icon);
+ RNA_parameter_set_lookup(&list, "active_data", active_dataptr);
+ RNA_parameter_set_lookup(&list, "active_property", &active_propname);
+ RNA_parameter_set_lookup(&list, "index", &index);
+ ui_list->type->ext.call((bContext *)C, &ul_ptr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_UIList_unregister(Main *UNUSED(bmain), StructRNA *type)
+{
+ uiListType *ult = RNA_struct_blender_type_get(type);
+
+ if (!ult)
+ return;
+
+ RNA_struct_free_extension(type, &ult->ext);
+
+ WM_uilisttype_freelink(ult);
+
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_WINDOW, NULL);
+}
+
+static StructRNA *rna_UIList_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ uiListType *ult, dummyult = {NULL};
+ uiList dummyuilist = {NULL};
+ PointerRNA dummyul_ptr;
+ int have_function[1];
+ size_t over_alloc = 0; /* warning, if this becomes a bess, we better do another alloc */
+
+ /* setup dummy menu & menu type to store static properties in */
+ dummyuilist.type = &dummyult;
+ RNA_pointer_create(NULL, &RNA_UIList, &dummyuilist, &dummyul_ptr);
+
+ /* validate the python class */
+ if (validate(&dummyul_ptr, data, have_function) != 0)
+ return NULL;
+
+ if (strlen(identifier) >= sizeof(dummyult.idname)) {
+ BKE_reportf(reports, RPT_ERROR, "Registering uilist class: '%s' is too long, maximum length is %d",
+ identifier, (int)sizeof(dummyult.idname));
+ return NULL;
+ }
+
+ /* check if we have registered this uilist type before, and remove it */
+ ult = WM_uilisttype_find(dummyult.idname, TRUE);
+ if (ult && ult->ext.srna)
+ rna_UIList_unregister(bmain, ult->ext.srna);
+
+ /* create a new menu type */
+ ult = MEM_callocN(sizeof(uiListType) + over_alloc, "python uilist");
+ memcpy(ult, &dummyult, sizeof(dummyult));
+
+ ult->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, ult->idname, &RNA_UIList);
+ ult->ext.data = data;
+ ult->ext.call = call;
+ ult->ext.free = free;
+ RNA_struct_blender_type_set(ult->ext.srna, ult);
+ RNA_def_struct_flag(ult->ext.srna, STRUCT_NO_IDPROPERTIES);
+
+ ult->draw_item = (have_function[0]) ? uilist_draw_item : NULL;
+
+ WM_uilisttype_add(ult);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_WINDOW, NULL);
+
+ return ult->ext.srna;
+}
+
+static StructRNA *rna_UIList_refine(PointerRNA *ptr)
+{
+ uiList *ui_list = (uiList *)ptr->data;
+ return (ui_list->type && ui_list->type->ext.srna) ? ui_list->type->ext.srna : &RNA_UIList;
+}
+
/* Header */
static void header_draw(const bContext *C, Header *hdr)
@@ -288,7 +403,7 @@ static void rna_Header_unregister(Main *UNUSED(bmain), StructRNA *type)
RNA_struct_free(&BLENDER_RNA, type);
/* update while blender is running */
- WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
+ WM_main_add_notifier(NC_WINDOW, NULL);
}
static StructRNA *rna_Header_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
@@ -330,7 +445,7 @@ static StructRNA *rna_Header_register(Main *bmain, ReportList *reports, void *da
ht = MEM_callocN(sizeof(HeaderType), "python buttons header");
memcpy(ht, &dummyht, sizeof(dummyht));
- ht->ext.srna = RNA_def_struct(&BLENDER_RNA, ht->idname, "Header");
+ ht->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, ht->idname, &RNA_Header);
ht->ext.data = data;
ht->ext.call = call;
ht->ext.free = free;
@@ -341,7 +456,7 @@ static StructRNA *rna_Header_register(Main *bmain, ReportList *reports, void *da
BLI_addtail(&art->headertypes, ht);
/* update while blender is running */
- WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
+ WM_main_add_notifier(NC_WINDOW, NULL);
return ht->ext.srna;
}
@@ -411,7 +526,7 @@ static void rna_Menu_unregister(Main *UNUSED(bmain), StructRNA *type)
RNA_struct_free(&BLENDER_RNA, type);
/* update while blender is running */
- WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
+ WM_main_add_notifier(NC_WINDOW, NULL);
}
static char _menu_descr[RNA_DYN_DESCR_MAX];
@@ -432,6 +547,8 @@ static StructRNA *rna_Menu_register(Main *bmain, ReportList *reports, void *data
/* clear in case they are left unset */
_menu_descr[0] = '\0';
+ /* We have to set default context! Else we get a void string... */
+ strcpy(dummymt.translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
/* validate the python class */
if (validate(&dummymtr, data, have_function) != 0)
@@ -463,7 +580,8 @@ static StructRNA *rna_Menu_register(Main *bmain, ReportList *reports, void *data
mt->description = buf;
}
- mt->ext.srna = RNA_def_struct(&BLENDER_RNA, mt->idname, "Menu");
+ mt->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, mt->idname, &RNA_Menu);
+ RNA_def_struct_translation_context(mt->ext.srna, mt->translation_context);
mt->ext.data = data;
mt->ext.call = call;
mt->ext.free = free;
@@ -476,7 +594,7 @@ static StructRNA *rna_Menu_register(Main *bmain, ReportList *reports, void *data
WM_menutype_add(mt);
/* update while blender is running */
- WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
+ WM_main_add_notifier(NC_WINDOW, NULL);
return mt->ext.srna;
}
@@ -495,6 +613,8 @@ static void rna_Menu_bl_description_set(PointerRNA *ptr, const char *value)
else assert(!"setting the bl_description on a non-builtin menu");
}
+/* UILayout */
+
static int rna_UILayout_active_get(PointerRNA *ptr)
{
return uiLayoutGetActive(ptr->data);
@@ -651,8 +771,8 @@ static void rna_def_panel(BlenderRNA *brna)
static EnumPropertyItem panel_flag_items[] = {
{PNL_DEFAULT_CLOSED, "DEFAULT_CLOSED", 0, "Default Closed",
"Defines if the panel has to be open or collapsed at the time of its creation"},
- {PNL_NO_HEADER, "HIDE_HEADER", 0, "Show Header",
- "If set to True, the panel shows a header, which contains a clickable "
+ {PNL_NO_HEADER, "HIDE_HEADER", 0, "Hide Header",
+ "If set to False, the panel shows a header, which contains a clickable "
"arrow to collapse the panel and the label (see bl_label)"},
{0, NULL, 0, NULL, NULL}
};
@@ -662,6 +782,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);
/* poll */
func = RNA_def_function(srna, "poll", NULL);
@@ -680,7 +801,7 @@ static void rna_def_panel(BlenderRNA *brna)
func = RNA_def_function(srna, "draw_header", NULL);
RNA_def_function_ui_description(func, "Draw UI elements into the panel's header UI layout");
- RNA_def_function_flag(func, FUNC_REGISTER);
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
parm = RNA_def_pointer(func, "context", "Context", "", "");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
@@ -702,16 +823,19 @@ static void rna_def_panel(BlenderRNA *brna)
"class name is \"OBJECT_PT_hello\", and bl_idname is not set by the "
"script, then bl_idname = \"OBJECT_PT_hello\"");
- /* panel's label indeed doesn't need PROP_TRANSLATE flag: translation of label happens in runtime
- * when drawing panel and having this flag set will make runtime switching of language much more tricky
- * because label will be stored translated */
prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->label");
RNA_def_property_flag(prop, PROP_REGISTER);
RNA_def_property_ui_text(prop, "Label",
"The panel label, shows up in the panel header at the right of the "
"triangle used to collapse the panel");
-
+
+ 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_flag(prop, PROP_REGISTER_OPTIONAL);
+ RNA_define_verify_sdna(TRUE);
+
prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type->space_type");
RNA_def_property_enum_items(prop, space_type_items);
@@ -738,6 +862,58 @@ static void rna_def_panel(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Options", "Options for this panel type");
}
+static void rna_def_uilist(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+ PropertyRNA *parm;
+ FunctionRNA *func;
+
+ srna = RNA_def_struct(brna, "UIList", NULL);
+ RNA_def_struct_ui_text(srna, "UIList", "UI list containing the elements of a collection");
+ RNA_def_struct_sdna(srna, "uiList");
+ RNA_def_struct_refine_func(srna, "rna_UIList_refine");
+ RNA_def_struct_register_funcs(srna, "rna_UIList_register", "rna_UIList_unregister", NULL);
+
+ /* draw */
+ func = RNA_def_function(srna, "draw_item", NULL);
+ RNA_def_function_ui_description(func, "Draw an item in the list (NOTE: when you define your own draw_item "
+ "function, you may want to check given 'item' is of the right type...)");
+ RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_pointer(func, "layout", "UILayout", "", "Layout to draw the item");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take Collection property");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
+ parm = RNA_def_pointer(func, "item", "AnyType", "", "Item of the collection property");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
+ parm = RNA_def_int(func, "icon", 0, 0, INT_MAX, "", "Icon of the item in the collection", 0, INT_MAX);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_pointer(func, "active_data", "AnyType", "",
+ "Data from which to take property for the active element");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
+ parm = RNA_def_string(func, "active_property", "", 0, "",
+ "Identifier of property in active_data, for the active element");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_int(func, "index", 0, 0, INT_MAX, "", "Index of the item in the collection", 0, INT_MAX);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ prop = RNA_def_property(srna, "layout_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, uilist_layout_type_items);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ /* registration */
+ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "type->idname");
+ RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
+ RNA_def_property_ui_text(prop, "ID Name",
+ "If this is set, the uilist gets a custom ID, otherwise it takes the "
+ "name of the class used to define the uilist (for example, if the "
+ "class name is \"OBJECT_UL_vgroups\", and bl_idname is not set by the "
+ "script, then bl_idname = \"OBJECT_UL_vgroups\")");
+}
+
static void rna_def_header(BlenderRNA *brna)
{
StructRNA *srna;
@@ -796,6 +972,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);
/* poll */
func = RNA_def_function(srna, "poll", NULL);
@@ -812,7 +989,7 @@ static void rna_def_menu(BlenderRNA *brna)
parm = RNA_def_pointer(func, "context", "Context", "", "");
RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_define_verify_sdna(0); /* not in sdna */
+ RNA_define_verify_sdna(FALSE); /* not in sdna */
prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "layout");
@@ -829,15 +1006,17 @@ static void rna_def_menu(BlenderRNA *brna)
"class name is \"OBJECT_MT_hello\", and bl_idname is not set by the "
"script, then bl_idname = \"OBJECT_MT_hello\")");
- /* menu's label indeed doesn't need PROP_TRANSLATE flag: translation of label happens in runtime
- * when drawing panel and having this flag set will make runtime switching of language much more tricky
- * because label will be stored translated */
prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->label");
RNA_def_property_flag(prop, PROP_REGISTER);
RNA_def_property_ui_text(prop, "Label", "The menu label");
- prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_TRANSLATE);
+ 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_flag(prop, PROP_REGISTER_OPTIONAL);
+
+ prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->description");
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_Menu_bl_description_set");
@@ -852,6 +1031,7 @@ void RNA_def_ui(BlenderRNA *brna)
{
rna_def_ui_layout(brna);
rna_def_panel(brna);
+ rna_def_uilist(brna);
rna_def_header(brna);
rna_def_menu(brna);
}
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 548539e3395..b2f17bfed8b 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -32,17 +32,72 @@
#include <stdlib.h>
#include <stdio.h>
+#include "BLI_utildefines.h"
+
+#include "BLF_translation.h"
+
#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "DNA_screen_types.h"
#include "UI_resources.h"
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
#include "rna_internal.h"
+#define DEF_ICON_BLANK_SKIP
+#define DEF_ICON(name) {ICON_##name, (#name), 0, (#name), ""},
+#define DEF_VICO(name) {VICO_##name, (#name), 0, (#name), ""},
+EnumPropertyItem icon_items[] = {
+#include "UI_icons.h"
+ {0, NULL, 0, NULL, NULL}
+};
+#undef DEF_ICON_BLANK_SKIP
+#undef DEF_ICON
+#undef DEF_VICO
+
#ifdef RNA_RUNTIME
-static void rna_uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *name, int icon,
- int expand, int slider, int toggle, int icon_only, int event, int full_event,
- int emboss, int index)
+static const char *rna_translate_ui_text(const char *text, const char *text_ctxt, StructRNA *type, PropertyRNA *prop,
+ int translate)
+{
+ /* Also return text if UI labels translation is disabled. */
+ if (!text || !text[0] || !translate || !BLF_translate_iface()) {
+ return text;
+ }
+
+ /* If a text_ctxt is specified, use it! */
+ if (text_ctxt && text_ctxt[0]) {
+ return BLF_pgettext(text_ctxt, text);
+ }
+
+ /* Else, if an RNA type or property is specified, use its context. */
+#if 0
+ /* XXX Disabled for now. Unfortunately, their is absolutely no way from py code to get the RNA struct corresponding
+ * to the 'data' (in functions like prop() & co), as this is pure runtime data. Hence, messages extraction
+ * script can't determine the correct context it should use for such 'text' messages...
+ * So for now, one have to explicitly specify the 'text_ctxt' when using prop() etc. functions,
+ * if default context is not suitable.
+ */
+ if (prop) {
+ return BLF_pgettext(RNA_property_translation_context(prop), text);
+ }
+#else
+ (void)prop;
+#endif
+ if (type) {
+ return BLF_pgettext(RNA_struct_translation_context(type), text);
+ }
+
+ /* Else, default context! */
+ return BLF_pgettext(BLF_I18NCONTEXT_DEFAULT, text);
+}
+
+static void rna_uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *name, const char *text_ctxt,
+ int translate, int icon, int expand, int slider, int toggle, int icon_only, int event,
+ int full_event, int emboss, int index)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
int flag = 0;
@@ -52,6 +107,9 @@ static void rna_uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname,
return;
}
+ /* Get translated name (label). */
+ name = rna_translate_ui_text(name, text_ctxt, NULL, prop, translate);
+
flag |= (slider) ? UI_ITEM_R_SLIDER : 0;
flag |= (expand) ? UI_ITEM_R_EXPAND : 0;
flag |= (toggle) ? UI_ITEM_R_TOGGLE : 0;
@@ -63,36 +121,266 @@ static void rna_uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname,
uiItemFullR(layout, ptr, prop, index, 0, flag, name, icon);
}
-static PointerRNA rna_uiItemO(uiLayout *layout, const char *opname, const char *name, int icon, int emboss)
+static void rna_uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name,
+ const char *text_ctxt, int translate, int icon)
+{
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+
+ if (!prop) {
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ /* 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);
+}
+
+static void rna_uiItemEnumR_string(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *value,
+ const char *name, const char *text_ctxt, int translate, int icon)
+{
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+
+ if (!prop) {
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ /* Get translated name (label). */
+ name = rna_translate_ui_text(name, text_ctxt, NULL, prop, translate);
+
+ /* XXX This will search property again :( */
+ uiItemEnumR_string(layout, ptr, propname, value, name, icon);
+}
+
+static void rna_uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
+ struct PointerRNA *searchptr, const char *searchpropname,
+ const char *name, const char *text_ctxt, int translate, int icon)
+{
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+
+ if (!prop) {
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ /* Get translated name (label). */
+ name = rna_translate_ui_text(name, text_ctxt, NULL, prop, translate);
+
+ /* XXX This will search property again :( */
+ uiItemPointerR(layout, ptr, propname, searchptr, searchpropname, name, icon);
+}
+
+static PointerRNA rna_uiItemO(uiLayout *layout, const char *opname, const char *name, const char *text_ctxt,
+ int translate, int icon, int emboss)
{
- int flag = UI_ITEM_O_RETURN_PROPS;
+ wmOperatorType *ot;
+ int flag;
+
+ ot = WM_operatortype_find(opname, 0); /* print error next */
+ if (!ot || !ot->srna) {
+ RNA_warning("%s '%s'", ot ? "unknown operator" : "operator missing srna", opname);
+ return PointerRNA_NULL;
+ }
+
+ /* Get translated name (label). */
+ name = rna_translate_ui_text(name, text_ctxt, ot->srna, NULL, translate);
+
+ flag = UI_ITEM_O_RETURN_PROPS;
flag |= (emboss) ? 0 : UI_ITEM_R_NO_BG;
- return uiItemFullO(layout, opname, name, icon, NULL, uiLayoutGetOperatorContext(layout), flag);
+
+ return uiItemFullO_ptr(layout, ot, name, icon, NULL, uiLayoutGetOperatorContext(layout), flag);
+}
+
+static void rna_uiItemMenuEnumO(uiLayout *layout, const char *opname, const char *propname, const char *name,
+ const char *text_ctxt, int translate, int icon)
+{
+ wmOperatorType *ot = WM_operatortype_find(opname, 0); /* print error next */
+
+ if (!ot || !ot->srna) {
+ RNA_warning("%s '%s'", ot ? "unknown operator" : "operator missing srna", opname);
+ return;
+ }
+
+ /* Get translated name (label). */
+ name = rna_translate_ui_text(name, text_ctxt, ot->srna, NULL, translate);
+
+ /* XXX This will search operator again :( */
+ uiItemMenuEnumO(layout, opname, propname, name, icon);
+}
+
+static void rna_uiItemL(uiLayout *layout, const char *name, const char *text_ctxt, 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;
+ }
+
+ uiItemL(layout, name, icon);
+}
+
+static void rna_uiItemM(uiLayout *layout, bContext *C, const char *menuname, const char *name, const char *text_ctxt,
+ int translate, int icon)
+{
+ /* Get translated name (label). */
+ name = rna_translate_ui_text(name, text_ctxt, NULL, NULL, translate);
+
+ uiItemM(layout, C, menuname, name, icon);
+}
+
+static void rna_uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename,
+ const char *name, const char *text_ctxt, int translate)
+{
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+
+ if (!prop) {
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ /* Get translated name (label). */
+ name = rna_translate_ui_text(name, text_ctxt, NULL, prop, translate);
+
+ /* XXX This will search property again :( */
+ uiTemplateAnyID(layout, ptr, propname, proptypename, name);
+}
+
+static void rna_uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *root_ptr,
+ const char *name, const char *text_ctxt, int translate)
+{
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+
+ if (!prop) {
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ /* Get translated name (label). */
+ name = rna_translate_ui_text(name, text_ctxt, NULL, prop, translate);
+
+ /* XXX This will search property again :( */
+ uiTemplatePathBuilder(layout, ptr, propname, root_ptr, name);
+}
+
+static int rna_ui_get_rnaptr_icon(bContext *C, PointerRNA *ptr_icon)
+{
+ return UI_rnaptr_icon_get(C, ptr_icon, RNA_struct_ui_icon(ptr_icon->type), FALSE);
+}
+
+static const char *rna_ui_get_enum_name(bContext *C, PointerRNA *ptr, const char *propname, const char *identifier)
+{
+ PropertyRNA *prop = NULL;
+ EnumPropertyItem *items = NULL, *item;
+ int free;
+ const char *name = "";
+
+ prop = RNA_struct_find_property(ptr, propname);
+ if (!prop || (RNA_property_type(prop) != PROP_ENUM)) {
+ RNA_warning("Property not found or not an enum: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return name;
+ }
+
+ RNA_property_enum_items_gettexted(C, ptr, prop, &items, NULL, &free);
+
+ if (items) {
+ for (item = items; item->identifier; item++) {
+ if (item->identifier[0] && strcmp(item->identifier, identifier) == 0) {
+ name = item->name;
+ break;
+ }
+ }
+ if (free) {
+ MEM_freeN(items);
+ }
+ }
+
+ return name;
+}
+
+static const char *rna_ui_get_enum_description(bContext *C, PointerRNA *ptr, const char *propname,
+ const char *identifier)
+{
+ PropertyRNA *prop = NULL;
+ EnumPropertyItem *items = NULL, *item;
+ int free;
+ const char *desc = "";
+
+ prop = RNA_struct_find_property(ptr, propname);
+ if (!prop || (RNA_property_type(prop) != PROP_ENUM)) {
+ RNA_warning("Property not found or not an enum: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return desc;
+ }
+
+ RNA_property_enum_items_gettexted(C, ptr, prop, &items, NULL, &free);
+
+ if (items) {
+ for (item = items; item->identifier; item++) {
+ if (item->identifier[0] && strcmp(item->identifier, identifier) == 0) {
+ desc = item->description;
+ break;
+ }
+ }
+ if (free) {
+ MEM_freeN(items);
+ }
+ }
+
+ return desc;
+}
+
+static int rna_ui_get_enum_icon(bContext *C, PointerRNA *ptr, const char *propname, const char *identifier)
+{
+ PropertyRNA *prop = NULL;
+ EnumPropertyItem *items = NULL, *item;
+ int free;
+ int icon = ICON_NONE;
+
+ prop = RNA_struct_find_property(ptr, propname);
+ if (!prop || (RNA_property_type(prop) != PROP_ENUM)) {
+ RNA_warning("Property not found or not an enum: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return icon;
+ }
+
+ RNA_property_enum_items(C, ptr, prop, &items, NULL, &free);
+
+ if (items) {
+ for (item = items; item->identifier; item++) {
+ if (item->identifier[0] && strcmp(item->identifier, identifier) == 0) {
+ icon = item->icon;
+ break;
+ }
+ }
+ if (free) {
+ MEM_freeN(items);
+ }
+ }
+
+ return icon;
}
#else
-#define DEF_ICON_BLANK_SKIP
-#define DEF_ICON(name) {ICON_##name, (#name), 0, (#name), ""},
-#define DEF_VICO(name) {VICO_##name, (#name), 0, (#name), ""},
-static EnumPropertyItem icon_items[] = {
-#include "UI_icons.h"
- {0, NULL, 0, NULL, NULL}
-};
-#undef DEF_ICON_BLANK_SKIP
-#undef DEF_ICON
-#undef DEF_VICO
+static void api_ui_item_common_text(FunctionRNA *func)
+{
+ RNA_def_string(func, "text", "", 0, "", "Override automatic text of the item");
+ RNA_def_string(func, "text_ctxt", "", 0, "", "Override automatic translation context of the given text");
+ RNA_def_boolean(func, "translate", true, "", "Translate the given text, when UI translation is enabled");
+}
static void api_ui_item_common(FunctionRNA *func)
{
PropertyRNA *prop;
- RNA_def_string_translate(func, "text", "", 0, "", "Override automatic text of the item");
+ api_ui_item_common_text(func);
prop = RNA_def_property(func, "icon", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, icon_items);
RNA_def_property_ui_text(prop, "Icon", "Override automatic icon of the item");
-
}
static void api_ui_item_op(FunctionRNA *func)
@@ -130,13 +418,8 @@ void RNA_api_ui_layout(StructRNA *srna)
{'h', "HUE", 0, "Hue", ""},
{0, NULL, 0, NULL, NULL}
};
-
- static EnumPropertyItem list_type_items[] = {
- {0, "DEFAULT", 0, "None", ""},
- {'c', "COMPACT", 0, "Compact", ""},
- {'i', "ICONS", 0, "Icons", ""},
- {0, NULL, 0, NULL, NULL}
- };
+
+ static float node_socket_color_default[] = { 0.0f, 0.0f, 0.0f, 1.0f };
/* simple layout specifiers */
func = RNA_def_function(srna, "row", "uiLayoutRow");
@@ -175,6 +458,44 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_float(func, "percentage", 0.0f, 0.0f, 1.0f, "Percentage", "Percentage of width to split at", 0.0f, 1.0f);
RNA_def_boolean(func, "align", 0, "", "Align buttons to each other");
+ /* Icon of a rna pointer */
+ func = RNA_def_function(srna, "icon", "rna_ui_get_rnaptr_icon");
+ parm = RNA_def_int(func, "icon_value", ICON_NONE, 0, INT_MAX, "", "Icon identifier", 0, INT_MAX);
+ RNA_def_function_return(func, parm);
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
+ parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take the icon");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
+ RNA_def_function_ui_description(func, "Return the custom icon for this data, "
+ "use it e.g. to get materials or texture icons");
+
+ /* UI name, description and icon of an enum item */
+ func = RNA_def_function(srna, "enum_item_name", "rna_ui_get_enum_name");
+ parm = RNA_def_string(func, "name", "", 0, "", "UI name of the enum item");
+ RNA_def_function_return(func, parm);
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
+ api_ui_item_rna_common(func);
+ parm = RNA_def_string(func, "identifier", "", 0, "", "Identifier of the enum item");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_function_ui_description(func, "Return the UI name for this enum item");
+
+ func = RNA_def_function(srna, "enum_item_description", "rna_ui_get_enum_description");
+ parm = RNA_def_string(func, "description", "", 0, "", "UI description of the enum item");
+ RNA_def_function_return(func, parm);
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
+ api_ui_item_rna_common(func);
+ parm = RNA_def_string(func, "identifier", "", 0, "", "Identifier of the enum item");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_function_ui_description(func, "Return the UI description for this enum item");
+
+ func = RNA_def_function(srna, "enum_item_icon", "rna_ui_get_enum_icon");
+ parm = RNA_def_int(func, "icon_value", ICON_NONE, 0, INT_MAX, "", "Icon identifier", 0, INT_MAX);
+ RNA_def_function_return(func, parm);
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
+ api_ui_item_rna_common(func);
+ parm = RNA_def_string(func, "identifier", "", 0, "", "Identifier of the enum item");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_function_ui_description(func, "Return the icon for this enum item");
+
/* items */
func = RNA_def_function(srna, "prop", "rna_uiItemR");
RNA_def_function_ui_description(func, "Item. Exposes an RNA item and places it into the layout");
@@ -194,17 +515,17 @@ void RNA_api_ui_layout(StructRNA *srna)
func = RNA_def_function(srna, "props_enum", "uiItemsEnumR");
api_ui_item_rna_common(func);
- func = RNA_def_function(srna, "prop_menu_enum", "uiItemMenuEnumR");
+ func = RNA_def_function(srna, "prop_menu_enum", "rna_uiItemMenuEnumR");
api_ui_item_rna_common(func);
api_ui_item_common(func);
- func = RNA_def_function(srna, "prop_enum", "uiItemEnumR_string");
+ func = RNA_def_function(srna, "prop_enum", "rna_uiItemEnumR_string");
api_ui_item_rna_common(func);
parm = RNA_def_string(func, "value", "", 0, "", "Enum property value");
RNA_def_property_flag(parm, PROP_REQUIRED);
api_ui_item_common(func);
- func = RNA_def_function(srna, "prop_search", "uiItemPointerR");
+ func = RNA_def_function(srna, "prop_search", "rna_uiItemPointerR");
api_ui_item_rna_common(func);
parm = RNA_def_pointer(func, "search_data", "AnyType", "", "Data from which to take collection to search in");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
@@ -227,7 +548,7 @@ void RNA_api_ui_layout(StructRNA *srna)
parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator");
RNA_def_property_flag(parm, PROP_REQUIRED);
- func = RNA_def_function(srna, "operator_menu_enum", "uiItemMenuEnumO");
+ func = RNA_def_function(srna, "operator_menu_enum", "rna_uiItemMenuEnumO");
api_ui_item_op(func); /* cant use api_ui_item_op_common because property must come right after */
parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator");
RNA_def_property_flag(parm, PROP_REQUIRED);
@@ -274,11 +595,15 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_property_flag(parm, PROP_REQUIRED);
#endif
- func = RNA_def_function(srna, "label", "uiItemL");
- RNA_def_function_ui_description(func, "Item. Display text in the layout");
+ func = RNA_def_function(srna, "label", "rna_uiItemL");
+ 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()...)");
- func = RNA_def_function(srna, "menu", "uiItemM");
+ func = RNA_def_function(srna, "menu", "rna_uiItemM");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_string(func, "menu", "", 0, "", "Identifier of the menu");
api_ui_item_common(func);
@@ -315,7 +640,7 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_int(func, "rows", 0, 0, INT_MAX, "Number of thumbnail preview rows to display", "", 0, INT_MAX);
RNA_def_int(func, "cols", 0, 0, INT_MAX, "Number of thumbnail preview columns to display", "", 0, INT_MAX);
- func = RNA_def_function(srna, "template_any_ID", "uiTemplateAnyID");
+ func = RNA_def_function(srna, "template_any_ID", "rna_uiTemplateAnyID");
parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in data");
@@ -323,16 +648,16 @@ void RNA_api_ui_layout(StructRNA *srna)
parm = RNA_def_string(func, "type_property", "", 0, "",
"Identifier of property in data giving the type of the ID-blocks to use");
RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_string_translate(func, "text", "", 0, "", "Custom label to display in UI");
+ api_ui_item_common_text(func);
- func = RNA_def_function(srna, "template_path_builder", "uiTemplatePathBuilder");
+ func = RNA_def_function(srna, "template_path_builder", "rna_uiTemplatePathBuilder");
parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in data");
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_pointer(func, "root", "ID", "", "ID-block from which path is evaluated from");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
- RNA_def_string_translate(func, "text", "", 0, "", "Custom label to display in UI");
+ api_ui_item_common_text(func);
func = RNA_def_function(srna, "template_modifier", "uiTemplateModifier");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
@@ -369,6 +694,10 @@ void RNA_api_ui_layout(StructRNA *srna)
api_ui_item_rna_common(func);
RNA_def_boolean(func, "expand", 0, "", "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);
+
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);
@@ -439,26 +768,30 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_boolean(func, "compact", 0, "", "Use more compact layout");
func = RNA_def_function(srna, "template_list", "uiTemplateList");
- RNA_def_function_ui_description(func, "Item. A list widget to display data, e.g. vertexgroups "
- "(WARNING: only one per panel allowed!).");
+ RNA_def_function_ui_description(func, "Item. A list widget to display data, e.g. vertexgroups.");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
- parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property");
+ parm = RNA_def_string(func, "listtype_name", "", 0, "", "Identifier of the list type to use");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_string(func, "list_id", "", 0, "",
+ "Identifier of this list widget (mandatory when using default \"" UI_UL_DEFAULT_CLASS_NAME
+ "\" class). "
+ "If this is set, the uilist gets a custom ID, otherwise it takes the "
+ "name of the class used to define the uilist (for example, if the "
+ "class name is \"OBJECT_UL_vgroups\", and list_id is not set by the "
+ "script, then bl_idname = \"OBJECT_UL_vgroups\")");
+ parm = RNA_def_pointer(func, "dataptr", "AnyType", "", "Data from which to take the Collection property");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
- parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in data");
+ parm = RNA_def_string(func, "propname", "", 0, "", "Identifier of the Collection property in data");
RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_pointer(func, "active_data", "AnyType", "",
- "Data from which to take property for the active element");
+ parm = RNA_def_pointer(func, "active_dataptr", "AnyType", "",
+ "Data from which to take the integer property, index of the active item");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
- parm = RNA_def_string(func, "active_property", "", 0, "",
- "Identifier of property in data, for the active element");
+ parm = RNA_def_string(func, "active_propname", "", 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, "prop_list", "", 0, "",
- "Identifier of a string property in each data member, specifying which "
- "of its properties should have a widget displayed in its row "
- "(format: \"propname1:propname2:propname3:...\")");
RNA_def_int(func, "rows", 5, 0, INT_MAX, "", "Number of rows to display", 0, INT_MAX);
RNA_def_int(func, "maxrows", 5, 0, INT_MAX, "", "Maximum number of rows to display", 0, INT_MAX);
- RNA_def_enum(func, "type", list_type_items, 0, "Type", "Type of list to use");
+ RNA_def_enum(func, "type", uilist_layout_type_items, UILST_LAYOUT_DEFAULT, "Type", "Type of layout to use");
func = RNA_def_function(srna, "template_running_jobs", "uiTemplateRunningJobs");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
@@ -498,6 +831,14 @@ void RNA_api_ui_layout(StructRNA *srna)
parm = RNA_def_pointer(func, "item", "KeyMapItem", "", "");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
+ func = RNA_def_function(srna, "template_component_menu", "uiTemplateComponentMenu");
+ RNA_def_function_ui_description(func, "Item. Display expanded property in a popup menu");
+ parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
+ parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in data");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_string(func, "name", "", 0, "", "");
+
func = RNA_def_function(srna, "introspect", "uiLayoutIntrospect");
parm = RNA_def_string(func, "string", "", 1024 * 1024, "Descr", "DESCR");
RNA_def_function_return(func, parm);
@@ -512,6 +853,12 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
api_ui_item_rna_common(func);
/* RNA_def_boolean(func, "show_global_settings", 0, "", "Show widgets to control global color management settings"); */
+
+ /* node socket icon */
+ func = RNA_def_function(srna, "template_node_socket", "uiTemplateNodeSocket");
+ RNA_def_function_ui_description(func, "Node Socket Icon");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ RNA_def_float_array(func, "color", 4, node_socket_color_default, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 7be34c398ae..c9a9cca3147 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -26,12 +26,6 @@
#include <stdlib.h>
-#include "RNA_access.h"
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
-#include "rna_internal.h"
-
#include "DNA_curve_types.h"
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
@@ -39,15 +33,22 @@
#include "DNA_view3d_types.h"
#include "DNA_scene_types.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_sound.h"
+#include "BKE_addon.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+
#include "WM_api.h"
#include "WM_types.h"
-#include "BLI_utildefines.h"
-
#include "BLF_translation.h"
-#include "BKE_sound.h"
-
#ifdef WITH_CYCLES
static EnumPropertyItem compute_device_type_items[] = {
{USER_COMPUTE_DEVICE_NONE, "NONE", 0, "None", "Don't use compute device"},
@@ -62,10 +63,12 @@ static EnumPropertyItem compute_device_type_items[] = {
#include "DNA_object_types.h"
#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 "GPU_draw.h"
@@ -78,14 +81,17 @@ static EnumPropertyItem compute_device_type_items[] = {
#include "CCL_api.h"
+#include "BKE_addon.h"
+
static void rna_userdef_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
WM_main_add_notifier(NC_WINDOW, NULL);
}
+/* also used by buffer swap switching */
static void rna_userdef_dpi_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
- U.widget_unit = (U.dpi * 20 + 36) / 72;
+ BKE_userdef_state();
WM_main_add_notifier(NC_WINDOW, NULL); /* full redraw */
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */
}
@@ -272,7 +278,8 @@ static void rna_UserDef_weight_color_update(Main *bmain, Scene *scene, PointerRN
{
Object *ob;
- vDM_ColorBand_store((U.flag & USER_CUSTOM_RANGE) ? (&U.coba_weight) : NULL);
+ bTheme *btheme = UI_GetTheme();
+ vDM_ColorBand_store((U.flag & USER_CUSTOM_RANGE) ? (&U.coba_weight) : NULL, btheme->tv3d.vertex_unreferenced);
for (ob = bmain->object.first; ob; ob = ob->id.next) {
if (ob->mode & OB_MODE_WEIGHT_PAINT)
@@ -319,6 +326,11 @@ static void rna_userdef_addon_remove(ReportList *reports, PointerRNA *bext_ptr)
return;
}
+ if (bext->prop) {
+ IDP_FreeProperty(bext->prop);
+ MEM_freeN(bext->prop);
+ }
+
BLI_freelinkN(&U.addons, bext);
RNA_POINTER_INVALIDATE(bext_ptr);
}
@@ -339,6 +351,11 @@ static PointerRNA rna_Theme_space_generic_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_ThemeSpaceGeneric, ptr->data);
}
+static PointerRNA rna_Theme_space_gradient_get(PointerRNA *ptr)
+{
+ return rna_pointer_inherit_refine(ptr, &RNA_ThemeSpaceGradient, ptr->data);
+}
+
static PointerRNA rna_Theme_space_list_generic_get(PointerRNA *ptr)
{
return rna_pointer_inherit_refine(ptr, &RNA_ThemeSpaceListGeneric, ptr->data);
@@ -426,6 +443,103 @@ static EnumPropertyItem *rna_lang_enum_properties_itemf(bContext *UNUSED(C), Poi
}
#endif
+static IDProperty *rna_AddonPref_idprops(PointerRNA *ptr, bool create)
+{
+ if (create && !ptr->data) {
+ IDPropertyTemplate val = {0};
+ ptr->data = IDP_New(IDP_GROUP, &val, "RNA_AddonPreferences group");
+ }
+
+ return ptr->data;
+}
+
+static PointerRNA rna_Addon_preferences_get(PointerRNA *ptr)
+{
+ bAddon *addon = (bAddon *)ptr->data;
+ bAddonPrefType *apt = BKE_addon_pref_type_find(addon->module, TRUE);
+ if (apt) {
+ if (addon->prop == NULL) {
+ IDPropertyTemplate val = {0};
+ addon->prop = IDP_New(IDP_GROUP, &val, addon->module); /* name is unimportant */
+ }
+ return rna_pointer_inherit_refine(ptr, apt->ext.srna, addon->prop);
+ }
+ else {
+ return PointerRNA_NULL;
+ }
+}
+
+static void rna_AddonPref_unregister(Main *UNUSED(bmain), StructRNA *type)
+{
+ bAddonPrefType *apt = RNA_struct_blender_type_get(type);
+
+ if (!apt)
+ return;
+
+ RNA_struct_free_extension(type, &apt->ext);
+
+ BKE_addon_pref_type_remove(apt);
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_WINDOW, NULL);
+}
+
+static StructRNA *rna_AddonPref_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ bAddonPrefType *apt, dummyapt = {{'\0'}};
+ bAddon dummyaddon = {NULL};
+ PointerRNA dummyhtr;
+ // int have_function[1];
+
+ /* setup dummy header & header type to store static properties in */
+ RNA_pointer_create(NULL, &RNA_AddonPreferences, &dummyaddon, &dummyhtr);
+
+ /* validate the python class */
+ if (validate(&dummyhtr, data, NULL /* have_function */ ) != 0)
+ return NULL;
+
+ BLI_strncpy(dummyapt.idname, dummyaddon.module, sizeof(dummyapt.idname));
+ if (strlen(identifier) >= sizeof(dummyapt.idname)) {
+ BKE_reportf(reports, RPT_ERROR, "Registering addon-prefs class: '%s' is too long, maximum length is %d",
+ identifier, (int)sizeof(dummyapt.idname));
+ return NULL;
+ }
+
+ /* check if we have registered this header type before, and remove it */
+ apt = BKE_addon_pref_type_find(dummyaddon.module, TRUE);
+ if (apt) {
+ if (apt->ext.srna) {
+ rna_AddonPref_unregister(bmain, apt->ext.srna);
+ }
+ }
+
+ /* create a new header type */
+ apt = MEM_mallocN(sizeof(bAddonPrefType), "addonpreftype");
+ memcpy(apt, &dummyapt, sizeof(dummyapt));
+ BKE_addon_pref_type_add(apt);
+
+ apt->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, identifier, &RNA_AddonPreferences);
+ apt->ext.data = data;
+ apt->ext.call = call;
+ apt->ext.free = free;
+ RNA_struct_blender_type_set(apt->ext.srna, apt);
+
+// apt->draw = (have_function[0]) ? header_draw : NULL;
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_WINDOW, NULL);
+
+ return apt->ext.srna;
+}
+
+/* placeholder, doesn't do anything useful yet */
+static StructRNA *rna_AddonPref_refine(PointerRNA *ptr)
+{
+ return (ptr->type) ? ptr->type : &RNA_AddonPreferences;
+}
+
#else
static void rna_def_userdef_theme_ui_font_style(BlenderRNA *brna)
@@ -435,7 +549,7 @@ static void rna_def_userdef_theme_ui_font_style(BlenderRNA *brna)
static EnumPropertyItem font_kerning_style[] = {
{0, "UNFITTED", 0, "Unfitted", "Use scaled but un-grid-fitted kerning distances"},
- {1, "DEFAULT", 0, "Default", "Use scaled and grid-fitted kerning distances"},
+ {1, "FITTED", 0, "Fitted", "Use scaled and grid-fitted kerning distances"},
{0, NULL, 0, NULL, NULL}
};
@@ -495,29 +609,14 @@ static void rna_def_userdef_theme_ui_style(BlenderRNA *brna)
RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
RNA_def_struct_ui_text(srna, "Style", "Theme settings for style sets");
- /* (not used yet) */
-#if 0
- prop = RNA_def_property(srna, "panelzoom", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.5, 2.0);
- RNA_def_property_ui_text(prop, "Panel Zoom", "Default zoom level for panel areas");
-#endif
prop = RNA_def_property(srna, "panel_title", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_pointer_sdna(prop, NULL, "paneltitle");
RNA_def_property_struct_type(prop, "ThemeFontStyle");
- RNA_def_property_ui_text(prop, "Panel Style", "");
+ RNA_def_property_ui_text(prop, "Panel Title Font", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- /* (not used yet) */
-#if 0
- prop = RNA_def_property(srna, "group_label", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_pointer_sdna(prop, NULL, "grouplabel");
- RNA_def_property_struct_type(prop, "ThemeFontStyle");
- RNA_def_property_ui_text(prop, "Group Label Font", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-#endif
prop = RNA_def_property(srna, "widget_label", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_pointer_sdna(prop, NULL, "widgetlabel");
@@ -648,10 +747,44 @@ static void rna_def_userdef_theme_ui_panel(BlenderRNA *brna)
prop = RNA_def_property(srna, "header", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_ui_text(prop, "Header", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
-
+
+ prop = RNA_def_property(srna, "back", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_ui_text(prop, "Background", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
prop = RNA_def_property(srna, "show_header", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_ui_text(prop, "Show Header", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "show_back", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Show Background", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+}
+
+static void rna_def_userdef_theme_ui_gradient(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ThemeGradientColors", NULL);
+ RNA_def_struct_sdna(srna, "uiGradientColors");
+ RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
+ RNA_def_struct_ui_text(srna, "Theme Background Color", "Theme settings for background colors and gradient");
+
+ prop = RNA_def_property(srna, "show_grad", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Use Gradient",
+ "Do a gradient for the background of the viewport working area");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "gradient", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Gradient Low", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "high_gradient", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Gradient High/Off", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_theme_ui(BlenderRNA *brna)
@@ -662,7 +795,8 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna)
rna_def_userdef_theme_ui_wcol(brna);
rna_def_userdef_theme_ui_wcol_state(brna);
rna_def_userdef_theme_ui_panel(brna);
-
+ rna_def_userdef_theme_ui_gradient(brna);
+
srna = RNA_def_struct(brna, "ThemeUserInterface", NULL);
RNA_def_struct_sdna(srna, "ThemeUI");
RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
@@ -757,9 +891,14 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "State Colors", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- prop = RNA_def_property(srna, "panel", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_ui_text(prop, "Panel Colors", "");
+ prop = RNA_def_property(srna, "menu_shadow_fac", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_ui_text(prop, "Menu Shadow Strength", "Blending factor for menu shadows");
+ RNA_def_property_range(prop, 0.01f, 1.0f);
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "menu_shadow_width", PROP_INT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Menu Shadow Width", "Width of menu shadows in standard pixels, set to zero to disable it");
+ RNA_def_property_range(prop, 0.0f, 24.0f);
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop = RNA_def_property(srna, "icon_file", PROP_STRING, PROP_FILEPATH);
@@ -837,10 +976,93 @@ static void rna_def_userdef_theme_space_generic(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Header Text Highlight", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+ /* panel settings */
+ prop = RNA_def_property(srna, "panelcolors", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_ui_text(prop, "Panel Colors", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
/* buttons */
/* if (! ELEM(spacetype, SPACE_BUTS, SPACE_OUTLINER)) { */
prop = RNA_def_property(srna, "button", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Region Background", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "button_title", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Region Text Titles", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "button_text", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Region Text", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "button_text_hi", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Region Text Highlight", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+/* } */
+}
+
+static void rna_def_userdef_theme_space_gradient(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ThemeSpaceGradient", NULL);
+ RNA_def_struct_sdna(srna, "ThemeSpace");
+ RNA_def_struct_ui_text(srna, "Theme Space Settings", "");
+
+ /* window */
+ prop = RNA_def_property(srna, "title", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Title", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "text", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Text", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "text_hi", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Text Highlight", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ /* header */
+ prop = RNA_def_property(srna, "header", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Header", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "header_text", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Header Text", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "header_text_hi", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Header Text Highlight", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ /* panel settings */
+ prop = RNA_def_property(srna, "panelcolors", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_ui_text(prop, "Panel Colors", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ /* gradient/background settings */
+ prop = RNA_def_property(srna, "gradients", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_ui_text(prop, "Gradient Colors", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ /* buttons */
+/* if (! ELEM(spacetype, SPACE_BUTS, SPACE_OUTLINER)) { */
+ prop = RNA_def_property(srna, "button", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Region Background", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
@@ -903,6 +1125,17 @@ static void rna_def_userdef_theme_spaces_main(StructRNA *srna)
RNA_def_property_ui_text(prop, "Theme Space", "Settings for space");
}
+static void rna_def_userdef_theme_spaces_gradient(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "space", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "ThemeSpaceGradient");
+ RNA_def_property_pointer_funcs(prop, "rna_Theme_space_gradient_get", NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Theme Space", "Settings for space");
+}
+
static void rna_def_userdef_theme_spaces_list_main(StructRNA *srna)
{
PropertyRNA *prop;
@@ -932,6 +1165,11 @@ static void rna_def_userdef_theme_spaces_vertex(StructRNA *srna)
RNA_def_property_range(prop, 1, 10);
RNA_def_property_ui_text(prop, "Vertex Size", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "vertex_unreferenced", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Vertex Group Unreferenced", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_theme_spaces_edge(StructRNA *srna)
@@ -962,6 +1200,11 @@ static void rna_def_userdef_theme_spaces_edge(StructRNA *srna)
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Edge UV Face Select", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "freestyle_edge_mark", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Freestyle Edge Mark", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_theme_spaces_face(StructRNA *srna)
@@ -987,6 +1230,11 @@ static void rna_def_userdef_theme_spaces_face(StructRNA *srna)
RNA_def_property_range(prop, 1, 10);
RNA_def_property_ui_text(prop, "Face Dot Size", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "freestyle_face_mark", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Freestyle Face Mark", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, short incl_nurbs)
@@ -1107,18 +1355,13 @@ static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
RNA_def_struct_ui_text(srna, "Theme 3D View", "Theme settings for the 3D View");
- rna_def_userdef_theme_spaces_main(srna);
+ rna_def_userdef_theme_spaces_gradient(srna);
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, "panel", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_array(prop, 4);
- RNA_def_property_ui_text(prop, "Panel", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
prop = RNA_def_property(srna, "wire", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Wire", "");
@@ -1273,11 +1516,6 @@ static void rna_def_userdef_theme_space_graph(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Grid", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- prop = RNA_def_property(srna, "panel", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Panel", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
prop = RNA_def_property(srna, "window_sliders", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "shade1");
RNA_def_property_array(prop, 3);
@@ -1360,12 +1598,6 @@ static void rna_def_userdef_theme_space_file(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Selected File", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- prop = RNA_def_property(srna, "tiles", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_float_sdna(prop, NULL, "panel");
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Tiles", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
prop = RNA_def_property(srna, "scrollbar", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "shade1");
RNA_def_property_array(prop, 3);
@@ -1473,6 +1705,13 @@ static void rna_def_userdef_theme_space_console(BlenderRNA *brna)
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Cursor", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "select", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "console_select");
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Selection", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
}
static void rna_def_userdef_theme_space_info(BlenderRNA *brna)
@@ -1537,10 +1776,28 @@ static void rna_def_userdef_theme_space_text(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Syntax Built-in", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+ prop = RNA_def_property(srna, "syntax_symbols", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "syntaxs");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Syntax Symbols", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
prop = RNA_def_property(srna, "syntax_special", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "syntaxv");
RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Decorator", "");
+ RNA_def_property_ui_text(prop, "Syntax Special", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "syntax_preprocessor", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "syntaxd");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Syntax PreProcessor", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "syntax_reserved", 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, "Syntax Reserved", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop = RNA_def_property(srna, "syntax_comment", PROP_FLOAT, PROP_COLOR_GAMMA);
@@ -1637,11 +1894,29 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Group Node", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+ prop = RNA_def_property(srna, "group_socket_node", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "console_output");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Group Socket Node", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
prop = RNA_def_property(srna, "frame_node", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "movie");
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Frame Node", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "matte_node", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "syntaxs");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Matte Node", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "distor_node", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "syntaxd");
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Distort Node", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
prop = RNA_def_property(srna, "noodle_curving", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "noodle_curving");
@@ -1654,7 +1929,7 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna)
static void rna_def_userdef_theme_space_logic(BlenderRNA *brna)
{
StructRNA *srna;
- PropertyRNA *prop;
+// PropertyRNA *prop;
/* space_logic */
@@ -1665,17 +1940,13 @@ static void rna_def_userdef_theme_space_logic(BlenderRNA *brna)
rna_def_userdef_theme_spaces_main(srna);
- prop = RNA_def_property(srna, "panel", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Panel", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_theme_space_buts(BlenderRNA *brna)
{
StructRNA *srna;
- PropertyRNA *prop;
+// PropertyRNA *prop;
/* space_buts */
@@ -1686,10 +1957,6 @@ static void rna_def_userdef_theme_space_buts(BlenderRNA *brna)
rna_def_userdef_theme_spaces_main(srna);
- prop = RNA_def_property(srna, "panel", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Panel", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_theme_space_time(BlenderRNA *brna)
@@ -2224,6 +2491,7 @@ static void rna_def_userdef_themes(BlenderRNA *brna)
static EnumPropertyItem active_theme_area[] = {
{0, "USER_INTERFACE", ICON_UI, "User Interface", ""},
+ {19, "STYLE", ICON_FONTPREVIEW, "Text Style", ""},
{18, "BONE_COLOR_SETS", ICON_COLOR, "Bone Color Sets", ""},
{1, "VIEW_3D", ICON_VIEW3D, "3D View", ""},
{2, "TIMELINE", ICON_TIME, "Timeline", ""},
@@ -2390,6 +2658,32 @@ static void rna_def_userdef_addon(BlenderRNA *brna)
prop = RNA_def_property(srna, "module", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Module", "Module name");
RNA_def_struct_name_property(srna, prop);
+
+ /* Collection active property */
+ prop = RNA_def_property(srna, "preferences", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "AddonPreferences");
+ RNA_def_property_pointer_funcs(prop, "rna_Addon_preferences_get", NULL, NULL, NULL);
+}
+
+static void rna_def_userdef_addon_pref(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "AddonPreferences", NULL);
+ RNA_def_struct_ui_text(srna, "Addon Preferences", "");
+ RNA_def_struct_sdna(srna, "bAddon"); /* WARNING: only a bAddon during registration */
+
+ RNA_def_struct_refine_func(srna, "rna_AddonPref_refine");
+ RNA_def_struct_register_funcs(srna, "rna_AddonPref_register", "rna_AddonPref_unregister", NULL);
+ RNA_def_struct_idprops_func(srna, "rna_AddonPref_idprops");
+
+ /* registration */
+ RNA_define_verify_sdna(0);
+ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "module");
+ RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
+ RNA_define_verify_sdna(1);
}
@@ -2400,6 +2694,7 @@ static void rna_def_userdef_dothemes(BlenderRNA *brna)
rna_def_userdef_theme_ui(brna);
rna_def_userdef_theme_space_generic(brna);
+ rna_def_userdef_theme_space_gradient(brna);
rna_def_userdef_theme_space_list_generic(brna);
rna_def_userdef_theme_space_view3d(brna);
@@ -3027,62 +3322,10 @@ static void rna_def_userdef_system(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
-#if 0
- /* hardcoded here, could become dynamic somehow */
- /* locale according to http://www.roseindia.net/tutorials/I18N/locales-list.shtml */
- /* if you edit here, please also edit the source/blender/blenfont/intern/blf_lang.c 's locales */
- /* Note: As this list is in alphabetical order, and not defined order,
- * here is the highest define currently in use: 35 (Esperanto). */
- static EnumPropertyItem language_items[] = {
- { 0, "", 0, N_("Nearly Done"), ""},
- { 0, "DEFAULT", 0, "Default (Default)", ""},
- /* using the utf8 flipped form of Arabic (العربية) */
- {21, "ARABIC", 0, "Arabic (ﺔﻴﺑﺮﻌﻟïº)", "ar_EG"},
- {32, "BRAZILIANPORTUGUESE", 0, "Brazilian Portuguese (Português do Brasil)", "pt_BR"},
- { 1, "ENGLISH", 0, "English (English)", "en_US"},
- { 8, "FRENCH", 0, "French (Français)", "fr_FR"},
- { 4, "ITALIAN", 0, "Italian (Italiano)", "it_IT"},
- { 2, "JAPANESE", 0, "Japanese (日本語)", "ja_JP"},
- {12, "PORTUGUESE", 0, "Portuguese (Português)", "pt"},
- {15, "RUSSIAN", 0, "Russian (РуÑÑкий)", "ru_RU"},
- {13, "SIMPLIFIED_CHINESE", 0, "Simplified Chinese (简体中文)", "zh_CN"},
- { 9, "SPANISH", 0, "Spanish (Español)", "es"},
- {14, "TRADITIONAL_CHINESE", 0, "Traditional Chinese (ç¹é«”中文)", "zh_TW"},
- {18, "UKRAINIAN", 0, "Ukrainian (УкраїнÑький)", "uk_UA"},
- { 0, "", 0, N_("In Progress"), ""},
-/* {22, "BULGARIAN", 0, "Bulgarian (БългарÑки)", "bg_BG"},*/ /* XXX Not active nor enough translated. */
-/* {10, "CATALAN", 0, "Catalan (Català)", "ca_AD"},*/ /* XXX Not active nor enough translated. */
- {16, "CROATIAN", 0, "Croatian (Hrvatski)", "hr_HR"},
- {11, "CZECH", 0, "Czech (Český)", "cs_CZ"},
- { 3, "DUTCH", 0, "Dutch (Nederlandse taal)", "nl_NL"},
- {35, "ESPERANTO", 0, "Esperanto (Esperanto)", "eo"},
- {34, "ESTONIAN", 0, "Estonian (Eestlane)", "et_EE"},
-/* { 6, "FINNISH", 0, "Finnish (Suomi)", "fi_FI"},*/ /* XXX Not active nor enough translated. */
- { 5, "GERMAN", 0, "German (Deutsch)", "de_DE"},
-/* {23, "GREEK", 0, "Greek (Ελληνικά)", "el_GR"},*/ /* XXX Not active nor enough translated. */
- /* using the utf8 flipped form of Hebrew (עִבְרִית)) */
- {33, "HEBREW", 0, "Hebrew (תירִבְעִ)", "he_IL"},
- {31, "HUNGARIAN", 0, "Hungarian (Magyar)", "hu_HU"},
- {27, "INDONESIAN", 0, "Indonesian (Bahasa indonesia)", "id_ID"},
- {29, "KYRGYZ", 0, "Kyrgyz (Кыргыз тили)", "ky_KG"},
-/* {24, "KOREAN", 0, "Korean (한국 언어)", "ko_KR"}, */ /* XXX Not active nor enough translated. */
-/* {25, "NEPALI", 0, "Nepali (नेपाली)", "ne_NP"},*/ /* XXX Not active nor enough translated. */
- /* using the utf8 flipped form of Persian (Ùارسی) */
- {26, "PERSIAN", 0, "Persian (ﯽﺳﺭﺎﻓ)", "fa_IR"},
-/* {19, "POLISH", 0, "Polish (Polski)", "pl_PL"},*/ /* XXX Not active nor enough translated. */
-/* {20, "ROMANIAN", 0, "Romanian (Român)", "ro_RO"}, */ /* XXX Not active nor enough translated. */
- {17, "SERBIAN", 0, "Serbian (СрпÑки)", "sr_RS"},
- {28, "SERBIAN_LATIN", 0, "Serbian Latin (Srpski latinica)", "sr_RS@latin"},
- { 7, "SWEDISH", 0, "Swedish (Svenska)", "sv_SE"},
- {30, "TURKISH", 0, "Turkish (Türkçe)", "tr_TR"},
- { 0, NULL, 0, NULL, NULL}
- };
-#else
static EnumPropertyItem language_items[] = {
- { 0, "DEFAULT", 0, "Default (Default)", ""},
- { 0, NULL, 0, NULL, NULL}
+ {0, "DEFAULT", 0, "Default (Default)", ""},
+ {0, NULL, 0, NULL, NULL}
};
-#endif
#ifdef WITH_CYCLES
static EnumPropertyItem compute_device_items[] = {
@@ -3106,7 +3349,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
prop = RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "dpi");
- RNA_def_property_range(prop, 48, 128);
+ RNA_def_property_range(prop, 48, 144);
RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display");
RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
@@ -3133,12 +3376,17 @@ static void rna_def_userdef_system(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_translate_tooltips", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_TR_TOOLTIPS);
- RNA_def_property_ui_text(prop, "Translate Tooltips", "Translate Tooltips");
+ RNA_def_property_ui_text(prop, "Translate Tooltips", "Translate tooltips");
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop = RNA_def_property(srna, "use_translate_interface", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_TR_IFACE);
- RNA_def_property_ui_text(prop, "Translate Interface", "Translate Interface");
+ RNA_def_property_ui_text(prop, "Translate Interface", "Translate interface");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "use_translate_new_dataname", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_TR_NEWDATANAME);
+ RNA_def_property_ui_text(prop, "Translate New Names", "Translate new data names (when adding/creating some)");
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop = RNA_def_property(srna, "use_textured_fonts", PROP_BOOLEAN, PROP_NONE);
@@ -3192,7 +3440,8 @@ static void rna_def_userdef_system(BlenderRNA *brna)
prop = RNA_def_property(srna, "prefetch_frames", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "prefetchframes");
- RNA_def_property_range(prop, 0, 500);
+ RNA_def_property_range(prop, 0, INT_MAX);
+ RNA_def_property_ui_range(prop, 0, 500, 1, 0);
RNA_def_property_ui_text(prop, "Prefetch Frames", "Number of frames to render ahead during playback (sequencer only)");
prop = RNA_def_property(srna, "memory_cache_limit", PROP_INT, PROP_NONE);
@@ -3229,6 +3478,12 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "GPU Mipmap Generation", "Generate Image Mipmaps on the GPU");
RNA_def_property_update(prop, 0, "rna_userdef_gl_gpu_mipmaps");
+ prop = RNA_def_property(srna, "image_gpubuffer_limit", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "image_gpubuffer_limit");
+ RNA_def_property_range(prop, 0, 128);
+ RNA_def_property_ui_text(prop, "Image GPU draw limit", "If set, amount of Mega Pixels to use for drawing Images as GPU textures");
+
+
prop = RNA_def_property(srna, "use_vertex_buffer_objects", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_VBO);
RNA_def_property_ui_text(prop, "VBOs",
@@ -3236,13 +3491,6 @@ static void rna_def_userdef_system(BlenderRNA *brna)
/* this isn't essential but nice to check if VBO draws any differently */
RNA_def_property_update(prop, NC_WINDOW, NULL);
-#if 0
- prop = RNA_def_property(srna, "use_antialiasing", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_AA);
- RNA_def_property_ui_text(prop, "Anti-aliasing",
- "Use anti-aliasing for the 3D view (may impact redraw performance)");
-#endif
-
prop = RNA_def_property(srna, "anisotropic_filter", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "anisotropic_filter");
RNA_def_property_enum_items(prop, anisotropic_items);
@@ -3275,7 +3523,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "wmdrawmethod");
RNA_def_property_enum_items(prop, draw_method_items);
RNA_def_property_ui_text(prop, "Window Draw Method", "Drawing method used by the window manager");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
+ RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
prop = RNA_def_property(srna, "audio_mixing_buffer", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mixbufsize");
@@ -3329,6 +3577,12 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_enum_items(prop, multi_sample_levels);
RNA_def_property_ui_text(prop, "MultiSample", "Enable OpenGL multi-sampling, only for systems that support it, requires restart");
+ prop = RNA_def_property(srna, "use_region_overlap", PROP_BOOLEAN, PROP_NONE);
+ 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");
+
#ifdef WITH_CYCLES
prop = RNA_def_property(srna, "compute_device_type", PROP_ENUM, PROP_NONE);
RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT);
@@ -3534,6 +3788,11 @@ static void rna_def_userdef_input(BlenderRNA *brna)
RNA_def_property_range(prop, 0, 32);
RNA_def_property_ui_text(prop, "Wheel Scroll Lines", "Number of lines scrolled at a time with the mouse wheel");
+ prop = RNA_def_property(srna, "use_trackpad_natural", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "uiflag2", USER_TRACKPAD_NATURAL);
+ RNA_def_property_ui_text(prop, "Trackpad Natural",
+ "If your system uses 'natural' scrolling, this option keeps consistent trackpad usage throughout the UI");
+
prop = RNA_def_property(srna, "active_keyconfig", PROP_STRING, PROP_DIRPATH);
RNA_def_property_string_sdna(prop, NULL, "keyconfigstr");
RNA_def_property_ui_text(prop, "Key Config", "The name of the active key configuration");
@@ -3664,6 +3923,11 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna)
"The time (in minutes) to wait between automatic temporary saves");
RNA_def_property_update(prop, 0, "rna_userdef_autosave_update");
+ prop = RNA_def_property(srna, "use_keep_session", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "uiflag2", USER_KEEP_SESSION);
+ RNA_def_property_ui_text(prop, "Keep Session",
+ "Always load session recovery and save it after quitting Blender");
+
prop = RNA_def_property(srna, "recent_files", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 0, 30);
RNA_def_property_ui_text(prop, "Recent Files", "Maximum number of recently opened files to remember");
@@ -3785,6 +4049,7 @@ void RNA_def_userdef(BlenderRNA *brna)
rna_def_userdef_filepaths(brna);
rna_def_userdef_system(brna);
rna_def_userdef_addon(brna);
+ rna_def_userdef_addon_pref(brna);
}
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index f3e28f1d7a3..f42197ec0a9 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -24,20 +24,23 @@
* \ingroup RNA
*/
-
#include <stdlib.h>
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "BLF_translation.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "rna_internal.h"
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
-#include "DNA_userdef_types.h"
-#include "DNA_windowmanager_types.h"
-
#include "WM_types.h"
EnumPropertyItem event_keymouse_value_items[] = {
@@ -416,6 +419,7 @@ EnumPropertyItem wm_report_items[] = {
{RPT_DEBUG, "DEBUG", 0, "Debug", ""},
{RPT_INFO, "INFO", 0, "Info", ""},
{RPT_OPERATOR, "OPERATOR", 0, "Operator", ""},
+ {RPT_PROPERTY, "PROPERTY", 0, "Property", ""},
{RPT_WARNING, "WARNING", 0, "Warning", ""},
{RPT_ERROR, "ERROR", 0, "Error", ""},
{RPT_ERROR_INVALID_INPUT, "ERROR_INVALID_INPUT", 0, "Invalid Input", ""},
@@ -465,7 +469,7 @@ static StructRNA *rna_OperatorProperties_refine(PointerRNA *ptr)
return ptr->type;
}
-static IDProperty *rna_OperatorProperties_idprops(PointerRNA *ptr, int create)
+static IDProperty *rna_OperatorProperties_idprops(PointerRNA *ptr, bool create)
{
if (create && !ptr->data) {
IDPropertyTemplate val = {0};
@@ -852,8 +856,11 @@ static void rna_Operator_unregister(struct Main *bmain, StructRNA *type)
/* update while blender is running */
wm = bmain->wm.first;
- if (wm)
+ if (wm) {
WM_operator_stack_clear(wm);
+
+ WM_operator_handlers_clear(wm, ot);
+ }
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
RNA_struct_free_extension(type, &ot->ext);
@@ -942,7 +949,7 @@ static int operator_check(bContext *C, wmOperator *op)
return result;
}
-static int operator_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int operator_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
extern FunctionRNA rna_Operator_invoke_func;
@@ -969,7 +976,7 @@ static int operator_invoke(bContext *C, wmOperator *op, wmEvent *event)
}
/* same as invoke */
-static int operator_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int operator_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
extern FunctionRNA rna_Operator_modal_func;
@@ -1045,6 +1052,7 @@ void macro_wrapper(wmOperatorType *ot, void *userdata);
static char _operator_idname[OP_MAX_TYPENAME];
static char _operator_name[OP_MAX_TYPENAME];
static char _operator_descr[RNA_DYN_DESCR_MAX];
+static char _operator_ctxt[RNA_DYN_DESCR_MAX];
static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
@@ -1058,10 +1066,13 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *
dummyot.idname = _operator_idname; /* only assigne the pointer, string is NULL'd */
dummyot.name = _operator_name; /* only assigne the pointer, string is NULL'd */
dummyot.description = _operator_descr; /* only assigne the pointer, string is NULL'd */
+ dummyot.translation_context = _operator_ctxt; /* only assigne the pointer, string is NULL'd */
RNA_pointer_create(NULL, &RNA_Operator, &dummyop, &dummyotr);
/* 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);
/* validate the python class */
if (validate(&dummyotr, data, have_function) != 0)
@@ -1112,9 +1123,10 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *
int idlen = strlen(_operator_idname) + 4;
int namelen = strlen(_operator_name) + 1;
int desclen = strlen(_operator_descr) + 1;
+ int ctxtlen = strlen(_operator_ctxt) + 1;
char *ch;
/* 2 terminators and 3 to convert a.b -> A_OT_b */
- ch = MEM_callocN(sizeof(char) * (idlen + namelen + desclen), "_operator_idname");
+ ch = MEM_callocN(sizeof(char) * (idlen + namelen + desclen + ctxtlen), "_operator_idname");
WM_operator_bl_idname(ch, _operator_idname); /* convert the idname from python */
dummyot.idname = ch;
ch += idlen;
@@ -1123,6 +1135,9 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *
ch += namelen;
strcpy(ch, _operator_descr);
dummyot.description = ch;
+ ch += desclen;
+ strcpy(ch, _operator_ctxt);
+ dummyot.translation_context = ch;
}
}
@@ -1137,8 +1152,9 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *
* for now just remove from dir(bpy.types) */
/* create a new operator type */
- dummyot.ext.srna = RNA_def_struct(&BLENDER_RNA, dummyot.idname, "Operator");
+ dummyot.ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, dummyot.idname, &RNA_Operator);
RNA_def_struct_flag(dummyot.ext.srna, STRUCT_NO_IDPROPERTIES); /* operator properties are registered separately */
+ RNA_def_struct_translation_context(dummyot.ext.srna, dummyot.translation_context);
dummyot.ext.data = data;
dummyot.ext.call = call;
dummyot.ext.free = free;
@@ -1177,8 +1193,14 @@ static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, v
dummyot.idname = _operator_idname; /* only assigne the pointer, string is NULL'd */
dummyot.name = _operator_name; /* only assigne the pointer, string is NULL'd */
dummyot.description = _operator_descr; /* only assigne the pointer, string is NULL'd */
+ dummyot.translation_context = _operator_ctxt; /* only assigne the pointer, string is NULL'd */
RNA_pointer_create(NULL, &RNA_Macro, &dummyop, &dummyotr);
+ /* 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);
+
/* validate the python class */
if (validate(&dummyotr, data, have_function) != 0)
return NULL;
@@ -1188,9 +1210,10 @@ static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, v
int idlen = strlen(_operator_idname) + 4;
int namelen = strlen(_operator_name) + 1;
int desclen = strlen(_operator_descr) + 1;
+ int ctxtlen = strlen(_operator_ctxt) + 1;
char *ch;
/* 2 terminators and 3 to convert a.b -> A_OT_b */
- ch = MEM_callocN(sizeof(char) * (idlen + namelen + desclen), "_operator_idname");
+ ch = MEM_callocN(sizeof(char) * (idlen + namelen + desclen + ctxtlen), "_operator_idname");
WM_operator_bl_idname(ch, _operator_idname); /* convert the idname from python */
dummyot.idname = ch;
ch += idlen;
@@ -1199,6 +1222,9 @@ static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, v
ch += namelen;
strcpy(ch, _operator_descr);
dummyot.description = ch;
+ ch += desclen;
+ strcpy(ch, _operator_ctxt);
+ dummyot.translation_context = ch;
}
if (strlen(identifier) >= sizeof(dummyop.idname)) {
@@ -1218,7 +1244,8 @@ static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, v
* for now just remove from dir(bpy.types) */
/* create a new operator type */
- dummyot.ext.srna = RNA_def_struct(&BLENDER_RNA, dummyot.idname, "Operator");
+ dummyot.ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, dummyot.idname, &RNA_Operator);
+ RNA_def_struct_translation_context(dummyot.ext.srna, dummyot.translation_context);
dummyot.ext.data = data;
dummyot.ext.call = call;
dummyot.ext.free = free;
@@ -1268,6 +1295,16 @@ static void rna_Operator_bl_label_set(PointerRNA *ptr, const char *value)
assert(!"setting the bl_label on a non-builtin operator");
}
+static void rna_Operator_bl_translation_context_set(PointerRNA *ptr, const char *value)
+{
+ wmOperator *data = (wmOperator *)(ptr->data);
+ char *str = (char *)data->type->translation_context;
+ if (!str[0])
+ BLI_strncpy(str, value, RNA_DYN_DESCR_MAX); /* utf8 already ensured */
+ else
+ assert(!"setting the bl_translation_context on a non-builtin operator");
+}
+
static void rna_Operator_bl_description_set(PointerRNA *ptr, const char *value)
{
wmOperator *data = (wmOperator *)(ptr->data);
@@ -1298,6 +1335,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);
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -1329,9 +1367,6 @@ static void rna_def_operator(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
RNA_def_struct_name_property(srna, prop);
- /* operator's label indeed doesn't need PROP_TRANSLATE flag: translation of label happens in runtime
- * when drawing panel and having this flag set will make runtime switching of language much more tricky
- * because label will be stored translated */
prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->name");
RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
@@ -1339,7 +1374,15 @@ static void rna_def_operator(BlenderRNA *brna)
/* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
RNA_def_property_flag(prop, PROP_REGISTER);
- prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_TRANSLATE);
+ 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_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_flag(prop, PROP_REGISTER_OPTIONAL);
+ RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */
+
+ prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->description");
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_description_set");
@@ -1375,6 +1418,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);
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -1396,9 +1440,6 @@ static void rna_def_macro_operator(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
RNA_def_struct_name_property(srna, prop);
- /* menu's label indeed doesn't need PROP_TRANSLATE flag: translation of label happens in runtime
- * when drawing panel and having this flag set will make runtime switching of language much more tricky
- * because label will be stored translated */
prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->name");
RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
@@ -1406,7 +1447,15 @@ static void rna_def_macro_operator(BlenderRNA *brna)
/* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
RNA_def_property_flag(prop, PROP_REGISTER);
- prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_TRANSLATE);
+ 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_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_flag(prop, PROP_REGISTER_OPTIONAL);
+ RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */
+
+ prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "type->description");
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_description_set");
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index b7895cc0e2d..64c5f7ae220 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -86,6 +86,16 @@ static void rna_event_timer_remove(struct wmWindowManager *wm, wmTimer *timer)
WM_event_remove_timer(wm, timer->win, timer);
}
+/* wrap these because of 'const wmEvent *' */
+static int rna_Operator_confirm(bContext *C, wmOperator *op, wmEvent *event)
+{
+ return WM_operator_confirm(C, op, event);
+}
+static int rna_Operator_props_popup(bContext *C, wmOperator *op, wmEvent *event)
+{
+ return WM_operator_props_popup(C, op, event);
+}
+
static wmKeyMapItem *rna_KeyMap_item_new(wmKeyMap *km, ReportList *reports, const char *idname, int type, int value,
int any, int shift, int ctrl, int alt, int oskey, int keymodifier, int head)
{
@@ -266,7 +276,7 @@ void RNA_api_wm(StructRNA *srna)
/* invoke functions, for use with python */
- func = RNA_def_function(srna, "invoke_props_popup", "WM_operator_props_popup");
+ func = RNA_def_function(srna, "invoke_props_popup", "rna_Operator_props_popup");
RNA_def_function_ui_description(func, "Operator popup invoke");
rna_generic_op_invoke(func, WM_GEN_INVOKE_EVENT | WM_GEN_INVOKE_RETURN);
@@ -284,7 +294,7 @@ void RNA_api_wm(StructRNA *srna)
RNA_def_function_ui_description(func, "Operator popup invoke");
rna_generic_op_invoke(func, WM_GEN_INVOKE_SIZE | WM_GEN_INVOKE_RETURN);
- func = RNA_def_function(srna, "invoke_confirm", "WM_operator_confirm");
+ func = RNA_def_function(srna, "invoke_confirm", "rna_Operator_confirm");
RNA_def_function_ui_description(func, "Operator confirmation");
rna_generic_op_invoke(func, WM_GEN_INVOKE_EVENT | WM_GEN_INVOKE_RETURN);
diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c
index a84b1124d44..b689a82c231 100644
--- a/source/blender/makesrna/intern/rna_world.c
+++ b/source/blender/makesrna/intern/rna_world.c
@@ -42,6 +42,7 @@
#include "MEM_guardedalloc.h"
+#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_texture.h"
@@ -121,14 +122,14 @@ static void rna_World_stars_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po
WM_main_add_notifier(NC_WORLD | ND_WORLD_STARS, wo);
}
-static void rna_World_use_nodes_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_World_use_nodes_update(bContext *C, PointerRNA *ptr)
{
World *wrld = (World *)ptr->data;
if (wrld->use_nodes && wrld->nodetree == NULL)
- ED_node_shader_default(scene, &wrld->id);
+ ED_node_shader_default(C, &wrld->id);
- rna_World_update(bmain, scene, ptr);
+ rna_World_update(CTX_data_main(C), CTX_data_scene(C), ptr);
}
#else
@@ -494,18 +495,6 @@ void RNA_def_world(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
-#if 0
- static EnumPropertyItem physics_engine_items[] = {
- {WOPHY_NONE, "NONE", 0, "None", ""},
- /*{WOPHY_ENJI, "ENJI", 0, "Enji", ""}, */
- /*{WOPHY_SUMO, "SUMO", 0, "Sumo (Deprecated)", ""}, */
- /*{WOPHY_DYNAMO, "DYNAMO", 0, "Dynamo", ""}, */
- /*{WOPHY_ODE, "ODE", 0, "ODE", ""}, */
- {WOPHY_BULLET, "BULLET", 0, "Bullet", ""},
- {0, NULL, 0, NULL, NULL}
- };
-#endif
-
srna = RNA_def_struct(brna, "World", "ID");
RNA_def_struct_ui_text(srna, "World",
"World datablock describing the environment and ambient lighting of a scene");
@@ -529,7 +518,7 @@ void RNA_def_world(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "zenr");
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Zenith Color", "Color at the zenith");
- RNA_def_property_update(prop, 0, "rna_World_update");
+ RNA_def_property_update(prop, NC_WORLD | ND_WORLD_DRAW, "rna_World_update");
prop = RNA_def_property(srna, "ambient_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "ambr");
@@ -554,17 +543,17 @@ void RNA_def_world(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_sky_blend", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "skytype", WO_SKYBLEND);
RNA_def_property_ui_text(prop, "Blend Sky", "Render background with natural progression from horizon to zenith");
- RNA_def_property_update(prop, 0, "rna_World_update");
+ RNA_def_property_update(prop, NC_WORLD | ND_WORLD_DRAW, "rna_World_update");
prop = RNA_def_property(srna, "use_sky_paper", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "skytype", WO_SKYPAPER);
RNA_def_property_ui_text(prop, "Paper Sky", "Flatten blend or texture coordinates");
- RNA_def_property_update(prop, 0, "rna_World_update");
+ RNA_def_property_update(prop, NC_WORLD | ND_WORLD_DRAW, "rna_World_update");
prop = RNA_def_property(srna, "use_sky_real", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "skytype", WO_SKYREAL);
RNA_def_property_ui_text(prop, "Real Sky", "Render background with a real horizon, relative to the camera angle");
- RNA_def_property_update(prop, 0, "rna_World_update");
+ RNA_def_property_update(prop, NC_WORLD | ND_WORLD_DRAW, "rna_World_update");
/* nested structs */
prop = RNA_def_property(srna, "light_settings", PROP_POINTER, PROP_NONE);
@@ -593,6 +582,7 @@ void RNA_def_world(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes to render the world");
RNA_def_property_update(prop, 0, "rna_World_use_nodes_update");
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index cf3bb05849a..9f1361b4909 100644
--- a/source/blender/modifiers/CMakeLists.txt
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -28,7 +28,6 @@ set(INC
.
intern
../blenkernel
- ../blenkernel/intern
../blenlib
../blenfont
../blenloader
@@ -64,9 +63,13 @@ set(SRC
intern/MOD_fluidsim.c
intern/MOD_fluidsim_util.c
intern/MOD_hook.c
- intern/MOD_lattice.c
intern/MOD_laplaciansmooth.c
+ intern/MOD_lattice.c
intern/MOD_mask.c
+ intern/MOD_meshcache.c
+ intern/MOD_meshcache_mdd.c
+ intern/MOD_meshcache_pc2.c
+ intern/MOD_meshcache_util.c
intern/MOD_meshdeform.c
intern/MOD_mirror.c
intern/MOD_multires.c
@@ -86,7 +89,9 @@ set(SRC
intern/MOD_solidify.c
intern/MOD_subsurf.c
intern/MOD_surface.c
+ intern/MOD_triangulate.c
intern/MOD_util.c
+ intern/MOD_uvwarp.c
intern/MOD_uvproject.c
intern/MOD_warp.c
intern/MOD_wave.c
@@ -94,11 +99,11 @@ set(SRC
intern/MOD_weightvgedit.c
intern/MOD_weightvgmix.c
intern/MOD_weightvgproximity.c
- intern/MOD_triangulate.c
MOD_modifiertypes.h
intern/MOD_boolean_util.h
intern/MOD_fluidsim_util.h
+ intern/MOD_meshcache_util.h
intern/MOD_util.h
intern/MOD_weightvg_util.h
)
diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h
index 290ba193567..bac75b3f30f 100644
--- a/source/blender/modifiers/MOD_modifiertypes.h
+++ b/source/blender/modifiers/MOD_modifiertypes.h
@@ -77,6 +77,8 @@ extern ModifierTypeInfo modifierType_Remesh;
extern ModifierTypeInfo modifierType_Skin;
extern ModifierTypeInfo modifierType_LaplacianSmooth;
extern ModifierTypeInfo modifierType_Triangulate;
+extern ModifierTypeInfo modifierType_UVWarp;
+extern ModifierTypeInfo modifierType_MeshCache;
/* MOD_util.c */
void modifier_type_init(ModifierTypeInfo *types[]);
diff --git a/source/blender/modifiers/SConscript b/source/blender/modifiers/SConscript
index 62fd9ba2de1..679109079c2 100644
--- a/source/blender/modifiers/SConscript
+++ b/source/blender/modifiers/SConscript
@@ -1,15 +1,54 @@
-#!/usr/bin/python
-Import ('env')
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
-sources = env.Glob('intern/*.c')
+Import('env')
-incs = '. ./intern'
-incs += ' #/intern/guardedalloc #/intern/bsp/extern #/intern/elbeem/extern #/extern/glew/include #/intern/opennl/extern'
-incs += ' ../render/extern/include ../blenloader ../bmesh'
-incs += ' ../include ../blenlib ../blenfont ../makesdna ../makesrna ../blenkernel ../blenkernel/intern'
-incs += ' ../gpu'
+sources = env.Glob('intern/*.c')
-incs += ' ' + env['BF_ZLIB_INC']
+incs = [
+ '.',
+ './intern',
+ '#/intern/guardedalloc',
+ '#/intern/bsp/extern',
+ '#/intern/elbeem/extern',
+ '#/extern/glew/include',
+ '#/intern/opennl/extern',
+ '../render/extern/include',
+ '../blenloader',
+ '../bmesh',
+ '../include',
+ '../blenlib',
+ '../blenfont',
+ '../makesdna',
+ '../makesrna',
+ '../blenkernel',
+ '../gpu',
+ env['BF_ZLIB_INC'],
+ ]
defs = []
@@ -17,7 +56,7 @@ if env ['WITH_BF_BOOLEAN']:
defs.append('WITH_MOD_BOOLEAN')
if env['WITH_BF_REMESH']:
- incs += ' #/intern/dualcon'
+ incs.append('#/intern/dualcon')
defs.append('WITH_MOD_REMESH')
if env['WITH_BF_FLUID']:
@@ -27,12 +66,12 @@ if env['WITH_BF_OCEANSIM']:
defs.append('WITH_OCEANSIM')
if env['WITH_BF_GAMEENGINE']:
- incs += ' #/extern/recastnavigation'
+ incs.append('#/extern/recastnavigation')
defs.append('WITH_GAMEENGINE')
if env['WITH_BF_INTERNATIONAL']:
defs.append('WITH_INTERNATIONAL')
-env.BlenderLib ( libname = 'bf_modifiers', sources = sources,
- includes = Split(incs), defines=defs,
- libtype=['core','player'], priority = [80, 40] )
+env.BlenderLib(libname='bf_modifiers', sources=sources,
+ includes=incs, defines=defs,
+ libtype=['core', 'player'], priority=[80, 40])
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index 3ca2c364345..bc65b27be0c 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -338,7 +338,6 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
/* offset matrix */
float offset[4][4];
float final_offset[4][4];
- float tmp_mat[4][4];
float length = amd->length;
int count = amd->count, maxVerts;
int *indexMap = NULL;
@@ -418,6 +417,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
unit_m4(final_offset);
for (j = 0; j < count - 1; j++) {
+ float tmp_mat[4][4];
mult_m4_m4m4(tmp_mat, offset, final_offset);
copy_m4_m4(final_offset, tmp_mat);
}
diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c
index 59befe4db05..b14c4ba0ad1 100644
--- a/source/blender/modifiers/intern/MOD_bevel.c
+++ b/source/blender/modifiers/intern/MOD_bevel.c
@@ -31,19 +31,22 @@
/** \file blender/modifiers/intern/MOD_bevel.c
* \ingroup modifiers
*/
+
+#include "DNA_object_types.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_string.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_deform.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
#include "BKE_bmesh.h" /* only for defines */
-#include "bmesh.h"
+#include "MOD_util.h"
-#include "DNA_object_types.h"
+#include "bmesh.h"
#include "MEM_guardedalloc.h"
@@ -88,21 +91,12 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
return dataMask;
}
-// #define USE_BM_BEVEL_OP_AS_MOD
-
#ifdef USE_BM_BEVEL_OP_AS_MOD
-/* BMESH_TODO
- *
- * this bevel calls the new bevel code (added since 2.64)
- * which is missing many of the options which the bevel modifier from 2.4x has.
- * - no vertex bevel
- * - no weight bevel
- *
- * These will need to be added to the bmesh operator.
- * - campbell
+/*
+ * This calls the new bevel code (added since 2.64)
*/
-static DerivedMesh *applyModifier(ModifierData *md, struct Object *UNUSED(ob),
+static DerivedMesh *applyModifier(ModifierData *md, struct Object *ob,
DerivedMesh *dm,
ModifierApplyFlag UNUSED(flag))
{
@@ -110,13 +104,33 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *UNUSED(ob),
BMesh *bm;
BMIter iter;
BMEdge *e;
+ BMVert *v;
+ float weight;
+ int vgroup = -1;
+ MDeformVert *dvert = NULL;
BevelModifierData *bmd = (BevelModifierData *) md;
const float threshold = cosf((bmd->bevel_angle + 0.00001f) * (float)M_PI / 180.0f);
- const int segments = 16; /* XXX */
+ const bool vertex_only = bmd->flags & BME_BEVEL_VERT;
bm = DM_to_bmesh(dm);
- if (bmd->lim_flags & BME_BEVEL_ANGLE) {
+ if (vertex_only) {
+ if ((bmd->lim_flags & BME_BEVEL_VGROUP) && bmd->defgrp_name[0]) {
+ modifier_get_vgroup(ob, dm, bmd->defgrp_name, &dvert, &vgroup);
+ }
+ BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_vert_is_manifold(v))
+ continue;
+ if (vgroup != -1) {
+ /* Is it safe to assume bmesh indices and dvert array line up?? */
+ weight = defvert_array_find_weight_safe(dvert, BM_elem_index_get(v), vgroup);
+ if (weight <= 0.0f)
+ continue;
+ }
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ }
+ }
+ else if (bmd->lim_flags & BME_BEVEL_ANGLE) {
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
/* check for 1 edge having 2 face users */
BMLoop *l_a, *l_b;
@@ -133,6 +147,11 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *UNUSED(ob),
/* crummy, is there a way just to operator on all? - campbell */
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_edge_is_manifold(e)) {
+ if (bmd->lim_flags & BME_BEVEL_WEIGHT) {
+ weight = BM_elem_float_data_get(&bm->edata, e, CD_BWEIGHT);
+ if (weight == 0.0f)
+ continue;
+ }
BM_elem_flag_enable(e, BM_ELEM_TAG);
BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
@@ -140,11 +159,15 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *UNUSED(ob),
}
}
- BM_mesh_bevel(bm, bmd->value, segments);
+ BM_mesh_bevel(bm, bmd->value, bmd->res,
+ vertex_only, bmd->lim_flags & BME_BEVEL_WEIGHT, true,
+ dvert, vgroup);
result = CDDM_from_bmesh(bm, TRUE);
- BLI_assert(bm->toolflagpool == NULL); /* make sure we never alloc'd this */
+ BLI_assert(bm->vtoolflagpool == NULL &&
+ bm->etoolflagpool == NULL &&
+ bm->ftoolflagpool == NULL); /* make sure we never alloc'd these */
BM_mesh_free(bm);
CDDM_calc_normals(result);
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index 0a48003fc81..04198d9feb9 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -135,7 +135,13 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
* in some cases the depsgraph fails us - especially for objects
* in other scenes when compositing */
if (bmd->object != ob) {
- dm = mesh_get_derived_final(md->scene, bmd->object, CD_MASK_MESH);
+ /* weak! - but we can too easy end up with circular dep crash otherwise */
+ if (modifiers_findByType(bmd->object, eModifierType_Boolean) == NULL) {
+ dm = mesh_get_derived_final(md->scene, bmd->object, CD_MASK_MESH);
+ }
+ else {
+ dm = bmd->object->derivedFinal;
+ }
}
else {
dm = NULL;
diff --git a/source/blender/modifiers/intern/MOD_boolean_util.c b/source/blender/modifiers/intern/MOD_boolean_util.c
index 0cf4f6a008f..c9a7dc9a73d 100644
--- a/source/blender/modifiers/intern/MOD_boolean_util.c
+++ b/source/blender/modifiers/intern/MOD_boolean_util.c
@@ -46,6 +46,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_depsgraph.h"
+#include "BKE_global.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
@@ -75,7 +76,7 @@ static void VertexIt_Destruct(CSG_VertexIteratorDescriptor *iterator)
if (iterator->it) {
/* deallocate memory for iterator */
MEM_freeN(iterator->it);
- iterator->it = 0;
+ iterator->it = NULL;
}
iterator->Done = NULL;
iterator->Fill = NULL;
@@ -126,11 +127,11 @@ static void VertexIt_Construct(CSG_VertexIteratorDescriptor *output, DerivedMesh
{
VertexIt *it;
- if (output == 0) return;
+ if (output == NULL) return;
/* allocate some memory for blender iterator */
it = (VertexIt *)(MEM_mallocN(sizeof(VertexIt), "Boolean_VIt"));
- if (it == 0) {
+ if (it == NULL) {
return;
}
/* assign blender specific variables */
@@ -220,11 +221,11 @@ static void FaceIt_Construct(
CSG_FaceIteratorDescriptor *output, DerivedMesh *dm, int offset, Object *ob)
{
FaceIt *it;
- if (output == 0) return;
+ if (output == NULL) return;
/* allocate some memory for blender iterator */
it = (FaceIt *)(MEM_mallocN(sizeof(FaceIt), "Boolean_FIt"));
- if (it == 0) {
+ if (it == NULL) {
return;
}
/* assign blender specific variables */
@@ -295,7 +296,7 @@ static Object *AddNewBlenderMesh(Scene *scene, Base *base)
basen->flag &= ~SELECT;
/* Initialize the mesh data associated with this object. */
- ob_new->data = BKE_mesh_add("Mesh");
+ ob_new->data = BKE_mesh_add(G.main, "Mesh");
/* Finally assign the object type. */
ob_new->type = OB_MESH;
diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c
index 2105a6efd21..0f5f9db2ee6 100644
--- a/source/blender/modifiers/intern/MOD_build.c
+++ b/source/blender/modifiers/intern/MOD_build.c
@@ -37,6 +37,7 @@
#include "BLI_utildefines.h"
#include "BLI_rand.h"
+#include "BLI_math_vector.h"
#include "BLI_ghash.h"
#include "DNA_scene_types.h"
@@ -104,12 +105,19 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
MVert *mvert_src = dm->getVertArray(dm);
- vertMap = MEM_callocN(sizeof(*vertMap) * numVert_src, "build modifier vertMap");
- for (i = 0; i < numVert_src; i++) vertMap[i] = i;
- edgeMap = MEM_callocN(sizeof(*edgeMap) * numEdge_src, "build modifier edgeMap");
- for (i = 0; i < numEdge_src; i++) edgeMap[i] = i;
- faceMap = MEM_callocN(sizeof(*faceMap) * numPoly_src, "build modifier faceMap");
- for (i = 0; i < numPoly_src; i++) faceMap[i] = i;
+ vertMap = MEM_mallocN(sizeof(*vertMap) * numVert_src, "build modifier vertMap");
+ edgeMap = MEM_mallocN(sizeof(*edgeMap) * numEdge_src, "build modifier edgeMap");
+ faceMap = MEM_mallocN(sizeof(*faceMap) * numPoly_src, "build modifier faceMap");
+
+#pragma omp parallel sections if (numVert_src + numEdge_src + numPoly_src >= DM_OMP_LIMIT)
+ {
+#pragma omp section
+ { range_vn_i(vertMap, numVert_src, 0); }
+#pragma omp section
+ { range_vn_i(edgeMap, numEdge_src, 0); }
+#pragma omp section
+ { range_vn_i(faceMap, numPoly_src, 0); }
+ }
frac = (BKE_scene_frame_get(md->scene) - bmd->start) / bmd->length;
CLAMP(frac, 0.0f, 1.0f);
@@ -222,7 +230,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
/* copy the vertices across */
for (hashIter = BLI_ghashIterator_new(vertHash);
- !BLI_ghashIterator_isDone(hashIter);
+ BLI_ghashIterator_notDone(hashIter);
BLI_ghashIterator_step(hashIter)
)
{
diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c
index 2530a230e0a..d5620f91d6e 100644
--- a/source/blender/modifiers/intern/MOD_cast.c
+++ b/source/blender/modifiers/intern/MOD_cast.c
@@ -137,13 +137,13 @@ static void sphere_do(
int i, defgrp_index;
int has_radius = 0;
short flag, type;
- float fac, facm, len = 0.0f;
+ float len = 0.0f;
+ float fac = cmd->fac;
+ float facm = 1.0f - fac;
+ const float fac_orig = fac;
float vec[3], center[3] = {0.0f, 0.0f, 0.0f};
float mat[4][4], imat[4][4];
- fac = cmd->fac;
- facm = 1.0f - fac;
-
flag = cmd->flag;
type = cmd->type; /* projection type: sphere or cylinder */
@@ -193,67 +193,6 @@ static void sphere_do(
if (len == 0.0f) len = 10.0f;
}
- /* ready to apply the effect, one vertex at a time;
- * tiny optimization: the code is separated (with parts repeated)
- * in two possible cases:
- * with or w/o a vgroup. With lots of if's in the code below,
- * further optimization's are possible, if needed */
- if (dvert) { /* with a vgroup */
- MDeformVert *dv = dvert;
- float fac_orig = fac;
- for (i = 0; i < numVerts; i++, dv++) {
- float tmp_co[3];
- float weight;
-
- copy_v3_v3(tmp_co, vertexCos[i]);
- if (ctrl_ob) {
- if (flag & MOD_CAST_USE_OB_TRANSFORM) {
- mul_m4_v3(mat, tmp_co);
- }
- else {
- sub_v3_v3(tmp_co, center);
- }
- }
-
- copy_v3_v3(vec, tmp_co);
-
- if (type == MOD_CAST_TYPE_CYLINDER)
- vec[2] = 0.0f;
-
- if (has_radius) {
- if (len_v3(vec) > cmd->radius) continue;
- }
-
- weight = defvert_find_weight(dv, defgrp_index);
- if (weight <= 0.0f) continue;
-
- fac = fac_orig * weight;
- facm = 1.0f - fac;
-
- normalize_v3(vec);
-
- if (flag & MOD_CAST_X)
- tmp_co[0] = fac * vec[0] * len + facm * tmp_co[0];
- if (flag & MOD_CAST_Y)
- tmp_co[1] = fac * vec[1] * len + facm * tmp_co[1];
- if (flag & MOD_CAST_Z)
- tmp_co[2] = fac * vec[2] * len + facm * tmp_co[2];
-
- if (ctrl_ob) {
- if (flag & MOD_CAST_USE_OB_TRANSFORM) {
- mul_m4_v3(imat, tmp_co);
- }
- else {
- add_v3_v3(tmp_co, center);
- }
- }
-
- copy_v3_v3(vertexCos[i], tmp_co);
- }
- return;
- }
-
- /* no vgroup */
for (i = 0; i < numVerts; i++) {
float tmp_co[3];
@@ -276,6 +215,16 @@ static void sphere_do(
if (len_v3(vec) > cmd->radius) continue;
}
+ if (dvert) {
+ const float weight = defvert_find_weight(&dvert[i], defgrp_index);
+ if (weight == 0.0f) {
+ continue;
+ }
+
+ fac = fac_orig * weight;
+ facm = 1.0f - fac;
+ }
+
normalize_v3(vec);
if (flag & MOD_CAST_X)
@@ -308,14 +257,13 @@ static void cuboid_do(
int i, defgrp_index;
int has_radius = 0;
short flag;
- float fac, facm;
+ float fac = cmd->fac;
+ float facm = 1.0f - fac;
+ const float fac_orig = fac;
float min[3], max[3], bb[8][3];
float center[3] = {0.0f, 0.0f, 0.0f};
float mat[4][4], imat[4][4];
- fac = cmd->fac;
- facm = 1.0f - fac;
-
flag = cmd->flag;
ctrl_ob = cmd->object;
@@ -397,118 +345,10 @@ static void cuboid_do(
bb[0][2] = bb[1][2] = bb[2][2] = bb[3][2] = min[2];
bb[4][2] = bb[5][2] = bb[6][2] = bb[7][2] = max[2];
- /* ready to apply the effect, one vertex at a time;
- * tiny optimization: the code is separated (with parts repeated)
- * in two possible cases:
- * with or w/o a vgroup. With lots of if's in the code below,
- * further optimization's are possible, if needed */
- if (dvert) { /* with a vgroup */
- float fac_orig = fac;
- for (i = 0; i < numVerts; i++) {
- MDeformWeight *dw = NULL;
- int j, octant, coord;
- float d[3], dmax, apex[3], fbb;
- float tmp_co[3];
-
- copy_v3_v3(tmp_co, vertexCos[i]);
- if (ctrl_ob) {
- if (flag & MOD_CAST_USE_OB_TRANSFORM) {
- mul_m4_v3(mat, tmp_co);
- }
- else {
- sub_v3_v3(tmp_co, center);
- }
- }
-
- if (has_radius) {
- if (fabsf(tmp_co[0]) > cmd->radius ||
- fabsf(tmp_co[1]) > cmd->radius ||
- fabsf(tmp_co[2]) > cmd->radius)
- {
- continue;
- }
- }
-
- for (j = 0; j < dvert[i].totweight; ++j) {
- if (dvert[i].dw[j].def_nr == defgrp_index) {
- dw = &dvert[i].dw[j];
- break;
- }
- }
- if (!dw) continue;
-
- fac = fac_orig * dw->weight;
- facm = 1.0f - fac;
-
- /* The algo used to project the vertices to their
- * bounding box (bb) is pretty simple:
- * for each vertex v:
- * 1) find in which octant v is in;
- * 2) find which outer "wall" of that octant is closer to v;
- * 3) calculate factor (var fbb) to project v to that wall;
- * 4) project. */
-
- /* find in which octant this vertex is in */
- octant = 0;
- if (tmp_co[0] > 0.0f) octant += 1;
- if (tmp_co[1] > 0.0f) octant += 2;
- if (tmp_co[2] > 0.0f) octant += 4;
-
- /* apex is the bb's vertex at the chosen octant */
- copy_v3_v3(apex, bb[octant]);
-
- /* find which bb plane is closest to this vertex ... */
- d[0] = tmp_co[0] / apex[0];
- d[1] = tmp_co[1] / apex[1];
- d[2] = tmp_co[2] / apex[2];
-
- /* ... (the closest has the higher (closer to 1) d value) */
- dmax = d[0];
- coord = 0;
- if (d[1] > dmax) {
- dmax = d[1];
- coord = 1;
- }
- if (d[2] > dmax) {
- /* dmax = d[2]; */ /* commented, we don't need it */
- coord = 2;
- }
-
- /* ok, now we know which coordinate of the vertex to use */
-
- if (fabsf(tmp_co[coord]) < FLT_EPSILON) /* avoid division by zero */
- continue;
-
- /* finally, this is the factor we wanted, to project the vertex
- * to its bounding box (bb) */
- fbb = apex[coord] / tmp_co[coord];
-
- /* calculate the new vertex position */
- if (flag & MOD_CAST_X)
- tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
- if (flag & MOD_CAST_Y)
- tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
- if (flag & MOD_CAST_Z)
- tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;
-
- if (ctrl_ob) {
- if (flag & MOD_CAST_USE_OB_TRANSFORM) {
- mul_m4_v3(imat, tmp_co);
- }
- else {
- add_v3_v3(tmp_co, center);
- }
- }
-
- copy_v3_v3(vertexCos[i], tmp_co);
- }
- return;
- }
-
- /* no vgroup (check previous case for comments about the code) */
+ /* ready to apply the effect, one vertex at a time */
for (i = 0; i < numVerts; i++) {
int octant, coord;
- float d[3], dmax, fbb, apex[3];
+ float d[3], dmax, apex[3], fbb;
float tmp_co[3];
copy_v3_v3(tmp_co, vertexCos[i]);
@@ -530,17 +370,39 @@ static void cuboid_do(
}
}
+ if (dvert) {
+ const float weight = defvert_find_weight(&dvert[i], defgrp_index);
+ if (weight == 0.0f) {
+ continue;
+ }
+
+ fac = fac_orig * weight;
+ facm = 1.0f - fac;
+ }
+
+ /* The algo used to project the vertices to their
+ * bounding box (bb) is pretty simple:
+ * for each vertex v:
+ * 1) find in which octant v is in;
+ * 2) find which outer "wall" of that octant is closer to v;
+ * 3) calculate factor (var fbb) to project v to that wall;
+ * 4) project. */
+
+ /* find in which octant this vertex is in */
octant = 0;
if (tmp_co[0] > 0.0f) octant += 1;
if (tmp_co[1] > 0.0f) octant += 2;
if (tmp_co[2] > 0.0f) octant += 4;
+ /* apex is the bb's vertex at the chosen octant */
copy_v3_v3(apex, bb[octant]);
+ /* find which bb plane is closest to this vertex ... */
d[0] = tmp_co[0] / apex[0];
d[1] = tmp_co[1] / apex[1];
d[2] = tmp_co[2] / apex[2];
+ /* ... (the closest has the higher (closer to 1) d value) */
dmax = d[0];
coord = 0;
if (d[1] > dmax) {
@@ -552,11 +414,16 @@ static void cuboid_do(
coord = 2;
}
- if (fabsf(tmp_co[coord]) < FLT_EPSILON)
+ /* ok, now we know which coordinate of the vertex to use */
+
+ if (fabsf(tmp_co[coord]) < FLT_EPSILON) /* avoid division by zero */
continue;
+ /* finally, this is the factor we wanted, to project the vertex
+ * to its bounding box (bb) */
fbb = apex[coord] / tmp_co[coord];
+ /* calculate the new vertex position */
if (flag & MOD_CAST_X)
tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
if (flag & MOD_CAST_Y)
diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c
index 54f3efcc84c..da0758a09d0 100644
--- a/source/blender/modifiers/intern/MOD_cloth.c
+++ b/source/blender/modifiers/intern/MOD_cloth.c
@@ -155,7 +155,7 @@ static void copyData(ModifierData *md, ModifierData *target)
if (clmd->sim_parms->effector_weights)
tclmd->sim_parms->effector_weights = MEM_dupallocN(clmd->sim_parms->effector_weights);
tclmd->coll_parms = MEM_dupallocN(clmd->coll_parms);
- tclmd->point_cache = BKE_ptcache_copy_list(&tclmd->ptcaches, &clmd->ptcaches, FALSE);
+ tclmd->point_cache = BKE_ptcache_add(&tclmd->ptcaches);
tclmd->clothObject = NULL;
}
diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c
index b9384e6208e..ab141312932 100644
--- a/source/blender/modifiers/intern/MOD_collision.c
+++ b/source/blender/modifiers/intern/MOD_collision.c
@@ -137,7 +137,7 @@ static void deformVerts(ModifierData *md, Object *ob,
numverts = dm->getNumVerts(dm);
- if ((current_time > collmd->time_xnew) || (BKE_ptcache_get_continue_physics())) {
+ if (current_time > collmd->time_xnew) {
unsigned int i;
/* check if mesh has changed */
diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c
index 28cdfa810fa..2d3d5c97af7 100644
--- a/source/blender/modifiers/intern/MOD_decimate.c
+++ b/source/blender/modifiers/intern/MOD_decimate.c
@@ -63,7 +63,7 @@ static void initData(ModifierData *md)
DecimateModifierData *dmd = (DecimateModifierData *) md;
dmd->percent = 1.0;
- dmd->angle = DEG2RADF(15.0f);
+ dmd->angle = DEG2RADF(5.0f);
}
static void copyData(ModifierData *md, ModifierData *target)
@@ -188,7 +188,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* update for display only */
dmd->face_count = bm->totface;
result = CDDM_from_bmesh(bm, FALSE);
- BLI_assert(bm->toolflagpool == NULL); /* make sure we never alloc'd this */
+ BLI_assert(bm->vtoolflagpool == NULL); /* make sure we never alloc'd this */
+ BLI_assert(bm->etoolflagpool == NULL);
+ BLI_assert(bm->ftoolflagpool == NULL);
BM_mesh_free(bm);
#ifdef USE_TIMEIT
diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c
index ec81c5ce699..33601c197b9 100644
--- a/source/blender/modifiers/intern/MOD_edgesplit.c
+++ b/source/blender/modifiers/intern/MOD_edgesplit.c
@@ -30,33 +30,24 @@
/** \file blender/modifiers/intern/MOD_edgesplit.c
* \ingroup modifiers
+ *
+ * EdgeSplit modifier
+ *
+ * Splits edges in the mesh according to sharpness flag
+ * or edge angle (can be used to achieve autosmoothing)
*/
-
-/* EdgeSplit modifier: Splits edges in the mesh according to sharpness flag
- * or edge angle (can be used to achieve autosmoothing) */
-
#include "BLI_utildefines.h"
#include "BLI_math.h"
-#include "MEM_guardedalloc.h"
-
#include "BKE_cdderivedmesh.h"
#include "BKE_modifier.h"
-#include "BKE_mesh.h"
#include "bmesh.h"
+#include "tools/bmesh_edgesplit.h"
#include "DNA_object_types.h"
-/* EdgeSplit */
-/* EdgeSplit modifier: Splits edges in the mesh according to sharpness flag
- * or edge angle (can be used to achieve autosmoothing)
- *
- * note: this code is very close to MOD_bevel.c
- */
-
-#define EDGE_MARK 1
static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Object *UNUSED(ob))
{
@@ -67,7 +58,6 @@ static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Obj
float threshold = cosf((emd->split_angle + 0.00001f) * (float)M_PI / 180.0f);
bm = DM_to_bmesh(dm);
- BM_mesh_elem_toolflags_ensure(bm);
if (emd->flags & MOD_EDGESPLIT_FROMANGLE) {
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
@@ -81,7 +71,7 @@ static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Obj
/* 2 face edge - check angle*/
(dot_v3v3(l1->f->no, l2->f->no) < threshold))
{
- BMO_elem_flag_enable(bm, e, EDGE_MARK);
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
}
}
}
@@ -94,14 +84,13 @@ static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Obj
(e->l->next != e->l))
{
if (!BM_elem_flag_test(e, BM_ELEM_SMOOTH)) {
- BMO_elem_flag_enable(bm, e, EDGE_MARK);
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
}
}
}
}
- BMO_op_callf(bm, BMO_FLAG_DEFAULTS,
- "split_edges edges=%fe", EDGE_MARK);
+ BM_mesh_edgesplit(bm, FALSE, TRUE);
/* BM_mesh_validate(bm); */ /* for troubleshooting */
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index 1298d281de8..638f8f0ae01 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -161,7 +161,7 @@ static void createFacepa(ExplodeModifierData *emd,
mul_v3_fl(center, 0.25);
}
else
- mul_v3_fl(center, 0.3333f);
+ mul_v3_fl(center, 1.0f / 3.0f);
p = BLI_kdtree_find_nearest(tree, center, NULL, NULL);
diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
index 266226040a3..743cd1a829e 100644
--- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c
+++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
@@ -82,6 +82,7 @@ typedef struct BLaplacianSystem LaplacianSystem;
static CustomDataMask required_data_mask(Object *UNUSED(ob), ModifierData *md);
static int is_disabled(ModifierData *md, int UNUSED(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 float cotan_weight(float *v1, float *v2, float *v3);
static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts);
@@ -93,13 +94,12 @@ static void init_data(ModifierData *md);
static void init_laplacian_matrix(LaplacianSystem *sys);
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);
+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);
- data = NULL;
}
}
@@ -196,10 +196,10 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, in
static void init_data(ModifierData *md)
{
LaplacianSmoothModifierData *smd = (LaplacianSmoothModifierData *) md;
- smd->lambda = 0.00001f;
- smd->lambda_border = 0.00005f;
+ smd->lambda = 0.01f;
+ smd->lambda_border = 0.01f;
smd->repeat = 1;
- smd->flag = MOD_LAPLACIANSMOOTH_X | MOD_LAPLACIANSMOOTH_Y | MOD_LAPLACIANSMOOTH_Z | MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME;
+ smd->flag = MOD_LAPLACIANSMOOTH_X | MOD_LAPLACIANSMOOTH_Y | MOD_LAPLACIANSMOOTH_Z | MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME | MOD_LAPLACIANSMOOTH_NORMALIZED;
smd->defgrp_name[0] = '\0';
}
@@ -239,6 +239,13 @@ static CustomDataMask required_data_mask(Object *UNUSED(ob), ModifierData *md)
return dataMask;
}
+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 cotan_weight(float *v1, float *v2, float *v3)
{
float a[3], b[3], c[3], clen;
@@ -372,10 +379,17 @@ static void init_laplacian_matrix(LaplacianSystem *sys)
if (has_4_vert) sys->zerola[idv4] = 1;
}
- sys->ring_areas[idv1] += areaf;
- sys->ring_areas[idv2] += areaf;
- sys->ring_areas[idv3] += areaf;
- if (has_4_vert) sys->ring_areas[idv4] += areaf;
+ 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;
+ }
if (has_4_vert) {
@@ -403,9 +417,9 @@ static void init_laplacian_matrix(LaplacianSystem *sys)
}
}
else {
- w1 = cotan_weight(v1, v2, v3);
- w2 = cotan_weight(v2, v3, v1);
- w3 = cotan_weight(v3, v1, v2);
+ w1 = cotan_weight(v1, v2, v3) / 2.0f;
+ w2 = cotan_weight(v2, v3, v1) / 2.0f;
+ w3 = cotan_weight(v3, v1, v2) / 2.0f;
sys->fweights[i][0] = sys->fweights[i][0] + w1;
sys->fweights[i][1] = sys->fweights[i][1] + w2;
@@ -505,43 +519,26 @@ static void fill_laplacian_matrix(LaplacianSystem *sys)
}
}
-static void validate_solution(LaplacianSystem *sys, short flag)
+static void validate_solution(LaplacianSystem *sys, short flag, float lambda, float lambda_border)
{
- int i, idv1, idv2;
- float leni, lene;
+ int i;
+ float lam;
float vini, vend;
- float *vi1, *vi2, ve1[3], ve2[3];
+
if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) {
vini = compute_volume(sys->vertexCos, sys->mfaces, sys->numFaces);
}
- for (i = 0; i < sys->numEdges; i++) {
- idv1 = sys->medges[i].v1;
- idv2 = sys->medges[i].v2;
- vi1 = sys->vertexCos[idv1];
- vi2 = sys->vertexCos[idv2];
- ve1[0] = nlGetVariable(0, idv1);
- ve1[1] = nlGetVariable(1, idv1);
- ve1[2] = nlGetVariable(2, idv1);
- ve2[0] = nlGetVariable(0, idv2);
- ve2[1] = nlGetVariable(1, idv2);
- ve2[2] = nlGetVariable(2, idv2);
- leni = len_v3v3(vi1, vi2);
- lene = len_v3v3(ve1, ve2);
- if (lene > leni * MOD_LAPLACIANSMOOTH_MAX_EDGE_PERCENTAGE || lene < leni * MOD_LAPLACIANSMOOTH_MIN_EDGE_PERCENTAGE) {
- sys->zerola[idv1] = 1;
- sys->zerola[idv2] = 1;
- }
- }
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] = nlGetVariable(0, i);
+ sys->vertexCos[i][0] += lam * (nlGetVariable(0, i) - sys->vertexCos[i][0]);
}
if (flag & MOD_LAPLACIANSMOOTH_Y) {
- sys->vertexCos[i][1] = nlGetVariable(1, i);
+ sys->vertexCos[i][1] += lam * (nlGetVariable(1, i) - sys->vertexCos[i][1]);
}
if (flag & MOD_LAPLACIANSMOOTH_Z) {
- sys->vertexCos[i][2] = nlGetVariable(2, i);
+ sys->vertexCos[i][2] += lam * (nlGetVariable(2, i) - sys->vertexCos[i][2]);
}
}
}
@@ -578,17 +575,17 @@ static void laplaciansmoothModifier_do(
sys->vert_centroid[0] = 0.0f;
sys->vert_centroid[1] = 0.0f;
sys->vert_centroid[2] = 0.0f;
- for (iter = 0; iter < smd->repeat; iter++) {
- memset_laplacian_system(sys, 0);
- nlNewContext();
- sys->context = nlGetCurrent();
- nlSolverParameteri(NL_NB_VARIABLES, numVerts);
- nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
- nlSolverParameteri(NL_NB_ROWS, numVerts);
- nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 3);
+ memset_laplacian_system(sys, 0);
+ nlNewContext();
+ sys->context = nlGetCurrent();
+ nlSolverParameteri(NL_NB_VARIABLES, numVerts);
+ nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
+ nlSolverParameteri(NL_NB_ROWS, numVerts);
+ nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 3);
- init_laplacian_matrix(sys);
+ init_laplacian_matrix(sys);
+ for (iter = 0; iter < smd->repeat; iter++) {
nlBegin(NL_SYSTEM);
for (i = 0; i < numVerts; i++) {
nlSetVariable(0, i, vertexCos[i][0]);
@@ -605,46 +602,64 @@ static void laplaciansmoothModifier_do(
nlBegin(NL_MATRIX);
dv = dvert;
for (i = 0; i < numVerts; i++) {
- nlRightHandSideAdd(0, i, vertexCos[i][0]);
- nlRightHandSideAdd(1, i, vertexCos[i][1]);
- nlRightHandSideAdd(2, i, vertexCos[i][2]);
- if (dv) {
- wpaint = defvert_find_weight(dv, defgrp_index);
- dv++;
- }
- else {
- wpaint = 1.0f;
- }
-
- if (sys->zerola[i] == 0) {
- w = sys->vweights[i] * sys->ring_areas[i];
- sys->vweights[i] = (w == 0.0f) ? 0.0f : -smd->lambda * wpaint / (4.0f * w);
- w = sys->vlengths[i];
- sys->vlengths[i] = (w == 0.0f) ? 0.0f : -smd->lambda_border * wpaint * 2.0f / w;
+ nlRightHandSideSet(0, i, vertexCos[i][0]);
+ nlRightHandSideSet(1, i, vertexCos[i][1]);
+ nlRightHandSideSet(2, i, vertexCos[i][2]);
+ if (iter == 0) {
+ if (dv) {
+ wpaint = defvert_find_weight(dv, defgrp_index);
+ dv++;
+ }
+ else {
+ wpaint = 1.0f;
+ }
- if (sys->numNeEd[i] == sys->numNeFa[i]) {
- nlMatrixAdd(i, i, 1.0f + smd->lambda * wpaint / (4.0f * sys->ring_areas[i]));
+ if (sys->zerola[i] == 0) {
+ if (smd->flag & MOD_LAPLACIANSMOOTH_NORMALIZED) {
+ w = sys->vweights[i];
+ sys->vweights[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda) * wpaint / w;
+ w = sys->vlengths[i];
+ sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w;
+ if (sys->numNeEd[i] == sys->numNeFa[i]) {
+ nlMatrixAdd(i, i, 1.0f + fabsf(smd->lambda) * wpaint);
+ }
+ else {
+ nlMatrixAdd(i, i, 1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f);
+ }
+ }
+ else {
+ w = sys->vweights[i] * sys->ring_areas[i];
+ sys->vweights[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda) * wpaint / (4.0f * w);
+ w = sys->vlengths[i];
+ sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w;
+
+ if (sys->numNeEd[i] == sys->numNeFa[i]) {
+ nlMatrixAdd(i, i, 1.0f + fabsf(smd->lambda) * wpaint / (4.0f * sys->ring_areas[i]));
+ }
+ else {
+ nlMatrixAdd(i, i, 1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f);
+ }
+ }
}
else {
- nlMatrixAdd(i, i, 1.0f + smd->lambda_border * wpaint * 2.0f);
+ nlMatrixAdd(i, i, 1.0f);
}
}
- else {
- nlMatrixAdd(i, i, 1.0f);
- }
}
- fill_laplacian_matrix(sys);
+ if (iter == 0) {
+ fill_laplacian_matrix(sys);
+ }
nlEnd(NL_MATRIX);
nlEnd(NL_SYSTEM);
if (nlSolveAdvanced(NULL, NL_TRUE)) {
- validate_solution(sys, smd->flag);
+ validate_solution(sys, smd->flag, smd->lambda, smd->lambda_border);
}
- nlDeleteContext(sys->context);
- sys->context = NULL;
}
+ nlDeleteContext(sys->context);
+ sys->context = NULL;
delete_laplacian_system(sys);
}
diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c
index 23ce8cdeb21..b86802340dc 100644
--- a/source/blender/modifiers/intern/MOD_mask.c
+++ b/source/blender/modifiers/intern/MOD_mask.c
@@ -316,7 +316,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* using ghash-iterators, map data into new mesh */
/* vertices */
for (hashIter = BLI_ghashIterator_new(vertHash);
- !BLI_ghashIterator_isDone(hashIter);
+ BLI_ghashIterator_notDone(hashIter);
BLI_ghashIterator_step(hashIter) )
{
MVert source;
@@ -334,7 +334,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* edges */
for (hashIter = BLI_ghashIterator_new(edgeHash);
- !BLI_ghashIterator_isDone(hashIter);
+ BLI_ghashIterator_notDone(hashIter);
BLI_ghashIterator_step(hashIter))
{
MEdge source;
@@ -355,7 +355,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* faces */
for (hashIter = BLI_ghashIterator_new(polyHash);
- !BLI_ghashIterator_isDone(hashIter);
+ BLI_ghashIterator_notDone(hashIter);
BLI_ghashIterator_step(hashIter) )
{
int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c
new file mode 100644
index 00000000000..be7bfae22fb
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_meshcache.c
@@ -0,0 +1,344 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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/modifiers/intern/MOD_meshcache.c
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_string.h"
+#include "BLI_path_util.h"
+#include "BLI_math.h"
+
+#include "BKE_DerivedMesh.h"
+#include "BKE_scene.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_main.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "MOD_meshcache_util.h" /* utility functions */
+
+#include "MOD_modifiertypes.h"
+
+#include "MOD_util.h"
+
+static void initData(ModifierData *md)
+{
+ MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md;
+
+ mcmd->flag = 0;
+ mcmd->type = MOD_MESHCACHE_TYPE_MDD;
+ mcmd->interp = MOD_MESHCACHE_INTERP_LINEAR;
+ mcmd->frame_scale = 1.0f;
+
+ mcmd->factor = 1.0f;
+
+ /* (Y, Z). Blender default */
+ mcmd->forward_axis = 1;
+ mcmd->up_axis = 2;
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md;
+ MeshCacheModifierData *tmcmd = (MeshCacheModifierData *)target;
+
+ tmcmd->flag = mcmd->flag;
+ tmcmd->type = mcmd->type;
+
+ tmcmd->time_mode = mcmd->time_mode;
+ tmcmd->play_mode = mcmd->play_mode;
+
+ tmcmd->forward_axis = mcmd->forward_axis;
+ tmcmd->up_axis = mcmd->up_axis;
+ tmcmd->flip_axis = mcmd->flip_axis;
+
+ tmcmd->interp = mcmd->interp;
+
+ tmcmd->frame_start = mcmd->frame_start;
+ tmcmd->frame_scale = mcmd->frame_scale;
+
+ tmcmd->factor = mcmd->factor;
+ tmcmd->deform_mode = mcmd->deform_mode;
+
+ tmcmd->eval_frame = mcmd->eval_frame;
+ tmcmd->eval_time = mcmd->eval_time;
+ tmcmd->eval_factor = mcmd->eval_factor;
+
+ BLI_strncpy(tmcmd->filepath, mcmd->filepath, sizeof(tmcmd->filepath));
+}
+
+static int dependsOnTime(ModifierData *md)
+{
+ MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md;
+ return (mcmd->play_mode == MOD_MESHCACHE_PLAY_CFEA);
+}
+
+static int isDisabled(ModifierData *md, int UNUSED(useRenderParams))
+{
+ MeshCacheModifierData *mcmd = (MeshCacheModifierData *) md;
+
+ /* leave it up to the modifier to check the file is valid on calculation */
+ return (mcmd->factor <= 0.0f) || (mcmd->filepath[0] == '\0');
+}
+
+
+static void meshcache_do(
+ MeshCacheModifierData *mcmd, Object *ob, DerivedMesh *UNUSED(dm),
+ float (*vertexCos_Real)[3], int numVerts)
+{
+ const bool use_factor = mcmd->factor < 1.0f;
+ float (*vertexCos_Store)[3] = (use_factor || (mcmd->deform_mode == MOD_MESHCACHE_DEFORM_INTEGRATE)) ?
+ MEM_mallocN(sizeof(*vertexCos_Store) * numVerts, __func__) : NULL;
+ float (*vertexCos)[3] = vertexCos_Store ? vertexCos_Store : vertexCos_Real;
+
+ Scene *scene = mcmd->modifier.scene;
+ const float fps = FPS;
+
+ char filepath[FILE_MAX];
+ const char *err_str = NULL;
+ bool ok;
+
+ float time;
+
+
+ /* -------------------------------------------------------------------- */
+ /* Interpret Time (the reading functions also do some of this ) */
+ if (mcmd->play_mode == MOD_MESHCACHE_PLAY_CFEA) {
+ const float cfra = BKE_scene_frame_get(scene);
+
+ switch (mcmd->time_mode) {
+ case MOD_MESHCACHE_TIME_FRAME:
+ {
+ time = cfra;
+ break;
+ }
+ case MOD_MESHCACHE_TIME_SECONDS:
+ {
+ time = cfra / fps;
+ break;
+ }
+ case MOD_MESHCACHE_TIME_FACTOR:
+ default:
+ {
+ time = cfra / fps;
+ break;
+ }
+ }
+
+ /* apply offset and scale */
+ time = (mcmd->frame_scale * time) - mcmd->frame_start;
+ }
+ else { /* if (mcmd->play_mode == MOD_MESHCACHE_PLAY_EVAL) { */
+ switch (mcmd->time_mode) {
+ case MOD_MESHCACHE_TIME_FRAME:
+ {
+ time = mcmd->eval_frame;
+ break;
+ }
+ case MOD_MESHCACHE_TIME_SECONDS:
+ {
+ time = mcmd->eval_time;
+ break;
+ }
+ case MOD_MESHCACHE_TIME_FACTOR:
+ default:
+ {
+ time = mcmd->eval_factor;
+ break;
+ }
+ }
+ }
+
+
+ /* -------------------------------------------------------------------- */
+ /* Read the File (or error out when the file is bad) */
+
+ /* would be nice if we could avoid doing this _every_ frame */
+ BLI_strncpy(filepath, mcmd->filepath, sizeof(filepath));
+ BLI_path_abs(filepath, ID_BLEND_PATH(G.main, (ID *)ob));
+
+ switch (mcmd->type) {
+ case MOD_MESHCACHE_TYPE_MDD:
+ ok = MOD_meshcache_read_mdd_times(filepath, vertexCos, numVerts,
+ mcmd->interp, time, fps, mcmd->time_mode, &err_str);
+ break;
+ case MOD_MESHCACHE_TYPE_PC2:
+ ok = MOD_meshcache_read_pc2_times(filepath, vertexCos, numVerts,
+ mcmd->interp, time, fps, mcmd->time_mode, &err_str);
+ break;
+ default:
+ ok = false;
+ break;
+ }
+
+
+ /* -------------------------------------------------------------------- */
+ /* tricky shape key integration (slow!) */
+ if (mcmd->deform_mode == MOD_MESHCACHE_DEFORM_INTEGRATE) {
+ Mesh *me = ob->data;
+
+ /* we could support any object type */
+ if (UNLIKELY(ob->type != OB_MESH)) {
+ modifier_setError(&mcmd->modifier, "'Integrate' only valid for Mesh objects");
+ }
+ else if (UNLIKELY(me->totvert != numVerts)) {
+ modifier_setError(&mcmd->modifier, "'Integrate' original mesh vertex mismatch");
+ }
+ else if (UNLIKELY(me->totpoly == 0)) {
+ modifier_setError(&mcmd->modifier, "'Integrate' requires faces");
+ }
+ else {
+ /* the moons align! */
+ int i;
+
+ float (*vertexCos_Source)[3] = MEM_mallocN(sizeof(*vertexCos_Source) * numVerts, __func__);
+ float (*vertexCos_New)[3] = MEM_mallocN(sizeof(*vertexCos_New) * numVerts, __func__);
+ MVert *mv = me->mvert;
+
+ for (i = 0; i < numVerts; i++, mv++) {
+ copy_v3_v3(vertexCos_Source[i], mv->co);
+ }
+
+ BKE_mesh_calc_relative_deform(
+ me->mpoly, me->totpoly,
+ me->mloop, me->totvert,
+
+ (const float (*)[3])vertexCos_Source, /* from the original Mesh*/
+ (const float (*)[3])vertexCos_Real, /* the input we've been given (shape keys!) */
+
+ (const float (*)[3])vertexCos, /* the result of this modifier */
+ vertexCos_New /* the result of this function */
+ );
+
+ /* write the corrected locations back into the result */
+ memcpy(vertexCos, vertexCos_New, sizeof(*vertexCos) * numVerts);
+
+ MEM_freeN(vertexCos_Source);
+ MEM_freeN(vertexCos_New);
+ }
+ }
+
+
+ /* -------------------------------------------------------------------- */
+ /* Apply the transformation matrix (if needed) */
+ if (UNLIKELY(err_str)) {
+ modifier_setError(&mcmd->modifier, "%s", err_str);
+ }
+ else if (ok) {
+ bool use_matrix = false;
+ float mat[3][3];
+ unit_m3(mat);
+
+ if (mat3_from_axis_conversion(mcmd->forward_axis, mcmd->up_axis, 1, 2, mat)) {
+ use_matrix = true;
+ }
+
+ if (mcmd->flip_axis) {
+ float tmat[3][3];
+ unit_m3(tmat);
+ if (mcmd->flip_axis & (1 << 0)) tmat[0][0] = -1.0f;
+ if (mcmd->flip_axis & (1 << 1)) tmat[1][1] = -1.0f;
+ if (mcmd->flip_axis & (1 << 2)) tmat[2][2] = -1.0f;
+ mul_m3_m3m3(mat, tmat, mat);
+
+ use_matrix = true;
+ }
+
+ if (use_matrix) {
+ int i;
+ for (i = 0; i < numVerts; i++) {
+ mul_m3_v3(mat, vertexCos[i]);
+ }
+ }
+ }
+
+ if (vertexCos_Store) {
+ if (ok) {
+ if (use_factor) {
+ interp_vn_vn(*vertexCos_Real, *vertexCos_Store, mcmd->factor, numVerts * 3);
+ }
+ else {
+ memcpy(vertexCos_Real, vertexCos_Store, sizeof(*vertexCos_Store) * numVerts);
+ }
+ }
+
+ MEM_freeN(vertexCos_Store);
+ }
+}
+
+static void deformVerts(ModifierData *md, Object *ob,
+ DerivedMesh *derivedData,
+ float (*vertexCos)[3],
+ int numVerts,
+ ModifierApplyFlag UNUSED(flag))
+{
+ MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md;
+
+ meshcache_do(mcmd, ob, derivedData, vertexCos, numVerts);
+}
+
+static void deformVertsEM(
+ ModifierData *md, Object *ob, struct BMEditMesh *UNUSED(editData),
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+ MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md;
+
+ meshcache_do(mcmd, ob, derivedData, vertexCos, numVerts);
+}
+
+
+ModifierTypeInfo modifierType_MeshCache = {
+ /* name */ "Mesh Cache",
+ /* structName */ "MeshCacheModifierData",
+ /* structSize */ sizeof(MeshCacheModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsCVs |
+ eModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ deformVerts,
+ /* deformMatrices */ NULL,
+ /* deformVertsEM */ deformVertsEM,
+ /* deformMatricesEM */ NULL,
+ /* applyModifier */ NULL,
+ /* applyModifierEM */ NULL,
+ /* initData */ initData,
+ /* requiredDataMask */ NULL,
+ /* freeData */ NULL,
+ /* isDisabled */ isDisabled,
+ /* updateDepgraph */ NULL,
+ /* dependsOnTime */ dependsOnTime,
+ /* dependsOnNormals */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/modifiers/intern/MOD_meshcache_mdd.c b/source/blender/modifiers/intern/MOD_meshcache_mdd.c
new file mode 100644
index 00000000000..e001855ba0b
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_meshcache_mdd.c
@@ -0,0 +1,301 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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, pkowal
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/modifiers/intern/MOD_meshcache_mdd.c
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "BLO_sys_types.h"
+#include "BLI_utildefines.h"
+#include "BLI_endian_switch.h"
+#include "BLI_fileops.h"
+#include "BLI_math.h"
+
+#include "MOD_meshcache_util.h" /* own include */
+
+#include "DNA_modifier_types.h"
+
+typedef struct MDDHead {
+ int frame_tot;
+ int verts_tot;
+} MDDHead; /* frames, verts */
+
+static bool meshcache_read_mdd_head(FILE *fp, const int verts_tot,
+ MDDHead *mdd_head,
+ const char **err_str)
+{
+ if (!fread(mdd_head, sizeof(*mdd_head), 1, fp)) {
+ *err_str = "Missing header";
+ return false;
+ }
+
+#ifdef __LITTLE_ENDIAN__
+ BLI_endian_switch_int32_array((int *)mdd_head, 2);
+#endif
+
+ if (mdd_head->verts_tot != verts_tot) {
+ *err_str = "Vertex count mismatch";
+ return false;
+ }
+
+ if (mdd_head->frame_tot <= 0) {
+ *err_str = "Invalid frame total";
+ return false;
+ }
+ /* intentionally dont seek back */
+
+ return true;
+}
+
+/**
+ * Gets the index frange and factor
+ */
+static bool meshcache_read_mdd_range(FILE *fp,
+ const int verts_tot,
+ const float frame, const char interp,
+ int r_index_range[2], float *r_factor,
+ const char **err_str)
+{
+ MDDHead mdd_head;
+
+ /* first check interpolation and get the vert locations */
+
+ if (meshcache_read_mdd_head(fp, verts_tot, &mdd_head, err_str) == false) {
+ return false;
+ }
+
+ MOD_meshcache_calc_range(frame, interp, mdd_head.frame_tot, r_index_range, r_factor);
+
+ return true;
+}
+
+static bool meshcache_read_mdd_range_from_time(FILE *fp,
+ const int verts_tot,
+ const float time, const float UNUSED(fps),
+ float *r_frame,
+ const char **err_str)
+{
+ MDDHead mdd_head;
+ int i;
+ float f_time, f_time_prev = FLT_MAX;
+ float frame;
+
+ if (meshcache_read_mdd_head(fp, verts_tot, &mdd_head, err_str) == false) {
+ return false;
+ }
+
+ for (i = 0; i < mdd_head.frame_tot; i++) {
+ fread(&f_time, sizeof(float), 1, fp);
+#ifdef __LITTLE_ENDIAN__
+ BLI_endian_switch_float(&f_time);
+#endif
+ if (f_time >= time) {
+ break;
+ }
+ f_time_prev = f_time;
+ }
+
+ if (i == mdd_head.frame_tot) {
+ frame = (float)(mdd_head.frame_tot - 1);
+ }
+ if (UNLIKELY(f_time_prev == FLT_MAX)) {
+ frame = 0.0f;
+ }
+ else {
+ const float range = f_time - f_time_prev;
+
+ if (range <= FRAME_SNAP_EPS) {
+ frame = (float)i;
+ }
+ else {
+ frame = (float)(i - 1) + ((time - f_time_prev) / range);
+ }
+ }
+
+ *r_frame = frame;
+ return true;
+}
+
+bool MOD_meshcache_read_mdd_index(FILE *fp,
+ float (*vertexCos)[3], const int verts_tot,
+ const int index, const float factor,
+ const char **err_str)
+{
+ MDDHead mdd_head;
+
+ if (meshcache_read_mdd_head(fp, verts_tot, &mdd_head, err_str) == false) {
+ return false;
+ }
+
+ if (fseek(fp, mdd_head.frame_tot * sizeof(int), SEEK_CUR) != 0) {
+ *err_str = "Header seek failed";
+ return false;
+ }
+
+ if (fseek(fp, index * mdd_head.verts_tot * sizeof(float) * 3, SEEK_CUR) != 0) {
+ *err_str = "Failed to seek frame";
+ return false;
+ }
+
+ if (factor >= 1.0f) {
+#if 1
+ float *vco = *vertexCos;
+ unsigned int i;
+ for (i = mdd_head.verts_tot; i != 0 ; i--, vco += 3) {
+ fread(vco, sizeof(float) * 3, 1, fp);
+
+# ifdef __LITTLE_ENDIAN__
+ BLI_endian_switch_float(vco + 0);
+ BLI_endian_switch_float(vco + 1);
+ BLI_endian_switch_float(vco + 2);
+# endif /* __LITTLE_ENDIAN__ */
+ }
+#else
+ /* no blending */
+ if (!fread(vertexCos, sizeof(float) * 3, mdd_head.verts_tot, f)) {
+ *err_str = errno ? strerror(errno) : "Failed to read frame";
+ return false;
+ }
+# ifdef __LITTLE_ENDIAN__
+ BLI_endian_switch_float_array(vertexCos[0], mdd_head.verts_tot * 3);
+# endif
+#endif
+ }
+ else {
+ const float ifactor = 1.0f - factor;
+ float *vco = *vertexCos;
+ unsigned int i;
+ for (i = mdd_head.verts_tot; i != 0 ; i--, vco += 3) {
+ float tvec[3];
+ fread(tvec, sizeof(float) * 3, 1, fp);
+
+#ifdef __LITTLE_ENDIAN__
+ BLI_endian_switch_float(tvec + 0);
+ BLI_endian_switch_float(tvec + 1);
+ BLI_endian_switch_float(tvec + 2);
+#endif
+
+ vco[0] = (vco[0] * ifactor) + (tvec[0] * factor);
+ vco[1] = (vco[1] * ifactor) + (tvec[1] * factor);
+ vco[2] = (vco[2] * ifactor) + (tvec[2] * factor);
+ }
+ }
+
+ return true;
+}
+
+bool MOD_meshcache_read_mdd_frame(FILE *fp,
+ float (*vertexCos)[3], const int verts_tot, const char interp,
+ const float frame,
+ const char **err_str)
+{
+ int index_range[2];
+ float factor;
+
+ if (meshcache_read_mdd_range(fp, verts_tot, frame, interp,
+ index_range, &factor, /* read into these values */
+ err_str) == false)
+ {
+ return false;
+ }
+
+ if (index_range[0] == index_range[1]) {
+ /* read single */
+ if ((fseek(fp, 0, SEEK_SET) == 0) &&
+ MOD_meshcache_read_mdd_index(fp, vertexCos, verts_tot, index_range[0], 1.0f, err_str))
+ {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ else {
+ /* read both and interpolate */
+ if ((fseek(fp, 0, SEEK_SET) == 0) &&
+ MOD_meshcache_read_mdd_index(fp, vertexCos, verts_tot, index_range[0], 1.0f, err_str) &&
+ (fseek(fp, 0, SEEK_SET) == 0) &&
+ MOD_meshcache_read_mdd_index(fp, vertexCos, verts_tot, index_range[1], factor, err_str))
+ {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+}
+
+bool MOD_meshcache_read_mdd_times(const char *filepath,
+ float (*vertexCos)[3], const int verts_tot, const char interp,
+ const float time, const float fps, const char time_mode,
+ const char **err_str)
+{
+ float frame;
+
+ FILE *fp = BLI_fopen(filepath, "rb");
+ bool ok;
+
+ if (fp == NULL) {
+ *err_str = errno ? strerror(errno) : "Unknown error opening file";
+ return false;
+ }
+
+ switch (time_mode) {
+ case MOD_MESHCACHE_TIME_FRAME:
+ {
+ frame = time;
+ break;
+ }
+ case MOD_MESHCACHE_TIME_SECONDS:
+ {
+ /* we need to find the closest time */
+ if (meshcache_read_mdd_range_from_time(fp, verts_tot, time, fps, &frame, err_str) == false) {
+ fclose(fp);
+ return false;
+ }
+ rewind(fp);
+ break;
+ }
+ case MOD_MESHCACHE_TIME_FACTOR:
+ default:
+ {
+ MDDHead mdd_head;
+ if (meshcache_read_mdd_head(fp, verts_tot, &mdd_head, err_str) == false) {
+ fclose(fp);
+ return false;
+ }
+
+ frame = CLAMPIS(time, 0.0f, 1.0f) * (float)mdd_head.frame_tot;
+ rewind(fp);
+ break;
+ }
+ }
+
+ ok = MOD_meshcache_read_mdd_frame(fp, vertexCos, verts_tot, interp, frame, err_str);
+
+ fclose(fp);
+ return ok;
+}
diff --git a/source/blender/modifiers/intern/MOD_meshcache_pc2.c b/source/blender/modifiers/intern/MOD_meshcache_pc2.c
new file mode 100644
index 00000000000..b20f62a8e77
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_meshcache_pc2.c
@@ -0,0 +1,277 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/modifiers/intern/MOD_meshcache_pc2.c
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "BLO_sys_types.h"
+#include "BLI_utildefines.h"
+#include "BLI_endian_switch.h"
+#include "BLI_fileops.h"
+#include "BLI_math.h"
+
+#include "MOD_meshcache_util.h" /* own include */
+
+#include "DNA_modifier_types.h"
+
+typedef struct PC2Head {
+ char header[12]; /* 'POINTCACHE2\0' */
+ int file_version; /* unused - should be 1 */
+ int verts_tot;
+ float start;
+ float sampling;
+ int frame_tot;
+} PC2Head; /* frames, verts */
+
+static bool meshcache_read_pc2_head(FILE *fp, const int verts_tot,
+ PC2Head *pc2_head,
+ const char **err_str)
+{
+ if (!fread(pc2_head, sizeof(*pc2_head), 1, fp)) {
+ *err_str = "Missing header";
+ return false;
+ }
+
+ if (strcmp(pc2_head->header, "POINTCACHE2") != 0) {
+ *err_str = "Invalid header";
+ return false;
+ }
+
+#ifdef __BIG_ENDIAN__
+ BLI_endian_switch_int32_array(&pc2_head->file_version, (sizeof(*pc2_head) - sizeof(pc2_head->header)) / sizeof(int));
+#endif
+
+ if (pc2_head->verts_tot != verts_tot) {
+ *err_str = "Vertex count mismatch";
+ return false;
+ }
+
+ if (pc2_head->frame_tot <= 0) {
+ *err_str = "Invalid frame total";
+ return false;
+ }
+ /* intentionally dont seek back */
+
+ return true;
+}
+
+
+/**
+ * Gets the index frange and factor
+ *
+ * currently same as for MDD
+ */
+static bool meshcache_read_pc2_range(FILE *fp,
+ const int verts_tot,
+ const float frame, const char interp,
+ int r_index_range[2], float *r_factor,
+ const char **err_str)
+{
+ PC2Head pc2_head;
+
+ /* first check interpolation and get the vert locations */
+
+ if (meshcache_read_pc2_head(fp, verts_tot, &pc2_head, err_str) == false) {
+ return false;
+ }
+
+ MOD_meshcache_calc_range(frame, interp, pc2_head.frame_tot, r_index_range, r_factor);
+
+ return true;
+}
+
+static bool meshcache_read_pc2_range_from_time(FILE *fp,
+ const int verts_tot,
+ const float time, const float fps,
+ float *r_frame,
+ const char **err_str)
+{
+ PC2Head pc2_head;
+ float frame;
+
+ if (meshcache_read_pc2_head(fp, verts_tot, &pc2_head, err_str) == false) {
+ return false;
+ }
+
+ frame = ((time / fps) - pc2_head.start) / pc2_head.sampling;
+
+ if (frame >= pc2_head.frame_tot) {
+ frame = (float)(pc2_head.frame_tot - 1);
+ }
+ else if (frame < 0.0f) {
+ frame = 0.0f;
+ }
+
+ *r_frame = frame;
+ return true;
+}
+
+bool MOD_meshcache_read_pc2_index(FILE *fp,
+ float (*vertexCos)[3], const int verts_tot,
+ const int index, const float factor,
+ const char **err_str)
+{
+ PC2Head pc2_head;
+
+ if (meshcache_read_pc2_head(fp, verts_tot, &pc2_head, err_str) == false) {
+ return false;
+ }
+
+ if (fseek(fp, index * pc2_head.verts_tot * sizeof(float) * 3, SEEK_CUR) != 0) {
+ *err_str = "Failed to seek frame";
+ return false;
+ }
+
+ if (factor >= 1.0f) {
+ float *vco = *vertexCos;
+ unsigned int i;
+ for (i = pc2_head.verts_tot; i != 0 ; i--, vco += 3) {
+ fread(vco, sizeof(float) * 3, 1, fp);
+
+# ifdef __BIG_ENDIAN__
+ BLI_endian_switch_float(vco + 0);
+ BLI_endian_switch_float(vco + 1);
+ BLI_endian_switch_float(vco + 2);
+# endif /* __BIG_ENDIAN__ */
+ }
+ }
+ else {
+ const float ifactor = 1.0f - factor;
+ float *vco = *vertexCos;
+ unsigned int i;
+ for (i = pc2_head.verts_tot; i != 0 ; i--, vco += 3) {
+ float tvec[3];
+ fread(tvec, sizeof(float) * 3, 1, fp);
+
+#ifdef __BIG_ENDIAN__
+ BLI_endian_switch_float(tvec + 0);
+ BLI_endian_switch_float(tvec + 1);
+ BLI_endian_switch_float(tvec + 2);
+#endif /* __BIG_ENDIAN__ */
+
+ vco[0] = (vco[0] * ifactor) + (tvec[0] * factor);
+ vco[1] = (vco[1] * ifactor) + (tvec[1] * factor);
+ vco[2] = (vco[2] * ifactor) + (tvec[2] * factor);
+ }
+ }
+
+ return true;
+}
+
+
+bool MOD_meshcache_read_pc2_frame(FILE *fp,
+ float (*vertexCos)[3], const int verts_tot, const char interp,
+ const float frame,
+ const char **err_str)
+{
+ int index_range[2];
+ float factor;
+
+ if (meshcache_read_pc2_range(fp, verts_tot, frame, interp,
+ index_range, &factor, /* read into these values */
+ err_str) == false)
+ {
+ return false;
+ }
+
+ if (index_range[0] == index_range[1]) {
+ /* read single */
+ if ((fseek(fp, 0, SEEK_SET) == 0) &&
+ MOD_meshcache_read_pc2_index(fp, vertexCos, verts_tot, index_range[0], 1.0f, err_str))
+ {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ else {
+ /* read both and interpolate */
+ if ((fseek(fp, 0, SEEK_SET) == 0) &&
+ MOD_meshcache_read_pc2_index(fp, vertexCos, verts_tot, index_range[0], 1.0f, err_str) &&
+ (fseek(fp, 0, SEEK_SET) == 0) &&
+ MOD_meshcache_read_pc2_index(fp, vertexCos, verts_tot, index_range[1], factor, err_str))
+ {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+}
+
+bool MOD_meshcache_read_pc2_times(const char *filepath,
+ float (*vertexCos)[3], const int verts_tot, const char interp,
+ const float time, const float fps, const char time_mode,
+ const char **err_str)
+{
+ float frame;
+
+ FILE *fp = BLI_fopen(filepath, "rb");
+ bool ok;
+
+ if (fp == NULL) {
+ *err_str = errno ? strerror(errno) : "Unknown error opening file";
+ return false;
+ }
+
+ switch (time_mode) {
+ case MOD_MESHCACHE_TIME_FRAME:
+ {
+ frame = time;
+ break;
+ }
+ case MOD_MESHCACHE_TIME_SECONDS:
+ {
+ /* we need to find the closest time */
+ if (meshcache_read_pc2_range_from_time(fp, verts_tot, time, fps, &frame, err_str) == false) {
+ fclose(fp);
+ return false;
+ }
+ rewind(fp);
+ break;
+ }
+ case MOD_MESHCACHE_TIME_FACTOR:
+ default:
+ {
+ PC2Head pc2_head;
+ if (meshcache_read_pc2_head(fp, verts_tot, &pc2_head, err_str) == false) {
+ fclose(fp);
+ return false;
+ }
+
+ frame = CLAMPIS(time, 0.0f, 1.0f) * (float)pc2_head.frame_tot;
+ rewind(fp);
+ break;
+ }
+ }
+
+ ok = MOD_meshcache_read_pc2_frame(fp, vertexCos, verts_tot, interp, frame, err_str);
+
+ fclose(fp);
+ return ok;
+}
diff --git a/source/blender/modifiers/intern/MOD_meshcache_util.c b/source/blender/modifiers/intern/MOD_meshcache_util.c
new file mode 100644
index 00000000000..679a79322c3
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_meshcache_util.c
@@ -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.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "MOD_meshcache_util.h"
+
+void MOD_meshcache_calc_range(const float frame, const char interp,
+ const int frame_tot,
+ int r_index_range[2], float *r_factor)
+{
+ if (interp == MOD_MESHCACHE_INTERP_NONE) {
+ r_index_range[0] = r_index_range[1] = max_ii(0, min_ii(frame_tot - 1, (int)(floorf(frame) + 0.5f)));
+ *r_factor = 1.0f; /* dummy */
+ }
+ else {
+ const float tframe = floorf(frame);
+ const float range = frame - tframe;
+ r_index_range[0] = (int)tframe;
+ if (range <= FRAME_SNAP_EPS) {
+ /* we're close enough not to need blending */
+ r_index_range[1] = r_index_range[0];
+ *r_factor = 1.0f; /* dummy */
+ }
+ else {
+ /* blend between 2 frames */
+ r_index_range[1] = r_index_range[0] + 1;
+ *r_factor = range;
+ }
+
+ /* clamp */
+ if ((r_index_range[0] >= frame_tot) ||
+ (r_index_range[1] >= frame_tot))
+ {
+ r_index_range[0] = r_index_range[1] = frame_tot - 1;
+ *r_factor = 1.0f; /* dummy */
+ }
+ else if ((r_index_range[0] < 0) ||
+ (r_index_range[1] < 0))
+ {
+ r_index_range[0] = r_index_range[1] = 0;
+ *r_factor = 1.0f; /* dummy */
+ }
+ }
+}
diff --git a/source/blender/modifiers/intern/MOD_meshcache_util.h b/source/blender/modifiers/intern/MOD_meshcache_util.h
new file mode 100644
index 00000000000..d7e71518f77
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_meshcache_util.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.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/modifiers/intern/MOD_meshcache_util.h
+ * \ingroup modifiers
+ */
+
+#ifndef __MOD_MESHCACHE_UTIL_H__
+
+struct MPoly;
+struct MLoop;
+
+/* MOD_meshcache_mdd.c */
+bool MOD_meshcache_read_mdd_index(FILE *fp,
+ float (*vertexCos)[3], const int vertex_tot,
+ const int index, const float factor,
+ const char **err_str);
+bool MOD_meshcache_read_mdd_frame(FILE *fp,
+ float (*vertexCos)[3], const int verts_tot, const char interp,
+ const float frame,
+ const char **err_str);
+bool MOD_meshcache_read_mdd_times(const char *filepath,
+ float (*vertexCos)[3], const int verts_tot, const char interp,
+ const float time, const float fps, const char time_mode,
+ const char **err_str);
+
+/* MOD_meshcache_pc2.c */
+bool MOD_meshcache_read_pc2_index(FILE *fp,
+ float (*vertexCos)[3], const int verts_tot,
+ const int index, const float factor,
+ const char **err_str);
+bool MOD_meshcache_read_pc2_frame(FILE *fp,
+ float (*vertexCos)[3], const int verts_tot, const char interp,
+ const float frame,
+ const char **err_str);
+bool MOD_meshcache_read_pc2_times(const char *filepath,
+ float (*vertexCos)[3], const int verts_tot, const char interp,
+ const float time, const float fps, const char time_mode,
+ const char **err_str);
+
+/* MOD_meshcache_util.c */
+void MOD_meshcache_calc_range(const float frame, const char interp,
+ const int frame_tot,
+ int r_index_range[2], float *r_factor);
+
+#define FRAME_SNAP_EPS 0.0001f
+
+#endif /* __MOD_MESHCACHE_UTIL_H__ */
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index 83c678db7b3..2b29f2afb9a 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -111,7 +111,7 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
MLoop *ml;
MPoly *mp;
float mtx[4][4];
- int i, j;
+ int i;
int a, totshape;
int *vtargetmap = NULL, *vtmap_a = NULL, *vtmap_b = NULL;
@@ -221,7 +221,7 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
ml = CDDM_get_loops(result);
for (i = 0; i < maxPolys; i++, mp++) {
MLoop *ml2;
- int e;
+ int j, e;
/* reverse the loop, but we keep the first vertex in the face the same,
* to ensure that quads are split the same way as on the other side */
@@ -249,8 +249,8 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
/* handle uvs,
* let tessface recalc handle updating the MTFace data */
if (mmd->flag & (MOD_MIR_MIRROR_U | MOD_MIR_MIRROR_V)) {
- const int do_mirr_u = (mmd->flag & MOD_MIR_MIRROR_U) != 0;
- const int do_mirr_v = (mmd->flag & MOD_MIR_MIRROR_V) != 0;
+ const bool do_mirr_u = (mmd->flag & MOD_MIR_MIRROR_U) != 0;
+ const bool do_mirr_v = (mmd->flag & MOD_MIR_MIRROR_V) != 0;
const int totuv = CustomData_number_of_layers(&result->loopData, CD_MLOOPUV);
diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c
index 564fa696c2a..338771f7746 100644
--- a/source/blender/modifiers/intern/MOD_ocean.c
+++ b/source/blender/modifiers/intern/MOD_ocean.c
@@ -1,4 +1,4 @@
-/**
+/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -25,6 +25,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/modifiers/intern/MOD_ocean.c
+ * \ingroup modifiers
+ */
+
#include "MEM_guardedalloc.h"
#include "DNA_customdata_types.h"
@@ -139,10 +143,10 @@ static void initData(ModifierData *md)
omd->ocean = BKE_add_ocean();
init_ocean_modifier(omd);
simulate_ocean_modifier(omd);
-#else // WITH_OCEANSIM
+#else /* WITH_OCEANSIM */
/* unused */
(void)md;
-#endif // WITH_OCEANSIM
+#endif /* WITH_OCEANSIM */
}
static void freeData(ModifierData *md)
@@ -153,10 +157,10 @@ static void freeData(ModifierData *md)
BKE_free_ocean(omd->ocean);
if (omd->oceancache)
BKE_free_ocean_cache(omd->oceancache);
-#else // WITH_OCEANSIM
+#else /* WITH_OCEANSIM */
/* unused */
(void)md;
-#endif // WITH_OCEANSIM
+#endif /* WITH_OCEANSIM */
}
static void copyData(ModifierData *md, ModifierData *target)
@@ -165,6 +169,7 @@ static void copyData(ModifierData *md, ModifierData *target)
OceanModifierData *omd = (OceanModifierData *) md;
OceanModifierData *tomd = (OceanModifierData *) target;
+ tomd->geometry_mode = omd->geometry_mode;
tomd->resolution = omd->resolution;
tomd->spatial_size = omd->spatial_size;
@@ -187,7 +192,6 @@ static void copyData(ModifierData *md, ModifierData *target)
tomd->refresh = 0;
-
tomd->size = omd->size;
tomd->repeat_x = omd->repeat_x;
tomd->repeat_y = omd->repeat_y;
@@ -201,11 +205,11 @@ static void copyData(ModifierData *md, ModifierData *target)
tomd->ocean = BKE_add_ocean();
init_ocean_modifier(tomd);
simulate_ocean_modifier(tomd);
-#else // WITH_OCEANSIM
+#else /* WITH_OCEANSIM */
/* unused */
(void)md;
(void)target;
-#endif // WITH_OCEANSIM
+#endif /* WITH_OCEANSIM */
}
#ifdef WITH_OCEANSIM
@@ -219,14 +223,14 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
return dataMask;
}
-#else // WITH_OCEANSIM
+#else /* WITH_OCEANSIM */
static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
{
/* unused */
(void)md;
return 0;
}
-#endif // WITH_OCEANSIM
+#endif /* WITH_OCEANSIM */
#if 0
static void dm_get_bounds(DerivedMesh *dm, float *sx, float *sy, float *ox, float *oy)
@@ -302,11 +306,7 @@ static DerivedMesh *generate_ocean_geometry(OceanModifierData *omd)
mpolys = CDDM_get_polys(result);
mloops = CDDM_get_loops(result);
-#if 0 // trunk
- origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
-#else // bmesh
origindex = CustomData_get_layer(&result->polyData, CD_ORIGINDEX);
-#endif
/* create vertices */
#pragma omp parallel for private(x, y) if (rx > OMP_MIN_RES)
@@ -443,7 +443,7 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob,
cfra = md->scene->r.cfra;
CLAMP(cfra, omd->bakestart, omd->bakeend);
- cfra -= omd->bakestart; // shift to 0 based
+ cfra -= omd->bakestart; /* shift to 0 based */
num_verts = dm->getNumVerts(dm);
num_faces = dm->getNumPolys(dm);
@@ -490,7 +490,8 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob,
mlcol = &mloopcols[mp->loopstart + j];
mlcol->r = mlcol->g = mlcol->b = (char)(foam * 255);
- /* mc->a = 255; */ /* no need to set */
+ /* This needs to be set (render engine uses) */
+ mlcol->a = 255;
} while (j--);
}
}
@@ -500,7 +501,7 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob,
/* displace the geometry */
- //#pragma omp parallel for private(i, ocr) if (omd->resolution > OMP_MIN_RES)
+ /* #pragma omp parallel for private(i, ocr) if (omd->resolution > OMP_MIN_RES) */
for (i = 0, mv = mverts; i < num_verts; i++, mv++) {
const float u = OCEAN_CO(size_co_inv, mv->co[0]);
const float v = OCEAN_CO(size_co_inv, mv->co[1]);
@@ -522,7 +523,7 @@ static DerivedMesh *doOcean(ModifierData *md, Object *ob,
return dm;
}
-#else // WITH_OCEANSIM
+#else /* WITH_OCEANSIM */
static DerivedMesh *doOcean(ModifierData *md, Object *UNUSED(ob),
DerivedMesh *derivedData,
int UNUSED(useRenderParams))
@@ -531,7 +532,7 @@ static DerivedMesh *doOcean(ModifierData *md, Object *UNUSED(ob),
(void)md;
return derivedData;
}
-#endif // WITH_OCEANSIM
+#endif /* WITH_OCEANSIM */
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
DerivedMesh *derivedData,
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index 4984682455a..63dcb5d942d 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -209,7 +209,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
if (psys == NULL || psys->totpart == 0)
return derivedData;
}
- else return derivedData;
+ else {
+ return derivedData;
+ }
if (pimd->flag & eParticleInstanceFlag_Parents)
totpart += psys->totpart;
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index 93b5e36e5a4..e7d62452590 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -225,7 +225,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
/* angle */
-#if 0 // cant incluide this, not predictable enough, though quite fun,.
+#if 0 /* cant incluide this, not predictable enough, though quite fun. */
if (ltmd->flag & MOD_SCREW_OBJECT_ANGLE) {
float mtx3_tx[3][3];
copy_m3_m4(mtx3_tx, mtx_tx);
@@ -274,7 +274,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1);
/* will the screw be closed?
- * Note! smaller then FLT_EPSILON*100 gives problems with float precision so its never closed. */
+ * Note! smaller then FLT_EPSILON * 100 gives problems with float precision so its never closed. */
if (fabsf(screw_ofs) <= (FLT_EPSILON * 100.0f) &&
fabsf(fabsf(angle) - ((float)M_PI * 2.0f)) <= (FLT_EPSILON * 100.0f))
{
@@ -314,11 +314,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
CustomData_add_layer(&result->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, maxPolys);
}
-#if 0 // trunk
- origindex = result->getPolyDataArray(result, CD_ORIGINDEX);
-#else // bmesh
origindex = CustomData_get_layer(&result->polyData, CD_ORIGINDEX);
-#endif
DM_copy_vert_data(dm, result, 0, 0, totvert); /* copy first otherwise this overwrites our own vertex normals */
diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c
index 7fe8dc69790..697ccdc49a4 100644
--- a/source/blender/modifiers/intern/MOD_shapekey.c
+++ b/source/blender/modifiers/intern/MOD_shapekey.c
@@ -54,13 +54,16 @@ static void deformVerts(ModifierData *md, Object *ob,
int numVerts,
ModifierApplyFlag UNUSED(flag))
{
- KeyBlock *kb = BKE_keyblock_from_object(ob);
+ Key *key = BKE_key_from_object(ob);
float (*deformedVerts)[3];
- if (kb && kb->totelem == numVerts) {
- deformedVerts = (float(*)[3])do_ob_key(md->scene, ob);
+ if (key && key->block.first) {
+ int deformedVerts_tot;
+ deformedVerts = (float(*)[3])BKE_key_evaluate_object(md->scene, ob, &deformedVerts_tot);
if (deformedVerts) {
- memcpy(vertexCos, deformedVerts, sizeof(float) * 3 * numVerts);
+ if (numVerts == deformedVerts_tot) {
+ memcpy(vertexCos, deformedVerts, sizeof(float) * 3 * numVerts);
+ }
MEM_freeN(deformedVerts);
}
}
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index d3a03614d7c..7a55f9a5b48 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -161,6 +161,15 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "Shrinkwrap Modifier");
}
+static int dependsOnNormals(ModifierData *md)
+{
+ ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
+
+ if (smd->target && smd->shrinkType == MOD_SHRINKWRAP_PROJECT)
+ return (smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL);
+
+ return false;
+}
ModifierTypeInfo modifierType_Shrinkwrap = {
/* name */ "Shrinkwrap",
@@ -185,7 +194,7 @@ ModifierTypeInfo modifierType_Shrinkwrap = {
/* isDisabled */ isDisabled,
/* updateDepgraph */ updateDepgraph,
/* dependsOnTime */ NULL,
- /* dependsOnNormals */ NULL,
+ /* dependsOnNormals */ dependsOnNormals,
/* foreachObjectLink */ foreachObjectLink,
/* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c
index a73d52a0a63..fbd2d3f1200 100644
--- a/source/blender/modifiers/intern/MOD_skin.c
+++ b/source/blender/modifiers/intern/MOD_skin.c
@@ -869,7 +869,7 @@ static DerivedMesh *subdivide_base(DerivedMesh *orig)
if (vg) {
vg->def_nr = dv1->dw[j].def_nr;
vg->w1 = dv1->dw[j].weight;
- vg->w1 = dv2->dw[k].weight;
+ vg->w2 = dv2->dw[k].weight;
}
}
}
@@ -1278,7 +1278,8 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f
return;
/* Get split face's verts */
- BM_iter_as_array(bm, BM_VERTS_OF_FACE, split_face, (void **)verts, 4);
+ // BM_iter_as_array(bm, BM_VERTS_OF_FACE, split_face, (void **)verts, 4);
+ BM_face_as_array_vert_quad(split_face, verts);
skin_choose_quad_bridge_order(verts, frame->verts, best_order);
/* Delete split face and merge */
@@ -1314,16 +1315,21 @@ static void skin_hole_detach_partially_attached_frame(BMesh *bm, Frame *frame)
}
-static void quad_from_tris(BMesh *bm, BMEdge *e, BMFace *adj[2], BMVert *ndx[4])
+static void quad_from_tris(BMEdge *e, BMFace *adj[2], BMVert *ndx[4])
{
BMVert *tri[2][3];
BMVert *opp = NULL;
int i, j;
BLI_assert(adj[0]->len == 3 && adj[1]->len == 3);
-
+
+#if 0
BM_iter_as_array(bm, BM_VERTS_OF_FACE, adj[0], (void **)tri[0], 3);
BM_iter_as_array(bm, BM_VERTS_OF_FACE, adj[1], (void **)tri[1], 3);
+#else
+ BM_face_as_array_vert_tri(adj[0], tri[0]);
+ BM_face_as_array_vert_tri(adj[1], tri[1]);
+#endif
/* Find what the second tri has that the first doesn't */
for (i = 0; i < 3; i++) {
@@ -1354,7 +1360,7 @@ static void add_quad_from_tris(SkinOutput *so, BMEdge *e, BMFace *adj[2])
{
BMVert *quad[4];
- quad_from_tris(so->bm, e, adj, quad);
+ quad_from_tris(e, adj, quad);
add_poly(so, quad[0], quad[1], quad[2], quad[3]);
}
@@ -1381,7 +1387,7 @@ static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd)
/* Construct quad using the two triangles adjacent to
* the edge */
- quad_from_tris(so->bm, e, adj, quad);
+ quad_from_tris(e, adj, quad);
/* Calculate a score for the quad, higher score for
* triangles being closer to coplanar */
@@ -1779,7 +1785,7 @@ static DerivedMesh *base_skin(DerivedMesh *origdm,
totvert = origdm->getNumVerts(origdm);
totedge = origdm->getNumEdges(origdm);
- create_vert_edge_map(&emap, &emapmem, medge, totvert, totedge);
+ BKE_mesh_vert_edge_map_create(&emap, &emapmem, medge, totvert, totedge);
emat = build_edge_mats(nodes, mvert, totvert, medge, emap, totedge);
skin_nodes = build_frames(mvert, totvert, nodes, emap, emat);
diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
index 75e54d77b15..9cdd52f2375 100644
--- a/source/blender/modifiers/intern/MOD_solidify.c
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -29,6 +29,7 @@
* \ingroup modifiers
*/
+#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "MEM_guardedalloc.h"
@@ -185,6 +186,8 @@ static void copyData(ModifierData *md, ModifierData *target)
tsmd->crease_outer = smd->crease_outer;
tsmd->crease_rim = smd->crease_rim;
tsmd->flag = smd->flag;
+ tsmd->mat_ofs = smd->mat_ofs;
+ tsmd->mat_ofs_rim = smd->mat_ofs_rim;
BLI_strncpy(tsmd->defgrp_name, smd->defgrp_name, sizeof(tsmd->defgrp_name));
}
@@ -248,7 +251,8 @@ static DerivedMesh *applyModifier(
const float ofs_new = smd->offset + ofs_orig;
const float offset_fac_vg = smd->offset_fac_vg;
const float offset_fac_vg_inv = 1.0f - smd->offset_fac_vg;
- const int do_flip = (smd->flag & MOD_SOLIDIFY_FLIP) != 0;
+ const bool do_flip = (smd->flag & MOD_SOLIDIFY_FLIP) != 0;
+ const bool do_clamp = (smd->offset_clamp != 0.0f);
/* weights */
MDeformVert *dvert, *dv = NULL;
@@ -420,6 +424,20 @@ static DerivedMesh *applyModifier(
float scalar_short;
float scalar_short_vgroup;
+ /* for clamping */
+ float *vert_lens = NULL;
+ const float offset = fabsf(smd->offset) * smd->offset_clamp;
+ const float offset_sq = offset * offset;
+
+ if (do_clamp) {
+ vert_lens = MEM_callocN(sizeof(float) * numVerts, "vert_lens");
+ fill_vn_fl(vert_lens, 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[medge[i].v1] = min_ff(vert_lens[medge[i].v1], ed_len);
+ vert_lens[medge[i].v2] = min_ff(vert_lens[medge[i].v2], ed_len);
+ }
+ }
if (ofs_new != 0.0f) {
scalar_short = scalar_short_vgroup = ofs_new / 32767.0f;
@@ -432,6 +450,16 @@ static DerivedMesh *applyModifier(
scalar_short_vgroup = (offset_fac_vg + (scalar_short_vgroup * offset_fac_vg_inv)) * scalar_short;
dv++;
}
+ if (do_clamp) {
+ /* always reset becaise we may have set before */
+ if (dv == NULL) {
+ scalar_short_vgroup = scalar_short;
+ }
+ if (vert_lens[i] < offset_sq) {
+ float scalar = sqrtf(vert_lens[i]) / offset;
+ scalar_short_vgroup *= scalar;
+ }
+ }
madd_v3v3short_fl(mv->co, mv->no, scalar_short_vgroup);
}
}
@@ -447,9 +475,23 @@ static DerivedMesh *applyModifier(
scalar_short_vgroup = (offset_fac_vg + (scalar_short_vgroup * offset_fac_vg_inv)) * scalar_short;
dv++;
}
+ if (do_clamp) {
+ /* always reset becaise we may have set before */
+ if (dv == NULL) {
+ scalar_short_vgroup = scalar_short;
+ }
+ if (vert_lens[i] < offset_sq) {
+ float scalar = sqrtf(vert_lens[i]) / offset;
+ scalar_short_vgroup *= scalar;
+ }
+ }
madd_v3v3short_fl(mv->co, mv->no, scalar_short_vgroup);
}
}
+
+ if (do_clamp) {
+ MEM_freeN(vert_lens);
+ }
}
else {
/* make a face normal layer if not present */
@@ -537,6 +579,25 @@ static DerivedMesh *applyModifier(
}
}
+ if (do_clamp) {
+ float *vert_lens = MEM_callocN(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, 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[medge[i].v1] = min_ff(vert_lens[medge[i].v1], ed_len);
+ vert_lens[medge[i].v2] = min_ff(vert_lens[medge[i].v2], ed_len);
+ }
+ for (i = 0; i < numVerts; i++) {
+ if (vert_lens[i] < offset_sq) {
+ float scalar = sqrtf(vert_lens[i]) / offset;
+ vert_angles[i] *= scalar;
+ }
+ }
+ MEM_freeN(vert_lens);
+ }
+
if (ofs_new) {
mv = mvert + (((ofs_new >= ofs_orig) == do_flip) ? numVerts : 0);
@@ -596,6 +657,10 @@ static DerivedMesh *applyModifier(
int *orig_ed;
int j;
+ if (crease_rim || crease_outer || crease_inner) {
+ result->cd_flag |= ME_CDFLAG_EDGE_CREASE;
+ }
+
/* add faces & edges */
origindex_edge = result->getEdgeDataArray(result, CD_ORIGINDEX);
ed = &medge[numEdges * 2];
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index e97f4191e6f..c48682b877e 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -47,7 +47,7 @@
#include "MOD_modifiertypes.h"
-#include "CCGSubSurf.h"
+#include "intern/CCGSubSurf.h"
static void initData(ModifierData *md)
{
@@ -103,10 +103,11 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
subsurf_flags |= SUBSURF_USE_RENDER_PARAMS;
if (isFinalCalc)
subsurf_flags |= SUBSURF_IS_FINAL_CALC;
- if (ob->flag & OB_MODE_EDIT)
+ if (ob->mode & OB_MODE_EDIT)
subsurf_flags |= SUBSURF_IN_EDIT_MODE;
result = subsurf_make_derived_from_derived(derivedData, smd, NULL, subsurf_flags);
+ result->cd_flag = derivedData->cd_flag;
if (useRenderParams || !isFinalCalc) {
DerivedMesh *cddm = CDDM_copy(result);
diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c
index 645fd5eb2cf..1c22e9bf364 100644
--- a/source/blender/modifiers/intern/MOD_triangulate.c
+++ b/source/blender/modifiers/intern/MOD_triangulate.c
@@ -33,8 +33,6 @@
#include "BKE_modifier.h"
#include "BKE_tessmesh.h"
-/* triangulation modifier, directly calls the bmesh operator */
-
static DerivedMesh *triangulate_dm(DerivedMesh *dm, const int flag)
{
DerivedMesh *result;
@@ -44,13 +42,7 @@ static DerivedMesh *triangulate_dm(DerivedMesh *dm, const int flag)
bm = DM_to_bmesh(dm);
- BM_mesh_elem_toolflags_ensure(bm);
- BMO_push(bm, NULL);
-
- BMO_op_callf(bm, BMO_FLAG_DEFAULTS,
- "triangulate faces=%af use_beauty=%b",
- (flag & MOD_TRIANGULATE_BEAUTY));
- BMO_pop(bm);
+ BM_mesh_triangulate(bm, (flag & MOD_TRIANGULATE_BEAUTY), false, NULL, NULL);
result = CDDM_from_bmesh(bm, FALSE);
BM_mesh_free(bm);
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index a27d5e5e03b..1084023fcf0 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -74,7 +74,7 @@ void get_texture_value(Tex *texture, float *tex_co, TexResult *texres)
int result_type;
/* no node textures for now */
- result_type = multitex_ext_safe(texture, tex_co, texres);
+ result_type = multitex_ext_safe(texture, tex_co, texres, NULL);
/* 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.
@@ -279,5 +279,7 @@ void modifier_type_init(ModifierTypeInfo *types[])
INIT_TYPE(Skin);
INIT_TYPE(LaplacianSmooth);
INIT_TYPE(Triangulate);
+ INIT_TYPE(UVWarp);
+ INIT_TYPE(MeshCache);
#undef INIT_TYPE
}
diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c
new file mode 100644
index 00000000000..249c3c89d5f
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_uvwarp.c
@@ -0,0 +1,268 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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): Pawel Kowal, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/modifiers/intern/MOD_uvwarp.c
+ * \ingroup modifiers
+ */
+
+#include <string.h>
+
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_action.h" /* BKE_pose_channel_find_name */
+#include "BKE_cdderivedmesh.h"
+#include "BKE_deform.h"
+#include "BKE_modifier.h"
+
+#include "depsgraph_private.h"
+
+#include "MOD_util.h"
+
+
+static void uv_warp_from_mat4_pair(float uv_dst[2], const float uv_src[2], float warp_mat[4][4],
+ int axis_u, int axis_v)
+{
+ float tuv[3] = {0.0f};
+
+ tuv[axis_u] = uv_src[0];
+ tuv[axis_v] = uv_src[1];
+
+ mul_m4_v3(warp_mat, tuv);
+
+ uv_dst[0] = tuv[axis_u];
+ uv_dst[1] = tuv[axis_v];
+}
+
+static void initData(ModifierData *md)
+{
+ UVWarpModifierData *umd = (UVWarpModifierData *) md;
+ umd->axis_u = 0;
+ umd->axis_v = 1;
+ copy_v2_fl(umd->center, 0.5f);
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ UVWarpModifierData *umd = (UVWarpModifierData *)md;
+ UVWarpModifierData *tumd = (UVWarpModifierData *)target;
+
+ tumd->axis_u = umd->axis_u;
+ tumd->axis_v = umd->axis_v;
+ copy_v2_v2(tumd->center, umd->center);
+ tumd->object_src = umd->object_src;
+ BLI_strncpy(tumd->bone_src, umd->bone_src, sizeof(tumd->bone_src));
+ tumd->object_dst = umd->object_dst;
+ BLI_strncpy(tumd->bone_dst, umd->bone_dst, sizeof(tumd->bone_dst));
+ BLI_strncpy(tumd->vgroup_name, umd->vgroup_name, sizeof(tumd->vgroup_name));
+ BLI_strncpy(tumd->uvlayer_name, umd->uvlayer_name, sizeof(umd->uvlayer_name));
+}
+
+static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
+{
+ UVWarpModifierData *umd = (UVWarpModifierData *)md;
+ CustomDataMask dataMask = 0;
+
+ /* ask for vertexgroups if we need them */
+ if (umd->vgroup_name[0])
+ dataMask |= CD_MASK_MDEFORMVERT;
+
+ return dataMask;
+}
+
+static void matrix_from_obj_pchan(float mat[4][4], Object *ob, const char *bonename)
+{
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bonename);
+ if (pchan) {
+ mult_m4_m4m4(mat, ob->obmat, pchan->pose_mat);
+ }
+ else {
+ copy_m4_m4(mat, ob->obmat);
+ }
+}
+
+#define OMP_LIMIT 1000
+static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
+ DerivedMesh *dm,
+ ModifierApplyFlag UNUSED(flag))
+{
+ UVWarpModifierData *umd = (UVWarpModifierData *) md;
+ int i, numPolys, numLoops;
+ MPoly *mpoly;
+ MLoop *mloop;
+ MLoopUV *mloopuv;
+ MDeformVert *dvert;
+ int defgrp_index;
+ char uvname[MAX_CUSTOMDATA_LAYER_NAME];
+ float mat_src[4][4];
+ float mat_dst[4][4];
+ float imat_dst[4][4];
+ float warp_mat[4][4];
+ const int axis_u = umd->axis_u;
+ const int axis_v = umd->axis_v;
+
+ /* make sure there are UV Maps available */
+ if (!CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) {
+ return dm;
+ }
+ else if (ELEM(NULL, umd->object_src, umd->object_dst)) {
+ modifier_setError(md, "From/To objects must be set");
+ return dm;
+ }
+
+ /* make sure anything moving UVs is available */
+ matrix_from_obj_pchan(mat_src, umd->object_src, umd->bone_src);
+ matrix_from_obj_pchan(mat_dst, umd->object_dst, umd->bone_dst);
+
+ invert_m4_m4(imat_dst, mat_dst);
+ mult_m4_m4m4(warp_mat, imat_dst, mat_src);
+
+ /* apply warp */
+ if (!is_zero_v2(umd->center)) {
+ float mat_cent[4][4];
+ float imat_cent[4][4];
+
+ unit_m4(mat_cent);
+ mat_cent[3][axis_u] = umd->center[0];
+ mat_cent[3][axis_v] = umd->center[1];
+
+ invert_m4_m4(imat_cent, mat_cent);
+
+ mult_m4_m4m4(warp_mat, warp_mat, imat_cent);
+ mult_m4_m4m4(warp_mat, mat_cent, warp_mat);
+ }
+
+ /* make sure we're using an existing layer */
+ CustomData_validate_layer_name(&dm->loopData, CD_MLOOPUV, umd->uvlayer_name, uvname);
+
+ numPolys = dm->getNumPolys(dm);
+ numLoops = dm->getNumLoops(dm);
+
+ mpoly = dm->getPolyArray(dm);
+ mloop = dm->getLoopArray(dm);
+ /* make sure we are not modifying the original UV map */
+ mloopuv = CustomData_duplicate_referenced_layer_named(&dm->loopData, CD_MLOOPUV, uvname, numLoops);
+ modifier_get_vgroup(ob, dm, umd->vgroup_name, &dvert, &defgrp_index);
+
+ if (dvert) {
+#pragma omp parallel for if (numPolys > OMP_LIMIT)
+ for (i = 0; i < numPolys; i++) {
+ float uv[2];
+ MPoly *mp = &mpoly[i];
+ MLoop *ml = &mloop[mp->loopstart];
+ MLoopUV *mluv = &mloopuv[mp->loopstart];
+ int l;
+ for (l = 0; l < mp->totloop; l++, ml++, mluv++) {
+ const float weight = defvert_find_weight(&dvert[ml->v], defgrp_index);
+ uv_warp_from_mat4_pair(uv, mluv->uv, warp_mat, axis_u, axis_v);
+ interp_v2_v2v2(mluv->uv, mluv->uv, uv, weight);
+ }
+ }
+ }
+ else {
+#pragma omp parallel for if (numPolys > OMP_LIMIT)
+ for (i = 0; i < numPolys; i++) {
+ MPoly *mp = &mpoly[i];
+ // MLoop *ml = &mloop[mp->loopstart];
+ MLoopUV *mluv = &mloopuv[mp->loopstart];
+ int l;
+ for (l = 0; l < mp->totloop; l++, /* ml++, */ mluv++) {
+ uv_warp_from_mat4_pair(mluv->uv, mluv->uv, warp_mat, axis_u, axis_v);
+ }
+ }
+ }
+
+ dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
+
+ return dm;
+}
+
+static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
+ struct BMEditMesh *UNUSED(editData),
+ DerivedMesh *derivedData)
+{
+ return applyModifier(md, ob, derivedData, MOD_APPLY_USECACHE);
+}
+
+static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
+{
+ UVWarpModifierData *umd = (UVWarpModifierData *) md;
+
+ walk(userData, ob, &umd->object_dst);
+ walk(userData, ob, &umd->object_src);
+}
+
+static void uv_warp_deps_object_bone(DagForest *forest, DagNode *obNode,
+ Object *obj, const char *bonename)
+{
+ if (obj) {
+ DagNode *curNode = dag_get_node(forest, obj);
+
+ if (bonename[0])
+ dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "UVWarp Modifier");
+ else
+ dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA, "UVWarp Modifier");
+ }
+}
+
+static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob),
+ DagNode *obNode)
+{
+ UVWarpModifierData *umd = (UVWarpModifierData *) md;
+
+ uv_warp_deps_object_bone(forest, obNode, umd->object_src, umd->bone_src);
+ uv_warp_deps_object_bone(forest, obNode, umd->object_dst, umd->bone_dst);
+}
+
+ModifierTypeInfo modifierType_UVWarp = {
+ /* name */ "UVWarp",
+ /* structName */ "UVWarpModifierData",
+ /* structSize */ sizeof(UVWarpModifierData),
+ /* type */ eModifierTypeType_NonGeometrical,
+ /* flags */ eModifierTypeFlag_AcceptsMesh |
+ eModifierTypeFlag_SupportsEditmode |
+ eModifierTypeFlag_EnableInEditmode,
+ /* copyData */ copyData,
+ /* deformVerts */ NULL,
+ /* deformMatrices */ NULL,
+ /* deformVertsEM */ NULL,
+ /* deformMatricesEM */ NULL,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ applyModifierEM,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepgraph */ updateDepgraph,
+ /* dependsOnTime */ NULL,
+ /* dependsOnNormals */ NULL,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index 5883b176317..f025352795b 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -361,7 +361,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
/* Mix weights. */
for (i = 0; i < numIdx; i++) {
- float weight2 = 0.0;
+ float weight2;
org_w[i] = dw1[i] ? dw1[i]->weight : wmd->default_weight_a;
weight2 = dw2[i] ? dw2[i]->weight : wmd->default_weight_b;
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index e936e571a5b..71d6d4880ad 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -107,9 +107,9 @@ static void get_vert2geom_distance(int numVerts, float (*v_cos)[3],
/*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) \
+#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
for (i = 0; i < numVerts; i++) {
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 141a3680df2..f3b3d6b1f53 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -123,6 +123,7 @@ set(SRC
composite/nodes/node_composite_pixelate.c
composite/node_composite_tree.c
+ composite/node_composite_util.c
shader/nodes/node_shader_camera.c
shader/nodes/node_shader_common.c
@@ -168,6 +169,7 @@ set(SRC
shader/nodes/node_shader_mix_shader.c
shader/nodes/node_shader_normal_map.c
shader/nodes/node_shader_object_info.c
+ shader/nodes/node_shader_hair_info.c
shader/nodes/node_shader_output_lamp.c
shader/nodes/node_shader_output_material.c
shader/nodes/node_shader_output_world.c
@@ -222,25 +224,21 @@ set(SRC
intern/node_common.c
intern/node_socket.c
+ composite/node_composite_util.h
shader/node_shader_util.h
texture/node_texture_util.h
+ NOD_common.h
NOD_composite.h
NOD_shader.h
NOD_texture.h
NOD_socket.h
+ NOD_static_types.h
intern/node_util.h
intern/node_exec.h
intern/node_common.h
)
-if(WITH_COMPOSITOR_LEGACY)
- list(APPEND SRC
- composite/node_composite_util.h
- composite/node_composite_util.c
- )
-endif()
-
if(WITH_PYTHON)
list(APPEND INC
../python
@@ -266,8 +264,4 @@ if(WITH_COMPOSITOR)
add_definitions(-DWITH_COMPOSITOR)
endif()
-if(WITH_COMPOSITOR_LEGACY)
- add_definitions(-DWITH_COMPOSITOR_LEGACY)
-endif()
-
blender_add_lib(bf_nodes "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/nodes/NOD_common.h b/source/blender/nodes/NOD_common.h
new file mode 100644
index 00000000000..ac0ceab36d4
--- /dev/null
+++ b/source/blender/nodes/NOD_common.h
@@ -0,0 +1,54 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Lukas Toenne.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file NOD_common.h
+ * \ingroup nodes
+ */
+
+#ifndef NOD_COMMON_H
+#define NOD_COMMON_H
+
+#include "BKE_node.h"
+
+void register_node_type_frame(void);
+void register_node_type_reroute(void);
+
+void register_node_type_group_input(void);
+void register_node_type_group_output(void);
+
+
+/* internal functions for editor */
+struct bNodeSocket *node_group_find_input_socket(struct bNode *groupnode, const char *identifier);
+struct bNodeSocket *node_group_find_output_socket(struct bNode *groupnode, const char *identifier);
+void node_group_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id);
+
+struct bNodeSocket *node_group_input_find_socket(struct bNode *node, const char *identifier);
+struct bNodeSocket *node_group_output_find_socket(struct bNode *node, const char *identifier);
+void node_group_input_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id);
+void node_group_output_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id);
+
+#endif
diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h
index 6d60ac0bb58..f272ec670e7 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -34,105 +34,109 @@
#include "BKE_node.h"
-extern bNodeTreeType ntreeType_Composite;
+extern struct bNodeTreeType *ntreeType_Composite;
/* ****************** types array for all composite nodes ****************** */
-void register_node_type_cmp_group(struct bNodeTreeType *ttype);
+void register_node_tree_type_cmp(void);
-void register_node_type_cmp_rlayers(struct bNodeTreeType *ttype);
-void register_node_type_cmp_image(struct bNodeTreeType *ttype);
-void register_node_type_cmp_texture(struct bNodeTreeType *ttype);
-void register_node_type_cmp_value(struct bNodeTreeType *ttype);
-void register_node_type_cmp_rgb(struct bNodeTreeType *ttype);
-void register_node_type_cmp_curve_time(struct bNodeTreeType *ttype);
-void register_node_type_cmp_movieclip(struct bNodeTreeType *ttype);
+void register_node_type_cmp_group(void);
+void register_node_type_cmp_forloop(void);
+void register_node_type_cmp_whileloop(void);
+
+void register_node_type_cmp_rlayers(void);
+void register_node_type_cmp_image(void);
+void register_node_type_cmp_texture(void);
+void register_node_type_cmp_value(void);
+void register_node_type_cmp_rgb(void);
+void register_node_type_cmp_curve_time(void);
+void register_node_type_cmp_movieclip(void);
void register_node_type_cmp_usermask(struct bNodeTreeType *ttype);
-void register_node_type_cmp_composite(struct bNodeTreeType *ttype);
-void register_node_type_cmp_viewer(struct bNodeTreeType *ttype);
-void register_node_type_cmp_splitviewer(struct bNodeTreeType *ttype);
-void register_node_type_cmp_output_file(struct bNodeTreeType *ttype);
-void register_node_type_cmp_view_levels(struct bNodeTreeType *ttype);
-
-void register_node_type_cmp_curve_rgb(struct bNodeTreeType *ttype);
-void register_node_type_cmp_mix_rgb(struct bNodeTreeType *ttype);
-void register_node_type_cmp_hue_sat(struct bNodeTreeType *ttype);
-void register_node_type_cmp_brightcontrast(struct bNodeTreeType *ttype);
-void register_node_type_cmp_gamma(struct bNodeTreeType *ttype);
-void register_node_type_cmp_invert(struct bNodeTreeType *ttype);
-void register_node_type_cmp_alphaover(struct bNodeTreeType *ttype);
-void register_node_type_cmp_zcombine(struct bNodeTreeType *ttype);
-void register_node_type_cmp_colorbalance(struct bNodeTreeType *ttype);
-void register_node_type_cmp_huecorrect(struct bNodeTreeType *ttype);
-
-void register_node_type_cmp_normal(struct bNodeTreeType *ttype);
-void register_node_type_cmp_curve_vec(struct bNodeTreeType *ttype);
-void register_node_type_cmp_map_value(struct bNodeTreeType *ttype);
-void register_node_type_cmp_map_range(struct bNodeTreeType *ttype);
-void register_node_type_cmp_normalize(struct bNodeTreeType *ttype);
-
-void register_node_type_cmp_filter(struct bNodeTreeType *ttype);
-void register_node_type_cmp_blur(struct bNodeTreeType *ttype);
-void register_node_type_cmp_dblur(struct bNodeTreeType *ttype);
-void register_node_type_cmp_bilateralblur(struct bNodeTreeType *ttype);
-void register_node_type_cmp_vecblur(struct bNodeTreeType *ttype);
-void register_node_type_cmp_dilateerode(struct bNodeTreeType *ttype);
-void register_node_type_cmp_inpaint(struct bNodeTreeType *ttype);
-void register_node_type_cmp_despeckle(struct bNodeTreeType *ttype);
-void register_node_type_cmp_defocus(struct bNodeTreeType *ttype);
-
-void register_node_type_cmp_valtorgb(struct bNodeTreeType *ttype);
-void register_node_type_cmp_rgbtobw(struct bNodeTreeType *ttype);
-void register_node_type_cmp_setalpha(struct bNodeTreeType *ttype);
-void register_node_type_cmp_idmask(struct bNodeTreeType *ttype);
-void register_node_type_cmp_math(struct bNodeTreeType *ttype);
-void register_node_type_cmp_seprgba(struct bNodeTreeType *ttype);
-void register_node_type_cmp_combrgba(struct bNodeTreeType *ttype);
-void register_node_type_cmp_sephsva(struct bNodeTreeType *ttype);
-void register_node_type_cmp_combhsva(struct bNodeTreeType *ttype);
-void register_node_type_cmp_sepyuva(struct bNodeTreeType *ttype);
-void register_node_type_cmp_combyuva(struct bNodeTreeType *ttype);
-void register_node_type_cmp_sepycca(struct bNodeTreeType *ttype);
-void register_node_type_cmp_combycca(struct bNodeTreeType *ttype);
-void register_node_type_cmp_premulkey(struct bNodeTreeType *ttype);
-
-void register_node_type_cmp_diff_matte(struct bNodeTreeType *ttype);
-void register_node_type_cmp_distance_matte(struct bNodeTreeType *ttype);
-void register_node_type_cmp_chroma_matte(struct bNodeTreeType *ttype);
-void register_node_type_cmp_color_matte(struct bNodeTreeType *ttype);
-void register_node_type_cmp_channel_matte(struct bNodeTreeType *ttype);
-void register_node_type_cmp_color_spill(struct bNodeTreeType *ttype);
-void register_node_type_cmp_luma_matte(struct bNodeTreeType *ttype);
-void register_node_type_cmp_doubleedgemask(struct bNodeTreeType *ttype);
-void register_node_type_cmp_keyingscreen(struct bNodeTreeType *ttype);
-void register_node_type_cmp_keying(struct bNodeTreeType *ttype);
-
-void register_node_type_cmp_translate(struct bNodeTreeType *ttype);
-void register_node_type_cmp_rotate(struct bNodeTreeType *ttype);
-void register_node_type_cmp_scale(struct bNodeTreeType *ttype);
-void register_node_type_cmp_flip(struct bNodeTreeType *ttype);
-void register_node_type_cmp_crop(struct bNodeTreeType *ttype);
-void register_node_type_cmp_displace(struct bNodeTreeType *ttype);
-void register_node_type_cmp_mapuv(struct bNodeTreeType *ttype);
-void register_node_type_cmp_transform(struct bNodeTreeType *ttype);
-void register_node_type_cmp_stabilize2d(struct bNodeTreeType *ttype);
-void register_node_type_cmp_moviedistortion(struct bNodeTreeType *ttype);
-void register_node_type_cmp_mask(struct bNodeTreeType *ttype);
-
-void register_node_type_cmp_glare(struct bNodeTreeType *ttype);
-void register_node_type_cmp_tonemap(struct bNodeTreeType *ttype);
-void register_node_type_cmp_lensdist(struct bNodeTreeType *ttype);
-
-
-void register_node_type_cmp_colorcorrection(struct bNodeTreeType *ttype);
-void register_node_type_cmp_boxmask(struct bNodeTreeType *ttype);
-void register_node_type_cmp_ellipsemask(struct bNodeTreeType *ttype);
-void register_node_type_cmp_bokehimage(struct bNodeTreeType *ttype);
-void register_node_type_cmp_bokehblur(struct bNodeTreeType *ttype);
-void register_node_type_cmp_switch(struct bNodeTreeType *ttype);
-void register_node_type_cmp_pixelate(struct bNodeTreeType *ttype);
-void register_node_type_cmp_trackpos(struct bNodeTreeType *ttype);
+void register_node_type_cmp_composite(void);
+void register_node_type_cmp_viewer(void);
+void register_node_type_cmp_splitviewer(void);
+void register_node_type_cmp_output_file(void);
+void register_node_type_cmp_view_levels(void);
+
+void register_node_type_cmp_curve_rgb(void);
+void register_node_type_cmp_mix_rgb(void);
+void register_node_type_cmp_hue_sat(void);
+void register_node_type_cmp_brightcontrast(void);
+void register_node_type_cmp_gamma(void);
+void register_node_type_cmp_invert(void);
+void register_node_type_cmp_alphaover(void);
+void register_node_type_cmp_zcombine(void);
+void register_node_type_cmp_colorbalance(void);
+void register_node_type_cmp_huecorrect(void);
+
+void register_node_type_cmp_normal(void);
+void register_node_type_cmp_curve_vec(void);
+void register_node_type_cmp_map_value(void);
+void register_node_type_cmp_map_range(void);
+void register_node_type_cmp_normalize(void);
+
+void register_node_type_cmp_filter(void);
+void register_node_type_cmp_blur(void);
+void register_node_type_cmp_dblur(void);
+void register_node_type_cmp_bilateralblur(void);
+void register_node_type_cmp_vecblur(void);
+void register_node_type_cmp_dilateerode(void);
+void register_node_type_cmp_inpaint(void);
+void register_node_type_cmp_despeckle(void);
+void register_node_type_cmp_defocus(void);
+
+void register_node_type_cmp_valtorgb(void);
+void register_node_type_cmp_rgbtobw(void);
+void register_node_type_cmp_setalpha(void);
+void register_node_type_cmp_idmask(void);
+void register_node_type_cmp_math(void);
+void register_node_type_cmp_seprgba(void);
+void register_node_type_cmp_combrgba(void);
+void register_node_type_cmp_sephsva(void);
+void register_node_type_cmp_combhsva(void);
+void register_node_type_cmp_sepyuva(void);
+void register_node_type_cmp_combyuva(void);
+void register_node_type_cmp_sepycca(void);
+void register_node_type_cmp_combycca(void);
+void register_node_type_cmp_premulkey(void);
+
+void register_node_type_cmp_diff_matte(void);
+void register_node_type_cmp_distance_matte(void);
+void register_node_type_cmp_chroma_matte(void);
+void register_node_type_cmp_color_matte(void);
+void register_node_type_cmp_channel_matte(void);
+void register_node_type_cmp_color_spill(void);
+void register_node_type_cmp_luma_matte(void);
+void register_node_type_cmp_doubleedgemask(void);
+void register_node_type_cmp_keyingscreen(void);
+void register_node_type_cmp_keying(void);
+
+void register_node_type_cmp_translate(void);
+void register_node_type_cmp_rotate(void);
+void register_node_type_cmp_scale(void);
+void register_node_type_cmp_flip(void);
+void register_node_type_cmp_crop(void);
+void register_node_type_cmp_displace(void);
+void register_node_type_cmp_mapuv(void);
+void register_node_type_cmp_transform(void);
+void register_node_type_cmp_stabilize2d(void);
+void register_node_type_cmp_moviedistortion(void);
+void register_node_type_cmp_mask(void);
+
+void register_node_type_cmp_glare(void);
+void register_node_type_cmp_tonemap(void);
+void register_node_type_cmp_lensdist(void);
+
+
+void register_node_type_cmp_colorcorrection(void);
+void register_node_type_cmp_boxmask(void);
+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_pixelate(void);
+void register_node_type_cmp_trackpos(void);
#endif
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 74135776c9c..9561fe00409 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -34,86 +34,91 @@
#include "BKE_node.h"
-extern struct bNodeTreeType ntreeType_Shader;
+extern struct bNodeTreeType *ntreeType_Shader;
/* the type definitions array */
/* ****************** types array for all shaders ****************** */
-void register_node_type_sh_group(struct bNodeTreeType *ttype);
-
-void register_node_type_sh_output(struct bNodeTreeType *ttype);
-void register_node_type_sh_material(struct bNodeTreeType *ttype);
-void register_node_type_sh_camera(struct bNodeTreeType *ttype);
-void register_node_type_sh_value(struct bNodeTreeType *ttype);
-void register_node_type_sh_rgb(struct bNodeTreeType *ttype);
-void register_node_type_sh_mix_rgb(struct bNodeTreeType *ttype);
-void register_node_type_sh_valtorgb(struct bNodeTreeType *ttype);
-void register_node_type_sh_rgbtobw(struct bNodeTreeType *ttype);
-void register_node_type_sh_texture(struct bNodeTreeType *ttype);
-void register_node_type_sh_normal(struct bNodeTreeType *ttype);
-void register_node_type_sh_gamma(struct bNodeTreeType *ttype);
-void register_node_type_sh_brightcontrast(struct bNodeTreeType *ttype);
-void register_node_type_sh_geom(struct bNodeTreeType *ttype);
-void register_node_type_sh_mapping(struct bNodeTreeType *ttype);
-void register_node_type_sh_curve_vec(struct bNodeTreeType *ttype);
-void register_node_type_sh_curve_rgb(struct bNodeTreeType *ttype);
-void register_node_type_sh_math(struct bNodeTreeType *ttype);
-void register_node_type_sh_vect_math(struct bNodeTreeType *ttype);
-void register_node_type_sh_squeeze(struct bNodeTreeType *ttype);
-void register_node_type_sh_dynamic(struct bNodeTreeType *ttype);
-void register_node_type_sh_material_ext(struct bNodeTreeType *ttype);
-void register_node_type_sh_invert(struct bNodeTreeType *ttype);
-void register_node_type_sh_seprgb(struct bNodeTreeType *ttype);
-void register_node_type_sh_combrgb(struct bNodeTreeType *ttype);
-void register_node_type_sh_hue_sat(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_brick(struct bNodeTreeType *ttype);
-
-void register_node_type_sh_attribute(struct bNodeTreeType *ttype);
-void register_node_type_sh_geometry(struct bNodeTreeType *ttype);
-void register_node_type_sh_light_path(struct bNodeTreeType *ttype);
-void register_node_type_sh_light_falloff(struct bNodeTreeType *ttype);
-void register_node_type_sh_object_info(struct bNodeTreeType *ttype);
-void register_node_type_sh_fresnel(struct bNodeTreeType *ttype);
-void register_node_type_sh_layer_weight(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_coord(struct bNodeTreeType *ttype);
-void register_node_type_sh_particle_info(struct bNodeTreeType *ttype);
-void register_node_type_sh_script(struct bNodeTreeType *ttype);
-void register_node_type_sh_normal_map(struct bNodeTreeType *ttype);
-void register_node_type_sh_tangent(struct bNodeTreeType *ttype);
-
-void register_node_type_sh_ambient_occlusion(struct bNodeTreeType *ttype);
-void register_node_type_sh_background(struct bNodeTreeType *ttype);
-void register_node_type_sh_bsdf_diffuse(struct bNodeTreeType *ttype);
-void register_node_type_sh_bsdf_glossy(struct bNodeTreeType *ttype);
-void register_node_type_sh_bsdf_glass(struct bNodeTreeType *ttype);
-void register_node_type_sh_bsdf_refraction(struct bNodeTreeType *ttype);
-void register_node_type_sh_bsdf_translucent(struct bNodeTreeType *ttype);
-void register_node_type_sh_bsdf_transparent(struct bNodeTreeType *ttype);
-void register_node_type_sh_bsdf_velvet(struct bNodeTreeType *ttype);
-void register_node_type_sh_bsdf_anisotropic(struct bNodeTreeType *ttype);
-void register_node_type_sh_emission(struct bNodeTreeType *ttype);
-void register_node_type_sh_holdout(struct bNodeTreeType *ttype);
-void register_node_type_sh_volume_transparent(struct bNodeTreeType *ttype);
-void register_node_type_sh_volume_isotropic(struct bNodeTreeType *ttype);
-void register_node_type_sh_mix_shader(struct bNodeTreeType *ttype);
-void register_node_type_sh_add_shader(struct bNodeTreeType *ttype);
-
-void register_node_type_sh_output_lamp(struct bNodeTreeType *ttype);
-void register_node_type_sh_output_material(struct bNodeTreeType *ttype);
-void register_node_type_sh_output_world(struct bNodeTreeType *ttype);
-
-void register_node_type_sh_tex_image(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_environment(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_sky(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_voronoi(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_gradient(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_magic(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_wave(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_musgrave(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_noise(struct bNodeTreeType *ttype);
-void register_node_type_sh_tex_checker(struct bNodeTreeType *ttype);
-void register_node_type_sh_bump(struct bNodeTreeType *ttype);
+void register_node_tree_type_sh(void);
+
+void register_node_type_sh_group(void);
+void register_node_type_sh_forloop(void);
+void register_node_type_sh_whileloop(void);
+
+void register_node_type_sh_output(void);
+void register_node_type_sh_material(void);
+void register_node_type_sh_camera(void);
+void register_node_type_sh_value(void);
+void register_node_type_sh_rgb(void);
+void register_node_type_sh_mix_rgb(void);
+void register_node_type_sh_valtorgb(void);
+void register_node_type_sh_rgbtobw(void);
+void register_node_type_sh_texture(void);
+void register_node_type_sh_normal(void);
+void register_node_type_sh_gamma(void);
+void register_node_type_sh_brightcontrast(void);
+void register_node_type_sh_geom(void);
+void register_node_type_sh_mapping(void);
+void register_node_type_sh_curve_vec(void);
+void register_node_type_sh_curve_rgb(void);
+void register_node_type_sh_math(void);
+void register_node_type_sh_vect_math(void);
+void register_node_type_sh_squeeze(void);
+void register_node_type_sh_dynamic(void);
+void register_node_type_sh_material_ext(void);
+void register_node_type_sh_invert(void);
+void register_node_type_sh_seprgb(void);
+void register_node_type_sh_combrgb(void);
+void register_node_type_sh_hue_sat(void);
+void register_node_type_sh_tex_brick(void);
+
+void register_node_type_sh_attribute(void);
+void register_node_type_sh_geometry(void);
+void register_node_type_sh_light_path(void);
+void register_node_type_sh_light_falloff(void);
+void register_node_type_sh_object_info(void);
+void register_node_type_sh_fresnel(void);
+void register_node_type_sh_layer_weight(void);
+void register_node_type_sh_tex_coord(void);
+void register_node_type_sh_particle_info(void);
+void register_node_type_sh_hair_info(void);
+void register_node_type_sh_script(void);
+void register_node_type_sh_normal_map(void);
+void register_node_type_sh_tangent(void);
+
+void register_node_type_sh_ambient_occlusion(void);
+void register_node_type_sh_background(void);
+void register_node_type_sh_bsdf_diffuse(void);
+void register_node_type_sh_bsdf_glossy(void);
+void register_node_type_sh_bsdf_glass(void);
+void register_node_type_sh_bsdf_refraction(void);
+void register_node_type_sh_bsdf_translucent(void);
+void register_node_type_sh_bsdf_transparent(void);
+void register_node_type_sh_bsdf_velvet(void);
+void register_node_type_sh_bsdf_anisotropic(void);
+void register_node_type_sh_emission(void);
+void register_node_type_sh_holdout(void);
+void register_node_type_sh_volume_transparent(void);
+void register_node_type_sh_volume_isotropic(void);
+void register_node_type_sh_mix_shader(void);
+void register_node_type_sh_add_shader(void);
+
+void register_node_type_sh_output_lamp(void);
+void register_node_type_sh_output_material(void);
+void register_node_type_sh_output_world(void);
+
+void register_node_type_sh_tex_image(void);
+void register_node_type_sh_tex_environment(void);
+void register_node_type_sh_tex_sky(void);
+void register_node_type_sh_tex_voronoi(void);
+void register_node_type_sh_tex_gradient(void);
+void register_node_type_sh_tex_magic(void);
+void register_node_type_sh_tex_wave(void);
+void register_node_type_sh_tex_musgrave(void);
+void register_node_type_sh_tex_noise(void);
+void register_node_type_sh_tex_checker(void);
+void register_node_type_sh_bump(void);
#endif
diff --git a/source/blender/nodes/NOD_socket.h b/source/blender/nodes/NOD_socket.h
index b14f7c4e884..5f7da1c3f4d 100644
--- a/source/blender/nodes/NOD_socket.h
+++ b/source/blender/nodes/NOD_socket.h
@@ -45,41 +45,11 @@ struct bNodeTree;
struct bNode;
struct bNodeStack;
-void node_socket_type_init(struct bNodeSocketType *types[]);
-
-void *node_socket_make_default_value(int type);
-void node_socket_free_default_value(int type, void *default_value);
-void node_socket_init_default_value(int type, void *default_value);
-void node_socket_copy_default_value(int type, void *to_default_value, void *from_default_value);
-void node_socket_convert_default_value(int to_type, void *to_default_value, int from_type, void *from_default_value);
-
-void node_socket_set_default_value_int(void *default_value, PropertySubType subtype, int value, int min, int max);
-void node_socket_set_default_value_float(void *default_value, PropertySubType subtype, float value, float min, float max);
-void node_socket_set_default_value_boolean(void *default_value, char value);
-void node_socket_set_default_value_vector(void *default_value, PropertySubType subtype, float x, float y, float z, float min, float max);
-void node_socket_set_default_value_rgba(void *default_value, float r, float g, float b, float a);
-void node_socket_set_default_value_shader(void *default_value);
-void node_socket_set_default_value_mesh(void *default_value);
-void node_socket_set_default_value_string(void *default_value, PropertySubType subtype, const char *value);
-
-struct bNodeSocket *node_add_input_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp);
-struct bNodeSocket *node_add_output_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp);
+struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp, int in_out);
void node_verify_socket_templates(struct bNodeTree *ntree, struct bNode *node);
-
-/* Socket Converters */
-
-#define SOCK_VECTOR_X 1
-#define SOCK_VECTOR_Y 2
-#define SOCK_VECTOR_Z 3
-
-#define SOCK_RGBA_R 1
-#define SOCK_RGBA_G 2
-#define SOCK_RGBA_B 3
-#define SOCK_RGBA_A 4
-
-#define SOCK_MESH_VERT_CO 1
-#define SOCK_MESH_VERT_NO 2
+void node_socket_init_default_value(struct bNodeSocket *sock);
+void register_standard_node_socket_types(void);
#endif
diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/nodes/NOD_static_types.h
index 14cdbc6cf7d..9d044772274 100644
--- a/source/blender/makesrna/intern/rna_nodetree_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -20,8 +20,8 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/makesrna/intern/rna_nodetree_types.h
- * \ingroup RNA
+/** \file blender/makesrna/intern/NOD_static_types.h
+ * \ingroup nodes
*/
/* intentionally no include guard */
@@ -31,7 +31,15 @@
#define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc)
#endif
+/* WARNING! If you edit those strings, please do the same in relevant nodes files (under blender/nodes/...)! */
+
/* Tree type Node ID RNA def function Enum name Struct name UI Name UI Description */
+DefNode( Node, NODE_FRAME, def_frame, "FRAME", Frame, "Frame", "" )
+DefNode( Node, NODE_GROUP, def_group, "GROUP", Group, "Group", "" )
+DefNode( Node, NODE_GROUP_INPUT, def_group_input, "GROUP_INPUT", GroupInput, "Group Input", "" )
+DefNode( Node, NODE_GROUP_OUTPUT, def_group_output, "GROUP_OUTPUT", GroupOutput, "Group Output", "" )
+DefNode( Node, NODE_REROUTE, 0, "REROUTE", Reroute, "Reroute", "" )
+
DefNode( ShaderNode, SH_NODE_OUTPUT, 0, "OUTPUT", Output, "Output", "" )
DefNode( ShaderNode, SH_NODE_MATERIAL, def_sh_material, "MATERIAL", Material, "Material", "" )
DefNode( ShaderNode, SH_NODE_RGB, 0, "RGB", RGB, "RGB", "" )
@@ -45,12 +53,12 @@ DefNode( ShaderNode, SH_NODE_GAMMA, 0, "GAMMA
DefNode( ShaderNode, SH_NODE_BRIGHTCONTRAST, 0, "BRIGHTCONTRAST", BrightContrast, "Bright Contrast", "" )
DefNode( ShaderNode, SH_NODE_GEOMETRY, def_sh_geometry, "GEOMETRY", Geometry, "Geometry", "" )
DefNode( ShaderNode, SH_NODE_MAPPING, def_sh_mapping, "MAPPING", Mapping, "Mapping", "" )
-DefNode( ShaderNode, SH_NODE_CURVE_VEC, def_vector_curve, "CURVE_VEC", VectorCurve, "Vector Curve", "" )
-DefNode( ShaderNode, SH_NODE_CURVE_RGB, def_rgb_curve, "CURVE_RGB", RGBCurve, "RGB Curve", "" )
+DefNode( ShaderNode, SH_NODE_CURVE_VEC, def_vector_curve, "CURVE_VEC", VectorCurve, "Vector Curves", "" )
+DefNode( ShaderNode, SH_NODE_CURVE_RGB, def_rgb_curve, "CURVE_RGB", RGBCurve, "RGB Curves", "" )
DefNode( ShaderNode, SH_NODE_CAMERA, 0, "CAMERA", CameraData, "Camera Data", "" )
DefNode( ShaderNode, SH_NODE_MATH, def_math, "MATH", Math, "Math", "" )
DefNode( ShaderNode, SH_NODE_VECT_MATH, def_vector_math, "VECT_MATH", VectorMath, "Vector Math", "" )
-DefNode( ShaderNode, SH_NODE_SQUEEZE, 0, "SQUEEZE", Squeeze, "Squeeze", "" )
+DefNode( ShaderNode, SH_NODE_SQUEEZE, 0, "SQUEEZE", Squeeze, "Squeeze Value", "" )
DefNode( ShaderNode, SH_NODE_MATERIAL_EXT, def_sh_material, "MATERIAL_EXT", ExtendedMaterial, "Extended Material", "" )
DefNode( ShaderNode, SH_NODE_INVERT, 0, "INVERT", Invert, "Invert", "" )
DefNode( ShaderNode, SH_NODE_SEPRGB, 0, "SEPRGB", SeparateRGB, "Separate RGB", "" )
@@ -68,14 +76,14 @@ DefNode( ShaderNode, SH_NODE_ATTRIBUTE, def_sh_attribute, "AT
DefNode( ShaderNode, SH_NODE_AMBIENT_OCCLUSION, 0, "AMBIENT_OCCLUSION", AmbientOcclusion, "Ambient Occlusion", "" )
DefNode( ShaderNode, SH_NODE_BACKGROUND, 0, "BACKGROUND", Background, "Background", "" )
DefNode( ShaderNode, SH_NODE_HOLDOUT, 0, "HOLDOUT", Holdout, "Holdout", "" )
-DefNode( ShaderNode, SH_NODE_BSDF_ANISOTROPIC, 0, "BSDF_ANISOTROPIC", BsdfAnisotropic, "Anisotropic Bsdf", "" )
-DefNode( ShaderNode, SH_NODE_BSDF_DIFFUSE, 0, "BSDF_DIFFUSE", BsdfDiffuse, "Diffuse Bsdf", "" )
-DefNode( ShaderNode, SH_NODE_BSDF_GLOSSY, def_glossy, "BSDF_GLOSSY", BsdfGlossy, "Glossy Bsdf", "" )
-DefNode( ShaderNode, SH_NODE_BSDF_GLASS, def_glossy, "BSDF_GLASS", BsdfGlass, "Glass Bsdf", "" )
-DefNode( ShaderNode, SH_NODE_BSDF_REFRACTION, def_glossy, "BSDF_REFRACTION", BsdfRefraction, "Refraction Bsdf", "" )
-DefNode( ShaderNode, SH_NODE_BSDF_TRANSLUCENT, 0, "BSDF_TRANSLUCENT", BsdfTranslucent, "Translucent Bsdf", "" )
-DefNode( ShaderNode, SH_NODE_BSDF_TRANSPARENT, 0, "BSDF_TRANSPARENT", BsdfTransparent, "Transparent Bsdf", "" )
-DefNode( ShaderNode, SH_NODE_BSDF_VELVET, 0, "BSDF_VELVET", BsdfVelvet, "Velvet Bsdf", "" )
+DefNode( ShaderNode, SH_NODE_BSDF_ANISOTROPIC, 0, "BSDF_ANISOTROPIC", BsdfAnisotropic, "Anisotropic BSDF", "" )
+DefNode( ShaderNode, SH_NODE_BSDF_DIFFUSE, 0, "BSDF_DIFFUSE", BsdfDiffuse, "Diffuse BSDF", "" )
+DefNode( ShaderNode, SH_NODE_BSDF_GLOSSY, def_glossy, "BSDF_GLOSSY", BsdfGlossy, "Glossy BSDF", "" )
+DefNode( ShaderNode, SH_NODE_BSDF_GLASS, def_glossy, "BSDF_GLASS", BsdfGlass, "Glass BSDF", "" )
+DefNode( ShaderNode, SH_NODE_BSDF_REFRACTION, def_glossy, "BSDF_REFRACTION", BsdfRefraction, "Refraction BSDF", "" )
+DefNode( ShaderNode, SH_NODE_BSDF_TRANSLUCENT, 0, "BSDF_TRANSLUCENT", BsdfTranslucent, "Translucent BSDF", "" )
+DefNode( ShaderNode, SH_NODE_BSDF_TRANSPARENT, 0, "BSDF_TRANSPARENT", BsdfTransparent, "Transparent BSDF", "" )
+DefNode( ShaderNode, SH_NODE_BSDF_VELVET, 0, "BSDF_VELVET", BsdfVelvet, "Velvet BSDF", "" )
DefNode( ShaderNode, SH_NODE_VOLUME_TRANSPARENT, 0, "VOLUME_TRANSPARENT", VolumeTransparent,"Transparent Volume","" )
DefNode( ShaderNode, SH_NODE_VOLUME_ISOTROPIC, 0, "VOLUME_ISOTROPIC", VolumeIsotropic, "Isotropic Volume", "" )
DefNode( ShaderNode, SH_NODE_EMISSION, 0, "EMISSION", Emission, "Emission", "" )
@@ -84,6 +92,7 @@ DefNode( ShaderNode, SH_NODE_LIGHT_PATH, 0, "LI
DefNode( ShaderNode, SH_NODE_LIGHT_FALLOFF, 0, "LIGHT_FALLOFF", LightFalloff, "Light Falloff", "" )
DefNode( ShaderNode, SH_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "" )
DefNode( ShaderNode, SH_NODE_PARTICLE_INFO, 0, "PARTICLE_INFO", ParticleInfo, "Particle Info", "" )
+DefNode( ShaderNode, SH_NODE_HAIR_INFO, 0, "HAIR_INFO", HairInfo, "Hair Info", "" )
DefNode( ShaderNode, SH_NODE_BUMP, 0, "BUMP", Bump, "Bump", "" )
DefNode( ShaderNode, SH_NODE_NORMAL_MAP, def_sh_normal_map, "NORMAL_MAP", NormalMap, "Normal Map", "" )
DefNode( ShaderNode, SH_NODE_TANGENT, def_sh_tangent, "TANGENT", Tangent, "Tangent", "" )
@@ -104,12 +113,12 @@ DefNode( ShaderNode, SH_NODE_TEX_COORD, def_sh_tex_coord, "TE
DefNode( CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" )
DefNode( CompositorNode, CMP_NODE_RGB, 0, "RGB", RGB, "RGB", "" )
DefNode( CompositorNode, CMP_NODE_VALUE, 0, "VALUE", Value, "Value", "" )
-DefNode( CompositorNode, CMP_NODE_MIX_RGB, def_mix_rgb, "MIX_RGB", MixRGB, "Mix RGB", "" )
+DefNode( CompositorNode, CMP_NODE_MIX_RGB, def_mix_rgb, "MIX_RGB", MixRGB, "Mix", "" )
DefNode( CompositorNode, CMP_NODE_VALTORGB, def_colorramp, "VALTORGB", ValToRGB, "ColorRamp", "" )
DefNode( CompositorNode, CMP_NODE_RGBTOBW, 0, "RGBTOBW", RGBToBW, "RGB to BW", "" )
DefNode( CompositorNode, CMP_NODE_NORMAL, 0, "NORMAL", Normal, "Normal", "" )
-DefNode( CompositorNode, CMP_NODE_CURVE_VEC, def_vector_curve, "CURVE_VEC", CurveVec, "Vector Curve", "" )
-DefNode( CompositorNode, CMP_NODE_CURVE_RGB, def_rgb_curve, "CURVE_RGB", CurveRGB, "RGB Curve", "" )
+DefNode( CompositorNode, CMP_NODE_CURVE_VEC, def_vector_curve, "CURVE_VEC", CurveVec, "Vector Curves", "" )
+DefNode( CompositorNode, CMP_NODE_CURVE_RGB, def_rgb_curve, "CURVE_RGB", CurveRGB, "RGB Curves", "" )
DefNode( CompositorNode, CMP_NODE_ALPHAOVER, def_cmp_alpha_over, "ALPHAOVER", AlphaOver, "Alpha Over", "" )
DefNode( CompositorNode, CMP_NODE_BLUR, def_cmp_blur, "BLUR", Blur, "Blur", "" )
DefNode( CompositorNode, CMP_NODE_FILTER, def_cmp_filter, "FILTER", Filter, "Filter", "" )
@@ -120,13 +129,13 @@ DefNode( CompositorNode, CMP_NODE_VECBLUR, def_cmp_vector_blur, "VECBL
DefNode( CompositorNode, CMP_NODE_SEPRGBA, 0, "SEPRGBA", SepRGBA, "Separate RGBA", "" )
DefNode( CompositorNode, CMP_NODE_SEPHSVA, 0, "SEPHSVA", SepHSVA, "Separate HSVA", "" )
DefNode( CompositorNode, CMP_NODE_SETALPHA, 0, "SETALPHA", SetAlpha, "Set Alpha", "" )
-DefNode( CompositorNode, CMP_NODE_HUE_SAT, def_cmp_hue_saturation, "HUE_SAT", HueSat, "Hue/Saturation", "" )
+DefNode( CompositorNode, CMP_NODE_HUE_SAT, def_cmp_hue_saturation, "HUE_SAT", HueSat, "Hue Saturation Value","" )
DefNode( CompositorNode, CMP_NODE_IMAGE, def_cmp_image, "IMAGE", Image, "Image", "" )
DefNode( CompositorNode, CMP_NODE_R_LAYERS, def_cmp_render_layers, "R_LAYERS", RLayers, "Render Layers", "" )
-DefNode( CompositorNode, CMP_NODE_COMPOSITE, 0, "COMPOSITE", Composite, "Composite", "" )
-DefNode( CompositorNode, CMP_NODE_OUTPUT_FILE, def_cmp_output_file, "OUTPUT_FILE", OutputFile, "Output File", "" )
+DefNode( CompositorNode, CMP_NODE_COMPOSITE, def_cmp_composite, "COMPOSITE", Composite, "Composite", "" )
+DefNode( CompositorNode, CMP_NODE_OUTPUT_FILE, def_cmp_output_file, "OUTPUT_FILE", OutputFile, "File Output", "" )
DefNode( CompositorNode, CMP_NODE_TEXTURE, def_texture, "TEXTURE", Texture, "Texture", "" )
-DefNode( CompositorNode, CMP_NODE_TRANSLATE, 0, "TRANSLATE", Translate, "Translate", "" )
+DefNode( CompositorNode, CMP_NODE_TRANSLATE, def_cmp_translate, "TRANSLATE", Translate, "Translate", "" )
DefNode( CompositorNode, CMP_NODE_ZCOMBINE, def_cmp_zcombine, "ZCOMBINE", Zcombine, "Z Combine", "" )
DefNode( CompositorNode, CMP_NODE_COMBRGBA, 0, "COMBRGBA", CombRGBA, "Combine RGBA", "" )
DefNode( CompositorNode, CMP_NODE_DILATEERODE, def_cmp_dilate_erode, "DILATEERODE", DilateErode, "Dilate/Erode", "" )
@@ -134,8 +143,8 @@ DefNode( CompositorNode, CMP_NODE_INPAINT, def_cmp_inpaint, "INPAI
DefNode( CompositorNode, CMP_NODE_DESPECKLE, def_cmp_despeckle, "DESPECKLE", Despeckle, "Despeckle", "" )
DefNode( CompositorNode, CMP_NODE_ROTATE, def_cmp_rotate, "ROTATE", Rotate, "Rotate", "" )
DefNode( CompositorNode, CMP_NODE_SCALE, def_cmp_scale, "SCALE", Scale, "Scale", "" )
-DefNode( CompositorNode, CMP_NODE_SEPYCCA, def_cmp_ycc, "SEPYCCA", SepYCCA, "Separate YCCA", "" )
-DefNode( CompositorNode, CMP_NODE_COMBYCCA, def_cmp_ycc, "COMBYCCA", CombYCCA, "Combine YCCA", "" )
+DefNode( CompositorNode, CMP_NODE_SEPYCCA, def_cmp_ycc, "SEPYCCA", SepYCCA, "Separate YCbCrA", "" )
+DefNode( CompositorNode, CMP_NODE_COMBYCCA, def_cmp_ycc, "COMBYCCA", CombYCCA, "Combine YCbCrA", "" )
DefNode( CompositorNode, CMP_NODE_SEPYUVA, 0, "SEPYUVA", SepYUVA, "Separate YUVA", "" )
DefNode( CompositorNode, CMP_NODE_COMBYUVA, 0, "COMBYUVA", CombYUVA, "Combine YUVA", "" )
DefNode( CompositorNode, CMP_NODE_DIFF_MATTE, def_cmp_diff_matte, "DIFF_MATTE", DiffMatte, "Difference Key", "" )
@@ -146,43 +155,44 @@ DefNode( CompositorNode, CMP_NODE_FLIP, def_cmp_flip, "FLIP"
DefNode( CompositorNode, CMP_NODE_SPLITVIEWER, def_cmp_splitviewer, "SPLITVIEWER", SplitViewer, "Split Viewer", "" )
DefNode( CompositorNode, CMP_NODE_MAP_UV, def_cmp_map_uv, "MAP_UV", MapUV, "Map UV", "" )
DefNode( CompositorNode, CMP_NODE_ID_MASK, def_cmp_id_mask, "ID_MASK", IDMask, "ID Mask", "" )
-DefNode( CompositorNode, CMP_NODE_DOUBLEEDGEMASK, def_cmp_double_edge_mask,"DOUBLEEDGEMASK", DoubleEdgeMask, "Double Edge Mask", "" )
+DefNode( CompositorNode, CMP_NODE_DOUBLEEDGEMASK, def_cmp_double_edge_mask,"DOUBLEEDGEMASK", DoubleEdgeMask, "Double Edge Mask", "" )
DefNode( CompositorNode, CMP_NODE_DEFOCUS, def_cmp_defocus, "DEFOCUS", Defocus, "Defocus", "" )
DefNode( CompositorNode, CMP_NODE_DISPLACE, 0, "DISPLACE", Displace, "Displace", "" )
DefNode( CompositorNode, CMP_NODE_COMBHSVA, 0, "COMBHSVA", CombHSVA, "Combine HSVA", "" )
DefNode( CompositorNode, CMP_NODE_MATH, def_math, "MATH", Math, "Math", "" )
-DefNode( CompositorNode, CMP_NODE_LUMA_MATTE, def_cmp_luma_matte, "LUMA_MATTE", LumaMatte, "Luma Matte", "" )
-DefNode( CompositorNode, CMP_NODE_BRIGHTCONTRAST, 0, "BRIGHTCONTRAST", BrightContrast, "Bright Contrast", "" )
+DefNode( CompositorNode, CMP_NODE_LUMA_MATTE, def_cmp_luma_matte, "LUMA_MATTE", LumaMatte, "Luminance Key", "" )
+DefNode( CompositorNode, CMP_NODE_BRIGHTCONTRAST, 0, "BRIGHTCONTRAST", BrightContrast, "Bright/Contrast", "" )
DefNode( CompositorNode, CMP_NODE_GAMMA, 0, "GAMMA", Gamma, "Gamma", "" )
DefNode( CompositorNode, CMP_NODE_INVERT, def_cmp_invert, "INVERT", Invert, "Invert", "" )
DefNode( CompositorNode, CMP_NODE_NORMALIZE, 0, "NORMALIZE", Normalize, "Normalize", "" )
DefNode( CompositorNode, CMP_NODE_CROP, def_cmp_crop, "CROP", Crop, "Crop", "" )
DefNode( CompositorNode, CMP_NODE_DBLUR, def_cmp_dblur, "DBLUR", DBlur, "Directional Blur", "" )
DefNode( CompositorNode, CMP_NODE_BILATERALBLUR, def_cmp_bilateral_blur, "BILATERALBLUR", Bilateralblur, "Bilateral Blur", "" )
-DefNode( CompositorNode, CMP_NODE_PREMULKEY, def_cmp_premul_key, "PREMULKEY", PremulKey, "Premul Key", "" )
+DefNode( CompositorNode, CMP_NODE_PREMULKEY, def_cmp_premul_key, "PREMULKEY", PremulKey, "Alpha Convert", "" )
DefNode( CompositorNode, CMP_NODE_GLARE, def_cmp_glare, "GLARE", Glare, "Glare", "" )
DefNode( CompositorNode, CMP_NODE_TONEMAP, def_cmp_tonemap, "TONEMAP", Tonemap, "Tonemap", "" )
-DefNode( CompositorNode, CMP_NODE_LENSDIST, def_cmp_lensdist, "LENSDIST", Lensdist, "Lensdist", "" )
+DefNode( CompositorNode, CMP_NODE_LENSDIST, def_cmp_lensdist, "LENSDIST", Lensdist, "Lens Distortion", "" )
DefNode( CompositorNode, CMP_NODE_VIEW_LEVELS, def_cmp_levels, "LEVELS", Levels, "Levels", "" )
-DefNode( CompositorNode, CMP_NODE_COLOR_MATTE, def_cmp_color_matte, "COLOR_MATTE", ColorMatte, "Color Matte", "" )
-DefNode( CompositorNode, CMP_NODE_DIST_MATTE, def_cmp_distance_matte, "DISTANCE_MATTE", DistanceMatte, "Distance Matte", "" )
+DefNode( CompositorNode, CMP_NODE_COLOR_MATTE, def_cmp_color_matte, "COLOR_MATTE", ColorMatte, "Color Key", "" )
+DefNode( CompositorNode, CMP_NODE_DIST_MATTE, def_cmp_distance_matte, "DISTANCE_MATTE", DistanceMatte, "Distance Key", "" )
DefNode( CompositorNode, CMP_NODE_COLORBALANCE, def_cmp_colorbalance, "COLORBALANCE", ColorBalance, "Color Balance", "" )
DefNode( CompositorNode, CMP_NODE_HUECORRECT, def_cmp_huecorrect, "HUECORRECT", HueCorrect, "Hue Correct", "" )
-DefNode( CompositorNode, CMP_NODE_MOVIECLIP, def_cmp_movieclip, "MOVIECLIP", MovieClip, "MovieClip", "" )
+DefNode( CompositorNode, CMP_NODE_MOVIECLIP, def_cmp_movieclip, "MOVIECLIP", MovieClip, "Movie Clip", "" )
DefNode( CompositorNode, CMP_NODE_TRANSFORM, dev_cmd_transform, "TRANSFORM", Transform, "Transform", "" )
DefNode( CompositorNode, CMP_NODE_STABILIZE2D, def_cmp_stabilize2d, "STABILIZE2D", Stabilize, "Stabilize 2D", "" )
DefNode( CompositorNode, CMP_NODE_MOVIEDISTORTION,def_cmp_moviedistortion,"MOVIEDISTORTION",MovieDistortion, "Movie Distortion", "" )
-DefNode( CompositorNode, CMP_NODE_MASK_BOX, def_cmp_boxmask, "BOXMASK", BoxMask, "Box mask", "" )
-DefNode( CompositorNode, CMP_NODE_MASK_ELLIPSE, def_cmp_ellipsemask, "ELLIPSEMASK", EllipseMask, "Ellipse mask", "" )
-DefNode( CompositorNode, CMP_NODE_BOKEHIMAGE, def_cmp_bokehimage, "BOKEHIMAGE", BokehImage, "Bokeh image", "" )
+DefNode( CompositorNode, CMP_NODE_MASK_BOX, def_cmp_boxmask, "BOXMASK", BoxMask, "Box Mask", "" )
+DefNode( CompositorNode, CMP_NODE_MASK_ELLIPSE, def_cmp_ellipsemask, "ELLIPSEMASK", EllipseMask, "Ellipse Mask", "" )
+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_COLORCORRECTION,def_cmp_colorcorrection,"COLORCORRECTION",ColorCorrection, "ColorCorrection", "" )
+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, "KeyingScreen", "" )
+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( TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" )
DefNode( TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" )
DefNode( TextureNode, TEX_NODE_TEXTURE, def_texture, "TEXTURE", Texture, "Texture", "" )
@@ -192,7 +202,7 @@ DefNode( TextureNode, TEX_NODE_MIX_RGB, def_mix_rgb, "MIX_R
DefNode( TextureNode, TEX_NODE_RGBTOBW, 0, "RGBTOBW", RGBToBW, "RGB to BW", "" )
DefNode( TextureNode, TEX_NODE_VALTORGB, def_colorramp, "VALTORGB", ValToRGB, "ColorRamp", "" )
DefNode( TextureNode, TEX_NODE_IMAGE, def_tex_image, "IMAGE", Image, "Image", "" )
-DefNode( TextureNode, TEX_NODE_CURVE_RGB, def_rgb_curve, "CURVE_RGB", CurveRGB, "RGB Curve", "" )
+DefNode( TextureNode, TEX_NODE_CURVE_RGB, def_rgb_curve, "CURVE_RGB", CurveRGB, "RGB Curves", "" )
DefNode( TextureNode, TEX_NODE_INVERT, 0, "INVERT", Invert, "Invert", "" )
DefNode( TextureNode, TEX_NODE_HUE_SAT, 0, "HUE_SAT", HueSaturation, "Hue/Saturation", "" )
DefNode( TextureNode, TEX_NODE_CURVE_TIME, def_time, "CURVE_TIME", CurveTime, "Curve Time", "" )
@@ -201,10 +211,22 @@ DefNode( TextureNode, TEX_NODE_VIEWER, 0, "VIEWE
DefNode( TextureNode, TEX_NODE_TRANSLATE, 0, "TRANSLATE", Translate, "Translate", "" )
DefNode( TextureNode, TEX_NODE_COORD, 0, "COORD", Coordinates, "Coordinates", "" )
DefNode( TextureNode, TEX_NODE_DISTANCE, 0, "DISTANCE", Distance, "Distance", "" )
-DefNode( TextureNode, TEX_NODE_COMPOSE, 0, "COMPOSE", Compose, "Compose", "" )
-DefNode( TextureNode, TEX_NODE_DECOMPOSE, 0, "DECOMPOSE", Decompose, "Decompose", "" )
+DefNode( TextureNode, TEX_NODE_COMPOSE, 0, "COMPOSE", Compose, "Combine RGBA", "" )
+DefNode( TextureNode, TEX_NODE_DECOMPOSE, 0, "DECOMPOSE", Decompose, "Separate RGBA", "" )
DefNode( TextureNode, TEX_NODE_VALTONOR, 0, "VALTONOR", ValToNor, "Value to Normal", "" )
DefNode( TextureNode, TEX_NODE_SCALE, 0, "SCALE", Scale, "Scale", "" )
+DefNode( TextureNode, TEX_NODE_AT, 0, "AT", At, "At", "" )
+/* procedural textures */
+DefNode( TextureNode, TEX_NODE_PROC+TEX_VORONOI, 0, "TEX_VORONOI", TexVoronoi, "Voronoi", "" )
+DefNode( TextureNode, TEX_NODE_PROC+TEX_BLEND, 0, "TEX_BLEND", TexBlend, "Blend", "" )
+DefNode( TextureNode, TEX_NODE_PROC+TEX_MAGIC, 0, "TEX_MAGIC", TexMagic, "Magic", "" )
+DefNode( TextureNode, TEX_NODE_PROC+TEX_MARBLE, 0, "TEX_MARBLE", TexMarble, "Marble", "" )
+DefNode( TextureNode, TEX_NODE_PROC+TEX_CLOUDS, 0, "TEX_CLOUDS", TexClouds, "Clouds", "" )
+DefNode( TextureNode, TEX_NODE_PROC+TEX_WOOD, 0, "TEX_WOOD", TexWood, "Wood", "" )
+DefNode( TextureNode, TEX_NODE_PROC+TEX_MUSGRAVE, 0, "TEX_MUSGRAVE", TexMusgrave, "Musgrave", "" )
+DefNode( TextureNode, TEX_NODE_PROC+TEX_NOISE, 0, "TEX_NOISE", TexNoise, "Noise", "" )
+DefNode( TextureNode, TEX_NODE_PROC+TEX_STUCCI, 0, "TEX_STUCCI", TexStucci, "Stucci", "" )
+DefNode( TextureNode, TEX_NODE_PROC+TEX_DISTNOISE, 0, "TEX_DISTNOISE", TexDistNoise, "Distorted Noise", "" )
/* undefine macros */
diff --git a/source/blender/nodes/NOD_texture.h b/source/blender/nodes/NOD_texture.h
index a1be9963b8a..ea003f23960 100644
--- a/source/blender/nodes/NOD_texture.h
+++ b/source/blender/nodes/NOD_texture.h
@@ -34,48 +34,52 @@
#include "BKE_node.h"
-extern bNodeTreeType ntreeType_Texture;
+extern struct bNodeTreeType *ntreeType_Texture;
/* ****************** types array for all texture nodes ****************** */
-void register_node_type_tex_group(struct bNodeTreeType *ttype);
+void register_node_tree_type_tex(void);
-void register_node_type_tex_math(struct bNodeTreeType *ttype);
-void register_node_type_tex_mix_rgb(struct bNodeTreeType *ttype);
-void register_node_type_tex_valtorgb(struct bNodeTreeType *ttype);
-void register_node_type_tex_valtonor(struct bNodeTreeType *ttype);
-void register_node_type_tex_rgbtobw(struct bNodeTreeType *ttype);
-void register_node_type_tex_output(struct bNodeTreeType *ttype);
-void register_node_type_tex_viewer(struct bNodeTreeType *ttype);
-void register_node_type_tex_checker(struct bNodeTreeType *ttype);
-void register_node_type_tex_texture(struct bNodeTreeType *ttype);
-void register_node_type_tex_bricks(struct bNodeTreeType *ttype);
-void register_node_type_tex_image(struct bNodeTreeType *ttype);
-void register_node_type_tex_curve_rgb(struct bNodeTreeType *ttype);
-void register_node_type_tex_curve_time(struct bNodeTreeType *ttype);
-void register_node_type_tex_invert(struct bNodeTreeType *ttype);
-void register_node_type_tex_hue_sat(struct bNodeTreeType *ttype);
-void register_node_type_tex_coord(struct bNodeTreeType *ttype);
-void register_node_type_tex_distance(struct bNodeTreeType *ttype);
+void register_node_type_tex_group(void);
+void register_node_type_tex_forloop(void);
+void register_node_type_tex_whileloop(void);
-void register_node_type_tex_rotate(struct bNodeTreeType *ttype);
-void register_node_type_tex_translate(struct bNodeTreeType *ttype);
-void register_node_type_tex_scale(struct bNodeTreeType *ttype);
-void register_node_type_tex_at(struct bNodeTreeType *ttype);
+void register_node_type_tex_math(void);
+void register_node_type_tex_mix_rgb(void);
+void register_node_type_tex_valtorgb(void);
+void register_node_type_tex_valtonor(void);
+void register_node_type_tex_rgbtobw(void);
+void register_node_type_tex_output(void);
+void register_node_type_tex_viewer(void);
+void register_node_type_tex_checker(void);
+void register_node_type_tex_texture(void);
+void register_node_type_tex_bricks(void);
+void register_node_type_tex_image(void);
+void register_node_type_tex_curve_rgb(void);
+void register_node_type_tex_curve_time(void);
+void register_node_type_tex_invert(void);
+void register_node_type_tex_hue_sat(void);
+void register_node_type_tex_coord(void);
+void register_node_type_tex_distance(void);
-void register_node_type_tex_compose(struct bNodeTreeType *ttype);
-void register_node_type_tex_decompose(struct bNodeTreeType *ttype);
+void register_node_type_tex_rotate(void);
+void register_node_type_tex_translate(void);
+void register_node_type_tex_scale(void);
+void register_node_type_tex_at(void);
-void register_node_type_tex_proc_voronoi(struct bNodeTreeType *ttype);
-void register_node_type_tex_proc_blend(struct bNodeTreeType *ttype);
-void register_node_type_tex_proc_magic(struct bNodeTreeType *ttype);
-void register_node_type_tex_proc_marble(struct bNodeTreeType *ttype);
-void register_node_type_tex_proc_clouds(struct bNodeTreeType *ttype);
-void register_node_type_tex_proc_wood(struct bNodeTreeType *ttype);
-void register_node_type_tex_proc_musgrave(struct bNodeTreeType *ttype);
-void register_node_type_tex_proc_noise(struct bNodeTreeType *ttype);
-void register_node_type_tex_proc_stucci(struct bNodeTreeType *ttype);
-void register_node_type_tex_proc_distnoise(struct bNodeTreeType *ttype);
+void register_node_type_tex_compose(void);
+void register_node_type_tex_decompose(void);
+
+void register_node_type_tex_proc_voronoi(void);
+void register_node_type_tex_proc_blend(void);
+void register_node_type_tex_proc_magic(void);
+void register_node_type_tex_proc_marble(void);
+void register_node_type_tex_proc_clouds(void);
+void register_node_type_tex_proc_wood(void);
+void register_node_type_tex_proc_musgrave(void);
+void register_node_type_tex_proc_noise(void);
+void register_node_type_tex_proc_stucci(void);
+void register_node_type_tex_proc_distnoise(void);
#endif
diff --git a/source/blender/nodes/SConscript b/source/blender/nodes/SConscript
index ec4f00a199a..9f56689bf43 100644
--- a/source/blender/nodes/SConscript
+++ b/source/blender/nodes/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('intern/*.c')
@@ -40,9 +66,6 @@ if env['WITH_BF_COMPOSITOR']:
incs += ' ../compositor '
defs.append("WITH_COMPOSITOR")
-if env['WITH_BF_COMPOSITOR_LEGACY']:
- defs.append("WITH_COMPOSITOR_LEGACY")
-
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 03462738d58..841dde3302b 100644
--- a/source/blender/nodes/composite/node_composite_tree.c
+++ b/source/blender/nodes/composite/node_composite_tree.c
@@ -44,6 +44,7 @@
#include "BKE_animsys.h"
#include "BKE_colortools.h"
+#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -51,7 +52,6 @@
#include "BKE_tracking.h"
#include "node_common.h"
-#include "node_exec.h"
#include "node_util.h"
#include "PIL_time.h"
@@ -65,14 +65,17 @@
#include "COM_compositor.h"
#endif
-static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func)
+static void composite_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
{
- Scene *sce;
- for (sce= main->scene.first; sce; sce= sce->id.next) {
- if (sce->nodetree) {
- func(calldata, &sce->id, sce->nodetree);
- }
- }
+ Scene *scene = CTX_data_scene(C);
+
+ *r_from = NULL;
+ *r_id = &scene->id;
+ *r_ntree = scene->nodetree;
+
+ /* update output sockets based on available layers */
+ ntreeCompositForceHidden(scene->nodetree, scene);
+
}
static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCallback func)
@@ -86,6 +89,7 @@ static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCa
func(calldata, NODE_CLASS_MATTE, N_("Matte"));
func(calldata, NODE_CLASS_DISTORT, N_("Distort"));
func(calldata, NODE_CLASS_GROUP, N_("Group"));
+ func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
}
@@ -95,9 +99,6 @@ static void free_node_cache(bNodeTree *UNUSED(ntree), bNode *node)
for (sock= node->outputs.first; sock; sock= sock->next) {
if (sock->cache) {
-#ifdef WITH_COMPOSITOR_LEGACY
- free_compbuf(sock->cache);
-#endif
sock->cache= NULL;
}
}
@@ -106,33 +107,17 @@ static void free_node_cache(bNodeTree *UNUSED(ntree), bNode *node)
static void free_cache(bNodeTree *ntree)
{
bNode *node;
- for (node= ntree->nodes.first; node; node= node->next)
+ for (node = ntree->nodes.first; node; node = node->next)
free_node_cache(ntree, node);
}
-static void update_node(bNodeTree *ntree, bNode *node)
-{
- bNodeSocket *sock;
-
- for (sock= node->outputs.first; sock; sock= sock->next) {
- if (sock->cache) {
- //free_compbuf(sock->cache);
- //sock->cache= NULL;
- }
- }
- node->need_exec= 1;
- /* individual node update call */
- if (node->typeinfo->updatefunc)
- node->typeinfo->updatefunc(ntree, node);
-}
-
/* local tree then owns all compbufs */
static void localize(bNodeTree *localtree, bNodeTree *ntree)
{
bNode *node, *node_next;
bNodeSocket *sock;
- for (node= ntree->nodes.first; node; node= node->next) {
+ for (node = ntree->nodes.first; node; node = node->next) {
/* ensure new user input gets handled ok */
node->need_exec= 0;
node->new_node->original = node;
@@ -149,28 +134,15 @@ static void localize(bNodeTree *localtree, bNodeTree *ntree)
}
}
- /* copy over the preview buffers to update graduatly */
- if (node->preview) {
- bNodePreview *preview = MEM_callocN(sizeof(bNodePreview), "Preview");
- preview->pad = node->preview->pad;
- preview->xsize = node->preview->xsize;
- preview->ysize = node->preview->ysize;
- preview->rect = MEM_dupallocN(node->preview->rect);
- node->new_node->preview = preview;
- }
-
for (sock= node->outputs.first; sock; sock= sock->next) {
sock->new_sock->cache= sock->cache;
-#ifdef WITH_COMPOSITOR_LEGACY
- compbuf_set_node(sock->new_sock->cache, node->new_node);
-#endif
sock->cache= NULL;
sock->new_sock->new_sock= sock;
}
}
/* replace muted nodes and reroute nodes by internal links */
- for (node= localtree->nodes.first; node; node= node_next) {
+ for (node = localtree->nodes.first; node; node = node_next) {
node_next = node->next;
if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
@@ -192,22 +164,7 @@ static void localize(bNodeTree *localtree, bNodeTree *ntree)
static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
{
- bNode *lnode;
-
- /* move over the compbufs and previews */
- for (lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
- if ( (lnode->exec & NODE_READY) && !(lnode->exec & NODE_SKIPPED) ) {
- if (ntreeNodeExists(ntree, lnode->new_node)) {
-
- if (lnode->preview && lnode->preview->rect) {
- nodeFreePreview(lnode->new_node);
- lnode->new_node->preview= lnode->preview;
- lnode->preview= NULL;
- }
-
- }
- }
- }
+ BKE_node_preview_sync_tree(ntree, localtree);
}
static void local_merge(bNodeTree *localtree, bNodeTree *ntree)
@@ -216,6 +173,8 @@ static void local_merge(bNodeTree *localtree, bNodeTree *ntree)
bNodeSocket *lsock;
/* move over the compbufs and previews */
+ BKE_node_preview_merge_tree(ntree, localtree, true);
+
for (lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
if (ntreeNodeExists(ntree, lnode->new_node)) {
if (ELEM(lnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
@@ -239,9 +198,6 @@ static void local_merge(bNodeTree *localtree, bNodeTree *ntree)
for (lsock= lnode->outputs.first; lsock; lsock= lsock->next) {
if (ntreeOutputExists(lnode->new_node, lsock->new_sock)) {
lsock->new_sock->cache= lsock->cache;
-#ifdef WITH_COMPOSITOR_LEGACY
- compbuf_set_node(lsock->new_sock->cache, lnode->new_node);
-#endif
lsock->cache= NULL;
lsock->new_sock= NULL;
}
@@ -255,442 +211,38 @@ static void update(bNodeTree *ntree)
ntreeSetOutput(ntree);
ntree_update_reroute_nodes(ntree);
-}
-
-bNodeTreeType ntreeType_Composite = {
- /* type */ NTREE_COMPOSIT,
- /* idname */ "NTCompositing Nodetree",
-
- /* node_types */ { NULL, NULL },
-
- /* free_cache */ free_cache,
- /* free_node_cache */ free_node_cache,
- /* foreach_nodetree */ foreach_nodetree,
- /* foreach_nodeclass */ foreach_nodeclass,
- /* localize */ localize,
- /* local_sync */ local_sync,
- /* local_merge */ local_merge,
- /* update */ update,
- /* update_node */ update_node,
- /* validate_link */ NULL,
- /* update_internal_links */ node_update_internal_links_default
-};
-
-
-/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
- * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
- */
-struct bNodeTreeExec *ntreeCompositBeginExecTree(bNodeTree *ntree, int use_tree_data)
-{
- bNodeTreeExec *exec;
- bNode *node;
- bNodeSocket *sock;
-
- if (use_tree_data) {
- /* XXX hack: prevent exec data from being generated twice.
- * this should be handled by the renderer!
- */
- if (ntree->execdata)
- return ntree->execdata;
- }
-
- /* ensures only a single output node is enabled */
- ntreeSetOutput(ntree);
-
- exec = ntree_exec_begin(ntree);
-
- for (node= exec->nodetree->nodes.first; node; node= node->next) {
- /* initialize needed for groups */
- node->exec= 0;
-
- for (sock= node->outputs.first; sock; sock= sock->next) {
- bNodeStack *ns= node_get_socket_stack(exec->stack, sock);
- if (ns && sock->cache) {
- ns->data= sock->cache;
- sock->cache= NULL;
- }
- }
- /* cannot initialize them while using in threads */
- if (ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT)) {
- curvemapping_initialize(node->storage);
- if (node->type==CMP_NODE_CURVE_RGB)
- curvemapping_premultiply(node->storage, 0);
- }
- }
-
- if (use_tree_data) {
- /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
- * which only store the ntree pointer. Should be fixed at some point!
- */
- ntree->execdata = exec;
- }
-
- return exec;
-}
-
-/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
- * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
- */
-void ntreeCompositEndExecTree(bNodeTreeExec *exec, int use_tree_data)
-{
- if (exec) {
- bNodeTree *ntree= exec->nodetree;
- bNode *node;
- bNodeStack *ns;
-
- for (node= exec->nodetree->nodes.first; node; node= node->next) {
- bNodeSocket *sock;
-
- for (sock= node->outputs.first; sock; sock= sock->next) {
- ns = node_get_socket_stack(exec->stack, sock);
- if (ns && ns->data) {
- sock->cache= ns->data;
- ns->data= NULL;
- }
- }
- if (node->type==CMP_NODE_CURVE_RGB)
- curvemapping_premultiply(node->storage, 1);
-
- node->need_exec= 0;
- }
-
- ntree_exec_end(exec);
-
- if (use_tree_data) {
- /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
- ntree->execdata = NULL;
- }
- }
-}
-
-#ifdef WITH_COMPOSITOR
-#ifdef WITH_COMPOSITOR_LEGACY
-
-/* ***************************** threaded version for execute composite nodes ************* */
-/* these are nodes without input, only giving values */
-/* or nodes with only value inputs */
-static int node_only_value(bNode *node)
-{
- bNodeSocket *sock;
-
- if (ELEM3(node->type, CMP_NODE_TIME, CMP_NODE_VALUE, CMP_NODE_RGB))
- return 1;
-
- /* doing this for all node types goes wrong. memory free errors */
- if (node->inputs.first && node->type==CMP_NODE_MAP_VALUE) {
- int retval= 1;
- for (sock= node->inputs.first; sock; sock= sock->next) {
- if (sock->link)
- retval &= node_only_value(sock->link->fromnode);
- }
- return retval;
- }
- return 0;
-}
-
-/* not changing info, for thread callback */
-typedef struct ThreadData {
- bNodeStack *stack;
- RenderData *rd;
-} ThreadData;
-
-static void *exec_composite_node(void *nodeexec_v)
-{
- bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
- bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */
- bNodeExec *nodeexec= nodeexec_v;
- bNode *node= nodeexec->node;
- ThreadData *thd= (ThreadData *)node->threaddata;
-
- node_get_stack(node, thd->stack, nsin, nsout);
-
- if (node->typeinfo->execfunc)
- node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
- else if (node->typeinfo->newexecfunc)
- node->typeinfo->newexecfunc(thd->rd, 0, node, nodeexec->data, nsin, nsout);
-
- node->exec |= NODE_READY;
- return NULL;
-}
-
-/* return total of executable nodes, for timecursor */
-static int setExecutableNodes(bNodeTreeExec *exec, ThreadData *thd)
-{
- bNodeTree *ntree = exec->nodetree;
- bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
- bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */
- bNodeExec *nodeexec;
- bNode *node;
- bNodeSocket *sock;
- int n, totnode= 0, group_edit= 0;
-
- /* if we are in group edit, viewer nodes get skipped when group has viewer */
- for (node= ntree->nodes.first; node; node= node->next)
- if (node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT))
- if (ntreeHasType((bNodeTree *)node->id, CMP_NODE_VIEWER))
- group_edit= 1;
-
- /* NB: using the exec data list here to have valid dependency sort */
- for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
- int a;
- node = nodeexec->node;
-
- node_get_stack(node, exec->stack, nsin, nsout);
-
- /* test the outputs */
- /* skip value-only nodes (should be in type!) */
- if (!node_only_value(node)) {
- for (a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
- if (nsout[a]->data==NULL && nsout[a]->hasoutput) {
- node->need_exec= 1;
- break;
- }
- }
- }
-
- /* test the inputs */
- for (a=0, sock= node->inputs.first; sock; sock= sock->next, a++) {
- /* skip viewer nodes in bg render or group edit */
- if ( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) && (G.background || group_edit))
- node->need_exec= 0;
- /* is sock in use? */
- else if (sock->link) {
- bNodeLink *link= sock->link;
-
- /* this is the test for a cyclic case */
- if (link->fromnode==NULL || link->tonode==NULL);
- else if (link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) {
- if (link->fromnode->need_exec) {
- node->need_exec= 1;
- break;
- }
- }
- else {
- node->need_exec= 0;
- printf("Node %s skipped, cyclic dependency\n", node->name);
- }
- }
- }
-
- if (node->need_exec) {
-
- /* free output buffers */
- for (a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
- if (nsout[a]->data) {
- free_compbuf(nsout[a]->data);
- nsout[a]->data= NULL;
- }
- }
- totnode++;
- /* printf("node needs exec %s\n", node->name); */
-
- /* tag for getExecutableNode() */
- node->exec= 0;
- }
- else {
- /* tag for getExecutableNode() */
- node->exec= NODE_READY|NODE_FINISHED|NODE_SKIPPED;
-
- }
- }
-
- /* last step: set the stack values for only-value nodes */
- /* just does all now, compared to a full buffer exec this is nothing */
- if (totnode) {
- for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
- node = nodeexec->node;
- if (node->need_exec==0 && node_only_value(node)) {
- if (node->typeinfo->execfunc) {
- node_get_stack(node, exec->stack, nsin, nsout);
- node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
- }
- }
- }
- }
-
- return totnode;
-}
-
-/* while executing tree, free buffers from nodes that are not needed anymore */
-static void freeExecutableNode(bNodeTreeExec *exec)
-{
- /* node outputs can be freed when:
- * - not a render result or image node
- * - when node outputs go to nodes all being set NODE_FINISHED
- */
- bNodeTree *ntree = exec->nodetree;
- bNodeExec *nodeexec;
- bNode *node;
- bNodeSocket *sock;
- int n;
-
- /* set exec flag for finished nodes that might need freed */
- for (node= ntree->nodes.first; node; node= node->next) {
- if (node->type!=CMP_NODE_R_LAYERS)
- if (node->exec & NODE_FINISHED)
- node->exec |= NODE_FREEBUFS;
- }
- /* clear this flag for input links that are not done yet.
- * Using the exec data for valid dependency sort.
- */
- for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
- node = nodeexec->node;
- if ((node->exec & NODE_FINISHED)==0) {
- for (sock= node->inputs.first; sock; sock= sock->next)
- if (sock->link)
- sock->link->fromnode->exec &= ~NODE_FREEBUFS;
- }
- }
- /* now we can free buffers */
- for (node= ntree->nodes.first; node; node= node->next) {
- if (node->exec & NODE_FREEBUFS) {
- for (sock= node->outputs.first; sock; sock= sock->next) {
- bNodeStack *ns= node_get_socket_stack(exec->stack, sock);
- if (ns && ns->data) {
- free_compbuf(ns->data);
- ns->data= NULL;
- // printf("freed buf node %s\n", node->name);
- }
- }
- }
- }
-}
-
-static bNodeExec *getExecutableNode(bNodeTreeExec *exec)
-{
- bNodeExec *nodeexec;
- bNodeSocket *sock;
- int n;
- for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
- if (nodeexec->node->exec==0) {
- /* input sockets should be ready */
- for (sock= nodeexec->node->inputs.first; sock; sock= sock->next) {
- if (sock->link && sock->link->fromnode)
- if ((sock->link->fromnode->exec & NODE_READY)==0)
- break;
- }
- if (sock==NULL)
- return nodeexec;
- }
+ if (ntree->update & NTREE_UPDATE_NODES) {
+ /* clean up preview cache, in case nodes have been removed */
+ BKE_node_preview_remove_unused(ntree);
}
- return NULL;
}
-/* check if texture nodes need exec or end */
-static void ntree_composite_texnode(bNodeTree *ntree, int init)
-{
- bNode *node;
-
- for (node= ntree->nodes.first; node; node= node->next) {
- if (node->type==CMP_NODE_TEXTURE && node->id) {
- Tex *tex= (Tex *)node->id;
- if (tex->nodetree && tex->use_nodes) {
- /* has internal flag to detect it only does it once */
- if (init) {
- if (!tex->nodetree->execdata)
- tex->nodetree->execdata = ntreeTexBeginExecTree(tex->nodetree, 1);
- }
- else
- ntreeTexEndExecTree(tex->nodetree->execdata, 1);
- tex->nodetree->execdata = NULL;
- }
- }
- }
-
-}
+bNodeTreeType *ntreeType_Composite;
-/* optimized tree execute test for compositing */
-static void ntreeCompositExecTreeOld(bNodeTree *ntree, RenderData *rd, int do_preview)
+void register_node_tree_type_cmp(void)
{
- bNodeExec *nodeexec;
- bNode *node;
- ListBase threads;
- ThreadData thdata;
- int totnode, curnode, rendering = TRUE, n;
- bNodeTreeExec *exec = ntree->execdata;
-
- if (do_preview)
- ntreeInitPreview(ntree, 0, 0);
-
- if (!ntree->execdata) {
- /* XXX this is the top-level tree, so we use the ntree->execdata pointer. */
- exec = ntreeCompositBeginExecTree(ntree, 1);
- }
- ntree_composite_texnode(ntree, 1);
-
- /* prevent unlucky accidents */
- if (G.background)
- rd->scemode &= ~R_COMP_CROP;
-
- /* setup callerdata for thread callback */
- thdata.rd= rd;
- thdata.stack= exec->stack;
-
- /* fixed seed, for example noise texture */
- BLI_srandom(rd->cfra);
-
- /* sets need_exec tags in nodes */
- curnode = totnode= setExecutableNodes(exec, &thdata);
-
- BLI_init_threads(&threads, exec_composite_node, rd->threads);
-
- while (rendering) {
-
- if (BLI_available_threads(&threads)) {
- nodeexec= getExecutableNode(exec);
- if (nodeexec) {
- node = nodeexec->node;
- if (ntree->progress && totnode)
- ntree->progress(ntree->prh, (1.0f - curnode/(float)totnode));
- if (ntree->stats_draw) {
- char str[128];
- BLI_snprintf(str, sizeof(str), "Compositing %d %s", curnode, node->name);
- ntree->stats_draw(ntree->sdh, str);
- }
- curnode--;
-
- node->threaddata = &thdata;
- node->exec= NODE_PROCESSING;
- BLI_insert_thread(&threads, nodeexec);
- }
- else
- PIL_sleep_ms(50);
- }
- else
- PIL_sleep_ms(50);
-
- rendering= 0;
- /* test for ESC */
- if (ntree->test_break && ntree->test_break(ntree->tbh)) {
- for (node= ntree->nodes.first; node; node= node->next)
- node->exec |= NODE_READY;
- }
-
- /* check for ready ones, and if we need to continue */
- for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
- node = nodeexec->node;
- if (node->exec & NODE_READY) {
- if ((node->exec & NODE_FINISHED)==0) {
- BLI_remove_thread(&threads, nodeexec); /* this waits for running thread to finish btw */
- node->exec |= NODE_FINISHED;
-
- /* freeing unused buffers */
- if (rd->scemode & R_COMP_FREE)
- freeExecutableNode(exec);
- }
- }
- else rendering= 1;
- }
- }
-
- BLI_end_threads(&threads);
-
- /* XXX top-level tree uses the ntree->execdata pointer */
- ntreeCompositEndExecTree(exec, 1);
+ bNodeTreeType *tt = ntreeType_Composite = MEM_callocN(sizeof(bNodeTreeType), "compositor node tree type");
+
+ tt->type = NTREE_COMPOSIT;
+ strcpy(tt->idname, "CompositorNodeTree");
+ strcpy(tt->ui_name, "Compositing");
+ tt->ui_icon = 0; /* defined in drawnode.c */
+ strcpy(tt->ui_description, "");
+
+ tt->free_cache = free_cache;
+ tt->free_node_cache = free_node_cache;
+ tt->foreach_nodeclass = foreach_nodeclass;
+ tt->localize = localize;
+ tt->local_sync = local_sync;
+ tt->local_merge = local_merge;
+ tt->update = update;
+ tt->get_from_context = composite_get_from_context;
+
+ tt->ext.srna = &RNA_CompositorNodeTree;
+
+ ntreeTypeAdd(tt);
}
-#endif /* WITH_COMPOSITOR_LEGACY */
-#endif /* WITH_COMPOSITOR */
void *COM_linker_hack = NULL;
@@ -699,16 +251,7 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int rendering, int
const ColorManagedDisplaySettings *display_settings)
{
#ifdef WITH_COMPOSITOR
-#ifdef WITH_COMPOSITOR_LEGACY
- if (G.debug_value == 200)
- {
- ntreeCompositExecTreeOld(ntree, rd, do_preview);
- }
- else
-#endif
- {
- COM_execute(rd, ntree, rendering, view_settings, display_settings);
- }
+ COM_execute(rd, ntree, rendering, view_settings, display_settings);
#else
(void)ntree, (void)rd, (void)rendering, (void)do_preview;
(void)view_settings, (void)display_settings;
@@ -827,7 +370,8 @@ static int node_animation_properties(bNodeTree *ntree, bNode *node)
lb = RNA_struct_type_properties(ptr.type);
for (link = lb->first; link; link = link->next) {
- int driven, len = 1, index;
+ int len = 1, index;
+ bool driven;
prop = (PropertyRNA *)link;
if (RNA_property_array_check(prop))
@@ -843,7 +387,8 @@ static int node_animation_properties(bNodeTree *ntree, bNode *node)
/* now check node sockets */
for (sock = node->inputs.first; sock; sock = sock->next) {
- int driven, len = 1, index;
+ int len = 1, index;
+ bool driven;
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
prop = RNA_struct_find_property(&ptr, "default_value");
diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c
index 57eb99021f6..02a5f410d83 100644
--- a/source/blender/nodes/composite/node_composite_util.c
+++ b/source/blender/nodes/composite/node_composite_util.c
@@ -31,1382 +31,29 @@
#include "node_composite_util.h"
-#ifdef WITH_COMPOSITOR_LEGACY
-#include <limits.h>
-
-CompBuf *alloc_compbuf(int sizex, int sizey, int type, int alloc)
-{
- CompBuf *cbuf= MEM_callocN(sizeof(CompBuf), "compbuf");
-
- cbuf->x= sizex;
- cbuf->y= sizey;
- cbuf->xrad= sizex/2;
- cbuf->yrad= sizey/2;
-
- cbuf->type= type;
- if (alloc) {
- if (cbuf->type==CB_RGBA)
- cbuf->rect= MEM_mapallocN(4*sizeof(float)*sizex*sizey, "compbuf RGBA rect");
- else if (cbuf->type==CB_VEC3)
- cbuf->rect= MEM_mapallocN(3*sizeof(float)*sizex*sizey, "compbuf Vector3 rect");
- else if (cbuf->type==CB_VEC2)
- cbuf->rect= MEM_mapallocN(2*sizeof(float)*sizex*sizey, "compbuf Vector2 rect");
- else
- cbuf->rect= MEM_mapallocN(sizeof(float)*sizex*sizey, "compbuf Fac rect");
- cbuf->malloc= 1;
- }
- cbuf->disprect.xmin = 0;
- cbuf->disprect.ymin = 0;
- cbuf->disprect.xmax = sizex;
- cbuf->disprect.ymax = sizey;
-
- return cbuf;
-}
-
-CompBuf *dupalloc_compbuf(CompBuf *cbuf)
-{
- CompBuf *dupbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1);
- if (dupbuf) {
- memcpy(dupbuf->rect, cbuf->rect, cbuf->type*sizeof(float)*cbuf->x*cbuf->y);
-
- dupbuf->xof= cbuf->xof;
- dupbuf->yof= cbuf->yof;
- }
- return dupbuf;
-}
-
-/* instead of reference counting, we create a list */
-CompBuf *pass_on_compbuf(CompBuf *cbuf)
-{
- CompBuf *dupbuf= (cbuf)? alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 0): NULL;
- CompBuf *lastbuf;
-
- if (dupbuf) {
- dupbuf->rect= cbuf->rect;
- dupbuf->xof= cbuf->xof;
- dupbuf->yof= cbuf->yof;
- dupbuf->malloc= 0;
-
- /* get last buffer in list, and append dupbuf */
- for (lastbuf= cbuf; lastbuf; lastbuf= lastbuf->next)
- if (lastbuf->next==NULL)
- break;
- lastbuf->next= dupbuf;
- dupbuf->prev= lastbuf;
- }
- return dupbuf;
-}
-
-
-void free_compbuf(CompBuf *cbuf)
-{
- /* check referencing, then remove from list and set malloc tag */
- if (cbuf->prev || cbuf->next) {
- if (cbuf->prev)
- cbuf->prev->next= cbuf->next;
- if (cbuf->next)
- cbuf->next->prev= cbuf->prev;
- if (cbuf->malloc) {
- if (cbuf->prev)
- cbuf->prev->malloc= 1;
- else
- cbuf->next->malloc= 1;
- cbuf->malloc= 0;
- }
- }
-
- if (cbuf->malloc && cbuf->rect)
- MEM_freeN(cbuf->rect);
-
- MEM_freeN(cbuf);
-}
-
-void print_compbuf(char *str, CompBuf *cbuf)
-{
- printf("Compbuf %s %d %d %p\n", str, cbuf->x, cbuf->y, (void *)cbuf->rect);
-
-}
-
-void compbuf_set_node(CompBuf *cbuf, bNode *node)
-{
- if (cbuf) cbuf->node = node;
-}
-
-
-CompBuf *get_cropped_compbuf(rcti *drect, float *rectf, int rectx, int recty, int type)
-{
- CompBuf *cbuf;
- rcti disprect= *drect;
- float *outfp;
- int dx, y;
-
- if (disprect.xmax>rectx) disprect.xmax = rectx;
- if (disprect.ymax>recty) disprect.ymax = recty;
- if (disprect.xmin>= disprect.xmax) return NULL;
- if (disprect.ymin>= disprect.ymax) return NULL;
-
- cbuf= alloc_compbuf(BLI_rcti_size_x(&disprect), BLI_rcti_size_y(&disprect), type, 1);
- outfp= cbuf->rect;
- rectf += type*(disprect.ymin*rectx + disprect.xmin);
- dx= type*cbuf->x;
- for (y=cbuf->y; y>0; y--, outfp+=dx, rectf+=type*rectx)
- memcpy(outfp, rectf, sizeof(float)*dx);
-
- return cbuf;
-}
-
-CompBuf *scalefast_compbuf(CompBuf *inbuf, int newx, int newy)
-{
- CompBuf *outbuf;
- float *rectf, *newrectf, *rf;
- int x, y, c, pixsize= inbuf->type;
- int ofsx, ofsy, stepx, stepy;
-
- if (inbuf->x==newx && inbuf->y==newy)
- return dupalloc_compbuf(inbuf);
-
- outbuf= alloc_compbuf(newx, newy, inbuf->type, 1);
- newrectf= outbuf->rect;
-
- stepx = (65536.0 * (inbuf->x - 1.0) / (newx - 1.0)) + 0.5;
- stepy = (65536.0 * (inbuf->y - 1.0) / (newy - 1.0)) + 0.5;
- ofsy = 32768;
-
- for (y = newy; y > 0 ; y--) {
- rectf = inbuf->rect;
- rectf += pixsize * (ofsy >> 16) * inbuf->x;
-
- ofsy += stepy;
- ofsx = 32768;
-
- for (x = newx ; x>0 ; x--) {
-
- rf= rectf + pixsize*(ofsx >> 16);
- for (c=0; c<pixsize; c++)
- newrectf[c] = rf[c];
-
- newrectf+= pixsize;
-
- ofsx += stepx;
- }
- }
-
- return outbuf;
-}
-
-void typecheck_compbuf_color(float *out, float *in, int outtype, int intype)
-{
- if (intype == outtype) {
- memcpy(out, in, sizeof(float)*outtype);
- }
- else if (outtype==CB_VAL) {
- if (intype==CB_VEC2) {
- *out= 0.5f*(in[0]+in[1]);
- }
- else if (intype==CB_VEC3) {
- *out= 0.333333f*(in[0]+in[1]+in[2]);
- }
- else if (intype==CB_RGBA) {
- *out = rgb_to_bw(in);
- }
- }
- else if (outtype==CB_VEC2) {
- if (intype==CB_VAL) {
- out[0] = in[0];
- out[1] = in[0];
- }
- else if (intype==CB_VEC3) {
- out[0] = in[0];
- out[1] = in[1];
- }
- else if (intype==CB_RGBA) {
- out[0] = in[0];
- out[1] = in[1];
- }
- }
- else if (outtype==CB_VEC3) {
- if (intype==CB_VAL) {
- out[0] = in[0];
- out[1] = in[0];
- out[2] = in[0];
- }
- else if (intype==CB_VEC2) {
- out[0] = in[0];
- out[1] = in[1];
- out[2] = 0.0f;
- }
- else if (intype==CB_RGBA) {
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
- }
- }
- else if (outtype==CB_RGBA) {
- if (intype==CB_VAL) {
- out[0] = in[0];
- out[1] = in[0];
- out[2] = in[0];
- out[3] = 1.0f;
- }
- else if (intype==CB_VEC2) {
- out[0] = in[0];
- out[1] = in[1];
- out[2] = 0.0f;
- out[3] = 1.0f;
- }
- else if (intype==CB_VEC3) {
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
- out[3] = 1.0f;
- }
- }
-}
-
-CompBuf *typecheck_compbuf(CompBuf *inbuf, int type)
-{
- if (inbuf && inbuf->type!=type) {
- CompBuf *outbuf;
- float *inrf, *outrf;
- int x;
-
- outbuf= alloc_compbuf(inbuf->x, inbuf->y, type, 1);
-
- /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */
- outbuf->xof= inbuf->xof;
- outbuf->yof= inbuf->yof;
-
- if (inbuf->rect_procedural) {
- outbuf->rect_procedural= inbuf->rect_procedural;
- copy_v3_v3(outbuf->procedural_size, inbuf->procedural_size);
- copy_v3_v3(outbuf->procedural_offset, inbuf->procedural_offset);
- outbuf->procedural_type= inbuf->procedural_type;
- outbuf->node= inbuf->node;
- return outbuf;
- }
-
- inrf= inbuf->rect;
- outrf= outbuf->rect;
- x= inbuf->x*inbuf->y;
-
- if (type==CB_VAL) {
- if (inbuf->type==CB_VEC2) {
- for (; x>0; x--, outrf+= 1, inrf+= 2)
- *outrf= 0.5f*(inrf[0]+inrf[1]);
- }
- else if (inbuf->type==CB_VEC3) {
- for (; x>0; x--, outrf+= 1, inrf+= 3)
- *outrf= 0.333333f*(inrf[0]+inrf[1]+inrf[2]);
- }
- else if (inbuf->type==CB_RGBA) {
- for (; x>0; x--, outrf+= 1, inrf+= 4)
- *outrf = rgb_to_bw(inrf);
- }
- }
- else if (type==CB_VEC2) {
- if (inbuf->type==CB_VAL) {
- for (; x>0; x--, outrf+= 2, inrf+= 1) {
- outrf[0] = inrf[0];
- outrf[1] = inrf[0];
- }
- }
- else if (inbuf->type==CB_VEC3) {
- for (; x>0; x--, outrf+= 2, inrf+= 3) {
- outrf[0] = inrf[0];
- outrf[1] = inrf[1];
- }
- }
- else if (inbuf->type==CB_RGBA) {
- for (; x>0; x--, outrf+= 2, inrf+= 4) {
- outrf[0] = inrf[0];
- outrf[1] = inrf[1];
- }
- }
- }
- else if (type==CB_VEC3) {
- if (inbuf->type==CB_VAL) {
- for (; x>0; x--, outrf+= 3, inrf+= 1) {
- outrf[0] = inrf[0];
- outrf[1] = inrf[0];
- outrf[2] = inrf[0];
- }
- }
- else if (inbuf->type==CB_VEC2) {
- for (; x>0; x--, outrf+= 3, inrf+= 2) {
- outrf[0] = inrf[0];
- outrf[1] = inrf[1];
- outrf[2] = 0.0f;
- }
- }
- else if (inbuf->type==CB_RGBA) {
- for (; x>0; x--, outrf+= 3, inrf+= 4) {
- outrf[0] = inrf[0];
- outrf[1] = inrf[1];
- outrf[2] = inrf[2];
- }
- }
- }
- else if (type==CB_RGBA) {
- if (inbuf->type==CB_VAL) {
- for (; x>0; x--, outrf+= 4, inrf+= 1) {
- outrf[0] = inrf[0];
- outrf[1] = inrf[0];
- outrf[2] = inrf[0];
- outrf[3] = 1.0f;
- }
- }
- else if (inbuf->type==CB_VEC2) {
- for (; x>0; x--, outrf+= 4, inrf+= 2) {
- outrf[0] = inrf[0];
- outrf[1] = inrf[1];
- outrf[2] = 0.0f;
- outrf[3] = 1.0f;
- }
- }
- else if (inbuf->type==CB_VEC3) {
- for (; x>0; x--, outrf+= 4, inrf+= 3) {
- outrf[0] = inrf[0];
- outrf[1] = inrf[1];
- outrf[2] = inrf[2];
- outrf[3] = 1.0f;
- }
- }
- }
-
- return outbuf;
- }
- return inbuf;
-}
-
-float *compbuf_get_pixel(CompBuf *cbuf, float *defcol, float *use, int x, int y, int xrad, int yrad)
-{
- if (cbuf) {
- if (cbuf->rect_procedural) {
- cbuf->rect_procedural(cbuf, use, (float)x/(float)xrad, (float)y/(float)yrad);
- return use;
- }
- else {
- static float col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
-
- /* map coords */
- x-= cbuf->xof;
- y-= cbuf->yof;
-
- if (y<-cbuf->yrad || y>= -cbuf->yrad+cbuf->y) return col;
- if (x<-cbuf->xrad || x>= -cbuf->xrad+cbuf->x) return col;
-
- return cbuf->rect + cbuf->type*( (cbuf->yrad+y)*cbuf->x + (cbuf->xrad+x) );
- }
- }
- else return defcol;
-}
-
-/* **************************************************** */
-
-static CompBuf *composit_check_compbuf(CompBuf *cbuf, int type, CompBuf *outbuf)
-{
- /* check type */
- CompBuf *dbuf= typecheck_compbuf(cbuf, type);
-
- /* if same as output and translated, duplicate so pixels don't interfere */
- if (dbuf == outbuf && !dbuf->rect_procedural && (dbuf->xof || dbuf->yof))
- dbuf= dupalloc_compbuf(dbuf);
-
- return dbuf;
-}
-
-/* Pixel-to-Pixel operation, 1 Image in, 1 out */
-void composit1_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col,
- void (*func)(bNode *, float *, float *),
- int src_type)
+int cmp_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree)
{
- CompBuf *src_use;
- float *outfp=out->rect, *srcfp;
- float color[4]; /* local color if compbuf is procedural */
- int xrad, yrad, x, y;
-
- src_use= composit_check_compbuf(src_buf, src_type, out);
-
- xrad= out->xrad;
- yrad= out->yrad;
-
- for (y= -yrad; y<-yrad+out->y; y++) {
- for (x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
- srcfp= compbuf_get_pixel(src_use, src_col, color, x, y, xrad, yrad);
- func(node, outfp, srcfp);
- }
- }
-
- if (src_use!=src_buf)
- free_compbuf(src_use);
+ return (strcmp(ntree->idname, "CompositorNodeTree")==0);
}
-/* Pixel-to-Pixel operation, 2 Images in, 1 out */
-void composit2_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col,
- CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *),
- int src_type, int fac_type)
+void cmp_node_update_default(bNodeTree *UNUSED(ntree), bNode *node)
{
- CompBuf *src_use, *fac_use;
- float *outfp=out->rect, *srcfp, *facfp;
- float color[4]; /* local color if compbuf is procedural */
- int xrad, yrad, x, y;
-
- src_use= composit_check_compbuf(src_buf, src_type, out);
- fac_use= composit_check_compbuf(fac_buf, fac_type, out);
-
- xrad= out->xrad;
- yrad= out->yrad;
-
- for (y= -yrad; y<-yrad+out->y; y++) {
- for (x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
- srcfp= compbuf_get_pixel(src_use, src_col, color, x, y, xrad, yrad);
- facfp= compbuf_get_pixel(fac_use, fac, color, x, y, xrad, yrad);
-
- func(node, outfp, srcfp, facfp);
+ bNodeSocket *sock;
+ for (sock= node->outputs.first; sock; sock= sock->next) {
+ if (sock->cache) {
+ //free_compbuf(sock->cache);
+ //sock->cache= NULL;
}
}
- if (src_use!=src_buf)
- free_compbuf(src_use);
- if (fac_use!=fac_buf)
- free_compbuf(fac_use);
+ node->need_exec= 1;
}
-/* Pixel-to-Pixel operation, 3 Images in, 1 out */
-void composit3_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *src2_buf, float *src2_col,
- CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *, float *),
- int src1_type, int src2_type, int fac_type)
+void cmp_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag)
{
- CompBuf *src1_use, *src2_use, *fac_use;
- float *outfp=out->rect, *src1fp, *src2fp, *facfp;
- float color[4]; /* local color if compbuf is procedural */
- int xrad, yrad, x, y;
-
- src1_use= composit_check_compbuf(src1_buf, src1_type, out);
- src2_use= composit_check_compbuf(src2_buf, src2_type, out);
- fac_use= composit_check_compbuf(fac_buf, fac_type, out);
-
- xrad= out->xrad;
- yrad= out->yrad;
-
- for (y= -yrad; y<-yrad+out->y; y++) {
- for (x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
- src1fp= compbuf_get_pixel(src1_use, src1_col, color, x, y, xrad, yrad);
- src2fp= compbuf_get_pixel(src2_use, src2_col, color, x, y, xrad, yrad);
- facfp= compbuf_get_pixel(fac_use, fac, color, x, y, xrad, yrad);
-
- func(node, outfp, src1fp, src2fp, facfp);
- }
- }
-
- if (src1_use!=src1_buf)
- free_compbuf(src1_use);
- if (src2_use!=src2_buf)
- free_compbuf(src2_use);
- if (fac_use!=fac_buf)
- free_compbuf(fac_use);
-}
-
-/* Pixel-to-Pixel operation, 4 Images in, 1 out */
-void composit4_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *fac1_buf, float *fac1,
- CompBuf *src2_buf, float *src2_col, CompBuf *fac2_buf, float *fac2,
- void (*func)(bNode *, float *, float *, float *, float *, float *),
- int src1_type, int fac1_type, int src2_type, int fac2_type)
-{
- CompBuf *src1_use, *src2_use, *fac1_use, *fac2_use;
- float *outfp=out->rect, *src1fp, *src2fp, *fac1fp, *fac2fp;
- float color[4]; /* local color if compbuf is procedural */
- int xrad, yrad, x, y;
-
- src1_use= composit_check_compbuf(src1_buf, src1_type, out);
- src2_use= composit_check_compbuf(src2_buf, src2_type, out);
- fac1_use= composit_check_compbuf(fac1_buf, fac1_type, out);
- fac2_use= composit_check_compbuf(fac2_buf, fac2_type, out);
-
- xrad= out->xrad;
- yrad= out->yrad;
-
- for (y= -yrad; y<-yrad+out->y; y++) {
- for (x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
- src1fp= compbuf_get_pixel(src1_use, src1_col, color, x, y, xrad, yrad);
- src2fp= compbuf_get_pixel(src2_use, src2_col, color, x, y, xrad, yrad);
- fac1fp= compbuf_get_pixel(fac1_use, fac1, color, x, y, xrad, yrad);
- fac2fp= compbuf_get_pixel(fac2_use, fac2, color, x, y, xrad, yrad);
-
- func(node, outfp, src1fp, fac1fp, src2fp, fac2fp);
- }
- }
-
- if (src1_use!=src1_buf)
- free_compbuf(src1_use);
- if (src2_use!=src2_buf)
- free_compbuf(src2_use);
- if (fac1_use!=fac1_buf)
- free_compbuf(fac1_use);
- if (fac2_use!=fac2_buf)
- free_compbuf(fac2_use);
-}
-
-
-CompBuf *valbuf_from_rgbabuf(CompBuf *cbuf, int channel)
-{
- CompBuf *valbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1);
- float *valf, *rectf;
- int tot;
-
- /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */
- valbuf->xof= cbuf->xof;
- valbuf->yof= cbuf->yof;
-
- valf= valbuf->rect;
-
- /* defaults to returning alpha channel */
- if ((channel < CHAN_R) || (channel > CHAN_A)) channel = CHAN_A;
-
- rectf= cbuf->rect + channel;
+ node_type_base(ntype, type, name, nclass, flag);
- for (tot= cbuf->x*cbuf->y; tot>0; tot--, valf++, rectf+=4)
- *valf= *rectf;
-
- return valbuf;
-}
-
-void valbuf_to_rgbabuf(CompBuf *valbuf, CompBuf *cbuf, int channel)
-{
- float *valf, *rectf;
- int tot;
-
- valf= valbuf->rect;
-
- /* defaults to returning alpha channel */
- if ((channel < CHAN_R) || (channel > CHAN_A)) channel = CHAN_A;
-
- rectf = cbuf->rect + channel;
-
- for (tot= cbuf->x*cbuf->y; tot>0; tot--, valf++, rectf+=4)
- *rectf = *valf;
-}
-
-static CompBuf *generate_procedural_preview(CompBuf *cbuf, int newx, int newy)
-{
- CompBuf *outbuf;
- float *outfp;
- int xrad, yrad, x, y;
-
- outbuf= alloc_compbuf(newx, newy, CB_RGBA, 1);
-
- outfp= outbuf->rect;
- xrad= outbuf->xrad;
- yrad= outbuf->yrad;
-
- for (y= -yrad; y<-yrad+outbuf->y; y++)
- for (x= -xrad; x<-xrad+outbuf->x; x++, outfp+=outbuf->type)
- cbuf->rect_procedural(cbuf, outfp, (float)x/(float)xrad, (float)y/(float)yrad);
-
- return outbuf;
-}
-
-/* OCIO_TODO: this function is only used by legacy compositor system only, which would likely be removed soon,
- * keep check for old color management flag for now
- */
-void generate_preview(void *data, bNode *node, CompBuf *stackbuf)
-{
- RenderData *rd= data;
- bNodePreview *preview= node->preview;
- int xsize, ysize;
- int profile_from= (rd->color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
- int predivide= (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
- int dither= 0;
- unsigned char *rect;
-
- if (preview && stackbuf) {
- CompBuf *cbuf, *stackbuf_use;
-
- if (stackbuf->rect==NULL && stackbuf->rect_procedural==NULL) return;
-
- stackbuf_use= typecheck_compbuf(stackbuf, CB_RGBA);
-
- if (stackbuf->x > stackbuf->y) {
- xsize= 140;
- ysize= (140*stackbuf->y)/stackbuf->x;
- }
- else {
- ysize= 140;
- xsize= (140*stackbuf->x)/stackbuf->y;
- }
-
- if (stackbuf_use->rect_procedural)
- cbuf= generate_procedural_preview(stackbuf_use, xsize, ysize);
- else
- cbuf= scalefast_compbuf(stackbuf_use, xsize, ysize);
-
- /* convert to byte for preview */
- rect= MEM_callocN(sizeof(unsigned char)*4*xsize*ysize, "bNodePreview.rect");
-
- IMB_buffer_byte_from_float(rect, cbuf->rect,
- 4, dither, IB_PROFILE_SRGB, profile_from, predivide,
- xsize, ysize, xsize, xsize);
-
- free_compbuf(cbuf);
- if (stackbuf_use!=stackbuf)
- free_compbuf(stackbuf_use);
-
- // BLI_lock_thread(LOCK_PREVIEW);
-
- if (preview->rect)
- MEM_freeN(preview->rect);
- preview->xsize= xsize;
- preview->ysize= ysize;
- preview->rect= rect;
-
- // BLI_unlock_thread(LOCK_PREVIEW);
- }
-}
-
-void do_rgba_to_yuva(bNode *UNUSED(node), float *out, float *in)
-{
- rgb_to_yuv(in[0], in[1], in[2], &out[0], &out[1], &out[2]);
- out[3]=in[3];
-}
-
-void do_rgba_to_hsva(bNode *UNUSED(node), float *out, float *in)
-{
- rgb_to_hsv(in[0], in[1], in[2], &out[0], &out[1], &out[2]);
- out[3]=in[3];
-}
-
-void do_rgba_to_ycca(bNode *UNUSED(node), float *out, float *in)
-{
- rgb_to_ycc(in[0], in[1], in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601);
- out[3]=in[3];
-}
-
-void do_yuva_to_rgba(bNode *UNUSED(node), float *out, float *in)
-{
- yuv_to_rgb(in[0], in[1], in[2], &out[0], &out[1], &out[2]);
- out[3]=in[3];
-}
-
-void do_hsva_to_rgba(bNode *UNUSED(node), float *out, float *in)
-{
- hsv_to_rgb(in[0], in[1], in[2], &out[0], &out[1], &out[2]);
- out[3]=in[3];
-}
-
-void do_ycca_to_rgba(bNode *UNUSED(node), float *out, float *in)
-{
- ycc_to_rgb(in[0], in[1], in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601);
- out[3]=in[3];
-}
-
-void do_copy_rgba(bNode *UNUSED(node), float *out, float *in)
-{
- copy_v4_v4(out, in);
-}
-
-void do_copy_rgb(bNode *UNUSED(node), float *out, float *in)
-{
- copy_v3_v3(out, in);
- out[3] = 1.0f;
-}
-
-void do_copy_value(bNode *UNUSED(node), float *out, float *in)
-{
- out[0] = in[0];
-}
-
-void do_copy_a_rgba(bNode *UNUSED(node), float *out, float *in, float *fac)
-{
- copy_v3_v3(out, in);
- out[3] = *fac;
-}
-
-/* only accepts RGBA buffers */
-void gamma_correct_compbuf(CompBuf *img, int inversed)
-{
- float *drect;
- int x;
-
- if (img->type!=CB_RGBA) return;
-
- drect= img->rect;
- if (inversed) {
- for (x=img->x*img->y; x>0; x--, drect+=4) {
- if (drect[0]>0.0f) drect[0] = sqrt(drect[0]); else drect[0] = 0.0f;
- if (drect[1]>0.0f) drect[1] = sqrt(drect[1]); else drect[1] = 0.0f;
- if (drect[2]>0.0f) drect[2] = sqrt(drect[2]); else drect[2] = 0.0f;
- }
- }
- else {
- for (x=img->x*img->y; x>0; x--, drect+=4) {
- if (drect[0]>0.0f) drect[0]*= drect[0]; else drect[0] = 0.0f;
- if (drect[1]>0.0f) drect[1]*= drect[1]; else drect[1] = 0.0f;
- if (drect[2]>0.0f) drect[2]*= drect[2]; else drect[2] = 0.0f;
- }
- }
-}
-
-void premul_compbuf(CompBuf *img, int inversed)
-{
- float *drect;
- int x;
-
- if (img->type!=CB_RGBA) return;
-
- drect= img->rect;
- if (inversed) {
- for (x=img->x*img->y; x>0; x--, drect+=4) {
- if (fabsf(drect[3]) < 1e-5f) {
- drect[0] = 0.0f;
- drect[1] = 0.0f;
- drect[2] = 0.0f;
- }
- else {
- drect[0] /= drect[3];
- drect[1] /= drect[3];
- drect[2] /= drect[3];
- }
- }
- }
- else {
- for (x=img->x*img->y; x>0; x--, drect+=4) {
- drect[0] *= drect[3];
- drect[1] *= drect[3];
- drect[2] *= drect[3];
- }
- }
-}
-
-
-
-/*
- * 2D Fast Hartley Transform, used for convolution
- */
-
-typedef float fREAL;
-
-// returns next highest power of 2 of x, as well it's log2 in L2
-static unsigned int nextPow2(unsigned int x, unsigned int* L2)
-{
- unsigned int pw, x_notpow2 = x & (x-1);
- *L2 = 0;
- while (x>>=1) ++(*L2);
- pw = 1 << (*L2);
- if (x_notpow2) { (*L2)++; pw<<=1; }
- return pw;
-}
-
-//------------------------------------------------------------------------------
-
-// from FXT library by Joerg Arndt, faster in order bitreversal
-// use: r = revbin_upd(r, h) where h = N>>1
-static unsigned int revbin_upd(unsigned int r, unsigned int h)
-{
- while (!((r^=h)&h)) h >>= 1;
- return r;
-}
-//------------------------------------------------------------------------------
-static void FHT(fREAL* data, unsigned int M, unsigned int inverse)
-{
- double tt, fc, dc, fs, ds, a = M_PI;
- fREAL t1, t2;
- int n2, bd, bl, istep, k, len = 1 << M, n = 1;
-
- int i, j = 0;
- unsigned int Nh = len >> 1;
- for (i=1;i<(len-1);++i) {
- j = revbin_upd(j, Nh);
- if (j>i) {
- t1 = data[i];
- data[i] = data[j];
- data[j] = t1;
- }
- }
-
- do {
- fREAL* data_n = &data[n];
-
- istep = n << 1;
- for (k=0; k<len; k+=istep) {
- t1 = data_n[k];
- data_n[k] = data[k] - t1;
- data[k] += t1;
- }
-
- n2 = n >> 1;
- if (n>2) {
- fc = dc = cos(a);
- fs = ds = sqrt(1.0 - fc*fc); //sin(a);
- bd = n-2;
- for (bl=1; bl<n2; bl++) {
- fREAL* data_nbd = &data_n[bd];
- fREAL* data_bd = &data[bd];
- for (k=bl; k<len; k+=istep) {
- t1 = fc*data_n[k] + fs*data_nbd[k];
- t2 = fs*data_n[k] - fc*data_nbd[k];
- data_n[k] = data[k] - t1;
- data_nbd[k] = data_bd[k] - t2;
- data[k] += t1;
- data_bd[k] += t2;
- }
- tt = fc*dc - fs*ds;
- fs = fs*dc + fc*ds;
- fc = tt;
- bd -= 2;
- }
- }
-
- if (n>1) {
- for (k=n2; k<len; k+=istep) {
- t1 = data_n[k];
- data_n[k] = data[k] - t1;
- data[k] += t1;
- }
- }
-
- n = istep;
- a *= 0.5;
- } while (n<len);
-
- if (inverse) {
- fREAL sc = (fREAL)1 / (fREAL)len;
- for (k=0; k<len; ++k)
- data[k] *= sc;
- }
-}
-//------------------------------------------------------------------------------
-/* 2D Fast Hartley Transform, Mx/My -> log2 of width/height,
- * nzp -> the row where zero pad data starts,
- * inverse -> see above */
-static void FHT2D(fREAL *data, unsigned int Mx, unsigned int My,
- unsigned int nzp, unsigned int inverse)
-{
- unsigned int i, j, Nx, Ny, maxy;
- fREAL t;
-
- Nx = 1 << Mx;
- Ny = 1 << My;
-
- // rows (forward transform skips 0 pad data)
- maxy = inverse ? Ny : nzp;
- for (j=0; j<maxy; ++j)
- FHT(&data[Nx*j], Mx, inverse);
-
- // transpose data
- if (Nx==Ny) { // square
- for (j=0; j<Ny; ++j)
- for (i=j+1; i<Nx; ++i) {
- unsigned int op = i + (j << Mx), np = j + (i << My);
- t=data[op], data[op]=data[np], data[np]=t;
- }
- }
- else { // rectangular
- unsigned int k, Nym = Ny-1, stm = 1 << (Mx + My);
- for (i=0; stm>0; i++) {
- #define PRED(k) (((k & Nym) << Mx) + (k >> My))
- for (j=PRED(i); j>i; j=PRED(j));
- if (j < i) continue;
- for (k=i, j=PRED(i); j!=i; k=j, j=PRED(j), stm--) {
- t=data[j], data[j]=data[k], data[k]=t;
- }
- #undef PRED
- stm--;
- }
- }
- // swap Mx/My & Nx/Ny
- i = Nx, Nx = Ny, Ny = i;
- i = Mx, Mx = My, My = i;
-
- // now columns == transposed rows
- for (j=0; j<Ny; ++j)
- FHT(&data[Nx*j], Mx, inverse);
-
- // finalize
- for (j=0; j<=(Ny >> 1); j++) {
- unsigned int jm = (Ny - j) & (Ny-1);
- unsigned int ji = j << Mx;
- unsigned int jmi = jm << Mx;
- for (i=0; i<=(Nx >> 1); i++) {
- unsigned int im = (Nx - i) & (Nx-1);
- fREAL A = data[ji + i];
- fREAL B = data[jmi + i];
- fREAL C = data[ji + im];
- fREAL D = data[jmi + im];
- fREAL E = (fREAL)0.5*((A + D) - (B + C));
- data[ji + i] = A - E;
- data[jmi + i] = B + E;
- data[ji + im] = C + E;
- data[jmi + im] = D - E;
- }
- }
-
-}
-
-//------------------------------------------------------------------------------
-
-/* 2D convolution calc, d1 *= d2, M/N - > log2 of width/height */
-static void fht_convolve(fREAL* d1, fREAL* d2, unsigned int M, unsigned int N)
-{
- fREAL a, b;
- unsigned int i, j, k, L, mj, mL;
- unsigned int m = 1 << M, n = 1 << N;
- unsigned int m2 = 1 << (M-1), n2 = 1 << (N-1);
- unsigned int mn2 = m << (N-1);
-
- d1[0] *= d2[0];
- d1[mn2] *= d2[mn2];
- d1[m2] *= d2[m2];
- d1[m2 + mn2] *= d2[m2 + mn2];
- for (i=1; i<m2; i++) {
- k = m - i;
- a = d1[i]*d2[i] - d1[k]*d2[k];
- b = d1[k]*d2[i] + d1[i]*d2[k];
- d1[i] = (b + a)*(fREAL)0.5;
- d1[k] = (b - a)*(fREAL)0.5;
- a = d1[i + mn2]*d2[i + mn2] - d1[k + mn2]*d2[k + mn2];
- b = d1[k + mn2]*d2[i + mn2] + d1[i + mn2]*d2[k + mn2];
- d1[i + mn2] = (b + a)*(fREAL)0.5;
- d1[k + mn2] = (b - a)*(fREAL)0.5;
- }
- for (j=1; j<n2; j++) {
- L = n - j;
- mj = j << M;
- mL = L << M;
- a = d1[mj]*d2[mj] - d1[mL]*d2[mL];
- b = d1[mL]*d2[mj] + d1[mj]*d2[mL];
- d1[mj] = (b + a)*(fREAL)0.5;
- d1[mL] = (b - a)*(fREAL)0.5;
- a = d1[m2 + mj]*d2[m2 + mj] - d1[m2 + mL]*d2[m2 + mL];
- b = d1[m2 + mL]*d2[m2 + mj] + d1[m2 + mj]*d2[m2 + mL];
- d1[m2 + mj] = (b + a)*(fREAL)0.5;
- d1[m2 + mL] = (b - a)*(fREAL)0.5;
- }
- for (i=1; i<m2; i++) {
- k = m - i;
- for (j=1; j<n2; j++) {
- L = n - j;
- mj = j << M;
- mL = L << M;
- a = d1[i + mj]*d2[i + mj] - d1[k + mL]*d2[k + mL];
- b = d1[k + mL]*d2[i + mj] + d1[i + mj]*d2[k + mL];
- d1[i + mj] = (b + a)*(fREAL)0.5;
- d1[k + mL] = (b - a)*(fREAL)0.5;
- a = d1[i + mL]*d2[i + mL] - d1[k + mj]*d2[k + mj];
- b = d1[k + mj]*d2[i + mL] + d1[i + mL]*d2[k + mj];
- d1[i + mL] = (b + a)*(fREAL)0.5;
- d1[k + mj] = (b - a)*(fREAL)0.5;
- }
- }
+ ntype->poll = cmp_node_poll_default;
+ ntype->updatefunc = cmp_node_update_default;
+ ntype->update_internal_links = node_update_internal_links_default;
}
-
-//------------------------------------------------------------------------------
-
-void convolve(CompBuf* dst, CompBuf* in1, CompBuf* in2)
-{
- fREAL *data1, *data2, *fp;
- unsigned int w2, h2, hw, hh, log2_w, log2_h;
- fRGB wt, *colp;
- int x, y, ch;
- int xbl, ybl, nxb, nyb, xbsz, ybsz;
- int in2done = FALSE;
-
- CompBuf* rdst = alloc_compbuf(in1->x, in1->y, in1->type, 1);
-
- // convolution result width & height
- w2 = 2*in2->x - 1;
- h2 = 2*in2->y - 1;
- // FFT pow2 required size & log2
- w2 = nextPow2(w2, &log2_w);
- h2 = nextPow2(h2, &log2_h);
-
- // alloc space
- data1 = (fREAL*)MEM_callocN(3*w2*h2*sizeof(fREAL), "convolve_fast FHT data1");
- data2 = (fREAL*)MEM_callocN(w2*h2*sizeof(fREAL), "convolve_fast FHT data2");
-
- // normalize convolutor
- wt[0] = wt[1] = wt[2] = 0.f;
- for (y=0; y<in2->y; y++) {
- colp = (fRGB*)&in2->rect[y*in2->x*in2->type];
- for (x=0; x<in2->x; x++)
- add_v3_v3(wt, colp[x]);
- }
- if (wt[0] != 0.f) wt[0] = 1.f/wt[0];
- 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<in2->y; y++) {
- colp = (fRGB*)&in2->rect[y*in2->x*in2->type];
- for (x=0; x<in2->x; x++)
- mul_v3_v3(colp[x], wt);
- }
-
- // copy image data, unpacking interleaved RGBA into separate channels
- // only need to calc data1 once
-
- // block add-overlap
- hw = in2->x >> 1;
- hh = in2->y >> 1;
- xbsz = (w2 + 1) - in2->x;
- ybsz = (h2 + 1) - in2->y;
- nxb = in1->x / xbsz;
- if (in1->x % xbsz) nxb++;
- nyb = in1->y / ybsz;
- if (in1->y % ybsz) nyb++;
- for (ybl=0; ybl<nyb; ybl++) {
- for (xbl=0; xbl<nxb; xbl++) {
-
- // each channel one by one
- for (ch=0; ch<3; ch++) {
- fREAL* data1ch = &data1[ch*w2*h2];
-
- // only need to calc fht data from in2 once, can re-use for every block
- if (!in2done) {
- // in2, channel ch -> data1
- for (y=0; y<in2->y; y++) {
- fp = &data1ch[y*w2];
- colp = (fRGB*)&in2->rect[y*in2->x*in2->type];
- for (x=0; x<in2->x; x++)
- fp[x] = colp[x][ch];
- }
- }
-
- // in1, channel ch -> data2
- memset(data2, 0, w2*h2*sizeof(fREAL));
- for (y=0; y<ybsz; y++) {
- int yy = ybl*ybsz + y;
- if (yy >= in1->y) continue;
- fp = &data2[y*w2];
- colp = (fRGB*)&in1->rect[yy*in1->x*in1->type];
- for (x=0; x<xbsz; x++) {
- int xx = xbl*xbsz + x;
- if (xx >= in1->x) continue;
- fp[x] = colp[xx][ch];
- }
- }
-
- // forward FHT
- // zero pad data start is different for each == height+1
- if (!in2done) FHT2D(data1ch, log2_w, log2_h, in2->y+1, 0);
- FHT2D(data2, log2_w, log2_h, in2->y+1, 0);
-
- // FHT2D transposed data, row/col now swapped
- // convolve & inverse FHT
- fht_convolve(data2, data1ch, log2_h, log2_w);
- FHT2D(data2, log2_h, log2_w, 0, 1);
- // data again transposed, so in order again
-
- // overlap-add result
- for (y=0; y<(int)h2; y++) {
- const int yy = ybl*ybsz + y - hh;
- if ((yy < 0) || (yy >= in1->y)) continue;
- fp = &data2[y*w2];
- colp = (fRGB*)&rdst->rect[yy*in1->x*in1->type];
- for (x=0; x<(int)w2; x++) {
- const int xx = xbl*xbsz + x - hw;
- if ((xx < 0) || (xx >= in1->x)) continue;
- colp[xx][ch] += fp[x];
- }
- }
-
- }
- in2done = TRUE;
- }
- }
-
- MEM_freeN(data2);
- MEM_freeN(data1);
- memcpy(dst->rect, rdst->rect, sizeof(float)*dst->x*dst->y*dst->type);
- free_compbuf(rdst);
-}
-
-
-/*
- *
- * Utility functions qd_* should probably be integrated better with other functions here.
- *
- */
-// sets fcol to pixelcolor at (x, y)
-void qd_getPixel(CompBuf* src, int x, int y, float* col)
-{
- if (src->rect_procedural) {
- float bc[4];
- src->rect_procedural(src, bc, (float)x/(float)src->xrad, (float)y/(float)src->yrad);
-
- switch (src->type) {
- /* these fallthrough to get all the channels */
- case CB_RGBA: col[3]=bc[3];
- case CB_VEC3: col[2]=bc[2];
- case CB_VEC2: col[1]=bc[1];
- case CB_VAL: col[0]=bc[0];
- }
- }
- else if ((x >= 0) && (x < src->x) && (y >= 0) && (y < src->y)) {
- float* bc = &src->rect[(x + y*src->x)*src->type];
- switch (src->type) {
- /* these fallthrough to get all the channels */
- case CB_RGBA: col[3]=bc[3];
- case CB_VEC3: col[2]=bc[2];
- case CB_VEC2: col[1]=bc[1];
- case CB_VAL: col[0]=bc[0];
- }
- }
- else {
- switch (src->type) {
- /* these fallthrough to get all the channels */
- case CB_RGBA: col[3]=0.0;
- case CB_VEC3: col[2]=0.0;
- case CB_VEC2: col[1]=0.0;
- case CB_VAL: col[0]=0.0;
- }
- }
-}
-
-// sets pixel (x, y) to color col
-void qd_setPixel(CompBuf* src, int x, int y, float* col)
-{
- if ((x >= 0) && (x < src->x) && (y >= 0) && (y < src->y)) {
- float* bc = &src->rect[(x + y*src->x)*src->type];
- switch (src->type) {
- /* these fallthrough to get all the channels */
- case CB_RGBA: bc[3]=col[3];
- case CB_VEC3: bc[2]=col[2];
- case CB_VEC2: bc[1]=col[1];
- case CB_VAL: bc[0]=col[0];
- }
- }
-}
-
-// adds fcol to pixelcolor (x, y)
-void qd_addPixel(CompBuf* src, int x, int y, float* col)
-{
- if ((x >= 0) && (x < src->x) && (y >= 0) && (y < src->y)) {
- float* bc = &src->rect[(x + y*src->x)*src->type];
- bc[0] += col[0], bc[1] += col[1], bc[2] += col[2];
- }
-}
-
-// multiplies pixel by factor value f
-void qd_multPixel(CompBuf* src, int x, int y, float f)
-{
- if ((x >= 0) && (x < src->x) && (y >= 0) && (y < src->y)) {
- float* bc = &src->rect[(x + y*src->x)*src->type];
- bc[0] *= f, bc[1] *= f, bc[2] *= f;
- }
-}
-
-// bilinear interpolation with wraparound
-void qd_getPixelLerpWrap(CompBuf* src, float u, float v, float* col)
-{
- const float ufl = floor(u), vfl = floor(v);
- const int nx = (int)ufl % src->x, ny = (int)vfl % src->y;
- const int x1 = (nx < 0) ? (nx + src->x) : nx;
- const int y1 = (ny < 0) ? (ny + src->y) : ny;
- const int x2 = (x1 + 1) % src->x, y2 = (y1 + 1) % src->y;
- const float* c00 = &src->rect[(x1 + y1*src->x)*src->type];
- const float* c10 = &src->rect[(x2 + y1*src->x)*src->type];
- const float* c01 = &src->rect[(x1 + y2*src->x)*src->type];
- const float* c11 = &src->rect[(x2 + y2*src->x)*src->type];
- const float uf = u - ufl, vf = v - vfl;
- const float w00=(1.f-uf)*(1.f-vf), w10=uf*(1.f-vf), w01=(1.f-uf)*vf, w11=uf*vf;
- col[0] = w00*c00[0] + w10*c10[0] + w01*c01[0] + w11*c11[0];
- if (src->type != CB_VAL) {
- col[1] = w00*c00[1] + w10*c10[1] + w01*c01[1] + w11*c11[1];
- col[2] = w00*c00[2] + w10*c10[2] + w01*c01[2] + w11*c11[2];
- col[3] = w00*c00[3] + w10*c10[3] + w01*c01[3] + w11*c11[3];
- }
-}
-
-// as above, without wrap around
-void qd_getPixelLerp(CompBuf* src, float u, float v, float* col)
-{
- const float ufl = floor(u), vfl = floor(v);
- const int x1 = (int)ufl, y1 = (int)vfl;
- const int x2 = (int)ceil(u), y2 = (int)ceil(v);
- if ((x2 >= 0) && (y2 >= 0) && (x1 < src->x) && (y1 < src->y)) {
- const float B[4] = {0, 0, 0, 0};
- const int ox1 = (x1 < 0), oy1 = (y1 < 0), ox2 = (x2 >= src->x), oy2 = (y2 >= src->y);
- const float* c00 = (ox1 || oy1) ? B : &src->rect[(x1 + y1*src->x)*src->type];
- const float* c10 = (ox2 || oy1) ? B : &src->rect[(x2 + y1*src->x)*src->type];
- const float* c01 = (ox1 || oy2) ? B : &src->rect[(x1 + y2*src->x)*src->type];
- const float* c11 = (ox2 || oy2) ? B : &src->rect[(x2 + y2*src->x)*src->type];
- const float uf = u - ufl, vf = v - vfl;
- const float w00=(1.f-uf)*(1.f-vf), w10=uf*(1.f-vf), w01=(1.f-uf)*vf, w11=uf*vf;
- col[0] = w00*c00[0] + w10*c10[0] + w01*c01[0] + w11*c11[0];
- if (src->type != CB_VAL) {
- col[1] = w00*c00[1] + w10*c10[1] + w01*c01[1] + w11*c11[1];
- col[2] = w00*c00[2] + w10*c10[2] + w01*c01[2] + w11*c11[2];
- col[3] = w00*c00[3] + w10*c10[3] + w01*c01[3] + w11*c11[3];
- }
- }
- else col[0] = col[1] = col[2] = col[3] = 0.f;
-}
-
-// as above, sampling only one channel
-void qd_getPixelLerpChan(CompBuf* src, float u, float v, int chan, float* out)
-{
- const float ufl = floor(u), vfl = floor(v);
- const int x1 = (int)ufl, y1 = (int)vfl;
- const int x2 = (int)ceil(u), y2 = (int)ceil(v);
- if (chan >= src->type) chan = 0;
- if ((x2 >= 0) && (y2 >= 0) && (x1 < src->x) && (y1 < src->y)) {
- const float B[4] = {0, 0, 0, 0};
- const int ox1 = (x1 < 0), oy1 = (y1 < 0), ox2 = (x2 >= src->x), oy2 = (y2 >= src->y);
- const float* c00 = (ox1 || oy1) ? B : &src->rect[(x1 + y1*src->x)*src->type + chan];
- const float* c10 = (ox2 || oy1) ? B : &src->rect[(x2 + y1*src->x)*src->type + chan];
- const float* c01 = (ox1 || oy2) ? B : &src->rect[(x1 + y2*src->x)*src->type + chan];
- const float* c11 = (ox2 || oy2) ? B : &src->rect[(x2 + y2*src->x)*src->type + chan];
- const float uf = u - ufl, vf = v - vfl;
- const float w00=(1.f-uf)*(1.f-vf), w10=uf*(1.f-vf), w01=(1.f-uf)*vf, w11=uf*vf;
- out[0] = w00*c00[0] + w10*c10[0] + w01*c01[0] + w11*c11[0];
- }
- else *out = 0.f;
-}
-
-
-CompBuf* qd_downScaledCopy(CompBuf* src, int scale)
-{
- CompBuf* fbuf;
- if (scale <= 1)
- fbuf = dupalloc_compbuf(src);
- else {
- int nw = src->x/scale, nh = src->y/scale;
- if ((2*(src->x % scale)) > scale) nw++;
- if ((2*(src->y % scale)) > scale) nh++;
- fbuf = alloc_compbuf(nw, nh, src->type, 1);
- {
- int x, y, xx, yy, sx, sy, mx, my;
- float colsum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- float fscale = 1.f/(float)(scale*scale);
- for (y=0; y<nh; y++) {
- fRGB* fcolp = (fRGB*)&fbuf->rect[y*fbuf->x*fbuf->type];
- yy = y*scale;
- my = yy + scale;
- if (my > src->y) my = src->y;
- for (x=0; x<nw; x++) {
- xx = x*scale;
- mx = xx + scale;
- if (mx > src->x) mx = src->x;
- zero_v3(colsum);
- for (sy=yy; sy<my; sy++) {
- fRGB* scolp = (fRGB*)&src->rect[sy*src->x*src->type];
- for (sx=xx; sx<mx; sx++)
- add_v3_v3(colsum, scolp[sx]);
- }
- mul_v3_fl(colsum, fscale);
- copy_v3_v3(fcolp[x], colsum);
- }
- }
- }
- }
- return fbuf;
-}
-
-// fast g.blur, per channel
-// xy var. bits 1 & 2 ca be used to blur in x or y direction separately
-void IIR_gauss(CompBuf* src, float sigma, int chan, int xy)
-{
- double q, q2, sc, cf[4], tsM[9], tsu[3], tsv[3];
- double *X, *Y, *W;
- const unsigned int src_width = src->x;
- const unsigned int src_height = src->y;
- unsigned int i, x, y, sz;
-
- // <0.5 not valid, though can have a possibly useful sort of sharpening effect
- if (sigma < 0.5f) return;
-
- if ((xy < 1) || (xy > 3)) xy = 3;
-
- // XXX The YVV macro defined below explicitly expects sources of at least 3x3 pixels,
- // so just skiping blur along faulty direction if src's def is below that limit!
- if (src_width < 3) xy &= ~(int) 1;
- if (src_height < 3) xy &= ~(int) 2;
- if (xy < 1) return;
-
- // see "Recursive Gabor Filtering" by Young/VanVliet
- // all factors here in double.prec. Required, because for single.prec it seems to blow up if sigma > ~200
- if (sigma >= 3.556f)
- q = 0.9804f * (sigma - 3.556f) + 2.5091f;
- else // sigma >= 0.5
- q = (0.0561f * sigma + 0.5784f) * sigma - 0.2568f;
- q2 = q * q;
- sc = (1.1668 + q) * (3.203729649 + (2.21566 + q) * q);
- // no gabor filtering here, so no complex multiplies, just the regular coefs.
- // all negated here, so as not to have to recalc Triggs/Sdika matrix
- cf[1] = q * (5.788961737 + (6.76492 + 3.0 * q) * q) / sc;
- cf[2] = -q2 * (3.38246 + 3.0 * q) / sc;
- // 0 & 3 unchanged
- cf[3] = q2 * q / sc;
- cf[0] = 1.0 - cf[1] - cf[2] - cf[3];
-
- // Triggs/Sdika border corrections,
- // it seems to work, not entirely sure if it is actually totally correct,
- // Besides J.M.Geusebroek's anigauss.c (see http://www.science.uva.nl/~mark),
- // found one other implementation by Cristoph Lampert,
- // but neither seem to be quite the same, result seems to be ok so far anyway.
- // Extra scale factor here to not have to do it in filter,
- // though maybe this had something to with the precision errors
- sc = cf[0] / ((1.0 + cf[1] - cf[2] + cf[3]) * (1.0 - cf[1] - cf[2] - cf[3]) * (1.0 + cf[2] + (cf[1] - cf[3]) * cf[3]));
- tsM[0] = sc * (-cf[3] * cf[1] + 1.0 - cf[3] * cf[3] - cf[2]);
- tsM[1] = sc * ((cf[3] + cf[1]) * (cf[2] + cf[3] * cf[1]));
- tsM[2] = sc * (cf[3] * (cf[1] + cf[3] * cf[2]));
- tsM[3] = sc * (cf[1] + cf[3] * cf[2]);
- tsM[4] = sc * (-(cf[2] - 1.0) * (cf[2] + cf[3] * cf[1]));
- tsM[5] = sc * (-(cf[3] * cf[1] + cf[3] * cf[3] + cf[2] - 1.0) * cf[3]);
- tsM[6] = sc * (cf[3] * cf[1] + cf[2] + cf[1] * cf[1] - cf[2] * cf[2]);
- tsM[7] = sc * (cf[1] * cf[2] + cf[3] * cf[2] * cf[2] - cf[1] * cf[3] * cf[3] - cf[3] * cf[3] * cf[3] - cf[3] * cf[2] + cf[3]);
- tsM[8] = sc * (cf[3] * (cf[1] + cf[3] * cf[2]));
-
-#define YVV(L) \
-{ \
- W[0] = cf[0] * X[0] + cf[1] * X[0] + cf[2] * X[0] + cf[3] * X[0]; \
- W[1] = cf[0] * X[1] + cf[1] * W[0] + cf[2] * X[0] + cf[3] * X[0]; \
- W[2] = cf[0] * X[2] + cf[1] * W[1] + cf[2] * W[0] + cf[3] * X[0]; \
- for (i = 3; i < L; i++) { \
- W[i] = cf[0] * X[i] + cf[1] * W[i - 1] + cf[2] * W[i - 2] + cf[3] * W[i - 3]; \
- } \
- tsu[0] = W[L - 1] - X[L - 1]; \
- tsu[1] = W[L - 2] - X[L - 1]; \
- tsu[2] = W[L - 3] - X[L - 1]; \
- tsv[0] = tsM[0] * tsu[0] + tsM[1] * tsu[1] + tsM[2] * tsu[2] + X[L - 1]; \
- tsv[1] = tsM[3] * tsu[0] + tsM[4] * tsu[1] + tsM[5] * tsu[2] + X[L - 1]; \
- tsv[2] = tsM[6] * tsu[0] + tsM[7] * tsu[1] + tsM[8] * tsu[2] + X[L - 1]; \
- Y[L - 1] = cf[0] * W[L - 1] + cf[1] * tsv[0] + cf[2] * tsv[1] + cf[3] * tsv[2]; \
- Y[L - 2] = cf[0] * W[L - 2] + cf[1] * Y[L - 1] + cf[2] * tsv[0] + cf[3] * tsv[1]; \
- Y[L - 3] = cf[0] * W[L - 3] + cf[1] * Y[L - 2] + cf[2] * Y[L - 1] + cf[3] * tsv[0]; \
- /* 'i != UINT_MAX' is really 'i >= 0', but necessary for unsigned int wrapping */ \
- for (i = L - 4; i != UINT_MAX; i--) { \
- Y[i] = cf[0] * W[i] + cf[1] * Y[i + 1] + cf[2] * Y[i + 2] + cf[3] * Y[i + 3]; \
- } \
-} (void)0
-
- // intermediate buffers
- sz = MAX2(src_width, src_height);
- X = MEM_callocN(sz * sizeof(double), "IIR_gauss X buf");
- Y = MEM_callocN(sz * sizeof(double), "IIR_gauss Y buf");
- W = MEM_callocN(sz * sizeof(double), "IIR_gauss W buf");
- if (xy & 1) { // H
- for (y = 0; y < src_height; ++y) {
- const int yx = y * src_width;
- for (x = 0; x < src_width; ++x)
- X[x] = src->rect[(x + yx) * src->type + chan];
- YVV(src_width);
- for (x = 0; x < src_width; ++x)
- src->rect[(x + yx) * src->type + chan] = Y[x];
- }
- }
- if (xy & 2) { // V
- for (x = 0; x < src_width; ++x) {
- for (y = 0; y < src_height; ++y)
- X[y] = src->rect[(x + y * src_width) * src->type + chan];
- YVV(src_height);
- for (y = 0; y < src_height; ++y)
- src->rect[(x + y * src_width) * src->type + chan] = Y[y];
- }
- }
-
- MEM_freeN(X);
- MEM_freeN(W);
- MEM_freeN(Y);
-#undef YVV
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
diff --git a/source/blender/nodes/composite/node_composite_util.h b/source/blender/nodes/composite/node_composite_util.h
index f2719ee0779..3f9cfc03089 100644
--- a/source/blender/nodes/composite/node_composite_util.h
+++ b/source/blender/nodes/composite/node_composite_util.h
@@ -33,177 +33,35 @@
#ifndef __NODE_COMPOSITE_UTIL_H__
#define __NODE_COMPOSITE_UTIL_H__
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_camera_types.h" /* qdn: defocus node, need camera info */
-#include "DNA_color_types.h"
#include "DNA_ID.h"
-#include "DNA_image_types.h"
-#include "DNA_material_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_node_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_texture_types.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
-#include "BLI_rand.h"
-#include "BLI_threads.h"
-#include "BLI_utildefines.h"
-#include "BLI_utildefines.h"
#include "BLF_translation.h"
-#include "BKE_blender.h"
-#include "BKE_camera.h"
#include "BKE_colortools.h"
-#include "BKE_global.h"
#include "BKE_image.h"
-#include "BKE_main.h"
-#include "BKE_material.h"
-#include "BKE_movieclip.h"
-#include "BKE_node.h"
#include "BKE_texture.h"
#include "BKE_tracking.h"
-#include "BKE_library.h"
-#include "BKE_object.h"
-
#include "node_util.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "RE_pipeline.h"
-#include "RE_shader_ext.h"
-#include "RE_render_ext.h"
/* only for forward declarations */
#include "NOD_composite.h"
#define CMP_SCALE_MAX 12000
-#ifdef WITH_COMPOSITOR_LEGACY
-
-/* *************************** operations support *************************** */
-
-/* general signal that's in output sockets, and goes over the wires */
-typedef struct CompBuf {
- float *rect;
- int x, y, xrad, yrad;
- short type, malloc;
- rcti disprect; /* cropped part of image */
- int xof, yof; /* relative to center of target image */
-
- void (*rect_procedural)(struct CompBuf *, float *, float, float);
- float procedural_size[3], procedural_offset[3];
- int procedural_type;
- bNode *node; /* only in use for procedural bufs */
-
- struct CompBuf *next, *prev; /* for pass-on, works nicer than reference counting */
-} CompBuf;
-
-/* defines also used for pixel size */
-#define CB_RGBA 4
-#define CB_VEC4 4
-#define CB_VEC3 3
-#define CB_VEC2 2
-#define CB_VAL 1
-
-/* defines for RGBA channels */
-#define CHAN_R 0
-#define CHAN_G 1
-#define CHAN_B 2
-#define CHAN_A 3
-
-
-
-CompBuf *alloc_compbuf(int sizex, int sizey, int type, int alloc);
-CompBuf *dupalloc_compbuf(CompBuf *cbuf);
-CompBuf *pass_on_compbuf(CompBuf *cbuf);
-void free_compbuf(CompBuf *cbuf);
-void print_compbuf(char *str, CompBuf *cbuf);
-void compbuf_set_node(struct CompBuf *cbuf, struct bNode *node);
-
-CompBuf *get_cropped_compbuf(rcti *drect, float *rectf, int rectx, int recty, int type);
-CompBuf *scalefast_compbuf(CompBuf *inbuf, int newx, int newy);
-CompBuf *typecheck_compbuf(CompBuf *inbuf, int type);
-void typecheck_compbuf_color(float *out, float *in, int outtype, int intype);
-
-/* **************************************************** */
-
-float *compbuf_get_pixel(CompBuf *cbuf, float *defcol, float *use, int x, int y, int xrad, int yrad);
-
-/* Pixel-to-Pixel operation, 1 Image in, 1 out */
-void composit1_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col,
- void (*func)(bNode *, float *, float *),
- int src_type);
-/* Pixel-to-Pixel operation, 2 Images in, 1 out */
-void composit2_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col,
- CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *),
- int src_type, int fac_type);
-
-/* Pixel-to-Pixel operation, 3 Images in, 1 out */
-void composit3_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *src2_buf, float *src2_col,
- CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *, float *),
- int src1_type, int src2_type, int fac_type);
-
-/* Pixel-to-Pixel operation, 4 Images in, 1 out */
-void composit4_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *fac1_buf, float *fac1,
- CompBuf *src2_buf, float *src2_col, CompBuf *fac2_buf, float *fac2,
- void (*func)(bNode *, float *, float *, float *, float *, float *),
- int src1_type, int fac1_type, int src2_type, int fac2_type);
-
-CompBuf *valbuf_from_rgbabuf(CompBuf *cbuf, int channel);
-void valbuf_to_rgbabuf(CompBuf *valbuf, CompBuf *cbuf, int channel);
-void generate_preview(void *data, bNode *node, CompBuf *stackbuf);
-
-void do_copy_rgba(bNode *node, float *out, float *in);
-void do_copy_rgb(bNode *node, float *out, float *in);
-void do_copy_value(bNode *node, float *out, float *in);
-void do_copy_a_rgba(bNode *node, float *out, float *in, float *fac);
-
-void do_rgba_to_yuva(bNode *node, float *out, float *in);
-void do_rgba_to_hsva(bNode *node, float *out, float *in);
-void do_rgba_to_ycca(bNode *node, float *out, float *in);
-void do_yuva_to_rgba(bNode *node, float *out, float *in);
-void do_hsva_to_rgba(bNode *node, float *out, float *in);
-void do_ycca_to_rgba(bNode *node, float *out, float *in);
-
-void gamma_correct_compbuf(CompBuf *img, int inversed);
-void premul_compbuf(CompBuf *img, int inversed);
-void convolve(CompBuf* dst, CompBuf* in1, CompBuf* in2);
-
-extern void node_ID_title_cb(void *node_v, void *unused_v);
-
-
-/* utility functions used by glare, tonemap and lens distortion */
-/* soms macros for color handling */
-typedef float fRGB[4];
-/* multiply c2 by color rgb, rgb as separate arguments */
-#define fRGB_rgbmult(c, r, g, b) { c[0]*=(r); c[1]*=(g); c[2]*=(b); } (void)0
-
-void qd_getPixel(CompBuf* src, int x, int y, float* col);
-void qd_setPixel(CompBuf* src, int x, int y, float* col);
-void qd_addPixel(CompBuf* src, int x, int y, float* col);
-void qd_multPixel(CompBuf* src, int x, int y, float f);
-void qd_getPixelLerpWrap(CompBuf* src, float u, float v, float* col);
-void qd_getPixelLerp(CompBuf* src, float u, float v, float* col);
-void qd_getPixelLerpChan(CompBuf* src, float u, float v, int chan, float* out);
-CompBuf* qd_downScaledCopy(CompBuf* src, int scale);
-void IIR_gauss(CompBuf* src, float sigma, int chan, int xy);
-/* end utility funcs */
-
-/* transformations */
-
-CompBuf* node_composit_transform(CompBuf *cbuf, float x, float y, float angle, float scale, int filter_type);
-float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc);
+int cmp_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree);
+void cmp_node_update_default(struct bNodeTree *UNUSED(ntree), struct bNode *node);
+void cmp_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag);
-#endif
+#endif /* __NODE_COMPOSITE_UTIL_H__ */
-#endif /* WITH_COMPOSITOR_LEGACY */
diff --git a/source/blender/nodes/composite/nodes/node_composite_alphaOver.c b/source/blender/nodes/composite/nodes/node_composite_alphaOver.c
index 72c2204d8c5..cdfcf045e35 100644
--- a/source/blender/nodes/composite/nodes/node_composite_alphaOver.c
+++ b/source/blender/nodes/composite/nodes/node_composite_alphaOver.c
@@ -43,120 +43,19 @@ static bNodeSocketTemplate cmp_node_alphaover_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_alphaover_premul(bNode *UNUSED(node), float *out, float *src, float *over, float *fac)
-{
-
- /* Zero alpha values should still permit an add of RGB data */
- if (over[3]<0.0f) {
- copy_v4_v4(out, src);
- }
- else if (fac[0]==1.0f && over[3]>=1.0f) {
- copy_v4_v4(out, over);
- }
- else {
- float mul= 1.0f - fac[0]*over[3];
-
- out[0] = (mul*src[0]) + fac[0]*over[0];
- out[1] = (mul*src[1]) + fac[0]*over[1];
- out[2] = (mul*src[2]) + fac[0]*over[2];
- out[3] = (mul*src[3]) + fac[0]*over[3];
- }
-}
-
-/* result will be still premul, but the over part is premulled */
-static void do_alphaover_key(bNode *UNUSED(node), float *out, float *src, float *over, float *fac)
-{
-
- if (over[3]<=0.0f) {
- copy_v4_v4(out, src);
- }
- else if (fac[0]==1.0f && over[3]>=1.0f) {
- copy_v4_v4(out, over);
- }
- else {
- float premul= fac[0]*over[3];
- float mul= 1.0f - premul;
-
- out[0] = (mul*src[0]) + premul*over[0];
- out[1] = (mul*src[1]) + premul*over[1];
- out[2] = (mul*src[2]) + premul*over[2];
- out[3] = (mul*src[3]) + fac[0]*over[3];
- }
-}
-
-/* result will be still premul, but the over part is premulled */
-static void do_alphaover_mixed(bNode *node, float *out, float *src, float *over, float *fac)
-{
-
- if (over[3]<=0.0f) {
- copy_v4_v4(out, src);
- }
- else if (fac[0]==1.0f && over[3]>=1.0f) {
- copy_v4_v4(out, over);
- }
- else {
- NodeTwoFloats *ntf= node->storage;
- float addfac= 1.0f - ntf->x + over[3]*ntf->x;
- float premul= fac[0]*addfac;
- float mul= 1.0f - fac[0]*over[3];
-
- out[0] = (mul*src[0]) + premul*over[0];
- out[1] = (mul*src[1]) + premul*over[1];
- out[2] = (mul*src[2]) + premul*over[2];
- out[3] = (mul*src[3]) + fac[0]*over[3];
- }
-}
-
-
-static void node_composit_exec_alphaover(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order in: col col */
- /* stack order out: col */
- if (out[0]->hasoutput==0)
- return;
-
- /* input no image? then only color operation */
- if (in[1]->data==NULL && in[2]->data==NULL) {
- do_alphaover_premul(node, out[0]->vec, in[1]->vec, in[2]->vec, in[0]->vec);
- }
- else {
- /* make output size of input image */
- CompBuf *cbuf= in[1]->data?in[1]->data:in[2]->data;
- CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
- NodeTwoFloats *ntf= node->storage;
-
- if (ntf->x != 0.0f)
- composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, in[0]->vec, do_alphaover_mixed, CB_RGBA, CB_RGBA, CB_VAL);
- else if (node->custom1)
- composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, in[0]->vec, do_alphaover_key, CB_RGBA, CB_RGBA, CB_VAL);
- else
- composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, in[0]->vec, do_alphaover_premul, CB_RGBA, CB_RGBA, CB_VAL);
-
- out[0]->data= stackbuf;
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_alphaover_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_alphaover_init(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= MEM_callocN(sizeof(NodeTwoFloats), "NodeTwoFloats");
}
-void register_node_type_cmp_alphaover(bNodeTreeType *ttype)
+void register_node_type_cmp_alphaover(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_ALPHAOVER, "AlphaOver", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_ALPHAOVER, "Alpha Over", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_alphaover_in, cmp_node_alphaover_out);
- node_type_size(&ntype, 80, 40, 120);
node_type_init(&ntype, node_alphaover_init);
node_type_storage(&ntype, "NodeTwoFloats", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_alphaover);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c b/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c
index 7674ace42a3..1f80df602df 100644
--- a/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c
+++ b/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c
@@ -43,222 +43,7 @@ static bNodeSocketTemplate cmp_node_bilateralblur_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-#define INIT_C3 \
- mean0 = 1; \
- mean1[0] = src[0]; \
- mean1[1] = src[1]; \
- mean1[2] = src[2]; \
- mean1[3] = src[3]; \
- (void)0
-
-/* finds color distances */
-#define COLOR_DISTANCE_C3(c1, c2) \
- ((c1[0] - c2[0]) * (c1[0] - c2[0]) + \
- (c1[1] - c2[1]) * (c1[1] - c2[1]) + \
- (c1[2] - c2[2]) * (c1[2] - c2[2]) + \
- (c1[3] - c2[3]) * (c1[3] - c2[3]))
-
-/* this is the main kernel function for comparing color distances
- * and adding them weighted to the final color */
-#define KERNEL_ELEMENT_C3(k) \
- temp_color = src + deltas[k]; \
- ref_color = ref + deltas[k]; \
- w = weight_tab[k] + \
- (double)COLOR_DISTANCE_C3(ref, ref_color) * i2sigma_color; \
- w = 1.0 / (w * w + 1); \
- mean0 += w; \
- mean1[0] += (double)temp_color[0] * w; \
- mean1[1] += (double)temp_color[1] * w; \
- mean1[2] += (double)temp_color[2] * w; \
- mean1[3] += (double)temp_color[3] * w; \
- (void)0
-
-/* write blurred values to image */
-#define UPDATE_OUTPUT_C3 \
- mean0 = 1.0 / mean0; \
- dest[x * pix + 0] = mean1[0] * mean0; \
- dest[x * pix + 1] = mean1[1] * mean0; \
- dest[x * pix + 2] = mean1[2] * mean0; \
- dest[x * pix + 3] = mean1[3] * mean0; \
- (void)0
-
-/* initializes deltas for fast access to neighbor pixels */
-#define INIT_3X3_DELTAS(deltas, step, nch) \
- ((deltas)[0] = (nch), (deltas)[1] = -(step) + (nch), \
- (deltas)[2] = -(step), (deltas)[3] = -(step) - (nch), \
- (deltas)[4] = -(nch), (deltas)[5] = (step) - (nch), \
- (deltas)[6] = (step), (deltas)[7] = (step) + (nch)); \
- (void)0
-
-
-/* code of this node was heavily inspired by the smooth function of opencv library.
- * The main change is an optional image input */
-static void node_composit_exec_bilateralblur(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- NodeBilateralBlurData *nbbd = node->storage;
- CompBuf *new, *source, *img = in[0]->data, *refimg = in[1]->data;
- double mean0, w, i2sigma_color, i2sigma_space;
- double mean1[4];
- double weight_tab[8];
- float *src, *dest, *ref, *temp_color, *ref_color;
- float sigma_color, sigma_space;
- int imgx, imgy, x, y, pix, i, step;
- int deltas[8];
- short found_determinator = 0;
-
- if (img == NULL || out[0]->hasoutput == 0)
- return;
-
- if (img->type != CB_RGBA) {
- img = typecheck_compbuf(in[0]->data, CB_RGBA);
- }
-
- imgx = img->x;
- imgy = img->y;
- pix = img->type;
- step = pix * imgx;
-
- if (refimg) {
- if (refimg->x == imgx && refimg->y == imgy) {
- if (ELEM3(refimg->type, CB_VAL, CB_VEC2, CB_VEC3)) {
- refimg = typecheck_compbuf(in[1]->data, CB_RGBA);
- found_determinator = 1;
- }
- }
- }
- else {
- refimg = img;
- }
-
- /* allocs */
- source = dupalloc_compbuf(img);
- new = alloc_compbuf(imgx, imgy, pix, 1);
-
- /* accept image offsets from other nodes */
- new->xof = img->xof;
- new->yof = img->yof;
-
- /* bilateral code properties */
- sigma_color = nbbd->sigma_color;
- sigma_space = nbbd->sigma_space;
-
- i2sigma_color = 1.0f / (sigma_color * sigma_color);
- i2sigma_space = 1.0f / (sigma_space * sigma_space);
-
- INIT_3X3_DELTAS(deltas, step, pix);
-
- weight_tab[0] = weight_tab[2] = weight_tab[4] = weight_tab[6] = i2sigma_space;
- weight_tab[1] = weight_tab[3] = weight_tab[5] = weight_tab[7] = i2sigma_space * 2;
-
- /* iterations */
- for (i = 0; i < nbbd->iter; i++) {
- src = source->rect;
- ref = refimg->rect;
- dest = new->rect;
- /*goes through image, there are more loops for 1st/last line and all other lines*/
- /*kernel element accumulates surrounding colors, which are then written with the update_output function*/
- for (x = 0; x < imgx; x++, src += pix, ref += pix) {
- INIT_C3;
-
- KERNEL_ELEMENT_C3(6);
-
- if (x > 0) {
- KERNEL_ELEMENT_C3(5);
- KERNEL_ELEMENT_C3(4);
- }
-
- if (x < imgx - 1) {
- KERNEL_ELEMENT_C3(7);
- KERNEL_ELEMENT_C3(0);
- }
-
- UPDATE_OUTPUT_C3;
- }
-
- dest += step;
-
- for (y = 1; y < imgy - 1; y++, dest += step, src += pix, ref += pix) {
- x = 0;
-
- INIT_C3;
-
- KERNEL_ELEMENT_C3(0);
- KERNEL_ELEMENT_C3(1);
- KERNEL_ELEMENT_C3(2);
- KERNEL_ELEMENT_C3(6);
- KERNEL_ELEMENT_C3(7);
-
- UPDATE_OUTPUT_C3;
-
- src += pix;
- ref += pix;
-
- for (x = 1; x < imgx - 1; x++, src += pix, ref += pix) {
- INIT_C3;
-
- KERNEL_ELEMENT_C3(0);
- KERNEL_ELEMENT_C3(1);
- KERNEL_ELEMENT_C3(2);
- KERNEL_ELEMENT_C3(3);
- KERNEL_ELEMENT_C3(4);
- KERNEL_ELEMENT_C3(5);
- KERNEL_ELEMENT_C3(6);
- KERNEL_ELEMENT_C3(7);
-
- UPDATE_OUTPUT_C3;
- }
-
- INIT_C3;
-
- KERNEL_ELEMENT_C3(2);
- KERNEL_ELEMENT_C3(3);
- KERNEL_ELEMENT_C3(4);
- KERNEL_ELEMENT_C3(5);
- KERNEL_ELEMENT_C3(6);
-
- UPDATE_OUTPUT_C3;
- }
-
- for (x = 0; x < imgx; x++, src += pix, ref += pix) {
- INIT_C3;
-
- KERNEL_ELEMENT_C3(2);
-
- if (x > 0) {
- KERNEL_ELEMENT_C3(3);
- KERNEL_ELEMENT_C3(4);
- }
- if (x < imgx - 1) {
- KERNEL_ELEMENT_C3(1);
- KERNEL_ELEMENT_C3(0);
- }
-
- UPDATE_OUTPUT_C3;
- }
-
- if (node->exec & NODE_BREAK) break;
-
- SWAP(CompBuf, *source, *new);
- }
-
- if (img != in[0]->data)
- free_compbuf(img);
-
- if (found_determinator == 1) {
- if (refimg != in[1]->data)
- free_compbuf(refimg);
- }
-
- out[0]->data = source;
-
- free_compbuf(new);
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_bilateralblur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_bilateralblur(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeBilateralBlurData *nbbd = MEM_callocN(sizeof(NodeBilateralBlurData), "node bilateral blur data");
node->storage = nbbd;
@@ -266,18 +51,14 @@ static void node_composit_init_bilateralblur(bNodeTree *UNUSED(ntree), bNode *no
nbbd->sigma_space = 5.0;
}
-void register_node_type_cmp_bilateralblur(bNodeTreeType *ttype)
+void register_node_type_cmp_bilateralblur(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_BILATERALBLUR, "Bilateral Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_BILATERALBLUR, "Bilateral Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_bilateralblur_in, cmp_node_bilateralblur_out);
- node_type_size(&ntype, 150, 120, 200);
node_type_init(&ntype, node_composit_init_bilateralblur);
node_type_storage(&ntype, "NodeBilateralBlurData", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_bilateralblur);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_blur.c b/source/blender/nodes/composite/nodes/node_composite_blur.c
index eb7f7763afb..e544ec7d9d8 100644
--- a/source/blender/nodes/composite/nodes/node_composite_blur.c
+++ b/source/blender/nodes/composite/nodes/node_composite_blur.c
@@ -44,705 +44,21 @@ static bNodeSocketTemplate cmp_node_blur_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static float *make_gausstab(int filtertype, int rad)
-{
- float *gausstab, sum, val;
- int i, n;
-
- n = 2 * rad + 1;
-
- gausstab = (float *) MEM_mallocN(n * sizeof(float), "gauss");
-
- sum = 0.0f;
- for (i = -rad; i <= rad; i++) {
- val = RE_filter_value(filtertype, (float)i / (float)rad);
- sum += val;
- gausstab[i + rad] = val;
- }
-
- sum = 1.0f / sum;
- for (i = 0; i < n; i++)
- gausstab[i] *= sum;
-
- return gausstab;
-}
-
-static float *make_bloomtab(int rad)
-{
- float *bloomtab, val;
- int i, n;
-
- n = 2 * rad + 1;
-
- bloomtab = (float *) MEM_mallocN(n * sizeof(float), "bloom");
-
- for (i = -rad; i <= rad; i++) {
- val = powf(1.0f - fabsf((float)i) / ((float)rad), 4.0f);
- bloomtab[i + rad] = val;
- }
-
- return bloomtab;
-}
-
-/* both input images of same type, either 4 or 1 channel */
-static void blur_single_image(bNode *node, CompBuf *new, CompBuf *img, float scale)
-{
- NodeBlurData *nbd = node->storage;
- CompBuf *work;
- register float sum, val;
- float rval, gval, bval, aval;
- float *gausstab, *gausstabcent;
- int rad, imgx = img->x, imgy = img->y;
- int x, y, pix = img->type;
- int i, bigstep;
- float *src, *dest;
-
- /* helper image */
- work = alloc_compbuf(imgx, imgy, img->type, 1); /* allocs */
-
- /* horizontal */
- if (nbd->sizex == 0) {
- memcpy(work->rect, img->rect, sizeof(float) * img->type * imgx * imgy);
- }
- else {
- rad = scale * (float)nbd->sizex;
- if (rad > imgx / 2)
- rad = imgx / 2;
- else if (rad < 1)
- rad = 1;
-
- gausstab = make_gausstab(nbd->filtertype, rad);
- gausstabcent = gausstab + rad;
-
- for (y = 0; y < imgy; y++) {
- float *srcd = img->rect + pix * (y * img->x);
-
- dest = work->rect + pix * (y * img->x);
-
- for (x = 0; x < imgx; x++) {
- int minr = x - rad < 0 ? -x : -rad;
- int maxr = x + rad > imgx ? imgx - x : rad;
-
- src = srcd + pix * (x + minr);
-
- sum = gval = rval = bval = aval = 0.0f;
- for (i = minr; i < maxr; i++) {
- val = gausstabcent[i];
- sum += val;
- rval += val * (*src++);
- if (pix == 4) {
- gval += val * (*src++);
- bval += val * (*src++);
- aval += val * (*src++);
- }
- }
- sum = 1.0f / sum;
- *dest++ = rval * sum;
- if (pix == 4) {
- *dest++ = gval * sum;
- *dest++ = bval * sum;
- *dest++ = aval * sum;
- }
- }
- if (node->exec & NODE_BREAK)
- break;
- }
-
- /* vertical */
- MEM_freeN(gausstab);
- }
-
- if (nbd->sizey == 0) {
- memcpy(new->rect, work->rect, sizeof(float) * img->type * imgx * imgy);
- }
- else {
- rad = scale * (float)nbd->sizey;
- if (rad > imgy / 2)
- rad = imgy / 2;
- else if (rad < 1)
- rad = 1;
-
- gausstab = make_gausstab(nbd->filtertype, rad);
- gausstabcent = gausstab + rad;
-
- bigstep = pix * imgx;
- for (x = 0; x < imgx; x++) {
- float *srcd = work->rect + pix * x;
-
- dest = new->rect + pix * x;
-
- for (y = 0; y < imgy; y++) {
- int minr = y - rad < 0 ? -y : -rad;
- int maxr = y + rad > imgy ? imgy - y : rad;
-
- src = srcd + bigstep * (y + minr);
-
- sum = gval = rval = bval = aval = 0.0f;
- for (i = minr; i < maxr; i++) {
- val = gausstabcent[i];
- sum += val;
- rval += val * src[0];
- if (pix == 4) {
- gval += val * src[1];
- bval += val * src[2];
- aval += val * src[3];
- }
- src += bigstep;
- }
- sum = 1.0f / sum;
- dest[0] = rval * sum;
- if (pix == 4) {
- dest[1] = gval * sum;
- dest[2] = bval * sum;
- dest[3] = aval * sum;
- }
- dest += bigstep;
- }
- if (node->exec & NODE_BREAK)
- break;
- }
- MEM_freeN(gausstab);
- }
-
- free_compbuf(work);
-}
-
-/* reference has to be mapped 0-1, and equal in size */
-static void bloom_with_reference(CompBuf *new, CompBuf *img, CompBuf *UNUSED(ref), float UNUSED(fac), NodeBlurData *nbd)
-{
- CompBuf *wbuf;
- register float val;
- float radxf, radyf;
- float **maintabs;
- float *gausstabx, *gausstabcenty;
- float *gausstaby, *gausstabcentx;
- int radx, rady, imgx = img->x, imgy = img->y;
- int x, y;
- int i, j;
- float *src, *dest, *wb;
-
- wbuf = alloc_compbuf(imgx, imgy, CB_VAL, 1);
-
- /* horizontal */
- radx = (float)nbd->sizex;
- if (radx > imgx / 2)
- radx = imgx / 2;
- else if (radx < 1)
- radx = 1;
-
- /* vertical */
- rady = (float)nbd->sizey;
- if (rady > imgy / 2)
- rady = imgy / 2;
- else if (rady < 1)
- rady = 1;
-
- x = MAX2(radx, rady);
- maintabs = MEM_mallocN(x * sizeof(void *), "gauss array");
- for (i = 0; i < x; i++)
- maintabs[i] = make_bloomtab(i + 1);
-
- /* vars to store before we go */
-// refd= ref->rect;
- src = img->rect;
-
- radxf = (float)radx;
- radyf = (float)rady;
-
- for (y = 0; y < imgy; y++) {
- for (x = 0; x < imgx; x++, src += 4) { //, refd++) {
-
-// int refradx= (int)(refd[0]*radxf);
-// int refrady= (int)(refd[0]*radyf);
-
- int refradx = (int)(radxf * 0.3f * src[3] * (src[0] + src[1] + src[2]));
- int refrady = (int)(radyf * 0.3f * src[3] * (src[0] + src[1] + src[2]));
-
- if (refradx > radx) refradx = radx;
- else if (refradx < 1) refradx = 1;
- if (refrady > rady) refrady = rady;
- else if (refrady < 1) refrady = 1;
-
- if (refradx == 1 && refrady == 1) {
- wb = wbuf->rect + (y * imgx + x);
- dest = new->rect + 4 * (y * imgx + x);
- wb[0] += 1.0f;
- dest[0] += src[0];
- dest[1] += src[1];
- dest[2] += src[2];
- dest[3] += src[3];
- }
- else {
- int minxr = x - refradx < 0 ? -x : -refradx;
- int maxxr = x + refradx > imgx ? imgx - x : refradx;
- int minyr = y - refrady < 0 ? -y : -refrady;
- int maxyr = y + refrady > imgy ? imgy - y : refrady;
-
- float *destd = new->rect + 4 * ( (y + minyr) * imgx + x + minxr);
- float *wbufd = wbuf->rect + ( (y + minyr) * imgx + x + minxr);
-
- gausstabx = maintabs[refradx - 1];
- gausstabcentx = gausstabx + refradx;
- gausstaby = maintabs[refrady - 1];
- gausstabcenty = gausstaby + refrady;
-
- for (i = minyr; i < maxyr; i++, destd += 4 * imgx, wbufd += imgx) {
- dest = destd;
- wb = wbufd;
- for (j = minxr; j < maxxr; j++, dest += 4, wb++) {
-
- val = gausstabcenty[i] * gausstabcentx[j];
- wb[0] += val;
- dest[0] += val * src[0];
- dest[1] += val * src[1];
- dest[2] += val * src[2];
- dest[3] += val * src[3];
- }
- }
- }
- }
- }
-
- x = imgx * imgy;
- dest = new->rect;
- wb = wbuf->rect;
- while (x--) {
- val = 1.0f / wb[0];
- dest[0] *= val;
- dest[1] *= val;
- dest[2] *= val;
- dest[3] *= val;
- wb++;
- dest += 4;
- }
-
- free_compbuf(wbuf);
-
- x = MAX2(radx, rady);
- for (i = 0; i < x; i++)
- MEM_freeN(maintabs[i]);
- MEM_freeN(maintabs);
-
-}
-
-#if 0
-static float hexagon_filter(float fi, float fj)
-{
- fi = fabs(fi);
- fj = fabs(fj);
-
- if (fj > 0.33f) {
- fj = (fj - 0.33f) / 0.66f;
- if (fi + fj > 1.0f)
- return 0.0f;
- else
- return 1.0f;
- }
- else return 1.0f;
-}
-#endif
-
-/* uses full filter, no horizontal/vertical optimize possible */
-/* both images same type, either 1 or 4 channels */
-static void bokeh_single_image(bNode *node, CompBuf *new, CompBuf *img, float fac)
-{
- NodeBlurData *nbd = node->storage;
- register float val;
- float radxf, radyf;
- float *gausstab, *dgauss;
- int radx, rady, imgx = img->x, imgy = img->y;
- int x, y, pix = img->type;
- int i, j, n;
- float *src = NULL, *dest, *srcd = NULL;
-
- /* horizontal */
- radxf = fac * (float)nbd->sizex;
- if (radxf > imgx / 2.0f)
- radxf = imgx / 2.0f;
- else if (radxf < 1.0f)
- radxf = 1.0f;
-
- /* vertical */
- radyf = fac * (float)nbd->sizey;
- if (radyf > imgy / 2.0f)
- radyf = imgy / 2.0f;
- else if (radyf < 1.0f)
- radyf = 1.0f;
-
- radx = ceil(radxf);
- rady = ceil(radyf);
-
- n = (2 * radx + 1) * (2 * rady + 1);
-
- /* create a full filter image */
- gausstab = MEM_mallocN(sizeof(float) * n, "filter tab");
- dgauss = gausstab;
- val = 0.0f;
- for (j = -rady; j <= rady; j++) {
- for (i = -radx; i <= radx; i++, dgauss++) {
- float fj = (float)j / radyf;
- float fi = (float)i / radxf;
- float dist = sqrt(fj * fj + fi * fi);
-
- // *dgauss= hexagon_filter(fi, fj);
- *dgauss = RE_filter_value(nbd->filtertype, dist);
-
- val += *dgauss;
- }
- }
-
- if (val != 0.0f) {
- val = 1.0f / val;
- for (j = n - 1; j >= 0; j--)
- gausstab[j] *= val;
- }
- else gausstab[4] = 1.0f;
-
- for (y = -rady + 1; y < imgy + rady - 1; y++) {
-
- if (y <= 0) srcd = img->rect;
- else if (y < imgy) srcd += pix * imgx;
- else srcd = img->rect + pix * (imgy - 1) * imgx;
-
- for (x = -radx + 1; x < imgx + radx - 1; x++) {
- int minxr = x - radx < 0 ? -x : -radx;
- int maxxr = x + radx >= imgx ? imgx - x - 1 : radx;
- int minyr = y - rady < 0 ? -y : -rady;
- int maxyr = y + rady > imgy - 1 ? imgy - y - 1 : rady;
-
- float *destd = new->rect + pix * ( (y + minyr) * imgx + x + minxr);
- float *dgausd = gausstab + (minyr + rady) * (2 * radx + 1) + minxr + radx;
-
- if (x <= 0) src = srcd;
- else if (x < imgx) src += pix;
- else src = srcd + pix * (imgx - 1);
-
- for (i = minyr; i <= maxyr; i++, destd += pix * imgx, dgausd += 2 * radx + 1) {
- dest = destd;
- dgauss = dgausd;
- for (j = minxr; j <= maxxr; j++, dest += pix, dgauss++) {
- val = *dgauss;
- if (val != 0.0f) {
- dest[0] += val * src[0];
- if (pix > 1) {
- dest[1] += val * src[1];
- dest[2] += val * src[2];
- dest[3] += val * src[3];
- }
- }
- }
- }
- }
- if (node->exec & NODE_BREAK)
- break;
- }
-
- MEM_freeN(gausstab);
-}
-
-
-/* reference has to be mapped 0-1, and equal in size */
-static void blur_with_reference(bNode *node, CompBuf *new, CompBuf *img, CompBuf *ref)
-{
- NodeBlurData *nbd = node->storage;
- CompBuf *blurbuf, *ref_use;
- register float sum, val;
- float rval, gval, bval, aval, radxf, radyf;
- float **maintabs;
- float *gausstabx, *gausstabcenty;
- float *gausstaby, *gausstabcentx;
- int radx, rady, imgx = img->x, imgy = img->y;
- int x, y, pix = img->type;
- int i, j;
- float *src, *dest, *refd, *blurd;
- float defcol[4] = {1.0f, 1.0f, 1.0f, 1.0f}; /* default color for compbuf_get_pixel */
- float proccol[4]; /* local color if compbuf is procedural */
- int refradx, refrady;
-
- if (ref->x != img->x || ref->y != img->y)
- return;
-
- ref_use = typecheck_compbuf(ref, CB_VAL);
-
- /* trick is; we blur the reference image... but only works with clipped values*/
- blurbuf = alloc_compbuf(imgx, imgy, CB_VAL, 1);
- blurbuf->xof = ref_use->xof;
- blurbuf->yof = ref_use->yof;
- blurd = blurbuf->rect;
- refd = ref_use->rect;
- for (x = imgx * imgy; x > 0; x--, refd++, blurd++) {
- if (refd[0] < 0.0f) blurd[0] = 0.0f;
- else if (refd[0] > 1.0f) blurd[0] = 1.0f;
- else blurd[0] = refd[0];
- }
-
- blur_single_image(node, blurbuf, blurbuf, 1.0f);
-
- /* horizontal */
- radx = (float)nbd->sizex;
- if (radx > imgx / 2)
- radx = imgx / 2;
- else if (radx < 1)
- radx = 1;
-
- /* vertical */
- rady = (float)nbd->sizey;
- if (rady > imgy / 2)
- rady = imgy / 2;
- else if (rady < 1)
- rady = 1;
-
- x = MAX2(radx, rady);
- maintabs = MEM_mallocN(x * sizeof(void *), "gauss array");
- for (i = 0; i < x; i++)
- maintabs[i] = make_gausstab(nbd->filtertype, i + 1);
-
- dest = new->rect;
- radxf = (float)radx;
- radyf = (float)rady;
-
- for (y = 0; y < imgy; y++) {
- for (x = 0; x < imgx; x++, dest += pix) {
- refd = compbuf_get_pixel(blurbuf, defcol, proccol, x - blurbuf->xrad, y - blurbuf->yrad, blurbuf->xrad, blurbuf->yrad);
- refradx = (int)(refd[0] * radxf);
- refrady = (int)(refd[0] * radyf);
-
- if (refradx > radx) refradx = radx;
- else if (refradx < 1) refradx = 1;
- if (refrady > rady) refrady = rady;
- else if (refrady < 1) refrady = 1;
-
- if (refradx == 1 && refrady == 1) {
- src = img->rect + pix * (y * imgx + x);
- if (pix == 1)
- dest[0] = src[0];
- else
- copy_v4_v4(dest, src);
- }
- else {
- int minxr = x - refradx < 0 ? -x : -refradx;
- int maxxr = x + refradx > imgx ? imgx - x : refradx;
- int minyr = y - refrady < 0 ? -y : -refrady;
- int maxyr = y + refrady > imgy ? imgy - y : refrady;
-
- float *srcd = img->rect + pix * ( (y + minyr) * imgx + x + minxr);
-
- gausstabx = maintabs[refradx - 1];
- gausstabcentx = gausstabx + refradx;
- gausstaby = maintabs[refrady - 1];
- gausstabcenty = gausstaby + refrady;
-
- sum = gval = rval = bval = aval = 0.0f;
-
- for (i = minyr; i < maxyr; i++, srcd += pix * imgx) {
- src = srcd;
- for (j = minxr; j < maxxr; j++, src += pix) {
-
- val = gausstabcenty[i] * gausstabcentx[j];
- sum += val;
- rval += val * src[0];
- if (pix > 1) {
- gval += val * src[1];
- bval += val * src[2];
- aval += val * src[3];
- }
- }
- }
- sum = 1.0f / sum;
- dest[0] = rval * sum;
- if (pix > 1) {
- dest[1] = gval * sum;
- dest[2] = bval * sum;
- dest[3] = aval * sum;
- }
- }
- }
- if (node->exec & NODE_BREAK)
- break;
- }
-
- free_compbuf(blurbuf);
-
- x = MAX2(radx, rady);
- for (i = 0; i < x; i++)
- MEM_freeN(maintabs[i]);
- MEM_freeN(maintabs);
-
- if (ref_use != ref)
- free_compbuf(ref_use);
-}
-
-static void node_composit_exec_blur(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
-{
- CompBuf *new, *img = in[0]->data;
- NodeBlurData *nbd = node->storage;
-
- if (img == NULL) return;
-
- /* store image in size that is needed for absolute/relative conversions on ui level */
- nbd->image_in_width = img->x;
- nbd->image_in_height = img->y;
-
- if (out[0]->hasoutput == 0) return;
-
- if (nbd->relative) {
- if (nbd->aspect == CMP_NODE_BLUR_ASPECT_NONE) {
- nbd->sizex = (int)(nbd->percentx * 0.01f * nbd->image_in_width);
- nbd->sizey = (int)(nbd->percenty * 0.01f * nbd->image_in_height);
- }
- else if (nbd->aspect == CMP_NODE_BLUR_ASPECT_Y) {
- nbd->sizex = (int)(nbd->percentx * 0.01f * nbd->image_in_width);
- nbd->sizey = (int)(nbd->percenty * 0.01f * nbd->image_in_width);
- }
- else if (nbd->aspect == CMP_NODE_BLUR_ASPECT_X) {
- nbd->sizex = (int)(nbd->percentx * 0.01f * nbd->image_in_height);
- nbd->sizey = (int)(nbd->percenty * 0.01f * nbd->image_in_height);
- }
- }
-
- if (nbd->sizex == 0 && nbd->sizey == 0) {
- new = pass_on_compbuf(img);
- out[0]->data = new;
- }
- else if (nbd->filtertype == R_FILTER_FAST_GAUSS) {
- if (in[1]->vec[0] < 0.001f) { /* time node inputs can be a tiny value */
- new = pass_on_compbuf(img);
- }
- else {
- // TODO: can this be mapped with reference, too?
- const float sx = ((float)nbd->sizex * in[1]->vec[0]) / 2.0f, sy = ((float)nbd->sizey * in[1]->vec[0]) / 2.0f;
- int c;
-
- if ((img == NULL) || (out[0]->hasoutput == 0)) return;
-
- if (img->type == CB_VEC2)
- new = typecheck_compbuf(img, CB_VAL);
- else if (img->type == CB_VEC3)
- new = typecheck_compbuf(img, CB_RGBA);
- else
- new = dupalloc_compbuf(img);
-
- if ((sx == sy) && (sx > 0.f)) {
- for (c = 0; c < new->type; ++c)
- IIR_gauss(new, sx, c, 3);
- }
- else {
- if (sx > 0.f) {
- for (c = 0; c < new->type; ++c)
- IIR_gauss(new, sx, c, 1);
- }
- if (sy > 0.f) {
- for (c = 0; c < new->type; ++c)
- IIR_gauss(new, sy, c, 2);
- }
- }
- }
- out[0]->data = new;
- }
- else {
- /* All non fast gauss blur methods */
- if (img->type == CB_VEC2 || img->type == CB_VEC3) {
- img = typecheck_compbuf(in[0]->data, CB_RGBA);
- }
-
- /* if fac input, we do it different */
- if (in[1]->data) {
- CompBuf *gammabuf;
-
- /* make output size of input image */
- new = alloc_compbuf(img->x, img->y, img->type, 1); /* allocs */
-
- /* accept image offsets from other nodes */
- new->xof = img->xof;
- new->yof = img->yof;
-
- if (nbd->gamma) {
- gammabuf = dupalloc_compbuf(img);
- gamma_correct_compbuf(gammabuf, 0);
- }
- else gammabuf = img;
-
- blur_with_reference(node, new, gammabuf, in[1]->data);
-
- if (nbd->gamma) {
- gamma_correct_compbuf(new, 1);
- free_compbuf(gammabuf);
- }
- if (node->exec & NODE_BREAK) {
- free_compbuf(new);
- new = NULL;
- }
- out[0]->data = new;
- }
- else {
-
- if (in[1]->vec[0] <= 0.001f) { /* time node inputs can be a tiny value */
- new = pass_on_compbuf(img);
- }
- else {
- CompBuf *gammabuf;
-
- /* make output size of input image */
- new = alloc_compbuf(img->x, img->y, img->type, 1); /* allocs */
-
- /* accept image offsets from other nodes */
- new->xof = img->xof;
- new->yof = img->yof;
-
- if (nbd->gamma) {
- gammabuf = dupalloc_compbuf(img);
- gamma_correct_compbuf(gammabuf, 0);
- }
- else gammabuf = img;
-
- if (nbd->bokeh)
- bokeh_single_image(node, new, gammabuf, in[1]->vec[0]);
- else if (1)
- blur_single_image(node, new, gammabuf, in[1]->vec[0]);
- else /* bloom experimental... */
- bloom_with_reference(new, gammabuf, NULL, in[1]->vec[0], nbd);
-
- if (nbd->gamma) {
- gamma_correct_compbuf(new, 1);
- free_compbuf(gammabuf);
- }
- if (node->exec & NODE_BREAK) {
- free_compbuf(new);
- new = NULL;
- }
- }
- out[0]->data = new;
- }
- if (img != in[0]->data)
- free_compbuf(img);
- }
-
- generate_preview(data, node, out[0]->data);
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_blur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_blur(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeBlurData *data = MEM_callocN(sizeof(NodeBlurData), "node blur data");
data->filtertype = R_FILTER_GAUSS;
node->storage = data;
}
-void register_node_type_cmp_blur(bNodeTreeType *ttype)
+void register_node_type_cmp_blur(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_BLUR, "Blur", NODE_CLASS_OP_FILTER, NODE_PREVIEW | NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_BLUR, "Blur", NODE_CLASS_OP_FILTER, NODE_PREVIEW | NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_blur_in, cmp_node_blur_out);
- node_type_size(&ntype, 120, 80, 200);
node_type_init(&ntype, node_composit_init_blur);
node_type_storage(&ntype, "NodeBlurData", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_blur);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_bokehblur.c b/source/blender/nodes/composite/nodes/node_composite_bokehblur.c
index 222ac7a5cdf..a2d9e6e1473 100644
--- a/source/blender/nodes/composite/nodes/node_composite_bokehblur.c
+++ b/source/blender/nodes/composite/nodes/node_composite_bokehblur.c
@@ -49,20 +49,19 @@ static bNodeSocketTemplate cmp_node_bokehblur_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_bokehblur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_bokehblur(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom3 = 4.0f;
node->custom4 = 16.0f;
}
-void register_node_type_cmp_bokehblur(bNodeTreeType *ttype)
+void register_node_type_cmp_bokehblur(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_BOKEHBLUR, "Bokeh Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_BOKEHBLUR, "Bokeh Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_bokehblur_in, cmp_node_bokehblur_out);
- node_type_size(&ntype, 120, 80, 200);
node_type_init(&ntype, node_composit_init_bokehblur);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_bokehimage.c b/source/blender/nodes/composite/nodes/node_composite_bokehimage.c
index 8324b77b2d1..c04682c42a6 100644
--- a/source/blender/nodes/composite/nodes/node_composite_bokehimage.c
+++ b/source/blender/nodes/composite/nodes/node_composite_bokehimage.c
@@ -36,12 +36,13 @@
#include "../node_composite_util.h"
/* **************** Bokeh image Tools ******************** */
-
+
static bNodeSocketTemplate cmp_node_bokehimage_out[] = {
{ SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
-static void node_composit_init_bokehimage(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+
+static void node_composit_init_bokehimage(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeBokehImage * data = MEM_callocN(sizeof(NodeBokehImage), "NodeBokehImage");
data->angle = 0.0f;
@@ -52,15 +53,14 @@ static void node_composit_init_bokehimage(bNodeTree *UNUSED(ntree), bNode *node,
node->storage = data;
}
-void register_node_type_cmp_bokehimage(bNodeTreeType *ttype)
+void register_node_type_cmp_bokehimage(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_BOKEHIMAGE, "Bokeh Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_BOKEHIMAGE, "Bokeh Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, cmp_node_bokehimage_out);
- node_type_size(&ntype, 140, 100, 320);
node_type_init(&ntype, node_composit_init_bokehimage);
node_type_storage(&ntype, "NodeBokehImage", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_boxmask.c b/source/blender/nodes/composite/nodes/node_composite_boxmask.c
index d3c6b2ccef0..41820457b4b 100644
--- a/source/blender/nodes/composite/nodes/node_composite_boxmask.c
+++ b/source/blender/nodes/composite/nodes/node_composite_boxmask.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate cmp_node_boxmask_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_boxmask(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_boxmask(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeBoxMask *data = MEM_callocN(sizeof(NodeBoxMask), "NodeBoxMask");
data->x = 0.5;
@@ -55,17 +55,16 @@ static void node_composit_init_boxmask(bNodeTree *UNUSED(ntree), bNode *node, bN
node->storage = data;
}
-void register_node_type_cmp_boxmask(bNodeTreeType *ttype)
+void register_node_type_cmp_boxmask(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MASK_BOX, "Box Mask", NODE_CLASS_MATTE, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MASK_BOX, "Box Mask", NODE_CLASS_MATTE, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_boxmask_in, cmp_node_boxmask_out);
- node_type_size(&ntype, 260, 110, 300);
node_type_init(&ntype, node_composit_init_boxmask);
node_type_storage(&ntype, "NodeBoxMask", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_brightness.c b/source/blender/nodes/composite/nodes/node_composite_brightness.c
index ecf572f59c7..669668fa654 100644
--- a/source/blender/nodes/composite/nodes/node_composite_brightness.c
+++ b/source/blender/nodes/composite/nodes/node_composite_brightness.c
@@ -47,65 +47,13 @@ static bNodeSocketTemplate cmp_node_brightcontrast_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-static void do_brightnesscontrast(bNode *UNUSED(node), float *out, float *in, float *in_brightness, float *in_contrast)
-{
- float i;
- int c;
- float a, b, v;
- float brightness = (*in_brightness) / 100.0f;
- float contrast = *in_contrast;
- float delta = contrast / 200.0f;
- a = 1.0f - delta * 2.0f;
- /*
- * The algorithm is by Werner D. Streidt
- * (http://visca.com/ffactory/archives/5-99/msg00021.html)
- * Extracted of OpenCV demhist.c
- */
- if (contrast > 0) {
- a = 1.0f / a;
- b = a * (brightness - delta);
- }
- else {
- delta *= -1;
- b = a * (brightness + delta);
- }
-
- for (c=0; c<3; c++) {
- i = in[c];
- v = a*i + b;
- out[c] = v;
- }
-}
-
-static void node_composit_exec_brightcontrast(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- if (out[0]->hasoutput==0)
- return;
-
- if (in[0]->data) {
- CompBuf *stackbuf, *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
- stackbuf= dupalloc_compbuf(cbuf);
- composit3_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, do_brightnesscontrast, CB_RGBA, CB_VAL, CB_VAL);
- out[0]->data = stackbuf;
- if (cbuf != in[0]->data)
- free_compbuf(cbuf);
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_brightcontrast(bNodeTreeType *ttype)
+void register_node_type_cmp_brightcontrast(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_brightcontrast_in, cmp_node_brightcontrast_out);
- node_type_size(&ntype, 140, 100, 320);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_brightcontrast);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_channelMatte.c b/source/blender/nodes/composite/nodes/node_composite_channelMatte.c
index 40dbbbb8dca..92cc55f511f 100644
--- a/source/blender/nodes/composite/nodes/node_composite_channelMatte.c
+++ b/source/blender/nodes/composite/nodes/node_composite_channelMatte.c
@@ -34,165 +34,18 @@
/* ******************* Channel Matte Node ********************************* */
-static bNodeSocketTemplate cmp_node_channel_matte_in[] ={
+static bNodeSocketTemplate cmp_node_channel_matte_in[] = {
{SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f},
{-1, 0, ""}
};
-static bNodeSocketTemplate cmp_node_channel_matte_out[] ={
+static bNodeSocketTemplate cmp_node_channel_matte_out[] = {
{SOCK_RGBA, 0, N_("Image")},
{SOCK_FLOAT, 0, N_("Matte")},
{-1, 0, ""}
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_normalized_rgba_to_ycca2(bNode *UNUSED(node), float *out, float *in)
-{
- /*normalize to the range 0.0 to 1.0) */
- rgb_to_ycc(in[0], in[1], in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601);
- out[0]=(out[0])/255.0f;
- out[1]=(out[1])/255.0f;
- out[2]=(out[2])/255.0f;
- out[3]=in[3];
-}
-
-static void do_normalized_ycca_to_rgba2(bNode *UNUSED(node), float *out, float *in)
-{
- /*un-normalize the normalize from above */
- in[0]=in[0]*255.0f;
- in[1]=in[1]*255.0f;
- in[2]=in[2]*255.0f;
- ycc_to_rgb(in[0], in[1], in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601);
- out[3]=in[3];
-}
-
-
-static void do_channel_matte(bNode *node, float *out, float *in)
-{
- NodeChroma *c=(NodeChroma *)node->storage;
- float alpha=0.0;
-
- switch (c->algorithm) {
- case 0: { /* Alpha=key_channel-limit channel */
- int key_channel=node->custom2-1;
- int limit_channel=c->channel-1;
- alpha=in[key_channel]-in[limit_channel];
- break;
- }
- case 1: { /* Alpha=G-MAX(R, B) */
- switch (node->custom2) {
- case 1:
- {
- alpha=in[0]-MAX2(in[1], in[2]);
- break;
- }
- case 2:
- {
- alpha=in[1]-MAX2(in[0], in[2]);
- break;
- }
- case 3:
- {
- alpha=in[2]-MAX2(in[0], in[1]);
- break;
- }
- default:
- break;
- }
- break;
- }
- default:
- break;
- }
-
- /*flip because 0.0 is transparent, not 1.0*/
- alpha=1-alpha;
-
- /* test range*/
- if (alpha>c->t1) {
- alpha=in[3]; /*whatever it was prior */
- }
- else if (alpha<c->t2) {
- alpha=0.0;
- }
- else {/*blend */
- alpha=(alpha-c->t2)/(c->t1-c->t2);
- }
-
-
- /* don't make something that was more transparent less transparent */
- if (alpha<in[3]) {
- out[3]=alpha;
- }
- else {
- out[3]=in[3];
- }
-}
-
-static void node_composit_exec_channel_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
-{
- CompBuf *cbuf;
- CompBuf *outbuf;
-
- if (in[0]->hasinput==0) return;
- if (in[0]->data==NULL) return;
- if (out[0]->hasoutput==0 && out[1]->hasoutput==0) return;
-
- cbuf=typecheck_compbuf(in[0]->data, CB_RGBA);
-
- outbuf=dupalloc_compbuf(cbuf);
-
- /*convert to colorspace*/
- switch (node->custom1) {
- case CMP_NODE_CHANNEL_MATTE_CS_RGB:
- break;
- case CMP_NODE_CHANNEL_MATTE_CS_HSV: /*HSV*/
- composit1_pixel_processor(node, outbuf, cbuf, in[1]->vec, do_rgba_to_hsva, CB_RGBA);
- break;
- case CMP_NODE_CHANNEL_MATTE_CS_YUV: /*YUV*/
- composit1_pixel_processor(node, outbuf, cbuf, in[1]->vec, do_rgba_to_yuva, CB_RGBA);
- break;
- case CMP_NODE_CHANNEL_MATTE_CS_YCC: /*YCC*/
- composit1_pixel_processor(node, outbuf, cbuf, in[1]->vec, do_normalized_rgba_to_ycca2, CB_RGBA);
- break;
- default:
- break;
- }
-
- /*use the selected channel information to do the key */
- composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_channel_matte, CB_RGBA);
-
- /*convert back to RGB colorspace in place*/
- switch (node->custom1) {
- case CMP_NODE_CHANNEL_MATTE_CS_RGB: /*RGB*/
- break;
- case CMP_NODE_CHANNEL_MATTE_CS_HSV: /*HSV*/
- composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_hsva_to_rgba, CB_RGBA);
- break;
- case CMP_NODE_CHANNEL_MATTE_CS_YUV: /*YUV*/
- composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_yuva_to_rgba, CB_RGBA);
- break;
- case CMP_NODE_CHANNEL_MATTE_CS_YCC: /*YCC*/
- composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_normalized_ycca_to_rgba2, CB_RGBA);
- break;
- default:
- break;
- }
-
- generate_preview(data, node, outbuf);
- out[0]->data=outbuf;
- if (out[1]->hasoutput)
- out[1]->data=valbuf_from_rgbabuf(outbuf, CHAN_A);
-
- if (cbuf!=in[0]->data)
- free_compbuf(cbuf);
-
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_channel_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_channel_matte(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
node->storage=c;
@@ -207,18 +60,14 @@ static void node_composit_init_channel_matte(bNodeTree *UNUSED(ntree), bNode *no
node->custom2= 2; /* Green Channel */
}
-void register_node_type_cmp_channel_matte(bNodeTreeType *ttype)
+void register_node_type_cmp_channel_matte(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_CHANNEL_MATTE, "Channel Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_CHANNEL_MATTE, "Channel Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_channel_matte_in, cmp_node_channel_matte_out);
- node_type_size(&ntype, 200, 80, 250);
node_type_init(&ntype, node_composit_init_channel_matte);
node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_channel_matte);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c b/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c
index f343f806d57..2e04ddb4f9f 100644
--- a/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c
+++ b/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c
@@ -45,137 +45,7 @@ static bNodeSocketTemplate cmp_node_chroma_out[] = {
{-1, 0, ""}
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_rgba_to_ycca_normalized(bNode *UNUSED(node), float *out, float *in)
-{
- rgb_to_ycc(in[0], in[1], in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601);
-
- //normalize to 0..1.0
- out[0]=out[0]/255.0f;
- out[1]=out[1]/255.0f;
- out[2]=out[2]/255.0f;
-
- //rescale to -1.0..1.0
- out[0]=(out[0]*2.0f)-1.0f;
- out[1]=(out[1]*2.0f)-1.0f;
- out[2]=(out[2]*2.0f)-1.0f;
-
- // out[0]=((out[0])-16)/255.0;
- // out[1]=((out[1])-128)/255.0;
- // out[2]=((out[2])-128)/255.0;
- out[3]=in[3];
-}
-
-static void do_ycca_to_rgba_normalized(bNode *UNUSED(node), float *out, float *in)
-{
- /*un-normalize the normalize from above */
- in[0]=(in[0]+1.0f)/2.0f;
- in[1]=(in[1]+1.0f)/2.0f;
- in[2]=(in[2]+1.0f)/2.0f;
-
- in[0]=(in[0]*255.0f);
- in[1]=(in[1]*255.0f);
- in[2]=(in[2]*255.0f);
-
- // in[0]=(in[0]*255.0)+16;
- // in[1]=(in[1]*255.0)+128;
- // in[2]=(in[2]*255.0)+128;
- ycc_to_rgb(in[0], in[1], in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601);
- out[3]=in[3];
-}
-
-static void do_chroma_key(bNode *node, float *out, float *in)
-{
- NodeChroma *c;
- float x, z, alpha;
- float theta, beta, angle, angle2;
- float kfg;
-
- c=node->storage;
-
- /* 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 chroma values*/
- theta=atan2(c->key[2], c->key[1]);
-
- /*rotate the cb and cr into x/z space */
- x=in[1]*cosf(theta)+in[2]*sinf(theta);
- z=in[2]*cosf(theta)-in[1]*sinf(theta);
-
- /*if within the acceptance angle */
- angle=c->t1; /* t1 is radians. */
-
- /* if kfg is <0 then the pixel is outside of the key color */
- kfg= x-(fabsf(z)/tanf(angle/2.0f));
-
- copy_v3_v3(out, in);
-
- if (kfg>0.0f) { /* found a pixel that is within key color */
- beta=atan2(z, x);
- angle2=c->t2; /* t2 is radians. */
-
- /* if beta is within the cutoff angle */
- if (fabsf(beta) < (angle2/2.0f)) {
- alpha=0.0;
- }
- else {
- alpha=1.0f-(kfg/c->fstrength);
- }
-
- /* don't make something that was more transparent less transparent */
- if (alpha<in[3]) {
- out[3]=alpha;
- }
- else {
- out[3]=in[3];
- }
- }
- else { /* make pixel just as transparent as it was before */
- out[3]=in[3];
- }
-}
-
-static void node_composit_exec_chroma_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
-{
- CompBuf *cbuf;
- CompBuf *chromabuf;
- NodeChroma *c;
-
- if (in[0]->hasinput==0) return;
- if (in[0]->data==NULL) return;
- if (out[0]->hasoutput==0 && out[1]->hasoutput==0) return;
-
- cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
-
- chromabuf= dupalloc_compbuf(cbuf);
-
- c=node->storage;
-
- /*convert rgbbuf to normalized chroma space*/
- composit1_pixel_processor(node, chromabuf, cbuf, in[0]->vec, do_rgba_to_ycca_normalized, CB_RGBA);
- /*convert key to normalized chroma color space */
- do_rgba_to_ycca_normalized(node, c->key, in[1]->vec);
-
- /*per pixel chroma key*/
- composit1_pixel_processor(node, chromabuf, chromabuf, in[0]->vec, do_chroma_key, CB_RGBA);
-
- /*convert back*/
- composit1_pixel_processor(node, chromabuf, chromabuf, in[0]->vec, do_ycca_to_rgba_normalized, CB_RGBA);
-
- out[0]->data= chromabuf;
- if (out[1]->hasoutput)
- out[1]->data= valbuf_from_rgbabuf(chromabuf, CHAN_A);
-
- generate_preview(data, node, chromabuf);
-
- if (cbuf!=in[0]->data)
- free_compbuf(cbuf);
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_chroma_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_chroma_matte(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
node->storage= c;
@@ -186,18 +56,14 @@ static void node_composit_init_chroma_matte(bNodeTree *UNUSED(ntree), bNode *nod
c->fstrength= 1.0f;
}
-void register_node_type_cmp_chroma_matte(bNodeTreeType *ttype)
+void register_node_type_cmp_chroma_matte(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_CHROMA_MATTE, "Chroma Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_CHROMA_MATTE, "Chroma Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_chroma_in, cmp_node_chroma_out);
- node_type_size(&ntype, 200, 80, 300);
node_type_init(&ntype, node_composit_init_chroma_matte);
node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_chroma_matte);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_colorMatte.c b/source/blender/nodes/composite/nodes/node_composite_colorMatte.c
index 07a6647d976..2ecb5e3fb7c 100644
--- a/source/blender/nodes/composite/nodes/node_composite_colorMatte.c
+++ b/source/blender/nodes/composite/nodes/node_composite_colorMatte.c
@@ -45,78 +45,7 @@ static bNodeSocketTemplate cmp_node_color_out[] = {
{-1, 0, ""}
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_color_key(bNode *node, float *out, float *in)
-{
- float h_wrap;
- NodeChroma *c;
- c=node->storage;
-
-
- copy_v3_v3(out, in);
-
- if (
- /* do hue last because it needs to wrap, and does some more checks */
-
- /* sat */ (fabsf(in[1]-c->key[1]) < c->t2) &&
- /* val */ (fabsf(in[2]-c->key[2]) < c->t3) &&
-
- /* multiply by 2 because it wraps on both sides of the hue,
- * otherwise 0.5 would key all hue's */
-
- /* hue */ ((h_wrap= 2.0f * fabsf(in[0]-c->key[0])) < c->t1 || (2.0f - h_wrap) < c->t1)
- ) {
- out[3]=0.0; /*make transparent*/
- }
-
- else { /*pixel is outside key color */
- out[3]=in[3]; /* make pixel just as transparent as it was before */
- }
-}
-
-static void node_composit_exec_color_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
-{
- CompBuf *cbuf;
- CompBuf *colorbuf;
- NodeChroma *c;
-
- if (in[0]->hasinput==0) return;
- if (in[0]->data==NULL) return;
- if (out[0]->hasoutput==0 && out[1]->hasoutput==0) return;
-
- cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
-
- colorbuf= dupalloc_compbuf(cbuf);
-
- c=node->storage;
-
- /*convert rgbbuf to hsv*/
- composit1_pixel_processor(node, colorbuf, cbuf, in[0]->vec, do_rgba_to_hsva, CB_RGBA);
-
- /*convert key to hsv*/
- do_rgba_to_hsva(node, c->key, in[1]->vec);
-
-
- /*per pixel color key*/
- composit1_pixel_processor(node, colorbuf, colorbuf, in[0]->vec, do_color_key, CB_RGBA);
-
- /*convert back*/
- composit1_pixel_processor(node, colorbuf, colorbuf, in[0]->vec, do_hsva_to_rgba, CB_RGBA);
-
- out[0]->data= colorbuf;
- if (out[1]->hasoutput)
- out[1]->data= valbuf_from_rgbabuf(colorbuf, CHAN_A);
-
- generate_preview(data, node, colorbuf);
-
- if (cbuf!=in[0]->data)
- free_compbuf(cbuf);
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_color_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_color_matte(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node color");
node->storage= c;
@@ -127,18 +56,14 @@ static void node_composit_init_color_matte(bNodeTree *UNUSED(ntree), bNode *node
c->fstrength= 1.0f;
}
-void register_node_type_cmp_color_matte(bNodeTreeType *ttype)
+void register_node_type_cmp_color_matte(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_COLOR_MATTE, "Color Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_COLOR_MATTE, "Color Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_color_in, cmp_node_color_out);
- node_type_size(&ntype, 200, 80, 300);
node_type_init(&ntype, node_composit_init_color_matte);
node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_color_matte);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_colorSpill.c b/source/blender/nodes/composite/nodes/node_composite_colorSpill.c
index 44a5ac9e968..60cfd7c90f3 100644
--- a/source/blender/nodes/composite/nodes/node_composite_colorSpill.c
+++ b/source/blender/nodes/composite/nodes/node_composite_colorSpill.c
@@ -43,282 +43,7 @@ static bNodeSocketTemplate cmp_node_color_spill_out[] = {
{-1, 0, ""}
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-#define AVG(a, b) ((a + b) / 2)
-
-
-static void do_simple_spillmap_red(bNode *node, float* out, float *in)
-{
- NodeColorspill *ncs;
- ncs=node->storage;
- out[0]=in[0]-( ncs->limscale * in[ncs->limchan] );
-}
-
-static void do_simple_spillmap_red_fac(bNode *node, float* out, float *in, float *fac)
-{
- NodeColorspill *ncs;
- ncs=node->storage;
-
- out[0] = *fac * (in[0]-( ncs->limscale * in[ncs->limchan]));
-}
-
-static void do_simple_spillmap_green(bNode *node, float* out, float *in)
-{
- NodeColorspill *ncs;
- ncs=node->storage;
- out[0]=in[1]-( ncs->limscale * in[ncs->limchan] );
-}
-
-static void do_simple_spillmap_green_fac(bNode *node, float* out, float *in, float *fac)
-{
- NodeColorspill *ncs;
- ncs=node->storage;
-
- out[0] = *fac * (in[1]-( ncs->limscale * in[ncs->limchan]));
-}
-
-static void do_simple_spillmap_blue(bNode *node, float* out, float *in)
-{
- NodeColorspill *ncs;
- ncs=node->storage;
- out[0]=in[2]-( ncs->limscale * in[ncs->limchan] );
-}
-
-static void do_simple_spillmap_blue_fac(bNode *node, float* out, float *in, float *fac)
-{
- NodeColorspill *ncs;
- ncs=node->storage;
-
- out[0] = *fac * (in[2]-( ncs->limscale * in[ncs->limchan]));
-}
-
-static void do_average_spillmap_red(bNode *node, float* out, float *in)
-{
- NodeColorspill *ncs;
- ncs=node->storage;
- out[0]=in[0]-(ncs->limscale * AVG(in[1], in[2]) );
-}
-
-static void do_average_spillmap_red_fac(bNode *node, float* out, float *in, float *fac)
-{
- NodeColorspill *ncs;
- ncs=node->storage;
-
- out[0] = *fac * (in[0]-(ncs->limscale * AVG(in[1], in[2]) ));
-}
-
-static void do_average_spillmap_green(bNode *node, float* out, float *in)
-{
- NodeColorspill *ncs;
- ncs=node->storage;
- out[0]=in[1]-(ncs->limscale * AVG(in[0], in[2]) );
-}
-
-static void do_average_spillmap_green_fac(bNode *node, float* out, float *in, float *fac)
-{
- NodeColorspill *ncs;
- ncs=node->storage;
-
- out[0] = *fac * (in[0]-(ncs->limscale * AVG(in[0], in[2]) ));
-}
-
-static void do_average_spillmap_blue(bNode *node, float* out, float *in)
-{
- NodeColorspill *ncs;
- ncs=node->storage;
- out[0]=in[2]-(ncs->limscale * AVG(in[0], in[1]) );
-}
-
-static void do_average_spillmap_blue_fac(bNode *node, float* out, float *in, float *fac)
-{
- NodeColorspill *ncs;
- ncs=node->storage;
-
- out[0] = *fac * (in[0]-(ncs->limscale * AVG(in[0], in[1]) ));
-}
-
-static void do_apply_spillmap_red(bNode *node, float* out, float *in, float *map)
-{
- NodeColorspill *ncs;
- ncs=node->storage;
- if (map[0]>0) {
- out[0]=in[0]-(ncs->uspillr*map[0]);
- out[1]=in[1]+(ncs->uspillg*map[0]);
- out[2]=in[2]+(ncs->uspillb*map[0]);
- }
- else {
- out[0]=in[0];
- out[1]=in[1];
- out[2]=in[2];
- }
-}
-
-static void do_apply_spillmap_green(bNode *node, float* out, float *in, float *map)
-{
- NodeColorspill *ncs;
- ncs=node->storage;
- if (map[0]>0) {
- out[0]=in[0]+(ncs->uspillr*map[0]);
- out[1]=in[1]-(ncs->uspillg*map[0]);
- out[2]=in[2]+(ncs->uspillb*map[0]);
- }
- else {
- out[0]=in[0];
- out[1]=in[1];
- out[2]=in[2];
- }
-}
-
-static void do_apply_spillmap_blue(bNode *node, float* out, float *in, float *map)
-{
- NodeColorspill *ncs;
- ncs=node->storage;
- if (map[0]>0) {
- out[0]=in[0]+(ncs->uspillr*map[0]);
- out[1]=in[1]+(ncs->uspillg*map[0]);
- out[2]=in[2]-(ncs->uspillb*map[0]);
- }
- else {
- out[0]=in[0];
- out[1]=in[1];
- out[2]=in[2];
- }
-}
-
-static void node_composit_exec_color_spill(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* Originally based on the information from the book "The Art and Science of Digital Composition" and
- * discussions from vfxtalk.com .*/
- CompBuf *cbuf;
- /* CompBuf *mask; */ /* UNUSED */
- CompBuf *rgbbuf;
- CompBuf *spillmap;
- NodeColorspill *ncs;
- ncs=node->storage;
-
- /* early out for missing connections */
- if (out[0]->hasoutput==0 ) return;
- if (in[0]->hasinput==0) return;
- if (in[0]->data==NULL) return;
-
- cbuf=typecheck_compbuf(in[0]->data, CB_RGBA);
- /* mask= */ /* UNUSED */ typecheck_compbuf(in[1]->data, CB_VAL);
- spillmap=alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1);
- rgbbuf=dupalloc_compbuf(cbuf);
-
- switch (node->custom1) {
- case 1: /*red spill*/
- {
- switch (node->custom2) {
- case 0: /* simple limit */
- {
- if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
- composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_red, CB_RGBA);
- }
- else {
- composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_red_fac, CB_RGBA, CB_VAL);
- }
- break;
- }
- case 1: /* average limit */
- {
- if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
- composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_red, CB_RGBA);
- }
- else {
- composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_red_fac, CB_RGBA, CB_VAL);
- }
- break;
- }
- }
- if (ncs->unspill==0) {
- ncs->uspillr=1.0f;
- ncs->uspillg=0.0f;
- ncs->uspillb=0.0f;
- }
- composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_red, CB_RGBA, CB_VAL);
- break;
- }
- case 2: /*green spill*/
- {
- switch (node->custom2) {
- case 0: /* simple limit */
- {
- if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
- composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_green, CB_RGBA);
- }
- else {
- composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_green_fac, CB_RGBA, CB_VAL);
- }
- break;
- }
- case 1: /* average limit */
- {
- if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
- composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_green, CB_RGBA);
- }
- else {
- composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_green_fac, CB_RGBA, CB_VAL);
- }
- break;
- }
- }
- if (ncs->unspill==0) {
- ncs->uspillr=0.0f;
- ncs->uspillg=1.0f;
- ncs->uspillb=0.0f;
- }
- composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_green, CB_RGBA, CB_VAL);
- break;
- }
- case 3: /*blue spill*/
- {
- switch (node->custom2) {
- case 0: /* simple limit */
- {
- if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
- composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_blue, CB_RGBA);
- }
- else {
- composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_blue_fac, CB_RGBA, CB_VAL);
- }
- break;
- }
- case 1: /* average limit */
- {
- if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
- composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_blue, CB_RGBA);
- }
- else {
- composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_blue_fac, CB_RGBA, CB_VAL);
- }
- break;
- }
- }
- if (ncs->unspill==0) {
- ncs->uspillr=0.0f;
- ncs->uspillg=0.0f;
- ncs->uspillb=1.0f;
- }
- composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_blue, CB_RGBA, CB_VAL);
- break;
- }
- default:
- break;
- }
-
- out[0]->data=rgbbuf;
-
- if (cbuf!=in[0]->data)
- free_compbuf(cbuf);
-
- free_compbuf(spillmap);
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_color_spill(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_color_spill(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeColorspill *ncs= MEM_callocN(sizeof(NodeColorspill), "node colorspill");
node->storage=ncs;
@@ -329,18 +54,14 @@ static void node_composit_init_color_spill(bNodeTree *UNUSED(ntree), bNode *node
ncs->unspill=0; /* do not use unspill */
}
-void register_node_type_cmp_color_spill(bNodeTreeType *ttype)
+void register_node_type_cmp_color_spill(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_COLOR_SPILL, "Color Spill", NODE_CLASS_MATTE, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_COLOR_SPILL, "Color Spill", NODE_CLASS_MATTE, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_color_spill_in, cmp_node_color_spill_out);
- node_type_size(&ntype, 140, 80, 200);
node_type_init(&ntype, node_composit_init_color_spill);
node_type_storage(&ntype, "NodeColorspill", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_color_spill);
-#endif
- nodeRegisterType(ttype, &ntype);
+ 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 df49e537788..693680f58a8 100644
--- a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c
+++ b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c
@@ -46,139 +46,7 @@ static bNodeSocketTemplate cmp_node_colorbalance_out[] = {
{-1, 0, ""}
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-/* this function implements ASC-CDL according to the spec at http://www.asctech.org/
- * Slope
- * S = in * slope
- * Offset
- * O = S + offset
- * = (in * slope) + offset
- * Power
- * out = Clamp(O) ^ power
- * = Clamp((in * slope) + offset) ^ power
- */
-DO_INLINE float colorbalance_cdl(float in, float offset, float power, float slope)
-{
- float x = in * slope + offset;
-
- /* prevent NaN */
- CLAMP(x, 0.0f, 1.0f);
-
- return powf(x, power);
-}
-
-/* note: lift_lgg is just 2-lift, gamma_inv is 1.0/gamma */
-DO_INLINE float colorbalance_lgg(float in, float lift_lgg, float gamma_inv, float gain)
-{
- /* 1:1 match with the sequencer with linear/srgb conversions, the conversion isn't pretty
- * but best keep it this way, since testing for durian shows a similar calculation
- * without lin/srgb conversions gives bad results (over-saturated shadows) with colors
- * slightly below 1.0. some correction can be done but it ends up looking bad for shadows or lighter tones - campbell */
- float x= (((linearrgb_to_srgb(in) - 1.0f) * lift_lgg) + 1.0f) * gain;
-
- /* prevent NaN */
- if (x < 0.f) x = 0.f;
-
- return powf(srgb_to_linearrgb(x), gamma_inv);
-}
-
-static void do_colorbalance_cdl(bNode *node, float* out, float *in)
-{
- NodeColorBalance *n= (NodeColorBalance *)node->storage;
-
- out[0] = colorbalance_cdl(in[0], n->lift[0], n->gamma[0], n->gain[0]);
- out[1] = colorbalance_cdl(in[1], n->lift[1], n->gamma[1], n->gain[1]);
- out[2] = colorbalance_cdl(in[2], n->lift[2], n->gamma[2], n->gain[2]);
- out[3] = in[3];
-}
-
-static void do_colorbalance_cdl_fac(bNode *node, float* out, float *in, float *fac)
-{
- NodeColorBalance *n= (NodeColorBalance *)node->storage;
- const float mfac= 1.0f - *fac;
-
- out[0] = mfac*in[0] + *fac * colorbalance_cdl(in[0], n->lift[0], n->gamma[0], n->gain[0]);
- out[1] = mfac*in[1] + *fac * colorbalance_cdl(in[1], n->lift[1], n->gamma[1], n->gain[1]);
- out[2] = mfac*in[2] + *fac * colorbalance_cdl(in[2], n->lift[2], n->gamma[2], n->gain[2]);
- out[3] = in[3];
-}
-
-static void do_colorbalance_lgg(bNode *node, float* out, float *in)
-{
- NodeColorBalance *n= (NodeColorBalance *)node->storage;
-
- out[0] = colorbalance_lgg(in[0], n->lift_lgg[0], n->gamma_inv[0], n->gain[0]);
- out[1] = colorbalance_lgg(in[1], n->lift_lgg[1], n->gamma_inv[1], n->gain[1]);
- out[2] = colorbalance_lgg(in[2], n->lift_lgg[2], n->gamma_inv[2], n->gain[2]);
- out[3] = in[3];
-}
-
-static void do_colorbalance_lgg_fac(bNode *node, float* out, float *in, float *fac)
-{
- NodeColorBalance *n= (NodeColorBalance *)node->storage;
- const float mfac= 1.0f - *fac;
-
- out[0] = mfac*in[0] + *fac * colorbalance_lgg(in[0], n->lift_lgg[0], n->gamma_inv[0], n->gain[0]);
- out[1] = mfac*in[1] + *fac * colorbalance_lgg(in[1], n->lift_lgg[1], n->gamma_inv[1], n->gain[1]);
- out[2] = mfac*in[2] + *fac * colorbalance_lgg(in[2], n->lift_lgg[2], n->gamma_inv[2], n->gain[2]);
- out[3] = in[3];
-}
-
-static void node_composit_exec_colorbalance(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- CompBuf *cbuf= in[1]->data;
- CompBuf *stackbuf;
-
- /* stack order input: fac, image */
- /* stack order output: image */
- if (out[0]->hasoutput==0) return;
-
- if (in[0]->vec[0] == 0.f && in[0]->data == NULL) {
- out[0]->data = pass_on_compbuf(cbuf);
- return;
- }
-
- {
- NodeColorBalance *n= (NodeColorBalance *)node->storage;
- int c;
-
- for (c = 0; c < 3; c++) {
- n->lift_lgg[c] = 2.0f - n->lift[c];
- n->gamma_inv[c] = (n->gamma[c] != 0.0f) ? 1.0f/n->gamma[c] : 1000000.0f;
- }
- }
-
- if (cbuf) {
- stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* create output based on image input */
-
- if (node->custom1 == 0) {
- /* lift gamma gain */
- if ((in[0]->data==NULL) && (in[0]->vec[0] >= 1.f)) {
- composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_colorbalance_lgg, CB_RGBA);
- }
- else {
- composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, in[0]->vec, do_colorbalance_lgg_fac, CB_RGBA, CB_VAL);
- }
- }
- else {
- /* offset/power/slope : ASC-CDL */
- if ((in[0]->data==NULL) && (in[0]->vec[0] >= 1.f)) {
- composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_colorbalance_cdl, CB_RGBA);
- }
- else {
- composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, in[0]->vec, do_colorbalance_cdl_fac, CB_RGBA, CB_VAL);
- }
-
- }
-
- out[0]->data=stackbuf;
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_colorbalance(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_colorbalance(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeColorBalance *n= node->storage= MEM_callocN(sizeof(NodeColorBalance), "node colorbalance");
@@ -187,18 +55,15 @@ static void node_composit_init_colorbalance(bNodeTree *UNUSED(ntree), bNode *nod
n->gain[0] = n->gain[1] = n->gain[2] = 1.0f;
}
-void register_node_type_cmp_colorbalance(bNodeTreeType *ttype)
+void register_node_type_cmp_colorbalance(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_COLORBALANCE, "Color Balance", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_COLORBALANCE, "Color Balance", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_colorbalance_in, cmp_node_colorbalance_out);
node_type_size(&ntype, 400, 200, 400);
node_type_init(&ntype, node_composit_init_colorbalance);
node_type_storage(&ntype, "NodeColorBalance", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_colorbalance);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_colorcorrection.c b/source/blender/nodes/composite/nodes/node_composite_colorcorrection.c
index 526f8472992..9b09462ed0f 100644
--- a/source/blender/nodes/composite/nodes/node_composite_colorcorrection.c
+++ b/source/blender/nodes/composite/nodes/node_composite_colorcorrection.c
@@ -47,7 +47,7 @@ static bNodeSocketTemplate cmp_node_colorcorrection_out[] = {
{ -1,0,""}
};
-static void node_composit_init_colorcorrection(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_colorcorrection(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeColorCorrection *n= node->storage= MEM_callocN(sizeof(NodeColorCorrection), "node colorcorrection");
n->startmidtones = 0.2f;
@@ -75,15 +75,15 @@ static void node_composit_init_colorcorrection(bNodeTree *UNUSED(ntree), bNode *
node->custom1 = 7; // red + green + blue enabled
}
-void register_node_type_cmp_colorcorrection(bNodeTreeType *ttype)
+void register_node_type_cmp_colorcorrection(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_COLORCORRECTION, "Color Correction", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_COLORCORRECTION, "Color Correction", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_colorcorrection_in, cmp_node_colorcorrection_out);
- node_type_size(&ntype, 400, 200, 500);
+ node_type_size(&ntype, 400, 200, 600);
node_type_init(&ntype, node_composit_init_colorcorrection);
node_type_storage(&ntype, "NodeColorCorrection", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_common.c b/source/blender/nodes/composite/nodes/node_composite_common.c
index 10b81cdaaa0..44643724073 100644
--- a/source/blender/nodes/composite/nodes/node_composite_common.c
+++ b/source/blender/nodes/composite/nodes/node_composite_common.c
@@ -32,202 +32,36 @@
#include "DNA_node_types.h"
-#include "BKE_node.h"
-
#include "node_composite_util.h"
+#include "NOD_common.h"
#include "node_common.h"
#include "node_exec.h"
-#if 0
-static void PRINT_BUFFERS(bNodeTreeExec *exec)
-{
- bNodeTree *ntree= exec->nodetree;
- bNode *node;
- bNodeSocket *sock;
- bNodeStack *ns;
- int i;
-
- printf("-------------- DEBUG --------------\n");
- for (sock=ntree->inputs.first, i=0; sock; sock=sock->next, ++i) {
- ns = node_get_socket_stack(exec->stack, sock);
- printf("%d. Tree Input %s", i, sock->name);
- if (ns->external)
- printf(" (external)");
- printf(": data=%p\n", ns->data);
- }
- for (sock=ntree->outputs.first, i=0; sock; sock=sock->next, ++i) {
- ns = node_get_socket_stack(exec->stack, sock);
- printf("%d. Tree Output %s", i, sock->name);
- if (ns->external)
- printf(" (external)");
- printf(": data=%p\n", ns->data);
- }
- for (node=ntree->nodes.first; node; node=node->next) {
- printf("Node %s:\n", node->name);
- for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) {
- ns = node_get_socket_stack(exec->stack, sock);
- printf("\t%d. Input %s", i, sock->name);
- if (ns->external)
- printf(" (external)");
- printf(": data=%p\n", ns->data);
- }
- for (sock=node->outputs.first, i=0; sock; sock=sock->next, ++i) {
- ns = node_get_socket_stack(exec->stack, sock);
- printf("\t%d. Output %s", i, sock->name);
- if (ns->external)
- printf(" (external)");
- printf(": data=%p\n", ns->data);
- }
- }
-}
-#endif
-
-static void copy_stack(bNodeStack *to, bNodeStack *from)
-{
- if (to != from) {
- copy_v4_v4(to->vec, from->vec);
- to->data = from->data;
- to->datatype = from->datatype;
-
- /* tag as copy to prevent freeing */
- to->is_copy = 1;
- }
-}
-
-static void move_stack(bNodeStack *to, bNodeStack *from)
-{
- if (to != from) {
- copy_v4_v4(to->vec, from->vec);
- to->data = from->data;
- to->datatype = from->datatype;
- to->is_copy = from->is_copy;
-
- zero_v4(from->vec);
- from->data = NULL;
- from->datatype = 0;
- from->is_copy = 0;
- }
-}
-
-/**** GROUP ****/
-
-static void *group_initexec(bNode *node)
-{
- bNodeTree *ngroup = (bNodeTree *)node->id;
- bNodeTreeExec *exec;
- bNodeSocket *sock;
- bNodeStack *ns;
-
- if (!ngroup)
- return NULL;
-
- /* initialize the internal node tree execution */
- exec = ntreeCompositBeginExecTree(ngroup, 0);
-
- /* tag group outputs as external to prevent freeing */
- for (sock = ngroup->outputs.first; sock; sock = sock->next) {
- if (!(sock->flag & SOCK_INTERNAL)) {
- ns = node_get_socket_stack(exec->stack, sock);
- ns->external = 1;
- }
- }
-
- return exec;
-}
-
-static void group_freeexec(bNode *UNUSED(node), void *nodedata)
-{
- bNodeTreeExec *gexec = (bNodeTreeExec *)nodedata;
-
- if (gexec)
- ntreeCompositEndExecTree(gexec, 0);
-}
-
-/* Copy inputs to the internal stack.
- * This is a shallow copy, no buffers are duplicated here!
- */
-static void group_copy_inputs(bNode *node, bNodeStack **in, bNodeStack *gstack)
-{
- bNodeSocket *sock;
- bNodeStack *ns;
- int a;
- for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) {
- if (sock->groupsock) {
- ns = node_get_socket_stack(gstack, sock->groupsock);
- copy_stack(ns, in[a]);
- }
- }
-}
-
-/* Copy internal results to the external outputs.
- */
-static void group_move_outputs(bNode *node, bNodeStack **out, bNodeStack *gstack)
-{
- bNodeSocket *sock;
- bNodeStack *ns;
- int a;
- for (sock = node->outputs.first, a = 0; sock; sock = sock->next, ++a) {
- if (sock->groupsock) {
- ns = node_get_socket_stack(gstack, sock->groupsock);
- move_stack(out[a], ns);
- }
- }
-}
-
-/* Free internal buffers */
-static void group_free_internal(bNodeTreeExec *gexec)
-{
- bNodeStack *ns;
- int i;
+#include "BKE_node.h"
- for (i = 0, ns = gexec->stack; i < gexec->stacksize; ++i, ++ns) {
- if (!ns->external && !ns->is_copy) {
- if (ns->data) {
-#ifdef WITH_COMPOSITOR_LEGACY
- free_compbuf(ns->data);
-#endif
- ns->data = NULL;
- }
- }
- }
-}
+#include "RNA_access.h"
-static void group_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
+void register_node_type_cmp_group(void)
{
- bNodeTreeExec *exec= (bNodeTreeExec *)nodedata;
-
- if (!exec)
- return;
+ static bNodeType ntype;
- /* XXX same behavior as trunk: all nodes inside group are executed.
- * it's stupid, but just makes it work. compo redesign will do this better.
+ /* NB: cannot use sh_node_type_base for node group, because it would map the node type
+ * to the shared NODE_GROUP integer type id.
*/
- {
- bNode *inode;
- for (inode=exec->nodetree->nodes.first; inode; inode=inode->next)
- inode->need_exec = 1;
- }
+ node_type_base_custom(&ntype, "CompositorNodeGroup", "Group", NODE_CLASS_GROUP, NODE_OPTIONS | NODE_CONST_OUTPUT);
+ ntype.type = NODE_GROUP;
+ ntype.poll = cmp_node_poll_default;
+ ntype.update_internal_links = node_update_internal_links_default;
+ ntype.ext.srna = RNA_struct_find("CompositorNodeGroup");
+ BLI_assert(ntype.ext.srna != NULL);
+ RNA_struct_blender_type_set(ntype.ext.srna, &ntype);
- group_copy_inputs(node, in, exec->stack);
- ntreeExecNodes(exec, data, thread);
- group_free_internal(exec);
- group_move_outputs(node, out, exec->stack);
-}
-
-void register_node_type_cmp_group(bNodeTreeType *ttype)
-{
- static bNodeType ntype;
-
- node_type_base(ttype, &ntype, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS | NODE_CONST_OUTPUT);
node_type_socket_templates(&ntype, NULL, NULL);
node_type_size(&ntype, 120, 60, 200);
node_type_label(&ntype, node_group_label);
- node_type_init(&ntype, node_group_init);
- node_type_valid(&ntype, node_group_valid);
- node_type_template(&ntype, node_group_template);
node_type_update(&ntype, NULL, node_group_verify);
- node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
- node_type_exec_new(&ntype, group_initexec, group_freeexec, group_execute);
+ strcpy(ntype.group_tree_idname, "CompositorNodeTree");
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
+
diff --git a/source/blender/nodes/composite/nodes/node_composite_composite.c b/source/blender/nodes/composite/nodes/node_composite_composite.c
index cb932b6a8de..7fa7a5048ab 100644
--- a/source/blender/nodes/composite/nodes/node_composite_composite.c
+++ b/source/blender/nodes/composite/nodes/node_composite_composite.c
@@ -39,78 +39,15 @@ static bNodeSocketTemplate cmp_node_composite_in[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-/* applies to render pipeline */
-static void node_composit_exec_composite(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
-{
- /* image assigned to output */
- /* stack order input sockets: col, alpha, z */
-
- if (node->flag & NODE_DO_OUTPUT) { /* only one works on out */
- Scene *scene= (Scene *)node->id;
- RenderData *rd= data;
-
- if (scene && (rd->scemode & R_DOCOMP)) {
- Render *re= RE_GetRender(scene->id.name);
- RenderResult *rr= RE_AcquireResultWrite(re);
- if (rr) {
- CompBuf *outbuf, *zbuf=NULL;
-
- if (rr->rectf)
- MEM_freeN(rr->rectf);
- outbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 1);
-
- if (in[1]->data==NULL)
- composit1_pixel_processor(node, outbuf, in[0]->data, in[0]->vec, do_copy_rgba, CB_RGBA);
- else
- composit2_pixel_processor(node, outbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba, CB_RGBA, CB_VAL);
-
- if (in[2]->data) {
- if (rr->rectz)
- MEM_freeN(rr->rectz);
- zbuf= alloc_compbuf(rr->rectx, rr->recty, CB_VAL, 1);
- composit1_pixel_processor(node, zbuf, in[2]->data, in[2]->vec, do_copy_value, CB_VAL);
- rr->rectz= zbuf->rect;
- zbuf->malloc= 0;
- free_compbuf(zbuf);
- }
- generate_preview(data, node, outbuf);
-
- /* we give outbuf to rr... */
- rr->rectf= outbuf->rect;
- outbuf->malloc= 0;
- free_compbuf(outbuf);
-
- /* signal for imageviewer to refresh (it converts to byte rects...) */
- BKE_image_signal(BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE);
-
- RE_ReleaseResult(re);
- return;
- }
- else
- RE_ReleaseResult(re);
- }
- }
- if (in[0]->data)
- generate_preview(data, node, in[0]->data);
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_composite(bNodeTreeType *ttype)
+void register_node_type_cmp_composite(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_COMPOSITE, "Composite", NODE_CLASS_OUTPUT, NODE_PREVIEW);
+ cmp_node_type_base(&ntype, CMP_NODE_COMPOSITE, "Composite", NODE_CLASS_OUTPUT, NODE_OPTIONS | NODE_PREVIEW);
node_type_socket_templates(&ntype, cmp_node_composite_in, NULL);
- node_type_size(&ntype, 80, 60, 200);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_composite);
-#endif
/* Do not allow muting for this node. */
node_type_internal_links(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_crop.c b/source/blender/nodes/composite/nodes/node_composite_crop.c
index ad51fae1998..677dafeb527 100644
--- a/source/blender/nodes/composite/nodes/node_composite_crop.c
+++ b/source/blender/nodes/composite/nodes/node_composite_crop.c
@@ -43,69 +43,7 @@ static bNodeSocketTemplate cmp_node_crop_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void node_composit_exec_crop(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- if (in[0]->data) {
- NodeTwoXYs *ntxy= node->storage;
- CompBuf *cbuf= in[0]->data;
- CompBuf *stackbuf;
- int x, y;
- float *srcfp, *outfp;
- rcti outputrect;
-
- if (node->custom2) {
- ntxy->x1= cbuf->x* ntxy->fac_x1;
- ntxy->x2= cbuf->x* ntxy->fac_x2;
- ntxy->y1= cbuf->y* ntxy->fac_y1;
- ntxy->y2= cbuf->y* ntxy->fac_y2;
- }
-
- /* check input image size */
- if (cbuf->x <= ntxy->x1 + 1)
- ntxy->x1= cbuf->x - 1;
-
- if (cbuf->y <= ntxy->y1 + 1)
- ntxy->y1= cbuf->y - 1;
-
- if (cbuf->x <= ntxy->x2 + 1)
- ntxy->x2= cbuf->x - 1;
-
- if (cbuf->y <= ntxy->y2 + 1)
- ntxy->y2= cbuf->y - 1;
-
- /* figure out the minimums and maximums */
- outputrect.xmax=MAX2(ntxy->x1, ntxy->x2) + 1;
- outputrect.xmin=MIN2(ntxy->x1, ntxy->x2);
- outputrect.ymax=MAX2(ntxy->y1, ntxy->y2) + 1;
- outputrect.ymin=MIN2(ntxy->y1, ntxy->y2);
-
- if (node->custom1) {
- /* this option crops the image size too */
- stackbuf= get_cropped_compbuf(&outputrect, cbuf->rect, cbuf->x, cbuf->y, cbuf->type);
- }
- else {
- /* this option won't crop the size of the image as well */
- /* allocate memory for the output image */
- stackbuf = alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1);
-
- /* select the cropped part of the image and set it to the output */
- for (y=outputrect.ymin; y<outputrect.ymax; y++) {
- srcfp= cbuf->rect + (y * cbuf->x + outputrect.xmin) * cbuf->type;
- outfp= stackbuf->rect + (y * stackbuf->x + outputrect.xmin) * stackbuf->type;
- for (x=outputrect.xmin; x<outputrect.xmax; x++, outfp+= stackbuf->type, srcfp+= cbuf->type)
- memcpy(outfp, srcfp, sizeof(float)*stackbuf->type);
- }
- }
-
- out[0]->data= stackbuf;
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_crop(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_crop(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTwoXYs *nxy= MEM_callocN(sizeof(NodeTwoXYs), "node xy data");
node->storage= nxy;
@@ -115,18 +53,14 @@ static void node_composit_init_crop(bNodeTree *UNUSED(ntree), bNode *node, bNode
nxy->y2= 0;
}
-void register_node_type_cmp_crop(bNodeTreeType *ttype)
+void register_node_type_cmp_crop(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_CROP, "Crop", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_CROP, "Crop", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_crop_in, cmp_node_crop_out);
- node_type_size(&ntype, 140, 100, 320);
node_type_init(&ntype, node_composit_init_crop);
node_type_storage(&ntype, "NodeTwoXYs", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_crop);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_curves.c b/source/blender/nodes/composite/nodes/node_composite_curves.c
index a1999ec8887..2bf901491bf 100644
--- a/source/blender/nodes/composite/nodes/node_composite_curves.c
+++ b/source/blender/nodes/composite/nodes/node_composite_curves.c
@@ -41,46 +41,24 @@ static bNodeSocketTemplate cmp_node_time_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void node_composit_exec_curves_time(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
-{
- RenderData *rd= data;
- /* stack order output: fac */
- float fac= 0.0f;
-
- if (node->custom1 < node->custom2)
- fac= (rd->cfra - node->custom1)/(float)(node->custom2-node->custom1);
-
- curvemapping_initialize(node->storage);
- fac = curvemapping_evaluateF(node->storage, 0, fac);
-
- out[0]->vec[0] = CLAMPIS(fac, 0.0f, 1.0f);
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_curves_time(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_curves_time(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom1= 1;
node->custom2= 250;
node->storage= curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
}
-void register_node_type_cmp_curve_time(bNodeTreeType *ttype)
+void register_node_type_cmp_curve_time(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_TIME, "Time", NODE_CLASS_INPUT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_TIME, "Time", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, cmp_node_time_out);
node_type_size(&ntype, 140, 100, 320);
node_type_init(&ntype, node_composit_init_curves_time);
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_curves_time);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -96,38 +74,22 @@ static bNodeSocketTemplate cmp_node_curve_vec_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void node_composit_exec_curve_vec(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order input: vec */
- /* stack order output: vec */
-
- curvemapping_initialize(node->storage);
- curvemapping_evaluate_premulRGBF(node->storage, out[0]->vec, in[0]->vec);
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_curve_vec(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_curve_vec(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f);
}
-void register_node_type_cmp_curve_vec(bNodeTreeType *ttype)
+void register_node_type_cmp_curve_vec(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_CURVE_VEC, "Vector Curves", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_CURVE_VEC, "Vector Curves", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_curve_vec_in, cmp_node_curve_vec_out);
node_type_size(&ntype, 200, 140, 320);
node_type_init(&ntype, node_composit_init_curve_vec);
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_curve_vec);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -145,84 +107,20 @@ static bNodeSocketTemplate cmp_node_curve_rgb_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_curves(bNode *node, float *out, float *in)
-{
- curvemapping_initialize(node->storage);
- curvemapping_evaluate_premulRGBF(node->storage, out, in);
- out[3] = in[3];
-}
-
-static void do_curves_fac(bNode *node, float *out, float *in, float *fac)
-{
- curvemapping_initialize(node->storage);
-
- if (*fac >= 1.0f)
- curvemapping_evaluate_premulRGBF(node->storage, out, in);
- else if (*fac <= 0.0f) {
- copy_v3_v3(out, in);
- }
- else {
- float col[4], mfac= 1.0f-*fac;
- curvemapping_evaluate_premulRGBF(node->storage, col, in);
- out[0] = mfac*in[0] + *fac*col[0];
- out[1] = mfac*in[1] + *fac*col[1];
- out[2] = mfac*in[2] + *fac*col[2];
- }
- out[3] = in[3];
-}
-
-static void node_composit_exec_curve_rgb(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order input: fac, image, black level, white level */
- /* stack order output: image */
-
- if (out[0]->hasoutput==0)
- return;
-
- curvemapping_initialize(node->storage);
-
- /* input no image? then only color operation */
- if (in[1]->data==NULL) {
- curvemapping_evaluateRGBF(node->storage, out[0]->vec, in[1]->vec);
- }
- else {
- /* make output size of input image */
- CompBuf *cbuf= in[1]->data;
- CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
-
- curvemapping_set_black_white(node->storage, in[2]->vec, in[3]->vec);
-
- if (in[0]->data==NULL && in[0]->vec[0] == 1.0f)
- composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_curves, CB_RGBA);
- else
- composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, in[0]->vec, do_curves_fac, CB_RGBA, CB_VAL);
-
- out[0]->data= stackbuf;
- }
-
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
}
-void register_node_type_cmp_curve_rgb(bNodeTreeType *ttype)
+void register_node_type_cmp_curve_rgb(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_curve_rgb_in, cmp_node_curve_rgb_out);
node_type_size(&ntype, 200, 140, 320);
node_type_init(&ntype, node_composit_init_curve_rgb);
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_curve_rgb);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_defocus.c b/source/blender/nodes/composite/nodes/node_composite_defocus.c
index 27ce0f7c4a7..9581ef981cb 100644
--- a/source/blender/nodes/composite/nodes/node_composite_defocus.c
+++ b/source/blender/nodes/composite/nodes/node_composite_defocus.c
@@ -44,831 +44,7 @@ static bNodeSocketTemplate cmp_node_defocus_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-// line coefs for point sampling & scancon. data.
-typedef struct BokehCoeffs {
- float x0, y0, dx, dy;
- float ls_x, ls_y;
- float min_x, min_y, max_x, max_y;
-} BokehCoeffs;
-
-// returns array of BokehCoeffs
-// returns length of array in 'len_bkh',
-// radius squared of inscribed disk in 'inradsq', needed in getWeight() test,
-// BKH[8] is the data returned for the bokeh shape & bkh_b[4] is it's 2d bound
-static void makeBokeh(char bktype, char ro, int* len_bkh, float* inradsq, BokehCoeffs BKH[8], float bkh_b[4])
-{
- float x0, x1, y0, y1, dx, dy, iDxy;
- /* ro now is in radians. */
- float w = MAX2(1e-6f, ro); // never reported stangely enough, but a zero offset causes missing center line...
- float wi = DEG2RADF(360.f/bktype);
- int i, ov, nv;
-
- // bktype must be at least 3 & <= 8
- bktype = (bktype<3) ? 3 : ((bktype>8) ? 8 : bktype);
- *len_bkh = bktype;
- *inradsq = -1.f;
-
- for (i=0; i<(*len_bkh); i++) {
- x0 = cos(w);
- y0 = sin(w);
- w += wi;
- x1 = cos(w);
- y1 = sin(w);
- if ((*inradsq)<0.f) {
- // radius squared of inscribed disk
- float idx=(x0+x1)*0.5f, idy=(y0+y1)*0.5f;
- *inradsq = idx*idx + idy*idy;
- }
- BKH[i].x0 = x0;
- BKH[i].y0 = y0;
- dx = x1-x0, dy = y1-y0;
- iDxy = 1.f / sqrtf(dx*dx + dy*dy);
- dx *= iDxy;
- dy *= iDxy;
- BKH[i].dx = dx;
- BKH[i].dy = dy;
- }
-
- // precalc scanconversion data
- // bokeh bound, not transformed, for scanconvert
- bkh_b[0] = bkh_b[2] = 1e10f; // xmin/ymin
- bkh_b[1] = bkh_b[3] = -1e10f; // xmax/ymax
- ov = (*len_bkh) - 1;
- for (nv=0; nv<(*len_bkh); nv++) {
- bkh_b[0] = MIN2(bkh_b[0], BKH[nv].x0); // xmin
- bkh_b[1] = MAX2(bkh_b[1], BKH[nv].x0); // xmax
- bkh_b[2] = MIN2(bkh_b[2], BKH[nv].y0); // ymin
- bkh_b[3] = MAX2(bkh_b[3], BKH[nv].y0); // ymax
- BKH[nv].min_x = MIN2(BKH[ov].x0, BKH[nv].x0);
- BKH[nv].max_x = MAX2(BKH[ov].x0, BKH[nv].x0);
- BKH[nv].min_y = MIN2(BKH[ov].y0, BKH[nv].y0);
- BKH[nv].max_y = MAX2(BKH[ov].y0, BKH[nv].y0);
- dy = BKH[nv].y0 - BKH[ov].y0;
- BKH[nv].ls_x = (BKH[nv].x0 - BKH[ov].x0) / ((dy==0.f) ? 1.f : dy);
- BKH[nv].ls_y = (BKH[nv].ls_x==0.f) ? 1.f : (1.f/BKH[nv].ls_x);
- ov = nv;
- }
-}
-
-// test if u/v inside shape & returns weight value
-static float getWeight(BokehCoeffs* BKH, int len_bkh, float u, float v, float rad, float inradsq)
-{
- BokehCoeffs* bc = BKH;
- float cdist, irad = (rad==0.f) ? 1.f : (1.f/rad);
- u *= irad;
- v *= irad;
-
- // early out test1: if point outside outer unit disk, it cannot be inside shape
- cdist = u*u + v*v;
- if (cdist>1.f) return 0.f;
-
- // early out test2: if point inside or on inner disk, point must be inside shape
- if (cdist<=inradsq) return 1.f;
-
- while (len_bkh--) {
- if ((bc->dy*(u - bc->x0) - bc->dx*(v - bc->y0)) > 0.f) return 0.f;
- bc++;
- }
- return 1.f;
-}
-
-// QMC.seq. for sampling, A.Keller, EMS
-static float RI_vdC(unsigned int bits, unsigned int r)
-{
- bits = ( bits << 16) | ( bits >> 16);
- bits = ((bits & 0x00ff00ff) << 8) | ((bits & 0xff00ff00) >> 8);
- bits = ((bits & 0x0f0f0f0f) << 4) | ((bits & 0xf0f0f0f0) >> 4);
- bits = ((bits & 0x33333333) << 2) | ((bits & 0xcccccccc) >> 2);
- bits = ((bits & 0x55555555) << 1) | ((bits & 0xaaaaaaaa) >> 1);
- bits ^= r;
- return (float)((double)bits / 4294967296.0);
-}
-
-// single channel IIR gaussian filtering
-// much faster than anything else, constant time independent of width
-// should extend to multichannel and make this a node, could be useful
-// note: this is an almost exact copy of 'IIR_gauss'
-static void IIR_gauss_single(CompBuf *buf, float sigma)
-{
- double q, q2, sc, cf[4], tsM[9], tsu[3], tsv[3];
- float *X, *Y, *W;
- const unsigned int src_width = buf->x;
- const unsigned int src_height = buf->y;
- unsigned int i, x, y, sz;
-
- // single channel only for now
- if (buf->type != CB_VAL) return;
-
- // <0.5 not valid, though can have a possibly useful sort of sharpening effect
- if (sigma < 0.5f) return;
-
- // see "Recursive Gabor Filtering" by Young/VanVliet
- // all factors here in double.prec. Required, because for single.prec it seems to blow up if sigma > ~200
- if (sigma >= 3.556f)
- q = 0.9804f * (sigma - 3.556f) + 2.5091f;
- else // sigma >= 0.5
- q = (0.0561f * sigma + 0.5784f) * sigma - 0.2568f;
- q2 = q * q;
- sc = (1.1668 + q) * (3.203729649 + (2.21566 + q) * q);
- // no gabor filtering here, so no complex multiplies, just the regular coefs.
- // all negated here, so as not to have to recalc Triggs/Sdika matrix
- cf[1] = q * (5.788961737 + (6.76492 + 3.0 * q) * q) / sc;
- cf[2] = -q2 * (3.38246 + 3.0 * q) / sc;
- // 0 & 3 unchanged
- cf[3] = q2 * q / sc;
- cf[0] = 1.0 - cf[1] - cf[2] - cf[3];
-
- // Triggs/Sdika border corrections,
- // it seems to work, not entirely sure if it is actually totally correct,
- // Besides J.M.Geusebroek's anigauss.c (see http://www.science.uva.nl/~mark),
- // found one other implementation by Cristoph Lampert,
- // but neither seem to be quite the same, result seems to be ok so far anyway.
- // Extra scale factor here to not have to do it in filter,
- // though maybe this had something to with the precision errors
- sc = cf[0] / ((1.0 + cf[1] - cf[2] + cf[3]) * (1.0 - cf[1] - cf[2] - cf[3]) * (1.0 + cf[2] + (cf[1] - cf[3]) * cf[3]));
- tsM[0] = sc * (-cf[3] * cf[1] + 1.0 - cf[3] * cf[3] - cf[2]);
- tsM[1] = sc * ((cf[3] + cf[1]) * (cf[2] + cf[3] * cf[1]));
- tsM[2] = sc * (cf[3] * (cf[1] + cf[3] * cf[2]));
- tsM[3] = sc * (cf[1] + cf[3] * cf[2]);
- tsM[4] = sc * (-(cf[2] - 1.0) * (cf[2] + cf[3] * cf[1]));
- tsM[5] = sc * (-(cf[3] * cf[1] + cf[3] * cf[3] + cf[2] - 1.0) * cf[3]);
- tsM[6] = sc * (cf[3] * cf[1] + cf[2] + cf[1] * cf[1] - cf[2] * cf[2]);
- tsM[7] = sc * (cf[1] * cf[2] + cf[3] * cf[2] * cf[2] - cf[1] * cf[3] * cf[3] - cf[3] * cf[3] * cf[3] - cf[3] * cf[2] + cf[3]);
- tsM[8] = sc * (cf[3] * (cf[1] + cf[3] * cf[2]));
-
-#define YVV(L) \
-{ \
- W[0] = cf[0] * X[0] + cf[1] * X[0] + cf[2] * X[0] + cf[3] * X[0]; \
- W[1] = cf[0] * X[1] + cf[1] * W[0] + cf[2] * X[0] + cf[3] * X[0]; \
- W[2] = cf[0] * X[2] + cf[1] * W[1] + cf[2] * W[0] + cf[3] * X[0]; \
- for (i = 3; i < L; i++) { \
- W[i] = cf[0] * X[i] + cf[1] * W[i - 1] + cf[2] * W[i - 2] + cf[3] * W[i - 3]; \
- } \
- tsu[0] = W[L - 1] - X[L - 1]; \
- tsu[1] = W[L - 2] - X[L - 1]; \
- tsu[2] = W[L - 3] - X[L - 1]; \
- tsv[0] = tsM[0] * tsu[0] + tsM[1] * tsu[1] + tsM[2] * tsu[2] + X[L - 1]; \
- tsv[1] = tsM[3] * tsu[0] + tsM[4] * tsu[1] + tsM[5] * tsu[2] + X[L - 1]; \
- tsv[2] = tsM[6] * tsu[0] + tsM[7] * tsu[1] + tsM[8] * tsu[2] + X[L - 1]; \
- Y[L - 1] = cf[0] * W[L - 1] + cf[1] * tsv[0] + cf[2] * tsv[1] + cf[3] * tsv[2]; \
- Y[L - 2] = cf[0] * W[L - 2] + cf[1] * Y[L - 1] + cf[2] * tsv[0] + cf[3] * tsv[1]; \
- Y[L - 3] = cf[0] * W[L - 3] + cf[1] * Y[L - 2] + cf[2] * Y[L - 1] + cf[3] * tsv[0]; \
- /* 'i != UINT_MAX' is really 'i >= 0', but necessary for unsigned int wrapping */ \
- for (i = L - 4; i != UINT_MAX; i--) { \
- Y[i] = cf[0] * W[i] + cf[1] * Y[i + 1] + cf[2] * Y[i + 2] + cf[3] * Y[i + 3]; \
- } \
-} (void)0
-
- // intermediate buffers
- sz = MAX2(src_width, src_height);
- Y = MEM_callocN(sz * sizeof(float), "IIR_gauss Y buf");
- W = MEM_callocN(sz * sizeof(float), "IIR_gauss W buf");
- // H
- for (y = 0; y < src_height; y++) {
- X = &buf->rect[y * src_width];
- YVV(src_width);
- memcpy(X, Y, sizeof(float) * src_width);
- }
- // V
- X = MEM_callocN(src_height * sizeof(float), "IIR_gauss X buf");
- for (x = 0; x < src_width; x++) {
- for (y = 0; y < src_height; y++)
- X[y] = buf->rect[x + y * src_width];
- YVV(src_height);
- for (y = 0; y < src_height; y++)
- buf->rect[x + y * src_width] = Y[y];
- }
- MEM_freeN(X);
-
- MEM_freeN(W);
- MEM_freeN(Y);
-#undef YVV
-}
-
-static void defocus_blur(bNode *node, CompBuf *new, CompBuf *img, CompBuf *zbuf, float inpval, int no_zbuf)
-{
- NodeDefocus *nqd = node->storage;
- CompBuf *wts; // weights buffer
- CompBuf *crad; // CoC radius buffer
- BokehCoeffs BKH[8]; // bokeh shape data, here never > 8 pts.
- float bkh_b[4] = {0}; // shape 2D bound
- float cam_fdist=1, cam_invfdist=1, cam_lens=35;
- float cam_sensor = DEFAULT_SENSOR_WIDTH;
- float dof_sp, maxfgc, bk_hn_theta=0, inradsq=0;
- int y, len_bkh=0, ydone = FALSE;
- float aspect, aperture;
- int minsz;
- //float bcrad, nmaxc, scf;
-
- // get some required params from the current scene camera
- // (ton) this is wrong, needs fixed
- Scene *scene= (Scene*)node->id;
- Object* camob = (scene)? scene->camera: NULL;
- if (camob && camob->type==OB_CAMERA) {
- Camera* cam = (Camera*)camob->data;
- cam_lens = cam->lens;
- cam_fdist = BKE_camera_object_dof_distance(camob);
- cam_sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
- if (cam_fdist == 0.0f) cam_fdist = 1e10f; /* if the dof is 0.0 then set it be be far away */
- cam_invfdist = 1.f / cam_fdist;
- }
- // guess work here.. best match with raytraced result
- minsz = MIN2(img->x, img->y);
- dof_sp = (float)minsz / ((cam_sensor / 2.0f) / cam_lens); // <- == aspect * MIN2(img->x, img->y) / tan(0.5f * fov);
-
- // aperture
- aspect = (img->x > img->y) ? (img->y / (float)img->x) : (img->x / (float)img->y);
- aperture = 0.5f * (cam_lens / (aspect * cam_sensor)) / nqd->fstop;
-
- // if not disk, make bokeh coefficients and other needed data
- if (nqd->bktype!=0) {
- makeBokeh(nqd->bktype, nqd->rotation, &len_bkh, &inradsq, BKH, bkh_b);
- bk_hn_theta = 0.5 * nqd->bktype * sin(2.0 * M_PI / nqd->bktype); // weight factor
- }
-
- // accumulated weights
- wts = alloc_compbuf(img->x, img->y, CB_VAL, 1);
- // CoC radius buffer
- crad = alloc_compbuf(img->x, img->y, CB_VAL, 1);
-
- // if 'no_zbuf' flag set (which is always set if input is not an image),
- // values are instead interpreted directly as blur radius values
- if (no_zbuf) {
- // to prevent *reaaallly* big radius values and impossible calculation times,
- // limit the maximum to half the image width or height, whichever is smaller
- float maxr = 0.5f*(float)MIN2(img->x, img->y);
- unsigned int p;
-
- for (p=0; p<(unsigned int)(img->x*img->y); p++) {
- crad->rect[p] = zbuf ? (zbuf->rect[p]*nqd->scale) : inpval;
- // bug #5921, limit minimum
- crad->rect[p] = MAX2(1e-5f, crad->rect[p]);
- crad->rect[p] = MIN2(crad->rect[p], maxr);
- // if maxblur!=0, limit maximum
- if (nqd->maxblur != 0.f) crad->rect[p] = MIN2(crad->rect[p], nqd->maxblur);
- }
- }
- else {
- float wt;
-
- // actual zbuffer.
- // separate foreground from background CoC's
- // then blur background and blend in again with foreground,
- // improves the 'blurred foreground overlapping in-focus midground' sharp boundary problem.
- // wts buffer here used for blendmask
- maxfgc = 0.f; // maximum foreground CoC radius
- for (y=0; y<img->y; y++) {
- unsigned int p = y * img->x;
- int x;
- for (x=0; x<img->x; x++) {
- unsigned int px = p + x;
- float iZ = (zbuf->rect[px]==0.f) ? 0.f : (1.f/zbuf->rect[px]);
- crad->rect[px] = 0.5f*(aperture*(dof_sp*(cam_invfdist - iZ) - 1.f));
- if (crad->rect[px] <= 0.f) {
- wts->rect[px] = 1.f;
- crad->rect[px] = -crad->rect[px];
- if (crad->rect[px] > maxfgc) maxfgc = crad->rect[px];
- }
- else crad->rect[px] = wts->rect[px] = 0;
- }
- }
-
- // fast blur...
- // bug #6656 part 1, probably when previous node_composite.c was split into separate files, it was not properly updated
- // to include recent cvs commits (well, at least not defocus node), so this part was missing...
- wt = min_ff(nqd->maxblur, aperture * 128.0f);
- IIR_gauss_single(crad, wt);
- IIR_gauss_single(wts, wt);
-
- // bug #6656 part 2a, although foreground blur is not based anymore on closest object,
- // the rescaling op below was still based on that anyway, and unlike the comment in below code,
- // the difference is therefore not always that small at all...
- // so for now commented out, not sure if this is going to cause other future problems, lets just wait and see...
- /*
- // find new maximum to scale it back to original
- // (could skip this, not strictly necessary, in general, difference is quite small, but just in case...)
- nmaxc = 0;
- for (p=0; p<(img->x*img->y); p++)
- if (crad->rect[p] > nmaxc) nmaxc = crad->rect[p];
- // rescale factor
- scf = (nmaxc==0.f) ? 1.f: (maxfgc / nmaxc);
- */
-
- // and blend...
- for (y=0; y<img->y; y++) {
- unsigned int p = y*img->x;
- int x;
-
- for (x=0; x<img->x; x++) {
- unsigned px = p + x;
- if (zbuf->rect[px]!=0.f) {
- float iZ = (zbuf->rect[px]==0.f) ? 0.f : (1.f/zbuf->rect[px]);
-
- // bug #6656 part 2b, do not rescale
- /*
- bcrad = 0.5f*fabs(aperture*(dof_sp*(cam_invfdist - iZ) - 1.f));
- // scale crad back to original maximum and blend
- crad->rect[px] = bcrad + wts->rect[px]*(scf*crad->rect[px] - bcrad);
- */
- crad->rect[px] = 0.5f*fabsf(aperture*(dof_sp*(cam_invfdist - iZ) - 1.f));
-
- // 'bug' #6615, limit minimum radius to 1 pixel, not really a solution, but somewhat mitigates the problem
- crad->rect[px] = MAX2(crad->rect[px], 0.5f);
- // if maxblur!=0, limit maximum
- if (nqd->maxblur != 0.f) crad->rect[px] = MIN2(crad->rect[px], nqd->maxblur);
- }
- else crad->rect[px] = 0.f;
- // clear weights for next part
- wts->rect[px] = 0.f;
- }
- // esc set by main calling process
- if (node->exec & NODE_BREAK)
- break;
- }
- }
-
- //------------------------------------------------------------------
- // main loop
-#ifndef __APPLE__ /* can crash on Mac, see bug #22856, disabled for now */
-#ifdef __INTEL_COMPILER /* icc doesn't like the compound statement -- internal error: 0_1506 */
- #pragma omp parallel for private(y) if (!nqd->preview) schedule(guided)
-#else
- #pragma omp parallel for private(y) if (!nqd->preview && img->y*img->x > 16384) schedule(guided)
-#endif
-#endif
- for (y=0; y<img->y; y++) {
- unsigned int p, p4, zp, cp, cp4;
- float *ctcol, u, v, ct_crad, cR2=0;
- int x, sx, sy;
-
- // some sort of visual feedback would be nice, or at least this text in the renderwin header
- // but for now just print some info in the console every 8 scanlines.
- #pragma omp critical
- {
- if (((ydone & 7)==0) || (ydone==(img->y-1))) {
- if (G.background==0) {
- printf("\rdefocus: Processing Line %d of %d ... ", ydone+1, img->y);
- fflush(stdout);
- }
- }
-
- ydone++;
- }
-
- // esc set by main calling process. don't break because openmp doesn't
- // allow it, just continue and do nothing
- if (node->exec & NODE_BREAK)
- continue;
-
- zp = y * img->x;
- for (x=0; x<img->x; x++) {
- cp = zp + x;
- cp4 = cp * img->type;
-
- // Circle of Confusion radius for current pixel
- cR2 = ct_crad = crad->rect[cp];
- // skip if zero (border render)
- if (ct_crad==0.f) {
- // related to bug #5921, forgot output image when skipping 0 radius values
- new->rect[cp4] = img->rect[cp4];
- if (new->type != CB_VAL) {
- new->rect[cp4+1] = img->rect[cp4+1];
- new->rect[cp4+2] = img->rect[cp4+2];
- new->rect[cp4+3] = img->rect[cp4+3];
- }
- continue;
- }
- cR2 *= cR2;
-
- // pixel color
- ctcol = &img->rect[cp4];
-
- if (!nqd->preview) {
- int xs, xe, ys, ye;
- float lwt, wtcol[4] = {0}, aacol[4] = {0};
- float wt;
-
- // shape weight
- if (nqd->bktype==0) // disk
- wt = 1.f/((float)M_PI*cR2);
- else
- wt = 1.f/(cR2*bk_hn_theta);
-
- // weighted color
- wtcol[0] = wt*ctcol[0];
- if (new->type != CB_VAL) {
- wtcol[1] = wt*ctcol[1];
- wtcol[2] = wt*ctcol[2];
- wtcol[3] = wt*ctcol[3];
- }
-
- // macro for background blur overlap test
- // unfortunately, since this is done per pixel,
- // it has a very significant negative impact on processing time...
- // (eg. aa disk blur without test: 112 sec, vs with test: 176 sec...)
- // iff center blur radius > threshold
- // and if overlap pixel in focus, do nothing, else add color/weigbt
- // (threshold constant is dependent on amount of blur)
- #define TESTBG1(c, w) {\
- if (ct_crad > nqd->bthresh) {\
- if (crad->rect[p] > nqd->bthresh) {\
- new->rect[p] += c[0];\
- wts->rect[p] += w;\
- }\
- }\
- else {\
- new->rect[p] += c[0];\
- wts->rect[p] += w;\
- }\
- }
- #define TESTBG4(c, w) {\
- if (ct_crad > nqd->bthresh) {\
- if (crad->rect[p] > nqd->bthresh) {\
- new->rect[p4] += c[0];\
- new->rect[p4+1] += c[1];\
- new->rect[p4+2] += c[2];\
- new->rect[p4+3] += c[3];\
- wts->rect[p] += w;\
- }\
- }\
- else {\
- new->rect[p4] += c[0];\
- new->rect[p4+1] += c[1];\
- new->rect[p4+2] += c[2];\
- new->rect[p4+3] += c[3];\
- wts->rect[p] += w;\
- }\
- }
- if (nqd->bktype == 0) {
- // Disk
- int _x, i, j, di;
- float Dj, T;
- // AA pixel
- #define AAPIX(a, b) {\
- int _ny = b;\
- if ((_ny >= 0) && (_ny < new->y)) {\
- int _nx = a;\
- if ((_nx >=0) && (_nx < new->x)) {\
- p = _ny*new->x + _nx;\
- if (new->type==CB_VAL) {\
- TESTBG1(aacol, lwt);\
- }\
- else {\
- p4 = p * new->type;\
- TESTBG4(aacol, lwt);\
- }\
- }\
- }\
- }
- // circle scanline
- #define CSCAN(a, b) {\
- int _ny = y + b;\
- if ((_ny >= 0) && (_ny < new->y)) {\
- xs = x - a + 1;\
- if (xs < 0) xs = 0;\
- xe = x + a;\
- if (xe > new->x) xe = new->x;\
- p = _ny*new->x + xs;\
- if (new->type==CB_VAL) {\
- for (_x=xs; _x<xe; _x++, p++) TESTBG1(wtcol, wt);\
- }\
- else {\
- p4 = p * new->type;\
- for (_x=xs; _x<xe; _x++, p++, p4+=new->type) TESTBG4(wtcol, wt);\
- }\
- }\
- }
-
- i = ceil(ct_crad);
- j = 0;
- T = 0;
- while (i > j) {
- Dj = sqrt(cR2 - j*j);
- Dj -= floorf(Dj);
- di = 0;
- if (Dj > T) { i--; di = 1; }
- T = Dj;
- aacol[0] = wtcol[0]*Dj;
- if (new->type != CB_VAL) {
- aacol[1] = wtcol[1]*Dj;
- aacol[2] = wtcol[2]*Dj;
- aacol[3] = wtcol[3]*Dj;
- }
- lwt = wt*Dj;
- if (i!=j) {
- // outer pixels
- AAPIX(x+j, y+i)
- AAPIX(x+j, y-i)
- if (j) {
- AAPIX(x-j, y+i) // BL
- AAPIX(x-j, y-i) // TL
- }
- if (di) { // only when i changed, interior of outer section
- CSCAN(j, i) // bottom
- CSCAN(j, -i) // top
- }
- }
- // lower mid section
- AAPIX(x+i, y+j)
- if (i) AAPIX(x-i, y+j)
- CSCAN(i, j)
- // upper mid section
- if (j) {
- AAPIX(x+i, y-j)
- if (i) AAPIX(x-i, y-j)
- CSCAN(i, -j)
- }
- j++;
- }
- #undef CSCAN
- #undef AAPIX
- }
- else {
- // n-agonal
- int ov, nv;
- float mind, maxd, lwt;
- ys = max_ii((int)floor(bkh_b[2] * ct_crad + y), 0);
- ye = min_ii((int)ceil(bkh_b[3] * ct_crad + y), new->y - 1);
- for (sy=ys; sy<=ye; sy++) {
- float fxs = 1e10f, fxe = -1e10f;
- float yf = (sy - y)/ct_crad;
- int found = 0;
- ov = len_bkh - 1;
- mind = maxd = 0;
- for (nv=0; nv<len_bkh; nv++) {
- if ((BKH[nv].max_y >= yf) && (BKH[nv].min_y <= yf)) {
- float tx = BKH[ov].x0 + BKH[nv].ls_x*(yf - BKH[ov].y0);
- if (tx < fxs) { fxs = tx; mind = BKH[nv].ls_x; }
- if (tx > fxe) { fxe = tx; maxd = BKH[nv].ls_x; }
- if (++found == 2) break;
- }
- ov = nv;
- }
- if (found) {
- fxs = fxs*ct_crad + x;
- fxe = fxe*ct_crad + x;
- xs = (int)floor(fxs), xe = (int)ceil(fxe);
- // AA hack for first and last x pixel, near vertical edges only
- if (fabsf(mind) <= 1.f) {
- if ((xs >= 0) && (xs < new->x)) {
- lwt = 1.f-(fxs - xs);
- aacol[0] = wtcol[0]*lwt;
- p = xs + sy*new->x;
- if (new->type==CB_VAL) {
- lwt *= wt;
- TESTBG1(aacol, lwt);
- }
- else {
- p4 = p * new->type;
- aacol[1] = wtcol[1]*lwt;
- aacol[2] = wtcol[2]*lwt;
- aacol[3] = wtcol[3]*lwt;
- lwt *= wt;
- TESTBG4(aacol, lwt);
- }
- }
- }
- if (fabsf(maxd) <= 1.f) {
- if ((xe >= 0) && (xe < new->x)) {
- lwt = 1.f-(xe - fxe);
- aacol[0] = wtcol[0]*lwt;
- p = xe + sy*new->x;
- if (new->type==CB_VAL) {
- lwt *= wt;
- TESTBG1(aacol, lwt);
- }
- else {
- p4 = p * new->type;
- aacol[1] = wtcol[1]*lwt;
- aacol[2] = wtcol[2]*lwt;
- aacol[3] = wtcol[3]*lwt;
- lwt *= wt;
- TESTBG4(aacol, lwt);
- }
- }
- }
- xs = MAX2(xs+1, 0);
- xe = MIN2(xe, new->x);
- // remaining interior scanline
- p = sy*new->x + xs;
- if (new->type==CB_VAL) {
- for (sx=xs; sx<xe; sx++, p++) TESTBG1(wtcol, wt);
- }
- else {
- p4 = p * new->type;
- for (sx=xs; sx<xe; sx++, p++, p4+=new->type) TESTBG4(wtcol, wt);
- }
- }
- }
-
- // now traverse in opposite direction, y scanlines,
- // but this time only draw the near horizontal edges,
- // applying same AA hack as above
- xs = MAX2((int)floor(bkh_b[0]*ct_crad + x), 0);
- xe = MIN2((int)ceil(bkh_b[1]*ct_crad + x), img->x - 1);
- for (sx=xs; sx<=xe; sx++) {
- float xf = (sx - x)/ct_crad;
- float fys = 1e10f, fye = -1e10f;
- int found = 0;
- ov = len_bkh - 1;
- mind = maxd = 0;
- for (nv=0; nv<len_bkh; nv++) {
- if ((BKH[nv].max_x >= xf) && (BKH[nv].min_x <= xf)) {
- float ty = BKH[ov].y0 + BKH[nv].ls_y*(xf - BKH[ov].x0);
- if (ty < fys) { fys = ty; mind = BKH[nv].ls_y; }
- if (ty > fye) { fye = ty; maxd = BKH[nv].ls_y; }
- if (++found == 2) break;
- }
- ov = nv;
- }
- if (found) {
- fys = fys*ct_crad + y;
- fye = fye*ct_crad + y;
- // near horizontal edges only, line slope <= 1
- if (fabsf(mind) <= 1.f) {
- int iys = (int)floor(fys);
- if ((iys >= 0) && (iys < new->y)) {
- lwt = 1.f - (fys - iys);
- aacol[0] = wtcol[0]*lwt;
- p = sx + iys*new->x;
- if (new->type==CB_VAL) {
- lwt *= wt;
- TESTBG1(aacol, lwt);
- }
- else {
- p4 = p * new->type;
- aacol[1] = wtcol[1]*lwt;
- aacol[2] = wtcol[2]*lwt;
- aacol[3] = wtcol[3]*lwt;
- lwt *= wt;
- TESTBG4(aacol, lwt);
- }
- }
- }
- if (fabsf(maxd) <= 1.f) {
- int iye = ceil(fye);
- if ((iye >= 0) && (iye < new->y)) {
- lwt = 1.f - (iye - fye);
- aacol[0] = wtcol[0]*lwt;
- p = sx + iye*new->x;
- if (new->type==CB_VAL) {
- lwt *= wt;
- TESTBG1(aacol, lwt);
- }
- else {
- p4 = p * new->type;
- aacol[1] = wtcol[1]*lwt;
- aacol[2] = wtcol[2]*lwt;
- aacol[3] = wtcol[3]*lwt;
- lwt *= wt;
- TESTBG4(aacol, lwt);
- }
- }
- }
- }
- }
-
- }
- #undef TESTBG4
- #undef TESTBG1
-
- }
- else {
- // sampled, simple rejection sampling here, good enough
- unsigned int maxsam, s, ui = BLI_rand()*BLI_rand();
- float wcor, cpr = BLI_frand(), lwt;
- if (no_zbuf)
- maxsam = nqd->samples; // no zbuffer input, use sample value directly
- else {
- // depth adaptive sampling hack, the more out of focus, the more samples taken, 16 minimum.
- maxsam = (int)(0.5f + nqd->samples*(1.f-(float)exp(-fabs(zbuf->rect[cp] - cam_fdist))));
- if (maxsam < 16) maxsam = 16;
- }
- wcor = 1.f/(float)maxsam;
- for (s=0; s<maxsam; ++s) {
- u = ct_crad*(2.f*RI_vdC(s, ui) - 1.f);
- v = ct_crad*(2.f*(s + cpr)/(float)maxsam - 1.f);
- sx = (int)(x + u + 0.5f), sy = (int)(y + v + 0.5f);
- if ((sx<0) || (sx >= new->x) || (sy<0) || (sy >= new->y)) continue;
- p = sx + sy*new->x;
- p4 = p * new->type;
- if (nqd->bktype==0) // Disk
- lwt = ((u*u + v*v)<=cR2) ? wcor : 0.f;
- else /* AA not needed here */
- lwt = wcor * getWeight(BKH, len_bkh, u, v, ct_crad, inradsq);
- // prevent background bleeding onto in-focus pixels, user-option
- if (ct_crad > nqd->bthresh) { // if center blur > threshold
- if (crad->rect[p] > nqd->bthresh) { // if overlap pixel in focus, do nothing, else add color/weigbt
- new->rect[p4] += ctcol[0] * lwt;
- if (new->type != CB_VAL) {
- new->rect[p4+1] += ctcol[1] * lwt;
- new->rect[p4+2] += ctcol[2] * lwt;
- new->rect[p4+3] += ctcol[3] * lwt;
- }
- wts->rect[p] += lwt;
- }
- }
- else {
- new->rect[p4] += ctcol[0] * lwt;
- if (new->type != CB_VAL) {
- new->rect[p4+1] += ctcol[1] * lwt;
- new->rect[p4+2] += ctcol[2] * lwt;
- new->rect[p4+3] += ctcol[3] * lwt;
- }
- wts->rect[p] += lwt;
- }
- }
- }
-
- }
- }
-
- // finally, normalize
- for (y=0; y<new->y; y++) {
- unsigned int p = y * new->x;
- unsigned int p4 = p * new->type;
- int x;
-
- for (x=0; x<new->x; x++) {
- float dv = (wts->rect[p]==0.f) ? 1.f : (1.f/wts->rect[p]);
- new->rect[p4] *= dv;
- if (new->type!=CB_VAL) {
- new->rect[p4+1] *= dv;
- new->rect[p4+2] *= dv;
- new->rect[p4+3] *= dv;
- }
- p++;
- p4 += new->type;
- }
- }
-
- free_compbuf(crad);
- free_compbuf(wts);
-
- printf("Done\n");
-}
-
-
-static void node_composit_exec_defocus(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- CompBuf *new, *old, *zbuf_use = NULL, *img = in[0]->data, *zbuf = in[1]->data;
- NodeDefocus *nqd = node->storage;
- int no_zbuf = nqd->no_zbuf;
-
- if ((img==NULL) || (out[0]->hasoutput==0)) return;
-
- // if image not valid type or fstop==infinite (128), nothing to do, pass in to out
- if (((img->type!=CB_RGBA) && (img->type!=CB_VAL)) || ((no_zbuf==0) && (nqd->fstop==128.f))) {
- out[0]->data = pass_on_compbuf(img);
- return;
- }
-
- if (zbuf!=NULL) {
- // Zbuf input, check to make sure, single channel, same size
- // doesn't have to be actual zbuffer, but must be value type
- if ((zbuf->x != img->x) || (zbuf->y != img->y)) {
- // could do a scale here instead...
- printf("Z input must be same size as image !\n");
- return;
- }
- zbuf_use = typecheck_compbuf(zbuf, CB_VAL);
- }
- else no_zbuf = 1; // no zbuffer input
-
- // ok, process
- old = img;
- if (nqd->gamco) {
- // gamma correct, blender func is simplified, fixed value & RGBA only,
- // should make user param. also depremul and premul afterwards, gamma
- // correction can't work with premul alpha
- old = dupalloc_compbuf(img);
- premul_compbuf(old, 1);
- gamma_correct_compbuf(old, 0);
- premul_compbuf(old, 0);
- }
-
- new = alloc_compbuf(old->x, old->y, old->type, 1);
- defocus_blur(node, new, old, zbuf_use, in[1]->vec[0]*nqd->scale, no_zbuf);
-
- if (nqd->gamco) {
- premul_compbuf(new, 1);
- gamma_correct_compbuf(new, 1);
- premul_compbuf(new, 0);
- free_compbuf(old);
- }
- if (node->exec & NODE_BREAK) {
- free_compbuf(new);
- new= NULL;
- }
- out[0]->data = new;
- if (zbuf_use && (zbuf_use != zbuf)) free_compbuf(zbuf_use);
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_defocus(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_defocus(bNodeTree *UNUSED(ntree), bNode *node)
{
/* qdn: defocus node */
NodeDefocus *nbd = MEM_callocN(sizeof(NodeDefocus), "node defocus data");
@@ -885,18 +61,14 @@ static void node_composit_init_defocus(bNodeTree *UNUSED(ntree), bNode *node, bN
node->storage = nbd;
}
-void register_node_type_cmp_defocus(bNodeTreeType *ttype)
+void register_node_type_cmp_defocus(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_DEFOCUS, "Defocus", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_DEFOCUS, "Defocus", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_defocus_in, cmp_node_defocus_out);
- node_type_size(&ntype, 150, 120, 200);
node_type_init(&ntype, node_composit_init_defocus);
node_type_storage(&ntype, "NodeDefocus", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_defocus);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_despeckle.c b/source/blender/nodes/composite/nodes/node_composite_despeckle.c
index 9d47e4bc276..486c69caba0 100644
--- a/source/blender/nodes/composite/nodes/node_composite_despeckle.c
+++ b/source/blender/nodes/composite/nodes/node_composite_despeckle.c
@@ -42,32 +42,19 @@ static bNodeSocketTemplate cmp_node_despeckle_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void node_composit_exec_despeckle(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **UNUSED(in), bNodeStack **UNUSED(out))
-{
- /* pass */
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_despeckle(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_despeckle(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom3 = 0.5f;
node->custom4 = 0.5f;
}
-void register_node_type_cmp_despeckle(bNodeTreeType *ttype)
+void register_node_type_cmp_despeckle(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_DESPECKLE, "Despeckle", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_DESPECKLE, "Despeckle", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_despeckle_in, cmp_node_despeckle_out);
- node_type_size(&ntype, 80, 40, 120);
node_type_init(&ntype, node_composit_init_despeckle);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_despeckle);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_diffMatte.c b/source/blender/nodes/composite/nodes/node_composite_diffMatte.c
index 014b72d3c60..99170c294de 100644
--- a/source/blender/nodes/composite/nodes/node_composite_diffMatte.c
+++ b/source/blender/nodes/composite/nodes/node_composite_diffMatte.c
@@ -45,92 +45,7 @@ static bNodeSocketTemplate cmp_node_diff_matte_out[] = {
{-1, 0, ""}
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_diff_matte(bNode *node, float *outColor, float *inColor1, float *inColor2)
-{
- NodeChroma *c= (NodeChroma *)node->storage;
- float tolerance=c->t1;
- float fper=c->t2;
- /* get falloff amount over tolerance size */
- float falloff=(1.0f-fper) * tolerance;
- float difference;
- float alpha;
- float maxInputAlpha;
-
- /* average together the distances */
- difference= fabs(inColor2[0]-inColor1[0]) +
- fabs(inColor2[1]-inColor1[1]) +
- fabs(inColor2[2]-inColor1[2]);
- difference=difference/3.0f;
-
- copy_v3_v3(outColor, inColor1);
-
- if (difference <= tolerance) {
- if (difference <= falloff) {
- alpha = 0.0f;
- }
- else {
- /* alpha as percent (distance / tolerance), each modified by falloff amount (in pixels)*/
- alpha=(difference-falloff)/(tolerance-falloff);
- }
-
- /*only change if more transparent than either image */
- maxInputAlpha=max_ff(inColor1[3], inColor2[3]);
- if (alpha < maxInputAlpha) {
- /*clamp*/
- if (alpha < 0.0f) alpha = 0.0f;
- if (alpha > 1.0f) alpha = 1.0f;
- outColor[3] = alpha;
- }
- else { /* leave as before */
- outColor[3]=maxInputAlpha;
- }
- }
-}
-
-static void node_composit_exec_diff_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
-{
- CompBuf *outbuf= NULL;
- CompBuf *imbuf1= NULL;
- CompBuf *imbuf2= NULL;
- /* NodeChroma *c; */ /* UNUSED */
-
- /*is anything connected?*/
- if (out[0]->hasoutput==0 && out[1]->hasoutput==0) return;
-
- /*must have an image imput*/
- if (in[0]->data==NULL) return;
-
-
- imbuf1=typecheck_compbuf(in[0]->data, CB_RGBA);
-
- /* if there's an image, use that, if not use the color */
- if (in[1]->data) {
- imbuf2=typecheck_compbuf(in[1]->data, CB_RGBA);
- }
-
- /* c=node->storage; */ /* UNUSED */
- outbuf=dupalloc_compbuf(imbuf1);
-
- /* note, processor gets a keyvals array passed on as buffer constant */
- composit2_pixel_processor(node, outbuf, imbuf1, in[0]->vec, imbuf2, in[1]->vec, do_diff_matte, CB_RGBA, CB_RGBA);
-
- out[0]->data=outbuf;
- if (out[1]->hasoutput)
- out[1]->data=valbuf_from_rgbabuf(outbuf, CHAN_A);
- generate_preview(data, node, outbuf);
-
- if (imbuf1!=in[0]->data)
- free_compbuf(imbuf1);
-
- if (imbuf2!=in[1]->data)
- free_compbuf(imbuf2);
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_diff_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_diff_matte(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
node->storage= c;
@@ -138,18 +53,14 @@ static void node_composit_init_diff_matte(bNodeTree *UNUSED(ntree), bNode *node,
c->t2= 0.1f;
}
-void register_node_type_cmp_diff_matte(bNodeTreeType *ttype)
+void register_node_type_cmp_diff_matte(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_DIFF_MATTE, "Difference Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_DIFF_MATTE, "Difference Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_diff_matte_in, cmp_node_diff_matte_out);
- node_type_size(&ntype, 200, 80, 250);
node_type_init(&ntype, node_composit_init_diff_matte);
node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_diff_matte);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_dilate.c b/source/blender/nodes/composite/nodes/node_composite_dilate.c
index 9787c9f7145..d9caff0d495 100644
--- a/source/blender/nodes/composite/nodes/node_composite_dilate.c
+++ b/source/blender/nodes/composite/nodes/node_composite_dilate.c
@@ -44,132 +44,21 @@ static bNodeSocketTemplate cmp_node_dilateerode_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void morpho_dilate(CompBuf *cbuf)
-{
- int x, y;
- float *p, *rectf = cbuf->rect;
-
- for (y = 0; y < cbuf->y; y++) {
- for (x = 0; x < cbuf->x - 1; x++) {
- p = rectf + cbuf->x * y + x;
- *p = max_ff(*p, *(p + 1));
- }
- }
-
- for (y = 0; y < cbuf->y; y++) {
- for (x = cbuf->x - 1; x >= 1; x--) {
- p = rectf + cbuf->x * y + x;
- *p = max_ff(*p, *(p - 1));
- }
- }
-
- for (x = 0; x < cbuf->x; x++) {
- for (y = 0; y < cbuf->y - 1; y++) {
- p = rectf + cbuf->x * y + x;
- *p = max_ff(*p, *(p + cbuf->x));
- }
- }
-
- for (x = 0; x < cbuf->x; x++) {
- for (y = cbuf->y - 1; y >= 1; y--) {
- p = rectf + cbuf->x * y + x;
- *p = max_ff(*p, *(p - cbuf->x));
- }
- }
-}
-
-static void morpho_erode(CompBuf *cbuf)
-{
- int x, y;
- float *p, *rectf = cbuf->rect;
-
- for (y = 0; y < cbuf->y; y++) {
- for (x = 0; x < cbuf->x - 1; x++) {
- p = rectf + cbuf->x * y + x;
- *p = min_ff(*p, *(p + 1));
- }
- }
-
- for (y = 0; y < cbuf->y; y++) {
- for (x = cbuf->x - 1; x >= 1; x--) {
- p = rectf + cbuf->x * y + x;
- *p = min_ff(*p, *(p - 1));
- }
- }
-
- for (x = 0; x < cbuf->x; x++) {
- for (y = 0; y < cbuf->y - 1; y++) {
- p = rectf + cbuf->x * y + x;
- *p = min_ff(*p, *(p + cbuf->x));
- }
- }
-
- for (x = 0; x < cbuf->x; x++) {
- for (y = cbuf->y - 1; y >= 1; y--) {
- p = rectf + cbuf->x * y + x;
- *p = min_ff(*p, *(p - cbuf->x));
- }
- }
-
-}
-
-static void node_composit_exec_dilateerode(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order in: mask */
- /* stack order out: mask */
- if (out[0]->hasoutput == 0)
- return;
-
- /* input no image? then only color operation */
- if (in[0]->data == NULL) {
- zero_v4(out[0]->vec);
- }
- else {
- /* make output size of input image */
- CompBuf *cbuf = typecheck_compbuf(in[0]->data, CB_VAL);
- CompBuf *stackbuf = dupalloc_compbuf(cbuf);
- short i;
-
- if (node->custom2 > 0) { // positive, dilate
- for (i = 0; i < node->custom2; i++)
- morpho_dilate(stackbuf);
- }
- else if (node->custom2 < 0) { // negative, erode
- for (i = 0; i > node->custom2; i--)
- morpho_erode(stackbuf);
- }
-
- if (cbuf != in[0]->data)
- free_compbuf(cbuf);
-
- out[0]->data = stackbuf;
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_dilateerode(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_dilateerode(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeDilateErode *data = MEM_callocN(sizeof(NodeDilateErode), "NodeDilateErode");
data->falloff = PROP_SMOOTH;
node->storage = data;
}
-void register_node_type_cmp_dilateerode(bNodeTreeType *ttype)
+void register_node_type_cmp_dilateerode(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_DILATEERODE, "Dilate/Erode", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_DILATEERODE, "Dilate/Erode", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_dilateerode_in, cmp_node_dilateerode_out);
- node_type_size(&ntype, 130, 100, 320);
node_type_init(&ntype, node_composit_init_dilateerode);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_dilateerode);
-#endif
-
node_type_storage(&ntype, "NodeDilateErode", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_directionalblur.c b/source/blender/nodes/composite/nodes/node_composite_directionalblur.c
index a343315264d..7edef3bf319 100644
--- a/source/blender/nodes/composite/nodes/node_composite_directionalblur.c
+++ b/source/blender/nodes/composite/nodes/node_composite_directionalblur.c
@@ -42,91 +42,7 @@ static bNodeSocketTemplate cmp_node_dblur_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static CompBuf *dblur(bNode *node, CompBuf *img, int iterations, int wrap,
- float center_x, float center_y, float dist, float angle, float spin, float zoom)
-{
- if ((dist != 0.f) || (spin != 0.f) || (zoom != 0.f)) {
- void (*getpix)(CompBuf *, float, float, float *) = wrap ? qd_getPixelLerpWrap : qd_getPixelLerp;
- const float a = angle;
- const float itsc = 1.f / powf(2.f, (float)iterations);
- float D;
- float center_x_pix, center_y_pix;
- float tx, ty;
- float sc, rot;
- CompBuf *tmp;
- int i, j;
-
- tmp = dupalloc_compbuf(img);
-
- D = dist * sqrtf(img->x * img->x + img->y * img->y);
- center_x_pix = center_x * img->x;
- center_y_pix = center_y * img->y;
-
- tx = itsc * D * cosf(a);
- ty = -itsc * D * sinf(a);
- sc = itsc * zoom;
- rot = itsc * spin;
-
- /* blur the image */
- for (i = 0; i < iterations; ++i) {
- const float cs = cosf(rot), ss = sinf(rot);
- const float isc = 1.f / (1.f + sc);
- unsigned int x, y;
- float col[4] = {0, 0, 0, 0};
-
- for (y = 0; y < img->y; ++y) {
- const float v = isc * (y - center_y_pix) + ty;
-
- for (x = 0; x < img->x; ++x) {
- const float u = isc * (x - center_x_pix) + tx;
- unsigned int p = (x + y * img->x) * img->type;
-
- getpix(tmp, cs * u + ss * v + center_x_pix, cs * v - ss * u + center_y_pix, col);
-
- /* mix img and transformed tmp */
- for (j = 0; j < 4; ++j) {
- img->rect[p + j] = 0.5f * (img->rect[p + j] + col[j]);
- }
- }
- }
-
- /* copy img to tmp */
- if (i != (iterations - 1))
- memcpy(tmp->rect, img->rect, sizeof(float) * img->x * img->y * img->type);
-
- /* double transformations */
- tx *= 2.f, ty *= 2.f;
- sc *= 2.f, rot *= 2.f;
-
- if (node->exec & NODE_BREAK) break;
- }
-
- free_compbuf(tmp);
- }
-
- return img;
-}
-
-static void node_composit_exec_dblur(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- NodeDBlurData *ndbd = node->storage;
- CompBuf *new, *img = in[0]->data;
-
- if ((img == NULL) || (out[0]->hasoutput == 0)) return;
-
- if (img->type != CB_RGBA)
- new = typecheck_compbuf(img, CB_RGBA);
- else
- new = dupalloc_compbuf(img);
-
- out[0]->data = dblur(node, new, ndbd->iter, ndbd->wrap, ndbd->center_x, ndbd->center_y, ndbd->distance, ndbd->angle, ndbd->spin, ndbd->zoom);
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_dblur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_dblur(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeDBlurData *ndbd = MEM_callocN(sizeof(NodeDBlurData), "node dblur data");
node->storage = ndbd;
@@ -134,18 +50,14 @@ static void node_composit_init_dblur(bNodeTree *UNUSED(ntree), bNode *node, bNod
ndbd->center_y = 0.5;
}
-void register_node_type_cmp_dblur(bNodeTreeType *ttype)
+void register_node_type_cmp_dblur(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_DBLUR, "Directional Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_DBLUR, "Directional Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_dblur_in, cmp_node_dblur_out);
- node_type_size(&ntype, 150, 120, 200);
node_type_init(&ntype, node_composit_init_dblur);
node_type_storage(&ntype, "NodeDBlurData", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_dblur);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_displace.c b/source/blender/nodes/composite/nodes/node_composite_displace.c
index c07ad0a0c97..33f82355629 100644
--- a/source/blender/nodes/composite/nodes/node_composite_displace.c
+++ b/source/blender/nodes/composite/nodes/node_composite_displace.c
@@ -47,155 +47,12 @@ static bNodeSocketTemplate cmp_node_displace_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-/* minimum distance (in pixels) a pixel has to be displaced
- * in order to take effect */
-#define DISPLACE_EPSILON 0.01f
-
-static void do_displace(bNode *node, CompBuf *stackbuf, CompBuf *cbuf, CompBuf *vecbuf, float *UNUSED(veccol), CompBuf *xbuf, CompBuf *ybuf, float *xscale, float *yscale)
-{
- ImBuf *ibuf;
- int x, y;
- float p_dx, p_dy; /* main displacement in pixel space */
- float d_dx, d_dy;
- float dxt, dyt;
- float u, v;
- float xs, ys;
- float vec[3], vecdx[3], vecdy[3];
- float col[3];
-
- ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0);
- ibuf->rect_float= cbuf->rect;
-
- for (y=0; y < stackbuf->y; y++) {
- for (x=0; x < stackbuf->x; x++) {
- /* calc pixel coordinates */
- qd_getPixel(vecbuf, x-vecbuf->xof, y-vecbuf->yof, vec);
-
- if (xbuf)
- qd_getPixel(xbuf, x-xbuf->xof, y-xbuf->yof, &xs);
- else
- xs = xscale[0];
-
- if (ybuf)
- qd_getPixel(ybuf, x-ybuf->xof, y-ybuf->yof, &ys);
- else
- ys = yscale[0];
-
- /* clamp x and y displacement to triple image resolution -
- * to prevent hangs from huge values mistakenly plugged in eg. z buffers */
- CLAMP(xs, -stackbuf->x*4, stackbuf->x*4);
- CLAMP(ys, -stackbuf->y*4, stackbuf->y*4);
-
- p_dx = vec[0] * xs;
- p_dy = vec[1] * ys;
-
- /* if no displacement, then just copy this pixel */
- if (fabsf(p_dx) < DISPLACE_EPSILON && fabsf(p_dy) < DISPLACE_EPSILON) {
- qd_getPixel(cbuf, x-cbuf->xof, y-cbuf->yof, col);
- qd_setPixel(stackbuf, x, y, col);
- continue;
- }
-
- /* displaced pixel in uv coords, for image sampling */
- u = (x - cbuf->xof - p_dx + 0.5f) / (float)stackbuf->x;
- v = (y - cbuf->yof - p_dy + 0.5f) / (float)stackbuf->y;
-
-
- /* calc derivatives */
- qd_getPixel(vecbuf, x-vecbuf->xof+1, y-vecbuf->yof, vecdx);
- qd_getPixel(vecbuf, x-vecbuf->xof, y-vecbuf->yof+1, vecdy);
- d_dx = vecdx[0] * xs;
- d_dy = vecdy[1] * ys;
-
- /* clamp derivatives to minimum displacement distance in UV space */
- dxt = p_dx - d_dx;
- dyt = p_dy - d_dy;
-
- dxt = signf(dxt)*max_ff(fabsf(dxt), DISPLACE_EPSILON)/(float)stackbuf->x;
- dyt = signf(dyt)*max_ff(fabsf(dyt), DISPLACE_EPSILON)/(float)stackbuf->y;
-
- ibuf_sample(ibuf, u, v, dxt, dyt, col);
- qd_setPixel(stackbuf, x, y, col);
-
- if (node->exec & NODE_BREAK) break;
- }
-
- if (node->exec & NODE_BREAK) break;
- }
- IMB_freeImBuf(ibuf);
-
-
-/* simple method for reference, linear interpolation */
-#if 0
- int x, y;
- float dx, dy;
- float u, v;
- float vec[3];
- float col[3];
-
- for (y=0; y < stackbuf->y; y++) {
- for (x=0; x < stackbuf->x; x++) {
- qd_getPixel(vecbuf, x, y, vec);
-
- dx = vec[0] * (xscale[0]);
- dy = vec[1] * (yscale[0]);
-
- u = (x - dx + 0.5f) / (float)stackbuf->x;
- v = (y - dy + 0.5f) / (float)stackbuf->y;
-
- qd_getPixelLerp(cbuf, u*cbuf->x - 0.5f, v*cbuf->y - 0.5f, col);
- qd_setPixel(stackbuf, x, y, col);
- }
- }
-#endif
-}
-
-
-static void node_composit_exec_displace(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- if (out[0]->hasoutput==0)
- return;
-
- if (in[0]->data && in[1]->data) {
- CompBuf *cbuf= in[0]->data;
- CompBuf *vecbuf= in[1]->data;
- CompBuf *xbuf= in[2]->data;
- CompBuf *ybuf= in[3]->data;
- CompBuf *stackbuf;
-
- cbuf= typecheck_compbuf(cbuf, CB_RGBA);
- vecbuf= typecheck_compbuf(vecbuf, CB_VEC3);
- xbuf= typecheck_compbuf(xbuf, CB_VAL);
- ybuf= typecheck_compbuf(ybuf, CB_VAL);
-
- stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
-
- do_displace(node, stackbuf, cbuf, vecbuf, in[1]->vec, xbuf, ybuf, in[2]->vec, in[3]->vec);
-
- out[0]->data= stackbuf;
-
-
- if (cbuf!=in[0]->data)
- free_compbuf(cbuf);
- if (vecbuf!=in[1]->data)
- free_compbuf(vecbuf);
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_displace(bNodeTreeType *ttype)
+void register_node_type_cmp_displace(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_DISPLACE, "Displace", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_DISPLACE, "Displace", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_displace_in, cmp_node_displace_out);
- node_type_size(&ntype, 140, 100, 320);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_displace);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c b/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c
index 7e605865cd2..b75301676e6 100644
--- a/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c
+++ b/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c
@@ -45,148 +45,7 @@ static bNodeSocketTemplate cmp_node_distance_matte_out[] = {
{-1, 0, ""}
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-/* note, keyvals is passed on from caller as stack array */
-/* might have been nicer as temp struct though... */
-static void do_distance_matte(bNode *node, float *out, float *in)
-{
- NodeChroma *c= (NodeChroma *)node->storage;
- float tolerance=c->t1;
- float fper=c->t2;
- /* get falloff amount over tolerance size */
- float falloff=(1.0f-fper) * tolerance;
- float distance;
- float alpha;
-
- distance=sqrt((c->key[0]-in[0])*(c->key[0]-in[0]) +
- (c->key[1]-in[1])*(c->key[1]-in[1]) +
- (c->key[2]-in[2])*(c->key[2]-in[2]));
-
- copy_v3_v3(out, in);
-
- if (distance <= tolerance) {
- if (distance <= falloff) {
- alpha = 0.0f;
- }
- else {
- /* alpha as percent (distance / tolerance), each modified by falloff amount (in pixels)*/
- alpha=(distance-falloff)/(tolerance-falloff);
- }
-
- /*only change if more transparent than before */
- if (alpha < in[3]) {
- /*clamp*/
- if (alpha < 0.0f) alpha = 0.0f;
- if (alpha > 1.0f) alpha = 1.0f;
- out[3]=alpha;
- }
- else { /* leave as before */
- out[3]=in[3];
- }
- }
-}
-
-static void do_chroma_distance_matte(bNode *node, float *out, float *in)
-{
- NodeChroma *c= (NodeChroma *)node->storage;
- float tolerance=c->t1;
- float fper=c->t2;
- /* get falloff amount over tolerance size */
- float falloff=(1.0f-fper) * tolerance;
- float y_key, cb_key, cr_key;
- float y_pix, cb_pix, cr_pix;
- float distance;
- float alpha;
-
- /*convert key to chroma colorspace */
- rgb_to_ycc(c->key[0], c->key[1], c->key[2], &y_key, &cb_key, &cr_key, BLI_YCC_JFIF_0_255);
- /* normalize the values */
- cb_key=cb_key/255.0f;
- cr_key=cr_key/255.0f;
-
- /*convert pixel to chroma colorspace */
- rgb_to_ycc(in[0], in[1], in[2], &y_pix, &cb_pix, &cr_pix, BLI_YCC_JFIF_0_255);
- /*normalize the values */
- cb_pix=cb_pix/255.0f;
- cr_pix=cr_pix/255.0f;
-
- distance=sqrt((cb_key-cb_pix)*(cb_key-cb_pix) +
- (cr_key-cr_pix)*(cr_key-cr_pix));
-
- copy_v3_v3(out, in);
-
- if (distance <= tolerance) {
- if (distance <= falloff) {
- alpha = 0.0f;
- }
- else {
- /* alpha as percent (distance / tolerance), each modified by falloff amount (in pixels)*/
- alpha=(distance-falloff)/(tolerance-falloff);
- }
-
- /*only change if more transparent than before */
- if (alpha < in[3]) {
- /*clamp*/
- if (alpha < 0.0f) alpha = 0.0f;
- if (alpha > 1.0f) alpha = 1.0f;
- out[3]=alpha;
- }
- else { /* leave as before */
- out[3]=in[3];
- }
- }
-}
-
-static void node_composit_exec_distance_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /*
- * Loosely based on the Sequencer chroma key plug-in, but enhanced to work in other color spaces and
- * uses a different difference function (suggested in forums of vfxtalk.com).
- */
- CompBuf *workbuf;
- CompBuf *inbuf;
- NodeChroma *c;
-
- /*is anything connected?*/
- if (out[0]->hasoutput==0 && out[1]->hasoutput==0) return;
- /*must have an image imput*/
- if (in[0]->data==NULL) return;
-
- inbuf=typecheck_compbuf(in[0]->data, CB_RGBA);
-
- c=node->storage;
- workbuf=dupalloc_compbuf(inbuf);
-
- /*use the input color*/
- c->key[0] = in[1]->vec[0];
- c->key[1] = in[1]->vec[1];
- c->key[2] = in[1]->vec[2];
-
- /* work in RGB color space */
- if (c->channel == 1) {
- /* note, processor gets a keyvals array passed on as buffer constant */
- composit1_pixel_processor(node, workbuf, workbuf, in[0]->vec, do_distance_matte, CB_RGBA);
- }
- /* work in YCbCr color space */
- else {
- composit1_pixel_processor(node, workbuf, workbuf, in[0]->vec, do_chroma_distance_matte, CB_RGBA);
- }
-
-
-
- out[0]->data=workbuf;
- if (out[1]->hasoutput)
- out[1]->data=valbuf_from_rgbabuf(workbuf, CHAN_A);
- generate_preview(data, node, workbuf);
-
- if (inbuf!=in[0]->data)
- free_compbuf(inbuf);
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_distance_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_distance_matte(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
node->storage= c;
@@ -195,18 +54,14 @@ static void node_composit_init_distance_matte(bNodeTree *UNUSED(ntree), bNode *n
c->t2= 0.1f;
}
-void register_node_type_cmp_distance_matte(bNodeTreeType *ttype)
+void register_node_type_cmp_distance_matte(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_DIST_MATTE, "Distance Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_DIST_MATTE, "Distance Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_distance_matte_in, cmp_node_distance_matte_out);
- node_type_size(&ntype, 200, 80, 250);
node_type_init(&ntype, node_composit_init_distance_matte);
node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_distance_matte);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c b/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c
index 3c1e3ee443e..0659a353afb 100644
--- a/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c
+++ b/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c
@@ -42,1249 +42,13 @@ static bNodeSocketTemplate cmp_node_doubleedgemask_out[] = {
{ -1, 0, "" } // output socket array terminator
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_adjacentKeepBorders(unsigned int t, unsigned int rw, unsigned int *limask, unsigned int *lomask, unsigned int *lres, float *res, unsigned int *rsize)
-{
- int x;
- unsigned int isz=0; // inner edge size
- unsigned int osz=0; // outer edge size
- unsigned int gsz=0; // gradient fill area size
- /* Test the four corners */
- /* upper left corner */
- x=t-rw+1;
- // test if inner mask is filled
- if (limask[x]) {
- // test if pixel underneath, or to the right, are empty in the inner mask,
- // but filled in the outer mask
- if ((!limask[x-rw] && lomask[x-rw]) || (!limask[x+1] && lomask[x+1])) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- /* upper right corner */
- x=t;
- // test if inner mask is filled
- if (limask[x]) {
- // test if pixel underneath, or to the left, are empty in the inner mask,
- // but filled in the outer mask
- if ((!limask[x-rw] && lomask[x-rw]) || (!limask[x-1] && lomask[x-1])) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- /* lower left corner */
- x=0;
- // test if inner mask is filled
- if (limask[x]) {
- // test if pixel above, or to the right, are empty in the inner mask,
- // but filled in the outer mask
- if ((!limask[x+rw] && lomask[x+rw]) || (!limask[x+1] && lomask[x+1])) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- /* lower right corner */
- x=rw-1;
- // test if inner mask is filled
- if (limask[x]) {
- // test if pixel above, or to the left, are empty in the inner mask,
- // but filled in the outer mask
- if ((!limask[x+rw] && lomask[x+rw]) || (!limask[x-1] && lomask[x-1])) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
-
- /* Test the TOP row of pixels in buffer, except corners */
- for (x= t-1; x>=(t-rw)+2; x--) {
- // test if inner mask is filled
- if (limask[x]) {
- // test if pixel to the right, or to the left, are empty in the inner mask,
- // but filled in the outer mask
- if ((!limask[x-1] && lomask[x-1]) || (!limask[x+1] && lomask[x+1])) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- }
-
- /* Test the BOTTOM row of pixels in buffer, except corners */
- for (x= rw-2; x; x--) {
- // test if inner mask is filled
- if (limask[x]) {
- // test if pixel to the right, or to the left, are empty in the inner mask,
- // but filled in the outer mask
- if ((!limask[x-1] && lomask[x-1]) || (!limask[x+1] && lomask[x+1])) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- }
- /* Test the LEFT edge of pixels in buffer, except corners */
- for (x= t-(rw<<1)+1; x>=rw; x-=rw) {
- // test if inner mask is filled
- if (limask[x]) {
- // test if pixel underneath, or above, are empty in the inner mask,
- // but filled in the outer mask
- if ((!limask[x-rw] && lomask[x-rw]) || (!limask[x+rw] && lomask[x+rw])) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- }
-
- /* Test the RIGHT edge of pixels in buffer, except corners */
- for (x= t-rw; x>rw; x-=rw) {
- // test if inner mask is filled
- if (limask[x]) {
- // test if pixel underneath, or above, are empty in the inner mask,
- // but filled in the outer mask
- if ((!limask[x-rw] && lomask[x-rw]) || (!limask[x+rw] && lomask[x+rw])) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- }
-
- rsize[0]=isz; // fill in our return sizes for edges + fill
- rsize[1]=osz;
- rsize[2]=gsz;
-}
-
-static void do_adjacentBleedBorders(unsigned int t, unsigned int rw, unsigned int *limask, unsigned int *lomask, unsigned int *lres, float *res, unsigned int *rsize)
-{
- int x;
- unsigned int isz=0; // inner edge size
- unsigned int osz=0; // outer edge size
- unsigned int gsz=0; // gradient fill area size
- /* Test the four corners */
- /* upper left corner */
- x=t-rw+1;
- // test if inner mask is filled
- if (limask[x]) {
- // test if pixel underneath, or to the right, are empty in the inner mask,
- // but filled in the outer mask
- if ((!limask[x-rw] && lomask[x-rw]) || (!limask[x+1] && lomask[x+1])) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- if (!lomask[x-rw] || !lomask[x+1]) { // test if outer mask is empty underneath or to the right
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- else {
- gsz++; // increment the gradient pixel count
- lres[x]=2; // flag pixel as gradient
- }
- }
- /* upper right corner */
- x=t;
- // test if inner mask is filled
- if (limask[x]) {
- // test if pixel underneath, or to the left, are empty in the inner mask,
- // but filled in the outer mask
- if ((!limask[x-rw] && lomask[x-rw]) || (!limask[x-1] && lomask[x-1])) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- if (!lomask[x-rw] || !lomask[x-1]) { // test if outer mask is empty underneath or to the left
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- else {
- gsz++; // increment the gradient pixel count
- lres[x]=2; // flag pixel as gradient
- }
- }
- /* lower left corner */
- x=0;
- // test if inner mask is filled
- if (limask[x]) {
- // test if pixel above, or to the right, are empty in the inner mask,
- // but filled in the outer mask
- if ((!limask[x+rw] && lomask[x+rw]) || (!limask[x+1] && lomask[x+1])) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- if (!lomask[x+rw] || !lomask[x+1]) { // test if outer mask is empty above or to the right
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- else {
- gsz++; // increment the gradient pixel count
- lres[x]=2; // flag pixel as gradient
- }
- }
- /* lower right corner */
- x=rw-1;
- // test if inner mask is filled
- if (limask[x]) {
- // test if pixel above, or to the left, are empty in the inner mask,
- // but filled in the outer mask
- if ((!limask[x+rw] && lomask[x+rw]) || (!limask[x-1] && lomask[x-1])) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- if (!lomask[x+rw] || !lomask[x-1]) { // test if outer mask is empty above or to the left
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- else {
- gsz++; // increment the gradient pixel count
- lres[x]=2; // flag pixel as gradient
- }
- }
- /* Test the TOP row of pixels in buffer, except corners */
- for (x= t-1; x>=(t-rw)+2; x--) {
- // test if inner mask is filled
- if (limask[x]) {
- // test if pixel to the left, or to the right, are empty in the inner mask,
- // but filled in the outer mask
- if ((!limask[x-1] && lomask[x-1]) || (!limask[x+1] && lomask[x+1])) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- if (!lomask[x-1] || !lomask[x+1]) { // test if outer mask is empty to the left or to the right
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- else {
- gsz++; // increment the gradient pixel count
- lres[x]=2; // flag pixel as gradient
- }
- }
- }
-
- /* Test the BOTTOM row of pixels in buffer, except corners */
- for (x= rw-2; x; x--) {
- // test if inner mask is filled
- if (limask[x]) {
- // test if pixel to the left, or to the right, are empty in the inner mask,
- // but filled in the outer mask
- if ((!limask[x-1] && lomask[x-1]) || (!limask[x+1] && lomask[x+1])) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- if (!lomask[x-1] || !lomask[x+1]) { // test if outer mask is empty to the left or to the right
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- else {
- gsz++; // increment the gradient pixel count
- lres[x]=2; // flag pixel as gradient
- }
- }
- }
- /* Test the LEFT edge of pixels in buffer, except corners */
- for (x= t-(rw<<1)+1; x>=rw; x-=rw) {
- // test if inner mask is filled
- if (limask[x]) {
- // test if pixel underneath, or above, are empty in the inner mask,
- // but filled in the outer mask
- if ((!limask[x-rw] && lomask[x-rw]) || (!limask[x+rw] && lomask[x+rw])) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- if (!lomask[x-rw] || !lomask[x+rw]) { // test if outer mask is empty underneath or above
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- else {
- gsz++; // increment the gradient pixel count
- lres[x]=2; // flag pixel as gradient
- }
- }
- }
-
- /* Test the RIGHT edge of pixels in buffer, except corners */
- for (x= t-rw; x>rw; x-=rw) {
- // test if inner mask is filled
- if (limask[x]) {
- // test if pixel underneath, or above, are empty in the inner mask,
- // but filled in the outer mask
- if ((!limask[x-rw] && lomask[x-rw]) || (!limask[x+rw] && lomask[x+rw])) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- if (!lomask[x-rw] || !lomask[x+rw]) { // test if outer mask is empty underneath or above
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- else {
- gsz++; // increment the gradient pixel count
- lres[x]=2; // flag pixel as gradient
- }
- }
- }
-
- rsize[0]=isz; // fill in our return sizes for edges + fill
- rsize[1]=osz;
- rsize[2]=gsz;
-}
-
-static void do_allKeepBorders(unsigned int t, unsigned int rw, unsigned int *limask, unsigned int *lomask, unsigned int *lres, float *res, unsigned int *rsize)
-{
- int x;
- unsigned int isz=0; // inner edge size
- unsigned int osz=0; // outer edge size
- unsigned int gsz=0; // gradient fill area size
- /* Test the four corners */
- /* upper left corner */
- x=t-rw+1;
- // test if inner mask is filled
- if (limask[x]) {
- // test if the inner mask is empty underneath or to the right
- if (!limask[x-rw] || !limask[x+1]) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- /* upper right corner */
- x=t;
- // test if inner mask is filled
- if (limask[x]) {
- // test if the inner mask is empty underneath or to the left
- if (!limask[x-rw] || !limask[x-1]) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- /* lower left corner */
- x=0;
- // test if inner mask is filled
- if (limask[x]) {
- // test if inner mask is empty above or to the right
- if (!limask[x+rw] || !limask[x+1]) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- /* lower right corner */
- x=rw-1;
- // test if inner mask is filled
- if (limask[x]) {
- // test if inner mask is empty above or to the left
- if (!limask[x+rw] || !limask[x-1]) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
-
- /* Test the TOP row of pixels in buffer, except corners */
- for (x= t-1; x>=(t-rw)+2; x--) {
- // test if inner mask is filled
- if (limask[x]) {
- // test if inner mask is empty to the left or to the right
- if (!limask[x-1] || !limask[x+1]) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- }
-
- /* Test the BOTTOM row of pixels in buffer, except corners */
- for (x= rw-2; x; x--) {
- // test if inner mask is filled
- if (limask[x]) {
- // test if inner mask is empty to the left or to the right
- if (!limask[x-1] || !limask[x+1]) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- }
- /* Test the LEFT edge of pixels in buffer, except corners */
- for (x= t-(rw<<1)+1; x>=rw; x-=rw) {
- // test if inner mask is filled
- if (limask[x]) {
- // test if inner mask is empty underneath or above
- if (!limask[x-rw] || !limask[x+rw]) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- }
-
- /* Test the RIGHT edge of pixels in buffer, except corners */
- for (x= t-rw; x>rw; x-=rw) {
- // test if inner mask is filled
- if (limask[x]) {
- // test if inner mask is empty underneath or above
- if (!limask[x-rw] || !limask[x+rw]) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- }
-
- rsize[0]=isz; // fill in our return sizes for edges + fill
- rsize[1]=osz;
- rsize[2]=gsz;
-}
-
-static void do_allBleedBorders(unsigned int t, unsigned int rw, unsigned int *limask, unsigned int *lomask, unsigned int *lres, float *res, unsigned int *rsize)
-{
- int x;
- unsigned int isz=0; // inner edge size
- unsigned int osz=0; // outer edge size
- unsigned int gsz=0; // gradient fill area size
- /* Test the four corners */
- /* upper left corner */
- x=t-rw+1;
- // test if inner mask is filled
- if (limask[x]) {
- // test if the inner mask is empty underneath or to the right
- if (!limask[x-rw] || !limask[x+1]) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- if (!lomask[x-rw] || !lomask[x+1]) { // test if outer mask is empty underneath or to the right
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- else {
- gsz++; // increment the gradient pixel count
- lres[x]=2; // flag pixel as gradient
- }
- }
- /* upper right corner */
- x=t;
- // test if inner mask is filled
- if (limask[x]) {
- // test if the inner mask is empty underneath or to the left
- if (!limask[x-rw] || !limask[x-1]) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- if (!lomask[x-rw] || !lomask[x-1]) { // test if outer mask is empty above or to the left
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- else {
- gsz++; // increment the gradient pixel count
- lres[x]=2; // flag pixel as gradient
- }
- }
- /* lower left corner */
- x=0;
- // test if inner mask is filled
- if (limask[x]) {
- // test if inner mask is empty above or to the right
- if (!limask[x+rw] || !limask[x+1]) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- if (!lomask[x+rw] || !lomask[x+1]) { // test if outer mask is empty underneath or to the right
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- else {
- gsz++; // increment the gradient pixel count
- lres[x]=2; // flag pixel as gradient
- }
- }
- /* lower right corner */
- x=rw-1;
- // test if inner mask is filled
- if (limask[x]) {
- // test if inner mask is empty above or to the left
- if (!limask[x+rw] || !limask[x-1]) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- if (!lomask[x+rw] || !lomask[x-1]) { // test if outer mask is empty underneath or to the left
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- else {
- gsz++; // increment the gradient pixel count
- lres[x]=2; // flag pixel as gradient
- }
- }
- /* Test the TOP row of pixels in buffer, except corners */
- for (x= t-1; x>=(t-rw)+2; x--) {
- // test if inner mask is filled
- if (limask[x]) {
- // test if inner mask is empty to the left or to the right
- if (!limask[x-1] || !limask[x+1]) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- if (!lomask[x-1] || !lomask[x+1]) { // test if outer mask is empty to the left or to the right
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- else {
- gsz++; // increment the gradient pixel count
- lres[x]=2; // flag pixel as gradient
- }
- }
- }
-
- /* Test the BOTTOM row of pixels in buffer, except corners */
- for (x= rw-2; x; x--) {
- // test if inner mask is filled
- if (limask[x]) {
- // test if inner mask is empty to the left or to the right
- if (!limask[x-1] || !limask[x+1]) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- if (!lomask[x-1] || !lomask[x+1]) { // test if outer mask is empty to the left or to the right
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- else {
- gsz++; // increment the gradient pixel count
- lres[x]=2; // flag pixel as gradient
- }
- }
- }
- /* Test the LEFT edge of pixels in buffer, except corners */
- for (x= t-(rw<<1)+1; x>=rw; x-=rw) {
- // test if inner mask is filled
- if (limask[x]) {
- // test if inner mask is empty underneath or above
- if (!limask[x-rw] || !limask[x+rw]) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- if (!lomask[x-rw] || !lomask[x+rw]) { // test if outer mask is empty underneath or above
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- else {
- gsz++; // increment the gradient pixel count
- lres[x]=2; // flag pixel as gradient
- }
- }
- }
-
- /* Test the RIGHT edge of pixels in buffer, except corners */
- for (x= t-rw; x>rw; x-=rw) {
- // test if inner mask is filled
- if (limask[x]) {
- // test if inner mask is empty underneath or above
- if (!limask[x-rw] || !limask[x+rw]) {
- isz++; // increment inner edge size
- lres[x]=4; // flag pixel as inner edge
- }
- else {
- res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge
- }
- }
- else if (lomask[x]) { // inner mask was empty, test if outer mask is filled
- if (!lomask[x-rw] || !lomask[x+rw]) { // test if outer mask is empty underneath or above
- osz++; // increment outer edge size
- lres[x]=3; // flag pixel as outer edge
- }
- else {
- gsz++; // increment the gradient pixel count
- lres[x]=2; // flag pixel as gradient
- }
- }
- }
-
- rsize[0]=isz; // fill in our return sizes for edges + fill
- rsize[1]=osz;
- rsize[2]=gsz;
-}
-
-static void do_allEdgeDetection(unsigned int t, unsigned int rw, unsigned int *limask, unsigned int *lomask, unsigned int *lres, float *res, unsigned int *rsize, unsigned int in_isz, unsigned int in_osz, unsigned int in_gsz)
-{
- int x; // x = pixel loop counter
- int a; // a = pixel loop counter
- int dx; // dx = delta x
- int pix_prevRow; // pix_prevRow = pixel one row behind the one we are testing in a loop
- int pix_nextRow; // pix_nextRow = pixel one row in front of the one we are testing in a loop
- int pix_prevCol; // pix_prevCol = pixel one column behind the one we are testing in a loop
- int pix_nextCol; // pix_nextCol = pixel one column in front of the one we are testing in a loop
- /* Test all rows between the FIRST and LAST rows, excluding left and right edges */
- for (x= (t-rw)+1, dx=x-(rw-2); dx>rw; x-=rw, dx-=rw) {
- a=x-2;
- pix_prevRow=a+rw;
- pix_nextRow=a-rw;
- pix_prevCol=a+1;
- pix_nextCol=a-1;
- while (a>dx-2) {
- if (!limask[a]) { // if the inner mask is empty
- if (lomask[a]) { // if the outer mask is full
- /*
- * Next we test all 4 directions around the current pixel: next/prev/up/down
- * The test ensures that the outer mask is empty and that the inner mask
- * is also empty. If both conditions are true for any one of the 4 adjacent pixels
- * then the current pixel is counted as being a true outer edge pixel.
- */
- if ((!lomask[pix_nextCol] && !limask[pix_nextCol]) ||
- (!lomask[pix_prevCol] && !limask[pix_prevCol]) ||
- (!lomask[pix_nextRow] && !limask[pix_nextRow]) ||
- (!lomask[pix_prevRow] && !limask[pix_prevRow]))
- {
- in_osz++; // increment the outer boundary pixel count
- lres[a]=3; // flag pixel as part of outer edge
- }
- else { // it's not a boundary pixel, but it is a gradient pixel
- in_gsz++; // increment the gradient pixel count
- lres[a]=2; // flag pixel as gradient
- }
- }
-
- }
- else {
- if (!limask[pix_nextCol] || !limask[pix_prevCol] || !limask[pix_nextRow] || !limask[pix_prevRow]) {
- in_isz++; // increment the inner boundary pixel count
- lres[a]=4; // flag pixel as part of inner edge
- }
- else {
- res[a]=1.0f; // pixel is part of inner mask, but not at an edge
- }
- }
- a--;
- pix_prevRow--;
- pix_nextRow--;
- pix_prevCol--;
- pix_nextCol--;
- }
- }
-
- rsize[0]=in_isz; // fill in our return sizes for edges + fill
- rsize[1]=in_osz;
- rsize[2]=in_gsz;
-}
-
-static void do_adjacentEdgeDetection(unsigned int t, unsigned int rw, unsigned int *limask, unsigned int *lomask, unsigned int *lres, float *res, unsigned int *rsize, unsigned int in_isz, unsigned int in_osz, unsigned int in_gsz)
-{
- int x; // x = pixel loop counter
- int a; // a = pixel loop counter
- int dx; // dx = delta x
- int pix_prevRow; // pix_prevRow = pixel one row behind the one we are testing in a loop
- int pix_nextRow; // pix_nextRow = pixel one row in front of the one we are testing in a loop
- int pix_prevCol; // pix_prevCol = pixel one column behind the one we are testing in a loop
- int pix_nextCol; // pix_nextCol = pixel one column in front of the one we are testing in a loop
- /* Test all rows between the FIRST and LAST rows, excluding left and right edges */
- for (x= (t-rw)+1, dx=x-(rw-2); dx>rw; x-=rw, dx-=rw) {
- a=x-2;
- pix_prevRow=a+rw;
- pix_nextRow=a-rw;
- pix_prevCol=a+1;
- pix_nextCol=a-1;
- while (a>dx-2) {
- if (!limask[a]) { // if the inner mask is empty
- if (lomask[a]) { // if the outer mask is full
- /*
- * Next we test all 4 directions around the current pixel: next/prev/up/down
- * The test ensures that the outer mask is empty and that the inner mask
- * is also empty. If both conditions are true for any one of the 4 adjacent pixels
- * then the current pixel is counted as being a true outer edge pixel.
- */
- if ((!lomask[pix_nextCol] && !limask[pix_nextCol]) ||
- (!lomask[pix_prevCol] && !limask[pix_prevCol]) ||
- (!lomask[pix_nextRow] && !limask[pix_nextRow]) ||
- (!lomask[pix_prevRow] && !limask[pix_prevRow]))
- {
- in_osz++; // increment the outer boundary pixel count
- lres[a]=3; // flag pixel as part of outer edge
- }
- else { // it's not a boundary pixel, but it is a gradient pixel
- in_gsz++; // increment the gradient pixel count
- lres[a]=2; // flag pixel as gradient
- }
- }
-
- }
- else {
- if ((!limask[pix_nextCol] && lomask[pix_nextCol]) ||
- (!limask[pix_prevCol] && lomask[pix_prevCol]) ||
- (!limask[pix_nextRow] && lomask[pix_nextRow]) ||
- (!limask[pix_prevRow] && lomask[pix_prevRow]))
- {
- in_isz++; // increment the inner boundary pixel count
- lres[a]=4; // flag pixel as part of inner edge
- }
- else {
- res[a]=1.0f; // pixel is part of inner mask, but not at an edge
- }
- }
- a--;
- pix_prevRow--; // advance all four "surrounding" pixel pointers
- pix_nextRow--;
- pix_prevCol--;
- pix_nextCol--;
- }
- }
-
- rsize[0]=in_isz; // fill in our return sizes for edges + fill
- rsize[1]=in_osz;
- rsize[2]=in_gsz;
-}
-
-static void do_createEdgeLocationBuffer(unsigned int t, unsigned int rw, unsigned int *lres, float *res, unsigned short *gbuf, unsigned int *innerEdgeOffset, unsigned int *outerEdgeOffset, unsigned int isz, unsigned int gsz)
-{
- int x; // x = pixel loop counter
- int a; // a = temporary pixel index buffer loop counter
- unsigned int ud; // ud = unscaled edge distance
- unsigned int dmin; // dmin = minimum edge distance
-
- unsigned int rsl; // long used for finding fast 1.0/sqrt
- unsigned int gradientFillOffset;
- unsigned int innerAccum=0; // for looping inner edge pixel indexes, represents current position from offset
- unsigned int outerAccum=0; // for looping outer edge pixel indexes, represents current position from offset
- unsigned int gradientAccum=0; // for looping gradient pixel indexes, represents current position from offset
- /*
- * Here we compute the size of buffer needed to hold (row, col) coordinates
- * for each pixel previously determined to be either gradient, inner edge,
- * or outer edge.
- *
- * Allocation is done by requesting 4 bytes "sizeof(int)" per pixel, even
- * though gbuf[] is declared as unsigned short* (2 bytes) because we don't
- * store the pixel indexes, we only store x, y location of pixel in buffer.
- *
- * This does make the assumption that x and y can fit in 16 unsigned bits
- * so if Blender starts doing renders greater than 65536 in either direction
- * this will need to allocate gbuf[] as unsigned int* and allocate 8 bytes
- * per flagged pixel.
- *
- * In general, the buffer on-screen:
- *
- * Example: 9 by 9 pixel block
- *
- * . = pixel non-white in both outer and inner mask
- * o = pixel white in outer, but not inner mask, adjacent to "." pixel
- * g = pixel white in outer, but not inner mask, not adjacent to "." pixel
- * i = pixel white in inner mask, adjacent to "g" or "." pixel
- * F = pixel white in inner mask, only adjacent to other pixels white in the inner mask
- *
- *
- * ......... <----- pixel #80
- * ..oooo...
- * .oggggo..
- * .oggiggo.
- * .ogiFigo.
- * .oggiggo.
- * .oggggo..
- * ..oooo...
- * pixel #00 -----> .........
- *
- * gsz = 18 (18 "g" pixels above)
- * isz = 4 (4 "i" pixels above)
- * osz = 18 (18 "o" pixels above)
- *
- *
- * The memory in gbuf[] after filling will look like this:
- *
- * gradientFillOffset (0 pixels) innerEdgeOffset (18 pixels) outerEdgeOffset (22 pixels)
- * / / /
- * / / /
- * |X Y X Y X Y X Y > <X Y X Y > <X Y X Y X Y > <X Y X Y | <- (x, y)
- * +--------------------------------> <----------------> <------------------------> <----------------+
- * |0 2 4 6 8 10 12 14 > ... <68 70 72 74 > ... <80 82 84 86 88 90 > ... <152 154 156 158 | <- bytes
- * +--------------------------------> <----------------> <------------------------> <----------------+
- * |g0 g0 g1 g1 g2 g2 g3 g3 > <g17 g17 i0 i0 > <i2 i2 i3 i3 o0 o0 > <o16 o16 o17 o17 | <- pixel
- * / / /
- * / / /
- * / / /
- * +---------- gradientAccum (18) ---------+ +--- innerAccum (22) ---+ +--- outerAccum (40) ---+
- *
- *
- * Ultimately we do need the pixel's memory buffer index to set the output
- * pixel color, but it's faster to reconstruct the memory buffer location
- * each iteration of the final gradient calculation than it is to deconstruct
- * a memory location into x, y pairs each round.
- */
-
-
- gradientFillOffset=0; // since there are likely "more" of these, put it first. :)
- *innerEdgeOffset=gradientFillOffset+gsz; // set start of inner edge indexes
- *outerEdgeOffset=(*innerEdgeOffset)+isz; // set start of outer edge indexes
- /* set the accumulators to correct positions */ // set up some accumulator variables for loops
- gradientAccum = gradientFillOffset; // each accumulator variable starts at its respective
- innerAccum = *innerEdgeOffset; // section's offset so when we start filling, each
- outerAccum = *outerEdgeOffset; // section fills up it's allocated space in gbuf
- //uses dmin=row, rsl=col
- for (x=0, dmin=0; x<t; x+=rw, dmin++) {
- for (rsl=0; rsl<rw; rsl++) {
- a=x+rsl;
- if (lres[a]==2) { // it is a gradient pixel flagged by 2
- ud=gradientAccum<<1; // double the index to reach correct unsigned short location
- gbuf[ud]=dmin; // insert pixel's row into gradient pixel location buffer
- gbuf[ud+1]=rsl; // insert pixel's column into gradient pixel location buffer
- gradientAccum++; // increment gradient index buffer pointer
- }
- else if (lres[a]==3) { // it is an outer edge pixel flagged by 3
- ud=outerAccum<<1; // double the index to reach correct unsigned short location
- gbuf[ud]=dmin; // insert pixel's row into outer edge pixel location buffer
- gbuf[ud+1]=rsl; // insert pixel's column into outer edge pixel location buffer
- outerAccum++; // increment outer edge index buffer pointer
- res[a]=0.0f; // set output pixel intensity now since it won't change later
- }
- else if (lres[a]==4) { // it is an inner edge pixel flagged by 4
- ud=innerAccum<<1; // double int index to reach correct unsigned short location
- gbuf[ud]=dmin; // insert pixel's row into inner edge pixel location buffer
- gbuf[ud+1]=rsl; // insert pixel's column into inner edge pixel location buffer
- innerAccum++; // increment inner edge index buffer pointer
- res[a]=1.0f; // set output pixel intensity now since it won't change later
- }
- }
- }
-
-}
-
-static void do_fillGradientBuffer(unsigned int rw, float *res, unsigned short *gbuf, unsigned int isz, unsigned int osz, unsigned int gsz, unsigned int innerEdgeOffset, unsigned int outerEdgeOffset)
-{
- int x; // x = pixel loop counter
- int a; // a = temporary pixel index buffer loop counter
- int fsz; // size of the frame
- unsigned int rsl; // long used for finding fast 1.0/sqrt
- float rsf; // float used for finding fast 1.0/sqrt
- const float rsopf = 1.5f; // constant float used for finding fast 1.0/sqrt
-
- unsigned int gradientFillOffset;
- unsigned int t;
- unsigned int ud; // ud = unscaled edge distance
- unsigned int dmin; // dmin = minimum edge distance
- float odist; // odist = current outer edge distance
- float idist; // idist = current inner edge distance
- int dx; // dx = X-delta (used for distance proportion calculation)
- int dy; // dy = Y-delta (used for distance proportion calculation)
- /*
- * The general algorithm used to color each gradient pixel is:
- *
- * 1.) Loop through all gradient pixels.
- * A.) For each gradient pixel:
- * a.) Loop though all outside edge pixels, looking for closest one
- * to the gradient pixel we are in.
- * b.) Loop through all inside edge pixels, looking for closest one
- * to the gradient pixel we are in.
- * c.) Find proportion of distance from gradient pixel to inside edge
- * pixel compared to sum of distance to inside edge and distance to
- * outside edge.
- *
- * In an image where:
- * . = blank (black) pixels, not covered by inner mask or outer mask
- * + = desired gradient pixels, covered only by outer mask
- * * = white full mask pixels, covered by at least inner mask
- *
- * ...............................
- * ...............+++++++++++.....
- * ...+O++++++..++++++++++++++....
- * ..+++\++++++++++++++++++++.....
- * .+++++G+++++++++*******+++.....
- * .+++++|+++++++*********+++.....
- * .++***I****************+++.....
- * .++*******************+++......
- * .+++*****************+++.......
- * ..+++***************+++........
- * ....+++**********+++...........
- * ......++++++++++++.............
- * ...............................
- *
- * O = outside edge pixel
- * \
- * G = gradient pixel
- * |
- * I = inside edge pixel
- *
- * __
- * *note that IO does not need to be a straight line, in fact
- * many cases can arise where straight lines do not work
- * correctly.
- *
- * __ __ __
- * d.) Pixel color is assigned as |GO| / ( |GI| + |GO| )
- *
- * The implementation does not compute distance, but the reciprocal of the
- * distance. This is done to avoid having to compute a square root, as a
- * reciprocal square root can be computed faster. Therefore, the code computes
- * pixel color as |GI| / (|GI| + |GO|). Since these are reciprocals, GI serves the
- * purpose of GO for the proportion calculation.
- *
- * For the purposes of the minimum distance comparisons, we only check
- * the sums-of-squares against each other, since they are in the same
- * mathematical sort-order as if we did go ahead and take square roots
- *
- * Loop through all gradient pixels.
- */
-
- for (x= gsz-1; x>=0; x--) {
- gradientFillOffset=x<<1;
- t=gbuf[gradientFillOffset]; // calculate column of pixel indexed by gbuf[x]
- fsz=gbuf[gradientFillOffset+1]; // calculate row of pixel indexed by gbuf[x]
- dmin=0xffffffff; // reset min distance to edge pixel
- for (a=outerEdgeOffset+osz-1; a>=outerEdgeOffset; a--) { // loop through all outer edge buffer pixels
- ud=a<<1;
- dy=t-gbuf[ud]; // set dx to gradient pixel column - outer edge pixel row
- dx=fsz-gbuf[ud+1]; // set dy to gradient pixel row - outer edge pixel column
- ud=dx*dx+dy*dy; // compute sum of squares
- if (ud<dmin) { // if our new sum of squares is less than the current minimum
- dmin=ud; // set a new minimum equal to the new lower value
- }
- }
- odist=(float)(dmin); // cast outer min to a float
- rsf=odist*0.5f; //
- rsl=*(unsigned int*)&odist; // use some peculiar properties of the way bits are stored
- rsl=0x5f3759df-(rsl>>1); // in floats vs. unsigned ints to compute an approximate
- odist=*(float*)&rsl; // reciprocal square root
- odist=odist*(rsopf-(rsf*odist*odist)); // -- ** this line can be iterated for more accuracy ** --
- dmin=0xffffffff; // reset min distance to edge pixel
- for (a= innerEdgeOffset+isz-1; a>=innerEdgeOffset; a--) { // loop through all inside edge pixels
- ud=a<<1;
- dy=t-gbuf[ud]; // compute delta in Y from gradient pixel to inside edge pixel
- dx=fsz-gbuf[ud+1]; // compute delta in X from gradient pixel to inside edge pixel
- ud=dx*dx+dy*dy; // compute sum of squares
- if (ud<dmin) { // if our new sum of squares is less than the current minimum we've found
- dmin=ud; // set a new minimum equal to the new lower value
- }
- }
- idist=(float)(dmin); // cast inner min to a float
- rsf=idist*0.5f; //
- rsl=*(unsigned int*)&idist; //
- rsl=0x5f3759df-(rsl>>1); // see notes above
- idist=*(float*)&rsl; //
- idist=idist*(rsopf-(rsf*idist*idist)); //
- /*
- * Note once again that since we are using reciprocals of distance values our
- * proportion is already the correct intensity, and does not need to be
- * subtracted from 1.0 like it would have if we used real distances.
- */
-
- /*
- * Here we reconstruct the pixel's memory location in the CompBuf by
- * Pixel Index = Pixel Column + ( Pixel Row * Row Width )
- */
- res[gbuf[gradientFillOffset+1]+(gbuf[gradientFillOffset]*rw)]=(idist/(idist+odist)); //set intensity
- }
-
-}
-
-
-static void node_composit_exec_doubleedgemask(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
-
- float *imask; // imask = pointer to inner mask pixel buffer
- float *omask; // omask = pointer to outer mask pixel buffer
- float *res; // res = pointer to output mask
-
- unsigned int *lres; // lres = unsigned int pointer to output pixel buffer (for bit operations)
- unsigned int *limask; // limask = unsigned int pointer to inner mask (for bit operations)
- unsigned int *lomask; // lomask = unsigned int pointer to outer mask (for bit operations)
-
- int rw; // rw = pixel row width
- int t; // t = total number of pixels in buffer - 1 (used for loop starts)
- int fsz; // size of the frame
-
- unsigned int isz=0; // size (in pixels) of inside edge pixel index buffer
- unsigned int osz=0; // size (in pixels) of outside edge pixel index buffer
- unsigned int gsz=0; // size (in pixels) of gradient pixel index buffer
- unsigned int rsize[3]; // size storage to pass to helper functions
- unsigned int innerEdgeOffset=0; // offset into final buffer where inner edge pixel indexes start
- unsigned int outerEdgeOffset=0; // offset into final buffer where outer edge pixel indexes start
-
- unsigned short *gbuf; // gradient/inner/outer pixel location index buffer
-
- CompBuf *cbuf; // pointer, will be set to inner mask data
- CompBuf *dbuf; // pointer, will be set to outer mask data
- CompBuf *stackbuf; // pointer, will get allocated as output buffer
-
- if (out[0]->hasoutput==0) { // if the node's output socket is not connected to anything...
- return; // do not execute any further, just exit the node immediately
- }
-
- if (in[0]->data && in[1]->data) { // if both input sockets have some data coming in...
- cbuf= in[0]->data; // get a pointer to the inner mask data
- dbuf= in[1]->data; // get a pointer to the outer mask data
- if (cbuf->type!=CB_VAL || dbuf->type!=CB_VAL) { // if either input socket has an incorrect data type coming in
- return; // exit the node immediately
- }
-
- t=(cbuf->x*cbuf->y)-1; // determine size of the frame
-
- stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); // allocate the output buffer
-
- imask= cbuf->rect; // set the inner mask
- omask= dbuf->rect; // set the outer mask
- res= stackbuf->rect; // set output pointer
- lres= (unsigned int*)res; // unsigned int pointer to output buffer (for bit level ops)
- limask=(unsigned int*)imask; // unsigned int pointer to input mask (for bit level ops)
- lomask=(unsigned int*)omask; // unsigned int pointer to output mask (for bit level ops)
- rw= cbuf->x; // width of a row of pixels
-
-
- /*
- * The whole buffer is broken up into 4 parts. The four CORNERS, the FIRST and LAST rows, the
- * LEFT and RIGHT edges (excluding the corner pixels), and all OTHER rows.
- * This allows for quick computation of outer edge pixels where
- * a screen edge pixel is marked to be gradient.
- *
- * The pixel type (gradient vs inner-edge vs outer-edge) tests change
- * depending on the user selected "Inner Edge Mode" and the user selected
- * "Buffer Edge Mode" on the node's GUI. There are 4 sets of basically the
- * same algorithm:
- *
- * 1.) Inner Edge -> Adjacent Only
- * Buffer Edge -> Keep Inside
- *
- * 2.) Inner Edge -> Adjacent Only
- * Buffer Edge -> Bleed Out
- *
- * 3.) Inner Edge -> All
- * Buffer Edge -> Keep Inside
- *
- * 4.) Inner Edge -> All
- * Buffer Edge -> Bleed Out
- *
- * Each version has slightly different criteria for detecting an edge pixel.
- */
- if (node->custom2) { // if "adjacent only" inner edge mode is turned on
- if (node->custom1) { // if "keep inside" buffer edge mode is turned on
- do_adjacentKeepBorders(t, rw, limask, lomask, lres, res, rsize);
- }
- else { // "bleed out" buffer edge mode is turned on
- do_adjacentBleedBorders(t, rw, limask, lomask, lres, res, rsize);
- }
- isz=rsize[0]; // set up inner edge, outer edge, and gradient buffer sizes after border pass
- osz=rsize[1];
- gsz=rsize[2];
- // detect edges in all non-border pixels in the buffer
- do_adjacentEdgeDetection(t, rw, limask, lomask, lres, res, rsize, isz, osz, gsz);
- }
- else { // "all" inner edge mode is turned on
- if (node->custom1) { // if "keep inside" buffer edge mode is turned on
- do_allKeepBorders(t, rw, limask, lomask, lres, res, rsize);
- }
- else { // "bleed out" buffer edge mode is turned on
- do_allBleedBorders(t, rw, limask, lomask, lres, res, rsize);
- }
- isz=rsize[0]; // set up inner edge, outer edge, and gradient buffer sizes after border pass
- osz=rsize[1];
- gsz=rsize[2];
- // detect edges in all non-border pixels in the buffer
- do_allEdgeDetection(t, rw, limask, lomask, lres, res, rsize, isz, osz, gsz);
- }
-
- isz=rsize[0]; // set edge and gradient buffer sizes once again...
- osz=rsize[1]; // the sizes in rsize[] may have been modified
- gsz=rsize[2]; // by the do_*EdgeDetection() function.
-
- // quick check for existance of edges in the buffer...
- // if we don't have any one of the three sizes, the other two make no difference visually,
- // so we can just pass the inner input buffer back as output.
- if (!gsz || !isz || !osz) {
- out[0]->data= stackbuf; // point the node output buffer to our filled buffer
- return;
- }
-
-
- fsz=gsz+isz+osz; // calculate size of pixel index buffer needed
- gbuf= MEM_mallocN(fsz*sizeof(int), "grd buf"); // allocate edge/gradient pixel index buffer
-
- do_createEdgeLocationBuffer(t, rw, lres, res, gbuf, &innerEdgeOffset, &outerEdgeOffset, isz, gsz);
- do_fillGradientBuffer(rw, res, gbuf, isz, osz, gsz, innerEdgeOffset, outerEdgeOffset);
-
- MEM_freeN(gbuf); // free the gradient index buffer
- out[0]->data= stackbuf; // point the node output buffer to our filled buffer
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_doubleedgemask(bNodeTreeType *ttype)
+void register_node_type_cmp_doubleedgemask(void)
{
static bNodeType ntype; // allocate a node type data structure
- node_type_base(ttype, &ntype, CMP_NODE_DOUBLEEDGEMASK, "Double Edge Mask", NODE_CLASS_MATTE, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_DOUBLEEDGEMASK, "Double Edge Mask", NODE_CLASS_MATTE, NODE_OPTIONS);
+ node_type_socket_templates(&ntype, cmp_node_doubleedgemask_in, cmp_node_doubleedgemask_out);
node_type_socket_templates(&ntype, cmp_node_doubleedgemask_in, cmp_node_doubleedgemask_out);
- node_type_size(&ntype, 210, 210, 210);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_doubleedgemask);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c b/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c
index 761b0b13f11..c4a01abc6d1 100644
--- a/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c
+++ b/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate cmp_node_ellipsemask_out[] = {
{ -1, 0, "" }
};
-static void node_composit_init_ellipsemask(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_ellipsemask(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeEllipseMask *data = MEM_callocN(sizeof(NodeEllipseMask), "NodeEllipseMask");
data->x = 0.5;
@@ -55,17 +55,17 @@ static void node_composit_init_ellipsemask(bNodeTree *UNUSED(ntree), bNode *node
node->storage = data;
}
-void register_node_type_cmp_ellipsemask(bNodeTreeType *ttype)
+void register_node_type_cmp_ellipsemask(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MASK_ELLIPSE, "Ellipse Mask", NODE_CLASS_MATTE, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MASK_ELLIPSE, "Ellipse Mask", NODE_CLASS_MATTE, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_ellipsemask_in, cmp_node_ellipsemask_out);
- node_type_size(&ntype, 260, 110, 300);
+ node_type_size(&ntype, 260, 110, 320);
node_type_init(&ntype, node_composit_init_ellipsemask);
node_type_storage(&ntype, "NodeEllipseMask", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_filter.c b/source/blender/nodes/composite/nodes/node_composite_filter.c
index a27116ab077..408c2ff8d73 100644
--- a/source/blender/nodes/composite/nodes/node_composite_filter.c
+++ b/source/blender/nodes/composite/nodes/node_composite_filter.c
@@ -43,197 +43,13 @@ static bNodeSocketTemplate cmp_node_filter_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_filter_edge(CompBuf *out, CompBuf *in, float *filter, float fac)
-{
- float *row1, *row2, *row3;
- float *fp, f1, f2, mfac= 1.0f-fac;
- int rowlen, x, y, c, pix= in->type;
-
- rowlen= in->x;
-
- for (y=0; y<in->y; y++) {
- /* setup rows */
- if (y==0) row1= in->rect;
- else row1= in->rect + pix*(y-1)*rowlen;
-
- row2= in->rect + y*pix*rowlen;
-
- if (y==in->y-1) row3= row2;
- else row3= row2 + pix*rowlen;
-
- fp= out->rect + pix*y*rowlen;
-
- if (pix==CB_RGBA) {
- copy_v4_v4(fp, row2);
- fp+= pix;
-
- for (x=2; x<rowlen; x++) {
- for (c=0; c<3; c++) {
- f1= filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8];
- f2= filter[0]*row1[0] + filter[3]*row1[4] + filter[6]*row1[8] + filter[1]*row2[0] + filter[4]*row2[4] + filter[7]*row2[8] + filter[2]*row3[0] + filter[5]*row3[4] + filter[8]*row3[8];
- fp[0] = mfac*row2[4] + fac*sqrt(f1*f1 + f2*f2);
- fp++; row1++; row2++; row3++;
- }
- fp[0] = row2[4];
- /* no alpha... will clear it completely */
- fp++; row1++; row2++; row3++;
- }
- copy_v4_v4(fp, row2+4);
- }
- else if (pix==CB_VAL) {
- fp+= pix;
- for (x=2; x<rowlen; x++) {
- f1= filter[0]*row1[0] + filter[1]*row1[1] + filter[2]*row1[2] + filter[3]*row2[0] + filter[4]*row2[1] + filter[5]*row2[2] + filter[6]*row3[0] + filter[7]*row3[1] + filter[8]*row3[2];
- f2= filter[0]*row1[0] + filter[3]*row1[1] + filter[6]*row1[2] + filter[1]*row2[0] + filter[4]*row2[1] + filter[7]*row2[2] + filter[2]*row3[0] + filter[5]*row3[1] + filter[8]*row3[2];
- fp[0] = mfac*row2[1] + fac*sqrt(f1*f1 + f2*f2);
- fp++; row1++; row2++; row3++;
- }
- }
- }
-}
-
-static void do_filter3(CompBuf *out, CompBuf *in, float *filter, float fac)
-{
- float *row1, *row2, *row3;
- float *fp, mfac= 1.0f-fac;
- int rowlen, x, y, c;
- int pixlen= in->type;
-
- rowlen= in->x;
-
- for (y=0; y<in->y; y++) {
- /* setup rows */
- if (y==0) row1= in->rect;
- else row1= in->rect + pixlen*(y-1)*rowlen;
-
- row2= in->rect + y*pixlen*rowlen;
-
- if (y==in->y-1) row3= row2;
- else row3= row2 + pixlen*rowlen;
-
- fp= out->rect + pixlen*(y)*rowlen;
-
- if (pixlen==1) {
- fp[0] = row2[0];
- fp+= 1;
-
- for (x=2; x<rowlen; x++) {
- fp[0] = mfac*row2[1] + fac*(filter[0]*row1[0] + filter[1]*row1[1] + filter[2]*row1[2] + filter[3]*row2[0] + filter[4]*row2[1] + filter[5]*row2[2] + filter[6]*row3[0] + filter[7]*row3[1] + filter[8]*row3[2]);
- fp++; row1++; row2++; row3++;
- }
- fp[0] = row2[1];
- }
- else if (pixlen==2) {
- fp[0] = row2[0];
- fp[1] = row2[1];
- fp+= 2;
-
- for (x=2; x<rowlen; x++) {
- for (c=0; c<2; c++) {
- fp[0] = mfac*row2[2] + fac*(filter[0]*row1[0] + filter[1]*row1[2] + filter[2]*row1[4] + filter[3]*row2[0] + filter[4]*row2[2] + filter[5]*row2[4] + filter[6]*row3[0] + filter[7]*row3[2] + filter[8]*row3[4]);
- fp++; row1++; row2++; row3++;
- }
- }
- fp[0] = row2[2];
- fp[1] = row2[3];
- }
- else if (pixlen==3) {
- copy_v3_v3(fp, row2);
- fp+= 3;
-
- for (x=2; x<rowlen; x++) {
- for (c=0; c<3; c++) {
- fp[0] = mfac*row2[3] + fac*(filter[0]*row1[0] + filter[1]*row1[3] + filter[2]*row1[6] + filter[3]*row2[0] + filter[4]*row2[3] + filter[5]*row2[6] + filter[6]*row3[0] + filter[7]*row3[3] + filter[8]*row3[6]);
- fp++; row1++; row2++; row3++;
- }
- }
- copy_v3_v3(fp, row2+3);
- }
- else {
- copy_v4_v4(fp, row2);
- fp+= 4;
-
- for (x=2; x<rowlen; x++) {
- for (c=0; c<4; c++) {
- fp[0] = mfac*row2[4] + fac*(filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8]);
- fp++; row1++; row2++; row3++;
- }
- }
- copy_v4_v4(fp, row2+4);
- }
- }
-}
-
-
-static void node_composit_exec_filter(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
-{
- static float soft[9] = {1/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 4/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 1/16.0f};
- float sharp[9] = {-1, -1, -1, -1, 9, -1, -1, -1, -1};
- float laplace[9] = {-1/8.0f, -1/8.0f, -1/8.0f, -1/8.0f, 1.0f, -1/8.0f, -1/8.0f, -1/8.0f, -1/8.0f};
- float sobel[9] = {1, 2, 1, 0, 0, 0, -1, -2, -1};
- float prewitt[9] = {1, 1, 1, 0, 0, 0, -1, -1, -1};
- float kirsch[9] = {5, 5, 5, -3, -3, -3, -2, -2, -2};
- float shadow[9] = {1, 2, 1, 0, 1, 0, -1, -2, -1};
-
- if (out[0]->hasoutput==0) return;
-
- /* stack order in: Image */
- /* stack order out: Image */
-
- if (in[1]->data) {
- /* make output size of first available input image */
- CompBuf *cbuf= in[1]->data;
- CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1); /* allocs */
-
- /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */
- stackbuf->xof= cbuf->xof;
- stackbuf->yof= cbuf->yof;
-
- switch (node->custom1) {
- case CMP_FILT_SOFT:
- do_filter3(stackbuf, cbuf, soft, in[0]->vec[0]);
- break;
- case CMP_FILT_SHARP:
- do_filter3(stackbuf, cbuf, sharp, in[0]->vec[0]);
- break;
- case CMP_FILT_LAPLACE:
- do_filter3(stackbuf, cbuf, laplace, in[0]->vec[0]);
- break;
- case CMP_FILT_SOBEL:
- do_filter_edge(stackbuf, cbuf, sobel, in[0]->vec[0]);
- break;
- case CMP_FILT_PREWITT:
- do_filter_edge(stackbuf, cbuf, prewitt, in[0]->vec[0]);
- break;
- case CMP_FILT_KIRSCH:
- do_filter_edge(stackbuf, cbuf, kirsch, in[0]->vec[0]);
- break;
- case CMP_FILT_SHADOW:
- do_filter3(stackbuf, cbuf, shadow, in[0]->vec[0]);
- break;
- }
-
- out[0]->data= stackbuf;
-
- generate_preview(data, node, out[0]->data);
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_filter(bNodeTreeType *ttype)
+void register_node_type_cmp_filter(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_FILTER, "Filter", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_FILTER, "Filter", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_filter_in, cmp_node_filter_out);
- node_type_size(&ntype, 80, 40, 120);
node_type_label(&ntype, node_filter_label);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_filter);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_flip.c b/source/blender/nodes/composite/nodes/node_composite_flip.c
index 4aa98d173e7..f05447d79c2 100644
--- a/source/blender/nodes/composite/nodes/node_composite_flip.c
+++ b/source/blender/nodes/composite/nodes/node_composite_flip.c
@@ -43,65 +43,12 @@ static bNodeSocketTemplate cmp_node_flip_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void node_composit_exec_flip(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- if (in[0]->data) {
- CompBuf *cbuf= in[0]->data;
- CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1); /* note, this returns zero'd image */
- int i, src_pix, src_width, src_height, srcydelt, outydelt, x, y;
- float *srcfp, *outfp;
-
- src_pix= cbuf->type;
- src_width= cbuf->x;
- src_height= cbuf->y;
- srcfp= cbuf->rect;
- outfp= stackbuf->rect;
- srcydelt= src_width*src_pix;
- outydelt= srcydelt;
-
- if (node->custom1) { /*set up output pointer for y flip*/
- outfp+= (src_height-1)*outydelt;
- outydelt= -outydelt;
- }
-
- for (y=0; y<src_height; y++) {
- if (node->custom1 == 1) { /* no x flip so just copy line*/
- memcpy(outfp, srcfp, sizeof(float) * src_pix * src_width);
- srcfp+=srcydelt;
- }
- else {
- outfp += (src_width-1)*src_pix;
- for (x=0; x<src_width; x++) {
- for (i=0; i<src_pix; i++) {
- outfp[i] = srcfp[i];
- }
- outfp -= src_pix;
- srcfp += src_pix;
- }
- outfp += src_pix;
- }
- outfp += outydelt;
- }
-
- out[0]->data= stackbuf;
-
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_flip(bNodeTreeType *ttype)
+void register_node_type_cmp_flip(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_FLIP, "Flip", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_FLIP, "Flip", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_flip_in, cmp_node_flip_out);
- node_type_size(&ntype, 140, 100, 320);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_flip);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_gamma.c b/source/blender/nodes/composite/nodes/node_composite_gamma.c
index b8c99894301..27bf72d53b4 100644
--- a/source/blender/nodes/composite/nodes/node_composite_gamma.c
+++ b/source/blender/nodes/composite/nodes/node_composite_gamma.c
@@ -34,7 +34,7 @@
#include "node_composite_util.h"
/* **************** Gamma Tools ******************** */
-
+
static bNodeSocketTemplate cmp_node_gamma_in[] = {
{ SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Gamma"), 1.0f, 0.0f, 0.0f, 0.0f, 0.001f, 10.0f, PROP_UNSIGNED},
@@ -45,50 +45,12 @@ static bNodeSocketTemplate cmp_node_gamma_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_gamma(bNode *UNUSED(node), float *out, float *in, float *fac)
-{
- int i=0;
- for (i=0; i<3; i++) {
- /* check for negative to avoid nan's */
- out[i] = (in[i] > 0.0f)? powf(in[i], fac[0]): in[i];
- }
- out[3] = in[3];
-}
-static void node_composit_exec_gamma(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order in: Fac, Image */
- /* stack order out: Image */
- if (out[0]->hasoutput==0) return;
-
- /* input no image? then only color operation */
- if (in[0]->data==NULL) {
- do_gamma(node, out[0]->vec, in[0]->vec, in[1]->vec);
- }
- else {
- /* make output size of input image */
- CompBuf *cbuf= in[0]->data;
- CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
-
- composit2_pixel_processor(node, stackbuf, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_gamma, CB_RGBA, CB_VAL);
-
- out[0]->data= stackbuf;
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_gamma(bNodeTreeType *ttype)
+void register_node_type_cmp_gamma(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_gamma_in, cmp_node_gamma_out);
- node_type_size(&ntype, 140, 100, 320);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_gamma);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_glare.c b/source/blender/nodes/composite/nodes/node_composite_glare.c
index 950d8a56f58..19f5ab10a15 100644
--- a/source/blender/nodes/composite/nodes/node_composite_glare.c
+++ b/source/blender/nodes/composite/nodes/node_composite_glare.c
@@ -41,443 +41,7 @@ static bNodeSocketTemplate cmp_node_glare_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-// mix two images, src buffer does not have to be same size,
-static void mixImages(CompBuf *dst, CompBuf *src, float mix)
-{
- int x, y;
- fRGB c1, c2, *dcolp, *scolp;
- const float mf = 2.f - 2.f*fabsf(mix - 0.5f);
- if ((dst->x == src->x) && (dst->y == src->y)) {
- for (y=0; y<dst->y; y++) {
- dcolp = (fRGB*)&dst->rect[y*dst->x*dst->type];
- scolp = (fRGB*)&src->rect[y*dst->x*dst->type];
- for (x=0; x<dst->x; x++) {
- copy_v3_v3(c1, dcolp[x]);
- copy_v3_v3(c2, scolp[x]);
- c1[0] += mix*(c2[0] - c1[0]);
- c1[1] += mix*(c2[1] - c1[1]);
- c1[2] += mix*(c2[2] - c1[2]);
- if (c1[0] < 0.f) c1[0] = 0.f;
- if (c1[1] < 0.f) c1[1] = 0.f;
- if (c1[2] < 0.f) c1[2] = 0.f;
- mul_v3_fl(c1, mf);
- copy_v3_v3(dcolp[x], c1);
- }
- }
- }
- else {
- float xr = src->x / (float)dst->x;
- float yr = src->y / (float)dst->y;
- for (y=0; y<dst->y; y++) {
- dcolp = (fRGB*)&dst->rect[y*dst->x*dst->type];
- for (x=0; x<dst->x; x++) {
- copy_v3_v3(c1, dcolp[x]);
- qd_getPixelLerp(src, (x + 0.5f)*xr - 0.5f, (y + 0.5f)*yr - 0.5f, c2);
- c1[0] += mix*(c2[0] - c1[0]);
- c1[1] += mix*(c2[1] - c1[1]);
- c1[2] += mix*(c2[2] - c1[2]);
- if (c1[0] < 0.f) c1[0] = 0.f;
- if (c1[1] < 0.f) c1[1] = 0.f;
- if (c1[2] < 0.f) c1[2] = 0.f;
- mul_v3_fl(c1, mf);
- copy_v3_v3(dcolp[x], c1);
- }
- }
- }
-}
-
-
-// adds src to dst image, must be of same size
-static void addImage(CompBuf* dst, CompBuf* src, float scale)
-{
- if ((dst->x == src->x) && (dst->y == src->y)) {
- int p = dst->x*dst->y*dst->type;
- float *dcol = dst->rect, *scol = src->rect;
- while (p--) *dcol++ += *scol++ * scale;
- }
-}
-
-
-// returns possibly downscaled copy of all pixels above threshold
-static CompBuf* BTP(CompBuf* src, float threshold, int scaledown)
-{
- int x, y;
- CompBuf* bsrc = qd_downScaledCopy(src, scaledown);
- float* cr = bsrc->rect;
- for (y=0; y<bsrc->y; ++y)
- for (x=0; x<bsrc->x; ++x, cr+=4) {
- if (rgb_to_luma_y(cr) >= threshold) {
- cr[0] -= threshold, cr[1] -= threshold, cr[2] -= threshold;
- cr[0] = MAX2(cr[0], 0.f);
- cr[1] = MAX2(cr[1], 0.f);
- cr[2] = MAX2(cr[2], 0.f);
- }
- else cr[0] = cr[1] = cr[2] = 0.f;
- }
- return bsrc;
-}
-
-//--------------------------------------------------------------------------------------------
-// simple 4-point star filter
-
-static void star4(NodeGlare* ndg, CompBuf* dst, CompBuf* src)
-{
- int x, y, i, xm, xp, ym, yp;
- float c[4] = {0, 0, 0, 0}, tc[4] = {0, 0, 0, 0};
- CompBuf *tbuf1, *tbuf2, *tsrc;
- const float f1 = 1.f - ndg->fade, f2 = (1.f - f1)*0.5f;
- //const float t3 = ndg->threshold*3.f;
- const float sc = (float)(1 << ndg->quality);
- const float isc = 1.f/sc;
-
- tsrc = BTP(src, ndg->threshold, (int)sc);
-
- tbuf1 = dupalloc_compbuf(tsrc);
- tbuf2 = dupalloc_compbuf(tsrc);
-
- for (i=0; i<ndg->iter; i++) {
- // (x || x-1, y-1) to (x || x+1, y+1)
- // F
- for (y=0; y<tbuf1->y; y++) {
- ym = y - i;
- yp = y + i;
- for (x=0; x<tbuf1->x; x++) {
- xm = x - i;
- xp = x + i;
- qd_getPixel(tbuf1, x, y, c);
- mul_v3_fl(c, f1);
- qd_getPixel(tbuf1, (ndg->angle ? xm : x), ym, tc);
- madd_v3_v3fl(c, tc, f2);
- qd_getPixel(tbuf1, (ndg->angle ? xp : x), yp, tc);
- madd_v3_v3fl(c, tc, f2);
- qd_setPixel(tbuf1, x, y, c);
- }
- }
- // B
- for (y=tbuf1->y-1; y>=0; y--) {
- ym = y - i;
- yp = y + i;
- for (x=tbuf1->x-1; x>=0; x--) {
- xm = x - i;
- xp = x + i;
- qd_getPixel(tbuf1, x, y, c);
- mul_v3_fl(c, f1);
- qd_getPixel(tbuf1, (ndg->angle ? xm : x), ym, tc);
- madd_v3_v3fl(c, tc, f2);
- qd_getPixel(tbuf1, (ndg->angle ? xp : x), yp, tc);
- madd_v3_v3fl(c, tc, f2);
- qd_setPixel(tbuf1, x, y, c);
- }
- }
- // (x-1, y || y+1) to (x+1, y || y-1)
- // F
- for (y=0; y<tbuf2->y; y++) {
- ym = y - i;
- yp = y + i;
- for (x=0; x<tbuf2->x; x++) {
- xm = x - i;
- xp = x + i;
- qd_getPixel(tbuf2, x, y, c);
- mul_v3_fl(c, f1);
- qd_getPixel(tbuf2, xm, (ndg->angle ? yp : y), tc);
- madd_v3_v3fl(c, tc, f2);
- qd_getPixel(tbuf2, xp, (ndg->angle ? ym : y), tc);
- madd_v3_v3fl(c, tc, f2);
- qd_setPixel(tbuf2, x, y, c);
- }
- }
- // B
- for (y=tbuf2->y-1; y>=0; y--) {
- ym = y - i;
- yp = y + i;
- for (x=tbuf2->x-1; x>=0; x--) {
- xm = x - i;
- xp = x + i;
- qd_getPixel(tbuf2, x, y, c);
- mul_v3_fl(c, f1);
- qd_getPixel(tbuf2, xm, (ndg->angle ? yp : y), tc);
- madd_v3_v3fl(c, tc, f2);
- qd_getPixel(tbuf2, xp, (ndg->angle ? ym : y), tc);
- madd_v3_v3fl(c, tc, f2);
- qd_setPixel(tbuf2, x, y, c);
- }
- }
- }
-
- for (y=0; y<tbuf1->y; ++y)
- for (x=0; x<tbuf1->x; ++x) {
- unsigned int p = (x + y*tbuf1->x)*tbuf1->type;
- tbuf1->rect[p] += tbuf2->rect[p];
- tbuf1->rect[p+1] += tbuf2->rect[p+1];
- tbuf1->rect[p+2] += tbuf2->rect[p+2];
- }
-
- for (y=0; y<dst->y; ++y) {
- const float m = 0.5f + 0.5f*ndg->mix;
- for (x=0; x<dst->x; ++x) {
- unsigned int p = (x + y*dst->x)*dst->type;
- qd_getPixelLerp(tbuf1, x*isc, y*isc, tc);
- dst->rect[p] = src->rect[p] + m*(tc[0] - src->rect[p]);
- dst->rect[p+1] = src->rect[p+1] + m*(tc[1] - src->rect[p+1]);
- dst->rect[p+2] = src->rect[p+2] + m*(tc[2] - src->rect[p+2]);
- }
- }
-
- free_compbuf(tbuf1);
- free_compbuf(tbuf2);
- free_compbuf(tsrc);
-}
-
-//--------------------------------------------------------------------------------------------
-// streak filter
-
-static void streaks(NodeGlare* ndg, CompBuf* dst, CompBuf* src)
-{
- CompBuf *bsrc, *tsrc, *tdst, *sbuf;
- int x, y, n;
- unsigned int nump=0;
- fRGB c1, c2, c3, c4;
- float a, ang = DEG2RADF(360.0f)/(float)ndg->angle;
-
- bsrc = BTP(src, ndg->threshold, 1 << ndg->quality);
- tsrc = dupalloc_compbuf(bsrc); // sample from buffer
- tdst = alloc_compbuf(tsrc->x, tsrc->y, tsrc->type, 1); // sample to buffer
- sbuf = alloc_compbuf(tsrc->x, tsrc->y, tsrc->type, 1); // streak sum buffer
-
-
- for (a=0.f; a<DEG2RADF(360.0f); a+=ang) {
- const float an = a + ndg->angle_ofs;
- const float vx = cos((double)an), vy = sin((double)an);
- for (n=0; n<ndg->iter; ++n) {
- const float p4 = pow(4.0, (double)n);
- const float vxp = vx*p4, vyp = vy*p4;
- const float wt = pow((double)ndg->fade, (double)p4);
- const float cmo = 1.f - (float)pow((double)ndg->colmod, (double)n+1); // colormodulation amount relative to current pass
- float* tdstcol = tdst->rect;
- for (y=0; y<tsrc->y; ++y) {
- for (x=0; x<tsrc->x; ++x, tdstcol+=4) {
- // first pass no offset, always same for every pass, exact copy,
- // otherwise results in uneven brightness, only need once
- if (n==0) qd_getPixel(tsrc, x, y, c1); else c1[0]=c1[1]=c1[2]=0;
- qd_getPixelLerp(tsrc, x + vxp, y + vyp, c2);
- qd_getPixelLerp(tsrc, x + vxp*2.f, y + vyp*2.f, c3);
- qd_getPixelLerp(tsrc, x + vxp*3.f, y + vyp*3.f, c4);
- // modulate color to look vaguely similar to a color spectrum
- fRGB_rgbmult(c2, 1.f, cmo, cmo);
- fRGB_rgbmult(c3, cmo, cmo, 1.f);
- fRGB_rgbmult(c4, cmo, 1.f, cmo);
- tdstcol[0] = 0.5f*(tdstcol[0] + c1[0] + wt*(c2[0] + wt*(c3[0] + wt*c4[0])));
- tdstcol[1] = 0.5f*(tdstcol[1] + c1[1] + wt*(c2[1] + wt*(c3[1] + wt*c4[1])));
- tdstcol[2] = 0.5f*(tdstcol[2] + c1[2] + wt*(c2[2] + wt*(c3[2] + wt*c4[2])));
- }
- }
- memcpy(tsrc->rect, tdst->rect, sizeof(float)*tdst->x*tdst->y*tdst->type);
- }
-
- addImage(sbuf, tsrc, 1.f/(float)(6 - ndg->iter));
- memset(tdst->rect, 0, tdst->x*tdst->y*tdst->type*sizeof(float));
- memcpy(tsrc->rect, bsrc->rect, bsrc->x*bsrc->y*bsrc->type*sizeof(float));
- nump++;
- }
-
- mixImages(dst, sbuf, 0.5f + 0.5f*ndg->mix);
-
- free_compbuf(tsrc);
- free_compbuf(tdst);
- free_compbuf(sbuf);
- free_compbuf(bsrc);
-}
-
-
-//--------------------------------------------------------------------------------------------
-// Ghosts (lensflare)
-
-static float smoothMask(float x, float y)
-{
- float t;
- x = 2.f*x - 1.f, y = 2.f*y - 1.f;
- if ((t = 1.f - sqrtf(x*x + y*y)) <= 0.f) return 0.f;
- return t;
-}
-
-static void ghosts(NodeGlare* ndg, CompBuf* dst, CompBuf* src)
-{
- // colormodulation and scale factors (cm & scalef) for 16 passes max: 64
- int x, y, n, p, np;
- fRGB c, tc, cm[64];
- float sc, isc, u, v, sm, s, t, ofs, scalef[64];
- CompBuf *tbuf1, *tbuf2, *gbuf;
- const float cmo = 1.f - ndg->colmod;
- const int qt = 1 << ndg->quality;
- const float s1 = 4.f/(float)qt, s2 = 2.f*s1;
-
- gbuf = BTP(src, ndg->threshold, qt);
- tbuf1 = dupalloc_compbuf(gbuf);
- IIR_gauss(tbuf1, s1, 0, 3);
- IIR_gauss(tbuf1, s1, 1, 3);
- IIR_gauss(tbuf1, s1, 2, 3);
- tbuf2 = dupalloc_compbuf(tbuf1);
- IIR_gauss(tbuf2, s2, 0, 3);
- IIR_gauss(tbuf2, s2, 1, 3);
- IIR_gauss(tbuf2, s2, 2, 3);
-
- if (ndg->iter & 1) ofs = 0.5f; else ofs = 0.f;
- for (x=0; x<(ndg->iter*4); x++) {
- y = x & 3;
- cm[x][0] = cm[x][1] = cm[x][2] = 1;
- if (y==1) fRGB_rgbmult(cm[x], 1.f, cmo, cmo);
- if (y==2) fRGB_rgbmult(cm[x], cmo, cmo, 1.f);
- if (y==3) fRGB_rgbmult(cm[x], cmo, 1.f, cmo);
- scalef[x] = 2.1f*(1.f-(x+ofs)/(float)(ndg->iter*4));
- if (x & 1) scalef[x] = -0.99f/scalef[x];
- }
-
- sc = 2.13;
- isc = -0.97;
- for (y=0; y<gbuf->y; y++) {
- v = (float)(y+0.5f) / (float)gbuf->y;
- for (x=0; x<gbuf->x; x++) {
- u = (float)(x+0.5f) / (float)gbuf->x;
- s = (u-0.5f)*sc + 0.5f, t = (v-0.5f)*sc + 0.5f;
- qd_getPixelLerp(tbuf1, s*gbuf->x, t*gbuf->y, c);
- sm = smoothMask(s, t);
- mul_v3_fl(c, sm);
- s = (u-0.5f)*isc + 0.5f, t = (v-0.5f)*isc + 0.5f;
- qd_getPixelLerp(tbuf2, s*gbuf->x - 0.5f, t*gbuf->y - 0.5f, tc);
- sm = smoothMask(s, t);
- madd_v3_v3fl(c, tc, sm);
- qd_setPixel(gbuf, x, y, c);
- }
- }
-
- memset(tbuf1->rect, 0, tbuf1->x*tbuf1->y*tbuf1->type*sizeof(float));
- for (n=1; n<ndg->iter; n++) {
- for (y=0; y<gbuf->y; y++) {
- v = (float)(y+0.5f) / (float)gbuf->y;
- for (x=0; x<gbuf->x; x++) {
- u = (float)(x+0.5f) / (float)gbuf->x;
- tc[0] = tc[1] = tc[2] = 0.f;
- for (p=0;p<4;p++) {
- np = (n<<2) + p;
- s = (u-0.5f)*scalef[np] + 0.5f;
- t = (v-0.5f)*scalef[np] + 0.5f;
- qd_getPixelLerp(gbuf, s*gbuf->x - 0.5f, t*gbuf->y - 0.5f, c);
- mul_v3_v3(c, cm[np]);
- sm = smoothMask(s, t)*0.25f;
- madd_v3_v3fl(tc, c, sm);
- }
- p = (x + y*tbuf1->x)*tbuf1->type;
- tbuf1->rect[p] += tc[0];
- tbuf1->rect[p+1] += tc[1];
- tbuf1->rect[p+2] += tc[2];
- }
- }
- memcpy(gbuf->rect, tbuf1->rect, tbuf1->x*tbuf1->y*tbuf1->type*sizeof(float));
- }
-
- free_compbuf(tbuf1);
- free_compbuf(tbuf2);
-
- mixImages(dst, gbuf, 0.5f + 0.5f*ndg->mix);
- free_compbuf(gbuf);
-}
-
-//--------------------------------------------------------------------------------------------
-// Fog glow (convolution with kernel of exponential falloff)
-
-static void fglow(NodeGlare* ndg, CompBuf* dst, CompBuf* src)
-{
- int x, y;
- float scale, u, v, r, w, d;
- fRGB fcol;
- CompBuf *tsrc, *ckrn;
- unsigned int sz = 1 << ndg->size;
- const float cs_r = 1.f, cs_g = 1.f, cs_b = 1.f;
-
- // temp. src image
- tsrc = BTP(src, ndg->threshold, 1 << ndg->quality);
- // make the convolution kernel
- ckrn = alloc_compbuf(sz, sz, CB_RGBA, 1);
-
- scale = 0.25f*sqrtf(sz*sz);
-
- for (y=0; y<sz; ++y) {
- v = 2.f*(y / (float)sz) - 1.f;
- for (x=0; x<sz; ++x) {
- u = 2.f*(x / (float)sz) - 1.f;
- r = (u*u + v*v)*scale;
- d = -sqrtf(sqrtf(sqrtf(r)))*9.f;
- fcol[0] = expf(d*cs_r), fcol[1] = expf(d*cs_g), fcol[2] = expf(d*cs_b);
- // linear window good enough here, visual result counts, not scientific analysis
- //w = (1.f-fabs(u))*(1.f-fabs(v));
- // actually, Hanning window is ok, cos^2 for some reason is slower
- w = (0.5f + 0.5f*cos((double)u*M_PI))*(0.5f + 0.5f*cos((double)v*M_PI));
- mul_v3_fl(fcol, w);
- qd_setPixel(ckrn, x, y, fcol);
- }
- }
-
- convolve(tsrc, tsrc, ckrn);
- free_compbuf(ckrn);
- mixImages(dst, tsrc, 0.5f + 0.5f*ndg->mix);
- free_compbuf(tsrc);
-}
-
-//--------------------------------------------------------------------------------------------
-
-static void node_composit_exec_glare(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- CompBuf *new, *src, *img = in[0]->data;
- NodeGlare* ndg = node->storage;
-
- if ((img == NULL) || (out[0]->hasoutput == 0)) return;
-
- if (img->type != CB_RGBA) {
- new = typecheck_compbuf(img, CB_RGBA);
- src = typecheck_compbuf(img, CB_RGBA);
- }
- else {
- new = dupalloc_compbuf(img);
- src = dupalloc_compbuf(img);
- }
-
- {
- int x, y;
- for (y=0; y<new->y; ++y) {
- fRGB* col = (fRGB*)&new->rect[y*new->x*new->type];
- for (x=0; x<new->x; ++x) {
- col[x][0] = MAX2(col[x][0], 0.f);
- col[x][1] = MAX2(col[x][1], 0.f);
- col[x][2] = MAX2(col[x][2], 0.f);
- }
- }
- }
-
- switch (ndg->type) {
- case 0:
- star4(ndg, new, src);
- break;
- case 1:
- fglow(ndg, new, src);
- break;
- case 3:
- ghosts(ndg, new, src);
- break;
- case 2:
- default:
- streaks(ndg, new, src);
- break;
- }
-
- free_compbuf(src);
- out[0]->data = new;
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_glare(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_glare(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeGlare *ndg = MEM_callocN(sizeof(NodeGlare), "node glare data");
ndg->quality = 1;
@@ -493,18 +57,14 @@ static void node_composit_init_glare(bNodeTree *UNUSED(ntree), bNode *node, bNod
node->storage = ndg;
}
-void register_node_type_cmp_glare(bNodeTreeType *ttype)
+void register_node_type_cmp_glare(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_GLARE, "Glare", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_GLARE, "Glare", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_glare_in, cmp_node_glare_out);
- node_type_size(&ntype, 150, 120, 200);
node_type_init(&ntype, node_composit_init_glare);
node_type_storage(&ntype, "NodeGlare", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_glare);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_hueSatVal.c b/source/blender/nodes/composite/nodes/node_composite_hueSatVal.c
index d52e3d01a32..01c6f639cbb 100644
--- a/source/blender/nodes/composite/nodes/node_composite_hueSatVal.c
+++ b/source/blender/nodes/composite/nodes/node_composite_hueSatVal.c
@@ -44,60 +44,7 @@ static bNodeSocketTemplate cmp_node_hue_sat_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_hue_sat_fac(bNode *node, float *out, float *in, float *fac)
-{
- NodeHueSat *nhs= node->storage;
-
- if (*fac!=0.0f && (nhs->hue!=0.5f || nhs->sat!=1.0f || nhs->val!=1.0f)) {
- float col[3], hsv[3], mfac= 1.0f - *fac;
-
- rgb_to_hsv(in[0], in[1], in[2], hsv, hsv+1, hsv+2);
- hsv[0]+= (nhs->hue - 0.5f);
- if (hsv[0]>1.0f) hsv[0]-=1.0f; else if (hsv[0]<0.0f) hsv[0]+= 1.0f;
- hsv[1]*= nhs->sat;
- hsv[2]*= nhs->val;
- hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col+1, col+2);
-
- out[0] = mfac*in[0] + *fac*col[0];
- out[1] = mfac*in[1] + *fac*col[1];
- out[2] = mfac*in[2] + *fac*col[2];
- out[3] = in[3];
- }
- else {
- copy_v4_v4(out, in);
- }
-}
-
-static void node_composit_exec_hue_sat(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order in: Fac, Image */
- /* stack order out: Image */
- if (out[0]->hasoutput==0) return;
-
- /* input no image? then only color operation */
- if (in[1]->data==NULL) {
- do_hue_sat_fac(node, out[0]->vec, in[1]->vec, in[0]->vec);
- }
- else {
- /* make output size of input image */
- CompBuf *cbuf= dupalloc_compbuf(in[1]->data);
- CompBuf *stackbuf=typecheck_compbuf(cbuf, CB_RGBA);
-
- composit2_pixel_processor(node, stackbuf, stackbuf, in[1]->vec, in[0]->data, in[0]->vec, do_hue_sat_fac, CB_RGBA, CB_VAL);
-
- out[0]->data= stackbuf;
-
- /* get rid of intermediary cbuf if it's extra */
- if (stackbuf!=cbuf)
- free_compbuf(cbuf);
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_hue_sat(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_hue_sat(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeHueSat *nhs= MEM_callocN(sizeof(NodeHueSat), "node hue sat");
node->storage= nhs;
@@ -106,18 +53,14 @@ static void node_composit_init_hue_sat(bNodeTree *UNUSED(ntree), bNode *node, bN
nhs->val= 1.0f;
}
-void register_node_type_cmp_hue_sat(bNodeTreeType *ttype)
+void register_node_type_cmp_hue_sat(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_hue_sat_in, cmp_node_hue_sat_out);
- node_type_size(&ntype, 150, 80, 250);
node_type_init(&ntype, node_composit_init_hue_sat);
node_type_storage(&ntype, "NodeHueSat", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_hue_sat);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_huecorrect.c b/source/blender/nodes/composite/nodes/node_composite_huecorrect.c
index f751dbea8d2..71e4df04911 100644
--- a/source/blender/nodes/composite/nodes/node_composite_huecorrect.c
+++ b/source/blender/nodes/composite/nodes/node_composite_huecorrect.c
@@ -43,107 +43,7 @@ static bNodeSocketTemplate cmp_node_huecorrect_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_huecorrect(bNode *node, float *out, float *in)
-{
- float hsv[3], f;
-
- rgb_to_hsv(in[0], in[1], in[2], hsv, hsv+1, hsv+2);
-
- curvemapping_initialize(node->storage);
-
- /* adjust hue, scaling returned default 0.5 up to 1 */
- f = curvemapping_evaluateF(node->storage, 0, hsv[0]);
- hsv[0] += f-0.5f;
-
- /* adjust saturation, scaling returned default 0.5 up to 1 */
- f = curvemapping_evaluateF(node->storage, 1, hsv[0]);
- hsv[1] *= (f * 2.f);
-
- /* adjust value, scaling returned default 0.5 up to 1 */
- f = curvemapping_evaluateF(node->storage, 2, hsv[0]);
- hsv[2] *= (f * 2.f);
-
- hsv[0] = hsv[0] - floorf(hsv[0]); /* mod 1.0 */
- CLAMP(hsv[1], 0.f, 1.f);
-
- /* convert back to rgb */
- hsv_to_rgb(hsv[0], hsv[1], hsv[2], out, out+1, out+2);
-
- out[3] = in[3];
-}
-
-static void do_huecorrect_fac(bNode *node, float *out, float *in, float *fac)
-{
- float hsv[3], rgb[3], f;
- const float mfac = 1.f-*fac;
-
- rgb_to_hsv(in[0], in[1], in[2], hsv, hsv+1, hsv+2);
-
- curvemapping_initialize(node->storage);
-
- /* adjust hue, scaling returned default 0.5 up to 1 */
- f = curvemapping_evaluateF(node->storage, 0, hsv[0]);
- hsv[0] += f-0.5f;
-
- /* adjust saturation, scaling returned default 0.5 up to 1 */
- f = curvemapping_evaluateF(node->storage, 1, hsv[0]);
- hsv[1] *= (f * 2.f);
-
- /* adjust value, scaling returned default 0.5 up to 1 */
- f = curvemapping_evaluateF(node->storage, 2, hsv[0]);
- hsv[2] *= (f * 2.f);
-
- hsv[0] = hsv[0] - floorf(hsv[0]); /* mod 1.0 */
- CLAMP(hsv[1], 0.f, 1.f);
-
- /* convert back to rgb */
- hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
-
- out[0] = mfac*in[0] + *fac*rgb[0];
- out[1] = mfac*in[1] + *fac*rgb[1];
- out[2] = mfac*in[2] + *fac*rgb[2];
- out[3] = in[3];
-}
-
-static void node_composit_exec_huecorrect(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- CompBuf *cbuf= in[1]->data;
- CompBuf *stackbuf;
-
- /* stack order input: fac, image, black level, white level */
- /* stack order output: image */
-
- if (out[0]->hasoutput==0)
- return;
-
- if (in[0]->vec[0] == 0.f && in[0]->data == NULL) {
- out[0]->data = pass_on_compbuf(cbuf);
- return;
- }
-
- /* input no image? then only color operation */
- if (in[1]->data==NULL) {
- do_huecorrect_fac(node, out[0]->vec, in[1]->vec, in[0]->vec);
- }
-
- if (cbuf) {
- stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* make output size of input image */
-
- if ((in[0]->data==NULL) && (in[0]->vec[0] >= 1.f))
- composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_huecorrect, CB_RGBA);
- else
- composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, in[0]->vec, do_huecorrect_fac, CB_RGBA, CB_VAL);
-
- out[0]->data= stackbuf;
- }
-
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_huecorrect(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_huecorrect(bNodeTree *UNUSED(ntree), bNode *node)
{
CurveMapping *cumapping = node->storage= curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
int c;
@@ -159,18 +59,15 @@ static void node_composit_init_huecorrect(bNodeTree *UNUSED(ntree), bNode *node,
cumapping->cur = 1;
}
-void register_node_type_cmp_huecorrect(bNodeTreeType *ttype)
+void register_node_type_cmp_huecorrect(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_HUECORRECT, "Hue Correct", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_HUECORRECT, "Hue Correct", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_huecorrect_in, cmp_node_huecorrect_out);
- node_type_size(&ntype, 320, 140, 400);
+ node_type_size(&ntype, 320, 140, 500);
node_type_init(&ntype, node_composit_init_huecorrect);
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_huecorrect);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_idMask.c b/source/blender/nodes/composite/nodes/node_composite_idMask.c
index ef0c5021192..529bc83946b 100644
--- a/source/blender/nodes/composite/nodes/node_composite_idMask.c
+++ b/source/blender/nodes/composite/nodes/node_composite_idMask.c
@@ -44,82 +44,12 @@ static bNodeSocketTemplate cmp_node_idmask_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-/* stackbuf should be zeroed */
-static void do_idmask(CompBuf *stackbuf, CompBuf *cbuf, float idnr)
-{
- float *rect;
- int x;
- char *abuf= MEM_mapallocN(cbuf->x*cbuf->y, "anti ali buf");
-
- rect= cbuf->rect;
- for (x= cbuf->x*cbuf->y - 1; x>=0; x--)
- if (rect[x]==idnr)
- abuf[x] = 255;
-
- antialias_tagbuf(cbuf->x, cbuf->y, abuf);
-
- rect= stackbuf->rect;
- for (x= cbuf->x*cbuf->y - 1; x>=0; x--)
- if (abuf[x]>1)
- rect[x] = (1.0f/255.0f)*(float)abuf[x];
-
- MEM_freeN(abuf);
-}
-
-/* full sample version */
-static void do_idmask_fsa(CompBuf *stackbuf, CompBuf *cbuf, float idnr)
-{
- float *rect, *rs;
- int x;
-
- rect= cbuf->rect;
- rs= stackbuf->rect;
- for (x= cbuf->x*cbuf->y - 1; x>=0; x--)
- if (rect[x]==idnr)
- rs[x] = 1.0f;
-
-}
-
-
-static void node_composit_exec_idmask(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
-{
- RenderData *rd= data;
-
- if (out[0]->hasoutput==0)
- return;
-
- if (in[0]->data) {
- CompBuf *cbuf= in[0]->data;
- CompBuf *stackbuf;
-
- if (cbuf->type!=CB_VAL)
- return;
-
- stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */;
-
- if ((rd->scemode & R_FULL_SAMPLE) || node->custom2 == 0)
- do_idmask_fsa(stackbuf, cbuf, (float)node->custom1);
- else
- do_idmask(stackbuf, cbuf, (float)node->custom1);
-
- out[0]->data= stackbuf;
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_idmask(bNodeTreeType *ttype)
+void register_node_type_cmp_idmask(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_ID_MASK, "ID Mask", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_ID_MASK, "ID Mask", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_idmask_in, cmp_node_idmask_out);
- node_type_size(&ntype, 140, 100, 320);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_idmask);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c
index 88d78df190f..c09903ad6c5 100644
--- a/source/blender/nodes/composite/nodes/node_composite_image.c
+++ b/source/blender/nodes/composite/nodes/node_composite_image.c
@@ -29,9 +29,11 @@
* \ingroup cmpnodes
*/
-
#include "node_composite_util.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+
/* **************** IMAGE (and RenderResult, multilayer image) ******************** */
static bNodeSocketTemplate cmp_node_rlayers_out[] = {
@@ -71,7 +73,7 @@ static bNodeSocket *cmp_node_image_add_render_pass_output(bNodeTree *ntree, bNod
bNodeSocket *sock;
NodeImageLayer *sockdata;
- sock = node_add_output_from_template(ntree, node, &cmp_node_rlayers_out[rres_index]);
+ sock = node_add_socket_from_template(ntree, node, &cmp_node_rlayers_out[rres_index], SOCK_OUT);
/* extra socket info */
sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
sock->storage = sockdata;
@@ -158,7 +160,7 @@ static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node,
else
type = SOCK_RGBA;
- sock = nodeAddSocket(ntree, node, SOCK_OUT, rpass->name, type);
+ sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, rpass->name, rpass->name);
/* extra socket info */
sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
sock->storage = sockdata;
@@ -203,8 +205,8 @@ static bNodeSocket *cmp_node_image_output_find_match(bNode *UNUSED(node), bNodeS
{
bNodeSocket *sock;
- for (sock=oldsocklist->first; sock; sock=sock->next)
- if (strcmp(sock->name, newsock->name)==0)
+ for (sock=oldsocklist->first; sock; sock = sock->next)
+ if (STREQ(sock->name, newsock->name))
return sock;
return NULL;
}
@@ -214,8 +216,8 @@ static bNodeSocket *cmp_node_image_output_relink(bNode *node, bNodeSocket *oldso
bNodeSocket *sock;
/* first try to find matching socket name */
- for (sock=node->outputs.first; sock; sock=sock->next)
- if (strcmp(sock->name, oldsock->name)==0)
+ for (sock = node->outputs.first; sock; sock = sock->next)
+ if (STREQ(sock->name, oldsock->name))
return sock;
/* no matching name, simply link to same index */
@@ -241,11 +243,8 @@ static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node)
/* XXX make callback */
cmp_node_image_create_outputs(ntree, node);
- /* flag all new sockets as dynamic, to prevent removal by socket verification function */
- for (newsock=node->outputs.first; newsock; newsock=newsock->next)
- newsock->flag |= SOCK_DYNAMIC;
- for (newsock=node->outputs.first; newsock; newsock=newsock->next) {
+ for (newsock = node->outputs.first; newsock; newsock=newsock->next) {
/* XXX make callback */
oldsock = cmp_node_image_output_find_match(node, newsock, &oldsocklist);
if (oldsock) {
@@ -285,244 +284,7 @@ static void cmp_node_image_update(bNodeTree *ntree, bNode *node)
cmp_node_image_verify_outputs(ntree, node);
}
-#ifdef WITH_COMPOSITOR_LEGACY
-
-/* float buffer from the image with matching color management */
-float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc)
-{
- float *rect;
- int predivide= (ibuf->flags & IB_cm_predivide);
-
- *alloc= FALSE;
-
- /* OCIO_TODO: this is a part of legacy compositor system, don't bother with porting this code
- * to new color management system since this code would likely be simply removed soon
- */
- if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) {
- rect= ibuf->rect_float;
- }
- else {
- rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
-
- IMB_buffer_float_from_float(rect, ibuf->rect_float,
- 4, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide,
- ibuf->x, ibuf->y, ibuf->x, ibuf->x);
-
- *alloc= TRUE;
- }
-
- return rect;
-}
-
-/* note: this function is used for multilayer too, to ensure uniform
- * handling with BKE_image_acquire_ibuf() */
-static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser)
-{
- ImBuf *ibuf;
- CompBuf *stackbuf;
- int type;
-
- float *rect;
- int alloc= FALSE;
-
- ibuf= BKE_image_acquire_ibuf(ima, iuser, NULL);
- if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
- return NULL;
- }
-
- if (ibuf->rect_float == NULL) {
- IMB_float_from_rect(ibuf);
- }
-
- /* now we need a float buffer from the image with matching color management */
- /* XXX weak code, multilayer is excluded from this */
- if (ibuf->channels == 4 && ima->rr==NULL) {
- rect= node_composit_get_float_buffer(rd, ibuf, &alloc);
- }
- else {
- /* non-rgba passes can't use color profiles */
- rect= ibuf->rect_float;
- }
- /* done coercing into the correct color management */
-
-
- type= ibuf->channels;
-
- if (rd->scemode & R_COMP_CROP) {
- stackbuf= get_cropped_compbuf(&rd->disprect, rect, ibuf->x, ibuf->y, type);
- if (alloc)
- MEM_freeN(rect);
- }
- else {
- /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */
- stackbuf= alloc_compbuf(ibuf->x, ibuf->y, type, FALSE);
- stackbuf->rect= rect;
- stackbuf->malloc= alloc;
- }
-
- /* code to respect the premul flag of images; I'm
- * not sure if this is a good idea for multilayer images,
- * since it never worked before for them.
- */
-#if 0
- if (type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
- //premul the image
- int i;
- float *pixel = stackbuf->rect;
-
- for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) {
- pixel[0] *= pixel[3];
- pixel[1] *= pixel[3];
- pixel[2] *= pixel[3];
- }
- }
-#endif
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
-
- return stackbuf;
-}
-
-static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd)
-{
- ImBuf *ibuf= BKE_image_acquire_ibuf((Image *)node->id, node->storage, NULL);
- CompBuf *zbuf= NULL;
-
- if (ibuf && ibuf->zbuf_float) {
- if (rd->scemode & R_COMP_CROP) {
- zbuf= get_cropped_compbuf(&rd->disprect, ibuf->zbuf_float, ibuf->x, ibuf->y, CB_VAL);
- }
- else {
- zbuf= alloc_compbuf(ibuf->x, ibuf->y, CB_VAL, 0);
- zbuf->rect= ibuf->zbuf_float;
- }
- }
-
- BKE_image_release_ibuf((Image *)node->id, ibuf, NULL);
-
- return zbuf;
-}
-
-/* check if layer is available, returns pass buffer */
-static CompBuf *compbuf_multilayer_get(RenderData *rd, RenderLayer *rl, Image *ima, ImageUser *iuser, int passindex)
-{
- RenderPass *rpass = BLI_findlink(&rl->passes, passindex);
- if (rpass) {
- CompBuf *cbuf;
-
- iuser->pass = passindex;
- BKE_image_multilayer_index(ima->rr, iuser);
- cbuf = node_composit_get_image(rd, ima, iuser);
-
- return cbuf;
- }
- return NULL;
-}
-
-static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
-{
- /* image assigned to output */
- /* stack order input sockets: col, alpha */
- if (node->id) {
- RenderData *rd= data;
- Image *ima= (Image *)node->id;
- ImageUser *iuser= (ImageUser *)node->storage;
- ImBuf *ibuf = NULL;
-
- /* first set the right frame number in iuser */
- BKE_image_user_frame_calc(iuser, rd->cfra, 0);
-
- /* force a load, we assume iuser index will be set OK anyway */
- if (ima->type==IMA_TYPE_MULTILAYER)
- ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
-
- if (ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
- RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
-
- if (rl) {
- bNodeSocket *sock;
- NodeImageLayer *sockdata;
- int out_index;
- CompBuf *combinedbuf= NULL, *firstbuf= NULL;
-
- for (sock=node->outputs.first, out_index=0; sock; sock=sock->next, ++out_index) {
- sockdata = sock->storage;
- if (out[out_index]->hasoutput) {
- CompBuf *stackbuf = out[out_index]->data = compbuf_multilayer_get(rd, rl, ima, iuser, sockdata->pass_index);
- if (stackbuf) {
- /* preview policy: take first 'Combined' pass if available,
- * otherwise just use the first layer.
- */
- if (!firstbuf) {
- firstbuf = stackbuf;
- }
- if (!combinedbuf &&
- (strcmp(sock->name, "Combined") == 0 || strcmp(sock->name, "Image") == 0))
- {
- combinedbuf = stackbuf;
- }
- }
- }
- }
-
- /* preview */
- if (combinedbuf)
- generate_preview(data, node, combinedbuf);
- else if (firstbuf)
- generate_preview(data, node, firstbuf);
- }
- }
- else {
- CompBuf *stackbuf = node_composit_get_image(rd, ima, iuser);
- if (stackbuf) {
- int num_outputs = BLI_countlist(&node->outputs);
-
- /*respect image premul option*/
- if (stackbuf->type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
- int i;
- float *pixel;
-
- /* first duplicate stackbuf->rect, since it's just a pointer
- * to the source imbuf, and we don't want to change that.*/
- stackbuf->rect = MEM_dupallocN(stackbuf->rect);
-
- /* since stackbuf now has allocated memory, rather than just a pointer,
- * mark it as allocated so it can be freed properly */
- stackbuf->malloc=1;
-
- /*premul the image*/
- pixel = stackbuf->rect;
- for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) {
- pixel[0] *= pixel[3];
- pixel[1] *= pixel[3];
- pixel[2] *= pixel[3];
- }
- }
-
- /* put image on stack */
- if (num_outputs > 0)
- out[0]->data= stackbuf;
-
- /* alpha output */
- if (num_outputs > 1 && out[1]->hasoutput)
- out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
-
- /* Z output */
- if (num_outputs > 2 && out[2]->hasoutput)
- out[2]->data= node_composit_get_zimage(node, rd);
-
- /* preview */
- generate_preview(data, node, stackbuf);
- }
- }
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_image(bNodeTree *ntree, bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_image(bNodeTree *ntree, bNode *node)
{
ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
node->storage= iuser;
@@ -540,187 +302,63 @@ static void node_composit_free_image(bNode *node)
bNodeSocket *sock;
/* free extra socket info */
- for (sock=node->outputs.first; sock; sock=sock->next)
+ for (sock = node->outputs.first; sock; sock = sock->next)
MEM_freeN(sock->storage);
MEM_freeN(node->storage);
}
-static void node_composit_copy_image(bNode *orig_node, bNode *new_node)
+static void node_composit_copy_image(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node)
{
bNodeSocket *sock;
- new_node->storage= MEM_dupallocN(orig_node->storage);
+ dest_node->storage= MEM_dupallocN(src_node->storage);
/* copy extra socket info */
- for (sock=orig_node->outputs.first; sock; sock=sock->next)
+ for (sock=src_node->outputs.first; sock; sock = sock->next)
sock->new_sock->storage = MEM_dupallocN(sock->storage);
}
-void register_node_type_cmp_image(bNodeTreeType *ttype)
+void register_node_type_cmp_image(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
- node_type_size(&ntype, 120, 80, 300);
+ cmp_node_type_base(&ntype, CMP_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
node_type_init(&ntype, node_composit_init_image);
node_type_storage(&ntype, "ImageUser", node_composit_free_image, node_composit_copy_image);
node_type_update(&ntype, cmp_node_image_update, NULL);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_image);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
/* **************** RENDER RESULT ******************** */
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, int recty, int passcode)
+static int node_composit_poll_rlayers(bNodeType *UNUSED(ntype), bNodeTree *ntree)
{
- float *fp= RE_RenderLayerGetPass(rl, passcode);
- if (fp) {
- CompBuf *buf;
- int buftype= CB_VEC3;
-
- if (ELEM4(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB, SCE_PASS_MIST, SCE_PASS_INDEXMA))
- buftype= CB_VAL;
- else if (passcode==SCE_PASS_VECTOR)
- buftype= CB_VEC4;
- else if (ELEM(passcode, SCE_PASS_COMBINED, SCE_PASS_RGBA))
- buftype= CB_RGBA;
-
- if (rd->scemode & R_COMP_CROP)
- buf= get_cropped_compbuf(&rd->disprect, fp, rectx, recty, buftype);
- else {
- buf= alloc_compbuf(rectx, recty, buftype, 0);
- buf->rect= fp;
- }
- return buf;
- }
- return NULL;
-}
-
-static void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out, int rectx, int recty)
-{
- if (out[RRES_OUT_Z]->hasoutput)
- out[RRES_OUT_Z]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_Z);
- if (out[RRES_OUT_VEC]->hasoutput)
- out[RRES_OUT_VEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_VECTOR);
- if (out[RRES_OUT_NORMAL]->hasoutput)
- out[RRES_OUT_NORMAL]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_NORMAL);
- if (out[RRES_OUT_UV]->hasoutput)
- out[RRES_OUT_UV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_UV);
-
- if (out[RRES_OUT_RGBA]->hasoutput)
- out[RRES_OUT_RGBA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RGBA);
- if (out[RRES_OUT_DIFF]->hasoutput)
- out[RRES_OUT_DIFF]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE);
- if (out[RRES_OUT_SPEC]->hasoutput)
- out[RRES_OUT_SPEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SPEC);
- if (out[RRES_OUT_SHADOW]->hasoutput)
- out[RRES_OUT_SHADOW]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SHADOW);
- if (out[RRES_OUT_AO]->hasoutput)
- out[RRES_OUT_AO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_AO);
- if (out[RRES_OUT_REFLECT]->hasoutput)
- out[RRES_OUT_REFLECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFLECT);
- if (out[RRES_OUT_REFRACT]->hasoutput)
- out[RRES_OUT_REFRACT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFRACT);
- if (out[RRES_OUT_INDIRECT]->hasoutput)
- out[RRES_OUT_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDIRECT);
- if (out[RRES_OUT_INDEXOB]->hasoutput)
- out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB);
- if (out[RRES_OUT_INDEXMA]->hasoutput)
- out[RRES_OUT_INDEXMA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXMA);
- if (out[RRES_OUT_MIST]->hasoutput)
- out[RRES_OUT_MIST]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_MIST);
- if (out[RRES_OUT_EMIT]->hasoutput)
- out[RRES_OUT_EMIT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_EMIT);
- if (out[RRES_OUT_ENV]->hasoutput)
- out[RRES_OUT_ENV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_ENVIRONMENT);
- if (out[RRES_OUT_DIFF_DIRECT]->hasoutput)
- out[RRES_OUT_DIFF_DIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE_DIRECT);
- if (out[RRES_OUT_DIFF_INDIRECT]->hasoutput)
- out[RRES_OUT_DIFF_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE_INDIRECT);
- if (out[RRES_OUT_DIFF_COLOR]->hasoutput)
- out[RRES_OUT_DIFF_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE_COLOR);
- if (out[RRES_OUT_GLOSSY_DIRECT]->hasoutput)
- out[RRES_OUT_GLOSSY_DIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_GLOSSY_DIRECT);
- if (out[RRES_OUT_GLOSSY_INDIRECT]->hasoutput)
- out[RRES_OUT_GLOSSY_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_GLOSSY_INDIRECT);
- if (out[RRES_OUT_GLOSSY_COLOR]->hasoutput)
- out[RRES_OUT_GLOSSY_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_GLOSSY_COLOR);
- if (out[RRES_OUT_TRANSM_DIRECT]->hasoutput)
- out[RRES_OUT_TRANSM_DIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_DIRECT);
- if (out[RRES_OUT_TRANSM_INDIRECT]->hasoutput)
- out[RRES_OUT_TRANSM_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_INDIRECT);
- if (out[RRES_OUT_TRANSM_COLOR]->hasoutput)
- out[RRES_OUT_TRANSM_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_COLOR);
-}
-
-static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
-{
- Scene *sce= (Scene *)node->id;
- Render *re= (sce)? RE_GetRender(sce->id.name): NULL;
- RenderData *rd= data;
- RenderResult *rr= NULL;
-
- if (re)
- rr= RE_AcquireResultRead(re);
-
- if (rr) {
- SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
- if (srl) {
- RenderLayer *rl= RE_GetRenderLayer(rr, srl->name);
- if (rl && rl->rectf) {
- CompBuf *stackbuf;
-
- /* we put render rect on stack, cbuf knows rect is from other ibuf when freed! */
- if (rd->scemode & R_COMP_CROP)
- stackbuf= get_cropped_compbuf(&rd->disprect, rl->rectf, rr->rectx, rr->recty, CB_RGBA);
- else {
- stackbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 0);
- stackbuf->rect= rl->rectf;
- }
- if (stackbuf==NULL) {
- printf("Error; Preview Panel in UV Window returns zero sized image\n");
- }
- else {
- stackbuf->xof= rr->xof;
- stackbuf->yof= rr->yof;
-
- /* put on stack */
- out[RRES_OUT_IMAGE]->data= stackbuf;
-
- if (out[RRES_OUT_ALPHA]->hasoutput)
- out[RRES_OUT_ALPHA]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
-
- node_composit_rlayers_out(rd, rl, out, rr->rectx, rr->recty);
-
- generate_preview(data, node, stackbuf);
- }
- }
- }
+ if (strcmp(ntree->idname, "CompositorNodeTree")==0) {
+ Scene *scene;
+
+ /* XXX ugly: check if ntree is a local scene node tree.
+ * Render layers node can only be used in local scene->nodetree,
+ * since it directly links to the scene.
+ */
+ for (scene = G.main->scene.first; scene; scene = scene->id.next)
+ if (scene->nodetree == ntree)
+ break;
+
+ return (scene != NULL);
}
-
- if (re)
- RE_ReleaseResult(re);
+ return false;
}
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_rlayers(bNodeTreeType *ttype)
+void register_node_type_cmp_rlayers(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_R_LAYERS, "Render Layers", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_R_LAYERS, "Render Layers", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out);
- node_type_size(&ntype, 150, 100, 300);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_rlayers);
-#endif
+ ntype.poll = node_composit_poll_rlayers;
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_inpaint.c b/source/blender/nodes/composite/nodes/node_composite_inpaint.c
index 25ecf428b4a..83517d07b69 100644
--- a/source/blender/nodes/composite/nodes/node_composite_inpaint.c
+++ b/source/blender/nodes/composite/nodes/node_composite_inpaint.c
@@ -44,25 +44,12 @@ static bNodeSocketTemplate cmp_node_inpaint_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void node_composit_exec_inpaint(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **UNUSED(in), bNodeStack **UNUSED(out))
-{
- /* pass */
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_inpaint(bNodeTreeType *ttype)
+void register_node_type_cmp_inpaint(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_INPAINT, "Inpaint", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_INPAINT, "Inpaint", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_inpaint_in, cmp_node_inpaint_out);
- node_type_size(&ntype, 130, 100, 320);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_inpaint);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_invert.c b/source/blender/nodes/composite/nodes/node_composite_invert.c
index 2db6e42f603..6a3da2c854b 100644
--- a/source/blender/nodes/composite/nodes/node_composite_invert.c
+++ b/source/blender/nodes/composite/nodes/node_composite_invert.c
@@ -43,99 +43,19 @@ static bNodeSocketTemplate cmp_node_invert_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_invert(bNode *node, float *out, float *in)
-{
- if (node->custom1 & CMP_CHAN_RGB) {
- out[0] = 1.0f - in[0];
- out[1] = 1.0f - in[1];
- out[2] = 1.0f - in[2];
- }
- else {
- copy_v3_v3(out, in);
- }
-
- if (node->custom1 & CMP_CHAN_A)
- out[3] = 1.0f - in[3];
- else
- out[3] = in[3];
-}
-
-static void do_invert_fac(bNode *node, float *out, float *in, float *fac)
-{
- float col[4], facm;
-
- do_invert(node, col, in);
-
- /* blend inverted result against original input with fac */
- facm = 1.0f - fac[0];
-
- if (node->custom1 & CMP_CHAN_RGB) {
- col[0] = fac[0]*col[0] + (facm*in[0]);
- col[1] = fac[0]*col[1] + (facm*in[1]);
- col[2] = fac[0]*col[2] + (facm*in[2]);
- }
- if (node->custom1 & CMP_CHAN_A)
- col[3] = fac[0]*col[3] + (facm*in[3]);
-
- copy_v4_v4(out, col);
-}
-
-static void node_composit_exec_invert(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order in: fac, Image, Image */
- /* stack order out: Image */
- float *fac= in[0]->vec;
-
- if (out[0]->hasoutput==0) return;
-
- /* input no image? then only color operation */
- if (in[1]->data==NULL && in[0]->data==NULL) {
- do_invert_fac(node, out[0]->vec, in[1]->vec, fac);
- }
- else {
- /* make output size of first available input image, or then size of fac */
- CompBuf *cbuf= in[1]->data?in[1]->data:in[0]->data;
-
- /* if neither RGB or A toggled on, pass through */
- if (node->custom1 != 0) {
- CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
-
- if (fac[0] < 1.0f || in[0]->data!=NULL)
- composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, fac, do_invert_fac, CB_RGBA, CB_VAL);
- else
- composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_invert, CB_RGBA);
- out[0]->data= stackbuf;
- return;
-
- }
- else {
- out[0]->data = pass_on_compbuf(cbuf);
- return;
- }
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_invert(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_invert(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom1 |= CMP_CHAN_RGB;
}
/* custom1 = mix type */
-void register_node_type_cmp_invert(bNodeTreeType *ttype)
+void register_node_type_cmp_invert(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_invert_in, cmp_node_invert_out);
- node_type_size(&ntype, 120, 120, 140);
node_type_init(&ntype, node_composit_init_invert);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_invert);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_keying.c b/source/blender/nodes/composite/nodes/node_composite_keying.c
index 6553df350ff..464df4d72ab 100644
--- a/source/blender/nodes/composite/nodes/node_composite_keying.c
+++ b/source/blender/nodes/composite/nodes/node_composite_keying.c
@@ -60,14 +60,7 @@ static bNodeSocketTemplate cmp_node_keying_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-static void node_composit_exec_keying(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **UNUSED(in), bNodeStack **UNUSED(out))
-{
- /* pass */
-}
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_keying(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_keying(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeKeyingData *data;
@@ -85,18 +78,14 @@ static void node_composit_init_keying(bNodeTree *UNUSED(ntree), bNode *node, bNo
node->storage = data;
}
-void register_node_type_cmp_keying(bNodeTreeType *ttype)
+void register_node_type_cmp_keying(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_KEYING, "Keying", NODE_CLASS_MATTE, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_KEYING, "Keying", NODE_CLASS_MATTE, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_keying_in, cmp_node_keying_out);
- node_type_size(&ntype, 140, 100, 320);
node_type_init(&ntype, node_composit_init_keying);
node_type_storage(&ntype, "NodeKeyingData", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_keying);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c
index 96e905827cb..b593196d815 100644
--- a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c
+++ b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c
@@ -50,141 +50,7 @@ static bNodeSocketTemplate cmp_node_keyingscreen_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void compute_gradient_screen(RenderData *rd, NodeKeyingScreenData *keyingscreen_data, MovieClip *clip, CompBuf *screenbuf)
-{
- MovieClipUser user = {0};
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingTrack *track;
- VoronoiTriangulationPoint *triangulated_points;
- VoronoiSite *sites;
- ImBuf *ibuf;
- ListBase *tracksbase;
- ListBase edges = {NULL, NULL};
- int sites_total, triangulated_points_total, triangles_total;
- int (*triangles)[3];
- int i, x, y;
- float *rect = screenbuf->rect;
-
- if (keyingscreen_data->tracking_object[0]) {
- MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, keyingscreen_data->tracking_object);
-
- if (!object)
- return;
-
- tracksbase = BKE_tracking_object_get_tracks(tracking, object);
- }
- else
- tracksbase = BKE_tracking_get_active_tracks(tracking);
-
- sites_total = BLI_countlist(tracksbase);
-
- if (!sites_total)
- return;
-
- BKE_movieclip_user_set_frame(&user, rd->cfra);
- ibuf = BKE_movieclip_get_ibuf(clip, &user);
-
- sites = MEM_callocN(sizeof(VoronoiSite) * sites_total, "keyingscreen voronoi sites");
- track = tracksbase->first;
- i = 0;
- while (track) {
- VoronoiSite *site = &sites[i];
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, rd->cfra);
- ImBuf *pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, TRUE, FALSE);
- int j;
-
- zero_v3(site->color);
-
- if (pattern_ibuf) {
- for (j = 0; j < pattern_ibuf->x * pattern_ibuf->y; j++) {
- if (pattern_ibuf->rect_float) {
- add_v3_v3(site->color, &pattern_ibuf->rect_float[4 * j]);
- }
- else {
- unsigned char *rrgb = (unsigned char *)pattern_ibuf->rect;
-
- site->color[0] += srgb_to_linearrgb((float)rrgb[4 * j + 0] / 255.0f);
- site->color[1] += srgb_to_linearrgb((float)rrgb[4 * j + 1] / 255.0f);
- site->color[2] += srgb_to_linearrgb((float)rrgb[4 * j + 2] / 255.0f);
- }
- }
-
- mul_v3_fl(site->color, 1.0f / (pattern_ibuf->x * pattern_ibuf->y));
- IMB_freeImBuf(pattern_ibuf);
- }
-
- site->co[0] = marker->pos[0] * screenbuf->x;
- site->co[1] = marker->pos[1] * screenbuf->y;
-
- track = track->next;
- i++;
- }
-
- IMB_freeImBuf(ibuf);
-
- BLI_voronoi_compute(sites, sites_total, screenbuf->x, screenbuf->y, &edges);
-
- BLI_voronoi_triangulate(sites, sites_total, &edges, screenbuf->x, screenbuf->y,
- &triangulated_points, &triangulated_points_total,
- &triangles, &triangles_total);
-
- for (y = 0; y < screenbuf->y; y++) {
- for (x = 0; x < screenbuf->x; x++) {
- int index = 4 * (y * screenbuf->x + x);
-
- rect[index + 0] = rect[index + 1] = rect[index + 2] = 0.0f;
- rect[index + 3] = 1.0f;
-
- for (i = 0; i < triangles_total; i++) {
- int *triangle = triangles[i];
- VoronoiTriangulationPoint *a = &triangulated_points[triangle[0]],
- *b = &triangulated_points[triangle[1]],
- *c = &triangulated_points[triangle[2]];
- float co[2] = {x, y}, w[3];
-
- if (barycentric_coords_v2(a->co, b->co, c->co, co, w)) {
- if (barycentric_inside_triangle_v2(w)) {
- rect[index + 0] += a->color[0] * w[0] + b->color[0] * w[1] + c->color[0] * w[2];
- rect[index + 1] += a->color[1] * w[0] + b->color[1] * w[1] + c->color[1] * w[2];
- rect[index + 2] += a->color[2] * w[0] + b->color[2] * w[1] + c->color[2] * w[2];
- }
- }
- }
- }
- }
-
- MEM_freeN(triangulated_points);
- MEM_freeN(triangles);
- MEM_freeN(sites);
- BLI_freelistN(&edges);
-}
-
-static void node_composit_exec_keyingscreen(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
-{
- NodeKeyingScreenData *keyingscreen_data = node->storage;
- RenderData *rd = data;
- CompBuf *screenbuf = NULL;
-
- if (node->id) {
- MovieClip *clip = (MovieClip *) node->id;
- MovieClipUser user = {0};
- int width, height;
-
- BKE_movieclip_user_set_frame(&user, rd->cfra);
- BKE_movieclip_get_size(clip, &user, &width, &height);
-
- screenbuf = alloc_compbuf(width, height, CB_RGBA, TRUE);
- compute_gradient_screen(rd, keyingscreen_data, clip, screenbuf);
- }
-
- out[0]->data = screenbuf;
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_keyingscreen(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_keyingscreen(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeKeyingScreenData *data;
@@ -193,18 +59,14 @@ static void node_composit_init_keyingscreen(bNodeTree *UNUSED(ntree), bNode *nod
node->storage = data;
}
-void register_node_type_cmp_keyingscreen(bNodeTreeType *ttype)
+void register_node_type_cmp_keyingscreen(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_KEYINGSCREEN, "Keying Screen", NODE_CLASS_MATTE, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_KEYINGSCREEN, "Keying Screen", NODE_CLASS_MATTE, NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, cmp_node_keyingscreen_out);
- node_type_size(&ntype, 140, 100, 320);
node_type_init(&ntype, node_composit_init_keyingscreen);
node_type_storage(&ntype, "NodeKeyingScreenData", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_keyingscreen);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_lensdist.c b/source/blender/nodes/composite/nodes/node_composite_lensdist.c
index c3f64f0eacb..c093d563363 100644
--- a/source/blender/nodes/composite/nodes/node_composite_lensdist.c
+++ b/source/blender/nodes/composite/nodes/node_composite_lensdist.c
@@ -43,150 +43,7 @@ static bNodeSocketTemplate cmp_node_lensdist_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-/* assumes *dst is type RGBA */
-static void lensDistort(CompBuf *dst, CompBuf *src, float kr, float kg, float kb, int jit, int proj, int fit)
-{
- int x, y, z;
- const float cx = 0.5f*(float)dst->x, cy = 0.5f*(float)dst->y;
-
- if (proj) {
- // shift
- CompBuf *tsrc = dupalloc_compbuf(src);
-
- for (z=0; z<tsrc->type; ++z)
- IIR_gauss(tsrc, (kr+0.5f)*(kr+0.5f), z, 1);
- kr *= 20.f;
-
- for (y=0; y<dst->y; y++) {
- fRGB *colp = (fRGB*)&dst->rect[y*dst->x*dst->type];
- const float v = (y + 0.5f)/(float)dst->y;
-
- for (x=0; x<dst->x; x++) {
- const float u = (x + 0.5f)/(float)dst->x;
-
- qd_getPixelLerpChan(tsrc, (u*dst->x + kr) - 0.5f, v*dst->y - 0.5f, 0, colp[x]);
- if (tsrc->type == CB_VAL)
- colp[x][1] = tsrc->rect[x + y*tsrc->x];
- else
- colp[x][1] = tsrc->rect[(x + y*tsrc->x)*tsrc->type + 1];
- qd_getPixelLerpChan(tsrc, (u*dst->x - kr) - 0.5f, v*dst->y - 0.5f, 2, colp[x]+2);
-
- /* set alpha */
- colp[x][3] = 1.0f;
- }
- }
- free_compbuf(tsrc);
- }
- else {
- // Spherical
- // Scale factor to make bottom/top & right/left sides fit in window after deform
- // so in the case of pincushion (kn < 0), corners will be outside window.
- // Now also optionally scales image such that black areas are not visible when distort factor is positive
- // (makes distorted corners match window corners, but really only valid if mk<=0.5)
- const float mk = MAX3(kr, kg, kb);
- const float sc = (fit && (mk > 0.f)) ? (1.f/(1.f + 2.f*mk)) : (1.f/(1.f + mk));
- const float drg = 4.f*(kg - kr), dgb = 4.f*(kb - kg);
-
- kr *= 4.f, kg *= 4.f, kb *= 4.f;
-
- for (y=0; y<dst->y; y++) {
- fRGB *colp = (fRGB*)&dst->rect[y*dst->x*dst->type];
- const float v = sc*((y + 0.5f) - cy)/cy;
-
- for (x=0; x<dst->x; x++) {
- int dr = 0, dg = 0, db = 0;
- float d, t, ln[6] = {0, 0, 0, 0, 0, 0};
- fRGB c1, tc = {0, 0, 0, 0};
- const float u = sc*((x + 0.5f) - cx)/cx;
- const float uv_dot = u * u + v * v;
- int sta = 0, mid = 0, end = 0;
-
- if ((t = 1.f - kr*uv_dot) >= 0.f) {
- d = 1.f/(1.f + sqrtf(t));
- ln[0] = (u*d + 0.5f)*dst->x - 0.5f, ln[1] = (v*d + 0.5f)*dst->y - 0.5f;
- sta = 1;
- }
- if ((t = 1.f - kg*uv_dot) >= 0.f) {
- d = 1.f/(1.f + sqrtf(t));
- ln[2] = (u*d + 0.5f)*dst->x - 0.5f, ln[3] = (v*d + 0.5f)*dst->y - 0.5f;
- mid = 1;
- }
- if ((t = 1.f - kb*uv_dot) >= 0.f) {
- d = 1.f/(1.f + sqrtf(t));
- ln[4] = (u*d + 0.5f)*dst->x - 0.5f, ln[5] = (v*d + 0.5f)*dst->y - 0.5f;
- end = 1;
- }
-
- if (sta && mid && end) {
- // RG
- const int dx = ln[2] - ln[0], dy = ln[3] - ln[1];
- const float dsf = sqrtf(dx*dx + dy*dy) + 1.f;
- const int ds = (int)(jit ? ((dsf < 4.f) ? 2.f : sqrtf(dsf)) : dsf);
- const float sd = 1.f/(float)ds;
-
- for (z=0; z<ds; ++z) {
- const float tz = ((float)z + (jit ? BLI_frand() : 0.5f))*sd;
- t = 1.f - (kr + tz*drg)*uv_dot;
- d = 1.f / (1.f + sqrtf(t));
- qd_getPixelLerp(src, (u*d + 0.5f)*dst->x - 0.5f, (v*d + 0.5f)*dst->y - 0.5f, c1);
- if (src->type == CB_VAL) c1[1] = c1[2] = c1[0];
- tc[0] += (1.f-tz)*c1[0], tc[1] += tz*c1[1];
- dr++, dg++;
- }
- // GB
- {
- const int dx = ln[4] - ln[2], dy = ln[5] - ln[3];
- const float dsf = sqrtf(dx*dx + dy*dy) + 1.f;
- const int ds = (int)(jit ? ((dsf < 4.f) ? 2.f : sqrtf(dsf)) : dsf);
- const float sd = 1.f/(float)ds;
-
- for (z=0; z<ds; ++z) {
- const float tz = ((float)z + (jit ? BLI_frand() : 0.5f))*sd;
- t = 1.f - (kg + tz*dgb)*uv_dot;
- d = 1.f / (1.f + sqrtf(t));
- qd_getPixelLerp(src, (u*d + 0.5f)*dst->x - 0.5f, (v*d + 0.5f)*dst->y - 0.5f, c1);
- if (src->type == CB_VAL) c1[1] = c1[2] = c1[0];
- tc[1] += (1.f-tz)*c1[1], tc[2] += tz*c1[2];
- dg++, db++;
- }
- }
- }
-
- if (dr) colp[x][0] = 2.f*tc[0] / (float)dr;
- if (dg) colp[x][1] = 2.f*tc[1] / (float)dg;
- if (db) colp[x][2] = 2.f*tc[2] / (float)db;
-
- /* set alpha */
- colp[x][3] = 1.0f;
- }
- }
- }
-}
-
-
-static void node_composit_exec_lensdist(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- CompBuf *new, *img = in[0]->data;
- NodeLensDist *nld = node->storage;
- const float k = MAX2(MIN2(in[1]->vec[0], 1.f), -0.999f);
- // smaller dispersion range for somewhat more control
- const float d = 0.25f*MAX2(MIN2(in[2]->vec[0], 1.f), 0.f);
- const float kr = MAX2(MIN2((k+d), 1.f), -0.999f), kb = MAX2(MIN2((k-d), 1.f), -0.999f);
-
- if ((img==NULL) || (out[0]->hasoutput==0)) return;
-
- new = alloc_compbuf(img->x, img->y, CB_RGBA, 1);
-
- lensDistort(new, img, (nld->proj ? d : kr), k, kb, nld->jit, nld->proj, nld->fit);
-
- out[0]->data = new;
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_lensdist(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_lensdist(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeLensDist *nld = MEM_callocN(sizeof(NodeLensDist), "node lensdist data");
nld->jit = nld->proj = nld->fit = 0;
@@ -194,18 +51,14 @@ static void node_composit_init_lensdist(bNodeTree *UNUSED(ntree), bNode *node, b
}
-void register_node_type_cmp_lensdist(bNodeTreeType *ttype)
+void register_node_type_cmp_lensdist(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_LENSDIST, "Lens Distortion", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_LENSDIST, "Lens Distortion", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_lensdist_in, cmp_node_lensdist_out);
- node_type_size(&ntype, 150, 120, 200);
node_type_init(&ntype, node_composit_init_lensdist);
node_type_storage(&ntype, "NodeLensDist", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_lensdist);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_levels.c b/source/blender/nodes/composite/nodes/node_composite_levels.c
index 57d94d6cb4d..e2b3895a96f 100644
--- a/source/blender/nodes/composite/nodes/node_composite_levels.c
+++ b/source/blender/nodes/composite/nodes/node_composite_levels.c
@@ -45,291 +45,19 @@ static bNodeSocketTemplate cmp_node_view_levels_out[] = {
{-1, 0, ""}
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void fill_bins(bNode *node, CompBuf* in, int* bins)
-{
- float value[4];
- int ivalue=0;
- int x, y;
-
- /*fill bins */
- for (y=0; y<in->y; y++) {
- for (x=0; x<in->x; x++) {
-
- /* get the pixel */
- qd_getPixel(in, x, y, value);
-
- if (value[3] > 0.0f) { /* don't count transparent pixels */
- switch (node->custom1) {
- case 1: { /* all colors */
- value[0] = rgb_to_bw(value);
- value[0]=value[0]*255; /* scale to 0-255 range */
- ivalue=(int)value[0];
- break;
- }
- case 2: { /* red channel */
- value[0]=value[0]*255; /* scale to 0-255 range */
- ivalue=(int)value[0];
- break;
- }
- case 3: { /* green channel */
- value[1]=value[1]*255; /* scale to 0-255 range */
- ivalue=(int)value[1];
- break;
- }
- case 4: /*blue channel */
- {
- value[2]=value[2]*255; /* scale to 0-255 range */
- ivalue=(int)value[2];
- break;
- }
- case 5: /* luminence */
- {
- rgb_to_yuv(value[0], value[1], value[2], &value[0], &value[1], &value[2]);
- value[0]=value[0]*255; /* scale to 0-255 range */
- ivalue=(int)value[0];
- break;
- }
- } /*end switch */
-
- /*clip*/
- if (ivalue<0) ivalue=0;
- if (ivalue>255) ivalue=255;
-
- /*put in the correct bin*/
- bins[ivalue]+=1;
- } /*end if alpha */
- }
- }
-}
-
-static float brightness_mean(bNode *node, CompBuf* in)
-{
- float sum=0.0;
- int numPixels=0.0;
- int x, y;
- float value[4];
-
- for (x=0; x< in->x; x++) {
- for (y=0; y < in->y; y++) {
-
- /* get the pixel */
- qd_getPixel(in, x, y, value);
-
- if (value[3] > 0.0f) { /* don't count transparent pixels */
- numPixels++;
- switch (node->custom1) {
- case 1:
- {
- value[0] = rgb_to_bw(value);
- sum+=value[0];
- break;
- }
- case 2:
- {
- sum+=value[0];
- break;
- }
- case 3:
- {
- sum+=value[1];
- break;
- }
- case 4:
- {
- sum+=value[2];
- break;
- }
- case 5:
- {
- rgb_to_yuv(value[0], value[1], value[2], &value[0], &value[1], &value[2]);
- sum+=value[0];
- break;
- }
- }
- }
- }
- }
-
- return sum/numPixels;
-}
-
-static float brightness_standard_deviation(bNode *node, CompBuf* in, float mean)
-{
- float sum=0.0;
- int numPixels=0.0;
- int x, y;
- float value[4];
-
- for (x=0; x< in->x; x++) {
- for (y=0; y < in->y; y++) {
-
- /* get the pixel */
- qd_getPixel(in, x, y, value);
-
- if (value[3] > 0.0f) { /* don't count transparent pixels */
- numPixels++;
- switch (node->custom1) {
- case 1:
- {
- value[0] = rgb_to_bw(value);
- sum+=(value[0]-mean)*(value[0]-mean);
- break;
- }
- case 2:
- {
- sum+=value[0];
- sum+=(value[0]-mean)*(value[0]-mean);
- break;
- }
- case 3:
- {
- sum+=value[1];
- sum+=(value[1]-mean)*(value[1]-mean);
- break;
- }
- case 4:
- {
- sum+=value[2];
- sum+=(value[2]-mean)*(value[2]-mean);
- break;
- }
- case 5:
- {
- rgb_to_yuv(value[0], value[1], value[2], &value[0], &value[1], &value[2]);
- sum+=(value[0]-mean)*(value[0]-mean);
- break;
- }
- }
- }
- }
- }
-
-
- return sqrt(sum/(float)(numPixels-1));
-}
-
-static void draw_histogram(bNode *node, CompBuf *out, int* bins)
-{
- int x, y;
- float color[4];
- float value;
- int max;
-
- /* find max value */
- max=0;
- for (x=0; x<256; x++) {
- if (bins[x]>max) max=bins[x];
- }
-
- /*draw histogram in buffer */
- for (x=0; x<out->x; x++) {
- for (y=0;y<out->y; y++) {
-
- /* get normalized value (0..255) */
- value=((float)bins[x]/(float)max)*255.0f;
-
- if (y < (int)value) { /*if the y value is below the height of the bar for this line then draw with the color */
- switch (node->custom1) {
- case 1: { /* draw in black */
- color[0]=0.0; color[1]=0.0; color[2]=0.0; color[3]=1.0;
- break;
- }
- case 2: { /* draw in red */
- color[0]=1.0; color[1]=0.0; color[2]=0.0; color[3]=1.0;
- break;
- }
- case 3: { /* draw in green */
- color[0]=0.0; color[1]=1.0; color[2]=0.0; color[3]=1.0;
- break;
- }
- case 4: { /* draw in blue */
- color[0]=0.0; color[1]=0.0; color[2]=1.0; color[3]=1.0;
- break;
- }
- case 5: { /* draw in white */
- color[0]=1.0; color[1]=1.0; color[2]=1.0; color[3]=1.0;
- break;
- }
- }
- }
- else {
- color[0]=0.8; color[1]=0.8; color[2]=0.8; color[3]=1.0;
- }
-
- /* set the color */
- qd_setPixel(out, x, y, color);
- }
- }
-}
-
-static void node_composit_exec_view_levels(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
-{
- CompBuf* cbuf;
- CompBuf* histogram;
- float mean, std_dev;
- int bins[256];
- int x;
-
- if (in[0]->hasinput==0) return;
- if (in[0]->data==NULL) return;
-
- histogram=alloc_compbuf(256, 256, CB_RGBA, 1);
- cbuf=typecheck_compbuf(in[0]->data, CB_RGBA);
-
- /*initalize bins*/
- for (x=0; x<256; x++) {
- bins[x]=0;
- }
-
- /*fill bins */
- fill_bins(node, in[0]->data, bins);
-
- /* draw the histogram chart */
- draw_histogram(node, histogram, bins);
-
- /* calculate the average brightness and contrast */
- mean=brightness_mean(node, in[0]->data);
- std_dev=brightness_standard_deviation(node, in[0]->data, mean);
-
- /* Printf debuging ;) */
-#if 0
- printf("Mean: %f\n", mean);
- printf("Std Dev: %f\n", std_dev);
-#endif
-
- if (out[0]->hasoutput)
- out[0]->vec[0] = mean;
- if (out[1]->hasoutput)
- out[1]->vec[0] = std_dev;
-
- generate_preview(data, node, histogram);
-
- if (cbuf!=in[0]->data)
- free_compbuf(cbuf);
- free_compbuf(histogram);
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_view_levels(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_view_levels(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom1=1; /*All channels*/
}
-void register_node_type_cmp_view_levels(bNodeTreeType *ttype)
+void register_node_type_cmp_view_levels(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_VIEW_LEVELS, "Levels", NODE_CLASS_OUTPUT, NODE_OPTIONS|NODE_PREVIEW);
+ cmp_node_type_base(&ntype, CMP_NODE_VIEW_LEVELS, "Levels", NODE_CLASS_OUTPUT, NODE_OPTIONS|NODE_PREVIEW);
node_type_socket_templates(&ntype, cmp_node_view_levels_in, cmp_node_view_levels_out);
- node_type_size(&ntype, 140, 100, 320);
node_type_init(&ntype, node_composit_init_view_levels);
node_type_storage(&ntype, "ImageUser", NULL, NULL);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_view_levels);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c b/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c
index ed232933139..606c95b495d 100644
--- a/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c
+++ b/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c
@@ -45,62 +45,7 @@ static bNodeSocketTemplate cmp_node_luma_matte_out[] = {
{-1, 0, ""}
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_luma_matte(bNode *node, float *out, float *in)
-{
- NodeChroma *c=(NodeChroma *)node->storage;
- float alpha;
-
- /* test range*/
- if (in[0]>c->t1) {
- alpha=1.0;
- }
- else if (in[0]<c->t2) {
- alpha=0.0;
- }
- else {/*blend */
- alpha=(in[0]-c->t2)/(c->t1-c->t2);
- }
-
- /* don't make something that was more transparent less transparent */
- if (alpha<in[3]) {
- out[3]=alpha;
- }
- else {
- out[3]=in[3];
- }
-
-}
-
-static void node_composit_exec_luma_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
-{
- CompBuf *cbuf;
- CompBuf *outbuf;
-
- if (in[0]->hasinput==0) return;
- if (in[0]->data==NULL) return;
- if (out[0]->hasoutput==0 && out[1]->hasoutput==0) return;
-
- cbuf=typecheck_compbuf(in[0]->data, CB_RGBA);
-
- outbuf=dupalloc_compbuf(cbuf);
-
- composit1_pixel_processor(node, outbuf, cbuf, in[1]->vec, do_rgba_to_yuva, CB_RGBA);
- composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_luma_matte, CB_RGBA);
- composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_yuva_to_rgba, CB_RGBA);
-
- generate_preview(data, node, outbuf);
- out[0]->data=outbuf;
- if (out[1]->hasoutput)
- out[1]->data=valbuf_from_rgbabuf(outbuf, CHAN_A);
- if (cbuf!=in[0]->data)
- free_compbuf(cbuf);
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_luma_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_luma_matte(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
node->storage=c;
@@ -108,18 +53,14 @@ static void node_composit_init_luma_matte(bNodeTree *UNUSED(ntree), bNode *node,
c->t2= 0.0f;
}
-void register_node_type_cmp_luma_matte(bNodeTreeType *ttype)
+void register_node_type_cmp_luma_matte(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_LUMA_MATTE, "Luminance Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_LUMA_MATTE, "Luminance Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_luma_matte_in, cmp_node_luma_matte_out);
- node_type_size(&ntype, 200, 80, 250);
node_type_init(&ntype, node_composit_init_luma_matte);
node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_luma_matte);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_mapRange.c b/source/blender/nodes/composite/nodes/node_composite_mapRange.c
index f96e133b19f..74c36a3e25a 100644
--- a/source/blender/nodes/composite/nodes/node_composite_mapRange.c
+++ b/source/blender/nodes/composite/nodes/node_composite_mapRange.c
@@ -46,13 +46,12 @@ static bNodeSocketTemplate cmp_node_map_range_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_map_range(bNodeTreeType *ttype)
+void register_node_type_cmp_map_range(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MAP_RANGE, "Map Range", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MAP_RANGE, "Map Range", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_map_range_in, cmp_node_map_range_out);
- node_type_size(&ntype, 120, 60, 150);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_mapUV.c b/source/blender/nodes/composite/nodes/node_composite_mapUV.c
index 40092a84367..0d2c53f241c 100644
--- a/source/blender/nodes/composite/nodes/node_composite_mapUV.c
+++ b/source/blender/nodes/composite/nodes/node_composite_mapUV.c
@@ -44,138 +44,12 @@ static bNodeSocketTemplate cmp_node_mapuv_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-/* foreach UV, use these values to read in cbuf and write to stackbuf */
-/* stackbuf should be zeroed */
-static void do_mapuv(CompBuf *stackbuf, CompBuf *cbuf, CompBuf *uvbuf, float threshold)
-{
- ImBuf *ibuf;
- float *out= stackbuf->rect, *uv, *uvnext, *uvprev;
- float dx, dy, alpha;
- int x, y, sx, sy, row= 3*stackbuf->x;
-
- /* ibuf needed for sampling */
- ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0);
- ibuf->rect_float= cbuf->rect;
-
- /* vars for efficient looping */
- uv= uvbuf->rect;
- uvnext= uv+row;
- uvprev= uv-row;
- sx= stackbuf->x;
- sy= stackbuf->y;
-
- for (y=0; y<sy; y++) {
- for (x=0; x<sx; x++, out+=4, uv+=3, uvnext+=3, uvprev+=3) {
- if (x>0 && x<sx-1 && y>0 && y<sy-1) {
- if (uv[2]!=0.0f) {
- float uv_l, uv_r;
-
- /* adaptive sampling, red (U) channel */
-
- /* prevent alpha zero UVs to be used */
- uv_l= uv[-1]!=0.0f? fabsf(uv[0]-uv[-3]) : 0.0f;
- uv_r= uv[ 5]!=0.0f? fabsf(uv[0]-uv[ 3]) : 0.0f;
-
- //dx= 0.5f*(fabs(uv[0]-uv[-3]) + fabs(uv[0]-uv[3]));
- dx= 0.5f*(uv_l + uv_r);
-
- uv_l= uvprev[-1]!=0.0f? fabsf(uv[0]-uvprev[-3]) : 0.0f;
- uv_r= uvnext[-1]!=0.0f? fabsf(uv[0]-uvnext[-3]) : 0.0f;
-
- //dx+= 0.25f*(fabs(uv[0]-uvprev[-3]) + fabs(uv[0]-uvnext[-3]));
- dx+= 0.25f*(uv_l + uv_r);
-
- uv_l= uvprev[ 5]!=0.0f? fabsf(uv[0]-uvprev[+3]) : 0.0f;
- uv_r= uvnext[ 5]!=0.0f? fabsf(uv[0]-uvnext[+3]) : 0.0f;
-
- //dx+= 0.25f*(fabs(uv[0]-uvprev[+3]) + fabs(uv[0]-uvnext[+3]));
- dx+= 0.25f*(uv_l + uv_r);
-
- /* adaptive sampling, green (V) channel */
-
- uv_l= uv[-row+2]!=0.0f? fabsf(uv[1]-uv[-row+1]) : 0.0f;
- uv_r= uv[ row+2]!=0.0f? fabsf(uv[1]-uv[ row+1]) : 0.0f;
-
- //dy= 0.5f*(fabs(uv[1]-uv[-row+1]) + fabs(uv[1]-uv[row+1]));
- dy= 0.5f*(uv_l + uv_r);
-
- uv_l= uvprev[-1]!=0.0f? fabsf(uv[1]-uvprev[+1-3]) : 0.0f;
- uv_r= uvnext[-1]!=0.0f? fabsf(uv[1]-uvnext[+1-3]) : 0.0f;
-
- //dy+= 0.25f*(fabs(uv[1]-uvprev[+1-3]) + fabs(uv[1]-uvnext[+1-3]));
- dy+= 0.25f*(uv_l + uv_r);
-
- uv_l= uvprev[ 5]!=0.0f? fabsf(uv[1]-uvprev[+1+3]) : 0.0f;
- uv_r= uvnext[ 5]!=0.0f? fabsf(uv[1]-uvnext[+1+3]) : 0.0f;
-
- //dy+= 0.25f*(fabs(uv[1]-uvprev[+1+3]) + fabs(uv[1]-uvnext[+1+3]));
- dy+= 0.25f*(uv_l + uv_r);
-
- /* UV to alpha threshold */
- alpha= 1.0f - threshold*(dx+dy);
- if (alpha<0.0f) alpha= 0.0f;
- else alpha*= uv[2];
-
- /* should use mipmap */
- if (dx > 0.20f) dx= 0.20f;
- if (dy > 0.20f) dy= 0.20f;
-
- ibuf_sample(ibuf, uv[0], uv[1], dx, dy, out);
- /* premul */
- if (alpha<1.0f) {
- out[0]*= alpha;
- out[1]*= alpha;
- out[2]*= alpha;
- out[3]*= alpha;
- }
- }
- }
- }
- }
-
- IMB_freeImBuf(ibuf);
-}
-
-
-static void node_composit_exec_mapuv(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- if (out[0]->hasoutput==0)
- return;
-
- if (in[0]->data && in[1]->data) {
- CompBuf *cbuf= in[0]->data;
- CompBuf *uvbuf= in[1]->data;
- CompBuf *stackbuf;
-
- cbuf= typecheck_compbuf(cbuf, CB_RGBA);
- uvbuf= typecheck_compbuf(uvbuf, CB_VEC3);
- stackbuf= alloc_compbuf(uvbuf->x, uvbuf->y, CB_RGBA, 1); /* allocs */;
-
- do_mapuv(stackbuf, cbuf, uvbuf, 0.05f*(float)node->custom1);
-
- out[0]->data= stackbuf;
-
- if (cbuf!=in[0]->data)
- free_compbuf(cbuf);
- if (uvbuf!=in[1]->data)
- free_compbuf(uvbuf);
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_mapuv(bNodeTreeType *ttype)
+void register_node_type_cmp_mapuv(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MAP_UV, "Map UV", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MAP_UV, "Map UV", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_mapuv_in, cmp_node_mapuv_out);
- node_type_size(&ntype, 140, 100, 320);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_mapuv);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_mapValue.c b/source/blender/nodes/composite/nodes/node_composite_mapValue.c
index 677d5bd5013..a61ecd41746 100644
--- a/source/blender/nodes/composite/nodes/node_composite_mapValue.c
+++ b/source/blender/nodes/composite/nodes/node_composite_mapValue.c
@@ -42,61 +42,19 @@ static bNodeSocketTemplate cmp_node_map_value_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_map_value(bNode *node, float *out, float *src)
-{
- TexMapping *texmap= node->storage;
-
- out[0] = (src[0] + texmap->loc[0])*texmap->size[0];
- if (texmap->flag & TEXMAP_CLIP_MIN)
- if (out[0]<texmap->min[0])
- out[0] = texmap->min[0];
- if (texmap->flag & TEXMAP_CLIP_MAX)
- if (out[0]>texmap->max[0])
- out[0] = texmap->max[0];
-}
-
-static void node_composit_exec_map_value(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order in: valbuf */
- /* stack order out: valbuf */
- if (out[0]->hasoutput==0) return;
-
- /* input no image? then only value operation */
- if (in[0]->data==NULL) {
- do_map_value(node, out[0]->vec, in[0]->vec);
- }
- else {
- /* make output size of input image */
- CompBuf *cbuf= in[0]->data;
- CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */
-
- composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_map_value, CB_VAL);
-
- out[0]->data= stackbuf;
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_map_value(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_map_value(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= add_tex_mapping();
}
-void register_node_type_cmp_map_value(bNodeTreeType *ttype)
+void register_node_type_cmp_map_value(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MAP_VALUE, "Map Value", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MAP_VALUE, "Map Value", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_map_value_in, cmp_node_map_value_out);
- node_type_size(&ntype, 100, 60, 150);
node_type_init(&ntype, node_composit_init_map_value);
node_type_storage(&ntype, "TexMapping", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_map_value);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_mask.c b/source/blender/nodes/composite/nodes/node_composite_mask.c
index 3463c1a8413..f97e83f177a 100644
--- a/source/blender/nodes/composite/nodes/node_composite_mask.c
+++ b/source/blender/nodes/composite/nodes/node_composite_mask.c
@@ -45,51 +45,9 @@ static bNodeSocketTemplate cmp_node_mask_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-static void node_composit_exec_mask(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
+static void node_composit_init_mask(bNodeTree *UNUSED(ntree), bNode *node)
{
- if (node->id) {
- Mask *mask = (Mask *)node->id;
- MaskRasterHandle *mr_handle;
- CompBuf *stackbuf;
- RenderData *rd = data;
- float *res;
- int sx, sy;
-
- if (!out[0]->hasoutput) {
- /* the node's output socket is not connected to anything...
- * do not execute any further, just exit the node immediately
- */
- return;
- }
-
- sx = (rd->size * rd->xsch) / 100;
- sy = (rd->size * rd->ysch) / 100;
-
- /* allocate the output buffer */
- stackbuf = alloc_compbuf(sx, sy, CB_VAL, TRUE);
- res = stackbuf->rect;
-
- /* mask raster begin */
- mr_handle = BKE_maskrasterize_handle_new();
- BKE_maskrasterize_handle_init(mr_handle, mask,
- sx, sy,
- TRUE,
- (node->custom1 & CMP_NODEFLAG_MASK_AA) != 0,
- (node->custom1 & CMP_NODEFLAG_MASK_NO_FEATHER) == 0);
- BKE_maskrasterize_buffer(mr_handle, sx, sy, res);
- BKE_maskrasterize_handle_free(mr_handle);
- /* mask raster end */
-
- /* pass on output and free */
- out[0]->data = stackbuf;
- }
-}
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_mask(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
-{
- NodeMask *data = MEM_callocN(sizeof(NodeMask), STRINGIFY(NodeMask));
+ NodeMask *data = MEM_callocN(sizeof(NodeMask), "NodeMask");
data->size_x = data->size_y = 256;
node->storage = data;
@@ -97,19 +55,15 @@ static void node_composit_init_mask(bNodeTree *UNUSED(ntree), bNode *node, bNode
node->custom3 = 0.5f; /* shutter */
}
-void register_node_type_cmp_mask(bNodeTreeType *ttype)
+void register_node_type_cmp_mask(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MASK, "Mask", NODE_CLASS_INPUT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MASK, "Mask", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, cmp_node_mask_out);
- node_type_size(&ntype, 140, 100, 320);
node_type_init(&ntype, node_composit_init_mask);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_mask);
-#endif
node_type_storage(&ntype, "NodeMask", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_math.c b/source/blender/nodes/composite/nodes/node_composite_math.c
index 5bc67adf5fb..802a370f882 100644
--- a/source/blender/nodes/composite/nodes/node_composite_math.c
+++ b/source/blender/nodes/composite/nodes/node_composite_math.c
@@ -44,173 +44,14 @@ static bNodeSocketTemplate cmp_node_math_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-static void do_math(bNode *node, float *out, float *in, float *in2)
-{
- switch (node->custom1) {
- case 0: /* Add */
- out[0] = in[0] + in2[0];
- break;
- case 1: /* Subtract */
- out[0] = in[0] - in2[0];
- break;
- case 2: /* Multiply */
- out[0] = in[0] * in2[0];
- break;
- case 3: /* Divide */
- {
- if (in2[0]==0) /* We don't want to divide by zero. */
- out[0] = 0.0;
- else
- out[0] = in[0] / in2[0];
- }
- break;
- case 4: /* Sine */
- out[0] = sin(in[0]);
- break;
- case 5: /* Cosine */
- out[0] = cos(in[0]);
- break;
- case 6: /* Tangent */
- out[0] = tan(in[0]);
- break;
- case 7: /* Arc-Sine */
- {
- /* Can't do the impossible... */
- if (in[0] <= 1 && in[0] >= -1 )
- out[0] = asin(in[0]);
- else
- out[0] = 0.0;
- }
- break;
- case 8: /* Arc-Cosine */
- {
- /* Can't do the impossible... */
- if ( in[0] <= 1 && in[0] >= -1 )
- out[0] = acos(in[0]);
- else
- out[0] = 0.0;
- }
- break;
- case 9: /* Arc-Tangent */
- out[0] = atan(in[0]);
- break;
- case 10: /* Power */
- {
- /* Only raise negative numbers by full integers */
- if ( in[0] >= 0 ) {
- out[0] = pow(in[0], in2[0]);
- }
- else {
- float y_mod_1 = fabsf(fmodf(in2[0], 1.0f));
-
- /* if input value is not nearly an integer, fall back to zero, nicer than straight rounding */
- if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) {
- out[0] = powf(in[0], floorf(in2[0] + 0.5f));
- }
- else {
- out[0] = 0.0f;
- }
- }
- }
- break;
- case 11: /* Logarithm */
- {
- /* Don't want any imaginary numbers... */
- if ( in[0] > 0 && in2[0] > 0 )
- out[0] = log(in[0]) / log(in2[0]);
- else
- out[0] = 0.0;
- }
- break;
- case 12: /* Minimum */
- {
- if ( in[0] < in2[0] )
- out[0] = in[0];
- else
- out[0] = in2[0];
- }
- break;
- case 13: /* Maximum */
- {
- if ( in[0] > in2[0] )
- out[0] = in[0];
- else
- out[0] = in2[0];
- }
- break;
- case 14: /* Round */
- {
- /* round by the second value */
- if ( in2[0] != 0.0f )
- out[0] = floorf(in[0] / in2[0] + 0.5f) * in2[0];
- else
- out[0] = floorf(in[0] + 0.5f);
- }
- break;
- case 15: /* Less Than */
- {
- if ( in[0] < in2[0] )
- out[0] = 1.0f;
- else
- out[0] = 0.0f;
- }
- break;
- case 16: /* Greater Than */
- {
- if ( in[0] > in2[0] )
- out[0] = 1.0f;
- else
- out[0] = 0.0f;
- }
- break;
- }
-}
-
-static void node_composit_exec_math(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- CompBuf *cbuf=in[0]->data;
- CompBuf *cbuf2=in[1]->data;
- CompBuf *stackbuf;
-
- /* check for inputs and outputs for early out*/
- if (out[0]->hasoutput==0) return;
-
- /* no image-color operation */
- if (in[0]->data==NULL && in[1]->data==NULL) {
- do_math(node, out[0]->vec, in[0]->vec, in[1]->vec);
- return;
- }
-
- /* create output based on first input */
- if (cbuf) {
- stackbuf=alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1);
- }
- /* and if it doesn't exist use the second input since we
- * know that one of them must exist at this point*/
- else {
- stackbuf=alloc_compbuf(cbuf2->x, cbuf2->y, CB_VAL, 1);
- }
-
- /* operate in case there's valid size */
- composit2_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_math, CB_VAL, CB_VAL);
- out[0]->data= stackbuf;
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_math(bNodeTreeType *ttype)
+void register_node_type_cmp_math(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_math_in, cmp_node_math_out);
- node_type_size(&ntype, 120, 110, 160);
node_type_label(&ntype, node_math_label);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_math);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_mixrgb.c b/source/blender/nodes/composite/nodes/node_composite_mixrgb.c
index 5d3ee480612..a3415761bf8 100644
--- a/source/blender/nodes/composite/nodes/node_composite_mixrgb.c
+++ b/source/blender/nodes/composite/nodes/node_composite_mixrgb.c
@@ -43,60 +43,14 @@ static bNodeSocketTemplate cmp_node_mix_rgb_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_mix_rgb(bNode *node, float *out, float *in1, float *in2, float *fac)
-{
- float col[3];
-
- copy_v3_v3(col, in1);
- if (node->custom2)
- ramp_blend(node->custom1, col, in2[3]*fac[0], in2);
- else
- ramp_blend(node->custom1, col, fac[0], in2);
- copy_v3_v3(out, col);
- out[3] = in1[3];
-}
-
-static void node_composit_exec_mix_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order in: fac, Image, Image */
- /* stack order out: Image */
- float *fac= in[0]->vec;
-
- if (out[0]->hasoutput==0) return;
-
- /* input no image? then only color operation */
- if (in[1]->data==NULL && in[2]->data==NULL) {
- do_mix_rgb(node, out[0]->vec, in[1]->vec, in[2]->vec, fac);
- }
- else {
- /* make output size of first available input image */
- CompBuf *cbuf= in[1]->data?in[1]->data:in[2]->data;
- CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
-
- composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, fac, do_mix_rgb, CB_RGBA, CB_RGBA, CB_VAL);
-
- out[0]->data= stackbuf;
-
- generate_preview(data, node, out[0]->data);
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
/* custom1 = mix type */
-void register_node_type_cmp_mix_rgb(bNodeTreeType *ttype)
+void register_node_type_cmp_mix_rgb(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_mix_rgb_in, cmp_node_mix_rgb_out);
- node_type_size(&ntype, 110, 60, 120);
node_type_label(&ntype, node_blend_label);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_mix_rgb);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_movieclip.c b/source/blender/nodes/composite/nodes/node_composite_movieclip.c
index 370cff5e0d7..2369bf221e6 100644
--- a/source/blender/nodes/composite/nodes/node_composite_movieclip.c
+++ b/source/blender/nodes/composite/nodes/node_composite_movieclip.c
@@ -35,6 +35,7 @@
static bNodeSocketTemplate cmp_node_movieclip_out[] = {
{ SOCK_RGBA, 0, N_("Image")},
+ { SOCK_FLOAT, 0, N_("Alpha")},
{ SOCK_FLOAT, 1, N_("Offset X")},
{ SOCK_FLOAT, 1, N_("Offset Y")},
{ SOCK_FLOAT, 1, N_("Scale")},
@@ -42,107 +43,7 @@ static bNodeSocketTemplate cmp_node_movieclip_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static CompBuf *node_composit_get_movieclip(RenderData *rd, MovieClip *clip, MovieClipUser *user)
-{
- ImBuf *orig_ibuf, *ibuf;
- CompBuf *stackbuf;
- int type;
-
- float *rect;
- int alloc = FALSE;
-
- orig_ibuf = BKE_movieclip_get_ibuf(clip, user);
-
- if (orig_ibuf == NULL || (orig_ibuf->rect == NULL && orig_ibuf->rect_float == NULL)) {
- IMB_freeImBuf(orig_ibuf);
- return NULL;
- }
-
- ibuf = IMB_dupImBuf(orig_ibuf);
- IMB_freeImBuf(orig_ibuf);
-
- if (ibuf->rect_float == NULL || (ibuf->userflags & IB_RECT_INVALID)) {
- IMB_float_from_rect(ibuf);
- ibuf->userflags &= ~IB_RECT_INVALID;
- }
-
- /* now we need a float buffer from the image with matching color management */
- if (ibuf->channels == 4) {
- rect = node_composit_get_float_buffer(rd, ibuf, &alloc);
- }
- else {
- /* non-rgba passes can't use color profiles */
- rect = ibuf->rect_float;
- }
- /* done coercing into the correct color management */
-
- if (!alloc) {
- rect = MEM_dupallocN(rect);
- alloc = TRUE;
- }
-
- type = ibuf->channels;
-
- if (rd->scemode & R_COMP_CROP) {
- stackbuf = get_cropped_compbuf(&rd->disprect, rect, ibuf->x, ibuf->y, type);
- if (alloc)
- MEM_freeN(rect);
- }
- else {
- /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */
- stackbuf = alloc_compbuf(ibuf->x, ibuf->y, type, FALSE);
- stackbuf->rect = rect;
- stackbuf->malloc = alloc;
- }
-
- IMB_freeImBuf(ibuf);
-
- return stackbuf;
-}
-
-static void node_composit_exec_movieclip(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
-{
- if (node->id) {
- RenderData *rd = data;
- MovieClip *clip = (MovieClip *)node->id;
- MovieClipUser *user = (MovieClipUser *)node->storage;
- CompBuf *stackbuf = NULL;
-
- BKE_movieclip_user_set_frame(user, rd->cfra);
-
- stackbuf = node_composit_get_movieclip(rd, clip, user);
-
- if (stackbuf) {
- MovieTrackingStabilization *stab = &clip->tracking.stabilization;
-
- /* put image on stack */
- out[0]->data = stackbuf;
-
- if (stab->flag & TRACKING_2D_STABILIZATION) {
- float loc[2], scale, angle;
- int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, rd->cfra);
-
- BKE_tracking_stabilization_data_get(&clip->tracking, clip_framenr, stackbuf->x, stackbuf->y,
- loc, &scale, &angle);
-
- out[1]->vec[0] = loc[0];
- out[2]->vec[0] = loc[1];
-
- out[3]->vec[0] = scale;
- out[4]->vec[0] = angle;
- }
-
- /* generate preview */
- generate_preview(data, node, stackbuf);
- }
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
{
MovieClipUser *user = MEM_callocN(sizeof(MovieClipUser), "node movie clip user");
@@ -150,18 +51,14 @@ static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(nt
user->framenr = 1;
}
-void register_node_type_cmp_movieclip(bNodeTreeType *ttype)
+void register_node_type_cmp_movieclip(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MOVIECLIP, "Movie Clip", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MOVIECLIP, "Movie Clip", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, cmp_node_movieclip_out);
- node_type_size(&ntype, 120, 80, 300);
node_type_init(&ntype, init);
node_type_storage(&ntype, "MovieClipUser", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_movieclip);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c b/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
index 9f4cd467c94..86666a38f1d 100644
--- a/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
+++ b/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
@@ -30,9 +30,6 @@
* \ingroup cmpnodes
*/
-#include "BLF_translation.h"
-
-
#include "node_composite_util.h"
/* **************** Translate ******************** */
@@ -47,66 +44,6 @@ static bNodeSocketTemplate cmp_node_moviedistortion_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-static void node_composit_exec_moviedistortion(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
-{
- if (in[0]->data) {
- if (node->id) {
- MovieClip *clip = (MovieClip *)node->id;
- CompBuf *cbuf = typecheck_compbuf(in[0]->data, CB_RGBA);
- CompBuf *stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 0);
- ImBuf *ibuf;
-
- ibuf = IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0);
-
- if (ibuf) {
- RenderData *rd = data;
- ImBuf *obuf;
- MovieTracking *tracking = &clip->tracking;
- int width, height;
- float overscan = 0.0f;
- MovieClipUser user = {0};
-
- BKE_movieclip_user_set_frame(&user, rd->cfra);
-
- ibuf->rect_float = cbuf->rect;
-
- BKE_movieclip_get_size(clip, &user, &width, &height);
-
- if (!node->storage)
- node->storage = BKE_tracking_distortion_new();
-
- if (node->custom1 == 0)
- obuf = BKE_tracking_distortion_exec(node->storage, tracking, ibuf, width, height, overscan, 1);
- else
- obuf = BKE_tracking_distortion_exec(node->storage, tracking, ibuf, width, height, overscan, 0);
-
- stackbuf->rect = obuf->rect_float;
- stackbuf->malloc = TRUE;
-
- obuf->mall &= ~IB_rectfloat;
- obuf->rect_float = NULL;
-
- IMB_freeImBuf(ibuf);
- IMB_freeImBuf(obuf);
- }
-
- /* pass on output and free */
- out[0]->data = stackbuf;
-
- if (cbuf != in[0]->data)
- free_compbuf(cbuf);
- }
- else {
- CompBuf *cbuf = in[0]->data;
- CompBuf *stackbuf = pass_on_compbuf(cbuf);
-
- out[0]->data = stackbuf;
- }
- }
-}
-#endif /* WITH_COMPOSITOR_LEGACY */
-
static const char *label(bNode *node)
{
if (node->custom1 == 0)
@@ -123,25 +60,21 @@ static void storage_free(bNode *node)
node->storage = NULL;
}
-static void storage_copy(bNode *orig_node, bNode *new_node)
+static void storage_copy(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node)
{
- if (orig_node->storage)
- new_node->storage = BKE_tracking_distortion_copy(orig_node->storage);
+ if (src_node->storage)
+ dest_node->storage = BKE_tracking_distortion_copy(src_node->storage);
}
-void register_node_type_cmp_moviedistortion(bNodeTreeType *ttype)
+void register_node_type_cmp_moviedistortion(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_MOVIEDISTORTION, "Movie Distortion", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_MOVIEDISTORTION, "Movie Distortion", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_moviedistortion_in, cmp_node_moviedistortion_out);
- node_type_size(&ntype, 140, 100, 320);
node_type_label(&ntype, label);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_moviedistortion);
-#endif
node_type_storage(&ntype, NULL, storage_free, storage_copy);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_normal.c b/source/blender/nodes/composite/nodes/node_composite_normal.c
index d104e8f03e6..0f7fdb53693 100644
--- a/source/blender/nodes/composite/nodes/node_composite_normal.c
+++ b/source/blender/nodes/composite/nodes/node_composite_normal.c
@@ -32,7 +32,6 @@
#include "node_composite_util.h"
-
/* **************** NORMAL ******************** */
static bNodeSocketTemplate cmp_node_normal_in[] = {
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION},
@@ -40,70 +39,17 @@ static bNodeSocketTemplate cmp_node_normal_in[] = {
};
static bNodeSocketTemplate cmp_node_normal_out[] = {
- { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION},
+ { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, PROP_DIRECTION},
{ SOCK_FLOAT, 0, N_("Dot")},
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_normal(bNode *node, float *out, float *in)
-{
- bNodeSocket *sock= node->outputs.first;
- float *nor= ((bNodeSocketValueVector*)sock->default_value)->value;
-
- /* render normals point inside... the widget points outside */
- out[0] = -dot_v3v3(nor, in);
-}
-
-/* generates normal, does dot product */
-static void node_composit_exec_normal(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- bNodeSocket *sock= node->outputs.first;
- float *nor= ((bNodeSocketValueVector*)sock->default_value)->value;
- /* stack order input: normal */
- /* stack order output: normal, value */
-
- /* input no image? then only vector op */
- if (in[0]->data==NULL) {
- copy_v3_v3(out[0]->vec, nor);
- /* render normals point inside... the widget points outside */
- out[1]->vec[0] = -dot_v3v3(out[0]->vec, in[0]->vec);
- }
- else if (out[1]->hasoutput) {
- /* make output size of input image */
- CompBuf *cbuf= in[0]->data;
- CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */
-
- composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_normal, CB_VEC3);
-
- out[1]->data= stackbuf;
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
-{
- bNodeSocket *sock= node->outputs.first;
- float *nor= ((bNodeSocketValueVector*)sock->default_value)->value;
-
- nor[0] = 0.0f;
- nor[1] = 0.0f;
- nor[2] = 1.0f;
-}
-
-void register_node_type_cmp_normal(bNodeTreeType *ttype)
+void register_node_type_cmp_normal(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_NORMAL, "Normal", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_NORMAL, "Normal", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_normal_in, cmp_node_normal_out);
- node_type_init(&ntype, init);
- node_type_size(&ntype, 100, 60, 200);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_normal);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_normalize.c b/source/blender/nodes/composite/nodes/node_composite_normalize.c
index 19b543dce5d..c101d7edec4 100644
--- a/source/blender/nodes/composite/nodes/node_composite_normalize.c
+++ b/source/blender/nodes/composite/nodes/node_composite_normalize.c
@@ -43,79 +43,12 @@ static bNodeSocketTemplate cmp_node_normalize_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_normalize(bNode *UNUSED(node), float *out, float *src, float *min, float *mult)
-{
- float res;
- res = (src[0] - min[0]) * mult[0];
- if (res > 1.0f) {
- out[0] = 1.0f;
- }
- else if (res < 0.0f) {
- out[0] = 0.0f;
- }
- else {
- out[0] = res;
- }
-}
-
-/* The code below assumes all data is inside range +- this, and that input buffer is single channel */
-#define BLENDER_ZMAX 10000.0f
-
-static void node_composit_exec_normalize(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order in: valbuf */
- /* stack order out: valbuf */
- if (out[0]->hasoutput==0) return;
-
- /* Input has no image buffer? Then pass the value */
- if (in[0]->data==NULL) {
- copy_v4_v4(out[0]->vec, in[0]->vec);
- }
- else {
- float min = 1.0f+BLENDER_ZMAX;
- float max = -1.0f-BLENDER_ZMAX;
- float mult = 1.0f;
- float *val;
- /* make output size of input image */
- CompBuf *cbuf= in[0]->data;
- int tot= cbuf->x*cbuf->y;
- CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */
-
- for (val = cbuf->rect; tot; tot--, val++) {
- if ((*val > max) && (*val <= BLENDER_ZMAX)) {
- max = *val;
- }
- if ((*val < min) && (*val >= -BLENDER_ZMAX)) {
- min = *val;
- }
- }
- /* In the rare case of flat buffer, which would cause a divide by 0, just pass the input to the output */
- if ((max-min) != 0.0f) {
- mult = 1.0f/(max-min);
- composit3_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, NULL, &min, NULL, &mult, do_normalize, CB_VAL, CB_VAL, CB_VAL);
- }
- else {
- memcpy(stackbuf->rect, cbuf->rect, sizeof(float) * cbuf->x * cbuf->y);
- }
-
- out[0]->data= stackbuf;
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_normalize(bNodeTreeType *ttype)
+void register_node_type_cmp_normalize(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_NORMALIZE, "Normalize", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_NORMALIZE, "Normalize", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_normalize_in, cmp_node_normalize_out);
- node_type_size(&ntype, 100, 60, 150);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_normalize);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
index 214617c91e5..18bb97c70ed 100644
--- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c
+++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
@@ -31,8 +31,13 @@
#include <string.h>
+#include "BLI_utildefines.h"
#include "BLI_path_util.h"
+#include "BKE_context.h"
+
+#include "RNA_access.h"
+
#include "node_composite_util.h"
#include "IMB_imbuf.h"
@@ -44,18 +49,18 @@
/* **************** OUTPUT FILE ******************** */
/* find unique path */
-static int unique_path_unique_check(void *arg, const char *name)
+static bool unique_path_unique_check(void *arg, const char *name)
{
struct {ListBase *lb; bNodeSocket *sock;} *data= arg;
bNodeSocket *sock;
- for (sock=data->lb->first; sock; sock=sock->next) {
+ for (sock=data->lb->first; sock; sock = sock->next) {
if (sock != data->sock) {
NodeImageMultiFileSocket *sockdata = sock->storage;
- if (strcmp(sockdata->path, name)==0)
- return 1;
+ if (STREQ(sockdata->path, name))
+ return true;
}
}
- return 0;
+ return false;
}
void ntreeCompositOutputFileUniquePath(ListBase *list, bNodeSocket *sock, const char defname[], char delim)
{
@@ -73,18 +78,18 @@ void ntreeCompositOutputFileUniquePath(ListBase *list, bNodeSocket *sock, const
}
/* find unique EXR layer */
-static int unique_layer_unique_check(void *arg, const char *name)
+static bool unique_layer_unique_check(void *arg, const char *name)
{
struct {ListBase *lb; bNodeSocket *sock;} *data= arg;
bNodeSocket *sock;
- for (sock=data->lb->first; sock; sock=sock->next) {
+ for (sock=data->lb->first; sock; sock = sock->next) {
if (sock != data->sock) {
NodeImageMultiFileSocket *sockdata = sock->storage;
- if (strcmp(sockdata->layer, name)==0)
- return 1;
+ if (STREQ(sockdata->layer, name))
+ return true;
}
}
- return 0;
+ return false;
}
void ntreeCompositOutputFileUniqueLayer(ListBase *list, bNodeSocket *sock, const char defname[], char delim)
{
@@ -104,7 +109,7 @@ void ntreeCompositOutputFileUniqueLayer(ListBase *list, bNodeSocket *sock, const
bNodeSocket *ntreeCompositOutputFileAddSocket(bNodeTree *ntree, bNode *node, const char *name, ImageFormatData *im_format)
{
NodeImageMultiFile *nimf = node->storage;
- bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_IN, "", SOCK_RGBA);
+ bNodeSocket *sock = nodeAddStaticSocket(ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, NULL, name);
/* create format data for the input socket */
NodeImageMultiFileSocket *sockdata = MEM_callocN(sizeof(NodeImageMultiFileSocket), "socket image format");
@@ -164,14 +169,19 @@ void ntreeCompositOutputFileSetLayer(bNode *node, bNodeSocket *sock, const char
ntreeCompositOutputFileUniqueLayer(&node->inputs, sock, name, '_');
}
-static void init_output_file(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp)
+/* XXX uses initfunc_api callback, regular initfunc does not support context yet */
+static void init_output_file(const bContext *C, PointerRNA *ptr)
{
+ Scene *scene = CTX_data_scene(C);
+ bNodeTree *ntree = ptr->id.data;
+ bNode *node = ptr->data;
NodeImageMultiFile *nimf= MEM_callocN(sizeof(NodeImageMultiFile), "node image multi file");
ImageFormatData *format = NULL;
node->storage= nimf;
+
+ if (scene) {
+ RenderData *rd = &scene->r;
- if (ntemp->scene) {
- RenderData *rd = &ntemp->scene->r;
BLI_strncpy(nimf->base_path, rd->pic, sizeof(nimf->base_path));
nimf->format = rd->im_format;
if (BKE_imtype_is_movie(nimf->format.imtype)) {
@@ -192,229 +202,50 @@ static void free_output_file(bNode *node)
bNodeSocket *sock;
/* free storage data in sockets */
- for (sock=node->inputs.first; sock; sock=sock->next) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
MEM_freeN(sock->storage);
}
MEM_freeN(node->storage);
}
-static void copy_output_file(struct bNode *node, struct bNode *target)
+static void copy_output_file(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node)
{
- bNodeSocket *sock, *newsock;
+ bNodeSocket *src_sock, *dest_sock;
- target->storage = MEM_dupallocN(node->storage);
+ dest_node->storage = MEM_dupallocN(src_node->storage);
/* duplicate storage data in sockets */
- for (sock=node->inputs.first, newsock=target->inputs.first; sock && newsock; sock=sock->next, newsock=newsock->next) {
- newsock->storage = MEM_dupallocN(sock->storage);
+ for (src_sock=src_node->inputs.first, dest_sock=dest_node->inputs.first; src_sock && dest_sock; src_sock=src_sock->next, dest_sock=dest_sock->next) {
+ dest_sock->storage = MEM_dupallocN(src_sock->storage);
}
}
-static void update_output_file(bNodeTree *UNUSED(ntree), bNode *node)
+static void update_output_file(bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock;
+ PointerRNA ptr;
+
+ cmp_node_update_default(ntree, node);
/* automatically update the socket type based on linked input */
- for (sock=node->inputs.first; sock; sock=sock->next) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
if (sock->link) {
- int linktype = sock->link->fromsock->type;
- if (linktype != sock->type)
- nodeSocketSetType(sock, linktype);
- }
- }
-}
-
-#ifdef WITH_COMPOSITOR_LEGACY
-
-/* write input data into individual files */
-static void exec_output_file_singlelayer(RenderData *rd, bNode *node, bNodeStack **in)
-{
- Main *bmain= G.main; /* TODO, have this passed along */
- NodeImageMultiFile *nimf= node->storage;
- bNodeSocket *sock;
- int i;
- int has_preview = 0;
-
- for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) {
- if (in[i]->data) {
- NodeImageMultiFileSocket *sockdata = sock->storage;
- ImageFormatData *format = (sockdata->use_node_format ? &nimf->format : &sockdata->format);
- char path[FILE_MAX];
- char filename[FILE_MAX];
- CompBuf *cbuf = NULL;
- ImBuf *ibuf;
-
- switch (format->planes) {
- case R_IMF_PLANES_BW:
- cbuf = typecheck_compbuf(in[i]->data, CB_VAL);
- break;
- case R_IMF_PLANES_RGB:
- cbuf = typecheck_compbuf(in[i]->data, CB_VEC3);
- break;
- case R_IMF_PLANES_RGBA:
- cbuf = typecheck_compbuf(in[i]->data, CB_RGBA);
- break;
- }
-
- ibuf = IMB_allocImBuf(cbuf->x, cbuf->y, format->planes, 0);
- /* XXX have to set this explicitly it seems */
- switch (format->planes) {
- case R_IMF_PLANES_BW: ibuf->channels = 1; break;
- case R_IMF_PLANES_RGB: ibuf->channels = 3; break;
- case R_IMF_PLANES_RGBA: ibuf->channels = 4; break;
- }
- ibuf->rect_float = cbuf->rect;
- ibuf->dither = rd->dither_intensity;
-
- /* get full path */
- BLI_join_dirfile(path, FILE_MAX, nimf->base_path, sockdata->path);
- BKE_makepicstring(filename, path, bmain->name, rd->cfra, format->imtype, (rd->scemode & R_EXTENSION), TRUE);
-
- if (0 == BKE_imbuf_write(ibuf, filename, format))
- printf("Cannot save Node File Output to %s\n", filename);
- else
- printf("Saved: %s\n", filename);
-
- IMB_freeImBuf(ibuf);
-
- /* simply pick the first valid input for preview */
- if (!has_preview) {
- generate_preview(rd, node, cbuf);
- has_preview = 1;
- }
-
- if (in[i]->data != cbuf)
- free_compbuf(cbuf);
- }
- }
-}
-
-/* write input data into layers */
-static void exec_output_file_multilayer(RenderData *rd, bNode *node, bNodeStack **in)
-{
- Main *bmain= G.main; /* TODO, have this passed along */
- NodeImageMultiFile *nimf= node->storage;
- void *exrhandle= IMB_exr_get_handle();
- char filename[FILE_MAX];
- bNodeSocket *sock;
- int i;
- /* Must have consistent pixel size for exr file, simply take the first valid input size. */
- int rectx = -1;
- int recty = -1;
- int has_preview = 0;
-
- BKE_makepicstring(filename, nimf->base_path, bmain->name, rd->cfra, R_IMF_IMTYPE_MULTILAYER, (rd->scemode & R_EXTENSION), TRUE);
- BLI_make_existing_file(filename);
-
- for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) {
- if (in[i]->data) {
- NodeImageMultiFileSocket *sockdata = sock->storage;
- CompBuf *cbuf = in[i]->data;
- char channelname[EXR_TOT_MAXNAME]; /* '.' and single character channel name is appended */
- char *channelname_ext;
-
- if (cbuf->rect_procedural) {
- printf("Error writing multilayer EXR: Procedural buffer not supported\n");
- continue;
- }
- if (rectx < 0) {
- rectx = cbuf->x;
- recty = cbuf->y;
- }
- else if (cbuf->x != rectx || cbuf->y != recty) {
- printf("Error: Multilayer EXR output node %s expects same resolution for all input buffers. Layer %s skipped.\n", node->name, sock->name);
- continue;
- }
-
- BLI_strncpy(channelname, sockdata->layer, sizeof(channelname)-2);
- channelname_ext = channelname + strlen(channelname);
-
- /* create channels */
- switch (cbuf->type) {
- case CB_VAL:
- strcpy(channelname_ext, ".V");
- IMB_exr_add_channel(exrhandle, NULL, channelname, 1, rectx, cbuf->rect);
- break;
- case CB_VEC2:
- strcpy(channelname_ext, ".X");
- IMB_exr_add_channel(exrhandle, NULL, channelname, 2, 2*rectx, cbuf->rect);
- strcpy(channelname_ext, ".Y");
- IMB_exr_add_channel(exrhandle, NULL, channelname, 2, 2*rectx, cbuf->rect+1);
- break;
- case CB_VEC3:
- strcpy(channelname_ext, ".X");
- IMB_exr_add_channel(exrhandle, NULL, channelname, 3, 3*rectx, cbuf->rect);
- strcpy(channelname_ext, ".Y");
- IMB_exr_add_channel(exrhandle, NULL, channelname, 3, 3*rectx, cbuf->rect+1);
- strcpy(channelname_ext, ".Z");
- IMB_exr_add_channel(exrhandle, NULL, channelname, 3, 3*rectx, cbuf->rect+2);
- break;
- case CB_RGBA:
- strcpy(channelname_ext, ".R");
- IMB_exr_add_channel(exrhandle, NULL, channelname, 4, 4*rectx, cbuf->rect);
- strcpy(channelname_ext, ".G");
- IMB_exr_add_channel(exrhandle, NULL, channelname, 4, 4*rectx, cbuf->rect+1);
- strcpy(channelname_ext, ".B");
- IMB_exr_add_channel(exrhandle, NULL, channelname, 4, 4*rectx, cbuf->rect+2);
- strcpy(channelname_ext, ".A");
- IMB_exr_add_channel(exrhandle, NULL, channelname, 4, 4*rectx, cbuf->rect+3);
- break;
- }
-
- /* simply pick the first valid input for preview */
- if (!has_preview) {
- generate_preview(rd, node, cbuf);
- has_preview = 1;
- }
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+ RNA_enum_set(&ptr, "type", sock->link->fromsock->type);
}
}
-
- /* when the filename has no permissions, this can fail */
- if (IMB_exr_begin_write(exrhandle, filename, rectx, recty, nimf->format.exr_codec)) {
- IMB_exr_write_channels(exrhandle);
- }
- else {
- /* TODO, get the error from openexr's exception */
- /* XXX nice way to do report? */
- printf("Error Writing Render Result, see console\n");
- }
-
- IMB_exr_close(exrhandle);
-}
-
-static void node_composit_exec_outputfile(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
-{
- RenderData *rd= data;
- NodeImageMultiFile *nimf= node->storage;
-
- if (G.is_rendering == FALSE) {
- /* only output files when rendering a sequence -
- * otherwise, it overwrites the output files just
- * scrubbing through the timeline when the compositor updates */
- return;
- }
-
- if (nimf->format.imtype==R_IMF_IMTYPE_MULTILAYER)
- exec_output_file_multilayer(rd, node, in);
- else
- exec_output_file_singlelayer(rd, node, in);
}
-#endif /* WITH_COMPOSITOR_LEGACY */
-void register_node_type_cmp_output_file(bNodeTreeType *ttype)
+void register_node_type_cmp_output_file(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_OUTPUT_FILE, "File Output", NODE_CLASS_OUTPUT, NODE_OPTIONS|NODE_PREVIEW);
+ cmp_node_type_base(&ntype, CMP_NODE_OUTPUT_FILE, "File Output", NODE_CLASS_OUTPUT, NODE_OPTIONS|NODE_PREVIEW);
node_type_socket_templates(&ntype, NULL, NULL);
- node_type_size(&ntype, 140, 80, 300);
- node_type_init(&ntype, init_output_file);
+ ntype.initfunc_api = init_output_file;
node_type_storage(&ntype, "NodeImageMultiFile", free_output_file, copy_output_file);
node_type_update(&ntype, update_output_file, NULL);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_outputfile);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_pixelate.c b/source/blender/nodes/composite/nodes/node_composite_pixelate.c
index 5eac4867a23..d12c09cb25e 100644
--- a/source/blender/nodes/composite/nodes/node_composite_pixelate.c
+++ b/source/blender/nodes/composite/nodes/node_composite_pixelate.c
@@ -45,13 +45,12 @@ static bNodeSocketTemplate cmp_node_pixelate_out[] = {
{ -1, 0, "" }
};
-void register_node_type_cmp_pixelate(bNodeTreeType *ttype)
+void register_node_type_cmp_pixelate(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_PIXELATE, "Pixelate", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_PIXELATE, "Pixelate", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_pixelate_in, cmp_node_pixelate_out);
- node_type_size(&ntype, 130, 100, 130);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_premulkey.c b/source/blender/nodes/composite/nodes/node_composite_premulkey.c
index 7f7b7692b02..bfc5a54cf73 100644
--- a/source/blender/nodes/composite/nodes/node_composite_premulkey.c
+++ b/source/blender/nodes/composite/nodes/node_composite_premulkey.c
@@ -44,37 +44,12 @@ static bNodeSocketTemplate cmp_node_premulkey_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void node_composit_exec_premulkey(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- if (out[0]->hasoutput==0)
- return;
-
- if (in[0]->data) {
- CompBuf *stackbuf, *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
-
- stackbuf= dupalloc_compbuf(cbuf);
- premul_compbuf(stackbuf, node->custom1 == 1);
-
- out[0]->data = stackbuf;
- if (cbuf != in[0]->data)
- free_compbuf(cbuf);
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_premulkey(bNodeTreeType *ttype)
+void register_node_type_cmp_premulkey(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_PREMULKEY, "Alpha Convert", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_PREMULKEY, "Alpha Convert", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_premulkey_in, cmp_node_premulkey_out);
- node_type_size(&ntype, 140, 100, 320);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_premulkey);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_rgb.c b/source/blender/nodes/composite/nodes/node_composite_rgb.c
index 54fba650783..e3209844319 100644
--- a/source/blender/nodes/composite/nodes/node_composite_rgb.c
+++ b/source/blender/nodes/composite/nodes/node_composite_rgb.c
@@ -32,47 +32,19 @@
#include "node_composite_util.h"
-
/* **************** RGB ******************** */
static bNodeSocketTemplate cmp_node_rgb_out[] = {
- { SOCK_RGBA, 0, N_("RGBA"), 0.5f, 0.5f, 0.5f, 1.0f},
+ { SOCK_RGBA, 0, N_("RGBA"), 0.5f, 0.5f, 0.5f, 1.0f},
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void node_composit_exec_rgb(void *UNUSED(data), bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
-{
- bNodeSocket *sock= node->outputs.first;
- float *col= ((bNodeSocketValueRGBA*)sock->default_value)->value;
-
- copy_v4_v4(out[0]->vec, col);
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_rgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
-{
- bNodeSocket *sock= node->outputs.first;
- float *col= ((bNodeSocketValueRGBA*)sock->default_value)->value;
- /* uses the default value of the output socket, must be initialized here */
- col[0] = 0.5f;
- col[1] = 0.5f;
- col[2] = 0.5f;
- col[3] = 1.0f;
-}
-
-void register_node_type_cmp_rgb(bNodeTreeType *ttype)
+void register_node_type_cmp_rgb(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_RGB, "RGB", NODE_CLASS_INPUT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_RGB, "RGB", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, cmp_node_rgb_out);
- node_type_init(&ntype, node_composit_init_rgb);
- node_type_size(&ntype, 140, 80, 140);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_rgb);
-#endif
+ node_type_size_preset(&ntype, NODE_SIZE_SMALL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_rotate.c b/source/blender/nodes/composite/nodes/node_composite_rotate.c
index 50c8b2a78c1..1f51e25798d 100644
--- a/source/blender/nodes/composite/nodes/node_composite_rotate.c
+++ b/source/blender/nodes/composite/nodes/node_composite_rotate.c
@@ -44,103 +44,18 @@ static bNodeSocketTemplate cmp_node_rotate_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-/* only supports RGBA nodes now */
-static void node_composit_exec_rotate(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
-
- if (out[0]->hasoutput==0)
- return;
-
- if (in[0]->data) {
- CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
- CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* note, this returns zero'd image */
- float rad, u, v, s, c, centx, centy, miny, maxy, minx, maxx;
- int x, y, yo, xo;
- ImBuf *ibuf, *obuf;
-
- rad= in[1]->vec[0];
-
-
- s= sin(rad);
- c= cos(rad);
- centx= cbuf->x/2;
- centy= cbuf->y/2;
-
- minx= -centx;
- maxx= -centx + (float)cbuf->x;
- miny= -centy;
- maxy= -centy + (float)cbuf->y;
-
-
- ibuf=IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0);
- obuf=IMB_allocImBuf(stackbuf->x, stackbuf->y, 32, 0);
-
- if (ibuf && obuf) {
- ibuf->rect_float=cbuf->rect;
- obuf->rect_float=stackbuf->rect;
-
- for (y=miny; y<maxy; y++) {
- yo= y+(int)centy;
-
- for (x=minx; x<maxx;x++) {
- u=c*x + y*s + centx;
- v=-s*x + c*y + centy;
- xo= x+(int)centx;
-
- switch (node->custom1) {
- case 0:
- nearest_interpolation(ibuf, obuf, u, v, xo, yo);
- break;
- case 1:
- bilinear_interpolation(ibuf, obuf, u, v, xo, yo);
- break;
- case 2:
- bicubic_interpolation(ibuf, obuf, u, v, xo, yo);
- break;
- }
-
- }
- }
-
- /* rotate offset vector too, but why negative rad, ehh?? Has to be replaced with [3][3] matrix once (ton) */
- s= sin(-rad);
- c= cos(-rad);
- centx= (float)cbuf->xof; centy= (float)cbuf->yof;
- stackbuf->xof= (int)( c*centx + s*centy);
- stackbuf->yof= (int)(-s*centx + c*centy);
-
- IMB_freeImBuf(ibuf);
- IMB_freeImBuf(obuf);
- }
-
- /* pass on output and free */
- out[0]->data= stackbuf;
- if (cbuf!=in[0]->data) {
- free_compbuf(cbuf);
- }
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_rotate(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_rotate(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom1= 1; /* Bilinear Filter*/
}
-void register_node_type_cmp_rotate(bNodeTreeType *ttype)
+void register_node_type_cmp_rotate(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_ROTATE, "Rotate", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_ROTATE, "Rotate", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_rotate_in, cmp_node_rotate_out);
- node_type_size(&ntype, 140, 100, 320);
node_type_init(&ntype, node_composit_init_rotate);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_rotate);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_scale.c b/source/blender/nodes/composite/nodes/node_composite_scale.c
index 2224d653c37..0d8763bf321 100644
--- a/source/blender/nodes/composite/nodes/node_composite_scale.c
+++ b/source/blender/nodes/composite/nodes/node_composite_scale.c
@@ -45,157 +45,12 @@ static bNodeSocketTemplate cmp_node_scale_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-/* only supports RGBA nodes now */
-/* node->custom1 stores if input values are absolute or relative scale */
-static void node_composit_exec_scale(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
-{
- if (out[0]->hasoutput == 0)
- return;
-
- if (in[0]->data) {
- RenderData *rd = data;
- CompBuf *stackbuf, *cbuf = typecheck_compbuf(in[0]->data, CB_RGBA);
- ImBuf *ibuf;
- int newx, newy;
- float ofsx = 0.0f, ofsy = 0.0f;
-
- if (node->custom1 == CMP_SCALE_RELATIVE) {
- newx = MAX2((int)(in[1]->vec[0] * cbuf->x), 1);
- newy = MAX2((int)(in[2]->vec[0] * cbuf->y), 1);
- }
- else if (node->custom1 == CMP_SCALE_SCENEPERCENT) {
- newx = cbuf->x * (rd->size / 100.0f);
- newy = cbuf->y * (rd->size / 100.0f);
- }
- else if (node->custom1 == CMP_SCALE_RENDERPERCENT) {
-
- if (node->custom3 != 0.0f || node->custom4 != 0.0f) {
- const float w_dst = (rd->xsch * rd->size) / 100;
- const float h_dst = (rd->ysch * rd->size) / 100;
-
- if (w_dst > h_dst) {
- ofsx = node->custom3 * w_dst;
- ofsy = node->custom4 * w_dst;
- }
- else {
- ofsx = node->custom3 * h_dst;
- ofsy = node->custom4 * h_dst;
- }
- }
-
- /* supports framing options */
- if (node->custom2 & CMP_SCALE_RENDERSIZE_FRAME_ASPECT) {
- /* apply aspect from clip */
- const float w_src = cbuf->x;
- const float h_src = cbuf->y;
-
- /* destination aspect is already applied from the camera frame */
- const float w_dst = (rd->xsch * rd->size) / 100;
- const float h_dst = (rd->ysch * rd->size) / 100;
-
- const float asp_src = w_src / h_src;
- const float asp_dst = w_dst / h_dst;
-
- if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) {
- if ((asp_src > asp_dst) == ((node->custom2 & CMP_SCALE_RENDERSIZE_FRAME_CROP) != 0)) {
- /* fit X */
- const float div = asp_src / asp_dst;
- newx = w_dst * div;
- newy = h_dst;
- }
- else {
- /* fit Y */
- const float div = asp_dst / asp_src;
- newx = w_dst;
- newy = h_dst * div;
- }
- }
- else {
- /* same as below - no aspect correction needed */
- newx = w_dst;
- newy = h_dst;
- }
- }
- else {
- /* stretch */
- newx = (rd->xsch * rd->size) / 100;
- newy = (rd->ysch * rd->size) / 100;
- }
- }
- else { /* CMP_SCALE_ABSOLUTE */
- newx = MAX2((int)in[1]->vec[0], 1);
- newy = MAX2((int)in[2]->vec[0], 1);
- }
- newx = MIN2(newx, CMP_SCALE_MAX);
- newy = MIN2(newy, CMP_SCALE_MAX);
-
- ibuf = IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0);
- if (ibuf) {
- ibuf->rect_float = cbuf->rect;
- IMB_scaleImBuf(ibuf, newx, newy);
-
- if (ibuf->rect_float == cbuf->rect) {
- /* no scaling happened. */
- stackbuf = pass_on_compbuf(in[0]->data);
- }
- else {
- stackbuf = alloc_compbuf(newx, newy, CB_RGBA, 0);
- stackbuf->rect = ibuf->rect_float;
- stackbuf->malloc = 1;
- }
-
- ibuf->rect_float = NULL;
- ibuf->mall &= ~IB_rectfloat;
- IMB_freeImBuf(ibuf);
-
- /* also do the translation vector */
- stackbuf->xof = (int)(ofsx + (((float)newx / (float)cbuf->x) * (float)cbuf->xof));
- stackbuf->yof = (int)(ofsy + (((float)newy / (float)cbuf->y) * (float)cbuf->yof));
- }
- else {
- stackbuf = dupalloc_compbuf(cbuf);
- printf("Scaling to %dx%d failed\n", newx, newy);
- }
-
- out[0]->data = stackbuf;
- if (cbuf != in[0]->data)
- free_compbuf(cbuf);
- }
- else if (node->custom1 == CMP_SCALE_ABSOLUTE) {
- CompBuf *stackbuf;
- int a, x, y;
- float *fp;
-
- x = MAX2((int)in[1]->vec[0], 1);
- y = MAX2((int)in[2]->vec[0], 1);
-
- stackbuf = alloc_compbuf(x, y, CB_RGBA, 1);
- fp = stackbuf->rect;
-
- a = stackbuf->x * stackbuf->y;
- while (a--) {
- copy_v4_v4(fp, in[0]->vec);
- fp += 4;
- }
-
- out[0]->data = stackbuf;
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_scale(bNodeTreeType *ttype)
+void register_node_type_cmp_scale(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_SCALE, "Scale", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_SCALE, "Scale", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_scale_in, cmp_node_scale_out);
- node_type_size(&ntype, 140, 100, 320);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_scale);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c
index f1a75493718..9aa64138cd6 100644
--- a/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c
+++ b/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c
@@ -46,75 +46,14 @@ static bNodeSocketTemplate cmp_node_sephsva_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_sephsva(bNode *UNUSED(node), float *out, float *in)
-{
- float h, s, v;
-
- rgb_to_hsv(in[0], in[1], in[2], &h, &s, &v);
-
- out[0] = h;
- out[1] = s;
- out[2] = v;
- out[3] = in[3];
-}
-
-static void node_composit_exec_sephsva(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order out: bw channels */
- /* stack order in: col */
-
- /* input no image? then only color operation */
- if (in[0]->data==NULL) {
- float h, s, v;
-
- rgb_to_hsv(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &h, &s, &v);
-
- out[0]->vec[0] = h;
- out[1]->vec[0] = s;
- out[2]->vec[0] = v;
- out[3]->vec[0] = in[0]->vec[3];
- }
- else if ((out[0]->hasoutput) || (out[1]->hasoutput) || (out[2]->hasoutput) || (out[3]->hasoutput)) {
- /* create new buffer so input buffer doesn't get corrupted */
- CompBuf *cbuf= dupalloc_compbuf(in[0]->data);
- CompBuf *cbuf2= typecheck_compbuf(cbuf, CB_RGBA);
-
- /* convert the RGB stackbuf to an HSV representation */
- composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sephsva, CB_RGBA);
-
- /* separate each of those channels */
- if (out[0]->hasoutput)
- out[0]->data= valbuf_from_rgbabuf(cbuf2, CHAN_R);
- if (out[1]->hasoutput)
- out[1]->data= valbuf_from_rgbabuf(cbuf2, CHAN_G);
- if (out[2]->hasoutput)
- out[2]->data= valbuf_from_rgbabuf(cbuf2, CHAN_B);
- if (out[3]->hasoutput)
- out[3]->data= valbuf_from_rgbabuf(cbuf2, CHAN_A);
-
- /*not used anymore */
- if (cbuf2!=cbuf)
- free_compbuf(cbuf2);
- free_compbuf(cbuf);
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_sephsva(bNodeTreeType *ttype)
+void register_node_type_cmp_sephsva(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_SEPHSVA, "Separate HSVA", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_SEPHSVA, "Separate HSVA", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, cmp_node_sephsva_in, cmp_node_sephsva_out);
- node_type_size(&ntype, 80, 40, 140);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_sephsva);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -131,63 +70,12 @@ static bNodeSocketTemplate cmp_node_combhsva_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_comb_hsva(bNode *UNUSED(node), float *out, float *in1, float *in2, float *in3, float *in4)
-{
- float r, g, b;
- hsv_to_rgb(in1[0], in2[0], in3[0], &r, &g, &b);
-
- out[0] = r;
- out[1] = g;
- out[2] = b;
- out[3] = in4[0];
-}
-
-static void node_composit_exec_combhsva(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order out: 1 rgba channels */
- /* stack order in: 4 value channels */
-
- /* input no image? then only color operation in HSV */
- if ((in[0]->data==NULL) && (in[1]->data==NULL) && (in[2]->data==NULL) && (in[3]->data==NULL)) {
- hsv_to_rgb(in[0]->vec[0], in[1]->vec[0], in[2]->vec[0],
- &out[0]->vec[0], &out[0]->vec[1], &out[0]->vec[2]);
- out[0]->vec[3] = in[3]->vec[0];
- }
- else {
- /* make output size of first available input image */
- CompBuf *cbuf;
- CompBuf *stackbuf;
-
- /* allocate a CompBuf the size of the first available input */
- if (in[0]->data) cbuf = in[0]->data;
- else if (in[1]->data) cbuf = in[1]->data;
- else if (in[2]->data) cbuf = in[2]->data;
- else cbuf = in[3]->data;
-
- stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
-
- composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec,
- in[2]->data, in[2]->vec, in[3]->data, in[3]->vec,
- do_comb_hsva, CB_VAL, CB_VAL, CB_VAL, CB_VAL);
-
- out[0]->data= stackbuf;
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_combhsva(bNodeTreeType *ttype)
+void register_node_type_cmp_combhsva(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_COMBHSVA, "Combine HSVA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_COMBHSVA, "Combine HSVA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_combhsva_in, cmp_node_combhsva_out);
- node_type_size(&ntype, 80, 40, 140);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_combhsva);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c
index 83b2c731020..603cc01c259 100644
--- a/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c
+++ b/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c
@@ -45,54 +45,14 @@ static bNodeSocketTemplate cmp_node_seprgba_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void node_composit_exec_seprgba(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out)
-{
- /* stack order out: bw channels */
- /* stack order in: col */
-
- /* input no image? then only color operation */
- if (in[0]->data==NULL) {
- out[0]->vec[0] = in[0]->vec[0];
- out[1]->vec[0] = in[0]->vec[1];
- out[2]->vec[0] = in[0]->vec[2];
- out[3]->vec[0] = in[0]->vec[3];
- }
- else {
- /* make sure we get right rgba buffer */
- CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
-
- /* don't do any pixel processing, just copy the stack directly (faster, I presume) */
- if (out[0]->hasoutput)
- out[0]->data= valbuf_from_rgbabuf(cbuf, CHAN_R);
- if (out[1]->hasoutput)
- out[1]->data= valbuf_from_rgbabuf(cbuf, CHAN_G);
- if (out[2]->hasoutput)
- out[2]->data= valbuf_from_rgbabuf(cbuf, CHAN_B);
- if (out[3]->hasoutput)
- out[3]->data= valbuf_from_rgbabuf(cbuf, CHAN_A);
-
- if (cbuf!=in[0]->data)
- free_compbuf(cbuf);
-
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_seprgba(bNodeTreeType *ttype)
+void register_node_type_cmp_seprgba(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_SEPRGBA, "Separate RGBA", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_SEPRGBA, "Separate RGBA", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, cmp_node_seprgba_in, cmp_node_seprgba_out);
- node_type_size(&ntype, 80, 40, 140);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_seprgba);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -110,61 +70,12 @@ static bNodeSocketTemplate cmp_node_combrgba_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_combrgba(bNode *UNUSED(node), float *out, float *in1, float *in2, float *in3, float *in4)
-{
- out[0] = in1[0];
- out[1] = in2[0];
- out[2] = in3[0];
- out[3] = in4[0];
-}
-
-static void node_composit_exec_combrgba(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order out: 1 rgba channels */
- /* stack order in: 4 value channels */
-
- /* input no image? then only color operation */
- if ((in[0]->data==NULL) && (in[1]->data==NULL) && (in[2]->data==NULL) && (in[3]->data==NULL)) {
- out[0]->vec[0] = in[0]->vec[0];
- out[0]->vec[1] = in[1]->vec[0];
- out[0]->vec[2] = in[2]->vec[0];
- out[0]->vec[3] = in[3]->vec[0];
- }
- else {
- /* make output size of first available input image */
- CompBuf *cbuf;
- CompBuf *stackbuf;
-
- /* allocate a CompBuf the size of the first available input */
- if (in[0]->data) cbuf = in[0]->data;
- else if (in[1]->data) cbuf = in[1]->data;
- else if (in[2]->data) cbuf = in[2]->data;
- else cbuf = in[3]->data;
-
- stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
-
- composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec,
- in[2]->data, in[2]->vec, in[3]->data, in[3]->vec,
- do_combrgba, CB_VAL, CB_VAL, CB_VAL, CB_VAL);
-
- out[0]->data= stackbuf;
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_combrgba(bNodeTreeType *ttype)
+void register_node_type_cmp_combrgba(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_COMBRGBA, "Combine RGBA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_COMBRGBA, "Combine RGBA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_combrgba_in, cmp_node_combrgba_out);
- node_type_size(&ntype, 80, 40, 140);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_combrgba);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c
index 982d674708c..cae70efc85d 100644
--- a/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c
+++ b/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c
@@ -46,122 +46,15 @@ static bNodeSocketTemplate cmp_node_sepycca_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-static void do_sepycca_601(bNode *UNUSED(node), float *out, float *in)
-{
- float y, cb, cr;
-
- rgb_to_ycc(in[0], in[1], in[2], &y, &cb, &cr, BLI_YCC_ITU_BT601);
-
- /*divided by 255 to normalize for viewing in */
- out[0] = y/255.0f;
- out[1] = cb/255.0f;
- out[2] = cr/255.0f;
- out[3] = in[3];
-}
-
-static void do_sepycca_709(bNode *UNUSED(node), float *out, float *in)
-{
- float y, cb, cr;
-
- rgb_to_ycc(in[0], in[1], in[2], &y, &cb, &cr, BLI_YCC_ITU_BT709);
-
- /*divided by 255 to normalize for viewing in */
- out[0] = y/255.0f;
- out[1] = cb/255.0f;
- out[2] = cr/255.0f;
- out[3] = in[3];
-}
-
-static void do_sepycca_jfif(bNode *UNUSED(node), float *out, float *in)
-{
- float y, cb, cr;
-
- rgb_to_ycc(in[0], in[1], in[2], &y, &cb, &cr, BLI_YCC_JFIF_0_255);
-
- /*divided by 255 to normalize for viewing in */
- out[0] = y/255.0f;
- out[1] = cb/255.0f;
- out[2] = cr/255.0f;
- out[3] = in[3];
-}
-
-static void node_composit_exec_sepycca(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* input no image? then only color operation */
- if (in[0]->data==NULL) {
- float y, cb, cr;
-
- switch (node->custom1) {
- case 1:
- rgb_to_ycc(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &cb, &cr, BLI_YCC_ITU_BT709);
- break;
- case 2:
- rgb_to_ycc(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &cb, &cr, BLI_YCC_JFIF_0_255);
- break;
- case 0:
- default:
- rgb_to_ycc(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &cb, &cr, BLI_YCC_ITU_BT601);
- break;
- }
-
- /*divided by 255 to normalize for viewing in */
- out[0]->vec[0] = y/255.0f;
- out[1]->vec[0] = cb/255.0f;
- out[2]->vec[0] = cr/255.0f;
- out[3]->vec[0] = in[0]->vec[3];
- }
- else if ((out[0]->hasoutput) || (out[1]->hasoutput) || (out[2]->hasoutput) || (out[3]->hasoutput)) {
- /* make copy of buffer so input buffer doesn't get corrupted */
- CompBuf *cbuf= dupalloc_compbuf(in[0]->data);
- CompBuf *cbuf2=typecheck_compbuf(cbuf, CB_RGBA);
-
- /* convert the RGB stackbuf to an HSV representation */
- switch (node->custom1) {
- case 1:
- composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sepycca_709, CB_RGBA);
- break;
- case 2:
- composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sepycca_jfif, CB_RGBA);
- break;
- case 0:
- default:
- composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sepycca_601, CB_RGBA);
- break;
- }
-
- /* separate each of those channels */
- if (out[0]->hasoutput)
- out[0]->data= valbuf_from_rgbabuf(cbuf2, CHAN_R);
- if (out[1]->hasoutput)
- out[1]->data= valbuf_from_rgbabuf(cbuf2, CHAN_G);
- if (out[2]->hasoutput)
- out[2]->data= valbuf_from_rgbabuf(cbuf2, CHAN_B);
- if (out[3]->hasoutput)
- out[3]->data= valbuf_from_rgbabuf(cbuf2, CHAN_A);
-
- /*not used anymore */
- if (cbuf2!=cbuf)
- free_compbuf(cbuf2);
- free_compbuf(cbuf);
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_sepycca(bNodeTreeType *ttype)
+void register_node_type_cmp_sepycca(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_SEPYCCA, "Separate YCbCrA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_SEPYCCA, "Separate YCbCrA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_sepycca_in, cmp_node_sepycca_out);
- node_type_size(&ntype, 80, 40, 140);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_sepycca);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -179,138 +72,12 @@ static bNodeSocketTemplate cmp_node_combycca_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_comb_ycca_601(bNode *UNUSED(node), float *out, float *in1, float *in2, float *in3, float *in4)
-{
- float r, g, b;
- float y, cb, cr;
-
- /*need to un-normalize the data*/
- y=in1[0]*255;
- cb=in2[0]*255;
- cr=in3[0]*255;
-
- ycc_to_rgb(y, cb, cr, &r, &g, &b, BLI_YCC_ITU_BT601);
-
- out[0] = r;
- out[1] = g;
- out[2] = b;
- out[3] = in4[0];
-}
-
-static void do_comb_ycca_709(bNode *UNUSED(node), float *out, float *in1, float *in2, float *in3, float *in4)
-{
- float r, g, b;
- float y, cb, cr;
-
- /*need to un-normalize the data*/
- y=in1[0]*255;
- cb=in2[0]*255;
- cr=in3[0]*255;
-
- ycc_to_rgb(y, cb, cr, &r, &g, &b, BLI_YCC_ITU_BT709);
-
- out[0] = r;
- out[1] = g;
- out[2] = b;
- out[3] = in4[0];
-}
-
-static void do_comb_ycca_jfif(bNode *UNUSED(node), float *out, float *in1, float *in2, float *in3, float *in4)
-{
- float r, g, b;
- float y, cb, cr;
-
- /*need to un-normalize the data*/
- y=in1[0]*255;
- cb=in2[0]*255;
- cr=in3[0]*255;
-
- ycc_to_rgb(y, cb, cr, &r, &g, &b, BLI_YCC_JFIF_0_255);
-
- out[0] = r;
- out[1] = g;
- out[2] = b;
- out[3] = in4[0];
-}
-
-static void node_composit_exec_combycca(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order out: 1 ycca channels */
- /* stack order in: 4 value channels */
-
- /* input no image? then only color operation */
- if ((in[0]->data==NULL) && (in[1]->data==NULL) && (in[2]->data==NULL) && (in[3]->data==NULL)) {
- float y = in[0]->vec[0] * 255;
- float cb = in[1]->vec[0] * 255;
- float cr = in[2]->vec[0] * 255;
-
- switch (node->custom1) {
- case 1:
- ycc_to_rgb(y, cb, cr, &out[0]->vec[0], &out[0]->vec[1], &out[0]->vec[2], BLI_YCC_ITU_BT709);
- break;
- case 2:
- ycc_to_rgb(y, cb, cr, &out[0]->vec[0], &out[0]->vec[1], &out[0]->vec[2], BLI_YCC_JFIF_0_255);
- break;
- case 0:
- default:
- ycc_to_rgb(y, cb, cr, &out[0]->vec[0], &out[0]->vec[1], &out[0]->vec[2], BLI_YCC_ITU_BT601);
- break;
- }
-
- out[0]->vec[3] = in[3]->vec[0];
- }
- else {
- /* make output size of first available input image */
- CompBuf *cbuf;
- CompBuf *stackbuf;
-
- /* allocate a CompBuf the size of the first available input */
- if (in[0]->data) cbuf = in[0]->data;
- else if (in[1]->data) cbuf = in[1]->data;
- else if (in[2]->data) cbuf = in[2]->data;
- else cbuf = in[3]->data;
-
- stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
-
-
- switch (node->custom1) {
- case 1:
- composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec,
- in[2]->data, in[2]->vec, in[3]->data, in[3]->vec,
- do_comb_ycca_709, CB_VAL, CB_VAL, CB_VAL, CB_VAL);
- break;
-
- case 2:
- composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec,
- in[2]->data, in[2]->vec, in[3]->data, in[3]->vec,
- do_comb_ycca_jfif, CB_VAL, CB_VAL, CB_VAL, CB_VAL);
- break;
- case 0:
- default:
- composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec,
- in[2]->data, in[2]->vec, in[3]->data, in[3]->vec,
- do_comb_ycca_601, CB_VAL, CB_VAL, CB_VAL, CB_VAL);
- break;
- }
-
- out[0]->data= stackbuf;
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_combycca(bNodeTreeType *ttype)
+void register_node_type_cmp_combycca(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_COMBYCCA, "Combine YCbCrA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_COMBYCCA, "Combine YCbCrA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_combycca_in, cmp_node_combycca_out);
- node_type_size(&ntype, 80, 40, 140);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_combycca);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c
index 0a9575971b4..74c840adef1 100644
--- a/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c
+++ b/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c
@@ -46,76 +46,14 @@ static bNodeSocketTemplate cmp_node_sepyuva_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_sepyuva(bNode *UNUSED(node), float *out, float *in)
-{
- float y, u, v;
-
- rgb_to_yuv(in[0], in[1], in[2], &y, &u, &v);
-
- out[0] = y;
- out[1] = u;
- out[2] = v;
- out[3] = in[3];
-}
-
-static void node_composit_exec_sepyuva(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order out: bw channels */
- /* stack order in: col */
-
- /* input no image? then only color operation */
- if (in[0]->data==NULL) {
- float y, u, v;
-
- rgb_to_yuv(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &u, &v);
-
- out[0]->vec[0] = y;
- out[1]->vec[0] = u;
- out[2]->vec[0] = v;
- out[3]->vec[0] = in[0]->vec[3];
- }
- else if ((out[0]->hasoutput) || (out[1]->hasoutput) || (out[2]->hasoutput) || (out[3]->hasoutput)) {
- /* make copy of buffer so input image doesn't get corrupted */
- CompBuf *cbuf= dupalloc_compbuf(in[0]->data);
- CompBuf *cbuf2=typecheck_compbuf(cbuf, CB_RGBA);
-
- /* convert the RGB stackbuf to an YUV representation */
- composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sepyuva, CB_RGBA);
-
- /* separate each of those channels */
- if (out[0]->hasoutput)
- out[0]->data= valbuf_from_rgbabuf(cbuf2, CHAN_R);
- if (out[1]->hasoutput)
- out[1]->data= valbuf_from_rgbabuf(cbuf2, CHAN_G);
- if (out[2]->hasoutput)
- out[2]->data= valbuf_from_rgbabuf(cbuf2, CHAN_B);
- if (out[3]->hasoutput)
- out[3]->data= valbuf_from_rgbabuf(cbuf2, CHAN_A);
-
- /*not used anymore */
- if (cbuf2!=cbuf)
- free_compbuf(cbuf2);
- free_compbuf(cbuf);
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-
-void register_node_type_cmp_sepyuva(bNodeTreeType *ttype)
+void register_node_type_cmp_sepyuva(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_SEPYUVA, "Separate YUVA", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_SEPYUVA, "Separate YUVA", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, cmp_node_sepyuva_in, cmp_node_sepyuva_out);
- node_type_size(&ntype, 80, 40, 140);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_sepyuva);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -133,64 +71,12 @@ static bNodeSocketTemplate cmp_node_combyuva_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_comb_yuva(bNode *UNUSED(node), float *out, float *in1, float *in2, float *in3, float *in4)
-{
- float r, g, b;
- yuv_to_rgb(in1[0], in2[0], in3[0], &r, &g, &b);
-
- out[0] = r;
- out[1] = g;
- out[2] = b;
- out[3] = in4[0];
-}
-
-static void node_composit_exec_combyuva(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order out: 1 rgba channels */
- /* stack order in: 4 value channels */
-
- /* input no image? then only color operation */
- if ((in[0]->data==NULL) && (in[1]->data==NULL) && (in[2]->data==NULL) && (in[3]->data==NULL)) {
- out[0]->vec[0] = in[0]->vec[0];
- out[0]->vec[1] = in[1]->vec[0];
- out[0]->vec[2] = in[2]->vec[0];
- out[0]->vec[3] = in[3]->vec[0];
- }
- else {
- /* make output size of first available input image */
- CompBuf *cbuf;
- CompBuf *stackbuf;
-
- /* allocate a CompBuf the size of the first available input */
- if (in[0]->data) cbuf = in[0]->data;
- else if (in[1]->data) cbuf = in[1]->data;
- else if (in[2]->data) cbuf = in[2]->data;
- else cbuf = in[3]->data;
-
- stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
-
- composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec,
- in[2]->data, in[2]->vec, in[3]->data, in[3]->vec,
- do_comb_yuva, CB_VAL, CB_VAL, CB_VAL, CB_VAL);
-
- out[0]->data= stackbuf;
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_combyuva(bNodeTreeType *ttype)
+void register_node_type_cmp_combyuva(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_COMBYUVA, "Combine YUVA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_COMBYUVA, "Combine YUVA", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_combyuva_in, cmp_node_combyuva_out);
- node_type_size(&ntype, 80, 40, 140);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_combyuva);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_setalpha.c b/source/blender/nodes/composite/nodes/node_composite_setalpha.c
index 59c104869fe..a162936c9a2 100644
--- a/source/blender/nodes/composite/nodes/node_composite_setalpha.c
+++ b/source/blender/nodes/composite/nodes/node_composite_setalpha.c
@@ -43,51 +43,12 @@ static bNodeSocketTemplate cmp_node_setalpha_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void node_composit_exec_setalpha(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order out: RGBA image */
- /* stack order in: col, alpha */
-
- /* input no image? then only color operation */
- if (in[0]->data==NULL && in[1]->data==NULL) {
- out[0]->vec[0] = in[0]->vec[0];
- out[0]->vec[1] = in[0]->vec[1];
- out[0]->vec[2] = in[0]->vec[2];
- out[0]->vec[3] = in[1]->vec[0];
- }
- else {
- /* make output size of input image */
- CompBuf *cbuf= in[0]->data?in[0]->data:in[1]->data;
- CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
-
- if (in[1]->data==NULL && in[1]->vec[0]==1.0f) {
- /* pass on image */
- composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_copy_rgb, CB_RGBA);
- }
- else {
- /* send an compbuf or a value to set as alpha - composit2_pixel_processor handles choosing the right one */
- composit2_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba, CB_RGBA, CB_VAL);
- }
-
- out[0]->data= stackbuf;
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-
-void register_node_type_cmp_setalpha(bNodeTreeType *ttype)
+void register_node_type_cmp_setalpha(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_SETALPHA, "Set Alpha", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_SETALPHA, "Set Alpha", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_setalpha_in, cmp_node_setalpha_out);
- node_type_size(&ntype, 120, 40, 140);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_setalpha);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_splitViewer.c b/source/blender/nodes/composite/nodes/node_composite_splitViewer.c
index 41fb0e822ed..7cb1cf1d65d 100644
--- a/source/blender/nodes/composite/nodes/node_composite_splitViewer.c
+++ b/source/blender/nodes/composite/nodes/node_composite_splitViewer.c
@@ -39,111 +39,7 @@ static bNodeSocketTemplate cmp_node_splitviewer_in[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_copy_split_rgba(bNode *UNUSED(node), float *out, float *in1, float *in2, float *fac)
-{
- if (*fac==0.0f) {
- copy_v4_v4(out, in1);
- }
- else {
- copy_v4_v4(out, in2);
- }
-}
-
-static void node_composit_exec_splitviewer(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
-{
- /* image assigned to output */
- /* stack order input sockets: image image */
-
- if (in[0]->data==NULL || in[1]->data==NULL)
- return;
-
- if (node->id && (node->flag & NODE_DO_OUTPUT)) { /* only one works on out */
- Image *ima= (Image *)node->id;
- RenderData *rd= data;
- ImBuf *ibuf;
- CompBuf *cbuf, *buf1, *buf2, *mask;
- int x, y;
- float offset;
- void *lock;
-
- buf1= typecheck_compbuf(in[0]->data, CB_RGBA);
- buf2= typecheck_compbuf(in[1]->data, CB_RGBA);
-
- BKE_image_user_frame_calc(node->storage, rd->cfra, 0);
-
- /* always returns for viewer image, but we check nevertheless */
- ibuf= BKE_image_acquire_ibuf(ima, node->storage, &lock);
- if (ibuf==NULL) {
- printf("node_composit_exec_viewer error\n");
- BKE_image_release_ibuf(ima, ibuf, lock);
- return;
- }
-
- /* free all in ibuf */
- imb_freerectImBuf(ibuf);
- imb_freerectfloatImBuf(ibuf);
- IMB_freezbuffloatImBuf(ibuf);
-
- /* make ibuf, and connect to ima */
- ibuf->x= buf1->x;
- ibuf->y= buf1->y;
- imb_addrectfloatImBuf(ibuf);
-
- ima->ok= IMA_OK_LOADED;
-
- /* output buf */
- cbuf= alloc_compbuf(buf1->x, buf1->y, CB_RGBA, 0); /* no alloc*/
- cbuf->rect= ibuf->rect_float;
-
- /* mask buf */
- mask= alloc_compbuf(buf1->x, buf1->y, CB_VAL, 1);
-
-
- /* Check which offset mode is selected and limit offset if needed */
- if (node->custom2 == 0) {
- offset = buf1->x / 100.0f * node->custom1;
- CLAMP(offset, 0, buf1->x);
- }
- else {
- offset = buf1->y / 100.0f * node->custom1;
- CLAMP(offset, 0, buf1->y);
- }
-
- if (node->custom2 == 0) {
- for (y=0; y<buf1->y; y++) {
- float *fac= mask->rect + y*buf1->x;
- for (x=offset; x>0; x--, fac++)
- *fac= 1.0f;
- }
- }
- else {
- for (y=0; y<offset; y++) {
- float *fac= mask->rect + y*buf1->x;
- for (x=buf1->x; x>0; x--, fac++)
- *fac= 1.0f;
- }
- }
-
- composit3_pixel_processor(node, cbuf, buf1, in[0]->vec, buf2, in[1]->vec, mask, NULL, do_copy_split_rgba, CB_RGBA, CB_RGBA, CB_VAL);
-
- BKE_image_release_ibuf(ima, ibuf, lock);
-
- generate_preview(data, node, cbuf);
- free_compbuf(cbuf);
- free_compbuf(mask);
-
- if (in[0]->data != buf1)
- free_compbuf(buf1);
- if (in[1]->data != buf2)
- free_compbuf(buf2);
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_splitviewer(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_splitviewer(bNodeTree *UNUSED(ntree), bNode *node)
{
ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
node->storage= iuser;
@@ -153,21 +49,17 @@ static void node_composit_init_splitviewer(bNodeTree *UNUSED(ntree), bNode *node
node->custom1= 50; /* default 50% split */
}
-void register_node_type_cmp_splitviewer(bNodeTreeType *ttype)
+void register_node_type_cmp_splitviewer(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_SPLITVIEWER, "SplitViewer", NODE_CLASS_OUTPUT, NODE_PREVIEW|NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_SPLITVIEWER, "Split Viewer", NODE_CLASS_OUTPUT, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_splitviewer_in, NULL);
- node_type_size(&ntype, 140, 100, 320);
node_type_init(&ntype, node_composit_init_splitviewer);
node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_splitviewer);
-#endif
/* Do not allow muting for this node. */
node_type_internal_links(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
index 1787e075a14..3b85b4a6b8c 100644
--- a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
+++ b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
@@ -45,42 +45,12 @@ static bNodeSocketTemplate cmp_node_stabilize2d_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void node_composit_exec_stabilize2d(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
-{
- if (in[0]->data && node->id) {
- RenderData *rd = data;
- MovieClip *clip = (MovieClip *)node->id;
- CompBuf *cbuf = typecheck_compbuf(in[0]->data, CB_RGBA);
- CompBuf *stackbuf;
- float loc[2], scale, angle;
- int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, rd->cfra);
-
- BKE_tracking_stabilization_data_get(&clip->tracking, clip_framenr, cbuf->x, cbuf->y, loc, &scale, &angle);
-
- stackbuf = node_composit_transform(cbuf, loc[0], loc[1], angle, scale, node->custom1);
-
- /* pass on output and free */
- out[0]->data = stackbuf;
-
- if (cbuf != in[0]->data)
- free_compbuf(cbuf);
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_stabilize2d(bNodeTreeType *ttype)
+void register_node_type_cmp_stabilize2d(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_STABILIZE2D, "Stabilize 2D", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_STABILIZE2D, "Stabilize 2D", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_stabilize2d_in, cmp_node_stabilize2d_out);
- node_type_size(&ntype, 140, 100, 320);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_stabilize2d);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_switch.c b/source/blender/nodes/composite/nodes/node_composite_switch.c
index 7f9127c969f..a6254de62d5 100644
--- a/source/blender/nodes/composite/nodes/node_composite_switch.c
+++ b/source/blender/nodes/composite/nodes/node_composite_switch.c
@@ -46,13 +46,13 @@ static bNodeSocketTemplate cmp_node_switch_out[] = {
};
/* custom1 = mix type */
-void register_node_type_cmp_switch(bNodeTreeType *ttype)
+void register_node_type_cmp_switch(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_SWITCH, "Switch", NODE_CLASS_LAYOUT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_SWITCH, "Switch", NODE_CLASS_LAYOUT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_switch_in, cmp_node_switch_out);
- node_type_size(&ntype, 110, 60, 120);
- nodeRegisterType(ttype, &ntype);
+ node_type_size_preset(&ntype, NODE_SIZE_SMALL);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_texture.c b/source/blender/nodes/composite/nodes/node_composite_texture.c
index b6518c48638..320b8f6aabe 100644
--- a/source/blender/nodes/composite/nodes/node_composite_texture.c
+++ b/source/blender/nodes/composite/nodes/node_composite_texture.c
@@ -44,118 +44,12 @@ static bNodeSocketTemplate cmp_node_texture_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-/* called without rect allocated */
-static void texture_procedural(CompBuf *cbuf, float *out, float xco, float yco)
-{
- bNode *node= cbuf->node;
- TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
- float vec[3], *size, nor[3] = {0.0f, 0.0f, 0.0f}, col[4];
- int retval, type= cbuf->procedural_type;
-
- size= cbuf->procedural_size;
-
- vec[0] = size[0]*(xco + cbuf->procedural_offset[0]);
- vec[1] = size[1]*(yco + cbuf->procedural_offset[1]);
- vec[2] = size[2]*cbuf->procedural_offset[2];
-
- retval= multitex_ext((Tex *)node->id, vec, NULL, NULL, 0, &texres);
-
- if (type==CB_VAL) {
- if (texres.talpha)
- col[0] = texres.ta;
- else
- col[0] = texres.tin;
- }
- else if (type==CB_RGBA) {
- if (texres.talpha)
- col[3] = texres.ta;
- else
- col[3] = texres.tin;
-
- if ((retval & TEX_RGB)) {
- copy_v3_v3(col, &texres.tr);
- }
- else {
- copy_v3_fl(col, col[3]);
- }
- }
- else {
- copy_v3_v3(col, nor);
- }
-
- typecheck_compbuf_color(out, col, cbuf->type, cbuf->procedural_type);
-}
-
-/* texture node outputs get a small rect, to make sure all other nodes accept it */
-/* only the pixel-processor nodes do something with it though */
-static void node_composit_exec_texture(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* outputs: value, color, normal */
-
- if (node->id) {
- RenderData *rd= data;
- short sizex, sizey;
-
- /* first make the preview image */
- CompBuf *prevbuf= alloc_compbuf(140, 140, CB_RGBA, 1); /* alloc */
-
- prevbuf->rect_procedural= texture_procedural;
- prevbuf->node= node;
- copy_v3_v3(prevbuf->procedural_offset, in[0]->vec);
- copy_v3_v3(prevbuf->procedural_size, in[1]->vec);
- prevbuf->procedural_type= CB_RGBA;
- composit1_pixel_processor(node, prevbuf, prevbuf, out[0]->vec, do_copy_rgba, CB_RGBA);
-
- generate_preview(data, node, prevbuf);
- free_compbuf(prevbuf);
-
- /* texture procedural buffer type doesnt work well, we now render a buffer in scene size */
- sizex = (rd->size*rd->xsch)/100;
- sizey = (rd->size*rd->ysch)/100;
-
- if (out[0]->hasoutput) {
- CompBuf *stackbuf= alloc_compbuf(sizex, sizey, CB_VAL, 1); /* alloc */
-
- stackbuf->rect_procedural= texture_procedural;
- stackbuf->node= node;
- copy_v3_v3(stackbuf->procedural_offset, in[0]->vec);
- copy_v3_v3(stackbuf->procedural_size, in[1]->vec);
- stackbuf->procedural_type= CB_VAL;
- composit1_pixel_processor(node, stackbuf, stackbuf, out[0]->vec, do_copy_value, CB_VAL);
- stackbuf->rect_procedural= NULL;
-
- out[0]->data= stackbuf;
- }
- if (out[1]->hasoutput) {
- CompBuf *stackbuf= alloc_compbuf(sizex, sizey, CB_RGBA, 1); /* alloc */
-
- stackbuf->rect_procedural= texture_procedural;
- stackbuf->node= node;
- copy_v3_v3(stackbuf->procedural_offset, in[0]->vec);
- copy_v3_v3(stackbuf->procedural_size, in[1]->vec);
- stackbuf->procedural_type= CB_RGBA;
- composit1_pixel_processor(node, stackbuf, stackbuf, out[0]->vec, do_copy_rgba, CB_RGBA);
- stackbuf->rect_procedural= NULL;
-
- out[1]->data= stackbuf;
- }
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_texture(bNodeTreeType *ttype)
+void register_node_type_cmp_texture(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW);
+ cmp_node_type_base(&ntype, CMP_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW);
node_type_socket_templates(&ntype, cmp_node_texture_in, cmp_node_texture_out);
- node_type_size(&ntype, 120, 80, 240);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_texture);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_tonemap.c b/source/blender/nodes/composite/nodes/node_composite_tonemap.c
index 00b1a5514dc..6f6fbc21a40 100644
--- a/source/blender/nodes/composite/nodes/node_composite_tonemap.c
+++ b/source/blender/nodes/composite/nodes/node_composite_tonemap.c
@@ -41,115 +41,7 @@ static bNodeSocketTemplate cmp_node_tonemap_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static float avgLogLum(CompBuf *src, float* auto_key, float* Lav, float* Cav)
-{
- float lsum = 0;
- int p = src->x*src->y;
- fRGB* bc = (fRGB*)src->rect;
- float avl, maxl = -1e10f, minl = 1e10f;
- const float sc = 1.f/(src->x*src->y);
- *Lav = 0.f;
- while (p--) {
- float L = rgb_to_luma_y(bc[0]);
- *Lav += L;
- add_v3_v3(Cav, bc[0]);
- lsum += (float)log((double)MAX2(L, 0.0) + 1e-5);
- maxl = (L > maxl) ? L : maxl;
- minl = (L < minl) ? L : minl;
- bc++;
- }
- *Lav *= sc;
- mul_v3_fl(Cav, sc);
- maxl = log((double)maxl + 1e-5); minl = log((double)minl + 1e-5f); avl = lsum*sc;
- *auto_key = (maxl > minl) ? ((maxl - avl) / (maxl - minl)) : 1.f;
- return exp((double)avl);
-}
-
-
-static void tonemap(NodeTonemap* ntm, CompBuf* dst, CompBuf* src)
-{
- int x, y;
- float dr, dg, db, al, igm = (ntm->gamma==0.f) ? 1 : (1.f / ntm->gamma);
- float auto_key, Lav, Cav[3] = {0, 0, 0};
-
- al = avgLogLum(src, &auto_key, &Lav, Cav);
- al = (al == 0.f) ? 0.f : (ntm->key / al);
-
- if (ntm->type == 1) {
- // Reinhard/Devlin photoreceptor
- const float f = exp((double)-ntm->f);
- const float m = (ntm->m > 0.f) ? ntm->m : (0.3f + 0.7f*pow((double)auto_key, 1.4));
- const float ic = 1.f - ntm->c, ia = 1.f - ntm->a;
- if (ntm->m == 0.f) printf("tonemap node, M: %g\n", m);
- for (y=0; y<src->y; ++y) {
- fRGB* sp = (fRGB*)&src->rect[y*src->x*src->type];
- fRGB* dp = (fRGB*)&dst->rect[y*src->x*src->type];
- for (x=0; x<src->x; ++x) {
- const float L = rgb_to_luma_y(sp[x]);
- float I_l = sp[x][0] + ic*(L - sp[x][0]);
- float I_g = Cav[0] + ic*(Lav - Cav[0]);
- float I_a = I_l + ia*(I_g - I_l);
- dp[x][0] /= (dp[x][0] + pow((double)f*I_a, (double)m));
- I_l = sp[x][1] + ic*(L - sp[x][1]);
- I_g = Cav[1] + ic*(Lav - Cav[1]);
- I_a = I_l + ia*(I_g - I_l);
- dp[x][1] /= (dp[x][1] + pow((double)f*I_a, (double)m));
- I_l = sp[x][2] + ic*(L - sp[x][2]);
- I_g = Cav[2] + ic*(Lav - Cav[2]);
- I_a = I_l + ia*(I_g - I_l);
- dp[x][2] /= (dp[x][2] + pow((double)f*I_a, (double)m));
- }
- }
- return;
- }
-
- // Reinhard simple photographic tm (simplest, not using whitepoint var)
- for (y=0; y<src->y; y++) {
- fRGB* sp = (fRGB*)&src->rect[y*src->x*src->type];
- fRGB* dp = (fRGB*)&dst->rect[y*src->x*src->type];
- for (x=0; x<src->x; x++) {
- copy_v4_v4(dp[x], sp[x]);
- mul_v3_fl(dp[x], al);
- dr = dp[x][0] + ntm->offset;
- dg = dp[x][1] + ntm->offset;
- db = dp[x][2] + ntm->offset;
- dp[x][0] /= ((dr == 0.f) ? 1.f : dr);
- dp[x][1] /= ((dg == 0.f) ? 1.f : dg);
- dp[x][2] /= ((db == 0.f) ? 1.f : db);
- if (igm != 0.f) {
- dp[x][0] = pow((double)MAX2(dp[x][0], 0.0), igm);
- dp[x][1] = pow((double)MAX2(dp[x][1], 0.0), igm);
- dp[x][2] = pow((double)MAX2(dp[x][2], 0.0), igm);
- }
- }
- }
-}
-
-
-static void node_composit_exec_tonemap(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- CompBuf *new, *img = in[0]->data;
-
- if ((img==NULL) || (out[0]->hasoutput==0)) return;
-
- if (img->type != CB_RGBA)
- img = typecheck_compbuf(img, CB_RGBA);
-
- new = dupalloc_compbuf(img);
-
- tonemap(node->storage, new, img);
-
- out[0]->data = new;
-
- if (img!=in[0]->data)
- free_compbuf(img);
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_tonemap(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_tonemap(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTonemap *ntm = MEM_callocN(sizeof(NodeTonemap), "node tonemap data");
ntm->type = 1;
@@ -165,18 +57,14 @@ static void node_composit_init_tonemap(bNodeTree *UNUSED(ntree), bNode *node, bN
node->storage = ntm;
}
-void register_node_type_cmp_tonemap(bNodeTreeType *ttype)
+void register_node_type_cmp_tonemap(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_TONEMAP, "Tonemap", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_TONEMAP, "Tonemap", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_tonemap_in, cmp_node_tonemap_out);
- node_type_size(&ntype, 150, 120, 200);
node_type_init(&ntype, node_composit_init_tonemap);
node_type_storage(&ntype, "NodeTonemap", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_tonemap);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_trackpos.c b/source/blender/nodes/composite/nodes/node_composite_trackpos.c
index 4364ca61ba1..bc3c54702ac 100644
--- a/source/blender/nodes/composite/nodes/node_composite_trackpos.c
+++ b/source/blender/nodes/composite/nodes/node_composite_trackpos.c
@@ -34,39 +34,26 @@
#include "node_composite_util.h"
static bNodeSocketTemplate cmp_node_trackpos_out[] = {
- { SOCK_FLOAT, 1, N_("X")},
- { SOCK_FLOAT, 1, N_("Y")},
+ { SOCK_FLOAT, 0, N_("X")},
+ { SOCK_FLOAT, 0, N_("Y")},
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void node_composit_exec_trackpos(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **UNUSED(in), bNodeStack **UNUSED(out))
-{
- /* pass */
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTrackPosData *data = MEM_callocN(sizeof(NodeTrackPosData), "node track position data");
node->storage = data;
}
-void register_node_type_cmp_trackpos(bNodeTreeType *ttype)
+void register_node_type_cmp_trackpos(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_TRACKPOS, "Track Position", NODE_CLASS_INPUT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_TRACKPOS, "Track Position", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, cmp_node_trackpos_out);
- node_type_size(&ntype, 120, 80, 300);
node_type_init(&ntype, init);
node_type_storage(&ntype, "NodeTrackPosData", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_trackpos);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_transform.c b/source/blender/nodes/composite/nodes/node_composite_transform.c
index d6bb545cd5c..8dc272adf38 100644
--- a/source/blender/nodes/composite/nodes/node_composite_transform.c
+++ b/source/blender/nodes/composite/nodes/node_composite_transform.c
@@ -48,99 +48,12 @@ static bNodeSocketTemplate cmp_node_transform_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-CompBuf* node_composit_transform(CompBuf *cbuf, float x, float y, float angle, float scale, int filter_type)
-{
- CompBuf *stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, TRUE);
- ImBuf *ibuf, *obuf;
- float mat[4][4], lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4];
- float svec[3] = {scale, scale, scale}, loc[2] = {x, y};
-
- unit_m4(rmat);
- unit_m4(lmat);
- unit_m4(smat);
- unit_m4(cmat);
-
- /* image center as rotation center */
- cmat[3][0] = (float)cbuf->x/2.0f;
- cmat[3][1] = (float)cbuf->y/2.0f;
- invert_m4_m4(icmat, cmat);
-
- size_to_mat4(smat, svec); /* scale matrix */
- add_v2_v2(lmat[3], loc); /* tranlation matrix */
- rotate_m4(rmat, 'Z', angle); /* rotation matrix */
-
- /* compose transformation matrix */
- mul_serie_m4(mat, lmat, cmat, rmat, smat, icmat, NULL, NULL, NULL);
-
- invert_m4(mat);
-
- ibuf = IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0);
- obuf = IMB_allocImBuf(stackbuf->x, stackbuf->y, 32, 0);
-
- if (ibuf && obuf) {
- int i, j;
-
- ibuf->rect_float = cbuf->rect;
- obuf->rect_float = stackbuf->rect;
-
- for (j = 0; j < cbuf->y; j++) {
- for (i = 0; i < cbuf->x; i++) {
- float vec[3] = {i, j, 0};
-
- mul_v3_m4v3(vec, mat, vec);
-
- switch (filter_type) {
- case 0:
- nearest_interpolation(ibuf, obuf, vec[0], vec[1], i, j);
- break;
- case 1:
- bilinear_interpolation(ibuf, obuf, vec[0], vec[1], i, j);
- break;
- case 2:
- bicubic_interpolation(ibuf, obuf, vec[0], vec[1], i, j);
- break;
- }
- }
- }
-
- IMB_freeImBuf(ibuf);
- IMB_freeImBuf(obuf);
- }
-
- /* pass on output and free */
- return stackbuf;
-}
-
-static void node_composit_exec_transform(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- if (in[0]->data) {
- CompBuf *cbuf = typecheck_compbuf(in[0]->data, CB_RGBA);
- CompBuf *stackbuf;
-
- stackbuf = node_composit_transform(cbuf, in[1]->vec[0], in[2]->vec[0], in[3]->vec[0], in[4]->vec[0], node->custom1);
-
- /* pass on output and free */
- out[0]->data = stackbuf;
-
- if (cbuf != in[0]->data)
- free_compbuf(cbuf);
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_transform(bNodeTreeType *ttype)
+void register_node_type_cmp_transform(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_TRANSFORM, "Transform", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_TRANSFORM, "Transform", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_transform_in, cmp_node_transform_out);
- node_type_size(&ntype, 140, 100, 320);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_transform);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_translate.c b/source/blender/nodes/composite/nodes/node_composite_translate.c
index 1c2963a2f08..ae293170004 100644
--- a/source/blender/nodes/composite/nodes/node_composite_translate.c
+++ b/source/blender/nodes/composite/nodes/node_composite_translate.c
@@ -46,33 +46,20 @@ static bNodeSocketTemplate cmp_node_translate_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void node_composit_exec_translate(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out)
+static void node_composit_init_translate(bNodeTree *UNUSED(ntree), bNode *node)
{
- if (in[0]->data) {
- CompBuf *cbuf= in[0]->data;
- CompBuf *stackbuf= pass_on_compbuf(cbuf);
-
- stackbuf->xof+= (int)floor(in[1]->vec[0]);
- stackbuf->yof+= (int)floor(in[2]->vec[0]);
-
- out[0]->data= stackbuf;
- }
+ NodeTranslateData *data = MEM_callocN(sizeof(NodeTranslateData), "node translate data");
+ node->storage = data;
}
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_translate(bNodeTreeType *ttype)
+void register_node_type_cmp_translate(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_TRANSLATE, "Translate", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_TRANSLATE, "Translate", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_translate_in, cmp_node_translate_out);
- node_type_size(&ntype, 140, 100, 320);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_translate);
-#endif
+ node_type_init(&ntype, node_composit_init_translate);
+ node_type_storage(&ntype, "NodeTranslateData", node_free_standard_storage, node_copy_standard_storage);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_valToRgb.c b/source/blender/nodes/composite/nodes/node_composite_valToRgb.c
index 5c111998b18..a1d51bdf171 100644
--- a/source/blender/nodes/composite/nodes/node_composite_valToRgb.c
+++ b/source/blender/nodes/composite/nodes/node_composite_valToRgb.c
@@ -44,63 +44,22 @@ static bNodeSocketTemplate cmp_node_valtorgb_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_colorband_composit(bNode *node, float *out, float *in)
-{
- do_colorband(node->storage, in[0], out);
-}
-
-static void node_composit_exec_valtorgb(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order in: fac */
- /* stack order out: col, alpha */
-
- if (out[0]->hasoutput==0 && out[1]->hasoutput==0)
- return;
-
- if (node->storage) {
- /* input no image? then only color operation */
- if (in[0]->data==NULL) {
- do_colorband(node->storage, in[0]->vec[0], out[0]->vec);
- }
- else {
- /* make output size of input image */
- CompBuf *cbuf= in[0]->data;
- CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
-
- composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_colorband_composit, CB_VAL);
-
- out[0]->data= stackbuf;
-
- if (out[1]->hasoutput)
- out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
-
- }
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_valtorgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_valtorgb(bNodeTree *UNUSED(ntree), bNode *node)
{
- node->storage= add_colorband(1);
+ node->storage= add_colorband(true);
}
-void register_node_type_cmp_valtorgb(bNodeTreeType *ttype)
+void register_node_type_cmp_valtorgb(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_valtorgb_in, cmp_node_valtorgb_out);
- node_type_size(&ntype, 240, 200, 300);
+ node_type_size(&ntype, 240, 200, 320);
node_type_init(&ntype, node_composit_init_valtorgb);
node_type_storage(&ntype, "ColorBand", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_valtorgb);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -115,48 +74,13 @@ static bNodeSocketTemplate cmp_node_rgbtobw_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_rgbtobw(bNode *UNUSED(node), float *out, float *in)
-{
- out[0] = rgb_to_bw(in);
-}
-
-static void node_composit_exec_rgbtobw(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- /* stack order out: bw */
- /* stack order in: col */
-
- if (out[0]->hasoutput==0)
- return;
-
- /* input no image? then only color operation */
- if (in[0]->data==NULL) {
- do_rgbtobw(node, out[0]->vec, in[0]->vec);
- }
- else {
- /* make output size of input image */
- CompBuf *cbuf= in[0]->data;
- CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */
-
- composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_rgbtobw, CB_RGBA);
-
- out[0]->data= stackbuf;
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_rgbtobw(bNodeTreeType *ttype)
+void register_node_type_cmp_rgbtobw(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0);
+ cmp_node_type_base(&ntype, CMP_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, cmp_node_rgbtobw_in, cmp_node_rgbtobw_out);
- node_type_size(&ntype, 80, 40, 120);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_rgbtobw);
-#endif
+ node_type_size_preset(&ntype, NODE_SIZE_SMALL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_value.c b/source/blender/nodes/composite/nodes/node_composite_value.c
index 2c65fe6be19..87c77440985 100644
--- a/source/blender/nodes/composite/nodes/node_composite_value.c
+++ b/source/blender/nodes/composite/nodes/node_composite_value.c
@@ -34,44 +34,17 @@
/* **************** VALUE ******************** */
static bNodeSocketTemplate cmp_node_value_out[] = {
- /* XXX value nodes use the output sockets for buttons, so we need explicit limits here! */
- { SOCK_FLOAT, 0, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ { SOCK_FLOAT, 0, N_("Value"), 0.5f, 0, 0, 0, -FLT_MAX, FLT_MAX, PROP_NONE},
{ -1, 0, "" }
};
-static void node_composit_init_value(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
-{
- bNodeSocket *sock= node->outputs.first;
- bNodeSocketValueFloat *dval= (bNodeSocketValueFloat*)sock->default_value;
- /* uses the default value of the output socket, must be initialized here */
- dval->value = 0.5f;
- dval->min = -FLT_MAX;
- dval->max = FLT_MAX;
-}
-
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void node_composit_exec_value(void *UNUSED(data), bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
-{
- bNodeSocket *sock= node->outputs.first;
- float val= ((bNodeSocketValueFloat*)sock->default_value)->value;
-
- out[0]->vec[0] = val;
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_value(bNodeTreeType *ttype)
+void register_node_type_cmp_value(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_VALUE, "Value", NODE_CLASS_INPUT, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_VALUE, "Value", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, cmp_node_value_out);
- node_type_init(&ntype, node_composit_init_value);
- node_type_size(&ntype, 80, 40, 120);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_value);
-#endif
+ node_type_size_preset(&ntype, NODE_SIZE_SMALL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_vecBlur.c b/source/blender/nodes/composite/nodes/node_composite_vecBlur.c
index 62c2c02836a..b00cfc315b0 100644
--- a/source/blender/nodes/composite/nodes/node_composite_vecBlur.c
+++ b/source/blender/nodes/composite/nodes/node_composite_vecBlur.c
@@ -45,49 +45,7 @@ static bNodeSocketTemplate cmp_node_vecblur_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void node_composit_exec_vecblur(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
-{
- NodeBlurData *nbd = node->storage;
- CompBuf *new, *img = in[0]->data, *vecbuf = in[2]->data, *zbuf = in[1]->data;
-
- if (img == NULL || vecbuf == NULL || zbuf == NULL || out[0]->hasoutput == 0)
- return;
- if (vecbuf->x != img->x || vecbuf->y != img->y) {
- printf("ERROR: cannot do different sized vecbuf yet\n");
- return;
- }
- if (vecbuf->type != CB_VEC4) {
- printf("ERROR: input should be vecbuf\n");
- return;
- }
- if (zbuf->type != CB_VAL) {
- printf("ERROR: input should be zbuf\n");
- return;
- }
- if (zbuf->x != img->x || zbuf->y != img->y) {
- printf("ERROR: cannot do different sized zbuf yet\n");
- return;
- }
-
- /* allow the input image to be of another type */
- img = typecheck_compbuf(in[0]->data, CB_RGBA);
-
- new = dupalloc_compbuf(img);
-
- /* call special zbuffer version */
- RE_zbuf_accumulate_vecblur(nbd, img->x, img->y, new->rect, img->rect, vecbuf->rect, zbuf->rect);
-
- out[0]->data = new;
-
- if (img != in[0]->data)
- free_compbuf(img);
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_vecblur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_vecblur(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeBlurData *nbd = MEM_callocN(sizeof(NodeBlurData), "node blur data");
node->storage = nbd;
@@ -96,18 +54,14 @@ static void node_composit_init_vecblur(bNodeTree *UNUSED(ntree), bNode *node, bN
}
/* custom1: itterations, custom2: maxspeed (0 = nolimit) */
-void register_node_type_cmp_vecblur(bNodeTreeType *ttype)
+void register_node_type_cmp_vecblur(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_VECBLUR, "Vector Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_VECBLUR, "Vector Blur", NODE_CLASS_OP_FILTER, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_vecblur_in, cmp_node_vecblur_out);
- node_type_size(&ntype, 120, 80, 200);
node_type_init(&ntype, node_composit_init_vecblur);
node_type_storage(&ntype, "NodeBlurData", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_vecblur);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_viewer.c b/source/blender/nodes/composite/nodes/node_composite_viewer.c
index 1c27cc21b06..70aae460af7 100644
--- a/source/blender/nodes/composite/nodes/node_composite_viewer.c
+++ b/source/blender/nodes/composite/nodes/node_composite_viewer.c
@@ -41,91 +41,7 @@ static bNodeSocketTemplate cmp_node_viewer_in[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
-{
- /* image assigned to output */
- /* stack order input sockets: col, alpha, z */
-
- if (node->id && (node->flag & NODE_DO_OUTPUT)) { /* only one works on out */
- RenderData *rd = data;
- Image *ima = (Image *)node->id;
- ImBuf *ibuf;
- CompBuf *cbuf, *tbuf;
- int rectx, recty;
- void *lock;
-
- BKE_image_user_frame_calc(node->storage, rd->cfra, 0);
-
- /* always returns for viewer image, but we check nevertheless */
- ibuf = BKE_image_acquire_ibuf(ima, node->storage, &lock);
- if (ibuf == NULL) {
- printf("node_composit_exec_viewer error\n");
- BKE_image_release_ibuf(ima, ibuf, lock);
- return;
- }
-
- /* free all in ibuf */
- imb_freerectImBuf(ibuf);
- imb_freerectfloatImBuf(ibuf);
- IMB_freezbuffloatImBuf(ibuf);
-
- /* get size */
- tbuf = in[0]->data ? in[0]->data : (in[1]->data ? in[1]->data : in[2]->data);
- if (tbuf == NULL) {
- rectx = 320; recty = 256;
- }
- else {
- rectx = tbuf->x;
- recty = tbuf->y;
- }
-
- /* make ibuf, and connect to ima */
- ibuf->x = rectx;
- ibuf->y = recty;
- imb_addrectfloatImBuf(ibuf);
-
- ima->ok = IMA_OK_LOADED;
-
- /* now we combine the input with ibuf */
- cbuf = alloc_compbuf(rectx, recty, CB_RGBA, 0); /* no alloc*/
- cbuf->rect = ibuf->rect_float;
-
- /* when no alpha, we can simply copy */
- if (in[1]->data == NULL) {
- composit1_pixel_processor(node, cbuf, in[0]->data, in[0]->vec, do_copy_rgba, CB_RGBA);
- }
- else
- composit2_pixel_processor(node, cbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba, CB_RGBA, CB_VAL);
-
- /* zbuf option */
- if (in[2]->data) {
- CompBuf *zbuf = alloc_compbuf(rectx, recty, CB_VAL, 1);
- ibuf->zbuf_float = zbuf->rect;
- ibuf->mall |= IB_zbuffloat;
-
- composit1_pixel_processor(node, zbuf, in[2]->data, in[2]->vec, do_copy_value, CB_VAL);
-
- /* free compbuf, but not the rect */
- zbuf->malloc = 0;
- free_compbuf(zbuf);
- }
-
- BKE_image_release_ibuf(ima, ibuf, lock);
-
- generate_preview(data, node, cbuf);
- free_compbuf(cbuf);
-
- }
- else if (in[0]->data) {
- generate_preview(data, node, in[0]->data);
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-static void node_composit_init_viewer(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_composit_init_viewer(bNodeTree *UNUSED(ntree), bNode *node)
{
ImageUser *iuser = MEM_callocN(sizeof(ImageUser), "node image user");
node->storage = iuser;
@@ -136,20 +52,16 @@ static void node_composit_init_viewer(bNodeTree *UNUSED(ntree), bNode *node, bNo
node->custom4 = 0.5f;
}
-void register_node_type_cmp_viewer(bNodeTreeType *ttype)
+void register_node_type_cmp_viewer(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_VIEWER, "Viewer", NODE_CLASS_OUTPUT, NODE_PREVIEW);
+ cmp_node_type_base(&ntype, CMP_NODE_VIEWER, "Viewer", NODE_CLASS_OUTPUT, NODE_OPTIONS | NODE_PREVIEW);
node_type_socket_templates(&ntype, cmp_node_viewer_in, NULL);
- node_type_size(&ntype, 80, 60, 200);
node_type_init(&ntype, node_composit_init_viewer);
node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_viewer);
-#endif
node_type_internal_links(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_zcombine.c b/source/blender/nodes/composite/nodes/node_composite_zcombine.c
index 8e639aaa357..6e5f38e1fab 100644
--- a/source/blender/nodes/composite/nodes/node_composite_zcombine.c
+++ b/source/blender/nodes/composite/nodes/node_composite_zcombine.c
@@ -48,193 +48,12 @@ static bNodeSocketTemplate cmp_node_zcombine_out[] = {
{ -1, 0, "" }
};
-#ifdef WITH_COMPOSITOR_LEGACY
-
-static void do_zcombine(bNode *node, float *out, float *src1, float *z1, float *src2, float *z2)
-{
- float alpha;
- float malpha;
-
- if (*z1 <= *z2) {
- if (node->custom1) {
- // use alpha in combine operation
- alpha= src1[3];
- malpha= 1.0f - alpha;
- out[0] = malpha*src2[0] + alpha*src1[0];
- out[1] = malpha*src2[1] + alpha*src1[1];
- out[2] = malpha*src2[2] + alpha*src1[2];
- out[3] = malpha*src2[3] + alpha*src1[3];
- }
- else {
- // do combination based solely on z value
- copy_v4_v4(out, src1);
- }
- }
- else {
- if (node->custom1) {
- // use alpha in combine operation
- alpha= src2[3];
- malpha= 1.0f - alpha;
- out[0] = malpha*src1[0] + alpha*src2[0];
- out[1] = malpha*src1[1] + alpha*src2[1];
- out[2] = malpha*src1[2] + alpha*src2[2];
- out[3] = malpha*src1[3] + alpha*src2[3];
- }
- else {
- // do combination based solely on z value
- copy_v4_v4(out, src1);
- }
-
- if (node->custom2)
- *z1= *z2;
- }
-}
-
-static void do_zcombine_mask(bNode *node, float *out, float *z1, float *z2)
-{
- if (*z1 > *z2) {
- *out= 1.0f;
- if (node->custom2)
- *z1= *z2;
- }
-}
-
-static void do_zcombine_add(bNode *node, float *out, float *col1, float *col2, float *acol)
-{
- float alpha;
- float malpha;
-
- if (node->custom1) {
- // use alpha in combine operation, antialiased mask in used here just as hint for the z value
- if (*acol>0.0f) {
- alpha= col2[3];
- malpha= 1.0f - alpha;
-
-
- out[0] = malpha*col1[0] + alpha*col2[0];
- out[1] = malpha*col1[1] + alpha*col2[1];
- out[2] = malpha*col1[2] + alpha*col2[2];
- out[3] = malpha*col1[3] + alpha*col2[3];
- }
- else {
- alpha= col1[3];
- malpha= 1.0f - alpha;
-
-
- out[0] = malpha*col2[0] + alpha*col1[0];
- out[1] = malpha*col2[1] + alpha*col1[1];
- out[2] = malpha*col2[2] + alpha*col1[2];
- out[3] = malpha*col2[3] + alpha*col1[3];
- }
- }
- else {
- // do combination based solely on z value but with antialiased mask
- alpha = *acol;
- malpha= 1.0f - alpha;
-
- out[0] = malpha*col1[0] + alpha*col2[0];
- out[1] = malpha*col1[1] + alpha*col2[1];
- out[2] = malpha*col1[2] + alpha*col2[2];
- out[3] = malpha*col1[3] + alpha*col2[3];
- }
-}
-
-static void node_composit_exec_zcombine(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
-{
- RenderData *rd= data;
- CompBuf *cbuf= in[0]->data;
- CompBuf *zbuf;
-
- /* stack order in: col z col z */
- /* stack order out: col z */
- if (out[0]->hasoutput==0 && out[1]->hasoutput==0)
- return;
-
- /* no input image; do nothing now */
- if (in[0]->data==NULL) {
- return;
- }
-
- if (out[1]->hasoutput) {
- /* copy or make a buffer for for the first z value, here we write result in */
- if (in[1]->data)
- zbuf= dupalloc_compbuf(in[1]->data);
- else {
- float *zval;
- int tot= cbuf->x*cbuf->y;
-
- zbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1);
- for (zval= zbuf->rect; tot; tot--, zval++)
- *zval= in[1]->vec[0];
- }
- /* lazy coder hack */
- node->custom2= 1;
- out[1]->data= zbuf;
- }
- else {
- node->custom2= 0;
- zbuf= in[1]->data;
- }
-
- if (rd->scemode & R_FULL_SAMPLE) {
- /* make output size of first input image */
- CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
-
- composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, zbuf, in[1]->vec, in[2]->data, in[2]->vec,
- in[3]->data, in[3]->vec, do_zcombine, CB_RGBA, CB_VAL, CB_RGBA, CB_VAL);
-
- out[0]->data= stackbuf;
- }
- else {
- /* make output size of first input image */
- CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
- CompBuf *mbuf;
- float *fp;
- int x;
- char *aabuf;
-
-
- /* make a mask based on comparison, optionally write zvalue */
- mbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1);
- composit2_pixel_processor(node, mbuf, zbuf, in[1]->vec, in[3]->data, in[3]->vec, do_zcombine_mask, CB_VAL, CB_VAL);
-
- /* convert to char */
- aabuf= MEM_mallocN(cbuf->x*cbuf->y, "aa buf");
- fp= mbuf->rect;
- for (x= cbuf->x*cbuf->y-1; x>=0; x--)
- if (fp[x]==0.0f) aabuf[x] = 0;
- else aabuf[x] = 255;
-
- antialias_tagbuf(cbuf->x, cbuf->y, aabuf);
-
- /* convert to float */
- fp= mbuf->rect;
- for (x= cbuf->x*cbuf->y-1; x>=0; x--)
- if (aabuf[x]>1)
- fp[x] = (1.0f/255.0f)*(float)aabuf[x];
-
- composit3_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[2]->data, in[2]->vec, mbuf, NULL,
- do_zcombine_add, CB_RGBA, CB_RGBA, CB_VAL);
- /* free */
- free_compbuf(mbuf);
- MEM_freeN(aabuf);
-
- out[0]->data= stackbuf;
- }
-}
-
-#endif /* WITH_COMPOSITOR_LEGACY */
-
-void register_node_type_cmp_zcombine(bNodeTreeType *ttype)
+void register_node_type_cmp_zcombine(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, CMP_NODE_ZCOMBINE, "Z Combine", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ cmp_node_type_base(&ntype, CMP_NODE_ZCOMBINE, "Z Combine", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, cmp_node_zcombine_in, cmp_node_zcombine_out);
- node_type_size(&ntype, 80, 40, 120);
-#ifdef WITH_COMPOSITOR_LEGACY
- node_type_exec(&ntype, node_composit_exec_zcombine);
-#endif
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c
index 86ef8a14c12..54ffd3cd01c 100644
--- a/source/blender/nodes/intern/node_common.c
+++ b/source/blender/nodes/intern/node_common.c
@@ -31,19 +31,22 @@
#include <string.h>
+#include <stddef.h>
#include "DNA_node_types.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BLF_translation.h"
#include "BKE_global.h"
+#include "BKE_idprop.h"
#include "BKE_library.h"
#include "BKE_main.h"
-#include "BLI_math.h"
#include "BKE_node.h"
#include "RNA_access.h"
@@ -55,247 +58,110 @@
#include "node_util.h"
#include "node_exec.h"
#include "NOD_socket.h"
+#include "NOD_common.h"
+
/**** Group ****/
-bNodeSocket *node_group_find_input(bNode *gnode, bNodeSocket *gsock)
+bNodeSocket *node_group_find_input_socket(bNode *groupnode, const char *identifier)
{
bNodeSocket *sock;
- for (sock=gnode->inputs.first; sock; sock=sock->next)
- if (sock->groupsock == gsock)
+ for (sock=groupnode->inputs.first; sock; sock = sock->next)
+ if (STREQ(sock->identifier, identifier))
return sock;
return NULL;
}
-bNodeSocket *node_group_find_output(bNode *gnode, bNodeSocket *gsock)
+bNodeSocket *node_group_find_output_socket(bNode *groupnode, const char *identifier)
{
bNodeSocket *sock;
- for (sock=gnode->outputs.first; sock; sock=sock->next)
- if (sock->groupsock == gsock)
+ for (sock=groupnode->outputs.first; sock; sock = sock->next)
+ if (STREQ(sock->identifier, identifier))
return sock;
return NULL;
}
-bNodeSocket *node_group_add_extern_socket(bNodeTree *UNUSED(ntree), ListBase *lb, int in_out, bNodeSocket *gsock)
-{
- bNodeSocket *sock;
-
- if (gsock->flag & SOCK_INTERNAL)
- return NULL;
-
- sock= MEM_callocN(sizeof(bNodeSocket), "sock");
-
- /* make a copy of the group socket */
- *sock = *gsock;
- sock->link = NULL;
- sock->next = sock->prev = NULL;
- sock->new_sock = NULL;
-
- /* group sockets are dynamically added */
- sock->flag |= SOCK_DYNAMIC|SOCK_COLLAPSED;
-
- sock->own_index = gsock->own_index;
- sock->groupsock = gsock;
- sock->limit = (in_out==SOCK_IN ? 1 : 0xFFF);
-
- sock->default_value = node_socket_make_default_value(sock->type);
- node_socket_copy_default_value(sock->type, sock->default_value, gsock->default_value);
-
- if (lb)
- BLI_addtail(lb, sock);
-
- return sock;
-}
-
-bNodeSocket *node_group_add_socket(bNodeTree *ngroup, const char *name, int type, int in_out)
-{
- bNodeSocketType *stype = ntreeGetSocketType(type);
- bNodeSocket *gsock = MEM_callocN(sizeof(bNodeSocket), "bNodeSocket");
-
- BLI_strncpy(gsock->name, name, sizeof(gsock->name));
- gsock->type = type;
- /* group sockets are dynamically added */
- gsock->flag |= SOCK_DYNAMIC|SOCK_COLLAPSED;
-
- gsock->next = gsock->prev = NULL;
- gsock->new_sock = NULL;
- gsock->link = NULL;
- /* assign new unique index */
- gsock->own_index = ngroup->cur_index++;
- gsock->limit = (in_out==SOCK_IN ? 0xFFF : 1);
-
- if (stype->value_structsize > 0)
- gsock->default_value = MEM_callocN(stype->value_structsize, "default socket value");
-
- BLI_addtail(in_out==SOCK_IN ? &ngroup->inputs : &ngroup->outputs, gsock);
-
- ngroup->update |= (in_out==SOCK_IN ? NTREE_UPDATE_GROUP_IN : NTREE_UPDATE_GROUP_OUT);
-
- return gsock;
-}
-
-bNodeSocket *node_group_expose_socket(bNodeTree *ngroup, bNodeSocket *sock, int in_out)
+/* groups display their internal tree name as label */
+const char *node_group_label(bNode *node)
{
- bNodeSocket *gsock= node_group_add_socket(ngroup, sock->name, sock->type, in_out);
-
- /* initialize the default value. */
- node_socket_copy_default_value(gsock->type, gsock->default_value, sock->default_value);
-
- return gsock;
+ return (node->id)? node->id->name + 2: IFACE_("Missing Datablock");
}
-void node_group_expose_all_sockets(bNodeTree *ngroup)
+int node_group_poll_instance(bNode *node, bNodeTree *nodetree)
{
- bNode *node;
- bNodeSocket *sock, *gsock;
-
- for (node=ngroup->nodes.first; node; node=node->next) {
- for (sock=node->inputs.first; sock; sock=sock->next) {
- if (!sock->link && !nodeSocketIsHidden(sock)) {
- gsock = node_group_add_socket(ngroup, sock->name, sock->type, SOCK_IN);
-
- /* initialize the default value. */
- node_socket_copy_default_value(gsock->type, gsock->default_value, sock->default_value);
-
- sock->link = nodeAddLink(ngroup, NULL, gsock, node, sock);
- }
- }
- for (sock=node->outputs.first; sock; sock=sock->next) {
- if (nodeCountSocketLinks(ngroup, sock)==0 && !nodeSocketIsHidden(sock)) {
- gsock = node_group_add_socket(ngroup, sock->name, sock->type, SOCK_OUT);
-
- /* initialize the default value. */
- node_socket_copy_default_value(gsock->type, gsock->default_value, sock->default_value);
-
- gsock->link = nodeAddLink(ngroup, node, sock, NULL, gsock);
- }
- }
- }
-}
-
-void node_group_remove_socket(bNodeTree *ngroup, bNodeSocket *gsock, int in_out)
-{
- nodeRemSocketLinks(ngroup, gsock);
-
- switch (in_out) {
- case SOCK_IN:
- BLI_remlink(&ngroup->inputs, gsock);
- ngroup->update |= NTREE_UPDATE_GROUP_IN;
- break;
- case SOCK_OUT:
- BLI_remlink(&ngroup->outputs, gsock);
- ngroup->update |= NTREE_UPDATE_GROUP_OUT;
- break;
- }
-
- if (gsock->default_value)
- MEM_freeN(gsock->default_value);
-
- MEM_freeN(gsock);
-}
-
-/* groups display their internal tree name as label */
-const char *node_group_label(bNode *node)
-{
- return (node->id)? node->id->name+2: IFACE_("Missing Datablock");
+ bNodeTree *grouptree = (bNodeTree*)node->id;
+ if (grouptree)
+ return nodeGroupPoll(nodetree, grouptree);
+ else
+ return 1;
}
-int node_group_valid(bNodeTree *ntree, bNodeTemplate *ntemp)
+int nodeGroupPoll(bNodeTree *nodetree, bNodeTree *grouptree)
{
- bNodeTemplate childtemp;
bNode *node;
+ int valid = 1;
- /* regular groups cannot be recursive */
- if (ntree == ntemp->ngroup)
+ if (nodetree == grouptree)
return 0;
- /* make sure all children are valid */
- for (node=ntemp->ngroup->nodes.first; node; node=node->next) {
- childtemp = nodeMakeTemplate(node);
- if (!nodeValid(ntree, &childtemp))
- return 0;
- }
-
- return 1;
-}
-
-bNodeTemplate node_group_template(bNode *node)
-{
- bNodeTemplate ntemp;
- ntemp.type = NODE_GROUP;
- ntemp.ngroup = (bNodeTree *)node->id;
- return ntemp;
-}
-
-void node_group_init(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp)
-{
- node->id = (ID *)ntemp->ngroup;
-
- /* NB: group socket input/output roles are inverted internally!
- * Group "inputs" work as outputs in links and vice versa.
- */
- if (ntemp->ngroup) {
- bNodeSocket *gsock;
- for (gsock=ntemp->ngroup->inputs.first; gsock; gsock=gsock->next)
- node_group_add_extern_socket(ntree, &node->inputs, SOCK_IN, gsock);
- for (gsock=ntemp->ngroup->outputs.first; gsock; gsock=gsock->next)
- node_group_add_extern_socket(ntree, &node->outputs, SOCK_OUT, gsock);
+ for (node=grouptree->nodes.first; node; node=node->next) {
+ if (node->typeinfo->poll_instance && !node->typeinfo->poll_instance(node, nodetree)) {
+ valid = 0;
+ break;
+ }
}
+ return valid;
}
-static bNodeSocket *group_verify_socket(bNodeTree *ntree, ListBase *lb, int in_out, bNodeSocket *gsock)
+/* used for both group nodes and interface nodes */
+static bNodeSocket *group_verify_socket(bNodeTree *ntree, bNode *gnode, bNodeSocket *iosock, ListBase *verify_lb, int in_out)
{
bNodeSocket *sock;
- /* group sockets tagged as internal are not exposed ever */
- if (gsock->flag & SOCK_INTERNAL)
- return NULL;
-
- for (sock= lb->first; sock; sock= sock->next) {
- if (sock->own_index==gsock->own_index)
- break;
+ for (sock= verify_lb->first; sock; sock= sock->next) {
+ if (STREQ(sock->identifier, iosock->identifier))
+ break;
}
if (sock) {
- sock->groupsock = gsock;
-
- BLI_strncpy(sock->name, gsock->name, sizeof(sock->name));
- if (gsock->type != sock->type)
- nodeSocketSetType(sock, gsock->type);
-
- /* XXX hack: group socket input/output roles are inverted internally,
- * need to change the limit value when making actual node sockets from them.
- */
- sock->limit = (in_out==SOCK_IN ? 1 : 0xFFF);
-
- BLI_remlink(lb, sock);
-
- return sock;
+ strcpy(sock->name, iosock->name);
}
else {
- return node_group_add_extern_socket(ntree, NULL, in_out, gsock);
+ sock = nodeAddSocket(ntree, gnode, in_out, iosock->idname, iosock->identifier, iosock->name);
+
+ if (iosock->typeinfo->interface_init_socket)
+ iosock->typeinfo->interface_init_socket(ntree, iosock, gnode, sock, "interface");
}
+
+ /* remove from list temporarily, to distinguish from orphaned sockets */
+ BLI_remlink(verify_lb, sock);
+
+ return sock;
}
-static void group_verify_socket_list(bNodeTree *ntree, bNode *node, ListBase *lb, int in_out, ListBase *glb)
+/* used for both group nodes and interface nodes */
+static void group_verify_socket_list(bNodeTree *ntree, bNode *gnode,
+ ListBase *iosock_lb, ListBase *verify_lb, int in_out)
{
- bNodeSocket *sock, *nextsock, *gsock;
+ bNodeSocket *iosock, *sock, *nextsock;
/* step by step compare */
- for (gsock= glb->first; gsock; gsock=gsock->next) {
+
+ iosock = iosock_lb->first;
+ for (; iosock; iosock = iosock->next) {
/* abusing new_sock pointer for verification here! only used inside this function */
- gsock->new_sock= group_verify_socket(ntree, lb, in_out, gsock);
+ iosock->new_sock = group_verify_socket(ntree, gnode, iosock, verify_lb, in_out);
}
/* leftovers are removed */
- for (sock=lb->first; sock; sock=nextsock) {
- nextsock=sock->next;
- if (sock->flag & SOCK_DYNAMIC)
- nodeRemoveSocket(ntree, node, sock);
+ for (sock = verify_lb->first; sock; sock = nextsock) {
+ nextsock = sock->next;
+ nodeRemoveSocket(ntree, gnode, sock);
}
/* and we put back the verified sockets */
- for (gsock= glb->first; gsock; gsock=gsock->next) {
- if (gsock->new_sock) {
- BLI_addtail(lb, gsock->new_sock);
- gsock->new_sock = NULL;
+ iosock = iosock_lb->first;
+ for (; iosock; iosock = iosock->next) {
+ if (iosock->new_sock) {
+ BLI_addtail(verify_lb, iosock->new_sock);
+ iosock->new_sock = NULL;
}
}
}
@@ -304,59 +170,16 @@ static void group_verify_socket_list(bNodeTree *ntree, bNode *node, ListBase *lb
void node_group_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id)
{
/* check inputs and outputs, and remove or insert them */
- if (node->id==id) {
- bNodeTree *ngroup= (bNodeTree*)node->id;
- group_verify_socket_list(ntree, node, &node->inputs, SOCK_IN, &ngroup->inputs);
- group_verify_socket_list(ntree, node, &node->outputs, SOCK_OUT, &ngroup->outputs);
+ if (id == node->id) {
+ bNodeTree *ngroup= (bNodeTree *)node->id;
+ group_verify_socket_list(ntree, node, &ngroup->inputs, &node->inputs, SOCK_IN);
+ group_verify_socket_list(ntree, node, &ngroup->outputs, &node->outputs, SOCK_OUT);
}
}
-struct bNodeTree *node_group_edit_get(bNode *node)
-{
- if (node->flag & NODE_GROUP_EDIT)
- return (bNodeTree*)node->id;
- else
- return NULL;
-}
-
-struct bNodeTree *node_group_edit_set(bNode *node, int edit)
-{
- if (edit) {
- bNodeTree *ngroup= (bNodeTree*)node->id;
- if (ngroup) {
- if (ngroup->id.lib)
- ntreeMakeLocal(ngroup);
-
- node->flag |= NODE_GROUP_EDIT;
- }
- return ngroup;
- }
- else {
- node->flag &= ~NODE_GROUP_EDIT;
- return NULL;
- }
-}
-
-void node_group_edit_clear(bNode *node)
-{
- bNodeTree *ngroup= (bNodeTree*)node->id;
- bNode *inode;
-
- node->flag &= ~NODE_GROUP_EDIT;
-
- if (ngroup)
- for (inode=ngroup->nodes.first; inode; inode=inode->next)
- nodeGroupEditClear(inode);
-}
-
-static void UNUSED_FUNCTION(node_group_link)(bNodeTree *ntree, bNodeSocket *sock, int in_out)
-{
- node_group_expose_socket(ntree, sock, in_out);
-}
-
/**** FRAME ****/
-static void node_frame_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_frame_init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeFrame *data = (NodeFrame *)MEM_callocN(sizeof(NodeFrame), "frame node storage");
node->storage = data;
@@ -366,19 +189,19 @@ static void node_frame_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate
data->label_size = 20;
}
-void register_node_type_frame(bNodeTreeType *ttype)
+void register_node_type_frame(void)
{
/* frame type is used for all tree types, needs dynamic allocation */
bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "frame node type");
- node_type_base(ttype, ntype, NODE_FRAME, "Frame", NODE_CLASS_LAYOUT, NODE_BACKGROUND|NODE_OPTIONS);
+ node_type_base(ntype, NODE_FRAME, "Frame", NODE_CLASS_LAYOUT, NODE_BACKGROUND|NODE_OPTIONS);
node_type_init(ntype, node_frame_init);
node_type_storage(ntype, "NodeFrame", node_free_standard_storage, node_copy_standard_storage);
node_type_size(ntype, 150, 100, 0);
node_type_compatibility(ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
ntype->needs_free = 1;
- nodeRegisterType(ttype, ntype);
+ nodeRegisterType(ntype);
}
@@ -403,34 +226,34 @@ static void node_reroute_update_internal_links(bNodeTree *ntree, bNode *node)
BLI_addtail(&node->internal_links, link);
}
-static void node_reroute_init(bNodeTree *ntree, bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_reroute_init(bNodeTree *ntree, bNode *node)
{
/* Note: Cannot use socket templates for this, since it would reset the socket type
* on each file read via the template verification procedure.
*/
- nodeAddSocket(ntree, node, SOCK_IN, "Input", SOCK_RGBA);
- nodeAddSocket(ntree, node, SOCK_OUT, "Output", SOCK_RGBA);
+ nodeAddStaticSocket(ntree, node, SOCK_IN, SOCK_RGBA, PROP_NONE, "Input", "Input");
+ nodeAddStaticSocket(ntree, node, SOCK_OUT, SOCK_RGBA, PROP_NONE, "Output", "Output");
}
-void register_node_type_reroute(bNodeTreeType *ttype)
+void register_node_type_reroute(void)
{
/* frame type is used for all tree types, needs dynamic allocation */
bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "frame node type");
- node_type_base(ttype, ntype, NODE_REROUTE, "Reroute", NODE_CLASS_LAYOUT, 0);
+ node_type_base(ntype, NODE_REROUTE, "Reroute", NODE_CLASS_LAYOUT, 0);
node_type_init(ntype, node_reroute_init);
node_type_internal_links(ntype, node_reroute_update_internal_links);
ntype->needs_free = 1;
- nodeRegisterType(ttype, ntype);
+ nodeRegisterType(ntype);
}
static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node)
{
bNodeSocket *input = node->inputs.first;
bNodeSocket *output = node->outputs.first;
- int type = SOCK_FLOAT;
bNodeLink *link;
+ int type = SOCK_FLOAT;
/* XXX it would be a little bit more efficient to restrict actual updates
* to rerout nodes connected to an updated node, but there's no reliable flag
@@ -446,6 +269,8 @@ static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node)
bNode *tonode = link->tonode;
if (!tonode || !fromnode)
continue;
+ if (nodeLinkIsHidden(link))
+ continue;
if (tonode == node && fromnode->type == NODE_REROUTE && !fromnode->done)
node_reroute_inherit_type_recursive(ntree, fromnode);
@@ -462,9 +287,13 @@ static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node)
/* arbitrary, could also test output->type, both are the same */
if (input->type != type) {
+ PointerRNA input_ptr, output_ptr;
/* same type for input/output */
- nodeSocketSetType(input, type);
- nodeSocketSetType(output, type);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, input, &input_ptr);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, output, &output_ptr);
+
+ RNA_enum_set(&input_ptr, "type", type);
+ RNA_enum_set(&output_ptr, "type", type);
}
}
@@ -484,9 +313,8 @@ void ntree_update_reroute_nodes(bNodeTree *ntree)
node_reroute_inherit_type_recursive(ntree, node);
}
-void BKE_node_tree_unlink_id_cb(void *calldata, struct ID *UNUSED(owner_id), struct bNodeTree *ntree)
+void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree)
{
- ID *id = (ID *)calldata;
bNode *node;
for (node = ntree->nodes.first; node; node = node->next) {
@@ -495,3 +323,179 @@ void BKE_node_tree_unlink_id_cb(void *calldata, struct ID *UNUSED(owner_id), str
}
}
}
+
+/**** GROUP_INPUT / GROUP_OUTPUT ****/
+
+static void node_group_input_init(bNodeTree *ntree, bNode *node)
+{
+ node_group_input_verify(ntree, node, (ID *)ntree);
+}
+
+bNodeSocket *node_group_input_find_socket(bNode *node, const char *identifier)
+{
+ bNodeSocket *sock;
+ for (sock = node->outputs.first; sock; sock = sock->next)
+ if (STREQ(sock->identifier, identifier))
+ return sock;
+ return NULL;
+}
+
+void node_group_input_verify(bNodeTree *ntree, bNode *node, ID *id)
+{
+ /* check inputs and outputs, and remove or insert them */
+ if (id == (ID *)ntree) {
+ /* value_in_out inverted for interface nodes to get correct socket value_property */
+ group_verify_socket_list(ntree, node, &ntree->inputs, &node->outputs, SOCK_OUT);
+
+ /* add virtual extension socket */
+ nodeAddSocket(ntree, node, SOCK_OUT, "NodeSocketVirtual", "__extend__", "");
+ }
+}
+
+static void node_group_input_update(bNodeTree *ntree, bNode *node)
+{
+ bNodeSocket *extsock = node->outputs.last;
+ bNodeLink *link;
+ /* Adding a tree socket and verifying will remove the extension socket!
+ * This list caches the existing links from the extension socket
+ * so they can be recreated after verification.
+ */
+ ListBase tmplinks;
+
+ /* find links from the extension socket and store them */
+ tmplinks.first = tmplinks.last = NULL;
+ for (link = ntree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
+ if (link->fromsock == extsock) {
+ bNodeLink *tlink = MEM_callocN(sizeof(bNodeLink), "temporary link");
+ *tlink = *link;
+ BLI_addtail(&tmplinks, tlink);
+ }
+ }
+
+ if (tmplinks.first) {
+ bNodeSocket *gsock, *newsock;
+ /* XXX Multiple sockets can be connected to the extension socket at once,
+ * in that case the arbitrary first link determines name and type.
+ * This could be improved by choosing the "best" type among all links,
+ * whatever that means.
+ */
+ bNodeLink *exposelink = tmplinks.first;
+
+ /* XXX what if connecting virtual to virtual socket?? */
+ gsock = ntreeAddSocketInterfaceFromSocket(ntree, exposelink->tonode, exposelink->tosock);
+
+ node_group_input_verify(ntree, node, (ID *)ntree);
+ newsock = node_group_input_find_socket(node, gsock->identifier);
+
+ /* redirect links from the extension socket */
+ for (link = tmplinks.first; link; link = link->next) {
+ nodeAddLink(ntree, node, newsock, link->tonode, link->tosock);
+ }
+
+ BLI_freelistN(&tmplinks);
+ }
+}
+
+void register_node_type_group_input(void)
+{
+ /* used for all tree types, needs dynamic allocation */
+ bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "node type");
+
+ node_type_base(ntype, NODE_GROUP_INPUT, "Group Input", NODE_CLASS_INTERFACE, NODE_OPTIONS);
+ node_type_size(ntype, 140, 80, 200);
+ node_type_init(ntype, node_group_input_init);
+ node_type_update(ntype, node_group_input_update, node_group_input_verify);
+ node_type_compatibility(ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
+
+ ntype->needs_free = 1;
+ nodeRegisterType(ntype);
+}
+
+static void node_group_output_init(bNodeTree *ntree, bNode *node)
+{
+ node_group_output_verify(ntree, node, (ID *)ntree);
+}
+
+bNodeSocket *node_group_output_find_socket(bNode *node, const char *identifier)
+{
+ bNodeSocket *sock;
+ for (sock = node->inputs.first; sock; sock = sock->next)
+ if (STREQ(sock->identifier, identifier))
+ return sock;
+ return NULL;
+}
+
+void node_group_output_verify(bNodeTree *ntree, bNode *node, ID *id)
+{
+ /* check inputs and outputs, and remove or insert them */
+ if (id == (ID *)ntree) {
+ /* value_in_out inverted for interface nodes to get correct socket value_property */
+ group_verify_socket_list(ntree, node, &ntree->outputs, &node->inputs, SOCK_IN);
+
+ /* add virtual extension socket */
+ nodeAddSocket(ntree, node, SOCK_IN, "NodeSocketVirtual", "__extend__", "");
+ }
+}
+
+static void node_group_output_update(bNodeTree *ntree, bNode *node)
+{
+ bNodeSocket *extsock = node->inputs.last;
+ bNodeLink *link;
+ /* Adding a tree socket and verifying will remove the extension socket!
+ * This list caches the existing links to the extension socket
+ * so they can be recreated after verification.
+ */
+ ListBase tmplinks;
+
+ /* find links to the extension socket and store them */
+ tmplinks.first = tmplinks.last = NULL;
+ for (link = ntree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
+ if (link->tosock == extsock) {
+ bNodeLink *tlink = MEM_callocN(sizeof(bNodeLink), "temporary link");
+ *tlink = *link;
+ BLI_addtail(&tmplinks, tlink);
+ }
+ }
+
+ if (tmplinks.first) {
+ bNodeSocket *gsock, *newsock;
+ /* XXX Multiple sockets can be connected to the extension socket at once,
+ * in that case the arbitrary first link determines name and type.
+ * This could be improved by choosing the "best" type among all links,
+ * whatever that means.
+ */
+ bNodeLink *exposelink = tmplinks.first;
+
+ /* XXX what if connecting virtual to virtual socket?? */
+ gsock = ntreeAddSocketInterfaceFromSocket(ntree, exposelink->fromnode, exposelink->fromsock);
+
+ node_group_output_verify(ntree, node, (ID *)ntree);
+ newsock = node_group_output_find_socket(node, gsock->identifier);
+
+ /* redirect links to the extension socket */
+ for (link = tmplinks.first; link; link = link->next) {
+ nodeAddLink(ntree, link->fromnode, link->fromsock, node, newsock);
+ }
+
+ BLI_freelistN(&tmplinks);
+ }
+}
+
+void register_node_type_group_output(void)
+{
+ /* used for all tree types, needs dynamic allocation */
+ bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "node type");
+
+ node_type_base(ntype, NODE_GROUP_OUTPUT, "Group Output", NODE_CLASS_INTERFACE, NODE_OPTIONS);
+ node_type_size(ntype, 140, 80, 200);
+ node_type_init(ntype, node_group_output_init);
+ node_type_update(ntype, node_group_output_update, node_group_output_verify);
+ node_type_compatibility(ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
+
+ ntype->needs_free = 1;
+ nodeRegisterType(ntype);
+}
diff --git a/source/blender/nodes/intern/node_common.h b/source/blender/nodes/intern/node_common.h
index 9e04a9e05f8..498da607b91 100644
--- a/source/blender/nodes/intern/node_common.h
+++ b/source/blender/nodes/intern/node_common.h
@@ -37,15 +37,8 @@
struct bNodeTree;
-void node_group_init(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp);
const char *node_group_label(struct bNode *node);
-struct bNodeTemplate node_group_template(struct bNode *node);
-int node_group_valid(struct bNodeTree *ntree, struct bNodeTemplate *ntemp);
-void node_group_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id);
-
-struct bNodeTree *node_group_edit_get(struct bNode *node);
-struct bNodeTree *node_group_edit_set(struct bNode *node, int edit);
-void node_group_edit_clear(bNode *node);
+int node_group_poll_instance(struct bNode *node, struct bNodeTree *nodetree);
void ntree_update_reroute_nodes(struct bNodeTree *ntree);
diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c
index 3cc7ebf9337..62a937b106c 100644
--- a/source/blender/nodes/intern/node_exec.c
+++ b/source/blender/nodes/intern/node_exec.c
@@ -41,12 +41,19 @@
#include "MEM_guardedalloc.h"
#include "node_exec.h"
+#include "node_util.h"
+/* supported socket types in old nodes */
+int node_exec_socket_use_stack(bNodeSocket *sock)
+{
+ return ELEM4(sock->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA, SOCK_SHADER);
+}
+
/* for a given socket, find the actual stack entry */
bNodeStack *node_get_socket_stack(bNodeStack *stack, bNodeSocket *sock)
{
- if (stack && sock)
+ if (stack && sock && sock->stack_index >= 0)
return stack + sock->stack_index;
return NULL;
}
@@ -75,7 +82,10 @@ static void node_init_input_index(bNodeSocket *sock, int *index)
sock->stack_index = sock->link->fromsock->stack_index;
}
else {
- sock->stack_index = (*index)++;
+ if (node_exec_socket_use_stack(sock))
+ sock->stack_index = (*index)++;
+ else
+ sock->stack_index = -1;
}
}
@@ -91,19 +101,27 @@ static void node_init_output_index(bNodeSocket *sock, int *index, ListBase *inte
}
}
/* if not internally connected, assign a new stack index anyway to avoid bad stack access */
- if (!link)
- sock->stack_index = (*index)++;
+ if (!link) {
+ if (node_exec_socket_use_stack(sock))
+ sock->stack_index = (*index)++;
+ else
+ sock->stack_index = -1;
+ }
}
else {
- sock->stack_index = (*index)++;
+ if (node_exec_socket_use_stack(sock))
+ sock->stack_index = (*index)++;
+ else
+ sock->stack_index = -1;
}
}
/* basic preparation of socket stacks */
-static struct bNodeStack *setup_stack(bNodeStack *stack, bNodeSocket *sock)
+static struct bNodeStack *setup_stack(bNodeStack *stack, bNodeTree *ntree, bNode *node, bNodeSocket *sock)
{
bNodeStack *ns = node_get_socket_stack(stack, sock);
- float null_value[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ if (!ns)
+ return NULL;
/* don't mess with remote socket stacks, these are initialized by other nodes! */
if (sock->link)
@@ -111,49 +129,35 @@ static struct bNodeStack *setup_stack(bNodeStack *stack, bNodeSocket *sock)
ns->sockettype = sock->type;
- if (sock->default_value) {
- switch (sock->type) {
+ switch (sock->type) {
case SOCK_FLOAT:
- ns->vec[0] = ((bNodeSocketValueFloat*)sock->default_value)->value;
+ ns->vec[0] = node_socket_get_float(ntree, node, sock);
break;
case SOCK_VECTOR:
- copy_v3_v3(ns->vec, ((bNodeSocketValueVector*)sock->default_value)->value);
+ node_socket_get_vector(ntree, node, sock, ns->vec);
break;
case SOCK_RGBA:
- copy_v4_v4(ns->vec, ((bNodeSocketValueRGBA*)sock->default_value)->value);
+ node_socket_get_color(ntree, node, sock, ns->vec);
break;
- }
- }
- else {
- switch (sock->type) {
- case SOCK_FLOAT:
- ns->vec[0] = 0.0f;
- break;
- case SOCK_VECTOR:
- copy_v3_v3(ns->vec, null_value);
- break;
- case SOCK_RGBA:
- copy_v4_v4(ns->vec, null_value);
- break;
- }
}
return ns;
}
-bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree)
+bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
{
bNodeTreeExec *exec;
bNode *node;
bNodeExec *nodeexec;
- bNodeSocket *sock, *gsock;
+ bNodeInstanceKey nodekey;
+ bNodeSocket *sock;
bNodeStack *ns;
int index;
bNode **nodelist;
int totnodes, n;
- if ((ntree->init & NTREE_TYPE_INIT)==0)
- ntreeInitTypes(ntree);
+ /* ensure all sock->link pointers and node levels are correct */
+ ntreeUpdateTree(ntree);
/* get a dependency-sorted list of nodes */
ntreeGetDependencyList(ntree, &nodelist, &totnodes);
@@ -165,30 +169,24 @@ bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree)
/* set stack indices */
index = 0;
- /* group inputs essentially work as outputs */
- for (gsock=ntree->inputs.first; gsock; gsock = gsock->next)
- node_init_output_index(gsock, &index, NULL);
for (n=0; n < totnodes; ++n) {
node = nodelist[n];
node->stack_index = index;
/* init node socket stack indexes */
- for (sock=node->inputs.first; sock; sock=sock->next)
+ for (sock = node->inputs.first; sock; sock = sock->next)
node_init_input_index(sock, &index);
if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
- for (sock=node->outputs.first; sock; sock=sock->next)
+ for (sock = node->outputs.first; sock; sock = sock->next)
node_init_output_index(sock, &index, &node->internal_links);
}
else {
- for (sock=node->outputs.first; sock; sock=sock->next)
+ for (sock = node->outputs.first; sock; sock = sock->next)
node_init_output_index(sock, &index, NULL);
}
}
- /* group outputs essentially work as inputs */
- for (gsock=ntree->outputs.first; gsock; gsock = gsock->next)
- node_init_input_index(gsock, &index);
/* allocated exec data pointers for nodes */
exec->totnodes = totnodes;
@@ -201,36 +199,30 @@ bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree)
for (n=0; n < exec->stacksize; ++n)
exec->stack[n].hasinput = 1;
- /* prepare group tree inputs */
- for (sock=ntree->inputs.first; sock; sock=sock->next) {
- /* ns = */ setup_stack(exec->stack, sock);
- }
- /* prepare all internal nodes for execution */
+ /* prepare all nodes for execution */
for (n=0, nodeexec= exec->nodeexec; n < totnodes; ++n, ++nodeexec) {
node = nodeexec->node = nodelist[n];
/* tag inputs */
- for (sock=node->inputs.first; sock; sock=sock->next) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
/* disable the node if an input link is invalid */
if (sock->link && !(sock->link->flag & NODE_LINK_VALID))
node->need_exec= 0;
- ns = setup_stack(exec->stack, sock);
- ns->hasoutput = 1;
+ ns = setup_stack(exec->stack, ntree, node, sock);
+ if (ns)
+ ns->hasoutput = 1;
}
/* tag all outputs */
- for (sock=node->outputs.first; sock; sock=sock->next) {
- /* ns = */ setup_stack(exec->stack, sock);
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ /* ns = */ setup_stack(exec->stack, ntree, node, sock);
}
+ nodekey = BKE_node_instance_key(parent_key, ntree, node);
+ nodeexec->data.preview = context->previews ? BKE_node_instance_hash_lookup(context->previews, nodekey) : NULL;
if (node->typeinfo->initexecfunc)
- nodeexec->data = node->typeinfo->initexecfunc(node);
- }
- /* prepare group tree outputs */
- for (sock=ntree->outputs.first; sock; sock=sock->next) {
- ns = setup_stack(exec->stack, sock);
- ns->hasoutput = 1;
+ nodeexec->data.data = node->typeinfo->initexecfunc(context, node, nodekey);
}
if (nodelist)
@@ -248,8 +240,9 @@ void ntree_exec_end(bNodeTreeExec *exec)
MEM_freeN(exec->stack);
for (n=0, nodeexec= exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
- if (nodeexec->node->typeinfo->freeexecfunc)
- nodeexec->node->typeinfo->freeexecfunc(nodeexec->node, nodeexec->data);
+ if (nodeexec->node->typeinfo)
+ if (nodeexec->node->typeinfo->freeexecfunc)
+ nodeexec->node->typeinfo->freeexecfunc(nodeexec->node, nodeexec->data.data);
}
if (exec->nodeexec)
@@ -258,7 +251,7 @@ void ntree_exec_end(bNodeTreeExec *exec)
MEM_freeN(exec);
}
-/**** Compositor/Material/Texture trees ****/
+/**** Material/Texture trees ****/
bNodeThreadStack *ntreeGetThreadStack(bNodeTreeExec *exec, int thread)
{
@@ -287,33 +280,7 @@ void ntreeReleaseThreadStack(bNodeThreadStack *nts)
nts->used = 0;
}
-void ntreeExecNodes(bNodeTreeExec *exec, void *callerdata, int thread)
-{
- bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
- bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */
- bNodeExec *nodeexec;
- bNode *node;
- int n;
-
- /* nodes are presorted, so exec is in order of list */
-
- for (n=0, nodeexec= exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) {
- node = nodeexec->node;
- if (node->need_exec) {
- node_get_stack(node, exec->stack, nsin, nsout);
- /* Handle muted nodes...
- * If the mute func is not set, assume the node should never be muted,
- * and hence execute it!
- */
- if (node->typeinfo->execfunc)
- node->typeinfo->execfunc(callerdata, node, nsin, nsout);
- else if (node->typeinfo->newexecfunc)
- node->typeinfo->newexecfunc(callerdata, thread, node, nodeexec->data, nsin, nsout);
- }
- }
-}
-
-void ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *callerdata, int thread)
+bool ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *callerdata, int thread)
{
bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */
@@ -331,10 +298,13 @@ void ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *call
* If the mute func is not set, assume the node should never be muted,
* and hence execute it!
*/
+// if (node->typeinfo->compatibility == NODE_NEW_SHADING)
+// return false;
if (node->typeinfo->execfunc)
- node->typeinfo->execfunc(callerdata, node, nsin, nsout);
- else if (node->typeinfo->newexecfunc)
- node->typeinfo->newexecfunc(callerdata, thread, node, nodeexec->data, nsin, nsout);
+ node->typeinfo->execfunc(callerdata, thread, node, &nodeexec->data, nsin, nsout);
}
}
+
+ /* signal to that all went OK, for render */
+ return true;
}
diff --git a/source/blender/nodes/intern/node_exec.h b/source/blender/nodes/intern/node_exec.h
index e985795de71..7d76ef34934 100644
--- a/source/blender/nodes/intern/node_exec.h
+++ b/source/blender/nodes/intern/node_exec.h
@@ -39,6 +39,8 @@
#include "BKE_node.h"
+#include "node_util.h"
+
#include "RNA_types.h"
struct bNodeTree;
@@ -48,20 +50,20 @@ struct bNodeStack;
/* Node execution data */
typedef struct bNodeExec {
struct bNode *node; /* backpointer to node */
- void *data; /* custom data storage */
+ bNodeExecData data;
} bNodeExec;
/* Execution Data for each instance of node tree execution */
typedef struct bNodeTreeExec {
struct bNodeTree *nodetree; /* backpointer to node tree */
- int totnodes; /* total node count */
+ int totnodes; /* total node count */
struct bNodeExec *nodeexec; /* per-node execution data */
int stacksize;
struct bNodeStack *stack; /* socket data stack */
/* only used by material and texture trees to keep one stack for each thread */
- ListBase *threadstack; /* one instance of the stack for each thread */
+ ListBase *threadstack; /* one instance of the stack for each thread */
} bNodeTreeExec;
/* stores one stack copy for each thread (material and texture trees) */
@@ -71,16 +73,22 @@ typedef struct bNodeThreadStack {
int used;
} bNodeThreadStack;
+int node_exec_socket_use_stack(struct bNodeSocket *sock);
+
struct bNodeStack *node_get_socket_stack(struct bNodeStack *stack, struct bNodeSocket *sock);
void node_get_stack(struct bNode *node, struct bNodeStack *stack, struct bNodeStack **in, struct bNodeStack **out);
-struct bNodeTreeExec *ntree_exec_begin(struct bNodeTree *ntree);
+struct bNodeTreeExec *ntree_exec_begin(struct bNodeExecContext *context, struct bNodeTree *ntree, bNodeInstanceKey parent_key);
void ntree_exec_end(struct bNodeTreeExec *exec);
-void ntreeExecNodes(struct bNodeTreeExec *exec, void *callerdata, int thread);
-
struct bNodeThreadStack *ntreeGetThreadStack(struct bNodeTreeExec *exec, int thread);
void ntreeReleaseThreadStack(struct bNodeThreadStack *nts);
-void ntreeExecThreadNodes(struct bNodeTreeExec *exec, struct bNodeThreadStack *nts, void *callerdata, int thread);
+bool ntreeExecThreadNodes(struct bNodeTreeExec *exec, struct bNodeThreadStack *nts, void *callerdata, int thread);
+
+struct bNodeTreeExec *ntreeShaderBeginExecTree_internal(struct bNodeExecContext *context, struct bNodeTree *ntree, bNodeInstanceKey parent_key);
+void ntreeShaderEndExecTree_internal(struct bNodeTreeExec *exec);
+
+struct bNodeTreeExec *ntreeTexBeginExecTree_internal(struct bNodeExecContext *context, struct bNodeTree *ntree, bNodeInstanceKey parent_key);
+void ntreeTexEndExecTree_internal(struct bNodeTreeExec *exec);
#endif
diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c
index 69256fafc3d..86a8331e5dd 100644
--- a/source/blender/nodes/intern/node_socket.c
+++ b/source/blender/nodes/intern/node_socket.c
@@ -33,547 +33,95 @@
#include "DNA_node_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-
#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_node.h"
+#include "BKE_idprop.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "RNA_types.h"
#include "MEM_guardedalloc.h"
#include "NOD_socket.h"
-/****************** FLOAT ******************/
-
-static bNodeSocketType node_socket_type_float = {
- /* type */ SOCK_FLOAT,
- /* ui_name */ "Float",
- /* ui_description */ "Floating Point",
- /* ui_icon */ 0,
- /* ui_color */ {160, 160, 160, 255},
-
- /* value_structname */ "bNodeSocketValueFloat",
- /* value_structsize */ sizeof(bNodeSocketValueFloat),
-
- /* buttonfunc */ NULL,
-};
-
-/****************** VECTOR ******************/
-
-static bNodeSocketType node_socket_type_vector = {
- /* type */ SOCK_VECTOR,
- /* ui_name */ "Vector",
- /* ui_description */ "3-dimensional floating point vector",
- /* ui_icon */ 0,
- /* ui_color */ {100, 100, 200, 255},
-
- /* value_structname */ "bNodeSocketValueVector",
- /* value_structsize */ sizeof(bNodeSocketValueVector),
-
- /* buttonfunc */ NULL,
-};
-
-/****************** RGBA ******************/
-
-static bNodeSocketType node_socket_type_rgba = {
- /* type */ SOCK_RGBA,
- /* ui_name */ "RGBA",
- /* ui_description */ "RGBA color",
- /* ui_icon */ 0,
- /* ui_color */ {200, 200, 40, 255},
-
- /* value_structname */ "bNodeSocketValueRGBA",
- /* value_structsize */ sizeof(bNodeSocketValueRGBA),
-
- /* buttonfunc */ NULL,
-};
-
-/****************** INT ******************/
-
-static bNodeSocketType node_socket_type_int = {
- /* type */ SOCK_INT,
- /* ui_name */ "Int",
- /* ui_description */ "Integer",
- /* ui_icon */ 0,
- /* ui_color */ {17, 133, 37, 255},
-
- /* value_structname */ "bNodeSocketValueInt",
- /* value_structsize */ sizeof(bNodeSocketValueInt),
-
- /* buttonfunc */ NULL,
-};
-
-/****************** BOOLEAN ******************/
-
-static bNodeSocketType node_socket_type_boolean = {
- /* type */ SOCK_BOOLEAN,
- /* ui_name */ "Boolean",
- /* ui_description */ "Boolean",
- /* ui_icon */ 0,
- /* ui_color */ {158, 139, 63, 255},
-
- /* value_structname */ "bNodeSocketValueBoolean",
- /* value_structsize */ sizeof(bNodeSocketValueBoolean),
-
- /* buttonfunc */ NULL,
-};
-
-/****************** SHADER ******************/
-
-static bNodeSocketType node_socket_type_shader = {
- /* type */ SOCK_SHADER,
- /* ui_name */ "Shader",
- /* ui_description */ "Shader",
- /* ui_icon */ 0,
- /* ui_color */ {100, 200, 100, 255},
-
- /* value_structname */ NULL,
- /* value_structsize */ 0,
-
- /* buttonfunc */ NULL,
-};
-
-/****************** MESH ******************/
-
-static bNodeSocketType node_socket_type_mesh = {
- /* type */ SOCK_MESH,
- /* ui_name */ "Mesh",
- /* ui_description */ "Mesh geometry data",
- /* ui_icon */ 0,
- /* ui_color */ {255, 133, 7, 255},
-
- /* value_structname */ NULL,
- /* value_structsize */ 0,
-
- /* buttonfunc */ NULL,
-};
+struct Main;
-/****************** STRING ******************/
-
-static bNodeSocketType node_socket_type_string = {
- /* type */ SOCK_STRING,
- /* ui_name */ "String",
- /* ui_description */ "String",
- /* ui_icon */ 0,
- /* ui_color */ {255, 255, 255, 255},
-
- /* value_structname */ "bNodeSocketValueString",
- /* value_structsize */ sizeof(bNodeSocketValueString),
-
- /* buttonfunc */ NULL,
-};
-
-void node_socket_type_init(bNodeSocketType *types[])
+struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp, int in_out)
{
- #define INIT_TYPE(name) types[node_socket_type_##name.type] = &node_socket_type_##name
+ bNodeSocket *sock = nodeAddStaticSocket(ntree, node, in_out, stemp->type, stemp->subtype, stemp->identifier, stemp->name);
- INIT_TYPE(float);
- INIT_TYPE(vector);
- INIT_TYPE(rgba);
- INIT_TYPE(int);
- INIT_TYPE(boolean);
- INIT_TYPE(shader);
- INIT_TYPE(mesh);
- INIT_TYPE(string);
+ sock->flag |= stemp->flag;
- #undef INIT_TYPE
-}
-
-void *node_socket_make_default_value(int type)
-{
- /* XXX currently just allocates from stype->structsize.
- * it might become necessary to do more complex allocations for later types.
- */
- bNodeSocketType *stype = ntreeGetSocketType(type);
- if (stype->value_structsize > 0) {
- void *default_value = MEM_callocN(stype->value_structsize, "default socket value");
- return default_value;
- }
- else
- return NULL;
-}
-
-void node_socket_free_default_value(int UNUSED(type), void *default_value)
-{
- /* XXX can just free the pointee for all current socket types. */
- if (default_value)
- MEM_freeN(default_value);
-}
-
-void node_socket_init_default_value(int type, void *default_value)
-{
- switch (type) {
- case SOCK_FLOAT:
- node_socket_set_default_value_float(default_value, PROP_NONE, 0.0f, -FLT_MAX, FLT_MAX);
- break;
- case SOCK_INT:
- node_socket_set_default_value_int(default_value, PROP_NONE, 0, INT_MIN, INT_MAX);
- break;
- case SOCK_BOOLEAN:
- node_socket_set_default_value_boolean(default_value, FALSE);
- break;
- case SOCK_VECTOR:
- node_socket_set_default_value_vector(default_value, PROP_NONE, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX);
- break;
- case SOCK_RGBA:
- node_socket_set_default_value_rgba(default_value, 0.0f, 0.0f, 0.0f, 1.0f);
- break;
- case SOCK_SHADER:
- node_socket_set_default_value_shader(default_value);
- break;
- case SOCK_MESH:
- node_socket_set_default_value_mesh(default_value);
- break;
- case SOCK_STRING:
- node_socket_set_default_value_string(default_value, PROP_NONE, (char *)"");
- break;
- }
-}
-
-void node_socket_set_default_value_int(void *default_value, PropertySubType subtype, int value, int min, int max)
-{
- bNodeSocketValueInt *val = default_value;
- val->subtype = subtype;
- val->value = value;
- val->min = min;
- val->max = max;
-}
-
-void node_socket_set_default_value_float(void *default_value, PropertySubType subtype, float value, float min, float max)
-{
- bNodeSocketValueFloat *val = default_value;
- val->subtype = subtype;
- val->value = value;
- val->min = min;
- val->max = max;
-}
-
-void node_socket_set_default_value_boolean(void *default_value, char value)
-{
- bNodeSocketValueBoolean *val = default_value;
- val->value = value;
-}
-
-void node_socket_set_default_value_vector(void *default_value, PropertySubType subtype, float x, float y, float z, float min, float max)
-{
- bNodeSocketValueVector *val = default_value;
- val->subtype = subtype;
- val->value[0] = x;
- val->value[1] = y;
- val->value[2] = z;
- val->min = min;
- val->max = max;
-}
-
-void node_socket_set_default_value_rgba(void *default_value, float r, float g, float b, float a)
-{
- bNodeSocketValueRGBA *val = default_value;
- val->value[0] = r;
- val->value[1] = g;
- val->value[2] = b;
- val->value[3] = a;
-}
-
-void node_socket_set_default_value_string(void *default_value, PropertySubType subtype, const char *value)
-{
- bNodeSocketValueString *val = default_value;
- val->subtype = subtype;
- BLI_strncpy(val->value, value, 1024);//FILE_MAX
-}
-
-void node_socket_set_default_value_shader(void *UNUSED(default_value))
-{
-}
-
-void node_socket_set_default_value_mesh(void *UNUSED(default_value))
-{
-}
-
-
-void node_socket_copy_default_value(int type, void *to_default_value, void *from_default_value)
-{
- /* XXX only one of these pointers is valid! just putting them here for convenience */
- bNodeSocketValueFloat *fromfloat= (bNodeSocketValueFloat*)from_default_value;
- bNodeSocketValueInt *fromint= (bNodeSocketValueInt*)from_default_value;
- bNodeSocketValueBoolean *frombool= (bNodeSocketValueBoolean*)from_default_value;
- bNodeSocketValueVector *fromvector= (bNodeSocketValueVector*)from_default_value;
- bNodeSocketValueRGBA *fromrgba= (bNodeSocketValueRGBA*)from_default_value;
- bNodeSocketValueString *fromstring= (bNodeSocketValueString*)from_default_value;
-
- bNodeSocketValueFloat *tofloat= (bNodeSocketValueFloat*)to_default_value;
- bNodeSocketValueInt *toint= (bNodeSocketValueInt*)to_default_value;
- bNodeSocketValueBoolean *tobool= (bNodeSocketValueBoolean*)to_default_value;
- bNodeSocketValueVector *tovector= (bNodeSocketValueVector*)to_default_value;
- bNodeSocketValueRGBA *torgba= (bNodeSocketValueRGBA*)to_default_value;
- bNodeSocketValueString *tostring= (bNodeSocketValueString*)to_default_value;
-
- switch (type) {
- case SOCK_FLOAT:
- *tofloat = *fromfloat;
- break;
- case SOCK_INT:
- *toint = *fromint;
- break;
- case SOCK_BOOLEAN:
- *tobool = *frombool;
- break;
- case SOCK_VECTOR:
- *tovector = *fromvector;
- break;
- case SOCK_RGBA:
- *torgba = *fromrgba;
- break;
- case SOCK_STRING:
- *tostring = *fromstring;
- break;
- }
-}
-
-/* XXX This is a makeshift function to have useful initial group socket values.
- * In the end this should be implemented by a flexible socket data conversion system,
- * which is yet to be implemented. The idea is that beside default standard conversions,
- * such as int-to-float, it should be possible to quickly select a conversion method or
- * a chain of conversions for each input, whenever there is more than one option.
- * E.g. a vector-to-float conversion could use either of the x/y/z components or
- * the vector length.
- *
- * In the interface this could be implemented by a pseudo-script textbox on linked inputs,
- * with quick selection from a predefined list of conversion options. Some Examples:
- * - vector component 'z' (vector->float): "z"
- * - grayscale color (float->color): "gray"
- * - color luminance (color->float): "lum"
- * - matrix column 2 length (matrix->vector->float): "col[1].len"
- * - mesh vertex coordinate 'y' (mesh->vertex->vector->float): "vertex.co.y"
- *
- * The actual conversion is then done by a series of conversion functions,
- * which are defined in the socket type structs.
- */
-void node_socket_convert_default_value(int to_type, void *to_default_value, int from_type, void *from_default_value)
-{
- /* XXX only one of these pointers is valid! just putting them here for convenience */
- bNodeSocketValueFloat *fromfloat= (bNodeSocketValueFloat*)from_default_value;
- bNodeSocketValueInt *fromint= (bNodeSocketValueInt*)from_default_value;
- bNodeSocketValueBoolean *frombool= (bNodeSocketValueBoolean*)from_default_value;
- bNodeSocketValueVector *fromvector= (bNodeSocketValueVector*)from_default_value;
- bNodeSocketValueRGBA *fromrgba= (bNodeSocketValueRGBA*)from_default_value;
-
- bNodeSocketValueFloat *tofloat= (bNodeSocketValueFloat*)to_default_value;
- bNodeSocketValueInt *toint= (bNodeSocketValueInt*)to_default_value;
- bNodeSocketValueBoolean *tobool= (bNodeSocketValueBoolean*)to_default_value;
- bNodeSocketValueVector *tovector= (bNodeSocketValueVector*)to_default_value;
- bNodeSocketValueRGBA *torgba= (bNodeSocketValueRGBA*)to_default_value;
-
- switch (from_type) {
- case SOCK_FLOAT:
- switch (to_type) {
- case SOCK_FLOAT:
- tofloat->value = fromfloat->value;
- break;
- case SOCK_INT:
- toint->value = (int)fromfloat->value;
- break;
- case SOCK_BOOLEAN:
- tobool->value = (fromfloat->value > 0.0f);
- break;
- case SOCK_VECTOR:
- tovector->value[0] = tovector->value[1] = tovector->value[2] = fromfloat->value;
- break;
- case SOCK_RGBA:
- torgba->value[0] = torgba->value[1] = torgba->value[2] = torgba->value[3] = fromfloat->value;
- break;
- }
- break;
- case SOCK_INT:
- switch (to_type) {
- case SOCK_FLOAT:
- tofloat->value = (float)fromint->value;
- break;
- case SOCK_INT:
- toint->value = fromint->value;
- break;
- case SOCK_BOOLEAN:
- tobool->value = (fromint->value > 0);
- break;
- case SOCK_VECTOR:
- tovector->value[0] = tovector->value[1] = tovector->value[2] = (float)fromint->value;
- break;
- case SOCK_RGBA:
- torgba->value[0] = torgba->value[1] = torgba->value[2] = torgba->value[3] = (float)fromint->value;
- break;
- }
- break;
- case SOCK_BOOLEAN:
- switch (to_type) {
- case SOCK_FLOAT:
- tofloat->value = (float)frombool->value;
- break;
- case SOCK_INT:
- toint->value = (int)frombool->value;
- break;
- case SOCK_BOOLEAN:
- tobool->value = frombool->value;
- break;
- case SOCK_VECTOR:
- tovector->value[0] = tovector->value[1] = tovector->value[2] = (float)frombool->value;
- break;
- case SOCK_RGBA:
- torgba->value[0] = torgba->value[1] = torgba->value[2] = torgba->value[3] = (float)frombool->value;
- break;
- }
- break;
- case SOCK_VECTOR:
- switch (to_type) {
- case SOCK_FLOAT:
- tofloat->value = fromvector->value[0];
- break;
- case SOCK_INT:
- toint->value = (int)fromvector->value[0];
- break;
- case SOCK_BOOLEAN:
- tobool->value = (fromvector->value[0] > 0.0f);
- break;
- case SOCK_VECTOR:
- copy_v3_v3(tovector->value, fromvector->value);
- break;
- case SOCK_RGBA:
- copy_v3_v3(torgba->value, fromvector->value);
- torgba->value[3] = 1.0f;
+ /* initialize default_value */
+ switch (stemp->type) {
+ case SOCK_FLOAT: {
+ bNodeSocketValueFloat *dval = sock->default_value;
+ dval->value = stemp->val1;
+ dval->min = stemp->min;
+ dval->max = stemp->max;
break;
}
- break;
- case SOCK_RGBA:
- switch (to_type) {
- case SOCK_FLOAT:
- tofloat->value = fromrgba->value[0];
- break;
- case SOCK_INT:
- toint->value = (int)fromrgba->value[0];
- break;
- case SOCK_BOOLEAN:
- tobool->value = (fromrgba->value[0] > 0.0f);
- break;
- case SOCK_VECTOR:
- copy_v3_v3(tovector->value, fromrgba->value);
- break;
- case SOCK_RGBA:
- copy_v4_v4(torgba->value, fromrgba->value);
+ case SOCK_INT: {
+ bNodeSocketValueInt *dval = sock->default_value;
+ dval->value = (int)stemp->val1;
+ dval->min = (int)stemp->min;
+ dval->max = (int)stemp->max;
break;
}
- break;
- }
-}
-
-static void node_socket_set_minmax_subtype(bNodeSocket *sock, struct bNodeSocketTemplate *stemp)
-{
- switch (sock->type) {
- case SOCK_FLOAT:
- {
- bNodeSocketValueFloat *dval= sock->default_value;
- dval->min = stemp->min;
- dval->max = stemp->max;
- dval->subtype = stemp->subtype;
+ case SOCK_BOOLEAN: {
+ bNodeSocketValueBoolean *dval = sock->default_value;
+ dval->value = (int)stemp->val1;
break;
}
- case SOCK_INT:
- {
- bNodeSocketValueInt *dval= sock->default_value;
+ case SOCK_VECTOR: {
+ bNodeSocketValueVector *dval = sock->default_value;
+ dval->value[0] = stemp->val1;
+ dval->value[1] = stemp->val2;
+ dval->value[2] = stemp->val3;
dval->min = stemp->min;
dval->max = stemp->max;
- dval->subtype = stemp->subtype;
break;
}
- case SOCK_VECTOR:
- {
- bNodeSocketValueVector *dval= sock->default_value;
- dval->min = stemp->min;
- dval->max = stemp->max;
- dval->subtype = stemp->subtype;
+ case SOCK_RGBA: {
+ bNodeSocketValueRGBA *dval = sock->default_value;
+ dval->value[0] = stemp->val1;
+ dval->value[1] = stemp->val2;
+ dval->value[2] = stemp->val3;
+ dval->value[3] = stemp->val4;
break;
}
}
-}
-
-struct bNodeSocket *node_add_input_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp)
-{
- bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_IN, stemp->name, stemp->type);
- sock->flag |= stemp->flag;
-
- switch (stemp->type) {
- case SOCK_INT:
- node_socket_set_default_value_int(sock->default_value, stemp->subtype, (int)stemp->val1, (int)stemp->min, (int)stemp->max);
- break;
- case SOCK_FLOAT:
- node_socket_set_default_value_float(sock->default_value, stemp->subtype, stemp->val1, stemp->min, stemp->max);
- break;
- case SOCK_BOOLEAN:
- node_socket_set_default_value_boolean(sock->default_value, (char)stemp->val1);
- break;
- case SOCK_VECTOR:
- node_socket_set_default_value_vector(sock->default_value, stemp->subtype, stemp->val1, stemp->val2, stemp->val3, stemp->min, stemp->max);
- break;
- case SOCK_RGBA:
- node_socket_set_default_value_rgba(sock->default_value, stemp->val1, stemp->val2, stemp->val3, stemp->val4);
- break;
- case SOCK_SHADER:
- node_socket_set_default_value_shader(sock->default_value);
- break;
- case SOCK_MESH:
- node_socket_set_default_value_mesh(sock->default_value);
- break;
- case SOCK_STRING:
- node_socket_set_default_value_string(sock->default_value, stemp->subtype, (char *)"");
- break;
- }
return sock;
}
-struct bNodeSocket *node_add_output_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp)
-{
- bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_OUT, stemp->name, stemp->type);
- node_socket_set_minmax_subtype(sock, stemp);
- return sock;
-}
-
static bNodeSocket *verify_socket_template(bNodeTree *ntree, bNode *node, int in_out, ListBase *socklist, bNodeSocketTemplate *stemp)
{
bNodeSocket *sock;
for (sock= socklist->first; sock; sock= sock->next) {
- if (!(sock->flag & SOCK_DYNAMIC) && strncmp(sock->name, stemp->name, NODE_MAXSTR)==0)
+ if (strncmp(sock->name, stemp->name, NODE_MAXSTR)==0)
break;
}
if (sock) {
- sock->type = stemp->type; /* in future, read this from tydefs! */
+ sock->type = stemp->type;
if (stemp->limit == 0) sock->limit= 0xFFF;
else sock->limit = stemp->limit;
sock->flag |= stemp->flag;
- /* Copy the property range and subtype parameters in case the template changed.
- * NOT copying the actual value here, only button behavior changes!
- */
- node_socket_set_minmax_subtype(sock, stemp);
-
BLI_remlink(socklist, sock);
return sock;
}
else {
/* no socket for this template found, make a new one */
- if (in_out==SOCK_IN)
- sock = node_add_input_from_template(ntree, node, stemp);
- else
- sock = node_add_output_from_template(ntree, node, stemp);
+ sock = node_add_socket_from_template(ntree, node, stemp, in_out);
/* remove the new socket from the node socket list first,
* will be added back after verification.
*/
@@ -592,8 +140,7 @@ static void verify_socket_template_list(bNodeTree *ntree, bNode *node, int in_ou
if (stemp_first==NULL) {
for (sock = (bNodeSocket*)socklist->first; sock; sock=nextsock) {
nextsock = sock->next;
- if (!(sock->flag & SOCK_DYNAMIC))
- nodeRemoveSocket(ntree, node, sock);
+ nodeRemoveSocket(ntree, node, sock);
}
}
else {
@@ -606,8 +153,7 @@ static void verify_socket_template_list(bNodeTree *ntree, bNode *node, int in_ou
/* leftovers are removed */
for (sock = (bNodeSocket*)socklist->first; sock; sock=nextsock) {
nextsock = sock->next;
- if (!(sock->flag & SOCK_DYNAMIC))
- nodeRemoveSocket(ntree, node, sock);
+ nodeRemoveSocket(ntree, node, sock);
}
/* and we put back the verified sockets */
@@ -635,14 +181,184 @@ static void verify_socket_template_list(bNodeTree *ntree, bNode *node, int in_ou
void node_verify_socket_templates(bNodeTree *ntree, bNode *node)
{
bNodeType *ntype= node->typeinfo;
- /* XXX Small trick: don't try to match socket lists when there are no templates.
- * This also prevents group node sockets from being removed, without the need to explicitly
+ /* Don't try to match socket lists when there are no templates.
+ * This prevents group node sockets from being removed, without the need to explicitly
* check the node type here.
*/
- if (ntype && ((ntype->inputs && ntype->inputs[0].type >= 0) ||
- (ntype->outputs && ntype->outputs[0].type >= 0)))
- {
- verify_socket_template_list(ntree, node, SOCK_IN, &node->inputs, ntype->inputs);
- verify_socket_template_list(ntree, node, SOCK_OUT, &node->outputs, ntype->outputs);
+ if (ntype) {
+ if (ntype->inputs && ntype->inputs[0].type >= 0)
+ verify_socket_template_list(ntree, node, SOCK_IN, &node->inputs, ntype->inputs);
+ if (ntype->outputs && ntype->outputs[0].type >= 0)
+ verify_socket_template_list(ntree, node, SOCK_OUT, &node->outputs, ntype->outputs);
+ }
+}
+
+
+void node_socket_init_default_value(bNodeSocket *sock)
+{
+ int type = sock->typeinfo->type;
+ int subtype = sock->typeinfo->subtype;
+
+ if (sock->default_value)
+ return; /* already initialized */
+
+ switch (type) {
+ case SOCK_FLOAT: {
+ bNodeSocketValueFloat *dval = MEM_callocN(sizeof(bNodeSocketValueFloat), "node socket value float");
+ dval->subtype = subtype;
+ dval->value = 0.0f;
+ dval->min = -FLT_MAX;
+ dval->max = FLT_MAX;
+
+ sock->default_value = dval;
+ break;
+ }
+ case SOCK_INT: {
+ bNodeSocketValueInt *dval = MEM_callocN(sizeof(bNodeSocketValueInt), "node socket value int");
+ dval->subtype = subtype;
+ dval->value = 0;
+ dval->min = INT_MIN;
+ dval->max = INT_MAX;
+
+ sock->default_value = dval;
+ break;
+ }
+ case SOCK_BOOLEAN: {
+ bNodeSocketValueBoolean *dval = MEM_callocN(sizeof(bNodeSocketValueBoolean), "node socket value bool");
+ dval->value = false;
+
+ sock->default_value = dval;
+ break;
+ }
+ case SOCK_VECTOR: {
+ static float default_value[] = { 0.0f, 0.0f, 0.0f };
+ bNodeSocketValueVector *dval = MEM_callocN(sizeof(bNodeSocketValueVector), "node socket value vector");
+ dval->subtype = subtype;
+ copy_v3_v3(dval->value, default_value);
+ dval->min = -FLT_MAX;
+ dval->max = FLT_MAX;
+
+ sock->default_value = dval;
+ break;
}
+ case SOCK_RGBA: {
+ static float default_value[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+ bNodeSocketValueRGBA *dval = MEM_callocN(sizeof(bNodeSocketValueRGBA), "node socket value color");
+ copy_v4_v4(dval->value, default_value);
+
+ sock->default_value = dval;
+ break;
+ }
+ case SOCK_STRING: {
+ bNodeSocketValueString *dval = MEM_callocN(sizeof(bNodeSocketValueString), "node socket value string");
+ dval->subtype = subtype;
+ dval->value[0] = '\0';
+
+ sock->default_value = dval;
+ break;
+ }
+ }
+}
+
+
+static void standard_node_socket_interface_init_socket(bNodeTree *UNUSED(ntree), bNodeSocket *UNUSED(stemp), bNode *UNUSED(node), bNodeSocket *sock, const char *UNUSED(data_path))
+{
+ /* initialize the type value */
+ sock->type = sock->typeinfo->type;
+}
+
+static bNodeSocketType *make_standard_socket_type(int type, int subtype)
+{
+ extern void ED_init_standard_node_socket_type(bNodeSocketType *);
+
+ const char *socket_idname = nodeStaticSocketType(type, subtype);
+ const char *interface_idname = nodeStaticSocketInterfaceType(type, subtype);
+ bNodeSocketType *stype;
+ StructRNA *srna;
+
+ stype = MEM_callocN(sizeof(bNodeSocketType), "node socket C type");
+ BLI_strncpy(stype->idname, socket_idname, sizeof(stype->idname));
+
+ /* set the RNA type
+ * uses the exact same identifier as the socket type idname */
+ srna = stype->ext_socket.srna = RNA_struct_find(socket_idname);
+ BLI_assert(srna != NULL);
+ /* associate the RNA type with the socket type */
+ RNA_struct_blender_type_set(srna, stype);
+
+ /* set the interface RNA type */
+ srna = stype->ext_interface.srna = RNA_struct_find(interface_idname);
+ BLI_assert(srna != NULL);
+ /* associate the RNA type with the socket type */
+ RNA_struct_blender_type_set(srna, stype);
+
+ /* extra type info for standard socket types */
+ stype->type = type;
+ stype->subtype = subtype;
+
+ /* XXX bad-level call! needed for setting draw callbacks */
+ ED_init_standard_node_socket_type(stype);
+
+ stype->interface_init_socket = standard_node_socket_interface_init_socket;
+
+ return stype;
+}
+
+static bNodeSocketType *make_socket_type_virtual(void)
+{
+ extern void ED_init_node_socket_type_virtual(bNodeSocketType *);
+
+ const char *socket_idname = "NodeSocketVirtual";
+ bNodeSocketType *stype;
+ StructRNA *srna;
+
+ stype = MEM_callocN(sizeof(bNodeSocketType), "node socket C type");
+ BLI_strncpy(stype->idname, socket_idname, sizeof(stype->idname));
+
+ /* set the RNA type
+ * uses the exact same identifier as the socket type idname */
+ srna = stype->ext_socket.srna = RNA_struct_find(socket_idname);
+ BLI_assert(srna != NULL);
+ /* associate the RNA type with the socket type */
+ RNA_struct_blender_type_set(srna, stype);
+
+ ED_init_node_socket_type_virtual(stype);
+
+ return stype;
+}
+
+
+void register_standard_node_socket_types(void)
+{
+ /* draw callbacks are set in drawnode.c to avoid bad-level calls */
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_NONE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_UNSIGNED));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_PERCENTAGE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_FACTOR));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_ANGLE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_FLOAT, PROP_TIME));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_NONE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_UNSIGNED));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_PERCENTAGE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_INT, PROP_FACTOR));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_BOOLEAN, PROP_NONE));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_NONE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_TRANSLATION));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_DIRECTION));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_VELOCITY));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_ACCELERATION));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_EULER));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_VECTOR, PROP_XYZ));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_RGBA, PROP_NONE));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_STRING, PROP_NONE));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_SHADER, PROP_NONE));
+
+ nodeRegisterSocketType(make_socket_type_virtual());
}
diff --git a/source/blender/nodes/intern/node_util.c b/source/blender/nodes/intern/node_util.c
index 09e6ddd18a5..c622c1c5227 100644
--- a/source/blender/nodes/intern/node_util.c
+++ b/source/blender/nodes/intern/node_util.c
@@ -30,6 +30,7 @@
*/
#include <limits.h>
+#include <string.h>
#include "DNA_action_types.h"
#include "DNA_node_types.h"
@@ -63,17 +64,17 @@ void node_free_standard_storage(bNode *node)
}
}
-void node_copy_curves(bNode *orig_node, bNode *new_node)
+void node_copy_curves(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node)
{
- new_node->storage = curvemapping_copy(orig_node->storage);
+ dest_node->storage = curvemapping_copy(src_node->storage);
}
-void node_copy_standard_storage(bNode *orig_node, bNode *new_node)
+void node_copy_standard_storage(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node)
{
- new_node->storage = MEM_dupallocN(orig_node->storage);
+ dest_node->storage = MEM_dupallocN(src_node->storage);
}
-void *node_initexec_curves(bNode *node)
+void *node_initexec_curves(bNodeExecContext *UNUSED(context), bNode *node, bNodeInstanceKey UNUSED(key))
{
curvemapping_initialize(node->storage);
return NULL; /* unused return */
@@ -129,6 +130,8 @@ void node_update_internal_links_default(bNodeTree *ntree, bNode *node)
fromindex = INT_MAX;
fromsock = NULL;
for (link=ntree->links.first; link; link=link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
if (link->tonode == node && link->tosock->type == datatype) {
int index = BLI_findindex(&node->inputs, link->tosock);
if (index < fromindex) {
@@ -146,6 +149,8 @@ void node_update_internal_links_default(bNodeTree *ntree, bNode *node)
toindex = INT_MAX;
tosock = NULL;
for (link=ntree->links.first; link; link=link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
if (link->fromnode == node && link->fromsock->type == datatype) {
int index = BLI_findindex(&node->outputs, link->fromsock);
if (index < toindex) {
@@ -188,3 +193,45 @@ void node_update_internal_links_default(bNodeTree *ntree, bNode *node)
BLI_addtail(&node->internal_links, ilink);
}
}
+
+float node_socket_get_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+ return RNA_float_get(&ptr, "default_value");
+}
+
+void node_socket_set_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float value)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+ RNA_float_set(&ptr, "default_value", value);
+}
+
+void node_socket_get_color(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float *value)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+ RNA_float_get_array(&ptr, "default_value", value);
+}
+
+void node_socket_set_color(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, const float *value)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+ RNA_float_set_array(&ptr, "default_value", value);
+}
+
+void node_socket_get_vector(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float *value)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+ RNA_float_get_array(&ptr, "default_value", value);
+}
+
+void node_socket_set_vector(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, const float *value)
+{
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+ RNA_float_set_array(&ptr, "default_value", value);
+}
diff --git a/source/blender/nodes/intern/node_util.h b/source/blender/nodes/intern/node_util.h
index 3134baa283c..2b3f84420f9 100644
--- a/source/blender/nodes/intern/node_util.h
+++ b/source/blender/nodes/intern/node_util.h
@@ -35,6 +35,8 @@
#include "DNA_listBase.h"
+#include "BLI_utildefines.h"
+
#include "BKE_node.h"
#include "MEM_guardedalloc.h"
@@ -43,17 +45,29 @@
#include "GPU_material.h" /* For Shader muting GPU code... */
+#include "RNA_access.h"
+
struct bNodeTree;
struct bNode;
+/* data for initializing node execution */
+typedef struct bNodeExecContext {
+ struct bNodeInstanceHash *previews;
+} bNodeExecContext;
+
+typedef struct bNodeExecData {
+ void *data; /* custom data storage */
+ struct bNodePreview *preview; /* optional preview image */
+} bNodeExecData;
+
/**** Storage Data ****/
extern void node_free_curves(struct bNode *node);
extern void node_free_standard_storage(struct bNode *node);
-extern void node_copy_curves(struct bNode *orig_node, struct bNode *new_node);
-extern void node_copy_standard_storage(struct bNode *orig_node, struct bNode *new_node);
-extern void *node_initexec_curves(struct bNode *node);
+extern void node_copy_curves(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node);
+extern void node_copy_standard_storage(struct bNodeTree *dest_ntree, struct bNode *dest_node, struct bNode *src_node);
+extern void *node_initexec_curves(struct bNodeExecContext *context, struct bNode *node, bNodeInstanceKey key);
/**** Labels ****/
@@ -64,14 +78,11 @@ const char *node_filter_label(struct bNode *node);
void node_update_internal_links_default(struct bNodeTree *ntree, struct bNode *node);
-#endif
+float node_socket_get_float(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock);
+void node_socket_set_float(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, float value);
+void node_socket_get_color(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, float *value);
+void node_socket_set_color(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, const float *value);
+void node_socket_get_vector(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, float *value);
+void node_socket_set_vector(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, const float *value);
-// this is needed for inlining behavior
-#if defined _MSC_VER
-# define DO_INLINE __inline
-#elif defined (__sun) || defined (__sun__)
-# define DO_INLINE
-#else
-# define DO_INLINE static inline
#endif
-
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index b7dc83d7d79..50ef122fe60 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -36,6 +36,7 @@
#include "DNA_material_types.h"
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
#include "DNA_world_types.h"
#include "BLI_listbase.h"
@@ -45,11 +46,14 @@
#include "BLF_translation.h"
+#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_scene.h"
+#include "RNA_access.h"
+
#include "GPU_material.h"
#include "RE_shader_ext.h"
@@ -59,23 +63,44 @@
#include "node_util.h"
#include "node_shader_util.h"
-static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func)
+static int shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype))
{
- Material *ma;
- Lamp *la;
- World *wo;
-
- for (ma = main->mat.first; ma; ma = ma->id.next)
- if (ma->nodetree)
- func(calldata, &ma->id, ma->nodetree);
-
- for (la = main->lamp.first; la; la = la->id.next)
- if (la->nodetree)
- func(calldata, &la->id, la->nodetree);
+ 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'
+ || strcmp(scene->r.engine, "BLENDER_RENDER")==0
+ || strcmp(scene->r.engine, "CYCLES")==0);
+}
- for (wo = main->world.first; wo; wo = wo->id.next)
- if (wo->nodetree)
- func(calldata, &wo->id, wo->nodetree);
+static void shader_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = OBACT;
+
+ if (snode->shaderfrom == SNODE_SHADER_OBJECT) {
+ if (ob) {
+ *r_from = &ob->id;
+ if (ob->type == OB_LAMP) {
+ *r_id = ob->data;
+ *r_ntree = ((Lamp *)ob->data)->nodetree;
+ }
+ else {
+ Material *ma = give_current_material(ob, ob->actcol);
+ if (ma) {
+ *r_id = &ma->id;
+ *r_ntree = ma->nodetree;
+ }
+ }
+ }
+ }
+ else { /* SNODE_SHADER_WORLD */
+ if (scene->world) {
+ *r_from = NULL;
+ *r_id = &scene->world->id;
+ *r_ntree = scene->world->nodetree;
+ }
+ }
}
static void foreach_nodeclass(Scene *scene, void *calldata, bNodeClassCallback func)
@@ -93,6 +118,7 @@ static void foreach_nodeclass(Scene *scene, void *calldata, bNodeClassCallback f
func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor"));
func(calldata, NODE_CLASS_SCRIPT, N_("Script"));
func(calldata, NODE_CLASS_GROUP, N_("Group"));
+ func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
}
@@ -113,22 +139,12 @@ static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree))
static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
{
- bNode *lnode;
-
- /* copy over contents of previews */
- for (lnode = localtree->nodes.first; lnode; lnode = lnode->next) {
- if (ntreeNodeExists(ntree, lnode->new_node)) {
- bNode *node = lnode->new_node;
-
- if (node->preview && node->preview->rect) {
- if (lnode->preview && lnode->preview->rect) {
- int xsize = node->preview->xsize;
- int ysize = node->preview->ysize;
- memcpy(node->preview->rect, lnode->preview->rect, 4 * xsize + xsize * ysize * sizeof(char) * 4);
- }
- }
- }
- }
+ BKE_node_preview_sync_tree(ntree, localtree);
+}
+
+static void local_merge(bNodeTree *localtree, bNodeTree *ntree)
+{
+ BKE_node_preview_merge_tree(ntree, localtree, true);
}
static void update(bNodeTree *ntree)
@@ -136,26 +152,37 @@ static void update(bNodeTree *ntree)
ntreeSetOutput(ntree);
ntree_update_reroute_nodes(ntree);
+
+ if (ntree->update & NTREE_UPDATE_NODES) {
+ /* clean up preview cache, in case nodes have been removed */
+ BKE_node_preview_remove_unused(ntree);
+ }
}
-bNodeTreeType ntreeType_Shader = {
- /* type */ NTREE_SHADER,
- /* id_name */ "NTShader Nodetree",
+bNodeTreeType *ntreeType_Shader;
+
+void register_node_tree_type_sh(void)
+{
+ bNodeTreeType *tt = ntreeType_Shader = MEM_callocN(sizeof(bNodeTreeType), "shader node tree type");
+
+ tt->type = NTREE_SHADER;
+ strcpy(tt->idname, "ShaderNodeTree");
+ strcpy(tt->ui_name, "Shader");
+ tt->ui_icon = 0; /* defined in drawnode.c */
+ strcpy(tt->ui_description, "");
- /* node_types */ { NULL, NULL },
+ tt->foreach_nodeclass = foreach_nodeclass;
+ tt->localize = localize;
+ tt->local_sync = local_sync;
+ tt->local_merge = local_merge;
+ tt->update = update;
+ tt->poll = shader_tree_poll;
+ tt->get_from_context = shader_get_from_context;
- /* free_cache */ NULL,
- /* free_node_cache */ NULL,
- /* foreach_nodetree */ foreach_nodetree,
- /* foreach_nodeclass */ foreach_nodeclass,
- /* localize */ localize,
- /* local_sync */ local_sync,
- /* local_merge */ NULL,
- /* update */ update,
- /* update_node */ NULL,
- /* validate_link */ NULL,
- /* update_internal_links */ node_update_internal_links_default
-};
+ tt->ext.srna = &RNA_ShaderNodeTree;
+
+ ntreeTypeAdd(tt);
+}
/* GPU material from shader nodes */
@@ -163,11 +190,11 @@ void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat)
{
bNodeTreeExec *exec;
- exec = ntreeShaderBeginExecTree(ntree, 1);
+ exec = ntreeShaderBeginExecTree(ntree);
ntreeExecGPUNodes(exec, mat, 1);
- ntreeShaderEndExecTree(exec, 1);
+ ntreeShaderEndExecTree(exec);
}
/* **************** call to switch lamploop for material node ************ */
@@ -180,27 +207,16 @@ void set_node_shader_lamp_loop(void (*lamp_loop_func)(ShadeInput *, ShadeResult
}
-/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
- * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
- */
-bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree, int use_tree_data)
+bNodeTreeExec *ntreeShaderBeginExecTree_internal(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
{
bNodeTreeExec *exec;
bNode *node;
- if (use_tree_data) {
- /* XXX hack: prevent exec data from being generated twice.
- * this should be handled by the renderer!
- */
- if (ntree->execdata)
- return ntree->execdata;
- }
-
/* ensures only a single output node is enabled */
ntreeSetOutput(ntree);
/* common base initialization */
- exec = ntree_exec_begin(ntree);
+ exec = ntree_exec_begin(context, ntree, parent_key);
/* allocate the thread stack listbase array */
exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array");
@@ -208,47 +224,63 @@ bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree, int use_tree_data)
for (node = exec->nodetree->nodes.first; node; node = node->next)
node->need_exec = 1;
- if (use_tree_data) {
- /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
- * which only store the ntree pointer. Should be fixed at some point!
- */
- ntree->execdata = exec;
- }
+ return exec;
+}
+
+bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree)
+{
+ bNodeExecContext context;
+ bNodeTreeExec *exec;
+
+ /* XXX hack: prevent exec data from being generated twice.
+ * this should be handled by the renderer!
+ */
+ if (ntree->execdata)
+ return ntree->execdata;
+
+ context.previews = ntree->previews;
+
+ exec = ntreeShaderBeginExecTree_internal(&context, ntree, NODE_INSTANCE_KEY_BASE);
+
+ /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
+ * which only store the ntree pointer. Should be fixed at some point!
+ */
+ ntree->execdata = exec;
return exec;
}
-/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
- * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
- */
-void ntreeShaderEndExecTree(bNodeTreeExec *exec, int use_tree_data)
+void ntreeShaderEndExecTree_internal(bNodeTreeExec *exec)
{
- if (exec) {
- bNodeTree *ntree = exec->nodetree;
- bNodeThreadStack *nts;
- int a;
-
- if (exec->threadstack) {
- for (a = 0; a < BLENDER_MAX_THREADS; a++) {
- for (nts = exec->threadstack[a].first; nts; nts = nts->next)
- if (nts->stack) MEM_freeN(nts->stack);
- BLI_freelistN(&exec->threadstack[a]);
- }
-
- MEM_freeN(exec->threadstack);
- exec->threadstack = NULL;
+ bNodeThreadStack *nts;
+ int a;
+
+ if (exec->threadstack) {
+ for (a = 0; a < BLENDER_MAX_THREADS; a++) {
+ for (nts = exec->threadstack[a].first; nts; nts = nts->next)
+ if (nts->stack) MEM_freeN(nts->stack);
+ BLI_freelistN(&exec->threadstack[a]);
}
- ntree_exec_end(exec);
+ MEM_freeN(exec->threadstack);
+ exec->threadstack = NULL;
+ }
+
+ ntree_exec_end(exec);
+}
+
+void ntreeShaderEndExecTree(bNodeTreeExec *exec)
+{
+ if (exec) {
+ ntreeShaderEndExecTree_internal(exec);
- if (use_tree_data) {
- /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
- ntree->execdata = NULL;
- }
+ /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
+ exec->nodetree->execdata = NULL;
}
}
-void ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr)
+/* only for Blender internal */
+bool ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr)
{
ShaderCallData scd;
/**
@@ -258,6 +290,7 @@ void ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr)
Material *mat = shi->mat;
bNodeThreadStack *nts = NULL;
bNodeTreeExec *exec = ntree->execdata;
+ int compat;
/* convert caller data to struct */
scd.shi = shi;
@@ -270,20 +303,24 @@ void ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr)
if (!exec) {
BLI_lock_thread(LOCK_NODES);
if (!ntree->execdata)
- ntree->execdata = ntreeShaderBeginExecTree(ntree, 1);
+ ntree->execdata = ntreeShaderBeginExecTree(ntree);
BLI_unlock_thread(LOCK_NODES);
exec = ntree->execdata;
}
nts = ntreeGetThreadStack(exec, shi->thread);
- ntreeExecThreadNodes(exec, nts, &scd, shi->thread);
+ compat = ntreeExecThreadNodes(exec, nts, &scd, shi->thread);
ntreeReleaseThreadStack(nts);
// \note: set material back to preserved material
shi->mat = mat;
+
/* better not allow negative for now */
if (shr->combined[0] < 0.0f) shr->combined[0] = 0.0f;
if (shr->combined[1] < 0.0f) shr->combined[1] = 0.0f;
if (shr->combined[2] < 0.0f) shr->combined[2] = 0.0f;
+
+ /* if compat is zero, it has been using non-compatible nodes */
+ return compat;
}
diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c
index 6130fe72af3..c8c4b49edb7 100644
--- a/source/blender/nodes/shader/node_shader_util.c
+++ b/source/blender/nodes/shader/node_shader_util.c
@@ -36,6 +36,20 @@
#include "node_exec.h"
+
+int sh_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree)
+{
+ return (strcmp(ntree->idname, "ShaderNodeTree")==0);
+}
+
+void sh_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag)
+{
+ node_type_base(ntype, type, name, nclass, flag);
+
+ ntype->poll = sh_node_poll_default;
+ ntype->update_internal_links = node_update_internal_links_default;
+}
+
/* ****** */
void nodestack_get_vec(float *in, short type_in, bNodeStack *ns)
@@ -46,7 +60,7 @@ void nodestack_get_vec(float *in, short type_in, bNodeStack *ns)
if (ns->sockettype==SOCK_FLOAT)
*in= *from;
else
- *in= 0.333333f*(from[0]+from[1]+from[2]);
+ *in= (from[0]+from[1]+from[2]) / 3.0f;
}
else if (type_in==SOCK_VECTOR) {
if (ns->sockettype==SOCK_FLOAT) {
@@ -84,7 +98,7 @@ void ntreeShaderGetTexcoMode(bNodeTree *ntree, int r_mode, short *texco, int *mo
bNodeSocket *sock;
int a;
- for (node= ntree->nodes.first; node; node= node->next) {
+ for (node = ntree->nodes.first; node; node = node->next) {
if (node->type==SH_NODE_TEXTURE) {
if ((r_mode & R_OSA) && node->id) {
Tex *tex= (Tex *)node->id;
@@ -123,74 +137,6 @@ void ntreeShaderGetTexcoMode(bNodeTree *ntree, int r_mode, short *texco, int *mo
}
}
-/* nodes that use ID data get synced with local data */
-void nodeShaderSynchronizeID(bNode *node, int copyto)
-{
- if (node->id==NULL) return;
-
- if (ELEM(node->type, SH_NODE_MATERIAL, SH_NODE_MATERIAL_EXT)) {
- bNodeSocket *sock;
- Material *ma= (Material *)node->id;
- int a;
-
- /* 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 (copyto) {
- switch (a) {
- case MAT_IN_COLOR:
- copy_v3_v3(&ma->r, ((bNodeSocketValueRGBA*)sock->default_value)->value); break;
- case MAT_IN_SPEC:
- copy_v3_v3(&ma->specr, ((bNodeSocketValueRGBA*)sock->default_value)->value); break;
- case MAT_IN_REFL:
- ma->ref= ((bNodeSocketValueFloat*)sock->default_value)->value; break;
- case MAT_IN_MIR:
- copy_v3_v3(&ma->mirr, ((bNodeSocketValueRGBA*)sock->default_value)->value); break;
- case MAT_IN_AMB:
- ma->amb= ((bNodeSocketValueFloat*)sock->default_value)->value; break;
- case MAT_IN_EMIT:
- ma->emit= ((bNodeSocketValueFloat*)sock->default_value)->value; break;
- case MAT_IN_SPECTRA:
- ma->spectra= ((bNodeSocketValueFloat*)sock->default_value)->value; break;
- case MAT_IN_RAY_MIRROR:
- ma->ray_mirror= ((bNodeSocketValueFloat*)sock->default_value)->value; break;
- case MAT_IN_ALPHA:
- ma->alpha= ((bNodeSocketValueFloat*)sock->default_value)->value; break;
- case MAT_IN_TRANSLUCENCY:
- ma->translucency= ((bNodeSocketValueFloat*)sock->default_value)->value; break;
- }
- }
- else {
- switch (a) {
- case MAT_IN_COLOR:
- copy_v3_v3(((bNodeSocketValueRGBA*)sock->default_value)->value, &ma->r); break;
- case MAT_IN_SPEC:
- copy_v3_v3(((bNodeSocketValueRGBA*)sock->default_value)->value, &ma->specr); break;
- case MAT_IN_REFL:
- ((bNodeSocketValueFloat*)sock->default_value)->value= ma->ref; break;
- case MAT_IN_MIR:
- copy_v3_v3(((bNodeSocketValueRGBA*)sock->default_value)->value, &ma->mirr); break;
- case MAT_IN_AMB:
- ((bNodeSocketValueFloat*)sock->default_value)->value= ma->amb; break;
- case MAT_IN_EMIT:
- ((bNodeSocketValueFloat*)sock->default_value)->value= ma->emit; break;
- case MAT_IN_SPECTRA:
- ((bNodeSocketValueFloat*)sock->default_value)->value= ma->spectra; break;
- case MAT_IN_RAY_MIRROR:
- ((bNodeSocketValueFloat*)sock->default_value)->value= ma->ray_mirror; break;
- case MAT_IN_ALPHA:
- ((bNodeSocketValueFloat*)sock->default_value)->value= ma->alpha; break;
- case MAT_IN_TRANSLUCENCY:
- ((bNodeSocketValueFloat*)sock->default_value)->value= ma->translucency; break;
- }
- }
- }
- }
- }
-
-}
-
-
void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, bNodeStack *ns)
{
memset(gs, 0, sizeof(*gs));
@@ -221,6 +167,7 @@ void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, bNodeStack *ns)
void node_data_from_gpu_stack(bNodeStack *ns, GPUNodeStack *gs)
{
+ copy_v4_v4(ns->vec, gs->vec);
ns->data= gs->link;
ns->sockettype= gs->sockettype;
}
@@ -230,7 +177,7 @@ static void gpu_stack_from_data_list(GPUNodeStack *gs, ListBase *sockets, bNodeS
bNodeSocket *sock;
int i;
- for (sock=sockets->first, i=0; sock; sock=sock->next, i++)
+ for (sock=sockets->first, i=0; sock; sock = sock->next, i++)
node_gpu_stack_from_data(&gs[i], sock->type, ns[i]);
gs[i].type= GPU_NONE;
@@ -241,30 +188,31 @@ static void data_from_gpu_stack_list(ListBase *sockets, bNodeStack **ns, GPUNode
bNodeSocket *sock;
int i;
- for (sock=sockets->first, i=0; sock; sock=sock->next, i++)
+ for (sock=sockets->first, i=0; sock; sock = sock->next, i++)
node_data_from_gpu_stack(ns[i], &gs[i]);
}
bNode *nodeGetActiveTexture(bNodeTree *ntree)
{
/* this is the node we texture paint and draw in textured draw */
- bNode *node;
+ bNode *node, *tnode;
if (!ntree)
return NULL;
- /* check for group edit */
- for (node= ntree->nodes.first; node; node= node->next)
- if (node->flag & NODE_GROUP_EDIT)
- break;
-
- if (node)
- ntree= (bNodeTree*)node->id;
-
- for (node= ntree->nodes.first; node; node= node->next)
+ for (node = ntree->nodes.first; node; node = node->next)
if (node->flag & NODE_ACTIVE_TEXTURE)
return node;
+ /* node active texture node in this tree, look inside groups */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->type==NODE_GROUP) {
+ tnode = nodeGetActiveTexture((bNodeTree*)node->id);
+ if (tnode)
+ return tnode;
+ }
+ }
+
return NULL;
}
@@ -276,7 +224,7 @@ void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, int do_outputs)
bNodeStack *stack;
bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */
- GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1];
+ GPUNodeStack gpuin[MAX_SOCKET + 1], gpuout[MAX_SOCKET + 1];
int do_it;
stack= exec->stack;
@@ -298,14 +246,7 @@ void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, int do_outputs)
node_get_stack(node, stack, nsin, nsout);
gpu_stack_from_data_list(gpuin, &node->inputs, nsin);
gpu_stack_from_data_list(gpuout, &node->outputs, nsout);
- if (node->typeinfo->gpufunc(mat, node, gpuin, gpuout))
- data_from_gpu_stack_list(&node->outputs, nsout, gpuout);
- }
- else if (node->typeinfo->gpuextfunc) {
- node_get_stack(node, stack, nsin, nsout);
- gpu_stack_from_data_list(gpuin, &node->inputs, nsin);
- gpu_stack_from_data_list(gpuout, &node->outputs, nsout);
- if (node->typeinfo->gpuextfunc(mat, node, nodeexec->data, gpuin, gpuout))
+ if (node->typeinfo->gpufunc(mat, node, &nodeexec->data, gpuin, gpuout))
data_from_gpu_stack_list(&node->outputs, nsout, gpuout);
}
}
@@ -320,7 +261,7 @@ void node_shader_gpu_tex_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in
float domax= (texmap->flag & TEXMAP_CLIP_MAX) != 0;
if (domin || domax || !(texmap->flag & TEXMAP_UNIT_MATRIX)) {
- GPUNodeLink *tmat = GPU_uniform((float*)texmap->mat);
+ GPUNodeLink *tmat = GPU_uniform((float *)texmap->mat);
GPUNodeLink *tmin = GPU_uniform(texmap->min);
GPUNodeLink *tmax = GPU_uniform(texmap->max);
GPUNodeLink *tdomin = GPU_uniform(&domin);
diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h
index e4dc74e8d40..57b129335bb 100644
--- a/source/blender/nodes/shader/node_shader_util.h
+++ b/source/blender/nodes/shader/node_shader_util.h
@@ -49,6 +49,12 @@
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_rand.h"
+#include "BLI_threads.h"
+#include "BLI_utildefines.h"
+
#include "BKE_blender.h"
#include "BKE_colortools.h"
#include "BKE_global.h"
@@ -63,12 +69,6 @@
#include "NOD_shader.h"
#include "node_util.h"
-#include "BLI_math.h"
-#include "BLI_blenlib.h"
-#include "BLI_rand.h"
-#include "BLI_threads.h"
-#include "BLI_utildefines.h"
-
#include "BLF_translation.h"
#include "IMB_imbuf_types.h"
@@ -79,6 +79,11 @@
#include "GPU_material.h"
+
+int sh_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree);
+void sh_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag);
+
+
/* ********* exec data struct, remains internal *********** */
typedef struct ShaderCallData {
@@ -86,40 +91,6 @@ typedef struct ShaderCallData {
ShadeResult *shr; /* from render pipe */
} ShaderCallData;
-/* output socket defines */
-#define GEOM_OUT_GLOB 0
-#define GEOM_OUT_LOCAL 1
-#define GEOM_OUT_VIEW 2
-#define GEOM_OUT_ORCO 3
-#define GEOM_OUT_UV 4
-#define GEOM_OUT_NORMAL 5
-#define GEOM_OUT_VCOL 6
-#define GEOM_OUT_VCOL_ALPHA 7
-#define GEOM_OUT_FRONTBACK 8
-
-
-/* input socket defines */
-#define MAT_IN_COLOR 0
-#define MAT_IN_SPEC 1
-#define MAT_IN_REFL 2
-#define MAT_IN_NORMAL 3
-#define MAT_IN_MIR 4
-#define MAT_IN_AMB 5
-#define MAT_IN_EMIT 6
-#define MAT_IN_SPECTRA 7
-#define MAT_IN_RAY_MIRROR 8
-#define MAT_IN_ALPHA 9
-#define MAT_IN_TRANSLUCENCY 10
-#define NUM_MAT_IN 11 /* for array size */
-
-/* output socket defines */
-#define MAT_OUT_COLOR 0
-#define MAT_OUT_ALPHA 1
-#define MAT_OUT_NORMAL 2
-#define MAT_OUT_DIFFUSE 3
-#define MAT_OUT_SPEC 4
-#define MAT_OUT_AO 5
-
extern void node_ID_title_cb(void *node_v, void *unused_v);
void nodestack_get_vec(float *in, short type_in, bNodeStack *ns);
diff --git a/source/blender/nodes/shader/nodes/node_shader_add_shader.c b/source/blender/nodes/shader/nodes/node_shader_add_shader.c
index ec868b2cc38..92b8d2d8111 100644
--- a/source/blender/nodes/shader/nodes/node_shader_add_shader.c
+++ b/source/blender/nodes/shader/nodes/node_shader_add_shader.c
@@ -40,24 +40,23 @@ static bNodeSocketTemplate sh_node_add_shader_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_add_shader(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_add_shader(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_add_shader", in, out);
}
/* node type definition */
-void register_node_type_sh_add_shader(bNodeTreeType *ttype)
+void register_node_type_sh_add_shader(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_ADD_SHADER, "Add Shader", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_ADD_SHADER, "Add Shader", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_add_shader_in, sh_node_add_shader_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_add_shader);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c
index 7dfefc9ece0..e3beb9e03b6 100644
--- a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c
+++ b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c
@@ -39,25 +39,24 @@ static bNodeSocketTemplate sh_node_ambient_occlusion_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_ambient_occlusion", in, out, GPU_builtin(GPU_VIEW_NORMAL));
}
/* node type definition */
-void register_node_type_sh_ambient_occlusion(bNodeTreeType *ttype)
+void register_node_type_sh_ambient_occlusion(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_AMBIENT_OCCLUSION, "Ambient Occlusion", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_AMBIENT_OCCLUSION, "Ambient Occlusion", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_ambient_occlusion_in, sh_node_ambient_occlusion_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_ambient_occlusion);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_attribute.c b/source/blender/nodes/shader/nodes/node_shader_attribute.c
index 9b2ed2f14f0..e3887a1d14d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_attribute.c
+++ b/source/blender/nodes/shader/nodes/node_shader_attribute.c
@@ -36,25 +36,23 @@ static bNodeSocketTemplate sh_node_attribute_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_attribute(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_attribute(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeShaderAttribute *attr = MEM_callocN(sizeof(NodeShaderAttribute), "NodeShaderAttribute");
node->storage = attr;
}
/* node type definition */
-void register_node_type_sh_attribute(bNodeTreeType *ttype)
+void register_node_type_sh_attribute(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_ATTRIBUTE, "Attribute", NODE_CLASS_INPUT, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_ATTRIBUTE, "Attribute", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_attribute_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_attribute);
node_type_storage(&ntype, "NodeShaderAttribute", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
- node_type_gpu(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_background.c b/source/blender/nodes/shader/nodes/node_shader_background.c
index d82c513540c..18be896e9aa 100644
--- a/source/blender/nodes/shader/nodes/node_shader_background.c
+++ b/source/blender/nodes/shader/nodes/node_shader_background.c
@@ -41,18 +41,16 @@ static bNodeSocketTemplate sh_node_background_out[] = {
};
/* node type definition */
-void register_node_type_sh_background(bNodeTreeType *ttype)
+void register_node_type_sh_background(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BACKGROUND, "Background", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_BACKGROUND, "Background", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_background_in, sh_node_background_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
- node_type_gpu(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_brightness.c b/source/blender/nodes/shader/nodes/node_shader_brightness.c
index 9c23a29cae9..94f7b8ff86f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_brightness.c
+++ b/source/blender/nodes/shader/nodes/node_shader_brightness.c
@@ -43,18 +43,22 @@ static bNodeSocketTemplate sh_node_brightcontrast_out[] = {
{ -1, 0, "" }
};
-void register_node_type_sh_brightcontrast(bNodeTreeType *ttype)
+static int gpu_shader_brightcontrast(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ return GPU_stack_link(mat, "brightness_contrast", in, out);
+}
+
+void register_node_type_sh_brightcontrast(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_brightcontrast_in, sh_node_brightcontrast_out);
node_type_size(&ntype, 140, 100, 320);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
- node_type_gpu(&ntype, NULL);
+ node_type_gpu(&ntype, gpu_shader_brightcontrast);
- nodeRegisterType(ttype, &ntype);
+ 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 71780e9316e..75923133133 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate sh_node_bsdf_anisotropic_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+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);
@@ -53,18 +53,17 @@ static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, bNode *UNUSED(node
}
/* node type definition */
-void register_node_type_sh_bsdf_anisotropic(bNodeTreeType *ttype)
+void register_node_type_sh_bsdf_anisotropic(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BSDF_ANISOTROPIC, "Anisotropic BSDF", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_BSDF_ANISOTROPIC, "Anisotropic BSDF", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_anisotropic_in, sh_node_bsdf_anisotropic_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_anisotropic);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c
index ad9f197afb8..bc764e26666 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c
@@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_bsdf_diffuse_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[2].link)
in[2].link = GPU_builtin(GPU_VIEW_NORMAL);
@@ -50,18 +50,17 @@ static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat, bNode *UNUSED(node), G
}
/* node type definition */
-void register_node_type_sh_bsdf_diffuse(bNodeTreeType *ttype)
+void register_node_type_sh_bsdf_diffuse(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BSDF_DIFFUSE, "Diffuse BSDF", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_BSDF_DIFFUSE, "Diffuse BSDF", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_diffuse_in, sh_node_bsdf_diffuse_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_diffuse);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
index 9e188092570..fe56a54011d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
@@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_bsdf_glass_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[3].link)
in[3].link = GPU_builtin(GPU_VIEW_NORMAL);
@@ -51,18 +51,17 @@ static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, bNode *UNUSED(node), GPU
}
/* node type definition */
-void register_node_type_sh_bsdf_glass(bNodeTreeType *ttype)
+void register_node_type_sh_bsdf_glass(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BSDF_GLASS, "Glass BSDF", NODE_CLASS_SHADER, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_BSDF_GLASS, "Glass BSDF", NODE_CLASS_SHADER, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_glass_in, sh_node_bsdf_glass_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_glass);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c
index 5e32930b707..81f15f3c5a8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c
@@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_bsdf_glossy_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[2].link)
in[2].link = GPU_builtin(GPU_VIEW_NORMAL);
@@ -50,18 +50,17 @@ static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, bNode *UNUSED(node), GP
}
/* node type definition */
-void register_node_type_sh_bsdf_glossy(bNodeTreeType *ttype)
+void register_node_type_sh_bsdf_glossy(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BSDF_GLOSSY, "Glossy BSDF", NODE_CLASS_SHADER, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_BSDF_GLOSSY, "Glossy BSDF", NODE_CLASS_SHADER, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_glossy_in, sh_node_bsdf_glossy_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_glossy);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c
index 99e66e39002..a14c1050812 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c
@@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_bsdf_refraction_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[3].link)
in[3].link = GPU_builtin(GPU_VIEW_NORMAL);
@@ -51,18 +51,17 @@ static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *UNUSED(node)
}
/* node type definition */
-void register_node_type_sh_bsdf_refraction(bNodeTreeType *ttype)
+void register_node_type_sh_bsdf_refraction(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BSDF_REFRACTION, "Refraction BSDF", NODE_CLASS_SHADER, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_BSDF_REFRACTION, "Refraction BSDF", NODE_CLASS_SHADER, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_refraction_in, sh_node_bsdf_refraction_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_refraction);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c
index 3c7084886b7..1ef807fd5ac 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c
@@ -40,7 +40,7 @@ static bNodeSocketTemplate sh_node_bsdf_translucent_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_translucent(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_translucent(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[1].link)
in[1].link = GPU_builtin(GPU_VIEW_NORMAL);
@@ -49,18 +49,17 @@ static int node_shader_gpu_bsdf_translucent(GPUMaterial *mat, bNode *UNUSED(node
}
/* node type definition */
-void register_node_type_sh_bsdf_translucent(bNodeTreeType *ttype)
+void register_node_type_sh_bsdf_translucent(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BSDF_TRANSLUCENT, "Translucent BSDF", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_BSDF_TRANSLUCENT, "Translucent BSDF", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_translucent_in, sh_node_bsdf_translucent_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_translucent);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c
index 7fb452ad78d..bdd9de6a3c4 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c
@@ -39,24 +39,23 @@ static bNodeSocketTemplate sh_node_bsdf_transparent_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_transparent(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_transparent(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_bsdf_transparent", in, out);
}
/* node type definition */
-void register_node_type_sh_bsdf_transparent(bNodeTreeType *ttype)
+void register_node_type_sh_bsdf_transparent(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BSDF_TRANSPARENT, "Transparent BSDF", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_BSDF_TRANSPARENT, "Transparent BSDF", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_transparent_in, sh_node_bsdf_transparent_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_transparent);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c
index a4d25d42d4e..eeb1365bc43 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c
@@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_bsdf_velvet_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[2].link)
in[2].link = GPU_builtin(GPU_VIEW_NORMAL);
@@ -50,18 +50,17 @@ static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, bNode *UNUSED(node), GP
}
/* node type definition */
-void register_node_type_sh_bsdf_velvet(bNodeTreeType *ttype)
+void register_node_type_sh_bsdf_velvet(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BSDF_VELVET, "Velvet BSDF", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_BSDF_VELVET, "Velvet BSDF", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_velvet_in, sh_node_bsdf_velvet_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_bsdf_velvet);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.c b/source/blender/nodes/shader/nodes/node_shader_bump.c
index b0605f9b248..ef57604e07a 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bump.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bump.c
@@ -46,23 +46,22 @@ static bNodeSocketTemplate sh_node_bump_out[] = {
{ -1, 0, "" }
};
-static int gpu_shader_bump(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *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));
}
/* node type definition */
-void register_node_type_sh_bump(bNodeTreeType *ttype)
+void register_node_type_sh_bump(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_BUMP, "Bump", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_BUMP, "Bump", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bump_in, sh_node_bump_out);
node_type_size(&ntype, 150, 60, 200);
node_type_storage(&ntype, "BumpNode", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, gpu_shader_bump);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_camera.c b/source/blender/nodes/shader/nodes/node_shader_camera.c
index fd36a94516e..aee89a02ee1 100644
--- a/source/blender/nodes/shader/nodes/node_shader_camera.c
+++ b/source/blender/nodes/shader/nodes/node_shader_camera.c
@@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_camera_out[] = {
};
-static void node_shader_exec_camera(void *data, bNode *UNUSED(node), bNodeStack **UNUSED(in), bNodeStack **out)
+static void node_shader_exec_camera(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **UNUSED(in), bNodeStack **out)
{
if (data) {
ShadeInput *shi= ((ShaderCallData *)data)->shi; /* Data we need for shading. */
@@ -52,22 +52,22 @@ static void node_shader_exec_camera(void *data, bNode *UNUSED(node), bNodeStack
}
}
-static int gpu_shader_camera(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_camera(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "camera", in, out, GPU_builtin(GPU_VIEW_POSITION));
}
-void register_node_type_sh_camera(bNodeTreeType *ttype)
+void register_node_type_sh_camera(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_CAMERA, "Camera Data", NODE_CLASS_INPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_CAMERA, "Camera Data", NODE_CLASS_INPUT, 0);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_camera_out);
node_type_size(&ntype, 95, 95, 120);
node_type_storage(&ntype, "node_camera", NULL, NULL);
- node_type_exec(&ntype, node_shader_exec_camera);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_camera);
node_type_gpu(&ntype, gpu_shader_camera);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_common.c b/source/blender/nodes/shader/nodes/node_shader_common.c
index 688d77d8350..155aa508ed9 100644
--- a/source/blender/nodes/shader/nodes/node_shader_common.c
+++ b/source/blender/nodes/shader/nodes/node_shader_common.c
@@ -33,12 +33,17 @@
#include "DNA_node_types.h"
+#include "BLI_utildefines.h"
+
#include "BKE_node.h"
#include "node_shader_util.h"
+#include "NOD_common.h"
#include "node_common.h"
#include "node_exec.h"
+#include "RNA_access.h"
+
static void copy_stack(bNodeStack *to, bNodeStack *from)
{
if (to != from) {
@@ -59,69 +64,80 @@ static void move_stack(bNodeStack *to, bNodeStack *from)
to->datatype = from->datatype;
to->is_copy = from->is_copy;
- zero_v4(from->vec);
from->data = NULL;
- from->datatype = 0;
from->is_copy = 0;
}
}
/**** GROUP ****/
-static void *group_initexec(bNode *node)
+static void *group_initexec(bNodeExecContext *context, bNode *node, bNodeInstanceKey key)
{
- bNodeTree *ngroup= (bNodeTree*)node->id;
+ bNodeTree *ngroup = (bNodeTree *)node->id;
bNodeTreeExec *exec;
if (!ngroup)
return NULL;
/* initialize the internal node tree execution */
- exec = ntreeShaderBeginExecTree(ngroup, 0);
+ exec = ntreeShaderBeginExecTree_internal(context, ngroup, key);
return exec;
}
static void group_freeexec(bNode *UNUSED(node), void *nodedata)
{
- bNodeTreeExec*gexec= (bNodeTreeExec*)nodedata;
+ bNodeTreeExec*gexec = (bNodeTreeExec *)nodedata;
- ntreeShaderEndExecTree(gexec, 0);
+ ntreeShaderEndExecTree_internal(gexec);
}
/* Copy inputs to the internal stack.
*/
-static void group_copy_inputs(bNode *node, bNodeStack **in, bNodeStack *gstack)
+static void group_copy_inputs(bNode *gnode, bNodeStack **in, bNodeStack *gstack)
{
+ bNodeTree *ngroup = (bNodeTree*)gnode->id;
+ bNode *node;
bNodeSocket *sock;
bNodeStack *ns;
int a;
- for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) {
- if (sock->groupsock) {
- ns = node_get_socket_stack(gstack, sock->groupsock);
- copy_stack(ns, in[a]);
+
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP_INPUT) {
+ for (sock = node->outputs.first, a = 0; sock; sock = sock->next, ++a) {
+ ns = node_get_socket_stack(gstack, sock);
+ if (ns)
+ copy_stack(ns, in[a]);
+ }
}
}
}
/* Copy internal results to the external outputs.
*/
-static void group_move_outputs(bNode *node, bNodeStack **out, bNodeStack *gstack)
+static void group_move_outputs(bNode *gnode, bNodeStack **out, bNodeStack *gstack)
{
+ bNodeTree *ngroup = (bNodeTree*)gnode->id;
+ bNode *node;
bNodeSocket *sock;
bNodeStack *ns;
int a;
- for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) {
- if (sock->groupsock) {
- ns = node_get_socket_stack(gstack, sock->groupsock);
- move_stack(out[a], ns);
+
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT)) {
+ for (sock = node->inputs.first, a = 0; sock; sock = sock->next, ++a) {
+ ns = node_get_socket_stack(gstack, sock);
+ if (ns)
+ move_stack(out[a], ns);
+ }
+ break; /* only one active output node */
}
}
}
-static void group_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
+static void group_execute(void *data, int thread, struct bNode *node, bNodeExecData *execdata, struct bNodeStack **in, struct bNodeStack **out)
{
- bNodeTreeExec *exec= (bNodeTreeExec*)nodedata;
+ bNodeTreeExec *exec = execdata->data;
bNodeThreadStack *nts;
if (!exec)
@@ -145,62 +161,88 @@ static void group_execute(void *data, int thread, struct bNode *node, void *node
ntreeReleaseThreadStack(nts);
}
-static void group_gpu_copy_inputs(bNode *node, GPUNodeStack *in, bNodeStack *gstack)
+static void group_gpu_copy_inputs(bNode *gnode, GPUNodeStack *in, bNodeStack *gstack)
{
+ bNodeTree *ngroup = (bNodeTree*)gnode->id;
+ bNode *node;
bNodeSocket *sock;
bNodeStack *ns;
int a;
- for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) {
- if (sock->groupsock) {
- ns = node_get_socket_stack(gstack, sock->groupsock);
- /* convert the external gpu stack back to internal node stack data */
- node_data_from_gpu_stack(ns, &in[a]);
+
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP_INPUT) {
+ for (sock = node->outputs.first, a = 0; sock; sock = sock->next, ++a) {
+ ns = node_get_socket_stack(gstack, sock);
+ if (ns) {
+ /* convert the external gpu stack back to internal node stack data */
+ node_data_from_gpu_stack(ns, &in[a]);
+ }
+ }
}
}
}
/* Copy internal results to the external outputs.
*/
-static void group_gpu_move_outputs(bNode *node, GPUNodeStack *out, bNodeStack *gstack)
+static void group_gpu_move_outputs(bNode *gnode, GPUNodeStack *out, bNodeStack *gstack)
{
+ bNodeTree *ngroup = (bNodeTree*)gnode->id;
+ bNode *node;
bNodeSocket *sock;
bNodeStack *ns;
int a;
- for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) {
- if (sock->groupsock) {
- ns = node_get_socket_stack(gstack, sock->groupsock);
- /* convert the node stack data result back to gpu stack */
- node_gpu_stack_from_data(&out[a], sock->type, ns);
+
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT)) {
+ for (sock = node->inputs.first, a = 0; sock; sock = sock->next, ++a) {
+ ns = node_get_socket_stack(gstack, sock);
+ if (ns) {
+ /* convert the node stack data result back to gpu stack */
+ node_gpu_stack_from_data(&out[a], sock->type, ns);
+ }
+ }
+ break; /* only one active output node */
}
}
}
-static int gpu_group_execute(GPUMaterial *mat, bNode *node, void *nodedata, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_group_execute(GPUMaterial *mat, bNode *node, bNodeExecData *execdata, GPUNodeStack *in, GPUNodeStack *out)
{
- bNodeTreeExec *exec= (bNodeTreeExec*)nodedata;
+ bNodeTreeExec *exec = execdata->data;
group_gpu_copy_inputs(node, in, exec->stack);
+ #if 0 /* XXX NODE_GROUP_EDIT is deprecated, depends on node space */
ntreeExecGPUNodes(exec, mat, (node->flag & NODE_GROUP_EDIT));
+ #else
+ ntreeExecGPUNodes(exec, mat, 0);
+ #endif
group_gpu_move_outputs(node, out, exec->stack);
return 1;
}
-void register_node_type_sh_group(bNodeTreeType *ttype)
+void register_node_type_sh_group(void)
{
static bNodeType ntype;
-
- node_type_base(ttype, &ntype, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS|NODE_CONST_OUTPUT);
+
+ /* NB: cannot use sh_node_type_base for node group, because it would map the node type
+ * to the shared NODE_GROUP integer type id.
+ */
+ node_type_base_custom(&ntype, "ShaderNodeGroup", "Group", NODE_CLASS_GROUP, NODE_OPTIONS | NODE_CONST_OUTPUT);
+ ntype.type = NODE_GROUP;
+ ntype.poll = sh_node_poll_default;
+ ntype.update_internal_links = node_update_internal_links_default;
+ ntype.ext.srna = RNA_struct_find("ShaderNodeGroup");
+ BLI_assert(ntype.ext.srna != NULL);
+ RNA_struct_blender_type_set(ntype.ext.srna, &ntype);
+
node_type_socket_templates(&ntype, NULL, NULL);
node_type_size(&ntype, 120, 60, 200);
node_type_label(&ntype, node_group_label);
- node_type_init(&ntype, node_group_init);
- node_type_valid(&ntype, node_group_valid);
- node_type_template(&ntype, node_group_template);
node_type_update(&ntype, NULL, node_group_verify);
- node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
- node_type_exec_new(&ntype, group_initexec, group_freeexec, group_execute);
- node_type_gpu_ext(&ntype, gpu_group_execute);
+ strcpy(ntype.group_tree_idname, "ShaderNodeTree");
+ node_type_exec(&ntype, group_initexec, group_freeexec, group_execute);
+ node_type_gpu(&ntype, gpu_group_execute);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_curves.c b/source/blender/nodes/shader/nodes/node_shader_curves.c
index 216e10a7e9a..b293b02cfe6 100644
--- a/source/blender/nodes/shader/nodes/node_shader_curves.c
+++ b/source/blender/nodes/shader/nodes/node_shader_curves.c
@@ -45,7 +45,7 @@ static bNodeSocketTemplate sh_node_curve_vec_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_curve_vec(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_curve_vec(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
float vec[3];
@@ -55,12 +55,12 @@ static void node_shader_exec_curve_vec(void *UNUSED(data), bNode *node, bNodeSta
curvemapping_evaluate3F(node->storage, out[0]->vec, vec);
}
-static void node_shader_init_curve_vec(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_curve_vec(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f);
}
-static int gpu_shader_curve_vec(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_curve_vec(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
float *array;
int size;
@@ -69,21 +69,20 @@ static int gpu_shader_curve_vec(GPUMaterial *mat, bNode *node, GPUNodeStack *in,
return GPU_stack_link(mat, "curves_vec", in, out, GPU_texture(size, array));
}
-void register_node_type_sh_curve_vec(bNodeTreeType *ttype)
+void register_node_type_sh_curve_vec(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_CURVE_VEC, "Vector Curves", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_CURVE_VEC, "Vector Curves", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_curve_vec_in, sh_node_curve_vec_out);
node_type_size(&ntype, 200, 140, 320);
node_type_init(&ntype, node_shader_init_curve_vec);
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
- node_type_exec(&ntype, node_shader_exec_curve_vec);
- node_type_exec_new(&ntype, node_initexec_curves, NULL, NULL); /* only for its initexec func */
+ node_type_exec(&ntype, node_initexec_curves, NULL, node_shader_exec_curve_vec);
node_type_gpu(&ntype, gpu_shader_curve_vec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -99,7 +98,7 @@ static bNodeSocketTemplate sh_node_curve_rgb_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_curve_rgb(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_curve_rgb(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
float vec[3];
@@ -112,12 +111,12 @@ static void node_shader_exec_curve_rgb(void *UNUSED(data), bNode *node, bNodeSta
}
}
-static void node_shader_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
}
-static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
float *array;
int size;
@@ -127,19 +126,18 @@ static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in,
return GPU_stack_link(mat, "curves_rgb", in, out, GPU_texture(size, array));
}
-void register_node_type_sh_curve_rgb(bNodeTreeType *ttype)
+void register_node_type_sh_curve_rgb(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_curve_rgb_in, sh_node_curve_rgb_out);
node_type_size(&ntype, 200, 140, 320);
node_type_init(&ntype, node_shader_init_curve_rgb);
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
- node_type_exec(&ntype, node_shader_exec_curve_rgb);
- node_type_exec_new(&ntype, node_initexec_curves, NULL, NULL); /* only for its initexec func */
+ node_type_exec(&ntype, node_initexec_curves, NULL, node_shader_exec_curve_rgb);
node_type_gpu(&ntype, gpu_shader_curve_rgb);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_emission.c b/source/blender/nodes/shader/nodes/node_shader_emission.c
index 0c4cb7ed51c..e11f199bbd0 100644
--- a/source/blender/nodes/shader/nodes/node_shader_emission.c
+++ b/source/blender/nodes/shader/nodes/node_shader_emission.c
@@ -40,24 +40,23 @@ static bNodeSocketTemplate sh_node_emission_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_emission(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_emission(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_emission", in, out, GPU_builtin(GPU_VIEW_NORMAL));
}
/* node type definition */
-void register_node_type_sh_emission(bNodeTreeType *ttype)
+void register_node_type_sh_emission(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_EMISSION, "Emission", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_EMISSION, "Emission", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_emission_in, sh_node_emission_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_emission);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_fresnel.c b/source/blender/nodes/shader/nodes/node_shader_fresnel.c
index 80913e6b07a..d627edebfa7 100644
--- a/source/blender/nodes/shader/nodes/node_shader_fresnel.c
+++ b/source/blender/nodes/shader/nodes/node_shader_fresnel.c
@@ -38,25 +38,24 @@ static bNodeSocketTemplate sh_node_fresnel_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_fresnel(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_fresnel(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
/* todo: is incoming vector normalized? */
return GPU_stack_link(mat, "node_fresnel", in, out, GPU_builtin(GPU_VIEW_NORMAL), GPU_builtin(GPU_VIEW_POSITION));
}
/* node type definition */
-void register_node_type_sh_fresnel(bNodeTreeType *ttype)
+void register_node_type_sh_fresnel(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_FRESNEL, "Fresnel", NODE_CLASS_INPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_FRESNEL, "Fresnel", NODE_CLASS_INPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_fresnel_in, sh_node_fresnel_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_fresnel);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_gamma.c b/source/blender/nodes/shader/nodes/node_shader_gamma.c
index c49554c44be..c5dafbe55d1 100644
--- a/source/blender/nodes/shader/nodes/node_shader_gamma.c
+++ b/source/blender/nodes/shader/nodes/node_shader_gamma.c
@@ -29,7 +29,7 @@
#include "node_shader_util.h"
/* **************** Gamma Tools ******************** */
-
+
static bNodeSocketTemplate sh_node_gamma_in[] = {
{ SOCK_RGBA, 1, N_("Color"), 1.0f, 1.0f, 1.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Gamma"), 1.0f, 0.0f, 0.0f, 0.0f, 0.001f, 10.0f, PROP_UNSIGNED},
@@ -41,18 +41,16 @@ static bNodeSocketTemplate sh_node_gamma_out[] = {
{ -1, 0, "" }
};
-void register_node_type_sh_gamma(bNodeTreeType *ttype)
+void register_node_type_sh_gamma(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_gamma_in, sh_node_gamma_out);
node_type_size(&ntype, 140, 100, 320);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
- node_type_gpu(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ 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 eb3d462d616..40ba2cca4e5 100644
--- a/source/blender/nodes/shader/nodes/node_shader_geom.c
+++ b/source/blender/nodes/shader/nodes/node_shader_geom.c
@@ -51,7 +51,7 @@ static bNodeSocketTemplate sh_node_geom_out[] = {
};
/* node execute callback */
-static void node_shader_exec_geom(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
+static void node_shader_exec_geom(void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **UNUSED(in), bNodeStack **out)
{
if (data) {
ShadeInput *shi= ((ShaderCallData *)data)->shi;
@@ -120,12 +120,12 @@ static void node_shader_exec_geom(void *data, bNode *node, bNodeStack **UNUSED(i
}
}
-static void node_shader_init_geometry(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_geometry(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= MEM_callocN(sizeof(NodeGeometry), "NodeGeometry");
}
-static int gpu_shader_geom(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_geom(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
NodeGeometry *ngeo= (NodeGeometry*)node->storage;
GPUNodeLink *orco = GPU_attribute(CD_ORCO, "");
@@ -138,18 +138,18 @@ static int gpu_shader_geom(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUN
}
/* node type definition */
-void register_node_type_sh_geom(bNodeTreeType *ttype)
+void register_node_type_sh_geom(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_GEOMETRY, "Geometry", NODE_CLASS_INPUT, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_GEOMETRY, "Geometry", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_geom_out);
node_type_size(&ntype, 120, 80, 160);
node_type_init(&ntype, node_shader_init_geometry);
node_type_storage(&ntype, "NodeGeometry", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, node_shader_exec_geom);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_geom);
node_type_gpu(&ntype, gpu_shader_geom);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_geometry.c b/source/blender/nodes/shader/nodes/node_shader_geometry.c
index acef885d2d4..c9626576833 100644
--- a/source/blender/nodes/shader/nodes/node_shader_geometry.c
+++ b/source/blender/nodes/shader/nodes/node_shader_geometry.c
@@ -40,7 +40,7 @@ static bNodeSocketTemplate sh_node_geometry_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_geometry(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_geometry(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_geometry", in, out,
GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL),
@@ -48,18 +48,17 @@ static int node_shader_gpu_geometry(GPUMaterial *mat, bNode *UNUSED(node), GPUNo
}
/* node type definition */
-void register_node_type_sh_geometry(bNodeTreeType *ttype)
+void register_node_type_sh_geometry(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_NEW_GEOMETRY, "Geometry", NODE_CLASS_INPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_NEW_GEOMETRY, "Geometry", NODE_CLASS_INPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_geometry_out);
node_type_size(&ntype, 120, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_geometry);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_hair_info.c b/source/blender/nodes/shader/nodes/node_shader_hair_info.c
new file mode 100644
index 00000000000..86c31086190
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_hair_info.c
@@ -0,0 +1,51 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+static bNodeSocketTemplate outputs[] = {
+ { SOCK_FLOAT, 0, N_("Is Strand"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_("Intercept"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_("Thickness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_VECTOR, 0, N_("Tangent Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+/* node type definition */
+void register_node_type_sh_hair_info(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_HAIR_INFO, "Hair Info", NODE_CLASS_INPUT, 0);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype, NULL, outputs);
+ node_type_size(&ntype, 150, 60, 200);
+ node_type_init(&ntype, NULL);
+ node_type_storage(&ntype, "", NULL, NULL);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/shader/nodes/node_shader_holdout.c b/source/blender/nodes/shader/nodes/node_shader_holdout.c
index 18ad4994c9b..9024cb507ed 100644
--- a/source/blender/nodes/shader/nodes/node_shader_holdout.c
+++ b/source/blender/nodes/shader/nodes/node_shader_holdout.c
@@ -40,18 +40,16 @@ static bNodeSocketTemplate sh_node_holdout_out[] = {
/* node type definition */
-void register_node_type_sh_holdout(bNodeTreeType *ttype)
+void register_node_type_sh_holdout(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_HOLDOUT, "Holdout", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_HOLDOUT, "Holdout", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_holdout_in, sh_node_holdout_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
- node_type_gpu(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
index b635ad1edd9..559d9289fb7 100644
--- a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
+++ b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
@@ -69,27 +69,27 @@ static void do_hue_sat_fac(bNode *UNUSED(node), float *out, float *hue, float *s
}
}
-static void node_shader_exec_hue_sat(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_hue_sat(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
do_hue_sat_fac(node, out[0]->vec, in[0]->vec, in[1]->vec, in[2]->vec, in[4]->vec, in[3]->vec);
}
-static int gpu_shader_hue_sat(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_hue_sat(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "hue_sat", in, out);
}
-void register_node_type_sh_hue_sat(bNodeTreeType *ttype)
+void register_node_type_sh_hue_sat(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_hue_sat_in, sh_node_hue_sat_out);
node_type_size(&ntype, 150, 80, 250);
- node_type_exec(&ntype, node_shader_exec_hue_sat);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_hue_sat);
node_type_gpu(&ntype, gpu_shader_hue_sat);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_invert.c b/source/blender/nodes/shader/nodes/node_shader_invert.c
index 2ea858f4e34..193ea93f54a 100644
--- a/source/blender/nodes/shader/nodes/node_shader_invert.c
+++ b/source/blender/nodes/shader/nodes/node_shader_invert.c
@@ -46,7 +46,7 @@ static bNodeSocketTemplate sh_node_invert_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_invert(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in,
+static void node_shader_exec_invert(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in,
bNodeStack **out)
{
float col[3], facm;
@@ -67,21 +67,21 @@ bNodeStack **out)
copy_v3_v3(out[0]->vec, col);
}
-static int gpu_shader_invert(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_invert(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "invert", in, out);
}
-void register_node_type_sh_invert(bNodeTreeType *ttype)
+void register_node_type_sh_invert(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_invert_in, sh_node_invert_out);
node_type_size(&ntype, 90, 80, 100);
- node_type_exec(&ntype, node_shader_exec_invert);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_invert);
node_type_gpu(&ntype, gpu_shader_invert);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c
index 3058483ebef..f342cb07e30 100644
--- a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c
+++ b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c
@@ -40,24 +40,23 @@ static bNodeSocketTemplate sh_node_layer_weight_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_layer_weight(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
+static int node_shader_gpu_layer_weight(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
{
return 0;
}
/* node type definition */
-void register_node_type_sh_layer_weight(bNodeTreeType *ttype)
+void register_node_type_sh_layer_weight(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_LAYER_WEIGHT, "Layer Weight", NODE_CLASS_INPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_LAYER_WEIGHT, "Layer Weight", NODE_CLASS_INPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_layer_weight_in, sh_node_layer_weight_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_layer_weight);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_light_falloff.c b/source/blender/nodes/shader/nodes/node_shader_light_falloff.c
index 2dec244ae3a..e30c59f6920 100644
--- a/source/blender/nodes/shader/nodes/node_shader_light_falloff.c
+++ b/source/blender/nodes/shader/nodes/node_shader_light_falloff.c
@@ -44,25 +44,24 @@ static bNodeSocketTemplate sh_node_light_falloff_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_light_falloff(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_light_falloff(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_light_falloff", in, out);
}
/* node type definition */
-void register_node_type_sh_light_falloff(bNodeTreeType *ttype)
+void register_node_type_sh_light_falloff(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_LIGHT_FALLOFF, "Light Falloff", NODE_CLASS_OP_COLOR, 0);
+ sh_node_type_base(&ntype, SH_NODE_LIGHT_FALLOFF, "Light Falloff", NODE_CLASS_OP_COLOR, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_light_falloff_in, sh_node_light_falloff_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_light_falloff);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_light_path.c b/source/blender/nodes/shader/nodes/node_shader_light_path.c
index b4a3d4e01e1..0b1f34f6a02 100644
--- a/source/blender/nodes/shader/nodes/node_shader_light_path.c
+++ b/source/blender/nodes/shader/nodes/node_shader_light_path.c
@@ -41,24 +41,23 @@ static bNodeSocketTemplate sh_node_light_path_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_light_path(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_light_path(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_light_path", in, out);
}
/* node type definition */
-void register_node_type_sh_light_path(bNodeTreeType *ttype)
+void register_node_type_sh_light_path(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_LIGHT_PATH, "Light Path", NODE_CLASS_INPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_LIGHT_PATH, "Light Path", NODE_CLASS_INPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_light_path_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_light_path);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c
index cedd3a4910c..910bf06c068 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mapping.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate sh_node_mapping_out[] = {
};
/* do the regular mapping options for blender textures */
-static void node_shader_exec_mapping(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_mapping(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
TexMapping *texmap= node->storage;
float *vec= out[0]->vec;
@@ -67,17 +67,17 @@ static void node_shader_exec_mapping(void *UNUSED(data), bNode *node, bNodeStack
}
-static void node_shader_init_mapping(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_mapping(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= add_tex_mapping();
}
-static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
TexMapping *texmap= node->storage;
float domin= (texmap->flag & TEXMAP_CLIP_MIN) != 0;
float domax= (texmap->flag & TEXMAP_CLIP_MAX) != 0;
- GPUNodeLink *tmat = GPU_uniform((float*)texmap->mat);
+ GPUNodeLink *tmat = GPU_uniform((float *)texmap->mat);
GPUNodeLink *tmin = GPU_uniform(texmap->min);
GPUNodeLink *tmax = GPU_uniform(texmap->max);
GPUNodeLink *tdomin = GPU_uniform(&domin);
@@ -86,18 +86,18 @@ static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, G
return GPU_stack_link(mat, "mapping", in, out, tmat, tmin, tmax, tdomin, tdomax);
}
-void register_node_type_sh_mapping(bNodeTreeType *ttype)
+void register_node_type_sh_mapping(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_MAPPING, "Mapping", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_MAPPING, "Mapping", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_mapping_in, sh_node_mapping_out);
node_type_size(&ntype, 240, 160, 320);
node_type_init(&ntype, node_shader_init_mapping);
node_type_storage(&ntype, "TexMapping", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, node_shader_exec_mapping);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_mapping);
node_type_gpu(&ntype, gpu_shader_mapping);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_material.c b/source/blender/nodes/shader/nodes/node_shader_material.c
index 2902bf143c8..aee280760ba 100644
--- a/source/blender/nodes/shader/nodes/node_shader_material.c
+++ b/source/blender/nodes/shader/nodes/node_shader_material.c
@@ -29,7 +29,6 @@
* \ingroup shdnodes
*/
-
#include "node_shader_util.h"
/* **************** MATERIAL ******************** */
@@ -76,7 +75,7 @@ static bNodeSocketTemplate sh_node_material_ext_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_material(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
if (data && node->id) {
ShadeResult shrnode;
@@ -92,7 +91,7 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in,
* we just want to know if a node input uses external data or the material setting.
* this is an ugly hack, but so is this node as a whole.
*/
- for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i)
+ for (sock = node->inputs.first, i=0; sock; sock = sock->next, ++i)
hasinput[i] = (sock->link != NULL);
shi= shcd->shi;
@@ -145,7 +144,7 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in,
/* make alpha output give results even if transparency is only enabled on
* the material linked in this not and not on the parent material */
mode = shi->mode;
- if(shi->mat->mode & MA_TRANSP)
+ if (shi->mat->mode & MA_TRANSP)
shi->mode |= MA_TRANSP;
shi->nodes= 1; /* temp hack to prevent trashadow recursion */
@@ -170,7 +169,7 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in,
col[3] = shrnode.alpha;
if (shi->do_preview)
- nodeAddToPreview(node, col, shi->xs, shi->ys, shi->do_manage);
+ BKE_node_preview_set_pixel(execdata->preview, col, shi->xs, shi->ys, shi->do_manage);
copy_v3_v3(out[MAT_OUT_COLOR]->vec, col);
out[MAT_OUT_ALPHA]->vec[0] = shrnode.alpha;
@@ -208,7 +207,7 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in,
}
-static void node_shader_init_material(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_material(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom1= SH_NODE_MAT_DIFF|SH_NODE_MAT_SPEC;
}
@@ -224,7 +223,7 @@ static GPUNodeLink *gpu_get_input_link(GPUNodeStack *in)
return GPU_uniform(in->vec);
}
-static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_material(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (node->id) {
GPUShadeInput shi;
@@ -237,7 +236,7 @@ static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in,
* the constant input stack values (e.g. in case material node is inside a group).
* we just want to know if a node input uses external data or the material setting.
*/
- for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i)
+ for (sock = node->inputs.first, i=0; sock; sock = sock->next, ++i)
hasinput[i] = (sock->link != NULL);
GPU_shadeinput_set(mat, (Material*)node->id, &shi);
@@ -308,33 +307,33 @@ static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in,
return 0;
}
-void register_node_type_sh_material(bNodeTreeType *ttype)
+void register_node_type_sh_material(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_MATERIAL, "Material", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW);
+ sh_node_type_base(&ntype, SH_NODE_MATERIAL, "Material", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW);
node_type_compatibility(&ntype, NODE_OLD_SHADING);
node_type_socket_templates(&ntype, sh_node_material_in, sh_node_material_out);
node_type_size(&ntype, 120, 80, 240);
node_type_init(&ntype, node_shader_init_material);
- node_type_exec(&ntype, node_shader_exec_material);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_material);
node_type_gpu(&ntype, gpu_shader_material);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
-void register_node_type_sh_material_ext(bNodeTreeType *ttype)
+void register_node_type_sh_material_ext(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_MATERIAL_EXT, "Extended Material", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW);
+ sh_node_type_base(&ntype, SH_NODE_MATERIAL_EXT, "Extended Material", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW);
node_type_compatibility(&ntype, NODE_OLD_SHADING);
node_type_socket_templates(&ntype, sh_node_material_ext_in, sh_node_material_ext_out);
node_type_size(&ntype, 120, 80, 240);
node_type_init(&ntype, node_shader_init_material);
- node_type_exec(&ntype, node_shader_exec_material);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_material);
node_type_gpu(&ntype, gpu_shader_material);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c
index 0b71a3f13b4..31a1501bc3f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_math.c
+++ b/source/blender/nodes/shader/nodes/node_shader_math.c
@@ -45,8 +45,7 @@ static bNodeSocketTemplate sh_node_math_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_math(void *UNUSED(data), bNode *node, bNodeStack **in,
-bNodeStack **out)
+static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
switch (node->custom1) {
@@ -207,7 +206,7 @@ bNodeStack **out)
}
}
-static int gpu_shader_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+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",
@@ -256,18 +255,18 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUN
return 1;
}
-void register_node_type_sh_math(bNodeTreeType *ttype)
+void register_node_type_sh_math(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_math_in, sh_node_math_out);
node_type_size(&ntype, 120, 110, 160);
node_type_label(&ntype, node_math_label);
node_type_storage(&ntype, "node_math", NULL, NULL);
- node_type_exec(&ntype, node_shader_exec_math);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_math);
node_type_gpu(&ntype, gpu_shader_math);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
index 18dcc8f7fef..982eaa228d1 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate sh_node_mix_rgb_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_mix_rgb(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_mix_rgb(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
/* stack order in: fac, col1, col2 */
/* stack order out: col */
@@ -62,7 +62,7 @@ static void node_shader_exec_mix_rgb(void *UNUSED(data), bNode *node, bNodeStack
copy_v3_v3(out[0]->vec, col);
}
-static int gpu_shader_mix_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_mix_rgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
static const char *names[] = {"mix_blend", "mix_add", "mix_mult", "mix_sub",
"mix_screen", "mix_div", "mix_diff", "mix_dark", "mix_light",
@@ -73,17 +73,17 @@ static int gpu_shader_mix_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, G
}
-void register_node_type_sh_mix_rgb(bNodeTreeType *ttype)
+void register_node_type_sh_mix_rgb(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_mix_rgb_in, sh_node_mix_rgb_out);
node_type_size(&ntype, 100, 60, 150);
node_type_label(&ntype, node_blend_label);
- node_type_exec(&ntype, node_shader_exec_mix_rgb);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_mix_rgb);
node_type_gpu(&ntype, gpu_shader_mix_rgb);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_mix_shader.c b/source/blender/nodes/shader/nodes/node_shader_mix_shader.c
index 039e63a4dea..f1415dcac1b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mix_shader.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mix_shader.c
@@ -30,7 +30,7 @@
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_mix_shader_in[] = {
- { SOCK_FLOAT, 1, N_("Fac"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Fac"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_SHADER, 1, N_("Shader")},
{ SOCK_SHADER, 1, N_("Shader")},
{ -1, 0, "" }
@@ -41,24 +41,23 @@ static bNodeSocketTemplate sh_node_mix_shader_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_mix_shader(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_mix_shader(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_mix_shader", in, out);
}
/* node type definition */
-void register_node_type_sh_mix_shader(bNodeTreeType *ttype)
+void register_node_type_sh_mix_shader(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_MIX_SHADER, "Mix Shader", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_MIX_SHADER, "Mix Shader", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_mix_shader_in, sh_node_mix_shader_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_mix_shader);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_normal.c b/source/blender/nodes/shader/nodes/node_shader_normal.c
index 0ad58d6af76..ba32a7e0924 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal.c
@@ -39,26 +39,14 @@ static bNodeSocketTemplate sh_node_normal_in[] = {
};
static bNodeSocketTemplate sh_node_normal_out[] = {
- { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION},
+ { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, PROP_DIRECTION},
{ SOCK_FLOAT, 0, N_("Dot")},
{ -1, 0, "" }
};
-static void node_shader_init_normal(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
-{
- bNodeSocket *sock= node->outputs.first;
- bNodeSocketValueVector *dval= (bNodeSocketValueVector*)sock->default_value;
-
- /* output value is used for normal vector */
- dval->value[0] = 0.0f;
- dval->value[1] = 0.0f;
- dval->value[2] = 1.0f;
-}
-
/* generates normal, does dot product */
-static void node_shader_exec_normal(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_normal(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
- bNodeSocket *sock= node->outputs.first;
float vec[3];
/* stack order input: normal */
@@ -66,29 +54,25 @@ static void node_shader_exec_normal(void *UNUSED(data), bNode *node, bNodeStack
nodestack_get_vec(vec, SOCK_VECTOR, in[0]);
- copy_v3_v3(out[0]->vec, ((bNodeSocketValueVector*)sock->default_value)->value);
/* render normals point inside... the widget points outside */
- out[1]->vec[0] = -dot_v3v3(out[0]->vec, vec);
+ out[1]->vec[0] = -dot_v3v3(vec, out[0]->vec);
}
-static int gpu_shader_normal(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_normal(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- bNodeSocket *sock= node->outputs.first;
- GPUNodeLink *vec = GPU_uniform(((bNodeSocketValueVector*)sock->default_value)->value);
-
+ GPUNodeLink *vec = GPU_uniform(out[0].vec);
return GPU_stack_link(mat, "normal", in, out, vec);
}
-void register_node_type_sh_normal(bNodeTreeType *ttype)
+void register_node_type_sh_normal(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_NORMAL, "Normal", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_NORMAL, "Normal", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_normal_in, sh_node_normal_out);
- node_type_init(&ntype, node_shader_init_normal);
- node_type_exec(&ntype, node_shader_exec_normal);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_normal);
node_type_gpu(&ntype, gpu_shader_normal);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
index 6a4eb9d81df..d971df215e9 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
@@ -40,31 +40,30 @@ static bNodeSocketTemplate sh_node_normal_map_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_normal_map(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_normal_map(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeShaderNormalMap *attr = MEM_callocN(sizeof(NodeShaderNormalMap), "NodeShaderNormalMap");
node->storage = attr;
}
-static int gpu_shader_normal_map(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_normal_map(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_normal_map", in, out, GPU_builtin(GPU_VIEW_NORMAL));
}
/* node type definition */
-void register_node_type_sh_normal_map(bNodeTreeType *ttype)
+void register_node_type_sh_normal_map(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_NORMAL_MAP, "Normal Map", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_NORMAL_MAP, "Normal Map", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_normal_map_in, sh_node_normal_map_out);
node_type_size(&ntype, 250, 60, 250);
node_type_init(&ntype, node_shader_init_normal_map);
node_type_storage(&ntype, "NodeShaderNormalMap", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, gpu_shader_normal_map);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
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 ef283004d46..d00037546ea 100644
--- a/source/blender/nodes/shader/nodes/node_shader_object_info.c
+++ b/source/blender/nodes/shader/nodes/node_shader_object_info.c
@@ -37,25 +37,24 @@ static bNodeSocketTemplate sh_node_object_info_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_object_info(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_object_info(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_object_info", in, out);
}
/* node type definition */
-void register_node_type_sh_object_info(bNodeTreeType *ttype)
+void register_node_type_sh_object_info(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_OBJECT_INFO, "Object Info", NODE_CLASS_INPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_OBJECT_INFO, "Object Info", NODE_CLASS_INPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_object_info_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_object_info);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_output.c b/source/blender/nodes/shader/nodes/node_shader_output.c
index 6f7f900aecd..c317fe0f58a 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output.c
@@ -39,7 +39,7 @@ static bNodeSocketTemplate sh_node_output_in[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_output(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
+static void node_shader_exec_output(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **UNUSED(out))
{
if (data) {
ShadeInput *shi= ((ShaderCallData *)data)->shi;
@@ -50,7 +50,7 @@ static void node_shader_exec_output(void *data, bNode *node, bNodeStack **in, bN
nodestack_get_vec(col+3, SOCK_FLOAT, in[1]);
if (shi->do_preview) {
- nodeAddToPreview(node, col, shi->xs, shi->ys, shi->do_manage);
+ BKE_node_preview_set_pixel(execdata->preview, col, shi->xs, shi->ys, shi->do_manage);
node->lasty= shi->ys;
}
@@ -65,7 +65,7 @@ static void node_shader_exec_output(void *data, bNode *node, bNodeStack **in, bN
}
}
-static int gpu_shader_output(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_output(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
GPUNodeLink *outlink;
@@ -80,19 +80,19 @@ static int gpu_shader_output(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack
return 1;
}
-void register_node_type_sh_output(bNodeTreeType *ttype)
+void register_node_type_sh_output(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_OUTPUT, "Output", NODE_CLASS_OUTPUT, NODE_PREVIEW);
+ sh_node_type_base(&ntype, SH_NODE_OUTPUT, "Output", NODE_CLASS_OUTPUT, NODE_PREVIEW);
node_type_compatibility(&ntype, NODE_OLD_SHADING);
node_type_socket_templates(&ntype, sh_node_output_in, NULL);
node_type_size(&ntype, 80, 60, 200);
- node_type_exec(&ntype, node_shader_exec_output);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_output);
node_type_gpu(&ntype, gpu_shader_output);
/* Do not allow muting output node. */
node_type_internal_links(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_output_lamp.c b/source/blender/nodes/shader/nodes/node_shader_output_lamp.c
index ce406a8f5a1..5bb45fe63f6 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output_lamp.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output_lamp.c
@@ -35,21 +35,19 @@ static bNodeSocketTemplate sh_node_output_lamp_in[] = {
};
/* node type definition */
-void register_node_type_sh_output_lamp(bNodeTreeType *ttype)
+void register_node_type_sh_output_lamp(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_OUTPUT_LAMP, "Lamp Output", NODE_CLASS_OUTPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_OUTPUT_LAMP, "Lamp Output", NODE_CLASS_OUTPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_output_lamp_in, NULL);
node_type_size(&ntype, 120, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
- node_type_gpu(&ntype, NULL);
/* Do not allow muting output node. */
node_type_internal_links(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_output_material.c b/source/blender/nodes/shader/nodes/node_shader_output_material.c
index f185e13010b..ddaee944f93 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output_material.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output_material.c
@@ -36,7 +36,7 @@ static bNodeSocketTemplate sh_node_output_material_in[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_output_material(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_output_material(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
GPUNodeLink *outlink;
@@ -48,21 +48,20 @@ static int node_shader_gpu_output_material(GPUMaterial *mat, bNode *UNUSED(node)
/* node type definition */
-void register_node_type_sh_output_material(bNodeTreeType *ttype)
+void register_node_type_sh_output_material(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_OUTPUT_MATERIAL, "Material Output", NODE_CLASS_OUTPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_OUTPUT_MATERIAL, "Material Output", NODE_CLASS_OUTPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_output_material_in, NULL);
node_type_size(&ntype, 120, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_output_material);
/* Do not allow muting output node. */
node_type_internal_links(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
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 953197ab2cd..99663489635 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output_world.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output_world.c
@@ -36,21 +36,19 @@ static bNodeSocketTemplate sh_node_output_world_in[] = {
};
/* node type definition */
-void register_node_type_sh_output_world(bNodeTreeType *ttype)
+void register_node_type_sh_output_world(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_OUTPUT_WORLD, "World Output", NODE_CLASS_OUTPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_OUTPUT_WORLD, "World Output", NODE_CLASS_OUTPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_output_world_in, NULL);
node_type_size(&ntype, 120, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
- node_type_gpu(&ntype, NULL);
/* Do not allow muting output node. */
node_type_internal_links(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
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 c7e31d117cc..e4d91d524d2 100644
--- a/source/blender/nodes/shader/nodes/node_shader_particle_info.c
+++ b/source/blender/nodes/shader/nodes/node_shader_particle_info.c
@@ -42,15 +42,15 @@ static bNodeSocketTemplate outputs[] = {
};
/* node type definition */
-void register_node_type_sh_particle_info(bNodeTreeType *ttype)
+void register_node_type_sh_particle_info(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_PARTICLE_INFO, "Particle Info", NODE_CLASS_INPUT, 0);
+ sh_node_type_base(&ntype, SH_NODE_PARTICLE_INFO, "Particle Info", NODE_CLASS_INPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, outputs);
node_type_size(&ntype, 150, 60, 200);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_rgb.c b/source/blender/nodes/shader/nodes/node_shader_rgb.c
index f37ff1d511b..f0c90b65823 100644
--- a/source/blender/nodes/shader/nodes/node_shader_rgb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_rgb.c
@@ -34,49 +34,25 @@
/* **************** RGB ******************** */
static bNodeSocketTemplate sh_node_rgb_out[] = {
- { SOCK_RGBA, 0, N_("Color")},
+ { SOCK_RGBA, 0, N_("Color"), 0.5f, 0.5f, 0.5f, 1.0f},
{ -1, 0, "" }
};
-static void node_shader_init_rgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static int gpu_shader_rgb(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- bNodeSocket *sock= node->outputs.first;
- bNodeSocketValueRGBA *dval= (bNodeSocketValueRGBA*)sock->default_value;
- /* uses the default value of the output socket, must be initialized here */
- dval->value[0] = 0.5f;
- dval->value[1] = 0.5f;
- dval->value[2] = 0.5f;
- dval->value[3] = 1.0f;
-}
-
-static void node_shader_exec_rgb(void *UNUSED(data), bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
-{
- bNodeSocket *sock= node->outputs.first;
- float *col= ((bNodeSocketValueRGBA*)sock->default_value)->value;
-
- copy_v3_v3(out[0]->vec, col);
-}
-
-static int gpu_shader_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
-{
- bNodeSocket *sock= node->outputs.first;
- float *col= ((bNodeSocketValueRGBA*)sock->default_value)->value;
- GPUNodeLink *vec = GPU_uniform(col);
-
+ GPUNodeLink *vec = GPU_uniform(out[0].vec);
return GPU_stack_link(mat, "set_rgba", in, out, vec);
}
-void register_node_type_sh_rgb(bNodeTreeType *ttype)
+void register_node_type_sh_rgb(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_RGB, "RGB", NODE_CLASS_INPUT, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_RGB, "RGB", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_rgb_out);
- node_type_init(&ntype, node_shader_init_rgb);
node_type_size(&ntype, 140, 80, 140);
- node_type_exec(&ntype, node_shader_exec_rgb);
node_type_gpu(&ntype, gpu_shader_rgb);
- nodeRegisterType(ttype, &ntype);
+ 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 b5563658a64..6666197770f 100644
--- a/source/blender/nodes/shader/nodes/node_shader_script.c
+++ b/source/blender/nodes/shader/nodes/node_shader_script.c
@@ -35,7 +35,7 @@
/* **************** Script ******************** */
-static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeShaderScript *nss = MEM_callocN(sizeof(NodeShaderScript), "shader script node");
node->storage = nss;
@@ -50,37 +50,29 @@ static void node_free_script(bNode *node)
MEM_freeN(nss->bytecode);
}
- if (nss->prop) {
- IDP_FreeProperty(nss->prop);
- MEM_freeN(nss->prop);
- }
-
MEM_freeN(nss);
}
}
-static void node_copy_script(bNode *orig_node, bNode *new_node)
+static void node_copy_script(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node)
{
- NodeShaderScript *orig_nss = orig_node->storage;
- NodeShaderScript *new_nss = MEM_dupallocN(orig_nss);
-
- if (orig_nss->bytecode)
- new_nss->bytecode = MEM_dupallocN(orig_nss->bytecode);
+ NodeShaderScript *src_nss = src_node->storage;
+ NodeShaderScript *dest_nss = MEM_dupallocN(src_nss);
- if (orig_nss->prop)
- new_nss->prop = IDP_CopyProperty(orig_nss->prop);
+ if (src_nss->bytecode)
+ dest_nss->bytecode = MEM_dupallocN(src_nss->bytecode);
- new_node->storage = new_nss;
+ dest_node->storage = dest_nss;
}
-void register_node_type_sh_script(bNodeTreeType *ttype)
+void register_node_type_sh_script(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_SCRIPT, "Script", NODE_CLASS_SCRIPT, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_SCRIPT, "Script", NODE_CLASS_SCRIPT, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_init(&ntype, init);
node_type_storage(&ntype, "NodeShaderScript", node_free_script, node_copy_script);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c
index 70fba161de9..c0ed9dc6a3e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c
@@ -44,30 +44,30 @@ static bNodeSocketTemplate sh_node_seprgb_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_seprgb(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_seprgb(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
out[0]->vec[0] = in[0]->vec[0];
out[1]->vec[0] = in[0]->vec[1];
out[2]->vec[0] = in[0]->vec[2];
}
-static int gpu_shader_seprgb(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_seprgb(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "separate_rgb", in, out);
}
-void register_node_type_sh_seprgb(bNodeTreeType *ttype)
+void register_node_type_sh_seprgb(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_SEPRGB, "Separate RGB", NODE_CLASS_CONVERTOR, 0);
+ sh_node_type_base(&ntype, SH_NODE_SEPRGB, "Separate RGB", NODE_CLASS_CONVERTOR, 0);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_seprgb_in, sh_node_seprgb_out);
node_type_size(&ntype, 80, 40, 140);
- node_type_exec(&ntype, node_shader_exec_seprgb);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_seprgb);
node_type_gpu(&ntype, gpu_shader_seprgb);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -84,28 +84,28 @@ static bNodeSocketTemplate sh_node_combrgb_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_combrgb(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_combrgb(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
out[0]->vec[0] = in[0]->vec[0];
out[0]->vec[1] = in[1]->vec[0];
out[0]->vec[2] = in[2]->vec[0];
}
-static int gpu_shader_combrgb(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_combrgb(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "combine_rgb", in, out);
}
-void register_node_type_sh_combrgb(bNodeTreeType *ttype)
+void register_node_type_sh_combrgb(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_COMBRGB, "Combine RGB", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_COMBRGB, "Combine RGB", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_combrgb_in, sh_node_combrgb_out);
node_type_size(&ntype, 80, 40, 140);
- node_type_exec(&ntype, node_shader_exec_combrgb);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_combrgb);
node_type_gpu(&ntype, gpu_shader_combrgb);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_squeeze.c b/source/blender/nodes/shader/nodes/node_shader_squeeze.c
index 8073f4b01d2..ad2e7353ac8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_squeeze.c
+++ b/source/blender/nodes/shader/nodes/node_shader_squeeze.c
@@ -45,7 +45,7 @@ static bNodeSocketTemplate sh_node_squeeze_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_squeeze(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_squeeze(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
float vec[3];
@@ -56,22 +56,22 @@ static void node_shader_exec_squeeze(void *UNUSED(data), bNode *UNUSED(node), bN
out[0]->vec[0] = 1.0f / (1.0f + powf(M_E, -((vec[0] - vec[2]) * vec[1])));
}
-static int gpu_shader_squeeze(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_squeeze(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "squeeze", in, out);
}
-void register_node_type_sh_squeeze(bNodeTreeType *ttype)
+void register_node_type_sh_squeeze(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_SQUEEZE, "Squeeze Value", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_SQUEEZE, "Squeeze Value", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING);
node_type_socket_templates(&ntype, sh_node_squeeze_in, sh_node_squeeze_out);
node_type_size(&ntype, 120, 110, 160);
node_type_storage(&ntype, "node_squeeze", NULL, NULL);
- node_type_exec(&ntype, node_shader_exec_squeeze);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_squeeze);
node_type_gpu(&ntype, gpu_shader_squeeze);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tangent.c b/source/blender/nodes/shader/nodes/node_shader_tangent.c
index 6c0d6d7cd9f..3f4c59f81ee 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tangent.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tangent.c
@@ -34,7 +34,7 @@ static bNodeSocketTemplate sh_node_tangent_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tangent(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_tangent(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeShaderTangent *attr = MEM_callocN(sizeof(NodeShaderTangent), "NodeShaderTangent");
attr->axis = SHD_TANGENT_AXIS_Z;
@@ -42,19 +42,16 @@ static void node_shader_init_tangent(bNodeTree *UNUSED(ntree), bNode *node, bNod
}
/* node type definition */
-void register_node_type_sh_tangent(bNodeTreeType *ttype)
+void register_node_type_sh_tangent(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TANGENT, "Tangent", NODE_CLASS_INPUT, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TANGENT, "Tangent", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_tangent_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tangent);
node_type_storage(&ntype, "NodeShaderTangent", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
- node_type_gpu(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
-
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 66bf0267586..dad74d324f8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
@@ -48,7 +48,7 @@ static bNodeSocketTemplate sh_node_tex_brick_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp))
+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);
@@ -62,7 +62,7 @@ static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode* node, bN
node->storage = tex;
}
-static int node_shader_gpu_tex_brick(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_brick(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[0].link)
in[0].link = GPU_attribute(CD_ORCO, "");
@@ -73,18 +73,17 @@ static int node_shader_gpu_tex_brick(GPUMaterial *mat, bNode *node, GPUNodeStack
}
/* node type definition */
-void register_node_type_sh_tex_brick(bNodeTreeType *ttype)
+void register_node_type_sh_tex_brick(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_BRICK, "Brick Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_BRICK, "Brick Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_brick_in, sh_node_tex_brick_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_brick);
node_type_storage(&ntype, "NodeTexBrick", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_brick);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
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 8a2ae2d40dc..dff533c4d80 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c
@@ -43,7 +43,7 @@ static bNodeSocketTemplate sh_node_tex_checker_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_checker(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+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);
@@ -52,7 +52,7 @@ static void node_shader_init_tex_checker(bNodeTree *UNUSED(ntree), bNode *node,
node->storage = tex;
}
-static int node_shader_gpu_tex_checker(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_checker(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[0].link)
in[0].link = GPU_attribute(CD_ORCO, "");
@@ -63,18 +63,17 @@ static int node_shader_gpu_tex_checker(GPUMaterial *mat, bNode *node, GPUNodeSta
}
/* node type definition */
-void register_node_type_sh_tex_checker(bNodeTreeType *ttype)
+void register_node_type_sh_tex_checker(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_CHECKER, "Checker Texture", NODE_CLASS_TEXTURE, 0);
+ sh_node_type_base(&ntype, SH_NODE_TEX_CHECKER, "Checker Texture", NODE_CLASS_TEXTURE, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_checker_in, sh_node_tex_checker_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_checker);
node_type_storage(&ntype, "NodeTexChecker", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_checker);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
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 dd717874951..5af5477e5c7 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
@@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_tex_coord_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
GPUNodeLink *orco = GPU_attribute(CD_ORCO, "");
GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, "");
@@ -53,18 +53,17 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), GPUN
}
/* node type definition */
-void register_node_type_sh_tex_coord(bNodeTreeType *ttype)
+void register_node_type_sh_tex_coord(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_COORD, "Texture Coordinate", NODE_CLASS_INPUT, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_COORD, "Texture Coordinate", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_tex_coord_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_coord);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
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 d2d0870e2ed..05352e810c0 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
@@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_tex_environment_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+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);
@@ -56,7 +56,7 @@ static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode *no
node->storage = tex;
}
-static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
Image *ima= (Image*)node->id;
ImageUser *iuser= NULL;
@@ -88,18 +88,17 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, GPUNod
}
/* node type definition */
-void register_node_type_sh_tex_environment(bNodeTreeType *ttype)
+void register_node_type_sh_tex_environment(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_ENVIRONMENT, "Environment Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_ENVIRONMENT, "Environment Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_environment_in, sh_node_tex_environment_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_environment);
node_type_storage(&ntype, "NodeTexEnvironment", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_environment);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
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 0802ecdea1d..5f559f9d0d6 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c
@@ -40,7 +40,7 @@ static bNodeSocketTemplate sh_node_tex_gradient_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_gradient(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+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);
@@ -50,7 +50,7 @@ static void node_shader_init_tex_gradient(bNodeTree *UNUSED(ntree), bNode *node,
node->storage = tex;
}
-static int node_shader_gpu_tex_gradient(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_gradient(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[0].link)
in[0].link = GPU_attribute(CD_ORCO, "");
@@ -61,18 +61,17 @@ static int node_shader_gpu_tex_gradient(GPUMaterial *mat, bNode *node, GPUNodeSt
}
/* node type definition */
-void register_node_type_sh_tex_gradient(bNodeTreeType *ttype)
+void register_node_type_sh_tex_gradient(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_GRADIENT, "Gradient Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_GRADIENT, "Gradient Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_gradient_in, sh_node_tex_gradient_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_gradient);
node_type_storage(&ntype, "NodeTexGradient", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_gradient);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
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 49b38434246..6a28414e8c4 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_tex_image_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+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);
@@ -56,7 +56,7 @@ static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode *node, bN
node->storage = tex;
}
-static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
Image *ima= (Image*)node->id;
ImageUser *iuser= NULL;
@@ -88,18 +88,17 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, GPUNodeStack
}
/* node type definition */
-void register_node_type_sh_tex_image(bNodeTreeType *ttype)
+void register_node_type_sh_tex_image(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_IMAGE, "Image Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_IMAGE, "Image Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_image_in, sh_node_tex_image_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_image);
node_type_storage(&ntype, "NodeTexImage", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_image);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
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 86feabbcc2b..c7c29f2c17a 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c
@@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_tex_magic_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_magic(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+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);
@@ -52,7 +52,7 @@ static void node_shader_init_tex_magic(bNodeTree *UNUSED(ntree), bNode *node, bN
node->storage = tex;
}
-static int node_shader_gpu_tex_magic(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_magic(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
NodeTexMagic *tex = (NodeTexMagic*)node->storage;
float depth = tex->depth;
@@ -66,18 +66,17 @@ static int node_shader_gpu_tex_magic(GPUMaterial *mat, bNode *node, GPUNodeStack
}
/* node type definition */
-void register_node_type_sh_tex_magic(bNodeTreeType *ttype)
+void register_node_type_sh_tex_magic(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_MAGIC, "Magic Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_MAGIC, "Magic Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_magic_in, sh_node_tex_magic_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_magic);
node_type_storage(&ntype, "NodeTexMagic", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_magic);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
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 cd4b5743e14..ae77c13c929 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
@@ -46,7 +46,7 @@ static bNodeSocketTemplate sh_node_tex_musgrave_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+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);
@@ -56,7 +56,7 @@ static void node_shader_init_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node,
node->storage = tex;
}
-static int node_shader_gpu_tex_musgrave(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_musgrave(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[0].link)
in[0].link = GPU_attribute(CD_ORCO, "");
@@ -67,18 +67,17 @@ static int node_shader_gpu_tex_musgrave(GPUMaterial *mat, bNode *node, GPUNodeSt
}
/* node type definition */
-void register_node_type_sh_tex_musgrave(bNodeTreeType *ttype)
+void register_node_type_sh_tex_musgrave(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_MUSGRAVE, "Musgrave Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_MUSGRAVE, "Musgrave Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_musgrave_in, sh_node_tex_musgrave_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_musgrave);
node_type_storage(&ntype, "NodeTexMusgrave", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_musgrave);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
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 18788f9e72c..3d3f4c86547 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
@@ -43,7 +43,7 @@ static bNodeSocketTemplate sh_node_tex_noise_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_noise(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+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);
@@ -52,7 +52,7 @@ static void node_shader_init_tex_noise(bNodeTree *UNUSED(ntree), bNode *node, bN
node->storage = tex;
}
-static int node_shader_gpu_tex_noise(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_noise(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[0].link)
in[0].link = GPU_attribute(CD_ORCO, "");
@@ -63,18 +63,17 @@ static int node_shader_gpu_tex_noise(GPUMaterial *mat, bNode *node, GPUNodeStack
}
/* node type definition */
-void register_node_type_sh_tex_noise(bNodeTreeType *ttype)
+void register_node_type_sh_tex_noise(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_NOISE, "Noise Texture", NODE_CLASS_TEXTURE, 0);
+ sh_node_type_base(&ntype, SH_NODE_TEX_NOISE, "Noise Texture", NODE_CLASS_TEXTURE, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_noise_in, sh_node_tex_noise_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_noise);
node_type_storage(&ntype, "NodeTexNoise", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_noise);
- nodeRegisterType(ttype, &ntype);
+ 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 7a1b853a7f4..e92ff5ddade 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
@@ -39,7 +39,7 @@ static bNodeSocketTemplate sh_node_tex_sky_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+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);
@@ -52,7 +52,7 @@ static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node, bNod
node->storage = tex;
}
-static int node_shader_gpu_tex_sky(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_sky(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[0].link)
in[0].link = GPU_attribute(CD_ORCO, "");
@@ -63,18 +63,17 @@ static int node_shader_gpu_tex_sky(GPUMaterial *mat, bNode *node, GPUNodeStack *
}
/* node type definition */
-void register_node_type_sh_tex_sky(bNodeTreeType *ttype)
+void register_node_type_sh_tex_sky(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_SKY, "Sky Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_SKY, "Sky Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_sky_in, sh_node_tex_sky_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_sky);
node_type_storage(&ntype, "NodeTexSky", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_sky);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
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 d4cc24687b3..89856864036 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
@@ -41,7 +41,7 @@ static bNodeSocketTemplate sh_node_tex_voronoi_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+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);
@@ -51,7 +51,7 @@ static void node_shader_init_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node,
node->storage = tex;
}
-static int node_shader_gpu_tex_voronoi(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_voronoi(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[0].link)
in[0].link = GPU_attribute(CD_ORCO, "");
@@ -62,18 +62,17 @@ static int node_shader_gpu_tex_voronoi(GPUMaterial *mat, bNode *node, GPUNodeSta
}
/* node type definition */
-void register_node_type_sh_tex_voronoi(bNodeTreeType *ttype)
+void register_node_type_sh_tex_voronoi(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_VORONOI, "Voronoi Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_VORONOI, "Voronoi Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_voronoi_in, sh_node_tex_voronoi_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_voronoi);
node_type_storage(&ntype, "NodeTexVoronoi", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_voronoi);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
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 8b23de0310c..22edacd347d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c
@@ -44,7 +44,7 @@ static bNodeSocketTemplate sh_node_tex_wave_out[] = {
{ -1, 0, "" }
};
-static void node_shader_init_tex_wave(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+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);
@@ -54,7 +54,7 @@ static void node_shader_init_tex_wave(bNodeTree *UNUSED(ntree), bNode *node, bNo
node->storage = tex;
}
-static int node_shader_gpu_tex_wave(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int node_shader_gpu_tex_wave(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[0].link)
in[0].link = GPU_attribute(CD_ORCO, "");
@@ -65,18 +65,17 @@ static int node_shader_gpu_tex_wave(GPUMaterial *mat, bNode *node, GPUNodeStack
}
/* node type definition */
-void register_node_type_sh_tex_wave(bNodeTreeType *ttype)
+void register_node_type_sh_tex_wave(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEX_WAVE, "Wave Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_TEX_WAVE, "Wave Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_tex_wave_in, sh_node_tex_wave_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tex_wave);
node_type_storage(&ntype, "NodeTexWave", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_tex_wave);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_texture.c b/source/blender/nodes/shader/nodes/node_shader_texture.c
index b77c7d07407..1ff315f6b80 100644
--- a/source/blender/nodes/shader/nodes/node_shader_texture.c
+++ b/source/blender/nodes/shader/nodes/node_shader_texture.c
@@ -48,7 +48,7 @@ static bNodeSocketTemplate sh_node_texture_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_texture(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
if (data && node->id) {
ShadeInput *shi= ((ShaderCallData *)data)->shi;
@@ -72,7 +72,7 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b
if (in[0]->datatype==NS_OSA_VECTORS) {
float *fp= in[0]->data;
- retval= multitex_nodes((Tex *)node->id, vec, fp, fp+3, shi->osatex, &texres, thread, which_output, NULL, NULL);
+ retval = multitex_nodes((Tex *)node->id, vec, fp, fp+3, shi->osatex, &texres, thread, which_output, NULL, NULL, NULL);
}
else if (in[0]->datatype==NS_OSA_VALUES) {
float *fp= in[0]->data;
@@ -80,14 +80,14 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b
dxt[0] = fp[0]; dxt[1] = dxt[2] = 0.0f;
dyt[0] = fp[1]; dyt[1] = dyt[2] = 0.0f;
- retval= multitex_nodes((Tex *)node->id, vec, dxt, dyt, shi->osatex, &texres, thread, which_output, NULL, NULL);
+ retval = multitex_nodes((Tex *)node->id, vec, dxt, dyt, shi->osatex, &texres, thread, which_output, NULL, NULL, NULL);
}
else
- retval= multitex_nodes((Tex *)node->id, vec, NULL, NULL, 0, &texres, thread, which_output, NULL, NULL);
+ retval = multitex_nodes((Tex *)node->id, vec, NULL, NULL, 0, &texres, thread, which_output, NULL, NULL, NULL);
}
else {
copy_v3_v3(vec, shi->lo);
- retval= multitex_nodes((Tex *)node->id, vec, NULL, NULL, 0, &texres, thread, which_output, NULL, NULL);
+ retval = multitex_nodes((Tex *)node->id, vec, NULL, NULL, 0, &texres, thread, which_output, NULL, NULL, NULL);
}
/* stupid exception */
@@ -113,13 +113,14 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b
copy_v3_v3(out[2]->vec, nor);
- if (shi->do_preview)
- nodeAddToPreview(node, out[1]->vec, shi->xs, shi->ys, shi->do_manage);
+ if (shi->do_preview) {
+ BKE_node_preview_set_pixel(execdata->preview, out[1]->vec, shi->xs, shi->ys, shi->do_manage);
+ }
}
}
-static int gpu_shader_texture(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_texture(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
Tex *tex = (Tex*)node->id;
@@ -143,16 +144,16 @@ static int gpu_shader_texture(GPUMaterial *mat, bNode *node, GPUNodeStack *in, G
return 0;
}
-void register_node_type_sh_texture(bNodeTreeType *ttype)
+void register_node_type_sh_texture(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW);
+ sh_node_type_base(&ntype, SH_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW);
node_type_compatibility(&ntype, NODE_OLD_SHADING);
node_type_socket_templates(&ntype, sh_node_texture_in, sh_node_texture_out);
node_type_size(&ntype, 120, 80, 240);
- node_type_exec(&ntype, node_shader_exec_texture);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_texture);
node_type_gpu(&ntype, gpu_shader_texture);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c
index 182487d343e..d5f0bf30966 100644
--- a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c
@@ -43,7 +43,7 @@ static bNodeSocketTemplate sh_node_valtorgb_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_valtorgb(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_valtorgb(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
/* stack order in: fac */
/* stack order out: col, alpha */
@@ -57,12 +57,12 @@ static void node_shader_exec_valtorgb(void *UNUSED(data), bNode *node, bNodeStac
}
}
-static void node_shader_init_valtorgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void node_shader_init_valtorgb(bNodeTree *UNUSED(ntree), bNode *node)
{
- node->storage= add_colorband(1);
+ node->storage= add_colorband(true);
}
-static int gpu_shader_valtorgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_valtorgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
float *array;
int size;
@@ -71,20 +71,20 @@ static int gpu_shader_valtorgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in,
return GPU_stack_link(mat, "valtorgb", in, out, GPU_texture(size, array));
}
-void register_node_type_sh_valtorgb(bNodeTreeType *ttype)
+void register_node_type_sh_valtorgb(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_valtorgb_in, sh_node_valtorgb_out);
node_type_size(&ntype, 240, 200, 300);
node_type_init(&ntype, node_shader_init_valtorgb);
node_type_storage(&ntype, "ColorBand", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, node_shader_exec_valtorgb);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_valtorgb);
node_type_gpu(&ntype, gpu_shader_valtorgb);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
@@ -99,7 +99,7 @@ static bNodeSocketTemplate sh_node_rgbtobw_out[] = {
};
-static void node_shader_exec_rgbtobw(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_rgbtobw(void *UNUSED(data), int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
/* stack order out: bw */
/* stack order in: col */
@@ -107,21 +107,21 @@ static void node_shader_exec_rgbtobw(void *UNUSED(data), bNode *UNUSED(node), bN
out[0]->vec[0] = rgb_to_bw(in[0]->vec);
}
-static int gpu_shader_rgbtobw(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_rgbtobw(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "rgbtobw", in, out);
}
-void register_node_type_sh_rgbtobw(bNodeTreeType *ttype)
+void register_node_type_sh_rgbtobw(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0);
+ sh_node_type_base(&ntype, SH_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_rgbtobw_in, sh_node_rgbtobw_out);
node_type_size(&ntype, 80, 40, 120);
- node_type_exec(&ntype, node_shader_exec_rgbtobw);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_rgbtobw);
node_type_gpu(&ntype, gpu_shader_rgbtobw);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_value.c b/source/blender/nodes/shader/nodes/node_shader_value.c
index a3d1e5afec2..642b5061a76 100644
--- a/source/blender/nodes/shader/nodes/node_shader_value.c
+++ b/source/blender/nodes/shader/nodes/node_shader_value.c
@@ -34,49 +34,25 @@
/* **************** VALUE ******************** */
static bNodeSocketTemplate sh_node_value_out[] = {
- /* XXX value nodes use the output sockets for buttons, so we need explicit limits here! */
- { SOCK_FLOAT, 0, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
+ { SOCK_FLOAT, 0, N_("Value"), 0.5f, 0, 0, 0, -FLT_MAX, FLT_MAX, PROP_NONE},
{ -1, 0, "" }
};
-static void node_shader_init_value(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static int gpu_shader_value(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- bNodeSocket *sock= node->outputs.first;
- bNodeSocketValueFloat *dval= (bNodeSocketValueFloat*)sock->default_value;
- /* uses the default value of the output socket, must be initialized here */
- dval->value = 0.5f;
- dval->min = -FLT_MAX;
- dval->max = FLT_MAX;
-}
-
-static void node_shader_exec_value(void *UNUSED(data), bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
-{
- bNodeSocket *sock= node->outputs.first;
- float val= ((bNodeSocketValueFloat*)sock->default_value)->value;
-
- out[0]->vec[0] = val;
-}
-
-static int gpu_shader_value(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
-{
- bNodeSocket *sock= node->outputs.first;
- float *val= &((bNodeSocketValueFloat*)sock->default_value)->value;
- GPUNodeLink *vec = GPU_uniform(val);
-
+ GPUNodeLink *vec = GPU_uniform(out[0].vec);
return GPU_stack_link(mat, "set_value", in, out, vec);
}
-void register_node_type_sh_value(bNodeTreeType *ttype)
+void register_node_type_sh_value(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_VALUE, "Value", NODE_CLASS_INPUT, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_VALUE, "Value", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_value_out);
- node_type_init(&ntype, node_shader_init_value);
node_type_size(&ntype, 80, 50, 120);
- node_type_exec(&ntype, node_shader_exec_value);
node_type_gpu(&ntype, gpu_shader_value);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_vectMath.c b/source/blender/nodes/shader/nodes/node_shader_vectMath.c
index 3e00421ddf0..9eb3c5a14e4 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vectMath.c
+++ b/source/blender/nodes/shader/nodes/node_shader_vectMath.c
@@ -47,7 +47,7 @@ static bNodeSocketTemplate sh_node_vect_math_out[] = {
{ -1, 0, "" }
};
-static void node_shader_exec_vect_math(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_shader_exec_vect_math(void *UNUSED(data), int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
float vec1[3], vec2[3];
@@ -102,7 +102,7 @@ static void node_shader_exec_vect_math(void *UNUSED(data), bNode *node, bNodeSta
}
-static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out)
+static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
static const char *names[] = {"vec_math_add", "vec_math_sub",
"vec_math_average", "vec_math_dot", "vec_math_cross",
@@ -139,18 +139,18 @@ static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in,
return 1;
}
-void register_node_type_sh_vect_math(bNodeTreeType *ttype)
+void register_node_type_sh_vect_math(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_VECT_MATH, "Vector Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ sh_node_type_base(&ntype, SH_NODE_VECT_MATH, "Vector Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_vect_math_in, sh_node_vect_math_out);
node_type_size(&ntype, 80, 75, 140);
node_type_label(&ntype, node_vect_math_label);
node_type_storage(&ntype, "node_vect_math", NULL, NULL);
- node_type_exec(&ntype, node_shader_exec_vect_math);
+ node_type_exec(&ntype, NULL, NULL, node_shader_exec_vect_math);
node_type_gpu(&ntype, gpu_shader_vect_math);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c b/source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c
index 5451eb303cc..458fbf43625 100644
--- a/source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c
+++ b/source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c
@@ -40,24 +40,23 @@ static bNodeSocketTemplate sh_node_volume_isotropic_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_volume_isotropic(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
+static int node_shader_gpu_volume_isotropic(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
{
return 0;
}
/* node type definition */
-void register_node_type_sh_volume_isotropic(bNodeTreeType *ttype)
+void register_node_type_sh_volume_isotropic(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_VOLUME_ISOTROPIC, "Isotropic Volume", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_VOLUME_ISOTROPIC, "Isotropic Volume", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_volume_isotropic_in, sh_node_volume_isotropic_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_volume_isotropic);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_transparent.c b/source/blender/nodes/shader/nodes/node_shader_volume_transparent.c
index ad7d7fceda3..c9bac06cbb0 100644
--- a/source/blender/nodes/shader/nodes/node_shader_volume_transparent.c
+++ b/source/blender/nodes/shader/nodes/node_shader_volume_transparent.c
@@ -40,24 +40,23 @@ static bNodeSocketTemplate sh_node_volume_transparent_out[] = {
{ -1, 0, "" }
};
-static int node_shader_gpu_volume_transparent(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
+static int node_shader_gpu_volume_transparent(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
{
return 0;
}
/* node type definition */
-void register_node_type_sh_volume_transparent(bNodeTreeType *ttype)
+void register_node_type_sh_volume_transparent(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, SH_NODE_VOLUME_TRANSPARENT, "Transparent Volume", NODE_CLASS_SHADER, 0);
+ sh_node_type_base(&ntype, SH_NODE_VOLUME_TRANSPARENT, "Transparent Volume", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_volume_transparent_in, sh_node_volume_transparent_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, node_shader_gpu_volume_transparent);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c
index ba94531c259..bab8ef0c631 100644
--- a/source/blender/nodes/texture/node_texture_tree.c
+++ b/source/blender/nodes/texture/node_texture_tree.c
@@ -34,6 +34,7 @@
#include "DNA_texture_types.h"
#include "DNA_node_types.h"
+#include "DNA_space_types.h"
#include "BLI_listbase.h"
#include "BLI_threads.h"
@@ -41,9 +42,11 @@
#include "BLF_translation.h"
+#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BKE_paint.h"
#include "node_common.h"
#include "node_exec.h"
@@ -51,16 +54,59 @@
#include "NOD_texture.h"
#include "node_texture_util.h"
+#include "RNA_access.h"
+
#include "RE_pipeline.h"
#include "RE_shader_ext.h"
-static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func)
+static void texture_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
{
- Tex *tx;
- for (tx = main->tex.first; tx; tx = tx->id.next) {
- if (tx->nodetree) {
- func(calldata, &tx->id, tx->nodetree);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = OBACT;
+ Tex *tx = NULL;
+
+ if (snode->texfrom == SNODE_TEX_OBJECT) {
+ if (ob) {
+ tx = give_current_object_texture(ob);
+ if (tx) {
+ if (ob->type == OB_LAMP)
+ *r_from = (ID*)ob->data;
+ else
+ *r_from = (ID*)give_current_material(ob, ob->actcol);
+
+ /* from is not set fully for material nodes, should be ID + Node then */
+ *r_id = &tx->id;
+ *r_ntree = tx->nodetree;
+ }
+ }
+ }
+ else if (snode->texfrom == SNODE_TEX_WORLD) {
+ if (scene->world) {
+ *r_from = (ID *)scene->world;
+ tx = give_current_world_texture(scene->world);
+ if (tx) {
+ *r_id = &tx->id;
+ *r_ntree = tx->nodetree;
+ }
+ }
+ }
+ else {
+ struct Brush *brush = NULL;
+
+ if (ob && (ob->mode & OB_MODE_SCULPT))
+ brush = paint_brush(&scene->toolsettings->sculpt->paint);
+ else
+ brush = paint_brush(&scene->toolsettings->imapaint.paint);
+
+ if (brush) {
+ *r_from = (ID *)brush;
+ tx = give_current_brush_texture(brush);
+ if (tx) {
+ *r_id = &tx->id;
+ *r_ntree = tx->nodetree;
+ }
}
}
}
@@ -75,6 +121,7 @@ static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCa
func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor"));
func(calldata, NODE_CLASS_DISTORT, N_("Distort"));
func(calldata, NODE_CLASS_GROUP, N_("Group"));
+ func(calldata, NODE_CLASS_INTERFACE, N_("Interface"));
func(calldata, NODE_CLASS_LAYOUT, N_("Layout"));
}
@@ -95,47 +142,47 @@ static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree))
static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
{
- bNode *lnode;
-
- /* copy over contents of previews */
- for (lnode = localtree->nodes.first; lnode; lnode = lnode->next) {
- if (ntreeNodeExists(ntree, lnode->new_node)) {
- bNode *node = lnode->new_node;
-
- if (node->preview && node->preview->rect) {
- if (lnode->preview && lnode->preview->rect) {
- int xsize = node->preview->xsize;
- int ysize = node->preview->ysize;
- memcpy(node->preview->rect, lnode->preview->rect, 4 * xsize + xsize * ysize * sizeof(char) * 4);
- }
- }
- }
- }
+ BKE_node_preview_sync_tree(ntree, localtree);
+}
+
+static void local_merge(bNodeTree *localtree, bNodeTree *ntree)
+{
+ BKE_node_preview_merge_tree(ntree, localtree, true);
}
static void update(bNodeTree *ntree)
{
ntree_update_reroute_nodes(ntree);
+
+ if (ntree->update & NTREE_UPDATE_NODES) {
+ /* clean up preview cache, in case nodes have been removed */
+ BKE_node_preview_remove_unused(ntree);
+ }
}
-bNodeTreeType ntreeType_Texture = {
- /* type */ NTREE_TEXTURE,
- /* id_name */ "NTTexture Nodetree",
+bNodeTreeType *ntreeType_Texture;
+
+void register_node_tree_type_tex(void)
+{
+ bNodeTreeType *tt = ntreeType_Texture = MEM_callocN(sizeof(bNodeTreeType), "texture node tree type");
- /* node_types */ { NULL, NULL },
+ tt->type = NTREE_TEXTURE;
+ strcpy(tt->idname, "TextureNodeTree");
+ strcpy(tt->ui_name, "Texture");
+ tt->ui_icon = 0; /* defined in drawnode.c */
+ strcpy(tt->ui_description, "");
- /* free_cache */ NULL,
- /* free_node_cache */ NULL,
- /* foreach_nodetree */ foreach_nodetree,
- /* foreach_nodeclass */ foreach_nodeclass,
- /* localize */ localize,
- /* local_sync */ local_sync,
- /* local_merge */ NULL,
- /* update */ update,
- /* update_node */ NULL,
- /* validate_link */ NULL,
- /* update_internal_links */ node_update_internal_links_default
-};
+ tt->foreach_nodeclass = foreach_nodeclass;
+ tt->update = update;
+ tt->localize = localize;
+ tt->local_sync = local_sync;
+ tt->local_merge = local_merge;
+ tt->get_from_context = texture_get_from_context;
+
+ tt->ext.srna = &RNA_TextureNodeTree;
+
+ ntreeTypeAdd(tt);
+}
int ntreeTexTagAnimated(bNodeTree *ntree)
{
@@ -158,24 +205,13 @@ int ntreeTexTagAnimated(bNodeTree *ntree)
return 0;
}
-/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
- * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
- */
-bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree, int use_tree_data)
+bNodeTreeExec *ntreeTexBeginExecTree_internal(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
{
bNodeTreeExec *exec;
bNode *node;
- if (use_tree_data) {
- /* XXX hack: prevent exec data from being generated twice.
- * this should be handled by the renderer!
- */
- if (ntree->execdata)
- return ntree->execdata;
- }
-
/* common base initialization */
- exec = ntree_exec_begin(ntree);
+ exec = ntree_exec_begin(context, ntree, parent_key);
/* allocate the thread stack listbase array */
exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array");
@@ -183,12 +219,28 @@ bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree, int use_tree_data)
for (node = exec->nodetree->nodes.first; node; node = node->next)
node->need_exec = 1;
- if (use_tree_data) {
- /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
- * which only store the ntree pointer. Should be fixed at some point!
- */
- ntree->execdata = exec;
- }
+ return exec;
+}
+
+bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree)
+{
+ bNodeExecContext context;
+ bNodeTreeExec *exec;
+
+ /* XXX hack: prevent exec data from being generated twice.
+ * this should be handled by the renderer!
+ */
+ if (ntree->execdata)
+ return ntree->execdata;
+
+ context.previews = ntree->previews;
+
+ exec = ntreeTexBeginExecTree_internal(&context, ntree, NODE_INSTANCE_KEY_BASE);
+
+ /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes,
+ * which only store the ntree pointer. Should be fixed at some point!
+ */
+ ntree->execdata = exec;
return exec;
}
@@ -207,35 +259,34 @@ static void tex_free_delegates(bNodeTreeExec *exec)
MEM_freeN(ns->data);
}
-/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes.
- * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees.
- */
-void ntreeTexEndExecTree(bNodeTreeExec *exec, int use_tree_data)
+void ntreeTexEndExecTree_internal(bNodeTreeExec *exec)
{
- if (exec) {
- bNodeTree *ntree = exec->nodetree;
- bNodeThreadStack *nts;
- int a;
+ bNodeThreadStack *nts;
+ int a;
+
+ if (exec->threadstack) {
+ tex_free_delegates(exec);
- if (exec->threadstack) {
- tex_free_delegates(exec);
-
- for (a = 0; a < BLENDER_MAX_THREADS; a++) {
- for (nts = exec->threadstack[a].first; nts; nts = nts->next)
- if (nts->stack) MEM_freeN(nts->stack);
- BLI_freelistN(&exec->threadstack[a]);
- }
-
- MEM_freeN(exec->threadstack);
- exec->threadstack = NULL;
+ for (a = 0; a < BLENDER_MAX_THREADS; a++) {
+ for (nts = exec->threadstack[a].first; nts; nts = nts->next)
+ if (nts->stack) MEM_freeN(nts->stack);
+ BLI_freelistN(&exec->threadstack[a]);
}
- ntree_exec_end(exec);
+ MEM_freeN(exec->threadstack);
+ exec->threadstack = NULL;
+ }
+
+ ntree_exec_end(exec);
+}
+
+void ntreeTexEndExecTree(bNodeTreeExec *exec)
+{
+ if (exec) {
+ ntreeTexEndExecTree_internal(exec);
- if (use_tree_data) {
- /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
- ntree->execdata = NULL;
- }
+ /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */
+ exec->nodetree->execdata = NULL;
}
}
@@ -275,7 +326,7 @@ int ntreeTexExecTree(
if (!exec) {
BLI_lock_thread(LOCK_NODES);
if (!nodes->execdata)
- ntreeTexBeginExecTree(nodes, 1);
+ ntreeTexBeginExecTree(nodes);
BLI_unlock_thread(LOCK_NODES);
exec = nodes->execdata;
diff --git a/source/blender/nodes/texture/node_texture_util.c b/source/blender/nodes/texture/node_texture_util.c
index 06473d800d0..80644157b02 100644
--- a/source/blender/nodes/texture/node_texture_util.c
+++ b/source/blender/nodes/texture/node_texture_util.c
@@ -49,13 +49,28 @@
#include <assert.h>
#include "node_texture_util.h"
+
+int tex_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree)
+{
+ return (strcmp(ntree->idname, "TextureNodeTree")==0);
+}
+
+void tex_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag)
+{
+ node_type_base(ntype, type, name, nclass, flag);
+
+ ntype->poll = tex_node_poll_default;
+ ntype->update_internal_links = node_update_internal_links_default;
+}
+
+
static void tex_call_delegate(TexDelegate *dg, float *out, TexParams *params, short thread)
{
if (dg->node->need_exec) {
dg->fn(out, params, dg->node, dg->in, thread);
if (dg->cdata->do_preview)
- tex_do_preview(dg->node, params->previewco, out);
+ tex_do_preview(dg->preview, params->previewco, out);
}
}
@@ -112,19 +127,17 @@ void params_from_cdata(TexParams *out, TexCallData *in)
out->mtex = in->mtex;
}
-void tex_do_preview(bNode *node, const float coord[2], const float col[4])
+void tex_do_preview(bNodePreview *preview, const float coord[2], const float col[4])
{
- bNodePreview *preview = node->preview;
-
if (preview) {
int xs = ((coord[0] + 1.0f) * 0.5f) * preview->xsize;
int ys = ((coord[1] + 1.0f) * 0.5f) * preview->ysize;
-
- nodeAddToPreview(node, col, xs, ys, 0); /* 0 = no color management */
+
+ BKE_node_preview_set_pixel(preview, col, xs, ys, 0); /* 0 = no color management */
}
}
-void tex_output(bNode *node, bNodeStack **in, bNodeStack *out, TexFn texfn, TexCallData *cdata)
+void tex_output(bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack *out, TexFn texfn, TexCallData *cdata)
{
TexDelegate *dg;
if (!out->data)
@@ -136,6 +149,7 @@ void tex_output(bNode *node, bNodeStack **in, bNodeStack *out, TexFn texfn, TexC
dg->cdata = cdata;
dg->fn = texfn;
dg->node = node;
+ dg->preview = execdata->preview;
memcpy(dg->in, in, MAX_SOCKET * sizeof(bNodeStack *));
dg->type = out->sockettype;
}
diff --git a/source/blender/nodes/texture/node_texture_util.h b/source/blender/nodes/texture/node_texture_util.h
index 16dbc2f7bfb..b81ea51ddff 100644
--- a/source/blender/nodes/texture/node_texture_util.h
+++ b/source/blender/nodes/texture/node_texture_util.h
@@ -48,6 +48,12 @@
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_rand.h"
+#include "BLI_threads.h"
+#include "BLI_utildefines.h"
+
#include "BKE_blender.h"
#include "BKE_colortools.h"
#include "BKE_global.h"
@@ -56,18 +62,12 @@
#include "BKE_material.h"
#include "BKE_node.h"
#include "BKE_texture.h"
-
#include "BKE_library.h"
#include "node_util.h"
-
#include "NOD_texture.h"
-#include "BLI_math.h"
-#include "BLI_blenlib.h"
-#include "BLI_rand.h"
-#include "BLI_threads.h"
-#include "BLI_utildefines.h"
+#include "NOD_texture.h"
#include "BLF_translation.h"
@@ -112,16 +112,21 @@ typedef struct TexDelegate {
TexCallData *cdata;
TexFn fn;
bNode *node;
+ bNodePreview *preview;
bNodeStack *in[MAX_SOCKET];
int type;
} TexDelegate;
+
+int tex_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree);
+void tex_node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag);
+
void tex_input_rgba(float *out, bNodeStack *in, TexParams *params, short thread);
void tex_input_vec(float *out, bNodeStack *in, TexParams *params, short thread);
float tex_input_value(bNodeStack *in, TexParams *params, short thread);
-void tex_output(bNode *node, bNodeStack **in, bNodeStack *out, TexFn texfn, TexCallData *data);
-void tex_do_preview(bNode *node, const float coord[2], const float col[4]);
+void tex_output(bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack *out, TexFn texfn, TexCallData *data);
+void tex_do_preview(bNodePreview *preview, const float coord[2], const float col[4]);
void params_from_cdata(TexParams *out, TexCallData *in);
diff --git a/source/blender/nodes/texture/nodes/node_texture_at.c b/source/blender/nodes/texture/nodes/node_texture_at.c
index 4c2d276b902..aafb9793d2c 100644
--- a/source/blender/nodes/texture/nodes/node_texture_at.c
+++ b/source/blender/nodes/texture/nodes/node_texture_at.c
@@ -53,19 +53,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **
tex_input_rgba(out, in[0], &np, thread);
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_at(bNodeTreeType *ttype)
+void register_node_type_tex_at(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_AT, "At", NODE_CLASS_DISTORT, 0);
+ tex_node_type_base(&ntype, TEX_NODE_AT, "At", NODE_CLASS_DISTORT, 0);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 140, 100, 320);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_bricks.c b/source/blender/nodes/texture/nodes/node_texture_bricks.c
index b4f81f08e43..15cde299f35 100644
--- a/source/blender/nodes/texture/nodes/node_texture_bricks.c
+++ b/source/blender/nodes/texture/nodes/node_texture_bricks.c
@@ -50,7 +50,7 @@ static bNodeSocketTemplate outputs[] = {
{ -1, 0, "" }
};
-static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom3 = 0.5; /* offset */
node->custom4 = 1.0; /* squash */
@@ -116,20 +116,20 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
}
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_bricks(bNodeTreeType *ttype)
+void register_node_type_tex_bricks(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_BRICKS, "Bricks", NODE_CLASS_PATTERN, NODE_PREVIEW|NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_BRICKS, "Bricks", NODE_CLASS_PATTERN, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 150, 60, 150);
node_type_init(&ntype, init);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_checker.c b/source/blender/nodes/texture/nodes/node_texture_checker.c
index 1f653d1f7b9..77c6a2e3010 100644
--- a/source/blender/nodes/texture/nodes/node_texture_checker.c
+++ b/source/blender/nodes/texture/nodes/node_texture_checker.c
@@ -65,19 +65,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **
}
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_checker(bNodeTreeType *ttype)
+void register_node_type_tex_checker(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_CHECKER, "Checker", NODE_CLASS_PATTERN, NODE_PREVIEW|NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_CHECKER, "Checker", NODE_CLASS_PATTERN, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 100, 60, 150);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_common.c b/source/blender/nodes/texture/nodes/node_texture_common.c
index 41bfd0ae00a..e884d50dc05 100644
--- a/source/blender/nodes/texture/nodes/node_texture_common.c
+++ b/source/blender/nodes/texture/nodes/node_texture_common.c
@@ -33,12 +33,17 @@
#include "DNA_node_types.h"
+#include "BLI_utildefines.h"
+
#include "BKE_node.h"
#include "node_texture_util.h"
+#include "NOD_common.h"
#include "node_common.h"
#include "node_exec.h"
+#include "RNA_access.h"
+
static void copy_stack(bNodeStack *to, bNodeStack *from)
{
if (to != from) {
@@ -53,7 +58,7 @@ static void copy_stack(bNodeStack *to, bNodeStack *from)
/**** GROUP ****/
-static void *group_initexec(bNode *node)
+static void *group_initexec(bNodeExecContext *context, bNode *node, bNodeInstanceKey key)
{
bNodeTree *ngroup= (bNodeTree*)node->id;
void *exec;
@@ -62,7 +67,7 @@ static void *group_initexec(bNode *node)
return NULL;
/* initialize the internal node tree execution */
- exec = ntreeTexBeginExecTree(ngroup, 0);
+ exec = ntreeTexBeginExecTree_internal(context, ngroup, key);
return exec;
}
@@ -71,43 +76,56 @@ static void group_freeexec(bNode *UNUSED(node), void *nodedata)
{
bNodeTreeExec*gexec= (bNodeTreeExec*)nodedata;
- ntreeTexEndExecTree(gexec, 0);
+ ntreeTexEndExecTree_internal(gexec);
}
/* Copy inputs to the internal stack.
* This is a shallow copy, no buffers are duplicated here!
*/
-static void group_copy_inputs(bNode *node, bNodeStack **in, bNodeStack *gstack)
+static void group_copy_inputs(bNode *gnode, bNodeStack **in, bNodeStack *gstack)
{
+ bNodeTree *ngroup = (bNodeTree*)gnode->id;
+ bNode *node;
bNodeSocket *sock;
bNodeStack *ns;
int a;
- for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) {
- if (sock->groupsock) {
- ns = node_get_socket_stack(gstack, sock->groupsock);
- copy_stack(ns, in[a]);
+
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP_INPUT) {
+ for (sock = node->outputs.first, a = 0; sock; sock = sock->next, ++a) {
+ ns = node_get_socket_stack(gstack, sock);
+ if (ns)
+ copy_stack(ns, in[a]);
+ }
}
}
}
/* Copy internal results to the external outputs.
*/
-static void group_copy_outputs(bNode *node, bNodeStack **out, bNodeStack *gstack)
+static void group_copy_outputs(bNode *gnode, bNodeStack **out, bNodeStack *gstack)
{
+ bNodeTree *ngroup = (bNodeTree*)gnode->id;
+ bNode *node;
bNodeSocket *sock;
bNodeStack *ns;
int a;
- for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) {
- if (sock->groupsock) {
- ns = node_get_socket_stack(gstack, sock->groupsock);
- copy_stack(out[a], ns);
+
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node->type == NODE_GROUP_OUTPUT && (node->flag & NODE_DO_OUTPUT)) {
+ for (sock = node->inputs.first, a = 0; sock; sock = sock->next, ++a) {
+ ns = node_get_socket_stack(gstack, sock);
+ if (ns)
+ copy_stack(out[a], ns);
+ }
+ break; /* only one active output node */
}
}
}
-static void group_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
+static void group_execute(void *data, int thread, struct bNode *node, bNodeExecData *execdata, struct bNodeStack **in, struct bNodeStack **out)
{
- bNodeTreeExec *exec= (bNodeTreeExec*)nodedata;
+ bNodeTreeExec *exec= execdata->data;
bNodeThreadStack *nts;
if (!exec)
@@ -131,20 +149,27 @@ static void group_execute(void *data, int thread, struct bNode *node, void *node
ntreeReleaseThreadStack(nts);
}
-void register_node_type_tex_group(bNodeTreeType *ttype)
+void register_node_type_tex_group(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS|NODE_CONST_OUTPUT);
+ /* NB: cannot use sh_node_type_base for node group, because it would map the node type
+ * to the shared NODE_GROUP integer type id.
+ */
+ node_type_base_custom(&ntype, "TextureNodeGroup", "Group", NODE_CLASS_GROUP, NODE_OPTIONS | NODE_CONST_OUTPUT);
+ ntype.type = NODE_GROUP;
+ ntype.poll = tex_node_poll_default;
+ ntype.update_internal_links = node_update_internal_links_default;
+ ntype.ext.srna = RNA_struct_find("TextureNodeGroup");
+ BLI_assert(ntype.ext.srna != NULL);
+ RNA_struct_blender_type_set(ntype.ext.srna, &ntype);
+
node_type_socket_templates(&ntype, NULL, NULL);
node_type_size(&ntype, 120, 60, 200);
node_type_label(&ntype, node_group_label);
- node_type_init(&ntype, node_group_init);
- node_type_valid(&ntype, node_group_valid);
- node_type_template(&ntype, node_group_template);
node_type_update(&ntype, NULL, node_group_verify);
- node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
- node_type_exec_new(&ntype, group_initexec, group_freeexec, group_execute);
+ strcpy(ntype.group_tree_idname, "TextureNodeTree");
+ node_type_exec(&ntype, group_initexec, group_freeexec, group_execute);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_compose.c b/source/blender/nodes/texture/nodes/node_texture_compose.c
index 25da4f19e52..065d16a5784 100644
--- a/source/blender/nodes/texture/nodes/node_texture_compose.c
+++ b/source/blender/nodes/texture/nodes/node_texture_compose.c
@@ -52,19 +52,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **
out[i] = tex_input_value(in[i], p, thread);
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_compose(bNodeTreeType *ttype)
+void register_node_type_tex_compose(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_COMPOSE, "Compose RGBA", NODE_CLASS_OP_COLOR, 0);
+ tex_node_type_base(&ntype, TEX_NODE_COMPOSE, "Combine RGBA", NODE_CLASS_OP_COLOR, 0);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 100, 60, 150);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_coord.c b/source/blender/nodes/texture/nodes/node_texture_coord.c
index 971520ebc38..b313e1f67ac 100644
--- a/source/blender/nodes/texture/nodes/node_texture_coord.c
+++ b/source/blender/nodes/texture/nodes/node_texture_coord.c
@@ -43,20 +43,20 @@ static void vectorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack *
copy_v3_v3(out, p->co);
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &vectorfn, data);
+ tex_output(node, execdata, in, out[0], &vectorfn, data);
}
-void register_node_type_tex_coord(bNodeTreeType *ttype)
+void register_node_type_tex_coord(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_COORD, "Coordinates", NODE_CLASS_INPUT, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_COORD, "Coordinates", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, outputs);
node_type_size(&ntype, 120, 110, 160);
node_type_storage(&ntype, "node_coord", NULL, NULL);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_curves.c b/source/blender/nodes/texture/nodes/node_texture_curves.c
index 5980f938938..1778eeaeffa 100644
--- a/source/blender/nodes/texture/nodes/node_texture_curves.c
+++ b/source/blender/nodes/texture/nodes/node_texture_curves.c
@@ -54,32 +54,31 @@ static void time_colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNU
out[0] = CLAMPIS(fac, 0.0f, 1.0f);
}
-static void time_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void time_exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &time_colorfn, data);
+ tex_output(node, execdata, in, out[0], &time_colorfn, data);
}
-static void time_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void time_init(bNodeTree *UNUSED(ntree), bNode *node)
{
node->custom1= 1;
node->custom2= 250;
node->storage= curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
}
-void register_node_type_tex_curve_time(bNodeTreeType *ttype)
+void register_node_type_tex_curve_time(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_CURVE_TIME, "Time", NODE_CLASS_INPUT, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_CURVE_TIME, "Time", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, time_outputs);
node_type_size(&ntype, 140, 100, 320);
node_type_init(&ntype, time_init);
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
- node_type_exec(&ntype, time_exec);
- node_type_exec_new(&ntype, node_initexec_curves, NULL, NULL); /* only for its initexec func */
+ node_type_exec(&ntype, node_initexec_curves, NULL, time_exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
/* **************** CURVE RGB ******************** */
@@ -102,27 +101,26 @@ static void rgb_colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in,
out[3] = cin[3];
}
-static void rgb_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void rgb_exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &rgb_colorfn, data);
+ tex_output(node, execdata, in, out[0], &rgb_colorfn, data);
}
-static void rgb_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void rgb_init(bNodeTree *UNUSED(ntree), bNode *node)
{
node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
}
-void register_node_type_tex_curve_rgb(bNodeTreeType *ttype)
+void register_node_type_tex_curve_rgb(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_CURVE_RGB, "RGB Curves", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, rgb_inputs, rgb_outputs);
node_type_size(&ntype, 200, 140, 320);
node_type_init(&ntype, rgb_init);
node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves);
- node_type_exec(&ntype, rgb_exec);
- node_type_exec_new(&ntype, node_initexec_curves, NULL, NULL); /* only for its initexec func */
+ node_type_exec(&ntype, node_initexec_curves, NULL, rgb_exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_decompose.c b/source/blender/nodes/texture/nodes/node_texture_decompose.c
index a2875c31d9e..1207377d150 100644
--- a/source/blender/nodes/texture/nodes/node_texture_decompose.c
+++ b/source/blender/nodes/texture/nodes/node_texture_decompose.c
@@ -70,22 +70,22 @@ static void valuefn_a(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack
*out = out[3];
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &valuefn_r, data);
- tex_output(node, in, out[1], &valuefn_g, data);
- tex_output(node, in, out[2], &valuefn_b, data);
- tex_output(node, in, out[3], &valuefn_a, data);
+ tex_output(node, execdata, in, out[0], &valuefn_r, data);
+ tex_output(node, execdata, in, out[1], &valuefn_g, data);
+ tex_output(node, execdata, in, out[2], &valuefn_b, data);
+ tex_output(node, execdata, in, out[3], &valuefn_a, data);
}
-void register_node_type_tex_decompose(bNodeTreeType *ttype)
+void register_node_type_tex_decompose(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_DECOMPOSE, "Decompose RGBA", NODE_CLASS_OP_COLOR, 0);
+ tex_node_type_base(&ntype, TEX_NODE_DECOMPOSE, "Separate RGBA", NODE_CLASS_OP_COLOR, 0);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 100, 60, 150);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_distance.c b/source/blender/nodes/texture/nodes/node_texture_distance.c
index 8c3b1555d5d..f47f9260337 100644
--- a/source/blender/nodes/texture/nodes/node_texture_distance.c
+++ b/source/blender/nodes/texture/nodes/node_texture_distance.c
@@ -56,20 +56,20 @@ static void valuefn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **
*out = len_v3v3(co2, co1);
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &valuefn, data);
+ tex_output(node, execdata, in, out[0], &valuefn, data);
}
-void register_node_type_tex_distance(bNodeTreeType *ttype)
+void register_node_type_tex_distance(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_DISTANCE, "Distance", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_DISTANCE, "Distance", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 120, 110, 160);
node_type_storage(&ntype, "node_distance", NULL, NULL);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_hueSatVal.c b/source/blender/nodes/texture/nodes/node_texture_hueSatVal.c
index b5e9969a830..56da4ad24c0 100644
--- a/source/blender/nodes/texture/nodes/node_texture_hueSatVal.c
+++ b/source/blender/nodes/texture/nodes/node_texture_hueSatVal.c
@@ -87,19 +87,19 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
out[3] = col[3];
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_hue_sat(bNodeTreeType *ttype)
+void register_node_type_tex_hue_sat(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 150, 80, 250);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_image.c b/source/blender/nodes/texture/nodes/node_texture_image.c
index 2ef1669a266..57fa562ac0b 100644
--- a/source/blender/nodes/texture/nodes/node_texture_image.c
+++ b/source/blender/nodes/texture/nodes/node_texture_image.c
@@ -83,12 +83,12 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNUSED(i
}
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
{
ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
node->storage= iuser;
@@ -97,16 +97,16 @@ static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(nt
iuser->ok= 1;
}
-void register_node_type_tex_image(bNodeTreeType *ttype)
+void register_node_type_tex_image(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, NULL, outputs);
node_type_size(&ntype, 120, 80, 300);
node_type_init(&ntype, init);
node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_invert.c b/source/blender/nodes/texture/nodes/node_texture_invert.c
index 9c2963d2dc2..fd6e2144e0e 100644
--- a/source/blender/nodes/texture/nodes/node_texture_invert.c
+++ b/source/blender/nodes/texture/nodes/node_texture_invert.c
@@ -58,19 +58,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **
out[3] = col[3];
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_invert(bNodeTreeType *ttype)
+void register_node_type_tex_invert(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 90, 80, 100);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_math.c b/source/blender/nodes/texture/nodes/node_texture_math.c
index 95d70ccc7d6..499412e750d 100644
--- a/source/blender/nodes/texture/nodes/node_texture_math.c
+++ b/source/blender/nodes/texture/nodes/node_texture_math.c
@@ -181,21 +181,21 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
}
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &valuefn, data);
+ tex_output(node, execdata, in, out[0], &valuefn, data);
}
-void register_node_type_tex_math(bNodeTreeType *ttype)
+void register_node_type_tex_math(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 120, 110, 160);
node_type_label(&ntype, node_math_label);
node_type_storage(&ntype, "node_math", NULL, NULL);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_mixRgb.c b/source/blender/nodes/texture/nodes/node_texture_mixRgb.c
index fe04854c734..12ac27f26b7 100644
--- a/source/blender/nodes/texture/nodes/node_texture_mixRgb.c
+++ b/source/blender/nodes/texture/nodes/node_texture_mixRgb.c
@@ -59,20 +59,20 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
ramp_blend(node->custom1, out, fac, col2);
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_mix_rgb(bNodeTreeType *ttype)
+void register_node_type_tex_mix_rgb(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 100, 60, 150);
node_type_label(&ntype, node_blend_label);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_output.c b/source/blender/nodes/texture/nodes/node_texture_output.c
index 2f5efe8c45e..f4086ed1eec 100644
--- a/source/blender/nodes/texture/nodes/node_texture_output.c
+++ b/source/blender/nodes/texture/nodes/node_texture_output.c
@@ -41,7 +41,7 @@ static bNodeSocketTemplate inputs[] = {
};
/* applies to render pipeline */
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **UNUSED(out))
{
TexCallData *cdata = (TexCallData *)data;
TexResult *target = cdata->target;
@@ -54,7 +54,7 @@ static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(o
tex_input_rgba(&target->tr, in[1], &params, cdata->thread);
else
tex_input_rgba(&target->tr, in[0], &params, cdata->thread);
- tex_do_preview(node, params.co, &target->tr);
+ tex_do_preview(execdata->preview, params.co, &target->tr);
}
else {
/* 0 means don't care, so just use first */
@@ -141,7 +141,7 @@ static void assign_index(struct bNode *node)
node->custom1 = index;
}
-static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
{
TexNodeOutput *tno = MEM_callocN(sizeof(TexNodeOutput), "TEX_output");
node->storage= tno;
@@ -151,26 +151,26 @@ static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(nt
assign_index(node);
}
-static void copy(bNode *orig, bNode *new)
+static void copy(bNodeTree *dest_ntree, bNode *dest_node, bNode *src_node)
{
- node_copy_standard_storage(orig, new);
- unique_name(new);
- assign_index(new);
+ node_copy_standard_storage(dest_ntree, dest_node, src_node);
+ unique_name(dest_node);
+ assign_index(dest_node);
}
-void register_node_type_tex_output(bNodeTreeType *ttype)
+void register_node_type_tex_output(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_OUTPUT, "Output", NODE_CLASS_OUTPUT, NODE_PREVIEW|NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_OUTPUT, "Output", NODE_CLASS_OUTPUT, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, NULL);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, init);
node_type_storage(&ntype, "TexNodeOutput", node_free_standard_storage, copy);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
/* Do not allow muting output. */
node_type_internal_links(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_proc.c b/source/blender/nodes/texture/nodes/node_texture_proc.c
index 8876d98b9b2..f7e7a585ae2 100644
--- a/source/blender/nodes/texture/nodes/node_texture_proc.c
+++ b/source/blender/nodes/texture/nodes/node_texture_proc.c
@@ -69,7 +69,7 @@ static void do_proc(float *result, TexParams *p, const float col1[4], const floa
texres.nor = NULL;
textype = multitex_nodes(tex, p->co, p->dxt, p->dyt, p->osatex,
- &texres, thread, 0, p->shi, p->mtex);
+ &texres, thread, 0, p->shi, p->mtex, NULL);
if (is_normal)
return;
@@ -129,11 +129,11 @@ static int count_outputs(bNode *node)
{ \
texfn(result, p, node, in, 1, &name##_map_inputs, thread); \
} \
- static void name##_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) \
+ static void name##_exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out) \
{ \
int outs = count_outputs(node); \
- if (outs >= 1) tex_output(node, in, out[0], &name##_colorfn, data); \
- if (outs >= 2) tex_output(node, in, out[1], &name##_normalfn, data); \
+ if (outs >= 1) tex_output(node, execdata, in, out[0], &name##_colorfn, data); \
+ if (outs >= 2) tex_output(node, execdata, in, out[1], &name##_normalfn, data); \
}
@@ -281,7 +281,7 @@ ProcDef(stucci)
/* --- */
-static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
{
Tex *tex = MEM_callocN(sizeof(Tex), "Tex");
node->storage= tex;
@@ -296,18 +296,18 @@ static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(nt
/* Node type definitions */
#define TexDef(TEXTYPE, outputs, name, Name) \
-void register_node_type_tex_proc_##name(bNodeTreeType *ttype) \
+void register_node_type_tex_proc_##name(void) \
{ \
static bNodeType ntype; \
\
- node_type_base(ttype, &ntype, TEX_NODE_PROC+TEXTYPE, Name, NODE_CLASS_TEXTURE, NODE_PREVIEW|NODE_OPTIONS); \
+ tex_node_type_base(&ntype, TEX_NODE_PROC+TEXTYPE, Name, NODE_CLASS_TEXTURE, NODE_PREVIEW | NODE_OPTIONS); \
node_type_socket_templates(&ntype, name##_inputs, outputs); \
node_type_size(&ntype, 140, 80, 140); \
node_type_init(&ntype, init); \
node_type_storage(&ntype, "Tex", node_free_standard_storage, node_copy_standard_storage); \
- node_type_exec(&ntype, name##_exec); \
+ node_type_exec(&ntype, NULL, NULL, name##_exec); \
\
- nodeRegisterType(ttype, &ntype); \
+ nodeRegisterType(&ntype); \
}
#define C outputs_color_only
diff --git a/source/blender/nodes/texture/nodes/node_texture_rotate.c b/source/blender/nodes/texture/nodes/node_texture_rotate.c
index 1b1d57044a3..02a5a9e1a97 100644
--- a/source/blender/nodes/texture/nodes/node_texture_rotate.c
+++ b/source/blender/nodes/texture/nodes/node_texture_rotate.c
@@ -90,19 +90,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **
tex_input_rgba(out, in[0], &np, thread);
}
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_rotate(bNodeTreeType *ttype)
+void register_node_type_tex_rotate(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_ROTATE, "Rotate", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_ROTATE, "Rotate", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 140, 100, 320);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_scale.c b/source/blender/nodes/texture/nodes/node_texture_scale.c
index 56562724fb9..8eabdabc713 100644
--- a/source/blender/nodes/texture/nodes/node_texture_scale.c
+++ b/source/blender/nodes/texture/nodes/node_texture_scale.c
@@ -63,19 +63,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **
tex_input_rgba(out, in[0], &np, thread);
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_scale(bNodeTreeType *ttype)
+void register_node_type_tex_scale(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_SCALE, "Scale", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_SCALE, "Scale", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 90, 80, 100);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_texture.c b/source/blender/nodes/texture/nodes/node_texture_texture.c
index cc7367a7632..a42633cb2b4 100644
--- a/source/blender/nodes/texture/nodes/node_texture_texture.c
+++ b/source/blender/nodes/texture/nodes/node_texture_texture.c
@@ -78,7 +78,7 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
texres.nor = nor;
textype = multitex_nodes(nodetex, co, dxt, dyt, p->osatex,
- &texres, thread, 0, p->shi, p->mtex);
+ &texres, thread, 0, p->shi, p->mtex, NULL);
if (textype & TEX_RGB) {
copy_v4_v4(out, &texres.tr);
@@ -90,19 +90,19 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
}
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_texture(bNodeTreeType *ttype)
+void register_node_type_tex_texture(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 120, 80, 240);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_translate.c b/source/blender/nodes/texture/nodes/node_texture_translate.c
index a95cb00a47d..55782fbecac 100644
--- a/source/blender/nodes/texture/nodes/node_texture_translate.c
+++ b/source/blender/nodes/texture/nodes/node_texture_translate.c
@@ -59,19 +59,19 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **
tex_input_rgba(out, in[0], &np, thread);
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &colorfn, data);
+ tex_output(node, execdata, in, out[0], &colorfn, data);
}
-void register_node_type_tex_translate(bNodeTreeType *ttype)
+void register_node_type_tex_translate(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_TRANSLATE, "Translate", NODE_CLASS_DISTORT, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_TRANSLATE, "Translate", NODE_CLASS_DISTORT, NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 90, 80, 100);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_valToNor.c b/source/blender/nodes/texture/nodes/node_texture_valToNor.c
index bbfc1fa616b..6be61c914db 100644
--- a/source/blender/nodes/texture/nodes/node_texture_valToNor.c
+++ b/source/blender/nodes/texture/nodes/node_texture_valToNor.c
@@ -75,19 +75,19 @@ static void normalfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack *
out[1] = val-nor[1];
out[2] = val-nor[2];
}
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &normalfn, data);
+ tex_output(node, execdata, in, out[0], &normalfn, data);
}
-void register_node_type_tex_valtonor(bNodeTreeType *ttype)
+void register_node_type_tex_valtonor(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_VALTONOR, "Value to Normal", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_VALTONOR, "Value to Normal", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 90, 80, 100);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_valToRgb.c b/source/blender/nodes/texture/nodes/node_texture_valToRgb.c
index 78635453fc1..871cdab384e 100644
--- a/source/blender/nodes/texture/nodes/node_texture_valToRgb.c
+++ b/source/blender/nodes/texture/nodes/node_texture_valToRgb.c
@@ -52,28 +52,28 @@ static void valtorgb_colorfn(float *out, TexParams *p, bNode *node, bNodeStack *
}
}
-static void valtorgb_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void valtorgb_exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &valtorgb_colorfn, data);
+ tex_output(node, execdata, in, out[0], &valtorgb_colorfn, data);
}
-static void valtorgb_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+static void valtorgb_init(bNodeTree *UNUSED(ntree), bNode *node)
{
- node->storage = add_colorband(1);
+ node->storage = add_colorband(true);
}
-void register_node_type_tex_valtorgb(bNodeTreeType *ttype)
+void register_node_type_tex_valtorgb(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
+ tex_node_type_base(&ntype, TEX_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, NODE_OPTIONS);
node_type_socket_templates(&ntype, valtorgb_in, valtorgb_out);
node_type_size(&ntype, 240, 200, 300);
node_type_init(&ntype, valtorgb_init);
node_type_storage(&ntype, "ColorBand", node_free_standard_storage, node_copy_standard_storage);
- node_type_exec(&ntype, valtorgb_exec);
+ node_type_exec(&ntype, NULL, NULL, valtorgb_exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
/* **************** RGBTOBW ******************** */
@@ -94,19 +94,19 @@ static void rgbtobw_valuefn(float *out, TexParams *p, bNode *UNUSED(node), bNode
*out = rgb_to_bw(cin);
}
-static void rgbtobw_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void rgbtobw_exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
{
- tex_output(node, in, out[0], &rgbtobw_valuefn, data);
+ tex_output(node, execdata, in, out[0], &rgbtobw_valuefn, data);
}
-void register_node_type_tex_rgbtobw(bNodeTreeType *ttype)
+void register_node_type_tex_rgbtobw(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0);
+ tex_node_type_base(&ntype, TEX_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, rgbtobw_in, rgbtobw_out);
node_type_size(&ntype, 80, 40, 120);
- node_type_exec(&ntype, rgbtobw_exec);
+ node_type_exec(&ntype, NULL, NULL, rgbtobw_exec);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/texture/nodes/node_texture_viewer.c b/source/blender/nodes/texture/nodes/node_texture_viewer.c
index 5cb8d8c438c..4f7d54ab833 100644
--- a/source/blender/nodes/texture/nodes/node_texture_viewer.c
+++ b/source/blender/nodes/texture/nodes/node_texture_viewer.c
@@ -42,7 +42,7 @@ static bNodeSocketTemplate outputs[] = {
{ -1, 0, "" }
};
-static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
+static void exec(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *execdata, bNodeStack **in, bNodeStack **UNUSED(out))
{
TexCallData *cdata = (TexCallData *)data;
@@ -52,21 +52,21 @@ static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(o
params_from_cdata(&params, cdata);
tex_input_rgba(col, in[0], &params, cdata->thread);
- tex_do_preview(node, params.previewco, col);
+ tex_do_preview(execdata->preview, params.previewco, col);
}
}
-void register_node_type_tex_viewer(bNodeTreeType *ttype)
+void register_node_type_tex_viewer(void)
{
static bNodeType ntype;
- node_type_base(ttype, &ntype, TEX_NODE_VIEWER, "Viewer", NODE_CLASS_OUTPUT, NODE_PREVIEW);
+ tex_node_type_base(&ntype, TEX_NODE_VIEWER, "Viewer", NODE_CLASS_OUTPUT, NODE_PREVIEW);
node_type_socket_templates(&ntype, inputs, outputs);
node_type_size(&ntype, 100, 60, 150);
- node_type_exec(&ntype, exec);
+ node_type_exec(&ntype, NULL, NULL, exec);
/* Do not allow muting viewer node. */
node_type_internal_links(&ntype, NULL);
- nodeRegisterType(ttype, &ntype);
+ nodeRegisterType(&ntype);
}
diff --git a/source/blender/opencl/SConscript b/source/blender/opencl/SConscript
deleted file mode 100644
index e91a99d5075..00000000000
--- a/source/blender/opencl/SConscript
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/python
-Import ('env')
-
-sources = env.Glob('intern/*.c')
-
-incs = '.'
-
-env.BlenderLib ( 'bf_opencl', sources, Split(incs), libtype=['core','player'], priority = [192,192] )
diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h
index 9bd45d2b759..0f5be095e0f 100644
--- a/source/blender/python/BPY_extern.h
+++ b/source/blender/python/BPY_extern.h
@@ -66,7 +66,7 @@ void BPY_python_end(void);
/* 2.5 UI Scripts */
int BPY_filepath_exec(struct bContext *C, const char *filepath, struct ReportList *reports);
-int BPY_text_exec(struct bContext *C, struct Text *text, struct ReportList *reports, const short do_jump);
+int BPY_text_exec(struct bContext *C, struct Text *text, struct ReportList *reports, const bool do_jump);
void BPY_text_free_code(struct Text *text);
void BPY_modules_update(struct bContext *C); // XXX - annoying, need this for pointers that get out of date
void BPY_modules_load_user(struct bContext *C);
@@ -87,6 +87,11 @@ void BPY_context_update(struct bContext *C);
void BPY_id_release(struct ID *id);
+/* I18n for addons */
+#ifdef WITH_INTERNATIONAL
+const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid);
+#endif
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript
index 012bc279cfb..4fb6d771c5b 100644
--- a/source/blender/python/SConscript
+++ b/source/blender/python/SConscript
@@ -1,4 +1,29 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
# TODO, split into 3 files.
@@ -46,16 +71,107 @@ if env['WITH_BF_PYTHON_SAFETY']:
if env['BF_BUILDINFO']:
defs.append('BUILD_DATE')
-if env['WITH_BF_INTERNATIONAL']:
- defs.append('WITH_INTERNATIONAL')
-if env['WITH_BF_CYCLES']:
- defs.append('WITH_CYCLES')
+# Audaspace is always on currently
+
+if env['WITH_BF_BULLET']:
+ defs.append('WITH_BULLET')
+
+# AVI is always on currently
if env['WITH_BF_FFMPEG']:
defs.append('WITH_FFMPEG')
incs += ' ' + env['BF_FFMPEG_INC']
-
+
+if env['WITH_BF_QUICKTIME']:
+ defs.append('WITH_QUICKTIME')
+
+if env['WITH_BF_SNDFILE']:
+ defs.append('WITH_SNDFILE')
+
+if env['WITH_BF_COMPOSITOR']:
+ defs.append('WITH_COMPOSITOR')
+
+if env['WITH_BF_CYCLES']:
+ defs.append('WITH_CYCLES')
+
+if env['WITH_BF_CYCLES_OSL']:
+ defs.append('WITH_CYCLES_OSL')
+
+if env['WITH_BF_FREESTYLE']:
+ incs += ' ../freestyle/intern/python'
+ defs.append('WITH_FREESTYLE')
+
+if env['WITH_BF_GAMEENGINE']:
+ defs.append('WITH_GAMEENGINE')
+
+if env['WITH_BF_CINEON']:
+ defs.append('WITH_CINEON')
+
+if env['WITH_BF_DDS']:
+ defs.append('WITH_DDS')
+
+if env['WITH_BF_FRAMESERVER']:
+ defs.append('WITH_FRAMESERVER')
+
+if env['WITH_BF_HDR']:
+ defs.append('WITH_HDR')
+
+if env['WITH_BF_OPENEXR']:
+ defs.append('WITH_OPENEXR')
+
+if env['WITH_BF_OPENJPEG']:
+ defs.append('WITH_OPENJPEG')
+
+if env['WITH_BF_REDCODE']:
+ defs.append('WITH_REDCODE')
+
+if env['WITH_BF_TIFF']:
+ defs.append('WITH_TIFF')
+
+# NDof is always on currently
+
+if env['WITH_BF_INTERNATIONAL']:
+ defs.append('WITH_INTERNATIONAL')
+
+if env['WITH_BF_OPENAL']:
+ defs.append('WITH_OPENAL')
+
+if env['WITH_BF_SDL']:
+ defs.append('WITH_SDL')
+
+if env['WITH_BF_JACK']:
+ defs.append('WITH_JACK')
+
+if env['WITH_BF_LIBMV']:
+ defs.append('WITH_LIBMV')
+
+if env['WITH_BF_BOOLEAN']:
+ defs.append('WITH_MOD_BOOLEAN')
+
+if env['WITH_BF_FLUID']:
+ defs.append('WITH_MOD_FLUID')
+
+if env['WITH_BF_OCEANSIM']:
+ defs.append('WITH_OCEANSIM')
+
+if env['WITH_BF_REMESH']:
+ defs.append('WITH_MOD_REMESH')
+
+if env['WITH_BF_SMOKE']:
+ defs.append('WITH_SMOKE')
+
+if env['WITH_BF_COLLADA']:
+ defs.append('WITH_COLLADA')
+
+if env['WITH_BF_OIIO']:
+ defs.append('WITH_OCIO')
+
+if env['WITH_BF_PLAYER']:
+ defs.append('WITH_PLAYER')
+
+
+
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-mingw', 'linuxcross', 'win64-vc'):
incs += ' ' + env['BF_PTHREADS_INC']
diff --git a/source/blender/python/bmesh/CMakeLists.txt b/source/blender/python/bmesh/CMakeLists.txt
index ccabe572ce5..b15923a87d2 100644
--- a/source/blender/python/bmesh/CMakeLists.txt
+++ b/source/blender/python/bmesh/CMakeLists.txt
@@ -51,4 +51,8 @@ set(SRC
bmesh_py_utils.h
)
+if(WITH_FREESTYLE)
+ add_definitions(-DWITH_FREESTYLE)
+endif()
+
blender_add_lib(bf_python_bmesh "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/python/bmesh/bmesh_py_api.c b/source/blender/python/bmesh/bmesh_py_api.c
index 18f5d895132..47e6baf8e93 100644
--- a/source/blender/python/bmesh/bmesh_py_api.c
+++ b/source/blender/python/bmesh/bmesh_py_api.c
@@ -98,7 +98,7 @@ static PyObject *bpy_bm_from_edit_mesh(PyObject *UNUSED(self), PyObject *value)
}
PyDoc_STRVAR(bpy_bm_update_edit_mesh_doc,
-".. method:: update_edit_mesh(mesh, tessface=True)\n"
+".. method:: update_edit_mesh(mesh, tessface=True, destructive=True)\n"
"\n"
" Update the mesh after changes to the BMesh in editmode, \n"
" optionally recalculating n-gon tessellation.\n"
@@ -107,14 +107,20 @@ 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"
+" :type destructive: boolean\n"
);
-static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args)
+static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
{
+ static const char *kwlist[] = {"mesh", "tessface", "destructive", NULL};
PyObject *py_me;
Mesh *me;
- int do_tessface = TRUE;
+ int do_tessface = true;
+ int is_destructive = true;
- if (!PyArg_ParseTuple(args, "O|i:update_edit_mesh", &py_me, &do_tessface)) {
+ if (!PyArg_ParseTupleAndKeywords(args, kw, "O|ii:update_edit_mesh", (char **)kwlist,
+ &py_me, &do_tessface, &is_destructive))
+ {
return NULL;
}
@@ -131,13 +137,8 @@ static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args)
}
{
- /* XXX, not great - infact this function could just not use the context at all
- * postpone that change until after release: BMESH_TODO - campbell */
- extern struct bContext *BPy_GetContext(void);
- extern void EDBM_update_generic(struct bContext *C, BMEditMesh *em, const short do_tessface);
-
- struct bContext *C = BPy_GetContext();
- EDBM_update_generic(C, me->edit_btmesh, do_tessface);
+ extern void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_destructive);
+ EDBM_update_generic(me->edit_btmesh, do_tessface, is_destructive);
}
Py_RETURN_NONE;
@@ -146,7 +147,7 @@ static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args)
static struct PyMethodDef BPy_BM_methods[] = {
{"new", (PyCFunction)bpy_bm_new, METH_NOARGS, bpy_bm_new_doc},
{"from_edit_mesh", (PyCFunction)bpy_bm_from_edit_mesh, METH_O, bpy_bm_from_edit_mesh_doc},
- {"update_edit_mesh", (PyCFunction)bpy_bm_update_edit_mesh, METH_VARARGS, bpy_bm_update_edit_mesh_doc},
+ {"update_edit_mesh", (PyCFunction)bpy_bm_update_edit_mesh, METH_VARARGS | METH_KEYWORDS, bpy_bm_update_edit_mesh_doc},
{NULL, NULL, 0, NULL}
};
diff --git a/source/blender/python/bmesh/bmesh_py_ops.c b/source/blender/python/bmesh/bmesh_py_ops.c
index 0a2091af5df..cc87d34d769 100644
--- a/source/blender/python/bmesh/bmesh_py_ops.c
+++ b/source/blender/python/bmesh/bmesh_py_ops.c
@@ -159,7 +159,7 @@ static PyObject *bpy_bmesh_ops_fakemod_getattro(PyObject *UNUSED(self), PyObject
const char *opname = _PyUnicode_AsString(pyname);
for (i = 0; i < tot; i++) {
- if (strcmp(bmo_opdefines[i]->opname, opname) == 0) {
+ if (STREQ(bmo_opdefines[i]->opname, opname)) {
return bpy_bmesh_op_CreatePyObject(opname);
}
}
diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c
index ded35363287..4d728b76707 100644
--- a/source/blender/python/bmesh/bmesh_py_ops_call.c
+++ b/source/blender/python/bmesh/bmesh_py_ops_call.c
@@ -48,11 +48,13 @@
static int bpy_bm_op_as_py_error(BMesh *bm)
{
if (BMO_error_occurred(bm)) {
+ /* note: we could have multiple errors */
const char *errmsg;
if (BMO_error_get(bm, &errmsg, NULL)) {
PyErr_Format(PyExc_RuntimeError,
"bmesh operator: %.200s",
errmsg);
+ BMO_error_clear(bm);
return -1;
}
}
@@ -214,7 +216,7 @@ static int bpy_slot_from_py(BMesh *bm, BMOperator *bmop, BMOpSlot *slot, PyObjec
return -1;
}
else if (((size = ((MatrixObject *)value)->num_col) != ((MatrixObject *)value)->num_row) ||
- (ELEM(size, 3, 4) == FALSE))
+ (ELEM(size, 3, 4) == false))
{
PyErr_Format(PyExc_TypeError,
"%.200s: keyword \"%.200s\" expected a 3x3 or 4x4 matrix Matrix",
@@ -319,7 +321,7 @@ static int bpy_slot_from_py(BMesh *bm, BMOperator *bmop, BMOpSlot *slot, PyObjec
elem_array = BPy_BMElem_PySeq_As_Array(&bm, value, 0, PY_SSIZE_T_MAX,
&elem_array_len, (slot->slot_subtype.elem & BM_ALL_NOLOOP),
- TRUE, TRUE, slot_name);
+ true, true, slot_name);
/* error is set above */
if (elem_array == NULL) {
@@ -523,7 +525,7 @@ static int bpy_slot_from_py(BMesh *bm, BMOperator *bmop, BMOpSlot *slot, PyObjec
*
* \note Don't throw any exceptions and should always return a valid (PyObject *).
*/
-static PyObject* bpy_slot_to_py(BMesh *bm, BMOpSlot *slot)
+static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot)
{
PyObject *item = NULL;
@@ -692,6 +694,9 @@ PyObject *BPy_BMO_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw)
{
BPY_BM_CHECK_OBJ(py_bm);
bm = py_bm->bm;
+
+ /* could complain about entering with exceptions... */
+ BMO_error_clear(bm);
}
else {
PyErr_SetString(PyExc_TypeError,
@@ -722,7 +727,7 @@ PyObject *BPy_BMO_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw)
return NULL;
}
- slot = BMO_slot_get(bmop.slots_in, slot_name);
+ slot = BMO_slot_get(bmop.slots_in, slot_name);
/* now assign the value */
if (bpy_slot_from_py(bm, &bmop, slot, value,
diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
index 5db9962e690..052496e3ed7 100644
--- a/source/blender/python/bmesh/bmesh_py_types.c
+++ b/source/blender/python/bmesh/bmesh_py_types.c
@@ -50,6 +50,8 @@
#include "bmesh_py_types_customdata.h"
#include "bmesh_py_types_meshdata.h"
+static void bm_dealloc_editmode_warn(BPy_BMesh *self);
+
/* Common Flags
* ************ */
@@ -77,11 +79,11 @@ PyC_FlagSet bpy_bm_htype_all_flags[] = {
};
PyC_FlagSet bpy_bm_hflag_all_flags[] = {
- {BM_ELEM_SELECT, "SELECT"},
- {BM_ELEM_HIDDEN, "HIDE"},
- {BM_ELEM_SEAM, "SEAM"},
- {BM_ELEM_SMOOTH, "SMOOTH"},
- {BM_ELEM_TAG, "TAG"},
+ {BM_ELEM_SELECT, "SELECT"},
+ {BM_ELEM_HIDDEN, "HIDE"},
+ {BM_ELEM_SEAM, "SEAM"},
+ {BM_ELEM_SMOOTH, "SMOOTH"},
+ {BM_ELEM_TAG, "TAG"},
{0, NULL}
};
@@ -101,7 +103,6 @@ PyDoc_STRVAR(bpy_bm_elem_tag_doc, "Generic attribute scripts can use for own
PyDoc_STRVAR(bpy_bm_elem_smooth_doc, "Smooth state of this element.\n\n:type: boolean");
PyDoc_STRVAR(bpy_bm_elem_seam_doc, "Seam for UV unwrapping.\n\n:type: boolean");
-
static PyObject *bpy_bm_elem_hflag_get(BPy_BMElem *self, void *flag)
{
const char hflag = (char)GET_INT_FROM_POINTER(flag);
@@ -120,11 +121,11 @@ static int bpy_bm_elem_hflag_set(BPy_BMElem *self, PyObject *value, void *flag)
param = PyLong_AsLong(value);
- if (param == TRUE) {
+ if (param == true) {
BM_elem_flag_enable(self->ele, hflag);
return 0;
}
- else if (param == FALSE) {
+ else if (param == false) {
BM_elem_flag_disable(self->ele, hflag);
return 0;
}
@@ -412,6 +413,14 @@ static PyObject *bpy_bmedge_is_manifold_get(BPy_BMEdge *self)
return PyBool_FromLong(BM_edge_is_manifold(self->e));
}
+PyDoc_STRVAR(bpy_bmedge_is_contiguous_doc,
+"True when this edge is manifold, between two faces with the same winding (read-only).\n\n:type: boolean"
+);
+static PyObject *bpy_bmedge_is_contiguous_get(BPy_BMEdge *self)
+{
+ BPY_BM_CHECK_OBJ(self);
+ return PyBool_FromLong(BM_edge_is_contiguous(self->e));
+}
PyDoc_STRVAR(bpy_bmedge_is_wire_doc,
"True when this edge is not connected to any faces (read-only).\n\n:type: boolean"
@@ -432,6 +441,47 @@ static PyObject *bpy_bmedge_is_boundary_get(BPy_BMEdge *self)
return PyBool_FromLong(BM_edge_is_boundary(self->e));
}
+#ifdef WITH_FREESTYLE
+PyDoc_STRVAR(bpy_bmedge_freestyle_edge_mark_doc,
+"Freestyle edge mark.\n\n:type: boolean"
+);
+static PyObject *bpy_bmedge_freestyle_edge_mark_get(BPy_BMEdge *self)
+{
+ FreestyleEdge *fed;
+
+ BPY_BM_CHECK_OBJ(self);
+ fed = CustomData_bmesh_get(&self->bm->edata, self->e->head.data, CD_FREESTYLE_EDGE);
+ return PyBool_FromLong(fed->flag & FREESTYLE_EDGE_MARK);
+}
+
+static int bpy_bmedge_freestyle_edge_mark_set(BPy_BMEdge *self, PyObject *value)
+{
+ int param;
+ FreestyleEdge *fed;
+
+ BPY_BM_CHECK_INT(self);
+
+ param = PyLong_AsLong(value);
+ if (param != false && param != true) {
+ PyErr_SetString(PyExc_TypeError,
+ "expected a boolean type 0/1");
+ return -1;
+ }
+
+ if (!CustomData_has_layer(&self->bm->edata, CD_FREESTYLE_EDGE)) {
+ BM_data_layer_add(self->bm, &self->bm->edata, CD_FREESTYLE_EDGE);
+ }
+
+ fed = CustomData_bmesh_get(&self->bm->edata, self->e->head.data, CD_FREESTYLE_EDGE);
+ if (param)
+ fed->flag &= ~FREESTYLE_EDGE_MARK;
+ else
+ fed->flag |= FREESTYLE_EDGE_MARK;
+
+ return 0;
+}
+#endif
+
/* Face
* ^^^^ */
@@ -491,6 +541,48 @@ static int bpy_bmface_material_index_set(BPy_BMFace *self, PyObject *value)
}
}
+#ifdef WITH_FREESTYLE
+PyDoc_STRVAR(bpy_bmface_freestyle_face_mark_doc,
+"Freestyle face mark.\n\n:type: boolean"
+);
+static PyObject *bpy_bmface_freestyle_face_mark_get(BPy_BMFace *self)
+{
+ FreestyleFace *ffa;
+
+ BPY_BM_CHECK_OBJ(self);
+ ffa = CustomData_bmesh_get(&self->bm->pdata, self->f->head.data, CD_FREESTYLE_FACE);
+ return PyBool_FromLong(ffa->flag & FREESTYLE_FACE_MARK);
+}
+
+static int bpy_bmface_freestyle_face_mark_set(BPy_BMFace *self, PyObject *value)
+{
+ int param;
+ FreestyleFace *ffa;
+
+ BPY_BM_CHECK_INT(self);
+
+ param = PyLong_AsLong(value);
+ if (param != false && param != true) {
+ PyErr_SetString(PyExc_TypeError,
+ "expected a boolean type 0/1");
+ return -1;
+ }
+
+ if (!CustomData_has_layer(&self->bm->pdata, CD_FREESTYLE_FACE)) {
+ BM_data_layer_add(self->bm, &self->bm->pdata, CD_FREESTYLE_FACE);
+ }
+
+ ffa = CustomData_bmesh_get(&self->bm->pdata, self->f->head.data, CD_FREESTYLE_FACE);
+ if (param)
+ ffa->flag &= ~FREESTYLE_FACE_MARK;
+ else
+ ffa->flag |= FREESTYLE_FACE_MARK;
+
+ return 0;
+}
+#endif
+
+
/* Loop
* ^^^^ */
@@ -559,6 +651,15 @@ static PyObject *bpy_bmloop_link_loop_radial_prev_get(BPy_BMLoop *self)
return BPy_BMLoop_CreatePyObject(self->bm, self->l->radial_prev);
}
+PyDoc_STRVAR(bpy_bm_is_convex_doc,
+"True when this loop is at the convex corner of a face, depends on a valid face normal (read-only).\n\n:type: :class:`BMLoop`"
+);
+static PyObject *bpy_bm_is_convex_get(BPy_BMLoop *self)
+{
+ BPY_BM_CHECK_OBJ(self);
+ return PyBool_FromLong(BM_loop_is_convex(self->l));
+}
+
/* ElemSeq
* ^^^^^^^ */
@@ -662,6 +763,10 @@ static PyGetSetDef bpy_bmedge_getseters[] = {
{(char *)"smooth", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_smooth_doc, (void *)BM_ELEM_SMOOTH},
{(char *)"seam", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_seam_doc, (void *)BM_ELEM_SEAM},
+#ifdef WITH_FREESTYLE
+ {(char *)"freestyle_edge_mark", (getter)bpy_bmedge_freestyle_edge_mark_get, (setter)bpy_bmedge_freestyle_edge_mark_set, (char *)bpy_bmedge_freestyle_edge_mark_doc, NULL},
+#endif
+
/* connectivity data */
{(char *)"verts", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmedge_verts_doc, (void *)BM_VERTS_OF_EDGE},
@@ -669,10 +774,11 @@ static PyGetSetDef bpy_bmedge_getseters[] = {
{(char *)"link_loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmedge_link_loops_doc, (void *)BM_LOOPS_OF_EDGE},
/* readonly checks */
- {(char *)"is_manifold", (getter)bpy_bmedge_is_manifold_get, (setter)NULL, (char *)bpy_bmedge_is_manifold_doc, NULL},
- {(char *)"is_wire", (getter)bpy_bmedge_is_wire_get, (setter)NULL, (char *)bpy_bmedge_is_wire_doc, NULL},
+ {(char *)"is_manifold", (getter)bpy_bmedge_is_manifold_get, (setter)NULL, (char *)bpy_bmedge_is_manifold_doc, NULL},
+ {(char *)"is_contiguous", (getter)bpy_bmedge_is_contiguous_get, (setter)NULL, (char *)bpy_bmedge_is_contiguous_doc, NULL},
+ {(char *)"is_wire", (getter)bpy_bmedge_is_wire_get, (setter)NULL, (char *)bpy_bmedge_is_wire_doc, NULL},
{(char *)"is_boundary", (getter)bpy_bmedge_is_boundary_get, (setter)NULL, (char *)bpy_bmedge_is_boundary_doc, NULL},
- {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
+ {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
@@ -686,6 +792,10 @@ static PyGetSetDef bpy_bmface_getseters[] = {
{(char *)"smooth", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_smooth_doc, (void *)BM_ELEM_SMOOTH},
+#ifdef WITH_FREESTYLE
+ {(char *)"freestyle_face_mark", (getter)bpy_bmface_freestyle_face_mark_get, (setter)bpy_bmface_freestyle_face_mark_set, (char *)bpy_bmface_freestyle_face_mark_doc, NULL},
+#endif
+
{(char *)"normal", (getter)bpy_bmface_normal_get, (setter)bpy_bmface_normal_set, (char *)bpy_bmface_normal_doc, NULL},
{(char *)"material_index", (getter)bpy_bmface_material_index_get, (setter)bpy_bmface_material_index_set, (char *)bpy_bmface_material_index_doc, NULL},
@@ -721,7 +831,8 @@ static PyGetSetDef bpy_bmloop_getseters[] = {
{(char *)"link_loop_radial_prev", (getter)bpy_bmloop_link_loop_radial_prev_get, (setter)NULL, (char *)bpy_bmloop_link_loop_radial_prev_doc, NULL},
/* readonly checks */
- {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
+ {(char *)"is_convex", (getter)bpy_bm_is_convex_get, (setter)NULL, (char *)bpy_bm_is_convex_doc, NULL},
+ {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
@@ -813,6 +924,8 @@ static PyObject *bpy_bmesh_free(BPy_BMesh *self)
if (self->bm) {
BMesh *bm = self->bm;
+ bm_dealloc_editmode_warn(self);
+
if ((self->flag & BPY_BMFLAG_IS_WRAPPED) == 0) {
BM_mesh_free(bm);
}
@@ -854,7 +967,7 @@ static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args)
bm = self->bm;
- BM_mesh_bm_to_me(bm, me, FALSE);
+ BM_mesh_bm_to_me(bm, me, false);
/* we could have the user do this but if they forget blender can easy crash
* since the references arrays for the objects derived meshes are now invalid */
@@ -884,9 +997,9 @@ 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_deform = true;
+ int use_render = false;
+ int use_cage = false;
DerivedMesh *dm;
const int mask = CD_MASK_BMESH;
@@ -984,7 +1097,7 @@ static PyObject *bpy_bmesh_from_mesh(BPy_BMesh *self, PyObject *args, PyObject *
BMesh *bm;
PyObject *py_mesh;
Mesh *me;
- int use_shape_key = FALSE;
+ int use_shape_key = false;
int shape_key_index = 0;
if (!PyArg_ParseTupleAndKeywords(args, kw, "O|ii:from_mesh", (char **)kwlist,
@@ -1032,7 +1145,7 @@ static PyObject *bpy_bmesh_select_flush(BPy_BMesh *self, PyObject *value)
BPY_BM_CHECK_OBJ(self);
param = PyLong_AsLong(value);
- if (param != FALSE && param != TRUE) {
+ if (param != false && param != true) {
PyErr_SetString(PyExc_TypeError,
"expected a boolean type 0/1");
return NULL;
@@ -1056,7 +1169,7 @@ PyDoc_STRVAR(bpy_bmesh_normal_update_doc,
static PyObject *bpy_bmesh_normal_update(BPy_BMesh *self, PyObject *args)
{
- int skip_hidden = FALSE;
+ int skip_hidden = false;
BPY_BM_CHECK_OBJ(self);
@@ -1163,7 +1276,7 @@ static PyObject *bpy_bm_elem_select_set(BPy_BMElem *self, PyObject *value)
BPY_BM_CHECK_OBJ(self);
param = PyLong_AsLong(value);
- if (param != FALSE && param != TRUE) {
+ if (param != false && param != true) {
PyErr_SetString(PyExc_TypeError,
"expected a boolean type 0/1");
return NULL;
@@ -1191,7 +1304,7 @@ static PyObject *bpy_bm_elem_hide_set(BPy_BMElem *self, PyObject *value)
BPY_BM_CHECK_OBJ(self);
param = PyLong_AsLong(value);
- if (param != FALSE && param != TRUE) {
+ if (param != false && param != true) {
PyErr_SetString(PyExc_TypeError,
"expected a boolean type 0/1");
return NULL;
@@ -1258,7 +1371,7 @@ static PyObject *bpy_bmvert_copy_from_vert_interp(BPy_BMVert *self, PyObject *ar
vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2,
&vert_seq_len, BM_VERT,
- TRUE, TRUE, "BMVert.copy_from_vert_interp(...)");
+ true, true, "BMVert.copy_from_vert_interp(...)");
if (vert_array == NULL) {
return NULL;
@@ -1508,8 +1621,8 @@ 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;
+ int do_verts = true;
+ int do_edges = true;
BMFace *f_cpy;
BPY_BM_CHECK_OBJ(self);
@@ -1616,6 +1729,21 @@ static PyObject *bpy_bmface_normal_update(BPy_BMFace *self)
}
+PyDoc_STRVAR(bpy_bmface_normal_flip_doc,
+".. method:: normal_flip()\n"
+"\n"
+" Reverses winding of a face, which flips its normal.\n"
+);
+static PyObject *bpy_bmface_normal_flip(BPy_BMFace *self)
+{
+ BPY_BM_CHECK_OBJ(self);
+
+ BM_face_normal_flip(self->bm, self->f);
+
+ Py_RETURN_NONE;
+}
+
+
/* Loop
* ---- */
@@ -1634,8 +1762,8 @@ 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;
+ int do_vertex = true;
+ int do_multires = true;
BPY_BM_CHECK_OBJ(self);
@@ -1803,7 +1931,7 @@ static PyObject *bpy_bmedgeseq_new(BPy_BMElemSeq *self, PyObject *args)
vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2,
&vert_seq_len, BM_VERT,
- TRUE, TRUE, "edges.new(...)");
+ true, true, "edges.new(...)");
if (vert_array == NULL) {
return NULL;
@@ -1881,7 +2009,7 @@ static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args)
vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 3, PY_SSIZE_T_MAX,
&vert_seq_len, BM_VERT,
- TRUE, TRUE, "faces.new(...)");
+ true, true, "faces.new(...)");
if (vert_array == NULL) {
return NULL;
@@ -2034,7 +2162,7 @@ static PyObject *bpy_bmedgeseq_get__method(BPy_BMElemSeq *self, PyObject *args)
vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2,
&vert_seq_len, BM_VERT,
- TRUE, TRUE, "edges.get(...)");
+ true, true, "edges.get(...)");
if (vert_array == NULL) {
return NULL;
@@ -2086,7 +2214,7 @@ static PyObject *bpy_bmfaceseq_get__method(BPy_BMElemSeq *self, PyObject *args)
vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 1, PY_SSIZE_T_MAX,
&vert_seq_len, BM_VERT,
- TRUE, TRUE, "faces.get(...)");
+ true, true, "faces.get(...)");
if (vert_array == NULL) {
return NULL;
@@ -2213,7 +2341,7 @@ static PyObject *bpy_bmelemseq_sort(BPy_BMElemSeq *self, PyObject *args, PyObjec
{
static const char *kwlist[] = {"key", "reverse", NULL};
PyObject *keyfunc = NULL; /* optional */
- int reverse = FALSE; /* optional */
+ int do_reverse = false; /* optional */
const char htype = bm_iter_itype_htype_map[self->itype];
int n_elem;
@@ -2238,7 +2366,7 @@ static PyObject *bpy_bmelemseq_sort(BPy_BMElemSeq *self, PyObject *args, PyObjec
if (!PyArg_ParseTupleAndKeywords(args, kw,
"|Oi:BMElemSeq.sort",
(char **)kwlist,
- &keyfunc, &reverse))
+ &keyfunc, &do_reverse))
{
return NULL;
}
@@ -2308,7 +2436,7 @@ static PyObject *bpy_bmelemseq_sort(BPy_BMElemSeq *self, PyObject *args, PyObjec
range_vn_i(elem_idx, n_elem, 0);
/* Sort the index array according to the order of the 'keys' array */
- if (reverse)
+ if (do_reverse)
elem_idx_compare_by_keys = bpy_bmelemseq_sort_cmp_by_keys_descending;
else
elem_idx_compare_by_keys = bpy_bmelemseq_sort_cmp_by_keys_ascending;
@@ -2424,6 +2552,7 @@ static struct PyMethodDef bpy_bmface_methods[] = {
{"calc_center_bounds", (PyCFunction)bpy_bmface_calc_center_bounds, METH_NOARGS, bpy_bmface_calc_center_bounds_doc},
{"normal_update", (PyCFunction)bpy_bmface_normal_update, METH_NOARGS, bpy_bmface_normal_update_doc},
+ {"normal_flip", (PyCFunction)bpy_bmface_normal_flip, METH_NOARGS, bpy_bmface_normal_flip_doc},
{NULL, NULL, 0, NULL}
};
@@ -2585,7 +2714,7 @@ static PyObject *bpy_bmelemseq_subscript_slice(BPy_BMElemSeq *self, Py_ssize_t s
{
BMIter iter;
int count = 0;
- int ok;
+ bool ok;
PyObject *list;
PyObject *item;
@@ -2597,14 +2726,14 @@ static PyObject *bpy_bmelemseq_subscript_slice(BPy_BMElemSeq *self, Py_ssize_t s
ok = BM_iter_init(&iter, self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL);
- BLI_assert(ok == TRUE);
+ BLI_assert(ok == true);
- if (UNLIKELY(ok == FALSE)) {
+ if (UNLIKELY(ok == false)) {
return list;
}
/* first loop up-until the start */
- for (ok = TRUE; ok; ok = (BM_iter_step(&iter) != NULL)) {
+ for (ok = true; ok; ok = (BM_iter_step(&iter) != NULL)) {
if (count == start) {
break;
}
@@ -2778,6 +2907,8 @@ static void bpy_bmesh_dealloc(BPy_BMesh *self)
/* have have been freed by bmesh */
if (bm) {
+ bm_dealloc_editmode_warn(self);
+
BM_data_layer_free(bm, &bm->vdata, CD_BM_ELEM_PYPTR);
BM_data_layer_free(bm, &bm->edata, CD_BM_ELEM_PYPTR);
BM_data_layer_free(bm, &bm->pdata, CD_BM_ELEM_PYPTR);
@@ -3403,7 +3534,7 @@ int bpy_bm_generic_valid_check(BPy_BMGeneric *self)
* function where the actual error will be caused by
* the previous action. */
#if 0
- if (BM_mesh_validate(self->bm) == FALSE) {
+ if (BM_mesh_validate(self->bm) == false) {
PyErr_Format(PyExc_ReferenceError,
"BMesh used by %.200s has become invalid",
Py_TYPE(self)->tp_name);
@@ -3448,7 +3579,7 @@ void bpy_bm_generic_invalidate(BPy_BMGeneric *self)
*/
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 char do_unique_check, const char do_bm_check,
+ const bool do_unique_check, const bool do_bm_check,
const char *error_prefix)
{
BMesh *bm = (r_bm && *r_bm) ? *r_bm : NULL;
@@ -3515,17 +3646,17 @@ void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_
if (do_unique_check) {
/* check for double verts! */
- int ok = TRUE;
+ 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;
+ if (UNLIKELY(BM_elem_flag_test(alloc[i], BM_ELEM_INTERNAL_TAG) == false)) {
+ ok = false;
}
/* ensure we don't leave this enabled */
BM_elem_flag_disable(alloc[i], BM_ELEM_INTERNAL_TAG);
}
- if (ok == FALSE) {
+ if (ok == false) {
PyErr_Format(PyExc_ValueError,
"%s: found the same %.200s used multiple times",
error_prefix, BPy_BMElem_StringFromHType(htype));
@@ -3588,3 +3719,51 @@ char *BPy_BMElem_StringFromHType(const char htype)
static char ret[32];
return BPy_BMElem_StringFromHType_ex(htype, ret);
}
+
+
+/* -------------------------------------------------------------------- */
+/* keep at bottom */
+/* BAD INCLUDES */
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_tessmesh.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "MEM_guardedalloc.h"
+
+/* there are cases where this warning isnt needed, otherwise it could be made into an error */
+static void bm_dealloc_warn(const char *mesh_name)
+{
+ PySys_WriteStdout("Modified BMesh '%.200s' from a wrapped editmesh is freed without a call "
+ "to bmesh.update_edit_mesh(mesh, destructive=True), this is will likely cause a crash\n",
+ mesh_name);
+}
+
+/* this function is called on free, it should stay quite fast */
+static void bm_dealloc_editmode_warn(BPy_BMesh *self)
+{
+ if (self->flag & BPY_BMFLAG_IS_WRAPPED) {
+ /* likely editmesh */
+ BMesh *bm = self->bm;
+ Scene *scene;
+ for (scene = G.main->scene.first; scene; scene = scene->id.next) {
+ Base *base = scene->basact;
+ if (base && base->object->type == OB_MESH) {
+ Mesh *me = base->object->data;
+ BMEditMesh *em = me->edit_btmesh;
+ if (em && em->bm == bm) {
+ /* not foolproof, scripter may have added/removed verts */
+ if (((em->vert_index && (MEM_allocN_len(em->vert_index) / sizeof(*em->vert_index)) != bm->totvert)) ||
+ ((em->edge_index && (MEM_allocN_len(em->edge_index) / sizeof(*em->edge_index)) != bm->totedge)) ||
+ ((em->face_index && (MEM_allocN_len(em->face_index) / sizeof(*em->face_index)) != bm->totface)))
+ {
+ bm_dealloc_warn(me->id.name + 2);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h
index d15918a3c11..f02b94be526 100644
--- a/source/blender/python/bmesh/bmesh_py_types.h
+++ b/source/blender/python/bmesh/bmesh_py_types.h
@@ -160,7 +160,7 @@ PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele); /* just checks ty
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 char do_unique_check, const char do_bm_check,
+ 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);
@@ -168,7 +168,7 @@ int BPy_BMElem_CheckHType(PyTypeObject *type, const char htype);
char *BPy_BMElem_StringFromHType_ex(const char htype, char ret[32]);
char *BPy_BMElem_StringFromHType(const char htype);
-void bpy_bm_generic_invalidate(BPy_BMGeneric *self);
+// void bpy_bm_generic_invalidate(BPy_BMGeneric *self);
int bpy_bm_generic_valid_check(BPy_BMGeneric *self);
int bpy_bm_generic_valid_check_source(BPy_BMGeneric *self, BMesh *bm_source, const char *error_prefix);
diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c
index fd31f3c40cc..63ad8756cec 100644
--- a/source/blender/python/bmesh/bmesh_py_types_customdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c
@@ -112,6 +112,14 @@ PyDoc_STRVAR(bpy_bmlayeraccess_collection__uv_doc,
PyDoc_STRVAR(bpy_bmlayeraccess_collection__color_doc,
"Accessor for vertex color 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`"
+);
+PyDoc_STRVAR(bpy_bmlayeraccess_collection__freestyle_face_doc,
+"Accessor for Freestyle face layer.\n\ntype: :class:`BMLayerCollection`"
+);
+#endif
static PyObject *bpy_bmlayeraccess_collection_get(BPy_BMLayerAccess *self, void *flag)
{
@@ -194,6 +202,9 @@ static PyGetSetDef bpy_bmlayeraccess_edge_getseters[] = {
{(char *)"bevel_weight", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__bevel_weight_doc, (void *)CD_BWEIGHT},
{(char *)"crease", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__crease_doc, (void *)CD_CREASE},
+#ifdef WITH_FREESTYLE
+ {(char *)"freestyle_edge", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__freestyle_edge_doc, (void *)CD_FREESTYLE_EDGE},
+#endif
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
@@ -205,6 +216,10 @@ static PyGetSetDef bpy_bmlayeraccess_face_getseters[] = {
{(char *)"tex", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__tex_doc, (void *)CD_MTEXPOLY},
+#ifdef WITH_FREESTYLE
+ {(char *)"freestyle_face", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__freestyle_face_doc, (void *)CD_FREESTYLE_FACE},
+#endif
+
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
@@ -981,7 +996,7 @@ PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer)
case CD_PROP_STR:
{
MStringProperty *mstring = value;
- ret = PyBytes_FromStringAndSize(mstring->s, BLI_strnlen(mstring->s, sizeof(mstring->s)));
+ ret = PyBytes_FromStringAndSize(mstring->s, mstring->s_len);
break;
}
case CD_MTEXPOLY:
@@ -1067,13 +1082,17 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj
case CD_PROP_STR:
{
MStringProperty *mstring = value;
- const char *tmp_val = PyBytes_AsString(py_value);
- if (UNLIKELY(tmp_val == NULL)) {
+ char *tmp_val;
+ Py_ssize_t tmp_val_len;
+ if (UNLIKELY(PyBytes_AsStringAndSize(py_value, &tmp_val, &tmp_val_len) == -1)) {
PyErr_Format(PyExc_TypeError, "expected bytes, not a %.200s", Py_TYPE(py_value)->tp_name);
ret = -1;
}
else {
- BLI_strncpy(mstring->s, tmp_val, min_ii(PyBytes_Size(py_value), sizeof(mstring->s)));
+ if (tmp_val_len > sizeof(mstring->s))
+ tmp_val_len = sizeof(mstring->s);
+ memcpy(mstring->s, tmp_val, tmp_val_len);
+ mstring->s_len = tmp_val_len;
}
break;
}
diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
index b0870578f5a..64435792ae2 100644
--- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
@@ -97,7 +97,7 @@ static PyGetSetDef bpy_bmtexpoly_getseters[] = {
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
-PyTypeObject BPy_BMTexPoly_Type = {{{0}}}; /* bm.loops.layers.uv.active */
+static PyTypeObject BPy_BMTexPoly_Type = {{{0}}}; /* bm.loops.layers.uv.active */
static void bm_init_types_bmtexpoly(void)
{
@@ -187,10 +187,10 @@ static int bpy_bmloopuv_flag_set(BPy_BMLoopUV *self, PyObject *value, void *flag
const int flag = GET_INT_FROM_POINTER(flag_p);
switch (PyLong_AsLong(value)) {
- case TRUE:
+ case true:
self->data->flag |= flag;
return 0;
- case FALSE:
+ case false:
self->data->flag &= ~flag;
return 0;
default:
diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.h b/source/blender/python/bmesh/bmesh_py_types_meshdata.h
index c9e8dce97a0..8280e5c3bc5 100644
--- a/source/blender/python/bmesh/bmesh_py_types_meshdata.h
+++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.h
@@ -51,9 +51,6 @@ PyObject *BPy_BMTexPoly_CreatePyObject(struct MTexPoly *mloopuv);
int BPy_BMLoopUV_AssignPyObject(struct MLoopUV *data, PyObject *value);
PyObject *BPy_BMLoopUV_CreatePyObject(struct MLoopUV *data);
-int BPy_BMLoopUV_AssignPyObject(struct MLoopUV *data, PyObject *value);
-PyObject *BPy_BMLoopUV_CreatePyObject(struct MLoopUV *data);
-
int BPy_BMLoopColor_AssignPyObject(struct MLoopCol *data, PyObject *value);
PyObject *BPy_BMLoopColor_CreatePyObject(struct MLoopCol *data);
diff --git a/source/blender/python/bmesh/bmesh_py_types_select.c b/source/blender/python/bmesh/bmesh_py_types_select.c
index dfcfbeb0ab5..33cb1f5d0fb 100644
--- a/source/blender/python/bmesh/bmesh_py_types_select.c
+++ b/source/blender/python/bmesh/bmesh_py_types_select.c
@@ -107,7 +107,7 @@ static PyObject *bpy_bmeditselseq_add(BPy_BMEditSelSeq *self, BPy_BMElem *value)
if ((BPy_BMVert_Check(value) ||
BPy_BMEdge_Check(value) ||
- BPy_BMFace_Check(value)) == FALSE)
+ BPy_BMFace_Check(value)) == false)
{
PyErr_Format(PyExc_TypeError,
"Expected a BMVert/BMedge/BMFace not a %.200s", Py_TYPE(value)->tp_name);
@@ -132,7 +132,7 @@ static PyObject *bpy_bmeditselseq_remove(BPy_BMEditSelSeq *self, BPy_BMElem *val
if ((BPy_BMVert_Check(value) ||
BPy_BMEdge_Check(value) ||
- BPy_BMFace_Check(value)) == FALSE)
+ BPy_BMFace_Check(value)) == false)
{
PyErr_Format(PyExc_TypeError,
"Expected a BMVert/BMedge/BMFace not a %.200s", Py_TYPE(value)->tp_name);
@@ -141,7 +141,7 @@ static PyObject *bpy_bmeditselseq_remove(BPy_BMEditSelSeq *self, BPy_BMElem *val
BPY_BM_CHECK_SOURCE_OBJ(value, self->bm, "select_history.remove()");
- if (BM_select_history_remove(self->bm, value->ele) == FALSE) {
+ if (BM_select_history_remove(self->bm, value->ele) == false) {
PyErr_SetString(PyExc_ValueError,
"Element not found in selection history");
return NULL;
@@ -196,7 +196,7 @@ static PyObject *bpy_bmeditselseq_subscript_int(BPy_BMEditSelSeq *self, int keyn
static PyObject *bpy_bmeditselseq_subscript_slice(BPy_BMEditSelSeq *self, Py_ssize_t start, Py_ssize_t stop)
{
int count = 0;
- int ok;
+ bool ok;
PyObject *list;
PyObject *item;
@@ -210,12 +210,12 @@ static PyObject *bpy_bmeditselseq_subscript_slice(BPy_BMEditSelSeq *self, Py_ssi
ok = (ese != NULL);
- if (UNLIKELY(ok == FALSE)) {
+ if (UNLIKELY(ok == false)) {
return list;
}
/* first loop up-until the start */
- for (ok = TRUE; ok; ok = ((ese = ese->next) != NULL)) {
+ for (ok = true; ok; ok = ((ese = ese->next) != NULL)) {
if (count == start) {
break;
}
@@ -429,7 +429,7 @@ int BPy_BMEditSel_Assign(BPy_BMesh *self, PyObject *value)
value_array = BPy_BMElem_PySeq_As_Array(&bm, value, 0, PY_SSIZE_T_MAX,
&value_len, BM_VERT | BM_EDGE | BM_FACE,
- TRUE, TRUE, "BMesh.select_history = value");
+ true, true, "BMesh.select_history = value");
if (value_array == NULL) {
return -1;
diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c
index f85c3347104..7c0adcfc997 100644
--- a/source/blender/python/bmesh/bmesh_py_utils.c
+++ b/source/blender/python/bmesh/bmesh_py_utils.c
@@ -90,7 +90,7 @@ static PyObject *bpy_bm_utils_vert_collapse_edge(PyObject *UNUSED(self), PyObjec
bm = py_edge->bm;
- e_new = BM_vert_collapse_edge(bm, py_edge->e, py_vert->v, TRUE);
+ e_new = BM_vert_collapse_edge(bm, py_edge->e, py_vert->v, true);
if (e_new) {
return BPy_BMEdge_CreatePyObject(bm, e_new);
@@ -106,7 +106,7 @@ static PyObject *bpy_bm_utils_vert_collapse_edge(PyObject *UNUSED(self), PyObjec
PyDoc_STRVAR(bpy_bm_utils_vert_collapse_faces_doc,
".. method:: vert_collapse_faces(vert, edge, fac, join_faces)\n"
"\n"
-" Split an edge, return the newly created data.\n"
+" Collapses a vertex that has only two manifold edges onto a vertex it shares an edge with.\n"
"\n"
" :arg vert: The vert that will be collapsed.\n"
" :type vert: :class:`bmesh.types.BMVert`\n"
@@ -156,14 +156,14 @@ static PyObject *bpy_bm_utils_vert_collapse_faces(PyObject *UNUSED(self), PyObje
bm = py_edge->bm;
- e_new = BM_vert_collapse_faces(bm, py_edge->e, py_vert->v, CLAMPIS(fac, 0.0f, 1.0f), do_join_faces, TRUE);
+ e_new = BM_vert_collapse_faces(bm, py_edge->e, py_vert->v, CLAMPIS(fac, 0.0f, 1.0f), do_join_faces, true);
if (e_new) {
return BPy_BMEdge_CreatePyObject(bm, e_new);
}
else {
PyErr_SetString(PyExc_ValueError,
- "vert_collapse_edge(vert, edge): no new edge created, internal error");
+ "vert_collapse_faces(vert, edge): no new edge created, internal error");
return NULL;
}
}
@@ -239,7 +239,7 @@ static PyObject *bpy_bm_utils_vert_separate(PyObject *UNUSED(self), PyObject *ar
edge_array = BPy_BMElem_PySeq_As_Array(&bm, edge_seq, 0, PY_SSIZE_T_MAX,
&edge_array_len, BM_EDGE,
- TRUE, TRUE, "vert_separate(...)");
+ true, true, "vert_separate(...)");
if (edge_array == NULL) {
return NULL;
@@ -338,7 +338,7 @@ 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;
+ int do_ccw = false;
BMesh *bm;
BMEdge *e_new = NULL;
@@ -396,7 +396,7 @@ static PyObject *bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args,
/* optional */
PyObject *py_coords = NULL;
- int edge_exists = TRUE;
+ int edge_exists = true;
BPy_BMEdge *py_edge_example = NULL;
float *coords;
@@ -426,8 +426,8 @@ static PyObject *bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args,
}
/* this doubles for checking that the verts are in the same mesh */
- if (BM_vert_in_face(py_face->f, py_vert_a->v) == FALSE ||
- BM_vert_in_face(py_face->f, py_vert_b->v) == FALSE)
+ if (BM_vert_in_face(py_face->f, py_vert_a->v) == false ||
+ BM_vert_in_face(py_face->f, py_vert_b->v) == false)
{
PyErr_SetString(PyExc_ValueError,
"face_split(...): one of the verts passed is not found in the face");
@@ -496,7 +496,7 @@ 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;
+ int do_remove = true;
if (!PyArg_ParseTuple(args, "O|i:face_join", &py_face_array, &do_remove)) {
return NULL;
@@ -504,7 +504,7 @@ static PyObject *bpy_bm_utils_face_join(PyObject *UNUSED(self), PyObject *args)
face_array = BPy_BMElem_PySeq_As_Array(&bm, py_face_array, 2, PY_SSIZE_T_MAX,
&face_seq_len, BM_FACE,
- TRUE, TRUE, "face_join(...)");
+ true, true, "face_join(...)");
if (face_array == NULL) {
return NULL; /* error will be set */
diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c
index 8d146bedb48..734d4b6b83f 100644
--- a/source/blender/python/generic/bpy_internal_import.c
+++ b/source/blender/python/generic/bpy_internal_import.c
@@ -66,7 +66,7 @@ static PyObject *imp_reload_orig = NULL;
*
* However Python's alternative is to use import hooks,
* which are implemented in a way that we can't use our own importer as a
- * fall-back (instead we must try and fail - raise an exception evert time).
+ * fall-back (instead we must try and fail - raise an exception every time).
* Since importing from blenders text-blocks is not the common case
* I prefer to use Pythons import by default and fall-back to
* Blenders - which we can only do by intercepting import calls I'm afraid.
@@ -81,7 +81,7 @@ void bpy_import_init(PyObject *builtins)
/* move reload here
* XXX, use import hooks */
- mod = PyImport_ImportModuleLevel((char *)"imp", NULL, NULL, NULL, 0);
+ mod = PyImport_ImportModuleLevel("imp", NULL, NULL, NULL, 0);
if (mod) {
PyObject *mod_dict = PyModule_GetDict(mod);
diff --git a/source/blender/python/generic/bpy_internal_import.h b/source/blender/python/generic/bpy_internal_import.h
index 1592ec52b4c..56cdf677ccb 100644
--- a/source/blender/python/generic/bpy_internal_import.h
+++ b/source/blender/python/generic/bpy_internal_import.h
@@ -48,9 +48,9 @@ struct Text;
void bpy_import_init(PyObject *builtins);
-PyObject* bpy_text_import(struct Text *text);
-PyObject* bpy_text_import_name(const char *name, int *found);
-PyObject* bpy_text_reimport(PyObject *module, int *found);
+PyObject *bpy_text_import(struct Text *text);
+PyObject *bpy_text_import_name(const char *name, int *found);
+PyObject *bpy_text_reimport(PyObject *module, int *found);
/* void bpy_text_clear_modules(int clear_all);*/ /* Clear user modules */
void bpy_text_filename_get(char *fn, size_t fn_len, struct Text *text);
diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c
index 53112d46098..85bb8125a3a 100644
--- a/source/blender/python/generic/idprop_py_api.c
+++ b/source/blender/python/generic/idprop_py_api.c
@@ -470,7 +470,9 @@ const char *BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty
Py_XDECREF(keys);
Py_XDECREF(vals);
}
- else return "invalid property value";
+ else {
+ return "invalid property value";
+ }
if (group->type == IDP_IDPARRAY) {
IDP_AppendArray(group, prop);
@@ -836,6 +838,11 @@ static PyObject *BPy_IDGroup_to_dict(BPy_IDProperty *self)
return BPy_IDGroup_MapDataToPy(self->prop);
}
+static PyObject *BPy_IDGroup_clear(BPy_IDProperty *self)
+{
+ IDP_ClearProperty(self->prop);
+ Py_RETURN_NONE;
+}
/* Matches python dict.get(key, [default]) */
static PyObject *BPy_IDGroup_Get(BPy_IDProperty *self, PyObject *args)
@@ -875,6 +882,8 @@ static struct PyMethodDef BPy_IDGroup_methods[] = {
"idprop.get(k[,d]) -> idprop[k] if k in idprop, else d. d defaults to None"},
{"to_dict", (PyCFunction)BPy_IDGroup_to_dict, METH_NOARGS,
"return a purely python version of the group"},
+ {"clear", (PyCFunction)BPy_IDGroup_clear, METH_NOARGS,
+ "clear all members from this group"},
{NULL, NULL, 0, NULL}
};
@@ -1447,6 +1456,8 @@ static PyObject *BPyInit_idprop_types(void)
submodule = PyModule_Create(&IDProp_types_module_def);
+ IDProp_Init_Types();
+
#define MODULE_TYPE_ADD(s, t) \
PyModule_AddObject(s, t.tp_name, (PyObject *)&t); Py_INCREF((PyObject *)&t)
@@ -1490,7 +1501,7 @@ PyObject *BPyInit_idprop(void)
mod = PyModule_Create(&IDProp_module_def);
- /* bmesh.types */
+ /* idprop.types */
PyModule_AddObject(mod, "types", (submodule = BPyInit_idprop_types()));
PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
Py_INCREF(submodule);
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index f62fdaf09db..2876d7666f4 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -33,6 +33,8 @@
#include <Python.h>
#include <frameobject.h>
+#include "BLI_utildefines.h" /* for bool */
+
#include "py_capi_utils.h"
/* only for BLI_strncpy_wchar_from_utf8, should replace with py funcs but too late in release now */
@@ -44,7 +46,7 @@
/* array utility function */
int PyC_AsArray(void *array, PyObject *value, const Py_ssize_t length,
- const PyTypeObject *type, const short is_double, const char *error_prefix)
+ const PyTypeObject *type, const bool is_double, const char *error_prefix)
{
PyObject *value_fast;
Py_ssize_t value_len;
@@ -112,6 +114,54 @@ int PyC_AsArray(void *array, PyObject *value, const Py_ssize_t length,
return 0;
}
+/* array utility function */
+PyObject *PyC_FromArray(const void *array, int length, const PyTypeObject *type,
+ const bool is_double, const char *error_prefix)
+{
+ PyObject *tuple;
+ int i;
+
+ tuple = PyTuple_New(length);
+
+ /* for each type */
+ if (type == &PyFloat_Type) {
+ if (is_double) {
+ const double *array_double = array;
+ for (i = 0; i < length; ++i) {
+ PyTuple_SET_ITEM(tuple, i, PyFloat_FromDouble(array_double[i]));
+ }
+ }
+ else {
+ const float *array_float = array;
+ for (i = 0; i < length; ++i) {
+ PyTuple_SET_ITEM(tuple, i, PyFloat_FromDouble(array_float[i]));
+ }
+ }
+ }
+ else if (type == &PyLong_Type) {
+ /* could use is_double for 'long int' but no use now */
+ const int *array_int = array;
+ for (i = 0; i < length; ++i) {
+ PyTuple_SET_ITEM(tuple, i, PyLong_FromLong(array_int[i]));
+ }
+ }
+ else if (type == &PyBool_Type) {
+ const int *array_bool = array;
+ for (i = 0; i < length; ++i) {
+ PyTuple_SET_ITEM(tuple, i, PyBool_FromLong(array_bool[i]));
+ }
+ }
+ else {
+ Py_DECREF(tuple);
+ PyErr_Format(PyExc_TypeError,
+ "%s: internal error %s is invalid",
+ error_prefix, type->tp_name);
+ return NULL;
+ }
+
+ return tuple;
+}
+
/* for debugging */
void PyC_ObSpit(const char *name, PyObject *var)
@@ -241,6 +291,23 @@ PyObject *PyC_Object_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...)
return item;
}
+PyObject *PyC_FrozenSetFromStrings(const char **strings)
+{
+ const char **str;
+ PyObject *ret;
+
+ ret = PyFrozenSet_New(NULL);
+
+ for (str = strings; *str; str++) {
+ PyObject *py_str = PyUnicode_FromString(*str);
+ PySet_Add(ret, py_str);
+ Py_DECREF(py_str);
+ }
+
+ return ret;
+}
+
+
/* similar to PyErr_Format(),
*
* implementation - we cant actually preprend the existing exception,
@@ -684,7 +751,7 @@ void *PyC_RNA_AsPointer(PyObject *value, const char *type_name)
PyObject *as_pointer;
PyObject *pointer;
- if (!strcmp(Py_TYPE(value)->tp_name, type_name) &&
+ if (STREQ(Py_TYPE(value)->tp_name, type_name) &&
(as_pointer = PyObject_GetAttrString(value, "as_pointer")) != NULL &&
PyCallable_Check(as_pointer))
{
@@ -737,7 +804,7 @@ char *PyC_FlagSet_AsString(PyC_FlagSet *item)
int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *value)
{
for ( ; item->identifier; item++) {
- if (strcmp(item->identifier, identifier) == 0) {
+ if (STREQ(item->identifier, identifier)) {
*value = item->value;
return 1;
}
diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h
index 935a5f9030b..239858032de 100644
--- a/source/blender/python/generic/py_capi_utils.h
+++ b/source/blender/python/generic/py_capi_utils.h
@@ -33,11 +33,14 @@ void PyC_LineSpit(void);
void PyC_StackSpit(void);
PyObject * PyC_ExceptionBuffer(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 short is_double, const char *error_prefix);
+ 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);
/* follow http://www.python.org/dev/peps/pep-0383/ */
PyObject * PyC_UnicodeFromByte(const char *str);
@@ -53,7 +56,7 @@ void PyC_MainModule_Restore(PyObject *main_mod);
void PyC_SetHomePath(const char *py_path_bundle);
-#define PYC_INTERPRETER_ACTIVE (((PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current)) != NULL)
+#define PYC_INTERPRETER_ACTIVE (((PyThreadState *)_Py_atomic_load_relaxed(&_PyThreadState_Current)) != NULL)
void *PyC_RNA_AsPointer(PyObject *value, const char *type_name);
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index 61c49027d9a..30ab4bd4b0e 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -47,7 +47,9 @@ set(SRC
bpy.c
bpy_app.c
bpy_app_ffmpeg.c
+ bpy_app_build_options.c
bpy_app_handlers.c
+ bpy_app_translations.c
bpy_driver.c
bpy_interface.c
bpy_interface_atexit.c
@@ -55,6 +57,7 @@ set(SRC
bpy_library.c
bpy_operator.c
bpy_operator_wrap.c
+ bpy_path.c
bpy_props.c
bpy_rna.c
bpy_rna_anim.c
@@ -68,12 +71,15 @@ set(SRC
bpy.h
bpy_app.h
bpy_app_ffmpeg.h
+ bpy_app_build_options.h
bpy_app_handlers.h
+ bpy_app_translations.h
bpy_driver.h
bpy_intern_string.h
bpy_library.h
bpy_operator.h
bpy_operator_wrap.h
+ bpy_path.h
bpy_props.h
bpy_rna.h
bpy_rna_anim.h
@@ -96,24 +102,147 @@ if(WITH_PYTHON_SAFETY)
add_definitions(-DWITH_PYTHON_SAFETY)
endif()
+
+
if(WITH_AUDASPACE)
add_definitions(-DWITH_AUDASPACE)
endif()
-if(WITH_CYCLES)
- add_definitions(-DWITH_CYCLES)
+if(WITH_BULLET)
+ add_definitions(-DWITH_BULLET)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+if(WITH_CODEC_AVI)
+ add_definitions(-DWITH_AVI)
endif()
if(WITH_CODEC_FFMPEG)
list(APPEND INC_SYS
${FFMPEG_INCLUDE_DIRS}
)
-
add_definitions(-DWITH_FFMPEG)
endif()
+if(WITH_CODEC_QUICKTIME)
+ add_definitions(-DWITH_QUICKTIME)
+endif()
+
+if(WITH_CODEC_SNDFILE)
+ add_definitions(-DWITH_SNDFILE)
+endif()
+
+if(WITH_COMPOSITOR)
+ add_definitions(-DWITH_COMPOSITOR)
+endif()
+
+if(WITH_CYCLES)
+ add_definitions(-DWITH_CYCLES)
+endif()
+
+if(WITH_CYCLES_OSL)
+ add_definitions(-DWITH_CYCLES_OSL)
+endif()
+
+if(WITH_FREESTYLE)
+ list(APPEND INC
+ ../../freestyle/intern/python
+ )
+ add_definitions(-DWITH_FREESTYLE)
+endif()
+
+if(WITH_GAMEENGINE)
+ add_definitions(-DWITH_GAMEENGINE)
+endif()
+
+if(WITH_IMAGE_CINEON)
+ add_definitions(-DWITH_CINEON)
+endif()
+
+if(WITH_IMAGE_DDS)
+ add_definitions(-DWITH_DDS)
+endif()
+
+if(WITH_IMAGE_FRAMESERVER)
+ add_definitions(-DWITH_FRAMESERVER)
+endif()
+
+if(WITH_IMAGE_HDR)
+ add_definitions(-DWITH_HDR)
+endif()
+
+if(WITH_IMAGE_OPENEXR)
+ add_definitions(-DWITH_OPENEXR)
+endif()
+
+if(WITH_IMAGE_OPENJPEG)
+ add_definitions(-DWITH_OPENJPEG)
+endif()
+
+if(WITH_IMAGE_REDCODE)
+ add_definitions(-DWITH_REDCODE)
+endif()
+
+if(WITH_IMAGE_TIFF)
+ add_definitions(-DWITH_TIFF)
+endif()
+
+if(WITH_INPUT_NDOF)
+ add_definitions(-DWITH_INPUT_NDOF)
+endif()
+
+if(WITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
+endif()
+
+if(WITH_OPENAL)
+ add_definitions(-DWITH_OPENAL)
+endif()
+
+if(WITH_SDL)
+ add_definitions(-DWITH_SDL)
+endif()
+
+if(WITH_JACK)
+ add_definitions(-DWITH_JACK)
+endif()
+
+if(WITH_LIBMV)
+ add_definitions(-DWITH_LIBMV)
+endif()
+
+if(WITH_MOD_BOOLEAN)
+ add_definitions(-DWITH_MOD_BOOLEAN)
+endif()
+
+if(WITH_MOD_FLUID)
+ add_definitions(-DWITH_MOD_FLUID)
+endif()
+
+if(WITH_MOD_OCEANSIM)
+ add_definitions(-DWITH_OCEANSIM)
+endif()
+
+if(WITH_MOD_REMESH)
+ add_definitions(-DWITH_MOD_REMESH)
+endif()
+
+if(WITH_MOD_SMOKE)
+ add_definitions(-DWITH_SMOKE)
+endif()
+
+if(WITH_OPENCOLLADA)
+ add_definitions(-DWITH_COLLADA)
+endif()
+
+if(WITH_OPENCOLORIO)
+ add_definitions(-DWITH_OCIO)
+endif()
+
+if(WITH_PLAYER)
+ add_definitions(-DWITH_PLAYER)
+endif()
+
+
+
+
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 3ed662f41d7..775cce3880b 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -27,31 +27,29 @@
* to access C defined builtin functions.
* A script writer should never directly access this module.
*/
-
-#define WITH_PYTHON /* for AUD_PyInit.h, possibly others */
#include <Python.h>
+#include "BLI_utildefines.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+
+#include "BKE_main.h"
+#include "BKE_global.h" /* XXX, G.main only */
+#include "BKE_blender.h"
+#include "BKE_bpath.h"
+
#include "RNA_types.h"
#include "RNA_access.h"
-#include "bpy.h"
-#include "bpy_util.h"
+#include "bpy.h"
+#include "bpy_util.h"
#include "bpy_rna.h"
#include "bpy_app.h"
#include "bpy_props.h"
#include "bpy_library.h"
#include "bpy_operator.h"
-#include "BLI_path_util.h"
-#include "BLI_string.h"
-#include "BLI_bpath.h"
-#include "BLI_utildefines.h"
-
-#include "BKE_main.h"
-#include "BKE_global.h" /* XXX, G.main only */
-#include "BKE_blender.h"
-
#include "MEM_guardedalloc.h"
/* external util modules */
@@ -60,6 +58,10 @@
#include "../generic/blf_py_api.h"
#include "../mathutils/mathutils.h"
+#ifdef WITH_FREESTYLE
+# include "BPy_Freestyle.h"
+#endif
+
PyObject *bpy_package_py = NULL;
PyDoc_STRVAR(bpy_script_paths_doc,
@@ -74,7 +76,7 @@ static PyObject *bpy_script_paths(PyObject *UNUSED(self))
{
PyObject *ret = PyTuple_New(2);
PyObject *item;
- char *path;
+ const char *path;
path = BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, NULL);
item = PyUnicode_DecodeFSDefault(path ? path : "");
@@ -94,7 +96,7 @@ static int bpy_blend_paths_visit_cb(void *userdata, char *UNUSED(path_dst), cons
PyObject *item = PyUnicode_DecodeFSDefault(path_src);
PyList_Append(list, item);
Py_DECREF(item);
- return FALSE; /* never edits the path */
+ return false; /* never edits the path */
}
PyDoc_STRVAR(bpy_blend_paths_doc,
@@ -116,9 +118,9 @@ 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;
+ int absolute = false;
+ int packed = false;
+ int local = false;
static const char *kwlist[] = {"absolute", "packed", "local", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kw, "|iii:blend_paths",
@@ -127,13 +129,13 @@ static PyObject *bpy_blend_paths(PyObject *UNUSED(self), PyObject *args, PyObjec
return NULL;
}
- if (absolute) flag |= BLI_BPATH_TRAVERSE_ABS;
- if (!packed) flag |= BLI_BPATH_TRAVERSE_SKIP_PACKED;
- if (local) flag |= BLI_BPATH_TRAVERSE_SKIP_LIBRARY;
+ if (absolute) flag |= BKE_BPATH_TRAVERSE_ABS;
+ if (!packed) flag |= BKE_BPATH_TRAVERSE_SKIP_PACKED;
+ if (local) flag |= BKE_BPATH_TRAVERSE_SKIP_LIBRARY;
list = PyList_New(0);
- BLI_bpath_traverse_main(G.main, bpy_blend_paths_visit_cb, flag, (void *)list);
+ BKE_bpath_traverse_main(G.main, bpy_blend_paths_visit_cb, flag, (void *)list);
return list;
}
@@ -147,16 +149,16 @@ static PyObject *bpy_user_resource(PyObject *UNUSED(self), PyObject *args, PyObj
int folder_id;
static const char *kwlist[] = {"type", "subdir", NULL};
- char *path;
+ const char *path;
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|s:user_resource", (char **)kwlist, &type, &subdir))
return NULL;
/* stupid string compare */
- if (!strcmp(type, "DATAFILES")) folder_id = BLENDER_USER_DATAFILES;
- else if (!strcmp(type, "CONFIG")) folder_id = BLENDER_USER_CONFIG;
- else if (!strcmp(type, "SCRIPTS")) folder_id = BLENDER_USER_SCRIPTS;
- else if (!strcmp(type, "AUTOSAVE")) folder_id = BLENDER_USER_AUTOSAVE;
+ if (STREQ(type, "DATAFILES")) folder_id = BLENDER_USER_DATAFILES;
+ else if (STREQ(type, "CONFIG")) folder_id = BLENDER_USER_CONFIG;
+ else if (STREQ(type, "SCRIPTS")) folder_id = BLENDER_USER_SCRIPTS;
+ else if (STREQ(type, "AUTOSAVE")) folder_id = BLENDER_USER_AUTOSAVE;
else {
PyErr_SetString(PyExc_ValueError, "invalid resource argument");
return NULL;
@@ -191,21 +193,21 @@ static PyObject *bpy_resource_path(PyObject *UNUSED(self), PyObject *args, PyObj
int major = BLENDER_VERSION / 100, minor = BLENDER_VERSION % 100;
static const char *kwlist[] = {"type", "major", "minor", NULL};
int folder_id;
- char *path;
+ const char *path;
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ii:resource_path", (char **)kwlist, &type, &major, &minor))
return NULL;
/* stupid string compare */
- if (!strcmp(type, "USER")) folder_id = BLENDER_RESOURCE_PATH_USER;
- else if (!strcmp(type, "LOCAL")) folder_id = BLENDER_RESOURCE_PATH_LOCAL;
- else if (!strcmp(type, "SYSTEM")) folder_id = BLENDER_RESOURCE_PATH_SYSTEM;
+ if (STREQ(type, "USER")) folder_id = BLENDER_RESOURCE_PATH_USER;
+ else if (STREQ(type, "LOCAL")) folder_id = BLENDER_RESOURCE_PATH_LOCAL;
+ else if (STREQ(type, "SYSTEM")) folder_id = BLENDER_RESOURCE_PATH_SYSTEM;
else {
PyErr_SetString(PyExc_ValueError, "invalid resource argument");
return NULL;
}
- path = BLI_get_folder_version(folder_id, (major * 100) + minor, FALSE);
+ path = BLI_get_folder_version(folder_id, (major * 100) + minor, false);
return PyUnicode_DecodeFSDefault(path ? path : "");
}
@@ -222,7 +224,7 @@ static PyMethodDef meth_bpy_resource_path =
static PyObject *bpy_import_test(const char *modname)
{
- PyObject *mod = PyImport_ImportModuleLevel((char *)modname, NULL, NULL, NULL, 0);
+ PyObject *mod = PyImport_ImportModuleLevel(modname, NULL, NULL, NULL, 0);
if (mod) {
Py_DECREF(mod);
}
@@ -234,6 +236,7 @@ static PyObject *bpy_import_test(const char *modname)
return mod;
}
+
/******************************************************************************
* Description: Creates the bpy module and adds it to sys.modules for importing
******************************************************************************/
@@ -244,7 +247,7 @@ void BPy_init_modules(void)
PyObject *mod;
/* Needs to be first since this dir is needed for future modules */
- char *modpath = BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, "modules");
+ const char * const modpath = BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, "modules");
if (modpath) {
// printf("bpy: found module path '%s'.\n", modpath);
PyObject *sys_path = PySys_GetObject("path"); /* borrow */
@@ -257,6 +260,9 @@ void BPy_init_modules(void)
}
/* stand alone utility modules not related to blender directly */
IDProp_Init_Types(); /* not actually a submodule, just types */
+#ifdef WITH_FREESTYLE
+ Freestyle_Init();
+#endif
mod = PyModule_New("_bpy");
@@ -293,6 +299,9 @@ void BPy_init_modules(void)
PyModule_AddObject(mod, "context", (PyObject *)bpy_context_module);
+ /* register bpy/rna classmethod callbacks */
+ BPY_rna_register_cb();
+
/* utility func's that have nowhere else to go */
PyModule_AddObject(mod, meth_bpy_script_paths.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_script_paths, NULL));
PyModule_AddObject(mod, meth_bpy_blend_paths.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_blend_paths, NULL));
diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c
index b1eeff8b3ae..17dafc4ac52 100644
--- a/source/blender/python/intern/bpy_app.c
+++ b/source/blender/python/intern/bpy_app.c
@@ -34,13 +34,15 @@
#include "bpy_app.h"
#include "bpy_app_ffmpeg.h"
+#include "bpy_app_build_options.h"
+
+#include "bpy_app_translations.h"
#include "bpy_app_handlers.h"
#include "bpy_driver.h"
-#include "BLI_path_util.h"
#include "BLI_utildefines.h"
-
+#include "BLI_path_util.h"
#include "BKE_blender.h"
#include "BKE_global.h"
@@ -83,8 +85,10 @@ static PyStructSequence_Field app_info_fields[] = {
/* submodules */
{(char *)"ffmpeg", (char *)"FFmpeg library information backend"},
+ {(char *)"build_options", (char *)"A set containing most important enabled optional build features"},
{(char *)"handlers", (char *)"Application handler callbacks"},
- {NULL}
+ {(char *)"translations", (char *)"Application and addons internationalization API"},
+ {NULL},
};
static PyStructSequence_Desc app_info_desc = {
@@ -103,9 +107,10 @@ static PyObject *make_app_info(void)
if (app_info == NULL) {
return NULL;
}
-
+#if 0
#define SetIntItem(flag) \
PyStructSequence_SET_ITEM(app_info, pos++, PyLong_FromLong(flag))
+#endif
#define SetStrItem(str) \
PyStructSequence_SET_ITEM(app_info, pos++, PyUnicode_FromString(str))
#define SetBytesItem(str) \
@@ -148,7 +153,9 @@ static PyObject *make_app_info(void)
#endif
SetObjItem(BPY_app_ffmpeg_struct());
+ SetObjItem(BPY_app_build_options_struct());
SetObjItem(BPY_app_handlers_struct());
+ SetObjItem(BPY_app_translations_struct());
#undef SetIntItem
#undef SetStrItem
@@ -179,7 +186,7 @@ static int bpy_app_debug_set(PyObject *UNUSED(self), PyObject *value, void *clos
const int flag = GET_INT_FROM_POINTER(closure);
const int param = PyObject_IsTrue(value);
- if (param < 0) {
+ if (param == -1) {
PyErr_SetString(PyExc_TypeError, "bpy.app.debug can only be True/False");
return -1;
}
@@ -238,12 +245,13 @@ static PyObject *bpy_app_driver_dict_get(PyObject *UNUSED(self), void *UNUSED(cl
static PyGetSetDef bpy_app_getsets[] = {
- {(char *)"debug", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG},
- {(char *)"debug_ffmpeg", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_FFMPEG},
- {(char *)"debug_python", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_PYTHON},
- {(char *)"debug_events", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_EVENTS},
- {(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", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG},
+ {(char *)"debug_ffmpeg", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_FFMPEG},
+ {(char *)"debug_freestyle", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_FREESTYLE},
+ {(char *)"debug_python", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_PYTHON},
+ {(char *)"debug_events", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_EVENTS},
+ {(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_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},
diff --git a/source/blender/python/intern/bpy_app_build_options.c b/source/blender/python/intern/bpy_app_build_options.c
new file mode 100644
index 00000000000..60105f73f37
--- /dev/null
+++ b/source/blender/python/intern/bpy_app_build_options.c
@@ -0,0 +1,310 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_app_build_options.c
+ * \ingroup pythonintern
+ */
+
+#include <Python.h>
+#include "BLI_utildefines.h"
+
+#include "bpy_app_build_options.h"
+
+static PyTypeObject BlenderAppBuildOptionsType;
+
+static PyStructSequence_Field app_builtopts_info_fields[] = {
+ /* names mostly follow CMake options, lowercase, after WITH_ */
+ {(char *)"bullet", NULL},
+ {(char *)"codec_avi", NULL},
+ {(char *)"codec_ffmpeg", NULL},
+ {(char *)"codec_quicktime", NULL},
+ {(char *)"codec_sndfile", NULL},
+ {(char *)"compositor", NULL},
+ {(char *)"cycles", NULL},
+ {(char *)"cycles_osl", NULL},
+ {(char *)"freestyle", NULL},
+ {(char *)"gameengine", NULL},
+ {(char *)"image_cineon", NULL},
+ {(char *)"image_dds", NULL},
+ {(char *)"image_frameserver", NULL},
+ {(char *)"image_hdr", NULL},
+ {(char *)"image_openexr", NULL},
+ {(char *)"image_openjpeg", NULL},
+ {(char *)"image_redcode", NULL},
+ {(char *)"image_tiff", NULL},
+ {(char *)"input_ndof", NULL},
+ {(char *)"audaspace", NULL},
+ {(char *)"international", NULL},
+ {(char *)"openal", NULL},
+ {(char *)"sdl", NULL},
+ {(char *)"jack", NULL},
+ {(char *)"libmv", NULL},
+ {(char *)"mod_boolean", NULL},
+ {(char *)"mod_fluid", NULL},
+ {(char *)"mod_oceansim", NULL},
+ {(char *)"mod_remesh", NULL},
+ {(char *)"mod_smoke", NULL},
+ {(char *)"collada", NULL},
+ {(char *)"opencolorio", NULL},
+ {(char *)"player", NULL},
+ {NULL}
+};
+
+
+static PyStructSequence_Desc app_builtopts_info_desc = {
+ (char *)"bpy.app.build_options", /* name */
+ (char *)"This module contains information about options blender is built with", /* doc */
+ app_builtopts_info_fields, /* fields */
+ (sizeof(app_builtopts_info_fields) / sizeof(PyStructSequence_Field)) - 1
+};
+
+static PyObject *make_builtopts_info(void)
+{
+ PyObject *builtopts_info;
+ int pos = 0;
+
+ builtopts_info = PyStructSequence_New(&BlenderAppBuildOptionsType);
+ if (builtopts_info == NULL) {
+ return NULL;
+ }
+
+#define SetObjIncref(item) \
+ PyStructSequence_SET_ITEM(builtopts_info, pos++, (Py_IncRef(item), item))
+
+#ifdef WITH_BULLET
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_AVI
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_FFMPEG
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_QUICKTIME
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_SNDFILE
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_COMPOSITOR
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_CYCLES
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_CYCLES_OSL
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_FREESTYLE
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_GAMEENGINE
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_CINEON
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_DDS
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_FRAMESERVER
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_HDR
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_OPENEXR
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_OPENJPEG
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_REDCODE
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_TIFF
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_INPUT_NDOF
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_AUDASPACE
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_INTERNATIONAL
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_OPENAL
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_SDL
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_JACK
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_LIBMV
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_MOD_BOOLEAN
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_MOD_FLUID
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_OCEANSIM
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_MOD_REMESH
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_SMOKE
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_COLLADA
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_OCIO
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#ifdef WITH_PLAYER
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
+#undef SetObjIncref
+
+ return builtopts_info;
+}
+
+PyObject *BPY_app_build_options_struct(void)
+{
+ PyObject *ret;
+
+ PyStructSequence_InitType(&BlenderAppBuildOptionsType, &app_builtopts_info_desc);
+
+ ret = make_builtopts_info();
+
+ /* prevent user from creating new instances */
+ BlenderAppBuildOptionsType.tp_init = NULL;
+ BlenderAppBuildOptionsType.tp_new = NULL;
+ BlenderAppBuildOptionsType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
+
+ return ret;
+}
diff --git a/source/blender/python/intern/bpy_app_build_options.h b/source/blender/python/intern/bpy_app_build_options.h
new file mode 100644
index 00000000000..82a1417ea2c
--- /dev/null
+++ b/source/blender/python/intern/bpy_app_build_options.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_app_build_options.h
+ * \ingroup pythonintern
+ */
+
+#ifndef __BPY_APP_BUILD_OPTIONS_H__
+#define __BPY_APP_BUILD_OPTIONS_H__
+
+PyObject *BPY_app_build_options_struct(void);
+
+#endif /* __BPY_APP_BUILD_OPTIONS_H__ */
diff --git a/source/blender/python/intern/bpy_app_ffmpeg.c b/source/blender/python/intern/bpy_app_ffmpeg.c
index 5ae2a11710a..3bf3dec3872 100644
--- a/source/blender/python/intern/bpy_app_ffmpeg.c
+++ b/source/blender/python/intern/bpy_app_ffmpeg.c
@@ -41,16 +41,16 @@ static PyTypeObject BlenderAppFFmpegType;
#define DEF_FFMPEG_LIB_VERSION(lib) \
{(char *)(#lib "_version"), (char *)("The " #lib " version as a tuple of 3 numbers")}, \
- {(char *)(#lib "_version_string"), (char *)("The " #lib " version formatted as a string")},
+ {(char *)(#lib "_version_string"), (char *)("The " #lib " version formatted as a string")}
static PyStructSequence_Field app_ffmpeg_info_fields[] = {
{(char *)"supported", (char *)("Boolean, True when Blender is built with FFmpeg support")},
- DEF_FFMPEG_LIB_VERSION(avcodec)
- DEF_FFMPEG_LIB_VERSION(avdevice)
- DEF_FFMPEG_LIB_VERSION(avformat)
- DEF_FFMPEG_LIB_VERSION(avutil)
- DEF_FFMPEG_LIB_VERSION(swscale)
+ DEF_FFMPEG_LIB_VERSION(avcodec),
+ DEF_FFMPEG_LIB_VERSION(avdevice),
+ DEF_FFMPEG_LIB_VERSION(avformat),
+ DEF_FFMPEG_LIB_VERSION(avutil),
+ DEF_FFMPEG_LIB_VERSION(swscale),
{NULL}
};
diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c
new file mode 100644
index 00000000000..6f042318de2
--- /dev/null
+++ b/source/blender/python/intern/bpy_app_translations.c
@@ -0,0 +1,829 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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_app_translations.c
+ * \ingroup pythonintern
+ *
+ * This file defines a singleton py object accessed via 'bpy.app.translations',
+ * which exposes various data and functions useful in i18n work.
+ * Most notably, it allows to extend main translations with py dicts.
+ */
+
+#include <Python.h>
+/* XXX Why bloody hell isn't that included in Python.h???? */
+#include <structmember.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_string.h"
+#include "BLI_ghash.h"
+
+#include "BPY_extern.h"
+#include "bpy_app_translations.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLF_translation.h"
+
+#include "RNA_types.h"
+#include "RNA_access.h"
+
+
+typedef struct
+{
+ PyObject_HEAD
+ /* The string used to separate context from actual message in PY_TRANSLATE RNA props. */
+ const char *context_separator;
+ /* A "named tuple" (StructSequence actually...) containing all C-defined contexts. */
+ PyObject *contexts;
+ /* A readonly mapping {C context id: python id} (actually, a MappingProxy). */
+ PyObject *contexts_C_to_py;
+ /* A py dict containing all registered py dicts (order is more or less random, first match wins!). */
+ PyObject *py_messages;
+} BlenderAppTranslations;
+
+/* Our singleton instance pointer */
+static BlenderAppTranslations *_translations = NULL;
+
+#ifdef WITH_INTERNATIONAL
+
+/***** Helpers for ghash *****/
+typedef struct GHashKey {
+ const char *msgctxt;
+ const char *msgid;
+} 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->msgid = BLI_strdup(msgid);
+ return key;
+}
+
+static unsigned int _ghashutil_keyhash(const void *ptr)
+{
+ const GHashKey *key = ptr;
+ unsigned int hash = BLI_ghashutil_strhash(key->msgctxt);
+ return hash ^ BLI_ghashutil_strhash(key->msgid);
+}
+
+static int _ghashutil_keycmp(const void *a, const void *b)
+{
+ const GHashKey *A = a;
+ const GHashKey *B = b;
+
+ /* Note: comparing msgid first, most of the time it will be enough! */
+ int cmp = BLI_ghashutil_strcmp(A->msgid, B->msgid);
+ if (cmp == 0)
+ return BLI_ghashutil_strcmp(A->msgctxt, B->msgctxt);
+ return cmp;
+}
+
+static void _ghashutil_keyfree(void *ptr)
+{
+ const GHashKey *key = ptr;
+
+ /* We assume both msgctxt and msgid were BLI_strdup'ed! */
+ MEM_freeN((void *)key->msgctxt);
+ MEM_freeN((void *)key->msgid);
+ MEM_freeN((void *)key);
+}
+
+static void _ghashutil_valfree(void *ptr)
+{
+ MEM_freeN(ptr);
+}
+
+/***** Python's messages cache *****/
+
+/* We cache all messages available for a given locale from all py dicts into a single ghash.
+ * Changing of locale is not so common, while looking for a message translation is, so let's try to optimize
+ * the later as much as we can!
+ * Note changing of locale, as well as (un)registering a message dict, invalidate that cache.
+ */
+static GHash *_translations_cache = NULL;
+
+static void _clear_translations_cache(void)
+{
+ if (_translations_cache) {
+ BLI_ghash_free(_translations_cache, _ghashutil_keyfree, _ghashutil_valfree);
+ }
+ _translations_cache = NULL;
+}
+
+static void _build_translations_cache(PyObject *py_messages, const char *locale)
+{
+ PyObject *uuid, *uuid_dict;
+ Py_ssize_t pos = 0;
+ char *language = NULL, *language_country = NULL, *language_variant = NULL;
+
+ /* 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);
+
+ /* Clear the cached ghash if needed, and create a new one. */
+ _clear_translations_cache();
+ _translations_cache = BLI_ghash_new(_ghashutil_keyhash, _ghashutil_keycmp, __func__);
+
+ /* Iterate over all py dicts. */
+ while (PyDict_Next(py_messages, &pos, &uuid, &uuid_dict)) {
+ PyObject *lang_dict;
+
+#if 0
+ PyObject_Print(uuid_dict, stdout, 0);
+ printf("\n");
+#endif
+
+ /* Try to get first complete locale, then language+country, then language+variant, then only language */
+ lang_dict = PyDict_GetItemString(uuid_dict, locale);
+ if (!lang_dict && language_country) {
+ lang_dict = PyDict_GetItemString(uuid_dict, language_country);
+ locale = language_country;
+ }
+ if (!lang_dict && language_variant) {
+ lang_dict = PyDict_GetItemString(uuid_dict, language_variant);
+ locale = language_variant;
+ }
+ if (!lang_dict && language) {
+ lang_dict = PyDict_GetItemString(uuid_dict, language);
+ locale = language;
+ }
+
+ if (lang_dict) {
+ PyObject *pykey, *trans;
+ Py_ssize_t ppos = 0;
+
+ if (!PyDict_Check(lang_dict)) {
+ printf("WARNING! In translations' dict of \"");
+ PyObject_Print(uuid, stdout, Py_PRINT_RAW);
+ printf("\":\n");
+ printf(" Each language key must have a dictionary as value, \"%s\" is not valid, skipping: ",
+ locale);
+ PyObject_Print(lang_dict, stdout, Py_PRINT_RAW);
+ printf("\n");
+ continue;
+ }
+
+ /* Iterate over all translations of the found language dict, and populate our ghash cache. */
+ while (PyDict_Next(lang_dict, &ppos, &pykey, &trans)) {
+ GHashKey *key;
+ const char *msgctxt = NULL, *msgid = NULL;
+ bool invalid_key = false;
+
+ if ((PyTuple_CheckExact(pykey) == false) || (PyTuple_GET_SIZE(pykey) != 2)) {
+ invalid_key = true;
+ }
+ else {
+ PyObject *tmp = PyTuple_GET_ITEM(pykey, 0);
+ if (tmp == Py_None) {
+ msgctxt = BLF_I18NCONTEXT_DEFAULT_BPYRNA;
+ }
+ else if (PyUnicode_Check(tmp)) {
+ msgctxt = _PyUnicode_AsString(tmp);
+ }
+ else {
+ invalid_key = true;
+ }
+
+ tmp = PyTuple_GET_ITEM(pykey, 1);
+ if (PyUnicode_Check(tmp)) {
+ msgid = _PyUnicode_AsString(tmp);
+ }
+ else {
+ invalid_key = true;
+ }
+ }
+
+ if (invalid_key) {
+ printf("WARNING! In translations' dict of \"");
+ PyObject_Print(uuid, stdout, Py_PRINT_RAW);
+ printf("\", %s language:\n", locale);
+ printf(" Keys must be tuples of (msgctxt [string or None], msgid [string]), "
+ "this one is not valid, skipping: ");
+ PyObject_Print(pykey, stdout, Py_PRINT_RAW);
+ printf("\n");
+ continue;
+ }
+ if (PyUnicode_Check(trans) == false) {
+ printf("WARNING! In translations' dict of \"");
+ PyObject_Print(uuid, stdout, Py_PRINT_RAW);
+ printf("\":\n");
+ printf(" Values must be strings, this one is not valid, skipping: ");
+ PyObject_Print(trans, stdout, Py_PRINT_RAW);
+ printf("\n");
+ continue;
+ }
+
+ key = _ghashutil_keyalloc(msgctxt, msgid);
+
+ /* Do not overwrite existing keys! */
+ if (BLI_ghash_lookup(_translations_cache, (void *)key)) {
+ continue;
+ }
+
+ BLI_ghash_insert(_translations_cache, key, BLI_strdup(_PyUnicode_AsString(trans)));
+ }
+ }
+ }
+
+ /* Clean up! */
+ if (language)
+ MEM_freeN(language);
+ if (language_country)
+ MEM_freeN(language_country);
+ if (language_variant)
+ MEM_freeN(language_variant);
+}
+
+const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid)
+{
+#define STATIC_LOCALE_SIZE 32 /* Should be more than enough! */
+
+ GHashKey *key;
+ static char locale[STATIC_LOCALE_SIZE] = "";
+ const char *tmp;
+
+ /* Just in case, should never happen! */
+ if (!_translations)
+ return msgid;
+
+ tmp = BLF_lang_get();
+ if (strcmp(tmp, locale) || !_translations_cache) {
+ PyGILState_STATE _py_state;
+
+ BLI_strncpy(locale, tmp, STATIC_LOCALE_SIZE);
+
+ /* Locale changed or cache does not exist, refresh the whole cache! */
+ /* This func may be called from C (i.e. outside of python interpreter 'context'). */
+ _py_state = PyGILState_Ensure();
+
+ _build_translations_cache(_translations->py_messages, locale);
+
+ PyGILState_Release(_py_state);
+ }
+
+ /* And now, simply create the key (context, messageid) and find it in the cached dict! */
+ key = _ghashutil_keyalloc(msgctxt, msgid);
+
+ tmp = BLI_ghash_lookup(_translations_cache, key);
+
+ _ghashutil_keyfree((void *)key);
+
+ return tmp ? tmp : msgid;
+
+#undef STATIC_LOCALE_SIZE
+}
+
+#endif /* WITH_INTERNATIONAL */
+
+PyDoc_STRVAR(app_translations_py_messages_register_doc,
+".. method:: register(module_name, translations_dict)\n"
+"\n"
+" Registers an addon's UI translations.\n"
+"\n"
+" Note: Does nothing when Blender is built without internationalization support.\n"
+"\n"
+" :arg module_name: The name identifying the addon.\n"
+" :type module_name: string\n"
+" :arg translations_dict: A dictionary built like that:\n"
+" {locale: {msg_key: msg_translation, ...}, ...}\n"
+" :type translations_dict: dict\n"
+"\n"
+);
+static PyObject *app_translations_py_messages_register(BlenderAppTranslations *self, PyObject *args, PyObject *kw)
+{
+#ifdef WITH_INTERNATIONAL
+ static const char *kwlist[] = {"module_name", "translations_dict", NULL};
+ PyObject *module_name, *uuid_dict;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kw, "O!O!:bpy.app.translations.register", (char **)kwlist, &PyUnicode_Type,
+ &module_name, &PyDict_Type, &uuid_dict))
+ {
+ return NULL;
+ }
+
+ if (PyDict_Contains(self->py_messages, module_name)) {
+ PyErr_Format(PyExc_ValueError,
+ "bpy.app.translations.register: translations message cache already contains some data for "
+ "addon '%s'", (const char *)_PyUnicode_AsString(module_name));
+ return NULL;
+ }
+
+ PyDict_SetItem(self->py_messages, module_name, uuid_dict);
+
+ /* Clear cached messages dict! */
+ _clear_translations_cache();
+#else
+ (void)self;
+ (void)args;
+ (void)kw;
+#endif
+
+ /* And we are done! */
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(app_translations_py_messages_unregister_doc,
+".. method:: unregister(module_name)\n"
+"\n"
+" Unregisters an addon's UI translations.\n"
+"\n"
+" Note: Does nothing when Blender is built without internationalization support.\n"
+"\n"
+" :arg module_name: The name identifying the addon.\n"
+" :type module_name: string\n"
+"\n"
+);
+static PyObject *app_translations_py_messages_unregister(BlenderAppTranslations *self, PyObject *args, PyObject *kw)
+{
+#ifdef WITH_INTERNATIONAL
+ static const char *kwlist[] = {"module_name", NULL};
+ PyObject *module_name;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kw, "O!:bpy.app.translations.unregister", (char **)kwlist, &PyUnicode_Type,
+ &module_name))
+ {
+ return NULL;
+ }
+
+ if (PyDict_Contains(self->py_messages, module_name)) {
+ PyDict_DelItem(self->py_messages, module_name);
+ /* Clear cached messages ghash! */
+ _clear_translations_cache();
+ }
+#else
+ (void)self;
+ (void)args;
+ (void)kw;
+#endif
+
+ /* And we are done! */
+ Py_RETURN_NONE;
+}
+
+/***** C-defined contexts *****/
+/* This is always available (even when WITH_INTERNATIONAL is not defined). */
+
+static PyTypeObject BlenderAppTranslationsContextsType;
+
+static BLF_i18n_contexts_descriptor _contexts[] = BLF_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!
+ */
+static PyStructSequence_Field
+app_translations_contexts_fields[sizeof(_contexts) / sizeof(BLF_i18n_contexts_descriptor)] = {{NULL}};
+
+static PyStructSequence_Desc app_translations_contexts_desc = {
+ (char *)"bpy.app.translations.contexts", /* name */
+ (char *)"This named tuple contains all pre-defined translation contexts", /* doc */
+ app_translations_contexts_fields, /* fields */
+ (sizeof(app_translations_contexts_fields) / sizeof(PyStructSequence_Field)) - 1
+};
+
+static PyObject *app_translations_contexts_make(void)
+{
+ PyObject *translations_contexts;
+ BLF_i18n_contexts_descriptor *ctxt;
+ int pos = 0;
+
+ translations_contexts = PyStructSequence_New(&BlenderAppTranslationsContextsType);
+ if (translations_contexts == NULL) {
+ return NULL;
+ }
+
+#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)
+
+ for (ctxt = _contexts; ctxt->c_id; ctxt++) {
+ if (ctxt->value) {
+ SetObjString(ctxt->value);
+ }
+ else {
+ SetObjNone();
+ }
+ }
+
+#undef SetObjString
+#undef SetObjNone
+
+ return translations_contexts;
+}
+
+/***** Main BlenderAppTranslations Py object definition *****/
+
+PyDoc_STRVAR(app_translations_contexts_doc,
+ "A named tuple containing all pre-defined translation contexts.\n"
+ "WARNING: Never use a (new) context starting with \"" BLF_I18NCONTEXT_DEFAULT_BPYRNA "\", it would be internally "
+ "assimilated as the default one!\n"
+);
+
+PyDoc_STRVAR(app_translations_contexts_C_to_py_doc,
+ "A readonly dict mapping contexts' C-identifiers to their py-identifiers."
+);
+
+static PyMemberDef app_translations_members[] = {
+ {(char *)"contexts", T_OBJECT_EX, offsetof(BlenderAppTranslations, contexts), READONLY,
+ app_translations_contexts_doc},
+ {(char *)"contexts_C_to_py", T_OBJECT_EX, offsetof(BlenderAppTranslations, contexts_C_to_py), READONLY,
+ app_translations_contexts_C_to_py_doc},
+ {NULL}
+};
+
+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)."
+);
+static PyObject *app_translations_locale_get(PyObject *UNUSED(self), void *UNUSED(userdata))
+{
+ return PyUnicode_FromString(BLF_lang_get());
+}
+
+/* Note: defining as getter, as (even if quite unlikely), this *may* change during runtime... */
+PyDoc_STRVAR(app_translations_locales_doc, "All locales currently known by Blender (i.e. available as translations).");
+static PyObject *app_translations_locales_get(PyObject *UNUSED(self), void *UNUSED(userdata))
+{
+ PyObject *ret;
+ EnumPropertyItem *it, *items = BLF_RNA_lang_enum_properties();
+ int num_locales = 0, pos = 0;
+
+ if (items) {
+ /* This is not elegant, but simple! */
+ for (it = items; it->identifier; it++) {
+ if (it->value)
+ num_locales++;
+ }
+ }
+
+ ret = PyTuple_New(num_locales);
+
+ if (items) {
+ for (it = items; it->identifier; it++) {
+ if (it->value)
+ PyTuple_SET_ITEM(ret, pos++, PyUnicode_FromString(it->description));
+ }
+ }
+
+ return ret;
+}
+
+static PyGetSetDef app_translations_getseters[] = {
+ /* {name, getter, setter, doc, userdata} */
+ {(char *)"locale", (getter)app_translations_locale_get, NULL, app_translations_locale_doc, NULL},
+ {(char *)"locales", (getter)app_translations_locales_get, NULL, app_translations_locales_doc, NULL},
+ {NULL}
+};
+
+/* pgettext helper. */
+static PyObject *_py_pgettext(PyObject *args, PyObject *kw, const char *(*_pgettext)(const char *, const char *))
+{
+ static const char *kwlist[] = {"msgid", "msgctxt", NULL};
+
+#ifdef WITH_INTERNATIONAL
+ char *msgid, *msgctxt = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kw,
+ "s|z:bpy.app.translations.pgettext",
+ (char **)kwlist, &msgid, &msgctxt))
+ {
+ return NULL;
+ }
+
+ return PyUnicode_FromString((*_pgettext)(msgctxt ? msgctxt : BLF_I18NCONTEXT_DEFAULT, msgid));
+#else
+ PyObject *msgid, *msgctxt;
+ (void)_pgettext;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kw,
+ "O|O:bpy.app.translations.pgettext",
+ (char **)kwlist, &msgid, &msgctxt))
+ {
+ return NULL;
+ }
+
+ Py_INCREF(msgid);
+
+ return msgid;
+#endif
+}
+
+PyDoc_STRVAR(app_translations_pgettext_doc,
+".. method:: pgettext(msgid, msgctxt)\n"
+"\n"
+" Try to translate the given msgid (with optional msgctxt).\n"
+" NOTE: The (msgid, msgctxt) parameter orders has been switched compared to gettext function, to allow\n"
+" single-parameter calls (context then defaults to BLF_I18NCONTEXT_DEFAULT).\n"
+" NOTE: You should really rarely need to use this function in regular addon code, as all translation should be\n"
+" handled by Blender internal code. The only exception are string containing formatting (like \"File: %r\"),\n"
+" but you should rather use pgettext_iface/_tip in those cases!\n"
+" Note: Does nothing when Blender is built without internationalization support (hence always returns msgid).\n"
+"\n"
+" :arg msgid: The string to translate.\n"
+" :type msgid: string\n"
+" :arg msgctxt: The translation context.\n"
+" :type msgctxt: string or None\n"
+" :default msgctxt: BLF_I18NCONTEXT_DEFAULT value.\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);
+}
+
+PyDoc_STRVAR(app_translations_pgettext_iface_doc,
+".. method:: pgettext_iface(msgid, msgctxt)\n"
+"\n"
+" Try to translate the given msgid (with optional msgctxt), if labels' translation is enabled.\n"
+" NOTE: See pgettext notes.\n"
+"\n"
+" :arg msgid: The string to translate.\n"
+" :type msgid: string\n"
+" :arg msgctxt: The translation context.\n"
+" :type msgctxt: string or None\n"
+" :default msgctxt: BLF_I18NCONTEXT_DEFAULT value.\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);
+}
+
+PyDoc_STRVAR(app_translations_pgettext_tip_doc,
+".. method:: pgettext_tip(msgid, msgctxt)\n"
+"\n"
+" Try to translate the given msgid (with optional msgctxt), if tooltips' translation is enabled.\n"
+" NOTE: See pgettext notes.\n"
+"\n"
+" :arg msgid: The string to translate.\n"
+" :type msgid: string\n"
+" :arg msgctxt: The translation context.\n"
+" :type msgctxt: string or None\n"
+" :default msgctxt: BLF_I18NCONTEXT_DEFAULT value.\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);
+}
+
+PyDoc_STRVAR(app_translations_pgettext_data_doc,
+".. method:: pgettext_data(msgid, msgctxt)\n"
+"\n"
+" Try to translate the given msgid (with optional msgctxt), if new data name's translation is enabled.\n"
+" NOTE: See pgettext notes.\n"
+"\n"
+" :arg msgid: The string to translate.\n"
+" :type msgid: string\n"
+" :arg msgctxt: The translation context.\n"
+" :type msgctxt: string or None\n"
+" :default msgctxt: BLF_I18NCONTEXT_DEFAULT value.\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);
+}
+
+PyDoc_STRVAR(app_translations_locale_explode_doc,
+".. method:: locale_explode(locale)\n"
+"\n"
+" Return all components and their combinations of the given ISO locale string.\n"
+"\n"
+" >>> bpy.app.translations.locale_explode(\"sr_RS@latin\")\n"
+" (\"sr\", \"RS\", \"latin\", \"sr_RS\", \"sr@latin\")\n"
+"\n"
+" For non-complete locales, missing elements will be None.\n"
+"\n"
+" :arg locale: The ISO locale string to explode.\n"
+" :type msgid: string\n"
+" :return: A tuple (language, country, variant, language_country, language@variant).\n"
+"\n"
+);
+static PyObject *app_translations_locale_explode(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw)
+{
+ static const char *kwlist[] = {"locale", NULL};
+ const char *locale;
+ char *language, *country, *variant, *language_country, *language_variant;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kw, "s:bpy.app.translations.locale_explode", (char **)kwlist, &locale)) {
+ return NULL;
+ }
+
+ BLF_locale_explode(locale, &language, &country, &variant, &language_country, &language_variant);
+
+ return Py_BuildValue("sssss", language, country, variant, language_country, language_variant);
+}
+
+static PyMethodDef app_translations_methods[] = {
+ /* Can't use METH_KEYWORDS alone, see http://bugs.python.org/issue11587 */
+ {"register", (PyCFunction)app_translations_py_messages_register, METH_VARARGS | METH_KEYWORDS,
+ app_translations_py_messages_register_doc},
+ {"unregister", (PyCFunction)app_translations_py_messages_unregister, METH_VARARGS | METH_KEYWORDS,
+ app_translations_py_messages_unregister_doc},
+ {"pgettext", (PyCFunction)app_translations_pgettext, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
+ app_translations_pgettext_doc},
+ {"pgettext_iface", (PyCFunction)app_translations_pgettext_iface, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
+ app_translations_pgettext_iface_doc},
+ {"pgettext_tip", (PyCFunction)app_translations_pgettext_tip, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
+ app_translations_pgettext_tip_doc},
+ {"pgettext_data", (PyCFunction)app_translations_pgettext_data, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
+ app_translations_pgettext_data_doc},
+ {"locale_explode", (PyCFunction)app_translations_locale_explode, METH_VARARGS | METH_KEYWORDS | METH_STATIC,
+ app_translations_locale_explode_doc},
+ {NULL}
+};
+
+static PyObject *app_translations_new(PyTypeObject *type, PyObject *UNUSED(args), PyObject *UNUSED(kw))
+{
+/* printf("%s (%p)\n", __func__, _translations); */
+
+ if (!_translations) {
+ _translations = (BlenderAppTranslations *)type->tp_alloc(type, 0);
+ if (_translations) {
+ PyObject *py_ctxts;
+ BLF_i18n_contexts_descriptor *ctxt;
+
+ _translations->contexts = app_translations_contexts_make();
+
+ py_ctxts = PyDict_New();
+ for (ctxt = _contexts; ctxt->c_id; ctxt++) {
+ PyObject *val = PyUnicode_FromString(ctxt->py_id);
+ PyDict_SetItemString(py_ctxts, ctxt->c_id, val);
+ Py_DECREF(val);
+ }
+ _translations->contexts_C_to_py = PyDictProxy_New(py_ctxts);
+ Py_DECREF(py_ctxts); /* The actual dict is only owned by its proxy */
+
+ _translations->py_messages = PyDict_New();
+ }
+ }
+
+ return (PyObject *)_translations;
+}
+
+static void app_translations_free(void *obj)
+{
+ PyObject_Del(obj);
+#ifdef WITH_INTERNATIONAL
+ _clear_translations_cache();
+#endif
+}
+
+PyDoc_STRVAR(app_translations_doc,
+" This object contains some data/methods regarding internationalization in Blender, and allows every py script\n"
+" to feature translations for its own UI messages.\n"
+"\n"
+" WARNING: Most of this object should only be useful if you actually manipulate i18n stuff from Python.\n"
+" If you are a regular addon, you should only bother about :contexts: and :context_sep: members, and the \n"
+" :register:/:unregister: functions!"
+"\n"
+" To add translations to your python script, you must define a dictionary formatted like that:\n"
+" {locale: {msg_key: msg_translation, ...}, ...}\n"
+" where:\n"
+" locale is either a lang iso code (e.g. 'fr'), a lang+country code (e.g. 'pt_BR'),\n"
+" a lang+variant code (e.g. 'sr@latin'), or a full code (e.g. 'uz_UZ@cyrilic').\n"
+" msg_key is a tuple (context, org message) - use, as much as possible, the predefined :contexts:.\n"
+" msg_translation is the translated message in given language!"
+" Then, call bpy.app.translations.register(__name__, your_dict) in your register() function, and \n"
+" bpy.app.translations.unregister(__name__) in your unregister() one.\n"
+"\n"
+" bl_i18n_utils module has several functions to help you collect strings to translate, and generate the needed\n"
+" python code (the translation dictionary), as well as optional intermediary po files if you want some...\n"
+" See its documentation for more details.\n"
+"\n"
+);
+static PyTypeObject BlenderAppTranslationsType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ /* tp_name */
+ "bpy.app._translations_type",
+ /* tp_basicsize */
+ sizeof(BlenderAppTranslations),
+ 0, /* tp_itemsize */
+ /* methods */
+ /* No destructor, this is a singleton! */
+ NULL, /* tp_dealloc */
+ NULL, /* printfunc tp_print; */
+ NULL, /* getattrfunc tp_getattr; */
+ NULL, /* setattrfunc tp_setattr; */
+ NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */
+ NULL, /* tp_repr */
+
+ /* Method suites for standard classes */
+ NULL, /* PyNumberMethods *tp_as_number; */
+ NULL, /* PySequenceMethods *tp_as_sequence; */
+ NULL, /* PyMappingMethods *tp_as_mapping; */
+
+ /* More standard operations (here for binary compatibility) */
+ NULL, /* hashfunc tp_hash; */
+ NULL, /* ternaryfunc tp_call; */
+ NULL, /* reprfunc tp_str; */
+ NULL, /* getattrofunc tp_getattro; */
+ NULL, /* setattrofunc tp_setattro; */
+
+ /* Functions to access object as input/output buffer */
+ NULL, /* PyBufferProcs *tp_as_buffer; */
+
+ /*** Flags to define presence of optional/expanded features ***/
+ Py_TPFLAGS_DEFAULT, /* long tp_flags; */
+
+ app_translations_doc, /* char *tp_doc; Documentation string */
+
+ /*** Assigned meaning in release 2.0 ***/
+ /* call function for all accessible objects */
+ NULL, /* traverseproc tp_traverse; */
+
+ /* delete references to contained objects */
+ NULL, /* inquiry tp_clear; */
+
+ /*** Assigned meaning in release 2.1 ***/
+ /*** rich comparisons ***/
+ NULL, /* richcmpfunc tp_richcompare; */
+
+ /*** weak reference enabler ***/
+ 0, /* long tp_weaklistoffset */
+
+ /*** Added in release 2.2 ***/
+ /* Iterators */
+ NULL, /* getiterfunc tp_iter; */
+ NULL, /* iternextfunc tp_iternext; */
+
+ /*** Attribute descriptor and subclassing stuff ***/
+ app_translations_methods, /* struct PyMethodDef *tp_methods; */
+ app_translations_members, /* struct PyMemberDef *tp_members; */
+ app_translations_getseters, /* struct PyGetSetDef *tp_getset; */
+ NULL, /* struct _typeobject *tp_base; */
+ NULL, /* PyObject *tp_dict; */
+ NULL, /* descrgetfunc tp_descr_get; */
+ NULL, /* descrsetfunc tp_descr_set; */
+ 0, /* long tp_dictoffset; */
+ NULL, /* initproc tp_init; */
+ NULL, /* allocfunc tp_alloc; */
+ /* newfunc tp_new; */
+ (newfunc)app_translations_new,
+ /* Low-level free-memory routine */
+ app_translations_free, /* freefunc tp_free; */
+ /* For PyObject_IS_GC */
+ NULL, /* inquiry tp_is_gc; */
+ NULL, /* PyObject *tp_bases; */
+ /* method resolution order */
+ NULL, /* PyObject *tp_mro; */
+ NULL, /* PyObject *tp_cache; */
+ NULL, /* PyObject *tp_subclasses; */
+ NULL, /* PyObject *tp_weaklist; */
+ NULL
+};
+
+PyObject *BPY_app_translations_struct(void)
+{
+ PyObject *ret;
+
+ /* Let's finalize our contexts structseq definition! */
+ {
+ BLF_i18n_contexts_descriptor *ctxt;
+ PyStructSequence_Field *desc;
+
+ /* We really populate the contexts' fields here! */
+ for (ctxt = _contexts, desc = app_translations_contexts_desc.fields; ctxt->c_id; ctxt++, desc++) {
+ desc->name = (char *)ctxt->py_id;
+ desc->doc = NULL;
+ }
+ desc->name = desc->doc = NULL; /* End sentinel! */
+
+ PyStructSequence_InitType(&BlenderAppTranslationsContextsType, &app_translations_contexts_desc);
+ }
+
+ if (PyType_Ready(&BlenderAppTranslationsType) < 0)
+ return NULL;
+
+ ret = PyObject_CallObject((PyObject *)&BlenderAppTranslationsType, NULL);
+
+ /* prevent user from creating new instances */
+ BlenderAppTranslationsType.tp_new = NULL;
+ /* without this we can't do set(sys.modules) [#29635] */
+ BlenderAppTranslationsType.tp_hash = (hashfunc)_Py_HashPointer;
+
+ return ret;
+}
diff --git a/source/blender/python/intern/bpy_app_translations.h b/source/blender/python/intern/bpy_app_translations.h
new file mode 100644
index 00000000000..704307574d0
--- /dev/null
+++ b/source/blender/python/intern/bpy_app_translations.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_app_translations.h
+ * \ingroup pythonintern
+ */
+
+#ifndef __BPY_APP_TRANSLATIONS_H__
+#define __BPY_APP_TRANSLATIONS_H__
+
+PyObject *BPY_app_translations_struct(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 9a79616c23b..72bfda89b64 100644
--- a/source/blender/python/intern/bpy_driver.c
+++ b/source/blender/python/intern/bpy_driver.c
@@ -75,14 +75,14 @@ int bpy_pydriver_create_dict(void)
}
/* add bpy to global namespace */
- mod = PyImport_ImportModuleLevel((char *)"bpy", NULL, NULL, NULL, 0);
+ mod = PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0);
if (mod) {
PyDict_SetItemString(bpy_pydriver_Dict, "bpy", mod);
Py_DECREF(mod);
}
/* add noise to global namespace */
- mod = PyImport_ImportModuleLevel((char *)"mathutils", NULL, NULL, NULL, 0);
+ mod = PyImport_ImportModuleLevel("mathutils", NULL, NULL, NULL, 0);
if (mod) {
PyObject *modsub = PyDict_GetItemString(PyModule_GetDict(mod), "noise");
PyDict_SetItemString(bpy_pydriver_Dict, "noise", modsub);
@@ -122,7 +122,7 @@ static void bpy_pydriver_update_dict(const float evaltime)
void BPY_driver_reset(void)
{
PyGILState_STATE gilstate;
- int use_gil = TRUE; /* !PYC_INTERPRETER_ACTIVE; */
+ bool use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -175,7 +175,7 @@ float BPY_driver_exec(ChannelDriver *driver, const float evaltime)
PyObject *expr_vars; /* speed up by pre-hashing string & avoids re-converting unicode strings for every execution */
PyObject *expr_code;
PyGILState_STATE gilstate;
- int use_gil;
+ bool use_gil;
DriverVar *dvar;
double result = 0.0; /* default return */
@@ -193,7 +193,7 @@ float BPY_driver_exec(ChannelDriver *driver, const float evaltime)
return 0.0f;
}
- use_gil = TRUE; /* !PYC_INTERPRETER_ACTIVE; */
+ use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
if (use_gil)
gilstate = PyGILState_Ensure();
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index cdecf64c93c..552df561bbd 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -39,11 +39,21 @@
#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
+#include "BLI_path_util.h"
+#include "BLI_fileops.h"
+#include "BLI_listbase.h"
+#include "BLI_math_base.h"
+#include "BLI_string.h"
+#include "BLI_string_utf8.h"
+#include "BLI_threads.h"
+
#include "RNA_types.h"
#include "bpy.h"
#include "gpu.h"
#include "bpy_rna.h"
+#include "bpy_path.h"
#include "bpy_util.h"
#include "bpy_traceback.h"
#include "bpy_intern_string.h"
@@ -51,15 +61,6 @@
#include "DNA_space_types.h"
#include "DNA_text_types.h"
-#include "BLI_path_util.h"
-#include "BLI_fileops.h"
-#include "BLI_listbase.h"
-#include "BLI_math_base.h"
-#include "BLI_string.h"
-#include "BLI_string_utf8.h"
-#include "BLI_utildefines.h"
-#include "BLI_threads.h"
-
#include "BKE_context.h"
#include "BKE_text.h"
#include "BKE_main.h"
@@ -165,7 +166,7 @@ void BPY_text_free_code(Text *text)
{
if (text->compiled) {
PyGILState_STATE gilstate;
- int use_gil = !PYC_INTERPRETER_ACTIVE;
+ bool use_gil = !PYC_INTERPRETER_ACTIVE;
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -212,6 +213,7 @@ static struct _inittab bpy_internal_modules[] = {
{(char *)"mathutils", PyInit_mathutils},
// {(char *)"mathutils.geometry", PyInit_mathutils_geometry},
// {(char *)"mathutils.noise", PyInit_mathutils_noise},
+ {(char *)"_bpy_path", BPyInit__bpy_path},
{(char *)"bgl", BPyInit_bgl},
{(char *)"blf", BPyInit_blf},
{(char *)"bmesh", BPyInit_bmesh},
@@ -269,7 +271,8 @@ void BPY_python_start(int argc, const char **argv)
Py_Initialize();
/* THIS IS BAD: see http://bugs.python.org/issue16129 */
-#if 1
+ /* this clobbers the stdout on exit (no 'MEM_printmemlist_stats') */
+#if 0
/* until python provides a reliable way to set the env var */
PyRun_SimpleString("import sys, io\n"
"sys.__backup_stdio__ = sys.__stdout__, sys.__stderr__\n" /* else we loose the FD's [#32720] */
@@ -307,11 +310,33 @@ void BPY_python_start(int argc, const char **argv)
(void)argv;
/* must run before python initializes */
- PyImport_ExtendInittab(bpy_internal_modules);
+ /* broken in py3.3, load explicitly below */
+ // PyImport_ExtendInittab(bpy_internal_modules);
#endif
bpy_intern_string_init();
+
+#ifdef WITH_PYTHON_MODULE
+ {
+ /* Manually load all modules */
+ struct _inittab *inittab_item;
+ PyObject *sys_modules = PyImport_GetModuleDict();
+
+ for (inittab_item = bpy_internal_modules; inittab_item->name; inittab_item++) {
+ PyObject *mod = inittab_item->initfunc();
+ if (mod) {
+ PyDict_SetItemString(sys_modules, inittab_item->name, mod);
+ }
+ else {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ // Py_DECREF(mod); /* ideally would decref, but in this case we never want to free */
+ }
+ }
+#endif
+
/* bpy.* and lets us import it */
BPy_init_modules();
@@ -375,8 +400,8 @@ static void python_script_error_jump_text(struct Text *text)
python_script_error_jump(text->id.name + 2, &lineno, &offset);
if (lineno != -1) {
/* select the line with the error */
- txt_move_to(text, lineno - 1, INT_MAX, FALSE);
- txt_move_to(text, lineno - 1, offset, TRUE);
+ txt_move_to(text, lineno - 1, INT_MAX, false);
+ txt_move_to(text, lineno - 1, offset, true);
}
}
@@ -394,7 +419,7 @@ typedef struct {
#endif
static int python_script_exec(bContext *C, const char *fn, struct Text *text,
- struct ReportList *reports, const short do_jump)
+ struct ReportList *reports, const bool do_jump)
{
Main *bmain_old = CTX_data_main(C);
PyObject *main_mod = NULL;
@@ -511,11 +536,11 @@ static int python_script_exec(bContext *C, const char *fn, struct Text *text,
/* Can run a file or text block */
int BPY_filepath_exec(bContext *C, const char *filepath, struct ReportList *reports)
{
- return python_script_exec(C, filepath, NULL, reports, FALSE);
+ return python_script_exec(C, filepath, NULL, reports, false);
}
-int BPY_text_exec(bContext *C, struct Text *text, struct ReportList *reports, const short do_jump)
+int BPY_text_exec(bContext *C, struct Text *text, struct ReportList *reports, const bool do_jump)
{
return python_script_exec(C, NULL, text, reports, do_jump);
}
@@ -716,12 +741,12 @@ void BPY_modules_load_user(bContext *C)
int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *result)
{
PyGILState_STATE gilstate;
- int use_gil = !PYC_INTERPRETER_ACTIVE;
+ bool use_gil = !PYC_INTERPRETER_ACTIVE;
PyObject *pyctx;
PyObject *item;
PointerRNA *ptr = NULL;
- int done = FALSE;
+ bool done = false;
if (use_gil)
gilstate = PyGILState_Ensure();
@@ -740,7 +765,8 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *
//result->ptr = ((BPy_StructRNA *)item)->ptr;
CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data);
- done = TRUE;
+ CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
+ done = true;
}
else if (PySequence_Check(item)) {
PyObject *seq_fast = PySequence_Fast(item, "bpy_context_get sequence conversion");
@@ -770,12 +796,12 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *
}
Py_DECREF(seq_fast);
-
- done = TRUE;
+ CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
+ done = true;
}
}
- if (done == 0) {
+ if (done == false) {
if (item) printf("PyContext '%s' not a valid type\n", member);
else printf("PyContext '%s' not found\n", member);
}
@@ -817,7 +843,7 @@ typedef struct {
} dealloc_obj;
/* call once __file__ is set */
-void bpy_module_delay_init(PyObject *bpy_proxy)
+static void bpy_module_delay_init(PyObject *bpy_proxy)
{
const int argc = 1;
const char *argv[2];
@@ -856,6 +882,9 @@ static void dealloc_obj_dealloc(PyObject *self)
}
PyMODINIT_FUNC
+PyInit_bpy(void);
+
+PyMODINIT_FUNC
PyInit_bpy(void)
{
PyObject *bpy_proxy = PyModule_Create(&bpy_proxy_def);
@@ -899,3 +928,16 @@ static void bpy_module_free(void *UNUSED(mod))
}
#endif
+
+
+/* EVIL, define text.c functions here... */
+/* BKE_text.h */
+int text_check_identifier_unicode(const unsigned int ch)
+{
+ return (ch < 255 && text_check_identifier((char)ch)) || Py_UNICODE_ISALNUM(ch);
+}
+
+int text_check_identifier_nodigit_unicode(const unsigned int ch)
+{
+ return (ch < 255 && text_check_identifier_nodigit((char)ch)) || Py_UNICODE_ISALPHA(ch);
+}
diff --git a/source/blender/python/intern/bpy_interface_atexit.c b/source/blender/python/intern/bpy_interface_atexit.c
index 13d8cedf907..5c4f6ba327c 100644
--- a/source/blender/python/intern/bpy_interface_atexit.c
+++ b/source/blender/python/intern/bpy_interface_atexit.c
@@ -31,13 +31,13 @@
#include <Python.h>
+#include "BLI_utildefines.h"
+
#include "bpy_util.h"
#include "bpy.h" /* own include */
#include "WM_api.h"
-#include "BLI_utildefines.h"
-
static PyObject *bpy_atexit(PyObject *UNUSED(self), PyObject *UNUSED(args), PyObject *UNUSED(kw))
{
/* close down enough of blender at least not to crash */
@@ -57,7 +57,7 @@ static void atexit_func_call(const char *func_name, PyObject *atexit_func_arg)
* this is intended, but if its problematic it could be changed
* - campbell */
- PyObject *atexit_mod = PyImport_ImportModuleLevel((char *)"atexit", NULL, NULL, NULL, 0);
+ PyObject *atexit_mod = PyImport_ImportModuleLevel("atexit", NULL, NULL, NULL, 0);
PyObject *atexit_func = PyObject_GetAttrString(atexit_mod, func_name);
PyObject *args = PyTuple_New(1);
PyObject *ret;
diff --git a/source/blender/python/intern/bpy_intern_string.c b/source/blender/python/intern/bpy_intern_string.c
index 70ea57bb33f..294f230ce99 100644
--- a/source/blender/python/intern/bpy_intern_string.c
+++ b/source/blender/python/intern/bpy_intern_string.c
@@ -35,6 +35,7 @@
PyObject *bpy_intern_str_register;
PyObject *bpy_intern_str_unregister;
PyObject *bpy_intern_str_bl_rna;
+PyObject *bpy_intern_str_bl_property;
PyObject *bpy_intern_str_order;
PyObject *bpy_intern_str_attr;
PyObject *bpy_intern_str___slots__;
@@ -46,6 +47,7 @@ void bpy_intern_string_init(void)
bpy_intern_str_register = PyUnicode_FromString("register");
bpy_intern_str_unregister = PyUnicode_FromString("unregister");
bpy_intern_str_bl_rna = PyUnicode_FromString("bl_rna");
+ bpy_intern_str_bl_property = PyUnicode_FromString("bl_property");
bpy_intern_str_order = PyUnicode_FromString("order");
bpy_intern_str_attr = PyUnicode_FromString("attr");
bpy_intern_str___slots__ = PyUnicode_FromString("__slots__");
@@ -58,6 +60,7 @@ void bpy_intern_string_exit(void)
Py_DECREF(bpy_intern_str_register);
Py_DECREF(bpy_intern_str_unregister);
Py_DECREF(bpy_intern_str_bl_rna);
+ Py_DECREF(bpy_intern_str_bl_property);
Py_DECREF(bpy_intern_str_order);
Py_DECREF(bpy_intern_str_attr);
Py_DECREF(bpy_intern_str___slots__);
diff --git a/source/blender/python/intern/bpy_intern_string.h b/source/blender/python/intern/bpy_intern_string.h
index 0b7ca2cd47b..2e0d18d8b7f 100644
--- a/source/blender/python/intern/bpy_intern_string.h
+++ b/source/blender/python/intern/bpy_intern_string.h
@@ -30,6 +30,7 @@ void bpy_intern_string_exit(void);
extern PyObject *bpy_intern_str_register;
extern PyObject *bpy_intern_str_unregister;
extern PyObject *bpy_intern_str_bl_rna;
+extern PyObject *bpy_intern_str_bl_property;
extern PyObject *bpy_intern_str_order;
extern PyObject *bpy_intern_str_attr;
extern PyObject *bpy_intern_str___slots__;
diff --git a/source/blender/python/intern/bpy_library.c b/source/blender/python/intern/bpy_library.c
index 7571fe0f75e..3f66fb7b337 100644
--- a/source/blender/python/intern/bpy_library.c
+++ b/source/blender/python/intern/bpy_library.c
@@ -244,7 +244,7 @@ static PyObject *bpy_lib_enter(BPy_Library *self, PyObject *UNUSED(args))
self->blo_handle = BLO_blendhandle_from_file(self->abspath, &reports);
if (self->blo_handle == NULL) {
- if (BPy_reports_to_error(&reports, PyExc_IOError, TRUE) != -1) {
+ if (BPy_reports_to_error(&reports, PyExc_IOError, true) != -1) {
PyErr_Format(PyExc_IOError,
"load: %s failed to open blend file",
self->abspath);
@@ -411,7 +411,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
/* append, rather than linking */
if ((self->flag & FILE_LINK) == 0) {
- BKE_library_make_local(bmain, lib, 1);
+ BKE_library_make_local(bmain, lib, true);
}
}
diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c
index 55ef217e781..26c043f796f 100644
--- a/source/blender/python/intern/bpy_operator.c
+++ b/source/blender/python/intern/bpy_operator.c
@@ -35,6 +35,9 @@
#include "RNA_types.h"
+#include "BLI_utildefines.h"
+#include "BLI_string.h"
+
#include "BPY_extern.h"
#include "bpy_operator.h"
#include "bpy_operator_wrap.h"
@@ -42,9 +45,6 @@
#include "bpy_util.h"
#include "../generic/bpy_internal_import.h"
-#include "BLI_utildefines.h"
-#include "BLI_string.h"
-
#include "RNA_access.h"
#include "RNA_enum_types.h"
@@ -85,7 +85,7 @@ static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args)
if (!PyArg_ParseTuple(args, "s|Os:_bpy.ops.poll", &opname, &context_dict, &context_str))
return NULL;
- ot = WM_operatortype_find(opname, TRUE);
+ ot = WM_operatortype_find(opname, true);
if (ot == NULL) {
PyErr_Format(PyExc_AttributeError,
@@ -147,7 +147,7 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
/* note that context is an int, python does the conversion in this case */
int context = WM_OP_EXEC_DEFAULT;
- int is_undo = FALSE;
+ int is_undo = false;
/* XXX Todo, work out a better solution for passing on context,
* could make a tuple from self and pack the name and Context into it... */
@@ -164,7 +164,7 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
return NULL;
}
- ot = WM_operatortype_find(opname, TRUE);
+ ot = WM_operatortype_find(opname, true);
if (ot == NULL) {
PyErr_Format(PyExc_AttributeError,
@@ -209,7 +209,7 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
CTX_py_dict_set(C, (void *)context_dict);
Py_XINCREF(context_dict); /* so we done loose it */
- if (WM_operator_poll_context((bContext *)C, ot, context) == FALSE) {
+ if (WM_operator_poll_context((bContext *)C, ot, context) == false) {
const char *msg = CTX_wm_operator_poll_msg_get(C);
PyErr_Format(PyExc_RuntimeError,
"Operator bpy.ops.%.200s.poll() %.200s",
@@ -248,7 +248,7 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
}
#endif
- error_val = BPy_reports_to_error(reports, PyExc_RuntimeError, FALSE);
+ 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) {
@@ -328,7 +328,7 @@ static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args)
if (!PyArg_ParseTuple(args, "s|O!i:_bpy.ops.as_string", &opname, &PyDict_Type, &kw, &all_args))
return NULL;
- ot = WM_operatortype_find(opname, TRUE);
+ ot = WM_operatortype_find(opname, true);
if (ot == NULL) {
PyErr_Format(PyExc_AttributeError,
@@ -369,7 +369,7 @@ static PyObject *pyop_dir(PyObject *UNUSED(self))
GHashIterator *iter = WM_operatortype_iter();
PyObject *list = PyList_New(0), *name;
- for ( ; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
+ for ( ; BLI_ghashIterator_notDone(iter); BLI_ghashIterator_step(iter)) {
wmOperatorType *ot = BLI_ghashIterator_getValue(iter);
name = PyUnicode_FromString(ot->idname);
@@ -392,7 +392,7 @@ static PyObject *pyop_getrna(PyObject *UNUSED(self), PyObject *value)
PyErr_SetString(PyExc_TypeError, "_bpy.ops.get_rna() expects a string argument");
return NULL;
}
- ot = WM_operatortype_find(opname, TRUE);
+ ot = WM_operatortype_find(opname, true);
if (ot == NULL) {
PyErr_Format(PyExc_KeyError, "_bpy.ops.get_rna(\"%s\") not found", opname);
return NULL;
@@ -408,7 +408,7 @@ static PyObject *pyop_getrna(PyObject *UNUSED(self), PyObject *value)
pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr);
#ifdef PYRNA_FREE_SUPPORT
- pyrna->freeptr = TRUE;
+ pyrna->freeptr = true;
#endif
return (PyObject *)pyrna;
}
@@ -425,7 +425,7 @@ static PyObject *pyop_getinstance(PyObject *UNUSED(self), PyObject *value)
PyErr_SetString(PyExc_TypeError, "_bpy.ops.get_instance() expects a string argument");
return NULL;
}
- ot = WM_operatortype_find(opname, TRUE);
+ ot = WM_operatortype_find(opname, true);
if (ot == NULL) {
PyErr_Format(PyExc_KeyError, "_bpy.ops.get_instance(\"%s\") not found", opname);
return NULL;
@@ -444,7 +444,7 @@ static PyObject *pyop_getinstance(PyObject *UNUSED(self), PyObject *value)
pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr);
#ifdef PYRNA_FREE_SUPPORT
- pyrna->freeptr = TRUE;
+ pyrna->freeptr = true;
#endif
op->ptr = &pyrna->ptr;
diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c
index 1caec294aa0..65b7bf62032 100644
--- a/source/blender/python/intern/bpy_operator_wrap.c
+++ b/source/blender/python/intern/bpy_operator_wrap.c
@@ -29,23 +29,23 @@
* functionality.
*/
-
#include <Python.h>
-#include "bpy_operator_wrap.h"
+#include "BLI_utildefines.h"
+
#include "WM_api.h"
#include "WM_types.h"
-#include "BLI_utildefines.h"
-
#include "RNA_access.h"
#include "RNA_define.h"
#include "bpy_rna.h"
+#include "bpy_intern_string.h"
+#include "bpy_operator_wrap.h" /* own include */
static void operator_properties_init(wmOperatorType *ot)
{
- PyObject *py_class = ot->ext.data;
+ PyTypeObject *py_class = ot->ext.data;
RNA_struct_blender_type_set(ot->ext.srna, ot);
/* only call this so pyrna_deferred_register_class gives a useful error
@@ -57,6 +57,65 @@ static void operator_properties_init(wmOperatorType *ot)
PyErr_Print(); /* failed to register operator props */
PyErr_Clear();
}
+
+ /* set the default property: ot->prop */
+ {
+ /* picky developers will notice that 'bl_property' won't work with inheritance
+ * get direct from the dict to avoid raising a load of attribute errors (yes this isnt ideal) - campbell */
+ PyObject *py_class_dict = py_class->tp_dict;
+ PyObject *bl_property = PyDict_GetItem(py_class_dict, bpy_intern_str_bl_property);
+ const char *prop_id;
+ bool prop_raise_error;
+
+ if (bl_property) {
+ if (PyUnicode_Check(bl_property)) {
+ /* since the property is explicitly given, raise an error if its not found */
+ prop_id = _PyUnicode_AsString(bl_property);
+ prop_raise_error = true;
+ }
+ else {
+ PyErr_Format(PyExc_ValueError,
+ "%.200s.bl_property should be a string, not %.200s",
+ ot->idname, Py_TYPE(bl_property)->tp_name);
+
+ /* this could be done cleaner, for now its OK */
+ PyErr_Print();
+ PyErr_Clear();
+
+ prop_id = NULL;
+ prop_raise_error = false;
+ }
+ }
+ else {
+ /* fallback to hard-coded string (pre 2.66, could be deprecated) */
+ prop_id = "type";
+ prop_raise_error = false;
+ }
+
+ if (prop_id) {
+ PointerRNA ptr;
+ PropertyRNA *prop;
+
+ RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
+ prop = RNA_struct_find_property(&ptr, prop_id);
+ if (prop) {
+ ot->prop = prop;
+ }
+ else {
+ if (prop_raise_error) {
+ PyErr_Format(PyExc_ValueError,
+ "%.200s.bl_property '%.200s' not found",
+ ot->idname, prop_id);
+
+ /* this could be done cleaner, for now its OK */
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ }
+ }
+ }
+ /* end 'ot->prop' assignment */
+
}
void operator_wrapper(wmOperatorType *ot, void *userdata)
@@ -67,19 +126,12 @@ void operator_wrapper(wmOperatorType *ot, void *userdata)
*ot = *((wmOperatorType *)userdata);
ot->srna = srna; /* restore */
- operator_properties_init(ot);
-
- /* XXX - not nice, set the first enum as searchable, should have a way for python to set */
- {
- PointerRNA ptr;
- PropertyRNA *prop;
-
- RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
- prop = RNA_struct_find_property(&ptr, "type");
- if (prop) {
- ot->prop = prop;
- }
+ /* Use i18n context from ext.srna if possible (py operators). */
+ if (ot->ext.srna) {
+ RNA_def_struct_translation_context(ot->srna, RNA_struct_translation_context(ot->ext.srna));
}
+
+ operator_properties_init(ot);
}
void macro_wrapper(wmOperatorType *ot, void *userdata)
@@ -95,6 +147,11 @@ void macro_wrapper(wmOperatorType *ot, void *userdata)
ot->ui = data->ui;
ot->ext = data->ext;
+ /* Use i18n context from ext.srna if possible (py operators). */
+ if (ot->ext.srna) {
+ RNA_def_struct_translation_context(ot->srna, RNA_struct_translation_context(ot->ext.srna));
+ }
+
operator_properties_init(ot);
}
@@ -112,7 +169,7 @@ PyObject *PYOP_wrap_macro_define(PyObject *UNUSED(self), PyObject *args)
if (!PyArg_ParseTuple(args, "Os:_bpy.ops.macro_define", &macro, &opname))
return NULL;
- if (WM_operatortype_find(opname, TRUE) == NULL) {
+ if (WM_operatortype_find(opname, true) == NULL) {
PyErr_Format(PyExc_ValueError,
"Macro Define: '%s' is not a valid operator id",
opname);
@@ -123,7 +180,7 @@ PyObject *PYOP_wrap_macro_define(PyObject *UNUSED(self), PyObject *args)
srna = srna_from_self(macro, "Macro Define:");
macroname = RNA_struct_identifier(srna);
- ot = WM_operatortype_find(macroname, TRUE);
+ ot = WM_operatortype_find(macroname, true);
if (!ot) {
PyErr_Format(PyExc_ValueError,
diff --git a/source/blender/python/intern/bpy_path.c b/source/blender/python/intern/bpy_path.c
new file mode 100644
index 00000000000..1d554b60bbe
--- /dev/null
+++ b/source/blender/python/intern/bpy_path.c
@@ -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.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_path.c
+ * \ingroup pythonintern
+ *
+ * This file defines '_bpy_path' module, Some 'C' funtionality used by 'bpy.path'
+ */
+
+#include <Python.h>
+
+#include "BLI_utildefines.h"
+
+#include "bpy_path.h"
+
+#include "../generic/py_capi_utils.h"
+
+/* #include "IMB_imbuf_types.h" */
+extern const char *imb_ext_image[];
+extern const char *imb_ext_movie[];
+extern const char *imb_ext_audio[];
+
+/*----------------------------MODULE INIT-------------------------*/
+static struct PyModuleDef _bpy_path_module_def = {
+ PyModuleDef_HEAD_INIT,
+ "_bpy_path", /* m_name */
+ NULL, /* m_doc */
+ 0, /* m_size */
+ NULL, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
+
+PyObject *BPyInit__bpy_path(void)
+{
+ PyObject *submodule;
+
+ submodule = PyModule_Create(&_bpy_path_module_def);
+
+ PyModule_AddObject(submodule, "extensions_image", PyC_FrozenSetFromStrings(imb_ext_image));
+ PyModule_AddObject(submodule, "extensions_movie", PyC_FrozenSetFromStrings(imb_ext_movie));
+ PyModule_AddObject(submodule, "extensions_audio", PyC_FrozenSetFromStrings(imb_ext_audio));
+
+ return submodule;
+}
+
diff --git a/source/blender/python/intern/bpy_path.h b/source/blender/python/intern/bpy_path.h
new file mode 100644
index 00000000000..a0f31202264
--- /dev/null
+++ b/source/blender/python/intern/bpy_path.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.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_path.h
+ * \ingroup pythonintern
+ */
+
+
+#ifndef __BPY_PATH_H__
+#define __BPY_PATH_H__
+
+PyObject *BPyInit__bpy_path(void);
+
+#endif
diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c
index bd033736865..c330eb1549d 100644
--- a/source/blender/python/intern/bpy_props.c
+++ b/source/blender/python/intern/bpy_props.c
@@ -33,12 +33,12 @@
#include "RNA_types.h"
+#include "BLI_utildefines.h"
+
#include "bpy_props.h"
#include "bpy_rna.h"
#include "bpy_util.h"
-#include "BLI_utildefines.h"
-
#include "BKE_idprop.h"
#include "RNA_access.h"
@@ -50,9 +50,11 @@
#include "../generic/py_capi_utils.h"
/* initial definition of callback slots we'll probably have more then 1 */
-#define BPY_DATA_CB_SLOT_SIZE 1
+#define BPY_DATA_CB_SLOT_SIZE 3
#define BPY_DATA_CB_SLOT_UPDATE 0
+#define BPY_DATA_CB_SLOT_GET 1
+#define BPY_DATA_CB_SLOT_SET 2
extern BPy_StructRNA *bpy_context_module;
@@ -72,13 +74,15 @@ static EnumPropertyItem property_flag_enum_items[] = {
{0, NULL, 0, NULL, NULL}};
/* subtypes */
+/* XXX Keep in sync with rna_rna.c's property_subtype_items ???
+ * Currently it is not...
+ */
static EnumPropertyItem property_subtype_string_items[] = {
{PROP_FILEPATH, "FILE_PATH", 0, "File Path", ""},
{PROP_DIRPATH, "DIR_PATH", 0, "Directory Path", ""},
{PROP_FILENAME, "FILE_NAME", 0, "Filename", ""},
{PROP_BYTESTRING, "BYTE_STRING", 0, "Byte String", ""},
- {PROP_TRANSLATE, "TRANSLATE", 0, "Translate", ""},
- {PROP_PASSWORD, "PASSWORD", 0, "Password", 0},
+ {PROP_PASSWORD, "PASSWORD", 0, "Password", "A string that is displayed hidden ('********')"},
{PROP_NONE, "NONE", 0, "None", ""},
{0, NULL, 0, NULL, NULL}};
@@ -197,7 +201,7 @@ static void bpy_prop_update_cb(struct bContext *C, struct PointerRNA *ptr, struc
BLI_assert(py_data != NULL);
if (!is_write_ok) {
- pyrna_write_set(TRUE);
+ pyrna_write_set(true);
}
bpy_context_set(C, &gilstate);
@@ -230,25 +234,1282 @@ static void bpy_prop_update_cb(struct bContext *C, struct PointerRNA *ptr, struc
bpy_context_clear(C, &gilstate);
if (!is_write_ok) {
- pyrna_write_set(FALSE);
+ pyrna_write_set(false);
+ }
+}
+
+static int bpy_prop_boolean_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop)
+{
+ PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject *py_func;
+ PyObject *args;
+ PyObject *self;
+ PyObject *ret;
+ PyGILState_STATE gilstate;
+ bool use_gil;
+ const int is_write_ok = pyrna_write_check();
+ int value;
+
+ BLI_assert(py_data != NULL);
+
+ if (!is_write_ok) {
+ pyrna_write_set(true);
+ }
+
+ use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+
+ if (use_gil)
+ gilstate = PyGILState_Ensure();
+
+ py_func = py_data[BPY_DATA_CB_SLOT_GET];
+
+ args = PyTuple_New(1);
+ self = pyrna_struct_as_instance(ptr);
+ PyTuple_SET_ITEM(args, 0, self);
+
+ ret = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (ret == NULL) {
+ printf_func_error(py_func);
+ value = false;
+ }
+ else {
+ value = PyLong_AsLong(ret);
+
+ if (value == -1 && PyErr_Occurred()) {
+ printf_func_error(py_func);
+ value = false;
+ }
+
+ Py_DECREF(ret);
+ }
+
+ if (use_gil)
+ PyGILState_Release(gilstate);
+
+ if (!is_write_ok) {
+ pyrna_write_set(false);
+ }
+
+ return value;
+}
+
+static void bpy_prop_boolean_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, int value)
+{
+ PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject *py_func;
+ PyObject *args;
+ PyObject *self;
+ PyObject *ret;
+ PyGILState_STATE gilstate;
+ bool use_gil;
+ const int is_write_ok = pyrna_write_check();
+
+ BLI_assert(py_data != NULL);
+
+ if (!is_write_ok) {
+ pyrna_write_set(true);
+ }
+
+ use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+
+ if (use_gil)
+ gilstate = PyGILState_Ensure();
+
+ py_func = py_data[BPY_DATA_CB_SLOT_SET];
+
+ args = PyTuple_New(2);
+ self = pyrna_struct_as_instance(ptr);
+ PyTuple_SET_ITEM(args, 0, self);
+
+ PyTuple_SET_ITEM(args, 1, PyBool_FromLong(value));
+
+ ret = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (ret == NULL) {
+ printf_func_error(py_func);
+ }
+ else {
+ if (ret != Py_None) {
+ PyErr_SetString(PyExc_ValueError, "the return value must be None");
+ printf_func_error(py_func);
+ }
+
+ Py_DECREF(ret);
+ }
+
+ if (use_gil)
+ PyGILState_Release(gilstate);
+
+ if (!is_write_ok) {
+ pyrna_write_set(false);
+ }
+}
+
+static void bpy_prop_boolean_array_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, int *values)
+{
+ PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject *py_func;
+ PyObject *args;
+ PyObject *self;
+ PyObject *ret;
+ PyGILState_STATE gilstate;
+ bool use_gil;
+ const int is_write_ok = pyrna_write_check();
+ int i, len = RNA_property_array_length(ptr, prop);
+
+ BLI_assert(py_data != NULL);
+
+ if (!is_write_ok) {
+ pyrna_write_set(true);
+ }
+
+ use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+
+ if (use_gil)
+ gilstate = PyGILState_Ensure();
+
+ py_func = py_data[BPY_DATA_CB_SLOT_GET];
+
+ args = PyTuple_New(1);
+ self = pyrna_struct_as_instance(ptr);
+ PyTuple_SET_ITEM(args, 0, self);
+
+ ret = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (ret == NULL) {
+ printf_func_error(py_func);
+
+ for (i = 0; i < len; ++i)
+ values[i] = false;
+ }
+ else {
+ if (PyC_AsArray(values, ret, len, &PyBool_Type, false, "BoolVectorProperty get") == -1) {
+ printf_func_error(py_func);
+
+ for (i = 0; i < len; ++i)
+ values[i] = false;
+
+ /* PyC_AsArray decrements refcount internally on error */
+ }
+ else {
+ Py_DECREF(ret);
+ }
+ }
+
+ if (use_gil)
+ PyGILState_Release(gilstate);
+
+ if (!is_write_ok) {
+ pyrna_write_set(false);
+ }
+}
+
+static void bpy_prop_boolean_array_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, const int *values)
+{
+ PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject *py_func;
+ PyObject *args;
+ PyObject *self;
+ PyObject *ret;
+ PyObject *py_values;
+ PyGILState_STATE gilstate;
+ bool use_gil;
+ const int is_write_ok = pyrna_write_check();
+ int len = RNA_property_array_length(ptr, prop);
+
+ BLI_assert(py_data != NULL);
+
+ if (!is_write_ok) {
+ pyrna_write_set(true);
+ }
+
+ use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+
+ if (use_gil)
+ gilstate = PyGILState_Ensure();
+
+ py_func = py_data[BPY_DATA_CB_SLOT_SET];
+
+ args = PyTuple_New(2);
+ self = pyrna_struct_as_instance(ptr);
+ PyTuple_SET_ITEM(args, 0, self);
+
+ py_values = PyC_FromArray(values, len, &PyBool_Type, false, "BoolVectorProperty set");
+ if (!py_values) {
+ printf_func_error(py_func);
+ }
+ else
+ PyTuple_SET_ITEM(args, 1, py_values);
+
+ ret = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (ret == NULL) {
+ printf_func_error(py_func);
+ }
+ else {
+ if (ret != Py_None) {
+ PyErr_SetString(PyExc_ValueError, "the return value must be None");
+ printf_func_error(py_func);
+ }
+
+ Py_DECREF(ret);
+ }
+
+ if (use_gil)
+ PyGILState_Release(gilstate);
+
+ if (!is_write_ok) {
+ pyrna_write_set(false);
+ }
+}
+
+static int bpy_prop_int_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop)
+{
+ PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject *py_func;
+ PyObject *args;
+ PyObject *self;
+ PyObject *ret;
+ PyGILState_STATE gilstate;
+ bool use_gil;
+ const int is_write_ok = pyrna_write_check();
+ int value;
+
+ BLI_assert(py_data != NULL);
+
+ if (!is_write_ok) {
+ pyrna_write_set(true);
+ }
+
+ use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+
+ if (use_gil)
+ gilstate = PyGILState_Ensure();
+
+ py_func = py_data[BPY_DATA_CB_SLOT_GET];
+
+ args = PyTuple_New(1);
+ self = pyrna_struct_as_instance(ptr);
+ PyTuple_SET_ITEM(args, 0, self);
+
+ ret = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (ret == NULL) {
+ printf_func_error(py_func);
+ value = 0.0f;
+ }
+ else {
+ value = PyLong_AsLong(ret);
+
+ if (value == -1 && PyErr_Occurred()) {
+ printf_func_error(py_func);
+ value = 0;
+ }
+
+ Py_DECREF(ret);
+ }
+
+ if (use_gil)
+ PyGILState_Release(gilstate);
+
+ if (!is_write_ok) {
+ pyrna_write_set(false);
+ }
+
+ return value;
+}
+
+static void bpy_prop_int_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, int value)
+{
+ PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject *py_func;
+ PyObject *args;
+ PyObject *self;
+ PyObject *ret;
+ PyGILState_STATE gilstate;
+ bool use_gil;
+ const int is_write_ok = pyrna_write_check();
+
+ BLI_assert(py_data != NULL);
+
+ if (!is_write_ok) {
+ pyrna_write_set(true);
+ }
+
+ use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+
+ if (use_gil)
+ gilstate = PyGILState_Ensure();
+
+ py_func = py_data[BPY_DATA_CB_SLOT_SET];
+
+ args = PyTuple_New(2);
+ self = pyrna_struct_as_instance(ptr);
+ PyTuple_SET_ITEM(args, 0, self);
+
+ PyTuple_SET_ITEM(args, 1, PyLong_FromLong(value));
+
+ ret = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (ret == NULL) {
+ printf_func_error(py_func);
+ }
+ else {
+ if (ret != Py_None) {
+ PyErr_SetString(PyExc_ValueError, "the return value must be None");
+ printf_func_error(py_func);
+ }
+
+ Py_DECREF(ret);
+ }
+
+ if (use_gil)
+ PyGILState_Release(gilstate);
+
+ if (!is_write_ok) {
+ pyrna_write_set(false);
+ }
+}
+
+static void bpy_prop_int_array_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, int *values)
+{
+ PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject *py_func;
+ PyObject *args;
+ PyObject *self;
+ PyObject *ret;
+ PyGILState_STATE gilstate;
+ bool use_gil;
+ const int is_write_ok = pyrna_write_check();
+ int i, len = RNA_property_array_length(ptr, prop);
+
+ BLI_assert(py_data != NULL);
+
+ if (!is_write_ok) {
+ pyrna_write_set(true);
+ }
+
+ use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+
+ if (use_gil)
+ gilstate = PyGILState_Ensure();
+
+ py_func = py_data[BPY_DATA_CB_SLOT_GET];
+
+ args = PyTuple_New(1);
+ self = pyrna_struct_as_instance(ptr);
+ PyTuple_SET_ITEM(args, 0, self);
+
+ ret = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (ret == NULL) {
+ printf_func_error(py_func);
+
+ for (i = 0; i < len; ++i)
+ values[i] = 0;
+ }
+ else {
+ if (PyC_AsArray(values, ret, len, &PyLong_Type, false, "IntVectorProperty get") == -1) {
+ printf_func_error(py_func);
+
+ for (i = 0; i < len; ++i)
+ values[i] = 0;
+
+ /* PyC_AsArray decrements refcount internally on error */
+ }
+ else {
+ Py_DECREF(ret);
+ }
+ }
+
+ if (use_gil)
+ PyGILState_Release(gilstate);
+
+ if (!is_write_ok) {
+ pyrna_write_set(false);
+ }
+}
+
+static void bpy_prop_int_array_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, const int *values)
+{
+ PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject *py_func;
+ PyObject *args;
+ PyObject *self;
+ PyObject *ret;
+ PyObject *py_values;
+ PyGILState_STATE gilstate;
+ bool use_gil;
+ const int is_write_ok = pyrna_write_check();
+ int len = RNA_property_array_length(ptr, prop);
+
+ BLI_assert(py_data != NULL);
+
+ if (!is_write_ok) {
+ pyrna_write_set(true);
+ }
+
+ use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+
+ if (use_gil)
+ gilstate = PyGILState_Ensure();
+
+ py_func = py_data[BPY_DATA_CB_SLOT_SET];
+
+ args = PyTuple_New(2);
+ self = pyrna_struct_as_instance(ptr);
+ PyTuple_SET_ITEM(args, 0, self);
+
+ py_values = PyC_FromArray(values, len, &PyLong_Type, false, "IntVectorProperty set");
+ if (!py_values) {
+ printf_func_error(py_func);
+ }
+ else
+ PyTuple_SET_ITEM(args, 1, py_values);
+
+ ret = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (ret == NULL) {
+ printf_func_error(py_func);
+ }
+ else {
+ if (ret != Py_None) {
+ PyErr_SetString(PyExc_ValueError, "the return value must be None");
+ printf_func_error(py_func);
+ }
+
+ Py_DECREF(ret);
+ }
+
+ if (use_gil)
+ PyGILState_Release(gilstate);
+
+ if (!is_write_ok) {
+ pyrna_write_set(false);
+ }
+}
+
+static float bpy_prop_float_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop)
+{
+ PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject *py_func;
+ PyObject *args;
+ PyObject *self;
+ PyObject *ret;
+ PyGILState_STATE gilstate;
+ bool use_gil;
+ const int is_write_ok = pyrna_write_check();
+ float value;
+
+ BLI_assert(py_data != NULL);
+
+ if (!is_write_ok) {
+ pyrna_write_set(true);
+ }
+
+ use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+
+ if (use_gil)
+ gilstate = PyGILState_Ensure();
+
+ py_func = py_data[BPY_DATA_CB_SLOT_GET];
+
+ args = PyTuple_New(1);
+ self = pyrna_struct_as_instance(ptr);
+ PyTuple_SET_ITEM(args, 0, self);
+
+ ret = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (ret == NULL) {
+ printf_func_error(py_func);
+ value = 0.0f;
+ }
+ else {
+ value = PyFloat_AsDouble(ret);
+
+ if (value == -1.0f && PyErr_Occurred()) {
+ printf_func_error(py_func);
+ value = 0.0f;
+ }
+
+ Py_DECREF(ret);
+ }
+
+ if (use_gil)
+ PyGILState_Release(gilstate);
+
+ if (!is_write_ok) {
+ pyrna_write_set(false);
}
+
+ return value;
}
-static int bpy_prop_callback_check(PyObject *py_func, int argcount)
+static void bpy_prop_float_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, float value)
+{
+ PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject *py_func;
+ PyObject *args;
+ PyObject *self;
+ PyObject *ret;
+ PyGILState_STATE gilstate;
+ bool use_gil;
+ const int is_write_ok = pyrna_write_check();
+
+ BLI_assert(py_data != NULL);
+
+ if (!is_write_ok) {
+ pyrna_write_set(true);
+ }
+
+ use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+
+ if (use_gil)
+ gilstate = PyGILState_Ensure();
+
+ py_func = py_data[BPY_DATA_CB_SLOT_SET];
+
+ args = PyTuple_New(2);
+ self = pyrna_struct_as_instance(ptr);
+ PyTuple_SET_ITEM(args, 0, self);
+
+ PyTuple_SET_ITEM(args, 1, PyFloat_FromDouble(value));
+
+ ret = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (ret == NULL) {
+ printf_func_error(py_func);
+ }
+ else {
+ if (ret != Py_None) {
+ PyErr_SetString(PyExc_ValueError, "the return value must be None");
+ printf_func_error(py_func);
+ }
+
+ Py_DECREF(ret);
+ }
+
+ if (use_gil)
+ PyGILState_Release(gilstate);
+
+ if (!is_write_ok) {
+ pyrna_write_set(false);
+ }
+}
+
+static void bpy_prop_float_array_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, float *values)
+{
+ PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject *py_func;
+ PyObject *args;
+ PyObject *self;
+ PyObject *ret;
+ PyGILState_STATE gilstate;
+ bool use_gil;
+ const int is_write_ok = pyrna_write_check();
+ int i, len = RNA_property_array_length(ptr, prop);
+
+ BLI_assert(py_data != NULL);
+
+ if (!is_write_ok) {
+ pyrna_write_set(true);
+ }
+
+ use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+
+ if (use_gil)
+ gilstate = PyGILState_Ensure();
+
+ py_func = py_data[BPY_DATA_CB_SLOT_GET];
+
+ args = PyTuple_New(1);
+ self = pyrna_struct_as_instance(ptr);
+ PyTuple_SET_ITEM(args, 0, self);
+
+ ret = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (ret == NULL) {
+ printf_func_error(py_func);
+
+ for (i = 0; i < len; ++i)
+ values[i] = 0.0f;
+ }
+ else {
+ if (PyC_AsArray(values, ret, len, &PyFloat_Type, false, "FloatVectorProperty get") == -1) {
+ printf_func_error(py_func);
+
+ for (i = 0; i < len; ++i)
+ values[i] = 0.0f;
+
+ /* PyC_AsArray decrements refcount internally on error */
+ }
+ else {
+ Py_DECREF(ret);
+ }
+ }
+
+ if (use_gil)
+ PyGILState_Release(gilstate);
+
+ if (!is_write_ok) {
+ pyrna_write_set(false);
+ }
+}
+
+static void bpy_prop_float_array_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, const float *values)
+{
+ PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject *py_func;
+ PyObject *args;
+ PyObject *self;
+ PyObject *ret;
+ PyObject *py_values;
+ PyGILState_STATE gilstate;
+ bool use_gil;
+ const int is_write_ok = pyrna_write_check();
+ int len = RNA_property_array_length(ptr, prop);
+
+ BLI_assert(py_data != NULL);
+
+ if (!is_write_ok) {
+ pyrna_write_set(true);
+ }
+
+ use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+
+ if (use_gil)
+ gilstate = PyGILState_Ensure();
+
+ py_func = py_data[BPY_DATA_CB_SLOT_SET];
+
+ args = PyTuple_New(2);
+ self = pyrna_struct_as_instance(ptr);
+ PyTuple_SET_ITEM(args, 0, self);
+
+ py_values = PyC_FromArray(values, len, &PyFloat_Type, false, "FloatVectorProperty set");
+ if (!py_values) {
+ printf_func_error(py_func);
+ }
+ else
+ PyTuple_SET_ITEM(args, 1, py_values);
+
+ ret = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (ret == NULL) {
+ printf_func_error(py_func);
+ }
+ else {
+ if (ret != Py_None) {
+ PyErr_SetString(PyExc_ValueError, "the return value must be None");
+ printf_func_error(py_func);
+ }
+
+ Py_DECREF(ret);
+ }
+
+ if (use_gil)
+ PyGILState_Release(gilstate);
+
+ if (!is_write_ok) {
+ pyrna_write_set(false);
+ }
+}
+
+static void bpy_prop_string_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, char *value)
+{
+ PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject *py_func;
+ PyObject *args;
+ PyObject *self;
+ PyObject *ret;
+ PyGILState_STATE gilstate;
+ bool use_gil;
+ const int is_write_ok = pyrna_write_check();
+
+ BLI_assert(py_data != NULL);
+
+ if (!is_write_ok) {
+ pyrna_write_set(true);
+ }
+
+ use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+
+ if (use_gil)
+ gilstate = PyGILState_Ensure();
+
+ py_func = py_data[BPY_DATA_CB_SLOT_GET];
+
+ args = PyTuple_New(1);
+ self = pyrna_struct_as_instance(ptr);
+ PyTuple_SET_ITEM(args, 0, self);
+
+ ret = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (ret == NULL) {
+ printf_func_error(py_func);
+ value[0] = '\0';
+ }
+ else if (!PyUnicode_Check(ret)) {
+ PyErr_Format(PyExc_TypeError,
+ "return value must be a string, not %.200s",
+ Py_TYPE(ret)->tp_name);
+ printf_func_error(py_func);
+ value[0] = '\0';
+ Py_DECREF(ret);
+ }
+ else {
+ Py_ssize_t length;
+ const char *buffer = _PyUnicode_AsStringAndSize(ret, &length);
+ memcpy(value, buffer, length + 1);
+ Py_DECREF(ret);
+ }
+
+ if (use_gil)
+ PyGILState_Release(gilstate);
+
+ if (!is_write_ok) {
+ pyrna_write_set(false);
+ }
+}
+
+static int bpy_prop_string_length_cb(struct PointerRNA *ptr, struct PropertyRNA *prop)
+{
+ PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject *py_func;
+ PyObject *args;
+ PyObject *self;
+ PyObject *ret;
+ PyGILState_STATE gilstate;
+ bool use_gil;
+ const int is_write_ok = pyrna_write_check();
+ int length;
+
+ BLI_assert(py_data != NULL);
+
+ if (!is_write_ok) {
+ pyrna_write_set(true);
+ }
+
+ use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+
+ if (use_gil)
+ gilstate = PyGILState_Ensure();
+
+ py_func = py_data[BPY_DATA_CB_SLOT_GET];
+
+ args = PyTuple_New(1);
+ self = pyrna_struct_as_instance(ptr);
+ PyTuple_SET_ITEM(args, 0, self);
+
+ ret = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (ret == NULL) {
+ printf_func_error(py_func);
+ length = 0;
+ }
+ else if (!PyUnicode_Check(ret)) {
+ PyErr_Format(PyExc_TypeError,
+ "return value must be a string, not %.200s",
+ Py_TYPE(ret)->tp_name);
+ printf_func_error(py_func);
+ length = 0;
+ Py_DECREF(ret);
+ }
+ else {
+ Py_ssize_t length_ssize_t = 0;
+ _PyUnicode_AsStringAndSize(ret, &length_ssize_t);
+ length = length_ssize_t;
+ Py_DECREF(ret);
+ }
+
+ if (use_gil)
+ PyGILState_Release(gilstate);
+
+ if (!is_write_ok) {
+ pyrna_write_set(false);
+ }
+
+ return length;
+}
+
+static void bpy_prop_string_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, const char *value)
+{
+ PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject *py_func;
+ PyObject *args;
+ PyObject *self;
+ PyObject *ret;
+ PyGILState_STATE gilstate;
+ bool use_gil;
+ const int is_write_ok = pyrna_write_check();
+ PyObject *py_value;
+
+ BLI_assert(py_data != NULL);
+
+ if (!is_write_ok) {
+ pyrna_write_set(true);
+ }
+
+ use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+
+ if (use_gil)
+ gilstate = PyGILState_Ensure();
+
+ py_func = py_data[BPY_DATA_CB_SLOT_SET];
+
+ args = PyTuple_New(2);
+ self = pyrna_struct_as_instance(ptr);
+ PyTuple_SET_ITEM(args, 0, self);
+
+ py_value = PyUnicode_FromString(value);
+ if (!py_value) {
+ PyErr_SetString(PyExc_ValueError, "the return value must be a string");
+ printf_func_error(py_func);
+ }
+ else
+ PyTuple_SET_ITEM(args, 1, py_value);
+
+ ret = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (ret == NULL) {
+ printf_func_error(py_func);
+ }
+ else {
+ if (ret != Py_None) {
+ PyErr_SetString(PyExc_ValueError, "the return value must be None");
+ printf_func_error(py_func);
+ }
+
+ Py_DECREF(ret);
+ }
+
+ if (use_gil)
+ PyGILState_Release(gilstate);
+
+ if (!is_write_ok) {
+ pyrna_write_set(false);
+ }
+}
+
+static int bpy_prop_enum_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop)
+{
+ PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject *py_func;
+ PyObject *args;
+ PyObject *self;
+ PyObject *ret;
+ PyGILState_STATE gilstate;
+ bool use_gil;
+ const int is_write_ok = pyrna_write_check();
+ int value;
+
+ BLI_assert(py_data != NULL);
+
+ if (!is_write_ok) {
+ pyrna_write_set(true);
+ }
+
+ use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+
+ if (use_gil)
+ gilstate = PyGILState_Ensure();
+
+ py_func = py_data[BPY_DATA_CB_SLOT_GET];
+
+ args = PyTuple_New(1);
+ self = pyrna_struct_as_instance(ptr);
+ PyTuple_SET_ITEM(args, 0, self);
+
+ ret = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (ret == NULL) {
+ printf_func_error(py_func);
+ value = RNA_property_enum_get_default(ptr, prop);
+ }
+ else {
+ value = PyLong_AsLong(ret);
+
+ if (value == -1 && PyErr_Occurred()) {
+ printf_func_error(py_func);
+ value = RNA_property_enum_get_default(ptr, prop);
+ }
+
+ Py_DECREF(ret);
+ }
+
+ if (use_gil)
+ PyGILState_Release(gilstate);
+
+ if (!is_write_ok) {
+ pyrna_write_set(false);
+ }
+
+ return value;
+}
+
+static void bpy_prop_enum_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, int value)
+{
+ PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop);
+ PyObject *py_func;
+ PyObject *args;
+ PyObject *self;
+ PyObject *ret;
+ PyGILState_STATE gilstate;
+ bool use_gil;
+ const int is_write_ok = pyrna_write_check();
+
+ BLI_assert(py_data != NULL);
+
+ if (!is_write_ok) {
+ pyrna_write_set(true);
+ }
+
+ use_gil = true; /* !PYC_INTERPRETER_ACTIVE; */
+
+ if (use_gil)
+ gilstate = PyGILState_Ensure();
+
+ py_func = py_data[BPY_DATA_CB_SLOT_SET];
+
+ args = PyTuple_New(2);
+ self = pyrna_struct_as_instance(ptr);
+ PyTuple_SET_ITEM(args, 0, self);
+
+ PyTuple_SET_ITEM(args, 1, PyLong_FromLong(value));
+
+ ret = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (ret == NULL) {
+ printf_func_error(py_func);
+ }
+ else {
+ if (ret != Py_None) {
+ PyErr_SetString(PyExc_ValueError, "the return value must be None");
+ printf_func_error(py_func);
+ }
+
+ Py_DECREF(ret);
+ }
+
+ if (use_gil)
+ PyGILState_Release(gilstate);
+
+ if (!is_write_ok) {
+ pyrna_write_set(false);
+ }
+}
+
+/* utility function we need for parsing int's in an if statement */
+static int py_long_as_int(PyObject *py_long, int *r_int)
+{
+ if (PyLong_CheckExact(py_long)) {
+ *r_int = (int)PyLong_AS_LONG(py_long);
+ return 0;
+ }
+ else {
+ return -1;
+ }
+}
+
+#if 0
+/* copies orig to buf, then sets orig to buf, returns copy length */
+static size_t strswapbufcpy(char *buf, const char **orig)
+{
+ const char *src = *orig;
+ char *dst = buf;
+ size_t i = 0;
+ *orig = buf;
+ while ((*dst = *src)) { dst++; src++; i++; }
+ return i + 1; /* include '\0' */
+}
+#endif
+
+static int icon_id_from_name(const char *name)
+{
+ EnumPropertyItem *item;
+ int id;
+
+ if (name[0]) {
+ for (item = icon_items, id = 0; item->identifier; item++, id++) {
+ if (STREQ(item->name, name)) {
+ return item->value;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, int *defvalue, const short is_enum_flag)
+{
+ EnumPropertyItem *items;
+ PyObject *item;
+ const Py_ssize_t seq_len = PySequence_Fast_GET_SIZE(seq_fast);
+ Py_ssize_t totbuf = 0;
+ int i;
+ short def_used = 0;
+ const char *def_cmp = NULL;
+
+ if (is_enum_flag) {
+ if (seq_len > RNA_ENUM_BITFLAG_SIZE) {
+ PyErr_SetString(PyExc_TypeError,
+ "EnumProperty(...): maximum "
+ STRINGIFY(RNA_ENUM_BITFLAG_SIZE)
+ " members for a ENUM_FLAG type property");
+ return NULL;
+ }
+ if (def && !PySet_Check(def)) {
+ PyErr_Format(PyExc_TypeError,
+ "EnumProperty(...): default option must be a 'set' "
+ "type when ENUM_FLAG is enabled, not a '%.200s'",
+ Py_TYPE(def)->tp_name);
+ return NULL;
+ }
+ }
+ else {
+ if (def) {
+ def_cmp = _PyUnicode_AsString(def);
+ if (def_cmp == NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "EnumProperty(...): default option must be a 'str' "
+ "type when ENUM_FLAG is disabled, not a '%.200s'",
+ Py_TYPE(def)->tp_name);
+ return NULL;
+ }
+ }
+ }
+
+ /* blank value */
+ *defvalue = 0;
+
+ items = MEM_callocN(sizeof(EnumPropertyItem) * (seq_len + 1), "enum_items_from_py1");
+
+ for (i = 0; i < seq_len; i++) {
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ const char *tmp_icon = NULL;
+ Py_ssize_t item_size;
+ Py_ssize_t id_str_size;
+ Py_ssize_t name_str_size;
+ Py_ssize_t desc_str_size;
+
+ item = PySequence_Fast_GET_ITEM(seq_fast, i);
+
+ if ((PyTuple_CheckExact(item)) &&
+ (item_size = PyTuple_GET_SIZE(item)) &&
+ (item_size >= 3 && item_size <= 5) &&
+ (tmp.identifier = _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 0), &id_str_size)) &&
+ (tmp.name = _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 1), &name_str_size)) &&
+ (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))) &&
+ py_long_as_int(PyTuple_GET_ITEM(item, 4), &tmp.value) != -1)))
+ {
+ if (is_enum_flag) {
+ if (item_size < 4) {
+ tmp.value = 1 << i;
+ }
+
+ if (def && PySet_Contains(def, PyTuple_GET_ITEM(item, 0))) {
+ *defvalue |= tmp.value;
+ def_used++;
+ }
+ }
+ else {
+ if (item_size < 4) {
+ tmp.value = i;
+ }
+
+ if (def && def_used == 0 && STREQ(def_cmp, tmp.identifier)) {
+ *defvalue = tmp.value;
+ def_used++; /* only ever 1 */
+ }
+ }
+
+ if (tmp_icon)
+ tmp.icon = icon_id_from_name(tmp_icon);
+
+ items[i] = tmp;
+
+ /* calculate combine string length */
+ totbuf += id_str_size + name_str_size + desc_str_size + 3; /* 3 is for '\0's */
+ }
+ else {
+ MEM_freeN(items);
+ PyErr_SetString(PyExc_TypeError,
+ "EnumProperty(...): expected a tuple containing "
+ "(identifier, name, description) and optionally an "
+ "icon name and unique number");
+ return NULL;
+ }
+
+ }
+
+ if (is_enum_flag) {
+ /* strict check that all set members were used */
+ if (def && def_used != PySet_GET_SIZE(def)) {
+ MEM_freeN(items);
+
+ PyErr_Format(PyExc_TypeError,
+ "EnumProperty(..., default={...}): set has %d unused member(s)",
+ PySet_GET_SIZE(def) - def_used);
+ return NULL;
+ }
+ }
+ else {
+ if (def && def_used == 0) {
+ MEM_freeN(items);
+
+ PyErr_Format(PyExc_TypeError,
+ "EnumProperty(..., default=\'%s\'): not found in enum members",
+ def_cmp);
+ return NULL;
+ }
+ }
+
+ /* disabled duplicating strings because the array can still be freed and
+ * the strings from it referenced, for now we can't support dynamically
+ * created strings from python. */
+#if 0
+ /* this would all work perfectly _but_ the python strings may be freed
+ * immediately after use, so we need to duplicate them, ugh.
+ * annoying because it works most of the time without this. */
+ {
+ EnumPropertyItem *items_dup = MEM_mallocN((sizeof(EnumPropertyItem) * (seq_len + 1)) + (sizeof(char) * totbuf),
+ "enum_items_from_py2");
+ EnumPropertyItem *items_ptr = items_dup;
+ char *buf = ((char *)items_dup) + (sizeof(EnumPropertyItem) * (seq_len + 1));
+ memcpy(items_dup, items, sizeof(EnumPropertyItem) * (seq_len + 1));
+ for (i = 0; i < seq_len; i++, items_ptr++) {
+ buf += strswapbufcpy(buf, &items_ptr->identifier);
+ buf += strswapbufcpy(buf, &items_ptr->name);
+ buf += strswapbufcpy(buf, &items_ptr->description);
+ }
+ MEM_freeN(items);
+ items = items_dup;
+ }
+ /* end string duplication */
+#endif
+
+ return items;
+}
+
+static EnumPropertyItem *bpy_prop_enum_itemf_cb(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, int *free)
+{
+ PyGILState_STATE gilstate;
+
+ PyObject *py_func = RNA_property_enum_py_data_get(prop);
+ PyObject *self = NULL;
+ PyObject *args;
+ PyObject *items; /* returned from the function call */
+
+ EnumPropertyItem *eitems = NULL;
+ int err = 0;
+
+ bpy_context_set(C, &gilstate);
+
+ 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);
+
+ items = PyObject_CallObject(py_func, args);
+
+ Py_DECREF(args);
+
+ if (items == NULL) {
+ err = -1;
+ }
+ else {
+ PyObject *items_fast;
+ int defvalue_dummy = 0;
+
+ if (!(items_fast = PySequence_Fast(items, "EnumProperty(...): "
+ "return value from the callback was not a sequence")))
+ {
+ err = -1;
+ }
+ else {
+ eitems = enum_items_from_py(items_fast, NULL, &defvalue_dummy,
+ (RNA_property_flag(prop) & PROP_ENUM_FLAG) != 0);
+
+ Py_DECREF(items_fast);
+
+ if (!eitems) {
+ err = -1;
+ }
+ }
+
+ Py_DECREF(items);
+ }
+
+ if (err != -1) { /* worked */
+ *free = 1;
+ }
+ else {
+ printf_func_error(py_func);
+
+ eitems = DummyRNA_NULL_items;
+ }
+
+
+ bpy_context_clear(C, &gilstate);
+ return eitems;
+}
+
+static int bpy_prop_callback_check(PyObject *py_func, const char *keyword, int argcount)
{
if (py_func && py_func != Py_None) {
if (!PyFunction_Check(py_func)) {
PyErr_Format(PyExc_TypeError,
- "update keyword: expected a function type, not a %.200s",
- Py_TYPE(py_func)->tp_name);
+ "%s keyword: expected a function type, not a %.200s",
+ keyword, Py_TYPE(py_func)->tp_name);
return -1;
}
else {
PyCodeObject *f_code = (PyCodeObject *)PyFunction_GET_CODE(py_func);
if (f_code->co_argcount != argcount) {
PyErr_Format(PyExc_TypeError,
- "update keyword: expected a function taking %d arguments, not %d",
- argcount, f_code->co_argcount);
+ "%s keyword: expected a function taking %d arguments, not %d",
+ keyword, argcount, f_code->co_argcount);
return -1;
}
}
@@ -257,32 +1518,215 @@ static int bpy_prop_callback_check(PyObject *py_func, int argcount)
return 0;
}
+static PyObject **bpy_prop_py_data_get(struct PropertyRNA *prop)
+{
+ PyObject **py_data = RNA_property_py_data_get(prop);
+ if (!py_data) {
+ py_data = MEM_callocN(sizeof(PyObject *) * BPY_DATA_CB_SLOT_SIZE, __func__);
+ RNA_def_py_data(prop, py_data);
+ }
+ return py_data;
+}
-static int bpy_prop_callback_assign(struct PropertyRNA *prop, PyObject *update_cb)
+static void bpy_prop_callback_assign_update(struct PropertyRNA *prop, PyObject *update_cb)
{
/* assume this is already checked for type and arg length */
if (update_cb && update_cb != Py_None) {
- PyObject **py_data = MEM_callocN(sizeof(PyObject *) * BPY_DATA_CB_SLOT_SIZE, __func__);
+ PyObject **py_data = bpy_prop_py_data_get(prop);
+
RNA_def_property_update_runtime(prop, (void *)bpy_prop_update_cb);
py_data[BPY_DATA_CB_SLOT_UPDATE] = update_cb;
- RNA_def_py_data(prop, py_data);
RNA_def_property_flag(prop, PROP_CONTEXT_PROPERTY_UPDATE);
}
+}
- return 0;
+static void bpy_prop_callback_assign_boolean(struct PropertyRNA *prop, PyObject *get_cb, PyObject *set_cb)
+{
+ BooleanPropertyGetFunc rna_get_cb = NULL;
+ BooleanPropertySetFunc rna_set_cb = NULL;
+
+ if (get_cb && get_cb != Py_None) {
+ PyObject **py_data = bpy_prop_py_data_get(prop);
+
+ rna_get_cb = bpy_prop_boolean_get_cb;
+ py_data[BPY_DATA_CB_SLOT_GET] = get_cb;
+ }
+
+ if (set_cb && set_cb != Py_None) {
+ PyObject **py_data = bpy_prop_py_data_get(prop);
+
+ rna_set_cb = bpy_prop_boolean_set_cb;
+ py_data[BPY_DATA_CB_SLOT_SET] = set_cb;
+ }
+
+ RNA_def_property_boolean_funcs_runtime(prop, rna_get_cb, rna_set_cb);
}
-/* utility function we need for parsing int's in an if statement */
-static int py_long_as_int(PyObject *py_long, int *r_int)
+static void bpy_prop_callback_assign_boolean_array(struct PropertyRNA *prop, PyObject *get_cb, PyObject *set_cb)
{
- if (PyLong_CheckExact(py_long)) {
- *r_int = (int)PyLong_AS_LONG(py_long);
- return 0;
+ BooleanArrayPropertyGetFunc rna_get_cb = NULL;
+ BooleanArrayPropertySetFunc rna_set_cb = NULL;
+
+ if (get_cb && get_cb != Py_None) {
+ PyObject **py_data = bpy_prop_py_data_get(prop);
+
+ rna_get_cb = bpy_prop_boolean_array_get_cb;
+ py_data[BPY_DATA_CB_SLOT_GET] = get_cb;
}
- else {
- return -1;
+
+ if (set_cb && set_cb != Py_None) {
+ PyObject **py_data = bpy_prop_py_data_get(prop);
+
+ rna_set_cb = bpy_prop_boolean_array_set_cb;
+ py_data[BPY_DATA_CB_SLOT_SET] = set_cb;
+ }
+
+ RNA_def_property_boolean_array_funcs_runtime(prop, rna_get_cb, rna_set_cb);
+}
+
+static void bpy_prop_callback_assign_int(struct PropertyRNA *prop, PyObject *get_cb, PyObject *set_cb)
+{
+ IntPropertyGetFunc rna_get_cb = NULL;
+ IntPropertySetFunc rna_set_cb = NULL;
+
+ if (get_cb && get_cb != Py_None) {
+ PyObject **py_data = bpy_prop_py_data_get(prop);
+
+ rna_get_cb = bpy_prop_int_get_cb;
+ py_data[BPY_DATA_CB_SLOT_GET] = get_cb;
+ }
+
+ if (set_cb && set_cb != Py_None) {
+ PyObject **py_data = bpy_prop_py_data_get(prop);
+
+ rna_set_cb = bpy_prop_int_set_cb;
+ py_data[BPY_DATA_CB_SLOT_SET] = set_cb;
+ }
+
+ RNA_def_property_int_funcs_runtime(prop, rna_get_cb, rna_set_cb, NULL);
+}
+
+static void bpy_prop_callback_assign_int_array(struct PropertyRNA *prop, PyObject *get_cb, PyObject *set_cb)
+{
+ IntArrayPropertyGetFunc rna_get_cb = NULL;
+ IntArrayPropertySetFunc rna_set_cb = NULL;
+
+ if (get_cb && get_cb != Py_None) {
+ PyObject **py_data = bpy_prop_py_data_get(prop);
+
+ rna_get_cb = bpy_prop_int_array_get_cb;
+ py_data[BPY_DATA_CB_SLOT_GET] = get_cb;
+ }
+
+ if (set_cb && set_cb != Py_None) {
+ PyObject **py_data = bpy_prop_py_data_get(prop);
+
+ rna_set_cb = bpy_prop_int_array_set_cb;
+ py_data[BPY_DATA_CB_SLOT_SET] = set_cb;
}
+
+ RNA_def_property_int_array_funcs_runtime(prop, rna_get_cb, rna_set_cb, NULL);
+}
+
+static void bpy_prop_callback_assign_float(struct PropertyRNA *prop, PyObject *get_cb, PyObject *set_cb)
+{
+ FloatPropertyGetFunc rna_get_cb = NULL;
+ FloatPropertySetFunc rna_set_cb = NULL;
+
+ if (get_cb && get_cb != Py_None) {
+ PyObject **py_data = bpy_prop_py_data_get(prop);
+
+ rna_get_cb = bpy_prop_float_get_cb;
+ py_data[BPY_DATA_CB_SLOT_GET] = get_cb;
+ }
+
+ if (set_cb && set_cb != Py_None) {
+ PyObject **py_data = bpy_prop_py_data_get(prop);
+
+ rna_set_cb = bpy_prop_float_set_cb;
+ py_data[BPY_DATA_CB_SLOT_SET] = set_cb;
+ }
+
+ RNA_def_property_float_funcs_runtime(prop, rna_get_cb, rna_set_cb, NULL);
+}
+
+static void bpy_prop_callback_assign_float_array(struct PropertyRNA *prop, PyObject *get_cb, PyObject *set_cb)
+{
+ FloatArrayPropertyGetFunc rna_get_cb = NULL;
+ FloatArrayPropertySetFunc rna_set_cb = NULL;
+
+ if (get_cb && get_cb != Py_None) {
+ PyObject **py_data = bpy_prop_py_data_get(prop);
+
+ rna_get_cb = bpy_prop_float_array_get_cb;
+ py_data[BPY_DATA_CB_SLOT_GET] = get_cb;
+ }
+
+ if (set_cb && set_cb != Py_None) {
+ PyObject **py_data = bpy_prop_py_data_get(prop);
+
+ rna_set_cb = bpy_prop_float_array_set_cb;
+ py_data[BPY_DATA_CB_SLOT_SET] = set_cb;
+ }
+
+ RNA_def_property_float_array_funcs_runtime(prop, rna_get_cb, rna_set_cb, NULL);
+}
+
+static void bpy_prop_callback_assign_string(struct PropertyRNA *prop, PyObject *get_cb, PyObject *set_cb)
+{
+ StringPropertyGetFunc rna_get_cb = NULL;
+ StringPropertyLengthFunc rna_length_cb = NULL;
+ StringPropertySetFunc rna_set_cb = NULL;
+
+ if (get_cb && get_cb != Py_None) {
+ PyObject **py_data = bpy_prop_py_data_get(prop);
+
+ rna_get_cb = bpy_prop_string_get_cb;
+ rna_length_cb = bpy_prop_string_length_cb;
+ py_data[BPY_DATA_CB_SLOT_GET] = get_cb;
+ }
+
+ if (set_cb && set_cb != Py_None) {
+ PyObject **py_data = bpy_prop_py_data_get(prop);
+
+ rna_set_cb = bpy_prop_string_set_cb;
+ py_data[BPY_DATA_CB_SLOT_SET] = set_cb;
+ }
+
+ RNA_def_property_string_funcs_runtime(prop, rna_get_cb, rna_length_cb, rna_set_cb);
+}
+
+static void bpy_prop_callback_assign_enum(struct PropertyRNA *prop, PyObject *get_cb, PyObject *set_cb, PyObject *itemf_cb)
+{
+ EnumPropertyGetFunc rna_get_cb = NULL;
+ EnumPropertyItemFunc rna_itemf_cb = NULL;
+ EnumPropertySetFunc rna_set_cb = NULL;
+
+ if (get_cb && get_cb != Py_None) {
+ PyObject **py_data = bpy_prop_py_data_get(prop);
+
+ rna_get_cb = bpy_prop_enum_get_cb;
+ py_data[BPY_DATA_CB_SLOT_GET] = get_cb;
+ }
+
+ if (set_cb && set_cb != Py_None) {
+ PyObject **py_data = bpy_prop_py_data_get(prop);
+
+ rna_set_cb = bpy_prop_enum_set_cb;
+ py_data[BPY_DATA_CB_SLOT_SET] = set_cb;
+ }
+
+ if (itemf_cb && itemf_cb != Py_None) {
+ rna_itemf_cb = bpy_prop_enum_itemf_cb;
+ RNA_def_property_enum_py_data(prop, (void *)itemf_cb);
+
+ /* watch out!, if a user is tricky they can probably crash blender
+ * if they manage to free the callback, take care! */
+ /* Py_INCREF(itemf_cb); */
+ }
+
+ RNA_def_property_enum_funcs_runtime(prop, rna_get_cb, rna_set_cb, rna_itemf_cb);
}
/* this define runs at the start of each function and deals with
@@ -386,7 +1830,9 @@ PyDoc_STRVAR(BPy_BoolProperty_doc,
"default=False, "
"options={'ANIMATABLE'}, "
"subtype='NONE', "
- "update=None)\n"
+ "update=None, "
+ "get=None, "
+ "set=None)\n"
"\n"
" Returns a new boolean property definition.\n"
"\n"
@@ -406,7 +1852,7 @@ static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
if (srna) {
static const char *kwlist[] = {"attr", "name", "description", "default",
- "options", "subtype", "update", NULL};
+ "options", "subtype", "update", "get", "set", NULL};
const char *id = NULL, *name = NULL, *description = "";
int id_len;
int def = 0;
@@ -416,20 +1862,28 @@ static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
char *pysubtype = NULL;
int subtype = PROP_NONE;
PyObject *update_cb = NULL;
+ PyObject *get_cb = NULL;
+ PyObject *set_cb = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kw,
- "s#|ssiO!sO:BoolProperty",
+ "s#|ssiO!sOOO:BoolProperty",
(char **)kwlist, &id, &id_len,
&name, &description, &def,
&PySet_Type, &pyopts, &pysubtype,
- &update_cb))
+ &update_cb, &get_cb, &set_cb))
{
return NULL;
}
BPY_PROPDEF_SUBTYPE_CHECK(BoolProperty, property_flag_items, property_subtype_number_items);
- if (bpy_prop_callback_check(update_cb, 2) == -1) {
+ if (bpy_prop_callback_check(update_cb, "update", 2) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(get_cb, "get", 1) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(set_cb, "set", 2) == -1) {
return NULL;
}
@@ -443,7 +1897,8 @@ static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
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_callback_assign(prop, update_cb);
+ bpy_prop_callback_assign_update(prop, update_cb);
+ bpy_prop_callback_assign_boolean(prop, get_cb, set_cb);
RNA_def_property_duplicate_pointers(srna, prop);
}
@@ -457,7 +1912,9 @@ PyDoc_STRVAR(BPy_BoolVectorProperty_doc,
"options={'ANIMATABLE'}, "
"subtype='NONE', "
"size=3, "
- "update=None)\n"
+ "update=None, "
+ "get=None, "
+ "set=None)\n"
"\n"
" Returns a new vector boolean property definition.\n"
"\n"
@@ -483,7 +1940,7 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject
if (srna) {
static const char *kwlist[] = {"attr", "name", "description", "default",
- "options", "subtype", "size", "update", NULL};
+ "options", "subtype", "size", "update", "get", "set", NULL};
const char *id = NULL, *name = NULL, *description = "";
int id_len;
int def[PYRNA_STACK_ARRAY] = {0};
@@ -495,13 +1952,15 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject
char *pysubtype = NULL;
int subtype = PROP_NONE;
PyObject *update_cb = NULL;
+ PyObject *get_cb = NULL;
+ PyObject *set_cb = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kw,
- "s#|ssOO!siO:BoolVectorProperty",
+ "s#|ssOO!siOOO:BoolVectorProperty",
(char **)kwlist, &id, &id_len,
&name, &description, &pydef,
&PySet_Type, &pyopts, &pysubtype, &size,
- &update_cb))
+ &update_cb, &get_cb, &set_cb))
{
return NULL;
}
@@ -515,10 +1974,16 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject
return NULL;
}
- if (pydef && PyC_AsArray(def, pydef, size, &PyBool_Type, FALSE, "BoolVectorProperty(default=sequence)") < 0)
+ if (pydef && PyC_AsArray(def, pydef, size, &PyBool_Type, false, "BoolVectorProperty(default=sequence)") == -1)
return NULL;
- if (bpy_prop_callback_check(update_cb, 2) == -1) {
+ if (bpy_prop_callback_check(update_cb, "update", 2) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(get_cb, "get", 1) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(set_cb, "set", 2) == -1) {
return NULL;
}
@@ -534,7 +1999,8 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject
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_callback_assign(prop, update_cb);
+ bpy_prop_callback_assign_update(prop, update_cb);
+ bpy_prop_callback_assign_boolean_array(prop, get_cb, set_cb);
RNA_def_property_duplicate_pointers(srna, prop);
}
@@ -550,7 +2016,9 @@ PyDoc_STRVAR(BPy_IntProperty_doc,
"step=1, "
"options={'ANIMATABLE'}, "
"subtype='NONE', "
- "update=None)\n"
+ "update=None, "
+ "get=None, "
+ "set=None)\n"
"\n"
" Returns a new int property definition.\n"
"\n"
@@ -571,7 +2039,7 @@ static PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw)
if (srna) {
static const char *kwlist[] = {"attr", "name", "description", "default",
"min", "max", "soft_min", "soft_max",
- "step", "options", "subtype", "update", NULL};
+ "step", "options", "subtype", "update", "get", "set", NULL};
const char *id = NULL, *name = NULL, *description = "";
int id_len;
int min = INT_MIN, max = INT_MAX, soft_min = INT_MIN, soft_max = INT_MAX, step = 1, def = 0;
@@ -581,21 +2049,29 @@ static PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw)
char *pysubtype = NULL;
int subtype = PROP_NONE;
PyObject *update_cb = NULL;
+ PyObject *get_cb = NULL;
+ PyObject *set_cb = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kw,
- "s#|ssiiiiiiO!sO:IntProperty",
+ "s#|ssiiiiiiO!sOOO:IntProperty",
(char **)kwlist, &id, &id_len,
&name, &description, &def,
&min, &max, &soft_min, &soft_max,
&step, &PySet_Type, &pyopts, &pysubtype,
- &update_cb))
+ &update_cb, &get_cb, &set_cb))
{
return NULL;
}
BPY_PROPDEF_SUBTYPE_CHECK(IntProperty, property_flag_items, property_subtype_number_items);
- if (bpy_prop_callback_check(update_cb, 2) == -1) {
+ if (bpy_prop_callback_check(update_cb, "update", 2) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(get_cb, "get", 1) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(set_cb, "set", 2) == -1) {
return NULL;
}
@@ -611,7 +2087,8 @@ static PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw)
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_callback_assign(prop, update_cb);
+ bpy_prop_callback_assign_update(prop, update_cb);
+ bpy_prop_callback_assign_int(prop, get_cb, set_cb);
RNA_def_property_duplicate_pointers(srna, prop);
}
Py_RETURN_NONE;
@@ -626,7 +2103,9 @@ PyDoc_STRVAR(BPy_IntVectorProperty_doc,
"options={'ANIMATABLE'}, "
"subtype='NONE', "
"size=3, "
- "update=None)\n"
+ "update=None, "
+ "get=None, "
+ "set=None)\n"
"\n"
" Returns a new vector int property definition.\n"
"\n"
@@ -653,7 +2132,7 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject
if (srna) {
static const char *kwlist[] = {"attr", "name", "description", "default",
"min", "max", "soft_min", "soft_max",
- "step", "options", "subtype", "size", "update", NULL};
+ "step", "options", "subtype", "size", "update", "get", "set", NULL};
const char *id = NULL, *name = NULL, *description = "";
int id_len;
int min = INT_MIN, max = INT_MAX, soft_min = INT_MIN, soft_max = INT_MAX, step = 1;
@@ -666,15 +2145,17 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject
char *pysubtype = NULL;
int subtype = PROP_NONE;
PyObject *update_cb = NULL;
+ PyObject *get_cb = NULL;
+ PyObject *set_cb = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kw,
- "s#|ssOiiiiiO!siO:IntVectorProperty",
+ "s#|ssOiiiiiO!siOOO:IntVectorProperty",
(char **)kwlist, &id, &id_len,
&name, &description, &pydef,
&min, &max, &soft_min, &soft_max,
&step, &PySet_Type, &pyopts,
&pysubtype, &size,
- &update_cb))
+ &update_cb, &get_cb, &set_cb))
{
return NULL;
}
@@ -688,10 +2169,16 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject
return NULL;
}
- if (pydef && PyC_AsArray(def, pydef, size, &PyLong_Type, FALSE, "IntVectorProperty(default=sequence)") < 0)
+ if (pydef && PyC_AsArray(def, pydef, size, &PyLong_Type, false, "IntVectorProperty(default=sequence)") == -1)
return NULL;
- if (bpy_prop_callback_check(update_cb, 2) == -1) {
+ if (bpy_prop_callback_check(update_cb, "update", 2) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(get_cb, "get", 1) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(set_cb, "set", 2) == -1) {
return NULL;
}
@@ -708,7 +2195,8 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject
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_callback_assign(prop, update_cb);
+ bpy_prop_callback_assign_update(prop, update_cb);
+ bpy_prop_callback_assign_int_array(prop, get_cb, set_cb);
RNA_def_property_duplicate_pointers(srna, prop);
}
Py_RETURN_NONE;
@@ -726,7 +2214,9 @@ PyDoc_STRVAR(BPy_FloatProperty_doc,
"options={'ANIMATABLE'}, "
"subtype='NONE', "
"unit='NONE', "
- "update=None)\n"
+ "update=None, "
+ "get=None, "
+ "set=None)\n"
"\n"
" Returns a new float property definition.\n"
"\n"
@@ -748,7 +2238,8 @@ static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw)
if (srna) {
static const char *kwlist[] = {"attr", "name", "description", "default",
"min", "max", "soft_min", "soft_max",
- "step", "precision", "options", "subtype", "unit", "update", NULL};
+ "step", "precision", "options", "subtype",
+ "unit", "update", "get", "set", NULL};
const char *id = NULL, *name = NULL, *description = "";
int id_len;
float min = -FLT_MAX, max = FLT_MAX, soft_min = -FLT_MAX, soft_max = FLT_MAX, step = 3, def = 0.0f;
@@ -761,15 +2252,17 @@ static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw)
char *pyunit = NULL;
int unit = PROP_UNIT_NONE;
PyObject *update_cb = NULL;
+ PyObject *get_cb = NULL;
+ PyObject *set_cb = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kw,
- "s#|ssffffffiO!ssO:FloatProperty",
+ "s#|ssffffffiO!ssOOO:FloatProperty",
(char **)kwlist, &id, &id_len,
&name, &description, &def,
&min, &max, &soft_min, &soft_max,
&step, &precision, &PySet_Type,
&pyopts, &pysubtype, &pyunit,
- &update_cb))
+ &update_cb, &get_cb, &set_cb))
{
return NULL;
}
@@ -781,7 +2274,13 @@ static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw)
return NULL;
}
- if (bpy_prop_callback_check(update_cb, 2) == -1) {
+ if (bpy_prop_callback_check(update_cb, "update", 2) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(get_cb, "get", 1) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(set_cb, "set", 2) == -1) {
return NULL;
}
@@ -797,7 +2296,8 @@ static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw)
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_callback_assign(prop, update_cb);
+ bpy_prop_callback_assign_update(prop, update_cb);
+ bpy_prop_callback_assign_float(prop, get_cb, set_cb);
RNA_def_property_duplicate_pointers(srna, prop);
}
Py_RETURN_NONE;
@@ -814,7 +2314,9 @@ PyDoc_STRVAR(BPy_FloatVectorProperty_doc,
"options={'ANIMATABLE'}, "
"subtype='NONE', "
"size=3, "
- "update=None)\n"
+ "update=None, "
+ "get=None, "
+ "set=None)\n"
"\n"
" Returns a new vector float property definition.\n"
"\n"
@@ -842,7 +2344,8 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec
if (srna) {
static const char *kwlist[] = {"attr", "name", "description", "default",
"min", "max", "soft_min", "soft_max",
- "step", "precision", "options", "subtype", "unit", "size", "update", NULL};
+ "step", "precision", "options", "subtype",
+ "unit", "size", "update", "get", "set", NULL};
const char *id = NULL, *name = NULL, *description = "";
int id_len;
float min = -FLT_MAX, max = FLT_MAX, soft_min = -FLT_MAX, soft_max = FLT_MAX, step = 3;
@@ -857,15 +2360,17 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec
char *pyunit = NULL;
int unit = PROP_UNIT_NONE;
PyObject *update_cb = NULL;
+ PyObject *get_cb = NULL;
+ PyObject *set_cb = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kw,
- "s#|ssOfffffiO!ssiO:FloatVectorProperty",
+ "s#|ssOfffffiO!ssiOOO:FloatVectorProperty",
(char **)kwlist, &id, &id_len,
&name, &description, &pydef,
&min, &max, &soft_min, &soft_max,
&step, &precision, &PySet_Type,
&pyopts, &pysubtype, &pyunit, &size,
- &update_cb))
+ &update_cb, &get_cb, &set_cb))
{
return NULL;
}
@@ -884,10 +2389,16 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec
return NULL;
}
- if (pydef && PyC_AsArray(def, pydef, size, &PyFloat_Type, FALSE, "FloatVectorProperty(default=sequence)") < 0)
+ if (pydef && PyC_AsArray(def, pydef, size, &PyFloat_Type, false, "FloatVectorProperty(default=sequence)") == -1)
return NULL;
- if (bpy_prop_callback_check(update_cb, 2) == -1) {
+ if (bpy_prop_callback_check(update_cb, "update", 2) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(get_cb, "get", 1) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(set_cb, "set", 2) == -1) {
return NULL;
}
@@ -904,7 +2415,8 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec
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_callback_assign(prop, update_cb);
+ bpy_prop_callback_assign_update(prop, update_cb);
+ bpy_prop_callback_assign_float_array(prop, get_cb, set_cb);
RNA_def_property_duplicate_pointers(srna, prop);
}
Py_RETURN_NONE;
@@ -917,7 +2429,9 @@ PyDoc_STRVAR(BPy_StringProperty_doc,
"maxlen=0, "
"options={'ANIMATABLE'}, "
"subtype='NONE', "
- "update=None)\n"
+ "update=None, "
+ "get=None, "
+ "set=None)\n"
"\n"
" Returns a new string property definition.\n"
"\n"
@@ -937,7 +2451,7 @@ static PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw
if (srna) {
static const char *kwlist[] = {"attr", "name", "description", "default",
- "maxlen", "options", "subtype", "update", NULL};
+ "maxlen", "options", "subtype", "update", "get", "set", NULL};
const char *id = NULL, *name = NULL, *description = "", *def = "";
int id_len;
int maxlen = 0;
@@ -947,20 +2461,28 @@ static PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw
char *pysubtype = NULL;
int subtype = PROP_NONE;
PyObject *update_cb = NULL;
+ PyObject *get_cb = NULL;
+ PyObject *set_cb = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kw,
- "s#|sssiO!sO:StringProperty",
+ "s#|sssiO!sOOO:StringProperty",
(char **)kwlist, &id, &id_len,
&name, &description, &def,
&maxlen, &PySet_Type, &pyopts, &pysubtype,
- &update_cb))
+ &update_cb, &get_cb, &set_cb))
{
return NULL;
}
BPY_PROPDEF_SUBTYPE_CHECK(StringProperty, property_flag_items, property_subtype_string_items);
- if (bpy_prop_callback_check(update_cb, 2) == -1) {
+ if (bpy_prop_callback_check(update_cb, "update", 2) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(get_cb, "get", 1) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(set_cb, "set", 2) == -1) {
return NULL;
}
@@ -975,246 +2497,22 @@ static PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw
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_callback_assign(prop, update_cb);
+ bpy_prop_callback_assign_update(prop, update_cb);
+ bpy_prop_callback_assign_string(prop, get_cb, set_cb);
RNA_def_property_duplicate_pointers(srna, prop);
}
Py_RETURN_NONE;
}
-#if 0
-/* copies orig to buf, then sets orig to buf, returns copy length */
-static size_t strswapbufcpy(char *buf, const char **orig)
-{
- const char *src = *orig;
- char *dst = buf;
- size_t i = 0;
- *orig = buf;
- while ((*dst = *src)) { dst++; src++; i++; }
- return i + 1; /* include '\0' */
-}
-#endif
-
-static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, int *defvalue, const short is_enum_flag)
-{
- EnumPropertyItem *items;
- PyObject *item;
- const Py_ssize_t seq_len = PySequence_Fast_GET_SIZE(seq_fast);
- Py_ssize_t totbuf = 0;
- int i;
- short def_used = 0;
- const char *def_cmp = NULL;
-
- if (is_enum_flag) {
- if (seq_len > RNA_ENUM_BITFLAG_SIZE) {
- PyErr_SetString(PyExc_TypeError,
- "EnumProperty(...): maximum "
- STRINGIFY(RNA_ENUM_BITFLAG_SIZE)
- " members for a ENUM_FLAG type property");
- return NULL;
- }
- if (def && !PySet_Check(def)) {
- PyErr_Format(PyExc_TypeError,
- "EnumProperty(...): default option must be a 'set' "
- "type when ENUM_FLAG is enabled, not a '%.200s'",
- Py_TYPE(def)->tp_name);
- return NULL;
- }
- }
- else {
- if (def) {
- def_cmp = _PyUnicode_AsString(def);
- if (def_cmp == NULL) {
- PyErr_Format(PyExc_TypeError,
- "EnumProperty(...): default option must be a 'str' "
- "type when ENUM_FLAG is disabled, not a '%.200s'",
- Py_TYPE(def)->tp_name);
- return NULL;
- }
- }
- }
-
- /* blank value */
- *defvalue = 0;
-
- items = MEM_callocN(sizeof(EnumPropertyItem) * (seq_len + 1), "enum_items_from_py1");
-
- for (i = 0; i < seq_len; i++) {
- EnumPropertyItem tmp = {0, "", 0, "", ""};
- Py_ssize_t item_size;
- Py_ssize_t id_str_size;
- Py_ssize_t name_str_size;
- Py_ssize_t desc_str_size;
-
- item = PySequence_Fast_GET_ITEM(seq_fast, i);
-
- if ((PyTuple_CheckExact(item)) &&
- (item_size = PyTuple_GET_SIZE(item)) &&
- (item_size == 3 || item_size == 4) &&
- (tmp.identifier = _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 0), &id_str_size)) &&
- (tmp.name = _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 1), &name_str_size)) &&
- (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))
- {
- if (is_enum_flag) {
- if (item_size < 4) {
- tmp.value = 1 << i;
- }
-
- if (def && PySet_Contains(def, PyTuple_GET_ITEM(item, 0))) {
- *defvalue |= tmp.value;
- def_used++;
- }
- }
- else {
- if (item_size < 4) {
- tmp.value = i;
- }
-
- if (def && def_used == 0 && strcmp(def_cmp, tmp.identifier) == 0) {
- *defvalue = tmp.value;
- def_used++; /* only ever 1 */
- }
- }
-
- items[i] = tmp;
-
- /* calculate combine string length */
- totbuf += id_str_size + name_str_size + desc_str_size + 3; /* 3 is for '\0's */
- }
- else {
- MEM_freeN(items);
- PyErr_SetString(PyExc_TypeError,
- "EnumProperty(...): expected a tuple containing "
- "(identifier, name, description) and optionally a "
- "unique number");
- return NULL;
- }
-
- }
-
- if (is_enum_flag) {
- /* strict check that all set members were used */
- if (def && def_used != PySet_GET_SIZE(def)) {
- MEM_freeN(items);
-
- PyErr_Format(PyExc_TypeError,
- "EnumProperty(..., default={...}): set has %d unused member(s)",
- PySet_GET_SIZE(def) - def_used);
- return NULL;
- }
- }
- else {
- if (def && def_used == 0) {
- MEM_freeN(items);
-
- PyErr_Format(PyExc_TypeError,
- "EnumProperty(..., default=\'%s\'): not found in enum members",
- def_cmp);
- return NULL;
- }
- }
-
- /* disabled duplicating strings because the array can still be freed and
- * the strings from it referenced, for now we can't support dynamically
- * created strings from python. */
-#if 0
- /* this would all work perfectly _but_ the python strings may be freed
- * immediately after use, so we need to duplicate them, ugh.
- * annoying because it works most of the time without this. */
- {
- EnumPropertyItem *items_dup = MEM_mallocN((sizeof(EnumPropertyItem) * (seq_len + 1)) + (sizeof(char) * totbuf),
- "enum_items_from_py2");
- EnumPropertyItem *items_ptr = items_dup;
- char *buf = ((char *)items_dup) + (sizeof(EnumPropertyItem) * (seq_len + 1));
- memcpy(items_dup, items, sizeof(EnumPropertyItem) * (seq_len + 1));
- for (i = 0; i < seq_len; i++, items_ptr++) {
- buf += strswapbufcpy(buf, &items_ptr->identifier);
- buf += strswapbufcpy(buf, &items_ptr->name);
- buf += strswapbufcpy(buf, &items_ptr->description);
- }
- MEM_freeN(items);
- items = items_dup;
- }
- /* end string duplication */
-#endif
-
- return items;
-}
-
-static EnumPropertyItem *bpy_props_enum_itemf(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, int *free)
-{
- PyGILState_STATE gilstate;
-
- PyObject *py_func = RNA_property_enum_py_data_get(prop);
- PyObject *self = NULL;
- PyObject *args;
- PyObject *items; /* returned from the function call */
-
- EnumPropertyItem *eitems = NULL;
- int err = 0;
-
- bpy_context_set(C, &gilstate);
-
- 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);
-
- items = PyObject_CallObject(py_func, args);
-
- Py_DECREF(args);
-
- if (items == NULL) {
- err = -1;
- }
- else {
- PyObject *items_fast;
- int defvalue_dummy = 0;
-
- if (!(items_fast = PySequence_Fast(items, "EnumProperty(...): "
- "return value from the callback was not a sequence")))
- {
- err = -1;
- }
- else {
- eitems = enum_items_from_py(items_fast, NULL, &defvalue_dummy,
- (RNA_property_flag(prop) & PROP_ENUM_FLAG) != 0);
-
- Py_DECREF(items_fast);
-
- if (!eitems) {
- err = -1;
- }
- }
-
- Py_DECREF(items);
- }
-
- if (err != -1) { /* worked */
- *free = 1;
- }
- else {
- printf_func_error(py_func);
-
- eitems = DummyRNA_NULL_items;
- }
-
-
- bpy_context_clear(C, &gilstate);
- return eitems;
-}
-
PyDoc_STRVAR(BPy_EnumProperty_doc,
".. function:: EnumProperty(items, "
"name=\"\", "
"description=\"\", "
"default=\"\", "
"options={'ANIMATABLE'}, "
- "update=None)\n"
+ "update=None, "
+ "get=None, "
+ "set=None)\n"
"\n"
" Returns a new enumerator property definition.\n"
"\n"
@@ -1227,13 +2525,15 @@ BPY_PROPDEF_DESC_DOC
" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE', 'ENUM_FLAG', 'LIBRARY_EDITABLE'].\n"
" :type options: set\n"
" :arg items: sequence of enum items formatted:\n"
-" [(identifier, name, description, number), ...] where the identifier is used\n"
+" [(identifier, name, description, icon, number), ...] where the identifier is used\n"
" for python access and other values are used for the interface.\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"
-" :type items: sequence of string triplets or a function\n"
+" WARNING: Do not use generators here (they will work the first time, but will lead to empty values\n"
+" in some unload/reload scenarii)!\n"
+" :type items: sequence of string triples or a function\n"
BPY_PROPDEF_UPDATE_DOC
);
static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
@@ -1244,7 +2544,7 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
if (srna) {
static const char *kwlist[] = {"attr", "items", "name", "description", "default",
- "options", "update", NULL};
+ "options", "update", "get", "set", NULL};
const char *id = NULL, *name = NULL, *description = "";
PyObject *def = NULL;
int id_len;
@@ -1254,22 +2554,30 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
PropertyRNA *prop;
PyObject *pyopts = NULL;
int opts = 0;
- short is_itemf = FALSE;
+ bool is_itemf = false;
PyObject *update_cb = NULL;
+ PyObject *get_cb = NULL;
+ PyObject *set_cb = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kw,
- "s#O|ssOO!O:EnumProperty",
+ "s#O|ssOO!OOO:EnumProperty",
(char **)kwlist, &id, &id_len,
&items, &name, &description,
&def, &PySet_Type, &pyopts,
- &update_cb))
+ &update_cb, &get_cb, &set_cb))
{
return NULL;
}
BPY_PROPDEF_CHECK(EnumProperty, property_flag_enum_items);
- if (bpy_prop_callback_check(update_cb, 2) == -1) {
+ if (bpy_prop_callback_check(update_cb, "update", 2) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(get_cb, "get", 1) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(set_cb, "set", 2) == -1) {
return NULL;
}
@@ -1290,7 +2598,7 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
return NULL;
}
- is_itemf = TRUE;
+ is_itemf = true;
eitems = DummyRNA_NULL_items;
}
else {
@@ -1312,25 +2620,17 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
if (opts & PROP_ENUM_FLAG) prop = RNA_def_enum_flag(srna, id, eitems, defvalue, name ? name : id, description);
else prop = RNA_def_enum(srna, id, eitems, defvalue, name ? name : id, description);
- if (is_itemf) {
- RNA_def_enum_funcs(prop, bpy_props_enum_itemf);
- RNA_def_enum_py_data(prop, (void *)items);
-
- /* watch out!, if a user is tricky they can probably crash blender
- * if they manage to free the callback, take care! */
- /* Py_INCREF(items); */
- }
-
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_callback_assign(prop, update_cb);
+ bpy_prop_callback_assign_update(prop, update_cb);
+ bpy_prop_callback_assign_enum(prop, get_cb, set_cb, (is_itemf ? items : NULL));
RNA_def_property_duplicate_pointers(srna, prop);
- if (is_itemf == FALSE) {
+ if (is_itemf == false) {
/* note: this must be postponed until after #RNA_def_property_duplicate_pointers
* otherwise if this is a generator it may free the strings before we copy them */
Py_DECREF(items_fast);
@@ -1422,7 +2722,7 @@ static PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *k
if (!ptype)
return NULL;
- if (bpy_prop_callback_check(update_cb, 2) == -1) {
+ if (bpy_prop_callback_check(update_cb, "update", 2) == -1) {
return NULL;
}
@@ -1433,7 +2733,7 @@ static PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *k
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_callback_assign(prop, update_cb);
+ bpy_prop_callback_assign_update(prop, update_cb);
RNA_def_property_duplicate_pointers(srna, prop);
}
Py_RETURN_NONE;
@@ -1498,12 +2798,17 @@ static PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject
}
PyDoc_STRVAR(BPy_RemoveProperty_doc,
-".. function:: RemoveProperty(attr)\n"
+".. function:: RemoveProperty(cls, attr="")\n"
"\n"
" Removes a dynamically defined property.\n"
"\n"
-" :arg attr: Property name.\n"
+" :arg cls: The class containing the property (must be a positional argument).\n"
+" :type cls: type\n"
+" :arg attr: Property name (must be passed as a keyword).\n"
" :type attr: string\n"
+"\n"
+".. note:: Typically this function doesn't need to be accessed directly.\n"
+" Instead use ``del cls.attr``\n"
);
static PyObject *BPy_RemoveProperty(PyObject *self, PyObject *args, PyObject *kw)
{
@@ -1518,7 +2823,7 @@ static PyObject *BPy_RemoveProperty(PyObject *self, PyObject *args, PyObject *kw
return ret;
}
else if (PyTuple_GET_SIZE(args) > 1) {
- PyErr_SetString(PyExc_ValueError, "all args must be keywords");
+ PyErr_SetString(PyExc_ValueError, "expected one positional arg, one keyword arg");
return NULL;
}
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index a0df8988068..735df7aeb10 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -37,6 +37,12 @@
#include "RNA_types.h"
+#include "BLI_dynstr.h"
+#include "BLI_string.h"
+#include "BLI_listbase.h"
+#include "BLI_math_rotation.h"
+#include "BLI_utildefines.h"
+
#include "BPY_extern.h"
#include "bpy_rna.h"
@@ -50,12 +56,6 @@
# include "MEM_guardedalloc.h"
#endif
-#include "BLI_dynstr.h"
-#include "BLI_string.h"
-#include "BLI_listbase.h"
-#include "BLI_math_rotation.h"
-#include "BLI_utildefines.h"
-
#ifdef USE_PYRNA_INVALIDATE_WEAKREF
# include "BLI_ghash.h"
#endif
@@ -250,7 +250,7 @@ static void id_release_weakref_list(struct ID *id, GHash *weakinfo_hash)
fprintf(stdout, "id_release_weakref: '%s', %d items\n", id->name, BLI_ghash_size(weakinfo_hash));
#endif
- while (!BLI_ghashIterator_isDone(&weakinfo_hash_iter)) {
+ while (BLI_ghashIterator_notDone(&weakinfo_hash_iter)) {
PyObject *weakref = (PyObject *)BLI_ghashIterator_getKey(&weakinfo_hash_iter);
PyObject *item = PyWeakref_GET_OBJECT(weakref);
if (item != Py_None) {
@@ -309,9 +309,9 @@ void BPY_id_release(struct ID *id)
}
#ifdef USE_PEDANTIC_WRITE
-static short rna_disallow_writes = FALSE;
+static bool rna_disallow_writes = false;
-static int rna_id_write_error(PointerRNA *ptr, PyObject *key)
+static bool rna_id_write_error(PointerRNA *ptr, PyObject *key)
{
ID *id = ptr->id.data;
if (id) {
@@ -329,30 +329,30 @@ static int rna_id_write_error(PointerRNA *ptr, PyObject *key)
"%.200s, %.200s datablock, error setting %.200s.%.200s",
id->name + 2, idtype, RNA_struct_identifier(ptr->type), pyname);
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
#endif /* USE_PEDANTIC_WRITE */
#ifdef USE_PEDANTIC_WRITE
-int pyrna_write_check(void)
+bool pyrna_write_check(void)
{
return !rna_disallow_writes;
}
-void pyrna_write_set(int val)
+void pyrna_write_set(bool val)
{
rna_disallow_writes = !val;
}
#else /* USE_PEDANTIC_WRITE */
-int pyrna_write_check(void)
+bool pyrna_write_check(void)
{
- return TRUE;
+ return true;
}
-void pyrna_write_set(int UNUSED(val))
+void pyrna_write_set(bool UNUSED(val))
{
/* nothing */
}
@@ -644,7 +644,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
RNA_property_float_get_array(ptr, prop, ((MatrixObject *)ret)->matrix);
}
else {
- PyObject *mat_cb = Matrix_CreatePyObject_cb(ret, 4, 4, mathutils_rna_matrix_cb_index, FALSE);
+ PyObject *mat_cb = Matrix_CreatePyObject_cb(ret, 4, 4, mathutils_rna_matrix_cb_index, 0);
Py_DECREF(ret); /* the matrix owns now */
ret = mat_cb; /* return the matrix instead */
}
@@ -655,7 +655,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
RNA_property_float_get_array(ptr, prop, ((MatrixObject *)ret)->matrix);
}
else {
- PyObject *mat_cb = Matrix_CreatePyObject_cb(ret, 3, 3, mathutils_rna_matrix_cb_index, FALSE);
+ PyObject *mat_cb = Matrix_CreatePyObject_cb(ret, 3, 3, mathutils_rna_matrix_cb_index, 0);
Py_DECREF(ret); /* the matrix owns now */
ret = mat_cb; /* return the matrix instead */
}
@@ -1123,7 +1123,7 @@ static const char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop)
{
EnumPropertyItem *item;
const char *result;
- int free = FALSE;
+ int free = false;
RNA_property_enum_items(BPy_GetContext(), ptr, prop, &item, NULL, &free);
if (item) {
@@ -1187,7 +1187,7 @@ int pyrna_set_to_enum_bitfield(EnumPropertyItem *items, PyObject *value, int *r_
return -1;
}
- if (pyrna_enum_value_from_id(items, param, &ret, error_prefix) < 0) {
+ if (pyrna_enum_value_from_id(items, param, &ret, error_prefix) == -1) {
return -1;
}
@@ -1202,7 +1202,7 @@ static int pyrna_prop_to_enum_bitfield(PointerRNA *ptr, PropertyRNA *prop, PyObj
{
EnumPropertyItem *item;
int ret;
- int free = FALSE;
+ int free = false;
*r_value = 0;
@@ -1282,7 +1282,7 @@ static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val)
}
else {
EnumPropertyItem *enum_item;
- int free = FALSE;
+ int free = false;
/* don't throw error here, can't trust blender 100% to give the
* right values, python code should not generate error for that */
@@ -1427,7 +1427,9 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const cha
{
arg_name = RNA_property_identifier(prop);
- if (strcmp(arg_name, "rna_type") == 0) continue;
+ if (STREQ(arg_name, "rna_type")) {
+ continue;
+ }
if (kw == NULL) {
PyErr_Format(PyExc_TypeError,
@@ -1478,7 +1480,7 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const cha
}
-static PyObject *pyrna_func_to_py(PointerRNA *ptr, FunctionRNA *func)
+static PyObject *pyrna_func_to_py(const PointerRNA *ptr, FunctionRNA *func)
{
BPy_FunctionRNA *pyfunc = (BPy_FunctionRNA *) PyObject_NEW(BPy_FunctionRNA, &pyrna_func_Type);
pyfunc->ptr = *ptr;
@@ -1510,12 +1512,18 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb
/* prefer not to have an exception here
* however so many poll functions return None or a valid Object.
* its a hassle to convert these into a bool before returning, */
- if (RNA_property_flag(prop) & PROP_OUTPUT)
+ if (RNA_property_flag(prop) & PROP_OUTPUT) {
param = PyObject_IsTrue(value);
- else
+ }
+ else {
param = PyLong_AsLong(value);
- if (param < 0) {
+ if (UNLIKELY(param & ~1)) { /* only accept 0/1 */
+ param = -1; /* error out below */
+ }
+ }
+
+ if (param == -1) {
PyErr_Format(PyExc_TypeError,
"%.200s %.200s.%.200s expected True/False or 0/1, not %.200s",
error_prefix, RNA_struct_identifier(ptr->type),
@@ -1617,9 +1625,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb
}
}
else {
-
/* Unicode String */
-
#ifdef USE_STRING_COERCE
PyObject *value_coerce = NULL;
if (ELEM3(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
@@ -1628,12 +1634,6 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb
}
else {
param = _PyUnicode_AsString(value);
-#ifdef WITH_INTERNATIONAL
- if (subtype == PROP_TRANSLATE) {
- param = IFACE_(param);
- }
-#endif /* WITH_INTERNATIONAL */
-
}
#else /* USE_STRING_COERCE */
param = _PyUnicode_AsString(value);
@@ -1676,13 +1676,13 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb
/* type checkins is done by each function */
if (RNA_property_flag(prop) & PROP_ENUM_FLAG) {
/* set of enum items, concatenate all values with OR */
- if (pyrna_prop_to_enum_bitfield(ptr, prop, value, &val, error_prefix) < 0) {
+ if (pyrna_prop_to_enum_bitfield(ptr, prop, value, &val, error_prefix) == -1) {
return -1;
}
}
else {
/* simple enum string */
- if (pyrna_string_to_enum(value, ptr, prop, &val, error_prefix) < 0) {
+ if (pyrna_string_to_enum(value, ptr, prop, &val, error_prefix) == -1) {
return -1;
}
}
@@ -1771,7 +1771,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb
}
else {
BPy_StructRNA *param = (BPy_StructRNA *)value;
- int raise_error = FALSE;
+ bool raise_error = false;
if (data) {
if (flag & PROP_RNAPTR) {
@@ -1798,7 +1798,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb
*((void **)data) = param->ptr.data;
}
else {
- raise_error = TRUE;
+ raise_error = true;
}
}
else {
@@ -2189,7 +2189,7 @@ static int pyrna_prop_collection_subscript_str_lib_pair_ptr(BPy_PropertyRNA *sel
else {
PyObject *keylib = PyTuple_GET_ITEM(key, 1);
Library *lib;
- int found = FALSE;
+ bool found = false;
if (keylib == Py_None) {
lib = NULL;
@@ -2225,8 +2225,8 @@ static int pyrna_prop_collection_subscript_str_lib_pair_ptr(BPy_PropertyRNA *sel
RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop)
{
ID *id = itemptr.data; /* always an ID */
- if (id->lib == lib && (strncmp(keyname, id->name + 2, sizeof(id->name) - 2) == 0)) {
- found = TRUE;
+ if (id->lib == lib && (STREQLEN(keyname, id->name + 2, sizeof(id->name) - 2))) {
+ found = true;
if (r_ptr) {
*r_ptr = itemptr;
}
@@ -2236,7 +2236,7 @@ static int pyrna_prop_collection_subscript_str_lib_pair_ptr(BPy_PropertyRNA *sel
RNA_PROP_END;
/* we may want to fail silently as with collection.get() */
- if ((found == FALSE) && err_not_found) {
+ if ((found == false) && err_not_found) {
/* only runs for getitem access so use fixed string */
PyErr_SetString(PyExc_KeyError,
"bpy_prop_collection[key, lib]: not found");
@@ -2249,7 +2249,7 @@ static int pyrna_prop_collection_subscript_str_lib_pair_ptr(BPy_PropertyRNA *sel
}
static PyObject *pyrna_prop_collection_subscript_str_lib_pair(BPy_PropertyRNA *self, PyObject *key,
- const char *err_prefix, const short err_not_found)
+ const char *err_prefix, const bool err_not_found)
{
PointerRNA ptr;
const int contains = pyrna_prop_collection_subscript_str_lib_pair_ptr(self, key, err_prefix, err_not_found, &ptr);
@@ -2442,7 +2442,7 @@ static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject
else if (PyTuple_Check(key)) {
/* special case, for ID datablocks we */
return pyrna_prop_collection_subscript_str_lib_pair(self, key,
- "bpy_prop_collection[id, lib]", TRUE);
+ "bpy_prop_collection[id, lib]", true);
}
else {
PyErr_Format(PyExc_TypeError,
@@ -2859,7 +2859,7 @@ static int pyrna_prop_collection_contains(BPy_PropertyRNA *self, PyObject *key)
if (PyTuple_Check(key)) {
/* special case, for ID datablocks we */
return pyrna_prop_collection_subscript_str_lib_pair_ptr(self, key,
- "(id, lib) in bpy_prop_collection", FALSE, NULL);
+ "(id, lib) in bpy_prop_collection", false, NULL);
}
else {
@@ -3119,6 +3119,33 @@ static PyObject *pyrna_struct_is_property_set(BPy_StructRNA *self, PyObject *arg
return PyBool_FromLong(RNA_property_is_set(&self->ptr, prop));
}
+PyDoc_STRVAR(pyrna_struct_property_unset_doc,
+".. method:: property_unset(property)\n"
+"\n"
+" Unset a property, will use default value afterward.\n"
+);
+static PyObject *pyrna_struct_property_unset(BPy_StructRNA *self, PyObject *args)
+{
+ PropertyRNA *prop;
+ const char *name;
+
+ PYRNA_STRUCT_CHECK_OBJ(self);
+
+ if (!PyArg_ParseTuple(args, "s:property_unset", &name))
+ return NULL;
+
+ if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s.property_unset(\"%.200s\") not found",
+ RNA_struct_identifier(self->ptr.type), name);
+ return NULL;
+ }
+
+ RNA_property_unset(&self->ptr, prop);
+
+ Py_RETURN_NONE;
+}
+
PyDoc_STRVAR(pyrna_struct_is_property_hidden_doc,
".. method:: is_property_hidden(property)\n"
"\n"
@@ -3465,7 +3492,7 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname)
}
else if (name[0] == '_') { /* rna can't start with a "_", so for __dict__ and similar we can skip using rna lookups */
/* annoying exception, maybe we need to have different types for this... */
- if ((strcmp(name, "__getitem__") == 0 || strcmp(name, "__setitem__") == 0) && !RNA_struct_idprops_check(self->ptr.type)) {
+ if ((STREQ(name, "__getitem__") || STREQ(name, "__setitem__")) && !RNA_struct_idprops_check(self->ptr.type)) {
PyErr_SetString(PyExc_AttributeError, "bpy_struct: no __getitem__ support for this type");
ret = NULL;
}
@@ -4199,7 +4226,7 @@ static PyObject *pyrna_prop_collection_get(BPy_PropertyRNA *self, PyObject *args
}
else if (PyTuple_Check(key_ob)) {
PyObject *ret = pyrna_prop_collection_subscript_str_lib_pair(self, key_ob,
- "bpy_prop_collection.get((id, lib))", FALSE);
+ "bpy_prop_collection.get((id, lib))", false);
if (ret) {
return ret;
}
@@ -4259,25 +4286,33 @@ static PyObject *pyrna_prop_collection_find(BPy_PropertyRNA *self, PyObject *key
return PyLong_FromLong(index);
}
-static void foreach_attr_type(BPy_PropertyRNA *self, const char *attr,
+static bool foreach_attr_type(BPy_PropertyRNA *self, const char *attr,
/* values to assign */
- RawPropertyType *raw_type, int *attr_tot, int *attr_signed)
+ RawPropertyType *raw_type, int *attr_tot, bool *attr_signed)
{
PropertyRNA *prop;
+ bool attr_ok = true;
*raw_type = PROP_RAW_UNSET;
*attr_tot = 0;
- *attr_signed = FALSE;
+ *attr_signed = false;
/* note: this is fail with zero length lists, so don't let this get caled in that case */
RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop)
{
prop = RNA_struct_find_property(&itemptr, attr);
- *raw_type = RNA_property_raw_type(prop);
- *attr_tot = RNA_property_array_length(&itemptr, prop);
- *attr_signed = (RNA_property_subtype(prop) == PROP_UNSIGNED) ? FALSE : TRUE;
+ if (prop) {
+ *raw_type = RNA_property_raw_type(prop);
+ *attr_tot = RNA_property_array_length(&itemptr, prop);
+ *attr_signed = (RNA_property_subtype(prop) != PROP_UNSIGNED);
+ }
+ else {
+ attr_ok = false;
+ }
break;
}
RNA_PROP_END;
+
+ return attr_ok;
}
/* pyrna_prop_collection_foreach_get/set both use this */
@@ -4285,7 +4320,7 @@ static int foreach_parse_args(BPy_PropertyRNA *self, PyObject *args,
/* values to assign */
const char **attr, PyObject **seq, int *tot, int *size,
- RawPropertyType *raw_type, int *attr_tot, int *attr_signed
+ RawPropertyType *raw_type, int *attr_tot, bool *attr_signed
)
{
#if 0
@@ -4293,18 +4328,30 @@ static int foreach_parse_args(BPy_PropertyRNA *self, PyObject *args,
int target_tot;
#endif
- *size = *attr_tot = *attr_signed = FALSE;
+ *size = *attr_tot = 0;
+ *attr_signed = false;
*raw_type = PROP_RAW_UNSET;
- if (!PyArg_ParseTuple(args, "sO", attr, seq) || (!PySequence_Check(*seq) && PyObject_CheckBuffer(*seq))) {
- PyErr_SetString(PyExc_TypeError, "foreach_get(attr, sequence) expects a string and a sequence");
+ if (!PyArg_ParseTuple(args, "sO:foreach_get/set", attr, seq)) {
+ return -1;
+ }
+
+ if (!PySequence_Check(*seq) && PyObject_CheckBuffer(*seq)) {
+ PyErr_Format(PyExc_TypeError,
+ "foreach_get/set expected second argument to be a sequence or buffer, not a %.200s",
+ Py_TYPE(*seq)->tp_name);
return -1;
}
*tot = PySequence_Size(*seq); /* TODO - buffer may not be a sequence! array.array() is tho. */
if (*tot > 0) {
- foreach_attr_type(self, *attr, raw_type, attr_tot, attr_signed);
+ if (!foreach_attr_type(self, *attr, raw_type, attr_tot, attr_signed)) {
+ PyErr_Format(PyExc_AttributeError,
+ "foreach_get/set '%.200s.%200s[...]' elements have no attribute '%.200s'",
+ RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop), *attr);
+ return -1;
+ }
*size = RNA_raw_type_sizeof(*raw_type);
#if 0 /* works fine but not strictly needed, we could allow RNA_property_collection_raw_* to do the checks */
@@ -4338,7 +4385,7 @@ static int foreach_parse_args(BPy_PropertyRNA *self, PyObject *args,
return 0;
}
-static int foreach_compat_buffer(RawPropertyType raw_type, int attr_signed, const char *format)
+static bool foreach_compat_buffer(RawPropertyType raw_type, int attr_signed, const char *format)
{
char f = format ? *format : 'B'; /* B is assumed when not set */
@@ -4366,16 +4413,18 @@ static int foreach_compat_buffer(RawPropertyType raw_type, int attr_signed, cons
static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set)
{
PyObject *item = NULL;
- int i = 0, ok = 0, buffer_is_compat;
+ int i = 0, ok = 0;
+ bool buffer_is_compat;
void *array = NULL;
/* get/set both take the same args currently */
const char *attr;
PyObject *seq;
- int tot, size, attr_tot, attr_signed;
+ int tot, size, attr_tot;
+ bool attr_signed;
RawPropertyType raw_type;
- if (foreach_parse_args(self, args, &attr, &seq, &tot, &size, &raw_type, &attr_tot, &attr_signed) < 0)
+ if (foreach_parse_args(self, args, &attr, &seq, &tot, &size, &raw_type, &attr_tot, &attr_signed) == -1)
return NULL;
if (tot == 0)
@@ -4384,7 +4433,7 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set)
if (set) { /* get the array from python */
- buffer_is_compat = FALSE;
+ buffer_is_compat = false;
if (PyObject_CheckBuffer(seq)) {
Py_buffer buf;
PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT);
@@ -4435,7 +4484,7 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set)
}
}
else {
- buffer_is_compat = FALSE;
+ buffer_is_compat = false;
if (PyObject_CheckBuffer(seq)) {
Py_buffer buf;
PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT);
@@ -4515,7 +4564,7 @@ PyDoc_STRVAR(pyrna_prop_collection_foreach_get_doc,
"\n"
" .. code-block:: python\n"
"\n"
-" collection.foreach_get(someseq, attr)\n"
+" collection.foreach_get(attr, someseq)\n"
"\n"
" # Python equivalent\n"
" for i in range(len(seq)): someseq[i] = getattr(collection, attr)\n"
@@ -4535,7 +4584,7 @@ PyDoc_STRVAR(pyrna_prop_collection_foreach_set_doc,
"\n"
" .. code-block:: python\n"
"\n"
-" collection.foreach_set(seq, attr)\n"
+" collection.foreach_set(attr, seq)\n"
"\n"
" # Python equivalent\n"
" for i in range(len(seq)): setattr(collection[i], attr, seq[i])\n"
@@ -4611,6 +4660,7 @@ static struct PyMethodDef pyrna_struct_methods[] = {
{"driver_remove", (PyCFunction)pyrna_struct_driver_remove, METH_VARARGS, pyrna_struct_driver_remove_doc},
{"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},
{"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},
@@ -4618,8 +4668,14 @@ static struct PyMethodDef pyrna_struct_methods[] = {
{"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, NULL},
/* experimental */
+ /* unused for now */
+#if 0
{"callback_add", (PyCFunction)pyrna_callback_add, METH_VARARGS, NULL},
{"callback_remove", (PyCFunction)pyrna_callback_remove, METH_VARARGS, NULL},
+
+ {"callback_add", (PyCFunction)pyrna_callback_classmethod_add, METH_VARARGS | METH_CLASS, NULL},
+ {"callback_remove", (PyCFunction)pyrna_callback_classmethod_remove, METH_VARARGS | METH_CLASS, NULL},
+#endif
{NULL, NULL, 0, NULL}
};
@@ -4913,7 +4969,7 @@ static PyObject *small_dict_get_item_string(PyObject *dict, const char *key_look
while (PyDict_Next(dict, &pos, &key, &value)) {
if (PyUnicode_Check(key)) {
- if (strcmp(key_lookup, _PyUnicode_AsString(key)) == 0) {
+ if (STREQ(key_lookup, _PyUnicode_AsString(key))) {
return value;
}
}
@@ -4933,7 +4989,8 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject
ParameterIterator iter;
PropertyRNA *parm;
PyObject *ret, *item;
- int i, pyargs_len, pykw_len, parms_len, ret_len, flag, err = 0, kw_tot = 0, kw_arg;
+ int i, pyargs_len, pykw_len, parms_len, ret_len, flag, err = 0, kw_tot = 0;
+ bool kw_arg;
PropertyRNA *pret_single = NULL;
void *retdata_single = NULL;
@@ -5014,7 +5071,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject
if (i < pyargs_len) {
item = PyTuple_GET_ITEM(args, i);
- kw_arg = FALSE;
+ kw_arg = false;
}
else if (kw != NULL) {
#if 0
@@ -5025,7 +5082,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject
if (item)
kw_tot++; /* make sure invalid keywords are not given */
- kw_arg = TRUE;
+ kw_arg = true;
}
i++; /* current argument */
@@ -5062,7 +5119,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject
char error_prefix[512];
PyErr_Clear(); /* re-raise */
- if (kw_arg == TRUE)
+ if (kw_arg == true)
BLI_snprintf(error_prefix, sizeof(error_prefix),
"%.200s.%.200s(): error with keyword argument \"%.200s\" - ",
RNA_struct_identifier(self_ptr->type),
@@ -5097,12 +5154,12 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject
DynStr *good_args = BLI_dynstr_new();
const char *arg_name, *bad_args_str, *good_args_str;
- int found = FALSE, first = TRUE;
+ bool found = false, first = true;
while (PyDict_Next(kw, &pos, &key, &value)) {
arg_name = _PyUnicode_AsString(key);
- found = FALSE;
+ found = false;
if (arg_name == NULL) { /* unlikely the argname is not a string but ignore if it is*/
PyErr_Clear();
@@ -5112,23 +5169,23 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject
RNA_parameter_list_begin(&parms, &iter);
for (; iter.valid; RNA_parameter_list_next(&iter)) {
parm = iter.parm;
- if (strcmp(arg_name, RNA_property_identifier(parm)) == 0) {
- found = TRUE;
+ if (STREQ(arg_name, RNA_property_identifier(parm))) {
+ found = true;
break;
}
}
RNA_parameter_list_end(&iter);
- if (found == FALSE) {
+ if (found == false) {
BLI_dynstr_appendf(bad_args, first ? "%s" : ", %s", arg_name);
- first = FALSE;
+ first = false;
}
}
}
/* list good args */
- first = TRUE;
+ first = true;
RNA_parameter_list_begin(&parms, &iter);
for (; iter.valid; RNA_parameter_list_next(&iter)) {
@@ -5137,7 +5194,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject
continue;
BLI_dynstr_appendf(good_args, first ? "%s" : ", %s", RNA_property_identifier(parm));
- first = FALSE;
+ first = false;
}
RNA_parameter_list_end(&iter);
@@ -5167,7 +5224,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject
BKE_reports_init(&reports, RPT_STORE);
RNA_function_call(C, &reports, self_ptr, self_func, &parms);
- err = (BPy_reports_to_error(&reports, PyExc_RuntimeError, TRUE));
+ err = (BPy_reports_to_error(&reports, PyExc_RuntimeError, true));
/* return value */
if (err != -1) {
@@ -5230,7 +5287,7 @@ static PyObject *pyrna_func_doc_get(BPy_FunctionRNA *self, void *UNUSED(closure)
PyObject *ret;
char *args;
- args = RNA_function_as_string_keywords(NULL, self->func, NULL, TRUE, TRUE);
+ args = RNA_function_as_string_keywords(NULL, self->func, NULL, true, true);
ret = PyUnicode_FromFormat("%.200s.%.200s(%.200s)\n%s",
RNA_struct_identifier(self->ptr.type),
@@ -5962,7 +6019,7 @@ static PyObject *pyrna_prop_collection_iter(BPy_PropertyRNA *self)
static PyObject *pyrna_prop_collection_iter_next(BPy_PropertyCollectionIterRNA *self)
{
- if (self->iter.valid == FALSE) {
+ if (self->iter.valid == false) {
PyErr_SetString(PyExc_StopIteration, "pyrna_prop_collection_iter stop");
return NULL;
}
@@ -6029,6 +6086,27 @@ static void pyrna_subtype_set_rna(PyObject *newclass, StructRNA *srna)
PyObject_SetAttr(newclass, bpy_intern_str_bl_rna, item);
Py_DECREF(item);
+ /* add staticmethods and classmethods */
+ {
+ const PointerRNA func_ptr = {{NULL}, srna, NULL};
+ const ListBase *lb;
+ Link *link;
+
+ lb = RNA_struct_type_functions(srna);
+ for (link = lb->first; link; link = link->next) {
+ FunctionRNA *func = (FunctionRNA *)link;
+ const int flag = RNA_function_flag(func);
+ if ((flag & FUNC_NO_SELF) && /* is staticmethod or classmethod */
+ (flag & FUNC_REGISTER) == false) /* is not for registration */
+ {
+ /* we may want to set the type of this later */
+ PyObject *func_py = pyrna_func_to_py(&func_ptr, func);
+ PyObject_SetAttrString(newclass, RNA_function_identifier(func), func_py);
+ Py_DECREF(func_py);
+ }
+ }
+ }
+
/* done with rna instance */
}
@@ -6068,7 +6146,7 @@ static PyObject *pyrna_srna_ExternalType(StructRNA *srna)
PyObject *newclass;
if (bpy_types_dict == NULL) {
- PyObject *bpy_types = PyImport_ImportModuleLevel((char *)"bpy_types", NULL, NULL, NULL, 0);
+ PyObject *bpy_types = PyImport_ImportModuleLevel("bpy_types", NULL, NULL, NULL, 0);
if (bpy_types == NULL) {
PyErr_Print();
@@ -6229,7 +6307,7 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr)
pyrna->ptr = *ptr;
#ifdef PYRNA_FREE_SUPPORT
- pyrna->freeptr = FALSE;
+ pyrna->freeptr = false;
#endif
#ifdef USE_PYRNA_STRUCT_REFERENCE
@@ -6309,15 +6387,15 @@ PyObject *pyrna_id_CreatePyObject(ID *id)
}
}
-int pyrna_id_FromPyObject(PyObject *obj, ID **id)
+bool pyrna_id_FromPyObject(PyObject *obj, ID **id)
{
if (BPy_StructRNA_Check(obj) && (RNA_struct_is_ID(((BPy_StructRNA *)obj)->ptr.type))) {
*id = ((BPy_StructRNA *)obj)->ptr.id.data;
- return TRUE;
+ return true;
}
else {
*id = NULL;
- return FALSE;
+ return false;
}
}
@@ -6502,6 +6580,9 @@ static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self)
static PyTypeObject pyrna_basetype_Type = BLANK_PYTHON_TYPE;
+/**
+ * Accessed from Python as 'bpy.types'
+ */
PyObject *BPY_rna_types(void)
{
BPy_BaseTypeRNA *self;
@@ -6528,7 +6609,7 @@ PyObject *BPY_rna_types(void)
return (PyObject *)self;
}
-StructRNA *pyrna_struct_as_srna(PyObject *self, int parent, const char *error_prefix)
+StructRNA *pyrna_struct_as_srna(PyObject *self, const bool parent, const char *error_prefix)
{
BPy_StructRNA *py_srna = NULL;
StructRNA *srna;
@@ -6602,7 +6683,7 @@ StructRNA *srna_from_self(PyObject *self, const char *error_prefix)
PyErr_Fetch(&error_type, &error_value, &error_traceback);
PyErr_Clear();
- srna = pyrna_struct_as_srna(self, 0, error_prefix);
+ srna = pyrna_struct_as_srna(self, false, error_prefix);
if (!PyErr_Occurred()) {
PyErr_Restore(error_type, error_value, error_traceback);
@@ -6742,14 +6823,14 @@ static int pyrna_deferred_register_class_recursive(StructRNA *srna, PyTypeObject
return pyrna_deferred_register_props(srna, py_class->tp_dict); /* getattr(..., "__dict__") returns a proxy */
}
-int pyrna_deferred_register_class(StructRNA *srna, PyObject *py_class)
+int pyrna_deferred_register_class(StructRNA *srna, PyTypeObject *py_class)
{
/* Panels and Menus don't need this
* save some time and skip the checks here */
if (!RNA_struct_idprops_register_check(srna))
return 0;
- return pyrna_deferred_register_class_recursive(srna, (PyTypeObject *)py_class);
+ return pyrna_deferred_register_class_recursive(srna, py_class);
}
/*-------------------- Type Registration ------------------------*/
@@ -6759,7 +6840,9 @@ static int rna_function_arg_count(FunctionRNA *func)
const ListBase *lb = RNA_function_defined_parameters(func);
PropertyRNA *parm;
Link *link;
- int count = (RNA_function_flag(func) & FUNC_NO_SELF) ? 0 : 1;
+ int flag = RNA_function_flag(func);
+ int is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE);
+ int count = is_staticmethod ? 0 : 1;
for (link = lb->first; link; link = link->next) {
parm = (PropertyRNA *)link;
@@ -6781,7 +6864,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
PyObject *py_class = (PyObject *)py_data;
PyObject *base_class = RNA_struct_py_type_get(srna);
PyObject *item;
- int i, flag, arg_count, func_arg_count;
+ int i, flag, is_staticmethod, arg_count, func_arg_count;
const char *py_class_name = ((PyTypeObject *)py_class)->tp_name; /* __name__ */
if (srna_base) {
@@ -6804,6 +6887,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
for (link = lb->first; link; link = link->next) {
func = (FunctionRNA *)link;
flag = RNA_function_flag(func);
+ is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE);
if (!(flag & FUNC_REGISTER))
continue;
@@ -6814,7 +6898,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
i++;
if (item == NULL) {
- if ((flag & FUNC_REGISTER_OPTIONAL) == 0) {
+ if ((flag & (FUNC_REGISTER_OPTIONAL & ~FUNC_REGISTER)) == 0) {
PyErr_Format(PyExc_AttributeError,
"expected %.200s, %.200s class to have an \"%.200s\" attribute",
class_type, py_class_name,
@@ -6826,7 +6910,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
}
else {
Py_DECREF(item); /* no need to keep a ref, the class owns it (technically we should keep a ref but...) */
- if (flag & FUNC_NO_SELF) {
+ if (is_staticmethod) {
if (PyMethod_Check(item) == 0) {
PyErr_Format(PyExc_TypeError,
"expected %.200s, %.200s class \"%.200s\" attribute to be a method, not a %.200s",
@@ -6850,9 +6934,9 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount;
/* note, the number of args we check for and the number of args we give to
- * @classmethods are different (quirk of python),
+ * @staticmethods are different (quirk of python),
* this is why rna_function_arg_count() doesn't return the value -1*/
- if (flag & FUNC_NO_SELF)
+ if (is_staticmethod)
func_arg_count++;
if (arg_count != func_arg_count) {
@@ -6883,7 +6967,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
/* Sneaky workaround to use the class name as the bl_idname */
#define BPY_REPLACEMENT_STRING(rna_attr, py_attr) \
- (strcmp(identifier, rna_attr) == 0) { \
+ (STREQ(identifier, rna_attr)) { \
item = PyObject_GetAttr(py_class, py_attr); \
if (item && item != Py_None) { \
if (pyrna_py_to_prop(dummyptr, prop, NULL, \
@@ -6894,7 +6978,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
} \
} \
Py_XDECREF(item); \
- } /* intendionally allow else here */
+ } /* intentionally allow else here */
if BPY_REPLACEMENT_STRING("bl_idname", bpy_intern_str___name__)
else if BPY_REPLACEMENT_STRING("bl_description", bpy_intern_str___doc__)
@@ -6937,8 +7021,10 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
PropertyRNA *parm;
ParameterIterator iter;
PointerRNA funcptr;
- int err = 0, i, flag, ret_len = 0;
- const char is_static = (RNA_function_flag(func) & FUNC_NO_SELF) != 0;
+ int err = 0, i, ret_len = 0;
+ int flag = RNA_function_flag(func);
+ const char is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE);
+ const char is_classmethod = (flag & FUNC_NO_SELF) && (flag & FUNC_USE_SELF_TYPE);
/* annoying!, need to check if the screen gets set to NULL which is a
* hint that the file was actually re-loaded. */
@@ -6973,7 +7059,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
bpy_context_set(C, &gilstate);
- if (!is_static) {
+ if (!(is_staticmethod || is_classmethod)) {
/* some datatypes (operator, render engine) can store PyObjects for re-use */
if (ptr->data) {
void **instance = RNA_struct_instance(ptr);
@@ -7013,7 +7099,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
if (py_class->tp_init) {
#ifdef USE_PEDANTIC_WRITE
const int prev_write = rna_disallow_writes;
- rna_disallow_writes = is_operator ? FALSE : TRUE; /* only operators can write on __init__ */
+ rna_disallow_writes = is_operator ? false : true; /* only operators can write on __init__ */
#endif
/* true in most cases even when the class its self doesn't define an __init__ function. */
@@ -7032,7 +7118,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
#else
const int prev_write = rna_disallow_writes;
- rna_disallow_writes = TRUE;
+ rna_disallow_writes = true;
/* 'almost' all the time calling the class isn't needed.
* We could just do... */
@@ -7064,18 +7150,21 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
}
}
- if (err != -1 && (is_static || py_class_instance)) { /* Initializing the class worked, now run its invoke function */
+ if (err != -1 && (is_staticmethod || is_classmethod || py_class_instance)) { /* Initializing the class worked, now run its invoke function */
PyObject *item = PyObject_GetAttrString((PyObject *)py_class, RNA_function_identifier(func));
-// flag = RNA_function_flag(func);
if (item) {
RNA_pointer_create(NULL, &RNA_Function, func, &funcptr);
args = PyTuple_New(rna_function_arg_count(func)); /* first arg is included in 'item' */
- if (is_static) {
+ if (is_staticmethod) {
i = 0;
}
+ else if (is_classmethod) {
+ PyTuple_SET_ITEM(args, 0, (PyObject *)py_class);
+ i = 1;
+ }
else {
PyTuple_SET_ITEM(args, 0, py_class_instance);
i = 1;
@@ -7105,7 +7194,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
}
#ifdef USE_PEDANTIC_WRITE
- rna_disallow_writes = is_readonly ? TRUE : FALSE;
+ rna_disallow_writes = is_readonly ? true : false;
#endif
/* *** Main Caller *** */
@@ -7114,7 +7203,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
/* *** Done Calling *** */
#ifdef USE_PEDANTIC_WRITE
- rna_disallow_writes = FALSE;
+ rna_disallow_writes = false;
#endif
RNA_parameter_list_end(&iter);
@@ -7209,7 +7298,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
if (err != 0) {
ReportList *reports;
/* alert the user, else they wont know unless they see the console. */
- if ((!is_static) &&
+ if ((!is_staticmethod) && (!is_classmethod) &&
(ptr->data) &&
(RNA_struct_is_a(ptr->type, &RNA_Operator)) &&
(is_valid_wm == (CTX_wm_manager(C) != NULL)))
@@ -7332,8 +7421,9 @@ PyDoc_STRVAR(pyrna_register_class_doc,
".. method:: register_class(cls)\n"
"\n"
" Register a subclass of a blender type in (:class:`bpy.types.Panel`,\n"
-" :class:`bpy.types.Menu`, :class:`bpy.types.Header`, :class:`bpy.types.Operator`,\n"
-" :class:`bpy.types.KeyingSetInfo`, :class:`bpy.types.RenderEngine`).\n"
+" :class:`bpy.types.UIList`, :class:`bpy.types.Menu`, :class:`bpy.types.Header`,\n"
+" :class:`bpy.types.Operator`, :class:`bpy.types.KeyingSetInfo`,\n"
+" :class:`bpy.types.RenderEngine`).\n"
"\n"
" If the class has a *register* class method it will be called\n"
" before registration.\n"
@@ -7378,7 +7468,7 @@ static PyObject *pyrna_register_class(PyObject *UNUSED(self), PyObject *py_class
}
/* warning: gets parent classes srna, only for the register function */
- srna = pyrna_struct_as_srna(py_class, 1, "register_class(...):");
+ srna = pyrna_struct_as_srna(py_class, true, "register_class(...):");
if (srna == NULL)
return NULL;
@@ -7414,7 +7504,7 @@ static PyObject *pyrna_register_class(PyObject *UNUSED(self), PyObject *py_class
srna_new = reg(CTX_data_main(C), &reports, py_class, identifier,
bpy_class_validate, bpy_class_call, bpy_class_free);
- if (BPy_reports_to_error(&reports, PyExc_RuntimeError, TRUE) == -1)
+ if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1)
return NULL;
/* python errors validating are not converted into reports so the check above will fail.
@@ -7434,7 +7524,7 @@ static PyObject *pyrna_register_class(PyObject *UNUSED(self), PyObject *py_class
*
* item = PyObject_GetAttrString(py_class, "__dict__");
*/
- if (pyrna_deferred_register_class(srna_new, py_class) != 0)
+ if (pyrna_deferred_register_class(srna_new, (PyTypeObject *)py_class) != 0)
return NULL;
/* call classed register method () */
@@ -7521,7 +7611,7 @@ static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_cla
return NULL;
}
- srna = pyrna_struct_as_srna(py_class, 0, "unregister_class(...):");
+ srna = pyrna_struct_as_srna(py_class, false, "unregister_class(...):");
if (srna == NULL)
return NULL;
@@ -7592,3 +7682,39 @@ static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_cla
Py_RETURN_NONE;
}
+
+/* currently this is fairly limited, we would need to make some way to split up
+ * pyrna_callback_classmethod_... if we want more then one callback per type */
+typedef struct BPyRNA_CallBack {
+ PyMethodDef py_method;
+ StructRNA *bpy_srna;
+} PyRNA_CallBack;
+
+static struct BPyRNA_CallBack pyrna_cb_methods[] = {
+ {{"draw_handler_add", (PyCFunction)pyrna_callback_classmethod_add, METH_VARARGS | METH_STATIC, ""}, &RNA_Space},
+ {{"draw_handler_remove", (PyCFunction)pyrna_callback_classmethod_remove, METH_VARARGS | METH_STATIC, ""}, &RNA_Space},
+ {{NULL, NULL, 0, NULL}, NULL}
+};
+
+void BPY_rna_register_cb(void)
+{
+ int i;
+
+ for (i = 0; pyrna_cb_methods[i].bpy_srna; i++) {
+ PyObject *cls;
+ PyObject *func;
+ PyObject *classmethod;
+ PyObject *args = PyTuple_New(1);
+
+ cls = pyrna_srna_Subtype(pyrna_cb_methods[i].bpy_srna);
+ func = PyCFunction_New(&pyrna_cb_methods[i].py_method, NULL);
+ PyTuple_SET_ITEM(args, 0, func);
+ classmethod = PyObject_CallObject((PyObject *)&PyClassMethod_Type, args);
+
+ PyObject_SetAttrString(cls, pyrna_cb_methods[i].py_method.ml_name, classmethod);
+
+ Py_DECREF(classmethod);
+ Py_DECREF(args); /* clears 'func' too */
+ Py_DECREF(cls);
+ }
+}
diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h
index 880ef4c2185..f546c2955e5 100644
--- a/source/blender/python/intern/bpy_rna.h
+++ b/source/blender/python/intern/bpy_rna.h
@@ -115,7 +115,7 @@ typedef struct {
#endif /* !USE_PYRNA_STRUCT_REFERENCE */
#ifdef PYRNA_FREE_SUPPORT
- int freeptr; /* needed in some cases if ptr.data is created on the fly, free when deallocing */
+ bool freeptr; /* needed in some cases if ptr.data is created on the fly, free when deallocing */
#endif /* PYRNA_FREE_SUPPORT */
} BPy_StructRNA;
@@ -164,20 +164,21 @@ typedef struct {
#define BPy_BaseTypeRNA BPy_PropertyRNA
StructRNA *srna_from_self(PyObject *self, const char *error_prefix);
-StructRNA *pyrna_struct_as_srna(PyObject *self, int parent, const char *error_prefix);
+StructRNA *pyrna_struct_as_srna(PyObject *self, const bool parent, const char *error_prefix);
void BPY_rna_init(void);
PyObject *BPY_rna_module(void);
void BPY_update_rna_module(void);
/*PyObject *BPY_rna_doc(void);*/
PyObject *BPY_rna_types(void);
+void BPY_rna_register_cb(void);
PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr);
PyObject *pyrna_prop_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop);
/* extern'd by other modules which don't deal closely with RNA */
PyObject *pyrna_id_CreatePyObject(struct ID *id);
-int pyrna_id_FromPyObject(PyObject *obj, struct ID **id);
+bool pyrna_id_FromPyObject(PyObject *obj, struct ID **id);
/* operators also need this to set args */
int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const char *error_prefix);
@@ -188,7 +189,7 @@ int pyrna_set_to_enum_bitfield(EnumPropertyItem *items, PyObject *value, int *r_
int pyrna_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *value, const char *error_prefix);
-int pyrna_deferred_register_class(struct StructRNA *srna, PyObject *py_class);
+int pyrna_deferred_register_class(struct StructRNA *srna, PyTypeObject *py_class);
/* called before stopping python */
void pyrna_alloc_types(void);
@@ -204,8 +205,8 @@ PyObject *pyrna_py_from_array_index(BPy_PropertyArrayRNA *self, PointerRNA *ptr,
PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop);
int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value);
-int pyrna_write_check(void);
-void pyrna_write_set(int val);
+bool pyrna_write_check(void);
+void pyrna_write_set(bool val);
void pyrna_invalidate(BPy_DummyPointerRNA *self);
int pyrna_struct_validity_check(BPy_StructRNA *pysrna);
diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c
index 69839514a12..b61ed55da06 100644
--- a/source/blender/python/intern/bpy_rna_anim.c
+++ b/source/blender/python/intern/bpy_rna_anim.c
@@ -44,6 +44,7 @@
#include "BKE_fcurve.h"
#include "RNA_access.h"
+#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -147,21 +148,29 @@ static int pyrna_struct_anim_args_parse(
/* internal use for insert and delete */
static int pyrna_struct_keyframe_parse(
PointerRNA *ptr, PyObject *args, PyObject *kw, const char *parse_str, const char *error_prefix,
- const char **path_full, int *index, float *cfra, const char **group_name) /* return values */
+ const char **path_full, int *index, float *cfra, const char **group_name, int *options) /* return values */
{
- static const char *kwlist[] = {"data_path", "index", "frame", "group", NULL};
+ static const char *kwlist[] = {"data_path", "index", "frame", "group", "options", NULL};
+ PyObject *pyoptions = NULL;
const char *path;
- /* note, parse_str MUST start with 's|ifs' */
- if (!PyArg_ParseTupleAndKeywords(args, kw, parse_str, (char **)kwlist, &path, index, cfra, group_name))
+ /* note, parse_str MUST start with 's|ifsO!' */
+ if (!PyArg_ParseTupleAndKeywords(args, kw, parse_str, (char **)kwlist, &path, index, cfra, group_name,
+ &PySet_Type, &pyoptions))
+ {
return -1;
+ }
- if (pyrna_struct_anim_args_parse(ptr, error_prefix, path, path_full, index) < 0)
+ if (pyrna_struct_anim_args_parse(ptr, error_prefix, path, path_full, index) == -1)
return -1;
if (*cfra == FLT_MAX)
*cfra = CTX_data_scene(BPy_GetContext())->r.cfra;
+ /* flag may be null (no option currently for remove keyframes e.g.). */
+ if (pyoptions && options && (pyrna_set_to_enum_bitfield(keying_flag_items, pyoptions, options, error_prefix) == -1))
+ return -1;
+
return 0; /* success */
}
@@ -172,12 +181,19 @@ char pyrna_struct_keyframe_insert_doc[] =
"\n"
" :arg data_path: path to the property to key, analogous to the fcurve's data path.\n"
" :type data_path: string\n"
-" :arg index: array index of the property to key. Defaults to -1 which will key all indices or a single channel if the property is not an array.\n"
+" :arg index: array index of the property to key. Defaults to -1 which will key all indices or a single channel "
+ "if the property is not an array.\n"
" :type index: int\n"
" :arg frame: The frame on which the keyframe is inserted, defaulting to the current frame.\n"
" :type frame: float\n"
" :arg group: The name of the group the F-Curve should be added to if it doesn't exist yet.\n"
" :type group: str\n"
+" :arg options: Some optional flags:\n"
+" 'NEEDED': Only insert keyframes where they're needed in the relevant F-Curves.\n"
+" 'VISUAL': Insert keyframes based on 'visual transforms'.\n"
+" 'XYZ_TO_RGB': Color for newly added transformation F-Curves (Location, Rotation, Scale) "
+ "and also Color is based on the transform axis.\n"
+" :type flag: set\n"
" :return: Success of keyframe insertion.\n"
" :rtype: boolean\n"
;
@@ -188,12 +204,13 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb
int index = -1;
float cfra = FLT_MAX;
const char *group_name = NULL;
+ int options = 0;
PYRNA_STRUCT_CHECK_OBJ(self);
if (pyrna_struct_keyframe_parse(&self->ptr, args, kw,
- "s|ifs:bpy_struct.keyframe_insert()", "bpy_struct.keyframe_insert()",
- &path_full, &index, &cfra, &group_name) == -1)
+ "s|ifsO!:bpy_struct.keyframe_insert()", "bpy_struct.keyframe_insert()",
+ &path_full, &index, &cfra, &group_name, &options) == -1)
{
return NULL;
}
@@ -203,10 +220,10 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb
BKE_reports_init(&reports, RPT_STORE);
- result = insert_keyframe(&reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0);
+ result = insert_keyframe(&reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, options);
MEM_freeN((void *)path_full);
- if (BPy_reports_to_error(&reports, PyExc_RuntimeError, TRUE) == -1)
+ if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1)
return NULL;
return PyBool_FromLong(result);
@@ -240,9 +257,9 @@ PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyOb
PYRNA_STRUCT_CHECK_OBJ(self);
if (pyrna_struct_keyframe_parse(&self->ptr, args, kw,
- "s|ifs:bpy_struct.keyframe_delete()",
+ "s|ifsO!:bpy_struct.keyframe_delete()",
"bpy_struct.keyframe_insert()",
- &path_full, &index, &cfra, &group_name) == -1)
+ &path_full, &index, &cfra, &group_name, NULL) == -1)
{
return NULL;
}
@@ -255,7 +272,7 @@ PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyOb
result = delete_keyframe(&reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0);
MEM_freeN((void *)path_full);
- if (BPy_reports_to_error(&reports, PyExc_RuntimeError, TRUE) == -1)
+ if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1)
return NULL;
return PyBool_FromLong(result);
@@ -285,7 +302,7 @@ PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args)
if (!PyArg_ParseTuple(args, "s|i:driver_add", &path, &index))
return NULL;
- if (pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_add():", path, &path_full, &index) < 0) {
+ if (pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_add():", path, &path_full, &index) == -1) {
return NULL;
}
else {
@@ -297,7 +314,7 @@ PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args)
result = ANIM_add_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0, DRIVER_TYPE_PYTHON);
- if (BPy_reports_to_error(&reports, PyExc_RuntimeError, TRUE) == -1)
+ if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1)
return NULL;
if (result) {
@@ -361,7 +378,7 @@ PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args)
if (!PyArg_ParseTuple(args, "s|i:driver_remove", &path, &index))
return NULL;
- if (pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_remove():", path, &path_full, &index) < 0) {
+ if (pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_remove():", path, &path_full, &index) == -1) {
return NULL;
}
else {
@@ -374,7 +391,7 @@ PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args)
MEM_freeN((void *)path_full);
- if (BPy_reports_to_error(&reports, PyExc_RuntimeError, TRUE) == -1)
+ if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1)
return NULL;
WM_event_add_notifier(BPy_GetContext(), NC_ANIMATION | ND_FCURVES_ORDER, NULL);
diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c
index f7114115a91..1043f68dbdb 100644
--- a/source/blender/python/intern/bpy_rna_callback.c
+++ b/source/blender/python/intern/bpy_rna_callback.c
@@ -32,23 +32,34 @@
#include "RNA_types.h"
+#include "BLI_utildefines.h"
+
#include "bpy_rna.h"
#include "bpy_rna_callback.h"
#include "bpy_util.h"
-#include "BLI_utildefines.h"
-
+#include "DNA_space_types.h"
#include "DNA_screen_types.h"
#include "RNA_access.h"
+#include "RNA_enum_types.h"
#include "BKE_context.h"
+#include "BKE_screen.h"
+
#include "ED_space_api.h"
/* use this to stop other capsules from being mis-used */
#define RNA_CAPSULE_ID "RNA_HANDLE"
#define RNA_CAPSULE_ID_INVALID "RNA_HANDLE_REMOVED"
+static EnumPropertyItem region_draw_mode_items[] = {
+ {REGION_DRAW_POST_PIXEL, "POST_PIXEL", 0, "Post Pixel", ""},
+ {REGION_DRAW_POST_VIEW, "POST_VIEW", 0, "Post View", ""},
+ {REGION_DRAW_PRE_VIEW, "PRE_VIEW", 0, "Pre View", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
static void cb_region_draw(const bContext *C, ARegion *UNUSED(ar), void *customdata)
{
PyObject *cb_func, *cb_args, *result;
@@ -56,8 +67,8 @@ static void cb_region_draw(const bContext *C, ARegion *UNUSED(ar), void *customd
bpy_context_set((bContext *)C, &gilstate);
- cb_func = PyTuple_GET_ITEM((PyObject *)customdata, 0);
- cb_args = PyTuple_GET_ITEM((PyObject *)customdata, 1);
+ cb_func = PyTuple_GET_ITEM((PyObject *)customdata, 1);
+ cb_args = PyTuple_GET_ITEM((PyObject *)customdata, 2);
result = PyObject_CallObject(cb_func, cb_args);
if (result) {
@@ -71,6 +82,7 @@ static void cb_region_draw(const bContext *C, ARegion *UNUSED(ar), void *customd
bpy_context_clear((bContext *)C, &gilstate);
}
+#if 0
PyObject *pyrna_callback_add(BPy_StructRNA *self, PyObject *args)
{
void *handle;
@@ -89,13 +101,7 @@ PyObject *pyrna_callback_add(BPy_StructRNA *self, PyObject *args)
if (RNA_struct_is_a(self->ptr.type, &RNA_Region)) {
if (cb_event_str) {
- static EnumPropertyItem region_draw_mode_items[] = {
- {REGION_DRAW_POST_PIXEL, "POST_PIXEL", 0, "Post Pixel", ""},
- {REGION_DRAW_POST_VIEW, "POST_VIEW", 0, "Post View", ""},
- {REGION_DRAW_PRE_VIEW, "PRE_VIEW", 0, "Pre View", ""},
- {0, NULL, 0, NULL, NULL}};
-
- if (pyrna_enum_value_from_id(region_draw_mode_items, cb_event_str, &cb_event, "bpy_struct.callback_add()") < 0) {
+ if (pyrna_enum_value_from_id(region_draw_mode_items, cb_event_str, &cb_event, "bpy_struct.callback_add()") == -1) {
return NULL;
}
}
@@ -136,6 +142,163 @@ PyObject *pyrna_callback_remove(BPy_StructRNA *self, PyObject *args)
ED_region_draw_cb_exit(((ARegion *)self->ptr.data)->type, handle);
}
+ else {
+ PyErr_SetString(PyExc_TypeError, "callback_remove(): type does not support callbacks");
+ return NULL;
+ }
+
+ /* don't allow reuse */
+ PyCapsule_SetName(py_handle, RNA_CAPSULE_ID_INVALID);
+
+ Py_RETURN_NONE;
+}
+#endif
+
+/* reverse of rna_Space_refine() */
+static eSpace_Type rna_Space_refine_reverse(StructRNA *srna)
+{
+ if (srna == &RNA_SpaceView3D) return SPACE_VIEW3D;
+ if (srna == &RNA_SpaceGraphEditor) return SPACE_IPO;
+ if (srna == &RNA_SpaceOutliner) return SPACE_OUTLINER;
+ if (srna == &RNA_SpaceProperties) return SPACE_BUTS;
+ if (srna == &RNA_SpaceFileBrowser) return SPACE_FILE;
+ if (srna == &RNA_SpaceImageEditor) return SPACE_IMAGE;
+ if (srna == &RNA_SpaceInfo) return SPACE_INFO;
+ if (srna == &RNA_SpaceSequenceEditor) return SPACE_SEQ;
+ if (srna == &RNA_SpaceTextEditor) return SPACE_TEXT;
+ if (srna == &RNA_SpaceDopeSheetEditor) return SPACE_ACTION;
+ if (srna == &RNA_SpaceNLA) return SPACE_NLA;
+ if (srna == &RNA_SpaceTimeline) return SPACE_TIME;
+ if (srna == &RNA_SpaceNodeEditor) return SPACE_NODE;
+ if (srna == &RNA_SpaceLogicEditor) return SPACE_LOGIC;
+ if (srna == &RNA_SpaceConsole) return SPACE_CONSOLE;
+ if (srna == &RNA_SpaceUserPreferences) return SPACE_USERPREF;
+ if (srna == &RNA_SpaceClipEditor) return SPACE_CLIP;
+ return -1;
+}
+
+PyObject *pyrna_callback_classmethod_add(PyObject *UNUSED(self), PyObject *args)
+{
+ void *handle;
+ PyObject *cls;
+ PyObject *cb_func, *cb_args;
+ char *cb_regiontype_str;
+ char *cb_event_str;
+ int cb_event;
+ int cb_regiontype;
+ StructRNA *srna;
+
+ if (PyTuple_GET_SIZE(args) < 2) {
+ PyErr_SetString(PyExc_ValueError, "handler_add(handle): expected at least 2 args");
+ return NULL;
+ }
+
+ cls = PyTuple_GET_ITEM(args, 0);
+ if (!(srna = pyrna_struct_as_srna(cls, false, "handler_add"))) {
+ return NULL;
+ }
+ cb_func = PyTuple_GET_ITEM(args, 1);
+ if (!PyCallable_Check(cb_func)) {
+ PyErr_SetString(PyExc_TypeError, "first argument isn't callable");
+ return NULL;
+ }
+
+ /* class spesific callbacks */
+ if (RNA_struct_is_a(srna, &RNA_Space)) {
+ if (!PyArg_ParseTuple(args, "OOO!ss:Space.draw_handler_add",
+ &cls, &cb_func, /* already assigned, no matter */
+ &PyTuple_Type, &cb_args, &cb_regiontype_str, &cb_event_str))
+ {
+ return NULL;
+ }
+
+ if (pyrna_enum_value_from_id(region_draw_mode_items, cb_event_str, &cb_event, "bpy_struct.callback_add()") == -1) {
+ return NULL;
+ }
+ else if (pyrna_enum_value_from_id(region_type_items, cb_regiontype_str, &cb_regiontype, "bpy_struct.callback_add()") == -1) {
+ return NULL;
+ }
+ else {
+ const eSpace_Type spaceid = rna_Space_refine_reverse(srna);
+ if (spaceid == -1) {
+ PyErr_Format(PyExc_TypeError, "unknown space type '%.200s'", RNA_struct_identifier(srna));
+ return NULL;
+ }
+ else {
+ SpaceType *st = BKE_spacetype_from_id(spaceid);
+ ARegionType *art = BKE_regiontype_from_id(st, cb_regiontype);
+
+ handle = ED_region_draw_cb_activate(art, cb_region_draw, (void *)args, cb_event);
+ Py_INCREF(args);
+ }
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "callback_add(): type does not support callbacks");
+ return NULL;
+ }
+
+ return PyCapsule_New((void *)handle, RNA_CAPSULE_ID, NULL);
+}
+
+PyObject *pyrna_callback_classmethod_remove(PyObject *UNUSED(self), PyObject *args)
+{
+ PyObject *cls;
+ PyObject *py_handle;
+ void *handle;
+ void *customdata;
+ StructRNA *srna;
+ char *cb_regiontype_str;
+ int cb_regiontype;
+
+ if (PyTuple_GET_SIZE(args) < 2) {
+ PyErr_SetString(PyExc_ValueError, "callback_remove(handle): expected at least 2 args");
+ return NULL;
+ }
+
+ cls = PyTuple_GET_ITEM(args, 0);
+ if (!(srna = pyrna_struct_as_srna(cls, false, "callback_remove"))) {
+ return NULL;
+ }
+ py_handle = PyTuple_GET_ITEM(args, 1);
+ handle = PyCapsule_GetPointer(py_handle, RNA_CAPSULE_ID);
+ if (handle == NULL) {
+ PyErr_SetString(PyExc_ValueError, "callback_remove(handle): NULL handle given, invalid or already removed");
+ return NULL;
+ }
+
+ if (RNA_struct_is_a(srna, &RNA_Space)) {
+ if (!PyArg_ParseTuple(args, "OO!s:Space.draw_handler_remove",
+ &cls, &PyCapsule_Type, &py_handle, /* already assigned, no matter */
+ &cb_regiontype_str))
+ {
+ return NULL;
+ }
+
+ customdata = ED_region_draw_cb_customdata(handle);
+ Py_DECREF((PyObject *)customdata);
+
+ if (pyrna_enum_value_from_id(region_type_items, cb_regiontype_str, &cb_regiontype, "bpy_struct.callback_remove()") == -1) {
+ return NULL;
+ }
+ else {
+ const eSpace_Type spaceid = rna_Space_refine_reverse(srna);
+ if (spaceid == -1) {
+ PyErr_Format(PyExc_TypeError, "unknown space type '%.200s'", RNA_struct_identifier(srna));
+ return NULL;
+ }
+ else {
+ SpaceType *st = BKE_spacetype_from_id(spaceid);
+ ARegionType *art = BKE_regiontype_from_id(st, cb_regiontype);
+
+ ED_region_draw_cb_exit(art, handle);
+ }
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "callback_remove(): type does not support callbacks");
+ return NULL;
+ }
/* don't allow reuse */
PyCapsule_SetName(py_handle, RNA_CAPSULE_ID_INVALID);
diff --git a/source/blender/python/intern/bpy_rna_callback.h b/source/blender/python/intern/bpy_rna_callback.h
index 7824d2b082d..4b801f35654 100644
--- a/source/blender/python/intern/bpy_rna_callback.h
+++ b/source/blender/python/intern/bpy_rna_callback.h
@@ -28,5 +28,10 @@
struct BPy_StructRNA;
struct PyObject;
+#if 0
PyObject *pyrna_callback_add(BPy_StructRNA *self, PyObject *args);
PyObject *pyrna_callback_remove(BPy_StructRNA *self, PyObject *args);
+#endif
+
+PyObject *pyrna_callback_classmethod_add(PyObject *cls, PyObject *args);
+PyObject *pyrna_callback_classmethod_remove(PyObject *cls, PyObject *args);
diff --git a/source/blender/python/intern/bpy_traceback.c b/source/blender/python/intern/bpy_traceback.c
index 48bf65a841b..81d12e9d9a6 100644
--- a/source/blender/python/intern/bpy_traceback.c
+++ b/source/blender/python/intern/bpy_traceback.c
@@ -29,6 +29,7 @@
#include <Python.h>
#include <frameobject.h>
+#include "BLI_utildefines.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
diff --git a/source/blender/python/intern/bpy_util.c b/source/blender/python/intern/bpy_util.c
index b7994eeccdc..b0b0f346944 100644
--- a/source/blender/python/intern/bpy_util.c
+++ b/source/blender/python/intern/bpy_util.c
@@ -29,9 +29,13 @@
#include <Python.h>
-#include "bpy_util.h"
+#include "BLI_utildefines.h"
#include "BLI_dynstr.h"
+
+#include "bpy_util.h"
+
#include "MEM_guardedalloc.h"
+
#include "BKE_report.h"
#include "BKE_context.h"
@@ -59,13 +63,13 @@ char *BPy_enum_as_string(EnumPropertyItem *item)
return cstring;
}
-short BPy_reports_to_error(ReportList *reports, PyObject *exception, const short clear)
+short BPy_reports_to_error(ReportList *reports, PyObject *exception, const bool clear)
{
char *report_str;
report_str = BKE_reports_string(reports, RPT_ERROR);
- if (clear) {
+ if (clear == true) {
BKE_reports_clear(reports);
}
diff --git a/source/blender/python/intern/bpy_util.h b/source/blender/python/intern/bpy_util.h
index b5f679b741f..b007e123cfc 100644
--- a/source/blender/python/intern/bpy_util.h
+++ b/source/blender/python/intern/bpy_util.h
@@ -39,7 +39,7 @@ char *BPy_enum_as_string(struct EnumPropertyItem *item);
#define BLANK_PYTHON_TYPE {PyVarObject_HEAD_INIT(NULL, 0) NULL}
/* error reporting */
-short BPy_reports_to_error(struct ReportList *reports, PyObject *exception, const short clear);
+short BPy_reports_to_error(struct ReportList *reports, PyObject *exception, const bool clear);
short BPy_errors_to_report(struct ReportList *reports);
/* TODO - find a better solution! */
diff --git a/source/blender/python/intern/gpu.c b/source/blender/python/intern/gpu.c
index 69fe0c48a41..747390abd0d 100644
--- a/source/blender/python/intern/gpu.c
+++ b/source/blender/python/intern/gpu.c
@@ -131,6 +131,7 @@ static PyObject *PyInit_gpu(void)
PyDict_SetItemString(d, # f, val); \
Py_DECREF(val)
+#if 0 /* UNUSED */
#define PY_OBJ_ADD_ID(d, s, f) \
val = PyUnicode_FromString(&s->f->id.name[2]); \
PyObject_SetAttrString(d, # f, val); \
@@ -145,6 +146,7 @@ static PyObject *PyInit_gpu(void)
val = PyUnicode_FromString(s->f); \
PyObject_SetAttrString(d, # f, val); \
Py_DECREF(val)
+#endif
PyDoc_STRVAR(GPU_export_shader_doc,
"export_shader(scene, material)\n"
diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c
index 202598233b6..47600e65351 100644
--- a/source/blender/python/mathutils/mathutils.c
+++ b/source/blender/python/mathutils/mathutils.c
@@ -340,7 +340,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 10
+#define MATHUTILS_TOT_CB 13
static Mathutils_Callback *mathutils_callbacks[MATHUTILS_TOT_CB] = {NULL};
unsigned char Mathutils_RegisterCallback(Mathutils_Callback *cb)
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index 05306f230d1..1fcebf29f28 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -829,10 +829,10 @@ static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args)
mat[0] = 1.0f;
mat[3] = 1.0f;
- if (strcmp(plane, "X") == 0) {
+ if (STREQ(plane, "X")) {
mat[2] = factor;
}
- else if (strcmp(plane, "Y") == 0) {
+ else if (STREQ(plane, "Y")) {
mat[1] = factor;
}
else {
@@ -855,15 +855,15 @@ static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args)
mat[4] = 1.0f;
mat[8] = 1.0f;
- if (strcmp(plane, "XY") == 0) {
+ if (STREQ(plane, "XY")) {
mat[6] = factor[0];
mat[7] = factor[1];
}
- else if (strcmp(plane, "XZ") == 0) {
+ else if (STREQ(plane, "XZ")) {
mat[3] = factor[0];
mat[5] = factor[1];
}
- else if (strcmp(plane, "YZ") == 0) {
+ else if (STREQ(plane, "YZ")) {
mat[1] = factor[0];
mat[2] = factor[1];
}
@@ -1025,13 +1025,13 @@ static PyObject *Matrix_resize_4x4(MatrixObject *self)
int col;
if (self->wrapped == Py_WRAP) {
- PyErr_SetString(PyExc_TypeError,
+ PyErr_SetString(PyExc_ValueError,
"Matrix.resize_4x4(): "
"cannot resize wrapped data - make a copy and resize that");
return NULL;
}
if (self->cb_user) {
- PyErr_SetString(PyExc_TypeError,
+ PyErr_SetString(PyExc_ValueError,
"Matrix.resize_4x4(): "
"cannot resize owned data - make a copy and resize that");
return NULL;
@@ -1080,7 +1080,7 @@ static PyObject *Matrix_to_4x4(MatrixObject *self)
}
/* TODO, 2x2 matrix */
- PyErr_SetString(PyExc_TypeError,
+ PyErr_SetString(PyExc_ValueError,
"Matrix.to_4x4(): "
"inappropriate matrix size");
return NULL;
@@ -1102,7 +1102,7 @@ static PyObject *Matrix_to_3x3(MatrixObject *self)
return NULL;
if ((self->num_row < 3) || (self->num_col < 3)) {
- PyErr_SetString(PyExc_TypeError,
+ PyErr_SetString(PyExc_ValueError,
"Matrix.to_3x3(): inappropriate matrix size");
return NULL;
}
@@ -1126,7 +1126,7 @@ static PyObject *Matrix_to_translation(MatrixObject *self)
return NULL;
if ((self->num_row < 3) || self->num_col < 4) {
- PyErr_SetString(PyExc_TypeError,
+ PyErr_SetString(PyExc_ValueError,
"Matrix.to_translation(): "
"inappropriate matrix size");
return NULL;
@@ -1156,7 +1156,7 @@ static PyObject *Matrix_to_scale(MatrixObject *self)
/*must be 3-4 cols, 3-4 rows, square matrix */
if ((self->num_row < 3) || (self->num_col < 3)) {
- PyErr_SetString(PyExc_TypeError,
+ PyErr_SetString(PyExc_ValueError,
"Matrix.to_scale(): "
"inappropriate matrix size, 3x3 minimum size");
return NULL;
@@ -1194,7 +1194,7 @@ static PyObject *Matrix_invert(MatrixObject *self)
return NULL;
if (self->num_col != self->num_row) {
- PyErr_SetString(PyExc_TypeError,
+ PyErr_SetString(PyExc_ValueError,
"Matrix.invert(ed): "
"only square matrices are supported");
return NULL;
@@ -1222,7 +1222,7 @@ static PyObject *Matrix_invert(MatrixObject *self)
break;
}
default:
- PyErr_Format(PyExc_TypeError,
+ PyErr_Format(PyExc_ValueError,
"Matrix invert(ed): size (%d) unsupported",
(int)self->num_col);
return NULL;
@@ -1281,7 +1281,7 @@ static PyObject *Matrix_adjugate(MatrixObject *self)
return NULL;
if (self->num_col != self->num_row) {
- PyErr_SetString(PyExc_TypeError,
+ PyErr_SetString(PyExc_ValueError,
"Matrix.adjugate(d): "
"only square matrices are supported");
return NULL;
@@ -1311,7 +1311,7 @@ static PyObject *Matrix_adjugate(MatrixObject *self)
break;
}
default:
- PyErr_Format(PyExc_TypeError,
+ PyErr_Format(PyExc_ValueError,
"Matrix adjugate(d): size (%d) unsupported",
(int)self->num_col);
return NULL;
@@ -1357,7 +1357,7 @@ static PyObject *Matrix_rotate(MatrixObject *self, PyObject *value)
return NULL;
if (self->num_row != 3 || self->num_col != 3) {
- PyErr_SetString(PyExc_TypeError,
+ PyErr_SetString(PyExc_ValueError,
"Matrix.rotate(): "
"must have 3x3 dimensions");
return NULL;
@@ -1390,7 +1390,7 @@ static PyObject *Matrix_decompose(MatrixObject *self)
float size[3];
if (self->num_row != 4 || self->num_col != 4) {
- PyErr_SetString(PyExc_TypeError,
+ PyErr_SetString(PyExc_ValueError,
"Matrix.decompose(): "
"inappropriate matrix size - expects 4x4 matrix");
return NULL;
@@ -1476,7 +1476,7 @@ static PyObject *Matrix_determinant(MatrixObject *self)
return NULL;
if (self->num_col != self->num_row) {
- PyErr_SetString(PyExc_TypeError,
+ PyErr_SetString(PyExc_ValueError,
"Matrix.determinant(): "
"only square matrices are supported");
return NULL;
@@ -1498,7 +1498,7 @@ static PyObject *Matrix_transpose(MatrixObject *self)
return NULL;
if (self->num_col != self->num_row) {
- PyErr_SetString(PyExc_TypeError,
+ PyErr_SetString(PyExc_ValueError,
"Matrix.transpose(d): "
"only square matrices are supported");
return NULL;
@@ -1533,6 +1533,53 @@ static PyObject *Matrix_transposed(MatrixObject *self)
return matrix__apply_to_copy((PyNoArgsFunction)Matrix_transpose, self);
}
+/*---------------------------matrix.normalize() ------------------*/
+PyDoc_STRVAR(Matrix_normalize_doc,
+".. method:: normalize()\n"
+"\n"
+" Normalize each of the matrix columns.\n"
+);
+static PyObject *Matrix_normalize(MatrixObject *self)
+{
+ if (BaseMath_ReadCallback(self) == -1)
+ return NULL;
+
+ if (self->num_col != self->num_row) {
+ PyErr_SetString(PyExc_ValueError,
+ "Matrix.normalize(): "
+ "only square matrices are supported");
+ return NULL;
+ }
+
+ if (self->num_col == 3) {
+ normalize_m3((float (*)[3])self->matrix);
+ }
+ else if (self->num_col == 4) {
+ normalize_m4((float (*)[4])self->matrix);
+ }
+ else {
+ PyErr_SetString(PyExc_ValueError,
+ "Matrix.normalize(): "
+ "can only use a 3x3 or 4x4 matrix");
+ }
+
+ (void)BaseMath_WriteCallback(self);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(Matrix_normalized_doc,
+".. method:: normalized()\n"
+"\n"
+" Return a column normalized matrix\n"
+"\n"
+" :return: a column normalized matrix\n"
+" :rtype: :class:`Matrix`\n"
+);
+static PyObject *Matrix_normalized(MatrixObject *self)
+{
+ return matrix__apply_to_copy((PyNoArgsFunction)Matrix_normalize, self);
+}
+
/*---------------------------matrix.zero() -----------------------*/
PyDoc_STRVAR(Matrix_zero_doc,
".. method:: zero()\n"
@@ -1568,7 +1615,7 @@ static PyObject *Matrix_identity(MatrixObject *self)
return NULL;
if (self->num_col != self->num_row) {
- PyErr_SetString(PyExc_TypeError,
+ PyErr_SetString(PyExc_ValueError,
"Matrix.identity(): "
"only square matrices are supported");
return NULL;
@@ -1924,7 +1971,7 @@ static PyObject *Matrix_add(PyObject *m1, PyObject *m2)
return NULL;
if (mat1->num_col != mat2->num_col || mat1->num_row != mat2->num_row) {
- PyErr_SetString(PyExc_TypeError,
+ PyErr_SetString(PyExc_ValueError,
"Matrix addition: "
"matrices must have the same dimensions for this operation");
return NULL;
@@ -1956,7 +2003,7 @@ static PyObject *Matrix_sub(PyObject *m1, PyObject *m2)
return NULL;
if (mat1->num_col != mat2->num_col || mat1->num_row != mat2->num_row) {
- PyErr_SetString(PyExc_TypeError,
+ PyErr_SetString(PyExc_ValueError,
"Matrix addition: "
"matrices must have the same dimensions for this operation");
return NULL;
@@ -2371,6 +2418,8 @@ static struct PyMethodDef Matrix_methods[] = {
/* operate on original or copy */
{"transpose", (PyCFunction) Matrix_transpose, METH_NOARGS, Matrix_transpose_doc},
{"transposed", (PyCFunction) Matrix_transposed, METH_NOARGS, Matrix_transposed_doc},
+ {"normalize", (PyCFunction) Matrix_normalize, METH_NOARGS, Matrix_normalize_doc},
+ {"normalized", (PyCFunction) Matrix_normalized, METH_NOARGS, Matrix_normalized_doc},
{"invert", (PyCFunction) Matrix_invert, METH_NOARGS, Matrix_invert_doc},
{"inverted", (PyCFunction) Matrix_inverted, METH_NOARGS, Matrix_inverted_doc},
{"adjugate", (PyCFunction) Matrix_adjugate, METH_NOARGS, Matrix_adjugate_doc},
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index 1db0538eb07..91cff67fc49 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -251,6 +251,86 @@ static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject
}
}
+/* Line-Line intersection using algorithm from mathworld.wolfram.com */
+
+PyDoc_STRVAR(M_Geometry_intersect_sphere_sphere_2d_doc,
+".. function:: intersect_sphere_sphere_2d(p_a, radius_a, p_b, radius_b)\n"
+"\n"
+" Returns 2 points on between intersecting circles.\n"
+"\n"
+" :arg p_a: Center of the first circle\n"
+" :type p_a: :class:`mathutils.Vector`\n"
+" :arg radius_a: Radius of the first circle\n"
+" :type radius_a: float\n"
+" :arg p_b: Center of the second circle\n"
+" :type p_b: :class:`mathutils.Vector`\n"
+" :arg radius_b: Radius of the second circle\n"
+" :type radius_b: float\n"
+" :rtype: tuple of :class:`mathutils.Vector`'s or None when there is no intersection\n"
+);
+static PyObject *M_Geometry_intersect_sphere_sphere_2d(PyObject *UNUSED(self), PyObject *args)
+{
+ PyObject *ret;
+ VectorObject *vec_a, *vec_b;
+ float *v_a, *v_b;
+ 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))
+ {
+ return NULL;
+ }
+
+ if (BaseMath_ReadCallback(vec_a) == -1 ||
+ BaseMath_ReadCallback(vec_b) == -1)
+ {
+ 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);
+
+ if (/* out of range */
+ (dist > rad_a + rad_b) ||
+ /* fully-contained in the other */
+ (dist < abs(rad_a - rad_b)) ||
+ /* co-incident */
+ (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);
+ }
+ else {
+ const float dist_delta = ((rad_a * rad_a) - (rad_b * rad_b) + (dist * dist)) / (2.0f * dist);
+ const float h = powf(fabsf((rad_a * rad_a) - (dist_delta * dist_delta)), 0.5f);
+ float i_cent[2];
+ float i1[2], i2[2];
+
+ i_cent[0] = v_a[0] + ((v_ab[0] * dist_delta) / dist);
+ i_cent[1] = v_a[1] + ((v_ab[1] * dist_delta) / dist);
+
+ i1[0] = i_cent[0] + h * v_ab[1] / dist;
+ i1[1] = i_cent[1] - h * v_ab[0] / dist;
+
+ 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));
+ }
+
+ return ret;
+}
+
PyDoc_STRVAR(M_Geometry_normal_doc,
".. function:: normal(v1, v2, v3, v4=None)\n"
"\n"
@@ -1102,7 +1182,7 @@ static PyObject *M_Geometry_interpolate_bezier(PyObject *UNUSED(self), PyObject
return NULL;
}
- dims = MAX4(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size);
+ 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];
@@ -1376,6 +1456,7 @@ static PyMethodDef M_Geometry_methods[] = {
{"intersect_line_sphere", (PyCFunction) M_Geometry_intersect_line_sphere, METH_VARARGS, M_Geometry_intersect_line_sphere_doc},
{"intersect_line_sphere_2d", (PyCFunction) M_Geometry_intersect_line_sphere_2d, METH_VARARGS, M_Geometry_intersect_line_sphere_2d_doc},
{"distance_point_to_plane", (PyCFunction) M_Geometry_distance_point_to_plane, METH_VARARGS, M_Geometry_distance_point_to_plane_doc},
+ {"intersect_sphere_sphere_2d", (PyCFunction) M_Geometry_intersect_sphere_sphere_2d, METH_VARARGS, M_Geometry_intersect_sphere_sphere_2d_doc},
{"area_tri", (PyCFunction) M_Geometry_area_tri, METH_VARARGS, M_Geometry_area_tri_doc},
{"normal", (PyCFunction) M_Geometry_normal, METH_VARARGS, M_Geometry_normal_doc},
{"barycentric_transform", (PyCFunction) M_Geometry_barycentric_transform, METH_VARARGS, M_Geometry_barycentric_transform_doc},
diff --git a/source/blender/python/mathutils/mathutils_noise.c b/source/blender/python/mathutils/mathutils_noise.c
index 4977663038d..31663bd369d 100644
--- a/source/blender/python/mathutils/mathutils_noise.c
+++ b/source/blender/python/mathutils/mathutils_noise.c
@@ -870,16 +870,16 @@ PyMODINIT_FUNC PyInit_mathutils_noise_types(void)
{
PyObject *submodule = PyModule_Create(&M_NoiseTypes_module_def);
- PyModule_AddIntConstant(submodule, (char *)"BLENDER", TEX_BLENDER);
- PyModule_AddIntConstant(submodule, (char *)"STDPERLIN", TEX_STDPERLIN);
- PyModule_AddIntConstant(submodule, (char *)"NEWPERLIN", TEX_NEWPERLIN);
- PyModule_AddIntConstant(submodule, (char *)"VORONOI_F1", TEX_VORONOI_F1);
- PyModule_AddIntConstant(submodule, (char *)"VORONOI_F2", TEX_VORONOI_F2);
- PyModule_AddIntConstant(submodule, (char *)"VORONOI_F3", TEX_VORONOI_F3);
- PyModule_AddIntConstant(submodule, (char *)"VORONOI_F4", TEX_VORONOI_F4);
- PyModule_AddIntConstant(submodule, (char *)"VORONOI_F2F1", TEX_VORONOI_F2F1);
- PyModule_AddIntConstant(submodule, (char *)"VORONOI_CRACKLE", TEX_VORONOI_CRACKLE);
- PyModule_AddIntConstant(submodule, (char *)"CELLNOISE", TEX_CELLNOISE);
+ PyModule_AddIntConstant(submodule, "BLENDER", TEX_BLENDER);
+ PyModule_AddIntConstant(submodule, "STDPERLIN", TEX_STDPERLIN);
+ PyModule_AddIntConstant(submodule, "NEWPERLIN", TEX_NEWPERLIN);
+ PyModule_AddIntConstant(submodule, "VORONOI_F1", TEX_VORONOI_F1);
+ PyModule_AddIntConstant(submodule, "VORONOI_F2", TEX_VORONOI_F2);
+ PyModule_AddIntConstant(submodule, "VORONOI_F3", TEX_VORONOI_F3);
+ PyModule_AddIntConstant(submodule, "VORONOI_F4", TEX_VORONOI_F4);
+ PyModule_AddIntConstant(submodule, "VORONOI_F2F1", TEX_VORONOI_F2F1);
+ PyModule_AddIntConstant(submodule, "VORONOI_CRACKLE", TEX_VORONOI_CRACKLE);
+ PyModule_AddIntConstant(submodule, "CELLNOISE", TEX_CELLNOISE);
return submodule;
}
@@ -900,13 +900,13 @@ PyMODINIT_FUNC PyInit_mathutils_noise_metrics(void)
{
PyObject *submodule = PyModule_Create(&M_NoiseMetrics_module_def);
- PyModule_AddIntConstant(submodule, (char *)"DISTANCE", TEX_DISTANCE);
- PyModule_AddIntConstant(submodule, (char *)"DISTANCE_SQUARED", TEX_DISTANCE_SQUARED);
- PyModule_AddIntConstant(submodule, (char *)"MANHATTAN", TEX_MANHATTAN);
- PyModule_AddIntConstant(submodule, (char *)"CHEBYCHEV", TEX_CHEBYCHEV);
- PyModule_AddIntConstant(submodule, (char *)"MINKOVSKY_HALF", TEX_MINKOVSKY_HALF);
- PyModule_AddIntConstant(submodule, (char *)"MINKOVSKY_FOUR", TEX_MINKOVSKY_FOUR);
- PyModule_AddIntConstant(submodule, (char *)"MINKOVSKY", TEX_MINKOVSKY);
+ PyModule_AddIntConstant(submodule, "DISTANCE", TEX_DISTANCE);
+ PyModule_AddIntConstant(submodule, "DISTANCE_SQUARED", TEX_DISTANCE_SQUARED);
+ PyModule_AddIntConstant(submodule, "MANHATTAN", TEX_MANHATTAN);
+ PyModule_AddIntConstant(submodule, "CHEBYCHEV", TEX_CHEBYCHEV);
+ PyModule_AddIntConstant(submodule, "MINKOVSKY_HALF", TEX_MINKOVSKY_HALF);
+ PyModule_AddIntConstant(submodule, "MINKOVSKY_FOUR", TEX_MINKOVSKY_FOUR);
+ PyModule_AddIntConstant(submodule, "MINKOVSKY", TEX_MINKOVSKY);
return submodule;
}
diff --git a/source/blender/quicktime/SConscript b/source/blender/quicktime/SConscript
index db1d4a4f1ab..a32f325de24 100644
--- a/source/blender/quicktime/SConscript
+++ b/source/blender/quicktime/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
diff --git a/source/blender/quicktime/apple/qtkit_export.m b/source/blender/quicktime/apple/qtkit_export.m
index e0858cd5ec2..7e7c986c6ea 100644
--- a/source/blender/quicktime/apple/qtkit_export.m
+++ b/source/blender/quicktime/apple/qtkit_export.m
@@ -61,8 +61,8 @@
#import <QTKit/QTKit.h>
#include <AudioToolbox/AudioToolbox.h>
-#if (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4) || !__LP64__
-#error 64 bit build & OSX 10.5 minimum are needed for QTKit
+#if MAC_OS_X_VERSION_MIN_REQUIRED <= 1040
+#error OSX 10.5 minimum is needed for QTKit
#endif
#include "quicktime_import.h"
@@ -295,8 +295,8 @@ static OSStatus AudioConverterInputCallback(AudioConverterRef inAudioConverter,
qtexport->audioTotalExportedFrames += *ioNumberDataPackets;
- AUD_readDevice(qtexport->audioInputDevice, (UInt8*)qtexport->audioInputBuffer,
- qtexport->audioInputFormat.mFramesPerPacket * *ioNumberDataPackets);
+ AUD_readDevice(qtexport->audioInputDevice, (UInt8 *)qtexport->audioInputBuffer,
+ qtexport->audioInputFormat.mFramesPerPacket * *ioNumberDataPackets);
ioData->mBuffers[0].mDataByteSize = qtexport->audioInputFormat.mBytesPerPacket * *ioNumberDataPackets;
ioData->mBuffers[0].mData = qtexport->audioInputBuffer;
@@ -357,7 +357,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R
tmpnam(name);
strcat(name, extension);
- outputFileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,(UInt8*) name, strlen(name), false);
+ outputFileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,(UInt8 *)name, strlen(name), false);
if (outputFileURL) {
@@ -557,7 +557,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R
[qtexport->movie setAttribute:[NSNumber numberWithBool:YES] forKey:QTMovieEditableAttribute];
[qtexport->movie setAttribute:@"Made with Blender" forKey:QTMovieCopyrightAttribute];
- qtexport->frameDuration = QTMakeTime(rd->frs_sec_base*1000, rd->frs_sec*1000);
+ qtexport->frameDuration = QTMakeTime(rd->frs_sec_base * 1000, rd->frs_sec * 1000);
/* specifying the codec attributes : try to retrieve them from render data first*/
if (rd->qtcodecsettings.codecType) {
diff --git a/source/blender/quicktime/apple/qtkit_import.m b/source/blender/quicktime/apple/qtkit_import.m
index 2e910e38871..974c2555ee5 100644
--- a/source/blender/quicktime/apple/qtkit_import.m
+++ b/source/blender/quicktime/apple/qtkit_import.m
@@ -32,6 +32,7 @@
#include "BLO_sys_types.h"
#include "BKE_global.h"
+#include "BLI_utildefines.h"
#include "BLI_dynstr.h"
#include "BLI_path_util.h"
diff --git a/source/blender/quicktime/apple/quicktime_export.c b/source/blender/quicktime/apple/quicktime_export.c
index 1c4ab5a4b0e..5e114bf7379 100644
--- a/source/blender/quicktime/apple/quicktime_export.c
+++ b/source/blender/quicktime/apple/quicktime_export.c
@@ -559,7 +559,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R
#ifdef __APPLE__
EnterMoviesOnThread(0);
- sprintf(theFullPath, "%s", name);
+ strcpy(theFullPath, name);
/* hack: create an empty file to make FSPathMakeRef() happy */
myFile = open(theFullPath, O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRUSR | S_IWUSR);
@@ -575,7 +575,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R
#endif
#ifdef _WIN32
qtname = get_valid_qtname(name);
- sprintf(theFullPath, "%s", qtname);
+ strcpy(theFullPath, qtname);
strcpy(name, qtname);
MEM_freeN(qtname);
@@ -905,7 +905,7 @@ int fromcocoa_request_qtcodec_settings(bContext *C, wmOperator *op)
void SCENE_OT_render_data_set_quicktime_codec(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Change codec";
+ ot->name = "Change Codec";
ot->description = "Change Quicktime codec Settings";
ot->idname = "SCENE_OT_render_data_set_quicktime_codec";
diff --git a/source/blender/quicktime/apple/quicktime_import.c b/source/blender/quicktime/apple/quicktime_import.c
index e44eba2bfe0..9481a37e3c7 100644
--- a/source/blender/quicktime/apple/quicktime_import.c
+++ b/source/blender/quicktime/apple/quicktime_import.c
@@ -210,13 +210,13 @@ int anim_is_quicktime(const char *name)
if (QTIME_DEBUG) printf("qt: checking as movie: %s\n", name);
#ifdef __APPLE__
- sprintf(theFullPath, "%s", name);
+ strcpy(theFullPath, name);
err = FSPathMakeRef(theFullPath, &myRef, 0);
err = FSGetCatalogInfo(&myRef, kFSCatInfoNone, NULL, NULL, &theFSSpec, NULL);
#else
qtname = get_valid_qtname(name);
- sprintf(theFullPath, "%s", qtname);
+ strcpy(theFullPath, qtname);
MEM_freeN(qtname);
CopyCStringToPascal(theFullPath, dst);
@@ -461,13 +461,13 @@ int startquicktime(struct anim *anim)
if (QTIME_DEBUG) printf("qt: attempting to load as movie %s\n", anim->name);
#ifdef __APPLE__
- sprintf(theFullPath, "%s", anim->name);
+ strcpy(theFullPath, anim->name);
err = FSPathMakeRef(theFullPath, &myRef, 0);
err = FSGetCatalogInfo(&myRef, kFSCatInfoNone, NULL, NULL, &theFSSpec, NULL);
#else
qtname = get_valid_qtname(anim->name);
- sprintf(theFullPath, "%s", qtname);
+ strcpy(theFullPath, qtname);
MEM_freeN(qtname);
CopyCStringToPascal(theFullPath, dst);
@@ -592,7 +592,7 @@ int imb_is_a_quicktime(char *name)
return 0;
}
- sprintf(theFullPath, "%s", name);
+ strcpy(theFullPath, name);
#ifdef __APPLE__
err = FSPathMakeRef(theFullPath, &myRef, 0);
err = FSGetCatalogInfo(&myRef, kFSCatInfoNone, NULL, NULL, &theFSSpec, NULL);
diff --git a/source/blender/quicktime/quicktime_export.h b/source/blender/quicktime/quicktime_export.h
index a3469ddafde..55323c05278 100644
--- a/source/blender/quicktime/quicktime_export.h
+++ b/source/blender/quicktime/quicktime_export.h
@@ -65,14 +65,14 @@ void filepath_qt(char *string, struct RenderData *rd);
void quicktime_verify_image_type(struct RenderData *rd, struct ImageFormatData *imf); //used by RNA for defaults values init, if needed
/*Video codec type*/
int quicktime_get_num_videocodecs(void);
-QuicktimeCodecTypeDesc* quicktime_get_videocodecType_desc(int indexValue);
+QuicktimeCodecTypeDesc *quicktime_get_videocodecType_desc(int indexValue);
int quicktime_rnatmpvalue_from_videocodectype(int codecType);
int quicktime_videocodecType_from_rnatmpvalue(int rnatmpvalue);
#ifdef USE_QTKIT
/*Audio codec type*/
int quicktime_get_num_audiocodecs(void);
-QuicktimeCodecTypeDesc* quicktime_get_audiocodecType_desc(int indexValue);
+QuicktimeCodecTypeDesc *quicktime_get_audiocodecType_desc(int indexValue);
int quicktime_rnatmpvalue_from_audiocodectype(int codecType);
int quicktime_audiocodecType_from_rnatmpvalue(int rnatmpvalue);
#endif
@@ -87,7 +87,7 @@ void makeqtstring(struct RenderData *rd, char *string); //for playanim.c
-#if (defined(USE_QTKIT) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 && __LP64__)
+#if (defined(USE_QTKIT) && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 && __LP64__)
//Include the quicktime codec types constants that are missing in QTKitDefines.h
enum {
kRawCodecType = 'raw ',
diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt
index a2d6e27bcb7..4f1d0d234fc 100644
--- a/source/blender/render/CMakeLists.txt
+++ b/source/blender/render/CMakeLists.txt
@@ -54,12 +54,14 @@ set(SRC
intern/raytrace/rayobject_qbvh.cpp
intern/raytrace/rayobject_rtbuild.cpp
intern/raytrace/rayobject_vbvh.cpp
+ intern/source/bake.c
intern/source/convertblender.c
intern/source/envmap.c
intern/source/external_engine.c
intern/source/gammaCorrectionTables.c
intern/source/imagetexture.c
intern/source/initrender.c
+ intern/source/multires_bake.c
intern/source/occlusion.c
intern/source/pipeline.c
intern/source/pixelblending.c
@@ -83,6 +85,7 @@ set(SRC
intern/source/zbuf.c
extern/include/RE_engine.h
+ extern/include/RE_multires_bake.h
extern/include/RE_pipeline.h
extern/include/RE_render_ext.h
extern/include/RE_shader_ext.h
@@ -141,6 +144,13 @@ if(WITH_MOD_SMOKE)
add_definitions(-DWITH_SMOKE)
endif()
+if(WITH_FREESTYLE)
+ list(APPEND INC
+ ../freestyle
+ )
+ add_definitions(-DWITH_FREESTYLE)
+endif()
+
if(WITH_CODEC_QUICKTIME)
list(APPEND INC
../quicktime
@@ -155,8 +165,13 @@ if(WITH_GAMEENGINE)
add_definitions(-DWITH_GAMEENGINE)
endif()
+if(WITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
+endif()
+
if(APPLE)
- if(CMAKE_OSX_ARCHITECTURES MATCHES "i386" OR CMAKE_OSX_ARCHITECTURES MATCHES "x86_64")
+ # SSE math is enabled by default on x86_64
+ if(CMAKE_OSX_ARCHITECTURES MATCHES "i386")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -mfpmath=sse")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mfpmath=sse")
endif()
diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript
index 8a044b19a79..9606c2c0f9c 100644
--- a/source/blender/render/SConscript
+++ b/source/blender/render/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('intern/source/*.c')
@@ -57,9 +83,16 @@ if env['WITH_BF_QUICKTIME']:
if env['WITH_BF_OPENEXR']:
defs.append('WITH_OPENEXR')
+if env['WITH_BF_FREESTYLE']:
+ incs += ' ../freestyle'
+ defs.append('WITH_FREESTYLE')
+
if env['WITH_BF_GAMEENGINE']:
defs.append('WITH_GAMEENGINE')
+if env['WITH_BF_INTERNATIONAL']:
+ defs.append('WITH_INTERNATIONAL')
+
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_engine.h b/source/blender/render/extern/include/RE_engine.h
index d2ffc3a0e26..cb35b0045f7 100644
--- a/source/blender/render/extern/include/RE_engine.h
+++ b/source/blender/render/extern/include/RE_engine.h
@@ -33,12 +33,14 @@
#define __RE_ENGINE_H__
#include "DNA_listBase.h"
+#include "DNA_scene_types.h"
#include "RNA_types.h"
struct bNode;
struct bNodeTree;
struct Object;
struct Render;
+struct RenderData;
struct RenderEngine;
struct RenderEngineType;
struct RenderLayer;
@@ -61,6 +63,8 @@ struct Scene;
#define RE_ENGINE_DO_DRAW 4
#define RE_ENGINE_DO_UPDATE 8
#define RE_ENGINE_RENDERING 16
+#define RE_ENGINE_HIGHLIGHT_TILES 32
+#define RE_ENGINE_USED_FOR_VIEWPORT 64
extern ListBase R_engines;
@@ -104,6 +108,7 @@ typedef struct RenderEngine {
} RenderEngine;
RenderEngine *RE_engine_create(RenderEngineType *type);
+RenderEngine *RE_engine_create_ex(RenderEngineType *type, bool use_for_viewport);
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);
@@ -130,5 +135,8 @@ 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);
+struct RenderData *RE_engine_get_render_data(struct Render *re);
+
#endif /* __RE_ENGINE_H__ */
diff --git a/source/blender/render/extern/include/RE_multires_bake.h b/source/blender/render/extern/include/RE_multires_bake.h
new file mode 100644
index 00000000000..04cfe55e3a3
--- /dev/null
+++ b/source/blender/render/extern/include/RE_multires_bake.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Morten Mikkelsen,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file RE_multires_bake.h
+ * \ingroup render
+ */
+
+#ifndef __RE_MULTIRES_BAKE_H__
+#define __RE_MULTIRES_BAKE_H__
+
+struct MultiresBakeRender;
+
+typedef struct MultiresBakeRender {
+ DerivedMesh *lores_dm, *hires_dm;
+ int simple, lvl, tot_lvl, bake_filter;
+ short mode, use_lores_mesh;
+
+ int number_of_rays;
+ float bias;
+
+ int tot_obj, tot_image;
+ ListBase image;
+
+ int baked_objects, baked_faces;
+
+ int raytrace_structure;
+ int octree_resolution;
+ int threads;
+
+ short *stop;
+ short *do_update;
+ float *progress;
+} MultiresBakeRender;
+
+void RE_multires_bake_images(struct MultiresBakeRender *bkr);
+
+#endif
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index f97e5ac3c59..020fa57cf94 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -219,6 +219,9 @@ void RE_TileProcessor(struct Render *re);
/* 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, unsigned int lay, int frame, const short write_still);
void RE_BlenderAnim(struct Render *re, struct Main *bmain, struct Scene *scene, struct Object *camera_override, unsigned int lay, int sfra, int efra, int tfra);
+#ifdef WITH_FREESTYLE
+void RE_RenderFreestyleStrokes(struct Render *re, struct Main *bmain, struct Scene *scene);
+#endif
/* error reporting */
void RE_SetReports(struct Render *re, struct ReportList *reports);
diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h
index 2a9a1becc42..2dfbdd0d6f5 100644
--- a/source/blender/render/extern/include/RE_render_ext.h
+++ b/source/blender/render/extern/include/RE_render_ext.h
@@ -49,10 +49,11 @@ struct RNode;
struct Render;
struct MTex;
struct ImBuf;
+struct ImagePool;
struct DerivedMesh;
/* 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);
+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);
/* particle.c */
void texture_rgb_blend(float in[3], const float tex[3], const float out[3], float fact, float facg, int blendtype);
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index 10045a8f7e1..d686de21517 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -184,19 +184,24 @@ typedef struct ShadeInput {
} ShadeInput;
+typedef struct BakeImBufuserData {
+ float *displacement_buffer;
+ char *mask_buffer;
+} BakeImBufuserData;
/* node shaders... */
struct Tex;
struct MTex;
struct ImBuf;
+struct ImagePool;
/* this one uses nodes */
-int multitex_ext(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres);
+int multitex_ext(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool);
/* nodes disabled */
-int multitex_ext_safe(struct Tex *tex, float texvec[3], struct TexResult *texres);
+int multitex_ext_safe(struct Tex *tex, float texvec[3], struct TexResult *texres, struct ImagePool *pool);
/* 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);
+ const short thread, short which_output, struct ShadeInput *shi, struct MTex *mtex, struct ImagePool *pool);
/* shaded view and bake */
struct Render;
@@ -206,6 +211,7 @@ struct Object;
int RE_bake_shade_all_selected(struct Render *re, int type, struct Object *actob, short *do_update, float *progress);
struct Image *RE_bake_shade_get_image(void);
void RE_bake_ibuf_filter(struct ImBuf *ibuf, char *mask, const int filter);
+void RE_bake_ibuf_normalize_displacement(struct ImBuf *ibuf, float *displacement, char *mask, float displacement_min, float displacement_max);
#define BAKE_RESULT_OK 0
#define BAKE_RESULT_NO_OBJECTS 1
diff --git a/source/blender/render/intern/include/envmap.h b/source/blender/render/intern/include/envmap.h
index d0f346f7402..a6c6d46e2e9 100644
--- a/source/blender/render/intern/include/envmap.h
+++ b/source/blender/render/intern/include/envmap.h
@@ -44,9 +44,10 @@
struct Render;
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);
+int envmaptex(struct Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool);
#endif /* __ENVMAP_H__ */
diff --git a/source/blender/render/intern/include/pixelshading.h b/source/blender/render/intern/include/pixelshading.h
index 30d574694b2..faf8c5f54f5 100644
--- a/source/blender/render/intern/include/pixelshading.h
+++ b/source/blender/render/intern/include/pixelshading.h
@@ -32,6 +32,8 @@
#ifndef __PIXELSHADING_H__
#define __PIXELSHADING_H__
+struct ImagePool;
+
/**
* Render the pixel at (x,y) for object ap. Apply the jitter mask.
* Output is given in float collector[4]. The type vector:
diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h
index 7a9d242a2a1..e9514b8585e 100644
--- a/source/blender/render/intern/include/rayobject.h
+++ b/source/blender/render/intern/include/rayobject.h
@@ -87,6 +87,8 @@ typedef struct RayFace {
RayObject *RE_rayface_from_vlak(RayFace *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr);
+RayObject *RE_rayface_from_coords(RayFace *rayface, void *ob, void *face, float *v1, float *v2, float *v3, float *v4);
+
/* RayObject representing faces directly from a given VlakRen structure. Thus
* allowing to save memory, but making code triangle intersection dependent on
* render structures. */
diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h
index 5d61417cbaf..61b39a59b0b 100644
--- a/source/blender/render/intern/include/render_result.h
+++ b/source/blender/render/intern/include/render_result.h
@@ -91,7 +91,7 @@ void render_result_rect_from_ibuf(struct RenderResult *rr, struct RenderData *rd
struct ImBuf *ibuf);
void render_result_rect_fill_zero(struct RenderResult *rr);
-void render_result_rect_get_pixels(struct RenderResult *rr, struct RenderData *rd,
+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);
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 6ed8d6a7b6c..f3cd60d8031 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -62,6 +62,7 @@ struct RayFace;
struct RenderEngine;
struct ReportList;
struct Main;
+struct ImagePool;
#define TABLEINITSIZE 1024
@@ -104,13 +105,19 @@ typedef struct RenderPart {
rcti disprect; /* part coordinates within total picture */
int rectx, recty; /* the size */
- short crop, ready; /* crop is amount of pixels we crop, for filter */
+ short crop, status; /* crop is amount of pixels we crop, for filter */
short sample, nr; /* sample can be used by zbuffers, nr is partnr */
short thread; /* thread id */
char *clipflag; /* clipflags for part zbuffering */
} RenderPart;
+enum {
+ PART_STATUS_NONE = 0,
+ PART_STATUS_IN_PROGRESS = 1,
+ PART_STATUS_READY = 2
+};
+
/* controls state of render, everything that's read-only during render stage */
struct Render
{
@@ -198,7 +205,6 @@ struct Render
ListBase strandsurface;
/* use this instead of R.r.cfra */
- float cfra;
float mblur_offs, field_offs;
/* render database */
@@ -229,6 +235,10 @@ struct Render
ListBase volumes;
ListBase volume_precache_parts;
+#ifdef WITH_FREESTYLE
+ ListBase freestyle_renders;
+#endif
+
/* arena for allocating data for use during render, for
* example dynamic TFaces to go in the VlakRen structure.
*/
@@ -255,6 +265,8 @@ struct Render
RenderStats i;
struct ReportList *reports;
+
+ struct ImagePool *pool;
};
/* ------------------------------------------------------------------------- */
@@ -368,6 +380,7 @@ struct halosort {
/* ------------------------------------------------------------------------- */
struct Material;
struct MTFace;
+struct ImagePool;
typedef struct RadFace {
float unshot[3], totrad[3];
@@ -381,6 +394,10 @@ typedef struct VlakRen {
struct Material *mat;
char puno;
char flag, ec;
+#ifdef WITH_FREESTYLE
+ char freestyle_edge_mark;
+ char freestyle_face_mark;
+#endif
int index;
} VlakRen;
@@ -397,6 +414,7 @@ typedef struct HaloRen {
int pixels;
unsigned int lay;
struct Material *mat;
+ struct ImagePool *pool;
} HaloRen;
/* ------------------------------------------------------------------------- */
@@ -612,6 +630,15 @@ typedef struct LampRen {
#define R_TANGENT 64
#define R_TRACEBLE 128
+/* vlakren->freestyle_edge_mark */
+#ifdef WITH_FREESTYLE
+# define R_EDGE_V1V2 1
+# define R_EDGE_V2V3 2
+# define R_EDGE_V3V4 4
+# define R_EDGE_V3V1 4
+# define R_EDGE_V4V1 8
+#endif
+
/* strandbuffer->flag */
#define R_STRAND_BSPLINE 1
#define R_STRAND_B_UNITS 2
diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h
index 30712250440..88b639c4ba9 100644
--- a/source/blender/render/intern/include/rendercore.h
+++ b/source/blender/render/intern/include/rendercore.h
@@ -83,6 +83,8 @@ int get_sample_layers(struct RenderPart *pa, struct RenderLayer *rl, struct Rend
/* -------- ray.c ------- */
+struct RayObject *RE_rayobject_create(int type, int size, int octree_resolution);
+
extern void freeraytree(Render *re);
extern void makeraytree(Render *re);
struct RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi);
diff --git a/source/blender/render/intern/include/renderdatabase.h b/source/blender/render/intern/include/renderdatabase.h
index 24989b13c48..1e81ca20d03 100644
--- a/source/blender/render/intern/include/renderdatabase.h
+++ b/source/blender/render/intern/include/renderdatabase.h
@@ -59,12 +59,16 @@ typedef struct VertTableNode {
float *tangent;
float *stress;
float *winspeed;
+ /* Index of vertex in source mesh (before modifiers). */
+ int *origindex;
} VertTableNode;
typedef struct VlakTableNode {
struct VlakRen *vlak;
struct MTFace *mtface;
struct MCol *mcol;
+ /* Index of mpoly in source mesh (before tessellation). */
+ int *origindex;
int totmtface, totmcol;
float *surfnor;
float *tangent;
@@ -114,9 +118,11 @@ float *RE_vertren_get_rad(struct ObjectRen *obr, struct VertRen *ver, int verify
float *RE_vertren_get_strand(struct ObjectRen *obr, struct VertRen *ver, int verify);
float *RE_vertren_get_tangent(struct ObjectRen *obr, struct VertRen *ver, int verify);
float *RE_vertren_get_winspeed(struct ObjectInstanceRen *obi, struct VertRen *ver, int verify);
+int *RE_vertren_get_origindex(struct ObjectRen *obr, VertRen *ver, int verify);
struct MTFace *RE_vlakren_get_tface(struct ObjectRen *obr, VlakRen *ren, int n, char **name, int verify);
struct MCol *RE_vlakren_get_mcol(struct ObjectRen *obr, VlakRen *ren, int n, char **name, int verify);
+int *RE_vlakren_get_origindex(struct ObjectRen *obr, VlakRen *vlak, int verify);
float *RE_vlakren_get_surfnor(struct ObjectRen *obr, VlakRen *ren, int verify);
float *RE_vlakren_get_nmap_tangent(struct ObjectRen *obr, VlakRen *ren, int verify);
RadFace **RE_vlakren_get_radface(struct ObjectRen *obr, VlakRen *ren, int verify);
diff --git a/source/blender/render/intern/include/texture.h b/source/blender/render/intern/include/texture.h
index 4b9fa2d2042..2dc12f39db7 100644
--- a/source/blender/render/intern/include/texture.h
+++ b/source/blender/render/intern/include/texture.h
@@ -60,6 +60,7 @@ struct TexResult;
struct Tex;
struct Image;
struct ImBuf;
+struct ImagePool;
/* texture.h */
@@ -76,9 +77,9 @@ 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);
-int imagewrap(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], struct TexResult *texres);
-void image_sample(struct Image *ima, float fx, float fy, float dx, float dy, float result[4]);
+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);
+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/raytrace/rayobject.cpp b/source/blender/render/intern/raytrace/rayobject.cpp
index c3babf99d51..9e639501fdd 100644
--- a/source/blender/render/intern/raytrace/rayobject.cpp
+++ b/source/blender/render/intern/raytrace/rayobject.cpp
@@ -87,7 +87,12 @@ MALWAYS_INLINE void rayface_from_vlak(RayFace *rayface, ObjectInstanceRen *obi,
RayObject *RE_rayface_from_vlak(RayFace *rayface, ObjectInstanceRen *obi, VlakRen *vlr)
{
- return rayface_from_coords(rayface, obi, vlr, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4 ? vlr->v4->co : 0);
+ return rayface_from_coords(rayface, obi, vlr, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4 ? vlr->v4->co : NULL);
+}
+
+RayObject *RE_rayface_from_coords(RayFace *rayface, void *ob, void *face, float *v1, float *v2, float *v3, float *v4)
+{
+ return rayface_from_coords(rayface, ob, face, v1, v2, v3, v4);
}
/* VlakPrimitive */
diff --git a/source/blender/render/intern/raytrace/rayobject_instance.cpp b/source/blender/render/intern/raytrace/rayobject_instance.cpp
index f9ed012b117..01e592cba0c 100644
--- a/source/blender/render/intern/raytrace/rayobject_instance.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_instance.cpp
@@ -173,13 +173,13 @@ static int RE_rayobject_instance_intersect(RayObject *o, Isect *isec)
static void RE_rayobject_instance_free(RayObject *o)
{
- InstanceRayObject *obj = (InstanceRayObject*)o;
+ InstanceRayObject *obj = (InstanceRayObject *)o;
MEM_freeN(obj);
}
static float RE_rayobject_instance_cost(RayObject *o)
{
- InstanceRayObject *obj = (InstanceRayObject*)o;
+ InstanceRayObject *obj = (InstanceRayObject *)o;
return RE_rayobject_cost(obj->target) + RE_COST_INSTANCE;
}
diff --git a/source/blender/render/intern/raytrace/rayobject_internal.h b/source/blender/render/intern/raytrace/rayobject_internal.h
index aa8ab8c3da4..07a1cd26c47 100644
--- a/source/blender/render/intern/raytrace/rayobject_internal.h
+++ b/source/blender/render/intern/raytrace/rayobject_internal.h
@@ -103,12 +103,12 @@ int RE_rayobjectcontrol_test_break(RayObjectControl *c);
#define RE_rayobject_isVlakPrimitive(o) ((((intptr_t)o)&3) == 3)
/* used to align a given ray object */
-#define RE_rayobject_align(o) ((RayObject*)(((intptr_t)o)&(~3)))
+#define RE_rayobject_align(o) ((RayObject *)(((intptr_t)o)&(~3)))
/* used to unalign a given ray object */
-#define RE_rayobject_unalignRayFace(o) ((RayObject*)(((intptr_t)o)|1))
-#define RE_rayobject_unalignRayAPI(o) ((RayObject*)(((intptr_t)o)|2))
-#define RE_rayobject_unalignVlakPrimitive(o) ((RayObject*)(((intptr_t)o)|3))
+#define RE_rayobject_unalignRayFace(o) ((RayObject *)(((intptr_t)o)|1))
+#define RE_rayobject_unalignRayAPI(o) ((RayObject *)(((intptr_t)o)|2))
+#define RE_rayobject_unalignVlakPrimitive(o) ((RayObject *)(((intptr_t)o)|3))
/*
* This rayobject represents a generic object. With it's own callbacks for raytrace operations.
diff --git a/source/blender/render/intern/raytrace/rayobject_octree.cpp b/source/blender/render/intern/raytrace/rayobject_octree.cpp
index dad7fe5fd60..e4fd5a6d41e 100644
--- a/source/blender/render/intern/raytrace/rayobject_octree.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_octree.cpp
@@ -542,13 +542,13 @@ static void octree_fill_rayface(Octree *oc, RayFace *face)
oc2 = rts[1][c];
oc3 = rts[2][c];
if (!RE_rayface_isQuad(face)) {
- ocmin[c] = MIN3(oc1, oc2, oc3);
- ocmax[c] = MAX3(oc1, oc2, oc3);
+ ocmin[c] = min_iii(oc1, oc2, oc3);
+ ocmax[c] = max_iii(oc1, oc2, oc3);
}
else {
oc4 = rts[3][c];
- ocmin[c] = MIN4(oc1, oc2, oc3, oc4);
- ocmax[c] = MAX4(oc1, oc2, oc3, oc4);
+ ocmin[c] = min_iiii(oc1, oc2, oc3, oc4);
+ ocmax[c] = max_iiii(oc1, oc2, oc3, oc4);
}
if (ocmax[c] > oc->ocres - 1) ocmax[c] = oc->ocres - 1;
if (ocmin[c] < 0) ocmin[c] = 0;
@@ -667,10 +667,12 @@ static void RE_rayobject_octree_done(RayObject *tree)
oc->ocface = NULL;
MEM_freeN(oc->ro_nodes);
oc->ro_nodes = NULL;
-
+
+#if 0
printf("%f %f - %f\n", oc->min[0], oc->max[0], oc->ocfacx);
printf("%f %f - %f\n", oc->min[1], oc->max[1], oc->ocfacy);
printf("%f %f - %f\n", oc->min[2], oc->max[2], oc->ocfacz);
+#endif
}
static void RE_rayobject_octree_bb(RayObject *tree, float *min, float *max)
@@ -993,7 +995,7 @@ static int RE_rayobject_octree_intersect(RayObject *tree, Isect *is)
}
xo = ocx1; yo = ocy1; zo = ocz1;
- dda_lambda = MIN3(lambda_x, lambda_y, lambda_z);
+ dda_lambda = min_fff(lambda_x, lambda_y, lambda_z);
vec2[0] = ox1;
vec2[1] = oy1;
@@ -1015,7 +1017,7 @@ static int RE_rayobject_octree_intersect(RayObject *tree, Isect *is)
vec2[2] = oz1 - dda_lambda * doz;
calc_ocval_ray(&ocval, (float)xo, (float)yo, (float)zo, vec1, vec2);
- //is->dist = (u1+dda_lambda*(u2-u1))*o_lambda;
+ //is->dist = (u1 + dda_lambda * (u2 - u1)) * o_lambda;
if (testnode(oc, is, no, ocval) )
found = 1;
@@ -1083,7 +1085,7 @@ static int RE_rayobject_octree_intersect(RayObject *tree, Isect *is)
}
- dda_lambda = MIN3(lambda_x, lambda_y, lambda_z);
+ dda_lambda = min_fff(lambda_x, lambda_y, lambda_z);
if (dda_lambda == lambda_o) break;
/* to make sure the last node is always checked */
if (lambda_o >= 1.0f) break;
diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp
index 4195b103811..1d67a8c4f44 100644
--- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp
@@ -50,15 +50,15 @@ static bool selected_node(RTBuilder::Object *node)
static void rtbuild_init(RTBuilder *b)
{
b->split_axis = -1;
- b->primitives.begin = 0;
- b->primitives.end = 0;
+ b->primitives.begin = NULL;
+ b->primitives.end = NULL;
b->primitives.maxsize = 0;
for (int i = 0; i < RTBUILD_MAX_CHILDS; i++)
b->child_offset[i] = 0;
for (int i = 0; i < 3; i++)
- b->sorted_begin[i] = b->sorted_end[i] = 0;
+ b->sorted_begin[i] = b->sorted_end[i] = NULL;
INIT_MINMAX(b->bb, b->bb + 3);
}
@@ -178,8 +178,8 @@ RTBuilder *rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp)
tmp->sorted_end[i] = b->sorted_begin[i] + b->child_offset[child + 1];
}
else {
- tmp->sorted_begin[i] = 0;
- tmp->sorted_end[i] = 0;
+ tmp->sorted_begin[i] = NULL;
+ tmp->sorted_end[i] = NULL;
}
return tmp;
diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
index d03bdb74407..3e80deefecd 100644
--- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
+++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp
@@ -38,12 +38,12 @@ int tot_hints = 0;
#include "MEM_guardedalloc.h"
-#include "BKE_global.h"
-
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_utildefines.h"
+#include "BKE_global.h"
+
#include "rayintersection.h"
#include "rayobject.h"
#include "rayobject_rtbuild.h"
diff --git a/source/blender/render/intern/raytrace/reorganize.h b/source/blender/render/intern/raytrace/reorganize.h
index 9d9711eee56..5624df25267 100644
--- a/source/blender/render/intern/raytrace/reorganize.h
+++ b/source/blender/render/intern/raytrace/reorganize.h
@@ -80,7 +80,6 @@ void reorganize_find_fittest_parent(Node *tree, Node *node, std::pair<float, Nod
}
}
-static int tot_moves = 0;
template<class Node>
void reorganize(Node *root)
{
@@ -109,8 +108,6 @@ void reorganize(Node *root)
tmp->sibling = best.second->child;
best.second->child = tmp;
-
- tot_moves++;
}
diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c
new file mode 100644
index 00000000000..c20b0c6da16
--- /dev/null
+++ b/source/blender/render/intern/source/bake.c
@@ -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) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributors: 2004/2005/2006 Blender Foundation, full recode
+ * Contributors: Vertex color baking, Copyright 2011 AutoCRC
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/render/intern/source/bake.c
+ * \ingroup render
+ */
+
+
+/* system includes */
+#include <stdio.h>
+#include <string.h>
+
+/* External modules: */
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_threads.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_image_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_main.h"
+#include "BKE_node.h"
+#include "BKE_scene.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+#include "IMB_colormanagement.h"
+
+/* local include */
+#include "rayintersection.h"
+#include "rayobject.h"
+#include "render_types.h"
+#include "renderdatabase.h"
+#include "shading.h"
+#include "zbuf.h"
+
+#include "PIL_time.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;
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+
+/* ************************* bake ************************ */
+
+
+typedef struct BakeShade {
+ ShadeSample ssamp;
+ ObjectInstanceRen *obi;
+ VlakRen *vlr;
+
+ ZSpan *zspan;
+ Image *ima;
+ ImBuf *ibuf;
+
+ int rectx, recty, quad, type, vdone;
+ bool ready;
+
+ float dir[3];
+ Object *actob;
+
+ /* Output: vertex color or image data. If vcol is not NULL, rect and
+ * rect_float should be NULL. */
+ MPoly *mpoly;
+ MLoop *mloop;
+ MLoopCol *vcol;
+
+ unsigned int *rect;
+ float *rect_float;
+
+ /* displacement buffer used for normalization with unknown maximal distance */
+ bool use_displacement_buffer;
+ float *displacement_buffer;
+ float displacement_min, displacement_max;
+
+ bool use_mask;
+ char *rect_mask; /* bake pixel mask */
+
+ float dxco[3], dyco[3];
+
+ short *do_update;
+
+ struct ColorSpace *rect_colorspace;
+} BakeShade;
+
+static void bake_set_shade_input(ObjectInstanceRen *obi, VlakRen *vlr, ShadeInput *shi, int quad, int UNUSED(isect), int x, int y, float u, float v)
+{
+ if (quad)
+ shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3);
+ else
+ shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);
+
+ /* cache for shadow */
+ shi->samplenr = R.shadowsamplenr[shi->thread]++;
+
+ shi->mask = 0xFFFF; /* all samples */
+
+ shi->u = -u;
+ shi->v = -v;
+ shi->xs = x;
+ shi->ys = y;
+
+ shade_input_set_uv(shi);
+ shade_input_set_normals(shi);
+
+ /* no normal flip */
+ if (shi->flippednor)
+ shade_input_flip_normals(shi);
+
+ /* set up view vector to look right at the surface (note that the normal
+ * is negated in the renderer so it does not need to be done here) */
+ shi->view[0] = shi->vn[0];
+ shi->view[1] = shi->vn[1];
+ shi->view[2] = shi->vn[2];
+}
+
+static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(quad), int x, int y, float UNUSED(u), float UNUSED(v), float *tvn, float *ttang)
+{
+ BakeShade *bs = handle;
+ ShadeSample *ssamp = &bs->ssamp;
+ ShadeResult shr;
+ VlakRen *vlr = shi->vlr;
+
+ shade_input_init_material(shi);
+
+ if (bs->type == RE_BAKE_AO) {
+ ambient_occlusion(shi);
+
+ if (R.r.bake_flag & R_BAKE_NORMALIZE) {
+ copy_v3_v3(shr.combined, shi->ao);
+ }
+ else {
+ zero_v3(shr.combined);
+ environment_lighting_apply(shi, &shr);
+ }
+ }
+ else {
+ if (bs->type == RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */
+ shi->r = shi->g = shi->b = 1.0f;
+
+ shade_input_set_shade_texco(shi);
+
+ /* only do AO for a full bake (and obviously AO bakes)
+ * AO for light bakes is a leftover and might not be needed */
+ if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_AO, RE_BAKE_LIGHT))
+ shade_samples_do_AO(ssamp);
+
+ if (shi->mat->nodetree && shi->mat->use_nodes) {
+ ntreeShaderExecTree(shi->mat->nodetree, shi, &shr);
+ shi->mat = vlr->mat; /* shi->mat is being set in nodetree */
+ }
+ else
+ shade_material_loop(shi, &shr);
+
+ if (bs->type == RE_BAKE_NORMALS) {
+ float nor[3];
+
+ copy_v3_v3(nor, shi->vn);
+
+ if (R.r.bake_normal_space == R_BAKE_SPACE_CAMERA) {
+ /* pass */
+ }
+ else if (R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) {
+ float mat[3][3], imat[3][3];
+
+ /* bitangent */
+ if (tvn && ttang) {
+ copy_v3_v3(mat[0], ttang);
+ cross_v3_v3v3(mat[1], tvn, ttang);
+ mul_v3_fl(mat[1], ttang[3]);
+ copy_v3_v3(mat[2], tvn);
+ }
+ else {
+ copy_v3_v3(mat[0], shi->nmaptang);
+ cross_v3_v3v3(mat[1], shi->nmapnorm, shi->nmaptang);
+ mul_v3_fl(mat[1], shi->nmaptang[3]);
+ copy_v3_v3(mat[2], shi->nmapnorm);
+ }
+
+ invert_m3_m3(imat, mat);
+ mul_m3_v3(imat, nor);
+ }
+ else if (R.r.bake_normal_space == R_BAKE_SPACE_OBJECT)
+ mul_mat3_m4_v3(ob->imat_ren, nor); /* ob->imat_ren includes viewinv! */
+ else if (R.r.bake_normal_space == R_BAKE_SPACE_WORLD)
+ mul_mat3_m4_v3(R.viewinv, nor);
+
+ normalize_v3(nor); /* in case object has scaling */
+
+ /* The invert of the red channel is to make
+ * the normal map compliant with the outside world.
+ * It needs to be done because in Blender
+ * the normal used in the renderer points inward. It is generated
+ * this way in calc_vertexnormals(). Should this ever change
+ * this negate must be removed. */
+ shr.combined[0] = (-nor[0]) / 2.0f + 0.5f;
+ shr.combined[1] = nor[1] / 2.0f + 0.5f;
+ shr.combined[2] = nor[2] / 2.0f + 0.5f;
+ }
+ else if (bs->type == RE_BAKE_TEXTURE) {
+ copy_v3_v3(shr.combined, &shi->r);
+ shr.alpha = shi->alpha;
+ }
+ else if (bs->type == RE_BAKE_SHADOW) {
+ copy_v3_v3(shr.combined, shr.shad);
+ shr.alpha = shi->alpha;
+ }
+ else if (bs->type == RE_BAKE_SPEC_COLOR) {
+ copy_v3_v3(shr.combined, &shi->specr);
+ shr.alpha = 1.0f;
+ }
+ else if (bs->type == RE_BAKE_SPEC_INTENSITY) {
+ copy_v3_fl(shr.combined, shi->spec);
+ shr.alpha = 1.0f;
+ }
+ else if (bs->type == RE_BAKE_MIRROR_COLOR) {
+ copy_v3_v3(shr.combined, &shi->mirr);
+ shr.alpha = 1.0f;
+ }
+ else if (bs->type == RE_BAKE_MIRROR_INTENSITY) {
+ copy_v3_fl(shr.combined, shi->ray_mirror);
+ shr.alpha = 1.0f;
+ }
+ else if (bs->type == RE_BAKE_ALPHA) {
+ copy_v3_fl(shr.combined, shi->alpha);
+ shr.alpha = 1.0f;
+ }
+ else if (bs->type == RE_BAKE_EMIT) {
+ copy_v3_fl(shr.combined, shi->emit);
+ shr.alpha = 1.0f;
+ }
+ }
+
+ if (bs->rect_float && !bs->vcol) {
+ float *col = bs->rect_float + 4 * (bs->rectx * y + x);
+ copy_v3_v3(col, shr.combined);
+ if (bs->type == RE_BAKE_ALL || bs->type == RE_BAKE_TEXTURE) {
+ col[3] = shr.alpha;
+ }
+ else {
+ col[3] = 1.0;
+ }
+ }
+ else {
+ /* Target is char (LDR). */
+ unsigned char col[4];
+
+ if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
+ float rgb[3];
+
+ copy_v3_v3(rgb, shr.combined);
+ if (R.scene_color_manage) {
+ /* Vertex colors have no way to specify color space, so they
+ * default to sRGB. */
+ if (!bs->vcol)
+ IMB_colormanagement_scene_linear_to_colorspace_v3(rgb, bs->rect_colorspace);
+ else
+ linearrgb_to_srgb_v3_v3(rgb, rgb);
+ }
+ rgb_float_to_uchar(col, rgb);
+ }
+ else {
+ rgb_float_to_uchar(col, shr.combined);
+ }
+
+ if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
+ col[3] = FTOCHAR(shr.alpha);
+ }
+ else {
+ col[3] = 255;
+ }
+
+ if (bs->vcol) {
+ /* Vertex color baking. Vcol has no useful alpha channel (it exists
+ * but is used only for vertex painting). */
+ bs->vcol->r = col[0];
+ bs->vcol->g = col[1];
+ bs->vcol->b = col[2];
+ }
+ else {
+ unsigned char *imcol = (unsigned char *)(bs->rect + bs->rectx * y + x);
+ copy_v4_v4_char((char *)imcol, (char *)col);
+ }
+
+ }
+
+ if (bs->rect_mask) {
+ bs->rect_mask[bs->rectx * y + x] = FILTER_MASK_USED;
+ }
+}
+
+static void bake_displacement(void *handle, ShadeInput *UNUSED(shi), float dist, int x, int y)
+{
+ BakeShade *bs = handle;
+ float disp;
+
+ if (R.r.bake_flag & R_BAKE_NORMALIZE) {
+ if (R.r.bake_maxdist)
+ disp = (dist + R.r.bake_maxdist) / (R.r.bake_maxdist * 2); /* alter the range from [-bake_maxdist, bake_maxdist] to [0, 1]*/
+ else
+ disp = dist;
+ }
+ else {
+ disp = 0.5f + dist; /* alter the range from [-0.5,0.5] to [0,1]*/
+ }
+
+ if (bs->displacement_buffer) {
+ float *displacement = bs->displacement_buffer + (bs->rectx * y + x);
+ *displacement = disp;
+ bs->displacement_min = min_ff(bs->displacement_min, disp);
+ bs->displacement_max = max_ff(bs->displacement_max, disp);
+ }
+
+ if (bs->rect_float && !bs->vcol) {
+ float *col = bs->rect_float + 4 * (bs->rectx * y + x);
+ col[0] = col[1] = col[2] = disp;
+ col[3] = 1.0f;
+ }
+ else {
+ /* Target is char (LDR). */
+ unsigned char col[4];
+ col[0] = col[1] = col[2] = FTOCHAR(disp);
+ col[3] = 255;
+
+ if (bs->vcol) {
+ /* Vertex color baking. Vcol has no useful alpha channel (it exists
+ * but is used only for vertex painting). */
+ bs->vcol->r = col[0];
+ bs->vcol->g = col[1];
+ bs->vcol->b = col[2];
+ }
+ else {
+ char *imcol = (char *)(bs->rect + bs->rectx * y + x);
+ copy_v4_v4_char((char *)imcol, (char *)col);
+ }
+ }
+ if (bs->rect_mask) {
+ bs->rect_mask[bs->rectx * y + x] = FILTER_MASK_USED;
+ }
+}
+
+static int bake_intersect_tree(RayObject *raytree, Isect *isect, float *start, float *dir, float sign, float *hitco, float *dist)
+{
+ float maxdist;
+ int hit;
+
+ /* might be useful to make a user setting for maxsize*/
+ if (R.r.bake_maxdist > 0.0f)
+ maxdist = R.r.bake_maxdist;
+ else
+ maxdist = RE_RAYTRACE_MAXDIST + R.r.bake_biasdist;
+
+ /* 'dir' is always normalized */
+ madd_v3_v3v3fl(isect->start, start, dir, -R.r.bake_biasdist);
+
+ mul_v3_v3fl(isect->dir, dir, sign);
+
+ isect->dist = maxdist;
+
+ hit = RE_rayobject_raycast(raytree, isect);
+ if (hit) {
+ madd_v3_v3v3fl(hitco, isect->start, isect->dir, isect->dist);
+
+ *dist = isect->dist;
+ }
+
+ return hit;
+}
+
+static void bake_set_vlr_dxyco(BakeShade *bs, float *uv1, float *uv2, float *uv3)
+{
+ VlakRen *vlr = bs->vlr;
+ float A, d1, d2, d3, *v1, *v2, *v3;
+
+ if (bs->quad) {
+ v1 = vlr->v1->co;
+ v2 = vlr->v3->co;
+ v3 = vlr->v4->co;
+ }
+ else {
+ v1 = vlr->v1->co;
+ v2 = vlr->v2->co;
+ v3 = vlr->v3->co;
+ }
+
+ /* formula derived from barycentric coordinates:
+ * (uvArea1*v1 + uvArea2*v2 + uvArea3*v3)/uvArea
+ * then taking u and v partial derivatives to get dxco and dyco */
+ A = (uv2[0] - uv1[0]) * (uv3[1] - uv1[1]) - (uv3[0] - uv1[0]) * (uv2[1] - uv1[1]);
+
+ if (fabsf(A) > FLT_EPSILON) {
+ A = 0.5f / A;
+
+ d1 = uv2[1] - uv3[1];
+ d2 = uv3[1] - uv1[1];
+ d3 = uv1[1] - uv2[1];
+ bs->dxco[0] = (v1[0] * d1 + v2[0] * d2 + v3[0] * d3) * A;
+ bs->dxco[1] = (v1[1] * d1 + v2[1] * d2 + v3[1] * d3) * A;
+ bs->dxco[2] = (v1[2] * d1 + v2[2] * d2 + v3[2] * d3) * A;
+
+ d1 = uv3[0] - uv2[0];
+ d2 = uv1[0] - uv3[0];
+ d3 = uv2[0] - uv1[0];
+ bs->dyco[0] = (v1[0] * d1 + v2[0] * d2 + v3[0] * d3) * A;
+ bs->dyco[1] = (v1[1] * d1 + v2[1] * d2 + v3[1] * d3) * A;
+ bs->dyco[2] = (v1[2] * d1 + v2[2] * d2 + v3[2] * d3) * A;
+ }
+ else {
+ bs->dxco[0] = bs->dxco[1] = bs->dxco[2] = 0.0f;
+ bs->dyco[0] = bs->dyco[1] = bs->dyco[2] = 0.0f;
+ }
+
+ if (bs->obi->flag & R_TRANSFORMED) {
+ mul_m3_v3(bs->obi->nmat, bs->dxco);
+ mul_m3_v3(bs->obi->nmat, bs->dyco);
+ }
+}
+
+static void do_bake_shade(void *handle, int x, int y, float u, float v)
+{
+ BakeShade *bs = handle;
+ VlakRen *vlr = bs->vlr;
+ ObjectInstanceRen *obi = bs->obi;
+ Object *ob = obi->obr->ob;
+ float l, *v1, *v2, *v3, tvn[3], ttang[4];
+ int quad;
+ ShadeSample *ssamp = &bs->ssamp;
+ ShadeInput *shi = ssamp->shi;
+
+ /* fast threadsafe break test */
+ if (R.test_break(R.tbh))
+ return;
+
+ /* setup render coordinates */
+ if (bs->quad) {
+ v1 = vlr->v1->co;
+ v2 = vlr->v3->co;
+ v3 = vlr->v4->co;
+ }
+ else {
+ v1 = vlr->v1->co;
+ v2 = vlr->v2->co;
+ v3 = vlr->v3->co;
+ }
+
+ l = 1.0f - u - v;
+
+ /* shrink barycentric coordinates inwards slightly to avoid some issues
+ * where baking selected to active might just miss the other face at the
+ * near the edge of a face */
+ if (bs->actob) {
+ const float eps = 1.0f - 1e-4f;
+ float invsum;
+
+ u = (u - 0.5f) * eps + 0.5f;
+ v = (v - 0.5f) * eps + 0.5f;
+ l = (l - 0.5f) * eps + 0.5f;
+
+ invsum = 1.0f / (u + v + l);
+
+ u *= invsum;
+ v *= invsum;
+ l *= invsum;
+ }
+
+ /* renderco */
+ shi->co[0] = l * v3[0] + u * v1[0] + v * v2[0];
+ shi->co[1] = l * v3[1] + u * v1[1] + v * v2[1];
+ shi->co[2] = l * v3[2] + u * v1[2] + v * v2[2];
+
+ /* avoid self shadow with vertex bake from adjacent faces [#33729] */
+ if ((bs->vcol != NULL) && (bs->actob == NULL)) {
+ madd_v3_v3fl(shi->co, vlr->n, 0.0001f);
+ }
+
+ if (obi->flag & R_TRANSFORMED)
+ mul_m4_v3(obi->mat, shi->co);
+
+ copy_v3_v3(shi->dxco, bs->dxco);
+ copy_v3_v3(shi->dyco, bs->dyco);
+
+ quad = bs->quad;
+ bake_set_shade_input(obi, vlr, shi, quad, 0, x, y, u, v);
+
+ if (bs->type == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) {
+ shade_input_set_shade_texco(shi);
+ copy_v3_v3(tvn, shi->nmapnorm);
+ copy_v4_v4(ttang, shi->nmaptang);
+ }
+
+ /* if we are doing selected to active baking, find point on other face */
+ if (bs->actob) {
+ Isect isec, minisec;
+ float co[3], minco[3], dist, mindist = 0.0f;
+ int hit, sign, dir = 1;
+
+ /* intersect with ray going forward and backward*/
+ hit = 0;
+ memset(&minisec, 0, sizeof(minisec));
+ minco[0] = minco[1] = minco[2] = 0.0f;
+
+ copy_v3_v3(bs->dir, shi->vn);
+
+ for (sign = -1; sign <= 1; sign += 2) {
+ memset(&isec, 0, sizeof(isec));
+ isec.mode = RE_RAY_MIRROR;
+
+ isec.orig.ob = obi;
+ isec.orig.face = vlr;
+ isec.userdata = bs->actob;
+ isec.check = RE_CHECK_VLR_BAKE;
+ isec.skip = RE_SKIP_VLR_NEIGHBOUR;
+
+ if (bake_intersect_tree(R.raytree, &isec, shi->co, shi->vn, sign, co, &dist)) {
+ if (!hit || len_squared_v3v3(shi->co, co) < len_squared_v3v3(shi->co, minco)) {
+ minisec = isec;
+ mindist = dist;
+ copy_v3_v3(minco, co);
+ hit = 1;
+ dir = sign;
+ }
+ }
+ }
+
+ if (bs->type == RE_BAKE_DISPLACEMENT) {
+ if (hit)
+ bake_displacement(handle, shi, (dir == -1) ? mindist : -mindist, x, y);
+ else
+ bake_displacement(handle, shi, 0.0f, x, y);
+ return;
+ }
+
+ /* if hit, we shade from the new point, otherwise from point one starting face */
+ if (hit) {
+ obi = (ObjectInstanceRen *)minisec.hit.ob;
+ vlr = (VlakRen *)minisec.hit.face;
+ quad = (minisec.isect == 2);
+ copy_v3_v3(shi->co, minco);
+
+ u = -minisec.u;
+ v = -minisec.v;
+ bake_set_shade_input(obi, vlr, shi, quad, 1, x, y, u, v);
+ }
+ }
+
+ if (bs->type == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT)
+ bake_shade(handle, ob, shi, quad, x, y, u, v, tvn, ttang);
+ else
+ bake_shade(handle, ob, shi, quad, x, y, u, v, 0, 0);
+}
+
+static int get_next_bake_face(BakeShade *bs)
+{
+ ObjectRen *obr;
+ VlakRen *vlr;
+ MTFace *tface;
+ static int v = 0, vdone = false;
+ static ObjectInstanceRen *obi = NULL;
+
+ if (bs == NULL) {
+ vlr = NULL;
+ v = vdone = false;
+ obi = R.instancetable.first;
+ return 0;
+ }
+
+ BLI_lock_thread(LOCK_CUSTOM1);
+
+ for (; obi; obi = obi->next, v = 0) {
+ obr = obi->obr;
+
+ for (; v < obr->totvlak; v++) {
+ vlr = RE_findOrAddVlak(obr, v);
+
+ if ((bs->actob && bs->actob == obr->ob) || (!bs->actob && (obr->ob->flag & SELECT))) {
+ if (R.r.bake_flag & R_BAKE_VCOL) {
+ /* Gather face data for vertex color bake */
+ Mesh *me;
+ int *origindex, vcollayer;
+ CustomDataLayer *cdl;
+
+ if (obr->ob->type != OB_MESH)
+ continue;
+ me = obr->ob->data;
+
+ origindex = RE_vlakren_get_origindex(obr, vlr, 0);
+ if (origindex == NULL)
+ continue;
+ if (*origindex >= me->totpoly) {
+ /* Small hack for Array modifier, which gives false
+ * original indices - z0r */
+ continue;
+ }
+#if 0
+ /* Only shade selected faces. */
+ if ((me->mface[*origindex].flag & ME_FACE_SEL) == 0)
+ continue;
+#endif
+
+ vcollayer = CustomData_get_render_layer_index(&me->ldata, CD_MLOOPCOL);
+ if (vcollayer == -1)
+ continue;
+
+ cdl = &me->ldata.layers[vcollayer];
+ bs->mpoly = me->mpoly + *origindex;
+ bs->vcol = ((MLoopCol *)cdl->data) + bs->mpoly->loopstart;
+ bs->mloop = me->mloop + bs->mpoly->loopstart;
+
+ /* Tag mesh for reevaluation. */
+ DAG_id_tag_update(&me->id, 0);
+ }
+ else {
+ Image *ima = NULL;
+ ImBuf *ibuf = NULL;
+ const float vec_alpha[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ const float vec_solid[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ const float nor_alpha[4] = {0.5f, 0.5f, 1.0f, 0.0f};
+ const float nor_solid[4] = {0.5f, 0.5f, 1.0f, 1.0f};
+
+ tface = RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
+
+ if (!tface || !tface->tpage)
+ continue;
+
+ ima = tface->tpage;
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+
+ if (ibuf == NULL)
+ continue;
+
+ if (ibuf->rect == NULL && ibuf->rect_float == NULL) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ continue;
+ }
+
+ if (ibuf->rect_float && !(ibuf->channels == 0 || ibuf->channels == 4)) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ continue;
+ }
+
+ if (ima->flag & IMA_USED_FOR_RENDER) {
+ ima->id.flag &= ~LIB_DOIT;
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ continue;
+ }
+
+ /* find the image for the first time? */
+ if (ima->id.flag & LIB_DOIT) {
+ ima->id.flag &= ~LIB_DOIT;
+
+ /* we either fill in float or char, this ensures things go fine */
+ if (ibuf->rect_float)
+ imb_freerectImBuf(ibuf);
+ /* clear image */
+ if (R.r.bake_flag & R_BAKE_CLEAR) {
+ if (R.r.bake_mode == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT)
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid);
+ else
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
+ }
+ /* might be read by UI to set active image for display */
+ R.bakebuf = ima;
+ }
+
+ /* Tag image for redraw. */
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+
+ bs->obi = obi;
+ bs->vlr = vlr;
+ bs->vdone++; /* only for error message if nothing was rendered */
+ v++;
+ BLI_unlock_thread(LOCK_CUSTOM1);
+ return 1;
+ }
+ }
+ }
+
+ BLI_unlock_thread(LOCK_CUSTOM1);
+ return 0;
+}
+
+static void bake_single_vertex(BakeShade *bs, VertRen *vert, float u, float v)
+{
+ int *origindex, i;
+ MLoopCol *basevcol;
+ MLoop *mloop;
+
+ origindex = RE_vertren_get_origindex(bs->obi->obr, vert, 0);
+ if (!origindex || *origindex == ORIGINDEX_NONE)
+ return;
+
+ /* Search for matching vertex index and apply shading. */
+ for (i = 0; i < bs->mpoly->totloop; i++) {
+ mloop = bs->mloop + i;
+ if (mloop->v != *origindex)
+ continue;
+ basevcol = bs->vcol;
+ bs->vcol = basevcol + i;
+ do_bake_shade(bs, 0, 0, u, v);
+ bs->vcol = basevcol;
+ break;
+ }
+}
+
+/* Bake all vertices of a face. Actually, this still works on a face-by-face
+ * basis, and each vertex on each face is shaded. Vertex colors are a property
+ * of loops, not vertices. */
+static void shade_verts(BakeShade *bs)
+{
+ VlakRen *vlr = bs->vlr;
+
+ /* Disable baking to image; write to vcol instead. vcol pointer is set in
+ * bake_single_vertex. */
+ bs->ima = NULL;
+ bs->rect = NULL;
+ bs->rect_float = NULL;
+ bs->displacement_buffer = NULL;
+ bs->displacement_min = FLT_MAX;
+ bs->displacement_max = -FLT_MAX;
+
+ bs->quad = 0;
+
+ /* No anti-aliasing for vertices. */
+ zero_v3(bs->dxco);
+ zero_v3(bs->dyco);
+
+ /* Shade each vertex of the face. u and v are barycentric coordinates; since
+ * we're only interested in vertices, these will be 0 or 1. */
+ if ((vlr->flag & R_FACE_SPLIT) == 0) {
+ /* Processing triangle face, whole quad, or first half of split quad. */
+
+ bake_single_vertex(bs, bs->vlr->v1, 1.0f, 0.0f);
+ bake_single_vertex(bs, bs->vlr->v2, 0.0f, 1.0f);
+ bake_single_vertex(bs, bs->vlr->v3, 0.0f, 0.0f);
+
+ if (vlr->v4) {
+ bs->quad = 1;
+ bake_single_vertex(bs, bs->vlr->v4, 0.0f, 0.0f);
+ }
+ }
+ else {
+ /* Processing second half of split quad. Only one vertex to go. */
+ if (vlr->flag & R_DIVIDE_24) {
+ bake_single_vertex(bs, bs->vlr->v2, 0.0f, 1.0f);
+ }
+ else {
+ bake_single_vertex(bs, bs->vlr->v3, 0.0f, 0.0f);
+ }
+ }
+}
+
+/* already have tested for tface and ima and zspan */
+static void shade_tface(BakeShade *bs)
+{
+ VlakRen *vlr = bs->vlr;
+ ObjectInstanceRen *obi = bs->obi;
+ ObjectRen *obr = obi->obr;
+ MTFace *tface = RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
+ Image *ima = tface->tpage;
+ float vec[4][2];
+ int a, i1, i2, i3;
+
+ /* check valid zspan */
+ if (ima != bs->ima) {
+ BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL);
+
+ bs->ima = ima;
+ bs->ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ /* note, these calls only free/fill contents of zspan struct, not zspan itself */
+ zbuf_free_span(bs->zspan);
+ zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y, R.clipcrop);
+ }
+
+ bs->rectx = bs->ibuf->x;
+ bs->recty = bs->ibuf->y;
+ bs->rect = bs->ibuf->rect;
+ bs->rect_colorspace = bs->ibuf->rect_colorspace;
+ bs->rect_float = bs->ibuf->rect_float;
+ bs->vcol = NULL;
+ bs->quad = 0;
+ bs->rect_mask = NULL;
+ bs->displacement_buffer = NULL;
+
+ if (bs->use_mask || bs->use_displacement_buffer) {
+ BakeImBufuserData *userdata = bs->ibuf->userdata;
+ if (userdata == NULL) {
+ BLI_lock_thread(LOCK_CUSTOM1);
+ userdata = bs->ibuf->userdata;
+ if (userdata == NULL) /* since the thread was locked, its possible another thread alloced the value */
+ userdata = MEM_callocN(sizeof(BakeImBufuserData), "BakeImBufuserData");
+
+ if (bs->use_mask) {
+ if (userdata->mask_buffer == NULL) {
+ userdata->mask_buffer = MEM_callocN(sizeof(char) * bs->rectx * bs->recty, "BakeMask");
+ }
+ }
+
+ if (bs->use_displacement_buffer)
+ userdata->displacement_buffer = MEM_callocN(sizeof(float) * bs->rectx * bs->recty, "BakeDisp");
+
+ bs->ibuf->userdata = userdata;
+
+ BLI_unlock_thread(LOCK_CUSTOM1);
+ }
+
+ bs->rect_mask = userdata->mask_buffer;
+ bs->displacement_buffer = userdata->displacement_buffer;
+ }
+
+ /* get pixel level vertex coordinates */
+ for (a = 0; a < 4; a++) {
+ /* Note, workaround for pixel aligned UVs which are common and can screw up our intersection tests
+ * where a pixel gets in between 2 faces or the middle of a quad,
+ * camera aligned quads also have this problem but they are less common.
+ * Add a small offset to the UVs, fixes bug #18685 - Campbell */
+ vec[a][0] = tface->uv[a][0] * (float)bs->rectx - (0.5f + 0.001f);
+ vec[a][1] = tface->uv[a][1] * (float)bs->recty - (0.5f + 0.002f);
+ }
+
+ /* UV indices have to be corrected for possible quad->tria splits */
+ i1 = 0; i2 = 1; i3 = 2;
+ vlr_set_uv_indices(vlr, &i1, &i2, &i3);
+ bake_set_vlr_dxyco(bs, vec[i1], vec[i2], vec[i3]);
+ zspan_scanconvert(bs->zspan, bs, vec[i1], vec[i2], vec[i3], do_bake_shade);
+
+ if (vlr->v4) {
+ bs->quad = 1;
+ bake_set_vlr_dxyco(bs, vec[0], vec[2], vec[3]);
+ zspan_scanconvert(bs->zspan, bs, vec[0], vec[2], vec[3], do_bake_shade);
+ }
+}
+
+static void *do_bake_thread(void *bs_v)
+{
+ BakeShade *bs = bs_v;
+
+ while (get_next_bake_face(bs)) {
+ if (R.r.bake_flag & R_BAKE_VCOL) {
+ shade_verts(bs);
+ }
+ else {
+ shade_tface(bs);
+ }
+
+ /* fast threadsafe break test */
+ if (R.test_break(R.tbh))
+ break;
+
+ /* access is not threadsafe but since its just true/false probably ok
+ * only used for interactive baking */
+ if (bs->do_update) {
+ *bs->do_update = true;
+ }
+ }
+ bs->ready = true;
+
+ BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL);
+
+ return NULL;
+}
+
+void RE_bake_ibuf_filter(ImBuf *ibuf, char *mask, const int filter)
+{
+ /* must check before filtering */
+ const short is_new_alpha = (ibuf->planes != R_IMF_PLANES_RGBA) && BKE_imbuf_alpha_test(ibuf);
+
+ /* Margin */
+ if (filter) {
+ IMB_filter_extend(ibuf, mask, filter);
+ }
+
+ /* if the bake results in new alpha then change the image setting */
+ if (is_new_alpha) {
+ ibuf->planes = R_IMF_PLANES_RGBA;
+ }
+ else {
+ if (filter && ibuf->planes != R_IMF_PLANES_RGBA) {
+ /* clear alpha added by filtering */
+ IMB_rectfill_alpha(ibuf, 1.0f);
+ }
+ }
+}
+
+void RE_bake_ibuf_normalize_displacement(ImBuf *ibuf, float *displacement, char *mask, float displacement_min, float displacement_max)
+{
+ int i;
+ float *current_displacement = displacement;
+ char *current_mask = mask;
+ float max_distance;
+
+ max_distance = max_ff(fabsf(displacement_min), fabsf(displacement_max));
+
+ for (i = 0; i < ibuf->x * ibuf->y; i++) {
+ if (*current_mask == FILTER_MASK_USED) {
+ float normalized_displacement;
+
+ if (max_distance > 1e-5f)
+ normalized_displacement = (*current_displacement + max_distance) / (max_distance * 2);
+ else
+ normalized_displacement = 0.5f;
+
+ if (ibuf->rect_float) {
+ /* currently baking happens to RGBA only */
+ float *fp = ibuf->rect_float + i * 4;
+ fp[0] = fp[1] = fp[2] = normalized_displacement;
+ fp[3] = 1.0f;
+ }
+
+ if (ibuf->rect) {
+ unsigned char *cp = (unsigned char *) (ibuf->rect + i);
+ cp[0] = cp[1] = cp[2] = FTOCHAR(normalized_displacement);
+ cp[3] = 255;
+ }
+ }
+
+ current_displacement++;
+ current_mask++;
+ }
+}
+
+/* using object selection tags, the faces with UV maps get baked */
+/* render should have been setup */
+/* returns 0 if nothing was handled */
+int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_update, float *progress)
+{
+ BakeShade *handles;
+ ListBase threads;
+ Image *ima;
+ int a, vdone = false, result = BAKE_RESULT_OK;
+ bool use_mask = false;
+ bool use_displacement_buffer = false;
+
+ re->scene_color_manage = BKE_scene_check_color_management_enabled(re->scene);
+
+ /* initialize render global */
+ R = *re;
+ R.bakebuf = NULL;
+
+ /* initialize static vars */
+ get_next_bake_face(NULL);
+
+ /* do we need a mask? */
+ if (re->r.bake_filter)
+ use_mask = true;
+
+ /* do we need buffer to store displacements */
+ if (type == RE_BAKE_DISPLACEMENT) {
+ if ((R.r.bake_flag & R_BAKE_NORMALIZE) && R.r.bake_maxdist == 0.0f) {
+ use_displacement_buffer = true;
+ use_mask = true;
+ }
+ }
+
+ /* baker uses this flag to detect if image was initialized */
+ if ((R.r.bake_flag & R_BAKE_VCOL) == 0) {
+ for (ima = G.main->image.first; ima; ima = ima->id.next) {
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ ima->id.flag |= LIB_DOIT;
+ ima->flag &= ~IMA_USED_FOR_RENDER;
+ if (ibuf) {
+ ibuf->userdata = NULL; /* use for masking if needed */
+ }
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+ }
+
+ BLI_init_threads(&threads, do_bake_thread, re->r.threads);
+
+ handles = MEM_callocN(sizeof(BakeShade) * re->r.threads, "BakeShade");
+
+ /* get the threads running */
+ for (a = 0; a < re->r.threads; a++) {
+ /* set defaults in handles */
+ handles[a].ssamp.shi[0].lay = re->lay;
+
+ if (type == RE_BAKE_SHADOW) {
+ handles[a].ssamp.shi[0].passflag = SCE_PASS_SHADOW;
+ }
+ else {
+ handles[a].ssamp.shi[0].passflag = SCE_PASS_COMBINED;
+ }
+ handles[a].ssamp.shi[0].combinedflag = ~(SCE_PASS_SPEC);
+ handles[a].ssamp.shi[0].thread = a;
+ handles[a].ssamp.tot = 1;
+
+ handles[a].type = type;
+ handles[a].actob = actob;
+ if (R.r.bake_flag & R_BAKE_VCOL)
+ handles[a].zspan = NULL;
+ else
+ handles[a].zspan = MEM_callocN(sizeof(ZSpan), "zspan for bake");
+
+ handles[a].use_mask = use_mask;
+ handles[a].use_displacement_buffer = use_displacement_buffer;
+
+ handles[a].do_update = do_update; /* use to tell the view to update */
+
+ handles[a].displacement_min = FLT_MAX;
+ handles[a].displacement_max = -FLT_MAX;
+
+ BLI_insert_thread(&threads, &handles[a]);
+ }
+
+ /* wait for everything to be done */
+ a = 0;
+ while (a != re->r.threads) {
+ PIL_sleep_ms(50);
+
+ /* calculate progress */
+ for (vdone = false, a = 0; a < re->r.threads; a++)
+ vdone += handles[a].vdone;
+ if (progress)
+ *progress = (float)(vdone / (float)re->totvlak);
+
+ for (a = 0; a < re->r.threads; a++) {
+ if (handles[a].ready == false) {
+ break;
+ }
+ }
+ }
+
+ /* filter and refresh images */
+ if ((R.r.bake_flag & R_BAKE_VCOL) == 0) {
+ float displacement_min = FLT_MAX, displacement_max = -FLT_MAX;
+
+ if (use_displacement_buffer) {
+ for (a = 0; a < re->r.threads; a++) {
+ displacement_min = min_ff(displacement_min, handles[a].displacement_min);
+ displacement_max = max_ff(displacement_max, handles[a].displacement_max);
+ }
+ }
+
+ for (ima = G.main->image.first; ima; ima = ima->id.next) {
+ if ((ima->id.flag & LIB_DOIT) == 0) {
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ BakeImBufuserData *userdata;
+
+ if (ima->flag & IMA_USED_FOR_RENDER)
+ result = BAKE_RESULT_FEEDBACK_LOOP;
+
+ if (!ibuf)
+ continue;
+
+ userdata = (BakeImBufuserData *)ibuf->userdata;
+ if (userdata) {
+ RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, re->r.bake_filter);
+
+ if (use_displacement_buffer) {
+ RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer,
+ displacement_min, displacement_max);
+ }
+ }
+
+ ibuf->userflags |= IB_BITMAPDIRTY;
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+ }
+
+ /* calculate return value */
+ for (a = 0; a < re->r.threads; a++) {
+ zbuf_free_span(handles[a].zspan);
+ MEM_freeN(handles[a].zspan);
+ }
+ }
+
+ MEM_freeN(handles);
+
+ BLI_end_threads(&threads);
+
+ if (vdone == 0) {
+ result = BAKE_RESULT_NO_OBJECTS;
+ }
+
+ return result;
+}
+
+struct Image *RE_bake_shade_get_image(void)
+{
+ return R.bakebuf;
+}
+
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 37fd213edd5..fbcab8c19d4 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -42,6 +42,11 @@
#include "BLI_memarena.h"
#include "BLI_ghash.h"
#include "BLI_linklist.h"
+#ifdef WITH_FREESTYLE
+# include "BLI_edgehash.h"
+#endif
+
+#include "BLF_translation.h"
#include "DNA_armature_types.h"
#include "DNA_camera_types.h"
@@ -150,6 +155,7 @@ static HaloRen *initstar(Render *re, ObjectRen *obr, const float vec[3], float h
har->hasize= hasize;
har->zd= 0.0;
+ har->pool = re->pool;
return har;
}
@@ -161,7 +167,7 @@ static HaloRen *initstar(Render *re, ObjectRen *obr, const float vec[3], float h
*/
void RE_make_stars(Render *re, Scene *scenev3d, void (*initfunc)(void),
- void (*vertexfunc)(float*), void (*termfunc)(void))
+ void (*vertexfunc)(float *), void (*termfunc)(void))
{
extern unsigned char hash[512];
ObjectRen *obr= NULL;
@@ -915,7 +921,7 @@ static void flag_render_node_material(Render *re, bNodeTree *ntree)
{
bNode *node;
- for (node=ntree->nodes.first; node; node= node->next) {
+ for (node = ntree->nodes.first; node; node = node->next) {
if (node->id) {
if (GS(node->id->name)==ID_MA) {
Material *ma= (Material *)node->id;
@@ -2653,6 +2659,9 @@ static void init_render_dm(DerivedMesh *dm, Render *re, ObjectRen *obr,
MVert *mvert = NULL;
MFace *mface;
Material *ma;
+#ifdef WITH_FREESTYLE
+ FreestyleFace *ffa;
+#endif
/* Curve *cu= ELEM(ob->type, OB_FONT, OB_CURVE) ? ob->data : NULL; */
mvert= dm->getVertArray(dm);
@@ -2682,6 +2691,9 @@ static void init_render_dm(DerivedMesh *dm, Render *re, ObjectRen *obr,
ma= give_render_material(re, ob, mat_iter+1);
end= dm->getNumTessFaces(dm);
mface= dm->getTessFaceArray(dm);
+#ifdef WITH_FREESTYLE
+ ffa= dm->getTessFaceDataArray(dm, CD_FREESTYLE_FACE);
+#endif
for (a=0; a<end; a++, mface++) {
int v1, v2, v3, v4, flag;
@@ -2693,7 +2705,7 @@ static void init_render_dm(DerivedMesh *dm, Render *re, ObjectRen *obr,
v2= mface->v2;
v3= mface->v3;
v4= mface->v4;
- flag= mface->flag & ME_SMOOTH;
+ flag = mface->flag & ME_SMOOTH;
vlr= RE_findOrAddVlak(obr, obr->totvlak++);
vlr->v1= RE_findOrAddVert(obr, vertofs+v1);
@@ -2711,6 +2723,9 @@ static void init_render_dm(DerivedMesh *dm, Render *re, ObjectRen *obr,
vlr->mat= ma;
vlr->flag= flag;
vlr->ec= 0; /* mesh edges rendered separately */
+#ifdef WITH_FREESTYLE
+ vlr->freestyle_face_mark= (ffa && (ffa[a].flag & FREESTYLE_FACE_MARK)) ? 1 : 0;
+#endif
if (len==0) obr->totvlak--;
else {
@@ -2820,7 +2835,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
ListBase disp={NULL, NULL};
Material **matar;
float *data, *fp, *orco=NULL;
- float n[3], mat[4][4];
+ float n[3], mat[4][4], nmat[4][4];
int nr, startvert, a, b;
int need_orco=0, totmat;
@@ -2835,6 +2850,11 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
mult_m4_m4m4(mat, re->viewmat, ob->obmat);
invert_m4_m4(ob->imat, mat);
+ /* local object -> world space transform for normals */
+ copy_m4_m4(nmat, mat);
+ transpose_m4(nmat);
+ invert_m4(nmat);
+
/* material array */
totmat= ob->totcol+1;
matar= MEM_callocN(sizeof(Material*)*totmat, "init_render_surf matar");
@@ -2859,7 +2879,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
}
else {
if (need_orco) {
- orco= get_object_orco(re, ob);
+ orco = get_object_orco(re, ob);
}
while (dl) {
@@ -2891,13 +2911,20 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
zero_v3(n);
index= dl->index;
for (a=0; a<dl->parts; a++, index+=3) {
+ int v1 = index[0], v2 = index[1], v3 = index[2];
+ float *co1 = &dl->verts[v1 * 3],
+ *co2 = &dl->verts[v2 * 3],
+ *co3 = &dl->verts[v3 * 3];
+
vlr= RE_findOrAddVlak(obr, obr->totvlak++);
- vlr->v1= RE_findOrAddVert(obr, startvert+index[0]);
- vlr->v2= RE_findOrAddVert(obr, startvert+index[1]);
- vlr->v3= RE_findOrAddVert(obr, startvert+index[2]);
+ vlr->v1= RE_findOrAddVert(obr, startvert + v1);
+ vlr->v2= RE_findOrAddVert(obr, startvert + v2);
+ vlr->v3= RE_findOrAddVert(obr, startvert + v3);
vlr->v4= NULL;
- if (area_tri_v3(vlr->v3->co, vlr->v2->co, vlr->v1->co)>FLT_EPSILON10) {
- normal_tri_v3(tmp, vlr->v3->co, vlr->v2->co, vlr->v1->co);
+
+ /* to prevent float accuracy issues, we calculate normal in local object space (not world) */
+ if (area_tri_v3(co3, co2, co1)>FLT_EPSILON10) {
+ normal_tri_v3(tmp, co3, co2, co1);
add_v3_v3(n, tmp);
}
@@ -2906,6 +2933,8 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
vlr->ec= 0;
}
+ /* transform normal to world space */
+ mul_m4_v3(nmat, n);
normalize_v3(n);
/* vertex normals */
@@ -3158,7 +3187,12 @@ static void init_camera_inside_volumes(Render *re)
{
ObjectInstanceRen *obi;
VolumeOb *vo;
- float co[3] = {0.f, 0.f, 0.f};
+ /* coordinates are all in camera space, so camera coordinate is zero. we also
+ * add an offset for the clip start, however note that with clip start it's
+ * actually impossible to do a single 'inside' test, since there will not be
+ * a single point where all camera rays start from, though for small clip start
+ * they will be close together. */
+ float co[3] = {0.f, 0.f, -re->clipsta};
for (vo= re->volumes.first; vo; vo= vo->next) {
for (obi= re->instancetable.first; obi; obi= obi->next) {
@@ -3199,6 +3233,33 @@ static void add_volume(Render *re, ObjectRen *obr, Material *ma)
BLI_addtail(&re->volumes, vo);
}
+#ifdef WITH_FREESTYLE
+static EdgeHash *make_freestyle_edge_mark_hash(DerivedMesh *dm)
+{
+ EdgeHash *edge_hash= BLI_edgehash_new();
+ FreestyleEdge *fed;
+ MEdge *medge;
+ int totedge, a;
+
+ medge = dm->getEdgeArray(dm);
+ totedge = dm->getNumEdges(dm);
+ fed = dm->getEdgeDataArray(dm, CD_FREESTYLE_EDGE);
+ if (fed) {
+ for (a = 0; a < totedge; a++) {
+ if (fed[a].flag & FREESTYLE_EDGE_MARK)
+ BLI_edgehash_insert(edge_hash, medge[a].v1, medge[a].v2, medge+a);
+ }
+ }
+ return edge_hash;
+}
+
+static int has_freestyle_edge_mark(EdgeHash *edge_hash, int v1, int v2)
+{
+ MEdge *medge= BLI_edgehash_lookup(edge_hash, v1, v2);
+ return (!medge) ? 0 : 1;
+}
+#endif
+
static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
{
Object *ob= obr->ob;
@@ -3212,12 +3273,15 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
CustomDataMask mask;
float xn, yn, zn, imat[3][3], mat[4][4]; //nor[3],
float *orco=0;
- int need_orco=0, need_stress=0, need_nmap_tangent=0, need_tangent=0;
+ int need_orco=0, need_stress=0, need_nmap_tangent=0, need_tangent=0, need_origindex=0;
int a, a1, ok, vertofs;
int end, do_autosmooth = FALSE, totvert = 0;
int use_original_normals = FALSE;
int recalc_normals = 0; /* false by default */
int negative_scale;
+#ifdef WITH_FREESTYLE
+ FreestyleFace *ffa;
+#endif
me= ob->data;
@@ -3262,6 +3326,10 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
need_nmap_tangent= 1;
}
+ /* origindex currently only used when baking to vertex colors */
+ if (re->flag & R_BAKING && re->r.bake_flag & R_BAKE_VCOL)
+ need_origindex= 1;
+
/* check autosmooth and displacement, we then have to skip only-verts optimize */
do_autosmooth |= (me->flag & ME_AUTOSMOOTH);
if (do_autosmooth)
@@ -3299,6 +3367,15 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
make_render_halos(re, obr, me, totvert, mvert, ma, orco);
}
else {
+ const int *index_vert_orig = NULL;
+ const int *index_mf_to_mpoly = NULL;
+ const int *index_mp_to_orig = NULL;
+ if (need_origindex) {
+ index_vert_orig = dm->getVertDataArray(dm, CD_ORIGINDEX);
+ /* double lookup for faces -> polys */
+ index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
+ }
for (a=0; a<totvert; a++, mvert++) {
ver= RE_findOrAddVert(obr, obr->totvert++);
@@ -3315,9 +3392,28 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
ver->orco= orco;
orco+=3;
}
+
+ if (need_origindex) {
+ int *origindex;
+ origindex = RE_vertren_get_origindex(obr, ver, 1);
+
+ /* Use orig index array if it's available (e.g. in the presence
+ * of modifiers). */
+ if (index_vert_orig)
+ *origindex = index_vert_orig[a];
+ else
+ *origindex = a;
+ }
}
if (!timeoffset) {
+#ifdef WITH_FREESTYLE
+ EdgeHash *edge_hash;
+
+ /* create a hash table of Freestyle edge marks */
+ edge_hash = make_freestyle_edge_mark_hash(dm);
+#endif
+
/* store customdata names, because DerivedMesh is freed */
RE_set_customdata_names(obr, &dm->faceData);
@@ -3354,6 +3450,9 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
if (ok) {
end= dm->getNumTessFaces(dm);
mface= dm->getTessFaceArray(dm);
+#ifdef WITH_FREESTYLE
+ ffa= dm->getTessFaceDataArray(dm, CD_FREESTYLE_FACE);
+#endif
for (a=0; a<end; a++, mface++) {
int v1, v2, v3, v4, flag;
@@ -3366,7 +3465,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 = mface->flag & ME_SMOOTH;
vlr= RE_findOrAddVlak(obr, obr->totvlak++);
vlr->v1= RE_findOrAddVert(obr, vertofs+v1);
@@ -3375,6 +3474,24 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
if (v4) vlr->v4= RE_findOrAddVert(obr, vertofs+v4);
else vlr->v4= 0;
+#ifdef WITH_FREESTYLE
+ /* Freestyle edge/face marks */
+ {
+ int edge_mark = 0;
+
+ if(has_freestyle_edge_mark(edge_hash, v1, v2)) edge_mark |= R_EDGE_V1V2;
+ if(has_freestyle_edge_mark(edge_hash, v2, v3)) edge_mark |= R_EDGE_V2V3;
+ if (!v4) {
+ if(has_freestyle_edge_mark(edge_hash, v3, v1)) edge_mark |= R_EDGE_V3V1;
+ } else {
+ if(has_freestyle_edge_mark(edge_hash, v3, v4)) edge_mark |= R_EDGE_V3V4;
+ if(has_freestyle_edge_mark(edge_hash, v4, v1)) edge_mark |= R_EDGE_V4V1;
+ }
+ vlr->freestyle_edge_mark= edge_mark;
+ }
+ vlr->freestyle_face_mark= (ffa && (ffa[a].flag & FREESTYLE_FACE_MARK)) ? 1 : 0;
+#endif
+
/* render normals are inverted in render */
if (use_original_normals) {
MFace *mf= me->mface+a;
@@ -3436,11 +3553,31 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
}
}
}
+
+ if (need_origindex) {
+ /* Find original index of mpoly for this tessface. Options:
+ * - Modified mesh; two-step look up from tessface -> modified mpoly -> original mpoly
+ * - OR Tesselated mesh; look up from tessface -> mpoly
+ * - OR Failsafe; tessface == mpoly. Could probably assert(false) in this case? */
+ int *origindex;
+ origindex = RE_vlakren_get_origindex(obr, vlr, 1);
+ if (index_mf_to_mpoly && index_mp_to_orig)
+ *origindex = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a);
+ else if (index_mf_to_mpoly)
+ *origindex = index_mf_to_mpoly[a];
+ else
+ *origindex = a;
+ }
}
}
}
}
}
+
+#ifdef WITH_FREESTYLE
+ /* release the hash table of Freestyle edge marks */
+ BLI_edgehash_free(edge_hash, NULL);
+#endif
/* exception... we do edges for wire mode. potential conflict when faces exist... */
end= dm->getNumEdges(dm);
@@ -3955,18 +4092,10 @@ static void set_renderlayer_lightgroups(Render *re, Scene *sce)
void init_render_world(Render *re)
{
int a;
- char *cp;
if (re->scene && re->scene->world) {
re->wrld= *(re->scene->world);
-
- cp= (char *)&re->wrld.fastcol;
-
- cp[0]= 255.0f*re->wrld.horr;
- cp[1]= 255.0f*re->wrld.horg;
- cp[2]= 255.0f*re->wrld.horb;
- cp[3]= 1;
-
+
copy_v3_v3(re->grvec, re->viewmat[2]);
normalize_v3(re->grvec);
copy_m3_m4(re->imat, re->viewinv);
@@ -4240,6 +4369,26 @@ static void check_non_flat_quads(ObjectRen *obr)
/* new normals */
normal_tri_v3(vlr->n, vlr->v3->co, vlr->v2->co, vlr->v1->co);
normal_tri_v3(vlr1->n, vlr1->v3->co, vlr1->v2->co, vlr1->v1->co);
+
+#ifdef WITH_FREESTYLE
+ /* Freestyle edge marks */
+ if (vlr->flag & R_DIVIDE_24) {
+ vlr1->freestyle_edge_mark=
+ ((vlr->freestyle_edge_mark & R_EDGE_V2V3) ? R_EDGE_V1V2 : 0) |
+ ((vlr->freestyle_edge_mark & R_EDGE_V3V4) ? R_EDGE_V2V3 : 0);
+ vlr->freestyle_edge_mark=
+ ((vlr->freestyle_edge_mark & R_EDGE_V1V2) ? R_EDGE_V1V2 : 0) |
+ ((vlr->freestyle_edge_mark & R_EDGE_V4V1) ? R_EDGE_V3V1 : 0);
+ }
+ else {
+ vlr1->freestyle_edge_mark=
+ ((vlr->freestyle_edge_mark & R_EDGE_V3V4) ? R_EDGE_V2V3 : 0) |
+ ((vlr->freestyle_edge_mark & R_EDGE_V4V1) ? R_EDGE_V3V1 : 0);
+ vlr->freestyle_edge_mark=
+ ((vlr->freestyle_edge_mark & R_EDGE_V1V2) ? R_EDGE_V1V2 : 0) |
+ ((vlr->freestyle_edge_mark & R_EDGE_V2V3) ? R_EDGE_V2V3 : 0);
+ }
+#endif
}
/* clear the flag when not divided */
else vlr->flag &= ~R_DIVIDE_24;
@@ -4710,7 +4859,7 @@ static int allow_render_dupli_instance(Render *UNUSED(re), DupliObject *dob, Obj
if (totmaterial) {
for (a= 0; a<*totmaterial; a++) {
- ma= give_current_material(obd, a);
+ ma= give_current_material(obd, a + 1);
if (ma && (ma->material_type == MA_TYPE_HALO))
return 0;
}
@@ -5022,8 +5171,8 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
* following calls don't depend on 'RE_SetCamera' */
RE_SetCamera(re, camera);
- normalize_m4(camera->obmat);
- invert_m4_m4(mat, camera->obmat);
+ normalize_m4_m4(mat, camera->obmat);
+ invert_m4(mat);
RE_SetView(re, mat);
camera->recalc= OB_RECALC_OB; /* force correct matrix for scaled cameras */
}
@@ -5067,7 +5216,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
tothalo= re->tothalo;
if (!re->test_break(re->tbh)) {
if (re->wrld.mode & WO_STARS) {
- re->i.infostr= "Creating Starfield";
+ re->i.infostr = IFACE_("Creating Starfield");
re->stats_draw(re->sdh, &re->i);
RE_make_stars(re, NULL, NULL, NULL, NULL);
}
@@ -5076,7 +5225,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
init_camera_inside_volumes(re);
- re->i.infostr= "Creating Shadowbuffers";
+ re->i.infostr = IFACE_("Creating Shadowbuffers");
re->stats_draw(re->sdh, &re->i);
/* SHADOW BUFFER */
@@ -5126,7 +5275,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
else
re->i.convertdone = TRUE;
- re->i.infostr= NULL;
+ re->i.infostr = NULL;
re->stats_draw(re->sdh, &re->i);
}
@@ -5172,8 +5321,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(camera->obmat);
- invert_m4_m4(mat, camera->obmat);
+ normalize_m4_m4(mat, camera->obmat);
+ invert_m4(mat);
RE_SetView(re, mat);
}
@@ -5539,7 +5688,7 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned
ListBase strandsurface;
int step;
- re->i.infostr= "Calculating previous frame vectors";
+ re->i.infostr = IFACE_("Calculating previous frame vectors");
re->r.mode |= R_SPEED;
speedvector_project(re, NULL, NULL, NULL); /* initializes projection code */
@@ -5558,7 +5707,7 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned
if (!re->test_break(re->tbh)) {
/* creates entire dbase */
- re->i.infostr= "Calculating next frame vectors";
+ re->i.infostr = IFACE_("Calculating next frame vectors");
database_fromscene_vectors(re, sce, lay, +1);
}
@@ -5606,7 +5755,7 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned
ok= 1;
}
if (ok==0) {
- printf("speed table: missing object %s\n", obi->ob->id.name+2);
+ printf("speed table: missing object %s\n", obi->ob->id.name + 2);
continue;
}
@@ -5622,7 +5771,7 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned
if (obi->totvector==oldobi->totvector)
calculate_speedvectors(re, obi, oldobi->vectors, step);
else
- printf("Warning: object %s has different amount of vertices or strands on other frame\n", obi->ob->id.name+2);
+ printf("Warning: object %s has different amount of vertices or strands on other frame\n", obi->ob->id.name + 2);
} /* not fluidsim */
oldobi= oldobi->next;
@@ -5644,7 +5793,7 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned
}
}
- re->i.infostr= NULL;
+ re->i.infostr = NULL;
re->stats_draw(re->sdh, &re->i);
}
@@ -5712,8 +5861,8 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
/* if no camera, set unit */
if (camera) {
- normalize_m4(camera->obmat);
- invert_m4_m4(mat, camera->obmat);
+ normalize_m4_m4(mat, camera->obmat);
+ invert_m4(mat);
RE_SetView(re, mat);
}
else {
diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c
index be8b7f6c357..c5872c52e0f 100644
--- a/source/blender/render/intern/source/envmap.c
+++ b/source/blender/render/intern/source/envmap.c
@@ -38,6 +38,8 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h" /* for rectcpy */
@@ -512,7 +514,7 @@ void make_envmaps(Render *re)
trace = (re->r.mode & R_RAYTRACE);
re->r.mode &= ~R_RAYTRACE;
- re->i.infostr = "Creating Environment maps";
+ re->i.infostr = IFACE_("Creating Environment maps");
re->stats_draw(re->sdh, &re->i);
/* 5 = hardcoded max recursion level */
@@ -668,7 +670,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)
+int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, struct ImagePool *pool)
{
extern Render R; /* only in this call */
/* texvec should be the already reflected normal */
@@ -687,12 +689,12 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
env->ima = tex->ima;
if (env->ima && env->ima->ok) {
if (env->cube[1] == NULL) {
- ImBuf *ibuf_ima = BKE_image_acquire_ibuf(env->ima, NULL, NULL);
+ ImBuf *ibuf_ima = BKE_image_pool_acquire_ibuf(env->ima, NULL, pool);
if (ibuf_ima)
envmap_split_ima(env, ibuf_ima);
else
env->ok = 0;
- BKE_image_release_ibuf(env->ima, ibuf_ima, NULL);
+ BKE_image_pool_release_ibuf(env->ima, ibuf_ima, pool);
}
}
}
@@ -720,7 +722,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);
+ imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, texres, pool);
/* edges? */
@@ -737,7 +739,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);
+ imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr1, pool);
}
else texr1.tr = texr1.tg = texr1.tb = texr1.ta = 0.0;
@@ -750,7 +752,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);
+ imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr2, pool);
}
else texr2.tr = texr2.tg = texr2.tb = texr2.ta = 0.0;
@@ -766,7 +768,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o
}
}
else {
- imagewrap(tex, NULL, ibuf, sco, texres);
+ imagewrap(tex, NULL, ibuf, sco, texres, pool);
}
return 1;
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index 6fdf11ba48c..90528fddc85 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -1,4 +1,5 @@
/*
+
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -128,9 +129,20 @@ int RE_engine_is_external(Render *re)
RenderEngine *RE_engine_create(RenderEngineType *type)
{
+ return RE_engine_create_ex(type, FALSE);
+}
+
+RenderEngine *RE_engine_create_ex(RenderEngineType *type, bool use_for_viewport)
+{
RenderEngine *engine = MEM_callocN(sizeof(RenderEngine), "RenderEngine");
engine->type = type;
+ if (use_for_viewport) {
+ engine->flag |= RE_ENGINE_USED_FOR_VIEWPORT;
+
+ BLI_begin_threaded_malloc();
+ }
+
return engine;
}
@@ -142,6 +154,10 @@ void RE_engine_free(RenderEngine *engine)
}
#endif
+ if (engine->flag & RE_ENGINE_USED_FOR_VIEWPORT) {
+ BLI_end_threaded_malloc();
+ }
+
if (engine->text)
MEM_freeN(engine->text);
@@ -150,6 +166,23 @@ void RE_engine_free(RenderEngine *engine)
/* Render Results */
+static RenderPart *get_part_from_result(Render *re, RenderResult *result)
+{
+ RenderPart *pa;
+
+ for (pa = re->parts.first; pa; pa = pa->next) {
+ if (result->tilerect.xmin == pa->disprect.xmin - re->disprect.xmin &&
+ result->tilerect.ymin == pa->disprect.ymin - re->disprect.ymin &&
+ result->tilerect.xmax == pa->disprect.xmax - re->disprect.xmin &&
+ result->tilerect.ymax == pa->disprect.ymax - re->disprect.ymin)
+ {
+ return pa;
+ }
+ }
+
+ return NULL;
+}
+
RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername)
{
Render *re = engine->re;
@@ -179,12 +212,19 @@ RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w,
/* can be NULL if we CLAMP the width or height to 0 */
if (result) {
+ RenderPart *pa;
+
BLI_addtail(&engine->fullresult, result);
result->tilerect.xmin += re->disprect.xmin;
result->tilerect.xmax += re->disprect.xmin;
result->tilerect.ymin += re->disprect.ymin;
result->tilerect.ymax += re->disprect.ymin;
+
+ pa = get_part_from_result(re, result);
+
+ if (pa)
+ pa->status = PART_STATUS_IN_PROGRESS;
}
return result;
@@ -203,7 +243,6 @@ void RE_engine_update_result(RenderEngine *engine, RenderResult *result)
void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel)
{
Render *re = engine->re;
- RenderPart *pa;
if (!result) {
return;
@@ -212,15 +251,10 @@ void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel
/* merge. on break, don't merge in result for preview renders, looks nicer */
if (!cancel) {
/* for exr tile render, detect tiles that are done */
- for (pa = re->parts.first; pa; pa = pa->next) {
- if (result->tilerect.xmin == pa->disprect.xmin &&
- result->tilerect.ymin == pa->disprect.ymin &&
- result->tilerect.xmax == pa->disprect.xmax &&
- result->tilerect.ymax == pa->disprect.ymax)
- {
- pa->ready = 1;
- }
- }
+ RenderPart *pa = get_part_from_result(re, result);
+
+ if (pa)
+ pa->status = PART_STATUS_READY;
if (re->result->do_exr_tile)
render_result_exr_file_merge(re->result, result);
@@ -310,6 +344,52 @@ 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)
+{
+ RenderPart *pa;
+ int total_tiles = 0;
+ rcti *tiles = NULL;
+ int allocation_size = 0, allocation_step = BLENDER_MAX_THREADS;
+
+ if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
+ *total_tiles_r = 0;
+ *tiles_r = NULL;
+ return;
+ }
+
+ for (pa = re->parts.first; pa; pa = pa->next) {
+ if (pa->status == PART_STATUS_IN_PROGRESS) {
+ if (total_tiles >= allocation_size) {
+ if (tiles == NULL)
+ 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;
+ }
+
+ tiles[total_tiles] = pa->disprect;
+
+ if (pa->crop) {
+ tiles[total_tiles].xmin += pa->crop;
+ tiles[total_tiles].ymin += pa->crop;
+ tiles[total_tiles].xmax -= pa->crop;
+ tiles[total_tiles].ymax -= pa->crop;
+ }
+
+ total_tiles++;
+ }
+ }
+
+ *total_tiles_r = total_tiles;
+ *tiles_r = tiles;
+}
+
+RenderData *RE_engine_get_render_data(Render *re)
+{
+ return &re->r;
+}
+
/* Render */
int RE_engine_render(Render *re, int do_all)
@@ -354,9 +434,7 @@ int RE_engine_render(Render *re, int do_all)
if (!engine) {
engine = RE_engine_create(type);
-
- if (persistent_data)
- re->engine = engine;
+ re->engine = engine;
}
engine->flag |= RE_ENGINE_RENDERING;
diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c
index cd06839b004..756fb098882 100644
--- a/source/blender/render/intern/source/imagetexture.c
+++ b/source/blender/render/intern/source/imagetexture.c
@@ -102,10 +102,15 @@ static void ibuf_get_color(float col[4], struct ImBuf *ibuf, int x, int y)
col[1] = ((float)rect[1])*(1.0f/255.0f);
col[2] = ((float)rect[2])*(1.0f/255.0f);
col[3] = ((float)rect[3])*(1.0f/255.0f);
+
+ /* bytes are internally straight, however render pipeline seems to expect premul */
+ col[0] *= col[3];
+ col[1] *= col[3];
+ col[2] *= col[3];
}
}
-int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResult *texres)
+int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResult *texres, struct ImagePool *pool)
{
float fx, fy, val1, val2, val3;
int x, y, retval;
@@ -125,13 +130,13 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
if (ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD))
return retval;
- ibuf= BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
+ ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
ima->flag|= IMA_USED_FOR_RENDER;
}
if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
@@ -159,14 +164,14 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
}
else {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
if ( (tex->flag & TEX_CHECKER_EVEN)==0) {
if ((xs+ys) & 1) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
@@ -183,14 +188,14 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
if (tex->extend == TEX_CLIPCUBE) {
if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0f || texvec[2]>1.0f) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
else if ( tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
@@ -219,7 +224,7 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
}
/* keep this before interpolation [#29761] */
- if (tex->imaflag & TEX_USEALPHA) {
+ if ((tex->imaflag & TEX_USEALPHA) && tex->ima && (tex->ima->flag & IMA_IGNORE_ALPHA) == 0) {
if ((tex->imaflag & TEX_CALCALPHA) == 0) {
texres->talpha = TRUE;
}
@@ -269,14 +274,18 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
ibuf_get_color(col, ibuf, x+1, y);
val2= (col[0]+col[1]+col[2]);
}
- else val2= val1;
+ else {
+ val2= val1;
+ }
if (y<ibuf->y-1) {
float col[4];
ibuf_get_color(col, ibuf, x, y+1);
- val3= (col[0]+col[1]+col[2]);
+ val3 = (col[0]+col[1]+col[2]);
+ }
+ else {
+ val3 = val1;
}
- else val3= val1;
/* do not mix up x and y here! */
texres->nor[0]= (val1-val2);
@@ -284,13 +293,19 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
}
}
- if (texres->talpha) texres->tin= texres->ta;
+ if (texres->talpha) {
+ texres->tin = texres->ta;
+ }
else if (tex->imaflag & TEX_CALCALPHA) {
- texres->ta= texres->tin= MAX3(texres->tr, texres->tg, texres->tb);
+ texres->ta = texres->tin = max_fff(texres->tr, texres->tg, texres->tb);
+ }
+ else {
+ texres->ta = texres->tin = 1.0;
}
- else texres->ta= texres->tin= 1.0;
- if (tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta;
+ if (tex->flag & TEX_NEGALPHA) {
+ texres->ta = 1.0f - texres->ta;
+ }
/* de-premul, this is being premulled in shade_input_do_shade() */
if (texres->ta!=1.0f && texres->ta>1e-4f) {
@@ -299,10 +314,10 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
texres->tg*= fx;
texres->tb*= fx;
}
-
+
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
-
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
+
BRICONTRGB;
return retval;
@@ -710,9 +725,10 @@ static int ibuf_get_color_clip(float col[4], ImBuf *ibuf, int x, int y, int extf
}
else {
char *rect = (char *)(ibuf->rect + x + y*ibuf->x);
- col[0] = rect[0]*(1.f/255.f);
- col[1] = rect[1]*(1.f/255.f);
- col[2] = rect[2]*(1.f/255.f);
+ float inv_alpha_fac = (1.0f / 255.0f) * rect[3] * (1.0f / 255.0f);
+ col[0] = rect[0] * inv_alpha_fac;
+ col[1] = rect[1] * inv_alpha_fac;
+ col[2] = rect[2] * inv_alpha_fac;
col[3] = clip ? 0.f : rect[3]*(1.f/255.f);
}
return clip;
@@ -823,7 +839,7 @@ static float EWA_WTS[EWA_MAXIDX + 1] = {
#endif
//static int ISNAN(float x) { return (x != x); }
-static void radangle2imp(float a2, float b2, float th, float* A, float* B, float* C, float* F)
+static void radangle2imp(float a2, float b2, float th, float *A, float *B, float *C, float *F)
{
float ct2 = cosf(th);
const float st2 = 1.0f - ct2 * ct2; /* <- sin(th)^2 */
@@ -835,7 +851,7 @@ static void radangle2imp(float a2, float b2, float th, float* A, float* B, float
}
/* all tests here are done to make sure possible overflows are hopefully minimized */
-static void imp2radangle(float A, float B, float C, float F, float* a, float* b, float* th, float* ecc)
+static void imp2radangle(float A, float B, float C, float F, float *a, float *b, float *th, float *ecc)
{
if (F <= 1e-5f) { /* use arbitrary major radius, zero minor, infinite eccentricity */
*a = sqrtf(A > C ? A : C);
@@ -1036,12 +1052,16 @@ static void image_mipmap_test(Tex *tex, ImBuf *ibuf)
IMB_makemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
BLI_unlock_thread(LOCK_IMAGE);
}
+ /* if no mipmap could be made, fall back on non-mipmap render */
+ if (ibuf->mipmap[0] == NULL) {
+ tex->imaflag &= ~TEX_MIPMAP;
+ }
}
}
}
-static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], float dxt[2], float dyt[2], TexResult *texres)
+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)
{
TexResult texr;
float fx, fy, minx, maxx, miny, maxy;
@@ -1072,12 +1092,12 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
if (ima) { /* hack for icon render */
if ((ima->ibufs.first == NULL) && (R.r.scemode & R_NO_IMAGE_LOAD)) return retval;
- ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
+ ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
}
if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
@@ -1088,7 +1108,10 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
/* mipmap test */
image_mipmap_test(tex, ibuf);
- if ((tex->imaflag & TEX_USEALPHA) && ((tex->imaflag & TEX_CALCALPHA) == 0)) texres->talpha = 1;
+ if ((tex->imaflag & TEX_USEALPHA) && tex->ima && (tex->ima->flag & IMA_IGNORE_ALPHA) == 0) {
+ if ((tex->imaflag & TEX_CALCALPHA) == 0)
+ texres->talpha = 1;
+ }
texr.talpha = texres->talpha;
if (tex->imaflag & TEX_IMAROT) {
@@ -1112,10 +1135,10 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
}
/* pixel coordinates */
- minx = MIN3(dxt[0], dyt[0], dxt[0] + dyt[0]);
- maxx = MAX3(dxt[0], dyt[0], dxt[0] + dyt[0]);
- miny = MIN3(dxt[1], dyt[1], dxt[1] + dyt[1]);
- maxy = MAX3(dxt[1], dyt[1], dxt[1] + dyt[1]);
+ minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
+ maxx = max_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
+ miny = min_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
+ maxy = max_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
/* tex_sharper has been removed */
minx = (maxx - minx)*0.5f;
@@ -1194,12 +1217,12 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
else {
if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
fx -= xs;
@@ -1219,14 +1242,14 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
if (tex->extend == TEX_CLIPCUBE) {
if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f || texvec[2] < -1.f || texvec[2] > 1.f) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
else if (tex->extend == TEX_CLIP || tex->extend == TEX_CHECKER) {
if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
@@ -1416,7 +1439,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
}
if (tex->imaflag & TEX_CALCALPHA)
- texres->ta = texres->tin = texres->ta * MAX3(texres->tr, texres->tg, texres->tb);
+ texres->ta = texres->tin = texres->ta * max_fff(texres->tr, texres->tg, texres->tb);
else
texres->tin = texres->ta;
if (tex->flag & TEX_NEGALPHA) texres->ta = 1.f - texres->ta;
@@ -1450,7 +1473,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
}
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
BRICONTRGB;
@@ -1458,7 +1481,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)
+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)
{
TexResult texr;
float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[2], dyt[2];
@@ -1472,7 +1495,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);
+ return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres, pool);
texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f;
@@ -1488,24 +1511,21 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
if (ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD))
return retval;
- ibuf= BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
+ ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
ima->flag|= IMA_USED_FOR_RENDER;
}
if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
/* mipmap test */
image_mipmap_test(tex, ibuf);
- if (tex->imaflag & TEX_USEALPHA) {
- if (tex->imaflag & TEX_CALCALPHA) {
- /* pass */
- }
- else {
+ if ((tex->imaflag & TEX_USEALPHA) && tex->ima && (tex->ima->flag & IMA_IGNORE_ALPHA) == 0) {
+ if ((tex->imaflag & TEX_CALCALPHA) == 0) {
texres->talpha = TRUE;
}
}
@@ -1535,10 +1555,10 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
/* pixel coordinates */
- minx = MIN3(dxt[0], dyt[0], dxt[0] + dyt[0]);
- maxx = MAX3(dxt[0], dyt[0], dxt[0] + dyt[0]);
- miny = MIN3(dxt[1], dyt[1], dxt[1] + dyt[1]);
- maxy = MAX3(dxt[1], dyt[1], dxt[1] + dyt[1]);
+ minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
+ maxx = max_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
+ miny = min_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
+ maxy = max_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
/* tex_sharper has been removed */
minx= (maxx-minx)/2.0f;
@@ -1608,14 +1628,14 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
}
else {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
if ( (tex->flag & TEX_CHECKER_EVEN)==0) {
if ((xs + ys) & 1) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
@@ -1652,14 +1672,14 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
if (tex->extend == TEX_CLIPCUBE) {
if (fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f || texvec[2]<-1.0f || texvec[2]>1.0f) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
else if (tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
if (fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f) {
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
return retval;
}
}
@@ -1826,9 +1846,11 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
}
if (tex->imaflag & TEX_CALCALPHA) {
- texres->ta= texres->tin= texres->ta*MAX3(texres->tr, texres->tg, texres->tb);
+ texres->ta = texres->tin = texres->ta * max_fff(texres->tr, texres->tg, texres->tb);
+ }
+ else {
+ texres->tin = texres->ta;
}
- else texres->tin= texres->ta;
if (tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta;
@@ -1855,17 +1877,17 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
}
if (ima)
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
BRICONTRGB;
return retval;
}
-void image_sample(Image *ima, float fx, float fy, float dx, float dy, float result[4])
+void image_sample(Image *ima, float fx, float fy, float dx, float dy, float result[4], struct ImagePool *pool)
{
TexResult texres;
- ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, NULL, pool);
if (UNLIKELY(ibuf == NULL)) {
zero_v4(result);
@@ -1884,7 +1906,7 @@ void image_sample(Image *ima, float fx, float fy, float dx, float dy, float resu
ima->flag|= IMA_USED_FOR_RENDER;
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, pool);
}
void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float result[4])
diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c
new file mode 100644
index 00000000000..e81359e8fca
--- /dev/null
+++ b/source/blender/render/intern/source/multires_bake.c
@@ -0,0 +1,1298 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 by Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Morten Mikkelsen,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/render/intern/source/multires_bake.c
+ * \ingroup render
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BLI_math.h"
+#include "BLI_listbase.h"
+#include "BLI_threads.h"
+
+#include "BKE_ccg.h"
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_multires.h"
+#include "BKE_modifier.h"
+#include "BKE_subsurf.h"
+
+#include "RE_multires_bake.h"
+#include "RE_pipeline.h"
+#include "RE_shader_ext.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "rayintersection.h"
+#include "rayobject.h"
+#include "rendercore.h"
+
+typedef void (*MPassKnownData)(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *thread_data,
+ void *bake_data, ImBuf *ibuf, const int face_index, const int lvl,
+ const float st[2], float tangmat[3][3], const int x, const int y);
+
+typedef void * (*MInitBakeData)(MultiresBakeRender *bkr, Image *ima);
+typedef void (*MFreeBakeData)(void *bake_data);
+
+typedef struct MultiresBakeResult {
+ float height_min, height_max;
+} MultiresBakeResult;
+
+typedef struct {
+ MVert *mvert;
+ MFace *mface;
+ MTFace *mtface;
+ float *pvtangent;
+ float *precomputed_normals;
+ int w, h;
+ int face_index;
+ int i0, i1, i2;
+ DerivedMesh *lores_dm, *hires_dm;
+ int lvl;
+ void *thread_data;
+ void *bake_data;
+ ImBuf *ibuf;
+ MPassKnownData pass_data;
+} MResolvePixelData;
+
+typedef void (*MFlushPixel)(const MResolvePixelData *data, const int x, const int y);
+
+typedef struct {
+ int w, h;
+ char *texels;
+ const MResolvePixelData *data;
+ MFlushPixel flush_pixel;
+} MBakeRast;
+
+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;
+
+typedef struct {
+ int number_of_rays;
+ float bias;
+
+ unsigned short *permutation_table_1;
+ unsigned short *permutation_table_2;
+
+ 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)
+{
+ 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);
+
+ if (!smoothnormal) { /* flat */
+ if (data->precomputed_normals) {
+ copy_v3_v3(norm, &data->precomputed_normals[3 * face_num]);
+ }
+ else {
+ float nor[3];
+ 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) {
+ 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);
+ }
+ }
+ else {
+ short *no = data->mvert[indices[vert_index]].no;
+
+ normal_short_to_float_v3(norm, no);
+ normalize_v3(norm);
+ }
+}
+
+static void init_bake_rast(MBakeRast *bake_rast, const ImBuf *ibuf, const MResolvePixelData *data, MFlushPixel flush_pixel)
+{
+ BakeImBufuserData *userdata = (BakeImBufuserData *) ibuf->userdata;
+
+ memset(bake_rast, 0, sizeof(MBakeRast));
+
+ bake_rast->texels = userdata->mask_buffer;
+ bake_rast->w = ibuf->x;
+ bake_rast->h = ibuf->y;
+ bake_rast->data = data;
+ bake_rast->flush_pixel = flush_pixel;
+}
+
+static void flush_pixel(const MResolvePixelData *data, const int x, const int y)
+{
+ float st[2] = {(x + 0.5f) / data->w, (y + 0.5f) / data->h};
+ float *st0, *st1, *st2;
+ float *tang0, *tang1, *tang2;
+ float no0[3], no1[3], no2[3];
+ float fUV[2], from_tang[3][3], to_tang[3][3];
+ float u, v, w, sign;
+ int r;
+
+ const int i0 = data->i0;
+ const int i1 = data->i1;
+ const int i2 = data->i2;
+
+ 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);
+
+ resolve_tri_uv(fUV, st, st0, st1, st2);
+
+ u = fUV[0];
+ v = fUV[1];
+ 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;
+
+ /* the sign is the same at all face vertices for any non degenerate face.
+ * Just in case we clamp the interpolated value though. */
+ sign = (tang0[3] * u + tang1[3] * v + tang2[3] * w) < 0 ? (-1.0f) : 1.0f;
+
+ /* this sequence of math is designed specifically as is with great care
+ * to be compatible with our shader. Please don't change without good reason. */
+ for (r = 0; r < 3; r++) {
+ from_tang[0][r] = tang0[r] * u + tang1[r] * v + tang2[r] * w;
+ from_tang[2][r] = no0[r] * u + no1[r] * v + no2[r] * w;
+ }
+
+ cross_v3_v3v3(from_tang[1], from_tang[2], from_tang[0]); /* B = sign * cross(N, T) */
+ mul_v3_fl(from_tang[1], sign);
+ invert_m3_m3(to_tang, from_tang);
+ }
+ else {
+ zero_m3(to_tang);
+ }
+
+ 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);
+}
+
+static void set_rast_triangle(const MBakeRast *bake_rast, const int x, const int y)
+{
+ const int w = bake_rast->w;
+ const int h = bake_rast->h;
+
+ if (x >= 0 && x < w && y >= 0 && y < h) {
+ if ((bake_rast->texels[y * w + x]) == 0) {
+ bake_rast->texels[y * w + x] = FILTER_MASK_USED;
+ flush_pixel(bake_rast->data, x, y);
+ }
+ }
+}
+
+static void rasterize_half(const MBakeRast *bake_rast,
+ const float s0_s, const float t0_s, const float s1_s, const float t1_s,
+ const float s0_l, const float t0_l, const float s1_l, const float t1_l,
+ const int y0_in, const int y1_in, const int is_mid_right)
+{
+ const int s_stable = fabsf(t1_s - t0_s) > FLT_EPSILON ? 1 : 0;
+ const int l_stable = fabsf(t1_l - t0_l) > FLT_EPSILON ? 1 : 0;
+ const int w = bake_rast->w;
+ const int h = bake_rast->h;
+ int y, y0, y1;
+
+ if (y1_in <= 0 || y0_in >= h)
+ return;
+
+ y0 = y0_in < 0 ? 0 : y0_in;
+ y1 = y1_in >= h ? h : y1_in;
+
+ for (y = y0; y < y1; y++) {
+ /*-b(x-x0) + a(y-y0) = 0 */
+ int iXl, iXr, x;
+ float x_l = s_stable != 0 ? (s0_s + (((s1_s - s0_s) * (y - t0_s)) / (t1_s - t0_s))) : s0_s;
+ float x_r = l_stable != 0 ? (s0_l + (((s1_l - s0_l) * (y - t0_l)) / (t1_l - t0_l))) : s0_l;
+
+ if (is_mid_right != 0)
+ SWAP(float, x_l, x_r);
+
+ iXl = (int)ceilf(x_l);
+ iXr = (int)ceilf(x_r);
+
+ if (iXr > 0 && iXl < w) {
+ iXl = iXl < 0 ? 0 : iXl;
+ iXr = iXr >= w ? w : iXr;
+
+ for (x = iXl; x < iXr; x++)
+ set_rast_triangle(bake_rast, x, y);
+ }
+ }
+}
+
+static void bake_rasterize(const MBakeRast *bake_rast, const float st0_in[2], const float st1_in[2], const float st2_in[2])
+{
+ const int w = bake_rast->w;
+ const int h = bake_rast->h;
+ float slo = st0_in[0] * w - 0.5f;
+ float tlo = st0_in[1] * h - 0.5f;
+ float smi = st1_in[0] * w - 0.5f;
+ float tmi = st1_in[1] * h - 0.5f;
+ float shi = st2_in[0] * w - 0.5f;
+ float thi = st2_in[1] * h - 0.5f;
+ int is_mid_right = 0, ylo, yhi, yhi_beg;
+
+ /* skip degenerates */
+ if ((slo == smi && tlo == tmi) || (slo == shi && tlo == thi) || (smi == shi && tmi == thi))
+ return;
+
+ /* sort by T */
+ if (tlo > tmi && tlo > thi) {
+ SWAP(float, shi, slo);
+ SWAP(float, thi, tlo);
+ }
+ else if (tmi > thi) {
+ SWAP(float, shi, smi);
+ SWAP(float, thi, tmi);
+ }
+
+ if (tlo > tmi) {
+ SWAP(float, slo, smi);
+ SWAP(float, tlo, tmi);
+ }
+
+ /* check if mid point is to the left or to the right of the lo-hi edge */
+ is_mid_right = (-(shi - slo) * (tmi - thi) + (thi - tlo) * (smi - shi)) > 0 ? 1 : 0;
+ ylo = (int) ceilf(tlo);
+ yhi_beg = (int) ceilf(tmi);
+ yhi = (int) ceilf(thi);
+
+ /*if (fTmi>ceilf(fTlo))*/
+ rasterize_half(bake_rast, slo, tlo, smi, tmi, slo, tlo, shi, thi, ylo, yhi_beg, is_mid_right);
+ rasterize_half(bake_rast, smi, tmi, shi, thi, slo, tlo, shi, thi, yhi_beg, yhi, is_mid_right);
+}
+
+static int multiresbake_test_break(MultiresBakeRender *bkr)
+{
+ if (!bkr->stop) {
+ /* this means baker is executed outside from job system */
+ return 0;
+ }
+
+ return *bkr->stop || G.is_break;
+}
+
+/* **** Threading routines **** */
+
+typedef struct MultiresBakeQueue {
+ int cur_face;
+ int tot_face;
+ SpinLock spin;
+} MultiresBakeQueue;
+
+typedef struct MultiresBakeThread {
+ /* this data is actually shared between all the threads */
+ MultiresBakeQueue *queue;
+ MultiresBakeRender *bkr;
+ Image *image;
+ void *bake_data;
+
+ /* thread-specific data */
+ MBakeRast bake_rast;
+ MResolvePixelData data;
+
+ /* displacement-specific data */
+ float height_min, height_max;
+} MultiresBakeThread;
+
+static int multires_bake_queue_next_face(MultiresBakeQueue *queue)
+{
+ int face = -1;
+
+ /* TODO: it could worth making it so thread will handle neighbor faces
+ * for better memory cache utilization
+ */
+
+ BLI_spin_lock(&queue->spin);
+ if (queue->cur_face < queue->tot_face) {
+ face = queue->cur_face;
+ queue->cur_face++;
+ }
+ BLI_spin_unlock(&queue->spin);
+
+ return face;
+}
+
+static void *do_multires_bake_thread(void *data_v)
+{
+ MultiresBakeThread *handle = (MultiresBakeThread *) data_v;
+ MResolvePixelData *data = &handle->data;
+ MBakeRast *bake_rast = &handle->bake_rast;
+ MultiresBakeRender *bkr = handle->bkr;
+ int f;
+
+ while ((f = multires_bake_queue_next_face(handle->queue)) >= 0) {
+ MTFace *mtfate = &data->mtface[f];
+ int verts[3][2], nr_tris, t;
+
+ if (multiresbake_test_break(bkr))
+ break;
+
+ if (mtfate->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;
+
+ verts[0][1] = 0;
+ verts[1][1] = 2;
+ verts[2][1] = 3;
+
+ 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];
+
+ 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;
+ }
+
+ /* update progress */
+ BLI_spin_lock(&handle->queue->spin);
+ bkr->baked_faces++;
+
+ if (bkr->do_update)
+ *bkr->do_update = TRUE;
+
+ if (bkr->progress)
+ *bkr->progress = ((float)bkr->baked_objects + (float)bkr->baked_faces / handle->queue->tot_face) / bkr->tot_obj;
+ BLI_spin_unlock(&handle->queue->spin);
+ }
+
+ return NULL;
+}
+
+/* some of arrays inside ccgdm are lazy-initialized, which will generally
+ * require lock around accessing such data
+ * this function will ensure all arrays are allocated before threading started
+ */
+static void init_ccgdm_arrays(DerivedMesh *dm)
+{
+ CCGElem **grid_data;
+ CCGKey key;
+ int grid_size;
+ int *grid_offset;
+
+ grid_size = dm->getGridSize(dm);
+ grid_data = dm->getGridData(dm);
+ grid_offset = dm->getGridOffset(dm);
+ dm->getGridKey(dm, &key);
+
+ (void) grid_size;
+ (void) grid_data;
+ (void) grid_offset;
+}
+
+static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, int require_tangent, MPassKnownData passKnownData,
+ MInitBakeData initBakeData, MFreeBakeData freeBakeData, MultiresBakeResult *result)
+{
+ DerivedMesh *dm = bkr->lores_dm;
+ const int lvl = bkr->lvl;
+ const int tot_face = dm->getNumTessFaces(dm);
+
+ if (tot_face > 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);
+ float *precomputed_normals = dm->getTessFaceDataArray(dm, CD_NORMAL);
+ float *pvtangent = NULL;
+
+ ListBase threads;
+ int i, tot_thread = bkr->threads > 0 ? bkr->threads : BLI_system_thread_count();
+
+ void *bake_data = NULL;
+
+ if (require_tangent) {
+ if (CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1)
+ DM_add_tangent_layer(dm);
+
+ pvtangent = DM_get_tessface_data_layer(dm, CD_TANGENT);
+ }
+
+ /* all threads shares the same custom bake data */
+ if (initBakeData)
+ bake_data = initBakeData(bkr, ima);
+
+ if (tot_thread > 1)
+ BLI_init_threads(&threads, do_multires_bake_thread, tot_thread);
+
+ handles = MEM_callocN(tot_thread * sizeof(MultiresBakeThread), "do_multires_bake handles");
+
+ init_ccgdm_arrays(bkr->hires_dm);
+
+ /* faces queue */
+ queue.cur_face = 0;
+ queue.tot_face = tot_face;
+ BLI_spin_init(&queue.spin);
+
+ /* fill in threads handles */
+ for (i = 0; i < tot_thread; i++) {
+ MultiresBakeThread *handle = &handles[i];
+
+ handle->bkr = bkr;
+ handle->image = ima;
+ handle->queue = &queue;
+
+ handle->data.mface = mface;
+ handle->data.mvert = mvert;
+ handle->data.mtface = mtface;
+ handle->data.pvtangent = pvtangent;
+ handle->data.precomputed_normals = precomputed_normals; /* don't strictly need this */
+ handle->data.w = ibuf->x;
+ handle->data.h = ibuf->y;
+ handle->data.lores_dm = dm;
+ handle->data.hires_dm = bkr->hires_dm;
+ handle->data.lvl = lvl;
+ handle->data.pass_data = passKnownData;
+ handle->data.thread_data = handle;
+ handle->data.bake_data = bake_data;
+ handle->data.ibuf = ibuf;
+
+ handle->height_min = FLT_MAX;
+ handle->height_max = -FLT_MAX;
+
+ init_bake_rast(&handle->bake_rast, ibuf, &handle->data, flush_pixel);
+
+ if (tot_thread > 1)
+ BLI_insert_thread(&threads, handle);
+ }
+
+ /* run threads */
+ if (tot_thread > 1)
+ BLI_end_threads(&threads);
+ else
+ do_multires_bake_thread(&handles[0]);
+
+ /* construct bake result */
+ result->height_min = handles[0].height_min;
+ result->height_max = handles[0].height_max;
+
+ for (i = 1; i < tot_thread; i++) {
+ result->height_min = min_ff(result->height_min, handles[i].height_min);
+ result->height_max = max_ff(result->height_max, handles[i].height_max);
+ }
+
+ BLI_spin_end(&queue.spin);
+
+ /* finalize baking */
+ if (freeBakeData)
+ freeBakeData(bake_data);
+
+ MEM_freeN(handles);
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+}
+
+/* mode = 0: interpolate normals,
+ * mode = 1: interpolate coord */
+static void interp_bilinear_grid(CCGKey *key, CCGElem *grid, float crn_x, float crn_y, int mode, float res[3])
+{
+ int x0, x1, y0, y1;
+ float u, v;
+ float data[4][3];
+
+ x0 = (int) crn_x;
+ x1 = x0 >= (key->grid_size - 1) ? (key->grid_size - 1) : (x0 + 1);
+
+ y0 = (int) crn_y;
+ y1 = y0 >= (key->grid_size - 1) ? (key->grid_size - 1) : (y0 + 1);
+
+ u = crn_x - x0;
+ v = crn_y - y0;
+
+ if (mode == 0) {
+ copy_v3_v3(data[0], CCG_grid_elem_no(key, grid, x0, y0));
+ copy_v3_v3(data[1], CCG_grid_elem_no(key, grid, x1, y0));
+ copy_v3_v3(data[2], CCG_grid_elem_no(key, grid, x1, y1));
+ copy_v3_v3(data[3], CCG_grid_elem_no(key, grid, x0, y1));
+ }
+ else {
+ copy_v3_v3(data[0], CCG_grid_elem_co(key, grid, x0, y0));
+ copy_v3_v3(data[1], CCG_grid_elem_co(key, grid, x1, y0));
+ copy_v3_v3(data[2], CCG_grid_elem_co(key, grid, x1, y1));
+ copy_v3_v3(data[3], CCG_grid_elem_co(key, grid, x0, y1));
+ }
+
+ interp_bilinear_quad_v3(data, u, v, res);
+}
+
+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])
+{
+ 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);
+
+ 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);
+ }
+ 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];
+
+ crn_y = (row * cell_side) + u * cell_side;
+ crn_x = (col * cell_side) + v * cell_side;
+ }
+
+ CLAMP(crn_x, 0.0f, grid_size);
+ CLAMP(crn_y, 0.0f, grid_size);
+
+ if (n != NULL)
+ interp_bilinear_grid(&key, grid_data[g_index + S], crn_x, crn_y, 0, n);
+
+ if (co != NULL)
+ interp_bilinear_grid(&key, grid_data[g_index + S], crn_x, crn_y, 1, co);
+}
+
+/* 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])
+{
+ 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]);
+ }
+ 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]);
+ }
+
+ 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])
+{
+ 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]);
+ }
+ else {
+ dm->getVertCo(dm, mface->v1, data[0]);
+ dm->getVertCo(dm, mface->v2, data[1]);
+ dm->getVertCo(dm, mface->v3, data[2]);
+ }
+
+ interp_barycentric_tri_v3(data, u, v, res);
+}
+
+/* **************** Displacement Baker **************** */
+
+static void *init_heights_data(MultiresBakeRender *bkr, Image *ima)
+{
+ MHeightBakeData *height_data;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ DerivedMesh *lodm = bkr->lores_dm;
+ BakeImBufuserData *userdata = ibuf->userdata;
+
+ if (userdata->displacement_buffer == NULL)
+ userdata->displacement_buffer = MEM_callocN(sizeof(float) * ibuf->x * ibuf->y, "MultiresBake heights");
+
+ height_data = MEM_callocN(sizeof(MHeightBakeData), "MultiresBake heightData");
+
+ height_data->ima = ima;
+ height_data->heights = userdata->displacement_buffer;
+
+ if (!bkr->use_lores_mesh) {
+ SubsurfModifierData smd = {{NULL}};
+ int ss_lvl = bkr->tot_lvl - bkr->lvl;
+
+ CLAMP(ss_lvl, 0, 6);
+
+ if (ss_lvl > 0) {
+ smd.levels = smd.renderLevels = ss_lvl;
+ smd.flags |= eSubsurfModifierFlag_SubsurfUv;
+
+ if (bkr->simple)
+ smd.subdivType = ME_SIMPLE_SUBSURF;
+
+ height_data->ssdm = subsurf_make_derived_from_derived(bkr->lores_dm, &smd, NULL, 0);
+ init_ccgdm_arrays(height_data->ssdm);
+ }
+ }
+
+ 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);
+
+ return (void *)height_data;
+}
+
+static void free_heights_data(void *bake_data)
+{
+ MHeightBakeData *height_data = (MHeightBakeData *)bake_data;
+
+ if (height_data->ssdm)
+ height_data->ssdm->release(height_data->ssdm);
+
+ MEM_freeN(height_data);
+}
+
+/* MultiresBake callback for heights baking
+ * general idea:
+ * - find coord of point with specified UV in hi-res mesh (let's call it p1)
+ * - find coord of point and normal with specified UV in lo-res mesh (or subdivided lo-res
+ * 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],
+ float UNUSED(tangmat[3][3]), const int x, const int y)
+{
+ MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
+ MFace mface;
+ 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];
+ resolve_quad_uv(uv, st, st0, st1, st2, st3);
+ }
+ else
+ resolve_tri_uv(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, 0);
+
+ 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);
+ }
+ 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);
+ }
+ 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);
+ }
+ }
+
+ sub_v3_v3v3(vec, p1, p0);
+ len = dot_v3v3(n, vec);
+
+ height_data->heights[pixel] = len;
+
+ thread_data->height_min = min_ff(thread_data->height_min, len);
+ thread_data->height_max = max_ff(thread_data->height_max, len);
+
+ if (ibuf->rect_float) {
+ float *rrgbf = ibuf->rect_float + pixel * 4;
+ rrgbf[0] = rrgbf[1] = rrgbf[2] = len;
+ rrgbf[3] = 1.0f;
+ }
+ else {
+ char *rrgb = (char *)ibuf->rect + pixel * 4;
+ rrgb[0] = rrgb[1] = rrgb[2] = FTOCHAR(len);
+ rrgb[3] = 255;
+ }
+}
+
+/* **************** Normal Maps Baker **************** */
+
+static void *init_normal_data(MultiresBakeRender *bkr, Image *UNUSED(ima))
+{
+ MNormalBakeData *normal_data;
+ DerivedMesh *lodm = bkr->lores_dm;
+
+ 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;
+}
+
+static void free_normal_data(void *bake_data)
+{
+ MNormalBakeData *normal_data = (MNormalBakeData *)bake_data;
+
+ MEM_freeN(normal_data);
+}
+
+/* MultiresBake callback for normals' baking
+ * general idea:
+ * - find coord and normal of point with specified UV in hi-res mesh
+ * - 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,
+ 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;
+ 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];
+ resolve_quad_uv(uv, st, st0, st1, st2, st3);
+ }
+ else
+ resolve_tri_uv(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);
+
+ mul_v3_m3v3(vec, tangmat, n);
+ normalize_v3(vec);
+ mul_v3_fl(vec, 0.5);
+ add_v3_v3(vec, tmp);
+
+ if (ibuf->rect_float) {
+ float *rrgbf = ibuf->rect_float + pixel * 4;
+ rrgbf[0] = vec[0];
+ rrgbf[1] = vec[1];
+ rrgbf[2] = vec[2];
+ rrgbf[3] = 1.0f;
+ }
+ else {
+ unsigned char *rrgb = (unsigned char *)ibuf->rect + pixel * 4;
+ rgb_float_to_uchar(rrgb, vec);
+ rrgb[3] = 255;
+ }
+}
+
+/* **************** Ambient Occlusion Baker **************** */
+
+// must be a power of two
+#define MAX_NUMBER_OF_AO_RAYS 1024
+
+static unsigned short ao_random_table_1[MAX_NUMBER_OF_AO_RAYS];
+static unsigned short ao_random_table_2[MAX_NUMBER_OF_AO_RAYS];
+
+static void init_ao_random(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_NUMBER_OF_AO_RAYS; i++) {
+ ao_random_table_1[i] = rand() & 0xffff;
+ ao_random_table_2[i] = rand() & 0xffff;
+ }
+}
+
+static unsigned short get_ao_random1(const int i)
+{
+ return ao_random_table_1[i & (MAX_NUMBER_OF_AO_RAYS - 1)];
+}
+
+static unsigned short get_ao_random2(const int i)
+{
+ return ao_random_table_2[i & (MAX_NUMBER_OF_AO_RAYS - 1)];
+}
+
+static void build_permutation_table(unsigned short permutation[], unsigned short temp_permutation[],
+ const int number_of_rays, const int is_first_perm_table)
+{
+ int i, k;
+
+ for (i = 0; i < number_of_rays; i++)
+ temp_permutation[i] = i;
+
+ for (i = 0; i < number_of_rays; i++) {
+ const unsigned int nr_entries_left = number_of_rays - i;
+ unsigned short rnd = is_first_perm_table != FALSE ? get_ao_random1(i) : get_ao_random2(i);
+ const unsigned short entry = rnd % nr_entries_left;
+
+ /* pull entry */
+ permutation[i] = temp_permutation[entry];
+
+ /* delete entry */
+ for (k = entry; k < nr_entries_left - 1; k++) {
+ temp_permutation[k] = temp_permutation[k + 1];
+ }
+ }
+
+ /* verify permutation table
+ * every entry must appear exactly once
+ */
+#if 0
+ for (i = 0; i < number_of_rays; i++) temp_permutation[i] = 0;
+ for (i = 0; i < number_of_rays; i++) ++temp_permutation[permutation[i]];
+ for (i = 0; i < number_of_rays; i++) BLI_assert(temp_permutation[i] == 1);
+#endif
+}
+
+static void create_ao_raytree(MultiresBakeRender *bkr, MAOBakeData *ao_data)
+{
+ DerivedMesh *hidm = bkr->hires_dm;
+ RayObject *raytree;
+ RayFace *face;
+ CCGElem **grid_data;
+ CCGKey key;
+ int num_grids, grid_size /*, face_side */, num_faces;
+ int i;
+
+ num_grids = hidm->getNumGrids(hidm);
+ grid_size = hidm->getGridSize(hidm);
+ grid_data = hidm->getGridData(hidm);
+ hidm->getGridKey(hidm, &key);
+
+ /* face_side = (grid_size << 1) - 1; */ /* UNUSED */
+ num_faces = num_grids * (grid_size - 1) * (grid_size - 1);
+
+ raytree = ao_data->raytree = RE_rayobject_create(bkr->raytrace_structure, num_faces, bkr->octree_resolution);
+ face = ao_data->rayfaces = (RayFace *) MEM_callocN(num_faces * sizeof(RayFace), "ObjectRen faces");
+
+ for (i = 0; i < num_grids; i++) {
+ int x, y;
+ for (x = 0; x < grid_size - 1; x++) {
+ for (y = 0; y < grid_size - 1; y++) {
+ float co[4][3];
+
+ copy_v3_v3(co[0], CCG_grid_elem_co(&key, grid_data[i], x, y));
+ copy_v3_v3(co[1], CCG_grid_elem_co(&key, grid_data[i], x, y + 1));
+ copy_v3_v3(co[2], CCG_grid_elem_co(&key, grid_data[i], x + 1, y + 1));
+ copy_v3_v3(co[3], CCG_grid_elem_co(&key, grid_data[i], x + 1, y));
+
+ RE_rayface_from_coords(face, ao_data, face, co[0], co[1], co[2], co[3]);
+ RE_rayobject_add(raytree, RE_rayobject_unalignRayFace(face));
+
+ face++;
+ }
+ }
+ }
+
+ RE_rayobject_done(raytree);
+}
+
+static void *init_ao_data(MultiresBakeRender *bkr, Image *UNUSED(ima))
+{
+ MAOBakeData *ao_data;
+ DerivedMesh *lodm = bkr->lores_dm;
+ unsigned short *temp_permutation_table;
+ size_t permutation_size;
+
+ init_ao_random();
+
+ ao_data = MEM_callocN(sizeof(MAOBakeData), "MultiresBake aoData");
+
+ 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);
+
+ /* initialize permutation tables */
+ permutation_size = sizeof(unsigned short) * bkr->number_of_rays;
+ ao_data->permutation_table_1 = MEM_callocN(permutation_size, "multires AO baker perm1");
+ ao_data->permutation_table_2 = MEM_callocN(permutation_size, "multires AO baker perm2");
+ temp_permutation_table = MEM_callocN(permutation_size, "multires AO baker temp perm");
+
+ build_permutation_table(ao_data->permutation_table_1, temp_permutation_table, bkr->number_of_rays, 1);
+ build_permutation_table(ao_data->permutation_table_2, temp_permutation_table, bkr->number_of_rays, 0);
+
+ MEM_freeN(temp_permutation_table);
+
+ return (void *)ao_data;
+}
+
+static void free_ao_data(void *bake_data)
+{
+ MAOBakeData *ao_data = (MAOBakeData *) bake_data;
+
+ RE_rayobject_free(ao_data->raytree);
+ MEM_freeN(ao_data->rayfaces);
+
+ MEM_freeN(ao_data->permutation_table_1);
+ MEM_freeN(ao_data->permutation_table_2);
+
+ MEM_freeN(ao_data);
+}
+
+/* builds an X and a Y axis from the given Z axis */
+static void build_coordinate_frame(float axisX[3], float axisY[3], const float axisZ[3])
+{
+ const float faX = fabsf(axisZ[0]);
+ const float faY = fabsf(axisZ[1]);
+ const float faZ = fabsf(axisZ[2]);
+
+ if (faX <= faY && faX <= faZ) {
+ const float len = sqrtf(axisZ[1] * axisZ[1] + axisZ[2] * axisZ[2]);
+ axisY[0] = 0; axisY[1] = axisZ[2] / len; axisY[2] = -axisZ[1] / len;
+ cross_v3_v3v3(axisX, axisY, axisZ);
+ }
+ else if (faY <= faZ) {
+ const float len = sqrtf(axisZ[0] * axisZ[0] + axisZ[2] * axisZ[2]);
+ axisX[0] = axisZ[2] / len; axisX[1] = 0; axisX[2] = -axisZ[0] / len;
+ cross_v3_v3v3(axisY, axisZ, axisX);
+ }
+ else {
+ const float len = sqrtf(axisZ[0] * axisZ[0] + axisZ[1] * axisZ[1]);
+ axisX[0] = axisZ[1] / len; axisX[1] = -axisZ[0] / len; axisX[2] = 0;
+ cross_v3_v3v3(axisY, axisZ, axisX);
+ }
+}
+
+/* return FALSE if nothing was hit and TRUE otherwise */
+static int trace_ao_ray(MAOBakeData *ao_data, float ray_start[3], float ray_direction[3])
+{
+ Isect isect = {{0}};
+
+ isect.dist = RE_RAYTRACE_MAXDIST;
+ copy_v3_v3(isect.start, ray_start);
+ copy_v3_v3(isect.dir, ray_direction);
+ isect.lay = -1;
+
+ normalize_v3(isect.dir);
+
+ return RE_rayobject_raycast(ao_data->raytree, &isect);
+}
+
+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,
+ const float st[2], float UNUSED(tangmat[3][3]), const int x, const int y)
+{
+ 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];
+ float cen[3];
+ float axisX[3], axisY[3], axisZ[3];
+ float shadow = 0;
+ float value;
+ 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];
+ resolve_quad_uv(uv, st, st0, st1, st2, st3);
+ }
+ else
+ resolve_tri_uv(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);
+
+ /* offset ray origin by user bias along normal */
+ for (i = 0; i < 3; i++)
+ cen[i] = pos[i] + ao_data->bias * nrm[i];
+
+ /* build tangent frame */
+ for (i = 0; i < 3; i++)
+ axisZ[i] = nrm[i];
+
+ build_coordinate_frame(axisX, axisY, axisZ);
+
+ /* static noise */
+ perm_offs = (get_ao_random2(get_ao_random1(x) + y)) & (MAX_NUMBER_OF_AO_RAYS - 1);
+
+ /* importance sample shadow rays (cosine weighted) */
+ for (i = 0; i < ao_data->number_of_rays; i++) {
+ int hit_something;
+
+ /* use N-Rooks to distribute our N ray samples across
+ * a multi-dimensional domain (2D)
+ */
+ const unsigned short I = ao_data->permutation_table_1[(i + perm_offs) % ao_data->number_of_rays];
+ const unsigned short J = ao_data->permutation_table_2[i];
+
+ const float JitPh = (get_ao_random2(I + perm_offs) & (MAX_NUMBER_OF_AO_RAYS-1))/((float) MAX_NUMBER_OF_AO_RAYS);
+ const float JitTh = (get_ao_random1(J + perm_offs) & (MAX_NUMBER_OF_AO_RAYS-1))/((float) MAX_NUMBER_OF_AO_RAYS);
+ const float SiSqPhi = (I + JitPh) / ao_data->number_of_rays;
+ const float Theta = (float)(2 * M_PI) * ((J + JitTh) / ao_data->number_of_rays);
+
+ /* this gives results identical to the so-called cosine
+ * weighted distribution relative to the north pole.
+ */
+ float SiPhi = sqrt(SiSqPhi);
+ float CoPhi = SiSqPhi < 1.0f ? sqrtf(1.0f - SiSqPhi) : 0;
+ float CoThe = cos(Theta);
+ float SiThe = sin(Theta);
+
+ const float dx = CoThe * CoPhi;
+ const float dy = SiThe * CoPhi;
+ const float dz = SiPhi;
+
+ /* transform ray direction out of tangent frame */
+ float dv[3];
+ for (k = 0; k < 3; k++)
+ dv[k] = axisX[k] * dx + axisY[k] * dy + axisZ[k] * dz;
+
+ hit_something = trace_ao_ray(ao_data, cen, dv);
+
+ if (hit_something != 0)
+ shadow += 1;
+ }
+
+ value = 1.0f - (shadow / ao_data->number_of_rays);
+
+ if (ibuf->rect_float) {
+ float *rrgbf = ibuf->rect_float + pixel * 4;
+ rrgbf[0] = rrgbf[1] = rrgbf[2] = value;
+ rrgbf[3] = 1.0f;
+ }
+ else {
+ unsigned char *rrgb = (unsigned char *) ibuf->rect + pixel * 4;
+ rrgb[0] = rrgb[1] = rrgb[2] = FTOCHAR(value);
+ rrgb[3] = 255;
+ }
+}
+
+/* **************** Common functions public API relates on **************** */
+
+static void count_images(MultiresBakeRender *bkr)
+{
+ int a, totface;
+ DerivedMesh *dm = bkr->lores_dm;
+ MTFace *mtface = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+
+ bkr->image.first = bkr->image.last = NULL;
+ bkr->tot_image = 0;
+
+ totface = dm->getNumTessFaces(dm);
+
+ for (a = 0; a < totface; a++)
+ mtface[a].tpage->id.flag &= ~LIB_DOIT;
+
+ for (a = 0; a < totface; a++) {
+ Image *ima = mtface[a].tpage;
+ if ((ima->id.flag & LIB_DOIT) == 0) {
+ LinkData *data = BLI_genericNodeN(ima);
+ BLI_addtail(&bkr->image, data);
+ bkr->tot_image++;
+ ima->id.flag |= LIB_DOIT;
+ }
+ }
+
+ for (a = 0; a < totface; a++)
+ mtface[a].tpage->id.flag &= ~LIB_DOIT;
+}
+
+static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
+{
+ LinkData *link;
+
+ for (link = bkr->image.first; link; link = link->next) {
+ Image *ima = (Image *)link->data;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+
+ if (ibuf->x > 0 && ibuf->y > 0) {
+ BakeImBufuserData *userdata = MEM_callocN(sizeof(BakeImBufuserData), "MultiresBake userdata");
+ userdata->mask_buffer = MEM_callocN(ibuf->y * ibuf->x, "MultiresBake imbuf mask");
+ ibuf->userdata = userdata;
+
+ switch (bkr->mode) {
+ case RE_BAKE_NORMALS:
+ do_multires_bake(bkr, ima, TRUE, apply_tangmat_callback, init_normal_data, free_normal_data, result);
+ break;
+ case RE_BAKE_DISPLACEMENT:
+ do_multires_bake(bkr, ima, FALSE, apply_heights_callback, init_heights_data, free_heights_data, result);
+ break;
+ case RE_BAKE_AO:
+ do_multires_bake(bkr, ima, FALSE, apply_ao_callback, init_ao_data, free_ao_data, result);
+ break;
+ }
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+
+ ima->id.flag |= LIB_DOIT;
+ }
+}
+
+static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
+{
+ LinkData *link;
+ int use_displacement_buffer = bkr->mode == RE_BAKE_DISPLACEMENT;
+
+ for (link = bkr->image.first; link; link = link->next) {
+ Image *ima = (Image *)link->data;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ BakeImBufuserData *userdata = (BakeImBufuserData *) ibuf->userdata;
+
+ if (ibuf->x <= 0 || ibuf->y <= 0)
+ continue;
+
+ if (use_displacement_buffer) {
+ RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer,
+ result->height_min, result->height_max);
+ }
+
+ RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, bkr->bake_filter);
+
+ ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID;
+
+ if (ibuf->rect_float)
+ ibuf->userflags |= IB_RECT_INVALID;
+
+ if (ibuf->mipmap[0]) {
+ ibuf->userflags |= IB_MIPMAP_INVALID;
+ imb_freemipmapImBuf(ibuf);
+ }
+
+ if (ibuf->userdata) {
+ if (userdata->displacement_buffer)
+ MEM_freeN(userdata->displacement_buffer);
+
+ MEM_freeN(userdata->mask_buffer);
+ MEM_freeN(userdata);
+ ibuf->userdata = NULL;
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+}
+
+void RE_multires_bake_images(MultiresBakeRender *bkr)
+{
+ MultiresBakeResult result;
+
+ count_images(bkr);
+ bake_images(bkr, &result);
+ finish_images(bkr, &result);
+}
diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c
index a7308821843..50f9d6caff6 100644
--- a/source/blender/render/intern/source/occlusion.c
+++ b/source/blender/render/intern/source/occlusion.c
@@ -44,6 +44,8 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "BKE_global.h"
#include "BKE_scene.h"
@@ -763,414 +765,6 @@ static float occ_solid_angle(OccNode *node, const float v[3], float d2, float in
return ((node->area * dotemit * dotreceive) / (d2 + node->area * INVPI)) * INVPI;
}
-static void vec_add_dir(float r[3], const float v1[3], const float v2[3], const float fac)
-{
- r[0] = v1[0] + fac * (v2[0] - v1[0]);
- r[1] = v1[1] + fac * (v2[1] - v1[1]);
- r[2] = v1[2] + fac * (v2[2] - v1[2]);
-}
-
-/* TODO: exact duplicate of ff_visible_quad() in math_geom.c
- * why not de-duplicate? (also above helper func) */
-static int occ_visible_quad(const float p[3], const float n[3],
- const float v0[3], const float v1[3], const float v2[3],
- float q0[3], float q1[3], float q2[3], float q3[3])
-{
- static const float epsilon = 1e-6f;
- float c, sd[3];
-
- c = dot_v3v3(n, p);
-
- /* signed distances from the vertices to the plane. */
- sd[0] = dot_v3v3(n, v0) - c;
- sd[1] = dot_v3v3(n, v1) - c;
- sd[2] = dot_v3v3(n, v2) - c;
-
- if (fabsf(sd[0]) < epsilon) sd[0] = 0.0f;
- if (fabsf(sd[1]) < epsilon) sd[1] = 0.0f;
- if (fabsf(sd[2]) < epsilon) sd[2] = 0.0f;
-
- if (sd[0] > 0) {
- if (sd[1] > 0) {
- if (sd[2] > 0) {
- /* +++ */
- copy_v3_v3(q0, v0);
- copy_v3_v3(q1, v1);
- copy_v3_v3(q2, v2);
- copy_v3_v3(q3, q2);
- }
- else if (sd[2] < 0) {
- /* ++- */
- copy_v3_v3(q0, v0);
- copy_v3_v3(q1, v1);
- vec_add_dir(q2, v1, v2, (sd[1] / (sd[1] - sd[2])));
- vec_add_dir(q3, v0, v2, (sd[0] / (sd[0] - sd[2])));
- }
- else {
- /* ++0 */
- copy_v3_v3(q0, v0);
- copy_v3_v3(q1, v1);
- copy_v3_v3(q2, v2);
- copy_v3_v3(q3, q2);
- }
- }
- else if (sd[1] < 0) {
- if (sd[2] > 0) {
- /* +-+ */
- copy_v3_v3(q0, v0);
- vec_add_dir(q1, v0, v1, (sd[0] / (sd[0] - sd[1])));
- vec_add_dir(q2, v1, v2, (sd[1] / (sd[1] - sd[2])));
- copy_v3_v3(q3, v2);
- }
- else if (sd[2] < 0) {
- /* +-- */
- copy_v3_v3(q0, v0);
- vec_add_dir(q1, v0, v1, (sd[0] / (sd[0] - sd[1])));
- vec_add_dir(q2, v0, v2, (sd[0] / (sd[0] - sd[2])));
- copy_v3_v3(q3, q2);
- }
- else {
- /* +-0 */
- copy_v3_v3(q0, v0);
- vec_add_dir(q1, v0, v1, (sd[0] / (sd[0] - sd[1])));
- copy_v3_v3(q2, v2);
- copy_v3_v3(q3, q2);
- }
- }
- else {
- if (sd[2] > 0) {
- /* +0+ */
- copy_v3_v3(q0, v0);
- copy_v3_v3(q1, v1);
- copy_v3_v3(q2, v2);
- copy_v3_v3(q3, q2);
- }
- else if (sd[2] < 0) {
- /* +0- */
- copy_v3_v3(q0, v0);
- copy_v3_v3(q1, v1);
- vec_add_dir(q2, v0, v2, (sd[0] / (sd[0] - sd[2])));
- copy_v3_v3(q3, q2);
- }
- else {
- /* +00 */
- copy_v3_v3(q0, v0);
- copy_v3_v3(q1, v1);
- copy_v3_v3(q2, v2);
- copy_v3_v3(q3, q2);
- }
- }
- }
- else if (sd[0] < 0) {
- if (sd[1] > 0) {
- if (sd[2] > 0) {
- /* -++ */
- vec_add_dir(q0, v0, v1, (sd[0] / (sd[0] - sd[1])));
- copy_v3_v3(q1, v1);
- copy_v3_v3(q2, v2);
- vec_add_dir(q3, v0, v2, (sd[0] / (sd[0] - sd[2])));
- }
- else if (sd[2] < 0) {
- /* -+- */
- vec_add_dir(q0, v0, v1, (sd[0] / (sd[0] - sd[1])));
- copy_v3_v3(q1, v1);
- vec_add_dir(q2, v1, v2, (sd[1] / (sd[1] - sd[2])));
- copy_v3_v3(q3, q2);
- }
- else {
- /* -+0 */
- vec_add_dir(q0, v0, v1, (sd[0] / (sd[0] - sd[1])));
- copy_v3_v3(q1, v1);
- copy_v3_v3(q2, v2);
- copy_v3_v3(q3, q2);
- }
- }
- else if (sd[1] < 0) {
- if (sd[2] > 0) {
- /* --+ */
- vec_add_dir(q0, v0, v2, (sd[0] / (sd[0] - sd[2])));
- vec_add_dir(q1, v1, v2, (sd[1] / (sd[1] - sd[2])));
- copy_v3_v3(q2, v2);
- copy_v3_v3(q3, q2);
- }
- else if (sd[2] < 0) {
- /* --- */
- return 0;
- }
- else {
- /* --0 */
- return 0;
- }
- }
- else {
- if (sd[2] > 0) {
- /* -0+ */
- vec_add_dir(q0, v0, v2, (sd[0] / (sd[0] - sd[2])));
- copy_v3_v3(q1, v1);
- copy_v3_v3(q2, v2);
- copy_v3_v3(q3, q2);
- }
- else if (sd[2] < 0) {
- /* -0- */
- return 0;
- }
- else {
- /* -00 */
- return 0;
- }
- }
- }
- else {
- if (sd[1] > 0) {
- if (sd[2] > 0) {
- /* 0++ */
- copy_v3_v3(q0, v0);
- copy_v3_v3(q1, v1);
- copy_v3_v3(q2, v2);
- copy_v3_v3(q3, q2);
- }
- else if (sd[2] < 0) {
- /* 0+- */
- copy_v3_v3(q0, v0);
- copy_v3_v3(q1, v1);
- vec_add_dir(q2, v1, v2, (sd[1] / (sd[1] - sd[2])));
- copy_v3_v3(q3, q2);
- }
- else {
- /* 0+0 */
- copy_v3_v3(q0, v0);
- copy_v3_v3(q1, v1);
- copy_v3_v3(q2, v2);
- copy_v3_v3(q3, q2);
- }
- }
- else if (sd[1] < 0) {
- if (sd[2] > 0) {
- /* 0-+ */
- copy_v3_v3(q0, v0);
- vec_add_dir(q1, v1, v2, (sd[1] / (sd[1] - sd[2])));
- copy_v3_v3(q2, v2);
- copy_v3_v3(q3, q2);
- }
- else if (sd[2] < 0) {
- /* 0-- */
- return 0;
- }
- else {
- /* 0-0 */
- return 0;
- }
- }
- else {
- if (sd[2] > 0) {
- /* 00+ */
- copy_v3_v3(q0, v0);
- copy_v3_v3(q1, v1);
- copy_v3_v3(q2, v2);
- copy_v3_v3(q3, q2);
- }
- else if (sd[2] < 0) {
- /* 00- */
- return 0;
- }
- else {
- /* 000 */
- return 0;
- }
- }
- }
-
- return 1;
-}
-
-/* altivec optimization, this works, but is unused */
-
-#if 0
-#include <Accelerate/Accelerate.h>
-
-typedef union {
- vFloat v;
- float f[4];
-} vFloatResult;
-
-static vFloat vec_splat_float(float val)
-{
- return (vFloat) {val, val, val, val};
-}
-
-static float occ_quad_form_factor(float *p, float *n, float *q0, float *q1, float *q2, float *q3)
-{
- vFloat vcos, rlen, vrx, vry, vrz, vsrx, vsry, vsrz, gx, gy, gz, vangle;
- vUInt8 rotate = (vUInt8) {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3};
- vFloatResult vresult;
- float result;
-
- /* compute r* */
- vrx = (vFloat) {q0[0], q1[0], q2[0], q3[0]} -vec_splat_float(p[0]);
- vry = (vFloat) {q0[1], q1[1], q2[1], q3[1]} -vec_splat_float(p[1]);
- vrz = (vFloat) {q0[2], q1[2], q2[2], q3[2]} -vec_splat_float(p[2]);
-
- /* normalize r* */
- rlen = vec_rsqrte(vrx * vrx + vry * vry + vrz * vrz + vec_splat_float(1e-16f));
- vrx = vrx * rlen;
- vry = vry * rlen;
- vrz = vrz * rlen;
-
- /* rotate r* for cross and dot */
- vsrx = vec_perm(vrx, vrx, rotate);
- vsry = vec_perm(vry, vry, rotate);
- vsrz = vec_perm(vrz, vrz, rotate);
-
- /* cross product */
- gx = vsry * vrz - vsrz * vry;
- gy = vsrz * vrx - vsrx * vrz;
- gz = vsrx * vry - vsry * vrx;
-
- /* normalize */
- rlen = vec_rsqrte(gx * gx + gy * gy + gz * gz + vec_splat_float(1e-16f));
- gx = gx * rlen;
- gy = gy * rlen;
- gz = gz * rlen;
-
- /* angle */
- vcos = vrx * vsrx + vry * vsry + vrz * vsrz;
- vcos = vec_max(vec_min(vcos, vec_splat_float(1.0f)), vec_splat_float(-1.0f));
- vangle = vacosf(vcos);
-
- /* dot */
- vresult.v = (vec_splat_float(n[0]) * gx +
- vec_splat_float(n[1]) * gy +
- vec_splat_float(n[2]) * gz) * vangle;
-
- result = (vresult.f[0] + vresult.f[1] + vresult.f[2] + vresult.f[3]) * (0.5f / (float)M_PI);
- result = MAX2(result, 0.0f);
-
- return result;
-}
-
-#endif
-
-/* SSE optimization, acos code doesn't work */
-
-#if 0
-
-#include <xmmintrin.h>
-
-static __m128 sse_approx_acos(__m128 x)
-{
- /* needs a better approximation than taylor expansion of acos, since that
- * gives big erros for near 1.0 values, sqrt(2*x)*acos(1-x) should work
- * better, see http://www.tom.womack.net/projects/sse-fast-arctrig.html */
-
- return _mm_set_ps1(1.0f);
-}
-
-static float occ_quad_form_factor(float *p, float *n, float *q0, float *q1, float *q2, float *q3)
-{
- float r0[3], r1[3], r2[3], r3[3], g0[3], g1[3], g2[3], g3[3];
- float a1, a2, a3, a4, dot1, dot2, dot3, dot4, result;
- float fresult[4] __attribute__((aligned(16)));
- __m128 qx, qy, qz, rx, ry, rz, rlen, srx, sry, srz, gx, gy, gz, glen, rcos, angle, aresult;
-
- /* compute r */
- qx = _mm_set_ps(q3[0], q2[0], q1[0], q0[0]);
- qy = _mm_set_ps(q3[1], q2[1], q1[1], q0[1]);
- qz = _mm_set_ps(q3[2], q2[2], q1[2], q0[2]);
-
- rx = qx - _mm_set_ps1(p[0]);
- ry = qy - _mm_set_ps1(p[1]);
- rz = qz - _mm_set_ps1(p[2]);
-
- /* normalize r */
- rlen = _mm_rsqrt_ps(rx * rx + ry * ry + rz * rz + _mm_set_ps1(1e-16f));
- rx = rx * rlen;
- ry = ry * rlen;
- rz = rz * rlen;
-
- /* cross product */
- srx = _mm_shuffle_ps(rx, rx, _MM_SHUFFLE(0, 3, 2, 1));
- sry = _mm_shuffle_ps(ry, ry, _MM_SHUFFLE(0, 3, 2, 1));
- srz = _mm_shuffle_ps(rz, rz, _MM_SHUFFLE(0, 3, 2, 1));
-
- gx = sry * rz - srz * ry;
- gy = srz * rx - srx * rz;
- gz = srx * ry - sry * rx;
-
- /* normalize g */
- glen = _mm_rsqrt_ps(gx * gx + gy * gy + gz * gz + _mm_set_ps1(1e-16f));
- gx = gx * glen;
- gy = gy * glen;
- gz = gz * glen;
-
- /* compute angle */
- rcos = rx * srx + ry * sry + rz * srz;
- rcos = _mm_max_ps(_mm_min_ps(rcos, _mm_set_ps1(1.0f)), _mm_set_ps1(-1.0f));
-
- angle = sse_approx_cos(rcos);
- aresult = (_mm_set_ps1(n[0]) * gx + _mm_set_ps1(n[1]) * gy + _mm_set_ps1(n[2]) * gz) * angle;
-
- /* sum together */
- result = (fresult[0] + fresult[1] + fresult[2] + fresult[3]) * (0.5f / (float)M_PI);
- result = MAX2(result, 0.0f);
-
- return result;
-}
-
-#endif
-
-static void normalizef(float *n)
-{
- float d;
-
- d = dot_v3v3(n, n);
-
- if (d > 1.0e-35F) {
- d = 1.0f / sqrtf(d);
-
- n[0] *= d;
- n[1] *= d;
- n[2] *= d;
- }
-}
-
-/* TODO: exact duplicate of ff_quad_form_factor() in math_geom.c
- * why not de-duplicate? (also above helper func) */
-static float occ_quad_form_factor(const float p[3], const float n[3], const float q0[3], const float q1[3], const float q2[3], const float q3[3])
-{
- float r0[3], r1[3], r2[3], r3[3], g0[3], g1[3], g2[3], g3[3];
- float a1, a2, a3, a4, dot1, dot2, dot3, dot4, result;
-
- sub_v3_v3v3(r0, q0, p);
- sub_v3_v3v3(r1, q1, p);
- sub_v3_v3v3(r2, q2, p);
- sub_v3_v3v3(r3, q3, p);
-
- normalizef(r0);
- normalizef(r1);
- normalizef(r2);
- normalizef(r3);
-
- cross_v3_v3v3(g0, r1, r0); normalizef(g0);
- cross_v3_v3v3(g1, r2, r1); normalizef(g1);
- cross_v3_v3v3(g2, r3, r2); normalizef(g2);
- cross_v3_v3v3(g3, r0, r3); normalizef(g3);
-
- a1 = saacosf(dot_v3v3(r0, r1));
- a2 = saacosf(dot_v3v3(r1, r2));
- a3 = saacosf(dot_v3v3(r2, r3));
- a4 = saacosf(dot_v3v3(r3, r0));
-
- dot1 = dot_v3v3(n, g0);
- dot2 = dot_v3v3(n, g1);
- dot3 = dot_v3v3(n, g2);
- dot4 = dot_v3v3(n, g3);
-
- result = (a1 * dot1 + a2 * dot2 + a3 * dot3 + a4 * dot4) * 0.5f / (float)M_PI;
- result = MAX2(result, 0.0f);
-
- return result;
-}
-
static float occ_form_factor(OccFace *face, float *p, float *n)
{
ObjectInstanceRen *obi;
@@ -1190,16 +784,16 @@ static float occ_form_factor(OccFace *face, float *p, float *n)
mul_m4_v3(obi->mat, v3);
}
- if (occ_visible_quad(p, n, v1, v2, v3, q0, q1, q2, q3))
- contrib += occ_quad_form_factor(p, n, q0, q1, q2, q3);
+ if (form_factor_visible_quad(p, n, v1, v2, v3, q0, q1, q2, q3))
+ contrib += form_factor_quad(p, n, q0, q1, q2, q3);
if (vlr->v4) {
copy_v3_v3(v4, vlr->v4->co);
if (obi->flag & R_TRANSFORMED)
mul_m4_v3(obi->mat, v4);
- if (occ_visible_quad(p, n, v1, v3, v4, q0, q1, q2, q3))
- contrib += occ_quad_form_factor(p, n, q0, q1, q2, q3);
+ if (form_factor_visible_quad(p, n, v1, v3, v4, q0, q1, q2, q3))
+ contrib += form_factor_quad(p, n, q0, q1, q2, q3);
}
return contrib;
@@ -1520,8 +1114,8 @@ static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int
return 0;
/* require intensities not being too different */
- mino = MIN4(samples[0]->intensity, samples[1]->intensity, samples[2]->intensity, samples[3]->intensity);
- maxo = MAX4(samples[0]->intensity, samples[1]->intensity, samples[2]->intensity, samples[3]->intensity);
+ mino = min_ffff(samples[0]->intensity, samples[1]->intensity, samples[2]->intensity, samples[3]->intensity);
+ maxo = max_ffff(samples[0]->intensity, samples[1]->intensity, samples[2]->intensity, samples[3]->intensity);
if (maxo - mino > 0.05f)
return 0;
@@ -1665,7 +1259,7 @@ void make_occ_tree(Render *re)
/* ugly, needed for occ_face */
R = *re;
- re->i.infostr = "Occlusion preprocessing";
+ re->i.infostr = IFACE_("Occlusion preprocessing");
re->stats_draw(re->sdh, &re->i);
re->occlusiontree = tree = occ_tree_build(re);
@@ -1793,9 +1387,9 @@ void sample_occ(Render *re, ShadeInput *shi)
copy_v3_v3(sample->ao, shi->ao);
copy_v3_v3(sample->env, shi->env);
copy_v3_v3(sample->indirect, shi->indirect);
- sample->intensity = MAX3(sample->ao[0], sample->ao[1], sample->ao[2]);
- sample->intensity = MAX2(sample->intensity, MAX3(sample->env[0], sample->env[1], sample->env[2]));
- sample->intensity = MAX2(sample->intensity, MAX3(sample->indirect[0], sample->indirect[1], sample->indirect[2]));
+ sample->intensity = max_fff(sample->ao[0], sample->ao[1], sample->ao[2]);
+ sample->intensity = max_ff(sample->intensity, max_fff(sample->env[0], sample->env[1], sample->env[2]));
+ sample->intensity = max_ff(sample->intensity, max_fff(sample->indirect[0], sample->indirect[1], sample->indirect[2]));
sample->dist2 = dot_v3v3(shi->dxco, shi->dxco) + dot_v3v3(shi->dyco, shi->dyco);
sample->filled = 1;
}
@@ -1888,9 +1482,9 @@ void cache_occ_samples(Render *re, RenderPart *pa, ShadeSample *ssamp)
copy_v3_v3(sample->ao, shi->ao);
copy_v3_v3(sample->env, shi->env);
copy_v3_v3(sample->indirect, shi->indirect);
- sample->intensity = MAX3(sample->ao[0], sample->ao[1], sample->ao[2]);
- sample->intensity = MAX2(sample->intensity, MAX3(sample->env[0], sample->env[1], sample->env[2]));
- sample->intensity = MAX2(sample->intensity, MAX3(sample->indirect[0], sample->indirect[1], sample->indirect[2]));
+ sample->intensity = max_fff(sample->ao[0], sample->ao[1], sample->ao[2]);
+ sample->intensity = max_ff(sample->intensity, max_fff(sample->env[0], sample->env[1], sample->env[2]));
+ sample->intensity = max_ff(sample->intensity, max_fff(sample->indirect[0], sample->indirect[1], sample->indirect[2]));
sample->dist2 = dot_v3v3(shi->dxco, shi->dxco) + dot_v3v3(shi->dyco, shi->dyco);
sample->x = shi->xs;
sample->y = shi->ys;
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index e22a90cacb5..721bfa01a92 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -45,6 +45,18 @@
#include "MEM_guardedalloc.h"
+#include "BLI_math.h"
+#include "BLI_rect.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_path_util.h"
+#include "BLI_fileops.h"
+#include "BLI_threads.h"
+#include "BLI_rand.h"
+#include "BLI_callbacks.h"
+
+#include "BLF_translation.h"
+
#include "BKE_animsys.h" /* <------ should this be here?, needed for sequencer update */
#include "BKE_camera.h"
#include "BKE_global.h"
@@ -57,16 +69,6 @@
#include "BKE_sequencer.h"
#include "BKE_writeavi.h" /* <------ should be replaced once with generic movie module */
-#include "BLI_math.h"
-#include "BLI_rect.h"
-#include "BLI_listbase.h"
-#include "BLI_string.h"
-#include "BLI_path_util.h"
-#include "BLI_fileops.h"
-#include "BLI_threads.h"
-#include "BLI_rand.h"
-#include "BLI_callbacks.h"
-
#include "PIL_time.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
@@ -75,6 +77,11 @@
#include "RE_engine.h"
#include "RE_pipeline.h"
+#ifdef WITH_FREESTYLE
+# include "BKE_library.h"
+# include "FRS_freestyle.h"
+#endif
+
/* internal */
#include "render_result.h"
#include "render_types.h"
@@ -155,22 +162,23 @@ static void stats_background(void *UNUSED(arg), RenderStats *rs)
mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0);
megs_peak_memory = (peak_memory) / (1024.0 * 1024.0);
- fprintf(stdout, "Fra:%d Mem:%.2fM (%.2fM, peak %.2fM) ", rs->cfra,
+ fprintf(stdout, IFACE_("Fra:%d Mem:%.2fM (%.2fM, Peak %.2fM) "), rs->cfra,
megs_used_memory, mmap_used_memory, megs_peak_memory);
if (rs->curfield)
- fprintf(stdout, "Field %d ", rs->curfield);
+ fprintf(stdout, IFACE_("Field %d "), rs->curfield);
if (rs->curblur)
- fprintf(stdout, "Blur %d ", rs->curblur);
+ fprintf(stdout, IFACE_("Blur %d "), rs->curblur);
if (rs->infostr) {
fprintf(stdout, "| %s", rs->infostr);
}
else {
if (rs->tothalo)
- fprintf(stdout, "Sce: %s Ve:%d Fa:%d Ha:%d La:%d", rs->scene_name, rs->totvert, rs->totface, rs->tothalo, rs->totlamp);
+ fprintf(stdout, IFACE_("Sce: %s Ve:%d Fa:%d Ha:%d La:%d"),
+ rs->scene_name, rs->totvert, rs->totface, rs->tothalo, rs->totlamp);
else
- fprintf(stdout, "Sce: %s Ve:%d Fa:%d La:%d", rs->scene_name, rs->totvert, rs->totface, rs->totlamp);
+ fprintf(stdout, IFACE_("Sce: %s Ve:%d Fa:%d La:%d"), rs->scene_name, rs->totvert, rs->totface, rs->totlamp);
}
BLI_callback_exec(G.main, NULL, BLI_CB_EVT_RENDER_STATS);
@@ -336,7 +344,7 @@ void RE_ResultGet32(Render *re, unsigned int *rect)
RenderResult rres;
RE_AcquireResultImage(re, &rres);
- render_result_rect_get_pixels(&rres, &re->r, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings);
+ render_result_rect_get_pixels(&rres, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings);
RE_ReleaseResultImage(re);
}
@@ -453,13 +461,43 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer *
re->i.starttime = PIL_check_seconds_timer();
re->r = *rd; /* hardcopy */
-
+
+ if (source) {
+ /* reuse border flags from source renderer */
+ re->r.mode &= ~(R_BORDER | R_CROP);
+ re->r.mode |= source->r.mode & (R_BORDER | R_CROP);
+
+ /* dimensions shall be shared between all renderers */
+ re->r.xsch = source->r.xsch;
+ re->r.ysch = source->r.ysch;
+ re->r.size = source->r.size;
+ }
+
re->winx = winx;
re->winy = winy;
- if (disprect) {
+ if (source && (source->r.mode & R_BORDER)) {
+ /* eeh, doesn't seem original bordered disprect is storing anywhere
+ * after insertion on black happening in do_render_fields_blur_3d(),
+ * so for now simply re-calculate disprect using border from source
+ * renderer (sergey)
+ */
+
+ re->disprect.xmin = source->r.border.xmin * winx;
+ re->disprect.xmax = source->r.border.xmax * winx;
+
+ re->disprect.ymin = source->r.border.ymin * winy;
+ re->disprect.ymax = source->r.border.ymax * winy;
+
+ re->rectx = BLI_rcti_size_x(&re->disprect);
+ re->recty = BLI_rcti_size_y(&re->disprect);
+
+ /* copy border itself, since it could be used by external engines */
+ re->r.border = source->r.border;
+ }
+ else if (disprect) {
re->disprect = *disprect;
- re->rectx = BLI_rcti_size_x(disprect);
- re->recty = BLI_rcti_size_y(disprect);
+ re->rectx = BLI_rcti_size_x(&re->disprect);
+ re->recty = BLI_rcti_size_y(&re->disprect);
}
else {
re->disprect.xmin = re->disprect.ymin = 0;
@@ -469,7 +507,7 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer *
re->recty = winy;
}
- if (re->rectx < 2 || re->recty < 2 || (BKE_imtype_is_movie(rd->im_format.imtype) &&
+ if (re->rectx < 1 || re->recty < 1 || (BKE_imtype_is_movie(rd->im_format.imtype) &&
(re->rectx < 16 || re->recty < 16) ))
{
BKE_report(re->reports, RPT_ERROR, "Image too small");
@@ -655,7 +693,9 @@ static int render_display_draw_enabled(Render *re)
static void *do_part_thread(void *pa_v)
{
RenderPart *pa = pa_v;
-
+
+ pa->status = PART_STATUS_IN_PROGRESS;
+
/* need to return nicely all parts on esc */
if (R.test_break(R.tbh) == 0) {
@@ -671,6 +711,10 @@ static void *do_part_thread(void *pa_v)
else
zbufshade_tile(pa);
+ /* we do actually write pixels, but don't allocate/deallocate anything,
+ * so it is safe with other threads reading at the same time */
+ BLI_rw_mutex_lock(&R.resultmutex, THREAD_LOCK_READ);
+
/* merge too on break! */
if (R.result->do_exr_tile) {
render_result_exr_file_merge(R.result, pa->result);
@@ -684,9 +728,11 @@ static void *do_part_thread(void *pa_v)
render_result_merge(R.result, pa->result);
}
}
+
+ BLI_rw_mutex_unlock(&R.resultmutex);
}
- pa->ready = 1;
+ pa->status = PART_STATUS_READY;
return NULL;
}
@@ -717,24 +763,33 @@ float panorama_pixel_rot(Render *re)
return phi;
}
-/* call when all parts stopped rendering, to find the next Y slice */
-/* if slice found, it rotates the dbase */
-static RenderPart *find_next_pano_slice(Render *re, int *minx, rctf *viewplane)
+/* for panorama, we render per Y slice, and update
+ * camera parameters when we go the next slice */
+static bool find_next_pano_slice(Render *re, int *slice, int *minx, rctf *viewplane)
{
RenderPart *pa, *best = NULL;
+ bool found = false;
*minx = re->winx;
+ if (!(re->r.mode & R_PANORAMA)) {
+ /* for regular render, just one 'slice' */
+ found = (*slice == 0);
+ (*slice)++;
+ return found;
+ }
+
/* most left part of the non-rendering parts */
for (pa = re->parts.first; pa; pa = pa->next) {
- if (pa->ready == 0 && pa->nr == 0) {
+ if (pa->status == PART_STATUS_NONE && pa->nr == 0) {
if (pa->disprect.xmin < *minx) {
+ found = true;
best = pa;
*minx = pa->disprect.xmin;
}
}
}
-
+
if (best) {
float phi = panorama_pixel_rot(re);
@@ -752,7 +807,10 @@ static RenderPart *find_next_pano_slice(Render *re, int *minx, rctf *viewplane)
R.panosi = sin(R.panodxp * phi);
R.panoco = cos(R.panodxp * phi);
}
- return best;
+
+ (*slice)++;
+
+ return found;
}
static RenderPart *find_next_part(Render *re, int minx)
@@ -765,7 +823,7 @@ static RenderPart *find_next_part(Render *re, int minx)
/* find center of rendered parts, image center counts for 1 too */
for (pa = re->parts.first; pa; pa = pa->next) {
- if (pa->ready) {
+ if (pa->status == PART_STATUS_READY) {
centx += BLI_rcti_cent_x(&pa->disprect);
centy += BLI_rcti_cent_y(&pa->disprect);
tot++;
@@ -776,7 +834,7 @@ static RenderPart *find_next_part(Render *re, int minx)
/* closest of the non-rendering parts */
for (pa = re->parts.first; pa; pa = pa->next) {
- if (pa->ready == 0 && pa->nr == 0) {
+ 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);
@@ -801,39 +859,66 @@ static void print_part_stats(Render *re, RenderPart *pa)
{
char str[64];
- BLI_snprintf(str, sizeof(str), "%s, Part %d-%d", re->scene->id.name + 2, pa->nr, re->i.totpart);
+ BLI_snprintf(str, sizeof(str), IFACE_("%s, Part %d-%d"), re->scene->id.name + 2, pa->nr, re->i.totpart);
re->i.infostr = str;
re->stats_draw(re->sdh, &re->i);
re->i.infostr = NULL;
}
+typedef struct RenderThread {
+ ThreadQueue *workqueue;
+ ThreadQueue *donequeue;
+
+ int number;
+} RenderThread;
+
+static void *do_render_thread(void *thread_v)
+{
+ RenderThread *thread = thread_v;
+ RenderPart *pa;
+
+ while ((pa = BLI_thread_queue_pop(thread->workqueue))) {
+ pa->thread = thread->number;
+ do_part_thread(pa);
+ BLI_thread_queue_push(thread->donequeue, pa);
+
+ if (R.test_break(R.tbh))
+ break;
+ }
+
+ return NULL;
+}
+
static void threaded_tile_processor(Render *re)
{
+ RenderThread thread[BLENDER_MAX_THREADS];
+ ThreadQueue *workqueue, *donequeue;
ListBase threads;
- RenderPart *pa, *nextpa;
+ RenderPart *pa;
rctf viewplane = re->viewplane;
- int rendering = 1, counter = 1, drawtimer = 0, hasdrawn, minx = 0;
+ 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 */
if (re->result == NULL || !(re->r.scemode & R_PREVIEWBUTS)) {
render_result_free(re->result);
-
+
if (re->sss_points && render_display_draw_enabled(re))
re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS);
else if (re->r.scemode & R_FULL_SAMPLE)
re->result = render_result_new_full_sample(re, &re->fullresult, &re->disprect, 0, RR_USE_EXR);
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);
}
BLI_rw_mutex_unlock(&re->resultmutex);
if (re->result == NULL)
return;
-
+
/* warning; no return here without closing exr file */
RE_parts_init(re, TRUE);
@@ -841,53 +926,46 @@ static void threaded_tile_processor(Render *re)
if (re->result->do_exr_tile)
render_result_exr_file_begin(re);
- BLI_init_threads(&threads, do_part_thread, re->r.threads);
-
/* assuming no new data gets added to dbase... */
R = *re;
/* set threadsafe break */
R.test_break = thread_break;
- /* timer loop demands to sleep when no parts are left, so we enter loop with a part */
- if (re->r.mode & R_PANORAMA)
- nextpa = find_next_pano_slice(re, &minx, &viewplane);
- else
- nextpa = find_next_part(re, 0);
-
- while (rendering) {
-
- if (re->test_break(re->tbh))
- PIL_sleep_ms(50);
- else if (nextpa && BLI_available_threads(&threads)) {
- drawtimer = 0;
- nextpa->nr = counter++; /* for nicest part, and for stats */
- nextpa->thread = BLI_available_thread_index(&threads); /* sample index */
- BLI_insert_thread(&threads, nextpa);
-
- nextpa = find_next_part(re, minx);
- }
- else if (re->r.mode & R_PANORAMA) {
- if (nextpa == NULL && BLI_available_threads(&threads) == re->r.threads)
- nextpa = find_next_pano_slice(re, &minx, &viewplane);
- else {
- PIL_sleep_ms(50);
- drawtimer++;
- }
+ /* create and fill work queue */
+ workqueue = BLI_thread_queue_init();
+ donequeue = BLI_thread_queue_init();
+
+ /* 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);
}
- else {
- PIL_sleep_ms(50);
- drawtimer++;
+
+ BLI_thread_queue_nowait(workqueue);
+
+ /* start all threads */
+ BLI_init_threads(&threads, do_render_thread, re->r.threads);
+
+ for (a = 0; a < re->r.threads; a++) {
+ thread[a].workqueue = workqueue;
+ thread[a].donequeue = donequeue;
+ thread[a].number = a;
+ BLI_insert_thread(&threads, &thread[a]);
}
- /* check for ready ones to display, and if we need to continue */
- rendering = 0;
- hasdrawn = 0;
- for (pa = re->parts.first; pa; pa = pa->next) {
- if (pa->ready) {
-
- BLI_remove_thread(&threads, pa);
-
+ /* wait for results to come back */
+ lastdraw = PIL_check_seconds_timer();
+
+ while (1) {
+ elapsed = PIL_check_seconds_timer() - lastdraw;
+ wait = (redrawtime - elapsed)*1000;
+
+ /* handle finished part */
+ if ((pa=BLI_thread_queue_pop_timeout(donequeue, wait))) {
if (pa->result) {
if (render_display_draw_enabled(re))
re->display_draw(re->ddh, pa->result, NULL);
@@ -897,26 +975,52 @@ static void threaded_tile_processor(Render *re)
pa->result = NULL;
re->i.partsdone++;
re->progress(re->prh, re->i.partsdone / (float)re->i.totpart);
- hasdrawn = 1;
}
+
+ totpart--;
}
- else {
- rendering = 1;
- if (pa->nr && pa->result && drawtimer > 20) {
- if (render_display_draw_enabled(re))
- re->display_draw(re->ddh, pa->result, &pa->result->renrect);
- hasdrawn = 1;
- }
+
+ /* check for render cancel */
+ if ((g_break=re->test_break(re->tbh)))
+ break;
+
+ /* or done with parts */
+ if (totpart == 0)
+ break;
+
+ /* redraw in progress parts */
+ elapsed = PIL_check_seconds_timer() - lastdraw;
+ if (elapsed > redrawtime) {
+ if (render_display_draw_enabled(re))
+ for (pa = re->parts.first; pa; pa = pa->next)
+ if ((pa->status == PART_STATUS_IN_PROGRESS) && pa->nr && pa->result)
+ re->display_draw(re->ddh, pa->result, &pa->result->renrect);
+
+ lastdraw = PIL_check_seconds_timer();
}
}
- if (hasdrawn)
- drawtimer = 0;
-
- /* on break, wait for all slots to get freed */
- if ( (g_break = re->test_break(re->tbh)) && BLI_available_threads(&threads) == re->r.threads)
- rendering = 0;
+ BLI_end_threads(&threads);
+
+ if ((g_break=re->test_break(re->tbh)))
+ break;
}
+
+ if (g_break) {
+ /* review the done queue and handle all the render parts,
+ * so no unfreed render result are lurking around
+ */
+ BLI_thread_queue_nowait(donequeue);
+ while ((pa = BLI_thread_queue_pop(donequeue))) {
+ if (pa->result) {
+ render_result_free_list(&pa->fullresult, pa->result);
+ pa->result = NULL;
+ }
+ }
+ }
+
+ 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);
@@ -927,7 +1031,6 @@ static void threaded_tile_processor(Render *re)
/* unset threadsafety */
g_break = 0;
- BLI_end_threads(&threads);
RE_parts_free(re);
re->viewplane = viewplane; /* restore viewplane, modified by pano render */
}
@@ -940,8 +1043,15 @@ void RE_TileProcessor(Render *re)
/* ************ This part uses API, for rendering Blender scenes ********** */
+#ifdef WITH_FREESTYLE
+static void add_freestyle(Render *re);
+#endif
+
static void do_render_3d(Render *re)
{
+ float cfra;
+ int cfra_backup;
+
/* try external */
if (RE_engine_render(re, 0))
return;
@@ -949,9 +1059,13 @@ static void do_render_3d(Render *re)
/* internal */
RE_parts_clamp(re);
-// re->cfra= cfra; /* <- unused! */
- re->scene->r.subframe = re->mblur_offs + re->field_offs;
-
+ /* add motion blur and fields offset to frames */
+ cfra_backup = re->scene->r.cfra;
+
+ cfra = re->scene->r.cfra + re->mblur_offs + re->field_offs;
+ re->scene->r.cfra = floorf(cfra);
+ re->scene->r.subframe = cfra - floorf(cfra);
+
/* lock drawing in UI during data phase */
if (re->draw_lock)
re->draw_lock(re->dlh, 1);
@@ -973,9 +1087,17 @@ static void do_render_3d(Render *re)
if (!re->test_break(re->tbh))
add_halo_flare(re);
+#ifdef WITH_FREESTYLE
+ /* Freestyle */
+ if( re->r.mode & R_EDGE_FRS)
+ if(!re->test_break(re->tbh))
+ add_freestyle(re);
+#endif
+
/* free all render verts etc */
RE_Database_Free(re);
+ re->scene->r.cfra = cfra_backup;
re->scene->r.subframe = 0.f;
}
@@ -1084,7 +1206,7 @@ static void do_render_blur_3d(Render *re)
blurfac = 1.0f / (float)(re->r.mblur_samples - blur);
- merge_renderresult_blur(rres, re->result, blurfac, re->r.alphamode & R_ALPHAKEY);
+ merge_renderresult_blur(rres, re->result, blurfac, FALSE);
if (re->test_break(re->tbh)) break;
}
@@ -1229,7 +1351,7 @@ static void do_render_fields_blur_3d(Render *re)
Object *camera = RE_GetCamera(re);
/* also check for camera here */
if (camera == NULL) {
- printf("ERROR: Cannot render, no camera\n");
+ BKE_report(re->reports, RPT_ERROR, "Cannot render, no camera");
G.is_break = TRUE;
return;
}
@@ -1312,6 +1434,7 @@ static void render_scene(Render *re, Scene *sce, int cfra)
resc->main = re->main;
resc->scene = sce;
resc->lay = sce->lay;
+ resc->scene_color_manage = BKE_scene_check_color_management_enabled(sce);
/* ensure scene has depsgraph, base flags etc OK */
BKE_scene_set_background(re->main, sce);
@@ -1345,6 +1468,19 @@ static int composite_needs_render(Scene *sce, int this_scene)
return 0;
}
+static bool rlayer_node_uses_alpha(bNodeTree *ntree, bNode *node)
+{
+ bNodeSocket *sock;
+
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ /* Weak! but how to make it better? */
+ if (STREQ(sock->name, "Alpha") && nodeCountSocketLinks(ntree, sock) > 0)
+ return true;
+ }
+
+ return false;
+}
+
static void tag_scenes_for_render(Render *re)
{
bNode *node;
@@ -1362,6 +1498,21 @@ static void tag_scenes_for_render(Render *re)
for (node = re->scene->nodetree->nodes.first; node; node = node->next) {
if (node->type == CMP_NODE_R_LAYERS) {
if (node->id) {
+ if (!MAIN_VERSION_ATLEAST(re->main, 265, 5)) {
+ if (rlayer_node_uses_alpha(re->scene->nodetree, node)) {
+ Scene *scene = (Scene *)node->id;
+
+ if (scene->r.alphamode != R_ALPHAPREMUL) {
+ BKE_reportf(re->reports, RPT_WARNING, "Setting scene %s alpha mode to Premul", scene->id.name + 2);
+
+ /* also print, so feedback is immediate */
+ printf("2.66 versioning fix: setting scene %s alpha mode to Premul\n", scene->id.name + 2);
+
+ scene->r.alphamode = R_ALPHAPREMUL;
+ }
+ }
+ }
+
if (node->id != (ID *)re->scene)
node->id->flag |= LIB_DOIT;
}
@@ -1411,6 +1562,74 @@ static void render_composit_stats(void *UNUSED(arg), char *str)
R.i.infostr = NULL;
}
+#ifdef WITH_FREESTYLE
+/* invokes Freestyle stroke rendering */
+static void add_freestyle(Render *re)
+{
+ SceneRenderLayer *srl, *actsrl;
+ LinkData *link;
+
+ actsrl = BLI_findlink(&re->r.layers, re->r.actlay);
+
+ FRS_init_stroke_rendering(re);
+
+ for (srl= (SceneRenderLayer *)re->r.layers.first; srl; srl= srl->next) {
+
+ link = (LinkData *)MEM_callocN(sizeof(LinkData), "LinkData to Freestyle render");
+ BLI_addtail(&re->freestyle_renders, link);
+
+ if ((re->r.scemode & R_SINGLE_LAYER) && srl != actsrl)
+ continue;
+ if (FRS_is_freestyle_enabled(srl)) {
+ link->data = (void *)FRS_do_stroke_rendering(re, srl);
+ }
+ }
+
+ FRS_finish_stroke_rendering(re);
+}
+
+/* merges the results of Freestyle stroke rendering into a given render result */
+static void composite_freestyle_renders(Render *re, int sample)
+{
+ Render *freestyle_render;
+ 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;
+ render_result_exr_file_read(freestyle_render, sample);
+ FRS_composite_result(re, srl, freestyle_render);
+ RE_FreeRenderResult(freestyle_render->result);
+ freestyle_render->result = NULL;
+ }
+ link = link->next;
+ }
+}
+
+/* releases temporary scenes and renders for Freestyle stroke rendering */
+static void free_all_freestyle_renders(Scene *scene)
+{
+ Render *re1, *freestyle_render;
+ LinkData *link;
+
+ for (re1= RenderGlobal.renderlist.first; re1; re1= re1->next) {
+ for (link = (LinkData *)re1->freestyle_renders.first; link; link = link->next) {
+ if (link->data) {
+ freestyle_render = (Render *)link->data;
+ BKE_scene_unlink(G.main, freestyle_render->scene, scene);
+ RE_FreeRender(freestyle_render);
+ }
+ }
+ BLI_freelistN( &re1->freestyle_renders );
+ }
+}
+#endif
/* reads all buffers, calls optional composite, merges in first result->rectf */
static void do_merge_fullsample(Render *re, bNodeTree *ntree)
@@ -1452,6 +1671,10 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
if (sample) {
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
render_result_exr_file_read(re1, sample);
+#ifdef WITH_FREESTYLE
+ if( re1->r.mode & R_EDGE_FRS)
+ composite_freestyle_renders(re1, sample);
+#endif
BLI_rw_mutex_unlock(&re->resultmutex);
}
ntreeCompositTagRender(re1->scene); /* ensure node gets exec to put buffers on stack */
@@ -1654,6 +1877,10 @@ static void do_render_composite_fields_blur_3d(Render *re)
do_merge_fullsample(re, NULL);
}
+#ifdef WITH_FREESTYLE
+ free_all_freestyle_renders(re->scene);
+#endif
+
/* weak... the display callback wants an active renderlayer pointer... */
re->result->renlay = render_get_active_layer(re, re->result);
re->display_draw(re->ddh, re->result, NULL);
@@ -1789,7 +2016,12 @@ static void do_render_all_options(Render *re)
re->display_draw(re->ddh, re->result, NULL);
}
else {
+ re->pool = BKE_image_pool_new();
+
do_render_composite_fields_blur_3d(re);
+
+ BKE_image_pool_free(re->pool);
+ re->pool = NULL;
}
re->i.lastframetime = PIL_check_seconds_timer() - re->i.starttime;
@@ -1905,7 +2137,7 @@ int RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *r
render_result_exr_file_path(scene, "", 0, str);
- if (BLI_file_is_writable(str) == 0) {
+ if (!BLI_file_is_writable(str)) {
BKE_report(reports, RPT_ERROR, "Cannot save render buffers, check the temp default path");
return 0;
}
@@ -2109,7 +2341,7 @@ 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.imtype, scene->r.scemode & R_EXTENSION, FALSE);
+ BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, FALSE);
/* reports only used for Movie */
do_write_image_or_movie(re, bmain, scene, NULL, name);
@@ -2125,6 +2357,17 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr
G.is_rendering = FALSE;
}
+#ifdef WITH_FREESTYLE
+void RE_RenderFreestyleStrokes(Render *re, Main *bmain, Scene *scene)
+{
+ re->result_ok= 0;
+ if(render_initialize_from_main(re, bmain, scene, NULL, NULL, scene->lay, 0, 0)) {
+ do_render_fields_blur_3d(re);
+ }
+ re->result_ok= 1;
+}
+#endif
+
static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const char *name_override)
{
char name[FILE_MAX];
@@ -2168,7 +2411,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
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.imtype, scene->r.scemode & R_EXTENSION, TRUE);
+ BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, TRUE);
if (re->r.im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
if (re->result) {
@@ -2196,7 +2439,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
if (BLI_testextensie(name, ".exr"))
name[strlen(name) - 4] = 0;
- BKE_add_image_extension(name, R_IMF_IMTYPE_JPEG90);
+ BKE_add_image_extension(name, &imf);
ibuf->planes = 24;
IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings,
@@ -2301,7 +2544,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
/* Touch/NoOverwrite options are only valid for image's */
if (BKE_imtype_is_movie(scene->r.im_format.imtype) == 0) {
if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH))
- BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, scene->r.im_format.imtype, scene->r.scemode & R_EXTENSION, TRUE);
+ BKE_makepicstring(name, scene->r.pic, bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, TRUE);
if (scene->r.mode & R_NO_OVERWRITE && BLI_exists(name)) {
printf("skipping existing frame \"%s\"\n", name);
@@ -2335,7 +2578,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
/* 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, 0, 0);
+ BLI_delete(name, false, false);
}
}
@@ -2375,6 +2618,8 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
RE_InitState(re, NULL, &sce->r, NULL, winx, winy, NULL);
+ re->pool = BKE_image_pool_new();
+
re->main = bmain;
re->scene = sce;
re->scene_color_manage = BKE_scene_check_color_management_enabled(sce);
@@ -2384,6 +2629,9 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
RE_SetCamera(re, camera);
do_render_3d(re);
+
+ BKE_image_pool_free(re->pool);
+ re->pool = NULL;
}
/* note; repeated win/disprect calc... solve that nicer, also in compo */
diff --git a/source/blender/render/intern/source/pixelblending.c b/source/blender/render/intern/source/pixelblending.c
index 21ff1151cfb..66fd2209881 100644
--- a/source/blender/render/intern/source/pixelblending.c
+++ b/source/blender/render/intern/source/pixelblending.c
@@ -120,7 +120,7 @@ void addalphaAddfacFloat(float dest[4], const float source[4], char addfac)
else
#endif
dest[0] = c;
-
+
c = (m * dest[1]) + source[1];
#ifdef RE_FLOAT_COLOR_CLIPPING
if (c >= RE_FULL_COLOR_FLOAT) dest[1] = RE_FULL_COLOR_FLOAT;
diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c
index 3420648cb52..8a023a2c009 100644
--- a/source/blender/render/intern/source/pixelshading.c
+++ b/source/blender/render/intern/source/pixelshading.c
@@ -286,7 +286,7 @@ int shadeHaloFloat(HaloRen *har, float col[4], int zz,
/* fill in col */
float t, zn, radist, ringf=0.0f, linef=0.0f, alpha, si, co;
int a;
-
+
if (R.wrld.mode & WO_MIST) {
if (har->type & HA_ONLYSKY) {
/* stars but no mist */
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
index a540cdb85d5..d740780ec30 100644
--- a/source/blender/render/intern/source/pointdensity.c
+++ b/source/blender/render/intern/source/pointdensity.c
@@ -40,6 +40,8 @@
#include "BLI_kdopbvh.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_lattice.h"
@@ -299,7 +301,7 @@ void make_pointdensities(Render *re)
if (re->scene->r.scemode & R_PREVIEWBUTS)
return;
- re->i.infostr= "Caching Point Densities";
+ 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) {
@@ -308,7 +310,7 @@ void make_pointdensities(Render *re)
}
}
- re->i.infostr= NULL;
+ re->i.infostr = NULL;
re->stats_draw(re->sdh, &re->i);
}
@@ -447,7 +449,7 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
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.cfra / (float)R.r.efra;
+ 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_turbulence(pd->noise_size, texvec[0]+time, texvec[1]+time, texvec[2]+time, pd->noise_depth);
}
diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c
index 127e0bc07b9..88c0719fa59 100644
--- a/source/blender/render/intern/source/rayshade.c
+++ b/source/blender/render/intern/source/rayshade.c
@@ -47,6 +47,8 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "BKE_global.h"
#include "BKE_node.h"
@@ -81,7 +83,7 @@ extern struct Render R;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
static int test_break(void *data)
{
- Render *re = (Render*)data;
+ Render *re = (Render *)data;
return re->test_break(re->tbh);
}
@@ -94,7 +96,7 @@ static void RE_rayobject_config_control(RayObject *r, Render *re)
}
}
-static RayObject* RE_rayobject_create(Render *re, int type, int size)
+RayObject *RE_rayobject_create(int type, int size, int octree_resolution)
{
RayObject * res = NULL;
@@ -117,7 +119,7 @@ static RayObject* RE_rayobject_create(Render *re, int type, int size)
if (type == R_RAYSTRUCTURE_OCTREE) //TODO dynamic ocres
- res = RE_rayobject_octree_create(re->r.ocres, size);
+ res = RE_rayobject_octree_create(octree_resolution, size);
else if (type == R_RAYSTRUCTURE_BLIBVH)
res = RE_rayobject_blibvh_create(size);
else if (type == R_RAYSTRUCTURE_VBVH)
@@ -129,10 +131,18 @@ static RayObject* RE_rayobject_create(Render *re, int type, int size)
else
res = RE_rayobject_vbvh_create(size); //Fallback
+ return res;
+}
+
+static RayObject* rayobject_create(Render *re, int type, int size)
+{
+ RayObject * res = NULL;
+
+ res = RE_rayobject_create(type, size, re->r.ocres);
if (res)
RE_rayobject_config_control(res, re);
-
+
return res;
}
@@ -240,11 +250,11 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi)
return NULL;
//Create Ray cast accelaration structure
- raytree = RE_rayobject_create( re, re->r.raytrace_structure, faces );
+ raytree = rayobject_create( re, re->r.raytrace_structure, faces );
if ( (re->r.raytrace_options & R_RAYTRACE_USE_LOCAL_COORDS) )
- vlakprimitive = obr->rayprimitives = (VlakPrimitive*)MEM_callocN(faces*sizeof(VlakPrimitive), "ObjectRen primitives");
+ vlakprimitive = obr->rayprimitives = (VlakPrimitive *)MEM_callocN(faces * sizeof(VlakPrimitive), "ObjectRen primitives");
else
- face = obr->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "ObjectRen faces");
+ face = obr->rayfaces = (RayFace *)MEM_callocN(faces * sizeof(RayFace), "ObjectRen faces");
obr->rayobi = obi;
@@ -334,13 +344,13 @@ static void makeraytree_single(Render *re)
}
//Create raytree
- raytree = re->raytree = RE_rayobject_create( re, re->r.raytrace_structure, faces+special );
+ raytree = re->raytree = rayobject_create( re, re->r.raytrace_structure, faces+special );
if ( (re->r.raytrace_options & R_RAYTRACE_USE_LOCAL_COORDS) ) {
- vlakprimitive = re->rayprimitives = (VlakPrimitive*)MEM_callocN(faces*sizeof(VlakPrimitive), "Raytrace vlak-primitives");
+ vlakprimitive = re->rayprimitives = (VlakPrimitive *)MEM_callocN(faces * sizeof(VlakPrimitive), "Raytrace vlak-primitives");
}
else {
- face = re->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces");
+ face = re->rayfaces = (RayFace *)MEM_callocN(faces * sizeof(RayFace), "Render ray faces");
}
for (obi=re->instancetable.first; obi; obi=obi->next)
@@ -392,7 +402,7 @@ static void makeraytree_single(Render *re)
}
if (!test_break(re)) {
- re->i.infostr= "Raytree.. building";
+ re->i.infostr = IFACE_("Raytree.. building");
re->stats_draw(re->sdh, &re->i);
RE_rayobject_done(raytree);
@@ -404,7 +414,7 @@ void makeraytree(Render *re)
float min[3], max[3], sub[3];
int i;
- re->i.infostr= "Raytree.. preparing";
+ re->i.infostr = IFACE_("Raytree.. preparing");
re->stats_draw(re->sdh, &re->i);
/* disable options not yet supported by octree,
@@ -417,7 +427,7 @@ void makeraytree(Render *re)
if (test_break(re)) {
freeraytree(re);
- re->i.infostr= "Raytree building canceled";
+ re->i.infostr = IFACE_("Raytree building canceled");
re->stats_draw(re->sdh, &re->i);
}
else {
@@ -425,16 +435,20 @@ void makeraytree(Render *re)
* This is ONLY needed to kept a bogus behavior of SUN and HEMI lights */
INIT_MINMAX(min, max);
RE_rayobject_merge_bb(re->raytree, min, max);
+ if (min[0] > max[0]) { /* empty raytree */
+ zero_v3(min);
+ zero_v3(max);
+ }
for (i=0; i<3; i++) {
+ /* TODO: explain why add top both min and max??? */
min[i] += 0.01f;
max[i] += 0.01f;
sub[i] = max[i]-min[i];
}
- re->maxdist = dot_v3v3(sub, sub);
- if (re->maxdist > 0.0f) re->maxdist= sqrt(re->maxdist);
+ re->maxdist = len_v3(sub);
- re->i.infostr= "Raytree finished";
+ re->i.infostr = IFACE_("Raytree finished");
re->stats_draw(re->sdh, &re->i);
}
@@ -488,8 +502,8 @@ static void shade_ray_set_derivative(ShadeInput *shi)
void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)
{
- ObjectInstanceRen *obi= (ObjectInstanceRen*)is->hit.ob;
- VlakRen *vlr= (VlakRen*)is->hit.face;
+ ObjectInstanceRen *obi = (ObjectInstanceRen *)is->hit.ob;
+ VlakRen *vlr = (VlakRen *)is->hit.face;
/* set up view vector */
copy_v3_v3(shi->view, is->dir);
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index f8281586038..751d141a8be 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -35,18 +35,19 @@
#include "MEM_guardedalloc.h"
-#include "BKE_image.h"
-#include "BKE_global.h"
-#include "BKE_main.h"
-#include "BKE_report.h"
-
+#include "BLI_utildefines.h"
#include "BLI_fileops.h"
#include "BLI_listbase.h"
#include "BLI_path_util.h"
#include "BLI_rect.h"
#include "BLI_string.h"
#include "BLI_threads.h"
-#include "BLI_utildefines.h"
+
+#include "BKE_image.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+#include "BKE_freestyle.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -434,7 +435,7 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
rr->renrect.xmin = 0; rr->renrect.xmax = rectx - 2 * crop;
/* crop is one or two extra pixels rendered for filtering, is used for merging and display too */
rr->crop = crop;
-
+
/* tilerect is relative coordinates within render disprect. do not subtract crop yet */
rr->tilerect.xmin = partrct->xmin - re->disprect.xmin;
rr->tilerect.xmax = partrct->xmax - re->disprect.xmin;
@@ -564,6 +565,7 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
rl->lay = (1 << 20) - 1;
rl->layflag = 0x7FFF; /* solid ztra halo strand */
rl->passflag = SCE_PASS_COMBINED;
+ BKE_freestyle_config_init(&srl->freestyleConfig);
re->r.actlay = 0;
}
@@ -924,7 +926,7 @@ static void save_empty_result_tiles(Render *re)
IMB_exrtile_clear_channels(rl->exrhandle);
for (pa = re->parts.first; pa; pa = pa->next) {
- if (pa->ready == 0) {
+ 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);
@@ -983,11 +985,9 @@ void render_result_exr_file_merge(RenderResult *rr, RenderResult *rrpart)
/* path to temporary exr file */
void render_result_exr_file_path(Scene *scene, const char *layname, int sample, char *filepath)
{
- char di[FILE_MAX], name[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100], fi[FILE_MAXFILE];
-
- BLI_strncpy(di, G.main->name, FILE_MAX);
- BLI_splitdirstring(di, fi);
+ char name[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100], fi[FILE_MAXFILE];
+ 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);
else
@@ -1077,8 +1077,7 @@ int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, c
ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd)
{
- int flags = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE) ? IB_cm_predivide : 0;
- ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, flags);
+ ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, 0);
/* if not exists, BKE_imbuf_write makes one */
ibuf->rect = (unsigned int *)rr->rect32;
@@ -1095,6 +1094,10 @@ ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd)
if (BKE_imtype_valid_depths(rd->im_format.imtype) & (R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_24 | R_IMF_CHAN_DEPTH_32)) {
IMB_float_from_rect(ibuf);
}
+ else {
+ /* ensure no float buffer remained from previous frame */
+ ibuf->rect_float = NULL;
+ }
}
/* color -> grayscale */
@@ -1148,17 +1151,15 @@ void render_result_rect_fill_zero(RenderResult *rr)
rr->rect32 = MEM_callocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
}
-void render_result_rect_get_pixels(RenderResult *rr, RenderData *rd, unsigned int *rect, int rectx, int recty,
+void render_result_rect_get_pixels(RenderResult *rr, unsigned int *rect, int rectx, int recty,
const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings)
{
if (rr->rect32) {
memcpy(rect, rr->rect32, sizeof(int) * rr->rectx * rr->recty);
}
else if (rr->rectf) {
- int predivide = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
-
IMB_display_buffer_transform_apply((unsigned char *) rect, rr->rectf, rr->rectx, rr->recty, 4,
- view_settings, display_settings, predivide);
+ view_settings, display_settings, TRUE);
}
else
/* else fill with black */
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index e6daa5f9094..96eaa656c36 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -121,7 +121,7 @@ static void init_render_texture(Render *re, Tex *tex)
}
if (tex->nodetree && tex->use_nodes) {
- ntreeTexBeginExecTree(tex->nodetree, 1); /* has internal flag to detect it only does it once */
+ ntreeTexBeginExecTree(tex->nodetree); /* has internal flag to detect it only does it once */
}
}
@@ -141,7 +141,7 @@ void init_render_textures(Render *re)
static void end_render_texture(Tex *tex)
{
if (tex && tex->use_nodes && tex->nodetree && tex->nodetree->execdata)
- ntreeTexEndExecTree(tex->nodetree->execdata, 1);
+ ntreeTexEndExecTree(tex->nodetree->execdata);
}
void end_render_textures(Render *re)
@@ -171,9 +171,9 @@ static void tex_normal_derivate(Tex *tex, TexResult *texres)
do_colorband(tex->coba, texres->nor[2], col);
fac3= (col[0]+col[1]+col[2]);
- texres->nor[0]= 0.3333f*(fac0 - fac1);
- texres->nor[1]= 0.3333f*(fac0 - fac2);
- texres->nor[2]= 0.3333f*(fac0 - fac3);
+ texres->nor[0]= (fac0 - fac1) / 3.0f;
+ texres->nor[1]= (fac0 - fac2) / 3.0f;
+ texres->nor[2]= (fac0 - fac3) / 3.0f;
return;
}
@@ -1099,7 +1099,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)
+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)
{
float tmpvec[3];
int retval = 0; /* return value, int:0, col:1, nor:2, everything:3 */
@@ -1137,12 +1137,12 @@ static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int o
retval = texnoise(tex, texres);
break;
case TEX_IMAGE:
- if (osatex) retval = imagewraposa(tex, tex->ima, NULL, texvec, dxt, dyt, texres);
- else retval = imagewrap(tex, tex->ima, NULL, texvec, texres);
+ if (osatex) retval = imagewraposa(tex, tex->ima, NULL, texvec, dxt, dyt, texres, pool);
+ else retval = imagewrap(tex, tex->ima, NULL, texvec, texres, pool);
BKE_image_tag_time(tex->ima); /* tag image as having being used */
break;
case TEX_ENVMAP:
- retval = envmaptex(tex, texvec, dxt, dyt, osatex, texres);
+ retval = envmaptex(tex, texvec, dxt, dyt, osatex, texres, pool);
break;
case TEX_MUSGRAVE:
/* newnoise: musgrave types */
@@ -1214,7 +1214,7 @@ static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int o
/* this is called from the shader and texture nodes */
int multitex_nodes(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)
+ const short thread, short which_output, ShadeInput *shi, MTex *mtex, struct ImagePool *pool)
{
if (tex==NULL) {
memset(texres, 0, sizeof(TexResult));
@@ -1230,16 +1230,16 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os
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);
+ rgbnor = multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output, pool);
if (mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
/* don't linearize float buffers, assumed to be linear */
if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace);
- BKE_image_release_ibuf(tex->ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
}
}
else {
@@ -1263,28 +1263,28 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os
}
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);
+ rgbnor = multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres, thread, which_output, pool);
{
- ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
/* don't linearize float buffers, assumed to be linear */
if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace);
- BKE_image_release_ibuf(tex->ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
}
}
return rgbnor;
}
else {
- return multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output);
+ return multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output, pool);
}
}
/* 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)
+static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt[3], float dyt[3], TexResult *texres, struct ImagePool *pool)
{
Tex *tex = mtex->tex;
@@ -1295,24 +1295,24 @@ 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);
+ return multitex(mtex->tex, texvec, dxt, dyt, shi->osatex, texres, shi->thread, mtex->which_output, pool);
}
}
/* Warning, if the texres's values are not declared zero, check the return value to be sure
* the color values are set before using the r/g/b values, otherwise you may use uninitialized values - Campbell */
-int multitex_ext(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres)
+int multitex_ext(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, struct ImagePool *pool)
{
- return multitex_nodes(tex, texvec, dxt, dyt, osatex, texres, 0, 0, NULL, NULL);
+ return multitex_nodes(tex, texvec, dxt, dyt, osatex, texres, 0, 0, NULL, NULL, pool);
}
/* extern-tex doesn't support nodes (ntreeBeginExec() can't be called when rendering is going on) */
-int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres)
+int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres, struct ImagePool *pool)
{
int use_nodes= tex->use_nodes, retval;
tex->use_nodes = FALSE;
- retval= multitex_nodes(tex, texvec, NULL, NULL, 0, texres, 0, 0, NULL, NULL);
+ retval= multitex_nodes(tex, texvec, NULL, NULL, 0, texres, 0, 0, NULL, NULL, pool);
tex->use_nodes= use_nodes;
return retval;
@@ -1339,7 +1339,7 @@ void texture_rgb_blend(float in[3], const float tex[3], const float out[3], floa
case MTEX_MUL:
fact*= facg;
- facm= 1.0f-facg;
+ facm= 1.0f-fact;
in[0]= (facm+fact*tex[0])*out[0];
in[1]= (facm+fact*tex[1])*out[1];
in[2]= (facm+fact*tex[2])*out[2];
@@ -1347,7 +1347,7 @@ void texture_rgb_blend(float in[3], const float tex[3], const float out[3], floa
case MTEX_SCREEN:
fact*= facg;
- facm= 1.0f-facg;
+ facm= 1.0f-fact;
in[0]= 1.0f - (facm+fact*(1.0f-tex[0])) * (1.0f-out[0]);
in[1]= 1.0f - (facm+fact*(1.0f-tex[1])) * (1.0f-out[1]);
in[2]= 1.0f - (facm+fact*(1.0f-tex[2])) * (1.0f-out[2]);
@@ -1355,7 +1355,7 @@ void texture_rgb_blend(float in[3], const float tex[3], const float out[3], floa
case MTEX_OVERLAY:
fact*= facg;
- facm= 1.0f-facg;
+ facm= 1.0f-fact;
if (out[0] < 0.5f)
in[0] = out[0] * (facm + 2.0f*fact*tex[0]);
@@ -1699,7 +1699,8 @@ 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])
+ 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)
{
TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL}; /* temp TexResult */
float tco[3], texv[3], cd, ud, vd, du, dv, idu, idv;
@@ -1727,12 +1728,12 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
if (!shi->osatex && (tex->type == TEX_IMAGE) && tex->ima) {
/* in case we have no proper derivatives, fall back to
* computing du/dv it based on image size */
- ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
if (ibuf) {
du = 1.f/(float)ibuf->x;
dv = 1.f/(float)ibuf->y;
}
- BKE_image_release_ibuf(tex->ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
}
else if (shi->osatex) {
/* we have derivatives, can compute proper du/dv */
@@ -1745,15 +1746,15 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi,
else { /* 3d procedural, estimate from all dx/dy elems */
const float adx[3] = {fabsf(dx[0]), fabsf(dx[1]), fabsf(dx[2])};
const float ady[3] = {fabsf(dy[0]), fabsf(dy[1]), fabsf(dy[2])};
- du = MAX3(adx[0], adx[1], adx[2]);
- dv = MAX3(ady[0], ady[1], ady[2]);
+ du = max_fff(adx[0], adx[1], adx[2]);
+ dv = max_fff(ady[0], ady[1], ady[2]);
}
}
/* center, main return value */
texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
- rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres);
- cd = fromrgb ? (texres->tr + texres->tg + texres->tb)*0.33333333f : texres->tin;
+ rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool);
+ cd = fromrgb ? (texres->tr + texres->tg + texres->tb) / 3.0f : texres->tin;
if (mtex->texco == TEXCO_UV) {
/* for the uv case, use the same value for both du/dv,
@@ -1766,16 +1767,16 @@ 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);
- ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin));
+ multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
+ ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
/* +v val */
tco[0] = co[0] + compat_bump->dudnv*du;
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);
- vd = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin));
+ multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
+ vd = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
}
else {
float tu[3], tv[3];
@@ -1808,16 +1809,16 @@ 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);
- ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin));
+ multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
+ ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
/* +v val */
tco[0] = co[0] + tv[0]*dv;
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);
- vd = idv*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin));
+ multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool);
+ vd = idv*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb) / 3.0f : ttexr.tin));
}
/* bumped normal */
@@ -1858,7 +1859,7 @@ 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])
+ float texvec[3], float dxt[3], float dyt[3], struct ImagePool *pool)
{
TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL}; /* temp TexResult */
@@ -1905,20 +1906,20 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T
/* resolve image dimensions */
if (found_deriv_map || (mtex->texflag&MTEX_BUMP_TEXTURESPACE)!=0) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
if (ibuf) {
dimx = ibuf->x;
dimy = ibuf->y;
aspect = ((float) dimy) / dimx;
}
- BKE_image_release_ibuf(tex->ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(tex->ima, ibuf, pool);
}
if (found_deriv_map) {
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);
+ rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool);
if (shi->obr->ob->derivedFinal) {
auto_bump = shi->obr->ob->derivedFinal->auto_bump_scale;
@@ -1960,14 +1961,14 @@ 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);
+ rgbnor = multitex_mtex(shi, mtex, STll, dxt, dyt, texres, pool);
Hll = (fromrgb) ? rgb_to_grayscale(&texres->tr) : texres->tin;
/* use ttexr for the other 2 taps */
- multitex_mtex(shi, mtex, STlr, dxt, dyt, &ttexr);
+ multitex_mtex(shi, mtex, STlr, dxt, dyt, &ttexr, pool);
Hlr = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
- multitex_mtex(shi, mtex, STul, dxt, dyt, &ttexr);
+ multitex_mtex(shi, mtex, STul, dxt, dyt, &ttexr, pool);
Hul = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
dHdx = Hscale*(Hlr - Hll);
@@ -1998,17 +1999,17 @@ 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);
+ rgbnor = multitex_mtex(shi, mtex, STc, dxt, dyt, texres, pool);
/* Hc = (fromrgb) ? rgb_to_grayscale(&texres->tr) : texres->tin; */ /* UNUSED */
/* use ttexr for the other taps */
- multitex_mtex(shi, mtex, STl, dxt, dyt, &ttexr);
+ 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);
+ 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);
+ 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);
+ multitex_mtex(shi, mtex, STu, dxt, dyt, &ttexr, pool);
Hu = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin;
dHdx = Hscale*(Hr - Hl);
@@ -2285,20 +2286,22 @@ void do_material_tex(ShadeInput *shi, Render *re)
if (texres.nor && !((tex->type==TEX_IMAGE) && (tex->imaflag & TEX_NORMALMAP))) {
if (use_compat_bump) {
rgbnor = compatible_bump_compute(&compat_bump, shi, mtex, tex,
- &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt);
+ &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt,
+ re->pool);
}
else if (use_ntap_bump) {
rgbnor = ntap_bump_compute(&ntap_bump, shi, mtex, tex,
- &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt);
+ &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt,
+ re->pool);
}
else {
texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
- rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres);
+ rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool);
}
}
else {
texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
- rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres);
+ rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool);
}
/* texture output */
@@ -2402,13 +2405,13 @@ void do_material_tex(ShadeInput *shi, Render *re)
/* inverse gamma correction */
if (tex->type==TEX_IMAGE) {
Image *ima = tex->ima;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, re->pool);
/* don't linearize float buffers, assumed to be linear */
if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace);
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, re->pool);
}
if (mtex->mapto & MAP_COL) {
@@ -2737,7 +2740,7 @@ 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, 0, mtex->which_output); /* NULL = dxt/dyt, 0 = shi->osatex - not supported */
+ rgbnor = multitex(tex, texvec, NULL, NULL, 0, &texres, 0, mtex->which_output, re->pool); /* NULL = dxt/dyt, 0 = shi->osatex - not supported */
/* texture output */
@@ -2904,7 +2907,7 @@ 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);
+ rgb = multitex(mtex->tex, texvec, dxt, dyt, osatex, &texres, 0, mtex->which_output, har->pool);
/* texture output */
if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
@@ -2936,13 +2939,13 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4])
/* inverse gamma correction */
if (mtex->tex->type==TEX_IMAGE) {
Image *ima = mtex->tex->ima;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &mtex->tex->iuser, NULL);
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &mtex->tex->iuser, har->pool);
/* don't linearize float buffers, assumed to be linear */
if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace);
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, har->pool);
}
fact= texres.tin*mtex->colfac;
@@ -3109,7 +3112,7 @@ 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);
+ rgb = multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres, thread, mtex->which_output, R.pool);
/* texture output */
if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
@@ -3157,13 +3160,13 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h
/* inverse gamma correction */
if (tex->type==TEX_IMAGE) {
Image *ima = tex->ima;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, R.pool);
/* don't linearize float buffers, assumed to be linear */
if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace);
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, R.pool);
}
if (mtex->mapto & WOMAP_HORIZ) {
@@ -3324,7 +3327,7 @@ 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);
+ rgb = multitex(tex, texvec, dxt, dyt, shi->osatex, &texres, shi->thread, mtex->which_output, R.pool);
/* texture output */
if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
@@ -3373,13 +3376,13 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r
/* inverse gamma correction */
if (tex->type==TEX_IMAGE) {
Image *ima = tex->ima;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL);
+ ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, R.pool);
/* don't linearize float buffers, assumed to be linear */
if (ibuf && !(ibuf->rect_float) && R.scene_color_manage)
IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace);
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ BKE_image_pool_release_ibuf(ima, ibuf, R.pool);
}
/* lamp colors were premultiplied with this */
@@ -3395,7 +3398,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)
+int externtex(MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread, struct ImagePool *pool)
{
Tex *tex;
TexResult texr;
@@ -3421,7 +3424,7 @@ 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);
+ rgb = multitex(tex, texvec, dxt, dyt, 0, &texr, thread, mtex->which_output, pool);
if (rgb) {
texr.tin = rgb_to_bw(&texr.tr);
@@ -3485,8 +3488,8 @@ void render_realtime_texture(ShadeInput *shi, Image *ima)
texr.nor= NULL;
- if (shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr);
- else imagewrap(tex, ima, NULL, texvec, &texr);
+ if (shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr, R.pool);
+ else imagewrap(tex, ima, NULL, texvec, &texr, R.pool);
shi->vcol[0]*= texr.tr;
shi->vcol[1]*= texr.tg;
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 3431c3ff5de..2d0f575b3e3 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -51,9 +51,12 @@
#include "DNA_image_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_group_types.h"
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_main.h"
@@ -710,9 +713,11 @@ static void sky_tile(RenderPart *pa, RenderLayer *rl)
if (pass[3]==0.0f) {
copy_v4_v4(pass, col);
+ pass[3] = 1.0f;
}
else {
addAlphaUnderFloat(pass, col);
+ pass[3] = 1.0f;
}
}
}
@@ -981,29 +986,6 @@ static void edge_enhance_add(RenderPart *pa, float *rectf, float *arect)
}
}
-static void convert_to_key_alpha(RenderPart *pa, RenderLayer *rl)
-{
- RenderLayer *rlpp[RE_MAX_OSA];
- int y, sample, totsample;
-
- totsample= get_sample_layers(pa, rl, rlpp);
-
- for (sample= 0; sample<totsample; sample++) {
- float *rectf= rlpp[sample]->rectf;
-
- for (y= pa->rectx*pa->recty; y>0; y--, rectf+=4) {
- if (rectf[3] >= 1.0f) {
- /* pass */
- }
- else if (rectf[3] > 0.0f) {
- rectf[0] /= rectf[3];
- rectf[1] /= rectf[3];
- rectf[2] /= rectf[3];
- }
- }
- }
-}
-
/* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */
static void clamp_alpha_rgb_range(RenderPart *pa, RenderLayer *rl)
{
@@ -1156,7 +1138,7 @@ static void addAlphaOverFloatMask(float *dest, float *source, unsigned short dma
dest[3]+= source[3];
return;
- }
+ }
dest[0]= (mul*dest[0]) + source[0];
dest[1]= (mul*dest[1]) + source[1];
@@ -1172,7 +1154,7 @@ typedef struct ZbufSolidData {
static void make_pixelstructs(RenderPart *pa, ZSpan *zspan, int sample, void *data)
{
- ZbufSolidData *sdata= (ZbufSolidData*)data;
+ ZbufSolidData *sdata = (ZbufSolidData *)data;
ListBase *lb= sdata->psmlist;
intptr_t *rd= pa->rectdaps;
int *ro= zspan->recto;
@@ -1312,10 +1294,6 @@ void zbufshadeDA_tile(RenderPart *pa)
/* clamp alpha to 0..1 range, can go outside due to filter */
clamp_alpha_rgb_range(pa, rl);
- /* de-premul alpha */
- if (R.r.alphamode & R_ALPHAKEY)
- convert_to_key_alpha(pa, rl);
-
/* free stuff within loop! */
MEM_freeN(pa->rectdaps); pa->rectdaps= NULL;
freeps(&psmlist);
@@ -1476,10 +1454,6 @@ void zbufshade_tile(RenderPart *pa)
if (rl->passflag & SCE_PASS_VECTOR)
reset_sky_speed(pa, rl);
- /* de-premul alpha */
- if (R.r.alphamode & R_ALPHAKEY)
- convert_to_key_alpha(pa, rl);
-
if (edgerect) MEM_freeN(edgerect);
edgerect= NULL;
@@ -1740,7 +1714,7 @@ void zbufshade_sss_tile(RenderPart *pa)
#if 0
if (rs) {
/* for each sample in this pixel, shade it */
- for (ps=(PixStr*)*rs; ps; ps=ps->next) {
+ for (ps = (PixStr *)(*rs); ps; ps=ps->next) {
ObjectInstanceRen *obi= &re->objectinstance[ps->obi];
ObjectRen *obr= obi->obr;
vlr= RE_findOrAddVlak(obr, (ps->facenr-1) & RE_QUAD_MASK);
@@ -2016,783 +1990,3 @@ void add_halo_flare(Render *re)
R.r.mode= mode;
}
-/* ************************* bake ************************ */
-
-
-typedef struct BakeShade {
- ShadeSample ssamp;
- ObjectInstanceRen *obi;
- VlakRen *vlr;
-
- ZSpan *zspan;
- Image *ima;
- ImBuf *ibuf;
-
- int rectx, recty, quad, type, vdone, ready;
-
- float dir[3];
- Object *actob;
-
- unsigned int *rect;
- float *rect_float;
-
- int use_mask;
- char *rect_mask; /* bake pixel mask */
-
- float dxco[3], dyco[3];
-
- short *do_update;
-
- struct ColorSpace *rect_colorspace;
-} BakeShade;
-
-static void bake_set_shade_input(ObjectInstanceRen *obi, VlakRen *vlr, ShadeInput *shi, int quad, int UNUSED(isect), int x, int y, float u, float v)
-{
- if (quad)
- shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3);
- else
- shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);
-
- /* cache for shadow */
- shi->samplenr= R.shadowsamplenr[shi->thread]++;
-
- shi->mask= 0xFFFF; /* all samples */
-
- shi->u= -u;
- shi->v= -v;
- shi->xs= x;
- shi->ys= y;
-
- shade_input_set_uv(shi);
- shade_input_set_normals(shi);
-
- /* no normal flip */
- if (shi->flippednor)
- shade_input_flip_normals(shi);
-
- /* set up view vector to look right at the surface (note that the normal
- * is negated in the renderer so it does not need to be done here) */
- shi->view[0]= shi->vn[0];
- shi->view[1]= shi->vn[1];
- shi->view[2]= shi->vn[2];
-}
-
-static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(quad), int x, int y, float UNUSED(u), float UNUSED(v), float *tvn, float *ttang)
-{
- BakeShade *bs= handle;
- ShadeSample *ssamp= &bs->ssamp;
- ShadeResult shr;
- VlakRen *vlr= shi->vlr;
-
- shade_input_init_material(shi);
-
- if (bs->type==RE_BAKE_AO) {
- ambient_occlusion(shi);
-
- if (R.r.bake_flag & R_BAKE_NORMALIZE) {
- copy_v3_v3(shr.combined, shi->ao);
- }
- else {
- zero_v3(shr.combined);
- environment_lighting_apply(shi, &shr);
- }
- }
- else {
- if (bs->type==RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */
- shi->r = shi->g = shi->b = 1.0f;
-
- shade_input_set_shade_texco(shi);
-
- /* only do AO for a full bake (and obviously AO bakes)
- * AO for light bakes is a leftover and might not be needed */
- if ( ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_AO, RE_BAKE_LIGHT))
- shade_samples_do_AO(ssamp);
-
- if (shi->mat->nodetree && shi->mat->use_nodes) {
- ntreeShaderExecTree(shi->mat->nodetree, shi, &shr);
- shi->mat= vlr->mat; /* shi->mat is being set in nodetree */
- }
- else
- shade_material_loop(shi, &shr);
-
- if (bs->type==RE_BAKE_NORMALS) {
- float nor[3];
-
- copy_v3_v3(nor, shi->vn);
-
- if (R.r.bake_normal_space == R_BAKE_SPACE_CAMERA) {
- /* pass */
- }
- else if (R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) {
- float mat[3][3], imat[3][3];
-
- /* bitangent */
- if (tvn && ttang) {
- copy_v3_v3(mat[0], ttang);
- cross_v3_v3v3(mat[1], tvn, ttang);
- mul_v3_fl(mat[1], ttang[3]);
- copy_v3_v3(mat[2], tvn);
- }
- else {
- copy_v3_v3(mat[0], shi->nmaptang);
- cross_v3_v3v3(mat[1], shi->nmapnorm, shi->nmaptang);
- mul_v3_fl(mat[1], shi->nmaptang[3]);
- copy_v3_v3(mat[2], shi->nmapnorm);
- }
-
- invert_m3_m3(imat, mat);
- mul_m3_v3(imat, nor);
- }
- else if (R.r.bake_normal_space == R_BAKE_SPACE_OBJECT)
- mul_mat3_m4_v3(ob->imat_ren, nor); /* ob->imat_ren includes viewinv! */
- else if (R.r.bake_normal_space == R_BAKE_SPACE_WORLD)
- mul_mat3_m4_v3(R.viewinv, nor);
-
- normalize_v3(nor); /* in case object has scaling */
-
- /* The invert of the red channel is to make
- * the normal map compliant with the outside world.
- * It needs to be done because in Blender
- * the normal used in the renderer points inward. It is generated
- * this way in calc_vertexnormals(). Should this ever change
- * this negate must be removed. */
- shr.combined[0]= (-nor[0])/2.0f + 0.5f;
- shr.combined[1]= nor[1]/2.0f + 0.5f;
- shr.combined[2]= nor[2]/2.0f + 0.5f;
- }
- else if (bs->type==RE_BAKE_TEXTURE) {
- shr.combined[0]= shi->r;
- shr.combined[1]= shi->g;
- shr.combined[2]= shi->b;
- shr.alpha = shi->alpha;
- }
- else if (bs->type==RE_BAKE_SHADOW) {
- copy_v3_v3(shr.combined, shr.shad);
- shr.alpha = shi->alpha;
- }
- else if (bs->type==RE_BAKE_SPEC_COLOR) {
- shr.combined[0]= shi->specr;
- shr.combined[1]= shi->specg;
- shr.combined[2]= shi->specb;
- shr.alpha = 1.0f;
- }
- else if (bs->type==RE_BAKE_SPEC_INTENSITY) {
- shr.combined[0]=
- shr.combined[1]=
- shr.combined[2]= shi->spec;
- shr.alpha = 1.0f;
- }
- else if (bs->type==RE_BAKE_MIRROR_COLOR) {
- shr.combined[0]= shi->mirr;
- shr.combined[1]= shi->mirg;
- shr.combined[2]= shi->mirb;
- shr.alpha = 1.0f;
- }
- else if (bs->type==RE_BAKE_MIRROR_INTENSITY) {
- shr.combined[0]=
- shr.combined[1]=
- shr.combined[2]= shi->ray_mirror;
- shr.alpha = 1.0f;
- }
- else if (bs->type==RE_BAKE_ALPHA) {
- shr.combined[0]=
- shr.combined[1]=
- shr.combined[2]= shi->alpha;
- shr.alpha = 1.0f;
- }
- else if (bs->type==RE_BAKE_EMIT) {
- shr.combined[0]=
- shr.combined[1]=
- shr.combined[2]= shi->emit;
- shr.alpha = 1.0f;
- }
- }
-
- if (bs->rect_float) {
- float *col= bs->rect_float + 4*(bs->rectx*y + x);
- copy_v3_v3(col, shr.combined);
- if (bs->type==RE_BAKE_ALL || bs->type==RE_BAKE_TEXTURE) {
- col[3]= shr.alpha;
- }
- else {
- col[3]= 1.0;
- }
- }
- else {
- unsigned char *col= (unsigned char *)(bs->rect + bs->rectx*y + x);
-
- if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
- float rgb[3];
-
- copy_v3_v3(rgb, shr.combined);
- if (R.scene_color_manage)
- IMB_colormanagement_scene_linear_to_colorspace_v3(rgb, bs->rect_colorspace);
- rgb_float_to_uchar(col, rgb);
- }
- else {
- rgb_float_to_uchar(col, shr.combined);
- }
-
- if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
- col[3]= FTOCHAR(shr.alpha);
- }
- else {
- col[3]= 255;
- }
- }
-
- if (bs->rect_mask) {
- bs->rect_mask[bs->rectx*y + x] = FILTER_MASK_USED;
- }
-}
-
-static void bake_displacement(void *handle, ShadeInput *UNUSED(shi), float dist, int x, int y)
-{
- BakeShade *bs= handle;
- float disp;
-
- if (R.r.bake_flag & R_BAKE_NORMALIZE && R.r.bake_maxdist) {
- disp = (dist+R.r.bake_maxdist) / (R.r.bake_maxdist*2); /* alter the range from [-bake_maxdist, bake_maxdist] to [0, 1]*/
- }
- else {
- disp = 0.5f + dist; /* alter the range from [-0.5,0.5] to [0,1]*/
- }
-
- if (bs->rect_float) {
- float *col= bs->rect_float + 4*(bs->rectx*y + x);
- col[0] = col[1] = col[2] = disp;
- col[3]= 1.0f;
- }
- else {
- char *col= (char *)(bs->rect + bs->rectx*y + x);
- col[0] = col[1] = col[2] = FTOCHAR(disp);
- col[3]= 255;
- }
- if (bs->rect_mask) {
- bs->rect_mask[bs->rectx*y + x] = FILTER_MASK_USED;
- }
-}
-
-static int bake_intersect_tree(RayObject* raytree, Isect* isect, float *start, float *dir, float sign, float *hitco, float *dist)
-{
- float maxdist;
- int hit;
-
- /* might be useful to make a user setting for maxsize*/
- if (R.r.bake_maxdist > 0.0f)
- maxdist= R.r.bake_maxdist;
- else
- maxdist= RE_RAYTRACE_MAXDIST + R.r.bake_biasdist;
-
- /* 'dir' is always normalized */
- madd_v3_v3v3fl(isect->start, start, dir, -R.r.bake_biasdist);
-
- mul_v3_v3fl(isect->dir, dir, sign);
-
- isect->dist = maxdist;
-
- hit = RE_rayobject_raycast(raytree, isect);
- if (hit) {
- madd_v3_v3v3fl(hitco, isect->start, isect->dir, isect->dist);
-
- *dist= isect->dist;
- }
-
- return hit;
-}
-
-static void bake_set_vlr_dxyco(BakeShade *bs, float *uv1, float *uv2, float *uv3)
-{
- VlakRen *vlr= bs->vlr;
- float A, d1, d2, d3, *v1, *v2, *v3;
-
- if (bs->quad) {
- v1= vlr->v1->co;
- v2= vlr->v3->co;
- v3= vlr->v4->co;
- }
- else {
- v1= vlr->v1->co;
- v2= vlr->v2->co;
- v3= vlr->v3->co;
- }
-
- /* formula derived from barycentric coordinates:
- * (uvArea1*v1 + uvArea2*v2 + uvArea3*v3)/uvArea
- * then taking u and v partial derivatives to get dxco and dyco */
- A= (uv2[0] - uv1[0])*(uv3[1] - uv1[1]) - (uv3[0] - uv1[0])*(uv2[1] - uv1[1]);
-
- if (fabsf(A) > FLT_EPSILON) {
- A= 0.5f/A;
-
- d1= uv2[1] - uv3[1];
- d2= uv3[1] - uv1[1];
- d3= uv1[1] - uv2[1];
- bs->dxco[0]= (v1[0]*d1 + v2[0]*d2 + v3[0]*d3)*A;
- bs->dxco[1]= (v1[1]*d1 + v2[1]*d2 + v3[1]*d3)*A;
- bs->dxco[2]= (v1[2]*d1 + v2[2]*d2 + v3[2]*d3)*A;
-
- d1= uv3[0] - uv2[0];
- d2= uv1[0] - uv3[0];
- d3= uv2[0] - uv1[0];
- bs->dyco[0]= (v1[0]*d1 + v2[0]*d2 + v3[0]*d3)*A;
- bs->dyco[1]= (v1[1]*d1 + v2[1]*d2 + v3[1]*d3)*A;
- bs->dyco[2]= (v1[2]*d1 + v2[2]*d2 + v3[2]*d3)*A;
- }
- else {
- bs->dxco[0]= bs->dxco[1]= bs->dxco[2]= 0.0f;
- bs->dyco[0]= bs->dyco[1]= bs->dyco[2]= 0.0f;
- }
-
- if (bs->obi->flag & R_TRANSFORMED) {
- mul_m3_v3(bs->obi->nmat, bs->dxco);
- mul_m3_v3(bs->obi->nmat, bs->dyco);
- }
-}
-
-static void do_bake_shade(void *handle, int x, int y, float u, float v)
-{
- BakeShade *bs= handle;
- VlakRen *vlr= bs->vlr;
- ObjectInstanceRen *obi= bs->obi;
- Object *ob= obi->obr->ob;
- float l, *v1, *v2, *v3, tvn[3], ttang[4];
- int quad;
- ShadeSample *ssamp= &bs->ssamp;
- ShadeInput *shi= ssamp->shi;
-
- /* fast threadsafe break test */
- if (R.test_break(R.tbh))
- return;
-
- /* setup render coordinates */
- if (bs->quad) {
- v1= vlr->v1->co;
- v2= vlr->v3->co;
- v3= vlr->v4->co;
- }
- else {
- v1= vlr->v1->co;
- v2= vlr->v2->co;
- v3= vlr->v3->co;
- }
-
- l= 1.0f-u-v;
-
- /* shrink barycentric coordinates inwards slightly to avoid some issues
- * where baking selected to active might just miss the other face at the
- * near the edge of a face */
- if (bs->actob) {
- const float eps = 1.0f - 1e-4f;
- float invsum;
-
- u = (u - 0.5f)*eps + 0.5f;
- v = (v - 0.5f)*eps + 0.5f;
- l = (l - 0.5f)*eps + 0.5f;
-
- invsum = 1.0f/(u + v + l);
-
- u *= invsum;
- v *= invsum;
- l *= invsum;
- }
-
- /* renderco */
- shi->co[0]= l*v3[0]+u*v1[0]+v*v2[0];
- shi->co[1]= l*v3[1]+u*v1[1]+v*v2[1];
- shi->co[2]= l*v3[2]+u*v1[2]+v*v2[2];
-
- if (obi->flag & R_TRANSFORMED)
- mul_m4_v3(obi->mat, shi->co);
-
- copy_v3_v3(shi->dxco, bs->dxco);
- copy_v3_v3(shi->dyco, bs->dyco);
-
- quad= bs->quad;
- bake_set_shade_input(obi, vlr, shi, quad, 0, x, y, u, v);
-
- if (bs->type==RE_BAKE_NORMALS && R.r.bake_normal_space==R_BAKE_SPACE_TANGENT) {
- shade_input_set_shade_texco(shi);
- copy_v3_v3(tvn, shi->nmapnorm);
- copy_v4_v4(ttang, shi->nmaptang);
- }
-
- /* if we are doing selected to active baking, find point on other face */
- if (bs->actob) {
- Isect isec, minisec;
- float co[3], minco[3], dist, mindist=0.0f;
- int hit, sign, dir=1;
-
- /* intersect with ray going forward and backward*/
- hit= 0;
- memset(&minisec, 0, sizeof(minisec));
- minco[0]= minco[1]= minco[2]= 0.0f;
-
- copy_v3_v3(bs->dir, shi->vn);
-
- for (sign=-1; sign<=1; sign+=2) {
- memset(&isec, 0, sizeof(isec));
- isec.mode= RE_RAY_MIRROR;
-
- isec.orig.ob = obi;
- isec.orig.face = vlr;
- isec.userdata= bs->actob;
- isec.check = RE_CHECK_VLR_BAKE;
- isec.skip = RE_SKIP_VLR_NEIGHBOUR;
-
- if (bake_intersect_tree(R.raytree, &isec, shi->co, shi->vn, sign, co, &dist)) {
- if (!hit || len_squared_v3v3(shi->co, co) < len_squared_v3v3(shi->co, minco)) {
- minisec= isec;
- mindist= dist;
- copy_v3_v3(minco, co);
- hit= 1;
- dir = sign;
- }
- }
- }
-
- if (bs->type==RE_BAKE_DISPLACEMENT) {
- if (hit)
- bake_displacement(handle, shi, (dir==-1)? mindist:-mindist, x, y);
- else
- bake_displacement(handle, shi, 0.0f, x, y);
- return;
- }
-
- /* if hit, we shade from the new point, otherwise from point one starting face */
- if (hit) {
- obi= (ObjectInstanceRen*)minisec.hit.ob;
- vlr= (VlakRen*)minisec.hit.face;
- quad= (minisec.isect == 2);
- copy_v3_v3(shi->co, minco);
-
- u= -minisec.u;
- v= -minisec.v;
- bake_set_shade_input(obi, vlr, shi, quad, 1, x, y, u, v);
- }
- }
-
- if (bs->type==RE_BAKE_NORMALS && R.r.bake_normal_space==R_BAKE_SPACE_TANGENT)
- bake_shade(handle, ob, shi, quad, x, y, u, v, tvn, ttang);
- else
- bake_shade(handle, ob, shi, quad, x, y, u, v, 0, 0);
-}
-
-static int get_next_bake_face(BakeShade *bs)
-{
- ObjectRen *obr;
- VlakRen *vlr;
- MTFace *tface;
- static int v= 0, vdone = FALSE;
- static ObjectInstanceRen *obi= NULL;
-
- if (bs==NULL) {
- vlr= NULL;
- v= vdone = FALSE;
- obi= R.instancetable.first;
- return 0;
- }
-
- BLI_lock_thread(LOCK_CUSTOM1);
-
- for (; obi; obi=obi->next, v=0) {
- obr= obi->obr;
-
- for (; v<obr->totvlak; v++) {
- vlr= RE_findOrAddVlak(obr, v);
-
- if ((bs->actob && bs->actob == obr->ob) || (!bs->actob && (obr->ob->flag & SELECT))) {
- tface= RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
-
- if (tface && tface->tpage) {
- Image *ima= tface->tpage;
- ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
- const float vec_alpha[4]= {0.0f, 0.0f, 0.0f, 0.0f};
- const float vec_solid[4]= {0.0f, 0.0f, 0.0f, 1.0f};
-
- if (ibuf==NULL)
- continue;
-
- if (ibuf->rect==NULL && ibuf->rect_float==NULL) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- continue;
- }
-
- if (ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4)) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- continue;
- }
-
- if (ima->flag & IMA_USED_FOR_RENDER) {
- ima->id.flag &= ~LIB_DOIT;
- BKE_image_release_ibuf(ima, ibuf, NULL);
- continue;
- }
-
- /* find the image for the first time? */
- if (ima->id.flag & LIB_DOIT) {
- ima->id.flag &= ~LIB_DOIT;
-
- /* we either fill in float or char, this ensures things go fine */
- if (ibuf->rect_float)
- imb_freerectImBuf(ibuf);
- /* clear image */
- if (R.r.bake_flag & R_BAKE_CLEAR)
- IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
-
- /* might be read by UI to set active image for display */
- R.bakebuf= ima;
- }
-
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
-
- bs->obi= obi;
- bs->vlr= vlr;
-
- bs->vdone++; /* only for error message if nothing was rendered */
- v++;
-
- BLI_unlock_thread(LOCK_CUSTOM1);
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
-
- return 1;
- }
- }
- }
- }
-
- BLI_unlock_thread(LOCK_CUSTOM1);
- return 0;
-}
-
-/* already have tested for tface and ima and zspan */
-static void shade_tface(BakeShade *bs)
-{
- VlakRen *vlr= bs->vlr;
- ObjectInstanceRen *obi= bs->obi;
- ObjectRen *obr= obi->obr;
- MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0);
- Image *ima= tface->tpage;
- float vec[4][2];
- int a, i1, i2, i3;
-
- /* check valid zspan */
- if (ima!=bs->ima) {
- BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL);
-
- bs->ima= ima;
- bs->ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
- /* note, these calls only free/fill contents of zspan struct, not zspan itself */
- zbuf_free_span(bs->zspan);
- zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y, R.clipcrop);
- }
-
- bs->rectx= bs->ibuf->x;
- bs->recty= bs->ibuf->y;
- bs->rect= bs->ibuf->rect;
- bs->rect_colorspace= bs->ibuf->rect_colorspace;
- bs->rect_float= bs->ibuf->rect_float;
- bs->quad= 0;
-
- if (bs->use_mask) {
- if (bs->ibuf->userdata==NULL) {
- BLI_lock_thread(LOCK_CUSTOM1);
- if (bs->ibuf->userdata==NULL) /* since the thread was locked, its possible another thread alloced the value */
- bs->ibuf->userdata = (void *)MEM_callocN(sizeof(char)*bs->rectx*bs->recty, "BakeMask");
- bs->rect_mask= (char *)bs->ibuf->userdata;
- BLI_unlock_thread(LOCK_CUSTOM1);
- }
- else {
- bs->rect_mask= (char *)bs->ibuf->userdata;
- }
- }
-
- /* get pixel level vertex coordinates */
- for (a=0; a<4; a++) {
- /* Note, workaround for pixel aligned UVs which are common and can screw up our intersection tests
- * where a pixel gets in between 2 faces or the middle of a quad,
- * camera aligned quads also have this problem but they are less common.
- * Add a small offset to the UVs, fixes bug #18685 - Campbell */
- vec[a][0]= tface->uv[a][0]*(float)bs->rectx - (0.5f + 0.001f);
- vec[a][1]= tface->uv[a][1]*(float)bs->recty - (0.5f + 0.002f);
- }
-
- /* UV indices have to be corrected for possible quad->tria splits */
- i1= 0; i2= 1; i3= 2;
- vlr_set_uv_indices(vlr, &i1, &i2, &i3);
- bake_set_vlr_dxyco(bs, vec[i1], vec[i2], vec[i3]);
- zspan_scanconvert(bs->zspan, bs, vec[i1], vec[i2], vec[i3], do_bake_shade);
-
- if (vlr->v4) {
- bs->quad= 1;
- bake_set_vlr_dxyco(bs, vec[0], vec[2], vec[3]);
- zspan_scanconvert(bs->zspan, bs, vec[0], vec[2], vec[3], do_bake_shade);
- }
-}
-
-static void *do_bake_thread(void *bs_v)
-{
- BakeShade *bs= bs_v;
-
- while (get_next_bake_face(bs)) {
- shade_tface(bs);
-
- /* fast threadsafe break test */
- if (R.test_break(R.tbh))
- break;
-
- /* access is not threadsafe but since its just true/false probably ok
- * only used for interactive baking */
- if (bs->do_update)
- *bs->do_update= TRUE;
- }
- bs->ready= 1;
-
- BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL);
-
- return NULL;
-}
-
-void RE_bake_ibuf_filter(ImBuf *ibuf, char *mask, const int filter)
-{
- /* must check before filtering */
- const short is_new_alpha= (ibuf->planes != R_IMF_PLANES_RGBA) && BKE_imbuf_alpha_test(ibuf);
-
- /* Margin */
- if (filter) {
- IMB_filter_extend(ibuf, mask, filter);
- }
-
- /* if the bake results in new alpha then change the image setting */
- if (is_new_alpha) {
- ibuf->planes= R_IMF_PLANES_RGBA;
- }
- else {
- if (filter && ibuf->planes != R_IMF_PLANES_RGBA) {
- /* clear alpha added by filtering */
- IMB_rectfill_alpha(ibuf, 1.0f);
- }
- }
-}
-
-/* using object selection tags, the faces with UV maps get baked */
-/* render should have been setup */
-/* returns 0 if nothing was handled */
-int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_update, float *progress)
-{
- BakeShade *handles;
- ListBase threads;
- Image *ima;
- int a, vdone = FALSE, use_mask = FALSE, result = BAKE_RESULT_OK;
-
- re->scene_color_manage = BKE_scene_check_color_management_enabled(re->scene);
-
- /* initialize render global */
- R= *re;
- R.bakebuf= NULL;
-
- /* initialize static vars */
- get_next_bake_face(NULL);
-
- /* do we need a mask? */
- if (re->r.bake_filter)
- use_mask = TRUE;
-
- /* baker uses this flag to detect if image was initialized */
- for (ima= G.main->image.first; ima; ima= ima->id.next) {
- ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
- ima->id.flag |= LIB_DOIT;
- ima->flag&= ~IMA_USED_FOR_RENDER;
- if (ibuf) {
- ibuf->userdata = NULL; /* use for masking if needed */
- }
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
-
- BLI_init_threads(&threads, do_bake_thread, re->r.threads);
-
- handles= MEM_callocN(sizeof(BakeShade)*re->r.threads, "BakeShade");
-
- /* get the threads running */
- for (a=0; a<re->r.threads; a++) {
- /* set defaults in handles */
- handles[a].ssamp.shi[0].lay= re->lay;
-
- if (type==RE_BAKE_SHADOW) {
- handles[a].ssamp.shi[0].passflag= SCE_PASS_SHADOW;
- }
- else {
- handles[a].ssamp.shi[0].passflag= SCE_PASS_COMBINED;
- }
- handles[a].ssamp.shi[0].combinedflag= ~(SCE_PASS_SPEC);
- handles[a].ssamp.shi[0].thread= a;
- handles[a].ssamp.tot= 1;
-
- handles[a].type= type;
- handles[a].actob= actob;
- handles[a].zspan= MEM_callocN(sizeof(ZSpan), "zspan for bake");
-
- handles[a].use_mask = use_mask;
-
- handles[a].do_update = do_update; /* use to tell the view to update */
-
- BLI_insert_thread(&threads, &handles[a]);
- }
-
- /* wait for everything to be done */
- a= 0;
- while (a!=re->r.threads) {
- PIL_sleep_ms(50);
-
- /* calculate progress */
- for (vdone = FALSE, a=0; a<re->r.threads; a++)
- vdone+= handles[a].vdone;
- if (progress)
- *progress = (float)(vdone / (float)re->totvlak);
-
- for (a=0; a<re->r.threads; a++) {
- if (handles[a].ready==0)
- break;
- }
- }
-
- /* filter and refresh images */
- for (ima= G.main->image.first; ima; ima= ima->id.next) {
- if ((ima->id.flag & LIB_DOIT)==0) {
- ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL);
-
- if (ima->flag & IMA_USED_FOR_RENDER)
- result= BAKE_RESULT_FEEDBACK_LOOP;
-
- if (!ibuf)
- continue;
-
- RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, re->r.bake_filter);
-
- ibuf->userflags |= IB_BITMAPDIRTY;
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
- }
-
- /* calculate return value */
- for (a=0; a<re->r.threads; a++) {
- zbuf_free_span(handles[a].zspan);
- MEM_freeN(handles[a].zspan);
- }
-
- MEM_freeN(handles);
-
- BLI_end_threads(&threads);
-
- if (vdone==0)
- result= BAKE_RESULT_NO_OBJECTS;
-
- return result;
-}
-
-struct Image *RE_bake_shade_get_image(void)
-{
- return R.bakebuf;
-}
-
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
index e189d8bdaea..8169250f74f 100644
--- a/source/blender/render/intern/source/renderdatabase.c
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -105,6 +105,8 @@
#define RE_MTFACE_ELEMS 1
#define RE_MCOL_ELEMS 4
#define RE_UV_ELEMS 2
+#define RE_VLAK_ORIGINDEX_ELEMS 1
+#define RE_VERT_ORIGINDEX_ELEMS 1
#define RE_SURFNOR_ELEMS 3
#define RE_RADFACE_ELEMS 1
#define RE_SIMPLIFY_ELEMS 2
@@ -192,10 +194,26 @@ float *RE_vertren_get_winspeed(ObjectInstanceRen *obi, VertRen *ver, int verify)
return winspeed + ver->index*RE_WINSPEED_ELEMS;
}
+int *RE_vertren_get_origindex(ObjectRen *obr, VertRen *ver, int verify)
+{
+ int *origindex;
+ int nr= ver->index>>8;
+
+ origindex= obr->vertnodes[nr].origindex;
+ if (origindex==NULL) {
+ if (verify)
+ origindex= obr->vertnodes[nr].origindex= MEM_mallocN(256*RE_VERT_ORIGINDEX_ELEMS*sizeof(int), "origindex table");
+ else
+ return NULL;
+ }
+ return origindex + (ver->index & 255)*RE_VERT_ORIGINDEX_ELEMS;
+}
+
VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver)
{
VertRen *v1= RE_findOrAddVert(obr, obr->totvert++);
float *fp1, *fp2;
+ int *int1, *int2;
int index= v1->index;
*v1= *ver;
@@ -221,6 +239,11 @@ VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver)
fp2= RE_vertren_get_tangent(obr, v1, 1);
memcpy(fp2, fp1, RE_TANGENT_ELEMS*sizeof(float));
}
+ int1= RE_vertren_get_origindex(obr, ver, 0);
+ if (int1) {
+ int2= RE_vertren_get_origindex(obr, v1, 1);
+ memcpy(int2, int1, RE_VERT_ORIGINDEX_ELEMS*sizeof(int));
+ }
return v1;
}
@@ -332,6 +355,21 @@ MCol *RE_vlakren_get_mcol(ObjectRen *obr, VlakRen *vlr, int n, char **name, int
return node->mcol + index*RE_MCOL_ELEMS;
}
+int *RE_vlakren_get_origindex(ObjectRen *obr, VlakRen *vlak, int verify)
+{
+ int *origindex;
+ int nr= vlak->index>>8;
+
+ origindex= obr->vlaknodes[nr].origindex;
+ if (origindex==NULL) {
+ if (verify)
+ origindex= obr->vlaknodes[nr].origindex= MEM_callocN(256*RE_VLAK_ORIGINDEX_ELEMS*sizeof(int), "origindex table");
+ else
+ return NULL;
+ }
+ return origindex + (vlak->index & 255)*RE_VLAK_ORIGINDEX_ELEMS;
+}
+
float *RE_vlakren_get_surfnor(ObjectRen *obr, VlakRen *vlak, int verify)
{
float *surfnor;
@@ -370,7 +408,7 @@ RadFace **RE_vlakren_get_radface(ObjectRen *obr, VlakRen *vlak, int verify)
radface= obr->vlaknodes[nr].radface;
if (radface==NULL) {
if (verify)
- radface= obr->vlaknodes[nr].radface= MEM_callocN(256*RE_RADFACE_ELEMS*sizeof(void*), "radface table");
+ radface = obr->vlaknodes[nr].radface= MEM_callocN(256 * RE_RADFACE_ELEMS * sizeof(void *), "radface table");
else
return NULL;
}
@@ -383,6 +421,7 @@ VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr)
MTFace *mtface, *mtface1;
MCol *mcol, *mcol1;
float *surfnor, *surfnor1, *tangent, *tangent1;
+ int *origindex, *origindex1;
RadFace **radface, **radface1;
int i, index = vlr1->index;
char *name;
@@ -400,6 +439,13 @@ VlakRen *RE_vlakren_copy(ObjectRen *obr, VlakRen *vlr)
memcpy(mcol1, mcol, sizeof(MCol)*RE_MCOL_ELEMS);
}
+ origindex= RE_vlakren_get_origindex(obr, vlr, 0);
+ if (origindex) {
+ origindex1= RE_vlakren_get_origindex(obr, vlr1, 1);
+ /* Just an int, but memcpy for consistency. */
+ memcpy(origindex1, origindex, sizeof(int)*RE_VLAK_ORIGINDEX_ELEMS);
+ }
+
surfnor= RE_vlakren_get_surfnor(obr, vlr, 0);
if (surfnor) {
surfnor1= RE_vlakren_get_surfnor(obr, vlr1, 1);
@@ -725,6 +771,8 @@ void free_renderdata_vertnodes(VertTableNode *vertnodes)
MEM_freeN(vertnodes[a].stress);
if (vertnodes[a].winspeed)
MEM_freeN(vertnodes[a].winspeed);
+ if (vertnodes[a].origindex)
+ MEM_freeN(vertnodes[a].origindex);
}
MEM_freeN(vertnodes);
@@ -743,6 +791,8 @@ void free_renderdata_vlaknodes(VlakTableNode *vlaknodes)
MEM_freeN(vlaknodes[a].mtface);
if (vlaknodes[a].mcol)
MEM_freeN(vlaknodes[a].mcol);
+ if (vlaknodes[a].origindex)
+ MEM_freeN(vlaknodes[a].origindex);
if (vlaknodes[a].surfnor)
MEM_freeN(vlaknodes[a].surfnor);
if (vlaknodes[a].tangent)
@@ -888,9 +938,9 @@ HaloRen *RE_findOrAddHalo(ObjectRen *obr, int nr)
// TABLEINITSIZE, obr->blohalen+TABLEINITSIZE );
temp=obr->bloha;
- obr->bloha=(HaloRen**)MEM_callocN(sizeof(void*)*(obr->blohalen+TABLEINITSIZE), "Bloha");
- if (temp) memcpy(obr->bloha, temp, obr->blohalen*sizeof(void*));
- memset(&(obr->bloha[obr->blohalen]), 0, TABLEINITSIZE*sizeof(void*));
+ obr->bloha = (HaloRen **)MEM_callocN(sizeof(void *) * (obr->blohalen + TABLEINITSIZE), "Bloha");
+ if (temp) memcpy(obr->bloha, temp, obr->blohalen*sizeof(void *));
+ memset(&(obr->bloha[obr->blohalen]), 0, TABLEINITSIZE * sizeof(void *));
obr->blohalen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/
if (temp) MEM_freeN(temp);
}
@@ -1001,7 +1051,7 @@ HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,
}
}
- externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0);
+ externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool);
yn= tin*mtex->colfac;
//zn= tin*mtex->alphafac;
@@ -1020,6 +1070,8 @@ HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma,
}
}
+ har->pool = re->pool;
+
return har;
}
@@ -1130,7 +1182,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);
+ hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool);
//yn= tin*mtex->colfac;
//zn= tin*mtex->alphafac;
@@ -1173,6 +1225,8 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater
//}
}
+ har->pool = re->pool;
+
return har;
}
diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c
index 078c11a2061..1a24055c7f4 100644
--- a/source/blender/render/intern/source/shadbuf.c
+++ b/source/blender/render/intern/source/shadbuf.c
@@ -38,10 +38,6 @@
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
-#include "BKE_global.h"
-#include "BKE_scene.h"
-
-
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_jitter.h"
@@ -49,6 +45,9 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_scene.h"
+
#include "PIL_time.h"
#include "renderpipeline.h"
@@ -812,7 +811,7 @@ void makeshadowbuf(Render *re, LampRen *lar)
static void *do_shadow_thread(void *re_v)
{
- Render *re= (Render*)re_v;
+ Render *re = (Render *)re_v;
LampRen *lar;
do {
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index db93a21de2d..bf0087d0292 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -151,6 +151,7 @@ void shade_material_loop(ShadeInput *shi, ShadeResult *shr)
/* do a shade, finish up some passes, apply mist */
void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr)
{
+ bool compat = false;
float alpha;
/* ------ main shading loop -------- */
@@ -158,10 +159,11 @@ 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) {
- ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
- }
- else {
+ 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 */
shade_input_init_material(shi);
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
index 597196f464b..003e74bd69a 100644
--- a/source/blender/render/intern/source/shadeoutput.c
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -1713,6 +1713,14 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
if (ma->mode & (MA_FACETEXTURE_ALPHA))
shi->alpha= shi->vcol[3];
}
+#ifdef WITH_FREESTYLE
+ else if (ma->vcol_alpha) {
+ shi->r= shi->vcol[0];
+ shi->g= shi->vcol[1];
+ shi->b= shi->vcol[2];
+ shi->alpha= shi->vcol[3];
+ }
+#endif
else if (ma->mode & (MA_VERTEXCOLP)) {
float neg_alpha = 1.0f - shi->vcol[3];
shi->r= shi->r*neg_alpha + shi->vcol[0]*shi->vcol[3];
@@ -1884,7 +1892,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
/* note: shi->mode! */
if (shi->mode & MA_TRANSP && (shi->mode & (MA_ZTRANSP|MA_RAYTRANSP))) {
if (shi->spectra!=0.0f) {
- float t = MAX3(shr->spec[0], shr->spec[1], shr->spec[2]);
+ float t = max_fff(shr->spec[0], shr->spec[1], shr->spec[2]);
t *= shi->spectra;
if (t>1.0f) t= 1.0f;
shi->alpha= (1.0f-t)*shi->alpha+t;
diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c
index 6d0e15ea46e..9d6391ccb59 100644
--- a/source/blender/render/intern/source/sss.c
+++ b/source/blender/render/intern/source/sss.c
@@ -55,6 +55,8 @@
#include "BLI_ghash.h"
#include "BLI_memarena.h"
+#include "BLF_translation.h"
+
#include "PIL_time.h"
#include "DNA_material_types.h"
@@ -994,7 +996,7 @@ void make_sss_tree(Render *re)
re->sss_hash= BLI_ghash_ptr_new("make_sss_tree gh");
- re->i.infostr= "SSS preprocessing";
+ re->i.infostr = IFACE_("SSS preprocessing");
re->stats_draw(re->sdh, &re->i);
for (mat= re->main->mat.first; mat; mat= mat->id.next)
@@ -1016,7 +1018,7 @@ void free_sss(Render *re)
if (re->sss_hash) {
GHashIterator *it= BLI_ghashIterator_new(re->sss_hash);
- while (!BLI_ghashIterator_isDone(it)) {
+ while (BLI_ghashIterator_notDone(it)) {
sss_free_tree(BLI_ghashIterator_getValue(it));
BLI_ghashIterator_step(it);
}
diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c
index 569bac29205..8b83ca4b6c3 100644
--- a/source/blender/render/intern/source/strand.c
+++ b/source/blender/render/intern/source/strand.c
@@ -522,7 +522,7 @@ static APixstrand *addpsAstrand(ZSpan *zspan)
static void do_strand_fillac(void *handle, int x, int y, float u, float v, float z)
{
- StrandPart *spart= (StrandPart*)handle;
+ StrandPart *spart= (StrandPart *)handle;
StrandShadeCache *cache= spart->cache;
StrandSegment *sseg= spart->segment;
APixstrand *apn, *apnew;
@@ -676,14 +676,14 @@ static void strand_render(Render *re, StrandSegment *sseg, float winmat[4][4], S
else {
float hoco1[4], hoco2[4];
int a, obi, index;
-
+
obi= sseg->obi - re->objectinstance;
index= sseg->strand->index;
projectvert(p1->co, winmat, hoco1);
projectvert(p2->co, winmat, hoco2);
-
+
for (a=0; a<totzspan; a++) {
#if 0
/* render both strand and single pixel wire to counter aliasing */
diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c
index 8757be740f3..028217b8609 100644
--- a/source/blender/render/intern/source/volume_precache.c
+++ b/source/blender/render/intern/source/volume_precache.c
@@ -43,6 +43,8 @@
#include "BLI_voxel.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "PIL_time.h"
#include "RE_shader_ext.h"
@@ -354,7 +356,7 @@ static void ms_diffuse(Render *re, int do_test_break, float *x0, float *x, float
static void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Material *ma)
{
const float diff = ma->vol.ms_diff * 0.001f; /* compensate for scaling for a nicer UI range */
- const int simframes = (int)(ma->vol.ms_spread * (float)MAX3(vp->res[0], vp->res[1], vp->res[2]));
+ const int simframes = (int)(ma->vol.ms_spread * (float)max_iii(vp->res[0], vp->res[1], vp->res[2]));
const int shade_type = ma->vol.shade_type;
float fac = ma->vol.ms_intensity;
@@ -400,10 +402,11 @@ static void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Materi
/* Displays progress every second */
if (time-lasttime>1.0) {
char str[64];
- BLI_snprintf(str, sizeof(str), "Simulating multiple scattering: %d%%", (int)(100.0f * (c / total)));
- re->i.infostr= str;
+ BLI_snprintf(str, sizeof(str), IFACE_("Simulating multiple scattering: %d%%"),
+ (int)(100.0f * (c / total)));
+ re->i.infostr = str;
re->stats_draw(re->sdh, &re->i);
- re->i.infostr= NULL;
+ re->i.infostr = NULL;
lasttime= time;
}
}
@@ -493,7 +496,7 @@ typedef struct VolPrecacheQueue {
*/
static void *vol_precache_part(void *data)
{
- VolPrecacheQueue *queue = (VolPrecacheQueue*)data;
+ VolPrecacheQueue *queue = (VolPrecacheQueue *)data;
VolPrecachePart *pa;
while ((pa = BLI_thread_queue_pop(queue->work))) {
@@ -652,7 +655,7 @@ static int precache_resolution(Render *re, VolumePrecache *vp, ObjectInstanceRen
global_bounds_obi(re, obi, bbmin, bbmax);
sub_v3_v3v3(dim, bbmax, bbmin);
- div = MAX3(dim[0], dim[1], dim[2]);
+ div = max_fff(dim[0], dim[1], dim[2]);
dim[0] /= div;
dim[1] /= div;
dim[2] /= div;
@@ -742,11 +745,12 @@ static void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *o
time= PIL_check_seconds_timer();
if (time-lasttime>1.0) {
char str[64];
- BLI_snprintf(str, sizeof(str), "Precaching volume: %d%%", (int)(100.0f * ((float)counter / (float)totparts)));
- re->i.infostr= str;
+ BLI_snprintf(str, sizeof(str), IFACE_("Precaching volume: %d%%"),
+ (int)(100.0f * ((float)counter / (float)totparts)));
+ re->i.infostr = str;
re->stats_draw(re->sdh, &re->i);
- re->i.infostr= NULL;
- lasttime= time;
+ re->i.infostr = NULL;
+ lasttime = time;
}
}
@@ -784,7 +788,7 @@ void volume_precache(Render *re)
ObjectInstanceRen *obi;
VolumeOb *vo;
- re->i.infostr= "Volume preprocessing";
+ re->i.infostr = IFACE_("Volume preprocessing");
re->stats_draw(re->sdh, &re->i);
for (vo= re->volumes.first; vo; vo= vo->next) {
@@ -803,7 +807,7 @@ void volume_precache(Render *re)
}
}
- re->i.infostr= NULL;
+ re->i.infostr = NULL;
re->stats_draw(re->sdh, &re->i);
}
diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c
index 77d6644479a..9990ad7e900 100644
--- a/source/blender/render/intern/source/voxeldata.c
+++ b/source/blender/render/intern/source/voxeldata.c
@@ -34,6 +34,10 @@
#include <stdlib.h>
#include <stdio.h>
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
@@ -41,6 +45,8 @@
#include "BLI_voxel.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -185,7 +191,7 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex)
for (y = 0; y < ibuf->y; y++) {
for (x = 0; x < ibuf->x; x++) {
/* currently averaged to monchrome */
- vd->dataset[BLI_VOXEL_INDEX(x, y, z, vd->resol)] = (rf[0] + rf[1] + rf[2]) * 0.333f;
+ vd->dataset[BLI_VOXEL_INDEX(x, y, z, vd->resol)] = (rf[0] + rf[1] + rf[2]) / 3.0f;
rf += 4;
}
}
@@ -400,7 +406,7 @@ void make_voxeldata(struct Render *re)
{
Tex *tex;
- re->i.infostr = "Loading voxel datasets";
+ re->i.infostr = IFACE_("Loading voxel datasets");
re->stats_draw(re->sdh, &re->i);
/* XXX: should be doing only textures used in this render */
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index 2e1b23435e5..a0267cd65b7 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -4148,8 +4148,17 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
}
if (addpassflag & SCE_PASS_INDEXMA) {
ObjectRen *obr = R.objectinstance[zrow[totface-1].obi].obr;
- VlakRen *vr = obr->vlaknodes->vlak;
- Material *mat = vr->mat;
+ Material *mat = NULL;
+
+ if (zrow[totface-1].segment == -1) {
+ if (obr->vlaknodes)
+ mat = obr->vlaknodes->vlak->mat;
+ }
+ else {
+ if (obr->strandbuf)
+ mat = obr->strandbuf->ma;
+ }
+
if (mat) {
for (a= 0; a<totfullsample; a++)
add_transp_material_index(rlpp[a], od, mat);
diff --git a/source/blender/windowmanager/SConscript b/source/blender/windowmanager/SConscript
index 68fdbec2cfa..6db0e142ac4 100644
--- a/source/blender/windowmanager/SConscript
+++ b/source/blender/windowmanager/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
import os
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 8d885bf6d6f..2fd80d17bb7 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -56,11 +56,13 @@ struct wmOperatorType;
struct wmOperator;
struct rcti;
struct PointerRNA;
+struct PropertyRNA;
struct EnumPropertyItem;
struct MenuType;
struct wmDropBox;
struct wmDrag;
struct ImBuf;
+struct ImageFormatData;
typedef struct wmJob wmJob;
@@ -68,6 +70,7 @@ typedef struct wmJob wmJob;
void WM_init_state_size_set (int stax, int stay, int sizx, int sizy);
void WM_init_state_fullscreen_set(void);
void WM_init_state_normal_set(void);
+void WM_init_native_pixels(int do_it);
void WM_init (struct bContext *C, int argc, const char **argv);
void WM_exit_ext (struct bContext *C, const short do_python);
@@ -92,21 +95,23 @@ void WM_check (struct bContext *C);
struct wmWindow *WM_window_open (struct bContext *C, struct rcti *rect);
+int WM_window_pixels_x (struct wmWindow *win);
+int WM_window_pixels_y (struct wmWindow *win);
+
/* defines for 'type' WM_window_open_temp */
#define WM_WINDOW_RENDER 0
#define WM_WINDOW_USERPREFS 1
#define WM_WINDOW_FILESEL 2
void WM_window_open_temp (struct bContext *C, struct rcti *position, int type);
+
+ /* returns true if draw method is triple buffer */
+int WM_is_draw_triple(struct wmWindow *win);
/* files */
-int WM_homefile_read_exec(struct bContext *C, struct wmOperator *op);
-int WM_homefile_read(struct bContext *C, struct ReportList *reports, short from_memory);
-int WM_homefile_write_exec(struct bContext *C, struct wmOperator *op);
void WM_file_read(struct bContext *C, const char *filepath, struct ReportList *reports);
-int WM_file_write(struct bContext *C, const char *target, int fileflags, struct ReportList *reports);
void WM_autosave_init(struct wmWindowManager *wm);
/* mouse cursors */
@@ -126,6 +131,7 @@ void *WM_paint_cursor_activate(struct wmWindowManager *wm,
void WM_paint_cursor_end(struct wmWindowManager *wm, void *handle);
void WM_cursor_warp (struct wmWindow *win, int x, int y);
+float WM_cursor_pressure (const struct wmWindow *win);
/* event map */
int WM_userdef_event_map(int kmitype);
@@ -140,12 +146,15 @@ struct wmEventHandler *WM_event_add_keymap_handler_priority(ListBase *handlers,
void WM_event_remove_keymap_handler(ListBase *handlers, wmKeyMap *keymap);
-struct wmEventHandler *WM_event_add_ui_handler(const struct bContext *C, ListBase *handlers,
- int (*func)(struct bContext *C, struct wmEvent *event, void *userdata),
- void (*remove)(struct bContext *C, void *userdata), void *userdata);
+struct wmEventHandler *WM_event_add_ui_handler(
+ const struct bContext *C, ListBase *handlers,
+ int (*func)(struct bContext *C, const struct wmEvent *event, void *userdata),
+ void (*remove)(struct bContext *C, void *userdata), void *userdata);
+
void WM_event_remove_ui_handler(ListBase *handlers,
- int (*func)(struct bContext *C, struct wmEvent *event, void *userdata),
- void (*remove)(struct bContext *C, void *userdata), void *userdata, int postpone);
+ int (*func)(struct bContext *C, const struct wmEvent *event, void *userdata),
+ void (*remove)(struct bContext *C, void *userdata),
+ void *userdata, int postpone);
void WM_event_remove_area_handler(struct ListBase *handlers, void *area);
struct wmEventHandler *WM_event_add_modal_handler(struct bContext *C, struct wmOperator *op);
@@ -156,13 +165,13 @@ struct wmEventHandler *WM_event_add_dropbox_handler(ListBase *handlers, ListBase
/* mouse */
void WM_event_add_mousemove(struct bContext *C);
void WM_event_add_mousemove_window(struct wmWindow *window);
-int WM_modal_tweak_exit(struct wmEvent *evt, int tweak_event);
+int WM_modal_tweak_exit(const struct wmEvent *event, int tweak_event);
/* notifiers */
void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference);
void WM_main_add_notifier(unsigned int type, void *reference);
-void wm_event_add (struct wmWindow *win, struct wmEvent *event_to_add); /* XXX only for warning */
+void wm_event_add(struct wmWindow *win, const struct wmEvent *event_to_add);
/* 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);
@@ -171,19 +180,19 @@ void WM_event_timer_sleep(struct wmWindowManager *wm, struct wmWindow *win, str
/* operator api, default callbacks */
/* invoke callback, uses enum property named "type" */
-int WM_operator_view3d_distance_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
-int WM_menu_invoke (struct bContext *C, struct wmOperator *op, struct wmEvent *event);
-int WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
+int WM_operator_view3d_distance_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
+int WM_menu_invoke (struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
+int WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
/* invoke callback, confirm menu + exec */
-int WM_operator_confirm (struct bContext *C, struct wmOperator *op, struct wmEvent *event);
+int WM_operator_confirm (struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
/* invoke callback, file selector "filepath" unset + exec */
-int WM_operator_filesel (struct bContext *C, struct wmOperator *op, struct wmEvent *event);
-int WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const char imtype);
+int WM_operator_filesel (struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
+int WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFormatData *im_format);
/* poll callback, context checks */
int WM_operator_winactive (struct bContext *C);
/* invoke callback, exec + redo popup */
-int WM_operator_props_popup_call(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
-int WM_operator_props_popup (struct bContext *C, struct wmOperator *op, struct wmEvent *event);
+int WM_operator_props_popup_call(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
+int WM_operator_props_popup (struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
int WM_operator_props_dialog_popup (struct bContext *C, struct wmOperator *op, int width, int height);
int WM_operator_redo_popup (struct bContext *C, struct wmOperator *op);
int WM_operator_ui_popup (struct bContext *C, struct wmOperator *op, int width, int height);
@@ -193,12 +202,13 @@ int WM_operator_confirm_message(struct bContext *C, struct wmOperator *op, con
/* operator api */
void WM_operator_free (struct wmOperator *op);
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 *idnamem, int quiet);
struct GHashIterator *WM_operatortype_iter(void);
-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_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);
int WM_operatortype_remove(const char *idname);
struct wmOperatorType *WM_operatortype_append_macro(const char *idname, const char *name, const char *description, int flag);
@@ -224,9 +234,9 @@ void WM_operator_properties_free(struct PointerRNA *ptr);
void WM_operator_properties_filesel(struct wmOperatorType *ot, int filter, short type, short action, short flag, short display);
void WM_operator_properties_border(struct wmOperatorType *ot);
void WM_operator_properties_border_to_rcti(struct wmOperator *op, struct rcti *rect);
-void WM_operator_properties_gesture_border(struct wmOperatorType *ot, int extend);
+void WM_operator_properties_gesture_border(struct wmOperatorType *ot, bool extend);
void WM_operator_properties_mouse_select(struct wmOperatorType *ot);
-void WM_operator_properties_gesture_straightline(struct wmOperatorType *ot, int cursor);
+void WM_operator_properties_gesture_straightline(struct wmOperatorType *ot, bool cursor);
void WM_operator_properties_select_all(struct wmOperatorType *ot);
int WM_operator_check_ui_enabled(const struct bContext *C, const char *idname);
@@ -253,9 +263,17 @@ int WM_operator_last_properties_store(struct wmOperator *op);
/* operator as a python command (resultuing string must be freed) */
char *WM_operator_pystring(struct bContext *C, struct wmOperatorType *ot, struct PointerRNA *opptr, int all_args);
+char *WM_prop_pystring_assign(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, int index);
void WM_operator_bl_idname(char *to, const char *from);
void WM_operator_py_idname(char *to, const char *from);
+/* *************** uilist types ******************** */
+void WM_uilisttype_init(void);
+struct uiListType *WM_uilisttype_find(const char *idname, int quiet);
+int WM_uilisttype_add(struct uiListType *ult);
+void WM_uilisttype_freelink(struct uiListType *ult);
+void WM_uilisttype_free(void);
+
/* *************** menu types ******************** */
void WM_menutype_init(void);
struct MenuType *WM_menutype_find(const char *idname, int quiet);
@@ -264,41 +282,43 @@ void WM_menutype_freelink(struct MenuType *mt);
void WM_menutype_free(void);
/* default operator callbacks for border/circle/lasso */
-int WM_border_select_invoke (struct bContext *C, struct wmOperator *op, struct wmEvent *event);
-int WM_border_select_modal (struct bContext *C, struct wmOperator *op, struct wmEvent *event);
+int WM_border_select_invoke (struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
+int WM_border_select_modal (struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
int WM_border_select_cancel(struct bContext *C, struct wmOperator *op);
-int WM_gesture_circle_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
-int WM_gesture_circle_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
+int WM_gesture_circle_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
+int WM_gesture_circle_modal(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
int WM_gesture_circle_cancel(struct bContext *C, struct wmOperator *op);
-int WM_gesture_lines_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
-int WM_gesture_lines_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
+int WM_gesture_lines_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
+int WM_gesture_lines_modal(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
int WM_gesture_lines_cancel(struct bContext *C, struct wmOperator *op);
-int WM_gesture_lasso_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
-int WM_gesture_lasso_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
+int WM_gesture_lasso_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
+int WM_gesture_lasso_modal(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
int WM_gesture_lasso_cancel(struct bContext *C, struct wmOperator *op);
const int (*WM_gesture_lasso_path_to_array(struct bContext *C, struct wmOperator *op, int *mcords_tot))[2];
-int WM_gesture_straightline_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
-int WM_gesture_straightline_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
+int WM_gesture_straightline_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
+int WM_gesture_straightline_modal(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
int WM_gesture_straightline_cancel(struct bContext *C, struct wmOperator *op);
/* Gesture manager API */
-struct wmGesture *WM_gesture_new(struct bContext *C, struct wmEvent *event, int type);
+struct wmGesture *WM_gesture_new(struct bContext *C, const struct wmEvent *event, int type);
void WM_gesture_end(struct bContext *C, struct wmGesture *gesture);
void WM_gestures_remove(struct bContext *C);
/* fileselecting support */
void WM_event_add_fileselect(struct bContext *C, struct wmOperator *op);
-void WM_event_fileselect_event(struct bContext *C, void *ophandle, int eventval);
+void WM_event_fileselect_event(struct wmWindowManager *wm, void *ophandle, int eventval);
#ifndef NDEBUG
-void WM_event_print(struct wmEvent *event);
+void WM_event_print(const struct wmEvent *event);
#endif
+void WM_operator_region_active_win_set(struct bContext *C);
+
/* drag and drop */
struct wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value);
void WM_event_drag_image(struct wmDrag *, struct ImBuf *, float scale, int sx, int sy);
-struct wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(struct bContext *, struct wmDrag *, struct wmEvent *event),
- void (*copy)(struct wmDrag *, struct wmDropBox *));
+struct wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(struct bContext *, struct wmDrag *, const struct wmEvent *event),
+ void (*copy)(struct wmDrag *, struct wmDropBox *));
ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid);
/* Set a subwindow active in pixelspace view, with optional scissor subset */
@@ -336,6 +356,7 @@ enum {
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,
/* add as needed, screencast, seq proxy build
* if having hard coded values is a problem */
@@ -365,6 +386,7 @@ void WM_jobs_kill_all_except(struct wmWindowManager *wm, void *owner);
void WM_jobs_kill_type(struct wmWindowManager *wm, int job_type);
int WM_jobs_has_running(struct wmWindowManager *wm);
+int WM_jobs_has_running_except(struct wmWindowManager *wm, int job_type);
/* clipboard */
char *WM_clipboard_text_get(int selection);
diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h
index 43369154dbb..49ee759bbf2 100644
--- a/source/blender/windowmanager/WM_keymap.h
+++ b/source/blender/windowmanager/WM_keymap.h
@@ -64,7 +64,7 @@ wmKeyMapItem *WM_keymap_add_menu(struct wmKeyMap *keymap, const char *idname, in
int val, int modifier, int keymodifier);
int WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi);
-char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len);
+int WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, const int len);
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);
@@ -81,6 +81,7 @@ wmKeyMap *WM_modalkeymap_add(struct wmKeyConfig *keyconf, const char *idname, st
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);
wmKeyMapItem *WM_modalkeymap_add_item_str(struct wmKeyMap *km, int type, int val, int modifier, int keymodifier, const char *value);
+wmKeyMapItem *WM_modalkeymap_find_propvalue(wmKeyMap *km, const int propvalue);
void WM_modalkeymap_assign(struct wmKeyMap *km, const char *opname);
/* Keymap Editor */
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 347f46c8166..c823810fc75 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -188,7 +188,7 @@ enum {
#define WM_UI_HANDLER_CONTINUE 0
#define WM_UI_HANDLER_BREAK 1
-typedef int (*wmUIHandlerFunc)(struct bContext *C, struct wmEvent *event, void *userdata);
+typedef int (*wmUIHandlerFunc)(struct bContext *C, const struct wmEvent *event, void *userdata);
typedef void (*wmUIHandlerRemoveFunc)(struct bContext *C, void *userdata);
/* ************** Notifiers ****************** */
@@ -239,6 +239,7 @@ typedef struct wmNotifier {
#define NC_MOVIECLIP (20<<24)
#define NC_MASK (21<<24)
#define NC_GPENCIL (22<<24)
+#define NC_LINESTYLE (23<<24)
/* data type, 256 entries is enough, it can overlap */
#define NOTE_DATA 0x00FF0000
@@ -407,6 +408,9 @@ typedef struct wmGesture {
/* customdata for circle is recti, (xmin, ymin) is center, xmax radius */
/* customdata for lasso is short array */
/* customdata for straight line is a recti: (xmin,ymin) is start, (xmax, ymax) is end */
+
+ /* free pointer to use for operator allocs (if set, its freed on exit)*/
+ void *userdata;
} wmGesture;
/* ************** wmEvent ************************ */
@@ -442,7 +446,10 @@ typedef struct wmEvent {
/* keymap item, set by handler (weak?) */
const char *keymap_idname;
-
+
+ /* tablet info, only use when the tablet is active */
+ struct wmTabletData *tablet_data;
+
/* custom data */
short custom; /* custom data type, stylus, 6dof, see wm_event_types.h */
short customdatafree;
@@ -506,6 +513,7 @@ typedef struct wmTimer {
typedef struct wmOperatorType {
const char *name; /* text for ui, undo */
const char *idname; /* unique identifier */
+ const char *translation_context;
const char *description; /* tooltips and python docs */
/* this callback executes the operator without any interactive input,
@@ -528,13 +536,13 @@ typedef struct wmOperatorType {
* any further events are handled in modal. if the operation is
* canceled due to some external reason, cancel is called
* - see defines below for return values */
- int (*invoke)(struct bContext *, struct wmOperator *, struct wmEvent *)
+ int (*invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *)
#ifdef __GNUC__
__attribute__((warn_unused_result))
#endif
;
int (*cancel)(struct bContext *, struct wmOperator *);
- int (*modal)(struct bContext *, struct wmOperator *, struct wmEvent *)
+ int (*modal)(struct bContext *, struct wmOperator *, const struct wmEvent *)
#ifdef __GNUC__
__attribute__((warn_unused_result))
#endif
@@ -639,7 +647,7 @@ typedef struct wmDropBox {
struct wmDropBox *next, *prev;
/* test if the dropbox is active, then can print optype name */
- int (*poll)(struct bContext *, struct wmDrag *, wmEvent *);
+ int (*poll)(struct bContext *, struct wmDrag *, const wmEvent *);
/* before exec, this copies drag info to wmDrop properties */
void (*copy)(struct wmDrag *, struct wmDropBox *);
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 8fe387765ce..29e0fcf302f 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -149,7 +149,88 @@ void WM_operator_stack_clear(wmWindowManager *wm)
WM_main_add_notifier(NC_WM | ND_HISTORY, NULL);
}
-/* ****************************************** */
+/**
+ * This function is needed in the case when an addon id disabled
+ * while a modal operator it defined is running.
+ */
+void WM_operator_handlers_clear(wmWindowManager *wm, wmOperatorType *ot)
+{
+ wmWindow *win;
+ for (win = wm->windows.first; win; win = win->next) {
+ ListBase *lb[2] = {&win->handlers, &win->modalhandlers};
+ wmEventHandler *handler;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ for (handler = lb[i]->first; handler; handler = handler->next) {
+ if (handler->op && handler->op->type == ot) {
+ /* don't run op->cancel because it needs the context,
+ * assume whoever unregisters the operator will cleanup */
+ handler->flag |= WM_HANDLER_DO_FREE;
+ WM_operator_free(handler->op);
+ handler->op = NULL;
+ }
+ }
+ }
+ }
+}
+
+/* ************ uiListType handling ************** */
+
+static GHash *uilisttypes_hash = NULL;
+
+uiListType *WM_uilisttype_find(const char *idname, int quiet)
+{
+ uiListType *ult;
+
+ if (idname[0]) {
+ ult = BLI_ghash_lookup(uilisttypes_hash, idname);
+ if (ult) {
+ return ult;
+ }
+ }
+
+ if (!quiet) {
+ printf("search for unknown uilisttype %s\n", idname);
+ }
+
+ return NULL;
+}
+
+int WM_uilisttype_add(uiListType *ult)
+{
+ BLI_ghash_insert(uilisttypes_hash, (void *)ult->idname, ult);
+ return 1;
+}
+
+void WM_uilisttype_freelink(uiListType *ult)
+{
+ BLI_ghash_remove(uilisttypes_hash, ult->idname, NULL, (GHashValFreeFP)MEM_freeN);
+}
+
+/* called on initialize WM_init() */
+void WM_uilisttype_init(void)
+{
+ uilisttypes_hash = BLI_ghash_str_new("uilisttypes_hash gh");
+}
+
+void WM_uilisttype_free(void)
+{
+ GHashIterator *iter = BLI_ghashIterator_new(uilisttypes_hash);
+
+ for (; BLI_ghashIterator_notDone(iter); BLI_ghashIterator_step(iter)) {
+ uiListType *ult = BLI_ghashIterator_getValue(iter);
+ if (ult->ext.free) {
+ ult->ext.free(ult->ext.data);
+ }
+ }
+ BLI_ghashIterator_free(iter);
+
+ BLI_ghash_free(uilisttypes_hash, NULL, (GHashValFreeFP)MEM_freeN);
+ uilisttypes_hash = NULL;
+}
+
+/* ************ MenuType handling ************** */
static GHash *menutypes_hash = NULL;
@@ -190,7 +271,7 @@ void WM_menutype_free(void)
{
GHashIterator *iter = BLI_ghashIterator_new(menutypes_hash);
- for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
+ for (; BLI_ghashIterator_notDone(iter); BLI_ghashIterator_step(iter)) {
MenuType *mt = BLI_ghashIterator_getValue(iter);
if (mt->ext.free) {
mt->ext.free(mt->ext.data);
diff --git a/source/blender/windowmanager/intern/wm_apple.c b/source/blender/windowmanager/intern/wm_apple.c
index a7bd43986dd..842fc353699 100644
--- a/source/blender/windowmanager/intern/wm_apple.c
+++ b/source/blender/windowmanager/intern/wm_apple.c
@@ -77,7 +77,7 @@ static int checkAppleVideoCard(void)
if ((theErr == 0) && (value != 0)) {
theErr = CGLDescribeRenderer(rend, j, kCGLRPCompliant, &value);
if ((theErr == 0) && (value != 0)) {
- /*fprintf(stderr,"make it big\n");*/
+ /*fprintf(stderr, "make it big\n");*/
CGLDestroyRendererInfo(rend);
macPrefState = 8;
return 1;
diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c
index ebde6407a48..2e15d6158e8 100644
--- a/source/blender/windowmanager/intern/wm_cursors.c
+++ b/source/blender/windowmanager/intern/wm_cursors.c
@@ -35,6 +35,8 @@
#include "GHOST_C-api.h"
+#include "BLI_utildefines.h"
+
#include "BLO_sys_types.h"
#include "DNA_listBase.h"
@@ -44,8 +46,8 @@
#include "BKE_global.h"
#include "BKE_main.h"
-#include "WM_api.h"
#include "WM_types.h"
+#include "WM_api.h"
#include "wm_cursors.h"
/* XXX this still is mess from old code */
@@ -188,12 +190,26 @@ void WM_cursor_grab_enable(wmWindow *win, int wrap, int hide, int bounds[4])
* It helps not to get a stuck WM when hitting a breakpoint
* */
GHOST_TGrabCursorMode mode = GHOST_kGrabNormal;
-
- if (hide) mode = GHOST_kGrabHide;
- else if (wrap) mode = GHOST_kGrabWrap;
+ float fac = GHOST_GetNativePixelSize(win->ghostwin);
+
+ /* in case pixel coords differ from window/mouse coords */
+ if (bounds) {
+ bounds[0] /= fac;
+ bounds[1] /= fac;
+ bounds[2] /= fac;
+ bounds[3] /= fac;
+ }
+
+ if (hide) {
+ mode = GHOST_kGrabHide;
+ }
+ else if (wrap) {
+ mode = GHOST_kGrabWrap;
+ }
if ((G.debug & G_DEBUG) == 0) {
- if (win && win->ghostwin) {
+ if (win->ghostwin) {
const GHOST_TabletData *tabletdata = GHOST_GetTabletData(win->ghostwin);
+
/* Note: There is no tabletdata on Windows if no tablet device is connected. */
if (!tabletdata)
GHOST_SetCursorGrab(win->ghostwin, mode, bounds, NULL);
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index 0581000e07c..ed066117b28 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -103,7 +103,7 @@ ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid)
-wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(bContext *, wmDrag *, wmEvent *),
+wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(bContext *, wmDrag *, const wmEvent *),
void (*copy)(wmDrag *, wmDropBox *))
{
wmDropBox *drop = MEM_callocN(sizeof(wmDropBox), "wmDropBox");
@@ -323,7 +323,7 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
drag_rect_minmax(rect, x, y, x + drag->sx, y + drag->sy);
else {
glColor4f(1.0, 1.0, 1.0, 0.65); /* this blends texture */
- glaDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_UNSIGNED_BYTE, drag->imb->rect, drag->scale, drag->scale);
+ glaDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_UNSIGNED_BYTE, GL_NEAREST, drag->imb->rect, drag->scale, drag->scale);
}
}
else {
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index a92ed65392c..173a8237c02 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -49,6 +49,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_screen.h"
#include "GHOST_C-api.h"
@@ -431,22 +432,22 @@ static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
triple->target = GL_TEXTURE_RECTANGLE_ARB;
triple->nx = 1;
triple->ny = 1;
- triple->x[0] = win->sizex;
- triple->y[0] = win->sizey;
+ triple->x[0] = WM_window_pixels_x(win);
+ triple->y[0] = WM_window_pixels_y(win);
}
else if (GPU_non_power_of_two_support()) {
triple->target = GL_TEXTURE_2D;
triple->nx = 1;
triple->ny = 1;
- triple->x[0] = win->sizex;
- triple->y[0] = win->sizey;
+ triple->x[0] = WM_window_pixels_x(win);
+ triple->y[0] = WM_window_pixels_y(win);
}
else {
triple->target = GL_TEXTURE_2D;
triple->nx = 0;
triple->ny = 0;
- split_width(win->sizex, MAX_N_TEX, triple->x, &triple->nx);
- split_width(win->sizey, MAX_N_TEX, triple->y, &triple->ny);
+ split_width(WM_window_pixels_x(win), MAX_N_TEX, triple->x, &triple->nx);
+ split_width(WM_window_pixels_y(win), MAX_N_TEX, triple->y, &triple->ny);
}
/* generate texture names */
@@ -491,7 +492,7 @@ static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
return 1;
}
-static void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple)
+static void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple, float alpha)
{
float halfx, halfy, ratiox, ratioy;
int x, y, sizex, sizey, offx, offy;
@@ -500,8 +501,8 @@ static void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple)
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++) {
- sizex = (x == triple->nx - 1) ? win->sizex - offx : triple->x[x];
- sizey = (y == triple->ny - 1) ? win->sizey - offy : triple->y[y];
+ sizex = (x == triple->nx - 1) ? WM_window_pixels_x(win) - offx : triple->x[x];
+ sizey = (y == triple->ny - 1) ? WM_window_pixels_y(win) - offy : triple->y[y];
/* wmOrtho for the screen has this same offset */
ratiox = sizex;
@@ -519,7 +520,7 @@ static void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple)
glBindTexture(triple->target, triple->bind[x + y * triple->nx]);
- glColor3f(1.0f, 1.0f, 1.0f);
+ glColor4f(1.0f, 1.0f, 1.0f, alpha);
glBegin(GL_QUADS);
glTexCoord2f(halfx, halfy);
glVertex2f(offx, offy);
@@ -546,8 +547,8 @@ static void wm_triple_copy_textures(wmWindow *win, wmDrawTriple *triple)
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++) {
- sizex = (x == triple->nx - 1) ? win->sizex - offx : triple->x[x];
- sizey = (y == triple->ny - 1) ? win->sizey - offy : triple->y[y];
+ sizex = (x == triple->nx - 1) ? WM_window_pixels_x(win) - offx : triple->x[x];
+ sizey = (y == triple->ny - 1) ? WM_window_pixels_y(win) - offy : triple->y[y];
glBindTexture(triple->target, triple->bind[x + y * triple->nx]);
glCopyTexSubImage2D(triple->target, 0, 0, 0, offx, offy, sizex, sizey);
@@ -557,6 +558,20 @@ static void wm_triple_copy_textures(wmWindow *win, wmDrawTriple *triple)
glBindTexture(triple->target, 0);
}
+static void wm_draw_region_blend(wmWindow *win, ARegion *ar)
+{
+ float fac = ED_region_blend_factor(ar);
+
+ /* region blend always is 1, except when blend timer is running */
+ if (fac < 1.0f) {
+ wmSubWindowScissorSet(win, win->screen->mainwin, &ar->winrct);
+
+ glEnable(GL_BLEND);
+ wm_triple_draw_textures(win, win->drawdata, 1.0f - fac);
+ glDisable(GL_BLEND);
+ }
+}
+
static void wm_method_draw_triple(bContext *C, wmWindow *win)
{
wmWindowManager *wm = CTX_wm_manager(C);
@@ -572,7 +587,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
wmSubWindowSet(win, screen->mainwin);
- wm_triple_draw_textures(win, win->drawdata);
+ wm_triple_draw_textures(win, win->drawdata, 1.0f);
}
else {
win->drawdata = MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple");
@@ -591,11 +606,14 @@ 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) {
- CTX_wm_region_set(C, ar);
- ED_region_do_draw(C, ar);
- ED_area_overdraw_flush(sa, ar);
- CTX_wm_region_set(C, NULL);
- copytex = 1;
+
+ if (ar->overlap == 0) {
+ CTX_wm_region_set(C, ar);
+ ED_region_do_draw(C, ar);
+ ED_area_overdraw_flush(sa, ar);
+ CTX_wm_region_set(C, NULL);
+ copytex = 1;
+ }
}
}
@@ -610,10 +628,27 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
wm_triple_copy_textures(win, triple);
}
+ /* 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);
+ CTX_wm_region_set(C, NULL);
+
+ wm_draw_region_blend(win, ar);
+ }
+ }
+
+ CTX_wm_area_set(C, NULL);
+ }
+
/* after area regions so we can do area 'overlay' drawing */
ED_screen_draw(win);
- /* draw overlapping regions */
+ /* draw floating regions (menus) */
for (ar = screen->regionbase.first; ar; ar = ar->next) {
if (ar->swinid) {
CTX_wm_menu_set(C, ar);
@@ -652,9 +687,9 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
if (wm->drags.first) {
wm_drags_draw(C, win, NULL);
}
-
}
+
/****************** main update call **********************/
/* quick test to prevent changing window drawable */
@@ -734,6 +769,14 @@ static int wm_automatic_draw_method(wmWindow *win)
return win->drawmethod;
}
+int WM_is_draw_triple(wmWindow *win)
+{
+ /* function can get called before this variable is set in drawing code below */
+ if (win->drawmethod != U.wmdrawmethod)
+ win->drawmethod = U.wmdrawmethod;
+ return USER_DRAW_TRIPLE == wm_automatic_draw_method(win);
+}
+
void wm_tag_redraw_overlay(wmWindow *win, ARegion *ar)
{
/* for draw triple gestures, paint cursors don't need region redraw */
@@ -753,15 +796,18 @@ void wm_draw_update(bContext *C)
GPU_free_unused_buffers();
for (win = wm->windows.first; win; win = win->next) {
- int state = GHOST_GetWindowState(win->ghostwin);;
-
- if (state == GHOST_kWindowStateMinimized) {
- /* do not update minimized windows, it gives issues on intel drivers (see [#33223])
- * anyway, it seems logical to skip update for invisile windows
- */
- continue;
+#ifdef WIN32
+ if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) {
+ GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin);
+
+ if (state == GHOST_kWindowStateMinimized) {
+ /* do not update minimized windows, it gives issues on intel drivers (see [#33223])
+ * anyway, it seems logical to skip update for invisible windows
+ */
+ continue;
+ }
}
-
+#endif
if (win->drawmethod != U.wmdrawmethod) {
wm_draw_window_clear(win);
win->drawmethod = U.wmdrawmethod;
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index c0e3b19c716..b2647626f3a 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -66,6 +66,8 @@
#include "RNA_access.h"
+#include "BIF_gl.h"
+
#include "UI_interface.h"
#include "PIL_time.h"
@@ -82,16 +84,21 @@
# include "RNA_enum_types.h"
#endif
+static void update_tablet_data(wmWindow *win, wmEvent *event);
+
static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports,
short context, short poll_only);
/* ************ event management ************** */
-void wm_event_add(wmWindow *win, wmEvent *event_to_add)
+void wm_event_add(wmWindow *win, const wmEvent *event_to_add)
{
- wmEvent *event = MEM_callocN(sizeof(wmEvent), "wmEvent");
+ wmEvent *event = MEM_mallocN(sizeof(wmEvent), "wmEvent");
*event = *event_to_add;
+
+ update_tablet_data(win, event);
+
BLI_addtail(&win->queue, event);
}
@@ -106,6 +113,11 @@ void wm_event_free(wmEvent *event)
MEM_freeN(event->customdata);
}
}
+
+ if (event->tablet_data) {
+ MEM_freeN(event->tablet_data);
+ }
+
MEM_freeN(event);
}
@@ -270,7 +282,7 @@ void wm_event_do_notifiers(bContext *C)
/* XXX context in notifiers? */
CTX_wm_window_set(C, win);
- /* printf("notifier win %d screen %s cat %x\n", win->winid, win->screen->id.name+2, note->category); */
+ /* printf("notifier win %d screen %s cat %x\n", win->winid, win->screen->id.name + 2, note->category); */
ED_screen_do_listen(C, note);
for (ar = win->screen->regionbase.first; ar; ar = ar->next) {
@@ -338,7 +350,7 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve
ARegion *region = CTX_wm_region(C);
ARegion *menu = CTX_wm_menu(C);
static int do_wheel_ui = TRUE;
- int is_wheel = ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE);
+ int is_wheel = ELEM3(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, MOUSEPAN);
int retval;
/* UI code doesn't handle return values - it just always returns break.
@@ -441,10 +453,26 @@ static void wm_operator_print(bContext *C, wmOperator *op)
MEM_freeN(buf);
}
+/**
+ * Sets the active region for this space from the context.
+ *
+ * \see #BKE_area_find_region_active_win
+ */
+void WM_operator_region_active_win_set(bContext *C)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa) {
+ ARegion *ar = CTX_wm_region(C);
+ if (ar && ar->regiontype == RGN_TYPE_WINDOW) {
+ sa->region_active_win = BLI_findindex(&sa->regionbase, ar);
+ }
+ }
+}
+
/* for debugging only, getting inspecting events manually is tedious */
#ifndef NDEBUG
-void WM_event_print(wmEvent *event)
+void WM_event_print(const wmEvent *event)
{
if (event) {
const char *unknown = "UNKNOWN";
@@ -561,10 +589,16 @@ static void wm_operator_finished(bContext *C, wmOperator *op, int repeat)
MEM_freeN(buf);
}
- if (wm_operator_register_check(wm, op->type))
+ if (wm_operator_register_check(wm, op->type)) {
+ /* take ownership of reports (in case python provided own) */
+ op->reports->flag |= RPT_FREE;
+
wm_operator_register(C, op);
- else
+ WM_operator_region_active_win_set(C);
+ }
+ else {
WM_operator_free(op);
+ }
}
}
@@ -904,6 +938,9 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event,
wm_operator_finished(C, op, 0);
}
else if (retval & OPERATOR_RUNNING_MODAL) {
+ /* take ownership of reports (in case python provided own) */
+ op->reports->flag |= RPT_FREE;
+
/* grab cursor during blocking modal ops (X11)
* Also check for macro
*/
@@ -1033,7 +1070,14 @@ static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA
}
if (!(ar && ar->regiontype == type) && area) {
- ARegion *ar1 = BKE_area_find_region_type(area, type);
+ ARegion *ar1;
+ if (type == RGN_TYPE_WINDOW) {
+ ar1 = BKE_area_find_region_active_win(area);
+ }
+ else {
+ ar1 = BKE_area_find_region_type(area, type);
+ }
+
if (ar1)
CTX_wm_region_set(C, ar1);
}
@@ -1132,13 +1176,6 @@ int WM_operator_call_py(bContext *C, wmOperatorType *ot, short context,
if (!is_undo && wm && (wm == CTX_wm_manager(C))) wm->op_undo_depth--;
- /* keep the reports around if needed later */
- if ((retval & OPERATOR_RUNNING_MODAL) ||
- ((retval & OPERATOR_FINISHED) && wm_operator_register_check(CTX_wm_manager(C), ot)))
- {
- reports->flag |= RPT_FREE; /* let blender manage freeing */
- }
-
return retval;
}
@@ -1343,6 +1380,15 @@ static void wm_event_modalkeymap(const bContext *C, wmOperator *op, wmEvent *eve
}
}
}
+ else {
+ /* modal keymap checking returns handled events fine, but all hardcoded modal
+ * handling typically swallows all events (OPERATOR_RUNNING_MODAL).
+ * This bypass just disables support for double clicks in hardcoded modal handlers */
+ if (event->val == KM_DBL_CLICK) {
+ event->prevval = event->val;
+ event->val = KM_PRESS;
+ }
+ }
}
/* bad hacking event system... better restore event type for checking of KM_CLICK for example */
@@ -1355,6 +1401,8 @@ static void wm_event_modalmap_end(wmEvent *event)
event->val = event->prevval;
event->prevval = 0;
}
+ else if (event->prevval == KM_DBL_CLICK)
+ event->val = KM_DBL_CLICK;
}
@@ -1394,20 +1442,10 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
if (ot->flag & OPTYPE_UNDO)
wm->op_undo_depth--;
- /* putting back screen context, reval can pass trough after modal failures! */
- if ((retval & OPERATOR_PASS_THROUGH) || wm_event_always_pass(event)) {
- CTX_wm_area_set(C, area);
- CTX_wm_region_set(C, region);
- }
- else {
- /* this special cases is for areas and regions that get removed */
- CTX_wm_area_set(C, NULL);
- CTX_wm_region_set(C, NULL);
- }
-
if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED))
wm_operator_reports(C, op, retval, FALSE);
+ /* important to run 'wm_operator_finished' before NULLing the context members */
if (retval & OPERATOR_FINISHED) {
wm_operator_finished(C, op, 0);
handler->op = NULL;
@@ -1417,6 +1455,17 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
handler->op = NULL;
}
+ /* putting back screen context, reval can pass trough after modal failures! */
+ if ((retval & OPERATOR_PASS_THROUGH) || wm_event_always_pass(event)) {
+ CTX_wm_area_set(C, area);
+ CTX_wm_region_set(C, region);
+ }
+ else {
+ /* this special cases is for areas and regions that get removed */
+ CTX_wm_area_set(C, NULL);
+ CTX_wm_region_set(C, NULL);
+ }
+
/* remove modal handler, operator itself should have been canceled and freed */
if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) {
WM_cursor_grab_disable(CTX_wm_window(C), NULL);
@@ -1640,9 +1689,9 @@ 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 int 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)
+ !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)
;
#endif
wmWindowManager *wm = CTX_wm_manager(C);
@@ -1716,6 +1765,10 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
break;
}
else {
+ if (action & WM_HANDLER_HANDLED)
+ if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS))
+ printf("%s: handled - and pass on! '%s'\n", __func__, kmi->idname);
+
#ifndef NDEBUG
if (do_debug_handler) {
printf("%s: un-handled '%s'...", __func__, kmi->idname);
@@ -2180,16 +2233,23 @@ 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));
+ }
+ }
}
/* ********** filesector handling ************ */
-void WM_event_fileselect_event(bContext *C, void *ophandle, int eventval)
+void WM_event_fileselect_event(wmWindowManager *wm, void *ophandle, int eventval)
{
/* add to all windows! */
wmWindow *win;
- for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) {
+ for (win = wm->windows.first; win; win = win->next) {
wmEvent event = *win->eventstate;
event.type = EVT_FILESELECT;
@@ -2211,6 +2271,7 @@ void WM_event_fileselect_event(bContext *C, void *ophandle, int eventval)
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?
@@ -2242,7 +2303,7 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op)
op->type->check(C, op); /* ignore return value */
}
- WM_event_fileselect_event(C, op, full ? EVT_FILESELECT_FULL_OPEN : EVT_FILESELECT_OPEN);
+ WM_event_fileselect_event(wm, op, full ? EVT_FILESELECT_FULL_OPEN : EVT_FILESELECT_OPEN);
}
#if 0
@@ -2427,14 +2488,14 @@ void WM_event_add_mousemove_window(wmWindow *window)
}
/* for modal callbacks, check configuration for how to interpret exit with tweaks */
-int WM_modal_tweak_exit(wmEvent *evt, int tweak_event)
+int WM_modal_tweak_exit(const wmEvent *event, int tweak_event)
{
/* if the release-confirm userpref setting is enabled,
* tweak events can be canceled when mouse is released
*/
if (U.flag & USER_RELEASECONFIRM) {
/* option on, so can exit with km-release */
- if (evt->val == KM_RELEASE) {
+ if (event->val == KM_RELEASE) {
switch (tweak_event) {
case EVT_TWEAK_L:
case EVT_TWEAK_M:
@@ -2455,7 +2516,7 @@ int WM_modal_tweak_exit(wmEvent *evt, int tweak_event)
* some items (i.e. markers) being tweaked may end up getting
* dropped all over
*/
- if (evt->val != KM_RELEASE)
+ if (event->val != KM_RELEASE)
return 1;
}
@@ -2632,9 +2693,12 @@ static void update_tablet_data(wmWindow *win, wmEvent *event)
wmtab->Xtilt = td->Xtilt;
wmtab->Ytilt = td->Ytilt;
- event->custom = EVT_DATA_TABLET;
- event->customdata = wmtab;
- event->customdatafree = 1;
+ event->tablet_data = wmtab;
+ // printf("%s: using tablet %.5f\n", __func__, wmtab->Pressure);
+ }
+ else {
+ event->tablet_data = NULL;
+ // printf("%s: not using tablet\n", __func__);
}
}
@@ -2682,15 +2746,17 @@ static void attach_ndof_data(wmEvent *event, const GHOST_TEventNDOFMotionData *g
}
/* imperfect but probably usable... draw/enable drags to other windows */
-static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *evt)
+static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *event)
{
- int mx = evt->x, my = evt->y;
+ int mx = event->x, my = event->y;
if (wm->windows.first == wm->windows.last)
return NULL;
- /* top window bar... */
- if (mx < 0 || my < 0 || mx > win->sizex || my > win->sizey + 30) {
+ /* in order to use window size and mouse position (pixels), we have to use a WM function */
+
+ /* check if outside, include top window bar... */
+ if (mx < 0 || my < 0 || mx > WM_window_pixels_x(win) || my > WM_window_pixels_y(win) + 30) {
wmWindow *owin;
wmEventHandler *handler;
@@ -2701,18 +2767,21 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi
return NULL;
/* to desktop space */
- mx += (int)win->posx;
- my += (int)win->posy;
+ mx += (int) (U.pixelsize * win->posx);
+ my += (int) (U.pixelsize * win->posy);
/* check other windows to see if it has mouse inside */
for (owin = wm->windows.first; owin; owin = owin->next) {
if (owin != win) {
- if (mx - owin->posx >= 0 && my - owin->posy >= 0 &&
- mx - owin->posx <= owin->sizex && my - owin->posy <= owin->sizey)
+ int posx = (int) (U.pixelsize * owin->posx);
+ int posy = (int) (U.pixelsize * owin->posy);
+
+ if (mx - posx >= 0 && owin->posy >= 0 &&
+ mx - posx <= WM_window_pixels_x(owin) && my - posy <= WM_window_pixels_y(owin))
{
- evt->x = mx - (int)owin->posx;
- evt->y = my - (int)owin->posy;
+ event->x = mx - (int)(U.pixelsize * owin->posx);
+ event->y = my - (int)(U.pixelsize * owin->posy);
return owin;
}
@@ -2722,6 +2791,24 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi
return NULL;
}
+static bool wm_event_is_double_click(wmEvent *event, wmEvent *event_state)
+{
+ if ((event->type == event_state->prevtype) &&
+ (event_state->prevval == KM_RELEASE) &&
+ (event->val == KM_PRESS))
+ {
+ if ((ISMOUSE(event->type) == false) || ((ABS(event->x - event_state->prevclickx)) <= 2 &&
+ (ABS(event->y - event_state->prevclicky)) <= 2))
+ {
+ if ((PIL_check_seconds_timer() - event_state->prevclicktime) * 1000 < U.dbl_click_time) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
/* windows store own event queues, no bContext here */
/* time is in 1000s of seconds, from ghost */
void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int UNUSED(time), void *customdata)
@@ -2731,18 +2818,16 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
/* initialize and copy state (only mouse x y and modifiers) */
event = *evt;
-
+
switch (type) {
/* mouse move, also to inactive window (X11 does this) */
case GHOST_kEventCursorMove:
{
GHOST_TEventCursorData *cd = customdata;
wmEvent *lastevent = win->queue.last;
- int cx, cy;
- GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy);
- evt->x = cx;
- evt->y = (win->sizey - 1) - cy;
+ evt->x = cd->x;
+ evt->y = cd->y;
event.x = evt->x;
event.y = evt->y;
@@ -2755,7 +2840,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
if (lastevent && lastevent->type == MOUSEMOVE)
lastevent->type = INBETWEEN_MOUSEMOVE;
- update_tablet_data(win, &event);
wm_event_add(win, &event);
/* also add to other window if event is there, this makes overdraws disappear nicely */
@@ -2768,7 +2852,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
oevent.y = owin->eventstate->y = event.y;
oevent.type = MOUSEMOVE;
- update_tablet_data(owin, &oevent);
wm_event_add(owin, &oevent);
}
@@ -2780,6 +2863,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
switch (pd->subtype) {
case GHOST_kTrackpadEventMagnify:
event.type = MOUSEZOOM;
+ pd->deltaX = -pd->deltaX;
+ pd->deltaY = -pd->deltaY;
break;
case GHOST_kTrackpadEventRotate:
event.type = MOUSEROTATE;
@@ -2790,20 +2875,14 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
break;
}
- {
- int cx, cy;
- GHOST_ScreenToClient(win->ghostwin, pd->x, pd->y, &cx, &cy);
- event.x = evt->x = cx;
- event.y = evt->y = (win->sizey - 1) - cy;
- }
-
+ event.x = evt->x = pd->x;
+ event.y = evt->y = pd->y;
event.val = 0;
/* Use prevx/prevy so we can calculate the delta later */
event.prevx = event.x - pd->deltaX;
event.prevy = event.y - (-pd->deltaY);
- update_tablet_data(win, &event);
wm_event_add(win, &event);
break;
}
@@ -2848,15 +2927,10 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
}
/* double click test */
- if (event.type == evt->prevtype && event.val == KM_PRESS) {
- if ((ABS(event.x - evt->prevclickx)) <= 2 &&
- (ABS(event.y - evt->prevclicky)) <= 2 &&
- ((PIL_check_seconds_timer() - evt->prevclicktime) * 1000 < U.dbl_click_time))
- {
- if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) )
- printf("%s Send double click\n", __func__);
- event.val = KM_DBL_CLICK;
- }
+ if (wm_event_is_double_click(&event, evt)) {
+ if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) )
+ printf("%s Send double click\n", __func__);
+ event.val = KM_DBL_CLICK;
}
if (event.val == KM_PRESS) {
evt->prevclicktime = PIL_check_seconds_timer();
@@ -2874,11 +2948,9 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
oevent.type = event.type;
oevent.val = event.val;
- update_tablet_data(owin, &oevent);
wm_event_add(owin, &oevent);
}
else {
- update_tablet_data(win, &event);
wm_event_add(win, &event);
}
@@ -2962,15 +3034,10 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
/* double click test */
/* if previous event was same type, and previous was release, and now it presses... */
- if (event.type == evt->prevtype && evt->prevval == KM_RELEASE && event.val == KM_PRESS) {
- if ((ABS(event.x - evt->prevclickx)) <= 2 &&
- (ABS(event.y - evt->prevclicky)) <= 2 &&
- ((PIL_check_seconds_timer() - evt->prevclicktime) * 1000 < U.dbl_click_time))
- {
- if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) )
- printf("%s Send double click\n", __func__);
- evt->val = event.val = KM_DBL_CLICK;
- }
+ if (wm_event_is_double_click(&event, evt)) {
+ if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) )
+ printf("%s Send double click\n", __func__);
+ evt->val = event.val = KM_DBL_CLICK;
}
/* this case happens on holding a key pressed, it should not generate
@@ -2979,7 +3046,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
event.keymodifier = 0;
/* this case happened with an external numpad, it's not really clear
- * why, but it's also impossible to map a key modifier to an unknwon
+ * why, but it's also impossible to map a key modifier to an unknown
* key, so it shouldn't harm */
if (event.keymodifier == UNKNOWNKEY)
event.keymodifier = 0;
@@ -3080,4 +3147,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
}
+#if 0
+ WM_event_print(&event);
+#endif
}
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 0e4af46d0fc..7152adb4a11 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -283,7 +283,9 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist)
/* in case UserDef was read, we re-initialize all, and do versioning */
static void wm_init_userdef(bContext *C)
{
+ /* versioning is here */
UI_init_userdef();
+
MEM_CacheLimiter_set_maximum(((size_t)U.memcachelimit) * 1024 * 1024);
sound_init(CTX_data_main(C));
@@ -300,6 +302,8 @@ static void wm_init_userdef(bContext *C)
/* update tempdir from user preferences */
BLI_init_temporary_dir(U.tempdir);
+
+ BKE_userdef_state();
}
@@ -388,6 +392,8 @@ void WM_file_read(bContext *C, const char *filepath, ReportList *reports)
/* also exit screens and editors */
wm_window_match_init(C, &wmbase);
+ /* confusing this global... */
+ G.relbase_valid = 1;
retval = BKE_read_file(C, filepath, reports);
G.save_over = 1;
@@ -408,7 +414,6 @@ void WM_file_read(bContext *C, const char *filepath, ReportList *reports)
}
if (retval != BKE_READ_FILE_FAIL) {
- G.relbase_valid = 1;
if (do_history) {
write_history();
}
@@ -485,23 +490,26 @@ void WM_file_read(bContext *C, const char *filepath, ReportList *reports)
/* called on startup, (context entirely filled with NULLs) */
/* or called for 'New File' */
-/* op can be NULL */
-int WM_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory)
+/* both startup.blend and userpref.blend are checked */
+int wm_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory)
{
ListBase wmbase;
- char tstr[FILE_MAX];
+ char startstr[FILE_MAX];
+ char prefstr[FILE_MAX];
int success = 0;
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE);
G.relbase_valid = 0;
if (!from_memory) {
- char *cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL);
+ const char * const cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL);
if (cfgdir) {
- BLI_make_file_string(G.main->name, tstr, cfgdir, BLENDER_STARTUP_FILE);
+ BLI_make_file_string(G.main->name, startstr, cfgdir, BLENDER_STARTUP_FILE);
+ BLI_make_file_string(G.main->name, prefstr, cfgdir, BLENDER_USERPREF_FILE);
}
else {
- tstr[0] = '\0';
+ startstr[0] = '\0';
+ prefstr[0] = '\0';
from_memory = 1;
}
}
@@ -512,14 +520,18 @@ int WM_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory
/* put aside screens to match with persistent windows later */
wm_window_match_init(C, &wmbase);
- if (!from_memory && BLI_exists(tstr)) {
- success = (BKE_read_file(C, tstr, NULL) != BKE_READ_FILE_FAIL);
-
+ if (!from_memory) {
+ if (BLI_exists(startstr)) {
+ success = (BKE_read_file(C, startstr, NULL) != BKE_READ_FILE_FAIL);
+ }
+
if (U.themes.first == NULL) {
- printf("\nError: No valid "STRINGIFY (BLENDER_STARTUP_FILE)", fall back to built-in default.\n\n");
+ if (G.debug & G_DEBUG)
+ printf("\nNote: No (valid) '%s' found, fall back to built-in default.\n\n", startstr);
success = 0;
}
}
+
if (success == 0) {
success = BKE_read_file_from_memory(C, datatoc_startup_blend, datatoc_startup_blend_size, NULL);
if (wmbase.first == NULL) wm_clear_default_size(C);
@@ -531,6 +543,12 @@ int WM_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory
#endif
}
+ /* check new prefs only after startup.blend was finished */
+ if (!from_memory && BLI_exists(prefstr)) {
+ int done = BKE_read_file_userdef(prefstr, NULL);
+ if (done) printf("Read new prefs: %s\n", prefstr);
+ }
+
/* prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake. Screws up autosaves otherwise
* can remove this eventually, only in a 2.53 and older, now its not written */
G.fileflags &= ~G_FILE_RELATIVE_REMAP;
@@ -584,20 +602,20 @@ int WM_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory
return TRUE;
}
-int WM_homefile_read_exec(bContext *C, wmOperator *op)
+int wm_homefile_read_exec(bContext *C, wmOperator *op)
{
int from_memory = strcmp(op->type->idname, "WM_OT_read_factory_settings") == 0;
- return WM_homefile_read(C, op->reports, from_memory) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return wm_homefile_read(C, op->reports, from_memory) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
-void WM_read_history(void)
+void wm_read_history(void)
{
char name[FILE_MAX];
LinkNode *l, *lines;
struct RecentFile *recent;
char *line;
int num;
- char *cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL);
+ const char * const cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL);
if (!cfgdir) return;
@@ -626,10 +644,14 @@ static void write_history(void)
{
struct RecentFile *recent, *next_recent;
char name[FILE_MAX];
- char *user_config_dir;
+ const char *user_config_dir;
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);
if (!user_config_dir)
@@ -708,11 +730,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, err_out);
+ IB_rect, OB_SOLID, FALSE, FALSE, R_ADDSKY, err_out);
}
else {
ibuf = ED_view3d_draw_offscreen_imbuf(scene, v3d, ar, BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
- IB_rect, FALSE, FALSE, err_out);
+ IB_rect, FALSE, R_ADDSKY, err_out);
}
if (ibuf) {
@@ -762,12 +784,11 @@ int write_crash_blend(void)
}
}
-int WM_file_write(bContext *C, const char *target, int fileflags, ReportList *reports)
+int wm_file_write(bContext *C, const char *target, int fileflags, ReportList *reports)
{
Library *li;
int len;
char filepath[FILE_MAX];
-
int *thumb = NULL;
ImBuf *ibuf_thumb = NULL;
@@ -808,8 +829,8 @@ int WM_file_write(bContext *C, const char *target, int fileflags, ReportList *re
if (G.fileflags & G_AUTOPACK) {
packAll(G.main, reports);
}
-
- ED_object_exit_editmode(C, EM_DO_UNDO);
+
+ ED_object_editmode_load(CTX_data_edit_object(C));
ED_sculpt_force_update(C);
/* don't forget not to return without! */
@@ -817,6 +838,14 @@ int WM_file_write(bContext *C, const char *target, int fileflags, ReportList *re
fileflags |= G_FILE_HISTORY; /* write file history */
+ /* first time saving */
+ /* XXX temp solution to solve bug, real fix coming (ton) */
+ if (G.main->name[0] == 0)
+ BLI_strncpy(G.main->name, filepath, sizeof(G.main->name));
+
+ /* XXX temp solution to solve bug, real fix coming (ton) */
+ G.main->recovered = 0;
+
if (BLO_write_file(CTX_data_main(C), filepath, fileflags, reports, thumb)) {
if (!(fileflags & G_FILE_SAVE_COPY)) {
G.relbase_valid = 1;
@@ -861,7 +890,7 @@ int WM_file_write(bContext *C, const char *target, int fileflags, ReportList *re
}
/* operator entry */
-int WM_homefile_write_exec(bContext *C, wmOperator *op)
+int wm_homefile_write_exec(bContext *C, wmOperator *op)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
@@ -881,7 +910,7 @@ int WM_homefile_write_exec(bContext *C, wmOperator *op)
/* force save as regular blend file */
fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_LOCK | G_FILE_SIGN | G_FILE_HISTORY);
- if (BLO_write_file(CTX_data_main(C), filepath, fileflags, op->reports, NULL) == 0) {
+ if (BLO_write_file(CTX_data_main(C), filepath, fileflags | G_FILE_USERPREFS, op->reports, NULL) == 0) {
printf("fail\n");
return OPERATOR_CANCELLED;
}
@@ -893,6 +922,28 @@ int WM_homefile_write_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+/* Only save the prefs block. operator entry */
+int wm_userpref_write_exec(bContext *C, wmOperator *op)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ char filepath[FILE_MAX];
+
+ /* 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);
+ printf("trying to save userpref at %s ", filepath);
+
+ if (BKE_write_file_userdef(filepath, op->reports) == 0) {
+ printf("fail\n");
+ return OPERATOR_CANCELLED;
+ }
+
+ printf("ok\n");
+
+ return OPERATOR_FINISHED;
+}
+
/************************ autosave ****************************/
void wm_autosave_location(char *filepath)
@@ -936,7 +987,7 @@ void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *UNUSED(w
wmWindow *win;
wmEventHandler *handler;
char filepath[FILE_MAX];
- int fileflags;
+
Scene *scene = CTX_data_scene(C);
WM_event_remove_timer(wm, NULL, wm->autosavetimer);
@@ -960,12 +1011,17 @@ void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *UNUSED(w
wm_autosave_location(filepath);
- /* force save as regular blend file */
- fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_LOCK | G_FILE_SIGN | G_FILE_HISTORY);
-
- /* no error reporting to console */
- BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL);
+ if (U.uiflag & USER_GLOBALUNDO) {
+ /* fast save of last undobuffer, now with UI */
+ BKE_undo_save_file(filepath);
+ }
+ 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);
+ /* no error reporting to console */
+ BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL);
+ }
/* do timer after file write, just in case file write takes a long time */
wm->autosavetimer = WM_event_add_timer(wm, NULL, TIMERAUTOSAVE, U.savetime * 60.0);
}
@@ -986,10 +1042,10 @@ void wm_autosave_delete(void)
if (BLI_exists(filename)) {
char str[FILE_MAX];
- BLI_make_file_string("/", str, BLI_temporary_dir(), "quit.blend");
+ BLI_make_file_string("/", str, BLI_temporary_dir(), BLENDER_QUIT_FILE);
/* if global undo; remove tempsave, otherwise rename */
- if (U.uiflag & USER_GLOBALUNDO) BLI_delete(filename, 0, 0);
+ if (U.uiflag & USER_GLOBALUNDO) BLI_delete(filename, false, false);
else BLI_rename(filename, str);
}
}
@@ -1002,3 +1058,6 @@ void wm_autosave_read(bContext *C, ReportList *reports)
WM_file_read(C, filename, reports);
}
+
+
+
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index a80386e9860..adf159bcfee 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -58,7 +58,7 @@
/* context checked on having screen, window and area */
-wmGesture *WM_gesture_new(bContext *C, wmEvent *event, int type)
+wmGesture *WM_gesture_new(bContext *C, const wmEvent *event, int type)
{
wmGesture *gesture = MEM_callocN(sizeof(wmGesture), "new gesture");
wmWindow *window = CTX_wm_window(C);
@@ -113,6 +113,9 @@ void WM_gesture_end(bContext *C, wmGesture *gesture)
win->tweak = NULL;
BLI_remlink(&win->gesture, gesture);
MEM_freeN(gesture->customdata);
+ if (gesture->userdata) {
+ MEM_freeN(gesture->userdata);
+ }
MEM_freeN(gesture);
}
@@ -255,7 +258,7 @@ static void draw_filled_lasso(wmGesture *gt)
if (sf_vert_first) {
const float zvec[3] = {0.0f, 0.0f, 1.0f};
BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
- BLI_scanfill_calc_ex(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES, zvec);
+ BLI_scanfill_calc_ex(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES | BLI_SCANFILL_CALC_HOLES, zvec);
glEnable(GL_BLEND);
glColor4f(1.0, 1.0, 1.0, 0.05);
@@ -306,17 +309,19 @@ static void wm_gesture_draw_lasso(wmGesture *gt)
static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt)
{
rcti *rect = (rcti *)gt->customdata;
-
+ int winsizex = WM_window_pixels_x(win);
+ int winsizey = WM_window_pixels_y(win);
+
glEnable(GL_LINE_STIPPLE);
glColor3ub(96, 96, 96);
glLineStipple(1, 0xCCCC);
- sdrawline(rect->xmin - win->sizex, rect->ymin, rect->xmin + win->sizex, rect->ymin);
- sdrawline(rect->xmin, rect->ymin - win->sizey, rect->xmin, rect->ymin + win->sizey);
+ sdrawline(rect->xmin - winsizex, rect->ymin, rect->xmin + winsizex, rect->ymin);
+ sdrawline(rect->xmin, rect->ymin - winsizey, rect->xmin, rect->ymin + winsizey);
glColor3ub(255, 255, 255);
glLineStipple(1, 0x3333);
- sdrawline(rect->xmin - win->sizex, rect->ymin, rect->xmin + win->sizex, rect->ymin);
- sdrawline(rect->xmin, rect->ymin - win->sizey, rect->xmin, rect->ymin + win->sizey);
+ sdrawline(rect->xmin - winsizex, rect->ymin, rect->xmin + winsizex, rect->ymin);
+ sdrawline(rect->xmin, rect->ymin - winsizey, rect->xmin, rect->ymin + winsizey);
glDisable(GL_LINE_STIPPLE);
}
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index c9f0bbffc63..532404cf218 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -33,7 +33,7 @@
#include <string.h>
#ifdef WIN32
-# include <Windows.h>
+# include <windows.h>
#endif
#include "MEM_guardedalloc.h"
@@ -48,6 +48,7 @@
#include "DNA_windowmanager_types.h"
#include "BLI_listbase.h"
+#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
@@ -65,6 +66,7 @@
#include "BKE_node.h"
#include "BKE_report.h"
+#include "BKE_addon.h"
#include "BKE_packedFile.h"
#include "BKE_sequencer.h" /* free seq clipboard */
#include "BKE_material.h" /* clear_matcopybuf */
@@ -123,18 +125,23 @@ static void wm_free_reports(bContext *C)
BKE_reports_clear(CTX_wm_reports(C));
}
-int wm_start_with_console = 0; /* used in creator.c */
+bool wm_start_with_console = false; /* used in creator.c */
/* only called once, for startup */
void WM_init(bContext *C, int argc, const char **argv)
{
+
if (!G.background) {
wm_ghost_init(C); /* note: it assigns C to ghost! */
wm_init_cursor_data();
}
GHOST_CreateSystemPaths();
+
+ BKE_addon_pref_type_init();
+
wm_operatortype_init();
WM_menutype_init();
+ WM_uilisttype_init();
set_free_windowmanager_cb(wm_close_and_free); /* library.c */
set_blender_test_break_cb(wm_window_testbreak); /* blender.c */
@@ -149,8 +156,8 @@ void WM_init(bContext *C, int argc, const char **argv)
BLF_lang_init();
/* get the default database, plus a wm */
- WM_homefile_read(C, NULL, G.factory_startup);
-
+ wm_homefile_read(C, NULL, G.factory_startup);
+
BLF_lang_set(NULL);
/* note: there is a bug where python needs initializing before loading the
@@ -158,7 +165,7 @@ void WM_init(bContext *C, int argc, const char **argv)
* initializing space types and other internal data.
*
* However cant redo this at the moment. Solution is to load python
- * before WM_homefile_read() or make py-drivers check if python is running.
+ * before wm_homefile_read() or make py-drivers check if python is running.
* Will try fix when the crash can be repeated. - campbell. */
#ifdef WITH_PYTHON
@@ -191,11 +198,11 @@ void WM_init(bContext *C, int argc, const char **argv)
clear_matcopybuf();
ED_render_clear_mtex_copybuf();
- // glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
ED_preview_init_dbase();
- WM_read_history();
+ wm_read_history();
/* allow a path of "", this is what happens when making a new file */
#if 0
@@ -211,6 +218,10 @@ void WM_init(bContext *C, int argc, const char **argv)
COM_linker_hack = COM_execute;
}
#endif
+
+ /* load last session, uses regular file reading so it has to be in end (after init py etc) */
+ if (U.uiflag2 & USER_KEEP_SESSION)
+ wm_recover_last_session(C, NULL);
}
void WM_init_splash(bContext *C)
@@ -372,6 +383,18 @@ void WM_exit_ext(bContext *C, const short do_python)
if (C && wm) {
wmWindow *win;
+ if (!G.background) {
+ if ((U.uiflag2 & USER_KEEP_SESSION) || BKE_undo_valid(NULL)) {
+ /* save the undo state as quit.blend */
+ char filename[FILE_MAX];
+
+ BLI_make_file_string("/", filename, BLI_temporary_dir(), BLENDER_QUIT_FILE);
+
+ if (BKE_undo_save_file(filename))
+ printf("Saved session recovery to '%s'\n", filename);
+ }
+ }
+
WM_jobs_kill_all(wm);
for (win = wm->windows.first; win; win = win->next) {
@@ -382,9 +405,12 @@ void WM_exit_ext(bContext *C, const short do_python)
ED_screen_exit(C, win, win->screen);
}
}
+
+ BKE_addon_pref_type_free();
wm_operatortype_free();
wm_dropbox_free();
WM_menutype_free();
+ WM_uilisttype_free();
/* all non-screen and non-space stuff editors did, like editmode */
if (C)
@@ -423,6 +449,7 @@ void WM_exit_ext(bContext *C, const short do_python)
#ifdef WITH_INTERNATIONAL
BLF_free_unifont();
+ BLF_free_unifont_mono();
BLF_lang_free();
#endif
@@ -454,9 +481,6 @@ void WM_exit_ext(bContext *C, const short do_python)
GPU_free_unused_buffers();
GPU_extensions_exit();
- if (!G.background) {
- BKE_undo_save_quit(); /* saves quit.blend if global undo is on */
- }
BKE_reset_undo();
ED_file_exit(); /* for fsmenu */
diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c
index 3c3e2c0feaa..e5963840261 100644
--- a/source/blender/windowmanager/intern/wm_jobs.c
+++ b/source/blender/windowmanager/intern/wm_jobs.c
@@ -363,7 +363,9 @@ void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
if (G.debug & G_DEBUG_JOBS)
wm_job->start_time = PIL_check_seconds_timer();
}
- else printf("job fails, not initialized\n");
+ else {
+ printf("job fails, not initialized\n");
+ }
}
}
@@ -589,3 +591,16 @@ int WM_jobs_has_running(wmWindowManager *wm)
return FALSE;
}
+
+int WM_jobs_has_running_except(wmWindowManager *wm, int job_type)
+{
+ wmJob *wm_job;
+
+ for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) {
+ if (wm_job->running && wm_job->job_type != job_type) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index 3739462ac2c..20e715c18d0 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -126,10 +126,13 @@ static int wm_keymap_item_equals(wmKeyMapItem *a, wmKeyMapItem *b)
/* properties can be NULL, otherwise the arg passed is used and ownership is given to the kmi */
void WM_keymap_properties_reset(wmKeyMapItem *kmi, struct IDProperty *properties)
{
- WM_operator_properties_free(kmi->ptr);
- MEM_freeN(kmi->ptr);
+ if (LIKELY(kmi->ptr)) {
+ WM_operator_properties_free(kmi->ptr);
+ MEM_freeN(kmi->ptr);
+
+ kmi->ptr = NULL;
+ }
- kmi->ptr = NULL;
kmi->properties = properties;
wm_keymap_item_properties_set(kmi);
@@ -734,6 +737,24 @@ 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)
+{
+
+ if (km->flag & KEYMAP_MODAL) {
+ wmKeyMapItem *kmi;
+ for (kmi = km->items.first; kmi; kmi = kmi->next) {
+ if (kmi->propvalue == propvalue) {
+ return kmi;
+ }
+ }
+ }
+ else {
+ BLI_assert(!"called with non modal keymap");
+ }
+
+ return NULL;
+}
+
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
{
wmOperatorType *ot = WM_operatortype_find(opname, 0);
@@ -782,7 +803,7 @@ const char *WM_key_event_string(short type)
return "";
}
-char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len)
+int WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len)
{
char buf[128];
@@ -815,9 +836,7 @@ char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len)
}
strcat(buf, WM_key_event_string(kmi->type));
- BLI_strncpy(str, buf, len);
-
- return str;
+ return BLI_strncpy_rlen(str, buf, len);
}
static wmKeyMapItem *wm_keymap_item_find_handlers(
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 8a0701b1063..b27f014ccb3 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -69,6 +69,7 @@
#include "BKE_library.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 */
@@ -103,11 +104,14 @@
#include "wm_draw.h"
#include "wm_event_system.h"
#include "wm_event_types.h"
+#include "wm_files.h"
#include "wm_subwindow.h"
#include "wm_window.h"
static GHash *global_ops_hash = NULL;
+#define UNDOCUMENTED_OPERATOR_TIP N_("(undocumented operator)")
+
/* ************ operator API, exported ********** */
@@ -150,7 +154,7 @@ void WM_operatortype_append(void (*opfunc)(wmOperatorType *))
wmOperatorType *ot;
ot = MEM_callocN(sizeof(wmOperatorType), "operatortype");
- ot->srna = RNA_def_struct(&BLENDER_RNA, "", "OperatorProperties");
+ 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);
opfunc(ot);
@@ -161,7 +165,7 @@ void WM_operatortype_append(void (*opfunc)(wmOperatorType *))
}
/* XXX All ops should have a description but for now allow them not to. */
- RNA_def_struct_ui_text(ot->srna, ot->name, ot->description ? ot->description : N_("(undocumented operator)"));
+ RNA_def_struct_ui_text(ot->srna, ot->name, ot->description ? ot->description : UNDOCUMENTED_OPERATOR_TIP);
RNA_def_struct_identifier(ot->srna, ot->idname);
BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot);
@@ -172,11 +176,11 @@ void WM_operatortype_append_ptr(void (*opfunc)(wmOperatorType *, void *), void *
wmOperatorType *ot;
ot = MEM_callocN(sizeof(wmOperatorType), "operatortype");
- ot->srna = RNA_def_struct(&BLENDER_RNA, "", "OperatorProperties");
+ 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);
opfunc(ot, userdata);
- RNA_def_struct_ui_text(ot->srna, ot->name, ot->description ? ot->description : N_("(undocumented operator)"));
+ RNA_def_struct_ui_text(ot->srna, ot->name, ot->description ? ot->description : UNDOCUMENTED_OPERATOR_TIP);
RNA_def_struct_identifier(ot->srna, ot->idname);
BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot);
@@ -244,7 +248,7 @@ static int wm_macro_exec(bContext *C, wmOperator *op)
return wm_macro_end(op, retval);
}
-static int wm_macro_invoke_internal(bContext *C, wmOperator *op, wmEvent *event, wmOperator *opm)
+static int wm_macro_invoke_internal(bContext *C, wmOperator *op, const wmEvent *event, wmOperator *opm)
{
int retval = OPERATOR_FINISHED;
@@ -271,13 +275,13 @@ static int wm_macro_invoke_internal(bContext *C, wmOperator *op, wmEvent *event,
return wm_macro_end(op, retval);
}
-static int wm_macro_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int wm_macro_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
wm_macro_start(op);
return wm_macro_invoke_internal(C, op, event, op->macro.first);
}
-static int wm_macro_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int wm_macro_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
wmOperator *opm = op->opm;
int retval = OPERATOR_FINISHED;
@@ -359,7 +363,7 @@ wmOperatorType *WM_operatortype_append_macro(const char *idname, const char *nam
}
ot = MEM_callocN(sizeof(wmOperatorType), "operatortype");
- ot->srna = RNA_def_struct(&BLENDER_RNA, "", "OperatorProperties");
+ ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties);
ot->idname = idname;
ot->name = name;
@@ -373,11 +377,13 @@ wmOperatorType *WM_operatortype_append_macro(const char *idname, const char *nam
ot->poll = NULL;
if (!ot->description) /* XXX All ops should have a description but for now allow them not to. */
- ot->description = N_("(undocumented operator)");
+ ot->description = UNDOCUMENTED_OPERATOR_TIP;
RNA_def_struct_ui_text(ot->srna, ot->name, ot->description);
RNA_def_struct_identifier(ot->srna, ot->idname);
- RNA_def_struct_translation_context(ot->srna, BLF_I18NCONTEXT_OPERATOR_DEFAULT);
+ /* 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);
BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot);
@@ -389,7 +395,7 @@ void WM_operatortype_append_macro_ptr(void (*opfunc)(wmOperatorType *, void *),
wmOperatorType *ot;
ot = MEM_callocN(sizeof(wmOperatorType), "operatortype");
- ot->srna = RNA_def_struct(&BLENDER_RNA, "", "OperatorProperties");
+ ot->srna = RNA_def_struct_ptr(&BLENDER_RNA, "", &RNA_OperatorProperties);
ot->flag = OPTYPE_MACRO;
ot->exec = wm_macro_exec;
@@ -399,7 +405,7 @@ void WM_operatortype_append_macro_ptr(void (*opfunc)(wmOperatorType *, void *),
ot->poll = NULL;
if (!ot->description)
- ot->description = N_("(undocumented operator)");
+ 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);
@@ -559,6 +565,187 @@ char *WM_operator_pystring(bContext *C, wmOperatorType *ot, PointerRNA *opptr, i
return cstring;
}
+/* return NULL if no match is found */
+#if 0
+static char *wm_prop_pystring_from_context(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index)
+{
+
+ /* loop over all context items and do 2 checks
+ *
+ * - see if the pointer is in the context.
+ * - see if the pointers ID is in the context.
+ */
+
+ /* don't get from the context store since this is normally set only for the UI and not usable elsewhere */
+ ListBase lb = CTX_data_dir_get_ex(C, FALSE, TRUE, TRUE);
+ LinkData *link;
+
+ const char *member_found = NULL;
+ const char *member_id = NULL;
+
+ char *prop_str = NULL;
+ char *ret = NULL;
+
+
+ for (link = lb.first; link; link = link->next) {
+ const char *identifier = link->data;
+ PointerRNA ctx_item_ptr = {{0}} // CTX_data_pointer_get(C, identifier); // XXX, this isnt working
+
+ if (ctx_item_ptr.type == NULL) {
+ continue;
+ }
+
+ if (ptr->id.data == ctx_item_ptr.id.data) {
+ if ((ptr->data == ctx_item_ptr.data) &&
+ (ptr->type == ctx_item_ptr.type))
+ {
+ /* found! */
+ member_found = identifier;
+ break;
+ }
+ else if (RNA_struct_is_ID(ctx_item_ptr.type)) {
+ /* we found a reference to this ID,
+ * so fallback to it if there is no direct reference */
+ member_id = identifier;
+ }
+ }
+ }
+
+ if (member_found) {
+ prop_str = RNA_path_property_py(ptr, prop, index);
+ if (prop_str) {
+ ret = BLI_sprintfN("bpy.context.%s.%s", member_found, prop_str);
+ MEM_freeN(prop_str);
+ }
+ }
+ else if (member_id) {
+ prop_str = RNA_path_struct_property_py(ptr, prop, index);
+ if (prop_str) {
+ ret = BLI_sprintfN("bpy.context.%s.%s", member_id, prop_str);
+ MEM_freeN(prop_str);
+ }
+ }
+
+ BLI_freelistN(&lb);
+
+ return ret;
+}
+#else
+
+/* use hard coded checks for now */
+static char *wm_prop_pystring_from_context(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index)
+{
+ const char *member_id = NULL;
+
+ char *prop_str = NULL;
+ char *ret = NULL;
+
+ if (ptr->id.data) {
+ ID *idptr = ptr->id.data;
+
+#define CTX_TEST_PTR_ID(C, member, idptr) \
+ { \
+ const char *ctx_member = member; \
+ PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, ctx_member); \
+ if (ctx_item_ptr.id.data == idptr) { \
+ member_id = ctx_member; \
+ break; \
+ } \
+ } (void)0
+
+#define CTX_TEST_PTR_ID_CAST(C, member, member_full, cast, idptr) \
+ { \
+ const char *ctx_member = member; \
+ const char *ctx_member_full = member_full; \
+ PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, ctx_member); \
+ if (ctx_item_ptr.id.data && cast(ctx_item_ptr.id.data) == idptr) { \
+ member_id = ctx_member_full; \
+ break; \
+ } \
+ } (void)0
+
+ switch (GS(idptr->name)) {
+ case ID_SCE:
+ {
+ CTX_TEST_PTR_ID(C, "scene", ptr->id.data);
+ break;
+ }
+ case ID_OB:
+ {
+ CTX_TEST_PTR_ID(C, "object", ptr->id.data);
+ break;
+ }
+ /* from rna_Main_objects_new */
+ case OB_DATA_SUPPORT_ID_CASE:
+ {
+#define ID_CAST_OBDATA(id_pt) (((Object *)(id_pt))->data)
+ CTX_TEST_PTR_ID_CAST(C, "object", "object.data", ID_CAST_OBDATA, ptr->id.data);
+ break;
+#undef ID_CAST_OBDATA
+ }
+ case ID_MA:
+ {
+#define ID_CAST_OBMATACT(id_pt) (give_current_material(((Object *)id_pt), ((Object *)id_pt)->actcol))
+ CTX_TEST_PTR_ID_CAST(C, "object", "object.active_material", ID_CAST_OBMATACT, ptr->id.data);
+ break;
+#undef ID_CAST_OBMATACT
+ }
+ case ID_WO:
+ {
+#define ID_CAST_SCENEWORLD(id_pt) (((Scene *)(id_pt))->world)
+ CTX_TEST_PTR_ID_CAST(C, "scene", "scene.world", ID_CAST_SCENEWORLD, ptr->id.data);
+ break;
+#undef ID_CAST_SCENEWORLD
+ }
+ case ID_SCR:
+ {
+ CTX_TEST_PTR_ID(C, "screen", ptr->id.data);
+ break;
+ }
+ }
+
+ if (member_id) {
+ prop_str = RNA_path_struct_property_py(ptr, prop, index);
+ if (prop_str) {
+ ret = BLI_sprintfN("bpy.context.%s.%s", member_id, prop_str);
+ MEM_freeN(prop_str);
+ }
+ }
+#undef CTX_TEST_PTR_ID
+#undef CTX_TEST_PTR_ID_CAST
+ }
+
+ return ret;
+}
+#endif
+
+char *WM_prop_pystring_assign(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index)
+{
+ char *lhs, *rhs, *ret;
+
+ lhs = C ? wm_prop_pystring_from_context(C, ptr, prop, index) : NULL;
+
+ if (lhs == NULL) {
+ /* fallback to bpy.data.foo[id] if we dont find in the context */
+ lhs = RNA_path_full_property_py(ptr, prop, index);
+ }
+
+ if (!lhs) {
+ return NULL;
+ }
+
+ rhs = RNA_property_as_string(C, ptr, prop, index);
+ if (!rhs) {
+ MEM_freeN(lhs);
+ return NULL;
+ }
+
+ ret = BLI_sprintfN("%s = %s", lhs, rhs);
+ MEM_freeN(lhs);
+ MEM_freeN(rhs);
+ return ret;
+}
+
void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot)
{
RNA_pointer_create(NULL, ot->srna, NULL, ptr);
@@ -690,7 +877,7 @@ void WM_operator_properties_free(PointerRNA *ptr)
/* ************ default op callbacks, exported *********** */
-int WM_operator_view3d_distance_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *UNUSED(event))
+int WM_operator_view3d_distance_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *UNUSED(event))
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -720,7 +907,7 @@ int WM_operator_view3d_distance_invoke(struct bContext *C, struct wmOperator *op
}
/* invoke callback, uses enum property named "type" */
-int WM_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
PropertyRNA *prop = op->type->prop;
uiPopupMenu *pup;
@@ -839,7 +1026,7 @@ static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg_op)
}
-int WM_enum_search_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
uiPupBlock(C, wm_enum_search_menu, op);
return OPERATOR_CANCELLED;
@@ -866,13 +1053,13 @@ int WM_operator_confirm_message(bContext *C, wmOperator *op, const char *message
}
-int WM_operator_confirm(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+int WM_operator_confirm(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
return WM_operator_confirm_message(C, op, NULL);
}
/* op->invoke, opens fileselect if path property not set, otherwise executes */
-int WM_operator_filesel(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+int WM_operator_filesel(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (RNA_struct_property_is_set(op->ptr, "filepath")) {
return WM_operator_call_notest(C, op); /* call exec direct */
@@ -883,14 +1070,14 @@ int WM_operator_filesel(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
}
}
-int WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const char imtype)
+int WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFormatData *im_format)
{
PropertyRNA *prop;
char filepath[FILE_MAX];
/* 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, imtype)) {
+ if (BKE_add_image_extension(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. */
@@ -996,7 +1183,7 @@ void WM_operator_properties_border_to_rcti(struct wmOperator *op, rcti *rect)
rect->ymax = RNA_int_get(op->ptr, "ymax");
}
-void WM_operator_properties_gesture_border(wmOperatorType *ot, int extend)
+void WM_operator_properties_gesture_border(wmOperatorType *ot, bool extend)
{
RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Gesture Mode", "", INT_MIN, INT_MAX);
@@ -1014,15 +1201,20 @@ void WM_operator_properties_mouse_select(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Selection", "Toggle the selection");
}
-void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor)
+void WM_operator_properties_gesture_straightline(wmOperatorType *ot, bool cursor)
{
RNA_def_int(ot->srna, "xstart", 0, INT_MIN, INT_MAX, "X Start", "", INT_MIN, INT_MAX);
RNA_def_int(ot->srna, "xend", 0, INT_MIN, INT_MAX, "X End", "", INT_MIN, INT_MAX);
RNA_def_int(ot->srna, "ystart", 0, INT_MIN, INT_MAX, "Y Start", "", INT_MIN, INT_MAX);
RNA_def_int(ot->srna, "yend", 0, INT_MIN, INT_MAX, "Y End", "", INT_MIN, INT_MAX);
- if (cursor)
- RNA_def_int(ot->srna, "cursor", cursor, 0, INT_MAX, "Cursor", "Mouse cursor style to use during the modal operator", 0, INT_MAX);
+ if (cursor) {
+ PropertyRNA *prop;
+
+ prop = RNA_def_int(ot->srna, "cursor", cursor, 0, INT_MAX,
+ "Cursor", "Mouse cursor style to use during the modal operator", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ }
}
@@ -1072,13 +1264,22 @@ static void wm_block_redo_cb(bContext *C, void *arg_op, int UNUSED(arg_event))
}
}
+static void wm_block_redo_cancel_cb(bContext *C, void *arg_op)
+{
+ wmOperator *op = arg_op;
+
+ /* if operator never got executed, free it */
+ if (op != WM_operator_last_redo(C))
+ WM_operator_free(op);
+}
+
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();
- int width = 300;
+ int width = 15 * UI_UNIT_X;
block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
uiBlockClearFlag(block, UI_BLOCK_LOOP);
@@ -1158,7 +1359,7 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData)
block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
uiBlockClearFlag(block, UI_BLOCK_LOOP);
- /* intentionally don't use 'UI_BLOCK_MOVEMOUSE_QUIT', some dialogs have many items
+ /* 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);
@@ -1214,7 +1415,7 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData)
return block;
}
-static void wm_operator_ui_popup_cancel(void *userData)
+static void wm_operator_ui_popup_cancel(struct bContext *UNUSED(C), void *userData)
{
wmOpPopUp *data = userData;
if (data->free_op && data->op) {
@@ -1262,9 +1463,9 @@ static int wm_operator_props_popup_ex(bContext *C, wmOperator *op, const int do_
/* if we don't have global undo, we can't do undo push for automatic redo,
* so we require manual OK clicking in this popup */
if (!(U.uiflag & USER_GLOBALUNDO))
- return WM_operator_props_dialog_popup(C, op, 300, UI_UNIT_Y);
+ return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, UI_UNIT_Y);
- uiPupBlock(C, wm_block_create_redo, op);
+ uiPupBlockEx(C, wm_block_create_redo, NULL, wm_block_redo_cancel_cb, op);
if (do_call)
wm_block_redo_cb(C, op, 0);
@@ -1276,12 +1477,12 @@ static int wm_operator_props_popup_ex(bContext *C, wmOperator *op, const int do_
* 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] */
-int WM_operator_props_popup_call(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+int WM_operator_props_popup_call(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
return wm_operator_props_popup_ex(C, op, TRUE);
}
-int WM_operator_props_popup(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+int WM_operator_props_popup(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
return wm_operator_props_popup_ex(C, op, FALSE);
}
@@ -1330,7 +1531,7 @@ static int wm_debug_menu_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int wm_debug_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int wm_debug_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
RNA_int_set(op->ptr, "debug_value", G.debug_value);
return WM_operator_props_dialog_popup(C, op, 9 * UI_UNIT_X, UI_UNIT_Y);
@@ -1399,14 +1600,14 @@ static void wm_block_splash_refreshmenu(bContext *UNUSED(C), void *UNUSED(arg_bl
static int wm_resource_check_prev(void)
{
- char *res = BLI_get_folder_version(BLENDER_RESOURCE_PATH_USER, BLENDER_VERSION, TRUE);
+ const char *res = BLI_get_folder_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 = BLI_get_folder_version(BLENDER_RESOURCE_PATH_LOCAL, BLENDER_VERSION, true);
}
#endif
@@ -1415,7 +1616,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 (BLI_get_folder_version(BLENDER_RESOURCE_PATH_USER, BLENDER_VERSION - 1, true) != NULL);
}
}
@@ -1429,7 +1630,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
int i;
MenuType *mt = WM_menutype_find("USERPREF_MT_splash", TRUE);
char url[96];
- char file [FILE_MAX];
+ char file[FILE_MAX];
#ifndef WITH_HEADLESS
extern char datatoc_splash_png[];
@@ -1452,9 +1653,9 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
"%d.%02d.%d", BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION);
BLI_snprintf(revision_buf, sizeof(revision_buf), "r%s", build_rev);
- BLF_size(style->widgetlabel.uifont_id, style->widgetlabel.points, U.dpi);
- ver_width = (int)BLF_width(style->widgetlabel.uifont_id, version_buf) + 5;
- rev_width = (int)BLF_width(style->widgetlabel.uifont_id, revision_buf) + 5;
+ BLF_size(style->widgetlabel.uifont_id, style->widgetlabel.points, U.pixelsize * U.dpi);
+ ver_width = (int)BLF_width(style->widgetlabel.uifont_id, version_buf) + 0.5f * U.widget_unit;
+ rev_width = (int)BLF_width(style->widgetlabel.uifont_id, revision_buf) + 0.5f * U.widget_unit;
#endif /* WITH_BUILDINFO */
block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
@@ -1464,16 +1665,17 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
* 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);
- but = uiDefBut(block, BUT_IMAGE, 0, "", 0, 10, 501, 282, ibuf, 0.0, 0.0, 0, 0, ""); /* button owns the imbuf now */
+ /* 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);
#ifdef WITH_BUILDINFO
- uiDefBut(block, LABEL, 0, version_buf, 494 - ver_width, 282 - 24, ver_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
- uiDefBut(block, LABEL, 0, revision_buf, 494 - rev_width, 282 - 36, rev_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+ uiDefBut(block, LABEL, 0, version_buf, U.pixelsize * 494 - ver_width, U.pixelsize * 258, ver_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+ uiDefBut(block, LABEL, 0, revision_buf, U.pixelsize * 494 - rev_width, U.pixelsize * 246, rev_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
#endif /* WITH_BUILDINFO */
- layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 10, 2, 480, 110, style);
+ layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 10, 2, U.pixelsize * 480, U.pixelsize * 110, style);
uiBlockSetEmboss(block, UI_EMBOSS);
/* show the splash menu (containing interaction presets), using python */
@@ -1492,18 +1694,26 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
split = uiLayoutSplit(layout, 0.0f, FALSE);
col = uiLayoutColumn(split, FALSE);
- uiItemL(col, "Links", ICON_NONE);
- uiItemStringO(col, IFACE_("Donations"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/blenderorg/blender-foundation/donation-payment");
- uiItemStringO(col, IFACE_("Credits"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/development/credits");
- uiItemStringO(col, IFACE_("Release Log"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/development/release-logs/blender-265");
- uiItemStringO(col, IFACE_("Manual"), ICON_URL, "WM_OT_url_open", "url", "http://wiki.blender.org/index.php/Doc:2.6/Manual");
+ uiItemL(col, IFACE_("Links"), ICON_NONE);
+ uiItemStringO(col, IFACE_("Donations"), ICON_URL, "WM_OT_url_open", "url",
+ "http://www.blender.org/blenderorg/blender-foundation/donation-payment");
+ uiItemStringO(col, IFACE_("Credits"), ICON_URL, "WM_OT_url_open", "url",
+ "http://www.blender.org/development/credits");
+ uiItemStringO(col, IFACE_("Release Log"), ICON_URL, "WM_OT_url_open", "url",
+ "http://www.blender.org/development/release-logs/blender-266");
+ uiItemStringO(col, IFACE_("Manual"), ICON_URL, "WM_OT_url_open", "url",
+ "http://wiki.blender.org/index.php/Doc:2.6/Manual");
uiItemStringO(col, IFACE_("Blender Website"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org");
- uiItemStringO(col, IFACE_("User Community"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/community/user-community");
- if (strcmp(STRINGIFY(BLENDER_VERSION_CYCLE), "release") == 0) {
- BLI_snprintf(url, sizeof(url), "http://www.blender.org/documentation/blender_python_api_%d_%d" STRINGIFY(BLENDER_VERSION_CHAR) "_release", BLENDER_VERSION / 100, BLENDER_VERSION % 100);
+ uiItemStringO(col, IFACE_("User Community"), ICON_URL, "WM_OT_url_open", "url",
+ "http://www.blender.org/community/user-community");
+ if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "release")) {
+ BLI_snprintf(url, sizeof(url), "http://www.blender.org/documentation/blender_python_api_%d_%d"
+ STRINGIFY(BLENDER_VERSION_CHAR) "_release",
+ BLENDER_VERSION / 100, BLENDER_VERSION % 100);
}
else {
- BLI_snprintf(url, sizeof(url), "http://www.blender.org/documentation/blender_python_api_%d_%d_%d", BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION);
+ BLI_snprintf(url, sizeof(url), "http://www.blender.org/documentation/blender_python_api_%d_%d_%d",
+ BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION);
}
uiItemStringO(col, IFACE_("Python API Reference"), ICON_URL, "WM_OT_url_open", "url", url);
uiItemL(col, "", ICON_NONE);
@@ -1534,7 +1744,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
return block;
}
-static int wm_splash_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
+static int wm_splash_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
uiPupBlock(C, wm_block_create_splash, NULL);
@@ -1588,7 +1798,7 @@ static int wm_search_menu_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-static int wm_search_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int wm_search_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
uiPupBlock(C, wm_block_search_menu, op);
@@ -1640,6 +1850,7 @@ static void WM_OT_call_menu(wmOperatorType *ot)
{
ot->name = "Call Menu";
ot->idname = "WM_OT_call_menu";
+ ot->description = "Call (draw) a pre-defined menu";
ot->exec = wm_call_menu_exec;
ot->poll = WM_operator_winactive;
@@ -1675,12 +1886,23 @@ static void WM_OT_window_duplicate(wmOperatorType *ot)
static void WM_OT_save_homefile(wmOperatorType *ot)
{
- ot->name = "Save User Settings";
+ ot->name = "Save Startup File";
ot->idname = "WM_OT_save_homefile";
- ot->description = "Make the current file the default .blend file";
+ ot->description = "Make the current file the default .blend file, includes preferences";
ot->invoke = WM_operator_confirm;
- ot->exec = WM_homefile_write_exec;
+ ot->exec = wm_homefile_write_exec;
+ ot->poll = WM_operator_winactive;
+}
+
+static void WM_OT_save_userpref(wmOperatorType *ot)
+{
+ ot->name = "Save User Settings";
+ ot->idname = "WM_OT_save_userpref";
+ ot->description = "Save user preferences separately, overrides startup file preferences";
+
+ ot->invoke = WM_operator_confirm;
+ ot->exec = wm_userpref_write_exec;
ot->poll = WM_operator_winactive;
}
@@ -1691,7 +1913,7 @@ static void WM_OT_read_homefile(wmOperatorType *ot)
ot->description = "Open the default file (doesn't save the current file)";
ot->invoke = WM_operator_confirm;
- ot->exec = WM_homefile_read_exec;
+ ot->exec = wm_homefile_read_exec;
/* ommit poll to run in background mode */
}
@@ -1702,7 +1924,7 @@ static void WM_OT_read_factory_settings(wmOperatorType *ot)
ot->description = "Load default file and user preferences";
ot->invoke = WM_operator_confirm;
- ot->exec = WM_homefile_read_exec;
+ ot->exec = wm_homefile_read_exec;
/* ommit poll to run in background mode */
}
@@ -1724,7 +1946,7 @@ static void open_set_use_scripts(wmOperator *op)
}
}
-static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
const char *openname = G.main->name;
@@ -1803,7 +2025,7 @@ static int wm_link_append_poll(bContext *C)
if (WM_operator_winactive(C)) {
/* linking changes active object which is pretty useful in general,
* but which totally confuses edit mode (i.e. it becoming not so obvious
- * to leave from edit mode and inwalid tools in toolbar might be displayed)
+ * to leave from edit mode and invalid tools in toolbar might be displayed)
* so disable link/append when in edit mode (sergey) */
if (CTX_data_edit_object(C))
return 0;
@@ -1814,7 +2036,7 @@ static int wm_link_append_poll(bContext *C)
return 0;
}
-static int wm_link_append_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int wm_link_append_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (RNA_struct_property_is_set(op->ptr, "filepath")) {
return WM_operator_call_notest(C, op);
@@ -1948,7 +2170,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
/* append, rather than linking */
if ((flag & FILE_LINK) == 0) {
Library *lib = BLI_findstring(&bmain->library, libname, offsetof(Library, filepath));
- if (lib) BKE_library_make_local(bmain, lib, 1);
+ if (lib) BKE_library_make_local(bmain, lib, true);
else BLI_assert(!"cant find name of just added library!");
}
@@ -1957,8 +2179,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
flag_all_listbases_ids(LIB_PRE_EXISTING, 0);
/* recreate dependency graph to include new objects */
- DAG_scene_sort(bmain, scene);
- DAG_ids_flush_update(bmain, 0);
+ DAG_scene_relations_rebuild(bmain, scene);
BLO_blendhandle_close(bh);
@@ -2003,21 +2224,38 @@ static void WM_OT_link_append(wmOperatorType *ot)
/* *************** recover last session **************** */
-static int wm_recover_last_session_exec(bContext *C, wmOperator *op)
+void wm_recover_last_session(bContext *C, ReportList *reports)
{
char filename[FILE_MAX];
+
+ BLI_make_file_string("/", filename, BLI_temporary_dir(), BLENDER_QUIT_FILE);
+ /* if reports==NULL, it's called directly without operator, we add a quick check here */
+ if (reports || BLI_exists(filename)) {
+ G.fileflags |= G_FILE_RECOVER;
+
+ /* XXX wm in context is not set correctly after WM_file_read -> crash */
+ /* do it before for now, but is this correct with multiple windows? */
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+ /* load file */
+ WM_file_read(C, filename, reports);
+
+ G.fileflags &= ~G_FILE_RECOVER;
+
+ /* XXX bad global... fixme */
+ if (G.main->name[0])
+ G.file_loaded = 1; /* prevents splash to show */
+ else {
+ G.relbase_valid = 0;
+ G.save_over = 0; /* start with save preference untitled.blend */
+ }
- G.fileflags |= G_FILE_RECOVER;
-
- /* XXX wm in context is not set correctly after WM_file_read -> crash */
- /* do it before for now, but is this correct with multiple windows? */
- WM_event_add_notifier(C, NC_WINDOW, NULL);
-
- /* load file */
- BLI_make_file_string("/", filename, BLI_temporary_dir(), "quit.blend");
- WM_file_read(C, filename, op->reports);
+ }
+}
- G.fileflags &= ~G_FILE_RECOVER;
+static int wm_recover_last_session_exec(bContext *C, wmOperator *op)
+{
+ wm_recover_last_session(C, op->reports);
return OPERATOR_FINISHED;
}
@@ -2025,7 +2263,7 @@ static void WM_OT_recover_last_session(wmOperatorType *ot)
{
ot->name = "Recover Last Session";
ot->idname = "WM_OT_recover_last_session";
- ot->description = "Open the last closed file (\"quit.blend\")";
+ ot->description = "Open the last closed file (\"" BLENDER_QUIT_FILE "\")";
ot->exec = wm_recover_last_session_exec;
ot->poll = WM_operator_winactive;
@@ -2049,11 +2287,11 @@ static int wm_recover_auto_save_exec(bContext *C, wmOperator *op)
WM_file_read(C, path, op->reports);
G.fileflags &= ~G_FILE_RECOVER;
-
+
return OPERATOR_FINISHED;
}
-static int wm_recover_auto_save_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int wm_recover_auto_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
char filename[FILE_MAX];
@@ -2083,7 +2321,7 @@ static void WM_OT_recover_auto_save(wmOperatorType *ot)
static void untitled(char *filepath)
{
if (G.save_over == 0 && strlen(filepath) < FILE_MAX - 16) {
- char *c = BLI_last_slash(filepath);
+ char *c = (char *)BLI_last_slash(filepath);
if (c)
strcpy(&c[1], "untitled.blend");
@@ -2102,7 +2340,7 @@ static void save_set_compress(wmOperator *op)
}
}
-static int wm_save_as_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int wm_save_as_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
char name[FILE_MAX];
@@ -2139,7 +2377,7 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
untitled(path);
}
- fileflags = G.fileflags;
+ fileflags = G.fileflags & ~G_FILE_USERPREFS;
/* set compression flag */
BKE_BIT_TEST_SET(fileflags, RNA_boolean_get(op->ptr, "compress"),
@@ -2158,7 +2396,7 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
G_FILE_MESH_COMPAT);
#endif
- if (WM_file_write(C, path, fileflags, op->reports) != 0)
+ if (wm_file_write(C, path, fileflags, op->reports) != 0)
return OPERATOR_CANCELLED;
WM_event_add_notifier(C, NC_WM | ND_FILESAVE, NULL);
@@ -2173,7 +2411,7 @@ static int blend_save_check(bContext *UNUSED(C), wmOperator *op)
RNA_string_get(op->ptr, "filepath", filepath);
if (!BLO_has_bfile_extension(filepath)) {
/* some users would prefer BLI_replace_extension(),
- * we keep getting knit-picking bug reports about this - campbell */
+ * we keep getting nitpicking bug reports about this - campbell */
BLI_ensure_extension(filepath, FILE_MAX, ".blend");
RNA_string_set(op->ptr, "filepath", filepath);
return TRUE;
@@ -2208,7 +2446,7 @@ static void WM_OT_save_as_mainfile(wmOperatorType *ot)
/* *************** save file directly ******** */
-static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
char name[FILE_MAX];
int ret;
@@ -2307,9 +2545,8 @@ static int wm_console_toggle_op(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...
- * And even worth, have to give the context as text, as xgettext doesn't expand macros. :( */
- ot->name = CTX_N_("Operator" /* BLF_I18NCONTEXT_OPERATOR_DEFAULT */, "Toggle System Console");
+ /* 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->idname = "WM_OT_console_toggle";
ot->description = N_("Toggle System Console");
@@ -2415,7 +2652,7 @@ static void wm_gesture_end(bContext *C, wmOperator *op)
WM_cursor_restore(CTX_wm_window(C));
}
-int WM_border_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+int WM_border_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (ISTWEAK(event->type))
op->customdata = WM_gesture_new(C, event, WM_GESTURE_RECT);
@@ -2430,7 +2667,7 @@ int WM_border_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-int WM_border_select_modal(bContext *C, wmOperator *op, wmEvent *event)
+int WM_border_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
wmGesture *gesture = op->customdata;
rcti *rect = gesture->customdata;
@@ -2499,7 +2736,7 @@ int WM_border_select_cancel(bContext *C, wmOperator *op)
int circle_select_size = 25; /* XXX - need some operator memory thing! */
#endif
-int WM_gesture_circle_invoke(bContext *C, wmOperator *op, wmEvent *event)
+int WM_gesture_circle_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
op->customdata = WM_gesture_new(C, event, WM_GESTURE_CIRCLE);
@@ -2534,7 +2771,7 @@ static void gesture_circle_apply(bContext *C, wmOperator *op)
#endif
}
-int WM_gesture_circle_modal(bContext *C, wmOperator *op, wmEvent *event)
+int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
wmGesture *gesture = op->customdata;
rcti *rect = gesture->customdata;
@@ -2552,7 +2789,18 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, wmEvent *event)
gesture_circle_apply(C, op);
}
else if (event->type == EVT_MODAL_MAP) {
+ float fac;
+
switch (event->val) {
+ case GESTURE_MODAL_CIRCLE_SIZE:
+ fac = 0.3f * (event->y - event->prevy);
+ if (fac > 0)
+ rect->xmax += ceil(fac);
+ else
+ rect->xmax += floor(fac);
+ if (rect->xmax < 1) rect->xmax = 1;
+ wm_gesture_tag_redraw(C);
+ break;
case GESTURE_MODAL_CIRCLE_ADD:
rect->xmax += 2 + rect->xmax / 10;
wm_gesture_tag_redraw(C);
@@ -2582,7 +2830,8 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_FINISHED; /* use finish or we don't get an undo */
}
}
-// /* Allow view navigation??? */
+ /* Allow view navigation??? */
+ /* note, this gives issues: 1) other modal ops run on top (border select), 2) middlemouse is used now 3) tablet/trackpad? */
// else {
// return OPERATOR_PASS_THROUGH;
// }
@@ -2619,7 +2868,7 @@ void WM_OT_circle_gesture(wmOperatorType *ot)
/* **************** Tweak gesture *************** */
-static void tweak_gesture_modal(bContext *C, wmEvent *event)
+static void tweak_gesture_modal(bContext *C, const wmEvent *event)
{
wmWindow *window = CTX_wm_window(C);
wmGesture *gesture = window->tweak;
@@ -2661,7 +2910,9 @@ static void tweak_gesture_modal(bContext *C, wmEvent *event)
WM_gesture_end(C, gesture);
/* when tweak fails we should give the other keymap entries a chance */
- event->val = KM_RELEASE;
+
+ /* XXX, assigning to readonly, BAD JUJU! */
+ ((wmEvent *)event)->val = KM_RELEASE;
}
break;
default:
@@ -2697,7 +2948,7 @@ void wm_tweakevent_test(bContext *C, wmEvent *event, int action)
/* *********************** lasso gesture ****************** */
-int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, wmEvent *event)
+int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
op->customdata = WM_gesture_new(C, event, WM_GESTURE_LASSO);
@@ -2712,7 +2963,7 @@ int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-int WM_gesture_lines_invoke(bContext *C, wmOperator *op, wmEvent *event)
+int WM_gesture_lines_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
op->customdata = WM_gesture_new(C, event, WM_GESTURE_LINES);
@@ -2754,7 +3005,7 @@ static void gesture_lasso_apply(bContext *C, wmOperator *op)
}
}
-int WM_gesture_lasso_modal(bContext *C, wmOperator *op, wmEvent *event)
+int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
wmGesture *gesture = op->customdata;
int sx, sy;
@@ -2810,7 +3061,7 @@ int WM_gesture_lasso_modal(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-int WM_gesture_lines_modal(bContext *C, wmOperator *op, wmEvent *event)
+int WM_gesture_lines_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
return WM_gesture_lasso_modal(C, op, event);
}
@@ -2929,7 +3180,7 @@ static int straightline_apply(bContext *C, wmOperator *op)
}
-int WM_gesture_straightline_invoke(bContext *C, wmOperator *op, wmEvent *event)
+int WM_gesture_straightline_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
op->customdata = WM_gesture_new(C, event, WM_GESTURE_STRAIGHTLINE);
@@ -2944,7 +3195,7 @@ int WM_gesture_straightline_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-int WM_gesture_straightline_modal(bContext *C, wmOperator *op, wmEvent *event)
+int WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
wmGesture *gesture = op->customdata;
rcti *rect = gesture->customdata;
@@ -3036,7 +3287,7 @@ typedef struct {
void *cursor;
} RadialControl;
-static void radial_control_set_initial_mouse(RadialControl *rc, wmEvent *event)
+static void radial_control_set_initial_mouse(RadialControl *rc, const wmEvent *event)
{
float d[2] = {0, 0};
float zoom[2] = {1, 1};
@@ -3045,6 +3296,7 @@ static void radial_control_set_initial_mouse(RadialControl *rc, wmEvent *event)
rc->initial_mouse[1] = event->y;
switch (rc->subtype) {
+ case PROP_NONE:
case PROP_DISTANCE:
d[0] = rc->initial_value;
break;
@@ -3144,6 +3396,7 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd
float zoom[2], col[3] = {1, 1, 1};
switch (rc->subtype) {
+ case PROP_NONE:
case PROP_DISTANCE:
r1 = rc->current_value;
r2 = rc->initial_value;
@@ -3165,6 +3418,11 @@ 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;
@@ -3284,7 +3542,7 @@ static int radial_control_get_properties(bContext *C, wmOperator *op)
{
RadialControl *rc = op->customdata;
PointerRNA ctx_ptr, use_secondary_ptr;
- PropertyRNA *use_secondary_prop;
+ PropertyRNA *use_secondary_prop = NULL;
const char *data_path;
RNA_pointer_create(NULL, &RNA_Context, C, &ctx_ptr);
@@ -3345,7 +3603,7 @@ static int radial_control_get_properties(bContext *C, wmOperator *op)
return 1;
}
-static int radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int radial_control_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
wmWindowManager *wm;
RadialControl *rc;
@@ -3382,8 +3640,8 @@ static int radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
/* get subtype of property */
rc->subtype = RNA_property_subtype(rc->prop);
- if (!ELEM3(rc->subtype, PROP_DISTANCE, PROP_FACTOR, PROP_ANGLE)) {
- BKE_report(op->reports, RPT_ERROR, "Property must be a distance, a factor, or an angle");
+ if (!ELEM4(rc->subtype, PROP_NONE, PROP_DISTANCE, PROP_FACTOR, PROP_ANGLE)) {
+ BKE_report(op->reports, RPT_ERROR, "Property must be a none, distance, a factor, or an angle");
MEM_freeN(rc);
return OPERATOR_CANCELLED;
}
@@ -3442,7 +3700,7 @@ static int radial_control_cancel(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
RadialControl *rc = op->customdata;
float new_value, dist, zoom[2];
@@ -3467,6 +3725,7 @@ static int radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
/* calculate new value and apply snapping */
switch (rc->subtype) {
+ case PROP_NONE:
case PROP_DISTANCE:
new_value = dist;
if (snap) new_value = ((int)new_value + 5) / 10 * 10;
@@ -3743,7 +4002,7 @@ static int wm_ndof_sensitivity_exec(bContext *UNUSED(C), wmOperator *op)
static void WM_OT_ndof_sensitivity_change(wmOperatorType *ot)
{
- ot->name = "Change NDOF sensitivity";
+ ot->name = "Change NDOF Sensitivity";
ot->idname = "WM_OT_ndof_sensitivity_change";
ot->description = "Change NDOF sensitivity";
@@ -3787,6 +4046,7 @@ void wm_operatortype_init(void)
WM_operatortype_append(WM_OT_read_homefile);
WM_operatortype_append(WM_OT_read_factory_settings);
WM_operatortype_append(WM_OT_save_homefile);
+ WM_operatortype_append(WM_OT_save_userpref);
WM_operatortype_append(WM_OT_window_fullscreen_toggle);
WM_operatortype_append(WM_OT_quit_blender);
WM_operatortype_append(WM_OT_open_mainfile);
@@ -3818,6 +4078,7 @@ static void gesture_circle_modal_keymap(wmKeyConfig *keyconf)
{GESTURE_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
{GESTURE_MODAL_CIRCLE_ADD, "ADD", 0, "Add", ""},
{GESTURE_MODAL_CIRCLE_SUB, "SUBTRACT", 0, "Subtract", ""},
+ {GESTURE_MODAL_CIRCLE_SIZE, "SIZE", 0, "Size", ""},
{GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""},
{GESTURE_MODAL_DESELECT, "DESELECT", 0, "DeSelect", ""},
@@ -3856,6 +4117,7 @@ static void gesture_circle_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, PADMINUS, KM_PRESS, 0, 0, GESTURE_MODAL_CIRCLE_SUB);
WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, 0, 0, GESTURE_MODAL_CIRCLE_ADD);
WM_modalkeymap_add_item(keymap, PADPLUSKEY, KM_PRESS, 0, 0, GESTURE_MODAL_CIRCLE_ADD);
+ WM_modalkeymap_add_item(keymap, MOUSEPAN, 0, 0, 0, GESTURE_MODAL_CIRCLE_SIZE);
/* assign map to operators */
WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_circle");
@@ -3891,6 +4153,7 @@ static void gesture_straightline_modal_keymap(wmKeyConfig *keyconf)
/* assign map to operators */
WM_modalkeymap_assign(keymap, "IMAGE_OT_sample_line");
+ WM_modalkeymap_assign(keymap, "PAINT_OT_weight_gradient");
}
@@ -3939,6 +4202,7 @@ static void gesture_border_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_assign(keymap, "MARKER_OT_select_border");
WM_modalkeymap_assign(keymap, "NLA_OT_select_border");
WM_modalkeymap_assign(keymap, "NODE_OT_select_border");
+ WM_modalkeymap_assign(keymap, "NODE_OT_viewer_border");
WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show");
WM_modalkeymap_assign(keymap, "OUTLINER_OT_select_border");
// WM_modalkeymap_assign(keymap, "SCREEN_OT_border_select"); // template
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index 8b387196da7..e4e529ace71 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -49,12 +49,12 @@
#include "PIL_time.h"
+#include "BLI_utildefines.h"
#include "BLI_fileops.h"
#include "BLI_listbase.h"
#include "BLI_path_util.h"
#include "BLI_rect.h"
#include "BLI_string.h"
-#include "BLI_utildefines.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -76,10 +76,16 @@
#include "WM_api.h" /* only for WM_main_playanim */
struct PlayState;
-static void playanim_window_zoom(const struct PlayState *ps, const float zoom_offset);
+static void playanim_window_zoom(struct PlayState *ps, const float zoom_offset);
typedef struct PlayState {
+ /* window and viewport size */
+ int win_x, win_y;
+
+ /* current zoom level */
+ float zoom;
+
/* playback state */
short direction;
short next_frame;
@@ -91,7 +97,7 @@ typedef struct PlayState {
short wait2;
short stopped;
short go;
-
+
int fstep;
/* current picture */
@@ -103,6 +109,9 @@ typedef struct PlayState {
/* saves passing args */
struct ImBuf *curframe_ibuf;
+
+ /* restarts player for file drop */
+ char dropped_file[FILE_MAX];
} PlayState;
/* for debugging */
@@ -204,7 +213,6 @@ typedef struct PlayAnimPict {
static struct ListBase picsbase = {NULL, NULL};
static int fromdisk = FALSE;
-static float zoomx = 1.0, zoomy = 1.0;
static double ptottime = 0.0, swaptime = 0.04;
static PlayAnimPict *playanim_step(PlayAnimPict *playanim, int step)
@@ -234,8 +242,9 @@ static int pupdate_time(void)
return (ptottime < 0);
}
-static void playanim_toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fontid, int fstep)
+static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf *ibuf, int fontid, int fstep)
{
+ float offsx, offsy;
if (ibuf == NULL) {
printf("%s: no ibuf for picture '%s'\n", __func__, picture ? picture->name : "<NIL>");
@@ -250,10 +259,29 @@ static void playanim_toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fon
GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
- glRasterPos2f(0.0f, 0.0f);
+ /* 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);
+
+ CLAMP(offsx, 0.0f, 1.0f);
+ CLAMP(offsy, 0.0f, 1.0f);
+ glRasterPos2f(offsx, offsy);
+
+ glClearColor(0.1, 0.1, 0.1, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* checkerboard for case alpha */
+ if (ibuf->planes == 32) {
+ 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);
+ }
+
glDrawPixels(ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ glDisable(GL_BLEND);
+
pupdate_time();
if (picture && (g_WS.qual & (WS_QUAL_SHIFT | WS_QUAL_LMOUSE)) && (fontid != -1)) {
@@ -276,7 +304,7 @@ static void playanim_toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fon
GHOST_SwapWindowBuffers(g_WS.ghost_window);
}
-static void build_pict_list(char *first, int totframes, int fstep, int fontid)
+static void build_pict_list(PlayState *ps, char *first, int totframes, int fstep, int fontid)
{
char *mem, filepath[FILE_MAX];
// short val;
@@ -292,7 +320,7 @@ static void build_pict_list(char *first, int totframes, int fstep, int fontid)
int pic;
ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
if (ibuf) {
- playanim_toscreen(NULL, ibuf, fontid, fstep);
+ playanim_toscreen(ps, NULL, ibuf, fontid, fstep);
IMB_freeImBuf(ibuf);
}
@@ -395,7 +423,7 @@ static void build_pict_list(char *first, int totframes, int fstep, int fontid)
ibuf = IMB_loadiffname(picture->name, picture->IB_flags, NULL);
}
if (ibuf) {
- playanim_toscreen(picture, ibuf, fontid, fstep);
+ playanim_toscreen(ps, picture, ibuf, fontid, fstep);
IMB_freeImBuf(ibuf);
}
pupdate_time();
@@ -580,7 +608,9 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
case GHOST_kKeyPeriod:
case GHOST_kKeyNumpadPeriod:
if (val) {
- if (ps->sstep) ps->wait2 = FALSE;
+ if (ps->sstep) {
+ ps->wait2 = FALSE;
+ }
else {
ps->sstep = TRUE;
ps->wait2 = !ps->wait2;
@@ -689,35 +719,41 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
break;
}
case GHOST_kEventWindowActivate:
- case GHOST_kEventWindowDeactivate: {
+ case GHOST_kEventWindowDeactivate:
+ {
g_WS.qual &= ~WS_QUAL_MOUSE;
break;
}
case GHOST_kEventWindowSize:
case GHOST_kEventWindowMove:
{
- int sizex, sizey;
-
- playanim_window_get_size(&sizex, &sizey);
+ float zoomx, zoomy;
+
+ playanim_window_get_size(&ps->win_x, &ps->win_y);
GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
- glViewport(0, 0, sizex, sizey);
- glScissor(0, 0, sizex, sizey);
-
- zoomx = (float) sizex / ps->ibufx;
- zoomy = (float) sizey / ps->ibufy;
- zoomx = floor(zoomx + 0.5f);
- zoomy = floor(zoomy + 0.5f);
- if (zoomx < 1.0f) zoomx = 1.0f;
- if (zoomy < 1.0f) zoomy = 1.0f;
-
- sizex = zoomx * ps->ibufx;
- sizey = zoomy * ps->ibufy;
+ zoomx = (float) ps->win_x / ps->ibufx;
+ zoomy = (float) ps->win_y / ps->ibufy;
+
+ /* zoom always show entire image */
+ ps->zoom = MIN2(zoomx, zoomy);
+
+ /* zoom steps of 2 for speed */
+ ps->zoom = floor(ps->zoom + 0.5f);
+ if (ps->zoom < 1.0f) ps->zoom = 1.0f;
+
+ 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);
- glPixelZoom(zoomx, zoomy);
- glEnable(GL_DITHER);
+ glPixelZoom(ps->zoom, ps->zoom);
ptottime = 0.0;
- playanim_toscreen(ps->picture, ps->curframe_ibuf, ps->fontid, ps->fstep);
+ playanim_toscreen(ps, ps->picture, ps->curframe_ibuf, ps->fontid, ps->fstep);
break;
}
@@ -727,6 +763,23 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
ps->go = FALSE;
break;
}
+ case GHOST_kEventDraggingDropDone:
+ {
+ GHOST_TEventDragnDropData *ddd = GHOST_GetEventData(evt);
+
+ if (ddd->dataType == GHOST_kDragnDropTypeFilenames) {
+ GHOST_TStringArray *stra = ddd->data;
+ int a;
+
+ for (a = 0; a < stra->count; a++) {
+ BLI_strncpy(ps->dropped_file, (char *)stra->strings[a], sizeof(ps->dropped_file));
+ ps->go = FALSE;
+ printf("drop file %s\n", stra->strings[a]);
+ break; /* only one drop element supported now */
+ }
+ }
+ break;
+ }
default:
/* quiet warnings */
break;
@@ -757,32 +810,31 @@ static void playanim_window_open(const char *title, int posx, int posy, int size
FALSE /* no stereo */, FALSE);
}
-static void playanim_window_zoom(const PlayState *ps, const float zoom_offset)
+static void playanim_window_zoom(PlayState *ps, const float zoom_offset)
{
int sizex, sizey;
/* int ofsx, ofsy; */ /* UNUSED */
- if (zoomx + zoom_offset > 0.0f) zoomx += zoom_offset;
- if (zoomy + zoom_offset > 0.0f) zoomy += zoom_offset;
+ if (ps->zoom + zoom_offset > 0.0f) ps->zoom += zoom_offset;
// playanim_window_get_position(&ofsx, &ofsy);
playanim_window_get_size(&sizex, &sizey);
/* ofsx += sizex / 2; */ /* UNUSED */
/* ofsy += sizey / 2; */ /* UNUSED */
- sizex = zoomx * ps->ibufx;
- sizey = zoomy * ps->ibufy;
+ sizex = ps->zoom * ps->ibufx;
+ sizey = ps->zoom * ps->ibufy;
/* ofsx -= sizex / 2; */ /* UNUSED */
/* ofsy -= sizey / 2; */ /* UNUSED */
- // window_set_position(g_WS.ghost_window,sizex,sizey);
+ // window_set_position(g_WS.ghost_window, sizex, sizey);
GHOST_SetClientSize(g_WS.ghost_window, sizex, sizey);
}
-void WM_main_playanim(int argc, const char **argv)
+/* return path for restart */
+static char *wm_main_playanim_intern(int argc, const char **argv)
{
struct ImBuf *ibuf = NULL;
- char filepath[FILE_MAX];
+ static char filepath[FILE_MAX]; /* abused to return dropped file path */
GHOST_TUns32 maxwinx, maxwiny;
- /* short c233 = FALSE, yuvx = FALSE; */ /* UNUSED */
int i;
/* This was done to disambiguate the name for use under c++. */
struct anim *anim = NULL;
@@ -790,7 +842,7 @@ void WM_main_playanim(int argc, const char **argv)
int sfra = -1;
int efra = -1;
int totblock;
-
+
PlayState ps = {0};
/* ps.doubleb = TRUE;*/ /* UNUSED */
@@ -805,6 +857,8 @@ void WM_main_playanim(int argc, const char **argv)
ps.wait2 = FALSE;
ps.stopped = FALSE;
ps.picture = NULL;
+ ps.dropped_file[0] = 0;
+ ps.zoom = 1.0f;
/* resetmap = FALSE */
ps.fstep = 1;
@@ -910,20 +964,16 @@ void WM_main_playanim(int argc, const char **argv)
#endif
#endif //XXX25
- /* XXX, fixme zr */
{
-// extern void add_to_mainqueue(wmWindow *win, void *user_data, short evt, short val, char ascii);
GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(ghost_event_proc, &ps);
g_WS.ghost_system = GHOST_CreateSystem();
GHOST_AddEventConsumer(g_WS.ghost_system, consumer);
-
-
playanim_window_open("Blender:Anim", start_x, start_y, ibuf->x, ibuf->y, 0);
-//XXX25 window_set_handler(g_WS.ghost_window, add_to_mainqueue, NULL);
+ /* 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);
@@ -941,11 +991,15 @@ void WM_main_playanim(int argc, const char **argv)
ps.ibufx = ibuf->x;
ps.ibufy = ibuf->y;
+
+ ps.win_x = ps.ibufx;
+ ps.win_y = ps.ibufy;
if (maxwinx % ibuf->x) maxwinx = ibuf->x * (1 + (maxwinx / ibuf->x));
if (maxwiny % ibuf->y) maxwiny = ibuf->y * (1 + (maxwiny / ibuf->y));
- glClearColor(0.0, 0.0, 0.0, 0.0);
+
+ glClearColor(0.1, 0.1, 0.1, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
GHOST_SwapWindowBuffers(g_WS.ghost_window);
@@ -956,11 +1010,11 @@ void WM_main_playanim(int argc, const char **argv)
efra = MAXFRAME;
}
- build_pict_list(filepath, (efra - sfra) + 1, ps.fstep, ps.fontid);
+ build_pict_list(&ps, filepath, (efra - sfra) + 1, ps.fstep, ps.fontid);
for (i = 2; i < argc; i++) {
BLI_strncpy(filepath, argv[i], sizeof(filepath));
- build_pict_list(filepath, (efra - sfra) + 1, ps.fstep, ps.fontid);
+ build_pict_list(&ps, filepath, (efra - sfra) + 1, ps.fstep, ps.fontid);
}
IMB_freeImBuf(ibuf);
@@ -1033,8 +1087,8 @@ void WM_main_playanim(int argc, const char **argv)
while (pupdate_time()) PIL_sleep_ms(1);
ptottime -= swaptime;
- playanim_toscreen(ps.picture, ibuf, ps.fontid, ps.fstep);
- } /* else deleten */
+ playanim_toscreen(&ps, ps.picture, ibuf, ps.fontid, ps.fstep);
+ } /* else delete */
else {
printf("error: can't play this image type\n");
exit(0);
@@ -1052,16 +1106,17 @@ void WM_main_playanim(int argc, const char **argv)
ps.next_frame = ps.direction;
- while ((hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0) || ps.wait2 != 0)) {
+ while ( (hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0)) || ps.wait2 != 0) {
if (hasevent) {
GHOST_DispatchEvents(g_WS.ghost_system);
}
+ /* Note, this still draws for mousemoves on pause */
if (ps.wait2) {
if (hasevent) {
if (ibuf) {
while (pupdate_time()) PIL_sleep_ms(1);
ptottime -= swaptime;
- playanim_toscreen(ps.picture, ibuf, ps.fontid, ps.fstep);
+ playanim_toscreen(&ps, ps.picture, ibuf, ps.fontid, ps.fstep);
}
}
}
@@ -1134,12 +1189,20 @@ void WM_main_playanim(int argc, const char **argv)
#else
/* we still miss freeing a lot!,
* but many areas could skip initialization too for anim play */
- IMB_exit();
- BKE_images_exit();
+
BLF_exit();
#endif
GHOST_DisposeWindow(g_WS.ghost_system, g_WS.ghost_window);
+ /* early exit, IMB and BKE should be exited only in end */
+ if (ps.dropped_file) {
+ BLI_strncpy(filepath, ps.dropped_file, sizeof(filepath));
+ return filepath;
+ }
+
+ IMB_exit();
+ BKE_images_exit();
+
totblock = MEM_get_memory_blocks_in_use();
if (totblock != 0) {
/* prints many bAKey, bArgument's which are tricky to fix */
@@ -1148,4 +1211,25 @@ void WM_main_playanim(int argc, const char **argv)
MEM_printmemlist();
#endif
}
+
+ return NULL;
+}
+
+
+void WM_main_playanim(int argc, const char **argv)
+{
+ bool looping = true;
+
+ while (looping) {
+ char *filepath = wm_main_playanim_intern(argc, argv);
+
+ if (filepath) { /* use simple args */
+ argv[1] = "-a";
+ argv[2] = filepath;
+ argc = 3;
+ }
+ else {
+ looping = false;
+ }
+ }
}
diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c
index 9b46dced6bc..01bebe8a1b8 100644
--- a/source/blender/windowmanager/intern/wm_subwindow.c
+++ b/source/blender/windowmanager/intern/wm_subwindow.c
@@ -217,10 +217,10 @@ void wm_subwindow_position(wmWindow *win, int swinid, rcti *winrct)
* fixed it). - zr (2001!)
*/
- if (swin->winrct.xmax > win->sizex)
- swin->winrct.xmax = win->sizex;
- if (swin->winrct.ymax > win->sizey)
- swin->winrct.ymax = win->sizey;
+ if (swin->winrct.xmax > WM_window_pixels_x(win))
+ swin->winrct.xmax = WM_window_pixels_x(win);
+ if (swin->winrct.ymax > WM_window_pixels_y(win))
+ swin->winrct.ymax = WM_window_pixels_y(win);
/* extra service */
wmSubWindowSet(win, swinid);
@@ -255,22 +255,21 @@ void wmSubWindowScissorSet(wmWindow *win, int swinid, rcti *srct)
width = BLI_rcti_size_x(&_curswin->winrct) + 1;
height = BLI_rcti_size_y(&_curswin->winrct) + 1;
glViewport(_curswin->winrct.xmin, _curswin->winrct.ymin, width, height);
-
+
if (srct) {
- width = BLI_rcti_size_x(srct) + 1;
- height = BLI_rcti_size_y(srct) + 1;
- glScissor(srct->xmin, srct->ymin, width, height);
+ int scissor_width = BLI_rcti_size_x(srct) + 1; /* only here */
+ int scissor_height = BLI_rcti_size_y(srct) + 1;
+ glScissor(srct->xmin, srct->ymin, scissor_width, scissor_height);
}
else
glScissor(_curswin->winrct.xmin, _curswin->winrct.ymin, width, height);
wmOrtho2(-GLA_PIXEL_OFS, (float)width - GLA_PIXEL_OFS, -GLA_PIXEL_OFS, (float)height - GLA_PIXEL_OFS);
glLoadIdentity();
-
+
glFlush();
}
-
/* enable the WM versions of opengl calls */
void wmSubWindowSet(wmWindow *win, int swinid)
{
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 09f7e1692d9..53698ca7e9e 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -28,7 +28,6 @@
* \ingroup wm
*/
-
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
@@ -37,12 +36,12 @@
#include "DNA_listBase.h"
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h"
-#include "RNA_access.h"
#include "MEM_guardedalloc.h"
#include "GHOST_C-api.h"
+#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -54,9 +53,10 @@
#include "BKE_global.h"
#include "BKE_main.h"
-
#include "BIF_gl.h"
+#include "RNA_access.h"
+
#include "WM_api.h"
#include "WM_types.h"
#include "wm.h"
@@ -75,6 +75,11 @@
#include "UI_interface.h"
+/* for assert */
+#ifndef NDEBUG
+# include "BLI_threads.h"
+#endif
+
/* the global to talk to ghost */
static GHOST_SystemHandle g_system = NULL;
@@ -91,7 +96,9 @@ static struct WMInitStruct {
int windowstate;
WinOverrideFlag override_flag;
-} wm_init_state = {0, 0, 0, 0, GHOST_kWindowStateNormal, 0};
+
+ int native_pixels;
+} wm_init_state = {0, 0, 0, 0, GHOST_kWindowStateNormal, 0, 1};
/* ******** win open & close ************ */
@@ -107,6 +114,17 @@ void wm_get_screensize(int *width_r, int *height_r)
*height_r = uiheight;
}
+/* size of all screens, useful since the mouse is bound by this */
+void wm_get_screensize_all(int *width_r, int *height_r)
+{
+ unsigned int uiwidth;
+ unsigned int uiheight;
+
+ GHOST_GetAllDisplayDimensions(g_system, &uiwidth, &uiheight);
+ *width_r = uiwidth;
+ *height_r = uiheight;
+}
+
/* keeps offset and size within monitor bounds */
/* XXX solve dual screen... */
static void wm_window_check_position(rcti *rect)
@@ -241,7 +259,7 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *winorig)
win->screen->do_refresh = TRUE;
win->screen->do_draw = TRUE;
- win->drawmethod = -1;
+ win->drawmethod = U.wmdrawmethod;
win->drawdata = NULL;
return win;
@@ -251,51 +269,50 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *winorig)
void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
{
wmWindow *tmpwin;
- bScreen *screen = win->screen;
+ int do_exit = 0;
+
+ /* first check if we have to quit (there are non-temp remaining windows) */
+ for (tmpwin = wm->windows.first; tmpwin; tmpwin = tmpwin->next) {
+ if (tmpwin == win)
+ continue;
+ if (tmpwin->screen->temp == 0)
+ break;
+ }
+
+ if (tmpwin == NULL)
+ do_exit = 1;
- /* first check if we have any non-temp remaining windows */
if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved) {
- if (wm->windows.first) {
- for (tmpwin = wm->windows.first; tmpwin; tmpwin = tmpwin->next) {
- if (tmpwin == win)
- continue;
- if (tmpwin->screen->temp == 0)
- break;
- }
- if (tmpwin == NULL) {
- if (!GHOST_confirmQuit(win->ghostwin))
- return;
- }
+ if (do_exit) {
+ if (!GHOST_confirmQuit(win->ghostwin))
+ return;
}
}
- BLI_remlink(&wm->windows, win);
-
- wm_draw_window_clear(win);
- CTX_wm_window_set(C, win); /* needed by handlers */
- WM_event_remove_handlers(C, &win->handlers);
- WM_event_remove_handlers(C, &win->modalhandlers);
- ED_screen_exit(C, win, win->screen);
-
- wm_window_free(C, wm, win);
-
- /* if temp screen, delete it after window free (it stops jobs that can access it) */
- if (screen->temp) {
- Main *bmain = CTX_data_main(C);
- BKE_libblock_free(&bmain->screen, screen);
+ /* let WM_exit do all freeing, for correct quit.blend save */
+ if (do_exit) {
+ WM_exit(C);
}
+ else {
+ bScreen *screen = win->screen;
+
+ BLI_remlink(&wm->windows, win);
+
+ wm_draw_window_clear(win);
+
+ CTX_wm_window_set(C, win); /* needed by handlers */
+ WM_event_remove_handlers(C, &win->handlers);
+ WM_event_remove_handlers(C, &win->modalhandlers);
+ ED_screen_exit(C, win, win->screen);
+
+ wm_window_free(C, wm, win);
- /* check remaining windows */
- if (wm->windows.first) {
- for (win = wm->windows.first; win; win = win->next)
- if (win->screen->temp == 0)
- break;
- /* in this case we close all */
- if (win == NULL)
- WM_exit(C);
- }
- else
- WM_exit(C);
+ /* if temp screen, delete it after window free (it stops jobs that can access it) */
+ if (screen->temp) {
+ Main *bmain = CTX_data_main(C);
+ BKE_libblock_free(&bmain->screen, screen);
+ }
+ }
}
void wm_window_title(wmWindowManager *wm, wmWindow *win)
@@ -308,8 +325,9 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win)
/* 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) + 12];
- BLI_snprintf(str, sizeof(str), "Blender%s [%s]", wm->file_saved ? "" : "*", G.main->name);
+ char str[sizeof(G.main->name) + 24];
+ BLI_snprintf(str, sizeof(str), "Blender%s [%s%s]", wm->file_saved ? "" : "*", G.main->name,
+ G.main->recovered ? " (Recovered)" : "");
GHOST_SetTitle(win->ghostwin, str);
}
else
@@ -344,8 +362,6 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win)
wm_get_screensize(&scr_w, &scr_h);
posy = (scr_h - win->posy - win->sizey);
- /* Disable AA for now, as GL_SELECT (used for border, lasso, ... select)
- * doesn't work well when AA is initialized, even if not used. */
ghostwin = GHOST_CreateWindow(g_system, title,
win->posx, posy, win->sizex, win->sizey,
(GHOST_TWindowState)win->windowstate,
@@ -354,6 +370,8 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win)
multisamples /* AA */);
if (ghostwin) {
+ GHOST_RectangleHandle bounds;
+
/* needed so we can detect the graphics card below */
GPU_extensions_init();
@@ -372,7 +390,19 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win)
if (!GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE)) {
glClear(GL_COLOR_BUFFER_BIT);
}
+
+ /* 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);
+ BKE_userdef_state();
+
+ /* store actual window size in blender window */
+ bounds = GHOST_GetClientBounds(win->ghostwin);
+ win->sizex = GHOST_GetWidthRectangle(bounds);
+ win->sizey = GHOST_GetHeightRectangle(bounds);
+ GHOST_DisposeRectangle(bounds);
+
wm_window_swap_buffers(win);
//GHOST_SetWindowState(ghostwin, GHOST_kWindowStateModified);
@@ -406,9 +436,22 @@ void wm_window_add_ghostwindows(wmWindowManager *wm)
wm_set_apple_prefsize(wm_init_state.size_x, wm_init_state.size_y);
}
#else
+ /* 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;
-
+#endif
+
+#if !defined(__APPLE__) && !defined(WIN32) /* 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);
+ /* pad */
+ wm_init_state.start_x = WM_WIN_INIT_PAD;
+ wm_init_state.start_y = WM_WIN_INIT_PAD;
+ wm_init_state.size_x -= WM_WIN_INIT_PAD * 2;
+ wm_init_state.size_y -= WM_WIN_INIT_PAD * 2;
#endif
}
@@ -420,9 +463,7 @@ void wm_window_add_ghostwindows(wmWindowManager *wm)
win->sizex = wm_init_state.size_x;
win->sizey = wm_init_state.size_y;
- /* we can't properly resize a maximized window */
win->windowstate = GHOST_kWindowStateNormal;
-
wm_init_state.override_flag &= ~WIN_OVERRIDE_GEOM;
}
@@ -468,7 +509,7 @@ wmWindow *WM_window_open(bContext *C, rcti *rect)
win->sizex = BLI_rcti_size_x(rect);
win->sizey = BLI_rcti_size_y(rect);
- win->drawmethod = -1;
+ win->drawmethod = U.wmdrawmethod;
win->drawdata = NULL;
WM_check(C);
@@ -530,6 +571,7 @@ void WM_window_open_temp(bContext *C, rcti *position, int type)
}
ED_screen_set(C, win->screen);
+ ED_screen_refresh(CTX_wm_manager(C), win); /* test scale */
if (sa->spacetype == SPACE_IMAGE)
GHOST_SetTitle(win->ghostwin, IFACE_("Blender Render"));
@@ -578,6 +620,24 @@ int wm_window_fullscreen_toggle_exec(bContext *C, wmOperator *UNUSED(op))
/* ************ events *************** */
+static void wm_convert_cursor_position(wmWindow *win, int *x, int *y)
+{
+ float fac = GHOST_GetNativePixelSize(win->ghostwin);
+
+ GHOST_ScreenToClient(win->ghostwin, *x, *y, x, y);
+ *x *= fac;
+
+ *y = (win->sizey - 1) - *y;
+ *y *= fac;
+}
+
+
+void wm_get_cursor_position(wmWindow *win, int *x, int *y)
+{
+ GHOST_GetCursorPosition(g_system, x, y);
+ wm_convert_cursor_position(win, x, y);
+}
+
typedef enum {
SHIFT = 's',
CONTROL = 'c',
@@ -629,10 +689,15 @@ void wm_window_make_drawable(bContext *C, wmWindow *win)
printf("%s: set drawable %d\n", __func__, win->winid);
}
GHOST_ActivateWindowDrawingContext(win->ghostwin);
+
+ /* this can change per window */
+ U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin);
+ BKE_userdef_state();
}
}
/* called by ghost, here we handle events for windows themselves or send to event system */
+/* mouse coordinate converversion happens here */
static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr)
{
bContext *C = C_void_ptr;
@@ -668,12 +733,20 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
case GHOST_kEventWindowDeactivate:
wm_event_add_ghostevent(wm, win, type, time, data);
win->active = 0; /* XXX */
+
+ /* clear modifiers for inactive windows */
+ win->eventstate->alt = 0;
+ win->eventstate->ctrl = 0;
+ win->eventstate->shift = 0;
+ win->eventstate->oskey = 0;
+ win->eventstate->keymodifier = 0;
+
break;
case GHOST_kEventWindowActivate:
{
GHOST_TEventKeyData kdata;
wmEvent event;
- int cx, cy, wx, wy;
+ int wx, wy;
wm->winactive = win; /* no context change! c->wm->windrawable is drawable, or for area queues */
@@ -681,6 +754,9 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
// window_handle(win, INPUTCHANGE, win->active);
/* bad ghost support for modifier keys... so on activate we set the modifiers again */
+
+ /* TODO: This is not correct since a modifier may be held when a window is activated...
+ * better solve this at ghost level. attempted fix r54450 but it caused bug [#34255] */
kdata.ascii = '\0';
kdata.utf8_buf[0] = '\0';
if (win->eventstate->shift && !query_qual(SHIFT)) {
@@ -703,11 +779,10 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
win->eventstate->keymodifier = 0;
/* entering window, update mouse pos. but no event */
- GHOST_GetCursorPosition(g_system, &wx, &wy);
-
- GHOST_ScreenToClient(win->ghostwin, wx, wy, &cx, &cy);
- win->eventstate->x = cx;
- win->eventstate->y = (win->sizey - 1) - cy;
+ wm_get_cursor_position(win, &wx, &wy);
+
+ win->eventstate->x = wx;
+ win->eventstate->y = wy;
win->addmousemove = 1; /* enables highlighted buttons */
@@ -770,7 +845,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
GHOST_DisposeRectangle(client_rect);
- wm_get_screensize(&scr_w, &scr_h);
+ wm_get_screensize_all(&scr_w, &scr_h);
sizex = r - l;
sizey = b - t;
posx = l;
@@ -857,14 +932,12 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
{
wmEvent event;
GHOST_TEventDragnDropData *ddd = GHOST_GetEventData(evt);
- int cx, cy, wx, wy;
+ int wx, wy;
/* entering window, update mouse pos */
- GHOST_GetCursorPosition(g_system, &wx, &wy);
-
- GHOST_ScreenToClient(win->ghostwin, wx, wy, &cx, &cy);
- win->eventstate->x = cx;
- win->eventstate->y = (win->sizey - 1) - cy;
+ wm_get_cursor_position(win, &wx, &wy);
+ win->eventstate->x = wx;
+ win->eventstate->y = wy;
event = *(win->eventstate); /* copy last state, like mouse coords */
@@ -907,11 +980,33 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
}
}
+ break;
+ }
+ case GHOST_kEventNativeResolutionChange:
+ // printf("change, pixel size %f\n", GHOST_GetNativePixelSize(win->ghostwin));
+
+ U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin);
+ BKE_userdef_state();
+ WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
+ WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL);
+
+ break;
+ case GHOST_kEventTrackpad:
+ {
+ GHOST_TEventTrackpadData *pd = data;
+ wm_convert_cursor_position(win, &pd->x, &pd->y);
+ wm_event_add_ghostevent(wm, win, type, time, data);
+ break;
+ }
+ case GHOST_kEventCursorMove:
+ {
+ GHOST_TEventCursorData *cd = data;
+ wm_convert_cursor_position(win, &cd->x, &cd->y);
+ wm_event_add_ghostevent(wm, win, type, time, data);
break;
}
-
default:
wm_event_add_ghostevent(wm, win, type, time, data);
break;
@@ -971,8 +1066,12 @@ static int wm_window_timer(const bContext *C)
void wm_window_process_events(const bContext *C)
{
- int hasevent = GHOST_ProcessEvents(g_system, 0); /* 0 is no wait */
-
+ int hasevent;
+
+ BLI_assert(BLI_thread_is_main());
+
+ hasevent = GHOST_ProcessEvents(g_system, 0); /* 0 is no wait */
+
if (hasevent)
GHOST_DispatchEvents(g_system);
@@ -994,7 +1093,9 @@ void wm_window_testbreak(void)
{
static double ltime = 0;
double curtime = PIL_check_seconds_timer();
-
+
+ BLI_assert(BLI_thread_is_main());
+
/* only check for breaks every 50 milliseconds
* if we get called more often.
*/
@@ -1017,6 +1118,10 @@ void wm_ghost_init(bContext *C)
g_system = GHOST_CreateSystem();
GHOST_AddEventConsumer(g_system, consumer);
+
+ if (wm_init_state.native_pixels) {
+ GHOST_UseNativePixels();
+ }
}
}
@@ -1068,6 +1173,8 @@ void WM_event_remove_timer(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *
if (wt == timer)
break;
if (wt) {
+ wmWindow *win;
+
if (wm->reports.reporttimer == wt)
wm->reports.reporttimer = NULL;
@@ -1075,6 +1182,17 @@ void WM_event_remove_timer(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *
if (wt->customdata)
MEM_freeN(wt->customdata);
MEM_freeN(wt);
+
+ /* there might be events in queue with this timer as customdata */
+ for (win = wm->windows.first; win; win = win->next) {
+ wmEvent *event;
+ for (event = win->queue.first; event; event = event->next) {
+ if (event->customdata == wt) {
+ event->customdata = NULL;
+ event->type = EVENT_NONE; /* timer users customdata, dont want NULL == NULL */
+ }
+ }
+ }
}
}
@@ -1126,7 +1244,9 @@ void WM_clipboard_text_set(char *buf, int selection)
if (*p == '\n') {
*(p2++) = '\r'; *p2 = '\n';
}
- else *p2 = *p;
+ else {
+ *p2 = *p;
+ }
}
*p2 = '\0';
@@ -1158,23 +1278,6 @@ void wm_window_get_position(wmWindow *win, int *posx_r, int *posy_r)
*posy_r = win->posy;
}
-void wm_window_get_size(wmWindow *win, int *width_r, int *height_r)
-{
- *width_r = win->sizex;
- *height_r = win->sizey;
-}
-
-/* exceptional case: - splash is called before events are processed
- * this means we don't actually know the window size so get this from GHOST */
-void wm_window_get_size_ghost(wmWindow *win, int *width_r, int *height_r)
-{
- GHOST_RectangleHandle bounds = GHOST_GetClientBounds(win->ghostwin);
- *width_r = GHOST_GetWidthRectangle(bounds);
- *height_r = GHOST_GetHeightRectangle(bounds);
-
- GHOST_DisposeRectangle(bounds);
-}
-
void wm_window_set_size(wmWindow *win, int width, int height)
{
GHOST_SetClientSize(win->ghostwin, width, height);
@@ -1202,12 +1305,6 @@ void wm_window_swap_buffers(wmWindow *win)
#endif
}
-void wm_get_cursor_position(wmWindow *win, int *x, int *y)
-{
- GHOST_GetCursorPosition(g_system, x, y);
- GHOST_ScreenToClient(win->ghostwin, *x, *y, x, y);
- *y = (win->sizey - 1) - *y;
-}
/* ******************* exported api ***************** */
@@ -1217,8 +1314,8 @@ void WM_init_state_size_set(int stax, int stay, int sizx, int sizy)
{
wm_init_state.start_x = stax; /* left hand pos */
wm_init_state.start_y = stay; /* bottom pos */
- wm_init_state.size_x = sizx;
- wm_init_state.size_y = sizy;
+ wm_init_state.size_x = sizx < 640 ? 640 : sizx;
+ wm_init_state.size_y = sizy < 480 ? 480 : sizy;
wm_init_state.override_flag |= WIN_OVERRIDE_GEOM;
}
@@ -1235,12 +1332,20 @@ void WM_init_state_normal_set(void)
wm_init_state.override_flag |= WIN_OVERRIDE_WINSTATE;
}
+void WM_init_native_pixels(int do_it)
+{
+ wm_init_state.native_pixels = do_it;
+}
+
/* This function requires access to the GHOST_SystemHandle (g_system) */
void WM_cursor_warp(wmWindow *win, int x, int y)
{
if (win && win->ghostwin) {
+ float f = GHOST_GetNativePixelSize(win->ghostwin);
int oldx = x, oldy = y;
+ x = x / f;
+ y = y / f;
y = win->sizey - y - 1;
GHOST_ClientToScreen(win->ghostwin, x, y, &x, &y);
@@ -1251,3 +1356,34 @@ void WM_cursor_warp(wmWindow *win, int x, int y)
}
}
+/**
+ * Get the cursor pressure, in most cases you'll want to use wmTabletData from the event
+ */
+float WM_cursor_pressure(const struct wmWindow *win)
+{
+ const GHOST_TabletData *td = GHOST_GetTabletData(win->ghostwin);
+ /* if there's tablet data from an active tablet device then add it */
+ if ((td != NULL) && td->Active != GHOST_kTabletModeNone) {
+ return td->Pressure;
+ }
+ else {
+ return -1.0f;
+ }
+}
+
+/* support for native pixel size */
+/* mac retina opens window in size X, but it has up to 2 x more pixels */
+int WM_window_pixels_x(wmWindow *win)
+{
+ float f = GHOST_GetNativePixelSize(win->ghostwin);
+
+ return (int)(f * (float)win->sizex);
+}
+
+int WM_window_pixels_y(wmWindow *win)
+{
+ float f = GHOST_GetNativePixelSize(win->ghostwin);
+
+ return (int)(f * (float)win->sizey);
+
+}
diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h
index 2d0dd2ef911..d12e1d47fa0 100644
--- a/source/blender/windowmanager/wm_event_system.h
+++ b/source/blender/windowmanager/wm_event_system.h
@@ -45,7 +45,8 @@ struct ARegion;
typedef struct wmEventHandler {
struct wmEventHandler *next, *prev;
- int type, flag; /* type default=0, rest is custom */
+ int type; /* WM_HANDLER_DEFAULT, ... */
+ int flag; /* WM_HANDLER_BLOCKING, ... */
/* keymap handler */
wmKeyMap *keymap; /* pointer to builtin/custom keymaps */
@@ -72,21 +73,17 @@ typedef struct wmEventHandler {
} wmEventHandler;
-
-/* handler flag */
- /* after this handler all others are ignored */
-#define WM_HANDLER_BLOCKING 1
- /* handler tagged to be freed in wm_handlers_do() */
-#define WM_HANDLER_DO_FREE 2
-
-
-
/* custom types for handlers, for signalling, freeing */
enum {
WM_HANDLER_DEFAULT,
WM_HANDLER_FILESELECT
};
+/* handler flag */
+enum {
+ WM_HANDLER_BLOCKING = 1, /* after this handler all others are ignored */
+ WM_HANDLER_DO_FREE = 2 /* handler tagged to be freed in wm_handlers_do() */
+};
/* wm_event_system.c */
void wm_event_free_all (wmWindow *win);
@@ -107,5 +104,8 @@ void wm_dropbox_free(void);
void wm_drags_check_ops(bContext *C, wmEvent *event);
void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect);
+/* wm_operators.c */
+void wm_recover_last_session(bContext *C, ReportList *reports);
+
#endif /* __WM_EVENT_SYSTEM_H__ */
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index 4d3d6ef89d9..338ef8bc65b 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -39,11 +39,10 @@
#define __WM_EVENT_TYPES_H__
/* customdata type */
-#define EVT_DATA_TABLET 1
-#define EVT_DATA_GESTURE 2
-#define EVT_DATA_TIMER 3
-#define EVT_DATA_LISTBASE 4
-#define EVT_DATA_NDOF_MOTION 5
+#define EVT_DATA_GESTURE 1
+#define EVT_DATA_TIMER 2
+#define EVT_DATA_LISTBASE 3
+#define EVT_DATA_NDOF_MOTION 4
/* tablet active, matches GHOST_TTabletMode */
#define EVT_TABLET_NONE 0
@@ -53,6 +52,11 @@
#define MOUSEX 4
#define MOUSEY 5
+
+/* *** wmEvent.type *** */
+
+/* non-event, for example disabled timer */
+#define EVENT_NONE 0
/* MOUSE : 0x00x */
#define LEFTMOUSE 1
#define MIDDLEMOUSE 2
@@ -148,11 +152,11 @@ enum {
#define TIMERJOBS 0x0114 /* timer event, jobs system */
#define TIMERAUTOSAVE 0x0115 /* timer event, autosave */
#define TIMERREPORT 0x0116 /* timer event, reports */
+#define TIMERREGION 0x0117 /* timer event, region slide in/out */
#define TIMERF 0x011F /* last timer */
/* test whether the event is timer event */
-#define ISTIMER(event) (event >= TIMER && event <= TIMERF)
-
+#define ISTIMER(event_type) (event_type >= TIMER && event_type <= TIMERF)
/* standard keyboard */
#define AKEY 'a'
@@ -286,29 +290,30 @@ enum {
/* for event checks */
/* only used for KM_TEXTINPUT, so assume that we want all user-inputtable ascii codes included */
/* UNUSED - see wm_eventmatch - BUG [#30479] */
-// #define ISTEXTINPUT(event) (event >= ' ' && event <= 255)
+// #define ISTEXTINPUT(event_type) (event_type >= ' ' && event_type <= 255)
+/* note, an alternative could be to check 'event->utf8_buf' */
/* test whether the event is a key on the keyboard */
-#define ISKEYBOARD(event) (event >= ' ' && event <= 320)
+#define ISKEYBOARD(event_type) (event_type >= ' ' && event_type <= 320)
/* test whether the event is a modifier key */
-#define ISKEYMODIFIER(event) ((event >= LEFTCTRLKEY && event <= LEFTSHIFTKEY) || event == OSKEY)
+#define ISKEYMODIFIER(event_type) ((event_type >= LEFTCTRLKEY && event_type <= LEFTSHIFTKEY) || event_type == OSKEY)
/* test whether the event is a mouse button */
-#define ISMOUSE(event) (event >= LEFTMOUSE && event <= MOUSEROTATE)
+#define ISMOUSE(event_type) (event_type >= LEFTMOUSE && event_type <= MOUSEROTATE)
/* test whether the event is tweak event */
-#define ISTWEAK(event) (event >= EVT_TWEAK_L && event <= EVT_GESTURE)
+#define ISTWEAK(event_type) (event_type >= EVT_TWEAK_L && event_type <= EVT_GESTURE)
/* test whether the event is a NDOF event */
-#define ISNDOF(event) (event >= NDOF_MOTION && event < NDOF_LAST)
+#define ISNDOF(event_type) (event_type >= NDOF_MOTION && event_type < NDOF_LAST)
/* test whether event type is acceptable as hotkey, excluding modifiers */
-#define ISHOTKEY(event) \
- ((ISKEYBOARD(event) || ISMOUSE(event) || ISNDOF(event)) && \
- (event != ESCKEY) && \
- (event >= LEFTCTRLKEY && event <= LEFTSHIFTKEY) == FALSE && \
- (event >= UNKNOWNKEY && event <= GRLESSKEY) == FALSE)
+#define ISHOTKEY(event_type) \
+ ((ISKEYBOARD(event_type) || ISMOUSE(event_type) || ISNDOF(event_type)) && \
+ (event_type != ESCKEY) && \
+ (event_type >= LEFTCTRLKEY && event_type <= LEFTSHIFTKEY) == FALSE && \
+ (event_type >= UNKNOWNKEY && event_type <= GRLESSKEY) == FALSE)
/* **************** BLENDER GESTURE EVENTS (0x5000) **************** */
@@ -379,6 +384,8 @@ enum {
#define GESTURE_MODAL_IN 9
#define GESTURE_MODAL_OUT 10
+#define GESTURE_MODAL_CIRCLE_SIZE 11 /* circle sel: size brush (for trackpad event) */
+
#endif /* __WM_EVENT_TYPES_H__ */
diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h
index f373530b5e6..fe007e7f52f 100644
--- a/source/blender/windowmanager/wm_files.h
+++ b/source/blender/windowmanager/wm_files.h
@@ -31,7 +31,13 @@
#ifndef __WM_FILES_H__
#define __WM_FILES_H__
-void WM_read_history(void);
+void wm_read_history(void);
+int wm_file_write(struct bContext *C, const char *target, int fileflags, struct ReportList *reports);
+int wm_homefile_read_exec(struct bContext *C, struct wmOperator *op);
+int wm_homefile_read(struct bContext *C, struct ReportList *reports, short from_memory);
+int wm_homefile_write_exec(struct bContext *C, struct wmOperator *op);
+int wm_userpref_write_exec(struct bContext *C, struct wmOperator *op);
+
#endif /* __WM_FILES_H__ */
diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h
index 6360cfd4802..a0546c88b78 100644
--- a/source/blender/windowmanager/wm_window.h
+++ b/source/blender/windowmanager/wm_window.h
@@ -40,6 +40,7 @@ void wm_ghost_init (bContext *C);
void wm_ghost_exit(void);
void wm_get_screensize(int *width_r, int *height_r);
+void wm_get_screensize_all(int *width_r, int *height_r);
wmWindow *wm_window_new (bContext *C);
void wm_window_free (bContext *C, wmWindowManager *wm, wmWindow *win);
@@ -55,8 +56,6 @@ void wm_window_make_drawable(bContext *C, 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_size (wmWindow *win, int *width_r, int *height_r);
-void wm_window_get_size_ghost(wmWindow *win, int *width_r, int *height_r);
void wm_window_get_position (wmWindow *win, int *posx_r, int *posy_r);
void wm_window_swap_buffers (wmWindow *win);
@@ -70,5 +69,12 @@ void wm_window_testbreak (void);
int wm_window_duplicate_exec(bContext *C, struct wmOperator *op);
int wm_window_fullscreen_toggle_exec(bContext *C, struct wmOperator *op);
+/* Initial (unmaximized) size to start with for
+ * systems that can't find it for themselves (X11).
+ * Clamped by real desktop limits */
+#define WM_WIN_INIT_SIZE_X 1800
+#define WM_WIN_INIT_SIZE_Y 1000
+#define WM_WIN_INIT_PAD 40
+
#endif /* __WM_WINDOW_H__ */
diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt
index 85bb07d6e83..c775f7d3279 100644
--- a/source/blenderplayer/CMakeLists.txt
+++ b/source/blenderplayer/CMakeLists.txt
@@ -95,6 +95,7 @@ endif()
bf_rna
bf_bmesh
bf_blenkernel
+ bf_intern_rigidbody
bf_blenloader
ge_blen_routines
bf_editor_datafiles
@@ -102,7 +103,6 @@ endif()
ge_logic_ketsji
ge_phys_bullet
ge_phys_dummy
- ge_phys_common
ge_logic
ge_rasterizer
ge_oglrasterizer
@@ -149,6 +149,8 @@ endif()
bf_intern_raskter
bf_intern_opencolorio
bf_intern_opennl
+ extern_rangetree
+ extern_wcwidth
)
if(WITH_MOD_CLOTH_ELTOPO)
diff --git a/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt b/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt
index afd5f5b0177..e8e7ee6ea0a 100644
--- a/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt
+++ b/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt
@@ -29,6 +29,7 @@ remove_strict_flags()
set(INC
.
..
+ ../../blender/blenlib
../../blender/blenkernel
../../blender/blenloader
../../blender/makesdna
@@ -60,4 +61,8 @@ if(WITH_GAMEENGINE)
add_definitions(-DWITH_GAMEENGINE)
endif()
+if(WITH_FREESTYLE)
+ add_definitions(-DWITH_FREESTYLE)
+endif()
+
blender_add_lib_nolist(blenkernel_blc "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blenderplayer/bad_level_call_stubs/SConscript b/source/blenderplayer/bad_level_call_stubs/SConscript
index 5efe9aa5761..2dbb0e00eb0 100644
--- a/source/blenderplayer/bad_level_call_stubs/SConscript
+++ b/source/blenderplayer/bad_level_call_stubs/SConscript
@@ -1,18 +1,48 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
-sources = 'stubs.c'
+sources = ['stubs.c']
-incs = '#/intern/guardedalloc'
-incs += ' #/source/blender/makesdna'
-incs += ' #/source/blender/makesrna'
-incs += ' #/source/blender/blenloader'
+incs = [
+ '#/intern/guardedalloc',
+ '#/source/blender/makesdna',
+ '#/source/blender/makesrna',
+ '#/source/blender/blenloader',
+ '#/source/blender/blenlib',
+ ]
-defs = ''
-if env['WITH_BF_INTERNATIONAL']:
- defs += 'WITH_FREETYPE2'
+defs = []
if env['WITH_BF_GAMEENGINE']:
- defs += ' WITH_GAMEENGINE'
+ defs.append('WITH_GAMEENGINE')
+
+if env['WITH_BF_FREESTYLE']:
+ defs.append(' WITH_FREESTYLE')
-env.BlenderLib ('blenkernel_blc', sources = Split(sources), includes=Split(incs), defines=Split(defs), libtype=['player'],priority=[220] )
+env.BlenderLib('blenkernel_blc', sources=sources, includes=incs, defines=defs, libtype=['player'], priority=[220])
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 2b29129c0f7..6004eb57000 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -34,6 +34,7 @@
#ifdef WITH_GAMEENGINE
#include <stdlib.h>
#include "DNA_listBase.h"
+#include "BLI_utildefines.h"
#include "RNA_types.h"
struct ARegion;
@@ -55,6 +56,10 @@ struct FCurve;
struct Heap;
struct HeapNode;
struct ID;
+#ifdef WITH_FREESTYLE
+struct FreestyleConfig;
+struct FreestyleLineSet;
+#endif
struct ImBuf;
struct Image;
struct ImageUser;
@@ -67,6 +72,7 @@ struct Mask;
struct Material;
struct MenuType;
struct Mesh;
+struct MetaBall;
struct ModifierData;
struct MovieClip;
struct MultiresModifierData;
@@ -83,6 +89,9 @@ struct RenderLayer;
struct RenderResult;
struct Scene;
struct Scene;
+#ifdef WITH_FREESTYLE
+struct SceneRenderLayer;
+#endif
struct ScrArea;
struct SculptSession;
struct ShadeInput;
@@ -105,15 +114,20 @@ struct bConstraintOb;
struct bConstraintTarget;
struct bContextDataResult;
struct bNode;
+struct bNodeType;
struct bNodeSocket;
+struct bNodeSocketType;
struct bNodeTree;
+struct bNodeTreeType;
struct bPoseChannel;
struct bPythonConstraint;
+struct bTheme;
struct uiLayout;
struct wmEvent;
struct wmKeyConfig;
struct wmKeyMap;
struct wmOperator;
+struct wmOperatorType;
struct wmWindow;
struct wmWindowManager;
@@ -193,16 +207,23 @@ void WM_menutype_free(void) {}
void WM_menutype_freelink(struct MenuType *mt) {}
int WM_menutype_add(struct MenuType *mt) {return 0;}
int WM_operator_props_dialog_popup(struct bContext *C, struct wmOperator *op, int width, int height) {return 0;}
-int WM_operator_confirm(struct bContext *C, struct wmOperator *op, struct wmEvent *event) {return 0;}
+int WM_operator_confirm(struct bContext *C, struct wmOperator *op, const struct wmEvent *event) {return 0;}
struct MenuType *WM_menutype_find(const char *idname, int quiet) {return (struct MenuType *) NULL;}
void WM_operator_stack_clear(struct bContext *C) {}
+void WM_operator_handlers_clear(struct bContext *C, struct wmOperatorType *ot) {}
void WM_autosave_init(struct bContext *C) {}
void WM_jobs_kill_all_except(struct wmWindowManager *wm) {}
-char *WM_clipboard_text_get(int selection) {return (char*)0;}
+char *WM_clipboard_text_get(int selection) {return (char *)0;}
void WM_clipboard_text_set(char *buf, int selection) {}
+void WM_uilisttype_init(void) {}
+struct uiListType *WM_uilisttype_find(const char *idname, int quiet) {return (struct uiListType *)NULL;}
+int WM_uilisttype_add(struct uiListType *ult) {return 0;}
+void WM_uilisttype_freelink(struct uiListType *ult) {}
+void WM_uilisttype_free(void) {}
+
struct wmKeyMapItem *WM_keymap_item_find_id(struct wmKeyMap *keymap, int id) {return (struct wmKeyMapItem *) NULL;}
int WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event) {return 0;}
void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference) {}
@@ -215,7 +236,7 @@ void ED_armature_edit_bone_remove(struct bArmature *arm, struct EditBone *exBone
void object_test_constraints(struct Object *owner) {}
void ED_object_parent(struct Object *ob, struct Object *par, int type, const char *substr) {}
void ED_object_constraint_set_active(struct Object *ob, struct bConstraint *con) {}
-void ED_node_composit_default(struct Scene *sce) {}
+void ED_node_composit_default(struct bContext *C, struct Scene *scene) {}
void *ED_region_draw_cb_activate(struct ARegionType *art, void(*draw)(const struct bContext *, struct ARegion *, void *), void *custumdata, int type) {return 0;} /* XXX this one looks weird */
void *ED_region_draw_cb_customdata(void *handle) {return 0;} /* XXX This one looks wrong also */
void ED_region_draw_cb_exit(struct ARegionType *art, void *handle) {}
@@ -292,10 +313,21 @@ void ED_area_newspace(struct bContext *C, struct ScrArea *sa, int type) {}
void ED_region_tag_redraw(struct ARegion *ar) {}
void WM_event_add_fileselect(struct bContext *C, struct wmOperator *op) {}
void WM_cursor_wait(int val) {}
-void ED_node_texture_default(struct Tex *tx) {}
-void ED_node_changed_update(struct bContext *C, struct bNode *node) {}
-void ED_node_generic_update(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node) {}
-void ED_node_tree_update(struct SpaceNode *snode, struct Scene *scene) {}
+void ED_node_texture_default(struct bContext *C, struct Tex *tx) {}
+void ED_node_tag_update_id(struct ID *id) {}
+void ED_node_tag_update_nodetree(struct Main *bmain, struct bNodeTree *ntree) {}
+void ED_node_tree_update(const struct bContext *C) {}
+void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo){}
+void ED_init_custom_node_type(struct bNodeType *ntype){}
+void ED_init_custom_node_socket_type(struct bNodeSocketType *stype){}
+void ED_init_standard_node_socket_type(struct bNodeSocketType *stype) {}
+void ED_init_node_socket_type_virtual(struct bNodeSocketType *stype) {}
+int ED_node_tree_path_length(struct SpaceNode *snode){return 0;}
+void ED_node_tree_path_get(struct SpaceNode *snode, char *value){}
+void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length){}
+void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, struct ID *id, struct ID *from){}
+void ED_node_tree_push(struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *gnode){}
+void ED_node_tree_pop(struct SpaceNode *snode){}
void ED_view3d_scene_layers_update(struct Main *bmain, struct Scene *scene) {}
int ED_view3d_scene_layer_set(int lay, const int *values) {return 0;}
void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar) {}
@@ -307,15 +339,16 @@ void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct AR
float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit) {return 0.0f;}
void view3d_apply_mat4(float mat[4][4], float *ofs, float *quat, float *dist) {}
int text_file_modified(struct Text *text) {return 0;}
-void ED_node_shader_default(struct Material *ma) {}
+void ED_node_shader_default(struct bContext *C, struct ID *id) {}
void ED_screen_animation_timer_update(struct bContext *C, int redraws) {}
void ED_screen_animation_playing(struct wmWindowManager *wm) {}
void ED_base_object_select(struct Base *base, short mode) {}
int ED_object_modifier_remove(struct ReportList *reports, struct Scene *scene, struct Object *ob, struct ModifierData *md) {return 0;}
int ED_object_modifier_add(struct ReportList *reports, struct Scene *scene, struct Object *ob, char *name, int type) {return 0;}
-void ED_object_modifier_clear(struct Scene *scene, struct Object *ob) {}
-void ED_object_enter_editmode(struct bContext *C, int flag) {}
-void ED_object_exit_editmode(struct bContext *C, int flag) {}
+void ED_object_modifier_clear(struct Main *bmain, struct Object *ob) {}
+void ED_object_editmode_enter(struct bContext *C, int flag) {}
+void ED_object_editmode_exit(struct bContext *C, int flag) {}
+bool ED_object_editmode_load(struct Object *obedit) { return false; }
int uiLayoutGetActive(struct uiLayout *layout) {return 0;}
int uiLayoutGetOperatorContext(struct uiLayout *layout) {return 0;}
int uiLayoutGetAlignment(struct uiLayout *layout) {return 0;}
@@ -328,6 +361,7 @@ void uiLayoutSetEnabled(struct uiLayout *layout, int enabled) {}
void uiLayoutSetAlignment(struct uiLayout *layout, int alignment) {}
void uiLayoutSetScaleX(struct uiLayout *layout, float scale) {}
void uiLayoutSetScaleY(struct uiLayout *layout, float scale) {}
+void uiTemplateIconView(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname) {}
void ED_base_object_free_and_unlink(struct Scene *scene, struct Base *base) {}
void ED_mesh_calc_normals(struct Mesh *me) {}
void ED_mesh_geometry_add(struct Mesh *mesh, struct ReportList *reports, int verts, int edges, int faces) {}
@@ -343,8 +377,10 @@ void ED_mesh_vertices_remove(struct Mesh *mesh, struct ReportList *reports, int
void ED_mesh_edges_remove(struct Mesh *mesh, struct ReportList *reports, int count) {}
void ED_mesh_faces_remove(struct Mesh *mesh, struct ReportList *reports, int count) {}
void ED_mesh_material_link(struct Mesh *mesh, struct Material *ma) {}
-int ED_mesh_color_add(struct bContext *C, struct Scene *scene, struct Object *ob, struct Mesh *me) {return 0;}
-int ED_mesh_uv_texture_add(struct bContext *C, struct Mesh *me) {return 0;}
+int ED_mesh_color_add(struct Mesh *me, const char *name, const bool active_set) { return -1; }
+int ED_mesh_uv_texture_add(struct Mesh *me, const char *name, const bool active_set) { return -1; }
+bool ED_mesh_color_remove_named(struct Mesh *me, const char *name) { return false; }
+bool ED_mesh_uv_texture_remove_named(struct Mesh *me, const char *name) { return false; }
void ED_object_constraint_dependency_update(struct Scene *scene, struct Object *ob) {}
void ED_object_constraint_update(struct Object *ob) {}
struct bDeformGroup *ED_vgroup_add_name(struct Object *ob, char *name) {return (struct bDeformGroup *) NULL;}
@@ -364,6 +400,8 @@ int ED_space_image_check_show_maskedit(struct Scene *scene, struct SpaceImage *s
void ED_nurb_set_spline_type(struct Nurb *nu, int type) {}
+void ED_mball_transform(struct MetaBall *mb, float *mat) {}
+
void make_editLatt(struct Object *obedit) {}
void load_editLatt(struct Object *obedit) {}
@@ -374,6 +412,7 @@ void make_editNurb(struct Object *obedit) {}
void uiItemR(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int flag, char *name, int icon) {}
struct PointerRNA uiItemFullO(struct uiLayout *layout, char *idname, char *name, int icon, struct IDProperty *properties, int context, int flag) {struct PointerRNA a = {{0}}; return a;}
+PointerRNA uiItemFullO_ptr(struct uiLayout *layout, struct wmOperatorType *ot, const char *name, int icon, struct IDProperty *properties, int context, int flag) {struct PointerRNA a = {{0}}; return a;}
struct uiLayout *uiLayoutRow(struct uiLayout *layout, int align) {return (struct uiLayout *) NULL;}
struct uiLayout *uiLayoutColumn(struct uiLayout *layout, int align) {return (struct uiLayout *) NULL;}
struct uiLayout *uiLayoutColumnFlow(struct uiLayout *layout, int number, int align) {return (struct uiLayout *) NULL;}
@@ -400,6 +439,8 @@ void uiItemFullR(struct uiLayout *layout, struct PointerRNA *ptr, struct Propert
void uiLayoutSetContextPointer(struct uiLayout *layout, char *name, struct PointerRNA *ptr) {}
char *uiLayoutIntrospect(struct uiLayout *layout) {return (char *)NULL;}
void UI_reinit_font(void) {}
+int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, int big) {return 0;}
+struct bTheme *UI_GetTheme(void) {return (struct bTheme *) NULL;};
/* rna template */
void uiTemplateAnyID(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, char *text) {}
@@ -414,7 +455,9 @@ void uiTemplateCurveMapping(struct uiLayout *layout, struct CurveMapping *cumap,
void uiTemplateColorRamp(struct uiLayout *layout, struct ColorBand *coba, int expand) {}
void uiTemplateLayers(struct uiLayout *layout, struct PointerRNA *ptr, char *propname) {}
void uiTemplateImageLayers(struct uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser) {}
-ListBase uiTemplateList(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, struct PointerRNA *activeptr, char *activepropname, int rows, int listtype) {struct ListBase b = {0,0}; return b;}
+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) {}
void uiTemplateRunningJobs(struct uiLayout *layout, struct bContext *C) {}
void uiTemplateOperatorSearch(struct uiLayout *layout) {}
void uiTemplateHeader3D(struct uiLayout *layout, struct bContext *C) {}
@@ -438,12 +481,15 @@ void uiTemplateMarker(struct uiLayout *layout, struct PointerRNA *ptr, const cha
void uiTemplateImageSettings(struct uiLayout *layout, struct PointerRNA *imfptr) {}
void uiTemplateColorspaceSettings(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname) {}
void uiTemplateColormanagedViewSettings(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, int show_global_settings) {}
+void uiTemplateComponentMenu(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name){}
+void uiTemplateNodeSocket(struct uiLayout *layout, struct bContext *C, float *color) {}
/* rna render */
struct RenderResult *RE_engine_begin_result(struct RenderEngine *engine, int x, int y, int w, int h) {return (struct RenderResult *) NULL;}
struct RenderResult *RE_AcquireResultRead(struct Render *re) {return (struct RenderResult *) NULL;}
struct RenderResult *RE_AcquireResultWrite(struct Render *re) {return (struct RenderResult *) NULL;}
struct RenderStats *RE_GetStats(struct Render *re) {return (struct RenderStats *) NULL;}
+struct RenderData *RE_engine_get_render_data(struct Render *re) {return (struct RenderData *) NULL;}
void RE_engine_update_result(struct RenderEngine *engine, struct RenderResult *result) {}
void RE_engine_update_progress(struct RenderEngine *engine, float progress) {}
void RE_engine_end_result(struct RenderEngine *engine, struct RenderResult *result) {}
@@ -478,8 +524,8 @@ void WM_operator_properties_free(struct PointerRNA *ptr) {}
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_sanitize(struct PointerRNA *ptr, const short no_context) {};
-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_append_ptr(void (*opfunc)(struct wmOperatorType*, void *), void *userdata) {}
+void WM_operatortype_append_macro_ptr(void (*opfunc)(struct wmOperatorType*, void *), void *userdata) {}
void WM_operator_bl_idname(char *to, const char *from) {}
void WM_operator_py_idname(char *to, const char *from) {}
void WM_operator_ui_popup(struct bContext *C, struct wmOperator *op, int width, int height) {}
@@ -516,7 +562,18 @@ void macro_wrapper(struct wmOperatorType *ot, void *userdata) {}
int pyrna_id_FromPyObject(struct PyObject *obj, struct ID **id) { return 0; }
struct PyObject *pyrna_id_CreatePyObject(struct ID *id) {return NULL; }
void BPY_context_update(struct bContext *C) {};
-
+const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid) { return msgid; }
+
+#ifdef WITH_FREESTYLE
+/* Freestyle */
+void FRS_init_freestyle_config(struct FreestyleConfig *config) {}
+void FRS_free_freestyle_config(struct FreestyleConfig *config) {}
+void FRS_copy_freestyle_config(struct FreestyleConfig *new_config, struct FreestyleConfig *config) {}
+struct FreestyleLineSet *FRS_get_active_lineset(struct FreestyleConfig *config) { return NULL; }
+short FRS_get_active_lineset_index(struct FreestyleConfig *config) { return 0; }
+void FRS_set_active_lineset_index(struct FreestyleConfig *config, short index) {}
+void FRS_unlink_target_object(struct FreestyleConfig *config, struct Object *ob) {}
+#endif
/* intern/dualcon */
struct DualConMesh;
struct DualConMesh *dualcon(const struct DualConMesh *input_mesh,
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index b66c000ac89..141eb04727a 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -80,6 +80,11 @@ if(WITH_BINRELOC)
blender_include_dirs(${BINRELOC_INCLUDE_DIRS})
endif()
+if(WITH_FREESTYLE)
+ add_definitions(-DWITH_FREESTYLE)
+ blender_include_dirs(../blender/freestyle)
+endif()
+
# Setup the exe sources and buildinfo
set(SRC
creator.c
@@ -279,15 +284,24 @@ if(WITH_PYTHON)
set(ADDON_EXCLUDE_CONDITIONAL "_addons_contrib/*") # dummy, wont do anything
endif()
+ # do not install freestyle dir if disabled
+ if(NOT WITH_FREESTYLE)
+ set(FREESTYLE_EXCLUDE_CONDITIONAL "freestyle/*")
+ else()
+ set(FREESTYLE_EXCLUDE_CONDITIONAL "_freestyle/*") # dummy, wont do anything
+ endif()
+
install(
DIRECTORY ${CMAKE_SOURCE_DIR}/release/scripts
DESTINATION ${TARGETDIR_VER}
PATTERN ".svn" EXCLUDE
PATTERN "__pycache__" EXCLUDE
PATTERN "${ADDON_EXCLUDE_CONDITIONAL}" EXCLUDE
+ PATTERN "${FREESTYLE_EXCLUDE_CONDITIONAL}" EXCLUDE
)
unset(ADDON_EXCLUDE_CONDITIONAL)
+ unset(FREESTYLE_EXCLUDE_CONDITIONAL)
endif()
# localization
@@ -472,7 +486,7 @@ elseif(WIN32)
if(WITH_PYTHON)
set_lib_path(PYLIB "python")
- STRING(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
+ string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
install(
FILES ${PYLIB}/lib/python${_PYTHON_VERSION_NO_DOTS}.dll
@@ -689,7 +703,7 @@ elseif(APPLE)
)
# python
- if(WITH_PYTHON AND NOT WITH_PYTHON_MODULE)
+ if(WITH_PYTHON AND NOT WITH_PYTHON_MODULE AND NOT WITH_PYTHON_FRAMEWORK)
# the python zip is first extract as part of the build process,
# and then later installed as part of make install. this is much
# quicker, and means we can easily exclude files on copy
@@ -742,7 +756,7 @@ elseif(APPLE)
)
# python
- if(WITH_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/
@@ -779,8 +793,7 @@ add_dependencies(blender makesdna)
get_property(BLENDER_LINK_LIBS GLOBAL PROPERTY BLENDER_LINK_LIBS)
-set(BLENDER_LINK_LIBS
- ${BLENDER_LINK_LIBS}
+list(APPEND BLENDER_LINK_LIBS
bf_windowmanager
bf_render
)
@@ -831,12 +844,12 @@ endif()
bf_editor_util
bf_editor_uvedit
bf_editor_curve
- bf_editor_armature
bf_editor_gpencil
bf_editor_interface
bf_editor_mesh
bf_editor_metaball
bf_editor_object
+ bf_editor_armature
bf_editor_physics
bf_editor_render
bf_editor_screen
@@ -853,6 +866,7 @@ endif()
bf_python_ext
bf_python_mathutils
bf_python_bmesh
+ bf_freestyle
bf_ikplugin
bf_modifiers
bf_bmesh
@@ -885,7 +899,6 @@ endif()
extern_colamd
ge_logic_ketsji
extern_recastnavigation
- ge_phys_common
ge_logic
ge_rasterizer
ge_oglrasterizer
@@ -893,7 +906,6 @@ endif()
ge_scenegraph
ge_logic_network
ge_logic_ngnetwork
- extern_bullet
ge_logic_loopbacknetwork
bf_intern_moto
extern_openjpeg
@@ -914,12 +926,14 @@ endif()
cycles_subd
bf_intern_raskter
bf_intern_opencolorio
+ extern_rangetree
+ extern_wcwidth
)
if(WITH_COMPOSITOR)
# added for opencl compositor
list_insert_before(BLENDER_SORTED_LIBS "bf_blenkernel" "bf_compositor")
- list_insert_after(BLENDER_SORTED_LIBS "bf_compositor" "bf_opencl")
+ list_insert_after(BLENDER_SORTED_LIBS "bf_compositor" "bf_intern_opencl")
endif()
if(WITH_LIBMV)
@@ -971,6 +985,14 @@ endif()
list(APPEND BLENDER_SORTED_LIBS bf_intern_locale)
endif()
+ if(WITH_BULLET)
+ list_insert_after(BLENDER_SORTED_LIBS "bf_blenkernel" "bf_intern_rigidbody")
+ endif()
+
+ if(WITH_BULLET AND NOT WITH_BULLET_SYSTEM)
+ list_insert_after(BLENDER_SORTED_LIBS "ge_logic_ngnetwork" "extern_bullet")
+ endif()
+
foreach(SORTLIB ${BLENDER_SORTED_LIBS})
set(REMLIB ${SORTLIB})
foreach(SEARCHLIB ${BLENDER_LINK_LIBS})
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 0f1207a9a88..7abb653e9b8 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -40,14 +40,29 @@
# include <xmmintrin.h>
#endif
+/* crash handler */
#ifdef WIN32
-# include <Windows.h>
+# include <process.h> /* getpid */
+#else
+# include <unistd.h> /* getpid */
+#endif
+
+#ifdef WIN32
+# 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>
+#include <errno.h>
/* This little block needed for linking to Blender... */
@@ -69,10 +84,12 @@
#include "BLI_blenlib.h"
#include "BKE_blender.h"
+#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h" /* for DAG_on_visible_update */
#include "BKE_font.h"
#include "BKE_global.h"
+#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_packedFile.h"
@@ -102,6 +119,10 @@
#include "BLI_scanfill.h" /* for BLI_setErrorCallBack, TODO, move elsewhere */
+#ifdef WITH_FREESTYLE
+# include "FRS_freestyle.h"
+#endif
+
#ifdef WITH_BUILDINFO_HEADER
# define BUILD_DATE
#endif
@@ -143,22 +164,28 @@ extern char build_system[];
#endif
/* Local Function prototypes */
-#ifndef WITH_PYTHON_MODULE
+#ifdef WITH_PYTHON_MODULE
+int main_python_enter(int argc, const char **argv);
+void main_python_exit(void);
+#else
static int print_help(int argc, const char **argv, void *data);
static int print_version(int argc, const char **argv, void *data);
#endif
/* for the callbacks: */
-#define BLEND_VERSION_STRING_FMT \
- "Blender %d.%02d (sub %d)\n", \
- BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION \
+#define BLEND_VERSION_FMT "Blender %d.%02d (sub %d)"
+#define BLEND_VERSION_ARG BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION
+/* pass directly to printf */
+#define BLEND_VERSION_STRING_FMT BLEND_VERSION_FMT "\n", BLEND_VERSION_ARG
/* Initialize callbacks for the modules that need them */
static void setCallbacks(void);
#ifndef WITH_PYTHON_MODULE
+static bool use_crash_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))
@@ -246,6 +273,7 @@ static int print_help(int UNUSED(argc), const char **UNUSED(argv), void *data)
printf("Misc Options:\n");
BLI_argsPrintArgDoc(ba, "--debug");
BLI_argsPrintArgDoc(ba, "--debug-fpe");
+ BLI_argsPrintArgDoc(ba, "--disable-crash-handler");
#ifdef WITH_FFMPEG
BLI_argsPrintArgDoc(ba, "--debug-ffmpeg");
@@ -280,6 +308,7 @@ static int print_help(int UNUSED(argc), const char **UNUSED(argv), void *data)
printf("\n");
BLI_argsPrintArgDoc(ba, "--python");
+ BLI_argsPrintArgDoc(ba, "--python-text");
BLI_argsPrintArgDoc(ba, "--python-console");
BLI_argsPrintArgDoc(ba, "--addons");
@@ -350,6 +379,12 @@ static int disable_python(int UNUSED(argc), const char **UNUSED(argv), void *UNU
return 0;
}
+static int disable_crash_handler(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
+{
+ use_crash_handler = false;
+ return 0;
+}
+
static int background_mode(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
{
G.background = 1;
@@ -423,6 +458,148 @@ 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(_MSV_VER)
+
+static void blender_crash_handler_backtrace(FILE *fp)
+{
+ (void)fp;
+
+#if 0
+#define MAXSYMBOL 256
+ unsigned short i;
+ void *stack[SIZE];
+ unsigned short nframes;
+ SYMBOL_INFO *symbolinfo;
+ HANDLE process;
+
+ process = GetCurrentProcess();
+
+ SymInitialize(process, NULL, TRUE);
+
+ nframes = CaptureStackBackTrace(0, SIZE, stack, NULL);
+ symbolinfo = MEM_callocN(sizeof(SYMBOL_INFO) + MAXSYMBOL * sizeof( char ), "crash Symbol table");
+ symbolinfo->MaxNameLen = MAXSYMBOL - 1;
+ symbolinfo->SizeOfStruct = sizeof(SYMBOL_INFO);
+
+ for (i = 0; i < nframes; i++) {
+ SymFromAddr(process, ( DWORD64 )( stack[ i ] ), 0, symbolinfo);
+
+ fprintf(fp, "%u: %s - 0x%0X\n", nframes - i - 1, symbolinfo->Name, symbolinfo->Address);
+ }
+
+ MEM_freeN(symbolinfo);
+#endif
+}
+
+#else /* non msvc/osx/linux */
+
+static void blender_crash_handler_backtrace(FILE *fp)
+{
+ (void)fp;
+}
+
+#endif
+
+static void blender_crash_handler(int signum)
+{
+
+#if 0
+ {
+ char fname[FILE_MAX];
+
+ if (!G.main->name[0]) {
+ BLI_make_file_string("/", fname, BLI_temporary_dir(), "crash.blend");
+ }
+ else {
+ BLI_strncpy(fname, G.main->name, sizeof(fname));
+ BLI_replace_extension(fname, sizeof(fname), ".crash.blend");
+ }
+
+ printf("Writing: %s\n", fname);
+ fflush(stdout);
+
+ BKE_undo_save_file(fname);
+ }
+#endif
+
+ FILE *fp;
+ char header[512];
+ wmWindowManager *wm = G.main->wm.first;
+
+ char fname[FILE_MAX];
+
+ if (!G.main->name[0]) {
+ BLI_join_dirfile(fname, sizeof(fname), BLI_temporary_dir(), "blender.crash.txt");
+ }
+ else {
+ BLI_join_dirfile(fname, sizeof(fname), BLI_temporary_dir(), BLI_path_basename(G.main->name));
+ BLI_replace_extension(fname, sizeof(fname), ".crash.txt");
+ }
+
+ printf("Writing: %s\n", fname);
+ fflush(stdout);
+
+ BLI_snprintf(header, sizeof(header), "# " BLEND_VERSION_FMT ", Revision: %s\n", BLEND_VERSION_ARG,
+#ifdef BUILD_DATE
+ build_rev
+#else
+ "Unknown"
+#endif
+ );
+
+ /* open the crash log */
+ errno = 0;
+ fp = BLI_fopen(fname, "wb");
+ if (fp == NULL) {
+ fprintf(stderr, "Unable to save '%s': %s\n",
+ fname, errno ? strerror(errno) : "Unknown error opening file");
+ }
+ else {
+ if (wm) {
+ BKE_report_write_file_fp(fp, &wm->reports, header);
+ }
+
+ blender_crash_handler_backtrace(fp);
+
+ fclose(fp);
+ }
+
+
+ /* really crash */
+ signal(signum, SIG_DFL);
+#ifndef WIN32
+ kill(getpid(), signum);
+#else
+ TerminateProcess(GetCurrentProcess(), signum);
+#endif
+}
+
+
static int set_factory_startup(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
{
G.factory_startup = 1;
@@ -481,6 +658,12 @@ static int prefsize(int argc, const char **argv, void *UNUSED(data))
return 4;
}
+static int native_pixels(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
+{
+ WM_init_native_pixels(0);
+ return 0;
+}
+
static int with_borders(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
{
WM_init_state_normal_set();
@@ -493,10 +676,10 @@ static int without_borders(int UNUSED(argc), const char **UNUSED(argv), void *UN
return 0;
}
-extern int wm_start_with_console; /* wm_init_exit.c */
+extern bool wm_start_with_console; /* wm_init_exit.c */
static int start_with_console(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
{
- wm_start_with_console = 1;
+ wm_start_with_console = true;
return 0;
}
@@ -747,7 +930,7 @@ static int set_ge_parameters(int argc, const char **argv, void *data)
}
- } /* if (*(argv[a+1]) == '=') */
+ } /* if (*(argv[a + 1]) == '=') */
}
return a;
@@ -913,11 +1096,11 @@ static int set_skip_frame(int argc, const char **argv, void *data)
_cmd; \
} \
CTX_data_scene_set(C, prevscene); \
- } \
+ } (void)0 \
#endif /* WITH_PYTHON */
-static int run_python(int argc, const char **argv, void *data)
+static int run_python_file(int argc, const char **argv, void *data)
{
#ifdef WITH_PYTHON
bContext *C = data;
@@ -929,12 +1112,42 @@ static int run_python(int argc, const char **argv, void *data)
BLI_strncpy(filename, argv[1], sizeof(filename));
BLI_path_cwd(filename);
- BPY_CTX_SETUP(BPY_filepath_exec(C, filename, NULL))
+ BPY_CTX_SETUP(BPY_filepath_exec(C, filename, NULL));
return 1;
}
else {
- printf("\nError: you must specify a Python script after '-P / --python'.\n");
+ printf("\nError: you must specify a filepath after '%s'.\n", argv[0]);
+ return 0;
+ }
+#else
+ (void)argc; (void)argv; (void)data; /* unused */
+ printf("This blender was built without python support\n");
+ return 0;
+#endif /* WITH_PYTHON */
+}
+
+static int run_python_text(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) {
+ /* Make the path absolute because its needed for relative linked blends to be found */
+ struct Text *text = (struct Text *)BKE_libblock_find_name(ID_TXT, argv[1]);
+
+ if (text) {
+ BPY_CTX_SETUP(BPY_text_exec(C, text, NULL, false));
+ return 1;
+ }
+ else {
+ printf("\nError: text block not found %s.\n", argv[1]);
+ return 1;
+ }
+ }
+ else {
+ printf("\nError: you must specify a text block after '%s'.\n", argv[0]);
return 0;
}
#else
@@ -949,7 +1162,7 @@ static int run_python_console(int UNUSED(argc), const char **argv, void *data)
#ifdef WITH_PYTHON
bContext *C = data;
- BPY_CTX_SETUP(BPY_string_exec(C, "__import__('code').interact()"))
+ BPY_CTX_SETUP(BPY_string_exec(C, "__import__('code').interact()"));
return 0;
#else
@@ -1116,6 +1329,8 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
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);
+
#undef PY_ENABLE_AUTO
#undef PY_DISABLE_AUTO
@@ -1128,6 +1343,11 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
#ifdef WITH_FFMPEG
BLI_argsAdd(ba, 1, NULL, "--debug-ffmpeg", "\n\tEnable debug messages from FFmpeg library", debug_mode_generic, (void *)G_DEBUG_FFMPEG);
#endif
+
+#ifdef WITH_FREESTYLE
+ 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-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);
@@ -1156,9 +1376,10 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
BLI_argsAdd(ba, 2, "-p", "--window-geometry", "<sx> <sy> <w> <h>\n\tOpen with lower left corner at <sx>, <sy> and width and height as <w>, <h>", prefsize, NULL);
BLI_argsAdd(ba, 2, "-w", "--window-border", "\n\tForce opening with borders (default)", with_borders, NULL);
BLI_argsAdd(ba, 2, "-W", "--window-borderless", "\n\tForce opening without borders", without_borders, NULL);
- BLI_argsAdd(ba, 2, "-con", "--start-console", "\n\tStart with the console window open (ignored if -b is set)", start_with_console, NULL);
+ BLI_argsAdd(ba, 2, "-con", "--start-console", "\n\tStart with the console window open (ignored if -b is set), (Windows only)", start_with_console, NULL);
BLI_argsAdd(ba, 2, "-R", NULL, "\n\tRegister .blend extension, then exit (Windows only)", register_extension, NULL);
BLI_argsAdd(ba, 2, "-r", NULL, "\n\tSilently register .blend extension, then exit (Windows only)", register_extension, ba);
+ BLI_argsAdd(ba, 2, NULL, "--no-native-pixels", "\n\tDo not use native pixel size, for high resolution displays (MacBook 'Retina')", native_pixels, ba);
/* third pass: disabling things and forcing settings */
BLI_argsAddCase(ba, 3, "-nojoystick", 1, NULL, 0, "\n\tDisable joystick support", no_joystick, syshandle);
@@ -1174,7 +1395,8 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
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, "-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 (filename or Blender Text)", run_python, 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-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);
@@ -1274,6 +1496,8 @@ int main(int argc, const char **argv)
IMB_init();
BKE_images_init();
+ BKE_brush_system_init();
+
#ifdef WITH_FFMPEG
IMB_ffmpeg_init();
#endif
@@ -1292,8 +1516,15 @@ int main(int argc, const char **argv)
setupArguments(C, ba, &syshandle);
BLI_argsParse(ba, 1, NULL, NULL);
-#endif
+ if (use_crash_handler) {
+ /* after parsing args */
+ signal(SIGSEGV, blender_crash_handler);
+ }
+#else
+ G.factory_startup = true; /* using preferences or user startup makes no sense for py-as-module */
+ (void)syshandle;
+#endif
/* after level 1 args, this is so playanim skips RNA init */
RNA_init();
@@ -1304,10 +1535,12 @@ int main(int argc, const char **argv)
#if defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS)
- G.background = 1; /* python module mode ALWAYS runs in background mode (for now) */
+ G.background = true; /* python module mode ALWAYS runs in background mode (for now) */
#else
/* for all platforms, even windos has it! */
- if (G.background) signal(SIGINT, blender_esc); /* ctrl c out bg render */
+ if (G.background) {
+ signal(SIGINT, blender_esc); /* ctrl c out bg render */
+ }
#endif
/* background render uses this font too */
@@ -1360,6 +1593,12 @@ int main(int argc, const char **argv)
CTX_py_init_set(C, 1);
WM_keymap_init(C);
+#ifdef WITH_FREESTYLE
+ /* initialize Freestyle */
+ FRS_initialize();
+ FRS_set_context(C);
+#endif
+
/* OK we are ready for it */
#ifndef WITH_PYTHON_MODULE
BLI_argsParse(ba, 4, load_file, C);
@@ -1398,7 +1637,7 @@ int main(int argc, const char **argv)
WM_main(C);
return 0;
-} /* end of int main(argc,argv) */
+} /* end of int main(argc, argv) */
#ifdef WITH_PYTHON_MODULE
void main_python_exit(void)
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
index 6807f531f0a..450ae1a16b5 100644
--- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -58,7 +58,6 @@
#include "RAS_GLExtensionManager.h"
#include "RAS_OpenGLRasterizer.h"
-#include "RAS_VAOpenGLRasterizer.h"
#include "RAS_ListRasterizer.h"
#include "NG_LoopBackNetworkDeviceInterface.h"
@@ -184,7 +183,7 @@ static int BL_KetsjiNextFrame(KX_KetsjiEngine *ketsjiengine, bContext *C, wmWind
}
struct BL_KetsjiNextFrameState {
- struct KX_KetsjiEngine* ketsjiengine;
+ class KX_KetsjiEngine* ketsjiengine;
struct bContext *C;
struct wmWindow* win;
struct Scene* scene;
@@ -270,7 +269,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
#ifdef WITH_PYTHON
bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 0) != 0);
#endif
- bool novertexarrays = (SYS_GetCommandLineInt(syshandle, "novertexarrays", 0) != 0);
+ // 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;
@@ -287,16 +286,12 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
RAS_IRenderTools* rendertools = new KX_BlenderRenderTools();
RAS_IRasterizer* rasterizer = NULL;
- if (displaylists) {
- if (GLEW_VERSION_1_1 && !novertexarrays)
- rasterizer = new RAS_ListRasterizer(canvas, true, true);
- else
- rasterizer = new RAS_ListRasterizer(canvas);
- }
- else if (GLEW_VERSION_1_1 && !novertexarrays)
- rasterizer = new RAS_VAOpenGLRasterizer(canvas, false);
+ //Don't use displaylists with VBOs
+ //If auto starts using VBOs, make sure to check for that here
+ if (displaylists && startscene->gm.raster_storage != RAS_STORE_VBO)
+ rasterizer = new RAS_ListRasterizer(canvas, true, startscene->gm.raster_storage);
else
- rasterizer = new RAS_OpenGLRasterizer(canvas);
+ rasterizer = new RAS_OpenGLRasterizer(canvas, startscene->gm.raster_storage);
// create the inputdevices
KX_BlenderKeyboardDevice* keyboarddevice = new KX_BlenderKeyboardDevice();
@@ -443,7 +438,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
ketsjiengine->SetCameraOverrideViewMatrix(MT_CmMatrix4x4(rv3d->viewmat));
if (rv3d->persp == RV3D_ORTHO)
{
- ketsjiengine->SetCameraOverrideClipping(-v3d->far, v3d->far);
+ ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far);
}
else
{
@@ -473,6 +468,8 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
sceneconverter->SetMaterials(true);
if (useglslmat && (gs.matmode == GAME_MAT_GLSL))
sceneconverter->SetGLSLMaterials(true);
+ if (scene->gm.flag & GAME_NO_MATERIAL_CACHING)
+ sceneconverter->SetCacheMaterials(false);
KX_Scene* startscene = new KX_Scene(keyboarddevice,
mousedevice,
diff --git a/source/gameengine/BlenderRoutines/CMakeLists.txt b/source/gameengine/BlenderRoutines/CMakeLists.txt
index 9a47d223f76..32efc5bde21 100644
--- a/source/gameengine/BlenderRoutines/CMakeLists.txt
+++ b/source/gameengine/BlenderRoutines/CMakeLists.txt
@@ -30,7 +30,6 @@ set(INC
)
set(INC_SYS
- ../../../extern/bullet2/src
${PTHREADS_INCLUDE_DIRS}
${GLEW_INCLUDE_PATH}
${BOOST_INCLUDE_DIR}
@@ -70,4 +69,12 @@ if(WITH_CODEC_FFMPEG)
add_definitions(-DWITH_FFMPEG)
endif()
+if(WITH_BULLET)
+ list(APPEND INC_SYS
+ ${BULLET_INCLUDE_DIRS}
+ )
+ add_definitions(-DWITH_BULLET)
+endif()
+
+
blender_add_lib(ge_blen_routines "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
index 346d2017ef0..6ab1d032bf2 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
@@ -154,11 +154,11 @@ SetViewPort(
int x1, int y1,
int x2, int y2
) {
- /* x1 and y1 are the min pixel coordinate (e.g. 0)
- x2 and y2 are the max pixel coordinate
- the width,height is calculated including both pixels
- therefore: max - min + 1
- */
+ /* x1 and y1 are the min pixel coordinate (e.g. 0)
+ * x2 and y2 are the max pixel coordinate
+ * the width,height is calculated including both pixels
+ * therefore: max - min + 1
+ */
int vp_width = (x2 - x1) + 1;
int vp_height = (y2 - y1) + 1;
int minx = m_frame_rect.GetLeft();
@@ -178,6 +178,18 @@ SetViewPort(
glScissor(minx + x1, miny + y1, vp_width, vp_height);
}
+ void
+KX_BlenderCanvas::
+UpdateViewPort(
+ int x1, int y1,
+ int x2, int y2
+) {
+ m_viewport[0] = x1;
+ m_viewport[1] = y1;
+ m_viewport[2] = x2;
+ m_viewport[3] = y2;
+}
+
const int*
KX_BlenderCanvas::
GetViewPort() {
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h
index 244394a115d..430f956bc7f 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h
+++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h
@@ -58,8 +58,9 @@ struct wmWindow;
class KX_BlenderCanvas : public RAS_ICanvas
{
private:
- /** Rect that defines the area used for rendering,
- relative to the context */
+ /**
+ * Rect that defines the area used for rendering,
+ * relative to the context */
RAS_Rect m_displayarea;
int m_viewport[4];
@@ -151,6 +152,13 @@ public:
int x1, int y1,
int x2, int y2
);
+
+ void
+ UpdateViewPort(
+ int x1, int y1,
+ int x2, int y2
+ );
+
const int*
GetViewPort();
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp
index 00836fa8ecb..f24392352b0 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp
@@ -121,8 +121,52 @@ static void DisableForText()
}
}
+void BL_draw_gamedebug_box(int xco, int yco, int width, int height, float percentage)
+{
+ /* This is a rather important line :( The gl-mode hasn't been left
+ * behind quite as neatly as we'd have wanted to. I don't know
+ * what cause it, though :/ .*/
+ glDisable(GL_DEPTH_TEST);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glOrtho(0, width, 0, height, -100, 100);
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ yco = height - yco;
+ int barsize = 50;
+
+ /* draw in black first*/
+ glColor3ub(0, 0, 0);
+ glBegin(GL_QUADS);
+ glVertex2f(xco + 1 + 1 + barsize * percentage, yco - 1 + 10);
+ glVertex2f(xco + 1, yco - 1 + 10);
+ glVertex2f(xco + 1, yco - 1);
+ glVertex2f(xco + 1 + 1 + barsize * percentage, yco - 1);
+ glEnd();
+
+ glColor3ub(255, 255, 255);
+ glBegin(GL_QUADS);
+ glVertex2f(xco + 1 + barsize * percentage, yco + 10);
+ glVertex2f(xco, yco + 10);
+ glVertex2f(xco, yco);
+ glVertex2f(xco + 1 + barsize * percentage, yco);
+ glEnd();
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ glEnable(GL_DEPTH_TEST);
+}
+
/* Print 3D text */
-void BL_print_game_line(int fontid, const char* text, int size, int dpi, float* color, double* mat, float aspect)
+void BL_print_game_line(int fontid, const char *text, int size, int dpi, float *color, double *mat, float aspect)
{
/* gl prepping */
DisableForText();
@@ -164,7 +208,9 @@ void BL_print_gamedebug_line(const char* text, int xco, int yco, int width, int
/* the actual drawing */
glColor3ub(255, 255, 255);
- BLF_draw_default((float)xco, (float)(height-yco), 0.0f, (char *)text, 65535); /* XXX, use real len */
+ BLF_size(blf_mono_font, 11, 72);
+ BLF_position(blf_mono_font, (float)xco, (float)(height-yco), 0.0f);
+ BLF_draw(blf_mono_font, (char *)text, 65535); /* XXX, use real len */
glMatrixMode(GL_PROJECTION);
glPopMatrix();
@@ -193,9 +239,13 @@ void BL_print_gamedebug_line_padded(const char* text, int xco, int yco, int widt
/* draw in black first*/
glColor3ub(0, 0, 0);
- BLF_draw_default((float)(xco+2), (float)(height-yco-2), 0.0f, text, 65535); /* XXX, use real len */
+ BLF_size(blf_mono_font, 11, 72);
+ BLF_position(blf_mono_font, (float)xco+1, (float)(height-yco-1), 0.0f);
+ BLF_draw(blf_mono_font, (char *)text, 65535);/* XXX, use real len */
+
glColor3ub(255, 255, 255);
- BLF_draw_default((float)xco, (float)(height-yco), 0.0f, text, 65535); /* XXX, use real len */
+ BLF_position(blf_mono_font, (float)xco, (float)(height-yco), 0.0f);
+ BLF_draw(blf_mono_font, (char *)text, 65535);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
@@ -259,7 +309,7 @@ void BL_MakeScreenShot(ScrArea *curarea, const char* filename)
ImBuf *ibuf;
BLI_path_abs(path, G.main->name);
/* BKE_add_image_extension() checks for if extension was already set */
- BKE_add_image_extension(path, R_IMF_IMTYPE_PNG); /* scene->r.im_format.imtype */
+ BKE_add_image_extension_from_type(path, R_IMF_IMTYPE_PNG); /* scene->r.im_format.imtype */
ibuf= IMB_allocImBuf(dumpsx, dumpsy, 24, 0);
ibuf->rect= dumprect;
ibuf->ftype= PNG;
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.h b/source/gameengine/BlenderRoutines/KX_BlenderGL.h
index 7ba612b19cf..5c3f0684764 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderGL.h
+++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.h
@@ -50,6 +50,7 @@ void BL_HideMouse(struct wmWindow *win);
void BL_NormalMouse(struct wmWindow *win);
void BL_WaitMouse(struct wmWindow *win);
+void BL_draw_gamedebug_box(int xco, int yco, int width, int height, float percentage);
void BL_print_game_line(int fontid, const char* text, int size, int dpi, float* color, double* mat, float aspect);
void BL_print_gamedebug_line(const char* text, int xco, int yco, int width, int height);
void BL_print_gamedebug_line_padded(const char* text, int xco, int yco, int width, int height);
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h b/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h
index 2a96d4c5216..0ce479cad6f 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h
+++ b/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h
@@ -64,7 +64,7 @@ public:
}
KX_EnumInputs ToNative(unsigned short incode) {
- return ConvertKeyCode(incode);
+ return ConvertKeyCode(incode);
}
virtual bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode)=0;
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp b/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp
index 19ba46ed6d7..5917ce40440 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp
@@ -49,8 +49,8 @@ KX_BlenderKeyboardDevice::~KX_BlenderKeyboardDevice()
}
/**
- IsPressed gives boolean information about keyboard status, true if pressed, false if not
-*/
+ * IsPressed gives boolean information about keyboard status, true if pressed, false if not
+ */
bool KX_BlenderKeyboardDevice::IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode)
{
@@ -64,11 +64,11 @@ bool KX_BlenderKeyboardDevice::IsPressed(SCA_IInputDevice::KX_EnumInputs inputco
return m_eventStatusTables[m_currentTable][inputcode];
}
*/
-/**
- NextFrame toggles currentTable with previousTable,
- and copy relevant event information from previous to current
- (pressed keys need to be remembered)
-*/
+/**
+ * NextFrame toggles currentTable with previousTable,
+ * and copy relevant event information from previous to current
+ * (pressed keys need to be remembered)
+ */
void KX_BlenderKeyboardDevice::NextFrame()
{
SCA_IInputDevice::NextFrame();
@@ -87,13 +87,11 @@ void KX_BlenderKeyboardDevice::NextFrame()
}
}
-/**
- ConvertBlenderEvent translates blender keyboard events into ketsji kbd events
- extra event information is stored, like ramp-mode (just released/pressed)
+/**
+ * ConvertBlenderEvent translates blender keyboard events into ketsji kbd events
+ * extra event information is stored, like ramp-mode (just released/pressed)
*/
-
-
-bool KX_BlenderKeyboardDevice::ConvertBlenderEvent(unsigned short incode,short val)
+bool KX_BlenderKeyboardDevice::ConvertBlenderEvent(unsigned short incode, short val)
{
bool result = false;
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.cpp b/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.cpp
index 8d90eacd27f..0cdc10264a5 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.cpp
@@ -46,8 +46,8 @@ KX_BlenderMouseDevice::~KX_BlenderMouseDevice()
}
/**
- IsPressed gives boolean information about mouse status, true if pressed, false if not
-*/
+ * IsPressed gives boolean information about mouse status, true if pressed, false if not
+ */
bool KX_BlenderMouseDevice::IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode)
{
@@ -62,11 +62,11 @@ bool KX_BlenderMouseDevice::IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode)
}
*/
-/**
- NextFrame toggles currentTable with previousTable,
- and copy relevant event information from previous to current
- (pressed keys need to be remembered)
-*/
+/**
+ * NextFrame toggles currentTable with previousTable,
+ * and copy relevant event information from previous to current
+ * (pressed keys need to be remembered)
+ */
void KX_BlenderMouseDevice::NextFrame()
{
SCA_IInputDevice::NextFrame();
@@ -104,13 +104,11 @@ void KX_BlenderMouseDevice::NextFrame()
}
-/**
- ConvertBlenderEvent translates blender mouse events into ketsji kbd events
- extra event information is stored, like ramp-mode (just released/pressed)
-*/
-
-
-bool KX_BlenderMouseDevice::ConvertBlenderEvent(unsigned short incode,short val)
+/**
+ * ConvertBlenderEvent translates blender mouse events into ketsji kbd events
+ * extra event information is stored, like ramp-mode (just released/pressed)
+ */
+bool KX_BlenderMouseDevice::ConvertBlenderEvent(unsigned short incode, short val)
{
bool result = false;
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
index e32239b148d..64ed384e961 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
@@ -280,6 +280,16 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat
}
}
}
+
+void KX_BlenderRenderTools::RenderBox2D(int xco,
+ int yco,
+ int width,
+ int height,
+ float percentage)
+{
+ BL_draw_gamedebug_box(xco, yco, width, height, percentage);
+}
+
void KX_BlenderRenderTools::RenderText3D(int fontid,
const char* text,
int size,
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h
index 7195524ceae..228763e7d2d 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h
+++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h
@@ -71,6 +71,13 @@ public:
void DisableOpenGLLights();
void ProcessLighting(RAS_IRasterizer *rasty, bool uselights, const MT_Transform& viewmat);
+ void RenderBox2D(int xco,
+ int yco,
+ int width,
+ int height,
+ float percentage);
+
+
void RenderText3D(int fontid,
const char* text,
int size,
diff --git a/source/gameengine/BlenderRoutines/SConscript b/source/gameengine/BlenderRoutines/SConscript
index 04dbe27337f..e2417d70b58 100644
--- a/source/gameengine/BlenderRoutines/SConscript
+++ b/source/gameengine/BlenderRoutines/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.cpp')
diff --git a/source/gameengine/CMakeLists.txt b/source/gameengine/CMakeLists.txt
index aae7e93cc91..cf7895e98ea 100644
--- a/source/gameengine/CMakeLists.txt
+++ b/source/gameengine/CMakeLists.txt
@@ -37,7 +37,6 @@ add_subdirectory(Ketsji)
add_subdirectory(Ketsji/KXNetwork)
add_subdirectory(Network)
add_subdirectory(Network/LoopBackNetwork)
-add_subdirectory(Physics/common)
add_subdirectory(Physics/Dummy)
add_subdirectory(Rasterizer)
add_subdirectory(Rasterizer/RAS_OpenGLRasterizer)
diff --git a/source/gameengine/Converter/BL_ArmatureConstraint.cpp b/source/gameengine/Converter/BL_ArmatureConstraint.cpp
index 379be91b523..131fdaed3ec 100644
--- a/source/gameengine/Converter/BL_ArmatureConstraint.cpp
+++ b/source/gameengine/Converter/BL_ArmatureConstraint.cpp
@@ -130,10 +130,10 @@ void BL_ArmatureConstraint::ReParent(BL_ArmatureObject* armature)
m_constraint = NULL;
m_posechannel = NULL;
// and locate the constraint
- for (pchan = (bPoseChannel*)newpose->chanbase.first; pchan; pchan=(bPoseChannel*)pchan->next) {
+ for (pchan = (bPoseChannel*)newpose->chanbase.first; pchan; pchan = (bPoseChannel*)pchan->next) {
if (!strcmp(pchan->name, posechannel)) {
// now locate the constraint
- for (pcon = (bConstraint*)pchan->constraints.first; pcon; pcon=(bConstraint*)pcon->next) {
+ for (pcon = (bConstraint *)pchan->constraints.first; pcon; pcon = (bConstraint *)pcon->next) {
if (!strcmp(pcon->name, constraint)) {
m_constraint = pcon;
m_posechannel = pchan;
diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp
index 1f1c404efcb..55d9decb333 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.cpp
+++ b/source/gameengine/Converter/BL_ArmatureObject.cpp
@@ -100,19 +100,20 @@ void game_copy_pose(bPose **dst, bPose *src, int copy_constraint)
/* remap pointers */
ghash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "game_copy_pose gh");
- pchan= (bPoseChannel*)src->chanbase.first;
- outpchan= (bPoseChannel*)out->chanbase.first;
+ pchan= (bPoseChannel *)src->chanbase.first;
+ outpchan= (bPoseChannel *)out->chanbase.first;
for (; pchan; pchan=pchan->next, outpchan=outpchan->next)
BLI_ghash_insert(ghash, pchan, outpchan);
- for (pchan = (bPoseChannel*)out->chanbase.first; pchan; pchan = pchan->next) {
- pchan->parent= (bPoseChannel*)BLI_ghash_lookup(ghash, pchan->parent);
- pchan->child= (bPoseChannel*)BLI_ghash_lookup(ghash, pchan->child);
+ for (pchan = (bPoseChannel *)out->chanbase.first; pchan; pchan = pchan->next) {
+ pchan->parent= (bPoseChannel *)BLI_ghash_lookup(ghash, pchan->parent);
+ pchan->child= (bPoseChannel *)BLI_ghash_lookup(ghash, pchan->child);
if (copy_constraint) {
ListBase listb;
// copy all constraint for backward compatibility
- copy_constraints(&listb, &pchan->constraints, FALSE); // copy_constraints NULLs listb, no need to make extern for this operation.
+ // BKE_copy_constraints NULLs listb, no need to make extern for this operation.
+ BKE_copy_constraints(&listb, &pchan->constraints, FALSE);
pchan->constraints= listb;
} else {
pchan->constraints.first = NULL;
@@ -157,8 +158,8 @@ void game_blend_poses(bPose *dst, bPose *src, float srcweight/*, short mode*/)
dstweight = 1.0F;
}
- schan= (bPoseChannel*)src->chanbase.first;
- for (dchan = (bPoseChannel*)dst->chanbase.first; dchan; dchan=(bPoseChannel*)dchan->next, schan= (bPoseChannel*)schan->next) {
+ schan= (bPoseChannel *)src->chanbase.first;
+ for (dchan = (bPoseChannel *)dst->chanbase.first; dchan; dchan=(bPoseChannel *)dchan->next, schan= (bPoseChannel *)schan->next) {
// always blend on all channels since we don't know which one has been set
/* quat interpolation done separate */
if (schan->rotmode == ROT_MODE_QUAT) {
@@ -304,7 +305,7 @@ void BL_ArmatureObject::LoadConstraints(KX_BlenderSceneConverter* converter)
case CONSTRAINT_TYPE_TRANSFORM:
case CONSTRAINT_TYPE_DISTLIMIT:
case CONSTRAINT_TYPE_TRANSLIKE:
- cti = constraint_get_typeinfo(pcon);
+ cti = BKE_constraint_get_typeinfo(pcon);
gametarget = gamesubtarget = NULL;
if (cti && cti->get_constraint_targets) {
ListBase listb = { NULL, NULL };
@@ -375,7 +376,7 @@ void BL_ArmatureObject::LoadChannels()
BL_ArmatureChannel* proxy;
m_channelNumber = 0;
- for (pchan = (bPoseChannel*)m_pose->chanbase.first; pchan; pchan=(bPoseChannel*)pchan->next) {
+ for (pchan = (bPoseChannel *)m_pose->chanbase.first; pchan; pchan=(bPoseChannel *)pchan->next) {
proxy = new BL_ArmatureChannel(this, pchan);
m_poseChannels.AddBack(proxy);
m_channelNumber++;
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index eb695e624e4..c5dea5d0b43 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -35,6 +35,8 @@
#endif
#include <math.h>
+#include <vector>
+#include <algorithm>
#include "BL_BlenderDataConversion.h"
#include "KX_BlenderGL.h"
@@ -164,7 +166,7 @@ extern Material defmaterial; /* material.c */
#include "SG_Tree.h"
#include "KX_ConvertPhysicsObject.h"
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
#include "CcdPhysicsEnvironment.h"
#include "CcdGraphicController.h"
#endif
@@ -192,6 +194,8 @@ extern "C" {
}
#endif
+#include "BLI_threads.h"
+
static bool default_light_mode = 0;
static std::map<int, SCA_IInputDevice::KX_EnumInputs> create_translate_table()
@@ -422,38 +426,46 @@ static void SetDefaultLightMode(Scene* scene)
}
+static bool GetMaterialUseVColor(Material *ma, const bool glslmat)
+{
+ if (ma) {
+ /* glsl uses vertex colors, otherwise use material setting
+ * defmaterial doesn't have VERTEXCOLP as default [#34505] */
+ return (glslmat || ma == &defmaterial || (ma->mode & MA_VERTEXCOLP) != 0);
+ }
+ else {
+ /* no material, use vertex colors */
+ return true;
+ }
+}
+
// --
static void GetRGB(
- const bool use_mcol,
- MFace *mface,
- MCol *mmcol,
+ const bool use_vcol,
+ MFace* mface,
+ MCol* mmcol,
Material *mat,
- unsigned int &c0,
- unsigned int &c1,
- unsigned int &c2,
- unsigned int &c3)
+ unsigned int c[4])
{
unsigned int color = 0xFFFFFFFFL;
- if (use_mcol) {
- // vertex colors
-
+ if (use_vcol == true) {
if (mmcol) {
- c0 = KX_Mcol2uint_new(mmcol[0]);
- c1 = KX_Mcol2uint_new(mmcol[1]);
- c2 = KX_Mcol2uint_new(mmcol[2]);
+ c[0] = KX_Mcol2uint_new(mmcol[0]);
+ c[1] = KX_Mcol2uint_new(mmcol[1]);
+ c[2] = KX_Mcol2uint_new(mmcol[2]);
if (mface->v4)
- c3 = KX_Mcol2uint_new(mmcol[3]);
+ c[3] = KX_Mcol2uint_new(mmcol[3]);
}
else { // backup white
- c0 = KX_rgbaint2uint_new(color);
- c1 = KX_rgbaint2uint_new(color);
- c2 = KX_rgbaint2uint_new(color);
+ c[0] = KX_rgbaint2uint_new(color);
+ c[1] = KX_rgbaint2uint_new(color);
+ c[2] = KX_rgbaint2uint_new(color);
if (mface->v4)
- c3 = KX_rgbaint2uint_new( color );
+ c[3] = KX_rgbaint2uint_new( color );
}
}
else {
- // material rgba
+ /* material rgba */
if (mat) {
union {
unsigned char cp[4];
@@ -465,14 +477,23 @@ static void GetRGB(
col_converter.cp[0] = (unsigned char) (mat->alpha * 255.0f);
color = col_converter.integer;
}
- // backup white is fallback
+ c[0] = KX_rgbaint2uint_new(color);
+ c[1] = KX_rgbaint2uint_new(color);
+ c[2] = KX_rgbaint2uint_new(color);
+ if (mface->v4) {
+ c[3] = KX_rgbaint2uint_new(color);
+ }
+ }
- c0 = KX_rgbaint2uint_new(color);
- c1 = KX_rgbaint2uint_new(color);
- c2 = KX_rgbaint2uint_new(color);
+#if 0 /* white, unused */
+ {
+ c[0] = KX_rgbaint2uint_new(color);
+ c[1] = KX_rgbaint2uint_new(color);
+ c[2] = KX_rgbaint2uint_new(color);
if (mface->v4)
- c3 = KX_rgbaint2uint_new(color);
+ c[3] = KX_rgbaint2uint_new(color);
}
+#endif
}
typedef struct MTF_localLayer {
@@ -480,42 +501,71 @@ typedef struct MTF_localLayer {
const char *name;
} MTF_localLayer;
-static void tface_to_uv_bge(const MFace *mface, const MTFace *tface, MT_Point2 uv[4])
+static void GetUVs(BL_Material *material, MTF_localLayer *layers, MFace *mface, MTFace *tface, MT_Point2 uvs[4][MAXTEX])
{
- uv[0].setValue(tface->uv[0]);
- uv[1].setValue(tface->uv[1]);
- uv[2].setValue(tface->uv[2]);
- if (mface->v4) {
- uv[3].setValue(tface->uv[3]);
+ int unit = 0;
+ if (tface)
+ {
+
+ uvs[0][0].setValue(tface->uv[0]);
+ uvs[1][0].setValue(tface->uv[1]);
+ uvs[2][0].setValue(tface->uv[2]);
+
+ if (mface->v4)
+ uvs[3][0].setValue(tface->uv[3]);
}
-}
+ else
+ {
+ uvs[0][0] = uvs[1][0] = uvs[2][0] = uvs[3][0] = MT_Point2(0.f, 0.f);
+ }
+
+ vector<STR_String> found_layers;
-static void GetUV(
- MFace *mface,
- MTFace *tface,
- MTF_localLayer *layers,
- const int layer_uv[2],
- MT_Point2 uv[4],
- MT_Point2 uv2[4])
-{
- bool validface = (tface != NULL);
+ for (int vind = 0; vind<MAXTEX; vind++)
+ {
+ BL_Mapping &map = material->mapping[vind];
- uv2[0] = uv2[1] = uv2[2] = uv2[3] = MT_Point2(0.0f, 0.0f);
+ if (!(map.mapping & USEUV)) continue;
- /* No material, what to do? let's see what is in the UV and set the material accordingly
- * light and visible is always on */
- if (layer_uv[0] != -1) {
- tface_to_uv_bge(mface, layers[layer_uv[0]].face, uv);
- if (layer_uv[1] != -1) {
- tface_to_uv_bge(mface, layers[layer_uv[1]].face, uv2);
+ if (std::find(found_layers.begin(), found_layers.end(), map.uvCoName) != found_layers.end())
+ continue;
+
+ //If no UVSet is specified, try grabbing one from the UV/Image editor
+ if (map.uvCoName.IsEmpty() && tface)
+ {
+ uvs[0][unit].setValue(tface->uv[0]);
+ uvs[1][unit].setValue(tface->uv[1]);
+ uvs[2][unit].setValue(tface->uv[2]);
+
+ if (mface->v4)
+ uvs[3][unit].setValue(tface->uv[3]);
+
+ ++unit;
+ continue;
+ }
+
+
+ for (int lay=0; lay<MAX_MTFACE; lay++)
+ {
+ MTF_localLayer& layer = layers[lay];
+ if (layer.face == 0) break;
+
+ if (map.uvCoName.IsEmpty() || strcmp(map.uvCoName.ReadPtr(), layer.name)==0)
+ {
+ uvs[0][unit].setValue(layer.face->uv[0]);
+ uvs[1][unit].setValue(layer.face->uv[1]);
+ uvs[2][unit].setValue(layer.face->uv[2]);
+
+ if (mface->v4)
+ uvs[3][unit].setValue(layer.face->uv[3]);
+ else
+ uvs[3][unit].setValue(0.0f, 0.0f);
+
+ ++unit;
+ found_layers.push_back(map.uvCoName);
+ break;
+ }
}
- }
- else if (validface) {
- tface_to_uv_bge(mface, tface, uv);
- }
- else {
- // nothing at all
- uv[0] = uv[1] = uv[2] = uv[3] = MT_Point2(0.0f, 0.0f);
}
}
@@ -526,25 +576,22 @@ static bool ConvertMaterial(
MTFace* tface,
const char *tfaceName,
MFace* mface,
- MCol* mmcol, /* only for text, use first mcol, weak */
- MTF_localLayer *layers,
- int layer_uv[2],
- const bool glslmat)
+ MCol* mmcol,
+ bool glslmat)
{
material->Initialize();
- int numchan = -1, texalpha = 0;
- bool validmat = (mat!=0);
- bool validface = (tface!=0);
+ int texalpha = 0;
+ const bool validmat = (mat != NULL);
+ const bool validface = (tface != NULL);
+ const bool use_vcol = GetMaterialUseVColor(mat, glslmat);
material->IdMode = DEFAULT_BLENDER;
- material->glslmat = (validmat)? glslmat: false;
+ material->glslmat = (validmat) ? glslmat: false;
material->materialindex = mface->mat_nr;
- /* default value for being unset */
- layer_uv[0] = layer_uv[1] = -1;
-
// --------------------------------
if (validmat) {
+
// use lighting?
material->ras_mode |= ( mat->mode & MA_SHLESS )?0:USE_LIGHT;
material->ras_mode |= ( mat->game.flag & GEMAT_BACKCULL )?0:TWOSIDED;
@@ -552,7 +599,6 @@ static bool ConvertMaterial(
// cast shadows?
material->ras_mode |= ( mat->mode & MA_SHADBUF )?CAST_SHADOW:0;
MTex *mttmp = 0;
- numchan = getNumTexChannels(mat);
int valid_index = 0;
/* In Multitexture use the face texture if and only if
@@ -561,12 +607,9 @@ static bool ConvertMaterial(
bool facetex = false;
if (validface && mat->mode &MA_FACETEXTURE)
facetex = true;
-
- numchan = numchan>MAXTEX?MAXTEX:numchan;
- if (facetex && numchan == 0) numchan = 1;
// foreach MTex
- for (int i=0; i<numchan; i++) {
+ for (int i=0; i<MAXTEX; i++) {
// use face tex
if (i==0 && facetex ) {
@@ -582,19 +625,14 @@ static bool ConvertMaterial(
material->flag[i] |= ( mat->game.alpha_blend & GEMAT_ALPHA )?USEALPHA:0;
material->flag[i] |= ( mat->game.alpha_blend & GEMAT_ADD )?CALCALPHA:0;
- if (material->img[i]->flag & IMA_REFLECT)
+ if (material->img[i]->flag & IMA_REFLECT) {
material->mapping[i].mapping |= USEREFL;
- else
- {
- mttmp = getImageFromMaterial( mat, i );
- if (mttmp && mttmp->texco &TEXCO_UV)
- {
- STR_String uvName = mttmp->uvname;
-
- if (!uvName.IsEmpty())
- material->mapping[i].uvCoName = mttmp->uvname;
- else
- material->mapping[i].uvCoName = "";
+ }
+ else {
+ mttmp = getMTexFromMaterial(mat, i);
+ if (mttmp && (mttmp->texco & TEXCO_UV)) {
+ /* string may be "" but thats detected as empty after */
+ material->mapping[i].uvCoName = mttmp->uvname;
}
material->mapping[i].mapping |= USEUV;
}
@@ -608,9 +646,9 @@ static bool ConvertMaterial(
continue;
}
- mttmp = getImageFromMaterial( mat, i );
- if ( mttmp ) {
- if ( mttmp->tex ) {
+ mttmp = getMTexFromMaterial(mat, i);
+ if (mttmp) {
+ if (mttmp->tex) {
if ( mttmp->tex->type == TEX_IMAGE ) {
material->mtexname[i] = mttmp->tex->id.name;
material->img[i] = mttmp->tex->ima;
@@ -619,11 +657,10 @@ static bool ConvertMaterial(
material->texname[i] = material->img[i]->id.name;
material->flag[i] |= ( mttmp->tex->imaflag &TEX_MIPMAP )?MIPMAP:0;
// -----------------------
- if ( mttmp->tex->imaflag &TEX_USEALPHA ) {
+ if (material->img[i] && (material->img[i]->flag & IMA_IGNORE_ALPHA) == 0)
material->flag[i] |= USEALPHA;
- }
// -----------------------
- else if ( mttmp->tex->imaflag &TEX_CALCALPHA ) {
+ if ( mttmp->tex->imaflag &TEX_CALCALPHA ) {
material->flag[i] |= CALCALPHA;
}
else if (mttmp->tex->flag &TEX_NEGALPHA) {
@@ -661,44 +698,44 @@ static bool ConvertMaterial(
#endif
/// --------------------------------
// mapping methods
- material->mapping[i].mapping |= ( mttmp->texco & TEXCO_REFL )?USEREFL:0;
-
- if (mttmp->texco & TEXCO_OBJECT) {
- material->mapping[i].mapping |= USEOBJ;
- if (mttmp->object)
- material->mapping[i].objconame = mttmp->object->id.name;
- }
- else if (mttmp->texco &TEXCO_REFL)
- material->mapping[i].mapping |= USEREFL;
- else if (mttmp->texco &(TEXCO_ORCO|TEXCO_GLOB))
- material->mapping[i].mapping |= USEORCO;
- else if (mttmp->texco &TEXCO_UV)
- {
- STR_String uvName = mttmp->uvname;
-
- if (!uvName.IsEmpty())
+ if (mat->septex & (1 << i)) {
+ // If this texture slot isn't in use, set it to disabled to prevent multi-uv problems
+ material->mapping[i].mapping = DISABLE;
+ } else {
+ material->mapping[i].mapping |= ( mttmp->texco & TEXCO_REFL )?USEREFL:0;
+
+ if (mttmp->texco & TEXCO_OBJECT) {
+ material->mapping[i].mapping |= USEOBJ;
+ if (mttmp->object)
+ material->mapping[i].objconame = mttmp->object->id.name;
+ }
+ else if (mttmp->texco &TEXCO_REFL)
+ material->mapping[i].mapping |= USEREFL;
+ else if (mttmp->texco &(TEXCO_ORCO|TEXCO_GLOB))
+ material->mapping[i].mapping |= USEORCO;
+ else if (mttmp->texco & TEXCO_UV) {
+ /* string may be "" but thats detected as empty after */
material->mapping[i].uvCoName = mttmp->uvname;
+ material->mapping[i].mapping |= USEUV;
+ }
+ else if (mttmp->texco &TEXCO_NORM)
+ material->mapping[i].mapping |= USENORM;
+ else if (mttmp->texco &TEXCO_TANGENT)
+ material->mapping[i].mapping |= USETANG;
else
- material->mapping[i].uvCoName = "";
- material->mapping[i].mapping |= USEUV;
+ material->mapping[i].mapping |= DISABLE;
+
+ material->mapping[i].scale[0] = mttmp->size[0];
+ material->mapping[i].scale[1] = mttmp->size[1];
+ material->mapping[i].scale[2] = mttmp->size[2];
+ material->mapping[i].offsets[0] = mttmp->ofs[0];
+ material->mapping[i].offsets[1] = mttmp->ofs[1];
+ material->mapping[i].offsets[2] = mttmp->ofs[2];
+
+ material->mapping[i].projplane[0] = mttmp->projx;
+ material->mapping[i].projplane[1] = mttmp->projy;
+ material->mapping[i].projplane[2] = mttmp->projz;
}
- else if (mttmp->texco &TEXCO_NORM)
- material->mapping[i].mapping |= USENORM;
- else if (mttmp->texco &TEXCO_TANGENT)
- material->mapping[i].mapping |= USETANG;
- else
- material->mapping[i].mapping |= DISABLE;
-
- material->mapping[i].scale[0] = mttmp->size[0];
- material->mapping[i].scale[1] = mttmp->size[1];
- material->mapping[i].scale[2] = mttmp->size[2];
- material->mapping[i].offsets[0] = mttmp->ofs[0];
- material->mapping[i].offsets[1] = mttmp->ofs[1];
- material->mapping[i].offsets[2] = mttmp->ofs[2];
-
- material->mapping[i].projplane[0] = mttmp->projx;
- material->mapping[i].projplane[1] = mttmp->projy;
- material->mapping[i].projplane[2] = mttmp->projz;
/// --------------------------------
switch (mttmp->blendtype) {
@@ -798,14 +835,11 @@ static bool ConvertMaterial(
material->ras_mode |= USE_LIGHT;
}
- const char *uvName = "", *uv2Name = "";
-
/* No material, what to do? let's see what is in the UV and set the material accordingly
* light and visible is always on */
if ( validface ) {
material->tile = tface->tile;
- uvName = tfaceName;
- }
+ }
else {
// nothing at all
material->alphablend = GEMAT_SOLID;
@@ -826,45 +860,19 @@ static bool ConvertMaterial(
material->ras_mode |= (mat && (mat->game.alpha_blend & GEMAT_ALPHA_SORT))? ZSORT: 0;
}
- // get uv sets
- if (validmat) {
- bool isFirstSet = true;
-
- // only two sets implemented, but any of the eight
- // sets can make up the two layers
- for (int vind = 0; vind<material->num_enabled; vind++) {
- BL_Mapping &map = material->mapping[vind];
+ // XXX The RGB values here were meant to be temporary storage for the conversion process,
+ // but fonts now make use of them too, so we leave them in for now.
+ unsigned int rgb[4];
+ GetRGB(use_vcol, mface, mmcol, mat, rgb);
- if (map.uvCoName.IsEmpty()) {
- isFirstSet = false;
- }
- else {
- for (int lay=0; lay<MAX_MTFACE; lay++) {
- MTF_localLayer& layer = layers[lay];
- if (layer.face == 0) break;
-
- if (strcmp(map.uvCoName.ReadPtr(), layer.name)==0) {
- if (isFirstSet) {
- layer_uv[0] = lay;
- isFirstSet = false;
- uvName = layer.name;
- }
- else if (strcmp(layer.name, uvName) != 0) {
- layer_uv[1] = lay;
- map.mapping |= USECUSTOMUV;
- uv2Name = layer.name;
- }
- }
- }
- }
- }
- }
-
- if (validmat && mmcol) { /* color is only for text */
- material->m_mcol = *(unsigned int *)mmcol;
+ // 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->SetUVLayerName(uvName);
- material->SetUVLayerName2(uv2Name);
if (validmat)
material->matname =(mat->id.name);
@@ -879,8 +887,188 @@ static bool ConvertMaterial(
return true;
}
+static RAS_MaterialBucket *material_from_mesh(Material *ma, MFace *mface, MTFace *tface, MCol *mcol, MTF_localLayer *layers, int lightlayer, unsigned int *rgb, MT_Point2 uvs[4][RAS_TexVert::MAX_UNIT], const char *tfaceName, KX_Scene* scene, KX_BlenderSceneConverter *converter)
+{
+ RAS_IPolyMaterial* polymat = converter->FindCachedPolyMaterial(ma);
+ BL_Material* bl_mat = converter->FindCachedBlenderMaterial(ma);
+ KX_BlenderMaterial* kx_blmat = NULL;
+ KX_PolygonMaterial* kx_polymat = NULL;
+
+ if (converter->GetMaterials()) {
+ /* do Blender Multitexture and Blender GLSL materials */
+
+ /* first is the BL_Material */
+ if (!bl_mat)
+ {
+ bl_mat = new BL_Material();
+
+ ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol,
+ converter->GetGLSLMaterials());
+
+ converter->CacheBlenderMaterial(ma, bl_mat);
+ }
+
+ const bool use_vcol = GetMaterialUseVColor(ma, bl_mat->glslmat);
+ GetRGB(use_vcol, mface, mcol, ma, rgb);
+
+ GetUVs(bl_mat, layers, mface, tface, uvs);
+
+ /* then the KX_BlenderMaterial */
+ if (polymat == NULL)
+ {
+ kx_blmat = new KX_BlenderMaterial();
+
+ kx_blmat->Initialize(scene, bl_mat, (ma?&ma->game:NULL), lightlayer);
+ polymat = static_cast<RAS_IPolyMaterial*>(kx_blmat);
+ converter->CachePolyMaterial(ma, polymat);
+ }
+ }
+ else {
+ /* do Texture Face materials */
+ Image* bima = (tface)? (Image*)tface->tpage: NULL;
+ STR_String imastr = (tface)? (bima? (bima)->id.name : "" ) : "";
+
+ char alpha_blend=0;
+ short tile=0;
+ int tilexrep=4,tileyrep = 4;
+
+ /* set material properties - old TexFace */
+ if (ma) {
+ alpha_blend = ma->game.alpha_blend;
+ /* Commented out for now. If we ever get rid of
+ * "Texture Face/Singletexture" we can then think about it */
+
+ /* Texture Face mode ignores texture but requires "Face Textures to be True "*/
+ #if 0
+ if ((ma->mode &MA_FACETEXTURE)==0 && (ma->game.flag &GEMAT_TEXT)==0) {
+ bima = NULL;
+ imastr = "";
+ alpha_blend = GEMAT_SOLID;
+ }
+ else {
+ alpha_blend = ma->game.alpha_blend;
+ }
+ #endif
+ }
+ /* check for tface tex to fallback on */
+ else {
+ if (bima) {
+ /* see if depth of the image is 32 */
+ if (BKE_image_has_alpha(bima))
+ alpha_blend = GEMAT_ALPHA;
+ else
+ alpha_blend = GEMAT_SOLID;
+ }
+ else {
+ alpha_blend = GEMAT_SOLID;
+ }
+ }
+
+ if (bima) {
+ tilexrep = bima->xrep;
+ tileyrep = bima->yrep;
+ }
+
+ /* set UV properties */
+ if (tface) {
+ uvs[0][0].setValue(tface->uv[0]);
+ uvs[1][0].setValue(tface->uv[1]);
+ uvs[2][0].setValue(tface->uv[2]);
+
+ if (mface->v4)
+ uvs[3][0].setValue(tface->uv[3]);
+
+ tile = tface->tile;
+ }
+ else {
+ /* no texfaces */
+ tile = 0;
+ }
+
+ /* get vertex colors */
+ if (mcol) {
+ /* we have vertex colors */
+ rgb[0] = KX_Mcol2uint_new(mcol[0]);
+ rgb[1] = KX_Mcol2uint_new(mcol[1]);
+ rgb[2] = KX_Mcol2uint_new(mcol[2]);
+
+ if (mface->v4)
+ rgb[3] = KX_Mcol2uint_new(mcol[3]);
+ }
+ else {
+ /* no vertex colors, take from material, otherwise white */
+ unsigned int color = 0xFFFFFFFFL;
+
+ if (ma)
+ {
+ union
+ {
+ unsigned char cp[4];
+ unsigned int integer;
+ } col_converter;
+
+ col_converter.cp[3] = (unsigned char) (ma->r*255.0);
+ col_converter.cp[2] = (unsigned char) (ma->g*255.0);
+ col_converter.cp[1] = (unsigned char) (ma->b*255.0);
+ col_converter.cp[0] = (unsigned char) (ma->alpha*255.0);
+
+ color = col_converter.integer;
+ }
+
+ rgb[0] = KX_rgbaint2uint_new(color);
+ rgb[1] = KX_rgbaint2uint_new(color);
+ rgb[2] = KX_rgbaint2uint_new(color);
+
+ if (mface->v4)
+ rgb[3] = KX_rgbaint2uint_new(color);
+ }
+
+ // only zsort alpha + add
+ const bool alpha = ELEM3(alpha_blend, GEMAT_ALPHA, GEMAT_ADD, GEMAT_ALPHA_SORT);
+ const bool zsort = (alpha_blend == GEMAT_ALPHA_SORT);
+ const bool light = (ma)?(ma->mode & MA_SHLESS)==0:default_light_mode;
+
+ // don't need zort anymore, deal as if it it's alpha blend
+ if (alpha_blend == GEMAT_ALPHA_SORT) alpha_blend = GEMAT_ALPHA;
+
+ if (polymat == NULL)
+ {
+ kx_polymat = new KX_PolygonMaterial();
+ kx_polymat->Initialize(imastr, ma, (int)mface->mat_nr,
+ tile, tilexrep, tileyrep,
+ alpha_blend, alpha, zsort, light, lightlayer, tface, (unsigned int*)mcol);
+ polymat = static_cast<RAS_IPolyMaterial*>(kx_polymat);
+
+ if (ma) {
+ polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec;
+ polymat->m_shininess = (float)ma->har/4.0f; // 0 < ma->har <= 512
+ polymat->m_diffuse = MT_Vector3(ma->r, ma->g, ma->b)*(ma->emit + ma->ref);
+ }
+ else {
+ polymat->m_specular.setValue(0.0f,0.0f,0.0f);
+ polymat->m_shininess = 35.0;
+ }
+
+ converter->CachePolyMaterial(ma, polymat);
+ }
+ }
+
+ // see if a bucket was reused or a new one was created
+ // this way only one KX_BlenderMaterial object has to exist per bucket
+ bool bucketCreated;
+ RAS_MaterialBucket* bucket = scene->FindBucket(polymat, bucketCreated);
+ if (bucketCreated) {
+ // this is needed to free up memory afterwards
+ converter->RegisterPolyMaterial(polymat);
+ if (converter->GetMaterials())
+ converter->RegisterBlenderMaterial(bl_mat);
+ }
+
+ return bucket;
+}
+
/* blenderobj can be NULL, make sure its checked for */
-RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, KX_BlenderSceneConverter *converter)
+RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, KX_BlenderSceneConverter *converter, bool libloading)
{
RAS_MeshObject *meshobj;
int lightlayer = blenderobj ? blenderobj->lay:(1<<20)-1; // all layers if no object.
@@ -910,7 +1098,6 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
// Extract avaiable layers
MTF_localLayer *layers = new MTF_localLayer[MAX_MTFACE];
- int layer_uv[2]; /* store uv1, uv2 layers */
for (int lay=0; lay<MAX_MTFACE; lay++) {
layers[lay].face = 0;
layers[lay].name = "";
@@ -933,31 +1120,38 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
meshobj->SetName(mesh->id.name + 2);
meshobj->m_sharedvertex_map.resize(totvert);
- RAS_IPolyMaterial* polymat = NULL;
- STR_String imastr;
- // These pointers will hold persistent material structure during the conversion
- // to avoid countless allocation/deallocation of memory.
- BL_Material* bl_mat = NULL;
- KX_BlenderMaterial* kx_blmat = NULL;
- KX_PolygonMaterial* kx_polymat = NULL;
- for (int f=0;f<totface;f++,mface++)
- {
- Material* ma = 0;
- bool collider = true;
- MT_Point2 uv0(0.0,0.0),uv1(0.0,0.0),uv2(0.0,0.0),uv3(0.0,0.0);
- MT_Point2 uv20(0.0,0.0),uv21(0.0,0.0),uv22(0.0,0.0),uv23(0.0,0.0);
- unsigned int rgb0,rgb1,rgb2,rgb3 = 0;
+ Material* ma = 0;
+ bool collider = true;
+ MT_Point2 uvs[4][RAS_TexVert::MAX_UNIT];
+ unsigned int rgb[4] = {0};
+
+ MT_Point3 pt[4];
+ MT_Vector3 no[4];
+ MT_Vector4 tan[4];
- MT_Point3 pt0, pt1, pt2, pt3;
- MT_Vector3 no0(0,0,0), no1(0,0,0), no2(0,0,0), no3(0,0,0);
- MT_Vector4 tan0(0,0,0,0), tan1(0,0,0,0), tan2(0,0,0,0), tan3(0,0,0,0);
+ /* ugh, if there is a less annoying way to do this please use that.
+ * since these are converted from floats to floats, theres no real
+ * advantage to use MT_ types - campbell */
+ for (unsigned int i = 0; i < 4; i++) {
+ const float zero_vec[4] = {0.0f};
+ pt[i].setValue(zero_vec);
+ no[i].setValue(zero_vec);
+ tan[i].setValue(zero_vec);
+ }
+ /* we need to manually initialize the uvs (MoTo doesn't do that) [#34550] */
+ for (unsigned int i = 0; i < RAS_TexVert::MAX_UNIT; i++) {
+ uvs[0][i] = uvs[1][i] = uvs[2][i] = uvs[3][i] = MT_Point2(0.f, 0.f);
+ }
+
+ for (int f=0;f<totface;f++,mface++)
+ {
/* get coordinates, normals and tangents */
- pt0.setValue(mvert[mface->v1].co);
- pt1.setValue(mvert[mface->v2].co);
- pt2.setValue(mvert[mface->v3].co);
- if (mface->v4) pt3.setValue(mvert[mface->v4].co);
+ pt[0].setValue(mvert[mface->v1].co);
+ pt[1].setValue(mvert[mface->v2].co);
+ pt[2].setValue(mvert[mface->v3].co);
+ if (mface->v4) pt[3].setValue(mvert[mface->v4].co);
if (mface->flag & ME_SMOOTH) {
float n0[3], n1[3], n2[3], n3[3];
@@ -965,13 +1159,13 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
normal_short_to_float_v3(n0, mvert[mface->v1].no);
normal_short_to_float_v3(n1, mvert[mface->v2].no);
normal_short_to_float_v3(n2, mvert[mface->v3].no);
- no0 = n0;
- no1 = n1;
- no2 = n2;
+ no[0] = n0;
+ no[1] = n1;
+ no[2] = n2;
if (mface->v4) {
normal_short_to_float_v3(n3, mvert[mface->v4].no);
- no3 = n3;
+ no[3] = n3;
}
}
else {
@@ -982,16 +1176,16 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
else
normal_tri_v3(fno,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
- no0 = no1 = no2 = no3 = MT_Vector3(fno);
+ no[0] = no[1] = no[2] = no[3] = MT_Vector3(fno);
}
if (tangent) {
- tan0 = tangent[f*4 + 0];
- tan1 = tangent[f*4 + 1];
- tan2 = tangent[f*4 + 2];
+ tan[0] = tangent[f*4 + 0];
+ tan[1] = tangent[f*4 + 1];
+ tan[2] = tangent[f*4 + 2];
if (mface->v4)
- tan3 = tangent[f*4 + 3];
+ tan[3] = tangent[f*4 + 3];
}
if (blenderobj)
ma = give_current_material(blenderobj, mface->mat_nr+1);
@@ -1007,171 +1201,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
bool visible = true;
bool twoside = false;
- if (converter->GetMaterials()) {
- const bool is_bl_mat_new = (bl_mat == NULL);
- //const bool is_kx_blmat_new = (kx_blmat == NULL);
- const bool glslmat = converter->GetGLSLMaterials();
- const bool use_mcol = ma ? (ma->mode & MA_VERTEXCOLP || glslmat) : true;
- /* do Blender Multitexture and Blender GLSL materials */
- MT_Point2 uv_1[4];
- MT_Point2 uv_2[4];
-
- /* first is the BL_Material */
- if (!bl_mat) {
- bl_mat = new BL_Material();
- }
-
- /* only */
- if (is_bl_mat_new || (bl_mat->material != ma)) {
- ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol,
- layers, layer_uv, glslmat);
- }
-
- /* vertex colors and uv's from the faces */
- GetRGB(use_mcol, mface, mcol, ma, rgb0, rgb1, rgb2, rgb3);
- GetUV(mface, tface, layers, layer_uv, uv_1, uv_2);
-
- uv0 = uv_1[0]; uv1 = uv_1[1];
- uv2 = uv_1[2]; uv3 = uv_1[3];
-
- uv20 = uv_2[0]; uv21 = uv_2[1];
- uv22 = uv_2[2]; uv23 = uv_2[3];
-
- /* then the KX_BlenderMaterial */
- if (kx_blmat == NULL)
- kx_blmat = new KX_BlenderMaterial();
-
- //if (is_kx_blmat_new || !kx_blmat->IsMaterial(bl_mat)) {
- kx_blmat->Initialize(scene, bl_mat, (ma ? &ma->game : NULL));
- //}
-
- polymat = static_cast<RAS_IPolyMaterial*>(kx_blmat);
- }
- else {
- /* do Texture Face materials */
- Image* bima = (tface)? (Image*)tface->tpage: NULL;
- imastr = (tface)? (bima? (bima)->id.name : "" ) : "";
-
- char alpha_blend=0;
- short tile=0;
- int tilexrep=4,tileyrep = 4;
-
- /* set material properties - old TexFace */
- if (ma) {
- alpha_blend = ma->game.alpha_blend;
- /* Commented out for now. If we ever get rid of
- * "Texture Face/Singletexture" we can then think about it */
-
- /* Texture Face mode ignores texture but requires "Face Textures to be True "*/
-#if 0
- if ((ma->mode &MA_FACETEXTURE)==0 && (ma->game.flag &GEMAT_TEXT)==0) {
- bima = NULL;
- imastr = "";
- alpha_blend = GEMAT_SOLID;
- }
- else {
- alpha_blend = ma->game.alpha_blend;
- }
-#endif
- }
- /* check for tface tex to fallback on */
- else {
- if (bima) {
- /* see if depth of the image is 32 */
- if (BKE_image_has_alpha(bima))
- alpha_blend = GEMAT_ALPHA;
- else
- alpha_blend = GEMAT_SOLID;
- }
- else {
- alpha_blend = GEMAT_SOLID;
- }
- }
-
- if (bima) {
- tilexrep = bima->xrep;
- tileyrep = bima->yrep;
- }
-
- /* set UV properties */
- if (tface) {
- uv0.setValue(tface->uv[0]);
- uv1.setValue(tface->uv[1]);
- uv2.setValue(tface->uv[2]);
-
- if (mface->v4)
- uv3.setValue(tface->uv[3]);
-
- tile = tface->tile;
- }
- else {
- /* no texfaces */
- tile = 0;
- }
-
- /* get vertex colors */
- if (mcol) {
- /* we have vertex colors */
- rgb0 = KX_Mcol2uint_new(mcol[0]);
- rgb1 = KX_Mcol2uint_new(mcol[1]);
- rgb2 = KX_Mcol2uint_new(mcol[2]);
-
- if (mface->v4)
- rgb3 = KX_Mcol2uint_new(mcol[3]);
- }
- else {
- /* no vertex colors, take from material, otherwise white */
- unsigned int color = 0xFFFFFFFFL;
-
- if (ma)
- {
- union
- {
- unsigned char cp[4];
- unsigned int integer;
- } col_converter;
-
- col_converter.cp[3] = (unsigned char) (ma->r * 255.0f);
- col_converter.cp[2] = (unsigned char) (ma->g * 255.0f);
- col_converter.cp[1] = (unsigned char) (ma->b * 255.0f);
- col_converter.cp[0] = (unsigned char) (ma->alpha * 255.0f);
-
- color = col_converter.integer;
- }
-
- rgb0 = KX_rgbaint2uint_new(color);
- rgb1 = KX_rgbaint2uint_new(color);
- rgb2 = KX_rgbaint2uint_new(color);
-
- if (mface->v4)
- rgb3 = KX_rgbaint2uint_new(color);
- }
-
- // only zsort alpha + add
- bool alpha = ELEM3(alpha_blend, GEMAT_ALPHA, GEMAT_ADD, GEMAT_ALPHA_SORT);
- bool zsort = (alpha_blend == GEMAT_ALPHA_SORT);
- bool light = (ma)?(ma->mode & MA_SHLESS)==0:default_light_mode;
-
- // don't need zort anymore, deal as if it it's alpha blend
- if (alpha_blend == GEMAT_ALPHA_SORT) alpha_blend = GEMAT_ALPHA;
-
- if (kx_polymat == NULL)
- kx_polymat = new KX_PolygonMaterial();
- kx_polymat->Initialize(imastr, ma, (int)mface->mat_nr,
- tile, tilexrep, tileyrep,
- alpha_blend, alpha, zsort, light, lightlayer, tface, (unsigned int*)mcol);
- polymat = static_cast<RAS_IPolyMaterial*>(kx_polymat);
-
- if (ma) {
- polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec;
- polymat->m_shininess = (float)ma->har/4.0f; // 0 < ma->har <= 512
- polymat->m_diffuse = MT_Vector3(ma->r, ma->g, ma->b)*(ma->emit + ma->ref);
- }
- else {
- polymat->m_specular.setValue(0.0f,0.0f,0.0f);
- polymat->m_shininess = 35.0;
- }
- }
+ RAS_MaterialBucket* bucket = material_from_mesh(ma, mface, tface, mcol, layers, lightlayer, rgb, uvs, tfaceName, scene, converter);
// set render flags
if (ma)
@@ -1188,30 +1218,9 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
/* mark face as flat, so vertices are split */
bool flat = (mface->flag & ME_SMOOTH) == 0;
-
- // see if a bucket was reused or a new one was created
- // this way only one KX_BlenderMaterial object has to exist per bucket
- bool bucketCreated;
- RAS_MaterialBucket* bucket = scene->FindBucket(polymat, bucketCreated);
- if (bucketCreated) {
- // this is needed to free up memory afterwards
- converter->RegisterPolyMaterial(polymat);
- if (converter->GetMaterials()) {
- converter->RegisterBlenderMaterial(bl_mat);
- // the poly material has been stored in the bucket, next time we must create a new one
- bl_mat = NULL;
- kx_blmat = NULL;
- } else {
- // the poly material has been stored in the bucket, next time we must create a new one
- kx_polymat = NULL;
- }
- } else {
- // from now on, use the polygon material from the material bucket
- polymat = bucket->GetPolyMaterial();
- // keep the material pointers, they will be reused for next face
- }
-
+
int nverts = (mface->v4)? 4: 3;
+
RAS_Polygon *poly = meshobj->AddPolygon(bucket, nverts);
poly->SetVisible(visible);
@@ -1219,12 +1228,12 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
poly->SetTwoside(twoside);
//poly->SetEdgeCode(mface->edcode);
- meshobj->AddVertex(poly,0,pt0,uv0,uv20,tan0,rgb0,no0,flat,mface->v1);
- meshobj->AddVertex(poly,1,pt1,uv1,uv21,tan1,rgb1,no1,flat,mface->v2);
- meshobj->AddVertex(poly,2,pt2,uv2,uv22,tan2,rgb2,no2,flat,mface->v3);
+ meshobj->AddVertex(poly,0,pt[0],uvs[0],tan[0],rgb[0],no[0],flat,mface->v1);
+ meshobj->AddVertex(poly,1,pt[1],uvs[1],tan[1],rgb[1],no[1],flat,mface->v2);
+ meshobj->AddVertex(poly,2,pt[2],uvs[2],tan[2],rgb[2],no[2],flat,mface->v3);
if (nverts==4)
- meshobj->AddVertex(poly,3,pt3,uv3,uv23,tan3,rgb3,no3,flat,mface->v4);
+ meshobj->AddVertex(poly,3,pt[3],uvs[3],tan[3],rgb[3],no[3],flat,mface->v4);
}
if (tface)
@@ -1246,22 +1255,19 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene,
meshobj->EndConversion();
// pre calculate texture generation
- for (list<RAS_MeshMaterial>::iterator mit = meshobj->GetFirstMaterial();
- mit != meshobj->GetLastMaterial(); ++ mit) {
- mit->m_bucket->GetPolyMaterial()->OnConstruction(lightlayer);
+ // However, we want to delay this if we're libloading so we can make sure we have the right scene.
+ if (!libloading) {
+ for (list<RAS_MeshMaterial>::iterator mit = meshobj->GetFirstMaterial();
+ mit != meshobj->GetLastMaterial(); ++ mit) {
+ mit->m_bucket->GetPolyMaterial()->OnConstruction();
+ }
}
if (layers)
delete []layers;
dm->release(dm);
- // cleanup material
- if (bl_mat)
- delete bl_mat;
- if (kx_blmat)
- delete kx_blmat;
- if (kx_polymat)
- delete kx_polymat;
+
converter->RegisterGameMesh(meshobj, mesh);
return meshobj;
}
@@ -1274,7 +1280,7 @@ static PHY_MaterialProps *CreateMaterialFromBlenderObject(struct Object* blender
MT_assert(materialProps && "Create physics material properties failed");
- Material* blendermat = give_current_material(blenderobject, 0);
+ Material* blendermat = give_current_material(blenderobject, 1);
if (blendermat)
{
@@ -1358,7 +1364,9 @@ static float my_boundbox_mesh(Mesh *me, float *loc, float *size)
float radius=0.0f, vert_radius, *co;
int a;
- if (me->bb==0) me->bb= (struct BoundBox *)MEM_callocN(sizeof(BoundBox), "boundbox");
+ if (me->bb==0) {
+ me->bb = BKE_boundbox_alloc_unit();
+ }
bb= me->bb;
INIT_MINMAX(min, max);
@@ -1535,7 +1543,7 @@ static void BL_CreateGraphicObjectNew(KX_GameObject* gameobj,
{
switch (physics_engine)
{
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
case UseBullet:
{
CcdPhysicsEnvironment* env = (CcdPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
@@ -1838,7 +1846,7 @@ static void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
switch (physics_engine)
{
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
case UseBullet:
KX_ConvertBulletObject(gameobj, meshobj, dm, kxscene, shapeprops, smmaterial, &objprop);
break;
@@ -1921,7 +1929,8 @@ static KX_GameObject *gameobject_from_blenderobject(
Object *ob,
KX_Scene *kxscene,
RAS_IRenderTools *rendertools,
- KX_BlenderSceneConverter *converter)
+ KX_BlenderSceneConverter *converter,
+ bool libloading)
{
KX_GameObject *gameobj = NULL;
Scene *blenderscene = kxscene->GetBlenderScene();
@@ -1958,7 +1967,7 @@ static KX_GameObject *gameobject_from_blenderobject(
Mesh* mesh = static_cast<Mesh*>(ob->data);
float center[3], extents[3];
float radius = my_boundbox_mesh((Mesh*) ob->data, center, extents);
- RAS_MeshObject* meshobj = BL_ConvertMesh(mesh,ob,kxscene,converter);
+ RAS_MeshObject* meshobj = BL_ConvertMesh(mesh,ob,kxscene,converter, libloading);
// needed for python scripting
kxscene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj);
@@ -1981,6 +1990,22 @@ static KX_GameObject *gameobject_from_blenderobject(
((ob->gameflag2 & OB_NEVER_DO_ACTIVITY_CULLING)!=0);
gameobj->SetIgnoreActivityCulling(ignoreActivityCulling);
gameobj->SetOccluder((ob->gameflag & OB_OCCLUDER) != 0, false);
+
+ // we only want obcolor used if there is a material in the mesh
+ // that requires it
+ Material *mat= NULL;
+ bool bUseObjectColor=false;
+
+ for (int i=0;i<mesh->totcol;i++) {
+ mat=mesh->mat[i];
+ if (!mat) break;
+ if ((mat->shade_flag & MA_OBCOLOR)) {
+ bUseObjectColor = true;
+ break;
+ }
+ }
+ if (bUseObjectColor)
+ gameobj->SetObjectColor(ob->col);
// two options exists for deform: shape keys and armature
// only support relative shape key
@@ -1988,7 +2013,7 @@ static KX_GameObject *gameobject_from_blenderobject(
bool bHasDvert = mesh->dvert != NULL && ob->defbase.first;
bool bHasArmature = (BL_ModifierDeformer::HasArmatureDeformer(ob) && ob->parent && ob->parent->type == OB_ARMATURE && bHasDvert);
bool bHasModifier = BL_ModifierDeformer::HasCompatibleDeformer(ob);
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
bool bHasSoftBody = (!ob->parent && (ob->gameflag & OB_SOFT_BODY));
#endif
if (bHasModifier) {
@@ -2015,7 +2040,7 @@ static KX_GameObject *gameobject_from_blenderobject(
BL_MeshDeformer *dcont = new BL_MeshDeformer((BL_DeformableGameObject*)gameobj,
ob, meshobj);
((BL_DeformableGameObject*)gameobj)->SetDeformer(dcont);
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
} else if (bHasSoftBody) {
KX_SoftBodyDeformer *dcont = new KX_SoftBodyDeformer(meshobj, (BL_DeformableGameObject*)gameobj);
((BL_DeformableGameObject*)gameobj)->SetDeformer(dcont);
@@ -2123,7 +2148,7 @@ static void UNUSED_FUNCTION(RBJconstraints)(Object *ob)//not used
conlist = get_active_constraints2(ob);
if (conlist) {
- for (curcon = (bConstraint *)conlist->first; curcon; curcon=(bConstraint *)curcon->next) {
+ for (curcon = (bConstraint *)conlist->first; curcon; curcon = (bConstraint *)curcon->next) {
printf("%i\n",curcon->type);
}
@@ -2187,26 +2212,37 @@ static void bl_ConvertBlenderObject_Single(
blenderobject->loc[1]+blenderobject->dloc[1],
blenderobject->loc[2]+blenderobject->dloc[2]
);
- MT_Vector3 eulxyz(blenderobject->rot);
+
+ MT_Matrix3x3 rotation;
+ float rotmat[3][3];
+ BKE_object_rot_to_mat3(blenderobject, rotmat, FALSE);
+ rotation.setValue3x3((float*)rotmat);
+
MT_Vector3 scale(blenderobject->size);
+
if (converter->addInitFromFrame) {//rcruiz
- float eulxyzPrev[3];
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]
);
- eulxyzPrev[0]=blenderobject->rot[0];
- eulxyzPrev[1]=blenderobject->rot[1];
- eulxyzPrev[2]=blenderobject->rot[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=eulxyz-eulxyzPrev;
+ 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;
@@ -2214,12 +2250,10 @@ static void bl_ConvertBlenderObject_Single(
}
gameobj->NodeSetLocalPosition(pos);
- gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz));
+ gameobj->NodeSetLocalOrientation(rotation);
gameobj->NodeSetLocalScale(scale);
gameobj->NodeUpdateGS(0);
- BL_ConvertMaterialIpos(blenderobject, gameobj, converter);
-
sumolist->Add(gameobj->AddRef());
BL_ConvertProperties(blenderobject,gameobj,timemgr,kxscene,isInActiveLayer);
@@ -2321,7 +2355,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
RAS_IRenderTools* rendertools,
RAS_ICanvas* canvas,
KX_BlenderSceneConverter* converter,
- bool alwaysUseExpandFraming
+ bool alwaysUseExpandFraming,
+ bool libloading
)
{
@@ -2355,6 +2390,10 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
set<Object*> allblobj; // all objects converted
set<Object*> groupobj; // objects from groups (never in active layer)
+ // This is bad, but we use this to make sure the first time this is called
+ // is not in a separate thread.
+ BL_Texture::GetMaxUnits();
+
if (alwaysUseExpandFraming) {
frame_type = RAS_FrameSettings::e_frame_extend;
aspect_width = canvas->GetWidth();
@@ -2431,7 +2470,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
base->object,
kxscene,
rendertools,
- converter);
+ converter,
+ libloading);
bool isInActiveLayer = (blenderobject->lay & activeLayerBitInfo) !=0;
bool addobj=true;
@@ -2490,7 +2530,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
blenderobject,
kxscene,
rendertools,
- converter);
+ converter,
+ libloading);
// this code is copied from above except that
// object from groups are never in active layer
@@ -2752,7 +2793,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
continue;
if (conlist) {
- for (curcon = (bConstraint *)conlist->first; curcon; curcon=(bConstraint *)curcon->next) {
+ for (curcon = (bConstraint *)conlist->first; curcon; curcon = (bConstraint *)curcon->next) {
if (curcon->type==CONSTRAINT_TYPE_RIGIDBODYJOINT) {
bRigidBodyJointConstraint *dat=(bRigidBodyJointConstraint *)curcon->data;
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.h b/source/gameengine/Converter/BL_BlenderDataConversion.h
index 2a7efaac898..f3a680929fb 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.h
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.h
@@ -38,7 +38,7 @@
#include "KX_PhysicsEngineEnums.h"
#include "SCA_IInputDevice.h"
-class RAS_MeshObject* BL_ConvertMesh(struct Mesh* mesh,struct Object* lightobj,class KX_Scene* scene, class KX_BlenderSceneConverter *converter);
+class RAS_MeshObject* BL_ConvertMesh(struct Mesh* mesh,struct Object* lightobj,class KX_Scene* scene, class KX_BlenderSceneConverter *converter, bool libloading);
void BL_ConvertBlenderObjects(struct Main* maggie,
class KX_Scene* kxscene,
@@ -47,7 +47,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
class RAS_IRenderTools* rendertools,
class RAS_ICanvas* canvas,
class KX_BlenderSceneConverter* sceneconverter,
- bool alwaysUseExpandFraming
+ bool alwaysUseExpandFraming,
+ bool libloading=false
);
SCA_IInputDevice::KX_EnumInputs ConvertKeyCode(int key_code);
diff --git a/source/gameengine/Converter/BL_DeformableGameObject.cpp b/source/gameengine/Converter/BL_DeformableGameObject.cpp
index 4967401f279..3a4a27a6722 100644
--- a/source/gameengine/Converter/BL_DeformableGameObject.cpp
+++ b/source/gameengine/Converter/BL_DeformableGameObject.cpp
@@ -94,7 +94,7 @@ bool BL_DeformableGameObject::GetShape(vector<float> &shape)
if (key && key->type==KEY_RELATIVE)
{
KeyBlock *kb;
- for (kb = (KeyBlock*)key->block.first; kb; kb = (KeyBlock*)kb->next)
+ for (kb = (KeyBlock *)key->block.first; kb; kb = (KeyBlock *)kb->next)
{
shape.push_back(kb->curval);
}
diff --git a/source/gameengine/Converter/BL_ModifierDeformer.cpp b/source/gameengine/Converter/BL_ModifierDeformer.cpp
index 53755deefe1..ec52eaac637 100644
--- a/source/gameengine/Converter/BL_ModifierDeformer.cpp
+++ b/source/gameengine/Converter/BL_ModifierDeformer.cpp
@@ -67,10 +67,6 @@ extern "C"{
#include "BLI_blenlib.h"
#include "BLI_math.h"
-#define __NLA_DEFNORMALS
-//#undef __NLA_DEFNORMALS
-
-
BL_ModifierDeformer::~BL_ModifierDeformer()
{
if (m_dm) {
diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp
index d8b4f6aaf1c..4806ed04cc6 100644
--- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp
@@ -176,9 +176,9 @@ void BL_ShapeActionActuator::BlendShape(Key* key, float srcweight)
dstweight = 1.0F - srcweight;
- for (it=m_blendshape.begin(), kb = (KeyBlock*)key->block.first;
+ for (it=m_blendshape.begin(), kb = (KeyBlock *)key->block.first;
kb && it != m_blendshape.end();
- kb = (KeyBlock*)kb->next, it++)
+ kb = (KeyBlock *)kb->next, it++)
{
kb->curval = kb->curval * dstweight + (*it) * srcweight;
}
@@ -439,7 +439,7 @@ bool BL_ShapeActionActuator::Update(double curtime, bool frame)
KeyBlock *kb;
// We go through and clear out the keyblocks so there isn't any interference
// from other shape actions
- for (kb=(KeyBlock*)key->block.first; kb; kb=(KeyBlock*)kb->next)
+ for (kb=(KeyBlock *)key->block.first; kb; kb=(KeyBlock *)kb->next)
kb->curval = 0.f;
animsys_evaluate_action(m_idptr, m_action, NULL, m_localtime);
diff --git a/source/gameengine/Converter/CMakeLists.txt b/source/gameengine/Converter/CMakeLists.txt
index e9dd97f3821..f18646c1de0 100644
--- a/source/gameengine/Converter/CMakeLists.txt
+++ b/source/gameengine/Converter/CMakeLists.txt
@@ -82,7 +82,7 @@ set(SRC
KX_ConvertControllers.cpp
KX_ConvertProperties.cpp
KX_ConvertSensors.cpp
- KX_IpoConvert.cpp
+ KX_LibLoadStatus.cpp
KX_SoftBodyDeformer.cpp
BL_ActionActuator.h
@@ -104,15 +104,15 @@ set(SRC
KX_ConvertControllers.h
KX_ConvertProperties.h
KX_ConvertSensors.h
- KX_IpoConvert.h
+ KX_LibLoadStatus.h
KX_SoftBodyDeformer.h
)
if(WITH_BULLET)
list(APPEND INC_SYS
- ../../../extern/bullet2/src
+ ${BULLET_INCLUDE_DIRS}
)
- add_definitions(-DUSE_BULLET)
+ add_definitions(-DWITH_BULLET)
endif()
if(WITH_AUDASPACE)
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
index d1684db0f5a..86e8c9c6e76 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
@@ -55,11 +55,12 @@
#include "KX_ConvertPhysicsObject.h"
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
#include "CcdPhysicsEnvironment.h"
#endif
#include "KX_BlenderSceneConverter.h"
+#include "KX_LibLoadStatus.h"
#include "KX_BlenderScalarInterpolator.h"
#include "BL_BlenderDataConversion.h"
#include "BlenderWorldInfo.h"
@@ -113,6 +114,14 @@ extern "C" {
#include "../../blender/blenlib/BLI_linklist.h"
}
+#include <pthread.h>
+
+/* This is used to avoid including pthread.h in KX_BlenderSceneConverter.h */
+typedef struct ThreadInfo {
+ vector<pthread_t> threads;
+ pthread_mutex_t merge_lock;
+} ThreadInfo;
+
KX_BlenderSceneConverter::KX_BlenderSceneConverter(
struct Main* maggie,
class KX_KetsjiEngine* engine
@@ -122,10 +131,13 @@ KX_BlenderSceneConverter::KX_BlenderSceneConverter(
m_ketsjiEngine(engine),
m_alwaysUseExpandFraming(false),
m_usemat(false),
- m_useglslmat(false)
+ m_useglslmat(false),
+ m_use_mat_cache(true)
{
tag_main(maggie, 0); /* avoid re-tagging later on */
m_newfilename = "";
+ m_threadinfo = new ThreadInfo();
+ pthread_mutex_init(&m_threadinfo->merge_lock, NULL);
}
@@ -135,6 +147,16 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
int i;
// delete sumoshapes
+ if (m_threadinfo) {
+ vector<pthread_t>::iterator pit = m_threadinfo->threads.begin();
+ while (pit != m_threadinfo->threads.end()) {
+ pthread_join((*pit), NULL);
+ pit++;
+ }
+
+ pthread_mutex_destroy(&m_threadinfo->merge_lock);
+ delete m_threadinfo;
+ }
int numAdtLists = m_map_blender_to_gameAdtList.size();
for (i=0; i<numAdtLists; i++) {
@@ -151,6 +173,7 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
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;
itp++;
}
@@ -158,6 +181,7 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
// delete after RAS_IPolyMaterial
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;
itmat++;
}
@@ -169,7 +193,7 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
itm++;
}
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
KX_ClearBulletSharedShapes();
#endif
@@ -230,7 +254,7 @@ Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String& name)
}
#include "KX_PythonInit.h"
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
#include "LinearMath/btIDebugDraw.h"
@@ -286,7 +310,8 @@ struct BlenderDebugDraw : public btIDebugDraw
void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
class RAS_IRenderTools* rendertools,
- class RAS_ICanvas* canvas)
+ class RAS_ICanvas* canvas,
+ bool libloading)
{
//find out which physics engine
Scene *blenderscene = destinationscene->GetBlenderScene();
@@ -296,7 +321,10 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
// hook for registration function during conversion.
m_currentScene = destinationscene;
destinationscene->SetSceneConverter(this);
- SG_SetActiveStage(SG_STAGE_CONVERTER);
+
+ // This doesn't really seem to do anything except cause potential issues
+ // when doing threaded conversion, so it's disabled for now.
+ // SG_SetActiveStage(SG_STAGE_CONVERTER);
if (blenderscene)
{
@@ -320,7 +348,7 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
switch (physics_engine)
{
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
case UseBullet:
{
CcdPhysicsEnvironment* ccdPhysEnv = new CcdPhysicsEnvironment(useDbvtCulling);
@@ -355,7 +383,8 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
rendertools,
canvas,
this,
- m_alwaysUseExpandFraming
+ m_alwaysUseExpandFraming,
+ libloading
);
//These lookup are not needed during game
@@ -369,7 +398,7 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
//that would result from this is fixed in RemoveScene()
m_map_mesh_to_gamemesh.clear();
-#ifndef USE_BULLET
+#ifndef WITH_BULLET
/* quiet compiler warning */
(void)useDbvtCulling;
#endif
@@ -406,6 +435,7 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene)
size = m_polymaterials.size();
for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
if ((*polymit).first == scene) {
+ m_polymat_cache.erase((*polymit).second->GetBlenderMaterial());
delete (*polymit).second;
*polymit = m_polymaterials.back();
m_polymaterials.pop_back();
@@ -420,6 +450,7 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene)
size = m_materials.size();
for (i=0, matit=m_materials.begin(); i<size; ) {
if ((*matit).first == scene) {
+ m_mat_cache.erase((*matit).second->material);
delete (*matit).second;
*matit = m_materials.back();
m_materials.pop_back();
@@ -458,6 +489,11 @@ void KX_BlenderSceneConverter::SetGLSLMaterials(bool val)
m_useglslmat = val;
}
+void KX_BlenderSceneConverter::SetCacheMaterials(bool val)
+{
+ m_use_mat_cache = val;
+}
+
bool KX_BlenderSceneConverter::GetMaterials()
{
return m_usemat;
@@ -468,8 +504,19 @@ bool KX_BlenderSceneConverter::GetGLSLMaterials()
return m_useglslmat;
}
+bool KX_BlenderSceneConverter::GetCacheMaterials()
+{
+ return m_use_mat_cache;
+}
+
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;
+ 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));
}
@@ -540,19 +587,39 @@ RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh(
} 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;
+ 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));
}
+void KX_BlenderSceneConverter::CachePolyMaterial(struct Material *mat, RAS_IPolyMaterial *polymat)
+{
+ if (m_use_mat_cache)
+ m_polymat_cache[mat] = polymat;
+}
+
+RAS_IPolyMaterial *KX_BlenderSceneConverter::FindCachedPolyMaterial(struct Material *mat)
+{
+ return (m_use_mat_cache) ? m_polymat_cache[mat] : NULL;
+}
+void KX_BlenderSceneConverter::CacheBlenderMaterial(struct Material *mat, BL_Material *blmat)
+{
+ if (m_use_mat_cache)
+ m_mat_cache[mat] = blmat;
+}
+
+BL_Material *KX_BlenderSceneConverter::FindCachedBlenderMaterial(struct Material *mat)
+{
+ return (m_use_mat_cache) ? m_mat_cache[mat] : NULL;
+}
void KX_BlenderSceneConverter::RegisterInterpolatorList(
BL_InterpolatorList *actList,
@@ -915,7 +982,67 @@ Main* KX_BlenderSceneConverter::GetMainDynamicPath(const char *path)
return NULL;
}
-bool KX_BlenderSceneConverter::LinkBlendFileMemory(void *data, int length, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options)
+void KX_BlenderSceneConverter::MergeAsyncLoads()
+{
+ vector<KX_Scene*> *merge_scenes;
+
+ 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 (sit=merge_scenes->begin(); sit!=merge_scenes->end(); ++sit) {
+ (*mit)->GetMergeScene()->MergeScene(*sit);
+ delete (*sit);
+ }
+
+
+ delete merge_scenes;
+ (*mit)->SetData(NULL);
+
+ (*mit)->Finish();
+ }
+
+ m_mergequeue.clear();
+
+ pthread_mutex_unlock(&m_threadinfo->merge_lock);
+}
+
+void KX_BlenderSceneConverter::AddScenesToMergeQueue(KX_LibLoadStatus *status)
+{
+ pthread_mutex_lock(&m_threadinfo->merge_lock);
+ m_mergequeue.push_back(status);
+ pthread_mutex_unlock(&m_threadinfo->merge_lock);
+}
+
+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
+
+ 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
+ }
+
+ delete scenes;
+ status->SetData(merge_scenes);
+
+ status->GetConverter()->AddScenesToMergeQueue(status);
+
+ return NULL;
+}
+
+KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFileMemory(void *data, int length, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options)
{
BlendHandle *bpy_openlib = BLO_blendhandle_from_memory(data, length);
@@ -923,12 +1050,12 @@ bool KX_BlenderSceneConverter::LinkBlendFileMemory(void *data, int length, const
return LinkBlendFile(bpy_openlib, path, group, scene_merge, err_str, options);
}
-bool KX_BlenderSceneConverter::LinkBlendFilePath(const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options)
+KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFilePath(const char *filepath, char *group, KX_Scene *scene_merge, char **err_str, short options)
{
- BlendHandle *bpy_openlib = BLO_blendhandle_from_file((char *)path, NULL);
+ BlendHandle *bpy_openlib = BLO_blendhandle_from_file(filepath, NULL);
// Error checking is done in LinkBlendFile
- return LinkBlendFile(bpy_openlib, path, group, scene_merge, err_str, options);
+ 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)
@@ -955,7 +1082,7 @@ static void load_datablocks(Main *main_newlib, BlendHandle *bpy_openlib, const c
BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag);
}
-bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options)
+KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options)
{
Main *main_newlib; /* stored as a dynamic 'main' until we free it */
const int idcode = BKE_idcode_from_name(group);
@@ -964,25 +1091,27 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha
// 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) {
snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group);
*err_str= err_local;
BLO_blendhandle_close(bpy_openlib);
- return false;
+ return NULL;
}
if (GetMainDynamicPath(path)) {
snprintf(err_local, sizeof(err_local), "blend file already open \"%s\"\n", path);
*err_str= err_local;
BLO_blendhandle_close(bpy_openlib);
- return false;
+ return NULL;
}
if (bpy_openlib==NULL) {
snprintf(err_local, sizeof(err_local), "could not open blendfile \"%s\"\n", path);
*err_str= err_local;
- return false;
+ return NULL;
}
main_newlib= (Main *)MEM_callocN( sizeof(Main), "BgeMain");
@@ -1009,6 +1138,8 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha
strncpy(main_newlib->name, path, sizeof(main_newlib->name));
+ status = new KX_LibLoadStatus(this, m_ketsjiEngine, scene_merge, path);
+
if (idcode==ID_ME) {
/* Convert all new meshes into BGE meshes */
ID* mesh;
@@ -1016,7 +1147,7 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha
for (mesh= (ID *)main_newlib->mesh.first; mesh; mesh= (ID *)mesh->next ) {
if (options & LIB_LOAD_VERBOSE)
printf("MeshName: %s\n", mesh->name+2);
- RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this);
+ 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);
}
}
@@ -1033,16 +1164,30 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha
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;
+
for (scene= (ID *)main_newlib->scene.first; scene; scene= (ID *)scene->next ) {
if (options & LIB_LOAD_VERBOSE)
printf("SceneName: %s\n", scene->name+2);
- /* merge into the base scene */
- KX_Scene* other= m_ketsjiEngine->CreateScene((Scene *)scene);
- scene_merge->MergeScene(other);
+ if (options & LIB_LOAD_ASYNC) {
+ scenes->push_back((Scene*)scene);
+ } else {
+ /* merge into the base scene */
+ 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
- delete other;
+ // RemoveScene(other); // Don't run this, it frees the entire scene converter data, just delete the scene
+ delete other;
+ }
+ }
+
+ if (options & LIB_LOAD_ASYNC) {
+ pthread_t id;
+ status->SetData(scenes);
+ pthread_create(&id, NULL, &async_convert, (void*)status);
+ m_threadinfo->threads.push_back(id);
}
#ifdef WITH_PYTHON
@@ -1063,9 +1208,14 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha
}
}
+ if (!(options & LIB_LOAD_ASYNC))
+ status->Finish();
+
+
// TIMEIT_END(bge_link_blend_file);
- return true;
+ m_status_map[main_newlib->name] = status;
+ return status;
}
/* Note m_map_*** are all ok and don't need to be freed
@@ -1302,7 +1452,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
}
if (IS_TAGGED(bmat)) {
-
+ m_polymat_cache.erase((*polymit).second->GetBlenderMaterial());
delete (*polymit).second;
*polymit = m_polymaterials.back();
m_polymaterials.pop_back();
@@ -1320,6 +1470,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
for (i=0, matit=m_materials.begin(); i<size; ) {
BL_Material *mat= (*matit).second;
if (IS_TAGGED(mat->material)) {
+ m_mat_cache.erase((*matit).second->material);
delete (*matit).second;
*matit = m_materials.back();
m_materials.pop_back();
@@ -1351,6 +1502,9 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
removeImportMain(maggie);
#endif
+ delete m_status_map[maggie->name];
+ m_status_map.erase(maggie->name);
+
free_main(maggie);
return true;
@@ -1469,7 +1623,7 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene,
}
}
- RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)me, NULL, kx_scene, this);
+ RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)me, NULL, kx_scene, this, false);
kx_scene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj);
m_map_mesh_to_gamemesh.clear(); /* This is at runtime so no need to keep this, BL_ConvertMesh adds */
return meshobj;
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.h b/source/gameengine/Converter/KX_BlenderSceneConverter.h
index 34a1117a0eb..06dac1707c5 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.h
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.h
@@ -39,6 +39,8 @@
#include "KX_ISceneConverter.h"
#include "KX_IpoConvert.h"
+#include <map>
+
using namespace std;
class KX_WorldInfo;
@@ -50,6 +52,7 @@ class BL_InterpolatorList;
class BL_Material;
struct Main;
struct Scene;
+struct ThreadInfo;
class KX_BlenderSceneConverter : public KX_ISceneConverter
{
@@ -58,6 +61,17 @@ class KX_BlenderSceneConverter : public KX_ISceneConverter
vector<pair<KX_Scene*,RAS_IPolyMaterial*> > m_polymaterials;
vector<pair<KX_Scene*,RAS_MeshObject*> > m_meshobjects;
vector<pair<KX_Scene*,BL_Material *> > m_materials;
+
+ vector<class KX_LibLoadStatus*> m_mergequeue;
+ ThreadInfo *m_threadinfo;
+
+ // Cached material conversions
+ map<struct Material*, BL_Material*> m_mat_cache;
+ map<struct Material*, RAS_IPolyMaterial*> m_polymat_cache;
+
+ // Saved KX_LibLoadStatus objects
+ map<char *, class KX_LibLoadStatus*> m_status_map;
+
// Should also have a list of collision shapes.
// For the time being this is held in KX_Scene::m_shapes
@@ -77,6 +91,7 @@ class KX_BlenderSceneConverter : public KX_ISceneConverter
bool m_alwaysUseExpandFraming;
bool m_usemat;
bool m_useglslmat;
+ bool m_use_mat_cache;
public:
KX_BlenderSceneConverter(
@@ -93,7 +108,8 @@ public:
virtual void ConvertScene(
class KX_Scene* destinationscene,
class RAS_IRenderTools* rendertools,
- class RAS_ICanvas* canvas
+ class RAS_ICanvas* canvas,
+ bool libloading=false
);
virtual void RemoveScene(class KX_Scene *scene);
@@ -110,8 +126,12 @@ public:
RAS_MeshObject *FindGameMesh(struct Mesh *for_blendermesh/*, unsigned int onlayer*/);
void RegisterPolyMaterial(RAS_IPolyMaterial *polymat);
+ void CachePolyMaterial(struct Material *mat, RAS_IPolyMaterial *polymat);
+ RAS_IPolyMaterial *FindCachedPolyMaterial(struct Material *mat);
void RegisterBlenderMaterial(BL_Material *mat);
+ void CacheBlenderMaterial(struct Material *mat, BL_Material *blmat);
+ BL_Material *FindCachedBlenderMaterial(struct Material *mat);
void RegisterInterpolatorList(BL_InterpolatorList *actList, struct bAction *for_act);
BL_InterpolatorList *FindInterpolatorList(struct bAction *for_act);
@@ -141,19 +161,26 @@ public:
virtual void SetGLSLMaterials(bool val);
virtual bool GetGLSLMaterials();
+ // cache materials during conversion
+ virtual void SetCacheMaterials(bool val);
+ virtual bool GetCacheMaterials();
+
struct Scene* GetBlenderSceneForName(const STR_String& name);
// struct Main* GetMain() { return m_maggie; }
struct Main* GetMainDynamicPath(const char *path);
vector<struct Main*> &GetMainDynamic();
- bool LinkBlendFileMemory(void *data, int length, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options);
- bool LinkBlendFilePath(const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options);
- bool LinkBlendFile(struct BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options);
+ class KX_LibLoadStatus *LinkBlendFileMemory(void *data, int length, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options);
+ class KX_LibLoadStatus *LinkBlendFilePath(const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options);
+ class KX_LibLoadStatus *LinkBlendFile(struct BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options);
bool MergeScene(KX_Scene *to, KX_Scene *from);
RAS_MeshObject *ConvertMeshSpecial(KX_Scene* kx_scene, Main *maggie, const char *name);
bool FreeBlendFile(struct Main *maggie);
bool FreeBlendFile(const char *path);
+
+ virtual void MergeAsyncLoads();
+ void AddScenesToMergeQueue(class KX_LibLoadStatus *status);
void PrintStats() {
printf("BGE STATS!\n");
@@ -183,6 +210,7 @@ public:
LIB_LOAD_LOAD_ACTIONS = 1,
LIB_LOAD_VERBOSE = 2,
LIB_LOAD_LOAD_SCRIPTS = 4,
+ LIB_LOAD_ASYNC = 8,
};
diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp
index 06399642edd..05da38dd1af 100644
--- a/source/gameengine/Converter/KX_ConvertActuators.cpp
+++ b/source/gameengine/Converter/KX_ConvertActuators.cpp
@@ -180,7 +180,10 @@ void BL_ConvertActuators(const char* maggiename,
bitLocalFlag.LinearVelocity = bool((obact->flag & ACT_LIN_VEL_LOCAL)!=0);
bitLocalFlag.AngularVelocity = bool((obact->flag & ACT_ANG_VEL_LOCAL)!=0);
bitLocalFlag.ServoControl = bool(obact->type == ACT_OBJECT_SERVO);
+ bitLocalFlag.CharacterMotion = bool(obact->type == ACT_OBJECT_CHARACTER);
+ bitLocalFlag.CharacterJump = bool((obact->flag & ACT_CHAR_JUMP)!=0);
bitLocalFlag.AddOrSetLinV = bool((obact->flag & ACT_ADD_LIN_VEL)!=0);
+ bitLocalFlag.AddOrSetCharLoc = bool((obact->flag & ACT_ADD_CHAR_LOC)!=0);
if (obact->reference && bitLocalFlag.ServoControl)
{
obref = converter->FindGameObject(obact->reference);
@@ -523,7 +526,8 @@ void BL_ConvertActuators(const char* maggiename,
editobact->me,
blenderobject,
scene,
- converter
+ converter,
+ false
);
KX_SCA_ReplaceMeshActuator* tmpreplaceact = new KX_SCA_ReplaceMeshActuator(
diff --git a/source/gameengine/Converter/KX_ConvertControllers.cpp b/source/gameengine/Converter/KX_ConvertControllers.cpp
index 769abd01ce0..5d3d0f33bec 100644
--- a/source/gameengine/Converter/KX_ConvertControllers.cpp
+++ b/source/gameengine/Converter/KX_ConvertControllers.cpp
@@ -157,7 +157,7 @@ void BL_ConvertControllers(
SCA_PythonController* pyctrl = new SCA_PythonController(gameobj, pycont->mode);
gamecontroller = pyctrl;
#ifdef WITH_PYTHON
-
+ PyGILState_STATE gstate = PyGILState_Ensure();
pyctrl->SetNamespace(converter->GetPyNamespace());
if (pycont->mode==SCA_PythonController::SCA_PYEXEC_SCRIPT) {
@@ -186,6 +186,7 @@ void BL_ConvertControllers(
}
}
+ PyGILState_Release(gstate);
#endif // WITH_PYTHON
break;
@@ -218,6 +219,7 @@ void BL_ConvertControllers(
converter->RegisterGameController(gamecontroller, bcontr);
#ifdef WITH_PYTHON
+ PyGILState_STATE gstate = PyGILState_Ensure();
if (bcontr->type==CONT_PYTHON) {
SCA_PythonController *pyctrl= static_cast<SCA_PythonController*>(gamecontroller);
/* not strictly needed but gives syntax errors early on and
@@ -232,6 +234,8 @@ void BL_ConvertControllers(
// pyctrl->Import();
}
}
+
+ PyGILState_Release(gstate);
#endif // WITH_PYTHON
//done with gamecontroller
diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp
index 538f9e2c833..acaf911c26e 100644
--- a/source/gameengine/Converter/KX_ConvertSensors.cpp
+++ b/source/gameengine/Converter/KX_ConvertSensors.cpp
@@ -260,14 +260,9 @@ void BL_ConvertSensors(struct Object* blenderobject,
// this sumoObject is not deleted by a gameobj, so delete it ourself
// later (memleaks)!
float radius = blendernearsensor->dist;
- PHY__Vector3 pos;
const MT_Vector3& wpos = gameobj->NodeGetWorldPosition();
- pos[0] = (float)wpos[0];
- pos[1] = (float)wpos[1];
- pos[2] = (float)wpos[2];
- pos[3] = 0.f;
bool bFindMaterial = false;
- PHY_IPhysicsController* physCtrl = kxscene->GetPhysicsEnvironment()->CreateSphereController(radius,pos);
+ PHY_IPhysicsController* physCtrl = kxscene->GetPhysicsEnvironment()->CreateSphereController(radius,wpos);
//will be done in KX_TouchEventManager::RegisterSensor()
//if (isInActiveLayer)
diff --git a/source/gameengine/Converter/KX_LibLoadStatus.cpp b/source/gameengine/Converter/KX_LibLoadStatus.cpp
new file mode 100644
index 00000000000..2a38e062f89
--- /dev/null
+++ b/source/gameengine/Converter/KX_LibLoadStatus.cpp
@@ -0,0 +1,252 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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): Mitchell Stokes
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file KX_LibLoadStatus.cpp
+ * \ingroup bgeconv
+ */
+
+#include "KX_LibLoadStatus.h"
+#include "PIL_time.h"
+
+KX_LibLoadStatus::KX_LibLoadStatus(class KX_BlenderSceneConverter* kx_converter,
+ class KX_KetsjiEngine* kx_engine,
+ class KX_Scene* merge_scene,
+ const char *path) :
+ m_converter(kx_converter),
+ m_engine(kx_engine),
+ m_mergescene(merge_scene),
+ m_data(NULL),
+ m_libname(path),
+ m_progress(0.f)
+#ifdef WITH_PYTHON
+ ,
+ m_finish_cb(NULL),
+ m_progress_cb(NULL)
+#endif
+{
+ m_endtime = m_starttime = PIL_check_seconds_timer();
+}
+
+void KX_LibLoadStatus::Finish()
+{
+ m_progress = 1.f;
+ m_endtime = PIL_check_seconds_timer();
+
+ RunFinishCallback();
+ RunProgressCallback();
+}
+
+void KX_LibLoadStatus::RunFinishCallback()
+{
+#ifdef WITH_PYTHON
+ if (m_finish_cb) {
+ PyObject* args = Py_BuildValue("(O)", GetProxy());
+
+ if (!PyObject_Call(m_finish_cb, args, NULL)) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ Py_DECREF(args);
+ }
+#endif
+}
+
+void KX_LibLoadStatus::RunProgressCallback()
+{
+// Progess callbacks are causing threading problems with Python, so they're disabled for now
+#if 0
+#ifdef WITH_PYTHON
+ if (m_progress_cb) {
+ //PyGILState_STATE gstate = PyGILState_Ensure();
+ PyObject* args = Py_BuildValue("(O)", GetProxy());
+
+ if (!PyObject_Call(m_progress_cb, args, NULL)) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ Py_DECREF(args);
+ //PyGILState_Release(gstate);
+ }
+#endif
+#endif
+}
+
+class KX_BlenderSceneConverter *KX_LibLoadStatus::GetConverter()
+{
+ return m_converter;
+}
+
+class KX_KetsjiEngine *KX_LibLoadStatus::GetEngine()
+{
+ return m_engine;
+}
+
+class KX_Scene *KX_LibLoadStatus::GetMergeScene()
+{
+ return m_mergescene;
+}
+
+void KX_LibLoadStatus::SetLibName(const char *name)
+{
+ m_libname = name;
+}
+
+const char *KX_LibLoadStatus::GetLibName()
+{
+ return m_libname;
+}
+
+void KX_LibLoadStatus::SetData(void *data)
+{
+ m_data = data;
+}
+
+void *KX_LibLoadStatus::GetData()
+{
+ return m_data;
+}
+
+void KX_LibLoadStatus::SetProgress(float progress)
+{
+ m_progress = progress;
+ RunProgressCallback();
+}
+
+float KX_LibLoadStatus::GetProgress()
+{
+ return m_progress;
+}
+
+void KX_LibLoadStatus::AddProgress(float progress)
+{
+ m_progress += progress;
+ RunProgressCallback();
+}
+
+#ifdef WITH_PYTHON
+
+PyMethodDef KX_LibLoadStatus::Methods[] =
+{
+ {NULL} //Sentinel
+};
+
+PyAttributeDef KX_LibLoadStatus::Attributes[] = {
+ KX_PYATTRIBUTE_RW_FUNCTION("onFinish", KX_LibLoadStatus, pyattr_get_onfinish, pyattr_set_onfinish),
+ // KX_PYATTRIBUTE_RW_FUNCTION("onProgress", KX_LibLoadStatus, pyattr_get_onprogress, pyattr_set_onprogress),
+ KX_PYATTRIBUTE_FLOAT_RO("progress", KX_LibLoadStatus, m_progress),
+ KX_PYATTRIBUTE_STRING_RO("libraryName", KX_LibLoadStatus, m_libname),
+ KX_PYATTRIBUTE_RO_FUNCTION("timeTaken", KX_LibLoadStatus, pyattr_get_timetaken),
+ { NULL } //Sentinel
+};
+
+PyTypeObject KX_LibLoadStatus::Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "KX_LibLoadStatus",
+ 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
+};
+
+
+PyObject* KX_LibLoadStatus::pyattr_get_onfinish(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_LibLoadStatus* self = static_cast<KX_LibLoadStatus*>(self_v);
+
+ if (self->m_finish_cb) {
+ Py_INCREF(self->m_finish_cb);
+ return self->m_finish_cb;
+ }
+
+ Py_RETURN_NONE;
+}
+
+int KX_LibLoadStatus::pyattr_set_onfinish(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_LibLoadStatus* self = static_cast<KX_LibLoadStatus*>(self_v);
+
+ if (!PyCallable_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "KX_LibLoadStatus.onFinished requires a callable object");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ if (self->m_finish_cb)
+ Py_DECREF(self->m_finish_cb);
+
+ Py_INCREF(value);
+ self->m_finish_cb = value;
+
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject* KX_LibLoadStatus::pyattr_get_onprogress(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_LibLoadStatus* self = static_cast<KX_LibLoadStatus*>(self_v);
+
+ if (self->m_progress_cb) {
+ Py_INCREF(self->m_progress_cb);
+ return self->m_progress_cb;
+ }
+
+ Py_RETURN_NONE;
+}
+
+int KX_LibLoadStatus::pyattr_set_onprogress(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_LibLoadStatus* self = static_cast<KX_LibLoadStatus*>(self_v);
+
+ if (!PyCallable_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "KX_LibLoadStatus.onProgress requires a callable object");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ if (self->m_progress_cb)
+ Py_DECREF(self->m_progress_cb);
+
+ Py_INCREF(value);
+ self->m_progress_cb = value;
+
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject* KX_LibLoadStatus::pyattr_get_timetaken(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_LibLoadStatus* self = static_cast<KX_LibLoadStatus*>(self_v);
+
+ return PyFloat_FromDouble(self->m_endtime - self->m_starttime);
+}
+#endif // WITH_PYTHON
diff --git a/source/gameengine/Converter/KX_LibLoadStatus.h b/source/gameengine/Converter/KX_LibLoadStatus.h
new file mode 100644
index 00000000000..3da7329213b
--- /dev/null
+++ b/source/gameengine/Converter/KX_LibLoadStatus.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.
+ *
+ * Contributor(s): Mitchell Stokes
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file KX_LibLoadStatus.h
+ * \ingroup bgeconv
+ */
+
+#ifndef __KX_LIBLOADSTATUS_H__
+#define __KX_LIBLOADSTATUS_H__
+
+#include "PyObjectPlus.h"
+
+class KX_LibLoadStatus : public PyObjectPlus
+{
+ Py_Header
+private:
+ class KX_BlenderSceneConverter* m_converter;
+ class KX_KetsjiEngine* m_engine;
+ class KX_Scene* m_mergescene;
+ void* m_data;
+ STR_String m_libname;
+
+ float m_progress;
+ double m_starttime;
+ double m_endtime;
+
+#ifdef WITH_PYTHON
+ PyObject* m_finish_cb;
+ PyObject* m_progress_cb;
+#endif
+
+public:
+ KX_LibLoadStatus(class KX_BlenderSceneConverter* kx_converter,
+ class KX_KetsjiEngine* kx_engine,
+ class KX_Scene* merge_scene,
+ const char *path);
+
+ void Finish(); // Called when the libload is done
+ void RunFinishCallback();
+ void RunProgressCallback();
+
+ class KX_BlenderSceneConverter *GetConverter();
+ class KX_KetsjiEngine *GetEngine();
+ class KX_Scene *GetMergeScene();
+
+ void SetLibName(const char *name);
+ const char *GetLibName();
+
+ void SetData(void *data);
+ void *GetData();
+
+ void SetProgress(float progress);
+ float GetProgress();
+ void AddProgress(float progress);
+
+#ifdef WITH_PYTHON
+ static PyObject* pyattr_get_onfinish(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_onfinish(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_onprogress(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_onprogress(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+
+ static PyObject* pyattr_get_timetaken(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+#endif
+};
+
+#endif // __KX_LIBLOADSTATUS_H__
diff --git a/source/gameengine/Converter/KX_SoftBodyDeformer.cpp b/source/gameengine/Converter/KX_SoftBodyDeformer.cpp
index 72d0c8733f2..d860b2ee694 100644
--- a/source/gameengine/Converter/KX_SoftBodyDeformer.cpp
+++ b/source/gameengine/Converter/KX_SoftBodyDeformer.cpp
@@ -42,7 +42,7 @@
#include "CTR_Map.h"
#include "CTR_HashedPtr.h"
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
#include "CcdPhysicsEnvironment.h"
#include "CcdPhysicsController.h"
diff --git a/source/gameengine/Converter/SConscript b/source/gameengine/Converter/SConscript
index b9c70910283..ef546ce1b19 100644
--- a/source/gameengine/Converter/SConscript
+++ b/source/gameengine/Converter/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.cpp')
@@ -38,7 +64,7 @@ if env['WITH_BF_CXX_GUARDEDALLOC']:
defs.append('WITH_CXX_GUARDEDALLOC')
if env['WITH_BF_BULLET']:
- defs.append('USE_BULLET')
+ defs.append('WITH_BULLET')
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
diff --git a/source/gameengine/Expressions/EmptyValue.cpp b/source/gameengine/Expressions/EmptyValue.cpp
index 2bb8f69ac51..8170c588a28 100644
--- a/source/gameengine/Expressions/EmptyValue.cpp
+++ b/source/gameengine/Expressions/EmptyValue.cpp
@@ -30,9 +30,9 @@
CEmptyValue::CEmptyValue()
/*
-pre:
-effect: constructs a new CEmptyValue
-*/
+ * pre:
+ * effect: constructs a new CEmptyValue
+ */
{
SetModified(false);
}
@@ -41,9 +41,9 @@ effect: constructs a new CEmptyValue
CEmptyValue::~CEmptyValue()
/*
-pre:
-effect: deletes the object
-*/
+ * pre:
+ * effect: deletes the object
+ */
{
}
@@ -52,10 +52,10 @@ effect: deletes the object
CValue * CEmptyValue::Calc(VALUE_OPERATOR op, CValue * val)
/*
-pre:
-ret: a new object containing the result of applying operator op to this
-object and val
-*/
+ * pre:
+ * ret: a new object containing the result of applying operator op to this
+ * object and val
+ */
{
return val->CalcFinal(VALUE_EMPTY_TYPE, op, this);
@@ -65,10 +65,10 @@ object and val
CValue * CEmptyValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue * val)
/*
-pre: the type of val is dtype
-ret: a new object containing the result of applying operator op to val and
-this object
-*/
+ * pre: the type of val is dtype
+ * ret: a new object containing the result of applying operator op to val and
+ * this object
+ */
{
return val->AddRef();
}
diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/InputParser.cpp
index 0a5af4a18ea..ed89fb13337 100644
--- a/source/gameengine/Expressions/InputParser.cpp
+++ b/source/gameengine/Expressions/InputParser.cpp
@@ -260,7 +260,8 @@ void CParser::NextSym()
opkind = OPless;
}
break;
- case '\"' : {
+ case '\"' :
+ {
int start;
sym = constsym;
constkind = stringtype;
@@ -354,7 +355,7 @@ int CParser::MakeInt()
}
#endif
-STR_String CParser::Symbol2Str(int s)
+const char *CParser::Symbol2Str(int s)
{
// returns a string representation of of symbol s,
// for use in Term when generating an error
@@ -370,18 +371,20 @@ STR_String CParser::Symbol2Str(int s)
case whocodedsym: return "WHOMADE";
case eolsym: return "end of line";
case idsym: return "identifier";
- default: return "unknown"; // should not happen
}
+ return "unknown"; // should not happen
}
void CParser::Term(int s)
{
// generates an error if the next symbol isn't the specified symbol s
// otherwise, skip the symbol
- if (s == sym) NextSym();
+ if (s == sym) {
+ NextSym();
+ }
else {
STR_String msg;
- msg.Format("Warning: " + Symbol2Str(s) + " expected\ncontinuing without it");
+ msg.Format("Warning: %s expected\ncontinuing without it", Symbol2Str(s));
// AfxMessageBox(msg,MB_ICONERROR);
@@ -462,7 +465,8 @@ CExpression *CParser::Ex(int i)
}
else {
switch (sym) {
- case constsym: {
+ case constsym:
+ {
switch (constkind) {
case booltype:
e1 = new CConstExpr(new CBoolValue(boolvalue));
diff --git a/source/gameengine/Expressions/InputParser.h b/source/gameengine/Expressions/InputParser.h
index 6dfeff55105..50bb1ae2f6e 100644
--- a/source/gameengine/Expressions/InputParser.h
+++ b/source/gameengine/Expressions/InputParser.h
@@ -102,7 +102,7 @@ private:
#if 0 /* not used yet */
int MakeInt();
#endif
- STR_String Symbol2Str(int s);
+ const char *Symbol2Str(int s);
void Term(int s);
int Priority(int optor);
CExpression *Ex(int i);
diff --git a/source/gameengine/Expressions/Operator2Expr.cpp b/source/gameengine/Expressions/Operator2Expr.cpp
index d0240b5ec75..b03d00e7f77 100644
--- a/source/gameengine/Expressions/Operator2Expr.cpp
+++ b/source/gameengine/Expressions/Operator2Expr.cpp
@@ -113,61 +113,61 @@ and m_rhs
}
-/*
+#if 0
bool COperator2Expr::IsInside(float x, float y, float z,bool bBorderInclude)
{
bool inside;
inside = false;
- switch (m_op)
- {
- case VALUE_ADD_OPERATOR: {
- // inside = first || second; // optimized with early out if first is inside
- // todo: calculate smallest leaf first ! is much faster...
-
- bool second;//first ;//,second;
-
- //first = m_lhs->IsInside(x,y,z);
- second = m_rhs->IsInside(x,y,z,bBorderInclude);
- if (second)
- return true; //early out
-
- // second = m_rhs->IsInside(x,y,z);
+ switch (m_op) {
+ case VALUE_ADD_OPERATOR:
+ {
+ // inside = first || second; // optimized with early out if first is inside
+ // todo: calculate smallest leaf first ! is much faster...
- return m_lhs->IsInside(x,y,z,bBorderInclude);
-
- break;
- }
-
- case VALUE_SUB_OPERATOR: {
- //inside = first && !second; // optimized with early out
- // todo: same as with add_operator: calc smallest leaf first
+ bool second;//first ;//,second;
- bool second;//first ;//,second;
- //first = m_lhs->IsInside(x,y,z);
- second = m_rhs->IsInside(x,y,z,bBorderInclude);
- if (second)
- return false;
+ //first = m_lhs->IsInside(x,y,z);
+ second = m_rhs->IsInside(x,y,z,bBorderInclude);
+ if (second)
+ return true; //early out
- // second space get subtracted -> negate!
- //second = m_rhs->IsInside(x,y,z);
+ // second = m_rhs->IsInside(x,y,z);
- return (m_lhs->IsInside(x,y,z,bBorderInclude));
+ return m_lhs->IsInside(x,y,z,bBorderInclude);
-
- break;
- }
- default:{
- assert(false);
- // not yet implemented, only add or sub csg operations
- }
+ break;
+ }
+
+ case VALUE_SUB_OPERATOR:
+ {
+ //inside = first && !second; // optimized with early out
+ // todo: same as with add_operator: calc smallest leaf first
+
+ bool second;//first ;//,second;
+ //first = m_lhs->IsInside(x,y,z);
+ second = m_rhs->IsInside(x,y,z,bBorderInclude);
+ if (second)
+ return false;
+
+ // second space get subtracted -> negate!
+ //second = m_rhs->IsInside(x,y,z);
+
+ return (m_lhs->IsInside(x,y,z,bBorderInclude));
+
+
+ break;
+ }
+ default:
+ {
+ assert(false);
+ // not yet implemented, only add or sub csg operations
+ }
}
return inside;
}
-
-
bool COperator2Expr::IsRightInside(float x, float y, float z,bool bBorderInclude)
{
return m_rhs->IsInside(x,y,z,bBorderInclude);
@@ -177,7 +177,8 @@ bool COperator2Expr::IsLeftInside(float x, float y, float z,bool bBorderInclude)
{
return m_lhs->IsInside(x,y,z,bBorderInclude);
}
-*/
+#endif
+
bool COperator2Expr::NeedsRecalculated()
{
// added some lines, just for debugging purposes, it could be a one-liner :)
diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp
index 11b00b7bbf5..52ad95c71b6 100644
--- a/source/gameengine/Expressions/PyObjectPlus.cpp
+++ b/source/gameengine/Expressions/PyObjectPlus.cpp
@@ -43,7 +43,7 @@
* Center for the Neural Basis of Cognition (CNBC)
* http://www.python.org/doc/PyCPP.html
*
-------------------------------*/
+ * ----------------------------- */
#include <stdlib.h>
#include <stddef.h>
@@ -103,7 +103,7 @@ void PyObjectPlus::InvalidateProxy() // check typename of each parent
/*------------------------------
* PyObjectPlus Type -- Every class, even the abstract one should have a Type
-------------------------------*/
+ * ----------------------------- */
PyTypeObject PyObjectPlus::Type = {
@@ -118,16 +118,16 @@ PyTypeObject PyObjectPlus::Type = {
0, /* setattrfunc tp_setattr; */
0, /* tp_compare */ /* DEPRECATED in python 3.0! */
py_base_repr, /* tp_repr */
- 0,0,0,0,0,0,0,0,0, /* Method suites for standard classes */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,/* long tp_flags; */
- 0,0,0,0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Method suites for standard classes */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */
+ 0, 0, 0, 0,
/* weak reference enabler */
#ifdef USE_WEAKREFS
offsetof(PyObjectPlus_Proxy, in_weakreflist), /* long tp_weaklistoffset; */
#else
0,
#endif
- 0,0,
+ 0, 0,
Methods,
0,
0,
@@ -217,8 +217,8 @@ PyObject *PyObjectPlus::py_base_new(PyTypeObject *type, PyObject *args, PyObject
}
/**
- * \param self A PyObjectPlus_Proxy
- */
+ * \param self A PyObjectPlus_Proxy
+ */
void PyObjectPlus::py_base_dealloc(PyObject *self) // python wrapper
{
#ifdef USE_WEAKREFS
@@ -311,14 +311,14 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
{
bool *val = reinterpret_cast<bool*>(ptr);
ptr += sizeof(bool);
- PyList_SET_ITEM(resultlist,i,PyBool_FromLong(*val));
+ PyList_SET_ITEM(resultlist, i, PyBool_FromLong(*val));
break;
}
case KX_PYATTRIBUTE_TYPE_SHORT:
{
short int *val = reinterpret_cast<short int*>(ptr);
ptr += sizeof(short int);
- PyList_SET_ITEM(resultlist,i,PyLong_FromLong(*val));
+ PyList_SET_ITEM(resultlist, i, PyLong_FromLong(*val));
break;
}
case KX_PYATTRIBUTE_TYPE_ENUM:
@@ -333,14 +333,14 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
{
int *val = reinterpret_cast<int*>(ptr);
ptr += sizeof(int);
- PyList_SET_ITEM(resultlist,i,PyLong_FromLong(*val));
+ PyList_SET_ITEM(resultlist, i, PyLong_FromLong(*val));
break;
}
case KX_PYATTRIBUTE_TYPE_FLOAT:
{
float *val = reinterpret_cast<float*>(ptr);
ptr += sizeof(float);
- PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble(*val));
+ PyList_SET_ITEM(resultlist, i, PyFloat_FromDouble(*val));
break;
}
default:
@@ -423,7 +423,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
PyObject *resultlist = PyList_New(attrdef->m_imax);
for (unsigned int i=0; i<attrdef->m_imax; i++)
{
- PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble(val[i]));
+ PyList_SET_ITEM(resultlist, i, PyFloat_FromDouble(val[i]));
}
return resultlist;
#endif
@@ -443,9 +443,9 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
PyObject *col = PyList_New(attrdef->m_imax);
for (unsigned int j=0; j<attrdef->m_imax; j++)
{
- PyList_SET_ITEM(col,j,PyFloat_FromDouble(val[j]));
+ PyList_SET_ITEM(col, j, PyFloat_FromDouble(val[j]));
}
- PyList_SET_ITEM(collist,i,col);
+ PyList_SET_ITEM(collist, i, col);
val += attrdef->m_imax;
}
return collist;
@@ -463,7 +463,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
PyObject *resultlist = PyList_New(3);
for (unsigned int i=0; i<3; i++)
{
- PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble((*val)[i]));
+ PyList_SET_ITEM(resultlist, i, PyFloat_FromDouble((*val)[i]));
}
return resultlist;
#endif
@@ -1110,7 +1110,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt
------------------------------*/
PyObject *PyObjectPlus::py_repr(void)
{
- PyErr_SetString(PyExc_SystemError, "Representation not overridden by object.");
+ PyErr_SetString(PyExc_SystemError, "Representation not overridden by object.");
return NULL;
}
@@ -1187,7 +1187,7 @@ void PyObjectPlus::SetDeprecationWarnings(bool ignoreDeprecationWarnings)
m_ignore_deprecation_warnings = ignoreDeprecationWarnings;
}
-void PyObjectPlus::ShowDeprecationWarning_func(const char* old_way,const char* new_way)
+void PyObjectPlus::ShowDeprecationWarning_func(const char *old_way, const char *new_way)
{
printf("Method %s is deprecated, please use %s instead.\n", old_way, new_way);
PyC_LineSpit();
diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h
index 37e26e88750..e2e7c248795 100644
--- a/source/gameengine/Expressions/PyObjectPlus.h
+++ b/source/gameengine/Expressions/PyObjectPlus.h
@@ -389,139 +389,139 @@ typedef struct KX_PYATTRIBUTE_DEF {
} m_typeCheck;
} PyAttributeDef;
-#define KX_PYATTRIBUTE_BOOL_RW(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_BOOL_RW_CHECK(name,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, false, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_BOOL_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RO, 0, 1, 0.f, 0.f, false, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_BOOL_RW(name, object, field) \
+ { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_BOOL_RW_CHECK(name, object, field, function) \
+ { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, false, offsetof(object, field), 0, 1, &object::function, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_BOOL_RO(name, object, field) \
+ { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RO, 0, 1, 0.f, 0.f, false, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL, NULL, NULL} }
/* attribute points to a single bit of an integer field, attribute=true if bit is set */
-#define KX_PYATTRIBUTE_FLAG_RW(name,object,field,bit) \
- { name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RW, bit, 0, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLAG_RW_CHECK(name,object,field,bit,function) \
- { name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RW, bit, 0, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLAG_RO(name,object,field,bit) \
- { name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RO, bit, 0, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLAG_RW(name, object, field, bit) \
+ { name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RW, bit, 0, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLAG_RW_CHECK(name, object, field, bit, function) \
+ { name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RW, bit, 0, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLAG_RO(name, object, field, bit) \
+ { name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RO, bit, 0, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
/* attribute points to a single bit of an integer field, attribute=true if bit is set*/
-#define KX_PYATTRIBUTE_FLAG_NEGATIVE_RW(name,object,field,bit) \
- { name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RW, bit, 1, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLAG_NEGATIVE_RW_CHECK(name,object,field,bit,function) \
- { name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RW, bit, 1, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLAG_NEGATIVE_RO(name,object,field,bit) \
- { name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RO, bit, 1, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLAG_NEGATIVE_RW(name, object, field, bit) \
+ { name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RW, bit, 1, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLAG_NEGATIVE_RW_CHECK(name, object, field, bit, function) \
+ { name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RW, bit, 1, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLAG_NEGATIVE_RO(name, object, field, bit) \
+ { name, KX_PYATTRIBUTE_TYPE_FLAG, KX_PYATTRIBUTE_RO, bit, 1, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
// enum field cannot be mapped to pointer (because we would need a pointer for each enum)
// use field size to verify mapping at runtime only, assuming enum size is equal to int size.
-#define KX_PYATTRIBUTE_ENUM_RW(name,min,max,clamp,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_ENUM_RW_CHECK(name,min,max,clamp,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_ENUM_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-
-#define KX_PYATTRIBUTE_SHORT_RW(name,min,max,clamp,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_SHORT_RW_CHECK(name,min,max,clamp,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_SHORT_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_SHORT_ARRAY_RW(name,min,max,clamp,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_SHORT_ARRAY_RW_CHECK(name,min,max,clamp,object,field,length,function) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_SHORT_ARRAY_RO(name,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_ENUM_RW(name, min, max, clamp, object, field) \
+ { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_ENUM_RW_CHECK(name, min, max, clamp, object, field, function) \
+ { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_ENUM_RO(name, object, field) \
+ { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+
+#define KX_PYATTRIBUTE_SHORT_RW(name, min, max, clamp, object, field) \
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_RW_CHECK(name, min, max, clamp, object, field, function) \
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, 1, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_RO(name, object, field) \
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_ARRAY_RW(name, min, max, clamp, object, field, length) \
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_ARRAY_RW_CHECK(name, min, max, clamp, object, field, length, function) \
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, length, &object::function, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_ARRAY_RO(name, object, field, length) \
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
// SHORT_LIST
-#define KX_PYATTRIBUTE_SHORT_LIST_RW(name,min,max,clamp,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_SHORT_LIST_RW_CHECK(name,min,max,clamp,object,field,length,function) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_SHORT_LIST_RO(name,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
-
-#define KX_PYATTRIBUTE_INT_RW(name,min,max,clamp,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_INT_RW_CHECK(name,min,max,clamp,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_INT_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_INT_ARRAY_RW(name,min,max,clamp,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK(name,min,max,clamp,object,field,length,function) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_INT_ARRAY_RO(name,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_LIST_RW(name, min, max, clamp, object, field, length) \
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_LIST_RW_CHECK(name, min, max, clamp, object, field, length, function) \
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, length, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_LIST_RO(name, object, field, length) \
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL, NULL} }
+
+#define KX_PYATTRIBUTE_INT_RW(name, min, max, clamp, object, field) \
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_RW_CHECK(name, min, max, clamp, object, field, function) \
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_RO(name, object, field) \
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_ARRAY_RW(name, min, max, clamp, object, field, length) \
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK(name, min, max, clamp, object, field, length, function) \
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, length, &object::function, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_ARRAY_RO(name, object, field, length) \
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL, NULL, NULL} }
// INT_LIST
-#define KX_PYATTRIBUTE_INT_LIST_RW(name,min,max,clamp,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_INT_LIST_RW_CHECK(name,min,max,clamp,object,field,length,function) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_INT_LIST_RO(name,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_LIST_RW(name, min, max, clamp, object, field, length) \
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_LIST_RW_CHECK(name, min, max, clamp, object, field, length, function) \
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, length, &object::function, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_LIST_RO(name, object, field, length) \
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} }
// always clamp for float
-#define KX_PYATTRIBUTE_FLOAT_RW(name,min,max,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLOAT_RW_CHECK(name,min,max,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLOAT_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_RW(name, min, max, object, field) \
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_RW_CHECK(name, min, max, object, field, function) \
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object, field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_RO(name, object, field) \
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} }
// field must be float[n], returns a sequence
-#define KX_PYATTRIBUTE_FLOAT_ARRAY_RW(name,min,max,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLOAT_ARRAY_RW_CHECK(name,min,max,object,field,length,function) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLOAT_ARRAY_RO(name,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_ARRAY_RW(name, min, max, object, field, length) \
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_ARRAY_RW_CHECK(name, min, max, object, field, length, function) \
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object, field), 0, length, &object::function, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_ARRAY_RO(name, object, field, length) \
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, length, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
// field must be float[n], returns a vector
-#define KX_PYATTRIBUTE_FLOAT_VECTOR_RW(name,min,max,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, length, min, max, true, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLOAT_VECTOR_RW_CHECK(name,min,max,object,field,length,function) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, length, min, max, true, false, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLOAT_VECTOR_RO(name,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, length, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_VECTOR_RW(name, min, max, object, field, length) \
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, length, min, max, true, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_VECTOR_RW_CHECK(name, min, max, object, field, length, function) \
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, length, min, max, true, false, offsetof(object, field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_VECTOR_RO(name, object, field, length) \
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, length, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} }
// field must be float[n][n], returns a matrix
-#define KX_PYATTRIBUTE_FLOAT_MATRIX_RW(name,min,max,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, length, length, min, max, true, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field[0], NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLOAT_MATRIX_RW_CHECK(name,min,max,object,field,length,function) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, length, length, min, max, true, false, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field[0], NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_FLOAT_MATRIX_RO(name,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, length, length, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field[0], NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_MATRIX_RW(name, min, max, object, field, length) \
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, length, length, min, max, true, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field[0], NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_MATRIX_RW_CHECK(name, min, max, object, field, length, function) \
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, length, length, min, max, true, false, offsetof(object, field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field[0], NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_FLOAT_MATRIX_RO(name, object, field, length) \
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, length, length, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field[0], NULL, NULL, NULL} }
// only for STR_String member
-#define KX_PYATTRIBUTE_STRING_RW(name,min,max,clamp,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field, NULL, NULL} }
-#define KX_PYATTRIBUTE_STRING_RW_CHECK(name,min,max,clamp,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field, NULL, NULL} }
-#define KX_PYATTRIBUTE_STRING_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field, NULL, NULL} }
+#define KX_PYATTRIBUTE_STRING_RW(name, min, max, clamp, object, field) \
+ { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field, NULL, NULL} }
+#define KX_PYATTRIBUTE_STRING_RW_CHECK(name, min, max, clamp, object, field, function) \
+ { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, false, offsetof(object, field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field, NULL, NULL} }
+#define KX_PYATTRIBUTE_STRING_RO(name, object, field) \
+ { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field, NULL, NULL} }
// only for char [] array
-#define KX_PYATTRIBUTE_CHAR_RW(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_CHAR, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0.f, true, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, ((object *)0)->field} }
-#define KX_PYATTRIBUTE_CHAR_RW_CHECK(name,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_CHAR, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0.f, true, false, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, ((object *)0)->field} }
-#define KX_PYATTRIBUTE_CHAR_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_CHAR, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), sizeof(((object *)0)->field), 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, ((object *)0)->field} }
+#define KX_PYATTRIBUTE_CHAR_RW(name, object, field) \
+ { name, KX_PYATTRIBUTE_TYPE_CHAR, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0.f, true, false, offsetof(object, field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, ((object *)0)->field} }
+#define KX_PYATTRIBUTE_CHAR_RW_CHECK(name, object, field, function) \
+ { name, KX_PYATTRIBUTE_TYPE_CHAR, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0.f, true, false, offsetof(object, field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, ((object *)0)->field} }
+#define KX_PYATTRIBUTE_CHAR_RO(name, object, field) \
+ { name, KX_PYATTRIBUTE_TYPE_CHAR, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), sizeof(((object *)0)->field), 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, ((object *)0)->field} }
// for MT_Vector3 member
-#define KX_PYATTRIBUTE_VECTOR_RW(name,min,max,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field, NULL} }
-#define KX_PYATTRIBUTE_VECTOR_RW_CHECK(name,min,max,clamp,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field, NULL} }
-#define KX_PYATTRIBUTE_VECTOR_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object,field), 0, 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field, NULL} }
-
-#define KX_PYATTRIBUTE_RW_FUNCTION(name,object,getfunction,setfunction) \
+#define KX_PYATTRIBUTE_VECTOR_RW(name, min, max, object, field) \
+ { name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object, field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field, NULL} }
+#define KX_PYATTRIBUTE_VECTOR_RW_CHECK(name, min, max, clamp, object, field, function) \
+ { name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, false, offsetof(object, field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field, NULL} }
+#define KX_PYATTRIBUTE_VECTOR_RO(name, object, field) \
+ { name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, offsetof(object, field), 0, 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field, NULL} }
+
+#define KX_PYATTRIBUTE_RW_FUNCTION(name, object, getfunction, setfunction) \
{ name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0.f, false, false, 0, 0, 1, NULL, &object::setfunction, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_RO_FUNCTION(name,object,getfunction) \
+#define KX_PYATTRIBUTE_RO_FUNCTION(name, object, getfunction) \
{ name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, false, 0, 0, 1, NULL, NULL, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_ARRAY_RW_FUNCTION(name,object,length,getfunction,setfunction) \
- { name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0,f, false, false, 0, 0, length, NULL, &object::setfunction, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_ARRAY_RO_FUNCTION(name,object,length,getfunction) \
- { name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0,f, false, false, 0, 0, length, NULL, NULL, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_ARRAY_RW_FUNCTION(name, object, length, getfunction, setfunction) \
+ { name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0, f, false, false, 0, 0, length, NULL, &object::setfunction, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_ARRAY_RO_FUNCTION(name, object, length, getfunction) \
+ { name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0, f, false, false, 0, 0, length, NULL, NULL, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL, NULL} }
/*------------------------------
@@ -614,7 +614,7 @@ public:
/** enable/disable display of deprecation warnings */
static void SetDeprecationWarnings(bool ignoreDeprecationWarnings);
/** Shows a deprecation warning */
- static void ShowDeprecationWarning_func(const char* method,const char* prop);
+ static void ShowDeprecationWarning_func(const char *method, const char *prop);
static void ClearDeprecationWarning();
#endif
diff --git a/source/gameengine/Expressions/SConscript b/source/gameengine/Expressions/SConscript
index 4dc165a7696..a6d82a4f2da 100644
--- a/source/gameengine/Expressions/SConscript
+++ b/source/gameengine/Expressions/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.cpp')
diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp
index bcfb7e92d71..706cfc13ca3 100644
--- a/source/gameengine/Expressions/Value.cpp
+++ b/source/gameengine/Expressions/Value.cpp
@@ -18,6 +18,7 @@
*
*/
#include "Value.h"
+#include "BoolValue.h"
#include "FloatValue.h"
#include "IntValue.h"
#include "VectorValue.h"
@@ -573,6 +574,11 @@ CValue* CValue::ConvertPythonToValue(PyObject *pyobj, const char *error_prefix)
} else
#endif
+ /* note: Boolean check should go before Int check [#34677] */
+ if (PyBool_Check(pyobj))
+ {
+ vallie = new CBoolValue( (bool)PyLong_AsLongLong(pyobj) );
+ } else
if (PyFloat_Check(pyobj))
{
vallie = new CFloatValue( (float)PyFloat_AsDouble(pyobj) );
diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h
index c4af3255f4a..580691d88c4 100644
--- a/source/gameengine/Expressions/Value.h
+++ b/source/gameengine/Expressions/Value.h
@@ -253,9 +253,9 @@ public:
// Increase global reference count, used to see at the end of the program
// if all CValue-derived classes have been dereferenced to 0
//debug(gRefCountValue++);
- #ifdef _DEBUG
+#ifdef _DEBUG
//gRefCountValue++;
- #endif
+#endif
m_refcount++;
return this;
}
@@ -266,9 +266,9 @@ public:
// Decrease global reference count, used to see at the end of the program
// if all CValue-derived classes have been dereferenced to 0
//debug(gRefCountValue--);
- #ifdef _DEBUG
+#ifdef _DEBUG
//gRefCountValue--;
- #endif
+#endif
// Decrease local reference count, if it reaches 0 the object should be freed
if (--m_refcount > 0)
{
diff --git a/source/gameengine/GameLogic/CMakeLists.txt b/source/gameengine/GameLogic/CMakeLists.txt
index e511704c7f4..ad357bd015b 100644
--- a/source/gameengine/GameLogic/CMakeLists.txt
+++ b/source/gameengine/GameLogic/CMakeLists.txt
@@ -71,6 +71,7 @@ set(SRC
SCA_PropertyEventManager.cpp
SCA_PropertySensor.cpp
SCA_PythonController.cpp
+ SCA_PythonJoystick.cpp
SCA_PythonKeyboard.cpp
SCA_PythonMouse.cpp
SCA_RandomActuator.cpp
@@ -114,6 +115,7 @@ set(SRC
SCA_PropertyEventManager.h
SCA_PropertySensor.h
SCA_PythonController.h
+ SCA_PythonJoystick.h
SCA_PythonKeyboard.h
SCA_PythonMouse.h
SCA_RandomActuator.h
diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
index 8b343be8226..8e729ffd7ae 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
+++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
@@ -81,7 +81,7 @@ SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex )
return NULL;
#else /* WITH_SDL */
if (joyindex < 0 || joyindex >= JOYINDEX_MAX) {
- ECHO("Error-invalid joystick index: " << joyindex);
+ JOYSTICK_ECHO("Error-invalid joystick index: " << joyindex);
return NULL;
}
@@ -96,7 +96,7 @@ SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex )
# else
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO) == -1 ) {
# endif
- ECHO("Error-Initializing-SDL: " << SDL_GetError());
+ JOYSTICK_ECHO("Error-Initializing-SDL: " << SDL_GetError());
return NULL;
}
@@ -242,7 +242,7 @@ bool SCA_Joystick::CreateJoystickDevice(void)
if (m_isinit == false) {
if (m_joyindex>=m_joynum) {
/* don't print a message, because this is done anyway */
- //ECHO("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)");
+ //JOYSTICK_ECHO("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)");
/* Need this so python args can return empty lists */
m_axismax = m_buttonmax = m_hatmax = 0;
@@ -253,7 +253,7 @@ bool SCA_Joystick::CreateJoystickDevice(void)
SDL_JoystickEventState(SDL_ENABLE);
m_isinit = true;
- ECHO("Joystick " << m_joyindex << " initialized");
+ JOYSTICK_ECHO("Joystick " << m_joyindex << " initialized");
/* must run after being initialized */
m_axismax = SDL_JoystickNumAxes(m_private->m_joystick);
@@ -279,7 +279,7 @@ void SCA_Joystick::DestroyJoystickDevice(void)
#ifdef WITH_SDL
if (m_isinit) {
if (SDL_JoystickOpened(m_joyindex)) {
- ECHO("Closing-joystick " << m_joyindex);
+ JOYSTICK_ECHO("Closing-joystick " << m_joyindex);
SDL_JoystickClose(m_private->m_joystick);
}
m_isinit = false;
@@ -307,8 +307,11 @@ int SCA_Joystick::pGetAxis(int axisnum, int udlr)
int SCA_Joystick::pAxisTest(int axisnum)
{
#ifdef WITH_SDL
- short i1 = m_axis_array[(axisnum * 2)];
- short i2 = m_axis_array[(axisnum * 2) + 1];
+ /* Use ints instead of shorts here to avoid problems when we get -32768.
+ * When we take the negative of that later, we should get 32768, which is greater
+ * than what a short can hold. In other words, abs(MIN_SHORT) > MAX_SHRT. */
+ int i1 = m_axis_array[(axisnum * 2)];
+ int i2 = m_axis_array[(axisnum * 2) + 1];
/* long winded way to do:
* return max_ff(absf(i1), absf(i2))
@@ -321,3 +324,12 @@ int SCA_Joystick::pAxisTest(int axisnum)
return 0;
#endif /* WITH_SDL */
}
+
+const char *SCA_Joystick::GetName()
+{
+#ifdef WITH_SDL
+ return SDL_JoystickName(m_joyindex);
+#else /* WITH_SDL */
+ return "";
+#endif /* WITH_SDL */
+}
diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h
index 912484a2fe5..dd9fbefa545 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h
+++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h
@@ -192,6 +192,11 @@ public:
* Test if the joystick is connected
*/
int Connected(void);
+
+ /**
+ * Name of the joytsick
+ */
+ const char *GetName();
};
#endif
diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h
index 148bdd0962e..37c867ef7d6 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h
+++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h
@@ -37,10 +37,10 @@
#endif
#ifndef _DEBUG
-# define ECHO(x)
+# define JOYSTICK_ECHO(x)
#else
# include <iostream>
-# define ECHO(x) std::cout << x << std::endl;
+# define JOYSTICK_ECHO(x) std::cout << x << std::endl;
#endif
#define JOYINDEX_MAX 8
diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp
index 5ad5aedbd39..6a87d3ccb98 100644
--- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp
@@ -97,6 +97,11 @@ bool SCA_2DFilterActuator::Update()
}
+void SCA_2DFilterActuator::SetScene(SCA_IScene *scene)
+{
+ m_scene = scene;
+}
+
void SCA_2DFilterActuator::SetShaderText(const char *text)
{
m_shaderText = text;
diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.h b/source/gameengine/GameLogic/SCA_2DFilterActuator.h
index a754d950859..4635a8ad9f8 100644
--- a/source/gameengine/GameLogic/SCA_2DFilterActuator.h
+++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.h
@@ -64,6 +64,8 @@ public:
virtual ~SCA_2DFilterActuator();
virtual bool Update();
+ void SetScene(SCA_IScene *scene);
+
virtual CValue* GetReplica();
};
#endif
diff --git a/source/gameengine/GameLogic/SCA_IActuator.h b/source/gameengine/GameLogic/SCA_IActuator.h
index 090df1e75e2..aed49bc1822 100644
--- a/source/gameengine/GameLogic/SCA_IActuator.h
+++ b/source/gameengine/GameLogic/SCA_IActuator.h
@@ -131,7 +131,7 @@ public:
virtual void ProcessReplica();
/**
- * Return true iff all the current events
+ * Return true if all the current events
* are negative. The definition of negative event is
* not immediately clear. But usually refers to key-up events
* or events where no action is required.
diff --git a/source/gameengine/GameLogic/SCA_IInputDevice.h b/source/gameengine/GameLogic/SCA_IInputDevice.h
index 1a403f40955..ceb9c1e1d4f 100644
--- a/source/gameengine/GameLogic/SCA_IInputDevice.h
+++ b/source/gameengine/GameLogic/SCA_IInputDevice.h
@@ -269,7 +269,7 @@ public:
KX_MAX_KEYS
- } ; // enum
+ }; // enum
protected:
@@ -301,17 +301,18 @@ public:
virtual void HookEscape();
- /* Next frame: we calculate the new key states. This goes as follows:
- *
- * KX_NO_INPUTSTATUS -> KX_NO_INPUTSTATUS
- * KX_JUSTACTIVATED -> KX_ACTIVE
- * KX_ACTIVE -> KX_ACTIVE
- * KX_JUSTRELEASED -> KX_NO_INPUTSTATUS
- *
- * Getting new events provides the
- * KX_NO_INPUTSTATUS->KX_JUSTACTIVATED and
- * KX_ACTIVE->KX_JUSTRELEASED transitions.
- */
+ /**
+ * Next frame: we calculate the new key states. This goes as follows:
+ *
+ * KX_NO_INPUTSTATUS -> KX_NO_INPUTSTATUS
+ * KX_JUSTACTIVATED -> KX_ACTIVE
+ * KX_ACTIVE -> KX_ACTIVE
+ * KX_JUSTRELEASED -> KX_NO_INPUTSTATUS
+ *
+ * Getting new events provides the
+ * KX_NO_INPUTSTATUS->KX_JUSTACTIVATED and
+ * KX_ACTIVE->KX_JUSTRELEASED transitions.
+ */
virtual void NextFrame();
diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h
index 0189af00322..365e2b0c853 100644
--- a/source/gameengine/GameLogic/SCA_IObject.h
+++ b/source/gameengine/GameLogic/SCA_IObject.h
@@ -221,7 +221,7 @@ public:
OBJ_ARMATURE=0,
OBJ_CAMERA=1,
OBJ_LIGHT=2,
- }ObjectTypes;
+ } ObjectTypes;
};
diff --git a/source/gameengine/GameLogic/SCA_JoystickManager.cpp b/source/gameengine/GameLogic/SCA_JoystickManager.cpp
index c21db794e42..780e4e9ce88 100644
--- a/source/gameengine/GameLogic/SCA_JoystickManager.cpp
+++ b/source/gameengine/GameLogic/SCA_JoystickManager.cpp
@@ -60,14 +60,16 @@ SCA_JoystickManager::~SCA_JoystickManager()
void SCA_JoystickManager::NextFrame(double curtime,double deltatime)
{
+ // We should always handle events in case we want to grab them with Python
+#ifdef WITH_SDL
+ SCA_Joystick::HandleEvents(); /* Handle all SDL Joystick events */
+#endif
+
if (m_sensors.Empty()) {
return;
}
else {
;
-#ifdef WITH_SDL
- SCA_Joystick::HandleEvents(); /* Handle all SDL Joystick events */
-#endif
SG_DList::iterator<SCA_JoystickSensor> it(m_sensors);
for (it.begin();!it.end();++it)
{
diff --git a/source/gameengine/GameLogic/SCA_LogicManager.h b/source/gameengine/GameLogic/SCA_LogicManager.h
index 690930196b3..4d8c20065b5 100644
--- a/source/gameengine/GameLogic/SCA_LogicManager.h
+++ b/source/gameengine/GameLogic/SCA_LogicManager.h
@@ -52,7 +52,7 @@ using namespace std;
typedef std::list<class SCA_IController*> controllerlist;
typedef std::map<class SCA_ISensor*,controllerlist > sensormap_t;
-/**
+/**
* This manager handles sensor, controllers and actuators.
* logic executes each frame the following way:
* find triggering sensors
@@ -63,7 +63,7 @@ typedef std::map<class SCA_ISensor*,controllerlist > sensormap_t;
* clear triggering sensors
* clear triggered controllers
* (actuators may be active during a longer timeframe)
-*/
+ */
#include "SCA_ILogicBrick.h"
#include "SCA_IActuator.h"
@@ -117,8 +117,8 @@ public:
void RemoveGameObject(const STR_String& gameobjname);
/**
- * remove Logic Bricks from the running logicmanager
- */
+ * remove Logic Bricks from the running logicmanager
+ */
void RemoveSensor(SCA_ISensor* sensor);
void RemoveController(SCA_IController* controller);
void RemoveActuator(SCA_IActuator* actuator);
diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp
index c2b1470ae7a..3a9e8ff0bbc 100644
--- a/source/gameengine/GameLogic/SCA_PythonController.cpp
+++ b/source/gameengine/GameLogic/SCA_PythonController.cpp
@@ -270,7 +270,7 @@ void SCA_PythonController::ErrorPrint(const char *error_msg)
* their user count. Not to mention holding references to wrapped data.
* This is especially bad when the PyObject for the wrapped data is freed, after blender
* has already dealocated the pointer */
- PySys_SetObject( (char *)"last_traceback", NULL);
+ PySys_SetObject("last_traceback", NULL);
PyErr_Clear(); /* just to be sure */
}
diff --git a/source/gameengine/GameLogic/SCA_PythonJoystick.cpp b/source/gameengine/GameLogic/SCA_PythonJoystick.cpp
new file mode 100644
index 00000000000..9b24ad7bcf2
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_PythonJoystick.cpp
@@ -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): Mitchell Stokes.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file gameengine/GameLogic/SCA_PythonJoystick.cpp
+ * \ingroup gamelogic
+ */
+
+
+#include "SCA_PythonJoystick.h"
+#include "./Joystick/SCA_Joystick.h"
+#include "SCA_IInputDevice.h"
+
+//#include "GHOST_C-api.h"
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+SCA_PythonJoystick::SCA_PythonJoystick(SCA_Joystick* joystick)
+: PyObjectPlus(),
+m_joystick(joystick)
+{
+#ifdef WITH_PYTHON
+ m_event_dict = PyDict_New();
+#endif
+}
+
+SCA_PythonJoystick::~SCA_PythonJoystick()
+{
+ // The joystick reference we got in the constructor was a new instance,
+ // so we release it here
+ m_joystick->ReleaseInstance();
+
+#ifdef WITH_PYTHON
+ PyDict_Clear(m_event_dict);
+ Py_DECREF(m_event_dict);
+#endif
+}
+
+#ifdef WITH_PYTHON
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+PyObject* SCA_PythonJoystick::py_repr(void)
+{
+ return PyUnicode_FromString(m_joystick->GetName());
+}
+
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject SCA_PythonJoystick::Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SCA_PythonJoystick",
+ 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 SCA_PythonJoystick::Methods[] = {
+ {NULL,NULL} //Sentinel
+};
+
+PyAttributeDef SCA_PythonJoystick::Attributes[] = {
+ KX_PYATTRIBUTE_RO_FUNCTION("numButtons", SCA_PythonJoystick, pyattr_get_num_x),
+ KX_PYATTRIBUTE_RO_FUNCTION("numHats", SCA_PythonJoystick, pyattr_get_num_x),
+ KX_PYATTRIBUTE_RO_FUNCTION("numAxis", SCA_PythonJoystick, pyattr_get_num_x),
+ KX_PYATTRIBUTE_RO_FUNCTION("activeButtons", SCA_PythonJoystick, pyattr_get_active_buttons),
+ KX_PYATTRIBUTE_RO_FUNCTION("hatValues", SCA_PythonJoystick, pyattr_get_hat_values),
+ KX_PYATTRIBUTE_RO_FUNCTION("axisValues", SCA_PythonJoystick, pyattr_get_axis_values),
+ KX_PYATTRIBUTE_RO_FUNCTION("name", SCA_PythonJoystick, pyattr_get_name),
+ { NULL } //Sentinel
+};
+
+// Use one function for numAxis, numButtons, and numHats
+PyObject* SCA_PythonJoystick::pyattr_get_num_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ SCA_PythonJoystick* self = static_cast<SCA_PythonJoystick*>(self_v);
+
+ if (strcmp(attrdef->m_name, "numButtons") == 0)
+ return PyLong_FromLong(self->m_joystick->GetNumberOfButtons());
+ else if (strcmp(attrdef->m_name, "numAxis") == 0)
+ return PyLong_FromLong(self->m_joystick->GetNumberOfAxes());
+ else if (strcmp(attrdef->m_name, "numHats") == 0)
+ return PyLong_FromLong(self->m_joystick->GetNumberOfHats());
+
+ // If we got here, we have a problem...
+ PyErr_SetString(PyExc_AttributeError, "invalid attribute");
+ return NULL;
+}
+
+PyObject* SCA_PythonJoystick::pyattr_get_active_buttons(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ SCA_PythonJoystick* self = static_cast<SCA_PythonJoystick*>(self_v);
+
+ const int button_number = self->m_joystick->GetNumberOfButtons();
+
+ PyObject *list = PyList_New(0);
+ PyObject *value;
+
+ for (int i=0; i < button_number; i++) {
+ if (self->m_joystick->aButtonPressIsPositive(i)) {
+ value = PyLong_FromLong(i);
+ PyList_Append(list, value);
+ Py_DECREF(value);
+ }
+ }
+
+ return list;
+}
+
+PyObject* SCA_PythonJoystick::pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ SCA_PythonJoystick* self = static_cast<SCA_PythonJoystick*>(self_v);
+
+ int hat_index = self->m_joystick->GetNumberOfHats();
+ PyObject *list = PyList_New(hat_index);
+
+ while (hat_index--) {
+ PyList_SET_ITEM(list, hat_index, PyLong_FromLong(self->m_joystick->GetHat(hat_index)));
+ }
+
+ return list;
+}
+
+PyObject* SCA_PythonJoystick::pyattr_get_axis_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ SCA_PythonJoystick* self = static_cast<SCA_PythonJoystick*>(self_v);
+
+ int axis_index = self->m_joystick->GetNumberOfAxes();
+ PyObject *list = PyList_New(axis_index);
+ int position;
+
+ while (axis_index--) {
+ position = self->m_joystick->GetAxisPosition(axis_index);
+
+ // We get back a range from -32768 to 32767, so we use an if here to
+ // get a perfect -1.0 to 1.0 mapping. Some oddball system might have an
+ // actual min of -32767 for shorts, so we use SHRT_MIN/MAX to be safe.
+ if (position < 0)
+ PyList_SET_ITEM(list, axis_index, PyFloat_FromDouble(position/((double)-SHRT_MIN)));
+ else
+ PyList_SET_ITEM(list, axis_index, PyFloat_FromDouble(position/(double)SHRT_MAX));
+ }
+
+ return list;
+}
+
+PyObject* SCA_PythonJoystick::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ SCA_PythonJoystick* self = static_cast<SCA_PythonJoystick*>(self_v);
+
+ return PyUnicode_FromString(self->m_joystick->GetName());
+}
+#endif
diff --git a/source/gameengine/GameLogic/SCA_PythonJoystick.h b/source/gameengine/GameLogic/SCA_PythonJoystick.h
new file mode 100644
index 00000000000..15c6285aed5
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_PythonJoystick.h
@@ -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.
+ *
+ * Contributor(s): Mitchell Stokes.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file SCA_PythonJoystick.h
+ * \ingroup gamelogic
+ */
+
+#ifndef __SCA_PYTHONJOYSTICK_H__
+#define __SCA_PYTHONJOYSTICK_H__
+
+#include "PyObjectPlus.h"
+
+class SCA_PythonJoystick : public PyObjectPlus
+{
+ Py_Header
+private:
+ class SCA_Joystick *m_joystick;
+#ifdef WITH_PYTHON
+ PyObject* m_event_dict;
+#endif
+public:
+ SCA_PythonJoystick(class SCA_Joystick* joystick);
+ virtual ~SCA_PythonJoystick();
+
+#ifdef WITH_PYTHON
+ virtual PyObject* py_repr(void);
+
+ static PyObject* pyattr_get_num_x(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject* pyattr_get_active_buttons(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject* pyattr_get_hat_values(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject* pyattr_get_axis_values(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject* pyattr_get_name(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+#endif
+};
+
+#endif //__SCA_PYTHONJOYSTICK_H__
+
diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp
index 5568072abcf..db6b4a63423 100644
--- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp
@@ -178,23 +178,15 @@ bool SCA_RandomActuator::Update()
case KX_RANDOMACT_FLOAT_NORMAL: {
/* normal (big numbers): para1 = mean, para2 = std dev */
- /*
-
- 070301 - nzc - Changed the termination condition. I think I
- made a small mistake here, but it only affects distro's where
- the seed equals 0. In that case, the algorithm locks. Let's
- just guard that case separately.
-
- */
+ /* 070301 - nzc: Changed the termination condition. I think I
+ * made a small mistake here, but it only affects distro's where
+ * the seed equals 0. In that case, the algorithm locks. Let's
+ * just guard that case separately.
+ */
float x = 0.0, y = 0.0, s = 0.0, t = 0.0;
if (m_base->GetSeed() == 0) {
- /*
-
- 070301 - nzc
- Just taking the mean here seems reasonable.
-
- */
+ /* 070301 - nzc: Just taking the mean here seems reasonable. */
tmpval = new CFloatValue(m_parameter1);
}
else {
diff --git a/source/gameengine/GameLogic/SConscript b/source/gameengine/GameLogic/SConscript
index da3c0fadb51..b274e518015 100644
--- a/source/gameengine/GameLogic/SConscript
+++ b/source/gameengine/GameLogic/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.cpp') + env.Glob('Joystick/*.cpp')
diff --git a/source/gameengine/GamePlayer/SConscript b/source/gameengine/GamePlayer/SConscript
index 0b140bba8e7..d1930aca26d 100644
--- a/source/gameengine/GamePlayer/SConscript
+++ b/source/gameengine/GamePlayer/SConscript
@@ -1,3 +1,29 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
SConscript(['common/SConscript',
'ghost/SConscript'])
diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.cpp b/source/gameengine/GamePlayer/common/GPC_Canvas.cpp
index b5c1c29238a..058454ca352 100644
--- a/source/gameengine/GamePlayer/common/GPC_Canvas.cpp
+++ b/source/gameengine/GamePlayer/common/GPC_Canvas.cpp
@@ -131,7 +131,15 @@ void GPC_Canvas::SetViewPort(int x1, int y1, int x2, int y2)
glViewport(x1,y1,x2-x1 + 1,y2-y1 + 1);
glScissor(x1,y1,x2-x1 + 1,y2-y1 + 1);
-};
+}
+
+void GPC_Canvas::UpdateViewPort(int x1, int y1, int x2, int y2)
+{
+ m_viewport[0] = x1;
+ m_viewport[1] = y1;
+ m_viewport[2] = x2;
+ m_viewport[3] = y2;
+}
const int *GPC_Canvas::GetViewPort()
{
diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.h b/source/gameengine/GamePlayer/common/GPC_Canvas.h
index ec5375c0e13..07f96166ec2 100644
--- a/source/gameengine/GamePlayer/common/GPC_Canvas.h
+++ b/source/gameengine/GamePlayer/common/GPC_Canvas.h
@@ -36,8 +36,8 @@
#include "RAS_Rect.h"
#ifdef WIN32
- #pragma warning (disable:4786) // suppress stl-MSVC debug info warning
- #include <windows.h>
+# pragma warning (disable:4786) // suppress stl-MSVC debug info warning
+# include <windows.h>
#endif /* WIN32 */
#include "GL/glew.h"
@@ -155,6 +155,7 @@ public:
);
void SetViewPort(int x1, int y1, int x2, int y2);
+ void UpdateViewPort(int x1, int y1, int x2, int y2);
const int *GetViewPort();
void ClearColor(float r, float g, float b, float a);
diff --git a/source/gameengine/GamePlayer/common/GPC_Engine.cpp b/source/gameengine/GamePlayer/common/GPC_Engine.cpp
index 11d648762c8..1a90fb8aca8 100644
--- a/source/gameengine/GamePlayer/common/GPC_Engine.cpp
+++ b/source/gameengine/GamePlayer/common/GPC_Engine.cpp
@@ -155,14 +155,14 @@ bool GPC_Engine::Start(const char *filename)
}
-bool GPC_Engine::Start(unsigned char *blenderDataBuffer,
- unsigned int blenderDataBufferSize)
+bool GPC_Engine::Start(const void *blenderDataBuffer,
+ unsigned int blenderDataBufferSize)
{
ReportList reports;
BlendFileData *bfd;
BKE_reports_init(&reports, RPT_STORE);
- bfd= BLO_read_from_memory(blenderDataBuffer, blenderDataBufferSize, &reports);
+ bfd = BLO_read_from_memory(blenderDataBuffer, blenderDataBufferSize, &reports);
BKE_reports_clear(&reports);
if (!bfd) {
diff --git a/source/gameengine/GamePlayer/common/GPC_Engine.h b/source/gameengine/GamePlayer/common/GPC_Engine.h
index 6247bd630bb..3a4fd9c81d6 100644
--- a/source/gameengine/GamePlayer/common/GPC_Engine.h
+++ b/source/gameengine/GamePlayer/common/GPC_Engine.h
@@ -103,7 +103,7 @@ public:
// different prototypes for Unix and Windows
void StartLoadingAnimation();
bool Start(const char *filename); // file-on-disk starter
- bool Start(unsigned char *blenderDataBuffer,
+ bool Start(const void *blenderDataBuffer,
unsigned int blenderDataBufferSize); // file-in-memory starter
void Stop();
diff --git a/source/gameengine/GamePlayer/common/GPC_RawImage.cpp b/source/gameengine/GamePlayer/common/GPC_RawImage.cpp
index c0d66541800..0e2585b0baa 100644
--- a/source/gameengine/GamePlayer/common/GPC_RawImage.cpp
+++ b/source/gameengine/GamePlayer/common/GPC_RawImage.cpp
@@ -29,7 +29,6 @@
* \ingroup player
*/
-
#include <iostream>
#include <string.h>
diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
index dfc866526eb..bab4aa14bbd 100644
--- a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
+++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
@@ -283,6 +283,78 @@ void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,in
}
}
+void GPC_RenderTools::RenderBox2D(int xco,
+ int yco,
+ int width,
+ int height,
+ float percentage)
+{
+ // Save and change OpenGL settings
+ int texture2D;
+ glGetIntegerv(GL_TEXTURE_2D, (GLint*)&texture2D);
+ glDisable(GL_TEXTURE_2D);
+ int fog;
+ glGetIntegerv(GL_FOG, (GLint*)&fog);
+ glDisable(GL_FOG);
+
+ int light;
+ glGetIntegerv(GL_LIGHTING, (GLint*)&light);
+ glDisable(GL_LIGHTING);
+
+ glDisable(GL_DEPTH_TEST);
+
+ // Set up viewing settings
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glOrtho(0, width, 0, height, -1, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ yco = height - yco;
+ int barsize = 50;
+
+ // draw in black first
+ glColor3ub(0, 0, 0);
+ glBegin(GL_QUADS);
+ glVertex2f(xco + 1 + 1 + barsize * percentage, yco - 1 + 10);
+ glVertex2f(xco + 1, yco - 1 + 10);
+ glVertex2f(xco + 1, yco - 1);
+ glVertex2f(xco + 1 + 1 + barsize * percentage, yco - 1);
+ glEnd();
+
+ glColor3ub(255, 255, 255);
+ glBegin(GL_QUADS);
+ glVertex2f(xco + 1 + barsize * percentage, yco + 10);
+ glVertex2f(xco, yco + 10);
+ glVertex2f(xco, yco);
+ glVertex2f(xco + 1 + barsize * percentage, yco);
+ glEnd();
+
+ // Restore view settings
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ // Restore OpenGL Settings
+ if (fog)
+ glEnable(GL_FOG);
+ else
+ glDisable(GL_FOG);
+
+ if (texture2D)
+ glEnable(GL_TEXTURE_2D);
+ else
+ glDisable(GL_TEXTURE_2D);
+ if (light)
+ glEnable(GL_LIGHTING);
+ else
+ glDisable(GL_LIGHTING);
+}
+
+
void GPC_RenderTools::RenderText3D( int fontid,
const char* text,
int size,
diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.h b/source/gameengine/GamePlayer/common/GPC_RenderTools.h
index 1030c09548a..f4dcddd3250 100644
--- a/source/gameengine/GamePlayer/common/GPC_RenderTools.h
+++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.h
@@ -70,6 +70,12 @@ public:
void DisableOpenGLLights();
void ProcessLighting(RAS_IRasterizer *rasty, bool uselights, const MT_Transform& viewmat);
+ void RenderBox2D(int xco,
+ int yco,
+ int width,
+ int height,
+ float percentage);
+
void RenderText3D(int fontid,
const char* text,
int size,
diff --git a/source/gameengine/GamePlayer/common/SConscript b/source/gameengine/GamePlayer/common/SConscript
index 6a1f47c51af..1648d8af78c 100644
--- a/source/gameengine/GamePlayer/common/SConscript
+++ b/source/gameengine/GamePlayer/common/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
import sys
Import ('env')
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
index 92db1fe790e..58710120afa 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
@@ -76,7 +76,6 @@ extern "C"
#include "SCA_IActuator.h"
#include "RAS_MeshObject.h"
#include "RAS_OpenGLRasterizer.h"
-#include "RAS_VAOpenGLRasterizer.h"
#include "RAS_ListRasterizer.h"
#include "RAS_GLExtensionManager.h"
#include "KX_PythonInit.h"
@@ -309,20 +308,21 @@ bool GPG_Application::startScreenSaverFullScreen(
#endif
-bool GPG_Application::startWindow(STR_String& title,
- int windowLeft,
- int windowTop,
- int windowWidth,
- int windowHeight,
- const bool stereoVisual,
- const int stereoMode,
- const GHOST_TUns16 samples)
+bool GPG_Application::startWindow(
+ STR_String& title,
+ int windowLeft,
+ int windowTop,
+ int windowWidth,
+ int windowHeight,
+ const bool stereoVisual,
+ const int stereoMode,
+ const GHOST_TUns16 samples)
{
bool success;
// Create the main window
//STR_String title ("Blender Player - GHOST");
m_mainWindow = fSystem->createWindow(title, windowLeft, windowTop, windowWidth, windowHeight, GHOST_kWindowStateNormal,
- GHOST_kDrawingContextTypeOpenGL, stereoVisual, samples);
+ GHOST_kDrawingContextTypeOpenGL, stereoVisual, false, samples);
if (!m_mainWindow) {
printf("error: could not create main window\n");
exit(-1);
@@ -341,16 +341,18 @@ bool GPG_Application::startWindow(STR_String& title,
return success;
}
-bool GPG_Application::startEmbeddedWindow(STR_String& title,
- const GHOST_TEmbedderWindowID parentWindow,
- const bool stereoVisual,
- const int stereoMode,
- const GHOST_TUns16 samples) {
+bool GPG_Application::startEmbeddedWindow(
+ STR_String& title,
+ const GHOST_TEmbedderWindowID parentWindow,
+ const bool stereoVisual,
+ const int stereoMode,
+ const GHOST_TUns16 samples)
+{
GHOST_TWindowState state = GHOST_kWindowStateNormal;
if (parentWindow != 0)
state = GHOST_kWindowStateEmbedded;
m_mainWindow = fSystem->createWindow(title, 0, 0, 0, 0, state,
- GHOST_kDrawingContextTypeOpenGL, stereoVisual, samples, parentWindow);
+ GHOST_kDrawingContextTypeOpenGL, stereoVisual, false, samples, parentWindow);
if (!m_mainWindow) {
printf("error: could not create main window\n");
@@ -367,13 +369,13 @@ bool GPG_Application::startEmbeddedWindow(STR_String& title,
bool GPG_Application::startFullScreen(
- int width,
- int height,
- int bpp,int frequency,
- const bool stereoVisual,
- const int stereoMode,
- const GHOST_TUns16 samples,
- bool useDesktop)
+ int width,
+ int height,
+ int bpp,int frequency,
+ const bool stereoVisual,
+ const int stereoMode,
+ const GHOST_TUns16 samples,
+ bool useDesktop)
{
bool success;
GHOST_TUns32 sysWidth=0, sysHeight=0;
@@ -387,6 +389,7 @@ bool GPG_Application::startFullScreen(
fSystem->beginFullScreen(setting, &m_mainWindow, stereoVisual, samples);
m_mainWindow->setCursorVisibility(false);
+ /* note that X11 ignores this (it uses a window internally for fullscreen) */
m_mainWindow->setState(GHOST_kWindowStateFullScreen);
success = initEngine(m_mainWindow, stereoMode);
@@ -582,16 +585,12 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
if (!m_rendertools)
goto initFailed;
- if (useLists) {
- if (GLEW_VERSION_1_1)
- m_rasterizer = new RAS_ListRasterizer(m_canvas, true);
- else
- m_rasterizer = new RAS_ListRasterizer(m_canvas);
- }
- else if (GLEW_VERSION_1_1)
- m_rasterizer = new RAS_VAOpenGLRasterizer(m_canvas);
+ //Don't use displaylists with VBOs
+ //If auto starts using VBOs, make sure to check for that here
+ if (useLists && gm->raster_storage != RAS_STORE_VBO)
+ m_rasterizer = new RAS_ListRasterizer(m_canvas, false, gm->raster_storage);
else
- m_rasterizer = new RAS_OpenGLRasterizer(m_canvas);
+ m_rasterizer = new RAS_OpenGLRasterizer(m_canvas, gm->raster_storage);
/* Stereo parameters - Eye Separation from the UI - stereomode from the command-line/UI */
m_rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) stereoMode);
@@ -708,6 +707,8 @@ bool GPG_Application::startEngine(void)
m_sceneconverter->SetMaterials(true);
if (m_blenderglslmat && (m_globalSettings->matmode == GAME_MAT_GLSL))
m_sceneconverter->SetGLSLMaterials(true);
+ if (m_startScene->gm.flag & GAME_NO_MATERIAL_CACHING)
+ m_sceneconverter->SetCacheMaterials(false);
KX_Scene* startscene = new KX_Scene(m_keyboard,
m_mouse,
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.h b/source/gameengine/GamePlayer/ghost/GPG_Application.h
index e04fcc2a555..f141443e738 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.h
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.h
@@ -61,23 +61,32 @@ public:
GPG_Application(GHOST_ISystem* system);
~GPG_Application(void);
- bool SetGameEngineData(struct Main* maggie, struct Scene* scene, GlobalSettings* gs, int argc, char** argv);
- bool startWindow(STR_String& title, int windowLeft, int windowTop, int windowWidth, int windowHeight,
- const bool stereoVisual, const int stereoMode, const GHOST_TUns16 samples=0);
- bool startFullScreen(int width, int height, int bpp, int frequency, const bool stereoVisual, const int stereoMode, const GHOST_TUns16 samples=0, bool useDesktop=false);
- bool startEmbeddedWindow(STR_String& title, const GHOST_TEmbedderWindowID parent_window, const bool stereoVisual, const int stereoMode, const GHOST_TUns16 samples=0);
+ bool SetGameEngineData(struct Main* maggie, struct Scene* scene, GlobalSettings* gs, int argc, char** argv);
+ bool startWindow(STR_String& title,
+ int windowLeft, int windowTop,
+ int windowWidth, int windowHeight,
+ const bool stereoVisual, const int stereoMode, const GHOST_TUns16 samples=0);
+ bool startFullScreen(int width, int height,
+ int bpp, int frequency,
+ const bool stereoVisual, const int stereoMode,
+ const GHOST_TUns16 samples=0, bool useDesktop=false);
+ bool startEmbeddedWindow(STR_String& title, const GHOST_TEmbedderWindowID parent_window,
+ const bool stereoVisual, const int stereoMode, const GHOST_TUns16 samples=0);
#ifdef WIN32
- bool startScreenSaverFullScreen(int width, int height, int bpp, int frequency, const bool stereoVisual, const int stereoMode, const GHOST_TUns16 samples=0);
- bool startScreenSaverPreview(HWND parentWindow, const bool stereoVisual, const int stereoMode, const GHOST_TUns16 samples=0);
+ bool startScreenSaverFullScreen(int width, int height,
+ int bpp, int frequency,
+ const bool stereoVisual, const int stereoMode, const GHOST_TUns16 samples=0);
+ bool startScreenSaverPreview(HWND parentWindow,
+ const bool stereoVisual, const int stereoMode, const GHOST_TUns16 samples=0);
#endif
virtual bool processEvent(GHOST_IEvent* event);
- int getExitRequested(void);
- const STR_String& getExitString(void);
- GlobalSettings* getGlobalSettings(void);
- bool StartGameEngine(int stereoMode);
- void StopGameEngine();
- void EngineNextFrame();
+ int getExitRequested(void);
+ const STR_String& getExitString(void);
+ GlobalSettings* getGlobalSettings(void);
+ bool StartGameEngine(int stereoMode);
+ void StopGameEngine();
+ void EngineNextFrame();
protected:
bool handleWheel(GHOST_IEvent* event);
@@ -165,4 +174,3 @@ protected:
int m_argc;
char** m_argv;
};
-
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
index ba7d3135a10..5d843cccf85 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -258,10 +258,10 @@ static void usage(const char* program, bool isBlenderPlayer)
static void get_filename(int argc, char **argv, char *filename)
{
#ifdef __APPLE__
-/* On Mac we park the game file (called game.blend) in the application bundle.
-* The executable is located in the bundle as well.
-* Therefore, we can locate the game relative to the executable.
- */
+ /* On Mac we park the game file (called game.blend) in the application bundle.
+ * The executable is located in the bundle as well.
+ * Therefore, we can locate the game relative to the executable.
+ */
int srclen = ::strlen(argv[0]);
int len = 0;
char *gamefile = NULL;
@@ -449,6 +449,10 @@ int main(int argc, char** argv)
IMB_init();
BKE_images_init();
+#ifdef WITH_FFMPEG
+ IMB_ffmpeg_init();
+#endif
+
// Setup builtin font for BLF (mostly copied from creator.c, wm_init_exit.c and interface_style.c)
BLF_init(11, U.dpi);
BLF_lang_init();
@@ -471,7 +475,7 @@ int main(int argc, char** argv)
break;
case SCREEN_SAVER_MODE_PASSWORD:
/* This is W95 only, which we currently do not support.
- Fall-back to normal screen saver behavior in that case... */
+ * Fall-back to normal screen saver behavior in that case... */
case SCREEN_SAVER_MODE_SAVER:
fullScreen = true;
fullScreenParFound = true;
@@ -608,7 +612,7 @@ int main(int argc, char** argv)
case 'i':
i++;
if ( (i + 1) <= validArguments )
- parentWindow = atoi(argv[i++]);
+ parentWindow = atoi(argv[i++]);
else {
error = true;
printf("error: too few options for parent window argument.\n");
@@ -641,10 +645,10 @@ int main(int argc, char** argv)
stereomode = (RAS_IRasterizer::StereoMode) atoi(argv[i]);
if (stereomode < RAS_IRasterizer::RAS_STEREO_NOSTEREO || stereomode >= RAS_IRasterizer::RAS_STEREO_MAXSTEREO)
stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
-
+
if (!strcmp(argv[i], "nostereo")) // ok, redundant but clear
stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
-
+
// only the hardware pageflip method needs a stereo window
else if (!strcmp(argv[i], "hwpageflip")) {
stereomode = RAS_IRasterizer::RAS_STEREO_QUADBUFFERED;
@@ -652,22 +656,22 @@ int main(int argc, char** argv)
}
else if (!strcmp(argv[i], "syncdoubling"))
stereomode = RAS_IRasterizer::RAS_STEREO_ABOVEBELOW;
-
+
else if (!strcmp(argv[i], "anaglyph"))
stereomode = RAS_IRasterizer::RAS_STEREO_ANAGLYPH;
-
+
else if (!strcmp(argv[i], "sidebyside"))
stereomode = RAS_IRasterizer::RAS_STEREO_SIDEBYSIDE;
-
+
else if (!strcmp(argv[i], "vinterlace"))
stereomode = RAS_IRasterizer::RAS_STEREO_VINTERLACE;
-
+
#if 0
- // future stuff
- else if (!strcmp(argv[i], "stencil")
- stereomode = RAS_STEREO_STENCIL;
+// // future stuff
+// else if (!strcmp(argv[i], "stencil")
+// stereomode = RAS_STEREO_STENCIL;
#endif
-
+
i++;
stereoParFound = true;
stereoFlag = STEREO_ENABLED;
@@ -729,7 +733,7 @@ int main(int argc, char** argv)
i++;
}
}
-
+
if ((windowWidth < kMinWindowWidth) || (windowHeight < kMinWindowHeight))
{
error = true;
@@ -752,8 +756,7 @@ int main(int argc, char** argv)
//fullScreen = false; // Can't use full screen
#endif
- if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0))
- {
+ if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0)) {
GPU_set_mipmap(0);
}
@@ -761,15 +764,14 @@ int main(int argc, char** argv)
GPU_set_gpu_mipmapping(U.use_gpu_mipmap);
// Create the system
- if (GHOST_ISystem::createSystem() == GHOST_kSuccess)
- {
+ if (GHOST_ISystem::createSystem() == GHOST_kSuccess) {
GHOST_ISystem* system = GHOST_ISystem::getSystem();
assertd(system);
if (!fullScreenWidth || !fullScreenHeight)
system->getMainDisplayDimensions(fullScreenWidth, fullScreenHeight);
// process first batch of events. If the user
- // drops a file on top off the blenderplayer icon, we
+ // drops a file on top off the blenderplayer icon, we
// receive an event with the filename
system->processEvents(0);
@@ -794,8 +796,7 @@ int main(int argc, char** argv)
// those may change during the game and persist after using Game Actuator
GlobalSettings gs;
- do
- {
+ do {
// Read the Blender file
BlendFileData *bfd;
@@ -810,19 +811,17 @@ int main(int argc, char** argv)
bfd = load_game_data(basedpath);
- if (!bfd)
- {
+ if (!bfd) {
// just add "//" in front of it
char temppath[242];
strcpy(temppath, "//");
strcat(temppath, basedpath);
-
+
BLI_path_abs(temppath, pathname);
bfd = load_game_data(temppath);
}
}
- else
- {
+ else {
bfd = load_game_data(BLI_program_path(), filename[0]? filename: NULL);
}
@@ -832,13 +831,11 @@ int main(int argc, char** argv)
usage(argv[0], isBlenderPlayer);
error = true;
exitcode = KX_EXIT_REQUEST_QUIT_GAME;
- }
- else
- {
+ }
+ else {
#ifdef WIN32
#if !defined(DEBUG)
- if (closeConsole)
- {
+ if (closeConsole) {
system->toggleConsole(0); // Close a console window
}
#endif // !defined(DEBUG)
@@ -860,8 +857,7 @@ int main(int argc, char** argv)
titlename = maggie->name;
// Check whether the game should be displayed full-screen
- if ((!fullScreenParFound) && (!windowParFound))
- {
+ if ((!fullScreenParFound) && (!windowParFound)) {
// Only use file settings when command line did not override
if ((scene->gm.playerflag & GAME_PLAYER_FULLSCREEN)) {
//printf("fullscreen option found in Blender file\n");
@@ -881,16 +877,16 @@ int main(int argc, char** argv)
// Check whether the game should be displayed in stereo
- if (!stereoParFound)
- {
+ if (!stereoParFound) {
if (scene->gm.stereoflag == STEREO_ENABLED) {
stereomode = (RAS_IRasterizer::StereoMode) scene->gm.stereomode;
if (stereomode == RAS_IRasterizer::RAS_STEREO_QUADBUFFERED)
stereoWindow = true;
}
}
- else
+ else {
scene->gm.stereoflag = STEREO_ENABLED;
+ }
if (!samplesParFound)
aasamples = scene->gm.aasamples;
@@ -904,10 +900,9 @@ int main(int argc, char** argv)
scene->gm.dome.tilt = domeTilt;
if (domeMode > 0)
scene->gm.dome.mode = domeMode;
- if (domeWarp)
- {
+ if (domeWarp) {
//XXX to do: convert relative to absolute path
- domeText= BKE_text_load(domeWarp, "");
+ domeText= BKE_text_load(G.main, domeWarp, "");
if (!domeText)
printf("error: invalid warpdata text file - %s\n", domeWarp);
else
@@ -924,23 +919,21 @@ int main(int argc, char** argv)
#ifdef WITH_PYTHON
setGamePythonPath(G.main->name);
#endif
- if (firstTimeRunning)
- {
+ if (firstTimeRunning) {
firstTimeRunning = false;
- if (fullScreen)
- {
+ if (fullScreen) {
#ifdef WIN32
if (scr_saver_mode == SCREEN_SAVER_MODE_SAVER)
{
app.startScreenSaverFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
- stereoWindow, stereomode, aasamples);
+ stereoWindow, stereomode, aasamples);
}
else
#endif
{
app.startFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
- stereoWindow, stereomode, aasamples, (scene->gm.playerflag & GAME_PLAYER_DESKTOP_RESOLUTION));
+ stereoWindow, stereomode, aasamples, (scene->gm.playerflag & GAME_PLAYER_DESKTOP_RESOLUTION));
}
}
else
@@ -964,8 +957,7 @@ int main(int argc, char** argv)
vector<STR_String> parts = path.Explode('\\');
#endif // WIN32
STR_String title;
- if (parts.size())
- {
+ if (parts.size()) {
title = parts[parts.size()-1];
parts = title.Explode('.');
if (parts.size() > 1)
@@ -973,8 +965,7 @@ int main(int argc, char** argv)
title = parts[0];
}
}
- else
- {
+ else {
title = "blenderplayer";
}
#ifdef WIN32
@@ -985,16 +976,15 @@ int main(int argc, char** argv)
else
#endif
{
- if (parentWindow != 0)
+ if (parentWindow != 0)
app.startEmbeddedWindow(title, parentWindow, stereoWindow, stereomode, aasamples);
else
app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight,
- stereoWindow, stereomode, aasamples);
+ stereoWindow, stereomode, aasamples);
}
}
}
- else
- {
+ else {
app.StartGameEngine(stereomode);
exitcode = KX_EXIT_REQUEST_NO_REQUEST;
}
@@ -1004,44 +994,40 @@ int main(int argc, char** argv)
// Enter main loop
bool run = true;
- char *python_main = NULL;
+ char *python_main = NULL;
pynextframestate.state = NULL;
pynextframestate.func = NULL;
#ifdef WITH_PYTHON
python_main = KX_GetPythonMain(scene);
#endif // WITH_PYTHON
- if (python_main)
- {
+ if (python_main) {
char *python_code = KX_GetPythonCode(maggie, python_main);
- if (python_code)
- {
-#ifdef WITH_PYTHON
+ if (python_code) {
+#ifdef WITH_PYTHON
gpg_nextframestate.system = system;
gpg_nextframestate.app = &app;
gpg_nextframestate.gs = &gs;
pynextframestate.state = &gpg_nextframestate;
pynextframestate.func = &GPG_PyNextFrame;
- printf("Yielding control to Python script '%s'...\n", python_main);
- PyRun_SimpleString(python_code);
- printf("Exit Python script '%s'\n", python_main);
+ printf("Yielding control to Python script '%s'...\n", python_main);
+ PyRun_SimpleString(python_code);
+ printf("Exit Python script '%s'\n", python_main);
#endif // WITH_PYTHON
- MEM_freeN(python_code);
- }
- else {
- fprintf(stderr, "ERROR: cannot yield control to Python: no Python text data block named '%s'\n", python_main);
- }
- }
- else
- {
- while (run)
- {
+ MEM_freeN(python_code);
+ }
+ else {
+ fprintf(stderr, "ERROR: cannot yield control to Python: no Python text data block named '%s'\n", python_main);
+ }
+ }
+ else {
+ while (run) {
run = GPG_NextFrame(system, &app, exitcode, exitstring, &gs);
}
}
app.StopGameEngine();
- /* 'app' is freed automatic when out of scope.
+ /* 'app' is freed automatic when out of scope.
* removal is needed else the system will free an already freed value */
system->removeEventConsumer(&app);
@@ -1056,7 +1042,8 @@ int main(int argc, char** argv)
// Dispose the system
GHOST_ISystem::disposeSystem();
- } else {
+ }
+ else {
error = true;
printf("error: couldn't create a system.\n");
}
@@ -1068,6 +1055,7 @@ int main(int argc, char** argv)
#ifdef WITH_INTERNATIONAL
BLF_free_unifont();
+ BLF_free_unifont_mono();
BLF_lang_free();
#endif
@@ -1086,5 +1074,3 @@ int main(int argc, char** argv)
return error ? -1 : 0;
}
-
-
diff --git a/source/gameengine/GamePlayer/ghost/SConscript b/source/gameengine/GamePlayer/ghost/SConscript
index fb046d0fdf8..64bd58aa784 100644
--- a/source/gameengine/GamePlayer/ghost/SConscript
+++ b/source/gameengine/GamePlayer/ghost/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
import sys
Import ('env')
diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp
index 5b7a2313f43..fa00cafa148 100644
--- a/source/gameengine/Ketsji/BL_Action.cpp
+++ b/source/gameengine/Ketsji/BL_Action.cpp
@@ -36,7 +36,6 @@
// These three are for getting the action from the logic manager
#include "KX_Scene.h"
-#include "KX_PythonInit.h"
#include "SCA_LogicManager.h"
extern "C" {
@@ -44,6 +43,10 @@ extern "C" {
#include "BKE_action.h"
#include "RNA_access.h"
#include "RNA_define.h"
+
+// Needed for material IPOs
+#include "BKE_material.h"
+#include "DNA_material_types.h"
}
BL_Action::BL_Action(class KX_GameObject* gameobj)
@@ -132,8 +135,10 @@ bool BL_Action::Play(const char* name,
m_priority = priority;
bAction* prev_action = m_action;
+ KX_Scene* kxscene = m_obj->GetScene();
+
// First try to load the action
- m_action = (bAction*)KX_GetActiveScene()->GetLogicManager()->GetActionByName(name);
+ m_action = (bAction*)kxscene->GetLogicManager()->GetActionByName(name);
if (!m_action)
{
printf("Failed to load action: %s\n", name);
@@ -151,33 +156,67 @@ bool BL_Action::Play(const char* name,
&& m_priority == priority && m_speed == playback_speed)
return false;
- if (prev_action != m_action)
- {
- // First get rid of any old controllers
- ClearControllerList();
+ // First get rid of any old controllers
+ ClearControllerList();
+
+ // Create an SG_Controller
+ SG_Controller *sg_contr = BL_CreateIPO(m_action, m_obj, kxscene->GetSceneConverter());
+ m_sg_contr_list.push_back(sg_contr);
+ m_obj->GetSGNode()->AddSGController(sg_contr);
+ sg_contr->SetObject(m_obj->GetSGNode());
- // Create an SG_Controller
- SG_Controller *sg_contr = BL_CreateIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter());
+ // Try obcolor
+ sg_contr = BL_CreateObColorIPO(m_action, m_obj, 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());
+ }
- // Extra controllers
- if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT)
- {
- sg_contr = BL_CreateLampIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter());
- m_sg_contr_list.push_back(sg_contr);
- m_obj->GetSGNode()->AddSGController(sg_contr);
- sg_contr->SetObject(m_obj->GetSGNode());
+ // Now try materials
+ if (m_obj->GetBlenderObject()->totcol==1) {
+ Material *mat = give_current_material(m_obj->GetBlenderObject(), 1);
+ if (mat) {
+ sg_contr = BL_CreateMaterialIpo(m_action, mat, 0, m_obj, 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());
+ }
}
- else if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA)
- {
- sg_contr = BL_CreateCameraIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter());
- m_sg_contr_list.push_back(sg_contr);
- m_obj->GetSGNode()->AddSGController(sg_contr);
- sg_contr->SetObject(m_obj->GetSGNode());
+ } else {
+ Material *mat;
+ STR_HashedString matname;
+
+ for (int matidx = 1; matidx <= m_obj->GetBlenderObject()->totcol; ++matidx) {
+ mat = give_current_material(m_obj->GetBlenderObject(), matidx);
+ if (mat) {
+ matname = mat->id.name;
+ sg_contr = BL_CreateMaterialIpo(m_action, mat, matname.hash(), m_obj, 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());
+ }
+ }
}
}
+
+ // Extra controllers
+ if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT)
+ {
+ sg_contr = BL_CreateLampIPO(m_action, m_obj, kxscene->GetSceneConverter());
+ m_sg_contr_list.push_back(sg_contr);
+ m_obj->GetSGNode()->AddSGController(sg_contr);
+ sg_contr->SetObject(m_obj->GetSGNode());
+ }
+ else if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA)
+ {
+ sg_contr = BL_CreateCameraIPO(m_action, m_obj, kxscene->GetSceneConverter());
+ m_sg_contr_list.push_back(sg_contr);
+ m_obj->GetSGNode()->AddSGController(sg_contr);
+ sg_contr->SetObject(m_obj->GetSGNode());
+ }
m_ipo_flags = ipo_flags;
InitIPO();
@@ -200,7 +239,7 @@ bool BL_Action::Play(const char* name,
// Now that we have the previous blend shape saved, we can clear out the key to avoid any
// further interference.
KeyBlock *kb;
- for (kb=(KeyBlock*)shape_deformer->GetKey()->block.first; kb; kb=(KeyBlock*)kb->next)
+ for (kb=(KeyBlock *)shape_deformer->GetKey()->block.first; kb; kb=(KeyBlock *)kb->next)
kb->curval = 0.f;
}
}
@@ -319,9 +358,9 @@ void BL_Action::BlendShape(Key* key, float srcweight, std::vector<float>& blends
dstweight = 1.0F - srcweight;
//printf("Dst: %f\tSrc: %f\n", srcweight, dstweight);
- for (it=blendshape.begin(), kb = (KeyBlock*)key->block.first;
+ for (it=blendshape.begin(), kb = (KeyBlock *)key->block.first;
kb && it != blendshape.end();
- kb = (KeyBlock*)kb->next, it++)
+ kb = (KeyBlock *)kb->next, it++)
{
//printf("OirgKeys: %f\t%f\n", kb->curval, (*it));
kb->curval = kb->curval * dstweight + (*it) * srcweight;
@@ -439,7 +478,7 @@ void BL_Action::Update(float curtime)
// We go through and clear out the keyblocks so there isn't any interference
// from other shape actions
KeyBlock *kb;
- for (kb=(KeyBlock*)key->block.first; kb; kb=(KeyBlock*)kb->next)
+ for (kb=(KeyBlock *)key->block.first; kb; kb=(KeyBlock *)kb->next)
kb->curval = 0.f;
// Now blend the shape
@@ -458,4 +497,7 @@ void BL_Action::Update(float curtime)
m_obj->UpdateIPO(m_localtime, m_ipo_flags & ACT_IPOFLAG_CHILD);
}
+
+ if (m_done)
+ ClearControllerList();
}
diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp
index 23bfd7a111b..f5f9b344b87 100644
--- a/source/gameengine/Ketsji/BL_BlenderShader.cpp
+++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp
@@ -80,7 +80,7 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat)
{
GPUVertexAttribs attribs;
GPUMaterial *gpumat;
- int i, attrib_num;
+ int i, attrib_num, uv = 0;
ras->SetAttribNum(0);
@@ -95,21 +95,15 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat)
ras->SetTexCoordNum(0);
ras->SetAttribNum(attrib_num);
- for (i=0; i<attrib_num; i++)
+ for (i = 0; i < attrib_num; i++)
ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABLE, i);
for (i = 0; i < attribs.totlayer; i++) {
if (attribs.layer[i].glindex > attrib_num)
continue;
- if (attribs.layer[i].type == CD_MTFACE) {
- if (!mat->uvName.IsEmpty() && strcmp(mat->uvName.ReadPtr(), attribs.layer[i].name) == 0)
- ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV1, attribs.layer[i].glindex);
- else if (!mat->uv2Name.IsEmpty() && strcmp(mat->uv2Name.ReadPtr(), attribs.layer[i].name) == 0)
- ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV2, attribs.layer[i].glindex);
- else
- ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV1, attribs.layer[i].glindex);
- }
+ if (attribs.layer[i].type == CD_MTFACE)
+ ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV, attribs.layer[i].glindex, uv++);
else if (attribs.layer[i].type == CD_TANGENT)
ras->SetAttrib(RAS_IRasterizer::RAS_TEXTANGENT, attribs.layer[i].glindex);
else if (attribs.layer[i].type == CD_ORCO)
diff --git a/source/gameengine/Ketsji/BL_Material.cpp b/source/gameengine/Ketsji/BL_Material.cpp
index 0954aa0f7ab..393d00223e0 100644
--- a/source/gameengine/Ketsji/BL_Material.cpp
+++ b/source/gameengine/Ketsji/BL_Material.cpp
@@ -10,23 +10,14 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
-MTex* getImageFromMaterial(Material *mat, int index)
+MTex* getMTexFromMaterial(Material *mat, int index)
{
- if (!mat) return 0;
-
- if (!(index >=0 && index < MAX_MTEX) ) return 0;
-
- MTex *m = mat->mtex[index];
- return m?m:0;
-}
-
-int getNumTexChannels( Material *mat )
-{
- int count = -1;
- if (!mat) return -1;
-
- for (count =0; (count < 10) && mat->mtex[count] != 0; count++) {}
- return count;
+ if (mat && (index >= 0) && (index < MAX_MTEX)) {
+ return mat->mtex[index];
+ }
+ else {
+ return NULL;
+ }
}
BL_Material::BL_Material()
@@ -36,7 +27,10 @@ BL_Material::BL_Material()
void BL_Material::Initialize()
{
- m_mcol = 0xFFFFFFFFL;
+ rgb[0] = 0;
+ rgb[1] = 0;
+ rgb[2] = 0;
+ rgb[3] = 0;
IdMode = 0;
ras_mode = 0;
glslmat = 0;
@@ -64,7 +58,7 @@ void BL_Material::Initialize()
int i;
- for (i=0; i<MAXTEX; i++) // :(
+ for (i = 0; i < MAXTEX; i++) // :(
{
mapping[i].mapping = 0;
mapping[i].offsets[0] = 0.f;
@@ -90,15 +84,6 @@ void BL_Material::Initialize()
}
}
-void BL_Material::SetUVLayerName(const STR_String& name)
-{
- uvName = name;
-}
-void BL_Material::SetUVLayerName2(const STR_String& name)
-{
- uv2Name = name;
-}
-
void BL_Material::SetSharedMaterial(bool v)
{
if ((v && num_users == -1) || num_users > 1 )
diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h
index ef180ed2126..be66e2ec84d 100644
--- a/source/gameengine/Ketsji/BL_Material.h
+++ b/source/gameengine/Ketsji/BL_Material.h
@@ -87,13 +87,8 @@ public:
MTFace tface; /* copy of the derived meshes tface */
Image* img[MAXTEX];
EnvMap* cubemap[MAXTEX];
- unsigned int m_mcol; /* for text color (only) */
- STR_String uvName;
- STR_String uv2Name;
-
- void SetUVLayerName(const STR_String &name);
- void SetUVLayerName2(const STR_String &name);
+ unsigned int rgb[4];
void SetSharedMaterial(bool v);
bool IsShared();
@@ -179,8 +174,7 @@ enum BL_MappingProj
// ------------------------------------
//extern void initBL_Material(BL_Material* mat);
-extern MTex* getImageFromMaterial(Material *mat, int index);
-extern int getNumTexChannels( Material *mat );
+extern MTex* getMTexFromMaterial(Material *mat, int index);
// ------------------------------------
#endif
diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp
index 66423ed820e..98fff5c8b65 100644
--- a/source/gameengine/Ketsji/BL_Texture.cpp
+++ b/source/gameengine/Ketsji/BL_Texture.cpp
@@ -60,6 +60,7 @@ public:
typedef std::map<char*, BL_TextureObject> BL_TextureMap;
static BL_TextureMap g_textureManager;
+static GLint g_max_units = -1;
BL_Texture::BL_Texture()
@@ -379,14 +380,17 @@ unsigned int BL_Texture::GetTextureType() const
int BL_Texture::GetMaxUnits()
{
- GLint unit=0;
-
- if (GLEW_ARB_multitexture) {
- glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &unit);
- return (MAXTEX>=unit?unit:MAXTEX);
+ if (g_max_units < 0) {
+ GLint unit;
+ if (GLEW_ARB_multitexture) {
+ glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &unit);
+ g_max_units = (MAXTEX>=unit)?unit:MAXTEX;
+ } else {
+ g_max_units = 0;
+ }
}
- return 0;
+ return g_max_units;
}
void BL_Texture::ActivateFirst()
diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt
index 524a38a4c26..fa40dad21e7 100644
--- a/source/gameengine/Ketsji/CMakeLists.txt
+++ b/source/gameengine/Ketsji/CMakeLists.txt
@@ -84,6 +84,7 @@ set(SRC
KX_FontObject.cpp
KX_GameActuator.cpp
KX_GameObject.cpp
+ KX_IpoConvert.cpp
KX_IPO_SGController.cpp
KX_IPhysicsController.cpp
KX_IpoActuator.cpp
@@ -161,6 +162,7 @@ set(SRC
KX_GameActuator.h
KX_GameObject.h
KX_IInterpolator.h
+ KX_IpoConvert.h
KX_IPOTransform.h
KX_IPO_SGController.h
KX_IPhysicsController.h
@@ -220,6 +222,18 @@ set(SRC
KX_VisibilityActuator.h
KX_WorldInfo.h
KX_WorldIpoController.h
+
+ # orphan headers (not apart of a library)
+ ../Physics/common/PHY_DynamicTypes.h
+ ../Physics/common/PHY_ICharacter.h
+ ../Physics/common/PHY_IController.h
+ ../Physics/common/PHY_IGraphicController.h
+ ../Physics/common/PHY_IMotionState.h
+ ../Physics/common/PHY_IPhysicsController.h
+ ../Physics/common/PHY_IPhysicsEnvironment.h
+ ../Physics/common/PHY_IVehicle.h
+ ../Physics/common/PHY_Pro.h
+
)
add_definitions(-DGLEW_STATIC)
@@ -252,9 +266,9 @@ if(WITH_BULLET)
../Physics/Bullet
)
list(APPEND INC
- ../../../extern/bullet2/src
+ ${BULLET_INCLUDE_DIRS}
)
- add_definitions(-DUSE_BULLET)
+ add_definitions(-DWITH_BULLET)
endif()
blender_add_lib(ge_logic_ketsji "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/gameengine/Ketsji/KXNetwork/SConscript b/source/gameengine/Ketsji/KXNetwork/SConscript
index 3d696501203..40a1ec10df3 100644
--- a/source/gameengine/Ketsji/KXNetwork/SConscript
+++ b/source/gameengine/Ketsji/KXNetwork/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.cpp')
diff --git a/source/gameengine/Ketsji/KX_ArmatureSensor.cpp b/source/gameengine/Ketsji/KX_ArmatureSensor.cpp
index 523f3ceeaea..c111a4de0eb 100644
--- a/source/gameengine/Ketsji/KX_ArmatureSensor.cpp
+++ b/source/gameengine/Ketsji/KX_ArmatureSensor.cpp
@@ -80,7 +80,7 @@ void KX_ArmatureSensor::FindConstraint()
for (pchan = (bPoseChannel*)pose->chanbase.first; pchan; pchan=(bPoseChannel*)pchan->next) {
if (!strcmp(pchan->name, m_posechannel)) {
// now locate the constraint
- for (pcon = (bConstraint*)pchan->constraints.first; pcon; pcon=(bConstraint*)pcon->next) {
+ for (pcon = (bConstraint *)pchan->constraints.first; pcon; pcon = (bConstraint *)pcon->next) {
if (!strcmp(pcon->name, m_constraintname)) {
if (pcon->flag & CONSTRAINT_DISABLE)
/* this constraint is not valid, can't use it */
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
index 20c36c2cc44..231ec27030d 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
@@ -60,7 +60,8 @@ KX_BlenderMaterial::KX_BlenderMaterial()
void KX_BlenderMaterial::Initialize(
KX_Scene *scene,
BL_Material *data,
- GameSettings *game)
+ GameSettings *game,
+ int lightlayer)
{
RAS_IPolyMaterial::Initialize(
data->texname[0],
@@ -84,6 +85,7 @@ void KX_BlenderMaterial::Initialize(
mModified = 0;
mConstructed = false;
mPass = 0;
+ mLightLayer = lightlayer;
// --------------------------------
// RAS_IPolyMaterial variables...
m_flag |= RAS_BLENDERMAT;
@@ -92,16 +94,11 @@ void KX_BlenderMaterial::Initialize(
m_flag |= (mMaterial->glslmat)? RAS_BLENDERGLSL: 0;
m_flag |= ((mMaterial->ras_mode & CAST_SHADOW)!=0)? RAS_CASTSHADOW: 0;
- // figure max
- int enabled = mMaterial->num_enabled;
- int max = BL_Texture::GetMaxUnits();
- mMaterial->num_enabled = enabled>=max?max:enabled;
-
// test the sum of the various modes for equality
// so we can ether accept or reject this material
// as being equal, this is rather important to
// prevent material bleeding
- for (int i=0; i<mMaterial->num_enabled; i++) {
+ for (int i=0; i<BL_Texture::GetMaxUnits(); i++) {
m_multimode += (mMaterial->flag[i] + mMaterial->blend_mode[i]);
}
m_multimode += mMaterial->IdMode+ (mMaterial->ras_mode & ~(USE_LIGHT));
@@ -124,7 +121,7 @@ MTFace* KX_BlenderMaterial::GetMTFace(void) const
unsigned int* KX_BlenderMaterial::GetMCol(void) const
{
// fonts on polys
- return &mMaterial->m_mcol;
+ return mMaterial->rgb;
}
void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const
@@ -138,11 +135,6 @@ void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const
RAS_IPolyMaterial::GetMaterialRGBAColor(rgba);
}
-bool KX_BlenderMaterial::IsMaterial(const BL_Material *bl_mat) const
-{
- return (mMaterial == bl_mat);
-}
-
Material *KX_BlenderMaterial::GetBlenderMaterial() const
{
return mMaterial->material;
@@ -163,7 +155,7 @@ void KX_BlenderMaterial::InitTextures()
{
// for each unique material...
int i;
- for (i=0; i<mMaterial->num_enabled; i++) {
+ for (i=0; i<BL_Texture::GetMaxUnits(); i++) {
if ( mMaterial->mapping[i].mapping & USEENV ) {
if (!GLEW_ARB_texture_cube_map) {
spit("CubeMap textures not supported");
@@ -185,14 +177,14 @@ void KX_BlenderMaterial::InitTextures()
}
}
-void KX_BlenderMaterial::OnConstruction(int layer)
+void KX_BlenderMaterial::OnConstruction()
{
if (mConstructed)
// when material are reused between objects
return;
if (mMaterial->glslmat)
- SetBlenderGLSLShader(layer);
+ SetBlenderGLSLShader();
InitTextures();
@@ -239,7 +231,8 @@ void KX_BlenderMaterial::OnExit()
}
BL_Texture::ActivateFirst();
- for (int i=0; i<mMaterial->num_enabled; i++) {
+ for (int i=0; i<BL_Texture::GetMaxUnits(); i++) {
+ if (!mTextures[i].Ok()) continue;
BL_Texture::ActivateUnit(i);
mTextures[i].DeleteTex();
mTextures[i].DisableUnit();
@@ -278,7 +271,7 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras)
mShader->ApplyShader();
// for each enabled unit
- for (i=0; i<mMaterial->num_enabled; i++) {
+ for (i=0; i<BL_Texture::GetMaxUnits(); i++) {
if (!mTextures[i].Ok()) continue;
mTextures[i].ActivateTexture();
mTextures[0].SetMapping(mMaterial->mapping[i].mapping);
@@ -354,7 +347,7 @@ void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras)
}
int mode = 0,i=0;
- for (i=0; (i<mMaterial->num_enabled && i<MAXTEX); i++) {
+ for (i=0; i<BL_Texture::GetMaxUnits(); i++) {
if ( !mTextures[i].Ok() ) continue;
mTextures[i].ActivateTexture();
@@ -407,6 +400,8 @@ KX_BlenderMaterial::ActivatShaders(
if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
tmp->setShaderData(true, rasty);
+ else if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW && IsAlpha() && !rasty->GetUsingOverrideShader())
+ tmp->setShaderData(true, rasty);
else
tmp->setShaderData(false, rasty);
@@ -452,6 +447,8 @@ KX_BlenderMaterial::ActivateBlenderShaders(
if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
tmp->setBlenderShaderData(true, rasty);
+ else if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW && IsAlpha() && !rasty->GetUsingOverrideShader())
+ tmp->setBlenderShaderData(true, rasty);
else
tmp->setBlenderShaderData(false, rasty);
@@ -501,6 +498,8 @@ KX_BlenderMaterial::ActivateMat(
if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
tmp->setTexData( true,rasty );
+ else if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW && IsAlpha() && !rasty->GetUsingOverrideShader())
+ tmp->setTexData(true, rasty);
else
tmp->setTexData( false,rasty);
@@ -635,7 +634,8 @@ void KX_BlenderMaterial::ActivatGLMaterials( RAS_IRasterizer* rasty )const
void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const
{
- if (ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) {
+ if (ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED ||
+ (ras->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW && IsAlpha() && !ras->GetUsingOverrideShader())) {
ras->SetAttribNum(0);
if (mShader && GLEW_ARB_shader_objects) {
if (mShader->GetAttribute() == BL_Shader::SHD_TANGENT) {
@@ -647,16 +647,9 @@ void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const
ras->SetTexCoordNum(mMaterial->num_enabled);
- for (int i=0; i<mMaterial->num_enabled; i++) {
+ for (int i=0; i<BL_Texture::GetMaxUnits(); i++) {
int mode = mMaterial->mapping[i].mapping;
- if (mode &USECUSTOMUV)
- {
- if (!mMaterial->mapping[i].uvCoName.IsEmpty())
- ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV2, i);
- continue;
- }
-
if ( mode &(USEREFL|USEOBJ))
ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_GEN, i);
else if (mode &USEORCO)
@@ -664,7 +657,7 @@ void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const
else if (mode &USENORM)
ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_NORM, i);
else if (mode &USEUV)
- ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV1, i);
+ ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV, i);
else if (mode &USETANG)
ras->SetTexCoord(RAS_IRasterizer::RAS_TEXTANGENT, i);
else
@@ -790,10 +783,19 @@ void KX_BlenderMaterial::UpdateIPO(
mMaterial->ref = (float)(ref);
}
-void KX_BlenderMaterial::SetBlenderGLSLShader(int layer)
+void KX_BlenderMaterial::Replace_IScene(SCA_IScene *val)
+{
+ mScene= static_cast<KX_Scene *>(val);
+ if (mBlenderShader)
+ mBlenderShader->SetScene(mScene);
+
+ OnConstruction();
+}
+
+void KX_BlenderMaterial::SetBlenderGLSLShader()
{
if (!mBlenderShader)
- mBlenderShader = new BL_BlenderShader(mScene, mMaterial->material, layer);
+ mBlenderShader = new BL_BlenderShader(mScene, mMaterial->material, mLightLayer);
if (!mBlenderShader->Ok()) {
delete mBlenderShader;
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h
index 7bc9c7c3863..c34a49e1bde 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.h
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h
@@ -39,7 +39,8 @@ public:
void Initialize(
class KX_Scene* scene,
BL_Material* mat,
- GameSettings* game
+ GameSettings* game,
+ int lightlayer
);
virtual ~KX_BlenderMaterial();
@@ -76,8 +77,6 @@ public:
TCachingInfo& cachingInfo
)const;
- /* mMaterial is private, but need this for conversion */
- bool IsMaterial(const BL_Material *bl_mat) const;
Material* GetBlenderMaterial() const;
MTFace* GetMTFace(void) const;
unsigned int* GetMCol(void) const;
@@ -97,14 +96,7 @@ public:
MT_Scalar ref, MT_Scalar emit, MT_Scalar alpha
);
- virtual void Replace_IScene(SCA_IScene *val)
- {
- mScene= static_cast<KX_Scene *>(val);
- if (mBlenderShader)
- {
- mBlenderShader->SetScene(mScene);
- }
- };
+ virtual void Replace_IScene(SCA_IScene *val);
#ifdef WITH_PYTHON
// --------------------------------
@@ -125,7 +117,7 @@ public:
// --------------------------------
// pre calculate to avoid pops/lag at startup
- virtual void OnConstruction(int layer);
+ virtual void OnConstruction();
static void EndFrame();
@@ -139,10 +131,11 @@ private:
unsigned int mBlendFunc[2];
bool mModified;
bool mConstructed; // if false, don't clean on exit
+ int mLightLayer;
void InitTextures();
- void SetBlenderGLSLShader(int layer);
+ void SetBlenderGLSLShader();
void ActivatGLMaterials( RAS_IRasterizer* rasty )const;
void ActivateTexGen( RAS_IRasterizer *ras ) const;
diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
index 20c41b95dd3..262ec541cf9 100644
--- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
+++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
@@ -4,7 +4,7 @@
//under visual studio the #define in KX_ConvertPhysicsObject.h is quicker for recompilation
#include "KX_ConvertPhysicsObject.h"
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
#include "KX_BulletPhysicsController.h"
@@ -75,6 +75,11 @@ void KX_BulletPhysicsController::SetLinVelocityMin(float val)
CcdPhysicsController::SetLinVelocityMin(val);
}
+void KX_BulletPhysicsController::Jump()
+{
+ CcdPhysicsController::Jump();
+}
+
float KX_BulletPhysicsController::GetLinVelocityMax()
{
return (float)CcdPhysicsController::GetLinVelocityMax();
@@ -119,6 +124,11 @@ void KX_BulletPhysicsController::RelativeTranslate(const MT_Vector3& dloc,bool l
}
+void KX_BulletPhysicsController::SetWalkDirection(const MT_Vector3& dloc,bool local)
+{
+ CcdPhysicsController::SetWalkDirection(dloc[0],dloc[1],dloc[2],local);
+}
+
void KX_BulletPhysicsController::RelativeRotate(const MT_Matrix3x3& drot,bool local)
{
float rotval[9];
@@ -155,6 +165,13 @@ MT_Vector3 KX_BulletPhysicsController::GetVelocity(const MT_Point3& pos)
return MT_Vector3(linVel[0],linVel[1],linVel[2]);
}
+MT_Vector3 KX_BulletPhysicsController::GetWalkDirection()
+{
+ float dir[3];
+ CcdPhysicsController::GetWalkDirection(dir[0], dir[1], dir[2]);
+ return MT_Vector3(dir[0], dir[1], dir[2]);
+}
+
void KX_BulletPhysicsController::SetAngularVelocity(const MT_Vector3& ang_vel,bool local)
{
CcdPhysicsController::SetAngularVelocity(ang_vel.x(),ang_vel.y(),ang_vel.z(),local);
@@ -536,4 +553,4 @@ const char* KX_BulletPhysicsController::getName()
return 0;
}
-#endif // USE_BULLET
+#endif // WITH_BULLET
diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.h b/source/gameengine/Ketsji/KX_BulletPhysicsController.h
index 4813b39a34e..3d13744567b 100644
--- a/source/gameengine/Ketsji/KX_BulletPhysicsController.h
+++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.h
@@ -8,7 +8,7 @@
#include "KX_IPhysicsController.h"
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
#include "CcdPhysicsController.h"
#endif
@@ -25,7 +25,7 @@ private:
btCollisionShape* m_bulletChildShape;
public:
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna, bool sensor, bool character, bool compound);
virtual ~KX_BulletPhysicsController ();
#endif
@@ -40,11 +40,14 @@ public:
virtual void RelativeRotate(const MT_Matrix3x3& drot,bool local);
virtual void ApplyTorque(const MT_Vector3& torque,bool local);
virtual void ApplyForce(const MT_Vector3& force,bool local);
+ virtual void SetWalkDirection(const MT_Vector3& dir,bool local);
virtual MT_Vector3 GetLinearVelocity();
virtual MT_Vector3 GetAngularVelocity();
virtual MT_Vector3 GetVelocity(const MT_Point3& pos);
+ virtual MT_Vector3 GetWalkDirection();
virtual void SetAngularVelocity(const MT_Vector3& ang_vel,bool local);
virtual void SetLinearVelocity(const MT_Vector3& lin_vel,bool local);
+ virtual void Jump();
virtual void getOrientation(MT_Quaternion& orn);
virtual void setOrientation(const MT_Matrix3x3& orn);
virtual void setPosition(const MT_Point3& pos);
diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp
index 792a0759b59..acf30b4866c 100644
--- a/source/gameengine/Ketsji/KX_CameraActuator.cpp
+++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp
@@ -36,7 +36,6 @@
#include "BLI_math_vector.h"
#include "KX_CameraActuator.h"
-#include <iostream>
#include <math.h>
#include <float.h>
#include "KX_GameObject.h"
@@ -197,7 +196,7 @@ bool KX_CameraActuator::Update(double curtime, bool frame)
MT_Point3 lookat = ((KX_GameObject*)m_ob)->NodeGetWorldPosition();
MT_Matrix3x3 actormat = ((KX_GameObject*)m_ob)->NodeGetWorldOrientation();
- float fp1[3], fp2[3], rc[3];
+ float fp1[3]={0}, fp2[3]={0}, rc[3];
float inp, fac; //, factor = 0.0; /* some factor... */
float mindistsq, maxdistsq, distsq;
float mat[3][3];
diff --git a/source/gameengine/Ketsji/KX_CharacterWrapper.cpp b/source/gameengine/Ketsji/KX_CharacterWrapper.cpp
index ce208f3a75f..3fbddef89be 100644
--- a/source/gameengine/Ketsji/KX_CharacterWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_CharacterWrapper.cpp
@@ -5,6 +5,7 @@
#include "KX_CharacterWrapper.h"
#include "PHY_ICharacter.h"
+#include "KX_PyMath.h"
KX_CharacterWrapper::KX_CharacterWrapper(PHY_ICharacter* character) :
PyObjectPlus(),
@@ -45,6 +46,9 @@ PyTypeObject KX_CharacterWrapper::Type = {
PyAttributeDef KX_CharacterWrapper::Attributes[] = {
KX_PYATTRIBUTE_RO_FUNCTION("onGround", KX_CharacterWrapper, pyattr_get_onground),
KX_PYATTRIBUTE_RW_FUNCTION("gravity", KX_CharacterWrapper, pyattr_get_gravity, pyattr_set_gravity),
+ KX_PYATTRIBUTE_RW_FUNCTION("maxJumps", KX_CharacterWrapper, pyattr_get_max_jumps, pyattr_set_max_jumps),
+ KX_PYATTRIBUTE_RO_FUNCTION("jumpCount", KX_CharacterWrapper, pyattr_get_jump_count),
+ KX_PYATTRIBUTE_RW_FUNCTION("walkDirection", KX_CharacterWrapper, pyattr_get_walk_dir, pyattr_set_walk_dir),
{ NULL } //Sentinel
};
@@ -77,6 +81,55 @@ int KX_CharacterWrapper::pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_D
return PY_SET_ATTR_SUCCESS;
}
+PyObject *KX_CharacterWrapper::pyattr_get_max_jumps(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_CharacterWrapper* self = static_cast<KX_CharacterWrapper*>(self_v);
+
+ return PyLong_FromLong(self->m_character->GetMaxJumps());
+}
+
+int KX_CharacterWrapper::pyattr_set_max_jumps(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_CharacterWrapper* self = static_cast<KX_CharacterWrapper*>(self_v);
+ long param = PyLong_AsLong(value);
+
+ if (param == -1)
+ {
+ PyErr_SetString(PyExc_ValueError, "KX_CharacterWrapper.maxJumps: expected an integer");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ self->m_character->SetMaxJumps((int)param);
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_CharacterWrapper::pyattr_get_jump_count(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_CharacterWrapper* self = static_cast<KX_CharacterWrapper*>(self_v);
+
+ return PyLong_FromLong(self->m_character->GetJumpCount());
+}
+
+PyObject *KX_CharacterWrapper::pyattr_get_walk_dir(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_CharacterWrapper* self = static_cast<KX_CharacterWrapper*>(self_v);
+
+ return PyObjectFrom(self->m_character->GetWalkDirection());
+}
+
+int KX_CharacterWrapper::pyattr_set_walk_dir(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_CharacterWrapper* self = static_cast<KX_CharacterWrapper*>(self_v);
+ MT_Vector3 dir;
+ if (!PyVecTo(value, dir)) {
+ PyErr_SetString(PyExc_TypeError, "KX_CharacterWrapper.walkDirection: expected a vector");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ self->m_character->SetWalkDirection(dir);
+ return PY_SET_ATTR_SUCCESS;
+}
+
PyMethodDef KX_CharacterWrapper::Methods[] = {
KX_PYMETHODTABLE_NOARGS(KX_CharacterWrapper, jump),
{NULL,NULL} //Sentinel
diff --git a/source/gameengine/Ketsji/KX_CharacterWrapper.h b/source/gameengine/Ketsji/KX_CharacterWrapper.h
index 3b0058aca6f..d4d8f195102 100644
--- a/source/gameengine/Ketsji/KX_CharacterWrapper.h
+++ b/source/gameengine/Ketsji/KX_CharacterWrapper.h
@@ -26,6 +26,11 @@ public:
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);
+ static PyObject* pyattr_get_max_jumps(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_max_jumps(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_jump_count(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject* pyattr_get_walk_dir(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_walk_dir(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
#endif // WITH_PYTHON
private:
diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
index e71037d08a0..903966b79be 100644
--- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
+++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
@@ -145,7 +145,7 @@ void KX_ConvertDynamoObject(KX_GameObject* gameobj,
struct KX_ObjectProperties* objprop);
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
void KX_ConvertBulletObject( class KX_GameObject* gameobj,
class RAS_MeshObject* meshobj,
diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
index ff3c46cb8ab..ece6abc9447 100644
--- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
+++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
@@ -58,7 +58,7 @@ extern "C"{
#include "BKE_DerivedMesh.h"
}
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
#include "BulletSoftBody/btSoftBody.h"
#include "CcdPhysicsEnvironment.h"
@@ -68,8 +68,8 @@ extern "C"{
#include "KX_BulletPhysicsController.h"
#include "btBulletDynamicsCommon.h"
- #ifdef WIN32
-#if _MSC_VER >= 1310
+#ifdef WIN32
+#if defined(_MSC_VER) && (_MSC_VER >= 1310)
//only use SIMD Hull code under Win32
//#define TEST_HULL 1
#ifdef TEST_HULL
@@ -574,4 +574,4 @@ bool KX_ReInstanceBulletShapeFromMesh(KX_GameObject *gameobj, KX_GameObject *fro
spc->ReplaceControllerShape(bm);
return true;
}
-#endif // USE_BULLET
+#endif // WITH_BULLET
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index c7f6954fd6c..ae5758b8597 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -42,7 +42,6 @@ typedef unsigned __int64 uint_ptr;
typedef unsigned long uint_ptr;
#endif
-#define KX_INERTIA_INFINITE 10000
#include "RAS_IPolygonMaterial.h"
#include "KX_BlenderMaterial.h"
#include "KX_GameObject.h"
@@ -1401,6 +1400,14 @@ CListValue* KX_GameObject::GetChildrenRecursive()
return list;
}
+KX_Scene* KX_GameObject::GetScene()
+{
+ SG_Node* node = this->GetSGNode();
+ KX_Scene* scene = static_cast<KX_Scene*>(node->GetSGClientInfo());
+
+ return scene;
+}
+
/* ---------------------------------------------------------------------
* Some stuff taken from the header
* --------------------------------------------------------------------- */
@@ -1755,8 +1762,7 @@ PyObject *KX_GameObject::PyReplaceMesh(PyObject *args)
PyObject *KX_GameObject::PyEndObject()
{
- SG_Node* node = this->GetSGNode();
- KX_Scene* scene = static_cast<KX_Scene*>(node->GetSGClientInfo());
+ KX_Scene* scene = GetScene();
scene->DelayedRemoveObject(this);
@@ -1778,7 +1784,7 @@ PyObject *KX_GameObject::PyReinstancePhysicsMesh(PyObject *args)
) {
return NULL;
}
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
/* gameobj and mesh can be NULL */
if (KX_ReInstanceBulletShapeFromMesh(this, gameobj, mesh))
Py_RETURN_TRUE;
@@ -2004,8 +2010,7 @@ PyObject *KX_GameObject::pyattr_get_group_members(void *self_v, const KX_PYATTRI
PyObject* KX_GameObject::pyattr_get_scene(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
- SG_Node *node = self->GetSGNode();
- KX_Scene *scene = static_cast<KX_Scene *>(node->GetSGClientInfo());
+ KX_Scene *scene = self->GetScene();
if (scene) {
return scene->GetProxy();
}
@@ -2737,11 +2742,11 @@ PyObject *KX_GameObject::PyGetReactionForce()
// only can get the velocity if we have a physics object connected to us...
// XXX - Currently not working with bullet intergration, see KX_BulletPhysicsController.cpp's getReactionForce
- /*
+#if 0
if (GetPhysicsController())
return PyObjectFrom(GetPhysicsController()->getReactionForce());
return PyObjectFrom(dummy_point);
- */
+#endif
return Py_BuildValue("fff", 0.0, 0.0, 0.0);
@@ -3057,7 +3062,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
if (dist != 0.0f)
toPoint = fromPoint + dist * (toPoint-fromPoint).safe_normalized();
- PHY_IPhysicsEnvironment* pe = KX_GetActiveScene()->GetPhysicsEnvironment();
+ PHY_IPhysicsEnvironment* pe = GetScene()->GetPhysicsEnvironment();
KX_IPhysicsController *spc = GetPhysicsController();
KX_GameObject *parent = GetParent();
if (!spc && parent)
@@ -3203,7 +3208,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
return none_tuple_3();
}
- PHY_IPhysicsEnvironment* pe = KX_GetActiveScene()->GetPhysicsEnvironment();
+ PHY_IPhysicsEnvironment* pe = GetScene()->GetPhysicsEnvironment();
KX_IPhysicsController *spc = GetPhysicsController();
KX_GameObject *parent = GetParent();
if (!spc && parent)
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index e71af674a79..86c712ea017 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -501,8 +501,8 @@ public:
void SetUserCollisionGroup(short filter);
void SetUserCollisionMask(short mask);
/**
- * Extra broadphase check for user controllable collisions
- */
+ * Extra broadphase check for user controllable collisions
+ */
bool CheckCollision(KX_GameObject *other);
/**
@@ -923,6 +923,8 @@ public:
CListValue* GetChildren();
CListValue* GetChildrenRecursive();
+ KX_Scene* GetScene();
+
#ifdef WITH_PYTHON
/**
* \section Python interface functions.
diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.h b/source/gameengine/Ketsji/KX_IPhysicsController.h
index 280b1816a1e..2019be57679 100644
--- a/source/gameengine/Ketsji/KX_IPhysicsController.h
+++ b/source/gameengine/Ketsji/KX_IPhysicsController.h
@@ -70,11 +70,14 @@ public:
virtual void RelativeRotate(const MT_Matrix3x3& drot,bool local)=0;
virtual void ApplyTorque(const MT_Vector3& torque,bool local)=0;
virtual void ApplyForce(const MT_Vector3& force,bool local)=0;
+ virtual void SetWalkDirection(const MT_Vector3& dir,bool local)=0;
virtual MT_Vector3 GetLinearVelocity()=0;
virtual MT_Vector3 GetAngularVelocity()=0;
virtual MT_Vector3 GetVelocity(const MT_Point3& pos)=0;
+ virtual MT_Vector3 GetWalkDirection()=0;
virtual void SetAngularVelocity(const MT_Vector3& ang_vel,bool local)=0;
virtual void SetLinearVelocity(const MT_Vector3& lin_vel,bool local)=0;
+ virtual void Jump()=0;
virtual void resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ) = 0;
virtual void getOrientation(MT_Quaternion& orn)=0;
diff --git a/source/gameengine/Ketsji/KX_ISceneConverter.h b/source/gameengine/Ketsji/KX_ISceneConverter.h
index 18fb336dbe0..616895a8269 100644
--- a/source/gameengine/Ketsji/KX_ISceneConverter.h
+++ b/source/gameengine/Ketsji/KX_ISceneConverter.h
@@ -57,10 +57,14 @@ public:
virtual void ConvertScene(
class KX_Scene* destinationscene,
class RAS_IRenderTools* rendertools,
- class RAS_ICanvas* canvas)=0;
+ class RAS_ICanvas* canvas,
+ bool libloading=false)=0;
virtual void RemoveScene(class KX_Scene *scene)=0;
+ // handle any pending merges from asynchronous loads
+ virtual void MergeAsyncLoads()=0;
+
virtual void SetAlwaysUseExpandFraming(bool to_what) = 0;
virtual void SetNewFileName(const STR_String& filename) = 0;
@@ -85,6 +89,10 @@ public:
virtual void SetGLSLMaterials(bool val) =0;
virtual bool GetGLSLMaterials()=0;
+ // cache materials during conversion
+ virtual void SetCacheMaterials(bool val) =0;
+ virtual bool GetCacheMaterials()=0;
+
virtual struct Scene* GetBlenderSceneForName(const STR_String& name)=0;
diff --git a/source/gameengine/Converter/KX_IpoConvert.cpp b/source/gameengine/Ketsji/KX_IpoConvert.cpp
index a81d52f6698..57130bf57b2 100644
--- a/source/gameengine/Converter/KX_IpoConvert.cpp
+++ b/source/gameengine/Ketsji/KX_IpoConvert.cpp
@@ -25,7 +25,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file gameengine/Converter/KX_IpoConvert.cpp
+/** \file gameengine/Ketsji/KX_IpoConvert.cpp
* \ingroup bgeconv
*/
@@ -162,32 +162,29 @@ SG_Controller *BL_CreateIPO(struct bAction *action, KX_GameObject* gameobj, KX_B
}
}
- {
- KX_ObColorIpoSGController* ipocontr_obcol=NULL;
-
- for (int i=0; i<4; i++) {
- if ((interp = adtList->GetScalarInterpolator("color", i))) {
- if (!ipocontr_obcol) {
- ipocontr_obcol = new KX_ObColorIpoSGController();
- gameobj->GetSGNode()->AddSGController(ipocontr_obcol);
- ipocontr_obcol->SetObject(gameobj->GetSGNode());
- }
- interpolator= new KX_ScalarInterpolator(&ipocontr_obcol->m_rgba[i], interp);
- ipocontr_obcol->AddInterpolator(interpolator);
- }
- }
- }
return ipocontr;
}
-void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_BlenderSceneConverter *converter)
+
+SG_Controller *BL_CreateObColorIPO(struct bAction *action, KX_GameObject* gameobj, KX_BlenderSceneConverter *converter)
{
- if (blenderobject->adt) {
- SG_Controller *ipocontr = BL_CreateIPO(blenderobject->adt->action, gameobj, converter);
- gameobj->GetSGNode()->AddSGController(ipocontr);
- ipocontr->SetObject(gameobj->GetSGNode());
+ KX_ObColorIpoSGController* ipocontr_obcol=NULL;
+ KX_IInterpolator *interpolator;
+ KX_IScalarInterpolator *interp;
+ BL_InterpolatorList *adtList= GetAdtList(action, converter);
+
+ for (int i=0; i<4; i++) {
+ if ((interp = adtList->GetScalarInterpolator("color", i))) {
+ if (!ipocontr_obcol) {
+ ipocontr_obcol = new KX_ObColorIpoSGController();
+ }
+ interpolator= new KX_ScalarInterpolator(&ipocontr_obcol->m_rgba[i], interp);
+ ipocontr_obcol->AddInterpolator(interpolator);
+ }
}
+
+ return ipocontr_obcol;
}
SG_Controller *BL_CreateLampIPO(struct bAction *action, KX_GameObject* lightobj, KX_BlenderSceneConverter *converter)
@@ -233,19 +230,6 @@ SG_Controller *BL_CreateLampIPO(struct bAction *action, KX_GameObject* lightobj
return ipocontr;
}
-void BL_ConvertLampIpos(struct Lamp* blenderlamp, KX_GameObject *lightobj,KX_BlenderSceneConverter *converter)
-{
-
- if (blenderlamp->adt) {
-
- SG_Controller* ipocontr = BL_CreateLampIPO(blenderlamp->adt->action, lightobj, converter);
- lightobj->GetSGNode()->AddSGController(ipocontr);
- ipocontr->SetObject(lightobj->GetSGNode());
-
-
- }
-}
-
SG_Controller *BL_CreateCameraIPO(struct bAction *action, KX_GameObject* cameraobj, KX_BlenderSceneConverter *converter)
{
KX_CameraIpoSGController* ipocontr = new KX_CameraIpoSGController();
@@ -285,17 +269,6 @@ SG_Controller *BL_CreateCameraIPO(struct bAction *action, KX_GameObject* camera
return ipocontr;
}
-void BL_ConvertCameraIpos(struct Camera* blendercamera, KX_GameObject *cameraobj,KX_BlenderSceneConverter *converter)
-{
-
- if (blendercamera->adt) {
- SG_Controller* ipocontr = BL_CreateCameraIPO(blendercamera->adt->action, cameraobj, converter);
- cameraobj->GetSGNode()->AddSGController(ipocontr);
- ipocontr->SetObject(cameraobj->GetSGNode());
- }
-}
-
-
void BL_ConvertWorldIpos(struct World* blenderworld,KX_BlenderSceneConverter *converter)
{
@@ -344,141 +317,97 @@ void BL_ConvertWorldIpos(struct World* blenderworld,KX_BlenderSceneConverter *co
}
}
-static void ConvertMaterialIpos(
+SG_Controller *BL_CreateMaterialIpo(
+ struct bAction *action,
Material* blendermaterial,
dword matname_hash,
KX_GameObject* gameobj,
KX_BlenderSceneConverter *converter
)
{
- if (blendermaterial->adt) {
- KX_MaterialIpoController* ipocontr = new KX_MaterialIpoController(matname_hash);
- gameobj->GetSGNode()->AddSGController(ipocontr);
- ipocontr->SetObject(gameobj->GetSGNode());
-
- BL_InterpolatorList *adtList= GetAdtList(blendermaterial->adt->action, converter);
+ KX_MaterialIpoController* ipocontr = NULL;
+ BL_InterpolatorList *adtList= GetAdtList(action, converter);
+ KX_IInterpolator *interpolator;
+ KX_IScalarInterpolator *sinterp;
- ipocontr->m_rgba[0] = blendermaterial->r;
- ipocontr->m_rgba[1] = blendermaterial->g;
- ipocontr->m_rgba[2] = blendermaterial->b;
- ipocontr->m_rgba[3] = blendermaterial->alpha;
-
- ipocontr->m_specrgb[0] = blendermaterial->specr;
- ipocontr->m_specrgb[1] = blendermaterial->specg;
- ipocontr->m_specrgb[2] = blendermaterial->specb;
-
- ipocontr->m_hard = blendermaterial->har;
- ipocontr->m_spec = blendermaterial->spec;
- ipocontr->m_ref = blendermaterial->ref;
- ipocontr->m_emit = blendermaterial->emit;
- ipocontr->m_alpha = blendermaterial->alpha;
-
- KX_IInterpolator *interpolator;
- KX_IScalarInterpolator *sinterp;
-
- // --
- for (int i=0; i<3; i++) {
- if ((sinterp = adtList->GetScalarInterpolator("diffuse_color", i))) {
- if (!ipocontr) {
- ipocontr = new KX_MaterialIpoController(matname_hash);
- gameobj->GetSGNode()->AddSGController(ipocontr);
- ipocontr->SetObject(gameobj->GetSGNode());
- }
- interpolator= new KX_ScalarInterpolator(&ipocontr->m_rgba[i], sinterp);
- ipocontr->AddInterpolator(interpolator);
- }
- }
-
- if ((sinterp = adtList->GetScalarInterpolator("alpha", 0))) {
+ // --
+ for (int i=0; i<3; i++) {
+ if ((sinterp = adtList->GetScalarInterpolator("diffuse_color", i))) {
if (!ipocontr) {
ipocontr = new KX_MaterialIpoController(matname_hash);
- gameobj->GetSGNode()->AddSGController(ipocontr);
- ipocontr->SetObject(gameobj->GetSGNode());
}
- interpolator= new KX_ScalarInterpolator(&ipocontr->m_rgba[3], sinterp);
+ interpolator= new KX_ScalarInterpolator(&ipocontr->m_rgba[i], sinterp);
ipocontr->AddInterpolator(interpolator);
}
+ }
- for (int i=0; i<3; i++) {
- if ((sinterp = adtList->GetScalarInterpolator("specular_color", i))) {
- if (!ipocontr) {
- ipocontr = new KX_MaterialIpoController(matname_hash);
- gameobj->GetSGNode()->AddSGController(ipocontr);
- ipocontr->SetObject(gameobj->GetSGNode());
- }
- interpolator= new KX_ScalarInterpolator(&ipocontr->m_specrgb[i], sinterp);
- ipocontr->AddInterpolator(interpolator);
- }
- }
-
- if ((sinterp = adtList->GetScalarInterpolator("specular_hardness", 0))) {
- if (!ipocontr) {
- ipocontr = new KX_MaterialIpoController(matname_hash);
- gameobj->GetSGNode()->AddSGController(ipocontr);
- ipocontr->SetObject(gameobj->GetSGNode());
- }
- interpolator= new KX_ScalarInterpolator(&ipocontr->m_hard, sinterp);
- ipocontr->AddInterpolator(interpolator);
+ if ((sinterp = adtList->GetScalarInterpolator("alpha", 0))) {
+ if (!ipocontr) {
+ ipocontr = new KX_MaterialIpoController(matname_hash);
}
+ interpolator= new KX_ScalarInterpolator(&ipocontr->m_rgba[3], sinterp);
+ ipocontr->AddInterpolator(interpolator);
+ }
- if ((sinterp = adtList->GetScalarInterpolator("specularity", 0))) {
+ for (int i=0; i<3; i++) {
+ if ((sinterp = adtList->GetScalarInterpolator("specular_color", i))) {
if (!ipocontr) {
ipocontr = new KX_MaterialIpoController(matname_hash);
- gameobj->GetSGNode()->AddSGController(ipocontr);
- ipocontr->SetObject(gameobj->GetSGNode());
}
- interpolator= new KX_ScalarInterpolator(&ipocontr->m_spec, sinterp);
+ interpolator= new KX_ScalarInterpolator(&ipocontr->m_specrgb[i], sinterp);
ipocontr->AddInterpolator(interpolator);
}
-
- if ((sinterp = adtList->GetScalarInterpolator("diffuse_reflection", 0))) {
- if (!ipocontr) {
- ipocontr = new KX_MaterialIpoController(matname_hash);
- gameobj->GetSGNode()->AddSGController(ipocontr);
- ipocontr->SetObject(gameobj->GetSGNode());
- }
- interpolator= new KX_ScalarInterpolator(&ipocontr->m_ref, sinterp);
- ipocontr->AddInterpolator(interpolator);
+ }
+
+ if ((sinterp = adtList->GetScalarInterpolator("specular_hardness", 0))) {
+ if (!ipocontr) {
+ ipocontr = new KX_MaterialIpoController(matname_hash);
}
-
- if ((sinterp = adtList->GetScalarInterpolator("emit", 0))) {
- if (!ipocontr) {
- ipocontr = new KX_MaterialIpoController(matname_hash);
- gameobj->GetSGNode()->AddSGController(ipocontr);
- ipocontr->SetObject(gameobj->GetSGNode());
- }
- interpolator= new KX_ScalarInterpolator(&ipocontr->m_emit, sinterp);
- ipocontr->AddInterpolator(interpolator);
+ interpolator= new KX_ScalarInterpolator(&ipocontr->m_hard, sinterp);
+ ipocontr->AddInterpolator(interpolator);
+ }
+
+ if ((sinterp = adtList->GetScalarInterpolator("specularity", 0))) {
+ if (!ipocontr) {
+ ipocontr = new KX_MaterialIpoController(matname_hash);
}
+ interpolator= new KX_ScalarInterpolator(&ipocontr->m_spec, sinterp);
+ ipocontr->AddInterpolator(interpolator);
}
-}
-void BL_ConvertMaterialIpos(
- struct Object* blenderobject,
- KX_GameObject* gameobj,
- KX_BlenderSceneConverter *converter
- )
-{
- if (blenderobject->totcol==1)
- {
- Material *mat = give_current_material(blenderobject, 1);
- // if there is only one material attached to the mesh then set material_index in BL_ConvertMaterialIpos to NULL
- // --> this makes the UpdateMaterialData function in KX_GameObject.cpp use the old hack of using SetObjectColor
- // because this yields a better performance as not all the vertex colors need to be edited
- if (mat) ConvertMaterialIpos(mat, 0, gameobj, converter);
+ if ((sinterp = adtList->GetScalarInterpolator("diffuse_reflection", 0))) {
+ if (!ipocontr) {
+ ipocontr = new KX_MaterialIpoController(matname_hash);
+ }
+ interpolator= new KX_ScalarInterpolator(&ipocontr->m_ref, sinterp);
+ ipocontr->AddInterpolator(interpolator);
}
- else
- {
- for (int material_index=1; material_index <= blenderobject->totcol; material_index++)
- {
- Material *mat = give_current_material(blenderobject, material_index);
- STR_HashedString matname;
- if (mat) {
- matname= mat->id.name; // who is using this name? can we remove the MA here?
- ConvertMaterialIpos(mat, matname.hash(), gameobj, converter);
- }
+
+ if ((sinterp = adtList->GetScalarInterpolator("emit", 0))) {
+ if (!ipocontr) {
+ ipocontr = new KX_MaterialIpoController(matname_hash);
}
+ interpolator= new KX_ScalarInterpolator(&ipocontr->m_emit, sinterp);
+ ipocontr->AddInterpolator(interpolator);
}
-}
+ if (ipocontr) {
+ ipocontr->m_rgba[0] = blendermaterial->r;
+ ipocontr->m_rgba[1] = blendermaterial->g;
+ ipocontr->m_rgba[2] = blendermaterial->b;
+ ipocontr->m_rgba[3] = blendermaterial->alpha;
+
+ ipocontr->m_specrgb[0] = blendermaterial->specr;
+ ipocontr->m_specrgb[1] = blendermaterial->specg;
+ ipocontr->m_specrgb[2] = blendermaterial->specb;
+
+ ipocontr->m_hard = blendermaterial->har;
+ ipocontr->m_spec = blendermaterial->spec;
+ ipocontr->m_ref = blendermaterial->ref;
+ ipocontr->m_emit = blendermaterial->emit;
+ ipocontr->m_alpha = blendermaterial->alpha;
+ }
+
+ return ipocontr;
+}
diff --git a/source/gameengine/Converter/KX_IpoConvert.h b/source/gameengine/Ketsji/KX_IpoConvert.h
index 861a2ba66f2..a653e4e110b 100644
--- a/source/gameengine/Converter/KX_IpoConvert.h
+++ b/source/gameengine/Ketsji/KX_IpoConvert.h
@@ -33,37 +33,36 @@
#define __KX_IPOCONVERT_H__
struct Object;
+struct bAction;
+class SG_Controller;
+class KX_GameObject;
+class KX_BlenderSceneConverter;
-class SG_Controller *BL_CreateIPO(struct bAction *action,
- class KX_GameObject* gameobj,
- class KX_BlenderSceneConverter *converter);
+SG_Controller *BL_CreateIPO(bAction *action,
+ KX_GameObject* gameobj,
+ KX_BlenderSceneConverter *converter);
-void BL_ConvertIpos(struct Object* blenderobject,
- class KX_GameObject* gameobj,
- class KX_BlenderSceneConverter *converter);
+SG_Controller *BL_CreateObColorIPO(bAction *action,
+ KX_GameObject* gameobj,
+ KX_BlenderSceneConverter *converter);
-class SG_Controller *BL_CreateLampIPO(struct bAction *action,
- class KX_GameObject* lightobj,
- class KX_BlenderSceneConverter *converter);
-
-void BL_ConvertLampIpos(struct Lamp* blenderlight,
- class KX_GameObject* lightobj,
- class KX_BlenderSceneConverter *converter);
+SG_Controller *BL_CreateLampIPO(bAction *action,
+ KX_GameObject* lightobj,
+ KX_BlenderSceneConverter *converter);
void BL_ConvertWorldIpos(struct World* blenderworld,
- class KX_BlenderSceneConverter *converter);
-
-class SG_Controller *BL_CreateCameraIPO(struct bAction *action,
- class KX_GameObject* cameraobj,
- class KX_BlenderSceneConverter *converter);
+ KX_BlenderSceneConverter *converter);
-void BL_ConvertCameraIpos(struct Camera* blendercamera,
- class KX_GameObject* cameraobj,
- class KX_BlenderSceneConverter *converter);
+SG_Controller *BL_CreateCameraIPO(bAction *action,
+ KX_GameObject* cameraobj,
+ KX_BlenderSceneConverter *converter);
-void BL_ConvertMaterialIpos(struct Object* blenderobject,
- class KX_GameObject* materialobj,
- class KX_BlenderSceneConverter *converter);
+SG_Controller *BL_CreateMaterialIpo(
+ bAction *action,
+ struct Material* blendermaterial,
+ dword matname_hash,
+ KX_GameObject* gameobj,
+ KX_BlenderSceneConverter *converter);
#endif /* __KX_IPOCONVERT_H__ */
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
index a12e12ccef2..fab19008b25 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -83,7 +83,7 @@
// not valid, skip rendering this frame.
//#define NZC_GUARDED_OUTPUT
#define DEFAULT_LOGIC_TIC_RATE 60.0
-#define DEFAULT_PHYSICS_TIC_RATE 60.0
+//#define DEFAULT_PHYSICS_TIC_RATE 60.0
#ifdef FREE_WINDOWS /* XXX mingw64 (gcc 4.7.0) defines a macro for DrawText that translates to DrawTextA. Not good */
#ifdef DrawText
@@ -184,7 +184,10 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
for (int i = tc_first; i < tc_numCategories; i++)
m_logger->AddCategory((KX_TimeCategory)i);
-
+
+#ifdef WITH_PYTHON
+ m_pyprofiledict = PyDict_New();
+#endif
}
@@ -197,6 +200,10 @@ KX_KetsjiEngine::~KX_KetsjiEngine()
delete m_logger;
if (m_usedome)
delete m_dome;
+
+#ifdef WITH_PYTHON
+ Py_CLEAR(m_pyprofiledict);
+#endif
}
@@ -256,6 +263,12 @@ void KX_KetsjiEngine::SetPyNamespace(PyObject *pythondictionary)
MT_assert(pythondictionary);
m_pythondictionary = pythondictionary;
}
+
+PyObject* KX_KetsjiEngine::GetPyProfileDict()
+{
+ Py_INCREF(m_pyprofiledict);
+ return m_pyprofiledict;
+}
#endif
@@ -297,7 +310,7 @@ void KX_KetsjiEngine::RenderDome()
return;
KX_SceneList::iterator sceneit;
- KX_Scene* scene;
+ KX_Scene* scene = NULL;
int n_renders=m_dome->GetNumberRenders();// usually 4 or 6
for (int i=0;i<n_renders;i++) {
@@ -592,6 +605,8 @@ bool KX_KetsjiEngine::NextFrame()
m_frameTime += framestep;
+ m_sceneconverter->MergeAsyncLoads();
+
for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
// for each scene, call the proceed functions
{
@@ -1165,7 +1180,7 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
m_rasterizer->SetDrawingMode(RAS_IRasterizer::KX_SHADOW);
/* binds framebuffer object, sets up camera .. */
- light->BindShadowBuffer(m_rasterizer, cam, camtrans);
+ light->BindShadowBuffer(m_rasterizer, m_canvas, cam, camtrans);
/* update scene */
scene->CalculateVisibleMeshes(m_rasterizer, cam, light->GetShadowLayer());
@@ -1444,7 +1459,7 @@ void KX_KetsjiEngine::RenderDebugProperties()
int xcoord = 12; // mmmm, these constants were taken from blender source
int ycoord = 17; // to 'mimic' behavior
- int profile_indent = 64;
+ int profile_indent = 72;
float tottime = m_logger->GetAverage();
if (tottime < 1e-6f) {
@@ -1455,15 +1470,14 @@ void KX_KetsjiEngine::RenderDebugProperties()
RAS_Rect viewport;
m_canvas->SetViewPort(0, 0, int(m_canvas->GetWidth()), int(m_canvas->GetHeight()));
- if (m_show_framerate || m_show_profile) {
+ if (m_show_framerate || m_show_profile) {
/* Title for profiling("Profile") */
- debugtxt.Format("Profile");
m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
- debugtxt.Ptr(),
- xcoord + const_xindent + title_xmargin, // Adds the constant x indent (0 for now) to the title x margin
- ycoord,
- m_canvas->GetWidth() /* RdV, TODO ?? */,
- m_canvas->GetHeight() /* RdV, TODO ?? */);
+ "Profile",
+ xcoord + const_xindent + title_xmargin, // Adds the constant x indent (0 for now) to the title x margin
+ ycoord,
+ m_canvas->GetWidth() /* RdV, TODO ?? */,
+ m_canvas->GetHeight() /* RdV, TODO ?? */);
// Increase the indent by default increase
ycoord += const_ysize;
@@ -1473,64 +1487,69 @@ void KX_KetsjiEngine::RenderDebugProperties()
/* Framerate display */
if (m_show_framerate) {
- debugtxt.Format("Frametime :");
- m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
- debugtxt.Ptr(),
- xcoord + const_xindent,
- ycoord,
- m_canvas->GetWidth() /* RdV, TODO ?? */,
- m_canvas->GetHeight() /* RdV, TODO ?? */);
+ m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
+ "Frametime :",
+ xcoord + const_xindent,
+ ycoord,
+ m_canvas->GetWidth() /* RdV, TODO ?? */,
+ m_canvas->GetHeight() /* RdV, TODO ?? */);
- debugtxt.Format("%5.1fms (%5.1f fps)", tottime * 1000.f, 1.0/tottime);
- m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
- debugtxt.Ptr(),
- xcoord + const_xindent + profile_indent,
- ycoord,
- m_canvas->GetWidth() /* RdV, TODO ?? */,
- m_canvas->GetHeight() /* RdV, TODO ?? */);
+ debugtxt.Format("%5.1fms (%.1ffps)", tottime * 1000.f, 1.0/tottime);
+ m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
+ debugtxt.ReadPtr(),
+ xcoord + const_xindent + profile_indent,
+ ycoord,
+ m_canvas->GetWidth() /* RdV, TODO ?? */,
+ m_canvas->GetHeight() /* RdV, TODO ?? */);
// Increase the indent by default increase
ycoord += const_ysize;
}
/* Profile display */
- if (m_show_profile)
- {
- for (int j = tc_first; j < tc_numCategories; j++)
- {
- debugtxt.Format(m_profileLabels[j]);
+ if (m_show_profile) {
+ for (int j = tc_first; j < tc_numCategories; j++) {
m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
- debugtxt.Ptr(),
+ m_profileLabels[j],
xcoord + const_xindent,
- ycoord,
+ ycoord,
m_canvas->GetWidth(),
m_canvas->GetHeight());
double time = m_logger->GetAverage((KX_TimeCategory)j);
- debugtxt.Format("%5.2fms (%2d%%)", time*1000.f, (int)(time/tottime * 100.f));
+ debugtxt.Format("%5.2fms | %d%%", time*1000.f, (int)(time/tottime * 100.f));
m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
- debugtxt.Ptr(),
+ debugtxt.ReadPtr(),
xcoord + const_xindent + profile_indent, ycoord,
m_canvas->GetWidth(),
m_canvas->GetHeight());
+
+ m_rendertools->RenderBox2D(xcoord + (int)(2.2 * profile_indent), ycoord, m_canvas->GetWidth(), m_canvas->GetHeight(), time/tottime);
ycoord += const_ysize;
+
+#ifdef WITH_PYTHON
+ PyObject *val = PyTuple_New(2);
+ PyTuple_SetItem(val, 0, PyFloat_FromDouble(time*1000.f));
+ PyTuple_SetItem(val, 1, PyFloat_FromDouble(time/tottime * 100.f));
+
+ PyDict_SetItemString(m_pyprofiledict, m_profileLabels[j], val);
+ Py_DECREF(val);
+#endif
}
}
// Add the ymargin for titles below the other section of debug info
ycoord += title_y_top_margin;
/* Property display*/
- if (m_show_debug_properties && m_propertiesPresent)
- {
+ if (m_show_debug_properties && m_propertiesPresent) {
/* Title for debugging("Debug properties") */
- debugtxt.Format("Debug Properties");
- m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
- debugtxt.Ptr(),
- xcoord + const_xindent + title_xmargin, // Adds the constant x indent (0 for now) to the title x margin
- ycoord,
- m_canvas->GetWidth() /* RdV, TODO ?? */,
- m_canvas->GetHeight() /* RdV, TODO ?? */);
+ m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
+ "Debug Properties",
+ xcoord + const_xindent + title_xmargin, // Adds the constant x indent (0 for now) to the title x margin
+ ycoord,
+ m_canvas->GetWidth() /* RdV, TODO ?? */,
+ m_canvas->GetHeight() /* RdV, TODO ?? */);
// Increase the indent by default increase
ycoord += const_ysize;
@@ -1538,20 +1557,18 @@ void KX_KetsjiEngine::RenderDebugProperties()
ycoord += title_y_bottom_margin;
KX_SceneList::iterator sceneit;
- for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
- {
+ for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++) {
KX_Scene* scene = *sceneit;
/* the 'normal' debug props */
vector<SCA_DebugProp*>& debugproplist = scene->GetDebugProperties();
for (vector<SCA_DebugProp*>::iterator it = debugproplist.begin();
- !(it==debugproplist.end());it++)
+ !(it==debugproplist.end());it++)
{
- CValue* propobj = (*it)->m_obj;
+ CValue *propobj = (*it)->m_obj;
STR_String objname = propobj->GetName();
STR_String propname = (*it)->m_name;
- if (propname == "__state__")
- {
+ if (propname == "__state__") {
// reserve name for object state
KX_GameObject* gameobj = static_cast<KX_GameObject*>(propobj);
unsigned int state = gameobj->GetState();
@@ -1569,27 +1586,25 @@ void KX_KetsjiEngine::RenderDebugProperties()
first = false;
}
}
- m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
- debugtxt.Ptr(),
- xcoord + const_xindent,
- ycoord,
- m_canvas->GetWidth(),
- m_canvas->GetHeight());
+ m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
+ debugtxt.ReadPtr(),
+ xcoord + const_xindent,
+ ycoord,
+ m_canvas->GetWidth(),
+ m_canvas->GetHeight());
ycoord += const_ysize;
}
- else
- {
- CValue* propval = propobj->GetProperty(propname);
- if (propval)
- {
+ else {
+ CValue *propval = propobj->GetProperty(propname);
+ if (propval) {
STR_String text = propval->GetText();
debugtxt = objname + ": '" + propname + "' = " + text;
- m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
- debugtxt.Ptr(),
- xcoord + const_xindent,
- ycoord,
- m_canvas->GetWidth(),
- m_canvas->GetHeight());
+ m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
+ debugtxt.ReadPtr(),
+ xcoord + const_xindent,
+ ycoord,
+ m_canvas->GetWidth(),
+ m_canvas->GetHeight());
ycoord += const_ysize;
}
}
@@ -1625,19 +1640,14 @@ KX_Scene* KX_KetsjiEngine::FindScene(const STR_String& scenename)
void KX_KetsjiEngine::ConvertAndAddScene(const STR_String& scenename,bool overlay)
{
// only add scene when it doesn't exist!
- if (FindScene(scenename))
- {
- STR_String tmpname = scenename;
- printf("warning: scene %s already exists, not added!\n",tmpname.Ptr());
+ if (FindScene(scenename)) {
+ printf("warning: scene %s already exists, not added!\n",scenename.ReadPtr());
}
- else
- {
- if (overlay)
- {
+ else {
+ if (overlay) {
m_addingOverlayScenes.insert(scenename);
}
- else
- {
+ else {
m_addingBackgroundScenes.insert(scenename);
}
}
@@ -1686,7 +1696,7 @@ void KX_KetsjiEngine::RemoveScheduledScenes()
}
}
-KX_Scene* KX_KetsjiEngine::CreateScene(Scene *scene)
+KX_Scene* KX_KetsjiEngine::CreateScene(Scene *scene, bool libloading)
{
KX_Scene* tmpscene = new KX_Scene(m_keyboarddevice,
m_mousedevice,
@@ -1697,7 +1707,8 @@ KX_Scene* KX_KetsjiEngine::CreateScene(Scene *scene)
m_sceneconverter->ConvertScene(tmpscene,
m_rendertools,
- m_canvas);
+ m_canvas,
+ libloading);
return tmpscene;
}
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h
index 972594bd90f..fdfe0551d18 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.h
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h
@@ -81,6 +81,7 @@ private:
#ifdef WITH_PYTHON
/* borrowed from sys.modules["__main__"], don't manage ref's */
PyObject* m_pythondictionary;
+ PyObject* m_pyprofiledict;
#endif
class SCA_IInputDevice* m_keyboarddevice;
class SCA_IInputDevice* m_mousedevice;
@@ -222,6 +223,7 @@ public:
#ifdef WITH_PYTHON
void SetPyNamespace(PyObject *pythondictionary);
PyObject* GetPyNamespace() { return m_pythondictionary; }
+ PyObject* GetPyProfileDict();
#endif
void SetSceneConverter(KX_ISceneConverter* sceneconverter);
void SetAnimRecordMode(bool animation_record, int startFrame);
@@ -413,7 +415,7 @@ public:
void GetOverrideFrameColor(float& r, float& g, float& b) const;
KX_Scene* CreateScene(const STR_String& scenename);
- KX_Scene* CreateScene(Scene *scene);
+ KX_Scene* CreateScene(Scene *scene, bool libloading=false);
GlobalSettings* GetGlobalSettings(void);
void SetGlobalSettings(GlobalSettings* gs);
diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp
index cf58d18838a..a8f309cc592 100644
--- a/source/gameengine/Ketsji/KX_Light.cpp
+++ b/source/gameengine/Ketsji/KX_Light.cpp
@@ -236,7 +236,7 @@ int KX_LightObject::GetShadowLayer()
return 0;
}
-void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_Transform& camtrans)
+void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, RAS_ICanvas *canvas, KX_Camera *cam, MT_Transform& camtrans)
{
GPULamp *lamp;
float viewmat[4][4], winmat[4][4];
@@ -246,6 +246,12 @@ void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_T
lamp = GetGPULamp();
GPU_lamp_shadow_buffer_bind(lamp, viewmat, &winsize, winmat);
+ if (GPU_lamp_shadow_buffer_type(lamp) == LA_SHADMAP_VARIANCE)
+ ras->SetUsingOverrideShader(true);
+
+ /* GPU_lamp_shadow_buffer_bind() changes the viewport, so update the canvas */
+ canvas->UpdateViewPort(0, 0, winsize, winsize);
+
/* setup camera transformation */
MT_Matrix4x4 modelviewmat((float*)viewmat);
MT_Matrix4x4 projectionmat((float*)winmat);
@@ -273,6 +279,9 @@ void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras)
{
GPULamp *lamp = GetGPULamp();
GPU_lamp_shadow_buffer_unbind(lamp);
+
+ if (GPU_lamp_shadow_buffer_type(lamp) == LA_SHADMAP_VARIANCE)
+ ras->SetUsingOverrideShader(false);
}
struct Image *KX_LightObject::GetTextureImage(short texslot)
diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h
index 52f076c772a..f88fc7f6a1b 100644
--- a/source/gameengine/Ketsji/KX_Light.h
+++ b/source/gameengine/Ketsji/KX_Light.h
@@ -64,7 +64,7 @@ public:
struct GPULamp *GetGPULamp();
bool HasShadowBuffer();
int GetShadowLayer();
- void BindShadowBuffer(class RAS_IRasterizer *ras, class KX_Camera *cam, class MT_Transform& camtrans);
+ void BindShadowBuffer(class RAS_IRasterizer *ras, class RAS_ICanvas *canvas, class KX_Camera *cam, class MT_Transform& camtrans);
void UnbindShadowBuffer(class RAS_IRasterizer *ras);
struct Image *GetTextureImage(short texslot);
void Update();
diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp
index d83e98d4712..57695df2782 100644
--- a/source/gameengine/Ketsji/KX_MeshProxy.cpp
+++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp
@@ -338,20 +338,20 @@ PyObject *KX_MeshProxy::PyTransformUV(PyObject *args, PyObject *kwds)
for (i = it.startvertex; i < it.endvertex; i++) {
RAS_TexVert *vert = &it.vertex[i];
if (uvindex_from != -1) {
- if (uvindex_from == 0) vert->SetUV2(vert->getUV1());
- else vert->SetUV1(vert->getUV2());
+ if (uvindex_from == 0) vert->SetUV(1, vert->getUV(0));
+ else vert->SetUV(0, vert->getUV(1));
}
switch (uvindex) {
case 0:
- vert->TransformUV1(transform);
+ vert->TransformUV(0, transform);
break;
case 1:
- vert->TransformUV2(transform);
+ vert->TransformUV(1, transform);
break;
case -1:
- vert->TransformUV1(transform);
- vert->TransformUV2(transform);
+ vert->TransformUV(0, transform);
+ vert->TransformUV(1, transform);
break;
}
}
diff --git a/source/gameengine/Ketsji/KX_NavMeshObject.cpp b/source/gameengine/Ketsji/KX_NavMeshObject.cpp
index 33656e9fd52..24400398f03 100644
--- a/source/gameengine/Ketsji/KX_NavMeshObject.cpp
+++ b/source/gameengine/Ketsji/KX_NavMeshObject.cpp
@@ -96,7 +96,7 @@ CValue* KX_NavMeshObject::GetReplica()
void KX_NavMeshObject::ProcessReplica()
{
KX_GameObject::ProcessReplica();
-
+ m_navMesh = NULL; /* without this, building frees the navmesh we copied from */
BuildNavMesh();
KX_Scene* scene = KX_GetActiveScene();
KX_ObstacleSimulation* obssimulation = scene->GetObstacleSimulation();
diff --git a/source/gameengine/Ketsji/KX_ObColorIpoSGController.cpp b/source/gameengine/Ketsji/KX_ObColorIpoSGController.cpp
index f7e3194ee78..7f81f221c07 100644
--- a/source/gameengine/Ketsji/KX_ObColorIpoSGController.cpp
+++ b/source/gameengine/Ketsji/KX_ObColorIpoSGController.cpp
@@ -45,10 +45,10 @@ bool KX_ObColorIpoSGController::Update(double currentTime)
{
if (m_modified)
{
- m_rgba[0]=0;
- m_rgba[1]=0;
- m_rgba[2]=0;
- m_rgba[3]=0;
+ SG_Spatial* ob = (SG_Spatial*)m_pObject;
+ KX_GameObject* kxgameobj= (KX_GameObject*) ob->GetSGClientObject();
+
+ m_rgba = kxgameobj->GetObjectColor();
T_InterpolatorList::iterator i;
for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
@@ -56,9 +56,6 @@ bool KX_ObColorIpoSGController::Update(double currentTime)
}
- SG_Spatial* ob = (SG_Spatial*)m_pObject;
- KX_GameObject* kxgameobj= (KX_GameObject*) ob->GetSGClientObject();
-
kxgameobj->SetObjectColor(m_rgba);
diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp
index 931039bc54c..d02554e185e 100644
--- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp
@@ -81,6 +81,16 @@ KX_ObjectActuator(
m_pid = m_torque;
}
+ if (m_bitLocalFlag.CharacterMotion)
+ {
+ KX_GameObject *parent = static_cast<KX_GameObject *>(GetParent());
+
+ if (!parent->GetPhysicsController() || !parent->GetPhysicsController()->IsCharacter())
+ {
+ printf("Character motion enabled on non-character object (%s), falling back to simple motion.\n", parent->GetName().Ptr());
+ m_bitLocalFlag.CharacterMotion = false;
+ }
+ }
if (m_reference)
m_reference->RegisterActuator(this);
UpdateFuzzyFlags();
@@ -116,10 +126,10 @@ bool KX_ObjectActuator::Update()
m_active_combined_velocity = false;
}
- // Explicitly stop the movement if we're using a character (apply movement is a little different for characters)
- if (parent->GetPhysicsController() && parent->GetPhysicsController()->IsCharacter()) {
+ // Explicitly stop the movement if we're using character motion
+ if (m_bitLocalFlag.CharacterMotion) {
MT_Vector3 vec(0.0, 0.0, 0.0);
- parent->ApplyMovement(vec, true);
+ parent->GetPhysicsController()->SetWalkDirection(vec, true);
}
m_linear_damping_active = false;
@@ -205,8 +215,35 @@ bool KX_ObjectActuator::Update()
m_previous_error = e;
m_error_accumulator = I;
parent->ApplyForce(m_force,(m_bitLocalFlag.LinearVelocity) != 0);
- } else
- {
+ }
+ else if (m_bitLocalFlag.CharacterMotion) {
+ MT_Vector3 dir = m_dloc;
+
+ if (m_bitLocalFlag.AddOrSetCharLoc) {
+ MT_Vector3 old_dir = parent->GetPhysicsController()->GetWalkDirection();
+
+ if (!old_dir.fuzzyZero()) {
+ MT_Scalar mag = old_dir.length();
+
+ dir = dir + old_dir;
+ if (!dir.fuzzyZero())
+ dir = dir.normalized() * mag;
+ }
+ }
+
+ // We always want to set the walk direction since a walk direction of (0, 0, 0) should stop the character
+ parent->GetPhysicsController()->SetWalkDirection(dir, (m_bitLocalFlag.DLoc) != 0);
+
+ if (!m_bitLocalFlag.ZeroDRot)
+ {
+ parent->ApplyRotation(m_drot,(m_bitLocalFlag.DRot) != 0);
+ }
+ if (m_bitLocalFlag.CharacterJump)
+ {
+ parent->GetPhysicsController()->Jump();
+ }
+ }
+ else {
if (!m_bitLocalFlag.ZeroForce)
{
parent->ApplyForce(m_force,(m_bitLocalFlag.Force) != 0);
diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h
index b0efee550af..1f2453e3700 100644
--- a/source/gameengine/Ketsji/KX_ObjectActuator.h
+++ b/source/gameengine/Ketsji/KX_ObjectActuator.h
@@ -54,7 +54,12 @@ struct KX_LocalFlags {
LinearVelocity(false),
AngularVelocity(false),
AddOrSetLinV(false),
+ AddOrSetCharLoc(false),
+ ServoControl(false),
+ CharacterMotion(false),
+ CharacterJump(false),
ZeroForce(false),
+ ZeroTorque(false),
ZeroDRot(false),
ZeroDLoc(false),
ZeroLinearVelocity(false),
@@ -69,7 +74,10 @@ struct KX_LocalFlags {
bool LinearVelocity;
bool AngularVelocity;
bool AddOrSetLinV;
+ bool AddOrSetCharLoc;
bool ServoControl;
+ bool CharacterMotion;
+ bool CharacterJump;
bool ZeroForce;
bool ZeroTorque;
bool ZeroDRot;
diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp
index f157d9ed20a..0f53c510cf7 100644
--- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp
@@ -109,7 +109,7 @@ void KX_PolygonMaterial::Initialize(
m_mcol = *mcol;
}
else {
- m_mcol = 0;
+ memset(&m_mcol, 0, sizeof(m_mcol));
}
m_material = ma;
@@ -154,7 +154,7 @@ bool KX_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingI
{
PyErr_Print();
PyErr_Clear();
- PySys_SetObject( (char *)"last_traceback", NULL);
+ PySys_SetObject("last_traceback", NULL);
}
}
else
diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h
index 2ce8f480c1c..89bfb4ff9fb 100644
--- a/source/gameengine/Ketsji/KX_PolygonMaterial.h
+++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h
@@ -60,7 +60,7 @@ class KX_PolygonMaterial : public PyObjectPlus, public RAS_IPolyMaterial
private:
/** Blender texture face structure. */
mutable MTFace m_tface;
- mutable unsigned int m_mcol; /* for text color (only) */
+ mutable unsigned int m_mcol;
Material* m_material;
#ifdef WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
index 9bb09d56de6..2e9b988dff1 100644
--- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
+++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
@@ -43,7 +43,7 @@
#include "PyObjectPlus.h"
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
# include "LinearMath/btIDebugDraw.h"
#endif
@@ -716,7 +716,7 @@ PyObject *initPythonConstraintBinding()
PyDict_SetItemString(d, "error", ErrorObject);
Py_DECREF(ErrorObject);
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
//Debug Modes constants to be used with setDebugMode() python function
KX_MACRO_addTypesToDict(d, DBG_NODEBUG, btIDebugDraw::DBG_NoDebug);
KX_MACRO_addTypesToDict(d, DBG_DRAWWIREFRAME, btIDebugDraw::DBG_DrawWireframe);
@@ -732,7 +732,7 @@ PyObject *initPythonConstraintBinding()
KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTS, btIDebugDraw::DBG_DrawConstraints);
KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTLIMITS, btIDebugDraw::DBG_DrawConstraintLimits);
KX_MACRO_addTypesToDict(d, DBG_FASTWIREFRAME, btIDebugDraw::DBG_FastWireframe);
-#endif // USE_BULLET
+#endif // WITH_BULLET
//Constraint types to be used with createConstraint() python function
KX_MACRO_addTypesToDict(d, POINTTOPOINT_CONSTRAINT, PHY_POINT2POINT_CONSTRAINT);
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index 996be97c474..06abc755a9a 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -92,6 +92,8 @@ extern "C" {
#include "SCA_PropertySensor.h"
#include "SCA_RandomActuator.h"
#include "SCA_KeyboardSensor.h" /* IsPrintable, ToCharacter */
+#include "SCA_JoystickManager.h" /* JOYINDEX_MAX */
+#include "SCA_PythonJoystick.h"
#include "SCA_PythonKeyboard.h"
#include "SCA_PythonMouse.h"
#include "KX_ConstraintActuator.h"
@@ -134,6 +136,7 @@ extern "C" {
/* for converting new scenes */
#include "KX_BlenderSceneConverter.h"
+#include "KX_LibLoadStatus.h"
#include "KX_MeshProxy.h" /* for creating a new library of mesh objects */
extern "C" {
#include "BKE_idcode.h"
@@ -151,6 +154,7 @@ static char gp_GamePythonPathOrig[FILE_MAX] = ""; // not super happy about this,
static SCA_PythonKeyboard* gp_PythonKeyboard = NULL;
static SCA_PythonMouse* gp_PythonMouse = NULL;
+static SCA_PythonJoystick* gp_PythonJoysticks[JOYINDEX_MAX] = {NULL};
#endif // WITH_PYTHON
static KX_Scene* gp_KetsjiScene = NULL;
@@ -194,7 +198,7 @@ static PyObject *gp_OrigPythonSysModules= NULL;
/* Macro for building the keyboard translation */
//#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyLong_FromLong(SCA_IInputDevice::KX_##name))
-#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, item=PyLong_FromLong(name)); Py_DECREF(item)
+//#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, item=PyLong_FromLong(name)); Py_DECREF(item)
/* For the defines for types from logic bricks, we do stuff explicitly... */
#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyLong_FromLong(name2)); Py_DECREF(item)
@@ -367,6 +371,15 @@ static PyObject *gPyLoadGlobalDict(PyObject *)
Py_RETURN_NONE;
}
+static char gPyGetProfileInfo_doc[] =
+"getProfileInfo()\n"
+"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\
@@ -667,14 +680,15 @@ static PyObject *gLibLoad(PyObject *, PyObject *args, PyObject *kwds)
Py_buffer py_buffer;
py_buffer.buf = NULL;
char *err_str= NULL;
+ KX_LibLoadStatus *status = NULL;
short options=0;
- int load_actions=0, verbose=0, load_scripts=1;
+ int load_actions=0, verbose=0, load_scripts=1, async=0;
- static const char *kwlist[] = {"path", "group", "buffer", "load_actions", "verbose", "load_scripts", NULL};
+ static const char *kwlist[] = {"path", "group", "buffer", "load_actions", "verbose", "load_scripts", "async", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|y*iii:LibLoad", const_cast<char**>(kwlist),
- &path, &group, &py_buffer, &load_actions, &verbose, &load_scripts))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|y*iiIi:LibLoad", const_cast<char**>(kwlist),
+ &path, &group, &py_buffer, &load_actions, &verbose, &load_scripts, &async))
return NULL;
/* setup options */
@@ -684,6 +698,8 @@ static PyObject *gLibLoad(PyObject *, PyObject *args, PyObject *kwds)
options |= KX_BlenderSceneConverter::LIB_LOAD_VERBOSE;
if (load_scripts != 0)
options |= KX_BlenderSceneConverter::LIB_LOAD_LOAD_SCRIPTS;
+ if (async != 0)
+ options |= KX_BlenderSceneConverter::LIB_LOAD_ASYNC;
if (!py_buffer.buf)
{
@@ -692,16 +708,16 @@ static PyObject *gLibLoad(PyObject *, PyObject *args, PyObject *kwds)
BLI_strncpy(abs_path, path, sizeof(abs_path));
BLI_path_abs(abs_path, gp_GamePythonPath);
- if (kx_scene->GetSceneConverter()->LinkBlendFilePath(abs_path, group, kx_scene, &err_str, options)) {
- Py_RETURN_TRUE;
+ if ((status=kx_scene->GetSceneConverter()->LinkBlendFilePath(abs_path, group, kx_scene, &err_str, options))) {
+ return status->GetProxy();
}
}
else
{
- if (kx_scene->GetSceneConverter()->LinkBlendFileMemory(py_buffer.buf, py_buffer.len, path, group, kx_scene, &err_str, options)) {
+ if ((status=kx_scene->GetSceneConverter()->LinkBlendFileMemory(py_buffer.buf, py_buffer.len, path, group, kx_scene, &err_str, options))) {
PyBuffer_Release(&py_buffer);
- Py_RETURN_TRUE;
+ return status->GetProxy();
}
PyBuffer_Release(&py_buffer);
@@ -851,6 +867,7 @@ static struct PyMethodDef game_methods[] = {
{"PrintGLInfo", (PyCFunction)pyPrintExt, METH_NOARGS, (const char *)"Prints GL Extension Info"},
{"PrintMemInfo", (PyCFunction)pyPrintStats, METH_NOARGS, (const char *)"Print engine statistics"},
{"NextFrame", (PyCFunction)gPyNextFrame, METH_NOARGS, (const char *)"Render next frame (if Python has control)"},
+ {"getProfileInfo", (PyCFunction)gPyGetProfileInfo, METH_NOARGS, gPyGetProfileInfo_doc},
/* library functions */
{"LibLoad", (PyCFunction)gLibLoad, METH_VARARGS|METH_KEYWORDS, (const char *)""},
{"LibNew", (PyCFunction)gLibNew, METH_VARARGS, (const char *)""},
@@ -1420,6 +1437,22 @@ PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack
gp_PythonMouse = new SCA_PythonMouse(gp_KetsjiEngine->GetMouseDevice(), gp_Canvas);
PyDict_SetItemString(d, "mouse", gp_PythonMouse->NewProxy(true));
+ PyObject* joylist = PyList_New(JOYINDEX_MAX);
+ for (int i=0; i<JOYINDEX_MAX; ++i) {
+ SCA_Joystick* joy = SCA_Joystick::GetInstance(i);
+ 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);
+ }
+ }
+ PyDict_SetItemString(d, "joysticks", joylist);
+
ErrorObject = PyUnicode_FromString("GameLogic.error");
PyDict_SetItemString(d, "error", ErrorObject);
Py_DECREF(ErrorObject);
@@ -1865,7 +1898,7 @@ PyObject *initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur
* somehow it remembers the sys.path - Campbell
*/
static bool first_time = true;
- char *py_path_bundle = BLI_get_folder(BLENDER_SYSTEM_PYTHON, NULL);
+ const char * const py_path_bundle = BLI_get_folder(BLENDER_SYSTEM_PYTHON, NULL);
#if 0 // TODO - py3
STR_String pname = progname;
@@ -1898,19 +1931,22 @@ 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());
/* mathutils types are used by the BGE even if we don't import them */
{
- PyObject *mod= PyImport_ImportModuleLevel((char *)"mathutils", NULL, NULL, NULL, 0);
+ PyObject *mod = PyImport_ImportModuleLevel("mathutils", NULL, NULL, NULL, 0);
Py_DECREF(mod);
}
#ifdef WITH_AUDASPACE
/* accessing a SoundActuator's sound results in a crash if aud is not initialized... */
{
- PyObject *mod= PyImport_ImportModuleLevel((char *)"aud", NULL, NULL, NULL, 0);
+ PyObject *mod = PyImport_ImportModuleLevel("aud", NULL, NULL, NULL, 0);
Py_DECREF(mod);
}
#endif
@@ -1937,6 +1973,13 @@ void exitGamePlayerPythonScripting()
delete gp_PythonMouse;
gp_PythonMouse = NULL;
+ for (int i=0; i<JOYINDEX_MAX; ++i) {
+ if (gp_PythonJoysticks[i]) {
+ delete gp_PythonJoysticks[i];
+ gp_PythonJoysticks[i] = NULL;
+ }
+ }
+
/* since python restarts we cant let the python backup of the sys.path hang around in a global pointer */
restorePySysObjects(); /* get back the original sys.path and clear the backup */
@@ -1960,7 +2003,7 @@ PyObject *initGamePythonScripting(const STR_String& progname, TPythonSecurityLev
#ifdef WITH_AUDASPACE
/* accessing a SoundActuator's sound results in a crash if aud is not initialized... */
{
- PyObject *mod= PyImport_ImportModuleLevel((char *)"aud", NULL, NULL, NULL, 0);
+ PyObject *mod= PyImport_ImportModuleLevel("aud", NULL, NULL, NULL, 0);
Py_DECREF(mod);
}
#endif
@@ -1985,6 +2028,13 @@ void exitGamePythonScripting()
delete gp_PythonMouse;
gp_PythonMouse = NULL;
+ for (int i=0; i<JOYINDEX_MAX; ++i) {
+ if (gp_PythonJoysticks[i]) {
+ delete gp_PythonJoysticks[i];
+ gp_PythonJoysticks[i] = NULL;
+ }
+ }
+
restorePySysObjects(); /* get back the original sys.path and clear the backup */
bpy_import_main_set(NULL);
PyObjectPlus::ClearDeprecationWarning();
diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
index 971730672db..05bdb3463a6 100644
--- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
@@ -47,6 +47,7 @@
#include "KX_ConstraintActuator.h"
#include "KX_ConstraintWrapper.h"
#include "KX_GameActuator.h"
+#include "KX_LibLoadStatus.h"
#include "KX_Light.h"
#include "KX_FontObject.h"
#include "KX_MeshProxy.h"
@@ -81,6 +82,7 @@
#include "SCA_RandomSensor.h"
#include "SCA_XNORController.h"
#include "SCA_XORController.h"
+#include "SCA_PythonJoystick.h"
#include "SCA_PythonKeyboard.h"
#include "SCA_PythonMouse.h"
#include "KX_IpoActuator.h"
@@ -170,9 +172,9 @@ void initPyTypes(void)
*/
/* For now just do PyType_Ready */
- PyObject *mod= PyModule_New("GameTypes");
- PyObject *dict= PyModule_GetDict(mod);
- PyDict_SetItemString(PySys_GetObject((char *)"modules"), (char *)"GameTypes", mod);
+ PyObject *mod = PyModule_New("GameTypes");
+ PyObject *dict = PyModule_GetDict(mod);
+ PyDict_SetItemString(PySys_GetObject("modules"), "GameTypes", mod);
Py_DECREF(mod);
@@ -198,6 +200,7 @@ void initPyTypes(void)
PyType_Ready_Attr(dict, KX_GameActuator, init_getset);
PyType_Ready_Attr(dict, KX_GameObject, init_getset);
PyType_Ready_Attr(dict, KX_IpoActuator, init_getset);
+ PyType_Ready_Attr(dict, KX_LibLoadStatus, init_getset);
PyType_Ready_Attr(dict, KX_LightObject, init_getset);
PyType_Ready_Attr(dict, KX_FontObject, init_getset);
PyType_Ready_Attr(dict, KX_MeshProxy, init_getset);
@@ -250,6 +253,7 @@ void initPyTypes(void)
PyType_Ready_Attr(dict, SCA_XNORController, init_getset);
PyType_Ready_Attr(dict, SCA_XORController, init_getset);
PyType_Ready_Attr(dict, SCA_IController, init_getset);
+ PyType_Ready_Attr(dict, SCA_PythonJoystick, init_getset);
PyType_Ready_Attr(dict, SCA_PythonKeyboard, init_getset);
PyType_Ready_Attr(dict, SCA_PythonMouse, init_getset);
}
diff --git a/source/gameengine/Ketsji/KX_RayCast.cpp b/source/gameengine/Ketsji/KX_RayCast.cpp
index 2a6b7d122b5..878f9d267dc 100644
--- a/source/gameengine/Ketsji/KX_RayCast.cpp
+++ b/source/gameengine/Ketsji/KX_RayCast.cpp
@@ -51,10 +51,10 @@ KX_RayCast::KX_RayCast(KX_IPhysicsController* ignoreController, bool faceNormal,
void KX_RayCast::reportHit(PHY_RayCastResult* result)
{
m_hitFound = true;
- m_hitPoint.setValue((const float*)result->m_hitPoint);
- m_hitNormal.setValue((const float*)result->m_hitNormal);
+ m_hitPoint = MT_Vector3(result->m_hitPoint);
+ m_hitNormal = MT_Vector3(result->m_hitNormal);
m_hitUVOK = result->m_hitUVOK;
- m_hitUV.setValue((const float*)result->m_hitUV);
+ m_hitUV = MT_Vector2(result->m_hitUV);
m_hitMesh = result->m_meshObject;
m_hitPolygon = result->m_polygon;
}
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 72be5f57b95..3e1a81c2f4f 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -47,6 +47,7 @@
//#include "SCA_AlwaysEventManager.h"
//#include "SCA_RandomEventManager.h"
//#include "KX_RayEventManager.h"
+#include "SCA_2DFilterActuator.h"
#include "KX_TouchEventManager.h"
#include "SCA_KeyboardManager.h"
#include "SCA_MouseManager.h"
@@ -87,7 +88,7 @@
#include "BL_DeformableGameObject.h"
#include "KX_ObstacleSimulation.h"
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
#include "KX_SoftBodyDeformer.h"
#include "KX_ConvertPhysicsObject.h"
#include "CcdPhysicsEnvironment.h"
@@ -227,7 +228,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
}
#ifdef WITH_PYTHON
- m_attr_dict = PyDict_New(); /* new ref */
+ m_attr_dict = NULL;
m_draw_call_pre = NULL;
m_draw_call_post = NULL;
#endif
@@ -287,9 +288,11 @@ KX_Scene::~KX_Scene()
}
#ifdef WITH_PYTHON
- PyDict_Clear(m_attr_dict);
- /* Py_CLEAR: Py_DECREF's and NULL's */
- Py_CLEAR(m_attr_dict);
+ if (m_attr_dict) {
+ PyDict_Clear(m_attr_dict);
+ /* Py_CLEAR: Py_DECREF's and NULL's */
+ Py_CLEAR(m_attr_dict);
+ }
/* these may be NULL but the macro checks */
Py_CLEAR(m_draw_call_pre);
@@ -1128,7 +1131,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj, bool use_gfx, bool u
blendobj->parent && // original object had armature (not sure this test is needed)
blendobj->parent->type == OB_ARMATURE &&
blendmesh->dvert!=NULL; // mesh has vertex group
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
bool bHasSoftBody = (!parentobj && (blendobj->gameflag & OB_SOFT_BODY));
#endif
bool releaseParent = true;
@@ -1169,9 +1172,8 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj, bool use_gfx, bool u
);
}
newobj->SetDeformer(modifierDeformer);
- }
- else if (bHasShapeKey)
- {
+ }
+ else if (bHasShapeKey) {
BL_ShapeDeformer* shapeDeformer;
if (bHasArmature)
{
@@ -1219,7 +1221,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj, bool use_gfx, bool u
);
newobj->SetDeformer(meshdeformer);
}
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
else if (bHasSoftBody)
{
KX_SoftBodyDeformer *softdeformer = new KX_SoftBodyDeformer(mesh, newobj);
@@ -1236,7 +1238,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj, bool use_gfx, bool u
gameobj->AddMeshUser();
}
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
if (use_phys) { /* update the new assigned mesh with the physics mesh */
KX_ReInstanceBulletShapeFromMesh(gameobj, NULL, use_gfx?NULL:mesh);
}
@@ -1487,7 +1489,7 @@ void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int
if (m_dbvt_culling)
{
// test culling through Bullet
- PHY__Vector4 planes[6];
+ MT_Vector4 planes[6];
// get the clip planes
MT_Vector4* cplanes = cam->GetNormalizedClipPlanes();
// and convert
@@ -1708,13 +1710,11 @@ void KX_Scene::SetGravity(const MT_Vector3& gravity)
MT_Vector3 KX_Scene::GetGravity()
{
- PHY__Vector3 gravity;
- MT_Vector3 vec;
+ MT_Vector3 gravity;
GetPhysicsEnvironment()->getGravity(gravity);
- vec = gravity.m_vec;
- return vec;
+ return gravity;
}
void KX_Scene::SetSceneConverter(class KX_BlenderSceneConverter* sceneConverter)
@@ -1753,7 +1753,7 @@ short KX_Scene::GetAnimationFPS()
return m_blenderScene->r.frs_sec;
}
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
#include "KX_BulletPhysicsController.h"
#endif
@@ -1765,7 +1765,7 @@ static void MergeScene_LogicBrick(SCA_ILogicBrick* brick, KX_Scene *to)
brick->Replace_NetworkScene(to->GetNetworkScene());
/* near sensors have physics controllers */
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
KX_TouchSensor *touch_sensor = dynamic_cast<class KX_TouchSensor *>(brick);
if (touch_sensor) {
touch_sensor->GetPhysicsController()->SetPhysicsEnvironment(to->GetPhysicsEnvironment());
@@ -1779,9 +1779,14 @@ static void MergeScene_LogicBrick(SCA_ILogicBrick* brick, KX_Scene *to)
if (sensor) {
sensor->Replace_EventManager(logicmgr);
}
+
+ SCA_2DFilterActuator *filter_actuator = dynamic_cast<class SCA_2DFilterActuator*>(brick);
+ if (filter_actuator) {
+ filter_actuator->SetScene(to);
+ }
}
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
#include "CcdGraphicController.h" // XXX ctrl->SetPhysicsEnvironment(to->GetPhysicsEnvironment());
#include "CcdPhysicsEnvironment.h" // XXX ctrl->SetPhysicsEnvironment(to->GetPhysicsEnvironment());
#include "KX_BulletPhysicsController.h"
@@ -1850,7 +1855,7 @@ static void MergeScene_GameObject(KX_GameObject* gameobj, KX_Scene *to, KX_Scene
for (int i=0; i<children.size(); i++)
children[i]->SetSGClientInfo(to);
}
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
SGControllerList::iterator contit;
SGControllerList& controllers = sg->GetSGControllerList();
for (contit = controllers.begin();contit!=controllers.end();++contit)
@@ -1859,7 +1864,7 @@ static void MergeScene_GameObject(KX_GameObject* gameobj, KX_Scene *to, KX_Scene
if (phys_ctrl)
phys_ctrl->SetPhysicsEnvironment(to->GetPhysicsEnvironment());
}
-#endif // USE_BULLET
+#endif // WITH_BULLET
}
/* If the object is a light, update it's scene */
if (gameobj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT)
@@ -1878,7 +1883,7 @@ static void MergeScene_GameObject(KX_GameObject* gameobj, KX_Scene *to, KX_Scene
bool KX_Scene::MergeScene(KX_Scene *other)
{
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
CcdPhysicsEnvironment *env= dynamic_cast<CcdPhysicsEnvironment *>(this->GetPhysicsEnvironment());
CcdPhysicsEnvironment *env_other= dynamic_cast<CcdPhysicsEnvironment *>(other->GetPhysicsEnvironment());
@@ -1888,7 +1893,7 @@ bool KX_Scene::MergeScene(KX_Scene *other)
printf("\tsource %d, terget %d\n", (int)(env!=NULL), (int)(env_other!=NULL));
return false;
}
-#endif // USE_BULLET
+#endif // WITH_BULLET
if (GetSceneConverter() != other->GetSceneConverter()) {
printf("KX_Scene::MergeScene: converters differ, aborting\n");
@@ -1931,7 +1936,7 @@ bool KX_Scene::MergeScene(KX_Scene *other)
GetLightList()->MergeList(other->GetLightList());
other->GetLightList()->ReleaseAndRemoveAll();
-#ifdef USE_BULLET
+#ifdef WITH_BULLET
if (env) /* bullet scene? - dummy scenes don't need touching */
env->MergeEnvironment(env_other);
#endif
@@ -2062,6 +2067,9 @@ static PyObject *Map_GetItem(PyObject *self_v, PyObject *item)
PyErr_SetString(PyExc_SystemError, "val = scene[key]: KX_Scene, "BGE_PROXY_ERROR_MSG);
return NULL;
}
+
+ if (!self->m_attr_dict)
+ self->m_attr_dict = PyDict_New();
if (self->m_attr_dict && (pyconvert=PyDict_GetItem(self->m_attr_dict, item))) {
@@ -2089,7 +2097,10 @@ static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
PyErr_SetString(PyExc_SystemError, "scene[key] = value: KX_Scene, "BGE_PROXY_ERROR_MSG);
return -1;
}
-
+
+ if (!self->m_attr_dict)
+ self->m_attr_dict = PyDict_New();
+
if (val==NULL) { /* del ob["key"] */
int del= 0;
@@ -2133,7 +2144,10 @@ static int Seq_Contains(PyObject *self_v, PyObject *value)
PyErr_SetString(PyExc_SystemError, "val in scene: KX_Scene, "BGE_PROXY_ERROR_MSG);
return -1;
}
-
+
+ if (!self->m_attr_dict)
+ self->m_attr_dict = PyDict_New();
+
if (self->m_attr_dict && PyDict_GetItem(self->m_attr_dict, value))
return 1;
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp
index 2a4f2b3e7d9..5438ae5a97c 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp
@@ -132,10 +132,13 @@ void KX_SoundActuator::play()
handle3d->setConeVolumeOuter(m_3d.cone_outer_gain);
}
- if (loop)
- m_handle->setLoopCount(-1);
- m_handle->setPitch(m_pitch);
- m_handle->setVolume(m_volume);
+ if (m_handle.get()) {
+ if (loop)
+ m_handle->setLoopCount(-1);
+ m_handle->setPitch(m_pitch);
+ m_handle->setVolume(m_volume);
+ }
+
m_isplaying = true;
}
diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
index 1597948bafe..44a6e2fd7ee 100644
--- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp
+++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
@@ -294,7 +294,7 @@ bool KX_TrackToActuator::Update(double curtime, bool frame)
{
// (1.0 , 0.0 , 0.0 ) x direction is forward, z (0.0 , 0.0 , 1.0 ) up
left = dir.safe_normalized();
- dir = (left.cross(up)).safe_normalized();
+ dir = up.cross(left).safe_normalized();
mat.setValue (
left[0], dir[0],up[0],
left[1], dir[1],up[1],
@@ -334,7 +334,7 @@ bool KX_TrackToActuator::Update(double curtime, bool frame)
{
// (1.0 , 0.0 , 0.0 ) x direction is forward, z (0.0 , 0.0 , 1.0 ) up
left = -dir.safe_normalized();
- dir = -(left.cross(up)).safe_normalized();
+ dir = up.cross(left).safe_normalized();
mat.setValue (
left[0], dir[0],up[0],
left[1], dir[1],up[1],
@@ -373,7 +373,7 @@ bool KX_TrackToActuator::Update(double curtime, bool frame)
{
// (1.0 , 0.0 , 0.0 ) -x direction is forward, z (0.0 , 0.0 , 1.0 ) up
left = -dir.safe_normalized();
- dir = -(left.cross(up)).safe_normalized();
+ dir = up.cross(left).safe_normalized();
mat.setValue (
left[0], dir[0],up[0],
left[1], dir[1],up[1],
diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
index 9cc91a33886..f189891bf02 100644
--- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
@@ -59,19 +59,12 @@ PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args)
PyVecTo(pylistPos,attachPos);
PyVecTo(pylistDir,attachDir);
PyVecTo(pylistAxleDir,attachAxle);
- PHY__Vector3 aPos,aDir,aAxle;
- aPos[0] = attachPos[0];
- aPos[1] = attachPos[1];
- aPos[2] = attachPos[2];
- aDir[0] = attachDir[0];
- aDir[1] = attachDir[1];
- aDir[2] = attachDir[2];
- aAxle[0] = -attachAxle[0];//someone reverse some conventions inside Bullet (axle winding)
- aAxle[1] = -attachAxle[1];
- aAxle[2] = -attachAxle[2];
+
+ //someone reverse some conventions inside Bullet (axle winding)
+ attachAxle = -attachAxle;
printf("attempt for addWheel: suspensionRestLength%f wheelRadius %f, hasSteering:%d\n",suspensionRestLength,wheelRadius,hasSteering);
- m_vehicle->AddWheel(motionState,aPos,aDir,aAxle,suspensionRestLength,wheelRadius,hasSteering);
+ m_vehicle->AddWheel(motionState,attachPos,attachDir,attachAxle,suspensionRestLength,wheelRadius,hasSteering);
}
} else {
diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.h b/source/gameengine/Ketsji/KX_VehicleWrapper.h
index ccd666e84f3..c38f57d8b9f 100644
--- a/source/gameengine/Ketsji/KX_VehicleWrapper.h
+++ b/source/gameengine/Ketsji/KX_VehicleWrapper.h
@@ -7,7 +7,6 @@
#define __KX_VEHICLEWRAPPER_H__
#include "Value.h"
-#include "PHY_DynamicTypes.h"
class PHY_IVehicle;
class PHY_IMotionState;
diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp
index 2354359af18..ab73ba1902a 100644
--- a/source/gameengine/Ketsji/KX_VertexProxy.cpp
+++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp
@@ -94,6 +94,7 @@ PyAttributeDef KX_VertexProxy::Attributes[] = {
KX_PYATTRIBUTE_RW_FUNCTION("XYZ", KX_VertexProxy, pyattr_get_XYZ, pyattr_set_XYZ),
KX_PYATTRIBUTE_RW_FUNCTION("UV", KX_VertexProxy, pyattr_get_UV, pyattr_set_UV),
+ KX_PYATTRIBUTE_RW_FUNCTION("uvs", KX_VertexProxy, pyattr_get_uvs, pyattr_set_uvs),
KX_PYATTRIBUTE_RW_FUNCTION("color", KX_VertexProxy, pyattr_get_color, pyattr_set_color),
KX_PYATTRIBUTE_RW_FUNCTION("normal", KX_VertexProxy, pyattr_get_normal, pyattr_set_normal),
@@ -146,25 +147,25 @@ PyObject *KX_VertexProxy::pyattr_get_a(void *self_v, const KX_PYATTRIBUTE_DEF *a
PyObject *KX_VertexProxy::pyattr_get_u(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self = static_cast<KX_VertexProxy*>(self_v);
- return PyFloat_FromDouble(self->m_vertex->getUV1()[0]);
+ return PyFloat_FromDouble(self->m_vertex->getUV(0)[0]);
}
PyObject *KX_VertexProxy::pyattr_get_v(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self = static_cast<KX_VertexProxy*>(self_v);
- return PyFloat_FromDouble(self->m_vertex->getUV1()[1]);
+ return PyFloat_FromDouble(self->m_vertex->getUV(0)[1]);
}
PyObject *KX_VertexProxy::pyattr_get_u2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self = static_cast<KX_VertexProxy*>(self_v);
- return PyFloat_FromDouble(self->m_vertex->getUV2()[0]);
+ return PyFloat_FromDouble(self->m_vertex->getUV(1)[0]);
}
PyObject *KX_VertexProxy::pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self = static_cast<KX_VertexProxy*>(self_v);
- return PyFloat_FromDouble(self->m_vertex->getUV2()[1]);
+ return PyFloat_FromDouble(self->m_vertex->getUV(1)[1]);
}
PyObject *KX_VertexProxy::pyattr_get_XYZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -176,7 +177,20 @@ PyObject *KX_VertexProxy::pyattr_get_XYZ(void *self_v, const KX_PYATTRIBUTE_DEF
PyObject *KX_VertexProxy::pyattr_get_UV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_VertexProxy* self = static_cast<KX_VertexProxy*>(self_v);
- return PyObjectFrom(MT_Point2(self->m_vertex->getUV1()));
+ return PyObjectFrom(MT_Point2(self->m_vertex->getUV(0)));
+}
+
+PyObject *KX_VertexProxy::pyattr_get_uvs(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
+
+ PyObject* uvlist = PyList_New(RAS_TexVert::MAX_UNIT);
+ for (int i=0; i<RAS_TexVert::MAX_UNIT; ++i)
+ {
+ PyList_SET_ITEM(uvlist, i, PyObjectFrom(MT_Point2(self->m_vertex->getUV(i))));
+ }
+
+ return uvlist;
}
PyObject *KX_VertexProxy::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -245,9 +259,9 @@ int KX_VertexProxy::pyattr_set_u(void *self_v, const struct KX_PYATTRIBUTE_DEF *
if (PyFloat_Check(value))
{
float val = PyFloat_AsDouble(value);
- MT_Point2 uv = self->m_vertex->getUV1();
+ MT_Point2 uv = self->m_vertex->getUV(0);
uv[0] = val;
- self->m_vertex->SetUV1(uv);
+ self->m_vertex->SetUV(0, uv);
self->m_mesh->SetMeshModified(true);
return PY_SET_ATTR_SUCCESS;
}
@@ -260,9 +274,9 @@ int KX_VertexProxy::pyattr_set_v(void *self_v, const struct KX_PYATTRIBUTE_DEF *
if (PyFloat_Check(value))
{
float val = PyFloat_AsDouble(value);
- MT_Point2 uv = self->m_vertex->getUV1();
+ MT_Point2 uv = self->m_vertex->getUV(0);
uv[1] = val;
- self->m_vertex->SetUV1(uv);
+ self->m_vertex->SetUV(0, uv);
self->m_mesh->SetMeshModified(true);
return PY_SET_ATTR_SUCCESS;
}
@@ -275,9 +289,9 @@ int KX_VertexProxy::pyattr_set_u2(void *self_v, const struct KX_PYATTRIBUTE_DEF
if (PyFloat_Check(value))
{
float val = PyFloat_AsDouble(value);
- MT_Point2 uv = self->m_vertex->getUV2();
+ MT_Point2 uv = self->m_vertex->getUV(1);
uv[0] = val;
- self->m_vertex->SetUV2(uv);
+ self->m_vertex->SetUV(1, uv);
self->m_mesh->SetMeshModified(true);
return PY_SET_ATTR_SUCCESS;
}
@@ -290,9 +304,9 @@ int KX_VertexProxy::pyattr_set_v2(void *self_v, const struct KX_PYATTRIBUTE_DEF
if (PyFloat_Check(value))
{
float val = PyFloat_AsDouble(value);
- MT_Point2 uv = self->m_vertex->getUV2();
+ MT_Point2 uv = self->m_vertex->getUV(1);
uv[1] = val;
- self->m_vertex->SetUV2(uv);
+ self->m_vertex->SetUV(1, uv);
self->m_mesh->SetMeshModified(true);
return PY_SET_ATTR_SUCCESS;
}
@@ -390,7 +404,7 @@ int KX_VertexProxy::pyattr_set_UV(void *self_v, const struct KX_PYATTRIBUTE_DEF
{
MT_Point2 vec;
if (PyVecTo(value, vec)) {
- self->m_vertex->SetUV1(vec);
+ self->m_vertex->SetUV(0, vec);
self->m_mesh->SetMeshModified(true);
return PY_SET_ATTR_SUCCESS;
}
@@ -398,6 +412,32 @@ int KX_VertexProxy::pyattr_set_UV(void *self_v, const struct KX_PYATTRIBUTE_DEF
return PY_SET_ATTR_FAIL;
}
+int KX_VertexProxy::pyattr_set_uvs(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v);
+ if (PySequence_Check(value))
+ {
+ MT_Point2 vec;
+ for (int i=0; i<PySequence_Size(value) && i<RAS_TexVert::MAX_UNIT; ++i)
+ {
+ if (PyVecTo(PySequence_GetItem(value, i), vec))
+ {
+ self->m_vertex->SetUV(i, vec);
+ self->m_mesh->SetMeshModified(true);
+ }
+ else
+ {
+ PyErr_SetString(PyExc_AttributeError, STR_String().Format("list[%d] was not a vector", i).ReadPtr());
+ return PY_SET_ATTR_FAIL;
+ }
+ }
+
+ self->m_mesh->SetMeshModified(true);
+ return PY_SET_ATTR_SUCCESS;
+ }
+ return PY_SET_ATTR_FAIL;
+}
+
int KX_VertexProxy::pyattr_set_color(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_VertexProxy* self = static_cast<KX_VertexProxy*>(self_v);
@@ -522,7 +562,7 @@ PyObject *KX_VertexProxy::PySetRGBA(PyObject *value)
PyObject *KX_VertexProxy::PyGetUV1()
{
- return PyObjectFrom(MT_Vector2(m_vertex->getUV1()));
+ return PyObjectFrom(MT_Vector2(m_vertex->getUV(0)));
}
PyObject *KX_VertexProxy::PySetUV1(PyObject *value)
@@ -531,31 +571,23 @@ PyObject *KX_VertexProxy::PySetUV1(PyObject *value)
if (!PyVecTo(value, vec))
return NULL;
- m_vertex->SetUV1(vec);
+ m_vertex->SetUV(0, vec);
m_mesh->SetMeshModified(true);
Py_RETURN_NONE;
}
PyObject *KX_VertexProxy::PyGetUV2()
{
- return PyObjectFrom(MT_Vector2(m_vertex->getUV2()));
+ return PyObjectFrom(MT_Vector2(m_vertex->getUV(1)));
}
PyObject *KX_VertexProxy::PySetUV2(PyObject *args)
{
MT_Point2 vec;
- unsigned int unit= RAS_TexVert::SECOND_UV;
-
- PyObject *list = NULL;
- if (!PyArg_ParseTuple(args, "O|i:setUV2", &list, &unit))
- return NULL;
-
- if (!PyVecTo(list, vec))
+ if (!PyVecTo(args, vec))
return NULL;
- m_vertex->SetFlag((m_vertex->getFlag()|RAS_TexVert::SECOND_UV));
- m_vertex->SetUnit(unit);
- m_vertex->SetUV2(vec);
+ m_vertex->SetUV(1, vec);
m_mesh->SetMeshModified(true);
Py_RETURN_NONE;
}
diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h
index 4247d138a66..8070825ad11 100644
--- a/source/gameengine/Ketsji/KX_VertexProxy.h
+++ b/source/gameengine/Ketsji/KX_VertexProxy.h
@@ -74,6 +74,7 @@ public:
static PyObject *pyattr_get_UV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject *pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject *pyattr_get_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject *pyattr_get_uvs(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_x(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static int pyattr_set_y(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static int pyattr_set_z(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
@@ -89,6 +90,7 @@ public:
static int pyattr_set_UV(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static int pyattr_set_color(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static int pyattr_set_normal(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static int pyattr_set_uvs(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
KX_PYMETHOD_NOARGS(KX_VertexProxy,GetXYZ);
KX_PYMETHOD_O(KX_VertexProxy,SetXYZ);
diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript
index 88689a5a736..0690bdd6538 100644
--- a/source/gameengine/Ketsji/SConscript
+++ b/source/gameengine/Ketsji/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
import sys
Import ('env')
@@ -45,7 +71,7 @@ if env['WITH_BF_CXX_GUARDEDALLOC']:
defs.append('WITH_CXX_GUARDEDALLOC')
if env['WITH_BF_BULLET']:
- defs.append('USE_BULLET')
+ defs.append('WITH_BULLET')
incs += ' #source/gameengine/Physics/Bullet'
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
diff --git a/source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.h b/source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.h
index 7581486c80a..8bbb1e91e35 100644
--- a/source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.h
+++ b/source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.h
@@ -45,8 +45,8 @@ public:
virtual ~NG_LoopBackNetworkDeviceInterface();
/**
- * Clear message buffer
- */
+ * Clear message buffer
+ */
virtual void NextFrame();
bool Connect(char *address, unsigned int port, char *password,
diff --git a/source/gameengine/Network/LoopBackNetwork/SConscript b/source/gameengine/Network/LoopBackNetwork/SConscript
index 7ca0a64f774..b183634d224 100644
--- a/source/gameengine/Network/LoopBackNetwork/SConscript
+++ b/source/gameengine/Network/LoopBackNetwork/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = 'NG_LoopBackNetworkDeviceInterface.cpp'
diff --git a/source/gameengine/Network/NG_NetworkDeviceInterface.h b/source/gameengine/Network/NG_NetworkDeviceInterface.h
index 6da478ecda5..7fcf799db31 100644
--- a/source/gameengine/Network/NG_NetworkDeviceInterface.h
+++ b/source/gameengine/Network/NG_NetworkDeviceInterface.h
@@ -49,16 +49,16 @@ public:
virtual void NextFrame()=0;
/**
- * Mark network connection online
- */
+ * Mark network connection online
+ */
void Online(void) { m_online = true; }
/**
- * Mark network connection offline
- */
+ * Mark network connection offline
+ */
void Offline(void) { m_online = false; }
/**
- * Is the network connection established ?
- */
+ * Is the network connection established ?
+ */
bool IsOnline(void) { return m_online; }
virtual bool Connect(char *address, unsigned int port, char *password,
@@ -67,9 +67,9 @@ public:
virtual void SendNetworkMessage(NG_NetworkMessage* msg)=0;
/**
- * read NG_NetworkMessage from library buffer, may be
- * irrelevant for loopbackdevices
- */
+ * read NG_NetworkMessage from library buffer, may be
+ * irrelevant for loopbackdevices
+ */
virtual std::vector<NG_NetworkMessage*> RetrieveNetworkMessages()=0;
diff --git a/source/gameengine/Network/NG_NetworkMessage.h b/source/gameengine/Network/NG_NetworkMessage.h
index 5185849f8d7..6ed266557fc 100644
--- a/source/gameengine/Network/NG_NetworkMessage.h
+++ b/source/gameengine/Network/NG_NetworkMessage.h
@@ -123,8 +123,8 @@ public:
}
/**
- * get the unique Network Message ID
- */
+ * get the unique Network Message ID
+ */
int GetMessageID() {
return m_uniqueMessageID;
}
diff --git a/source/gameengine/Network/NG_NetworkScene.h b/source/gameengine/Network/NG_NetworkScene.h
index 10dad210128..e6233852ee2 100644
--- a/source/gameengine/Network/NG_NetworkScene.h
+++ b/source/gameengine/Network/NG_NetworkScene.h
@@ -42,7 +42,7 @@
//MSVC defines SendMessage as a win api function, even though we aren't using it
#ifdef SendMessage
- #undef SendMessage
+# undef SendMessage
#endif
using namespace std;
diff --git a/source/gameengine/Network/SConscript b/source/gameengine/Network/SConscript
index bbf714383b7..7365db5ba99 100644
--- a/source/gameengine/Network/SConscript
+++ b/source/gameengine/Network/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.cpp') #'NG_NetworkMessage.cpp NG_NetworkObject.cpp NG_NetworkScene.cpp'
diff --git a/source/gameengine/Physics/Bullet/CMakeLists.txt b/source/gameengine/Physics/Bullet/CMakeLists.txt
index 43b1bfe7468..c5b601361d9 100644
--- a/source/gameengine/Physics/Bullet/CMakeLists.txt
+++ b/source/gameengine/Physics/Bullet/CMakeLists.txt
@@ -44,7 +44,6 @@ set(INC
)
set(INC_SYS
- ../../../../extern/bullet2/src
${GLEW_INCLUDE_PATH}
${PYTHON_INCLUDE_DIRS}
)
@@ -60,7 +59,10 @@ set(SRC
)
if(WITH_BULLET)
- add_definitions(-DUSE_BULLET)
+ list(APPEND INC
+ ${BULLET_INCLUDE_DIRS}
+ )
+ add_definitions(-DWITH_BULLET)
endif()
blender_add_lib(ge_phys_bullet "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/gameengine/Physics/Bullet/CcdGraphicController.cpp b/source/gameengine/Physics/Bullet/CcdGraphicController.cpp
index 36e7b0d482f..3cb80e53e12 100644
--- a/source/gameengine/Physics/Bullet/CcdGraphicController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdGraphicController.cpp
@@ -55,7 +55,7 @@ void CcdGraphicController::setLocalAabb(const MT_Point3& aabbMin,const MT_Point3
SetGraphicTransform();
}
-void CcdGraphicController::setLocalAabb(const PHY__Vector3& aabbMin,const PHY__Vector3& aabbMax)
+void CcdGraphicController::setLocalAabb(const MT_Vector3& aabbMin,const MT_Vector3& aabbMax)
{
m_localAabbMin.setValue(aabbMin[0],aabbMin[1],aabbMin[2]);
m_localAabbMax.setValue(aabbMax[0],aabbMax[1],aabbMax[2]);
diff --git a/source/gameengine/Physics/Bullet/CcdGraphicController.h b/source/gameengine/Physics/Bullet/CcdGraphicController.h
index 72eb699ce5b..064f86040f6 100644
--- a/source/gameengine/Physics/Bullet/CcdGraphicController.h
+++ b/source/gameengine/Physics/Bullet/CcdGraphicController.h
@@ -42,7 +42,7 @@ public:
void setLocalAabb(const btVector3& aabbMin,const btVector3& aabbMax);
void setLocalAabb(const MT_Point3& aabbMin,const MT_Point3& aabbMax);
- virtual void setLocalAabb(const PHY__Vector3& aabbMin,const PHY__Vector3& aabbMax);
+ virtual void setLocalAabb(const MT_Vector3& aabbMin,const MT_Vector3& aabbMax);
virtual void setLocalAabb(const float aabbMin[3],const float aabbMax[3]);
PHY_IMotionState* GetMotionState() { return m_motionState; }
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index 6c6ce94d8d5..08ea9706eba 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -24,7 +24,6 @@ subject to the following restrictions:
#include "btBulletDynamicsCommon.h"
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
-
#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
#include "PHY_IMotionState.h"
@@ -33,11 +32,10 @@ subject to the following restrictions:
#include "KX_GameObject.h"
#include "BulletSoftBody/btSoftBody.h"
-#include "BulletSoftBody//btSoftBodyInternals.h"
+#include "BulletSoftBody/btSoftBodyInternals.h"
#include "BulletSoftBody/btSoftBodyHelpers.h"
#include "LinearMath/btConvexHull.h"
#include "BulletCollision/Gimpact/btGImpactShape.h"
-#include "BulletCollision/Gimpact/btGImpactShape.h"
#include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
@@ -68,6 +66,58 @@ float gAngularSleepingTreshold;
btVector3 startVel(0,0,0);//-10000);
+BlenderBulletCharacterController::BlenderBulletCharacterController(btMotionState *motionState, btPairCachingGhostObject *ghost, btConvexShape* shape, float stepHeight)
+ : btKinematicCharacterController(ghost,shape,stepHeight,2),
+ m_motionState(motionState),
+ m_jumps(0),
+ m_maxJumps(1)
+{
+}
+
+void BlenderBulletCharacterController::updateAction(btCollisionWorld *collisionWorld, btScalar dt)
+{
+ if (onGround())
+ m_jumps = 0;
+
+ btKinematicCharacterController::updateAction(collisionWorld,dt);
+ m_motionState->setWorldTransform(getGhostObject()->getWorldTransform());
+}
+
+int BlenderBulletCharacterController::getMaxJumps() const
+{
+ return m_maxJumps;
+}
+
+void BlenderBulletCharacterController::setMaxJumps(int maxJumps)
+{
+ m_maxJumps = maxJumps;
+}
+
+int BlenderBulletCharacterController::getJumpCount() const
+{
+ return m_jumps;
+}
+
+bool BlenderBulletCharacterController::canJump() const
+{
+ return onGround() || m_jumps < m_maxJumps;
+}
+
+void BlenderBulletCharacterController::jump()
+{
+ if (!canJump())
+ return;
+
+ m_verticalVelocity = m_jumpSpeed;
+ m_wasJumping = true;
+ m_jumps++;
+}
+
+const btVector3& BlenderBulletCharacterController::getWalkDirection()
+{
+ return m_walkDirection;
+}
+
CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci)
:m_cci(ci)
{
@@ -154,25 +204,6 @@ public:
};
-class BlenderBulletCharacterController : public btKinematicCharacterController
-{
-private:
- btMotionState* m_motionState;
-
-public:
- BlenderBulletCharacterController(btMotionState *motionState, btPairCachingGhostObject *ghost, btConvexShape* shape, float stepHeight)
- : btKinematicCharacterController(ghost,shape,stepHeight,2),
- m_motionState(motionState)
- {
- }
-
- virtual void updateAction(btCollisionWorld *collisionWorld, btScalar dt)
- {
- btKinematicCharacterController::updateAction(collisionWorld,dt);
- m_motionState->setWorldTransform(getGhostObject()->getWorldTransform());
- }
-};
-
btRigidBody* CcdPhysicsController::GetRigidBody()
{
return btRigidBody::upcast(m_object);
@@ -463,9 +494,6 @@ bool CcdPhysicsController::CreateCharacterController()
m_characterController = new BlenderBulletCharacterController(m_bulletMotionState,(btPairCachingGhostObject*)m_object,(btConvexShape*)m_collisionShape,m_cci.m_stepHeight);
- PHY__Vector3 gravity;
- m_cci.m_physicsEnv->getGravity(gravity);
- m_characterController->setGravity(-gravity.m_vec[2]); // need positive gravity
m_characterController->setJumpSpeed(m_cci.m_jumpSpeed);
m_characterController->setFallSpeed(m_cci.m_fallSpeed);
@@ -645,9 +673,9 @@ CcdPhysicsController::~CcdPhysicsController()
}
- /**
- SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
- */
+/**
+ * SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
+ */
bool CcdPhysicsController::SynchronizeMotionStates(float time)
{
//sync non-static to motionstate, and static from motionstate (todo: add kinematic etc.)
@@ -730,8 +758,8 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time)
}
/**
- WriteMotionStateToDynamics synchronizes dynas, kinematic and deformable entities (and do 'late binding')
- */
+ * WriteMotionStateToDynamics synchronizes dynas, kinematic and deformable entities (and do 'late binding')
+ */
void CcdPhysicsController::WriteMotionStateToDynamics(bool nondynaonly)
{
@@ -901,20 +929,27 @@ void CcdPhysicsController::RelativeTranslate(float dlocX,float dlocY,float dloc
if (local)
dloc = xform.getBasis()*dloc;
- if (m_characterController)
- {
- m_characterController->setWalkDirection(dloc/GetPhysicsEnvironment()->getNumTimeSubSteps());
- }
- else
- {
-
- xform.setOrigin(xform.getOrigin() + dloc);
- SetCenterOfMassTransform(xform);
- }
+ xform.setOrigin(xform.getOrigin() + dloc);
+ SetCenterOfMassTransform(xform);
}
}
+void CcdPhysicsController::SetWalkDirection(float dirX,float dirY,float dirZ,bool local)
+{
+
+ if (m_object && m_characterController)
+ {
+ btVector3 dir(dirX,dirY,dirZ);
+ btTransform xform = m_object->getWorldTransform();
+
+ if (local)
+ dir = xform.getBasis()*dir;
+
+ m_characterController->setWalkDirection(dir/GetPhysicsEnvironment()->getNumTimeSubSteps());
+ }
+}
+
void CcdPhysicsController::RelativeRotate(const float rotval[9],bool local)
{
if (m_object)
@@ -1055,7 +1090,7 @@ void CcdPhysicsController::resolveCombinedVelocities(float linvelX,float linvel
{
}
-void CcdPhysicsController::getPosition(PHY__Vector3& pos) const
+void CcdPhysicsController::getPosition(MT_Vector3& pos) const
{
const btTransform& xform = m_object->getWorldTransform();
pos[0] = xform.getOrigin().x();
@@ -1242,6 +1277,13 @@ void CcdPhysicsController::applyImpulse(float attachX,float attachY,float attac
}
}
+
+void CcdPhysicsController::Jump()
+{
+ if (m_object && m_characterController)
+ m_characterController->jump();
+}
+
void CcdPhysicsController::SetActive(bool active)
{
}
@@ -1298,6 +1340,24 @@ void CcdPhysicsController::GetVelocity(const float posX,const float posY,const
linvZ = 0.f;
}
}
+
+void CcdPhysicsController::GetWalkDirection(float& dirX,float& dirY,float& dirZ)
+{
+ if (m_object && m_characterController)
+ {
+ const btVector3 dir = m_characterController->getWalkDirection();
+ dirX = dir.x();
+ dirY = dir.y();
+ dirZ = dir.z();
+ }
+ else
+ {
+ dirX = 0.f;
+ dirY = 0.f;
+ dirZ = 0.f;
+ }
+}
+
void CcdPhysicsController::getReactionForce(float& forceX,float& forceY,float& forceZ)
{
}
@@ -2169,8 +2229,9 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin, b
);
btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(indexVertexArrays);
gimpactShape->setMargin(margin);
- collisionShape = gimpactShape;
gimpactShape->updateBound();
+ collisionShape = gimpactShape;
+
} else
{
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
index 6df5c85f5c0..f1f0ca31419 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
@@ -391,17 +391,42 @@ struct CcdConstructionInfo
};
-
class btRigidBody;
class btCollisionObject;
class btSoftBody;
+class btPairCachingGhostObject;
+
+class BlenderBulletCharacterController : public btKinematicCharacterController
+{
+private:
+ btMotionState* m_motionState;
+ int m_jumps;
+ int m_maxJumps;
+
+public:
+ BlenderBulletCharacterController(btMotionState *motionState, btPairCachingGhostObject *ghost, btConvexShape* shape, float stepHeight);
+
+ virtual void updateAction(btCollisionWorld *collisionWorld, btScalar dt);
+
+ int getMaxJumps() const;
+
+ void setMaxJumps(int maxJumps);
+
+ int getJumpCount() const;
+
+ virtual bool canJump() const;
+
+ virtual void jump();
+
+ const btVector3& getWalkDirection();
+};
///CcdPhysicsController is a physics object that supports continuous collision detection and time of impact based physics resolution.
class CcdPhysicsController : public PHY_IPhysicsController
{
protected:
btCollisionObject* m_object;
- btKinematicCharacterController* m_characterController;
+ BlenderBulletCharacterController* m_characterController;
class PHY_IMotionState* m_MotionState;
@@ -478,12 +503,12 @@ protected:
/**
- SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
- */
+ * SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
+ */
virtual bool SynchronizeMotionStates(float time);
/**
- WriteMotionStateToDynamics ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
- */
+ * WriteMotionStateToDynamics ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
+ */
virtual void WriteMotionStateToDynamics(bool nondynaonly);
virtual void WriteDynamicsToMotionState();
@@ -494,11 +519,12 @@ protected:
// kinematic methods
virtual void RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local);
+ virtual void SetWalkDirection(float dirX,float dirY,float dirZ,bool local);
virtual void RelativeRotate(const float drot[9],bool local);
virtual void getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal);
virtual void setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal);
virtual void setPosition(float posX,float posY,float posZ);
- virtual void getPosition(PHY__Vector3& pos) const;
+ virtual void getPosition(MT_Vector3& pos) const;
virtual void setScaling(float scaleX,float scaleY,float scaleZ);
@@ -508,6 +534,7 @@ protected:
virtual void SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local);
virtual void SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local);
virtual void applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ);
+ virtual void Jump();
virtual void SetActive(bool active);
// reading out information from physics
@@ -515,6 +542,7 @@ protected:
virtual void GetAngularVelocity(float& angVelX,float& angVelY,float& angVelZ);
virtual void GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ);
virtual void getReactionForce(float& forceX,float& forceY,float& forceZ);
+ virtual void GetWalkDirection(float& dirX,float& dirY,float& dirZ);
// dyna's that are rigidbody are free in orientation, dyna's with non-rigidbody are restricted
virtual void setRigidBody(bool rigid);
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index 486411d7e35..d5ceba0ec57 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -97,9 +97,9 @@ public:
virtual void AddWheel(
PHY_IMotionState* motionState,
- PHY__Vector3 connectionPoint,
- PHY__Vector3 downDirection,
- PHY__Vector3 axleDirection,
+ MT_Vector3 connectionPoint,
+ MT_Vector3 downDirection,
+ MT_Vector3 axleDirection,
float suspensionRestLength,
float wheelRadius,
bool hasSteering
@@ -270,10 +270,10 @@ public:
class CharacterWrapper : public PHY_ICharacter
{
private:
- btKinematicCharacterController* m_controller;
+ BlenderBulletCharacterController* m_controller;
public:
- CharacterWrapper(btKinematicCharacterController* cont)
+ CharacterWrapper(BlenderBulletCharacterController* cont)
: m_controller(cont)
{}
@@ -295,6 +295,33 @@ public:
{
m_controller->setGravity(gravity);
}
+
+ virtual int GetMaxJumps()
+ {
+ return m_controller->getMaxJumps();
+ }
+
+ virtual void SetMaxJumps(int maxJumps)
+ {
+ m_controller->setMaxJumps(maxJumps);
+ }
+
+ virtual int GetJumpCount()
+ {
+ return m_controller->getJumpCount();
+ }
+
+ virtual void SetWalkDirection(const MT_Vector3& dir)
+ {
+ btVector3 vec = btVector3(dir[0], dir[1], dir[2]);
+ m_controller->setWalkDirection(vec);
+ }
+
+ virtual MT_Vector3 GetWalkDirection()
+ {
+ btVector3 vec = m_controller->getWalkDirection();
+ return MT_Vector3(vec[0], vec[1], vec[2]);
+ }
};
class CcdOverlapFilterCallBack : public btOverlapFilterCallback
@@ -920,7 +947,7 @@ void CcdPhysicsEnvironment::setSolverType(int solverType)
-void CcdPhysicsEnvironment::getGravity(PHY__Vector3& grav)
+void CcdPhysicsEnvironment::getGravity(MT_Vector3& grav)
{
const btVector3& gravity = m_dynamicsWorld->getGravity();
grav[0] = gravity.getX();
@@ -1179,7 +1206,7 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac
{
// soft body using different face numbering because of randomization
// hopefully we have stored the original face number in m_tag
- btSoftBody* softBody = static_cast<btSoftBody*>(rayCallback.m_collisionObject);
+ const btSoftBody* softBody = static_cast<const btSoftBody*>(rayCallback.m_collisionObject);
if (softBody->m_faces[hitTriangleIndex].m_tag != 0)
{
rayCallback.m_hitTriangleIndex = (int)((uintptr_t)(softBody->m_faces[hitTriangleIndex].m_tag)-1);
@@ -1199,7 +1226,7 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac
if (shape->isSoftBody())
{
// soft body give points directly in world coordinate
- btSoftBody* softBody = static_cast<btSoftBody*>(rayCallback.m_collisionObject);
+ const btSoftBody* softBody = static_cast<const btSoftBody*>(rayCallback.m_collisionObject);
v1 = softBody->m_faces[hitTriangleIndex].m_n[0]->m_x;
v2 = softBody->m_faces[hitTriangleIndex].m_n[1]->m_x;
v3 = softBody->m_faces[hitTriangleIndex].m_n[2]->m_x;
@@ -1247,7 +1274,7 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac
if (shape->isSoftBody())
{
// we can get the real normal directly from the body
- btSoftBody* softBody = static_cast<btSoftBody*>(rayCallback.m_collisionObject);
+ const btSoftBody* softBody = static_cast<const btSoftBody*>(rayCallback.m_collisionObject);
rayCallback.m_hitNormalWorld = softBody->m_faces[hitTriangleIndex].m_normal;
} else
{
@@ -1549,7 +1576,7 @@ struct OcclusionBuffer
}
}
}
- else if (width == 1) {
+ else if (width == 1) {
// Degenerated in at least 2 vertical lines
// The algorithm below doesn't work when face has a single pixel width
// We cannot use general formulas because the plane is degenerated.
@@ -1820,7 +1847,7 @@ struct DbvtCullingCallback : btDbvt::ICollide
};
static OcclusionBuffer gOcb;
-bool CcdPhysicsEnvironment::cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4 *planes, int nplanes, int occlusionRes, const int *viewport, double modelview[16], double projection[16])
+bool CcdPhysicsEnvironment::cullingTest(PHY_CullingCallback callback, void* userData, MT_Vector4 *planes, int nplanes, int occlusionRes, const int *viewport, double modelview[16], double projection[16])
{
if (!m_cullingTree)
return false;
@@ -2184,8 +2211,8 @@ void CcdPhysicsEnvironment::CallbackTriggers()
int numContacts = manifold->getNumContacts();
if (numContacts)
{
- btRigidBody* rb0 = static_cast<btRigidBody*>(manifold->getBody0());
- btRigidBody* rb1 = static_cast<btRigidBody*>(manifold->getBody1());
+ 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++)
@@ -2196,8 +2223,8 @@ void CcdPhysicsEnvironment::CallbackTriggers()
m_debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color);
}
}
- btRigidBody* obj0 = rb0;
- btRigidBody* obj1 = rb1;
+ const btRigidBody* obj0 = rb0;
+ const btRigidBody* obj1 = rb1;
//m_internalOwner is set in 'addPhysicsController'
CcdPhysicsController* ctrl0 = static_cast<CcdPhysicsController*>(obj0->getUserPointer());
@@ -2320,7 +2347,7 @@ PHY_ICharacter* CcdPhysicsEnvironment::getCharacterController(KX_GameObject *ob)
{
CcdPhysicsController* controller = (CcdPhysicsController*)ob->GetPhysicsController()->GetUserData();
if (controller->GetCharacterController())
- return new CharacterWrapper(controller->GetCharacterController());
+ return new CharacterWrapper((BlenderBulletCharacterController*)controller->GetCharacterController());
return NULL;
}
@@ -2331,7 +2358,7 @@ int numController = 0;
-PHY_IPhysicsController* CcdPhysicsEnvironment::CreateSphereController(float radius,const PHY__Vector3& position)
+PHY_IPhysicsController* CcdPhysicsEnvironment::CreateSphereController(float radius,const MT_Vector3& position)
{
CcdConstructionInfo cinfo;
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
index 18ce0550498..8cf88526969 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
@@ -140,7 +140,7 @@ protected:
virtual void setDebugMode(int debugMode);
virtual void setGravity(float x,float y,float z);
- virtual void getGravity(PHY__Vector3& grav);
+ virtual void getGravity(MT_Vector3& grav);
virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
@@ -190,7 +190,7 @@ protected:
btTypedConstraint* getConstraintById(int constraintId);
virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
- virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes, int occlusionRes, const int *viewport, double modelview[16], double projection[16]);
+ virtual bool cullingTest(PHY_CullingCallback callback, void* userData, MT_Vector4* planes, int nplanes, int occlusionRes, const int *viewport, double modelview[16], double projection[16]);
//Methods for gamelogic collision/physics callbacks
@@ -200,7 +200,7 @@ protected:
virtual bool requestCollisionCallback(PHY_IPhysicsController* ctrl);
virtual bool removeCollisionCallback(PHY_IPhysicsController* ctrl);
//These two methods are used *solely* to create controllers for Near/Radar sensor! Don't use for anything else
- virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position);
+ virtual PHY_IPhysicsController* CreateSphereController(float radius,const MT_Vector3& position);
virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight);
diff --git a/source/gameengine/Physics/Bullet/SConscript b/source/gameengine/Physics/Bullet/SConscript
index ba4db001533..6ef2750e8d6 100644
--- a/source/gameengine/Physics/Bullet/SConscript
+++ b/source/gameengine/Physics/Bullet/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = 'CcdPhysicsEnvironment.cpp CcdPhysicsController.cpp CcdGraphicController.cpp'
@@ -30,6 +56,6 @@ if env['WITH_BF_CXX_GUARDEDALLOC']:
defs.append('WITH_CXX_GUARDEDALLOC')
if env['WITH_BF_BULLET']:
- defs.append('USE_BULLET')
+ defs.append('WITH_BULLET')
env.BlenderLib ( 'ge_phys_bullet', Split(sources), Split(incs), defs, libtype=['core','player'], priority=[350,50], cxx_compileflags=env['BGE_CXXFLAGS'])
diff --git a/source/gameengine/Physics/Dummy/CMakeLists.txt b/source/gameengine/Physics/Dummy/CMakeLists.txt
index 6a21fc6fcb7..529a75b2a62 100644
--- a/source/gameengine/Physics/Dummy/CMakeLists.txt
+++ b/source/gameengine/Physics/Dummy/CMakeLists.txt
@@ -26,6 +26,7 @@
set(INC
.
../common
+ ../../../../intern/moto/include
)
set(INC_SYS
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
index d1fabba18f9..72450e4307c 100644
--- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
@@ -85,7 +85,7 @@ void DummyPhysicsEnvironment::setGravity(float x,float y,float z)
{
}
-void DummyPhysicsEnvironment::getGravity(PHY__Vector3& grav)
+void DummyPhysicsEnvironment::getGravity(class MT_Vector3& grav)
{
}
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
index 5ce34bdf7cf..9f6bc85fced 100644
--- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
@@ -56,7 +56,7 @@ public:
virtual float getFixedTimeStep();
virtual void setGravity(float x,float y,float z);
- virtual void getGravity(PHY__Vector3& grav);
+ virtual void getGravity(class MT_Vector3& grav);
virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
float pivotX,float pivotY,float pivotZ,
@@ -80,7 +80,7 @@ public:
}
virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
- virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes, int occlusionRes, const int *viewport, double modelview[16], double projection[16]) { return false; }
+ virtual bool cullingTest(PHY_CullingCallback callback, void* userData, class MT_Vector4* planes, int nplanes, int occlusionRes, const int *viewport, double modelview[16], double projection[16]) { return false; }
//gamelogic callbacks
@@ -91,7 +91,7 @@ public:
}
virtual bool requestCollisionCallback(PHY_IPhysicsController* ctrl) { return false; }
virtual bool removeCollisionCallback(PHY_IPhysicsController* ctrl) { return false;}
- virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position) {return 0;}
+ virtual PHY_IPhysicsController* CreateSphereController(float radius,const class MT_Vector3& position) {return 0;}
virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight) { return 0;}
virtual void setConstraintParam(int constraintId,int param,float value,float value1)
diff --git a/source/gameengine/Physics/Dummy/SConscript b/source/gameengine/Physics/Dummy/SConscript
index 13d1a893823..15a68ad4e85 100644
--- a/source/gameengine/Physics/Dummy/SConscript
+++ b/source/gameengine/Physics/Dummy/SConscript
@@ -1,9 +1,35 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = 'DummyPhysicsEnvironment.cpp'
-incs = '. ../common'
+incs = '. ../common ../../../../intern/moto/include'
defs = []
diff --git a/source/gameengine/Physics/common/PHY_DynamicTypes.h b/source/gameengine/Physics/common/PHY_DynamicTypes.h
index 0fe2533cf93..d10f48ad7a4 100644
--- a/source/gameengine/Physics/common/PHY_DynamicTypes.h
+++ b/source/gameengine/Physics/common/PHY_DynamicTypes.h
@@ -20,69 +20,9 @@ subject to the following restrictions:
#ifndef __PHY_DYNAMICTYPES_H__
#define __PHY_DYNAMICTYPES_H__
-
+#include "MT_Vector3.h"
struct KX_ClientObjectInfo;
-class PHY_Shape;
-
-struct PHY__Vector2
-{
- float m_vec[2];
-
- operator const float* () const
- {
- return &m_vec[0];
- }
- operator float* ()
- {
- return &m_vec[0];
- }
-};
-
-struct PHY__Vector3
-{
- float m_vec[4];
-
- operator const float* () const
- {
- return &m_vec[0];
- }
- operator float* ()
- {
- return &m_vec[0];
- }
-};
-
-struct PHY__Vector4
-{
- float m_vec[4];
- PHY__Vector4() {}
- void setValue(const float *value)
- {
- m_vec[0] = *value++;
- m_vec[1] = *value++;
- m_vec[2] = *value++;
- m_vec[3] = *value++;
- }
- void setValue(const double *value)
- {
- m_vec[0] = (float)(*value++);
- m_vec[1] = (float)(*value++);
- m_vec[2] = (float)(*value++);
- m_vec[3] = (float)(*value++);
- }
-
- operator const float* () const
- {
- return &m_vec[0];
- }
- operator float* ()
- {
- return &m_vec[0];
- }
-};
-
-//typedef float PHY__Vector3[4];
enum
{
@@ -97,9 +37,9 @@ enum
};
typedef struct PHY_CollData {
- PHY__Vector3 m_point1; /* Point in object1 in world coordinates */
- PHY__Vector3 m_point2; /* Point in object2 in world coordinates */
- PHY__Vector3 m_normal; /* point2 - point1 */
+ MT_Vector3 m_point1; /* Point in object1 in world coordinates */
+ MT_Vector3 m_point2; /* Point in object2 in world coordinates */
+ MT_Vector3 m_normal; /* point2 - point1 */
} PHY_CollData;
@@ -148,7 +88,4 @@ typedef enum PHY_ShapeType {
PHY_SHAPE_PROXY
} PHY_ShapeType;
-
-typedef float PHY_Vector3[3];
-
#endif /* __PHY_DYNAMICTYPES_H__ */
diff --git a/source/gameengine/Physics/common/PHY_ICharacter.h b/source/gameengine/Physics/common/PHY_ICharacter.h
index e2fc5e45125..a3d3000a143 100644
--- a/source/gameengine/Physics/common/PHY_ICharacter.h
+++ b/source/gameengine/Physics/common/PHY_ICharacter.h
@@ -15,12 +15,21 @@
class PHY_ICharacter
{
public:
+ virtual ~PHY_ICharacter(){};
virtual void Jump()= 0;
virtual bool OnGround()= 0;
virtual float GetGravity()= 0;
virtual void SetGravity(float gravity)= 0;
+
+ virtual int GetMaxJumps()= 0;
+ virtual void SetMaxJumps(int maxJumps)= 0;
+
+ virtual int GetJumpCount()= 0;
+
+ virtual void SetWalkDirection(const class MT_Vector3& dir)=0;
+ virtual MT_Vector3 GetWalkDirection()=0;
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GE:PHY_ICharacter")
diff --git a/source/gameengine/Physics/common/PHY_IController.h b/source/gameengine/Physics/common/PHY_IController.h
index 003c4edf598..ae1b2d9ad53 100644
--- a/source/gameengine/Physics/common/PHY_IController.h
+++ b/source/gameengine/Physics/common/PHY_IController.h
@@ -41,14 +41,14 @@ class PHY_IPhysicsEnvironment;
#endif
/**
- PHY_IController is the abstract simplified Interface to objects
- controlled by the physics engine. This includes the physics objects
- and the graphics object for view frustrum and occlusion culling.
-*/
+ * PHY_IController is the abstract simplified Interface to objects
+ * controlled by the physics engine. This includes the physics objects
+ * and the graphics object for view frustrum and occlusion culling.
+ */
class PHY_IController
{
public:
- virtual ~PHY_IController();
+ virtual ~PHY_IController(){};
// clientinfo for raycasts for example
virtual void* getNewClientInfo()=0;
virtual void setNewClientInfo(void* clientinfo)=0;
diff --git a/source/gameengine/Physics/common/PHY_IGraphicController.h b/source/gameengine/Physics/common/PHY_IGraphicController.h
index cb13eda4f18..5f64e7ccc80 100644
--- a/source/gameengine/Physics/common/PHY_IGraphicController.h
+++ b/source/gameengine/Physics/common/PHY_IGraphicController.h
@@ -36,19 +36,18 @@
/**
- PHY_IPhysicsController is the abstract simplified Interface to a physical object.
- It contains the IMotionState and IDeformableMesh Interfaces.
-*/
+ * PHY_IPhysicsController is the abstract simplified Interface to a physical object.
+ * It contains the IMotionState and IDeformableMesh Interfaces.
+ */
class PHY_IGraphicController : public PHY_IController
{
public:
- virtual ~PHY_IGraphicController();
/**
- SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
- */
+ * SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
+ */
virtual bool SetGraphicTransform()=0;
virtual void Activate(bool active=true)=0;
- virtual void setLocalAabb(const PHY__Vector3& aabbMin,const PHY__Vector3& aabbMax)=0;
+ virtual void setLocalAabb(const class MT_Vector3& aabbMin,const class MT_Vector3& aabbMax)=0;
virtual void setLocalAabb(const float* aabbMin,const float* aabbMax)=0;
virtual PHY_IGraphicController* GetReplica(class PHY_IMotionState* motionstate) {return 0;}
diff --git a/source/gameengine/Physics/common/PHY_IMotionState.h b/source/gameengine/Physics/common/PHY_IMotionState.h
index ccf7cf74724..be5b2b54907 100644
--- a/source/gameengine/Physics/common/PHY_IMotionState.h
+++ b/source/gameengine/Physics/common/PHY_IMotionState.h
@@ -37,14 +37,14 @@
#endif
/**
- PHY_IMotionState is the Interface to explicitly synchronize the world transformation.
- Default implementations for mayor graphics libraries like OpenGL and DirectX can be provided.
-*/
+ * PHY_IMotionState is the Interface to explicitly synchronize the world transformation.
+ * Default implementations for mayor graphics libraries like OpenGL and DirectX can be provided.
+ */
class PHY_IMotionState
{
public:
- virtual ~PHY_IMotionState();
+ virtual ~PHY_IMotionState(){};
virtual void getWorldPosition(float& posX,float& posY,float& posZ)=0;
virtual void getWorldScaling(float& scaleX,float& scaleY,float& scaleZ)=0;
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h
index bc7671abe80..18af42adc15 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsController.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h
@@ -38,21 +38,21 @@ class PHY_IMotionState;
class PHY_IPhysicsEnvironment;
/**
- PHY_IPhysicsController is the abstract simplified Interface to a physical object.
- It contains the IMotionState and IDeformableMesh Interfaces.
-*/
+ * PHY_IPhysicsController is the abstract simplified Interface to a physical object.
+ * It contains the IMotionState and IDeformableMesh Interfaces.
+ */
class PHY_IPhysicsController : public PHY_IController
{
public:
- virtual ~PHY_IPhysicsController();
+ virtual ~PHY_IPhysicsController(){};
/**
- SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
- */
+ * SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
+ */
virtual bool SynchronizeMotionStates(float time)=0;
/**
- WriteMotionStateToDynamics ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
- */
+ * WriteMotionStateToDynamics ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
+ */
virtual void WriteMotionStateToDynamics(bool nondynaonly)=0;
virtual void WriteDynamicsToMotionState()=0;
@@ -66,7 +66,7 @@ class PHY_IPhysicsController : public PHY_IController
virtual void getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal)=0;
virtual void setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal)=0;
virtual void setPosition(float posX,float posY,float posZ)=0;
- virtual void getPosition(PHY__Vector3& pos) const=0;
+ virtual void getPosition(class MT_Vector3& pos) const=0;
virtual void setScaling(float scaleX,float scaleY,float scaleZ)=0;
// physics methods
@@ -100,7 +100,7 @@ class PHY_IPhysicsController : public PHY_IController
virtual float GetLinVelocityMax() const=0;
virtual void SetLinVelocityMax(float val) = 0;
- PHY__Vector3 GetWorldPosition(PHY__Vector3& localpos);
+ class MT_Vector3 GetWorldPosition(class MT_Vector3& localpos);
#ifdef WITH_CXX_GUARDEDALLOC
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
index bfbe570ad0c..14904a70553 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
@@ -32,8 +32,10 @@
#ifndef __PHY_IPHYSICSENVIRONMENT_H__
#define __PHY_IPHYSICSENVIRONMENT_H__
-#include <vector>
#include "PHY_DynamicTypes.h"
+#include "MT_Vector2.h"
+#include "MT_Vector3.h"
+#include "MT_Vector4.h"
#ifdef WITH_CXX_GUARDEDALLOC
#include "MEM_guardedalloc.h"
@@ -50,13 +52,13 @@ class PHY_IPhysicsController;
struct PHY_RayCastResult
{
PHY_IPhysicsController* m_controller;
- PHY__Vector3 m_hitPoint;
- PHY__Vector3 m_hitNormal;
+ MT_Vector3 m_hitPoint;
+ MT_Vector3 m_hitNormal;
const RAS_MeshObject* m_meshObject; // !=NULL for mesh object (only for Bullet controllers)
int m_polygon; // index of the polygon hit by the ray,
// only if m_meshObject != NULL
int m_hitUVOK; // !=0 if UV coordinate in m_hitUV is valid
- PHY__Vector2 m_hitUV; // UV coordinates of hit point
+ MT_Vector2 m_hitUV; // UV coordinates of hit point
};
/**
@@ -96,13 +98,14 @@ public:
};
/**
-* Physics Environment takes care of stepping the simulation and is a container for physics entities (rigidbodies,constraints, materials etc.)
-* A derived class may be able to 'construct' entities by loading and/or converting
-*/
+ * Physics Environment takes care of stepping the simulation and is a container for physics entities
+ * (rigidbodies,constraints, materials etc.)
+ * A derived class may be able to 'construct' entities by loading and/or converting
+ */
class PHY_IPhysicsEnvironment
{
public:
- virtual ~PHY_IPhysicsEnvironment();
+ virtual ~PHY_IPhysicsEnvironment(){};
virtual void beginFrame() = 0;
virtual void endFrame() = 0;
/// Perform an integration step of duration 'timeStep'.
@@ -143,7 +146,7 @@ class PHY_IPhysicsEnvironment
virtual void setUseEpa(bool epa) {}
virtual void setGravity(float x,float y,float z)=0;
- virtual void getGravity(PHY__Vector3& grav) = 0;
+ virtual void getGravity(MT_Vector3& grav) = 0;
virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
float pivotX,float pivotY,float pivotZ,
@@ -166,7 +169,7 @@ class PHY_IPhysicsEnvironment
//culling based on physical broad phase
// the plane number must be set as follow: near, far, left, right, top, botton
// the near plane must be the first one and must always be present, it is used to get the direction of the view
- virtual bool cullingTest(PHY_CullingCallback callback, void *userData, PHY__Vector4* planeNormals, int planeNumber, int occlusionRes, const int *viewport, double modelview[16], double projection[16]) = 0;
+ virtual bool cullingTest(PHY_CullingCallback callback, void *userData, MT_Vector4* planeNormals, int planeNumber, int occlusionRes, const int *viewport, double modelview[16], double projection[16]) = 0;
//Methods for gamelogic collision/physics callbacks
//todo:
@@ -176,7 +179,7 @@ class PHY_IPhysicsEnvironment
virtual bool requestCollisionCallback(PHY_IPhysicsController* ctrl)=0;
virtual bool removeCollisionCallback(PHY_IPhysicsController* ctrl)=0;
//These two methods are *solely* used to create controllers for sensor! Don't use for anything else
- virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position) =0;
+ virtual PHY_IPhysicsController* CreateSphereController(float radius,const MT_Vector3& position) =0;
virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight)=0;
virtual void setConstraintParam(int constraintId,int param,float value,float value1) = 0;
diff --git a/source/gameengine/Physics/common/PHY_IVehicle.cpp b/source/gameengine/Physics/common/PHY_IVehicle.cpp
deleted file mode 100644
index a60bb3e596d..00000000000
--- a/source/gameengine/Physics/common/PHY_IVehicle.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-/** \file gameengine/Physics/common/PHY_IVehicle.cpp
- * \ingroup phys
- */
-
-#include "PHY_IVehicle.h"
-
-PHY_IVehicle::~PHY_IVehicle()
-{
-
-}
diff --git a/source/gameengine/Physics/common/PHY_IVehicle.h b/source/gameengine/Physics/common/PHY_IVehicle.h
index ecf7a87c40f..1dcec69a335 100644
--- a/source/gameengine/Physics/common/PHY_IVehicle.h
+++ b/source/gameengine/Physics/common/PHY_IVehicle.h
@@ -18,13 +18,13 @@ class PHY_IMotionState;
class PHY_IVehicle
{
public:
- virtual ~PHY_IVehicle();
+ virtual ~PHY_IVehicle(){};
virtual void AddWheel(
PHY_IMotionState* motionState,
- PHY__Vector3 connectionPoint,
- PHY__Vector3 downDirection,
- PHY__Vector3 axleDirection,
+ MT_Vector3 connectionPoint,
+ MT_Vector3 downDirection,
+ MT_Vector3 axleDirection,
float suspensionRestLength,
float wheelRadius,
bool hasSteering
diff --git a/source/gameengine/Physics/common/SConscript b/source/gameengine/Physics/common/SConscript
deleted file mode 100644
index abff3e33121..00000000000
--- a/source/gameengine/Physics/common/SConscript
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/python
-Import ('env')
-
-sources = 'PHY_IMotionState.cpp PHY_IController.cpp PHY_IPhysicsController.cpp PHY_IGraphicController.cpp PHY_IPhysicsEnvironment.cpp PHY_IVehicle.cpp'
-
-incs = '. ../Dummy #intern/moto/include'
-
-defs = []
-
-if env['WITH_BF_CXX_GUARDEDALLOC']:
- defs.append('WITH_CXX_GUARDEDALLOC')
- incs += ' #intern/guardedalloc'
-
-env.BlenderLib ( 'ge_phys_common', Split(sources), Split(incs), defs, libtype=['core','player'], priority=[360,55], cxx_compileflags=env['BGE_CXXFLAGS'])
diff --git a/source/gameengine/Rasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/CMakeLists.txt
index ddc72c08ea1..3ea26c3be9d 100644
--- a/source/gameengine/Rasterizer/CMakeLists.txt
+++ b/source/gameengine/Rasterizer/CMakeLists.txt
@@ -29,6 +29,7 @@ set(INC
../Ketsji
../SceneGraph
../../blender/makesdna
+ ../../blender/blenlib
../../blender/blenkernel
../../../intern/container
../../../intern/guardedalloc
diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
index cf869e71945..e093b7cd722 100644
--- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
@@ -428,14 +428,16 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
// reverting to texunit 0, without this we get bug [#28462]
glActiveTextureARB(GL_TEXTURE0);
-
- glViewport(rect.GetLeft(), rect.GetBottom(), rect_width, rect_height);
+ canvas->SetViewPort(0, 0, rect_width-1, rect_height-1);
glDisable(GL_DEPTH_TEST);
// in case the previous material was wire
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// if the last rendered face had alpha add it would messes with the color of the plane we apply 2DFilter to
glDisable(GL_BLEND);
+ // fix for [#34523] alpha buffer is now available for all OSs
+ glDisable(GL_ALPHA_TEST);
+
glPushMatrix(); //GL_MODELVIEW
glLoadIdentity(); // GL_MODELVIEW
glMatrixMode(GL_TEXTURE);
@@ -466,7 +468,8 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
}
glEnable(GL_DEPTH_TEST);
- glViewport(viewport[0],viewport[1],viewport[2],viewport[3]);
+ //We can't pass the results of canvas->GetViewPort() directly because canvas->SetViewPort() does some extra math [#34517]
+ canvas->SetViewPort(0, 0, viewport[2]-1, viewport[3]-1);
EndShaderProgram();
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp
index f24e3397801..b2b766b65e8 100644
--- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp
@@ -148,7 +148,8 @@ void RAS_BucketManager::RenderAlphaBuckets(
// Having depth masks disabled/enabled gives different artifacts in
// case no sorting is done or is done inexact. For compatibility, we
// disable it.
- rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_DISABLED);
+ if (rasty->GetDrawingMode() != RAS_IRasterizer::KX_SHADOW)
+ rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_DISABLED);
OrderBuckets(cameratrans, m_AlphaBuckets, slots, true);
@@ -232,6 +233,24 @@ void RAS_BucketManager::Renderbuckets(
RenderSolidBuckets(cameratrans, rasty, rendertools);
RenderAlphaBuckets(cameratrans, rasty, rendertools);
+ /* All meshes should be up to date now */
+ /* Don't do this while processing buckets because some meshes are split between buckets */
+ BucketList::iterator bit;
+ list<RAS_MeshSlot>::iterator mit;
+ for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) {
+ // RAS_MaterialBucket *bucket = *bit; /* UNUSED */
+ for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) {
+ mit->m_mesh->SetMeshModified(false);
+ }
+ }
+ for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) {
+ // RAS_MaterialBucket* bucket = *bit; /* UNUSED */
+ for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) {
+ mit->m_mesh->SetMeshModified(false);
+ }
+ }
+
+
rendertools->SetClientObject(rasty, NULL);
}
diff --git a/source/gameengine/Rasterizer/RAS_ICanvas.h b/source/gameengine/Rasterizer/RAS_ICanvas.h
index 60b9f052075..63ad7892aa5 100644
--- a/source/gameengine/Rasterizer/RAS_ICanvas.h
+++ b/source/gameengine/Rasterizer/RAS_ICanvas.h
@@ -178,7 +178,19 @@ public:
SetViewPort(
int x1, int y1,
int x2, int y2
- ) = 0;
+ ) = 0;
+
+ /**
+ * Update the Canvas' viewport (used when the viewport changes without using SetViewPort()
+ * eg: Shadow buffers and FBOs
+ */
+
+ virtual
+ void
+ UpdateViewPort(
+ int x1, int y1,
+ int x2, int y2
+ ) = 0;
/**
* Get the visible viewport
diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
index 9fffc8bebc9..7aeeb364b47 100644
--- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
+++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
@@ -177,14 +177,14 @@ public:
virtual void Replace_IScene(SCA_IScene *val) {} /* overridden by KX_BlenderMaterial */
/**
- * \return the equivalent drawing mode for the material settings (equivalent to old TexFace tface->mode).
- */
+ * \return the equivalent drawing mode for the material settings (equivalent to old TexFace tface->mode).
+ */
int ConvertFaceMode(struct GameSettings *game, bool image) const;
/*
* PreCalculate texture gen
*/
- virtual void OnConstruction(int layer) {}
+ virtual void OnConstruction() {}
#ifdef WITH_CXX_GUARDEDALLOC
diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h
index e6948025999..c04b62bc5da 100644
--- a/source/gameengine/Rasterizer/RAS_IRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h
@@ -52,6 +52,7 @@ using namespace std;
class RAS_ICanvas;
class RAS_IPolyMaterial;
+class RAS_MeshSlot;
typedef vector<unsigned short> KX_IndexArray;
typedef vector<RAS_TexVert> KX_VertexArray;
@@ -129,7 +130,7 @@ public:
RAS_TEXCO_GEN, //< GPU will generate texture coordinates
RAS_TEXCO_ORCO, //< Vertex coordinates (object space)
RAS_TEXCO_GLOB, //< Vertex coordinates (world space)
- RAS_TEXCO_UV1, //< UV coordinates
+ RAS_TEXCO_UV, //< UV coordinates
RAS_TEXCO_OBJECT, //< Use another object's position as coordinates
RAS_TEXCO_LAVECTOR, //< Light vector as coordinates
RAS_TEXCO_VIEW, //< View vector as coordinates
@@ -137,7 +138,6 @@ public:
RAS_TEXCO_WINDOW, //< Window coordinates
RAS_TEXCO_NORM, //< Normal coordinates
RAS_TEXTANGENT, //<
- RAS_TEXCO_UV2, //<
RAS_TEXCO_VCOL, //< Vertex Color
RAS_TEXCO_DISABLE //< Disable this texture unit (cached)
};
@@ -396,7 +396,7 @@ public:
virtual void SetTexCoordNum(int num) = 0;
virtual void SetAttribNum(int num) = 0;
virtual void SetTexCoord(TexCoGen coords, int unit) = 0;
- virtual void SetAttrib(TexCoGen coords, int unit) = 0;
+ virtual void SetAttrib(TexCoGen coords, int unit, int layer = 0) = 0;
virtual const MT_Matrix4x4& GetViewMatrix() const = 0;
virtual const MT_Matrix4x4& GetViewInvMatrix() const = 0;
@@ -417,6 +417,8 @@ public:
virtual void SetAnisotropicFiltering(short level)=0;
virtual short GetAnisotropicFiltering()=0;
+ virtual void SetUsingOverrideShader(bool val)=0;
+ virtual bool GetUsingOverrideShader()=0;
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GE:RAS_IRasterizer")
diff --git a/source/gameengine/Rasterizer/RAS_IRenderTools.h b/source/gameengine/Rasterizer/RAS_IRenderTools.h
index bccda634222..6131abc0650 100644
--- a/source/gameengine/Rasterizer/RAS_IRenderTools.h
+++ b/source/gameengine/Rasterizer/RAS_IRenderTools.h
@@ -100,6 +100,22 @@ public:
double* oglmatrix,
int drawingmode
)=0;
+
+ /**
+ * Renders 2D boxes.
+ * \param xco Position on the screen (origin in lower left corner).
+ * \param yco Position on the screen (origin in lower left corner).
+ * \param width Width of the canvas to draw to.
+ * \param height Height of the canvas to draw to.
+ * \param percentage Percentage of bar.
+ */
+ virtual
+ void
+ RenderBox2D(int xco,
+ int yco,
+ int width,
+ int height,
+ float percentage) = 0;
/**
* Renders 3D text string using BFL.
diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
index 9fb47117f1d..8ea09029a35 100644
--- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
+++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
@@ -605,7 +605,8 @@ void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRa
if (ms.m_pDeformer)
{
- ms.m_pDeformer->Apply(m_material);
+ if (ms.m_pDeformer->Apply(m_material))
+ ms.m_mesh->SetMeshModified(true);
// KX_ReInstanceShapeFromMesh(ms.m_mesh); // Recompute the physics mesh. (Can't call KX_* from RAS_)
}
@@ -648,10 +649,6 @@ void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRa
else
rasty->IndexPrimitives(ms);
- if (rasty->QueryLists())
- if (ms.m_DisplayList)
- ms.m_mesh->SetMeshModified(false);
-
rendertools->PopMatrix();
}
diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp
index 2ccb9453b3d..2af71c5efa9 100644
--- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp
+++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp
@@ -115,7 +115,7 @@ RAS_MeshObject::RAS_MeshObject(Mesh* mesh)
int count=0;
// initialize weight cache for shape objects
// count how many keys in this mesh
- for (kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next)
+ for (kb= (KeyBlock *)m_mesh->key->block.first; kb; kb= (KeyBlock *)kb->next)
count++;
m_cacheWeightIndex.resize(count,-1);
}
@@ -129,7 +129,7 @@ RAS_MeshObject::~RAS_MeshObject()
{
KeyBlock *kb;
// remove the weight cache to avoid memory leak
- for (kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) {
+ for (kb = (KeyBlock *)m_mesh->key->block.first; kb; kb = (KeyBlock *)kb->next) {
if (kb->weights)
MEM_freeN(kb->weights);
kb->weights= NULL;
@@ -324,15 +324,14 @@ void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba)
void RAS_MeshObject::AddVertex(RAS_Polygon *poly, int i,
const MT_Point3& xyz,
- const MT_Point2& uv,
- const MT_Point2& uv2,
+ const MT_Point2 uvs[RAS_TexVert::MAX_UNIT],
const MT_Vector4& tangent,
const unsigned int rgba,
const MT_Vector3& normal,
bool flat,
int origindex)
{
- RAS_TexVert texvert(xyz, uv, uv2, tangent, rgba, normal, flat, origindex);
+ RAS_TexVert texvert(xyz, uvs, tangent, rgba, normal, flat, origindex);
RAS_MeshMaterial *mmat;
RAS_DisplayArray *darray;
RAS_MeshSlot *slot;
diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h
index 281eae8734a..d77d0483024 100644
--- a/source/gameengine/Rasterizer/RAS_MeshObject.h
+++ b/source/gameengine/Rasterizer/RAS_MeshObject.h
@@ -116,8 +116,7 @@ public:
virtual RAS_Polygon* AddPolygon(RAS_MaterialBucket *bucket, int numverts);
virtual void AddVertex(RAS_Polygon *poly, int i,
const MT_Point3& xyz,
- const MT_Point2& uv,
- const MT_Point2& uv2,
+ const MT_Point2 uvs[RAS_TexVert::MAX_UNIT],
const MT_Vector4& tangent,
const unsigned int rgbacolor,
const MT_Vector3& normal,
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt
index 189c4f78f77..11cb4b1d9f9 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt
@@ -46,12 +46,17 @@ set(SRC
RAS_GLExtensionManager.cpp
RAS_ListRasterizer.cpp
RAS_OpenGLRasterizer.cpp
- RAS_VAOpenGLRasterizer.cpp
+ RAS_StorageIM.cpp
+ RAS_StorageVA.cpp
+ RAS_StorageVBO.cpp
RAS_GLExtensionManager.h
+ RAS_IStorage.h
RAS_ListRasterizer.h
RAS_OpenGLRasterizer.h
- RAS_VAOpenGLRasterizer.h
+ RAS_StorageIM.h
+ RAS_StorageVA.h
+ RAS_StorageVBO.h
)
add_definitions(-DGLEW_STATIC)
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_IStorage.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_IStorage.h
new file mode 100644
index 00000000000..f5c16bc8cd8
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_IStorage.h
@@ -0,0 +1,62 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 *****
+ */
+
+#ifndef __KX_STORAGE
+#define __KX_STORAGE
+
+#include "RAS_MaterialBucket.h"
+
+enum RAS_STORAGE_TYPE {
+ RAS_AUTO_STORAGE,
+ RAS_IMMEDIATE,
+ RAS_VA,
+ RAS_VBO
+};
+
+class RAS_IStorage
+{
+
+public:
+ virtual ~RAS_IStorage() {};
+
+ virtual bool Init()=0;
+ virtual void Exit()=0;
+
+ virtual void IndexPrimitives(RAS_MeshSlot& ms)=0;
+ virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms)=0;
+
+ virtual void SetDrawingMode(int drawingmode)=0;
+
+
+#ifdef WITH_CXX_GUARDEDALLOC
+public:
+ void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:RAS_IStorage"); }
+ void operator delete( void *mem ) { MEM_freeN(mem); }
+#endif
+};
+
+#endif //__KX_STORAGE
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
index d74aa134779..3a60643e9e7 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
@@ -106,9 +106,8 @@ bool RAS_ListSlot::End()
-RAS_ListRasterizer::RAS_ListRasterizer(RAS_ICanvas* canvas, bool useVertexArrays, bool lock)
-: RAS_VAOpenGLRasterizer(canvas, lock),
- mUseVertexArrays(useVertexArrays),
+RAS_ListRasterizer::RAS_ListRasterizer(RAS_ICanvas* canvas, bool lock, int storage)
+: RAS_OpenGLRasterizer(canvas, storage),
mATI(false)
{
if (!strcmp((const char*)glGetString(GL_VENDOR), "ATI Technologies Inc."))
@@ -238,11 +237,8 @@ void RAS_ListRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
return;
}
}
- // derived mesh cannot use vertex array
- if (mUseVertexArrays && !ms.m_pDerivedMesh)
- RAS_VAOpenGLRasterizer::IndexPrimitives(ms);
- else
- RAS_OpenGLRasterizer::IndexPrimitives(ms);
+
+ RAS_OpenGLRasterizer::IndexPrimitives(ms);
if (ms.m_bDisplayList) {
localSlot->EndList();
@@ -267,13 +263,7 @@ void RAS_ListRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
}
}
- // workaround: note how we do not use vertex arrays for making display
- // lists, since glVertexAttribPointerARB doesn't seem to work correct
- // in display lists on ATI? either a bug in the driver or in Blender ..
- if (mUseVertexArrays && !mATI && !ms.m_pDerivedMesh)
- RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(ms);
- else
- RAS_OpenGLRasterizer::IndexPrimitivesMulti(ms);
+ RAS_OpenGLRasterizer::IndexPrimitivesMulti(ms);
if (ms.m_bDisplayList) {
localSlot->EndList();
@@ -283,29 +273,17 @@ void RAS_ListRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
bool RAS_ListRasterizer::Init(void)
{
- if (mUseVertexArrays) {
- return RAS_VAOpenGLRasterizer::Init();
- } else {
- return RAS_OpenGLRasterizer::Init();
- }
+ return RAS_OpenGLRasterizer::Init();
}
void RAS_ListRasterizer::SetDrawingMode(int drawingmode)
{
- if (mUseVertexArrays) {
- RAS_VAOpenGLRasterizer::SetDrawingMode(drawingmode);
- } else {
- RAS_OpenGLRasterizer::SetDrawingMode(drawingmode);
- }
+ RAS_OpenGLRasterizer::SetDrawingMode(drawingmode);
}
void RAS_ListRasterizer::Exit()
{
- if (mUseVertexArrays) {
- RAS_VAOpenGLRasterizer::Exit();
- } else {
- RAS_OpenGLRasterizer::Exit();
- }
+ RAS_OpenGLRasterizer::Exit();
}
// eof
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
index a8eb2d5ffdf..558850a9173 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
@@ -7,7 +7,7 @@
#define __RAS_LISTRASTERIZER_H__
#include "RAS_MaterialBucket.h"
-#include "RAS_VAOpenGLRasterizer.h"
+#include "RAS_OpenGLRasterizer.h"
#include <vector>
#include <map>
@@ -49,9 +49,8 @@ typedef std::map<RAS_DisplayArrayList, RAS_ListSlot*> RAS_ArrayLists;
typedef std::vector<RAS_ListSlot*> RAS_ListSlots; // indexed by material slot number
typedef std::map<DerivedMesh*, RAS_ListSlots*> RAS_DerivedMeshLists;
-class RAS_ListRasterizer : public RAS_VAOpenGLRasterizer
+class RAS_ListRasterizer : public RAS_OpenGLRasterizer
{
- bool mUseVertexArrays;
bool mATI;
RAS_ArrayLists mArrayLists;
RAS_DerivedMeshLists mDerivedMeshLists;
@@ -61,7 +60,7 @@ class RAS_ListRasterizer : public RAS_VAOpenGLRasterizer
public:
void RemoveListSlot(RAS_ListSlot* list);
- RAS_ListRasterizer(RAS_ICanvas* canvas, bool useVertexArrays=false, bool lock=false);
+ RAS_ListRasterizer(RAS_ICanvas* canvas, bool lock=false, int storage=RAS_AUTO_STORAGE);
virtual ~RAS_ListRasterizer();
virtual void IndexPrimitives(class RAS_MeshSlot& ms);
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
index 22a700c7d2b..f995f7ddb3d 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
@@ -43,6 +43,10 @@
#include "MT_CmMatrix4x4.h"
#include "RAS_IRenderTools.h" // rendering text
+#include "RAS_StorageIM.h"
+#include "RAS_StorageVA.h"
+#include "RAS_StorageVBO.h"
+
#include "GPU_draw.h"
#include "GPU_material.h"
#include "GPU_extensions.h"
@@ -74,7 +78,7 @@ static GLuint right_eye_vinterlace_mask[32];
*/
static GLuint hinterlace_mask[33];
-RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas)
+RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas, int storage)
:RAS_IRasterizer(canvas),
m_2DCanvas(canvas),
m_fogenabled(false),
@@ -89,11 +93,13 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas)
m_noOfScanlines(32),
m_motionblur(0),
m_motionblurvalue(-1.0),
+ m_usingoverrideshader(false),
m_texco_num(0),
m_attrib_num(0),
//m_last_alphablend(GPU_BLEND_SOLID),
m_last_frontface(true),
- m_materialCachingInfo(0)
+ m_materialCachingInfo(0),
+ m_storage_type(storage)
{
m_viewmatrix.setIdentity();
m_viewinvmatrix.setIdentity();
@@ -107,6 +113,24 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas)
hinterlace_mask[32] = 0;
m_prevafvalue = GPU_get_anisotropic();
+
+ if (m_storage_type == RAS_VBO /*|| m_storage_type == RAS_AUTO_STORAGE && GLEW_ARB_vertex_buffer_object*/)
+ {
+ m_storage = new RAS_StorageVBO(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
+ m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
+ m_storage_type = RAS_VBO;
+ }
+ else if ((m_storage_type == RAS_VA) || (m_storage_type == RAS_AUTO_STORAGE && GLEW_VERSION_1_1))
+ {
+ m_storage = new RAS_StorageVA(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
+ m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
+ m_storage_type = RAS_VA;
+ }
+ else
+ {
+ m_storage = m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m_attrib_num, m_attrib, m_attrib_layer);
+ m_storage_type = RAS_IMMEDIATE;
+ }
}
@@ -115,10 +139,16 @@ RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer()
{
// Restore the previous AF value
GPU_set_anisotropic(m_prevafvalue);
+ if (m_failsafe_storage && m_failsafe_storage != m_storage)
+ delete m_failsafe_storage;
+
+ if (m_storage)
+ delete m_storage;
}
bool RAS_OpenGLRasterizer::Init()
{
+ bool storage_init;
GPU_state_init();
@@ -146,7 +176,9 @@ bool RAS_OpenGLRasterizer::Init()
glShadeModel(GL_SMOOTH);
- return true;
+ storage_init = m_storage->Init();
+
+ return true && storage_init;
}
@@ -267,6 +299,8 @@ bool RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat)
void RAS_OpenGLRasterizer::Exit()
{
+ m_storage->Exit();
+
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glClearDepth(1.0);
@@ -289,7 +323,7 @@ void RAS_OpenGLRasterizer::Exit()
bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time)
{
m_time = time;
- m_drawingmode = drawingmode;
+ SetDrawingMode(drawingmode);
// Blender camera routine destroys the settings
if (m_drawingmode < KX_SOLID)
@@ -328,6 +362,11 @@ void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode)
if (m_drawingmode == KX_WIREFRAME)
glDisable(GL_CULL_FACE);
+
+ m_storage->SetDrawingMode(drawingmode);
+ if (m_failsafe_storage && m_failsafe_storage != m_storage) {
+ m_failsafe_storage->SetDrawingMode(drawingmode);
+ }
}
int RAS_OpenGLRasterizer::GetDrawingMode()
@@ -666,7 +705,7 @@ void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms,
glattrib = -1;
if (GLEW_ARB_vertex_program)
for (unit=0; unit<m_attrib_num; unit++)
- if (m_attrib[unit] == RAS_TEXCO_UV1)
+ if (m_attrib[unit] == RAS_TEXCO_UV)
glattrib = unit;
rendertools->RenderText(polymat->GetDrawingMode(), polymat,
@@ -701,264 +740,29 @@ void RAS_OpenGLRasterizer::SetTexCoord(TexCoGen coords, int unit)
m_texco[unit] = coords;
}
-void RAS_OpenGLRasterizer::SetAttrib(TexCoGen coords, int unit)
+void RAS_OpenGLRasterizer::SetAttrib(TexCoGen coords, int unit, int layer)
{
// this changes from material to material
- if (unit < RAS_MAX_ATTRIB)
+ if (unit < RAS_MAX_ATTRIB) {
m_attrib[unit] = coords;
-}
-
-void RAS_OpenGLRasterizer::TexCoord(const RAS_TexVert &tv)
-{
- int unit;
-
- if (GLEW_ARB_multitexture) {
- for (unit=0; unit<m_texco_num; unit++) {
- if (tv.getFlag() & RAS_TexVert::SECOND_UV && (int)tv.getUnit() == unit) {
- glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2());
- continue;
- }
- switch (m_texco[unit]) {
- case RAS_TEXCO_ORCO:
- case RAS_TEXCO_GLOB:
- glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getXYZ());
- break;
- case RAS_TEXCO_UV1:
- glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV1());
- break;
- case RAS_TEXCO_NORM:
- glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getNormal());
- break;
- case RAS_TEXTANGENT:
- glMultiTexCoord4fvARB(GL_TEXTURE0_ARB+unit, tv.getTangent());
- break;
- case RAS_TEXCO_UV2:
- glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2());
- break;
- default:
- break;
- }
- }
+ m_attrib_layer[unit] = layer;
}
-
- if (GLEW_ARB_vertex_program) {
- for (unit=0; unit<m_attrib_num; unit++) {
- switch (m_attrib[unit]) {
- case RAS_TEXCO_ORCO:
- case RAS_TEXCO_GLOB:
- glVertexAttrib3fvARB(unit, tv.getXYZ());
- break;
- case RAS_TEXCO_UV1:
- glVertexAttrib2fvARB(unit, tv.getUV1());
- break;
- case RAS_TEXCO_NORM:
- glVertexAttrib3fvARB(unit, tv.getNormal());
- break;
- case RAS_TEXTANGENT:
- glVertexAttrib4fvARB(unit, tv.getTangent());
- break;
- case RAS_TEXCO_UV2:
- glVertexAttrib2fvARB(unit, tv.getUV2());
- break;
- case RAS_TEXCO_VCOL:
- glVertexAttrib4ubvARB(unit, tv.getRGBA());
- break;
- default:
- break;
- }
- }
- }
-
}
void RAS_OpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
{
- IndexPrimitivesInternal(ms, false);
+ if (ms.m_pDerivedMesh)
+ m_failsafe_storage->IndexPrimitives(ms);
+ else
+ m_storage->IndexPrimitives(ms);
}
void RAS_OpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
{
- IndexPrimitivesInternal(ms, true);
-}
-
-static bool current_wireframe;
-static RAS_MaterialBucket *current_bucket;
-static RAS_IPolyMaterial *current_polymat;
-static RAS_MeshSlot *current_ms;
-static RAS_MeshObject *current_mesh;
-static int current_blmat_nr;
-static GPUVertexAttribs current_gpu_attribs;
-static Image *current_image;
-static int CheckMaterialDM(int matnr, void *attribs)
-{
- // only draw the current material
- if (matnr != current_blmat_nr)
- return 0;
- GPUVertexAttribs *gattribs = (GPUVertexAttribs *)attribs;
- if (gattribs)
- memcpy(gattribs, &current_gpu_attribs, sizeof(GPUVertexAttribs));
- return 1;
-}
-
-/*
-static int CheckTexfaceDM(void *mcol, int index)
-{
-
- // index is the original face index, retrieve the polygon
- RAS_Polygon* polygon = (index >= 0 && index < current_mesh->NumPolygons()) ?
- current_mesh->GetPolygon(index) : NULL;
- if (polygon && polygon->GetMaterial() == current_bucket) {
- // must handle color.
- if (current_wireframe)
- return 2;
- if (current_ms->m_bObjectColor) {
- MT_Vector4& rgba = current_ms->m_RGBAcolor;
- glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
- // don't use mcol
- return 2;
- }
- if (!mcol) {
- // we have to set the color from the material
- unsigned char rgba[4];
- current_polymat->GetMaterialRGBAColor(rgba);
- glColor4ubv((const GLubyte *)rgba);
- return 2;
- }
- return 1;
- }
- return 0;
-}
-*/
-
-static DMDrawOption CheckTexDM(MTFace *tface, int has_mcol, int matnr)
-{
-
- // index is the original face index, retrieve the polygon
- if (matnr == current_blmat_nr &&
- (tface == NULL || tface->tpage == current_image)) {
- // must handle color.
- if (current_wireframe)
- return DM_DRAW_OPTION_NO_MCOL;
- if (current_ms->m_bObjectColor) {
- MT_Vector4& rgba = current_ms->m_RGBAcolor;
- glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
- // don't use mcol
- return DM_DRAW_OPTION_NO_MCOL;
- }
- if (!has_mcol) {
- // we have to set the color from the material
- unsigned char rgba[4];
- current_polymat->GetMaterialRGBAColor(rgba);
- glColor4ubv((const GLubyte *)rgba);
- return DM_DRAW_OPTION_NO_MCOL;
- }
- return DM_DRAW_OPTION_NORMAL;
- }
- return DM_DRAW_OPTION_SKIP;
-}
-
-void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
-{
- bool obcolor = ms.m_bObjectColor;
- bool wireframe = m_drawingmode <= KX_WIREFRAME;
- MT_Vector4& rgba = ms.m_RGBAcolor;
- RAS_MeshSlot::iterator it;
-
- if (ms.m_pDerivedMesh) {
- // mesh data is in derived mesh,
- current_bucket = ms.m_bucket;
- current_polymat = current_bucket->GetPolyMaterial();
- current_ms = &ms;
- current_mesh = ms.m_mesh;
- current_wireframe = wireframe;
- // MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL); /* UNUSED */
-
- // handle two-side
- if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_BACKCULL)
- this->SetCullFace(true);
- else
- this->SetCullFace(false);
-
- if (current_polymat->GetFlag() & RAS_BLENDERGLSL) {
- // GetMaterialIndex return the original mface material index,
- // increment by 1 to match what derived mesh is doing
- current_blmat_nr = current_polymat->GetMaterialIndex()+1;
- // For GLSL we need to retrieve the GPU material attribute
- 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);
- else
- memset(&current_gpu_attribs, 0, sizeof(current_gpu_attribs));
- // DM draw can mess up blending mode, restore at the end
- int current_blend_mode = GPU_get_material_alpha_blend();
- ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM);
- GPU_set_material_alpha_blend(current_blend_mode);
- }
- else {
- //ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol);
- current_blmat_nr = current_polymat->GetMaterialIndex();
- current_image = current_polymat->GetBlenderImage();
- ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL);
- }
- return;
- }
- // iterate over display arrays, each containing an index + vertex array
- for (ms.begin(it); !ms.end(it); ms.next(it)) {
- RAS_TexVert *vertex;
- size_t i, j, numvert;
-
- numvert = it.array->m_type;
-
- if (it.array->m_type == RAS_DisplayArray::LINE) {
- // line drawing
- glBegin(GL_LINES);
-
- for (i=0; i<it.totindex; i+=2)
- {
- vertex = &it.vertex[it.index[i]];
- glVertex3fv(vertex->getXYZ());
-
- vertex = &it.vertex[it.index[i+1]];
- glVertex3fv(vertex->getXYZ());
- }
-
- glEnd();
- }
- else {
- // triangle and quad drawing
- if (it.array->m_type == RAS_DisplayArray::TRIANGLE)
- glBegin(GL_TRIANGLES);
- else
- glBegin(GL_QUADS);
-
- for (i=0; i<it.totindex; i+=numvert)
- {
- if (obcolor)
- glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
-
- for (j=0; j<numvert; j++) {
- vertex = &it.vertex[it.index[i+j]];
-
- if (!wireframe) {
- if (!obcolor)
- glColor4ubv((const GLubyte *)(vertex->getRGBA()));
-
- glNormal3fv(vertex->getNormal());
-
- if (multi)
- TexCoord(*vertex);
- else
- glTexCoord2fv(vertex->getUV1());
- }
-
- glVertex3fv(vertex->getXYZ());
- }
- }
-
- glEnd();
- }
- }
+ if (ms.m_pDerivedMesh)
+ m_failsafe_storage->IndexPrimitivesMulti(ms);
+ else
+ m_storage->IndexPrimitivesMulti(ms);
}
void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat)
@@ -1259,3 +1063,14 @@ short RAS_OpenGLRasterizer::GetAnisotropicFiltering()
{
return (short)GPU_get_anisotropic();
}
+
+void RAS_OpenGLRasterizer::SetUsingOverrideShader(bool val)
+{
+ m_usingoverrideshader = val;
+}
+
+bool RAS_OpenGLRasterizer::GetUsingOverrideShader()
+{
+ return m_usingoverrideshader;
+}
+
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
index 88bb0be531b..94589f84197 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
@@ -41,6 +41,7 @@
using namespace std;
#include "RAS_IRasterizer.h"
+#include "RAS_IStorage.h"
#include "RAS_MaterialBucket.h"
#include "RAS_ICanvas.h"
@@ -83,7 +84,6 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer
float m_ambr;
float m_ambg;
float m_ambb;
-
double m_time;
MT_Matrix4x4 m_viewmatrix;
MT_Matrix4x4 m_viewinvmatrix;
@@ -103,10 +103,13 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer
int m_motionblur;
float m_motionblurvalue;
+ bool m_usingoverrideshader;
+
protected:
int m_drawingmode;
TexCoGen m_texco[RAS_MAX_TEXCO];
TexCoGen m_attrib[RAS_MAX_ATTRIB];
+ int m_attrib_layer[RAS_MAX_ATTRIB];
int m_texco_num;
int m_attrib_num;
//int m_last_alphablend;
@@ -115,9 +118,16 @@ protected:
/** Stores the caching information for the last material activated. */
RAS_IPolyMaterial::TCachingInfo m_materialCachingInfo;
+ /**
+ * Making use of a Strategy desing pattern for storage behavior.
+ * Examples of concrete strategies: Vertex Arrays, VBOs, Immediate Mode*/
+ int m_storage_type;
+ RAS_IStorage* m_storage;
+ RAS_IStorage* m_failsafe_storage; //So derived mesh can use immediate mode
+
public:
double GetTime();
- RAS_OpenGLRasterizer(RAS_ICanvas* canv);
+ RAS_OpenGLRasterizer(RAS_ICanvas* canv, int storage=RAS_AUTO_STORAGE);
virtual ~RAS_OpenGLRasterizer();
/*enum DrawType
@@ -166,8 +176,6 @@ public:
class RAS_IPolyMaterial* polymat,
class RAS_IRenderTools* rendertools);
- void IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi);
-
virtual void SetProjectionMatrix(MT_CmMatrix4x4 & mat);
virtual void SetProjectionMatrix(const MT_Matrix4x4 & mat);
virtual void SetViewMatrix(
@@ -289,7 +297,7 @@ public:
virtual void SetTexCoordNum(int num);
virtual void SetAttribNum(int num);
virtual void SetTexCoord(TexCoGen coords, int unit);
- virtual void SetAttrib(TexCoGen coords, int unit);
+ virtual void SetAttrib(TexCoGen coords, int unit, int layer = 0);
void TexCoord(const RAS_TexVert &tv);
@@ -316,6 +324,8 @@ public:
virtual void SetAnisotropicFiltering(short level);
virtual short GetAnisotropicFiltering();
+ virtual void SetUsingOverrideShader(bool val);
+ virtual bool GetUsingOverrideShader();
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("GE:RAS_OpenGLRasterizer")
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp
new file mode 100644
index 00000000000..900d6f387ff
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp
@@ -0,0 +1,310 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 *****
+ */
+
+#include "RAS_StorageIM.h"
+
+#include "GL/glew.h"
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_material.h"
+
+#include "DNA_meshdata_types.h"
+
+extern "C"{
+ #include "BLI_utildefines.h"
+ #include "BKE_DerivedMesh.h"
+}
+
+RAS_StorageIM::RAS_StorageIM(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib, int *attrib_layer) :
+ m_texco_num(texco_num),
+ m_attrib_num(attrib_num),
+ m_texco(texco),
+ m_attrib(attrib),
+ m_attrib_layer(attrib_layer)
+{
+}
+RAS_StorageIM::~RAS_StorageIM()
+{
+}
+
+bool RAS_StorageIM::Init()
+{
+ return true;
+}
+void RAS_StorageIM::Exit()
+{
+}
+
+void RAS_StorageIM::IndexPrimitives(RAS_MeshSlot& ms)
+{
+ IndexPrimitivesInternal(ms, false);
+}
+
+void RAS_StorageIM::IndexPrimitivesMulti(class RAS_MeshSlot& ms)
+{
+ IndexPrimitivesInternal(ms, true);
+}
+
+void RAS_StorageIM::TexCoord(const RAS_TexVert &tv)
+{
+ int unit;
+
+ if (GLEW_ARB_multitexture) {
+ for (unit = 0; unit < *m_texco_num; unit++) {
+ switch (m_texco[unit]) {
+ case RAS_IRasterizer::RAS_TEXCO_ORCO:
+ case RAS_IRasterizer::RAS_TEXCO_GLOB:
+ glMultiTexCoord3fvARB(GL_TEXTURE0_ARB + unit, tv.getXYZ());
+ break;
+ case RAS_IRasterizer::RAS_TEXCO_UV:
+ glMultiTexCoord2fvARB(GL_TEXTURE0_ARB + unit, tv.getUV(unit));
+ break;
+ case RAS_IRasterizer::RAS_TEXCO_NORM:
+ glMultiTexCoord3fvARB(GL_TEXTURE0_ARB + unit, tv.getNormal());
+ break;
+ case RAS_IRasterizer::RAS_TEXTANGENT:
+ glMultiTexCoord4fvARB(GL_TEXTURE0_ARB + unit, tv.getTangent());
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (GLEW_ARB_vertex_program) {
+ for (unit = 0; unit < *m_attrib_num; unit++) {
+ switch (m_attrib[unit]) {
+ case RAS_IRasterizer::RAS_TEXCO_ORCO:
+ case RAS_IRasterizer::RAS_TEXCO_GLOB:
+ glVertexAttrib3fvARB(unit, tv.getXYZ());
+ break;
+ case RAS_IRasterizer::RAS_TEXCO_UV:
+ glVertexAttrib2fvARB(unit, tv.getUV(m_attrib_layer[unit]));
+ break;
+ case RAS_IRasterizer::RAS_TEXCO_NORM:
+ glVertexAttrib3fvARB(unit, tv.getNormal());
+ break;
+ case RAS_IRasterizer::RAS_TEXTANGENT:
+ glVertexAttrib4fvARB(unit, tv.getTangent());
+ break;
+ case RAS_IRasterizer::RAS_TEXCO_VCOL:
+ glVertexAttrib4ubvARB(unit, tv.getRGBA());
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+}
+
+void RAS_StorageIM::SetCullFace(bool enable)
+{
+ if (enable)
+ glEnable(GL_CULL_FACE);
+ else
+ glDisable(GL_CULL_FACE);
+}
+
+static bool current_wireframe;
+static RAS_MaterialBucket *current_bucket;
+static RAS_IPolyMaterial *current_polymat;
+static RAS_MeshSlot *current_ms;
+static RAS_MeshObject *current_mesh;
+static int current_blmat_nr;
+static GPUVertexAttribs current_gpu_attribs;
+static Image *current_image;
+static int CheckMaterialDM(int matnr, void *attribs)
+{
+ // only draw the current material
+ if (matnr != current_blmat_nr)
+ return 0;
+ GPUVertexAttribs *gattribs = (GPUVertexAttribs *)attribs;
+ if (gattribs)
+ memcpy(gattribs, &current_gpu_attribs, sizeof(GPUVertexAttribs));
+ return 1;
+}
+
+/*
+static int CheckTexfaceDM(void *mcol, int index)
+{
+
+ // index is the original face index, retrieve the polygon
+ RAS_Polygon* polygon = (index >= 0 && index < current_mesh->NumPolygons()) ?
+ current_mesh->GetPolygon(index) : NULL;
+ if (polygon && polygon->GetMaterial() == current_bucket) {
+ // must handle color.
+ if (current_wireframe)
+ return 2;
+ if (current_ms->m_bObjectColor) {
+ MT_Vector4& rgba = current_ms->m_RGBAcolor;
+ glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
+ // don't use mcol
+ return 2;
+ }
+ if (!mcol) {
+ // we have to set the color from the material
+ unsigned char rgba[4];
+ current_polymat->GetMaterialRGBAColor(rgba);
+ glColor4ubv((const GLubyte *)rgba);
+ return 2;
+ }
+ return 1;
+ }
+ return 0;
+}
+*/
+
+static DMDrawOption CheckTexDM(MTFace *tface, int has_mcol, int matnr)
+{
+
+ // index is the original face index, retrieve the polygon
+ if (matnr == current_blmat_nr &&
+ (tface == NULL || tface->tpage == current_image)) {
+ // must handle color.
+ if (current_wireframe)
+ return DM_DRAW_OPTION_NO_MCOL;
+ if (current_ms->m_bObjectColor) {
+ MT_Vector4& rgba = current_ms->m_RGBAcolor;
+ glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
+ // don't use mcol
+ return DM_DRAW_OPTION_NO_MCOL;
+ }
+ if (!has_mcol) {
+ // we have to set the color from the material
+ unsigned char rgba[4];
+ current_polymat->GetMaterialRGBAColor(rgba);
+ glColor4ubv((const GLubyte *)rgba);
+ return DM_DRAW_OPTION_NO_MCOL;
+ }
+ return DM_DRAW_OPTION_NORMAL;
+ }
+ return DM_DRAW_OPTION_SKIP;
+}
+
+void RAS_StorageIM::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
+{
+ bool obcolor = ms.m_bObjectColor;
+ bool wireframe = m_drawingmode <= RAS_IRasterizer::KX_WIREFRAME;
+ MT_Vector4& rgba = ms.m_RGBAcolor;
+ RAS_MeshSlot::iterator it;
+
+ if (ms.m_pDerivedMesh) {
+ // mesh data is in derived mesh,
+ current_bucket = ms.m_bucket;
+ current_polymat = current_bucket->GetPolyMaterial();
+ current_ms = &ms;
+ current_mesh = ms.m_mesh;
+ current_wireframe = wireframe;
+ // MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL); /* UNUSED */
+
+ // handle two-side
+ if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_BACKCULL)
+ this->SetCullFace(true);
+ else
+ this->SetCullFace(false);
+
+ if (current_polymat->GetFlag() & RAS_BLENDERGLSL) {
+ // GetMaterialIndex return the original mface material index,
+ // increment by 1 to match what derived mesh is doing
+ current_blmat_nr = current_polymat->GetMaterialIndex()+1;
+ // For GLSL we need to retrieve the GPU material attribute
+ 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);
+ else
+ memset(&current_gpu_attribs, 0, sizeof(current_gpu_attribs));
+ // DM draw can mess up blending mode, restore at the end
+ int current_blend_mode = GPU_get_material_alpha_blend();
+ ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM);
+ GPU_set_material_alpha_blend(current_blend_mode);
+ } else {
+ //ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol);
+ current_blmat_nr = current_polymat->GetMaterialIndex();
+ current_image = current_polymat->GetBlenderImage();
+ ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL);
+ }
+ return;
+ }
+ // iterate over display arrays, each containing an index + vertex array
+ for (ms.begin(it); !ms.end(it); ms.next(it)) {
+ RAS_TexVert *vertex;
+ size_t i, j, numvert;
+
+ numvert = it.array->m_type;
+
+ if (it.array->m_type == RAS_DisplayArray::LINE) {
+ // line drawing
+ glBegin(GL_LINES);
+
+ for (i = 0; i < it.totindex; i += 2)
+ {
+ vertex = &it.vertex[it.index[i]];
+ glVertex3fv(vertex->getXYZ());
+
+ vertex = &it.vertex[it.index[i+1]];
+ glVertex3fv(vertex->getXYZ());
+ }
+
+ glEnd();
+ }
+ else {
+ // triangle and quad drawing
+ if (it.array->m_type == RAS_DisplayArray::TRIANGLE)
+ glBegin(GL_TRIANGLES);
+ else
+ glBegin(GL_QUADS);
+
+ for (i = 0; i < it.totindex; i += numvert)
+ {
+ if (obcolor)
+ glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
+
+ for (j = 0; j < numvert; j++) {
+ vertex = &it.vertex[it.index[i+j]];
+
+ if (!wireframe) {
+ if (!obcolor)
+ glColor4ubv((const GLubyte *)(vertex->getRGBA()));
+
+ glNormal3fv(vertex->getNormal());
+
+ if (multi)
+ TexCoord(*vertex);
+ else
+ glTexCoord2fv(vertex->getUV(0));
+ }
+
+ glVertex3fv(vertex->getXYZ());
+ }
+ }
+
+ glEnd();
+ }
+ }
+}
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.h
new file mode 100644
index 00000000000..54ba2a57b61
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.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) 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 *****
+ */
+
+#ifndef __KX_IMMEDIATEMODESTORAGE
+#define __KX_IMMEDIATEMODESTORAGE
+
+#include "RAS_IStorage.h"
+#include "RAS_IRasterizer.h"
+
+class RAS_StorageIM : public RAS_IStorage
+{
+public:
+ RAS_StorageIM(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib, int *attrib_layer);
+ virtual ~RAS_StorageIM();
+
+ virtual bool Init();
+ virtual void Exit();
+
+ virtual void IndexPrimitives(RAS_MeshSlot& ms);
+ virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms);
+
+ virtual void SetDrawingMode(int drawingmode){m_drawingmode=drawingmode;};
+
+protected:
+ int m_drawingmode;
+ int* m_texco_num;
+ int* m_attrib_num;
+ RAS_IRasterizer::TexCoGen* m_texco;
+ RAS_IRasterizer::TexCoGen* m_attrib;
+ int* m_attrib_layer;
+
+ void TexCoord(const RAS_TexVert &tv);
+ void SetCullFace(bool enable);
+
+ void IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi);
+
+
+#ifdef WITH_CXX_GUARDEDALLOC
+public:
+ void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:RAS_StorageIM"); }
+ void operator delete( void *mem ) { MEM_freeN(mem); }
+#endif
+};
+
+#endif //__KX_IMMEDIATEMODESTORAGE
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp
new file mode 100644
index 00000000000..72af3852cf6
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp
@@ -0,0 +1,320 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 *****
+ */
+
+#include "RAS_StorageVA.h"
+
+#include "GL/glew.h"
+
+RAS_StorageVA::RAS_StorageVA(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib, int *attrib_layer) :
+ m_texco_num(texco_num),
+ m_attrib_num(attrib_num),
+ m_last_texco_num(0),
+ m_last_attrib_num(0),
+ m_texco(texco),
+ m_attrib(attrib),
+ m_attrib_layer(attrib_layer)
+{
+}
+
+RAS_StorageVA::~RAS_StorageVA()
+{
+}
+
+bool RAS_StorageVA::Init()
+{
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ return true;
+}
+
+void RAS_StorageVA::Exit()
+{
+}
+
+void RAS_StorageVA::IndexPrimitives(RAS_MeshSlot& ms)
+{
+ static const GLsizei stride = sizeof(RAS_TexVert);
+ bool wireframe = m_drawingmode <= RAS_IRasterizer::KX_WIREFRAME;
+ RAS_MeshSlot::iterator it;
+ GLenum drawmode;
+
+ if (!wireframe)
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+
+ // use glDrawElements to draw each vertexarray
+ for (ms.begin(it); !ms.end(it); ms.next(it)) {
+ if (it.totindex == 0)
+ continue;
+
+ // drawing mode
+ if (it.array->m_type == RAS_DisplayArray::TRIANGLE)
+ drawmode = GL_TRIANGLES;
+ else if (it.array->m_type == RAS_DisplayArray::QUAD)
+ drawmode = GL_QUADS;
+ else
+ drawmode = GL_LINES;
+
+ // colors
+ if (drawmode != GL_LINES && !wireframe) {
+ if (ms.m_bObjectColor) {
+ const MT_Vector4& rgba = ms.m_RGBAcolor;
+
+ glDisableClientState(GL_COLOR_ARRAY);
+ glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
+ }
+ else {
+ glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+ glEnableClientState(GL_COLOR_ARRAY);
+ }
+ }
+ else
+ glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+
+ glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ());
+ glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal());
+ if (!wireframe) {
+ glTexCoordPointer(2, GL_FLOAT, stride, it.vertex->getUV(0));
+ if (glIsEnabled(GL_COLOR_ARRAY))
+ glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA());
+ }
+
+ // here the actual drawing takes places
+ glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index);
+ }
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ if (!wireframe) {
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ }
+}
+
+void RAS_StorageVA::IndexPrimitivesMulti(class RAS_MeshSlot& ms)
+{
+ static const GLsizei stride = sizeof(RAS_TexVert);
+ bool wireframe = m_drawingmode <= RAS_IRasterizer::KX_WIREFRAME, use_color_array = true;
+ RAS_MeshSlot::iterator it;
+ GLenum drawmode;
+
+ if (!wireframe)
+ EnableTextures(true);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+
+ // use glDrawElements to draw each vertexarray
+ for (ms.begin(it); !ms.end(it); ms.next(it)) {
+ if (it.totindex == 0)
+ continue;
+
+ // drawing mode
+ if (it.array->m_type == RAS_DisplayArray::TRIANGLE)
+ drawmode = GL_TRIANGLES;
+ else if (it.array->m_type == RAS_DisplayArray::QUAD)
+ drawmode = GL_QUADS;
+ else
+ drawmode = GL_LINES;
+
+ // colors
+ if (drawmode != GL_LINES && !wireframe) {
+ if (ms.m_bObjectColor) {
+ const MT_Vector4& rgba = ms.m_RGBAcolor;
+
+ glDisableClientState(GL_COLOR_ARRAY);
+ glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
+ use_color_array = false;
+ }
+ else {
+ glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+ glEnableClientState(GL_COLOR_ARRAY);
+ use_color_array = true;
+ }
+ }
+ else
+ glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+
+ glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ());
+ glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal());
+
+ if (!wireframe) {
+ TexCoordPtr(it.vertex);
+ if (use_color_array)
+ glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA());
+ }
+
+ // here the actual drawing takes places
+ glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index);
+ }
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ if (!wireframe) {
+ glDisableClientState(GL_COLOR_ARRAY);
+ EnableTextures(false);
+ }
+}
+
+void RAS_StorageVA::TexCoordPtr(const RAS_TexVert *tv)
+{
+ /* note: this function must closely match EnableTextures to enable/disable
+ * the right arrays, otherwise coordinate and attribute pointers from other
+ * materials can still be used and cause crashes */
+ int unit;
+
+ if (GLEW_ARB_multitexture)
+ {
+ for (unit = 0; unit < *m_texco_num; unit++)
+ {
+ glClientActiveTextureARB(GL_TEXTURE0_ARB+unit);
+ switch (m_texco[unit]) {
+ case RAS_IRasterizer::RAS_TEXCO_ORCO:
+ case RAS_IRasterizer::RAS_TEXCO_GLOB:
+ glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getXYZ());
+ break;
+ case RAS_IRasterizer::RAS_TEXCO_UV:
+ glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV(unit));
+ break;
+ case RAS_IRasterizer::RAS_TEXCO_NORM:
+ glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getNormal());
+ break;
+ case RAS_IRasterizer::RAS_TEXTANGENT:
+ glTexCoordPointer(4, GL_FLOAT, sizeof(RAS_TexVert),tv->getTangent());
+ break;
+ default:
+ break;
+ }
+ }
+
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ }
+
+ if (GLEW_ARB_vertex_program) {
+ for (unit = 0; unit < *m_attrib_num; unit++) {
+ switch (m_attrib[unit]) {
+ case RAS_IRasterizer::RAS_TEXCO_ORCO:
+ case RAS_IRasterizer::RAS_TEXCO_GLOB:
+ glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getXYZ());
+ break;
+ case RAS_IRasterizer::RAS_TEXCO_UV:
+ glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV(m_attrib_layer[unit]));
+ break;
+ case RAS_IRasterizer::RAS_TEXCO_NORM:
+ glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getNormal());
+ break;
+ case RAS_IRasterizer::RAS_TEXTANGENT:
+ glVertexAttribPointerARB(unit, 4, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getTangent());
+ break;
+ case RAS_IRasterizer::RAS_TEXCO_VCOL:
+ glVertexAttribPointerARB(unit, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(RAS_TexVert), tv->getRGBA());
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+void RAS_StorageVA::EnableTextures(bool enable)
+{
+ RAS_IRasterizer::TexCoGen *texco, *attrib;
+ int unit, texco_num, attrib_num;
+
+ /* we cache last texcoords and attribs to ensure we disable the ones that
+ * were actually last set */
+ if (enable) {
+ texco = m_texco;
+ texco_num = *m_texco_num;
+ attrib = m_attrib;
+ attrib_num = *m_attrib_num;
+
+ memcpy(m_last_texco, m_texco, sizeof(RAS_IRasterizer::TexCoGen)*(*m_texco_num));
+ m_last_texco_num = *m_texco_num;
+ memcpy(m_last_attrib, m_attrib, sizeof(RAS_IRasterizer::TexCoGen)*(*m_attrib_num));
+ m_last_attrib_num = *m_attrib_num;
+ }
+ else {
+ texco = m_last_texco;
+ texco_num = m_last_texco_num;
+ attrib = m_last_attrib;
+ attrib_num = m_last_attrib_num;
+ }
+
+ if (GLEW_ARB_multitexture) {
+ for (unit = 0; unit < texco_num; unit++) {
+ glClientActiveTextureARB(GL_TEXTURE0_ARB + unit);
+
+ switch (texco[unit]) {
+ case RAS_IRasterizer::RAS_TEXCO_ORCO:
+ case RAS_IRasterizer::RAS_TEXCO_GLOB:
+ case RAS_IRasterizer::RAS_TEXCO_UV:
+ case RAS_IRasterizer::RAS_TEXCO_NORM:
+ case RAS_IRasterizer::RAS_TEXTANGENT:
+ if (enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ else glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ break;
+ default:
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ break;
+ }
+ }
+
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ }
+ else {
+ if (texco_num) {
+ if (enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ else glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ }
+
+ if (GLEW_ARB_vertex_program) {
+ for (unit = 0; unit < attrib_num; unit++) {
+ switch (attrib[unit]) {
+ case RAS_IRasterizer::RAS_TEXCO_ORCO:
+ case RAS_IRasterizer::RAS_TEXCO_GLOB:
+ case RAS_IRasterizer::RAS_TEXCO_UV:
+ case RAS_IRasterizer::RAS_TEXCO_NORM:
+ case RAS_IRasterizer::RAS_TEXTANGENT:
+ case RAS_IRasterizer::RAS_TEXCO_VCOL:
+ if (enable) glEnableVertexAttribArrayARB(unit);
+ else glDisableVertexAttribArrayARB(unit);
+ break;
+ default:
+ glDisableVertexAttribArrayARB(unit);
+ break;
+ }
+ }
+ }
+
+ if (!enable) {
+ m_last_texco_num = 0;
+ m_last_attrib_num = 0;
+ }
+}
+
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.h
index 6b159db05ed..e4d00310a11 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.h
@@ -25,46 +25,54 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file RAS_VAOpenGLRasterizer.h
- * \ingroup bgerastogl
- */
+#ifndef __KX_VERTEXARRAYSTORAGE
+#define __KX_VERTEXARRAYSTORAGE
-#ifndef __RAS_VAOPENGLRASTERIZER_H__
-#define __RAS_VAOPENGLRASTERIZER_H__
+#include "RAS_IStorage.h"
+#include "RAS_IRasterizer.h"
#include "RAS_OpenGLRasterizer.h"
-class RAS_VAOpenGLRasterizer : public RAS_OpenGLRasterizer
+class RAS_StorageVA : public RAS_IStorage
{
- void TexCoordPtr(const RAS_TexVert *tv);
- /* bool m_Lock; */ /* UNUSED */
-
- TexCoGen m_last_texco[RAS_MAX_TEXCO];
- TexCoGen m_last_attrib[RAS_MAX_ATTRIB];
- int m_last_texco_num;
- int m_last_attrib_num;
public:
- RAS_VAOpenGLRasterizer(RAS_ICanvas* canvas, bool lock=false);
- virtual ~RAS_VAOpenGLRasterizer();
+ RAS_StorageVA(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib, int *attrib_layer);
+ virtual ~RAS_StorageVA();
virtual bool Init();
virtual void Exit();
- virtual void SetDrawingMode(int drawingmode);
-
- virtual void IndexPrimitives(class RAS_MeshSlot& ms);
+ virtual void IndexPrimitives(RAS_MeshSlot& ms);
virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms);
-private:
+ virtual void SetDrawingMode(int drawingmode){m_drawingmode=drawingmode;};
+
+protected:
+ int m_drawingmode;
+
+ int* m_texco_num;
+ int* m_attrib_num;
+
+ int m_last_texco_num;
+ int m_last_attrib_num;
+
+ RAS_IRasterizer::TexCoGen* m_texco;
+ RAS_IRasterizer::TexCoGen* m_attrib;
+ int* m_attrib_layer;
+
+ RAS_IRasterizer::TexCoGen m_last_texco[RAS_MAX_TEXCO];
+ RAS_IRasterizer::TexCoGen m_last_attrib[RAS_MAX_ATTRIB];
+
virtual void EnableTextures(bool enable);
- //virtual bool QueryArrays() {return true;}
- //virtual bool QueryLists() {return m_Lock;}
+ virtual void TexCoordPtr(const RAS_TexVert *tv);
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("GE:RAS_VAOpenGLRasterizer")
+public:
+ void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:RAS_StorageVA"); }
+ void operator delete( void *mem ) { MEM_freeN(mem); }
#endif
};
-#endif /* __RAS_VAOPENGLRASTERIZER_H__ */
+#endif //__KX_VERTEXARRAYSTORAGE
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp
new file mode 100644
index 00000000000..3de77951fa7
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp
@@ -0,0 +1,258 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 *****
+ */
+
+#include "RAS_StorageVBO.h"
+#include "RAS_MeshObject.h"
+
+#include "GL/glew.h"
+
+VBO::VBO(RAS_DisplayArray *data, unsigned int indices)
+{
+ this->data = data;
+ this->size = data->m_vertex.size();
+ this->indices = indices;
+ this->stride = 32*sizeof(GLfloat); // ATI cards really like 32byte aligned VBOs, so we add a little padding
+
+ // Determine drawmode
+ if (data->m_type == data->QUAD)
+ this->mode = GL_QUADS;
+ else if (data->m_type == data->TRIANGLE)
+ this->mode = GL_TRIANGLES;
+ else
+ this->mode = GL_LINE;
+
+ // Generate Buffers
+ glGenBuffersARB(1, &this->ibo);
+ glGenBuffersARB(1, &this->vbo_id);
+
+ // Fill the buffers with initial data
+ UpdateIndices();
+ UpdateData();
+
+ // Establish offsets
+ this->vertex_offset = 0;
+ this->normal_offset = (void*)(3*sizeof(GLfloat));
+ this->tangent_offset = (void*)(6*sizeof(GLfloat));
+ this->color_offset = (void*)(10*sizeof(GLfloat));
+ this->uv_offset = (void*)(11*sizeof(GLfloat));
+}
+
+VBO::~VBO()
+{
+ glDeleteBuffersARB(1, &this->ibo);
+ glDeleteBuffersARB(1, &this->vbo_id);
+}
+
+void VBO::UpdateData()
+{
+ unsigned int i, j, k;
+
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vbo_id);
+ glBufferData(GL_ARRAY_BUFFER, this->stride*this->size, NULL, GL_STATIC_DRAW);
+
+ // Map the buffer
+ GLfloat *vbo_map = (GLfloat*)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+
+ // Gather data
+ for (i = 0, j = 0; i < data->m_vertex.size(); i++, j += this->stride/sizeof(GLfloat))
+ {
+ memcpy(&vbo_map[j], data->m_vertex[i].getXYZ(), sizeof(float)*3);
+ memcpy(&vbo_map[j+3], data->m_vertex[i].getNormal(), sizeof(float)*3);
+ memcpy(&vbo_map[j+6], data->m_vertex[i].getTangent(), sizeof(float)*4);
+ memcpy(&vbo_map[j+10], data->m_vertex[i].getRGBA(), sizeof(char)*4);
+
+ for (k = 0; k < RAS_TexVert::MAX_UNIT; k++)
+ memcpy(&vbo_map[j+11+(k*2)], data->m_vertex[i].getUV(k), sizeof(float)*2);
+ }
+
+ glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
+}
+
+void VBO::UpdateIndices()
+{
+ int space = data->m_index.size() * sizeof(GLushort);
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, this->ibo);
+
+ // Upload Data to VBO
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, space, &data->m_index[0], GL_STATIC_DRAW);
+}
+
+void VBO::Draw(int texco_num, RAS_IRasterizer::TexCoGen* texco, int attrib_num, RAS_IRasterizer::TexCoGen* attrib, int *attrib_layer, bool multi)
+{
+ int unit;
+
+ // Bind buffers
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, this->ibo);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vbo_id);
+
+ // Vertexes
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, this->stride, this->vertex_offset);
+
+ // Normals
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glNormalPointer(GL_FLOAT, this->stride, this->normal_offset);
+
+ // Colors
+ glEnableClientState(GL_COLOR_ARRAY);
+ glColorPointer(4, GL_UNSIGNED_BYTE, this->stride, this->color_offset);
+
+ if (multi)
+ {
+ for (unit = 0; unit < texco_num; ++unit)
+ {
+ glClientActiveTexture(GL_TEXTURE0_ARB + unit);
+ switch (texco[unit]) {
+ case RAS_IRasterizer::RAS_TEXCO_ORCO:
+ case RAS_IRasterizer::RAS_TEXCO_GLOB:
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(3, GL_FLOAT, this->stride, this->vertex_offset);
+ break;
+ case RAS_IRasterizer::RAS_TEXCO_UV:
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, this->stride, (void*)((intptr_t)this->uv_offset+(sizeof(GLfloat)*2*unit)));
+ break;
+ case RAS_IRasterizer::RAS_TEXCO_NORM:
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(3, GL_FLOAT, this->stride, this->normal_offset);
+ break;
+ case RAS_IRasterizer::RAS_TEXTANGENT:
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(4, GL_FLOAT, this->stride, this->tangent_offset);
+ break;
+ default:
+ break;
+ }
+ }
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ }
+ else //TexFace
+ {
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, this->stride, this->uv_offset);
+ }
+
+ if (GLEW_ARB_vertex_program)
+ {
+ for (unit = 0; unit < attrib_num; ++unit)
+ {
+ switch (attrib[unit]) {
+ case RAS_IRasterizer::RAS_TEXCO_ORCO:
+ case RAS_IRasterizer::RAS_TEXCO_GLOB:
+ glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, this->stride, this->vertex_offset);
+ glEnableVertexAttribArrayARB(unit);
+ break;
+ case RAS_IRasterizer::RAS_TEXCO_UV:
+ glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, this->stride, (void*)((intptr_t)this->uv_offset+attrib_layer[unit]*sizeof(GLfloat)*2));
+ glEnableVertexAttribArrayARB(unit);
+ break;
+ case RAS_IRasterizer::RAS_TEXCO_NORM:
+ glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, stride, this->normal_offset);
+ glEnableVertexAttribArrayARB(unit);
+ break;
+ case RAS_IRasterizer::RAS_TEXTANGENT:
+ glVertexAttribPointerARB(unit, 4, GL_FLOAT, GL_FALSE, this->stride, this->tangent_offset);
+ glEnableVertexAttribArrayARB(unit);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ glDrawElements(this->mode, this->indices, GL_UNSIGNED_SHORT, 0);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ if (GLEW_ARB_vertex_program)
+ {
+ for (int i = 0; i < attrib_num; ++i)
+ glDisableVertexAttribArrayARB(i);
+ }
+
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+}
+
+RAS_StorageVBO::RAS_StorageVBO(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib, int *attrib_layer):
+ m_texco_num(texco_num),
+ m_attrib_num(attrib_num),
+ m_texco(texco),
+ m_attrib(attrib),
+ m_attrib_layer(attrib_layer)
+{
+}
+
+RAS_StorageVBO::~RAS_StorageVBO()
+{
+}
+
+bool RAS_StorageVBO::Init()
+{
+ return true;
+}
+
+void RAS_StorageVBO::Exit()
+{
+ m_vbo_lookup.clear();
+}
+
+void RAS_StorageVBO::IndexPrimitives(RAS_MeshSlot& ms)
+{
+ IndexPrimitivesInternal(ms, false);
+}
+
+void RAS_StorageVBO::IndexPrimitivesMulti(RAS_MeshSlot& ms)
+{
+ IndexPrimitivesInternal(ms, true);
+}
+
+void RAS_StorageVBO::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
+{
+ RAS_MeshSlot::iterator it;
+ VBO *vbo;
+
+ for (ms.begin(it); !ms.end(it); ms.next(it))
+ {
+ vbo = m_vbo_lookup[it.array];
+
+ if (vbo == 0)
+ m_vbo_lookup[it.array] = vbo = new VBO(it.array, it.totindex);
+
+ // Update the vbo
+ if (ms.m_mesh->MeshModified())
+ {
+ vbo->UpdateData();
+ }
+
+ vbo->Draw(*m_texco_num, m_texco, *m_attrib_num, m_attrib, m_attrib_layer, multi);
+ }
+}
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h
new file mode 100644
index 00000000000..2fe0c32f399
--- /dev/null
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h
@@ -0,0 +1,101 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 *****
+ */
+
+#ifndef __KX_VERTEXBUFFEROBJECTSTORAGE
+#define __KX_VERTEXBUFFEROBJECTSTORAGE
+
+#include <map>
+#include "GL/glew.h"
+
+#include "RAS_IStorage.h"
+#include "RAS_IRasterizer.h"
+
+#include "RAS_OpenGLRasterizer.h"
+
+class VBO
+{
+public:
+ VBO(RAS_DisplayArray *data, unsigned int indices);
+ ~VBO();
+
+ void Draw(int texco_num, RAS_IRasterizer::TexCoGen* texco, int attrib_num, RAS_IRasterizer::TexCoGen* attrib, int *attrib_layer, bool multi);
+
+ void UpdateData();
+ void UpdateIndices();
+private:
+ RAS_DisplayArray* data;
+ GLuint size;
+ GLuint stride;
+ GLuint indices;
+ GLenum mode;
+ GLuint ibo;
+ GLuint vbo_id;
+
+ void* vertex_offset;
+ void* normal_offset;
+ void* color_offset;
+ void* tangent_offset;
+ void* uv_offset;
+};
+
+class RAS_StorageVBO : public RAS_IStorage
+{
+
+public:
+ RAS_StorageVBO(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib, int *attrib_layer);
+ virtual ~RAS_StorageVBO();
+
+ virtual bool Init();
+ virtual void Exit();
+
+ virtual void IndexPrimitives(RAS_MeshSlot& ms);
+ virtual void IndexPrimitivesMulti(RAS_MeshSlot& ms);
+
+ virtual void SetDrawingMode(int drawingmode){m_drawingmode=drawingmode;};
+
+protected:
+ int m_drawingmode;
+
+ int* m_texco_num;
+ int* m_attrib_num;
+
+ RAS_IRasterizer::TexCoGen* m_texco;
+ RAS_IRasterizer::TexCoGen* m_attrib;
+ int* m_attrib_layer;
+
+ std::map<RAS_DisplayArray*, class VBO*> m_vbo_lookup;
+
+ virtual void IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi);
+
+#ifdef WITH_CXX_GUARDEDALLOC
+public:
+ void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:RAS_StorageVA"); }
+ void operator delete( void *mem ) { MEM_freeN(mem); }
+#endif
+};
+
+#endif //__KX_VERTEXBUFFEROBJECTSTORAGE
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp
deleted file mode 100644
index 076acb0d153..00000000000
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp
+++ /dev/null
@@ -1,382 +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/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp
- * \ingroup bgerastogl
- */
-
-#include "RAS_VAOpenGLRasterizer.h"
-#include <stdlib.h>
-
-#include "GL/glew.h"
-#include "GPU_extensions.h"
-
-#include "STR_String.h"
-#include "RAS_TexVert.h"
-#include "MT_CmMatrix4x4.h"
-#include "RAS_IRenderTools.h" // rendering text
-
-RAS_VAOpenGLRasterizer::RAS_VAOpenGLRasterizer(RAS_ICanvas* canvas, bool lock)
-: RAS_OpenGLRasterizer(canvas),
- /* m_Lock(lock && GLEW_EXT_compiled_vertex_array), */ /* UNUSED */
- m_last_texco_num(0),
- m_last_attrib_num(0)
-{
-}
-
-RAS_VAOpenGLRasterizer::~RAS_VAOpenGLRasterizer()
-{
-}
-
-bool RAS_VAOpenGLRasterizer::Init(void)
-{
-
- bool result = RAS_OpenGLRasterizer::Init();
-
- if (result)
- {
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- }
-
- return result;
-}
-
-void RAS_VAOpenGLRasterizer::SetDrawingMode(int drawingmode)
-{
- m_drawingmode = drawingmode;
-
- switch (m_drawingmode)
- {
- case KX_BOUNDINGBOX:
- case KX_WIREFRAME:
- //glDisableClientState(GL_COLOR_ARRAY);
- //glDisable(GL_CULL_FACE);
- break;
- case KX_SOLID:
- //glDisableClientState(GL_COLOR_ARRAY);
- break;
- case KX_TEXTURED:
- case KX_SHADED:
- case KX_SHADOW:
- //glEnableClientState(GL_COLOR_ARRAY);
- default:
- break;
- }
-}
-
-void RAS_VAOpenGLRasterizer::Exit()
-{
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
-
- RAS_OpenGLRasterizer::Exit();
-}
-
-void RAS_VAOpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
-{
- static const GLsizei stride = sizeof(RAS_TexVert);
- bool wireframe = m_drawingmode <= KX_WIREFRAME;
- RAS_MeshSlot::iterator it;
- GLenum drawmode;
-
- if (ms.m_pDerivedMesh) {
- // cannot be handled here, pass to RAS_OpenGLRasterizer
- RAS_OpenGLRasterizer::IndexPrimitivesInternal(ms, false);
- return;
- }
-
- if (!wireframe)
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
- // use glDrawElements to draw each vertexarray
- for (ms.begin(it); !ms.end(it); ms.next(it)) {
- if (it.totindex == 0)
- continue;
-
- // drawing mode
- if (it.array->m_type == RAS_DisplayArray::TRIANGLE)
- drawmode = GL_TRIANGLES;
- else if (it.array->m_type == RAS_DisplayArray::QUAD)
- drawmode = GL_QUADS;
- else
- drawmode = GL_LINES;
-
- // colors
- if (drawmode != GL_LINES && !wireframe) {
- if (ms.m_bObjectColor) {
- const MT_Vector4& rgba = ms.m_RGBAcolor;
-
- glDisableClientState(GL_COLOR_ARRAY);
- glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
- }
- else {
- glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
- glEnableClientState(GL_COLOR_ARRAY);
- }
- }
- else
- glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
-
- glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ());
- glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal());
- if (!wireframe) {
- glTexCoordPointer(2, GL_FLOAT, stride, it.vertex->getUV1());
- if (glIsEnabled(GL_COLOR_ARRAY))
- glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA());
- }
-
- // here the actual drawing takes places
- glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index);
- }
-
- if (!wireframe) {
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
- }
-}
-
-void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
-{
- static const GLsizei stride = sizeof(RAS_TexVert);
- bool wireframe = m_drawingmode <= KX_WIREFRAME;
- RAS_MeshSlot::iterator it;
- GLenum drawmode;
-
- if (ms.m_pDerivedMesh) {
- // cannot be handled here, pass to RAS_OpenGLRasterizer
- RAS_OpenGLRasterizer::IndexPrimitivesInternal(ms, true);
- return;
- }
-
- if (!wireframe)
- EnableTextures(true);
-
- // use glDrawElements to draw each vertexarray
- for (ms.begin(it); !ms.end(it); ms.next(it)) {
- if (it.totindex == 0)
- continue;
-
- // drawing mode
- if (it.array->m_type == RAS_DisplayArray::TRIANGLE)
- drawmode = GL_TRIANGLES;
- else if (it.array->m_type == RAS_DisplayArray::QUAD)
- drawmode = GL_QUADS;
- else
- drawmode = GL_LINES;
-
- // colors
- if (drawmode != GL_LINES && !wireframe) {
- if (ms.m_bObjectColor) {
- const MT_Vector4& rgba = ms.m_RGBAcolor;
-
- glDisableClientState(GL_COLOR_ARRAY);
- glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
- }
- else {
- glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
- glEnableClientState(GL_COLOR_ARRAY);
- }
- }
- else
- glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
-
- glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ());
- glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal());
- if (!wireframe) {
- TexCoordPtr(it.vertex);
- if (glIsEnabled(GL_COLOR_ARRAY))
- glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA());
- }
-
- // here the actual drawing takes places
- glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index);
- }
-
- if (!wireframe) {
- glDisableClientState(GL_COLOR_ARRAY);
- EnableTextures(false);
- }
-}
-
-void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv)
-{
- /* note: this function must closely match EnableTextures to enable/disable
- * the right arrays, otherwise coordinate and attribute pointers from other
- * materials can still be used and cause crashes */
- int unit;
-
- if (GLEW_ARB_multitexture)
- {
- for (unit=0; unit<m_texco_num; unit++)
- {
- glClientActiveTextureARB(GL_TEXTURE0_ARB+unit);
- if (tv->getFlag() & RAS_TexVert::SECOND_UV && (int)tv->getUnit() == unit) {
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert), tv->getUV2());
- continue;
- }
- switch (m_texco[unit]) {
- case RAS_TEXCO_ORCO:
- case RAS_TEXCO_GLOB:
- glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getXYZ());
- break;
- case RAS_TEXCO_UV1:
- glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV1());
- break;
- case RAS_TEXCO_NORM:
- glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getNormal());
- break;
- case RAS_TEXTANGENT:
- glTexCoordPointer(4, GL_FLOAT, sizeof(RAS_TexVert),tv->getTangent());
- break;
- case RAS_TEXCO_UV2:
- glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV2());
- break;
- default:
- break;
- }
- }
-
- glClientActiveTextureARB(GL_TEXTURE0_ARB);
- }
-
- if (GLEW_ARB_vertex_program) {
- for (unit=0; unit<m_attrib_num; unit++) {
- switch (m_attrib[unit]) {
- case RAS_TEXCO_ORCO:
- case RAS_TEXCO_GLOB:
- glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getXYZ());
- break;
- case RAS_TEXCO_UV1:
- glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV1());
- break;
- case RAS_TEXCO_NORM:
- glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getNormal());
- break;
- case RAS_TEXTANGENT:
- glVertexAttribPointerARB(unit, 4, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getTangent());
- break;
- case RAS_TEXCO_UV2:
- glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV2());
- break;
- case RAS_TEXCO_VCOL:
- glVertexAttribPointerARB(unit, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(RAS_TexVert), tv->getRGBA());
- break;
- default:
- break;
- }
- }
- }
-}
-
-void RAS_VAOpenGLRasterizer::EnableTextures(bool enable)
-{
- TexCoGen *texco, *attrib;
- int unit, texco_num, attrib_num;
-
- /* we cache last texcoords and attribs to ensure we disable the ones that
- * were actually last set */
- if (enable) {
- texco = m_texco;
- texco_num = m_texco_num;
- attrib = m_attrib;
- attrib_num = m_attrib_num;
-
- memcpy(m_last_texco, m_texco, sizeof(TexCoGen)*m_texco_num);
- m_last_texco_num = m_texco_num;
- memcpy(m_last_attrib, m_attrib, sizeof(TexCoGen)*m_attrib_num);
- m_last_attrib_num = m_attrib_num;
- }
- else {
- texco = m_last_texco;
- texco_num = m_last_texco_num;
- attrib = m_last_attrib;
- attrib_num = m_last_attrib_num;
- }
-
- if (GLEW_ARB_multitexture) {
- for (unit=0; unit<texco_num; unit++) {
- glClientActiveTextureARB(GL_TEXTURE0_ARB+unit);
-
- switch (texco[unit]) {
- case RAS_TEXCO_ORCO:
- case RAS_TEXCO_GLOB:
- case RAS_TEXCO_UV1:
- case RAS_TEXCO_NORM:
- case RAS_TEXTANGENT:
- case RAS_TEXCO_UV2:
- if (enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- else glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- break;
- default:
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- break;
- }
- }
-
- glClientActiveTextureARB(GL_TEXTURE0_ARB);
- }
- else {
- if (texco_num) {
- if (enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- else glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- }
- }
-
- if (GLEW_ARB_vertex_program) {
- for (unit=0; unit<attrib_num; unit++) {
- switch (attrib[unit]) {
- case RAS_TEXCO_ORCO:
- case RAS_TEXCO_GLOB:
- case RAS_TEXCO_UV1:
- case RAS_TEXCO_NORM:
- case RAS_TEXTANGENT:
- case RAS_TEXCO_UV2:
- case RAS_TEXCO_VCOL:
- if (enable) glEnableVertexAttribArrayARB(unit);
- else glDisableVertexAttribArrayARB(unit);
- break;
- default:
- glDisableVertexAttribArrayARB(unit);
- break;
- }
- }
- }
-
- if (!enable) {
- m_last_texco_num = 0;
- m_last_attrib_num = 0;
- }
-}
-
diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp
index 945644ff3e6..aaaf70728fe 100644
--- a/source/gameengine/Rasterizer/RAS_TexVert.cpp
+++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp
@@ -32,26 +32,29 @@
#include "RAS_TexVert.h"
#include "MT_Matrix4x4.h"
+#include "BLI_math.h"
RAS_TexVert::RAS_TexVert(const MT_Point3& xyz,
- const MT_Point2& uv,
- const MT_Point2& uv2,
- const MT_Vector4& tangent,
- const unsigned int rgba,
- const MT_Vector3& normal,
- const bool flat,
- const unsigned int origindex)
+ const MT_Point2 uvs[MAX_UNIT],
+ const MT_Vector4& tangent,
+ const unsigned int rgba,
+ const MT_Vector3& normal,
+ const bool flat,
+ const unsigned int origindex)
{
xyz.getValue(m_localxyz);
- uv.getValue(m_uv1);
- uv2.getValue(m_uv2);
SetRGBA(rgba);
SetNormal(normal);
tangent.getValue(m_tangent);
- m_flag = (flat)? FLAT: 0;
+ m_flag = (flat) ? FLAT: 0;
m_origindex = origindex;
m_unit = 2;
m_softBodyIndex = -1;
+
+ for (int i = 0; i < MAX_UNIT; ++i)
+ {
+ uvs[i].getValue(m_uvs[i]);
+ }
}
const MT_Point3& RAS_TexVert::xyz()
@@ -77,29 +80,17 @@ void RAS_TexVert::SetXYZ(const MT_Point3& xyz)
void RAS_TexVert::SetXYZ(const float xyz[3])
{
- m_localxyz[0] = xyz[0]; m_localxyz[1] = xyz[1]; m_localxyz[2] = xyz[2];
-}
-
-void RAS_TexVert::SetUV1(const MT_Point2& uv)
-{
- uv.getValue(m_uv1);
+ copy_v3_v3(m_localxyz, xyz);
}
-void RAS_TexVert::SetUV1(const float uv[3])
+void RAS_TexVert::SetUV(int index, const MT_Point2& uv)
{
- m_uv1[0] = uv[0];
- m_uv1[1] = uv[1];
+ uv.getValue(m_uvs[index]);
}
-void RAS_TexVert::SetUV2(const MT_Point2& uv)
+void RAS_TexVert::SetUV(int index, const float uv[2])
{
- uv.getValue(m_uv2);
-}
-
-void RAS_TexVert::SetUV2(const float uv[3])
-{
- m_uv2[0] = uv[0];
- m_uv2[1] = uv[1];
+ copy_v2_v2(m_uvs[index], uv);
}
void RAS_TexVert::SetRGBA(const unsigned int rgba)
@@ -115,7 +106,7 @@ void RAS_TexVert::SetFlag(const short flag)
void RAS_TexVert::SetUnit(const unsigned int u)
{
- m_unit = u <= (unsigned int) MAX_UNIT ? u: (unsigned int)MAX_UNIT;
+ m_unit = (u <= (unsigned int) MAX_UNIT) ? u: (unsigned int)MAX_UNIT;
}
void RAS_TexVert::SetNormal(const MT_Vector3& normal)
@@ -132,16 +123,21 @@ void RAS_TexVert::SetTangent(const MT_Vector3& tangent)
// compare two vertices, and return TRUE if both are almost identical (they can be shared)
bool RAS_TexVert::closeTo(const RAS_TexVert* other)
{
- return (
- /* m_flag == other->m_flag && */
- /* at the moment the face only stores the smooth/flat setting so don't bother comparing it */
- m_rgba == other->m_rgba &&
- MT_fuzzyEqual(MT_Vector3(m_normal), MT_Vector3(other->m_normal)) &&
- MT_fuzzyEqual(MT_Vector3(m_tangent), MT_Vector3(other->m_tangent)) &&
- MT_fuzzyEqual(MT_Vector2(m_uv1), MT_Vector2(other->m_uv1)) &&
- MT_fuzzyEqual(MT_Vector2(m_uv2), MT_Vector2(other->m_uv2)) /* &&
- MT_fuzzyEqual(MT_Vector3(m_localxyz), MT_Vector3(other->m_localxyz))*/);
- /* don't bother comparing m_localxyz since we know there from the same vert */
+ const float eps = FLT_EPSILON;
+ for (int i = 0; i < MAX_UNIT; i++) {
+ if (!compare_v2v2(m_uvs[i], other->m_uvs[i], eps)) {
+ return false;
+ }
+ }
+
+ return (/* m_flag == other->m_flag && */
+ /* at the moment the face only stores the smooth/flat setting so don't bother comparing it */
+ (m_rgba == other->m_rgba) &&
+ compare_v3v3(m_normal, other->m_normal, eps) &&
+ compare_v3v3(m_tangent, other->m_tangent, eps)
+ /* don't bother comparing m_localxyz since we know there from the same vert */
+ /* && compare_v3v3(m_localxyz, other->m_localxyz, eps))*/
+ );
}
short RAS_TexVert::getFlag() const
@@ -157,17 +153,12 @@ unsigned int RAS_TexVert::getUnit() const
void RAS_TexVert::Transform(const MT_Matrix4x4& mat, const MT_Matrix4x4& nmat)
{
- SetXYZ((mat*MT_Vector4(m_localxyz[0], m_localxyz[1], m_localxyz[2], 1.0)).getValue());
- SetNormal((nmat*MT_Vector4(m_normal[0], m_normal[1], m_normal[2], 1.0)).getValue());
- SetTangent((nmat*MT_Vector4(m_tangent[0], m_tangent[1], m_tangent[2], 1.0)).getValue());
-}
-
-void RAS_TexVert::TransformUV1(const MT_Matrix4x4& mat)
-{
- SetUV1((mat * MT_Vector4(m_uv1[0], m_uv1[1], 0.0, 1.0)).getValue());
+ SetXYZ((mat * MT_Vector4(m_localxyz[0], m_localxyz[1], m_localxyz[2], 1.0)).getValue());
+ SetNormal((nmat * MT_Vector4(m_normal[0], m_normal[1], m_normal[2], 1.0)).getValue());
+ SetTangent((nmat * MT_Vector4(m_tangent[0], m_tangent[1], m_tangent[2], 1.0)).getValue());
}
-void RAS_TexVert::TransformUV2(const MT_Matrix4x4& mat)
+void RAS_TexVert::TransformUV(int index, const MT_Matrix4x4& mat)
{
- SetUV2((mat * MT_Vector4(m_uv2[0], m_uv2[1], 0.0, 1.0)).getValue());
+ SetUV(index, (mat * MT_Vector4(m_uvs[index][0], m_uvs[index][1], 0.0, 1.0)).getValue());
}
diff --git a/source/gameengine/Rasterizer/RAS_TexVert.h b/source/gameengine/Rasterizer/RAS_TexVert.h
index 98ea4dd60aa..a91d2c7f848 100644
--- a/source/gameengine/Rasterizer/RAS_TexVert.h
+++ b/source/gameengine/Rasterizer/RAS_TexVert.h
@@ -48,23 +48,21 @@ class RAS_TexVert
{
float m_localxyz[3]; // 3*4 = 12
- float m_uv1[2]; // 2*4 = 8
- float m_uv2[2]; // 2*4 = 8
+ float m_uvs[8][2]; // 8*2*4=64 //8 = MAX_UNIT
unsigned int m_rgba; // 4
- float m_tangent[4]; // 4*4 = 16
- float m_normal[3]; // 3*4 = 12
+ float m_tangent[4]; // 4*4 = 16
+ float m_normal[3]; // 3*4 = 12
short m_flag; // 2
short m_softBodyIndex; //2
unsigned int m_unit; // 4
unsigned int m_origindex; // 4
//---------
- // 56+6+8+2=72
- // 32 bytes total size, fits nice = 56 = not fit nice.
+ // 120
+ // 32 bytes total size, fits nice = 120 = not fit nice.
public:
enum {
FLAT = 1,
- SECOND_UV = 2,
MAX_UNIT = 8
};
@@ -74,8 +72,7 @@ public:
RAS_TexVert()// :m_xyz(0,0,0),m_uv(0,0),m_rgba(0)
{}
RAS_TexVert(const MT_Point3& xyz,
- const MT_Point2& uv,
- const MT_Point2& uv2,
+ const MT_Point2 uvs[MAX_UNIT],
const MT_Vector4& tangent,
const unsigned int rgba,
const MT_Vector3& normal,
@@ -83,12 +80,8 @@ public:
const unsigned int origindex);
~RAS_TexVert() {};
- const float* getUV1 () const {
- return m_uv1;
- };
-
- const float* getUV2 () const {
- return m_uv2;
+ const float* getUV (int unit) const {
+ return m_uvs[unit];
};
const float* getXYZ() const {
@@ -123,10 +116,8 @@ public:
void SetXYZ(const MT_Point3& xyz);
void SetXYZ(const float xyz[3]);
- void SetUV1(const MT_Point2& uv);
- void SetUV2(const MT_Point2& uv);
- void SetUV1(const float uv[2]);
- void SetUV2(const float uv[2]);
+ void SetUV(int index, const MT_Point2& uv);
+ void SetUV(int index, const float uv[2]);
void SetRGBA(const unsigned int rgba);
void SetNormal(const MT_Vector3& normal);
@@ -139,8 +130,7 @@ public:
void Transform(const class MT_Matrix4x4& mat,
const class MT_Matrix4x4& nmat);
- void TransformUV1(const MT_Matrix4x4& mat);
- void TransformUV2(const MT_Matrix4x4& mat);
+ void TransformUV(int index, const MT_Matrix4x4& mat);
// compare two vertices, to test if they can be shared, used for
// splitting up based on uv's, colors, etc
diff --git a/source/gameengine/Rasterizer/RAS_texmatrix.cpp b/source/gameengine/Rasterizer/RAS_texmatrix.cpp
index d335a38171f..3203fcf9d6b 100644
--- a/source/gameengine/Rasterizer/RAS_texmatrix.cpp
+++ b/source/gameengine/Rasterizer/RAS_texmatrix.cpp
@@ -52,9 +52,9 @@ void RAS_CalcTexMatrix(RAS_TexVert p[3],MT_Point3& origin,MT_Vector3& udir,MT_Ve
MT_Scalar d = -p[0].xyz().dot(normal);
- MT_Matrix3x3 mat3( p[0].getUV1()[0],p[0].getUV1()[1], 1,
- p[1].getUV1()[0],p[1].getUV1()[1], 1,
- p[2].getUV1()[0],p[2].getUV1()[1], 1);
+ MT_Matrix3x3 mat3( p[0].getUV(0)[0],p[0].getUV(0)[1], 1,
+ p[1].getUV(0)[0],p[1].getUV(0)[1], 1,
+ p[2].getUV(0)[0],p[2].getUV(0)[1], 1);
MT_Matrix3x3 mat3inv = mat3.inverse();
diff --git a/source/gameengine/Rasterizer/SConscript b/source/gameengine/Rasterizer/SConscript
index 4164271ba9b..3e7dacad8ba 100644
--- a/source/gameengine/Rasterizer/SConscript
+++ b/source/gameengine/Rasterizer/SConscript
@@ -1,18 +1,62 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
sources = env.Glob('*.cpp')
+incs = [
+ '.',
+ '#intern/guardedalloc',
+ '#intern/string',
+ '#intern/moto/include',
+ '#intern/container',
+ '#source/gameengine/BlenderRoutines',
+ '#extern/glew/include',
+ '#source/gameengine/Expressions',
+ '#source/gameengine/SceneGraph',
+ '#source/blender/blenlib',
+ '#source/blender/blenkernel',
+ '#source/blender/makesdna',
+ ]
-incs = '. #intern/guardedalloc #intern/string #intern/moto/include #intern/container #source/gameengine/BlenderRoutines #extern/glew/include #source/gameengine/Expressions #source/gameengine/SceneGraph #source/blender/blenkernel #source/blender/makesdna'
-
-defs = [ 'GLEW_STATIC' ]
+defs = ['GLEW_STATIC']
if env['WITH_BF_PYTHON']:
- incs += ' ' + env['BF_PYTHON_INC']
+ if type(env['BF_PYTHON_INC']) == str:
+ incs.append(env['BF_PYTHON_INC'].split(' '))
+ else:
+ incs.append(env['BF_PYTHON_INC'])
defs.append('WITH_PYTHON')
if env['WITH_BF_CXX_GUARDEDALLOC']:
defs.append('WITH_CXX_GUARDEDALLOC')
-env.BlenderLib ( 'ge_rasterizer', sources, Split(incs), defs, libtype=['core','player'], priority=[350,70], cxx_compileflags=env['BGE_CXXFLAGS'])
+env.BlenderLib('ge_rasterizer', sources,
+ includes=incs, defines=defs,
+ libtype=['core', 'player'], priority=[350, 70],
+ cxx_compileflags=env['BGE_CXXFLAGS'])
diff --git a/source/gameengine/SConscript b/source/gameengine/SConscript
index aebbf4d9fcf..ae1bb756f8e 100644
--- a/source/gameengine/SConscript
+++ b/source/gameengine/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
SConscript(['BlenderRoutines/SConscript',
@@ -9,7 +35,6 @@ SConscript(['BlenderRoutines/SConscript',
'Ketsji/KXNetwork/SConscript',
'Network/SConscript',
'Network/LoopBackNetwork/SConscript',
- 'Physics/common/SConscript',
'Physics/Dummy/SConscript',
'Rasterizer/SConscript',
'Rasterizer/RAS_OpenGLRasterizer/SConscript',
diff --git a/source/gameengine/SceneGraph/SConscript b/source/gameengine/SceneGraph/SConscript
index 9270169199e..c88a2d6280b 100644
--- a/source/gameengine/SceneGraph/SConscript
+++ b/source/gameengine/SceneGraph/SConscript
@@ -1,4 +1,29 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
Import ('env')
diff --git a/source/gameengine/SceneGraph/SG_ParentRelation.h b/source/gameengine/SceneGraph/SG_ParentRelation.h
index 6e314996456..ce45b42c148 100644
--- a/source/gameengine/SceneGraph/SG_ParentRelation.h
+++ b/source/gameengine/SceneGraph/SG_ParentRelation.h
@@ -29,7 +29,7 @@
/** \file SG_ParentRelation.h
* \ingroup bgesg
* \page SG_ParentRelationPage SG_ParentRelation
-
+ *
* \section SG_ParentRelationSection SG_ParentRelation
*
* This is an abstract interface class to the Scene Graph library.
@@ -48,7 +48,7 @@
* should not be value types and should be allocated on the heap.
*
*/
-
+
#ifndef __SG_PARENTRELATION_H__
#define __SG_PARENTRELATION_H__
diff --git a/source/gameengine/VideoTexture/PyTypeList.cpp b/source/gameengine/VideoTexture/PyTypeList.cpp
index 96ac1cc5b6b..99e9ae13e64 100644
--- a/source/gameengine/VideoTexture/PyTypeList.cpp
+++ b/source/gameengine/VideoTexture/PyTypeList.cpp
@@ -92,6 +92,6 @@ void PyTypeList::reg(PyObject *module)
// increase ref count
Py_INCREF((*it)->getType());
// add type to module
- PyModule_AddObject(module, (char*)(*it)->getName(), (PyObject *)(*it)->getType());
+ PyModule_AddObject(module, (*it)->getName(), (PyObject *)(*it)->getType());
}
}
diff --git a/source/gameengine/VideoTexture/SConscript b/source/gameengine/VideoTexture/SConscript
index e66284948ed..ac8082e0d09 100644
--- a/source/gameengine/VideoTexture/SConscript
+++ b/source/gameengine/VideoTexture/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
import sys
Import ('env')
diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
index 8976a21376a..93a1d09869b 100644
--- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp
+++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
@@ -174,7 +174,7 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV
if (avformat_open_input(&formatCtx, filename, inputFormat, formatParams)!=0)
return -1;
- if (av_find_stream_info(formatCtx)<0)
+ if (avformat_find_stream_info(formatCtx, NULL) < 0)
{
av_close_input_file(formatCtx);
return -1;
@@ -209,7 +209,7 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV
return -1;
}
codecCtx->workaround_bugs = 1;
- if (avcodec_open(codecCtx, codec)<0)
+ if (avcodec_open2(codecCtx, codec, NULL) < 0)
{
av_close_input_file(formatCtx);
return -1;
@@ -1022,7 +1022,7 @@ AVFrame *VideoFFmpeg::grabFrame(long position)
AVFrame * input = m_frame;
/* This means the data wasnt read properly,
- this check stops crashing */
+ * this check stops crashing */
if ( input->data[0]==0 && input->data[1]==0
&& input->data[2]==0 && input->data[3]==0)
{
diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp
index 72415026bb9..e23bd1a3231 100644
--- a/source/gameengine/VideoTexture/blendVideoTex.cpp
+++ b/source/gameengine/VideoTexture/blendVideoTex.cpp
@@ -214,12 +214,12 @@ PyObject *initVideoTexture(void)
pyFilterTypes.reg(m);
Py_INCREF(&TextureType);
- PyModule_AddObject(m, (char*)"Texture", (PyObject *)&TextureType);
- PyModule_AddIntConstant(m, (char*)"SOURCE_ERROR", SourceError);
- PyModule_AddIntConstant(m, (char*)"SOURCE_EMPTY", SourceEmpty);
- PyModule_AddIntConstant(m, (char*)"SOURCE_READY", SourceReady);
- PyModule_AddIntConstant(m, (char*)"SOURCE_PLAYING", SourcePlaying);
- PyModule_AddIntConstant(m, (char*)"SOURCE_STOPPED", SourceStopped);
+ PyModule_AddObject(m, "Texture", (PyObject *)&TextureType);
+ PyModule_AddIntConstant(m, "SOURCE_ERROR", SourceError);
+ PyModule_AddIntConstant(m, "SOURCE_EMPTY", SourceEmpty);
+ PyModule_AddIntConstant(m, "SOURCE_READY", SourceReady);
+ PyModule_AddIntConstant(m, "SOURCE_PLAYING", SourcePlaying);
+ PyModule_AddIntConstant(m, "SOURCE_STOPPED", SourceStopped);
// init last error description
Exception::m_lastError = "";
diff --git a/source/icons/SConscript b/source/icons/SConscript
index 4bb27a7d4fb..443f6454417 100644
--- a/source/icons/SConscript
+++ b/source/icons/SConscript
@@ -1,4 +1,30 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Nathan Letwory.
+#
+# ***** END GPL LICENSE BLOCK *****
+
Import ('env')
import btools
diff --git a/source/tests/CMakeLists.txt b/source/tests/CMakeLists.txt
index dd84882bea3..1bda9e7ae9e 100644
--- a/source/tests/CMakeLists.txt
+++ b/source/tests/CMakeLists.txt
@@ -46,6 +46,10 @@ set(TEST_BLENDER_EXE ${TEST_BLENDER_EXE} --background -noaudio --factory-startup
# ------------------------------------------------------------------------------
# GENERAL PYTHON CORRECTNESS TESTS
+add_test(script_load_keymap ${TEST_BLENDER_EXE}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_keymap_completeness.py
+)
+
add_test(script_load_addons ${TEST_BLENDER_EXE}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_load_addons.py
)
diff --git a/source/tests/batch_import.py b/source/tests/batch_import.py
index 177ab8ea0b0..a2c5fb59055 100644
--- a/source/tests/batch_import.py
+++ b/source/tests/batch_import.py
@@ -112,7 +112,7 @@ def batch_import(operator="",
for i, f in enumerate(files):
print(" %s(filepath=%r) # %d of %d" % (operator, f, i + start, len(files)))
- # hack so loading the new file doesnt undo our loaded addons
+ # hack so loading the new file doesn't undo our loaded addons
addon_utils.reset_all = lambda: None # XXX, hack
bpy.ops.wm.read_factory_settings()
@@ -134,8 +134,7 @@ def batch_import(operator="",
print("\tSaving: %r" % fout_blend)
fout_dir = os.path.dirname(fout_blend)
- if not os.path.exists(fout_dir):
- os.makedirs(fout_dir)
+ os.makedirs(fout_dir, exist_ok=True)
bpy.ops.wm.save_as_mainfile(filepath=fout_blend)
diff --git a/source/tests/bl_keymap_completeness.py b/source/tests/bl_keymap_completeness.py
new file mode 100644
index 00000000000..00322907f69
--- /dev/null
+++ b/source/tests/bl_keymap_completeness.py
@@ -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 #####
+
+# <pep8 compliant>
+
+# simple script to test 'keyconfig_utils' contains correct values.
+
+
+from bpy_extras import keyconfig_utils
+
+
+def check_maps():
+ maps = {}
+
+ def fill_maps(ls):
+ for km_name, km_space_type, km_region_type, km_sub in ls:
+ maps[km_name] = (km_space_type, km_region_type)
+ fill_maps(km_sub)
+
+ fill_maps(keyconfig_utils.KM_HIERARCHY)
+
+ import bpy
+ keyconf = bpy.context.window_manager.keyconfigs.active
+ maps_bl = set(keyconf.keymaps.keys())
+ maps_py = set(maps.keys())
+
+ err = False
+ # Check keyconfig contains only maps that exist in blender
+ test = maps_py - maps_bl
+ if test:
+ print("Keymaps that are in 'keyconfig_utils' but not blender")
+ for km_id in sorted(test):
+ print("\t%s" % km_id)
+ err = True
+
+ test = maps_bl - maps_py
+ if test:
+ print("Keymaps that are in blender but not in 'keyconfig_utils'")
+ for km_id in sorted(test):
+ km = keyconf.keymaps[km_id]
+ print(" ('%s', '%s', '%s', [])," % (km_id, km.space_type, km.region_type))
+ err = True
+
+ # Check space/region's are OK
+ print("Comparing keymap space/region types...")
+ for km_id, km in keyconf.keymaps.items():
+ km_py = maps.get(km_id)
+ if km_py is not None:
+ km_space_type, km_region_type = km_py
+ if km_space_type != km.space_type or km_region_type != km.region_type:
+ print(" Error:")
+ print(" expected -- ('%s', '%s', '%s', [])," % (km_id, km.space_type, km.region_type))
+ print(" got -- ('%s', '%s', '%s', [])," % (km_id, km_space_type, km_region_type))
+ print("done!")
+
+ return err
+
+
+def main():
+ err = check_maps()
+
+ import bpy
+ if err and bpy.app.background:
+ # alert CTest we failed
+ import sys
+ sys.exit(1)
+
+if __name__ == "__main__":
+ main()
diff --git a/source/tests/bl_load_addons.py b/source/tests/bl_load_addons.py
index 5d9ac750362..83bdfb42c95 100644
--- a/source/tests/bl_load_addons.py
+++ b/source/tests/bl_load_addons.py
@@ -27,16 +27,46 @@ import sys
import imp
-def reload_addons(do_reload=True, do_reverse=True):
+def disable_addons():
+ # first disable all
+ addons = bpy.context.user_preferences.addons
+ for mod_name in list(addons.keys()):
+ addon_utils.disable(mod_name)
+ assert(bool(addons) is False)
+
+
+def test_load_addons():
modules = addon_utils.modules({})
modules.sort(key=lambda mod: mod.__name__)
+
+ disable_addons()
+
addons = bpy.context.user_preferences.addons
- # first disable all
- for mod_name in list(addons.keys()):
- addon_utils.disable(mod_name)
+ addons_fail = []
- assert(bool(addons) is False)
+ for mod in modules:
+ mod_name = mod.__name__
+ print("\tenabling:", mod_name)
+ addon_utils.enable(mod_name)
+ if mod_name not in addons:
+ addons_fail.append(mod_name)
+
+ if addons_fail:
+ print("addons failed to load (%d):" % len(addons_fail))
+ for mod_name in addons_fail:
+ print(" %s" % mod_name)
+ else:
+ print("addons all loaded without errors!")
+ print("")
+
+
+def reload_addons(do_reload=True, do_reverse=True):
+ modules = addon_utils.modules({})
+ modules.sort(key=lambda mod: mod.__name__)
+ addons = bpy.context.user_preferences.addons
+
+ disable_addons()
# Run twice each time.
for i in (0, 1):
@@ -57,11 +87,14 @@ def reload_addons(do_reload=True, do_reverse=True):
imp.reload(sys.modules[mod_name])
if do_reverse:
- # in case order matters when it shouldnt
+ # in case order matters when it shouldn't
modules.reverse()
def main():
+ # first load addons, print a list of all addons that fail
+ test_load_addons()
+
reload_addons(do_reload=False, do_reverse=False)
reload_addons(do_reload=False, do_reverse=True)
reload_addons(do_reload=True, do_reverse=True)
diff --git a/source/tests/bl_load_py_modules.py b/source/tests/bl_load_py_modules.py
index b634b4c4385..9677397e01d 100644
--- a/source/tests/bl_load_py_modules.py
+++ b/source/tests/bl_load_py_modules.py
@@ -26,6 +26,12 @@ import addon_utils
import sys
import os
+BLACKLIST = {
+ "bl_i18n_utils",
+ "cycles",
+ "io_export_dxf", # TODO, check on why this fails
+ }
+
def source_list(path, filename_check=None):
from os.path import join
@@ -73,20 +79,26 @@ def load_modules():
for script_path in paths:
for mod_dir in sys.path:
if mod_dir.startswith(script_path):
- module_paths.append(mod_dir)
+ if mod_dir not in module_paths:
+ if os.path.exists(mod_dir):
+ module_paths.append(mod_dir)
#
# collect modules from our paths.
- module_names = set()
+ module_names = {}
for mod_dir in module_paths:
# print("mod_dir", mod_dir)
for mod, mod_full in bpy.path.module_names(mod_dir):
+ if mod in BLACKLIST:
+ continue
if mod in module_names:
- raise Exception("Module found twice %r" % mod)
+ mod_dir_prev, mod_full_prev = module_names[mod]
+ raise Exception("Module found twice %r.\n (%r -> %r, %r -> %r)" %
+ (mod, mod_dir, mod_full, mod_dir_prev, mod_full_prev))
modules.append(__import__(mod))
- module_names.add(mod)
+ module_names[mod] = mod_dir, mod_full
del module_names
#
@@ -107,7 +119,7 @@ def load_modules():
modules.append(mod_imp)
#
- # check which filepaths we didnt load
+ # check which filepaths we didn't load
source_files = []
for mod_dir in module_paths:
source_files.extend(source_list(mod_dir, filename_check=lambda f: f.endswith(".py")))
@@ -128,7 +140,7 @@ def load_modules():
ignore_paths = [
os.sep + "presets" + os.sep,
os.sep + "templates" + os.sep,
- ]
+ ] + [(os.sep + f + os.sep) for f in BLACKLIST]
for f in source_files:
ok = False
diff --git a/source/tests/bl_mesh_modifiers.py b/source/tests/bl_mesh_modifiers.py
index 92fae25df16..2f342f2c65e 100644
--- a/source/tests/bl_mesh_modifiers.py
+++ b/source/tests/bl_mesh_modifiers.py
@@ -34,7 +34,7 @@ USE_QUICK_RENDER = False
IS_BMESH = hasattr(__import__("bpy").types, "LoopColors")
# -----------------------------------------------------------------------------
-# utility funcs
+# utility functions
def render_gl(context, filepath, shade):
@@ -147,7 +147,7 @@ def ctx_viewport_camera(context):
def ctx_camera_setup(context,
location=(0.0, 0.0, 0.0),
lookat=(0.0, 0.0, 0.0),
- # most likely the followuing vars can be left as defaults
+ # most likely the following vars can be left as defaults
up=(0.0, 0.0, 1.0),
lookat_axis='-Z',
up_axis='Y',
@@ -258,7 +258,7 @@ def mesh_uv_add(obj):
uv_lay = obj.data.uv_textures.new()
if IS_BMESH:
- # XXX, odd that we need to do this. until uvs and texface
+ # XXX, odd that we need to do this. until UV's and texface
# are separated we will need to keep it
uv_loops = obj.data.uv_layers[-1]
uv_list = uv_loops.data[:]
diff --git a/source/tests/bl_mesh_validate.py b/source/tests/bl_mesh_validate.py
index a57a06d65e3..ac5be7d08d7 100644
--- a/source/tests/bl_mesh_validate.py
+++ b/source/tests/bl_mesh_validate.py
@@ -98,7 +98,7 @@ def test_meshes():
data.loops.add(len(m[2]))
for idx, v in enumerate(m[2]):
data.loops[idx].vertex_index = v
- # Polys.
+ # Polygons.
data.polygons.add(len(m[3]))
for idx, l in enumerate(m[3]):
data.polygons[idx].loop_start = l[0]
@@ -131,7 +131,7 @@ def test_builtins():
data.loops[l].edge_index = \
random.randrange(0, len(data.edges) * 2)
elif rnd == 3:
- # Make fun with some poly.
+ # Make fun with some polygons.
p = random.randrange(0, len(data.polygons))
if random.randint(0, 1):
data.polygons[p].loop_start = \
diff --git a/source/tests/bl_pyapi_mathutils.py b/source/tests/bl_pyapi_mathutils.py
index a37f74463ee..1754644e813 100644
--- a/source/tests/bl_pyapi_mathutils.py
+++ b/source/tests/bl_pyapi_mathutils.py
@@ -89,7 +89,7 @@ class MatrixTesting(unittest.TestCase):
(19, 26, 33),
(29, 40, 51)))
- self.assertEqual(mat1*mat2, prod_mat1)
+ self.assertEqual(mat1 * mat2, prod_mat1)
self.assertEqual(mat2 * mat1, prod_mat2)
def test_mat4x4_vec3D_mult(self):
diff --git a/source/tests/bl_rst_completeness.py b/source/tests/bl_rst_completeness.py
index e9e2779bda8..6e67f8d908d 100644
--- a/source/tests/bl_rst_completeness.py
+++ b/source/tests/bl_rst_completeness.py
@@ -56,6 +56,7 @@ modules = (
("gpu.rst", "gpu", False),
)
+
def is_directive_pydata(filepath, directive):
if directive.type in {"function", "method", "class", "attribute", "data"}:
return True
@@ -113,7 +114,6 @@ def module_validate(filepath, mod, mod_name, doctree, partial_ok):
print(directive_to_str(filepath, directive_child), end=" ")
print("rst contains non existing class member %r" % attr_id)
-
# MODULE member missing from RST ???
doctree_dict = directive_members_dict(filepath, doctree)
for attr in dir(mod):
@@ -136,7 +136,7 @@ def module_validate(filepath, mod, mod_name, doctree, partial_ok):
def main():
-
+
if bge is None:
print("Skipping BGE modules!")
@@ -151,7 +151,7 @@ def main():
doctree = rst_to_doctree_mini.parse_rst_py(filepath)
__import__(modname)
mod = sys.modules[modname]
-
+
module_validate(filepath, mod, modname, doctree, partial_ok)
diff --git a/source/tests/bl_run_operators.py b/source/tests/bl_run_operators.py
index 5bb25537458..e6f1cc56eb0 100644
--- a/source/tests/bl_run_operators.py
+++ b/source/tests/bl_run_operators.py
@@ -26,6 +26,11 @@
import bpy
import sys
+USE_ATTRSET = False
+USE_RANDOM = False
+RANDOM_SEED = [1] # so we can redo crashes
+RANDOM_RESET = 0.1 # 10% chance of resetting on each mew operator
+
op_blacklist = (
"script.reload",
"export*.*",
@@ -36,18 +41,40 @@ op_blacklist = (
"*.link_append",
"render.render",
"render.play_rendered_anim",
+ "sound.bake_animation", # OK but slow
+ "sound.mixdown", # OK but slow
+ "object.bake_image", # OK but slow
+ "object.paths_calculate", # OK but slow
+ "object.paths_update", # OK but slow
+ "ptcache.bake_all", # OK but slow
+ "nla.bake", # OK but slow
"*.*_export",
"*.*_import",
+ "ed.undo_push",
"wm.blenderplayer_start",
"wm.url_open",
"wm.doc_view",
+ "wm.doc_edit",
+ "wm.doc_view_manual",
"wm.path_open",
"wm.theme_install",
"wm.context_*",
+ "wm.properties_add",
+ "wm.properties_remove",
+ "wm.properties_edit",
+ "wm.properties_context_change",
"wm.operator_cheat_sheet",
- "wm.keyconfig_test", # just annoying - but harmless
- "wm.memory_statistics", # another annoying one
- "console.*", # just annoying - but harmless
+ "wm.interface_theme_*",
+ "wm.appconfig_*", # just annoying - but harmless
+ "wm.keyitem_add", # just annoying - but harmless
+ "wm.keyconfig_activate", # just annoying - but harmless
+ "wm.keyconfig_preset_add", # just annoying - but harmless
+ "wm.keyconfig_test", # just annoying - but harmless
+ "wm.memory_statistics", # another annoying one
+ "wm.dependency_relations", # another annoying one
+ "wm.keymap_restore", # another annoying one
+ "wm.addon_*", # harmless, but dont change state
+ "console.*", # just annoying - but harmless
)
@@ -64,8 +91,114 @@ def filter_op_list(operators):
operators[:] = [op for op in operators if is_op_ok(op[0])]
+def reset_blend():
+ bpy.ops.wm.read_factory_settings()
+ for scene in bpy.data.scenes:
+ # reduce range so any bake action doesnt take too long
+ scene.frame_start = 1
+ scene.frame_end = 5
+
+
+if USE_ATTRSET:
+ def build_property_typemap(skip_classes):
+
+ property_typemap = {}
+
+ for attr in dir(bpy.types):
+ cls = getattr(bpy.types, attr)
+ if issubclass(cls, skip_classes):
+ continue
+
+ ## 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():
+ if not prop.is_skip_save:
+ properties.append(prop_id)
+
+ properties.remove("rna_type")
+ property_typemap[attr] = properties
+
+ return property_typemap
+ CLS_BLACKLIST = (
+ bpy.types.BrushTextureSlot,
+ bpy.types.Brush,
+ )
+ property_typemap = build_property_typemap(CLS_BLACKLIST)
+ bpy_struct_type = bpy.types.Struct.__base__
+
+ def id_walk(value, parent):
+ value_type = type(value)
+ value_type_name = value_type.__name__
+
+ value_id = getattr(value, "id_data", Ellipsis)
+ value_props = property_typemap.get(value_type_name, ())
+
+ for prop in value_props:
+ subvalue = getattr(value, prop)
+
+ if subvalue == parent:
+ continue
+ # grr, recursive!
+ if prop == "point_caches":
+ continue
+ subvalue_type = type(subvalue)
+ yield value, prop, subvalue_type
+ subvalue_id = getattr(subvalue, "id_data", Ellipsis)
+
+ if value_id == subvalue_id:
+ if subvalue_type == float:
+ pass
+ elif subvalue_type == int:
+ pass
+ elif subvalue_type == bool:
+ pass
+ elif subvalue_type == str:
+ pass
+ elif hasattr(subvalue, "__len__"):
+ for sub_item in subvalue[:]:
+ if isinstance(sub_item, bpy_struct_type):
+ subitem_id = getattr(sub_item, "id_data", Ellipsis)
+ if subitem_id == subvalue_id:
+ yield from id_walk(sub_item, value)
+
+ if subvalue_type.__name__ in property_typemap:
+ yield from id_walk(subvalue, value)
+
+ # main function
+ _random_values = (
+ None, object,
+ 1, 0.1, -1,
+ "", "test", b"", b"test",
+ (), [], {},
+ (10,), (10, 20), (0, 0, 0),
+ {},
+ )
+
+ def attrset_data():
+ for attr in dir(bpy.data):
+ if attr == "window_managers":
+ continue
+ seq = getattr(bpy.data, attr)
+ if seq.__class__.__name__ == 'bpy_prop_collection':
+ for id_data in seq:
+ for val, prop, tp in id_walk(id_data, bpy.data):
+ # print(id_data)
+ for val_rnd in _random_values:
+ try:
+ setattr(val, prop, val_rnd)
+ except:
+ pass
+
+
def run_ops(operators, setup_func=None, reset=True):
print("\ncontext:", setup_func.__name__)
+
+ if USE_RANDOM:
+ import random
+ if random.random() < (1.0 - RANDOM_RESET):
+ reset = False
+
# first invoke
for op_id, op in operators:
if op.poll():
@@ -74,9 +207,16 @@ def run_ops(operators, setup_func=None, reset=True):
# disable will get blender in a bad state and crash easy!
if reset:
- bpy.ops.wm.read_factory_settings()
+ reset_blend()
- setup_func()
+ if USE_RANDOM:
+ # we can't be sure it will work
+ try:
+ setup_func()
+ except:
+ pass
+ else:
+ setup_func()
for mode in {'EXEC_DEFAULT', 'INVOKE_DEFAULT'}:
try:
@@ -86,11 +226,21 @@ def run_ops(operators, setup_func=None, reset=True):
#traceback.print_exc()
pass
+ if USE_ATTRSET:
+ attrset_data()
+
if not operators:
# run test
if reset:
- bpy.ops.wm.read_factory_settings()
- setup_func()
+ reset_blend()
+ if USE_RANDOM:
+ # we can't be sure it will work
+ try:
+ setup_func()
+ except:
+ pass
+ else:
+ setup_func()
# contexts
@@ -217,7 +367,7 @@ def main():
bpy_check_type_duplicates()
- # bpy.ops.wm.read_factory_settings()
+ # reset_blend()
import bpy
operators = []
for mod_name in dir(bpy.ops):
@@ -233,8 +383,10 @@ def main():
# for testing, mix the list up.
#operators.reverse()
- #import random
- #random.shuffle(operators)
+ if USE_RANDOM:
+ import random
+ random.seed(RANDOM_SEED[0])
+ random.shuffle(operators)
# 2 passes, first just run setup_func to make sure they are ok
for operators_test in ((), operators):
@@ -270,4 +422,7 @@ def main():
print("Finished %r" % __file__)
if __name__ == "__main__":
+ #~ for i in range(200):
+ #~ RANDOM_SEED[0] += 1
+ #~ main()
main()
diff --git a/source/tests/check_deprecated.py b/source/tests/check_deprecated.py
index c5c7bdcdcb0..bb9fcd818d2 100644
--- a/source/tests/check_deprecated.py
+++ b/source/tests/check_deprecated.py
@@ -31,12 +31,12 @@ SKIP_DIRS = ("extern",
def is_c_header(filename):
ext = splitext(filename)[1]
- return (ext in (".h", ".hpp", ".hxx"))
+ return (ext in {".h", ".hpp", ".hxx", ".hh"})
def is_c(filename):
ext = splitext(filename)[1]
- return (ext in (".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl"))
+ return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl"})
def is_c_any(filename):
diff --git a/source/tests/pep8.py b/source/tests/pep8.py
index ccaaeb7c0cd..cb86953e00e 100644
--- a/source/tests/pep8.py
+++ b/source/tests/pep8.py
@@ -21,20 +21,20 @@
import os
# depends on pep8, pyflakes, pylint
-# for ubuntu
+# for Ubuntu
#
# sudo apt-get install pylint pyflakes
#
# sudo apt-get install python-setuptools python-pip
# sudo pip install pep8
#
-# in debian install pylint pyflakes pep8 with apt-get/aptitude/etc
+# in Debian install pylint pyflakes pep8 with apt-get/aptitude/etc
#
# on *nix run
# python source/tests/pep8.py > test_pep8.log 2>&1
# how many lines to read into the file, pep8 comment
-# should be directly after the licence header, ~20 in most cases
+# should be directly after the license header, ~20 in most cases
PEP8_SEEK_COMMENT = 40
SKIP_PREFIX = "./tools", "./config", "./scons", "./extern"
FORCE_PEP8_ALL = False
@@ -115,7 +115,7 @@ def main():
# let pep8 complain about line length
os.system("pylint "
"--disable="
- "C0111," # missing docstring
+ "C0111," # missing doc string
"C0103," # invalid name
"W0613," # unused argument, may add this back
# but happens a lot for 'context' for eg.
diff --git a/source/tests/rna_info_dump.py b/source/tests/rna_info_dump.py
index 615c3b035ce..40d7b7c38a6 100644
--- a/source/tests/rna_info_dump.py
+++ b/source/tests/rna_info_dump.py
@@ -18,7 +18,7 @@
# <pep8 compliant>
-# Used for generating API diff's between releases
+# Used for generating API diffs between releases
# ./blender.bin --background -noaudio --python source/tests/rna_info_dump.py
import bpy
diff --git a/source/tests/rst_to_doctree_mini.py b/source/tests/rst_to_doctree_mini.py
index 181037299cf..cb7b0291296 100644
--- a/source/tests/rst_to_doctree_mini.py
+++ b/source/tests/rst_to_doctree_mini.py
@@ -45,7 +45,7 @@ def parse_rst_py(filepath):
# -->
# ("foo", "bar")
re_prefix = re.compile(r"^\.\.\s([a-zA-Z09\-]+)::\s*(.*)\s*$")
-
+
tree = collections.defaultdict(list)
indent_map = {}
indent_prev = 0